[
  {
    "path": ".clang-format",
    "content": "---\n# We'll use defaults from the LLVM style, but with 2 columns indentation.\nBasedOnStyle: LLVM\nIndentWidth: 2\n---\nLanguage: Cpp\n# Force pointers to the type for C++.\nDerivePointerAlignment: false\nPointerAlignment: Left\nColumnLimit: 100\n\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.com/devcontainers/templates/tree/main/src/debian\n{\n\t\"name\": \"Debian\",\n\t// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile\n\t\"image\": \"mcr.microsoft.com/devcontainers/cpp:debian-12\"\n\n\t// Features to add to the dev container. More info: https://containers.dev/features.\n\t// \"features\": {},\n\n\t// Use 'forwardPorts' to make a list of ports inside the container available locally.\n\t// \"forwardPorts\": [],\n\n\t// Configure tool-specific properties.\n\t// \"customizations\": {},\n\n\t// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.\n\t// \"remoteUser\": \"root\"\n}\n"
  },
  {
    "path": ".github/workflows/wwiv-binaries.yml",
    "content": "# WWIV continuous build script\n# Copyright (C)2023, WWIV Software Services\n#\n\nname: WWIV 5.9\nrun-name: WWIV 5.9 CI\n\n# ** IMPORTANT: ONLY allow on push events here since WWIV\n# has some self hosted runners\n\non:\n  push:\n    branches: \n      - main\n\nenv:\n    CMAKE_BIN: cmake\n    CTEST_BIN: ctest\n    CPACK_BIN: cpack\n    WORKSPACE: ${{ github.workspace }}\n    WWIV_RELEASE: 5.9.0\n    WWIV_RELEASE_LABEL: wwiv59\n    # TODO - rushfan - we should probably remove this.\n    BUILD_NUMBER: 8675309\n\njobs:\n  wwiv-build-number:\n    name: Create Build Number\n    if: github.repository_owner == 'wwivbbs'\n    runs-on: ubuntu-latest\n    outputs:\n      build_number: ${{ steps.buildnumber.outputs.build_number }}\n      wwiv_tag: ${{ steps.generate_tag.outputs.wwiv_tag }}\n    steps:\n      - name: Checkout, Tag and Build Number\n        id: buildnumber\n        uses: onyxmueller/build-tag-number@v1\n        with:\n          token: ${{secrets.github_token}}  \n          \n      - name: Check out repository code\n        uses: actions/checkout@v4\n        with:\n          submodules: recursive\n          \n      - name: Generate Tag Name\n        id: generate_tag\n        shell: bash\n        run: |\n          echo \"wwiv_tag=${{ env.WWIV_RELEASE_LABEL }}_${{ steps.buildnumber.outputs.build_number }}\" >> $GITHUB_OUTPUT\n          echo \"WWIV_TAG=${{ env.WWIV_RELEASE_LABEL }}_${{ steps.buildnumber.outputs.build_number }}\" >> $GITHUB_ENV\n\n      - name: Tag the latet commit repository with tag ${{ env.WWIV_TAG }}\n        id: tag\n        run: |\n          echo \"WWIV_TAG: ${{ env.WWIV_TAG }}\"\n          git config --global user.email \"gh-action@wwivbbs.org\"\n          git config --global user.name \"GitHub Action\"\n          git tag -f -a \"${{ env.WWIV_TAG }}\" -m \"${{ env.WWIV_TAG }} SHA: \" ${{ github.sha }}\n          git push origin ${{ env.WWIV_TAG }}\n\n  create_release:\n    name: Create Release\n    needs: wwiv-build-number\n    runs-on: ubuntu-latest\n    env:\n      WWIV_TAG: ${{needs.wwiv-build-number.outputs.wwiv_tag}}\n    steps:\n      - name: Create Release\n        id: create_release\n        uses: softprops/action-gh-release@v1\n        with:\n          name: \"${{ env.WWIV_TAG }}\"\n          draft: false\n          prerelease: true\n          generate_release_notes: false   \n          tag_name: \"${{ env.WWIV_TAG }}\"\n\n  wwiv-release:\n    name: Build and Publish\n    needs: \n      - create_release\n      - wwiv-build-number\n    strategy:\n        matrix:\n          os: \n            - windows-2022\n            - ubuntu-22.04\n            - debian-11\n            - debian-12\n            # - ubuntu-20.04\n          include:\n            # Disabled since it's failing to link with cryptlib for some reason\n            # - os: ubuntu-20.04 \n            #   lib_suffix: so\n            #   archive_suffix: tar.gz\n            #   wwiv_distro: linux-ubuntu2004 \n\n            # Run's on the weatherstation private cloud\n            - os: debian-11\n              lib_suffix: so\n              wwiv_distro: linux-debian11\n              archive_suffix: tar.gz\n            # Run's on the weatherstation private cloud\n            - os: debian-12\n              lib_suffix: so\n              wwiv_distro: linux-debian12\n              archive_suffix: tar.gz\n\n            # Github hosted runner\n            - os: ubuntu-22.04\n              lib_suffix: so\n              wwiv_distro: linux-ubuntu2204 \n              archive_suffix: tar.gz\n            # Github hosted runner\n            - os: windows-2022\n              lib_suffix: dll\n              wwiv_distro: win-x86 \n              archive_suffix: zip\n        fail-fast: false\n    runs-on: ${{ matrix.os }}\n    # TODO: Update this on new releases\n    environment: WWIV59\n    env:\n      BUILD_NUMBER: ${{needs.wwiv-build-number.outputs.build_number}}\n      WWIV_TAG: ${{needs.wwiv-build-number.outputs.wwiv_tag}}\n      WWIV_DISTRO: ${{ matrix.wwiv_distro }}\n      WWIV_RELEASE_ARCHIVE_FILE: wwiv-${{ matrix.wwiv_distro }}-${{ vars.WWIV_RELEASE }}.${{needs.wwiv-build-number.outputs.build_number}}.${{ matrix.archive_suffix }}\n      CMAKE_BINARY_DIR: '${{ github.workspace }}/_build'\n      WWIV_RELEASE_DIR: '${{ github.workspace }}/_build/release'\n      \n    steps:\n\n      # - name: Dump Vars\n      #   env:\n      #     VARS: ${{ toJson(vars) }}\n      #     EVENT: ${{ toJson(github.event) }}\n      #     REPO: ${{ github.repository }}\n      #     RELEASE: ${{ vars.WWIV_RELEASE }}\n      #   shell: bash\n      #   run: |\n      #     echo \"WWIV_RELEASE_ARCHIVE_FILE: ${{ env.WWIV_RELEASE_ARCHIVE_FILE }}\"\n      #     echo \"release: ${{ env.RELEASE }}\"\n      #     echo \"github.repository_owner: ${{ github.repository_owner }}\"\n      #     echo \"github.repo: ${{ env.REPO }}\"\n      #     echo \"github.event context: ${{ env.EVENT }}\"\n      #     echo \"vars context: ${{ env.VARS }}\"\n\n      # Check it out again since now it's a new job.\n      - name: Check out repository code\n        uses: actions/checkout@v4\n        with:\n          submodules: recursive\n          \n      - name: Get CMake\n        uses: lukka/get-cmake@latest\n      - name: Setup a new vcpkg\n        uses: lukka/run-vcpkg@v11   # Always specify the specific _version_ of the\n\n      - name: Locate Visual Studio (Windows)\n        if: ${{ matrix.os == 'windows-2022' }}\n        run: |\n          $vcbase=$(vswhere -legacy -latest -property installationPath)\n          echo VCVARS_ALL=\"${vcbase}\\VC\\Auxiliary\\Build\\vcvarsall.bat\" >> \"$env:GITHUB_ENV\"\n\n      - name: Set up Visual Studio Env (Windows)\n        uses: egor-tensin/vs-shell@v2\n        if: ${{ matrix.os == 'windows-2022' }}\n        with:\n          arch: x86\n\n      - name: Build (Windows)\n        if: ${{ matrix.os == 'windows-2022' }}\n        shell: cmd\n        run: builds\\jenkins\\wwiv\\build.cmd\n        env:\n          WWIV_ARCH: x86\n          WWIV_RELEASE: 5.9.0\n\n      - name: Build (Linux)\n        if: ${{ matrix.os != 'windows-2022' }}\n        shell: bash\n        run: builds/jenkins/wwiv/build\n        env:\n          WWIV_ARCH: x86\n          WWIV_RELEASE: 5.9.0\n\n      - name: Upload coverage reports to Codecov\n        uses: codecov/codecov-action@v3\n        env:\n          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}\n          \n      - name: Look for output file\n        run: ls ${{ env.WWIV_RELEASE_ARCHIVE_FILE }}\n  \n      - uses: actions/upload-artifact@v4\n        with:\n          name: ${{ env.WWIV_RELEASE_ARCHIVE_FILE }}\n          path: ${{ env.WWIV_RELEASE_ARCHIVE_FILE }}\n\n      - name: Release to Latest\n        uses: softprops/action-gh-release@v1\n        with:\n          tag_name: \"${{ env.WWIV_TAG }}\"\n          files: ${{ env.WWIV_RELEASE_ARCHIVE_FILE }}"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.sln.docstates\n*.VC.opendb\n*.VC.db\n.vs\n*.COD\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\nunzip__Win32_Release/\nzip___Win32_Release/\nunzip__Win32_Debug/\nzip___Win32_Debug/\n# archives directory from jenkins\narchives/\nstaging/\nwwiv-build-*.zip\n\n# Roslyn cache directories\n*.ide/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n#NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding addin-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings \n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# If using the old MSBuild-Integrated Package Restore, uncomment this:\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Others\nsql/\n*.Cache\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Templates\ntemplate.h\n\n################################################################################\n#\n# Linux/UNIX files\n#\n#\nCMakeFiles\nCMakeCache.txt\nMakefile\n*.a\ndeps/cl345/*.o\ndeps/cl345/static-obj/\ndeps/cl345/tools/endian\n\t\n_build/\n_b/\n\n# CLion files\n.idea/\n*.cbp\n\n# Used by local build system\ncore/version.cpp.saved\n\n# VCPkg Artifacts\nvcpkg_installed\n\n\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"deps/my_basic\"]\n\tpath = deps/my_basic\n\turl = https://github.com/wwivbbs/my_basic.git\n[submodule \"deps/pdcurses\"]\n\tpath = deps/pdcurses\n\turl = https://github.com/wwivbbs/PDCurses.git\n\tbranch = master\n[submodule \"vcpkg\"]\n\tpath = vcpkg\n\turl = https://github.com/Microsoft/vcpkg\n"
  },
  {
    "path": ".lgtm",
    "content": "approvals = 1\npattern = \"(?i)LGTM\"\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "############################################################################### \r\n#\r\n# CMake for WWIV\r\n\r\ncmake_minimum_required(VERSION 3.15 FATAL_ERROR)\r\n\r\nif(POLICY CMP0092)\r\n  # MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.\r\n  cmake_policy(SET CMP0092 NEW)\r\nendif()\r\n\r\nset(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake\r\n  CACHE STRING \"Vcpkg toolchain file\")\r\n\r\nproject(wwiv)\r\n\r\n\r\nlist(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)\r\n\r\n# Set the current root as the Include directory for the compiler,\r\n# since WWIV uses include paths like \"core/foo.h\"\r\ninclude_directories(${CMAKE_SOURCE_DIR})\r\n\r\ninclude(Common)\r\ninclude(FindASan)\r\nfind_package(fmt CONFIG REQUIRED)\r\nfind_package(cereal CONFIG REQUIRED)\r\n\r\nMACRO_ENSURE_OUT_OF_SOURCE_BUILD()\r\nENSURE_MINIMUM_COMPILER_VERSIONS()\r\n\r\nif(WWIV_ASAN_ENABLED)\r\n  string(REGEX REPLACE \"/RTC(su|[1su])\" \"\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\r\n  message(STATUS \"Enabling -fsanitize=address\")\r\n  message(STATUS \"CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}\\n\")\r\n  add_compile_options(-fsanitize=address)\r\nendif()\r\n\r\n# fanalyzer\r\nif(WWIV_GCC_ANALYZER_ENABLED)\r\n  message(STATUS \"Enabling -fanalyzer\")\r\n  add_compile_options(-fanalyzer)\r\nendif()\r\n\r\nif (WWIV_BUILD_TESTS)\r\n  message (STATUS \"WWIV_BUILD_TESTS is ON\")\r\n  find_package(GTest CONFIG REQUIRED)\r\n\r\n  # Workaround gtest really wanting to compile with /Mtd vs /MD\r\n  set(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\r\n  enable_testing()\r\n  include(GoogleTest)\r\nendif (WWIV_BUILD_TESTS)\r\n\r\n# Cryptlib\r\nif (WWIV_SSH_CRYPTLIB AND NOT OS2)\r\nadd_subdirectory(deps/cl345)\r\nendif()\r\n\r\n\r\nif(WIN32 OR OS2)\r\n  # We only use pdcurses on Win32\r\n  add_definitions(-DPDC_WIDE)\r\n  add_subdirectory(deps/pdcurses EXCLUDE_FROM_ALL)\r\nendif()\r\n\r\n#if (NOT OS2)\r\nset(WWIV_BUILD_WWIVD ON)\r\n#endif()\r\nadd_subdirectory(bbs)\r\nadd_subdirectory(binkp)\r\nadd_subdirectory(common)\r\nadd_subdirectory(core)\r\nadd_subdirectory(fsed)\r\nadd_subdirectory(lnet)\r\nadd_subdirectory(local_io)\r\nadd_subdirectory(localui)\r\nadd_subdirectory(net_core)\r\nadd_subdirectory(network)\r\nadd_subdirectory(network1)\r\nadd_subdirectory(network2)\r\nadd_subdirectory(network3)\r\nadd_subdirectory(networkb)\r\nadd_subdirectory(networkc)\r\nadd_subdirectory(networkf)\r\nadd_subdirectory(networkt)\r\nadd_subdirectory(sdk)\r\nadd_subdirectory(wwivconfig)\r\n\r\nif (WWIV_BUILD_WWIVD)\r\nadd_subdirectory(wwivd)\r\nendif()\r\n\r\nadd_subdirectory(wwivfsed)\r\nadd_subdirectory(wwivutil)\r\n\r\nif (WWIV_INSTALL)\r\n  # Create build.nfo\r\n  message(STATUS \"Writing ${CMAKE_BINARY_DIR}/BUILD.NFO\")\r\n  file(\r\n    WRITE \"${CMAKE_BINARY_DIR}/build.nfo\"\r\n    \"Build URL $ENV{BUILD_URL}\\n\"\r\n    \"Build Version: $ENV{BUILD_NUMBER}\\n\\n\"\r\n  )\r\n\r\n  if(WWIV_ZIP_INSTALL_FILES)\r\n    create_datafile_archive(\"data\" \"${WWIV_INSTALL_SRC}/data\")\r\n    create_datafile_archive(\"inifiles\" \"${WWIV_INSTALL_SRC}/inifiles\")\r\n    create_datafile_archive(\"gfiles\" \"${WWIV_INSTALL_SRC}/gfiles\")\r\n    create_datafile_archive(\"menus\" \"${WWIV_INSTALL_SRC}/menus\")\r\n    create_datafile_archive(\"scripts\" \"${WWIV_INSTALL_SRC}/scripts\")\r\n    create_datafile_archive(\"zip-city\" \"${WWIV_INSTALL_SRC}/zip-city\")\r\n    create_datafile_archive(\"regions\" \"${WWIV_INSTALL_SRC}/regions\")\r\n    if (UNIX)\r\n      create_datafile_archive(\"unix\" \"${WWIV_INSTALL_SRC}/platform/unix\")\r\n    endif()\r\n  endif()\r\n\r\n  install(TARGETS bbs DESTINATION .)\r\n  install(TARGETS lnet DESTINATION .)\r\n  install(TARGETS network DESTINATION .)\r\n  install(TARGETS networkb DESTINATION .)\r\n  install(TARGETS networkc DESTINATION .)\r\n  install(TARGETS networkf DESTINATION .)\r\n  install(TARGETS networkt DESTINATION .)\r\n  install(TARGETS network1 DESTINATION .)\r\n  install(TARGETS network2 DESTINATION .)\r\n  install(TARGETS network3 DESTINATION .)\r\n  install(TARGETS wwivconfig DESTINATION .)\r\n  install(TARGETS wwivfsed DESTINATION .)\r\nif(WWIV_BUILD_WWIVD)\r\n  install(TARGETS wwivd DESTINATION .)\r\nendif()\r\n  install(TARGETS wwivutil DESTINATION .)\r\n\r\n  if (UNIX)\r\n    set(PLATFORM_DIR \"${WWIV_INSTALL_SRC}/platform/unix\")\r\n    # Copy shell scripts, rest can be from unix.zip\r\n    file(GLOB PLATFORM_FILES \"${PLATFORM_DIR}/*.sh\" \"${PLATFORM_DIR}/*.bash\")\r\n    foreach(file ${PLATFORM_FILES})\r\n      message(DEBUG \"Installing Platform Specific File: ${file}\")\r\n      INSTALL(FILES \"${file}\" \r\n              PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE\r\n              DESTINATION .)\r\n    endforeach()\r\n  elseif(WIN32)\r\n    set(PLATFORM_DIR \"${WWIV_INSTALL_SRC}/platform/win32\")\r\n    file(GLOB PLATFORM_FILES \"${PLATFORM_DIR}/*\")\r\n    foreach(file ${PLATFORM_FILES})\r\n      message(DEBUG \"Installing Platform Specific File: ${file}\")\r\n      INSTALL(FILES \"${file}\" DESTINATION .)\r\n    endforeach()\r\n    INSTALL(FILES \"${CL32_DLL}\" DESTINATION .)\r\n\r\n  elseif(OS2)\r\n    set(PLATFORM_DIR \"${WWIV_INSTALL_SRC}/platform/os2\")\r\n    file(GLOB PLATFORM_FILES \"${PLATFORM_DIR}/*\")\r\n    foreach(file ${PLATFORM_FILES})\r\n      message(DEBUG \"Installing Platform Specific File: ${file}\")\r\n      INSTALL(FILES \"${file}\" DESTINATION .)\r\n    endforeach()\r\n  endif()\r\n\r\n  file(GLOB DOCS_FILES \"${WWIV_INSTALL_SRC}/docs/*\")\r\n  foreach(file ${DOCS_FILES})\r\n    INSTALL(FILES \"${file}\" DESTINATION .)\r\n  endforeach()\r\nendif (WWIV_INSTALL)\r\n"
  },
  {
    "path": "CMakePresets.json",
    "content": "{\n    \"version\": 4,\n    \"configurePresets\": [\n        {\n            \"name\": \"wwiv-default\",\n            \"displayName\": \"wwiv default build\",\n            \"description\": \"Ninja, x86 debug\",\n            \"generator\": \"Ninja\",\n            \"binaryDir\": \"${sourceDir}/_build\",\n            \"architecture\": {\n                \"value\": \"x86\",\n                \"strategy\": \"external\"\n            },\n            \"cacheVariables\": {\n                \"CMAKE_BUILD_TYPE\": \"Debug\",\n                \"CMAKE_INSTALL_PREFIX\": \"${sourceDir}/install\"\n            }\n        },\n        {\n            \"name\": \"VSCode Debug\",\n            \"description\": \"\",\n            \"displayName\": \"\",\n            \"inherits\": [\n                \"windows-default\"\n            ]\n        }\n    ],\n    \"buildPresets\": [\n        {\n            \"name\": \"WWIV Debug Build\",\n            \"displayName\": \"WWIV Debug Build\",\n            \"configurePreset\": \"wwiv-default\",\n            \"description\": \"Default Windows debug build (MSVC)\"\n        }\n    ],\n    \"testPresets\": [\n        {\n          \"name\": \"wwiv-test-default\",\n          \"description\": \"Enable output on failure\",\n          \"configurePreset\": \"linux-debug\",\n          \"output\": {\n            \"outputOnFailure\": true\n          }\n        },\n        {\n          \"name\": \"core-test-windows\",\n          \"inherits\": \"wwiv-test-default\",\n          \"configurePreset\": \"x86-debug\"\n        }\n      ]\n}"
  },
  {
    "path": "CMakeSettings.json",
    "content": "﻿{\r\n  \"configurations\": [\r\n    {\r\n      \"name\": \"x86-Debug\",\r\n      \"generator\": \"Ninja\",\r\n      \"configurationType\": \"Debug\",\r\n      \"buildRoot\": \"${projectDir}\\\\out\\\\build\\\\${name}\",\r\n      \"installRoot\": \"${projectDir}\\\\out\\\\install\\\\${name}\",\r\n      \"cmakeCommandArgs\": \"\",\r\n      \"buildCommandArgs\": \"\",\r\n      \"ctestCommandArgs\": \"\",\r\n      \"inheritEnvironments\": [ \"msvc_x86\" ],\r\n      \"intelliSenseMode\": \"windows-msvc-x64\"\r\n    }\r\n  ]\r\n}"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# WWIV Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress (@wwivbbs.org), posting via an official social media account, or acting as \nan appointed representative at an online or offline event. Representation of a\nproject may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at coc@wwivbbs.org. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "Doxyfile",
    "content": "# Doxyfile 1.8.10\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the config file\n# that follow. The default is UTF-8 which is also the encoding used for all text\n# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv\n# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv\n# for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = \"WWIV BBS\"\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         = 5.2\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"WWIV BBS System\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           = W:/wwivbbs.github.io/images/WWIV_logo.jpg\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = W:\\wwiv-doxygen\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        = \n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    = \n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = NO\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 4\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines.\n\nALIASES                = \n\n# This tag can be used to specify a number of word-keyword mappings (TCL only).\n# A mapping has the form \"name=value\". For example adding \"class=itcl::class\"\n# will allow you to use the command class in the itcl::class meaning.\n\nTCL_SUBST              = \n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, Javascript,\n# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:\n# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:\n# Fortran. In the later case the parser tries to guess whether the code is fixed\n# or free formatted code, this is the default for Fortran type files), VHDL. For\n# instance to make doxygen treat .inc files as Fortran files (default is PHP),\n# and .f files as C (default is Fortran), use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen.\n\nEXTENSION_MAPPING      = \n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See http://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = NO\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# (class|struct|union) declarations. If set to NO, these declarations will be\n# included in the documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lower-case letters. If set to YES, upper-case letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = NO\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       = \n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    = \n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            = \n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         = \n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong or incomplete\n# parameter documentation, but not about the absence of documentation.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = W:\\wwiv\\core \\\n                         W:\\wwiv\\sdk \\\n                         W:\\wwiv\\networkb \\\n                         W:\\wwiv\\localui\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: http://www.gnu.org/software/libiconv) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,\n# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,\n# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,\n# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,\n# *.vhdl, *.ucf, *.qsf, *.as and *.js.\n\nFILE_PATTERNS          = *.c \\\n                         *.cc \\\n                         *.cxx \\\n                         *.cpp \\\n                         *.c++ \\\n                         *.java \\\n                         *.ii \\\n                         *.ixx \\\n                         *.ipp \\\n                         *.i++ \\\n                         *.inl \\\n                         *.idl \\\n                         *.ddl \\\n                         *.odl \\\n                         *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.cs \\\n                         *.d \\\n                         *.php \\\n                         *.php4 \\\n                         *.php5 \\\n                         *.phtml \\\n                         *.inc \\\n                         *.m \\\n                         *.markdown \\\n                         *.md \\\n                         *.mm \\\n                         *.dox \\\n                         *.py \\\n                         *.f90 \\\n                         *.f \\\n                         *.for \\\n                         *.tcl \\\n                         *.vhd \\\n                         *.vhdl \\\n                         *.ucf \\\n                         *.qsf \\\n                         *.as \\\n                         *.js\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                = \n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       = \n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        = \n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           = \n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             = \n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n\nINPUT_FILTER           = \n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n\nFILTER_PATTERNS        = \n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS = \n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE = \n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = NO\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# function all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see http://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the config file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the\n# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the\n# cost of reduced performance. This can be particularly helpful with template\n# rich C++ code for which doxygen's built-in parser lacks the necessary type\n# information.\n# Note: The availability of this option depends on whether or not doxygen was\n# compiled with the --with-libclang option.\n# The default value is: NO.\n\nCLANG_ASSISTED_PARSING = NO\n\n# If clang assisted parsing is enabled you can provide the compiler with command\n# line options that you would normally use when invoking the compiler. Note that\n# the include paths will already be set by doxygen for the files and directories\n# specified with INPUT and INCLUDE_PATH.\n# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.\n\nCLANG_OPTIONS          = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in\n# which the alphabetical index list will be split.\n# Minimum value: 1, maximum value: 20, default value: 5.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nCOLS_IN_ALPHA_INDEX    = 5\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            = \n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            = \n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        = \n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list). For an example see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  = \n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       = \n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# http://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 359\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 3\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 240\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = NO\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see: http://developer.apple.com/tools/xcode/), introduced with\n# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a\n# Makefile in the HTML output directory. Running make will produce the docset in\n# that directory and running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html\n# for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on\n# Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               = \n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           = \n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the main .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     = \n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               = \n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-\n# folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   = \n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  = \n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  = \n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           = \n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = NO\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# http://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from http://www.mathjax.org before deployment.\n# The default value is: http://cdn.mathjax.org/mathjax/latest.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     = \n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       = \n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using Javascript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/). See the section \"External Indexing and\n# Searching\" for details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       = \n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     = \n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when enabling USE_PDFLATEX this option is only used for generating\n# bitmaps for formulas in the HTML output, but not in the Makefile that is\n# written to the output directory.\n# The default file is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         = \n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber,\n# $projectbrief, $projectlogo. Doxygen will replace $title with the empty\n# string, for the replacement values of the other commands the user is referred\n# to HTML_HEADER.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           = \n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           = \n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET = \n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      = \n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate\n# the PDF file directly from the LaTeX files. Set this option to YES, to get a\n# higher quality PDF documentation.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# http://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's config\n# file, i.e. a series of assignments. You only have to provide replacements,\n# missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    = \n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's config file. A template extensions file can be generated\n# using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    = \n\n# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code\n# with syntax highlighting in the RTF output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_SOURCE_CODE        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             = \n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the\n# program listings (including syntax highlighting and cross-referencing\n# information) to the DOCBOOK output. Note that enabling this will significantly\n# increase the size of the DOCBOOK output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_PROGRAMLISTING = NO\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see http://autogen.sf.net) file that captures the\n# structure of the code including all documentation. Note that this feature is\n# still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX = \n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           = \n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  = \n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             = \n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      = \n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               = \n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       = \n\n# If the ALLEXTERNALS tag is set to YES, all external class will be listed in\n# the class index. If set to NO, only the inherited external classes will be\n# listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n# The PERL_PATH should be the absolute path and name of the perl script\n# interpreter (i.e. the result of 'which perl').\n# The default file (with absolute path) is: /usr/bin/perl.\n\nPERL_PATH              = /usr/bin/perl\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = YES\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            = \n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               = \n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font in the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           = \n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# http://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               = \n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           = \n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           = \n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           = \n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file. If left blank, it is assumed\n# PlantUML is not used or called during a preprocessing step. Doxygen will\n# generate a warning when it encounters a \\startuml command in this case and\n# will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      = \n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  = \n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "Folder.DotSettings",
    "content": "﻿<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namespace:System;assembly=mscorlib\" xmlns:ss=\"urn:shemas-jetbrains-com:settings-storage-xaml\" xmlns:wpf=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=bbsdir/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Bink/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=binkp/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=bputs/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Callout/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=checka/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=datadir/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=endl/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=fidonet/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Fsed/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=gotoxy/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=maxlen/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=msgapi/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=netdir/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=nqsc/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=nqscn/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=oqsc/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=printfile/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=qscn/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=subboards/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=subnum/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=usernum/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=userqsc/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=wwiv/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=wwivd/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=zipfile/@EntryIndexedValue\">True</s:Boolean></wpf:ResourceDictionary>"
  },
  {
    "path": "LICENSE",
    "content": "WWIV Bulletin Board Software (BBS)\nCopyright 1998 WWIV Software Services\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nFull text:\n=======================================================================\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MAINTAINERS",
    "content": "wwiv\n\n"
  },
  {
    "path": "README.md",
    "content": "WWIV BBS\n========\n\nWWIV is compiled with the following compilers:\n  \n- MS Visual C++ 2019 Community Edition.\n- GCC 8.3 (or later) on Linux \n  (tested on Debian10, Ubuntu 20.04, Centos7 with SCL/GCC-8)\n- CMake 3.18 or newer\n\n***\n\n# Building WWIV BBS\n***\n\nWe prefer contributors to FORK ```wwivbbs``` repositories to their account and work from there.\n\n## Building on Windows\n\n### Installing Git\n\nYou will need [Git](https://git-scm.com) installed.  You can use the GitHub Desktop GUI, but it's also easy\nto use the command line tool directly.  You'll need to download [Git](https://git-scm.com/download/win) and\ninstall it.  Make sure the ```git``` command is in your PATH.\n\nIf you are using GitHub Desktop, this is likely in the folder: \"Documents\\GitHub\\WWIV\".  Otherwise just\ncreate a directory and clone your fork.  You can follow instructions that are written by GitHub \n[Here](https://help.github.com/en/github/getting-started-with-github/fork-a-repo). Just make sure that\nwhen you clone the repo, you have \"Recurse Submodules\" specified in the tool, or using \n```--recurse-submodules``` on the command line.\n\n### Download and Install Visual Studio\nWWIV is compiled with the VS2019 compiler for windows. \nYou can download [Microsoft Visual Studio 2019 Community](https://www.visualstudio.com/downloads/)\n\nChoose to install the ```Desktop development with C++``` workload.\nYou also may want to optionally install the following \"Individual Components\":\n```\n   Git For Windows (Only if you do not have this already)\n   GitHub extension for Visual Studio\n```\n\n\n### Build WWIV (Windows)\n* If you cloned a git repository for your fork of WWIV, then select File then Open and choose Folder.\n\n* If you are using the GitHub for Windows extension, then from the Visual Studio IDE, select File and then ```Open from Source Control```\nOn the bottom, you should see your local GIT repositories already.\nAbove that you will see Login to GitHub, do that.\n* Now in your Local repositories (Documents\\GitHub\\WWIV), open the\n  folder WWIV in Visual Studio. It should recognize the CMake build\n  and be able to build WWIV.\n* When VS says \"READY\" on the bottom, go to Build on the menu and select Build Solution(F7). If you have any build errors, run Build one more time and see if that resolves itself as there can be timing issues on some machines.\n* You select whether or not you are building DEBUG or RELEASE on the toolbar. Those binaries and other built files will be places in a \\debug and \\release folder along side your github source files. ex: ```Documents\\GitHub\\WWIV\\debug``` or ```Documents\\GitHub\\WWIV\\release```.\n\n\n## Building on Linux\nThis only builds the binaries, it does NOT include the supporting files.\nPlease follow the\n[Linux Installation](http://docs.wwivbbs.org/en/latest/linux_installation/) instructions under\n*Steps to install the software* for first installing the base system.\n\n** NOTE:** Do these steps as a non-root user; your BBS user would be the easiest from a file permissions perspective later on.  root should never be used to compile binaries.\n\n### Install pre-requisite software\n\nPackage | Comments\n------- | ----------\ngit | to grab the source code for compiling  \nncurses | ncurses-devel, libncurses5-dev, etc depending on your distro\nzlib1g-dev | or zlib-dev depending on your distro\ncmake | 3.18 or later (3.22 or later if using arm64 or aarch64)\nmake | for cryptlib\nninja-build | 1.8 or later, earlier versions probably work too\ng++ | 8.3.0 or later (easiest to install via build-essential on debian/ubuntu)\n\nIf you are on debian or ubuntu, you can use the ```/builds/linux/install-prereqs.sh``` \nscript to ensure that the right software is installed.  This command should be executed as root (using sudo)\n\n### WWIV Binaries\nHere's the list of binaries that will be built in the build directory:  \n\n* bbs/bbs  \n* network/network  \n* networkb/networkb\n* networkc/networkc\n* networkf/networkf\n* networkt/networkt\n* network1/network1\n* network2/network2\n* network3/network3\n* wwivconfig/wwivconfig  \n* wwivd/wwivd  \n* wwivutil/wwivutil  \n\n#### Getting the source from GitHub\nIf you plan to have an active repo, we prefer contributors to FORK WWIVBBS\nrepositories to their account and work from there.  \n\n* [Fork](https://help.github.com/articles/fork-a-repo/), then clone your fork\n    \n    ```bash\n    # Create a directory for your fork's clone.\n    mkdir git\n    chdir git\n    # Clone your fork into the current directory (git).\n    # Use your GitHub username instead of <em>YOUR-USERNAME</em>\n    git clone --recurse-submodules -j8 https://github.com/<em>YOUR-USERNAME</em>/wwiv.git\n    ```\n* Navigate to wwiv\n\n#### Compiling WWIV\n\n\nNow change directory to the ```wwiv``` directory where you cloned the repository\nand run the following:\n  ```\n  mkdir _build\n  cd _build \n  ../cmake-config.sh \n  cmake --build .\n  ```\n\nCopy all of the files newly built, or symlinks to them from your WWIV base install\ni.e. in /opt/wwiv/ (assuming the source is in $HOME/git/wwiv now.)\n```\n # This should be done as the wwiv user who has the source code.\n cd /opt/wwiv\n ln -s $HOME/git/wwiv/builds/tools/linux/use-built-bin.sh\n \n export BUILT_BIN=$HOME/out/wwiv\n ./use-built-bin.sh ${BUILT_BIN} bbs wwivd wwivconfig network network?\n\n```\n\n#### Out of Source Build warning\n\nIf you get an error about needing to do an out of source build, please make sure that\nyou are executing the cmake command from a directory that is not the same as your source\ncode, such as a subdirectory called ```_b``` or ```_build``` or even a different directory\nall together. I use ```/home/rushfan/out/wwiv``` myself.\n\nOnce you get a warning about this, you will need to clean the build so you need to\nremove the following file and directory:\n  * CMakeFiles\n  * CMakeCache.txt \n\n\n## Building on ChromeOS/ChromeBook \n\n* Tested successfully on\n  * ChromeOS versions 99.x.x and higher\n  * CPU/Arch 64bit (i3, i5, aarch64, mediatek arm64)\n  * 4GB+ Memory\n\n* Tested un-successful on (Was unable to get build tools installed)\n  * ChromeOS version below 99.x.x\n  * CPU/Arch 32bit\n  * Under 4GB \n\n\n* Notes: \n  * Not really for production, but great for developing and testing.\n  * Use Linux build directions\n  * Telnet/SSH/Status Ports must be above 10,000 due to limitations on ChromeOS\n  * If running on arm64, or aarch64 CPU, use cmake 3.22.x or higher\n  * Recommend installing under your primary user instead of \"wwiv\" for simplicity sake. (Again not recommended for production use)\n    * If you choose to use a new user be sure to restart the entire linux sub-system after install. \n\n***\nInstallation and SysOp Instructions\n====================\n\nAll the installation and SysOp administration information you \nneed is in the [WWIV Documentation](https://docs.wwivbbs.org/)\n\n***\n\nGet Involved\n====================\n\nIf you want to help out with WWIV BBS:\n\n* Read the [Contributors Guidelines](contributing.md)\n* Check out the [WWIV BBS Homepage](https://www.wwivbbs.org) and find us on IRC.\n* Jump into the [Issues List](https://github.com/wwivbbs/wwiv/issues).\n"
  },
  {
    "path": "bbs/CMakeLists.txt",
    "content": "# CMake for WWIV\n\nadd_library(\n  bbs_lib \n  acs.cpp\n  application.cpp\n  archivers.cpp\n  attach.cpp\n  automsg.cpp\n  batch.cpp\n  bbs.cpp\n  bbs_event_handlers.cpp\n  bbslist.cpp\n  bbsovl1.cpp\n  bbsovl2.cpp\n  bbsovl3.cpp\n  bbsutl.cpp\n  bbsutl1.cpp\n  bbsutl2.cpp\n  chains.cpp\n  chat.cpp\n  chnedit.cpp\n  conf.cpp\n  confutil.cpp\n  connect1.cpp\n  crc.cpp\n  defaults.cpp\n  diredit.cpp\n  dirlist.cpp\n  dropfile.cpp\n  dsz.cpp\n  email.cpp\n  execexternal.cpp\n  external_edit.cpp\n  external_edit_qbbs.cpp\n  external_edit_wwiv.cpp\n  extract.cpp\n  finduser.cpp\n  gfiles.cpp\n  gfileedit.cpp\n  hop.cpp\n  inetmsg.cpp\n  inmsg.cpp\n  instmsg.cpp\n  interpret.cpp\n  lilo.cpp\n  listplus.cpp\n  lpfunc.cpp\n  misccmd.cpp\n  message_file.cpp\n  message_find.cpp\n  mmkey.cpp\n  msgbase1.cpp\n  msgscan.cpp\n  multinst.cpp\n  multmail.cpp\n  netsup.cpp\n  newuser.cpp\n  normupld.cpp\n  save_qscan.cpp\n  readmail.cpp\n  read_message.cpp\n  shortmsg.cpp\n  showfiles.cpp\n  sr.cpp\n  srrcv.cpp\n  srsend.cpp\n  stuffin.cpp\n  subacc.cpp\n  subedit.cpp\n  sublist.cpp\n  subreq.cpp\n  syschat.cpp\n  sysopf.cpp\n  sysoplog.cpp\n  trashcan.cpp\n  trytoul.cpp\n  uedit.cpp\n  utility.cpp\n  valscan.cpp\n  vote.cpp\n  voteedit.cpp\n  wqscn.cpp\n  xfer.cpp\n  xferovl.cpp\n  xferovl1.cpp\n  xfertmp.cpp\n  xinit.cpp\n  wfc.cpp\n  basic/basic.cpp\n  basic/debug_model.cpp\n  basic/debug_state.cpp\n  basic/debugger.cpp\n  basic/util.cpp\n  basic/wwiv.cpp\n  basic/wwiv_data.cpp\n  basic/wwiv_file.cpp\n  basic/wwiv_io.cpp\n  basic/wwiv_os.cpp\n  basic/wwiv_time.cpp\n  ../deps/my_basic/core/my_basic.c\n  menus/config_menus.cpp\n  menus/mainmenu.cpp\n  menus/menucommands.cpp\n  menus/menuspec.cpp\n  menus/menusupp.cpp\n  menus/printcommands.cpp\n  qwk/qwk.cpp\n  qwk/qwk_email.cpp\n  qwk/qwk_mail_packet.cpp\n  qwk/qwk_reply.cpp\n  qwk/qwk_text.cpp\n  qwk/qwk_ui.cpp\n  qwk/qwk_util.cpp\n  prot/crctab.cpp\n  prot/zmodem.cpp\n  prot/zmodemcrc.cpp\n  prot/zmodemr.cpp\n  prot/zmodemt.cpp\n  prot/zmutil.cpp\n  prot/zmwwiv.cpp\n)\n\n\nif(UNIX) \n  message(STATUS \"UNIX ROCKS\")\n  target_sources(bbs_lib PRIVATE\n      exec_unix.cpp \n      \"exec_socket.cpp\"\n      make_abs_cmd_unix.cpp \n  )  \n  if(CMAKE_SYSTEM_NAME MATCHES \"SunOS.*\")\n    list(APPEND CMAKE_EXE_LINKER_FLAGS \"-lsocket -lnsl -lkstat -lssp\")\n  endif()\n\n  find_package (Threads)\n  target_link_libraries(bbs_lib z util ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} nlohmann_json::nlohmann_json)\n\nendif()\n\nif(WIN32)\n  target_sources(bbs_lib PRIVATE\n\t\texec_win32.cpp \n\t\t\"exec_socket.cpp\"\n\t\tmake_abs_cmd_win32.cpp \n  )\n\n  set_max_warnings(bbs_lib)\nendif()\n\nif(OS2)\n  target_sources(bbs_lib PRIVATE\n\t\texec_os2.cpp \n\t\tmake_abs_cmd_os2.cpp \n  )\nendif()\nfind_package(nlohmann_json CONFIG REQUIRED)\n\ntarget_link_libraries(\n  bbs_lib \n  local_io \n  localui \n  common\n  core \n  fsed\n  sdk \n  nlohmann_json::nlohmann_json\n\n)\n\n find_path(CPP_HTTPLIB_INCLUDE_DIRS \"httplib.h\")\ntarget_include_directories(bbs_lib PRIVATE ${CPP_HTTPLIB_INCLUDE_DIRS})\n\nif (WWIV_SSH_CRYPTLIB AND NOT OS2) \n  message(STATUS \"WWIV_SSH_CRYPTLIB is ON\")\n  include_directories(../deps/cl345)\n  target_sources(bbs_lib PRIVATE ssh.cpp)\n  target_link_libraries(bbs_lib CL345_LIB)\n  target_compile_definitions(bbs_lib PRIVATE WWIV_HAS_SSH_CRYPTLIB)\nendif()\n\n\nadd_executable(bbs bbs_main.cpp)\ntarget_link_libraries(bbs bbs_lib fmt::fmt-header-only)\nif (WIN32)\n  add_custom_command(\n    TARGET bbs POST_BUILD\n    COMMAND cmake -E copy_if_different ${CL32_DLL} \"$<TARGET_FILE_DIR:bbs>\"\n  )\nendif()\n\n## Tests\nif (WWIV_BUILD_TESTS)\n\n    set(test_sources\n      bbs_test_main.cpp\n      bbs_helper.cpp\n      bbs_macro_context_test.cpp\n      bbslist_test.cpp\n      bputs_test.cpp\n      bputch_test.cpp\n      datetime_test.cpp\n      dsz_test.cpp\n      email_test.cpp\n      input_test.cpp\n      make_abs_test.cpp\n      msgbase1_test.cpp\n      pause_test.cpp\n      printfile_test.cpp\n      quote_test.cpp\n      qwk_test.cpp\n      stuffin_test.cpp\n      trashcan_test.cpp\n      utility_test.cpp\n      wutil_test.cpp\n      xfer_test.cpp\n      basic/basic_test.cpp\n      basic/util_test.cpp\n    )\n    add_executable(bbs_tests ${test_sources})\n\n    if (WIN32)\n      add_custom_command(\n        TARGET bbs_tests POST_BUILD\n        COMMAND cmake -E copy_if_different ${CL32_DLL} \"$<TARGET_FILE_DIR:bbs>\"\n      )\n    endif()\n\n    if(APPLE)\n      target_link_libraries(program \"-framework CoreFoundation\" \"-framework Security\" \" -framework Foundation\")\n    endif()\n\n    if(UNIX) \n      if(CMAKE_SYSTEM_NAME MATCHES \"SunOS.*\")\n        set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}  -lnsl -lkstat -lssp\")\n        endif()\n      find_package(ZLIB REQUIRED)\n    endif()\n\n  include(GoogleTest)\n\n  target_link_libraries(bbs_tests core bbs_lib core_fixtures common_fixtures GTest::gtest)\n  gtest_discover_tests(bbs_tests)\n\nendif() # WWIV_BUILD_TESTS"
  },
  {
    "path": "bbs/acs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/acs.h\"\n\n#include \"sdk/acs/acs.h\"\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"common/input.h\"\n#include \"common/value/bbsvalueprovider.h\"\n#include \"common/value/uservalueprovider.h\"\n#include \"core/stl.h\"\n#include <string>\n\nusing namespace wwiv::common::value;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs {\n\nbool check_acs(const std::string& expression, acs_debug_t debug) {\n  if (StringTrim(expression).empty()) {\n    // Empty expression is always allowed.\n    return true;\n  }\n\n  const UserValueProvider user_provider(a()->context());\n  const BbsValueProvider bbs_provider(*a()->config(), a()->sess());\n\n  auto [result, debug_info] =\n      sdk::acs::check_acs(*a()->config(), expression, &user_provider, &bbs_provider);\n  for (const auto& l : debug_info) {\n    if (debug == acs_debug_t::local) {\n      LOG(INFO) << l;\n    } else if (debug == acs_debug_t::remote) {\n      bout.pl(l);\n    }\n  }\n\n  return result;\n}\n\nbool validate_acs(const std::string& expression, acs_debug_t debug) {\n  const UserValueProvider up(a()->context());\n  const BbsValueProvider bbsp(*a()->config(), a()->sess());\n  auto [result, ex_what, debug_info] = \n    sdk::acs::validate_acs(expression, &up, &bbsp);\n  if (result) {\n    return true;\n  }\n  if (debug == acs_debug_t::local) {\n    LOG(INFO) << ex_what;\n  } else if (debug == acs_debug_t::remote) {\n    bout.pl(ex_what);\n  }\n  for (const auto& l : debug_info) {\n    if (debug == acs_debug_t::local) {\n      LOG(INFO) << l;\n    } else if (debug == acs_debug_t::remote) {\n      bout.pl(l);\n    }\n  }\n  return false;\n}\n\nstd::string input_acs(common::Input& in, common::Output& out, const std::string& prompt, \n                      const std::string& orig_text, int max_length) {\n  if (!prompt.empty()) {\n    out.pl(\"|#5 WWIV ACS Help\");\n    out.pl(\"|#9 ACS expressions are of the form: |#1attribute OP value\");\n    out.pl(\"|#9 attributes are: |#1user.sl, user.dsl, user.ar, user.dar, user.name, etc \");\n    out.pl(\"|#9 OP (operators) are: |#1>, <, >=. <=, ==, !=\");\n    out.nl();\n    out.pl(\"|#9 Expressions can be grouped with |#1() |#9and combined with \"\n           \"|#1|| |#9(or) or |#1&& |#9(and)\");\n    out.nl();\n    out.pl(\"|#9 Examples: |#2user.sl >= 20\");\n    out.pl(\"|#9           |#2user.sl > 100 || user.ar == 'A'\");\n    out.nl();\n    out.pl(\"|#9 For full documentation see:|#7 http://docs.wwivbbs.org/en/latest/cfg/acs/\\r\\n\");\n    out.nl();\n    out.print(\"|#7{}\\r\\n|#9:\", prompt);\n  }\n\n  auto s = in.input_text(orig_text, max_length);\n\n  if (!validate_acs(s, acs_debug_t::remote)) {\n    out.pausescr();\n    return orig_text;\n  }\n  return s;\n}\n\n} // namespace wwiv::bbs\n"
  },
  {
    "path": "bbs/acs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_ACS_H\n#define INCLUDED_BBS_ACS_H\n\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"sdk/acs/acs.h\"\n\n#include <string>\n\nnamespace wwiv::bbs {\n\nbool check_acs(const std::string& expression, sdk::acs::acs_debug_t debug = sdk::acs::acs_debug_t::none);\nbool validate_acs(const std::string& expression, sdk::acs::acs_debug_t debug = sdk::acs::acs_debug_t::none);\nstd::string input_acs(common::Input& in, common::Output& out, const std::string& prompt, \n                      const std::string& orig_text, int max_length);\n\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/application.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/application.h\"\n\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl2.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/bbsutl2.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/diredit.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/interpret.h\"\n#include \"bbs/lilo.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/ssh.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/subedit.h\"\n#include \"bbs/syschat.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/tag.h\"\n#include \"bbs/wfc.h\"\n#include \"bbs/wqscn.h\"\n#include \"bbs/basic/basic.h\"\n#include \"bbs/menus/mainmenu.h\"\n#include \"bbs/menus/printcommands.h\"\n#include \"common/datetime.h\"\n#include \"common/exceptions.h\"\n#include \"common/input.h\"\n#include \"common/null_remote_io.h\"\n#include \"common/output.h\"\n#include \"common/pipe_expr.h\"\n#include \"common/remote_io.h\"\n#include \"common/workspace.h\"\n#include \"core/command_line.h\"\n#include \"core/eventbus.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings-ng.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"fsed/fsed.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"bbs/chnedit.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"bbs/uedit.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/gfiles.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/names.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"localui/curses_io.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/menus/menu_set.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/networks.h\"\n#include <algorithm>\n#include <chrono>\n#include <iostream>\n#include <memory>\n#include <random>\n#include <stdexcept>\n#include <string>\n\n#if defined(_WIN32)\n#include <crtdbg.h>\n// Needed for isatty\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"common/remote_socket_io.h\"\n#include \"local_io/local_io_win32.h\"\n#include <io.h>\n#else\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"local_io/local_io_curses.h\"\n#include \"local_io/null_local_io.h\" // Used for Linux build.\n#include <unistd.h>\n#endif // _WIN32\n\n#if defined(__OS2__) && defined (_WWIV_USE_TAKE_HANDLES)\n#include \"libcx/handles.h\"\n#endif\n\n#if defined(__OS2__) || defined(_WIN32)\n#include \"common/remote_pipe_io.h\"\n\n#endif\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\n// Implementation of Context for the Application\nclass ApplicationContext final : public Context {\npublic:\n  explicit ApplicationContext(Application* app) : app_(app) {}\n  ApplicationContext() = delete;\n  ApplicationContext(const ApplicationContext&) = delete;\n  ApplicationContext(ApplicationContext&&) = delete;\n  ApplicationContext& operator=(const ApplicationContext&) = delete;\n  ApplicationContext& operator = (ApplicationContext &&) = delete;\n  ~ApplicationContext() override = default;\n  [[nodiscard]] Config& config() override { return *app_->config(); }\n  [[nodiscard]] User& u() override { return *app_->user(); }\n  [[nodiscard]] SessionContext& session_context() override { return app_->sess(); }\n  [[nodiscard]] bool mci_enabled() const override { return bout.mci_enabled(); }\n  [[nodiscard]] const std::vector<editorrec>& editors() const override {\n    return app_->editors;\n  }\n  [[nodiscard]] const Chains& chains() const override {\n    return *app_->chains;\n  }\n\nprivate:\n  Application* app_;\n};\n\n\nApplication::Application(LocalIO* localIO)\n    : local_io_(localIO), oklevel_(exitLevelOK), errorlevel_(exitLevelNotOK),\n      session_context_(std::make_unique<SessionContext>(localIO)),\n      context_(std::make_unique<ApplicationContext>(this)),\n      pipe_eval_(std::make_unique<PipeEval>(*context_)),\n      bbs_macro_context_(std::make_unique<BbsMacroContext>(context_.get(), *pipe_eval_)),\n      batch_(std::make_unique<Batch>()) {\n  VLOG(4) << \"Application::Application()\";\n  ::bout.SetLocalIO(localIO);\n  bout.set_context_provider([this]() -> Context& { return *this->context_; });\n  bout.set_macro_context_provider(\n      [this]() -> MacroContext& { return *bbs_macro_context_; });\n\n  VLOG(4) << \"Application::Application(): 2\";\n  ::bin.SetLocalIO(localIO);\n  bin.set_context_provider([this]() -> Context& { return *this->context_; });\n\n  VLOG(4) << \"Application::Application(): 3\";\n  sess().SetCurrentReadMessageArea(-1);\n  thisuser_ = std::make_unique<User>();\n\n  VLOG(4) << \"Application::Application(): 4\";\n#ifndef __OS2__\n  tzset();\n#endif \n  VLOG(4) << \"Application::Application(): 5\";\n\n  memset(&asv, 0, sizeof(asv_rec));\n  VLOG(4) << \"Application::Application(): 5a\";\n  newuser_colors = {7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n  newuser_bwcolors = {7, 15, 15, 15, 112, 15, 15, 7, 7, 7};\n  VLOG(4) << \"Application::Application(): 5d\";\n  User::CreateNewUserRecord(user(), 50, 20, 0, 0.1234f, newuser_colors, newuser_bwcolors);\n\n  VLOG(4) << \"Application::Application(): 6\";\n  // Set the home directory\n  bbs_dir_ = File::current_directory();\n  chains = std::make_unique<Chains>();\n  VLOG(4) << \"Application::Application(): EXIT\";\n}\n\nApplication::~Application() {\n  if (comm_ && sess().ok_modem_stuff()) {\n    comm_->close(false);\n    comm_.reset(nullptr);\n  }\n  if (local_io_) {\n    local_io_->SetCursor(wwiv::local::io::LocalIO::cursorNormal);\n  }\n  // CursesIO.\n  delete wwiv::local::ui::curses_out;\n  wwiv::local::ui::curses_out = nullptr;\n}\n\nSessionContext& Application::sess() { \n  CHECK(session_context_);\n  return *session_context_; \n}\nconst SessionContext& Application::sess() const { \n  CHECK(session_context_);\n  return *session_context_; \n}\n\nvoid Application::set_user_for_test(User& u) { *thisuser_ = u; }\n\nContext& Application::context() {\n  CHECK(context_);\n  return *context_;\n}\n\nconst Context& Application::context() const {\n  CHECK(context_);\n  return *context_;\n}\n\nbool Application::reset_local_io(LocalIO* wlocal_io) {\n  local_io_.reset(wlocal_io);\n  ::bout.SetLocalIO(wlocal_io);\n  ::bin.SetLocalIO(wlocal_io);\n  session_context_->reset_local_io(wlocal_io);\n\n  const auto screen_bottom = bout.localIO()->GetDefaultScreenBottom();\n  bout.localIO()->SetScreenBottom(screen_bottom);\n  session_context_->num_screen_lines(screen_bottom + 1);\n\n  ClearTopScreenProtection();\n  return true;\n}\n\nvoid Application::CreateComm(unsigned int nHandle, unsigned int /* parent_pid*/,\n                             CommunicationType type) {\n  switch (type) {\n  case CommunicationType::SSH: {\n#ifdef WWIV_HAS_SSH_CRYPTLIB\n    const auto key_fn = FilePath(config_->datadir(), \"wwiv.key\");\n    const File key_file(key_fn);\n    const auto system_password = config()->system_password();\n    wwiv::bbs::Key key(key_fn.string(), system_password);\n    if (!File::Exists(key_fn)) {\n      LOG(ERROR) << \"Key file doesn't exist. Will try to create it.\";\n      if (!key.Create()) {\n        LOG(ERROR) << \"Unable to create or open key file!.  SSH will be disabled!\" << std::endl;\n        comm_ = std::make_unique<RemoteSocketIO>(nHandle, true);\n        break;\n      }\n    }\n    if (!key.Open()) {\n      LOG(ERROR) << \"Unable to open key file!. Did you change your sytem pw?\";\n      LOG(ERROR) << \"If so, delete \" << key_file;\n      LOG(ERROR) << \"SSH will be disabled!\";\n      comm_ = std::make_unique<RemoteSocketIO>(nHandle, true);\n      break;\n    }\n    comm_ = std::make_unique<wwiv::bbs::IOSSH>(nHandle, key);\n#else\n  LOG(ERROR) << \"Attempting to use SSH when SSH support is not enabled.\";\n  LOG(ERROR) << \"SSH will be disabled!\";\n  comm_ = std::make_unique<RemoteSocketIO>(nHandle, true);\n#endif\n  } break;\n  case CommunicationType::TELNET: {\n#if defined(__OS2__) && defined (_WWIV_USE_TAKE_HANDLES)\n    LOG(ERROR) << \"Using _WWIV_USE_TAKE_HANDLES\";\n    LIBCX_HANDLE handles[] = {{LIBCX_HANDLE_FD, 0, nHandle}};\n    wwiv::os::yield();\n    wwiv::os::yield();\n    wwiv::os::yield();\n    if (libcx_take_handles(handles, 1, parent_pid, 0) == -1) {\n      LOG(ERROR) << \"Unable to take file handles: error\" << errno;\n    }\n    wwiv::os::yield();\n#endif\n    comm_ = std::make_unique<RemoteSocketIO>(nHandle, true);\n  } break;\n  case CommunicationType::PIPE: {\n#if defined(__OS2__) || defined(_WIN32)\n    const auto node_num = sess().instance_number();\n    comm_ = std::make_unique<RemotePipeIO>(node_num, true);\n#endif\n  } break;\n  case CommunicationType::NONE: {\n    comm_ = std::make_unique<wwiv::common::NullRemoteIO>(local_io_.get());\n  } break;\n  case CommunicationType::STDIO:\n    comm_ = std::make_unique<wwiv::common::NullRemoteIO>(local_io_.get());\n    break;\n  }\n  bout.SetComm(comm_.get());\n  bin.SetComm(comm_.get());\n}\n\nvoid Application::SetCommForTest(RemoteIO* remote_io) {\n  comm_.reset(remote_io);\n  bout.SetComm(remote_io);\n  bin.SetComm(remote_io);\n}\n\nbool Application::ReadCurrentUser() { \n  DCHECK_GE(sess().user_num(), 1);\n  return ReadCurrentUser(sess().user_num());\n}\n\nbool Application::ReadCurrentUser(int user_number) {\n  DCHECK_GE(user_number, 1);\n  if (!users()->readuser(user(), user_number)) {\n    return false;\n  }\n  last_read_user_number_ = user_number;\n  // Update all other session variables that are dependent.\n  sess().load_menu_set(config_->menudir(), user()->menu_set());\n  sess().num_screen_lines(sess().using_modem() ? user()->screen_lines()\n                                          : bout.localIO()->GetDefaultScreenBottom() + 1);\n  return true;\n}\n\nvoid Application::reset_effective_sl() {\n  sess().effective_sl(user()->sl());\n}\n\nbool Application::WriteCurrentUser() {\n  DCHECK_GE(sess().user_num(), 1);\n  return WriteCurrentUser(sess().user_num()); \n}\n\nbool Application::WriteCurrentUser(int user_number) {\n  DCHECK_GE(sess().user_num(), 1) << \"Trying to call WriteCurrentUser with user_number 0\";\n\n  if (user_number != last_read_user_number_) {\n    LOG(ERROR) << \"Trying to call WriteCurrentUser with user_number: \" << user_number\n               << \"; last_read_user_number_: \" << last_read_user_number_;\n  }\n  // Update any possibly changed session variables.\n  sess().load_menu_set(config_->menudir(), user()->menu_set());\n  return users()->writeuser(user(), user_number);\n}\n\nvoid Application::tleft(bool check_for_timeout) {\n  const auto nsln = nsl();\n\n  // Check for timeout 1st.\n  if (check_for_timeout && sess().IsUserOnline()) {\n    if (nsln == 0) {\n      bout.outstr(\"\\r\\nTime expired.\\r\\n\\n\");\n      a()->Hangup();\n    }\n    return;\n  }\n\n  // If we're not displaying the time left or password on the\n  // topdata display, leave now.\n  if (bout.localIO()->topdata() == LocalIO::topdata_t::none) {\n    return;\n  }\n\n  const auto temp_sysop = user()->sl() != 255 && sess().effective_sl() == 255;\n  const auto sysop_available = wwiv::common::sysop1();\n\n  const auto cx = bout.localIO()->WhereX();\n  const auto cy = bout.localIO()->WhereY();\n  const auto ctl = bout.localIO()->GetTopLine();\n  const auto cc = bout.curatr();\n  bout.curatr(bout.localIO()->GetTopScreenColor());\n  bout.localIO()->SetTopLine(0);\n  const auto line_number =\n      (sess().chatcall() && (bout.localIO()->topdata() == LocalIO::topdata_t::user)) ? 5 : 4;\n\n  bout.localIO()->PutsXY(1, line_number, GetCurrentSpeed());\n  for (auto i = bout.localIO()->WhereX(); i < 23; i++) {\n    bout.localIO()->Putch(static_cast<unsigned char>('\\xCD'));\n  }\n\n  if (temp_sysop) {\n    bout.localIO()->PutsXY(23, line_number, \"Temp Sysop\");\n  }\n\n  if (sysop_available) {\n    bout.localIO()->PutsXY(64, line_number, \"Available\");\n  }\n\n  const auto min_left = nsln / SECONDS_PER_MINUTE;\n  const auto secs_left = nsln % SECONDS_PER_MINUTE;\n  const auto tleft_display = fmt::sprintf(\"T-%4ldm %2lds\", min_left, secs_left);\n  switch (bout.localIO()->topdata()) {\n  case LocalIO::topdata_t::system: {\n    if (sess().IsUserOnline()) {\n      bout.localIO()->PutsXY(18, 3, tleft_display);\n    }\n  } break;\n  case LocalIO::topdata_t::user: {\n    if (sess().IsUserOnline()) {\n      bout.localIO()->PutsXY(18, 3, tleft_display);\n    } else {\n      bout.localIO()->PutsXY(18, 3, user()->password());\n    }\n  } break;\n  case LocalIO::topdata_t::none:\n    break;\n  }\n  bout.localIO()->SetTopLine(ctl);\n  bout.curatr(cc);\n  bout.localIO()->GotoXY(cx, cy);\n}\n\nvoid Application::handle_sysop_key(uint8_t key) {\n  if (bin.okskey()) {\n    if (key >= AF1 && key <= AF10) {\n      // N is the auto-val number (1-10). Add one to make it 1 based not 0 based.\n      const auto n = key - AF1 + 1;\n      auto_val(n, user());\n      reset_effective_sl();\n    } else {\n      switch (key) {\n      case F1: /* F1 */\n        OnlineUserEditor();\n        break;\n      case SF1:\n        /* Shift-F1 */\n        // Nothing.\n        UpdateTopScreen();\n        break;\n      case CF1: /* Ctrl-F1 */\n        // Used to be shutdown bbs in 3 minutes.\n        break;\n      case F2: /* F2 */\n        bout.localIO()->increment_topdata();\n        UpdateTopScreen();\n        break;\n      case F3: /* F3 */\n        if (sess().using_modem()) {\n          sess().incom(!sess().incom());\n          bout.dump();\n          tleft(false);\n        }\n        break;\n      case F4: /* F4 */\n        sess().clear_chatcall();\n        UpdateTopScreen();\n        break;\n      case F5: /* F5 */\n        bout.remoteIO()->disconnect();\n        a()->Hangup(hangup_type_t::sysop_forced);\n        break;\n      case SF5: { /* Shift-F5 */\n        std::random_device rd;\n        std::mt19937 e{rd()};\n        std::uniform_int_distribution dist_len{10, 30};\n        std::uniform_int_distribution dist{1, 256};\n        for (auto i = 0; i < dist_len(e); i++) {\n          bout.outchr(static_cast<char>(dist(e) & 0xff));\n        }\n        bout.remoteIO()->disconnect();\n        a()->Hangup(hangup_type_t::sysop_forced);\n        } break;\n      case CF5: /* Ctrl-F5 */\n        bout.outstr(\"\\r\\nCall back later when you are there.\\r\\n\\n\");\n        bout.remoteIO()->disconnect();\n        a()->Hangup(hangup_type_t::sysop_forced);\n        break;\n      case F6: /* F6 - was Toggle Sysop Alert*/\n        tleft(false);\n        break;\n      case F7: /* F7 */\n        user()->subtract_extratime(std::chrono::minutes(5));\n        tleft(false);\n        break;\n      case F8: /* F8 */\n        user()->add_extratime(std::chrono::minutes(5));\n        tleft(false);\n        break;\n      case F9: /* F9 */\n        if (user()->sl() != 255) {\n          if (sess().effective_sl() != 255) {\n            sess().effective_sl(255);\n          } else {\n            reset_effective_sl();\n          }\n          changedsl();\n          tleft(false);\n        }\n        break;\n      case F10: /* F10 */\n        if (sess().chatting() == wwiv::common::chatting_t::none) {\n          if (config()->sysconfig_flags() & sysconfig_2_way) {\n            chat1(\"\", true);\n          } else {\n            chat1(\"\", false);\n          }\n        } else {\n          sess().chatting(wwiv::common::chatting_t::none);\n        }\n        break;\n      case CF10: /* Ctrl-F10 */\n        if (sess().chatting() == wwiv::common::chatting_t::none) {\n          chat1(\"\", false);\n        } else {\n          sess().chatting(chatting_t::none);\n        }\n        break;\n      case HOME: /* HOME */ {\n        if (sess().chatting() == chatting_t::one_way) {\n          toggle_chat_file();\n        }\n      } break;\n      default:\n        break;\n        ;\n      }\n    }\n  }\n}\n\nvoid Application::DisplaySysopWorkingIndicator(bool displayWait) {\n  const std::string waitString = \"-=[WAIT]=-\";\n  auto nNumPrintableChars = waitString.length();\n  for (auto iter = waitString.begin(); iter != waitString.end(); ++iter) {\n    if (*iter == 3 && nNumPrintableChars > 1) {\n      nNumPrintableChars -= 2;\n    }\n  }\n\n  if (displayWait) {\n    if (okansi()) {\n      const auto nSavedAttribute = bout.curatr();\n      bout.ansic(3);\n      bout.print(\"{}\\x1b[{}D\", waitString, nNumPrintableChars);\n      bout.setc(nSavedAttribute);\n    } else {\n      bout.outstr(waitString);\n    }\n  } else {\n    if (okansi()) {\n      for (unsigned int j = 0; j < nNumPrintableChars; j++) {\n        bout.outchr(' ');\n      }\n      bout.Left(nNumPrintableChars);\n    } else {\n      for (unsigned int j = 0; j < nNumPrintableChars; j++) {\n        bout.bs();\n      }\n    }\n  }\n}\n\nvoid Application::UpdateTopScreen() {\n  if (at_wfc()) {\n    return;\n  }\n\n  auto status = (status_manager()->get_status());\n  int i;\n  char sl[82], ar[17], dar[17], restrict[17], rst[17];\n\n  auto lll = bout.lines_listed();\n\n  if (so() && !sess().incom()) {\n    bout.localIO()->topdata(LocalIO::topdata_t::none);\n  }\n\n#ifdef _WIN32\n  if (config()->sysconfig_flags() & sysconfig_titlebar) {\n    // Only set the titlebar if the user wanted it that way.\n    const auto username_num = user()->name_and_number();\n    const auto title = fmt::sprintf(\"WWIV Node %d (User: %s)\", sess().instance_number(), username_num);\n    ::SetConsoleTitle(title.c_str());\n  }\n#endif // _WIN32\n\n  switch (bout.localIO()->topdata()) {\n  case LocalIO::topdata_t::none:\n    bout.localIO()->set_protect(0);\n    break;\n  case LocalIO::topdata_t::system:\n    bout.localIO()->set_protect(5);\n    break;\n  case LocalIO::topdata_t::user:\n    if (sess().chatcall()) {\n      bout.localIO()->set_protect(6);\n    } else {\n      if (bout.localIO()->GetTopLine() == 6) {\n        bout.localIO()->set_protect(0);\n      }\n      bout.localIO()->set_protect(5);\n    }\n    break;\n  }\n  // This used to be inside of localIO::set_protect but that\n  // made absolutely no sense, so pulled it out here\n  if (!sess().using_modem()) {\n    sess().num_screen_lines(bout.localIO()->GetDefaultScreenBottom() + 1 - bout.localIO()->GetTopLine());\n  }\n\n  auto cx = bout.localIO()->WhereX();\n  auto cy = bout.localIO()->WhereY();\n  auto nOldTopLine = bout.localIO()->GetTopLine();\n  auto cc = bout.curatr();\n  bout.curatr(bout.localIO()->GetTopScreenColor());\n  bout.localIO()->SetTopLine(0);\n  for (i = 0; i < 80; i++) {\n    sl[i] = '\\xCD';\n  }\n  sl[80] = '\\0';\n\n  switch (bout.localIO()->topdata()) {\n  case LocalIO::topdata_t::none:\n    break;\n  case LocalIO::topdata_t::system: {\n    bout.localIO()->PutsXY(0, 0,\n                      fmt::format(\"{:>50}  Activity for {:>8}:      \", config()->system_name(),\n                                  status->last_date()));\n\n    bout.localIO()->PutsXY(\n        0, 1,\n        fmt::sprintf(\n            \"Users: %4u       Total Calls: %5lu      Calls Today: %4u    Posted      :%3u \",\n            status->num_users(), status->caller_num(), status->calls_today(),\n            status->localposts()));\n\n    const auto username_num = user()->name_and_number();\n    bout.localIO()->PutsXY(0, 2,\n                      fmt::sprintf(\"%-36s      %-4u min   /  %2u%%    E-mail sent :%3u \",\n                                   username_num, status->active_today_minutes(),\n                                   static_cast<int>(10 * status->active_today_minutes() / 144),\n                                   status->email_today()));\n\n    auto feedback_waiting = 0;\n    if (const auto sysop = users()->readuser(1)) {\n      feedback_waiting = sysop->email_waiting();\n    }\n    bout.localIO()->PutsXY(\n        0, 3,\n        fmt::sprintf(\n            \"SL=%3u   DL=%3u               FW=%3u      Uploaded:%2u files    Feedback    :%3u \",\n            user()->sl(), user()->dsl(), feedback_waiting, status->uploads_today(),\n            status->feedback_today()));\n  } break;\n  case LocalIO::topdata_t::user: {\n    to_char_array(rst, restrict_string);\n    for (i = 0; i <= 15; i++) {\n      if (user()->has_ar(1 << i)) {\n        ar[i] = static_cast<char>('A' + i);\n      } else {\n        ar[i] = SPACE;\n      }\n      if (user()->has_dar(1 << i)) {\n        dar[i] = static_cast<char>('A' + i);\n      } else {\n        dar[i] = SPACE;\n      }\n      if (user()->has_restrict(1 << i)) {\n        restrict[i] = rst[i];\n      } else {\n        restrict[i] = SPACE;\n      }\n    }\n    dar[16] = '\\0';\n    ar[16] = '\\0';\n    restrict[16] = '\\0';\n    std::string lo;\n    if (date() != user()->laston()) {\n      lo = user()->laston();\n    } else {\n      lo = fmt::sprintf(\"Today:%2d\", user()->ontoday());\n    }\n\n    const auto username_num = user()->name_and_number();\n    auto line =\n        fmt::sprintf(\"%-35s W=%3u UL=%4u/%6lu SL=%3u LO=%5u PO=%4u\", username_num,\n                     user()->email_waiting(), user()->uploaded(), user()->uk(),\n                     user()->sl(), user()->logons(), user()->messages_posted());\n    bout.localIO()->PutsXYA(0, 0, bout.curatr(), line);\n\n    std::string callsign_or_regnum = user()->callsign();\n    if (user()->wwiv_regnum()) {\n      callsign_or_regnum = std::to_string(user()->wwiv_regnum());\n    }\n    auto used_this_session = (system_clock::now() - sess().system_logon_time());\n    auto used_total = used_this_session + user()->timeon();\n    auto minutes_used = duration_cast<minutes>(used_total);\n\n    bout.localIO()->PutsXY(0, 1,\n                      fmt::sprintf(\"%-20s %12s  %-6s DL=%4u/%6lu DL=%3u TO=%5.0d ES=%4u\",\n                                   user()->real_name(), user()->voice_phone(),\n                                   callsign_or_regnum, user()->downloaded(),\n                                   user()->dk(), user()->dsl(), minutes_used.count(),\n                                   user()->email_sent() + user()->email_net()));\n\n    bout.localIO()->PutsXY(0, 2,\n                      fmt::sprintf(\"ARs=%-16s/%-16s R=%-16s EX=%3u %-8s FS=%4u\", ar, dar, restrict,\n                                   user()->exempt(), lo, user()->feedback_sent()));\n\n    int feedback_waiting = 0;\n    if (const auto sysop = users()->readuser(1)) {\n      feedback_waiting = sysop->email_waiting();\n    }\n    bout.localIO()->PutsXY(0, 3,\n                      fmt::sprintf(\"%-40.40s %c %2u %-16.16s           FW= %3u\",\n                                   user()->note(), user()->gender(), user()->age(),\n                                   ctypes(user()->computer_type()), feedback_waiting));\n\n    if (sess() .chatcall()) {\n      bout.localIO()->PutsXY(0, 4, fmt::format(\"{:<80}\", sess().chat_reason()));\n    }\n  } break;\n  }\n  if (nOldTopLine != 0) {\n    bout.localIO()->PutsXY(0, nOldTopLine - 1, sl);\n  }\n  bout.localIO()->SetTopLine(nOldTopLine);\n  bout.localIO()->GotoXY(cx, cy);\n  bout.curatr(cc);\n  tleft(false);\n\n  bout.lines_listed(lll);\n}\n\nvoid Application::ClearTopScreenProtection() {\n  bout.localIO()->set_protect(0);\n  if (!sess().using_modem()) {\n    sess().num_screen_lines(bout.localIO()->GetDefaultScreenBottom() + 1 - bout.localIO()->GetTopLine());\n  }\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nvoid Application::Cls() {\n  bout.localIO()->Cls();\n  bout.clear_lines_listed();\n}\n\nstd::string Application::GetCurrentSpeed() const { return current_speed_; }\n\nstd::string Application::network_name() const {\n  if (nets_->empty() || network_num_ >= wwiv::stl::ssize(*nets_)) {\n    return {};\n  }\n  return nets_->at(network_num_).name;\n}\n\nstd::string Application::network_directory() const {\n  if (nets_->empty() || network_num_ >= wwiv::stl::ssize(*nets_)) {\n    return {};\n  }\n  return nets_->at(network_num_).dir.string();\n}\n\nget_caller_t Application::GetCaller() {\n  wwiv::bbs::WFC wfc(this);\n  const auto [lokb, unx] = wfc.doWFCEvents();\n\n  if (lokb == wwiv::bbs::wfc_events_t::exit) {\n    // Magic exit from WWIV\n    return get_caller_t::exit;\n  }\n\n  sess().using_modem(sess().incom());\n  modem_speed_ = 38400;\n  bin.okskey(true);\n  Cls();\n  bout.localIO()->Puts(StrCat(\"Logging on at \", GetCurrentSpeed(), \" ...\\r\\n\"));\n\n  return lokb == wwiv::bbs::wfc_events_t::login_fast ? get_caller_t::fast_login\n                                                     : get_caller_t::normal_login;\n}\n\nvoid Application::GotCaller(int ms) {\n  bout.localIO()->SetTopLine(0);\n  frequent_init();\n  wfc_cls(a());\n  modem_speed_ = ms;\n  ReadCurrentUser(1);\n  read_qscn(1, sess().qsc, false);\n  reset_effective_sl();\n  sess().user_num(1);\n  if (user()->deleted()) {\n    user()->screen_width(80);\n    user()->screen_lines(25);\n  }\n  Cls();\n  bout.localIO()->Puts(StrCat(\"Logging on at \", GetCurrentSpeed(), \" ...\\r\\n\"));\n  const auto remote_conneted = modem_speed_ != 0;\n  sess().incom(remote_conneted);\n  sess().outcom(remote_conneted);\n  sess().using_modem(remote_conneted);\n}\n\nstd::filesystem::path Application::bbspath() const noexcept { return bbs_dir_; }\nstd::filesystem::path Application::bindir() const noexcept { return bindir_; }\nstd::filesystem::path Application::configdir() const noexcept { return configdir_; }\nstd::filesystem::path Application::logdir() const noexcept { return logdir_; }\nint Application::verbose() const noexcept { return verbose_; }\n\nint Application::ExitBBSImpl(int exit_level, bool perform_shutdown) {\n  std::clog << fmt::format(\"\\r\\nWWIV Bulletin Board System {} exiting at error level {}\\r\\n\\n\",\n                           full_version(), exit_level);\n  std::clog.flush();\n\n  // Only perform shutdown when asked and able.\n  if (!shutdown_on_exit_allowed_ || !perform_shutdown) {\n    return exit_level;\n  }\n  \n  // Only perform shutdown if we've loaded config.json\n  if (!a()->config()) {\n    return exit_level;\n  }\n\n  write_inst(INST_LOC_DOWN, 0, INST_FLAGS_NONE);\n  if (exit_level != Application::exitLevelOK && exit_level != Application::exitLevelQuit) {\n    // Only log the exiting at abnormal error levels, since we see lots of exiting statements\n    // in the logs that don't correspond to sessions every being created (network probes, etc).\n    sysoplog(false, \"\");\n    sysoplog(false, fmt::format(\"WWIV {}, inst {}, taken down at {} on {} with exit code {}.\",\n                                   short_version(), sess().instance_number(), times(), fulldate(),\n                                   exit_level));\n    sysoplog(false, \"\");\n  }\n  catsl();\n  std::clog.flush();\n\n  return exit_level;\n}\n\nint Application::Run(int argc, char* argv[]) {\n  VLOG(4) << \"Application::Run(): \";\n  auto bps = 0;\n  auto ooneuser = false;\n  auto type = CommunicationType::NONE;\n\n#ifdef _WIN32\n  // Disable padding with 0xFE for all safe string functions.\n  // We'd rather leave them padded with 0x0 as default.\n  _CrtSetDebugFillThreshold(0);\n#endif\n  VLOG(4) << \"Application::Run(): 1\";\n  CommandLine cmdline(argc, argv, \"\");\n  cmdline.AddStandardArgs();\n  VLOG(4) << \"Application::Run(): 2\";\n  cmdline.set_no_args_allowed(true);\n  cmdline.add_argument({\"error_exit\", 'a', \"Specify the Error Exit Level\", \"1\"});\n  cmdline.add_argument({\"fsed\", 'f', \"Opens file in the FSED\", \"\"});\n  cmdline.add_argument({\"bps\", 'b', \"Modem speed of logged on user\", \"38400\"});\n  cmdline.add_argument({\"sysop_cmd\", 'c', \"Executes a sysop command (b/c/d)\", \"\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"debug\", 'd', \"Debug WWIVbasic Scripts\", false});\n  cmdline.add_argument({\"debug_port\", \"Debug WWIVbasic Script Port Number\", \"9948\"});\n  cmdline.add_argument(\n      BooleanCommandLineArgument{\"beginday\", 'e', \"Load for beginday event only\", false});\n  cmdline.add_argument({\"handle\", 'h', \"Socket handle\", \"0\"});\n  //cmdline.add_argument({\"parent_pid\", 'p', \"WWIVd's PID\", \"0\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"no_modem\", 'm',\n                                                  \"Don't access the modem at all\", false});\n  cmdline.add_argument({\"instance\", 'n', \"Designate instance number <inst>\", \"1\"});\n  cmdline.add_argument({\"menu_commands\", 'o', \"Displays the menu commands available then exits.\", \"\"});\n  cmdline.add_argument({\"ok_exit\", 'q', \"Normal exit level\", \"0\"});\n  cmdline.add_argument({\"remaining_min\", 'r', \"Specify max # minutes until event\", \"0\"});\n  cmdline.add_argument({\"run_basic\", 's', \"Executes a WWIVbasic script\", \"\"});\n  cmdline.add_argument({\"user_num\", 'u', \"Pass usernumber <user#> online\", \"0\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"version\", 'V', \"Display version.\", false});\n  std::ostringstream xhelp;\n  xhelp << \"Someone is logged in with T for telnet\";\n#if defined(__OS2__) || defined(_WIN32)\n  xhelp << \", P for pipes\";\n#endif\n  xhelp << \", or S for ssh.\";\n  cmdline.add_argument({\"x\", 'x', xhelp.str(), \"\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"no_hangup\", 'z',\n                                                  \"Do not hang up on user when at log off\", false});\n  VLOG(4) << \"Application::Run(): 3\";\n  VLOG(1) << \"Before Parse\";\n  if (!cmdline.Parse()) {\n    std::cout << \"WWIV Bulletin Board System [\" << full_version() << \"]\\r\\n\\n\";\n    std::cout << cmdline.GetHelp() << std::endl;\n    return EXIT_FAILURE;\n  }\n  if (cmdline.help_requested()) {\n    std::cout << \"WWIV Bulletin Board System [\" << full_version() << \"]\\r\\n\\n\";\n    std::cout << cmdline.GetHelp() << std::endl;\n    return 0;\n  }\n  if (cmdline.barg(\"version\")) {\n    std::cout << \"WWIV Bulletin Board System [\" << full_version() << \"]\\r\\n\\n\";\n    return 0;\n  }\n\n  if (const auto bbs_env = environment_variable(\"BBS\"); !bbs_env.empty()) {\n    if (bbs_env.find(\"WWIV\") != std::string::npos) {\n      LOG(ERROR) << \"You are already in the BBS, type 'EXIT' instead.\\n\\n\";\n      return 255;\n    }\n  }\n  \n  bout.curatr(0x07);\n  // Set the directories.\n  bbs_dir_ = cmdline.bbsdir();\n  bindir_ = cmdline.bindir();\n  logdir_ = cmdline.logdir();\n  configdir_ = cmdline.configdir();\n  verbose_ = cmdline.verbose();\n  File::set_current_directory(bbs_dir_);\n  \n  oklevel_ = cmdline.iarg(\"ok_exit\");\n  errorlevel_ = cmdline.iarg(\"error_exit\");\n  const unsigned int hSockOrComm = cmdline.iarg(\"handle\");\n  const unsigned int parent_pid = 0; //cmdline.iarg(\"parent_pid\");\n  no_hangup_ = cmdline.barg(\"no_hangup\");\n  sess().ok_modem_stuff(!cmdline.barg(\"no_modem\"));\n  sess().instance_number(cmdline.iarg(\"instance\"));\n  auto debug = cmdline.barg(\"debug\");\n  if (debug) {\n    auto debug_port = cmdline.iarg(\"debug_port\");\n    sess().debug_wwivbasic_port(debug_port);\n  }\n\n  auto this_usernum_from_commandline = static_cast<uint16_t>(cmdline.iarg(\"user_num\"));\n  if (const auto x = cmdline.sarg(\"x\"); !x.empty()) {\n    const auto xarg = to_upper_case_char(x.at(0));\n    if (cmdline.arg(\"handle\").is_default() && (xarg == 'T' || xarg == 'S')) {\n      std::clog << \"-h must be specified when using '\"\n           << \"-x\" << x << \"'\" << std::endl;\n      return errorlevel_;\n    }\n    if (xarg == 'T' || xarg == 'S' || xarg == 'P') {\n      // Setting a max of 57600 for the BPS value, by default we use 38400\n      // as the default value.\n      bps = std::min<int>(cmdline.iarg(\"bps\"), 57600);\n      switch (xarg) { \n      case 'S':\n        SetCurrentSpeed(\"SSH\");\n        type = CommunicationType::SSH; \n        break;\n      case 'P':\n        SetCurrentSpeed(\"TELNET/PIPE\");\n        type = CommunicationType::PIPE;\n        break;\n      case 'T':\n      default:\n        SetCurrentSpeed(\"TELNET\");\n        type = CommunicationType::TELNET;\n        break;\n      }\n      // Set it false until we call liLo\n      user_already_on_ = true;\n      ooneuser = true;\n      sess().using_modem(false);\n      sess().incom(true);\n      sess().outcom(false);\n    } else {\n      std::clog << \"Invalid Command line argument given '\" << \"-x\" << x << \"'\" << std::endl;\n      return errorlevel_;\n    }\n  }\n  if (this_usernum_from_commandline > 0) {\n    if (!user_already_on_) {\n      SetCurrentSpeed(\"KB\");\n    }\n    user_already_on_ = true;\n    ooneuser = true;\n  }\n\n  // Setup the full-featured localIO if we have a TTY (or console)\n  if (isatty(fileno(stdin))) {\n#if defined(_WIN32) && !defined(WWIV_WIN32_CURSES_IO)\n    reset_local_io(new Win32ConsoleIO());\n#elif defined(__OS2__)\n    // Like Win32, OS/2 has a real local console attached when a remote session is spawned.\n    // Let's use the same curses IO as we do locally.\n    wwiv::local::ui::CursesIO::Init(fmt::sprintf(\"WWIV BBS %s\", full_version()));\n    reset_local_io(new CursesLocalIO(wwiv::local::ui::curses_out->GetMaxY(), \n\t\t\t\t     wwiv::local::ui::curses_out->GetMaxX()));\n\n#else\n    if (type == CommunicationType::NONE) {\n      // We only want the localIO if we ran this locally at a terminal\n      // and also not passed in from the telnet handler, etc.  On Windows\n      // We always have a local console, so this is *NIX specific.\n      wwiv::local::ui::CursesIO::Init(fmt::sprintf(\"WWIV BBS %s\", full_version()));\n      reset_local_io(new CursesLocalIO(wwiv::local::ui::curses_out->GetMaxY(), \n                                       wwiv::local::ui::curses_out->GetMaxX()));\n    } else if (type == CommunicationType::TELNET || type == CommunicationType::SSH) {\n      reset_local_io(new NullLocalIO());\n    }\n#endif\n  } else {\n#ifdef __unix__\n    reset_local_io(new NullLocalIO());\n#endif // __unix__\n  }\n\n  // Add the environment variable or overwrite the existing one\n  const auto env_str = std::to_string(sess().instance_number());\n  set_environment_variable(\"WWIV_INSTANCE\", env_str);\n  if (!ReadConfig()) {\n    // Gotta read the config before we can create the socket handles.\n    // Since we may need the SSH key.\n    return Application::exitLevelNotOK;\n  }\n\n  const auto sysop_cmd = cmdline.sarg(\"sysop_cmd\");\n  const auto fsed = cmdline.sarg(\"fsed\");\n  const auto run_basic = cmdline.sarg(\"run_basic\");\n  const auto mini_cmd = !sysop_cmd.empty() || !fsed.empty() || !run_basic.empty();\n  if (mini_cmd) {\n    // HACK for now, pass arg into InitializeBBS\n    user_already_on_ = true;\n  }\n  CreateComm(hSockOrComm, parent_pid, type);\n  if (!InitializeBBS(!user_already_on_ && sysop_cmd.empty() && fsed.empty() && run_basic.empty())) {\n    return exitLevelNotOK;\n  }\n  bout.localIO()->UpdateNativeTitleBar(config()->system_name(), sess().instance_number());\n\n  auto remote_opened = true;\n  // If we are telnet...\n  if (type == CommunicationType::TELNET || \n      type == CommunicationType::SSH || \n      type == CommunicationType::PIPE) {\n    sess().ok_modem_stuff(true);\n    remote_opened = bout.remoteIO()->open();\n  }\n\n  if (!remote_opened) {\n    // Remote side disconnected.\n    std::clog << \"Remote side disconnected.\" << std::endl;\n    return oklevel_;\n  }\n\n  if (cmdline.barg(\"beginday\")) {\n    if (const auto status = status_manager()->get_status(); date() != status->last_date()) {\n      // This may be another node, but the user explicitly wanted to run the begin-day\n      // event from the commandline, so we'll just check the date.\n      beginday(true);\n    } else {\n      sysoplog(false, \"!!! Wanted to run the beginday event when it's not required!!!\");\n      std::clog << \"! WARNING: Tried to run beginday event again\\r\\n\\n\";\n      sleep_for(seconds(2));\n    }\n    return oklevel_;\n  }\n  if (mini_cmd) {\n    bout.remoteIO()->remote_info().clear();\n    frequent_init();\n    ReadCurrentUser(1);\n    reset_effective_sl();\n    // not sure if this is right\n    sess().user_num(0);\n    // Since hang_it_up sets hangup_ = true, let's ensure we're always\n    // not in this state when we enter the WFC.\n    sess().hangup(false);\n  }\n\n  if (const auto menu_commands = cmdline.arg(\"menu_commands\"); !menu_commands.is_default()) {\n    wwiv::bbs::menus::PrintMenuCommands(menu_commands.as_string());\n    return 0;\n  }\n\n  if (!sysop_cmd.empty()) {\n    LOG(INFO) << \"Executing Sysop Command: \" << sysop_cmd;\n\n    set_at_wfc(true);\n    switch (static_cast<char>(std::toupper(sysop_cmd.front()))) {\n    case 'B':\n      boardedit();\n      break;\n    case 'C':\n      chainedit();\n      break;\n    case 'D':\n      dlboardedit();\n      break;\n    default:\n      LOG(ERROR) << \"Unknown Sysop Command: '\" << sysop_cmd;\n      return errorlevel_;\n    }\n    return oklevel_;\n  }\n  // Runs the FSED on a file\n  if (!fsed.empty()) {\n    LOG(INFO) << \"Executing FSED on : \" << fsed;\n\n    wwiv::fsed::fsed(a()->context(), fsed);\n    return oklevel_;\n  }\n  if (!run_basic.empty()) {\n    const auto eff_user = std::max<int>(this_usernum_from_commandline, 1);\n    ReadCurrentUser(eff_user);\n    reset_effective_sl();\n    sess().user_num(eff_user);\n    if (!wwiv::bbs::basic::RunBasicScript(run_basic)) {\n      LOG(ERROR) << \"Error running WWIVbasic script: '\" << run_basic;\n      return errorlevel_;\n    }\n    return oklevel_;\n  }\n\n#if 0\n  localIO()->Puts(\"Debug: Press any key...\");\n  localIO()->GetChar();\n#endif // 0\n  do {\n    if (this_usernum_from_commandline) {\n      sess().user_num(this_usernum_from_commandline);\n      ReadCurrentUser();\n      if (!user()->deleted()) {\n        GotCaller(bps);\n        sess().user_num(this_usernum_from_commandline);\n        ReadCurrentUser();\n        read_qscn(sess().user_num(), sess().qsc, false);\n        reset_effective_sl();\n        changedsl();\n        sess().okmacro(true);\n      } else {\n        this_usernum_from_commandline = 0;\n      }\n    }\n    try {\n      // Try setting this at the top of the try loop. It's currently only\n      // set in logon() which could cause problems if we get hung up before then.\n      sess().SetLogonTime();\n      \n      auto gt = get_caller_t::normal_login;\n      if (!this_usernum_from_commandline) {\n        if (user_already_on_) {\n          GotCaller(bps);\n        } else {\n          gt = GetCaller();\n          if (gt == get_caller_t::exit) {\n            // GetCaller returning false means time to exit.\n            return Application::exitLevelOK;\n          }\n        }\n      }\n\n      if (gt == get_caller_t::normal_login) {\n        if (!this_usernum_from_commandline) {\n          getuser();\n        }\n      } else {\n        sess().using_modem(false);\n        sess().okmacro(true);\n        reset_effective_sl();\n        changedsl();\n      }\n      this_usernum_from_commandline = 0;\n      CheckForHangup();\n      // Set new timeout\n      logon();\n      setiia(seconds(5));\n      set_net_num(0);\n      while (!sess().hangup() && sess().user_num() > 0) {\n        CheckForHangup();\n        filelist.clear();\n        write_inst(INST_LOC_MAIN, current_user_sub().subnum, INST_FLAGS_NONE);\n        try {\n          wwiv::bbs::menus::mainmenu();\n        } catch (const std::logic_error& le) {\n          std::cerr << \"Caught std::logic_error: \" << le.what() << \"\\r\\n\";\n          sysoplog(le.what());\n        }\n      }\n    } catch (const hangup_error& h) {\n      if (sess().IsUserOnline() && h.hangup_type() == hangup_type_t::user_disconnected) {\n        // Don't need to log this unless the user actually made it online.\n        std::cerr << h.what() << \"\\r\\n\";\n        sysoplog(h.what());\n      }\n    }\n    logoff();\n    {\n      // post_logoff_cleanup\n      VLOG(1) << \"post_logoff_cleanup\";\n      remove_from_temp(\"*.*\", sess().dirs().temp_directory(), false);\n      remove_from_temp(\"*.*\", sess().dirs().batch_directory(), false);\n      remove_from_temp(\"*.*\", sess().dirs().qwk_directory(), false);\n      remove_from_temp(\"*.*\", sess().dirs().scratch_directory(), false);\n      if (!batch().entry.empty() && batch().ssize() != batch().numbatchdl()) {\n        for (const auto& b : batch().entry) {\n          if (!b.sending()) {\n            didnt_upload(b);\n          }\n        }\n      }\n      batch().clear();\n    }\n    if (!no_hangup_ && sess().using_modem() && sess().ok_modem_stuff()) {\n      hang_it_up();\n    }\n    catsl();\n    frequent_init();\n    wfc_cls(a());\n    cleanup_net();\n\n    if (!no_hangup_ && sess().ok_modem_stuff()) {\n      bout.remoteIO()->disconnect();\n    }\n    user_already_on_ = false;\n  } while (!ooneuser);\n\n  return oklevel_;\n}\n\n/** Returns the WWIV SDK Config Object. */\nConfig* Application::config() const { return config_.get(); }\nvoid Application::set_config_for_test(const wwiv::sdk::Config& config) {\n  if (!config_) {\n    config_ = std::make_unique<Config>(config);\n  } else {\n    *config_ = config;\n  }\n}\n\n/** Returns the WWIV Names.LST Config Object. */\nNames* Application::names() const { return names_.get(); }\n\nmsgapi::MessageApi* Application::msgapi(int type) const {\n  if (type == 0) {\n    return wwiv::stl::at(msgapis_, 2).get();\n  }\n  return wwiv::stl::at(msgapis_, type).get();\n}\n\nmsgapi::MessageApi* Application::msgapi() const {\n  if (current_sub().storage_type == 0) {\n    LOG(ERROR) << \"Invalid storage type on sub: \" << current_sub().filename;\n  }\n  return msgapi(current_sub().storage_type);\n}\n\nmsgapi::WWIVMessageApi* Application::msgapi_email() const {\n  return dynamic_cast<wwiv::sdk::msgapi::WWIVMessageApi*>(msgapi(2));\n}\n\nfiles::FileApi* Application::fileapi() const {\n  return fileapi_.get();\n}\nfiles::FileArea* Application::current_file_area() const {\n  return file_area_.get();\n}\n\nvoid Application::set_current_file_area(std::unique_ptr<wwiv::sdk::files::FileArea> a) {\n  file_area_ = std::move(a);\n}\n\nBatch& Application::batch() { return *batch_; }\n\nstatic usersubrec empty_user_sub{\"\", -1};\n\nconst usersubrec& Application::current_user_sub() const {\n  const auto n = current_user_sub_num();\n  if (n >= usub.size()) {\n    return empty_user_sub;\n  }\n  return usub[n];\n}\n\nconst usersubrec& Application::current_user_dir() const {\n  const auto n = current_user_dir_num();\n  if (n >= udir.size()) {\n    return empty_user_sub;\n  }\n  return udir[n];\n}\n\nconst subboard_t& Application::current_sub() const {\n  return subs().sub(sess().GetCurrentReadMessageArea());\n}\n\nvoid Application::set_current_user_dir_num(int n) { \n  user_dir_num_ = static_cast<uint16_t>(n);\n  if (user_dir_num_ < 0 || user_dir_num_ > wwiv::stl::size_int(udir)) {\n    user_dir_num_ = 0;\n  }\n\n  auto subnum = current_user_dir().subnum;\n  if (subnum < 0 || subnum  > dirs().size()) {\n    subnum = 0;\n  }\n  // Update the value in the context.\n  if (!dirs().empty()) {\n    sess().current_dir(dirs()[subnum]);\n  } else {\n    sess().current_dir(wwiv::sdk::files::directory_t{});\n  }\n}\n\nconst files::directory_t& Application::current_dir() const {\n return dirs()[current_user_dir().subnum];\n}\n\nSubs& Application::subs() {\n  CHECK(subs_);\n  return *subs_;\n}\n\nconst Subs& Application::subs() const {\n  CHECK(subs_);\n  return *subs_;\n}\n\nConferences& Application::all_confs() {\n  CHECK(all_confs_);\n  return *all_confs_;\n}\n\nconst Conferences& Application::all_confs() const {\n  CHECK(all_confs_);\n  return *all_confs_;\n}\n\nfiles::Dirs& Application::dirs() {\n  CHECK(dirs_);\n  return *dirs_;\n}\n\nconst files::Dirs& Application::dirs() const {\n  CHECK(dirs_);\n  return *dirs_;\n}\n\nNetworks& Application::nets() {\n  CHECK(nets_);\n  return *nets_;\n}\n\nconst Networks& Application::nets() const {\n  CHECK(nets_);\n  return *nets_;\n}\n\nGFiles& Application::gfiles() {\n  CHECK(gfiles_);\n  return *gfiles_;\n}\n\nconst GFiles& Application::gfiles() const {\n  CHECK(gfiles_);\n  return *gfiles_;\n}\n\nInstances& Application::instances() {\n  CHECK(instances_);\n  return *instances_;\n}\n\nconst Instances& Application::instances() const {\n  CHECK(instances_);\n  return *instances_;\n}\n\nconst Network& Application::current_net() const {\n  const static Network empty_rec(network_type_t::unknown, \"(Unknown)\");\n  if (nets_->empty()) {\n    return empty_rec;\n  }\n  return nets_->at(net_num());\n}\n\nwwiv::sdk::net::Network& Application::mutable_current_net() {\n  static wwiv::sdk::net::Network empty_rec{};\n  if (nets_->empty()) {\n    return empty_rec;\n  }\n  return nets_->at(net_num());\n}\n\nbool Application::IsUseInternalFsed() const { return internal_fsed_; }\n\n/**\n * Should be called after a user is logged off, and will initialize\n * screen-access variables.\n */\nvoid Application::frequent_init() {\n  setiia(seconds(5));\n\n  // Context Globals to move to Application\n  // Context Globals in Application\n  set_extratimecall(seconds(0));\n  ReadCurrentUser(1);\n  sess().reset();\n  bin.charbufferpointer_ = 0;\n  received_short_message(false);\n  use_workspace = false;\n\n  set_net_num(0);\n  read_qscn(1, sess().qsc, false);\n  reset_disable_conf();\n\n  // Output context\n  bout.reset();\n  bin.okskey(true);\n\n  // DSZ Log\n  File::Remove(dsz_logfile_name_, true);\n}\n\n// This function checks to see if the user logged on to the com port has\n// hung up.  Obviously, if no user is logged on remotely, this does nothing.\n// returns the value of sess().hangup()\nbool Application::CheckForHangup() {\n  if (!sess().hangup() && sess().using_modem() && !bout.remoteIO()->connected()) {\n    if (sess().IsUserOnline()) {\n      sysoplog(\"Hung Up.\");\n    }\n    a()->Hangup(hangup_type_t::user_disconnected);\n  }\n  return sess().hangup();\n}\n\nvoid Application::Hangup(hangup_type_t t) {\n  if (!cleanup_cmd.empty()) {\n    bout.nl();\n    wwiv::bbs::CommandLine sc(cleanup_cmd);\n    ExecuteExternalProgram(sc, spawn_option(SPAWNOPT_CLEANUP));\n    bout.nl(2);\n  }\n  if (sess().hangup()) {\n    return;\n  }\n  sess().hangup(true);\n  // Force close the socket to stop it from waiting for the caller.\n  // TODO - See if this should happen somewhere else.\n  comm_->close(false);\n  VLOG(1) << \"Invoked Hangup()\";\n  throw hangup_error(t, user()->name_and_number());\n}\n"
  },
  {
    "path": "bbs/application.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_APPLICATION_H\n#define INCLUDED_BBS_APPLICATION_H\n\n#include \"bbs/runnable.h\"\n#include \"common/exceptions.h\"\n#include \"core/stl.h\"\n\n#include <chrono>\n#include <filesystem>\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\n///////////////////////////////////////////////////////////////////////////////\n// ASV Settings (populated by INI file\n//\nstruct asv_rec {\n  uint8_t sl, dsl, exempt;\n\n  uint16_t ar, dar, restrict;\n};\n\nclass Batch;\nclass BbsMacroContext;\nstruct arcrec;\nstruct editorrec;\nstruct newexternalrec;\nstruct tagrec_t;\nstruct usersubrec;\n\nnamespace wwiv {\nnamespace local {\nnamespace io {\nclass LocalIO;\n}\n}\n\nnamespace common {\nclass SessionContext;\nenum class CommunicationType;\nclass Context;\nclass PipeEval;\nclass RemoteIO;\n\n}\nnamespace core {\nclass IniFile;\n}\nnamespace sdk {\nstruct conference_t;\nclass Config;\nclass Conferences;\nclass Chains;\nclass GFiles;\nclass Instances;\nclass Names;\nclass Networks;\nclass StatusMgr;\nclass Subs;\nstruct subboard_t;\nclass User;\nclass UserManager;\n\nnamespace files {\nclass Dirs;\nclass FileApi;\nclass FileArea;\nstruct directory_t;\n} // namespace wwiv::sdk::files\n\nnamespace msgapi {\nclass MessageApi;\nclass WWIVMessageApi;\n} // namespace msgapi\n\nnamespace net {\nclass Network;\n}\n\n} // namespace sdk\n} // namespace wwiv\n\nenum class get_caller_t { exit, fast_login, normal_login };\n\n/**\n * Application - Holds information and status data about the current user\n * session on the BBS. (i.e. user record, and all data/variables\n * associated with the current logon)\n *\n * This is different from the BbsApp which holds global BBS information\n * associated with this instance of WWIV globally (not tied to a user)\n */\nclass Application final : public Runnable {\n  friend class BbsHelper;\n\npublic:\n  // Constants\n  static constexpr int exitLevelOK{0};\n  static constexpr int exitLevelNotOK = 1;\n  static constexpr int exitLevelQuit = 2;\n\n  explicit Application(wwiv::local::io::LocalIO* localIO);\n  Application() = delete;\n  Application(Application&&) = delete;\n  Application(const Application&) = delete;\n  Application& operator=(const Application&) = delete;\n  Application& operator=(Application&&) = delete;\n  ~Application() override;\n\n  [[nodiscard]] wwiv::sdk::User* user() const { return thisuser_.get(); }\n\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  void set_user_for_test(wwiv::sdk::User& u);\n\n   /**\n    * Provides a mutable  context class for submodules that operate on it. The\n    * context should be enough to run displays and most activities outside of the BBS.\n    */\n  [[nodiscard]] wwiv::common::Context& context();\n   /**\n    * Provides a constant context class for submodules that operate on it. The\n    * context should be enough to run displays and most activities outside of the BBS.\n    */\n  [[nodiscard]] const wwiv::common::Context& context() const;\n\n   /**\n    * Provides a mutable session context class for submodules that operate on it.\n    * This can also be obtained via the Context class.\n    */\n  [[nodiscard]] wwiv::common::SessionContext& sess();\n  [[nodiscard]] const wwiv::common::SessionContext& sess() const;\n\n  void handle_sysop_key(uint8_t key);\n  void tleft(bool check_for_timeout);\n  void DisplaySysopWorkingIndicator(bool displayWait);\n  //[[nodiscard]] wwiv::local::io::LocalIO* localIO() const;\n  bool reset_local_io(wwiv::local::io::LocalIO* wlocal_io);\n  [[nodiscard]] const std::string& GetAttachmentDirectory() const { return attach_dir_; }\n  [[nodiscard]] const std::filesystem::path& netfoss_dir() const { return netfoss_dir_; }\n  [[nodiscard]] const std::string& network_extension() const { return network_extension_; }\n\n  void UpdateTopScreen();\n  void ClearTopScreenProtection();\n  /** Calls LocalIO::Cls() and bout.clear_lines_listed */\n  void Cls();\n\n  /*! @function CreateComm Creates up the communications subsystem */\n  void CreateComm(unsigned int nHandle, unsigned int parent_pid, wwiv::common::CommunicationType type);\n  /**\n   * Sets the RemoteIO handle for testing.\n   * NOTE: This should only be used in unit tests.\n   */\n  void SetCommForTest(wwiv::common::RemoteIO* remote_io);\n\n  bool ReadCurrentUser();\n  bool ReadCurrentUser(int user_number);\n  bool WriteCurrentUser();\n  bool WriteCurrentUser(int user_number);\n\n  void reset_effective_sl();\n\n  [[nodiscard]] int GetChatNameSelectionColor() const { return chatname_color_; }\n\n  [[nodiscard]] int GetMessageColor() const { return message_color_; }\n\n  [[nodiscard]] uint16_t GetForcedReadSubNumber() const { return forced_read_subnum_; }\n  void SetForcedReadSubNumber(int n) { forced_read_subnum_ = static_cast<uint16_t>(n); }\n\n  /**\n   * Gets the current speed or TELNET for the current user.  This should not ever be\n   * used to compare to a number or anything other than display purposes.\n   */\n  [[nodiscard]] std::string GetCurrentSpeed() const;\n\n  /**\n   * Sets the current speed or TELNET for the current user.  This should not ever be\n   * used to compare to a number or anything other than display purposes.\n   */\n  void SetCurrentSpeed(const std::string& s) { current_speed_ = s; }\n\n  [[nodiscard]] std::string network_name() const;\n  [[nodiscard]] std::string network_directory() const;\n\n  [[nodiscard]] bool IsCarbonCopyEnabled() const { return allow_cc_; }\n  void SetCarbonCopyEnabled(bool b) { allow_cc_ = b; }\n\n  [[nodiscard]] int GetNumMessagesReadThisLogon() const { return num_msgs_read_cur_logon_; }\n  void SetNumMessagesReadThisLogon(int n) { num_msgs_read_cur_logon_ = n; }\n\n  [[nodiscard]] bool IsNewScanAtLogin() const { return newscan_at_login_; }\n  void SetNewScanAtLogin(bool b) { newscan_at_login_ = b; }\n\n  // This is the current user's dir number they are sitting on.\n  // This is a user dir number (a()->udir[b], not directories[b]).\n  [[nodiscard]] uint16_t current_user_dir_num() const { return user_dir_num_; }\n  void set_current_user_dir_num(int n);\n\n  // This is the current user's sub number they are sitting on.\n  // This is a user sub number (usub[b], not subboards[b]).\n  [[nodiscard]] uint16_t current_user_sub_num() const { return user_sub_num_; }\n  void set_current_user_sub_num(int n) { user_sub_num_ = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] const usersubrec& current_user_sub() const;\n  [[nodiscard]] const usersubrec& current_user_dir() const;\n\n  // This is set by iscan1 (for the most part) and is the sub number the user is\n  // currently scanning/reading.  Note. this is the subnumber from subboards\n  // not usub.\n  // The most common usage pattern is:\n  // iscan(a()->current_user_sub_num());\n  // if (a()->sess().GetCurrentReadMessageArea() < 0) { ... }\n\n  [[nodiscard]] const wwiv::sdk::subboard_t& current_sub() const;\n  [[nodiscard]] const wwiv::sdk::files::directory_t& current_dir() const;\n\n  [[nodiscard]] const wwiv::sdk::net::Network& current_net() const;\n  [[nodiscard]] wwiv::sdk::net::Network& mutable_current_net();\n\n  [[nodiscard]] bool IsUseInternalZmodem() const { return internal_zmodem_; }\n  [[nodiscard]] bool IsUseInternalFsed() const; \n\n  [[nodiscard]] int GetNumMessagesInCurrentMessageArea() const { return num_msgs_current_sub_; }\n  void SetNumMessagesInCurrentMessageArea(int n) { num_msgs_current_sub_ = n; }\n\n  [[nodiscard]] int GetBeginDayNodeNumber() const { return beginday_node_number_; }\n  void SetBeginDayNodeNumber(int n) { beginday_node_number_ = n; }\n\n  [[nodiscard]] int GetExecChildProcessWaitTime() const { return exec_child_process_wait_time_; }\n  void SetExecChildProcessWaitTime(int n) { exec_child_process_wait_time_ = n; }\n\n  [[nodiscard]] bool IsExecLogSyncFoss() const { return exec_log_syncfoss_; }\n\n  [[nodiscard]] int net_num() const { return network_num_; }\n  void set_net_num(int n) { network_num_ = n; }\n\n  [[nodiscard]] wwiv::sdk::StatusMgr* status_manager() const { return statusMgr.get(); }\n  [[nodiscard]] wwiv::sdk::UserManager* users() const { return user_manager_.get(); }\n\n  [[nodiscard]] uint8_t primary_port() const { return primary_port_; }\n\n  [[nodiscard]] std::filesystem::path bbspath() const noexcept;\n  [[nodiscard]] std::filesystem::path bindir() const noexcept;\n  [[nodiscard]] std::filesystem::path configdir() const noexcept;\n  [[nodiscard]] std::filesystem::path logdir() const noexcept;\n  [[nodiscard]] int verbose() const noexcept;\n\n  [[nodiscard]] bool HasConfigFlag(int nFlag) const { return (flags_ & nFlag) != 0; }\n\n  [[nodiscard]] uint32_t spawn_option(const std::string& c) const { return wwiv::stl::at(spawn_opts_, c); }\n\n  void set_at_wfc(bool b) { at_wfc_ = b; }\n  [[nodiscard]] bool at_wfc() const { return at_wfc_; }\n\n  [[nodiscard]] bool fullscreen_read_prompt() const { return full_screen_read_prompt_; }\n\n  /** Returns the WWIV SDK Config Object. */\n  [[nodiscard]] wwiv::sdk::Config* config() const;\n  void set_config_for_test(const wwiv::sdk::Config& config);\n\n  /** Returns the WWIV Names.LST Config Object. */\n  [[nodiscard]] wwiv::sdk::Names* names() const;\n\n  [[nodiscard]] wwiv::sdk::msgapi::MessageApi* msgapi(int type) const;\n  [[nodiscard]] wwiv::sdk::msgapi::MessageApi* msgapi() const;\n  [[nodiscard]] wwiv::sdk::msgapi::WWIVMessageApi* msgapi_email() const;\n\n  [[nodiscard]] wwiv::sdk::files::FileApi* fileapi() const;\n  [[nodiscard]] wwiv::sdk::files::FileArea* current_file_area() const;\n  void set_current_file_area(std::unique_ptr<wwiv::sdk::files::FileArea> a);\n\n  // Public subsystems\n  [[nodiscard]] Batch& batch();\n  [[nodiscard]] wwiv::sdk::Subs& subs();\n  [[nodiscard]] const wwiv::sdk::Subs& subs() const;\n  [[nodiscard]] wwiv::sdk::Conferences& all_confs();\n  [[nodiscard]] const wwiv::sdk::Conferences& all_confs() const;\n\n  [[nodiscard]] wwiv::sdk::files::Dirs& dirs();\n  [[nodiscard]] const wwiv::sdk::files::Dirs& dirs() const;\n\n  [[nodiscard]] wwiv::sdk::Networks& nets();\n  [[nodiscard]] const wwiv::sdk::Networks& nets() const;\n\n  [[nodiscard]] wwiv::sdk::GFiles& gfiles();\n  [[nodiscard]] const wwiv::sdk::GFiles& gfiles() const;\n\n  [[nodiscard]] wwiv::sdk::Instances& instances();\n  [[nodiscard]] const wwiv::sdk::Instances& instances() const;\n\n  bool read_subs();\n  bool create_message_api();\n\n  [[nodiscard]] std::chrono::seconds extratimecall() const;\n  std::chrono::seconds set_extratimecall(std::chrono::duration<double> et);\n  std::chrono::seconds add_extratimecall(std::chrono::duration<double> et);\n  std::chrono::seconds subtract_extratimecall(std::chrono::duration<double> et);\n\n  void frequent_init();\n  bool CheckForHangup();\n  void Hangup(wwiv::common::hangup_type_t t = wwiv::common::hangup_type_t::user_logged_off);\n\n  /*!\n   * @function Run main bbs loop - Invoked from the application\n   *           main method.\n   * @param argc The number of arguments\n   * @param argv arguments\n   */\n  int Run(int argc, char* argv[]) override;\n\n  int ExitBBSImpl(int exit_level, bool perform_shutdown);\n\n  [[nodiscard]] bool InitializeBBS(bool cleanup_network); // old init() method\n  void ReadINIFile(wwiv::core::IniFile& ini); // from xinit.cpp\n  bool ReadInstanceSettings(int instance_number);\n  bool ReadConfig();\n\n  // Data from system_operation_rec, make it public for now, and add\n  // accessors later on.\n  int chatname_color_{0};\n  int message_color_{0};\n\n  uint16_t forced_read_subnum_{0};\n  bool allow_cc_ = false;\n  bool quoting_ = false;\n\n  bool newscan_at_login_{false};\n  bool internal_zmodem_{true};\n  bool internal_fsed_{true};\n  bool exec_log_syncfoss_{true};\n  int num_msgs_read_cur_logon_{0};\n  uint16_t user_dir_num_{0};\n  uint16_t user_sub_num_{0};\n  // This one should stay in int since -1 is an allowed value.\n  int num_msgs_current_sub_{0};\n\n  int beginday_node_number_{1};\n  int exec_child_process_wait_time_{500};\n  int network_num_{0};\n  int subchg{0};\n\n  std::string net_email_name;\n  uint8_t primary_port_{1};\n  std::string dsz_logfile_name_;\n\n  asv_rec asv{};\n\n  uint16_t max_batch{0};\n  uint16_t max_extend_lines{0};\n  uint16_t max_chains{0};\n  uint16_t max_gfilesec{0};\n  uint16_t screen_saver_time{0};\n\n  std::vector<uint8_t> newuser_colors;\n  std::vector<uint8_t> newuser_bwcolors;\n\n  // public data structures\n  std::vector<editorrec> editors;\n  std::unique_ptr<wwiv::sdk::Chains> chains;\n\n  std::vector<newexternalrec> externs;\n  std::vector<newexternalrec> over_intern;\n  std::vector<arcrec> arcs;\n  // The current set of subs visible to the user in the current conference.\n  // TODO(rusfan): Move into conf\n  std::vector<usersubrec> usub;\n  // The current set of dirs visible to the user in the current conference.\n  std::vector<usersubrec> udir;\n  std::vector<tagrec_t> filelist;\n  std::unique_ptr<wwiv::sdk::Conferences> all_confs_;\n\n  std::vector<wwiv::sdk::conference_t> uconfsub;\n  std::vector<wwiv::sdk::conference_t> uconfdir;\n\n  std::string beginday_cmd;     // beginday event\n  std::string logon_cmd;        // logon event\n  std::string logoff_cmd;       // logoff event\n  std::string cleanup_cmd;       // logoff event\n  std::string newuser_cmd;      // newuser event\n  std::string upload_cmd;       // upload event\n  std::string terminal_command; // Terminal command\n\n  // TODO(rushfan): All of these are moved from vars.h.\n  // Figure out a better way\n  bool emchg_{false};\n  bool no_hangup_{false};\n  int modem_speed_{38400};\n\nprivate:\n  /*!\n   * @function GetCaller WFC Screen loop\n   */\n  get_caller_t GetCaller();\n\n  /*!\n   * @function GotCaller login routines\n   * @param ms Modem Speed (may be a locked speed)\n   */\n  void GotCaller(int ms);\n  void read_nextern();\n  void read_arcs();\n  void read_editors();\n  void read_nintern();\n  void read_networks();\n  bool read_names();\n  bool read_dirs();\n  void read_chains();\n  void read_gfile();\n  void check_phonenum();\n  void create_phone_file();\n\n  // Private fields.\nprivate:\n  // Constructor parameters\n\n  std::unique_ptr<wwiv::local::io::LocalIO> local_io_;\n  int oklevel_;\n  int errorlevel_;\n  std::unique_ptr<wwiv::common::SessionContext> session_context_;\n\n  /*!\n   * The current working directory.\n   */\n  std::filesystem::path bbs_dir_;\n  std::string bindir_;\n  std::string configdir_;\n  std::string logdir_;\n  int verbose_{0};\n\n  std::string network_extension_;\n  bool user_already_on_{false};\n  bool at_wfc_{false};\n  // If true, then we are allowed to perform a shutdown on exit, if false it means the BBS\n  // hasn't yet been started.\n  bool shutdown_on_exit_allowed_{false};\n\n  std::unique_ptr<wwiv::sdk::StatusMgr> statusMgr;\n  std::unique_ptr<wwiv::sdk::UserManager> user_manager_;\n  std::string attach_dir_;\n  std::filesystem::path netfoss_dir_;\n  std::unique_ptr<wwiv::sdk::User> thisuser_;\n  std::unique_ptr<wwiv::common::RemoteIO> comm_;\n  std::string current_speed_;\n  std::unique_ptr<wwiv::sdk::Config> config_;\n  std::unique_ptr<wwiv::sdk::Names> names_;\n  std::map<int, std::unique_ptr<wwiv::sdk::msgapi::MessageApi>> msgapis_;\n  std::unique_ptr<wwiv::sdk::files::FileApi> fileapi_;\n  std::unique_ptr<wwiv::sdk::files::FileArea> file_area_;\n  std::unique_ptr<wwiv::sdk::Subs> subs_;\n  std::unique_ptr<wwiv::sdk::files::Dirs> dirs_;\n  std::unique_ptr<wwiv::sdk::Networks> nets_;\n  std::unique_ptr<wwiv::sdk::GFiles> gfiles_;\n  std::unique_ptr<wwiv::sdk::Instances> instances_;\n\n  // Former global variables and system_operation_rec members to be moved\n  uint32_t flags_{0};\n  std::map<const std::string, uint32_t> spawn_opts_;\n  bool full_screen_read_prompt_{true};\n  int last_read_user_number_{0};\n  std::chrono::duration<double> extratimecall_{};\n  std::unique_ptr<wwiv::common::Context> context_;\n  std::unique_ptr<wwiv::common::PipeEval> pipe_eval_;\n  std::unique_ptr<BbsMacroContext> bbs_macro_context_;\n  std::unique_ptr<Batch> batch_;\n};\n\n#endif\n"
  },
  {
    "path": "bbs/archivers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/archivers.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/make_abs_cmd.h\"\n#include \"bbs/stuffin.h\"\n#include \"core/strings.h\"\n#include \"sdk/files/arc.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nstatic const char DEFAULT_EXT[] = \"ZIP\";\nconstexpr int MAX_ARCS = 15;\n\n\n// Returns which archive as a number in your archive config\n// Returns the first archiver you have listed if unknown\nstd::optional<arcrec> match_archiver(const std::vector<arcrec>& arcs, const std::string& filename) {\n  return wwiv::sdk::files::find_arcrec(arcs, filename, DEFAULT_EXT);\n}\n\nstd::optional<arc_command_t> get_arc_cmd(const std::string& arc_fn, arc_command_type_t cmdtype, const std::string& ofn) {\n\n  auto oa = wwiv::sdk::files::find_arcrec(a()->arcs, arc_fn);\n  if (!oa) {\n    return std::nullopt;\n  }\n  const auto& arc = oa.value();\n  std::string cmdline;\n  switch (cmdtype) {\n  case arc_command_type_t::list:\n    cmdline = arc.arcl;\n    break;\n  case arc_command_type_t::extract:\n    cmdline = arc.arce;\n    break;\n  case arc_command_type_t::add:\n    cmdline = arc.arca;\n    break;\n  case arc_command_type_t::remove:\n    cmdline = arc.arcd;\n    break;\n  case arc_command_type_t::comment:\n    cmdline = arc.arck;\n    break;\n  case arc_command_type_t::test:\n    cmdline = arc.arct;\n    break;\n  default:\n    // Unknown type.\n    return std::nullopt;\n  }\n\n  if (cmdline.empty()) {\n    return std::nullopt;\n  }\n\n  if (cmdline == \"@internal\") {\n    arc_command_t c{};\n    c.internal = true;\n    return {c};\n  }\n  wwiv::bbs::CommandLine cl(cmdline, a()->bbspath());\n  cl.args(arc_fn, ofn);\n  arc_command_t c{false, cl.cmdline()};\n  return {c};\n}\n"
  },
  {
    "path": "bbs/archivers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef _ARCHIVERS_H_\n#define _ARCHIVERS_H_\n\n#include \"sdk/vardec.h\"\n#include <optional>\n#include <string>\n#include <vector>\n\nstd::optional<arcrec> match_archiver(const std::vector<arcrec>& arcs, const std::string& filename);\n\nstruct arc_command_t {\n  bool internal{false};\n  std::string cmd;\n};\n\nenum class arc_command_type_t { list, extract, add, comment, remove, test };\nstd::optional<arc_command_t> get_arc_cmd(const std::string& arc_fn, arc_command_type_t cmd,\n                                         const std::string& data);\n\n#endif  // _ARCHIVERS_H_\n"
  },
  {
    "path": "bbs/attach.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/attach.h\"\n\n#include <memory>\n#include <string>\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"common/com.h\"\n#include \"bbs/email.h\"\n#include \"common/input.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"local_io/wconstants.h\"\n#include \"common/output.h\"\n#include \"bbs/xfer.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/names.h\"\n#include \"sdk/filenames.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nvoid attach_file(int mode) {\n  bool found;\n  std::string full_pathname;\n  std::string file_to_attach;\n  filestatusrec fsr{};\n\n  bout.nl();\n  bool bDirectionForward = true;\n  auto pFileEmail(OpenEmailFile(true));\n  if (!pFileEmail->IsOpen()) {\n    bout.outstr(\"\\r\\nNo mail.\\r\\n\");\n    pFileEmail->Close();\n    return;\n  }\n  auto max = pFileEmail->length() / sizeof(mailrec);\n  auto cur = (bDirectionForward) ? max - 1 : 0;\n\n  int ok = 0;\n  bool done = false;\n  do {\n    mailrec m{};\n    pFileEmail->Seek(cur * sizeof(mailrec), File::Whence::begin);\n    pFileEmail->Read(&m, sizeof(mailrec));\n    while ((m.fromsys != 0 || m.fromuser != a()->sess().user_num() || m.touser == 0) &&\n           cur < max && cur >= 0) {\n      if (bDirectionForward) {\n        --cur;\n      } else {\n        ++cur;\n      }\n      if (cur < max && cur >= 0) {\n        pFileEmail->Seek(cur * sizeof(mailrec), File::Whence::begin);\n        pFileEmail->Read(&m, sizeof(mailrec));\n      }\n    }\n    if (m.fromsys != 0 || m.fromuser != a()->sess().user_num() || m.touser == 0 || cur >= max ||\n        cur < 0) {\n      done = true;\n    } else {\n      bool done1 = false;\n      do {\n        done1 = false;\n        bout.nl();\n        if (m.tosys == 0) {\n          bout.outstr(\"|#1  To|#7: |#2\");\n          if ((m.anony & (anony_receiver | anony_receiver_pp | anony_receiver_da)) &&\n              (a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_email_anony) == 0) {\n            bout.outstr(\">UNKNOWN<\");\n          } else {\n            bout.outstr(a()->names()->UserName(m.touser));\n          }\n          bout.nl();\n        } else {\n          bout.print(\"|#1To|#7: |#2User {} System {}\\r\\n\", m.tosys, m.touser);\n        }\n        bout.print(\"|#1Subj|#7: |#2{}\\r\\n\", m.title);\n        time_t tTimeNow = time(nullptr);\n        int nDaysAgo = static_cast<int>((tTimeNow - m.daten) / SECONDS_PER_DAY);\n        bout.print(\"|#1Sent|#7: |#2 {} days ago\\r\\n\", nDaysAgo);\n        if (m.status & status_file) {\n          File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n          if (fileAttach.Open(File::modeBinary | File::modeReadOnly)) {\n            found = false;\n            auto lNumRead = fileAttach.Read(&fsr, sizeof(fsr));\n            while (lNumRead > 0 && !found) {\n              if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                bout.print(\"|#1Filename|#0.... |#2{} ({} bytes)|#0\\r\\n\", fsr.filename, fsr.numbytes);\n                found = true;\n              }\n              if (!found) {\n                lNumRead = fileAttach.Read(&fsr, sizeof(fsr));\n              }\n            }\n            if (!found) {\n              bout.outstr(\"|#1Filename|#0.... |#2Unknown or missing|#0\\r\\n\");\n            }\n            fileAttach.Close();\n          } else {\n            bout.outstr(\"|#1Filename|#0.... |#2Unknown or missing|#0\\r\\n\");\n          }\n        }\n        bout.nl();\n        char ch = 0;\n        if (mode == 0) {\n          bout.outstr(\"|#9(R)ead, (A)ttach, (N)ext, (Q)uit : \");\n          ch = onek(\"QRAN\");\n        } else {\n          bout.outstr(\"|#9(R)ead, (A)ttach, (Q)uit : \");\n          ch = onek(\"QRA\");\n        }\n        switch (ch) {\n        case 'Q':\n          done1 = true;\n          done = true;\n          break;\n        case 'A': {\n          bool newname = false;\n          bool done2 = false;\n          if (m.status & status_file) {\n            bout.outstr(\"|#6File already attached, (D)elete, (O)verwrite, or (Q)uit? : \");\n            char ch1 = onek(\"QDO\");\n            switch (ch1) {\n            case 'Q':\n              done2 = true;\n              break;\n            case 'D':\n            case 'O': {\n              m.status ^= status_file;\n              pFileEmail->Seek(static_cast<long>(sizeof(mailrec)) * -1L, File::Whence::current);\n              pFileEmail->Write(&m, sizeof(mailrec));\n              File attachFile(FilePath(a()->config()->datadir(), ATTACH_DAT));\n              if (attachFile.Open(File::modeReadWrite | File::modeBinary)) {\n                found = false;\n                auto lNumRead = attachFile.Read(&fsr, sizeof(fsr));\n                while (lNumRead > 0 && !found) {\n                  if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                    fsr.id = 0;\n                    File::Remove(FilePath(a()->GetAttachmentDirectory(), fsr.filename));\n                    attachFile.Seek(static_cast<long>(sizeof(filestatusrec)) * -1L, File::Whence::current);\n                    attachFile.Write(&fsr, sizeof(fsr));\n                  }\n                  if (!found) {\n                    lNumRead = attachFile.Read(&fsr, sizeof(fsr));\n                  }\n                }\n                attachFile.Close();\n                bout.outstr(\"File attachment removed.\\r\\n\");\n              }\n              if (ch1 == 'D') {\n                done2 = true;\n              }\n              break;\n            }\n            }\n          }\n          if (File::freespace_for_path(a()->GetAttachmentDirectory()) < 500) {\n            bout.outstr(\"Not enough free space to attach a file.\\r\\n\");\n          } else {\n            if (!done2) {\n              bool bRemoteUpload = false;\n              found = false;\n              bout.nl();\n              if (so()) {\n                if (a()->sess().incom()) {\n                  bout.outstr(\"|#5Upload from remote? \");\n                  if (bin.yesno()) {\n                    bRemoteUpload = true;\n                  }\n                }\n                if (!bRemoteUpload) {\n                  bout.outstr(\"|#5Path/filename (wildcards okay) : \\r\\n\");\n                  file_to_attach = bin.input(35, true);\n                  if (!file_to_attach.empty()) {\n                    bout.nl();\n                    if (strchr(file_to_attach.c_str(), '*') != nullptr || strchr(file_to_attach.c_str(), '?') != nullptr) {\n                      file_to_attach = get_wildlist(file_to_attach);\n                    }\n                    if (!File::Exists(file_to_attach)) {\n                      found = true;\n                    }\n                    if (!okfn(stripfn(file_to_attach)) || strchr(file_to_attach.c_str(), '?')) {\n                      found = true;\n                    }\n                  }\n                  if (!found && !file_to_attach.empty()) {\n                    full_pathname = FilePath(a()->GetAttachmentDirectory(), stripfn(file_to_attach)).string();\n                    bout.nl();\n                    bout.ansic(5);\n                    bout.print(\"{}?\",file_to_attach);\n                    if (!bin.yesno()) {\n                      found = true;\n                    }\n                  }\n                }\n              }\n              std::string new_filename;\n              if (!so() || bRemoteUpload) {\n                bout.outstr(\"|#2Filename: \");\n                file_to_attach = bin.input(12, true);\n                new_filename = FilePath(a()->GetAttachmentDirectory(), file_to_attach).string();\n                if (!okfn(file_to_attach) || strchr(file_to_attach.c_str(), '?')) {\n                  found = true;\n                }\n              }\n              if (File::Exists(new_filename)) {\n                bout.outstr(\"Target file exists.\\r\\n\");\n                bool done3 = false;\n                do {\n                  found = true;\n                  bout.outstr(\"|#5New name? \");\n                  if (bin.yesno()) {\n                    bout.outstr(\"|#5Filename: \");\n                    new_filename = bin.input(12, true);\n                    full_pathname = FilePath(a()->GetAttachmentDirectory(), new_filename).string();\n                    if (okfn(new_filename) && !strchr(new_filename.c_str(), '?') && !File::Exists(new_filename)) {\n                      found = false;\n                      done3 = true;\n                      newname = true;\n                    } else {\n                      bout.outstr(\"Try Again.\\r\\n\");\n                    }\n                  } else {\n                    done3 = true;\n                  }\n                } while (!done3 && !a()->sess().hangup());\n              }\n              File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n              if (fileAttach.Open(File::modeBinary | File::modeReadOnly)) {\n                auto lNumRead = fileAttach.Read(&fsr, sizeof(fsr));\n                while (lNumRead > 0 && !found) {\n                  if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                    found = true;\n                  } else {\n                    lNumRead = fileAttach.Read(&fsr, sizeof(fsr));\n                  }\n                }\n                fileAttach.Close();\n              }\n              if (found) {\n                bout.outstr(\"File already exists or invalid filename.\\r\\n\");\n              } else {\n                if (so() && !bRemoteUpload) {\n                  std::error_code ec;\n                  if (!std::filesystem::copy_file(file_to_attach, full_pathname, ec)) {\n                    bout.outstr(\"done.\\r\\n\");\n                    ok = 1;\n                  } else {\n                    bout.outstr(\"\\r\\n|#6Error in copy.\\r\\n\");\n                    bin.getkey();\n                  }\n                } else {\n                  const auto full_path = FilePath(a()->GetAttachmentDirectory(), file_to_attach);\n                  receive_file(full_path.string(), &ok, \"\", 0);\n                }\n                if (ok) {\n                  File attachmentFile(full_pathname);\n                  if (!attachmentFile.Open(File::modeReadOnly | File::modeBinary)) {\n                    ok = 0;\n                    bout.outstr(\"\\r\\n\\nDOS error - File not bFound.\\r\\n\\n\");\n                  } else {\n                    fsr.numbytes = static_cast<decltype(fsr.numbytes)>(attachmentFile.length());\n                    attachmentFile.Close();\n                    if (newname) {\n                      to_char_array(fsr.filename, stripfn(new_filename));\n                    } else {\n                      to_char_array(fsr.filename, stripfn(file_to_attach));\n                    }\n                    fsr.id = m.daten;\n                    bout.print(\"|#5Attach {} ({} bytes) to Email? \", fsr.filename, fsr.numbytes);\n                    if (bin.yesno()) {\n                      m.status ^= status_file;\n                      pFileEmail->Seek(static_cast<long>(sizeof(mailrec)) * -1L, File::Whence::current);\n                      pFileEmail->Write(&m, sizeof(mailrec));\n                      File attachFile(FilePath(a()->config()->datadir(), ATTACH_DAT));\n                      if (!attachFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n                        bout.outstr(\"Could not write attachment data.\\r\\n\");\n                        m.status ^= status_file;\n                        pFileEmail->Seek(static_cast<long>(sizeof(mailrec)) * -1L, File::Whence::current);\n                        pFileEmail->Write(&m, sizeof(mailrec));\n                      } else {\n                        filestatusrec fsr1{};\n                        fsr1.id = 1;\n                        File::size_type num_read = 0;\n                        do {\n                          num_read = attachFile.Read(&fsr1, sizeof(filestatusrec));\n                        } while (num_read > 0 && fsr1.id != 0);\n\n                        if (fsr1.id == 0) {\n                          attachFile.Seek(static_cast<long>(sizeof(filestatusrec)) * -1L, File::Whence::current);\n                        } else {\n                          attachFile.Seek(0L, File::Whence::end);\n                        }\n                        attachFile.Write(&fsr, sizeof(filestatusrec));\n                        attachFile.Close();\n                        const auto to_user_name = a()->names()->UserName(m.touser);\n                        sysoplog(fmt::sprintf(\"Attached %s (%u bytes) in message to %s\",\n                                              fsr.filename, fsr.numbytes, to_user_name));\n                        bout.outstr(\"File attached.\\r\\n\");\n                      }\n                    } else {\n                      File::Remove(FilePath(a()->GetAttachmentDirectory(), fsr.filename));\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n        break;\n        case 'N':\n          done1 = true;\n          if (bDirectionForward) {\n            --cur;\n          } else {\n            ++cur;\n          }\n          if (cur >= max || cur < 0) {\n            done = true;\n          }\n          break;\n        case 'R': {\n          bout.nl(2);\n          bool next;\n          auto o = read_type2_message(&m.msg, m.anony & 0x0f, false, \"email\", 0, 0);\n          if (!o) {\n            break;\n          }\n          auto& msg = o.value();\n          msg.title = m.title;\n          int fake_msgno = -1;\n          display_type2_message(fake_msgno, msg, &next);\n          if (m.status & status_file) {\n            File f(FilePath(a()->config()->datadir(), ATTACH_DAT));\n            if (f.Open(File::modeReadOnly | File::modeBinary)) {\n              found = false;\n              auto num_read = f.Read(&fsr, sizeof(fsr));\n              while (num_read > 0 && !found) {\n                if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                  bout.print(\"Attached file: {} ({} bytes).\", fsr.filename, fsr.numbytes);\n                  bout.nl();\n                  found = true;\n                }\n                if (!found) {\n                  num_read = f.Read(&fsr, sizeof(fsr));\n                }\n              }\n              if (!found) {\n                bout.outstr(\"File attached but attachment data missing.  Alert sysop!\\r\\n\");\n              }\n              f.Close();\n            } else {\n              bout.outstr(\"File attached but attachment data missing.  Alert sysop!\\r\\n\");\n            }\n          }\n        }\n        break;\n        }\n      } while (!a()->sess().hangup() && !done1);\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\n"
  },
  {
    "path": "bbs/attach.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_ATTACH_H__\n#define __INCLUDED_BBS_ATTACH_H__\n\nvoid attach_file(int mode);\n\n#endif  // __INCLUDED_BBS_ATTACH_H__"
  },
  {
    "path": "bbs/automsg.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/automsg.h\"\n\n#include \"instmsg.h\"\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/email.h\"\n#include \"bbs/sysoplog.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic bool is_automessage_locked() {\n  const auto lock_file = FilePath(a()->config()->gfilesdir(), LOCKAUTO_MSG);\n  return File::Exists(lock_file);\n}\n\n/**\n * Reads the auto message\n */\nvoid read_automessage() {\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  bout.nl();\n  const auto current_status = a()->status_manager()->get_status();\n  const auto anonymous = current_status->automessage_anon();\n\n  TextFile autoMessageFile(FilePath(a()->config()->gfilesdir(), AUTO_MSG), \"rt\");\n  std::string line;\n  if (!autoMessageFile.IsOpen() || !autoMessageFile.ReadLine(&line)) {\n    bout.outstr(\"|#3No auto-message.\\r\\n\");\n    bout.nl();\n    return;\n  }\n\n  StringTrimEnd(&line);\n  auto authorName = line;\n  if (anonymous) {\n    if (a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_post_anony) {\n      std::stringstream ss;\n      ss << \"<<< \" << line << \" >>>\";\n      authorName = ss.str();\n    } else {\n      authorName = \">UNKNOWN<\";\n    }\n  }\n  bout.print(\"\\r\\n|#9Auto message by: |#2{}|#0\\r\\n\\n\", authorName);\n\n  auto line_number = 0;\n  while (autoMessageFile.ReadLine(&line) && line_number++ < 10) {\n    StringTrim(&line);\n    bout.ansic(9);\n    bout.pl(line);\n  }\n  bout.nl();\n}\n\n/**\n * Writes the auto message\n */\nvoid write_automessage() {\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  if (is_automessage_locked()) {\n    bout.outstr(\"\\r\\n|#3Message is locked.\\r\\n\\n\");\n    bout.pausescr();\n    return;\n  }\n  if (a()->user()->restrict_automessage()) {\n    bout.outstr(\"\\r\\n|#6Not allowed to write to automessage (RESTRICT).\\r\\n\\n\");\n    bout.pausescr();\n    return;\n  }\n  std::vector<std::string> lines;\n  std::string rollOver;\n\n  bout.outstr(\"\\r\\n|#9Enter auto-message. Max 5 lines. Colors allowed:|#0\\r\\n\\n\");\n  for (int i = 0; i < 5; i++) {\n    bout.print(\"|#7{}:|#0\", i + 1);\n    std::string line;\n    inli(&line, &rollOver, 70);\n    lines.push_back(StringTrimEnd(line));\n  }\n  bout.nl();\n  bool bAnonStatus = false;\n  if (a()->config()->sl(a()->sess().effective_sl()).ability & ability_post_anony) {\n    bout.outstr(\"|#9Anonymous? \");\n    bAnonStatus = bin.yesno();\n  }\n\n  auto authorName = a()->user()->name_and_number();\n  if (bAnonStatus) {\n      authorName = \">UNKNOWN<\";\n    }\n  bout.print(\"\\r\\n|#9Auto message by: |#2{}|#0\\r\\n\\n\", authorName);\n  for (const auto& line: lines) {\n      bout.ansic(9);\n      bout.pl(line);\n  }\n  bout.nl();\n  bout.outstr(\"|#9Is this OK? \");\n  if (bin.yesno()) {\n    a()->status_manager()->Run([bAnonStatus](Status& s) {\n      s.automessage_anon(bAnonStatus);\n      s.automessage_usernum(a()->sess().user_num());\n    });\n\n    TextFile file(FilePath(a()->config()->gfilesdir(), AUTO_MSG), \"wt\");\n    file.WriteLine(authorName);\n    sysoplog(\"Changed Auto-message\");\n    for (const auto& line : lines) {\n      file.WriteLine(line);\n      sysoplog(true, line);\n    }\n    bout.outstr(\"\\r\\n|#5Auto-message saved.\\r\\n\\n\");\n    file.Close();\n  }\n}\n\nstatic char ShowAMsgMenuAndGetInput() {\n  auto bCanWrite = false;\n  if (!a()->user()->restrict_automessage()) {\n    bCanWrite = a()->user()->sl() > 20;\n  }\n\n  if (cs()) {\n    bout.outstr(\"|#9(|#2Q|#9)uit, (|#2R|#9)ead, (|#2A|#9)uto-reply, (|#2W|#9)rite, (|#2L|#9)ock, \"\n              \"(|#2D|#9)el, (|#2U|#9)nlock : \");\n    return onek(\"QRWALDU\", true);\n  }\n  if (bCanWrite) {\n    bout.outstr(\"|#9(|#2Q|#9)uit, (|#2R|#9)ead, (|#2A|#9)uto-reply, (|#2W|#9)rite : \");\n    return onek(\"QRWA\", true);\n  }\n  bout.outstr(\"|#9(|#2Q|#9)uit, (|#2R|#9)ead, (|#2A|#9)uto-reply : \");\n  return onek(\"QRA\", true);\n}\n\nvoid email_automessage_author() {\n  clear_quotes(a()->sess());\n  const auto status = a()->status_manager()->get_status();\n  if (status->automessage_usernum() > 0) {\n    email(\"Re: AutoMessage\", status->automessage_usernum(), 0,\n          false, status->automessage_anon() ? anony_sender : 0);\n  }\n}\n\nvoid delete_automessage() {\n  if (!cs()) {\n    bout.outstr(\"|#6Unauthorized.\\r\\n\");\n    return;\n  }\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  bout.outstr(\"\\r\\n|#3Delete Auto-message, Are you sure? \");\n  if (bin.yesno()) {\n    const auto file = FilePath(a()->config()->gfilesdir(), AUTO_MSG);\n    File::Remove(file);\n  }\n  bout.nl(2);\n}\n\nvoid lock_automessage() {\n  if (!cs()) {\n    bout.outstr(\"|#6Unauthorized.\\r\\n\");\n    return;\n  }\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  const auto lock_file = FilePath(a()->config()->gfilesdir(), LOCKAUTO_MSG);\n  if (File::Exists(lock_file)) {\n    bout.outstr(\"\\r\\n|#3Message is already locked.\\r\\n\\n\");\n    return;\n  }\n  bout.outstr(\"|#9Do you want to lock the Auto-message? \");\n  if (bin.yesno()) {\n    /////////////////////////////////////////////////////////\n    // This makes a file in your GFILES dir 1 bytes long,\n    // to tell the board if it is locked or not. It consists\n    // of a space.\n    //\n    TextFile lockFile(lock_file, \"w+t\");\n    lockFile.WriteChar(' ');\n    lockFile.Close();\n  }\n}\n\nvoid unlock_automessage() {\n  if (!cs()) {\n    bout.outstr(\"|#6Unauthorized.\\r\\n\");\n    return;\n  }\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  const auto lock_file = FilePath(a()->config()->gfilesdir(), LOCKAUTO_MSG);\n  if (!File::Exists(lock_file)) {\n    bout.outstr(\"Message not locked.\\r\\n\");\n  } else {\n    bout.outstr(\"|#5Unlock message? \");\n    if (bin.yesno()) {\n      File::Remove(lock_file);\n    }\n  }\n}\n/**\n * Main Auto Message menu.  Displays the auto message then queries for input.\n */\nvoid do_legacy_automessage() {\n  write_inst(INST_LOC_AMSG, 0, INST_FLAGS_NONE);\n  // initially show the auto message\n  read_automessage();\n\n  auto done = false;\n  do {\n    bout.nl();\n    const auto cmdKey = ShowAMsgMenuAndGetInput();\n    switch (cmdKey) {\n    case 'Q':\n      done = true;\n      break;\n    case 'R':\n      read_automessage();\n      break;\n    case 'W':\n      write_automessage();\n      break;\n    case 'A': {\n      email_automessage_author();\n    } break;\n    case 'D':\n      delete_automessage();\n      break;\n    case 'L':\n      lock_automessage();\n      break;\n    case 'U':\n      unlock_automessage();\n      break;\n    default: break;\n    }\n  } while (!done);\n}\n"
  },
  {
    "path": "bbs/automsg.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_AUTOMSG_H\n#define INCLUDED_BBS_AUTOMSG_H\n\nvoid read_automessage();\nvoid do_legacy_automessage();\n\nvoid write_automessage();\nvoid email_automessage_author();\nvoid delete_automessage();\nvoid lock_automessage();\nvoid unlock_automessage();\n\n\n#endif\n"
  },
  {
    "path": "bbs/basic/basic.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"bbs/basic/basic.h\"\n#include \"httplib.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/basic/util.h\"\n#include \"bbs/basic/wwiv.h\"\n#include \"bbs/basic/wwiv_data.h\"\n#include \"bbs/basic/wwiv_file.h\"\n#include \"bbs/basic/wwiv_io.h\"\n#include \"bbs/basic/wwiv_os.h\"\n#include \"bbs/basic/wwiv_time.h\"\n#include \"common/input.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n\n#include <chrono>\n#include <cstdarg>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace std::chrono_literals;\n\nnamespace wwiv::bbs::basic {\n\nstatic int my_print(struct mb_interpreter_t* bas, const char* fmt, ...) {\n  char buf[1024];\n\n  va_list argptr;\n  va_start(argptr, fmt);\n  vsnprintf(buf, sizeof(buf), fmt, argptr);  // NOLINT(clang-diagnostic-format-nonliteral)\n  va_end(argptr);\n\n  const auto* d = get_wwiv_script_userdata(bas);\n  d->out->outstr(buf);\n  d->out->nl();\n  return MB_FUNC_OK;\n}\n\nstatic int my_input(struct mb_interpreter_t* bas, const char* prompt, char* buf, int size) {\n  const auto* d = get_wwiv_script_userdata(bas);\n  if (prompt && *prompt) {\n    d->out->outstr(prompt);\n  }\n  const auto v = d->in->input_text(\"\", size);\n  strcpy(buf, v.c_str());\n  return stl::size_int(v);\n}\n\nstatic bool RegisterMyBasicGlobals() {\n  mb_init();\n  return true;\n}\n\nstatic std::optional<std::string> ReadBasicFile(wwiv::common::Output& out,\n                                                const std::filesystem::path& path,\n                                                const std::string& script_name) {\n    if (script_name.find(\"..\") != std::string::npos) {\n    LOG(ERROR) << \"Invalid script name: \" << script_name;\n    out.print(\"|#6Invalid script name: {}\\r\\n\", script_name);\n    return std::nullopt;\n  }\n\n  if (!File::Exists(path)) {\n    LOG(ERROR) << \"Unable to locate script: \" << path;\n    out.print(\"|#6Unable to locate script: {}\\r\\n\", script_name);\n    return std::nullopt;\n  }\n  TextFile file(path, \"r\");\n  if (!file) {\n    LOG(ERROR) << \"Unable to read script: \" << path;\n    out.print(\"|#6Unable to read script: {}\\r\\n\", script_name);\n    return std::nullopt;\n  }\n  const auto lines = file.ReadFileIntoString();\n  return {lines};\n}\n\nbool Basic::LoadBasicFile(mb_interpreter_t* bas, const std::string& script_name) {\n  const auto* d = get_wwiv_script_userdata(bas);\n  const auto path = FilePath(d->script_dir, script_name);\n  const auto o = ReadBasicFile(*d->out, path, script_name);\n  if (!o) {\n    return false;\n  }\n  if (d->basic->debugger_attached()) {\n    d->basic->debugger()->current_debug_state().AddSourceModule(script_name, o.value());\n  }\n  const auto ret = mb_load_string(bas, o.value().c_str(), true);\n  return ret == MB_FUNC_OK;\n} \n\nstatic void _on_error(struct mb_interpreter_t* s, mb_error_e err, const char* msg, const char* func,\n                      int p, uint16_t row, uint16_t col, int abort_code) {\n  mb_unrefvar(s);\n  mb_unrefvar(p);\n\n  if (err == SE_NO_ERR) {\n    // No erorr here.\n    return;\n  }\n\n  std::string errmsg;\n\n  if (!func) {\n    errmsg = fmt::sprintf(\"Error:\\n    Line %d, Col %d\\n    Code %d, Abort Code %d\\n    Message: %s.\\n\", row, col,\n           static_cast<int>(err), err == SE_EA_EXTENDED_ABORT ? abort_code - MB_EXTENDED_ABORT : abort_code, msg);\n  } else if (err == SE_RN_REACHED_TO_WRONG_FUNCTION) {\n    errmsg = fmt::sprintf(\n        \"Error:\\n    Line %d, Col %d in Func: %s\\n    Code %d, Abort Code %d\\n    Message: %s.\\n\",\n        row, col, func, static_cast<int>(err), abort_code, msg);\n  } else {\n    errmsg = fmt::sprintf(\n        \"Error:\\n    Line %d, Col %d in File: %s\\n    Code %d, Abort Code %d\\n    Message: %s.\\n\",\n        row, col, func, static_cast<int>(err), err == SE_EA_EXTENDED_ABORT ? abort_code - MB_EXTENDED_ABORT : abort_code,\n        msg);\n  }\n\n  const auto* d = get_wwiv_script_userdata(s);\n  auto& out = *d->out;\n  out.print(\"|#6{}\", errmsg);\n  \n  LOG(ERROR) << errmsg;\n}\n\nBasic::Basic(common::Input& i, common::Output& o, const sdk::Config& config, common::Context* ctx)\n    : bin_(i), bout_(o), config_(config), ctx_(ctx) {\n\n  // Creates the script user-data passed to the interpreter.  This data can be used\n  // by the implementation of custom functions.  Values derived from the script name\n  // must be set in RunScript.\n  script_userdata_ = std::make_unique<BasicScriptState>(\n    config_.datadir(), config_.scriptdir(), ctx, &bin_, &bout_, this);\n\n  [[maybe_unused]] static auto once = RegisterMyBasicGlobals();\n\n  bas_ = SetupBasicInterpreter();\n  RegisterDefaultNamespaces();\n}\n\nBasic::~Basic() {\n}\n\nstatic std::string ScriptBaseName(const std::string& script_name) {\n  auto basename = ToStringLowerCase(script_name);\n  if (ends_with(basename, \".bas\")) {\n    return basename.substr(0, basename.find_last_of('.'));\n  }\n  return basename;\n}\n\nmb_interpreter_t* Basic::SetupBasicInterpreter() {\n  struct mb_interpreter_t* bas = nullptr;\n  mb_open(&bas);\n\n  mb_set_error_handler(bas, _on_error);\n\n  if (a()->sess().debug_wwivbasic()) {\n    // Only add these handlers if we're in debug mode.\n    mb_debug_set_stepped_handler(bas, _on_prev_stepped, _on_post_stepped);\n  }\n\n  mb_set_import_handler(bas, [](struct mb_interpreter_t* b, const char* p) -> int {\n    return LoadBasicFile(b, p) ? MB_FUNC_OK : MB_FUNC_ERR;\n  });\n\n  mb_set_printer(bas, my_print);\n  mb_set_inputer(bas, my_input);\n\n  return bas;  \n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool Basic::RegisterDefaultNamespaces() {\n  RegisterNamespaceWWIV(bas_);\n  RegisterNamespaceWWIVIO(bas_);\n  RegisterNamespaceData(bas_);\n  if (config_.script_package_file_enabled()) {\n    RegisterNamespaceWWIVFILE(bas_);\n  }\n  if (config_.script_package_os_enabled()) {\n    RegisterNamespaceWWIVOS(bas_);\n  }\n  RegisterNamespaceWWIVTIME(bas_);\n\n  return true;\n}\n\nbool Basic::RunScript(const std::string& module, const std::string& text) {\n\n  if (!config_.scripting_enabled()) {\n    bout_.outstr(\"WWIVbasic scripting is not enabled on this system.\");\n    return false;\n  }\n  const auto m = ToStringUpperCase(module);\n  {\n    std::lock_guard lock(mu_);\n    script_userdata_->module = m;\n    initial_module_ = m;\n    initial_module_source_ = text;\n  }\n  mb_set_userdata(bas_, script_userdata_.get());\n\n  if (mb_load_string(bas_, text.c_str(), true) != MB_FUNC_OK) {\n    LOG(ERROR) << \"Unable to load text: '\" << text << \"'\";\n    return false;\n  }\n\n  if (a()->sess().debug_wwivbasic()) {\n    bout.pl(\"Waiting for debugger to attach...\");\n    StartDebugger(a()->sess().debug_wwivbasic_port());\n    debugger_->current_debug_state().SetInitialModule(module, text);\n    debugger()->WaitForDebuggerToAttach();\n  }\n\n  static std::mutex script_mutex;\n  std::lock_guard<std::mutex> guard(script_mutex);\n  const auto ret = mb_run(bas_, false);\n  mb_close(&bas_);\n\n  // We don't call mb_dispose since we only call mb_init once per execution.\n  if (ret != MB_FUNC_OK) {\n    LOG(INFO) << \"Failure exiting script: '\" << module << \"' error code (MB_FUNC_XXXX) : \" << ret;\n    return false;\n  }\n  return true;\n}\n\n\nbool Basic::StartDebugger(int port) { \n  std::lock_guard lock(mu_);\n  debugger_ = std::make_unique<Debugger>();\n  return debugger_->StartServers(port);\n}\n\n\nbool Basic::debugger_attached() const {\n  std::lock_guard lock(mu_);\n  if (debugger_) {\n    return debugger_->attached();\n  }\n  return false;\n}\n\nDebugger* Basic::debugger() {\n  std::lock_guard lock(mu_);\n  return debugger_.get();\n}\n\nbool Basic::RunScript(const std::string& script_name) {\n  const auto path = FilePath(config_.scriptdir(), script_name);\n  if (!File::Exists(path)) {\n    bout_.print(\"|#6Unable to locate script: {}\", script_name);\n    return false;\n  }\n\n  const auto o = ReadBasicFile(bout_, path, script_name);\n  if (!o) {\n    return false;\n  }\n  const auto module = ScriptBaseName(script_name);\n  // Check for debugger enablement\n  return RunScript(module, o.value());\n}\n\n\nbool RunBasicScript(const std::string& script_name) {\n  Basic basic(bin, bout, *a()->config(), &a()->context());\n  return basic.RunScript(script_name);\n}\n\n}\n\n"
  },
  {
    "path": "bbs/basic/basic.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_BASIC_H\n#define INCLUDED_BBS_BASIC_BASIC_H\n\n#include \"bbs/basic/util.h\"\n#include \"bbs/basic/debug_state.h\"\n#include \"bbs/basic/debugger.h\"\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n\nnamespace httplib {\nclass Client;\nclass ContentReader;\nstruct Response;\nstruct Request;\nclass Server;\n} // namespace httplib\n\nnamespace wwiv::common {\nclass Input;\nclass Output;\n}\n\nnamespace wwiv::sdk {\nclass Config;\nclass User;\n} // namespace wwiv::sdk\n\nnamespace wwiv::bbs::basic {\n\nclass Basic {\npublic:\n  Basic(common::Input& i, common::Output& o, const sdk::Config& config,\n        common::Context* ctx);\n  ~Basic();\n\n  bool RunScript(const std::string& script_name);\n  bool RunScript(const std::string& module, const std::string& text);\n  bool StartDebugger(int port);\n  [[nodiscard]] mb_interpreter_t* bas() const noexcept { return bas_; }\n\n  // Debugger helpers\n  bool debugger_attached() const;\n  Debugger* debugger();\n\nprivate:\n  bool RegisterDefaultNamespaces();\n  mb_interpreter_t* SetupBasicInterpreter();\n  static bool LoadBasicFile(mb_interpreter_t* bas, const std::string& script_name);\n\n  common::Input& bin_;\n  common::Output& bout_;\n  const sdk::Config& config_;\n  const common::Context* ctx_;\n  std::unique_ptr<BasicScriptState> script_userdata_;\n\n  mb_interpreter_t* bas_;\n\n  // Guard everything the debugger touches\n  mutable std::mutex mu_;\n  std::unique_ptr<DebugState> debug_state_;\n  std::unique_ptr<Debugger> debugger_;\n  std::string initial_module_;\n  std::string initial_module_source_;\n};\n\nbool RunBasicScript(const std::string& script_name);\n\n} // namespace wwiv::bbs\n\n#endif\n"
  },
  {
    "path": "bbs/basic/basic_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// ReSharper disable CppClangTidyCppcoreguidelinesMacroUsage\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n\n#include \"bbs/basic/basic.h\"\n#include \"bbs/basic/util.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include \"fmt/format.h\"\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::bbs::basic;\nusing namespace wwiv::strings;\n\nclass BasicTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    helper.SetUp();\n    // Enable the FILE and OS package.\n    helper.config().scripting_enabled(true);\n    helper.config().script_package_file_enabled(true);\n    helper.config().script_package_os_enabled(true);\n    basic.reset(new Basic(bin, bout, *a()->config(), &helper.context()));\n  }\n\n  [[nodiscard]] bool RunScript(const std::string& text) {\n    const auto* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();\n    const auto module = StrCat(test_info->test_suite_name(), \"#\", test_info->name());\n\n    RegisterBasicUnitTestModule(basic->bas());\n    const auto r = basic->RunScript(module, text);\n    basic.reset(new Basic(bin, bout, *a()->config(), &helper.context()));\n    return r;\n  }\n\n  static bool IsValueEq(const mb_value_t& v1, const mb_value_t& v2, const std::string& msg) {\n    if (v1.type != v2.type) {\n      LOG(WARNING) << \"Different datatypes in ASSERT.EQUALS\";\n      return false;\n    }\n    switch (v1.type) {\n    case MB_DT_INT: {\n      const auto eq = v1.value.integer == v2.value.integer;\n      if (!eq) {\n        std::cerr << \"FAIL: ASSERT.EQUALS: '\" << v1.value.integer << \"' != '\"\n                  << v2.value.integer << \"'\" << msg << std::endl;\n      }\n      return eq;\n    }\n    case MB_DT_REAL: {\n      const auto eq =\n          std::abs(v1.value.float_point - v2.value.float_point) < 0.001f;\n      if (!eq) {\n        std::cerr << \"FAIL: ASSERT.EQUALS: '\" << v1.value.float_point << \"' != '\"\n                  << v2.value.float_point << \"'\" << msg << std::endl;\n      }\n      return eq;\n    }\n    case MB_DT_STRING: {\n      const auto eq = IsEquals(v1.value.string, v2.value.string);\n      if (!eq) {\n        std::cerr << \"FAIL: ASSERT.EQUALS: '\" << v1.value.string << \"' != '\"\n                  << v2.value.string << \"'\" << msg << std::endl;\n      }\n      return eq;\n    }\n    case MB_DT_NIL:\n    case MB_DT_UNKNOWN:\n    case MB_DT_NUM:\n    case MB_DT_TYPE:\n    case MB_DT_USERTYPE:\n    case MB_DT_USERTYPE_REF:\n    case MB_DT_ARRAY:\n    case MB_DT_LIST:\n    case MB_DT_LIST_IT:\n    case MB_DT_DICT:\n    case MB_DT_DICT_IT:\n    case MB_DT_COLLECTION:\n    case MB_DT_ITERATOR:\n    case MB_DT_CLASS:\n    case MB_DT_ROUTINE:\n      LOG(ERROR) << \"Unknown datatype for LHS: \" << v1.type;\n      return false;\n    }\n    return false;\n  }\n\n  static bool IsValueNotEq(const mb_value_t& v1, const mb_value_t& v2, const std::string& msg) {\n    return !IsValueEq(v1, v2, msg);\n  }\n\n  static void RegisterBasicUnitTestModule(mb_interpreter_t* basi) {\n    mb_begin_module(basi, \"ASSERT\");\n\n    mb_register_func(basi, \"EQUALS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n      mb_check(mb_attempt_open_bracket(bas, l));\n      auto v1 = wwiv_mb_pop_value(bas, l);\n      auto v2 = wwiv_mb_pop_value(bas, l);\n      if (!v1 || !v2) {\n        LOG(WARNING) << \"missing params in ASSERT.EQUALS\";\n        return MB_FUNC_ERR;\n      }\n      std::string msg;\n      if (mb_has_arg(bas, l)) {\n        if (const auto rm = wwiv_mb_pop_string(bas, l)) {\n          msg = rm.value();          \n        }\n      }\n      mb_check(mb_attempt_close_bracket(bas, l));\n      return IsValueEq(v1.value(), v2.value(), msg) ? MB_FUNC_OK : MB_FUNC_ERR;\n\n    });\n\n    mb_register_func(basi, \"NE\", [](struct mb_interpreter_t* bas, void** l) -> int {\n      mb_check(mb_attempt_open_bracket(bas, l));\n      auto v1 = wwiv_mb_pop_value(bas, l);\n      auto v2 = wwiv_mb_pop_value(bas, l);\n      if (!v1 || !v2) {\n        LOG(WARNING) << \"missing params in ASSERT.NE\";\n        return MB_FUNC_ERR;\n      }\n      std::string msg;\n      if (mb_has_arg(bas, l)) {\n        if (const auto rm = wwiv_mb_pop_string(bas, l)) {\n          msg = rm.value();          \n        }\n      }\n      mb_check(mb_attempt_close_bracket(bas, l));\n      return IsValueNotEq(v1.value(), v2.value(), msg) ? MB_FUNC_OK : MB_FUNC_ERR;\n    });\n\n    mb_end_module(basi);\n  }\n\n  BbsHelper helper{};\n  std::unique_ptr<Basic> basic;\n};\n\n#define BASIC_ASSERT_EQUALS(v1, v2)                                                                \\\n  do {                                                                                             \\\n    const auto __s = fmt::format(R\"( ASSERT.EQUALS({}, {}) )\", v1, v2);                            \\\n    ASSERT_TRUE(RunScript(__s));                                                                   \\\n  } while (0)\n\n#define BASIC_ASSERT_NE(v1, v2)                                                                \\\n  do {                                                                                             \\\n    const auto __s = fmt::format(R\"( ASSERT.NE({}, {}) )\", v1, v2);                            \\\n    ASSERT_TRUE(RunScript(__s));                                                                   \\\n  } while (0)\n\nTEST_F(BasicTest, Smoke) {\n  ASSERT_TRUE(RunScript(\"print \\\"Hello World\\\"\"));\n\n  EXPECT_EQ(\"Hello World\", StringTrim(helper.io()->captured()));\n}\n\nTEST_F(BasicTest, Smoke_Fail) {\n  // There is no outstr( function.\n  ASSERT_FALSE(RunScript(\"outstr( \\\"Hello World\\\"\"));\n\n  EXPECT_EQ(\"\", StringTrim(helper.io()->captured()));\n}\n\nTEST_F(BasicTest, Assert_Int_False) {\n  BASIC_ASSERT_NE(1, 2);\n  ASSERT_FALSE(RunScript(\"ASSERT.EQUALS(1, 2)\"));\n}\n\nTEST_F(BasicTest, Assert_Int_True) {\n  BASIC_ASSERT_EQUALS(1, 1);\n  ASSERT_TRUE(RunScript(\"ASSERT.EQUALS(1, 1)\"));\n}\n\nTEST_F(BasicTest, Assert_String_False) {\n  BASIC_ASSERT_NE(\"\\\"hello\\\"\", \"\\\"world\\\"\");\n}\n\nTEST_F(BasicTest, Assert_String_True) {\n  BASIC_ASSERT_EQUALS(\"\\\"hello\\\"\", \"\\\"hello\\\"\");\n}\n\nTEST_F(BasicTest, Assert_Real_False) {\n  ASSERT_FALSE(RunScript(\"ASSERT.EQUALS(1.1, 1.2)\"));\n}\n\nTEST_F(BasicTest, Assert_Real_True) {\n  ASSERT_TRUE(RunScript(\"ASSERT.EQUALS(1.1, 1.1)\"));\n}\n\nTEST_F(BasicTest, Assert_DifferentTypes) {\n  ASSERT_FALSE(RunScript(R\"( ASSERT.EQUALS(\"1.1\", 1.1) )\"));\n}\n\n\nTEST_F(BasicTest, ModuleNames) {\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(\"wwiv\", wwiv.module_name()) )\"));\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(\"wwiv.io\", wwiv.io.module_name()) )\"));\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(\"wwiv.io.file\", wwiv.io.file.module_name()) )\"));\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(\"wwiv.data\", wwiv.data.module_name()) )\"));\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(\"wwiv.os\", wwiv.os.module_name()) )\"));\n}\n\nTEST_F(BasicTest, WWIV_Version) {\n  const auto script = fmt::format(R\"(ASSERT.EQUALS(\"{}\", wwiv.version()) )\",\n                                  wwiv::core::short_version());\n  EXPECT_TRUE(RunScript(script));\n}\n\nTEST_F(BasicTest, WWIV_Version_Import) {\n  const auto script = fmt::format(R\"(\nimport \"@wwiv\"\nASSERT.EQUALS(\"{}\", version())\n)\", wwiv::core::short_version());\n  EXPECT_TRUE(RunScript(script));\n}\n\nTEST_F(BasicTest, WWIV_IO_PrintFile) {\n  helper.files().CreateTempFile(\"gfiles/file1.msg\", \"this is file1\");\n  ASSERT_TRUE(RunScript(\"wwiv.io.printfile(\\\"file1.msg\\\")\"));\n\n  EXPECT_EQ(\"this is file1\\r\\n\", helper.io()->captured());\n}\n  \nTEST_F(BasicTest, WWIV_IO_PrintFile_DoesNotExist) {\n  ASSERT_TRUE(RunScript(\"wwiv.io.printfile(\\\"file1.msg\\\")\"));\n  EXPECT_EQ(\"\", helper.io()->captured());\n}\n\nTEST_F(BasicTest, WWIV_IO_Outstr) {\n  ASSERT_TRUE(RunScript(\"wwiv.io.outstr(\\\"Hello World\\\")\"));\n\n  EXPECT_EQ(\"Hello World\", helper.io()->captured());\n}\n\nTEST_F(BasicTest, WWIV_IO_Puts) {\n  ASSERT_TRUE(RunScript(\"wwiv.io.puts(\\\"Hello World\\\")\"));\n\n  EXPECT_EQ(\"Hello World\", helper.io()->captured());\n}\n\nTEST_F(BasicTest, WWIV_IO_PL) {\n  ASSERT_TRUE(RunScript(\"wwiv.io.pl(\\\"Hello World\\\")\"));\n\n  EXPECT_EQ(\"Hello World\\r\\n\", helper.io()->captured());\n}\n\nTEST_F(BasicTest, WWIV_Eval_Pass) {\n  helper.user()->sl(200);\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(wwiv.eval(\"user.sl > 100\"), TRUE) )\"));\n}\n\nTEST_F(BasicTest, WWIV_Eval_Fail) {\n  helper.user()->sl(200);\n  EXPECT_TRUE(RunScript(R\"( ASSERT.EQUALS(wwiv.eval(\"user.sl < 200\"), FALSE) )\"));\n}\n\nTEST_F(BasicTest, WWIV_IO_FILE_ReadIntoString) {\n  const std::string actual = \"this is file1\";\n  helper.files().CreateTempFile(\"gfiles/file1.msg\", actual);\n  ASSERT_TRUE(RunScript(R\"( \no = wwiv.io.file.open_options(\"GFILES\")\nh = wwiv.io.file.open(o, \"file1.msg\", \"R\")\ns = wwiv.io.file.readintostring(h)\nprint s\n)\" ));\n\n  EXPECT_EQ(StrCat(actual, \"\\r\\n\"), helper.io()->captured());\n}\n\nTEST_F(BasicTest, WWIV_IO_FILE_ReadLines) {\n  const std::string expected = \"1\\r\\n2\\r\\n3\\r\\n\";\n  helper.files().CreateTempFile(\"gfiles/file1.msg\", expected);\n  ASSERT_TRUE(RunScript(R\"(\n\ndef PrintList(l)\n  i = iterator(l)\n  while move_next(i)\n    print get(i)\n  wend\nenddef\n\nlines = list()\no = wwiv.io.file.open_options(\"GFILES\")\nh = wwiv.io.file.open(o, \"file1.msg\", \"R\")\nwwiv.io.file.readlines(h, lines)\nPrintList (lines)\n\n)\" ));\n  const auto e = SplitString(expected, \"\\r\\n\", true);\n  ASSERT_EQ(3, wwiv::stl::ssize(e));\n\n  const auto actual = SplitString(helper.io()->captured(), \"\\r\\n\", true);\n  EXPECT_THAT(actual, testing::ElementsAre(\"1\", \"2\", \"3\"));\n}\n"
  },
  {
    "path": "bbs/basic/debug_model.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"bbs/basic/debug_model.h\"\n#include \"bbs/basic/util.h\"\n#include <nlohmann/json.hpp>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::bbs::basic {\n\n\n// Variable\n\nvoid to_json(nlohmann::json& j, const Variable& v) {\n  j = nlohmann::json{ \n    {\"name\", v.name}, \n    {\"type\", v.type}, \n    {\"value\", v.value},\n    {\"frame\", v.frame}\n  };\n}\n\nvoid from_json(const nlohmann::json& j, Variable& v) {\n  j.at(\"name\").get_to(v.name);\n  j.at(\"type\").get_to(v.type);\n  j.at(\"value\").get_to(v.value);\n  j.at(\"frame\").get_to(v.frame);\n}\n\n\n// DebugLocation\n\nvoid to_json(nlohmann::json& j, const DebugLocation& v) {\n  j = nlohmann::json{ \n    {\"module\", v.module}, \n    {\"pos\", v.pos},\n    {\"row\", v.row},\n    {\"col\", v.col}\n  };\n}\n\nvoid from_json(const nlohmann::json& j, DebugLocation& v) {\n  j.at(\"module\").get_to(v.module);\n  j.at(\"pos\").get_to(v.pos);\n  j.at(\"row\").get_to(v.row);\n  j.at(\"col\").get_to(v.col);\n}\n\n\n// Breakpoint\n\n// map TaskState values to JSON as strings\nNLOHMANN_JSON_SERIALIZE_ENUM(Breakpoint::Type, {\n    {Breakpoint::Type::line, \"line\"},\n    {Breakpoint::Type::function, \"function\"},\n    {Breakpoint::Type::step, \"step\"},\n  })\n\nvoid to_json(nlohmann::json& j, const Breakpoint& v) {\n  j = nlohmann::json{\n    {\"module\", v.module},\n    {\"id\", v.id},\n    {\"typ\", v.typ},\n    {\"line\", v.line},\n    {\"function_name\", v.function_name},\n    {\"hit_count\", v.hit_count}\n  };\n}\n\nvoid from_json(const nlohmann::json& j, Breakpoint& v) {\n  j.at(\"module\").get_to(v.module);\n  j.at(\"line\").get_to(v.line);\n  j.at(\"id\").get_to(v.id);\n  j.at(\"typ\").get_to(v.typ);\n  j.at(\"function_name\").get_to(v.function_name);\n  j.at(\"hit_count\").get_to(v.hit_count);\n}\n\n}\n\n"
  },
  {
    "path": "bbs/basic/debug_model.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2023, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_DEBUG_MODEL_H\n#define INCLUDED_BBS_BASIC_DEBUG_MODEL_H\n\n#include <nlohmann/json_fwd.hpp>\n#include <map>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n#include <vector>\n\nnamespace wwiv::bbs::basic {\n\nstruct Variable {\n  std::string name;\n  std::string type;\n  std::string value;\n  int frame{ 0 };\n};\nvoid to_json(nlohmann::json& j, const Variable& p);\nvoid from_json(const nlohmann::json& j, Variable& p);\n\nstruct Breakpoint {\n  // Line breakpoints break at a specific line.\n  // function breakpoints stop when the function name in the callstack first happens\n  // step breakpoints will stop on the next time the callstack_depth is the same or less\n  // than when created and also will auto_delete.\n  enum class Type { line, function, step} ;\n  int id{ 0 };\n  Type typ{ Type::line };\n  std::string module;\n  std::string function_name;\n  int callstack_depth{ -1 };\n  int line{ 0 };\n  bool auto_delete{ false };\n  bool visible{ true };\n  int hit_count{ 0 };\n};\n\nvoid to_json(nlohmann::json& j, const Breakpoint& p);\nvoid from_json(const nlohmann::json& j, Breakpoint& p);\n\nstruct DebugLocation {\n  std::string module;\n  int pos;\n  int row;\n  int col;\n};\nvoid to_json(nlohmann::json& j, const DebugLocation& v);\nvoid from_json(const nlohmann::json& j, DebugLocation& v);\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/basic/debug_state.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"bbs/basic/debug_state.h\"\n\n#include \"core/strings.h\"\n#include \"bbs/basic/util.h\"\n#include <nlohmann/json.hpp>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n#include <mutex>\n#include <vector>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::basic {\n\n// Breakpoints\nvoid Breakpoints::clear() {\n  breakpoints_.clear();\n}\n\nstd::optional<Breakpoint> Breakpoints::add(const std::string& module, int line) {\n  Breakpoint b{};\n  b.id = ++id_;\n  b.module = wwiv::strings::ToStringUpperCase(module);\n  b.line = line;\n  breakpoints_.push_back(b);\n  return { b };\n}\n\nvoid Breakpoints::step(int depth) {\n  Breakpoint b{};\n  b.id = ++id_;\n  b.typ = Breakpoint::Type::step;\n  b.auto_delete = false;\n  b.visible = false;\n  b.callstack_depth = depth;\n  breakpoints_.emplace_back(b);\n}\n\nbool Breakpoints::removeAllAtLine(const std::string& module, int line) {\n  bool any_removed{ false };\n  for (auto it = std::begin(breakpoints_); it != std::end(breakpoints_); ++it) {\n    if (it->line == line && wwiv::strings::iequals(it->module, module)) {\n      it = breakpoints_.erase(it);\n    }\n  }\n  return any_removed;\n}\n\nbool Breakpoints::remove(int id) {\n  for (auto it = std::begin(breakpoints_); it != std::end(breakpoints_); ++it) {\n    if (it->id == id) {\n      it = breakpoints_.erase(it);\n      return true;\n    }\n  }\n  return false;\n}\n\nstd::vector<Breakpoint> Breakpoints::visible() const {\n  std::vector<Breakpoint> result;\n  std::copy_if(breakpoints_.begin(), breakpoints_.end(), std::back_inserter(result), \n    [](const Breakpoint& b) {return b.visible; });\n  return result;\n}\n\n\nbool DebugState::breakpoint_hit(int line) {\n  auto& bs = breakpoints_.all();\n  for (auto it = std::begin(bs); it != std::end(bs); ++it) {\n    if (wwiv::strings::iequals(it->module, current_module_) && \n        it->line == line && \n        it->typ == Breakpoint::Type::line) {\n      it->hit_count++;\n      if (it->auto_delete) {\n        breakpoints_.all().erase(it);\n      }\n      return true;\n    } else if (it->typ == Breakpoint::Type::step && num_stack_frames_ <= it->callstack_depth) {\n      // we're at the same level or lower, remove the breakpoint.\n      breakpoints_.all().erase(it);\n      return true;\n    }\n    // todo: implement function breakpoints here.\n  }\n  return false;\n}\n\n// DebugState\n\nvoid DebugState::SetCallStackFrames(char** f, int fc) {\n  std::lock_guard lock(mu_);\n  frames_.clear();\n  for (int i = 0; i < fc && f[i] != nullptr; i++) {\n    frames_.emplace_back(f[i]);\n  }\n  if (!frames_.empty()) {\n    // The root module has no stack frame.\n    current_function_ = frames_.front();\n  }\n}\n\nstd::vector<std::string> DebugState::stack_frames() const {\n  std::lock_guard lock(mu_);\n  return frames_;\n}\n\nvoid DebugState::SetLocation(int pos, int row, int col) {\n  std::lock_guard lock(mu_);\n  location_.module = current_module_;\n  location_.pos = pos;\n  location_.row = row;\n  location_.col = col;\n}\n\nDebugLocation DebugState::location() const {\n  std::lock_guard lock(mu_);\n  return location_;\n}\n\nBreakpoints& DebugState::breakpoints() {\n  std::lock_guard lock(mu_);\n  return breakpoints_;\n}\n\nvoid DebugState::SetRunningState(RunningState state) {\n  std::lock_guard lock(mu_);\n  running_state_ = state;\n}\n\nRunningState DebugState::running_state() const {\n  std::lock_guard lock(mu_);\n  return running_state_;\n}\n\nvoid DebugState::SetCurrentModuleName(const std::string& module) {\n  std::lock_guard lock(mu_);\n  current_module_ = ToStringUpperCase(module);\n}\n\nvoid DebugState::SetInitialModule(const std::string& module, const std::string& text) {\n  const auto m = ToStringUpperCase(module);\n  std::lock_guard lock(mu_);\n  initial_module_ = m;\n  current_module_ = m;\n  source_map_[m] = text;\n}\n\nvoid DebugState::AddSourceModule(const std::string& module, const std::string& text) {\n  const auto m = ToStringUpperCase(module);\n  std::lock_guard lock(mu_);\n  source_map_[m] = text;\n}\n\nstd::string DebugState::current_module_name() const {\n  std::lock_guard lock(mu_);\n  return current_module_.empty() ? initial_module_ : current_module_;\n}\n\nstd::optional<std::string> DebugState::module_source(const std::string& module) const {\n  const auto m = ToStringUpperCase(module);\n  std::lock_guard lock(mu_);\n  if (auto it = source_map_.find(m); it != source_map_.end()) {\n    return it->second;\n  }\n  return std::nullopt;\n}\n\nstd::string DebugState::to_string() const {\n  std::lock_guard lock(mu_);\n  return fmt::format(\"{} {} {} {}\\n\", location_.module, location_.pos, location_.row, location_.col);\n}\n\nstd::string DebugState::to_json() const {\n  std::lock_guard lock(mu_);\n  nlohmann::json j;\n  j[\"version\"] = \"0.0\";\n  j[\"location\"] = location_;\n  j[\"breakpoints\"] = breakpoints_.all();\n  j[\"vars\"] = vars_;\n  j[\"stack\"] = frames_;\n  // Current module\n  j[\"initial_module\"] = initial_module_;\n  return j.dump(4);\n}\n\n\nvoid DebugState::clear_vars() {\n  std::lock_guard lock(mu_);\n  vars_.clear();\n}\n\nvoid DebugState::set_ast(void** a) {\n  std::lock_guard lock(mu_);\n  ast_ = a;\n}\n\nvoid** DebugState::ast() {\n  std::lock_guard lock(mu_);\n  return ast_;\n}\n\nstd::vector<Variable> DebugState::vars() const {\n  std::lock_guard lock(mu_);\n  return vars_;\n}\n\nvoid DebugState::add_var(const Variable& v) {\n  std::lock_guard lock(mu_);\n  vars_.push_back(v);\n}\n\n\n}\n\n"
  },
  {
    "path": "bbs/basic/debug_state.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2023, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_DEBUG_STATE_H\n#define INCLUDED_BBS_BASIC_DEBUG_STATE_H\n\n#include \"bbs/basic/debug_model.h\"\n#include <nlohmann/json_fwd.hpp>\n#include <map>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n#include <vector>\n\n\nnamespace wwiv::bbs::basic {\n\nclass Breakpoints {\npublic:\n  void clear();\n  std::optional<Breakpoint> add(const std::string& module, int line);\n  void step(int callstack_depth);\n  bool remove(int id);\n  bool removeAllAtLine(const std::string& module, int line);\n  std::vector<Breakpoint>& all() { return breakpoints_; }\n  const std::vector<Breakpoint>& all() const { return breakpoints_; }\n  std::vector<Breakpoint> visible() const;\n\n\nprivate:\n  std::vector<Breakpoint> breakpoints_;\n  int id_{0};\n};\n\nenum class RunningState { \n  // Running, don't interrupt until a breakpoint is hit\n  RUNNING, \n  // Will take one step\n  STEPPING, \n  // Will take one step at the same stack frame\n  STEPPING_OVER,\n  // Stopped after a break or step\n  STOPPED, \n  // Trying to HALT\n  HALTING, \n  // Done halting\n  HALTED, \n  // Who knows.\n  UNKNOWN \n};\n\nclass DebugState {\npublic:\n  void SetCallStackFrames(char** frames, int fc);\n  std::vector<std::string> stack_frames() const;\n\n  void SetLocation(int pos, int row, int col);\n  DebugLocation location() const;\n\n  Breakpoints& breakpoints();\n  bool breakpoint_hit(int line);\n  void SetRunningState(RunningState state);\n  RunningState running_state() const;\n  void SetCurrentModuleName(const std::string& module);\n\n  /// Sets the initial and current module name and text\n  void SetInitialModule(const std::string& module, const std::string& text);\n  void AddSourceModule(const std::string& module, const std::string& text);\n  std::string current_module_name() const;\n  std::optional<std::string> module_source(const std::string& module) const;\n\n  // Variables\n  void clear_vars();\n  void set_ast(void** a);\n  void** ast();\n  std::vector<Variable> vars() const;\n  void add_var(const Variable& v);\n  void set_frame(int f) { frame_ = f; }\n  int frame() const { return frame_; }\n  void set_num_stack_frames(int f) { num_stack_frames_ = f; }\n  int num_stack_frames() const { return num_stack_frames_; }\n\n  // Breakpoints\n\n  std::string to_string() const;\n  std::string to_json() const;\n\nprivate:\n  mutable std::mutex mu_;\n  std::vector<std::string> frames_;\n  std::string current_function_;\n  DebugLocation location_;\n  RunningState running_state_{RunningState::UNKNOWN};\n  std::map<std::string, std::string> source_map_;\n  std::string current_module_;\n  std::string initial_module_;\n  // Vars support\n  void** ast_{ nullptr };\n  std::vector<Variable> vars_;\n  Breakpoints breakpoints_;\n  int frame_{ 0 };\n  int num_stack_frames_{ 0 };\n};\n\n\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/basic/debugger.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2023, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"httplib.h\"\n\n#include \"basic.h\"\n#include \"debugger.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <nlohmann/json.hpp>\n#include <cmath>\n#include <map>\n#include <mutex>\n#include <optional>\n#include <random>\n#include <string>\n#include <thread>\n#include <vector>\n\nusing namespace std::chrono_literals;\n\nnamespace wwiv::bbs::basic {\n\nstatic const char MIME_TYPE_JSON[] = \"application/json\";\nstatic const char MIME_TYPE_TEXT[] = \"text/plain\";\n\nbool Debugger::WaitForDebuggerToAttach() {\n  int count = 0;\n  while (true) {\n    if (attached()) {\n      return true;\n    }\n    wwiv::os::sleep_for(1s);\n    if (++count % 5 == 0) {\n    }\n    if (count > 120) {\n      return false;\n    }\n  }\n}\n\nstd::string dump_headers(const httplib::Headers& headers) {\n  std::string s;\n  char buf[BUFSIZ];\n\n  for (auto it = headers.begin(); it != headers.end(); ++it) {\n    const auto& x = *it;\n    snprintf(buf, sizeof(buf), \"%s: %s\\n\", x.first.c_str(), x.second.c_str());\n    s += buf;\n  }\n\n  return s;\n}\n\nstatic std::string log(const httplib::Request& req, const httplib::Response& res) {\n  std::string s;\n\n  s += \"================================\\n\";\n  s += fmt::format(\"{} {} {}\", req.method, req.version, req.path);\n\n  for (auto it = req.params.begin(); it != req.params.end(); ++it) {\n    s += fmt::format(\"{:c}{}={}\", (it == req.params.begin()) ? '?' : '&', it->first,\n      it->second);\n  }\n  s += \"\\n\";\n  s += dump_headers(req.headers);\n  s += \"--------------------------------\\n\";\n\n  s += fmt::format(\"{} {}\\n\", res.status, res.version);\n  s += dump_headers(res.headers);\n  s += \"\\n\";\n\n  if (!res.body.empty()) {\n    s += res.body;\n  }\n\n  s += \"\\n\";\n  return s;\n}\n\n// Having this here in a c++ file means we can delete basic without knowing\n// the complete types of httplib in basic.h\nDebugger ::~Debugger() {\n  // Stop the server then join the thread to wait for it to exit.\n  if (svr_) {\n    svr_->stop();\n    srv_thread_.join();\n  }\n}\n\nDebugState& Debugger::current_debug_state() {\n  std::lock_guard lock(mu_);\n  return debug_state_;\n}\n\nbool Debugger::attached() const {\n  std::lock_guard lock(mu_);\n  return attached_;\n}\n\nbool Debugger::StartServers(int port) {\n  using namespace std::placeholders;\n  svr_ = std::make_unique<httplib::Server>();\n\n  svr_->Get(\"/debug/status\", std::bind(&Debugger::status, this, _1, _2));\n\n  // std::bind gives 'error C2668: 'httplib::Server::Post': ambiguous call to overloaded function'\n  // here\n  svr_->Post(\"/debug/v1/attach\",\n             [this](const httplib::Request& req, httplib::Response& res) { Attach(req, res); });\n  svr_->Post(\"/debug/v1/detach\",\n             [this](const httplib::Request& req, httplib::Response& res) { Detach(req, res); });\n\n  svr_->Delete(R\"(/debug/v1/breakpoint/(\\d+))\",\n    [this](const httplib::Request& req, httplib::Response& res) { DeleteBreakpoint(req, res); });\n  svr_->Post(\"/debug/v1/breakpoint\",\n    [this](const httplib::Request& req, httplib::Response& res) { CreateBreakpoint(req, res); });\n  svr_->Post(\"/debug/v1/stepover\",\n             [this](const httplib::Request& req, httplib::Response& res) { stepover(req, res); });\n  svr_->Post(\"/debug/v1/tracein\",\n             [this](const httplib::Request& req, httplib::Response& res) { tracein(req, res); });\n  svr_->Post(\"/debug/v1/run\",\n             [this](const httplib::Request& req, httplib::Response& res) { run(req, res); });\n  svr_->Post(\"/debug/v1/stop\",\n             [this](const httplib::Request& req, httplib::Response& res) { stop(req, res); });\n\n  svr_->Get(\"/debug/v1/source\", std::bind(&Debugger::source, this, _1, _2));\n  svr_->Get(\"/debug/v1/state\", std::bind(&Debugger::state, this, _1, _2));\n  svr_->Get(\"/debug/v1/watch\", std::bind(&Debugger::watch, this, _1, _2));\n\n  svr_->set_logger([](const httplib::Request& req, const httplib::Response& res) {\n    VLOG(1) << log(req, res);\n  });\n  srv_thread_ = std::thread(\n      [&](int p) {\n        svr_->listen(\"0.0.0.0\", p);\n        attached_ = false;\n        session_id_.clear();\n      },\n      port);\n  return true;\n}\n\nstatic std::string create_debug_session_id() {\n  std::random_device rd;\n  std::mt19937_64 e2(rd());\n  std::uniform_int_distribution<long long int> dist(std::llround(std::pow(2, 61)), std::llround(std::pow(2, 62)));\n\n  const auto result = dist(e2);\n  return std::to_string(result);\n}\n\nvoid Debugger::Attach(const httplib::Request&, httplib::Response& res) {\n  if (attached()) {\n    res.status = 400;\n    res.set_content(\"Already attached\", MIME_TYPE_TEXT);\n    return;\n  }\n  nlohmann::json j; \n  j[\"attached\"] = true;\n  session_id_ = create_debug_session_id();\n  j[\"session_id\"] = session_id_;\n  j[\"initial_module\"] = current_debug_state().current_module_name();\n  res.set_content(j.dump(4), \"application/json\");\n\n  std::lock_guard lock(mu_);\n  attached_ = true;\n}\n\nvoid Debugger::Detach(const httplib::Request&, httplib::Response& res) {\n  if (!attached()) {\n    res.status = 400;\n    res.set_content(\"Not Attached\", MIME_TYPE_TEXT);\n    return;\n  }\n  res.set_content(\"detached\", MIME_TYPE_TEXT);\n  std::lock_guard lock(mu_);\n  attached_ = false;\n  session_id_.clear();\n  // restore back to the running state.\n  debug_state_.SetRunningState(RunningState::RUNNING);\n}\n\n// Post to create a breakpoint\nvoid Debugger::CreateBreakpoint(const httplib::Request& req, httplib::Response& res) {\n  if (!attached()) {\n    res.status = 400;\n    res.set_content(\"Not Attached\", MIME_TYPE_TEXT);\n    return;\n  }\n\n  // res.set_content(\"detached\", MIME_TYPE_TEXT);\n  int line = -1;\n  if (req.has_param(\"line\")) {\n    line = wwiv::strings::to_number<int>(req.get_param_value(\"line\"));\n    // TODO(rushfan): Need module here too.\n  } else {\n    res.status = 400;\n    res.set_content(\"missing line number\", MIME_TYPE_TEXT);\n    return;\n  }\n\n  std::string module = this->debug_state_.current_module_name();\n  if (req.has_param(\"module\")) {\n    module = req.get_param_value(\"module\");\n  }\n\n  if (req.has_param(\"typ\")) {\n    auto typ = req.get_param_value(\"module\");\n    if (typ != \"line\") {\n      res.status = 400;\n      res.set_content(\"only line breakpoints are supported\", MIME_TYPE_TEXT);\n    }\n  }\n\n  std::lock_guard lock(mu_);\n  if (auto ob = debug_state_.breakpoints().add(module, line)) {\n    res.status = 200;\n    nlohmann::json j;\n    j = ob.value();\n    res.set_content(j.dump(4), \"application/json\");\n    return;\n  }\n\n  res.status = 400;\n  res.set_content(\"Adding breakpoint failed\", MIME_TYPE_TEXT);\n}\n\nvoid Debugger::DeleteBreakpoint(const httplib::Request& req, httplib::Response& res) {\n  if (!attached()) {\n    res.status = 400;\n    res.set_content(\"Not Attached\", MIME_TYPE_TEXT);\n    return;\n  }\n\n  const auto id = wwiv::strings::to_number<int>(req.matches[1]);\n\n  {\n    std::lock_guard lock(mu_);\n    debug_state_.breakpoints().remove(id);\n  }\n\n  res.status = 200;\n  res.set_content(\"breakpoint deleted\", MIME_TYPE_TEXT);\n}\nvoid Debugger::state(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  res.set_content(debug_state_.to_json(), MIME_TYPE_JSON);\n}\n\nvoid Debugger::stepover(const httplib::Request&, httplib::Response& res) {\n\n  {\n    std::lock_guard lock(mu_);\n    // realistically this should set a breakpoint on next line then run\n    debug_state_.SetRunningState(RunningState::STEPPING_OVER);\n  }\n\n  // try to let the next step happen before we get the location.\n  const auto last_step = step_count().load();\n  wwiv::os::sleep_for(15ms);\n  auto start = std::chrono::steady_clock::now();\n  while (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start).count() < 5) {\n    const auto current_step = step_count().load();\n    wwiv::os::sleep_for(10ms);\n    if (current_step > last_step) {\n      break;\n    }\n  }\n  res.set_content(debug_state_.to_json(), MIME_TYPE_JSON);\n}\n\nvoid Debugger::run(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  res.set_content(debug_state_.to_json(), MIME_TYPE_JSON);\n  debug_state_.SetRunningState(RunningState::RUNNING);\n}\n\nvoid Debugger::stop(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  // Grab snapshot before stopping\n  res.set_content(debug_state_.to_json(), MIME_TYPE_JSON);\n  debug_state_.SetRunningState(RunningState::HALTING);\n}\n\nvoid Debugger::tracein(const httplib::Request&, httplib::Response& res) { \n  std::lock_guard lock(mu_);\n  debug_state_.SetRunningState(RunningState::STEPPING);\n\n  res.set_content(debug_state_.to_json(), MIME_TYPE_JSON);\n}\n\nvoid Debugger::source(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  const auto source = debug_state_.module_source(debug_state_.current_module_name()).value_or(\"\");\n  res.set_content(source, MIME_TYPE_TEXT);\n}\n\nvoid Debugger::status(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  res.set_content(\"ok\", MIME_TYPE_TEXT);\n}\n\nvoid Debugger::watch(const httplib::Request&, httplib::Response& res) {\n  std::lock_guard lock(mu_);\n  nlohmann::json j = debug_state_.vars();\n  res.set_content(j.dump(4), MIME_TYPE_JSON);\n}\n\n// Handlers for my_basic\n\n\nstatic std::string to_string(struct mb_interpreter_t* bas, void** ast, mb_value_t v) {\n  switch (v.type) {\n  case MB_DT_INT:\n    return std::to_string(v.value.integer);\n  case MB_DT_REAL:\n    return std::to_string(v.value.float_point);\n  case MB_DT_STRING:\n    if (v.value.string != nullptr) {\n      return v.value.string;\n    }\n    return {};\n    break;\n  case MB_DT_LIST: {\n    int count = 0;\n    if (mb_count_coll(bas, ast, v, &count) != MB_FUNC_OK) {\n      return {};\n    }\n    std::string result;\n    for (auto i = 0; i < count; i++) {\n      mb_value_t idx;\n      mb_make_int(idx, i);\n      mb_value_t val{};\n      if (mb_get_coll(bas, ast, v, idx, &val) == MB_FUNC_OK) {\n        if (!result.empty()) {\n          result += \", \";\n        }\n        result.append(to_string(bas, ast, val));\n      }\n    }\n    return fmt::format(\"[{}]\", result);\n  } break;\n  default:\n    return fmt::format(\"$$$ UNKNOWN VALUE FROM TYPE: {}$$\", static_cast<int>(v.type));\n  }\n}\n\nstatic void var_collector(struct mb_interpreter_t* bas, const char* n, mb_value_t v) {\n  const auto* data = get_wwiv_script_userdata(bas);\n  if (!data->basic->debugger_attached()) {\n    return;\n  }\n  auto& debug_state = data->basic->debugger()->current_debug_state();\n  Variable var;\n  var.name = (n != nullptr) ? n : \"\";\n  var.type = mb_get_type_string(v.type);\n  var.frame = debug_state.frame();\n  auto** ast = debug_state.ast();\n  var.value = to_string(bas, ast, v);\n  debug_state.add_var(var);\n}\n\nint _on_prev_stepped(struct mb_interpreter_t* bas, void** ast, const char* src, int pos,\n  uint16_t row, uint16_t col) {\n  LOG(INFO) << \"on_prev_stepped [enter]: row: \" << row << \"; pos: \" << pos;\n\n  const auto* data = get_wwiv_script_userdata(bas);\n  if (!data->basic->debugger_attached()) {\n    return MB_FUNC_OK;\n  }\n  auto& debug_state = data->basic->debugger()->current_debug_state();\n  if (src) {\n    debug_state.SetCurrentModuleName(src);\n  }\n\n  // Update State\n  debug_state.set_num_stack_frames(mb_debug_count_stack_frames(bas));\n  char* frames[16];\n  memset(frames, 0, sizeof(frames));\n  const auto mfc = std::min<int>(debug_state.num_stack_frames(), 16);\n  mb_debug_get_stack_trace(bas, frames, mfc);\n  debug_state.SetCallStackFrames(frames, mfc);\n  debug_state.SetLocation(pos, row, col);\n\n  // Update variables\n  debug_state.clear_vars();\n  debug_state.set_ast(ast);\n  for (int i = 0; i <= debug_state.num_stack_frames(); i++) {\n    debug_state.set_frame(i);\n    mb_get_vars(bas, ast, var_collector, i);\n  }\n  LOG(INFO) << \"on_prev_stepped [state updated]: row: \" << row << \"; pos: \" << pos << \"; fc: \" << mfc;\n\n  // See what to do now\n  // TODO: Move this into running state.\n  for (;;) {\n    switch (const auto s = debug_state.running_state()) {\n    case RunningState::UNKNOWN:\n      debug_state.SetRunningState(RunningState::STOPPED);\n      break;\n    case RunningState::HALTING:\n      debug_state.SetRunningState(RunningState::HALTED);\n      return MB_FUNC_OK;\n    case RunningState::HALTED:\n      return MB_FUNC_BYE;\n    case RunningState::RUNNING:\n      // Check for breakpoints.\n      if (debug_state.breakpoint_hit(row)) {\n        data->basic->debugger()->step_count()++;\n        LOG(INFO) << \"on_prev_stepped [breakpoint hit]: row: \" << row;\n        debug_state.SetRunningState(RunningState::STOPPED);\n        continue;\n      }\n      return MB_FUNC_OK;\n    // Step In\n    case RunningState::STEPPING:\n      data->basic->debugger()->step_count()++;\n      debug_state.SetRunningState(RunningState::STOPPED);\n      return MB_FUNC_OK;\n    case RunningState::STEPPING_OVER: {\n      // Add a step breakpoint and run.\n      const auto fc = debug_state.num_stack_frames();\n      debug_state.breakpoints().step(fc);\n      debug_state.SetRunningState(RunningState::RUNNING);\n      LOG(INFO) << \"Adding STEP breakpoint: row: \" << row << \"; fc: \" << fc;\n      return MB_FUNC_OK;\n    } \n    case RunningState::STOPPED:\n      // Add way to bail\n      if (data->in->bkbhit()) {\n        if (data->in->bgetchraw() == 0x03) {\n          data->out->pl(\"Exiting debugger...\");\n          return MB_FUNC_BYE;\n        }\n      }\n      wwiv::os::sleep_for(10ms);\n      break;\n    default:\n      break;\n    }\n  }\n}\n\nint _on_post_stepped(struct mb_interpreter_t* bas, void** ast, const char* source_file,\n  int pos, uint16_t row, uint16_t col) {\n  mb_unrefvar(bas);\n  mb_unrefvar(ast);\n  mb_unrefvar(source_file);\n  mb_unrefvar(pos);\n  mb_unrefvar(row);\n  mb_unrefvar(col);\n\n  return MB_FUNC_OK;\n}\n\n} // namespace wwiv::bbs::basic\n"
  },
  {
    "path": "bbs/basic/debugger.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2023, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_DEBUGGER_H\n#define INCLUDED_BBS_BASIC_DEBUGGER_H\n\n#include \"bbs/basic/debug_state.h\"\n#include \"bbs/basic/util.h\"\n#include <nlohmann/json_fwd.hpp>\n\n#include <atomic>\n#include <map>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <thread>\n#include <vector>\n\nnamespace httplib {\nclass Client;\nclass ContentReader;\nstruct Response;\nstruct Request;\nclass Server;\n} // namespace httplib\n\nnamespace wwiv::bbs::basic {\n\n\nclass Debugger {\npublic:\n  Debugger() = default;\n  ~Debugger();\n  DebugState& current_debug_state();\n  bool attached() const;\n\n  // Debugger Core\n  bool StartServers(int port);\n  bool WaitForDebuggerToAttach();\n\n  // step count\n  std::atomic<int>& step_count() { return step_count_; }\n\nprivate:\n  void Attach(const httplib::Request& req, httplib::Response& res);\n  void Detach(const httplib::Request& req, httplib::Response& res);\n  void CreateBreakpoint(const httplib::Request& req, httplib::Response& res);\n  void DeleteBreakpoint(const httplib::Request& req, httplib::Response& res);\n\n  // HTTP action handlers\n  void run(const httplib::Request&, httplib::Response& res);\n  void stop(const httplib::Request&, httplib::Response& res);\n  void stepover(const httplib::Request&, httplib::Response& res);\n  void tracein(const httplib::Request&, httplib::Response& res);\n\n  // HTTP Getters\n  void state(const httplib::Request&, httplib::Response& res);\n  void source(const httplib::Request&, httplib::Response& res);\n  void status(const httplib::Request&, httplib::Response& res);\n  void watch(const httplib::Request&, httplib::Response& res);\n\nprivate:\n  mutable std::mutex mu_;\n  DebugState debug_state_;\n  bool attached_{false};\n  std::thread srv_thread_;\n  std::unique_ptr<httplib::Server> svr_;\n  std::atomic<int> step_count_{ 0 };\n  std::string session_id_;\n};\n\nint _on_prev_stepped(struct mb_interpreter_t* bas, void** ast, const char* src, int pos,\n  uint16_t row, uint16_t col);\nint _on_post_stepped(struct mb_interpreter_t* bas, void** ast, const char* src, int pos,\n  uint16_t row, uint16_t col);\n\n\n} // namespace wwiv::bbs::basic\n\n#endif\n"
  },
  {
    "path": "bbs/basic/scripts/attach.cmd",
    "content": "curl http://localhost:9948/debug/v1/attach -d \"foo\" -vv"
  },
  {
    "path": "bbs/basic/scripts/bp.cmd",
    "content": "curl http://localhost:9948/debug/v1/breakpoint -d \"line=10\" -vv"
  },
  {
    "path": "bbs/basic/scripts/source.cmd",
    "content": "curl http://localhost:9948/debug/v1/source \n"
  },
  {
    "path": "bbs/basic/scripts/state.cmd",
    "content": "curl http://localhost:9948/debug/v1/state -vv\n"
  },
  {
    "path": "bbs/basic/scripts/step.cmd",
    "content": "curl -X POST http://localhost:9948/debug/v1/stepover -vv -d \"\"\n"
  },
  {
    "path": "bbs/basic/util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"bbs/basic/util.h\"\n\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/log.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include <string>\n#include <utility>\n\nnamespace wwiv::bbs::basic {\n\nclass Basic;\n\nusing namespace wwiv::common;\n\nBasicScriptState::BasicScriptState(std::filesystem::path d, std::filesystem::path s, Context* c, Input* i,\n                                   Output* o, Basic* b)\n    : datadir(d), script_dir(s), ctx(c), in(i), out(o), module(\"none\"), basic(b) {}\n\nchar* BasicStrDup(std::string_view s) { \n  return mb_memdup(s.data(), s.size() + 1);\n}\n\nint BasicScriptState::emplace_exec_options(chain_type_t c, file_location_t f, dropfile_type_t d) {\n  wwiv_exec_options_t o;\n  o.type = c;\n  o.loc = f;\n  o.dropfile = d;\n\n  const auto handle = allocate_handle();\n  exec_options.emplace(handle, o);\n  return handle;\n}\n\nBasicScriptState* get_wwiv_script_userdata(struct mb_interpreter_t* bas) {\n  void* x{};\n  const auto result = mb_get_userdata(bas, &x);\n  if (result != MB_FUNC_OK) {\n    LOG(ERROR) << \"Error getting the script userdata\";\n    return nullptr;\n  }\n  return static_cast<BasicScriptState*>(x);\n}\n\nint mb_empty_function(mb_interpreter_t* s, void** l) {\n  mb_check(mb_attempt_open_bracket(s, l));\n  mb_check(mb_attempt_close_bracket(s, l));\n  return MB_FUNC_OK;\n}\n\nmb_value_t wwiv_mb_make_string(const std::string_view s) {\n  mb_value_t t;\n  mb_make_string(t, BasicStrDup(s));\n  return t;\n}\n\nmb_value_t wwiv_mb_make_int(int i) {\n  mb_value_t t;\n  mb_make_int(t, i);\n  return t;\n}\n\nmb_value_t wwiv_mb_make_real(float f) {\n  mb_value_t t;\n  mb_make_real(t, f);\n  return t;\n}\n\nstd::optional<mb_value_t> wwiv_mb_pop_value(mb_interpreter_t* bas, void** l) {\n  mb_value_t arg;\n  mb_make_nil(arg);\n  if (mb_pop_value(bas, l, &arg) != MB_FUNC_OK) {\n    return std::nullopt;\n  }\n  return {arg};\n}\n\nstd::optional<mb_value_t> wwiv_mb_pop_usertype(mb_interpreter_t* bas, void** l) {\n  mb_value_t arg;\n  mb_make_nil(arg);\n  if (mb_pop_value(bas, l, &arg) != MB_FUNC_OK) {\n    return std::nullopt;\n  }\n  if (arg.type != MB_DT_USERTYPE) {\n    return std::nullopt;\n  }\n\n  return {arg};\n}\n\nstd::optional<std::string> wwiv_mb_pop_string(mb_interpreter_t* bas, void** l) {\n  auto o = wwiv_mb_pop_value(bas, l);\n  if (!o) {\n    return std::nullopt;\n  }\n  if (o.value().type != MB_DT_STRING) {\n    return std::nullopt;\n  }\n  return { o.value().value.string };\n}\n\nstd::optional<int> wwiv_mb_pop_int(mb_interpreter_t* bas, void** l) {\n  auto o = wwiv_mb_pop_value(bas, l);\n  if (!o) {\n    return std::nullopt;\n  }\n  if (o.value().type != MB_DT_INT) {\n    return std::nullopt;\n  }\n  return { o.value().value.integer };\n}\n\nstd::optional<int> wwiv_mb_pop_handle(mb_interpreter_t* bas, void** l) {\n  mb_value_t arg;\n  mb_make_nil(arg);\n  const auto ret = mb_pop_value(bas, l, &arg);\n  if (ret != MB_FUNC_OK || arg.type != MB_DT_USERTYPE) {\n    return std::nullopt;\n  }\n  return { arg.value.integer };\n}\n\nint wwiv_mb_push_handle(mb_interpreter_t* bas, void** l, int h) {\n  mb_value_t val;\n  val.type = MB_DT_USERTYPE;\n  val.value.integer = h;\n\n  return mb_push_value(bas, l, val);\n}\n\nint wwiv_mb_push_string(mb_interpreter_t* bas, void** l, std::string_view s) {\n  const auto v = wwiv_mb_make_string(s);\n  return mb_push_value(bas, l, v);\n}\n\nfile_location_t to_file_location_t(const std::string& s) {\n  if (strings::iequals(s, \"MENUS\")) {\n    return file_location_t::MENUS;\n  }\n  if (strings::iequals(s, \"GFILES\")) {\n    return file_location_t::GFILES;\n  }\n  if (strings::iequals(s, \"TEMP\")) {\n    return file_location_t::TEMP;\n  }\n  if (strings::iequals(s, \"BBS\")) {\n    return file_location_t::BBS;\n  }\n  return file_location_t::GFILES;\n}\n\ndropfile_type_t to_dropfile_type_t(const std::string& s) {\n  if (strings::iequals(s, \"DOOR.SYS\")) {\n    return dropfile_type_t::DOOR_SYS;\n  }\n  return dropfile_type_t::CHAIN_TXT;\n}\n\nchain_type_t to_chain_type_t(const std::string& s) {\n  if (strings::iequals(s, \"FOSSIL\")) {\n    return chain_type_t::FOSSIL;\n  }\n  if (strings::iequals(s, \"NETFOSS\")) {\n    return chain_type_t::NETFOSS;\n  }\n  if (strings::iequals(s, \"STDIO\")) {\n    return chain_type_t::STDIO;\n  }\n  return chain_type_t::DOOR32;\n}\n\n}\n"
  },
  {
    "path": "bbs/basic/util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_UTIL_H\n#define INCLUDED_BBS_BASIC_UTIL_H\n\n#include \"common/context.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/textfile.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n\n#include <filesystem>\n#include <memory>\n#include <string>\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nchar* BasicStrDup(std::string_view s);\nclass Basic;\n\nenum class file_location_t { GFILES, MENUS, TEMP, BBS };\nenum class chain_type_t { DOOR32, STDIO, FOSSIL, NETFOSS };\nenum class dropfile_type_t { CHAIN_TXT, DOOR_SYS };\n\nstruct wwiv_file_handle_t {\n  file_location_t loc{file_location_t::GFILES};\n  std::unique_ptr<TextFile> file;\n};\n\nstruct wwiv_exec_options_t {\n  chain_type_t type{chain_type_t::DOOR32};\n  file_location_t loc{file_location_t::TEMP};\n  dropfile_type_t dropfile{dropfile_type_t::CHAIN_TXT};\n};\n\nclass BasicScriptState {\npublic:\n  BasicScriptState(std::filesystem::path d, std::filesystem::path s, common::Context* c,\n                   common::Input* i, common::Output* o, Basic* b);\n  std::filesystem::path datadir;\n  std::filesystem::path script_dir;\n  common::Context* ctx;\n  common::Input* in;\n  common::Output* out;\n  Basic* basic;\n  std::string module;\n\n  int allocate_handle() noexcept { return ++handle_; }\n\n  int emplace_exec_options(chain_type_t, file_location_t, dropfile_type_t);\n  std::map<int, wwiv_file_handle_t> files;\n  std::map<int, wwiv_exec_options_t> exec_options;\n\nprivate:\n  int handle_{0};\n};\n\n/**\n * Gets the WWIV script \"userdata\" (BasicScriptState) that was applied at the\n * script level for the interpreter session.\n */\nBasicScriptState* get_wwiv_script_userdata(struct mb_interpreter_t* bas);\n\n/**\n * Attempts to open and close the brackets () for an empty\n * function, returning MB_FUNC_OK on success and an error\n * code on failure\n */\nint mb_empty_function(struct mb_interpreter_t* s, void** l);\n\n/**\n * Creates a mb_value_t from string s\n *\n * equivalent to:\n * mb_value_t v;\n * mb_make_string(v, BasicStrDup(s));\n */\nmb_value_t wwiv_mb_make_string(std::string_view s);\nmb_value_t wwiv_mb_make_int(int i);\nmb_value_t wwiv_mb_make_real(float f);\n\nstd::optional<mb_value_t> wwiv_mb_pop_value(struct mb_interpreter_t* bas, void** l);\nstd::optional<mb_value_t> wwiv_mb_pop_usertype(struct mb_interpreter_t* bas, void** l);\nstd::optional<std::string> wwiv_mb_pop_string(struct mb_interpreter_t* bas, void** l);\nstd::optional<int> wwiv_mb_pop_int(struct mb_interpreter_t* bas, void** l);\nstd::optional<int> wwiv_mb_pop_handle(struct mb_interpreter_t* bas, void** l);\n\n/** Pushes a WWIVbasic handle, which is a usertype wrapping an integer */\nint wwiv_mb_push_handle(struct mb_interpreter_t* bas, void** l, int h);\n/** Pushes a string onto the interpreter stack */\nint wwiv_mb_push_string(struct mb_interpreter_t* bas, void** l, std::string_view s);\n\nfile_location_t to_file_location_t(const std::string& s);\ndropfile_type_t to_dropfile_type_t(const std::string& s);\nchain_type_t to_chain_type_t(const std::string& s);\n\n#define MB_FUNC_ERR_IF_ABSENT(o) do { if (!o) return MB_FUNC_ERR; } while (0)\n#define MB_FUNC_ERR_IF_ABSENT_MSG(o, msg) do { if (!o) { LOG(ERROR) << msg; return MB_FUNC_ERR; } } while (0)\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/util_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/basic/util.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"core/stl.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n\nusing namespace wwiv::stl;\nusing namespace wwiv::bbs::basic;\n\nTEST(BasicUtilTest, MakeString) {\n  const auto s = wwiv_mb_make_string(\"Hello\");\n  EXPECT_STREQ(\"Hello\", s.value.string);\n}\n\nTEST(BasicUtilTest, MakeInt) {\n  const auto s = wwiv_mb_make_int(1234);\n  EXPECT_EQ(1234, s.value.integer);\n}\n\nTEST(BasicUtilTest, MakeReal) {\n  const auto s = wwiv_mb_make_real(1234);\n  EXPECT_FLOAT_EQ(1234.0, s.value.float_point);\n}\n"
  },
  {
    "path": "bbs/basic/wwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/interpret.h\"\n#include \"bbs/basic/util.h\"\n#include \"bbs/menus/menucommands.h\"\n#include \"common/pipe_expr.h\"\n#include \"core/version.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n\n#include <string>\n\nnamespace wwiv::bbs::basic {\n\nstatic int _version(struct mb_interpreter_t* bas, void** l) {\n  mb_check(mb_empty_function(bas, l));\n  mb_push_string(bas, l, BasicStrDup(wwiv::core::short_version()));\n  return MB_FUNC_OK;\n}\n\nbool RegisterNamespaceWWIV(mb_interpreter_t* basi) {\n  mb_begin_module(basi, \"WWIV\");\n  mb_register_func(basi, \"VERSION\", _version);\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_empty_function(bas, l));\n    sd->out->outstr(\"wwiv\\r\\n\");\n    mb_check(mb_push_string(bas, l, BasicStrDup(\"wwiv\")));\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"COMMAND\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    auto cmd = wwiv_mb_pop_string(bas, l);\n    if (!cmd) {\n      // command missing\n      return MB_FUNC_ERR;\n    }\n    std::string data;\n    if (mb_has_arg(bas, l)) {\n      if (const auto o =  wwiv_mb_pop_string(bas, l)) {\n        data = o.value();\n      }\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n\n    menus::interpret_command(nullptr, cmd.value(), data);\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"EVAL\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    char* arg = nullptr;\n    if (mb_has_arg(bas, l)) {\n      mb_check(mb_pop_string(bas, l, &arg));\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    if (arg) {\n      const auto ret = check_acs(arg);\n      mb_push_int(bas, l, ret ? 1 : 0);\n    } else {\n      mb_push_int(bas, l, 0);\n    }\n    return MB_FUNC_OK;\n  });\n\n  // Crappy, awful API way to get data out of WWIVs' macros.\n  mb_register_func(basi, \"INTERPRET\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    if (!mb_has_arg(bas, l)) {\n      return MB_FUNC_ERR;\n    }\n    char* arg = nullptr;\n    mb_check(mb_pop_string(bas, l, &arg));\n\n    auto* d = get_wwiv_script_userdata(bas);\n    common::PipeEval pipe_eval(*d->ctx);\n    const BbsMacroContext ctx(d->ctx, pipe_eval);\n    const auto s = ctx.interpret_macro_char(*arg);\n    mb_check(mb_attempt_close_bracket(bas, l));\n    mb_push_string(bas, l, BasicStrDup(s));\n    return MB_FUNC_OK;\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n\n}\n"
  },
  {
    "path": "bbs/basic/wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_H\n#define INCLUDED_BBS_BASIC_WWIV_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\n  \nbool RegisterNamespaceWWIV(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/wwiv_data.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv_data.h\"\n\n#include \"deps/my_basic/core/my_basic.h\"\n#include \"bbs/basic/util.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/cereal_utils.h\"\n#include \"fmt/format.h\"\n#include <cassert>\n#include <optional>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::basic {\n\nenum class script_data_type_t { STRING, INT, REAL };\n\nstruct script_data_t {\n  script_data_type_t type;\n  std::string s;\n  int i{};\n  float r{};\n};\n\ntemplate <class Archive> void serialize(Archive& ar, script_data_t& t) {\n  SERIALIZE(t, type);\n  if (t.type == script_data_type_t::INT) {\n    SERIALIZE(t, i);\n  } else if (t.type == script_data_type_t::REAL) {\n    SERIALIZE(t, r);\n  } else if (t.type == script_data_type_t::STRING) {\n    SERIALIZE(t, s);\n  }\n}\n\nstatic mb_value_t to_mb_value(const script_data_t& f) {\n  switch (f.type) {\n  case script_data_type_t::INT:\n    return wwiv_mb_make_int(f.i);\n  case script_data_type_t::REAL:\n    return wwiv_mb_make_real(f.r);\n  case script_data_type_t::STRING:\n    return wwiv_mb_make_string(f.s);\n  }\n  DLOG(FATAL) << \"Should not happen\";\n  return {};\n}\n\nstatic script_data_t to_script_data(const mb_value_t& v) {\n  script_data_t result{};\n  switch (v.type) {\n  case MB_DT_INT:\n    result.type = script_data_type_t::INT;\n    result.i = v.value.integer;\n    return result;\n  case MB_DT_REAL:\n    result.type = script_data_type_t::REAL;\n    result.r = v.value.float_point;\n    return result;\n  case MB_DT_STRING:\n    result.type = script_data_type_t::STRING;\n    result.s = v.value.string;\n    return result;\n  case MB_DT_NIL:\n  case MB_DT_UNKNOWN:\n  case MB_DT_NUM:\n  case MB_DT_TYPE:\n  case MB_DT_USERTYPE:\n  case MB_DT_USERTYPE_REF:\n  case MB_DT_ARRAY:\n  case MB_DT_LIST:\n  case MB_DT_LIST_IT:\n  case MB_DT_DICT:\n  case MB_DT_DICT_IT:\n  case MB_DT_COLLECTION:\n  case MB_DT_ITERATOR:\n  case MB_DT_CLASS:\n  case MB_DT_ROUTINE:\n    LOG(ERROR) << \"Unable to convert type (unknown) for basic type: \" << v.type;\n    return {};\n  }\n  LOG(ERROR) << \"Unable to convert type (unknown) for basic type: \" << v.type;\n  return {};\n}\n\nenum class wwiv_data_scope_t { global, user };\n\nstatic std::filesystem::path DataFileName(const BasicScriptState* ud, wwiv_data_scope_t scope) {\n  const auto module_name = ToStringLowerCase(ud->module);\n  if (scope == wwiv_data_scope_t::global) {\n    return FilePath(ud->datadir, StrCat(module_name, \".script.json\"));\n  }\n  const auto fn =\n      fmt::format(\"{}.user.{}.script.json\", module_name, ud->ctx->session_context().user_num());\n  return FilePath(ud->datadir, fn);\n}\n\n\nstatic bool SaveData(const BasicScriptState* ud,\n                     wwiv_data_scope_t scope, const std::vector<script_data_t>& data) {\n  const auto path = DataFileName(ud, scope);\n  JsonFile json(path, \"data\", data);\n  return json.Save();\n}\n\nstatic std::optional<std::vector<script_data_t>> LoadData(const BasicScriptState* ud,\n                                                          wwiv_data_scope_t scope) {\n  std::vector<script_data_t> data;\n  const auto path = DataFileName(ud, scope);\n  JsonFile json(path, \"data\", data);\n  if (!json.Load()) {\n    return std::nullopt;\n  }\n  return data;\n}\n\nbool RegisterNamespaceData(mb_interpreter_t* basi) {\n  mb_begin_module(basi, \"WWIV.DATA\");\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    return mb_push_string(bas, l, BasicStrDup(\"wwiv.data\"));\n  });\n\n  mb_register_func(basi, \"SAVE\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* d = get_wwiv_script_userdata(bas);\n    mb_assert(bas && l);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    char* scope_str = nullptr;\n    auto scope{wwiv_data_scope_t::global};\n    if (mb_has_arg(bas, l)) {\n      // Scope: GLOBAL OR USER\n      mb_check(mb_pop_string(bas, l, &scope_str));\n      scope = iequals(\"USER\", scope_str) ? wwiv_data_scope_t::user : wwiv_data_scope_t::global;\n    }\n    if (mb_has_arg(bas, l)) {\n      mb_value_t arg;\n      mb_make_nil(arg);\n      mb_check(mb_pop_value(bas, l, &arg));\n      // arg should be coll.\n      if (arg.type != MB_DT_LIST) {\n        d->out->outstr(\"|#6Error: Only saving a LIST is currently supported. (not DICT)\\r\\n\");\n        return MB_FUNC_WARNING;\n      }\n      int count = 0;\n      mb_check(mb_count_coll(bas, l, arg, &count));\n      // *d->out << \" with size: \" << count;\n      std::vector<script_data_t> data;\n      for (auto i = 0; i < count; i++) {\n        mb_value_t idx;\n        mb_make_int(idx, i);\n        mb_value_t val{};\n        if (mb_get_coll(bas, l, arg, idx, &val) == MB_FUNC_OK) {\n          data.emplace_back(to_script_data(val));\n        }\n      }\n\n      if (!SaveData(d, scope, data)) {\n        d->out->outstr(\"|#6Error saving data.\\r\\n\");\n      }\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return MB_FUNC_OK;\n  });\n\n  // l = LOAD(\"GLOBAL|USER\")\n  mb_register_func(basi, \"LOAD\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_assert(bas && l);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    char* scope_str = nullptr;\n    auto scope{wwiv_data_scope_t::global};\n    if (mb_has_arg(bas, l)) {\n      // Scope: GLOBAL OR USER\n      mb_check(mb_pop_string(bas, l, &scope_str));\n      scope = iequals(\"USER\", scope_str) ? wwiv_data_scope_t::user : wwiv_data_scope_t::global;\n    }\n    if (mb_has_arg(bas, l)) {\n      mb_value_t arg;\n      mb_make_nil(arg);\n      mb_check(mb_pop_value(bas, l, &arg));\n      // arg should be coll.\n      if (arg.type != MB_DT_LIST) {\n        sd->out->outstr(\"|#6Error: Only loading a LIST is currently supported. (not DICT)\\r\\n\");\n        return MB_FUNC_WARNING;\n      }\n\n      auto current_count = 0;\n      mb_check(mb_count_coll(bas, l, arg, &current_count));\n      if (auto data = LoadData(sd, scope)) {\n        for (const auto& d : data.value()) {\n          const auto val = to_mb_value(d);\n          const auto idx = wwiv_mb_make_int(current_count++);\n          const auto ret = mb_set_coll(bas, l, arg, idx, val);\n          if (ret != MB_FUNC_OK) {\n            sd->out->outstr(\"[oops] \");\n          }\n        }\n      }\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return MB_FUNC_OK;\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n}"
  },
  {
    "path": "bbs/basic/wwiv_data.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_DATA_H\n#define INCLUDED_BBS_BASIC_WWIV_DATA_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceData(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/wwiv_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv_file.h\"\n\n#include \"bbs/basic/util.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include <string>\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVFILE(mb_interpreter_t* basi) {  \n  mb_begin_module(basi, \"WWIV.IO.FILE\");\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    return mb_push_string(bas, l, BasicStrDup(\"wwiv.io.file\"));\n  });\n\n  mb_register_func(basi, \"OPEN_OPTIONS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n\n    auto loc = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT_MSG(loc, \"OPEN_OPTIONS: Expected Location\");\n    const auto loc_enum = to_file_location_t(loc.value());\n    if (loc_enum != file_location_t::GFILES && loc_enum != file_location_t::MENUS) {\n      LOG(ERROR) << \"Invalid location specified: \" << loc.value();\n      return MB_FUNC_ERR;\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n\n    // N.B. We don't use bytes since it's easier to use integer for\n    // an integer key.\n    return wwiv_mb_push_handle(bas, l, static_cast<int>(loc_enum));\n  });\n \n  mb_register_func(basi, \"OPEN\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    auto arg = wwiv_mb_pop_usertype(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(arg);\n    auto loc = static_cast<file_location_t>(arg.value().value.integer);\n\n    auto arg_name = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(arg_name);\n\n    auto* sd = get_wwiv_script_userdata(bas);\n    const auto gfdir = sd->ctx->session_context().dirs().gfiles_directory();\n    const std::filesystem::path file_part{arg_name.value()};\n    const auto filename = file_part.filename();\n    const auto path = core::FilePath(gfdir, filename);\n\n    auto arg_mode = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(arg_name);\n    std::string mode = strings::iequals(\"W\", arg_mode.value()) ? \"wt\" : \"rt\";\n\n    const auto handle = sd->allocate_handle();\n    sd->files[handle].loc = loc;\n    sd->files[handle].file = std::make_unique<TextFile>(path, mode);\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return wwiv_mb_push_handle(bas, l, static_cast<int>(handle));\n  });\n\n  mb_register_func(basi, \"READINTOSTRING\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n\n    const auto handle = wwiv_mb_pop_handle(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(handle);\n\n    auto& f = stl::at(sd->files, handle.value());\n    mb_check(mb_attempt_close_bracket(bas, l));\n    const auto s = f.file->ReadFileIntoString();\n    mb_check(mb_push_string(bas, l, BasicStrDup(s)));\n\n    return MB_FUNC_OK;\n  });\n\n  // Read lines of a file into collection.\n  mb_register_func(basi, \"READLINES\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n\n    const auto handle = wwiv_mb_pop_handle(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(handle);\n    auto* sd = get_wwiv_script_userdata(bas);\n    auto& f = stl::at(sd->files, handle.value());\n    auto lines = f.file->ReadFileIntoVector();\n\n    mb_value_t arg;\n    mb_make_nil(arg);\n    mb_check(mb_pop_value(bas, l, &arg));\n    // arg should be coll.\n    if (arg.type != MB_DT_LIST) {\n      sd->out->outstr(\"|#6Error: Only saving a LIST is currently supported. (not DICT)\\r\\n\");\n      return MB_FUNC_WARNING;\n    }\n\n    auto current_count = 0;\n    mb_check(mb_count_coll(bas, l, arg, &current_count));\n    for (const auto& line : lines) {\n      const auto val = wwiv_mb_make_string(line);\n      const auto idx = wwiv_mb_make_int(current_count++);\n      const auto ret = mb_set_coll(bas, l, arg, idx, val);\n      if (ret != MB_FUNC_OK) {\n        sd->out->outstr(\"[oops] \");\n      }\n    }\n\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"LAST_MODIFIED\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n\n    const auto handle = wwiv_mb_pop_handle(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(handle);\n\n    auto* sd = get_wwiv_script_userdata(bas);\n    auto& f = stl::at(sd->files, handle.value());\n    const auto t = static_cast<int>(core::File::last_write_time(f.file->full_pathname()));\n    \n    mb_check(mb_attempt_close_bracket(bas, l));\n    mb_push_int(bas, l, t);\n    return MB_FUNC_OK;\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n}"
  },
  {
    "path": "bbs/basic/wwiv_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_FILE_H\n#define INCLUDED_BBS_BASIC_WWIV_FILE_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVFILE(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/wwiv_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv_io.h\"\n\n#include \"bbs/basic/util.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include <string>\n\nnamespace wwiv::bbs::basic {\n\n\nbool RegisterNamespaceWWIVIO(mb_interpreter_t* basi) {\n  mb_begin_module(basi, \"WWIV.IO\");\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    return mb_push_string(bas, l, BasicStrDup(\"wwiv.io\"));\n  });\n\n  // Replaced by OUTSTR, but left ofr compatbility\n  mb_register_func(basi, \"PUTS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    while (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->outstr(arg);\n    }\n    return mb_attempt_close_bracket(bas, l);\n  });\n\n  mb_register_func(basi, \"OUTSTR\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    while (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->outstr(arg);\n    }\n    return mb_attempt_close_bracket(bas, l);\n  });\n\n  mb_register_func(basi, \"PL\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    const auto* sd = get_wwiv_script_userdata(bas);\n    while (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->outstr(arg);\n      sd->out->nl();\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"PRINTFILE\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    if (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->printfile(arg);\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"GETS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    auto arg = 0;\n    if (mb_has_arg(bas, l)) {\n      mb_check(mb_pop_int(bas, l, &arg));\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    if (arg > 0) {\n      const auto s = bin.input_text(\"\", arg);\n      mb_push_string(bas, l, BasicStrDup(s));\n    }\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"GETKEY\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    const auto* sd = get_wwiv_script_userdata(bas);\n    const auto ch = sd->in->getkey();\n    char s[2] = {ch, 0};\n    return mb_push_string(bas, l, BasicStrDup(s));\n  });\n\n  mb_register_func(basi, \"CLS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    const auto* sd = get_wwiv_script_userdata(bas);\n    sd->out->cls();\n    return MB_FUNC_OK;\n  });\n\n  mb_register_func(basi, \"NL\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    int num_lines = 1;\n    if (mb_has_arg(bas, l)) {\n      mb_check(mb_pop_int(bas, l, &num_lines));\n    }\n    sd->out->nl(num_lines);\n    return mb_attempt_close_bracket(bas, l);\n  });\n\n  mb_register_func(basi, \"YN\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    while (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->outstr(arg);\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    const auto ret = bin.yesno();\n\n    return mb_push_int(bas, l, ret ? 1 : 0);\n  });\n\n  mb_register_func(basi, \"NY\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    const auto* sd = get_wwiv_script_userdata(bas);\n    mb_check(mb_attempt_open_bracket(bas, l));\n    while (mb_has_arg(bas, l)) {\n      char* arg = nullptr;\n      mb_check(mb_pop_string(bas, l, &arg));\n      sd->out->outstr(arg);\n    }\n    mb_check(mb_attempt_close_bracket(bas, l));\n    const auto ret = bin.noyes();\n\n    return mb_push_int(bas, l, ret ? 1 : 0);\n  });\n\n  mb_register_func(basi, \"PAUSE\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    bout.pausescr();\n    return MB_FUNC_OK;\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n}"
  },
  {
    "path": "bbs/basic/wwiv_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_IO_H\n#define INCLUDED_BBS_BASIC_WWIV_IO_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVIO(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/wwiv_os.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv_os.h\"\n\n\n#include \"bbs/execexternal.h\"\n#include \"bbs/basic/util.h\"\n#include \"core/strings.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include <string>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::basic {\n\nstatic uint32_t chain_type_to_flags(chain_type_t c, file_location_t loc) {\n  uint32_t flags = 0;\n  if (c == chain_type_t::FOSSIL) {\n    flags |= EFLAG_SYNC_FOSSIL;\n  } else if (c == chain_type_t::STDIO) {\n    flags |= EFLAG_STDIO;\n  } else if (c == chain_type_t::NETFOSS) {\n    flags |= EFLAG_NETFOSS;\n  }\n\n  if (loc != file_location_t::BBS) {\n    flags |= EFLAG_TEMP_DIR;\n  }\n  return flags;\n}\n\nbool RegisterNamespaceWWIVOS(mb_interpreter_t* basi) {\n\n  mb_begin_module(basi, \"WWIV.OS\");\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    return mb_push_string(bas, l, BasicStrDup(\"wwiv.os\"));\n  });\n\n  mb_register_func(basi, \"EXEC_OPTIONS\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    const auto arg_chaintype = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT_MSG(arg_chaintype, \"EXEC_OPTIONS: Expected DOORTYPE\");\n    const auto chain_type =  to_chain_type_t(arg_chaintype.value());\n\n    const auto arg_dir = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT_MSG(arg_dir, \"EXEC_OPTIONS: Expected dir\");\n    const auto dir = to_file_location_t(arg_dir.value());\n\n    const auto arg_dropfile = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT_MSG(arg_dropfile, \"EXEC_OPTIONS: Expected dropfile type\");\n    const auto dropfile_type = to_dropfile_type_t(arg_dropfile.value());\n\n    auto* sd = get_wwiv_script_userdata(bas);\n    const auto handle = sd->emplace_exec_options(chain_type, dir, dropfile_type);\n    mb_check(mb_attempt_close_bracket(bas, l));\n\n    return wwiv_mb_push_handle(bas, l, handle);\n  });\n\n  mb_register_func(basi, \"EXEC\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    const auto handle = wwiv_mb_pop_handle(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(handle);\n    const auto cmd = wwiv_mb_pop_string(bas, l);\n    MB_FUNC_ERR_IF_ABSENT(cmd);\n    mb_check(mb_attempt_close_bracket(bas, l));\n\n    auto* sd = get_wwiv_script_userdata(bas);\n    if (!stl::contains(sd->exec_options, handle.value())) {\n      LOG(ERROR) << \"Unable to find exec options handle: \" << handle.value();\n      return MB_FUNC_ERR;\n    }\n    const auto& opt = stl::at(sd->exec_options, handle.value());\n\n    LOG(INFO) << \"Execute Command: \" << cmd.value();\n    wwiv::bbs::CommandLine cl(cmd.value());\n    const auto ret = ExecuteExternalProgram(cl, chain_type_to_flags(opt.type, opt.loc));\n\n    return mb_push_int(bas, l, ret == 0 ? 1 : 0);\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n}"
  },
  {
    "path": "bbs/basic/wwiv_os.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_OS_H\n#define INCLUDED_BBS_BASIC_WWIV_OS_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVOS(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/basic/wwiv_time.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include  \"bbs/basic/wwiv_time.h\"\n\n#include \"bbs/basic/util.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"deps/my_basic/core/my_basic.h\"\n#include <string>\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVTIME(mb_interpreter_t* basi) {\n\n  mb_begin_module(basi, \"WWIV.TIME\");\n\n  mb_register_func(basi, \"MODULE_NAME\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_empty_function(bas, l));\n    return mb_push_string(bas, l, BasicStrDup(\"wwiv.time\"));\n  });\n\n  mb_register_func(basi, \"FORMAT\", [](struct mb_interpreter_t* bas, void** l) -> int {\n    mb_check(mb_attempt_open_bracket(bas, l));\n    char* raw_arg{nullptr};\n    int t{};\n    mb_check(mb_pop_int(bas, l, &t));\n    mb_check(mb_pop_string(bas, l, &raw_arg));\n    if (!raw_arg) {\n      LOG(WARNING) << \"FORMAT: Expected format style\";\n      return MB_FUNC_ERR;\n    }\n    const auto s = core::DateTime::from_time_t(t).to_string(raw_arg);\n    const auto ret = wwiv_mb_make_string(s);\n    mb_check(mb_attempt_close_bracket(bas, l));\n\n    return mb_push_value(bas, l, ret);\n  });\n\n  return mb_end_module(basi) == MB_FUNC_OK;\n}\n\n}"
  },
  {
    "path": "bbs/basic/wwiv_time.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BASIC_WWIV_TIME_H\n#define INCLUDED_BBS_BASIC_WWIV_TIME_H\n\nstruct mb_interpreter_t;\n\nnamespace wwiv::bbs::basic {\n\nbool RegisterNamespaceWWIVTIME(mb_interpreter_t* basi);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/batch.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// ReSharper disable CppClangTidyHicppMultiwayPathsCovered\n#include \"bbs/batch.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/dsz.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/make_abs_cmd.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/srsend.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/files.h\"\n#include <algorithm>\n#include <chrono>\n#include <iterator>\n#include <string>\n#include <utility>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// trytoul.cpp\nint try_to_ul(const std::string& file_name);\n\n// normupld.cpp\nvoid normalupload(int dn);\n\n//////////////////////////////////////////////////////////////////////////////\n// Implementation\n\n// Shows listing of files currently in batch queue(s), both upload and\n// download. Shows estimated time, by item, for files in the d/l queue.\nstatic void listbatch() {\n  bout.nl();\n  if (a()->batch().empty()) {\n    return;\n  }\n  bool abort = false;\n  bout.print(\"|#9Files - |#2{}  \", a()->batch().size());\n  if (a()->batch().numbatchdl()) {\n    bout.print(\"|#9Time - |#2{}\", ctim(a()->batch().dl_time_in_secs()));\n  }\n  bout.nl(2);\n  int current_num = 0;\n  for (const auto& b : a()->batch().entry) {\n    if (abort || a()->sess().hangup()) {\n      break;\n    }\n    std::string buffer;\n    ++current_num;\n    if (b.sending()) {\n      const auto t = ctim(b.time(a()->modem_speed_));\n      buffer = fmt::format(\"{}. (D) {}   {}  {}\", current_num, b.aligned_filename(), t,\n                           a()->dirs()[b.dir()].name);\n    } else {\n      buffer = fmt::format(\"{}. (U) {}             {}\", current_num, b.aligned_filename(),\n                           a()->dirs()[b.dir()].name);\n    }\n    bout.bpla(buffer, &abort);\n  }\n  bout.nl();\n}\n\nstatic void downloaded(const std::string& file_name, long lCharsPerSecond) {\n\n  for (auto it = begin(a()->batch().entry); it != end(a()->batch().entry); ++it) {\n    const auto& b = *it;\n    if (file_name == b.aligned_filename() && b.sending()) {\n      dliscan1(b.dir());\n      auto* area = a()->current_file_area();\n      auto nRecNum = recno(b.aligned_filename());\n      if (nRecNum > 0) {\n        auto f = area->ReadFile(nRecNum);\n        a()->user()->increment_downloaded();\n        a()->user()->set_dk(a()->user()->dk() + bytes_to_k(f.numbytes()));\n        ++f.u().numdloads;\n        if (area->UpdateFile(f, nRecNum)) {\n          area->Save();\n        }\n        if (lCharsPerSecond) {\n          sysoplog(fmt::format(\"Downloaded '{}' ({} cps).\", f, lCharsPerSecond));\n        } else {\n          sysoplog(fmt::format(\"Downloaded '{}'.\", f));\n        }\n        if (a()->config()->sysconfig_flags() & sysconfig_log_dl) {\n          if (const auto user = a()->users()->readuser(f.u().ownerusr, UserManager::mask::non_deleted);\n              user.has_value() && !user->deleted()) {\n            if (date_to_daten(user->firston()) < f.u().daten) {\n              const auto user_name_number = a()->user()->name_and_number();\n              ssm(f.u().ownerusr) << user_name_number << \" downloaded|#1 \\\"\" << f << \"\\\" |#7on \"\n                                  << fulldate();\n            }\n          }\n        }\n      }\n      it = a()->batch().delbatch(it);\n      return;\n    }\n  }\n  sysoplog(fmt::format(\"!!! Couldn't find \\\"{}\\\" in DL batch queue.\", file_name));\n}\n\nvoid didnt_upload(const BatchEntry& b) {\n  if (b.sending()) {\n    return;\n  }\n\n  dliscan1(b.dir());\n  auto* area = a()->current_file_area();\n  auto nRecNum = recno(b.aligned_filename());\n  if (nRecNum <= 0) {\n    sysoplog(fmt::format(\"!!! Couldn't find \\\"{}\\\" in transfer area.\", b.aligned_filename()));\n    return;\n  }\n  files::FileRecord f{};\n  do {\n    f = area->ReadFile(nRecNum);\n    if (f.numbytes() != 0) {\n      nRecNum = nrecno(b.aligned_filename(), nRecNum);\n    }\n  }\n  while (nRecNum != -1 && f.numbytes() != 0);\n\n  if (nRecNum == -1 || f.numbytes() != 0) {\n    sysoplog(fmt::format(\"!!! Couldn't find \\\"\\\" in transfer area.\", b.aligned_filename()));\n    return;\n  }\n  if (area->DeleteFile(f, nRecNum)) {\n    area->Save();\n  }\n}\n\nstatic void uploaded(const std::string& file_name, long cps) {\n  for (auto it = begin(a()->batch().entry); it != end(a()->batch().entry); ++it) {\n    const auto& b = *it;\n    if (file_name == b.aligned_filename() && !b.sending()) {\n      dliscan1(b.dir());\n      auto* area = a()->current_file_area();\n      auto nRecNum = recno(b.aligned_filename());\n      if (nRecNum > 0) {\n        files::FileRecord f{};\n        do {\n          f = area->ReadFile(nRecNum);\n          if (f.numbytes() != 0) {\n            nRecNum = nrecno(b.aligned_filename(), nRecNum);\n          }\n        }\n        while (nRecNum != -1 && f.numbytes() != 0);\n        if (nRecNum != -1 && f.numbytes() == 0) {\n          const auto source_filename = FilePath(a()->sess().dirs().batch_directory(), file_name);\n          const auto dest_filename = FilePath(a()->dirs()[b.dir()].path, file_name);\n          if (source_filename != dest_filename && File::Exists(source_filename)) {\n            File::Rename(source_filename, dest_filename);\n            File::Remove(source_filename);\n          }\n          File file(dest_filename);\n          if (file.Open(File::modeBinary | File::modeReadOnly)) {\n            if (!a()->upload_cmd.empty()) {\n              file.Close();\n              if (!check_ul_event(b.dir(), &f.u())) {\n                didnt_upload(b);\n              } else {\n                file.Open(File::modeBinary | File::modeReadOnly);\n              }\n            }\n            if (file.IsOpen()) {\n              f.set_numbytes(file.length());\n              file.Close();\n              get_file_idz(f, a()->dirs()[b.dir()]);\n              a()->user()->increment_uploaded();\n              add_to_file_database(f);\n              a()->user()->set_uk(a()->user()->uk() + static_cast<int>(bytes_to_k(f.numbytes())));\n              a()->status_manager()->Run([](Status& s)\n              {\n                s.increment_uploads_today();\n                s.increment_filechanged(Status::file_change_upload);\n              });\n              if (area->UpdateFile(f, nRecNum)) {\n                area->Save();\n              }\n              sysoplog(\n                  fmt::format(\"+ '{}' uploaded on {} ({} cps)\", f, a()->dirs()[b.dir()].name, cps));\n              bout.print(\"Uploaded '{}' to {} ({} cps)\\r\\n\", f, a()->dirs()[b.dir()].name, cps);\n            }\n          }\n          it = a()->batch().delbatch(it);\n          return;\n        }\n      }\n      it = a()->batch().delbatch(it);\n      if (try_to_ul(file_name)) {\n        sysoplog(fmt::sprintf(\"!!! Couldn't find file \\\"%s\\\" in directory.\", file_name));\n        bout.print(\"Deleting - couldn't find data for file {}\\r\\n\", file_name);\n      }\n      return;\n    }\n  }\n  if (try_to_ul(file_name)) {\n    sysoplog(fmt::format(\"!!! Couldn't find \\\"{}\\\" in UL batch queue.\", file_name));\n    bout.print(\"Deleting - don't know what to do with file {}\\r\\n\", file_name);\n\n    File::Remove(FilePath(a()->sess().dirs().batch_directory(), file_name));\n  }\n}\n\nstatic void ProcessDSZLogFile(const std::string& path) {\n  ProcessDSZLogFile(path, [](dsz_logline_t t, std::string fn, int cps)\n  {\n    switch (t) {\n    case dsz_logline_t::download:\n      downloaded(fn, cps);\n      break;\n    case dsz_logline_t::upload:\n      uploaded(fn, cps);\n      break;\n    case dsz_logline_t::error:\n    default:\n      sysoplog(fmt::format(\"Error transferring \\\"{}\\\"\", fn));\n      break;\n    }\n  });\n}\n\nstatic int hangup_color(int left) {\n  if (left < 3) {\n    return 6;\n  }\n  if (left < 6) {\n    return 2;\n  }\n  return 5;\n}\n\n// This function returns one character from either the local keyboard or\n// remote com port (if applicable).  Every second of inactivity, a\n// beep is sounded.  After 10 seconds of inactivity, the user is hung up.\nstatic void bihangup() {\n  bout.dump();\n  const auto batch_lastchar = steady_clock::now();\n  auto nextbeep = seconds(1);\n  bout.outstr(\"\\r\\n|#2Automatic disconnect in progress.\\r\\n\");\n  bout.outstr(\"|#2Press 'H' to Hangup, or any other key to return to system.\\r\\n\");\n\n  while (!bin.bkbhit() && !a()->sess().hangup()) {\n    const auto dd = steady_clock::now();\n    const auto elapsed = dd - batch_lastchar;\n    if (elapsed > nextbeep) {\n      nextbeep += seconds(1);\n      const auto left = 10 - static_cast<int>(duration_cast<seconds>(elapsed).count());\n      bout.ansic(hangup_color(left));\n      bout.outstr(\"\\r\");\n      bout.outstr(std::to_string(left));\n    }\n    if (dd - batch_lastchar > seconds(10)) {\n      bout.nl();\n      bout.outstr(\"Thank you for calling.\");\n      bout.nl();\n      bout.remoteIO()->disconnect();\n      a()->Hangup();\n      return;\n    }\n    a()->CheckForHangup();\n  }\n  if (const auto ch = bin.getkey(); ch == 'h' || ch == 'H') {\n    a()->Hangup();\n  }\n}\n\nvoid zmbatchdl(bool bHangupAfterDl) {\n  int cur = 0;\n\n  if (!a()->sess().incom()) {\n    return;\n  }\n\n  auto message = StrCat(\"ZModem Download: Files - \", a()->batch().size(),\n                        \" Time - \", ctim(a()->batch().dl_time_in_secs()));\n  if (bHangupAfterDl) {\n    message += \", HAD\";\n  }\n  sysoplog(message);\n  bout.nl();\n  bout.outstr(message);\n  bout.nl(2);\n\n  bool bRatioBad = false;\n  bool ok = true;\n  // TODO(rushfan): Rewrite this to use iterators;\n  do {\n    a()->tleft(true);\n    if (a()->config()->req_ratio() > 0.0001 && a()->user()->ratio() < a()->config()->req_ratio()) {\n      bRatioBad = true;\n    }\n    if (a()->user()->exempt_ratio()) {\n      bRatioBad = false;\n    }\n    if (!a()->batch().entry[cur].sending()) {\n      bRatioBad = false;\n      ++cur;\n    }\n    if (nsl() >= a()->batch().entry[cur].time(a()->modem_speed_) && !bRatioBad) {\n      const auto dir_num = a()->batch().entry[cur].dir();\n      dliscan1(dir_num);\n      const int record_number = recno(a()->batch().entry[cur].aligned_filename());\n      if (record_number <= 0) {\n        a()->batch().delbatch(cur);\n      } else {\n        bout.localIO()->Puts(StrCat(\"Files left - \", a()->batch().size(), \", Time left - \",\n                                    ctim(a()->batch().dl_time_in_secs()), \"\\r\\n\"));\n        auto* area = a()->current_file_area();\n        auto f = area->ReadFile(record_number);\n        auto send_filename = FilePath(a()->dirs()[dir_num].path, f);\n        if (a()->dirs()[dir_num].mask & mask_cdrom) {\n          auto orig_filename = FilePath(a()->dirs()[dir_num].path, f);\n          // update the send filename and copy it from the CD-ROM\n          send_filename = FilePath(a()->sess().dirs().temp_directory(), f);\n          if (!File::Exists(send_filename)) {\n            File::Copy(orig_filename, send_filename);\n          }\n        }\n        write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n        const auto send_fn = send_filename.string();\n        double percent;\n        zmodem_send(send_fn, &ok, &percent);\n        if (ok) {\n          downloaded(f.aligned_filename(), 0);\n        }\n      }\n    } else {\n      a()->batch().delbatch(cur);\n    }\n  }\n  while (ok && !a()->sess().hangup() && size_int(a()->batch().entry) > cur && !bRatioBad);\n\n  if (bRatioBad) {\n    bout.outstr(\"\\r\\nYour ratio is too low to continue the transfer.\\r\\n\\n\\n\");\n  }\n  if (bHangupAfterDl) {\n    bihangup();\n  }\n}\n\nchar end_ymodem_batch1() {\n  char b[128];\n\n  memset(b, 0, 128);\n\n  bool done = false;\n  int nerr = 0;\n  bool bAbort = false;\n  char ch;\n  do {\n    send_block(b, 5, true, 0);\n    ch = gettimeout(5, &bAbort);\n    if (ch == CF || ch == CX) {\n      done = true;\n    } else {\n      ++nerr;\n      if (nerr >= 9) {\n        done = true;\n      }\n    }\n  }\n  while (!done && !a()->sess().hangup() && !bAbort);\n  if (ch == CF) {\n    return CF;\n  }\n  if (ch == CX) {\n    return CX;\n  }\n  return CU;\n}\n\nstatic void end_ymodem_batch() {\n  bool abort = false;\n  int oldx = bout.localIO()->WhereX();\n  int oldy = bout.localIO()->WhereY();\n  bool ucrc = false;\n  if (!okstart(&ucrc, &abort)) {\n    abort = true;\n  }\n  if (!abort && !a()->sess().hangup()) {\n    const char ch = end_ymodem_batch1();\n    if (ch == CX) {\n      abort = true;\n    }\n    if (ch == CU) {\n      const auto fn = FilePath(a()->sess().dirs().temp_directory(),\n                                   StrCat(\".does-not-exist-\", a()->sess().instance_number(), \".$$$\"));\n      File::Remove(fn);\n      File nullFile(fn);\n      int terr = 0;\n      send_b(nullFile, 0L, 3, 0, &ucrc, files::FileName(\"\"), &terr, &abort);\n      abort = true;\n      File::Remove(fn);\n    }\n  }\n  bout.localIO()->GotoXY(oldx, oldy);\n}\n\nvoid ymbatchdl(bool bHangupAfterDl) {\n  int cur = 0;\n\n  if (!a()->sess().incom()) {\n    return;\n  }\n  auto message = StrCat(\"Ymodem Download: Files - \", a()->batch().size(),\n                        \", Time - \", ctim(a()->batch().dl_time_in_secs()));\n  if (bHangupAfterDl) {\n    message += \", HAD\";\n  }\n  sysoplog(message);\n  bout.nl();\n  bout.outstr(message);\n  bout.nl(2);\n\n  bool bRatioBad = false;\n  bool ok = true;\n  //TODO(rushfan): rewrite to use iterators.\n  do {\n    a()->tleft(true);\n    if ((a()->config()->req_ratio() > 0.0001) && (a()->user()->ratio() < a()->config()->req_ratio())) {\n      bRatioBad = true;\n    }\n    if (a()->user()->exempt_ratio()) {\n      bRatioBad = false;\n    }\n    if (!a()->batch().entry[cur].sending()) {\n      bRatioBad = false;\n      ++cur;\n    }\n    if (nsl() >= a()->batch().entry[cur].time(a()->modem_speed_) && !bRatioBad) {\n      const auto dir_num = a()->batch().entry[cur].dir();\n      dliscan1(dir_num);\n      if (const auto record_number = recno(a()->batch().entry[cur].aligned_filename());\n          record_number <= 0) {\n        a()->batch().delbatch(cur);\n      } else {\n        bout.localIO()->Puts(StrCat(\"Files left - \", a()->batch().size(), \", Time left - \",\n                                    ctim(a()->batch().dl_time_in_secs()), \"\\r\\n\"));\n        auto* area = a()->current_file_area();\n        auto f = area->ReadFile(record_number);\n        auto send_filename = FilePath(a()->dirs()[dir_num].path, f);\n        if (a()->dirs()[dir_num].mask & mask_cdrom) {\n          auto orig_filename = FilePath(a()->dirs()[dir_num].path, f);\n          send_filename = FilePath(a()->sess().dirs().temp_directory(), f);\n          if (!File::Exists(send_filename)) {\n            File::Copy(orig_filename, send_filename);\n          }\n        }\n        write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n        double percent;\n        xymodem_send(send_filename.string(), &ok, &percent, true, true, true);\n        if (ok) {\n          downloaded(f.aligned_filename(), 0);\n        }\n      }\n    } else {\n      a()->batch().delbatch(cur);\n    }\n  } while (ok && !a()->sess().hangup() && size_int(a()->batch().entry) > cur && !bRatioBad);\n\n  if (ok && !a()->sess().hangup()) {\n    end_ymodem_batch();\n  }\n  if (bRatioBad) {\n    bout.outstr(\"\\r\\nYour ratio is too low to continue the transfer.\\r\\n\\n\");\n  }\n  if (bHangupAfterDl) {\n    bihangup();\n  }\n}\n\nstatic double ratio1(unsigned long xa) {\n  if (a()->user()->dk() == 0 && xa == 0) {\n    return 99.999;\n  }\n  const auto r =\n      static_cast<double>(a()->user()->uk()) / static_cast<double>(a()->user()->dk() + xa);\n  return std::min<double>(r, 99.998);\n}\n\nstatic std::string make_ul_batch_list() {\n  const auto fn = fmt::sprintf(\"%s.%3.3u\", FILESUL_NOEXT, a()->sess().instance_number());\n  // TODO(rushfan): This should move to a temp directory.\n  const auto list_filename = FilePath(a()->bbspath(), fn);\n\n  File::Remove(list_filename, true);\n\n  TextFile tf(list_filename, \"wt\");\n  for (const auto& b : a()->batch().entry) {\n    if (b.sending()) {\n      continue;\n    }\n    auto line = FilePath(a()->dirs()[b.dir()].path, files::FileName(b.aligned_filename()));\n    tf.WriteLine(line.string());\n  }\n  return list_filename.string();\n}\n\nstatic std::filesystem::path make_dl_batch_list() {\n  const auto fn = fmt::sprintf(\"%s.%3.3u\", FILESDL_NOEXT, a()->sess().instance_number());\n  auto list_filename = FilePath(a()->bbspath(), fn);\n\n  File::Remove(list_filename, true);\n\n  TextFile tf(list_filename, \"wt\");\n\n  int32_t at = 0;\n  unsigned long addk = 0;\n  for (const auto& b : a()->batch().entry) {\n    if (!b.sending()) {\n      continue;\n    }\n    std::string filename_to_send;\n    if (a()->dirs()[b.dir()].mask & mask_cdrom) {\n      const auto fileToSend =\n          FilePath(a()->sess().dirs().temp_directory(), files::FileName(b.aligned_filename()));\n      if (!File::Exists(fileToSend)) {\n        auto sourceFile = FilePath(a()->dirs()[b.dir()].path, files::FileName(b.aligned_filename()));\n        File::Copy(sourceFile, fileToSend);\n      }\n      filename_to_send = fileToSend.string();\n    } else {\n      filename_to_send = FilePath(a()->dirs()[b.dir()].path, files::FileName(b.aligned_filename())).string();\n    }\n    bool ok = true;\n    if (nsl() < b.time(a()->modem_speed_) + at) {\n      ok = false;\n      bout.print(\"Cannot download {}: Not enough time\\r\\n\", b.aligned_filename());\n    }\n    const auto thisk = bytes_to_k(b.len());\n    if (a()->config()->req_ratio() > 0.0001f &&\n        ratio1(addk + thisk) < a()->config()->req_ratio() &&\n        !a()->user()->exempt_ratio()) {\n      ok = false;\n      bout.print(\"Cannot download {}: Ratio too low\\r\\n\", b.aligned_filename());\n    }\n    if (ok) {\n      tf.WriteLine(filename_to_send);\n      at += b.time(a()->modem_speed_);\n      addk += thisk;\n    }\n  }\n  return list_filename;\n}\n\nstatic void run_cmd(const std::string& orig_commandline, const std::string& downlist, const std::string& uplist,\n                    const std::string& dl, bool bHangupAfterDl) {\n  if (orig_commandline.empty()) {\n    if (!downlist.empty()) {\n      File::Remove(downlist, true);\n    }\n    if (!uplist.empty()) {\n      File::Remove(uplist, true);\n    }\n    return;\n  }\n\n  wwiv::bbs::CommandLine cl(orig_commandline, a()->bbspath());\n  cl.args(std::to_string(std::min<int>(a()->modem_speed_, 57600)),\n          std::to_string(a()->primary_port()),\n          downlist,\n          std::to_string(std::min<int>(a()->modem_speed_, 57600)),\n          uplist);\n  a()->Cls();\n  const auto user_name_number = a()->user()->name_and_number();\n  const auto message = fmt::format(\"{} is currently online at {} bps\\r\\n\\r\\n{}\\r\\n{}\\r\\n\",\n                                    user_name_number, a()->modem_speed_, dl, cl.cmdline());\n  bout.localIO()->Puts(message);\n  if (a()->sess().incom()) {\n    File::Remove(a()->dsz_logfile_name_, true);\n    ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_PROT_BATCH) | EFLAG_BATCH_DIR);\n    if (bHangupAfterDl) {\n      bihangup();\n    } else {\n      bout.outstr(\"\\r\\n|#9Please wait...\\r\\n\\n\");\n    }\n    ProcessDSZLogFile(a()->dsz_logfile_name_);\n    a()->UpdateTopScreen();\n  }\n    \n  if (!downlist.empty()) {\n    File::Remove(downlist, true);\n  }\n  if (!uplist.empty()) {\n    File::Remove(uplist, true);\n  }\n}\n\n\nvoid dszbatchdl(bool bHangupAfterDl, const std::string& command_line, const std::string& description) {\n  auto download_log_entry = fmt::format(\"{} BATCH Download: Files - {}, Time - ()\", \n        description, a()->batch().size(), ctim(a()->batch().dl_time_in_secs()));\n  if (bHangupAfterDl) {\n    download_log_entry += \", HAD\";\n  }\n  sysoplog(download_log_entry);\n  bout.nl();\n  bout.outstr(download_log_entry);\n  bout.nl(2);\n\n  write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n  const auto list_filename = make_dl_batch_list();\n  run_cmd(command_line, list_filename.string(), \"\", download_log_entry, bHangupAfterDl);\n}\n\nstatic void dszbatchul(bool bHangupAfterDl, char* command_line, const std::string& description) {\n  auto download_log_entry =\n      fmt::format(\"{} BATCH Upload: Files - {}\", description, a()->batch().size());\n  if (bHangupAfterDl) {\n    download_log_entry += \", HAD\";\n  }\n  sysoplog(download_log_entry);\n  bout.nl();\n  bout.outstr(download_log_entry);\n  bout.nl(2);\n\n  write_inst(INST_LOC_UPLOAD, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n  const auto list_filename = make_ul_batch_list();\n\n  const auto ti = std::chrono::system_clock::now();\n  run_cmd(command_line, \"\", list_filename, download_log_entry, bHangupAfterDl);\n  const auto time_used = std::chrono::system_clock::now() - ti;\n  a()->user()->add_extratime(time_used);\n}\n\nint batchdl(int mode) {\n  bool done = false;\n  do {\n    char ch = 0;\n    switch (mode) {  // NOLINT(hicpp-multiway-paths-covered)\n    case 0:\n    case 3:\n      bout.nl();\n      if (mode == 3) {\n        bout.outstr(\"|#7[|#2L|#7]|#1ist Files, |#7[|#2C|#7]|#1lear Queue, |#7[|#2R|#7]|#1emove File, \"\n                  \"|#7[|#2Q|#7]|#1uit or |#7[|#2D|#7]|#1ownload : |#0\");\n        ch = onek(\"QLRDC\\r\");\n      } else {\n        bout.outstr(\"|#9Batch: L,R,Q,C,D,U,? : \");\n        ch = onek(\"Q?CLRDU\");\n      }\n      break;\n    case 1:\n      listbatch();\n      ch = 'D';\n      break;\n    case 2:\n      listbatch();\n      ch = 'U';\n      break;\n    }\n    switch (ch) {\n    case '?':\n      bout.printfile(TBATCH_NOEXT);\n      break;\n    case 'Q':\n      if (mode == 3) {\n        return 1;\n      }\n      done = true;\n      break;\n    case 'L':\n      listbatch();\n      break;\n    case 'R': {\n      bout.nl();\n      bout.outstr(\"|#9Remove which? \");\n      std::string s = bin.input(4);\n      auto i = to_number<int>(s);\n      if (i > 0 && i <= size_int(a()->batch().entry)) {\n        didnt_upload(a()->batch().entry[i - 1]);\n        a()->batch().delbatch(i - 1);\n      }\n      if (a()->batch().empty()) {\n        bout.outstr(\"\\r\\nBatch queue empty.\\r\\n\\n\");\n        done = true;\n      }\n    }\n    break;\n    case 'C':\n      bout.outstr(\"|#5Clear queue? \");\n      if (bin.yesno()) {\n        for (const auto& b : a()->batch().entry) { didnt_upload(b); }\n        a()->batch().entry.clear();\n        bout.outstr(\"Queue cleared.\\r\\n\");\n        if (mode == 3) {\n          return 1;\n        }\n      }\n      done = true;\n      break;\n    case 'U': {\n      if (mode != 3) {\n        bout.nl();\n        bout.outstr(\"|#5Hang up after transfer? \");\n        const auto hangup_after_dl = bin.yesno();\n        bout.nl(2);\n        int i = get_protocol(xfertype::xf_up_batch);\n        if (i > 0) {\n          dszbatchul(hangup_after_dl, a()->externs[i - WWIV_NUM_INTERNAL_PROTOCOLS].receivebatchfn,\n                     a()->externs[i - WWIV_NUM_INTERNAL_PROTOCOLS].description);\n          if (!hangup_after_dl) {\n            bout.printf(\"Your ratio is now: %-6.3f\\r\\n\", a()->user()->ratio());\n          }\n        }\n        done = true;\n      }\n    }\n    break;\n    case 'D':\n    case 13:\n      if (mode != 3) {\n        if (a()->batch().numbatchdl() == 0) {\n          bout.outstr(\"\\r\\nNothing in batch download queue.\\r\\n\\n\");\n          done = true;\n          break;\n        }\n        bout.nl();\n        if (!ratio_ok()) {\n          bout.outstr(\"\\r\\nSorry, your ratio is too low.\\r\\n\\n\");\n          done = true;\n          break;\n        }\n        bout.outstr(\"|#5Hang up after transfer? \");\n        const auto hangup_after_dl = bin.yesno();\n        bout.nl();\n        int i = get_protocol(xfertype::xf_down_batch);\n        if (i > 0) {\n          if (i == WWIV_INTERNAL_PROT_YMODEM) {\n            if (!a()->over_intern.empty() && a()->over_intern[2].othr & othr_override_internal &&\n                a()->over_intern[2].sendbatchfn[0]) {\n              dszbatchdl(hangup_after_dl, a()->over_intern[2].sendbatchfn, prot_name(4));\n            } else {\n              ymbatchdl(hangup_after_dl);\n            }\n          } else if (i == WWIV_INTERNAL_PROT_ZMODEM) {\n            zmbatchdl(hangup_after_dl);\n          } else {\n            dszbatchdl(hangup_after_dl, a()->externs[i - WWIV_NUM_INTERNAL_PROTOCOLS].sendbatchfn,\n                       a()->externs[i - WWIV_NUM_INTERNAL_PROTOCOLS].description);\n          }\n          if (!hangup_after_dl) {\n            bout.nl();\n            bout.printf(\"Your ratio is now: %-6.3f\\r\\n\", a()->user()->ratio());\n          }\n        }\n      }\n      done = true;\n      break;\n    }\n  }\n  while (!done && !a()->sess().hangup());\n  return 0;\n}\n\nvoid upload(int dn) {\n  if (a()->current_user_dir().subnum < 0 || a()->udir.empty() || dn < 0) {\n    // We don't have any current directory, can not list files.\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n  const auto& d = a()->dirs()[dn];\n  dliscan1(d);\n  const auto free_space = File::freespace_for_path(d.path);\n  if (free_space < 100) {\n    bout.outstr(\"\\r\\nNot enough disk space to upload here.\\r\\n\\n\");\n    return;\n  }\n  listbatch();\n  bout.print(\"Upload - {}k free.\", free_space);\n  bout.nl();\n  bout.printfile(TRY2UL_NOEXT);\n\n  bool done = false;\n  do {\n    bout.outstr(\"|#2B|#7) |#1Blind batch upload\\r\\n\");\n    bout.outstr(\"|#2N|#7) |#1Normal upload\\r\\n\");\n    bout.outstr(\"|#2Q|#7) |#1Quit\\r\\n\\n\");\n    bout.outstr(\"|#2Which |#7(|#2B,n,q,?|#7)|#1: \");\n\n    const char key = onek(\"QB\\rN?\");\n    switch (key) {\n    case 'B':\n    case '\\r':\n      batchdl(2);\n      done = true;\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'N':\n      normalupload(dn);\n      done = true;\n      break;\n    case '?':\n      bout.outstr(\"This is help?\");\n      bout.nl();\n      bout.pausescr();\n      done = false;\n      break;\n    }\n  }\n  while (!done && !a()->sess().hangup());\n}\n\nstd::chrono::seconds time_to_transfer(int32_t file_size, int32_t modem_speed) {\n  if (modem_speed == 0) {\n    return std::chrono::seconds(0);\n  }\n  const double ms = modem_speed;\n  const double fs = file_size;\n  return std::chrono::seconds(std::lround(12.656 * fs / ms));\n}\n\nBatchEntry::BatchEntry(std::string fn, int d, int l, bool s)\n: filename_(std::move(fn)), dir_(static_cast<int16_t>(d)), len_(l), sending_(s) {}\nBatchEntry::BatchEntry(const files::FileName& fn, int d, int l, bool s)\n: BatchEntry(fn.aligned_filename(), d, l, s) {}\n\nBatchEntry::BatchEntry() = default;\n\nint32_t BatchEntry::time(int modem_speed) const {\n  const auto d = time_to_transfer(modem_speed, len());\n  return static_cast<int32_t>(d.count());\n}\n\nint Batch::FindBatch(const std::string& file_name) {\n  for (int i = 0; i < size_int(entry); i++) {\n    if (iequals(file_name, entry[i].aligned_filename())) {\n      return i;\n    }\n  }\n\n  return -1;\n}\n\nbool Batch::RemoveBatch(const std::string& file_name) {\n  const auto n = FindBatch(file_name);\n  if (n < 0) {\n    return false;\n  }\n  return delbatch(n);\n}\n\nbool Batch::delbatch(size_t pos) {\n  if (pos >= entry.size()) {\n    return false;\n  }\n  return erase_at(entry, pos);\n}\n\nstd::vector<BatchEntry>::iterator Batch::delbatch(std::vector<BatchEntry>::iterator& it) {\n  return entry.erase(it);\n}\n\nlong Batch::dl_time_in_secs() const {\n\n  if (a()->modem_speed_ == 0) {\n    return 0;\n  }\n\n  size_t r = 0;\n  for (const auto& e : entry) {\n    if (e.sending()) {\n      r += e.len();\n    }\n  }\n\n  const auto t = 12.656 * r / a()->modem_speed_;\n  return std::lround(t);\n}\n\nbool Batch::contains_file(const std::string& file_name) const {\n  for (const auto& b : entry) {\n    if (iequals(file_name, b.aligned_filename())) {\n      return true;\n    }\n  }\n  return false;\n\n}\n\nbool Batch::contains_file(const files::FileName& fn) const {\n  return contains_file(fn.aligned_filename());\n}\n"
  },
  {
    "path": "bbs/batch.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BATCH_H__\n#define __INCLUDED_BBS_BATCH_H__\n\n#include \"core/stl.h\"\n#include \"core/wwivport.h\"\n#include \"sdk/files/file_record.h\"\n#include <chrono>\n#include <string>\n#include <vector>\n\n/**\n * One Batch Upload/Download entry.\n */\nclass BatchEntry {\npublic:\n  BatchEntry();\n  BatchEntry(std::string fn, int d, int l, bool s);\n  BatchEntry(const wwiv::sdk::files::FileName& fn, int d, int l, bool s);\n\n  [[nodiscard]] int32_t time(int modem_speed) const;\n\n  /** Aligned filename */\n  [[nodiscard]] std::string aligned_filename() const { return filename_; }\n\n  /** The read directory number (as in directory_t) */\n  [[nodiscard]] int16_t dir() const { return dir_; } \n\n  /** Size of the file*/\n  [[nodiscard]] int32_t len() const { return len_; }\n\n  [[nodiscard]] bool sending() const { return sending_; }\n\nprivate:\n  std::string filename_;\n  int16_t dir_{-1};\n  int32_t len_{0};\n  bool sending_{false};\n};\n\nclass Batch {\npublic:\n  bool clear() {\n    entry.clear();\n    return true;\n  }\n\n  bool AddBatch(const BatchEntry& b) {\n    entry.push_back(b);\n    return true;\n  }\n\n  bool AddBatch(BatchEntry&& b) {\n    entry.emplace_back(b);\n    return true;\n  }\n\n  [[nodiscard]] int FindBatch(const std::string& file_name);\n  bool RemoveBatch(const std::string& file_name);\n  // deletes an entry by position;\n  bool delbatch(size_t pos);\n  std::vector<BatchEntry>::iterator delbatch(std::vector<BatchEntry>::iterator& it);\n\n  [[nodiscard]] long dl_time_in_secs() const;\n  [[nodiscard]] bool contains_file(const std::string& file_name) const;\n  [[nodiscard]] bool contains_file(const wwiv::sdk::files::FileName& fn) const;\n\n  [[nodiscard]] int numbatchdl() const {\n    auto r = 0;\n    for (const auto& e : entry) {\n      if (e.sending())\n        r++;\n    }\n    return r;\n  }\n\n  [[nodiscard]] size_t numbatchul() const noexcept {\n    size_t r = 0;\n    for (const auto& e : entry) {\n      if (!e.sending())\n        r++;\n    }\n    return r;\n  }\n\n  [[nodiscard]] int size() const noexcept {\n    return wwiv::stl::size_int(entry);\n  }\n\n  [[nodiscard]] ssize_t ssize() const noexcept {\n    return wwiv::stl::ssize(entry);\n  }\n\n  [[nodiscard]] bool empty() const noexcept {\n    return entry.empty();\n  }\n\n  std::vector<BatchEntry> entry;\n};\n\nvoid upload(int dn);\nvoid dszbatchdl(bool bHangupAfterDl, const std::string& command_line, const std::string& description);\nint batchdl(int mode);\nvoid didnt_upload(const BatchEntry& b);\nvoid ymbatchdl(bool bHangupAfterDl);\nvoid zmbatchdl(bool bHangupAfterDl);\n\nstd::chrono::seconds time_to_transfer(int32_t file_size, int32_t modem_speed);\n\n#endif  // __INCLUDED_BBS_BATCH_H__\n"
  },
  {
    "path": "bbs/bbs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n\n#include \"bbs/application.h\"\n#include \"common/exceptions.h\"\n#include \"core/cp437.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"local_io/stdio_local_io.h\"\n#include \"sdk/config.h\"\n#include <exception>\n#include <iostream>\n\n#if !defined( _WIN32 )\n#include <unistd.h>\n#endif // !_WIN32\n\n\n// Uncomment this line to use curses on Win32\n#define WWIV_WIN32_CURSES_IO\n\nstatic Application* app_;\n\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\nApplication* a() { return app_; }\n\n// [ VisibleForTesting ]\nApplication* CreateSession(LocalIO* localIO) {\n  app_ = new Application(localIO);\n  return app_;\n}\nusing wwiv::core::Logger;\nusing wwiv::core::LoggerConfig;\nusing wwiv::sdk::LogDirFromConfig;\n\nint bbsmain(int argc, char *argv[]) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  std::unique_ptr<Application> bbs;\n  try {\n#ifdef WWIV_PAUSE_AT_START\n    std::cout << \"pause\";\n    getchar();\n#endif\n#ifndef __OS2__    \n    set_wwiv_codepage(wwiv::core::wwiv_codepage_t::utf8);\n#endif\n\n    // Create a default session using stdio, we'll reset the LocalIO\n    // later once we know what type to use.\n    VLOG(4) << \"Before CreateSession\";\n    bbs.reset(CreateSession(new StdioLocalIO()));\n    VLOG(4) << \"After CreateSession\";\n    const auto return_code = bbs->Run(argc, argv); \n    return bbs->ExitBBSImpl(return_code, true);\n  } catch (const wwiv::common::hangup_error& e) {\n    if (e.hangup_type() == wwiv::common::hangup_type_t::user_disconnected) {\n      LOG(ERROR) << \"BBS User Hung Up: \" << e.what();\n    }\n    if (bbs) {\n      return bbs->ExitBBSImpl(Application::exitLevelOK, true);\n    }\n    return Application::exitLevelOK;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"BBS Terminated by exception: \" << e.what();\n    if (bbs) {\n      return bbs->ExitBBSImpl(Application::exitLevelNotOK, true);\n    }\n  }\n  DLOG(FATAL) << \"Should never reach here\";\n  return Application::exitLevelNotOK;\n}\n"
  },
  {
    "path": "bbs/bbs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BBS_H\n#define INCLUDED_BBS_BBS_H\n\n/*\n * @header WWIV 5 Main Application\n * Main Starting point of the WWIV 5 System.\n */\n\n#include \"bbs/application.h\"\n\n// Function Prototypes\nApplication* CreateSession(wwiv::local::io::LocalIO* localIO);\nApplication* a();\n\n#endif\n\n\n"
  },
  {
    "path": "bbs/bbs_event_handlers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs_event_handlers.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"common/common_events.h\"\n#include \"core/eventbus.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"instmsg.h\"\n#include \"multinst.h\"\n#include \"utility.h\"\n#include \"common/datetime.h\"\n#include \"common/output.h\"\n\nnamespace wwiv::bbs {\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\nstatic void PrintTime() {\n  const auto line = bout.SaveCurrentLine();\n\n  bout.ansic(0);\n  bout.nl(2);\n  const auto dt = DateTime::now();\n  bout.print(\"|#2{}\\r\\n\", dt.to_string());\n  if (a()->sess().IsUserOnline()) {\n    const auto time_on = std::chrono::system_clock::now() - a()->sess().system_logon_time();\n    const auto seconds_on =\n        static_cast<long>(std::chrono::duration_cast<std::chrono::seconds>(time_on).count());\n    bout.print(\"|#9Time on   = |#1{}\\r\\n\", ctim(seconds_on));\n    bout.print(\"|#9Time left = |#1{}\\r\\n\", ctim(nsl()));\n  }\n  bout.nl();\n  bout.RestoreCurrentLine(line);\n}\n\nstatic void CheckForHangup() {\n  a()->CheckForHangup();\n}\n\nstatic void GiveupTimeSlices() {\n  yield();\n  if (inst_msg_waiting() && (!a()->sess().in_chatroom() || !a()->sess().chatline())) {\n    process_inst_msgs();\n  } else {\n    sleep_for(std::chrono::milliseconds(100));\n  }\n  yield();\n}\n\nbool bbs_callbacks() {\n  // Register Application Level Callbacks\n  bus().add_handler<ProcessInstanceMessages>([]() {\n    if (inst_msg_waiting() && !a()->sess().chatline()) {\n      process_inst_msgs();\n    }\n  });\n  bus().add_handler<ResetProcessingInstanceMessages>([]() { setiia(std::chrono::seconds(5)); });\n  bus().add_handler<PauseProcessingInstanceMessages>([]() { setiia(std::chrono::seconds(0)); });\n  bus().add_handler<CheckForHangupEvent>(CheckForHangup);\n  bus().add_handler<HangupEvent>([]() { a()->Hangup(); });\n  bus().add_handler<UpdateTopScreenEvent>([]() { a()->UpdateTopScreen(); });\n  bus().add_handler<UpdateTimeLeft>(\n      [](const UpdateTimeLeft& u) { a()->tleft(u.check_for_timeout); });\n  bus().add_handler<HandleSysopKey>([](const HandleSysopKey& k) { a()->handle_sysop_key(k.key); });\n  bus().add_handler<GiveupTimeslices>(GiveupTimeSlices);\n  bus().add_handler<DisplayTimeLeft>(PrintTime);\n  bus().add_handler<DisplayMultiInstanceStatus>(multi_instance);\n\n  bus().add_handler<ToggleAvailable>(toggle_avail);\n  bus().add_handler<ToggleInvisble>(toggle_invis);\n  return true;\n}\n\n} // namespace wwiv::bbs\n"
  },
  {
    "path": "bbs/bbs_event_handlers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BBS_EVENT_HANDLERS_H\n#define INCLUDED_BBS_BBS_EVENT_HANDLERS_H\n\nnamespace wwiv::bbs {\n\nbool bbs_callbacks();\n\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/bbs_helper.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2014-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WIT`OUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"bbs/bbs_helper.h\"\r\n\r\n#include \"bbs/application.h\"\r\n#include \"bbs/bbs.h\"\r\n#include \"sdk/menus/menu_set.h\"\r\n\r\n#include <memory>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::sdk;\r\n\r\nBbsHelper::BbsHelper() : CommonHelper(42) {\r\n  app_.reset(CreateSession(io_->local_io()));\r\n  app_->SetCommForTest(io_->remote_io());\r\n  app_->set_config_for_test(*config_);\r\n  app_->sess().instance_number(42);\r\n}\r\n\r\nvoid BbsHelper::SetUp() {\r\n  CommonHelper::SetUp();\r\n}\r\n\r\nConfig& BbsHelper::config() const {\r\n  return *app_->config();\r\n}\r\n\r\nwwiv::common::SessionContext& BbsHelper::sess() {\r\n  return app_->sess();\r\n}\r\n\r\nUser* BbsHelper::user() {\r\n  return app_->user();  \r\n}\r\n\r\nconst User* BbsHelper::user() const {\r\n  return app_->user();  \r\n}\r\n\r\nwwiv::common::Context& BbsHelper::context() {\r\n  return app_->context();\r\n}\r\n"
  },
  {
    "path": "bbs/bbs_helper.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_BBS_HELPER_H\r\n#define INCLUDED_BBS_HELPER_H\r\n\r\n#include \"bbs/bbs.h\"\r\n#include \"common/common_helper.h\"\r\n#include <memory>\r\n\r\n/*\r\n * \r\n * Test helper for using code with heavy BBS dependencies.\r\n * \r\n * To use, add an instance as a field in the test class.  Then invoke.\r\n * BbsHelper::SetUp before use. typically from Test::SetUp.\r\n */\r\nclass BbsHelper : public CommonHelper {\r\npublic:\r\n  BbsHelper();\r\n  virtual ~BbsHelper() = default;\r\n  void SetUp() override;\r\n  [[nodiscard]] wwiv::sdk::Config& config() const override;\r\n  [[nodiscard]] wwiv::common::SessionContext& sess() override;\r\n  [[nodiscard]] wwiv::sdk::User* user() override;\r\n  [[nodiscard]] const wwiv::sdk::User* user() const;\r\n  [[nodiscard]] wwiv::common::Context& context() override;\r\n\r\n  std::unique_ptr<Application> app_;\r\n\r\n};\r\n\r\n#endif\r\n"
  },
  {
    "path": "bbs/bbs_macro_context_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n#include \"bbs/interpret.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"common/context.h\"\n#include \"common/macro_context.h\"\n#include \"common/pipe_expr.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::common;\n\nclass BbsMacroContextTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    helper.SetUp();\n    pipe_eval = std::make_unique<PipeEval>(a()->context());\n    bc = std::make_unique<BbsMacroContext>(&a()->context(), *pipe_eval);\n  }\n\n  BbsHelper helper{};\n  std::unique_ptr<BbsMacroContext> bc;\n  std::unique_ptr<PipeEval> pipe_eval;\n};\n\nTEST_F(BbsMacroContextTest, Move_Up2) {\n  std::string s1 = \"[2A\";\n  auto it = std::cbegin(s1);\n\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.up, 2);\n}\n\nTEST_F(BbsMacroContextTest, Move_Up) {\n  std::string s1 = \"[A\";\n  auto it = std::cbegin(s1);\n\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.up, 1);\n}\n\nTEST_F(BbsMacroContextTest, Move_Down) {\n  std::string s1 = \"[2B\";\n  auto it = std::cbegin(s1);\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.up, 0);\n  EXPECT_EQ(i.down, 2);\n}\n\nTEST_F(BbsMacroContextTest, Move_Left) {\n  std::string s1 = \"[2D\";\n  auto it = std::cbegin(s1);\n\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.left, 2);\n}\n\nTEST_F(BbsMacroContextTest, Move_Right) {\n  std::string s1 = \"[2C\";\n  auto it = std::cbegin(s1);\n\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.right, 2);\n}\n\nTEST_F(BbsMacroContextTest, Move_XY) {\n  std::string s1 = \"[10;20H\";\n  auto it = std::cbegin(s1);\n\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::movement);\n  EXPECT_EQ(i.x, 10);\n  EXPECT_EQ(i.y, 20);\n}\n\nTEST_F(BbsMacroContextTest, Expr_Ending) {\n  std::string s1 = \"{hello}\";\n  auto it = std::cbegin(s1);\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::text);\n  EXPECT_EQ(i.text, \"{hello}\");\n}\n\nTEST_F(BbsMacroContextTest, Expr_WithAdditional) {\n  std::string s1 = \"{hello}Hello\";\n  auto it = std::cbegin(s1);\n  const auto i = bc->interpret(it, std::end(s1));\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::text);\n  EXPECT_EQ(i.text, \"{hello}\");\n  EXPECT_EQ(\"Hello\", std::string(it, std::cend(s1)));\n}\n\nTEST_F(BbsMacroContextTest, JustText) {\n  const std::string s1 = \"hello\";\n  auto it = std::cbegin(s1);\n  const auto end = std::cend(s1);\n  const auto i = bc->interpret(it, end);\n  EXPECT_EQ(i.cmd, interpreted_cmd_t::text);\n  EXPECT_EQ(i.text, \"h\");\n  EXPECT_EQ('e', *it);\n  EXPECT_EQ(it, std::cbegin(s1) + 1);\n}\n\nTEST_F(BbsMacroContextTest, Variable) {\n  const std::string s1 = \"{user.name}\";\n  auto it = std::cbegin(s1);\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->sl(200);\n  helper.sess().effective_sl(200);\n  const auto i = bc->interpret(it, std::cend(s1));\n  EXPECT_EQ(i.text, \"Rushfan\");\n}\n\nTEST_F(BbsMacroContextTest, If) {\n  const std::string s1 = R\"({if \"user.sl >= 200\", \"over\", \"under\"})\";\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  {\n    helper.user()->sl(200);\n    helper.sess().effective_sl(200);\n    auto it = std::cbegin(s1);\n    const auto i = bc->interpret(it, std::cend(s1));\n    EXPECT_EQ(i.text, \"over\");\n  }\n  {\n    helper.user()->sl(199);\n    helper.sess().effective_sl(199);\n    auto it = std::cbegin(s1);\n    const auto i = bc->interpret(it, std::cend(s1));\n    EXPECT_EQ(i.text, \"under\");\n  }\n}\n"
  },
  {
    "path": "bbs/bbs_main.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2014-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\nint bbsmain(int argc, char *argv[]);\r\n\r\nint main(int argc, char *argv[]) {\r\n  return bbsmain(argc, argv);\r\n}\r\n"
  },
  {
    "path": "bbs/bbs_test_main.cpp",
    "content": "#include \"gtest/gtest.h\"\r\n\r\n#include \"core/log.h\"\r\n\r\nusing namespace wwiv::core;\r\n\r\nint main(int argc, char* argv[]) {\r\n  testing::InitGoogleTest(&argc, argv);\r\n\r\n  LoggerConfig logger_config{};\r\n  logger_config.register_file_destinations = false;\r\n  logger_config.log_startup = false;\r\n  Logger::Init(argc, argv, logger_config);\r\n  return RUN_ALL_TESTS();\r\n}\r\n"
  },
  {
    "path": "bbs/bbslist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbslist.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/sysopf.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"core/cereal_utils.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include <iomanip>\n#include <map>\n#include <string>\n#include <vector>\n\n// This is defined in keycodes.h and breaks rapidjson since that is what is used\n// for the template variable.\n#undef CT\n\n#include \"common/output.h\"\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/archives/json.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/memory.hpp>\n\nusing wwiv::common::InputMode;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nnamespace cereal {\n//! Saving for std::map<std::string, std::string> for text based archives\n// Note that this shows off some internal cereal traits such as EnableIf,\n// which will only allow this template to be instantiated if its predicates\n// are true\ntemplate <class Archive, class C, class A,\n  traits::EnableIf<traits::is_text_archive<Archive>::value> = traits::sfinae> inline\n  void save(Archive & ar, std::map<std::string, std::string, C, A> const & map) {\n  for (const auto & i : map)\n    ar(cereal::make_nvp(i.first, i.second));\n}\n\n//! Loading for std::map<std::string, std::string> for text based archives\ntemplate <class Archive, class C, class A,\n  traits::EnableIf<traits::is_text_archive<Archive>::value> = traits::sfinae> inline\n  void load(Archive & ar, std::map<std::string, std::string, C, A> & map) {\n  map.clear();\n\n  auto hint = map.begin();\n  while (true) {\n    const auto namePtr = ar.getNodeName();\n\n    if (!namePtr)\n      break;\n\n    std::string key = namePtr;\n    std::string value; ar(value);\n    hint = map.emplace_hint(hint, std::move(key), std::move(value));\n  }\n}\n} // namespace cereal\n\n\nnamespace wwiv::bbslist {\n\ntemplate <class Archive> void serialize(Archive& ar, BbsListEntry& b) {\n  SERIALIZE(b, name);\n  SERIALIZE(b, software);\n  SERIALIZE(b, sysop_name);\n  SERIALIZE(b, location);\n  SERIALIZE(b, addresses);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, BbsListAddress& a) {\n  SERIALIZE(a, type);\n  SERIALIZE(a, address);\n}\n\nbool LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                  std::vector<BbsListEntry>& entries) {\n  entries.clear();\n\n  TextFile file(FilePath(dir, filename), \"r\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n  const auto text = file.ReadFileIntoString();\n  std::stringstream ss;\n  ss << text;\n  cereal::JSONInputArchive load(ss);\n  load(cereal::make_nvp(\"bbslist\", entries));\n\n  // Assign id numbers.\n  int id = 1;\n  for (auto& e : entries) {\n    e.id = id++;\n  }\n  return true;\n}\n\nbool SaveToJSON(const std::filesystem::path& dir, const std::string& filename,\n                const std::vector<BbsListEntry>& entries) {\n  std::ostringstream ss;\n  {\n    cereal::JSONOutputArchive save(ss);\n    save(cereal::make_nvp(\"bbslist\", entries));\n  }\n\n  TextFile file(FilePath(dir, filename), \"w\");\n  if (!file.IsOpen()) {\n    // rapidjson will assert if the file does not exist, so we need to\n    // verify that the file exists first.\n    return false;\n  }\n\n  file.Write(ss.str());\n  return true;\n}\n\nstatic bool ConvertLegacyList(const std::filesystem::path& dir, const std::string& legacy_filename,\n                              std::vector<BbsListEntry>& entries) {\n\n  TextFile legacy_file(FilePath(dir, legacy_filename), \"r\");\n  if (!legacy_file.IsOpen()) {\n    return false;\n  }\n\n  std::string line;\n  while (legacy_file.ReadLine(&line)) {\n    if (line.size() < 79) {\n      // All real bbs entry lines are 79\n      continue;\n    }\n    if (line[3] != '-' || line[7] != '-') {\n      // check for ddd-ddd-dddd\n      continue;\n    }\n    BbsListEntry e{};\n    auto name = StringTrimEnd(line.substr(14, 42));\n    e.name = name;\n    e.addresses.push_back({\"modem\", line.substr(0, 12)});\n    e.software = line.substr(74, 4);\n    entries.emplace_back(e);\n  }\n  return true;\n}\n\nstatic void ReadBBSList(const std::vector<BbsListEntry>& entries) {\n  auto cnt = 0;\n  bout.cls();\n  bout.litebar(StrCat(a()->config()->system_name(), \" BBS List\"));\n  for (const auto& entry : entries) {\n    bout.ansic(++cnt % 2 == 0 ? 1 : 9);\n    bout.print(\"{:<3} : {:<60} ({})\\r\\n\", entry.id, entry.name, entry.software);\n    for (const auto& a : entry.addresses) {\n      bout.ansic((cnt % 2) == 0 ? 1 : 9);\n      bout.print(\"{:<11} : {}\\r\\n\", a.type, a.address);\n    }\n  }\n  bout.nl();\n}\n\nvoid delete_bbslist() {\n  std::vector<BbsListEntry> entries;\n  LoadFromJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n\n  if (entries.empty()) {\n    bout.pl(\"|#6You can not delete an entry when the list is empty.\");\n    bout.pausescr();\n    return;\n  }\n\n  ReadBBSList(entries);\n  bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) Enter Entry Number to Delete: \");\n  const auto r = bin.input_number_hotkey(1, {'Q'}, 1, 9999, false);\n  if (r.key == 'Q' || r.num == 0) {\n    return;\n  }\n  for (auto b = std::begin(entries); b != std::end(entries); ++b) {\n    if (b->id == r.num) {\n      entries.erase(b);\n      bout.pl(\"|10Entry deleted.\");\n      SaveToJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n      return;\n    }\n  }\n}\n\nstatic bool IsBBSPhoneNumberValid(const std::string& phoneNumber) {\n  if (phoneNumber.length() != 12) {\n    return false;\n  }\n  if (phoneNumber[3] != '-' || phoneNumber[7] != '-') {\n    return false;\n  }\n  for (const auto ch : phoneNumber) {\n    if (!strchr(\"0123456789-\", ch)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nstatic bool IsBBSPhoneNumberUnique(const std::string& phoneNumber, const std::vector<BbsListEntry>& entries) {\n  for (const auto& e : entries) {\n    for (const auto& a : e.addresses) {\n      if (a.type != \"modem\") {\n        continue;\n      }\n      if (a.address == phoneNumber) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nstatic bool AddBBSListEntry(std::vector<BbsListEntry>& entries) {\n  bout.nl();\n  bout.outstr(\"|#9Does this BBS have a modem line? (y/N) : \");\n  const auto has_pots = bin.noyes();\n  bout.outstr(\"|#9Is this BBS telnettable? (Y/n)         : \");\n  const auto has_telnet = bin.yesno();\n\n  if (!has_telnet && !has_pots) {\n    bout.nl();\n    bout.pl(\"|#6Either a modem or telnet connection is required.\");\n    bout.pausescr();\n    return false;\n  }\n\n  bout.nl();\n  BbsListEntry entry = {};\n  if (has_pots) {\n    bout.outstr(\"|#9Enter the Modem Number   : \");\n    const auto phone_number = bin.input_phonenumber(\"\", 12);\n    bout.nl();\n    if (!IsBBSPhoneNumberValid(phone_number)) {\n      bout.outstr(\"\\r\\n|#6 Error: Please enter number in correct format.\\r\\n\\n\");\n      return false;\n    }\n    if (!IsBBSPhoneNumberUnique(phone_number, entries)) {\n      bout.outstr(\"|#6Sorry, It's already in the BBS list.\\r\\n\\n\\n\");\n      return false;\n    }\n    entry.addresses.push_back({\"modem\", phone_number});\n  }\n\n  if (has_telnet) {\n    bout.outstr(\"|#9Enter the Telnet Address : \");\n    const auto telnet_address = bin.input_text(\"\", 50);\n    bout.nl();\n    if (!telnet_address.empty()) {\n      entry.addresses.push_back({\"telnet\", telnet_address});\n    }\n  }\n\n  bout.outstr(\"|#9Enter the BBS Name       : \");\n  entry.name = bin.input_text(\"\", 50);\n  bout.nl();\n  bout.outstr(\"|#9Enter BBS Type (ex. WWIV): \");\n  entry.software = bin.input_upper(\"WWIV\", 12);\n  bout.nl();\n  bout.outstr(\"|#9Enter the BBS Location   : \");\n  entry.location = bin.input_upper(\"\", 50);\n  bout.nl();\n  bout.outstr(\"|#9Enter the Sysop Name     : \");\n  entry.sysop_name = bin.input_text(\"\", 50);\n  bout.nl(2);\n  bout.outstr(\"|#5Is this information correct? \");\n  if (bin.yesno()) {\n    entries.emplace_back(entry);\n    bout.outstr(\"\\r\\n|#3This entry will be added to BBS list.\\r\\n\");\n    return true;\n  }\n  return false;\n}\n\nstatic char ShowBBSListMenuAndGetChoice() {\n  bout.nl();\n  if (so()) {\n    bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) [|#2BBS list|#9]: (|#1R|#9)ead, (|#1A|#9)dd,\"\n              \" (|#1D|#9)elete, (|#1N|#9)et : \");\n    return onek(\"QRNAD\");\n  }\n  bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) [|#2BBS list|#9] (|#1R|#9)ead, (|#1A|#9)dd, (|#1N|#9)et : \");\n  return onek(\"QRNA\");\n}\n\nvoid add_bbslist() {\n  std::vector<BbsListEntry> entries;\n  LoadFromJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n  if (a()->sess().effective_sl() <= 10) {\n    bout.outstr(\"\\r\\n\\nYou must be a validated user to add to the BBS list.\\r\\n\\n\");\n    return;\n  }\n  if (a()->user()->restrict_automessage()) {\n    bout.outstr(\"\\r\\n\\nYou can not add to the BBS list.\\r\\n\\n\\n\");\n    return;\n  }\n  if (AddBBSListEntry(entries)) {\n    SaveToJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n  }\n}\n\nvoid read_bbslist() {\n  std::vector<BbsListEntry> entries;\n  LoadFromJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n  if (entries.empty()) {\n    ConvertLegacyList(a()->config()->gfilesdir(), BBSLIST_MSG, entries);\n    SaveToJSON(a()->config()->datadir(), BBSLIST_JSON, entries);\n  }\n  ReadBBSList(entries);\n}\n\nvoid BBSList() {\n  while (!a()->sess().hangup()) {\n    const auto ch = ShowBBSListMenuAndGetChoice();\n    switch (ch) {\n    case 'A': {\n      add_bbslist();\n    } break;\n    case 'D': {\n      delete_bbslist();\n    } break;\n    case 'N':\n      query_print_net_listing(false);\n      break;\n    case 'R': {\n      read_bbslist();\n    } break;\n    case 'Q':\n      return;\n    default: break;\n    }\n  }\n}\n\n} // namespace wwiv::bbslist\n"
  },
  {
    "path": "bbs/bbslist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2014-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BBSLIST_H\n#define INCLUDED_BBS_BBSLIST_H\n\n#include <filesystem>\n#include <string>\n#include <vector>\n\nnamespace wwiv::bbslist {\n\nstruct BbsListAddress {\n  std::string type;\n  std::string address;\n};\n\nstruct BbsListEntry {\n  int id{0};\n  std::string name;\n  std::string software;\n  std::string sysop_name;\n  std::string location;\n  std::vector<BbsListAddress> addresses;\n};\n\nbool LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                  std::vector<BbsListEntry>& entries);\n\nbool SaveToJSON(const std::filesystem::path& dir, const std::string& filename, \n                const std::vector<BbsListEntry>& entries);\n\nvoid read_bbslist();\nvoid delete_bbslist();\nvoid add_bbslist();\nvoid BBSList();\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "bbs/bbslist_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbslist.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"sdk/menus/menu_set.h\"\n\n#include \"gtest/gtest.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::bbslist;\n\nstatic std::string FindAddressByType(const BbsListEntry& entry, const std::string& type) {\n  for (const auto& a : entry.addresses) {\n    if (type == a.type) {\n      return a.address;\n    }\n  }\n  return {};\n}\n\nclass NewBbsListTest : public testing::Test {\nprotected:\n  void SetUp() override { helper.SetUp(); }\n  std::string dir() { return helper.files().TempDir().string(); }\n  std::filesystem::path CreateTempFile(const std::string& name, const std::string& contents) {\n    return helper.files().CreateTempFile(name, contents);\n  }\n  BbsHelper helper{};\n};\n\nTEST_F(NewBbsListTest, NoFile) {\n  std::vector<BbsListEntry> entries;\n  ASSERT_FALSE(LoadFromJSON(dir(), \"bbslist.json\", entries));\n}\n\nTEST_F(NewBbsListTest, SingleItem_NoAddress) {\n  const std::string json = R\"({ \"bbslist\": [ { \"name\": \"n1\", \"software\": \"s1\" } ] })\";\n  this->CreateTempFile(\"bbslist.json\", json);\n   \n  std::vector<BbsListEntry> entries;\n  ASSERT_TRUE(LoadFromJSON(dir(), \"bbslist.json\", entries));\n\n  ASSERT_EQ(1u, entries.size());\n  EXPECT_EQ(\"n1\", entries[0].name);\n  EXPECT_EQ(\"s1\", entries[0].software);\n}\n\nTEST_F(NewBbsListTest, SingleItem_Address) {\n  const std::string json = R\"(\n    { \"bbslist\":\n      [ { \"name\": \"n1\", \"software\": \"s1\", \n      \"addresses\": [ \n        { \"type\":\"telnet\", \"address\":\"example.com\" } \n        ] } \n      ] \n    } )\";\n  this->CreateTempFile(\"bbslist.json\", json);\n\n  std::vector<BbsListEntry> entries;\n  EXPECT_TRUE(LoadFromJSON(dir(), \"bbslist.json\", entries));\n\n  EXPECT_EQ(1u, entries.size());\n  const auto& e = entries[0];\n  EXPECT_EQ(\"n1\", e.name);\n  EXPECT_EQ(\"s1\", e.software);\n  EXPECT_EQ(1u, e.addresses.size());\n  EXPECT_EQ(\"example.com\", FindAddressByType(e, \"telnet\"));\n}\n\nTEST_F(NewBbsListTest, MultipleEntries) {\n  const std::string json =\n      R\"({ \"bbslist\": [\n      { \"name\": \"n1\", \"software\": \"s\", \"addresses\": [ { \"type\":\"telnet\", \"address\":\"example.com\" } ] }, \n      { \"name\": \"n2\", \"software\": \"s\", \"addresses\": [ { \"type\":\"ssh\", \"address\":\"foobar.com\" } ] }, \n      { \"name\": \"n3\", \"software\": \"s\", \"addresses\": [ { \"type\":\"modem\", \"address\":\"415-000-0000\" } ] } \n      ] \n    })\";\n  this->CreateTempFile(\"bbslist.json\", json);\n\n  std::vector<BbsListEntry> entries;\n  ASSERT_TRUE(LoadFromJSON(dir(), \"bbslist.json\", entries));\n  \n  EXPECT_EQ(3u, entries.size());\n  EXPECT_EQ(\"n1\", entries[0].name);\n  EXPECT_EQ(\"n2\", entries[1].name);\n  EXPECT_EQ(\"n3\", entries[2].name);\n  EXPECT_EQ(\"s\", entries[0].software);\n  EXPECT_EQ(\"s\", entries[1].software);\n  EXPECT_EQ(\"s\", entries[2].software);\n  EXPECT_EQ(1u, entries[0].addresses.size());\n  EXPECT_EQ(\"example.com\", FindAddressByType(entries[0], \"telnet\"));\n  EXPECT_EQ(\"foobar.com\", FindAddressByType(entries[1], \"ssh\"));\n  EXPECT_EQ(\"415-000-0000\", FindAddressByType(entries[2], \"modem\"));\n}\n\nTEST_F(NewBbsListTest, WriteSingleEntry) {\n  std::vector<BbsListEntry> entries;\n  {\n    BbsListEntry e{};\n    e.name = \"n1\";\n    e.software = \"SOFT\";\n    e.addresses.push_back({\"ssh\", \"example.com\"});\n    entries.emplace_back(e);\n  }\n\n  ASSERT_TRUE(SaveToJSON(dir(), \"bbslist.json\", entries));\n  std::vector<BbsListEntry> new_entries;\n  ASSERT_TRUE(LoadFromJSON(dir(), \"bbslist.json\", new_entries));\n  EXPECT_EQ(1u, new_entries.size());\n  const auto& e = new_entries.at(0);\n  EXPECT_EQ(\"n1\", e.name);\n  EXPECT_EQ(\"SOFT\", e.software);\n  EXPECT_EQ(1u, new_entries.at(0).addresses.size());\n  const auto a = new_entries.at(0).addresses.cbegin();\n  EXPECT_EQ(\"ssh\", a->type);\n  EXPECT_EQ(\"example.com\", a->address);\n}\n"
  },
  {
    "path": "bbs/bbsovl1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbsovl1.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/email.h\"\n#include \"bbs/external_edit.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"common/workspace.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n//////////////////////////////////////////////////////////////////////////////\n// Implementation\n\n/**\n * Displays a horizontal bar of nSize characters in nColor\n * @param width Length of the horizontal bar to display\n * @param color Color of the horizontal bar to display\n */\nvoid DisplayHorizontalBar(int width, int color) {\n  const auto ch = (okansi()) ? '\\xC4' : '-';\n  bout.ansic(color);\n  bout.outstr(std::string(width, ch));\n  bout.nl();\n}\n\n/**\n * Displays some basic user statistics for the current user.\n */\nvoid YourInfo() {\n  if (bout.printfile(\"yourinfo\")) {\n    // We displayed the new file based yourinfo, exit here.\n    return;\n  }\n  // Legacy yourinfo used.\n  LOG(WARNING) << \"Legacy yourinfo used, please add yourinfo.msg to gfiles directory.\";\n  bout.cls();\n  bout.litebar(\"Your User Information\");\n  bout.nl();\n  bout.print(\"|#9Your name      : |#2{}\\r\\n\", a()->user()->name_and_number());\n  bout.print(\"|#9Phone number   : |#2{}\\r\\n\", a()->user()->voice_phone());\n  if (a()->user()->email_waiting() > 0) {\n    bout.print(\"|#9Mail Waiting   : |#2{}\\r\\n\", a()->user()->email_waiting());\n  }\n  bout.print(\"|#9Security Level : |#2{}\\r\\n\", a()->user()->sl());\n  if (a()->sess().effective_sl() != a()->user()->sl()) {\n    bout.print(\"|#1 (temporarily |#2{}|#1)\", a()->sess().effective_sl());\n  }\n  bout.nl();\n  bout.print(\"|#9Transfer SL    : |#2{}\\r\\n\", a()->user()->dsl());\n  bout.print(\"|#9Date Last On   : |#2{}\\r\\n\", a()->user()->laston());\n  bout.print(\"|#9Times on       : |#2{}\\r\\n\", a()->user()->logons());\n  bout.print(\"|#9On today       : |#2{}\\r\\n\", a()->user()->ontoday());\n  bout.print(\"|#9Messages posted: |#2{}\\r\\n\", a()->user()->messages_posted());\n  const auto total_mail_sent =\n      a()->user()->email_sent() + a()->user()->feedback_sent() + a()->user()->email_net();\n  bout.print(\"|#9E-mail sent    : |#2{}\\r\\n\", total_mail_sent);\n  const auto minutes_used =\n      duration_cast<minutes>(a()->user()->timeon()  + a()->sess().duration_used_this_session()).count();\n  bout.print(\"|#9Time spent on  : |#2{} |#9Minutes\\r\\n\", minutes_used);\n\n  // Transfer Area Statistics\n  bout.print(\"|#9Uploads        : |#2{}|#9k in|#2 {} |#9files\\r\\n\", a()->user()->uk(),\n             a()->user()->uploaded());\n  bout.print(\"|#9Downloads      : |#2{}|#9k in|#2 {} |#9files\\r\\n\", a()->user()->dk(),\n             a()->user()->downloaded());\n  bout.print(\"|#9Transfer Ratio : |#2{}\\r\\n\", a()->user()->ratio());\n  bout.nl();\n  bout.pausescr();\n}\n\n/**\n * Gets the maximum number of lines allowed for a post by the current user.\n * @return The maximum message length in lines\n */\nint GetMaxMessageLinesAllowed() {\n  if (so()) {\n    return 120;\n  }\n  return cs() ? 100 : 80;\n}\n\n/**\n * Allows user to upload a post.\n */\nvoid upload_post() {\n  File file(FilePath(a()->sess().dirs().temp_directory(), INPUT_MSG));\n  const auto max_bytes = 250 * static_cast<File::size_type>(GetMaxMessageLinesAllowed());\n\n  bout.print(\"\\r\\nYou may now upload a message, max bytes: {}\\r\\n\\r\\n\", max_bytes);\n  auto i = 0;\n  receive_file(file.full_pathname(), &i, INPUT_MSG, -1);\n  if (file.Open(File::modeReadOnly | File::modeBinary)) {\n    const auto file_size = file.length();\n    if (file_size > max_bytes) {\n      bout.outstr(\"\\r\\n|#6Sorry, your message is too long.  Not saved.\\r\\n\\n\");\n      file.Close();\n      File::Remove(file.path());\n    } else {\n      file.Close();\n      use_workspace = true;\n      bout.outstr(\"\\r\\n|#7* |#1Message uploaded.  The next post or email will contain that text.\\r\\n\\n\");\n    }\n  } else {\n    bout.outstr(\"\\r\\n|#3Nothing saved.\\r\\n\\n\");\n  }\n}\n\n/**\n * High-level function for sending email.\n */\nvoid send_email() {\n  write_inst(INST_LOC_EMAIL, 0, INST_FLAGS_NONE);\n  a()->sess().clear_irt();\n\n  bout.outstr(\"\\r\\n\\n|#9Enter user name or number:\\r\\n:\");\n  const auto username = fixup_user_entered_email(bin.input_text(75));\n\n  auto [user_number, system_number] = parse_email_info(username);\n  clear_quotes(a()->sess());\n  if (user_number || system_number) {\n    email(\"\", user_number, system_number, false, 0);\n  }\n}\n\n/**\n * High-level function for selecting conference type to edit.\n */\nvoid edit_confs() {\n  if (!ValidateSysopPassword()) {\n    return;\n  }\n\n  while (!a()->sess().hangup()) {\n    bout.cls();\n    bout.litebar(\"Conference Editor\");\n    bout.outstr(\"|#5Edit Which Conferences:\\r\\n\\n\");\n    bout.outstr(\"|#21|#9)|#1 Subs\\r\\n\");\n    bout.outstr(\"|#22|#9)|#1 Dirs\\r\\n\");\n    bout.outstr(\"\\r\\n|#9Select [|#21|#9,|#22|#9,|#2Q|#9]: \");\n    const auto ch = onek(\"Q12\", true);\n    switch (ch) {\n    case '1':\n      conf_edit(a()->all_confs().subs_conf());\n      break;\n    case '2':\n      conf_edit(a()->all_confs().dirs_conf());\n      break;\n    case 'Q':\n      return;\n    }\n    a()->CheckForHangup();\n  }\n}\n\n/**\n * Sends Feedback to the SysOp.  If  bNewUserFeedback is true then this is\n * new user feedback, otherwise it is \"normal\" feedback.\n * The user can choose to email anyone listed.\n * Users with a()->sess().user_num() < 10 who have sysop privs will be listed, so\n * this user can select which sysop to leave feedback to.\n */\nvoid feedback(bool bNewUserFeedback) {\n  int i;\n  char onek_str[20], ch;\n\n  clear_quotes(a()->sess());\n\n  if (bNewUserFeedback) {\n    const auto title =\n        fmt::format(\"|#1Validation Feedback (|#6{}|#2 slots left|#1)\",\n                     a()->config()->max_users() - a()->status_manager()->user_count());\n    // We disable the fsed here since it was hanging on some systems.  Not sure why\n    // but it's better to be safe -- Rushfan 2003-12-04\n    email(title, 1, 0, true, 0, false);\n    return;\n  }\n  if (a()->user()->guest_user()) {\n    a()->status_manager()->reload_status();\n    email(\"Guest Account Feedback\", 1, 0, true, 0, true);\n    return;\n  }\n  const int num_user_records = a()->users()->num_user_records();\n  int i1 = 0;\n\n  for (i = 2; i < 10 && i < num_user_records; i++) {\n    if (const auto user = a()->users()->readuser(i, UserManager::mask::non_deleted); \n      user->sl() == 255 || a()->config()->sl(user->sl()).ability & ability_cosysop) {\n      i1++;\n    }\n  }\n\n  if (!i1) {\n    i = 1;\n  } else {\n    onek_str[0] = '\\0';\n    i1 = 0;\n    bout.nl();\n    for (i = 1; (i < 10 && i < num_user_records); i++) {\n      User user;\n      a()->users()->readuser(&user, i);\n      if ((user.sl() == 255 || a()->config()->sl(user.sl()).ability & ability_cosysop) &&\n          !user.deleted()) {\n        bout.print(\"|#2{}|#7)|#1 {}\\r\\n\", i, a()->names()->UserName(i));\n        onek_str[i1++] = static_cast<char>('0' + i);\n      }\n    }\n    const auto key_quit = bout.lang().value(\"KEY_QUIT\", \"Q\").front();\n    onek_str[i1++] = key_quit;\n    onek_str[i1] = '\\0';\n    bout.nl();\n    bout.print(\"|#1Feedback to ({}): \", onek_str);\n    ch = onek(onek_str, true);\n    if (ch == key_quit) {\n      return;\n    }\n    bout.nl();\n    i = ch - '0';\n  }\n\n  email(\"|#1Feedback\", static_cast<uint16_t>(i), 0, false, 0, true);\n}\n\n/**\n * Allows editing of ASCII text files. Must have an external editor defined,\n * and toggled for use in defaults.\n */\nvoid text_edit() {\n  bout.nl();\n  bout.outstr(\"|#9Enter Filename: \");\n  const auto filename = bin.input_filename(12);\n  if (filename.find(\".log\") != std::string::npos || !okfn(filename)) {\n    return;\n  }\n  sysoplog(fmt::format(\"@ Edited: {}\", filename));\n  if (ok_external_fsed()) {\n    fsed_text_edit(filename, a()->config()->gfilesdir(), 500, MSGED_FLAG_NO_TAGLINE);\n  }\n}\n"
  },
  {
    "path": "bbs/bbsovl1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BBSOVL1_H__\n#define __INCLUDED_BBS_BBSOVL1_H__\n\nvoid DisplayHorizontalBar(int nSize, int nColor);\nvoid YourInfo();\nint  GetMaxMessageLinesAllowed();\nvoid upload_post();\nvoid send_email();\nvoid edit_confs();\nvoid feedback(bool bNewUserFeedback);\nvoid text_edit();\n\n#endif  // __INCLUDED_BBS_BBSOVL1_H__"
  },
  {
    "path": "bbs/bbsovl2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbsovl2.h\"\n#include \"sdk/arword.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/confutil.h\"\n#include \"common/output.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/names.h\"\n#include <chrono>\n#include <string>\n#include \"core/log.h\"\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\n\n// Allows local-only editing of some of the user data in a shadowized window.\nvoid OnlineUserEditor() {\n  auto& u = *a()->user();\n\n  bout.localIO()->savescreen();\n  a()->DisplaySysopWorkingIndicator(true);\n  const auto wx = 5;\n  const auto wy = 3;\n  bout.localIO()->MakeLocalWindow(wx, wy - 2, 70, 16 + 2);\n  const auto bar = StrCat(\"\\xC3\", std::string(70 - wx + 3, '\\xC4'), \"\\xB4\");\n  bout.localIO()->PutsXY(wx, wy, bar);\n  bout.localIO()->PutsXY(wx, wy + 4, bar);\n  bout.localIO()->PutsXY(wx, wy + 7, bar);\n  bout.localIO()->PutsXY(wx, wy + 11, bar);\n  bout.localIO()->PutsXY(wx, wy + 13, bar);\n  if (*a()->sess().qsc > 999) {\n    *a()->sess().qsc = 999;\n  }\n  std::string restrict;\n  for (int i = 0; i <= 15; i++) {\n    restrict.push_back(u.has_restrict(1 << i) ? restrict_string[i] : ' ');\n  }\n\n  // heading\n  const auto s = StrCat(\"[\", a()->user()->name_and_number(), \"]\");\n  bout.localIO()->PutsXYA(wx + 1, wy - 1, 31, fmt::format(\"{:<30}{:>37}\",\" WWIV User Editor\", s));\n\n  bout.localIO()->PutsXYA(wx + 2, wy + 1, 3, StrCat(\"Security Level(SL): \", u.sl()));\n  auto ar = word_to_arstr(u.ar_int(), \"\");\n  bout.localIO()->PutsXYA(wx + 36, wy + 1, 3, StrCat(\"  Message AR: \", ar));\n  bout.localIO()->PutsXYA(wx + 2, wy + 2, 3, StrCat(\"DL Sec. Level(DSL): \", u.dsl()));\n  auto dar = word_to_arstr(u.dar_int(), \"\");\n  bout.localIO()->PutsXYA(wx + 36, wy + 2, 3, StrCat(\" Download AR: \", dar));\n  bout.localIO()->PutsXYA(wx + 2, wy + 3, 3, StrCat(\"   User Exemptions: \", u.exempt()));\n  bout.localIO()->PutsXYA(wx + 36, wy + 3, 3, StrCat(\"Restrictions: \", restrict));\n  bout.localIO()->PutsXYA(wx + 2, wy + 5, 3, StrCat(\"         Sysop Sub: \", *a()->sess().qsc));\n  bout.localIO()->PutsXYA(wx + 36, wy + 5, 3, StrCat(\"   Time Bank: \", u.banktime_minutes()));\n  bout.localIO()->PutsXYA(wx + 2, wy + 6, 3, StrCat(\"        Ass Points: \", u.ass_points()));\n  bout.localIO()->PutsXYA(wx + 36, wy + 6, 3, StrCat(\" Gold Points: \", u.gold()));\n  bout.localIO()->PutsXYA(wx + 2, wy + 8, 3, StrCat(\"       KB Uploaded: \", u.uk()));\n  bout.localIO()->PutsXYA(wx + 35, wy + 8, 3, StrCat(\"KB Downloaded: \", u.dk()));\n  bout.localIO()->PutsXYA(wx + 2, wy + 9, 3, StrCat(\"    Files Uploaded: \", u.uploaded()));\n  bout.localIO()->PutsXYA(wx + 32, wy + 9, 3, StrCat(\"Files Downloaded: \", u.downloaded()));\n  bout.localIO()->PutsXYA(wx + 2, wy + 10, 3, StrCat(\"   Messages Posted: \", u.messages_posted()));\n  bout.localIO()->PutsXYA(wx + 32, wy + 10, 3, StrCat(\"Number of Logons: \", u.logons()));\n  bout.localIO()->PutsXYA(wx + 2, wy + 12, 3, StrCat(\"Note: \", u.note()));\n  bout.localIO()->PutsXYA(wx + 1, wy + 14, 31,\n                          \"    (ENTER) Next Field   (UP-ARROW) Previous Field    (ESC) Exit    \");\n  bout.curatr(3);\n  bool done = false;\n  int cp = 0;\n  while (!done) {\n    auto rc = EditlineResult::ABORTED;\n    switch (cp) {\n    case 0: {\n      bout.localIO()->GotoXY(wx + 22, wy + 1);\n      auto sl = std::to_string(u.sl());\n      rc = bout.localIO()->EditLine(sl, 3, AllowedKeys::NUM_ONLY);\n      u.sl(to_number<unsigned int>(sl));\n      bout.localIO()->Format(\"{:3}\", u.sl());\n    } break;\n    case 1: {\n      bout.localIO()->GotoXY(wx + 50, wy + 1);\n      rc = bout.localIO()->EditLine(ar, 16, AllowedKeys::SET, \"ABCDEFGHIJKLMNOP \");\n      u.ar_int(str_to_arword(ar));\n    } break;\n    case 2: {\n      bout.localIO()->GotoXY(wx + 22, wy + 2);\n      auto dsl = std::to_string(u.dsl());\n      rc = bout.localIO()->EditLine(dsl, 3, AllowedKeys::NUM_ONLY);\n      u.dsl(to_number<int>(dsl));\n      bout.localIO()->Format(\"{:3}\", u.dsl());\n      } break;\n    case 3: {\n      bout.localIO()->GotoXY(wx + 50, wy + 2);\n\n      rc = bout.localIO()->EditLine(dar, 16, AllowedKeys::SET, \"ABCDEFGHIJKLMNOP \");\n      u.dar_int(str_to_arword(dar));\n    } break;\n    case 4: {\n      bout.localIO()->GotoXY(wx + 22, wy + 3);\n      auto exempt = std::to_string(u.exempt());\n      rc = bout.localIO()->EditLine(exempt, 3, AllowedKeys::NUM_ONLY);\n      u.exempt(to_number<int>(exempt));\n      bout.localIO()->Format(\"{:3}\", exempt);\n    } break;\n    case 5: {\n      bout.localIO()->GotoXY(wx + 50, wy + 3);\n      rc = bout.localIO()->EditLine(restrict, 16, AllowedKeys::SET, restrict_string);\n      u.restriction(0);\n      for (int i = 0; i <= 15; i++) {\n        if (restrict[i] != SPACE) {\n          u.set_restrict(1 << i);\n        }\n      }\n    } break;\n    case 6: {\n      bout.localIO()->GotoXY(wx + 22, wy + 5);\n      auto sysopsub = std::to_string(*a()->sess().qsc);\n      rc = bout.localIO()->EditLine(sysopsub, 3, AllowedKeys::NUM_ONLY);\n      *a()->sess().qsc = to_number<uint32_t>(sysopsub);\n      bout.localIO()->Format(\"{:3}\", sysopsub);\n    } break;\n    case 7: {\n      bout.localIO()->GotoXY(wx + 50, wy + 5);\n      auto banktime = std::to_string(u.banktime_minutes());\n      rc = bout.localIO()->EditLine(banktime, 5, AllowedKeys::NUM_ONLY);\n      u.banktime_minutes(to_number<uint16_t>(banktime));\n      bout.localIO()->Format(\"{:5}\", banktime);\n    } break;\n    case 8: {\n      bout.localIO()->GotoXY(wx + 22, wy + 6);\n      auto ass = std::to_string(u.ass_points());\n      rc = bout.localIO()->EditLine(ass, 5, AllowedKeys::NUM_ONLY);\n      u.ass_points(to_number<int>(ass));\n      bout.localIO()->Format(\"{:5}\", ass);\n    } break;\n    case 9: {\n      bout.localIO()->GotoXY(wx + 50, wy + 6);\n      auto gold = std::to_string(u.gold());\n      rc = bout.localIO()->EditLine(gold, 5, AllowedKeys::NUM_ONLY);\n      u.gold(static_cast<float>(atof(gold.c_str())));\n      bout.localIO()->Format(\"{:5}\", fmt::sprintf(\"%7.2f\", u.gold()));\n    } break;\n    case 10: {\n      bout.localIO()->GotoXY(wx + 22, wy + 8);\n      auto uk = std::to_string(u.uk());\n      rc = bout.localIO()->EditLine(uk, 7, AllowedKeys::NUM_ONLY);\n      u.set_uk(to_number<uint32_t>(uk));\n      bout.localIO()->Format(\"{:7}\", uk);\n    } break;\n    case 11: {\n      bout.localIO()->GotoXY(wx + 50, wy + 8);\n      auto dk = std::to_string(u.dk());\n      rc = bout.localIO()->EditLine(dk, 7, AllowedKeys::NUM_ONLY);\n      u.set_dk(to_number<uint32_t>(dk));\n      bout.localIO()->Format(\"{:7}\", dk);\n    } break;\n    case 12: {\n      bout.localIO()->GotoXY(wx + 22, wy + 9);\n      auto up = std::to_string(u.uploaded());\n      rc = bout.localIO()->EditLine(up, 5, AllowedKeys::NUM_ONLY);\n      u.uploaded(to_number<int>(up));\n      bout.localIO()->Format(\"{:5}\", up);\n    } break;\n    case 13: {\n      bout.localIO()->GotoXY(wx + 50, wy + 9);\n      auto down = std::to_string(u.downloaded());\n      rc = bout.localIO()->EditLine(down, 5, AllowedKeys::NUM_ONLY);\n      u.downloaded(to_number<int>(down));\n      bout.localIO()->Format(\"{:5}\", down);\n    } break;\n    case 14: {\n      bout.localIO()->GotoXY(wx + 22, wy + 10);\n      auto posts = std::to_string(u.messages_posted());\n      rc = bout.localIO()->EditLine(posts, 5, AllowedKeys::NUM_ONLY);\n      u.messages_posted(to_number<int>(posts));\n      bout.localIO()->Format(\"{:5}\", posts);\n    } break;\n    case 15: {\n      bout.localIO()->GotoXY(wx + 50, wy + 10);\n      auto logons = std::to_string(u.logons());\n      rc = bout.localIO()->EditLine(logons, 5, AllowedKeys::NUM_ONLY);\n      u.logons(to_number<int>(logons));\n      bout.localIO()->Format(\"{:5}\",u.logons());\n    } break;\n    case 16: {\n      bout.localIO()->GotoXY(wx + 8, wy + 12);\n      auto note = u.note();\n      rc = bout.localIO()->EditLine(note, 60, AllowedKeys::ALL);\n      u.note(StringTrimEnd(note));\n    } break;\n    default: {\n      LOG(ERROR) << \"Unknown case: \" << cp;\n      rc = EditlineResult::ABORTED;\n    } break;\n    }\n    switch (rc) {\n    case EditlineResult::ABORTED:\n      done = true;\n      break;\n    case EditlineResult::DONE:\n      done = true;\n      break;\n    case EditlineResult::NEXT:\n      cp = (cp + 1) % 17;\n      break;\n    case EditlineResult::PREV:\n      cp--;\n      if (cp < 0) {\n        cp = 16;\n      }\n      break;\n    default:\n      done = true;\n    }\n  }\n  bout.localIO()->restorescreen();\n  a()->reset_effective_sl();\n  changedsl();\n  a()->DisplaySysopWorkingIndicator(false);\n}\n\nvoid BackPrint(const std::string& strText, int nColorCode, int nCharDelay, int nStringDelay) {\n  bout.back_outstr(strText, nColorCode, milliseconds(nCharDelay), milliseconds(nStringDelay));\n}\n\nvoid SpinPuts(const std::string& strText, int color) {\n  bout.spin_outstr(strText, color);\n}\n"
  },
  {
    "path": "bbs/bbsovl2.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BBSOVL2_H__\n#define __INCLUDED_BBS_BBSOVL2_H__\n\n#include <string>\n\nvoid OnlineUserEditor();\nvoid BackPrint(const std::string& text, int nColorCode = 6, int nCharDelay = 20, int nStringDelay = 1000);\nvoid SpinPuts(const std::string& text, int color);\n\n#endif  // __INCLUDED_BBS_BBSOVL2_H__"
  },
  {
    "path": "bbs/bbsovl3.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbsovl3.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/output.h\"\n#include \"local_io/keycodes.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\n\nbool do_sysop_command(int nCommandID) {\n  unsigned int nKeyStroke;\n  bool bNeedToRedraw = false;\n\n  switch (nCommandID) {\n  // Commands that cause screen to need to be redrawn go here\n  case COMMAND_F1:\n  case COMMAND_CF1:\n  case COMMAND_CF9:\n  case COMMAND_F10:\n  case COMMAND_CF10:\n    bNeedToRedraw = true;\n    nKeyStroke = nCommandID - 256;\n    break;\n\n  // Commands that don't change the screen around\n  case COMMAND_SF1:\n  case COMMAND_F2:\n  case COMMAND_SF2:\n  case COMMAND_CF2:\n  case COMMAND_F3:\n  case COMMAND_SF3:\n  case COMMAND_CF3:\n  case COMMAND_F4:\n  case COMMAND_SF4:\n  case COMMAND_CF4:\n  case COMMAND_F5:\n  case COMMAND_SF5:\n  case COMMAND_CF5:\n  case COMMAND_F6:\n  case COMMAND_SF6:\n  case COMMAND_CF6:\n  case COMMAND_F7:\n  case COMMAND_SF7:\n  case COMMAND_CF7:\n  case COMMAND_F8:\n  case COMMAND_SF8:\n  case COMMAND_CF8:\n  case COMMAND_F9:\n  case COMMAND_SF9:\n  case COMMAND_SF10:\n    bNeedToRedraw = false;\n    nKeyStroke = nCommandID - 256;\n    break;\n\n  default:\n    nKeyStroke = 0;\n    break;\n  }\n\n  if (nKeyStroke) {\n    if (bNeedToRedraw) {\n      bout.cls();\n    }\n\n    a()->handle_sysop_key(static_cast<uint8_t>(nKeyStroke));\n\n    if (bNeedToRedraw) {\n      bout.cls();\n    }\n  }\n  return bNeedToRedraw;\n}\n\nvoid ListAllColors() {\n  bout.nl();\n  for (int i = 0; i < 128; i++) {\n    if ((i % 26) == 0) {\n      bout.nl();\n    }\n    bout.setc(i);\n    bout.printf(\"%3d\", i);\n  }\n  bout.ansic(0);\n  bout.nl();\n}\n"
  },
  {
    "path": "bbs/bbsovl3.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BBSOVL3_H__\n#define __INCLUDED_BBS_BBSOVL3_H__\n\n#include <string>\n\nbool do_sysop_command(int command);\nvoid ListAllColors();\n\n\n#endif  // __INCLUDED_BBS_BBSOVL3_H__\n"
  },
  {
    "path": "bbs/bbsutl.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbsutl.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/interpret.h\"\n#include \"bbs/utility.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include <chrono>\n#include <string>\n\nusing std::chrono::seconds;\nusing std::chrono::steady_clock;\nusing namespace wwiv::common;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\n\nbool inli(std::string* outBuffer, std::string* rollover, std::string::size_type maxlen, bool add_crlf,\n          bool allow_previous, bool two_color, bool clear_previous_line) {\n  char buffer[4096] = {0}, rollover_buffer[4096] = {0};\n  to_char_array(buffer, *outBuffer);\n  if (rollover) {\n    to_char_array(rollover_buffer, *rollover);\n  } else {\n    memset(rollover_buffer, 0, sizeof(rollover_buffer));\n  }\n  bool ret = inli(buffer, rollover_buffer, maxlen, add_crlf, allow_previous, two_color, clear_previous_line);\n  outBuffer->assign(buffer);\n  if (rollover) {\n    rollover->assign(rollover_buffer);\n  }\n  return ret;\n}\n\n// returns true if needs to keep inputting this line\nbool inli(char *buffer, char *rollover, std::string::size_type nMaxLen, bool add_crlf, bool allow_previous,\n          bool two_color, bool clear_previous_line) {\n  char rollover_buffer[255];\n\n  CHECK_NOTNULL(buffer);\n  CHECK_NOTNULL(rollover);\n  if (buffer == nullptr || rollover == nullptr) {\n    // Should never happen from previous CHECKs but makes the static\n    // analysis happy in MSVC.\n    return false;\n  }\n\n  const auto cm = a()->sess().chatting();\n\n  const auto begx = bout.wherex();\n  if (rollover[0] != 0) {\n    char* ss = rollover_buffer;\n    for (int i = 0; rollover[i]; i++) {\n      if (rollover[i] == CC || rollover[i] == CO) {\n        *ss++ = 'P' - '@';\n      } else {\n        *ss++ = rollover[i];\n      }\n      // Add a second ^P if we are working on RIP codes\n      if (rollover[i] == CO && rollover[i + 1] != CO && rollover[i - 1] != CO) {\n        *ss++ = 'P' - '@';\n      }\n    }\n    *ss = '\\0';\n    if (bin.charbufferpointer_) {\n      char szTempBuffer[255];\n      strcpy(szTempBuffer, rollover_buffer);\n      strcat(szTempBuffer, &bin.charbuffer[bin.charbufferpointer_]);\n      strcpy(&bin.charbuffer[1], szTempBuffer);\n      bin.charbufferpointer_ = 1;\n    } else {\n      strcpy(&bin.charbuffer[1], rollover_buffer);\n      bin.charbufferpointer_ = 1;\n    }\n    rollover[0] = '\\0';\n  }\n  std::string::size_type cp = 0;\n  auto done = false;\n  unsigned char ch;\n  do {\n    ch = bin.getkey();\n    if (two_color) {\n      bout.ansic(bin.IsLastKeyLocal() ? 1 : 0);\n    }\n    if (cm != chatting_t::none && a()->sess().chatting() == chatting_t::none) {\n        ch = RETURN;\n    }\n    if (ch >= SPACE) {\n      if (bout.wherex() < (a()->user()->screen_width() - 1) && cp < nMaxLen) {\n        buffer[cp++] = ch;\n        bout.outchr(ch);\n        if (bout.wherex() == (a()->user()->screen_width() - 1)) {\n          done = true;\n        }\n      } else {\n        if (bout.wherex() >= (a()->user()->screen_width() - 1)) {\n          done = true;\n        }\n      }\n    } else switch (ch) {\n      case CG:\n        break;\n      case RETURN:                            // C/R\n        buffer[cp] = '\\0';\n        done = true;\n        break;\n      case BACKSPACE:                             // Backspace\n        if (cp) {\n          if (buffer[cp - 2] == CC) {\n            cp -= 2;\n            bout.ansic(0);\n          } else {\n            if (buffer[cp - 1] == BACKSPACE) {\n              cp--;\n              bout.outchr(SPACE);\n            } else {\n              cp--;\n              bout.bs();\n            }\n          }\n        } else if (allow_previous) {\n          if (okansi()) {\n            if (clear_previous_line) {\n              bout.clear_whole_line();\n            }\n            bout.outstr(\"\\x1b[1A\");\n          } else {\n            bout.outstr(\"[*> Previous Line <*]\\r\\n\");\n          }\n          return true;\n        }\n        break;\n      case CX:                            // Ctrl-X\n        while (bout.wherex() > begx) {\n          bout.bs();\n          cp = 0;\n        }\n        bout.ansic(0);\n        break;\n      case CW:                            // Ctrl-W\n        if (cp) {\n          do {\n            if (buffer[cp - 2] == CC) {\n              cp -= 2;\n              bout.ansic(0);\n            } else if (buffer[cp - 1] == BACKSPACE) {\n              cp--;\n              bout.outchr(SPACE);\n            } else {\n              cp--;\n              bout.bs();\n            }\n          } while (cp && buffer[cp - 1] != SPACE && buffer[cp - 1] != BACKSPACE);\n        }\n        break;\n      case CN:                            // Ctrl-N\n        if (bout.wherex() && cp < nMaxLen) {\n          bout.outchr(BACKSPACE);\n          buffer[cp++] = BACKSPACE;\n        }\n        break;\n      case CP:                            // Ctrl-P\n        if (cp < nMaxLen - 1) {\n          ch = bin.getkey();\n          if (ch >= SPACE && ch <= 126) {\n            buffer[cp++] = CC;\n            buffer[cp++] = ch;\n            bout.ansic(ch - '0');\n          } else if (ch == CP && cp < nMaxLen - 2) {\n            ch = bin.getkey();\n            if (ch != CP) {\n              buffer[cp++] = CO;\n              buffer[cp++] = CO;\n              buffer[cp++] = ch;\n              bout.outchr('\\xf');\n              bout.outchr('\\xf');\n              bout.outchr(ch);\n            }\n          }\n        }\n        break;\n      case TAB: {                           // Tab\n        int charsNeeded = 5 - (cp % 5);\n        if ((cp + charsNeeded) < nMaxLen\n            && (bout.wherex() + charsNeeded) < a()->user()->screen_width()) {\n          charsNeeded = 5 - ((bout.wherex() + 1) % 5);\n          for (auto j = 0; j < charsNeeded; j++) {\n            buffer[cp++] = SPACE;\n            bout.outchr(SPACE);\n          }\n        }\n      }\n      break;\n      }\n  } while (!done && !a()->sess().hangup());\n\n  if (a()->sess().hangup()) {\n    // Caller isn't here, so we are not saving any message.\n    return false;\n  }\n\n  if (ch != RETURN) {\n    auto lastwordstart = cp - 1;\n    while (lastwordstart > 0 && buffer[lastwordstart] != SPACE && buffer[lastwordstart] != BACKSPACE) {\n      lastwordstart--;\n    }\n    if (lastwordstart > static_cast<std::string::size_type>(bout.wherex() / 2)\n        && lastwordstart != (cp - 1)) {\n      const auto lastwordlen = cp - lastwordstart - 1;\n      for (std::string::size_type j = 0; j < lastwordlen; j++) {\n        bout.outchr(BACKSPACE);\n      }\n      for (std::string::size_type j = 0; j < lastwordlen; j++) {\n        bout.outchr(SPACE);\n      }\n      for (std::string::size_type j = 0; j < lastwordlen; j++) {\n        rollover[j] = buffer[cp - lastwordlen + j];\n      }\n      rollover[lastwordlen] = '\\0';\n      cp -= lastwordlen;\n    }\n    buffer[cp++] = CA;\n    buffer[cp] = '\\0';\n  }\n  if (add_crlf) {\n    bout.nl();\n  }\n  return false;\n}\n\n\n// Returns 1 if current user has sysop access (permanent or temporary), else\n// returns 0.\nbool so() {\n  return a()->sess().effective_sl() == 255;\n}\n\n/**\n * Checks for Co-SysOp status\n * @return true if current user has limited co-sysop access (or better)\n */\nbool cs() {\n  if (so()) {\n    return true;\n  }\n\n  return (a()->config()->sl(a()->sess().effective_sl()).ability & ability_cosysop) ? true : false;\n}\n\n\n/**\n * Checks for limited Co-SysOp status\n * <em>Note: Limited co sysop status may be for this message area only.</em>\n *\n * @return true if current user has limited co-sysop access (or better)\n */\nbool lcs() {\n  if (cs()) {\n    return true;\n  }\n\n  if (a()->config()->sl(a()->sess().effective_sl()).ability & ability_limited_cosysop) {\n    if (*a()->sess().qsc == 999) {\n      return true;\n    }\n    return (*a()->sess().qsc == static_cast<uint32_t>(a()->current_user_sub().subnum)) ? true : false;\n  }\n  return false;\n}\n\n\n// Returns 1 if sysop is \"chatable\", else returns 0. Takes into account\n// current user's chat restriction (if any) and sysop high and low times,\n// if any, as well as status of scroll-lock key.\nbool sysop2() {\n  if (!sysop1()) {\n    return false;\n  }\n  if (a()->user()->restrict_chat()) {\n    return false;\n  }\n  if (a()->config()->sysop_low_time() != a()->config()->sysop_high_time()) {\n    const auto m = minutes_since_midnight();\n    if (a()->config()->sysop_high_time() > a()->config()->sysop_low_time()) {\n      if (m <= a()->config()->sysop_low_time() || m >= a()->config()->sysop_high_time()) {\n        return false;\n      }\n    } else if (m <= a()->config()->sysop_low_time() && m >= a()->config()->sysop_high_time()) {\n      return false;\n    }\n  }\n  return true;\n}\n\n// Returns 1 if ANSI detected, or if local user, else returns 0. Uses the\n// cursor position interrogation ANSI sequence for remote detection.\nint check_ansi() {\n  if (!a()->sess().incom()) {\n    return 1;\n  }\n\n  if (const auto o = bin.screen_size()) {\n    const auto& ss = o.value();\n    VLOG(1) << \"Screen size: x: \" << ss.x << \"; y: \" << ss.y;\n  } else {\n    LOG(WARNING) << \"Unable to get screen size from terminal.\";\n  }\n\n  if (const auto pos = bin.remoteIO()->screen_position()) {\n    return 1;\n  }\n\n  return 0;\n}\n\nstd::string YesNoString(bool bYesNo) {\n  return bYesNo ? \"Yes\" : \"No\";\n}\n\nvoid *BbsAllocA(size_t size) {\n  auto* p = calloc(size + 1, 1);\n  CHECK_NOTNULL(p);\n  return p;\n}\n"
  },
  {
    "path": "bbs/bbsutl.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BBSUTL_H__\n#define __INCLUDED_BBS_BBSUTL_H__\n\n#include \"common/input.h\"\n#include <string>\n\nbool inli(std::string* outBuffer, std::string* rollover, std::string::size_type maxlen, bool add_crlf = true,\n  bool bAllowPrevious = false, bool two_color_chatmode = false, bool clear_previous_line = false);\nbool inli(char *buffer, char *rollover, std::string::size_type maxlen, bool add_crlf = true,\n  bool allow_previous = false, bool two_color = false, bool clear_previous_line = false);\nbool so();\nbool cs();\nbool lcs();\nbool sysop2();\nint  check_ansi();\nstd::string YesNoString(bool bYesNo);\nvoid* BbsAllocA(size_t num_bytes);\n\n\n#endif  // __INCLUDED_BBS_BBSUTL_H__"
  },
  {
    "path": "bbs/bbsutl1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbsutl1.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/mmkey.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include <chrono>\n#include <filesystem>\n#include <string>\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/networks.h\"\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nstatic const size_t MAX_CONF_LINE = 4096;\n\n\n/*\n * Returns number of \"words\" in a specified string, using a specified set\n * of characters as delimiters.\n */\nstatic int wordcount(const std::string& instr, const char* delimstr) {\n  char szTempBuffer[MAX_CONF_LINE];\n  auto i = 0;\n\n  to_char_array(szTempBuffer, instr);\n  for (auto* s = strtok(szTempBuffer, delimstr); s; s = strtok(nullptr, delimstr)) {\n    i++;\n  }\n  return i;\n}\n\n/*\n * Returns pointer to string representing the nth \"word\" of a string, using\n * a specified set of characters as delimiters.\n */\nstatic std::string extractword(int ww, const std::string& instr, const char* delimstr) {\n  char buffer[MAX_CONF_LINE];\n  auto i = 0;\n\n  if (!ww) {\n    return {};\n  }\n\n  to_char_array(buffer, instr);\n  for (auto* s = strtok(buffer, delimstr); s && i++ < ww; s = strtok(nullptr, delimstr)) {\n    if (i == ww) {\n      return std::string(s);\n    }\n  }\n  return {};\n}\n\n/**\n * Filters networks by viability.\n *\n * A viable network is:\n *   (1) has system_num reachable.\n *   (2) If the network is FTN, then tries to match zone from the network.\n *\n * Returns a vector of networks and the system names identified by the email address\n * either from system_num for WWIVnet networks, or from parsing the FidoNet Address\n * out of the email address for FTN networks.\n */\nstd::vector<NetworkAndName> filter_networks(std::vector<Network>& nets,\n                                            const std::string& email, int system_num) {\n  if (nets.empty()) {\n    return {};\n  }\n\n  std::vector<NetworkAndName> viable;\n  const auto ftnadr = fido::get_address_from_single_line(email);\n  for (auto& net : nets) {\n    set_net_num(net.network_number());\n    if (const auto csne = next_system(system_num)) {\n      if (net.type == network_type_t::ftn) {\n        if (ftnadr.has_value() && net.try_load_nodelist()) {\n          if (!net.nodelist->has_zone(ftnadr->zone())) {\n            VLOG(1) << \"Skipping net known to not have zone: \" << net.name << \"; zone: \" << ftnadr->zone();\n            // This nodelist is loaded and doesn't have the zone, skip it.\n            continue;\n          }\n        }\n      }\n      viable.emplace_back(net, csne->name);\n    }\n  }\n  return viable;\n}\n\nstatic std::optional<int> query_network(const std::vector<NetworkAndName>& nets) {\n  if (nets.empty()) {\n    return std::nullopt;    \n  }\n  if (nets.size() == 1) {\n    return { nets.front().net.network_number() };\n  }\n  std::string onx{'Q'};\n  std::set<char> odc;\n  bout.nl();\n  auto nn = 1;\n  for (const auto& v : nets) {\n    set_net_num(v.net.network_number());\n    if (nn < 9) {\n      onx.push_back(static_cast<char>(nn + '0'));\n    } else {\n      odc.insert(static_cast<char>(nn / 10));\n    }\n    bout.print(\"|#2{}|#9) {} (|#1{}|#9)\\r\\n\", nn, v.net.name, v.system_name);\n    ++nn;\n  }\n  bout.outstr(\"|#2Q|#9) Quit\\r\\n\\n\");\n  bout.outstr(\"|#5(|#2Q|#5=|#1Quit|#5) Which network (number): \");\n  if (nets.size() < 9) {\n    const char ch = onek(onx);\n    if (ch == 'Q') {\n      return std::nullopt;\n    }\n    const int n = ch - '1';\n    return { wwiv::stl::at(nets, n).net.network_number() };\n  }\n  const auto mmk = mmkey(odc); \n  if (mmk == \"Q\") {\n    return std::nullopt;\n  }\n  const auto selected =  to_number<int>(mmk) - 1;\n  if (selected < 0 || selected >= wwiv::stl::size_int(nets)) {\n    return std::nullopt;\n  }\n  return {wwiv::stl::at(nets, selected).net.network_number()};\n}\n\nstatic std::tuple<uint16_t, uint16_t> parse_internet_email_info(const std::string& email) {\n  for (auto i = 0; i < wwiv::stl::size_int(a()->nets()); i++) {\n    set_net_num(i);\n    if (a()->current_net().type == network_type_t::internet) {\n      a()->net_email_name = ToStringLowerCase(email);\n      // 0 for the user, and we'll use the network.\n      return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(INTERNET_EMAIL_FAKE_OUTBOUND_NODE));\n    }\n  }\n  bout.outstr(\"Unknown user.\\r\\n\");\n  return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n}\n\nstd::tuple<uint16_t, uint16_t> parse_ftn_email_info(const std::string& email) {\n  a()->net_email_name = ToStringLowerCase(email);\n  // We don't have a network name, so need to loop through them all.\n  std::vector<Network> nets;\n  for (const auto& net : a()->nets().networks()) {\n    if (net.type == network_type_t::ftn) {\n      nets.push_back(net);\n    }\n  }\n\n  if (const auto o = query_network(filter_networks(nets, email, FTN_FAKE_OUTBOUND_NODE))) {\n    set_net_num(o.value());\n    return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(FTN_FAKE_OUTBOUND_NODE));\n  }\n  return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n}\n\nstd::tuple<uint16_t, uint16_t> parse_local_email_info(const std::string& email) {\n  if (const auto user_number = finduser1(email); user_number > 0) {\n    return std::make_tuple(static_cast<uint16_t>(user_number), static_cast<uint16_t>(0));\n  }\n  if (iequals(email, \"SYSOP\")) {\n    return std::make_tuple(static_cast<uint16_t>(1), static_cast<uint16_t>(0));\n  }\n  bout.outstr(\"Unknown user.\\r\\n\");\n  return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n}\n\n\nstd::tuple<uint16_t, uint16_t> parse_wwivnet_email_info(const std::string& email, int system_number,\n                                                        const std::string& network_name) {\n\n  auto user_number = to_number<int>(email);\n  if (user_number == 0 && email.front() == '#') {\n    user_number = to_number<int>(email.substr(1));\n  }\n\n  a()->net_email_name = ToStringLowerCase(email);\n  if (!network_name.empty()) {\n    for (auto i = 0; i < wwiv::stl::size_int(a()->nets()); i++) {\n      set_net_num(i);\n      if (iequals(network_name, a()->network_name())) {\n        if (valid_system(system_number)) {\n          if (system_number == a()->current_net().sysnum) {\n            return parse_local_email_info(email);\n          }\n          // return 0,0 since we set the net_email_name already.\n          return std::make_tuple(static_cast<uint16_t>(user_number), static_cast<uint16_t>(system_number));\n        }\n      }\n    }\n    return std::make_tuple(static_cast<uint16_t>(user_number), static_cast<uint16_t>(system_number));\n  }\n  // We don't have a network name, so need to loop through them all.\n  std::vector<Network> nets;\n  for (const auto& net : a()->nets().networks()) {\n    if (net.type == network_type_t::wwivnet) {\n      nets.push_back(net);\n    }\n  }\n\n  if (const auto o = query_network(filter_networks(nets, email, system_number))) {\n    set_net_num(o.value());\n    return std::make_tuple(static_cast<uint16_t>(user_number),\n                           static_cast<uint16_t>(system_number));\n  }\n  return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n}\n\nstd::tuple<uint16_t, uint16_t> parse_email_info(const std::string& email_address) {\n  if (email_address.empty()) {\n    return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n  }\n  \n  if (const auto atidx = email_address.rfind('@');\n    atidx != std::string::npos) {\n    if (atidx == email_address.size() - 1) {\n      // malformed email address of 1@\n      return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n    }\n    const auto email = email_address.substr(0, atidx);\n    if (isdigit(email_address.at(atidx + 1))) {\n      // We have something like \"xx @N\" where N is a digit.\n      const auto suffix = email_address.substr(atidx + 1);\n      auto system_number = to_number<int>(suffix);\n      std::string network_name;\n      if (const auto dotidx = suffix.find('.'); dotidx != std::string::npos) {\n        network_name = suffix.substr(dotidx + 1);\n        system_number = to_number<int>(suffix.substr(0, dotidx));\n      }\n\n      if (system_number == FTN_FAKE_OUTBOUND_NODE) {\n        return parse_ftn_email_info(email);\n      }\n      if (system_number == INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n        return parse_internet_email_info(email);\n      }\n      if (system_number == INTERNET_NEWS_FAKE_OUTBOUND_NODE) {\n        bout.pl(\"|#6NNTP is not supported yet.\");\n        return std::make_tuple(static_cast<uint16_t>(0), static_cast<uint16_t>(0));\n      }\n      return parse_wwivnet_email_info(email, system_number, network_name);\n    }\n    return parse_internet_email_info(email);\n  }\n  // No @, so just a local address.\n  return parse_local_email_info(email_address);\n}\n\nstd::string username_system_net_as_string(uint16_t un, const std::string& user_name, uint16_t sn,\n                                          const std::string& network_name) {\n  std::ostringstream ss;\n  if (un) {\n    ss << \"#\" << un;\n  } else {\n    ss << user_name;\n  }\n  if (sn > 0) {\n    ss << \" @\" << sn;\n  }\n  if (!network_name.empty()) {\n    ss << \".\" << network_name;\n  }\n  return ss.str();\n}\n\nstd::string username_system_net_as_string(uint16_t un, const std::string& user_name, uint16_t sn) {\n  return username_system_net_as_string(un, user_name, sn, \"\");\n}\n\n/**\n * Queries user and verifies system password.\n * @return true if the password entered is valid.\n */\nbool ValidateSysopPassword() {\n  bout.nl();\n  if (!so()) {\n    return false;\n  }\n  if (!a()->sess().incom()) {\n    return true;\n  }\n  const auto password = bin.input_password(\"|#7SY: \", 20);\n  return password == a()->config()->system_password();\n}\n\n/**\n * Hangs up the modem if user online. Whether using modem or not.\n */\nvoid hang_it_up() {\n  VLOG(1) << \"hang_it_up()\";\n  if (!a()->sess().ok_modem_stuff()) {\n    return;\n  }\n  if (!bout.remoteIO()->disconnect()) {\n    LOG(WARNING) << \"remoteIO->disconnect() returned false.\";\n  }\n  a()->Hangup();\n}\n\n/**\n * Plays a sound definition file (*.sdf) through PC speaker. SDF files\n * should reside in the gfiles dir. The only params passed to function are\n * filename and false if playback is not abortable, true if it is abortable. If no\n * extension then .SDF is appended. A full path to file may be specified to\n * override gfiles dir. Format of file is:\n *\n * <freq> <duration in ms> [pause_delay in ms]\n * 1000 1000 50\n *\n * Returns true if successful, else returns false. The pause_delay is optional and\n * is used to insert silences between tones.\n */\nbool play_sdf(const std::string& sound_filename, bool abortable) {\n  if (sound_filename.empty()) {\n    return false;\n  }\n\n  std::filesystem::path full_pathname;\n  // append gfiles directory if no path specified\n  if (sound_filename.find(File::pathSeparatorChar) == std::string::npos) {\n    full_pathname = FilePath(a()->config()->gfilesdir(), sound_filename);\n  } else {\n    full_pathname = sound_filename;\n  }\n\n  // append .SDF if no extension specified\n  if (!full_pathname.has_extension()) {\n    full_pathname.replace_extension(\".sdf\");\n  }\n\n  // Must Exist\n  if (!File::Exists(full_pathname)) {\n    return false;\n  }\n\n  // must be able to open read-only\n  TextFile soundFile(full_pathname, \"rt\");\n  if (!soundFile.IsOpen()) {\n    return false;\n  }\n\n  // scan each line, ignore lines with words<2\n  std::string soundLine;\n  while (soundFile.ReadLine(&soundLine)) {\n    if (abortable && bin.bkbhit()) {\n      break;\n    }\n    const auto nw = wordcount(soundLine, DELIMS_WHITE);\n    if (nw >= 2) {\n      const auto freq = to_number<int>(extractword(1, soundLine, DELIMS_WHITE));\n      auto dur = to_number<int>(extractword(2, soundLine, DELIMS_WHITE));\n\n      // only play if freq and duration > 0\n      if (freq > 0 && dur > 0) {\n        auto pause_delay = 0;\n        if (nw > 2) {\n          pause_delay = to_number<int>(extractword(3, soundLine, DELIMS_WHITE));\n        }\n        sound(freq, milliseconds(dur));\n        if (pause_delay > 0) {\n          sleep_for(milliseconds(pause_delay));\n        }\n      }\n    }\n  }\n\n  return true;\n}\n\n/**\n * Describes the area code as listed in regions.dat\n * @param nAreaCode The area code to describe\n */\nstd::string describe_area_code(int nAreaCode) {\n  TextFile file(FilePath(a()->config()->datadir(), REGIONS_DAT), \"rt\");\n  if (!file.IsOpen()) {\n    // Failed to open regions area code file\n    return \"\";\n  }\n\n  std::string previous;\n  std::string current;\n  while (file.ReadLine(&current)) {\n    const auto current_town = to_number<int>(current);\n    if (current_town == nAreaCode) {\n      return previous;\n    }\n    if (current_town == 0) {\n      // Only set this on values that are town names and not area codes.\n      previous = current;\n    }\n  }\n  return \"\";\n}\n\n/**\n * Describes the Town (area code + prefix) as listed in the regions file.\n * @param nAreaCode The area code to describe\n * @param nTargetTown The phone number prefix to describe\n * @return the description for the specified area code.\n */\nstd::string describe_area_code_prefix(int nAreaCode, int nTargetTown) {\n  const auto regions_dir = FilePath(a()->config()->datadir(), REGIONS_DIR);\n  const auto filename = fmt::sprintf(\"%s.%-3d\", REGIONS_DIR, nAreaCode);\n  TextFile file(FilePath(regions_dir, filename), \"rt\");\n  if (!file.IsOpen()) {\n    // Failed to open regions area code file\n    return \"\";\n  }\n\n  std::string previous;\n  std::string current;\n  while (file.ReadLine(&current)) {\n    const auto current_town = to_number<int>(current);\n    if (current_town == nTargetTown) {\n      return previous;\n    }\n    if (current_town == 0) {\n      // Only set this on values that are town names and not area codes.\n      previous = current;\n    }\n  }\n  return \"\";\n}\n"
  },
  {
    "path": "bbs/bbsutl1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_BBSUTL1_H\n#define INCLUDED_BBS_BBSUTL1_H\n\n#include \"sdk/net/net.h\"\n\n#include <string>\n#include <tuple>\n#include <vector>\n\n/**\n * Finds user_num and system number from emailAddress and sets the\n * network number as appropriate.\n *\n * @param email_address The text of the email address.\n * @return tuple of {un User Number, System Number}\n */\nstd::tuple<uint16_t, uint16_t> parse_email_info(const std::string& email_address);\n\n/**\n * @verbatim\n * Creates string of form (#un | user_name) @sn[.network_name].\n * example: Rushfan @1.rushfan or #1 @1.rushnet or #1 @1\n */\nstd::string username_system_net_as_string(uint16_t un, const std::string& user_name,\n                                          uint16_t sn, const std::string& network_name);\nstd::string username_system_net_as_string(uint16_t un, const std::string& user_name,\n                                          uint16_t sn);\n\nbool ValidateSysopPassword();\nvoid hang_it_up();\nbool play_sdf(const std::string& soundFileName, bool abortable);\nstd::string describe_area_code(int nAreaCode);\nstd::string describe_area_code_prefix(int nAreaCode, int town);\n\n/**\n * Represents a network and also system name pair.\n */\nstruct NetworkAndName {\n  NetworkAndName(wwiv::sdk::net::Network n, std::string s)\n      : net(std::move(n)), system_name(std::move(s)), n_(n) {}\n  wwiv::sdk::net::Network net;\n  std::string system_name;\n  const wwiv::sdk::net::Network& n_;\n};\n\n/**\n * Filters networks by viability.\n *\n * A viable network is:\n *   (1) has system_num reachable.\n *   (2) If the network is FTN, then tries to match zone from the network.\n *\n * Returns a vector of networks and the system names identified by the email address\n * either from system_num for WWIVnet networks, or from parsing the FidoNet Address\n * out of the email address for FTN networks.\n */\nstd::vector<NetworkAndName> filter_networks(std::vector<wwiv::sdk::net::Network>& nets,\n                                            const std::string& email, int system_num);\n\n#endif\n"
  },
  {
    "path": "bbs/bbsutl2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/filenames.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n/**\n * Returns the computer type string for computer type number num.\n *\n * @param num The computer type number for which to return the name\n *\n * @return The text describing computer type num\n */\nstd::string ctypes(int num) {\n  // The default list of computer types\n  const std::vector<std::string> default_ctypes{\n    \"IBM PC (8088)\",\n    \"IBM PS/2\",\n    \"IBM AT (80286)\",\n    \"IBM AT (80386)\",\n    \"IBM AT (80486)\",\n    \"Pentium\",\n    \"Apple 2\",\n    \"Apple Mac\",\n    \"Commodore Amiga\",\n    \"Commodore\",\n    \"Atari\",\n    \"Other\",\n  };\n\n  const IniFile iniFile(FilePath(a()->bbspath(), WWIV_INI), \"CTYPES\");\n  if (iniFile.IsOpen()) {\n    return iniFile.value<std::string>(fmt::format(\"COMP_TYPE[{}]\", num + 1));\n  }\n  if (num < 0 || num > size_int(default_ctypes)) {\n    return \"\";\n  }\n  return default_ctypes[num];\n}\n"
  },
  {
    "path": "bbs/bbsutl2.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_BBSUTL2_H__\n#define __INCLUDED_BBS_BBSUTL2_H__\n\n#include <string>\n\nstd::string ctypes(int num);\n\n#endif  // __INCLUDED_BBS_BBSUTL2_H__"
  },
  {
    "path": "bbs/bputch_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/bbs_helper.h\"\n#include \"common/output.h\"\n#include \"sdk/menus/menu_set.h\"\n#include <string>\n\nclass BPutchTest : public ::testing::Test {\nprotected:\n  void SetUp() override { helper.SetUp(); }\n\n  virtual int Puts(std::string s) {\n    auto count = 0;\n    for (const auto& c : s) {\n      count += bout.outchr(c);\n    }\n    return count;\n  }\n\n  BbsHelper helper{};\n};\n\nTEST_F(BPutchTest, SingleLetter) {\n  EXPECT_EQ(1, bout.outchr('A'));\n  EXPECT_STREQ(\"A\", helper.io()->captured().c_str());\n}\n\nTEST_F(BPutchTest, MultipleLetters) {\n  const std::string kHelloWorld = \"Hello World\\r\\n\";\n  EXPECT_EQ(wwiv::stl::ssize(kHelloWorld), Puts(kHelloWorld));\n  EXPECT_EQ(kHelloWorld, helper.io()->captured());\n}\n"
  },
  {
    "path": "bbs/bputs_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"common/output.h\"\n#include <iostream>\n#include <string>\n\nclass BPutsTest : public ::testing::Test {\nprotected:\n  void SetUp() override { helper.SetUp(); }\n\n  virtual int Puts(const std::string& s) {\n    const auto size = bout.outstr(s);\n    std::cerr << \"Puts: [\" << s << \"]; size: \" << size << \"\\r\\n\";\n    return size;\n  }\n\n  BbsHelper helper{};\n};\n\nTEST_F(BPutsTest, SingleLetter) {\n  EXPECT_EQ(1, bout.outstr(\"A\"));\n  EXPECT_STREQ(\"A\", helper.io()->captured().c_str());\n}\n\nTEST_F(BPutsTest, MultipleLetters) {\n  const std::string kHelloWorld = \"Hello World\\r\\n\";\n  EXPECT_EQ(wwiv::stl::ssize(kHelloWorld), Puts(kHelloWorld));\n  EXPECT_EQ(kHelloWorld, helper.io()->captured());\n}\n\nTEST_F(BPutsTest, SinglePipe) {\n  const std::string kPlainHelloWorld = \"Hello World\";\n  const std::string kAnsiHelloWorld = \"\\x1B[0;36;40;1mHello World\";\n  const std::string s = \"|#1Hello World\";\n  Puts(s);\n  EXPECT_EQ(kPlainHelloWorld, helper.io()->captured());\n  EXPECT_EQ(kAnsiHelloWorld, helper.io()->rcaptured());\n}\n\nTEST_F(BPutsTest, SinglePipe_WithEndLine) {\n  const std::string kPlainHelloWorld = \"Hello World\\r\\n\";\n  const std::string kAnsiHelloWorld = \"\\x1B[0;36;40;1mHello World\\r\\x1B[0;37;40m\\n\";\n  // TODO(rushfan): Our wonky linux handling adds the \\r before all \\n, however\n  // this causes deltas here. The output is OK, but just has an extra \\r\n  const std::string kAnsiHelloWorldUnix = \"\\x1B[0;36;40;1mHello World\\r\\x1B[0;37;40m\\r\\n\";\n  const std::string s = \"|#1Hello World\\r\\n\";\n  Puts(s);\n  EXPECT_EQ(kPlainHelloWorld, helper.io()->captured());\n#ifdef _WIN32\n  EXPECT_EQ(kAnsiHelloWorld, helper.io()->rcaptured());\n#else\n  EXPECT_EQ(kAnsiHelloWorldUnix, helper.io()->rcaptured());\n#endif\n}\n\nTEST_F(BPutsTest, RepeatedPipe) {\n  const std::string kPlainHelloWorld = \"Hello World\";\n  const std::string kAnsiHelloWorld = \"\\x1B[0;36;40;1mHello World\";\n  const std::string s = \"|#1Hello |#1World\";\n  Puts(s);\n  EXPECT_EQ(kPlainHelloWorld, helper.io()->captured());\n  EXPECT_EQ(kAnsiHelloWorld, helper.io()->rcaptured());\n}\n\nTEST_F(BPutsTest, RepeatedPipe_WithEndLine) {\n  const std::string kPlainHelloWorld = \"Hello World\\r\\n\";\n  const std::string kAnsiHelloWorld = \"\\x1B[0;36;40;1mHello World\\r\\x1B[0;37;40m\\n\";\n  const std::string kAnsiHelloWorldUnix = \"\\x1B[0;36;40;1mHello World\\r\\x1B[0;37;40m\\r\\n\";\n  const std::string s = \"|#1Hello |#1World\\r\\n\";\n  Puts(s);\n  EXPECT_EQ(kPlainHelloWorld, helper.io()->captured());\n#ifdef _WIN32\n  EXPECT_EQ(kAnsiHelloWorld, helper.io()->rcaptured());\n#else\n  EXPECT_EQ(kAnsiHelloWorldUnix, helper.io()->rcaptured());\n#endif\n}\n\nTEST_F(BPutsTest, IfPipe_Yes) {\n  const std::string s1 = R\"(|{if \"user.sl >= 200\", \"|@N\", \"|@R\"})\";\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  helper.user()->sl(200);\n  helper.sess().effective_sl(200);\n  bout.outstr(s1);\n  EXPECT_EQ(\"Rushfan\", helper.io()->captured());\n}\n\nTEST_F(BPutsTest, IfPipe_No) {\n  const std::string s1 = R\"(|{if \"user.sl >= 200\", \"|@N\", \"|@R\"})\";\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  helper.user()->sl(100);\n  helper.sess().effective_sl(100);\n  bout.outstr(s1);\n  EXPECT_EQ(\"RealName\", helper.io()->captured());\n}\n\nTEST_F(BPutsTest, IfPipe_Embedded) {\n  const std::string s1 = R\"(Hello |{if \"user.sl >= 200\", \"|@N\", \"|@R\"})\";\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  helper.user()->sl(200);\n  helper.sess().effective_sl(200);\n  bout.outstr(s1);\n  EXPECT_EQ(\"Hello Rushfan\", helper.io()->captured());\n}\n\nTEST_F(BPutsTest, MapValue_Smoke) {\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  helper.user()->sl(200);\n  helper.sess().effective_sl(200);\n  helper.context().add_context_variable(\"m\", {{\"num\", \"1234\"}});\n  bout.outstr(R\"(Message # |{m.num})\");\n  EXPECT_EQ(\"Message # 1234\", helper.io()->captured());\n}\n\nTEST_F(BPutsTest, Pipe_User) {\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->real_name(\"RealName\");\n  bout.outstr(R\"(Hello |{user.name})\");\n  EXPECT_EQ(\"Hello Rushfan\", helper.io()->captured());\n}\n\nTEST_F(BPutsTest, Pipe_BBS) {\n  helper.user()->set_name(\"Rushfan\");\n  auto cfg = helper.config().to_config_t();\n  cfg.systemname = \"TestBBS\";\n  helper.config().set_config(cfg, false);\n  bout.outstr(R\"(BBS Name: |{bbs.name})\");\n  EXPECT_EQ(\"BBS Name: TestBBS\", helper.io()->captured());\n}\n"
  },
  {
    "path": "bbs/chains.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/chains.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/chnedit.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/multinst.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"common/input.h\"\n#include \"core/cp437.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include <algorithm>\n#include <map>\n#include <set>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstruct chains_map {\n  std::vector<const chain_t*> chains;\n  std::set<char> odc;\n};\n\nstatic void show_chain(const chain_t& c, bool ansi, int chain_num, bool& abort) {\n  User user{};\n  const auto& r = c.regby;\n  const auto is_regged = r.empty() ? false : a()->users()->readuser(&user, *r.begin());\n  const std::string regname = is_regged ? user.name() : \"Available\";\n  if (ansi) {\n    bout.bpla(fmt::format(\" |#{:d}\\xB3|#5{:3d}|#{:d}\\xB3|#1{:>41.41}|#{:d}\\xB3|{:2d}{:21.21}|#{:d}\"\n                          \"\\xB3|#1{:5d}|#{:d}\\xB3\",\n                          FRAME_COLOR, chain_num, FRAME_COLOR, c.description, FRAME_COLOR,\n                          (is_regged) ? 14 : 13, regname, FRAME_COLOR, c.usage, FRAME_COLOR),\n              &abort);\n  } else {\n    bout.bpla(\n        fmt::format(\" |{:3d}|{:41.41}|{:21.21}|{:5d}|\", chain_num, c.description, regname, c.usage),\n        &abort);\n  }\n\n  if (!is_regged) {\n    return;\n  }\n\n  for (const auto rb : r) {\n    if (rb <= 1) {\n      continue;\n    }\n    if (r.size() == 1) {\n      continue;\n    }\n    if (!a()->users()->readuser(&user, rb)) {\n      continue;\n    }\n    if (ansi) {\n      bout.bpla(fmt::format(\" |#{:d}\\xB3   \\xBA{:41.41}\\xB3|#2{:21.21}|#{:d}\\xB3{:5.5}\\xB3\",\n                            FRAME_COLOR, \" \", user.name(), FRAME_COLOR, \" \"),\n                &abort);\n    } else {\n      bout.bpla(fmt::format(\" |   |                                         |{:21}|     |\",\n                            rb ? user.name() : \"Available\"),\n                &abort);\n    }\n  }\n}\n\n// Displays the list of chains to a user\n// Note: we aren't using a const map since [] doesn't work for const maps.\nstatic void show_chains(const chains_map& chains) {\n  bout.cls();\n  bout.printfile(CHAINS_NOEXT);\n  auto abort = false;\n  auto next = false;\n  if (a()->chains->HasRegisteredChains()) {\n    bout.bpla(\n        fmt::format(\"|#5  Num |#1{:42}|#2{:22}|#1{:5}\", \"Description\", \"Sponsored by\", \"Usage\"),\n        &abort);\n\n    if (okansi()) {\n      bout.bpla(\n          fmt::format(\"|#{:d} {}\", FRAME_COLOR,\n                      \"\\xDA\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xBF\"),\n          &abort);\n    } else {\n      bout.bpla(\" +---+-----------------------------------------+---------------------+-----+\",\n                &abort);\n    }\n    for (auto i = 0; i < size_int(chains.chains) && !abort && !a()->sess().hangup(); i++) {\n      show_chain(*chains.chains.at(i), okansi(), i + 1, abort);\n    }\n    if (okansi()) {\n      bout.bpla(\n          fmt::format(\"|#{:d} {}\", FRAME_COLOR,\n                      \"\\xC0\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                      \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xD9\"),\n          &abort);\n    } else {\n      bout.bpla(\" +---+-----------------------------------------+---------------------+-----+\",\n                &abort);\n    }\n  } else {\n    bout.litebar(StrCat(a()->config()->system_name(), \" Online Programs\"));\n    if (a()->config()->toggles().show_chain_usage) {\n      bout.bpla(fmt::format(\" |#5Num |#1{:28.28}|#1{:5.5} |#5Num |#1{:28}|#1{:5}\", \"Description\",\n                            \"Usage\", \"Description\", \"Usage\"),\n                &abort);\n      if (okansi()) {\n        bout.outstr(\n            \"|#\"\n            \"7\\xDA\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC2\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xBF\\r\\n\");\n      } else {\n        bout.bpla(\"+--+----------------------------+-----+--+----------------------------+-----+\",\n                  &abort);\n      }\n      for (auto i = 0; i < size_int(chains.chains) && !abort && !a()->sess().hangup(); i++) {\n        if (a()->sess().hangup() || abort) {\n          break;\n        }\n        const auto bar = fmt::format(\"|#{:d}{}\", FRAME_COLOR, okansi() ? \"\\xB3\" : \"|\");\n        auto* c = chains.chains.at(i);\n        bout.outstr(fmt::format(\"{}|#2{:2d}{} |#1{:27.27}{}|#1{:5d}{}\", bar, i + 1, bar,\n                                c->description, bar, c->usage, bar),\n                    &abort, &next);\n        if (++i >= size_int(chains.chains)) {\n          bout.bpla(fmt::format(\"  {}                            {}     {}\", bar, bar, bar),\n                    &abort);\n        } else {\n          c = chains.chains.at(i);\n          bout.bpla(fmt::format(\"|#2{:2d}{} |#1{:27.27}{}|#1{:5d}{}\", i + 1, bar, c->description,\n                                bar, c->usage, bar),\n                    &abort);\n        }\n      }\n      if (okansi()) {\n        bout.outstr(\n            \"|#\"\n            \"7\\xC0\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC1\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xD9\\r\\n\");\n      } else {\n        bout.bpla(\"+--+----------------------------+-----+--+----------------------------+-----+\",\n                  &abort);\n      }\n    } else {\n      if (okansi()) {\n        bout.outstr(\n            \"|#\"\n            \"7\\xDA\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC2\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xBF\\r\\n\");\n      } else {\n        bout.bpla(\"+--+----------------------------------+--+----------------------------------+\",\n                  &abort);\n      }\n      const auto bar = fmt::format(\"|#{:d}{}\", FRAME_COLOR, okansi() ? \"\\xB3\" : \"|\");\n      for (int i = 0; i < size_int(chains.chains); ++i) {\n        if (a()->sess().hangup() || abort) {\n          break;\n        }\n        auto* c = chains.chains[i];\n        bout.outstr(fmt::format(\"{}|#2{:2d}{} |#1{:33.33}{}\", bar, i + 1, bar, c->description, bar),\n                    &abort, &next);\n        if (++i >= size_int(chains.chains)) {\n          bout.bpla(fmt::format(\"  {}                                  {}\", bar, bar), &abort);\n        } else {\n          c = chains.chains[i];\n          bout.bpla(fmt::format(\"|#2{:2d}{} |#1{:33.33}{}\", i + 1, bar, c->description, bar),\n                    &abort);\n        }\n      }\n      if (okansi()) {\n        bout.outstr(\n            \"|#\"\n            \"7\\xC0\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC1\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xD9\\r\\n\");\n      } else {\n        bout.bpla(\"+--+----------------------------------+--+----------------------------------+\",\n                  &abort);\n      }\n    }\n  }\n}\n\n// Executes a \"chain\", index number chain_num.\nvoid run_chain(const chain_t& c, int chain_num) {\n  if (auto inst = find_instance_by_loc(INST_LOC_CHAINS, chain_num + 1); inst != 0) {\n    const auto h = fmt::format(\"|#2Chain {} is in use on instance {}. \", c.description, inst);\n    if (!c.multi_user) {\n      bout.print(\"{} Try again later.\\r\\n\", h);\n      return;\n    }\n    bout.print(\"{} Care to join in? \", h);\n    if (!bin.yesno()) {\n      return;\n    }\n  }\n  write_inst(INST_LOC_CHAINS, chain_num + 1, INST_FLAGS_NONE);\n  a()->chains->increment_chain_usage(chain_num);\n  a()->chains->Save();\n  sysoplog(fmt::format(\"!Ran \\\"{}\\\"\", c.description));\n  a()->user()->chains_run(a()->user()->chains_run() + 1);\n#ifdef _WIN32\n  ScopeExit at_exit;\n  if (c.local_console_cp437) {\n    set_wwiv_codepage(wwiv_codepage_t::cp437);\n    at_exit.swap([] { set_wwiv_codepage(wwiv_codepage_t::utf8); });\n  }\n#endif\n  wwiv::bbs::CommandLine cl(c.filename);\n  cl.args(create_chain_file(), std::to_string(a()->modem_speed_),\n          std::to_string(a()->primary_port()), std::to_string(a()->modem_speed_));\n  const auto flags = Chains::to_exec_flags(c);\n  ExecuteExternalProgram(cl, flags);\n  write_inst(INST_LOC_CHAINS, 0, INST_FLAGS_NONE);\n  if (c.pause) {\n    bout.pausescr();\n  }\n  a()->UpdateTopScreen();\n}\n\nvoid run_chain(int chain_num) {\n  const auto& c = a()->chains->at(chain_num);\n  run_chain(c, chain_num);\n}\n\n\n\n//////////////////////////////////////////////////////////////////////////////\n// Main high-level function for chain access and execution.\n\nchains_map build_chains_map() {\n  auto mapp{0};\n  std::vector<const chain_t*> chains;\n  std::set<char> odc;\n  const auto& all_chains = a()->chains->chains();\n  for (auto i = 0; i < wwiv::stl::ssize(all_chains); i++) {\n    const auto& c = all_chains[i];\n    if (c.ansi && !okansi()) {\n      continue;\n    }\n    if (c.local_only && a()->sess().using_modem()) {\n      continue;\n    }\n    if (!wwiv::bbs::check_acs(c.acs)) {\n      continue;\n    }\n    chains.push_back(&c);\n    ++mapp;\n    if (mapp < 100) {\n      if ((mapp % 10) == 0) {\n        odc.insert(static_cast<char>('0' + (mapp / 10)));\n      }\n    }\n  }\n\n  return chains_map{chains, odc};\n}\n\nvoid do_chains() {\n\n  auto chains_map = build_chains_map();\n\n  while (!a()->sess().hangup()) {\n    a()->tleft(true);\n    if (chains_map.chains.empty()) {\n      bout.outstr(\"\\r\\n\\n|#5Sorry, no external programs available.\\r\\n\");\n      return;\n    }\n\n    show_chains(chains_map);\n    a()->tleft(true);\n    bout.nl();\n    bout.print(\"|#5Which Chain (1-{}, Q=Quit, {}?=List): \", size_int(chains_map.chains) + 1,\n               (so() ? \"*=ChainEdit, \" : \"\"));\n\n    std::string ss;\n    if (size_int(chains_map.chains) < 100) {\n      ss = mmkey(chains_map.odc);\n    } else {\n      ss = bin.input_upper(3);\n    }\n    if (const auto chain_num = to_number<int>(ss);\n        chain_num > 0 && chain_num <= size_int(chains_map.chains)) {\n      bout.outstr(\"\\r\\n|#6Please wait...\\r\\n\");\n      run_chain(*chains_map.chains[chain_num - 1], chain_num - 1);\n    } else if (ss == \"Q\") {\n      // No cleanup needed, any cleanup should be RAII.\n      return;\n    } else if (ss == \"*\" && so()) {\n      chainedit();\n      chains_map = build_chains_map();\n    } else if (ss == \"?\") {\n      show_chains(chains_map);\n    }\n  } \n}\n"
  },
  {
    "path": "bbs/chains.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CHAINS_H\n#define INCLUDED_BBS_CHAINS_H\n\nnamespace wwiv::sdk {\n  struct chain_t;\n}\n\nvoid run_chain(const wwiv::sdk::chain_t& c, int chain_num);\nvoid run_chain(int chain_num);\nvoid do_chains();\n\n\n#endif  // INCLUDED_BBS_CHAINS_H"
  },
  {
    "path": "bbs/chat.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/multinst.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nstruct ch_type {\n  char name[60];\n  int sl;\n  char ar;\n  char sex;\n  uint8_t min_age;\n  uint8_t max_age;\n};\n\nstruct ch_action {\n  int r;\n  char aword[12];\n  char toprint[80];\n  char toperson[80];\n  char toall[80];\n  char singular[80];\n};\n\nstatic int g_nChatOpSecLvl;\nstatic int g_nNumActions;\nconstexpr int MAX_NUM_ACT = 100;\nstatic ch_action* actions[MAX_NUM_ACT];\nstatic ch_type channels[11];\n\nint rip_words(int start_pos, const char* cmsg, char* wd, int size, char lookfor);\nint f_action(int start_pos, int end_pos, char* aword);\nint main_loop(const char* message, char* from_message, char* color_string, char* messageSent,\n              bool& bActionMode, int loc, int num_actions);\nstd::vector<int> who_online(int loc);\nvoid intro(int loc);\nvoid ch_direct(const std::string& message, int loc, char* color_string, int node);\nvoid ch_whisper(const std::string&, char* color_string, int node);\nint wusrinst(char* n);\nvoid secure_ch(int ch);\nvoid cleanup_chat();\nvoid page_user(int loc);\nvoid moving(bool bOnline, int loc);\nvoid load_actions(IniFile* pIniFile);\nvoid add_action(ch_action act);\nvoid free_actions();\nvoid exec_action(const char* message, char* color_string, int loc, int nact);\nvoid action_help(int num);\nvoid ga(const char* message, char* color_string, int loc, int type);\nvoid list_channels();\nint change_channels(int loc);\nbool check_ch(int ch);\nvoid load_channels(IniFile& pIniFile);\nint userinst(char* user);\n\nstatic int grabname(const std::string& orig, int channel) {\n  auto node = 0;\n  User u;\n  if (orig.empty() || orig.front() == ' ') {\n    return 0;\n  }\n\n  const auto space = orig.find(' ', 1);\n  const auto message = orig.substr(0, space);\n\n  if (auto n = to_number<int>(message)) {\n    if (n < 1 || n > num_instances()) {\n      bout.printf(\"%s%d|#1]\\r\\n\", \"|#1[|#9There is no user on instance \", n);\n      return 0;\n    }\n    if (const auto ir = a()->instances().at(n); ir.online() && (!ir.invisible() || so())) {\n      if (channel && ir.loc_code() != channel) {\n        bout.outstr(\"|#1[|#9That user is not in this chat channel|#1]\\r\\n\");\n        return 0;\n      }\n      return n;\n    }\n    bout.printf(\"%s%d|#1]\\r\\n\", \"|#1[|#9There is no user on instance \", n);\n    return 0;\n  }\n  {\n    node = 0;\n    const auto name = ToStringUpperCase(message);\n    for (auto i = 1; i <= num_instances(); i++) {\n      if (auto ir = a()->instances().at(i); ir.online() && (!ir.invisible() || so())) {\n        if (channel && (ir.loc_code() != channel)) {\n          continue;\n        }\n        a()->users()->readuser(&u, ir.user_number());\n        if (name == u.name()) {\n          node = i;\n          break;\n        }\n      }\n    }\n  }\n  if (!node) {\n    if (channel) {\n      bout.outstr(\"|#1[|#9That user is not in this chat channel|#1]\\r\\n\");\n    } else {\n      bout.outstr(\"|#1[|#9Specified user is not online|#1]\\r\\n\");\n    }\n  }\n  return node;\n}\n\nstatic std::string StripName(const std::string& in) {\n  if (in.empty() || in.front() == ' ') {\n    return in;\n  }\n\n  const auto space = in.find(' ', 1);\n  return in.substr(space);\n}\n\n// Sets color_string string for current node\nstatic void get_colors(char* color_string, const IniFile* pIniFile) {\n  const auto s = pIniFile->value<std::string>(StrCat(\"C\", a()->sess().instance_number()));\n  strcpy(color_string, s.c_str());\n}\n\nvoid chat_room() {\n  char szColorString[15];\n  bool bShowPrompt;\n\n  g_nNumActions = -1;\n  g_nChatOpSecLvl = 256;\n\n  char szMessageSent[80], szFromMessage[50];\n  strcpy(szMessageSent, \"|#1[|#9Message Sent|#1]\\r\\n\");\n  strcpy(szFromMessage, \"|#9From %.12s|#1: %s%s\");\n  IniFile ini(FilePath(a()->bbspath(), CHAT_INI), \"CHAT\");\n  if (ini.IsOpen()) {\n    g_nChatOpSecLvl = ini.value<int>(\"CHATOP_SL\");\n    bShowPrompt = ini.value<bool>(\"CH_PROMPT\");\n    load_channels(ini);\n    load_actions(&ini);\n    get_colors(szColorString, &ini);\n    ini.Close();\n  } else {\n    bout.outstr(\"|#6[CHAT] SECTION MISSING IN CHAT.INI - ALERT THE SYSOP IMMEDIATELY!\\r\\n\");\n    bout.pausescr();\n    return;\n  }\n  cleanup_chat();\n  bout.outstr(\"\\r\\n|#2Welcome to the WWIV Chatroom\\n\\r\\n\");\n  auto loc = 0;\n  if (bShowPrompt) {\n    while (!loc) {\n      bout.nl();\n      bout.outstr(\"|#1Select a chat channel to enter:\\r\\n\");\n      loc = change_channels(-1);\n      if (loc == -1) {\n        return;\n      }\n    }\n  } else {\n    if (a()->user()->restrict_iichat() || !check_ch(1)) {\n      bout.outstr(\"\\r\\n|#6You may not access inter-instance chat facilities.\\r\\n\");\n      bout.pausescr();\n      return;\n    }\n    loc = INST_LOC_CH1;\n    write_inst(loc, 0, INST_FLAGS_NONE);\n    moving(true, loc);\n    intro(loc);\n    bout.nl();\n  }\n\n  TempDisablePause disable_pause(bout);\n  a()->sess().chatline(false);\n  a()->sess().in_chatroom(true);\n  auto oiia = setiia(std::chrono::milliseconds(500));\n\n  bool bActionMode = true;\n  while (!a()->sess().hangup()) {\n    setiia(std::chrono::milliseconds(500));\n    a()->CheckForHangup();\n    if (inst_msg_waiting()) {\n      process_inst_msgs(); \n    }\n    bout.ansic(1);\n    bout.outstr(szColorString);\n    a()->tleft(true);\n    a()->sess().chatline(false);\n    auto message = bin.input_text(\"\", false, 255);\n    if (message.empty()) {\n      intro(loc);\n    } else {\n      int c = main_loop(message.c_str(), szFromMessage, szColorString, szMessageSent, bActionMode, loc,\n                        g_nNumActions);\n      if (!c) {\n        break;\n      } else {\n        loc = c;\n      }\n    }\n  }\n  setiia(oiia);\n  moving(false, loc);\n  free_actions();\n  a()->sess().in_chatroom(false);\n}\n\nint rip_words(int start_pos, const char* message, char* wd, int size, char lookfor) {\n  unsigned int nPos;\n  int nSpacePos = -1;\n\n  for (nPos = start_pos; nPos <= strlen(message); nPos++) {\n    if (nSpacePos == -1 && (message[nPos] == ' ')) {\n      continue;\n    }\n    if (message[nPos] != lookfor) {\n      nSpacePos++;\n      if (nSpacePos > size) {\n        break;\n      }\n      wd[nSpacePos] = message[nPos];\n    } else {\n      nSpacePos++;\n      nPos++;\n      wd[nSpacePos] = '\\0';\n      break;\n    }\n  }\n  wd[nSpacePos] = '\\0';\n  return nPos;\n}\n\nint f_action(int start_pos, int end_pos, char* aword) {\n  int test = ((end_pos - start_pos) / 2) + start_pos;\n  if (!((end_pos - start_pos) / 2)) {\n    test++;\n    if (iequals(aword, actions[test]->aword)) {\n      return test;\n    }\n    if (iequals(aword, actions[test - 1]->aword)) {\n      return test - 1;\n    } else {\n      return -1;\n    }\n  }\n  if (StringCompareIgnoreCase(aword, actions[test]->aword) < 0) {\n    end_pos = test;\n  } else if (StringCompareIgnoreCase(aword, actions[test]->aword) > 0) {\n    start_pos = test;\n  } else {\n    return test;\n  }\n  if (start_pos != end_pos) {\n    test = f_action(start_pos, end_pos, aword);\n  }\n  return test;\n}\n\n// Sends out a raw_message to everyone in channel LOC\nstatic void out_msg(const std::string& message, int loc) {\n  for (auto i = 1; i <= num_instances(); i++) {\n    auto ir = a()->instances().at(i);\n    if (ir.loc_code() == loc && i != a()->sess().instance_number()) {\n      send_inst_str(i, message);\n    }\n  }\n}\n\n// Determines if a word is an action, if so, executes it\nbool check_action(const char* message, char* color_string, int loc) {\n  char s[12];\n\n  unsigned int x = rip_words(0, message, s, 12, ' ');\n  if (iequals(\"GA\", s)) {\n    ga(message + x, color_string, loc, 0);\n    return true;\n  }\n  if (iequals(\"GA's\", s)) {\n    ga(message + x, color_string, loc, 1);\n    return true;\n  }\n  int p = f_action(0, g_nNumActions, s);\n  if (p != -1) {\n    if (strlen(message) <= x) {\n      exec_action(\"\\0\", color_string, loc, p);\n    } else {\n      exec_action(message + x, color_string, loc, p);\n    }\n    return true;\n  }\n  return false;\n}\n\nint main_loop(const char* raw_message, char* from_message, char* color_string, char* messageSent,\n              bool& bActionMode, int loc, int num_actions) {\n  User u;\n\n  bool bActionHandled = true;\n  if (bActionMode) {\n    bActionHandled = !check_action(raw_message, color_string, loc);\n  }\n  if (iequals(raw_message, \"/w\")) {\n    bActionHandled = 0;\n    multi_instance();\n    bout.nl();\n  } else if (iequals(raw_message, \"list\")) {\n    bout.nl();\n    for (int i2 = 0; i2 <= num_actions; i2++) {\n      bout.printf(\"%-16.16s\", actions[i2]->aword);\n    }\n    bout.nl();\n    bActionHandled = 0;\n  } else if (iequals(raw_message, \"/q\") || iequals(raw_message, \"x\")) {\n    bActionHandled = 0;\n    bout.outstr(\"\\r\\n|#2Exiting Chatroom\\r\\n\");\n    return 0;\n  } else if (iequals(raw_message, \"/a\")) {\n    bActionHandled = 0;\n    if (bActionMode) {\n      bout.outstr(\"|#1[|#9Action mode disabled|#1]\\r\\n\");\n      bActionMode = false;\n    } else {\n      bout.outstr(\"|#1[|#9Action mode enabled|#1]\\r\\n\");\n      bActionMode = true;\n    }\n  } else if (iequals(raw_message, \"/s\")) {\n    bActionHandled = 0;\n    secure_ch(loc);\n  } else if (iequals(raw_message, \"/u\")) {\n    bActionHandled = 0;\n    const auto fn = fmt::format(\"CHANNEL.{}\", (loc + 1 - INST_LOC_CH1));\n    if (File::Exists(fn)) {\n      File::Remove(fn);\n      const auto m = fmt::format(\"\\r\\n|#1[|#9{} has unsecured the channel|#1]\", a()->user()->name());\n      out_msg(m, loc);\n      bout.outstr(\"|#1[|#9Channel Unsecured|#1]\\r\\n\");\n    } else {\n      bout.outstr(\"|#1[|#9Channel not secured!|#1]\\r\\n\");\n    }\n  } else if (iequals(raw_message, \"/p\")) {\n    bActionHandled = 0;\n    page_user(loc);\n  } else if (iequals(raw_message, \"/c\")) {\n    int nChannel = change_channels(loc);\n    loc = nChannel;\n    bActionHandled = 0;\n  } else if (iequals(raw_message, \"?\") || iequals(raw_message, \"/?\")) {\n    bActionHandled = 0;\n    bout.print_help_file(CHAT_NOEXT);\n  } else if (bActionHandled && raw_message[0] == '>') {\n    bActionHandled = 0;\n    int nUserNum = grabname(raw_message + 1, loc);\n    if (nUserNum) {\n      auto message = StripName(raw_message);\n      ch_direct(message, loc, color_string, nUserNum);\n    }\n  } else if (bActionHandled && raw_message[0] == '/') {\n    int nUserNum = grabname(raw_message + 1, 0);\n    if (nUserNum) {\n      auto message = StripName(raw_message);\n      ch_whisper(message, color_string, nUserNum);\n    }\n    bActionHandled = 0;\n  } else {\n    if (bActionHandled) {\n      bout.outstr(messageSent);\n    }\n    if (!raw_message[0]) {\n      return loc;\n    }\n  }\n  if (bActionHandled) {\n    const auto t = fmt::sprintf(from_message, a()->user()->name(), color_string, raw_message);\n    out_msg(t, loc);\n  }\n  return loc;\n}\n\n// Fills an array with information of who's online.\nstd::vector<int> who_online(int loc) {\n  std::vector<int> r{};\n  for (auto i = 1; i <= wwiv::stl::size_int(a()->instances()); i++) {\n    const auto ir = a()->instances().at(i);\n    if (!ir.invisible() || so()) {\n      if (ir.loc_code() == loc && i != a()->sess().instance_number()) {\n        r.emplace_back(i);\n      }\n    }\n  }\n  return r;\n}\n\n// Displays which channel the user is in, who's in the channel with them,\n// whether or not the channel is secured, and tells the user how to obtain\n// help\nvoid intro(int loc) {\n\n  bout.print(\"|#7You are in {} with: \\r\\n\", channels[loc - INST_LOC_CH1 + 1].name);\n  auto users = who_online(loc);\n  if (!users.empty()) {\n    auto first = true;\n    for (const auto& usernum : users) {\n      User u;\n      a()->users()->readuser(&u, usernum);\n      if (!first) {\n        bout.outstr(\"|#7and \");\n      }\n      bout.print(\"|#1{} \", u.name());\n      first = false;\n    }\n  } else {\n    bout.outstr(\"|#7You are the only one here.\\r\\n\");\n  }\n  const auto fn = fmt::format(\"CHANNEL.{}\", (loc + 1 - INST_LOC_CH1));\n  if (loc != INST_LOC_CH1 && File::Exists(fn)) {\n    bout.outstr(\"|#7This channel is |#1secured|#7.\\r\\n\");\n  }\n  bout.outstr(\"|#7Type ? for help.\\r\\n\");\n}\n\n// This function is called when a > sign is encountered at the beginning of\n//   a line, it's used for directing messages\n\nvoid ch_direct(const std::string& message, int loc, char* color_string, int node) {\n  if (message.empty()) {\n    bout.outstr(\"|#1[|#9Message required after using a / or > command.|#1]\\r\\n\");\n    return;\n  }\n\n  auto ir = a()->instances().at(node);\n  if (ir.loc_code() == loc) {\n    User u;\n    a()->users()->readuser(&u, ir.user_number());\n    const auto s = fmt::sprintf(\"|#9From %.12s|#6 [to %s]|#1: %s%s\", a()->user()->name(),\n                                u.name(), color_string, message);\n    for (auto i = 1; i <= num_instances(); i++) {\n      ir = a()->instances().at(i);\n      if (ir.loc_code() == loc && i != a()->sess().instance_number()) {\n        send_inst_str(i, s);\n      }\n    }\n    bout.print(\"|#1[|#9Message directed to {}|#1\\r\\n\", u.name());\n  } else {\n    bout.outstr(message);\n    bout.nl();\n  }\n}\n\n// This function is called when a / sign is encountered at the beginning of\n//   a raw_message, used for whispering\nvoid ch_whisper(const std::string& message, char* color_string, int node) {\n  if (message.empty()) {\n    bout.outstr(\"|#1[|#9Message required after using a / or > command.|#1]\\r\\n\");\n    return;\n  }\n  if (!node) {\n    return;\n  }\n\n  auto text = message;\n  const auto ir = a()->instances().at(node);\n  if (ir.in_channel()) {\n    text = fmt::sprintf(\"|#9From %.12s|#6 [WHISPERED]|#2|#1:%s%s\", a()->user()->name(),\n                        color_string, message);\n  }\n  send_inst_str(node, text);\n  if (auto ou = a()->users()->readuser(ir.user_number())) {\n    bout.print(\"|#1[|#9Message sent only to {}|#1]\\r\\n\", ou.value().name());\n  }\n}\n\n// This function determines whether or not user N is online\n\nint wusrinst(char* n) {\n\n  for (auto i = 0; i <= num_instances(); i++) {\n    auto ir = a()->instances().at(i);\n    if (ir.online()) {\n      if (auto u = a()->users()->readuser(ir.user_number())) {\n        if (iequals(u.value().name(), n)) {\n          return i;\n        }\n      }\n    }\n  }\n  return 0;\n}\n\n// Secures a channel\n\nvoid secure_ch(int ch) {\n  if (ch == INST_LOC_CH1) {\n    bout.outstr(\"|#1[|#9Cannot secure channel 1|#1]\\r\\n\");\n    return;\n  }\n  const auto fn = fmt::format(\"CHANNEL.{}\", (ch + 1 - INST_LOC_CH1));\n  if (File::Exists(fn)) {\n    bout.outstr(\"|#1[|#9Channel already secured!|#1]\\r\\n\");\n  } else {\n    {\n      File file(fn);\n      file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile | File::modeText);\n      file.Write(a()->user()->name());\n    }\n    bout.outstr(\"|#1[|#9Channel Secured|#1]\\r\\n\");\n    const auto msg = fmt::format(\"\\r\\n|#1[|#9{} has secured the channel|#1]\", a()->user()->name());\n    out_msg(msg, ch);\n  }\n}\n\n// Eliminates unnecessary lockfiles\n\nvoid cleanup_chat() {\n  for (auto x = INST_LOC_CH2; x <= INST_LOC_CH10; x++) {\n    const auto fn = fmt::format(\"CHANNEL.%d\", (x + 1 - INST_LOC_CH1));\n    if (File::Exists(fn) && who_online(x).empty()) {\n      File::Remove(fn);\n    }\n  }\n}\n\n// Pages a user\n\nvoid page_user(int loc) {\n  int i = 0;\n\n  loc = loc + 1 - INST_LOC_CH1;\n  bout.nl();\n  multi_instance();\n  bout.nl();\n  while ((i < 1 || i > num_instances()) && !a()->sess().hangup()) {\n    a()->CheckForHangup();\n    bout.print(\"|#2Which instance would you like to page? (1-{}, Q): \", num_instances());\n    auto s = bin.input(2);\n    if (!s.empty() && s.front() == 'Q') {\n      return;\n    }\n    i = to_number<int>(s);\n  }\n  if (i == a()->sess().instance_number()) {\n    bout.outstr(\"|#1[|#9Cannot page the instance you are on|#1]\\r\\n\");\n    return;\n  }\n  const auto ir = a()->instances().at(i);\n  if (!ir.online() || (!so() && ir.invisible())) {\n    bout.print(\"|#1[|#9There is no user on instance {}|#1]\\r\\n\", i);\n    return;\n  }\n  if (!ir.available() && !so()) {\n    bout.outstr(\"|#1[|#9That user is not available for chat!|#1]\");\n    return;\n  }\n  const auto s = fmt::format(\n      \"{} is paging you from Chatroom channel {}.  Type /C from the MAIN MENU to enter the \"\n      \"Chatroom.\",\n      a()->user()->name(), loc);\n  send_inst_str(i, s);\n  bout.outstr(\"|#1[|#9Page Sent|#1]\\r\\n\");\n}\n\n// Announces when a user has left a channel\n\nvoid moving(bool bOnline, int loc) {\n  if (is_chat_invis()) {\n    return;\n  }\n  const auto s = fmt::format(\"|#6{} {}\", a()->user()->name(),\n          (bOnline ? \"is on the air.\" : \"has signed off.\"));\n  out_msg(s, loc);\n}\n\n\n// Loads the actions into memory\n\nvoid load_actions(IniFile* pIniFile) {\n  int to_read = pIniFile->value<int>(\"NUM_ACTIONS\");\n  if (!to_read) {\n    return;\n  }\n  for (int cn = 1; cn <= to_read; cn++) {\n    ch_action act;\n    memset(&act, 0, sizeof(ch_action));\n    for (int ca = 0; ca <= 5; ca++) {\n      char rstr[10];\n      sprintf(rstr, \"%d%c\", cn, 65 + ca);\n      std::string s = pIniFile->value<std::string>(rstr);\n      const char* ini_value = s.c_str();\n      switch (ca) {\n      case 0:\n        act.r = to_number<int>((ini_value != nullptr) ? ini_value : \"0\");\n        break;\n      case 1:\n        strcpy(act.aword, (ini_value != nullptr) ? ini_value : \"\");\n        break;\n      case 2:\n        strcpy(act.toprint, (ini_value != nullptr) ? ini_value : \"\");\n        break;\n      case 3:\n        strcpy(act.toperson, (ini_value != nullptr) ? ini_value : \"\");\n        break;\n      case 4:\n        strcpy(act.toall, (ini_value != nullptr) ? ini_value : \"\");\n        break;\n      case 5:\n        strcpy(act.singular, (ini_value != nullptr) ? ini_value : \"\");\n        break;\n      default:\n        // TODO Should an error be displayed here?\n        break;\n      }\n    }\n    add_action(act);\n  }\n}\n\n// Used by load_actions(), adds an action into the array\nvoid add_action(ch_action act) {\n  if (g_nNumActions < 100) {\n    g_nNumActions++;\n  } else {\n    return;\n  }\n  ch_action* addact = static_cast<ch_action*>(calloc(sizeof(ch_action) + 1, 1));\n  addact->r = act.r;\n  strcpy(addact->aword, act.aword);\n  strcpy(addact->toprint, act.toprint);\n  strcpy(addact->toperson, act.toperson);\n  strcpy(addact->toall, act.toall);\n  strcpy(addact->singular, act.singular);\n  actions[g_nNumActions] = addact;\n}\n\n// Removes the actions from memory\nvoid free_actions() {\n  for (int i = 0; i <= g_nNumActions; i++) {\n    free(actions[i]);\n  }\n}\n\n// \"Executes\" an action\n\nvoid exec_action(const char* message, char* color_string, int loc, int nact) {\n  char tmsg[150], final[170];\n\n  bool ok = (strlen(message) == 0) ? false : true;\n  if (iequals(message, \"?\")) {\n    action_help(nact);\n    return;\n  }\n\n  int p = 0;\n  if (ok) {\n    p = grabname(message, loc);\n    if (!p) {\n      return;\n    }\n  }\n  if (ok) {\n    sprintf(tmsg, actions[nact]->toperson, a()->user()->GetName());\n  } else if (actions[nact]->r) {\n    bout.outstr(\"This action requires a recipient.\\r\\n\");\n    return;\n  } else {\n    sprintf(tmsg, actions[nact]->singular, a()->user()->GetName());\n  }\n  bout.pl(actions[nact]->toprint);\n  sprintf(final, \"%s%s\", color_string, tmsg);\n  if (!ok) {\n    out_msg(final, loc);\n  } else {\n    send_inst_str(p, final);\n    const auto oa = a()->users()->readuser(a()->instances().at(p).user_number());\n    if (!oa) {\n      return;\n    }\n    sprintf(tmsg, actions[nact]->toall, a()->user()->GetName(), oa.value().GetName());\n    sprintf(final, \"%s%s\", color_string, tmsg);\n    for (int c = 1; c <= num_instances(); c++) {\n      const auto ir = a()->instances().at(c);\n      if (ir.loc_code() == loc && c != a()->sess().instance_number() && c != p) {\n        send_inst_str(c, final);\n      }\n    }\n  }\n}\n\n// Displays help on an action\nvoid action_help(int num) {\n  char buffer[150];\n  char ac[13], rec[18];\n\n  strcpy(ac, \"|#6[USER]|#1\");\n  strcpy(rec, \"|#6[RECIPIENT]|#1\");\n  bout.print(\"\\r\\n|#5Word:|#1 {}\\r\\n\", actions[num]->aword);\n  bout.print(\"|#5To user:|#1 {}\\r\\n\", actions[num]->toprint);\n  sprintf(buffer, actions[num]->toperson, ac);\n  bout.print(\"|#5To recipient:|#1 {}\\r\\n\", buffer);\n  sprintf(buffer, actions[num]->toall, ac, rec);\n  bout.print(\"|#5To everyone else:|#1 {}\\r\\n\", buffer);\n  if (actions[num]->r == 1) {\n    bout.outstr(\"|#5This action requires a recipient.\\n\\r\\n\");\n    return;\n  }\n  sprintf(buffer, actions[num]->singular, ac);\n  bout.print(\"|#5Used singular:|#1 {}\\r\\n\", buffer);\n  bout.outstr(\"|#5This action does not require a recipient.\\n\\r\\n\");\n}\n\n// Executes a GA command\n\nvoid ga(const char* message, char* color_string, int loc, int type) {\n  if (!strlen(message) || message[0] == '\\0') {\n    bout.outstr(\"|#1[|#9A message is required after the GA command|#1]\\r\\n\");\n    return;\n  }\n  char buffer[500];\n  sprintf(buffer, \"%s%s%s %s\", color_string, a()->user()->GetName(), (type ? \"'s\" : \"\"), message);\n  bout.outstr(\"|#1[|#9Generic Action Sent|#1]\\r\\n\");\n  out_msg(buffer, loc);\n}\n\n// Lists the chat channels\nvoid list_channels() {\n  int tl = 0, secure[11], check[11];\n  char s[12];\n\n  for (auto i = 1; i <= 10; i++) {\n    sprintf(s, \"CHANNEL.%d\", i);\n    secure[i] = (File::Exists(s)) ? 1 : 0;\n    check[i] = 0;\n  }\n\n  for (auto i1 = 1; i1 <= num_instances(); i1++) {\n    const auto ir = a()->instances().at(i1);\n    if (!ir.invisible() || so()) {\n      if (ir.in_channel()) {\n        check[ir.loc_code() - INST_LOC_CH1 + 1] = 1;\n      }\n    }\n  }\n\n  for (tl = 1; tl <= 10; tl++) {\n    bout.print(\"|#1{} |#7-|#9 {}\\r\\n\", tl, channels[tl].name);\n    if (!check[tl]) {\n      continue;\n    }\n    auto users = who_online(tl + INST_LOC_CH1 - 1);\n    if (users.empty()) {\n      continue;\n    }\n    if (tl == 10) {\n      bout.outchr(SPACE);\n    }\n    bout.outstr(\"    |#9Users in channel: \");\n    auto first = true;\n    for (const auto& usernum : users) {\n      if (auto u = a()->users()->readuser(usernum)) {\n        if (!first) {\n          bout.outstr(\"|#7and \");\n        }\n        bout.print(\"|#1{} \", u.value().name());\n        first = false;\n      }\n    }\n    bout.outstr(\" \");\n    if (secure[tl]) {\n      bout.outstr(\"|#6[SECURED]\");\n    }\n    bout.nl();\n  }\n}\n\n// Calls list_channels() then prompts for a channel to change to.\nint change_channels(int loc) {\n  auto ch_ok = 0, temploc = 0;\n  char szMessage[80];\n\n  cleanup_chat();\n  bout.nl();\n  list_channels();\n  bout.nl();\n  while ((temploc < 1 || temploc > 10) && !a()->sess().hangup()) {\n    a()->CheckForHangup();\n    bout.outstr(\"|#1Enter a channel number, 1 to 10, Q to quit: \");\n    bin.input(szMessage, 2);\n    if (to_upper_case_char(szMessage[0]) == 'Q') {\n      return loc;\n    }\n    temploc = to_number<int>(szMessage);\n  }\n  if (check_ch(temploc)) {\n    sprintf(szMessage, \"CHANNEL.%d\", temploc);\n    if (!File::Exists(szMessage)) {\n      ch_ok = 1;\n    } else {\n      if (a()->user()->sl() >= g_nChatOpSecLvl || so()) {\n        bout.outstr(\"|#9This channel is secured.  Are you |#1SURE|#9 you wish to enter? \");\n        if (bin.yesno()) {\n          ch_ok = 1;\n        }\n      } else {\n        bout.outstr(\"|#1Channel is secured.  You cannot enter it.\\r\\n\");\n      }\n    }\n    if (ch_ok) {\n      if (loc != -1) {\n        moving(false, loc);\n      }\n      loc = temploc + (INST_LOC_CH1 - 1);\n      write_inst(loc, 0, INST_FLAGS_NONE);\n      moving(true, loc);\n      bout.nl();\n      intro(loc);\n    }\n  }\n  return loc;\n}\n\n// Checks to see if user has requirements to enter a channel\n//   (SL, AR, Sex, Age, etc)\n\nbool check_ch(int ch) {\n  uint16_t c_ar;\n  char szMessage[80];\n\n  if (static_cast<int>(a()->user()->sl()) < channels[ch].sl && !so()) {\n    bout.print(\"\\r\\n|#9A security level of |#1{}\"\n               \"|#9 is required to access this channel.\\r\\n\",\n               channels[ch].sl);\n    bout.print(\"|#9Your security level is |#1{}|#9.\\r\\n\", a()->user()->sl());\n    return false;\n  }\n  if (channels[ch].ar != '0') {\n    c_ar = static_cast<uint16_t>(1 << (channels[ch].ar - 65));\n  } else {\n    c_ar = 0;\n  }\n  if (c_ar && !a()->user()->has_ar(c_ar)) {\n    sprintf(szMessage, \"\\r\\n|#9The \\\"|#1%c|#9\\\" AR is required to access this chat channel.\\r\\n\",\n            channels[ch].ar);\n    bout.outstr(szMessage);\n    return false;\n  }\n  char gender = channels[ch].sex;\n  if (gender != 65 && a()->user()->gender() != gender &&\n      a()->user()->sl() < g_nChatOpSecLvl) {\n    if (gender == 77) {\n      bout.outstr(\"\\r\\n|#9Only |#1males|#9 are allowed in this channel.\\r\\n\");\n    } else if (gender == 70) {\n      bout.outstr(\"\\r\\n|#9Only |#1females|#9 are allowed in this channel.\\r\\n\");\n    } else {\n      bout.outstr(\"\\r\\n|#6The sysop has configured this channel improperly!\\r\\n\");\n    }\n    return false;\n  }\n  if (a()->user()->age() < channels[ch].min_age && a()->user()->sl() < g_nChatOpSecLvl) {\n    bout.print(\"\\r\\n|#9You must be |#1{}|#9 or older to enter this channel.\\r\\n\", channels[ch].min_age);\n    return false;\n  }\n  if (a()->user()->age() > channels[ch].max_age && a()->user()->sl() < g_nChatOpSecLvl) {\n    bout.print(\"\\r\\n|#9You must be |#1{}|#9 or younger to enter this channel.\\r\\n\", channels[ch].max_age);\n    return false;\n  }\n  return true;\n}\n\n// Loads channel information into memory\nvoid load_channels(IniFile& ini) {\n  char buffer[6];\n\n  for (int cn = 1; cn <= 10; cn++) {\n    for (int ca = 0; ca <= 5; ca++) {\n      sprintf(buffer, \"CH%d%c\", cn, 65 + ca);\n      switch (ca) {\n      case 0:\n        to_char_array(channels[cn].name, ini.value<std::string>(buffer));\n        break;\n      case 1:\n        channels[cn].sl = ini.value<int>(buffer);\n        break;\n      case 2: {\n        std::string temp = ini.value<std::string>(buffer);\n        if (temp.empty() || temp.front() == '0') {\n          channels[cn].ar = 0;\n        } else {\n          channels[cn].ar = temp.front();\n        }\n      } break;\n      case 3: {\n        std::string temp = ini.value<std::string>(buffer);\n        if (!temp.empty()) {\n          channels[cn].sex = temp.front();\n        }\n      } break;\n      case 4:\n        channels[cn].min_age = ini.value<uint8_t>(buffer);\n        break;\n      case 5:\n        channels[cn].max_age = ini.value<uint8_t>(buffer);\n        break;\n      }\n    }\n  }\n}\n\n// Determines the node number a user is on\nint userinst(char* user) {\n  if (strlen(user) == 0) {\n    return 0;\n  }\n  auto p = wusrinst(user);\n  if (p) {\n    auto ir = a()->instances().at(p);\n    if (!ir.invisible() || so()) {\n      return p;\n    }\n  }\n  p = to_number<int>(user);\n  if (p > 0 && p <= num_instances()) {\n    const auto ir = a()->instances().at(p);\n    if (!ir.online() && (so() || !ir.invisible())) {\n      return p;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "bbs/chat.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_CHAT_H__\n#define __INCLUDED_BBS_CHAT_H__\n\nvoid chat_room();\n\n#endif  // __INCLUDED_BBS_CHAT_H__\n"
  },
  {
    "path": "bbs/chnedit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/utility.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"core/datafile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\n#include <string>\n#include <vector>\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid delete_chain(size_t chain_num);\n\nstatic std::string chaindata(int chain_num) {\n  const auto& c = a()->chains->at(chain_num);\n  return fmt::sprintf(\"|#2%2d |#1%-32.32s  |#5%-35.35s\", chain_num,\n                      stripcolors(c.description), c.filename);\n}\n\nstatic void showchains() {\n  bout.cls();\n  auto abort = false;\n  bout.bpla(\"|#2NN Description                       Path Name\", &abort);\n  bout.bpla(\"|#7== --------------------------------  =================================== \", &abort);\n  for (auto chain_num = 0; chain_num < size_int(a()->chains->chains()) && !abort; chain_num++) {\n    const auto s = chaindata(chain_num);\n    bout.bpla(s, &abort);\n  }\n}\n\nvoid ShowChainCommandLineHelp() {\n  bout.outstr(\"|#2Macro Value\\r\\n\");\n  bout.outstr(\"|#7===== ===============================================================\\r\\n\");\n  bout.outstr(\"|#1  %% |#9 A single '%' Character\\r\\n\");\n  bout.outstr(\"|#1  %1 |#9 CHAIN.TXT full pathname (legacy parameter)\\r\\n\");\n  bout.outstr(\"|#1  %A |#9 CALLINFO.BBS full pathname \\r\\n\");\n  bout.outstr(\"|#1  %C |#9 CHAIN.TXT full pathname \\r\\n\");\n  bout.outstr(\"|#1  %D |#9 DORIFOx.DEF full pathname \\r\\n\");\n  bout.outstr(\"|#1  %E |#9 DOOR32.SYS full pathname \\r\\n\");\n  bout.outstr(\"|#1  %H |#9 Socket Handle \\r\\n\");\n  bout.outstr(\"|#1  %I |#9 TEMP directory for the instance \\r\\n\");\n  bout.outstr(\"|#1  %K |#9 GFiles Comment File For Archives\\r\\n\");\n  bout.outstr(\"|#1  %M |#9 Modem Baud Rate\\r\\n\");\n  bout.outstr(\"|#1  %N |#9 Node (Instance) number\\r\\n\");\n  bout.outstr(\"|#1  %O |#9 PCBOARD.SYS full pathname\\r\\n\");\n  bout.outstr(\"|#1  %P |#9 ComPort Number\\r\\n\");\n  bout.outstr(\"|#1  %R |#9 DOOR.SYS Full Pathname\\r\\n\");\n  bout.outstr(\"|#1  %S |#9 Com Port Baud Rate\\r\\n\");\n  bout.outstr(\"|#1  %T |#9 Minutes Remaining\\r\\n\");\n  bout.outstr(\"|#1  %U |#9 Users Handle (primary name)\\r\\n\");\n  bout.outstr(\"|#1  %Z |#9Socket port/path '12345' or '/wwiv/bbs/e/1/scratch/wwiv.sock'\\r\\n\");\n  bout.nl();\n}\n\nstatic std::string YesNoStringList(bool b, const std::string& yes, const std::string& no) {\n  return b ? yes : no;\n}\n\nstatic void list_chain_sponsors(const std::set<short> sponsors, char letter) {\n  if (sponsors.empty()) {\n    if (letter) {\n      bout.print(\"|#9{:c}) \", letter);\n    }\n    bout.pl(\"Registered by: |#2AVAILABLE\");\n    return;\n  }\n\n  const std::string second(letter ? 18 : 15, ' ');\n  bool first = true;\n  for (const auto& r : sponsors) {\n    if (const auto user = a()->users()->readuser(r)) {\n      if (first) {\n        if (letter) {\n          bout.print(\"|#9{:c}) \", letter);\n        }\n        bout.outstr(\"Registered by: |#2\");\n      } else {\n        bout.print(\"{}|#2\", second);\n      }\n      first = false;\n      bout.pl(user->name_and_number());\n    }  \n  }\n}\n\nstatic void modify_chain_sponsors(int chain_num, chain_t& c) {\n  auto done = false;\n  do {\n    bout.cls();\n    bout.litebar(fmt::format(\"Editing Chain #{}\", chain_num));\n    list_chain_sponsors(c.regby, 0);\n    bout.nl();\n    bout.outstr(\"|#9(A)dd, (R)emove, (Q)uit: Which (A,R,Q) ? \");\n    switch (const auto ch = onek(\"QARQ\", true); ch) {\n    case 'Q':\n      return;\n    case 'A': {\n      if (c.regby.size() > 5) {\n        bout.pl(\"|#6Only 5 sponsors allowed.\");\n        bout.pausescr();\n        break;\n      }\n      auto nn = bin.input_upper(30);\n      if (const auto user_number = finduser1(nn); user_number > 0) {\n        c.regby.insert(static_cast<int16_t>(user_number));\n      }\n    } break;\n    case 'R': {\n      auto nn = bin.input_upper(30);\n      if (const auto user_number = finduser1(nn); user_number > 0) {\n        c.regby.erase(static_cast<int16_t>(user_number));\n      }\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\nstatic std::string chain_exec_mode_to_string(const chain_exec_mode_t& t) {\n#ifdef __OS2__\n  std::vector<std::string> names{\"|#2DOOR32 (Socket)\", \"|#1Emulate DOS Interrupts\", \n\t\t\t\t   \"|#5WWIVFoss OS/2\", \"|#3STDIO\", \"|#5NetFoss\"};\n#else\n  std::vector<std::string> names{\"|#2DOOR32 (Socket)\", \n    \t\t                         \"|#1Emulate DOS Interrupts\", \n\t\t\t\t                         \"|#5SyncFoss\",        \n                                 \"|#3STDIO\",\n                                 \"|#5NetFoss\",\n                                 \"|#7Listen Socket Port\",\n                                 \"|#7Listen UNIX Socket\"};\n#endif\n  try {\n    return names.at(static_cast<size_t>(t));\n  } catch (std::out_of_range&) {\n    return names.at(0);\n  }\n}\n\nstatic void modify_chain(ssize_t chain_num) {\n  auto c = a()->chains->at(chain_num);\n  auto done = false;\n  do {\n    bout.cls();\n    bout.litebar(fmt::format(\"Editing Chain #{}\", chain_num));\n\n    bout.print(\"|#9A) Description  : |#2{}\\r\\n\", c.description);\n    bout.print(\"|#9B) Filename     : |#2{}\\r\\n\", c.filename);\n    bout.print(\"|#9C) ACS          : |#2{}\\r\\n\", c.acs);\n    bout.print(\"|#9D) ANSI         : |#2{}\\r\\n\", (c.ansi ? \"|#2Required\" : \"|#5Optional\"));\n    bout.print(\"|#9E) Exec Mode    : |#2{}\\r\\n\", chain_exec_mode_to_string(c.exec_mode));\n    const auto launch_from = YesNoStringList(c.dir == chain_exec_dir_t::temp, \"Temp/Node Directory\",\n                                             \"BBS Root Directory\");\n    if (c.exec_mode == chain_exec_mode_t::netfoss) {\n      bout.pl(\"|#9F) Launch From  : |08Temp/Node Directory\");\n    } else {\n      bout.print(\"|#9F) Launch From  : |#2{}\\r\\n\",launch_from);\n    }\n    bout.print(\"|#9G) Local only   : |#2{}\\r\\n\", YesNoString(c.local_only));\n    bout.print(\"|#9H) Multi user   : |#2{}\\r\\n\", YesNoString(c.multi_user));\n    bout.print(\"|#9I) Usage        : |#2{}\\r\\n\", c.usage);\n    std::string allowed = \"QABCDEFGHIKL[]\";\n    list_chain_sponsors(c.regby, 'J');\n#ifdef _WIN32\n  if (c.exec_mode == chain_exec_mode_t::netfoss || c.exec_mode == chain_exec_mode_t::fossil) {\n    bout.pl(\"|#9K) Local CP437  : |08Yes\");\n  } else {\n    bout.print(\"|#9K) Local CP437  : |#2{}\\r\\n\", YesNoString(c.local_console_cp437));\n  }\n#endif\n    bout.print(\"|#9L) Pause after  : |#2{}\\r\\n\", YesNoString(c.pause));\n    bout.nl();\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Which (|#1A|#7-|#1JL|#7,|#1[|#7=|#1Prev|#7,|#1]|#7=|#1Next|#7) : \");\n    allowed.push_back('J');\n    const auto ch = onek(allowed, true);\n    switch (ch) {\n    case 'Q': {\n      done = true;\n    } break;\n    case '[':\n      a()->chains->at(chain_num) = c;\n      if (--chain_num < 0) {\n        chain_num = size_int(a()->chains->chains()) - 1;\n      }\n      c = a()->chains->at(chain_num);\n      break;\n    case ']':\n      a()->chains->at(chain_num) = c;\n      if (++chain_num >= size_int(a()->chains->chains())) {\n        chain_num = 0;\n      }\n      c = a()->chains->at(chain_num);\n      break;\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"|#7New Description? \");\n      auto descr = bin.input_text(c.description, 40);\n      if (!descr.empty()) {\n        c.description = descr;\n      }\n    } break;\n    case 'B': {\n      bout.cls();\n      ShowChainCommandLineHelp();\n      bout.outstr(\"\\r\\n|#9Enter Command Line.\\r\\n|#7:\");\n      c.filename = bin.input_cmdline(c.filename, 79);\n    } break;\n    case 'C': {\n      bout.nl();\n      c.acs = input_acs(bin, bout, \"New ACS?\", c.acs, 78);\n    } break;\n    case 'D':\n      c.ansi = !c.ansi;\n      break;\n    case 'E':\n      ++c.exec_mode;\n#if defined (__OS2__)\n      if (c.exec_mode == chain_exec_mode_t::stdio) {\n        ++c.exec_mode;\n      }\n      if (c.exec_mode == chain_exec_mode_t::dos) {\n        c.exec_mode++;\n      }\n      if (c.exec_mode == chain_exec_mode_t::netfoss) {\n        c.exec_mode++;\n      }\n      if (c.exec_mode == chain_exec_mode_t::sock_port ||\n          c.exec_mode == chain_exec_mode_t::sock_unix) {\n        c.exec_mode++;\n      }\n#elif defined(__unix__)\n      if (c.exec_mode == chain_exec_mode_t::dos) {\n        c.exec_mode++;\n      }\n      if (c.exec_mode == chain_exec_mode_t::fossil) {\n        c.exec_mode++;\n      }\n      if (c.exec_mode == chain_exec_mode_t::netfoss) {\n        c.exec_mode++;\n      }\n#endif\n      break;\n    case 'F':\n      if (c.exec_mode == chain_exec_mode_t::netfoss) {\n        c.dir = chain_exec_dir_t::temp;\n      } else {\n        ++c.dir;\n      }\n      break;\n    case 'G':\n      c.local_only = !c.local_only;\n      break;\n    case 'H':\n      c.multi_user = !c.multi_user;\n      break;\n    case 'I': {\n      bout.nl();\n      bout.outstr(\"|#5Times Run : \");\n      c.usage = bin.input_number(c.usage);\n    } break;\n    case 'J':\n      modify_chain_sponsors(chain_num, c);\n      break;\n    case 'K': {\n#ifdef _WIN32\n      if (!(c.exec_mode == chain_exec_mode_t::netfoss || c.exec_mode == chain_exec_mode_t::fossil)) {\n        c.local_console_cp437 = !c.local_console_cp437;\n      }\n#endif\n    } break;\n    case 'L': \n      c.pause = !c.pause;\n      break;\n    \n    }\n  } while (!done && !a()->sess().hangup());\n  a()->chains->at(chain_num) = c;\n}\n\nstatic void insert_chain(size_t pos) {\n  chain_t c{};\n  c.description = \"** NEW CHAIN **\";\n  c.filename = \"REM\";\n  c.acs = \"user.sl >= 10\";\n  c.exec_mode = chain_exec_mode_t::none;\n  a()->chains->insert(pos, c);\n  modify_chain(pos);\n}\n\nvoid delete_chain(size_t chain_num) {\n  a()->chains->erase(chain_num);\n}\n\nvoid chainedit() {\n  if (!ValidateSysopPassword()) {\n    return;\n  }\n  showchains();\n  auto done = false;\n  do {\n    bout.nl();\n    bout.outstr(\"|#7Chains: (D)elete, (I)nsert, (M)odify, (Q)uit, ? : \");\n    const auto ch = onek(\"QDIM?\");\n    switch (ch) {\n    case '?':\n      showchains();\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'M': {\n      bout.nl();\n      bout.outstr(\"|#2(Q=Quit) Chain number? \");\n      auto r = bin.input_number_hotkey(0, {'Q'}, 0, size_int(a()->chains->chains()), false);\n      if (r.key != 'Q' && r.num < size_int(a()->chains->chains())) {\n        modify_chain(r.num);\n      }\n    } break;\n    case 'I': {\n      if (a()->chains->chains().size() < a()->max_chains) {\n        bout.nl();\n        bout.outstr(\"|#2(Q=Quit) Insert before which chain ('$' for end) : \");\n        auto r = bin.input_number_hotkey(0, {'$', 'Q'}, 0, size_int(a()->chains->chains()), false);\n        if (r.key == 'Q') {\n          break;\n        }\n        const auto chain = (r.key == '$') ? size_int(a()->chains->chains()) : r.num;\n        if (chain >= 0 && chain <= size_int(a()->chains->chains())) {\n          insert_chain(chain);\n        }\n      }\n    } break;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#2(Q=Quit) Delete which chain? \");\n      auto r = bin.input_number_hotkey(0, {'$', 'Q'}, 0, size_int(a()->chains->chains()), false);\n      if (r.key == 'Q') {\n        break;\n      }\n      if (r.num >= 0 && r.num < size_int(a()->chains->chains())) {\n        bout.nl();\n        bout.print(\"|#5Delete {}? \", a()->chains->at(r.num).description);\n        if (bin.yesno()) {\n          delete_chain(r.num);\n        }\n      }\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n\n  a()->chains->Save();\n}\n"
  },
  {
    "path": "bbs/chnedit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CHNEDIT_H\n#define INCLUDED_BBS_CHNEDIT_H\n\nvoid chainedit();\n\n#endif\n"
  },
  {
    "path": "bbs/common.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef __INCLUDED_COMMON_H__\n#define __INCLUDED_COMMON_H__\n\n#include \"core/wwivport.h\"\n#include \"sdk/wwivcolors.h\"\n#include <string>\n\n// Defines for listplus\nconstexpr int LP_LIST_DIR = 0;\nconstexpr int LP_SEARCH_ALL = 1;\nconstexpr int LP_NSCAN_DIR = 2;\nconstexpr int LP_NSCAN_NSCAN = 3;\n\nconstexpr int ALL_DIRS = 0;\nconstexpr int THIS_DIR = 1;\nconstexpr int NSCAN_DIRS = 2;\n\nconstexpr int WWIV_LISTPLUS_NORMAL_HIGHLIGHT =\n    (static_cast<uint8_t>(wwiv::sdk::Color::YELLOW) +\n     (static_cast<uint8_t>(wwiv::sdk::Color::BLACK) << 4));\nconstexpr int WWIV_LISTPLUS_NORMAL_MENU_ITEM =\n    (static_cast<uint8_t>(wwiv::sdk::Color::CYAN) +\n     (static_cast<uint8_t>(wwiv::sdk::Color::BLACK) << 4));\nconstexpr int WWIV_LISTPLUS_CURRENT_HIGHLIGHT =\n    (static_cast<uint8_t>(wwiv::sdk::Color::RED) +\n     (static_cast<uint8_t>(wwiv::sdk::Color::LIGHTGRAY) << 4));\nconstexpr int WWIV_LISTPLUS_CURRENT_MENU_ITEM =\n    (static_cast<uint8_t>(wwiv::sdk::Color::BLACK) +\n     (static_cast<uint8_t>(wwiv::sdk::Color::LIGHTGRAY) << 4));\n\nstruct side_menu_colors {\n  int normal_highlight = WWIV_LISTPLUS_NORMAL_HIGHLIGHT;\n  int normal_menu_item = WWIV_LISTPLUS_NORMAL_MENU_ITEM;\n  int current_highlight = WWIV_LISTPLUS_CURRENT_HIGHLIGHT;\n  int current_menu_item = WWIV_LISTPLUS_CURRENT_MENU_ITEM;\n};\n\nstruct search_record {\n  std::string filemask;\n  daten_t nscandate{0};\n  std::string search;\n\n  int alldirs{0};\n  bool search_extended{false};\n};\n\n#endif // __INCLUDED_COMMON_H__\n"
  },
  {
    "path": "bbs/conf.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/conf.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/mmkey.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/input_range.h\"\n#include \"common/pause.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/files/dirs.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic int disable_conf_cnt = 0;\n\nnamespace wwiv::bbs {\n\nTempDisableConferences::TempDisableConferences()\n    : wwiv::core::Transaction([] { tmp_disable_conf(false); }, nullptr) {\n  tmp_disable_conf(true);\n}\n\n} // namespace wwiv\n\nvoid tmp_disable_conf(bool disable) {\n  static int ocs = 0, oss = 0, ocd = 0, osd = 0;\n\n  if (disable) {\n    disable_conf_cnt++;\n    if (okconf(a()->user())) {\n      a()->sess().disable_conf(true);\n      ocs = a()->sess().current_user_sub_conf_num();\n      oss = a()->current_user_sub().subnum;\n      ocd = a()->sess().current_user_dir_conf_num();\n      osd = a()->current_user_dir().subnum;\n      clear_usersubs(a()->all_confs().subs_conf(), a()->usub, oss);\n      clear_usersubs(a()->all_confs().dirs_conf(), a()->udir, oss);\n    }\n  } else if (disable_conf_cnt) {\n    disable_conf_cnt--;\n    if (disable_conf_cnt == 0 && a()->sess().disable_conf()) {\n      a()->sess().disable_conf(false);\n      auto key = at(a()->uconfsub, ocs).key.key();\n      setuconf(a()->all_confs().subs_conf(), key, oss);\n      key = at(a()->uconfdir, ocd).key.key();\n      setuconf(a()->all_confs().dirs_conf(), key, osd);\n    }\n  }\n}\n\nvoid reset_disable_conf() { disable_conf_cnt = 0; }\n\nconf_info_t get_conf_info(ConferenceType conftype) {\n  if (conftype == ConferenceType::CONF_DIRS) {\n    conf_info_t ret(a()->all_confs().dirs_conf(), a()->uconfdir);\n    ret.file_name = FilePath(a()->config()->datadir(), DIRS_CNF).string();\n    ret.num_subs_or_dirs = a()->dirs().size();\n    return ret;\n  }\n\n  conf_info_t ret(a()->all_confs().subs_conf(), a()->uconfsub);\n  ret.file_name = FilePath(a()->config()->datadir(), SUBS_CNF).string();\n  ret.num_subs_or_dirs = size_int(a()->subs().subs());\n  return ret;\n}\n\n/**\n * Select a free (unused) conf key\n */\n static std::optional<char> select_free_conf_key(Conference& conf, bool listconfs) {\n  if (listconfs) {\n    bout.nl();\n    list_confs(conf, false);\n  }\n  std::set<char> current;\n  for (const auto& cp : conf.confs()) {\n    current.insert(cp.key.key());\n  }\n  std::string allowed(\" \\r\\n\");\n  for (auto c = 'A'; c <= 'Z'; c++) {\n    if (!contains(current, c)) {\n      allowed.push_back(c);\n    }\n  }\n  bout.print(\"|#9Select a free conference key (|#1{}|#9): \", allowed);\n  const auto key = onek(allowed, true);\n  if (key == ' ' || key == '\\r' || key == '\\n') {\n    return std::nullopt;\n  }\n  return { key };\n}\n\n\n/*\n * Presents user with selection of conferences, gets selection, and changes\n * conference.\n */\nvoid jump_conf(ConferenceType conftype) {\n  bout.litebar(StrCat(a()->config()->system_name(), \" Conference Selection\"));\n  auto info = get_conf_info(conftype);\n  std::string allowable = \" \";\n  bout.nl();\n  for (const auto& uc : info.uc) {\n    if (bin.checka())\n      break;\n    const auto ac = uc.key.key();\n    bout.print(\"|#2{}|#7)|#1 {}\\r\\n\", ac, stripcolors(uc.conf_name));\n    allowable.push_back(ac);\n  }\n\n  bout.nl();\n  bout.print(\"|#2Select [{}, <space> to quit]: \", allowable.substr(1));\n  const auto ch = onek(allowable);\n  if (ch == ' ') {\n    return;\n  }\n  auto& conf = conftype == ConferenceType::CONF_SUBS ? a()->all_confs().subs_conf() : a()->all_confs().dirs_conf();\n  auto& uc = conftype == ConferenceType::CONF_SUBS ? a()->uconfsub : a()->uconfdir;\n  if (const auto o = conf.try_conf(ch)) {\n    setuconf(conf, o.value().key.key(), -1);\n    for (auto i=0; i < size_int(uc); i++) {\n      if (ch == at(uc, i).key.key()) {\n        if (conftype == ConferenceType::CONF_SUBS) {\n          a()->sess().set_current_user_sub_conf_num(i);\n        } else {\n          a()->sess().set_current_user_dir_conf_num(i);\n        }\n      }\n    }\n  }\n}\n\nstatic int display_conf_subs(Conference& conf) {\n  auto abort = false;\n  bout.cls();\n  bout.bpla(\"|#2NN  Name                                    ConfList\", &abort);\n  bout.bpla(\"|#7--- ======================================= ==========================\", &abort);\n\n  auto count = 0;\n  switch (conf.type()) {\n  case ConferenceType::CONF_SUBS: {\n    count = size_int(a()->subs().subs());\n    for (auto i = 0; i < count; i++) {\n      const auto& sub = a()->subs().sub(i);\n      const auto s =\n          fmt::sprintf(\"|#2%3d |#1%-39.39s |#5%s\", i, stripcolors(sub.name), sub.conf.to_string());\n      bout.bpla(s, &abort);\n    }\n  } break;\n  case ConferenceType::CONF_DIRS: {\n    count = size_int(a()->dirs().dirs());\n    for (auto i = 0; i < count; i++) {\n      const auto& dir = a()->dirs().dir(i);\n      const auto s =\n          fmt::sprintf(\"|#2%3d |#1%-39.39s |#5%s\", i, stripcolors(dir.name), dir.conf.to_string());\n      bout.bpla(s, &abort);\n    }\n  } break;\n  }\n  return count;\n}\n\nstatic conf_set_t& get_conf_set(Conference& conf, int num) {\n  if (conf.type() == ConferenceType::CONF_DIRS) {\n    return a()->dirs().dir(num).conf;\n  }\n  return a()->subs().sub(num).conf;\n}\n\nvoid edit_conf_subs(Conference& conf) {\n  auto changed{false};\n  while (!a()->sess().hangup()) {\n    const auto count = display_conf_subs(conf);\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9)uit, (|#2S|#9)et, (|#2C|#9)lear, (|#2T|#9)oggle conferences, (|#2?|#9) List conferences: \");\n    const auto cmd = onek_ncr(\"CSTQ?\");\n    if (cmd == 'Q') {\n      break;\n    } if (cmd == '?') {\n      list_confs(conf, false);\n      bout.pausescr();\n      continue;\n    }\n    bout.Left(80);\n    bout.clreol();\n    bout.outstr(\"|#9(|#2ENTER|#9=Exit) Enter conference key: \");\n    const auto key = onek_ncr(StrCat(\"\\r\\n\\x1b\", conf.keys_string()));\n    if (key == 0 || key == '\\r' || key == '\\n' || key == ESC) {\n      continue;\n    }\n\n    bout.Left(80);\n    bout.clreol();\n    bout.outstr(\"|#9Enter range (i.e. 1-10, 5, etc): \");\n    std::set<int> range;\n    for (auto i=0; i <count; i++) {\n      range.insert(i);\n    }\n    if (auto o = input_range(bin, 40, range)) {\n      const auto& r = o.value();\n      for (const auto n : r) {\n        auto& cs = get_conf_set(conf, n);\n        changed = true;\n        switch (cmd) {  // NOLINT(hicpp-multiway-paths-covered)\n        case 'S':\n          cs.insert(key);\n          break;\n        case 'C':\n          cs.erase(key);\n          break;\n        case 'T':\n          cs.toggle(key);\n          break;\n        }\n      }\n    }\n  }\n\n  if (changed) {\n    if (conf.type() == ConferenceType::CONF_DIRS) {\n      a()->dirs().Save();      \n    } else if (conf.type() == ConferenceType::CONF_SUBS) {\n      a()->subs().Save();\n    }\n  }\n}\n\n\n/*\n * Function for editing the data for one conference.\n */\nstatic void modify_conf(Conference& conf, char key) {\n  auto changed = false;\n  auto done = false;\n\n  if (!conf.exists(key)) {\n    return;\n  }\n\n  do {\n    auto& c = conf.conf(key);\n    bout.cls();\n    bout.litebar(\"Edit Conference\");\n\n    bout.print(\"|#9A) Key  : |#2{}\\r\\n\", c.key.key());\n    bout.print(\"|#9B) Name : |#2{}\\r\\n\", c.conf_name);\n    bout.print(\"|#9C) ACS  : |#2{}\\r\\n\", c.acs);\n    bout.nl();\n\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Conference Edit [|#1A|#7-|#1C|#7] : \");\n    const auto ch = onek(\"QABC\", true);\n\n    switch (ch) { // NOLINT(hicpp-multiway-paths-covered)\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"|#2New Key: \");\n      const auto ch1 = onek(\"\\rABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n      if (ch1 == c.key.key() || ch1 == '\\r') {\n        break;\n      }\n      if (conf.exists(ch1)) {\n        bout.nl();\n        bout.outstr(\"|#6That key already in use!\\r\\n\");\n        bout.pausescr();\n        break;\n      }\n      c.key.key(ch1);\n      changed = true;\n    } break;\n    case 'B': {\n      bout.nl();\n      bout.outstr(\"|#2Conference Name: \");\n      auto cname = bin.input_text(60);\n      if (!cname.empty()) {\n        c.conf_name = cname;\n        changed = true;\n      }\n    } break;\n    case 'C': {\n      bout.nl();\n      c.acs = wwiv::bbs::input_acs(bin, bout, \"New ACS?\", c.acs, 60);\n      changed = true;\n    } break;\n    case 'Q':\n      done = true;\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n\n  if (changed) {\n    a()->all_confs().Save();\n  }\n}\n\n/*\n * Function for inserting one conference.\n */\nstatic void insert_conf(Conference& conf, char key) {\n\n  conference_t c{};\n  c.key.key(key);\n  c.conf_name = StrCat(\"Conference \", c.key);\n  c.acs = \"\";\n\n  conf.add(c);\n\n  if (!a()->all_confs().Save()) {\n    LOG(ERROR) << \"Unable to save conferences.\";\n  }\n\n  modify_conf(conf, key);\n}\n\n/**\n * Function for deleting one conference.\n */\nstatic void delete_conf(Conference& conf, char key) {\n  conf.erase(key);\n  a()->all_confs().Save();\n}\n\n/**\n * Function for editing conferences.\n */\nvoid conf_edit(Conference& conf) {\n  auto done = false;\n\n  do {\n    list_confs(conf, false);\n    bout.nl();\n    bout.outstr(\"|#2I|#7)|#1nsert, |#2D|#7)|#1elete, |#2M|#7)|#1odify, |#2Q|#7)|#1uit, |#2S|#7)|#1ubs Configuration|#2? |#7 : \");\n    const auto ch = onek(\"QIDMS?\", true);\n    switch (ch) { // NOLINT(hicpp-multiway-paths-covered)\n    case 'D':\n      if (conf.size() == 1) {\n        bout.outstr(\"\\r\\n|#6Cannot delete all conferences!\\r\\n\");\n      } else {\n        if (auto ec = select_conf(\"Delete which conference? \", conf, false)) {\n          delete_conf(conf, ec.value());\n        }\n      }\n      break;\n    case 'I':\n      if (conf.size() == MAX_CONFERENCES) {\n        bout.outstr(\"\\r\\n|#6Cannot insert any more conferences!\\r\\n\");\n      } else {\n        if (auto ec = select_free_conf_key(conf, false)){\n          insert_conf(conf, ec.value());\n        }\n      }\n      break;\n    case 'M': {\n      if (auto ec = select_conf(\"Modify which conference? \", conf, false)) {\n        modify_conf(conf, ec.value());\n      }\n    } break;\n    case 'S':\n      edit_conf_subs(conf);\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case '?':\n      bout.cls();\n      list_confs(conf, false);\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n  if (!a()->at_wfc()) {\n    changedsl();\n  }\n}\n\n/*\n * Lists conferences of a specified type.\n */\nvoid list_confs(ConferenceType conftype, bool list_subs) {\n  if (conftype == ConferenceType::CONF_SUBS) {\n    return list_confs(a()->all_confs().subs_conf(), list_subs);\n  }\n  return list_confs(a()->all_confs().dirs_conf(), list_subs);\n}\n\nvoid list_confs(Conference& conf, bool list_subs) {\n  bout.cls();\n  auto abort = false;\n  bout.bpla(\"|#2Key Name                    ACS\", &abort);\n  bout.bpla(\"|#7--- ======================= -------------------------------------------------\",\n            &abort);\n\n  for (const auto& cp : conf.confs()) {\n    if (abort) {\n      break;\n    }\n    const auto l = fmt::sprintf(\"|#2 %c |#1 %-23.23s |#5%s\", cp.key.key(), cp.conf_name, cp.acs);\n    bout.bpla(l, &abort);\n    if (!list_subs) {\n      continue;\n    }\n    auto subnum = 0;\n    for (const auto& sub : a()->subs().subs()) {\n      if (sub.conf.contains(cp.key.key())) {\n        const auto ll = fmt::format(\"   \\xC3\\xC4\\xC4\\xC4 |#9Sub #{:<3} : {}\", subnum, sub.name);\n        bout.ansic(7);\n        bout.bpla(ll, &abort);\n      }\n      ++subnum;\n    }\n  }\n  bout.nl();\n}\n\n/*\n * Allows user to select a conference. Returns the conference selected\n * (0-based), or -1 if the user aborted. Error message is printed for\n * invalid conference selections.\n */\nstd::optional<char> select_conf(const std::string& prompt_text, Conference& conf, bool listconfs) {\n  if (listconfs) {\n    bout.nl();\n    list_confs(conf, false);\n  }\n  std::string allowed(\" \\r\\n?\\x1b\");\n  for (const auto& cp : conf.confs()) {\n    allowed.push_back(cp.key.key());\n  }\n  while (!a()->sess().hangup()) {\n    if (!prompt_text.empty()) {\n      bout.nl();\n      bout.print(\"|#1{}\", prompt_text);\n    }\n    auto key = onek(allowed, true);\n    if (key == ' ' || key == '\\r' || key == '\\n' || key == ESC) {\n      return std::nullopt;\n    }\n    if (key == '?') {\n      bout.nl();\n      list_confs(conf, false);\n      continue;\n    }\n    if (conf.exists(key)) {\n      return {key};\n    }\n    bout.outstr(\"\\r\\n|#6Invalid conference key!\\r\\n\");\n  }\n  return std::nullopt;\n}\n"
  },
  {
    "path": "bbs/conf.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CONF_H\n#define INCLUDED_BBS_CONF_H\n\n#include \"core/transaction.h\"\n#include \"sdk/conf/conf.h\"\n#include <string>\n\nnamespace wwiv::bbs {\nclass TempDisableConferences: public core::Transaction {\npublic:\n  TempDisableConferences();\n};\n\n}  // namespace\n\nclass conf_info_t {\npublic:\n  conf_info_t(wwiv::sdk::Conference& c, std::vector<wwiv::sdk::conference_t>& u)\n      : confs(c), uc(u), num_confs(c.size()) {}\n\n  wwiv::sdk::Conference& confs;\n  std::vector<wwiv::sdk::conference_t>& uc;\n  int num_confs;\n  std::string file_name;\n  int num_subs_or_dirs = 0;\n};\n\nvoid tmp_disable_conf(bool disable);\nvoid reset_disable_conf();\nconf_info_t get_conf_info(wwiv::sdk::ConferenceType conftype);\n\nvoid jump_conf(wwiv::sdk::ConferenceType conftype);\nvoid conf_edit(wwiv::sdk::Conference& conf);\nvoid list_confs(wwiv::sdk::ConferenceType conftype, bool list_subs);\nvoid list_confs(wwiv::sdk::Conference& conf, bool list_subs = true);\nstd::optional<char> select_conf(const std::string& prompt_text, wwiv::sdk::Conference& conf,\n                                bool listconfs);\n\n/**\n * Select the conferences to which dirs and subs belong.\n */\nvoid edit_conf_subs(wwiv::sdk::Conference& conf);\n\n#endif\n"
  },
  {
    "path": "bbs/confutil.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/confutil.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/conf.h\"\n#include \"core/stl.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/files/dirs.h\"\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\n\nstatic bool access_sub(User& u, const subboard_t& s) {\n  if (!check_acs(s.read_acs)) {\n    return false;\n  }\n\n  if ((s.anony & anony_ansi_only) && !u.ansi()) {\n    return false;\n  }\n\n  return true;\n}\n\nstatic void addusub(std::vector<usersubrec>& us, int sub, char key = 0) {\n  for (auto& u : us) {\n    if (u.subnum == sub) {\n      // we already have this sub.\n      return;\n    }\n  }\n  usersubrec c{};\n  c.subnum = static_cast<int16_t>(sub);\n  if (key) {\n    c.keys = key;\n  }\n  us.emplace_back(c);\n}\n\n// Populates uc with the user visible subs for the current conference.\nstatic bool create_usersubs(Conference& conf, std::vector<usersubrec>& uc, \n                            char conf_key, int old_subnum) {\n  if (auto o = conf.try_conf(conf_key)) {\n    auto new_conf_subnum = -1;\n    // We found the conference.\n    const auto& c = o.value();\n    if (!check_acs(c.acs)) {\n      return false;\n    }\n\n    uc.clear();\n    if (conf.type() == ConferenceType::CONF_SUBS) {\n      const auto& subs = a()->subs().subs();\n      for (auto subnum = 0; subnum < size_int(subs); subnum++) {\n        const auto& s = at(subs, subnum);\n        if (!s.conf.contains(conf_key)) {\n          continue;\n        }\n        // This sub is in our current conference.\n        if (!check_acs(s.read_acs)) {\n          continue;\n        }\n        addusub(uc, subnum, s.key);\n      }\n    } else {\n      const auto& dirs = a()->dirs().dirs();\n      for (auto subnum = 0; subnum < size_int(dirs); subnum++) {\n        const auto& s = at(dirs, subnum);\n        if (!s.conf.contains(conf_key)) {\n          continue;\n        }\n        // This sub is in our current conference.\n        if (!check_acs(s.acs)) {\n          continue;\n        }\n        addusub(uc, subnum);\n      }\n    }\n\n    auto num_key = 1;\n    for (auto i = 0; i < size_int(uc); i++) {\n      auto& u = at(uc, i);\n      if (u.keys.empty()) {\n        u.keys = std::to_string(num_key++);\n      }\n      if (u.subnum == old_subnum) {\n        // We have a new subnum position within this conference.\n        new_conf_subnum = i;\n      }\n    }\n\n    if (conf.type() == ConferenceType::CONF_SUBS) {\n      a()->set_current_user_sub_num(new_conf_subnum != -1 ? new_conf_subnum : 0);\n    } else {\n      a()->set_current_user_dir_num(new_conf_subnum != -1 ? new_conf_subnum : 0);\n    }\n    return true;\n  }\n  return false;\n}\n\nbool access_at_least_one_conf(Conference& conf, const conf_set_t& e) {\n  for (auto c : e.data_) {\n    if (auto o = conf.try_conf(c)) {\n      if (!check_acs(o.value().acs)) {\n        return false;\n      }\n    } else {\n      return false;\n    }\n  }\n  return true;\n}\n\n// Populates uc with the user visible subs for the current conference.\nbool clear_usersubs(Conference& conf, std::vector<usersubrec>& uc, int old_subnum) {\n  if (conf.empty()) {\n    const wwiv::sdk::key_t key('A');\n    conf.add(conference_t{key, \"General\", \"\"});\n  }\n  auto new_conf_subnum = -1;\n  uc.clear();\n  // iterate through each sub and make sure we have access to at least\n  // one conference for this sub.\n  if (conf.type() == ConferenceType::CONF_SUBS) {\n    const auto& subs = a()->subs().subs();\n    for (auto subnum = 0; subnum < size_int(subs); subnum++) {\n      const auto& s = at(subs, subnum);\n      if (!access_at_least_one_conf(conf, s.conf)) {\n        continue;\n      }\n      // This sub is in our current conference.\n      if (!access_sub(*a()->user(), s)) {\n        continue;\n      }\n      addusub(uc, subnum, s.key);\n    }\n  } else {\n    const auto& dirs = a()->dirs().dirs();\n    for (auto subnum = 0; subnum < size_int(dirs); subnum++) {\n      const auto& s = at(dirs, subnum);\n      if (!access_at_least_one_conf(conf, s.conf)) {\n        continue;\n      }\n      // This sub is in our current conference.\n      if (!check_acs(s.acs)) {\n        continue;\n      }\n      addusub(uc, subnum);\n    }\n  }\n  // TODO from here on down can probably be extracted and shared\n  // with create_usersubs\n  auto num_key = 1;\n  for (auto i = 0; i < size_int(uc); i++) {\n    auto& u = at(uc, i);\n    if (u.keys.empty()) {\n      u.keys = std::to_string(num_key++);\n    }\n    if (u.subnum == old_subnum) {\n      // We have a new subnum position within this conference.\n      new_conf_subnum = i;\n    }\n  }\n\n  if (conf.type() == ConferenceType::CONF_SUBS) {\n    a()->set_current_user_sub_num(new_conf_subnum != -1 ? new_conf_subnum : 0);\n  } else {\n    a()->set_current_user_dir_num(new_conf_subnum != -1 ? new_conf_subnum : 0);\n  }\n  return true;\n}\n\nvoid setuconf(Conference& conf, char key, int old_subnum) {\n  auto& usd = conf.type() == ConferenceType::CONF_SUBS ? a()->usub : a()->udir;\n  if (conf.exists(key)) {\n    create_usersubs(conf, usd, key, old_subnum);\n  } else {\n    clear_usersubs(conf, usd, old_subnum);\n  }\n}\n\nvoid setuconf(ConferenceType conf_type, int num, int old_subnum) {\n  if (conf_type == ConferenceType::CONF_DIRS) {\n    auto& conf = a()->all_confs().dirs_conf();\n    const auto key = at(a()->uconfdir, num).key.key();\n    setuconf(conf, key, old_subnum);\n    return;\n  }\n  auto& conf = a()->all_confs().subs_conf();\n  const auto key = at(a()->uconfsub, num).key.key();\n  setuconf(conf, key, old_subnum);\n}\n\nvoid changedsl() {\n  const auto subconfkey = optional_at(a()->uconfsub, a()->sess().current_user_sub_conf_num());\n  const auto dirconfkey = optional_at(a()->uconfdir, a()->sess().current_user_dir_conf_num());\n\n  a()->UpdateTopScreen();\n  a()->uconfsub.clear();\n  a()->uconfdir.clear();\n\n  for (const auto& c : a()->all_confs().subs_conf().confs()) {\n    if (check_acs(c.acs)) {\n      a()->uconfsub.emplace_back(c);\n    }\n  }\n\n  for (const auto& c : a()->all_confs().dirs_conf().confs()) {\n    if (check_acs(c.acs)) {\n      a()->uconfdir.emplace_back(c);\n    }\n  }\n\n  // Move to first message area in new conference\n  a()->sess().set_current_user_sub_conf_num(0);\n  if (subconfkey) {\n    for (auto i = 0; i < size_int(a()->uconfsub); i++) {\n      if (at(a()->uconfsub, i).key.key() == subconfkey.value().key.key()) {\n        a()->sess().set_current_user_sub_conf_num(i);\n        break;\n      }\n    }\n  }\n  if (dirconfkey) {\n    a()->sess().set_current_user_dir_conf_num(0);\n    for (auto i = 0; i < size_int(a()->uconfdir); i++) {\n      if (at(a()->uconfdir, i).key.key() == dirconfkey.value().key.key()) {\n        a()->sess().set_current_user_dir_conf_num(i);\n        break;\n      }\n    }\n  }\n\n  if (okconf(a()->user()) && !a()->uconfsub.empty()) {\n    // Only set the subs if our conf list is not empty.\n    const auto& s = at(a()->uconfsub, a()->sess().current_user_sub_conf_num());\n    setuconf(a()->all_confs().subs_conf(), s.key.key(), -1);\n  } else {\n    clear_usersubs(a()->all_confs().subs_conf(), a()->usub, -1);\n    a()->uconfsub.emplace_back(a()->all_confs().subs_conf().front());\n  }\n\n  if (okconf(a()->user()) && !a()->uconfdir.empty()) {\n    // Only set the dirs if our conf list is not empty.\n    const auto& d = at(a()->uconfdir, a()->sess().current_user_dir_conf_num());\n    setuconf(a()->all_confs().dirs_conf(), d.key.key(), -1);\n  } else {\n    clear_usersubs(a()->all_confs().dirs_conf(), a()->udir, -1);\n    a()->uconfdir.emplace_back(a()->all_confs().dirs_conf().front());\n  }\n}\n\nbool okconf(User* user) {\n  if (a()->sess().disable_conf()) {\n    return false;\n  }\n  return user->has_flag(User::conference);\n}\n\nbool ok_multiple_conf(User* user, const std::vector<wwiv::sdk::conference_t>& uc) {\n  if (!okconf(user)) {\n    return false;\n  }\n  return uc.size() > 1;\n}\n\n"
  },
  {
    "path": "bbs/confutil.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CONFUTIL_H\n#define INCLUDED_BBS_CONFUTIL_H\n\n#include \"sdk/user.h\"\n#include \"sdk/conf/conf.h\"\n#include <vector>\n\nbool clear_usersubs(wwiv::sdk::Conference& conf, std::vector<usersubrec>& uc, int old_subnum);\nvoid setuconf(wwiv::sdk::Conference& conf, char key, int old_subnum);\nvoid setuconf(wwiv::sdk::ConferenceType type, int num, int old_subnum);\nvoid changedsl();\n\n/*\n * Checks status of given userrec to see if conferencing is turned on.\n */\nbool okconf(wwiv::sdk::User* user);\n\n/*\n * Checks status of given userrec to see if conferencing is turned on \n * *and* that multiple conferences are defined.\n */\nbool ok_multiple_conf(wwiv::sdk::User* user, const std::vector<wwiv::sdk::conference_t>& uc);\n\n/** Returns true if a user conference exists at position uc */\nbool has_userconf_to_dirconf(int uc);\n\n#endif\n"
  },
  {
    "path": "bbs/connect1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/bbs.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/net/networks.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstd::optional<net_system_list_rec> next_system(int ts) {\n  const auto b = BbsListNet::ReadBbsDataNet(a()->current_net().dir);\n  return b.node_config_for(ts);\n}\n\nbool valid_system(int ts) {\n  return next_system(ts).has_value();\n}\n\nvoid set_net_num(int network_number) {\n  if (network_number >= 0 && network_number < wwiv::stl::ssize(a()->nets())) {\n    a()->set_net_num(network_number);\n  }\n}\n\nint32_t next_system_reg(int16_t ts) {\n  const auto b = BbsListNet::ReadBbsDataNet(a()->current_net().dir);\n  if (const auto & r = b.reg_number(); r.find(ts) != r.end()) {\n    return wwiv::stl::at(r, ts);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "bbs/connect1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CONNECT1_H\n#define INCLUDED_BBS_CONNECT1_H\n\n#include <cstdint>\n#include <optional>\n\nstruct net_system_list_rec;\n\nbool valid_system(int ts);\nstd::optional<net_system_list_rec> next_system(int ts);\nvoid set_net_num(int network_number);\nint32_t next_system_reg(int16_t ts);\n\n#endif\n"
  },
  {
    "path": "bbs/crc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/crc.h\"\n#include <cstdint>\n\n/**********************************************************************\\\n|*                                                                    *|\n|* Demonstration program to compute the 32-bit CRC used as the frame  *|\n|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|\n|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|\n|* protocol).  The 32-bit FCS was added via the Federal Register,     *|\n|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|\n|* this polynomial is or will be included in CCITT V.41, which        *|\n|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|\n|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|\n|* errors by a factor of 10^-5 over 16-bit FCS.                       *|\n|*                                                                    *|\n\\**********************************************************************/\n\n/* Need an unsigned type capable of holding 32 bits; */\ntypedef unsigned long int UNS_32_BITS;\n\n/* First, the polynomial itself and its table of feedback terms.  The  */\n/* polynomial is                                                       */\n/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */\n/* Note that we take it \"backwards\" and put the highest-order term in  */\n/* the lowest-order bit.  The X^32 term is \"implied\"; the LSB is the   */\n/* X^31 term, etc.  The X^0 term (usually shown as \"+1\") results in    */\n/* the MSB being 1.                                                    */\n\n/* Note that the usual hardware shift register implementation, which   */\n/* is what we're using (we're merely optimizing it by doing eight-bit  */\n/* chunks at a time) shifts bits into the lowest-order term.  In our   */\n/* implementation, that means shifting towards the right.  Why do we   */\n/* do it this way?  Because the calculated CRC must be transmitted in  */\n/* order from highest-order term to lowest-order term.  UARTs transmit */\n/* characters in order from LSB to MSB.  By storing the CRC this way,  */\n/* we hand it to the UART in the order low-byte to high-byte; the UART */\n/* sends each low-bit to hight-bit; and the result is transmission bit */\n/* by bit from highest- to lowest-order term without requiring any bit */\n/* shuffling on our part.  Reception works similarly.                  */\n\n/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */\n/*                                                                     */\n/*  1. The table can be generated at runtime if desired; code to do so */\n/*     is shown later.  It might not be obvious, but the feedback      */\n/*     terms simply represent the results of eight shift/xor opera-    */\n/*     tions for all combinations of data and CRC register values.     */\n/*                                                                     */\n/*  2. The CRC accumulation logic is the same for all CRC polynomials, */\n/*     be they sixteen or thirty-two bits wide.  You simply choose the */\n/*     appropriate table.  Alternatively, because the table can be     */\n/*     generated at runtime, you can start by generating the table for */\n/*     the polynomial in question and use exactly the same \"updcrc\",   */\n/*     if your application needn't simultaneously handle two CRC       */\n/*     polynomials.  (Note, however, that XMODEM is strange.)          */\n/*                                                                     */\n/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */\n/*     of course, 32-bit entries work OK if the high 16 bits are zero. */\n/*                                                                     */\n/*  4. The values must be right-shifted by eight bits by the \"updcrc\"  */\n/*     logic; the shift must be unsigned (bring in zeroes).  On some   */\n/*     hardware you could probably optimize the shift in assembler by  */\n/*     using byte-swap instructions.                                   */\n\nstatic UNS_32_BITS crc_32_tab[] = {\n  /* CRC polynomial 0xedb88320 */\n  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\n  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\n  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\n  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\n  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\n  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\n  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\n  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\n  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\n  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\n  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\n  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n};\n\n\n#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))\n\nuint16_t crc;\n\nunsigned long int crc32buf(const char *buffer, std::size_t nLength) {\n  unsigned long int oldcrc32;\n  oldcrc32 = 0xFFFFFFFF;\n  for (; nLength; --nLength, ++buffer) {\n    oldcrc32 = UPDC32(*buffer, oldcrc32);\n  }\n  return ~oldcrc32;\n}\n"
  },
  {
    "path": "bbs/crc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_CRC_H\n#define INCLUDED_BBS_CRC_H\n\n#include <cstddef>\n#include <cstdint>\n\nunsigned long int crc32buf(const char *buffer, std::size_t nLength);\n\n// used by old sr.cpp and friends.\nextern uint16_t crc;\n\n#endif  // INCLUDED_BBS_CRC_H\n"
  },
  {
    "path": "bbs/datetime_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"common/datetime.h\"\n#include <chrono>\n#include <ctime>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\n\nTEST(DateTime, isleap) {\n  ASSERT_TRUE(isleap(2000));\n  ASSERT_TRUE(isleap(2004));\n  ASSERT_TRUE(isleap(2008));\n  ASSERT_FALSE(isleap(2014));\n  ASSERT_FALSE(isleap(2100));\n}\n\n"
  },
  {
    "path": "bbs/defaults.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/defaults.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl3.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/common.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/inetmsg.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/misccmd.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/newuser.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/qwk/qwk.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"menus/config_menus.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/net/networks.h\"\n\n#include <sstream>\n#include <string>\n#include <vector>\n\nusing wwiv::common::InputMode;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic const int STOP_LIST = 0;\nstatic const int MAX_SCREEN_LINES_TO_SHOW = 24;\n\nvoid select_editor() {\n  bout.outstr(\"|#10|#9) Line Editor\\r\\n\");\n  if (okansi() && a()->IsUseInternalFsed()) {\n    bout.outstr(\"|#1A|#9) Full-Screen Editor\\r\\n\");\n  }\n  for (auto i = 0; i < size_int(a()->editors); i++) {\n    bout.print(\"|#1{}|#9) {}\\r\\n\", i+1, a()->editors[i].description);\n  }\n  std::set<char> keys;\n  keys.insert('Q');\n  bout.nl();\n  bout.outstr(\"|#9Which editor (|#1\");\n  if (okansi() && a()->IsUseInternalFsed()) {\n    keys.insert('A');\n    bout.outstr(\"A|#9, |#1\");\n  }\n  bout.print(\"1-{}, |#9(Q=No Change) ? \", a()->editors.size());\n  const auto cur_editor = a()->user()->default_editor();\n  const auto k = bin.input_number_hotkey(cur_editor != 0xff ? cur_editor : 0, keys, 0,\n                                         size_int(a()->editors), false);\n  if (k.key == 'A') {\n    a()->user()->default_editor(0xff);\n  } else if (k.key == 'Q') {\n    a()->user()->default_editor(cur_editor);\n  } else {\n    a()->user()->default_editor(k.num);\n  }\n}\n\nstatic std::string GetMailBoxStatus() {\n  if (a()->user()->forward_systemnum() == 0 &&\n      a()->user()->forward_usernum() == 0) {\n    return std::string(\"Normal\");\n  }\n  if (a()->user()->forward_systemnum() != 0) {\n    if (a()->user()->mailbox_forwarded()) {\n      return fmt::format(\"Forward to #{} @{}.{}.\", a()->user()->forward_usernum(),\n                         a()->user()->forward_systemnum(),\n                         wwiv::stl::at(a()->nets(), a()->user()->forward_netnum()).name);\n    }\n    const auto fwd_username = read_inet_addr(a()->sess().user_num());\n    return StrCat(\"Forwarded to Internet \", fwd_username);\n  }\n\n  if (a()->user()->mailbox_closed()) {\n    return \"Closed\";\n  }\n\n  User ur;\n  a()->users()->readuser(&ur, a()->user()->forward_usernum());\n  if (ur.deleted()) {\n    a()->user()->forward_usernum(0);\n    return \"Normal\";\n  }\n  return StrCat(\"Forward to \", a()->names()->UserName(a()->user()->forward_usernum()));\n}\n\nstatic void print_cur_stat() {\n  bout.cls();\n  bout.litebar(\"Your Preferences\");\n  const auto screen_size =\n      fmt::format(\"{} X {}\", a()->user()->screen_width(), a()->user()->screen_lines());\n  const std::string ansi_setting =\n      a()->user()->ansi() ? (a()->user()->color() ? \"Color\" : \"Monochrome\") : \"No ANSI\";\n  bout.print(\"|#11|#9) Screen size       : |#2{:<16} \", screen_size);\n  bout.print(\"|#12|#9) ANSI              : |#2{}\", ansi_setting);\n  bout.nl();\n  bout.print(\"|#13|#9) Pause on screen   : |#2{:<16} \", a()->user()->pause() ? \"On \" : \"Off\");\n  bout.nl();\n  bout.print(\"|#14|#9) Mailbox           : |#2{}\", GetMailBoxStatus());\n  bout.nl();\n  bout.print(\"{:<45} {}\\r\\n\", \"|#15|#9) Configured Q-scan\", \"|#16|#9) Change password\");\n  \n  if (okansi()) {\n    bout.print(\"{:<45} {}\\r\\n\", \"|#17|#9) Update macros\", \"|#18|#9) Change colors\");\n\n    const auto editor_num = a()->user()->default_editor();\n    std::string editor_name = \"Line\";\n    if (a()->IsUseInternalFsed() && editor_num == 0xff) {\n      editor_name = \"Full Screen\";\n    }\n    if (editor_num > 0 && editor_num <= size_int(a()->editors)) {\n      editor_name = a()->editors[editor_num - 1].description;\n    }\n    bout.print(\"|#19|#9) Message editor    : |#2{:<16} \", editor_name); \n    bout.print(\"|#1A|#9) Extended colors   : |#2{}\\r\\n\", YesNoString(a()->user()->extra_color()));\n  } else {\n    bout.pl(\"|#17|#9) Update macros\");\n  }\n\n  const auto inet_addr =\n      ((a()->user()->email_address().empty()) ? \"None.\" : a()->user()->email_address());\n  bout.print(\"|#1B|#9) Optional lines    : |#2{:<16} \", a()->user()->optional_val());\n  bout.print(\"|#1C|#9) Conferencing      : |#2{}\\r\\n\", YesNoString(a()->user()->use_conference()));\n  bout.print(\"|#1D|#9) Show Hidden Lines : |#2{:<16} \", YesNoString(a()->user()->has_flag(User::msg_show_controlcodes)));\n  if (a()->fullscreen_read_prompt()) {\n    bout.print(\"|#1G|#9) Message Reader    : |#2{}\\r\\n\",\n               (a()->user()->has_flag(User::fullScreenReader) ? \"Full-Screen\" : \"Traditional\"));\n  }\n  bout.print(\"|#1I|#9) Internet Address  : |#2{}\\r\\n\", inet_addr);\n  bout.print(\"|#1K|#9) Configure Menus                      \");\n  if (okansi()) {\n    bout.print(\"|#1L|#9) ListPlus Enabled   : |#2{}\", YesNoString(a()->user()->data.lp_options & cfl_enable));\n  }\n  bout.nl();\n\n  if (num_instances() > 1) {\n    bout.print(\"|#1M|#9) Allow user msgs   : |#2{:<16} |#1N|#9) Configure QWK\", YesNoString(!a()->user()->ignore_msgs()));\n  }\n  bout.nl();\n  bout.print(\"|#1S|#9) Cls Between Msgs? : |#2{:<16} \",\n                      YesNoString(a()->user()->clear_screen()));\n  bout.print(\"|#1T|#9) 12hr or 24hr clock: |#2{}\\r\\n\", (a()->user()->twentyfour_clock() ? \"24hr\" : \"12hr\"));\n\n  std::string wwiv_regnum = \"(None)\";\n  if (a()->user()->wwiv_regnum()) {\n    wwiv_regnum = std::to_string(a()->user()->wwiv_regnum());\n  }\n  bout.print(\"|#1U|#9) Use Msg AutoQuote : |#2{:<16} \", YesNoString(a()->user()->auto_quote()));\n  bout.print(\"|#1W|#9) WWIV reg num      : |#2{}\\r\\n\", wwiv_regnum);\n\n  bout.pl(\"|#1Q|#9) Quit to main menu\");\n}\n\nstatic std::string DisplayColorName(int c) {\n  switch (c) {\n  case 0:\n    return \"Black\";\n  case 1:\n    return \"Blue\";\n  case 2:\n    return \"Green\";\n  case 3:\n    return \"Cyan\";\n  case 4:\n    return \"Red\";\n  case 5:\n    return \"Magenta\";\n  case 6:\n    return \"Yellow\";\n  case 7:\n    return \"White\";\n  default:\n    return \"\";\n  }\n}\n\nstd::string DescribeColorCode(int nColorCode) {\n  std::ostringstream os;\n\n  if (a()->user()->color()) {\n    os << DisplayColorName(nColorCode & 0x07) << \" on \" << DisplayColorName((nColorCode >> 4) & 0x07);\n  } else {\n    os << ((nColorCode & 0x07) ? \"Normal\" : \"Inversed\");\n  }\n\n  if (nColorCode & 0x08) {\n    os << \", Bold\";\n  }\n  if (nColorCode & 0x80) {\n    os << \", Blinking\";\n  }\n  return os.str();\n}\n\nvoid color_list() {\n  bout.nl(2);\n  for (int i = 0; i < 8; i++) {\n    bout.setc(static_cast<unsigned char>((i == 0) ? 0x70 : i));\n    bout.print(\"{}. {}|#0\\r\\n\", i, DisplayColorName(static_cast<char>(i)));\n  }\n}\n\nstatic void reset_user_colors_to_defaults() {\n  for (int i = 0; i <= 9; i++) {\n    a()->user()->color(i, a()->newuser_colors[i]);\n    a()->user()->bwcolor(i, a()->newuser_bwcolors[i]);\n  }\n}\n\nvoid change_colors() {\n  bool done = false;\n  bout.nl();\n  do {\n    bout.cls();\n    bout.outstr(\"|#5Customize Colors:\");\n    bout.nl(2);\n    if (!a()->user()->color()) {\n      std::ostringstream os;\n      os << \"Monochrome base color : \";\n      if ((a()->user()->bwcolor(1) & 0x70) == 0) {\n        os << DisplayColorName(a()->user()->bwcolor(1) & 0x07);\n      } else {\n        os << DisplayColorName((a()->user()->bwcolor(1) >> 4) & 0x07);\n      }\n      bout.outstr(os.str());\n      bout.nl(2);\n    }\n    for (int i = 0; i < 10; i++) {\n      std::ostringstream os;\n      bout.ansic(i);\n      os << i << \".\";\n      switch (i) {\n      case 0:\n        os << \"Default           \";\n        break;\n      case 1:\n        os << \"Yes/No            \";\n        break;\n      case 2:\n        os << \"Prompt            \";\n        break;\n      case 3:\n        os << \"Note              \";\n        break;\n      case 4:\n        os << \"Input line        \";\n        break;\n      case 5:\n        os << \"Yes/No Question   \";\n        break;\n      case 6:\n        os << \"Notice!           \";\n        break;\n      case 7:\n        os << \"Border            \";\n        break;\n      case 8:\n        os << \"Extra color #1    \";\n        break;\n      case 9:\n        os << \"Extra color #2    \";\n        break;\n      }\n      os << DescribeColorCode(a()->user()->color(i));\n      bout.outstr(os.str());\n      bout.nl();\n    }\n    bout.outstr(\"\\r\\n|#9[|#2R|#9]eset Colors to Default Values, [|#2Q|#9]uit\\r\\n\");\n    bout.outstr(\"|#9Enter Color Number to Modify (|#20|#9-|#29|#9,|#2R|#9,|#2Q|#9): \");\n    char ch = onek(\"RQ0123456789\", true);\n    if (ch == 'Q') {\n      done = true;\n    } else if (ch == 'R') {\n      reset_user_colors_to_defaults();\n    } else {\n      uint8_t nc;\n      const int color_num = ch - '0';\n      if (a()->user()->color()) {\n        color_list();\n        bout.ansic(0);\n        bout.nl();\n        bout.outstr(\"|#9(Q=Quit) Foreground? \");\n        ch = onek(\"Q01234567\");\n        if (ch == 'Q') {\n          continue;\n        }\n        nc = static_cast<uint8_t>(ch - '0');\n        bout.outstr(\"|#9(Q=Quit) Background? \");\n        ch = onek(\"Q01234567\");\n        if (ch == 'Q') {\n          continue;\n        }\n        nc = static_cast<uint8_t>(nc | ((ch - '0') << 4));\n      } else {\n        bout.nl();\n        bout.outstr(\"|#9Inversed? \");\n        if (bin.yesno()) {\n          if ((a()->user()->bwcolor(1) & 0x70) == 0) {\n            nc = static_cast<uint8_t>(0 | ((a()->user()->bwcolor(1) & 0x07) << 4));\n          } else {\n            nc = static_cast<uint8_t>(a()->user()->bwcolor(1) & 0x70);\n          }\n        } else {\n          if ((a()->user()->bwcolor(1) & 0x70) == 0) {\n            nc = static_cast<uint8_t>(0 | (a()->user()->bwcolor(1) & 0x07));\n          } else {\n            nc = static_cast<uint8_t>((a()->user()->bwcolor(1) & 0x70) >> 4);\n          }\n        }\n      }\n      bout.outstr(\"|#9Bold? \");\n      if (bin.yesno()) {\n        nc |= 0x08;\n      }\n\n      bout.outstr(\"|#9Blinking? \");\n      if (bin.yesno()) {\n        nc |= 0x80;\n      }\n\n      bout.nl(2);\n      bout.setc(nc);\n      bout.outstr(DescribeColorCode(nc));\n      bout.ansic(0);\n      bout.nl(2);\n      bout.outstr(\"|#8Is this OK? \");\n      if (bin.yesno()) {\n        bout.outstr(\"\\r\\nColor saved.\\r\\n\\n\");\n        if (a()->user()->color()) {\n          a()->user()->color(color_num, nc);\n        } else {\n          a()->user()->bwcolor(color_num, nc);\n        }\n      } else {\n        bout.outstr(\"\\r\\nNot saved, then.\\r\\n\\n\");\n      }\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\nvoid l_config_qscan() {\n  bool abort = false;\n  bout.outstr(\"\\r\\n|#9Boards to q-scan marked with '*'|#0\\r\\n\\n\");\n  for (size_t i = 0; i < a()->usub.size() && !abort; i++) {\n    const auto ch =\n        (a()->sess().qsc_q[a()->usub[i].subnum / 32] & (1L << (a()->usub[i].subnum % 32))) ? '*'\n                                                                                           : ' ';\n    bout.bpla(\n        fmt::format(\"{} {}. {}\", ch, a()->usub[i].keys, a()->subs().sub(a()->usub[i].subnum).name),\n        &abort);\n  }\n  bout.nl(2);\n}\n\nvoid config_qscan() {\n  if (okansi()) {\n    config_scan_plus(QSCAN);\n    return;\n  }\n\n  const auto oc = a()->sess().current_user_sub_conf_num();\n  const auto os = a()->current_user_sub().subnum;\n\n  bool done;\n  bool done1 = false;\n  do {\n    char ch;\n    if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n      std::string conf_list{\" \"};\n      auto abort = false;\n      bout.outstr(\"\\r\\nSelect Conference: \\r\\n\\n\");\n      for (const auto& c : a()->uconfsub) {\n        bout.bpla(fmt::format(\"{}) {}\", c.key.key(), stripcolors(c.conf_name)), &abort);\n        conf_list.push_back(c.key.key());\n      }\n      bout.nl();\n      bout.print(\"Select [{}, <space> to quit]: \", conf_list.substr(1));\n      ch = onek(conf_list);\n    } else {\n      ch = '-';\n    }\n    switch (ch) {\n    case ' ':\n      done1 = true;\n      break;\n    default:\n      if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n        auto& conf = a()->all_confs().subs_conf();\n        const auto o = conf.try_conf(ch);\n        if (!o) {\n          break;\n        }\n        setuconf(conf, o.value().key.key(), -1);\n      }\n      l_config_qscan();\n      done = false;\n      do {\n        bout.nl();\n        bout.outstr(\"|#2Enter message base number (|#1C=Clr All, Q=Quit, S=Set All|#2): \");\n        std::string s = mmkey(MMKeyAreaType::subs);\n        if (!s.empty()) {\n          for (size_t i = 0; i < a()->usub.size(); i++) {\n            if (s == a()->usub[i].keys) {\n              a()->sess().qsc_q[a()->usub[i].subnum / 32] ^= (1L << (a()->usub[i].subnum % 32));\n            }\n            if (s == \"S\") {\n              a()->sess().qsc_q[a()->usub[i].subnum / 32] |= (1L << (a()->usub[i].subnum % 32));\n            }\n            if (s == \"C\") {\n              a()->sess().qsc_q[a()->usub[i].subnum / 32] &= ~(1L << (a()->usub[i].subnum % 32));\n            }\n          }\n          if (s == \"Q\") {\n            done = true;\n          }\n          if (s == \"?\") {\n            l_config_qscan();\n          }\n        }\n      } while (!done && !a()->sess().hangup());\n      break;\n    }\n    if (!ok_multiple_conf(a()->user(), a()->uconfsub)) {\n      done1 = true;\n    }\n\n  } while (!done1 && !a()->sess().hangup());\n\n  if (okconf(a()->user())) {\n    setuconf(ConferenceType::CONF_SUBS, oc, os);\n  }\n}\n\nstatic void list_macro(const std::string& s) {\n  int i = 0;\n  const char* macro_text = s.c_str();\n\n  while (i < 80 && macro_text[i] != 0) {\n    if (macro_text[i] >= 32) {\n      bout.outchr(macro_text[i]);\n    } else {\n      if (macro_text[i] == 16) {\n        bout.ansic(macro_text[++i] - 48);\n      } else {\n        switch (macro_text[i]) {\n        case RETURN:\n          bout.outchr('|');\n          break;\n        case TAB:\n          bout.outchr('\\xF9');\n          break;\n        default:\n          bout.outchr('^');\n          bout.outchr(static_cast<char>(macro_text[i] + 64));\n          break;\n        }\n      }\n    }\n    ++i;\n  }\n  bout.nl();\n}\n\nstatic void macroedit(char *macro_text) {\n  *macro_text = '\\0';\n  bout.nl();\n  bout.outstr(\"|#5Enter your macro, press |#7[|#1CTRL-Z|#7]|#5 when finished.\\r\\n\\n\");\n  bin.okskey(false);\n  bout.ansic(0);\n  bool done = false;\n  int i = 0;\n  bool toggle = false;\n  int textclr = 0;\n  do {\n    switch (const char ch = bin.getkey(); ch) {\n    case CZ:\n      done = true;\n      break;\n    case BACKSPACE:\n      bout.bs();\n      i--;\n      if (i < 0) {\n        i = 0;\n      }\n      macro_text[i] = '\\0';\n      break;\n    case CP:\n      macro_text[i++] = ch;\n      toggle = true;\n      break;\n    case RETURN:\n      macro_text[i++] = ch;\n      bout.ansic(0);\n      bout.outchr('|');\n      bout.ansic(textclr);\n      break;\n    case TAB:\n      macro_text[i++] = ch;\n      bout.ansic(0);\n      bout.outchr('\\xF9') ;\n      bout.ansic(textclr);\n      break;\n    default:\n      macro_text[i++] = ch;\n      if (toggle) {\n        toggle = false;\n        textclr = ch - 48;\n        bout.ansic(textclr);\n      } else {\n        bout.outchr(ch);\n      }\n      break;\n    }\n    macro_text[i + 1] = 0;\n  } while (!done && i < 80 && !a()->sess().hangup());\n  bin.okskey(true);\n  bout.ansic(0);\n  bout.nl();\n  bout.outstr(\"|#9Is this okay? \");\n  if (!bin.yesno()) {\n    *macro_text = '\\0';\n  }\n}\n\nvoid change_macros() {\n  char szMacro[255], ch;\n  bool done = false;\n\n  do {\n    bout.outchr(CL);\n    bout.outstr(\"|#4Macro A: \\r\\n\");\n    list_macro(a()->user()->macro(2));\n    bout.nl();\n    bout.outstr(\"|#4Macro D: \\r\\n\");\n    list_macro(a()->user()->macro(0));\n    bout.nl();\n    bout.outstr(\"|#4Macro F: \\r\\n\");\n    list_macro(a()->user()->macro(1));\n    bout.nl(2);\n    bout.outstr(\"|#9Macro to edit or Q:uit (A,D,F,Q) : |#0\");\n    ch = onek(\"QADF\");\n    szMacro[0] = 0;\n    switch (ch) {\n    case 'A':\n      macroedit(szMacro);\n      if (szMacro[0]) {\n        a()->user()->macro(2, szMacro);\n      }\n      break;\n    case 'D':\n      macroedit(szMacro);\n      if (szMacro[0]) {\n        a()->user()->macro(0, szMacro);\n      }\n      break;\n    case 'F':\n      macroedit(szMacro);\n      if (szMacro[0]) {\n        a()->user()->macro(1, szMacro);\n      }\n      break;\n    case 'Q':\n      done = true;\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\nvoid change_password() {\n  bout.nl();\n  bout.outstr(\"|#9Change password? \");\n  if (!bin.yesno()) {\n    return;\n  }\n\n  bout.nl();\n  std::string password = bin.input_password(\"|#9You must now enter your current password.\\r\\n|#7: \", 8);\n  if (password != a()->user()->password()) {\n    bout.outstr(\"\\r\\nIncorrect.\\r\\n\\n\");\n    return;\n  }\n  bout.nl(2);\n  password = bin.input_password(\"|#9Enter your new password, 3 to 8 characters long.\\r\\n|#7: \", 8);\n  bout.nl(2);\n  std::string password2 = bin.input_password(\"|#9Repeat password for verification.\\r\\n|#7: \", 8);\n  if (password == password2) {\n    if (password2.length() < 3) {\n      bout.nl();\n      bout.outstr(\"|#6Password must be 3-8 characters long.\\r\\n|#6Password was not changed.\\r\\n\\n\");\n    } else {\n      a()->user()->password(password);\n      bout.outstr(\"\\r\\n|#1Password changed.\\r\\n\\n\");\n      sysoplog(\"Changed Password.\");\n    }\n  } else {\n    bout.outstr(\"\\r\\n|#6VERIFY FAILED.\\r\\n|#6Password not changed.\\r\\n\\n\");\n  }\n}\n\nvoid modify_mailbox() {\n  bout.nl();\n  bout.outstr(\"|#9Do you want to close your mailbox? \");\n  if (bin.yesno()) {\n    bout.outstr(\"|#5Are you sure? \");\n    if (bin.yesno()) {\n      a()->user()->close_mailbox();\n      return;\n    }\n  }\n  bout.outstr(\"|#5Do you want to forward your mail? \");\n  if (!bin.yesno()) {\n    a()->user()->clear_mailbox_forward();\n    return;\n  }\n  \n  if (const auto network_number = getnetnum_by_type(network_type_t::internet); network_number != -1) {\n    a()->set_net_num(network_number);\n    bout.outstr(\"|#5Do you want to forward to your Internet address? \");\n    if (bin.yesno()) {\n      bout.outstr(\"|#3Enter the Internet E-Mail Address.\\r\\n|#9:\");\n      if (const auto entered_address = bin.input_text(a()->user()->email_address(), 75);\n          check_inet_addr(entered_address)) {\n        a()->user()->email_address(entered_address);\n        a()->user()->forward_netnum(network_number);\n        a()->user()->forward_systemnum(INTERNET_EMAIL_FAKE_OUTBOUND_NODE);\n        bout.outstr(\"\\r\\nSaved.\\r\\n\\n\");\n      }\n      return;\n    }\n  }\n\n  bout.nl();\n  bout.outstr(\"|#2Forward to? \");\n  const auto entered_forward_to = bin.input_upper(40);\n\n  auto [tu, ts] = parse_email_info(entered_forward_to);\n  a()->user()->forward_usernum(tu);\n  a()->user()->forward_systemnum(ts);\n  if (a()->user()->forward_systemnum() != 0) {\n    a()->user()->forward_netnum(a()->net_num());\n    if (a()->user()->forward_usernum() == 0) {\n      a()->user()->clear_mailbox_forward();\n      bout.outstr(\"\\r\\nCan't forward to a user name, must use user number.\\r\\n\\n\");\n    }\n  } else if (a()->user()->forward_usernum() == a()->sess().user_num()) {\n    bout.outstr(\"\\r\\nCan't forward to yourself.\\r\\n\\n\");\n    a()->user()->forward_usernum(0);\n  }\n\n  bout.nl();\n  if (a()->user()->forward_usernum() == 0\n      && a()->user()->forward_systemnum() == 0) {\n    a()->user()->forward_netnum(0);\n    bout.outstr(\"Forwarding reset.\");\n  } else {\n    bout.outstr(\"Saved.\");\n  }\n  bout.nl(2);\n}\n\nvoid change_optional_lines() {\n  bout.outstr(\"|#9You may specify your optional lines value from 0-10,\\r\\n\"\n            \"|#20 |#9being all, |#210 |#9being none.\\r\\n\"\n            \"|#2What value? \");\n  if (const auto r = bin.input_number_hotkey(a()->user()->optional_val(), {'Q'}, 0, 10);\n      r.key != 'Q') {\n    a()->user()->optional_val(r.num);\n  }\n}\n\nvoid enter_regnum() {\n  bout.outstr(\"|#7Enter your WWIV registration number, or enter '|#20|#7' for none.\\r\\n|#0:\");\n  const auto regnum = bin.input_number(a()->user()->wwiv_regnum());\n  a()->user()->wwiv_regnum(regnum);\n  changedsl();\n}\n\nvoid change_email_address() {\n  bout.nl();\n  bout.outstr(\"|#9Enter your Internet mailing address.\\r\\n|#7:\");\n  if (const auto address = bin.input_text(65); !address.empty()) {\n    if (check_inet_addr(address)) {\n      a()->user()->email_address(address);\n    } else {\n      bout.outstr(\"\\r\\n|#6Invalid address format.\\r\\n\\n\");\n      bout.pausescr();\n    }\n  } else {\n    bout.outstr(\"|#5Delete Internet address? \");\n    if (bin.yesno()) {\n      a()->user()->email_address(\"\");\n    }\n  }\n}\n\nvoid defaults(bool& need_menu_reload) {\n  auto done = false;\n  do {\n    print_cur_stat();\n    a()->tleft(true);\n    if (a()->sess().hangup()) {\n      return;\n    }\n    bout.nl();\n    bout.outstr(\"|#9Defaults: \");\n    std::string allowable = \"Q?1234567BCDIKMNTUW\";\n    if (okansi()) {\n      allowable.append(\"89ALS\");\n      if (a()->fullscreen_read_prompt()) {\n        allowable.push_back('G');\n      }\n    }\n    switch (const auto ch = onek(allowable, true); ch) {\n    case 'Q':\n      done = true;\n      break;\n    case '?':\n      print_cur_stat();\n      break;\n    case '1':\n      input_screensize();\n      break;\n    case '2':\n      input_ansistat();\n      if (!okansi()) {\n        a()->user()->clear_flag(User::fullScreenReader);\n      }\n      break;\n    case '3':\n      a()->user()->toggle_flag(User::pauseOnPage);\n      break;\n    case '4':\n      modify_mailbox();\n      break;\n    case '5':\n      config_qscan();\n      break;\n    case '6':\n      change_password();\n      break;\n    case '7':\n      change_macros();\n      break;\n    case '8':\n      change_colors();\n      break;\n    case '9':\n      select_editor();\n      break;\n    case 'A':\n      a()->user()->toggle_flag(User::extraColor);\n      break;\n    case 'B':\n      change_optional_lines();\n      break;\n    case 'C':\n      a()->user()->toggle_flag(User::conference);\n      changedsl();\n      break;\n    case 'D':\n      a()->user()->toggle_flag(User::msg_show_controlcodes);\n      break;\n    case 'G':\n      a()->user()->toggle_flag(User::fullScreenReader);\n      break;\n    case 'I': {\n      change_email_address();\n    }\n    break;\n    case 'K':\n      wwiv::bbs::menus::ConfigUserMenuSet(\"\");\n      need_menu_reload = true;\n      break;\n    case 'L':\n      a()->user()->data.lp_options ^= cfl_enable;\n      break;\n    case 'M':\n      a()->user()->toggle_flag(User::noMsgs);\n      break;\n    case 'N':\n      wwiv::bbs::qwk::qwk_config_user();\n      break;\n    case 'S':\n      a()->user()->toggle_flag(User::clearScreen);\n      break;\n    case 'T':\n      a()->user()->toggle_flag(User::twentyFourHourClock);\n      break;\n    case 'U':\n      a()->user()->toggle_flag(User::autoQuote);\n      break;\n    case 'W':\n      enter_regnum();\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n  a()->WriteCurrentUser();\n}\n\n// private function used by list_config_scan_plus and drawscan\nstatic int GetMaxLinesToShowForScanPlus() {\n  return (a()->user()->screen_lines() - (4 + STOP_LIST) >\n          MAX_SCREEN_LINES_TO_SHOW - (4 + STOP_LIST) ?\n          MAX_SCREEN_LINES_TO_SHOW - (4 + STOP_LIST) :\n          a()->user()->screen_lines() - (4 + STOP_LIST));\n}\n\nstatic void list_config_scan_plus(int first, int *amount, int type) {\n  auto& confsubdir = type == NSCAN ? a()->uconfdir : a()->uconfsub;\n  bool bUseConf = ok_multiple_conf(a()->user(), confsubdir);\n\n  bout.cls();\n  bout.clear_lines_listed();\n\n  if (bUseConf) {\n    std::string name;\n    if (type == QSCAN) {\n      name = a()->uconfsub[a()->sess().current_user_sub_conf_num()].conf_name;\n    }\n    else {\n      name = a()->uconfdir[a()->sess().current_user_dir_conf_num()].conf_name;\n    }\n    const auto s = trim_to_size_ignore_colors(name, 26);\n    bout.printf(\"|#1Configure |#2%cSCAN |#9-- |#2%-26s |#9-- |#1Press |#7[|#2SPACE|#7]|#1 to toggle a %s\\r\\n\",\n                 type == 0 ? 'Q' : 'N', s, type == 0 ? \"sub\" : \"dir\");\n  } else {\n    bout.printf(\"|#1Configure |#2%cSCAN                                   |#1Press |#7[|#2SPACE|#7]|#1 to toggle a %s\\r\\n\",\n                 type == 0 ? 'Q' : 'N', type == 0 ? \"sub\" : \"dir\");\n  }\n  bout.ansic(7);\n  bout.outstr(std::string(79, '\\xC4'));\n  bout.nl();\n\n  const auto max_lines = GetMaxLinesToShowForScanPlus();\n\n  if (type == QSCAN) {\n    for (size_t this_sub = first; this_sub < a()->usub.size() && *amount < max_lines * 2;\n         this_sub++) {\n      bout.clear_lines_listed();\n      auto s = fmt::sprintf(\"|#7[|#1%c|#7] |#9%s\",\n              (a()->sess().qsc_q[a()->usub[this_sub].subnum / 32] & (1L << (a()->usub[this_sub].subnum % 32))) ? '\\xFE' : ' ',\n              a()->subs().sub(a()->usub[this_sub].subnum).name);\n      if (s.length() > 44) {\n        s.resize(44);\n      }\n      if (*amount >= max_lines) {\n        bout.goxy(40, 3 + *amount - max_lines);\n        bout.outstr(s);\n      } else {\n        bout.outstr(s);\n        bout.nl();\n      }\n      ++*amount;\n    }\n  } else {\n    for (auto this_dir = first; this_dir < wwiv::stl::size_int(a()->udir) && *amount < max_lines * 2;\n         this_dir++) {\n      bout.clear_lines_listed();\n      const int alias_dir = a()->udir[this_dir].subnum;\n      auto s =\n          fmt::sprintf(\"|#7[|#1%c|#7] |#2%s\",\n                       a()->sess().qsc_n[alias_dir / 32] & (1L << (alias_dir % 32)) ? '\\xFE' : ' ',\n                       a()->dirs()[alias_dir].name);\n      if (s.length() > 44) {\n        s.resize(44);\n      }\n      if (*amount >= max_lines) {\n        bout.goxy(40, 3 + *amount - max_lines);\n        bout.outstr(s);\n      } else {\n        bout.outstr(s);\n        bout.nl();\n      }\n      ++*amount;\n    }\n  }\n  bout.nl();\n  bout.clear_lines_listed();\n}\n\nstatic void drawscan(int filepos, bool tagged) {\n  const auto max_lines = GetMaxLinesToShowForScanPlus();\n  if (filepos >= max_lines) {\n    bout.goxy(40, 3 + filepos - max_lines);\n  } else {\n    bout.goxy(1, filepos + 3);\n  }\n\n  bout.setc(static_cast<uint8_t>(wwiv::sdk::Color::BLACK) + (static_cast<uint8_t>(wwiv::sdk::Color::CYAN) << 4));\n  bout.print(\"[{:c}]\", tagged ? '\\xFE' : ' ');\n  bout.setc(static_cast<uint8_t>(wwiv::sdk::Color::YELLOW) + (static_cast<uint8_t>(wwiv::sdk::Color::BLACK) << 4));\n\n  if (filepos >= max_lines) {\n    bout.goxy(41, 3 + filepos - max_lines);\n  } else {\n    bout.goxy(2, filepos + 3);\n  }\n}\n\nstatic void undrawscan(int filepos, long tagged) {\n  const auto max_lines = GetMaxLinesToShowForScanPlus();\n\n  if (filepos >= max_lines) {\n    bout.goxy(40, 3 + filepos - max_lines);\n  } else {\n    bout.goxy(1, filepos + 3);\n  }\n  bout.printf(\"|#7[|#1%c|#7]\", tagged ? '\\xFE' : ' ');\n}\n\nstatic bool is_inscan(int dir) {\n  auto sysdir = false;\n  if (a()->udir[0].keys == \"0\") {\n    sysdir = true;\n  }\n\n  for (auto this_dir = 0; this_dir < size_int(a()->udir); this_dir++) {\n    const auto key = std::to_string(sysdir ? dir : dir + 1);\n    if (key == a()->udir[this_dir].keys) {\n      const auto ad = a()->udir[this_dir].subnum;\n      return (a()->sess().qsc_n[ad / 32] & 1L << ad % 32) != 0;\n    }\n  }\n  return false;\n}\n\nvoid config_scan_plus(int type) {\n  int command;\n  int top = 0;\n  int amount = 0, pos = 0, side_pos = 0;\n  side_menu_colors smc{};\n\n  auto& confsubdir = type == NSCAN ? a()->uconfdir : a()->uconfsub;\n  int useconf = ok_multiple_conf(a()->user(), confsubdir);\n  bout.localIO()->topdata(LocalIO::topdata_t::none);\n  a()->UpdateTopScreen();\n\n  std::vector<std::string> menu_items = { \"Next\",  \"Previous\", \"Toggle\", \"Clear All\", \"Set All\" };\n\n  if (type == 0) {\n    menu_items.emplace_back(\"Read New\");\n  } else {\n    menu_items.emplace_back(\"List\");\n  }\n\n  if (useconf) {\n    menu_items.emplace_back(\"{ Conf\");\n    menu_items.emplace_back(\"} Conf\");\n    menu_items.emplace_back(\"Quit\");\n    menu_items.emplace_back(\"?\");\n  } else {\n    menu_items.emplace_back(\"Quit\");\n    menu_items.emplace_back(\"?\");\n  }\n  bool done = false;\n  while (!done && !a()->sess().hangup()) {\n    amount = 0;\n    list_config_scan_plus(top, &amount, type);\n    if (!amount) {\n      top = 0;\n      list_config_scan_plus(top, &amount, type);\n      if (!amount) {\n        done = true;\n      }\n    }\n    if (!done) {\n      drawscan(pos, type ? is_inscan(top + pos) :\n               a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] & (1L << (a()->usub[top + pos].subnum % 32)));\n    }\n    bool redraw = true;\n    bool menu_done = false;\n    while (!menu_done && !a()->sess().hangup() && !done) {\n      command = side_menu(&side_pos, redraw, menu_items, 1,\n                          a()->user()->screen_lines() - STOP_LIST > MAX_SCREEN_LINES_TO_SHOW - STOP_LIST ?\n                          MAX_SCREEN_LINES_TO_SHOW - STOP_LIST :\n                          a()->user()->screen_lines() - STOP_LIST, &smc);\n      bout.clear_lines_listed();\n      redraw = true;\n      bout.ansic(0);\n      if (do_sysop_command(command)) {\n        menu_done = true;\n        amount = 0;\n      }\n      switch (command) {\n      case '?':\n      case CO:\n        bout.cls();\n        bout.print_help_file(SCONFIG_HLP);\n        bout.pausescr();\n        menu_done = true;\n        amount = 0;\n        break;\n      case COMMAND_DOWN:\n        undrawscan(pos, type ? is_inscan(top + pos) :\n                   a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] & (1L << (a()->usub[top + pos].subnum % 32)));\n        ++pos;\n        if (pos >= amount) {\n          pos = 0;\n        }\n        drawscan(pos, type ? is_inscan(top + pos) :\n                 a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] & (1L << (a()->usub[top + pos].subnum % 32)));\n        redraw = false;\n        break;\n      case COMMAND_UP:\n        undrawscan(pos, type ? is_inscan(top + pos) : a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] &\n                                   (1L << (a()->usub[top + pos].subnum % 32)));\n        if (!pos) {\n          pos = amount - 1;\n        } else {\n          --pos;\n        }\n        drawscan(pos, type ? is_inscan(top + pos) : a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] &\n                                 (1L << (a()->usub[top + pos].subnum % 32)));\n        redraw = false;\n        break;\n      case SPACE: {\n        if (type == 0) {\n          a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] ^=\n              (1L << (a()->usub[top + pos].subnum % 32));\n        } else {\n          auto sysdir = a()->udir[0].keys == \"0\";\n          for (auto this_dir = 0; this_dir < size_int(a()->udir); this_dir++) {\n            const auto s = std::to_string(sysdir ? top + pos : top + pos + 1);\n            if (s == a()->udir[this_dir].keys) {\n              int ad = a()->udir[this_dir].subnum;\n              a()->sess().qsc_n[ad / 32] ^= (1L << (ad % 32));\n            }\n          }\n        }\n        drawscan(pos, type ? is_inscan(top + pos) : a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] &\n                                 (1L << (a()->usub[top + pos].subnum % 32)));\n        redraw = false;\n      } break;\n      case EXECUTE:\n        if (!useconf && side_pos > 5) {\n          side_pos += 2;\n        }\n        switch (side_pos) {\n        case 0:\n          top += amount;\n          if (type == 0) {\n            if (top >= size_int(a()->usub)) {\n              top = 0;\n            }\n          } else {\n            if (top >= size_int(a()->udir)) {\n              top = 0;\n            }\n          }\n          pos = 0;\n          menu_done = true;\n          amount = 0;\n          break;\n        case 1:\n          if (top > a()->user()->screen_lines() - 4) {\n            top -= a()->user()->screen_lines() - 4;\n          } else {\n            top = 0;\n          }\n          pos = 0;\n          menu_done = true;\n          amount = 0;\n          break;\n        case 2:\n          if (type == 0) {\n            a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] ^=\n                (1L << (a()->usub[top + pos].subnum % 32));\n          } else {\n            bool sysdir = a()->udir[0].keys == \"0\";\n            for (int this_dir = 0; this_dir < wwiv::stl::size_int(a()->udir); this_dir++) {\n              const auto s = fmt::format(\"{}\", sysdir ? top + pos : top + pos + 1);\n              if (s == a()->udir[this_dir].keys) {\n                int ad = a()->udir[this_dir].subnum;\n                a()->sess().qsc_n[ad / 32] ^= (1L << (ad % 32));\n              }\n            }\n          }\n          drawscan(pos, type ? is_inscan(top + pos)\n                             : a()->sess().qsc_q[a()->usub[top + pos].subnum / 32] &\n                                   (1L << (a()->usub[top + pos].subnum % 32)));\n          redraw = false;\n          break;\n        case 3:\n          if (type == 0) {\n            for (size_t this_sub = 0; this_sub < a()->usub.size(); this_sub++) {\n              if (a()->sess().qsc_q[a()->usub[this_sub].subnum / 32] &\n                  (1L << (a()->usub[this_sub].subnum % 32))) {\n                a()->sess().qsc_q[a()->usub[this_sub].subnum / 32] ^=\n                    (1L << (a()->usub[this_sub].subnum % 32));\n              }\n            }\n          } else {\n            for (auto this_dir = 0; this_dir < size_int(a()->udir); this_dir++) {\n              if (a()->sess().qsc_n[a()->udir[this_dir].subnum / 32] &\n                  (1L << (a()->udir[this_dir].subnum % 32))) {\n                a()->sess().qsc_n[a()->udir[this_dir].subnum / 32] ^=\n                    1L << (a()->udir[this_dir].subnum % 32);\n              }\n            }\n          }\n          pos = 0;\n          menu_done = true;\n          amount = 0;\n          break;\n        case 4:\n          if (type == 0) {\n            for (auto this_sub = 0; this_sub < size_int(a()->usub); this_sub++) {\n              if (!(a()->sess().qsc_q[a()->usub[this_sub].subnum / 32] &\n                    (1L << (a()->usub[this_sub].subnum % 32)))) {\n                a()->sess().qsc_q[a()->usub[this_sub].subnum / 32] ^=\n                    (1L << (a()->usub[this_sub].subnum % 32));\n              }\n            }\n          } else {\n            for (auto this_dir = 0; this_dir < wwiv::stl::size_int(a()->udir); this_dir++) {\n              if (!(a()->sess().qsc_n[a()->udir[this_dir].subnum / 32] &\n                    (1L << (a()->udir[this_dir].subnum % 32)))) {\n                a()->sess().qsc_n[a()->udir[this_dir].subnum / 32] ^=\n                    1L << (a()->udir[this_dir].subnum % 32);\n              }\n            }\n          }\n          pos = 0;\n          menu_done = true;\n          amount = 0;\n          break;\n        case 5:\n          if (type == 0) {\n            bool nextsub = false;\n            qscan(static_cast<uint16_t>(top + pos), nextsub);\n          } else {\n            auto cudn_saved = a()->current_user_dir_num();\n            a()->set_current_user_dir_num(static_cast<uint16_t>(top + pos));\n            listfiles();\n            a()->set_current_user_dir_num(cudn_saved);\n          }\n          menu_done = true;\n          amount = 0;\n          break;\n        case 6:\n          if (okconf(a()->user())) {\n            if (type == 0) {\n              auto confnum = a()->sess().current_user_sub_conf_num();\n              if (confnum > 0) {\n                a()->sess().set_current_user_sub_conf_num(confnum - 1);\n              } else {\n                a()->sess().set_current_user_sub_conf_num(size_int(a()->uconfsub)-1);\n              }\n              setuconf(ConferenceType::CONF_SUBS, a()->sess().current_user_sub_conf_num(), -1);\n            } else {\n              auto confnum = a()->sess().current_user_dir_conf_num();\n              if (confnum > 0) {\n                a()->sess().set_current_user_dir_conf_num(confnum - 1);\n              } else {\n                a()->sess().set_current_user_dir_conf_num(size_int(a()->uconfdir)-1);\n              }\n              setuconf(ConferenceType::CONF_DIRS, a()->sess().current_user_dir_conf_num(), -1);\n            }\n            pos = 0;\n            menu_done = true;\n            amount = 0;\n          }\n          break;\n        case 7:\n          if (okconf(a()->user())) {\n            if (type == 0) {\n              int confnum = a()->sess().current_user_sub_conf_num();\n              if (confnum < size_int(a()->uconfsub) - 1) {\n                a()->sess().set_current_user_sub_conf_num(confnum + 1);\n              } else {\n                a()->sess().set_current_user_sub_conf_num(0);\n              }\n              setuconf(ConferenceType::CONF_SUBS, a()->sess().current_user_sub_conf_num(), -1);\n            }\n\n            else {\n              int confnum = a()->sess().current_user_dir_conf_num();\n              if (confnum < size_int(a()->uconfdir) - 1) {\n                a()->sess().set_current_user_dir_conf_num(confnum + 1);\n              } else {\n                a()->sess().set_current_user_dir_conf_num(0);\n              }\n              setuconf(ConferenceType::CONF_DIRS, a()->sess().current_user_dir_conf_num(), -1);\n            }\n            pos = 0;\n            menu_done = true;\n            amount = 0;\n          }\n          break;\n        case 8:\n          menu_done = true;\n          done = true;\n          break;\n        case 9:\n          bout.cls();\n          bout.print_help_file(SCONFIG_HLP);\n          bout.pausescr();\n          menu_done = true;\n          amount = 0;\n          if (!useconf) {\n            side_pos -= 2;\n          }\n          break;\n        }\n        break;\n      case GET_OUT:\n        menu_done = true;\n        done = true;\n        break;\n      }\n    }\n  }\n  bout.clear_lines_listed();\n  bout.nl();\n}\n"
  },
  {
    "path": "bbs/defaults.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_DEFAULTS_H\n#define INCLUDED_BBS_DEFAULTS_H\n\n#include <string>\n\nvoid select_editor();\nstd::string DescribeColorCode(int nColorCode);\nvoid color_list();\nvoid config_qscan();\nvoid enter_regnum();\nvoid defaults(bool& need_menu_reload);\nvoid config_scan_plus(int type);\nvoid change_password();\nvoid change_macros();\nvoid modify_mailbox();\nvoid change_optional_lines();\nvoid change_email_address();\nvoid change_colors();\n\n#endif\n"
  },
  {
    "path": "bbs/diredit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"core/datafile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/net/networks.h\"\n#include <string>\n\nusing wwiv::common::InputMode;\nusing wwiv::core::DataFile;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n//\n// Local Function Prototypes\n//\n\nvoid modify_dir(int n);\nvoid swap_dirs(int dir1, int dir2);\nvoid insert_dir(int n);\nvoid delete_dir(int n);\n\nstatic std::string tail(const std::string& s, int len) {\n  return len >= ssize(s) ? s : s.substr(s.size() - len);\n}\n\nstatic std::string dirdata(int n) {\n  const auto& r = a()->dirs()[n];\n  return fmt::sprintf(\"|#2%4d |#1%-24.24s |#2%-8s |#9%-3d |#3%-23.23s |#1%s\", n, stripcolors(r.name), r.filename,\n                      r.maxfiles, tail(r.path, 23), r.conf.to_string());\n}\n\nstatic void showdirs() {\n  bout.cls();\n  bout.outstr(\"|#7(|#1File Areas Editor|#7) Enter Substring: \");\n  const auto pattern = bin.input_text(20);\n  bout.cls();\n  bool abort = false;\n  bout.bpla(\"|#2##   Description              Filename Num Path                    Conf\", &abort);\n  bout.bpla(\"|#7==== ======================== -------- === ----------------------- -------\",\n            &abort);\n  for (auto i = 0; i < wwiv::stl::ssize(a()->dirs()) && !abort; i++) {\n    auto text = StrCat(a()->dirs()[i].name, \" \", a()->dirs()[i].filename);\n    if (ifind_first(text, pattern)) {\n      bout.bpla(dirdata(i), &abort);\n    }\n  }\n}\n\nstd::optional<Network> select_network() {\n  std::map<int, Network> nets;\n  auto num = 0;\n  for (const auto& n : a()->nets().networks()) {\n    if (n.type == network_type_t::ftn) {\n      nets.emplace(++num, n);\n    }\n  }\n\n  bout.pl(\"|#5Networks: \");\n  for (const auto& n : nets) {\n    bout.print(\"|#1{}|#9) |#2{}\\r\\n\", n.first, n.second.name);\n  }\n  bout.nl();\n  bout.outstr(\"|#2(Q=Quit) Select Network Number : \");\n  const auto r = bin.input_number_hotkey(0, {'Q'}, 1, num, false);\n  if (r.key == 'Q') {\n    return std::nullopt;\n  }\n  auto it = nets.find(r.num);\n  if (it == std::end(nets)) {\n    return std::nullopt;\n  }\n  return {it->second};\n}\n\nenum class list_area_tags_style_t { number, indent };\nstatic void list_area_tags(const std::vector<wwiv::sdk::files::dir_area_t>& area_tags,\n                           list_area_tags_style_t style) {\n  if (area_tags.empty()) {\n    bout.pl(\"|#6(None)\");\n    return;\n  }\n  Network empty(network_type_t::unknown, \"(Unknown)\");\n\n  auto nn = 0;\n  auto first{true};\n  for (const auto& t : area_tags) {\n    if (style == list_area_tags_style_t::number) {\n      bout.print(\"|#2{}|#9) \", ++nn);\n    } else if (style == list_area_tags_style_t::indent) {\n      if (!first) {\n        bout.outstr(\"                  \");\n      }\n      first = false;\n    }\n    bout.print(\"|#1{}|#9@|#5{}\\r\\n\", t.area_tag,  a()->nets().by_uuid(t.net_uuid).value_or(empty).name);\n  }\n}\n\n// I don't think there is a real max length, but we'll pick something\n// File Echo Area Tag field limit - FTN #1617\nstatic const int kAreaTagLength = 60;\n\nstatic void edit_ftn_area_tags(std::vector<wwiv::sdk::files::dir_area_t>& area_tags) {\n  auto done{false};\n  do {\n    bout.cls();\n    bout.litebar(\"Editing File Area Tags\");\n    bout.nl();\n    list_area_tags(area_tags, list_area_tags_style_t::number);\n\n    bout.nl();\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Which (|#2A|#7dd, |#2E|#7dit, or |#2D|#7elete) : \");\n    const auto ch = onek(\"QAED\", true);\n    switch (ch) {\n    case 'A': {\n      files::dir_area_t da{};\n      bout.outstr(\"Enter Name? \");\n      da.area_tag = bin.input_upper(kAreaTagLength);\n      const auto r = select_network();\n      if (!r) {\n        break;\n      }\n      da.net_uuid = r.value().uuid;\n      area_tags.push_back(da);\n    } break;\n    case 'D': {\n      if (area_tags.empty()) {\n        break;\n      }\n      bout.print(\"(Q=Quit, 1={}) Enter Number? \", area_tags.size());\n      const auto r = bin.input_number_hotkey(0, {'Q'}, 1, size_int(area_tags), false);\n      if (r.key == 'Q') {\n        break;\n      }\n      bout.outstr(\"Are you sure?\");\n      if (bin.noyes()) {\n        erase_at(area_tags, r.num - 1);\n      }\n    } break;\n    case 'E': {\n      bout.outstr(\"Edit!\");\n      if (area_tags.empty()) {\n        break;\n      }\n      bout.print(\"(Q=Quit, 1={}) Enter Number? \", area_tags.size());\n      const auto r = bin.input_number_hotkey(0, {'Q'}, 1, size_int(area_tags), false);\n      if (r.key == 'Q') {\n        break;\n      }\n      files::dir_area_t da{};\n      bout.outstr(\"Enter Name? \");\n      da.area_tag = bin.input_upper(kAreaTagLength);\n      const auto nr = select_network();\n      if (!nr) {\n        break;\n      }\n      da.net_uuid = nr.value().uuid;\n      bout.outstr(\"Are you sure?\");\n      if (bin.noyes()) {\n        area_tags[r.num - 1] = da;\n      }\n    } break;\n    case 'Q':\n      done = true;\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\nvoid modify_dir(int n) {\n  auto r = a()->dirs()[n];\n  auto done = false;\n  do {\n    bout.cls();\n    bout.litebar(StrCat(\"Editing File Area #\", n));\n    bout.print(\"|#9A) Name         : |#2{}\\r\\n\", r.name);\n    bout.print(\"|#9B) Filename     : |#2{}\\r\\n\", r.filename);\n    bout.print(\"|#9C) Path         : |#2{}\\r\\n\", r.path);\n    bout.print(\"|#9D) ACS          : |#2{}\\r\\n\", r.acs);\n    bout.print(\"|#9F) Max Files    : |#2{}\\r\\n\", r.maxfiles);\n    bout.print(\"|#9H) Require PD   : |#2{}\\r\\n\", YesNoString((r.mask & mask_PD)));\n    bout.print(\"|#9J) Uploads      : |#2{}\\r\\n\",\n               ((r.mask & mask_no_uploads) ? \"Disallowed\" : \"Allowed\"));\n    bout.print(\"|#9K) Arch. only   : |#2{}\\r\\n\", YesNoString((r.mask & mask_archive)));\n    bout.print(\"|#9L) Drive Type   : |#2{}\\r\\n\",\n               ((r.mask & mask_cdrom) ? \"|#3CD ROM\" : \"HARD DRIVE\"));\n    if (r.mask & mask_cdrom) {\n      bout.print(\"|#9M) Available    : |#2{}\\r\\n\", YesNoString((r.mask & mask_offline)));\n    }\n    bout.print(\"|#9N) //UPLOADALL  : |#2{}\\r\\n\", YesNoString((r.mask & mask_uploadall)));\n    bout.print(\"|#9O) WWIV Reg     : |#2{}\\r\\n\", YesNoString((r.mask & mask_wwivreg)));\n    bout.outstr(\"|#9T) FTN Area Tags: |#2\");\n    list_area_tags(r.area_tags, list_area_tags_style_t::indent);\n    bout.print(\"|#9   Conferences  : |#2{}\\r\\n\", r.conf.to_string());\n    bout.nl(2);\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Which (|#1A|#7-|#1O|#7,|#1[T|#7,|#1[|#7,|#1]|#7) : \");\n    const auto ch = onek(\"QABCDEFGHJKLMNOT[]\", true);\n    switch (ch) {\n    case 'Q':\n      done = true;\n      break;\n    case '[':\n      a()->dirs()[n] = r;\n      if (--n < 0) {\n        n = a()->dirs().size() - 1;\n      }\n      r = a()->dirs()[n];\n      break;\n    case ']':\n      a()->dirs()[n] = r;\n      if (++n >= a()->dirs().size()) {\n        n = 0;\n      }\n      r = a()->dirs()[n];\n      break;\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"|#2New name? \");\n      auto s = bin.input_text(r.name, 40);\n      if (!s.empty()) {\n        r.name = s;\n      }\n    } break;\n    case 'B': {\n      bout.nl();\n      bout.outstr(\"|#2New filename? \");\n      auto s = bin.input_filename(r.filename, 8);\n      if (!s.empty() && !contains(s, '.')) {\n        r.filename = s;\n      }\n    } break;\n    case 'C': {\n      bout.nl();\n      bout.print(\"|#9Enter new path, optionally with drive specifier.\\r\\n\"\n                 \"|#9No backslash on end.\\r\\n\\n\"\n                 \"|#9The current path is:\\r\\n\"\n                 \"|#1{}\\r\\n\\r\\n\",\n                 r.path);\n      bout.outstr(\" \\b\");\n      if (auto s = bin.input_path(r.path, 79); !s.empty()) {\n        const std::string dir{s};\n        if (!File::Exists(dir)) {\n          File::set_current_directory(a()->bbspath());\n          if (!File::mkdirs(dir)) {\n            bout.pl(\"|#6Unable to create or change to directory.\");\n            bout.pausescr();\n            s.clear();\n          }\n        }\n        if (!s.empty()) {\n          s = File::EnsureTrailingSlash(s);\n          r.path = s;\n          bout.nl(2);\n          bout.outstr(\"|#3The path for this directory is changed.\\r\\n\"\n                    \"|#9If there are any files in it, you must manually move them to the new \"\n                    \"directory.\\r\\n\");\n          bout.pausescr();\n        }\n      }\n    } break;\n    case 'D': {\n      bout.nl();\n      r.acs = wwiv::bbs::input_acs(bin, bout, \"New ACS?\", r.acs, 77);\n    } break;\n    case 'F': {\n      bout.nl();\n      bout.outstr(\"|#2New max files? \");\n      r.maxfiles = bin.input_number(r.maxfiles);\n    } break;\n    case 'H':\n      r.mask ^= mask_PD;\n      break;\n    case 'J':\n      r.mask ^= mask_no_uploads;\n      break;\n    case 'K':\n      r.mask ^= mask_archive;\n      break;\n    case 'L':\n      r.mask ^= mask_cdrom;\n      if (r.mask & mask_cdrom) {\n        r.mask |= mask_no_uploads;\n      } else {\n        r.mask &= ~mask_offline;\n      }\n      break;\n    case 'M':\n      if (r.mask & mask_cdrom) {\n        r.mask ^= mask_offline;\n      }\n      break;\n    case 'N':\n      r.mask ^= mask_uploadall;\n      break;\n    case 'O':\n      r.mask &= ~mask_wwivreg;\n      bout.nl();\n      bout.outstr(\"|#5Require WWIV 4.xx registration? \");\n      if (bin.yesno()) {\n        r.mask |= mask_wwivreg;\n      }\n      break;\n    case 'T': {\n      edit_ftn_area_tags(r.area_tags);\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n\n  a()->dirs()[n] = r;\n}\n\nvoid swap_dirs(int dir1, int dir2) {\n  if (dir1 < 0 || dir1 >= a()->dirs().size() || dir2 < 0 || dir2 >= a()->dirs().size()) {\n    return;\n  }\n  const int num_user_records = a()->users()->num_user_records();\n\n  if (auto * pTempQScan = static_cast<uint32_t*>(BbsAllocA(a()->config()->qscn_len())); pTempQScan) {\n    for (auto i = 1; i <= num_user_records; i++) {\n      read_qscn(i, pTempQScan, true);\n      auto* pTempQScan_n = pTempQScan + 1;\n\n      int i1 = 0;\n      if (pTempQScan_n[dir1 / 32] & (1L << (dir1 % 32))) {\n        i1 = 1;\n      }\n\n      int i2 = 0;\n      if (pTempQScan_n[dir2 / 32] & (1L << (dir2 % 32))) {\n        i2 = 1;\n      }\n      if (i1 + i2 == 1) {\n        pTempQScan_n[dir1 / 32] ^= (1L << (dir1 % 32));\n        pTempQScan_n[dir2 / 32] ^= (1L << (dir2 % 32));\n      }\n      write_qscn(i, pTempQScan, true);\n    }\n    close_qscn();\n    free(pTempQScan);\n  }\n  const auto drt = a()->dirs()[dir1];\n  a()->dirs()[dir1] = a()->dirs()[dir2];\n  a()->dirs()[dir2] = drt;\n}\n\nvoid insert_dir(int n) {\n  if (n < 0 || n > a()->dirs().size()) {\n    return;\n  }\n\n  files::directory_t r{};\n  r.name = \"** NEW DIR **\";\n  r.filename = \"noname\";\n  r.path = a()->config()->dloadsdir().string();\n  r.acs = \"user.sl >= 10\";\n  r.maxfiles = 500;\n  r.mask = 0;\n\n  a()->dirs().insert(n, r);\n  const auto num_user_records = a()->users()->num_user_records();\n\n  if (auto * pTempQScan = static_cast<uint32_t*>(BbsAllocA(a()->config()->qscn_len())); pTempQScan) {\n    auto* pTempQScan_n = pTempQScan + 1;\n\n    const uint32_t m1 = 1L << (n % 32);\n    const uint32_t m2 = 0xffffffff << ((n % 32) + 1);\n    const uint32_t m3 = 0xffffffff >> (32 - (n % 32));\n\n    for (int i = 1; i <= num_user_records; i++) {\n      read_qscn(i, pTempQScan, true);\n\n      int i1;\n      for (i1 = a()->dirs().size() / 32; i1 > n / 32; i1--) {\n        pTempQScan_n[i1] = (pTempQScan_n[i1] << 1) | (pTempQScan_n[i1 - 1] >> 31);\n      }\n      pTempQScan_n[i1] = m1 | (m2 & (pTempQScan_n[i1] << 1)) | (m3 & pTempQScan_n[i1]);\n\n      write_qscn(i, pTempQScan, true);\n    }\n    close_qscn();\n    free(pTempQScan);\n  }\n}\n\nvoid delete_dir(int n) {\n  if (n < 0 || n >= a()->dirs().size()) {\n    return;\n  }\n  a()->dirs().erase(n);\n\n  const auto num_users = a()->users()->num_user_records();\n\n  const auto pTempQScan = std::make_unique<uint32_t[]>(a()->config()->qscn_len());\n  if (pTempQScan) {\n    auto* pTempQScan_n = pTempQScan.get() + 1;\n\n    const uint32_t m2 = 0xffffffff << (n % 32);\n    const uint32_t m3 = 0xffffffff >> (32 - (n % 32));\n\n    for (auto i = 1; i <= num_users; i++) {\n      read_qscn(i, pTempQScan.get(), true);\n\n      pTempQScan_n[n / 32] = (pTempQScan_n[n / 32] & m3) | ((pTempQScan_n[n / 32] >> 1) & m2) |\n                             (pTempQScan_n[(n / 32) + 1] << 31);\n\n      for (auto i1 = (n / 32) + 1; i1 <= a()->dirs().size() / 32; i1++) {\n        pTempQScan_n[i1] = (pTempQScan_n[i1] >> 1) | (pTempQScan_n[i1 + 1] << 31);\n      }\n\n      write_qscn(i, pTempQScan.get(), true);\n    }\n    close_qscn();\n  }\n}\n\nvoid dlboardedit() {\n\n  if (!ValidateSysopPassword()) {\n    return;\n  }\n  showdirs();\n  auto done = false;\n  do {\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9)uit (|#2D|#9)elete, (|#2I|#9)nsert, (|#2M|#9)odify, (|#2S|#9)wapDirs, (|#2C|#9)onference : \");\n    char s[81];\n    switch (const auto ch = onek(\"QSDIMC?\"); ch) {\n    case '?':\n      showdirs();\n      break;\n    case 'C':\n      edit_conf_subs(a()->all_confs().dirs_conf());\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'M': {\n      bout.nl();\n      bout.outstr(\"|#2(Q=Quit) Dir number? \");\n      const auto r = bin.input_number_hotkey(0, {'Q'}, 0, a()->dirs().size());\n      if (r.key == 'Q') {\n        break;\n      }\n      modify_dir(r.num);\n    } break;\n    case 'S':\n      if (a()->dirs().size() < a()->config()->max_dirs()) {\n        bout.nl();\n        bout.outstr(\"|#2Take dir number? \");\n        bin.input(s, 4);\n        auto i1 = to_number<int>(s);\n        if (!s[0] || i1 < 0 || i1 >= a()->dirs().size()) {\n          break;\n        }\n        bout.nl();\n        bout.outstr(\"|#2And put before dir number? \");\n        bin.input(s, 4);\n        const auto i2 = to_number<int>(s);\n        if (!s[0] || i2 < 0 || i2 % 32 == 0 || i2 > a()->dirs().size() || i1 == i2) {\n          break;\n        }\n        bout.nl();\n        if (i2 < i1) {\n          i1++;\n        }\n        write_qscn(a()->sess().user_num(), a()->sess().qsc, true);\n        bout.outstr(\"|#1Moving dir now...Please wait...\");\n        insert_dir(i2);\n        swap_dirs(i1, i2);\n        delete_dir(i1);\n        showdirs();\n      } else {\n        bout.outstr(\"\\r\\n|#6You must increase the number of dirs in WWIVconfig first.\\r\\n\");\n      }\n      break;\n    case 'I': {\n      if (a()->dirs().size() < a()->config()->max_dirs()) {\n        bout.nl();\n        bout.outstr(\"|#2Insert before which dir? \");\n        bin.input(s, 4);\n        const auto i = to_number<int>(s);\n        if (s[0] != 0 && i >= 0 && i <= a()->dirs().size()) {\n          insert_dir(i);\n          modify_dir(i);\n        }\n      }\n    } break;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#2Delete which dir? \");\n      bin.input(s, 4);\n      const auto i = to_number<int>(s);\n      if (s[0] != 0 && i >= 0 && i < a()->dirs().size()) {\n        bout.nl();\n        bout.print(\"|#5Delete {}? \", a()->dirs()[i].name);\n        if (bin.yesno()) {\n          // Grab a reference to this filename before deleting it, since once\n          // a()->dirs()[i] is deleted it no longer exists.\n          const auto fn = a()->dirs()[i].filename;\n          delete_dir(i);\n          bout.nl();\n          bout.outstr(\"|#5Delete data files (.DIR/.EXT) for dir also? \");\n          if (bin.yesno()) {\n            File::Remove(FilePath(a()->config()->datadir(), StrCat(fn, \".dir\")));\n            File::Remove(FilePath(a()->config()->datadir(), StrCat(fn, \".ext\")));\n          }\n        }\n      }\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n  a()->dirs().Save();\n  if (!a()->at_wfc()) {\n    changedsl();\n  }\n}\n"
  },
  {
    "path": "bbs/diredit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_DIREDIT_H__\n#define __INCLUDED_BBS_DIREDIT_H__\n\nvoid dlboardedit();\n\n#endif  // __INCLUDED_BBS_DIREDIT_H__"
  },
  {
    "path": "bbs/dirlist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/files.h\"\n\nusing namespace wwiv::sdk;\n\n/** Displays the available file areas for the current user. */\nvoid dirlist(int mode) {\n\n  if (a()->udir.empty()) {\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n\n  bool next   = false;\n  int oc      = a()->sess().current_user_dir_conf_num();\n  int os      = a()->current_user_dir().subnum;\n  int nd      = 0;\n  int sn      = a()->sess().current_user_dir_conf_num();\n  int en      = a()->sess().current_user_dir_conf_num();\n  bool done   = false;\n\n  do {\n    bool is = false;\n    bool abort = false;\n    int p = 1;\n    int i = sn;\n\n    while (i <= en && !abort) {\n      auto i1 = 0;\n      while (i1 < wwiv::stl::size_int(a()->udir) && !abort) {\n        auto& udir = wwiv::stl::at(a()->udir, i1);\n        auto& dir = a()->dirs().dir(udir.subnum);\n        auto& conf = wwiv::stl::at(a()->uconfdir, i);\n        std::string s;\n        size_t firstp = 0;\n        if (p && mode == 0) {\n          p = 0;\n          firstp = i1;\n          bout.cls();\n          if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n            auto conf_name = stripcolors(conf.conf_name);\n            s = fmt::sprintf(\" [ Conference %c ] [ %s ] \", conf.key.key(), conf_name);\n          } else {\n            s = fmt::sprintf(\" [ %s File Areas ] \", a()->config()->system_name());\n          }\n          bout.litebar(s);\n          DisplayHorizontalBar(78, 7);\n          bout.outstr(\"|#2 Dir Qscan?     Directory Name                          Total Files\\r\\n\");\n          DisplayHorizontalBar(78, 7);\n        }\n        ++nd;\n        const auto directory_number = udir.subnum;\n        if (directory_number == 0) {\n          is = true;\n        }\n        std::string scanme = \"|#6No \";\n        if (a()->sess().qsc_n[directory_number / 32] & (1L << (directory_number % 32))) {\n          scanme = \"|#5Yes\";\n        }\n        dliscan1(dir);\n        if (a()->current_user_dir().subnum == a()->udir[i1].subnum) {\n          s = fmt::sprintf(\" |#9%3s |#9\\xB3 |#6%3s |#9\\xB3|17|15 %-40.40s |#9\\xB3 |#9%4d|16\",\n                           a()->udir[i1].keys, scanme, dir.name,\n                           a()->current_file_area()->number_of_files());\n        } else {\n          s = fmt::sprintf(\" |#9%3s |#9\\xB3 |#6%3s |#9\\xB3 %s%-40.40s |#9\\xB3 |#9%4d\",\n                           a()->udir[i1].keys, scanme,\n                           mode == 1 && a()->dirs()[a()->udir[i1].subnum].mask & mask_cdrom ? \"|#9\"\n                                                                                            : \"|#1\",\n                           dir.name, a()->current_file_area()->number_of_files());\n        }\n        if (okansi()) {\n          bout.outstr(s, &abort, &next);\n        } else {\n          bout.outstr(stripcolors(s), &abort, &next);\n        }\n        int lastp = i1++;\n        bout.nl();\n        if (bout.lines_listed() >= a()->sess().num_screen_lines() - 2 && mode == 0) {\n          p = 1;\n          bout.clear_lines_listed();\n          DisplayHorizontalBar(78, 7);\n          bout.printf(\"|#1Select |#9[|#2%d-%d, [N]ext Page, [Q]uit|#9]|#0 : \",\n                                            is ? firstp : firstp + 1, lastp);\n          std::string ss = mmkey(MMKeyAreaType::dirs, true);\n          if (isdigit(ss[0])) {\n            for (uint16_t i3 = 0; i3 < static_cast<uint16_t>(a()->dirs().size()); i3++) {\n              if (ss == a()->udir[i3].keys) {\n                a()->set_current_user_dir_num(i3);\n                os = a()->current_user_dir().subnum;\n                done = true;\n                abort = true;\n              }\n            }\n          } else {\n            switch (ss.front()) {\n            case 'Q':\n              if (okconf(a()->user())) {\n                setuconf(ConferenceType::CONF_DIRS, oc, os);\n              }\n              done    = true;\n              abort   = true;\n              break;\n            default:\n              bout.backline();\n              break;\n            }\n          }\n        }\n      }\n      if (nd) {\n        i++;\n      }\n      if (!okconf(a()->user())) {\n        break;\n      }\n    }\n    if (i == 0) {\n      bout.bpla(\"None.\", &abort);\n      bout.nl();\n    }\n    if (!abort && mode == 0) {\n      p = 1;\n      DisplayHorizontalBar(78, 7);\n      if (okconf(a()->user())) {\n        if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n          bout.printf(\"|#1Select |#9[|#2%d-%d, J=Join Conference, ?=List Again, Q=Quit|#9]|#0 : \",\n                                            is ? 0 : 1, is ? nd - 1 : nd);\n        } else {\n          bout.printf(\"|#1Select |#9[|#2%d-%d, ?=List Again, Q=Quit|#9]|#0 : \", is ? 0 : 1,\n                                            is ? nd - 1 : nd);\n        }\n      } else {\n        bout.printf(\"|#1Select |#9[|#2%d-%d, ?=List Again, Q=Quit|#9]|#0 : \", is ? 0 : 1,\n                                          is ? nd - 1 : nd);\n      }\n      std::string ss = mmkey(MMKeyAreaType::subs, true);\n      if (ss.empty() || ss == \"Q\" || ss == \"\\r\") {\n        if (okconf(a()->user())) {\n          setuconf(ConferenceType::CONF_DIRS, oc, os);\n        }\n        done = true;\n      }\n      if (ss == \"J\") {\n        if (okconf(a()->user())) {\n          jump_conf(ConferenceType::CONF_DIRS);\n        }\n        sn = en = oc = a()->sess().current_user_dir_conf_num();\n        nd = i = 0;\n        is = false;\n      }\n      if (isdigit(ss.front())) {\n        for (uint16_t i3 = 0; i3 < a()->dirs().size(); i3++) {\n          if (ss == a()->udir[i3].keys) {\n            a()->set_current_user_dir_num(i3);\n            os = a()->current_user_dir().subnum;\n            done = true;\n          }\n        }\n      }\n      nd = 0;\n    } else {\n      if (okconf(a()->user())) {\n        setuconf(ConferenceType::CONF_DIRS, oc, os);\n      }\n      done = true;\n    }\n  } while (!a()->sess().hangup() && !done);\n}\n\n\n"
  },
  {
    "path": "bbs/dirlist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_DIRLIST_H__\n#define __INCLUDED_BBS_DIRLIST_H__\n\nvoid dirlist(int mode);\n\n#endif  // __INCLUDED_BBS_DIRLIST_H__"
  },
  {
    "path": "bbs/dropfile.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/dropfile.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"common/datetime.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"common/output.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include <algorithm>\n#include <memory>\n#include <string>\n\nusing std::chrono::duration_cast;\nusing std::chrono::seconds;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n#pragma pack(push, 1)\n\n// See http://wiki.bbs.nz/doors:dropfiles:pcboardsys\n// Note, this doesn't seem to match perfectly what that states, but this\n// is the same pcboard.sys format wwiv has done for years.\nstruct pcboard_sys_rec {\n  char display[2], printer[2], page_bell[2], alarm[2], sysop_next, errcheck[2], graphics, nodechat,\n      openbps[5], connectbps[5];\n\n  int16_t usernum;\n\n  char firstname[15], password[12];\n\n  int16_t time_on, prev_used;\n\n  char time_logged[5];\n\n  int16_t time_limit, down_limit;\n\n  char curconf, bitmap1[5], bitmap2[5];\n\n  int16_t time_added, time_credit;\n\n  char slanguage[4], name[25];\n\n  int16_t sminsleft;\n\n  char snodenum, seventtime[5], seventactive[2], sslide[2], smemmsg[4], scomport, packflag, bpsflag;\n\n  // PCB 14.5 extra stuff\n  char ansi, lastevent[8];\n\n  int16_t lasteventmin;\n\n  char exittodos, eventupcoming;\n\n  int16_t lastconfarea;\n\n  char hconfbitmap;\n  // end PCB 14.5 additions\n};\n#pragma pack(pop)\n\n[[maybe_unused]] static constexpr auto sizeof_pcboard_sys = sizeof(pcboard_sys_rec);\n\nstatic constexpr int NULL_HANDLE = 0;\n\nstatic int GetDoor32CommType() {\n  if (!a()->sess().using_modem()) {\n    return 0;\n  }\n#ifdef _WIN32\n  return bout.remoteIO()->GetHandle() == NULL_HANDLE ? 1 : 2;\n#else\n  return 0;\n#endif\n}\n\nstatic int GetDoor32Emulation() { return (okansi()) ? 1 : 0; }\n\nstd::filesystem::path create_dropfile_path(drop_file_t dropfile_type) {\n  const auto tempdir = a()->sess().dirs().temp_directory();\n  switch (dropfile_type) {\n  case drop_file_t::CHAIN_TXT:\n    return FilePath(tempdir, DROPFILE_CHAIN_TXT);\n  case drop_file_t::DORINFO_DEF:\n    return FilePath(tempdir, \"dorinfo1.def\");\n  case drop_file_t::PCBOARD_SYS:\n    return FilePath(tempdir, \"pcboard.sys\");\n  case drop_file_t::CALLINFO_BBS:\n    return FilePath(tempdir, \"callinfo.bbs\");\n  case drop_file_t::DOOR_SYS:\n    return FilePath(tempdir, \"door.sys\");\n  case drop_file_t::DOOR32_SYS:\n    return FilePath(tempdir, \"door32.sys\");\n  default:\n    // Default to CHAIN.TXT since this is the native WWIV format\n    return FilePath(tempdir, DROPFILE_CHAIN_TXT);\n  }\n}\n\nstd::string create_dropfile_filename(drop_file_t dropfile_type) {\n  return create_dropfile_path(dropfile_type).string();\n}\n\n/**\n * Returns first or last name from string (s) back into s\n */\nstatic std::string GetNamePartForDropFile(bool last_name, const std::string& name) {\n  if (const auto idx = name.find(' '); idx != std::string::npos) {\n    // We have a space\n    if (last_name) {\n      return name.substr(idx + 1);\n    }\n    return name.substr(0, idx);\n  }\n  if (last_name) {\n    // If we only have one name, don't return it for the last name\n    return {};\n  }\n  return name;\n}\n\nstatic long GetMinutesRemainingForDropFile() {\n  const auto time_left = std::max<long>((nsl() / 60) - 1L, 0);\n  if (!a()->sess().using_modem()) {\n    // When we generate a dropfile from the WFC, give it a suitable amount\n    // of time remaining vs. 1 minute since we don't have an active session.\n    // Also allow at least an hour for all local users.\n    return std::max<long>(60, time_left);\n  }\n  return time_left;\n}\n\n/** make DORINFO1.DEF (RBBS and many others) dropfile */\nvoid CreateDoorInfoDropFile() {\n  const auto fileName = create_dropfile_filename(drop_file_t::DORINFO_DEF);\n  const auto& u = *a()->user();\n  File::Remove(fileName);\n  TextFile f(fileName, \"wd\");\n  if (f.IsOpen()) {\n    f.WriteLine(a()->config()->system_name());\n    f.WriteLine(a()->config()->sysop_name());\n    f.WriteLine();\n    f.WriteLine(fmt::sprintf(\"COM%d\",a()->sess().incom() ? a()->primary_port() : 0));\n    f.WriteLine(fmt::sprintf (\"%u BAUD,N,8,1\", ((a()->sess().using_modem()) ? a()->modem_speed_ : 0)));\n    f.WriteLine(\"0\");\n    if (!(a()->config()->sysconfig_flags() & sysconfig_allow_alias)) {\n      f.WriteLine(GetNamePartForDropFile(false, u.real_name()));\n      f.WriteLine(GetNamePartForDropFile(true, u.real_name()));\n    } else {\n      f.WriteLine(u.name());\n      f.WriteLine();\n    }\n    if (!u.city().empty() && !u.state().empty()) {\n      f.WriteLine(StrCat(u.city(), \", \", u.state()));\n    } else {\n      f.WriteLine();\n    }\n    f.WriteLine(u.ansi() ? \"1\" : \"0\");\n    f.WriteLine(std::to_string(u.sl()));\n    f.WriteLine(std::to_string(GetMinutesRemainingForDropFile()));\n    f.Close();\n  }\n}\n\n/** make PCBOARD.SYS (PC Board) drop file */\nvoid CreatePCBoardSysDropFile() {\n  const auto fileName = create_dropfile_filename(drop_file_t::PCBOARD_SYS);\n  const auto& u = *a()->user();\n  File::Remove(fileName);\n  File pcbFile(fileName);\n  if (pcbFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    pcboard_sys_rec pcb{};\n    memset(&pcb, 0, sizeof(pcb));\n    memcpy(pcb.display, \"-1\", 2);\n    memcpy(pcb.printer, \" 0\", 2); // -1 if logging is to the printer, 0 otherwise;\n    memcpy(pcb.page_bell, \" 0\", 2);\n    memcpy(pcb.alarm, \" 0\", 2);\n    memcpy(pcb.errcheck, \"-1\", 2);\n    if (okansi()) {\n      pcb.graphics = 'Y';\n      pcb.ansi = '1';\n    } else {\n      pcb.graphics = 'N';\n      pcb.ansi = '0';\n    }\n    pcb.nodechat = 32;\n    auto modem_speed_str = std::to_string(a()->modem_speed_);\n    sprintf(pcb.openbps, \"%-5.5s\", modem_speed_str.c_str());\n    if (!a()->sess().incom()) {\n      memcpy(pcb.connectbps, \"Local\", 5);\n    } else {\n      snprintf(pcb.connectbps, 5, \"%-5.5d\", a()->modem_speed_);\n    }\n    pcb.usernum = static_cast<int16_t>(u.usernum());\n    char szName[255];\n    sprintf(szName, \"%-25.25s\", u.GetName());\n    char* firstname = strtok(szName, \" \\t\");\n    sprintf(pcb.firstname, \"%-15.15s\", firstname);\n    // Don't write password  security\n    strcpy(pcb.password, \"XXX\");\n    const auto timeon_sec = duration_cast<seconds>(u.timeon()).count();\n    pcb.time_on = static_cast<int16_t>(timeon_sec / 60);\n    pcb.prev_used = 0;\n    auto time_has_hhmmss = ctim(u.timeon());\n    pcb.time_logged[0] = time_has_hhmmss[0];\n    pcb.time_logged[1] = time_has_hhmmss[1];\n    pcb.time_logged[2] = ':';\n    pcb.time_logged[3] = time_has_hhmmss[3];\n    pcb.time_logged[4] = time_has_hhmmss[4];\n    pcb.time_limit = static_cast<int16_t>(nsl());\n    pcb.down_limit = 1024;\n    pcb.curconf = static_cast<char>(a()->sess().current_user_sub_conf_num());\n    strcpy(pcb.slanguage, a()->sess().current_language().c_str());\n    strcpy(pcb.name, u.GetName());\n    pcb.sminsleft = pcb.time_limit;\n    pcb.snodenum = static_cast<char>((num_instances() > 1) ? a()->sess().instance_number() : 0);\n    memcpy(pcb.seventtime, \"01:00\", 5);\n    memcpy(pcb.seventactive, \" 0\", 2);\n    memcpy(pcb.sslide, \" 0\", 2);\n    pcb.scomport = a()->primary_port() + '0';\n    pcb.packflag = 27;\n    pcb.bpsflag = 32;\n    // Added for PCB 14.5 Revision\n    auto status = a()->status_manager()->get_status();\n    to_char_array_no_null(pcb.lastevent, status->last_date());\n    pcb.exittodos = '0';\n    pcb.eventupcoming = '0';\n    pcb.lastconfarea = static_cast<int16_t>(a()->sess().current_user_sub_conf_num());\n    // End Additions\n\n    pcbFile.Write(&pcb, sizeof(pcb));\n    pcbFile.Close();\n  }\n}\n\n// See https://github.com/jquast/x84/blob/master/x84/bbs/door.py#L290\n// Also\n// https://github.com/sdudley/maximus/blob/1cc413a28df645aeb7170ac7524a05abf501e6ab/mec/misc/callinfo.mec\nvoid CreateCallInfoBbsDropFile() {\n  // make CALLINFO.BBS (WildCat!)\n  const auto& u = *a()->user();\n  const auto fileName = create_dropfile_filename(drop_file_t::CALLINFO_BBS);\n  File::Remove(fileName);\n  TextFile file(fileName, \"wd\");\n  if (file.IsOpen()) {\n    file.WriteLine(u.real_name());\n    switch (a()->modem_speed_) {\n    case 300:\n      file.WriteLine(\"1\");\n      break;\n    case 1200:\n      file.WriteLine(\"2\");\n      break;\n    case 2400:\n      file.WriteLine(\"0\");\n      break;\n    case 19200:\n      file.WriteLine(\"4\");\n      break;\n    default:\n      file.WriteLine(\"3\");\n    }\n    const auto t = times();\n    const auto start_duration = duration_since_midnight(a()->sess().system_logon_time());\n    const auto start_minute = std::chrono::duration_cast<std::chrono::minutes>(start_duration).count();\n    file.WriteLine(\" \");\n    file.WriteLine(u.sl());\n    file.WriteLine(GetMinutesRemainingForDropFile());\n    file.WriteLine(u.ansi() ? \"COLOR\" : \"MONO\");\n    file.WriteLine(\"X\");\n    file.WriteLine(u.usernum());\n    file.WriteLine(start_minute);\n    file.WriteLine(t.substr(0, 5));\n    file.WriteLine(\"0\");\n    file.WriteLine(\"ABCD\");\n    file.WriteLine(\"0\");\n    file.WriteLine(\"0\");\n    file.WriteLine(\"0\");\n    file.WriteLine(\"0\");\n    file.Write(fmt::sprintf(\"%s\\n%s 00:01\\nEXPERT\\nN\\n%s\\n%d\\n%d\\n1\\n%d\\n%d\\n%s\\n%s\\n%d\\n\",\n                        u.voice_phone(), u.laston(),\n                        u.laston(), u.logons(),\n                        u.screen_lines(), u.uploaded(),\n                        u.downloaded(), \"8N1\",\n                        (a()->sess().incom()) ? \"REMOTE\" : \"LOCAL\",\n                        (a()->sess().incom()) ? a()->primary_port() : 0));\n    file.WriteLine(u.birthday_mmddyy());\n    file.WriteLine(a()->sess().incom() ? std::to_string(a()->modem_speed_) : \"38400\");\n    file.Close();\n  }\n}\n\nstatic unsigned int GetDoorHandle() {\n  if (bout.remoteIO()) {\n    return bout.remoteIO()->GetDoorHandle();\n  }\n  return 0;\n}\n\n/** Make DOOR32.SYS drop file */\nvoid CreateDoor32SysDropFile() {\n  /* =========================================================================\n     File Format: (available at http://www.mysticbbs.com/door32/d32spec1.txt)\n     =========================================================================\n\n     0                       Line 1 : Comm type (0=local, 1=serial, 2=telnet)\n     0                       Line 2 : Comm or socket handle\n     38400                   Line 3 : Baud rate\n     Mystic 1.07             Line 4 : BBSID (software name and version)\n     1                       Line 5 : User record position (1-based)\n     James Coyle             Line 6 : User's real name\n     g00r00                  Line 7 : User's handle/alias\n     255                     Line 8 : User's security level\n     58                      Line 9 : User's time left (in minutes)\n     1                       Line 10: Emulation *See Below\n     1                       Line 11: Current node number\n\n    * The following are values we've predefined for the emulation:\n\n      0 = Ascii\n      1 = Ansi\n      2 = Avatar\n      3 = RIP\n      4 = Max Graphics\n\n     ========================================================================= */\n  const auto fileName = create_dropfile_filename(drop_file_t::DOOR32_SYS);\n  const auto& u = *a()->user();\n  File::Remove(fileName);\n\n  TextFile file(fileName, \"wt\");\n  if (!file.IsOpen()) {\n    return;\n  }\n  file.WriteLine(GetDoor32CommType());\n  file.WriteLine(GetDoorHandle());\n  const auto cspeed = std::to_string(a()->modem_speed_);\n  file.WriteLine(cspeed);\n  file.WriteLine(StrCat(\"WWIV \", short_version()));\n  file.WriteLine(u.usernum());\n  file.WriteLine(u.real_name());\n  file.WriteLine(u.name());\n  file.WriteLine(u.sl());\n  file.WriteLine(60 * GetMinutesRemainingForDropFile());\n  file.WriteLine(GetDoor32Emulation());\n  file.WriteLine(a()->sess().instance_number());\n}\n\n/** Create generic DOOR.SYS dropfile.\n * See https://github.com/wwivbbs/wwiv/wiki/DOOR.SYS-format\n * or http://files.mpoli.fi/unpacked/software/dos/bbs/drwy231.zip/doorsys.doc\n */\nvoid CreateDoorSysDropFile() {\n  const auto fileName = create_dropfile_filename(drop_file_t::DOOR_SYS);\n  File::Remove(fileName);\n  const auto& u = *a()->user();\n\n  TextFile file(fileName, \"wd\");\n  if (file.IsOpen()) {\n    const auto cspeed = std::to_string(a()->modem_speed_);\n    const auto real_name = u.real_name();\n    auto line = fmt::sprintf(\"COM%d\\n%s\\n%c\\n%u\\n%d\\n%c\\n%c\\n%c\\n%c\\n%s\\n%s, %s\\n\",\n            a()->sess().using_modem() ? a()->primary_port() : 0, cspeed, '8',\n            a()->sess().instance_number(), // node\n            a()->sess().using_modem() ? a()->modem_speed_ : 38400,\n            'Y', // screen display\n            'N', // log to printer\n            'N', // page bell\n            'N', // caller alarm\n            real_name, u.city(), u.state());\n    file.Write(line);\n    line = fmt::sprintf(\"%s\\n%s\\n%s\\n%d\\n%u\\n%s\\n%u\\n%ld\\n\", u.voice_phone(),\n            real_name,\n            \"X\", // u.password()\n            u.sl(), u.logons(), u.laston(),\n            static_cast<uint32_t>(60L * GetMinutesRemainingForDropFile()),\n            GetMinutesRemainingForDropFile());\n    file.Write(line);\n    const auto* const ansiStatus = okansi() ? \"GR\" : \"NG\";\n    line = fmt::sprintf(\"%s\\n%u\\n%c\\n%s\\n%u\\n%s\\n%u\\n%c\\n%u\\n%u\\n%u\\n%d\\n\", ansiStatus,\n            u.screen_lines(), u.IsExpert() ? 'Y' : 'N',\n            \"1,2,3\",                     // conferences\n            a()->current_user_sub_num(), // current 'conference'\n            \"12/31/99\",                  // expiration date\n            u.usernum(),\n            'Y', // default protocol\n            u.uploaded(), u.downloaded(),\n            0,  // kb dl today\n            0); // kb dl/day max\n    file.Write(line);\n    const auto birthday_date = u.birthday_mmddyy();\n    const auto gfilesdir = a()->config()->gfilesdir().string();\n    const auto datadir = a()->config()->datadir().string();\n    const auto t = times();\n    line = fmt::sprintf(\"%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%c\\n%c\\n%c\\n%u\\n%u\\n%s\\n%-.5s\\n%s\\n\", \n            birthday_date,\n            datadir, gfilesdir,\n            a()->config()->sysop_name(), u.name(),\n            \"00:01\", // event time\n            'Y',\n            okansi() ? 'N' : 'Y', // ansi ok but graphics turned off\n            'N',                    // record-locking\n            u.color(0), u.banktime_minutes(),\n            u.laston(), // last n-scan date\n            t,\n            \"00:01\"); // time last call\n    file.Write(line);\n    line = fmt::sprintf(\"%u\\n%u\\n%d\\n%d\\n%s\\n%u\\n%d\\n\",\n            99, // max files dl/day\n            0,  // files dl today so far\n            u.uk(), u.dk(), u.note(),\n            u.chains_run(), u.messages_posted());\n    file.Write(line);\n    file.Close();\n  }\n}\n\nstatic void create_drop_files() {\n  CreateDoorInfoDropFile();\n  CreatePCBoardSysDropFile();\n  CreateCallInfoBbsDropFile();\n  CreateDoorSysDropFile();\n  CreateDoor32SysDropFile();\n}\n\n/**\n * \\verbatim \nCHAIN.TXT Definition File by MrBill.\n-----------CHAIN.TXT-----------------------------------\n1                  User number\nMRBILL             User alias\nBill               User real name\nUser callsign (HAM radio)\n21                 User age\nM                  User sex\n16097.00           User gold\n05/19/89           User last logon date\n80                 User colums\n25                 User width\n255                User security level (0-255)\n1                  1 if Co-SysOp, 0 if not\n1                  1 if SysOp, 0 if not\n1                  1 if ANSI, 0 if not\n0                  1 if at remote, 0 if local console\n2225.78            User number of seconds left till logoff\nF:\\WWIV\\GFILES\\    System GFILES directory (gen. txt files)\nF:\\WWIV\\DATA\\      System DATA directory\n890519.LOG         System log of the day\n2400               User baud rate\n2                  System com port\nMrBill's Abode     System name\nMrBill             System SysOp\n83680              Time user logged on/# of secs. from midn\n554                User number of seconds on system so far\n5050               User number of uploaded k\n22                 User number of uploads\n42                 User amount of downloaded k\n1                  User number of downloads\n8N1                User parity\n2400               Com port baud rate\n7400               WWIVnet node number\n\\endverbatim \n */\nstd::string create_chain_file() {\n  const auto cspeed = std::to_string(a()->modem_speed_);\n  const auto& u = *a()->user();\n\n  create_drop_files();\n  const auto start_duration = duration_since_midnight(a()->sess().system_logon_time());\n  const auto start_second =\n      static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(start_duration).count());\n  const auto used_duration = std::chrono::system_clock::now() - a()->sess().system_logon_time();\n  const auto seconds_used =\n      static_cast<int>(std::chrono::duration_cast<std::chrono::seconds>(used_duration).count());\n\n  auto fileName = create_dropfile_filename(drop_file_t::CHAIN_TXT);\n  File::Remove(fileName);\n  TextFile file(fileName, \"wd\");\n  if (file.IsOpen()) {\n    file.Write(fmt::sprintf(\n        \"%d\\n%s\\n%s\\n%s\\n%d\\n%c\\n%10.2f\\n%s\\n%d\\n%d\\n%d\\n\", u.usernum(), u.name(),\n        u.real_name(), u.callsign(), u.age(),\n        u.gender(), u.gold(), u.laston(),\n        u.screen_width(), u.screen_lines(), u.sl()));\n    const auto temporary_log_filename = instance_sysoplog_filename();\n    const auto gfilesdir = a()->config()->gfilesdir().string();\n    const auto datadir = a()->config()->datadir().string();\n    file.Write(fmt::sprintf(\"%d\\n%d\\n%d\\n%u\\n%8ld.00\\n%s\\n%s\\n%s\\n\", cs(), so(), okansi(),\n                            a()->sess().incom(), nsl(), gfilesdir, datadir,\n                            temporary_log_filename));\n    if (a()->sess().using_modem()) {\n      file.WriteLine(a()->modem_speed_);\n    } else {\n      file.WriteLine(\"KB\");\n    }\n    file.Write(fmt::sprintf(\"%d\\n%s\\n%s\\n%d\\n%d\\n%lu\\n%u\\n%lu\\n%u\\n%s\\n%s\\n%u\\n\", a()->primary_port(),\n                        a()->config()->system_name(), a()->config()->sysop_name(),\n                        start_second, seconds_used, u.uk(),\n                        u.uploaded(), u.dk(),\n                        u.downloaded(), \"8N1\", cspeed,\n                        a()->current_net().sysnum));\n    file.Write(fmt::sprintf(\"N\\nN\\nN\\n\"));\n    file.Write(fmt::sprintf(\"%u\\n%u\\n\", u.ar_int(), u.dar_int()));\n    file.Close();\n  }\n\n  return fileName;\n}\n\nstd::string nf_path(const std::string& cmd) {\n  const auto path = FilePath(a()->netfoss_dir(), cmd);\n  return path.string();\n}\n\nstd::optional<std::string> create_netfoss_bat() {\n\n  if (!File::Exists(a()->netfoss_dir())) {\n    LOG(ERROR) << \"NetFoss not installed into NETFOSS_DIR: \" << a()->netfoss_dir().string();\n    return std::nullopt;\n  }\n  const auto& tempdir = a()->sess().dirs().temp_directory();\n  const auto path = FilePath(tempdir, \"nf.bat\");\n\n  TextFile f(path, \"wt\");\n  if (!f.IsOpen()) {\n    return std::nullopt;\n  }\n\n  f.WriteLine(\"@echo off\");\n  f.WriteLine(StrCat(\"rem WWIV Generated NF.BAT: \", DateTime::now().to_string()));\n  f.WriteLine(nf_path(\"ansi.com\"));\n  f.WriteLine(nf_path(\"netfoss.com\"));\n  f.WriteLine(\"if errorlevel 1 goto end\");\n  f.WriteLine(nf_path(\"netcom.exe %1 %2 %3 %4 %5 %6 %7 %8 %9\"));\n  f.WriteLine(nf_path(\"netfoss.com /u\"));\n  f.WriteLine(\":end\");\n\n  return f.full_pathname();\n}"
  },
  {
    "path": "bbs/dropfile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2014-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_DROPFILE_H\n#define INCLUDED_BBS_DROPFILE_H\n\n#include <optional>\n#include <string>\n\nenum class drop_file_t {\n  CHAIN_TXT,\n  DORINFO_DEF,\n  PCBOARD_SYS,\n  CALLINFO_BBS,\n  DOOR_SYS,\n  DOOR32_SYS\n};\n\n/** \n * Creates a dropfile of type dropfile_type, and returns the string form\n * of the filename.\n */\nstd::string create_dropfile_filename(drop_file_t dropfile_type);\n/**\n * Creates a dropfile of type chain.txt, and returns the string form\n * of the filename.\n */\nstd::string create_chain_file();\n\nstd::optional<std::string> create_netfoss_bat();\n\n#endif\n"
  },
  {
    "path": "bbs/dsz.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/dsz.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"sdk/files/files.h\"\n#include <string>\n#include <tuple>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstd::tuple<dsz_logline_t, std::string, int> handle_dszline(const std::string& l) {\n\n  const auto parts = SplitString(l, \" \\t\");\n  if (parts.size() < 11) {\n    LOG(ERROR) << \"Malformed DSZ Log Line: '\" << l << \"'\";\n    return std::make_tuple(dsz_logline_t::error, \"\", 0);\n  }\n  const auto code = parts.at(0).front();\n  const auto cps = to_number<int>(parts.at(4));\n  const std::filesystem::path p(parts.at(10));\n  const auto fn = p.has_filename() ? wwiv::sdk::files::align(p.filename().string()) : \"\";\n\n  switch (code) {\n  case 'Z':\n  case 'r':\n  case 'R':\n  case 'B':\n  case 'H':\n    // received a file\n    return std::make_tuple(dsz_logline_t::upload, fn, cps);\n  case 'z':\n  case 's':\n  case 'S':\n  case 'b':\n  case 'h':\n  case 'Q':\n    // sent a file\n    return std::make_tuple(dsz_logline_t::download, fn, cps);\n  case 'E':\n  case 'e':\n  case 'L':\n  case 'l':\n  case 'U':\n  default:\n    return std::make_tuple(dsz_logline_t::error, \"\", -1);\n  }\n}\n\nbool ProcessDSZLogFile(const std::string& path, dsz_logline_callback_fn cb) {\n  TextFile tf(path, \"rt\");\n  if (!tf) {\n    return false;\n  }\n  const auto lines = tf.ReadFileIntoVector();\n  for (const auto& l : lines) {\n    auto [type, fn, cps] = handle_dszline(l);\n    cb(type, fn, cps);\n  }\n  return true;\n}\n"
  },
  {
    "path": "bbs/dsz.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_DSZ_H__\n#define __INCLUDED_BBS_DSZ_H__\n\n#include <functional>\n#include <string>\n#include <tuple>\n\nenum class dsz_logline_t {\n  upload,\n  download,\n  error\n};\n\n\ntypedef std::function<void(dsz_logline_t, std::string, int)> dsz_logline_callback_fn;\n\nstd::tuple<dsz_logline_t, std::string, int> handle_dszline(const std::string& l);\nbool ProcessDSZLogFile(const std::string& path, dsz_logline_callback_fn cb);\n\n#endif  // __INCLUDED_BBS_DSZ_H__\n"
  },
  {
    "path": "bbs/dsz_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2007-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/dsz.h\"\n#include \"core/log.h\"\n#include \"core/textfile.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/files/files.h\"\n#include <string>\n\nTEST(DszTest, Smoke) {\n  wwiv::core::test::FileHelper h;\n  const std::string loglines=R\"(Z  46532 38400 bps 3324 cps   0 errors    66 1024 DSZ.COM 1177\nZ 124087 19200 bps 1880 cps   0 errors     6 1024 MXY.TMP 1177\nS 217837 57600 bps 5050 cps   0 errors     0 1024 MPT110.ZIP MPt\n)\";\n  std::vector<std::string> fn_e{\"DSZ.COM\", \"MXY.TMP\", \"MPT110.ZIP\"};\n  std::vector<int> cps_e{3324, 1880, 5050};\n  const auto path = h.CreateTempFile(\"dsz.log\", loglines);\n\n  TextFile tf(path, \"rt\");\n  auto lines = tf.ReadFileIntoVector();\n  for (const auto& l : lines) {\n    LOG(INFO) << l;\n  }\n\n  int dn = 0, ul = 0, e = 0;\n  std::vector<std::string> fn_a;\n  std::vector<int> cps_a;\n  ProcessDSZLogFile(path.string(), [&](dsz_logline_t t, std::string fn, int cps)\n  {\n    fn_a.push_back(fn);\n    cps_a.push_back(cps);\n    switch (t) {\n    case dsz_logline_t::download:\n      ++dn;\n      break;\n    case dsz_logline_t::upload:\n      ++ul;\n      break;\n    case dsz_logline_t::error:\n      ++e;\n      break;\n    }\n  });\n  EXPECT_EQ(1, dn);\n  EXPECT_EQ(2, ul);\n  for (int i=0; i < 3; i++) {\n    EXPECT_EQ(fn_a.at(i), wwiv::sdk::files::align(fn_e.at(i)));\n    EXPECT_EQ(cps_a.at(i), cps_e.at(i));\n  }\n}\n"
  },
  {
    "path": "bbs/email.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/email.h\"\n\n#include \"bbs/attach.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/inetmsg.h\"\n#include \"bbs/inmsg.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/sysoplog.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"core/datetime.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/fido/nodelist.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/networks.h\"\n\n#include <chrono>\n#include <memory>\n#include <string>\n\nstatic constexpr int NUM_ATTEMPTS_TO_OPEN_EMAIL = 5;\nstatic constexpr int DELAY_BETWEEN_EMAIL_ATTEMPTS = 9;\n\nusing std::chrono::seconds;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\n// returns true on success (i.e. the message gets forwarded)\nbool ForwardMessage(uint16_t *pUserNumber, uint16_t *pSystemNumber) {\n  if (*pSystemNumber) {\n    return false;\n  }\n\n  User userRecord;\n  a()->users()->readuser(&userRecord, *pUserNumber);\n  if (userRecord.deleted()) {\n    return false;\n  }\n  if (userRecord.forward_usernum() == 0 && userRecord.forward_systemnum() == 0 &&\n      userRecord.forward_systemnum() != INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n    return false;\n  }\n  if (userRecord.forward_systemnum() != 0) {\n    if (!userRecord.forwarded_to_internet()) {\n      const int network_number = a()->net_num();\n      set_net_num(userRecord.forward_netnum());\n      if (!valid_system(userRecord.forward_systemnum())) {\n        set_net_num(network_number);\n        return false;\n      }\n      if (!userRecord.forward_usernum()) {\n        a()->net_email_name = read_inet_addr(*pUserNumber);\n        if (!check_inet_addr(a()->net_email_name)) {\n          return false;\n        }\n      }\n      *pUserNumber = userRecord.forward_usernum();\n      *pSystemNumber = userRecord.forward_systemnum();\n      return true;\n    }\n    a()->net_email_name = read_inet_addr(*pUserNumber);\n    *pUserNumber = 0;\n    *pSystemNumber = 0;\n    return false;\n  }\n  auto current_user = userRecord.forward_usernum();\n  if (current_user == -1 || current_user == std::numeric_limits<decltype(current_user)>::max()) {\n    bout.outstr(\"Mailbox Closed.\\r\\n\");\n    if (so()) {\n      bout.outstr(\"(Forcing)\\r\\n\");\n    } else {\n      *pUserNumber = 0;\n      *pSystemNumber = 0;\n    }\n    return false;\n  }\n  std::unique_ptr<bool[]> ss(new bool[a()->config()->max_users() + 300]);\n\n  ss[*pUserNumber] = true;\n  a()->users()->readuser(&userRecord, current_user);\n  while (userRecord.forward_usernum() || userRecord.forward_systemnum()) {\n    if (userRecord.forward_systemnum()) {\n      if (!valid_system(userRecord.forward_systemnum())) {\n        return false;\n      }\n      *pUserNumber = userRecord.forward_usernum();\n      *pSystemNumber = userRecord.forward_systemnum();\n      set_net_num(userRecord.forward_netnum());\n      return true;\n    }\n    if (ss[current_user]) {\n      return false;\n    }\n    ss[current_user] = true;\n    if (userRecord.mailbox_closed()) {\n      bout.outstr(\"Mailbox Closed.\\r\\n\");\n      if (so()) {\n        bout.outstr(\"(Forcing)\\r\\n\");\n        *pUserNumber = current_user;\n        *pSystemNumber = 0;\n      } else {\n        *pUserNumber = 0;\n        *pSystemNumber = 0;\n      }\n      return false;\n    }\n    current_user = userRecord.forward_usernum() ;\n    a()->users()->readuser(&userRecord, current_user);\n  }\n  *pSystemNumber = 0;\n  *pUserNumber = current_user;\n  return true;\n}\n\nstd::unique_ptr<File> OpenEmailFile(bool bAllowWrite) {\n  const auto fn = FilePath(a()->config()->datadir(), EMAIL_DAT);\n\n  if (!File::Exists(fn)) {\n    // If it does not exist, try to create it via the open call (sf bug 1215434)\n    auto file = std::make_unique<File>(fn);\n    if (!file->Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n      LOG(ERROR) << \"Unable to create email file: \" << fn;\n    }\n    return file;\n  }\n\n  auto file = std::make_unique<File>(fn);\n  for (auto num = 0; num < NUM_ATTEMPTS_TO_OPEN_EMAIL; num++) {\n    if (file->Open(bAllowWrite ? File::modeBinary | File::modeCreateFile | File::modeReadWrite\n                                  : File::modeBinary | File::modeReadOnly)) {\n      return file;\n    }\n    sleep_for(seconds(DELAY_BETWEEN_EMAIL_ATTEMPTS));\n  }\n  if (!file->IsOpen()) {\n    LOG(ERROR) << \"Unable to open email file: \" << fn;\n  }\n  return file;\n}\n\nvoid sendout_email(EmailData& data) {\n  mailrec m{};\n  mailrec messageRecord{};\n  net_header_rec nh{};\n\n  to_char_array(m.title, data.title);\n  m.msg = *data.msg;\n  m.anony = data.anony;\n  if (data.from_system == a()->current_net().sysnum) {\n    m.fromsys = 0;\n  } else {\n    m.fromsys = data.from_system;\n  }\n  m.fromuser = data.from_user;\n  m.tosys = data.system_number;\n  m.touser = data.user_number;\n  m.status = 0;\n  m.daten = daten_t_now();\n\n  if (m.fromsys && wwiv::stl::ssize(a()->nets()) > 1) {\n    m.status |= status_new_net;\n    // always trim to WWIV_MESSAGE_TITLE_LENGTH now.\n    m.title[71] = '\\0';\n    m.network.network_msg.net_number = static_cast<int8_t>(data.from_network_number);\n  }\n\n  if (data.system_number == 0) {\n    auto file_email(OpenEmailFile(true));\n    if (!file_email->IsOpen()) {\n      return;\n    }\n    auto nEmailFileLen = file_email->length() / sizeof(mailrec);\n    File::size_type i = 0;\n    if (nEmailFileLen != 0) {\n      i = nEmailFileLen - 1;\n      file_email->Seek(i * sizeof(mailrec), File::Whence::begin);\n      file_email->Read(&messageRecord, sizeof(mailrec));\n      while (i > 0 && messageRecord.tosys == 0 && messageRecord.touser == 0) {\n        --i;\n        file_email->Seek(i * sizeof(mailrec), File::Whence::begin);\n        if (auto i1 = file_email->Read(&messageRecord, sizeof(mailrec)); i1 == -1) {\n          bout.outstr(\"|#6DIDN'T READ WRITE!\\r\\n\");\n        }\n      }\n      if (messageRecord.tosys || messageRecord.touser) {\n        ++i;\n      }\n    }\n\n    file_email->Seek(i * sizeof(mailrec), File::Whence::begin);\n    auto bytes_written = file_email->Write(&m, sizeof(mailrec));\n    file_email->Close();\n    if (bytes_written == -1) {\n      bout.outstr(\"|#6DIDN'T SAVE RIGHT!\\r\\n\");\n    }\n  } else {\n    auto o = readfile(&m.msg, \"email\"); \n    if (!o) {\n      return;\n    }\n    if (data.forwarded_code == 2) {\n      // Not sure where this is ever set to 2...\n      remove_link(&m.msg, \"email\");\n    }\n    nh.tosys  = static_cast<uint16_t>(data.system_number);\n    nh.touser = static_cast<uint16_t>(data.user_number);\n    if (data.from_system > 0) {\n      nh.fromsys = static_cast<uint16_t>(data.from_system);\n    } else {\n      nh.fromsys = a()->current_net().sysnum;\n    }\n    nh.fromuser = static_cast<uint16_t>(data.from_user);\n    nh.main_type = main_type_email;\n    nh.minor_type = 0;\n    nh.list_len = 0;\n    nh.daten = m.daten;\n    nh.method = 0;\n    auto b = o.value();\n    auto b1 = std::make_unique<char[]>(b.size() + 768);\n    int i = 0;\n    if (data.user_number == 0 && data.from_network_number == a()->net_num()) {\n      nh.main_type = main_type_email_name;\n      strcpy(&b1[i], a()->net_email_name.c_str());\n      i += wwiv::stl::size_int(a()->net_email_name) + 1;\n    }\n    strcpy(&b1[i], m.title);\n    i += ssize(m.title) + 1;\n    memmove(&b1[i], b.c_str(), b.length());\n    nh.length = wwiv::stl::size_int(b) + i;\n    if (nh.length > 32760) {\n      bout.printf(\"Message truncated by %lu bytes for the network.\", nh.length - 32760L);\n      nh.length = 32760;\n    }\n    if (data.from_network_number != a()->net_num()) {\n      gate_msg(&nh, b1.get(), \n        a()->net_num(), a()->net_email_name, \n      {}, data.from_network_number);\n    } else {\n      const auto fn =\n          fmt::format(\"{}{}\", data.forwarded_code ? \"p1\" : \"p0\", a()->network_extension());\n      File packet(FilePath(a()->network_directory(), fn));\n      packet.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite);\n      packet.Seek(0L, File::Whence::end);\n      packet.Write(&nh, sizeof(net_header_rec));\n      packet.Write(b1.get(), nh.length);\n      packet.Close();\n    }\n  }\n  std::string logMessage = \"Mail sent to \";\n  if (data.system_number == 0) {\n    User userRecord;\n    a()->users()->readuser(&userRecord, data.user_number);\n    userRecord.email_waiting(userRecord.email_waiting() + 1);\n    a()->users()->writeuser(&userRecord, data.user_number);\n    if (const auto instance = user_online(data.user_number)) {\n      send_inst_sysstr(instance.value(), \"You just received email.\");\n    }\n    if (data.an) {\n      logMessage += a()->names()->UserName(data.user_number);\n      sysoplog(logMessage);\n    } else {\n      auto tempLogMessage = StrCat(logMessage, a()->names()->UserName(data.user_number));\n      sysoplog(tempLogMessage);\n      logMessage += \">UNKNOWN<\";\n    }\n    if (data.system_number == 0 \n        && a()->sess().effective_sl() >= a()->config()->validated_sl()\n        && userRecord.forward_systemnum() == 0\n        && !data.silent_mode) {\n      bout.outstr(\"|#5Attach a file to this message? \");\n      if (bin.yesno()) {\n        attach_file(1);\n      }\n    }\n  } else {\n    std::string logMessagePart;\n    if ((data.system_number == 1 && a()->current_net().type == network_type_t::internet) ||\n        data.system_number == INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n      logMessagePart = a()->net_email_name;\n    } else {\n      auto netname = (wwiv::stl::ssize(a()->nets()) > 1) ? a()->network_name() : \"\";\n      logMessagePart = username_system_net_as_string(data.user_number, a()->net_email_name,\n                                                     data.system_number, netname);\n    }\n    sysoplog(fmt::format(\"{}{}\", logMessage, logMessagePart));\n  }\n\n  a()->status_manager()->Run([&](Status& status) {\n    if (data.user_number == 1 && data.system_number == 0) {\n      status.increment_feedback_today();\n      a()->user()->feedback_sent(a()->user()->feedback_sent() + 1);\n      a()->user()->feedback_today(a()->user()->feedback_today() + 1);\n    } else {\n      status.increment_email_today();\n      a()->user()->email_today(a()->user()->email_today() + 1);\n      if (data.system_number == 0) {\n        a()->user()->email_sent(a()->user()->email_sent() + 1);\n      } else {\n        a()->user()->email_net(a()->user()->email_net() + 1);\n      }\n    }\n  });\n  if (!data.silent_mode) {\n    bout.ansic(3);\n    bout.outstr(logMessage);\n    bout.nl();\n  }\n}\n\nbool ok_to_mail(uint16_t user_number, uint16_t system_number, bool bForceit) {\n  if (system_number != 0 && a()->current_net().sysnum == 0) {\n    bout.outstr(\"\\r\\nSorry, this system is not a part of WWIVnet.\\r\\n\\n\");\n    return false;\n  }\n  if (system_number == 0) {\n    if (user_number == 0) {\n      return false;\n    }\n    User userRecord;\n    a()->users()->readuser(&userRecord, user_number);\n    if ((userRecord.sl() == 255 &&\n         userRecord.email_waiting() >\n             (a()->config()->max_waiting() * 5)) ||\n        (userRecord.sl() != 255 &&\n         userRecord.email_waiting() > a()->config()->max_waiting()) ||\n        userRecord.email_waiting() > 200) {\n      if (!bForceit) {\n        bout.outstr(\"\\r\\nMailbox full.\\r\\n\");\n        return false;\n      }\n    }\n    if (userRecord.deleted()) {\n      bout.outstr(\"\\r\\nDeleted user.\\r\\n\\n\");\n      return false;\n    }\n  } else {\n    if (!valid_system(system_number)) {\n      bout.outstr(\"\\r\\nUnknown system number.\\r\\n\\n\");\n      return false;\n    }\n    if (a()->user()->restrict_net()) {\n      bout.outstr(\"\\r\\nYou can't send mail off the system.\\r\\n\");\n      return false;\n    }\n  }\n  if (!bForceit) {\n    if (((user_number == 1 && system_number == 0 &&\n          (a()->user()->feedback_today() >= 10)) ||\n         ((user_number != 1 || system_number != 0) &&\n          (a()->user()->email_today() >= a()->config()->sl(a()->sess().effective_sl()).emails)))\n        && !cs()) {\n      bout.outstr(\"\\r\\nToo much mail sent today.\\r\\n\\n\");\n      return false;\n    }\n    if (a()->user()->restrict_email() && user_number != 1) {\n      bout.outstr(\"\\r\\nYou can't send mail.\\r\\n\\n\");\n      return false;\n    }\n  }\n  return true;\n}\n\nvoid email(const std::string& title, uint16_t user_number, uint16_t system_number, bool forceit, int anony, bool bAllowFSED) {\n  auto nNumUsers = 0;\n  messagerec msg{};\n  std::string destination;\n  struct {\n    uint16_t user_number;\n    uint16_t system_number;\n    int net_num;\n    char net_name[20], net_email_name[40];\n  } carbon_copy[20];\n\n  auto cc = false, bcc = false;\n\n  if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n    bout.outstr(\"\\r\\nSorry, not enough disk space left.\\r\\n\\n\");\n    return;\n  }\n  bout.nl();\n  if (ForwardMessage(&user_number, &system_number)) {\n    if (system_number == INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n      destination = read_inet_addr(user_number);\n    }\n    bout.outstr(\"\\r\\nMail Forwarded.\\r\\n\\n\");\n    if (user_number == 0 && system_number == 0) {\n      bout.outstr(\"Forwarded to unknown user.\\r\\n\");\n      return;\n    }\n  }\n  if (!user_number && !system_number) {\n    return;\n  }\n  if (!ok_to_mail(user_number, system_number, forceit)) {\n    return;\n  }\n  std::string destination_bbs_name;\n  std::optional<net_system_list_rec> csne;\n  if (system_number) {\n    csne = next_system(system_number);\n    destination_bbs_name = csne->name;\n  }\n  bool an = true;\n  if (a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_email_anony) {\n    an = true;\n  } else if (anony & (anony_sender | anony_sender_da | anony_sender_pp)) {\n    an = false;\n  } else {\n    an = true;\n  }\n  if (system_number == 0) {\n    set_net_num(0);\n    if (an) {\n      destination = a()->names()->UserName(user_number);\n    } else {\n      destination = \">UNKNOWN<\";\n    }\n  } else {\n    if (a()->current_net().type == network_type_t::internet) {\n      destination = a()->net_email_name;\n    } else if (a()->current_net().type == network_type_t::ftn) {\n      destination = a()->net_email_name;\n      try {\n        auto addr = fido::get_address_from_single_line(destination);\n        if (!addr.has_value()) {\n          bout.print(\"Bad FTN Address: {}\", destination);\n          return;\n        }\n        if (auto & net = a()->mutable_current_net(); net.try_load_nodelist()) {\n          if (auto & nl = *net.nodelist; nl.contains(addr.value())) {\n            const auto& e = nl.entry(addr.value());\n            destination_bbs_name = e.name();\n          } else {\n            bout.print(\"|#6Address '|#2{}|#6' does not existing in the nodelist.\\r\\n\", addr->as_string());\n            bout.nl(2);\n            bout.outstr(\"|#5Are you sure you want to send to this address? \");\n            if (!bin.noyes()) {\n              return;\n            }\n          }\n        } else {\n          bout.pl(\"Unable to validate FTN address against nodelist.\");\n          sysoplog(\"WARNING: Unable to validate FTN address against nodelist.\");\n          sysoplog(fmt::format(\"Nodelist base: {} does not exist in netdir: {}\",\n                                    net.fido.nodelist_base, net.dir.string()));\n        }\n      } catch (const fido::bad_fidonet_address& e) {\n        bout.print(\"Bad FTN Address: {}; error: {}\", destination, e.what());\n        return;\n      }\n    } else {\n      std::string netname = (wwiv::stl::ssize(a()->nets()) > 1) ? a()->network_name() : \"\";\n      destination =\n          username_system_net_as_string(user_number, a()->net_email_name, system_number, netname);\n    }\n  }\n  bout.print(\"|#9E-mailing:      |#2{}\", destination);\n  if (system_number != 0) {\n    bout.print(\" |#9(|#1{}|#9)\", a()->current_net().name); \n  }\n  bout.nl();\n  uint8_t i = (a()->config()->sl(a()->sess().effective_sl()).ability & ability_email_anony) ? anony_enable_anony : anony_none;\n\n  if (anony & (anony_receiver_pp | anony_receiver_da)) {\n    i = anony_enable_dear_abby;\n  }\n  if (anony & anony_receiver) {\n    i = anony_enable_anony;\n  }\n  if (i == anony_enable_anony && a()->user()->restrict_anony()) {\n    i = 0;\n  }\n  if (system_number != 0) {\n    i = 0;\n    anony = 0;\n    bout.print(\"|#9Name of system: |#2{}\\r\\n\", destination_bbs_name);\n    if (a()->current_net().type == network_type_t::wwivnet) {\n      bout.nl();\n      CHECK(csne.has_value());\n      bout.print(\"|#9Number of hops: |#2{}\\r\\n\", csne->numhops);\n      bout.nl();\n    }\n  }\n  write_inst(INST_LOC_EMAIL, (system_number == 0) ? user_number : 0, INST_FLAGS_NONE);\n\n  msg.storage_type = EMAIL_STORAGE;\n  MessageEditorData data(a()->user()->name_and_number());\n  data.title = title;\n  data.need_title = true;\n  data.fsed_flags = (bAllowFSED) ? FsedFlags::FSED : FsedFlags::NOFSED;\n  data.anonymous_flag = i;\n  data.aux = \"email\";\n  data.to_name = destination;\n  data.sub_name = \"WWIV E-mail\";\n  data.msged_flags = MSGED_FLAG_NONE;\n  if (!inmsg(data)) {\n    return;\n  }\n  savefile(data.text, &msg, data.aux);\n  i = data.anonymous_flag;\n  if (anony & anony_sender) {\n    i |= anony_receiver;\n  }\n  if (anony & anony_sender_da) {\n    i |= anony_receiver_da;\n  }\n  if (anony & anony_sender_pp) {\n    i |= anony_receiver_pp;\n  }\n\n  if (a()->IsCarbonCopyEnabled()) {\n    bout.nl();\n    bout.outstr(\"|#9Copy this mail to others? \");\n    nNumUsers = 0;\n    if (bin.yesno()) {\n      bool done = false;\n      carbon_copy[nNumUsers].user_number = user_number;\n      carbon_copy[nNumUsers].system_number = system_number;\n      to_char_array(carbon_copy[nNumUsers].net_name, a()->network_name());\n      to_char_array(carbon_copy[nNumUsers].net_email_name, a()->net_email_name);\n      carbon_copy[nNumUsers].net_num = a()->net_num();\n      nNumUsers++;\n      do {\n        bout.outstr(\"|#9Enter Address (blank to end) : \");\n        std::string emailAddress = bin.input(75);\n        if (emailAddress.empty()) {\n          done = true;\n          break;\n        }\n        if (auto [tu, ts] = parse_email_info(emailAddress); tu || ts) {\n          carbon_copy[nNumUsers].user_number = tu;\n          carbon_copy[nNumUsers].system_number = ts;\n          to_char_array(carbon_copy[nNumUsers].net_name, a()->network_name());\n          to_char_array(carbon_copy[nNumUsers].net_email_name, a()->net_email_name);\n          carbon_copy[nNumUsers].net_num = a()->net_num();\n          nNumUsers++;\n          cc = true;\n        }\n        if (nNumUsers == 20) {\n          bout.outstr(\"|#6Maximum number of addresses reached!\");\n          done = true;\n        }\n      } while (!done);\n      if (cc) {\n        bout.outstr(\"|#9Show Recipients in message? \");\n        bcc = !bin.yesno();\n      }\n    }\n  }\n\n  if (cc && !bcc) {\n    int listed = 0;\n    std::string s1 = \"\\003\"\"6Carbon Copy: \\003\"\"1\";\n    lineadd(&msg, \"\\003\"\"7----\", \"email\");\n    for (int j = 0; j < nNumUsers; j++) {\n      if (carbon_copy[j].system_number == 0) {\n        set_net_num(0);\n        destination = a()->names()->UserName(carbon_copy[j].user_number);\n      } else {\n        if (carbon_copy[j].system_number == 1 &&\n            carbon_copy[j].user_number == 0 &&\n            a()->nets()[carbon_copy[j].net_num].type == network_type_t::internet) {\n          destination = carbon_copy[j].net_email_name;\n        } else {\n          set_net_num(carbon_copy[j].net_num);\n          if (wwiv::stl::ssize(a()->nets()) > 1) {\n            if (carbon_copy[j].user_number == 0) {\n              destination = fmt::sprintf(\"%s@%u.%s\", carbon_copy[j].net_email_name, carbon_copy[j].system_number,\n                      carbon_copy[j].net_name);\n            } else {\n              destination = fmt::sprintf(\"#%u@%u.%s\", carbon_copy[j].user_number, carbon_copy[j].system_number, carbon_copy[j].net_name);\n            }\n          } else {\n            if (carbon_copy[j].user_number == 0) {\n              destination = fmt::sprintf(\"%s@%u\", carbon_copy[j].net_email_name, carbon_copy[j].system_number);\n            } else {\n              destination = fmt::sprintf(\"#%u@%u\", carbon_copy[j].user_number, carbon_copy[j].system_number);\n            }\n          }\n        }\n      }\n      if (j == 0) {\n        s1 = StrCat(\"\\003\"\"6Original To: \\003\"\"1\", destination);\n        lineadd(&msg, s1, \"email\");\n        s1 = \"\\003\"\"6Carbon Copy: \\003\"\"1\";\n      } else {\n        if (s1.length() + destination.length() < 77) {\n          s1 += destination;\n          if (j + 1 < nNumUsers) {\n            s1 += \", \";\n          } else {\n            s1 += \"  \";\n          }\n          listed = 0;\n        } else {\n          lineadd(&msg, s1, \"email\");\n          s1 += \"\\003\"\"1             \";\n          j--;\n          listed = 1;\n        }\n      }\n    }\n    if (!listed) {\n      lineadd(&msg, s1, \"email\");\n    }\n  }\n\n  EmailData email(data);\n  email.msg = &msg;\n  email.anony = i;\n  email.an = an;\n  email.set_from_user(a()->sess().user_num());\n  email.from_system = a()->current_net().sysnum;\n  email.forwarded_code = 0;\n\n  if (!cc) {\n    email.system_number = system_number;\n    email.user_number = user_number;\n    email.from_network_number = a()->net_num();\n    sendout_email(email);\n    return;\n  }\n  for (int counter = 0; counter < nNumUsers; counter++) {\n    set_net_num(carbon_copy[counter].net_num);\n    email.user_number = carbon_copy[counter].user_number;\n    email.system_number = carbon_copy[counter].system_number;\n    email.from_network_number = carbon_copy[counter].net_num;\n    sendout_email(email);\n  }\n}\n\nvoid imail(const std::string& title, uint16_t user_number, uint16_t system_number) {\n  bool fwdm = false;\n\n  if (ForwardMessage(&user_number, &system_number)) {\n    bout.outstr(\"Mail forwarded.\\r\\n\");\n    fwdm = true;\n  }\n\n  if (!user_number && !system_number) {\n    return;\n  }\n\n  std::string internet_email_address;\n  if (fwdm) {\n    internet_email_address = read_inet_addr(user_number);\n  }\n  \n  bool doit = true;\n  if (system_number == 0) {\n    if (auto user = a()->users()->readuser(user_number, UserManager::mask::non_deleted)) {\n      bout.print(\"|#5E-mail {}? \", user->name_and_number());\n      if (!bin.yesno()) {\n        doit = false;\n      }\n    } else {\n      doit = false;\n    }\n  } else {\n    if (fwdm) {\n      bout.print(\"|#5E-mail {}? \", internet_email_address);\n    } else {\n      bout.print(\"|#5E-mail User {} @{}? \", user_number, system_number);\n    }\n    if (!bin.yesno()) {\n      doit = false;\n    }\n  }\n  clear_quotes(a()->sess());\n  if (doit) {\n    email(title, user_number, system_number, false, 0);\n  }\n}\n\nvoid delmail(File& f, size_t loc) {\n  mailrec m{};\n  User user;\n\n  f.Seek(loc * sizeof(mailrec), File::Whence::begin);\n  f.Read(&m, sizeof(mailrec));\n\n  if (m.touser == 0 && m.tosys == 0) {\n    return;\n  }\n\n  bool rm = true;\n  if (m.status & status_multimail) {\n    const auto num_records = f.length() / sizeof(mailrec);\n    auto otf = false;\n    for (size_t i = 0; i < num_records; i++) {\n      if (i != loc) {\n        mailrec m1{};\n        f.Seek(i * sizeof(mailrec), File::Whence::begin);\n        f.Read(&m1, sizeof(mailrec));\n        if (m.msg.stored_as == m1.msg.stored_as && \n            m.msg.storage_type == m1.msg.storage_type &&\n            m1.daten != 0xffffffff) {\n          otf = true;\n        }\n      }\n    }\n    if (otf) {\n      rm = false;\n    }\n  }\n  if (rm) {\n    remove_link(&m.msg, \"email\");\n  }\n\n  if (m.tosys == 0) {\n    a()->users()->readuser(&user, m.touser);\n    if (user.email_waiting()) {\n      user.email_waiting(user.email_waiting() - 1);\n      a()->users()->writeuser(&user, m.touser);\n    }\n  }\n  f.Seek(loc * sizeof(mailrec), File::Whence::begin);\n  m.touser = 0;\n  m.tosys = 0;\n  m.daten = 0xffffffff;\n  m.msg.storage_type = 0;\n  m.msg.stored_as = 0xffffffff;\n  f.Write(&m, sizeof(mailrec));\n}\n\nstd::string fixup_user_entered_email(const std::string& user_input) {\n  if (user_input.empty()) {\n    return{};\n  }\n  if (const auto at_pos = user_input.find('@'); at_pos != std::string::npos &&\n                                                at_pos < user_input.size() - 1 &&\n                                                isalpha(user_input.at(at_pos + 1))) {\n    if (!contains(user_input, INTERNET_EMAIL_FAKE_OUTBOUND_ADDRESS)) {\n      return StrCat(ToStringLowerCase(user_input), \" \", INTERNET_EMAIL_FAKE_OUTBOUND_ADDRESS);\n    }\n    return user_input;\n  }\n\n  const auto first = user_input.find_last_of('(');\n  const auto last = user_input.find_last_of(')');\n  if (first != std::string::npos && last != std::string::npos) {\n    // This is where we'd check for (NNNN) and add in the @NNN for the FTN networks.\n    if (last > first) {\n      const auto inner = user_input.substr(first + 1, last - first - 1);\n      if (wwiv::stl::contains(inner, '/') && !contains(user_input, FTN_FAKE_OUTBOUND_ADDRESS)) {\n        // At least need a FTN address.\n        return StrCat(user_input, \" \", FTN_FAKE_OUTBOUND_ADDRESS);\n        //bout.print(\"\\r\\n|#9Sending to FTN Address: |#2{}\\r\\n\", inner);\n      }\n    }\n  }\n  return user_input;\n}\n"
  },
  {
    "path": "bbs/email.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MSGBASE_H\n#define INCLUDED_BBS_MSGBASE_H\n\n#include <memory>\n#include <string>\n#include \"common/message_editor_data.h\"\n#include \"core/file.h\"\n#include \"sdk/vardec.h\"\n\nclass EmailData {\npublic:\n  explicit EmailData(const wwiv::common::MessageEditorData& msged)\n      : title(msged.title), silent_mode(msged.silent_mode) {}\n  EmailData() = default;\n  ~EmailData() = default;\n\n  std::string title;\n  messagerec * msg{nullptr};\n  uint8_t anony{0};\n  uint16_t user_number{0};\n  uint16_t system_number{0};\n  bool an{false};\n  uint16_t from_user{0};\n  uint16_t from_system{0};\n  int forwarded_code{0};\n  int from_network_number{0};\n\n  void set_from_user(int u) { from_user = static_cast<uint16_t>(u); }\n  void set_from_system(int u) { from_system = static_cast<uint16_t>(u); }\n  void set_user_number(int u) { user_number = static_cast<uint16_t>(u); }\n\n  bool silent_mode;     // Used for ASV and new emails.  No questions, etc.\n};\n\nbool ForwardMessage(uint16_t* user_number, uint16_t* system_number);\n[[nodiscard]] std::unique_ptr<wwiv::core::File> OpenEmailFile(bool allow_write);\nvoid sendout_email(::EmailData& data);\n[[nodiscard]] bool ok_to_mail(uint16_t user_number, uint16_t system_number, bool force_it);\nvoid email(const std::string& title, uint16_t user_number, uint16_t system_number, bool force_it,\n           int anony, bool allow_fsed = true);\nvoid imail(const std::string& title, uint16_t user_number, uint16_t system_number);\nvoid delmail(wwiv::core::File& pFile, size_t loc);\n\n[[nodiscard]] std::string fixup_user_entered_email(const std::string& user_input);\n\n#endif\n"
  },
  {
    "path": "bbs/email_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/email.h\"\n\n\nTEST(EmailTest, Smoke) {\n  EXPECT_EQ(\"1\", fixup_user_entered_email(\"1\"));\n  EXPECT_EQ(\"1@1\", fixup_user_entered_email(\"1@1\"));\n  EXPECT_EQ(\"1@1.WWIVNET\", fixup_user_entered_email(\"1@1.WWIVNET\"));\n\n  EXPECT_EQ(\"rushfan@wwiv.us @32767\", fixup_user_entered_email(\"rushfan@wwiv.us @32767\"));\n  EXPECT_EQ(\"rushfan@wwiv.us @32767\", fixup_user_entered_email(\"rushfan@wwiv.us\"));\n  EXPECT_EQ(\"rushfan (1:1/100) @32765\", fixup_user_entered_email(\"rushfan (1:1/100)\"));\n  EXPECT_EQ(\"rushfan (1:1/100) @32765\", fixup_user_entered_email(\"rushfan (1:1/100) @32765\"));\n}\n"
  },
  {
    "path": "bbs/exec.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_EXEC_H\n#define INCLUDED_BBS_EXEC_H\n\n#include \"bbs/stuffin.h\"\n#include <string>\n\n// Used to execute a command, called by ExecuteCommandline and the WFC\nint exec_cmdline(wwiv::bbs::CommandLine& sc, int flags);\n\n#endif\n"
  },
  {
    "path": "bbs/exec_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/exec.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/stuffin.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/log.h\"\n#include \"fmt/format.h\"\n\n#include <cctype>\n#include <process.h>\n#include <string>\n\n\nint exec_cmdline(wwiv::bbs::CommandLine& cmdline, int flags) {\n  if (a()->sess().ok_modem_stuff() && a()->sess().using_modem()) {\n    VLOG(1) <<\"Closing remote IO\";\n    bout.remoteIO()->close(true);\n  }\n\n  const auto cmd = cmdline.cmdline();\n  auto res = system(cmd.c_str());\n\n  if (a()->sess().ok_modem_stuff() && a()->sess().using_modem()) {\n    VLOG(1) << \"Reopening comm (on createprocess error)\";\n    bout.remoteIO()->open();\n  }\n  if (res != 0) {\n    LOG(ERROR) << \"error on system: \" << res << \"; errno: \" << errno;\n  }\n  return res;\n}\n\n"
  },
  {
    "path": "bbs/exec_socket.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/exec_socket.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <chrono>\n#include <string>\n\n#ifdef _WIN32\n#include <winsock2.h>\n#include <WS2tcpip.h>\n#include <afunix.h>\n#include <MSWSock.h>\n#elif defined(__unix__)\n#include <fcntl.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <sys/un.h>\n#include <sys/wait.h>\n#endif\n\nnamespace wwiv::bbs {\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nstatic bool SetBlockingMode(SOCKET sock, bool blocking_mode) {\n  if (sock == INVALID_SOCKET) {\n    return false;\n  }\n\n#ifdef _WIN32\n  u_long nonblocking = blocking_mode ? 0 : 1;\n  return ioctlsocket(sock, FIONBIO, &nonblocking) == NO_ERROR;\n#else // _WIN32\n  int flags = fcntl(sock, F_GETFL, 0 /* ignored */);\n  return fcntl(sock, F_SETFL, flags | O_NONBLOCK) != -1;\n#endif // _WIN32\n}\n\nExecSocket::ExecSocket(const std::filesystem::path& dir, uint16_t port, exec_socket_type_t type)\n    : dir_(dir), type_(type) {\n  stop_.store(false);\n\n  const int af = (type == exec_socket_type_t::unix_domain) ? AF_UNIX : AF_INET;\n  server_socket_ = socket(af, SOCK_STREAM, 0);\n  if (server_socket_ == -1) {\n    LOG(ERROR) << \"socket error\";\n    server_socket_ = INVALID_SOCKET;\n    return;\n  }\n\n  if (type == exec_socket_type_t::unix_domain) {\n    struct sockaddr_un addr {};\n    memset(&addr, 0, sizeof(addr));\n    addr.sun_family = AF_UNIX;\n    auto p = path();\n    File::Remove(p);\n    to_char_array(addr.sun_path, p.string());\n    if (bind(server_socket_, (struct sockaddr*)&addr, sizeof(addr)) == -1) {\n      LOG(ERROR) << \"bind error\";\n      server_socket_ = INVALID_SOCKET;\n      return;\n    }\n\n  } else {\n    // port\n    struct sockaddr_in my_addr {};\n    memset(&my_addr, 0, sizeof(sockaddr_in));\n\n    int optval = 1;\n    if (setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&optval),\n                   sizeof(optval)) == -1) {\n      LOG(ERROR) << \"Unable to create socket [SO_REUSEADDR]\";\n      server_socket_ = INVALID_SOCKET;\n      return;\n    }\n    if (setsockopt(server_socket_, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<char*>(&optval),\n                   sizeof(optval)) == -1) {\n      LOG(ERROR) << \"Unable to create socket [SO_KEEPALIVE]\";\n      server_socket_ = INVALID_SOCKET;\n      return;\n    }\n    // Try to set nodelay.\n    setsockopt(server_socket_, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&optval),\n               sizeof(optval));\n\n    my_addr.sin_family = AF_INET;\n    my_addr.sin_port = htons(port);\n    memset(&(my_addr.sin_zero), 0, 8);\n    my_addr.sin_addr.s_addr = INADDR_ANY;\n\n    if (bind(server_socket_, reinterpret_cast<sockaddr*>(&my_addr), sizeof(my_addr)) == -1) {\n      // throw socket_error(msg);\n      LOG(ERROR) << \"bind error\";\n      server_socket_ = INVALID_SOCKET;\n      return;\n    }\n\n    struct sockaddr_in sin_port;\n    socklen_t len = sizeof(sockaddr_in);\n    if (getsockname(server_socket_, (struct sockaddr*)&sin_port, &len) == -1) {\n      LOG(ERROR) << \"getsockname error\";\n      return;\n    }\n    port_ = ntohs(sin_port.sin_port);\n    VLOG(1) << \"Bound to port: \" << port_;\n  }\n\n  if (listen(server_socket_, 1) == -1) {\n    LOG(ERROR) << \"listen error\";\n    server_socket_ = INVALID_SOCKET;\n    return;\n  }\n}\n\nExecSocket::~ExecSocket() {\n  if (server_socket_ != -1) {\n    closesocket(server_socket_);\n  }\n}\n\n\nstd::optional<int> ExecSocket::accept() {\n  VLOG(1) << \"ExecSocket::accept()\";\n  struct timeval tv;\n  fd_set rfds;\n  FD_ZERO(&rfds);\n  FD_SET(server_socket_, &rfds);\n\n  tv.tv_sec = 20; // 10 seconds\n  tv.tv_usec = 0;\n  \n  if (const auto res = select(server_socket_ + 1, &rfds, nullptr, nullptr, &tv); res > 0) {\n    if (client_socket_ = ::accept(server_socket_, nullptr, nullptr); client_socket_ > 0) {\n      SetBlockingMode(client_socket_, false);\n      VLOG(1) << \"Accepted: \";\n      return {client_socket_};\n    }\n  }\n  LOG(ERROR) << \"accept error\";\n  return std::nullopt;\n}\n\n[[nodiscard]] inline std::filesystem::path ExecSocket::path() const {\n  return wwiv::core::FilePath(dir_, \"wwivexec.sock\");\n}\n\nstd::string ExecSocket::z() const { \n  if (type_ == exec_socket_type_t::port) {\n    return fmt::format(\"{}\", port_);\n  }\n  return path().string();\n}\n\n// static \nbool ExecSocket::process_still_active(EXEC_SOCKET_HANDLE h) {\n#ifdef _WIN32\n  DWORD dwExitCode;\n  if (GetExitCodeProcess(h, &dwExitCode) && dwExitCode != STILL_ACTIVE) {\n    VLOG(1) << \"Process exited. Ending pump_socket\";\n    return false;\n  }\n  return true;\n#elif defined(__unix__)\n  int status_code = 0;\n  pid_t wp = waitpid(h, &status_code, WNOHANG);\n  if (wp == -1 || wp > 0) {\n    // -1 means error and >0 is the pid\n    VLOG(2) << \"waitpid returned: \" << wp << \"; errno: \" << errno;\n    if (WIFEXITED(status_code)) {\n      VLOG(1) << \"child exited with code: \" << WEXITSTATUS(status_code);\n      return false;\n    }\n    if (WIFSIGNALED(status_code)) {\n      VLOG(1) << \"child caught signal: \" << WTERMSIG(status_code);\n    } else {\n      LOG(INFO) << \"Raw status_code: \" << status_code;\n    }\n    LOG(INFO) << \"core dump? : \" << WCOREDUMP(status_code);\n  }\n  return true;\n#endif\n}\n\npump_socket_result_t ExecSocket::pump_socket(EXEC_SOCKET_HANDLE hProcess, SOCKET sock, wwiv::common::RemoteIO& io) {\n  static constexpr int check_process_every = 10;\n  char buf[1024];\n  int count = 0;\n  while (!stop_.load()) {\n    if (auto num_read = recv(sock, buf, sizeof(buf), 0); num_read > 0) {\n      io.write(buf, num_read);\n    } else if (num_read == 0) {\n      VLOG(1) << \"Exiting pump_socket: recv.\";\n      return pump_socket_result_t::socket_error;\n    }\n\n    if (!io.connected()) {\n      VLOG(1) << \"Exiting pump_socket: Caller Hung up.\";\n      return pump_socket_result_t::socket_error;\n    }\n\n    if (io.incoming()) {\n      if (auto num_read = io.read(buf, sizeof(buf)); num_read > 0) {\n        if (send(sock, buf, num_read, 0) == 0) {\n          // TODO(rushfan): handle nonblocking error?\n          VLOG(1) << \"Exiting pump_socket; Write to socket failed\";\n          return pump_socket_result_t::socket_error;\n        }\n      }\n    }\n\n    if (++count >= check_process_every) {\n      count = 0;\n      if (!process_still_active(hProcess)) {\n        return pump_socket_result_t::process_exit;\n      }\n    }\n    wwiv::os::sleep_for(std::chrono::milliseconds(100));\n  }\n  return pump_socket_result_t::process_exit;\n}\n\nbool ExecSocket::stop_pump() { \n  stop_.store(true); \n  return true;\n}\n\n} // namespace wwiv::bbs\n"
  },
  {
    "path": "bbs/exec_socket.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_EXEC_SOCKET_H\n#define INCLUDED_BBS_EXEC_SOCKET_H\n\n#include <atomic>\n#include <filesystem>\n#include <optional>\n#include <string>\n#include \"common/remote_io.h\"\n#include \"core/net.h\"\n\n#if defined(__unix__)\n#include <sys/types.h>\n#endif\n\nnamespace wwiv::bbs {\n\nenum class exec_socket_type_t { port, unix_domain };\n\nenum class pump_socket_result_t { process_exit, socket_error };\n\n#ifdef _WIN32\ntypedef void* EXEC_SOCKET_HANDLE;\n#else \ntypedef pid_t EXEC_SOCKET_HANDLE;\n#endif\n\nclass ExecSocket final {\npublic:\n  ExecSocket(const std::filesystem::path& dir)\n      : ExecSocket(dir, 0, exec_socket_type_t::unix_domain) {}\n  ExecSocket(uint16_t port) : ExecSocket(\"\", port, exec_socket_type_t::port) {}\n  ~ExecSocket();\n  std::optional<int> accept();\n\n  [[nodiscard]] std::filesystem::path path() const;\n  [[nodiscard]] int port() const noexcept { return port_; }\n  [[nodiscard]] bool listening() const noexcept { return server_socket_ != -1; }\n\n  /** returns the value to use for %Z, which is either the UNIX path or the socket hostname:port */\n  [[nodiscard]] std::string z() const;\n\n  /** Handles pumping data between socket and remote IO */\n  pump_socket_result_t pump_socket(EXEC_SOCKET_HANDLE hProcess, SOCKET sock, wwiv::common::RemoteIO& io);\n\n  bool stop_pump();\n  static bool process_still_active(EXEC_SOCKET_HANDLE h);\n\nprivate:\n  ExecSocket(const std::filesystem::path& dir, uint16_t port, exec_socket_type_t type);\n  const std::filesystem::path dir_;\n  exec_socket_type_t type_;\n  std::filesystem::path unix_path_;\n  SOCKET server_socket_{INVALID_SOCKET};\n  SOCKET client_socket_{INVALID_SOCKET};\n  int port_{0};\n  std::atomic<bool> stop_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/exec_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                                WWIV Version 5                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/exec.h\"\n#include <sys/wait.h>\n\n#define TTYDEFCHARS\n#ifndef _POSIX_VDISABLE\n#  define _POSIX_VDISABLE 0\n#endif\n#include <termios.h>\n#include <sys/ttydefaults.h>\n#undef TTYDEFCHARS\n\n#include <unistd.h>\n\n#if defined(__APPLE__)\n#include <util.h>\n#elif defined(__GLIBC__)\n#include <pty.h>\n#else /* bsd without glibc */\n#include <libutil.h>\n#endif\n\n#include \"bbs/bbs.h\"\n#include \"bbs/exec_socket.h\"\n#include \"bbs/stuffin.h\"\n#include \"common/context.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"sdk/vardec.h\"\n\n#include <tuple>\n\nstatic const char SHELL[] = \"/bin/bash\";\n\nusing namespace wwiv::bbs;\n\n\nstatic int ReadWriteNonBinary(int sock, int pty_fd, fd_set& rfd) {\n  if (FD_ISSET(sock, &rfd)) {\n    char input{};\n    if (read(sock, &input, 1) == 0) { \n      return -1;\n    }\n    if (static_cast<uint8_t>(input) == 0xff) {\n      // IAC, skip over them so we ignore them for now\n      // This was causing the do suppress GA (255, 253, 3)\n      // to get interpreted as a SIGINT by dosemu on startup.\n      LOG(INFO) << \"IAC\";\n      if (read(sock, &input, 1) == 0) { \n        return -1;\n      }\n      if (read(sock, &input, 1) == 0) { \n        return -1;\n      }\n      return 0;\n    }\n    if (input == 3) {\n      VLOG(1) << \"control-c from user, skipping.\";\n      return 0;\n    }\n    VLOG(4) << \"Read from Socket: input: \" << input << \" [\" << static_cast<unsigned int>(input)\n\t    << \"]\";\n    write(pty_fd, &input, 1);\n    VLOG(4) << \"read from socket, write to term: '\" << input << \"'\";\n  }\n  if (FD_ISSET(pty_fd, &rfd)) {\n    char input{};\n    read(pty_fd, &input, 1);\n    if (input == '\\n') {\n      VLOG(1) << \"Performed LF -> CRLF translation.\";\n      write(sock, \"\\r\\n\", 2);\n    } else {\n      VLOG(4) << \"Read From Terminal: '\" << input << \"'; [\" << static_cast<unsigned>(input) << \"]\";\n      write(sock, &input, 1);\n    }\n  }\n  return 0;\n}\n\nstatic constexpr int READ_SIZE = 1024;\nstatic int ReadWriteBinary(int sock, int pty_fd, fd_set& rfd) {\n  VLOG(1) << \"ReadWriteBinary Loop: << sock: \" << sock\n\t    << \"; pty_fd: \" << pty_fd;\n  if (FD_ISSET(sock, &rfd)) {\n    char input[READ_SIZE + 10];\n    const int num_read = read(sock, &input, READ_SIZE);\n    if (num_read > 0) {\n      const auto w = write(pty_fd, &input, num_read);\n      VLOG(1) << \"wrote[pty_fd]: \" << num_read << \";w:\" << w;\n    } else {\n      VLOG(1) << \"num_read[sock] <= 0; \" << num_read;\n    }\n  }\n  if (FD_ISSET(pty_fd, &rfd)) {\n    char input[READ_SIZE + 10];\n    const int num_read = read(pty_fd, &input, READ_SIZE);\n    if (num_read > 0) {\n      const auto w = write(sock, &input, num_read);\n      VLOG(1) << \"wrote[sock]: \" << num_read << \";w:\" << w;\n    } else {\n      VLOG(1) << \"num_read[pty_fd] <= 0; \" << num_read;\n    }\n  }\n  return 0;\n}\n\nstatic void pump_stdio(int sock, int pty_fd, pid_t pid, bool binary) {\n  const auto max_fd = std::max<int>(sock, pty_fd) + 1;\n  for (;;) {\n    fd_set rfd;\n    FD_ZERO(&rfd);\n    if (pty_fd > -1) {\n      FD_SET(pty_fd, &rfd);\n    }\n    FD_SET(sock, &rfd);\n\n    struct timeval tv = {1, 0};\n    auto ret = select(max_fd, &rfd, nullptr, nullptr, &tv);\n    if (ret < 0) {\n      LOG(INFO) << \"select returned <0\";\n      break;\n    }\n    // N.B. This has been copied to ExecSocket::process_active\n    int status_code = 0;\n    pid_t wp = waitpid(pid, &status_code, WNOHANG);\n    if (wp == -1 || wp > 0) {\n      // -1 means error and >0 is the pid\n      VLOG(2) << \"waitpid returned: \" << wp << \"; errno: \" << errno;\n      if (WIFEXITED(status_code)) {\n        VLOG(1) << \"child exited with code: \" << WEXITSTATUS(status_code);\n        return;\n      }\n      if (WIFSIGNALED(status_code)) {\n        VLOG(1) << \"child caught signal: \" << WTERMSIG(status_code);\n      } else {\n        LOG(INFO) << \"Raw status_code: \" << status_code;\n      }\n      LOG(INFO) << \"core dump? : \" << WCOREDUMP(status_code);\n      return;\n    }\n\n    if (pty_fd != -1) {\n      // Only do this in STDIO mode.\n      if (binary) {\n        ReadWriteBinary(sock, pty_fd, rfd);\n      } else {\n        if (ReadWriteNonBinary(sock, pty_fd, rfd) == -1) {\n          close(pty_fd);\n          return;\n        }\n      }\n    }\n  }\n\n}\n\nstatic int wait_for_exit(pid_t pid) {\n  // Wait for child to exit.\n  for (;;) {\n    VLOG(1) << \"about to call waitpid at the end\";\n    // In the parent, wait for the child to terminate.\n    int status_code = 1;\n    if (waitpid(pid, &status_code, 0) == -1) {\n      if (errno != EINTR) {\n        return -1;\n      }\n    } else {\n      return status_code;\n    }\n  }\n  // Should never happen.\n  return -1;\n}\n\n/**\n * returns a tuple of (pid, pty).\n * if pid == -1, fork failed.\n * if pty == -1, there is no pty\n */\nstatic std::tuple<pid_t, int> UnixSpawn(const wwiv::bbs::CommandLine& cmdline, int flags, int sock) {\n  if (cmdline.empty()) {\n    std::make_tuple(-1, -1);\n  }\n  auto cmd = cmdline.cmdline();\n  LOG(INFO) << \"Exec: '\" << cmd << \"'\";\n\n  int pid = -1;\n  int pty_fd = -1;\n  if (flags & EFLAG_STDIO) {\n    LOG(INFO) << \"Exec using STDIO: '\" << cmd << \"' errno: \" << errno;\n    struct winsize ws {};\n    ws.ws_col = 80;\n    ws.ws_row = 25;\n    struct termios tio {};\n    tio.c_iflag = TTYDEF_IFLAG;\n    tio.c_oflag = TTYDEF_OFLAG;\n    tio.c_lflag = TTYDEF_LFLAG;\n    tio.c_cflag = TTYDEF_CFLAG;\n    memcpy(&tio.c_cc, ttydefchars, sizeof(tio.c_cc));\n    cfsetspeed(&tio, TTYDEF_SPEED);\n\n    pid = forkpty(&pty_fd, nullptr, &tio, &ws);\n  } else {\n    pid = fork();\n  }\n  if (pid == -1) {\n    auto e = errno;\n    LOG(ERROR) << \"Fork Failed: errno: '\" << e << \"'\";\n    // Fork failed.\n    return std::make_tuple(-1, -1);\n  }\n  if (pid == 0) {\n    // In the child\n    const char* argv[4] = {SHELL, \"-c\", cmd.c_str(), 0};\n    execv(SHELL, const_cast<char** const>(argv));\n    exit(127);\n  }\n\n  // In the parent now.\n  VLOG(1) << \"In parent, pid \" << pid << \"; errno: \" << errno;\n  return std::make_tuple(pid, pty_fd);\n}\n\nint exec_cmdline(wwiv::bbs::CommandLine& cmdline, int flags) {\n  bool need_reopen_io = false;\n  std::unique_ptr<wwiv::bbs::ExecSocket> exec_socket;\n  if (a()->sess().ok_modem_stuff()) {\n    if (flags & EFLAG_SYNC_FOSSIL) {\n      LOG(ERROR) << \"EFLAG_SYNC_FOSSIL is not supported on UNIX\";\n    }\n    if (flags & EFLAG_NETFOSS) {\n      LOG(ERROR) << \"EFLAG_SYNC_FOSSIL is not supported on UNIX\";\n    }\n    if (flags & EFLAG_COMIO) {\n      LOG(ERROR) << \"EFLAG_COMIO is not supported on UNIX\";\n    }\n    if (flags & EFLAG_STDIO) {\n      VLOG(2) << \"Temporarily pausing comm for spawn\";\n      need_reopen_io = true;\n      bout.remoteIO()->close(true);\n    } else if (flags & EFLAG_LISTEN_SOCK) {\n      exec_socket = std::make_unique<wwiv::bbs::ExecSocket>(0);\n      // Add %Z into the commandline.\n      if (exec_socket->listening()) {\n        cmdline.add('Z', exec_socket->z());\n        VLOG(1) << \"listening to socket: \" << exec_socket->z();\n      }\n\n    } else if (flags & EFLAG_UNIX_SOCK) {\n      exec_socket = std::make_unique<wwiv::bbs::ExecSocket>(a()->sess().dirs().scratch_directory());\n      // Add %Z into the commandline.\n      if (exec_socket->listening()) {\n        cmdline.add('Z', exec_socket->z());\n        VLOG(1) << \"listening to socket: \" << exec_socket->z();\n      }\n\n    } else {\n      VLOG(2) << \"Temporarily pausing comm for spawn\";\n      need_reopen_io = true;\n      bout.remoteIO()->close(true);\n    }\n  }\n\n  const auto sock = bout.remoteIO()->GetDoorHandle();\n  auto [pid, pty] = UnixSpawn(cmdline, flags, sock);\n  if (pid == -1) {\n    return 1;\n  }\n\n  if (flags & EFLAG_STDIO) {\n    pump_stdio(sock, pty, pid, (flags & EFLAG_BINARY));\n  } else if (exec_socket) {\n    if (const auto sock = exec_socket->accept()) {\n      DCHECK(bout.remoteIO());\n      if (exec_socket->pump_socket(pid, sock.value(), *bout.remoteIO()) !=\n          pump_socket_result_t::process_exit) {\n        // sockets closed but process still running.\n        VLOG(1) << \"Forcefully terminating pid: \" << pid;\n        kill(pid, SIGKILL);\n      }\n    } else {\n      // sockets closed but process still running.\n      VLOG(1) << \"Accept never happend; Forcefully terminating pid: \" << pid;\n      kill(pid, SIGKILL);\n    }\n  }\n\n  // Wait for child to exit.\n  const auto result = wait_for_exit(pid);\n\n  // reengage comm stuff\n  if (need_reopen_io) {\n    bout.remoteIO()->open();\n  }\n  return result;\n}\n"
  },
  {
    "path": "bbs/exec_win32.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/exec.h\"\n\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/exec_socket.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sysoplog.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include <algorithm>\n#include <atomic>\n#include <sstream>\n#include <string>\n\n#ifdef _WIN32\n#define NOCRYPT // Disable include of wincrypt.h\n#include <winsock2.h>\n#endif // _WIN32\n\nstatic FILE* hLogFile;\n\nconst int CONST_SBBSFOS_FOSSIL_MODE = 0;\nconst int CONST_SBBSFOS_DOSIN_MODE = 1;\nconst int CONST_SBBSFOS_DOSOUT_MODE = 2;\nconst int CONST_SBBSFOS_LOOPS_BEFORE_YIELD = 10;\nconst int CONST_SBBSFOS_BUFFER_SIZE = 5000;\nconst int CONST_SBBSFOS_BUFFER_PADDING = 1000; // padding in case of errors.\n\nconst DWORD SBBSEXEC_IOCTL_START = 0x8001;\nconst DWORD SBBSEXEC_IOCTL_COMPLETE = 0x8002;\nconst DWORD SBBSEXEC_IOCTL_READ = 0x8003;\nconst DWORD SBBSEXEC_IOCTL_WRITE = 0x8004;\nconst DWORD SBBSEXEC_IOCTL_DISCONNECT = 0x8005;\nconst DWORD SBBSEXEC_IOCTL_STOP = 0x8006;\nconst int CONST_NUM_LOOPS_BEFORE_EXIT_CHECK = 500;\ntypedef HANDLE(WINAPI* OPENVXDHANDLEFUNC)(HANDLE);\n\nusing namespace std::chrono_literals;\nusing namespace wwiv::bbs;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n// Helper functions\n\nstatic void LogToSync(const std::string& s) {\n  if (a()->IsExecLogSyncFoss()) {\n    fputs(s.c_str(), hLogFile);\n  }\n}\n\nstatic std::filesystem::path GetSyncFosTempFilePath() {\n  return FilePath(a()->sess().dirs().temp_directory(), \"WWIVSYNC.ENV\");\n}\n\nstatic std::filesystem::path GetDosXtrnPath() {\n  return FilePath(a()->bindir(), \"dosxtrn.exe\");\n}\n\nstatic std::string CreateSyncFosCommandLine(const std::string& tempFilePath, int nSyncMode) {\n  std::stringstream ss;\n  ss << GetDosXtrnPath().string() << \" \" << tempFilePath << \" \" << \"NT\" << \" \";\n  ss << a()->sess().instance_number() << \" \" << nSyncMode << \" \" << CONST_SBBSFOS_LOOPS_BEFORE_YIELD;\n  return ss.str();\n}\n\n// returns true if the file is deleted.\nstatic bool DeleteSyncTempFile() {\n  const auto fn = GetSyncFosTempFilePath();\n  if (File::Exists(fn)) {\n    File::Remove(fn);\n    return true;\n  }\n  return false;\n}\n\nstatic bool CreateSyncTempFile(std::string *out, const std::string& commandLine) {\n  out->assign(GetSyncFosTempFilePath().string());\n  DeleteSyncTempFile();\n\n  TextFile file(*out, \"wt\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n  file.Write(commandLine);\n  if (!file.Close()) {\n    return false;\n  }\n\n  return true;\n}\n\nbool DoSyncFosLoopNT(HANDLE hProcess, HANDLE hSyncHangupEvent, HANDLE hSyncReadSlot, int nSyncMode) {\n  LogToSync(\"Starting DoSyncFosLoopNT()\\r\\n\");\n  HANDLE hSyncWriteSlot = INVALID_HANDLE_VALUE;     // Mail Slot for writing\n\n  // Cleanup on all exit paths\n  auto at_exit = finally([&] {\n    if (hSyncHangupEvent != INVALID_HANDLE_VALUE) { \n      CloseHandle(hSyncHangupEvent);\n      hSyncHangupEvent = INVALID_HANDLE_VALUE;\n    }\n    if (hSyncReadSlot != INVALID_HANDLE_VALUE) { \n      CloseHandle(hSyncReadSlot); \n      hSyncReadSlot = INVALID_HANDLE_VALUE;\n    }\n    if (hSyncWriteSlot != INVALID_HANDLE_VALUE) { \n      CloseHandle(hSyncWriteSlot); \n      hSyncWriteSlot = INVALID_HANDLE_VALUE;\n    }\n  });\n\n  char szReadBuffer[ CONST_SBBSFOS_BUFFER_SIZE + CONST_SBBSFOS_BUFFER_PADDING ];\n  ::ZeroMemory(szReadBuffer, CONST_SBBSFOS_BUFFER_SIZE + CONST_SBBSFOS_BUFFER_PADDING);\n  szReadBuffer[ CONST_SBBSFOS_BUFFER_SIZE + 1 ] = '\\xFE';\n\n  auto counter = 0;\n  for (;;) {\n    counter++;\n    if (a()->sess().using_modem() && (!bout.remoteIO()->connected())) {\n      SetEvent(hSyncHangupEvent);\n      LogToSync(\"Setting Hangup Event and Sleeping\\r\\n\");\n      wwiv::os::sleep_for(1s);\n    }\n\n    if (counter > CONST_NUM_LOOPS_BEFORE_EXIT_CHECK) {\n      // Only check for exit when we've been idle\n      DWORD dwExitCode = 0;\n      if (GetExitCodeProcess(hProcess, &dwExitCode)) {\n        if (dwExitCode != STILL_ACTIVE) {\n          // process is done and so are we.\n          LogToSync(\"Process finished, exiting\\r\\n\");\n          return true;\n        }\n      }\n    }\n\n    if (bout.remoteIO()->incoming()) {\n      counter = 0;\n      // SYNCFOS_DEBUG_PUTS( \"Char available to send to the door\" );\n      const auto nNumReadFromComm = bout.remoteIO()->read(szReadBuffer, CONST_SBBSFOS_BUFFER_SIZE);\n\n      if (a()->IsExecLogSyncFoss()) {\n        // LogToSync(StrCat(\"Read [\", nNumReadFromComm, \"] from comm\\r\\n\"));\n        for (unsigned int n_lp = 0; n_lp < nNumReadFromComm; n_lp++) {\n          fprintf(hLogFile, \"[%u]\", static_cast<unsigned char>(szReadBuffer[n_lp]));\n        }\n        fprintf(hLogFile, \"   \");\n        for (unsigned int n_lp = 0; n_lp < nNumReadFromComm; n_lp++) {\n          fprintf(hLogFile, \"[%c]\", static_cast<unsigned char>(szReadBuffer[ n_lp ]));\n        }\n        fprintf(hLogFile, \"\\r\\n\");\n      }\n\n      if (hSyncWriteSlot == INVALID_HANDLE_VALUE) {\n        // Create Write handle.\n        wwiv::os::sleep_for(500ms);\n        auto write_slot_name = fmt::format(R\"(\\\\.\\mailslot\\sbbsexec\\wr{})\", a()->sess().instance_number());\n        LogToSync(StrCat(\"Creating Mail Slot: '\", write_slot_name, \"'\\r\\n\"));\n\n        hSyncWriteSlot = CreateFile(write_slot_name.c_str(),\n                                    GENERIC_WRITE,\n                                    FILE_SHARE_READ,\n                                    nullptr,\n                                    OPEN_EXISTING,\n                                    FILE_ATTRIBUTE_NORMAL,\n                                    static_cast<HANDLE>(nullptr));\n        if (hSyncWriteSlot == INVALID_HANDLE_VALUE) {\n          sysoplog(StrCat(\"!!! Unable to create mail slot for writing for SyncFoss External program: \", GetLastError()));\n          LogToSync(StrCat(\"!!! Unable to create mail slot for writing for SyncFoss External program: \", GetLastError()));\n          return false;\n        }\n        LogToSync(\"Created MailSlot\\r\\n\");\n      }\n\n      if (nNumReadFromComm == 3 && static_cast<uint8_t>(szReadBuffer[0]) == 0xff) {\n        // IAC, skip over them so we ignore them for now.\n        // We do this in exec_unix.cpp too.\n        LOG(INFO) << \"IAC\";\n      } else {\n        DWORD dwNumWrittenToSlot = 0;\n        WriteFile(hSyncWriteSlot, szReadBuffer, nNumReadFromComm, &dwNumWrittenToSlot, nullptr);\n        if (a()->IsExecLogSyncFoss()) {\n          LogToSync(StrCat(\"Wrote [\", dwNumWrittenToSlot, \"] to MailSlot\\r\\n\"));\n        }\n      }\n    }\n\n    int nBufferPtr      = 0;    // BufPtr\n    DWORD dwNextSize    = 0;    // InUsed\n    DWORD dwNumMessages = 0;    // TmpLong\n    DWORD dwReadTimeOut = 0;    // -------\n\n    if (GetMailslotInfo(hSyncReadSlot, nullptr, &dwNextSize, &dwNumMessages, &dwReadTimeOut)) {\n      if (dwNumMessages > 0) {\n        // Too verbose.\n        if (a()->IsExecLogSyncFoss()) {\n          LogToSync(StrCat(\"[\", dwNumMessages, \"/\", std::min<DWORD>(dwNumMessages,\n          CONST_SBBSFOS_BUFFER_SIZE - 1000), \"] slot messages\\r\\n\"));\n        }\n        dwNumMessages = std::min<DWORD>(dwNumMessages, CONST_SBBSFOS_BUFFER_SIZE - 1000);\n        dwNextSize = 0;\n\n        for (DWORD nSlotCounter = 0; nSlotCounter < dwNumMessages; nSlotCounter++) {\n          if (ReadFile(hSyncReadSlot,\n                       &szReadBuffer[ nBufferPtr ],\n                       CONST_SBBSFOS_BUFFER_SIZE - nBufferPtr,\n                       &dwNextSize,\n                       nullptr)) {\n            if (dwNextSize > 1) {\n              LogToSync(StrCat(\"[\", dwNextSize, \"] bytes read   \\r\\n\"));\n            }\n            if (dwNextSize == MAILSLOT_NO_MESSAGE) {\n              LogToSync(\"** MAILSLOT thinks it's empty!\\r\\n\");\n            } else {\n              nBufferPtr += dwNextSize;   // was just ++.. oops\n            }\n\n            if (nBufferPtr >= CONST_SBBSFOS_BUFFER_SIZE - 10) {\n              break;\n            }\n          }\n        }\n      } else {\n        wwiv::os::yield();\n      }\n\n      if (nBufferPtr > 0) {\n        counter = 0;\n        if (nSyncMode & CONST_SBBSFOS_DOSOUT_MODE) {\n          // For some reason this doesn't write twice locally, so it works pretty well.\n          szReadBuffer[nBufferPtr] = '\\0';\n          bout.outstr(szReadBuffer);\n\n          // ExpandWWIVHeartCodes( szReadBuffer );\n          // int nNumWritten = bout.remoteIO()->write( szReadBuffer, strlen( szReadBuffer )  );\n        } else {\n          const auto num_written = bout.remoteIO()->write(szReadBuffer, nBufferPtr);\n          if (a()->IsExecLogSyncFoss()) {\n            // Too verbose.\n            LogToSync(StrCat(\"Wrote [\", num_written, \"] bytes to comm.\\r\\n\"));\n          }\n        }\n      }\n      if (a()->IsExecLogSyncFoss()) {\n        if (szReadBuffer[CONST_SBBSFOS_BUFFER_SIZE + 1] != '\\xFE') {\n          LogToSync(\"!!!!!! MEMORY CORRUPTION ON szReadBuffer !!!!!!!!\\r\\n\\r\\n\\n\\n\");\n        }\n      }\n    }\n    if (counter > 0) {\n      wwiv::os::yield();\n    }\n  }\n}\n\nstatic bool SetupSyncFoss(DWORD& dwCreationFlags, HANDLE& hSyncHangupEvent, HANDLE& hSyncReadSlot) {\n  hSyncHangupEvent = INVALID_HANDLE_VALUE;\n  hSyncReadSlot = INVALID_HANDLE_VALUE;     // Mail Slot for reading\n\n  // Create each syncfoss window in it's own WOW VDM.\n  dwCreationFlags |= CREATE_SEPARATE_WOW_VDM;\n\n  // Create Hangup Event.\n  const auto event_name = fmt::format(\"sbbsexec_hungup{}\", a()->sess().instance_number());\n  hSyncHangupEvent = CreateEvent(nullptr, TRUE, FALSE, event_name.c_str());\n  if (hSyncHangupEvent == INVALID_HANDLE_VALUE) {\n    LogToSync(StrCat(\"!!! Unable to create Hangup Event for SyncFoss External program: \", GetLastError()));\n    sysoplog(StrCat(\"!!! Unable to create Hangup Event for SyncFoss External program: \", GetLastError()));\n    return false;\n  }\n\n  // Create Read Mail Slot\n  const auto readslot_name = fmt::format(R\"(\\\\.\\mailslot\\sbbsexec\\rd{})\", a()->sess().instance_number());\n  hSyncReadSlot = CreateMailslot(readslot_name.c_str(), CONST_SBBSFOS_BUFFER_SIZE, 0, nullptr);\n  if (hSyncReadSlot == INVALID_HANDLE_VALUE) {\n    LogToSync(StrCat(\"!!! Unable to create mail slot for reading for SyncFoss External program: \", GetLastError()));\n    sysoplog(StrCat(\"!!! Unable to create mail slot for reading for SyncFoss External program: \", GetLastError()));\n    CloseHandle(hSyncHangupEvent);\n    hSyncHangupEvent = INVALID_HANDLE_VALUE;\n    return false;\n  }\n  return true;\n}\n\n\n// last_error as a std::string.\nstatic std::string ErrorAsString(DWORD last_error) {\n  LPSTR messageBuffer{nullptr};\n  const auto size = FormatMessageA(\n      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n      nullptr, \n    last_error, \n    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \n    reinterpret_cast<LPSTR>(&messageBuffer), \n    0, \n    nullptr);\n\n  std::string message{messageBuffer, size};\n\n  // Free the buffer.\n  LocalFree(messageBuffer);\n  return fmt::format(\"({}): {}\", last_error, message);\n}\n//  Main code that launches external programs and handle sbbsexec support\n\nstatic int exec_cmdline_sync(wwiv::bbs::CommandLine& cmdline, int flags, int nSyncMode = 0) {\n  const auto saved_binary_mode = bout.remoteIO()->binary_mode();\n\n  STARTUPINFO si{};\n  PROCESS_INFORMATION pi{};\n\n  ZeroMemory(&si, sizeof(si));\n  si.cb = sizeof(STARTUPINFO);\n  ZeroMemory(&pi, sizeof(pi));\n\n  std::string syncFosTempFile;\n  const auto user_command_line = cmdline.cmdline();\n  if (!CreateSyncTempFile(&syncFosTempFile, user_command_line)) {\n    return -1;\n  }\n  auto working_cmdline = CreateSyncFosCommandLine(syncFosTempFile, nSyncMode);\n\n  const auto logfile_name = FilePath(a()->logdir(), \"wwivsync.log\");\n  hLogFile = fopen(logfile_name.string().c_str(), \"at\");\n  LogToSync(std::string(78, '='));\n  LogToSync(\"\\r\\n\\r\\n\");\n\n  VLOG(1) << \"exec_cmdline: working_commandline: \" << working_cmdline;\n\n  std::string title = (flags & EFLAG_NETPROG)\n                          ? \"NETWORK\"\n                          : fmt::format(\"{} in door on node {}\", a()->user()->GetName(),\n                                        a()->sess().instance_number());\n  si.lpTitle = &title[0];\n\n  auto hSyncHangupEvent = INVALID_HANDLE_VALUE; // NOLINT(readability-qualified-auto)\n  auto hSyncReadSlot = INVALID_HANDLE_VALUE;    // Mailslot for reading\n  DWORD dwCreationFlags = 0;\n  SetupSyncFoss(dwCreationFlags, hSyncHangupEvent, hSyncReadSlot);\n  wwiv::os::sleep_for(250ms);\n\n  const auto current_directory = File::current_directory().string();\n\n  // Need a non-const string for the commandline\n  char szTempWorkingCommandline[MAX_PATH + 1];\n  to_char_array(szTempWorkingCommandline, working_cmdline);\n  const auto bRetCP =\n      CreateProcess(nullptr, szTempWorkingCommandline, nullptr, nullptr, TRUE, dwCreationFlags,\n                    nullptr, // a()->xenviron not using nullptr causes things to not work.\n                    current_directory.c_str(), &si, &pi);\n\n  if (!bRetCP) {\n    const auto error_code = ::GetLastError();\n    const auto error_message = ErrorAsString(error_code);\n    LOG(ERROR) << \"CreateProcessFailed: error: \" << error_message;\n    sysoplog(fmt::format(\"!!! CreateProcess failed for command: [{}] with Error Message: {}\", working_cmdline, error_message));\n\n    // Restore old binary mode.\n    bout.remoteIO()->set_binary_mode(saved_binary_mode);\n    return -1;\n  }\n\n  // Kinda hacky but WaitForInputIdle doesn't work on console application.\n  wwiv::os::sleep_for(std::chrono::milliseconds(a()->GetExecChildProcessWaitTime()));\n  const auto sleep_zero_times = 5;\n  for (auto iter = 0; iter < sleep_zero_times; iter++) {\n    wwiv::os::yield();\n  }\n\n  CloseHandle(pi.hThread);\n\n  bout.remoteIO()->set_binary_mode(true);\n  const auto sync_loop_status =\n      DoSyncFosLoopNT(pi.hProcess, hSyncHangupEvent, hSyncReadSlot, nSyncMode);\n  LogToSync(StrCat(\"DoSyncFosLoopNT: Returned \", sync_loop_status, \"\\r\\n\", std::string(78, '='),\n                    \"\\r\\n\\r\\n\\r\\n\"));\n\n  if (sync_loop_status) {\n    DWORD dwExitCode = 0;\n    GetExitCodeProcess(pi.hProcess, &dwExitCode);\n    if (dwExitCode == STILL_ACTIVE) {\n      LogToSync(\"Terminating Sync Process\");\n      LOG(INFO) << \"Terminating Sync process.\";\n      TerminateProcess(pi.hProcess, 0);\n    } else {\n      LogToSync(fmt::format(\"Sync Process Exit Code: {}\", dwExitCode));\n    }\n  }\n  fclose(hLogFile);\n\n  DWORD dwExitCode = 0;\n  GetExitCodeProcess(pi.hProcess, &dwExitCode);\n\n  // Close process and thread handles.\n  CloseHandle(pi.hProcess);\n\n  // Restore old binary mode.\n  bout.remoteIO()->set_binary_mode(saved_binary_mode);\n\n  return static_cast<int>(dwExitCode);\n}\n\nHANDLE stdin_read = nullptr;\nHANDLE stdin_write = nullptr;\nHANDLE stdout_read = nullptr;\nHANDLE stdout_write = nullptr;\nstd::atomic<bool> stop_pipe;\n\nstatic bool create_stdio_pipes() {\n  stop_pipe.store(false);\n  SECURITY_ATTRIBUTES saAttr{};\n\n  // Set the bInheritHandle flag so pipe handles are inherited.\n  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);\n  saAttr.bInheritHandle = TRUE;\n  saAttr.lpSecurityDescriptor = nullptr;\n\n  // Create a pipe for the child process's STDOUT.\n  if (!CreatePipe(&stdout_read, &stdout_write, &saAttr, 0)) {\n    return false;\n  }\n\n  // Ensure the read handle to the pipe for STDOUT is not inherited.\n  if (!SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0)) {\n    return false;\n  }\n\n  // Create a pipe for the child process's STDIN.\n  if (!CreatePipe(&stdin_read, &stdin_write, &saAttr, 0)) {\n    return false;\n  }\n\n  // Ensure the write handle to the pipe for STDIN is not inherited.\n  if (!SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0)) {\n    return false;\n  }\n\n  return true;\n}\n\nvoid pump_pipes(HANDLE hProcess) {\n  static constexpr int check_process_every = 10;\n  char buf[1024];\n  int count = 0;\n  while (!stop_pipe.load()) {\n    DWORD num_read, num_avail, msg_left;\n    if (PeekNamedPipe(stdout_read, buf, sizeof(buf), &num_read, &num_avail, &msg_left) &&\n        num_read > 0) {\n      auto b = ReadFile(stdout_read, buf, sizeof(buf), &num_read, NULL);\n      if (!b || num_read == 0) {\n        VLOG(1) << \"Exiting pump_pipes: b:\" << b << \"; num_read: \" << num_read;\n        return;\n      }\n      bout.remoteIO()->write(buf, num_read);\n    }\n\n    if (!bout.remoteIO()->connected()) {\n      VLOG(1) << \"Exiting pump_pipes: Caller Hung up.\";\n      return;\n    }\n\n    if (bout.remoteIO()->incoming()) {\n      if (num_read = bout.remoteIO()->read(buf, sizeof(buf)); num_read > 0) {\n        DWORD num_written;\n        if (!WriteFile(stdin_write, buf, num_read, &num_written, nullptr)) {\n          VLOG(1) << \"Exiting pump_pipes; Write to pipe failed\";\n          return;\n        }\n      }\n    }\n\n    if (++count >= check_process_every) {\n      count = 0;\n      DWORD dwExitCode;\n      if (GetExitCodeProcess(hProcess, &dwExitCode) && dwExitCode != STILL_ACTIVE) {\n        VLOG(1) << \"Process exited. Ending pump_pipes\";\n        return;\n      }\n    }\n  }\n  Sleep(100);\n}\n\nint exec_cmdline(wwiv::bbs::CommandLine& cmdline, int flags) {\n  auto mask = EFLAG_COMIO | EFLAG_NETFOSS | EFLAG_LISTEN_SOCK | EFLAG_STDIO | EFLAG_SYNC_FOSSIL | EFLAG_UNIX_SOCK;\n  auto test = flags & mask;\n  if ((test & (test - 1)) != 0) {\n    // Not allowed.\n    LOG(ERROR) << \"Tried to execute command with multiple exec types: \" << cmdline.cmdline();\n    return false;\n  }\n\n  bool need_reopen_remoteio = false;\n  STARTUPINFO si{};\n  PROCESS_INFORMATION pi{};\n\n  ZeroMemory(&si, sizeof(si));\n  si.cb = sizeof(STARTUPINFO);\n  ZeroMemory(&pi, sizeof(pi));\n\n  std::unique_ptr<wwiv::bbs::ExecSocket> exec_socket;\n\n  auto working_cmdline = cmdline.cmdline();\n  if (a()->sess().using_modem()) {\n    if (flags & EFLAG_SYNC_FOSSIL) {\n      return exec_cmdline_sync(cmdline, flags, 0);\n    }\n    if (flags & EFLAG_COMIO) {\n      return exec_cmdline_sync(cmdline, flags,\n                               CONST_SBBSFOS_DOSIN_MODE | CONST_SBBSFOS_DOSOUT_MODE);\n    }\n\n    if (flags & EFLAG_STDIO) {\n      if (!create_stdio_pipes()) {\n        LOG(ERROR) << \"Unable to create pipes for STDIO\";\n        return -1;\n      }\n      // Set the socket to be std{in,out}\n      // This doesn't work at all\n      // const auto sock = bout.remoteIO()->GetDoorHandle();\n\n      // si.hStdError = stdout_write;\n      si.hStdOutput = stdout_write;\n      si.hStdInput = stdin_read;\n      si.dwFlags |= STARTF_USESTDHANDLES;\n      // N.B. Don't close remote IO.\n    } else if (flags & EFLAG_NETFOSS) {\n      if (const auto nf_path = create_netfoss_bat()) {\n        working_cmdline = fmt::format(\"{} {}\", nf_path.value(), cmdline.cmdline());\n        VLOG(1) << \"Closing remote IO for NetFOSS\";\n        bout.remoteIO()->close(true);\n        need_reopen_remoteio = true;\n      } else {\n        ssm(1) << \"NetFoss is not installed properly.\";\n        LOG(ERROR) << \"Failed to create NF.BAT for command: \" << working_cmdline;\n        bout.nl(2);\n        bout.pl(\"|#6Please tell the SysOp to install NetFoss properly.\");\n        bout.nl(2);\n        bout.pausescr();\n        return false;\n      }\n    } else if (flags & EFLAG_LISTEN_SOCK) {\n      uint16_t port = 0;\n      exec_socket = std::make_unique<wwiv::bbs::ExecSocket>(port);\n      // Add %Z into the commandline.\n      if (exec_socket->listening()) {\n        cmdline.add('Z', exec_socket->z());\n        working_cmdline = cmdline.cmdline();\n      }\n\n    } else if (flags & EFLAG_UNIX_SOCK) {\n      exec_socket = std::make_unique<wwiv::bbs::ExecSocket>(a()->sess().dirs().scratch_directory());\n      // Add %Z into the commandline.\n      if (exec_socket->listening()) {\n        cmdline.add('Z', exec_socket->z());\n        working_cmdline = cmdline.cmdline();\n      }\n    } else {\n      // Not STDIO or NETFOSS so close remote IO  \n      VLOG(1) << \"Closing remote IO\";\n      bout.remoteIO()->close(true);\n      need_reopen_remoteio = true;\n    }\n  }\n  VLOG(1) << \"exec_cmdline: working_commandline: \" << working_cmdline;\n\n  std::string title = (flags & EFLAG_NETPROG) \n    ? \"NETWORK\" : fmt::format(\"{} in door on node {}\", a()->user()->GetName(), a()->sess().instance_number());\n\n  si.lpTitle = &title[0];\n\n  const auto current_directory = File::current_directory().string();\n\n  // Need a non-const string for the commandline\n  char szTempWorkingCommandline[MAX_PATH+1];\n  to_char_array(szTempWorkingCommandline, working_cmdline);\n  DWORD dwCreationFlags = 0;\n  if (!CreateProcess(nullptr, szTempWorkingCommandline, nullptr, nullptr, TRUE, dwCreationFlags,\n                     nullptr, // a()->xenviron not using nullptr causes things to not work.\n                     current_directory.c_str(), &si, &pi)) {\n    const auto error_code = ::GetLastError();\n    const auto error_message = ErrorAsString(error_code);\n    LOG(ERROR) << \"CreateProcessFailed: error: \" << error_message;\n    sysoplog(fmt::format(\"!!! CreateProcess failed for command: [{}] with Error Message: {}\", working_cmdline, error_message));\n\n    // If we return here, we may have to reopen the communications port.\n    if (a()->sess().ok_modem_stuff() && a()->sess().using_modem() && need_reopen_remoteio) {\n      VLOG(1) << \"Reopening comm (on createprocess error)\";\n      bout.remoteIO()->open();\n    }\n    // Restore old binary mode.\n    return -1;\n  }\n\n  CloseHandle(pi.hThread);\n  bool terminated = false;\n\n  if (a()->sess().using_modem() && (flags & EFLAG_STDIO)) {\n    CloseHandle(stdout_write);\n    CloseHandle(stdin_read);\n    pump_pipes(pi.hProcess);\n  } else if (exec_socket) {\n    if (const auto sock = exec_socket->accept()) {\n      DCHECK(bout.remoteIO());\n      const auto res = exec_socket->pump_socket(pi.hProcess, sock.value(), *bout.remoteIO());\n      if (res != pump_socket_result_t::process_exit) {\n        // sockets closed but process still running.\n        VLOG(1) << \"Sockets closed, process still running; Forcefully terminating pid: \"\n                << pi.hProcess;\n        if (TerminateProcess(pi.hProcess, 127)) {\n          terminated = true;\n        }\n      }\n    } else {\n      VLOG(1) << \"Accept never happend; Forcefully terminating pid: \" << pi.hProcess;\n      if (TerminateProcess(pi.hProcess, 127)) {\n        terminated = true;\n      }\n    }\n  }\n\n  if (!terminated) {\n    // Wait until child process exits.\n    WaitForSingleObject(pi.hProcess, INFINITE);\n  }\n\n  DWORD dwExitCode = 0;\n  GetExitCodeProcess(pi.hProcess, &dwExitCode);\n\n  // Close process handle.\n  CloseHandle(pi.hProcess);\n\n  // reengage comm stuff\n  if (need_reopen_remoteio && a()->sess().ok_modem_stuff() && a()->sess().using_modem()) {\n    VLOG(1) << \"Reopening comm\";\n    bout.remoteIO()->open();\n  }\n\n  return static_cast<int>(dwExitCode);\n}\n"
  },
  {
    "path": "bbs/execexternal.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/execexternal.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/exec.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/wqscn.h\"\n#include \"bbs/basic/basic.h\"\n#include \"core/log.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/instance.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\n\nstatic int ExecuteExternalProgramNoScript(wwiv::bbs::CommandLine& commandLine, uint32_t nFlags) {\n  LOG(INFO) << \"ExecuteExternalProgram: \" << commandLine.cmdline();\n  // forget it if the user has hung up\n  if (!(nFlags & EFLAG_NOHUP)) {\n    if (a()->CheckForHangup()) {\n      LOG(ERROR) << \"Not executing program.  User Hung Up\";\n      return -1;\n    }\n  }\n  [[maybe_unused]] auto _ = create_chain_file();\n\n  // get ready to run it\n  if (a()->sess().IsUserOnline()) {\n    a()->WriteCurrentUser();\n    write_qscn(a()->sess().user_num(), a()->sess().qsc, false);\n  }\n\n  // extra processing for net programs\n  if (nFlags & EFLAG_NETPROG) {\n    write_inst(INST_LOC_NET, a()->net_num() + 1, INST_FLAGS_NONE);\n  }\n\n  auto exec_dir = a()->bbspath();\n  if (nFlags & EFLAG_TEMP_DIR) {\n    exec_dir = a()->sess().dirs().temp_directory();\n  } else if (nFlags & EFLAG_BATCH_DIR) {\n    exec_dir = a()->sess().dirs().batch_directory();\n  } else if (nFlags & EFLAG_QWK_DIR) {\n    exec_dir = a()->sess().dirs().qwk_directory();\n  }\n  if (!(nFlags & EFLAG_NO_CHANGE_DIR)) {\n    if (!File::set_current_directory(exec_dir)) {\n      LOG(ERROR) << \"Unable to set working directory to: \" << exec_dir;\n    }\n  }\n\n  // Some LocalIO implementations (Curses) needs to disable itself before\n  // we fork some other process.\n  bout.localIO()->DisableLocalIO();\n  const auto return_code = exec_cmdline(commandLine, nFlags);\n\n  // Re-engage the local IO engine if needed.\n  bout.localIO()->ReenableLocalIO();\n  File::set_current_directory(a()->bbspath());\n\n  // Reread the user record.\n  if (a()->sess().IsUserOnline()) {\n    a()->ReadCurrentUser();\n    read_qscn(a()->sess().user_num(), a()->sess().qsc, false, true);\n    a()->UpdateTopScreen();\n  }\n\n  // return to caller\n  return return_code;\n}\n\nint ExecuteExternalProgram(wwiv::bbs::CommandLine& cmdline, uint32_t flags) {\n  auto command_line = cmdline.cmdline();\n  if (command_line.front() != '@') {\n    return ExecuteExternalProgramNoScript(cmdline, flags);\n  }\n\n  if (flags & EFLAG_NOSCRIPT) {\n    LOG(WARNING) << \"Not running '\" << command_line << \"' as a script since EFLAG_NOSCRIPT is specified.\";\n    return ExecuteExternalProgramNoScript(cmdline, flags);\n  }\n \n  // Let's see if we need to run a basic script.\n  const std::string BASIC_PREFIX = \"@basic:\";\n  if (!wwiv::strings::starts_with(command_line, BASIC_PREFIX)) {\n    return 1;\n  }\n\n  const auto cmd = command_line.substr(BASIC_PREFIX.size());\n  LOG(INFO) << \"Running basic script: \" << cmd;\n  return wwiv::bbs::basic::RunBasicScript(cmd) ? 0 : 1;\n}"
  },
  {
    "path": "bbs/execexternal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_EXECEXTERNAL_H\n#define INCLUDED_BBS_EXECEXTERNAL_H\n\n#include \"bbs/stuffin.h\"\n#include <string>\n\n/**\n * Executes an external program or am internal script.\n *\n * To execute a script, use prefix the command with @ and script type.\n * For a basic script, use the following syntax for command_line:\n * '@basic:[SCRIPT_NAME]'\n *\n * flags are the EFLAG_XXXX flags defined in vardec.h\n */\nint ExecuteExternalProgram(wwiv::bbs::CommandLine& command_line, uint32_t flags);\n\n#endif\n"
  },
  {
    "path": "bbs/external_edit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/external_edit.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/external_edit_qbbs.h\"\n#include \"bbs/external_edit_wwiv.h\"\n#include \"bbs/make_abs_cmd.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/utility.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/output.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fsed/fsed.h\"\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n/////////////////////////////////////////////////////////////////////////////\n// Actually launch the editor. This won't create any control files, etc.\nstatic bool external_edit_internal(const std::string& edit_filename, const std::filesystem::path& working_directory,\n                                   const editorrec& editor, int numlines) {\n\n  std::string editorCommand = a()->sess().incom() ? editor.filename : editor.filenamecon;\n  if (editorCommand.empty()) {\n    bout.outstr(\"You can't use that full screen editor. (eti)\\r\\n\\r\\n\");\n    bout.pausescr();\n    return false;\n  }\n\n  if (File::Exists(edit_filename)) {\n    File file(edit_filename);\n    if (File::is_directory(edit_filename)) {\n      bout.nl();\n      bout.outstr(\"|#6You can't edit a directory.\\r\\n\\r\\n\");\n      bout.pausescr();\n      return false;\n    }\n  }\n\n  make_abs_cmd(a()->bbspath(), &editorCommand);\n\n  const auto stripped_file_name{stripfn(edit_filename)};\n  auto on_exit = finally([=] { File::set_current_directory(a()->bbspath()); });\n  if (!working_directory.empty()) {\n    File::set_current_directory(working_directory);\n  }\n\n  const auto tft_fn = FilePath(File::current_directory(), stripped_file_name);\n  const auto orig_file_time = File::Exists(tft_fn) ? File::last_write_time(tft_fn) : 0;\n\n  const auto num_screen_lines = a()->user()->screen_lines();\n  wwiv::bbs::CommandLine cl(editorCommand);\n  cl.args(tft_fn.string(), std::to_string(a()->user()->screen_width()),\n          std::to_string(num_screen_lines), std::to_string(numlines));\n\n  ExecuteExternalProgram(cl, ansir_to_flags(editor.ansir) | EFLAG_NO_CHANGE_DIR);\n  bout.clear_lines_listed();\n\n  const auto file_time_now = File::Exists(tft_fn) ? File::last_write_time(tft_fn) : 0;\n  return File::Exists(tft_fn) && orig_file_time != file_time_now;\n}\n\nstatic std::unique_ptr<ExternalMessageEditor>\nCreateExternalMessageEditor(const editorrec& editor, MessageEditorData& data, int maxli,\n                            int* setanon, const std::filesystem::path& temp_directory) {\n  if (editor.bbs_type == EDITORREC_EDITOR_TYPE_QBBS) {\n    return std::make_unique<ExternalQBBSMessageEditor>(editor, data, maxli, setanon,\n                                                       temp_directory);\n  }\n  return std::make_unique<ExternalWWIVMessageEditor>(editor, data, maxli, setanon, temp_directory);\n}\n\nbool ExternalMessageEditor::Run() {\n  if (!Before()) {\n    return false;\n  }\n  if (!external_edit_internal(editor_filename(), temp_directory_, editor_, maxli_)) {\n    return false;\n  }\n  return After();\n}\n\nbool DoExternalMessageEditor(MessageEditorData& data, int maxli, int* setanon) {\n  const size_t editor_number = a()->user()->default_editor() - 1;\n  if (editor_number >= a()->editors.size() || !okansi()) {\n    bout.outstr(\"\\r\\nYou can't use that full screen editor (EME).\\r\\n\\n\");\n    return false;\n  }\n\n  const auto& editor = a()->editors[editor_number];\n  auto eme = CreateExternalMessageEditor(editor, data, maxli, setanon, a()->sess().dirs().temp_directory());\n  return eme->Run();\n}\n\nbool external_text_edit(const std::string& edit_filename, const std::filesystem::path& working_directory,\n                        int numlines, int flags) {\n  bout.nl();\n  const auto editor_number = a()->user()->default_editor() - 1;\n  if (editor_number >= wwiv::stl::ssize(a()->editors) || !okansi()) {\n    bout.outstr(\"You can't use that full screen editor. (ete1)\\r\\n\\r\\n\");\n    bout.pausescr();\n    return false;\n  }\n\n  const auto& editor = a()->editors[editor_number];\n  MessageEditorData data(a()->user()->name_and_number());\n  data.msged_flags = flags;\n  auto setanon = 0;\n  if (auto eme = CreateExternalMessageEditor(editor, data, numlines, &setanon,\n                                             a()->sess().dirs().temp_directory()); !eme->Before()) {\n    return false;\n  }\n  \n  return external_edit_internal(edit_filename, working_directory, editor, numlines);\n}\n\nbool fsed_text_edit(const std::string& edit_filename, const std::filesystem::path& new_directory,\n                    int numlines, int flags) {\n  if (ok_external_fsed()) {\n    return external_text_edit(edit_filename, new_directory, numlines, flags);\n  }\n  std::filesystem::path p{edit_filename};\n  const auto dir = p.parent_path();\n  return wwiv::fsed::fsed(a()->context(), p);\n}\n"
  },
  {
    "path": "bbs/external_edit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_EXTERNAL_EDIT_H__\n#define __INCLUDED_EXTERNAL_EDIT_H__\n\n#include \"common/message_editor_data.h\"\n#include <string>\n#include <filesystem>\n#include \"sdk/vardec.h\"\n\nclass ExternalMessageEditor {\npublic:\n  ExternalMessageEditor(const editorrec& editor, wwiv::common::MessageEditorData& data, int maxli, int* setanon,\n                        const std::filesystem::path& temp_directory)\n      : editor_(editor), data_(data), maxli_(maxli), setanon_(setanon),\n        temp_directory_(temp_directory){};\n  virtual ~ExternalMessageEditor() = default;\n\n  virtual bool Run();\n  virtual void CleanupControlFiles() = 0;\n  virtual bool Before() = 0;\n  virtual bool After() = 0;\n  virtual std::string editor_filename() const = 0;\n\nprotected:\n  const editorrec editor_;\n  wwiv::common::MessageEditorData& data_;\n  const int maxli_;\n  int* setanon_;\n  const std::filesystem::path temp_directory_;\n};\nbool DoExternalMessageEditor(wwiv::common::MessageEditorData& data, int maxli, int* setanon);\n\nbool external_text_edit(const std::string& edit_filename, const std::filesystem::path& new_directory,\n                        int numlines, int flags);\nbool fsed_text_edit(const std::string& edit_filename, const std::filesystem::path& new_directory,\n                    int numlines, int flags);\n\n#endif // __INCLUDED_EXTERNAL_EDIT_H__\n"
  },
  {
    "path": "bbs/external_edit_qbbs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/external_edit_qbbs.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/utility.h\"\n#include \"common/message_editor_data.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/fido/fido_util.h\"\n\n#include <filesystem>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\n\nstd::string ExternalQBBSMessageEditor::editor_filename() const { return MSGTMP; }\n\nExternalQBBSMessageEditor ::~ExternalQBBSMessageEditor() {\n  this->ExternalQBBSMessageEditor::CleanupControlFiles();\n}\n\nvoid ExternalQBBSMessageEditor::CleanupControlFiles() {\n  File::Remove(FilePath(temp_directory_, MSGINF), true);\n  File::Remove(FilePath(temp_directory_, MSGTMP), true);\n}\n\n/**\n * Creates a MSGINF file for QBBS style editors.\n *\n * MSGINF. - A text file containing message information:\n *\n * line 1: Who the message is FROM\n * line 2: Who the message is TO\n * line 3: Message subject\n * line 4: Message number }   Where message is being\n * line 5: Message area   }   posted. (not used in editor)\n * line 6: Private flag (\"YES\" or \"NO\")\n */\nstatic bool WriteMsgInf(const std::string& title, const std::string& sub_name, bool is_email,\n                        const std::string& to_name, bool real_name, const std::filesystem::path& temp_directory,\n                        const wwiv::sdk::User& user) {\n  TextFile file(FilePath(temp_directory, MSGINF), \"wd\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n\n  // line 1: Who the message is FROM\n  file.WriteLine(real_name ? user.real_name() : user.name());\n  if (!to_name.empty()) {\n    // line 2: Who the message is TO\n    file.WriteLine(to_name);\n  } else {\n    // Since we don't know who this is to, make it all.\n    // line 2: Who the message is TO\n    file.WriteLine(\"All\");\n  }\n  // line 3: Message subject\n  file.WriteLine(title);\n  // Message area # - We are not QBBS\n  // line 4: Message number\n  file.WriteLine(\"0\");\n  if (is_email) {\n    // line 5: Message area\n    file.WriteLine(\"E-mail\");\n    // line 6: Private flag (\"YES\" or \"NO\")\n    file.WriteLine(\"YES\");\n  } else {\n    // line 5: Message area\n    file.WriteLine(sub_name);\n    // line 6: Private flag (\"YES\" or \"NO\")\n    file.WriteLine(\"NO\");\n  }\n  file.Close();\n  return true;\n}\n\nstatic bool CreateMsgTmpFromQuotesTxt(const std::filesystem::path& tmpdir) {\n  const auto qfn = FilePath(tmpdir, QUOTES_TXT);\n  if (!File::Exists(qfn)) {\n    return false;\n  }\n  // Copy quotes.txt to MSGTMP if it exists\n  TextFile in(qfn, \"rt\");\n  if (!in) {\n    return false; \n  }\n  File out(FilePath(tmpdir, MSGTMP));\n  if (!out.Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile |\n                File::modeTruncate)) {\n    return false;\n  }\n  const auto lines = in.ReadFileIntoVector();\n  int num_to_skip = 2;\n  for (const auto& l : lines) {\n    if (!l.empty()) {\n      if (l.front() == CD) {\n        continue;\n      }\n      if (num_to_skip-- > 0) {\n        continue;\n      }\n    }\n    out.Writeln(stripcolors(l));\n  }\n  return true;\n}\n\nbool ExternalQBBSMessageEditor::Before() {\n  CleanupControlFiles();\n  CreateMsgTmpFromQuotesTxt(temp_directory_);\n  const bool real_name = data_.anonymous_flag & anony_real_name;\n  return WriteMsgInf(data_.title, data_.sub_name, data_.is_email(), data_.to_name, real_name,\n                     temp_directory_, *a()->user());\n}\n\nbool ExternalQBBSMessageEditor::After() {\n  // Copy MSGTMP to INPUT_MSG since that's what the rest of WWIV expects.\n\n  TextFile from(FilePath(temp_directory_, MSGTMP), \"rt\");\n  if (!from) {\n    return false;\n  }\n  const auto qbbs = from.ReadFileIntoString();\n  const auto wwiv = wwiv::sdk::fido::FidoToWWIVText(qbbs, true);\n\n  TextFile to(FilePath(temp_directory_, INPUT_MSG), \"wt\");\n  if (!to) {\n    return false;\n  }\n\n  return to.Write(wwiv) != 0;\n}\n\n"
  },
  {
    "path": "bbs/external_edit_qbbs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_EXTERNAL_EDIT_QBBS_H__\n#define __INCLUDED_EXTERNAL_EDIT_QBBS_H__\n\n#include \"bbs/external_edit.h\"\n#include \"common/message_editor_data.h\"\n#include <filesystem>\n#include <string>\n#include \"sdk/vardec.h\"\n\nclass ExternalQBBSMessageEditor final : public ExternalMessageEditor {\npublic:\n  ExternalQBBSMessageEditor(const editorrec& editor, wwiv::common::MessageEditorData& data, int maxli,\n                            int* setanon, const std::filesystem::path& temp_directory)\n      : ExternalMessageEditor(editor, data, maxli, setanon, temp_directory) {}\n  virtual ~ExternalQBBSMessageEditor();\n  void CleanupControlFiles() override;\n  bool Before() override;\n  bool After() override;\n  [[nodiscard]] std::string editor_filename() const override;\n};\n\n\n#endif // __INCLUDED_EXTERNAL_EDIT_QBBS_H__\n"
  },
  {
    "path": "bbs/external_edit_wwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/external_edit_wwiv.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/output.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nstruct fedit_data_rec {\n  char tlen, ttl[81], anon;\n};\n\nstd::string ExternalWWIVMessageEditor::editor_filename() const { return INPUT_MSG; }\n\nExternalWWIVMessageEditor ::~ExternalWWIVMessageEditor() { this->CleanupControlFiles(); }\n\nvoid ExternalWWIVMessageEditor::CleanupControlFiles() {\n  File::Remove(FilePath(temp_directory_, FEDIT_INF), true);\n  File::Remove(FilePath(temp_directory_, RESULT_ED), true);\n  File::Remove(FilePath(temp_directory_, EDITOR_INF), true);\n}\n\nstatic void ReadWWIVResultFiles(std::string* title, int* anon, const std::filesystem::path& tempdir) {\n  const auto fp = FilePath(tempdir, RESULT_ED);\n  if (File::Exists(fp)) {\n    TextFile file(fp, \"rt\");\n    std::string anon_string;\n    if (file.ReadLine(&anon_string)) {\n      *anon = to_number<int>(anon_string);\n      if (file.ReadLine(title)) {\n        // Strip whitespace from title to avoid issues like bug #29\n        StringTrim(title);\n      }\n    }\n    file.Close();\n  } else if (File::Exists(FilePath(tempdir, FEDIT_INF))) {\n    fedit_data_rec fedit_data{};\n    memset(&fedit_data, '\\0', sizeof(fedit_data_rec));\n    File file(FilePath(tempdir, FEDIT_INF));\n    file.Open(File::modeBinary | File::modeReadOnly);\n    if (file.Read(&fedit_data, sizeof(fedit_data))) {\n      title->assign(fedit_data.ttl);\n      *anon = fedit_data.anon;\n    }\n  }\n}\n\nstatic void WriteWWIVEditorControlFiles(const std::string& title, const std::string& sub_name,\n                                        const std::string& to_name, int flags,\n                                        const std::filesystem::path& tempdir) {\n  TextFile f(FilePath(tempdir, EDITOR_INF), \"wt\");\n  if (f.IsOpen()) {\n    if (!to_name.empty()) {\n      flags |= MSGED_FLAG_HAS_REPLY_NAME;\n    }\n    if (!title.empty()) {\n      flags |= MSGED_FLAG_HAS_REPLY_TITLE;\n    }\n    f.WriteLine(title);\n    f.WriteLine(sub_name);\n    f.WriteLine(a()->user()->usernum());\n    f.WriteLine(a()->user()->name());\n    f.WriteLine(a()->user()->real_name());\n    f.WriteLine(a()->user()->sl());\n    f.WriteLine(flags);\n    f.WriteLine(bout.localIO()->GetTopLine());\n    f.WriteLine(\"0\"); // Was user.language\n  }\n  if (flags & MSGED_FLAG_NO_TAGLINE) {\n    // disable tag lines by creating a DISABLE.TAG file\n    TextFile fileDisableTag(FilePath(tempdir, DISABLE_TAG), \"w\");\n    fileDisableTag.Write(\"\");\n  } else {\n    File::Remove(FilePath(tempdir, DISABLE_TAG), true);\n  }\n  if (title.empty()) {\n    File::Remove(FilePath(tempdir, QUOTES_TXT), true);\n  }\n\n  // Write FEDIT.INF\n  fedit_data_rec fedit_data{};\n  memset(&fedit_data, '\\0', sizeof(fedit_data_rec));\n  fedit_data.tlen = 60;\n  to_char_array(fedit_data.ttl, title);\n  fedit_data.anon = 0;\n\n  File fedit_inf(FilePath(tempdir, FEDIT_INF));\n  if (fedit_inf.Open(File::modeDefault | File::modeCreateFile | File::modeTruncate,\n                     File::shareDenyReadWrite)) {\n    fedit_inf.Write(&fedit_data, sizeof(fedit_data));\n    fedit_inf.Close();\n  }\n}\n\nbool ExternalWWIVMessageEditor::Before() {\n  CleanupControlFiles();\n  WriteWWIVEditorControlFiles(data_.title, data_.sub_name, data_.to_name, data_.msged_flags, temp_directory_);\n\n  return true;\n}\n\nbool ExternalWWIVMessageEditor::After() { \n  ReadWWIVResultFiles(&data_.title, setanon_, temp_directory_); \n  return true;\n}\n\n"
  },
  {
    "path": "bbs/external_edit_wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_EXTERNAL_EDIT_WWIv_H__\n#define __INCLUDED_EXTERNAL_EDIT_WWIv_H__\n\n#include \"bbs/external_edit.h\"\n#include \"common/message_editor_data.h\"\n#include <string>\n#include <filesystem>\n#include \"sdk/vardec.h\"\n\nclass ExternalWWIVMessageEditor : public ExternalMessageEditor {\npublic:\n  ExternalWWIVMessageEditor(const editorrec& editor, wwiv::common::MessageEditorData& data, int maxli,\n                            int* setanon, const std::filesystem::path& temp_directory)\n      : ExternalMessageEditor(editor, data, maxli, setanon, temp_directory) {}\n  virtual ~ExternalWWIVMessageEditor();\n  void CleanupControlFiles() override;\n  bool Before() override;\n  bool After() override;\n  std::string editor_filename() const override;\n};\n\n\n#endif // __INCLUDED_EXTERNAL_EDIT_WWIv_H__\n"
  },
  {
    "path": "bbs/extract.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/extract.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n\n#include <filesystem>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nstatic std::optional<std::filesystem::path> get_extract_dir() {\n  bout.print_help_file(MEXTRACT_NOEXT);\n  do {\n    bout.outstr(\"|#5(Q=Quit) Which (D,G,T) ? \");\n    switch (const auto ch1 = onek(\"QGDT?\"); ch1) {\n    case 'G':\n      return a()->sess().dirs().gfiles_directory();\n    case 'D':\n      return a()->config()->datadir();\n    case 'T':\n      return a()->sess().dirs().temp_directory();\n    case '?':\n      bout.print_help_file(MEXTRACT_NOEXT);\n      break;\n    case 'Q':\n    default:\n      return std::nullopt;\n    }\n  } while (!a()->sess().hangup());\n  return std::nullopt;\n}\n\nvoid extract_out(const std::string& text, const std::string& title) {\n  const auto odir = get_extract_dir();\n  if (!odir) {\n    return;\n  }\n  const auto& dir = odir.value();\n  auto done = false;\n  std::filesystem::path path;\n  std::string mode = \"wt\";\n  do {\n    bout.outstr(\"|#2Save under what filename? \");\n    const auto fn = bin.input_filename(50);\n    if (fn.empty()) {\n      return;\n    }\n    path = FilePath(dir, fn);\n    \n    if (!File::Exists(path)) {\n      break;\n    }\n    bout.outstr(\"\\r\\nFilename already in use.\\r\\n\\n\");\n    bout.outstr(\"|#0O|#1)verwrite, |#0A|#1)ppend, |#0N|#1)ew name, |#0Q|#1)uit? |#0\");\n    switch (const auto ch1 = onek(\"QOAN\"); ch1) {\n    case 'N':\n      continue;\n    case 'A':\n      mode = \"at\";\n      done = true;\n      break;\n    case 'O':\n      done = true;\n      File::Remove(path);\n      break;\n    case 'Q':\n    default:\n      return;\n    }\n    bout.nl();\n  } while (!a()->sess().hangup() && !done);\n\n  if (a()->sess().hangup()) {\n    return;\n  }\n  TextFile file(path, mode);\n  if (!file) {\n    bout.outstr(\"|#6Could not open file for writing.\\r\\n\");\n    return;\n  }\n  file.WriteLine(title);\n  file.Write(text);\n  bout.print(\"|#9Message written to: '|#2{}|#9'\\r\\n\\r\\n\", file.full_pathname());\n  bout.pausescr();\n}\n\n"
  },
  {
    "path": "bbs/extract.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_EXTRACT_H__\n#define __INCLUDED_BBS_EXTRACT_H__\n\n#include <string>\n\nvoid extract_out(const std::string& text, const std::string& title);\n\n#endif  // __INCLUDED_BBS_EXTRACT_H__"
  },
  {
    "path": "bbs/finduser.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/finduser.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"sdk/names.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\n#include <string>\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n//\n// Returns user number\n//      or 0 if user not found\n//      or special value\n//\n// This function will remove the special characters from arround the searchString that are\n// used by the network and remote, etc.\n//\n// Special values:\n//\n//  -1      = NEW USER\n//\nint finduser(const std::string& searchString) {\n  User user;\n\n  a()->users()->set_user_writes_allowed(true);\n  if (searchString == \"NEW\") {\n    return -1;\n  }\n  auto user_number = to_number<int>(searchString);\n  if (user_number > 0) {\n    a()->users()->readuser(&user, user_number);\n    if (user.deleted()) {\n      return 0;\n    }\n    return user_number;\n  }\n  user_number = a()->names()->FindUser(searchString);\n  if (user_number == 0) {\n    return 0;\n  } \n  a()->users()->readuser(&user, user_number);\n  if (user.deleted()) {\n    return 0;\n  }\n  if (iequals(user.name(), \"GUEST\")) {\n    a()->users()->set_user_writes_allowed(false);\n  }\n  return user_number;\n}\n\n\n// Takes user name/handle as parameter, and returns user number, if found,\n// else returns 0.\nint finduser1(const std::string& searchString) {\n  if (searchString.empty()) {\n    return 0;\n  }\n  if (const auto un = finduser(searchString); un > 0) {\n    return un;\n  }\n\n  const auto name_part = ToStringUpperCase(searchString);\n  for (const auto& n : a()->names()->names_vector()) {\n    if (strstr(reinterpret_cast<const char*>(n.name), name_part.c_str()) == nullptr) {\n      continue;\n    }\n\n    bout.print(\"|#5Do you mean {} (Y/N/Q)? \", a()->names()->UserName(n.number));\n    const auto ch = bin.ynq();\n    if (ch == 'Y') {\n      return n.number;\n    }\n    if (ch == 'Q') {\n      return 0;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "bbs/finduser.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_FINDUSER_H__\n#define __INCLUDED_BBS_FINDUSER_H__\n\n#include <string>\n\nint finduser(const std::string& searchString);\nint finduser1(const std::string& searchString);\n\n#endif  // __INCLUDED_BBS_FINDUSER_H__"
  },
  {
    "path": "bbs/gfileedit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/gfileedit.h\"\n\n#include \"acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/pause.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/gfiles.h\"\n#include \"sdk/status.h\"\n\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic std::string gfiledata(const gfile_dir_t& r, int nSectionNum) {\n  return fmt::sprintf(\"|#2%2d |#1%-40s  |#2%-8s |#9%-3d |#5%-23s\",\n          nSectionNum, stripcolors(r.name), r.filename, r.maxfiles, r.acs);\n}\n\nstatic void showsec() {\n  bout.cls();\n  auto abort = false;\n  bout.bpla(\"|#2NN Name                                      FN       ACS\", &abort);\n  bout.bpla(\"|#7-- ----------------------------------------  ======== -----------------------\", &abort);\n  auto current_section = 0;\n  for (const auto& r : a()->gfiles().dirs()) {\n    bout.bpla(gfiledata(r, current_section++), &abort);\n    if (abort) {\n      break;\n    }\n  }\n}\n\nvoid modify_sec(int n) {\n  auto& r = a()->gfiles().dir(n);\n  auto done = false;\n  do {\n    bout.cls();\n    bout.litebar(StrCat(\"Editing G-File Area # \", n));\n    bout.print(\"|#9A) Name      : |#2{}\\r\\n\", r.name);\n    bout.print(\"|#9B) Filename  : |#2{}\\r\\n\", r.filename);\n    bout.print(\"|#9C) ACS       : |#2{}\\r\\n\", r.acs);\n    bout.print(\"|#9D) Max Files : |#2{}\\r\\n\", r.maxfiles);\n    bout.nl();\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Which (|#1A|#7-|#1F,|#1[|#7,|#1]|#7) : \");\n    const auto ch = onek(\"QABCD[]\", true);\n    switch (ch) {\n    case 'Q':\n      done = true;\n      break;\n    case '[':\n      a()->gfiles().set_dir(n, r);\n      if (--n < 0) {\n        n = size_int(a()->gfiles()) - 1;\n      }\n      r = a()->gfiles().dir(n);\n      break;\n    case ']':\n      a()->gfiles().set_dir(n, r);\n      if (++n >= size_int(a()->gfiles())) {\n        n = 0;\n      }\n      r = a()->gfiles().dir(n);\n      break;\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"|#2New name? \");\n      r.name = bin.input_text(r.name, 40);\n    } break;\n    case 'B': {\n      bout.nl();\n      if (File::Exists(FilePath(a()->config()->gfilesdir(), r.filename))) {\n        bout.outstr(\"\\r\\nThere is currently a directory for this g-file section.\\r\\n\");\n        bout.outstr(\"If you change the filename, the directory will still be there.\\r\\n\\n\");\n      }\n      bout.nl();\n      bout.outstr(\"|#2New filename? \");\n      auto fname = bin.input_filename(r.filename, 20);\n      if (!fname.empty()) {\n        r.filename = fname;\n        if (!File::Exists(FilePath(a()->config()->gfilesdir(), r.filename))) {\n          bout.nl();\n          bout.outstr(\"|#5Create directory for this section? \");\n          if (bin.yesno()) {\n            File dir(FilePath(a()->config()->gfilesdir(), r.filename));\n            File::mkdirs(dir);\n          } else {\n            bout.outstr(\"\\r\\nYou will have to create the directory manually, then.\\r\\n\\n\");\n          }\n        } else {\n          bout.outstr(\"\\r\\nA directory already exists under this filename.\\r\\n\\n\");\n        }\n        bout.pausescr();\n      }\n    } break;\n    case 'C': {\n      bout.nl();\n      r.acs = wwiv::bbs::input_acs(bin, bout, \"New ACS?\", r.acs, 60);\n    } break;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#1Max 99 files/section.\\r\\n|#2New max files? \");\n      r.maxfiles = bin.input_number(r.maxfiles, 0, 999, true);\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n  a()->gfiles().set_dir(n, r);\n}\n\n\nvoid insert_sec(int n) {\n  gfile_dir_t r{};\n  r.filename = \"NONAME\";\n  r.name = \"** NEW SECTION **\";\n  r.acs = \"user.sl >= 10\";\n  r.maxfiles = 99;\n  a()->gfiles().insert(n, r);\n  modify_sec(n);\n}\n\n\nvoid delete_sec(int n) {\n  a()->gfiles().erase(n);\n}\n\n\nvoid gfileedit() {\n  if (!ValidateSysopPassword()) {\n    return;\n  }\n  showsec();\n  auto done = false;\n  do {\n    bout.nl();\n    bout.outstr(\"|#2G-files: D:elete, I:nsert, M:odify, Q:uit, ? : \");\n    const auto ch = onek(\"QDIM?\");\n    switch (ch) {\n    case '?':\n      showsec();\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'M': {\n      bout.nl();\n      bout.outstr(\"|#2Section number? \");\n      std::set<char> q{'Q', 27, '\\r'};\n      const auto t = bin.input_number_hotkey(0, q, 0, size_int(a()->gfiles()), false);\n      if (!t.key) {      \n        modify_sec(t.num);\n      }\n      } break;\n    case 'I': {\n      if (size_int(a()->gfiles()) < a()->max_gfilesec) {\n        bout.nl();\n        bout.outstr(\"|#2Insert before which section? \");\n        std::set<char> q{'Q', 27, '\\r'};\n        const auto t = bin.input_number_hotkey(0, q, 0, size_int(a()->gfiles()), false);\n        if (!t.key) {\n          insert_sec(t.num);\n        }\n      }\n      } break;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#2Delete which section? \");\n      std::set<char> q{'Q', 27, '\\r'};\n      const auto t = bin.input_number_hotkey(0, q, 0, size_int(a()->gfiles()), false);\n      if (!t.key) {\n        bout.nl();\n        bout.print(\"|#5Delete {}?\", a()->gfiles().dir(t.num).name);\n        if (bin.yesno()) {\n          delete_sec(t.num);\n        }\n      }\n      } break;\n    }\n  } while (!done && !a()->sess().hangup());\n  a()->gfiles().Save();\n}\n\n\nbool fill_sec(int sn) {\n  const auto nf = size_int(a()->gfiles().dir(sn).files);\n  const auto path = FilePath(a()->config()->gfilesdir(), a()->gfiles()[sn].filename);\n  const auto filespec = FilePath(path, \"*.*\");\n  FindFiles ff(filespec, FindFiles::FindFilesType::files);\n  bool ok{true};\n  for (const auto& f : ff) {\n    if (a()->sess().hangup() || !ok) {\n      break;\n    }\n    auto found = false;\n    auto& g = a()->gfiles().dir(sn).files;\n    for (auto i1 = 0; i1 < nf && !found; i1++) {\n      if (iequals(f.name,  g[i1].filename)) {\n        found = true;\n      }\n    }\n    if (found) {\n      continue;\n    }\n    bout.print(\"|#2{} : \", f.name);\n    auto s1s = bin.input_text(60);\n    if (s1s.empty()) {\n      bout.outstr(\"|#6Aborted.\\r\\n\");\n      return false;\n    }\n    gfile_t g1{};\n    g1.filename = f.name;\n    g1.description = s1s;\n    g1.daten = daten_t_now();\n    a()->gfiles().dir(sn).files.emplace_back(g1);\n  }\n\n  if (nf >= a()->gfiles().dir(sn).maxfiles) {\n    bout.outstr(\"Section full.\\r\\n\");\n  }\n  a()->gfiles().Save();\n  a()->status_manager()->Run([&](Status& status) {\n    status.gfile_date(date());\n  });\n  return true;\n}\n"
  },
  {
    "path": "bbs/gfileedit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_GFILEEDIT_H\n#define INCLUDED_BBS_GFILEEDIT_H\n\nvoid modify_sec(int n);\nvoid gfileedit();\nbool fill_sec(int sn);\n\n#endif\n"
  },
  {
    "path": "bbs/gfiles.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/gfiles.h\"\n#include \"sdk/gfiles.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/gfileedit.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid gfiles2();\nvoid gfiles3(int n);\n\nstatic void gfl_hdr(int which) {\n  std::string s, s1, s2, s3;\n  if (okansi()) {\n    s2 = std::string(29, '\\xC4');\n  } else {\n    s2 = std::string(29, '-');\n  }\n  if (which) {\n    s1 = std::string(12, ' ');\n    s3 = std::string(11, ' ');\n  } else {\n    s1 = std::string(12, ' ');\n    s3 = std::string(17, ' ');\n  }\n  bool abort = false;\n  if (okansi()) {\n    if (which) {\n      s = StrCat(\"|#7\\xDA\\xC4\\xC4\\xC4\\xC2\", s2, \"\\xC2\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC2\", s2, \"\\xC2\\xC4\\xC4\\xC4\\xC4\\xBF\");\n    } else {\n      s = StrCat(\"|#7\\xDA\\xC4\\xC4\\xC4\\xC2\", s2, \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC2\", s2, \"\\xC4\\xC4\\xC4\\xC4\\xBF\");\n    }\n  } else {\n    if (which) {\n      s = StrCat(\"+---+\", s2, \"+----+---+\", s2, \"+----+\");\n    } else {\n      s = StrCat(\"+---+\", s2, \"-----+---+\", s2, \"----+\");\n    }\n  }\n  bout.bpla(s, &abort);\n  bout.ansic(0);\n  if (okansi()) {\n    if (which) {\n      s = StrCat(\"|#7\\xB3|#2 # |#7\\xB3\", s1, \"|#1 Name \", s3, \"|#7\\xB3|#9Size|#7\\xB3|#2 # |#7\\xB3\", s1, \"|#1 Name \", s3, \"|#7\\xB3|#9Size|#7\\xB3\");\n    } else {\n      s = StrCat(\"|#7\\xB3|#2 # |#7\\xB3\", s1, \"|#1 Name\", s3, \"|#7\\xB3|#2 # |#7\\xB3\", s1, \"|#1Name\", s3, \"|#7\\xB3\");\n    }\n  } else {\n    if (which) {\n      s = StrCat(\"| #   |\", s1, \"Name \", s1, \"|Size| # |\", s1, \" Name\", s1, \"|Size|\");\n    } else {\n      s = StrCat(\"| # |\", s1, \" Name     \", s1, \"| # |\", s1, \" Name    \", s1, \"|\");\n    }\n  }\n  bout.bpla(s, &abort);\n  bout.ansic(0);\n  if (okansi()) {\n    if (which) {\n      s = StrCat(\"|#7\\xC3\\xC4\\xC4\\xC4\\xC5\", s2, \"\\xC5\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC5\", s2, \"\\xC5\\xC4\\xC4\\xC4\\xC4\\xB4\");\n    } else {\n      s = StrCat(\"|#7\\xC3\\xC4\\xC4\\xC4\\xC5\", s2, \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC5\", s2, \"\\xC4\\xC4\\xC4\\xC4\\xB4\");\n    }\n  } else {\n    if (which) {\n      s = StrCat(\"+---+\", s2, \"+----+---+\", s2, \"+----+\");\n    }\n    else {\n      s = StrCat(\"+---+\", s2, \"-----+---+\", s2, \"----+\");\n    }\n  }\n  bout.bpla(s, &abort);\n  bout.ansic(0);\n}\n\nstatic void list_sec(std::vector<int> map) {\n  auto i2 = 0;\n  auto abort = false;\n  std::string s, s2, s3, s4, s5, s6, s7;\n  if (okansi()) {\n    s2 = std::string(29, '\\xC4');\n    s3 = std::string(12, '\\xC4');\n    s7 = std::string(12, '\\xC4');\n  } else {\n    s2 = std::string(29, '-');\n    s3 = std::string(12, '-');\n    s7 = std::string(12, '-');\n  }\n\n  bout.cls();\n  bout.litebar(StrCat(a()->config()->system_name(), \" G-Files Section\"));\n  gfl_hdr(0);\n  std::string t = times();\n  for (int i = 0; i < size_int(map) && !abort && !a()->sess().hangup(); i++) {\n    std::string lnum = std::to_string(i+1);\n    std::string rnum;\n    s4 = trim_to_size_ignore_colors(a()->gfiles()[map[i]].name, 34);\n    if (i + 1 >= size_int(map)) {\n      if (okansi()) {\n        rnum = std::string(3, '\\xFE');\n        s5 = std::string(29, '\\xFE');\n      } else {\n        rnum = std::string(3, 'o');\n        s5 = std::string(29, 'o');\n      }\n    } else {\n      rnum = std::to_string(i + 2);\n      s5 = trim_to_size_ignore_colors(a()->gfiles()[map[i + 1]].name, 29);\n    }\n    if (okansi()) {\n      s = fmt::sprintf(\"|#7\\xB3|#2%3s|#7\\xB3|#1%-34s|#7\\xB3|#2%3s|#7\\xB3|#1%-33s|#7\\xB3\", lnum, s4,\n                       rnum, s5);\n    } else {\n      s = fmt::sprintf(\"|%3s|%-34s|%3s|%-33s|\", lnum, s4, rnum, s5);\n    }\n    bout.bpla(s, &abort);\n    bout.ansic(0);\n    i++;\n    if (i2 > 10) {\n      i2 = 0;\n      std::string s1;\n      if (okansi()) {\n        s1 = fmt::sprintf(\n            \"|#7\\xC3\\xC4\\xC4\\xC4X%s\\xC4\\xC4\\xC4\\xC4\\xC4X\\xC4\\xC4\\xC4X\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4%s|#\"\n            \"1\\xFE|#7\\xC4|#2%s|#7\\xC4|#2\\xFE|#7\\xC4\\xC4\\xC4X\",\n            s2, s3, t);\n      } else {\n        s1 = fmt::sprintf(\"+---+%s-----+--------+%s-o-%s-o---+\", s2, s3, t);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n      bout.nl();\n      bout.pausescr();\n      gfl_hdr(1);\n    }\n  }\n  if (!abort) {\n    if (so()) {\n      std::string s1;\n      if (okansi()) {\n        s1 = fmt::sprintf(\"|#7\\xC3\\xC4\\xC4\\xC4\\xC1%s\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC1%\"\n                          \"s\\xC4\\xC4\\xC4\\xC4\\xB4\",\n                          s2, s2);\n      } else {\n        s1 = fmt::sprintf(\"+---+%s-----+---+%s----+\", s2, s2);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n\n      std::string padding61(61, ' ');\n      if (okansi()) {\n        s1 = fmt::sprintf(\"|#7\\xB3  |#2G|#7)|#1G-File Edit%s|#7\\xB3\", padding61);\n      } else {\n        s1 = fmt::sprintf(\"|  G)G-File Edit%s|\", padding61);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n      if (okansi()) {\n        s1 = fmt::sprintf(\"|#7\\xC0\\xC4\\xC4\\xC4\\xC4%\"\n                          \"s\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4%s|#\"\n                          \"1\\xFE|#7\\xC4|#2%s|#7\\xC4|#1\\xFE|#7\\xC4\\xC4\\xC4\\xD9\",\n                          s2, s7, t);\n      } else {\n        s1 = fmt::sprintf(\"+----%s----------------%so-%s-o---+\", s2, s7, t);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n    } else {\n      std::string s1;\n      if (okansi()) {\n        s1 = fmt::sprintf(\n            \"|#7\\xC0\\xC4\\xC4\\xC4\\xC1%\"\n            \"s\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n            \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4%s|#1\\xFE|#7\\xC4|#2%s|#7\\xC4|#1\\xFE|#7\\xC4\\xC4\\xC4\\xD9\",\n            s2, s3, t);\n      } else {\n        s1 = fmt::sprintf(\"+---+%s-----+---------------------+%so-%s-o---+\", s2, s3, t);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n    }\n  }\n  bout.ansic(0);\n  bout.nl();\n}\n\nstatic void list_gfiles(const gfile_dir_t& g) {\n  int i;\n  std::string s, s2, s3, s4, s5;\n  std::string lnum, rnum, lsize, rsize;\n  const auto t = times();\n\n  auto abort = false;\n  bout.cls();\n  bout.litebar(g.name);\n  auto i2 = 0;\n  if (okansi()) {\n    s2 = std::string(29, '\\xC4');\n    s3 = std::string(12, '\\xC4');\n  } else {\n    s2 = std::string(29, '-');\n    s3 = std::string(12, '-');\n  }\n  gfl_hdr(1);\n  const auto gfilesdir = a()->config()->gfilesdir();\n  for (i = 0; i < size_int(g.files) && !abort && !a()->sess().hangup(); i++) {\n    i2++;\n    lnum = std::to_string(i + 1);\n    s4 = trim_to_size_ignore_colors(g.files[i].description, 29);\n    if (const auto path_name = FilePath(gfilesdir, FilePath(g.filename, g.files[i].filename));\n        File::Exists(path_name)) {\n      File handle(path_name);\n      lsize = humanize(handle.length());\n    } else {\n      lsize = \"OFL\";\n    }\n    if (i + 1 >= size_int(g.files)) {\n      if (okansi()) {\n        rnum = std::string(3, '\\xFE');\n        s5 = std::string(29, '\\xFE');\n        rsize = std::string(4, '\\xFE');\n      } else {\n        rnum = std::string(3, 'o');\n        s5 = std::string(29, 'o');\n        rsize = std::string(4, 'o');\n      }\n    } else {\n      rnum = std::to_string(i + 2);\n      s5 = trim_to_size_ignore_colors(g.files[i + 1].description, 29);\n      const auto path_name2 =\n          FilePath(gfilesdir, FilePath(g.filename, g.files[i + 1].filename));\n      if (File::Exists(path_name2)) {\n        File handle(path_name2);\n        rsize = humanize(handle.length());\n      } else {\n        rsize = \"OFL\";\n      }\n    }\n    if (okansi()) {\n      s = fmt::sprintf(\"|#7\\xB3|#2%3s|#7\\xB3|#1%-29s|#7\\xB3|#2%4s|#7\\xB3|#2%3s|#7\\xB3|#1%-29s|#\"\n                       \"7\\xB3|#2%4s|#7\\xB3\",\n                       lnum, s4, lsize, rnum, s5, rsize);\n    } else {\n      s = fmt::sprintf(\"|%3s|%-29s|%4s|%3s|%-29s|%4s|\", lnum, s4, lsize, rnum, s5, rsize);\n    }\n    bout.bpla(s, &abort);\n    bout.ansic(0);\n    i++;\n    if (i2 > 10) {\n      i2 = 0;\n      std::string s1;\n      if (okansi()) {\n        s1 = fmt::sprintf(\"|#7\\xC3\\xC4\\xC4\\xC4X%sX\\xC4\\xC4\\xC4\\xC4X\\xC4\\xC4\\xC4X\\xC4%s|#1\\xFE|#\"\n                          \"7\\xC4|#2%s|#7\\xC4|#1\\xFE|#7\\xC4\\xFE\\xC4\\xC4\\xC4\\xC4\\xD9\",\n                          s2, s3, t);\n      } else {\n        s1 = fmt::sprintf(\"+---+%s+----+---+%s-o-%s-o-+----+\", s2, s3, t);\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n      bout.nl();\n      bout.pausescr();\n      gfl_hdr(1);\n    }\n  }\n  if (!abort) {\n    if (okansi()) {\n      s = fmt::sprintf(\"|#7\\xC3\\xC4\\xC4\\xC4\\xC1%s\\xC1\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC1%\"\n                       \"s\\xC1\\xC4\\xC4\\xC4\\xC4\\xB4\",\n                       s2, s2);\n    } else {\n      s = fmt::sprintf(\"+---+%s+----+---+%s+----+\", s2, s2);\n    }\n    bout.bpla(s, &abort);\n    bout.ansic(0);\n    if (so()) {\n      std::string s1 = okansi()\n        ? \"|#7\\xB3 |#1A|#7)|#2Add a G-File  |#1D|#7)|#2Download a G-file  |#1E|#7)|#2Edit this section  |#1R|#7)|#2Remove a G-File |#7\\xB3\"\n        : \"| A)Add a G-File  D)Download a G-file  E)Edit this section  R)Remove a G-File |\";\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n    } else {\n      std::string s1;\n      if (okansi()) {\n        s1 = StrCat(\"|#7\\xB3  |#2D  |#1Download a G-file\", std::string(55, ' '), \"|#7\\xB3\");\n      } else {\n        s1 = StrCat(\"|  D  Download a G-file\", std::string(55, ' '), \"|\");\n      }\n      bout.bpla(s1, &abort);\n      bout.ansic(0);\n    }\n  }\n  std::string s1;\n  if (okansi()) {\n    s1 = fmt::sprintf(\n        \"|#7\\xC0\\xC4\\xC4\\xC4\\xC4%s\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4%\"\n        \"s|#1\\xFE|#7\\xC4|#2%s|#7\\xC4|#1\\xFE|#7\\xC4\\xC4\\xC4\\xC4\\xD9\",\n        s2, s3, t);\n  } else {\n    s1 = fmt::sprintf(\"+----%s----------------%so-%s-o----+\",\n        s2, s3, t);\n  }\n  bout.bpla(s1, &abort);\n  bout.ansic(0);\n  bout.nl();\n}\n\nstatic void gfile_sec(int sn) {\n  int i, i1, i2;\n  bool abort;\n\n  const auto& section = a()->gfiles().dir(sn);\n  auto& g = a()->gfiles().dir(sn).files;\n  const auto nf = size_int(g);\n  std::set<char> odc;\n  for (i = 1; i <= nf / 10; i++) {\n    odc.insert(static_cast<char>(i + '0'));\n  }\n  list_gfiles(a()->gfiles().dir(sn));\n  bool done = false;\n  while (!done && !a()->sess().hangup()) {\n    a()->tleft(true);\n    bout.print(\"|#9Current G|#1-|#9File Section |#1: |#5{}\\r\\n|#0\\r\\n\", section.name);\n    bout.print(\"|#9Which G|#1-|#9File |#1(|#21|#1-|#2{}|#1), |#1(|#2Q|#1=|#9Quit|#1, \"\n               \"|#2?|#1=|#9Relist|#1) : |#5\",\n               size_int(g));\n    std::string ss = mmkey(odc);\n    i = to_number<int>(ss);\n    if (ss == \"Q\") {\n      done = true;\n    } else if (ss == \"E\" && so()) {\n      done = true;\n      gfiles3(sn);\n    }\n    if (ss == \"A\" && so()) {\n      fill_sec(sn);\n      g = a()->gfiles().dir(sn).files;\n      odc.clear();\n      for (i = 1; i <= nf / 10; i++) {\n        odc.insert(static_cast<char>(i + '0'));\n      }\n    } else if (ss == \"R\" && so()) {\n      bout.nl();\n      bout.outstr(\"|#2G-file number to delete? \");\n      std::string ss1 = mmkey(odc);\n      i = to_number<int>(ss1);\n      if (i > 0 && i <= nf) {\n        bout.print(\"|#9Remove {}|#1? |#5\", g[i - 1].description);\n        if (bin.yesno()) {\n          bout.outstr(\"|#5Erase file too? \");\n          if (bin.yesno()) {\n            const auto file_name = FilePath(section.filename, g[i - 1].filename);\n            File::Remove(FilePath(a()->config()->gfilesdir(), file_name));\n          }\n          erase_at(g, i-1);\n          a()->gfiles().Save();\n          bout.outstr(\"\\r\\nDeleted.\\r\\n\\n\");\n        }\n      }\n    } else if (ss == \"?\") {\n      list_gfiles(section);\n    } else if (ss == \"Q\") {\n      done = true;\n    } else if (i > 0 && i <= nf) {\n      auto file_name = FilePath(a()->config()->gfilesdir(),\n                                FilePath(section.filename, g[i - 1].filename));\n      i1 = bout.printfile_path(file_name);\n      a()->user()->gfiles_read(a()->user()->gfiles_read() + 1);\n      if (i1 == 0) {\n        sysoplog(fmt::format(\"Read G-file '{}'\", g[i - 1].filename));\n      }\n    } else if (ss == \"D\") {\n      bool done1 = false;\n      while (!done1 && !a()->sess().hangup()) {\n        bout.outstr(\"|#9Download which G|#1-|#9file |#1(|#2Q|#1=|#9Quit|#1, |#2?|#1=|#9Relist) : |#5\");\n        ss = mmkey(odc);\n        i2 = to_number<int>(ss);\n        abort = false;\n        if (ss == \"?\") {\n          list_gfiles(section);\n          bout.print(\"|#9Current G|#1-|#9File Section |#1: |#5{}\\r\\n\", section.name);\n        } else if (ss == \"Q\") {\n          list_gfiles(section);\n          done1 = true;\n        } else if (!abort) {\n          if (i2 > 0 && i2 <= nf) {\n            auto file_name = FilePath(section.filename, g[i2 - 1].filename);\n            File file(FilePath(a()->config()->datadir(), file_name));\n            if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n              bout.print(\"|#6File not found : [{}]\", file.full_pathname());\n            } else {\n              auto file_size = file.length();\n              file.Close();\n              bool sent = false;\n              abort = false;\n              send_file(file_name, &sent, &abort, g[i2 - 1].filename, -1, file_size);\n              std::string s1;\n              if (sent) {\n                s1 = fmt::format(\"|#2{} |#9successfully transferred|#1.|#0\\r\\n\", g[i2 - 1].filename);\n                done1 = true;\n              } else {\n                s1 = fmt::format(\"|#6\\xFE |#9Error transferring |#2{}|#1.|#0\", g[i2 - 1].filename);\n                done1 = true;\n              }\n              bout.nl();\n              bout.outstr(s1);\n              bout.nl();\n              sysoplog(s1);\n            }\n          } else {\n            done1 = true;\n          }\n        }\n      }\n    }\n  }\n}\n\nvoid gfiles2() {\n  write_inst(INST_LOC_GFILEEDIT, 0, INST_FLAGS_ONLINE);\n  sysoplog(\"@ Ran Gfile Edit\");\n  gfileedit();\n  gfiles();\n}\n\nvoid gfiles3(int n) {\n  write_inst(INST_LOC_GFILEEDIT, 0, INST_FLAGS_ONLINE);\n  sysoplog(\"@ Ran Gfile Edit\");\n  modify_sec(n);\n  gfile_sec(n);\n}\n\nvoid gfiles() {\n  std::vector<int> map;\n\n  bool done = false;\n  int nmap = 0;\n  int current_section = 0;\n  std::set<char> odc;\n  for (const auto& r : a()->gfiles().dirs()) {\n    if (wwiv::bbs::check_acs(r.acs)) {\n      map.push_back(current_section);\n      ++nmap;\n      if ((nmap % 10) == 0) {\n        odc.insert(static_cast<char>('0' + (nmap / 10)));\n      }\n    }\n    current_section++;\n  }\n  if (nmap == 0) {\n    bout.outstr(\"\\r\\nNo G-file sections available.\\r\\n\\n\");\n    return;\n  }\n  list_sec(map);\n  while (!done && !a()->sess().hangup()) {\n    a()->tleft(true);\n    bout.outstr(\"|#9G|#1-|#9Files Main Menu|#0\\r\\n\");\n    bout.print(\"|#9Which Section |#1(|#21|#1-|#2{}\"\n               \"|#1), |#1(|#2Q|#1=|#9Quit|#1, |#2?|#1=|#9Relist|#1) : |#5\",\n               nmap);\n    std::string ss = mmkey(odc);\n    if (ss == \"Q\") {\n      done = true;\n    } else if (ss == \"G\" && so()) {\n      done = true;\n      gfiles2();\n    } else if (ss == \"A\" && cs()) {\n      bool bIsSectionFull = false;\n      for (int i = 0; i < nmap && !bIsSectionFull; i++) {\n        bout.nl();\n        bout.print(\"Now loading files for {}\\r\\n\\r\\n\", a()->gfiles()[map[i]].name);\n        bIsSectionFull = fill_sec(map[i]);\n      }\n    } else {\n      if (int i = to_number<int>(ss); i > 0 && i <= nmap) {\n        gfile_sec(map[i-1]);\n      }\n    }\n    if (!done) {\n      list_sec(map);\n    }\n  }\n}\n"
  },
  {
    "path": "bbs/gfiles.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_GFILES_H__\n#define __INCLUDED_BBS_GFILES_H__\n\n#include \"sdk/vardec.h\"\n\nvoid gfiles();\n\n#endif  // __INCLUDED_BBS_GFILES_H__"
  },
  {
    "path": "bbs/hop.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/bbs.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/utility.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/files/dirs.h\"\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid HopSub() {\n  auto abort = false;\n  const auto nc = wwiv::stl::size_int(a()->uconfsub);\n\n  if (okansi()) {\n    bout.clear_whole_line();\n  } else {\n    bout.nl();\n  }\n  bout.outstr(\"|#9Enter name or partial name of sub to hop to:\\r\\n:\");\n  if (okansi()) {\n    bout.newline = false;\n  }\n  const auto partial = ToStringUpperCase(bin.input_text(40));\n  if (partial.empty()) {\n    return;\n  }\n  if (!okansi()) {\n    bout.nl();\n  }\n\n  auto c = 0;\n  const int oc = a()->sess().current_user_sub_conf_num();\n  const int os = a()->current_user_sub().subnum;\n\n  while (c < nc && !abort) {\n    if (okconf(a()->user())) {\n      setuconf(ConferenceType::CONF_SUBS, c, -1);\n    }\n    uint16_t i = 0;\n    while (i < a()->usub.size() && !abort) {\n      auto subname = ToStringUpperCase(a()->subs().sub(a()->usub[i].subnum).name);\n      if (subname.find(partial) != std::string::npos) {\n        if (okansi()) {\n          bout.clear_whole_line();\n        }\n        if (!okansi()) {\n          bout.nl();\n        }\n        bout.print(\"|#5Do you mean \\\"{}\\\" (Y/N/Q)? \", a()->subs().sub(a()->usub[i].subnum).name);\n        const auto ch = onek_ncr(\"QYN\\r\");\n        if (ch == 'Y') {\n          abort = true;\n          a()->set_current_user_sub_num(i);\n          break;\n        }\n        if (ch == 'Q') {\n          abort = true;\n          if (okconf(a()->user())) {\n            setuconf(ConferenceType::CONF_SUBS, oc, os);\n          }\n          break;\n        }\n      }\n      ++i;\n    }\n    c++;\n    if (!okconf(a()->user())) {\n      break;\n    }\n  }\n  if (okconf(a()->user()) && !abort) {\n    setuconf(ConferenceType::CONF_SUBS, oc, os);\n  }\n}\n\n\nvoid HopDir() {\n  bool abort = false;\n\n  const auto nc = wwiv::stl::size_int(a()->uconfdir);\n\n  if (okansi()) {\n    bout.clear_whole_line();\n  } else {\n    bout.nl();\n  }\n  bout.outstr(\"|#9Enter name or partial name of dir to hop to:\\r\\n:\");\n  if (okansi()) {\n    bout.newline = false;\n  }\n  const auto partial = ToStringUpperCase(bin.input_text(20));\n  if (partial.empty()) {\n    return;\n  }\n  if (!okansi()) {\n    bout.nl();\n  }\n\n  auto c = 0;\n  const auto oc = a()->sess().current_user_dir_conf_num();\n  const auto os = a()->current_user_dir().subnum;\n\n  while (c < nc && !abort) {\n    if (okconf(a()->user())) {\n      setuconf(ConferenceType::CONF_DIRS, c, -1);\n    }\n    for (const auto& udir : a()->udir) {\n      auto& dir = a()->dirs().dir(udir.subnum);\n      auto subname = ToStringUpperCase(dir.name);\n      if (subname.find(partial) != std::string::npos) {\n        if (okansi()) {\n          bout.clear_whole_line();\n        } else {\n          bout.nl();\n        }\n        bout.print(\"|#5Do you mean \\\"{}\\\" (Y/N/Q)? \", dir.name);\n        const auto ch = onek_ncr(\"QYN\\r\");\n        if (ch == 'Y') {\n          abort = true;\n          a()->set_current_user_dir_num(udir.subnum);\n          break;\n        }\n        if (ch == 'Q') {\n          abort = true;\n          if (okconf(a()->user())) {\n            setuconf(ConferenceType::CONF_DIRS, oc, os);\n          }\n          break;\n        }\n      }\n    }\n    c++;\n    if (!okconf(a()->user())) {\n      break;\n    }\n  }\n  if (okconf(a()->user()) && !abort) {\n    setuconf(ConferenceType::CONF_DIRS, oc, os);\n  }\n}\n\n\n"
  },
  {
    "path": "bbs/hop.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_HOP_H__\n#define __INCLUDED_BBS_HOP_H__\n\nvoid HopSub();\nvoid HopDir();\n\n#endif  // __INCLUDED_BBS_HOP_H__"
  },
  {
    "path": "bbs/inetmsg.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/inetmsg.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/email.h\"\n#include \"common/input.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/misccmd.h\"\n#include \"common/quote.h\"\n#include \"bbs/utility.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nbool check_inet_addr(const std::string& a) {\n  return !a.empty() && (contains(a, '@') && contains(a, '.'));\n}\n\nstd::string read_inet_addr(int user_number) {\n  if (!user_number) {\n    return {};\n  }\n\n  if (user_number == a()->user()->usernum()) {\n    if (check_inet_addr(a()->user()->email_address())) {\n      return  a()->user()->email_address();\n    }\n  } else if (auto user = a()->users()->readuser(user_number)) {\n    return user->email_address();\n  }\n  return {};\n}\n\n"
  },
  {
    "path": "bbs/inetmsg.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_INETMSG_H\n#define INCLUDED_BBS_INETMSG_H\n\n#include <string>\n\n/**\n * Minimal checks for email address validity. \n */\nbool check_inet_addr(const std::string& inetaddr);\n\n/**\n * Gets the email address from the user at user_number or an empty string\n * if the email address does not exist or is invalid.\n */\nstd::string read_inet_addr(int user_number);\nvoid send_inst_sysstr(int whichinst, const std::string& send_string);\n\n#endif  // INCLUDED_BBS_INETMSG_H"
  },
  {
    "path": "bbs/inmsg.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/inmsg.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsovl2.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/external_edit.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/utility.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"common/workspace.h\"\n#include \"core/datetime.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"fsed/fsed.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/net/networks.h\"\n#include <chrono>\n#include <sstream>\n#include <string>\n#include <vector>\n\nusing wwiv::common::InputMode;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic const char crlf[] = \"\\r\\n\";\n\nstatic bool GetMessageToName(MessageEditorData& data) {\n  // If a()->sess().GetCurrentReadMessageArea() is -1, then it hasn't been set by reading a sub,\n  // also, if we are using e-mail, this is definately NOT a FidoNet\n  // post so there's no reason in wasting everyone's time in the loop...\n  if (a()->sess().GetCurrentReadMessageArea() == -1 || data.is_email()) {\n    return false;\n  }\n\n  if (a()->current_sub().nets.empty()) {\n    return false;\n  }\n\n  const auto saved_newline = bout.newline;\n  for (const auto& xnp : a()->current_sub().nets) {\n    if (a()->nets()[xnp.net_num].type == network_type_t::ftn && !data.is_email()) {\n      bout.outstr(\"|#2To   : \");\n      bout.newline = false;\n      const auto to_name = bin.input_text(\"All\", 40);\n      bout.newline = saved_newline;\n      if (to_name.empty()) {\n        data.to_name = \"All\";\n        bout.outstr(\"|#4All\\r\\n\");\n        bout.ansic(0);\n      } else {\n        data.to_name = to_name;\n      }\n      return true;\n    }\n  }\n\n  return false;\n}\n\nstatic void GetMessageTitle(MessageEditorData& data) {\n  auto force_title = !data.title.empty();\n  if (okansi()) {\n    if (!data.silent_mode) {\n      bout.outstr(\"|#2Title: \");\n      bout.mpl(60);\n    }\n    if (!data.title.empty()) {\n      bout.outstr(data.title);\n      return;\n    }\n    auto irt = a()->sess().irt();\n    if (!irt.empty()) {\n      std::string s1;\n      auto ch = '\\0';\n      irt = stripcolors(StringTrim(a()->sess().irt()));\n      if (strncasecmp(irt.c_str(), \"re:\", 3) != 0) {\n        if (data.silent_mode) {\n          s1 = irt;\n          a()->sess().clear_irt();\n        } else {\n          s1 = StrCat(\"Re: \", irt);\n        }\n      } else {\n        s1 = a()->sess().irt();\n      }\n      if (s1.length() > 60) {\n        s1.resize(60);\n      }\n      if (!data.silent_mode && !force_title) {\n        bout.outstr(s1);\n        ch = bin.getkey();\n        if (ch == 10) {\n          ch = bin.getkey();\n        }\n      } else {\n        data.title.assign(s1);\n        ch = RETURN;\n      }\n      force_title = false;\n      if (ch != RETURN) {\n        bout.outstr(\"\\r\");\n        if (ch == SPACE || ch == ESC) {\n          ch = '\\0';\n        }\n        bout.outstr(\"|#2Title: \");\n        bout.mpl(60);\n        auto rollover_line = fmt::sprintf(\"%c\", ch);\n        inli(&s1, &rollover_line, 60, true, false);\n        data.title.assign(s1);\n      } else {\n        bout.nl();\n        data.title.assign(s1);\n      }\n    } else {\n      data.title = bin.input_text(60);\n    }\n  } else {\n    if (data.silent_mode || force_title) {\n      data.title = a()->sess().irt();\n    } else {\n      bout.outstr(\"       (---=----=----=----=----=----=----=----=----=----=----=----)\\r\\n\");\n      bout.outstr(\"Title: \");\n      data.title = bin.input_text(60);\n    }\n  }\n}\n\nstatic bool InternalMessageEditor(std::vector<std::string>& lin, int maxli, int* setanon, MessageEditorData& data) {\n  auto abort = false, next = false;\n  auto curli = 0;\n\n  bout.nl(2);\n  bout.print(\"|#9Enter message now, you can use |#2{}|#9 lines.\\r\\n\", maxli);\n  bout.outstr(\"|#9Colors: ^P-0\\003\"\"11\\003\"\"22\\003\"\"33\\003\"\"44\\003\"\"55\\003\"\"66\\003\"\"77\\003\"\"88\\003\"\"99\\003\"\"0\");\n  bout.nl();\n  bout.outstr(\"|#9Enter |#2/S|#9 at the start of a blank line to save your email.\\r\\n\");\n  bout.outstr(\"|#9Enter |#2/Q|#9 to quote previous message, |#2/HELP|#9 for other editor commands.\\r\\n\");\n\n  bout.ansic(7);\n  std::string header = \"[---=----=----=----=----=----=----=----]----=----=----=----=----=----=----=----]\";\n  if (a()->user()->screen_width() < 80) {\n    header.resize(a()->user()->screen_width());\n  }\n  bout.outstr(header);\n  bout.nl();\n\n  std::string current_line;\n  auto check_message_size = true;\n  auto save_message = false;\n  auto done = false;\n  std::string rollover_line;\n  std::vector<std::string> quoted_lines;\n  while (!done && !a()->sess().hangup()) {\n    while (inli(&current_line, &rollover_line, 160, true, (curli > 0))) {\n      // returning true means we back spaced past the current line.\n      // intuitive eh?\n      curli--;\n      if (curli >= 0) {\n        // Don't keep retreating past line 0.\n        rollover_line = lin.at(curli);\n        if (ssize(rollover_line) > a()->user()->screen_width() - 1) {\n          rollover_line.resize(a()->user()->screen_width() - 2);\n        }\n      } else {\n        curli = 0;\n      }\n    }\n    if (a()->sess().hangup()) {\n      done = true;\n    }\n    check_message_size = true;\n    if (current_line[0] == '/') {\n      auto cmd = ToStringUpperCase(current_line);\n      if (cmd == \"/HELP\" ||\n          cmd == \"/H\" ||\n          cmd == \"/?\") {\n        check_message_size = false;\n        bout.print_help_file(EDITOR_NOEXT);\n      } else if ((cmd == \"/QUOTE\") ||\n                 (cmd == \"/Q\")) {\n        check_message_size = false;\n        quoted_lines = query_quote_lines(a()->sess());\n\n        if (quoted_lines.empty()) {\n          bout.nl();          \n        }\n        for (const auto& ql  : quoted_lines) {\n          bout.bpla(ql, &abort);\n          if (curli == size_int(lin)) {\n            // we're inserting a new line at the end.\n            lin.emplace_back(ql);\n          } else if (curli < size_int(lin)) {\n            // replacing an older line.\n            lin.at(curli).assign(ql);\n          }\n          curli++;\n        } \n      } else if (cmd == \"/LI\") {\n        check_message_size = false;\n        abort = false;\n        for (auto i = 0; i < curli && !abort; i++) {\n          auto line = lin.at(i);\n          if (!line.empty() && line.back() == CA) {\n            line.pop_back();\n          }\n          if (!line.empty() && line.front() == CB) {\n            line = line.substr(1);\n            auto i5 = 0;\n            // TODO(rushfan): Make a utility function to do this in strings.h\n            for (auto i4 = 0; i4 < ssize(line); i4++) {\n              if (line[i4] == 8 || line[i4] == 3) {\n                --i5;\n              } else {\n                ++i5;\n              }\n            }\n            for (auto i4 = 0; (i4 < (a()->user()->screen_width() - i5) / 2) && (!abort); i4++) {\n              bout.outstr(\" \", &abort, &next);\n            }\n          }\n          bout.bpla(line, &abort);\n        }\n        if (!okansi() || next) {\n          bout.nl();\n          bout.outstr(\"Continue...\\r\\n\");\n        }\n      } else if (cmd == \"/ES\" ||\n                 cmd == \"/S\") {\n        save_message = true;\n        done = true;\n        check_message_size = false;\n      } else if (cmd == \"/ESY\" ||\n                 cmd == \"/SY\") {\n        save_message = true;\n        done = true;\n        check_message_size = false;\n        *setanon = 1;\n      } else if (cmd == \"/ESN\" ||\n                 cmd == \"/SN\") {\n        save_message = true;\n        done = true;\n        check_message_size = false;\n        *setanon = -1;\n      } else if (cmd == \"/ABT\" ||\n                 cmd == \"/A\") {\n        done = true;\n        check_message_size = false;\n      } else if (cmd == \"/CLR\") {\n        check_message_size = false;\n        curli = 0;\n        bout.outstr(\"Message cleared... Start over...\\r\\n\\n\");\n      } else if (cmd == \"/RL\") {\n        check_message_size = false;\n        if (curli) {\n          curli--;\n          bout.outstr(\"Replace:\\r\\n\");\n        } else {\n          bout.outstr(\"Nothing to replace.\\r\\n\");\n        }\n      } else if (cmd == \"/TI\") {\n        check_message_size = false;\n        bout.outstr(\"|#1Subj|#7: |#2\");\n        data.title = bin.input_text(60);\n        bout.outstr(\"Continue...\\r\\n\\n\");\n      }\n      if (cmd.length() > 3) {\n        cmd.resize(3);\n      }\n      if (cmd == \"/C:\") {\n        const auto centered_text = current_line.substr(3);\n        current_line = fmt::sprintf(\"%c%s\", CB, centered_text);\n      } else if (cmd == \"/SU\" && current_line[3] == '/' && curli > 0) {\n        auto old_string = current_line.substr(4);\n        auto slash = old_string.find('/');\n        if (slash != std::string::npos) {\n          auto new_string = old_string.substr(slash + 1);\n          old_string.resize(slash);\n          // We've already advanced curli to point to the new row, so we need\n          // to back up one.\n          auto last_line = curli - 1;\n          auto temp = lin.at(last_line);\n          StringReplace(&temp, old_string, new_string);\n          lin[last_line] = temp;\n          bout.print(\"Last line:\\r\\n{}\\r\\nContinue...\\r\\n\", lin.at(last_line));\n        }\n        check_message_size = false;\n      }\n    }\n\n    if (check_message_size) {\n      if (curli == size_int(lin)) {\n        // we're inserting a new line at the end.\n        lin.emplace_back(current_line);\n      } else if (curli < size_int(lin)) {\n        // replacing an older line.\n        lin.at(curli).assign(current_line);\n      }\n      // Since we added the line, let's move forward.\n      curli++;\n      if (curli == maxli + 1) {\n        bout.outstr(\"\\r\\n-= No more lines, last line lost =-\\r\\n/S to save\\r\\n\\n\");\n        curli--;\n      } else if (curli == maxli) {\n        bout.outstr(\"-= Message limit reached, /S to save =-\\r\\n\");\n      } else if (curli + 5 == maxli) {\n        bout.outstr(\"-= 5 lines left =-\\r\\n\");\n      }\n    }\n  }\n  if (curli == 0) {\n    save_message = false;\n  }\n  lin.resize(curli);\n  return save_message;\n}\n\n\nstatic void UpdateMessageBufferInReplyToInfo(std::ostringstream& ss, bool is_email, const std::string& to_name, const std::string& title) {\n  auto fido_addr_added{false};\n  if (!to_name.empty() && !is_email && !a()->current_sub().nets.empty()) {\n    for (const auto& xnp : a()->current_sub().nets) {\n      if (a()->nets()[xnp.net_num].type == network_type_t::ftn) {\n        const auto buf = fmt::sprintf(\"%c0FidoAddr: %s\", CD, to_name);\n        ss << buf << crlf;\n        fido_addr_added = true;\n        break;\n      }\n    }\n  }\n\n  if (!is_email) {\n    // I don't think either RE: or BY lines should show up in email messages.\n    // Also the message SDK only has support for adding them to subs, not emails too.\n    if (!to_name.empty() && !iequals(to_name, \"All\")) {\n      if (!title.empty() && title.front() != '\"' && !fido_addr_added) {\n      // Don't add RE: line if we have a \"^D0FidoAddr\" line.\n      ss << \"RE: \" << title << crlf;\n      }\n      ss << \"BY: \" << to_name << crlf;\n    }\n    // ss << crlf; // Do we really want this extra line?\n  }\n}\n\nstatic std::filesystem::path FindTagFileName() {\n  for (const auto& xnp : a()->current_sub().nets) {\n    const auto& nd = a()->nets()[xnp.net_num].dir;\n    auto filename = FilePath(nd, StrCat(xnp.stype, \".tag\"));\n    if (File::Exists(filename)) {\n      return filename;\n    }\n    filename = FilePath(nd, GENERAL_TAG);\n    if (File::Exists(filename)) {\n      return filename;\n    }\n    filename = FilePath(a()->config()->datadir(), StrCat(xnp.stype, \".tag\"));\n    if (File::Exists(filename)) {\n      return filename;\n    }\n    filename = FilePath(a()->config()->datadir(), GENERAL_TAG);\n    if (File::Exists(filename)) {\n      return filename;\n    }\n  }\n  return {};\n}\n\nstatic void UpdateMessageBufferTagLine(std::ostringstream& ss, bool is_email, const std::string& to_name) {\n  if (a()->subs().subs().empty() && a()->sess().GetCurrentReadMessageArea() <= 0) {\n    return;\n  }\n  if (is_email) {\n    return;\n  }\n  if (a()->current_sub().nets.empty()) {\n    return;\n  }\n  if (a()->current_sub().anony & anony_no_tag) {\n    return;\n  }\n  if (iequals(to_name, \"Multi-Mail\")) {\n    return;\n  }\n\n  const auto filename = FindTagFileName();\n  if (filename.empty()) {\n    // FindTagFileName returns an empty string if no tag name exists, so\n    // just exit here since there is no tag.\n    return;\n  }\n  TextFile file(filename, \"rb\");\n  if (file.IsOpen()) {\n    int j = 0;\n    std::string s;\n    do {\n      s.clear();\n      const auto line_read = file.ReadLine(&s);\n      if (line_read && s.length() > 1 && s[s.length() - 2] == RETURN) {\n        // remove last 2 characters.\n        s.pop_back();\n        s.pop_back();\n      }\n      auto s1 = s;\n      if (s[0] != CD) {\n        s1 = fmt::sprintf(\"%c%c%s\", CD, j + '2', s);\n      }\n      if (!j) {\n        ss << fmt::sprintf(\"%c1\", CD) << crlf;\n      }\n      ss << s1 << crlf;\n      if (j < 7) {\n        j++;\n      }\n    } while (!file.IsEndOfFile());\n    file.Close();\n  }\n}\n\nstatic void UpdateMessageBufferQuotesCtrlLines(std::ostringstream& ss) {\n  const auto quotes_filename = FilePath(a()->sess().dirs().temp_directory(), QUOTES_TXT);\n  TextFile file(quotes_filename, \"rt\");\n  if (file.IsOpen()) {\n    std::string quote_text;\n    while (file.ReadLine(&quote_text)) {\n      const auto slash_n = quote_text.find('\\n');\n      if (slash_n != std::string::npos) {\n        quote_text.resize(slash_n);\n      }\n      if (starts_with(quote_text, \"\\004\"\"0U\")) {\n        ss << quote_text << crlf;\n      }\n    }\n    file.Close();\n  }\n\n  const auto msginf_filename = FilePath(a()->sess().dirs().temp_directory(), \"msginf\");\n  File::Copy(quotes_filename, msginf_filename);\n}\n\nstatic void GetMessageAnonStatus(bool *real_name, uint8_t *anony, int setanon) {\n  // Changed *anony to anony\n  switch (*anony) {\n  case 0:\n    *anony = 0;\n    break;\n  case anony_enable_anony:\n    if (setanon) {\n      if (setanon == 1) {\n        *anony = anony_sender;\n      } else {\n        *anony = 0;\n      }\n    } else {\n      bout.Left(80);\n      bout.clreol();\n      bout.outstr(\"|#5Anonymous? \");\n      if (bin.yesno()) {\n        *anony = anony_sender;\n      } else {\n        *anony = 0;\n      }\n    }\n    break;\n  case anony_enable_dear_abby: {\n    bout.nl();\n    bout.print(\"1. {}\\r\\n\", a()->user()->name_and_number());\n    bout.outstr(\"2. Abby\\r\\n\");\n    bout.outstr(\"3. Problemed Person\\r\\n\\n\");\n    bout.outstr(\"|#5Which? \");\n    char chx = onek(\"\\r123\");\n    switch (chx) {\n    case '\\r':\n    case '1':\n      *anony = 0;\n      break;\n    case '2':\n      *anony = anony_sender_da;\n      break;\n    case '3':\n      *anony = anony_sender_pp;\n    }\n  }\n  break;\n  case anony_force_anony:\n    *anony = anony_sender;\n    break;\n  case anony_real_name:\n    *real_name = true;\n    *anony = 0;\n    break;\n  }\n}\n\nstatic std::string ostringstream_to_wwivtext(const std::ostringstream& b) {\n  auto text = b.str();\n  if (text.back() != CZ) {\n    text.push_back(CZ);\n  }\n  return text;\n}\n\nbool inmsg(MessageEditorData& data) {\n\n  const auto oiia = setiia(std::chrono::milliseconds(0));\n  if (data.fsed_flags != FsedFlags::NOFSED && !okfsed()) {\n    data.fsed_flags = FsedFlags::NOFSED;\n  }\n\n  const auto exted_filename = FilePath(a()->sess().dirs().temp_directory(), INPUT_MSG);\n  if (data.fsed_flags != FsedFlags::NOFSED) {\n    data.fsed_flags = FsedFlags::FSED;\n  }\n  if (use_workspace) {\n    if (!File::Exists(exted_filename)) {\n      use_workspace = false;\n    } else {\n      data.fsed_flags = FsedFlags::WORKSPACE;\n    }\n  }\n\n  auto at_exit = finally([=]() {\n    setiia(oiia);\n    // Might not need to do this anymore since quoting\n    // isn't so convoluted.\n    bin.charbufferpointer_ = 0;\n    bin.charbuffer[0] = '\\0';\n    clear_quotes(a()->sess());\n    File::Remove(exted_filename);\n  });\n\n  bout.nl();\n\n  if (data.to_name.empty()) {\n    if (GetMessageToName(data)) {\n      bout.nl();\n    }\n  } else {\n    bout.outstr(\"|#2To   : \");\n    bout.mpl(40);\n    bout.pl(data.to_name);\n  }\n\n  GetMessageTitle(data);\n  if (data.title.empty() && data.need_title) {\n    bout.outstr(\"|#6Aborted.\\r\\n\");\n    return false;\n  }\n\n  std::vector<std::string> lin;\n  int setanon = 0;\n  auto save_message = false;\n  auto maxli = GetMaxMessageLinesAllowed();\n  if (data.fsed_flags == FsedFlags::NOFSED) {   // Use Internal Message Editor\n    save_message = InternalMessageEditor(lin, maxli, &setanon, data);\n  } else if (data.fsed_flags == FsedFlags::FSED) {   // Use Full Screen Editor\n    if (ok_internal_fsed()) {\n      if (File::Exists(exted_filename)) {\n        // We have auto-quote or a file loaded into the workspace.\n        TextFile editor_file(exted_filename, \"r\");\n        lin = editor_file.ReadFileIntoVector();\n      }\n      save_message = wwiv::fsed::fsed(a()->context(), lin, maxli, data, false);\n    } else {\n      save_message = DoExternalMessageEditor(data, maxli, &setanon);\n      TextFile editor_file(exted_filename, \"r\");\n      lin = editor_file.ReadFileIntoVector();\n    }\n  } else if (data.fsed_flags == FsedFlags::WORKSPACE) { // \"auto-send mail message\"\n    use_workspace = false;\n    save_message = File::Exists(exted_filename);\n    if (save_message) {\n      if (!data.silent_mode) {\n        bout.outstr(\"Reading in file...\\r\\n\");\n      }\n      TextFile editor_file(exted_filename, \"r\");\n      lin = editor_file.ReadFileIntoVector();\n    }\n  }\n\n  if (!save_message) {\n    bout.outstr(\"|#6Aborted.\\r\\n\");\n    return false;\n  }\n  bout.backline();\n  if (!data.silent_mode) {\n    SpinPuts(\"Saving...\", 2);\n  }\n  std::ostringstream b;\n\n  auto real_name = false;\n  GetMessageAnonStatus(&real_name, &data.anonymous_flag, setanon);\n  // Add author name\n  if (real_name) {\n    b << a()->user()->real_name() << crlf;\n  } else if (data.silent_mode) {\n    b << a()->config()->sysop_name() << \" #1\" << crlf;\n  } else {\n    b << a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum) << crlf;\n  }\n\n  // Add date to message body\n  b << daten_to_wwivnet_time(daten_t_now()) << crlf;\n  UpdateMessageBufferQuotesCtrlLines(b);\n\n  if (!data.title.empty()) {\n    UpdateMessageBufferInReplyToInfo(b, data.is_email(), data.to_name, data.title);\n  }\n\n  // TODO(rushfan): This and the date above, etc. Will need to be transformed\n  // into structured data when moving to a proper message API.\n  //\n  // New in 5.x. Add PID to all message types. This will be for WWIV messages\n  // as well as FTN messages so we know the Program ID (WWIV) that created\n  // the message.\n  const auto control_d_zero = fmt::sprintf(\"%c0\", CD);\n  b << control_d_zero << \"PID: WWIV \" << full_version() << crlf;\n\n  // iterate through the lines in \"lin\" and append them to 'b'\n  for (const auto& l : lin) {\n    b << l << crlf;\n  }\n\n  if (a()->HasConfigFlag(OP_FLAGS_MSG_TAG)) {\n    UpdateMessageBufferTagLine(b, data.is_email(), data.to_name);\n  }\n\n  data.text = ostringstream_to_wwivtext(b);\n  return true;\n}\n"
  },
  {
    "path": "bbs/inmsg.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_INMSG_H__\n#define __INCLUDED_BBS_INMSG_H__\n\n#include \"bbs/external_edit.h\"\n#include \"common/message_editor_data.h\"\n\nbool inmsg(wwiv::common::MessageEditorData& data);\n\n#endif  // __INCLUDED_BBS_INMSG_H__"
  },
  {
    "path": "bbs/input_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/bbs_helper.h\"\n\nusing wwiv::sdk::User;\n\nclass InputTest : public ::testing::Test {\nprotected:\n  void SetUp() override {}\n};\n\nTEST_F(InputTest, Smoke) { \n}\n"
  },
  {
    "path": "bbs/instmsg.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/instmsg.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/datetime.h\"\n#include \"common/output.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/instance_message.h\"\n#include \"sdk/names.h\"\n\n#include <chrono>\n#include <string>\n\nusing std::chrono::seconds;\nusing std::chrono::steady_clock;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic bool chat_avail;\nstatic bool chat_invis;\n\nstatic steady_clock::time_point last_iia;\nstatic std::chrono::milliseconds iia;\n\nbool is_chat_invis() { \n  return chat_invis; \n}\n\nvoid send_inst_str(int whichinst, const std::string& s) {\n  send_instance_string(*a()->config(), instance_message_type_t::user, whichinst,\n                       a()->sess().user_num(), a()->sess().instance_number(), s);\n}\n\nvoid send_inst_sysstr(int whichinst, const std::string& s) {\n  send_instance_string(*a()->config(), instance_message_type_t::system, whichinst,\n                       a()->sess().user_num(), a()->sess().instance_number(), s);\n}\n\n/*\n * \"Broadcasts\" a message to all online instances.\n */\nvoid broadcast(const std::string& message) {\n  for (auto i = 1; i <= num_instances(); i++) {\n    if (i != a()->sess().instance_number() && a()->instances().at(i).available()) {\n      send_inst_str(i, message);\n    }\n  }\n}\n\n/*\n * Handles one inter-instance message, based on type, returns inter-instance\n * main type of the \"packet\".\n */\nstatic void handle_inst_msg(const instance_message_t& ih) {\n  if (a()->sess().hangup() || !a()->sess().IsUserOnline()) {\n    return;\n  }\n  const auto line = bout.SaveCurrentLine();\n  bout.nl(2);\n  if (a()->sess().in_chatroom()) {\n    bout.pl(ih.message);\n    bout.RestoreCurrentLine(line);\n    return;\n  }\n  if (ih.message_type == instance_message_type_t::system) {\n    const auto from_user_name = a()->names()->UserName(ih.from_user);\n    bout.printf(\"|#1%.12s (%d)|#0> |#2\", from_user_name, ih.from_instance);\n  } else {\n    bout.outstr(\"|#6[SYSTEM ANNOUNCEMENT] |#7> |#2\");\n  }\n  bout.pl(ih.message);\n  bout.nl();\n  bout.RestoreCurrentLine(line);\n}\n\nvoid process_inst_msgs() {\n  if (!inst_msg_waiting()) {\n    return;\n  }\n  last_iia = steady_clock::now();\n  const auto oiia = setiia(std::chrono::milliseconds(0));\n\n  // Handle semaphores\n  const auto sem_fnd = FilePath(a()->sess().dirs().scratch_directory(), \"*.wwiv\");\n  FindFiles ffs(sem_fnd, FindFiles::FindFilesType::files, FindFiles::WinNameType::long_name);\n  for (const auto& f : ffs) {\n   if (f.name == \"readuser.wwiv\") {\n     LOG(INFO) << \"Reread current user\";\n     File::Remove(FilePath(a()->sess().dirs().scratch_directory(), f.name));\n     a()->ReadCurrentUser();\n   }\n  }\n\n  auto messages = read_all_instance_messages(*a()->config(), a()->sess().instance_number(), 1000);\n  for (const auto& m : messages) {\n    handle_inst_msg(m);\n  }\n  setiia(oiia);\n}\n\n/*\n * Returns max instance number.\n */\nint num_instances() {\n  return a()->instances().size();\n}\n\n\n/*\n * Returns true if  user_number is online, and returns instance user is on in\n * wi, else returns false.\n */\nstd::optional<int> user_online(int user_number) {\n  for (auto i = 1; i <= wwiv::stl::size_int(a()->instances()); i++) {\n    if (i == a()->sess().instance_number()) {\n      continue;\n    }\n    if (const auto ir = a()->instances().at(i); ir.user_number() == user_number && ir.online()) {\n      return i;\n    }\n  }\n  return std::nullopt;\n}\n\n/*\n* Writes BBS location data to instance.dat, so other instances can see\n* some info about this instance.\n*/\nvoid write_inst(int loc, int subloc, int flags) {\n  static Instance ti(a()->config()->root_directory(), a()->config()->datadir(), a()->sess().instance_number());\n\n  auto re_write = false;\n  if (ti.user_number() == 0) {\n    const auto ir = a()->instances().at(a()->sess().instance_number());\n    ti.ir().user = static_cast<int16_t>(ir.user_number());\n    ti.ir().inst_started = daten_t_now();\n    re_write = true;\n  }\n\n  uint16_t cf = ti.ir().flags & (~(INST_FLAGS_ONLINE | INST_FLAGS_MSG_AVAIL));\n  if (a()->sess().IsUserOnline()) {\n    cf |= INST_FLAGS_ONLINE;\n    if (chat_invis) {\n      cf |= INST_FLAGS_INVIS;\n    }\n    if (!a()->user()->ignore_msgs()) {\n      switch (loc) {\n      case INST_LOC_MAIN:\n      case INST_LOC_XFER:\n      case INST_LOC_SUBS:\n      case INST_LOC_EMAIL:\n      case INST_LOC_CHATROOM:\n      case INST_LOC_RMAIL:\n        if (chat_avail) {\n          cf |= INST_FLAGS_MSG_AVAIL;\n        }\n        break;\n      default:\n        if (loc >= INST_LOC_CH1 && loc <= INST_LOC_CH10 && chat_avail) {\n          cf |= INST_FLAGS_MSG_AVAIL;\n        }\n        break;\n      }\n    }\n    if (const auto ms = static_cast<uint16_t>(a()->sess().using_modem() ? a()->modem_speed_ : 0); ti.modem_speed() != ms) {\n      ti.ir().modem_speed = ms;\n      re_write = true;\n    }\n  }\n  if (flags != INST_FLAGS_NONE) {\n    // set an option\n    ti.ir().flags |= flags;\n  }\n  if (ti.invisible() && !chat_invis) {\n    cf = 0;\n    if (ti.ir().flags & INST_FLAGS_ONLINE) {\n      cf |= INST_FLAGS_ONLINE;\n    }\n    if (ti.ir().flags & INST_FLAGS_MSG_AVAIL) {\n      cf |= INST_FLAGS_MSG_AVAIL;\n    }\n    re_write = true;\n  }\n  if (cf != ti.ir().flags) {\n    re_write = true;\n    ti.ir().flags = cf;\n  }\n  if (ti.ir().number != a()->sess().instance_number()) {\n    re_write = true;\n    ti.ir().number = static_cast<int16_t>(a()->sess().instance_number());\n  }\n  if (loc == INST_LOC_DOWN) {\n    re_write = true;\n  } else {\n    if (a()->sess().IsUserOnline()) {\n      if (ti.ir().user != a()->sess().user_num()) {\n        re_write = true;\n        if (a()->sess().user_num() > 0 && a()->sess().user_num() <= a()->config()->max_users()) {\n          ti.ir().user = static_cast<int16_t>(a()->sess().user_num());\n        }\n      }\n    }\n  }\n\n  if (ti.ir().subloc != static_cast<uint16_t>(subloc)) {\n    re_write = true;\n    ti.ir().subloc = static_cast<uint16_t>(subloc);\n  }\n  if (ti.ir().loc != static_cast<uint16_t>(loc)) {\n    re_write = true;\n    ti.ir().loc = static_cast<uint16_t>(loc);\n  }\n  const auto ti_chat_invis = ti.invisible();\n  const auto ti_msg_avail = (ti.ir().flags & INST_FLAGS_MSG_AVAIL) != 0;\n  if ((ti_chat_invis != chat_invis || ti_msg_avail != chat_avail) && ti.loc_code() != INST_LOC_WFC) {\n    re_write = true;\n  }\n  if (!re_write) {\n    return;\n  }\n\n  ti.ir().last_update = daten_t_now();\n  a()->instances().upsert(a()->sess().instance_number(), ti);\n}\n\n/*\n* Returns 1 if a message waiting for this instance, 0 otherwise.\n*/\nbool inst_msg_waiting() {\n  if (iia.count() == 0) return false;\n\n  const auto l = steady_clock::now();\n  if ((l - last_iia) < iia) {\n    return false;\n  }\n\n  if (File::ExistsWildcard(FilePath(a()->sess().dirs().scratch_directory(), \"msg*.json\"))) {\n    return true;\n  }\n\n  if (File::ExistsWildcard(FilePath(a()->sess().dirs().scratch_directory(), \"*.wwiv\"))) {\n    return true;\n  }\n\n  last_iia = l;\n  return false;\n}\n\n// Sets inter-instance availability on/off, for inter-instance messaging.\n// returns the old iia value.\nstd::chrono::milliseconds setiia(std::chrono::milliseconds poll_time) {\n  const auto oiia = iia;\n  iia = poll_time;\n  return oiia;\n}\n\n// Toggles user availability, called when ctrl-N is hit\n\nvoid toggle_avail() {\n\n  const auto line = bout.SaveCurrentLine();\n  chat_avail = !chat_avail;\n\n  bout.print(\"\\r\\nYou are now {}\\r\\n\\r\\n\", chat_avail ? \"available for chat.\" : \"not available for chat.\");\n  const auto loc = a()->instances().at(a()->sess().instance_number()).loc_code();\n  write_inst(loc, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n  bout.RestoreCurrentLine(line);\n}\n\n// Toggles invisibility, called when ctrl-L is hit by a sysop\n\nvoid toggle_invis() {\n  const auto line = bout.SaveCurrentLine();\n  chat_invis = !chat_invis;\n\n  bout.print(\"\\r\\nYou are now {}\\r\\n\\r\\n\", chat_invis ? \"invisible.\" : \"visible.\");\n  const auto loc = a()->instances().at(a()->sess().instance_number()).loc_code();\n  write_inst(loc, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n  bout.RestoreCurrentLine(line);\n}\n"
  },
  {
    "path": "bbs/instmsg.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_INSTMSG_H\n#define INCLUDED_INSTMSG_H\n\n#include <chrono>\n#include <optional>\n#include <string>\n#include \"sdk/instance.h\"\n\nconstexpr int INST_MSG_STRING = 1;  // A string to print out to the user\nconstexpr int UNUSED_INST_MSG_SHUTDOWN = 2;  // Hangs up, ends BBS execution\nconstexpr int INST_MSG_SYSMSG = 3;  // Message from the system, not a user\nconstexpr int UNUSED_INST_MSG_CLEANNET = 4;  // should call cleanup_net\nconstexpr int INST_MSG_CHAT = 6;  // External chat request\n\n/****************************************************************************/\n\n\n\n\nvoid send_inst_str(int whichinst, const std::string& send_string);\nvoid broadcast(const std::string& message);\nvoid process_inst_msgs();\nint  num_instances();\nstd::optional<int> user_online(int user_number);\nvoid write_inst(int loc, int subloc = 0, int flags = wwiv::sdk::INST_FLAGS_NONE);\nbool inst_msg_waiting();\nstd::chrono::milliseconds setiia(std::chrono::milliseconds poll_time);\nvoid toggle_invis();\nvoid toggle_avail();\nbool is_chat_invis();\n\n#endif\n\n"
  },
  {
    "path": "bbs/interpret.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/interpret.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl2.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/utility.h\"\n#include \"common/datetime.h\"\n#include \"common/macro_context.h\"\n#include \"common/output.h\"\n#include \"common/pipe_expr.h\"\n#include \"core/datetime.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/files/dirs.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n\nBbsMacroContext::BbsMacroContext(wwiv::common::Context* context,\n                                 wwiv::common::PipeEval& pipe_eval)\n  : MacroContext(context), pipe_eval_(pipe_eval) {}\n\nstd::string BbsMacroContext::interpret_macro_char(char ch) const {\n  if (!context_) {\n    return \"\";\n  }\n  if (!context_->mci_enabled()) {\n    return \"\";\n  }\n  try {\n    switch (ch) {\n    case '@':                               // Dir name\n      return context_->session_context().current_dir().name;\n    case '~':                               // Total mails/feed backs sent\n      return std::to_string(context_->u().email_sent() + context_->u().feedback_sent() +\n                       context_->u().email_net());\n    case '/':                               // Today's date\n      return fulldate();\n    case '%':                               // Time left today\n      return std::to_string(static_cast<int>(nsl() / 60));\n    case '#':                               // User's number\n      return std::to_string(context_->u().usernum());\n    case '$':                               // File points (UNUSED)\n      return \"0\"; //to_string(u().GetFilePoints());\n    case '*':                               // User reg num\n      return std::to_string(context_->u().wwiv_regnum());\n    case '-':                               // Aggravation points\n      return std::to_string(context_->u().ass_points());\n    case ':':                               // Sub number\n      return a()->current_user_sub().keys;\n    case ';':                               // Directory number\n      return a()->current_user_dir().keys;\n    case '!':                               // Built-in pause\n      bout.pausescr();\n      return \"\";\n    case '&':\n      return context_->u().ansi() ? \"ANSI\" : \"ASCII\";\n    case 'A':                               // User's age\n      return std::to_string(context_->u().age());\n    case 'a':                               // User's language\n      return context_->session_context().current_language();\n    case 'B':                               // User's birthday\n      return context_->u().birthday_mmddyy();\n    case 'b':                               // Minutes in bank\n      return std::to_string(context_->u().banktime_minutes());\n    case 'C':                               // User's city\n      return context_->u().city();\n    case 'c':                               // User's country\n      return context_->u().country();\n    case 'D':                               // Files downloaded\n      return std::to_string(context_->u().downloaded());\n    case 'd':                               // User's DSL\n      return std::to_string(context_->u().dsl());\n    case 'E':                               // E-mails sent\n      return std::to_string(context_->u().email_sent());\n    case 'e':                               // Net E-mails sent\n      return std::to_string(context_->u().email_net());\n    case 'F':\n      return std::to_string(context_->u().feedback_sent());\n    case 'f':                               // First time user called\n      return context_->u().firston();\n    case 'G':                               // Messages read\n      return std::to_string(context_->u().messages_read());\n    case 'g':                               // Gold\n      return std::to_string(context_->u().gold());\n    case 'I':                               // User's call sIgn\n      return context_->u().callsign();\n    case 'i':                               // Illegal log-ons\n      return std::to_string(context_->u().illegal_logons());\n    case 'J': {                             // Message conference\n      const int x = context_->session_context().current_user_sub_conf_num();\n      if (x < 0 || x >= wwiv::stl::ssize(a()->uconfsub)) {\n        return {};\n      }\n      return wwiv::stl::at(a()->uconfsub, x).conf_name;\n    }\n    case 'j': { // Transfer conference\n      const int x = a()->sess().current_user_dir_conf_num();\n      if (x < 0 || x >= wwiv::stl::ssize(a()->uconfdir)) {\n        return {};\n      }\n      return wwiv::stl::at(a()->uconfdir, x).conf_name;\n    }\n    case 'K':                               // Kb uploaded\n      return std::to_string(context_->u().uk());\n    case 'k':                               // Kb downloaded\n      return std::to_string(context_->u().dk());\n    case 'L':                               // Last call\n      return context_->u().laston();\n    case 'l':                               // Number of logons\n      return std::to_string(context_->u().logons());\n    case 'M':                               // Mail waiting\n      return std::to_string(context_->u().email_waiting());\n    case 'm':                               // Messages posted\n      return std::to_string(context_->u().messages_posted());\n    case 'N':                               // User's name\n      return context_->u().name();\n    case 'n':                               // Sysop's note\n      return context_->u().note();\n    case 'O':                               // Times on today\n      return std::to_string(context_->u().ontoday());\n    case 'o': {\n      // Time on today\n      const auto used_this_session =\n          (std::chrono::system_clock::now() - context_->session_context().system_logon_time());\n      const auto min_used = context_->u().timeon() + used_this_session;\n      return std::to_string(std::chrono::duration_cast<std::chrono::minutes>(min_used).count());\n    }\n    case 'P':                               // BBS phone\n      return (config_ == nullptr) ? \"\" : config_->system_phone();\n    case 'p':                               // User's phone\n      return context_->u().data_phone();\n    case 'R':                               // User's real name\n      return context_->u().real_name();\n    case 'r':                               // Last baud rate\n      return std::to_string(context_->u().last_bps());\n    case 'S':                               // User's SL\n      return std::to_string(context_->u().sl());\n    case 's':                               // User's street address\n      return context_->u().street();\n    case 'T':                               // User's sTate\n      return context_->u().state();\n    case 't':                               // Current time\n      return times();\n    case 'U':                               // Files uploaded\n      return std::to_string(context_->u().uploaded());\n    case 'u':  {                             // Current sub\n      if (const auto subnum = a()->current_user_sub().subnum;\n          subnum >= 0 && subnum < wwiv::stl::ssize(a()->subs())) {\n        return a()->subs().sub(subnum).name;\n      }\n      return {};\n    }\n    case 'W':                               // Total # of messages in sub\n      return std::to_string(a()->GetNumMessagesInCurrentMessageArea());\n    case 'X':                               // User's sex\n      return fmt::sprintf(\"%c\", context_->u().gender());\n    case 'Y':                               // Your BBS name\n      return config_ == nullptr ? \"\" : config_->system_name();\n    case 'y':                               // Computer type\n      return ctypes(context_->u().computer_type());\n    case 'Z':                               // User's zip code\n      return context_->u().zip_code();\n    case 'z':\n      return fmt::format(\"{:2.3f}\", context_->u().ratio());\n    default:\n      return {};\n    }\n      \n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught exception in interpret_macro_char(ch): '\" << ch << \"' :\" << e.what();\n  }\n  return {}; \n}\n\nwwiv::common::Interpreted BbsMacroContext::interpret_string(const std::string& s) const {\n  if (s.length() < 2) {\n    // We need at least 2 chars to be useful.\n    return s;\n  }\n  const auto code = s.front();\n  auto data = s.substr(1);\n  switch (code) {\n    case '@':\n      return interpret_macro_char(data.front());\n    case '[': {\n      // movement\n      const auto type = data.back();\n      data.pop_back();\n      wwiv::common::Interpreted res;\n      res.cmd = wwiv::common::interpreted_cmd_t::movement;\n      switch (type) {\n        case 'A': res.up = data.empty() ? 1 : to_number<int>(data); break;\n        case 'B': res.down = data.empty() ? 1 : to_number<int>(data); break;\n        case 'C': res.right = data.empty() ? 1 : to_number<int>(data); break;\n        case 'D': res.left = data.empty() ? 1 : to_number<int>(data); break;\n        case 'H': {\n          const auto semi = data.find(';');\n          if (data.empty() || semi == std::string::npos) {\n            return s;\n          }\n          const auto x = to_number<int>(data.substr(0, semi));\n          res.x = std::max<int>(0, x);\n          const auto y = to_number<int>(data.substr(semi + 1));\n          res.y = std::max<int>(0,y);\n          return res;\n        }\n        case 'J': {\n          res.cls = true;\n          return res;\n        }\n        case 'K': {\n          if (const auto ct = data.empty() ? 0 : to_number<int>(data); ct == 0) {\n            res.clreol = true;\n          } else if (ct == 1) {\n            res.clrbol = true;\n          } else if (ct == 2) {\n            res.clreol = true;\n            res.clrbol = true;\n          }\n          return res;\n        }\n        case 'N': { // NL\n          const auto ct = data.empty() ? 1 : to_number<int>(data);\n          res.nl = ct;\n          return res;\n        }\n        default:\n          return s;\n      }\n      return res;\n    }\n    default:   return {};\n  }\n}\n\nwwiv::common::Interpreted BbsMacroContext::evaluate_expression(const std::string& expr) const {\n  wwiv::common::Interpreted r{};\n  r.text = pipe_eval_.eval(expr);\n  r.needs_reinterpreting = true;\n  return r;\n}\n\nbool BbsMacroFilter::write(char c) {\n  if (pipe_ == pipe_type_t::macro) {\n    auto s = ctx_->interpret_macro_char(c);\n    for (const auto ch : s) {\n      chain_->write(ch);\n    }\n    return true;\n  }\n  // todo - handle expr and movement\n  if (pipe_ == pipe_type_t::pipe) {\n    if (c == '@') {\n      pipe_ = pipe_type_t::macro;\n      return true;\n    }\n    if (c == '{') {\n      pipe_ = pipe_type_t::expr;\n      return true;\n    }\n    if (c == '[') {\n      pipe_ = pipe_type_t::movement;\n      return true;\n    }\n    pipe_ = pipe_type_t::none;\n    chain_->write('|');\n    return chain_->write(c);\n  }\n  if (c == '|') {\n    pipe_ = pipe_type_t::pipe;\n    return true;\n  }\n  return chain_->write(c);\n}\n\nbool BbsMacroFilter::attr(uint8_t a) { \n  return chain_->attr(a);\n}\n\nvoid BbsMacroFilter::close() {\n  chain_->close();\n}\n"
  },
  {
    "path": "bbs/interpret.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_INTERPRET_H\n#define INCLUDED_BBS_INTERPRET_H\n\n#include \"common/macro_context.h\"\n#include \"sdk/ansi/ansi.h\"\n#include <string>\n\nnamespace wwiv::common {\nclass Context;\nclass PipeEval;\n}\n\nnamespace wwiv::sdk {\nclass Config;\n}\n\nclass BbsMacroContext final : public wwiv::common::MacroContext {\npublic:\n  BbsMacroContext(wwiv::common::Context* context, wwiv::common::PipeEval& pipe_eval);\n  ~BbsMacroContext() override = default;\n\n  // Interprets only a macro code.\n  [[nodiscard]] std::string interpret_macro_char(char c) const override;\n  // Interprets a macro, movement or command.\n  // Expects the leading '@', '{', or '[' to be present.\n  [[nodiscard]] wwiv::common::Interpreted interpret_string(const std::string&) const override;\n\n  [[nodiscard]] wwiv::common::Interpreted evaluate_expression(const std::string&) const override;\n\n  void set_config(wwiv::sdk::Config* config) { config_ = config; }\n\nprivate:\n  wwiv::sdk::Config* config_{nullptr};\n  // Not Owned\n  wwiv::common::PipeEval& pipe_eval_;\n};\n\nenum class pipe_type_t { none, pipe, macro, movement, expr };\nclass BbsMacroFilter final : public wwiv::sdk::ansi::AnsiFilter {\npublic:\n  BbsMacroFilter(AnsiFilter* chain, const wwiv::common::MacroContext* ctx)\n      : chain_(chain), ctx_(ctx) {}\n  bool write(char c) override;\n  bool attr(uint8_t a) override;\n  void close() override;\n\nprivate:\n  AnsiFilter* chain_;\n  const wwiv::common::MacroContext* ctx_;\n  pipe_type_t pipe_{pipe_type_t::none};\n};\n\n#endif\n"
  },
  {
    "path": "bbs/lilo.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/automsg.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/email.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/inetmsg.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/newuser.h\"\n#include \"bbs/readmail.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/trashcan.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/wqscn.h\"\n#include \"bbs/basic/basic.h\"\n#include \"bbs/menus/menusupp.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/net/networks.h\"\n\n#include <chrono>\n#include <limits>\n#include <memory>\n#include <string>\n\nusing std::chrono::duration;\nusing std::chrono::duration_cast;\nusing std::chrono::milliseconds;\nusing std::chrono::seconds;\nusing namespace wwiv::bbs::menus;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nstatic char g_szLastLoginDate[9];\n\n\nstatic void CleanUserInfo() {\n  if (okconf(a()->user()) && !a()->uconfsub.empty()) {\n    setuconf(ConferenceType::CONF_SUBS, a()->user()->subconf(), 0);\n    a()->sess().set_current_user_sub_conf_num(a()->user()->subconf());\n  } else {\n    a()->sess().set_current_user_sub_conf_num(0);    \n  }\n  if (okconf(a()->user()) && !a()->uconfdir.empty()) {\n    setuconf(ConferenceType::CONF_DIRS, a()->user()->dirconf(), 0);\n    a()->sess().set_current_user_dir_conf_num(a()->user()->dirconf());\n  } else {\n    a()->sess().set_current_user_dir_conf_num(0);    \n  }\n  if (a()->user()->subnum() > a()->config()->max_subs()) {\n    a()->user()->subnum(0);\n  }\n  if (a()->user()->dirnum() > a()->config()->max_dirs()) {\n    a()->user()->dirnum(0);\n  }\n  const auto last_subnum = a()->user()->subnum();\n  if (last_subnum < size_int(a()->usub)) {\n    a()->set_current_user_sub_num(last_subnum);\n  }\n  const auto last_dirnum = a()->user()->dirnum();\n  if (last_subnum < size_int(a()->udir)) {\n    a()->set_current_user_dir_num(last_dirnum);\n  }\n}\n  \nbool IsPhoneNumberUSAFormat(User *pUser) {\n  const auto country = pUser->country();\n  return country == \"USA\" || country == \"CAN\" || country == \"MEX\";\n}\n\nstatic int GetAnsiStatusAndShowWelcomeScreen() {\n  bout.print(\"\\r\\nWWIV {}\\r\\n\", full_version());\n  bout.pl(\"Copyright (c) 1998-2023, WWIV Software Services.\");\n  bout.pl(\"All Rights Reserved.\");\n\n  const auto ans = check_ansi();\n  if (ans > 0) {\n    a()->user()->set_flag(User::flag_ansi);\n    a()->user()->set_flag(User::status_color);\n  }\n  bout.nl();\n  if (!bout.printfile_random(WELCOME_NOEXT)) {\n    bout.printfile(WELCOME_NOEXT);\n  }\n  if (bout.curatr() != 7) {\n    bout.ResetColors();\n  }\n  return ans;\n}\n\nstatic uint16_t FindUserByRealName(const std::string& user_name) {\n  if (user_name.empty()) {\n    return 0;\n  }\n\n  bout.outstr(\"Searching...\");\n  auto abort = false;\n  auto current_count = 0;\n  for (const auto& n : a()->names()->names_vector()) {\n    if (a()->sess().hangup() || abort) { break; }\n    if (++current_count % 25 == 0) {\n      // changed from 15 since computers are faster now-a-days\n      bout.outstr(\".\");\n    }\n    const auto current_user = n.number;\n    a()->ReadCurrentUser(current_user);\n    \n    if (const auto temp_user_name = ToStringUpperCase(a()->user()->real_name());\n        temp_user_name == user_name && !a()->user()->deleted()) {\n      bout.print(\"|#5Do you mean {}? \", a()->names()->UserName(n.number));\n      if (bin.yesno()) {\n        return current_user;\n      }\n    }\n    bin.checka(&abort);\n  }\n  return 0;\n}\n\nstatic int ShowLoginAndGetUserNumber(const std::string& remote_username) {\n  bout.nl();\n  // bout.outstr(\"Enter number or name or 'NEW'\\r\\nNN: \");\n  bout.str(\"NN_PROMPT\");\n\n  std::string user_name;\n  if (remote_username.empty()) {\n    user_name = bin.input_upper(30);\n  } else {\n    bout.pl(remote_username);\n    user_name = remote_username;\n  }\n  StringTrim(&user_name);\n\n  Trashcan trashcan(*a()->config());\n  if (trashcan.IsTrashName(user_name)) {\n    LOG(INFO) << \"Trashcan name entered from IP: \" << bout.remoteIO()->remote_info().address\n              << \"; name: \" << user_name;\n    hang_it_up();\n    a()->Hangup();\n    return 0;\n  }\n\n  if (const auto user_number = finduser(user_name); user_number != 0) {\n    return user_number;\n  }\n  return FindUserByRealName(user_name);\n}\n\nstatic bool IsPhoneRequired() {\n  const IniFile ini(FilePath(a()->bbspath(), WWIV_INI),\n                    {StrCat(\"WWIV-\", a()->sess().instance_number()), INI_TAG});\n  if (ini.IsOpen() && ini.value<bool>(\"LOGON_PHONE\", false)) {\n    return true;\n  }\n  return false;\n}\n\nbool VerifyPhoneNumber() {\n  if (a()->user()->voice_phone().empty() || !IsPhoneNumberUSAFormat(a()->user()) || a()->user()->country().empty()) {\n    return true;\n  }\n\n  auto phone_number = bin.input_password(\"PH: ###-###-\", 4);\n  if (phone_number != a()->user()->voice_phone().substr(8)) {\n    if (phone_number.length() == 4 && phone_number[3] == '-') {\n      bout.outstr(\"\\r\\n!! Enter the LAST 4 DIGITS of your phone number ONLY !!\\r\\n\\n\");\n    }\n    return false;\n  }\n  return true;\n}\n\nstatic bool VerifyPassword(const std::string& remote_password) {\n  a()->UpdateTopScreen();\n\n  if (!remote_password.empty() && remote_password == a()->user()->password()) {\n    return true;\n  }\n\n  const auto password = bin.input_password(bout.lang().value(\"PW_PROMPT\"), 8);\n  return password == a()->user()->password();\n}\n\nstatic bool VerifySysopPassword() {\n  const auto password = bin.input_password(\"SY: \", 20);\n  return password == a()->config()->system_password();\n}\n\nstatic void DoFailedLoginAttempt() {\n  a()->user()->increment_illegal_logons();\n  a()->WriteCurrentUser();\n  bout.outstr(\"\\r\\n\\aILLEGAL LOGON\\a\\r\\n\\n\");\n\n  sysoplog(false, \"\");\n  sysoplog(false, fmt::format(\"### ILLEGAL LOGON for {}\", a()->user()->name_and_number()));\n  sysoplog(false, \"\");\n  a()->sess().user_num(0);\n}\n\nstatic void LeaveBadPasswordFeedback(int ans) {\n  auto at_exit = finally([] {\n    a()->sess().user_num(0);\n  });\n  \n  if (ans > 0) {\n    a()->user()->set_flag(User::flag_ansi);\n  } else {\n    a()->user()->clear_flag(User::flag_ansi);\n  }\n  bout.outstr(\"|#6Too many logon attempts!!\\r\\n\\n\");\n  bout.print(\"|#9Would you like to leave Feedback to {}? \", a()->config()->sysop_name());\n  if (!bin.yesno()) {\n    return;\n  }\n  bout.nl();\n  bout.outstr(\"What is your NAME or HANDLE? \");\n  const auto temp_name = bin.input_proper(\"\", 31);\n  if (temp_name.empty()) {\n    return;\n  }\n  bout.nl();\n  a()->sess().user_num(1);\n  a()->user()->set_name(temp_name);\n  a()->user()->macro(0, \"\");\n  a()->user()->macro(1, \"\");\n  a()->user()->macro(2, \"\");\n  a()->user()->sl(a()->config()->newuser_sl());\n  a()->user()->screen_width(80);\n  if (ans > 0) {\n    select_editor();\n  } else {\n    a()->user()->default_editor(0);\n  }\n  a()->user()->email_sent(0);\n  const auto save_allow_cc = a()->IsCarbonCopyEnabled();\n  a()->SetCarbonCopyEnabled(false);\n  const auto title = StrCat(\"** Illegal logon feedback from \", temp_name);\n  email(title, 1, 0, true, 0, true);\n  a()->SetCarbonCopyEnabled(save_allow_cc);\n  if (a()->user()->email_sent() > 0) {\n    ssm(1) << \"Check your mailbox.  Someone forgot their password again!\";\n  }\n}\n\nstatic void CheckCallRestrictions() {\n  if (a()->sess().user_num() > 0 && a()->user()->restrict_logon() &&\n      date() == a()->user()->laston() &&\n      a()->user()->ontoday() > 0) {\n    bout.nl();\n    bout.outstr(\"|#6Sorry, you can only logon once per day.\\r\\n\");\n    a()->Hangup();\n  }\n}\n\nstatic void logon_guest() {\n  a()->sess().SetUserOnline(true);\n  bout.nl(2);\n  input_ansistat();\n\n  bout.printfile(GUEST_NOEXT);\n  bout.pausescr();\n\n  std::string userName, reason;\n  auto count = 0;\n  do {\n    bout.outstr(\"\\r\\n|#5Enter your real name : \");\n    userName = bin.input_upper(25);\n    bout.outstr(\"\\r\\n|#5Purpose of your call?\\r\\n\");\n    reason = bin.input_text(79);\n    if (!userName.empty() && !reason.empty()) {\n      break;\n    }\n    count++;\n  } while (count < 3);\n\n  if (count >= 3) {\n    bout.printfile(REJECT_NOEXT);\n    ssm(1) << \"Guest Account failed to enter name and purpose\";\n    a()->Hangup();\n  } else {\n    ssm(1) << \"Guest Account accessed by \" << userName << \" on \" << times() << \" for\" << reason;\n  }\n}\n\nvoid getuser() {\n  // Reset the key timeout to 30 seconds while trying to log in a user.\n  auto at_exit = finally([] { a()->sess().okmacro(true); bin.reset_key_timeout(); });\n\n  a()->sess().okmacro(false);\n  // TODO(rushfan): uncomment this\n  //bout.set_logon_key_timeout();\n\n  // Let's set this to 0 here since we don't have a user yet.\n  a()->sess().user_num(0);\n  a()->sess().set_current_user_sub_conf_num(0);\n  a()->sess().set_current_user_dir_conf_num(0);\n  a()->sess().effective_sl(a()->config()->newuser_sl());\n  a()->user()->SetStatus(0);\n\n  const auto& ip = bout.remoteIO()->remote_info().address;\n  const auto& hostname = bout.remoteIO()->remote_info().address_name;\n  if (!ip.empty()) {\n    bout.print(\"Client Address: {} ({})\\r\\n\", hostname, ip);\n    bout.nl();\n  }\n  write_inst(INST_LOC_GETUSER, 0, INST_FLAGS_NONE);\n\n  int count = 0;\n  bool ok = false;\n\n  const auto ans = GetAnsiStatusAndShowWelcomeScreen();\n  auto first_time = true;\n  do {\n    std::string remote_username;\n    std::string remote_password;\n    if (first_time) {\n      remote_username = ToStringUpperCase(bout.remoteIO()->remote_info().username);\n      remote_password = ToStringUpperCase(bout.remoteIO()->remote_info().password);\n      first_time = false;\n    }\n    const auto usernum = ShowLoginAndGetUserNumber(remote_username);\n    if (usernum > 0) {\n      a()->sess().user_num(static_cast<uint16_t>(usernum));\n      a()->ReadCurrentUser();\n      read_qscn(a()->sess().user_num(), a()->sess().qsc, false);\n      if (const auto instance_number = user_online(a()->sess().user_num());\n          instance_number && a()->user()->sl() < 255) {\n        bout.print(\"\\r\\n|#6You are already online on instance {}!\\r\\n\\n\", instance_number.value());\n        continue;\n      }\n      ok = true;\n      if (a()->user()->guest_user()) {\n        logon_guest();\n      } else {\n        a()->sess().effective_sl(a()->config()->newuser_sl());\n        if (!VerifyPassword(remote_password)) {\n          ok = false;\n        }\n\n        if ((a()->config()->sysconfig_flags() & sysconfig_free_phone) == 0 && IsPhoneRequired()) {\n          if (!VerifyPhoneNumber()) {\n            ok = false;\n          }\n        }\n        if (a()->user()->sl() == 255 && a()->sess().incom() && ok) {\n          if (!VerifySysopPassword()) {\n            ok = false;\n          }\n        }\n      }\n      if (ok) {\n        a()->reset_effective_sl();\n        changedsl();\n      } else {\n        DoFailedLoginAttempt();\n      }\n    } else if (usernum == 0) {\n      bout.nl();\n      bout.outstr(\"|#6Unknown user.\\r\\n\");\n      a()->sess().user_num(static_cast<uint16_t>(usernum));\n    } else if (usernum == -1) {\n      write_inst(INST_LOC_NEWUSER, 0, INST_FLAGS_NONE);\n      play_sdf(NEWUSER_NOEXT, false);\n      newuser();\n      ok = true;\n    }\n  } while (!ok && ++count < 3);\n\n  if (count >= 3) {\n    LeaveBadPasswordFeedback(ans);\n  }\n\n  CheckCallRestrictions();\n  if (!ok) {\n    a()->Hangup();\n  }\n}\n\nstatic void FixUserLinesAndColors() {\n  if (a()->user()->GetNumExtended() > a()->max_extend_lines) {\n    a()->user()->SetNumExtended(a()->max_extend_lines);\n  }\n  if (a()->user()->raw_color(8) == 0 || a()->user()->raw_color(9) == 0) {\n    a()->user()->color(8, a()->newuser_colors[8]);\n    a()->user()->color(9, a()->newuser_colors[9]);\n  }\n\n  // Query screen size if mismatch.\n  if (detect_screensize()) {\n    a()->WriteCurrentUser();\n  }\n}\n\nstatic void UpdateUserStatsForLogin() {\n  to_char_array(g_szLastLoginDate, date());\n  if (a()->user()->laston() != g_szLastLoginDate) {\n    ResetTodayUserStats(a()->user());\n  }\n  AddCallToday(a()->user());\n  a()->set_current_user_sub_num(0);\n  a()->SetNumMessagesReadThisLogon(0);\n  const auto& udir = a()->udir;\n  if (udir.size() > 1 && udir[0].subnum == 0 && udir[1].subnum > 0) {\n    a()->set_current_user_dir_num(1);\n  } else {\n    a()->set_current_user_dir_num(0);\n  }\n  if (a()->sess().effective_sl() != 255 && !a()->user()->guest_user()) {\n    a()->status_manager()->Run([](Status& s) {\n      s.increment_caller_num();\n      s.increment_calls_today();\n    });\n  }\n}\n\nstatic void PrintLogonFile() {\n  if (!a()->sess().incom()) {\n    return;\n  }\n  play_sdf(LOGON_NOEXT, false);\n  if (!bout.printfile(LOGON_NOEXT)) {\n    bout.pausescr();\n  }\n}\n\nstatic void PrintUserSpecificFiles() {\n  const auto* user = a()->user();  // not-owned\n  bout.printfile(fmt::format(\"sl{}\", user->sl()));\n  bout.printfile(fmt::format(\"dsl{}\", user->dsl()));\n\n  const auto short_size = std::numeric_limits<uint16_t>::digits - 1;\n  for (auto i=0; i < short_size; i++) {\n    if (user->has_ar(1 << i)) {\n      bout.printfile(fmt::format(\"ar{}\", static_cast<char>('A' + i)));\n    }\n  }\n\n  for (auto i=0; i < short_size; i++) {\n    if (user->has_dar(1 << i)) {\n      bout.printfile(fmt::format(\"dar{}\", static_cast<char>('A' + i)));\n    }\n  }\n}\n\nstatic std::string CreateLastOnLogLine(const Status& status) {\n  std::string log_line;\n  if (a()->HasConfigFlag(OP_FLAGS_SHOW_CITY_ST) &&\n    a()->config()->newuser_config().use_address_city_state != newuser_item_type_t::unused) {\n    const std::string username_num = a()->user()->name_and_number();\n    const std::string t = times();\n    const std::string f = fulldate();\n    log_line = fmt::sprintf(\n      \"|#1%-6ld %-25.25s %-5.5s %-5.5s %-15.15s %-2.2s %-3.3s %-8.8s %2d\\r\\n\",\n      status.caller_num(),\n      username_num,\n      t,\n      f,\n      a()->user()->city(),\n      a()->user()->state(),\n      a()->user()->country(),\n      a()->GetCurrentSpeed(),\n      a()->user()->ontoday());\n  } else {\n    const auto username_num = a()->user()->name_and_number();\n    const auto t = times();\n    const auto f = fulldate();\n    log_line = fmt::sprintf(\"|#1%-6ld %-25.25s %-10.10s %-5.5s %-5.5s %-20.20s %2d\\r\\n\",\n                            status.caller_num(), username_num, a()->sess().current_language(),\n                            t, f, a()->GetCurrentSpeed(), a()->user()->ontoday());\n  }\n  return log_line;\n}\n\n\nstatic void UpdateLastOnFile() {\n  const auto laston_txt_filename = FilePath(a()->config()->gfilesdir(), LASTON_TXT);\n  std::vector<std::string> lines;\n  {\n    TextFile laston_file(laston_txt_filename, \"r\");\n    lines = laston_file.ReadFileIntoVector();\n  }\n\n\n  auto status = a()->status_manager()->get_status();\n  {\n    const auto username_num = a()->user()->name_and_number();\n    auto t = times();\n    auto f = fulldate();\n    const auto sysop_log_line = fmt::sprintf(\"%ld: %s %s %s   %s - %d (%u)\",\n                                             status->caller_num(),\n                                             username_num,\n                                             t,\n                                             f,\n                                             a()->GetCurrentSpeed(),\n                                             a()->user()->ontoday(),\n                                             a()->sess().instance_number());\n    sysoplog(false, \"\");\n    sysoplog(false, stripcolors(sysop_log_line));\n    sysoplog(false, \"\");\n  }\n  if (a()->sess().incom()) {\n    const auto& remote_address = bout.remoteIO()->remote_info().address;\n    if (!remote_address.empty()) {\n      sysoplog(fmt::format(\"Remote IP: {}\", remote_address));\n    }\n  }\n  if (a()->sess().effective_sl() == 255 && !a()->sess().incom()) {\n    return;\n  }\n\n  // add line to laston.txt. We keep 8 lines\n  if (a()->sess().effective_sl() != 255) {\n    TextFile lastonFile(laston_txt_filename, \"w\");\n    if (lastonFile.IsOpen()) {\n      auto it = lines.begin();\n      // skip over any lines over 7\n      while (lines.size() - std::distance(lines.begin(), it) >= 8) {\n        ++it;\n      }\n      while (it != lines.end()) {\n        lastonFile.WriteLine(*it++);\n      }\n      lastonFile.Write(CreateLastOnLogLine(*status));\n      lastonFile.Close();\n    }\n  }\n}\n\nstatic std::string process_net_log_line(const std::string& line) {\n  const auto date = StringTrim(line.substr(0, 8));\n  const auto time = StringTrim(line.substr(9, 8));\n  const auto node = StringTrim(line.substr(21, 5));\n  const auto sent = StringTrim(line.substr(30, 5));\n  const auto recd = StringTrim(line.substr(39, 5));\n  const auto net_name = StringTrim(line.substr(64));\n\n  const auto& net = a()->nets().at(net_name);\n  auto b = BbsListNet::ReadBbsDataNet(net.dir);\n  std::string bbs_node_name = \"Unknown\";\n  if (auto o = b.node_config_for(to_number<int>(node))) {\n    bbs_node_name = o.value().name;\n  }\n\n  const auto bbs_node_network = StrCat(node, \".\", StringTrim(net.name));\n  return fmt::format(\"|#1{:<11} {:<11} {:<7} {:<7} @{:<15} {}\", date, time, sent, recd, bbs_node_network,\n                     bbs_node_name);\n}\n\n\nstatic void DisplayLastNetInfo() {\n  const auto net_log_filename = FilePath(a()->config()->gfilesdir(), NET_LOG);\n  TextFile nlf(net_log_filename, \"rt\");\n  if (!nlf) {\n    return;\n  }\n  std::vector<std::string> lines;\n  for (const auto& line : nlf.ReadLastLinesIntoVector(6)) {\n    lines.emplace_back(process_net_log_line(line));\n  }\n  if (lines.empty()) {\n    return;\n  }\n  bout.nl(2);\n  bout.outstr(\"|#5                      Most Recent Network Activity|#0\");\n  bout.nl(2);\n  bout.pl(\"|#2  Date        Time      Sent    Recd    Connection       BBS\");\n  const auto bar = okansi() ? static_cast<char>('\\xCD') : '=';\n  bout.print(\"|#7{}\\r\\n\", std::string(79, bar));\n  for (const auto& line : lines) {\n    bout.pl(line);\n    if (bin.checka()) {\n      break;\n    }\n  }\n  bout.nl(2);\n  bout.pausescr();\n}\n\nstatic void CheckAndUpdateUserInfo() {\n  const auto& nc = a()->config()->newuser_config();\n\n  if (nc.use_birthday == newuser_item_type_t::required && a()->user()->birthday_year() == 0) {\n    bout.outstr(\"\\r\\nPlease enter the following information:\\r\\n\");\n    do {\n      bout.nl();\n      input_age(a()->user());\n      bout.nl();\n      bout.print(\"{} -- Correct? \", a()->user()->birthday_mmddyy());\n      if (!bin.yesno()) {\n        a()->user()->birthday_mdy(0, 0, 0);\n      }\n    } while (a()->user()->birthday_year() == 0);\n  }\n\n  if (nc.use_real_name == newuser_item_type_t::required && a()->user()->real_name().empty()) {\n    input_realname();\n  }\n  if (nc.use_address_country == newuser_item_type_t::required && a()->user()->country().empty()) {\n    input_country();\n  }\n  if (nc.use_address_zipcode == newuser_item_type_t::required && a()->user()->zip_code().empty()) {\n    input_zipcode();\n  }\n  if (nc.use_address_street == newuser_item_type_t::required && a()->user()->street().empty()) {\n    input_street();\n  }\n  if (nc.use_address_city_state == newuser_item_type_t::required && a()->user()->city().empty()) {\n    input_city();\n  }\n  if (nc.use_address_city_state == newuser_item_type_t::required && a()->user()->state().empty()) {\n    input_state();\n  }\n  if (nc.use_data_phone == newuser_item_type_t::required && a()->user()->data_phone().empty()) {\n    input_dataphone();\n  }\n  if (nc.use_computer_type == newuser_item_type_t::required && a()->user()->computer_type() == -1) {\n    input_comptype();\n  }\n}\n\nstatic void DisplayUserLoginInformation() {\n  bout.nl();\n\n  const auto username_num = a()->user()->name_and_number();\n  bout.print(\"|#9Name/Handle|#0....... |#2{}\\r\\n\", username_num);\n  bout.outstr(\"|#9Internet Address|#0.. |#2\");\n  if (check_inet_addr(a()->user()->email_address())) {\n    bout.pl(a()->user()->email_address());\n  } else {\n    bout.outstr(\"None.\\r\\n\");\n  }\n  if (const auto la = a()->user()->last_address(); !la.empty()) {\n    bout.print(\"|#9Last IP Address|#0... |#2{}\\r\\n\", la.to_string());\n  }\n\n  bout.print(\"|#9Time allowed on|#0... |#2{}\\r\\n\", (nsl() + 30) / SECONDS_PER_MINUTE);\n  if (a()->user()->illegal_logons() > 0) {\n    bout.print(\"|#9Illegal logons|#0.... |#2{}\\r\\n\", a()->user()->illegal_logons());\n  }\n  if (a()->user()->email_waiting() > 0) {\n    bout.print(\"|#9Mail waiting|#0...... |#2{}\\r\\n\", a()->user()->email_waiting());\n  }\n  if (a()->user()->ontoday() == 1) {\n    bout.print(\"|#9Date last on|#0...... |#2{}\\r\\n\", a()->user()->laston());\n  } else {\n    bout.print(\"|#9Times on today|#0.... |#2{}\\r\\n\", a()->user()->ontoday());\n  }\n  bout.print(\"|#9Sysop currently|#0... |#2{}\\r\\n\", (sysop2() ? \"Available\" : \"NOT Available\"));\n  bout.print(\"|#9System is|#0......... |#2WWIV {}\\r\\n\", full_version());\n\n  /////////////////////////////////////////////////////////////////////////\n  a()->status_manager()->reload_status();\n  const auto screen_width = a()->user()->screen_width() - 19;\n  int width = 0;\n  bout.outstr(\"|#9Networks|#0.......... \");\n  for (const auto& n : a()->nets().networks()) {\n    const auto s = to_string(n);\n    const auto len = size_without_colors(s);\n    if (width + len >= screen_width) {\n      bout.nl();\n      bout.outstr(\"|#0.................. \");\n      width = 0;\n    }\n    bout.outstr(s);\n    width += len;\n  }\n  bout.nl();\n\n  bout.print(\"|#9Host OS|#0........... |#2{}\\r\\n\", os_version_string());\n  bout.print(\"|#9Instance|#0.......... |#2{}\\r\\n\\r\\n\", a()->sess().instance_number());\n  if (a()->user()->forward_usernum()) {\n    if (a()->user()->forward_systemnum() != 0) {\n      set_net_num(a()->user()->forward_netnum());\n      if (!valid_system(a()->user()->forward_systemnum())) {\n        a()->user()->clear_mailbox_forward();\n        bout.outstr(\"Forwarded to unknown system; forwarding reset.\\r\\n\");\n      } else {\n        bout.outstr(\"Mail set to be forwarded to \");\n        if (wwiv::stl::ssize(a()->nets()) > 1) {\n          bout.print(\"#{} @{}.{}.\\r\\n\", a()->user()->forward_usernum(),\n                     a()->user()->forward_systemnum(), a()->network_name());\n        } else {\n          bout.print(\"#{} @{}.\\r\\n\", a()->user()->forward_usernum(),\n                     a()->user()->forward_systemnum());\n        }\n      }\n    } else {\n      if (a()->user()->mailbox_closed()) {\n        bout.outstr(\"Your mailbox is closed.\\r\\n\\n\");\n      } else {\n        bout.print(\"Mail set to be forwarded to #{}\\r\\n\", a()->user()->forward_usernum());\n      }\n    }\n  } else if (a()->user()->forward_systemnum() != 0) {\n    const auto internet_addr = read_inet_addr(a()->sess().user_num());\n    bout.print(\"Mail forwarded to Internet {}.\\r\\n\", internet_addr);\n  }\n  if (a()->sess().IsTimeOnlineLimited()) {\n    bout.outstr(\"\\r\\n|#3Your on-line time is limited by an external event.\\r\\n\\n\");\n  }\n}\n\nstatic void LoginCheckForNewMail() {\n  bout.outstr(\"|#9Scanning for new mail... \");\n  if (a()->user()->email_waiting() > 0) {\n    const auto messages = check_new_mail(a()->sess().user_num());\n    if (messages) {\n      bout.print(\"|#9You have |#2{}|#9 new message(s).\\r\\n\\r\\n|#9Read your mail now? \", messages);\n      if (bin.noyes()) {\n        readmail(true);\n      }\n    } else {\n      bout.print(\"|#9You have |#2{}|#9 old message(s) in your mailbox.\\r\\n\",\n                 a()->user()->email_waiting());\n    }\n  } else {\n    bout.outstr(\" |#9No mail found.\\r\\n\");\n  }\n}\n\nstatic std::vector<bool> read_voting() {\n  DataFile<votingrec> file(FilePath(a()->config()->datadir(), VOTING_DAT));\n  std::vector<bool> questused(20);\n  if (!file) {\n    return questused;\n  }\n  std::vector<votingrec> votes;\n  file.ReadVector(votes);\n  int cur = 0;\n  for (const auto& v : votes) {\n    if (v.numanswers != 0) {\n      questused[cur] = true;\n    }\n    ++cur;\n  }\n  return questused;\n}\n\nstatic void CheckUserForVotingBooth() {\n  auto questused = read_voting();\n  if (!a()->user()->restrict_vote() && a()->sess().effective_sl() >= a()->config()->validated_sl()) {\n    for (int i = 0; i < 20; i++) {\n      if (questused[i] && a()->user()->votes(i) == 0) {\n        bout.nl();\n        bout.outstr(\"|#9You haven't voted yet.\\r\\n\");\n        return;\n      }\n    }\n  }\n}\n\n// Updates the User::last_address field since we've already displayed\n// it to the user from the last session.\nstatic void UpdateLastAddress() {\n  if (!a()->sess().incom()) {\n    return;\n  }\n  const auto remote_address = bout.remoteIO()->remote_info().address;\n  if (remote_address.empty()) {\n    return;\n  }\n  if (auto ipaddr = ip_address::from_string(remote_address)) {\n    a()->user()->last_address(ipaddr.value());\n  }\n}\n\nvoid logon() {\n  if (a()->sess().user_num() < 1) {\n    LOG(ERROR) << \"Tried to logon user number < 1\";\n    a()->Hangup();\n    return;\n  }\n  a()->sess().SetUserOnline(true);\n  write_inst(INST_LOC_LOGON, 0, INST_FLAGS_NONE);\n  bout.ResetColors();\n\n  FixUserLinesAndColors();\n  UpdateUserStatsForLogin();\n\n  PrintLogonFile();\n  LastCallers();\n  UpdateLastOnFile();\n\n  if (a()->config()->toggles().lastnet_at_logon) {\n    DisplayLastNetInfo();  // Morgul Added\n  }\n  PrintUserSpecificFiles();\n\n  read_automessage();\n  a()->sess().SetLogonTime();\n  a()->UpdateTopScreen();\n  bout.nl(2);\n  bout.pausescr();\n  if (!a()->logon_cmd.empty()) {\n    bout.nl();\n    wwiv::bbs::CommandLine cl(a()->logon_cmd);\n    cl.args(create_chain_file());\n    ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_LOGON));\n    bout.nl(2);\n  }\n\n  DisplayUserLoginInformation();\n  UpdateLastAddress();\n\n  CheckAndUpdateUserInfo();\n\n  a()->UpdateTopScreen();\n  a()->read_subs();\n  rsm(a()->sess().user_num(), a()->user(), true);\n\n  LoginCheckForNewMail();\n\n  if (a()->user()->nscan_daten()) {\n    a()->sess().nscandate(a()->user()->nscan_daten());\n  } else {\n    a()->sess().nscandate(a()->user()->last_daten());\n  }\n  a()->batch().clear();\n\n  CheckUserForVotingBooth();\n\n  if ((a()->sess().incom() || sysop1()) && a()->user()->sl() < 255) {\n    broadcast(fmt::format(\"{} Just logged on!\", a()->user()->name()));\n  }\n  setiia(std::chrono::seconds(5));\n\n  // New Message Scan\n  auto done_newscan_all = false;\n  if (a()->IsNewScanAtLogin()) {\n    bout.outstr(\"\\r\\n|#5Scan All Message Areas For New Messages? \");\n    if (bin.yesno()) {\n      wwiv::bbs::menus::NewMsgsAllConfs();\n      done_newscan_all = true;\n    }\n  }\n\n  // Handle case of first conf with no subs avail\n  if (a()->usub.empty() && okconf(a()->user())) {\n    for (auto confnum = 0; confnum < size_int(a()->uconfsub) && a()->usub.empty(); confnum++) {\n      setuconf(ConferenceType::CONF_SUBS, confnum, -1);\n      a()->sess().set_current_user_sub_conf_num(confnum);\n    }\n  }\n\n  if (a()->HasConfigFlag(OP_FLAGS_USE_FORCESCAN) && !done_newscan_all) {\n    auto nextsub = false;\n    if (a()->user()->sl() < 255) {\n      a()->sess().forcescansub(true);\n      qscan(a()->GetForcedReadSubNumber(), nextsub);\n      a()->sess().forcescansub(false);\n    } else {\n      qscan(a()->GetForcedReadSubNumber(), nextsub);\n    }\n  }\n  CleanUserInfo();\n}\n\nvoid logoff() {\n  VLOG(1) << \"logoff()\";\n  mailrec m{};\n\n  if (a()->sess().incom()) {\n    play_sdf(LOGOFF_NOEXT, false);\n  }\n\n  if (a()->sess().user_num() > 0) {\n    if ((a()->sess().incom() || sysop1()) && a()->user()->sl() < 255) {\n      broadcast(fmt::format(\"{} Just logged off!\", a()->user()->name()));\n    }\n  }\n  setiia(std::chrono::seconds(5));\n  if (!bout.remoteIO()->disconnect()) {\n    LOG(WARNING) << \"remoteIO->disconnect() returned false.\";\n  }\n  // Don't need hangup here, but *do* want to ensure that a()->sess().hangup() is true.\n  a()->sess().hangup(true);\n  VLOG(1) << \"Setting a()->sess().hangup()=true in logoff\";\n  if (a()->sess().user_num() < 1) {\n    return;\n  }\n\n  std::string text = \"  Logged Off At \";\n  text += times();\n  if (a()->sess().effective_sl() != 255 || a()->sess().incom()) {\n    sysoplog(false, \"\");\n    sysoplog(false, stripcolors(text));\n  }\n  a()->user()->last_bps(a()->modem_speed_);\n\n  // put this back here where it belongs... (not sure why it te\n  a()->user()->laston(g_szLastLoginDate);\n\n  a()->user()->illegal_logons(0);\n  const auto seconds_used_duration = duration_cast<seconds>(\n      std::chrono::system_clock::now() - a()->sess().system_logon_time() - a()->extratimecall());\n  a()->user()->add_timeon(seconds_used_duration);\n  a()->user()->add_timeon_today(seconds_used_duration);\n\n  a()->status_manager()->Run([=](Status& s) {\n    const int active_today = s.active_today_minutes();\n    const auto minutes_used_now = std::chrono::duration_cast<std::chrono::minutes>(seconds_used_duration).count();\n    s.active_today_minutes(active_today + minutes_used_now);\n  });\n\n  if (a()->sess().scanned_files()) {\n    a()->user()->nscan_daten(a()->user()->last_daten());\n  }\n  a()->user()->last_daten(daten_t_now());\n  const auto used_this_session = (std::chrono::system_clock::now() - a()->sess().system_logon_time());\n  const auto min_used = std::chrono::duration_cast<std::chrono::minutes>(used_this_session);\n  sysoplog(false, fmt::format(\"Read: {}   Time on: {} minutes.\", a()->GetNumMessagesReadThisLogon(),\n                              min_used.count()));\n  {\n    if (auto file_email(OpenEmailFile(true)); file_email->IsOpen()) {\n      a()->user()->email_waiting(0);\n      const auto num_records = static_cast<int>(file_email->length() / sizeof(mailrec));\n      auto r = 0;\n      auto w = 0;\n      while (r < num_records) {\n        file_email->Seek(static_cast<long>(sizeof(mailrec)) * static_cast<long>(r), File::Whence::begin);\n        file_email->Read(&m, sizeof(mailrec));\n        if (m.tosys != 0 || m.touser != 0) {\n          if (m.tosys == 0 && m.touser == a()->sess().user_num()) {\n            if (a()->user()->email_waiting() != 255) {\n              a()->user()->email_waiting(a()->user()->email_waiting() + 1);\n            }\n          }\n          if (r != w) {\n            file_email->Seek(static_cast<long>(sizeof(mailrec)) * static_cast<long>(w), File::Whence::begin);\n            file_email->Write(&m, sizeof(mailrec));\n          }\n          ++w;\n        }\n        ++r;\n      }\n      if (r != w) {\n        m.tosys = 0;\n        m.touser = 0;\n        for (auto w1 = w; w1 < r; w1++) {\n          file_email->Seek(static_cast<long>(sizeof(mailrec)) * static_cast<long>(w1), File::Whence::begin);\n          file_email->Write(&m, sizeof(mailrec));\n        }\n      }\n      file_email->Close();\n      file_email->set_length(static_cast<long>(sizeof(mailrec)) * static_cast<long>(w));\n      a()->status_manager()->Run([](Status& s) {\n        s.increment_filechanged(Status::file_change_email);\n      });\n    }\n  }\n  if (received_short_message()) {\n    File smwFile(FilePath(a()->config()->datadir(), SMW_DAT));\n    if (smwFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      const auto num_records = static_cast<int>(smwFile.length() / sizeof(shortmsgrec));\n      auto r = 0;\n      auto w = 0;\n      while (r < num_records) {\n        shortmsgrec sm{};\n        smwFile.Seek(r * sizeof(shortmsgrec), File::Whence::begin);\n        smwFile.Read(&sm, sizeof(shortmsgrec));\n        if (sm.tosys != 0 || sm.touser != 0) {\n          if (sm.tosys == 0 && sm.touser == a()->sess().user_num()) {\n            a()->user()->set_flag(User::SMW);\n          }\n          if (r != w) {\n            smwFile.Seek(w * sizeof(shortmsgrec), File::Whence::begin);\n            smwFile.Write(&sm, sizeof(shortmsgrec));\n          }\n          ++w;\n        }\n        ++r;\n      }\n      smwFile.Close();\n      smwFile.set_length(w * sizeof(shortmsgrec));\n    }\n  }\n  a()->WriteCurrentUser();\n  write_qscn(a()->sess().user_num(), a()->sess().qsc, false);\n}\n\n"
  },
  {
    "path": "bbs/lilo.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_LILO_H\n#define INCLUDED_BBS_LILO_H\n\nnamespace wwiv::sdk {\nclass User;\n}\n\nbool IsPhoneNumberUSAFormat(wwiv::sdk::User* pUser);\nvoid getuser();\nvoid logon();\nvoid logoff();\nvoid logon_guest();\n\n#endif\n"
  },
  {
    "path": "bbs/listplus.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/listplus.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/dirlist.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/lpfunc.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/wwivcolors.h\"\n#include <algorithm>\n#include <csignal>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// How far from the bottom that the side menu will be on the screen\n// This is used because of people who don't set there screenlines up correctly\n// It defines how far up from the users screenlines to put the menu\nstatic constexpr int STOP_LIST = 0;\n\nint bulk_move = 0;\nint bulk_dir = -1;\nbool ext_is_on = false;\nlistplus_config lp_config;\n\nstatic char _on_[] = \"ON!\";\nstatic char _off_[] = \"OFF\";\n\nstatic bool lp_config_loaded = false;\n\n// TODO(rushfan): Convert this to use strings.\nstatic void colorize_foundtext(char* text, search_record* search_rec, int color) {\n  char found_color[10], normal_color[10];\n  char find[101], word[101];\n\n  sprintf(found_color, \"|%02d|%02d\", lp_config.found_fore_color, lp_config.found_back_color);\n  sprintf(normal_color, \"|16|%02d\", color);\n\n  if (lp_config.colorize_found_text) {\n    to_char_array(find, search_rec->search);\n    char* tok = strtok(find, \"&|!()\");\n\n    while (tok) {\n      char* temp_buffer = text;\n      strcpy(word, tok);\n      StringTrim(word);\n\n      while (temp_buffer && word[0]) {\n        if ((temp_buffer = strcasestr(temp_buffer, word)) != nullptr) {\n          int size = ssize(temp_buffer) + 1;\n          memmove(&temp_buffer[6], &temp_buffer[0], size);\n          strncpy(temp_buffer, found_color, 6);\n          temp_buffer += strlen(word) + 6;\n          size = ssize(temp_buffer) + 1;\n          memmove(&temp_buffer[6], &temp_buffer[0], size);\n          strncpy(temp_buffer, normal_color, 6);\n          temp_buffer += 6;\n          ++temp_buffer;\n        }\n      }\n      tok = strtok(nullptr, \"&|!()\");\n    }\n  }\n}\n\nstatic void colorize_foundtext(std::string* text, search_record* search_rec, int color) {\n  std::unique_ptr<char[]> s(new char[text->size() * 2 + (12 * 10)]); // extra padding for colorized\n  strcpy(s.get(), text->c_str());\n  colorize_foundtext(s.get(), search_rec, color);\n  text->assign(s.get());\n}\n\nstatic void build_header() {\n  int desc_pos = 30;\n  std::string header(\" Tag # \");\n  if (a()->user()->data.lp_options & cfl_fname) {\n    header += \"FILENAME\";\n  }\n  if (a()->user()->data.lp_options & cfl_extension) {\n    header += \".EXT \";\n  }\n  if (a()->user()->data.lp_options & cfl_dloads) {\n    header += \" DL \";\n  }\n  if (a()->user()->data.lp_options & cfl_kbytes) {\n    header += \"Bytes \";\n  }\n\n  if (a()->user()->data.lp_options & cfl_days_old) {\n    header += \"Age \";\n  }\n  if (a()->user()->data.lp_options & cfl_description) {\n    desc_pos = size_int(header);\n    header += \"Description\";\n  }\n  StringJustify(&header, 79, ' ', JustificationType::LEFT);\n  bout.print(\"|23|01{}\\r\\n\", header);\n\n  header.clear();\n  if (a()->user()->data.lp_options & cfl_date_uploaded) {\n    header += \"Date Uploaded      \";\n  }\n  if (a()->user()->data.lp_options & cfl_upby) {\n    header += \"Who uploaded\";\n  }\n  if (!header.empty()) {\n    StringJustify(&header, desc_pos + ssize(header), ' ', JustificationType::RIGHT);\n    StringJustify(&header, 79, ' ', JustificationType::LEFT);\n    bout.print(\"|23|01{}\\r\\n\", header);\n  }\n}\n\nstatic void printtitle_plus_old() {\n  bout.print(\"|16|15{}\\r\\n\", std::string(79, '\\xDC'));\n\n  const auto buf =\n      fmt::sprintf(\"Area %d : %-30.30s (%d files)\", to_number<int>(a()->current_user_dir().keys),\n                   a()->dirs()[a()->current_user_dir().subnum].name,\n                   a()->current_file_area()->number_of_files());\n  bout.printf(\"|23|01 \\xF9 %-56s Space=Tag/?=Help \\xF9 \\r\\n\", buf);\n\n  if (a()->user()->data.lp_options & cfl_header) {\n    build_header();\n  }\n\n  bout.print(\"|16|08{}\\r\\n|#0\", std::string(79, '\\xDF'));\n}\n\nvoid printtitle_plus() {\n  bout.cls();\n\n  if (a()->user()->data.lp_options & cfl_header) {\n    printtitle_plus_old();\n  } else {\n    const auto buf =\n        fmt::format(\"Area {} : {: <30} ({} files)\", to_number<int>(a()->current_user_dir().keys),\n                    a()->dirs()[a()->current_user_dir().subnum].name,\n                    a()->current_file_area()->number_of_files());\n    bout.litebar(fmt::format(\"{:<54} Space=Tag/?=Help\", buf));\n    bout.ansic(0);\n  }\n}\n\nstatic int lp_configured_lines() {\n  return (a()->user()->data.lp_options & cfl_date_uploaded ||\n          a()->user()->data.lp_options & cfl_upby)\n           ? 3\n           : 2;\n}\n\nint first_file_pos() {\n  int pos = FIRST_FILE_POS;\n  if (a()->user()->data.lp_options & cfl_header) {\n    pos += lp_configured_lines();\n  }\n  return pos;\n}\n\nvoid print_searching(search_record* search_rec) {\n  bout.cls();\n\n  if (search_rec->search.size() > 3) {\n    bout.print(\"|#9Search keywords : |#2{}\", search_rec->search);\n    bout.nl(2);\n  }\n  bout.outstr(\"|#9<Space> aborts  : \");\n  bout.cls();\n  bout.printf(\" |17|15%-40.40s|16|#0\\r\", a()->dirs()[a()->current_user_dir().subnum].name);\n}\n\nstatic void catch_divide_by_zero(int signum) {\n  if (signum == SIGFPE) {\n    sysoplog(\"Caught divide by 0\");\n  }\n}\n\nint listfiles_plus(int type) {\n  if (a()->current_user_dir().subnum < 0 || a()->udir.empty()) {\n    // We don't have any current directory, can not list files.\n    bout.pl(\"|#6No directories available.\");\n    return 0;\n  }\n\n  const auto save_topdata = bout.localIO()->topdata();\n  const auto save_dir = a()->current_user_dir_num();\n  const long save_status = a()->user()->get_status();\n\n  ext_is_on = a()->user()->full_descriptions();\n  signal(SIGFPE, catch_divide_by_zero);\n\n  bout.localIO()->topdata(wwiv::local::io::LocalIO::topdata_t::none);\n  a()->UpdateTopScreen();\n  bout.cls();\n\n  const int r = listfiles_plus_function(type);\n  // Stop trailing bits left on screen.\n  bout.cls();\n  bout.ansic(0);\n  bout.goxy(1, a()->user()->screen_lines() - 3);\n  bout.nl(3);\n\n  bout.clear_lines_listed();\n\n  if (type != LP_NSCAN_NSCAN) {\n    tmp_disable_conf(false);\n  }\n\n  a()->user()->SetStatus(save_status);\n\n  if (type == LP_NSCAN_DIR || type == LP_SEARCH_ALL) {\n    // change Build3\n    a()->set_current_user_dir_num(save_dir);\n  }\n  dliscan();\n\n  bout.localIO()->topdata(save_topdata);\n  a()->UpdateTopScreen();\n\n  return r;\n}\n\nint lp_add_batch(const std::string& file_name, int dn, int fs) {\n  if (a()->batch().FindBatch(file_name) > -1) {\n    return 0;\n  }\n\n  if (a()->batch().size() >= a()->max_batch) {\n    bout.goxy(1, a()->user()->screen_lines() - 1);\n    bout.outstr(\"No room left in batch queue.\\r\\n\");\n    bout.pausescr();\n  } else if (!ratio_ok()) {\n    bout.pausescr();\n  } else {\n    if (nsl() <= a()->batch().dl_time_in_secs() + time_to_transfer(a()->modem_speed_, fs).count() &&\n        !so()) {\n      bout.goxy(1, a()->user()->screen_lines() - 1);\n      bout.outstr(\"Not enough time left in queue.\\r\\n\");\n      bout.pausescr();\n    } else {\n      if (dn == -1) {\n        bout.goxy(1, a()->user()->screen_lines() - 1);\n        bout.outstr(\"Can't add temporary file to batch queue.\\r\\n\");\n        bout.pausescr();\n      } else {\n        a()->batch().AddBatch({file_name, dn, fs, true});\n        return 1;\n      }\n    }\n  }\n  return 0;\n}\n\n\nint printinfo_plus(uploadsrec* u, int filenum, int marked, int LinesLeft,\n                   search_record* search_rec) {\n  int numl = 0, will_fit = 78;\n  int char_printed = 0, extdesc_pos;\n\n  files::FileName filename(u->filename);\n  const auto& fn = filename.aligned_filename();\n  if (fn.empty()) {\n    // Make sure the filename isn't empty, if it is then lets bail!\n    return 0; \n  }\n  std::filesystem::path p{fn};\n  const auto dot_idx = fn.find('.');\n  const auto extension =\n      fmt::format(\"{:<3}\", dot_idx == std::string::npos ? \"\" : fn.substr(dot_idx + 1));\n  // stem includes \" around the filename.\n  const auto basename =\n      fmt::format(\"{:<8}\", dot_idx == std::string::npos ? fn : fn.substr(0, dot_idx));\n\n  auto now = DateTime::now().to_time_t();\n  auto diff_time = static_cast<long>(difftime(now, u->daten));\n  int days_old = diff_time / SECONDS_PER_DAY;\n\n  auto file_information = fmt::sprintf(\"|%02d %c |%02d%3d \", lp_config.tagged_color,\n                                       marked ? '\\xFE' : ' ', lp_config.file_num_color, filenum);\n  int width = 7;\n  bout.clear_lines_listed();\n\n  std::string buffer;\n  if (a()->user()->data.lp_options & cfl_fname) {\n    buffer = basename;\n    if (search_rec) {\n      colorize_foundtext(&buffer, search_rec, a()->user()->data.lp_colors[0]);\n    }\n    file_information += fmt::format(\"|{:02}{}\", a()->user()->data.lp_colors[0], buffer);\n    width += 8;\n  }\n  if (a()->user()->data.lp_options & cfl_extension) {\n    buffer = extension;\n    if (search_rec) {\n      colorize_foundtext(&buffer, search_rec, a()->user()->data.lp_colors[1]);\n    }\n    file_information += fmt::sprintf(\"|%02d.%s\", a()->user()->data.lp_colors[1], buffer);\n    width += 4;\n  }\n  if (a()->user()->data.lp_options & cfl_dloads) {\n    file_information += fmt::sprintf(\" |%02d%3d\", a()->user()->data.lp_colors[2], u->numdloads);\n    width += 4;\n  }\n  if (a()->user()->data.lp_options & cfl_kbytes) {\n    buffer = humanize(u->numbytes);\n    if (!(a()->dirs()[a()->current_user_dir().subnum].mask & mask_cdrom)) {\n      auto stf = FilePath(a()->dirs()[a()->current_user_dir().subnum].path,\n                          files::FileName(u->filename));\n      if (lp_config.check_exist) {\n        if (!File::Exists(stf)) {\n          buffer = \"OFFLN\";\n        }\n      }\n    }\n    file_information += fmt::format(\" |{:02}{:>4} \", a()->user()->data.lp_colors[3], buffer);\n    width += 6;\n  }\n\n  if (a()->user()->data.lp_options & cfl_days_old) {\n    file_information += fmt::sprintf(\" |%02d%3d\", a()->user()->data.lp_colors[6], days_old);\n    width += 4;\n  }\n  if (a()->user()->data.lp_options & cfl_description) {\n    ++width;\n    buffer = u->description;\n    if (search_rec) {\n      colorize_foundtext(&buffer, search_rec, a()->user()->data.lp_colors[10]);\n    }\n    file_information += fmt::sprintf(\" |%02d%s\", a()->user()->data.lp_colors[10], buffer);\n    extdesc_pos = width;\n  } else {\n    extdesc_pos = -1;\n  }\n\n  auto fi = trim_to_size_ignore_colors(file_information, will_fit);\n  fi += \"\\r\\n\";\n  bout.outstr(fi);\n  numl++;\n\n  if (extdesc_pos > 0) {\n    int num_extended, lines_left;\n    int lines_printed;\n\n    lines_left = LinesLeft - numl;\n    num_extended = a()->user()->GetNumExtended();\n    if (num_extended < lp_config.show_at_least_extended) {\n      num_extended = lp_config.show_at_least_extended;\n    }\n    if (num_extended > lines_left) {\n      num_extended = lines_left;\n    }\n    if (ext_is_on && mask_extended & u->mask) {\n      lines_printed = print_extended(u->filename, num_extended, -extdesc_pos,\n                                          static_cast<Color>(a()->user()->data.lp_colors[10]),\n                                          search_rec);\n    } else {\n      lines_printed = 0;\n    }\n\n    if (lines_printed) {\n      numl += lines_printed;\n      char_printed = 0;\n    }\n  }\n  if (bout.wherex()) {\n    if (char_printed) {\n      bout.nl();\n      ++numl;\n    } else {\n      bout.outchr('\\r');\n    }\n  }\n  file_information.clear();\n\n  if (a()->user()->data.lp_options & cfl_date_uploaded) {\n    if (u->actualdate[2] == '/' && u->actualdate[5] == '/') {\n      buffer = fmt::sprintf(\"UL: %s  New: %s\", u->date, u->actualdate);\n      StringJustify(&buffer, 27, ' ', JustificationType::LEFT);\n    } else {\n      buffer = fmt::sprintf(\"UL: %s\", u->date);\n      StringJustify(&buffer, 12, ' ', JustificationType::LEFT);\n    }\n    file_information += fmt::sprintf(\"|%02d%s  \", a()->user()->data.lp_colors[4], buffer);\n  }\n\n  if (a()->user()->data.lp_options & cfl_upby) {\n    if (a()->user()->data.lp_options & cfl_date_uploaded) {\n      StringJustify(&file_information, ssize(file_information) + width, ' ',\n                    JustificationType::RIGHT);\n      bout.outstr(file_information);\n      bout.nl();\n      ++numl;\n    }\n    auto tmp = properize(std::string(u->upby));\n    file_information = fmt::sprintf(\"|%02dUpby: %-15s\", a()->user()->data.lp_colors[7], tmp);\n  }\n\n  if (!buffer.empty()) {\n    StringJustify(&file_information, ssize(file_information) + width, ' ',\n                  JustificationType::RIGHT);\n    bout.outstr(file_information);\n    bout.nl();\n    ++numl;\n  }\n  return numl;\n}\n\nint print_extended(const std::string& file_name, int numlist, int indent, Color color,\n                        search_record* search_rec) {\n\n  const int will_fit = 80 - std::abs(indent) - 2;\n\n  auto ss = a()->current_file_area()->ReadExtendedDescriptionAsString(file_name).value_or(\"\");\n\n  if (ss.empty()) {\n    return 0;\n  }\n  StringTrimEnd(&ss);\n  if (search_rec && search_rec->filemask != \"????????.???\") {\n    colorize_foundtext(&ss, search_rec, static_cast<uint8_t>(color));\n  }\n  if (indent > -1 && indent != 16) {\n    bout.outstr(\"  |#9Extended Description:\\n\\r\");\n  }\n  const auto lines = SplitString(ss, \"\\n\", false);\n  auto numl = std::min<int>(size_int(lines), numlist);\n  for (auto i = 0; i < numl; i++) {\n    bout.Right(std::abs(indent));\n    auto l = lines.at(i);\n    if (ssize(l) > will_fit) {\n      l.resize(will_fit);\n    }\n    bout.setc(static_cast<uint8_t>(color));\n    bout.outstr(lines.at(i));\n    bout.nl();\n  }\n  bout.ansic(0);\n  if (bout.wherex()) {\n    bout.nl();\n    ++numl;\n  }\n  return numl;\n}\n\nvoid show_fileinfo(uploadsrec* u) {\n  bout.cls();\n  bout.ansic(7);\n  bout.outstr(std::string(78, '\\xCD'));\n  bout.nl();\n  bout.print(\"  |#9Filename    : |#2{}\\r\\n\", u->filename);\n  bout.print(\"  |#9Uploaded on : |#2{} by |#2{}\\r\\n\", u->date, u->upby);\n  if (u->actualdate[2] == '/' && u->actualdate[5] == '/') {\n    bout.print(\"  |#9Newest file : |#2{}\\r\\n\", u->actualdate);\n  }\n  bout.print(\"  |#9Size        : |#2{}\\r\\n\", humanize(u->numbytes));\n  bout.print(\"  |#9Downloads   : |#2{}\\r\\n\", u->numdloads);\n  bout.print(\"  |#9Description : |#2{}\\r\\n\", u->description);\n  print_extended(u->filename, 255, 16, Color::YELLOW, nullptr);\n  bout.ansic(7);\n  bout.outstr(std::string(78, '\\xCD'));\n  bout.nl();\n  bout.pausescr();\n}\n\nint check_lines_needed(uploadsrec* u) {\n  const auto num_extended = std::max<int>(a()->user()->GetNumExtended(),\n                                          lp_config.show_at_least_extended);\n  const auto max_lines = std::min<int>(num_extended, calc_max_lines());\n\n  auto elines = 0;\n  if (a()->user()->data.lp_options & cfl_description) {\n    if (ext_is_on && mask_extended & u->mask) {\n      const auto ss = a()->current_file_area()->ReadExtendedDescriptionAsString(u->filename).\n                           value_or(\"\");\n      const auto lines = SplitString(ss, \"\\r\");\n      elines = size_int(lines);\n    }\n  }\n  const auto lc_lines_used = lp_configured_lines();\n  return std::min<int>(lc_lines_used + elines, max_lines - 1);\n}\n\nint prep_search_rec(search_record* r, int type) {\n  r->search_extended = lp_config.search_extended_on ? true : false;\n\n  if (type == LP_LIST_DIR) {\n    r->filemask = file_mask();\n    r->alldirs = THIS_DIR;\n  } else if (type == LP_SEARCH_ALL) {\n    r->alldirs = ALL_DIRS;\n    if (!search_criteria(r)) {\n      return 0;\n    }\n  } else if (type == LP_NSCAN_DIR) {\n    r->alldirs = THIS_DIR;\n    r->nscandate = a()->sess().nscandate();\n  } else if (type == LP_NSCAN_NSCAN) {\n    a()->sess().scanned_files(true);\n    r->nscandate = a()->sess().nscandate();\n    r->alldirs = ALL_DIRS;\n  } else {\n    sysoplog(\"Undef LP type\");\n    return 0;\n  }\n\n  if (r->filemask.empty() && !r->nscandate && !r->search[0]) {\n    return 0;\n  }\n\n  if (!r->filemask.empty()) {\n    if (!contains(r->filemask, '.')) {\n      r->filemask += \".*\";\n    }\n  }\n  r->filemask = aligns(r->filemask);\n  return 1;\n}\n\nint calc_max_lines() {\n  if (lp_config.max_screen_lines_to_show) {\n    return std::min<int>(a()->user()->screen_lines(), lp_config.max_screen_lines_to_show) -\n           (first_file_pos() + 1 + STOP_LIST);\n  }\n  return a()->user()->screen_lines() - (first_file_pos() + 1 + STOP_LIST);\n}\n\nstatic void check_lp_colors() {\n  bool needs_defaults = false;\n  auto* u = a()->user();\n  for (auto& c : u->data.lp_colors) {\n    if (!c) {\n      needs_defaults = true;\n      c = static_cast<uint8_t>(Color::CYAN);\n    }\n  }\n\n  if (needs_defaults) {\n    u->data.lp_colors[0] = static_cast<uint8_t>(Color::LIGHTGREEN);\n    u->data.lp_colors[1] = static_cast<uint8_t>(Color::LIGHTGREEN);\n    u->data.lp_colors[4] = static_cast<uint8_t>(Color::LIGHTCYAN);\n    u->data.lp_colors[5] = static_cast<uint8_t>(Color::LIGHTCYAN);\n    u->data.lp_colors[10] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  }\n}\n\nvoid save_lp_config() {\n  if (lp_config_loaded) {\n    File fileConfig(FilePath(a()->config()->datadir(), LISTPLUS_CFG));\n    if (fileConfig.Open(File::modeBinary | File::modeCreateFile | File::modeTruncate |\n                        File::modeReadWrite)) {\n      fileConfig.Write(&lp_config, sizeof(listplus_config));\n      fileConfig.Close();\n    }\n  }\n}\n\nvoid load_lp_config() {\n  if (!lp_config_loaded) {\n    File fileConfig(FilePath(a()->config()->datadir(), LISTPLUS_CFG));\n    if (!fileConfig.Open(File::modeBinary | File::modeReadOnly)) {\n      memset(&lp_config, 0, sizeof(listplus_config));\n\n      lp_config.normal_highlight =\n          static_cast<uint8_t>(Color::YELLOW) + (static_cast<uint8_t>(Color::BLACK) << 4);\n      lp_config.normal_menu_item =\n          static_cast<uint8_t>(Color::CYAN) + (static_cast<uint8_t>(Color::BLACK) << 4);\n      lp_config.current_highlight =\n          static_cast<uint8_t>(Color::BLUE) + (static_cast<uint8_t>(Color::LIGHTGRAY) << 4);\n      lp_config.current_menu_item =\n          static_cast<uint8_t>(Color::BLACK) + (static_cast<uint8_t>(Color::LIGHTGRAY) << 4);\n\n      lp_config.tagged_color = static_cast<uint8_t>(Color::LIGHTGRAY);\n      lp_config.file_num_color = static_cast<uint8_t>(Color::GREEN);\n\n      lp_config.found_fore_color = static_cast<uint8_t>(Color::RED);\n      lp_config.found_back_color = static_cast<uint8_t>(Color::LIGHTGRAY) + 16;\n\n      lp_config.current_file_color =\n          static_cast<uint8_t>(Color::BLACK) + (static_cast<uint8_t>(Color::LIGHTGRAY) << 4);\n\n      lp_config.max_screen_lines_to_show = 24;\n      lp_config.show_at_least_extended = 5;\n\n      lp_config.edit_enable = 1;         // Do or don't let users edit their config\n      lp_config.request_file = 1;        // Do or don't use file request\n      lp_config.colorize_found_text = 1; // Do or don't colorize found text\n      lp_config.search_extended_on = 0;\n      // Defaults to either on or off in adv search, or is either on or off in simple search\n      lp_config.simple_search = 1; // Which one is entered when searching, can switch to other still\n      lp_config.no_configuration = 0; // Toggles configurable menus on and off\n      lp_config.check_exist = 1;\n      // Will check to see if the file exists on hardrive and put N/A if not\n      lp_config_loaded = true;\n      lp_config.forced_config = 0;\n\n      save_lp_config();\n    } else {\n      fileConfig.Read(&lp_config, sizeof(listplus_config));\n      lp_config_loaded = true;\n      fileConfig.Close();\n    }\n  }\n  check_lp_colors();\n}\n\nvoid sysop_configure() {\n  bool done = false;\n\n  if (!so()) {\n    return;\n  }\n\n  load_lp_config();\n\n  while (!done && !a()->sess().hangup()) {\n    bout.cls();\n    bout.printfile(LPSYSOP_NOEXT);\n    bout.PutsXYSC(38, 2, lp_config.normal_highlight, fmt::sprintf(\"%3d\", lp_config.normal_highlight));\n    bout.PutsXYSC(77, 2, lp_config.normal_menu_item, fmt::sprintf(\"%3d\", lp_config.normal_menu_item));\n    bout.PutsXYSC(38, 3, lp_config.current_highlight, fmt::sprintf(\"%3d\", lp_config.current_highlight));\n    bout.PutsXYSC(77, 3, lp_config.current_menu_item, fmt::sprintf(\"%3d\", lp_config.current_menu_item));\n    bout.ansic(0);\n    bout.PutsXY(38, 6, fmt::sprintf(\"|%02d%2d\", lp_config.tagged_color, lp_config.tagged_color));\n    bout.PutsXY(77, 6, fmt::sprintf(\"|%02d%2d\", lp_config.file_num_color, lp_config.file_num_color));\n    bout.PutsXY(38, 7, fmt::sprintf(\"|%02d%2d\", lp_config.found_fore_color, lp_config.found_fore_color));\n    bout.PutsXY(77, 7, fmt::sprintf(\"|%02d%2d\", lp_config.found_back_color, lp_config.found_back_color));\n    bout.PutsXYSC(38, 8, lp_config.current_file_color, fmt::sprintf(\"%3d\", lp_config.current_file_color));\n    bout.PutsXY(38, 11, fmt::sprintf(\"|#4%2d\", lp_config.max_screen_lines_to_show));\n    bout.PutsXY(77, 11,fmt::sprintf(\"|#4%2d\", lp_config.show_at_least_extended));\n    bout.PutsXY(74, 14, fmt::sprintf(\"|#4%s\", lp_config.request_file ? _on_ : _off_));\n    bout.PutsXY(74, 15, fmt::sprintf(\"|#4%s\", lp_config.search_extended_on ? _on_ : _off_));\n    bout.PutsXY(74, 16, fmt::sprintf(\"|#4%s\", lp_config.edit_enable ? _on_ : _off_));\n    bout.ansic(0);\n    bout.PutsXY(29, 14, fmt::sprintf(\"|#4%s\", lp_config.no_configuration ? _on_ : _off_));\n    bout.PutsXY(29, 15, fmt::sprintf(\"|#4%s\", lp_config.colorize_found_text ? _on_ : _off_));\n    bout.PutsXY(29, 16, fmt::sprintf(\"|#4%s\", lp_config.simple_search ? _on_ : _off_));\n    bout.PutsXY(29, 17, fmt::sprintf(\"|#4%s\", lp_config.check_exist ? _on_ : _off_));\n    bout.PutsXY(1, 19, \"|#9Q-Quit \");\n    const auto key = onek(\"Q\\rABCDEFGHIJKLMNOPRS\", true);\n    switch (key) {\n    case 'Q':\n    case '\\r':\n      done = true;\n      break;\n    case 'A':\n    case 'B':\n    case 'C':\n    case 'D':\n    case 'I': {\n      auto color = SelectColor(2);\n      if (color >= 0) {\n        switch (key) {\n        case 'A':\n          lp_config.normal_highlight = color;\n          break;\n        case 'B':\n          lp_config.normal_menu_item = color;\n          break;\n        case 'C':\n          lp_config.current_highlight = color;\n          break;\n        case 'D':\n          lp_config.current_menu_item = color;\n          break;\n        case 'I':\n          lp_config.current_file_color = color;\n          break;\n        }\n      }\n      } break;\n    case 'E':\n    case 'F':\n    case 'G':\n    case 'H': {\n      const auto color = SelectColor(1);\n      if (color >= 0) {\n        switch (key) {\n        case 'E':\n          lp_config.tagged_color = color;\n          break;\n        case 'F':\n          lp_config.file_num_color = color;\n          break;\n        case 'G':\n          lp_config.found_fore_color = color;\n          break;\n        case 'H':\n          lp_config.found_back_color = color + 16;\n          break;\n        }\n      }\n      } break;\n    case 'J':\n      bout.outstr(\"Enter max amount of lines to show (0=disabled) \");\n      lp_config.max_screen_lines_to_show = bin.input_number(lp_config.max_screen_lines_to_show, 0, 20, true);\n      break;\n    case 'K':\n      bout.outstr(\"Enter minimum extended description lines to show \");\n      lp_config.show_at_least_extended = bin.input_number(lp_config.show_at_least_extended, 0, 20, true);\n      break;\n    case 'L':\n      lp_config.no_configuration = !lp_config.no_configuration;\n      break;\n    case 'M':\n      lp_config.request_file = !lp_config.request_file;\n      break;\n    case 'N':\n      lp_config.colorize_found_text = !lp_config.colorize_found_text;\n      break;\n    case 'O':\n      lp_config.search_extended_on = !lp_config.search_extended_on;\n      break;\n    case 'P':\n      lp_config.simple_search = !lp_config.simple_search;\n      break;\n    case 'R':\n      lp_config.edit_enable = !lp_config.edit_enable;\n      break;\n    case 'S':\n      lp_config.check_exist = !lp_config.check_exist;\n      break;\n    }\n  }\n  save_lp_config();\n  load_lp_config();\n}\n\nshort SelectColor(int which) {\n  unsigned char nc;\n\n  bout.nl();\n\n  if (a()->user()->color()) {\n    color_list();\n    bout.ansic(0);\n    bout.nl();\n    bout.outstr(\"|#2Foreground? \");\n    unsigned char ch = onek(\"01234567\");\n    nc = ch - '0';\n\n    if (which == 2) {\n      bout.outstr(\"|#2Background? \");\n      ch = onek(\"01234567\");\n      nc |= (ch - '0') << 4;\n    }\n  } else {\n    bout.nl();\n    bout.outstr(\"|#5Inversed? \");\n    if (bin.yesno()) {\n      if ((a()->user()->bwcolor(1) & 0x70) == 0) {\n        nc = (a()->user()->bwcolor(1) & 0x07) << 4;\n      } else {\n        nc = a()->user()->bwcolor(1) & 0x70;\n      }\n    } else {\n      if ((a()->user()->bwcolor(1) & 0x70) == 0) {\n        nc = a()->user()->bwcolor(1) & 0x07;\n      } else {\n        nc = (a()->user()->bwcolor(1) & 0x70) >> 4;\n      }\n    }\n  }\n\n  bout.outstr(\"|#5Intensified? \");\n  if (bin.yesno()) {\n    nc |= 0x08;\n  }\n\n  if (which == 2) {\n    bout.outstr(\"|#5Blinking? \");\n    if (bin.yesno()) {\n      nc |= 0x80;\n    }\n  }\n  bout.nl();\n  bout.setc(nc);\n  bout.outstr(DescribeColorCode(nc));\n  bout.ansic(0);\n  bout.nl();\n\n  bout.outstr(\"|#5Is this OK? \");\n  if (bin.yesno()) {\n    return nc;\n  }\n  return -1;\n}\n\nstatic void update_user_config_screen(uploadsrec* u, int which) {\n  const std::vector<std::string> lp_color_list{\n      \"Black   \",\n      \"Blue    \",\n      \"Green   \",\n      \"Cyan    \",\n      \"Red     \",\n      \"Purple  \",\n      \"Brown   \",\n      \"L-Gray  \",\n      \"D-Gray  \",\n      \"L-Blue  \",\n      \"L-Green \",\n      \"L-Cyan  \",\n      \"L-Red   \",\n      \"L-Purple\",\n      \"Yellow  \",\n      \"White   \"\n  };\n\n  const auto color_background = static_cast<uint8_t>(Color::BLUE) << 4;\n  auto color_selected = static_cast<uint8_t>(Color::LIGHTRED) | color_background;\n  auto color_notselected = static_cast<uint8_t>(Color::BLACK) | color_background;\n  const auto color_colortext = static_cast<uint8_t>(Color::LIGHTCYAN) | color_background;\n  auto& lpo = a()->user()->data.lp_options;\n  auto& lpc = a()->user()->data.lp_colors;\n\n  if (which < 1 || which == 1) {\n    bout.goxy(37, 4);\n    bout.setc(lpo & cfl_fname ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[0]]);\n  }\n  if (which < 1 || which == 2) {\n    bout.goxy(37, 5);\n    bout.setc(lpo & cfl_extension ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[1]]);\n  }\n  if (which < 1 || which == 3) {\n    bout.goxy(37, 6);\n    bout.setc(lpo & cfl_dloads ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[2]]);\n  }\n  if (which < 1 || which == 4) {\n    bout.goxy(37, 7);\n    bout.setc(lpo & cfl_kbytes ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[3]]);\n  }\n  if (which < 1 || which == 5) {\n    bout.goxy(37, 8);\n    bout.setc(lpo & cfl_description ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[10]]);\n  }\n  if (which < 1 || which == 6) {\n    bout.goxy(37, 9);\n    bout.setc(lpo & cfl_date_uploaded ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[4]]);\n  }\n  if (which < 1 || which == 7) {\n    bout.goxy(37, 10);\n    bout.setc(lpo & cfl_file_points ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[5]]);\n  }\n  if (which < 1 || which == 8) {\n    bout.goxy(37, 11);\n    bout.setc(lpo & cfl_days_old ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[6]]);\n  }\n  if (which < 1 || which == 9) {\n    bout.goxy(37, 12);\n    bout.setc(lpo & cfl_upby ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n    bout.outstr(lp_color_list[lpc[7]]);\n  }\n  if (which < 1 || which == 10) {\n    bout.goxy(37, 13);\n    bout.setc(lpo & cfl_header ? color_selected : color_notselected);\n    bout.outstr(\"\\xFE \");\n    bout.setc(color_colortext);\n  }\n  bout.setc(Color::YELLOW);\n  bout.goxy(1, 21);\n  bout.clreol();\n  bout.nl();\n  bout.clreol();\n  bout.nl();\n  bout.clreol();\n  bout.goxy(1, 21);\n\n  search_record sr{};\n  printinfo_plus(u, 1, 1, 30, &sr);\n  bout.goxy(30, 17);\n  bout.setc(Color::YELLOW);\n  bout.bs();\n}\n\nvoid config_file_list() {\n  if (a()->current_user_dir().subnum < 0 || a()->udir.empty()) {\n    // We don't have any current directory, can not list files.\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n\n  int which = -1;\n  unsigned long bit = 0L;\n  uploadsrec u = {};\n\n  to_char_array(u.filename, \"WWIV55.ZIP\");\n  to_char_array(u.description, \"This is a sample description!\");\n  to_char_array(u.date, date());\n  const std::string username_num = a()->user()->name_and_number();\n  to_char_array(u.upby, username_num);\n  u.numdloads = 50;\n  u.numbytes = 655535L;\n  u.daten = daten_t_now() - 10000;\n\n  load_lp_config();\n\n  bout.cls();\n  bout.printfile(LPCONFIG_NOEXT);\n  if (!(a()->user()->data.lp_options & cfl_fname)) {\n    a()->user()->data.lp_options |= cfl_fname;\n  }\n\n  if (!(a()->user()->data.lp_options & cfl_description)) {\n    a()->user()->data.lp_options |= cfl_description;\n  }\n\n  auto done = false;\n  while (!done && !a()->sess().hangup()) {\n    update_user_config_screen(&u, which);\n    switch (const int key = onek(\"Q2346789H!@#$%^&*(\"); key) {\n    case '2':\n    case '3':\n    case '4':\n    case '6':\n    case '7':\n    case '8':\n    case '9':\n    case 'H':\n      switch (key) {\n      case '2':\n        bit = cfl_extension;\n        which = 2;\n        break;\n      case '3':\n        bit = cfl_dloads;\n        which = 3;\n        break;\n      case '4':\n        bit = cfl_kbytes;\n        which = 4;\n        break;\n      case '6':\n        bit = cfl_date_uploaded;\n        which = 6;\n        break;\n      case '7':\n        bit = cfl_file_points;\n        which = 7;\n        break;\n      case '8':\n        bit = cfl_days_old;\n        which = 8;\n        break;\n      case '9':\n        bit = cfl_upby;\n        which = 9;\n        break;\n      case 'H':\n        bit = cfl_header;\n        which = 10;\n        break;\n      }\n      a()->user()->data.lp_options ^= bit;\n      break;\n\n    case '!':\n    case '@':\n    case '#':\n    case '$':\n    case '%':\n    case '^':\n    case '&':\n    case '*':\n    case '(':\n      switch (key) {\n      case '!':\n        bit = 0;\n        which = 1;\n        break;\n      case '@':\n        bit = 1;\n        which = 2;\n        break;\n      case '#':\n        bit = 2;\n        which = 3;\n        break;\n      case '$':\n        bit = 3;\n        which = 4;\n        break;\n      case '%':\n        bit = 10;\n        which = 5;\n        break;\n      case '^':\n        bit = 4;\n        which = 6;\n        break;\n      case '&':\n        bit = 5;\n        which = 7;\n        break;\n      case '*':\n        bit = 6;\n        which = 8;\n        break;\n      case '(':\n        bit = 7;\n        which = 9;\n        break;\n      }\n\n      ++a()->user()->data.lp_colors[bit];\n      if (a()->user()->data.lp_colors[bit] > 15) {\n        a()->user()->data.lp_colors[bit] = 1;\n      }\n      break;\n    case 'Q':\n      done = true;\n      break;\n    }\n  }\n  bout.nl(4);\n}\n\nstatic int rename_filename(const std::string& file_name, int dn) {\n  int ret = 1;\n\n  dliscan1(dn);\n  std::string s = file_name;\n  if (s.empty()) {\n    return 1;\n  }\n  if (!contains(s, '.')) {\n    s += \".*\";\n  }\n  const auto orig_aligned_filename = aligns(s);\n\n  int i = recno(orig_aligned_filename);\n  while (i > 0) {\n    const int current_file_position = i;\n    auto* area = a()->current_file_area();\n    auto& dir = a()->dirs()[dn];\n    auto f = area->ReadFile(current_file_position);\n    bout.nl();\n    printfileinfo(&f.u(), dir);\n    bout.nl();\n    bout.outstr(\"|#5Change info for this file (Y/N/Q)? \");\n    char ch = bin.ynq();\n    if (ch == 'Q') {\n      ret = 0;\n      break;\n    }\n    if (ch == 'N') {\n      i = nrecno(orig_aligned_filename, current_file_position);\n      continue;\n    }\n    bout.nl();\n    bout.outstr(\"|#2New filename? \");\n    auto new_filename = bin.input(12);\n    if (!okfn(new_filename)) {\n      new_filename.clear();\n    }\n    if (!new_filename.empty()) {\n      new_filename = aligns(new_filename);\n      if (new_filename != \"        .   \") {\n        files::FileName nfn(new_filename);\n        auto new_fn = FilePath(a()->dirs()[dn].path, nfn);\n        if (File::Exists(new_fn)) {\n          bout.outstr(\"Filename already in use; not changed.\\r\\n\");\n        } else {\n          auto old_fn = FilePath(a()->dirs()[dn].path, f);\n          File::Rename(old_fn, new_fn);\n          if (File::Exists(new_fn)) {\n            auto ss = area->ReadExtendedDescriptionAsString(f).value_or(std::string());\n            if (!ss.empty()) {\n              // TODO(rushfan): Display error if these fail?\n              area->DeleteExtendedDescription(f, current_file_position);\n              area->AddExtendedDescription(new_filename, ss);\n            }\n            f.set_filename(new_filename);\n            f.set_extended_description(!ss.empty());\n          } else {\n            bout.outstr(\"Bad filename.\\r\\n\");\n          }\n        }\n      }\n    }\n    bout.nl();\n    bout.outstr(\"New description:\\r\\n|#2: \");\n    auto desc = bin.input_text(f.u().description, 58);\n    if (!desc.empty()) {\n      f.set_description(desc);\n    }\n    auto ss = area->ReadExtendedDescriptionAsString(f).value_or(std::string());\n    bout.nl(2);\n    bout.outstr(\"|#5Modify extended description? \");\n    if (bin.yesno()) {\n      bout.nl();\n      if (!ss.empty()) {\n        bout.outstr(\"|#5Delete it? \");\n        if (bin.yesno()) {\n          area->DeleteExtendedDescription(f, current_file_position);\n          f.set_extended_description(false);\n        } else {\n          f.set_extended_description(true);\n          modify_extended_description(&ss, a()->dirs()[dn].name);\n          if (!ss.empty()) {\n            area->DeleteExtendedDescription(f, current_file_position);\n            area->AddExtendedDescription(f, current_file_position, ss);\n          }\n        }\n      } else {\n        modify_extended_description(&ss, a()->dirs()[dn].name);\n        if (!ss.empty()) {\n          area->AddExtendedDescription(f, current_file_position, ss);\n          f.set_extended_description(true);\n        } else {\n          f.set_extended_description(false);\n        }\n      }\n    } else if (!ss.empty()) {\n      f.set_extended_description(true);\n    } else {\n      f.set_extended_description(false);\n    }\n    if (a()->current_file_area()->UpdateFile(f, i)) {\n      a()->current_file_area()->Save();\n    }\n    i = nrecno(orig_aligned_filename, current_file_position);\n  }\n  return ret;\n}\n\nstatic int remove_filename(const std::string& file_name, int dn) {\n  if (file_name.empty()) {\n    return 1;\n  }\n\n  const auto& dir = a()->dirs()[dn];\n  dliscan1(dir);\n\n  auto fn{file_name};\n  if (fn.find('.') == std::string::npos) {\n    fn += \".*\";\n  }\n  fn = aligns(fn);\n  int i = recno(fn);\n  bool abort = false;\n  bool rdlp = false;\n  int ret = 1;\n  while (!a()->sess().hangup() && i > 0 && !abort) {\n    auto f = a()->current_file_area()->ReadFile(i);\n    if (dcs() || f.u().ownersys == 0 && f.u().ownerusr == a()->sess().user_num()) {\n      bout.nl();\n      printfileinfo(&f.u(), dir);\n      bout.outstr(\"|#9Remove (|#2Y/N/Q|#9) |#0: |#2\");\n      char ch = bin.ynq();\n      if (ch == 'Q') {\n        ret = 0;\n        abort = true;\n      } else if (ch == 'Y') {\n        rdlp = true;\n        bool rm = false;\n        if (dcs()) {\n          bout.outstr(\"|#5Delete file too? \");\n          rm = bin.yesno();\n          if (rm && f.u().ownersys == 0) {\n            bout.outstr(\"|#5Remove DL points? \");\n            rdlp = bin.yesno();\n          }\n          bout.outstr(\"|#5Remove from ALLOW.DAT? \");\n          if (bin.yesno()) {\n            remove_from_file_database(fn);\n          }\n        } else {\n          rm = true;\n          remove_from_file_database(fn);\n        }\n        if (rm) {\n          File::Remove(FilePath(dir.path, f));\n          if (rdlp && f.u().ownersys == 0) {\n            if (auto user = a()->users()->readuser(f.u().ownerusr, UserManager::mask::non_deleted)) {\n              if (date_to_daten(user->firston()) < f.u().daten) {\n                user->decrement_uploaded();\n                user->decrement_uploaded();\n                user->set_uk(user->uk() - bytes_to_k(f.numbytes()));\n                a()->users()->writeuser(&user.value(), f.u().ownerusr);\n              }\n            }\n          }\n        }\n        sysoplog(fmt::format(\"- '{}' removed off of {}\", f, a()->dirs()[dn].name));\n        if (a()->current_file_area()->DeleteFile(f, i)) {\n          a()->current_file_area()->Save();\n          --i;\n        }\n      }\n    }\n    i = nrecno(fn, i);\n  }\n  return ret;\n}\n\nstatic int move_filename(const std::string& file_name, int dn) {\n  int nDestDirNum = -1, ret = 1;\n  const auto move_fn = aligns(file_name);\n  dliscan1(dn);\n  int nRecNum = recno(move_fn);\n  if (nRecNum < 0) {\n    bout.outstr(\"\\r\\nFile not found.\\r\\n\");\n    return ret;\n  }\n  bool done = false;\n  bool ok = false;\n\n  tmp_disable_conf(true);\n  wwiv::common::TempDisablePause diable_pause(bout);\n  while (!a()->sess().hangup() && nRecNum > 0 && !done) {\n    int cp = nRecNum;\n    const auto& dir = a()->dirs()[dn];\n    auto source_filearea = a()->fileapi()->Open(dir);\n    auto f = source_filearea->ReadFile(nRecNum);\n    auto src_fn = FilePath(dir.path, f);\n    bout.nl();\n    printfileinfo(&f.u(), dir);\n    bout.nl();\n    bout.outstr(\"|#5Move this (Y/N/Q)? \");\n    char ch = 'Y';\n    if (bulk_move) {\n      bout.ansic(1);\n      bout.outstr(YesNoString(true));\n      bout.nl();\n    } else {\n      ch = bin.ynq();\n    }\n\n    if (ch == 'Q') {\n      done = true;\n      ret = 0;\n    } else if (ch == 'Y') {\n      if (!bulk_move) {\n        std::string ss;\n        do {\n          bout.nl(2);\n          bout.outstr(\"|#2To which directory? \");\n          ss = mmkey(MMKeyAreaType::dirs);\n          if (ss[0] == '?') {\n            dirlist(1);\n            dliscan1(dn);\n          }\n        }\n        while (!a()->sess().hangup() && ss[0] == '?');\n\n        nDestDirNum = -1;\n        if (ss[0]) {\n          for (auto i1 = 0; i1 < a()->dirs().size(); i1++) {\n            if (ss == a()->udir[i1].keys) {\n              nDestDirNum = i1;\n            }\n          }\n        }\n\n        if (a()->batch().size() > 1) {\n          bout.outstr(\"|#5Move all tagged files? \");\n          if (bin.yesno()) {\n            bulk_move = 1;\n            bulk_dir = nDestDirNum;\n          }\n        }\n      } else {\n        nDestDirNum = bulk_dir;\n      }\n\n      if (nDestDirNum != -1) {\n        ok = true;\n        nDestDirNum = a()->udir[nDestDirNum].subnum;\n        dliscan1(nDestDirNum);\n        if (recno(f.aligned_filename()) > 0) {\n          ok = false;\n          bout.nl();\n          bout.outstr(\"Filename already in use in that directory.\\r\\n\");\n        }\n        if (a()->current_file_area()->number_of_files() >= a()->dirs()[nDestDirNum].maxfiles) {\n          ok = false;\n          bout.outstr(\"\\r\\nToo many files in that directory.\\r\\n\");\n        }\n        if (File::freespace_for_path(a()->dirs()[nDestDirNum].path) <\n            static_cast<long>(f.numbytes() / 1024L) + 3) {\n          ok = false;\n          bout.outstr(\"\\r\\nNot enough disk space to move it.\\r\\n\");\n        }\n        dliscan();\n      } else {\n        ok = false;\n      }\n    } else {\n      ok = false;\n    }\n    if (ok && !done) {\n      if (!bulk_move) {\n        bout.outstr(\"|#5Reset upload time for file? \");\n        if (bin.yesno()) {\n          f.set_date(DateTime::now());\n        }\n      } else {\n          f.set_date(DateTime::now());\n      }\n      --cp;\n      auto ss = source_filearea->ReadExtendedDescriptionAsString(f).value_or(\"\");\n      if (source_filearea->DeleteFile(f, nRecNum)) {\n        source_filearea->Save();\n      }\n      auto dest_fn = FilePath(a()->dirs()[nDestDirNum].path, f);\n      dliscan1(nDestDirNum);\n      auto* area = a()->current_file_area();\n      if (area->AddFile(f)) {\n        area->Save();\n      }\n      auto current_file_position = area->FindFile(f);\n      if (!ss.empty()) {\n        f.set_extended_description(true);\n        if (current_file_position.has_value()) {\n          area->AddExtendedDescription(f, current_file_position.value(), ss);\n        } else {\n          area->AddExtendedDescription(f.filename(), ss);\n        }\n      }\n      if (src_fn != dest_fn && File::Exists(src_fn)) {\n        File::Rename(src_fn, dest_fn);\n      }\n      bout.outstr(\"\\r\\nFile moved.\\r\\n\");\n    }\n    dliscan();\n    nRecNum = nrecno(move_fn, cp);\n  }\n  tmp_disable_conf(false);\n  return ret;\n}\n\nvoid do_batch_sysop_command(int mode, const std::string& file_name) {\n  const auto save_curdir = a()->current_user_dir_num();\n  bout.cls();\n\n  if (a()->batch().numbatchdl() > 0) {\n    auto done = false;\n    for (auto it = begin(a()->batch().entry); it != end(a()->batch().entry) && !done;) {\n      const auto& b = *it;\n      if (b.sending()) {\n        switch (mode) {\n        case SYSOP_DELETE:\n          if (!remove_filename(b.aligned_filename(), b.dir())) {\n            done = true;\n          } else {\n            it = a()->batch().delbatch(it);\n            continue;\n          }\n          break;\n        case SYSOP_RENAME:\n          if (!rename_filename(b.aligned_filename(), b.dir())) {\n            done = true;\n          } else {\n            it = a()->batch().delbatch(it);\n            continue;\n          }\n          break;\n        case SYSOP_MOVE:\n          if (!move_filename(b.aligned_filename(), b.dir())) {\n            done = true;\n          } else {\n            it = a()->batch().delbatch(it);\n            continue;\n          }\n          break;\n        }\n      }\n      ++it;\n    }\n  } else {\n    // Just act on the single file\n    switch (mode) {\n    case SYSOP_DELETE:\n      remove_filename(file_name, a()->current_user_dir().subnum);\n      break;\n    case SYSOP_RENAME:\n      rename_filename(file_name, a()->current_user_dir().subnum);\n      break;\n    case SYSOP_MOVE:\n      move_filename(file_name, a()->current_user_dir().subnum);\n      break;\n    }\n  }\n  a()->set_current_user_dir_num(save_curdir);\n  dliscan();\n}\n\nint search_criteria(search_record* sr) {\n  if (a()->current_user_dir().subnum < 0 || a()->udir.empty()) {\n    // We don't have any current directory, can not list files.\n    bout.pl(\"|#6No directories available.\");\n    return 0;\n  }\n  auto all_conf = true;\n\n  const auto useconf = ok_multiple_conf(a()->user(), a()->uconfdir);\n\nLP_SEARCH_HELP:\n  sr->search_extended = lp_config.search_extended_on ? true : false;\n\n  bout.cls();\n  bout.printfile(LPSEARCH_NOEXT);\n\n  auto done = false;\n  char x{0};\n  while (!done) {\n    bout.goxy(1, 15);\n    for (auto i = 0; i < 9; i++) {\n      bout.goxy(1, 15 + i);\n      bout.clreol();\n    }\n    bout.goxy(1, 15);\n\n    bout.print(\"|#9A)|#2 Filename (wildcards) :|#2 {}\\r\\n\", sr->filemask);\n    bout.print(\"|#9B)|#2 Text (no wildcards)  :|#2 {}\\r\\n\", sr->search);\n    const auto dir_name = stripcolors(a()->dirs()[a()->current_user_dir().subnum].name);\n    bout.print(\"|#9C)|#2 Which Directories    :|#2 {}\\r\\n\", \n               sr->alldirs == THIS_DIR ? dir_name : sr->alldirs == ALL_DIRS ? \"All dirs\" : \"Dirs in NSCAN\");\n    const auto conf_name =\n        stripcolors(a()->uconfdir[a()->sess().current_user_dir_conf_num()].conf_name);\n    bout.print(\"|#9D)|#2 Which Conferences    :|#2 {}\\r\\n\", all_conf ? \"All Conferences\" : conf_name);\n    bout.print(\"|#9E)|#2 Extended Description :|#2 {}\\r\\n\", sr->search_extended ? \"Yes\" : \"No \");\n    bout.nl();\n    bout.outstr(\"|15Select item to change |#2<CR>|15 to start search |#2Q=Quit|15:|#0 \");\n\n    x = onek(\"QABCDE\\r?\");\n\n    switch (x) {\n    case 'A':\n      bout.outstr(\"Filename (wildcards okay) : \");\n      sr->filemask = bin.input(12, true);\n      if (sr->filemask[0]) {\n        if (okfn(sr->filemask)) {\n          if (sr->filemask.size() < 8) {\n            sysoplog(fmt::format(\"Filespec: {}\", sr->filemask));\n          } else {\n            if (contains(sr->filemask, '.')) {\n              sysoplog(fmt::format(\"Filespec: {}\", sr->filemask));\n            } else {\n              bout.print(\"|#6Invalid filename: {}\\r\\n\", sr->filemask);\n              bout.pausescr();\n              sr->filemask[0] = '\\0';\n            }\n          }\n        } else {\n          bout.print(\"|#6Invalid filespec: {}\\r\\n\", sr->filemask);\n          bout.pausescr();\n          sr->filemask[0] = 0;\n        }\n      }\n      break;\n\n    case 'B':\n      bout.outstr(\"Keyword(s) : \");\n      sr->search = bin.input_upper(60);\n      if (sr->search[0]) {\n        sysoplog(StrCat(\"Keyword: \", sr->search));\n      }\n      break;\n\n    case 'C':\n      ++sr->alldirs;\n      if (sr->alldirs >= 3) {\n        sr->alldirs = 0;\n      }\n      break;\n\n    case 'D':\n      all_conf = !all_conf;\n      break;\n\n    case 'E':\n      sr->search_extended = !sr->search_extended;\n      break;\n\n    case 'Q':\n      return 0;\n\n    case '\\r':\n      done = true;\n      break;\n\n    case '?':\n      goto LP_SEARCH_HELP;\n\n    }\n  }\n\n  if (sr->search[0] == ' ' && sr->search[1] == 0) {\n    sr->search[0] = 0;\n  }\n\n  if (useconf && all_conf) {\n    // toggle conferences off\n    tmp_disable_conf(true);\n  }\n\n  return x;\n}\n\nvoid view_file(const std::string& aligned_file_name) {\n  bout.cls();\n  dliscan();\n  auto abort = false;\n  auto i = recno(aligned_file_name);\n  do {\n    if (i > 0) {\n      auto f = a()->current_file_area()->ReadFile(i);\n      const auto i1 = list_arc_out(stripfn(f.unaligned_filename()),\n                                   a()->dirs()[a()->current_user_dir().subnum].path);\n      if (i1) {\n        abort = true;\n      }\n      bin.checka(&abort);\n      i = nrecno(aligned_file_name, i);\n    }\n  }\n  while (i > 0 && !a()->sess().hangup() && !abort);\n  bout.nl();\n  bout.pausescr();\n}\n\nint lp_try_to_download(const std::string& file_mask, int dn) {\n  int rtn;\n  auto abort = false;\n\n  dliscan1(dn);\n  auto i = recno(file_mask);\n  if (i <= 0) {\n    bin.checka(&abort);\n    return abort ? -1 : 0;\n  }\n  bool ok = true;\n\n  foundany = 1;\n  do {\n    a()->tleft(true);\n    auto f = a()->current_file_area()->ReadFile(i);\n\n    if (!(f.u().mask & mask_no_ratio)) {\n      if (!ratio_ok()) {\n        return -2;\n      }\n    }\n\n    write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_ONLINE);\n    auto d = fmt::sprintf(\"%-40.40s\", f.u().description);\n    abort = false;\n    rtn = add_batch(d, f.aligned_filename(), dn, f.numbytes());\n\n    if (abort || rtn == -3) {\n      ok = false;\n    } else {\n      i = nrecno(file_mask, i);\n    }\n  }\n  while (i > 0 && ok && !a()->sess().hangup());\n  if (rtn == -2) {\n    return -2;\n  }\n  return abort || rtn == -3 ? -1 : 1;\n}\n\nvoid download_plus(const std::string& file_name) {\n  if (a()->batch().numbatchdl() != 0) {\n    bout.nl();\n    bout.outstr(\"|#2Download files in your batch queue (|#1Y/n|#2)? \");\n    if (bin.noyes()) {\n      batchdl(1);\n      return;\n    }\n  }\n  if (file_name.empty()) {\n    return;\n  }\n  auto fn{file_name};\n\n  if (strchr(fn.c_str(), '.') == nullptr) {\n    fn += \".*\";\n  }\n  fn = aligns(fn);\n  if (lp_try_to_download(fn, a()->current_user_dir().subnum) == 0) {\n    bout.outstr(\"\\r\\nSearching all directories.\\r\\n\\n\");\n    auto dn = 0;\n    auto count = 0;\n    auto color = 3;\n    foundany = 0;\n    bout.outstr(\"\\r|#2Searching \");\n    while (dn < a()->dirs().size()) {\n      count++;\n      bout.ansic(color);\n      bout.outstr(\".\");\n      if (count == NUM_DOTS) {\n        bout.outstr(\"\\r\");\n        bout.outstr(\"|#2Searching \");\n        color++;\n        count = 0;\n        if (color == 4) {\n          color++;\n        }\n        if (color == 10) {\n          color = 0;\n        }\n      }\n      if (lp_try_to_download(fn, a()->udir[dn].subnum) < 0) {\n        break;\n      }\n      dn++;\n    }\n    if (!foundany) {\n      bout.outstr(\"File not found.\\r\\n\\n\");\n    }\n  }\n}\n\nvoid request_file(const std::string& file_name) {\n  bout.cls();\n  bout.nl();\n\n  bout.printfile(LPFREQ_NOEXT);\n  bout.outstr(\"|#2File missing.  Request it? \");\n\n  if (bin.noyes()) {\n    ssm(1) << a()->user()->name() << \" is requesting file \" << file_name;\n    bout.outstr(\"File request sent\\r\\n\");\n  } else {\n    bout.outstr(\"File request NOT sent\\r\\n\");\n  }\n  bout.pausescr();\n}\n"
  },
  {
    "path": "bbs/listplus.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_LISTPLUS_H__\n#define __INCLUDED_LISTPLUS_H__\n\n#include \"bbs/common.h\"\n#include \"sdk/wwivcolors.h\"\n\nextern int foundany;\nstruct uploadsrec;\n\n// This is the place the first file will be printed, which defaults to line\n// 3, if you modify the file listing header, this will need to be changed\n// depending on where the file will need to start after your modification\nstatic constexpr int FIRST_FILE_POS = 3;\n\n// Defines for the sysop commands\nstatic constexpr int SYSOP_DELETE = 1;\nstatic constexpr int SYSOP_RENAME = 2;\nstatic constexpr int SYSOP_MOVE = 3;\n\n#pragma pack(push, 1)\n\nstruct listplus_config {\n  uint8_t unused_at_head[12]; // was: long fi, lssm, sent;\n\n  // Side menu colors  (fore+(back<<4))\n  int16_t normal_highlight, normal_menu_item, current_highlight, current_menu_item;\n\n  // Foreground only\n  int16_t tagged_color, file_num_color;\n\n  // Color for 'found' text when searching\n  int16_t found_fore_color, found_back_color;\n\n  // What file you are on, its color (fore+(back<<4))\n  int16_t current_file_color;\n\n  // if set to 0, will use the users info, otherwise it will show up to\n  // this variable, no more\n  int16_t max_screen_lines_to_show;\n\n  // If users extended description setting is lower than this, it will force\n  // this amount to show (good for people who leave it at 0)\n  int16_t show_at_least_extended;\n\n  // Toggles\n  unsigned int edit_enable : 1;\n  unsigned int request_file : 1;\n  unsigned int colorize_found_text : 1;\n  unsigned int search_extended_on : 1;\n\n  unsigned int simple_search : 1;\n  unsigned int no_configuration : 1;\n  unsigned int check_exist : 1;\n  unsigned int xxxxxxxxxxxxxxxxx : 9;\n\n  int16_t forced_config;\n};\n\n#pragma pack(pop)\n\nextern listplus_config lp_config;\n\nvoid printtitle_plus();\nint first_file_pos();\nvoid print_searching(search_record* search_rec);\nint listfiles_plus(int type);\nint lp_add_batch(const std::string& file_name, int dn, int fs);\nint printinfo_plus(uploadsrec* upload_record, int filenum, int marked, int LinesLeft,\n                   search_record* search_rec);\nint print_extended(const std::string& file_name, int numlist, int indent,\n                        wwiv::sdk::Color color, search_record* search_rec);\nvoid show_fileinfo(uploadsrec* upload_record);\nint check_lines_needed(uploadsrec* upload_record);\nint prep_search_rec(search_record* r, int type);\nint calc_max_lines();\nvoid load_lp_config();\nvoid save_lp_config();\nvoid sysop_configure();\nshort SelectColor(int which);\nvoid config_file_list();\nvoid do_batch_sysop_command(int mode, const std::string& file_name);\nint search_criteria(search_record* sr);\nvoid view_file(const std::string& aligned_file_name);\nint lp_try_to_download(const std::string& file_mask, int dn);\nvoid download_plus(const std::string& file_name);\nvoid request_file(const std::string& file_name);\n\n#endif // __INCLUDED_LISTPLUS_H__\n"
  },
  {
    "path": "bbs/lpfunc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/lpfunc.h\"\n\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl3.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/common.h\"\n#include \"bbs/listplus.h\"\n#include \"common/pause.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/output.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/files.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// Local function prototypes\nint  compare_criteria(search_record * sr, uploadsrec * ur);\nbool lp_compare_strings(const char *raw, const char *formula);\nbool lp_compare_strings_wh(const char *raw, const char *formula, unsigned *pos, int size);\nint  lp_get_token(const char *formula, unsigned *pos);\nint  lp_get_value(const char *raw, const char *formula, unsigned *pos);\n\n// These are defined in listplus.cpp\nextern int bulk_move;\nextern bool ext_is_on;\n\nstatic void drawfile(int filepos, int filenum) {\n  bout.clear_lines_listed();\n  bout.PutsXYSC(4, filepos + first_file_pos(), lp_config.current_file_color, fmt::format(\"{:>3}|#0\", filenum));\n  bout.goxy(4, filepos + first_file_pos());\n}\n\nstatic void undrawfile(int filepos, int filenum) {\n  bout.clear_lines_listed();\n  bout.PutsXYSC(4, filepos + first_file_pos(), lp_config.file_num_color, fmt::format(\"{:>3}|#0\", filenum));\n}\n\nstatic void prep_menu_items(std::vector<std::string>* menu_items) {\n  menu_items->push_back(\"Next\");\n  menu_items->push_back(\"Prev\");\n  menu_items->push_back(\"Tag\");\n  menu_items->push_back(\"Info\");\n  menu_items->push_back(\"ViewZip\");\n\n  if (a()->sess().using_modem()) {\n    menu_items->push_back(\"Dload\");\n  } else {\n    menu_items->push_back(\"Move\");\n  }\n\n  menu_items->push_back(\"+Dir\");\n  menu_items->push_back(\"-Dir\");\n  menu_items->push_back(\"Full-Desc\");\n  menu_items->push_back(\"Quit\");\n  menu_items->push_back(\"?\");\n  if (so()) {\n    menu_items->push_back(\"Sysop\");\n  }\n}\n\nstatic void load_listing() {\n  a()->user()->data.lp_options |= cfl_fname;\n  a()->user()->data.lp_options |= cfl_description;\n\n  for (auto& lp_color : a()->user()->data.lp_colors) {\n    if (lp_color == 0) {\n      lp_color = 7;\n    }\n  }\n}\n\nint listfiles_plus_function(int type) {\n  int file_handle[51];\n  char vert_pos[51];\n  int file_pos = 0, save_file_pos = 0, menu_pos = 0;\n  size_t save_dir = a()->current_user_dir_num();\n  bool sysop_mode = false;\n  side_menu_colors smc{};\n  search_record search_rec = {};\n\n  load_lp_config();\n\n  smc.normal_highlight = lp_config.normal_highlight;\n  smc.normal_menu_item = lp_config.normal_menu_item;\n  smc.current_highlight = lp_config.current_highlight;\n  smc.current_menu_item = lp_config.current_menu_item;\n\n  load_listing();\n\n  std::vector<std::string> menu_items;\n  prep_menu_items(&menu_items);\n\n  std::vector<uploadsrec> file_recs(a()->user()->screen_lines() + 20);\n  if (!prep_search_rec(&search_rec, type)) {\n    return 0;\n  }\n\n  auto max_lines = calc_max_lines();\n  auto all_done = false;\n\n  for (uint16_t this_dir = 0; this_dir < a()->udir.size() && !a()->sess().hangup() && !all_done;\n       this_dir++) {\n    int also_this_dir = a()->udir[this_dir].subnum;\n    auto scan_dir = false;\n    bin.checka(&all_done);\n\n    if (search_rec.alldirs == THIS_DIR) {\n      if (this_dir == save_dir) {\n        scan_dir = true;\n      }\n    } else {\n      if (a()->sess().qsc_n[also_this_dir / 32] & (1L << (also_this_dir % 32))) {\n        scan_dir = true;\n      }\n\n      if (search_rec.alldirs == ALL_DIRS && (type != LP_NSCAN_NSCAN)) {\n        scan_dir = true;\n      }\n    }\n\n    int save_first_file = 0;\n    if (scan_dir) {\n      a()->set_current_user_dir_num(this_dir);\n      dliscan();\n      int first_file = save_first_file = 1;\n      int amount = 0;\n      bool done = false;\n      int matches = 0;\n      int lines = 0;\n      int changedir = 0;\n\n      while (!done && !a()->sess().hangup() && !all_done) {\n        bin.checka(&all_done);\n        if (!amount) {\n          print_searching(&search_rec);\n        }\n        if (a()->current_file_area()->number_of_files()) {\n          changedir = 0;\n          bool force_menu = false;\n          auto f = a()->current_file_area()->ReadFile(first_file + amount);\n          file_recs[matches] = f.u();\n          if (compare_criteria(&search_rec, &file_recs[matches])) {\n            int lines_left = max_lines - lines;\n            int needed = check_lines_needed(&file_recs[matches]);\n            if (needed <= lines_left) {\n              if (!matches) {\n                printtitle_plus();\n              }\n              file_handle[matches] = first_file + amount;\n              vert_pos[matches] = static_cast<char>(lines);\n              auto marked = a()->batch().contains_file(file_recs[matches].filename);\n              int lines_used = printinfo_plus(&file_recs[matches], file_handle[matches], marked,\n                                              lines_left, &search_rec);\n              if (lines_used > 1 && lines_used < lines_left) {\n                bout.nl();\n                ++lines_used;\n              }\n              lines += lines_used;\n              ++matches;\n            } else {\n              force_menu = true;\n            }\n          }\n          if (!force_menu) {\n            ++amount;\n          }\n\n          if (lines >= max_lines ||\n              a()->current_file_area()->number_of_files() < first_file + amount || force_menu) {\n            if (matches) {\n              file_pos = save_file_pos;\n              drawfile(vert_pos[file_pos], file_handle[file_pos]);\n              bool redraw = true;\n              save_file_pos = 0;\n              bool menu_done = false;\n              while (!menu_done && !a()->sess().hangup()) {\n                int command = side_menu(&menu_pos, redraw, menu_items, 2, max_lines + first_file_pos() + 1, &smc);\n                redraw = true;\n                bulk_move = 0;\n                bout.ansic(0);\n                if (do_sysop_command(command)) {\n                  menu_done = true;\n                  amount = lines = matches = 0;\n                  save_file_pos = file_pos;\n                }\n                if (command == COMMAND_PAGEUP) {\n                  command = EXECUTE;\n                  menu_pos = 1;\n                }\n                if (command == COMMAND_PAGEDN) {\n                  command = EXECUTE;\n                  menu_pos = 0;\n                }\n                switch (command) {\n                case CX:\n                case AX:\n                  goto TOGGLE_EXTENDED;\n                case '?':\n                case CO:\n                  bout.cls();\n                  bout.print_help_file(LISTPLUS_HLP);\n                  bout.pausescr();\n                  menu_done = true;\n                  amount = lines = matches = 0;\n                  save_file_pos = file_pos;\n                  break;\n                case COMMAND_DOWN:\n                  undrawfile(vert_pos[file_pos], file_handle[file_pos]);\n                  ++file_pos;\n                  if (file_pos >= matches) {\n                    file_pos = 0;\n                  }\n                  drawfile(vert_pos[file_pos], file_handle[file_pos]);\n                  redraw = false;\n                  break;\n                case COMMAND_UP:\n                  undrawfile(vert_pos[file_pos], file_handle[file_pos]);\n                  if (!file_pos) {\n                    file_pos = matches - 1;\n                  } else {\n                    --file_pos;\n                  }\n                  drawfile(vert_pos[file_pos], file_handle[file_pos]);\n                  redraw = false;\n                  break;\n                case SPACE:\n                  goto ADD_OR_REMOVE_BATCH;\n                case EXECUTE:\n                  switch (menu_pos) {\n                  case 0:\n                    save_first_file = first_file;\n                    first_file += amount;\n                    if (first_file > a()->current_file_area()->number_of_files()) {\n                      done = true;\n                    }\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    break;\n                  case 1:\n                    if (save_first_file >= first_file) {\n                      if (first_file > 5) {\n                        first_file -= 5;\n                      } else {\n                        first_file = 1;\n                      }\n                    } else {\n                      first_file = save_first_file;\n                    }\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    break;\n                  case 2:\n                    if (sysop_mode) {\n                      do_batch_sysop_command(SYSOP_DELETE, file_recs[file_pos].filename);\n                      menu_done = true;\n                      save_file_pos = file_pos = 0;\n                      amount = lines = matches = 0;\n                    } else {\nADD_OR_REMOVE_BATCH:\n                      if (a()->batch().FindBatch(file_recs[file_pos].filename) > -1) {\n                        a()->batch().RemoveBatch(file_recs[file_pos].filename);\n                        redraw = false;\n                      }\n                      else if (!ratio_ok() && !sysop_mode) {\n                        menu_done = true;\n                        amount = lines = matches = 0;\n                        save_file_pos = file_pos;\n                        bout.pausescr();\n                      } else {\n                        redraw = false;\n                        if (!(a()->dirs()[a()->current_user_dir().subnum].mask & mask_cdrom) && !sysop_mode) {\n                          auto tf =\n                              FilePath(a()->dirs()[a()->current_user_dir().subnum].path,\n                                             wwiv::sdk::files::unalign(file_recs[file_pos].filename));\n                          if (sysop_mode || !a()->sess().using_modem() || File::Exists(tf)) {\n                            lp_add_batch(file_recs[file_pos].filename, a()->current_user_dir().subnum,\n                                         file_recs[file_pos].numbytes);\n                          } else if (lp_config.request_file) {\n                            menu_done = true;\n                            amount = lines = matches = 0;\n                            request_file(file_recs[file_pos].filename);\n                          }\n                        } else {\n                          lp_add_batch(file_recs[file_pos].filename, a()->current_user_dir().subnum,\n                                       file_recs[file_pos].numbytes);\n                        }\n                      }\n                      bout.goxy(1, first_file_pos() + vert_pos[file_pos]);\n                      bout.printf(\n                          \"|%02d %c \", lp_config.tagged_color,\n                          a()->batch().contains_file(file_recs[file_pos].filename) ? '\\xFE' : ' ');\n                      undrawfile(vert_pos[file_pos], file_handle[file_pos]);\n                      ++file_pos;\n                      if (file_pos >= matches) {\n                        file_pos = 0;\n                      }\n                      drawfile(vert_pos[file_pos], file_handle[file_pos]);\n                      redraw = false;\n                    }\n                    break;\n                  case 3:\n                    if (!sysop_mode) {\n                      show_fileinfo(&file_recs[file_pos]);\n                      menu_done = true;\n                      save_file_pos = file_pos;\n                      amount = lines = matches = 0;\n                    } else {\n                      do_batch_sysop_command(SYSOP_RENAME, file_recs[file_pos].filename);\n                      menu_done = true;\n                      save_file_pos = file_pos;\n                      amount = lines = matches = 0;\n                    }\n                    menu_pos = 0;\n                    break;\n                  case 4:\n                    if (!sysop_mode) {\n                      view_file(file_recs[file_pos].filename);\n                      menu_done = true;\n                      save_file_pos = file_pos;\n                      amount = lines = matches = 0;\n                    } else {\n                      do_batch_sysop_command(SYSOP_MOVE, file_recs[file_pos].filename);\n                      menu_done = true;\n                      save_file_pos = file_pos = 0;\n                      amount = lines = matches = 0;\n                    }\n                    menu_pos = 0;\n                    break;\n                  case 5:\n                    if (!sysop_mode && a()->sess().using_modem()) {\n                      bout.cls();\n                      menu_done = true;\n                      save_file_pos = file_pos;\n                      amount = lines = matches = 0;\n                      if (!ratio_ok()) {\n                        bout.pausescr();\n                      } else {\n                        if (!ratio_ok()  && !sysop_mode) {\n                          menu_done = true;\n                          amount = lines = matches = 0;\n                          save_file_pos = file_pos;\n                          bout.pausescr();\n                        } else {\n                          redraw = false;\n                          if (!(a()->dirs()[a()->current_user_dir().subnum].mask & mask_cdrom) && !sysop_mode) {\n                            auto tf =\n                                FilePath(a()->dirs()[a()->current_user_dir().subnum].path,\n                                             wwiv::sdk::files::unalign(file_recs[file_pos].filename));\n                            if (sysop_mode || !a()->sess().using_modem() || File::Exists(tf)) {\n                              lp_add_batch(file_recs[file_pos].filename, a()->current_user_dir().subnum,\n                                           file_recs[file_pos].numbytes);\n                            } else if (lp_config.request_file) {\n                              menu_done = true;\n                              amount = lines = matches = 0;\n                              request_file(file_recs[file_pos].filename);\n                            }\n                          } else {\n                            lp_add_batch(file_recs[file_pos].filename, a()->current_user_dir().subnum,\n                                         file_recs[file_pos].numbytes);\n                          }\n                          download_plus(file_recs[file_pos].filename);\n                        }\n                      }\n                      dliscan();\n                    } else if (!sysop_mode) {\n                      do_batch_sysop_command(SYSOP_MOVE, file_recs[file_pos].filename);\n                      menu_done = true;\n                      save_file_pos = file_pos = 0;\n                      amount = lines = matches = 0;\n                    } else {\n                      sysop_configure();\n                      smc.normal_highlight = lp_config.normal_highlight;\n                      smc.normal_menu_item = lp_config.normal_menu_item;\n                      smc.current_highlight = lp_config.current_highlight;\n                      smc.current_menu_item = lp_config.current_menu_item;\n                      menu_done = true;\n                      save_file_pos = file_pos;\n                      amount = lines = matches = 0;\n                    }\n                    menu_pos = 0;\n                    break;\n                  case 6:\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    first_file = 1;\n                    changedir = 1;\n                    if (a()->current_user_dir_num() < a()->dirs().size() - 1\n                        && a()->udir[a()->current_user_dir_num() + 1].subnum >= 0) {\n                      a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n                      ++this_dir;\n                    } else {\n                      a()->set_current_user_dir_num(0);\n                      this_dir = 0;\n                    }\n                    if (!type) {\n                      save_dir = a()->current_user_dir_num();\n                    }\n                    dliscan();\n                    menu_pos = 0;\n                    break;\n                  case 7:\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    first_file = 1;\n                    changedir = -1;\n                    if (a()->current_user_dir_num() > 0) {\n                      a()->set_current_user_dir_num(a()->current_user_dir_num() - 1);\n                      --this_dir;\n                    } else {\n                      while ((a()->udir[a()->current_user_dir_num() + 1].subnum >= 0)\n                             && (a()->current_user_dir_num() < a()->dirs().size() - 1)) {\n                        a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n                      }\n                      this_dir = a()->current_user_dir_num();\n                    }\n                    if (!type) {\n                      save_dir = a()->current_user_dir_num();\n                    }\n                    dliscan();\n                    menu_pos = 0;\n                    break;\n                  case 8:\nTOGGLE_EXTENDED:\n                    ext_is_on = !ext_is_on;\n                    a()->user()->full_descriptions(!a()->user()->full_descriptions());\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    file_pos = 0;\n                    save_file_pos = file_pos;\n                    menu_pos = 0;\n                    break;\n                  case 9:\n                    menu_done = true;\n                    done = true;\n                    amount = lines = matches = 0;\n                    all_done = true;\n                    bout.clear_lines_listed();\n                    break;\n                  case 10:\n                    bout.cls();\n                    bout.print_help_file(LISTPLUS_HLP);\n                    bout.pausescr();\n                    menu_done = true;\n                    amount = lines = matches = 0;\n                    save_file_pos = file_pos;\n                    break;\n                  case 11:\n                    if (so() && !sysop_mode) {\n                      sysop_mode = true;\n                      menu_items[2] =  \"Delete\";\n                      menu_items[3] = \"Rename\";\n                      menu_items[4] = \"Move\";\n                      menu_items[5] = \"Config\";\n                      menu_items[11] = \"Back\";\n                    } else {\n                      sysop_mode = false;\n                      prep_menu_items(&menu_items);\n                    }\n                    bout.outchr('\\r');\n                    bout.clreol();\n                    break;\n                  }\n                  break;\n                case GET_OUT:\n                  menu_done = true;\n                  done = true;\n                  all_done = true;\n                  amount = lines = matches = 0;\n                  break;\n                }\n              }\n            }\n            else {\n              if (!changedir) {\n                done = true;\n              } else if (changedir == 1) {\n                if ((a()->current_user_dir_num() < a()->dirs().size() - 1)\n                    && (a()->udir[a()->current_user_dir_num() + 1].subnum >= 0)) {\n                  a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n                } else {\n                  a()->set_current_user_dir_num(0);\n                }\n                dliscan();\n              } else {\n                if (a()->current_user_dir_num() > 0) {\n                  a()->set_current_user_dir_num(a()->current_user_dir_num() - 1);\n                } else {\n                  while ((a()->udir[a()->current_user_dir_num() + 1].subnum >= 0)\n                         && (a()->current_user_dir_num() < a()->dirs().size() - 1)) {\n                    a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n                  }\n                }\n                dliscan();\n              }\n            }\n          }\n        } else {\n          if (!changedir) {\n            done = true;\n          } else if (changedir == 1) {\n            if (a()->current_user_dir_num() < a()->dirs().size() - 1\n                && a()->udir[a()->current_user_dir_num() + 1].subnum >= 0) {\n              a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n            } else {\n              a()->set_current_user_dir_num(0);\n            }\n            dliscan();\n          } else {\n            if (a()->current_user_dir_num() > 0) {\n              a()->set_current_user_dir_num(a()->current_user_dir_num() - 1);\n            } else {\n              while ((a()->udir[a()->current_user_dir_num() + 1].subnum >= 0)\n                     && (a()->current_user_dir_num() < a()->dirs().size() - 1)) {\n                a()->set_current_user_dir_num(a()->current_user_dir_num() + 1);\n              }\n            }\n            dliscan();\n          }\n        }\n      }\n    }\n  }\n\n  return all_done ? 1 : 0;\n}\n\nstatic constexpr char STR_AND = '&';\nstatic constexpr char STR_SPC = ' ';\nstatic constexpr char STR_OR = '|';\nstatic constexpr char STR_NOT = '!';\nstatic constexpr char STR_OPEN_PAREN = '(';\nstatic constexpr char STR_CLOSE_PAREN = ')';\n\nint compare_criteria(search_record * sr, uploadsrec * ur) {\n  // \"        .   \"\n  if (sr->filemask != \"        .   \") {\n    if (!wwiv::sdk::files::aligned_wildcard_match(sr->filemask, ur->filename)) {\n      return 0;\n    }\n  }\n  // the above test was passed if it got here\n\n\n  if (sr->nscandate) {\n    if (ur->daten < sr->nscandate) {\n      return 0;\n    }\n  }\n\n  // the above test was passed if it got here\n  if (!sr->search[0]) {\n    // this is return 1 because top two tests were passed\n    // and we are not searching on text, so it is assume to\n    // have passed the test\n    return 1;                                 \n  }\n  // we want to search the filename, description and ext description\n  // as one unit, that way, if you specify something like 'one & two\n  // and one is located in the description and two is in the\n  // extended description, then it will properly find the search\n  std::string buff;\n  if (sr->search_extended && ur->mask & mask_extended) {\n    buff = a()->current_file_area()->ReadExtendedDescriptionAsString(ur->filename).value_or(\"\");\n  }\n\n  if (buff.empty()) {\n    // Something had something.\n    return 0;\n  }\n\n  // tag the file name and description on to the end of the extended\n  // description (if there is one)\n  buff += StrCat(\" \", ur->filename, \" \", ur->description);\n\n  if (lp_compare_strings(buff.c_str(), sr->search.c_str())) {\n    return 1;\n  }\n\n  // failed search test, so exit with 0\n  return 0;\n}\n\nbool lp_compare_strings(const char *raw, const char *formula) {\n  unsigned i = 0;\n\n  return lp_compare_strings_wh(raw, formula, &i, ssize(formula));\n}\n\nbool lp_compare_strings_wh(const char *raw, const  char *formula, unsigned *pos, int size) {\n  bool rvalue;\n\n  auto lvalue = lp_get_value(raw, formula, pos) ? true : false;\n  while (*pos < static_cast<unsigned>(size)) {\n    const auto token = lp_get_token(formula, pos);\n\n    switch (token) {\n    case STR_SPC:                         // Added\n    case STR_AND:\n      rvalue = lp_compare_strings_wh(raw, formula, pos, size);\n      lvalue = lvalue && rvalue;\n      break;\n\n    case STR_OR:\n      rvalue = lp_compare_strings_wh(raw, formula, pos, size);\n      lvalue = lvalue || rvalue;\n      break;\n\n    case STR_CLOSE_PAREN:\n    case 0:\n      return lvalue;\n\n    default:\n      return lvalue;\n    }\n  }\n  return lvalue;\n}\n\nint lp_get_token(const char *formula, unsigned *pos) {\n  auto tpos = 0;\n\n  while (formula[*pos] && isspace(formula[*pos])) {\n    ++* pos;\n  }\n\n  if (isalpha(formula[*pos])) {\n    // remove isspace to split by word basis\n    while (isalnum(formula[*pos]) || isspace(formula[*pos])) {\n      ++tpos;\n      ++*pos;\n    }\n  }\n  ++*pos;\n  return formula[*pos - 1];\n}\n\nint lp_get_value(const char *raw, const char *formula, unsigned *pos) {\n  char szBuffer[255];\n  int tpos = 0;\n  int sign = 1, started_number = 0;\n\n  while (formula[*pos] && isspace(formula[*pos])) {\n    ++* pos;\n  }\n  int x = formula[*pos];\n\nOPERATOR_CHECK_1:\n  switch (x) {\n  case STR_NOT:\n    sign = !sign;\n    ++*pos;\n    if (formula[*pos]) {\n      x = formula[*pos];\n      goto OPERATOR_CHECK_1;\n    }\n    return 0;\n\n  case STR_AND:\n  case STR_SPC:\n  case STR_OR:\n    return 0;\n  }\n\n  switch (x) {\n  case STR_OPEN_PAREN:\n    ++*pos;\n    if (lp_compare_strings_wh(raw, formula, pos, ssize(formula))) {\n      return (sign) ? 1 : 0;\n    } else {\n      return (sign) ? 0 : 1;\n    }\n  }\n\n  bool done = false;\n  while (!done && formula[*pos]) {\n    x = formula[*pos];\n    switch (x) {\n    case STR_NOT:\n      if (started_number) {\n        done = true;\n        break;\n      }\n      sign = !sign;\n      ++*pos;\n      continue;\n    case STR_AND:\n    case STR_SPC:\n    case STR_OR:\n    case STR_OPEN_PAREN:\n    case STR_CLOSE_PAREN: {\n      done = true;\n      break;\n    }\n    default:\n      started_number = 1;\n      szBuffer[tpos] = static_cast<char>(x);\n      ++tpos;\n      ++*pos;\n      break;\n    }\n  }\n  szBuffer[tpos] = 0;\n  StringTrim(szBuffer);\n\n  if (ifind_first(raw, szBuffer)) {\n    return (sign ? 1 : 0);\n  }\n  return (sign ? 0 : 1);\n}\n\n\n"
  },
  {
    "path": "bbs/lpfunc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_LPFUNC_H__\n#define __INCLUDED_BBS_LPFUNC_H__\n\nint  listfiles_plus_function(int type);\n\n#endif  // __INCLUDED_BBS_LPFUNC_H__\n"
  },
  {
    "path": "bbs/make_abs_cmd.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MAKE_ABS_CMD_H\n#define INCLUDED_BBS_MAKE_ABS_CMD_H\n\n#include <filesystem>\n#include <string>\n\n/**\n * Using the root directory, turn out into an absolute path\n * to a command.\n */\nvoid make_abs_cmd(const std::filesystem::path& root, std::string* out);\n\n#endif\n"
  },
  {
    "path": "bbs/make_abs_cmd_os2.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"bbs/make_abs_cmd.h\"\r\n#include \"bbs/bbs.h\"\r\n#include \"bbs/application.h\"\r\n\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n\r\n#include <direct.h>\r\n#include <filesystem>\r\n#include <string>\r\n#include <vector>\r\n\r\n#define __USE_EMX\r\n#include <stdlib.h>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::strings;\r\n\r\nvoid make_abs_cmd(const std::filesystem::path& root, std::string* out) {\r\n  if (out->find(\"\\\\\") == std::string::npos) {\r\n        // Use current path of we don't have an abs path.\r\n    std::string s(*out);\r\n    File f(FilePath(a()->bbspath(), s));\r\n    *out = f.full_pathname();\r\n  }\r\n}\r\n\r\n"
  },
  {
    "path": "bbs/make_abs_cmd_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                                WWIV Version 5                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/make_abs_cmd.h\"\n\n#include <sys/stat.h>\n#include <unistd.h>\n#include <string>\n\n#include \"bbs/bbs.h\"\n#include \"bbs/application.h\"\n#include \"core/file.h\"\n#include <filesystem>\n\nusing std::string;\nusing namespace wwiv::core;\n\nvoid make_abs_cmd(const std::filesystem::path& root, std::string* out) {\n  if (out->find(\"/\") == std::string::npos) {\n\t// Use current path of we don't have an abs path.\n    std::string s(*out);\n    File f(FilePath(a()->bbspath(), s));\n    *out = f.full_pathname();\n  }\n}\n\n"
  },
  {
    "path": "bbs/make_abs_cmd_win32.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/make_abs_cmd.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <direct.h>\n#include <filesystem>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nvoid make_abs_cmd(const std::filesystem::path& root, std::string* out) {\n  \n  const std::vector<std::string> exts{\n    \"\",\n    \".com\",\n    \".exe\",\n    \".bat\",\n    \".btm\",\n    \".cmd\",\n  };\n\n  auto s1{*out};\n  const auto is_abs_with_drive = s1.size() > 2 && s1.at(1) == ':';\n\n  std::string s2;\n  if (is_abs_with_drive) {\n    if (s1.at(2) != '\\\\') {\n      auto* curdir = _getdcwd(to_upper_case_char(s1[0]) - 'A' + 1, nullptr, 0);\n      if (curdir && *curdir) {\n        s1 = fmt::format(\"{}:\\\\{}\\\\{}\", s1.front(), curdir, s1.substr(2));\n      } else {\n        s1 = fmt::format(\"{}:\\\\{}\", s1.front(), s1.substr(2));\n      }\n      free(curdir);\n    }\n  } else if (s1.front() == '\\\\') {\n    auto drive = root.string().front();\n    s1 = fmt::format(\"{}:{}\", drive, s1);\n  } else {\n    s2 = s1;\n    if (const auto wsidx = s2.find_first_of(\" \\t\"); wsidx != std::string::npos) {\n      if (s2.find(File::pathSeparatorChar) != std::string::npos) {\n        s1 = FilePath(root, s1).string();\n      }\n    }\n  }\n\n  if (const auto idx = s1.find(' '); idx != std::string::npos) {\n    s2 = fmt::format(\" {}\", s1.substr(idx + 1));\n    s1 = s1.substr(0, idx);\n  } else {\n    s2.clear();\n  }\n  for (const auto& ext : exts) {\n    if (ext.empty()) {\n      const auto last_slash = s1.find_last_of(File::pathSeparatorChar);\n      auto t = last_slash == std::string::npos ? s1 : s1.substr(last_slash + 1);\n      if (strchr(t.c_str(), '.') == nullptr) {\n        continue;\n      }\n    }\n    auto s = StrCat(s1, ext);\n    if (s1[1] == ':') {\n      if (File::Exists(s)) {\n        if (File::is_directory(s)) {\n          *out = FilePath(s, s2).string();\n        } else {\n          *out = StrCat(s, s2);\n        }\n        return;\n      }\n    } else {\n      if (File::Exists(s)) {\n        if (std::error_code ec; is_directory(root, ec) && !is_directory(FilePath(root, s), ec)) {\n          *out = StrCat(FilePath(root, s).string(), s2);\n        } else {\n          *out = FilePath(root, StrCat(s, s2)).string();\n        }\n        return;\n      }\n      char szFoundPath[4096];\n      if (const auto err = _searchenv_s(s.c_str(), \"PATH\", szFoundPath); err == 0 && strlen(szFoundPath) > 0) {\n        *out = StrCat(szFoundPath, s2);\n        return;\n      }\n    }\n  }\n\n  const auto maybe_dir = FilePath(root, s1);\n  if (std::error_code ec; File::Exists(maybe_dir) && is_directory(maybe_dir, ec)) {\n    *out = StrCat(maybe_dir.string(), s2);\n  } else {\n    *out = FilePath(root, StrCat(s1, s2)).string();\n  }\n}\n\n"
  },
  {
    "path": "bbs/make_abs_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/make_abs_cmd.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n\n#include \"gtest/gtest.h\"\n#include <filesystem>\n#include <filesystem>\n#include <string>\n\nusing wwiv::strings::StrCat;\nusing namespace wwiv::core;\n\nclass MakeAbsTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    helper.SetUp();\n    root = helper.app_->bbspath();\n  }\n  BbsHelper helper{};\n  std::filesystem::path root;\n};\n\n#ifdef _WIN32\n\nTEST_F(MakeAbsTest, NotUnderRoot) {\n  const std::string expected = \"c:\\\\windows\\\\system32\\\\cmd.exe foo\";\n  std::string cmdline = \"cmd foo\";\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\nTEST_F(MakeAbsTest, UnderRoot) {\n  const auto foo = helper.files().CreateTempFile(\"foo.exe\", \"\");\n  const auto expected = StrCat(foo.string(), \" bar\");\n  std::string cmdline = \"foo bar\";\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\nTEST_F(MakeAbsTest, UnderRoot_WithExt) {\n  const auto foo = helper.files().CreateTempFile(\"foo.exe\", \"\");\n  const auto expected = StrCat(foo.string(), \" bar\");\n  std::string cmdline = \"foo.exe bar\";\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\nTEST_F(MakeAbsTest, UnderRoot_SlashInParam) {\n  const auto foo = helper.files().CreateTempFile(\"foo.exe\", \"\");\n  const auto arg = StrCat(\" bar\", File::pathSeparatorChar, \"baz\");\n  const auto expected = StrCat(foo.string(), arg);\n  auto cmdline = StrCat(\"foo\", arg);\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\nTEST_F(MakeAbsTest, UnderRoot_SlashInParam_DoesNotExist) {\n  const auto foo = helper.files().CreateTempFilePath(\"foo\");\n  const auto arg = StrCat(\" bar\", File::pathSeparatorChar, \"baz\");\n  const auto expected = StrCat(foo.string(), arg);\n  auto cmdline = StrCat(\"foo\", arg);\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\nTEST_F(MakeAbsTest, DoesNotExist) {\n  const auto foo = helper.files().CreateTempFilePath(\"foo\");\n  const auto expected = StrCat(foo.string(), \" bar\");\n  std::string cmdline = \"foo bar\";\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\n#else \n\nTEST_F(MakeAbsTest, Smoke) {\n  File f(FilePath(helper.files().TempDir(), \"ls foo\"));\n  std::string expected = f.full_pathname();\n  std::string cmdline = \"ls foo\";\n  make_abs_cmd(root, &cmdline);\n  EXPECT_STRCASEEQ(expected.c_str(), cmdline.c_str());\n}\n\n#endif  // _WIN32\n"
  },
  {
    "path": "bbs/menus/config_menus.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/config_menus.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/sysoplog.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/findfiles.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/menus/menu_set.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::menus;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::bbs::menus {\n\nstatic bool ValidateMenuSet(const std::string& menu_set) {\n  // ensure the entry point exists\n  return File::Exists(FilePath(FilePath(a()->config()->menudir(), menu_set), \"main.mnu.json\"));\n}\n\nstatic std::map<int, menu_set_t> ListMenuDirs() {\n  std::map<int, menu_set_t> result;\n\n  bout.nl();\n  bout.pl(\"|#1Available Menus Sets\");\n  bout.pl(\"|#9============================\");\n\n  int num = 1;\n  const auto menu_directory = a()->config()->menudir();\n  auto menus = FindFiles(FilePath(menu_directory, \"*\"), FindFiles::FindFilesType::directories);\n\n  for (const auto& d : menus) {\n    MenuSet56 m(FilePath(menu_directory, d.name));\n    if (!check_acs(m.menu_set.acs)) {\n      VLOG(1) << \"check acs failed for: \" << d.name;\n      continue;\n    }\n    bout.print(\"|#2#{} |#1{:<8.8} |#9{:<60.60}\\r\\n\", num, m.menu_set.name, m.menu_set.description);\n    result.emplace(num, m.menu_set);\n    ++num;\n  }\n  bout.nl();\n  bout.ansic(0);\n  return result;\n}\n\n/**\n * Sets a menuset to one specified by 'name', returning true on success and\n * false otherwise.\n */\nstatic bool SetMenuSet(const menu_set_t& m) {\n  if (!ValidateMenuSet(m.name)) {\n    return false;\n  }\n\n  if (!check_acs(m.acs)) {\n    return false;\n  }\n\n  a()->user()->set_menu_set(m.name);\n  sysoplog(fmt::format(\"Menu in use : {} - {}\", a()->user()->menu_set(),\n                       a()->user()->hotkeys() ? \"Hot\" : \"Off\"));\n  // Save current menu setup.\n  return a()->WriteCurrentUser();\n}\n\nvoid ConfigUserMenuSet(const std::string& data) {\n  if (!data.empty() && ValidateMenuSet(data)) {\n    // Try to set the menu based on data first.\n    MenuSet56 m(FilePath(a()->config()->menudir(), data));\n    if (SetMenuSet(m.menu_set)) {\n      // Success at setting the menuset, no need to query the caller.\n      return;\n    }\n  }\n\n  bout.cls();\n  bout.litebar(\"Configure Menus\");\n  bout.printfile(MENUWEL_NOEXT);\n  bool done = false;\n\n  const auto r = ListMenuDirs();\n  if (r.size() == 1) {\n    if (const auto m = std::begin(r)->second; ValidateMenuSet(m.name)) {\n      bout.outstr(\"|#5You are currently using the only available menuset.\\r\\n\\r\\n\");\n      SetMenuSet(m);\n      bout.pausescr();\n      return;\n    }\n  }\n\n  while (!done) {\n    bout.nl();\n    bout.print(\"|#11|#9) Menuset      :|#2 {}\\r\\n\", a()->user()->menu_set());\n    bout.print(\"|#12|#9) Use hot keys :|#2 {}\\r\\n\", (a()->user()->hotkeys() ? \"Yes\" : \"No \"));\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) : \");\n    const auto chKey = onek(\"Q12?\");\n\n    switch (chKey) {\n    case 'Q':\n      done = true;\n      break;\n    case '1': {\n      bout.nl(2);\n      bout.outstr(\"|#9Enter the menu set to use : \");\n      auto sel = bin.input_number<int>(1, 1, r.size(), false);\n      if (const auto m = wwiv::stl::at(r, sel); ValidateMenuSet(m.name)) {\n        bout.nl();\n        bout.print(\"|#9Menu Set : |#2{:<8.8} :  |#1{}|#0\\r\\n\", m.name, m.description);\n        bout.outstr(\"|#5Use this menu set? \");\n        if (bin.noyes()) {\n          SetMenuSet(m);\n          break;\n        }\n      }\n      bout.nl();\n      bout.pl(\"|#6That menu set does not exists. Resetting to the default menu set.\");\n      bout.pausescr();\n      if (a()->user()->menu_set().empty()) {\n        MenuSet56 wwiv_menu(FilePath(a()->config()->menudir(), \"wwiv\"));\n        SetMenuSet(wwiv_menu.menu_set);\n      }\n    } break;\n    case '2':\n      a()->user()->set_hotkeys(!a()->user()->hotkeys());\n      break;\n    case '?':\n      bout.printfile(MENUWEL_NOEXT);\n      continue; // bypass the below cls()\n    }\n    bout.cls();\n  }\n\n  bout.nl(2);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "bbs/menus/config_menus.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MENUS_CONFIG_MENUS_H\n#define INCLUDED_BBS_MENUS_CONFIG_MENUS_H\n\n#include \"core/stl.h\"\n#include \"core/textfile.h\"\n#include <map>\n#include <string>\n\nnamespace wwiv::bbs::menus {\n\n// Functions used bbs.cpp and defaults.cpp\nvoid ConfigUserMenuSet(const std::string& data);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "bbs/menus/mainmenu.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/mainmenu.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/menus/config_menus.h\"\n#include \"bbs/menus/menucommands.h\"\n#include \"common/printfile.h\"\n#include \"common/menus/menu_generator.h\"\n#include \"common/value/bbsvalueprovider.h\"\n#include \"common/value/uservalueprovider.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/menus/menu_set.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::common::menus;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::menus;\n\nnamespace wwiv::bbs::menus {\n\nstatic bool CheckMenuPassword(const std::string& pw) {\n  if (pw.empty()) {\n    return true;\n  }\n  const auto expected_password = pw == \"*SYSTEM\" ? a()->config()->system_password() : pw;\n  bout.nl();\n  const auto actual_password = bin.input_password(\"|#2SY: \", 20);\n  return actual_password == expected_password;\n}\n\nstatic void log_command(menu_logtype_t logging, const menu_item_56_t& mi) {\n  switch (logging) {\n  case menu_logtype_t::key:\n    sysopchar(mi.item_key);\n    break;\n  case menu_logtype_t::command: {\n    for (const auto& a : mi.actions) {\n      sysoplog(a.cmd);\n    }\n  } break;\n  case menu_logtype_t::description: {\n    if (!mi.item_text.empty()) {\n      sysoplog(fmt::format(\"({}) : {}\", mi.item_key, mi.item_text));\n    } else {\n      for (const auto& a : mi.actions) {\n        sysoplog(a.cmd);\n      }\n    }\n  } break;\n  case menu_logtype_t::none:\n    break;\n  }\n}\n\nMainMenu::MainMenu(const Config& config) : config_(config) {}\n\nvoid MainMenu::Run() {\n  menu_set_ = a()->sess().current_menu_set();\n  auto main = std::make_unique<Menu>(config_.menudir(), menu_set_, \"main\");\n  auto loop_count = 0;\n  while (!main->initalized() || !check_acs(menu_set_.menu_set.acs) || !check_acs(main->menu().acs)) {\n    ConfigUserMenuSet(\"\");\n    // This should get updated when the user record gets written.\n    menu_set_ = a()->sess().current_menu_set();\n    // TODO(rushfan): Update menu_set_ and reload main\n    main = std::make_unique<Menu>(config_.menudir(), menu_set_, \"main\");\n    ++loop_count;\n    if (loop_count >= 3) {\n      auto errm = \"Caller unable to select a menu after 3 tries, please check for misconfiguration\";\n      LOG(ERROR) << errm;\n      sysoplog(errm);\n      ssm(1) << errm;\n    }\n  }\n\n  // N.B. Main menu can not have a password.\n  // Also should we skip the ACS on the main menu and just use the MENUSET\n  // ACS?\n\n  while (true) {\n    if (stack_.empty()) {\n      stack_.push_back(*main);\n    }\n\n    auto& cur_menu = stack_.back();\n    auto [res, s] = cur_menu.Run();\n    switch (res) {\n    case menu_run_result_t::return_from_menu:\n    case menu_run_result_t::error:\n      stack_.pop_back();\n      break;\n    case menu_run_result_t::push_menu: {\n      Menu m(config_.menudir(), menu_set_, s);\n      if (!m.initalized()) {\n        LOG(ERROR) << \"Menu never loaded\";\n        continue;\n      }\n      stack_.push_back(m);\n    } break;\n    case menu_run_result_t::clear_stack:\n      stack_.clear();\n      break;\n    case menu_run_result_t::change_menu_set:\n      stack_.clear();\n      menu_set_ = a()->sess().current_menu_set();\n      main = std::make_unique<Menu>(config_.menudir(), menu_set_, \"main\");\n      break;\n    case menu_run_result_t::none:\n      // Do nothing.\n      break;\n    }\n  }\n}\n\nvoid mainmenu() {\n  MainMenu m(*a()->config());\n  m.Run();\n}\n\nMenu::Menu(const std::filesystem::path& menu_path, const MenuSet56& menu_set,\n           const std::string& menu_name)\n    : menu_set_name_(menu_set.menu_set.name), menu_name_(menu_name),\n      menu_set_(menu_set),  menu_(menu_path, menu_set, menu_name) {\n\n  menu_set_path_ = menu_set_.menuset_dir();\n  prompt_ = \"|09Command? \";\n\n  // Load Prompt;\n  const auto prompt_filename = StrCat(menu_name, \".pro\");\n  const auto prompt_path = FilePath(menu_set_path_, prompt_filename);\n\n  TextFile prompt_file(prompt_path, \"rb\");\n  if (prompt_file.IsOpen()) {\n    const auto tmp = prompt_file.ReadFileIntoString();\n    const auto end = tmp.find(\".end.\");\n    if (end != std::string::npos) {\n      prompt_ = tmp.substr(0, end);\n    } else {\n      prompt_ = tmp;\n    }\n  }\n}\n\nvoid Menu::DisplayMenu() {\n  if (menu_displayed_) {\n    VLOG(1) << \"DisplayMenu: menu_displayed_ = true\";\n    return;\n  }\n  if (menu().cls) {\n    bout.cls();\n  }\n  const auto path =\n      common::CreateFullPathToPrint({menu_set_path_}, *a()->user(), menu_name_);\n  if (!bout.printfile_path(path, true, false)) {\n    GenerateMenu(menu_type_t::short_menu);\n  }\n  menu_displayed_ = true;\n}\n\nstd::string Menu::GetCommandFromUser() const {\n  if (!a()->user()->hotkeys()) {\n    return bin.input_upper(50);\n  }\n  const auto nums = menu().num_action;\n  if (nums == menu_numflag_t::dirs) {\n    write_inst(INST_LOC_XFER, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n    return mmkey(MMKeyAreaType::dirs);\n  }\n  if (nums == menu_numflag_t::subs) {\n    write_inst(INST_LOC_MAIN, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n    return mmkey(MMKeyAreaType::subs);\n  }\n  std::set<char> x = {'/'};\n  return mmkey(x);\n}\n\nstatic bool IsNumber(const std::string& command) {\n  if (command.empty()) {\n    return false;\n  }\n  for (const auto& ch : command) {\n    if (!isdigit(ch)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nstd::optional<menu_item_56_t> Menu::GetMenuItemForCommand(const std::string& cmd) const {\n  const auto nums = menu().num_action;\n  if (IsNumber(cmd) && nums != menu_numflag_t::none) {\n    if (nums == menu_numflag_t::subs) {\n      menu_item_56_t i{};\n      menu_action_56_t a{\"SetSubNumber\", cmd, \"\"};\n      i.actions.emplace_back(a);\n      return {i};\n    }\n    if (nums == menu_numflag_t::dirs) {\n      menu_item_56_t i{};\n      menu_action_56_t a{\"SetDirNumber\", cmd, \"\"};\n      i.actions.emplace_back(a);\n      return {i};\n    }\n  }\n\n  for (const auto& mi : menu().items) {\n    if (cmd == mi.item_key) {\n      return {mi};\n    }\n  }\n\n  // Check global items.\n  for (const auto& mi : menu_set_.menu_set.items) {\n    if (cmd == mi.item_key) {\n      return {mi};\n    }\n  }\n\n  return std::nullopt;\n}\n\nstd::tuple<menu_command_action_t, std::string> Menu::ExecuteAction(const menu_action_56_t& a) {\n  if (auto o = interpret_command(this, a.cmd, a.data)) {\n    auto& ctx = o.value();\n    if (ctx.menu_action == menu_command_action_t::return_from_menu) {\n      return std::make_tuple(menu_command_action_t::return_from_menu, \"\");\n    }\n    if (ctx.menu_action == menu_command_action_t::push_menu) {\n      return std::make_tuple(menu_command_action_t::push_menu, a.data);\n    }\n  }\n  return std::make_tuple(menu_command_action_t::none, \"\");\n}\n\nstd::tuple<menu_command_action_t, std::string>\nMenu::ExecuteActions(const std::vector<menu_action_56_t>& actions) {\n  for (const auto& action : actions) {\n    auto [a, d] = ExecuteAction(action);\n    VLOG(1) << \"Action: \" << action.cmd << \"; \" << action.data;\n    if (a == menu_command_action_t::push_menu) {\n      return std::make_tuple(menu_command_action_t::push_menu, d);\n    }\n    if (a == menu_command_action_t::return_from_menu) {\n      return std::make_tuple(menu_command_action_t::return_from_menu, \"\");\n    }\n  }\n  return std::make_tuple(menu_command_action_t::none, \"\");\n}\n\nstd::tuple<menu_run_result_t, std::string> Menu::Run() {\n  const auto menu_set = a()->user()->menu_set();\n  if (!menu_.initialized()) {\n    return std::make_tuple(menu_run_result_t::error, \"\");\n  }\n  if (!check_acs(menu().acs)) {\n    sysoplog(\"Insufficient ACS for menu.\");\n    bout.print(\"|#6Insufficient ACS for menu: {}\\r\\n\", menu().title);\n    return std::make_tuple(menu_run_result_t::error, \"\");\n  }\n  if (!CheckMenuPassword(menu().password)) {\n    LOG(ERROR) << \"Incorrect password\";\n    return std::make_tuple(menu_run_result_t::error, \"\");\n  }\n\n  {\n    // Process entrance actions.\n    auto [a, d] = ExecuteActions(menu().enter_actions);\n    if (a == menu_command_action_t::push_menu) {\n      return std::make_tuple(menu_run_result_t::push_menu, d);\n    }\n    if (a == menu_command_action_t::return_from_menu) {\n      return std::make_tuple(menu_run_result_t::return_from_menu, \"\");\n    }\n  }\n\n  auto first = true;\n  // We have a good menu.\n  for (;;) {\n    if (menu().help_type == menu_help_display_t::never) {\n      // Do nothing\n    } else if (menu().help_type == menu_help_display_t::always) {\n      DisplayMenu();\n    } else if (first && menu().help_type == menu_help_display_t::on_entrance) {\n      DisplayMenu();\n      first = false;\n    } else if (menu().help_type == menu_help_display_t::user_choice && !a()->user()->IsExpert()) {\n      DisplayMenu();\n    }\n    const auto save_mci = bout.mci_enabled();\n    bout.enable_mci();\n    bout.outstr(prompt_);\n    bout.set_mci_enabled(save_mci);\n    // Do actions on enter.\n\n    auto cmd = GetCommandFromUser();\n    // Reset menu displayed\n    menu_displayed_ = false;\n    if (auto omi = GetMenuItemForCommand(cmd)) {\n      const auto& mi = omi.value();\n      if (!check_acs(mi.acs)) {\n        sysoplog(fmt::format(\"Insufficient ACS for menu item: {}\", mi.item_key));\n        bout.print(\"|#6Insufficient ACS for menu item: {}\\r\\n\", mi.item_key);\n        continue;\n      }\n      VLOG(1) << \"Command is: \" << cmd << \"; \" << mi.item_key;\n      log_command(menu().logging_action, mi);\n      auto [action, d] = ExecuteActions(mi.actions);\n      if (action == menu_command_action_t::push_menu) {\n        // No push or pop allowed in exit actions\n        (void) ExecuteActions(menu().exit_actions);\n        return std::make_tuple(menu_run_result_t::push_menu, d);\n      }\n      if (action == menu_command_action_t::return_from_menu) {\n        // No push or pop allowed in exit actions\n        (void) ExecuteActions(menu().exit_actions);\n        return std::make_tuple(menu_run_result_t::return_from_menu, \"\");\n      }\n      if (reload || !iequals(menu_set, a()->user()->menu_set())) {\n        // We changed menu sets.  Reload is set by Defaults when changing the\n        // menu set.\n        return std::make_tuple(menu_run_result_t::change_menu_set, \"\");\n      }\n    }\n  }\n}\n\n\nvoid Menu::GenerateMenu(menu_type_t typ) {\n  if (menu_displayed_) {\n    VLOG(1) << \"GenerateMenu: menu_displayed_: true\";\n    return;\n  }\n  const auto lines = GenerateMenuAsLines(typ);\n  for (const auto& l : lines) {\n    if (bin.checka()) {\n      break;\n    }\n    bout.pl(l);\n  }\n  menu_displayed_ = true;\n}\n\n\nstd::vector<std::string> Menu::GenerateMenuAsLines(menu_type_t typ) {\n  const common::value::UserValueProvider up(a()->context());\n  const common::value::BbsValueProvider bp(*a()->config(), a()->sess());\n  const std::vector<const wwiv::sdk::value::ValueProvider*> providers{&up, &bp};\n  return GenerateMenuLines(*a()->config(), menu_set_, menu(), *a()->user(),\n                           providers, typ);\n}\n\n\n} // namespace wwiv::bbs::menus\n"
  },
  {
    "path": "bbs/menus/mainmenu.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_MENUS_MAINMENU_H\n#define INCLUDED_MENUS_MAINMENU_H\n\n#include \"menucommands.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/menus/menu_set.h\"\n#include <filesystem>\n#include <map>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\nclass Config;\nclass User;\n}\n\nnamespace wwiv::bbs::menus {\n// Functions used b bbs.cpp and defaults.cpp\nvoid mainmenu();\n\nenum class menu_run_result_t {\n  none,\n  error,\n  push_menu,\n  return_from_menu,\n  clear_stack,\n  change_menu_set\n};\n\nclass Menu {\npublic:\n  Menu() = delete;\n  Menu(const Menu&) = default;\n  Menu(Menu&&) noexcept = default;\n  Menu& operator=(const Menu&) = default;\n  Menu& operator=(Menu&&) = default;\n  Menu(const std::filesystem::path& menu_path, const wwiv::sdk::menus::MenuSet56& menu_set,\n               const std::string& menu_name);\n  ~Menu() = default;\n  [[nodiscard]] bool initalized() const { return menu_.initialized(); }\n  // Gets the command string from the user for this menu.\n  [[nodiscard]] std::string GetCommandFromUser() const;\n  [[nodiscard]] std::optional<wwiv::sdk::menus::menu_item_56_t>\n  GetMenuItemForCommand(const std::string& cmd) const;\n  void DisplayMenu();\n  // Generates the short form (multi-column) or long form (single col, help text) menu.\n  [[nodiscard]] std::vector<std::string> GenerateMenuAsLines(sdk::menus::menu_type_t typ);\n  // Generates the short form (multi-column) or long form (single col, help text) menu.\n  void GenerateMenu(sdk::menus::menu_type_t typ);\n  [[nodiscard]] const sdk::menus::menu_56_t& menu() const noexcept { return menu_.menu; }\n  [[nodiscard]] std::tuple<menu_command_action_t, std::string>\n  ExecuteAction(const sdk::menus::menu_action_56_t& a);\n  [[nodiscard]] std::tuple<menu_command_action_t, std::string>\n  ExecuteActions(const std::vector<wwiv::sdk::menus::menu_action_56_t>& actions);\n  [[nodiscard]] std::tuple<menu_run_result_t, std::string> Run();\n\n  bool reload{false}; /* true if we are going to reload the menus */\n  bool menu_displayed_{false};\n\nprivate:\n  const std::string menu_set_name_;\n  const std::string menu_name_;\n  const wwiv::sdk::menus::MenuSet56 menu_set_;\n  sdk::menus::Menu56 menu_;\n  std::filesystem::path menu_set_path_;\n  std::string prompt_;\n};\n\nclass MainMenu {\npublic:\n  explicit MainMenu(const sdk::Config& config);\n  void Run();\n\n  wwiv::sdk::menus::MenuSet56 menu_set_;\n  const sdk::Config& config_;\n\nprivate:\n  std::vector<Menu> stack_;\n};\n\n} // namespace wwiv::bbs::menus\n\n#endif\n"
  },
  {
    "path": "bbs/menus/menu_context.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MENUS_MENU_CONTEXT_H\n#define INCLUDED_BBS_MENUS_MENU_CONTEXT_H\n\n#include \"core/stl.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::bbs::menus {\nclass Menu;\n\nenum class menu_command_action_t { none, push_menu, return_from_menu };\n\nstruct MenuContext {\n  MenuContext(Menu* m, std::string d)\n      : cur_menu(m), data(std::move(d)) {}\n  // May be null if not invoked from an actual menu.\n  Menu* cur_menu;\n  std::string data;\n  menu_command_action_t menu_action{menu_command_action_t::none};\n  bool need_reload{false};\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "bbs/menus/menucommands.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/menucommands.h\"\n\n#include \"bbs/automsg.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbslist.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsovl3.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/hop.h\"\n#include \"bbs/newuser.h\"\n#include \"bbs/sublist.h\"\n#include \"bbs/syschat.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/xferovl1.h\"\n#include \"bbs/basic/basic.h\"\n#include \"bbs/menus/config_menus.h\"\n#include \"bbs/menus/mainmenu.h\"\n#include \"bbs/menus/menuspec.h\"\n#include \"bbs/menus/menusupp.h\"\n#include \"bbs/qwk/qwk.h\"\n#include \"common/output.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include <functional>\n#include <map>\n#include <string>\n#include <utility>\n\nusing wwiv::core::IniFile;\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::bbs::menus {\n\n// Categories\nstatic const std::string MENU_CAT_MSGS = \"Message\";\nstatic const std::string MENU_CAT_EMAIL = \"EMail\";\nstatic const std::string MENU_CAT_FILE = \"File\";\nstatic const std::string MENU_CAT_BBSLIST = \"BBSList\";\nstatic const std::string MENU_CAT_AUTOMSG = \"AutoMessage\";\nstatic const std::string MENU_CAT_CHAIN = \"Chain\";\nstatic const std::string MENU_CAT_NET = \"Net\";\nstatic const std::string MENU_CAT_QWK = \"QWK\";\nstatic const std::string MENU_CAT_VOTE = \"Vote\";\nstatic const std::string MENU_CAT_GFILES = \"GFiles\";\nstatic const std::string MENU_CAT_SYSOP = \"SYSOP\";\nstatic const std::string MENU_CAT_MENU = \"Menu\";\nstatic const std::string MENU_CAT_SYS = \"System\";\nstatic const std::string MENU_CAT_CONF = \"Conference\";\nstatic const std::string MENU_CAT_USER = \"User\";\n\nstd::optional<MenuContext> interpret_command(Menu* menu, const std::string& cmd,\n                                            const std::string& data) {\n  if (cmd.empty()) {\n    return std::nullopt;\n  }\n\n  if (static auto functions = CreateCommandMap(); contains(functions, cmd)) {\n    MenuContext context(menu, data);\n    at(functions, cmd).f_(context);\n    if (menu) {\n      menu->reload = context.need_reload;\n    }\n    return {context};\n  }\n  return std::nullopt;\n}\n\nstd::map<std::string, MenuItem, ci_less> CreateCommandMap() {\n  std::map<std::string, MenuItem, ci_less> m;\n\n  m.emplace(\"MENU\", MenuItem(R\"(<menu>\n  Loads up and starts running a new menu set, where <menu> equals the name of\n  the menu to load.)\",\n                             MENU_CAT_MENU, [](MenuContext& context) {\n                               context.menu_action = menu_command_action_t::push_menu;\n                             }));\n  m.emplace(\"ReturnFromMenu\", MenuItem(R\"()\", MENU_CAT_MENU, [](MenuContext& context) {\n              context.menu_action = menu_command_action_t::return_from_menu;\n            }));\n  m.emplace(\"DLFreeFile\", MenuItem(R\"(\n<dirfname> <filename>\n\n  This will download a file, but not check ratios or charge a download charge.\n  You must specify the dir filename, which is the name of the data file in\n  the transfer editor.  filename is the name of the file being downloaded.\n)\",\n                                   MENU_CAT_FILE, [](MenuContext& context) {\n                                     MenuDownload(context.data, true, true);\n                                   }));\n  m.emplace(\"DLFile\", MenuItem(R\"(\n<dirfname> <filename>\n\n  This will download a file, with a check for ratios and will update the\n  kb downloaded and number of files downloaded.\n  You must specify the dirfilename, which is the name of the data file in\n  the transfer editor.  filename is the name of the file being downloaded.\n)\",\n                               MENU_CAT_FILE, [](MenuContext& context) {\n                                 MenuDownload(context.data, false, true);\n                               }));\n  m.emplace(\"RunDoor\", MenuItem(R\"(<door name>\n\n  Runs a door (chain) with doorname matching, exactly, the description you have\n  given the door in //CHEDIT\n)\",\n                                MENU_CAT_CHAIN, [](MenuContext& context) {\n                                  MenuRunDoorName(context.data, false);\n                                }));\n  m.emplace(\"RunDoorFree\", MenuItem(R\"(<door name>\n\n  Runs a door (chain) with doorname matching, exactly, the description you have\n  given the door in //CHEDIT, but this function bypasses the check to see if\n  the user is allowed to run the door.\n)\",\n                                    MENU_CAT_CHAIN, [](MenuContext& context) {\n                                      MenuRunDoorName(context.data, true);\n                                    }));\n  m.emplace(\"RunDoorNumber\", MenuItem(R\"(<door number>\n\n  Like RunDoor, but you must specify the #1 in //CHEDIT instead of the\n  description.\n)\",\n                                      MENU_CAT_CHAIN, [](MenuContext& context) {\n                                        const auto t = to_number<int>(context.data);\n                                        MenuRunDoorNumber(t, false);\n                                      }));\n  m.emplace(\"RunDoorNumberFree\", MenuItem(R\"(<door number>\n\n  Like RunDoorFree, but you must specify the #1 in //CHEDIT instead of the\n  description.\n)\",\n                                          MENU_CAT_CHAIN, [](MenuContext& context) {\n                                            const auto t = to_number<int>(context.data);\n                                            MenuRunDoorNumber(t, true);\n                                          }));\n  m.emplace(\"RunBasic\", MenuItem(R\"(<script name>\n\nRuns a WWIVbasic Script\n)\",\n                                 MENU_CAT_SYS, [](MenuContext& context) {\n                                   // Runs a basic script from GFILES/\n                                   basic::RunBasicScript(context.data);\n                                 }));\n  m.emplace(\"PrintFile\", MenuItem(R\"(<filename>\n\n  Prints a file, first checking to see if you specified an absolute path,\n  then the language dir, then the gfilesdir.  It will use the usual checks to\n  determine .ANS, or .MSG if not specified.\n)\",\n                                  MENU_CAT_SYS, [](MenuContext& context) {\n                                    bout.printfile(context.data, true);\n                                  }));\n  m.emplace(\"PrintFileNA\", MenuItem(R\"(<filename>\n\n  Just like PrintFile, but the user can not abort it with the space bar.\n)\",\n                                    MENU_CAT_SYS, [](MenuContext& context) {\n                                      bout.printfile(context.data, false);\n                                    }));\n  m.emplace(\"SetSubNumber\", MenuItem(R\"(<key>\n\n  Equivalent to typing in a number at the main menu, it sets the current sub\n  number.\n)\",\n                                     MENU_CAT_MSGS, SetSubNumber));\n  m.emplace(\"SetDirNumber\", MenuItem(R\"( <key>\n\n  Equivalent to typing in a number at the xfer menu, it sets the current dir\n  number.\n)\",\n                                     MENU_CAT_FILE, SetDirNumber));\n  m.emplace(\"SetMsgConf\", MenuItem(R\"(<key>\n\n  Sets the subboards conference to key\n)\",\n                                   MENU_CAT_MSGS, [](MenuContext& context) {\n                                     if (context.data.empty()) {\n                                       LOG(ERROR) << \"SetMsgConf requires a key to be specified.\";\n                                       return;\n                                     }\n                                     SetMsgConf(context.data.front());\n                                   }));\n  m.emplace(\"SetDirConf\", MenuItem(R\"(<key>\n\n  Sets the xfer section conference to key\n)\",\n                                   MENU_CAT_FILE, [](MenuContext& context) {\n                                     if (context.data.empty()) {\n                                       LOG(ERROR) << \"SetDirConf requires a key to be specified.\";\n                                       return;\n                                     }\n                                     SetDirConf(context.data.front());\n                                   }));\n  m.emplace(\"EnableConf\", MenuItem(R\"(\n\n  Turns conferencing on\n)\",\n                                   MENU_CAT_CONF, [](MenuContext&) { EnableConf(); }));\n  m.emplace(\"DisableConf\", MenuItem(R\"(\n\n  Turns conferencing off\n)\",\n                                    MENU_CAT_CONF, [](MenuContext&) { DisableConf(); }));\n  m.emplace(\"Pause\", MenuItem(R\"(\n\n  Pauses the screen, like 'pausescr()' in C code\n)\",\n                              MENU_CAT_SYS, [](MenuContext&) { bout.pausescr(); }));\n  //\n  // User commands\n  //\n  m.emplace(\"ConfigUserMenuSet\", MenuItem(R\"(Use user:menus instead.\n  Sets the user's menuset to the value specified by data\n  or takes the user into the user menu config so they can select which menuset to use.)\",\n                                          MENU_CAT_USER, [](MenuContext& context) {\n                                            ConfigUserMenuSet(context.data);\n                                            a()->WriteCurrentUser();\n                                            context.need_reload = true;\n                                          }));\n\n  m.emplace(\"user:menus\", MenuItem(R\"(Sets the user's menuset to the value specified by data\n  or takes the user into the user menu config so they can select which menuset to use.\n)\",\n                                   MENU_CAT_USER, [](MenuContext& context) {\n                                     ConfigUserMenuSet(context.data);\n                                     a()->WriteCurrentUser();\n                                     context.need_reload = true;\n                                   }));\n\n  m.emplace(\"user:realname\", MenuItem(R\"(Allows the user to change their real name)\", MENU_CAT_USER,\n                                      [](MenuContext&) {\n                                        input_realname();\n                                        a()->WriteCurrentUser();\n                                      }));\n\n  m.emplace(\"user:dataphone\", MenuItem(R\"(Allows the user to change their data phone number)\",\n                                       MENU_CAT_USER, [](MenuContext&) {\n                                         input_dataphone();\n                                         a()->WriteCurrentUser();\n                                       }));\n\n  m.emplace(\"user:phone\", MenuItem(R\"(Allows the user to change their voice phone number)\",\n                                   MENU_CAT_USER, [](MenuContext&) {\n                                     input_phone();\n                                     a()->WriteCurrentUser();\n                                   }));\n\n  m.emplace(\"user:address\", MenuItem(R\"(Allows the user to change their address)\", MENU_CAT_USER, [](MenuContext&) {\n              input_street();\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:city\", MenuItem(R\"(Allows the user to change their city)\", MENU_CAT_USER, [](MenuContext&) {\n              input_city();\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:state\", MenuItem(R\"(Allows the user to change their state)\", MENU_CAT_USER, [](MenuContext&) {\n              input_state();\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:zipcode\", MenuItem(R\"(Allows the user to change their zipcode)\", MENU_CAT_USER, [](MenuContext&) {\n              input_zipcode();\n              a()->WriteCurrentUser();\n            }));\n  m.emplace(\"user:country\", MenuItem(R\"(Allows the user to change their country)\", MENU_CAT_USER, [](MenuContext&) {\n              input_country();\n              a()->WriteCurrentUser();\n            }));\n  m.emplace(\"user:gender\", MenuItem(R\"(Allows the user to change their gender)\", MENU_CAT_USER, [](MenuContext&) {\n              input_sex();\n              a()->WriteCurrentUser();\n            }));\n  m.emplace(\"user:comptype\", MenuItem(R\"(Allows the user to change their computer type)\",\n                                      MENU_CAT_USER, [](MenuContext&) {\n                                        input_comptype();\n                                        a()->WriteCurrentUser();\n                                      }));\n  m.emplace(\"user:screensize\", MenuItem(R\"(Allows the user to change their screen size)\",\n                                        MENU_CAT_USER, [](MenuContext&) {\n                                          input_screensize();\n                                          a()->WriteCurrentUser();\n                                        }));\n  m.emplace(\"user:ansistate\", MenuItem(R\"(Allows the user to change their ANSI state)\",\n                                       MENU_CAT_USER, [](MenuContext&) {\n                                         input_ansistat();\n                                         a()->WriteCurrentUser();\n                                       }));\n  m.emplace(\"user:callsign\", MenuItem(R\"(Allows the user to change their HAM callsign)\",\n                                      MENU_CAT_USER, [](MenuContext&) {\n                                        input_callsign();\n                                        a()->WriteCurrentUser();\n                                      }));\n  m.emplace(\"user:editor\", MenuItem(R\"(Allows the user to change their default editor)\",\n                                    MENU_CAT_USER, [](MenuContext&) {\n                                      select_editor();\n                                      a()->WriteCurrentUser();\n                                    }));\n  m.emplace(\"user:qscan\", MenuItem(R\"(Allows the user to change their subs that are newscanned)\",\n                                   MENU_CAT_USER, [](MenuContext&) {\n                                     config_qscan();\n                                     a()->WriteCurrentUser();\n                                   }));\n  m.emplace(\"user:regnum\",\n            MenuItem(R\"(Allows the user to change their WWIV 4.x registration number)\",\n                     MENU_CAT_USER, [](MenuContext&) {\n                       enter_regnum();\n                       a()->WriteCurrentUser();\n                     }));\n  m.emplace(\"user:mailbox\", MenuItem(R\"(Allows the user to change their email forward/mailbox settings)\",\n                     MENU_CAT_USER, [](MenuContext&) {\n                       modify_mailbox();\n                       a()->WriteCurrentUser();\n                     }));\n  m.emplace(\"user:password\", MenuItem(R\"(Allows the user to change their password)\", MENU_CAT_USER,\n                                      [](MenuContext&) {\n                                        change_password();\n                                        a()->WriteCurrentUser();\n                                      }));\n  m.emplace(\"user:macros\", MenuItem(R\"(Allows the user to change their macros)\", MENU_CAT_USER, [](MenuContext&) {\n              change_macros();\n              a()->WriteCurrentUser();\n            }));\n  m.emplace(\"user:optional_lines\", MenuItem(R\"(Allows the user to change the number of optional lines displayed)\",\n                     MENU_CAT_USER, [](MenuContext&) {\n                       change_optional_lines();\n                       a()->WriteCurrentUser();\n                     }));\n  m.emplace(\"user:email\", MenuItem(R\"(Allows the user to change their email address)\",\n                                   MENU_CAT_USER, [](MenuContext&) {\n                                     change_email_address();\n                                     a()->WriteCurrentUser();\n                                   }));\n  m.emplace(\"user:colors\", MenuItem(R\"(Allows the user to change their colors)\", MENU_CAT_USER, [](MenuContext&) {\n              change_colors();\n              a()->WriteCurrentUser();\n            }));\n\n\n  m.emplace(\"user:pause\", MenuItem(R\"(Toggles pause on page)\", MENU_CAT_USER, [](MenuContext&) {\n              a()->user()->toggle_flag(User::pauseOnPage);\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:extra_color\", MenuItem(R\"(Toggles Extra Colors)\", MENU_CAT_USER, [](MenuContext&) {\n              a()->user()->toggle_flag(User::extraColor);\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:conference\", MenuItem(R\"(Toggles if conferences are enables)\", MENU_CAT_USER, [](MenuContext&) {\n              a()->user()->toggle_flag(User::conference);\n              a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:ctrlcodes\", MenuItem(R\"(Toggles if message lines with kludges or control codes are shown)\", MENU_CAT_USER, [](MenuContext&) {\n                       a()->user()->toggle_flag(User::msg_show_controlcodes);\n                       a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:fs_reader\", MenuItem(R\"(Toggles If the full screen message reader is used)\", MENU_CAT_USER, [](MenuContext&) {\n                                         a()->user()->toggle_flag(User::fullScreenReader);\n                                         a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:nomsgs\", MenuItem(R\"(Toggles If the user doesn't want inter instance messages)\", MENU_CAT_USER, [](MenuContext&) {\n                                      a()->user()->toggle_flag(User::noMsgs);\n                                      a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:cls\", MenuItem(R\"(Toggles If the screen should be cleared between messages in the non-full screen message reader)\", MENU_CAT_USER, [](MenuContext&) {\n            a()->user()->toggle_flag(User::clearScreen);\n            a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:24\", MenuItem(R\"(Toggles If the time should be displayed using a 24-hour clock vs. 12-hour)\", MENU_CAT_USER, [](MenuContext&) {\n                       a()->user()->toggle_flag(User::twentyFourHourClock);\n                       a()->WriteCurrentUser();\n            }));\n\n  m.emplace(\"user:autoquote\", MenuItem(R\"(Toggles If new messages in external editors should contain the entire reply text)\", MENU_CAT_USER, [](MenuContext&) {\n            a()->user()->toggle_flag(User::autoQuote);\n            a()->WriteCurrentUser();\n            }));\n\n  // ========================================================================\n  // Menu\n\n  m.emplace(\n      \"menu:display\",\n      MenuItem(R\"(Prints the 'novice menus' for the current menu set, or if one doesn't exist,\n  it will generate one using command \"menu:generate_short\")\",\n               MENU_CAT_MENU, [](MenuContext& context) {\n                 if (context.cur_menu) {\n                   context.cur_menu->DisplayMenu();\n                 }\n               }));\n  m.emplace(\"menu:generate_short\",\n            MenuItem(R\"( Generates the short form 'novice menus' for the current menu set.\nThis command does not attempt to display a .msg/.ans file.)\",\n                     MENU_CAT_MENU, [](MenuContext& context) {\n                       if (context.cur_menu) {\n                         context.cur_menu->GenerateMenu(sdk::menus::menu_type_t::short_menu);\n                       }\n                     }));\n\n  m.emplace(\n      \"menu:generate_long\",\n      MenuItem(\n          R\"(Generates the long form (one cmd per line) help text/menu for the current menu set.\nThis command does not attempt to display a .msg/.ans file.\n)\",\n          MENU_CAT_MENU, [](MenuContext& context) {\n            if (context.cur_menu) {\n              context.cur_menu->GenerateMenu(sdk::menus::menu_type_t::long_menu);\n            }\n          }));\n\n    m.emplace(\"DisplayHelp\", MenuItem(R\"(An alias for DisplayMenu. \n  This alias is deprecated, please use menu:display.)\",\n                                    MENU_CAT_MENU, [](MenuContext& context) {\n                                      if (context.cur_menu) {\n                                        context.cur_menu->DisplayMenu();\n                                      }\n                                    }));\n\n  m.emplace(\n        \"DisplayMenu\",\n        MenuItem(R\"(Prints the 'novice menus' for the current menu set, or if one doesn't exist,\n  it will generate one using command \"menu:generate_short\"\n)\",\n                 MENU_CAT_MENU, [](MenuContext& context) {\n                   if (context.cur_menu) {\n                     context.cur_menu->DisplayMenu();\n                   }\n                 }));\n\n  // ========================================================================\n\n  m.emplace(\"SelectSub\", MenuItem(R\"(\n\n  This will prompt the user to enter a sub to change to.  However, it does not\n  first show the subs (like Renegade).  However, you can stack a sublist and\n  then this command to mimic the action.\n)\",\n                                  MENU_CAT_MSGS, [](MenuContext&) { ChangeSubNumber(); }));\n  m.emplace(\"SelectDir\", MenuItem(R\"(\n\n  Like SelectSub, but for the xfer section.\n)\",\n                                  MENU_CAT_FILE, [](MenuContext&) { ChangeDirNumber(); }));\n  m.emplace(\"SubList\", MenuItem(R\"(\n\n  List the subs available\n)\",\n                                MENU_CAT_MSGS, [](MenuContext&) { SubList(); }));\n  m.emplace(\"UpSubConf\", MenuItem(R\"(\n\n  Increment ()) to the previous conference number\n)\",\n                                  MENU_CAT_CONF, [](MenuContext&) { UpSubConf(); }));\n  m.emplace(\"DownSubConf\", MenuItem(R\"(\n\n  Decrement ({) to the next sub conference\n)\",\n                                    MENU_CAT_CONF, [](MenuContext&) { DownSubConf(); }));\n  m.emplace(\"UpSub\", MenuItem(R\"(\n\n  Increment the current sub# (+)\n)\",\n                              MENU_CAT_MSGS, [](MenuContext&) { UpSub(); }));\n  m.emplace(\"DownSub\", MenuItem(R\"(\n\n  Decrement the current sub number (-)\n)\",\n                                MENU_CAT_MSGS, [](MenuContext&) { DownSub(); }));\n  m.emplace(\"ValidateUser\", MenuItem(R\"(\n  Validate a new users.  I think this '!'\n)\",\n                                     MENU_CAT_SYSOP, [](MenuContext&) { ValidateUser(); }));\n  m.emplace(\"Doors\", MenuItem(R\"(\n  Enter the doors, or chains section.  Like '.'\n)\",\n                              MENU_CAT_CHAIN, [](MenuContext&) { Chains(); }));\n  m.emplace(\"TimeBank\", MenuItem(R\"(\n  Enter the time bank\n)\",MENU_CAT_SYS, [](MenuContext&) { TimeBank(); }));\n\n  // =========================================================================================\n\n  m.emplace(\"AutoMessage\", MenuItem(R\"(Displays the legacy automessage menu)\", MENU_CAT_AUTOMSG,\n                                    [](MenuContext&) { do_legacy_automessage(); }));\n\n  m.emplace(\"ReadAutoMessage\", MenuItem(R\"(Read the auto message)\", MENU_CAT_AUTOMSG,\n                                        [](MenuContext&) { read_automessage(); }));\n\n  m.emplace(\"amsg:read\", MenuItem(R\"(Read the auto message \n[use automessage:read instead]\n)\",\n                                  MENU_CAT_AUTOMSG, [](MenuContext&) { read_automessage(); }));\n\n  m.emplace(\"amsg:write\", MenuItem(R\"(Writes a new auto message)\", MENU_CAT_AUTOMSG,\n                                   [](MenuContext&) { write_automessage(); }));\n\n  m.emplace(\"amsg:delete\", MenuItem(R\"(Deletes the auto message (cosysop required))\",\n                                    MENU_CAT_AUTOMSG, [](MenuContext&) { delete_automessage(); }));\n\n  m.emplace(\"amsg:lock\", MenuItem(R\"(Locks the automessage (cosysop required))\", MENU_CAT_AUTOMSG,\n                                  [](MenuContext&) { lock_automessage(); }));\n  m.emplace(\"amsg:unlock\", MenuItem(R\"(Unlocks the automessage (cosysop required))\",\n                                    MENU_CAT_AUTOMSG, [](MenuContext&) { unlock_automessage(); }));\n  m.emplace(\"amsg:email\", MenuItem(R\"(E-mail the author of the automessage)\", MENU_CAT_AUTOMSG,\n                                   [](MenuContext&) { email_automessage_author(); }));\n\n  // =========================================================================================\n  // BBS List\n\n\n\n  m.emplace(\"bbslist\", MenuItem(R\"(Legacy BBSList Menu)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { wwiv::bbslist::BBSList(); }));\n  m.emplace(\"bbslist:bbslist\", MenuItem(R\"(Legacy BBSList Menu)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { wwiv::bbslist::BBSList(); }));\n  m.emplace(\"bbslist:add\", MenuItem(R\"(Adds a new BBS to the BBSList)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { wwiv::bbslist::add_bbslist(); }));\n  m.emplace(\"bbslist:delete\", MenuItem(R\"(Deletes a new BBS from the BBSList)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { wwiv::bbslist::delete_bbslist(); }));\n  m.emplace(\"bbslist:read\", MenuItem(R\"(Read the bbslist)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { wwiv::bbslist::read_bbslist(); }));\n  m.emplace(\"bbslist:net\", MenuItem(R\"(Read the network bbs lists)\", MENU_CAT_BBSLIST,\n                                [](MenuContext&) { query_print_net_listing(false); }));\n\n\n  // =========================================================================================\n  // BBS List\n\n\n  m.emplace(\"RequestChat\", MenuItem(R\"(\n  Request chat from the sysop\n)\",\n                                    MENU_CAT_SYS, [](MenuContext&) { RequestChat(); }));\n  m.emplace(\"Defaults\", MenuItem(R\"(\n  Enter the normal 'defaults' section\n)\",\n                                 MENU_CAT_SYS,\n                                 [](MenuContext& context) { Defaults(context.need_reload); }));\n  m.emplace(\"SendEMail\", MenuItem(R\"(\n  Enter and send email 'E' from the main menu\n)\",\n                                  MENU_CAT_EMAIL, [](MenuContext&) { SendEMail(); }));\n  m.emplace(\"Feedback\", MenuItem(R\"(\n  Leave feedback to the syosp.  'F'\n)\",\n                                 MENU_CAT_SYS, [](MenuContext&) { FeedBack(); }));\n  m.emplace(\"Bulletins\", MenuItem(R\"(\n  Enter the bulletins (or 'gfiles') section.  'G'\n)\",\n                                  MENU_CAT_GFILES, [](MenuContext&) { Bulletins(); }));\n  m.emplace(\"HopSub\", MenuItem(R\"(\n  Hop to another sub.  'H'\n)\",\n                               MENU_CAT_MSGS, [](MenuContext&) { HopSub(); }));\n  m.emplace(\"SystemInfo\", MenuItem(R\"(\n  View the system info\n)\",\n                                   MENU_CAT_SYS, [](MenuContext&) { SystemInfo(); }));\n  m.emplace(\"JumpSubConf\", MenuItem(R\"(\n  Jump to another sub conference.\n)\",\n                                    MENU_CAT_CONF, [](MenuContext&) { JumpSubConf(); }));\n  m.emplace(\"KillEMail\", MenuItem(R\"(\n  Kill email that you have sent 'K'\n)\",\n                                  MENU_CAT_EMAIL, [](MenuContext&) { KillEMail(); }));\n  m.emplace(\"LastCallers\", MenuItem(R\"(\n  View the last few callers\n)\",\n                                    MENU_CAT_SYS, [](MenuContext&) { LastCallers(); }));\n  m.emplace(\"ReadEMail\", MenuItem(R\"(\n  Read your email\n)\",\n                                  MENU_CAT_EMAIL, [](MenuContext&) { ReadEMail(); }));\n  m.emplace(\"NewMessageScan\", MenuItem(R\"(\n  Do a new message scan\n)\",\n                                       MENU_CAT_MSGS, [](MenuContext&) { NewMessageScan(); }));\n  m.emplace(\"Goodbye\", MenuItem(R\"(\n  Normal logoff 'O'\n)\",\n                                MENU_CAT_SYS, [](MenuContext&) { GoodBye(); }));\n  m.emplace(\"PostMessage\", MenuItem(R\"(\n  Post a message in the current sub\n)\",\n                                    MENU_CAT_MSGS, [](MenuContext&) { WWIV_PostMessage(); }));\n  m.emplace(\"NewMsgScanCurSub\", MenuItem(R\"(\n  Scan new messages in the current message sub\n)\",\n                                         MENU_CAT_MSGS, [](MenuContext&) { ScanSub(); }));\n  m.emplace(\"RemovePost\", MenuItem(R\"(\n  Remove a post\n)\",\n                                   MENU_CAT_MSGS, [](MenuContext&) { RemovePost(); }));\n  m.emplace(\"TitleScan\", MenuItem(R\"(\n  Scan the titles of the messages in the current sub\n)\",\n                                  MENU_CAT_MSGS, [](MenuContext&) { TitleScan(); }));\n  m.emplace(\"ListUsers\", MenuItem(R\"(\n  List users who have access to the current sub\n)\",\n                                  MENU_CAT_MSGS, [](MenuContext&) { ListUsers(); }));\n  m.emplace(\"Vote\", MenuItem(R\"(\n  Enter the voting both\n)\",\n                             MENU_CAT_VOTE, [](MenuContext&) { Vote(); }));\n  m.emplace(\"ToggleExpert\", MenuItem(R\"(\n  Turn 'X'pert mode on or off (toggle)\n  Can optionally pass \"quiet=on\" as the command data to suppress displaying the expert mode state.\n)\",\n                                     MENU_CAT_SYS, [](MenuContext& c) { ToggleExpert(c.data); }));\n  m.emplace(\"YourInfo\", MenuItem(R\"(\n  Display the yourinfo screen\n)\",\n                                 MENU_CAT_SYS, [](MenuContext&) { YourInfo(); }));\n  m.emplace(\"WWIVVer\", MenuItem(R\"(\n  Get the wwiv version\n)\",\n                                MENU_CAT_SYS, [](MenuContext&) { WWIVVersion(); }));\n  m.emplace(\"ConferenceEdit\", MenuItem(R\"(\n  Sysop command ot edit the conferences\n)\",\n                                       MENU_CAT_SYSOP, [](MenuContext&) { JumpEdit(); }));\n  m.emplace(\"SubEdit\", MenuItem(R\"(\n  Sysop command to edit the subboards\n)\",\n                                MENU_CAT_SYSOP, [](MenuContext&) { BoardEdit(); }));\n  m.emplace(\"ChainEdit\", MenuItem(R\"(\n  Sysop command to edit the doors or chains\n)\",\n                                  MENU_CAT_SYSOP, [](MenuContext&) { ChainEdit(); }));\n  m.emplace(\"ToggleAvailable\", MenuItem(R\"(\n  Toggle the sysop availability for chat\n)\",\n                                        MENU_CAT_SYSOP, [](MenuContext&) { ToggleChat(); }));\n  m.emplace(\"ChangeUser\", MenuItem(R\"(\n  Sysop command equal to //CHUSER, to change into another users\n)\",\n                                   MENU_CAT_SYSOP, [](MenuContext&) { ChangeUser(); }));\n  m.emplace(\"DirEdit\", MenuItem(R\"(\n  Sysop command to edit the directory records\n)\",\n                                MENU_CAT_SYSOP, [](MenuContext&) { DirEdit(); }));\n  m.emplace(\"Edit\", MenuItem(R\"(\n  Sysop command to edit a text file\n)\",\n                             MENU_CAT_SYSOP, [](MenuContext&) { EditText(); }));\n  m.emplace(\"BulletinEdit\", MenuItem(R\"(\n  Sysop command to edit the bulletins 'gfiles'\n)\",\n                                     MENU_CAT_GFILES, [](MenuContext&) { EditBulletins(); }));\n  m.emplace(\"LoadText\", MenuItem(R\"(\n  Sysop command to load a text file that will be edited in the text editor\n)\",\n                                 MENU_CAT_SYS, [](MenuContext&) { LoadTextFile(); }));\n  m.emplace(\"ReadAllMail\", MenuItem(R\"(\n  Sysop command to read all mail\n)\",\n                                    MENU_CAT_EMAIL, [](MenuContext&) { ReadAllMail(); }));\n  m.emplace(\"ResetQscan\", MenuItem(R\"(\n  Set all messages to read (I think)\n)\",\n                                   MENU_CAT_MSGS, [](MenuContext&) { ResetQscan(); }));\n  m.emplace(\"MemStat\", MenuItem(R\"()\", MENU_CAT_SYSOP, [](MenuContext&) { MemoryStatus(); }));\n  m.emplace(\"VoteEdit\", MenuItem(R\"(\n  Sysop command to edit the voting both\n)\",\n                                 MENU_CAT_SYSOP, [](MenuContext&) { InitVotes(); }));\n  m.emplace(\"Log\", MenuItem(R\"(\n  Syosp command to view the log file\n)\",\n                            MENU_CAT_SYS, [](MenuContext&) { ReadLog(); }));\n  m.emplace(\"NetLog\", MenuItem(R\"(\n  Sysop command to view the network log\n)\",\n                               MENU_CAT_NET, [](MenuContext&) { ReadNetLog(); }));\n  m.emplace(\"Pending\", MenuItem(R\"(\n  Shows which net files are ready to be sent\n)\",\n                                MENU_CAT_NET, [](MenuContext&) { PrintPending(); }));\n  m.emplace(\"Status\", MenuItem(R\"()\", MENU_CAT_SYSOP, [](MenuContext&) { PrintStatus(); }));\n  m.emplace(\"TextEdit\", MenuItem(R\"(\n  Edit a text file\n)\",\n                                 MENU_CAT_SYS, [](MenuContext&) { TextEdit(); }));\n  m.emplace(\"VotePrint\", MenuItem(R\"(\n  Show the voting statistics\n)\",\n                                  MENU_CAT_VOTE, [](MenuContext&) { VotePrint(); }));\n  m.emplace(\"YLog\", MenuItem(R\"(\n  View yesterdays log\n)\",\n                             MENU_CAT_SYS, [](MenuContext&) { YesterdaysLog(); }));\n  m.emplace(\"ZLog\", MenuItem(R\"(\n  View the ZLog\n)\",\n                             MENU_CAT_SYS, [](MenuContext&) { ZLog(); }));\n  m.emplace(\"ViewNetDataLog\", MenuItem(R\"(\n  View the net data logs\n)\",\n                                       MENU_CAT_SYSOP, [](MenuContext&) { ViewNetDataLog(); }));\n  m.emplace(\"UploadPost\", MenuItem(R\"(\n  Allow a user to upload a post that will be posted\n)\",\n                                   MENU_CAT_MSGS, [](MenuContext&) { UploadPost(); }));\n  m.emplace(\"cls\", MenuItem(R\"(\n  Clear the screen\n)\",\n                            MENU_CAT_SYS, [](MenuContext&) { bout.cls(); }));\n  m.emplace(\"NetListing\",\n            MenuItem(R\"(\n  Show networks\n)\",\n                     MENU_CAT_NET, [](MenuContext&) { query_print_net_listing(false); }));\n  m.emplace(\"WHO\", MenuItem(R\"(\n  Show who else is online\n)\",\n                            MENU_CAT_SYS, [](MenuContext&) { WhoIsOnline(); }));\n  m.emplace(\"NewMsgsAllConfs\", MenuItem(R\"(\n  Do a new message scan for all subs in all conferences '/A'\n)\",\n                                        MENU_CAT_CONF, [](MenuContext&) {\n                                          // /A NewMsgsAllConfs\n                                          NewMsgsAllConfs();\n                                        }));\n  m.emplace(\"MultiEMail\", MenuItem(R\"(\n  Send multi-email\n)\",\n                                   MENU_CAT_EMAIL, [](MenuContext&) {\n                                     // /E \"MultiEMail\"\n                                     MultiEmail();\n                                   }));\n  m.emplace(\"NewMsgScanFromHere\",\n            MenuItem(R\"(\n  Read new messages starting from the current sub\n)\",\n                     MENU_CAT_MSGS, [](MenuContext&) { NewMsgScanFromHere(); }));\n  m.emplace(\"ValidatePosts\", MenuItem(R\"(\n  Sysop command to validate unvalidated posts\n)\",\n                                      MENU_CAT_MSGS, [](MenuContext&) { ValidateScan(); }));\n  m.emplace(\"ChatRoom\", MenuItem(R\"(\n  Go into the multiuser chat room\n)\",\n                                 MENU_CAT_SYS, [](MenuContext&) { ChatRoom(); }));\n  m.emplace(\"ClearQScan\", MenuItem(R\"(\n  Marks messages unread.\n)\",\n                                   MENU_CAT_MSGS, [](MenuContext&) { ClearQScan(); }));\n  m.emplace(\"FastGoodBye\", MenuItem(R\"(\n  Logoff fast '/O'\n)\",\n                                    MENU_CAT_SYS, [](MenuContext&) { FastGoodBye(); }));\n  m.emplace(\"NewFilesAllConfs\",\n            MenuItem(R\"(\n  New file scan in all directories in all conferences\n)\",\n                     MENU_CAT_FILE, [](MenuContext&) { NewFilesAllConfs(); }));\n  m.emplace(\"ReadIDZ\", MenuItem(R\"(\n  Sysop command to read the file_id.diz and add it to the extended description\n)\",\n                                MENU_CAT_FILE, [](MenuContext&) { ReadIDZ(); }));\n  m.emplace(\"UploadAllDirs\", MenuItem(R\"(\n  Syosp command to add any files sitting in the directories, but not in\n  the file database to wwiv's file database\n)\",\n                                      MENU_CAT_FILE, [](MenuContext&) { UploadAllDirs(); }));\n  m.emplace(\"UploadCurDir\", MenuItem(R\"(\n  Sysop command to scan the current directory for any files that are not in\n  wwiv's file database and adds them to it.\n)\",\n                                     MENU_CAT_FILE, [](MenuContext&) { UploadCurDir(); }));\n  m.emplace(\"RenameFiles\", MenuItem(R\"(\n  Sysop command to edit and rename files\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { RenameFiles(); }));\n  m.emplace(\"MoveFiles\", MenuItem(R\"(\n  Sysop command to move files\n)\",\n                                  MENU_CAT_FILE, [](MenuContext&) { MoveFiles(); }));\n  m.emplace(\"SortDirs\", MenuItem(R\"(\n  Sort the directory by date or name\n)\",\n                                 MENU_CAT_FILE, [](MenuContext&) { SortDirs(); }));\n  m.emplace(\"ReverseSortDirs\", MenuItem(R\"(\n  Sort the directory by date or name, backwards.\n)\",\n                                        MENU_CAT_FILE, [](MenuContext&) { ReverseSort(); }));\n  m.emplace(\"AllowEdit\", MenuItem(R\"(\n  Sysop command to enter the 'ALLOW.DAT' editor.\n)\",\n                                  MENU_CAT_FILE, [](MenuContext&) { AllowEdit(); }));\n  m.emplace(\"UploadFilesBBS\", MenuItem(R\"(\n  Import a files.bbs (probably a CD) into the wwiv's file database\n)\",\n                                       MENU_CAT_FILE, [](MenuContext&) { UploadFilesBBS(); }));\n  m.emplace(\"DirList\", MenuItem(R\"(\n  List the directory names in the xfer section\n)\",\n                                MENU_CAT_FILE, [](MenuContext&) { DirList(); }));\n  m.emplace(\"UpDirConf\", MenuItem(R\"(\n  Go to the next directory conference '}'\n)\",\n                                  MENU_CAT_CONF, [](MenuContext&) { UpDirConf(); }));\n  m.emplace(\"UpDir\", MenuItem(R\"(\n  Go to the next directory number '+'\n)\",\n                              MENU_CAT_FILE, [](MenuContext&) { UpDir(); }));\n  m.emplace(\"DownDirConf\", MenuItem(R\"(\n  Go to the prior directory conference '{'\n)\",\n                                    MENU_CAT_CONF, [](MenuContext&) { DownDirConf(); }));\n  m.emplace(\"DownDir\", MenuItem(R\"(\n  Go to the prior directory number '-'\n)\",\n                                MENU_CAT_FILE, [](MenuContext&) { DownDir(); }));\n  m.emplace(\"ListUsersDL\", MenuItem(R\"(\n  List users with access to the current xfer sub\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { ListUsersDL(); }));\n  m.emplace(\"PrintDSZLog\", MenuItem(R\"(\n  View the DSZ log\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { PrintDSZLog(); }));\n  m.emplace(\"PrintDevices\", MenuItem(R\"(\n  Show the 'devices'.  I have no idea why.\n)\",\n                                     MENU_CAT_SYS, [](MenuContext&) { PrintDevices(); }));\n  m.emplace(\"ViewArchive\", MenuItem(R\"(\n  List an archive's contents\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { ViewArchive(); }));\n  m.emplace(\"BatchMenu\", MenuItem(R\"(\n  Enter the batch menu 'B'\n)\",\n                                  MENU_CAT_FILE, [](MenuContext&) { BatchMenu(); }));\n  m.emplace(\"Download\", MenuItem(R\"(\n  Download a file 'D'\n)\",\n                                 MENU_CAT_FILE, [](MenuContext&) { Download(); }));\n  m.emplace(\"FindDescription\",\n            MenuItem(R\"(\n  Search for a file by description\n)\",\n                     MENU_CAT_FILE, [](MenuContext&) { FindDescription(); }));\n  m.emplace(\"HopDir\", MenuItem(R\"(\n  Hop to another directory number 'H'\n)\",\n                               MENU_CAT_FILE, [](MenuContext&) { HopDir(); }));\n  m.emplace(\"JumpDirConf\", MenuItem(R\"(\n  Jump to another directory conference 'J'\n)\",\n                                    MENU_CAT_CONF, [](MenuContext&) { JumpDirConf(); }));\n  m.emplace(\"ListFiles\", MenuItem(R\"(\n  List the file in the current directory\n)\",\n                                  MENU_CAT_FILE, [](MenuContext&) { ListFiles(); }));\n  m.emplace(\"NewFileScan\", MenuItem(R\"(\n  List files that are new since your 'New Scan Date (usually last call)' 'N'\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { NewFileScan(); }));\n  m.emplace(\"SetNewFileScanDate\",\n            MenuItem(R\"(\n  Set the 'New Scan Date' to a new date\n)\",\n                     MENU_CAT_FILE, [](MenuContext&) { SetNewFileScanDate(); }));\n  m.emplace(\"RemoveFiles\", MenuItem(R\"(\n  Remove a file you uploaded\n)\",\n                                    MENU_CAT_FILE, [](MenuContext&) { RemoveFiles(); }));\n  m.emplace(\"SearchAllFiles\", MenuItem(R\"(\n  Search all files???\n)\",\n                                       MENU_CAT_FILE, [](MenuContext&) { SearchAllFiles(); }));\n  m.emplace(\"XferDefaults\", MenuItem(R\"(\n  Enter the xfer section defaults\n)\",\n                                     MENU_CAT_FILE, [](MenuContext&) { XferDefaults(); }));\n  m.emplace(\"Upload\", MenuItem(R\"(\n  User upload a file\n)\",\n                               MENU_CAT_FILE, [](MenuContext&) { Upload(); }));\n  m.emplace(\"YourInfoDL\", MenuItem(R\"(\n  Prints user info for downloads\n)\",\n                                   MENU_CAT_SYS, [](MenuContext&) { YourInfoDL(); }));\n  m.emplace(\"UploadToSysop\", MenuItem(R\"(\n  Upload a file into dir#0, the sysop dir.\n)\",\n                                      MENU_CAT_FILE, [](MenuContext&) { UploadToSysop(); }));\n  m.emplace(\"SetNewScanMsg\", MenuItem(R\"(\n  Enter the menu so that a user can set which subs he want to scan when doing\n  a new message scan\n)\",\n                                      MENU_CAT_MSGS, [](MenuContext&) { SetNewScanMsg(); }));\n  m.emplace(\"LoadTextFile\", MenuItem(R\"(\n  Looks like a duplicate to 'LoadText'\n)\",\n                                     MENU_CAT_SYS, [](MenuContext&) { LoadTextFile(); }));\n  m.emplace(\"GuestApply\", MenuItem(R\"(\n  Allows a guest to apply for access\n)\",\n                                   MENU_CAT_SYS, [](MenuContext&) { GuestApply(); }));\n  m.emplace(\"ConfigFileList\", MenuItem(R\"(\n  Enter the List+ configurator so the user can set it up to look like he wants\n)\",\n                                       MENU_CAT_FILE, [](MenuContext&) { ConfigFileList(); }));\n  m.emplace(\"ListAllColors\", MenuItem(R\"(\n  Display all colors available for use.\n)\",\n                                      MENU_CAT_SYS, [](MenuContext&) { ListAllColors(); }));\n  m.emplace(\"RemoveNotThere\", MenuItem(R\"(\n  SYSOP command to remove files that do not exist.\n)\",\n                                       MENU_CAT_FILE, [](MenuContext&) { RemoveNotThere(); }));\n  m.emplace(\"AttachFile\", MenuItem(R\"()\", MENU_CAT_EMAIL, [](MenuContext&) { AttachFile(); }));\n  m.emplace(\"UnQScan\", MenuItem(R\"(\n  Marks messages as unread\n)\",\n                                MENU_CAT_MSGS, [](MenuContext&) { UnQScan(); }));\n\n  ///////////////////////////////////////////////////////////////////////////\n  /// QWK Menu Command\n  ///\n\n  m.emplace(\"Packers\", MenuItem(R\"(\n  Executes the QWK menu. (Legacy, use qwk: commands now)\n)\",\n                                MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_menu(); }));\n\n  m.emplace(\"qwk:menu\", MenuItem(R\"(\n  Executes the default QWK menu.\n)\",\n                                MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_menu(); }));\n\n  m.emplace(\"qwk:upload\", MenuItem(R\"(\n  Upload a QWK Reply Packet\n)\",\n                                MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_upload(); }));\n\n  m.emplace(\"qwk:download\", MenuItem(R\"(\n  Download a QWK Message Packet\n)\",\n                                MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_download(); }));\n  m.emplace(\"qwk:config_user\",\n            MenuItem(R\"(\n  Configures User Settings for QWK)\",\n                     MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_config_user(); }));\n  m.emplace(\"qwk:config_sysop\",\n            MenuItem(R\"(\n  Configures SysOp Settings for QWK)\",\n                     MENU_CAT_QWK, [](MenuContext&) { qwk::qwk_config_sysop(); }));\n  \n  ///////////////////////////////////////////////////////////////////////////\n  /// \n  m.emplace(\"InitVotes\", MenuItem(R\"()\", MENU_CAT_VOTE, [](MenuContext&) { InitVotes(); }));\n  m.emplace(\"TurnMCIOn\", MenuItem(R\"(\n  Enable MCI codes\n)\",\n                                  MENU_CAT_SYS, [](MenuContext&) { bout.enable_mci(); }));\n  m.emplace(\"TurnMCIOff\", MenuItem(R\"(\n  Disable MCI codes\n)\",\n                                   MENU_CAT_SYS, [](MenuContext&) { bout.disable_mci(); }));\n  //  m.emplace(\"\", MenuItem(R\"()\", \"\", [](MenuContext& context) {\n  //    } ));\n\n  // Set the cmd names.\n  for (auto& i : m) {\n    i.second.cmd_ = i.first;\n  }\n  return m;\n}\n\n} // namespace wwiv::bbs::menus\n"
  },
  {
    "path": "bbs/menus/menucommands.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_MENUS_MENUCOMMANDS_H\n#define INCLUDED_MENUS_MENUCOMMANDS_H\n\n#include \"bbs/menus/menu_context.h\"\n#include \"core/stl.h\"\n#include <filesystem>\n#include <map>\n#include <optional>\n#include <string>\n\nnamespace wwiv::bbs::menus {\nclass Menu;\n\nstruct MenuItem {\n  MenuItem(std::string desc, std::string category, std::function<void(MenuContext&)> f)\n      : description_(std::move(desc)), category_(std::move(category)), f_(std::move(f)) {}\n  MenuItem(std::string desc, std::function<void(MenuContext&)> f)\n      : description_(std::move(desc)), f_(std::move(f)) {}\n\n  explicit MenuItem(std::function<void(MenuContext&)> f) : f_(std::move(f)) {}\n\n  std::string description_;\n  std::string category_;\n  std::function<void(MenuContext&)> f_;\n  // Set at the end of CreateMenuMap.\n  std::string cmd_;\n};\n\nstd::map<std::string, MenuItem, wwiv::stl::ci_less> CreateCommandMap();\n\n/**\n * Executes a menu command ```script``` using the menu data for the context of\n * the MENU, or nullptr if not invoked from an actual menu.\n */\nstd::optional<MenuContext> interpret_command(Menu* menu, const std::string& cmd, const std::string& data);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "bbs/menus/menuspec.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/menuspec.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/chains.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/multinst.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/menus/menusupp.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/files.h\"\n\n#include <string>\n\nnamespace wwiv::bbs::menus {\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n/* ---------------------------------------------------------------------- */\n/* menuspec.cpp - Menu Specific support functions                           */\n/*                                                                        */\n/* Functions that don't have any direct WWIV function go in here           */\n/* ie, functions to help emulate other BBS's.                             */\n/* ---------------------------------------------------------------------- */\n\n\nstatic int FindDN(const std::string& dl_fn) {\n  for (auto i = 0; i < a()->dirs().size(); i++) {\n    if (iequals(a()->dirs()[i].filename, dl_fn)) {\n      return i;\n    }\n  }\n  return -1;\n}\n\n/**\n *  Download a file\n *\n *  dir_fn:  fname of your directory record\n *  dl_fn:   Filename to download\n *  free_dl: true if this is a free download\n *  show_title:  true if title is to be shown with file info\n */\nint MenuDownload(const std::string& dir_fn, const std::string& dl_fn, bool free_dl, bool show_title) {\n  int bOkToDL;\n  User ur;\n  bool abort = false;\n\n  int dn = FindDN(dir_fn);\n\n  if (dn == -1) {\n    sysoplog(\"Download: Dir Not Found\");                  /* DL - DIR NOT FOUND */\n    return 0;\n  }\n  const auto& dir = a()->dirs()[dn];\n  dliscan1(dir);\n\n  int nRecordNumber = recno(dl_fn);\n  if (nRecordNumber <= 0) {\n    bin.checka(&abort);\n    if (abort) {\n      return -1;\n    }\n    sysoplog(\"Download: File Not Found\"); /* DL - FILE NOT FOUND */\n    return 0;\n  }\n  bool ok = true;\n  while (nRecordNumber > 0 && ok && !a()->sess().hangup()) {\n    a()->tleft(true);\n    auto f = a()->current_file_area()->ReadFile(nRecordNumber);\n    bout.nl();\n\n    if (show_title) {\n      bout.print(\"Directory  : {}\\r\\n\", dir.name);\n    }\n    bOkToDL = printfileinfo(&f.u(), dir);\n\n    if (!ratio_ok()) {\n      return -1;\n    }\n    if (bOkToDL || free_dl) {\n      write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_NONE);\n      auto s1 = FilePath(dir.path, f);\n      if (dir.mask & mask_cdrom) {\n        s1 = FilePath(a()->sess().dirs().temp_directory(), f);\n        if (!File::Exists(s1)) {\n          File::Copy(FilePath(dir.path, f), s1);\n        }\n      }\n      bool sent = false;\n      if (bOkToDL == -1) {\n        send_file(s1, &sent, &abort, f.aligned_filename(), dn, -2L);\n      } else {\n        send_file(s1, &sent, &abort, f.aligned_filename(), dn, f.numbytes());\n      }\n\n      if (sent) {\n        if (!free_dl) {\n          a()->user()->increment_downloaded();\n          a()->user()->set_dk(a()->user()->dk() +\n                                    static_cast<int>(bytes_to_k(f.numbytes())));\n        }\n        ++f.u().numdloads;\n        if (a()->current_file_area()->UpdateFile(f, nRecordNumber)) {\n          a()->current_file_area()->Save();\n        }\n\n        sysoplog(fmt::format(\"Downloaded '{}'.\", f));\n\n        if (a()->config()->sysconfig_flags() & sysconfig_log_dl) {\n          a()->users()->readuser(&ur, f.u().ownerusr);\n          if (!ur.deleted()) {\n            if (date_to_daten(ur.firston()) < f.u().daten) {\n              const auto username_num = a()->user()->name_and_number();\n              ssm(f.u().ownerusr) << username_num << \" downloaded '\" << f.aligned_filename() << \"' on \" << date();\n            }\n          }\n        }\n      }\n\n      bout.nl(2);\n      bout.printf(\"Your ratio is now: %-6.3f\\r\\n\", a()->user()->ratio());\n\n      if (a()->sess().IsUserOnline()) {\n        a()->UpdateTopScreen();\n      }\n    } else {\n      bout.outstr(\"\\r\\n\\nNot enough time left to D/L.\\r\\n\");\n    }\n    if (abort) {\n      ok = false;\n    } else {\n      nRecordNumber = nrecno(dl_fn, nRecordNumber);\n    }\n  }\n  return abort ? -1 : 1;\n}\n\nint MenuDownload(const std::string& dir_and_fname, bool bFreeDL, bool bTitle) {\n  auto v = SplitString(dir_and_fname, \" \", true);\n  if (v.size() != 2) {\n    return -1;\n  }\n  return MenuDownload(wwiv::stl::at(v, 0), aligns(v.at(1)), bFreeDL, bTitle);\n}\n\nstatic int FindDoorNo(const std::string& name) {\n  for (auto i = 0; i < size_int(a()->chains->chains()); i++) {\n    if (iequals(a()->chains->at(i).description, name)) {\n      return i;\n    }\n  }\n\n  return -1;\n}\n\nstatic bool ValidateDoorAccess(int door_number) {\n  const auto& c = a()->chains->at(door_number);\n  if (c.ansi && !okansi()) {\n    return false;\n  }\n  if (c.local_only && a()->sess().using_modem()) {\n    return false;\n  }\n  if (!check_acs(c.acs)) {\n    return false;\n  }\n  // Check multi-instance doors.\n  if (auto inst = find_instance_by_loc(INST_LOC_CHAINS, door_number + 1); inst != 0) {\n    const auto inuse_msg = fmt::format(\"|#2Chain '{}' is in use on instance {}.  \", c.description, inst);\n    if (!c.multi_user) {\n      bout.print(\"{} Try again later.\\r\\n\", inuse_msg);\n      return false;\n    }\n    bout.print(\"{} Care to join in? \", inuse_msg);\n    if (!bin.yesno()) {\n      return false;\n    }\n  }\n  // passed all the checks, return true\n  return true;\n}\n\n/**\n * Run a Door (chain)\n *\n * name = Door description to run\n * bFree  = If true, security on door will not back checked\n */\nbool MenuRunDoorName(const std::string& name, bool bFree) {\n  const auto door_number = FindDoorNo(name);\n  return door_number >= 0 ? MenuRunDoorNumber(door_number, bFree) : false;\n}\n\nbool MenuRunDoorNumber(int nDoorNumber, bool bFree) {\n  if (!bFree && !ValidateDoorAccess(nDoorNumber)) {\n    return false;\n  }\n\n  run_chain(nDoorNumber);\n  return true;\n}\n\n/* ----------------------- */\n/* End of run door section */\n/* ----------------------- */\nvoid ChangeSubNumber() {\n  bout.outstr(\"|#7Select Sub number : |#0\");\n\n  const auto s = mmkey(MMKeyAreaType::subs);\n  for (auto i = 0; i < size_int(a()->usub); i++) {\n    if (s == a()->usub[i].keys) {\n      a()->set_current_user_sub_num(i);\n    }\n  }\n}\n\nvoid ChangeDirNumber() {\n  auto done = false;\n  while (!done && !a()->sess().hangup()) {\n    bout.outstr(\"|#7Select Dir number : |#0\");\n\n    const auto s = mmkey(MMKeyAreaType::dirs);\n\n    if (s[0] == '?') {\n      DirList();\n      bout.nl();\n      continue;\n    }\n    for (auto i = 0; i < size_int(a()->udir); i++) {\n      if (s == a()->udir[i].keys) {\n        a()->set_current_user_dir_num(i);\n        done = true;\n      }\n    }\n  }\n}\n\n\nstatic void SetConf(ConferenceType t, char key) {\n  auto info = get_conf_info(t);\n\n  for (auto i = 0; i < size_int(info.uc); i++) {\n    if (key == info.uc[i].key.key()) {\n      setuconf(t, i, -1);\n      break;\n    }\n  }\n}\n\n// have a little conference ability...\nvoid SetMsgConf(char conf_designator) {\n  SetConf(ConferenceType::CONF_SUBS, conf_designator);\n}\n\nvoid SetDirConf(char conf_designator) {\n  SetConf(ConferenceType::CONF_DIRS, conf_designator);\n}\n\nvoid EnableConf() {\n  tmp_disable_conf(false);\n}\n\nvoid DisableConf() {\n  tmp_disable_conf(true);\n}\n\nvoid SetNewScanMsg() {\n  sysoplog(\"Select Subs\");\n  config_qscan();\n}\n\n}\n"
  },
  {
    "path": "bbs/menus/menuspec.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MENUS_MENUSPEC_H\n#define INCLUDED_BBS_MENUS_MENUSPEC_H\n\n#include <string>\n\nnamespace wwiv::bbs::menus {\n\nint MenuDownload(const std::string& dir_fn, const std::string& dl_fn, bool free_dl,\n                 bool show_title);\nint MenuDownload(const std::string& dir_and_fname, bool bFreeDL, bool bTitle);\nbool MenuRunDoorName(const std::string& name, bool bFree);\nbool MenuRunDoorNumber(int nDoorNumber, bool bFree);\nvoid ChangeSubNumber();\nvoid ChangeDirNumber();\nvoid SetMsgConf(char conf_designator);\nvoid SetDirConf(char conf_designator);\nvoid EnableConf();\nvoid DisableConf();\nvoid SetNewScanMsg();\n\n}\n\n#endif"
  },
  {
    "path": "bbs/menus/menusupp.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/menusupp.h\"\n\n#include \"bbs/attach.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/chains.h\"\n#include \"bbs/chat.h\"\n#include \"bbs/chnedit.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/diredit.h\"\n#include \"bbs/dirlist.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/external_edit.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/gfileedit.h\"\n#include \"bbs/gfiles.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/listplus.h\"\n#include \"bbs/misccmd.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/multinst.h\"\n#include \"bbs/multmail.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/newuser.h\"\n#include \"bbs/readmail.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/subedit.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/sysoplog.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"bbs/tag.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/valscan.h\"\n#include \"bbs/vote.h\"\n#include \"bbs/voteedit.h\"\n#include \"bbs/wqscn.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xferovl1.h\"\n#include \"bbs/xfertmp.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/menus/menu_data_util.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"common/quote.h\"\n#include \"common/workspace.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/net/networks.h\"\n\n#include <memory>\n#include <string>\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::menus {\n\nvoid UnQScan() {\n  bout.nl();\n  bout.outstr(\"|#9Mark messages as unread on [C]urrent sub or [A]ll subs (A/C/Q)? \");\n  switch (const char ch = onek(\"QAC\\r\"); ch) {\n  case 'Q':\n  case RETURN:\n    break;\n  case 'A': {\n    for (int i = 0; i < a()->config()->max_subs(); i++) {\n      a()->sess().qsc_p[i] = 0;\n    }\n    bout.outstr(\"\\r\\nQ-Scan pointers reset.\\r\\n\\n\");\n  }\n  break;\n  case 'C': {\n    bout.nl();\n    a()->sess().qsc_p[a()->current_user_sub().subnum] = 0;\n    bout.print(\"Messages on {} marked as unread.\\r\\n\",\n               a()->subs().sub(a()->current_user_sub().subnum).name);\n  }\n  break;\n  }\n}\n\nvoid DirList() {\n  dirlist(0);\n}\n\nvoid UpSubConf() {\n  if (!okconf(a()->user())) {\n    return;\n  }\n  const auto cn = a()->sess().current_user_sub_conf_num();\n  const auto ncn = cn < size_int(a()->uconfsub) - 1 ? cn + 1 : 0;\n  a()->sess().set_current_user_sub_conf_num(ncn);\n  setuconf(ConferenceType::CONF_SUBS, ncn, -1);\n}\n\nvoid DownSubConf() {\n  if (!okconf(a()->user())) {\n    return;\n  }\n  const auto cn = a()->sess().current_user_sub_conf_num();\n  const auto ncn = cn > 0 ? cn - 1 : size_int(a()->uconfsub) - 1;\n  a()->sess().set_current_user_sub_conf_num(ncn);\n  setuconf(ConferenceType::CONF_SUBS, a()->sess().current_user_sub_conf_num(), -1);\n}\n\nvoid DownSub() {\n  const auto cn = a()->current_user_sub_num();\n  const auto ncn = cn > 0 ? cn - 1 : size_int(a()->usub) - 1;\n  a()->set_current_user_sub_num(ncn);\n}\n\nvoid UpSub() {\n  const auto cn = a()->current_user_sub_num();\n  const auto last = size_int(a()->usub) - 1;\n  const auto ncn = cn < last ? cn + 1 : 0;\n  a()->set_current_user_sub_num(ncn);\n}\n\nvoid ValidateUser() {\n  bout.nl(2);\n  bout.outstr(\"|#9Enter user name or number:\\r\\n:\");\n  const auto user_name = bin.input_upper(30);\n  if (const auto user_number = finduser1(user_name); user_number > 0) {\n    sysoplog(fmt::format(\"@ Validated user #{}\", user_number));\n    valuser(user_number);\n  } else {\n    bout.outstr(\"Unknown user.\\r\\n\");\n  }\n}\n\nvoid Chains() {\n  if (GuestCheck()) {\n    write_inst(INST_LOC_CHAINS, 0, INST_FLAGS_NONE);\n    play_sdf(CHAINS_NOEXT, false);\n    do_chains();\n  }\n}\n\nvoid TimeBank() {\n  if (GuestCheck()) {\n    write_inst(INST_LOC_BANK, 0, INST_FLAGS_NONE);\n    time_bank();\n  }\n}\n\nvoid Defaults(bool& need_menu_reload) {\n  if (GuestCheck()) {\n    write_inst(INST_LOC_DEFAULTS, 0, INST_FLAGS_NONE);\n    if (bout.printfile(DEFAULTS_NOEXT)) {\n      bout.pausescr();\n    }\n    defaults(need_menu_reload);\n  }\n}\n\nvoid SendEMail() {\n  send_email();\n}\n\nvoid FeedBack() {\n  write_inst(INST_LOC_FEEDBACK, 0, INST_FLAGS_NONE);\n  feedback(false);\n}\n\nvoid Bulletins() {\n  write_inst(INST_LOC_GFILES, 0, INST_FLAGS_NONE);\n  bout.printfile(GFILES_NOEXT);\n  gfiles();\n}\n\nvoid SystemInfo() {\n  WWIVVersion();\n\n  if (bout.printfile(LOGON_NOEXT)) {\n    // Only display the pause if the file is not empty and contains information\n    bout.pausescr();\n  }\n\n  if (bout.printfile(SYSTEM_NOEXT)) {\n    bout.pausescr();\n  }\n}\n\nvoid JumpSubConf() {\n  if (okconf(a()->user())) {\n    jump_conf(ConferenceType::CONF_SUBS);\n  }\n}\n\nvoid KillEMail() {\n  if (GuestCheck()) {\n    write_inst(INST_LOC_KILLEMAIL, 0, INST_FLAGS_NONE);\n    kill_old_email();\n  }\n}\n\nvoid LastCallers() {\n  if (a()->user()->clear_screen()) bout.cls();\n  bout.nl(2);\n  bout.print(\"|#1Last few callers to |#5{}|#7: |#0\\r\\n\", a()->config()->system_name() );\n  bout.nl(2);\n  if (a()->HasConfigFlag(OP_FLAGS_SHOW_CITY_ST) &&\n      a()->config()->newuser_config().use_address_city_state != newuser_item_type_t::unused) {\n    bout.outstr(\"|#2Number Name/Handle               Time  Date  City            ST Cty Modem    ##\\r\\n\");\n  } else {\n    bout.outstr(\"|#2Number Name/Handle               Language   Time  Date  Speed                ##\\r\\n\");\n  }\n  const char filler_char = okansi() ? '\\xCD' : '=';\n  bout.print(\"|#7{}\\r\\n\", std::string(79, filler_char));\n  bout.printfile(LASTON_TXT);\n  bout.print(\"|#7{}\\r\\n\", std::string(79, filler_char));\n  bout.nl();\n  bout.pausescr();\n\n  // InterBBS Last Callers MOD\n  for (const auto& n : a()->nets().networks()) {\n    auto s1 = FilePath(n.dir, LASTON_TXT);\n    if (File::Exists(s1)) {\n        bout.printfile_path(s1);\n        bout.pausescr();\n\t}\n    }\n  // InterBBS Last Callers MOD ends here\n\n}\n\nvoid ReadEMail() {\n  readmail(false);\n}\n\nvoid NewMessageScan() {\n  if (okconf(a()->user())) {\n    bout.nl();\n    bout.outstr(\"|#5New message scan in all conferences? \");\n    if (bin.noyes()) {\n      NewMsgsAllConfs();\n      return;\n    }\n  }\n  write_inst(INST_LOC_SUBS, 65535, INST_FLAGS_NONE);\n  bout.newline = false;\n  nscan();\n  bout.newline = true;\n}\n\nvoid GoodBye() {\n\n  if (a()->batch().numbatchdl() != 0) {\n    bout.nl();\n    bout.outstr(\"|#2Download files in your batch queue (|#1Y/n|#2)? \");\n    if (bin.noyes()) {\n      batchdl(1);\n    }\n  }\n  auto filename = FilePath(a()->sess().dirs().current_menu_gfiles_directory(), LOGOFF_MAT);\n  if (!File::Exists(filename)) {\n    filename = FilePath(a()->config()->gfilesdir(), LOGOFF_MAT);\n  }\n  if (File::Exists(filename)) {\n    int cycle = 0;\n    do {\n      bout.cls();\n      bout.printfile_path(filename);\n      switch (const auto ch = onek(\"QFTO\", true); ch) {\n      case 'Q':\n        cycle = 1;\n        break;\n      case 'F':\n        write_inst(INST_LOC_FEEDBACK, 0, INST_FLAGS_ONLINE);\n        feedback(false);\n        a()->UpdateTopScreen();\n        break;\n      case 'T':\n        write_inst(INST_LOC_BANK, 0, INST_FLAGS_ONLINE);\n        time_bank();\n        break;\n      case 'O':\n        cycle = 1;\n        write_inst(INST_LOC_LOGOFF, 0, INST_FLAGS_NONE);\n        bout.cls();\n        auto used_this_session =\n            (std::chrono::system_clock::now() - a()->sess().system_logon_time());\n        auto secs_used = std::chrono::duration_cast<std::chrono::seconds>(used_this_session);\n        bout.print(\"Time on   = {}\\r\\n\", ctim(static_cast<long>(secs_used.count())));\n        {\n          TempDisablePause disable_pause(bout);\n          bout.printfile(LOGOFF_NOEXT);\n        }\n        a()->user()->subnum(a()->current_user_sub_num());\n        a()->user()->dirnum(a()->current_user_dir_num());\n        if (okconf(a()->user())) {\n          a()->user()->subconf(a()->sess().current_user_sub_conf_num());\n          a()->user()->dirconf(a()->sess().current_user_dir_conf_num());\n        }\n        LogOffCmd();\n        a()->Hangup();\n        break;\n      }\n    } while (cycle == 0);\n  } else {\n    bout.nl(2);\n    bout.outstr(\"|#5Log Off? \");\n    if (bin.yesno()) {\n      write_inst(INST_LOC_LOGOFF, 0, INST_FLAGS_NONE);\n      bout.cls();\n      const auto used_this_session =\n          (std::chrono::system_clock::now() - a()->sess().system_logon_time());\n      const auto sec_used = static_cast<long>(std::chrono::duration_cast<std::chrono::seconds>(used_this_session).count());\n      bout.print(\"Time on   = {}\\r\\n\", ctim(sec_used));\n      {\n        TempDisablePause disable_pause(bout);\n        bout.printfile(LOGOFF_NOEXT);\n      }\n      a()->user()->subnum(a()->current_user_sub_num());\n      a()->user()->dirnum(a()->current_user_dir_num());\n      if (okconf(a()->user())) {\n        a()->user()->subconf(a()->sess().current_user_sub_conf_num());\n        a()->user()->dirconf(a()->sess().current_user_dir_conf_num());\n      }\n      LogOffCmd();\n      a()->Hangup();\n    }\n  }\n}\n\nvoid WWIV_PostMessage() {\n  a()->sess().clear_irt();\n  clear_quotes(a()->sess());\n  if (!a()->usub.empty()) {\n    post(PostData());\n  }\n}\n\nvoid ScanSub() {\n  if (!a()->usub.empty()) {\n    write_inst(INST_LOC_SUBS, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n    bool nextsub = false;\n    qscan(a()->current_user_sub_num(), nextsub);\n  }\n}\n\nvoid RemovePost() {\n  if (!a()->usub.empty()) {\n    write_inst(INST_LOC_SUBS, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n    remove_post();\n  }\n}\n\nvoid TitleScan() {\n  if (!a()->usub.empty()) {\n    write_inst(INST_LOC_SUBS, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n    ScanMessageTitles();\n  }\n}\n\nvoid ListUsers() {\n  list_users(LIST_USERS_MESSAGE_AREA);\n}\n\nvoid Vote() {\n  if (GuestCheck()) {\n    write_inst(INST_LOC_VOTE, 0, INST_FLAGS_NONE);\n    vote();\n  }\n}\n\nvoid ToggleExpert(const std::string& data) {\n  const common::menus::menu_data_and_options_t opts(data);\n  a()->user()->toggle_flag(User::flag_expert);\n  auto o = opts.opts(\"quiet\");\n  if (const auto quiet = !o.empty() && *std::begin(o) == \"off\"; !quiet) {\n    bout.print(\"|#3Expert mode is: {}\\r\\n\", (a()->user()->IsExpert() ? \"On\" : \"Off\"));\n  }\n}\n\nvoid WWIVVersion() {\n  bout.cls();\n  bout.print(\"|#9WWIV Bulletin Board System {}\\r\\n\", full_version());\n  bout.pl(\"|#9Copyright (C) 1998-2023, WWIV Software Services.\");\n  bout.pl(\"|#9All Rights Reserved.\");\n  bout.nl();\n  bout.pl(\"|#9Licensed under the Apache License, Version 2.0.\");\n  bout.pl(\"|#9Please see |#1http://www.wwivbbs.org/ |#9for more information\");\n  bout.nl();\n  bout.print(\"|#9Compile Time    : |#2{}\\r\\n\", wwiv_compile_datetime());\n  bout.print(\"|#9SysOp Name      : |#2{}\\r\\n\", a()->config()->sysop_name());\n  bout.print(\"|#9OS              : |#2{}\\r\\n\", os::os_version_string());\n  bout.print(\"|#9Instance        : |#2{}\\r\\n\", a()->sess().instance_number());\n\n  if (!a()->nets().empty()) {\n    const auto status = a()->status_manager()->get_status();\n    a()->status_manager()->reload_status();\n    bool first = true;\n    bout.print(\"|#9Network Version : |#2net{}\\r\\n\", status->status_net_version());\n    bout.outstr(\"|#9Networks        : \");\n    for (const auto& n : a()->nets().networks()) {\n      if (n.sysnum) {\n        if (!first) {\n          bout.outstr(\"                : \");\n        }\n        first = false;\n        bout.pl(to_string(n));\n      }\n    }\n  }\n\n  bout.nl(3);\n  bout.pausescr();\n}\n\nvoid JumpEdit() {\n  write_inst(INST_LOC_CONFEDIT, 0, INST_FLAGS_NONE);\n  edit_confs();\n}\n\nvoid BoardEdit() {\n  write_inst(INST_LOC_BOARDEDIT, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Board Edit\");\n  boardedit();\n}\n\nvoid ChainEdit() {\n  write_inst(INST_LOC_CHAINEDIT, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Chain Edit\");\n  chainedit();\n}\n\nvoid ToggleChat() {\n  bout.nl(2);\n  const bool bOldAvail = sysop2();\n  ToggleScrollLockKey();\n  const bool bNewAvail = sysop2();\n  if (bOldAvail != bNewAvail) {\n    bout.outstr(bNewAvail ? \"|#5Sysop now available\\r\\n\" : \"|#3Sysop now unavailable\\r\\n\");\n    sysoplog(\"@ Changed sysop available status\");\n  } else {\n    bout.outstr(\"|#6Unable to toggle Sysop availability (hours restriction)\\r\\n\");\n  }\n  a()->UpdateTopScreen();\n}\n\nvoid ChangeUser() {\n  write_inst(INST_LOC_CHUSER, 0, INST_FLAGS_NONE);\n  chuser();\n}\n\nvoid DirEdit() {\n  write_inst(INST_LOC_DIREDIT, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Directory Edit\");\n  dlboardedit();\n}\n\nvoid LoadTextFile() {\n  bout.nl();\n  bout.outstr(\"|#9Enter Filename: \");\n  const auto fileName = bin.input_path(\"\", 50);\n  if (!fileName.empty()) {\n    bout.nl();\n    bout.outstr(\"|#5Allow editing? \");\n    if (bin.yesno()) {\n      bout.nl();\n      LoadFileIntoWorkspace(a()->context(), fileName, false);\n    } else {\n      bout.nl();\n      LoadFileIntoWorkspace(a()->context(), fileName, true);\n    }\n  }\n}\n\nvoid EditText() {\n  write_inst(INST_LOC_TEDIT, 0, INST_FLAGS_NONE);\n  bout.nl();\n  bout.outstr(\"|#7Enter Filespec: \");\n  const auto fn = bin.input_path(50);\n  if (!fn.empty()) {\n    fsed_text_edit(fn, \"\", 500, MSGED_FLAG_NO_TAGLINE);\n  }\n}\n\nvoid EditBulletins() {\n  write_inst(INST_LOC_GFILEEDIT, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Gfile Edit\");\n  gfileedit();\n}\n\nvoid ReadAllMail() {\n  write_inst(INST_LOC_MAILR, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Read mail\");\n  mailr();\n}\n\nvoid ResetQscan() {\n  bout.outstr(\"|#5Reset all QScan/NScan pointers (For All Users)? \");\n  if (bin.yesno()) {\n    write_inst(INST_LOC_RESETQSCAN, 0, INST_FLAGS_NONE);\n    for (int i = 0; i <= a()->users()->num_user_records(); i++) {\n      read_qscn(i, a()->sess().qsc, true);\n      memset(a()->sess().qsc_p, 0,\n             a()->config()->qscn_len() - 4 * (1 + ((a()->config()->max_dirs() + 31) / 32) +\n                                              ((a()->config()->max_subs() + 31) / 32)));\n      write_qscn(i, a()->sess().qsc, true);\n    }\n    read_qscn(1, a()->sess().qsc, false);\n    close_qscn();\n  }\n}\n\nvoid MemoryStatus() {\n  const auto status = a()->status_manager()->get_status();\n  bout.nl();\n  bout.print(\"Qscanptr        : {}\\r\\n\", status->qscanptr());\n}\n\nvoid InitVotes() {\n  write_inst(INST_LOC_VOTE, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Ivotes\");\n  ivotes();\n}\n\nvoid ReadLog() {\n  const auto sysop_log_file = sysoplog_filename(date());\n  bout.print_local_file(sysop_log_file);\n}\n\nvoid ReadNetLog() {\n  bout.print_local_file(NET_LOG);\n}\n\nvoid PrintPending() {\n  print_pending_list();\n}\n\nvoid PrintStatus() {\n  prstatus();\n}\n\nvoid TextEdit() {\n  write_inst(INST_LOC_TEDIT, 0, INST_FLAGS_NONE);\n  sysoplog(\"@ Ran Text Edit\");\n  text_edit();\n}\n\nvoid VotePrint() {\n  write_inst(INST_LOC_VOTEPRINT, 0, INST_FLAGS_NONE);\n  voteprint();\n}\n\nvoid YesterdaysLog() {\n  const auto status = a()->status_manager()->get_status();\n  bout.print_local_file(status->log_filename(1));\n}\n\nvoid ZLog() {\n  zlog();\n}\n\nvoid ViewNetDataLog() {\n  while (!a()->sess().hangup()) {\n    bout.nl();\n    bout.outstr(\"|#9Which NETDAT log (0-2,Q)? \");\n    const auto netdat_num= onek(\"Q012\");\n    if (netdat_num == 'Q') {\n      return;\n    }\n    bout.print_local_file(fmt::format(\"netdat{}.log\", netdat_num));\n  }\n}\n\nvoid UploadPost() {\n  upload_post();\n}\n\nvoid WhoIsOnline() {\n  multi_instance();\n  bout.nl();\n  bout.pausescr();\n}\n\nvoid NewMsgsAllConfs() {\n  bool ac = false;\n\n  write_inst(INST_LOC_SUBS, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n  bout.newline = false;\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    ac = true;\n    tmp_disable_conf(true);\n  }\n  nscan();\n  bout.newline = true;\n  if (ac == true) {\n    tmp_disable_conf(false);\n  }\n}\n\nvoid MultiEmail() {\n  slash_e();\n}\n\nvoid NewMsgScanFromHere() {\n  bout.newline = false;\n  nscan(a()->current_user_sub_num());\n  bout.newline = true;\n}\n\nvoid ValidateScan() {\n  bout.newline = false;\n  valscan();\n  bout.newline = true;\n}\n\nvoid ChatRoom() {\n  write_inst(INST_LOC_CHATROOM, 0, INST_FLAGS_NONE);\n  chat_room();\n}\n\nvoid ClearQScan() {\n  bout.nl();\n  bout.outstr(\"|#5Mark messages as read on [C]urrent sub or [A]ll subs (A/C/Q)? \");\n  switch (const auto ch = onek(\"QAC\\r\"); ch) {\n  case 'Q':\n  case RETURN:\n    break;\n  case 'A': {\n    const auto status = a()->status_manager()->get_status();\n    for (int i = 0; i < a()->config()->max_subs(); i++) {\n      a()->sess().qsc_p[i] = status->qscanptr() - 1L;\n    }\n    bout.nl();\n    bout.outstr(\"Q-Scan pointers cleared.\\r\\n\");\n  }\n  break;\n  case 'C':\n    const auto status = a()->status_manager()->get_status();\n    bout.nl();\n    a()->sess().qsc_p[a()->current_user_sub().subnum] = status->qscanptr() - 1L;\n    bout.print(\"Messages on {} marked as read.\\r\\n\", a()->subs().sub(a()->current_user_sub().subnum).name);\n    break;\n  }\n}\n\nvoid FastGoodBye() {\n  if (a()->batch().numbatchdl() != 0) {\n    bout.nl();\n    bout.outstr(\"|#2Download files in your batch queue (|#1Y/n|#2)? \");\n    if (bin.noyes()) {\n      batchdl(1);\n    }\n  }\n  a()->user()->subnum(a()->current_user_sub_num());\n  a()->user()->dirnum(a()->current_user_dir_num());\n  if (okconf(a()->user())) {\n    a()->user()->subconf(a()->sess().current_user_sub_conf_num());\n    a()->user()->dirconf(a()->sess().current_user_dir_conf_num());\n  }\n  LogOffCmd();\n  a()->Hangup();\n}\n\nvoid NewFilesAllConfs() {\n  bout.nl();\n  int ac = 0;\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    ac = 1;\n    tmp_disable_conf(true);\n  }\n  nscanall();\n  if (ac) {\n    tmp_disable_conf(false);\n  }\n}\n\nvoid ReadIDZ() {\n  bout.nl();\n  bout.outstr(\"|#5Read FILE_ID.DIZ for all directories? \");\n  if (bin.yesno()) {\n    read_idz_all();\n  } else {\n    read_idz(true, a()->current_user_dir_num());\n  }\n}\n\nvoid RemoveNotThere() {\n  removenotthere();\n}\n\nvoid UploadAllDirs() {\n  bout.nl(2);\n  auto ok = true;\n  for (auto dn = 0;\n       dn < size_int(a()->udir) && a()->udir[dn].subnum >= 0 && ok && !a()->sess().hangup(); dn++) {\n    bout.print(\"|#9Now uploading files for: |#2{}\\r\\n\", a()->dirs()[a()->udir[dn].subnum].name);\n    ok = uploadall(dn);\n  }\n}\n\n\nvoid UploadCurDir() {\n  uploadall(a()->current_user_dir_num());\n}\n\nvoid RenameFiles() {\n  rename_file();\n}\n\nvoid MoveFiles() {\n  move_file();\n}\n\nvoid SortDirs() {\n  bout.nl();\n  bout.outstr(\"|#5Sort all dirs? \");\n  bool bSortAll = bin.yesno();\n  bout.nl();\n  bout.outstr(\"|#5Sort by date? \");\n\n  int nType = 0;\n  if (bin.yesno()) {\n    nType = 2;\n  }\n\n  TempDisablePause disable_pause(bout);\n  if (bSortAll) {\n    sort_all(nType);\n  } else {\n    sortdir(a()->current_user_dir().subnum, nType);\n  }\n}\n\nvoid ReverseSort() {\n  bout.nl();\n  bout.outstr(\"|#5Sort all dirs? \");\n  bool bSortAll = bin.yesno();\n  bout.nl();\n  TempDisablePause disable_pause(bout);\n  if (bSortAll) {\n    sort_all(1);\n  } else {\n    sortdir(a()->current_user_dir().subnum, 1);\n  }\n}\n\nvoid AllowEdit() {\n  edit_database();\n}\n\nvoid UploadFilesBBS() {\n  bout.nl();\n  bout.outstr(\"|#21|#9) PCB, RBBS   - <filename> <size> <date> <description>\\r\\n\");\n  bout.outstr(\"|#22|#9) QBBS format - <filename> <description>\\r\\n\");\n  bout.nl();\n  bout.outstr(\"|#Select Format (1,2,Q) : \");\n  char ch = onek(\"Q12\");\n  bout.nl();\n  if (ch != 'Q') {\n    bout.outstr(\"|#9Enter Filename (wildcards allowed).\\r\\n|#7: \");\n    bout.mpl(77);\n    const auto filespec = bin.input_text(80);\n    const auto type = (ch == '1') ? 2 : 0;\n    upload_files(filespec, a()->current_user_dir_num(), type);\n  }\n}\n\nvoid UpDirConf() {\n  if (!okconf(a()->user())) {\n    return;\n  }\n  const auto cn = a()->sess().current_user_dir_conf_num();\n  const auto last = size_int(a()->uconfdir) - 1;\n  a()->sess().set_current_user_dir_conf_num( (cn < last) ? cn + 1 : 0);\n  setuconf(ConferenceType::CONF_DIRS, a()->sess().current_user_dir_conf_num(), -1);\n}\n\nvoid UpDir() {\n  const auto cd = a()->current_user_dir_num();\n  const auto last = size_int(a()->udir) - 1;\n  if (cd < last) {\n    a()->set_current_user_dir_num(cd + 1);\n  } else {\n    a()->set_current_user_dir_num(0);\n  }\n}\n\nvoid DownDirConf() {\n  if (!okconf(a()->user())) {\n    return;\n  }\n  const auto cn = a()->sess().current_user_dir_conf_num();\n  const auto ncn = cn > 0 ? cn - 1 : size_int(a()->uconfdir) - 1;\n  a()->sess().set_current_user_dir_conf_num(ncn);\n  setuconf(ConferenceType::CONF_DIRS, ncn, -1);\n}\n\nvoid DownDir() {\n  const auto cd = a()->current_user_dir_num();\n  const auto last = size_int(a()->udir) - 1;\n  if (cd > 0) {\n    a()->set_current_user_dir_num(cd - 1);\n  } else {\n    a()->set_current_user_dir_num(last);\n  }\n}\n\nvoid ListUsersDL() {\n  list_users(LIST_USERS_FILE_AREA);\n}\n\nvoid PrintDSZLog() {\n  if (File::Exists(a()->dsz_logfile_name_)) {\n    bout.print_local_file(a()->dsz_logfile_name_);\n  }\n}\n\nvoid PrintDevices() {\n  print_devices();\n}\n\nvoid ViewArchive() {\n  arc_l();\n}\n\nvoid BatchMenu() {\n  batchdl(0);\n}\n\nvoid Download() {\n  play_sdf(DOWNLOAD_NOEXT, false);\n  bout.printfile(DOWNLOAD_NOEXT);\n  download();\n}\n\nvoid FindDescription() {\n  finddescription();\n}\n\nvoid JumpDirConf() {\n  if (okconf(a()->user())) {\n    jump_conf(ConferenceType::CONF_DIRS);\n  }\n}\n\nvoid ConfigFileList() {\n  if (okansi()) {\n    config_file_list();\n  }\n}\n\nvoid ListFiles() {\n  listfiles();\n}\n\nvoid NewFileScan() {\n  SetNewFileScanDate();\n  bool abort = false;\n  bool need_title = true;\n  bout.nl();\n  bout.outstr(\"|#5Search all directories? \");\n  if (bin.yesno()) {\n    nscanall();\n  } else {\n    bout.nl();\n    nscandir(a()->current_user_dir_num(), need_title, &abort);\n    if (!a()->filelist.empty()) {\n      endlist(2);\n    } else {\n      bout.nl();\n      bout.outstr(\"|#2No new files found.\\r\\n\");\n    }\n  }\n}\n\nvoid RemoveFiles() {\n  if (GuestCheck()) {\n    removefile();\n  }\n}\n\nvoid SearchAllFiles() {\n  searchall();\n}\n\nvoid XferDefaults() {\n  if (GuestCheck()) {\n    xfer_defaults();\n  }\n}\n\nvoid Upload() {\n  play_sdf(UPLOAD_NOEXT, false);\n  bout.printfile(UPLOAD_NOEXT);\n  if (a()->user()->restrict_validate() || a()->user()->restrict_upload() ||\n      (a()->config()->sysconfig_flags() & sysconfig_all_sysop)) {\n    if (a()->config()->new_uploads_dir() < a()->dirs().size()) {\n      upload(static_cast<int>(a()->config()->new_uploads_dir()));\n    } else {\n      upload(0);\n    }\n  } else {\n    upload(a()->current_user_dir().subnum);\n  }\n}\n\nvoid YourInfoDL() {\n  YourInfo();\n}\n\nvoid UploadToSysop() {\n  bout.printfile(ZUPLOAD_NOEXT);\n  bout.nl(2);\n  bout.outstr(\"Sending file to sysop :-\\r\\n\\n\");\n  upload(0);\n}\n\nvoid GuestApply() {\n  if (a()->user()->guest_user()) {\n    newuser();\n  } else {\n    bout.outstr(\"You already have an account on here!\\r\\n\\r\\n\");\n  }\n}\n\nvoid AttachFile() {\n  attach_file(0);\n}\n\nbool GuestCheck() {\n  if (a()->user()->guest_user()) {\n    bout.outstr(\"|#6This command is only for registered users.\\r\\n\");\n    return false;\n  }\n  return true;\n}\n\nvoid SetSubNumber(const MenuContext& context) {\n  for (auto i = 0; i < size_int(a()->usub); i++) {\n    if (a()->usub[i].keys == context.data) {\n      a()->set_current_user_sub_num(i);\n    }\n  }\n}\n\nvoid SetDirNumber(const MenuContext& context) {\n  for (auto i = 0; i < size_int(a()->udir); i++) {\n    if (a()->udir[i].keys == context.data) {\n      a()->set_current_user_dir_num(i);\n    }\n  }\n}\n\nvoid LogOffCmd() {\n  if (a()->logoff_cmd.empty()) {\n    return;\n  }\n\n  bout.nl();\n  wwiv::bbs::CommandLine cl(a()->logoff_cmd);\n  cl.args(create_chain_file());\n  ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_LOGOFF));\n  bout.nl(2);\n}\n\n\n}\n"
  },
  {
    "path": "bbs/menus/menusupp.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_BBS_MENUS_MENUSUPP_H\r\n#define INCLUDED_BBS_MENUS_MENUSUPP_H\r\n\r\n#include \"bbs/menus/menu_context.h\"\r\n\r\nnamespace wwiv::bbs::menus {\r\n\r\nvoid UnQScan();\r\nvoid DirList();\r\nvoid UpSubConf();\r\nvoid DownSubConf();\r\nvoid DownSub();\r\nvoid UpSub();\r\nvoid ValidateUser();\r\nvoid Chains();\r\nvoid TimeBank();\r\nvoid Defaults(bool& need_menu_reload);\r\nvoid SendEMail();\r\nvoid FeedBack();\r\nvoid Bulletins();\r\nvoid SystemInfo();\r\nvoid JumpSubConf();\r\nvoid KillEMail();\r\nvoid LastCallers();\r\nvoid ReadEMail();\r\nvoid NewMessageScan();\r\nvoid GoodBye();\r\nvoid WWIV_PostMessage();\r\nvoid ScanSub();\r\nvoid RemovePost();\r\nvoid TitleScan();\r\nvoid ListUsers();\r\nvoid Vote();\r\nvoid ToggleExpert(const std::string& data);\r\nvoid WWIVVersion();\r\nvoid JumpEdit();\r\nvoid BoardEdit();\r\nvoid ChainEdit();\r\nvoid ToggleChat();\r\nvoid ChangeUser();\r\nvoid DirEdit();\r\nvoid LoadTextFile();\r\nvoid EditText();\r\nvoid EditBulletins();\r\nvoid ReadAllMail();\r\nvoid ResetQscan();\r\nvoid MemoryStatus();\r\nvoid InitVotes();\r\nvoid ReadLog();\r\nvoid ReadNetLog();\r\nvoid PrintPending();\r\nvoid PrintStatus();\r\nvoid TextEdit();\r\nvoid VotePrint();\r\nvoid YesterdaysLog();\r\nvoid ZLog();\r\nvoid ViewNetDataLog();\r\nvoid UploadPost();\r\nvoid WhoIsOnline();\r\nvoid NewMsgsAllConfs();\r\nvoid MultiEmail();\r\nvoid NewMsgScanFromHere();\r\nvoid ValidateScan();\r\nvoid ChatRoom();\r\nvoid ClearQScan();\r\nvoid FastGoodBye();\r\nvoid NewFilesAllConfs();\r\nvoid ReadIDZ();\r\nvoid RemoveNotThere();\r\nvoid UploadAllDirs();\r\nvoid UploadCurDir();\r\nvoid RenameFiles();\r\nvoid MoveFiles();\r\nvoid SortDirs();\r\nvoid ReverseSort();\r\nvoid AllowEdit();\r\nvoid UploadFilesBBS();\r\nvoid UpDirConf();\r\nvoid UpDir();\r\nvoid DownDirConf();\r\nvoid DownDir();\r\nvoid ListUsersDL();\r\nvoid PrintDSZLog();\r\nvoid PrintDevices();\r\nvoid ViewArchive();\r\nvoid BatchMenu();\r\nvoid Download();\r\nvoid FindDescription();\r\nvoid JumpDirConf();\r\nvoid ConfigFileList();\r\nvoid ListFiles();\r\nvoid NewFileScan();\r\nvoid RemoveFiles();\r\nvoid SearchAllFiles();\r\nvoid XferDefaults();\r\nvoid Upload();\r\nvoid YourInfoDL();\r\nvoid UploadToSysop();\r\nvoid GuestApply();\r\nvoid AttachFile();\r\nbool GuestCheck();\r\nvoid LogOffCmd();\r\nvoid SetSubNumber(const MenuContext& context);\r\nvoid SetDirNumber(const MenuContext& context);\r\n\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "bbs/menus/printcommands.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/menus/printcommands.h\"\n\n#include \"bbs/menus/menucommands.h\"\n#include \"bbs/bbs.h\"\n#include \"sdk/config.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/menus/menus_cereal.h\"\n\nnamespace wwiv::bbs::menus {\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::menus;\n\nvoid emit_menu(const std::string& cmd, const std::string& cat, const std::string& desc,\n               bool markdown, bool group_by_cat) {\n  const auto lines = SplitString(desc, \"\\n\");\n  const auto c = group_by_cat || cat.empty() ? \"\" : StrCat(\" [\", cat, \"]\");\n  if (markdown) {\n    std::cout << \"### \";\n  }\n  std::cout << cmd << c << std::endl;\n  for (const auto& d : lines) {\n    std::cout << \"    \" << StringTrim(d) << std::endl;\n  }\n  std::cout << std::endl << std::endl;\n}\n\nvoid emit_category_name(const std::string& cat, bool output_markdown) {\n  if (cat.empty()) {\n    return;\n  }\n\n  if (output_markdown) {\n    std::cout << \"## \";\n  }\n  std::cout << \"Category: \" << StringTrim(cat) << std::endl;\n  std::cout << \"***\" << std::endl;\n  std::cout << std::endl;\n}\n\nvoid PrintMenuCommands(const std::string& arg) {\n  const auto category_group = arg.find('c') != std::string::npos;\n  const auto output_markdown = arg.find('m') != std::string::npos;\n  const auto output_json = arg.find('j') != std::string::npos;\n\n  auto raw_commands = CreateCommandMap();\n  auto& commands = raw_commands;\n  std::map<std::string, std::vector<MenuItem>> cat_commands;\n  for (const auto& c : raw_commands) {\n    cat_commands[c.second.category_].emplace_back(c.second);\n  }\n\n  if (output_json) {\n    std::cout << \"Saving JSON help file.\" << std::endl;\n    std::vector<menu_command_help_t> cmds;\n    for (const auto& c : raw_commands) {\n      menu_command_help_t cmd{};\n      cmd.cat = c.second.category_;\n      cmd.cmd = c.second.cmd_;\n      cmd.help = c.second.description_;\n      StringTrim(&cmd.help);\n      cmds.emplace_back(cmd);\n    }\n    std::sort(std::begin(cmds), std::end(cmds),\n              [](const menu_command_help_t& l, const menu_command_help_t& r) -> bool {\n                return l < r;\n              });\n    SaveCommandHelpJSON(a()->config()->datadir(), cmds);\n    return;\n  }\n\n  if (output_markdown) {\n    std::cout << R\"(\n# WWIV Menu Commands\n***\n\nHere is the list of all WWIV Menu Commands available in the Menu Editor broken\nout by category.\n\n)\";\n  }\n\n  if (category_group) {\n    for (const auto& c : cat_commands) {\n      emit_category_name(c.first, output_markdown);\n      for (const auto& m : c.second) {\n        emit_menu(m.cmd_, \"\", m.description_, output_markdown, true);\n      }\n    }\n    return;\n  }\n  for (const auto& c : commands) {\n    const auto cmd = c.first;\n    const auto cat = c.second.category_;\n    const auto desc = c.second.description_;\n    emit_menu(cmd, cat, desc, output_markdown, false);\n  }\n}\n\n\n}\n"
  },
  {
    "path": "bbs/menus/printcommands.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_MENUS_PRINTCOMMANDS_H\n#define INCLUDED_MENUS_PRINTCOMMANDS_H\n\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::bbs::menus {\n\n/**\n * Writes the menu commands to standard out.\n *\n */\nvoid PrintMenuCommands(const std::string& arg);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "bbs/message_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/message_file.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/msgapi/type2_text.h\"\n#include \"sdk/status.h\"\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\ntemplate <class S>\nconstexpr auto MSG_STARTING(S section) { return section * GATSECLEN + GAT_SECTION_SIZE; }\n\nstatic long gat_section = -1;\nstatic gati_t *gat = new gati_t[2048]();\n\n/**\n* Opens the message area file {messageAreaFileName} and returns the file handle.\n* Note: This is a Private method to this module.\n*/\nstatic std::unique_ptr<File> OpenMessageFile(const std::string messageAreaFileName) {\n  a()->status_manager()->reload_status();\n\n  const auto filename =\n      FilePath(a()->config()->msgsdir(), StrCat(messageAreaFileName, FILENAME_DAT_EXTENSION));\n  auto file = std::make_unique<File>(filename);\n  if (!file->Open(File::modeReadWrite | File::modeBinary)) {\n    // Create message area file if it doesn't exist.\n    file->Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite);\n    for (int i = 0; i < GAT_NUMBER_ELEMENTS; i++) {\n      gat[i] = 0;\n    }\n    file->Write(gat, GAT_SECTION_SIZE);\n    file->Close();\n    file->set_length(GAT_SECTION_SIZE + (75L * 1024L));\n    file->Open(File::modeReadWrite | File::modeBinary);\n    gat_section = 0;\n  }\n  file->Seek(0L, File::Whence::begin);\n  file->Read(gat, GAT_SECTION_SIZE);\n\n  gat_section = 0;\n  return file;\n}\n\nstatic void set_gat_section(File& file, int section) {\n  if (gat_section == section) {\n    return;\n  }\n  auto file_size = file.length();\n  const auto section_pos = section * GATSECLEN;\n  if (file_size < section_pos) {\n    file.set_length(section_pos);\n    file_size = section_pos;\n  }\n  file.Seek(section_pos, File::Whence::begin);\n  if (file_size < (section_pos + GAT_SECTION_SIZE)) {\n    for (auto i = 0; i < GAT_NUMBER_ELEMENTS; i++) {\n      gat[i] = 0;\n    }\n    file.Write(gat, GAT_SECTION_SIZE);\n  } else {\n    file.Read(gat, GAT_SECTION_SIZE);\n  }\n  gat_section = section;\n}\n\nstatic void save_gat(File& file) {\n  const auto section_pos = gat_section * GATSECLEN;\n  file.Seek(section_pos, File::Whence::begin);\n  file.Write(gat, GAT_SECTION_SIZE);\n  a()->status_manager()->Run([](Status& s) {\n    s.increment_filechanged(Status::file_change_posts);\n  });\n}\n\n/**\n* Deletes a message\n* This is a public function.\n*/\nvoid remove_link(const messagerec* msg, const std::string& fileName) {\n  switch (msg->storage_type) {\n  case 0:\n  case 1:\n    break;\n  case 2:\n  {\n    auto file(OpenMessageFile(fileName));\n    if (!file->IsOpen()) {\n      return;\n    }\n    set_gat_section(*file, static_cast<int>(msg->stored_as / GAT_NUMBER_ELEMENTS));\n    uint32_t current_section = msg->stored_as % GAT_NUMBER_ELEMENTS;\n    while (current_section > 0 && current_section < GAT_NUMBER_ELEMENTS) {\n      const int next_section = static_cast<long>(gat[current_section]);\n      gat[current_section] = 0;\n      current_section = next_section;\n    }\n    save_gat(*file);\n    file->Close();\n  }\n  break;\n  default:\n    // illegal storage type\n    break;\n  }\n}\n\nvoid savefile(const std::string& text, messagerec* msg, const std::string& fileName) {\n  switch (msg->storage_type) {\n  case 0:\n  case 1:\n    break;\n  case 2:\n  {\n    gati_t gati[128];\n    memset(&gati, 0, sizeof(gati));\n    auto file(OpenMessageFile(fileName));\n    if (file->IsOpen()) {\n      for (int section = 0; section < 1024; section++) {\n        set_gat_section(*file, section);\n        int gatp = 0;\n        int nNumBlocksRequired = static_cast<int>((text.length() + 511L) / MSG_BLOCK_SIZE);\n        gati_t i4 = 1;\n        while (gatp < nNumBlocksRequired && i4 < GAT_NUMBER_ELEMENTS) {\n          if (gat[i4] == 0) {\n            gati[gatp++] = i4;\n          }\n          ++i4;\n        }\n        if (gatp >= nNumBlocksRequired) {\n          gati[gatp] = static_cast<gati_t>(-1);\n          const auto text_len = ssize(text);\n          for (int i = 0; i < nNumBlocksRequired; i++) {\n            char block[MSG_BLOCK_SIZE + 1];\n            memset(block, 0, sizeof(block));\n            file->Seek(MSG_STARTING(gat_section) + MSG_BLOCK_SIZE * static_cast<long>(gati[i]), File::Whence::begin);\n            const auto remaining = std::min(text_len - (i * MSG_BLOCK_SIZE), MSG_BLOCK_SIZE);\n            memcpy(block, &text[i * MSG_BLOCK_SIZE], remaining);\n            file->Write(block, MSG_BLOCK_SIZE);\n            gat[gati[i]] = gati[i + 1];\n          }\n          save_gat(*file);\n          break;\n        }\n      }\n      file->Close();\n    }\n    msg->stored_as = static_cast<long>(gati[0]) + static_cast<long>(gat_section) * GAT_NUMBER_ELEMENTS;\n  }\n  break;\n  default:\n  {\n    bout.printf(\"WWIV:ERROR:msgbase.cpp: Save - storage_type=%u!\\r\\n\", msg->storage_type);\n  }\n  break;\n  }\n}\n\nstd::optional<std::string> readfile(const messagerec* msg, const std::string& fileName) {\n  if (msg->storage_type != 2) {\n    return std::nullopt;\n  }\n\n  auto file(OpenMessageFile(fileName));\n  set_gat_section(*file, static_cast<int>(msg->stored_as) / GAT_NUMBER_ELEMENTS);\n  auto current_section = static_cast<int>(msg->stored_as % GAT_NUMBER_ELEMENTS);\n  long message_length = 0;\n  while (current_section > 0 && current_section < GAT_NUMBER_ELEMENTS) {\n    message_length += MSG_BLOCK_SIZE;\n    current_section = gat[current_section];\n  }\n  if (message_length == 0) {\n    bout.outstr(\"\\r\\nNo message found.\\r\\n\\n\");\n    return std::nullopt;\n  }\n\n  std::string out;\n  current_section = static_cast<int>(msg->stored_as) % GAT_NUMBER_ELEMENTS;\n  while (current_section > 0 && current_section < GAT_NUMBER_ELEMENTS) {\n    file->Seek(MSG_STARTING(gat_section) + MSG_BLOCK_SIZE * static_cast<uint32_t>(current_section), File::Whence::begin);\n    char b[MSG_BLOCK_SIZE + 1];\n    file->Read(b, MSG_BLOCK_SIZE);\n    b[MSG_BLOCK_SIZE] = 0;\n    out.append(b);\n    current_section = gat[current_section];\n  }\n  file->Close();\n  const auto last_cz = out.find_last_of(wwiv::local::io::CZ);\n  const auto last_block_start = out.size() - MSG_BLOCK_SIZE;\n  if (last_cz != std::string::npos && last_block_start >= 0 && last_cz > last_block_start) {\n    // last block has a Control-Z in it.  Make sure we add a 0 after it.\n    out.resize(last_cz);\n  }\n  return {out};\n}\n\nvoid lineadd(const messagerec* msg, const std::string& sx, std::string fileName) {\n  const auto line = fmt::sprintf(\"%s\\r\\n\\x1a\", sx);\n\n  switch (msg->storage_type) {\n  case 0:\n  case 1:\n    break;\n  case 2:\n  {\n    auto message_file(OpenMessageFile(fileName));\n    set_gat_section(*message_file, msg->stored_as / GAT_NUMBER_ELEMENTS);\n    int new1 = 1;\n    while (new1 < GAT_NUMBER_ELEMENTS && gat[new1] != 0) {\n      ++new1;\n    }\n    auto i = static_cast<int>(msg->stored_as % GAT_NUMBER_ELEMENTS);\n    while (gat[i] != 65535) {\n      i = gat[i];\n    }\n    char *b = nullptr;\n    // The +1 may not be needed but BbsAllocA did it.\n    if ((b = static_cast<char*>(calloc(GAT_NUMBER_ELEMENTS + 1, 1))) == nullptr) {\n      message_file->Close();\n      return;\n    }\n    message_file->Seek(MSG_STARTING(gat_section) + static_cast<long>(i) * MSG_BLOCK_SIZE, File::Whence::begin);\n    message_file->Read(b, MSG_BLOCK_SIZE);\n    int j = 0;\n    while (j < MSG_BLOCK_SIZE && b[j] != wwiv::local::io::CZ) {\n      ++j;\n    }\n    strcpy(&(b[j]), line.c_str());\n    message_file->Seek(MSG_STARTING(gat_section) + static_cast<long>(i) * MSG_BLOCK_SIZE, File::Whence::begin);\n    message_file->Write(b, MSG_BLOCK_SIZE);\n    if (j + line.size() > MSG_BLOCK_SIZE && new1 != GAT_NUMBER_ELEMENTS) {\n      message_file->Seek(MSG_STARTING(gat_section) + static_cast<long>(new1)  * MSG_BLOCK_SIZE, File::Whence::begin);\n      message_file->Write(b + MSG_BLOCK_SIZE, MSG_BLOCK_SIZE);\n      gat[new1] = 65535;\n      gat[i] = static_cast<gati_t>(new1);\n      save_gat(*message_file);\n    }\n    free(b);\n    message_file->Close();\n  }\n  break;\n  default:\n    // illegal storage type\n    break;\n  }\n}\n"
  },
  {
    "path": "bbs/message_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MESSAGE_FILE_H\n#define INCLUDED_BBS_MESSAGE_FILE_H\n\n#include <cstdint>\n#include <optional>\n#include <string>\n\nconstexpr uint8_t EMAIL_STORAGE = 2;\n\nstruct messagerec;\n\nvoid remove_link(const messagerec* msg, const std::string& fileName);\nvoid savefile(const std::string& text, messagerec* msg, const std::string& fileName);\nstd::optional<std::string> readfile(const messagerec* msg, const std::string& fileName);\nvoid lineadd(const messagerec* msg, const std::string& sx, const std::string fileName);\n\n#endif\n"
  },
  {
    "path": "bbs/message_find.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/message_find.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/subacc.h\"\n#include \"common/com.h\"\n#include \"common/full_screen.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"sdk/subxtr.h\"\n\nnamespace wwiv::bbs {\n\nstatic std::string last_search_string;\nstatic bool last_search_forward{true};\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n\nfind_message_result_t FindNextMessageAgain(int msgno) {\n  const auto search_string = last_search_string;\n  const auto msgnum_limit = last_search_forward ? a()->GetNumMessagesInCurrentMessageArea() : 1;\n  auto tmp_msgnum = msgno;\n  auto fnd = false;\n  while (tmp_msgnum != msgnum_limit && !fnd) {\n    if (last_search_forward) {\n      tmp_msgnum++;\n    } else {\n      tmp_msgnum--;\n    }\n    if (bin.checka()) {\n      break;\n    }\n    if (!(tmp_msgnum % 5)) {\n      bout.printf(\"%5.5d\", tmp_msgnum);\n      for (auto i1 = 0; i1 < 5; i1++) {\n        bout.outstr(\"\\b\");\n      }\n      if (!(tmp_msgnum % 100)) {\n        a()->tleft(true);\n        a()->CheckForHangup();\n      }\n    }\n    if (auto o = readfile(&(get_post(tmp_msgnum)->msg), a()->current_sub().filename)) {\n      auto b = ToStringUpperCase(o.value());\n      const std::string title = stripcolors(get_post(tmp_msgnum)->title);\n      const auto ft = title.find(search_string) != std::string::npos;\n      const auto fb = b.find(search_string) != std::string::npos;\n      fnd = ft || fb;\n    }\n  }\n  if (fnd) {\n    return {true, tmp_msgnum};\n  }\n  return { false, -1};\n}\n\nfind_message_result_t FindNextMessage(int msgno) {\n  bout.nl();\n  bout.print(\"|#7Find what? (CR=\\\"{})|#1: \", last_search_string);\n  auto search_string = bin.input_upper(20);\n  if (search_string.empty()) {\n    search_string = last_search_string;\n  }\n  bout.nl();\n  bout.outstr(\"|#1Backwards or Forwards? \");\n  const auto ch = onek(\"QBF\\r\");\n  if (ch == 'Q') {\n    return {false, -1};\n  }\n  bout.nl();\n  bout.outstr(\"|#1Searching -> |#2\");\n\n  // Store search direction and limit\n  const auto search_forward = ch != '-' && ch != 'B';\n  last_search_forward = search_forward;\n  last_search_string = search_string;\n\n  return FindNextMessageAgain(msgno);\n}\n\nfind_message_result_t FindNextMessageFS(common::FullScreenView& fs, int msgno) {\n  fs.ClearCommandLine();\n  fs.PutsCommandLine(fmt::format(\"|#7Find what? (CR=\\\"{}\\\")|#1: \", last_search_string));\n  auto search_string = fs.in().input_upper(20);\n  if (search_string.empty()) {\n    search_string = last_search_string;\n  }\n  fs.ClearCommandLine();\n  fs.PutsCommandLine(\"|#1Backwards or Forwards? \");\n  const auto ch = onek(\"QBF\\r\");\n  if (ch == 'Q') {\n    return {false, -1};\n  }\n  fs.ClearCommandLine();\n  fs.PutsCommandLine(\"|#1Searching -> |#2 \");\n\n  // Store search direction and limit\n  const auto search_forward = ch != '-' && ch != 'B';\n  last_search_forward = search_forward;\n  last_search_string = search_string;\n\n  return FindNextMessageAgain(msgno);\n}\n\n}\n"
  },
  {
    "path": "bbs/message_find.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MESSAGE_FIND_H\n#define INCLUDED_BBS_MESSAGE_FIND_H\n\nnamespace wwiv::common {\nclass FullScreenView;\n}\n\nenum class MsgScanOption;\n\nnamespace wwiv::bbs {\n\nstruct find_message_result_t {\n  // If found:   MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n  // otherwise:  MsgScanOption::SCAN_OPTION_READ_PROMPT;\n  bool found{false};\n  int msgnum{-1};\n};\n\n/**\n * Searches for the next message in the current area using last direction and\n * search string.\n */\nfind_message_result_t FindNextMessageAgain(int msgno);\n\n/**\n * Searches for the next message in the current area using prompting for the\n * direction and search string.\n */\nfind_message_result_t FindNextMessage(int msgno);\n\n/**\n * Searches for the next message in the current area using prompting for the\n * direction and search string using the FullScreenView's Command Area.\n */\nfind_message_result_t FindNextMessageFS(common::FullScreenView& fs, int msgno);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/misccmd.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/misccmd.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/email.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/net/networks.h\"\n\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nvoid kill_old_email() {\n  mailrec m{};\n  mailrec m1{};\n  User user;\n  filestatusrec fsr{};\n\n  bout.outstr(\"|#5List mail starting at most recent? \");\n  bool forward = bin.yesno();\n  auto pFileEmail(OpenEmailFile(false));\n  if (!pFileEmail->IsOpen()) {\n    bout.outstr(\"\\r\\nNo mail.\\r\\n\");\n    return;\n  }\n  auto max = static_cast<int>(pFileEmail->length() / sizeof(mailrec));\n  int cur = 0;\n  if (forward) {\n    cur = max - 1;\n  }\n\n  bool done = false;\n  do {\n    pFileEmail->Seek(cur * sizeof(mailrec), File::Whence::begin);\n    pFileEmail->Read(&m, sizeof(mailrec));\n    while ((m.fromsys != 0 || m.fromuser != a()->sess().user_num() || m.touser == 0) && cur < max && cur >= 0) {\n      if (forward) {\n        --cur;\n      } else {\n        ++cur;\n      }\n      if (cur < max && cur >= 0) {\n        pFileEmail->Seek(cur * sizeof(mailrec), File::Whence::begin);\n        pFileEmail->Read(&m, sizeof(mailrec));\n      }\n    }\n    if (m.fromsys != 0 || m.fromuser != a()->sess().user_num() || m.touser == 0 || cur >= max || cur < 0) {\n      done = true;\n    } else {\n      pFileEmail->Close();\n\n      bool done1 = false;\n      do {\n        bout.nl();\n        bout.outstr(\"|#1  To|#9: \");\n        bout.ansic(a()->GetMessageColor());\n\n        if (m.tosys == 0) {\n          a()->users()->readuser(&user, m.touser);\n          std::string tempName = a()->user()->name_and_number();\n          if ((m.anony & (anony_receiver | anony_receiver_pp | anony_receiver_da))\n              && ((a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_email_anony) == 0)) {\n            tempName = \">UNKNOWN<\";\n          }\n          bout.outstr(tempName);\n          bout.nl();\n        } else {\n          bout.print(\"#{} @{}\\r\\n\", m.tosys, m.tosys);\n        }\n        bout.printf(\"|#1Subj|#9: |#%d%60.60s\\r\\n\", a()->GetMessageColor(), m.title);\n        time_t lCurrentTime = time(nullptr);\n        int nDaysAgo = static_cast<int>((lCurrentTime - m.daten) / SECONDS_PER_DAY);\n        bout.outstr(\"|#1Sent|#9: \");\n        bout.ansic(a()->GetMessageColor());\n        bout.print(\"{} days ago\\r\\n\", nDaysAgo);\n        if (m.status & status_file) {\n          File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n          if (fileAttach.Open(File::modeBinary | File::modeReadOnly)) {\n            bool found = false;\n            auto l1 = fileAttach.Read(&fsr, sizeof(fsr));\n            while (l1 > 0 && !found) {\n              if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                bout.print(\"|#1Filename|#0.... |#2{} ({} bytes)|#0\\r\\n\", fsr.filename,\n                           fsr.numbytes);\n                found = true;\n              }\n              if (!found) {\n                l1 = fileAttach.Read(&fsr, sizeof(fsr));\n              }\n            }\n            if (!found) {\n              bout.outstr(\"|#1Filename|#0.... |#2Unknown or missing|#0\\r\\n\");\n            }\n            fileAttach.Close();\n          } else {\n            bout.outstr(\"|#1Filename|#0.... |#2Unknown or missing|#0\\r\\n\");\n          }\n        }\n        bout.nl();\n        bout.outstr(\"|#9(R)ead, (D)elete, (N)ext, (Q)uit : \");\n        switch (char ch = onek(\"QRDN\"); ch) {\n        case 'Q':\n          done1   = true;\n          done    = true;\n          break;\n        case 'N':\n          done1 = true;\n          if (forward) {\n            --cur;\n          } else {\n            ++cur;\n          }\n          if (cur >= max || cur < 0) {\n            done = true;\n          }\n          break;\n        case 'D': {\n          done1 = true;\n          auto delete_email_file = OpenEmailFile(true);\n          delete_email_file->Seek(cur * sizeof(mailrec), File::Whence::begin);\n          delete_email_file->Read(&m1, sizeof(mailrec));\n          if (memcmp(&m, &m1, sizeof(mailrec)) == 0) {\n            delmail(*delete_email_file, cur);\n            bool found = false;\n            if (m.status & status_file) {\n              File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n              if (fileAttach.Open(File::modeBinary | File::modeReadWrite)) {\n                auto l1 = fileAttach.Read(&fsr, sizeof(fsr));\n                while (l1 > 0 && !found) {\n                  if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                    found = true;\n                    fsr.id = 0;\n                    fileAttach.Seek(static_cast<long>(sizeof(filestatusrec)) * -1L, File::Whence::current);\n                    fileAttach.Write(&fsr, sizeof(filestatusrec));\n                    File::Remove(FilePath(a()->GetAttachmentDirectory(), fsr.filename));\n                  } else {\n                    l1 = fileAttach.Read(&fsr, sizeof(filestatusrec));\n                  }\n                }\n                fileAttach.Close();\n              }\n            }\n            bout.nl();\n            if (found) {\n              bout.outstr(\"Mail and file deleted.\\r\\n\\n\");\n              sysoplog(fmt::format(\"Deleted mail and attached file: {}\", fsr.filename));\n            } else {\n              bout.outstr(\"Mail deleted.\\r\\n\\n\");\n              const std::string username_num = a()->names()->UserName(m1.touser);\n              sysoplog(fmt::format(\"Deleted mail sent to {}\", username_num));\n            }\n          } else {\n            bout.outstr(\"Mail file changed; try again.\\r\\n\");\n          }\n          delete_email_file->Close();\n        }\n        break;\n        case 'R': {\n          bout.nl(2);\n          if (auto o = read_type2_message(&m.msg, m.anony & 0x0f, false, \"email\", 0, 0)) {\n            auto& msg = o.value();\n            msg.title = m.title;\n            msg.message_area = \"Personal E-Mail\";\n            auto next = false;\n            auto fake_msgno = -1;\n            display_type2_message(fake_msgno, msg, &next);\n          }\n        }\n        break;\n        }\n      } while (!a()->sess().hangup() && !done1);\n      pFileEmail = OpenEmailFile(false);\n      if (!pFileEmail->IsOpen()) {\n        break;\n      }\n    }\n  } while (!done && !a()->sess().hangup());\n  pFileEmail->Close();\n}\n\nvoid list_users(int mode) {\n  subboard_t s = {};\n  files::directory_t d{};\n  User user;\n  std::string find_text;\n\n  if (a()->current_user_sub().subnum == -1 && mode == LIST_USERS_MESSAGE_AREA) {\n    bout.outstr(\"\\r\\n|#6No Message Sub Available!\\r\\n\\n\");\n    return;\n  }\n  if (a()->current_user_dir().subnum == -1 && mode == LIST_USERS_FILE_AREA) {\n    bout.outstr(\"\\r\\n|#6 No Dirs Available.\\r\\n\\n\");\n    return;\n  }\n\n  auto snum = a()->sess().user_num();\n\n  bout.nl();\n  bout.outstr(\"|#5Sort by user number? \");\n  bool bSortByUserNumber = bin.yesno();\n  bout.nl();\n  bout.outstr(\"|#5Search for a name or city? \");\n  if (bin.yesno()) {\n    bout.nl();\n    bout.outstr(\"|#5Enter text to find: \");\n    find_text = bin.input_upper(10);\n  }\n\n  if (mode == LIST_USERS_MESSAGE_AREA) {\n    s = a()->subs().sub(a()->current_user_sub().subnum);\n  } else {\n    d = a()->dirs()[a()->current_user_dir().subnum];\n  }\n\n  bool abort  = false;\n  bool next   = false;\n  int p       = 0;\n  int num     = 0;\n  bool found  = true;\n  int count   = 0;\n  int ncnm    = 0;\n  int numscn  = 0;\n  int color   = 3;\n  a()->WriteCurrentUser();\n  write_qscn(a()->sess().user_num(), a()->sess().qsc, false);\n  a()->status_manager()->reload_status();\n\n  File userList(FilePath(a()->config()->datadir(), USER_LST));\n  int nNumUserRecords = a()->users()->num_user_records();\n\n  for (int i = 0; (i < nNumUserRecords) && !abort && !a()->sess().hangup(); i++) {\n    a()->sess().user_num(0);\n    if (ncnm > 5) {\n      count++;\n      bout.ansic(color);\n      bout.outstr(\".\");\n      if (count == NUM_DOTS) {\n        bout.outstr(\"\\r\", &abort, &next);\n        bout.outstr(\"|#2Searching \", &abort, &next);\n        color++;\n        count = 0;\n        if (color == 4) {\n          color++;\n        }\n        if (color == 7) {\n          color = 0;\n        }\n      }\n    }\n    if (p == 0 && found) {\n      bout.cls();\n      auto title_line = StrCat(a()->config()->system_name(), \" User Listing\");\n      if (okansi()) {\n        bout.litebar(title_line);\n      } else {\n        int i1;\n        for (i1 = 0; i1 < 78; i1++) {\n          bout.outchr(45);\n        }\n        bout.nl();\n        bout.print(\"|#5{}\", title_line);\n        bout.nl();\n        for (i1 = 0; i1 < 78; i1++) {\n          bout.outchr(45);\n        }\n        bout.nl();\n      }\n      bout.ansic(FRAME_COLOR);\n      bout.bpla(\"\\xD5\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xD1\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xD1\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xD1\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xD1\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xB8\",\n          &abort);\n      found = false;\n    }\n\n    int user_number = (bSortByUserNumber) ? i + 1 : a()->names()->names_vector()[i].number;\n    a()->users()->readuser(&user, user_number);\n    read_qscn(user_number, a()->sess().qsc, false);\n    changedsl();\n    bool in_qscan = (a()->sess().qsc_q[a()->current_user_sub().subnum / 32] &\n                     (1L << (a()->current_user_sub().subnum % 32)))\n                        ? true\n                        : false;\n    bool ok = true;\n    if (user.deleted()) {\n      ok = false;\n    }\n    if (mode == LIST_USERS_MESSAGE_AREA && !wwiv::bbs::check_acs(s.read_acs)) {\n        ok = false;\n    }\n    if (mode == LIST_USERS_FILE_AREA && !wwiv::bbs::check_acs(d.acs)) {\n      ok = false;\n    }\n    if (!find_text.empty()) {\n      char s5[ 41 ];\n      to_char_array(s5, user.city());\n      if (!strstr(user.GetName(), find_text.c_str()) &&\n          !strstr(strupr(s5), find_text.c_str()) &&\n          !strstr(user.state().c_str(), find_text.c_str())) {\n        ok = false;\n      }\n    }\n    if (ok) {\n      found = true;\n      bout.clreol();\n      if (user.last_bps() > 32767 || user.last_bps() < 300) {\n        user.last_bps(33600);\n      }\n      std::string city = \"Unknown\";\n      if (!user.city().empty()) {\n        city = fmt::format(\"{:.18}, {}\", user.city(), user.state());\n      }\n      auto properName = properize(user.name());\n      const auto line = fmt::sprintf(\"|#%d\\xB3|#9%5d |#%d\\xB3|#6%c|#1%-20.20s|#%d\\xB3|#2 \"\n                                     \"%-24.24s|#%d\\xB3 |#1%-9s |#%d\\xB3  |#3%-5u  |#%d\\xB3\",\n                                     FRAME_COLOR, user_number, FRAME_COLOR, in_qscan ? '*' : ' ',\n                                     properName, FRAME_COLOR, city, FRAME_COLOR, user.laston(),\n                                     FRAME_COLOR, user.last_bps(), FRAME_COLOR);\n      bout.bpla(line, &abort);\n      num++;\n      if (in_qscan) {\n        numscn++;\n      }\n      ++p;\n      if (p == static_cast<int>(a()->user()->screen_lines()) - 6) {\n        //bout.backline();\n        bout.clreol();\n        bout.ansic(FRAME_COLOR);\n        bout.bpla(\"\\xD4\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xBE\",\n            &abort);\n        bout.outstr(\"|#1[Enter] to continue or Q=Quit : \");\n        switch (auto ch = onek(\"Q\\r \"); ch) {\n        case 'Q':\n          abort = true;\n          i = a()->status_manager()->user_count();\n          break;\n        case SPACE:\n        case RETURN:\n          p = 0;\n          break;\n        }\n      }\n    } else {\n      ncnm++;\n    }\n  }\n  //bout.backline();\n  bout.clreol();\n  bout.ansic(FRAME_COLOR);\n  bout.bpla(\"\\xD4\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCF\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xBE\",\n      &abort);\n  if (!abort) {\n    bout.nl(2);\n    bout.print(\"|#1{} user(s) have access and {} user(s) scan this subboard.\",  num , numscn);\n    bout.nl();\n    bout.pausescr();\n  }\n  a()->ReadCurrentUser(snum);\n  read_qscn(snum, a()->sess().qsc, false);\n  a()->sess().user_num(snum);\n  changedsl();\n}\n\n\nvoid time_bank() {\n  char s[81], bc[81];\n\n  bout.nl();\n  if (!wwiv::bbs::check_acs(\"user.validated == true\")) {\n    bout.outstr(\"|#6You must be validated to access the timebank.\\r\\n\");\n    return;\n  }\n  if (a()->user()->banktime_minutes() > a()->config()->sl(a()->sess().effective_sl()).time_per_logon) {\n    a()->user()->banktime_minutes(a()->config()->sl(a()->sess().effective_sl()).time_per_logon);\n  }\n\n  if (okansi()) {\n    strcpy(bc, \"ڿĳŴ\");\n  } else {\n    strcpy(bc, \"++++-|+++++\");\n  }\n\n  bool done = false;\n  do {\n    bout.cls();\n    bout.outstr(\"|#5WWIV TimeBank\\r\\n\");\n    bout.nl();\n    bout.outstr(\"|#2D|#9)eposit Time\\r\\n\");\n    bout.outstr(\"|#2W|#9)ithdraw Time\\r\\n\");\n    bout.outstr(\"|#2Q|#9)uit\\r\\n\");\n    bout.nl();\n    bout.print(\"|#9Balance:   |#2{}|#9 minutes\\r\\n\", a()->user()->banktime_minutes());\n    bout.print(\"|#9Time Left: |#2{}|#9 minutes\\r\\n\", static_cast<int>(nsl() / 60));\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) [|#2Time Bank|#9] Enter Command: |#2\");\n    bout.mpl(1);\n    switch (char c = onek(\"QDW\"); c) {\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#1Deposit how many minutes: \");\n      bin.input(s, 3, true);\n      auto i = to_number<int>(s);\n      if (i > 0) {\n        long nsln = nsl();\n        if ((i + a()->user()->banktime_minutes()) >\n            a()->config()->sl(a()->sess().effective_sl()).time_per_logon) {\n          i = a()->config()->sl(a()->sess().effective_sl()).time_per_logon -\n              a()->user()->banktime_minutes();\n        }\n        if (i > (nsln / SECONDS_PER_MINUTE)) {\n          i = static_cast<int>(nsln / SECONDS_PER_MINUTE);\n        }\n        a()->user()->add_banktime_minutes(i);\n        a()->user()->subtract_extratime(std::chrono::minutes(i));\n        a()->tleft(false);\n      }\n    } break;\n    case 'W': {\n      bout.nl();\n      if (a()->user()->banktime_minutes() == 0) {\n        break;\n      }\n      bout.outstr(\"|#1Withdraw How Many Minutes: \");\n      bin.input(s, 3, true);\n      auto i = to_number<int>(s);\n      if (i > 0) {\n        if (i > a()->user()->banktime_minutes()) {\n          i = a()->user()->banktime_minutes();\n        }\n        a()->user()->subtract_banktime_minutes(i);\n        a()->user()->add_extratime(std::chrono::minutes(i));\n        a()->tleft(false);\n      }\n    } break;\n    case 'Q':\n      done = true;\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\nint getnetnum(const std::string& network_name) {\n  for (auto i = 0; i < wwiv::stl::size_int(a()->nets()); i++) {\n    if (iequals(a()->nets()[i].name, network_name)) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nint getnetnum_by_type(network_type_t type) {\n  const auto& n = a()->nets().networks();\n  for (auto i = 0; i < wwiv::stl::ssize(a()->nets()); i++) {\n    if (n[i].type == type) {\n      return i;\n    }\n  }\n  return -1;\n}\n"
  },
  {
    "path": "bbs/misccmd.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MISCCMD_H\n#define INCLUDED_BBS_MISCCMD_H\n\n#include \"sdk/net/net.h\"\n\n#include <string>\n\nvoid kill_old_email();\nvoid list_users(int mode);\nvoid time_bank();\nint getnetnum(const std::string& network_name);\nint getnetnum_by_type(wwiv::sdk::net::network_type_t type);\n\n#endif\n"
  },
  {
    "path": "bbs/mmkey.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/mmkey.h\"\n\n#include \"bbsovl3.h\"\n#include \"bbs/bbs.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include <set>\n#include <string>\n\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nstatic bool mmkey_use_bgetch_event = true;\n\nstatic char mmkey_getch() {\n  if (!mmkey_use_bgetch_event) {\n    return bin.getkey(false);\n  }\n  const auto bge = bin.bgetch_event(wwiv::common::Input::numlock_status_t::NUMBERS);\n  if (do_sysop_command(bge)) {\n    // Handle local sysop commands.\n    return 0;\n  }\n  if (bge == COMMAND_DELETE || bge == COMMAND_LEFT) {\n    return BACKSPACE;\n  }\n  if (bge >= 255) {\n    return 0;\n  }\n  return static_cast<char>(bge & 0xff);\n}\n\nstatic int max_sub_key(std::vector<usersubrec>& container) {\n  auto key = 0;\n  for (const auto& r : container) {\n    const auto current_key = to_number<int>(r.keys);\n    if (current_key == 0) {\n      return key;\n    }\n    key = current_key;\n  }\n  return key;\n}\n\nstd::string mmkey(std::set<char>& x, std::set<char>& xx, bool bListOption) {\n  unsigned char ch;\n  std::string cmd1;\n\n  do {\n    do {\n      ch = mmkey_getch();\n      if (bListOption && (ch == RETURN || ch == SPACE)) {\n        ch = upcase(ch);\n        return std::string(1, ch);\n      }\n    } while ((ch <= ' ' || ch > 126) && !a()->sess().hangup());\n    ch = upcase(ch);\n    bout.outchr(ch);\n    if (ch == RETURN) {\n      cmd1.clear();\n    } else {\n      cmd1 = ch;\n    }\n    auto p = 0;\n    if (contains(xx, ch)) {\n      p = 2;\n    } else if (contains(x, ch)) {\n      p = 1;\n    } else {\n      bout.nl();\n      bout.newline = true;\n      return cmd1;\n    }\n\n    auto cp = 1;\n    do {\n      do {\n        ch = mmkey_getch();\n      } while (((ch < ' ' && ch != RETURN && ch != BACKSPACE) || ch > 126) && !a()->sess().hangup());\n      ch = upcase(ch);\n      if (ch == RETURN) {\n        bout.nl();\n        bout.newline = true;\n        return cmd1;\n      }\n      if (ch == BACKSPACE) {\n        bout.bs();\n        cmd1.pop_back();\n        cp--;\n      } else {\n        cmd1.push_back(ch);\n        bout.outchr(ch);\n        cp++;\n        if (ch == '/' && cmd1[0] == '/') {\n          bout.newline = true;\n          return bin.input_upper(\"\", 50, false);\n        }\n        if (cp == p + 1) {\n          bout.nl();\n          bout.newline = true;\n          return cmd1;\n        }\n      }\n    } while (cp > 0);\n  } while (!a()->sess().hangup());\n  return{};\n}\n\nstd::string mmkey(std::set<char>& x) {\n  std::set<char> xx;\n  return mmkey(x, xx, false);\n}\n\n\nstd::string mmkey(MMKeyAreaType dl, bool bListOption) {\n  std::set<char> x = {'/'};\n  std::set<char> xx{};\n  switch (dl) {\n  case MMKeyAreaType::subs: {\n    const auto max_key = max_sub_key(a()->usub);\n    for (char i = 1; i <= max_key / 10; i++) {\n      x.insert(i + '0');\n    }\n    for (char i = 1; i <= max_key / 100; i++) {\n      xx.insert(i + '0');\n    }\n  } break;\n  case MMKeyAreaType::dirs: {\n    const auto max_key = max_sub_key(a()->udir);\n    for (char i = 1; i <= max_key / 10; i++) {\n      x.insert(i + '0');\n    }\n    for (char i = 1; i <= max_key / 100; i++) {\n      xx.insert(i + '0');\n    }\n  } break;\n  default: {\n    DLOG(FATAL) << \"invalid mmkey dl: \" << static_cast<int>(dl);\n  }\n  }\n\n  return mmkey(x, xx, bListOption);\n}\n"
  },
  {
    "path": "bbs/mmkey.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MMKEY_H\n#define INCLUDED_BBS_MMKEY_H\n\n#include <string>\n#include <set>\n\nenum class MMKeyAreaType {\n  subs,\n  dirs\n};\n\nstd::string mmkey(std::set<char>& x, std::set<char>& xx, bool bListOption);\nstd::string mmkey(std::set<char>& x);\nstd::string mmkey(MMKeyAreaType dl, bool bListOption = false);\n\n\n#endif\n"
  },
  {
    "path": "bbs/msgbase1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/msgbase1.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/inmsg.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/msgscan.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/input.h\"\n#include \"common/message_editor_data.h\"\n#include \"core/datetime.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/msgapi/parsed_message.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/subscribers.h\"\n#include <memory>\n#include <string>\n\nusing std::chrono::duration;\nusing std::chrono::duration_cast;\nusing std::chrono::minutes;\nusing std::chrono::seconds;\nusing std::chrono::system_clock;\nusing wwiv::sdk::fido::FidoAddress;\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid send_net_post(postrec* pPostRecord, const subboard_t& sub) {\n  auto o = readfile(&(pPostRecord->msg), sub.filename);\n  if (!o) {\n    return;\n  }\n\n  int netnum;\n  const auto orig_netnum = a()->net_num();\n  if (pPostRecord->status & status_post_new_net) {\n    netnum = pPostRecord->network.network_msg.net_number;\n  } else if (!sub.nets.empty()) {\n    netnum = sub.nets[0].net_num;\n  } else {\n    netnum = a()->net_num();\n  }\n\n  const auto nn1 = netnum;\n  if (pPostRecord->ownersys == 0) {\n    netnum = -1;\n  }\n\n  const auto& text = o.value();\n  net_header_rec nhorig = {};\n  nhorig.tosys = 0;\n  nhorig.touser = 0;\n  nhorig.fromsys = pPostRecord->ownersys;\n  nhorig.fromuser = pPostRecord->owneruser;\n  nhorig.list_len = 0;\n  nhorig.daten = pPostRecord->daten;\n  nhorig.length = size_int(text) + 1 + strlen(pPostRecord->title);\n  nhorig.method = 0;\n\n  auto message_length = text.size();\n  if (nhorig.length > 32755) {\n    bout.printf(\"Message truncated by %lu bytes for the network.\", nhorig.length - 32755L);\n    nhorig.length = 32755;\n    message_length = nhorig.length - strlen(pPostRecord->title) - 1;\n  }\n  std::unique_ptr<char[]> b1(new char[nhorig.length + 100]);\n  strcpy(b1.get(), pPostRecord->title);\n  memmove(&(b1[strlen(pPostRecord->title) + 1]), text.c_str(), message_length);\n\n  for (const auto& xnp : sub.nets) {\n    if (xnp.net_num == netnum && xnp.host) {\n      continue;\n    }\n    set_net_num(xnp.net_num);\n    const auto& net = a()->nets()[xnp.net_num];\n    auto nh = nhorig;\n    std::vector<uint16_t> list;\n    nh.minor_type = 0;\n    if (!nh.fromsys) {\n      nh.fromsys = net.sysnum;\n    }\n    nh.main_type = main_type_new_post;\n    if (xnp.host) {\n      nh.tosys = xnp.host;\n    } else {\n      auto subscribers = ReadSubcriberFile(FilePath(net.dir, StrCat(\"n\", xnp.stype, \".net\")));\n      for (const auto& s : subscribers) {\n        if ((a()->net_num() != netnum || nh.fromsys != s) && s != net.sysnum) {\n          if (valid_system(s)) {\n            nh.list_len++;\n            list.push_back(s);\n          }\n        }\n      }\n    }\n    if (nn1 == a()->net_num()) {\n      const std::string body(b1.get(), nh.length);\n      send_net(&nh, list, body, xnp.stype);\n    } else {\n      gate_msg(&nh, b1.get(), xnp.net_num, xnp.stype, list, netnum);\n    }\n  }\n\n  set_net_num(orig_netnum);\n}\n\nstatic std::string net_type_to_string(const network_type_t& t) {\n  switch (t) {\n  case network_type_t::wwivnet:\n    return \"WWIV\";\n  case network_type_t::ftn:\n    return \"FTN\";\n  case network_type_t::internet:\n    return \"Internet\";\n  case network_type_t::news:\n    return \"Newsgroup\";\n  }\n  return \"Unknown\";\n}\n\nvoid post(const PostData& post_data) {\n  if (!iscan(a()->current_user_sub_num())) {\n    bout.outstr(\"\\r\\n|#6A file required is in use by another instance. Try again later.\\r\\n\");\n    return;\n  }\n  if (a()->sess().GetCurrentReadMessageArea() < 0) {\n    bout.outstr(\"\\r\\nNo subs available.\\r\\n\\n\");\n    return;\n  }\n\n  if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n    bout.outstr(\"\\r\\nSorry, not enough disk space left.\\r\\n\\n\");\n    return;\n  }\n  if (a()->user()->restrict_post() ||\n      a()->user()->posts_today() >= a()->config()->sl(a()->sess().effective_sl()).posts) {\n    bout.outstr(\"\\r\\nToo many messages posted today.\\r\\n\\n\");\n    return;\n  }\n  if (!check_acs(a()->current_sub().post_acs)) {\n    bout.outstr(\"\\r\\nYou can't post here.\\r\\n\\n\");\n    return;\n  }\n\n  MessageEditorData data(a()->user()->name_and_number());\n  messagerec m{};\n  m.storage_type = static_cast<unsigned char>(a()->current_sub().storage_type);\n  data.anonymous_flag = a()->subs().sub(a()->sess().GetCurrentReadMessageArea()).anony & 0x0f;\n  if (data.anonymous_flag == 0 && a()->config()->sl(a()->sess().effective_sl()).ability & ability_post_anony) {\n    data.anonymous_flag = anony_enable_anony;\n  }\n  if (data.anonymous_flag == anony_enable_anony && a()->user()->restrict_anony()) {\n    data.anonymous_flag = 0;\n  }\n  if (!a()->current_sub().nets.empty()) {\n    data.anonymous_flag &= anony_real_name;\n    if (a()->user()->restrict_net()) {\n      bout.outstr(\"\\r\\nYou can't post on networked sub-boards.\\r\\n\\n\");\n      return;\n    }\n    if (a()->current_net().sysnum != 0) {\n      bout.outstr(\"\\r\\n|#9This post will go out on: \");\n      for (auto i = 0; i < size_int(a()->current_sub().nets); i++) {\n        if (i) {\n          bout.outstr(\"|#9, \");\n        }\n        const auto& n = a()->nets()[a()->current_sub().nets[i].net_num];\n        bout.print(\"|#2{}|#1({})\", n.name, net_type_to_string(n.type));\n      }\n      bout.outstr(\".\\r\\n\\n\");\n    }\n  }\n  const auto start_time = DateTime::now().to_system_clock();\n\n  write_inst(INST_LOC_POST, a()->sess().GetCurrentReadMessageArea(), INST_FLAGS_NONE);\n\n  data.fsed_flags = FsedFlags::FSED;\n  data.msged_flags =\n      (a()->current_sub().anony & anony_no_tag) ? MSGED_FLAG_NO_TAGLINE : MSGED_FLAG_NONE;\n  data.aux = a()->current_sub().filename;\n  data.sub_name = a()->subs().sub(a()->current_user_sub().subnum).name;\n  data.to_name = post_data.reply_to.name;\n  data.need_title = true;\n\n  if (!inmsg(data)) {\n    m.stored_as = 0xffffffff;\n    return;\n  }\n\n  // Additions for MSGID reply.\n  if (a()->current_net().type == network_type_t::ftn && !post_data.reply_to.text.empty()) {\n    // We're handling a reply.\n    if (const auto msgid = FtnMessageDupe::GetMessageIDFromWWIVText(post_data.reply_to.text);\n        !msgid.empty()) {\n      const auto address = a()->current_net().fido.fido_address;\n      try {\n        FidoAddress addr(address);\n        add_ftn_msgid(*a()->config(), addr, msgid, &data);\n      } catch (wwiv::sdk::fido::bad_fidonet_address& e) {\n        LOG(ERROR) << \"Exception parsing address: \" << address << \"; reason: \" << e.what();\n      }\n    }\n  }\n  savefile(data.text, &m, data.aux);\n\n  postrec p{};\n  memset(&p, 0, sizeof(postrec));\n  to_char_array(p.title, data.title);\n  p.anony = static_cast<unsigned char>(data.anonymous_flag);\n  p.msg = m;\n  p.ownersys = 0;\n  p.owneruser = static_cast<uint16_t>(a()->sess().user_num());\n  a()->status_manager()->Run([&](Status& s) { p.qscan = s.next_qscanptr(); });\n  p.daten = daten_t_now();\n  p.status = 0;\n  if (a()->user()->restrict_validate()) {\n    p.status |= status_unvalidated;\n  }\n\n  open_sub(true);\n\n  if (!a()->current_sub().nets.empty() && a()->current_sub().anony & anony_val_net &&\n      (!lcs() || !post_data.reply_to.title.empty())) {\n    p.status |= status_pending_net;\n    auto dm = true;\n    for (auto i = a()->GetNumMessagesInCurrentMessageArea();\n         i >= 1 && i > a()->GetNumMessagesInCurrentMessageArea() - 28; i--) {\n      if (get_post(i)->status & status_pending_net) {\n        dm = false;\n        break;\n      }\n    }\n    if (dm) {\n      // Only SSM if this is the one and only pending networking message.\n      ssm(1) << \"Unvalidated net posts on \" << a()->current_sub().name << \".\";\n    }\n  }\n  if (a()->GetNumMessagesInCurrentMessageArea() >= a()->current_sub().maxmsgs) {\n    int i = 1;\n    int dm = 0;\n    while (i <= a()->GetNumMessagesInCurrentMessageArea()) {\n      auto* pp = get_post(i);\n      if (!pp) {\n        break;\n      }\n      if ((pp->status & status_no_delete) == 0 ||\n          pp->msg.storage_type != a()->current_sub().storage_type) {\n        dm = i;\n        break;\n      }\n      ++i;\n    }\n    if (dm == 0) {\n      dm = 1;\n    }\n    delete_message(dm);\n  }\n  add_post(&p);\n\n  a()->user()->messages_posted(a()->user()->messages_posted() + 1);\n  a()->user()->posts_today(a()->user()->posts_today() + 1);\n  a()->status_manager()->Run([](Status& s) {\n    s.increment_msgs_today();\n    s.IncrementNumLocalPosts();\n  });\n\n  if (a()->HasConfigFlag(OP_FLAGS_POSTTIME_COMPENSATE)) {\n    const auto end_time = DateTime::now().to_system_clock();\n    auto diff_time = end_time - start_time;\n    const auto allowed_time_per_login = a()->config()->sl(a()->sess().effective_sl()).time_per_logon;\n    if (duration_cast<minutes>(diff_time).count() > allowed_time_per_login) {\n      diff_time = minutes(allowed_time_per_login);\n    }\n    a()->user()->add_extratime(diff_time);\n  }\n  close_sub();\n\n  a()->UpdateTopScreen();\n  sysoplog(fmt::format(\"+ '{}' posted on {}\", p.title, a()->current_sub().name));\n  bout.print(\"Posted on {}\\r\\n\", a()->current_sub().name);\n  if (!a()->current_sub().nets.empty()) {\n    a()->user()->posts_net(a()->user()->posts_net() + 1);\n    if (!(p.status & status_pending_net)) {\n      send_net_post(&p, a()->current_sub());\n    }\n  }\n}\n\nvoid add_ftn_msgid(const wwiv::sdk::Config& config, const FidoAddress& addr, const std::string& msgid,\n                   MessageEditorData* data) {\n  FtnMessageDupe dupe(config);\n  if (dupe.IsInitialized()) {\n    const auto new_msgid = dupe.CreateMessageID(addr);\n    WWIVParsedMessageText pmt(data->text);\n    // TODO(rushfan): Should we keep removing them while they exist in case\n    // there are more than 1??\n    // Remove the existing MSGID lines.\n    pmt.remove_control_line(\"MSGID\");\n    pmt.remove_control_line(\"REPLY\");\n\n    pmt.add_control_line(StrCat(\"MSGID: \", new_msgid));\n    pmt.add_control_line_after(\"MSGID\", StrCat(\"REPLY: \", msgid));\n    data->text = pmt.to_string();\n  }\n}\n\nstd::string grab_user_name(messagerec* m, const std::string& file_name, int network_number) {\n  a()->net_email_name.clear();\n  auto o = readfile(m, file_name);\n  if (!o) {\n    return {};\n  }\n  auto text = o.value();\n  const auto cr = text.find_first_of('\\r');\n  if (cr == std::string::npos) {\n    return {};\n  }\n  text.resize(cr);\n  // Don't assume that we have a valid network at the network_number position.\n  if (network_number < size_int(a()->nets()) &&\n      a()->nets()[network_number].type == network_type_t::ftn) {\n    // 1st line of message is from.\n    a()->net_email_name = text;\n    return text;\n  }\n  const auto* ss2 = text.c_str();\n  if (text[0] == '`' && text[1] == '`') {\n    for (const char* ss1 = ss2 + 2; *ss1; ss1++) {\n      if (ss1[0] == '`' && ss1[1] == '`') {\n        ss2 = ss1 + 2;\n      }\n    }\n    while (*ss2 == ' ') {\n      ++ss2;\n    }\n    a()->net_email_name = ss2;\n    return ss2;\n  }\n  return {};\n}\n\nvoid qscan(uint16_t start_subnum, bool& nextsub) {\n  const int sub_number = a()->usub[start_subnum].subnum;\n\n  if (a()->sess().hangup() || sub_number < 0) {\n    return;\n  }\n  bout.nl();\n  auto memory_last_read = a()->sess().qsc_p[sub_number];\n\n  iscan1(sub_number);\n  auto num_lines = 3;\n  if (const auto on_disk_last_post = WWIVReadLastRead(sub_number); !on_disk_last_post || on_disk_last_post > memory_last_read) {\n    const auto old_subnum = a()->current_user_sub_num();\n    a()->set_current_user_sub_num(start_subnum);\n\n    if (!iscan(a()->current_user_sub_num())) {\n      bout.outstr(\"\\r\\n|#6A file required is in use by another instance. Try again later.\\r\\n\");\n      return;\n    }\n    memory_last_read = a()->sess().qsc_p[sub_number];\n\n    bout.printf(\"\\r\\n\\n|#1< Q-scan %s %s - %lu msgs >\\r\\n\", a()->current_sub().name,\n                 a()->current_user_sub().keys, a()->GetNumMessagesInCurrentMessageArea());\n\n    int i;\n    for (i = a()->GetNumMessagesInCurrentMessageArea();\n         (i > 1) && (get_post(i - 1)->qscan > memory_last_read); i--)\n      ;\n\n    if (a()->GetNumMessagesInCurrentMessageArea() > 0 &&\n        i <= a()->GetNumMessagesInCurrentMessageArea() &&\n        get_post(i)->qscan > a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()]) {\n      scan(i, MsgScanOption::SCAN_OPTION_READ_MESSAGE, nextsub, false);\n    } else {\n      const auto status = a()->status_manager()->get_status();\n      a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()] = status->qscanptr() - 1;\n    }\n\n    a()->set_current_user_sub_num(old_subnum);\n    bout.print(\"|#1< {} Q-Scan Done >\", a()->current_sub().name);\n    num_lines = 4;\n  } else if (!a()->sess().forcescansub()) {\n    // No need to display this if we're in a forced nscan for this sub.\n    bout.print(\"|#1< Nothing new on {}\", a()->subs().sub(sub_number).name);\n  }\n  bout.clreol();\n  bout.nl();\n  bout.clear_lines_listed();\n  bout.clreol();\n  bout.move_up_if_newline(num_lines);\n  bout.nl();\n}\n\nvoid nscan(uint16_t start_subnum) {\n  bool nextsub = true;\n\n  bout.outstr(\"\\r\\n|#3-=< Q-Scan All >=-\\r\\n\");\n  for (auto i = start_subnum; i < a()->usub.size() && nextsub && !a()->sess().hangup();\n       i++) {\n    if (a()->sess().qsc_q[a()->usub[i].subnum / 32] & (1L << (a()->usub[i].subnum % 32))) {\n      qscan(i, nextsub);\n    }\n    bool abort = false;\n    bin.checka(&abort);\n    if (abort) {\n      nextsub = false;\n    }\n  }\n  bout.nl();\n  bout.clreol();\n  bout.outstr(\"|#3-=< Global Q-Scan Done >=-\\r\\n\\n\");\n  if (nextsub && a()->user()->newscan_files() && !a()->sess().scanned_files()) {\n    bout.clear_lines_listed();\n    tmp_disable_conf(true);\n    nscanall();\n    tmp_disable_conf(false);\n  }\n}\n\nvoid ScanMessageTitles() {\n  if (!iscan(a()->current_user_sub_num())) {\n    bout.outstr(\"\\r\\n|#7A file required is in use by another instance. Try again later.\\r\\n\");\n    return;\n  }\n  bout.nl();\n  if (a()->sess().GetCurrentReadMessageArea() < 0) {\n    bout.outstr(\"No subs available.\\r\\n\");\n    return;\n  }\n  bout.printf(\"|#2%d |#9messages in area |#2%s\\r\\n\",\n                       a()->GetNumMessagesInCurrentMessageArea(), a()->current_sub().name);\n  if (a()->GetNumMessagesInCurrentMessageArea() == 0) {\n    return;\n  }\n  bout.print(\"|#9Start listing at (|#21|#9-|#2{}|#9): \", a()->GetNumMessagesInCurrentMessageArea());\n  const auto r =\n      bin.input_number_hotkey(1, {'Q', 'S'}, 1, a()->GetNumMessagesInCurrentMessageArea(), false);\n  if (auto nextsub = false; r.key == 'S') {\n    scan(0, MsgScanOption::SCAN_OPTION_READ_PROMPT, nextsub, true);\n  } else if (r.key != 'Q') {\n    scan(r.num - 1, MsgScanOption::SCAN_OPTION_LIST_TITLES, nextsub, true);\n  }\n}\n\nvoid remove_post() {\n  if (!iscan(a()->current_user_sub_num())) {\n    bout.outstr(\"\\r\\n|#6A file required is in use by another instance. Try again later.\\r\\n\\n\");\n    return;\n  }\n  if (a()->sess().GetCurrentReadMessageArea() < 0) {\n    bout.outstr(\"\\r\\nNo subs available.\\r\\n\\n\");\n    return;\n  }\n  bool any = false, abort = false;\n  bout.print(\"\\r\\n\\nPosts by you on {}\\r\\n\\r\\n\", a()->current_sub().name);\n  for (int j = 1; j <= a()->GetNumMessagesInCurrentMessageArea() && !abort; j++) {\n    if (get_post(j)->ownersys == 0 && get_post(j)->owneruser == a()->sess().user_num()) {\n      any = true;\n      bout.bpla(fmt::sprintf(\"%u: %60.60s\", j, get_post(j)->title), &abort);\n    }\n  }\n  if (!any) {\n    bout.outstr(\"None.\\r\\n\");\n    if (!cs()) {\n      return;\n    }\n  }\n  bout.outstr(\"\\r\\n|#2Remove which? \");\n  const auto postnum = bin.input_number(0, 0, a()->GetNumMessagesInCurrentMessageArea(), false);\n  OpenSub opened_sub(true);\n  if (postnum > 0 && postnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n    if (get_post(postnum)->ownersys == 0 && get_post(postnum)->owneruser == a()->sess().user_num() ||\n        lcs()) {\n      if (get_post(postnum)->owneruser == a()->sess().user_num() && get_post(postnum)->ownersys == 0) {\n        User tu;\n        a()->users()->readuser(&tu, get_post(postnum)->owneruser);\n        if (!tu.deleted()) {\n          if (date_to_daten(tu.firston()) < get_post(postnum)->daten) {\n            if (tu.messages_posted()) {\n              tu.messages_posted(tu.messages_posted() - 1);\n              a()->users()->writeuser(&tu, get_post(postnum)->owneruser);\n            }\n          }\n        }\n      }\n      sysoplog(fmt::format(\"- '{}' removed from {}\", get_post(postnum)->title, a()->current_sub().name));\n      delete_message(postnum);\n      bout.outstr(\"\\r\\nMessage removed.\\r\\n\\n\");\n    }\n  }\n}\n"
  },
  {
    "path": "bbs/msgbase1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MSGBASE1_H\n#define INCLUDED_BBS_MSGBASE1_H\n\n#include \"common/message_editor_data.h\"\n#include \"sdk/subxtr.h\"\n#include <string>\n#include <utility>\n\nnamespace wwiv {\nnamespace sdk {\nclass Config;\n}\n}\n\nstruct messagerec;\nstruct postrec;\n\nnamespace wwiv::sdk::fido {\n  class FidoAddress;\n}\n\nclass PostReplyToData {\npublic:\n  // Original text this next post will reply to\n  std::string text;\n  // Original name of the sender we are replying to\n  std::string name;\n  // Original title this next post will reply to\n  std::string title;\n};\n\nclass PostData {\npublic:\n  explicit PostData(PostReplyToData i) : reply_to(std::move(i)) {}\n  PostData() : PostData(PostReplyToData()) {}\n  PostReplyToData reply_to;\n};\n\nvoid send_net_post(postrec* p, const wwiv::sdk::subboard_t& sub);\nvoid post(const PostData& data);\nvoid add_ftn_msgid(const wwiv::sdk::Config& config, const wwiv::sdk::fido::FidoAddress& addr, const std::string& msgid,\n                   wwiv::common::MessageEditorData* data);\nstd::string grab_user_name(messagerec* m, const std::string& file_name, int network_number);\nvoid qscan(uint16_t start_subnum, bool& next_sub);\nvoid nscan(uint16_t start_subnum = 0);\nvoid ScanMessageTitles();\nvoid remove_post();\n\n#endif\n"
  },
  {
    "path": "bbs/msgbase1_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/msgbase1.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"common/message_editor_data.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/fido/fido_address.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::common;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::stl;\n\nTEST(Msgbase1Test, Smoke) {}\n\nTEST(Msgbase1Test, AddFtnMsgid_Smoke) {\n  BbsHelper helper;\n  helper.SetUp();\n\n  MessageEditorData data(\"Random Username\");\n  const std::string msgid = \"1:2/3 deadbeef\";\n  FidoAddress addr(\"1:2/3\");\n  data.text = \"Hello World\\r\\n\\004\"\n              \"0MSGID 1:2/3 deadbeef\\r\\nHello World2\\r\\n\";\n  add_ftn_msgid(*a()->config(), addr, msgid, &data);\n  \n  // One one gone\n  ASSERT_EQ(std::string::npos, data.text.find(\"MSGID 1:2/3 deadbeef\"));\n  // Reply line added right.\n  ASSERT_NE(std::string::npos, data.text.find(\"REPLY: 1:2/3 deadbeef\\r\\n\"));\n}\n"
  },
  {
    "path": "bbs/msgscan.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/msgscan.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/email.h\"\n#include \"bbs/extract.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/message_find.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/showfiles.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/sublist.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/full_screen.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"common/workspace.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/msgapi/message.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n\n#include <algorithm>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic std::string GetScanReadPrompts(int msg_num) {\n  if (a()->sess().forcescansub()) {\n    if (msg_num < a()->GetNumMessagesInCurrentMessageArea()) {\n      return \"|#1Press |#7[|#2ENTER|#7]|#1 to go to the next message...\";\n    }\n    return \"|#1Press |#7[|#2ENTER|#7]|#1 to continue...\";\n  }\n\n  std::string local_network_name = \"Local\";\n  if (!a()->current_sub().nets.empty()) {\n    local_network_name = a()->network_name();\n  } else {\n    set_net_num(0);\n  }\n  const auto sub_name_prompt = fmt::sprintf(\n      \"|#7[|#1%s|#7] [|#2%s|#7]\", local_network_name, a()->current_sub().name);\n  return fmt::sprintf(\"%s |#7(|#1Read |#2%d |#1of |#2%d|#1|#7) : \", sub_name_prompt,\n                      msg_num, a()->GetNumMessagesInCurrentMessageArea());\n}\n\nstatic void HandleScanReadAutoReply(int& msgnum, const char* user_input,\n                                    MsgScanOption& scan_option) {\n  auto* post = get_post(msgnum);\n  if (!post) {\n    return;\n  }\n  if (!lcs() && post->status & (status_unvalidated | status_delete)) {\n    return;\n  }\n  std::string reply_to_name;\n  if (post->ownersys && !post->owneruser) {\n    reply_to_name = grab_user_name(&post->msg, a()->current_sub().filename, a()->net_num());\n  }\n\n  if (auto o = readfile(&post->msg, a()->current_sub().filename)) {\n    auto b = o.value();\n    grab_quotes(b, reply_to_name, a()->context());\n\n    if (okfsed() && a()->user()->auto_quote() && msgnum > 0 &&\n        msgnum <= a()->GetNumMessagesInCurrentMessageArea() && user_input[0] != 'O') {\n      const auto type =\n          user_input[0] == '@' ? quote_date_format_t::generic : quote_date_format_t::post;\n      auto_quote(b, reply_to_name, type, post->daten, a()->context());\n    }\n  }\n\n  if (post->status & status_post_new_net) {\n    set_net_num(post->network.network_msg.net_number);\n    if (post->network.network_msg.net_number == static_cast<uint8_t>(-1)) {\n      bout.outstr(\"|#6Deleted network.\\r\\n\");\n      return;\n    }\n  }\n\n  if (user_input[0] == 'O' && (so() || lcs())) {\n    const auto gfilesdir = a()->config()->gfilesdir().string();\n    show_files(\"*.frm\", gfilesdir.c_str());\n    bout.outstr(\"|#2Which form letter: \");\n    auto fn = bin.input_filename(\"\", 8);\n    if (fn.empty()) {\n      return;\n    }\n    auto full_pathname = FilePath(a()->config()->gfilesdir(), StrCat(fn, \".frm\"));\n    if (!File::Exists(full_pathname)) {\n      full_pathname = FilePath(a()->config()->gfilesdir(), StrCat(\"form\", fn, \".msg\"));\n    }\n    if (File::Exists(full_pathname)) {\n      LoadFileIntoWorkspace(a()->context(), full_pathname, true);\n      email(a()->sess().irt(), post->owneruser, post->ownersys, false, post->anony);\n      clear_quotes(a()->sess());\n    }\n  } else if (user_input[0] == '@') {\n    bout.nl();\n    bout.outstr(\"|#21|#7]|#9 Reply to Different Address\\r\\n\");\n    bout.outstr(\"|#22|#7]|#9 Forward Message\\r\\n\");\n    bout.nl();\n    bout.outstr(\"|#7(Q=Quit) Select [1,2] : \");\n    switch (auto ch_reply = onek(\"Q12\\r\", true); ch_reply) {\n    case '\\r':\n    case 'Q':\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      break;\n    case '1': {\n      bout.nl();\n      bout.outstr(\"|#9Enter user name or number:\\r\\n:\");\n      const auto un_nn = fixup_user_entered_email(bin.input(75, true));\n      if (auto [un, sy] = parse_email_info(un_nn); un || sy) {\n        email(\"\", un, sy, false, 0);\n      }\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n    } break;\n    case '2': {\n      if (msgnum > 0 && msgnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n        auto o = readfile(&post->msg, a()->current_sub().filename);\n        if (!o) {\n          break;\n        }\n        auto b = o.value();\n        std::string filename = \"EXTRACT.TMP\";\n        if (File::Exists(filename)) {\n          File::Remove(filename);\n        }\n        File fileExtract(filename);\n        if (!fileExtract.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n          bout.outstr(\"|#6Could not open file for writing.\\r\\n\");\n        } else {\n          if (fileExtract.length() > 0) {\n            fileExtract.Seek(-1L, File::Whence::end);\n            char chLastChar = CZ;\n            fileExtract.Read(&chLastChar, 1);\n            if (chLastChar == CZ) {\n              fileExtract.Seek(-1L, File::Whence::end);\n            }\n          }\n          auto buffer = fmt::format(\"ON: {}\", a()->current_sub().name);\n          fileExtract.Write(buffer);\n          fileExtract.Write(\"\\r\\n\\r\\n\", 4);\n          fileExtract.Write(post->title, strlen(post->title));\n          fileExtract.Write(\"\\r\\n\", 2);\n          fileExtract.Write(b);\n          fileExtract.Close();\n        }\n        bout.nl();\n        bout.outstr(\"|#5Allow editing? \");\n        if (bin.yesno()) {\n          bout.nl();\n          LoadFileIntoWorkspace(a()->context(), filename, false);\n        } else {\n          bout.nl();\n          LoadFileIntoWorkspace(a()->context(), filename, true);\n        }\n        send_email();\n        const auto tmpfn = FilePath(a()->sess().dirs().temp_directory(), INPUT_MSG);\n        if (File::Exists(tmpfn)) {\n          File::Remove(tmpfn);\n        }\n      }\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n    } break;\n    }\n  } else {\n    if (lcs() || (a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_post_anony) || post->anony == 0) {\n      email(\"\", post->owneruser, post->ownersys, false, 0);\n    } else {\n      email(\"\", post->owneruser, post->ownersys, false, post->anony);\n    }\n    clear_quotes(a()->sess());\n  }\n}\n\nstatic void HandleScanReadFind(int& msgno, MsgScanOption& scan_option) {\n  const auto r = wwiv::bbs::FindNextMessage(msgno);\n  if (r.found) {\n    msgno = r.msgnum;\n    scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n  } else {\n    scan_option = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n  }\n}\n\nstatic FullScreenView CreateFullScreenListTitlesView() {\n\n  std::map<std::string, std::string> m;\n  m[\"subnum\"] = std::to_string(a()->current_user_sub_num());\n  const auto& c = a()->current_sub();\n  m[\"name\"] = c.name;\n  m[\"desc\"] = c.desc;\n  m[\"maxmsgs\"] = std::to_string(c.maxmsgs);\n  m[\"filename\"] = c.filename;\n  m[\"num_msgs\"] = std::to_string(a()->GetNumMessagesInCurrentMessageArea());\n  a()->context().add_context_variable(\"cursub\", m);\n\n  const auto saved_mci_enabled = bout.mci_enabled();\n  auto at_exit = finally([=] {\n    a()->context().clear_context_variables();\n    bout.set_mci_enabled(saved_mci_enabled);\n  });\n  bout.set_mci_enabled(true);\n  auto num_header_lines = 2;\n  if (bout.printfile(\"fs_msgscan\")) {\n    if (const auto iter = a()->context().return_values().find(\"num_header_lines\");\n        iter != std::end(a()->context().return_values())) {\n      num_header_lines = to_number<int>(iter->second);\n    }\n  } else {\n    bout.print(\"|[2J|#4Sub #{} - {}  ({} messages.)|[K|#0\\r\\n\", a()->current_user_sub_num(),\n                  a()->current_sub().name, a()->GetNumMessagesInCurrentMessageArea());\n    bout.print(\"|14      Num {:<42} From\\r\\n\", \"Title\");\n  }\n\n  bout.clear_lines_listed();\n  const auto screen_width = a()->user()->screen_width();\n  const auto screen_length = a()->user()->screen_lines() - 1;\n  return FullScreenView(bout, bin, num_header_lines, screen_width, screen_length);\n}\n\nstatic std::string CreateLine(std::optional<Message>&& msg, const int msgnum) {\n  if (!msg) {\n    return \"\";\n  }\n  std::string tmpbuf;\n  const auto& h = msg->header();\n  if (h.local() && h.from_usernum() == a()->sess().user_num()) {\n    tmpbuf = fmt::sprintf(\"|09[|11%d|09]\", msgnum);\n  } else if (!h.local()) {\n    tmpbuf = fmt::sprintf(\"|09<|11%d|09>\", msgnum);\n  } else {\n    tmpbuf = fmt::sprintf(\"|09(|11%d|09)\", msgnum);\n  }\n  std::string line = \"       \";\n  if (h.storage_type() == 2) {\n    // HACK: Need to make this generic. this before supporting JAM.\n    // N.B. If for some reason dynamic_cast fails, a std::bad_cast is thrown.\n    if (h.last_read() > a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()]) {\n      line[0] = '*';\n    }\n  }\n  if (h.pending_network() || h.unvalidated()) {\n    line[0] = '+';\n  }\n  const auto tmpbuf_size = size_without_colors(tmpbuf);\n  line.resize(std::max<int>(0, 9 - tmpbuf_size));\n  line += tmpbuf;\n  line += \"|11 \";\n  if ((h.unvalidated() || h.deleted()) && !lcs()) {\n    line += \"<<< NOT VALIDATED YET >>>\";\n  } else {\n    // Need the StringTrim on post title since some FSEDs\n    // added \\r in the title string, also gets rid of extra spaces\n    line += trim_to_size_ignore_colors(StringTrim(h.title()), 60);\n  }\n\n  if (a()->user()->screen_width() >= 80) {\n    if (size_without_colors(line) > 50) {\n      line = trim_to_size_ignore_colors(line, 50);\n    }\n    line += std::string(51 - size_without_colors(line), ' ');\n    if (okansi()) {\n      line += \"|09\\xB3|10 \";\n    } else {\n      line += \"| \";\n    }\n    if ((h.anony() & 0x0f) && ((a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_post_anony) == 0)) {\n      line += \">UNKNOWN<\";\n    } else {\n      line += trim_to_size_ignore_colors(h.from(), 25);\n    }\n  }\n  return line;\n}\n\nstatic std::vector<std::string> CreateMessageTitleVector(MessageArea* area, int start, int num) {\n  std::vector<std::string> lines;\n  for (auto i = start; i < start + num; i++) {\n    if (auto line = CreateLine(area->ReadMessage(i), i); !line.empty()) {\n      lines.push_back(line);\n    }\n  }\n  return lines;\n}\n\nstatic void display_title_new(const std::vector<std::string>& lines, const FullScreenView& fs,\n                              int i, bool selected) {\n  bout.goxy(1, i + fs.lines_start());\n  const auto& l = wwiv::stl::at(lines, i);\n  if (selected) {\n    bout.outstr(\"|17|12>\");\n  } else {\n    bout.outstr(\"|16|#0 \");\n  }\n  bout.outstr(pad_to_ignore_colors(l, fs.screen_width() - 1));\n  bout.outstr(\"|#0\");\n}\n\nstatic void display_titles_new(const std::vector<std::string>& lines, const FullScreenView& fs,\n                               int start, int selected) {\n  for (auto i = 0; i < fs.message_height(); i++) {\n    if (i >= size_int(lines)) {\n      break;\n    }\n    const auto is_selected = i == selected - start;\n    display_title_new(lines, fs, i, is_selected);\n  }\n}\n\nstatic ReadMessageResult HandleListTitlesFullScreen(int& msgnum, MsgScanOption& scan_option_type) {\n  bout.cls();\n  auto* api = a()->msgapi();\n  auto area = api->Open(a()->current_sub(), a()->sess().GetCurrentReadMessageArea());\n  if (!area) {\n    ReadMessageResult result;\n    result.command = 0;\n    return result;\n  }\n  // Want to start the list after the one we just read.\n  ++msgnum;\n  scan_option_type = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n\n  auto num_msgs_in_area = area->number_of_messages();\n  msgnum = std::min(msgnum, num_msgs_in_area);\n  if (msgnum > num_msgs_in_area) {\n    ReadMessageResult result;\n    result.command = 0;\n    return result;\n  }\n\n  auto fs = CreateFullScreenListTitlesView();\n  fs.DrawTopBar();\n  fs.DrawBottomBar(\"\");\n  fs.GotoContentAreaTop();\n\n  const auto window_top_min = 1;\n  const auto first = 1;\n  const auto last =\n      std::max<int>(first, area->number_of_messages() - fs.message_height() + window_top_min);\n  const auto height = std::min<int>(num_msgs_in_area, fs.message_height());\n\n  auto selected = msgnum;\n  auto window_top = std::min(msgnum, last);\n  // When starting mid-range, sometimes the selected is past the bottom.\n  if (auto window_bottom = window_top + height - window_top_min + 1; selected > window_bottom) {\n    selected = window_bottom;\n  }\n\n  auto done = false;\n  auto need_redraw = true;\n  auto last_selected = selected;\n  while (!done) {\n    a()->CheckForHangup();\n    auto lines = CreateMessageTitleVector(area.get(), window_top, height);\n    if (need_redraw) {\n      // Full redraw of the screen\n      display_titles_new(lines, fs, window_top, selected);\n    } else if (last_selected != selected) {\n      // Partial redraw of part of the screen\n      display_title_new(lines, fs, (last_selected - window_top), false);\n      display_title_new(lines, fs, (selected - window_top), true);\n    }\n\n    if (last_selected != selected) {\n      // Do this for all cases, even if need_redraw isn' true.\n      bout.goxy(1, fs.lines_start() + selected - (window_top - window_top_min) + window_top_min);\n      fs.DrawBottomBar(StrCat(\"Selected: \", selected));\n      last_selected = selected;\n    }\n\n    if (need_redraw) {\n      fs.ClearCommandLine();\n      fs.PutsCommandLine(\"|#9(|#2Q|#9=Quit, |#2?|#9=Help): \");\n    }\n    need_redraw = false;\n    auto key = bin.bgetch_event(\n        wwiv::common::Input::numlock_status_t::NOTNUMBERS,\n                     [&](wwiv::common::Input::bgetch_timeout_status_t status, int s) {\n                              if (status == wwiv::common::Input::bgetch_timeout_status_t::WARNING) {\n            fs.PrintTimeoutWarning(s);\n                              } else if (status ==\n                                         wwiv::common::Input::bgetch_timeout_status_t::CLEAR) {\n            fs.ClearCommandLine();\n          }\n        });\n    switch (key) {\n    case COMMAND_UP: {\n      if (selected + window_top_min - 1 == window_top) {\n        // At the top of the window, move the window up one.\n        if (window_top > window_top_min) {\n          window_top--;\n          selected--;\n          need_redraw = true;\n        }\n      } else {\n        selected--;\n      }\n    } break;\n    case COMMAND_PAGEUP: {\n      auto orig_window_top = window_top;\n      window_top -= height;\n      selected -= height;\n      window_top = std::max<int>(window_top, window_top_min);\n      selected = std::max<int>(selected, 1);\n      if (orig_window_top != window_top) {\n        // Only redraw the screen if we've moved it.\n        need_redraw = true;\n      }\n    } break;\n    case COMMAND_HOME: {\n      need_redraw = true;\n      selected = 1;\n      window_top = window_top_min;\n    } break;\n    case COMMAND_DOWN: {\n      auto current_window_bottom = window_top + height - window_top_min;\n      auto d = num_msgs_in_area - height + window_top_min;\n      if (selected < current_window_bottom) {\n        selected++;\n      } else if (window_top < d) {\n        selected++;\n        window_top++;\n        need_redraw = true;\n      }\n    } break;\n    case COMMAND_PAGEDN: {\n      auto orig_window_top = window_top;\n      window_top += height;\n      selected += height;\n      window_top = std::min<int>(window_top, num_msgs_in_area - height + window_top_min);\n      selected = std::min<int>(selected, num_msgs_in_area);\n      if (orig_window_top != window_top) {\n        // Only redraw the screen if we've moved it.\n        need_redraw = true;\n      }\n    } break;\n    case COMMAND_END: {\n      window_top = num_msgs_in_area - height + window_top_min;\n      selected = window_top;\n      need_redraw = true;\n    } break;\n    case SOFTRETURN: {\n      // Do nothing. SyncTerm sends CRLF on enter, not just CR\n      // like we get from the local terminal. So we'll ignore the\n      // SOFTRETURN (10, aka LF).\n    } break;\n    case RETURN: {\n      ReadMessageResult result;\n      result.option = ReadMessageOption::READ_MESSAGE;\n      msgnum = selected;\n      fs.ClearCommandLine();\n      return result;\n    }\n    default: {\n      if ((key & 0xff) == key) {\n        key = toupper(key & 0xff);\n        switch (key) {\n        case 'F': {\n          fs.ClearCommandLine();\n\n          const auto r = wwiv::bbs::FindNextMessageFS(fs, msgnum);\n          if (r.found) {\n            msgnum = r.msgnum;\n            scan_option_type = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n          } else {\n            scan_option_type = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n          }\n\n          fs.ClearCommandLine();\n          ReadMessageResult result;\n          result.option = ReadMessageOption::READ_MESSAGE;\n          return result;\n        }\n        case 'J': {\n          fs.ClearCommandLine();\n          bout.print(\"Enter Message Number (1-{}) :\", num_msgs_in_area);\n          msgnum = bin.input_number(msgnum, 1, num_msgs_in_area, false);\n\n          ReadMessageResult result;\n          result.option = ReadMessageOption::READ_MESSAGE;\n          fs.ClearCommandLine();\n          return result;\n        }\n        case 'Q': {\n          ReadMessageResult result;\n          result.option = ReadMessageOption::COMMAND;\n          result.command = 'Q';\n          fs.ClearCommandLine();\n          return result;\n        }\n        case '?': {\n          need_redraw = true;\n          fs.ClearMessageArea();\n          if (!bout.printfile(TITLE_FSED_NOEXT)) {\n            fs.ClearCommandLine();\n            bout.print(\"|#6Unable to find file: {}\", TITLE_FSED_NOEXT);\n            bout.pausescr();\n            fs.ClearCommandLine();\n          } else {\n            fs.ClearCommandLine();\n            bout.pausescr();\n            fs.ClearCommandLine();\n          }\n        } break;\n        } // default switch\n      }\n    } break;\n    } // switch\n  }\n  return {};\n}\n\nstatic void HandleListTitles(int& msgnum, MsgScanOption& scan_option_type) {\n  bout.cls();\n  auto* api = a()->msgapi();\n  auto area = api->Open(a()->current_sub(), a()->sess().GetCurrentReadMessageArea());\n  if (!area) {\n    return;\n  }\n  scan_option_type = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n  auto fs = CreateFullScreenListTitlesView();\n\n  const auto num_msgs_in_area = area->number_of_messages();\n  auto abort = false;\n  if (msgnum >= num_msgs_in_area) {\n    return;\n  }\n\n  bout.print(\"|#7{:c}{}{:c}\\r\\n\", static_cast<unsigned char>(198),\n             std::string(a()->user()->screen_width() - 3, static_cast<unsigned char>(205)),\n             static_cast<unsigned char>(181));\n  const auto num_title_lines = std::max<int>(a()->sess().num_screen_lines() - 6, 1);\n  auto i = 0;\n  while (!abort && ++i <= num_title_lines) {\n    ++msgnum;\n    const auto line = CreateLine(area->ReadMessage(msgnum), msgnum);\n    bout.bpla(line, &abort);\n    if (msgnum >= num_msgs_in_area) {\n      abort = true;\n    }\n  }\n  bout.print(\"|#7{:c}{}{:c}\\r\\n\", static_cast<unsigned char>(198),\n             std::string(a()->user()->screen_width() - 3, static_cast<unsigned char>(205)),\n             static_cast<unsigned char>(181));\n}\n\nstatic void HandleMessageDownload(int msgnum) {\n  if (msgnum > 0 && msgnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n    auto o = readfile(&(get_post(msgnum)->msg), (a()->current_sub().filename));\n    if (!o) {\n      return;\n    }\n    const auto& b = o.value();\n    bout.outstr(\"|#1Message Download -\\r\\n\\n\");\n    bout.outstr(\"|#2Filename to use? \");\n    const auto filename = bin.input_filename(12);\n    if (!okfn(filename)) {\n      return;\n    }\n    const auto f = FilePath(a()->sess().dirs().temp_directory(), filename);\n    File::Remove(f);\n    TextFile tf(f, \"wt\");\n    tf.Write(b);\n\n    bool bFileAbortStatus;\n    bool bStatus;\n    send_file(f, &bStatus, &bFileAbortStatus, f.string(), -1, b.length());\n    bout.print(\"|#1Message download... |#2{}\", bStatus ? \"successful\" : \"unsuccessful\");\n    if (bStatus) {\n      sysoplog(\"Downloaded message\");\n    }\n  }\n}\n\nvoid HandleMessageMove(int& msg_num) {\n  if ((lcs()) && (msg_num > 0) &&\n      (msg_num <= a()->GetNumMessagesInCurrentMessageArea())) {\n    std::string ss1;\n    tmp_disable_conf(true);\n    bout.nl();\n    do {\n      bout.outstr(\"|#5(|#2Q|#5=|#2Quit|#5) Move to which sub? \");\n      ss1 = mmkey(MMKeyAreaType::subs);\n      if (ss1[0] == '?') {\n        old_sublist();\n      }\n    } while (ss1[0] == '?');\n    auto temp_sub_num = -1;\n    if (ss1[0] == 0) {\n      tmp_disable_conf(false);\n      return;\n    }\n    auto ok = false;\n    for (auto i1 = 0; i1 < size_int(a()->usub) && !ok; i1++) {\n      if (ss1 == a()->usub[i1].keys) {\n        temp_sub_num = i1;\n        bout.nl();\n        bout.print(\"|#9Copying to {}\\r\\n\", a()->subs().sub(a()->usub[temp_sub_num].subnum).name);\n        ok = true;\n      }\n    }\n    if (temp_sub_num != -1) {\n      if (!wwiv::bbs::check_acs(a()->subs().sub(a()->usub[temp_sub_num].subnum).post_acs)) {\n        bout.nl();\n        bout.outstr(\"Sorry, you don't have post access on that sub.\\r\\n\\n\");\n        temp_sub_num = -1;\n      }\n    }\n    if (temp_sub_num != -1) {\n      open_sub(true);\n      resynch(&msg_num, nullptr);\n      auto p2 = *get_post(msg_num);\n      auto p1 = p2;\n      auto b = readfile(&(p2.msg), (a()->current_sub().filename)).value_or(\"\");\n      bout.nl();\n      bout.outstr(\"|#5Delete original post? \");\n      if (bin.yesno()) {\n        delete_message(msg_num);\n        if (msg_num > 1) {\n          msg_num--;\n        }\n      }\n      close_sub();\n      iscan(temp_sub_num);\n      open_sub(true);\n      p2.msg.storage_type = static_cast<unsigned char>(a()->current_sub().storage_type);\n      savefile(b, &(p2.msg), (a()->current_sub().filename));\n      a()->status_manager()->Run([&](Status& s) { p2.qscan = s.next_qscanptr(); });\n      if (a()->GetNumMessagesInCurrentMessageArea() >= a()->current_sub().maxmsgs) {\n        auto temp_msg_num = 1;\n        auto msg_to_delete = 0;\n        while (msg_to_delete == 0 && temp_msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n          if ((get_post(temp_msg_num)->status & status_no_delete) == 0) {\n            msg_to_delete = temp_msg_num;\n          }\n          ++temp_msg_num;\n        }\n        if (msg_to_delete == 0) {\n          msg_to_delete = 1;\n        }\n        delete_message(msg_to_delete);\n      }\n      if (!(a()->current_sub().anony & anony_val_net) || a()->current_sub().nets.empty()) {\n        p2.status &= ~status_pending_net;\n      }\n      if (!a()->current_sub().nets.empty()) {\n        p2.status |= status_pending_net;\n        a()->user()->posts_net(a()->user()->posts_net() + 1);\n        send_net_post(&p2, a()->current_sub());\n      }\n      add_post(&p2);\n      close_sub();\n      tmp_disable_conf(false);\n      iscan(a()->current_user_sub_num());\n      bout.nl();\n      bout.outstr(\"|#9Message moved.\\r\\n\\n\");\n      resynch(&msg_num, &p1);\n    } else {\n      tmp_disable_conf(false);\n    }\n  }\n}\n\nstatic void HandleMessageLoad() {\n  if (!so()) {\n    return;\n  }\n  bout.nl();\n  bout.outstr(\"|#2Filename: \");\n  const auto fn = bin.input_path(50);\n  if (fn.empty()) {\n    return;\n  }\n  bout.nl();\n  bout.outstr(\"|#5Allow editing? \");\n  const auto no_edit_allowed = !bin.yesno();\n  bout.nl();\n  LoadFileIntoWorkspace(a()->context(), fn, no_edit_allowed);\n}\n\nvoid HandleMessageReply(int& msg_num) {\n  auto p2 = *get_post(msg_num);\n  if (!lcs() && (p2.status & (status_unvalidated | status_delete))) {\n    return;\n  }\n  const auto& cs = a()->current_sub();\n  auto o =\n      read_type2_message(&p2.msg, p2.anony & 0x0f, true, cs.filename, p2.ownersys, p2.owneruser);\n  if (!o) {\n    return;\n  }\n  auto& m = o.value();\n  m.title = p2.title;\n\n  grab_quotes(m.raw_message_text, m.from_user_name, a()->context());\n\n  if (okfsed() && a()->user()->auto_quote() && msg_num > 0 &&\n      msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n    // auto_quote needs the raw message text like from readfile(), so that\n    // the top two lines are header information.\n    auto_quote(m.raw_message_text, m.from_user_name, quote_date_format_t::generic, p2.daten,\n               a()->context());\n  }\n\n  if (!m.title.empty()) {\n    a()->sess().irt(m.title);\n  }\n  PostReplyToData r;\n  r.name = m.from_user_name;\n  r.title = m.title;\n  r.text = m.message_text;\n  post(PostData(r));\n  resynch(&msg_num, &p2);\n  clear_quotes(a()->sess());\n}\n\nstatic void HandleMessageDelete(int& msg_num) {\n  if (!lcs()) {\n    return;\n  }\n  if (!msg_num) {\n    return;\n  }\n\n  bout.print(\"|#5Delete message #{}. Are you sure?\", msg_num);\n  if (!bin.noyes()) {\n    return;\n  }\n\n  open_sub(true);\n  resynch(&msg_num, nullptr);\n  auto p2 = *get_post(msg_num);\n  delete_message(msg_num);\n  close_sub();\n\n  auto at_exit = finally([&] { resynch(&msg_num, &p2); });\n  if (p2.ownersys != 0) {\n    return;\n  }\n  User tu;\n  if (!a()->users()->readuser(&tu, p2.owneruser)) {\n    return;\n  }\n  if (tu.deleted()) {\n    return;\n  }\n  if (date_to_daten(tu.firston()) < p2.daten) {\n    bout.nl();\n    bout.outstr(\"|#2Remove how many posts credit? \");\n    auto num_credits =\n        bin.input_number<uint16_t>(0, 0, static_cast<uint16_t>(tu.messages_posted()));\n    if (num_credits != 0) {\n      tu.messages_posted(tu.messages_posted() - num_credits);\n    }\n    bout.nl();\n    bout.print(\"|#7Post credit removed = {}\\r\\n\", num_credits);\n    tu.deleted_posts(tu.deleted_posts() + 1);\n    a()->users()->writeuser(&tu, p2.owneruser);\n    a()->UpdateTopScreen();\n  }\n}\n\nstatic void HandleMessageExtract(int& msgnum) {\n  if (!so()) {\n    return;\n  }\n  if (msgnum > 0 && msgnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n    if (auto o = readfile(&get_post(msgnum)->msg, (a()->current_sub().filename))) {\n      const auto& b = o.value();\n      extract_out(b, get_post(msgnum)->title);\n    }\n  }\n}\n\nstatic void HandleMessageHelp() {\n  if (a()->sess().forcescansub()) {\n    bout.printfile(MUSTREAD_NOEXT);\n  } else if (lcs()) {\n    bout.print_help_file(SMBMAIN_NOEXT);\n  } else {\n    bout.print_help_file(MBMAIN_NOEXT);\n  }\n}\n\nstatic void HandleValUser(int msg_num) {\n  if (cs() && get_post(msg_num)->ownersys == 0 && msg_num > 0 &&\n      msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n    valuser(get_post(msg_num)->owneruser);\n  } else if (cs() && msg_num > 0 &&\n             msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n    bout.nl();\n    bout.outstr(\"|#6Post from another system.\\r\\n\\n\");\n  }\n}\n\nstatic void HandleToggleAutoPurge(int msg_num) {\n  if (lcs() && msg_num > 0 &&\n      msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n    wwiv::bbs::OpenSub opened_sub(true);\n    resynch(&msg_num, nullptr);\n    auto p3 = get_post(msg_num);\n    p3->status ^= status_no_delete;\n    write_post(msg_num, p3);\n    bout.nl();\n    if (p3->status & status_no_delete) {\n      bout.outstr(\"|#9Message will |#6NOT|#9 be auto-purged.\\r\\n\");\n    } else {\n      bout.outstr(\"|#9Message |#2CAN|#9 now be auto-purged.\\r\\n\");\n    }\n    bout.nl();\n  }\n}\n\nstatic void HandleTogglePendingNet(int msg_num, int& val) {\n  if (lcs() && msg_num > 0 && msg_num <= a()->GetNumMessagesInCurrentMessageArea() &&\n      a()->current_sub().anony & anony_val_net && !a()->current_sub().nets.empty()) {\n    wwiv::bbs::OpenSub opened_sub(true);\n    resynch(&msg_num, nullptr);\n    auto p3 = get_post(msg_num);\n    p3->status ^= status_pending_net;\n    write_post(msg_num, p3);\n    close_sub();\n    bout.nl();\n    if (p3->status & status_pending_net) {\n      val |= 2;\n      bout.outstr(\"|#9Will be sent out on net now.\\r\\n\");\n    } else {\n      bout.outstr(\"|#9Not set for net pending now.\\r\\n\");\n    }\n    bout.nl();\n  }\n}\n\nstatic void HandleRemoveFromNewScan() {\n  const auto subname = a()->subs().sub(a()->current_user_sub().subnum).name;\n  bout.print(\"|#5Remove '{}' from your Q-Scan? \", subname);\n  if (bin.yesno()) {\n    a()->sess().qsc_q[a()->current_user_sub().subnum / 32] ^=\n        (1L << (a()->current_user_sub().subnum % 32));\n    return;\n  }\n\n  bout.print(\"|#9Mark messages in '{}' as read? \", subname);\n  if (bin.yesno()) {\n    const auto status = a()->status_manager()->get_status();\n    a()->sess().qsc_p[a()->current_user_sub().subnum] = status->qscanptr() - 1L;\n  }\n}\n\nstatic void HandleToggleUnAnonymous(int msg_num) {\n  if (lcs() && msg_num > 0 && msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n    wwiv::bbs::OpenSub opened_sub(true);\n    resynch(&msg_num, nullptr);\n    postrec* p3 = get_post(msg_num);\n    p3->anony = 0;\n    write_post(msg_num, p3);\n    bout.nl();\n    bout.outstr(\"|#9Message is not anonymous now.\\r\\n\");\n  }\n}\n\nstatic void HandleScanReadPrompt(int& msgnum, MsgScanOption& scan_option, bool& nextsub,\n                                 bool& title_scan, bool& done, bool& quit, int& val) {\n  bin.resetnsp();\n  const auto read_prompt = GetScanReadPrompts(msgnum);\n  bout.nl();\n  bout.outstr(read_prompt);\n  char szUserInput[81];\n  bin.input(szUserInput, 5, true);\n  resynch(&msgnum, nullptr);\n  while (szUserInput[0] == 32) {\n    char szTempBuffer[255];\n    strcpy(szTempBuffer, &(szUserInput[1]));\n    strcpy(szUserInput, szTempBuffer);\n  }\n  if (title_scan && szUserInput[0] == 0 && msgnum < a()->GetNumMessagesInCurrentMessageArea()) {\n    scan_option = MsgScanOption::SCAN_OPTION_LIST_TITLES;\n    szUserInput[0] = 'T';\n    szUserInput[1] = '\\0';\n  } else {\n    title_scan = false;\n    scan_option = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n  }\n  auto nUserInput = to_number<int>(szUserInput);\n  if (szUserInput[0] == '\\0') {\n    nUserInput = msgnum + 1;\n    if (nUserInput >= a()->GetNumMessagesInCurrentMessageArea() + 1) {\n      done = true;\n    }\n  }\n\n  if (nUserInput != 0 && nUserInput <= a()->GetNumMessagesInCurrentMessageArea() &&\n      nUserInput >= 1) {\n    scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n    msgnum = nUserInput;\n  } else if (szUserInput[1] == '\\0') {\n    if (a()->sess().forcescansub()) {\n      return;\n    }\n    switch (szUserInput[0]) {\n    case '$':\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      msgnum = a()->GetNumMessagesInCurrentMessageArea();\n      break;\n    case 'F':\n      HandleScanReadFind(msgnum, scan_option);\n      break;\n    case 'Q':\n      quit = true;\n      done = true;\n      nextsub = false;\n      break;\n    case 'B':\n      if (nextsub) {\n        HandleRemoveFromNewScan();\n      }\n      nextsub = true;\n      done = true;\n      quit = true;\n      break;\n    case 'T':\n      title_scan = true;\n      scan_option = MsgScanOption::SCAN_OPTION_LIST_TITLES;\n      break;\n    case 'R':\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      break;\n    case '?':\n      HandleMessageHelp();\n      break;\n    case '@':\n    case 'A':\n      HandleScanReadAutoReply(msgnum, szUserInput, scan_option);\n      break;\n    case 'D':\n      HandleMessageDelete(msgnum);\n      break;\n    case 'E':\n      HandleMessageExtract(msgnum);\n      break;\n    case 'L':\n      HandleMessageLoad();\n      break;\n    case 'M':\n      HandleMessageMove(msgnum);\n      break;\n    case 'N':\n      HandleToggleAutoPurge(msgnum);\n      break;\n    case 'P':\n      a()->sess().clear_irt();\n      post(PostData());\n      break;\n    case 'U':\n      HandleToggleUnAnonymous(msgnum);\n      break;\n    case 'V':\n      HandleValUser(msgnum);\n      break;\n    case 'W':\n      HandleMessageReply(msgnum);\n      break;\n    case 'X':\n      HandleTogglePendingNet(msgnum, val);\n      break;\n    case 'Y':\n      HandleMessageDownload(msgnum);\n      break;\n    case '>':\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      break;\n    case '-':\n      if (msgnum > 1 && (msgnum - 1 < a()->GetNumMessagesInCurrentMessageArea())) {\n        --msgnum;\n        scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      }\n      break;\n      // These used to be threaded code.\n    case '*':\n      break;\n    case '[':\n      break;\n    case ']':\n      break;\n    }\n  }\n}\n\nstatic void validate() {\n  bout.nl();\n  bout.outstr(\"|#5Validate messages here? \");\n  if (bin.noyes()) {\n    wwiv::bbs::OpenSub opened_sub(true);\n    for (int i = 1; i <= a()->GetNumMessagesInCurrentMessageArea(); i++) {\n      postrec* p3 = get_post(i);\n      if (p3->status & (status_unvalidated | status_delete)) {\n        p3->status &= (~(status_unvalidated | status_delete));\n      }\n      write_post(i, p3);\n    }\n  }\n}\n\nstatic void network_validate() {\n  bout.nl();\n  bout.outstr(\"|#5Network validate here? \");\n  if (bin.yesno()) {\n    int nNumMsgsSent = 0;\n    std::vector<postrec> to_validate;\n    {\n      wwiv::bbs::OpenSub opened_sub(true);\n      for (int i = 1; i <= a()->GetNumMessagesInCurrentMessageArea(); i++) {\n        if (auto * p4 = get_post(i); p4->status & status_pending_net) {\n          to_validate.push_back(*p4);\n          p4->status &= ~status_pending_net;\n          write_post(i, p4);\n        }\n      }\n    }\n    for (auto p : to_validate) {\n      send_net_post(&p, a()->current_sub());\n      nNumMsgsSent++;\n    }\n\n    bout.nl();\n    bout.print(\"{} messages sent.\", nNumMsgsSent);\n    bout.nl(2);\n  }\n}\n\n// Asks if user wants to post, returns true if done, meaning user says Yes (and posts) or No.\nstatic bool query_post() {\n  if (!a()->user()->restrict_post() &&\n      a()->user()->posts_today() < a()->config()->sl(a()->sess().effective_sl()).posts &&\n      wwiv::bbs::check_acs(a()->current_sub().post_acs)) {\n    bout.print(\"\\r|#5Post on {} (|#2Y/N/Q|#5) ? \", a()->current_sub().name);\n    a()->sess().clear_irt();\n    clear_quotes(a()->sess());\n    const auto q = bin.ynq();\n    if (q == 'Y') {\n      post(PostData());\n      return true;\n    }\n    return q == 'N';\n  }\n  bout.outstr(\"|#5Move to the next sub?\");\n  return bin.noyes();\n}\n\nstatic void scan_new(int msgnum, MsgScanOption scan_option, bool& nextsub, bool title_scan) {\n  auto done = false;\n  auto val = 0;\n  auto skip_query_post = false;\n  while (!done) {\n    a()->CheckForHangup();\n    ReadMessageResult result{};\n    if (scan_option == MsgScanOption::SCAN_OPTION_READ_MESSAGE) {\n      if (msgnum > 0 && msgnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n        // Only try to read messages we can.\n        auto next = true;\n        result = read_post(msgnum, &next, &val);\n      } else {\n        result.option = ReadMessageOption::NEXT_MSG;\n      }\n    } else if (scan_option == MsgScanOption::SCAN_OPTION_LIST_TITLES) {\n      result = HandleListTitlesFullScreen(msgnum, scan_option);\n    } else if (scan_option == MsgScanOption::SCAN_OPTION_READ_PROMPT) {\n      auto quit = false;\n      HandleScanReadPrompt(msgnum, scan_option, nextsub, title_scan, done, quit, val);\n      if (quit) {\n        done = true;\n      }\n    }\n\n    switch (result.option) {\n    case ReadMessageOption::READ_MESSAGE: {\n      scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      if (msgnum > a()->GetNumMessagesInCurrentMessageArea()) {\n        done = true;\n      }\n    } break;\n    case ReadMessageOption::NEXT_MSG: {\n      if (++msgnum > a()->GetNumMessagesInCurrentMessageArea()) {\n        done = true;\n      }\n    } break;\n    case ReadMessageOption::PREV_MSG: {\n      if (--msgnum <= 0) {\n        done = true;\n      }\n    } break;\n    case ReadMessageOption::JUMP_TO_MSG: {\n      const auto max_msgnum = a()->GetNumMessagesInCurrentMessageArea();\n      bout.print(\"Enter Message Number (1-{}) :\", max_msgnum);\n      msgnum = bin.input_number(msgnum, 0, max_msgnum, false);\n      if (msgnum < 1) {\n        done = true;\n      }\n    } break;\n    case ReadMessageOption::LIST_TITLES: {\n      scan_option = MsgScanOption::SCAN_OPTION_LIST_TITLES;\n    } break;\n    case ReadMessageOption::COMMAND: {\n      switch (result.command) {\n      case 'Q':\n        done = true;\n        nextsub = false;\n        break;\n      case '@':\n        HandleScanReadAutoReply(msgnum, \"@\", scan_option);\n        break;\n      case 'A':\n        HandleScanReadAutoReply(msgnum, \"A\", scan_option);\n        break;\n      case 'B':\n        if (nextsub) {\n          skip_query_post = true;\n          HandleRemoveFromNewScan();\n        }\n        nextsub = true;\n        done = true;\n        break;\n      case 'D':\n        HandleMessageDelete(msgnum);\n        break;\n      case 'E':\n        HandleMessageExtract(msgnum);\n        break;\n      case 'L':\n        HandleMessageLoad();\n        break;\n      case 'M':\n        HandleMessageMove(msgnum);\n        break;\n      case 'N':\n        HandleToggleAutoPurge(msgnum);\n        break;\n      case 'P': {\n\ta()->sess().clear_irt();\n        post(PostData());\n      } break;\n      case 'U':\n        HandleToggleUnAnonymous(msgnum);\n        break;\n      case 'V':\n        HandleValUser(msgnum);\n        break;\n      case 'W':\n        HandleMessageReply(msgnum);\n        break;\n      case 'X':\n        HandleTogglePendingNet(msgnum, val);\n        break;\n      case 'Y':\n        HandleMessageDownload(msgnum);\n        break;\n      }\n    } break;\n    }\n    if (done) {\n      if ((val & 1) && lcs()) {\n        validate();\n      }\n      if ((val & 2) && lcs()) {\n        network_validate();\n      }\n      if (!skip_query_post) {\n        done = query_post();\n      }\n      if (!done) {\n        // back to list title.\n        scan_option = MsgScanOption::SCAN_OPTION_LIST_TITLES;\n      }\n    }\n  }\n}\n\nvoid scan(int msg_num, MsgScanOption scan_option, bool& nextsub, bool title_scan) {\n  a()->sess().clear_irt();\n\n  int val = 0;\n  iscan(a()->current_user_sub_num());\n  if (a()->sess().GetCurrentReadMessageArea() < 0) {\n    bout.nl();\n    bout.outstr(\"No subs available.\\r\\n\\n\");\n    return;\n  }\n\n  const auto& cs = a()->current_sub();\n  const auto fsreader_enabled =\n      a()->fullscreen_read_prompt() && a()->user()->has_flag(User::fullScreenReader);\n  const auto skip_fs_reader_per_sub = (cs.anony & anony_no_fullscreen) != 0;\n  if (fsreader_enabled && !skip_fs_reader_per_sub) {\n    scan_new(msg_num, scan_option, nextsub, title_scan);\n    return;\n  }\n\n  bool done = false;\n  bool quit = false;\n  do {\n    a()->tleft(true);\n    a()->CheckForHangup();\n    set_net_num((a()->current_sub().nets.empty()) ? 0 : a()->current_sub().nets[0].net_num);\n    if (scan_option != MsgScanOption::SCAN_OPTION_READ_PROMPT) {\n      resynch(&msg_num, nullptr);\n    }\n    write_inst(INST_LOC_SUBS, a()->current_user_sub().subnum, INST_FLAGS_NONE);\n\n    switch (scan_option) {\n    case MsgScanOption::SCAN_OPTION_READ_PROMPT: { // Read Prompt\n      HandleScanReadPrompt(msg_num, scan_option, nextsub, title_scan, done, quit, val);\n    } break;\n    case MsgScanOption::SCAN_OPTION_LIST_TITLES: { // List Titles\n      HandleListTitles(msg_num, scan_option);\n    } break;\n    case MsgScanOption::SCAN_OPTION_READ_MESSAGE: { // Read Message\n      auto next = false;\n      if (msg_num > 0 && msg_num <= a()->GetNumMessagesInCurrentMessageArea()) {\n        const auto old_incom = a()->sess().incom();\n        if (a()->sess().forcescansub()) {\n          a()->sess().incom(false);\n        }\n        read_post(msg_num, &next, &val);\n        if (a()->sess().forcescansub()) {\n          a()->sess().incom(old_incom);\n        }\n      }\n      bout.ansic(0);\n      bout.nl();\n      if (next) {\n        ++msg_num;\n        if (msg_num > a()->GetNumMessagesInCurrentMessageArea()) {\n          done = true;\n        }\n        scan_option = MsgScanOption::SCAN_OPTION_READ_MESSAGE;\n      } else {\n        scan_option = MsgScanOption::SCAN_OPTION_READ_PROMPT;\n      }\n    } break;\n    }\n  } while (!done);\n\n  if ((val & 1) && lcs()) {\n    validate();\n  }\n  if ((val & 2) && lcs()) {\n    network_validate();\n  }\n  bout.nl();\n  if (quit) {\n    return;\n  }\n  query_post();\n  bout.nl();\n}\n"
  },
  {
    "path": "bbs/msgscan.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_MSGSCAN_H__\n#define __INCLUDED_BBS_MSGSCAN_H__\n\nenum class MsgScanOption {\n  SCAN_OPTION_READ_PROMPT,\n  SCAN_OPTION_LIST_TITLES,\n  SCAN_OPTION_READ_MESSAGE\n};\n\nvoid scan(int msgnum, MsgScanOption scan_option, bool &next_sub, bool title_scan);\n\n#endif  // __INCLUDED_BBS_MSGSCAN_H__\n"
  },
  {
    "path": "bbs/multinst.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/multinst.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/instmsg.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/names.h\"\n#include \"sdk/subxtr.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n// Local function prototypes\n\n/*\n * Returns a std::string (in out) like:\n *\n * Instance   1: Offline\n *     LastUser: Sysop #1\n *\n * or\n *\n * Instance  22: Network transmission\n *     CurrUser: Sysop #1\n */\nstd::string make_inst_str(int instance_num, int format) {\n  auto ir = a()->instances().at(instance_num);\n\n  switch (format) {\n  case INST_FORMAT_WFC:\n    return ir.location_description();\n  case INST_FORMAT_OLD:\n    // Not used anymore.\n    return fmt::sprintf(\"|#1Instance %-3d: |#2\", instance_num);\n  case INST_FORMAT_LIST: {\n    std::string user_name{\"(Nobody)\"};\n    if (ir.user_number() < a()->config()->max_users() && ir.user_number() > 0) {\n      if (ir.online()) {\n        user_name = a()->names()->UserName(ir.user_number());\n      } else {\n        user_name = StrCat(\"Last: \", a()->names()->UserName(ir.user_number()));\n      }\n    }\n    const auto as = ir.location_description();\n    return fmt::sprintf(\"|#5%-4d |#2%-35.35s |#1%-37.37s\", instance_num, user_name, as);\n  }\n  default:\n    return fmt::format(\"** INVALID INSTANCE FORMAT PASSED [{}] **\", format);\n  }\n}\n\nvoid multi_instance() {\n  bout.nl();\n  const auto num = num_instances();\n  if (num < 1) {\n    bout.outstr(\"|#6Couldn't find instance data file.\\r\\n\");\n    return;\n  }\n\n  bout.printf(\"|#5Node |#1%-35.35s |#2%-37.37s\\r\\n\", \"User Name\", \"Activity\");\n  bout.print(\"==== {} {}\\r\\n\", std::string(35, '='), std::string(37, '='));\n\n  for (int inst = 1; inst <= num; inst++) {\n    bout.pl(make_inst_str(inst, INST_FORMAT_LIST));\n  }\n}\n\nint find_instance_by_loc(int loc, int subloc) {\n  if (loc == INST_LOC_FSED) {\n    return 0;\n  }\n\n  const auto instances = a()->instances().all();\n  if (instances.size() <= 1) {\n    return 0;\n  }\n  for (const auto& in : instances) {\n    if (in.loc_code() == loc && in.subloc_code() == subloc && in.node_number() > 0 &&\n        in.node_number() != a()->sess().instance_number()) {\n      return in.node_number();\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "bbs/multinst.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_MULTINT_H\n#define INCLUDED_BBS_MULTINT_H\n\n#include <string>\n\nstd::string make_inst_str(int nInstanceNum, int nInstanceFormat);\nvoid multi_instance();\n\n/**\n *Finds the instance number at loc and subloc, or returns 0 if none can be found.\n */\nint  find_instance_by_loc(int loc, int subloc);\n\n#endif"
  },
  {
    "path": "bbs/multmail.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/multmail.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/email.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/inmsg.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/sysoplog.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/findfiles.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include <string>\n\n// local function prototypes\nvoid add_list(int *pnUserNumber, int *numu, int maxu, int allowdup);\nint  oneuser();\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid multimail(int *pnUserNumber, int numu) {\n  mailrec m, m1;\n  char s[255];\n  User user;\n  memset(&m, 0, sizeof(mailrec));\n\n  if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n    bout.nl();\n    bout.outstr(\"Sorry, not enough disk space left.\\r\\n\\n\");\n    return;\n  }\n  bout.nl();\n  MessageEditorData data(a()->user()->name_and_number());\n  data.need_title = true;\n  if (a()->config()->sl(a()->sess().effective_sl()).ability & ability_email_anony) {\n    data.anonymous_flag = anony_enable_anony;\n  }\n  bout.outstr(\"|#5Show all recipients in mail? \");\n  bool show_all = bin.yesno();\n  int j = 0;\n  auto s1 = fmt::sprintf(\"\\003\"\"6CC: \\003\"\"1\");\n\n  m.msg.storage_type = EMAIL_STORAGE;\n  a()->sess().irt(\"Multi-Mail\");\n  File::Remove(QUOTES_TXT);\n  data.aux = \"email\";\n  data.fsed_flags = FsedFlags::FSED;\n  data.to_name = \"Multi-Mail\";\n  data.msged_flags = MSGED_FLAG_NONE;\n  if (!inmsg(data)) {\n    return;\n  }\n  savefile(data.text, &m.msg, data.aux);\n  strcpy(m.title, data.title.c_str());\n\n  bout.outstr(\"Mail sent to:\\r\\n\");\n  sysoplog(\"Multi-Mail to:\");\n\n  lineadd(&m.msg, \"\\003\"\"7----\", \"email\");\n\n  for (int cv = 0; cv < numu; cv++) {\n    if (pnUserNumber[cv] < 0) {\n      continue;\n    }\n    a()->users()->readuser(&user, pnUserNumber[cv]);\n    if ((user.sl() == 255 && (user.email_waiting() > a()->config()->max_waiting() * 5)) ||\n        ((user.sl() != 255) && (user.email_waiting() > a()->config()->max_waiting())) ||\n        user.email_waiting() > 200) {\n      bout.print(\"{} mailbox full, not sent.\", a()->names()->UserName(pnUserNumber[cv]));\n      pnUserNumber[cv] = -1;\n      continue;\n    }\n    if (user.deleted()) {\n      bout.outstr(\"User deleted, not sent.\\r\\n\");\n      pnUserNumber[cv] = -1;\n      continue;\n    }\n    strcpy(s, \"  \");\n    user.email_waiting(user.email_waiting() + 1);\n    a()->users()->writeuser(&user, pnUserNumber[cv]);\n    const auto pnunn = a()->names()->UserName(pnUserNumber[cv]);\n    strcat(s, pnunn.c_str());\n    a()->status_manager()->Run([&](Status& status) {\n      if (pnUserNumber[cv] == 1) {\n        status.increment_feedback_today();\n        a()->user()->feedback_today(a()->user()->feedback_today() + 1);\n        a()->user()->feedback_sent(a()->user()->feedback_sent() + 1);\n      } else {\n        status.increment_email_today();\n        a()->user()->email_sent(a()->user()->email_sent() + 1);\n        a()->user()->email_today(a()->user()->email_today() + 1);\n      }\n    });\n    sysoplog(s);\n    bout.outstr(s);\n    bout.nl();\n    if (show_all) {\n      const std::string pnunn2 = a()->names()->UserName(pnUserNumber[cv]);\n      s1 = fmt::sprintf(\"%-22.22s  \", pnunn2);\n      j++;\n      if (j >= 3) {\n        lineadd(&m.msg, s1, \"email\");\n        j = 0;\n        s1 = \"\\003\"\"1    \";\n      }\n    }\n  }\n  if (show_all) {\n    if (j) {\n      lineadd(&m.msg, s1, \"email\");\n    }\n  }\n  s1 = fmt::sprintf(\"\\003\"\"2Mail Sent to %d Addresses!\", numu);\n  lineadd(&m.msg, \"\\003\"\"7----\", \"email\");\n  lineadd(&m.msg, s1, \"email\");\n\n  m.anony = static_cast<unsigned char>(data.anonymous_flag);\n  m.fromsys = 0;\n  m.fromuser = static_cast<uint16_t>(a()->sess().user_num());\n  m.tosys = 0;\n  m.touser = 0;\n  m.status = status_multimail;\n  m.daten = daten_t_now();\n\n  auto pFileEmail(OpenEmailFile(true));\n  auto len = pFileEmail->length() / sizeof(mailrec);\n  File::size_type i = 0;\n  if (len != 0) {\n    i = len - 1;\n    pFileEmail->Seek(static_cast<long>(i) * sizeof(mailrec), File::Whence::begin);\n    pFileEmail->Read(&m1, sizeof(mailrec));\n    while ((i > 0) && (m1.tosys == 0) && (m1.touser == 0)) {\n      --i;\n      pFileEmail->Seek(static_cast<long>(i) * sizeof(mailrec), File::Whence::begin);\n      auto i1 = pFileEmail->Read(&m1, sizeof(mailrec));\n      if (i1 == -1) {\n        bout.outstr(\"|#6DIDN'T READ WRITE!\\r\\n\");\n      }\n    }\n    if ((m1.tosys) || (m1.touser)) {\n      ++i;\n    }\n  }\n  pFileEmail->Seek(static_cast<long>(i) * sizeof(mailrec), File::Whence::begin);\n  for (auto cv = 0; cv < numu; cv++) {\n    if (pnUserNumber[cv] > 0) {\n      m.touser = static_cast<uint16_t>(pnUserNumber[cv]);\n      pFileEmail->Write(&m, sizeof(mailrec));\n    }\n  }\n  pFileEmail->Close();\n}\n\nstatic char *mml_s;\nstatic int mml_started;\n\nint oneuser() {\n  char s[81], *ss;\n  int i;\n  User user;\n\n  if (mml_s) {\n    if (mml_started) {\n      ss = strtok(nullptr, \"\\r\\n\");\n    } else {\n      ss = strtok(mml_s, \"\\r\\n\");\n    }\n    mml_started = 1;\n    if (ss == nullptr) {\n      free(mml_s);\n      mml_s = nullptr;\n      return -1;\n    }\n    strcpy(s, ss);\n    for (i = 0; s[i] != 0; i++) {\n      s[i] = upcase(s[i]);\n    }\n  } else {\n    bout.outstr(\"|#2>\");\n    bin.input(s, 40);\n  }\n  auto user_number_int = finduser1(s);\n  if (user_number_int == 65535) {\n    return -1;\n  }\n  if (s[0] == 0) {\n    return -1;\n  }\n  if (user_number_int <= 0) {\n    bout.nl();\n    bout.outstr(\"Unknown user.\\r\\n\\n\");\n    return 0;\n  }\n  uint16_t user_number = static_cast<uint16_t>(user_number_int);\n  uint16_t system_number = 0;\n  if (ForwardMessage(&user_number, &system_number)) {\n    bout.nl();\n    bout.outstr(\"Forwarded.\\r\\n\\n\");\n    if (system_number) {\n      bout.outstr(\"Forwarded to another system.\\r\\n\");\n      bout.outstr(\"Can't send multi-mail to another system.\\r\\n\\n\");\n      return 0;\n    }\n  }\n  if (user_number == 0) {\n    bout.nl();\n    bout.outstr(\"Unknown user.\\r\\n\\n\");\n    return 0;\n  }\n  a()->users()->readuser(&user, user_number);\n  if (((user.sl() == 255) && (user.email_waiting() > (a()->config()->max_waiting() * 5))) ||\n      ((user.sl() != 255) && (user.email_waiting() > a()->config()->max_waiting())) ||\n      (user.email_waiting() > 200)) {\n    bout.nl();\n    bout.outstr(\"Mailbox full.\\r\\n\\n\");\n    return 0;\n  }\n  if (user.deleted()) {\n    bout.nl();\n    bout.outstr(\"Deleted user.\\r\\n\\n\");\n    return 0;\n  }\n  bout.print(\"     -> {}\\r\\n\", a()->names()->UserName(user_number));\n  return user_number;\n}\n\n\nvoid add_list(int *pnUserNumber, int *numu, int maxu, int allowdup) {\n  bool done = false;\n  int mml = (mml_s != nullptr);\n  mml_started = 0;\n  while (!done && (*numu < maxu)) {\n    int i = oneuser();\n    if (mml && (!mml_s)) {\n      done = true;\n    }\n    if (i == -1) {\n      done = true;\n    } else if (i) {\n      if (!allowdup) {\n        for (int i1 = 0; i1 < *numu; i1++) {\n          if (pnUserNumber[i1] == i) {\n            bout.nl();\n            bout.outstr(\"Already in list, not added.\\r\\n\\n\");\n            i = 0;\n\t    break;\n          }\n\t}\n\t  if (i) {\n\t    pnUserNumber[(*numu)++] = i;\n\t  }\n      } else {\n\tif (i) {\n\t    pnUserNumber[(*numu)++] = i;\n\t}\n      }\n    }\n  }\n  if (*numu == maxu) {\n    bout.nl();\n    bout.outstr(\"List full.\\r\\n\\n\");\n  }\n}\n\n#define MAX_LIST 40\n\nvoid slash_e() {\n  int user_number[MAX_LIST]={}, numu, i;\n  char s[81],*sss;\n\n  mml_s = nullptr;\n  mml_started = 0;\n  if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n    bout.nl();\n    bout.outstr(\"Sorry, not enough disk space left.\\r\\n\\n\");\n    return;\n  }\n  if (((a()->user()->feedback_today() >= 10) ||\n       (a()->user()->email_today() >= a()->config()->sl(a()->sess().effective_sl()).emails))\n      && (!cs())) {\n    bout.outstr(\"Too much mail sent today.\\r\\n\\n\");\n    return;\n  }\n  if (a()->user()->restrict_email()) {\n    bout.outstr(\"You can't send mail.\\r\\n\");\n    return;\n  }\n  auto done = false;\n  numu = 0;\n  do {\n    bout.nl(2);\n    bout.print(\"|#2Multi-Mail: List: {} : A,M,D,L,E,Q,? : \",numu);\n    switch (char ch = onek(\"QAMDEL?\"); ch) {\n    case '?':\n      bout.printfile(MMAIL_NOEXT);\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'A':\n      bout.nl();\n      bout.print(\"Enter names/numbers for users, one per line, max {}.\\r\\n\\n\",MAX_LIST);\n      mml_s = nullptr;\n      //add_list(user_number, &numu, MAX_LIST, so());\n      add_list(user_number, &numu, MAX_LIST, 0); // do we really want sysops\n                                           // to be able to add dupe entries?\n      break;\n    case 'M': {\n      FindFiles ff(FilePath(a()->config()->datadir(), \"*.mml\"), FindFiles::FindFilesType::any);\n      if (ff.empty()) {\n        bout.nl();\n        bout.outstr(\"No mailing lists available.\\r\\n\\n\");\n        break;\n      }\n      bout.nl();\n      bout.outstr(\"Available mailing lists:\\r\\n\\n\");\n      for (const auto& f : ff) {\n        to_char_array(s, f.name);\n        sss = strchr(s, '.');\n        if (sss) {\n          *sss = 0;\n        }\n        bout.outstr(s);\n        bout.nl();\n      }\n\n      bout.nl();\n      bout.outstr(\"|#2Which? \");\n      bin.input(s, 8);\n      File fileMailList(FilePath(a()->config()->datadir(), s));\n      if (!fileMailList.Open(File::modeBinary | File::modeReadOnly)) {\n        bout.nl();\n        bout.outstr(\"Unknown mailing list.\\r\\n\\n\");\n      } else {\n        auto i1 = fileMailList.length();\n        mml_s = static_cast<char *>(BbsAllocA(i1 + 10L));\n        fileMailList.Read(mml_s, i1);\n        mml_s[i1] = '\\n';\n        mml_s[i1 + 1] = 0;\n        fileMailList.Close();\n        mml_started = 0;\n        add_list(user_number, &numu, MAX_LIST, so());\n        if (mml_s) {\n          free(mml_s);\n          mml_s = nullptr;\n        }\n      }\n    }\n    break;\n    case 'E':\n      if (!numu) {\n        bout.nl();\n        bout.outstr(\"Need to specify some users first - use A or M\\r\\n\\n\");\n      } else {\n        multimail(user_number, numu);\n        done = true;\n      }\n      break;\n    case 'D':\n      if (numu) {\n\tbout.nl();\n\tfor (i = 0; i < numu; i++) {\n\t  User user;\n\t  a()->users()->readuser(&user, user_number[i]);\n\t  bout.print(\"{}. {}\\r\\n\", i + 1, a()->names()->UserName(user_number[i]));\n\t}\n        bout.nl();\n        bout.outstr(\"|#2Delete which? \");\n        bin.input(s, 2);\n        i = to_number<int>(s);\n        if ((i > 0) && (i <= numu)) {\n          --numu;\n          for (auto i1 = i - 1; i1 < numu; i1++) {\n            user_number[i1] = user_number[i1 + 1];\n          }\n        }\n      }\n      break;\n    case 'L':\n      bout.nl();\n      for (i = 0; i < numu; i++) {\n        User user;\n        a()->users()->readuser(&user, user_number[i]);\n        bout.print(\"{}. {}\\r\\n\", i + 1, a()->names()->UserName(user_number[i]));\n      }\n      break;\n    }\n    a()->CheckForHangup();\n  } while (!done);\n}\n"
  },
  {
    "path": "bbs/multmail.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_MULTMAIL_H__\n#define __INCLUDED_BBS_MULTMAIL_H__\n\nvoid multimail(int *user_number, int numu);\nvoid slash_e();\n\n#endif  // __INCLUDED_BBS_MULTMAIL_H__"
  },
  {
    "path": "bbs/netsup.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/netsup.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/wfc.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/numbers.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include \"sdk/net/binkp.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/callouts.h\"\n#include \"sdk/net/contact.h\"\n\n#include <chrono>\n#include <cstdint>\n#include <string>\n#include <vector>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr int MAX_CONNECTS = 1000;\n\n/** Returns a full path to exe under the WWIV_DIR */\nstatic std::string CreateNetworkBinary(const std::string& exe) {\n  std::ostringstream ss;\n  ss << FilePath(a()->bindir(), exe).string();\n#ifdef _WIN32\n  // CreateProcess is failing on Windows without the .exe extension, and since\n  // we don't use MakeAbsCmd on this, it's without .exe.\n  ss << \".exe\";\n#endif  // _WIN32\n  ss << \" --v=\" << a()->verbose();\n  ss << \" --bbsdir=\" << a()->bbspath().string();\n  ss << \" --bindir=\" << a()->bindir().string();\n  ss << \" --configdir=\" << a()->configdir().string();\n\n  return ss.str();\n}\n\nstruct CalloutEntry {\n  CalloutEntry(uint16_t o, int e) : node(o), net(e) {}\n  uint16_t node;\n  int net;\n};\n\nvoid cleanup_net() {\n  if (a()->nets().empty()) {\n    return;\n  }\n  if (a()->nets()[0].sysnum == 0 && wwiv::stl::ssize(a()->nets()) == 1) {\n    return;\n  }\n  a()->sess().hangup(true);\n  a()->sess().using_modem(false);\n  if (a()->sess().IsUserOnline()) {\n    hang_it_up();\n  }\n\n  for (int nNetNumber = 0;\n       nNetNumber < wwiv::stl::ssize(a()->nets());\n       nNetNumber++) {\n    set_net_num(nNetNumber);\n    const auto& net = a()->nets()[nNetNumber];\n    VLOG(2) << \"cleanup_net: Processing Network: \" << net.name;\n\n    if (!net.sysnum) {\n      VLOG(1) << \"Skipping network due to no sysnum: \" << net.name;\n      continue;\n    }\n\n    a()->ClearTopScreenProtection();\n\n    std::ostringstream ss;\n    ss << CreateNetworkBinary(\"networkc\");\n    ss << \" --quiet\";\n    ss << \" --process_instance=\" << a()->sess().instance_number();\n    ss << \" .\" << nNetNumber;\n    const auto networkc_cmd = ss.str();\n    wwiv::bbs::CommandLine cl(networkc_cmd);\n    VLOG(1) << \"Executing Network Command: '\" << cl.cmdline() << \"'\";\n    ExecuteExternalProgram(cl, EFLAG_NETPROG | EFLAG_NOHUP);\n    a()->status_manager()->reload_status();\n    a()->sess().SetCurrentReadMessageArea(-1);\n    a()->ReadCurrentUser(1);\n  }\n  a()->Cls();\n}\n\nstatic void do_callout(const Network& net, int sn) {\n  const Callout callout(net, a()->config()->max_backups());\n  Contact contact(net, false);\n  Binkp binkp(net.dir);\n\n  const auto* const callout_rec = callout.net_call_out_for(sn); // i con\n  if (callout_rec == nullptr) {\n    return;\n  }\n\n  const NetworkContact* contact_rec = contact.contact_rec_for(sn); // i2 ncn\n  if (!contact_rec) {\n    return;\n  }\n  auto const csne = next_system(callout_rec->sysnum);\n  if (!csne) {\n    return;\n  }\n\n  const auto cmd = StrCat(CreateNetworkBinary(\"network\"), \" -n\", sn, \" .\", a()->net_num());\n  bout.print(\"|#7Calling out to: |#2{} - {} @{}\\r\\n\", csne->name, net.name, sn);\n  if (contact_rec->bytes_waiting() > 0) {\n    bout.print(\"|#7Amount pending: |#2{}k\\r\\n\", bytes_to_k(contact_rec->bytes_waiting()));\n  }\n  bout.print(\"|#7Commandline is: |#2{}\\r\\n\", cmd);\n  bout.print(\"|#7{}|#0...\\r\\n\", std::string(80, '\\xCD'));\n  wwiv::bbs::CommandLine cl(cmd);\n  ExecuteExternalProgram(cl, EFLAG_NETPROG | EFLAG_NOHUP);\n  a()->status_manager()->reload_status();\n  cleanup_net();\n}\n\nvoid print_pending_list() {\n  int lines = 0;\n  auto ss = a()->user()->get_status();\n\n  if (a()->nets().empty()) {\n    return;\n  }\n  if (a()->nets()[0].sysnum == 0 && wwiv::stl::ssize(a()->nets()) == 1) {\n    return;\n  }\n\n  auto current_time = DateTime::now();\n\n  bout.nl(2);\n  bout.outstr(\"                           |#3-> |#9Network Status |#3<-\\r\\n\");\n  bout.nl();\n\n  bout.outstr(\"|#\"\n          \"7\\xDA\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC2\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xBF\\r\\n\");\n  bout.outstr(\"|#7\\xB3 |#1Ok? |#7\\xB3 |#1Network  |#7\\xB3 |#1 Node |#7\\xB3  |#1 Sent  \"\n          \"|#7\\xB3|#1Received |#7\\xB3|#1Ready |#7\\xB3|#1Fails|#7\\xB3  |#1Elapsed  |#7\\xB3|#7\\r\\n\");\n  bout.outstr(\"|#\"\n          \"7\\xC3\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC5\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xB4\\r\\n\");\n\n  for (const auto& net : a()->nets().networks()) {\n    if (!net.sysnum) {\n      continue;\n    }\n\n    Callout callout(net, a()->config()->max_backups());\n    Contact contact(net, false);\n\n    for (const auto& p : callout.callout_config()) {\n      const NetworkContact* r = contact.contact_rec_for(p.first);\n      if (!r) {\n        // skip\n        continue;\n      }\n      const auto& con = p.second;\n      if (con.options & options_hide_pend) {\n        // skip hidden ones.\n        continue;\n      }\n      if (!r->lastcontactsent() && !r->bytes_waiting()) {\n        // Skip ones without bytes waiting that we've not contacted recently.\n        continue;\n      }\n\n      std::string atc = allowed_to_call(con, DateTime::now()) ? \"|#5Yes\" : \"|#3---\";\n\n      std::string last_contact_sent{\"|#6     -    \"};\n      if (r->lastcontactsent()) {\n        const auto then = DateTime::from_time_t(r->lastcontactsent());\n        const auto diff = current_time.to_system_clock() - then.to_system_clock();\n        last_contact_sent = ctim(diff);\n      }\n\n      auto bsent = fmt::format(\"{}k\", (r->bytes_sent() + 1023) / 1024);\n      auto brec = fmt::format(\"{}k\", (r->bytes_received() + 1023) / 1024);\n      auto bwait = fmt::format(\"{}k\", (r->bytes_waiting() + 1023) / 1024);\n\n      bout.print(\n          \"|#7\\xB3 {:>3} |#7\\xB3 |#2{:<8} |#7\\xB3 |#2{:>5} |#7\\xB3|#2{:>8} |#7\\xB3|#2{:>8} \"\n          \"|#7\\xB3|#2{:>5} |#7\\xB3|#2{:>4} |#7\\xB3|#2{:>10} |#7\\xB3|#7\\r\\n\",\n          atc, net.name, r->systemnumber(), bsent, brec, bwait, r->numfails(),\n          last_contact_sent);\n      if (!a()->user()->pause() && lines++ == 20) {\n        bout.pausescr();\n        lines = 0;\n      }\n    }\n  }\n\n  for (const auto& net : a()->nets().networks()) {\n    if (!net.sysnum) {\n      continue;\n    }\n\n    File deadNetFile(FilePath(net.dir, DEAD_NET));\n    if (deadNetFile.Open(File::modeReadOnly | File::modeBinary)) {\n      const auto dead_net_file_size = deadNetFile.length();\n      deadNetFile.Close();\n      const auto deadk = fmt::format(\"{}k\", (dead_net_file_size + 1023) / 1024);\n      bout.print(\n          \"|#7\\xB3 |#3--- |#7\\xB3 |#2{:>8} |#7\\xB3 |#6DEAD! |#7\\xB3 |#2------- |#7\\xB3 \"\n          \"|#2------- |#7\\xB3|#2{:>5} |#7\\xB3|#2 --- |#7\\xB3 |#2--------- |#7\\xB3\\r\\n\",\n          net.name, deadk);\n    }\n  }\n\n  for (const auto& net : a()->nets().networks()) {\n    if (!net.sysnum) {\n      continue;\n    }\n\n    File checkNetFile(FilePath(net.dir, CHECK_NET));\n    if (checkNetFile.Open(File::modeReadOnly | File::modeBinary)) {\n      const auto check_net_file_size = checkNetFile.length();\n      checkNetFile.Close();\n      const auto checkk = fmt::format(\"{}k\", (check_net_file_size + 1023) / 1024);\n      bout.print(\n          \"|#7\\xB3 |#3--- |#7\\xB3 |#2{:>8} |#7\\xB3 |#6CHECK |#7\\xB3 |#2------- |#7\\xB3 \"\n          \"|#2------- |#7\\xB3|#2{:>5} |#7\\xB3|#2 --- |#7\\xB3 |#2--------- |#7\\xB3\\r\\n\",\n          net.name, checkk);\n    }\n  }\n\n  bout.outstr(\"|#\"\n          \"7\\xc0\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC1\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xD9\\r\\n\");\n  bout.nl();\n  a()->user()->SetStatus(ss);\n  if (bout.lines_listed()) {\n    bout.pausescr();\n  }\n}\n\nvoid gate_msg(net_header_rec* nh, char* messageText, int nNetNumber,\n              const std::string& subtype_or_author, std::vector<uint16_t> list, int nFromNetworkNumber) {\n  char newname[256], qn[200], on[200];\n  char nm[205];\n  int i;\n  const auto& from_net = a()->nets()[nFromNetworkNumber];\n  const auto& to_net = a()->nets()[nNetNumber];\n\n  if (strlen(messageText) >= 80) {\n    return;\n  }\n\n  auto* original_text = messageText;\n  messageText += strlen(original_text) + 1;\n  auto ntl = static_cast<uint16_t>(nh->length - strlen(original_text) - 1);\n  auto* ss = strchr(messageText, '\\r');\n  if (ss && (ss - messageText < 200) && (ss - messageText < ntl)) {\n    strncpy(nm, messageText, ss - messageText);\n    nm[ss - messageText] = 0;\n    ss++;\n    if (*ss == '\\n') {\n      ss++;\n    }\n    nh->length -= static_cast<uint32_t>(ss - messageText);\n    ntl = ntl - static_cast<uint16_t>(ss - messageText);\n    messageText = ss;\n\n    qn[0] = on[0] = '\\0';\n\n    if (nFromNetworkNumber == -1 || nh->fromsys == from_net.sysnum) {\n\n      strcpy(newname, nm);\n      ss = strrchr(newname, '@');\n      if (ss) {\n        sprintf(ss + 1, \"%u\", to_net.sysnum);\n        ss = strrchr(nm, '@');\n        if (ss) {\n          ++ss;\n          while (*ss >= '0' && *ss <= '9') {\n            ++ss;\n          }\n          strcat(newname, ss);\n        }\n        strcat(newname, \"\\r\\n\");\n        nh->fromsys = to_net.sysnum;\n      }\n    } else {\n      if (nm[0] == '`' && nm[1] == '`') {\n        for (i = wwiv::strings::ssize(nm) - 2; i > 0; i--) {\n          if (nm[i] == '`' && nm[i + 1] == '`') {\n            break;\n          }\n        }\n        if (i > 0) {\n          i += 2;\n          strncpy(qn, nm, i);\n          qn[i] = ' ';\n          qn[i + 1] = 0;\n        }\n      } else {\n        i = 0;\n      }\n      if (qn[0] == 0) {\n        ss = strrchr(nm, '#');\n        if (ss) {\n          if (ss[1] >= '0' && ss[1] <= '9') {\n            *ss = 0;\n            ss--;\n            while (ss > nm && *ss == ' ') {\n              *ss = 0;\n              ss--;\n            }\n          }\n        }\n        if (nm[0]) {\n          if (nh->fromuser) {\n            sprintf(qn, \"``%s`` \", nm);\n          } else {\n            strcpy(on, nm);\n          }\n        }\n      }\n      if (on[0] == 0 && nh->fromuser == 0) {\n        strcpy(on, nm + i);\n      }\n      if (from_net.sysnum == 1 && on[0] &&\n          from_net.type == network_type_t::internet) {\n        sprintf(newname, \"%s%s\", qn, on);\n      } else if (from_net.sysnum == 1 && on[0] &&\n                 from_net.type == network_type_t::news) {\n        sprintf(newname, \"%s%s\", qn, on);\n      }\n      else {\n        if (on[0]) {\n          sprintf(newname, \"%s%s@%u.%s\\r\\n\", qn, on, nh->fromsys,\n                  from_net.name.c_str());\n        } else {\n          sprintf(newname, \"%s#%u@%u.%s\\r\\n\", qn, nh->fromuser, nh->fromsys,\n                  from_net.name.c_str());\n        }\n      }\n      nh->fromsys = to_net.sysnum;\n      nh->fromuser = 0;\n    }\n\n    nh->length += strlen(newname);\n    if (nh->main_type == main_type_email_name || nh->main_type == main_type_new_post) {\n      nh->length += size_uint32(subtype_or_author) + 1;\n    }\n    const auto packet_filename = StrCat(to_net.dir, \"p1\", a()->network_extension());\n    File file(packet_filename);\n    if (file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      file.Seek(0L, File::Whence::end);\n      if (list.empty()) {\n        nh->list_len = 0;\n      }\n      if (nh->list_len) {\n        nh->tosys = 0;\n      }\n      file.Write(nh, sizeof(net_header_rec));\n      if (nh->list_len) {\n        file.Write(&list[0], sizeof(uint16_t) * (nh->list_len));\n      }\n      if (nh->main_type == main_type_email_name || nh->main_type == main_type_new_post) {\n        file.Write(subtype_or_author.c_str(), subtype_or_author.size() + 1);\n      }\n      file.Write(original_text, strlen(original_text) + 1);\n      file.Write(newname, strlen(newname));\n      file.Write(messageText, ntl);\n      file.Close();\n    }\n  }\n}\n\nstatic std::string to_difftime_string(daten_t now, daten_t then) {\n  if (then == 0) {\n    return fmt::format(\"{:<16}\", \"NEVER\");\n  }\n  const auto h = std::min<int>(999, static_cast<int>((now - then) / SECONDS_PER_HOUR));\n  const auto m = static_cast<int>(((now - then) % SECONDS_PER_HOUR) / 60);\n  const auto s = fmt::format(\"{}:{:0<2} Hrs\", h, m);\n  return fmt::format(\"{:<16}\", s);\n}\n\nstatic void print_call(uint16_t sn, const Network& net) {\n  static int color;\n  auto now = daten_t_now();\n\n  Callout callout(net, a()->config()->max_backups());\n  Contact contact(net, false);\n  Binkp binkp(net.dir);\n\n  const NetworkContact* ncn = contact.contact_rec_for(sn);\n  if (!ncn) {\n    return;\n  }\n  auto csne = next_system(sn);\n  if (!csne) {\n    return;\n  }\n\n  static auto got_color = false;\n  if (!got_color) {\n    got_color = true;\n    IniFile ini(FilePath(a()->bbspath(), WWIV_INI),\n                StrCat(\"WWIV-\", a()->sess().instance_number()), INI_TAG);\n    if (ini.IsOpen()) {\n      color = ini.value(\"CALLOUT_COLOR_TEXT\", 14);\n    }\n  }\n  auto s1 = humanize(ncn->bytes_waiting());\n  bout.localIO()->PutsXYA(58, 17, color, s1);\n\n  s1 = humanize(ncn->bytes_received());\n  bout.localIO()->PutsXYA(23, 17, color, s1);\n\n  s1 = humanize(ncn->bytes_sent());\n  bout.localIO()->PutsXYA(23, 18, color, s1);\n\n  s1 = to_difftime_string(now, ncn->firstcontact());\n  bout.localIO()->PutsXYA(23, 16, color, s1);\n\n  s1 = to_difftime_string(now, ncn->lastcontactsent());\n  bout.localIO()->PutsXYA(58, 16, color, s1);\n\n  s1 = to_difftime_string(now, ncn->lasttry());\n  bout.localIO()->PutsXYA(58, 15, color, s1);\n\n  const auto ncns = fmt::format(\"{:<16}\", ncn->numcontacts());\n  bout.localIO()->PutsXYA(23, 15, color,  ncns);\n  bout.localIO()->PutsXYA(41, 3, color, fmt::format(\"{:<30}\", csne->name, 30));\n  auto* binkp_node = binkp.binkp_session_config_for(csne->sysnum);\n  std::string hostname = csne->phone;\n  auto speed = StrCat(std::to_string(csne->speed), \" BPS\");\n  if (binkp_node != nullptr) {\n    // Use host:port is we have it.\n    hostname = StrCat(binkp_node->host, \":\", binkp_node->port);\n    speed = \"BinkP\";\n  }\n  bout.localIO()->PutsXYA(23, 19, color, fmt::format(\"{:<30}\", hostname));\n  bout.localIO()->PutsXYA(58, 18, color, fmt::format(\"{:<10}\", speed));\n  bout.localIO()->PutsXYA(14, 3, color, fmt::format(\"{:<16}\", a()->network_name()));\n}\n\nstatic void fill_call(int color, int row, const std::vector<CalloutEntry>& entries) {\n  int x = 0, y = 0;\n  char s1[6];\n\n  for (int i = row * 10; (i < ((row + 6) * 10)); i++) {\n    if (x > 69) {\n      x = 0;\n      y++;\n    }\n    if (i < size_int(entries)) {\n      sprintf(s1, \"%-5u\", wwiv::stl::at(entries, i).node);\n    } else {\n      strcpy(s1, \"     \");\n    }\n    bout.curatr(color);\n    bout.localIO()->PutsXY(6 + x, 5 + y, s1);\n    x += 7;\n  }\n}\n\nstatic std::pair<int, int> ansicallout() {\n  static auto callout_ansi = true;\n  static int color1, color2, color3, color4;\n  static auto got_info = false;\n  auto rownum = 0;\n  bout.localIO()->SetCursor(LocalIO::cursorNone);\n  if (!got_info) {\n    got_info = true;\n    color1 = 9;\n    color2 = 30;\n    color3 = 3;\n    color4 = 14;\n    IniFile ini(FilePath(a()->bbspath(), WWIV_INI),\n                StrCat(\"WWIV-\", a()->sess().instance_number()), INI_TAG);\n    if (ini.IsOpen()) {\n      callout_ansi = ini.value<bool>(\"CALLOUT_ANSI\");\n      color1 = ini.value(\"CALLOUT_COLOR\", color1);\n      color2 = ini.value(\"CALLOUT_HIGHLIGHT\", color2);\n      color3 = ini.value(\"CALLOUT_NORMAL\", color3);\n      color4 = ini.value(\"CALLOUT_COLOR_TEXT\", color4);\n      ini.Close();\n    }\n  }\n\n  if (!callout_ansi) {\n    bout.nl();\n    bout.cls();\n    bout.outstr(\"|#9Callout to which system? \");\n    auto sn = bin.input_number<uint16_t>(1, 1, 32767);\n    bout.localIO()->SetCursor(LocalIO::cursorNormal);\n    return std::make_pair(sn, -1);\n  }\n  int pos = 0, sn = 0, snn = 0;\n  std::vector<CalloutEntry> entries;\n  for (int nn = 0; nn < wwiv::stl::ssize(a()->nets()); nn++) {\n    set_net_num(nn);\n    const auto& net = a()->nets()[nn];\n    Callout callout(net, a()->config()->max_backups());\n    Contact contact(net, false);\n\n    const auto& nodemap = callout.callout_config();\n    for (const auto& p : nodemap) {\n      auto* const con = contact.contact_rec_for(p.first);\n      if (!con) {\n        continue;\n      }\n      if (!(p.second.options & options_hide_pend) && valid_system(p.second.sysnum)) {\n        entries.emplace_back(con->systemnumber(), nn);\n      }\n    }\n    if (entries.size() > MAX_CONNECTS) {\n      break;\n    }\n  }\n\n  if (entries.empty()) {\n    return std::make_pair<uint16_t, int>(0, -1);\n  }\n\n  a()->Cls();\n  bout.curatr(color1);\n  bout.localIO()->MakeLocalWindow(3, 2, 73, 10);\n  const auto header = StrCat(\"\\xC3\", std::string(71, '\\xC4'), \"\\xB4\");\n  bout.localIO()->PutsXYA(3, 4, color1, header);\n  bout.localIO()->MakeLocalWindow(3, 14, 73, 7);\n  bout.localIO()->PutsXYA(5, 3, color3, \"Network:\");\n  bout.localIO()->PutsXYA(31, 3, color3, \"BBS Name:\");\n  bout.localIO()->PutsXYA(5, 15, color3, \"# Connections   :\");\n  bout.localIO()->PutsXYA(5, 16, color3, \"First Contact   :\");\n  bout.localIO()->PutsXYA(5, 17, color3, \"KB Received     :\");\n  bout.localIO()->PutsXYA(5, 18, color3, \"KB Sent         :\");\n  bout.localIO()->PutsXYA(5, 19, color3, \"Address         :\");\n  bout.localIO()->PutsXYA(40, 15, color3, \"Last Attempt    :\");\n  bout.localIO()->PutsXYA(40, 16, color3, \"Last Contact    :\");\n  bout.localIO()->PutsXYA(40, 17, color3, \"KB Waiting      :\");\n  bout.localIO()->PutsXYA(40, 18, color3, \"Max Speed       :\");\n\n  fill_call(color4, rownum, entries);\n  int x = 0;\n  int y = 0;\n  bout.localIO()->PutsXYA(6, 5, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n  print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n\n  auto done = false;\n  do {\n    unsigned char ch = static_cast<unsigned char>(to_upper_case_char(bout.localIO()->GetChar()));\n    switch (ch) {\n    case ' ':\n    case RETURN:\n      sn = at(entries, pos).node;\n      snn = at(entries, pos).net;\n      done = true;\n      break;\n    case 'Q':\n    case ESC:\n      sn = 0;\n      snn = -1;\n      done = true;\n      break;\n    // Ignore warning of duplicate case\n    case 0xE0: // (-32 or 224) I don't know MS's CRT returns this on arrow keys....\n    case 0:\n      ch = to_upper_case_char(bout.localIO()->GetChar());\n      switch (ch) {\n      case RARROW: // right arrow\n        if (pos < size_int(entries) - 1 && x < 63) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos++;\n          x += 7;\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        }\n        break;\n      case LARROW: // left arrow\n        if (x > 0) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos--;\n          x -= 7;\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        }\n        break;\n      case UPARROW: // up arrow\n        if (y > 0) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos -= 10;\n          y--;\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        } else if (rownum > 0) {\n          pos -= 10;\n          rownum--;\n          fill_call(color4, rownum, entries);\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        }\n        break;\n      case DNARROW: // down arrow\n        if (y < 5 && pos + 10 < size_int(entries)) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos += 10;\n          y++;\n        } else if ((rownum + 6) * 10 < size_int(entries)) {\n          rownum++;\n          fill_call(color4, rownum, entries);\n          if (pos + 10 < size_int(entries)) {\n            pos += 10;\n          } else {\n            --y;\n          }\n        }\n        bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n        print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        break;\n      case HOME: // home\n        if (pos > 0) {\n          x = 0;\n          y = 0;\n          pos = 0;\n          rownum = 0;\n          fill_call(color4, rownum, entries);\n          bout.localIO()->PutsXYA(6, 5, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        } break;\n      case PAGEUP: // page up\n        if (y > 0) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos -= 10 * y;\n          y = 0;\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        } else {\n          if (rownum > 5) {\n            pos -= 60;\n            rownum -= 6;\n          } else {\n            pos -= 10 * rownum;\n            rownum = 0;\n          }\n          fill_call(color4, rownum, entries);\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        }\n        break;\n      case PAGEDN: // page down\n        if (y < 5) {\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color4, fmt::sprintf(\"%-5u\", entries[pos].node));\n          pos += 10 * (5 - y);\n          y = 5;\n          while (pos >= size_int(entries)) {\n            pos -= 10;\n            --y;\n          }\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        } else if ((rownum + 6) * 10 < size_int(entries)) {\n          for (int i1 = 0; i1 < 6; i1++) {\n            if ((rownum + 6) * 10 < size_int(entries)) {\n              rownum++;\n              pos += 10;\n            }\n          }\n          fill_call(color4, rownum, entries);\n          if (pos >= size_int(entries)) {\n            pos -= 10;\n            --y;\n          }\n          bout.localIO()->PutsXYA(6 + x, 5 + y, color2, fmt::sprintf(\"%-5u\", entries[pos].node));\n          print_call(entries[pos].node, a()->nets()[entries[pos].net]);\n        }\n        break;\n      }\n    }\n  } while (!done);\n\n  bout.curatr(color3);\n  a()->Cls();\n  bout.localIO()->SetCursor(LocalIO::cursorNormal);\n  return std::make_pair(sn, snn);\n}\n\nstatic int FindNetworkNumberForNode(int sn) {\n  for (auto net_number = 0; net_number < wwiv::stl::ssize(a()->nets()); net_number++) {\n    const auto net = a()->nets()[net_number];\n    if (Callout callout(net, a()->config()->max_backups()); callout.net_call_out_for(sn) != nullptr) {\n      return net_number;\n    }\n  }\n  return -1;\n}\n\nvoid force_callout() {\n  auto [system_number, network_number] = ansicallout();\n  if (system_number <= 0) {\n    return;\n  }\n  if (network_number < 0) {\n    network_number = FindNetworkNumberForNode(system_number);\n  }\n  if (network_number < 0) {\n    return;\n  }\n  const auto& net = a()->nets()[network_number];\n\n  set_net_num(network_number);\n  const Callout callout(net, a()->config()->max_backups());\n\n  if (!allowed_to_call(*callout.net_call_out_for(system_number), DateTime::now())) {\n    return;\n  }\n\n  a()->Cls();\n  do_callout(net, system_number);\n}\n"
  },
  {
    "path": "bbs/netsup.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_NETSUP_H\n#define INCLUDED_BBS_NETSUP_H\n\n#include <cstdint>\n#include <string>\n#include <vector>\n\nstruct net_header_rec;\n\nvoid cleanup_net();\nvoid print_pending_list();\nvoid gate_msg(net_header_rec* nh, char* messageText, int net_number, const std::string& author_name,\n              std::vector<uint16_t> list, int nFromNetworkNumber);\nvoid force_callout();\n\n#endif\n"
  },
  {
    "path": "bbs/newuser.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/newuser.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsovl2.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/bbsutl2.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/email.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/inetmsg.h\"\n#include \"bbs/inmsg.h\"\n#include \"bbs/lilo.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/trashcan.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/workspace.h\"\n#include \"core/clock.h\"\n#include \"core/inifile.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/phone_numbers.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include <chrono>\n#include <string>\n#include <sstream>\n\nusing std::chrono::milliseconds;\nusing wwiv::common::InputMode;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// Local function prototypes\n\nstatic bool CreateNewUserRecord();\n\nbool CanCreateNewUserAccountHere();\nvoid noabort(const char* file_name);\nbool check_zip(const std::string& zipcode, int mode);\nvoid VerifyNewUserPassword();\nvoid SendNewUserFeedbackIfRequired();\nvoid ExecNewUserCommand();\nvoid new_mail();\nbool CheckPasswordComplexity(User* pUser, std::string& password);\n\nvoid input_phone() {\n  bool ok = true;\n  std::string phoneNumber;\n  do {\n    bout.nl();\n    bout.outstr(\"|#3Enter your VOICE phone no. in the form:\\r\\n|#3 ###-###-####\\r\\n|#2:\");\n    phoneNumber = bin.input_phonenumber(a()->user()->voice_phone(), 12);\n    \n    ok = valid_phone(phoneNumber);\n    if (!ok) {\n      bout.nl();\n      bout.outstr(\"|#6Please enter a valid phone number in the correct format.\\r\\n\");\n    }\n  } while (!ok && !a()->sess().hangup());\n  if (!a()->sess().hangup()) {\n    a()->user()->voice_phone(phoneNumber);\n  }\n}\n\nvoid input_dataphone() {\n  bool ok = true;\n  do {\n    bout.nl();\n    bout.outstr(\"|#9Enter your DATA phone no. in the form. \\r\\n\");\n    bout.print(\"|#9 ###-###-#### - Press Enter to use [{}].\\r\\n\", a()->user()->voice_phone());\n    auto data_phone_number = bin.input_phonenumber(a()->user()->data_phone(), 12);\n    if (data_phone_number[0] == '\\0') {\n      data_phone_number = a()->user()->voice_phone();\n    }\n    ok = valid_phone(data_phone_number);\n\n    if (ok) {\n      a()->user()->data_phone(data_phone_number);\n    } else {\n      bout.nl();\n      bout.outstr(\"|#6Please enter a valid phone number in the correct format.\\r\\n\");\n    }\n  } while (!ok && !a()->sess().hangup());\n}\n\nstatic bool check_name(const std::string& user_name) {\n  if (user_name.length() == 0 || user_name[user_name.length() - 1] == 32 || user_name[0] < 65 ||\n      finduser(user_name) != 0 || user_name.find(\"@\") != std::string::npos ||\n      user_name.find(\"#\") != std::string::npos) {\n    return false;\n  }\n\n  Trashcan trashcan(*a()->config());\n  if (trashcan.IsTrashName(user_name)) {\n    LOG(INFO) << \"Trashcan name entered from IP: \" << bout.remoteIO()->remote_info().address\n              << \"; name: \" << user_name;\n    hang_it_up();\n    a()->Hangup();\n    return false;\n  }\n  return true;\n}\n\nvoid input_name() {\n  int count = 0;\n  bool ok = true;\n  do {\n    bout.nl();\n    if (!(a()->config()->sysconfig_flags() & sysconfig_allow_alias)) {\n      bout.outstr(\"|#3Enter your FULL REAL name.\\r\\n\");\n    } else {\n      bout.outstr(\"|#3Enter your full name, or your alias.\\r\\n\");\n    }\n    std::string temp_local_name = bin.input_upper(a()->user()->name(), 30);\n    ok = check_name(temp_local_name);\n    if (ok) {\n      a()->user()->set_name(temp_local_name);\n    } else {\n      bout.nl();\n      bout.outstr(\"|#6I'm sorry, you can't use that name.\\r\\n\");\n      ++count;\n      if (count == 3) {\n        hang_it_up();\n        a()->Hangup();\n      }\n    }\n  } while (!ok && !a()->sess().hangup());\n}\n\n// Function to check if both first and last names are entered\nbool containsFirstAndLastName(const std::string& name) {\n    std::istringstream stream(name);\n    std::string part;\n    int count = 0;\n    \n    while (stream >> part) {\n        ++count;\n    }\n    \n    return count >= 2;\n}\n\nvoid input_realname() {\n  if (a()->config()->sysconfig_flags() & sysconfig_allow_alias) {\n    do {\n      bout.nl();\n      bout.outstr(\"|#3Enter your FULL real name.\\r\\n\");\n      std::string temp_local_name = bin.input_proper(a()->user()->real_name(), 30);\n      if (temp_local_name.empty() || ((a()->config()->newuser_config().first_last_name_required == newuser_item_type_t::required) && !containsFirstAndLastName(temp_local_name) )) {\n        bout.nl();\n        bout.outstr(\"|#6Sorry, you must enter your FULL real name.\\r\\n\");\n      } else {\n        a()->user()->real_name(temp_local_name);\n      }\n    } while (a()->user()->real_name_or_empty().empty() && !a()->sess().hangup());\n  } \n}\n\nvoid input_callsign() {\n  bout.nl();\n  bout.outstr(\" |#3Enter your amateur radio callsign, or just hit <ENTER> if none.\\r\\n|#2:\");\n  const auto s = bin.input_upper(a()->user()->callsign(), 6);\n  a()->user()->callsign(s);\n}\n\nbool valid_phone(const std::string& phoneNumber) {\n  if (a()->config()->sysconfig_flags() & sysconfig_free_phone) {\n    return true;\n  }\n\n  if (!IsPhoneNumberUSAFormat(a()->user()) && !a()->user()->country().empty()) {\n    return true;\n  }\n  if (phoneNumber.length() != 12) {\n    return false;\n  }\n  if (phoneNumber[3] != '-' || phoneNumber[7] != '-') {\n    return false;\n  }\n  for (int i = 0; i < 12; i++) {\n    if (i != 3 && i != 7) {\n      if (phoneNumber[i] < '0' || phoneNumber[i] > '9') {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nvoid input_street() {\n  std::string street;\n  do {\n    bout.nl();\n    bout.outstr(\"|#3Enter your street address.\\r\\n\");\n    street = bin.input_proper(a()->user()->street(), 30);\n\n    if (street.empty()) {\n      bout.nl();\n      bout.outstr(\"|#6I'm sorry, you must enter your street address.\\r\\n\");\n    }\n  } while (street.empty() && !a()->sess().hangup());\n  if (!a()->sess().hangup()) {\n    a()->user()->street(street);\n  }\n}\n\nvoid input_city() {\n  std::string city;\n  do {\n    bout.nl();\n    bout.outstr(\"|#3Enter your city (i.e San Francisco). \\r\\n\");\n    city = bin.input_proper(a()->user()->city(), 30);\n\n    if (city.empty()) {\n      bout.nl();\n      bout.outstr(\"|#6I'm sorry, you must enter your city.\\r\\n\");\n    }\n  } while (city.empty() && !a()->sess().hangup());\n  a()->user()->city(city);\n}\n\nvoid input_state() {\n  std::string state;\n  do {\n    bout.nl();\n    if (iequals(a()->user()->country(), \"CAN\")) {\n      bout.outstr(\"|#3Enter your province (i.e. QC).\\r\\n\");\n    } else {\n      bout.outstr(\"|#3Enter your state (i.e. CA). \\r\\n\");\n    }\n    bout.outstr(\"|#2:\");\n    state = bin.input_upper(2);\n\n    if (state.empty()) {\n      bout.nl();\n      bout.outstr(\"|#6I'm sorry, you must enter your state or province.\\r\\n\");\n    }\n  } while (state.empty() && (!a()->sess().hangup()));\n  a()->user()->state(state);\n}\n\nvoid input_country() {\n  std::string country;\n  do {\n    bout.nl();\n    bout.outstr(\"|#9Enter your country.  Hit Enter for \\\"|#1USA|#9\\\"\\r\\n\");\n    bout.outstr(\"|#7: \");\n    country = bin.input_upper(3);\n    if (country.empty()) {\n      country = \"USA\";\n    }\n  } while (country.empty() && (!a()->sess().hangup()));\n  a()->user()->country(country);\n}\n\nvoid input_zipcode() {\n  std::string zipcode;\n  do {\n    int len = 7;\n    bout.nl();\n    if (iequals(a()->user()->country(), \"USA\")) {\n      bout.outstr(\"|#3Enter your zipcode as #####-#### \\r\\n\");\n      len = 10;\n    } else {\n      bout.outstr(\"|#3Enter your postal code as L#L-#L#\\r\\n\");\n      len = 7;\n    }\n    bout.outstr(\"|#2:\");\n    zipcode = bin.input_upper(len);\n\n    if (zipcode.empty()) {\n      bout.nl();\n      bout.outstr(\"|#6I'm sorry, you must enter your zipcode.\\r\\n\");\n    }\n  } while (zipcode.empty() && (!a()->sess().hangup()));\n  a()->user()->zip_code(zipcode);\n}\n\nvoid input_sex() {\n  bout.nl();\n  bout.outstr(\"|#2Your gender (M,F) :\");\n  a()->user()->gender(onek(\"MF\"));\n}\n\nvoid input_age(User* u) {\n  int y = 2000, m = 1, d = 1;\n  const auto dt = DateTime::now();\n\n  bout.nl();\n  do {\n    bout.nl();\n    y = (dt.year() - 30) / 100;\n    bout.outstr(\"|#2Year you were born: \");\n    y = bin.input_number<int>(y, 1900, static_cast<int>(dt.year() - 30));\n  } while (!a()->sess().hangup() && y < 1905);\n\n  do {\n    bout.nl();\n    bout.outstr(\"|#2Month you were born (1-12) : \");\n    m = bin.input_number<int>(u->birthday_month(), 1, 12);\n  } while (!a()->sess().hangup() && (m > 12 || m < 1));\n\n  do {\n    std::map<int, int> days_in_month = {\n        {1, 31}, {3, 31}, {4, 30},  {5, 31},  {6, 30},  {7, 31},\n        {8, 31}, {9, 30}, {10, 31}, {11, 30}, {12, 31},\n    };\n    if (isleap(y)) {\n      days_in_month[2] = 29;\n    } else {\n      days_in_month[2] = 28;\n    }\n    bout.nl();\n    bout.outstr(\"|#2Day of month you were born (1-31) : \");\n    d = bin.input_number<int>(u->birthday_mday(), 1, days_in_month.at(m));\n  } while (!a()->sess().hangup() && (d > 31 || d < 1));\n  u->birthday_mdy(m, d, y);\n  bout.nl();\n}\n\nvoid input_comptype() {\n  int ct = -1;\n\n  bool ok = true;\n  do {\n    bout.nl();\n    bout.outstr(\"Known computer types:\\r\\n\\n\");\n    int i = 0;\n    for (i = 1; !ctypes(i).empty(); i++) {\n      bout.print(\"{}. {}\", i, ctypes(i));\n    }\n    bout.nl();\n    bout.outstr(\"|#3Enter your computer type, or the closest to it (ie, Compaq -> IBM).\\r\\n\");\n    bout.outstr(\"|#2:\");\n    ct = bin.input_number(1, 1, i, false);\n    ok = true;\n    if (ct < 1 || ct > i) {\n      ok = false;\n    }\n  } while (!ok && !a()->sess().hangup());\n\n  a()->user()->computer_type(ct);\n  if (a()->sess().hangup()) {\n    a()->user()->computer_type(-1);\n  }\n}\n\nbool detect_screensize() { \n  if (const auto sso = bin.screen_size()) {\n    const auto& ss = sso.value();\n    if (ss.x != a()->user()->screen_width() || ss.y != a()->user()->screen_lines()) {\n      bout.print(\"|#9Screen size of |#2{}|#9x|#2{} |#9detected.  Use it?\", ss.x, ss.y);\n      if (bin.noyes()) {\n        a()->user()->screen_width(ss.x);\n        a()->user()->screen_lines(ss.y);\n        a()->sess().num_screen_lines(ss.y);\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvoid input_screensize() {\n  if (detect_screensize()) {\n    return;\n  }\n\n  bout.nl();\n  bout.outstr(\"|#9How wide is your screen : \");\n  const auto x = bin.input_number(a()->user()->screen_width(), 40, 160, true);\n  bout.outstr(\"|#9How tall is your screen : \");\n  const auto y = bin.input_number(a()->user()->screen_lines(), 20, 100, true);\n  a()->user()->screen_width(x);\n  a()->user()->screen_lines(y);\n  a()->sess().num_screen_lines(y);\n}\n\nbool CheckPasswordComplexity(User*, std::string& password) {\n  if (password.length() < 3) {\n    // TODO - the min length should be in wwiv.ini\n    return false;\n  }\n  return true;\n}\n\nvoid input_pw(User* pUser) {\n  std::string password;\n  bool ok = true;\n  do {\n    ok = true;\n    password.clear();\n    bout.nl();\n    password = bin.input_password(\"|#3Please enter a new password, 3-8 chars.\\r\\n\", 8);\n\n    if (!CheckPasswordComplexity(pUser, password)) {\n      ok = false;\n      bout.nl(2);\n      bout.outstr(\"Invalid password.  Try again.\\r\\n\\n\");\n    }\n  } while (!ok && !a()->sess().hangup());\n\n  if (ok) {\n    pUser->password(password);\n  } else {\n    bout.outstr(\"Password not changed.\\r\\n\");\n  }\n}\n\nvoid input_ansistat() {\n  a()->user()->clear_flag(User::flag_ansi);\n  a()->user()->clear_flag(User::status_color);\n  bout.nl();\n  if (check_ansi() == 1) {\n    bout.outstr(\"ANSI graphics support detected.  Use it? \");\n  } else {\n    bout.outstr(\"\u001b[0;34;3mTEST\u001b[C\");\n    bout.outstr(\"\u001b[0;30;45mTEST\u001b[C\");\n    bout.outstr(\"\u001b[0;1;31;44mTEST\u001b[C\");\n    bout.outstr(\"\u001b[0;32;7mTEST\u001b[C\");\n    bout.outstr(\"\u001b[0;1;5;33;46mTEST\u001b[C\");\n    bout.outstr(\"\u001b[0;4mTEST\u001b[0m\\r\\n\");\n    bout.outstr(\"Is the above line colored, italicized, bold, inversed, or blinking? \");\n  }\n  if (bin.noyes()) {\n    a()->user()->set_flag(User::flag_ansi);\n    bout.nl();\n    bout.outstr(\"|#5Do you want color? \");\n    if (bin.noyes()) {\n      a()->user()->set_flag(User::status_color);\n      a()->user()->set_flag(User::extraColor);\n    } else {\n      color_list();\n      bout.nl();\n      bout.outstr(\"|#2Monochrome base color (<C/R>=7)? \");\n      char ch = onek(\"\\r123456789\");\n      if (ch == '\\r') {\n        ch = '7';\n      }\n      int c = ch - '0';\n      int c2 = c << 4;\n      for (int i = 0; i < 10; i++) {\n        if ((a()->user()->bwcolor(i) & 0x70) == 0) {\n          a()->user()->bwcolor(i, (a()->user()->bwcolor(i) & 0x88) | c);\n        } else {\n          a()->user()->bwcolor(i, (a()->user()->bwcolor(i) & 0x88) | c2);\n        }\n      }\n    }\n  }\n}\n\n// Inserts a record into NAMES.LST\nstatic void InsertSmallRecord(StatusMgr& sm, Names& names, int user_number, const char* name) {\n  sm.Run([&](Status& s) {\n    names.Add(name, user_number);\n    names.Save();\n    s.increment_num_users();\n    s.increment_filechanged(Status::file_change_names);\n  });\n}\n\nstatic int find_new_usernum(const User* pUser, uint32_t* qscn) {\n  File userFile(FilePath(a()->config()->datadir(), USER_LST));\n  for (int i = 0; !userFile.IsOpen() && (i < 20); i++) {\n    if (!userFile.Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile)) {\n      sleep_for(milliseconds(100));\n    }\n  }\n  if (!userFile.IsOpen()) {\n    return -1;\n  }\n\n  int nNewUserNumber = static_cast<int>((userFile.length() / a()->config()->userrec_length()) - 1);\n  userFile.Seek(a()->config()->userrec_length(), File::Whence::begin);\n  int user_number = 1;\n\n  if (nNewUserNumber == a()->status_manager()->user_count()) {\n    user_number = nNewUserNumber + 1;\n  } else {\n    while (user_number <= nNewUserNumber) {\n      if (user_number % 25 == 0) {\n        userFile.Close();\n        for (int n = 0; !userFile.IsOpen() && (n < 20); n++) {\n          if (!userFile.Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile)) {\n            sleep_for(milliseconds(100));\n          }\n        }\n        if (!userFile.IsOpen()) {\n          return -1;\n        }\n        userFile.Seek(static_cast<File::size_type>(user_number * a()->config()->userrec_length()),\n                      File::Whence::begin);\n        nNewUserNumber =\n            static_cast<int>((userFile.length() / a()->config()->userrec_length()) - 1);\n      }\n      User tu;\n      userFile.Read(&tu.data, a()->config()->userrec_length());\n\n      if (tu.deleted() && tu.sl() != 255) {\n        userFile.Seek(static_cast<File::size_type>(user_number * a()->config()->userrec_length()),\n                      File::Whence::begin);\n        userFile.Write(&pUser->data, a()->config()->userrec_length());\n        userFile.Close();\n        write_qscn(user_number, qscn, false);\n        InsertSmallRecord(*a()->status_manager(), *a()->names(), user_number, pUser->GetName());\n        return user_number;\n      }\n      user_number++;\n    }\n  }\n\n  if (user_number <= a()->config()->max_users()) {\n    userFile.Seek(static_cast<File::size_type>(user_number * a()->config()->userrec_length()),\n                  File::Whence::begin);\n    userFile.Write(&pUser->data, a()->config()->userrec_length());\n    userFile.Close();\n    write_qscn(user_number, qscn, false);\n    InsertSmallRecord(*a()->status_manager(), *a()->names(), user_number, pUser->GetName());\n    return user_number;\n  } else {\n    userFile.Close();\n    return -1;\n  }\n}\n\n// Clears a()->user()'s data and makes it ready to be a new user, also\n// clears the QScan pointers\nstatic bool CreateNewUserRecord() {\n  a()->sess().ResetQScanPointers(*a()->config());\n\n  auto* u = a()->user();\n  a()->reset_effective_sl();\n\n  const auto ok =\n      User::CreateNewUserRecord(u, a()->config()->newuser_sl(), a()->config()->newuser_dsl(),\n                                a()->config()->newuser_restrict(), a()->config()->newuser_gold(),\n                                a()->newuser_colors, a()->newuser_bwcolors);\n  u->CreateRandomPassword();\n  return ok;\n}\n\n// returns true if the user is allow to create a new user account\n// on here, if this function returns false, a sufficient error\n// message has already been displayed to the user.\nbool CanCreateNewUserAccountHere() {\n  if (a()->status_manager()->user_count() >= a()->config()->max_users()) {\n    bout.nl(2);\n    bout.outstr(\"I'm sorry, but the system currently has the maximum number of users it can\\r\\nhandle.\\r\\n\\n\");\n    return false;\n  }\n\n  if (a()->config()->closed_system()) {\n    bout.nl(2);\n    bout.outstr(\"I'm sorry, but the system is currently closed, and not accepting new users.\\r\\n\\n\");\n    return false;\n  }\n\n  if (!a()->config()->newuser_password().empty() && a()->sess().incom()) {\n    bout.nl(2);\n    bool ok = false;\n    int nPasswordAttempt = 0;\n    do {\n      auto password = bin.input_password(\"New User Password: \", 20);\n      if (password == a()->config()->newuser_password()) {\n        ok = true;\n      } else {\n        sysoplog(StrCat(\"Wrong newuser password: \", password));\n      }\n    } while (!ok && !a()->sess().hangup() && (nPasswordAttempt++ < 4));\n    if (!ok) {\n      return false;\n    }\n  }\n  return true;\n}\n\nvoid DoNewUserASV() {\n  IniFile ini(FilePath(a()->bbspath(), WWIV_INI),\n              StrCat(\"WWIV-\", a()->sess().instance_number()), INI_TAG);\n  if (!ini.IsOpen()) {\n    return;\n  }\n  // TODO(rushfan) : Fix this, it's clearly broken\"\n  //const auto asv_num = ini.value<int>(\"SIMPLE_ASV_NUM\", 0);\n  if (a()->HasConfigFlag(OP_FLAGS_SIMPLE_ASV) && a()->asv.sl > a()->config()->newuser_sl() &&\n      a()->asv.sl < 90) {\n    bout.nl();\n    bout.outstr(\"|#5Are you currently a WWIV SysOp? \");\n    if (bin.yesno()) {\n      bout.nl();\n      bout.outstr(\"|#5Please enter your BBS name and number.\\r\\n\");\n      const auto note = bin.input_text(60);\n      a()->user()->note(note);\n      a()->user()->sl(a()->asv.sl);\n      a()->user()->dsl(a()->asv.dsl);\n      a()->user()->ar_int(a()->asv.ar);\n      a()->user()->dar_int(a()->asv.dar);\n      a()->user()->exempt(a()->asv.exempt);\n      a()->user()->restriction(a()->asv.restrict);\n      bout.nl();\n      bout.printfile(ASV_NOEXT);\n      bout.nl();\n      bout.pausescr();\n    }\n  }\n}\n\nstatic void add_phone_number(int usernum, const std::string& phone) {\n  if (phone.find(\"000-\") != std::string::npos) {\n    return;\n  }\n\n  PhoneNumbers pn(*a()->config());\n  if (!pn.IsInitialized()) {\n    return;\n  }\n\n  pn.insert(usernum, phone);\n}\n\nvoid WriteNewUserInfoToSysopLog() {\n  const auto* u = a()->user();\n  sysoplog(\"** New User Information **\");\n  sysoplog(fmt::format(\"-> {} #{} ({})\", u->name(), a()->sess().user_num(), u->real_name_or_empty()));\n  if (a()->config()->newuser_config().use_address_street != newuser_item_type_t::unused) {\n    sysoplog(StrCat(\"-> \", u->street()));\n  }\n  if (a()->config()->newuser_config().use_address_city_state != newuser_item_type_t::unused) {\n    sysoplog(fmt::format(\"-> {}, {} {}  ({})\", u->city(), u->state(), u->zip_code(), u->country()));\n  }\n  if (a()->config()->newuser_config().use_voice_phone != newuser_item_type_t::unused) {\n    sysoplog(fmt::format(\"-> {} (Voice)\", u->voice_phone()));\n    if (!u->voice_phone().empty()) {\n      add_phone_number(a()->sess().user_num(), u->voice_phone());\n    }\n  }\n  if (a()->config()->newuser_config().use_data_phone != newuser_item_type_t::unused) {\n    sysoplog(fmt::format(\"-> {} (Data)\", u->data_phone()));\n    if (!u->data_phone().empty()) {\n      add_phone_number(a()->sess().user_num(), u->data_phone());\n    }\n  }\n  if (a()->config()->newuser_config().use_birthday != newuser_item_type_t::unused) {\n    sysoplog(fmt::format(\"-> {} ({} yr old {})\", u->birthday_mmddyy(), u->age(), u->gender()));\n  }\n  if (a()->config()->newuser_config().use_computer_type != newuser_item_type_t::unused) {\n    sysoplog(fmt::format(\"-> Using a {} Computer\", ctypes(u->computer_type())));\n  }\n  if (u->wwiv_regnum()) {\n    sysoplog(fmt::format(\"-> WWIV Registration # {}\", u->wwiv_regnum()));\n  }\n  sysoplog(\"********\");\n\n}\n\nvoid VerifyNewUserPassword() {\n  bool ok = false;\n  do {\n    bout.nl(2);\n    bout.print(\"|#9Your User Number: |#2{}\\r\\n\", a()->sess().user_num());\n    bout.print(\"|#9Your Password:    |#2{}\\r\\n\", a()->user()->password());\n    bout.nl(1);\n    bout.outstr(\"|#9Please write down this information, and enter your password for verification.\\r\\n\");\n    bout.outstr(\"|#9You will need to know this password in order to change it to something else.\\r\\n\\n\");\n    const auto password = bin.input_password(bout.lang().value(\"PW_PROMPT\"), 8);\n    if (password == a()->user()->password()) {\n      ok = true;\n    }\n  } while (!ok && !a()->sess().hangup());\n}\n\nvoid SendNewUserFeedbackIfRequired() {\n  if (!a()->sess().incom()) {\n    return;\n  }\n\n  if (a()->config()->sysconfig_flags() & sysconfig_no_newuser_feedback) {\n    // If NEWUSER_FEEDBACK=N don't attempt to send newuser feedback.\n    return;\n  }\n\n  bout.printfile(FEEDBACK_NOEXT);\n  feedback(true);\n  if (a()->HasConfigFlag(OP_FLAGS_FORCE_NEWUSER_FEEDBACK)) {\n    if (!a()->user()->email_sent() && !a()->user()->feedback_sent()) {\n      bout.printfile(NOFBACK_NOEXT);\n      a()->users()->delete_user(a()->sess().user_num());\n      a()->Hangup();\n    }\n  }\n}\n\nvoid ExecNewUserCommand() {\n  if (!a()->sess().hangup() && !a()->newuser_cmd.empty()) {\n    wwiv::bbs::CommandLine cl(a()->newuser_cmd);\n    cl.args(create_chain_file());\n\n    // Log what is happening here.\n    sysoplog(false, \"Executing New User Event: \");\n    sysoplog(cl.cmdline());\n\n    a()->WriteCurrentUser();\n    ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_NEWUSER));\n    a()->ReadCurrentUser();\n  }\n}\n\n\n/**\n * Takes an input string and reduces repeated spaces in the string to one space.\n */\nvoid single_space(char* text) {\n  if (!text || !*text) {\n    return;\n  }\n  char* pInputBuffer = text;\n  char* pOutputBuffer = text;\n  int i = 0;\n  int cnt = 0;\n\n  while (*pInputBuffer) {\n    if (isspace(*pInputBuffer) && cnt) {\n      pInputBuffer++;\n    } else {\n      if (!isspace(*pInputBuffer)) {\n        cnt = 0;\n      } else {\n        *pInputBuffer = ' ';\n        cnt = 1;\n      }\n      pOutputBuffer[i++] = *pInputBuffer++;\n    }\n  }\n  pOutputBuffer[i] = '\\0';\n}\n\nbool check_zip(const std::string& zipcode, int mode) {\n  char city[81], state[21];\n\n  if (zipcode.empty()) {\n    return false;\n  }\n\n  auto ok = true;\n  auto found = false;\n\n  const auto zipcity_dir = FilePath(a()->config()->datadir(), ZIPCITY_DIR);\n  const auto fn = fmt::format(\"zip{}.dat\", zipcode.front());\n\n  TextFile zip_file(FilePath(zipcity_dir, fn), \"r\");\n  if (!zip_file.IsOpen()) {\n    ok = false;\n    if (mode != 2) {\n      bout.print(\"\\r\\n|#6{} not found\\r\\n\", FilePath(zipcity_dir, fn).string());\n    }\n  } else {\n    char zip_buf[81];\n    while ((zip_file.ReadLine(zip_buf, 80)) && !found && !a()->sess().hangup()) {\n      single_space(zip_buf);\n      if (strncmp(zip_buf, zipcode.c_str(), 5) == 0) {\n        found = true;\n        auto ss = strtok(zip_buf, \" \");\n        ss = strtok(nullptr, \" \");\n        StringTrim(ss);\n        strcpy(state, ss);\n        ss = strtok(nullptr, \"\\r\\n\");\n        StringTrim(ss);\n        strncpy(city, ss, 30);\n        city[31] = '\\0';\n        properize(city);\n      }\n    }\n    zip_file.Close();\n  }\n\n  if (mode != 2 && !found) {\n    bout.nl();\n    bout.print(\"|#6No match for {}.\", zipcode);\n    ok = false;\n  }\n\n  if (!mode && found) {\n    bout.print(\"\\r\\n|#2{} is in {}, {}.\", zipcode, city, state);\n    ok = false;\n  }\n\n  if (found) {\n    if (mode != 2) {\n      bout.print(\"\\r\\n|#2{}, {}  USA? (y/N): \", city, state);\n      if (bin.yesno()) {\n        a()->user()->city(city);\n        a()->user()->state(state);\n        a()->user()->country(\"USA\");\n      } else {\n        bout.nl();\n        bout.outstr(\"|#6My records show differently.\\r\\n\\n\");\n        ok = false;\n      }\n    } else {\n      a()->user()->city(city);\n      a()->user()->state(state);\n      a()->user()->country(\"USA\");\n    }\n  }\n  return ok;\n}\n\n\nvoid noabort(const char* file_name) {\n  bool oic = false;\n\n  if (a()->sess().using_modem()) {\n    oic = a()->sess().incom();\n    a()->sess().incom(false);\n    bout.dump();\n  }\n  bout.printfile(file_name);\n  if (a()->sess().using_modem()) {\n    bout.dump();\n    a()->sess().incom(oic);\n  }\n}\n\nstatic void cln_nu() {\n  bout.RestorePosition();\n  bout.ansic(0);\n  bout.clreol();\n}\n\n/////////////////////////////////////////////////////////////////////////////\n\nenum class NewUserItemResult { success, no_change, need_redraw };\n\nclass NewUserContext {\npublic:\n  NewUserContext(char l, User& u, newuser_item_type_t i, bool f) : letter(l), user(u), item_type(i), first(f) {}\n  char letter;\n  User& user;\n  newuser_item_type_t item_type;\n  bool first{true};\n};\n\ntypedef std::function<NewUserItemResult(NewUserContext&)> newuser_item_fn;\nclass NewUserItem {\npublic:\n  NewUserItem(newuser_item_fn f, newuser_item_type_t s) : fn(std::move(f)), state(s) {}\n  newuser_item_fn fn;\n  newuser_item_type_t state;\n};\n\nNewUserItemResult DoNameOrHandle(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Name (alias or real)    : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto temp_name = bin.input_upper(c.user.name(), 30);\n    if (check_name(temp_name)) {\n      c.user.set_name(temp_name);\n      break;\n    }\n    cln_nu();\n    BackPrint(\"I'm sorry, you can't use that name.\", 6, 20, 1000);\n  }\n  cln_nu();\n  bout.print(\"|#2{}\", c.user.name());\n  bout.nl();\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoRealName(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Real Name               : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto temp_name = bin.input_proper(c.user.real_name_or_empty(), 30);\n    if (!temp_name.empty() || c.item_type != newuser_item_type_t::required) {\n      c.user.real_name(temp_name);\n      break;\n    }\n    cln_nu();\n    BackPrint(\"I'm sorry, you can't use that name.\", 6, 20, 1000);\n  }\n  cln_nu();\n  bout.print(\"|#2{}\", c.user.real_name());\n  bout.nl();\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoBirthDay(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Birth Date (MM/DD/YYYY) : \", c.letter);\n  bout.SavePosition();\n  if (c.user.age() == 0 && c.first) {\n    bool ok = false;\n    bout.SavePosition();\n    do {\n      ok = false;\n      cln_nu();\n      auto s = bin.input_date_mmddyyyy(\"\");\n      if (s.size() == 10) {\n        auto m = to_number<int>(s.substr(0, 2));\n        auto d = to_number<int>(s.substr(3, 2));\n        auto y = to_number<int>(s.substr(6, 4));\n        ok = true;\n        SystemClock clock{};\n        if ((((m == 2) || (m == 9) || (m == 4) || (m == 6) || (m == 11)) && (d >= 31)) ||\n            ((m == 2) && (((!isleap(y)) && (d == 29)) || (d == 30))) ||\n            (years_old(m, d, y, clock) < 5) || (d > 31) || ((m == 0) || (y == 0) || (d == 0))) {\n          ok = false;\n        }\n        if (m > 12) {\n          ok = false;\n        }\n        if (ok) {\n          c.user.birthday_mdy(m, d, y);\n          cln_nu();\n          bout.print(\"|#2{} ({} years old)\\r\\n\", c.user.birthday_month_dd_yyyy(), c.user.age());\n          return NewUserItemResult::success;\n        }\n      }\n      cln_nu();\n      BackPrint(\"Invalid Birthdate.\", 6, 20, 1000);\n      if (c.item_type != newuser_item_type_t::required) {\n        ok = true;\n      }\n    } while (!ok && !a()->sess().hangup());\n  } \n  bout.print(\"|#2{} ({} years old)\\r\\n\", c.user.birthday_month_dd_yyyy(), c.user.age());\n  return NewUserItemResult::no_change;\n}\n\n// TODO(rushfan): This needs updating, maybe add option to quit, system defined items?\nNewUserItemResult DoGender(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Sex (Gender)            : \", c.letter);\n  bout.SavePosition();\n  if (c.user.gender() != 'M' && c.user.gender() != 'F') {\n    bout.mpl(1);\n    c.user.gender(onek_ncr(\"MF\"));\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.gender() == 'M' ? \"Male\" : \"Female\");\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoCountry(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Country                 : \", c.letter);\n  bout.SavePosition();\n  if (c.first) {\n    auto country = bin.input_upper(c.user.country(), 3);\n    if (!country.empty()) {\n      c.user.country(country);\n    } else {\n      c.user.country(\"USA\");\n    }\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.country());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoZipCode(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) ZIP or Postal Code      : \", c.letter);\n  bout.SavePosition();\n  if (c.user.zip_code().empty() && c.first) {\n    bool ok = false;\n    do {\n      if (iequals(c.user.country(), \"USA\")) {\n        auto zip = bin.input_upper(c.user.zip_code(), 5);\n        check_zip(zip, 2);\n        c.user.zip_code(zip);\n      } else {\n        auto zip = bin.input_upper(c.user.zip_code(), 7);\n        c.user.zip_code(zip);\n      }\n      cln_nu();\n      if (!c.user.zip_code().empty() || c.item_type != newuser_item_type_t::required) {\n        ok = true;\n      }\n    } while (!ok && !a()->sess().hangup());\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.zip_code());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoStreet(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Street Address          : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto st = bin.input_proper(c.user.street(), 30);\n    if (!st.empty() || c.item_type != newuser_item_type_t::required) {\n      c.user.street(st);\n      break;\n    }\n    cln_nu();\n    BackPrint(\"I'm sorry, you must enter your street address.\", 6, 20, 1000);\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.street());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoCityState(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) City                    : \", c.letter);\n  bout.SavePosition();\n  if (c.user.city().empty() && c.first) {\n    bool ok = false;\n    do {\n      auto city = bin.input_proper(c.user.city(), 30);\n      if (!city.empty() || c.item_type != newuser_item_type_t::required) {\n        c.user.city(city);\n        ok = true;\n      }\n    } while (!ok && !a()->sess().hangup());\n    c.user.city(properize(c.user.city()));\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.city());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoState(NewUserContext& c) {\n\n  bout.print(\"|#1{:c}|#9) State                   : \", c.letter);\n  bout.SavePosition();\n  if (c.user.state().empty() && c.first) {\n    bool ok = false;\n    do {\n      ok = false;\n      if (auto state = bin.input_upper(c.user.state(), 2); !state.empty() || c.item_type != newuser_item_type_t::required) {\n         c.user.state(state);\n         ok = true;\n        }\n        bout.RestorePosition();\n      } while (!ok && !a()->sess().hangup());\n    }\n\n  \n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.state());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoEmailAddress(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Internet Mail Address   : \", c.letter);\n  bout.SavePosition();\n  bool done = false;\n  while (!done && c.first) {\n    c.user.email_address(bin.input_text(c.user.email_address(), 44));\n    if (!check_inet_addr(c.user.email_address())) {\n      cln_nu();\n      BackPrint(\"Invalid address!\", 6, 20, 1000);\n      c.user.email_address(\"\");\n    }\n    if (c.item_type != newuser_item_type_t::required || !c.user.email_address().empty()) {\n      done = true;\n    }\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.email_address());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoVoicePhone(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Voice Phone             : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto phoneNumber = bin.input_phonenumber(c.user.voice_phone(), 12);\n    if (valid_phone(phoneNumber)) {\n      c.user.voice_phone(phoneNumber);\n      break;\n    }\n    if (!c.user.voice_phone().empty()  || c.item_type != newuser_item_type_t::required) {\n      break;\n    }\n    cln_nu();\n    BackPrint(\"I'm sorry, you can't use that phone number.\", 6, 20, 1000);\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.voice_phone());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoDataPhone(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Data Phone              : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto phoneNumber = bin.input_phonenumber(c.user.data_phone(), 12);\n    if (valid_phone(phoneNumber)) {\n      c.user.data_phone(phoneNumber);\n      break;\n    }\n    if (!c.user.data_phone().empty()  || c.item_type != newuser_item_type_t::required) {\n      break;\n    }\n    cln_nu();\n    BackPrint(\"I'm sorry, you can't use that phone number.\", 6, 20, 1000);\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.data_phone());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoCallsign(NewUserContext& c) {\n  bout.print(\"|#1{:c}|#9) Callsign                : \", c.letter);\n  bout.SavePosition();\n  while (!a()->sess().hangup() && c.first) {\n    bout.SavePosition();\n    const auto s = bin.input_upper(c.user.callsign(), 6);\n    if (!s.empty() || c.item_type != newuser_item_type_t::required) {\n      c.user.callsign(s);\n      break;\n    }\n    cln_nu();\n  }\n  cln_nu();\n  bout.print(\"|#2{}\\r\\n\", c.user.callsign());\n  return NewUserItemResult::success;\n}\n\nNewUserItemResult DoComputerType(NewUserContext& c) {\n  int ct = -1;\n\n  std::string computer_type = c.user.computer_type() >= 0 ? ctypes(c.user.computer_type()) : \"Unknown\";\n  if (c.user.computer_type() >= 0 || !c.first) {\n    bout.print(\"|#1{:c}|#9) Computer Type           : |#2{}\\r\\n\", c.letter, computer_type);\n    return NewUserItemResult::no_change;\n  }\n  bool ok = true;\n  do {\n    bout.cls();\n    bout.litebar(\"Known computer types: \");\n    int i = 0;\n    for (i = 1; !ctypes(i).empty(); i++) {\n      bout.print(\"{}. {}\\r\\n\", i, ctypes(i));\n    }\n    bout.nl();\n    bout.outstr(\"|#9Enter your computer type, or the closest to it (ie, Compaq -> IBM).\\r\\n\");\n    bout.outstr(\"|#9: \");\n    ct = bin.input_number(1, 1, i, false);\n    ok = true;\n    if (ct < 1 || ct > i) {\n      ok = false;\n    }\n  } while (!ok && !a()->sess().hangup());\n\n  c.user.computer_type(ct);\n  return NewUserItemResult::need_redraw;\n}\n\nvoid NewUserDataEntry(const newuser_config_t& nc) {\n  auto& u = *a()->user();\n\n  bout.newline = false;\n  const auto saved_topdata = bout.localIO()->topdata();\n  bout.localIO()->topdata(wwiv::local::io::LocalIO::topdata_t::none);\n  a()->UpdateTopScreen();\n  auto letter = 'A';\n  std::map<char, NewUserItem> nu_items;\n  std::map<char, std::function<void(User&)>> clr_items;\n\n  nu_items.try_emplace(letter, DoNameOrHandle, newuser_item_type_t::required);\n  ++letter;\n  if (nc.use_real_name != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoRealName, nc.use_real_name);\n    ++letter;\n  }\n  if (nc.use_birthday != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoBirthDay, nc.use_birthday);\n    clr_items.try_emplace(letter, [](User& u) { u.birthday_mdy(0, 0, 0); });\n    ++letter;\n  }\n  if (nc.use_voice_phone != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoVoicePhone, nc.use_voice_phone);\n    ++letter;\n  }\n  if (nc.use_data_phone != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoDataPhone, nc.use_data_phone);\n    ++letter;\n  }\n  if (nc.use_callsign != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoCallsign, nc.use_callsign);\n    ++letter;\n  }\n  if (nc.use_gender != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoGender, nc.use_gender);\n    clr_items.try_emplace(letter, [](User& u) { u.gender('N'); });\n    ++letter;\n  }\n  if (nc.use_address_country != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoCountry, nc.use_address_country);\n    clr_items.try_emplace(letter, [](User& u) { u.country(\"\"); });\n    ++letter;\n  }\n  if (nc.use_address_zipcode != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoZipCode, nc.use_address_zipcode);\n    clr_items.try_emplace(letter, [](User& u) { u.zip_code(\"\"); });\n    ++letter;\n  }\n  if (nc.use_address_street != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoStreet, nc.use_address_street);\n    ++letter;\n  }\n  if (nc.use_address_city_state != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoCityState, nc.use_address_city_state);\n    clr_items.try_emplace(letter, [](User& u) { u.city(\"\"); });\n    ++letter;\n  }\n  if (nc.use_address_city_state != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoState, nc.use_address_city_state);\n    clr_items.try_emplace(letter, [](User& u) { u.state(\"\"); });\n    ++letter;\n  }\n  if (nc.use_email_address != newuser_item_type_t::unused) {\n    nu_items.try_emplace(letter, DoEmailAddress, nc.use_email_address);\n    ++letter;\n  }\n  if (nc.use_computer_type != newuser_item_type_t::unused) {\n    u.computer_type(-1);\n    nu_items.try_emplace(letter, DoComputerType, nc.use_computer_type);\n    clr_items.try_emplace(letter, [](User& u) { u.computer_type(-1); });\n    ++letter;\n  }\n  std::set<char> letters;\n  do {\n    bout.cls();\n    bout.litebar(StrCat(a()->config()->system_name(), \" New User Registration\"));\n    auto need_redraw = false;\n    for (auto& kv : nu_items) {\n      const auto is_first = letters.find(kv.first) == std::end(letters);\n      NewUserContext context(kv.first, u, kv.second.state, is_first);\n      letters.insert(kv.first);\n      if (const auto result = kv.second.fn(context); result == NewUserItemResult::need_redraw) {\n        need_redraw = true;\n        break;\n      }\n    }\n    if (need_redraw) {\n      continue;\n    }\n    bout.nl();\n    bout.outstr(\"|#5Item to change or [|#2Q|#5] to Quit : |#0\");\n    std::string allowed(\"Q\");\n    for (auto cc = 'A'; cc <= letter; cc++) {\n      allowed.push_back(cc);\n    }\n    auto ch = onek(allowed);\n    if (ch == 'Q') {\n      break;\n    }\n    if (auto c = clr_items.find(ch); c != std::end(clr_items) ) {\n      clr_items.at(ch)(u);\n    }\n    // Reset 'first' so it runs again vs. displays.\n    letters.erase(ch);\n  } while (!a()->sess().hangup());\n\n  if (u.ansi()) {\n    u.set_flag(User::status_color);\n    u.set_flag(User::extraColor);\n    // Enable the internal FSED and full screen reader for the sysop.\n    u.default_editor(0xff);\n    u.set_flag(User::fullScreenReader);\n  }\n  bout.localIO()->topdata(saved_topdata);\n  a()->UpdateTopScreen();\n  bout.newline = true;\n}\n\nvoid newuser() {\n  sysoplog(false, \"\");\n  const auto t = times();\n  const auto f = fulldate();\n  sysoplog(false, fmt::format(\"*** NEW USER {}   {}    {} ({})\", f, t, a()->GetCurrentSpeed(),\n                              a()->sess().instance_number()));\n\n  LOG(INFO) << \"New User Attempt from IP Address: \" << bout.remoteIO()->remote_info().address;\n  a()->sess().num_screen_lines(25);\n\n  if (!CreateNewUserRecord()) {\n    return;\n  }\n\n  if (!CanCreateNewUserAccountHere() || a()->sess().hangup()) {\n    a()->Hangup();\n    return;\n  }\n\n  if (check_ansi() == 1) {\n    a()->user()->set_flag(User::flag_ansi);\n    a()->user()->set_flag(User::status_color);\n    a()->user()->set_flag(User::extraColor);\n    a()->user()->set_flag(User::fullScreenReader);\n    // 0xff is the internal FSED.\n    a()->user()->default_editor(0xff);\n  }\n  bout.printfile(SYSTEM_NOEXT);\n  bout.nl();\n  bout.pausescr();\n  bout.printfile(NEWUSER_NOEXT);\n  bout.nl();\n  bout.pausescr();\n  bout.cls();\n  bout.print(\"|#5Create a new user account on |#2{}|#5? \", a()->config()->system_name());\n  if (!bin.noyes()) {\n    bout.outstr(\"|#6Sorry the system does not meet your needs!\\r\\n\");\n    a()->Hangup();\n    return;\n  }\n\n  input_screensize();\n  NewUserDataEntry(a()->config()->newuser_config());\n\n  bout.nl(4);\n  bout.print(\"Random password: \\\"{}\\\"\\r\\n\\r\\n\", a()->user()->password());\n  bout.outstr(\"|#5Do you want a different password (Y/N)? \");\n  if (bin.yesno()) {\n    input_pw(a()->user());\n  }\n\n  DoNewUserASV();\n\n  if (a()->sess().hangup()) {\n    return;\n  }\n  bout.nl();\n  bout.outstr(\"Please wait...\\r\\n\\n\");\n  const auto usernum = find_new_usernum(a()->user(), a()->sess().qsc);\n  if (usernum <= 0) {\n    bout.nl();\n    bout.outstr(\"|#6Error creating user account.\\r\\n\\n\");\n    a()->Hangup();\n    return;\n  }\n  if (usernum == 1) {\n    // This is the #1 sysop record. Tell the sysop thank you and\n    // update his user record with: s255/d255/r0\n    ssm(1) << \"Thank you for installing WWIV! - The WWIV Development Team.\";\n    auto user = a()->user();\n    user->sl(255);\n    user->dsl(255);\n    user->restriction(0);\n  }\n  // Set the user number on the session and also on this User instance\n  // since it hasn't been loaded nor saved from the UserManager yet.\n  a()->sess().user_num(usernum);\n  a()->user()->user_number_ = usernum;\n\n  WriteNewUserInfoToSysopLog();\n  ssm(1) << \"You have a new user: \" << a()->user()->name() << \" #\" << a()->sess().user_num();\n\n  LOG(INFO) << \"New User Created: '\" << a()->user()->name() << \"' \"\n            << \"IP Address: \" << bout.remoteIO()->remote_info().address;\n\n  a()->UpdateTopScreen();\n  VerifyNewUserPassword();\n  SendNewUserFeedbackIfRequired();\n  ExecNewUserCommand();\n  a()->reset_effective_sl();\n  changedsl();\n  new_mail();\n}\n\nvoid new_mail() {\n  auto file = FilePath(a()->config()->gfilesdir(),\n                           (a()->user()->sl() > a()->config()->newuser_sl()) ? NEWSYSOP_MSG\n                                                                                : NEWMAIL_MSG);\n\n  if (!File::Exists(file)) {\n    return;\n  }\n  const auto save_ed = a()->user()->default_editor();\n  a()->user()->default_editor(0);\n  LoadFileIntoWorkspace(a()->context(), file, true, true);\n  use_workspace = true;\n\n  MessageEditorData data(a()->user()->name_and_number());\n  data.title = StrCat(\"Welcome to \", a()->config()->system_name(), \"!\");\n  data.need_title = true;\n  data.anonymous_flag = 0;\n  data.aux = \"email\";\n  data.fsed_flags = FsedFlags::NOFSED;\n  data.to_name = a()->user()->name_and_number();\n  data.msged_flags = MSGED_FLAG_NONE;\n  data.silent_mode = true;\n  messagerec msg;\n  msg.storage_type = 2;\n  if (inmsg(data)) {\n    savefile(data.text, &msg, data.aux);\n\n    EmailData email(data);\n    email.msg = &msg;\n    email.anony = 0;\n    email.set_user_number(a()->sess().user_num());\n    email.system_number = 0;\n    email.an = true;\n    email.from_user = 1;\n    email.from_system = 0;\n    email.forwarded_code = 1;\n    email.from_network_number = 0;\n    email.silent_mode = true;\n    sendout_email(email);\n  }\n  a()->user()->email_waiting(a()->user()->email_waiting() + 1);\n  a()->user()->default_editor(save_ed);\n}\n"
  },
  {
    "path": "bbs/newuser.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_NEWUSER_H\n#define INCLUDED_BBS_NEWUSER_H\n\n#include \"sdk/user.h\"\n\n#include <string>\n\nvoid input_phone();\nvoid input_dataphone();\nvoid input_name();\nvoid input_realname();\nbool valid_phone(const std::string& phoneNumber);\nvoid input_street();\nvoid input_city();\nvoid input_state();\nvoid input_country();\nvoid input_zipcode();\nvoid input_sex();\nvoid input_age(wwiv::sdk::User* u);\nvoid input_comptype();\n/**\n * detects the screensize and returns true if the caller accepted the \n * new size.  The userrecord will be updated by the function.\n * \n */\nbool detect_screensize();\nvoid input_screensize();\nvoid input_pw(wwiv::sdk::User* u);\nvoid input_ansistat();\nvoid input_callsign();\nvoid newuser();\n\n\n\n\n#endif\n"
  },
  {
    "path": "bbs/normupld.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/numbers.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/status.h\"\n#include \"sdk/files/files.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n//////////////////////////////////////////////////////////////////////////////\n// Implementation\n\nvoid normalupload(int dn) {\n  files::FileRecord f;\n  auto ok = 1;\n\n  const auto& d = a()->dirs()[dn];\n  dliscan1(d);\n  if (a()->current_file_area()->number_of_files() >= d.maxfiles) {\n    bout.nl(3);\n    bout.outstr(\"This directory is currently full.\\r\\n\\n\");\n    return;\n  }\n  if (d.mask & mask_no_uploads && !dcs()) {\n    bout.nl(2);\n    bout.outstr(\"Uploads are not allowed to this directory.\\r\\n\\n\");\n    return;\n  }\n  bout.outstr(\"|#9Filename: \");\n  auto input_fn = bin.input(12);\n  if (!okfn(input_fn)) {\n    input_fn.clear();\n  } else {\n    if (!is_uploadable(input_fn)) {\n      if (so()) {\n        bout.nl();\n        bout.outstr(\"|#5In filename database - add anyway? \");\n        if (!bin.yesno()) {\n          input_fn.clear();\n        }\n      } else {\n        input_fn.clear();\n        bout.nl();\n        bout.outstr(\"|#6File either already here or unwanted.\\r\\n\");\n      }\n    }\n  }\n  input_fn = aligns(input_fn);\n  if (strchr(input_fn.c_str(), '?')) {\n    return;\n  }\n  if (d.mask & mask_archive) {\n    ok = 0;\n    std::string supportedExtensions;\n    for (int k = 0; k < MAX_ARCS; k++) {\n      if (a()->arcs[k].extension[0] && a()->arcs[k].extension[0] != ' ') {\n        if (!supportedExtensions.empty()) {\n          supportedExtensions += \", \";\n        }\n        supportedExtensions += a()->arcs[k].extension;\n        if (iequals(input_fn.substr(9), a()->arcs[k].extension)) {\n          ok = 1;\n        }\n      }\n    }\n    if (!ok) {\n      bout.nl();\n      bout.print(\"Sorry, all uploads to this dir must be archived.\\r\\n\"\n                 \"Supported types are:\\r\\n{}\\r\\n\\n\",\n                 supportedExtensions);\n      return;\n    }\n  }\n  f.set_filename(input_fn);\n  f.set_ownerusr(a()->sess().user_num());\n  f.set_ownersys(0);\n  f.u().numdloads = 0;\n  f.u().unused_filetype = 0;\n  f.u().mask = 0;\n  const auto unn = a()->user()->name_and_number();\n  to_char_array(f.u().upby, unn);\n  to_char_array(f.u().date, date());\n  bout.nl();\n  ok = 1;\n  auto xfer = true;\n  if (a()->batch().contains_file(f.filename())) {\n    ok = 0;\n    bout.nl();\n    bout.outstr(\"That file is already in the batch queue.\\r\\n\\n\");\n  } else {\n    if (!wwiv::strings::iequals(input_fn, \"        .   \")) {\n      bout.print(\"|#5Upload '{}' to {}? \", input_fn, d.name);\n    } else {\n      ok = 0;\n    }\n  }\n\n  const auto dir_path = File::absolute(a()->bbspath(), d.path);\n  const auto receive_fn = FilePath(dir_path, files::unalign(input_fn));\n  if (ok && bin.yesno()) {\n    if (File::Exists(receive_fn)) {\n      if (dcs()) {\n        xfer = false;\n        bout.nl(2);\n        bout.outstr(\"File already exists.\\r\\n|#5Add to database anyway? \");\n        if (!bin.yesno()) {\n          ok = 0;\n        }\n      } else {\n        bout.nl(2);\n        bout.outstr(\"That file is already here.\\r\\n\\n\");\n        ok = 0;\n      }\n    } else if (!a()->sess().incom()) {\n      bout.nl();\n      bout.outstr(\"File isn't already there.\\r\\nCan't upload locally.\\r\\n\\n\");\n      ok = 0;\n    }\n    if (d.mask & mask_PD && ok) {\n      bout.nl();\n      bout.outstr(\"|#5Is this program PD/Shareware? \");\n      if (!bin.yesno()) {\n        bout.nl();\n        bout.outstr(\"This directory is for Public Domain/\\r\\nShareware programs ONLY.  Please do not\\r\\n\");\n        bout.outstr(\"upload other programs.  If you have\\r\\ntrouble with this policy, please contact\\r\\n\");\n        bout.outstr(\"the sysop.\\r\\n\\n\");\n        const auto message = fmt::format(\"Wanted to upload \\\"{}\\\"\", f);\n        sysoplog(fmt::format(\"*** ASS-PTS: 5, Reason: [{}]\", message));\n        a()->user()->increment_ass_points(5);\n        ok = 0;\n      } else {\n        f.set_mask(mask_PD, true);\n      }\n    }\n    if (ok) {\n      bout.nl();\n      bout.outstr(\"Please enter a one line description.\\r\\n:\");\n      auto desc = bin.input_text(58);\n      f.set_description(desc);\n      bout.nl();\n      std::string ext_desc;\n      modify_extended_description(&ext_desc, a()->dirs()[dn].name);\n      if (!ext_desc.empty()) {\n        a()->current_file_area()->AddExtendedDescription(f, ext_desc);\n        f.set_extended_description(true);\n      }\n      bout.nl();\n      if (xfer) {\n        write_inst(INST_LOC_UPLOAD, a()->current_user_dir().subnum, INST_FLAGS_ONLINE);\n        auto ti = std::chrono::system_clock::now();\n        receive_file(receive_fn.string(), &ok, f.filename().aligned_filename(), dn);\n        auto used = std::chrono::system_clock::now() - ti;\n        a()->user()->add_extratime(used);\n      }\n      if (ok) {\n        File file(receive_fn);\n        if (ok == 1) {\n          if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n            ok = 0;\n            bout.nl(2);\n            bout.outstr(\"OS error - File not found: \\r\\n\");\n            LOG(ERROR) << \"OS error - File not found: \" << receive_fn.string();\n            if (f.mask(mask_extended)) {\n              a()->current_file_area()->DeleteExtendedDescription(f.filename());\n            }\n          }\n          if (ok && !a()->upload_cmd.empty()) {\n            file.Close();\n            bout.outstr(\"Please wait...\\r\\n\");\n            if (!check_ul_event(dn, &f.u())) {\n              if (f.mask(mask_extended)) {\n                a()->current_file_area()->DeleteExtendedDescription(f.filename());\n              }\n              ok = 0;\n            } else {\n              file.Open(File::modeBinary | File::modeReadOnly);\n            }\n          }\n        }\n        if (ok) {\n          if (ok == 1) {\n            f.set_numbytes(file.length());\n            file.Close();\n            a()->user()->increment_uploaded();\n            add_to_file_database(f);\n            a()->user()->set_uk(a()->user()->uk() + bytes_to_k(f.numbytes()));\n\n            get_file_idz(f, a()->dirs()[dn]);\n          } else {\n            f.set_numbytes(0);\n          }\n          f.set_date(DateTime::now());\n          if (auto * area = a()->current_file_area(); area->AddFile(f)) {\n            area->Save();\n          }\n          if (ok == 1) {\n            a()->status_manager()->Run([](Status& s) {\n              s.increment_uploads_today();\n              s.increment_filechanged(Status::file_change_upload);\n            });\n            sysoplog(fmt::format(\"+ \\\"{}\\\" uploaded on {}\", f, a()->dirs()[dn].name));\n            bout.nl(2);\n            bout.printf(\"File uploaded.\\r\\n\\nYour ratio is now: %-6.3f\\r\\n\", a()->user()->ratio());\n            bout.nl(2);\n            if (a()->sess().IsUserOnline()) {\n              a()->UpdateTopScreen();\n            }\n          }\n        }\n      } else {\n        bout.nl(2);\n        bout.outstr(\"File transmission aborted.\\r\\n\\n\");\n        if (f.mask(mask_extended)) {\n          a()->current_file_area()->DeleteExtendedDescription(f.filename());\n        }\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "bbs/pause_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs_helper.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::common;\nusing wwiv::sdk::User;\n\nclass PauseTest : public ::testing::Test {\nprotected:\n  void SetUp() override { helper.SetUp(); }\n\n  BbsHelper helper{};\n};\n\nTEST_F(PauseTest, Smoke) {\n  helper.user()->set_flag(User::pauseOnPage);\n  {\n    TempDisablePause disable_pause(bout);\n    EXPECT_FALSE(helper.user()->pause());\n  }\n  EXPECT_TRUE(helper.user()->pause());\n}\n"
  },
  {
    "path": "bbs/printfile_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2014-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"gtest/gtest.h\"\r\n\r\n#include \"bbs/bbs_helper.h\"\r\n#include \"common/output.h\"\r\n#include \"common/printfile.h\"\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include <regex>\r\n#include <string>\r\n\r\nusing wwiv::sdk::User;\r\nusing namespace wwiv::common;\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::strings;\r\n\r\nclass PrintFileTest : public ::testing::Test {\r\nprotected:\r\n  void SetUp() override { \r\n    helper.SetUp(); \r\n    helper.user()->screen_width(80);\r\n    const auto lang = FilePath(helper.files().TempDir(), \"en/gfiles\");\r\n    const auto gfiles = FilePath(helper.files().TempDir(), \"gfiles\");\r\n    dirs.push_back(lang);\r\n    dirs.push_back(gfiles);\r\n  }\r\n\r\n  std::filesystem::path CreateTempFile(const std::string& name) {\r\n    return helper.files().CreateTempFile(name, \"1\");\r\n  }\r\n\r\n  std::filesystem::path CreateFullPathToPrint(const std::string& basename) const {\r\n    return wwiv::common::CreateFullPathToPrint(dirs, *helper.user(), basename);\r\n  }\r\n\r\n  BbsHelper helper{};\r\n  std::vector<std::filesystem::path> dirs;\r\n  };\r\n\r\nTEST_F(PrintFileTest, LanguageDir) {\r\n  const auto expected_ans = CreateTempFile(\"en/gfiles/one.ans\");\r\n  const auto expected_bw = CreateTempFile(\"en/gfiles/one.b&w\");\r\n  const auto expected_msg = CreateTempFile(\"en/gfiles/one.msg\");\r\n  CreateTempFile(\"gfiles/one.ans\");\r\n  CreateTempFile(\"gfiles/one.b&w\");\r\n  CreateTempFile(\"gfiles/one.msg\");\r\n\r\n  helper.user()->SetStatus(0);\r\n  const auto actual_msg = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_msg, actual_msg);\r\n\r\n  helper.user()->set_flag(User::flag_ansi);\r\n  const auto actual_bw = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_bw, actual_bw);\r\n\r\n  helper.user()->set_flag(User::status_color);\r\n  const auto actual_ans = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_ans, actual_ans);\r\n}\r\n\r\nTEST_F(PrintFileTest, GFilesOnly_NoExt) {\r\n  const auto expected_ans = CreateTempFile(\"gfiles/one.ans\");\r\n  const auto expected_bw = CreateTempFile(\"gfiles/one.b&w\");\r\n  const auto expected_msg = CreateTempFile(\"gfiles/one.msg\");\r\n\r\n  helper.user()->SetStatus(0);\r\n  const auto actual_msg = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_msg, actual_msg);\r\n\r\n  helper.user()->set_flag(User::flag_ansi);\r\n  const auto actual_bw = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_bw, actual_bw);\r\n\r\n  helper.user()->set_flag(User::status_color);\r\n  const auto actual_ans = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(expected_ans, actual_ans);\r\n}\r\n\r\nTEST_F(PrintFileTest, WithExtension) {\r\n  const auto expected_ans = CreateTempFile(\"gfiles/one.ans\");\r\n  const auto expected_bw = CreateTempFile(\"gfiles/one.b&w\");\r\n  const auto expected_msg = CreateTempFile(\"gfiles/one.msg\");\r\n\r\n  const auto actual_msg = CreateFullPathToPrint(\"one.msg\");\r\n  EXPECT_EQ(expected_msg, actual_msg);\r\n  const auto actual_bw = CreateFullPathToPrint(\"one.b&w\");\r\n  EXPECT_EQ(expected_bw, actual_bw);\r\n  const auto actual_ans = CreateFullPathToPrint(\"one.ans\");\r\n  EXPECT_EQ(expected_ans, actual_ans);\r\n}\r\n\r\nTEST_F(PrintFileTest, FullyQualified) {\r\n  const auto expected = CreateTempFile(\"gfiles/one.ans\");\r\n  const auto actual = CreateFullPathToPrint(expected.string());\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST_F(PrintFileTest, WithCols) {\r\n  const auto base_ans = CreateTempFile(\"gfiles/one.msg\");\r\n  const auto expected_msg = CreateTempFile(\"gfiles/one.80.msg\");\r\n  const auto msg120 = CreateTempFile(\"gfiles/one.120.msg\");\r\n  const auto msg132 = CreateTempFile(\"gfiles/one.132.msg\");\r\n  const auto msg40 = CreateTempFile(\"gfiles/one.40.msg\");\r\n\r\n  const auto actual_msg = CreateFullPathToPrintWithCols(base_ans, 80);\r\n  EXPECT_EQ(expected_msg, actual_msg);\r\n}\r\n\r\nTEST_F(PrintFileTest, WithCols_None) {\r\n  const auto expected_msg = CreateTempFile(\"gfiles/one.msg\");\r\n  const auto msg100 = CreateTempFile(\"gfiles/one.100.msg\");\r\n  const auto msg120 = CreateTempFile(\"gfiles/one.120.msg\");\r\n  const auto msg132 = CreateTempFile(\"gfiles/one.132.msg\");\r\n\r\n  const auto actual_msg = CreateFullPathToPrintWithCols(expected_msg, 80);\r\n  EXPECT_EQ(expected_msg, actual_msg);\r\n}\r\n\r\nTEST_F(PrintFileTest, GFilesOnly_WithCols) {\r\n  const auto msg132 = CreateTempFile(\"gfiles/one.132.msg\");\r\n  const auto base_msg = CreateTempFile(\"gfiles/one.msg\");\r\n\r\n  helper.user()->screen_width(132);\r\n  const auto actual_msg = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(msg132, actual_msg);\r\n\r\n  helper.user()->screen_width(80);\r\n  const auto actual_bw = CreateFullPathToPrint(\"one\");\r\n  EXPECT_EQ(base_msg, actual_bw);\r\n}"
  },
  {
    "path": "bbs/prot/crctab.cpp",
    "content": "/*\n *  Crc calculation stuff\n */\n\n#include <cstdint>\n\n/* crctab calculated by Mark G. Mendel, Network Systems Corporation */\nuint16_t crctab[256] = {\n    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,\n    0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,\n    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,\n    0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,\n    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,\n    0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,\n    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,\n    0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,\n    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,\n    0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,\n    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,\n    0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,\n    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,\n    0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,\n    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,\n    0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,\n    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,\n    0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,\n    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,\n    0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,\n    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,\n    0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};\n\n/*\n * updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.\n *  NOTE: First argument must be in range 0 to 255.\n *        Second argument is referenced twice.\n *\n * Programmers may incorporate any or all code into their programs,\n * giving proper credit within the source. Publication of the\n * source routines is permitted so long as proper credit is given\n * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,\n * Omen Technology.\n */\n\n#define updcrc(cp, crc) (crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)\n\n/*\n * Copyright (C) 1986 Gary S. Brown.  You may use this program, or\n * code or tables extracted from it, as desired without restriction.\n */\n\n/* First, the polynomial itself and its table of feedback terms.  The  */\n/* polynomial is                                                       */\n/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */\n/* Note that we take it \"backwards\" and put the highest-order term in  */\n/* the lowest-order bit.  The X^32 term is \"implied\"; the LSB is the   */\n/* X^31 term, etc.  The X^0 term (usually shown as \"+1\") results in    */\n/* the MSB being 1.                                                    */\n\n/* Note that the usual hardware shift register implementation, which   */\n/* is what we're using (we're merely optimizing it by doing eight-bit  */\n/* chunks at a time) shifts bits into the lowest-order term.  In our   */\n/* implementation, that means shifting towards the right.  Why do we   */\n/* do it this way?  Because the calculated CRC must be transmitted in  */\n/* order from highest-order term to lowest-order term.  UARTs transmit */\n/* characters in order from LSB to MSB.  By storing the CRC this way,  */\n/* we hand it to the UART in the order low-byte to high-byte; the UART */\n/* sends each low-bit to hight-bit; and the result is transmission bit */\n/* by bit from highest- to lowest-order term without requiring any bit */\n/* shuffling on our part.  Reception works similarly.                  */\n\n/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */\n/*                                                                     */\n/*     The table can be generated at runtime if desired; code to do so */\n/*     is shown later.  It might not be obvious, but the feedback      */\n/*     terms simply represent the results of eight shift/xor opera-    */\n/*     tions for all combinations of data and CRC register values.     */\n/*                                                                     */\n/*     The values must be right-shifted by eight bits by the \"updcrc\"  */\n/*     logic; the shift must be unsigned (bring in zeroes).  On some   */\n/*     hardware you could probably optimize the shift in assembler by  */\n/*     using byte-swap instructions.                                   */\n\nunsigned long cr3tab[] =\n    {/* CRC polynomial 0xedb88320 */\n     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,\n     0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,\n     0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,\n     0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,\n     0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n     0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n     0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,\n     0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,\n     0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n     0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,\n     0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n     0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,\n     0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,\n     0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n     0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,\n     0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n     0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,\n     0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n     0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,\n     0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,\n     0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,\n     0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n     0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,\n     0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,\n     0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,\n     0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,\n     0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n     0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,\n     0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,\n     0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,\n     0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n     0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n     0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};\n\n#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))\n\n/* End of crctab.c */\n"
  },
  {
    "path": "bbs/prot/crctab.h",
    "content": "/*\t@(#)crctab.h 1.2 96/09/13\t*/\n\n#include <cstdint>\n\n/*\n *  Crc calculation stuff.  See crctab.c\n */\n\nextern uint16_t crctab[256];\n\n#define updcrc(cp, crc) (crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)\n\nextern unsigned long cr3tab[];\n\n#define UPDC32(b, c) (cr3tab[((int)c ^ b) & 0xff] ^ ((c >> 8) & 0x00FFFFFF))\n"
  },
  {
    "path": "bbs/prot/reference/checkcrc.cpp",
    "content": "#include <cstdint>\n#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n#include <stdio.h>\n#include <sys/types.h>\n\n#include \"crctab.h\"\n\n\nstatic\tu_char\tmsg0[] = {\n\t  0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00, \n\t  0xbc, 0xef, 0x92, 0x8c,} ;\nstatic\tu_char\tmsg0c[] = {\n\t  0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00,\n\t  0xbc, 0xef, 0x92, 0x8c, 0x0b, 0xdf,} ;\nstatic\tu_char\tmsg1[] = {\n\t  0x0a, 0x23, 0x69, 0x6e, \n\t  0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, \n\t  0x79, 0x73, 0x2f, 0x74, 0x65, 0x72, 0x6d, 0x69, \n\t  0x6f, 0x73, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 0x69, \n\t  0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x22, \n\t  0x78, 0x6d, 0x6f, 0x64, 0x65, 0x6d, 0x2e, 0x68, \n\t  0x22, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x0a, \n\t  0x73, 0x65, 0x6e, 0x64, 0x43, 0x61, 0x6e, 0x63, \n\t  0x65, 0x6c, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x09, \n\t  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, \n\t  0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, 0x73, 0x68, \n\t  0x28, 0x43, 0x41, 0x4e, 0x29, 0x20, 0x7c, 0x7c, \n\t  0x20, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, \n\t  0x73, 0x68, 0x28, 0x43, 0x41, 0x4e, 0x29, 0x20, \n\t  0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, 0x09, 0x2f, \n\t  0x2a, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6f, \n\t  0x6e, 0x65, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, \n\t  0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x72, 0x65, \n\t  0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, \n\t  0x7a, 0x65, 0x72, 0x6f, 0x20, 0x6f, 0x6e, 0x20, \n\t  0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2a, 0x2f, \n\t  0x0a, 0x69, 0x6e, 0x74, 0x0a, 0x73, 0x65, 0x6e, \n\t  0x64, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x28, 0x63, \n\t  0x29, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x09, \n\t  0x63, 0x20, 0x3b, 0x0a, 0x7b, 0x0a, 0x09, 0x2f, \n\t  0x2a, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2c, \n\t  0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x20, 0x69, \n\t  0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, 0x6f, 0x72, \n\t  0x74, 0x20, 0x2a, 0x2f, 0x0a, 0x09, 0x2f, 0x2a, \n\t  0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x63, \n\t  0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x70, 0x72, \n\t  0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x61, 0x20, \n\t  0x77, 0x61, 0x79, 0x20, 0x18, 0x69, 0x4c, 0x5b, \n\t  0x62, 0x0f,\n\t  0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, \n\t  0x00, 0x00, 0xbc, 0xef, 0x92, 0x8c, 0x0a, 0x23, \n\t  0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, \n\t  0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 0x65, 0x72, \n\t  0x6d, 0x69, 0x6f, 0x73, 0x2e, 0x68, 0x3e, 0x0a, \n\t  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, \n\t  0x20, 0x22, 0x78, 0x6d, 0x6f, 0x64, 0x65, 0x6d, \n\t  0x2e, 0x68, 0x22, 0x0a, 0x0a, 0x0a, 0x69, 0x6e, \n\t  0x74, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x43, 0x61, \n\t  0x6e, 0x63, 0x65, 0x6c, 0x28, 0x29, 0x0a, 0x7b, \n\t  0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, \n\t  0x20, 0x73, 0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, \n\t  0x73, 0x68, 0x28, 0x43, 0x41, 0x4e, 0x29, 0x20, \n\t  0x7c, 0x7c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x46, \n\t  0x6c, 0x75, 0x73, 0x68, 0x28, 0x43, 0x41, 0x4e, \n\t  0x29, 0x20, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x0a, \n\t  0x09, 0x2f, 0x2a, 0x20, 0x73, 0x65, 0x6e, 0x64, \n\t  0x20, 0x6f, 0x6e, 0x65, 0x20, 0x63, 0x68, 0x61, \n\t  0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x2c, 0x20, \n\t  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, \n\t  0x6f, 0x6e, 0x7a, 0x65, 0x72, 0x6f, 0x20, 0x6f, \n\t  0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, \n\t  0x2a, 0x2f, 0x0a, 0x69, 0x6e, 0x74, 0x0a, 0x73, \n\t  0x65, 0x6e, 0x64, 0x46, 0x6c, 0x75, 0x73, 0x68, \n\t  0x28, 0x63, 0x29, 0x0a, 0x09, 0x63, 0x68, 0x61, \n\t  0x72, 0x09, 0x63, 0x20, 0x3b, 0x0a, 0x7b, 0x0a, \n\t  0x09, 0x2f, 0x2a, 0x20, 0x66, 0x69, 0x72, 0x73, \n\t  0x74, 0x2c, 0x20, 0x66, 0x6c, 0x75, 0x73, 0x68, \n\t  0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, \n\t  0x6f, 0x72, 0x74, 0x20, 0x2a, 0x2f, 0x0a, 0x09, \n\t  0x2f, 0x2a, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, \n\t  0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, \n\t  0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, \n\t  0x61, 0x20, 0x77, 0x61, 0x79, 0x20, 0x18, 0x6b, \n\t  0x60, 0x3a, 0x6c, 0xe1, \n\t} ;\nstatic\tu_char\tmsg2[] = {1} ;\n\n#ifdef\tCOMMENT\n#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)\n#define updcrc(cp, crc) ( crctab[((crc>>8)^cp) & 255] ^ (crc<<8) )\n#endif\t/* COMMENT */\n\nstatic\tint\taddcrc(int data, int crc) ;\n\n\nmain()\n{\n  uint16_t crc16;\n\tuint32_t\tcrc32 ;\n\tint\ti,j ;\n\tuint32_t\tk ;\n\tu_char\t*msg = msg0 ;\n\tint\tlen = sizeof(msg0) ;\n\n\n\t/* crc16 of message */\n\n\tcrc16 = 0 ;\n\tcrc32 = 0xffffffff ;\n\n\tfor(i=0; i<len; ++i)\n\t{\n\t  crc16 = addcrc(msg[i], crc16) ;\n\t}\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\n\tcrc16 = addcrc(0, crc16) ;\n\tcrc16 = addcrc(0, crc16) ;\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\n\n\t/* crc of reception */\n\n\tj = crc16 ;\n\tcrc16 = 0 ;\n\tcrc32 = 0xffffffff ;\n\n\tfor(i=0; i<len; ++i)\n\t{\n\t  crc16 = addcrc(msg[i], crc16) ;\n\t}\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\n\tcrc16 = addcrc(j>>8, crc16) ;\n\tcrc16 = addcrc(j&0xff, crc16) ;\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\n\n\n#ifdef\tCOMMENT\n\tcrc16 = 0 ;\n\tcrc32 = 0xffffffff ;\n\n\tfor(i=0; i<len; ++i)\n\t{\n\t  crc16 = updcrc(msg[i], crc16) ;\n\t  crc32 = UPDC32(msg[i], crc32) ;\n\t  printf(\"%4.4x\\n\", crc16) ;\n\t}\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\tprintf(\"crc32=%8.8x, ~crc=%8.8x\\n\", crc32,~crc32) ;\n\n\n#ifdef\tCOMMENT\n\tprintf(\"\\n\") ;\n\tprintf(\"%2.2x\\n\", crc16&0xff) ;\n\tprintf(\"%2.2x\\n\", crc16>>8) ;\n#endif\t/* COMMENT */\n\n\ti = crc16 ;\n\tcrc16 = updcrc(i&0xff, crc16) ;\n\tcrc16 = updcrc(i>>8, crc16) ;\n\n\tk = ~crc32 ;\n\tcrc32 = updcrc(k&0xff, crc32) ;\n\tcrc32 = updcrc((k>>8)&0xff, crc32) ;\n\tcrc32 = updcrc((k>>16)&0xff, crc32) ;\n\tcrc32 = updcrc((k>>24)&0xff, crc32) ;\n\n\tprintf(\"crc16=%4.4hx, ~crc16=%4.4hx\\n\", crc16, ~crc16&0xffff) ;\n\tprintf(\"crc32=%8.8x, ~crc=%8.8x\\n\", crc32,~crc32) ;\n#endif\t/* COMMENT */\n\n\texit(0) ;\n}\n\n\nstatic\tint\naddcrc(int data, int crc)\n{\n  int j;\n  crc ^= (uint16_t)data << 8;\n\tfor(j=0; j<8; ++j) {\n\t  if( crc & 0x8000 )\n\t    crc = (crc<<1) ^ 0x1021;\n\t  else\n\t    crc <<= 1 ;\n\t}\n\treturn crc & 0xffff ;\n}\n"
  },
  {
    "path": "bbs/prot/reference/main.cpp",
    "content": "#include <cstdint>\n#ifndef lint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n/*\n * Copyright (c) 1995 by Edward A. Falk\n */\n\n\n/**********\n *\n *\n *\t@   @   @@@    @@@   @   @  \n *\t@@ @@  @   @    @    @@  @  \n *\t@ @ @  @@@@@    @    @ @ @  \n *\t@ @ @  @   @    @    @  @@  \n *\t@ @ @  @   @   @@@   @   @  \n *\n *\tMAIN - demonstration zmodem program\n *\n *\tThis program implements the x,y,z-modem protocols, using the\n *\tzmodem library.\n *\n *\tEdward A. Falk\n *\n *\tJan, 1995\n *\n *\n *\n **********/\n\nstatic\tchar\tusage [] =\n\"usage:\tzmodem -r [options]\\n\\\n\tzmodem -s [options] file [file ...]\\n\\\n\t-r\t\treceive files\\n\\\n\t-s\t\tsend files\\n\\\n\t- file\t\tallows you to transmit files with '-' in their names\\n\\\n\t-v\t\tverbose, more v's increase messages.\\n\\\n\t-l /dev/ttyX\tuse specified serial port instead of /dev/tty\\n\\\n\t-b baud\t\tset baud rate\\n\\\n\t-x file\t\tuse xmodem, specify filename\\n\\\n\t-y\t\tuse ymodem\\n\\\n\t-k\t\tuse 1k, packets (ymodem, xmodem)\\n\\\n\t-win nn\t\tset sliding window to nn bytes (send)\\n\\\n\t-buf nn\t\tset input buffer size to nn bytes (receive)\\n\\\n\t-L nn\t\tset packet length\\n\\\n\t-e\t\tescape control characters\\n\\\n\t-a\t\tascii text\\n\\\n\t-i\t\timage (binary data)\\n\\\n\t-resume\t\tcontinue an interrupted transfer\\n\\\n\t-new\t\ttransfer only if newer\\n\\\n\t-newl\t\ttransfer only if newer or longer\\n\\\n\t-diff\t\ttransfer only if dates or lengths differ\\n\\\n\t-crc\t\ttransfer only if length or crc different\\n\\\n\t-apnd\t\tappend to existing file\\n\\\n\t-clob\t\tforce overwrite of existing files\\n\\\n\t-prot\t\tdo not overwrite existing files\\n\\\n\t-chng\t\tchange filename if destination exists\\n\\\n\t-noloc\t\tdo not transfer unless destination exists\\n\\\n\t-[hq]\t\tthis list\\n\" ;\n\n#include <stdio.h>\n\n/****\n *\n * Constants,  typedefs, externals, globals, statics, macros, block data\n *\n ****/\n\n\n\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <signal.h>\n\n#include <fcntl.h>\n#include <errno.h>\n#include <sys/time.h>\n#include <sys/termios.h>\n#include <sys/param.h>\n\n#include \"zmodem.h\"\n#include \"seriallog.h\"\n\nextern\tint\terrno ;\nextern\tchar\t*getenv() ;\n\n\n\t/* compile-time parameters */\n\n#define\tESCCTRL\t0\t/* control characters need to be escaped */\n\n#if !defined(CRTSCTS) && defined(CNEW_RTSCTS)\n#define\tCRTSCTS\tCNEW_RTSCTS\n#endif\n\nstatic\tint\tbaud = 0 ;\t\t/* requested baud rate */\nstatic\tchar\t*line = NULL ;\t\t/* requested serial line */\nstatic\tint\tverbose = 0 ;\nstatic\tint\tsend = 0 ;\t\t/* send files */\nstatic\tint\treceive = 0 ;\t\t/* receive */\nstatic\tint\txmodem = 0 ;\t\t/* use xmodem */\nstatic\tint\tymodem = 0 ;\t\t/* use ymodem */\nstatic\tint\tescCtrl = ESCCTRL ;\nstatic\tint\tascii = 0 ;\t\t/* translate line endings */\nstatic\tint\tbinary = 0 ;\t\t/* don't translate line endings */\nstatic\tint\tresume = 0 ;\t\t/* resume interrupted transfers */\nstatic\tint\txferType = 0 ;\t\t/* new,newl,diff,crc, etc. */\nstatic\tint\tnoloc = 0 ;\nstatic\tint\tdoCancel = 0 ;\nstatic\tint\tdoLogging = 0 ;\n\nstatic\tint\tCorrupt = 0 ;\t\t/* deliberately corrupt data */\n\nstatic\tint\tfileErrs ;\t\t/* used to track errors per file */\nstatic\tint\tfileSent ;\t\t/* track amount sent */\n\nstatic\tZModem\tinfo ;\n\nstatic\tint\tbegun = 0 ;\nstatic\tstruct\ttermios\told_settings, new_settings ;\n\nstatic\tint\tFinishXmit(ZModem *info) ;\nstatic\tint\tDoReceive(ZModem *info) ;\nstatic\tint\tInitXmit(ZModem *info) ;\nstatic\tint\tXmitFile(char *filename, int f0, int f1, ZModem *info) ;\nstatic\tvoid\tSendFile() ;\nstatic\tvoid\tRcvFiles() ;\nstatic\tvoid\tRcvXmodem() ;\nstatic\tint\tgetBaud() ;\nstatic\tvoid\tresetCom() ;\nstatic\tchar\t*basename(char *name) ;\n\n#ifdef\tSVr4\nstatic\tvoid\tsighandle(int) ;\n#else\nstatic\tvoid\tsighandle() ;\n#endif\n\nextern\tFILE\t*SerialLogFile ;\nextern\tFILE\t*zmodemlogfile ;\n\nint\nmain(int argc, char **argv)\n{\n\tchar\t*progname ;\n\n#ifdef\tCOMMENT\n\tprintf(\"%d\\n\", getpid()) ;\n#endif\t/* COMMENT */\n\n\tinfo.ifd = info.ofd = -1 ;\n\tinfo.zrinitflags = 0 ;\n\tinfo.zsinitflags = 0 ;\n\tinfo.attn = NULL ;\n\tinfo.packetsize = 0 ;\n\tinfo.windowsize = 0 ;\n\tinfo.bufsize = 0 ;\n\n\tprogname = basename(argv[0]) ;\n\tif( strcmp(progname,\"rz\") == 0 )\n\t  receive = 1 ;\n\telse if( strcmp(progname, \"sz\") == 0 )\n\t  send = 1 ;\n\n\t++argv, --argc ;\t/* skip program name */\n\n\t/* parse options */\n\n\tfor(; argc > 0  &&  **argv == '-'; ++argv, --argc )\n\t{\n\t  if( strcmp(*argv, \"-r\") == 0 )\n\t    receive = 1 ;\n\t  else if( strcmp(*argv, \"-s\") == 0 )\n\t    send = 1 ;\n\t  else if( strncmp(*argv, \"-v\", 2) == 0 )\n\t    verbose += strlen(*argv)+1 ;\n\t  else if( strcmp(*argv, \"-l\") == 0 && --argc > 0 )\n\t    line = *++argv ;\n\t  else if( strcmp(*argv, \"-b\") == 0 && --argc > 0 )\n\t    baud = getBaud(atoi(*++argv)) ;\n\t  else if( strcmp(*argv, \"-x\") == 0 )\n\t    xmodem = 1 ;\n\t  else if( strcmp(*argv, \"-y\") == 0 )\n\t    ymodem = 1 ;\n\t  else if( strcmp(*argv, \"-win\") == 0 && --argc > 0 )\n\t    info.windowsize = atoi(*++argv) ;\n\t  else if( strcmp(*argv, \"-buf\") == 0 && --argc > 0 )\n\t    info.bufsize = atoi(*++argv) ;\n\t  else if( strcmp(*argv, \"-L\") == 0 && --argc > 0 )\n\t    info.packetsize = atoi(*++argv) ;\n\t  else if( strcmp(*argv, \"-k\") == 0 )\n\t    info.packetsize = 1024 ;\n\t  else if( strcmp(*argv, \"-e\") == 0 )\n\t    escCtrl = ESCCTL ;\n\t  else if( strcmp(*argv, \"-a\") == 0 )\n\t    ascii = 1 ;\n\t  else if( strcmp(*argv, \"-i\") == 0 )\n\t    binary = 1 ;\n\t  else if( strcmp(*argv, \"-resume\") == 0 )\n\t    resume = 1 ;\n\t  else if( strcmp(*argv, \"-new\") == 0 )\n\t    xferType = ZMNEW ;\n\t  else if( strcmp(*argv, \"-newl\") == 0 )\n\t    xferType = ZMNEWL ;\n\t  else if( strcmp(*argv, \"-diff\") == 0 )\n\t    xferType = ZMDIFF ;\n\t  else if( strcmp(*argv, \"-crc\") == 0 )\n\t    xferType = ZMCRC ;\n\t  else if( strcmp(*argv, \"-apnd\") == 0 )\n\t    xferType = ZMAPND ;\n\t  else if( strcmp(*argv, \"-clob\") == 0 )\n\t    xferType = ZMCLOB ;\n\t  else if( strcmp(*argv, \"-prot\") == 0 )\n\t    xferType = ZMPROT ;\n\t  else if( strcmp(*argv, \"-chng\") == 0 )\n\t    xferType = ZMCHNG ;\n\t  else if( strcmp(*argv, \"-noloc\") == 0 )\n\t    noloc = ZMSKNOLOC ;\n\t  else if( strcmp(*argv, \"-h\") == 0 ||\n\t\t   strcmp(*argv, \"-q\") == 0 )\n\t  {\n\t    fprintf(stderr, usage) ;\n\t    exit(0) ;\n\t  }\n\t  else if( strcmp(*argv, \"-corrupt\") == 0 )\n\t    Corrupt = 1 ;\n\t  else if( strcmp(*argv, \"-log\") == 0 )\n\t    doLogging = 1 ;\n\t  else if( strcmp(*argv, \"-\") == 0 ) {\n\t    ++argv, --argc ; break ;\n\t  }\n\t  else {\n\t    fprintf(stderr, \"unknown argument '%s' or missing value\\n%s\",\n\t      *argv, usage) ;\n\t    exit(2) ;\n\t  }\n\t}\n\n\n\tif( doLogging ) {\n\t  if( (SerialLogFile = fopen(\"xfer.log\", \"w\")) == NULL )\n\t    perror(\"xfer.log\") ;\n\t  if( (zmodemlogfile = fopen(\"zmodem.log\",\"w\")) == NULL )\n\t    perror(\"zmodem.log\") ;\n\t}\n\n\n\tif( send ) {\n\t  for(; argc > 0; ++argv, --argc )\t/* process filenames */\n\t    SendFile(*argv) ;\n\t  FinishXmit(&info) ;\n\t}\n\n\telse if( receive )\n\t{\n\t  if( !xmodem )\n\t    RcvFiles() ;\n\t  else\n\t    for(; argc > 0; ++argv, --argc )\t/* process filenames */\n\t      RcvXmodem(*argv) ;\n\t}\n\n\n\telse {\n\t  fprintf(stderr,\n\t    \"either -s (send) or -r (receive) must be specified\\n%s\", usage) ;\n\t  exit(2) ;\n\t}\n\n\tresetCom() ;\n\texit(0) ;\n}\n\n\nstatic\tvoid\nsighandle(int arg)\n{\n\tdoCancel = 1 ;\n}\n\n\n\nstatic\tvoid\nopenCom()\n{\n\tchar\t*ptr ;\n\n\tif( line == NULL )\n\t  line = getenv(\"RZSZLINE\") ;\n\n\tif( baud == 0 && (ptr = getenv(\"RZSZBAUD\")) != NULL )\n\t  baud = getBaud(atoi(ptr)) ;\n\n\tif( line == NULL ) {\n\t  info.ifd = 0 ;\n\t  info.ofd = 1 ;\n\t}\n\telse if( (info.ifd = info.ofd = open(line, O_RDWR)) == -1 ) {\n\t  fprintf(stderr,\n\t    \"cannot open %s, %s, use \\\"zmodem -h\\\" for more info\\n\",\n\t    line, strerror(errno)) ;\n\t  exit(2) ;\n\t}\n\n\t/* assumption: setting attributes for one half of channel will\n\t * change both halves.  This fails if different physical\n\t * devices are used.\n\t */\n\ttcgetattr(info.ifd,&old_settings) ;\n\tnew_settings = old_settings ;\n\n#ifdef\tIUCLC\n\tnew_settings.c_iflag &=\n\t  ~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;\n#else\n\tnew_settings.c_iflag &=\n\t  ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF|IMAXBEL) ;\n#endif\n\tnew_settings.c_oflag &= ~OPOST ;\n\tnew_settings.c_cflag &= ~(CSIZE|PARENB) ;\n\tnew_settings.c_cflag |= CS8 ;\n\tif( baud != 0 ) {\n\t  cfsetospeed(&new_settings, baud) ;\n\t  cfsetispeed(&new_settings, baud) ;\n\t}\n\telse\n\t  baud = cfgetospeed(&old_settings) ;\n\tnew_settings.c_lflag = 0 ;\n\tnew_settings.c_cc[VMIN] = 32 ;\n\tnew_settings.c_cc[VTIME] = 1 ;\n\ttcsetattr(info.ifd,TCSADRAIN, &new_settings) ;\n\n\tinfo.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32|escCtrl ;\n\tinfo.zsinitflags = escCtrl ;\n\tif( info.packetsize == 0 ) {\n\t  if( xmodem || ymodem )\n\t    info.packetsize = 128 ;\n\t  /* TODO: what about future high-speed interfaces? */\n\t  else if( baud < B2400 )\n\t    info.packetsize = 256 ;\n\t  else if( baud == B2400 )\n\t    info.packetsize = 512 ;\n\t  else\n\t    info.packetsize = 1024 ;\n\t}\n}\n\n\nstatic\tvoid\nresetCom()\n{\n\ttcsetattr(info.ifd,TCSADRAIN, &old_settings) ;\n}\n\n\n\nstatic\tvoid\nSendFile(char *filename)\n{\n\tint\tf0, f1 ;\n\n\tfileErrs = 0 ;\n\n\tif( !begun )\t\t/* establish connection */\n\t{\n\t  openCom() ;\n\n\t  signal(SIGINT, sighandle) ;\n\t  signal(SIGTERM, sighandle) ;\n\t  signal(SIGHUP, sighandle) ;\n\n\t  if( InitXmit(&info) ) {\n\t    fprintf(stderr, \"connect failed\\n\") ;\n\t    resetCom() ;\n\t    exit(1) ;\n\t  }\n\n\t  begun = 1 ;\n\t}\n\n\tif( ascii )\n\t  f0 = ZCNL ;\n\telse if( binary )\n\t  f0 = ZCBIN ;\n\telse if( resume )\n\t  f0 = ZCRESUM ;\n\telse\n\t  f0 = 0 ;\n\n\tf1 = xferType | noloc ;\n\n\tif( XmitFile(filename, f0,f1, &info) ) {\n\t  fprintf(stderr, \"connect failed\\n\") ;\n\t  resetCom() ;\n\t  exit(1) ;\n\t}\n}\n\n\n\nstatic\tvoid\nRcvFiles()\n{\n\topenCom() ;\n\n\tsignal(SIGINT, sighandle) ;\n\tsignal(SIGTERM, sighandle) ;\n\n\tif( DoReceive(&info) ) {\n\t  fprintf(stderr, \"connect failed\\n\") ;\n\t  resetCom() ;\n\t  exit(1) ;\n\t}\n}\n\n\n\nstatic\tvoid\nRcvXmodem(char *filename)\n{\n\t/* TODO: */\n}\n\n\nstatic\tint\ngetBaud(int b)\n{\n\tswitch(b) {\n\t  case 50: return B50 ;\n\t  case 75: return B75 ;\n\t  case 110: return B110 ;\n\t  case 134: return B134 ;\n\t  case 150: return B150 ;\n\t  case 200: return B200 ;\n\t  case 300: return B300 ;\n\t  case 600: return B600 ;\n\t  case 1200: return B1200 ;\n\t  case 1800: return B1800 ;\n\t  case 2400: return B2400 ;\n\t  case 4800: return B4800 ;\n\t  case 9600: return B9600 ;\n\t  case 19200: return B19200 ;\n\t  case 38400: return B38400 ;\n\t  default: return 0 ;\n\t}\n}\n\n\n\n\t/* TEST: randomly corrupt every 1000th byte */\nstatic\tvoid\ncorrupt(u_char *buffer, int len)\n{\n\textern double drand48() ;\n\n\twhile( --len >= 0 ) {\n\t  if( drand48() < 1./1000. )\n\t    *buffer ^= 0x81 ;\n\t  ++buffer ;\n\t}\n}\n\n\nstatic\tint\ndoIO(ZModem *info)\n{\n\tfd_set\treadfds ;\n\tstruct timeval timeout ;\n\tint\ti ;\n\tint\tlen ;\n\tu_char\tbuffer[1024] ;\n\tint\tdone = 0 ;\n\n\twhile(!done)\n\t{\n\t  FD_ZERO(&readfds) ;\n\t  FD_SET(info->ifd, &readfds) ;\n\t  timeout.tv_sec = info->timeout ;\n\t  timeout.tv_usec = 0 ;\n\t  i = select(info->ifd+1, &readfds,NULL,NULL, &timeout) ;\n\t  if( doCancel ) {\n\t    ZmodemAbort(info) ;\n\t    fprintf(stderr, \"cancelled by user\\n\") ;\n\t    resetCom() ;\n\t    exit(3) ;\n\t  }\n\t  if( i<0 )\n\t    perror(\"select\") ;\n\t  else if( i==0 )\n\t    done = ZmodemTimeout(info) ;\n\t  else {\n\t    len = read(info->ifd, buffer, sizeof(buffer)) ;\n\t    if( Corrupt )\n\t      corrupt(buffer, len) ;\n\t    if( SerialLogFile != NULL )\n\t      SerialLog(buffer, len, 1) ;\n\t    done = ZmodemRcv(buffer, len, info) ;\n\t  }\n\t}\n\tif( SerialLogFile != NULL )\n\t  SerialLogFlush() ;\n\treturn done ;\n}\n\n\nstatic\tint\nInitXmit(ZModem *info)\n{\n\tint\tdone ;\n\n\tif( xmodem )\n\t  done = XmodemTInit(info) ;\n\telse if( ymodem )\n\t  done = YmodemTInit(info) ;\n\telse\n\t  done = ZmodemTInit(info) ;\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\nstatic\tint\nXmitFile(char *filename, int f0, int f1, ZModem *info)\n{\n\tint\tdone ;\n\n\tdone = ZmodemTFile(filename,filename, f0,f1,0,0,\n\t\t0,0, info) ;\n\tswitch( done ) {\n\t  case 0:\n\t    if( verbose )\n\t      fprintf(stderr, \"Sending: \\\"%s\\\"\\n\", filename) ;\n\t    break ;\n\n\t  case ZmErrCantOpen:\n\t    fprintf(stderr, \"cannot open file \\\"%s\\\": %s\\n\",\n\t      filename, strerror(errno)) ;\n\t    return 0 ;\n\n\t  case ZmFileTooLong:\n\t    fprintf(stderr, \"filename \\\"%s\\\" too long, skipping...\\n\",\n\t      filename) ;\n\t    return 0 ;\n\n\t  case ZmDone:\n\t    return 0 ;\n\n\t  default:\n\t    return 1 ;\n\t}\n\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\n\nstatic\tint\nFinishXmit(ZModem *info)\n{\n\tint\tdone ;\n\n\tdone = ZmodemTFinish(info) ;\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\n\nstatic\tint\nDoReceive(ZModem *info)\n{\n\tint\tdone ;\n\n\tif( ymodem )\n\t  done = YmodemRInit(info) ;\n\telse\n\t  done = ZmodemRInit(info) ;\n\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\nint\nZXmitStr(u_char *buffer, int len, ZModem *info)\n{\n\tu_char\tb2[1024] ;\n\n\t/* TEST: randomly corrupt every 1000th byte */\n\tif( Corrupt )\n\t{\n\t  bcopy(buffer, b2, len) ;\n\t  corrupt(b2, len) ;\n\t  buffer = b2 ;\n\t}\n\n\tif( SerialLogFile != NULL )\n\t  SerialLog(buffer, len, 0) ;\n\n\tif( write(info->ofd, buffer, len) != len )\n\t  return ZmErrSys ;\n\n\treturn 0 ;\n}\n\n\nvoid\nZIFlush(ZModem *info)\n{\n\tif( SerialLogFile != NULL )\n\t  SerialLogFlush() ;\n\n\tif( tcflush(info->ifd, TCIFLUSH) != 0 )\n\t  perror(\"TCIFLUSH\") ;\n}\n\nvoid\nZOFlush(ZModem *info)\n{\n\tif( SerialLogFile != NULL )\n\t  SerialLogFlush() ;\n\n\tif( tcflush(info->ifd, TCOFLUSH) != 0 )\n\t  perror(\"TCOFLUSH\") ;\n}\n\nvoid\nZStatus(int type, int j, char *str)\n{\n\tswitch( type ) {\n\t  case RcvByteCount:\n\t    if( verbose >= 2 )\n\t      fprintf(stderr, \"received: %6d bytes\\n\", j) ;\n\t    break ;\n\t  case SndByteCount:\n\t    fileSent = j ;\n\t    if( verbose >= 2 )\n\t      fprintf(stderr, \"sent: %6d bytes\\n\", j) ;\n\t    break ;\n\t  case RcvTimeout:\n\t    if( verbose )\n\t      fprintf(stderr, \"receiver timeouts: %2d\\n\", j) ;\n\t    break ;\n\t  case SndTimeout:\n\t    if( verbose )\n\t      fprintf(stderr, \"sender timeouts: %2d\\n\", j) ;\n\t    break ;\n\t  case RmtCancel:\n\t    fprintf(stderr, \"transfer cancelled by remote\\n\") ;\n\t    break ;\n\t  case ProtocolErr:\n\t    if( verbose >= 3 )\n\t      fprintf(stderr, \"protocol error: %2.2d\\n\", j) ;\n\t    break ;\n\t  case RemoteMessage:\n\t    fprintf(stderr, \"remote message: %s\\n\",str) ;\n\t    break ;\n\t  case DataErr:\n\t    if( verbose >= 3 )\n\t      fprintf(stderr, \"data errors: %2d\\n\", j) ;\n#ifdef\tCOMMENT\n\t    if( ++fileErrs > 20 )\n\t    {\n\t      /* something's wrong */\n\t      ZmodemAbort(&info) ;\n\t    }\n#endif\t/* COMMENT */\n\t    break ;\n\t  case FileErr:\n\t    fprintf(stderr, \"cannot write file: %s\\n\", strerror(errno)) ;\n\t    break ;\n\t}\n}\n\n\nint\nZAttn(ZModem *info)\n{\n\tchar\t*ptr ;\n\n\tif( info->attn == NULL )\n\t  return 0 ;\n\n\tfor(ptr = info->attn; *ptr != '\\0'; ++ptr) {\n\t  if( *ptr == ATTNBRK )\n\t    tcsendbreak(info->ifd, 0) ;\n\t  else if( *ptr == ATTNPSE )\n\t    sleep(1) ;\n\t  else\n\t    write(info->ifd, ptr, 1) ;\n\t}\n\treturn 0 ;\n}\n\n\nFILE *\nZOpenFile(char *name, uint32_t crc, ZModem *info)\n{\n\tstruct stat\tbuf ;\n\tint\t\texists ;\t/* file already exists */\nstatic\tint\t\tchangeCount = 0 ;\n\tchar\t\tname2[MAXPATHLEN] ;\n\tint\t\tapnd = 0 ;\n\tint\t\tf0,f1 ;\n\tFILE\t\t*rval ;\n\n\t/* TODO: if absolute path, do we want to allow it?\n\t * if relative path, do we want to prepend something?\n\t */\n\n\tif( *name == '/' )\t/* for now, disallow absolute paths */\n\t  return NULL ;\n\n\tif( stat(name, &buf) == 0 )\n\t  exists = 1 ;\n\telse if( errno == ENOENT )\n\t  exists = 0 ;\n\telse\n\t  return NULL ;\n\n\n\t/* if remote end has not specified transfer flags, we can\n\t * accept the local definitions\n\t */\n\n\tif( (f0=info->f0) == 0 ) {\n\t  if( ascii )\n\t    f0 = ZCNL ;\n\t  else if( binary )\n\t    f0 = ZCBIN ;\n\t  else if( resume )\n\t    f0 = ZCRESUM ;\n\t  else\n\t    f0 = 0 ;\n\t}\n\n\tif( (f1=info->f1) == 0 )\n\t  f1 = xferType | noloc ;\n\n\tif( f0 == ZCRESUM ) {\t/* if exists, and we already have it, return */\n\t  if( exists  &&  buf.st_size == info->len )\n\t    return NULL ;\n\t  apnd = 1 ;\n\t}\n\n\t/* reject if file not found and it most be there (ZMSKNOLOC) */\n\tif( !exists && (f1 & ZMSKNOLOC) )\n\t  return NULL ;\n\n\tswitch( f1 & ZMMASK ) {\n\t  case 0:\t/* Implementation-dependent.  In this case, we\n\t\t\t * reject if file exists (and ZMSKNOLOC not set) */\n\t    if( exists && !(f1 & ZMSKNOLOC) ) {\n\t      fprintf(stderr, \"%s already exists\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMNEWL:\t/* take if newer or longer than file on disk */\n\t    if( exists  &&  info->date <= buf.st_mtime  &&\n\t\tinfo->len <= buf.st_size ) {\n\t      fprintf(stderr, \"%s already exists\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMCRC:\t\t/* take if different CRC or length */\n\t    if( exists  &&  info->len == buf.st_size && crc == FileCrc(name) )\n\t    {\n\t      fprintf(stderr, \"%s already exists\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMAPND:\t/* append */\n\t    apnd = 1 ;\n\t  case ZMCLOB:\t/* unconditional replace */\n\t    break ;\n\n\t  case ZMNEW:\t/* take if newer than file on disk */\n\t    if( exists  &&  info->date <= buf.st_mtime ) {\n\t      fprintf(stderr, \"%s already exists and is newer\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMDIFF:\t/* take if different date or length */\n\t    if( exists  &&  info->date == buf.st_mtime  &&\n\t\tinfo->len == buf.st_size )\n\t    {\n\t      fprintf(stderr, \"%s already exists\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMPROT:\t/* only if dest does not exist */\n\t    if( exists )\n\t    {\n\t      fprintf(stderr, \"%s already exists\\n\", name) ;\n\t      return NULL ;\n\t    }\n\t    break ;\n\n\t  case ZMCHNG:\t/* invent new filename if exists */\n\t    if( exists ) {\n\t      while( exists ) {\n\t\tsprintf(name2, \"%s_%d\", name, changeCount++) ;\n\t\texists = stat(name2, &buf) == 0 || errno != ENOENT ;\n\t      }\n\t      name = name2 ;\n\t    }\n\t    break ;\n\t}\n\n\t/* here if we've decided to accept */\n#ifdef\tCOMMENT\n\tif( exists && !apnd && unlink(name) != 0 )\n\t  return NULL ;\n#endif\t/* COMMENT */\n\n\t/* TODO: build directory path if needed */\n\n\tif( verbose )\n\t  fprintf(stderr, \"Receiving: \\\"%s\\\"\\n\", name) ;\n\n\trval = fopen(name, apnd ? \"a\" : \"w\") ;\n\tif( rval == NULL )\n\t  perror(name) ;\n\treturn rval ;\n}\n\n\nint\nZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info)\n{\n\t/* TODO: if ZCNL set in info->f0, convert\n\t * newlines to local convention\n\t */\n\n\treturn fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;\n}\n\n\n\nint\nZCloseFile(ZModem *info)\n{\n\tstruct timeval tvp[2] ;\n\tfclose(info->file) ;\n\tif( ymodem )\n\t  truncate(info->filename, info->len) ;\n\tif( info->date != 0 ) {\n\t  tvp[0].tv_sec = tvp[1].tv_sec = info->date ;\n\t  tvp[0].tv_usec = tvp[1].tv_usec = 0 ;\n\t  utimes(info->filename, tvp) ;\n\t}\n\tif( info->mode & 01000000 )\n\t  chmod(info->filename, info->mode&0777) ;\n\treturn 0 ;\n}\n\n\nvoid\nZIdleStr(u_char *buffer, int len, ZModem *info)\n{\n#ifdef\tCOMMENT\n\tfwrite(buffer, 1,len, stdout) ;\n#endif\t/* COMMENT */\n}\n\nvoid\nZFlowControl(int onoff, ZModem *info)\n{\n\tif( onoff ) {\n\t  new_settings.c_iflag |= IXON|IXANY|IXOFF ;\n#ifdef\tCOMMENT\n\t  new_settings.c_cflag |= CRTSCTS ;\n#endif\t/* COMMENT */\n\t}\n\telse {\n\t  new_settings.c_iflag &= ~(IXON|IXANY|IXOFF) ;\n\t  new_settings.c_cflag &= ~CRTSCTS ;\n\t}\n\ttcsetattr(info->ifd,TCSADRAIN, &new_settings) ;\n}\n\n\n\nstatic\tchar *\nbasename(char *name)\n{\n\tchar\t*ptr ;\n\n\tif( (ptr = strrchr(name, '/')) == NULL )\n\t  return name ;\n\telse\n\t  return ++ptr ;\n}\n"
  },
  {
    "path": "bbs/prot/reference/network.cpp",
    "content": "#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n/*\n * Copyright (c) 1995 by Edward A. Falk\n */\n\n\n/**********\n *\n *\n *\t@   @  @@@@@  @@@@@  @   @   @@@   @@@@   @   @  \n *\t@@  @  @        @    @   @  @   @  @   @  @  @   \n *\t@ @ @  @@@      @    @ @ @  @   @  @@@@   @@@    \n *\t@  @@  @        @    @ @ @  @   @  @  @   @  @   \n *\t@   @  @@@@@    @     @ @    @@@   @   @  @   @  \n *\n *\tNETWORK - Make network connection\n *\n *\tRoutines provided here:\n *\n *\n *\tvoid\n *\tIpConnect()\n *\t\tMake IP connection according to parameters in gcomm.h\n *\n *\tvoid\n *\tIpDisConnect()\n *\t\tClose IP connection.\n *\n *\n *\n *\tEdward A. Falk\n *\n *\tJanuary, 1995\n *\n *\n *\n **********/\n\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <malloc.h>\n#include <string.h>\n#include <ctype.h>\n#include <fcntl.h>\n#include <varargs.h>\n#include <errno.h>\n#include <sys/param.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/stat.h>\n#ifdef\tCOMMENT\n#include <sys/ttold.h>\n#include <sys/termio.h>\n#endif\t/* COMMENT */\n#include <termio.h>\n#include <sys/stat.h>\n\n#include <netdb.h>\t\t/* stuff used by tcp/ip */\n#include <sys/socket.h>\n#include <netinet/in.h>\n\n#include <sys/wait.h>\n#include <sys/signal.h>\n\n#include \"gcomm.h\"\n\nextern\tint\terrno ;\n#ifdef\tCOMMENT\nextern\tchar\t*sys_errlist[] ;\n#endif\t/* COMMENT */\n\n\n\nvoid\nIpConnect()\n{\n\tint\tsockfd ;\n\tint\ti,j ;\n\tstruct hostent *hostent ;\n\tstruct sockaddr_in sockaddr ;\n\tint\tport ;\n\n\tWindowStatus(\"Connecting...\") ;\n\n\tport = PortLookup(hostPort) ;\n\tif( port == -1 )\n\t  return ;\n\n\tbzero(&sockaddr, sizeof(sockaddr)) ;\n\tsockaddr.sin_family = AF_INET ;\n\tsockaddr.sin_port = htons(port) ;\n\n\thostent = gethostbyname(hostId) ;\n\tif( hostent != NULL )\n\t{\n\t  sockaddr.sin_addr = *(struct in_addr *) hostent->h_addr ;\n\t}\n\telse if( isdigit(hostId[0]) )\n\t{\n\t  i = sscanf(hostId, \"%d.%d.%d.%d\",\n\t\t&sockaddr.sin_addr.S_un.S_un_b.s_b1,\n\t\t&sockaddr.sin_addr.S_un.S_un_b.s_b2,\n\t\t&sockaddr.sin_addr.S_un.S_un_b.s_b3,\n\t\t&sockaddr.sin_addr.S_un.S_un_b.s_b4) ;\n\t  if( i != 4 ) {\n\t    WindowStatus(\"Host address must be in dd.dd.dd.dd format\") ;\n\t    return ;\n\t  }\n\t}\n\telse {\n\t  WindowStatus(\"Hostname not found\") ;\n\t  return ;\n\t}\n\n\tsockfd = socket(AF_INET, SOCK_STREAM, 0) ;\n\tif( sockfd < 0 ) {\n\t  WindowStatus(\"Cannot open socket: %s\", sys_errlist[errno]) ;\n\t  return ;\n\t}\n\n\ti = connect(sockfd, &sockaddr, sizeof(sockaddr)) ;\n\tif( i < 0 ) {\n\t  WindowStatus(\"Cannot connect to host: %s\", sys_errlist[errno]) ;\n\t  close(sockfd) ;\n\t  return ;\n\t}\n\n\tifd = ofd = sockfd ;\n\n\ti = fcntl(ifd, F_GETFL, 0) ;\n\tj = fcntl(ifd, F_SETFL, i|O_NDELAY) ;\n\n\tconnectionActive = 1 ;\n\tconnectTime0 = time(NULL) ;\n\tWindowStatus(\"Connected\") ;\n}\n\n\nvoid\nIpDisConnect()\n{\n\tif( ifd == -1 )\n\t  return ;\n\n\tclose(ifd) ;\n\tifd = ofd = -1 ;\n\n\tconnectionActive = 0 ;\n}\n"
  },
  {
    "path": "bbs/prot/reference/receive.cpp",
    "content": "#include <cstdint>\n#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n\n#define\tTEST\t/* standalone test */\n\n#include <unistd.h>\n#include <string.h>\n#include \"zmodem.h\"\n#include <sys/stat.h>\n\n#include <fcntl.h>\n#include <errno.h>\n#include <sys/time.h>\n#include <sys/termios.h>\n#include <sys/termio.h>\t\t/* define TCSBRK */\n#include <sys/param.h>\n\nextern\tint\terrno ;\n\nstatic\tu_char\tzeros[4] = {0,0,0,0} ;\n\nmain(argc,argv)\n\tint\targc ;\n\tchar\t**argv ;\n{\n\tstruct\ttermios\told_settings, new_settings ;\n\tfd_set\treadfds ;\n\tstruct timeval timeout ;\n\tint\ti ;\n\tint\tlen ;\n\tchar\tbuffer[1024] ;\n\tint\tdone = 0 ;\n\tint\tfilecount = 0 ;\n\tZModem\tinfo ;\n\n#ifdef\tTEST\n\nstatic\tu_char\tAmsg0[] = {\n\t  0x72, 0x7a, 0x0d, 0x2a, 0x2a, 0x18, 0x42, 0x30, \n\t  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, \n\t  0x30, 0x30, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x11, \n\t} ;\nstatic\tu_char\tAmsg1[] = {\n\t  0x2a, 0x18, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, \n\t  0x7d, 0xa4, 0xe2, 0xbc, 0x00, 0x18, 0x6b, 0x2f, \n\t  0xaa, 0xb9, 0x9b, 0x2a, 0x18, 0x43, 0x02, 0x00, \n\t  0x00, 0x00, 0x00, 0x7d, 0xa4, 0xe2, 0xbc, \n\t} ;\nstatic\tu_char\tAmsg2[] = {\n\t  0x00, 0x18, 0x6b, 0x2f, 0xaa, 0xb9, 0x9b, 0x2a, \n\t  0x18, 0x43, 0x04, 0x00, 0x00, 0x04, 0x00, 0xd9, \n\t  0x94, 0xce, 0x57, \n\t} ;\nstatic\tu_char\tAmsg3[] = {\n\t  0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2e, \n\t  0x63, 0x00, 0x31, 0x36, 0x39, 0x38, 0x36, 0x20, \n\t  0x35, 0x37, 0x30, 0x30, 0x36, 0x36, 0x37, 0x36, \n\t  0x37, 0x30, 0x20, 0x31, 0x30, 0x30, 0x36, 0x36, \n\t  0x34, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, \n\t  0x30, 0x00, 0x18, 0x6b, 0x57, 0xed, 0x76, 0xb6, \n\t} ;\nstatic\tu_char\tAmsg4[] = {\n\t  0x2a, 0x18, 0x43, 0x0a, 0x00, 0x00, 0x00, 0x00, \n\t  0xbc, 0xef, 0x92, 0x8c, 0x0a, 0x23, 0x64, 0x65, \n\t  0x66, 0x69, 0x6e, 0x65, 0x09, 0x54, 0x45, 0x53, \n\t  0x54, 0x09, 0x2f, 0x2a, 0x20, 0x73, 0x74, 0x61, \n\t  0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x20, \n\t  0x74, 0x65, 0x73, 0x74, 0x20, 0x2a, 0x2f, 0x0a, \n\t  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, \n\t  0x65, 0x20, 0x3c, 0x75, 0x6e, 0x69, 0x73, 0x74, \n\t  0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x23, 0x69, 0x6e, \n\t  0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, \n\t  0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x68, 0x3e, \n\t  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, \n\t  0x65, 0x20, 0x22, 0x7a, 0x6d, 0x6f, 0x64, 0x65, \n\t  0x6d, 0x2e, 0x68, 0x22, 0x0a, 0x23, 0x69, 0x6e, \n\t  0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, \n\t  0x79, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x2e, \n\t  0x68, 0x3e, 0x0a, 0x0a, 0x23, 0x69, 0x6e, 0x63, \n\t  0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x66, 0x63, \n\t  0x6e, 0x74, 0x6c, 0x2e, 0x68, 0x3e, 0x0a, 0x23, \n\t  0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, \n\t  0x3c, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x2e, 0x68, \n\t  0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, \n\t  0x64, 0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, \n\t  0x74, 0x69, 0x6d, 0x65, 0x2e, 0x68, 0x3e, 0x0a, \n\t  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, \n\t  0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, 0x65, \n\t  0x72, 0x6d, 0x69, 0x6f, 0x73, 0x2e, 0x68, 0x3e, \n\t  0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, \n\t  0x65, 0x20, 0x3c, 0x73, 0x79, 0x73, 0x2f, 0x74, \n\t  0x65, 0x72, 0x6d, 0x69, 0x6f, 0x2e, 0x68, 0x3e, \n\t  0x09, 0x09, 0x2f, 0x2a, 0x20, 0x64, 0x65, 0x66, \n\t  0x69, 0x6e, 0x65, 0x20, 0x54, 0x43, 0x53, 0x42, \n\t  0x52, 0x4b, 0x20, 0x2a, 0x2f, 0x0a, 0x23, 0x69, \n\t  0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, \n\t  0x73, 0x79, 0x73, 0x2f, 0x70, 0x61, 0x72, 0x61, \n\t  0x6d, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x65, 0x78, \n\t  0x74, 0x65, 0x72, 0x6e, 0x09, 0x69, 0x6e, 0x74, \n\t  0x09, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x20, 0x3b, \n\t  0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, \n\t  0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09, \n\t  0x7a, 0x65, 0x72, 0x6f, 0x73, 0x5b, 0x34, 0x5d, \n\t  0x20, 0x3d, 0x20, 0x7b, 0x30, 0x2c, 0x30, 0x2c, \n\t  0x30, 0x2c, 0x30, 0x7d, 0x20, 0x3b, 0x0a, 0x0a, \n\t  0x6d, 0x61, 0x69, 0x6e, 0x28, 0x61, 0x72, 0x67, \n\t  0x63, 0x2c, 0x61, 0x72, 0x67, 0x76, 0x29, 0x0a, \n\t  0x09, 0x69, 0x6e, 0x74, 0x09, 0x61, 0x72, 0x67, \n\t  0x63, 0x20, 0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61, \n\t  0x72, 0x09, 0x2a, 0x2a, 0x61, 0x72, 0x67, 0x76, \n\t  0x20, 0x3b, 0x0a, 0x7b, 0x0a, 0x09, 0x73, 0x74, \n\t  0x72, 0x75, 0x63, 0x74, 0x09, 0x74, 0x65, 0x72, \n\t  0x6d, 0x69, 0x6f, 0x73, 0x09, 0x6f, 0x6c, 0x64, \n\t  0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, \n\t  0x73, 0x2c, 0x20, 0x6e, 0x65, 0x77, 0x5f, 0x73, \n\t  0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, \n\t  0x3b, 0x0a, 0x09, 0x66, 0x64, 0x5f, 0x73, 0x65, \n\t  0x74, 0x09, 0x72, 0x65, 0x61, 0x64, 0x66, 0x64, \n\t  0x73, 0x20, 0x3b, 0x0a, 0x09, 0x73, 0x74, 0x72, \n\t  0x75, 0x63, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, \n\t  0x76, 0x61, 0x6c, 0x20, 0x74, 0x69, 0x6d, 0x65, \n\t  0x6f, 0x75, 0x74, 0x20, 0x3b, 0x0a, 0x09, 0x69, \n\t  0x6e, 0x74, 0x09, 0x69, 0x20, 0x3b, 0x0a, 0x09, \n\t  0x69, 0x6e, 0x74, 0x09, 0x6c, 0x65, 0x6e, 0x20, \n\t  0x3b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x72, 0x09, \n\t  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5b, 0x31, \n\t  0x30, 0x32, 0x34, 0x5d, 0x20, 0x3b, 0x0a, 0x09, \n\t  0x69, 0x6e, 0x74, 0x09, 0x64, 0x6f, 0x6e, 0x65, \n\t  0x20, 0x3d, 0x20, 0x30, 0x20, 0x3b, 0x0a, 0x09, \n\t  0x69, 0x6e, 0x74, 0x09, 0x66, 0x69, 0x6c, 0x65, \n\t  0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, \n\t  0x30, 0x20, 0x3b, 0x0a, 0x09, 0x5a, 0x4d, 0x6f, \n\t  0x64, 0x65, 0x6d, 0x09, 0x69, 0x6e, 0x66, 0x6f, \n\t  0x20, 0x3b, 0x0a, 0x0a, 0x23, 0x69, 0x66, 0x64, \n\t  0x65, 0x66, 0x09, 0x54, 0x45, 0x53, 0x54, 0x0a, \n\t  0x0a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x09, \n\t  0x75, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x09, 0x41, \n\t  0x6d, 0x73, 0x67, 0x30, 0x5b, 0x5d, 0x20, 0x3d, \n\t  0x20, 0x7b, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, \n\t  0x37, 0x32, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x61, \n\t  0x2c, 0x20, 0x30, 0x78, 0x30, 0x64, 0x2c, 0x20, \n\t  0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, 0x78, \n\t  0x32, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x31, 0x38, \n\t  0x2c, 0x20, 0x30, 0x78, 0x34, 0x32, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x0a, 0x09, \n\t  0x20, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, \n\t  0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x64, \n\t  0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20, \n\t  0x30, 0x78, 0x31, 0x31, 0x2c, 0x20, 0x0a, 0x09, \n\t  0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74, \n\t  0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, \n\t  0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x31, 0x5b, \n\t  0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, \n\t  0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34, \n\t  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x34, 0x2c, \n\t  0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, \n\t  0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x64, \n\t  0x64, 0x2c, 0x20, 0x30, 0x78, 0x35, 0x31, 0x2c, \n\t  0x20, 0x30, 0x78, 0x61, 0x32, 0x2c, 0x20, 0x30, \n\t  0x78, 0x33, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x37, \n\t  0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x34, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x63, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, \n\t  0x78, 0x32, 0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, \n\t  0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x37, 0x2c, 0x20, 0x30, \n\t  0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x35, 0x2c, 0x20, 0x30, \n\t  0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, 0x30, \n\t  0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x18, 0x6a, 0xf8, 0x0e, \n\t  0xd1, 0x2f, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x0a, \n\t  0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30, \n\t  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, \n\t  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, \n\t  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, \n\t  0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x62, 0x2c, 0x20, 0x30, 0x78, 0x63, \n\t  0x63, 0x2c, 0x20, 0x30, 0x78, 0x38, 0x38, 0x2c, \n\t  0x20, 0x30, 0x78, 0x38, 0x36, 0x2c, 0x20, 0x0a, \n\t  0x09, 0x20, 0x20, 0x30, 0x78, 0x31, 0x61, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x7d, 0x20, 0x3b, 0x0a, 0x73, \n\t  0x74, 0x61, 0x74, 0x69, 0x63, 0x09, 0x75, 0x5f, \n\t  0x63, 0x68, 0x61, 0x72, 0x09, 0x41, 0x6d, 0x73, \n\t  0x67, 0x32, 0x5b, 0x5d, 0x20, 0x3d, 0x20, 0x7b, \n\t  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x61, \n\t  0x2c, 0x20, 0x30, 0x78, 0x31, 0x38, 0x2c, 0x20, \n\t  0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30, 0x78, \n\t  0x30, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x30, 0x30, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, \n\t  0x30, 0x78, 0x64, 0x64, 0x2c, 0x20, 0x30, 0x78, \n\t  0x35, 0x31, 0x2c, 0x20, 0x30, 0x78, 0x61, 0x32, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x33, 0x2c, 0x20, \n\t  0x30, 0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78, \n\t  0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39, \n\t  0x2c, 0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20, \n\t  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37, 0x33, \n\t  0x2c, 0x20, 0x30, 0x78, 0x32, 0x65, 0x2c, 0x20, \n\t  0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30, 0x78, \n\t  0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x37, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, \n\t  0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x37, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x35, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, \n\t  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x33, 0x31, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x34, 0x2c, 0x20, 0x30, 0x78, \n\t  0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, 0x31, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, \n\t  0x30, 0x78, 0x33, 0x36, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x33, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, 0x30, \n\t  0x2c, 0x20, 0x30, 0x78, 0x33, 0x30, 0x2c, 0x20, \n\t  0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, \n\t  0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x62, \n\t  0x2c, 0x20, 0x30, 0x78, 0x63, 0x63, 0x2c, 0x20, \n\t  0x30, 0x78, 0x38, 0x38, 0x2c, 0x20, 0x30, 0x78, \n\t  0x38, 0x36, 0x2c, 0x20, 0x0a, 0x09, 0x20, 0x20, \n\t  0x30, 0x78, 0x31, 0x61, 0x2c, 0x20, 0x0a, 0x09, \n\t  0x7d, 0x20, 0x3b, 0x0a, 0x73, 0x74, 0x61, 0x74, \n\t  0x69, 0x63, 0x09, 0x75, 0x5f, 0x63, 0x68, 0x61, \n\t  0x72, 0x09, 0x41, 0x6d, 0x73, 0x67, 0x33, 0x5b, \n\t  0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x32, 0x61, 0x2c, 0x20, 0x30, \n\t  0x78, 0x31, 0x38, 0x2c, 0x20, 0x30, 0x78, 0x34, \n\t  0x33, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, \n\t  0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, \n\t  0x78, 0x30, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, \n\t  0x30, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x30, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x62, \n\t  0x63, 0x2c, 0x20, 0x30, 0x78, 0x65, 0x66, 0x2c, \n\t  0x20, 0x30, 0x78, 0x39, 0x32, 0x2c, 0x20, 0x30, \n\t  0x78, 0x38, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x30, \n\t  0x61, 0x2c, 0x20, 0x30, 0x78, 0x32, 0x33, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x65, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x63, 0x2c, 0x20, 0x30, 0x78, 0x37, \n\t  0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, \n\t  0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x78, 0x33, \n\t  0x63, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x37, \n\t  0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, \n\t  0x20, 0x30, 0x78, 0x32, 0x66, 0x2c, 0x20, 0x30, \n\t  0x78, 0x37, 0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x35, 0x2c, 0x20, 0x30, 0x78, 0x37, 0x32, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x39, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x36, 0x66, 0x2c, 0x20, 0x30, \n\t  0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, 0x78, 0x32, \n\t  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c, \n\t  0x20, 0x30, 0x78, 0x33, 0x65, 0x2c, 0x20, 0x30, \n\t  0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x32, \n\t  0x33, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x39, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x36, \n\t  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x33, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x63, 0x2c, 0x20, 0x30, \n\t  0x78, 0x37, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x34, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, \n\t  0x20, 0x30, 0x78, 0x32, 0x30, 0x2c, 0x20, 0x30, \n\t  0x78, 0x32, 0x32, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x37, 0x38, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x66, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, \n\t  0x20, 0x30, 0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x64, 0x2c, 0x20, 0x30, 0x78, 0x32, \n\t  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x38, 0x2c, \n\t  0x20, 0x0a, 0x09, 0x20, 0x20, 0x30, 0x78, 0x32, \n\t  0x32, 0x2c, 0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, \n\t  0x20, 0x30, 0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, \n\t  0x78, 0x30, 0x61, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x39, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x65, 0x2c, \n\t  0x20, 0x30, 0x78, 0x37, 0x34, 0x2c, 0x20, 0x30, \n\t  0x78, 0x30, 0x61, 0x2c, 0x20, 0x0a, 0x09, 0x20, \n\t  0x20, 0x30, 0x78, 0x37, 0x33, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x35, 0x2c, 0x20, 0x30, 0x78, 0x36, \n\t  0x65, 0x2c, 0x20, 0x30, 0x78, 0x36, 0x34, 0x2c, \n\t  0x20, 0x30, 0x78, 0x34, 0x33, 0x2c, 0x20, 0x30, \n\t  0x78, 0x36, 0x18, 0x6a, 0x4a, 0xe5, 0x72, 0x71, \n\t} ;\n\n#define\tE(b)\t{b, sizeof(b)}\nstatic\tstruct {u_char *am; int len} Amsgs[] = {\n\t  E(Amsg0),\n\t  E(Amsg1),\n\t  E(Amsg2),\n\t  E(Amsg3),\n\t  E(Amsg4),} ;\n\n#endif\t/* TEST */\n\n\t/* try to trap uninit. variables */\n\tmemset(&info,0xa5,sizeof(info)) ;\n\n\tinfo.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32 ;\n\tinfo.packetsize = 128 ;\n\tinfo.bufsize = 0 ;\n\n#ifdef\tTEST\n\tdone = ZmodemRInit(&info) ;\n\tfor(i=0; !done; ++i )\n\t  done = ZmodemRcv(Amsgs[i].am, Amsgs[i].len, &info) ;\n\n#else\n\tif( argc < 2 )\n\t  exit(2) ;\n\n\tinfo.ifd = open(argv[1], O_RDWR) ;\n\n\tif( info.ifd == -1 )\n\t  exit(1) ;\n\n\ttcgetattr(info.ifd,&old_settings) ;\n\tnew_settings = old_settings ;\n\n\tnew_settings.c_iflag &=\n\t  ~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;\n\tnew_settings.c_oflag = 0 ;\n\tnew_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;\n\tnew_settings.c_lflag = 0 ;\n\tnew_settings.c_cc[VMIN] = 32 ;\n\tnew_settings.c_cc[VTIME] = 1 ;\n\ttcsetattr(info.ifd,TCSADRAIN, &new_settings) ;\n\n\tdone = ZmodemRInit(&info) ;\n\n\twhile(!done)\n\t{\n\t  FD_ZERO(&readfds) ;\n\t  FD_SET(info.ifd, &readfds) ;\n\t  timeout.tv_sec = info.timeout ;\n\t  timeout.tv_usec = 0 ;\n\t  i = select(info.ifd+1, &readfds,NULL,NULL, &timeout) ;\n\t  if( i<0 )\n\t    perror(\"select\") ;\n\t  else if( i==0 )\n\t    done = ZmodemTimeout(&info) ;\n\t  else {\n\t    len = read(info.ifd, buffer, sizeof(buffer)) ;\n\t    done = ZmodemRcv(buffer, len, &info) ;\n\t  }\n\t}\n\n\ttcsetattr(info.ifd,TCSADRAIN, &old_settings) ;\n#endif\t/* TEST */\n\texit(0) ;\n}\n\n\n\n\nint\nZXmitStr(buffer, len, info)\n\tu_char\t*buffer ;\n\tint\tlen ;\n\tZModem\t*info ;\n{\n\tint\ti,j ;\n\tu_char\tc ;\nextern\tdouble\tdrand48() ;\n\n#ifdef\tTEST\n\tfor(i=0; i<len; i += 16)\n\t{\n\t  printf(\"   \") ;\n\t  for(j=0; j<16 && i+j<len; ++j)\n\t    printf(\"%2.2x \", buffer[i+j]) ;\n\t  for(; j<16; ++j)\n\t    printf(\"   \") ;\n\t  printf(\"  |\") ;\n\t  for(j=0; j<16 && i+j<len; ++j)\n\t    putchar(((c=buffer[i+j]) < 040 || c >= 0177) ? '.' : c ) ;\n\t  printf(\"|\\n\") ;\n\t}\n#else\n\n#ifdef\tCOMMENT\n/* TEST: randomly corrupt one out of every 300 bytes */\nfor(i=0; i<len; ++i)\n  if( drand48() < 1./300. ) {\n    fprintf(stderr, \"byte %d was %2.2x, is\", i, buffer[i]) ;\n    buffer[i] ^= 1<<(lrand48()&7) ;\n    fprintf(stderr, \" %2.2x\\n\", buffer[i]) ;\n  }\n#endif\t/* COMMENT */\n\n\tif( write(info->ifd, buffer, len) != len )\n\t  return ZmErrSys ;\n#endif\t/* TEST */\n\n\treturn 0 ;\n}\n\n\nvoid\nZIFlush(info)\n\tZModem\t*info ;\n{\n}\n\nvoid\nZOFlush(info)\n\tZModem\t*info ;\n{\n}\n\nvoid\nZStatus(i,j,str)\n{\n\tfprintf(stderr,\"status %d=%d\\n\",i,j) ;\n}\n\n\nint\nZAttn(info)\n\tZModem\t*info ;\n{\n\tchar\t*ptr ;\n\tint\ti = 0 ;\n\n\tfor(ptr = info->attn; *ptr != '\\0'; ++ptr) {\n\t  if( *ptr == ATTNBRK )\n\t    ioctl(info->ifd, TCSBRK, 0) ;\n\t  else if( *ptr == ATTNPSE )\n\t    sleep(1) ;\n\t  else\n\t    write(info->ifd, ptr, 1) ;\n\t}\n\treturn 0 ;\n}\n\n\nFILE *\nZOpenFile(name, crc, info)\n\tchar\t*name ;\n\tuint32_t\tcrc ;\n\tZModem\t*info ;\n{\n\tstruct stat\tbuf ;\n\tint\t\texists ;\t/* file already exists */\nstatic\tint\t\tchangeCount = 0 ;\n\tchar\t\tname2[MAXPATHLEN] ;\n\tint\t\tapnd = 0 ;\n\tint\t\tf0,f1,f2,f3 ;\n\n\t/* TODO: if absolute path, do we want to allow it?\n\t * if relative path, do we want to prepend something?\n\t */\n\n\tif( *name == '/' )\t/* for now, disallow absolute paths */\n\t  return NULL ;\n\n\tif( stat(name, &buf) == 0 )\n\t  exists = 1 ;\n\telse if( errno == ENOENT )\n\t  exists = 0 ;\n\telse\n\t  return NULL ;\n\n\n\t/* if remote end has not specified transfer flags, we can\n\t * accept the local definitions\n\t */\n\n\tif( f0 == ZCRESUM ) {\t/* if exists, and we already have it, return */\n\t  if( exists  &&  buf.st_size == info->len )\n\t    return NULL ;\n\t  apnd = 1 ;\n\t}\n\n\t/* reject if file not found and it most be there (ZMSKNOLOC) */\n\tif( !exists && (f1 & ZMSKNOLOC) )\n\t  return NULL ;\n\n\tswitch( f1 & ZMMASK ) {\n\t  case 0:\t/* Implementation-dependent.  In this case, we\n\t\t\t * reject if file exists (and ZMSKNOLOC not set) */\n\t    if( exists && !(f1 & ZMSKNOLOC) )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMNEWL:\t/* take if newer or longer than file on disk */\n\t    if( exists  &&  info->date <= buf.st_mtime  &&\n\t\tinfo->len <= buf.st_size )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMCRC:\t\t/* take if different CRC or length */\n\t    if( exists  &&  info->len == buf.st_size && crc == FileCrc(name) )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMAPND:\t/* append */\n\t    apnd = 1 ;\n\t  case ZMCLOB:\t/* unconditional replace */\n\t    break ;\n\n\t  case ZMNEW:\t/* take if newer than file on disk */\n\t    if( exists  &&  info->date <= buf.st_mtime )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMDIFF:\t/* take if different date or length */\n\t    if( exists  &&  info->date == buf.st_mtime  &&\n\t\tinfo->len == buf.st_size )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMPROT:\t/* only if dest does not exist */\n\t    if( exists )\n\t      return NULL ;\n\t    break ;\n\n\t  case ZMCHNG:\t/* invent new filename if exists */\n\t    if( exists ) {\n\t      while( exists ) {\n\t\tsprintf(name2, \"%s_%d\", name, changeCount++) ;\n\t\texists = stat(name2, &buf) == 0 || errno != ENOENT ;\n\t      }\n\t      name = name2 ;\n\t    }\n\t    break ;\n\t}\n\n\t/* here if we've decided to accept */\n\tif( exists && !apnd && unlink(name) != 0 )\n\t  return NULL ;\n\n\t/* TODO: build directory path if needed */\n\n\treturn fopen(name, apnd ? \"a\" : \"w\") ;\n}\n\n\nint\nZWriteFile(buffer, len, file, info)\n\tu_char\t*buffer ;\n\tint\tlen ;\n\tFILE\t*file ;\n\tZModem\t*info ;\n{\n\t/* TODO: if ZCNL set in info->f0, convert\n\t * newlines to local convention\n\t */\n\n\treturn fwrite(buffer, 1, len, file) == len ? 0 : ZmErrSys ;\n}\n\n\nint\nZCloseFile(info)\n\tZModem *info ;\n{\n\tfclose(info->file) ;\n\tchmod(info->filename, info->mode&0777) ;\n}\n"
  },
  {
    "path": "bbs/prot/reference/send.cpp",
    "content": "#include <cstdint>\n#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n\n#define\tTEST\t/* standalone test */\n\n#include <unistd.h>\n#include <string.h>\n#include \"zmodem.h\"\n#include <sys/stat.h>\n\n#include <fcntl.h>\n#include <errno.h>\n#include <sys/time.h>\n#include <sys/termios.h>\n#include <sys/termio.h>\t\t/* define TCSBRK */\n#include <sys/param.h>\n\nextern\tint\terrno ;\n\nstatic\tu_char\tzeros[4] = {0,0,0,0} ;\n\nmain(argc,argv)\n\tint\targc ;\n\tchar\t**argv ;\n{\n\tstruct\ttermios\told_settings, new_settings ;\n\tfd_set\treadfds ;\n\tstruct timeval timeout ;\n\tint\ti ;\n\tint\tlen ;\n\tchar\tbuffer[1024] ;\n\tint\tdone = 0 ;\n\tint\tfilecount = 0 ;\n\tZModem\tinfo ;\n\n#ifdef\tTEST\n\nstatic\tu_char\tAmsg0[] = {\n\t  0x43, \n\t} ;\nstatic\tu_char\tAmsg1[] = {\n\t  0x06, 0x43, \n\t} ;\nstatic\tu_char\tAmsg2[] = {\n\t  0x06, \n\t} ;\nstatic\tu_char\tAmsg3[] = {\n\t  0x06, \n\t} ;\nstatic\tu_char\tAmsg4[] = {\n\t  0x06, 0x43, \n\t} ;\nstatic\tu_char\tAmsg5[] = {\n\t  0x06, 0x43, \n\t} ;\nstatic\tu_char\tAmsg6[] = {\n\t  0x06, \n\t} ;\nstatic\tu_char\tAmsg7[] = {\n\t  0x06, \n\t} ;\nstatic\tu_char\tAmsg8[] = {\n\t  0x06, \n\t} ;\nstatic\tu_char\tAmsg9[] = {\n\t  0x06, 0x43, \n\t} ;\n\n\n#define\tE(b)\t{b, sizeof(b)}\nstatic\tstruct {u_char *bm; int len} Bmsgs[] = {\n\t  E(Amsg0),\n\t  E(Amsg1),\n\t  E(Amsg2),\n\t  E(Amsg3),\n\t  E(Amsg4),\n\t  E(Amsg5),\n\t  E(Amsg6),\n\t  E(Amsg7),\n\t  E(Amsg8),\n\t  E(Amsg9),} ;\n\n\n#endif\t/* TEST */\n\n\t/* try to trap uninit. variables */\n\tmemset(&info,0xa5,sizeof(info)) ;\n\n\tinfo.zsinitflags = 0 ;\n\tinfo.attn = \"\\17\\336\" ;\n\tinfo.packetsize = 1024 ;\n\tinfo.windowsize = 4096 ;\n\n#ifdef\tTEST\n\tdone = YmodemTInit(&info) ;\n\tfor(i=0; !done; ++i )\n\t  done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;\n\n\tdone = ZmodemTFile(\"utils.c\",\"utils.c\", 0,0,0,0, 1,0, &info) ;\n\tfor(; !done; ++i )\n\t  done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;\n\n\tdone = ZmodemTFile(\"foo.c\",\"foo.c\", 0,0,0,0, 1,0, &info) ;\n\tfor(; !done; ++i )\n\t  done = ZmodemRcv(Bmsgs[i].bm, Bmsgs[i].len, &info) ;\n\n\tdone = ZmodemTFinish(info) ;\n\n#else\n\tif( argc < 2 )\n\t  exit(2) ;\n\n\tinfo.ifd = open(argv[1], O_RDWR) ;\n\n\tif( info.ifd == -1 )\n\t  exit(1) ;\n\n\ttcgetattr(info.ifd,&old_settings) ;\n\tnew_settings = old_settings ;\n\n\tnew_settings.c_iflag &=\n\t  ~(ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXOFF|IMAXBEL) ;\n\tnew_settings.c_oflag = 0 ;\n\tnew_settings.c_cflag = B300|CS8|CREAD|CLOCAL ;\n\tnew_settings.c_lflag = 0 ;\n\tnew_settings.c_cc[VMIN] = 32 ;\n\tnew_settings.c_cc[VTIME] = 1 ;\n\ttcsetattr(info.ifd,TCSADRAIN, &new_settings) ;\n\n\tInitXmit(&info) ;\n\tXmitFile(\"utils.c\",1,0,&info) ;\n#ifdef\tCOMMENT\n\tXmitFile(\"foo\",1,0,&info) ;\n\tXmitFile(\"foo.c\",1,0,&info) ;\n\tXmitFile(\"raw\",1,0,&info) ;\n#endif\t/* COMMENT */\n\tFinishXmit(&info) ;\n\n\ttcsetattr(info.ifd,TCSADRAIN, &old_settings) ;\n#endif\t/* TEST */\n\texit(0) ;\n}\n\n\nstatic\tint\ndoIO(info)\n\tZModem\t*info ;\n{\n\tfd_set\treadfds ;\n\tstruct timeval timeout ;\n\tint\ti ;\n\tint\tlen ;\n\tchar\tbuffer[1024] ;\n\tint\tdone = 0 ;\n\n\twhile(!done)\n\t{\n\t  FD_ZERO(&readfds) ;\n\t  FD_SET(info->ifd, &readfds) ;\n\t  timeout.tv_sec = info->timeout ;\n\t  timeout.tv_usec = 0 ;\n\t  i = select(info->ifd+1, &readfds,NULL,NULL, &timeout) ;\n\t  if( i<0 )\n\t    perror(\"select\") ;\n\t  else if( i==0 )\n\t    done = ZmodemTimeout(info) ;\n\t  else {\n\t    len = read(info->ifd, buffer, sizeof(buffer)) ;\n\t    done = ZmodemRcv(buffer, len, info) ;\n\t  }\n\t}\n\treturn done ;\n}\n\n\nint\nInitXmit(info)\n\tZModem\t*info ;\n{\n\tint\tdone ;\n\n\tdone = ZmodemTInit(info) ;\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\nXmitFile(filename,nfiles,nbytes,info)\n\tchar\t*filename ;\n\tint\tnfiles, nbytes ;\n\tZModem\t*info ;\n{\n\tint\tdone ;\n\n\tdone = ZmodemTFile(filename,filename, 0,ZMCLOB,0,0,\n\t\tnfiles,nbytes, info) ;\n\tif( done == ZmErrCantOpen || done == ZmFileTooLong )\n\t  return 0 ;\n\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\n\nFinishXmit(info)\n\tZModem\t*info ;\n{\n\tint\tdone ;\n\n\tdone = ZmodemTFinish(info) ;\n\tif( !done )\n\t  done = doIO(info) ;\n\n\treturn done != ZmDone ;\n}\n\n\nint\nZXmitStr(buffer, len, info)\n\tu_char\t*buffer ;\n\tint\tlen ;\n\tZModem\t*info ;\n{\n\tint\ti,j ;\n\tu_char\tc ;\nextern\tdouble\tdrand48() ;\n\n#ifdef\tTEST\n\tfor(i=0; i<len; i += 16)\n\t{\n\t  printf(\"   \") ;\n\t  for(j=0; j<16 && i+j<len; ++j)\n\t    printf(\"%2.2x \", buffer[i+j]) ;\n\t  for(; j<16; ++j)\n\t    printf(\"   \") ;\n\t  printf(\"  |\") ;\n\t  for(j=0; j<16 && i+j<len; ++j)\n\t    putchar(((c=buffer[i+j]) < 040 || c >= 0177) ? '.' : c ) ;\n\t  printf(\"|\\n\") ;\n\t}\n#else\n\n#ifdef\tCOMMENT\n/* TEST: randomly corrupt one out of every 300 bytes */\nfor(i=0; i<len; ++i)\n  if( drand48() < 1./300. ) {\n    fprintf(stderr, \"byte %d was %2.2x, is\", i, buffer[i]) ;\n    buffer[i] ^= 1<<(lrand48()&7) ;\n    fprintf(stderr, \" %2.2x\\n\", buffer[i]) ;\n  }\n#endif\t/* COMMENT */\n\n\tif( write(info->ifd, buffer, len) != len )\n\t  return ZmErrSys ;\n#endif\t/* TEST */\n\n\treturn 0 ;\n}\n\n\nvoid\nZIFlush(info)\n\tZModem\t*info ;\n{\n}\n\nvoid\nZOFlush(info)\n\tZModem\t*info ;\n{\n}\n\nvoid\nZStatus(i,j,str)\n{\n\tfprintf(stderr,\"status %d=%d\\n\",i,j) ;\n}\n\n\nint\nZAttn(info)\n\tZModem\t*info ;\n{\n\tchar\t*ptr ;\n\tint\ti = 0 ;\n\n\tfor(ptr = info->attn; *ptr != '\\0'; ++ptr) {\n\t  if( *ptr == ATTNBRK )\n\t    ioctl(info->ifd, TCSBRK, 0) ;\n\t  else if( *ptr == ATTNPSE )\n\t    sleep(1) ;\n\t  else\n\t    write(info->ifd, ptr, 1) ;\n\t}\n\treturn 0 ;\n}\n\n\nFILE *\nZOpenFile(name, f0,f1,f2,f3, len, date, mode, filesRem, bytesRem, crc)\n\tchar\t*name ;\n\tint\tf0,f1,f2,f3, len, mode, filesRem, bytesRem ;\n\tlong\tdate ;\n\tuint32_t\tcrc ;\n{\n}\n\n\nint\nZWriteFile()\n{}\n\n\nZCloseFile(info)\n\tZModem *info ;\n{}\n\nZFlowControl(info)\n\tZModem *info ;\n{}\n"
  },
  {
    "path": "bbs/prot/reference/seriallog.cpp",
    "content": "#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n/* seriallog routines.  Write data to log file, tagged with timestamp\n * and channel.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n#include <sys/time.h>\n\n#include \"seriallog.h\"\n\nstatic\tstruct timeval\ttimestamp = {0,0} ;\n\n#define\tDTIME\t1500\t\t/* timeout, milliseconds */\n\nstatic\tint\twhich = -1 ;\t/* last transmitted */\n\nstatic\tchar\tobuf[4096] ;\nstatic\tint\tolen = -1 ;\n\n\tFILE\t*SerialLogFile = NULL ;\n\n\t/* flush out buffered text */\n\nvoid\nSerialLogFlush()\n{\n\tint\ti ;\n\n\tif( SerialLogFile == NULL )\n\t  return ;\n\n\tif( which != -1 && olen > 0 )\n\t{\n\t  i = fwrite((char *)&which, sizeof(int), 1, SerialLogFile) ;\n\t  i = fwrite((char *)&timestamp, sizeof(timestamp), 1, SerialLogFile) ;\n\t  i = fwrite((char *)&olen, sizeof(int), 1, SerialLogFile) ;\n\t  i = fwrite(obuf, 1, olen, SerialLogFile) ;\n\t}\n\tfflush(SerialLogFile) ;\n\n\twhich = -1 ;\n\tolen = 0 ;\n}\n\n\nvoid\nSerialLog(const void *data, int len, int w)\n{\n\tstruct timezone\tz ;\n\tstruct timeval\ttime ;\n\tint\tdt ;\n\tint\ti ;\n\n\tif( SerialLogFile == NULL )\n\t  return ;\n\n\tgettimeofday(&time, &z) ;\n\tdt = (time.tv_sec - timestamp.tv_sec)*1000 +\n\t     (time.tv_usec - timestamp.tv_usec)/1000 ;\n\n\tif( w != which || dt > DTIME ) {\n\t  SerialLogFlush() ;\n\t  which = w ;\n\t  timestamp = time ;\n\t}\n\n\twhile( len > 0 )\n\t{\n\t  if( olen+len > sizeof(obuf) )\n\t    SerialLogFlush() ;\n\n\t  i = len > sizeof(obuf) ? sizeof(obuf) : len ;\n\t  bcopy(data, obuf+olen, i) ;\n\t  olen += i ;\n\t  len -= i ;\n\t}\n}\n"
  },
  {
    "path": "bbs/prot/reference/seriallog.h",
    "content": "/*\t$Id$\t*/\n\n#ifndef\tSERIALLOG_H\n#define\tSERIALLOG_H\n\n\nextern\tFILE\t*SerialLogFile ;\nextern\tvoid\tSerialLogFlush() ;\nextern\tvoid\tSerialLog(const void *data, int len, int w) ;\n\n#endif\n"
  },
  {
    "path": "bbs/prot/reference/utils.cpp",
    "content": "#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n/*\n * Copyright (c) 1995 by Edward A. Falk\n */\n\n\n/**********\n *\n *\n *\t@   @  @@@@@   @@@   @       @@@@  \n *\t@   @    @      @    @      @      \n *\t@   @    @      @    @       @@@   \n *\t@   @    @      @    @          @  \n *\t @@@     @     @@@   @@@@@  @@@@   \n *\n *\tUTILS - utilities used by xmodem library.\n *\n *\tRoutines provided here:\n *\n *\n *\tname (args)\n *\t\tBrief description.\n *\n *\tint sendCancel()\n *\n *\t\tsend cancel string <CAN><CAN>\n *\n *\n *\tint sendFlush(c)\n *\t\tchar\tc ;\n *\n *\t\tflush input, send one character, return nonzero on error\n *\n *\n *\tint sendChr(c)\n *\t\tchar\tc ;\n *\n *\t\tsend one character, return nonzero on error\n *\n *\n *\tint sendStr(str, len)\n *\t\tchar\t*str ;\n *\t\tint\tlen ;\n *\n *\t\tsend string, return nonzero on error\n *\n *\n *\tint calcChecksum(ptr, count)\n *\t\tchar\t*ptr ;\n *\t\tint\tcount ;\n *\n *\t\tcompute checksum (used by xmodem)\n *\n *\n *\tEdward A. Falk\n *\n *\tJanuary, 1995\n *\n *\n *\n **********/\n\n\n\n\n//#include <sys/termios.h>\n//#include <sys/ioctl.h>\n#include \"xmodem.h\"\n\n\nint\nsendCancel()\n{\n\treturn sendFlush(CAN) || sendFlush(CAN) ;\n}\n\n\n\t/* send one character, return nonzero on error */\nint\nsendFlush(char c)\n{\n\t/* first, flush input port */\n\t/* TODO: caller provide a way to do this? */\n\n\tif( xmRfd == -1 )\n\t  return XmErrNotOpen ;\n\n\t/* TODO: caller provides flush */\n\tif( ioctl(xmRfd, TCFLSH, TCIFLUSH) == -1 )\n\t  return XmErrSys ;\n\n\treturn sendChr(c) ;\n}\n\n\n\t/* send one character, return nonzero on error */\n\nint\nsendChr(char c)\n{\n\t/* TODO: caller provide character output func? */\n\tif( xmTfd == -1 )\n\t  return XmErrNotOpen ;\n\n\treturn write(xmTfd, &c, 1) ==1 ? 0 : XmErrSys ;\n}\n\n\n\t/* send multiple characters, return nonzero on error */\n\nint\nsendStr(char *str, int len)\n{\n\t/* TODO: caller provide character output func? */\n\tif( xmTfd == -1 )\n\t  return XmErrNotOpen ;\n\n\treturn write(xmTfd, str, len) == len ? 0 : XmErrSys ;\n}\n\n\t/* compute checksum */\n\nint\ncalcChecksum(char *ptr, int count)\n{\n\tint csum = 0 ;\n\twhile( --count >= 0 )\n\t  csum += (u_char) *ptr++ ;\n\treturn csum & 255 ;\n}\n"
  },
  {
    "path": "bbs/prot/reference/zmodem.txt",
    "content": "\n   These routines are intended to be incorportated into other programs,\n   and do not constitute a zmodem program by themselves, although a\n   demo zmodem program that uses these routines has been included.\n\n   All information pertaining to a transfer session is kept in a data\n   structure defined by the caller.  This makes it possible for the\n   caller to drive multiple simultaneous sessions.\n\n   Caller provides I/O, timing and query routines.  Caller remains\n   in control at all times.  Typical use is to call these routines\n   from a select(2) loop.\n\n   Overview:\n\n    Transmit files:\n\n      1 Init ZModem structure and open communications channel.\n      2 Call ZmodemTInit() to begin protocol.\n      3 Read characters from remote end and pass them to\n\tZmodemRcv() until ZmodemRcv() returns ZmDone or an error.\n      4 Call ZmodemTFile() to begin transfer of a file.\n      5 Read characters from remote end and pass them to\n\tZmodemRcv() until ZmodemRcv() returns ZmDone or an error.\n      6 repeat steps 4&5 for all files.\n      7 Call ZmodemTFinish() to indicate that all files have been\n\ttransfered.\n      8 Read characters from remote end and pass them to\n\tZmodemRcv() until ZmodemRcv() returns ZmDone or an error.\n\n    Receive files:\n\n      1 Init ZModem structure and open communications channel.\n      2 Call ZmodemRInit() to begin protocol.\n      3 Read characters from remote end and pass them to\n\tZmodemRcv() until ZmodemRcv() returns ZmDone or an error.\n\n\n\n   In detail:\n\n   1) Create a ZModem structure as defined below and fill it in.\n\n      'ifd', 'ofd' are the file descriptors used for input and output.\n\tThe interpretation of ifd and ofd is entirely up to the calling\n\troutines, since the caller will be providing I/O functions.\n\n      'zrinitflags' is composed of the flags described below.\n\tThey describe the receive channel capabilities\n\tand affect how the protocol will be carried out.\n\tDefine these to receive files.  When sending files, these\n\tflags will be defined from the remote end.\n\n      'zsinitflags' is composed of the flags described below.\n\tThey describe the transmit channel capabilities\n\tand affect how the protocol will be carried out.\n\tDefine these to send files.  When receiving files, these\n\tflags will be defined from the remote end.\n\n      'attn': For transmit, this is the optional nul-terminated\n\tattention string to be sent by the receiver to interrupt the\n\ttransmission.  For example, it might simply contain ^O to flush\n\tthe buffers, or it might interrupt the sending program.  Caller\n\tneeds to handle this interrupt properly and call ZmodemAttention().\n\n\tFor receive, this is the optional nul-terminated attention string\n\tdefined at the remote end.  Caller needs to provide a function that\n\tcan execute this sequence.\n\n      'timeout' is read-only, set by the zmodem package.  It is the\n\ttimeout value in seconds.  If this much time passes without\n\tanything being received, caller should call the ZmodemTimeout()\n\tfunction.  Note that timeout may be zero, in which case the\n\tZTimeout function should be called immediately if no characters\n\tare ready to be received.\n\n      'packetsize' is set to the preferred data packet size.  Define\n\tthis when sending files.  Recommended length values are 256\n\tbytes below 2400 bps, 512 at 2400 bps, and 1024 above 4800 bps\n\tor when the data link is known to be relatively error free.\n\tIgnored during receive.\n\n      'bufsize' is set to the size of the receive buffer size.  Define\n\tthis when receiving files.  When sending files, this will be\n\tdefined at the other end.\n\n      'windowsize' is used to prevent network connections from\n\tbuffering too many characters during transmit.  Setting\n\t'windowsize' to nonzero causes zmodem to request status reports\n\tfrom the receiver during transmit, and to pause if more than\n\tthis many bytes have been sent but not yet acknowledged.  Set\n\tto zero to turn off windowing.  Ignored during receive.\n\n      Other fields are used to track the internal state of the zmodem\n      driver functions.\n\n     Since this is a source package, you are, of course, free to extend\n     the ZModem structure as you see fit.\n\n\n   2) Define the following functions:\n\n\tint\n\tZXmitStr(u_char *str, int len, ZModem *info)\n\t\tTransmit a buffer.  Return 0 on success, ZmErrSys on error.\n\n\tvoid\n\tZIFlush(ZModem *info)\n\t\tFlush all unread input on receive channel.  Do nothing if\n\t\tthis is not possible.\n\n\tvoid\n\tZOFlush(ZModem *info)\n\t\tFlush all buffered but not-yet-transmitted output\n\t\ton transmit channel.  Do nothing if this is not possible.\n\n\tint\n\tZAttn(ZModem *info)\n\t\tSend attention signal defined in ZModem->attn.  Do\n\t\tnothing if this field is NULL.  Otherwise, this field\n\t\tis a nul-terminated character string to be\n\t\ttransmitted.  There are two special characters defined\n\t\tbelow: ATTNBRK (0335) indicates that a BREAK signal\n\t\tshould be sent, and ATTNPSE (0336) represents a\n\t\t1-second pause.\n\n\tvoid\n\tZFlowControl(int onoff, ZModem *info)\n\t\tTurn flow control on or off depending on the onoff flag.\n\n\tvoid\n\tZStatus(int type, int value, char *status)\n\t\tCalled to provide status information.  Ignore or display\n\t\tat your option.  Status string is not static, so copy\n\t\tit if you need it beyond this call.  Type is defined\n\t\tbelow under \"ZStatus() types\".\n\n\tFILE *\n\tZOpenFile(char *name, u_long crc, ZModem *info)\n\n\t\tCalled when receiving files, this function decides\n\t\twhether or not to accept the specified file, and\n\t\tif so, opens it for writing and returns the stdio\n\t\tfile handle.  If this function decides not to accept\n\t\tthe file, or cannot open the file, it returns NULL\n\t\tand the remote sender is told to skip this file.\n\n\t\tinfo->f0-f3 are the transfer flags, described below under\n\t\t\"ZFILE transfer flags\".  These describe the type of\n\t\ttransfer desired (binary/ascii), and conditions for the\n\t\ttransfer, such as 'transfer if source newer or longer'.\n\n\t\tinfo->len is the length of the file in bytes.  info->date is\n\t\tthe last modification date of the file, in seconds since\n\t\t1-jan-1970.  info->mode is the unix file mode + 01000000, or\n\t\tzero if not known.  info->filesRem and info->bytesRem are the\n\t\tnumber of files and bytes remaining to be transferred\n\t\tif known, zero otherwise.  'crc' is the file crc-32 value.\n\t\tThis is only provided if F1 contains ZMCRC.\n\n\tint\n\tZWriteFile(u_char *buffer, int len, FILE *file, ZModem *info)\n\t\tWrite a buffer of data to the file.  Normally, you would\n\t\tsimply call fwrite(buffer, 1, len, file), but you may\n\t\twant to translate line endings, etc.  File transfer\n\t\tflags are available as info->f0,f1,f2,f3.\n\n\t\tReturn 0 on success, ZmErrSys on failure, with errno\n\t\tdescribing the failure.\n\n\n\tint\n\tZCloseFile(ZModem *info)\n\t\tClose file after successful completion.  File modification\n\t\tdate and modes should be set at this time.\t\n\n\tvoid\n\tZIdleStr(u_char *buffer, int len, ZModem *info)\n\t\tCalled to pass text that is received out-of-protocol.\n\t\tThis function may ignore or display this text at your\n\t\toption.\n\n\n  3) Open the communications channel.\n\n\tIf possible, this should be a full-duplex channel with full\n\t8-bit transmission.  Hardware flow control and/or XON/XOFF\n\tflow control should be enabled.\n\n\n  4) Call these routines:\n\n\tAll functions return 0 on success, nonzero on failure.  See\n\t\"error code definitions\", below.\n\n    Send:\n\n\tint\n\tZmodemTInit(ZModem *info)\n\t\tBegin a Zmodem transmit session.\n\n\tint\n\tZmodemRcv(u_char *buffer, int len, ZModem *info)\n\t\tCall whenever characters are received.  If this function\n\t\treturns ZmDone, previous function has completed successfully,\n\t\teither call ZmodemTFile() to start next file, or call\n\t\tZmodemTFinish() to terminate the session.\n\n\tint\n\tZmodemTimeout(ZModem *info)\n\t\tCall whenever the timeout period expires and no\n\t\tcharacters have been received.\n\n\tint\n\tZmodemAttention(ZModem *info)\n\t\tCall whenever the attention sequence has been received\n\t\tfrom the remote end.  It is safe to call this function\n\t\tfrom an interrupt handler.\n\n\tint\n\tZmodemTFile(char *filename, char *rfilename, \n\t  u_char f0,f1,f2,f3, int filesRem, int bytesRem, ZModem *info)\n\t\tBegin transmitting a file.  If filename is not NULL,\n\t\tthen this function will open it.  Otherwise, info->file\n\t\tmust point to a stdio stream that is open for input.\n\t\tIt is preferable to provide the filename, so that\n\t\tZmodem can transmit file size and other information.\n\t\t'rfilename' is the filename given to the remote end.\n\t\tThis may be the same as filename, the file part of\n\t\tfilename, or something else alltogether.  'rfilename'\n\t\tmust not be longer than the smallest data packet the\n\t\tremote end might be willing to receive (about 200\n\t\tcharacters).  f0-f3 are transfer flags, see \"ZCBIN\"\n\t\tbelow.  'filesRem' and 'bytesRem' are the number of files\n\t\tand bytes remaining to be transmitted, if known; zero if\n\t\tnot.\n\n\t\tIf 'filename' cannot be accessed, ZmodemTFile() returns\n\t\tZmErrCantOpen.  The link is still established, so you\n\t\tneed to either proceed with the next file or call\n\t\tZmodemTFinish().\n\n\tint\n\tZmodemTFinish(ZModem *info)\n\t\tCall after final file transfer has completed successfully.\n\n\tint\n\tZmodemAbort(ZModem *info)\n\t\tCall to abort transfer.  Physical connection remains\n\t\topen until you close it.\n\n\n    Receive:\n\n\tint\n\tZmodemRInit(ZModem *info)\n\t\tCall to get ready to receive first file.  This function\n\t\twill inform the sender that we are ready to receive.\n\n\tint\n\tZmodemRcv(u_char *buffer, int len, ZModem *info)\n\t\tCall whenever characters are received.  If this\n\t\tfunction returns ZmDone, all file transfers have\n\t\tcompleted successfully.\n\n\tint\n\tZmodemTimeout(ZModem *info)\n\t\tCall whenever the timeout period expires and no\n\t\tcharacters have been received.\n\n\tint\n\tZmodemAbort(ZModem *info)\n\t\tCall to abort transfer.\n\n    Ymodem and Xmodem:\n\n\tint YmodemTInit(ZModem *info)\n\tint XmodemTInit(ZModem *info)\n\tint YmodemRInit(ZModem *info)\n\tint XmodemRInit(ZModem *info)\n\t\tSame semantics as ZmodemTInit and ZmodemRInit.  It is\n\t\tnot normally necessary to call the Ymodem*Init() functions\n\t\tas the Zmodem protocol will automatically switch to Ymodem\n\t\twhen needed.\n\n\n    Utility:\n\n\tu_long\n\tFileCrc(char *name)\n\t\tReturn CRC-32 of file.\n\n  5) Return Values:\n\n\tZmDone\t\tDone.  Proceed with next file or ZmodemTFinish\n\t\t\t(transmit) or exit (receive).\n\n\tZmErrInt\tInternal error.  Link has been closed.\n\tZmErrSys\tSystem error, see errno.  Link is closed.\n\tZmErrNotOpen\tnot used.\n\tZmFileTooLong\tnot used.\n\tZmFileCantWrite\tnot used.\n\tZmErrCantOpen\tCan not open file, see errno.  Link is still open.\n\tZmErrInitTo\tTransmitter failed to respond to init req.  Link closed.\n\tZmErrSequence\tPacket received out of sequence.  Link is closed.\n\tZmErrCancel\tCancelled by remote end.  Link is closed.\n\tZmErrRcvTo\tRemote end timed out during transfer.  Link is closed.\n\tZmErrSndTo\tRemote end timed out during transfer.  Link is closed.\n\tZmErrCmdTo\tRemote end timed out during transfer.  Link is closed.\n\n\tNote that \"link is closed\" means that the remote end is (presumably)\n\tno longer operating.  The actual communications channel is not\n\tclosed unless you close it.  \"Link is still open\" means that the\n\tremote end is still ready to receive the next file.\n"
  },
  {
    "path": "bbs/prot/reference/zmodemdump.cpp",
    "content": "#include <cstdint>\n#ifndef\tlint\nstatic const char rcsid[] = \"$Id$\" ;\n#endif\n\n\n\t/* variation on serialmon companion program serialdump, which\n\t * interprets data as a zmodem dialog\n\t */\n\n#include <stdio.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <time.h>\n//#include <sys/termios.h>\n#include <sys/types.h>\n//#include <sys/time.h>\n\n#include <assert.h>\n\n#include \"crctab.h\"\n\n#define\tMAXBUF\t2048\n#define\tMAXLINE\t16\n#define\tMAXHBUF\t128\n#define\tOLINELEN (MAXLINE*2)\n\n#define\tCAN\t030\n#define\tXON\t021\n\n#define\tZDLE\t030\n#define\tZPAD\t'*'\n#define\tZBIN\t'A'\n#define\tZHEX\t'B'\n#define\tZBIN32\t'C'\n#define\tZBINR32\t'D'\n#define\tZVBIN\t'a'\n#define\tZVHEX\t'b'\n#define\tZVBIN32\t'c'\n#define\tZVBINR32 'd'\n#define\tZRESC\t0177\n\n\n#define\tZRQINIT\t0\t/* request receive init */\n#define\tZRINIT\t1\t/* receive init */\n#define\tZSINIT\t2\t/* send init sequence, define Attn */\n#define\tZACK\t3\t/* ACK */\n#define\tZFILE\t4\t/* file name, from sender */\n#define\tZSKIP\t5\t/* skip file command, from receiver */\n#define\tZNAK\t6\t/* last packet was garbled */\n#define\tZABORT\t7\t/* abort */\n#define\tZFIN\t8\t/* finish session */\n#define\tZRPOS\t9\t/* resume file from this position, from receiver */\n#define\tZDATA\t10\t/* data packets to follow, from sender */\n#define\tZEOF\t11\t/* end of file, from sender */\n#define\tZFERR\t12\t/* fatal i/o error, from receiver */\n#define\tZCRC\t13\t/* request for file crc, from receiver */\n#define\tZCHALLENGE 14\t/* \"send this number back to me\", from receiver */\n#define\tZCOMPL\t15\t/* request is complete */\n#define\tZCAN\t16\t/* other end cancelled with CAN-CAN-CAN-CAN-CAN */\n#define\tZFREECNT 17\t/* request for free bytes on filesystem */\n#define\tZCOMMAND 18\t/* command, from sending program */\n#define\tZSTDERR\t19\t/* output this message to stderr */\n\n#define\tZCRCE\t'h'\n#define\tZCRCG\t'i'\n#define\tZCRCQ\t'j'\n#define\tZCRCW\t'k'\n#define\tZRUB0\t'l'\n#define\tZRUB1\t'm'\n\ntypedef\tenum {Idle, Padding, HexHeader, Header16, Header32,\n\t\tInData, InCrc} ZState ;\n\ntypedef\tstruct {\n\t  ZState\tstate ;\n\t  int\t\theadertype ;\n\t  int\t\tdata[4] ;\n\t  int\t\tcrcBytes[4] ;\n\t  int\t\tcount ;\n\t  int\t\tzdlePend ;\t/* ZDLE received */\n\t  int\t\tcrcCmd ;\n\t  int\t\tcrclen ;\n\t  uint32_t\tcrc ;\n\t} Zinfo ;\n\n\tu_char\tbuffer[MAXBUF] ;\n\tu_char\tline[MAXLINE] ;\n\tu_char\thbuffer[MAXHBUF] ;\n\tint\tlinecnt = 0 ;\n\tint\thbufcnt = 0 ;\n\n\nmain( int argc, char **argv )\n{\n\tint\ti,j ;\n\tint\tlen ;\n\tint\twhich ;\n\tstruct timeval\ttimestamp, oldtime ;\n\tstruct tm *tm ;\n\n\tZinfo\tAinfo, Binfo ;\n\n\tprintf(\"serial log.  'A' is application, 'B' is serial port\\n\\n\") ;\n\n\toldtime.tv_sec = 0 ;\n\n\tAinfo.state = Binfo.state = Idle ;\n\tAinfo.zdlePend = Binfo.zdlePend = 0 ;\n\n\twhile( (i=fread((char *)&which, sizeof(which), 1, stdin)) > 0 )\n\t{\n\t  i = fread((char *)&timestamp, sizeof(timestamp), 1, stdin) ;\n\t  i = fread((char *)&len, sizeof(len), 1, stdin) ;\n\t  if( timestamp.tv_sec != oldtime.tv_sec  ||\n\t      timestamp.tv_usec != oldtime.tv_usec )\n\t  {\n\t    if( linecnt > 0 )\n\t      dumpLine() ;\n\n\t    tm = localtime(&timestamp.tv_sec) ;\n\t    printf(\"%c: %2d:%2.2d:%2.2d.%2.2d\\n\", 'A'+which,\n\t      tm->tm_hour,tm->tm_min,tm->tm_sec, timestamp.tv_usec/10000 ) ;\n\n\t    oldtime = timestamp ;\n\t  }\n\n\n\t  while( len > 0 )\n\t  {\n\t    i = MAXBUF ;\n\t    if( len < i ) i = len ;\n\t    j = fread(buffer, 1, i, stdin) ;\nassert(j <= MAXBUF) ;\n\t    len -= j ;\n\t    parseData(which ? &Binfo : &Ainfo, j) ;\n\t  }\n\n\t  while( len > 0 )\n\t  {\n\t    i = MAXLINE - linecnt ;\n\t    if( len < i ) i = len ;\nassert(linecnt+i <= MAXLINE) ;\n\t    j = fread(line+linecnt, 1, i, stdin) ;\nassert(linecnt+j <= MAXLINE) ;\n\t    len -= j ;\n\t    linecnt += j ;\n\t    if( linecnt >= MAXLINE )\n\t      dumpLine() ;\n\t  }\n\t}\n\tif( linecnt > 0 )\n\t  dumpLine() ;\n\n\texit(0) ;\n}\n\nchar\ntoprintable(char c)\n{\n\tc &= 0177 ;\n\tif( c >= 0x20 && c <= 0x7e )\n\t  return c ;\n\telse\n\t  return '.' ;\n}\n\ndumpLine()\n{\n\tint\ti,j ;\n\n\tif( linecnt <= 0 )\n\t  return ;\n\n\tif( linecnt > MAXLINE ) linecnt = MAXLINE ;\n\tprintf(\"     \") ;\n\tfor(i=0; i<linecnt; ++i) {\nassert(i <= MAXLINE) ;\n\t  printf(\"%2.2x \", line[i]) ;\n\t}\n\tfor(; i<MAXLINE; ++i)\n\t  printf(\"   \") ;\n\tprintf(\"\\t|\") ;\n\tfor(i=0; i<linecnt; ++i) {\nassert(i <= MAXLINE) ;\n\t  printf(\"%c\",toprintable(line[i])) ;\n\t}\n\tprintf(\"|\\n\") ;\n\n\tlinecnt = 0 ;\n}\n\n\nstatic\tu_char\thexHeaderStart[] = {ZPAD,ZPAD,ZDLE,ZHEX} ;\nstatic\tu_char\theader16Start[] = {ZPAD,ZDLE,ZBIN} ;\nstatic\tu_char\theader32Start[] = {ZPAD,ZDLE,ZBIN32} ;\n\nparseData( Zinfo *info, int len )\n{\n\tu_char\t*ptr, c ;\n\tint\tidx ;\n\n\tfor(ptr = buffer; --len >= 0; ptr++) {\nassert(ptr >= buffer && ptr < buffer+MAXBUF) ;\n\t  c = *ptr ;\n\t  if( c != XON )\n\t    switch( info->state ) {\n\t      case Idle:\n\t\tif( c != ZPAD )\n\t\t  dataChar(c) ;\n\t\telse {\n\t\t  info->state = Padding ;\n\t\t  info->count = 1 ;\n\t\t  hbuffer[0] = c ;\n\t\t}\n\t\tbreak ;\n\n\t      case Padding:\n\t\tif( c == ZDLE ) {\n\t\t  info->zdlePend = 1 ;\n\t\t}\n\t\telse if( info->zdlePend ) {\n\t\t  info->zdlePend = 0 ;\n\t\t  info->count = 0 ;\n\t\t  switch(c) {\n\t\t    case ZHEX:\n\t\t      info->state = HexHeader ;\n\t\t      info->crclen=2 ;\n\t\t      info->crc = 0 ;\n\t\t      break ;\n\t\t    case ZBIN:\n\t\t      info->state = Header16 ;\n\t\t      info->crclen=2 ;\n\t\t      info->crc = 0 ;\n\t\t      break ;\n\t\t    case ZBIN32:\n\t\t      info->state = Header32 ;\n\t\t      info->crclen=4 ;\n\t\t      info->crc = 0xffffffff ;\n\t\t      break ;\n\t\t    default:\n\t\t      cancelHeader(info) ; break ;\n\t\t  }\n\t\t}\n\t\telse if( c == ZPAD )\n\t\t{\n\t\t  if( info->count < 2 ) {\nassert(info->count < MAXHBUF) ;\n\t\t    hbuffer[info->count++] = c ;\n\t\t  }\n\t\t  else\n\t\t    dataChar(c) ;\n\t\t}\n\t\telse\n\t\t  cancelHeader(info) ; break ;\n\t\tbreak ;\n\n\t      case HexHeader:\n\t\tif( c == ZDLE && !info->zdlePend ) {\n\t\t  info->zdlePend = 1 ;\n\t\t  break ;\n\t\t}\n\n\t\tif( info->zdlePend ) {\n\t\t  c = zdle(c) ;\n\t\t  info->zdlePend = 0 ;\n\t\t}\n\n\t\tidx = info->count++ ;\nassert(idx < MAXHBUF) ;\n\t\thbuffer[idx] = c ;\n\t\tif( info->count >= 16 ) {\t\t/* end of header */\n\t\t  info->headertype = hex2(hbuffer+0) ;\n\t\t  info->data[0] = hex2(hbuffer+2) ;\n\t\t  info->data[1] = hex2(hbuffer+4) ;\n\t\t  info->data[2] = hex2(hbuffer+6) ;\n\t\t  info->data[3] = hex2(hbuffer+8) ;\n\t\t  info->crcBytes[0] = hex2(hbuffer+10) ;\n\t\t  info->crcBytes[1] = hex2(hbuffer+12) ;\n\t\t  displayHeader(info) ;\n\t\t}\n\t\tbreak ;\n\n\t      case Header16:\n\t\tif( c == ZDLE && !info->zdlePend ) {\n\t\t  info->zdlePend = 1 ;\n\t\t  break ;\n\t\t}\n\n\t\tif( info->zdlePend ) {\n\t\t  c = zdle(c) ;\n\t\t  info->zdlePend = 0 ;\n\t\t}\n\n\t\tidx = info->count++ ;\nassert(idx < MAXHBUF) ;\n\t\thbuffer[idx] = c ;\n\t\tif( info->count >= 7 ) {\t\t/* end of header */\n\t\t  info->headertype = hbuffer[0] ;\n\t\t  info->data[0] = hbuffer[1] ;\n\t\t  info->data[1] = hbuffer[2] ;\n\t\t  info->data[2] = hbuffer[3] ;\n\t\t  info->data[3] = hbuffer[4] ;\n\t\t  info->crcBytes[0] = hbuffer[5] ;\n\t\t  info->crcBytes[1] = hbuffer[6] ;\n\t\t  displayHeader(info) ;\n\t\t}\n\t\tbreak ;\n\n\t      case Header32:\n\t\tif( c == ZDLE && !info->zdlePend ) {\n\t\t  info->zdlePend = 1 ;\n\t\t  break ;\n\t\t}\n\n\t\tif( info->zdlePend ) {\n\t\t  c = zdle(c) ;\n\t\t  info->zdlePend = 0 ;\n\t\t}\n\n\t\tidx = info->count++ ;\nassert(idx < MAXHBUF) ;\n\t\thbuffer[idx] = c ;\n\t\tif( info->count >= 9 ) {\t\t/* end of header */\n\t\t  info->headertype = hbuffer[0] ;\n\t\t  info->data[0] = hbuffer[1] ;\n\t\t  info->data[1] = hbuffer[2] ;\n\t\t  info->data[2] = hbuffer[3] ;\n\t\t  info->data[3] = hbuffer[4] ;\n\t\t  info->crcBytes[0] = hbuffer[5] ;\n\t\t  info->crcBytes[1] = hbuffer[6] ;\n\t\t  info->crcBytes[2] = hbuffer[7] ;\n\t\t  info->crcBytes[3] = hbuffer[8] ;\n\t\t  displayHeader(info) ;\n\t\t}\n\t\tbreak ;\n\n\t      case InData:\n\t\tif( info->zdlePend )\n\t\t{\n\t\t  info->zdlePend = 0 ;\n\t\t  switch( c ) {\n\t\t    case ZCRCE:\n\t\t    case ZCRCW:\n\t\t    case ZCRCG:\n\t\t    case ZCRCQ:\n\t\t      info->crcCmd = c ;\n\t\t      dumpLine() ;\n\t\t      info->state = InCrc ;\n\t\t      info->count = 0 ;\n\t\t      break ;\n\t\t    default:\n\t\t      c = zdle(c) ;\n\t\t      dataChar(c) ;\n\t\t      break ;\n\t\t  }\n\t\t}\n\t\telse if( c == ZDLE )\n\t\t  info->zdlePend = 1 ;\n\t\telse\n\t\t  dataChar(c) ;\n\t\tbreak ;\n\n\t      case InCrc:\n\t\tif( info->zdlePend ) {\n\t\t  c = zdle(c) ;\n\t\t  info->zdlePend = 0 ;\n\t\t}\n\n\t\tif( c == ZDLE )\n\t\t  info->zdlePend = 1 ;\n\t\telse\n\t\t{\n\t\t  dataChar(c) ;\n\t\t  if( ++info->count >= info->crclen )\n\t\t  {\n\t\t    dumpCrc() ;\n\t\t    switch( info->crcCmd ) {\n\t\t      case ZCRCE:\n\t\t\tprintf(\"     ZCRCE: end of frame, header follows\\n\") ;\n\t\t\tinfo->state = Idle ;\n\t\t\tbreak ;\n\t\t      case ZCRCW:\n\t\t\tprintf(\"     ZCRCW: end of frame, send ZACK\\n\") ;\n\t\t\tinfo->state = Idle ;\n\t\t\tbreak ;\n\t\t      case ZCRCG:\n\t\t\tprintf(\"     ZCRCG: more data follows:\\n\") ;\n\t\t\tinfo->state = InData ;\n\t\t\tbreak ;\n\t\t      case ZCRCQ:\n\t\t\tprintf(\"     ZCRCQ: send ZACK, more data follows:\\n\") ;\n\t\t\tinfo->state = InData ;\n\t\t\tbreak ;\n\t\t    }\n\t\t  }\n\t\t}\n\t\tbreak ;\n\t    }\n\t}\n}\n\n\n\t/* handle a character that's not part of the protocol */\n\ndataChar(int c)\n{\nassert(linecnt < MAXLINE) ;\n\tline[linecnt++] = c ;\n\tif( linecnt >= MAXLINE )\n\t  dumpLine() ;\n}\n\n\n\t/* here if we thought we were in a header, but were wrong */\n\ncancelHeader( Zinfo *info )\n{\n\tint\ti ;\n\n\tfor(i=0; i<info->count; ++i) {\nassert(i < MAXHBUF) ;\n\t  dataChar(hbuffer[i]) ;\n\t}\n\n\tinfo->state = Idle ;\n}\n\n\n\t/* here to display a full header.  CRC's not currently checked */\n\ndisplayHeader( Zinfo *info )\n{\n\tint\ti ;\n\tuint32_t\tcrc ;\n\tint\th32 = info->state == Header32 ;\nstatic\tchar\t*names[] = {\n\t  \"ZRQINIT\", \"ZRINIT\", \"ZSINIT\", \"ZACK\", \"ZFILE\", \"ZSKIP\",\n\t  \"ZNAK\", \"ZABORT\", \"ZFIN\", \"ZRPOS\", \"ZDATA\", \"ZEOF\", \"ZFERR\",\n\t  \"ZCRC\", \"ZCHALLENGE\", \"ZCOMPL\", \"ZCAN\", \"ZFREECNT\",\n\t  \"ZCOMMAND\", \"ZSTDERR\",} ;\n\n\tdumpLine() ;\n\n\tprintf(\"     \") ;\n\tswitch( info->state ) {\n\t  case HexHeader: printf(\"hex header\") ; break ;\n\t  case Header16: printf(\"bin header\") ; break ;\n\t  case Header32: printf(\"bin32 header\") ; break ;\n\t}\n\tprintf(\" %d: %s: d=[%x %x %x %x]\", info->headertype,\n\t  info->headertype <= ZSTDERR ? names[info->headertype] : \"BAD HEADER\",\n\t  info->data[0], info->data[1], info->data[2], info->data[3]) ;\n\tswitch( info->state ) {\n\t  case HexHeader:\n\t  case Header16:\n\t    printf(\" crc=[%x %x]\", info->crcBytes[0], info->crcBytes[1]) ;\n\t    break ;\n\t  case Header32:\n\t    printf(\" crc=[%x %x %x %x]\",\n\t      info->crcBytes[0], info->crcBytes[1],\n\t      info->crcBytes[2], info->crcBytes[3]) ;\n\t    break ;\n\t}\n\n\tswitch( info->headertype ) {\n\t  case ZRQINIT:\n\t  case ZRINIT:\n\t  case ZACK:\n\t  case ZSKIP:\n\t  case ZNAK:\n\t  case ZABORT:\n\t  case ZFIN:\n\t  case ZRPOS:\n\t  case ZEOF:\n\t  case ZFERR:\n\t  case ZCRC:\n\t  case ZCHALLENGE:\n\t  case ZCOMPL:\n\t  case ZCAN:\n\t  case ZFREECNT:\n\t  case ZCOMMAND:\n\t    printf(\"\\n\") ;\n\t    info->state = Idle ;\n\t    break ;\n\n\t  case ZSINIT:\n\t  case ZFILE:\n\t  case ZDATA:\n\t  case ZSTDERR:\n\t    printf(\", data follows:\\n\") ;\n\t    info->state = InData ;\n\t    info->count = 0 ;\n\t    break ;\n\t}\n\n\tif( !h32 )\n\t{\n\t  crc = 0 ;\n\t  crc = updcrc(info->headertype, crc) ;\n\t  crc = updcrc(info->data[0], crc) ;\n\t  crc = updcrc(info->data[1], crc) ;\n\t  crc = updcrc(info->data[2], crc) ;\n\t  crc = updcrc(info->data[3], crc) ;\n\t  crc = updcrc(info->crcBytes[0], crc) ;\n\t  crc = updcrc(info->crcBytes[1], crc) ;\n\t  if( crc&0xffff != 0 )\n\t    printf(\"     CRC ERROR\\n\") ;\n\t}\n\telse\n\t{\n\t  crc = 0xffffffff ;\n\t  crc = UPDC32(info->headertype, crc) ;\n\t  crc = UPDC32(info->data[0], crc) ;\n\t  crc = UPDC32(info->data[1], crc) ;\n\t  crc = UPDC32(info->data[2], crc) ;\n\t  crc = UPDC32(info->data[3], crc) ;\n\t  crc = UPDC32(info->crcBytes[0], crc) ;\n\t  crc = UPDC32(info->crcBytes[1], crc) ;\n\t  crc = UPDC32(info->crcBytes[2], crc) ;\n\t  crc = UPDC32(info->crcBytes[3], crc) ;\n\t  if( crc != 0xdebb20e3 )\n\t    printf(\"     CRC ERROR\\n\") ;\n\t}\n}\n\ndumpCrc()\n{\n\tint\ti,j ;\n\n\tif( linecnt <= 0 )\n\t  return ;\n\n\tif( linecnt > MAXLINE ) linecnt = MAXLINE ;\n\tprintf(\"     crc: \") ;\n\tfor(i=0; i<linecnt; ++i) {\nassert(i < MAXLINE) ;\n\t  printf(\"%2.2x \", line[i]) ;\n\t}\n\tprintf(\"\\n\") ;\n\n\tlinecnt = 0 ;\n}\n\n\n\t/* return value of 2 hex digits */\n\nint\nhex2(char *chrs)\n{\n\treturn\t(hex1(chrs[0]) << 4) + hex1(chrs[1]) ;\n}\n\n\t/* return value of a hex digit */\n\nint\nhex1(int chr)\n{\n\tchr -= '0' ;\n\tif( chr > 9 )\n\t  chr -= 'A'-'0'-10 ;\n\tif( chr > 15 )\n\t  chr -= 'a' - 'A' ;\n\n\treturn\tchr ;\n}\n\n\n\t/* apply ZDLE to chr */\n\nint\nzdle(int chr)\n{\n\tswitch( chr ) {\n\t  case ZRUB0: return 0177 ;\n\t  case ZRUB1: return 0377 ;\n\t  default:\n\t    if( (chr & 0140) == 0100 )\n\t      return chr ^ 0100 ;\n\t    return -1 ;\n\t}\n}\n"
  },
  {
    "path": "bbs/prot/xmodem.h",
    "content": "/*\t$Id$\t*/\n\n//#include <sys/param.h>\n\n#if !defined(MAXPATHLEN)\n#define MAXPATHLEN 260\n#endif\n\ntypedef enum {\n  Xmodem = 0,\n  XmodemCrc = 1,\n  WXmodem = 2,\n  Ymodem = 3,\n  YmodemG = 4,\n} Protocol;\n\nextern bool xmodem1k; /* 1k blocks supported */\nextern bool fileInfo; /* ymodem: send file attributes? */\nextern Protocol protocol;\nextern int xmTfd; /* transmit file descriptor */\nextern int xmRfd; /* receive file descriptor */\n\nextern int xmTimeout; /* timeout, seconds */\n\nextern char xmDefPath[MAXPATHLEN];  /* default location (ymodem) */\nextern char xmFilename[MAXPATHLEN]; /* current filename */\n\n/* error code definitions */\n\n#define XmDone -1         /* done */\n#define XmErrInt -2       /* internal error */\n#define XmErrSys -3       /* system error, see errno */\n#define XmErrNotOpen -4   /* communication channel not open */\n#define XmErrCantOpen -5  /* can't open file, see errno */\n#define XmErrInitTo -10   /* transmitter failed to respond to init req. */\n#define XmErrSequence -11 /* packet received out of sequence */\n#define XmErrCancel -12   /* cancelled by remote end */\n#define XmErrRcvTo -13    /* remote end timed out during transfer */\n\n#ifdef __STDC__\n\nextern int XmodemRInit(char* path, Protocol p);\n/* start receive protocol */\nextern int XmodemRRcv(char c); /* call for each received char. */\nextern int XmodemRTimeout();   /* call if xmTimeout expires */\nextern int XmodemRAbort();     /* call to abort protocol */\n\nextern int XmodemTInit(char* path, Protocol p);\n/* start transmit protocol */\nextern int XmodemTRcv(char c); /* call for each received char. */\nextern int XmodemTTimeout();   /* call if xmTimeout expires */\nextern int XmodemTAbort();     /* call to abort protocol */\nextern int XmodemTFinish();    /* call after last file sent (ymodem) */\n\n#else\n\nextern int XmodemRInit();    /* start receive protocol */\nextern int XmodemRRcv();     /* call for each received char. */\nextern int XmodemRTimeout(); /* call if xmTimeout expires */\nextern int XmodemRAbort();   /* call to abort protocol */\n\nextern int XmodemTInit();    /* start transmit protocol */\nextern int XmodemTRcv();     /* call for each received char. */\nextern int XmodemTTimeout(); /* call if xmTimeout expires */\nextern int XmodemTAbort();   /* call to abort protocol */\n\n#endif\n\n/* INTERNAL */\n\n#define SOH 1   /* ^A */\n#define STX 2   /* ^B */\n#define EOT 4   /* ^D */\n#define ACK 6   /* ^F */\n#define DLE 16  /* ^P */\n#define XON 17  /* ^Q */\n#define XOFF 19 /* ^S */\n#define NAK 21  /* ^U */\n#define SYN 22  /* ^V */\n#define CAN 24  /* ^X */\n\n#ifndef False\n#define False 0\n#define True 1\n#endif\n\n#define MAXERROR 10\n#define INITTO 10 /* initialization timeout, basic xmodem */\n#define INITTO2 3 /* initialization timeout */\n#define PKTTO 5   /* in-packet receive timeout */\n\n#define MAXPACKET 1024 /* max packet length */\n\n#ifdef __STDC__\n\nextern int sendCancel(), sendFlush(char), sendChr(char), sendStr(char*, int);\nextern int calcrc(char* ptr, int count);\nextern int calcChecksum(char* ptr, int count);\n\n#else\n\nextern int sendCancel(), sendFlush(), sendChr(), sendStr();\nextern int calcrc();\nextern int calcChecksum();\n\n#endif\n"
  },
  {
    "path": "bbs/prot/xmodemr.cpp",
    "content": "#ifndef lint\nstatic const char rcsid[] = \"$Id$\";\n#endif lint\n\n/*\n * Copyright (c) 1995 by Edward A. Falk\n */\n\n/**********\n *\n *\n *\t@   @  @   @   @@@   @@@@   @@@@@  @   @  @@@@\n *\t @ @   @@ @@  @   @  @   @  @      @@ @@  @   @\n *\t  @    @ @ @  @   @  @   @  @@@    @ @ @  @@@@\n *\t @ @   @ @ @  @   @  @   @  @      @ @ @  @  @\n *\t@   @  @ @ @   @@@   @@@@   @@@@@  @ @ @  @   @\n *\n *\tXMODEMR - receiver side of xmodem/ymodem protocol\n *\n *\tCaller sets flags defined in xmodem.h as appropriate.\n *\t(default is basic xmodem)\n *\n *\tThis code is designed to be called from inside a larger\n *\tprogram, so it is implemented as a state machine where\n *\tpractical.\n *\n *\n *\tfunctions:\n *\n *\tXmodemRInit(char *filename, Protocol p)\n *\t\tInitiate a receive\n *\n *\tXmodemRTimeout()\n *\t\tcalled after timeout expired\n *\n *\tXmodemRRcv(char c)\n *\t\tcalled after character received\n *\n *\tXmodemRAbort()\n *\t\tabort transfer\n *\n *\tall functions return 0 on success, 1 on abort\n *\n *\n *\n *\tEdward A. Falk\n *\n *\tJanuary, 1995\n *\n *\n *\n **********/\n\n#include \"xmodem.h\"\n#include <stdio.h>\n#include <sys/types.h>\n\n/* TODO: WXmodem */\n\nbool xmodem1k = False;\nProtocol protocol = Xmodem;\nint xmTfd = -1;\nint xmRfd = -1;\n\nint xmTimeout = 0;\n\nchar xmDefPath[MAXPATHLEN];\nchar xmFilename[MAXPATHLEN];\n\ntypedef enum {\n  Start,  /* waiting to begin */\n  Init,   /* sent initial NAK, 'C' or 'W' */\n  Packet, /* receiving a packet */\n  Wait,   /* wait for start of next packet */\n} XmodemState;\n\nstatic bool ymodem;\nstatic XmodemState state = Start;\nstatic int errorCount = 0;\nstatic int errorCount2;\nstatic int ignoreCount;\nstatic int eotCount;  /* count EOT's, reject first one */\nstatic int inCount;   /* characters received this packet */\nstatic int pktLen;    /* length of this packet data */\nstatic int pktHdrLen; /* id, cmpl, checksum or crc */\nstatic char packet[MAXPACKET + 5], *optr;\nstatic int packetId;    /* id of last received packet */\nstatic int packetCount; /* # packets received */\n\nstatic FILE* ofile; /* output file fd */\nstatic int fileLen, fileDate, fileMode;\n\nstatic int XmodemRStart();\nstatic int processPacket();\nstatic int rejectPacket();\nstatic int acceptPacket();\n\nint XmodemRInit(char* file, Protocol prot) {\n  int err;\n\n  state = Start;\n  protocol = prot;\n  ymodem = prot == Ymodem || prot == YmodemG;\n\n  if (ymodem)\n    strcpy(xmDefPath, file);\n  else\n    strcpy(xmFilename, file);\n\n  eotCount = errorCount = errorCount2 = 0;\n\n  if (err = XmodemRStart())\n    return err;\n\n  state = Init;\n  packetId = ymodem ? 255 : 0;\n  packetCount = 0;\n\n  pktHdrLen = protocol == Xmodem ? 3 : 4;\n\n  return 0;\n}\n\n/* send startup character */\n\nstatic int XmodemRStart() {\n  static char pchars[5] = {NAK, 'C', 'W', 'C', 'C'};\n  static int timeouts[5] = {INITTO, INITTO2, INITTO2, INITTO, INITTO};\n  char c = pchars[(int)protocol];\n  int err;\n\n  if (err = sendFlush(c))\n    return err;\n\n  xmTimeout = timeouts[(int)protocol];\n\n  return 0;\n}\n\nint XmodemRRcv(char c) {\n  errorCount = 0;\n\n  switch (state) {\n  case Start: /* shouldn't happen, ignore */\n    if (c == CAN)\n      return XmErrCancel;\n    break;\n\n  case Init: /* waiting */\n  case Wait:\n    switch (c) {\n    case SOH:\n    case STX:\n      pktLen = c == STX ? 1024 : 128;\n      inCount = 0;\n      optr = packet;\n      state = Packet;\n      xmTimeout = PKTTO;\n      break;\n\n    case EOT:\n      if (++eotCount > 1) {\n        sendFlush(ACK);\n        if (ymodem)\n          return XmodemRInit(); /* restart protocol */\n        else\n          return XmDone;\n      } else\n        return rejectPacket(); /* make xmitter try again */\n\n    case CAN:\n      return XmErrCancel;\n\n    default: /* ignore all others */\n      if (++ignoreCount > 1030) {\n        ignoreCount = 0;\n        return sendFlush(NAK);\n      }\n      break;\n    }\n    break;\n\n  case Packet: /* mid packet */\n    *optr++ = c;\n    if (++inCount >= pktLen + pktHdrLen)\n      ProcessPacket();\n    break;\n  }\n  return 0;\n}\n\nint XmodemRTimeout() {\n  if (++errorCount > MAXERROR)\n    return state == Init ? XmErrInitTo : XmErrRcvTo;\n\n  switch (state) {\n  case Start:\n    return -1; /* shouldn't happen */\n  case Init:\n    if (++errorCount2 >= 3)\n      switch (protocol) {\n      case WXmodem:\n        protocol = XmodemCrc;\n        errorCount2 = 0;\n        break;\n      case XmodemCrc:\n        protocol = Xmodem;\n        pktHdrLen = 3;\n        break;\n      }\n    return XmodemRStart();\n\n  case Wait:   /* timeout while waiting */\n  case Packet: /* timeout in mid packet */\n    return rejectPacket();\n  }\n}\n\nint XmodemRAbort() { return sendCancel(); }\n\nstatic int ProcessPacket() {\n  int id = (u_char)packet[0];\n  int idc = (u_char)packet[1];\n  int i;\n\n  if (idc != 255 - id)\n    return rejectPacket();\n\n  if (id == packetId) /* duplicate */\n    return acceptPacket();\n\n  if (id != (packetId + 1) % 256) { /* out of sequence */\n    (void)sendCancel();\n    return XmErrSequence;\n  }\n\n  if (protocol == Xmodem) {\n    /* compute checksum */\n    int csum = calcChecksum(packet + 2, pktLen);\n    if (csum != (u_char)packet[2 + pktLen])\n      return rejectPacket();\n  } else {\n    int crc0 = (u_char)packet[pktLen + 2] << 8 | (u_char)packet[pktLen + 3];\n    int crc1 = calcrc(packet + 2, pktLen);\n    if (crc0 != crc1)\n      return rejectPacket();\n  }\n\n  /* it's a good packet */\n  packetId = (packetId + 1) % 256;\n\n  /* is this the first packet? */\n\n  if (packetCount == 0) {\n    if (ymodem) {\n      if (packet[2] == '\\0') { /* last file */\n        (void)acceptPacket();\n        return XmDone;\n      }\n\n      if (packet[2] == '/')\n        strcpy(xmFilename, packet + 2);\n      else {\n        strcpy(xmFilename, xmDefPath);\n        strcat(xmFilename, packet + 2);\n      }\n\n      fileLen = fileDate = fileMode = -1;\n      sscanf(packet + 2 + strlen(packet) + 1, \"%d %o %o\", &fileLen, &fileDate, &fileMode);\n    }\n\n    if ((ofile = fopen(xmFilename, \"w\")) == NULL) {\n      sendCancel();\n      return XmErrCantOpen;\n    }\n\n    if (ymodem) {\n      packetCount = 1;\n      (void)acceptPacket();\n      return sendFlush('C');\n    } else\n      state = Packet;\n  }\n\n  ++packetCount;\n\n  /* TODO: ymodem: if this is last packet, truncate it */\n  if ((i = fwrite(packet + 2, 1, pktLen, ofile)) != pktLen) {\n    sendCancel();\n    return XmErrSys;\n  } else\n    return acceptPacket();\n}\n\nstatic int rejectPacket() {\n  state = Wait;\n  xmTimeout = INITTO;\n  return sendFlush(NAK);\n}\n\nstatic int acceptPacket() {\n  state = Wait;\n  xmTimeout = INITTO;\n  return sendFlush(ACK);\n}\n\n#ifdef COMMENT /* stand-alone testing */\n\n#include <fcntl.h>\n#include <sys/termios.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <unistd.h>\n\nmain(argc, argv) int argc;\nchar** argv;\n{\n  struct termios old_settings, new_settings;\n  fd_set readfds;\n  struct timeval timeout;\n  int i;\n  int len;\n  char buffer[1024];\n  bool done = False;\n\n  if (argc < 2)\n    exit(2);\n\n  xmTfd = xmRfd = open(argv[1], O_RDWR);\n\n  if (xmTfd == -1)\n    exit(1);\n\n  tcgetattr(xmTfd, &old_settings);\n  new_settings = old_settings;\n\n  new_settings.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IUCLC | IXON | IXOFF | IMAXBEL);\n  new_settings.c_oflag = 0;\n  new_settings.c_cflag = B300 | CS8 | CREAD | CLOCAL;\n  new_settings.c_lflag = 0;\n  new_settings.c_cc[VMIN] = 32;\n  new_settings.c_cc[VTIME] = 1;\n  tcsetattr(xmTfd, TCSADRAIN, &new_settings);\n\n  xmodem1k = 0;\n  done = XmodemRInit(\"foo\", XmodemCrc) != 0;\n#ifdef COMMENT\n  xmodem1k = 1;\n  done = XmodemRInit(\"./\", Ymodem) != 0;\n#endif /* COMMENT */\n\n  while (!done) {\n    FD_ZERO(&readfds);\n    FD_SET(xmTfd, &readfds);\n    timeout.tv_sec = xmTimeout;\n    timeout.tv_usec = 0;\n    i = select(xmTfd + 1, &readfds, NULL, NULL, &timeout);\n    if (i < 0)\n      perror(\"select\");\n    else if (i == 0)\n      done = XmodemRTimeout() != 0;\n    else {\n      len = read(xmTfd, buffer, sizeof(buffer));\n      for (i = 0; !done && i < len; ++i)\n        done = XmodemRRcv(buffer[i]) != 0;\n    }\n  }\n\n  tcsetattr(xmTfd, TCSADRAIN, &old_settings);\n  exit(0);\n}\n#endif /* COMMENT */\n"
  },
  {
    "path": "bbs/prot/xmodemt.cpp",
    "content": "#ifndef lint\nstatic const char rcsid[] = \"$Id$\";\n#endif\n\n/*\n * Copyright (c) 1995 by Edward A. Falk\n */\n\n/**********\n *\n *\n *\t@   @  @   @   @@@   @@@@   @@@@@  @   @  @@@@@\n *\t @ @   @@ @@  @   @  @   @  @      @@ @@    @\n *\t  @    @ @ @  @   @  @   @  @@@    @ @ @    @\n *\t @ @   @ @ @  @   @  @   @  @      @ @ @    @\n *\t@   @  @ @ @   @@@   @@@@   @@@@@  @ @ @    @\n *\n *\tXMODEMT - transmit side of xmodem protocol\n *\n * Caller sets flags defined in xmodem.h as appropriate.\n * (default is basic xmodem)\n *\n * This code is designed to be called from inside a larger\n * program, so it is implemented as a state machine where\n * practical.\n *\n * functions:\n *\n *\tXmodemTInit(char *filename, Protocol p)\n *\t\tInitiate a receive\n *\n *\tXmodemTTimeout()\n *\t\tcalled after timeout expired\n *\n *\tXmodemTRcv(char c)\n *\t\tcalled after character received\n *\n *\tXmodemTFinish()\n *\t\tlast file (ymodem)\n *\n *\tXmodemTAbort()\n *\t\tabort transfer\n *\n * all functions return 0 on success, 1 on abort\n *\n *\tEdward A. Falk\n *\n *\tJanuary, 1995\n *\n *\n *\n **********/\n\n#include \"xmodem.h\"\n#include <cstring>\n#include <stdio.h>\n#include <sys/types.h>\n\nbool fileInfo = False;\n\n/* TODO: WXmodem, YmodemG */\n\ntypedef enum {\n  File,     /* waiting for initial protocol character */\n  FileWait, /* sent file header, waiting for ACK */\n  Start,    /* waiting to begin */\n  Wait,     /* sent a packet, waiting for ACK */\n  Eot,      /* sent an EOT, waiting for ACK */\n  EndWait,  /* sent null filename, waiting for ACK */\n} XmodemState;\n\nstatic XmodemState state = Start;\nstatic bool ymodem;\nstatic bool useCrc; /* receiver wants crc */\nstatic int pktLen;  /* length of this packet data */\nstatic int pktMaxLen;\nstatic char packet[MAXPACKET];\nstatic char pktHdr[3], pktCrc[2];\nstatic int packetId;    /* id of last received packet */\nstatic int packetCount; /* # packets received */\n\nstatic FILE* ifile = NULL; /* input file fd */\nstatic int fileLen, fileDate, fileMode;\n\nstatic int sendFilename();\nstatic int sendPacket();\nstatic int buildPacket();\nstatic int resendPacket();\n\nint XmodemTInit(char* file, Protocol prot) {\n  int err;\n\n  protocol = prot;\n  ymodem = prot == Ymodem || prot == YmodemG;\n  state = ymodem ? File : Start;\n\n  strcpy(xmFilename, file);\n\n  if ((ifile = fopen(xmFilename, \"r\")) == NULL) {\n    sendCancel();\n    return XmErrCantOpen;\n  }\n\n  packetId = 1;\n  packetCount = 0;\n  pktMaxLen = xmodem1k ? 1024 : 128;\n\n  xmTimeout = 60;\n\n  return 0;\n}\n\nint XmodemTRcv(char c) {\n  if (c == CAN) {\n    if (ifile != NULL)\n      fclose(ifile);\n    return XmErrCancel;\n  }\n\n  switch (state) {\n  case File: /* waiting for command, ymodem */\n    switch (c) {\n    case NAK:\n      useCrc = False;\n      return sendFilename();\n    case 'C':\n      useCrc = True;\n      return sendFilename();\n    }\n    break;\n\n  case FileWait: /* waiting for filename ACK */\n    switch (c) {\n    case NAK:\n      return resendPacket();\n    case ACK:\n      state = Start;\n      return 0;\n    }\n\n  case Start: /* waiting for command, data */\n    switch (c) {\n    case NAK: /* wants checksums */\n      if (!ymodem)\n        protocol = Xmodem;\n      useCrc = False;\n      return sendPacket();\n\n    case 'C':\n      useCrc = True;\n      return sendPacket();\n\n    case 'W':\n      if (!ymodem) {\n        protocol = WXmodem;\n        useCrc = True;\n        /* TODO: WXmodem */\n      }\n    }\n    break;\n\n  case Wait: /* waiting for ACK */\n    switch (c) {\n    case ACK:\n      return sendPacket();\n    case NAK:\n      return resendPacket();\n    }\n    break; /* ignore all other characters */\n\n  case Eot: /* waiting for ACK after EOT */\n    switch (c) {\n    case ACK:\n      return XmDone;\n    case NAK:\n      return sendChr(EOT);\n    }\n    break;\n\n  case EndWait: /* waiting for filename ACK */\n    switch (c) {\n    case NAK:\n      return resendPacket();\n    case ACK:\n      return XmDone;\n    }\n  }\n  return 0;\n}\n\nstatic int sendFilename() {\n  int i;\n  char* ptr;\n\n  pktLen = 128;\n\n  /* TODO: protect against long filenames */\n  strcpy(packet, xmFilename);\n  ptr = packet + strlen(packet) + 1;\n  /* TODO: get file info */\n  if (fileInfo) {\n    sprintf(ptr, \"%d %o %o %o\", 0, 0, 0100644);\n    ptr += strlen(ptr) + 1;\n  }\n\n  /* TODO: what if file desc buffer too big? */\n\n  if (ptr > packet + 128)\n    pktLen = 1024;\n\n  i = pktLen - (ptr - packet);\n  bzero(ptr, i);\n\n  state = FileWait;\n  packetId = 0;\n  return buildPacket();\n}\n\nint XmodemTFinish() {\n  int i;\n  char* ptr;\n\n  pktLen = 128;\n  bzero(packet, pktLen);\n\n  state = EndWait;\n  packetId = 0;\n  return buildPacket();\n}\n\nstatic char* bufptr;\nstatic int buflen = 0;\n\nstatic int sendPacket() {\n  int i;\n\n  /* This code assumes that a incomplete reads can only happen\n   * after EOF.  This will fail with pipes.\n   * TODO: try to make pipes work.\n   */\n\n  state = Wait;\n\n  if (buflen > 0) { /* previous incomplete packet */\n    memcpy(packet, bufptr, 128);\n    bufptr += 128;\n    if (buflen < 128)\n      for (i = buflen; i < 128; ++i)\n        packet[i] = 0x1a;\n    buflen -= 128;\n    pktLen = 128;\n    return buildPacket();\n  }\n\n  if ((i = fread(packet, 1, pktMaxLen, ifile)) <= 0) { /* EOF */\n    state = Eot;\n    return sendChr(EOT);\n  }\n\n  else if (i == pktMaxLen) { /* full buffer */\n    pktLen = i;\n    return buildPacket();\n  }\n\n  buflen = i;\n  bufptr = packet;\n  pktLen = 128;\n  return buildPacket();\n}\n\nstatic int buildPacket() {\n  int i;\n\n  pktHdr[0] = pktLen == 128 ? SOH : STX;\n  pktHdr[1] = (char)packetId;\n  pktHdr[2] = (char)(255 - packetId);\n  ++packetId;\n\n  if (useCrc) {\n    i = calcrc(packet, pktLen);\n    pktCrc[0] = (char)(i >> 8);\n    pktCrc[1] = (char)(i & 0xff);\n  } else\n    pktCrc[0] = (char)calcChecksum(packet, pktLen);\n\n  return resendPacket();\n}\n\nstatic int resendPacket() {\n  int i;\n\n  (i = sendStr(pktHdr, 3)) || (i = sendStr(packet, pktLen)) ||\n      (i = sendStr(pktCrc, useCrc ? 2 : 1));\n  return i;\n}\n\nint XmodemTTimeout() {\n  switch (state) {\n  case File:\n  case Start:\n    return XmErrInitTo;\n  case FileWait:\n  case Wait:\n  case Eot:\n    return XmErrRcvTo;\n  }\n}\n\nint XmodemTAbort() { return sendCancel(); }\n\n//#include <unistd.h>\n#include <fcntl.h>\n#include <sys/types.h>\n//#include <sys/time.h>\n//#include <sys/termios.h>\n\nmain(argc, argv) int argc;\nchar** argv;\n{\n  struct termios old_settings, new_settings;\n  fd_set readfds;\n  struct timeval timeout;\n  int i;\n  int len;\n  char buffer[1024];\n  bool done = False;\n  int filecount = 0;\n\n  if (argc < 2)\n    exit(2);\n\n  xmTfd = xmRfd = open(argv[1], O_RDWR);\n\n  if (xmTfd == -1)\n    exit(1);\n\n  tcgetattr(xmTfd, &old_settings);\n  new_settings = old_settings;\n\n  new_settings.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IUCLC | IXON | IXOFF | IMAXBEL);\n  new_settings.c_oflag = 0;\n  new_settings.c_cflag = B300 | CS8 | CREAD | CLOCAL;\n  new_settings.c_lflag = 0;\n  new_settings.c_cc[VMIN] = 32;\n  new_settings.c_cc[VTIME] = 1;\n  tcsetattr(xmTfd, TCSADRAIN, &new_settings);\n\n  xmodem1k = 1;\n  done = XmodemTInit(\"xmodem.h\", Ymodem) != 0;\n\n  while (!done) {\n    FD_ZERO(&readfds);\n    FD_SET(xmTfd, &readfds);\n    timeout.tv_sec = xmTimeout;\n    timeout.tv_usec = 0;\n    i = select(xmTfd + 1, &readfds, NULL, NULL, &timeout);\n    if (i < 0)\n      perror(\"select\");\n    else if (i == 0)\n      done = XmodemTTimeout() != 0;\n    else {\n      len = read(xmTfd, buffer, sizeof(buffer));\n      for (i = 0; !done && i < len; ++i)\n        done = XmodemTRcv(buffer[i]) != 0;\n    }\n    if (done) {\n      switch (++filecount) {\n      case 1:\n        done = XmodemTInit(\"crc.c\", Ymodem) != 0;\n        break;\n      case 2:\n        done = XmodemTFinish();\n        break;\n      case 3:\n        break;\n      }\n    }\n  }\n\n  tcsetattr(xmTfd, TCSADRAIN, &old_settings);\n  exit(0);\n}\n"
  },
  {
    "path": "bbs/prot/zmodem.cpp",
    "content": "/**\n *\tZMODEM - main logic parser for zmodem library\n *\n *\tRoutines provided here:\n *\n *\tname (args)\n *\t\tBrief description.\n *\n *\tint ZmodemRcv(u_char *buffer, int len, ZModem *info)\n *\t\tCall whenever characters are received.  If this function\n *\t\treturns ZmDone, previous function has completed successfully,\n *\t\teither call ZmodemTFile() to start next file, or call\n *\t\tZmodemTFinish() to terminate the session.\n *\n *\n *\tint\n *\tZmodemTimeout(ZModem *info)\n *\t\tCall whenever the timeout period expires and no\n *\t\tcharacters have been received.\n *\n *\tint\n *\tZmodemAttention(ZModem *info)\n *\t\tCall whenever the attention sequence has been received\n *\t\tfrom the remote end.  It is safe to call this function\n *\t\tfrom an interrupt handler.\n *\n *\tint\n *\tZmodemAbort(ZModem *info)\n *\t\tCall to abort transfer.  Physical connection remains\n *\t\topen until you close it.\n *\n *\tCopyright (c) 1995 by Edward A. Falk\n *\tJanuary, 1995\n */\n\n// TODO: sample input before initial send\n// TODO: more intelligent timeout dispatch\n// TODO: read all pending input before sending next data packet out\n// TODO: if received ZDATA while waiting for ZFILE/ZFIN, it's probably leftovers\n// TODO: enable flow control for zmodem, disable for X/YModem\n\n#include \"bbs/prot/crctab.h\"\n#include \"bbs/prot/zmodem.h\"\n#include \"bbs/prot/zmutil.h\"\n\n#include <cstring>\n#include <cctype>\n#include <cerrno>\n\nstatic u_char zeros[4] = {0, 0, 0, 0};\n\nextern int YrcvChar(char c, ZModem* info);\nextern int YrcvTimeout(ZModem* info);\nextern void ZIdleStr(u_char* buffer, int len, ZModem* info);\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4706 4127 4244 4100)\n#endif\n\n/* LEXICAL BOX: handle characters received from remote end.\n * These may be header, data or noise.\n *\n * This section is a finite state machine for parsing headers\n * and reading input data.  The info->chrCount field is effectively\n * the state variable.\n */\n\nint FinishChar(char c, ZModem* info);\nint DataChar(u_char c, ZModem* info);\nint HdrChar(u_char c, ZModem* info);\nint IdleChar(u_char c, ZModem* info);\nextern int YsendChar(char c, ZModem* info);\n\nint ZProtocol(ZModem* info);\nint ZDataReceived(ZModem* info, int crcGood);\n\nint ZmodemRcv(u_char* str, int len, ZModem* info) {\n  int err;\n\n  zmodemlog(\"ZmodemRcv: [{}], len={}; InputState={}\\n\", sname(info), len, static_cast<int>(info->InputState));\n  info->rcvlen = len;\n\n  while (--info->rcvlen >= 0) {\n    const auto c = *str++;\n\n    if (c == CAN) {\n      if (++info->canCount >= 5) {\n        zmodemlog(\"ZmodemRcv: ZmErrCancel\\r\\n\");\n        ZStatus(RmtCancel, 0, nullptr);\n        return ZmErrCancel;\n      }\n    } else {\n      info->canCount = 0;\n    }\n\n    if (info->InputState == ZModem::Ysend) {\n      if ((err = YsendChar(c, info))) {\n        zmodemlog(\"ZmodemRcv: Error in YsendChar [{}]\\r\\n\", err);\n        return err;\n      }\n    } else if (info->InputState == ZModem::Yrcv) {\n      if ((err = YrcvChar(c, info))) {\n        zmodemlog(\"ZmodemRcv: Error in YrcvChar [{}]\\r\\n\", err);\n        return err;\n      }\n    }\n\n    else if (c != XON && c != XOFF) {\n      /* now look at what we have */\n      switch (info->InputState) {\n      case ZModem::Idle:\n        if ((err = IdleChar(c, info))) {\n          zmodemlog(\"ZmodemRcv: Error in IdleChar {}d]\\r\\n\", err);\n          return err;\n        }\n        break;\n\n      case ZModem::Inhdr:\n        if ((err = HdrChar(c, info))) {\n          zmodemlog(\"ZmodemRcv: Error in HdrChar [{}]\\r\\n\", err);\n          return err;\n        }\n        break;\n\n      case ZModem::Indata:\n        if ((err = DataChar(c, info))) {\n          zmodemlog(\"ZmodemRcv: Error in DataChar [{}]\\r\\n\", err);\n          return err;\n        }\n        break;\n\n      case ZModem::Finish:\n        if ((err = FinishChar(c, info))) {\n          if (err != ZmDone) {\n            zmodemlog(\"ZmodemRcv: Error in FinishChar [{}]\\r\\n\", err);\n          }\n          return err;\n        }\n        break;\n\n      default:\n        break;\n      }\n    }\n  }\n\n  return 0;\n}\n\n/* handle character input while idling\n * looking for ZPAD-ZDLE sequence which introduces a header\n */\n\nint IdleChar(u_char c, ZModem* info) {\n  if (info->chrCount == 0) {\n    if (c == ZPAD) {\n      ++info->chrCount;\n    } else if (info->state == Sending && ++info->noiseCount > MaxNoise) {\n      info->waitflag = 1;\n    } else if (info->state == TStart && (c == 'C' || c == 'G' || c == NAK)) {\n      /* switch to ymodem */\n      info->state = YTStart;\n      info->InputState = ZModem::Ysend;\n      info->Protocol = ZModem::YMODEM;\n      return YsendChar(c, info);\n    } else {\n      ZIdleStr(&c, 1, info);\n    }\n  }\n\n  else {\n    switch (c) {\n    case ZPAD:\n      ++info->chrCount;\n      break;\n    case ZDLE:\n      info->InputState = ZModem::Inhdr;\n      info->chrCount = 0;\n      break;\n    default:\n      while (--info->chrCount >= 0) {\n        ZIdleStr((u_char*)\"*\", 1, info);\n      }\n      info->chrCount = 0;\n      break;\n    }\n  }\n  return 0;\n}\n\nstatic uint8_t rcvHex(uint8_t i, char c) {\n  if (c <= '9') {\n    c -= '0';\n  } else if (c <= 'F') {\n    c -= 'A' - 10;\n  } else {\n    c -= 'a' - 10;\n  }\n  return (i << 4) + c;\n}\n\n/* handle character input in a header */\n\nint HdrChar(u_char c, ZModem* info) {\n  int i;\n  int crc = 0;\n\n  if (c == ZDLE) {\n    info->escape = 1;\n    return 0;\n  }\n\n  if (info->escape) {\n    info->escape = 0;\n    switch (c) {\n    case ZRUB0:\n      c = 0177;\n      break;\n    case ZRUB1:\n      c = 0377;\n      break;\n    default:\n      c ^= 0100;\n      break;\n    }\n  }\n\n  if (info->chrCount == 0) {\n    /* waiting for format */\n    switch (c) {\n    case ZHEX:\n    case ZBIN:\n    case ZBIN32:\n      info->DataType = c;\n      info->chrCount = 1;\n      info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL;\n      memset(info->hdrData, 0, sizeof(info->hdrData));\n      break;\n    default:\n      info->InputState = ZModem::Idle;\n      info->chrCount = 0;\n      zmodemlog(\"Calling ZXmitHdrHex ZNAK; State [{}]\\n\", sname(info));\n      return ZXmitHdrHex(ZNAK, zeros, info);\n    }\n    return 0;\n  }\n\n  switch (info->DataType) {\n  /* hex header is 14 hex digits, cr, lf.  Optional xon is ignored */\n  case ZHEX:\n    // zmodemlog(\"HdrChar: [DataType: ZHEX: ch: {:d}/'{:c}' chrCount: {}]\\n\", c, c, info->chrCount);\n    if (info->chrCount <= 14 && !isxdigit(c)) {\n      info->InputState = ZModem::Idle;\n      info->chrCount = 0;\n      zmodemlog(\"HdrChar: [DataType: ZHEX] Calling ZXmitHdrHex ZNAK\\n\");\n      return ZXmitHdrHex(ZNAK, zeros, info);\n    }\n    if (info->chrCount <= 14) {\n      i = (info->chrCount - 1) / 2;\n      info->hdrData[i] = rcvHex(info->hdrData[i], c);\n    }\n    if (info->chrCount == 16) {\n      crc = 0;\n      for (i = 0; i < 7; ++i) {\n        crc = updcrc(info->hdrData[i], crc);\n      }\n      info->InputState = ZModem::Idle;\n      info->chrCount = 0;\n      if ((crc & 0xffff) != 0) {\n        zmodemlog(\"HdrChar: [ZHEX] Calling ZXmitHdrHex ZNAK\\n\");\n        return ZXmitHdrHex(ZNAK, zeros, info);\n      }\n      zmodemlog(\"HdrChar: [ZHEX] Calling ZProtocol\\n\");\n      return ZProtocol(info);\n    }\n  ++info->chrCount;\n  break;\n  case ZBIN:\n    /* binary header is type, 4 bytes data, 2 bytes CRC */\n    info->hdrData[info->chrCount - 1] = c;\n    info->crc = updcrc(c, info->crc);\n    if (++info->chrCount > 7) {\n      info->InputState = ZModem::Idle;\n      info->chrCount = 0;\n      if ((crc & 0xffff) != 0) {\n        zmodemlog(\"HdrChar: [ZBIN] Calling ZXmitHdrHex ZNAK\\n\");\n        return ZXmitHdrHex(ZNAK, zeros, info);\n      }\n      zmodemlog(\"HdrChar: [ZBIN] Calling ZProtocol\\n\");\n      return ZProtocol(info);\n    }\n    return 0;\n  case ZBIN32:\n    /* binary32 header is type, 4 bytes data, 4 bytes CRC */\n    info->hdrData[info->chrCount - 1] = c;\n    info->crc = UPDC32(c, info->crc);\n    if (++info->chrCount > 9) {\n      info->InputState = ZModem::Idle;\n      info->chrCount = 0;\n      if (info->crc != 0xdebb20e3) { /* see note below */\n        zmodemlog(\"HdrChar: [ZBIN32] Calling ZXmitHdrHex ZNAK\\n\");\n        return ZXmitHdrHex(ZNAK, zeros, info);\n      }\n      zmodemlog(\"HdrChar: [ZBIN32] Calling ZProtocol\\n\");\n      return ZProtocol(info);\n    }\n    return 0;\n  default: {\n    zmodemlog(\"HdrChar Not handled: [Datatype: {:d}/'{:c}', char: {:d}/'{:c}', count: {}]\\r\\n\", \n      info->DataType, info->DataType, c, c, info->chrCount);\n  } break;\n  }\n  return 0;\n}\n\n/* handle character input in a data buffer */\n\nint DataChar(u_char c, ZModem* info) {\n  if (c == ZDLE) {\n    info->escape = 1;\n    // zmodemlog(\"DataChar: Got ZDLE at [chrCount: {}]\\n\", info->chrCount);\n    return 0;\n  }\n\n  if (info->escape) {\n    info->escape = 0;\n    switch (c) {\n    case ZCRCE:\n    case ZCRCG:\n    case ZCRCQ:\n    case ZCRCW:\n      info->PacketType = c;\n      info->crcCount = (info->DataType == ZBIN32) ? 4 : 2;\n      //zmodemlog(\"Changing Packet Type to: [PacketType: {:c}] on [chrCount: {}]. [crcCount: {}] [char: {:d}/'{:c}']\\n\", \n      //  info->PacketType, info->chrCount, info->crcCount, c, c);\n      if (info->DataType == ZBIN) {\n        info->crc = updcrc(c, info->crc);\n      } else {\n        info->crc = UPDC32(c, info->crc);\n      }\n      return 0;\n    case ZRUB0:\n      // zmodemlog(\"DataChar: Got ZRUB0\\n\");\n      c = 0177;\n      break;\n    case ZRUB1:\n      // zmodemlog(\"DataChar: Got ZRUB1\\n\");\n      c = 0377;\n      break;\n    default: {\n      if ((c & 0x60) != 0x40) {\n        zmodemlog(\"DataChar: BAD c ^= 0100 [{:d}] [{:d}] [{:d}]\\n\", c, c^ 0100, 0100);\n      }\n      c ^= 0100;\n      } break;\n    }\n  }\n\n  switch (info->DataType) {\n  /* TODO: are hex data packets ever used? */\n  case ZBIN:\n    info->crc = updcrc(c, info->crc);\n    if (info->crcCount == 0) {\n      info->buffer[info->chrCount++] = c;\n    } else if (--info->crcCount == 0) {\n      zmodemlog(\"ZBIN ZDataReceived. Size: {}; crc: {:x}\\r\\n\", info->chrCount, info->crc);\n      return ZDataReceived(info, (info->crc & 0xffff) == 0);\n    }\n    break;\n  case ZBIN32:\n    info->crc = UPDC32(c, info->crc);\n    if (info->crcCount == 0) {\n      info->buffer[info->chrCount++] = c;\n    } else if (--info->crcCount == 0) {\n      const auto crc_matches = info->crc == 0xdebb20e3;\n      if (!crc_matches) {\n        zmodemlog(\"ZBIN32 ZDataReceived. Size: {}; crc: {:x}, expected: {:x} [crcCount: {}]\\n\",\n                  info->chrCount, info->crc, 0xdebb20e3, info->crcCount);\n      }\n      return ZDataReceived(info, crc_matches);\n    }\n    break;\n    case ZHEX: {\n      zmodemlog(\"DataChar: Received ZHEX\\r\\n\");\n    } break;\n    default: {\n    } break;\n  }\n  return 0;\n}\n\n/* wait for \"OO\" */\nint FinishChar(char c, ZModem* info) {\n  if (c == 'O') {\n    if (++info->chrCount >= 2) {\n      return ZmDone;\n    }\n  } else {\n    info->chrCount = 0;\n  }\n  return 0;\n}\n\nint ZPF(ZModem* info);\nint Ignore(ZModem* info);\nint AnswerChallenge(ZModem* info);\nint GotAbort(ZModem* info);\nint GotCancel(ZModem* info);\nint GotCommand(ZModem* info);\nint GotStderr(ZModem* info);\nint RetDone(ZModem* info);\nint GotCommandData(ZModem* info, int crcGood);\nint GotStderrData(ZModem* info);\n\n/* PROTOCOL LOGIC:  This section of code handles the actual\n * protocol.  This is also driven by a finite state machine\n *\n * State tables are sorted by approximate frequency order to\n * reduce search time.\n */\n\n/* Extra ZRINIT headers are the receiver trying to resync.  */\n\n/* If compiling for Send Only or Receive Only, convert table\n * entries to no-ops so we don't have to link zmodem[rt].o\n */\n\n\nextern StateTable RStartOps[];\nextern StateTable RSinitWaitOps[];\nextern StateTable RFileNameOps[];\nextern StateTable RCrcOps[];\nextern StateTable RFileOps[];\nextern StateTable RDataOps[];\nextern StateTable RFinishOps[];\nextern int GotFileName(ZModem* info, int crcGood);\nextern int ResendCrcReq(ZModem* info);\nextern int GotSinitData(ZModem* info, int crcGood);\nextern int ResendRpos(ZModem* info);\nextern int GotFileData(ZModem* info, int crcGood);\nextern int SendRinit(ZModem* info);\n\nextern StateTable TStartOps[];\nextern StateTable TInitOps[];\nextern StateTable FileWaitOps[];\nextern StateTable CrcWaitOps[];\nextern StateTable SendingOps[];\nextern StateTable SendDoneOps[];\nextern StateTable SendWaitOps[];\nextern StateTable SendEofOps[];\nextern StateTable TFinishOps[];\nextern int SendMoreFileData(ZModem* info);\n\nstatic StateTable CommandDataOps[] = {\n#ifdef COMMENT\n    {ZRQINIT, f, 1, 1},\n    {ZRINIT, f, 1, 1},\n    {ZSINIT, f, 1, 1},\n    {ZACK, f, 1, 1},\n    {ZFILE, f, 1, 1},\n    {ZSKIP, f, 1, 1},\n    {ZNAK, f, 1, 1},\n    {ZABORT, f, 1, 1, TFinish},\n    {ZFIN, f, 1, 1},\n    {ZRPOS, f, 1, 1},\n    {ZDATA, f, 1, 1},\n    {ZEOF, f, 1, 1},\n    {ZFERR, f, 1, 1, TFinish},\n    {ZCRC, f, 1, 1},\n    {ZCHALLENGE, f, 1, 1},\n    {ZCOMPL, f, 1, 1},\n    {ZCAN, f, 1, 1},\n    {ZFREECNT, f, 1, 1},\n    {ZCOMMAND, f, 1, 1},\n    {ZSTDERR, f, 1, 1},\n#endif /* COMMENT */\n    {99, ZPF, 0, 0, CommandData},\n};\n\nstatic StateTable CommandWaitOps[] = {\n#ifdef COMMENT\n    {ZRQINIT, f, 1, 1},\n    {ZRINIT, f, 1, 1},\n    {ZSINIT, f, 1, 1},\n    {ZACK, f, 1, 1},\n    {ZFILE, f, 1, 1},\n    {ZSKIP, f, 1, 1},\n    {ZNAK, f, 1, 1},\n    {ZABORT, f, 1, 1, TFinish},\n    {ZFIN, f, 1, 1},\n    {ZRPOS, f, 1, 1},\n    {ZDATA, f, 1, 1},\n    {ZEOF, f, 1, 1},\n    {ZFERR, f, 1, 1, TFinish},\n    {ZCRC, f, 1, 1},\n    {ZCHALLENGE, f, 1, 1},\n    {ZCOMPL, f, 1, 1},\n    {ZCAN, f, 1, 1},\n    {ZFREECNT, f, 1, 1},\n    {ZCOMMAND, f, 1, 1},\n    {ZSTDERR, f, 1, 1},\n#endif /* COMMENT */\n    {99, ZPF, 0, 0, CommandWait},\n};\n\nstatic StateTable StderrDataOps[] = {\n#ifdef COMMENT\n    {ZRQINIT, f, 1, 1},\n    {ZRINIT, f, 1, 1},\n    {ZSINIT, f, 1, 1},\n    {ZACK, f, 1, 1},\n    {ZFILE, f, 1, 1},\n    {ZSKIP, f, 1, 1},\n    {ZNAK, f, 1, 1},\n    {ZABORT, f, 1, 1, TFinish},\n    {ZFIN, f, 1, 1},\n    {ZRPOS, f, 1, 1},\n    {ZDATA, f, 1, 1},\n    {ZEOF, f, 1, 1},\n    {ZFERR, f, 1, 1, TFinish},\n    {ZCRC, f, 1, 1},\n    {ZCHALLENGE, f, 1, 1},\n    {ZCOMPL, f, 1, 1},\n    {ZCAN, f, 1, 1},\n    {ZFREECNT, f, 1, 1},\n    {ZCOMMAND, f, 1, 1},\n    {ZSTDERR, f, 1, 1},\n#endif /* COMMENT */\n    {99, ZPF, 0, 0, StderrData},\n};\n\nstatic StateTable DoneOps[] = {\n    {99, ZPF, 0, 0, Done},\n};\n\nstatic StateTable* tables[] = {\n    RStartOps,      RSinitWaitOps,  RFileNameOps,  RCrcOps,    RFileOps,\n    RDataOps,       RDataOps, /* RDataErr is the same as RData */\n    RFinishOps,\n\n    TStartOps,      TInitOps,       FileWaitOps,   CrcWaitOps, SendingOps,\n    SendWaitOps,    SendDoneOps,    SendEofOps,    TFinishOps,\n\n    CommandDataOps, CommandWaitOps, StderrDataOps, DoneOps,\n};\n\nconst char* hdrnames[] = {\n    \"ZRQINIT\",    \"ZRINIT\", \"ZSINIT\", \"ZACK\",     \"ZFILE\",    \"ZSKIP\",   \"ZNAK\",\n    \"ZABORT\",     \"ZFIN\",   \"ZRPOS\",  \"ZDATA\",    \"ZEOF\",     \"ZFERR\",   \"ZCRC\",\n    \"ZCHALLENGE\", \"ZCOMPL\", \"ZCAN\",   \"ZFREECNT\", \"ZCOMMAND\", \"ZSTDERR\",\n};\n\n/* This function is called (indirectly) by the ZmodemRcv()\n * function when a full header has been received.\n */\n\nint ZProtocol(ZModem* info) {\n  StateTable* table;\n#if defined(_DEBUG)\n  zmodemlog(\"ZProtocol: State [{}] received {}: {:#04x} {:#04x} {:#04x} {:#04x} = {:#010x}\\n\",\n            sname(info), hdrnames[info->hdrData[0]], info->hdrData[1], info->hdrData[2],\n            info->hdrData[3], info->hdrData[4], ZDec4(info->hdrData + 1));\n#endif\n  /* Flags are sent in F3 F2 F1 F0 order.  Data is sent in P0 P1 P2 P3 */\n\n  info->timeoutCount = 0;\n  info->noiseCount = 0;\n\n  table = tables[info->state];\n  while (table->type != 99 && table->type != info->hdrData[0]) {\n    ++table;\n  }\n  zmodemlog(\"  state {} => {}, iflush={}, oflush={}\\n\", sname(info),\n            sname2(table->newstate), table->IFlush, table->OFlush);\n  info->state = table->newstate;\n  if (table->IFlush) {\n    info->rcvlen = 0;\n    ZIFlush(info);\n  }\n  if (table->OFlush) {\n    ZOFlush(info);\n  }\n\n  return table->func(info);\n}\n\nint ZDataReceived(ZModem* info, int crcGood) {\n  switch (info->state) {\n  case RSinitWait:\n    return GotSinitData(info, crcGood);\n  case RFileName:\n    return GotFileName(info, crcGood);\n  case RData:\n    return GotFileData(info, crcGood);\n  case CommandData:\n    return GotCommandData(info, crcGood);\n  case StderrData:\n    return GotStderrData(info /* , crcGood */);\n  default:\n    return ZPF(info);\n  }\n}\n\nint ZmodemTimeout(ZModem* info) {\n  /* timed out while waiting for input */\n  ++info->timeoutCount;\n  //zmodemlog(\"timeout {}[{}]\\n\", info->timeoutCount, sname(info));\n  switch (info->state) {\n  /* receive */\n  case RStart: /* waiting for INIT frame from other end */\n    if (info->timeoutCount > 4) {\n      return YmodemRInit(info);\n    }\n  case RSinitWait:\n  case RFileName:\n    if (info->timeout > 0) {\n      ZStatus(SndTimeout, info->timeoutCount, nullptr);\n    }\n    if (info->timeoutCount > 4) {\n      return ZmErrRcvTo;\n    }\n    info->state = RStart;\n    return SendRinit(info);\n  case RCrc:\n  case RFile:\n  case RData:\n    ZStatus(SndTimeout, info->timeoutCount, nullptr);\n    if (info->timeoutCount > 2) {\n      info->timeoutCount = 0;\n      info->state = RStart;\n      return SendRinit(info);\n    }\n    return info->state == RCrc ? ResendCrcReq(info) : ResendRpos(info);\n  case RFinish:\n    ZStatus(SndTimeout, info->timeoutCount, nullptr);\n    return ZmDone;\n  case YRStart:\n  case YRDataWait:\n  case YRData:\n  case YREOF:\n    return YrcvTimeout(info);\n  /* transmit */\n  case TStart:   /* waiting for INIT frame from other end */\n  case TInit:    /* sent INIT, waiting for ZACK */\n  case FileWait: /* sent file header, waiting for ZRPOS */\n  case CrcWait:  /* sent file crc, waiting for ZRPOS */\n  case SendWait: /* waiting for ZACK */\n  case SendEof:  /* sent EOF, waiting for ZACK */\n  case TFinish:  /* sent ZFIN, waiting for ZFIN */\n  case YTStart:\n  case YTFile:\n  case YTDataWait:\n  case YTData:\n  case YTEOF:\n  case YTFin:\n    ZStatus(RcvTimeout, 0, nullptr);\n    return ZmErrRcvTo;\n  case Sending: /* sending data subpackets, ready for int */\n    return SendMoreFileData(info);\n  /* general */\n  case CommandData: /* waiting for command data */\n  case StderrData:  /* waiting for stderr data */\n    return ZmErrSndTo;\n  case CommandWait: /* waiting for command to execute */\n    return ZmErrCmdTo;\n  case Done:\n    return ZmDone;\n  default:\n    return 0;\n  }\n}\n\nint ZmodemAttention(ZModem* info) {\n  /* attention received from remote end */\n  if (info->state == Sending) {\n    ZOFlush(info);\n    info->interrupt = 1;\n  }\n  return 0;\n}\n\nint ZmodemAbort(ZModem* info) {\n  zmodemlog(\"ZmodemAbort [{}]\\r\\n\", sname(info));\n  static u_char canistr[] = {CAN, CAN, CAN, CAN, CAN, CAN, CAN, CAN, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};\n  info->state = Done;\n  ZIFlush(info);\n  ZOFlush(info);\n  return ZXmitStr(canistr, sizeof(canistr), info);\n}\n\n/* used to completely ignore headers */\n\nint Ignore(ZModem* info) { return 0; }\n\n/* ignore header contents, return ZmDone */\n\nint RetDone(ZModem* info) {\n  zmodemlog(\"RetDone: [{}]\\n\", sname(info));\n  return ZmDone;\n}\n\n/* ignore header contents, return ZmErrCancel */\n\nint GotCancel(ZModem* info) {\n  zmodemlog(\"GotCancel [{}]\\r\\n\", sname(info));\n  return ZmErrCancel;\n}\n\n/* utility: set up to receive a data packet */\n\nint dataSetup(ZModem* info) {\n  info->InputState = ZModem::Indata;\n  info->chrCount = 0;\n  info->crcCount = 0;\n  info->crc = (info->DataType != ZBIN32) ? 0 : 0xffffffffL;\n  return 0;\n}\n\n/* called when a remote command received.  For now, we\n * refuse to execute commands.  Send EPERM and ignore.\n */\nint GotCommand(ZModem* info) {\n  u_char rbuf[4];\n  /* TODO: add command capability */\n\n  rbuf[0] = EPERM;\n  rbuf[1] = rbuf[2] = rbuf[3] = 0;\n  return ZXmitHdrHex(ZCOMPL, rbuf, info);\n}\n\nint GotCommandData(ZModem* info, int crcGood) {\n  /* TODO */\n  zmodemlog(\"GotCommandData [{}]\\r\\n\", sname(info));\n\n  return 0;\n}\n\n/* called when the remote system wants to put something to\n * stderr\n */\nint GotStderr(ZModem* info) {\n  info->InputState = ZModem::Indata;\n  info->chrCount = 0;\n  return 0;\n}\n\nint GotStderrData(ZModem* info) {\n  info->buffer[info->chrCount] = '\\0';\n  ZStatus(RemoteMessage, info->chrCount, reinterpret_cast<char*>(info->buffer));\n  return 0;\n}\n\n/* Protocol failure:  An unexpected packet arrived.  This could\n * be from many sources, such as old pipelined info finally arriving\n * or a serial line with echo enabled.  Report it and ignore it.\n */\n\nint ZPF(ZModem* info) {\n  info->waitflag = 1; /* pause any in-progress transmission */\n  zmodemlog(\"ZPF [{}]\\r\\n\", sname(info));\n  ZStatus(ProtocolErr, info->hdrData[0], nullptr);\n  return 0;\n}\n\nint AnswerChallenge(ZModem* info) { return ZXmitHdrHex(ZACK, info->hdrData + 1, info); }\n\nint GotAbort(ZModem* info) {\n  zmodemlog(\"GotAbort [{}]\\r\\n\", sname(info));\n  ZStatus(RmtCancel, 0, nullptr);\n  return ZXmitHdrHex(ZFIN, zeros, info);\n}\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "bbs/prot/zmodem.h",
    "content": "/*\t$Id$\t*/\n\n#ifndef ZMODEM_H\n#define ZMODEM_H\n\n#undef CANFDX\n#undef CANOVIO\n#undef CANFC32\n#undef ZCBIN\n#undef ZDLE\n#undef ZPAD\n#undef ZBIN\n#undef ZBIN32\n#undef ZHEX\n#undef ZRQINIT\n#undef ZRINIT\n#undef ZACK\n#undef ZSKIP\n#undef ZNAK\n#undef ZFIN\n#undef ZFILE\n#undef ZRPOS\n#undef ZDATA\n#undef ZEOF\n#undef ZFERR\n#undef ZCRC\n#undef ZCAN\n#undef ZCRCE\n#undef ZCRCG\n#undef ZCRCQ\n#undef ZCRCW\n#undef ZRUB0\n#undef ZRUB1\n\n/* Header file for Zmodem protocol driver routines */\n\n/* PARAMETERS\n *\n * The following #defines control the behavior of the Zmodem\n * package.  Note that these may be replaced with variables\n * if you like.  For example, \"#define DoInitRZ\" may be replaced\n * with \"extern int DoInitRz\" to use a global variable, or with\n * \"#define DoInitRZ (info->doInitRz)\" to use a variable you\n * add to the ZModem structure.\n *\n * It is assumed that the compiler is good enough to optimize\n * \"if( 0 )\" and \"if( 1 )\" cases.  If not, you may wish to modify\n * the source code to use #ifdef instead.\n */\n\n#define DoInitRZ 1     /* send initial \"rz\\r\" when transmitting */\n#define AllowCommand 0 /* allow remote end to execute commands */\n#define SendSample 1   /* sender can sample reverse channel */\n#define SendAttn 1     /* sender can be interrupted with Attn signal */\n#define ResponseTime                                                                               \\\n  10               /* reasonable response time for sender to                                       \\\n                    * respond to requests from receiver */\n#define SerialNo 1 /* receiver serial # */\n#define MaxNoise                                                                                   \\\n  64               /* max \"noise\" characters before transmission                                   \\\n                    * pauses */\n#define MaxErrs 20 /* Max receive errors before cancel */\n\n/* always send ZSINIT header, even if not                                                      \\\n * needed, this makes protocol more robust */\n// Maybe not, this was causing a warning on syncterm.\n// Causing it to bail fast on Linux though.\n#define AlwaysSinit 1\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// constants\n//\n//\n\n#include <cstdint>\n#include <cstdio>\n#include <sys/types.h>\n\n//\n// Convenience types.  from bits/types.h in glibc\n//\n#if defined(_WIN32)\ntypedef unsigned char u_char;\n#endif // _WIN32\n\n/* Internal State */\n\nenum ZMState {\n  /* receive */\n  RStart,     /* sent RINIT, waiting for ZFILE or SINIT */\n  RSinitWait, /* got SINIT, waiting for data */\n  RFileName,  /* got ZFILE, waiting for filename & info */\n  RCrc,       /* got filename, want crc too */\n  RFile,      /* got filename, ready to read */\n  RData,      /* reading data */\n  RDataErr,   /* encountered error, ignoring input */\n  RFinish,    /* sent ZFIN, waiting for 'OO' */\n\n  /* transmit */\n  TStart,   /* waiting for INIT frame from other end */\n  TInit,    /* received INIT, sent INIT, waiting for ZACK */\n  FileWait, /* sent file header, waiting for ZRPOS */\n  CrcWait,  /* sent file crc, waiting for ZRPOS */\n  Sending,  /* sending data subpackets, ready for int */\n  SendWait, /* waiting for ZACK */\n  SendDone, /* file finished, need to send EOF */\n  SendEof,  /* sent EOF, waiting for ZACK */\n  TFinish,  /* sent ZFIN, waiting for ZFIN */\n\n  /* general */\n  CommandData, /* waiting for command data */\n  CommandWait, /* waiting for command to execute */\n  StderrData,  /* waiting for stderr data */\n  Done,\n\n  /* x/ymodem transmit */\n  YTStart,    /* waiting for 'G', 'C' or NAK */\n  YTFile,     /* sent filename, waiting for ACK */\n  YTDataWait, /* ready to send data, waiting for 'C' */\n  YTData,     /* sent data, waiting for ACK */\n  YTEOF,      /* sent eof, waiting for ACK */\n  YTFin,      /* sent null filename, waiting for ACK */\n\n  /* x/ymodem receive */\n  YRStart,    /* sent 'C', waiting for filename */\n  YRDataWait, /* received filename, waiting for data */\n  YRData,     /* receiving filename or data */\n  YREOF       /* received first EOT, waiting for 2nd */\n};\n\nstruct ZModem {\n  int ifd;         /* input fd, for use by caller's routines */\n  int ofd;         /* output fd, for use by caller's routines */\n  FILE* file;      /* file being transfered */\n  int zrinitflags; /* receiver capabilities, see below */\n  int zsinitflags; /* sender capabilities, see below */\n  char* attn;      /* attention string, see below */\n  int timeout;     /* timeout value, in seconds */\n  int bufsize;     /* receive buffer size, bytes */\n  int packetsize;  /* preferred transmit packet size */\n  int windowsize;  /* max window size */\n\n  /* file attributes: read-only */\n\n  int filesRem, bytesRem;\n  u_char f0, f1, f2, f3;   /* file flags */\n  int len, mode, fileType; /* file flags */\n  uint32_t date;             /* file date */\n\n  /* From here down, internal to Zmodem package */\n\n  ZMState state;   /* protocol internal state */\n  char* filename;  /* filename */\n  char* rfilename; /* remote filename */\n  int crc32;       /* use 32-bit crc */\n  int pktLen;      /* length of this packet */\n  int DataType;    /* input data type */\n  int PacketType;  /* type of this packet */\n  int rcvlen;\n  int chrCount;       /* chars received in current header/buffer */\n  int crcCount;       /* crc characters remaining at end of buffer */\n  int canCount;       /* how many CAN chars received? */\n  int noiseCount;     /* how many noise chars received? */\n  int errorFlush;     /* ignore incoming data because of error */\n  u_char* buffer;     /* data buffer */\n  uint32_t offset;      /* file offset */\n  uint32_t lastOffset;  /* last acknowledged offset */\n  uint32_t zrposOffset; /* last offset specified w/zrpos */\n  int ylen, bufp;     /* len,location of last Ymodem packet */\n  int fileEof;        /* file eof reached */\n  int packetCount;    /* # packets received */\n  int errCount;       /* how many data errors? */\n  int timeoutCount;   /* how many times timed out? */\n  int windowCount;    /* how much data sent in current window */\n  int atSign;         /* last char was '@' */\n  int lastCR;         /* last char was CR */\n  int escCtrl;        /* other end requests ctrl chars be escaped */\n  int escHibit;       /* other end requests hi bit be escaped */\n  int escape;         /* next character is escaped */\n  int interrupt;      /* received attention signal */\n  int waitflag;       /* next send should wait */\n  /* parser state */\n  enum { Idle, Padding, Inhdr, Indata, Finish, Ysend, Yrcv } InputState;\n  enum { XMODEM, YMODEM, ZMODEM } Protocol;\n  u_char hdrData[9];   /* header type and data */\n  u_char fileFlags[4]; /* file xfer flags */\n  uint32_t crc;          /* crc of incoming header/data */\n  enum { Full, StrWindow, SlidingWindow, Segmented } Streaming;\n};\n\n/* ZRINIT flags.  Describe receiver capabilities */\n#define CANFDX 1    /* Rx is Full duplex */\n#define CANOVIO 2   /* Rx can overlap I/O */\n#define CANBRK 4    /* Rx can send a break */\n#define CANCRY 010  /* Rx can decrypt */\n#define CANLZW 020  /* Rx can uncompress */\n#define CANFC32 040 /* Rx can use 32-bit crc */\n#define ESCCTL 0100 /* Rx needs control chars escaped */\n#define ESC8 0200   /* Rx needs 8th bit escaped. */\n\n/* ZSINIT flags.  Describe sender capabilities */\n\n#define TESCCTL 0100 /* Tx needs control chars escaped */\n#define TESC8 0200   /* Tx needs 8th bit escaped. */\n\n/* ZFILE transfer flags */\n\n/* F0 */\n#define ZCBIN 1 /* binary transfer */\n#define ZCNL 2  /* convert NL to local eol convention */\n#define ZCRESUM                                                                                    \\\n  3 /* resume interrupted file xfer, or append to a                                                \\\n       growing file. */\n\n/* F1 */\n#define ZMNEWL 1       /* transfer if source newer or longer */\n#define ZMCRC 2        /* transfer if different CRC or length */\n#define ZMAPND 3       /* append to existing file, if any */\n#define ZMCLOB 4       /* replace existing file */\n#define ZMNEW 5        /* transfer if source is newer */\n#define ZMDIFF 6       /* transfer if dates or lengths different */\n#define ZMPROT 7       /* protect: transfer only if dest doesn't exist */\n#define ZMCHNG 8       /* change filename if destination exists */\n#define ZMMASK 037     /* mask for above. */\n#define ZMSKNOLOC 0200 /* skip if not present at Rx end */\n\n/* F2 */\n#define ZTLZW 1 /* lzw compression */\n#define ZTRLE 3 /* run-length encoding */\n\n/* F3 */\n#define ZCANVHDR 1 /* variable headers ok */\n#define ZRWOVR 4   /* byte position for receive window override/256 */\n#define ZXSPARS 64 /* encoding for sparse file ops. */\n\n/* ATTN string special characters.  All other characters sent verbose */\n\n#define ATTNBRK '\\335' /* send break signal */\n#define ATTNPSE '\\336' /* pause for one second */\n\n/* ZStatus() types */\n\n#define RcvByteCount 0  /* value is # bytes received */\n#define SndByteCount 1  /* value is # bytes sent */\n#define RcvTimeout 2    /* receiver did not respond, aborting */\n#define SndTimeout 3    /* value is # of consecutive send timeouts */\n#define RmtCancel 4     /* remote end has cancelled */\n#define ProtocolErr 5   /* protocol error has occurred, val=hdr */\n#define RemoteMessage 6 /* message from remote end */\n#define DataErr 7       /* data error, val=error count */\n#define FileErr 8       /* error writing file, val=errno */\n#define FileBegin 9     /* file transfer begins, str=name */\n#define FileEnd 10      /* file transfer ends, str=name */\n#define FileSkip 11     /* file being skipped, str=name */\n\n/* error code definitions [O] means link still open */\n\n#define ZmDone -1          /* done */\n#define ZmErrInt -2        /* internal error */\n#define ZmErrSys -3        /* system error, see errno */\n#define ZmErrNotOpen -4    /* communication channel not open */\n#define ZmErrCantOpen -5   /* can't open file, see errno [O] */\n#define ZmFileTooLong -6   /* remote filename too long [O] */\n#define ZmFileCantWrite -7 /* could not write file, see errno */\n#define ZmDataErr -8       /* too many data errors */\n#define ZmErrInitTo -10    /* transmitter failed to respond to init req. */\n#define ZmErrSequence -11  /* packet received out of sequence */\n#define ZmErrCancel -12    /* cancelled by remote end */\n#define ZmErrRcvTo -13     /* remote receiver timed out during transfer */\n#define ZmErrSndTo -14     /* remote sender timed out during transfer */\n#define ZmErrCmdTo -15     /* remote command timed out */\n\n/* zmodem-supplied functions: */\n\nextern int ZmodemTInit(ZModem* info);\nextern int ZmodemTFile(const char* file_name, const char* pszRemoteFileName, uint8_t f0, uint8_t f1,\n                       uint8_t f2, uint8_t f3, int filesRem, int bytesRem, ZModem* info);\nextern int ZmodemTFinish(ZModem* info);\nextern int ZmodemAbort(ZModem* info);\nextern int ZmodemRInit(ZModem* info);\nextern int ZmodemRcv(u_char* str, int len, ZModem* info);\nextern int ZmodemTimeout(ZModem* info);\nextern int ZmodemAttention(ZModem* info);\n\nextern int YmodemTInit(ZModem* info);\nextern int XmodemTInit(ZModem* info);\nextern int YmodemRInit(ZModem* info);\n\n/* caller-supplied functions: */\n\nextern int ZXmitStr(const u_char* str, int len, ZModem* info);\nextern void ZIFlush(ZModem* info);\nextern void ZOFlush(ZModem* info);\nextern int ZAttn(ZModem* info);\nextern void ZStatus(int type, int value, char* status);\nextern FILE* ZOpenFile(char* name, uint32_t crc, ZModem* info);\n\n/* From here on down, internal to Zmodem package */\n\n/* ZModem character definitions */\n\n#define ZDLE 030     /* zmodem escape is CAN */\n#define ZPAD '*'     /* pad */\n#define ZBIN 'A'     /* introduces 16-bit crc binary header */\n#define ZHEX 'B'     /* introduces 16-bit crc hex header */\n#define ZBIN32 'C'   /* introduces 32-bit crc binary header */\n#define ZBINR32 'D'  /* introduces RLE packed binary frame w/32-bit crc */\n#define ZVBIN 'a'    /* alternate ZBIN */\n#define ZVHEX 'b'    /* alternate ZHEX */\n#define ZVBIN32 'c'  /* alternate ZBIN32 */\n#define ZVBINR32 'd' /* alternate ZBINR32 */\n#define ZRESC 0177   /* RLE flag/escape character */\n\n/* ZModem header type codes */\n\n#define ZRQINIT 0     /* request receive init */\n#define ZRINIT 1      /* receive init */\n#define ZSINIT 2      /* send init sequence, define Attn */\n#define ZACK 3        /* ACK */\n#define ZFILE 4       /* file name, from sender */\n#define ZSKIP 5       /* skip file command, from receiver */\n#define ZNAK 6        /* last packet was garbled */\n#define ZABORT 7      /* abort */\n#define ZFIN 8        /* finish session */\n#define ZRPOS 9       /* resume file from this position, from receiver */\n#define ZDATA 10      /* data packets to follow, from sender */\n#define ZEOF 11       /* end of file, from sender */\n#define ZFERR 12      /* fatal i/o error, from receiver */\n#define ZCRC 13       /* request for file crc, from receiver */\n#define ZCHALLENGE 14 /* \"send this number back to me\", from receiver */\n#define ZCOMPL 15     /* request is complete */\n#define ZCAN 16       /* other end cancelled with CAN-CAN-CAN-CAN-CAN */\n#define ZFREECNT 17   /* request for free bytes on filesystem */\n#define ZCOMMAND 18   /* command, from sending program */\n#define ZSTDERR 19    /* output this message to stderr */\n\n/* ZDLE escape sequences */\n\n#define ZCRCE 'h' /* CRC next, frame ends, header follows */\n#define ZCRCG 'i' /* CRC next, frame continues nonstop */\n#define ZCRCQ 'j' /* CRC next, send ZACK, frame continues nonstop */\n#define ZCRCW 'k' /* CRC next, send ZACK, frame ends */\n#define ZRUB0 'l' /* translate to 0177 */\n#define ZRUB1 'm' /* translate to 0377 */\n\n/* ascii definitions */\n\n#define SOH 1   /* ^A */\n#define STX 2   /* ^B */\n#define EOT 4   /* ^D */\n#define ACK 6   /* ^F */\n#define DLE 16  /* ^P */\n#define XON 17  /* ^Q */\n#define XOFF 19 /* ^S */\n#define NAK 21  /* ^U */\n#define SYN 22  /* ^V */\n#define CAN 24  /* ^X */\n\nextern int ZXmitHdr(int type, int format, u_char data[4], ZModem* info);\nint ZXmitHdrHex(int type, u_char data[4], ZModem* info);\nint ZXmitHdrBin(int type, u_char data[4], ZModem* info);\nint ZXmitHdrBin32(int type, u_char data[4], ZModem* info);\nextern u_char* putZdle(u_char* ptr, u_char c, ZModem* info);\n\nextern u_char* ZEnc4(uint32_t n);\nextern uint32_t ZDec4(u_char buf[4]);\n\n/* state table entry.  There is one row of the table per\n * possible state.  Each row is a row of all reasonable\n * inputs for this state.  The entries are sorted so that\n * the most common inputs occur first, to reduce search time\n * Unexpected input is reported and ignored, as it might be\n * caused by echo or something.\n *\n * Extra ZRINIT headers are the receiver trying to resync.\n */\n\nstruct StateTable {\n  int type;             /* frame type */\n  int (*func)(ZModem*); /* transition function */\n  int IFlush;           /* flag: flush input first */\n  int OFlush;           /* flag: flush output first */\n  ZMState newstate;     /* new state.  May be overridden by func */\n};\n\n#endif\n"
  },
  {
    "path": "bbs/prot/zmodemcrc.cpp",
    "content": "/*\n *  Crc - 32 BIT ANSI X3.66 CRC checksum files\n */\n#include <cstdio>\n#include <cstring>\n#include <iostream>\n#define OK 0\n#define ERROR (-1)\n#define LINT_ARGS\n\nint crc32file(char* name);\n\n/**********************************************************************\\\n|*                                                                    *|\n|* Demonstration program to compute the 32-bit CRC used as the frame  *|\n|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|\n|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|\n|* protocol).  The 32-bit FCS was added via the Federal Register,     *|\n|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|\n|* this polynomial is or will be included in CCITT V.41, which        *|\n|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|\n|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|\n|* errors by a factor of 10^-5 over 16-bit FCS.                       *|\n|*                                                                    *|\n\\**********************************************************************/\n\n/* Need an unsigned type capable of holding 32 bits; */\ntypedef unsigned long int UNS_32_BITS;\n\n/*\n * Copyright (C) 1986 Gary S. Brown.  You may use this program, or\n * code or tables extracted from it, as desired without restriction.\n */\n/* First, the polynomial itself and its table of feedback terms.  The  */\n/* polynomial is                                                       */\n/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */\n/* Note that we take it \"backwards\" and put the highest-order term in  */\n/* the lowest-order bit.  The X^32 term is \"implied\"; the LSB is the   */\n/* X^31 term, etc.  The X^0 term (usually shown as \"+1\") results in    */\n/* the MSB being 1.                                                    */\n\n/* Note that the usual hardware shift register implementation, which   */\n/* is what we're using (we're merely optimizing it by doing eight-bit  */\n/* chunks at a time) shifts bits into the lowest-order term.  In our   */\n/* implementation, that means shifting towards the right.  Why do we   */\n/* do it this way?  Because the calculated CRC must be transmitted in  */\n/* order from highest-order term to lowest-order term.  UARTs transmit */\n/* characters in order from LSB to MSB.  By storing the CRC this way,  */\n/* we hand it to the UART in the order low-byte to high-byte; the UART */\n/* sends each low-bit to hight-bit; and the result is transmission bit */\n/* by bit from highest- to lowest-order term without requiring any bit */\n/* shuffling on our part.  Reception works similarly.                  */\n\n/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */\n/*                                                                     */\n/*  1. The table can be generated at runtime if desired; code to do so */\n/*     is shown later.  It might not be obvious, but the feedback      */\n/*     terms simply represent the results of eight shift/xor opera-    */\n/*     tions for all combinations of data and CRC register values.     */\n/*                                                                     */\n/*  2. The CRC accumulation logic is the same for all CRC polynomials, */\n/*     be they sixteen or thirty-two bits wide.  You simply choose the */\n/*     appropriate table.  Alternatively, because the table can be     */\n/*     generated at runtime, you can start by generating the table for */\n/*     the polynomial in question and use exactly the same \"updcrc\",   */\n/*     if your application needn't simultaneously handle two CRC       */\n/*     polynomials.  (Note, however, that XMODEM is strange.)          */\n/*                                                                     */\n/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */\n/*     of course, 32-bit entries work OK if the high 16 bits are zero. */\n/*                                                                     */\n/*  4. The values must be right-shifted by eight bits by the \"updcrc\"  */\n/*     logic; the shift must be unsigned (bring in zeroes).  On some   */\n/*     hardware you could probably optimize the shift in assembler by  */\n/*     using byte-swap instructions.                                   */\n\nstatic UNS_32_BITS crc_32_tab[] =\n    {/* CRC polynomial 0xedb88320 */\n     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,\n     0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,\n     0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,\n     0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,\n     0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,\n     0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n     0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,\n     0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n     0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,\n     0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,\n     0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,\n     0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n     0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,\n     0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,\n     0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,\n     0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n     0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,\n     0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n     0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,\n     0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n     0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,\n     0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,\n     0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,\n     0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n     0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,\n     0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,\n     0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,\n     0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,\n     0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,\n     0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n     0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,\n     0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n     0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,\n     0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,\n     0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,\n     0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n     0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};\n\n#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))\n\nint Block = 0; /* Pad file with 032's to multiple of Block */\n\nint crc32file(char* name) {\n  FILE* fin;\n  unsigned long oldcrc32;\n  unsigned long crc32;\n  unsigned long oldcrc;\n  int c;\n  long charcnt;\n  long l;\n\n  oldcrc32 = 0xFFFFFFFF;\n  charcnt = 0;\n  if ((fin = fopen(name, \"r\")) == nullptr) {\n    perror(name);\n    return ERROR;\n  }\n  while ((c = getc(fin)) != EOF) {\n    ++charcnt;\n    oldcrc32 = UPDC32(c, oldcrc32);\n  }\n\n  if (ferror(fin)) {\n    perror(name);\n    fclose(fin);\n    return ERROR;\n  } else {\n    if (Block) {\n      for (l = charcnt; l % Block; ++l) {\n        oldcrc32 = UPDC32(032, oldcrc32);\n      }\n    }\n    crc32 = oldcrc32;\n    oldcrc = oldcrc32 = ~oldcrc32;\n\n    printf(\"%08lX %7ld \", oldcrc, charcnt);\n    if (Block == 128) {\n      printf(\"%5ld+%3ld \", charcnt / Block, charcnt % Block);\n    }\n    if (Block == 1024) {\n      printf(\"%5ld+%4ld \", charcnt / Block, charcnt % Block);\n    }\n  }\n\n  fclose(fin);\n  return OK;\n}\n"
  },
  {
    "path": "bbs/prot/zmodemr.cpp",
    "content": "/**\n *\tZMODEMR - receive side of zmodem protocol\n *\n * receive side of zmodem protocol\n *\n * This code is designed to be called from inside a larger\n * program, so it is implemented as a state machine where\n * practical.\n *\n * functions:\n *\n *\tZmodemRInit(ZModem *info)\n *\t\tInitiate a connection\n *\n *\tZmodemRAbort(ZModem *info)\n *\t\tabort transfer\n *\n * all functions return 0 on success, 1 on failure\n *\n *\n *\tCopyright (c) 1995 by Edward A. Falk\n *\n *\tJanuary, 1995\n */\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <ctype.h>\n#include <errno.h>\n\n#include \"core/strings.h\"\n#include \"bbs/prot/zmutil.h\"\n#include \"bbs/prot/crctab.h\"\n#include \"bbs/prot/zmodem.h\"\n#include \"fmt/format.h\"\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4706 4127 4244 4100)\n#endif\n\n// extern\tint\terrno;\n\nint ZWriteFile(u_char* buffer, int len, FILE*, ZModem*);\nint ZCloseFile(ZModem* info);\nvoid ZFlowControl(int onoff, ZModem* info);\n\nstatic u_char zeros[4] = {0, 0, 0, 0};\n\nint ZmodemRInit(ZModem* info) {\n  info->packetCount = 0;\n  info->offset = 0;\n  info->errCount = 0;\n  info->escCtrl = info->escHibit = info->atSign = info->escape = 0;\n  info->InputState = ZModem::Idle;\n  info->canCount = info->chrCount = 0;\n  info->filename = nullptr;\n  info->interrupt = 0;\n  info->waitflag = 0;\n  info->attn = nullptr;\n  info->file = nullptr;\n\n  info->buffer = (u_char*)malloc(8192);\n\n  info->state = RStart;\n  info->timeoutCount = 0;\n\n  ZIFlush(info);\n\n  /* Don't send ZRINIT right away, there might be a ZRQINIT in\n   * the input buffer.  Instead, set timeout to zero and return.\n   * This will allow ZmodemRcv() to check the input stream first.\n   * If nothing found, a ZRINIT will be sent immediately.\n   */\n  info->timeout = 0;\n#if defined(_DEBUG)\n  zmodemlog(\"ZmodemRInit[{}]: flush input, new state = RStart\\n\", sname(info));\n#endif\n  return 0;\n}\n\nint YmodemRInit(ZModem* info) {\n  info->errCount = 0;\n  info->InputState = ZModem::Yrcv;\n  info->canCount = info->chrCount = 0;\n  info->noiseCount = 0;\n  info->filename = nullptr;\n  info->file = nullptr;\n\n  if (info->buffer == nullptr) {\n    info->buffer = (u_char*)malloc(1024);\n  }\n\n  info->state = YRStart;\n  info->packetCount = -1;\n  info->timeoutCount = 0;\n  info->timeout = 10;\n  info->offset = 0;\n\n  ZIFlush(info);\n\n  return ZXmitStr((u_char*)\"C\", 1, info);\n}\n\nextern int ZPF(ZModem* info);\nextern int Ignore(ZModem* info);\nextern int GotCommand(ZModem* info);\nextern int GotStderr(ZModem* info);\n\nint SendRinit(ZModem* info);\nint GotSinit(ZModem* info);\nint GotFile(ZModem* info);\nint GotFin(ZModem* info);\nint GotData(ZModem* info);\nint GotEof(ZModem* info);\nint GotFreecnt(ZModem* info);\nint GotFileCrc(ZModem* info);\nint ResendCrcReq(ZModem* info);\nint ResendRpos(ZModem* info);\n\n/* sent ZRINIT, waiting for ZSINIT or ZFILE */\nStateTable RStartOps[] = {\n    {ZSINIT, GotSinit, 0, 1, RSinitWait}, /* SINIT, wait for attn str */\n    {ZFILE, GotFile, 0, 0, RFileName},    /* FILE, wait for filename */\n    {ZRQINIT, SendRinit, 0, 1, RStart},   /* sender confused, resend */\n    {ZFIN, GotFin, 1, 0, RFinish},        /* sender shutting down */\n    {ZNAK, SendRinit, 1, 0, RStart},      /* RINIT was bad, resend */\n#ifdef TODO\n    {ZCOMPL, f, 1, 1, s},\n#endif                                         /* TODO */\n    {ZFREECNT, GotFreecnt, 0, 0, RStart},      /* sender wants free space */\n    {ZCOMMAND, GotCommand, 0, 0, CommandData}, /* sender wants command */\n    {ZSTDERR, GotStderr, 0, 0, StderrData},    /* sender wants to send msg */\n    {99, ZPF, 0, 0, RStart},                   /* anything else is an error */\n};\n\nStateTable RSinitWaitOps[] = {\n    /* waiting for data */\n    {99, ZPF, 0, 0, RSinitWait},\n};\n\nStateTable RFileNameOps[] = {\n    /* waiting for file name */\n    {99, ZPF, 0, 0, RFileName},\n};\n\nStateTable RCrcOps[] = {\n    /* waiting for CRC */\n    {ZCRC, GotFileCrc, 0, 0, RFile},    /* sender sent it */\n    {ZNAK, ResendCrcReq, 0, 0, RCrc},   /* ZCRC was bad, resend */\n    {ZRQINIT, SendRinit, 1, 1, RStart}, /* sender confused, restart */\n    {ZFIN, GotFin, 1, 1, RFinish},      /* sender signing off */\n    {99, ZPF, 0, 0, RCrc},\n};\n\nStateTable RFileOps[] = {\n    /* waiting for ZDATA */\n    {ZDATA, GotData, 0, 0, RData},      /* got it */\n    {ZNAK, ResendRpos, 0, 0, RFile},    /* ZRPOS was bad, resend */\n    {ZEOF, GotEof, 0, 0, RStart},       /* end of file */\n    {ZRQINIT, SendRinit, 1, 1, RStart}, /* sender confused, restart */\n    {ZFILE, ResendRpos, 0, 0, RFile},   /* ZRPOS was bad, resend */\n    {ZFIN, GotFin, 1, 1, RFinish},      /* sender signing off */\n    {99, ZPF, 0, 0, RFile},\n};\n\n/* waiting for data, but a packet could possibly arrive due\n * to error recovery or something\n */\nStateTable RDataOps[] = {\n    {ZRQINIT, SendRinit, 1, 1, RStart}, /* sender confused, restart */\n    {ZFILE, GotFile, 0, 1, RFileName},  /* start a new file (??) */\n    {ZNAK, ResendRpos, 1, 1, RFile},    /* ZRPOS was bad, resend */\n    {ZFIN, GotFin, 1, 1, RFinish},      /* sender signing off */\n    {ZDATA, GotData, 0, 1, RData},      /* file data follows */\n    {ZEOF, GotEof, 1, 1, RStart},       /* end of file */\n    {99, ZPF, 0, 0, RData},\n};\n\n/* here if we've sent ZFERR or ZABORT.  Waiting for ZFIN */\n\nStateTable RFinishOps[] = {\n    {ZRQINIT, SendRinit, 1, 1, RStart}, /* sender confused, restart */\n    {ZFILE, GotFile, 1, 1, RFileName},  /* start a new file */\n    {ZNAK, GotFin, 1, 1, RFinish},      /* resend ZFIN */\n    {ZFIN, GotFin, 1, 1, RFinish},      /* sender signing off */\n    {99, ZPF, 0, 0, RFinish},\n};\n\nextern const char* hdrnames[];\n\nextern int dataSetup(ZModem* info);\n\n/* RECEIVE-RELATED STUFF BELOW HERE */\n\n/* resend ZRINIT header in response to ZRQINIT or ZNAK header */\n\nint SendRinit(ZModem* info) {\n  u_char dbuf[4];\n\n#ifdef COMMENT\n  if (info->timeoutCount >= 5)\n  /* TODO: switch to Ymodem */\n#endif /* COMMENT */\n#if defined(_DEBUG)\n    zmodemlog(\"SendRinit[{}]: send ZRINIT\\n\", sname(info));\n#endif\n  info->timeout = ResponseTime;\n  dbuf[0] = info->bufsize & 0xff;\n  dbuf[1] = (info->bufsize >> 8) & 0xff;\n  dbuf[2] = 0;\n  dbuf[3] = info->zrinitflags;\n  return ZXmitHdrHex(ZRINIT, dbuf, info);\n}\n\n/* received a ZSINIT header in response to ZRINIT */\n\nint GotSinit(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"GotSinit[{}]: call dataSetup\\n\", sname(info));\n#endif\n  info->zsinitflags = info->hdrData[4];\n  info->escCtrl = info->zsinitflags & TESCCTL;\n  info->escHibit = info->zsinitflags & TESC8;\n  ZFlowControl(1, info);\n  return dataSetup(info);\n}\n\n/* received rest of ZSINIT packet */\n\nint GotSinitData(ZModem* info, int crcGood) {\n  info->InputState = ZModem::Idle;\n  info->chrCount = 0;\n  info->state = RStart;\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotSinitData[{}]: crcGood={}\\n\", sname(info), crcGood);\n#endif\n\n  if (!crcGood) {\n    return ZXmitHdrHex(ZNAK, zeros, info);\n  }\n\n  if (info->attn != nullptr) {\n    free(info->attn);\n  }\n  info->attn = nullptr;\n  if (info->buffer[0] != '\\0') {\n    info->attn = strdup(reinterpret_cast<char*>(info->buffer));\n  }\n  return ZXmitHdrHex(ZACK, ZEnc4(SerialNo), info);\n}\n\n/* got ZFILE.  Cache flags and set up to receive filename */\n\nint GotFile(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"GotFile[{}]\\n\", sname(info));\n#endif\n\n  info->errCount = 0;\n  info->f0 = info->hdrData[4];\n  info->f1 = info->hdrData[3];\n  info->f2 = info->hdrData[2];\n  info->f3 = info->hdrData[1];\n  return dataSetup(info);\n}\n\n/* utility: see if ZOpenFile wants this file, and if\n * so, request it from sender.\n */\n\nint requestFile(ZModem* info, uint32_t crc) {\n  info->file = ZOpenFile(reinterpret_cast<char*>(info->buffer), crc, info);\n\n  if (info->file == nullptr) {\n#if defined(_DEBUG)\n    zmodemlog(\"requestFile[{}]: send ZSKIP\\n\", sname(info));\n#endif\n    info->state = RStart;\n    ZStatus(FileSkip, 0, info->filename);\n    return ZXmitHdrHex(ZSKIP, zeros, info);\n  } else {\n#if defined(_DEBUG)\n    zmodemlog(\"requestFile[{}]: send ZRPOS({})\\n\", sname(info), info->offset);\n#endif\n    info->offset = info->f0 == ZCRESUM ? ftell(info->file) : 0;\n    info->state = RFile;\n    ZStatus(FileBegin, 0, info->filename);\n    return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info);\n  }\n}\n\n/* parse filename info. */\n\nvoid parseFileName(ZModem* info, char* fileinfo) {\n  char* ptr;\n  int serial = 0;\n\n  info->len = info->mode = info->filesRem = info->bytesRem = info->fileType = 0;\n  ptr = fileinfo + strlen(fileinfo) + 1;\n  if (info->filename != nullptr) {\n    free(info->filename);\n  }\n  info->filename = strdup(fileinfo);\n  sscanf(ptr, \"%d %lo %o %o %d %d %d\", &info->len, &info->date, &info->mode, &serial,\n         &info->filesRem, &info->bytesRem, &info->fileType);\n}\n\n/* got filename.  Parse arguments from it and execute\n * policy function ZOpenFile(), provided by caller\n */\n\nint GotFileName(ZModem* info, int crcGood) {\n  info->InputState = ZModem::Idle;\n  info->chrCount = 0;\n\n  //#ifdef CHECK_FILENAME_CRC\n  if (!crcGood) {\n#if defined(_DEBUG)\n    zmodemlog(\"GotFileName[{}]: bad crc, send ZNAK\\n\", sname(info));\n    parseFileName(info, reinterpret_cast<char*>(info->buffer));\n    zmodemlog(\"GotFileName[{}]: filename: '{}'\", sname(info), info->filename);\n    // The u_char of info->buffer was causing an error \"'Formatting of non-void pointers is disallowed.\" in newer\n    // fmtlib 9.x versions.\n    //zmodemlog(\"GotFileName[{}]: buffer: '{}'\", sname(info), info->buffer);\n#endif\n    info->state = RStart;\n    return ZXmitHdrHex(ZNAK, zeros, info);\n  }\n  //#endif // CHECK_FILENAME_CRC\n\n  parseFileName(info, reinterpret_cast<char*>(info->buffer));\n\n  if ((info->f1 & ZMMASK) == ZMCRC) {\n    info->state = RCrc;\n    return ZXmitHdrHex(ZCRC, zeros, info);\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotFileName[{}]: good crc, call requestFile\\n\", sname(info));\n#endif\n  info->state = RFile;\n  return requestFile(info, 0);\n}\n\nint ResendCrcReq(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"ResendCrcReq[{}]: send ZCRC\\n\", sname(info));\n#endif\n  return ZXmitHdrHex(ZCRC, zeros, info);\n}\n\n/* received file CRC, now we're ready to accept or reject */\n\nint GotFileCrc(ZModem* info) {\n  const auto crc = ZDec4(info->hdrData + 1);\n#if defined(_DEBUG)\n  zmodemlog(\"GotFileCrc[{}]: call requestFile; crc: {}/{:x}\\n\", sname(info), crc, crc);\n#endif\n  return requestFile(info, crc);\n}\n\n/* last ZRPOS was bad, resend it */\n\nint ResendRpos(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"ResendRpos[{}]: send ZRPOS({})\\n\", sname(info), info->offset);\n#endif\n  return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info);\n}\n\n/* recevied ZDATA header */\n\nint GotData(ZModem* info) {\n  int err;\n#if defined(_DEBUG)\n  zmodemlog(\"GotData[{}]:\\n\", sname(info));\n#endif\n  if (ZDec4(info->hdrData + 1) != info->offset) {\n    if (info->attn != nullptr && (err = ZAttn(info)) != 0)\n      return err;\n#if defined(_DEBUG)\n    zmodemlog(\"  bad, send ZRPOS({})\\n\", info->offset);\n#endif\n    return ZXmitHdrHex(ZRPOS, ZEnc4(info->offset), info);\n  }\n\n  /* Let's do it! */\n  return dataSetup(info);\n}\n\n/* Utility: flush input, send attn, send specified header */\n\nint fileError(ZModem* info, int type, int data) {\n  int err;\n\n  info->InputState = ZModem::Idle;\n  info->chrCount = 0;\n\n  if (info->attn != nullptr && (err = ZAttn(info)) != 0) {\n    return err;\n  }\n  return ZXmitHdrHex(type, ZEnc4(data), info);\n}\n\n/* received file data */\n\nvoid DumpBuffer(ZModem* info) {\n  zmodemlog(\"========================================================================\\r\\n\");\n  zmodemlog(\"Dumping Buffer for {} chars\\r\\n\", info->chrCount);\n  zmodemlog(\"========================================================================\\r\\n\");\n  std::string s;\n  s.reserve(100);\n  auto offset = info->offset;\n  for (auto i=0; i < info->chrCount; ++i) {\n    auto cur = fmt::format(\"{:3} \", static_cast<uint8_t>(info->buffer[i]));\n    if ((i % 16 == 0) && !s.empty()) {\n      zmodemlog(\"{:07d} {}\\r\\n\", offset + i, s);\n      s.clear();\n      s.reserve(100);\n      offset = info->offset + i;\n    }\n    s.append(cur);\n  }\n  if (!s.empty()) {\n    zmodemlog(\"{}\\r\\n\", s);\n  }\n  zmodemlog(\"========================================================================\\r\\n\");\n}\n\nint GotFileData(ZModem* info, int crcGood) {\n  /* OK, now what?  Flushing the buffers and executing the\n   * attn sequence has likely chopped off the input stream\n   * mid-packet.  Now we switch to idle mode and treat all\n   * incoming stuff like noise until we get a new valid\n   * packet.\n   */\n\n  if (!crcGood) {\n    /* oh bugger, an error. */\n#if defined(_DEBUG)\n    zmodemlog(\"GotFileData[{}]: bad crc, send ZRPOS({}), new state = RFile\\n\", sname(info),\n              info->offset);\n    DumpBuffer(info);\n#endif\n    ZStatus(DataErr, ++info->errCount, nullptr);\n    if (info->errCount > MaxErrs) {\n      ZmodemAbort(info);\n      return ZmDataErr;\n    }\n    info->state = RFile;\n    info->InputState = ZModem::Idle;\n    info->chrCount = 0;\n    return fileError(info, ZRPOS, info->offset);\n  }\n\n  if (ZWriteFile(info->buffer, info->chrCount, info->file, info)) {\n    /* RED ALERT!  Could not write the file. */\n    ZStatus(FileErr, errno, nullptr);\n    info->state = RFinish;\n    info->InputState = ZModem::Idle;\n    info->chrCount = 0;\n    return fileError(info, ZFERR, errno);\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotFileData[{}]: [offset: {}][count: {}]\\n\", sname(info), info->offset, info->chrCount);\n#endif\n  info->offset += info->chrCount;\n  ZStatus(RcvByteCount, info->offset, nullptr);\n\n  /* if this was the last data subpacket, leave data mode */\n  if (info->PacketType == ZCRCE || info->PacketType == ZCRCW) {\n#if defined(_DEBUG)\n    zmodemlog(\"  ZCRCE|ZCRCW, new state RFile\");\n#endif\n    info->state = RFile;\n    info->InputState = ZModem::Idle;\n    info->chrCount = 0;\n  } else {\n    dataSetup(info);\n  }\n\n  if (info->PacketType == ZCRCQ || info->PacketType == ZCRCW) {\n#if defined(_DEBUG)\n    zmodemlog(\",  send ZACK\\n\");\n#endif\n    return ZXmitHdrHex(ZACK, ZEnc4(info->offset), info);\n  }\n  return 0;\n}\n\n/* received ZEOF packet, file is now complete */\n\nint GotEof(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"GotEof[{}]: [offset: {}]\\n\", sname(info), info->offset);\n#endif\n  if (ZDec4(info->hdrData + 1) != info->offset) {\n#if defined(_DEBUG)\n    zmodemlog(\"  bad length, state = RFile\\n\");\n#endif\n    info->state = RFile;\n    return 0; /* it was probably spurious */\n  }\n\n  /* TODO: if we can't close the file, send a ZFERR */\n  ZCloseFile(info);\n  info->file = nullptr;\n  ZStatus(FileEnd, 0, info->filename);\n  if (info->filename != nullptr) {\n    free(info->filename);\n    info->filename = nullptr;\n  }\n  return SendRinit(info);\n}\n\n/* got ZFIN, respond in kind */\n\nint GotFin(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"GotFin[{}]: send ZFIN\\n\", sname(info));\n#endif\n  info->InputState = ZModem::Finish;\n  info->chrCount = 0;\n  if (info->filename != nullptr) {\n    free(info->filename);\n  }\n  return ZXmitHdrHex(ZFIN, zeros, info);\n}\n\nint GotFreecnt(ZModem* info) {\n  /* TODO: how do we find free space on system? */\n  return ZXmitHdrHex(ZACK, ZEnc4(0xffffffff), info);\n}\n\n/* YMODEM */\n\nstatic u_char AckStr[1] = {ACK};\nstatic u_char NakStr[1] = {NAK};\nstatic u_char CanStr[2] = {CAN, CAN};\n\nint ProcessPacket(ZModem* info);\nint acceptPacket(ZModem* info);\nint rejectPacket(ZModem* info);\nint calcCrc(u_char* str, int len);\n\nint YrcvChar(char c, ZModem* info) {\n  int err;\n\n  if (info->canCount >= 2) {\n    ZStatus(RmtCancel, 0, nullptr);\n    return ZmErrCancel;\n  }\n\n  switch (info->state) {\n  case YREOF:\n    if (c == EOT) {\n      ZCloseFile(info);\n      info->file = nullptr;\n      ZStatus(FileEnd, 0, info->filename);\n      if (info->filename != nullptr) {\n        free(info->filename);\n      }\n      if ((err = acceptPacket(info)) != 0) {\n        return err;\n      }\n      info->packetCount = -1;\n      info->offset = 0;\n      info->state = YRStart;\n      return ZXmitStr((u_char*)\"C\", 1, info);\n    }\n    /* else, drop through */\n\n  case YRStart:\n  case YRDataWait:\n    switch (c) {\n    case SOH:\n    case STX:\n      info->pktLen = c == SOH ? (128 + 4) : (1024 + 4);\n      info->state = YRData;\n      info->chrCount = 0;\n      info->timeout = 1;\n      info->noiseCount = 0;\n      info->crc = 0;\n      break;\n    case EOT:\n      /* ignore first EOT to protect against false eot */\n      info->state = YREOF;\n      return rejectPacket(info);\n    default:\n      if (++info->noiseCount > 135) {\n        return ZXmitStr(NakStr, 1, info);\n      }\n      break;\n    }\n    break;\n  case YRData:\n    info->buffer[info->chrCount++] = c;\n    if (info->chrCount >= info->pktLen) {\n      return ProcessPacket(info);\n    }\n    break;\n  default:\n    break;\n  }\n\n  return 0;\n}\n\nint YrcvTimeout(ZModem* info) {\n  switch (info->state) {\n  case YRStart:\n    if (info->timeoutCount >= 10) {\n      ZXmitStr(CanStr, 2, info);\n      return ZmErrInitTo;\n    }\n    return ZXmitStr((u_char*)\"C\", 1, info);\n\n  case YRDataWait:\n  case YREOF:\n  case YRData:\n    if (info->timeoutCount >= 10) {\n      ZXmitStr(CanStr, 2, info);\n      return ZmErrRcvTo;\n    }\n    return ZXmitStr(NakStr, 1, info);\n  default:\n    return 0;\n  }\n}\n\nint ProcessPacket(ZModem* info) {\n  int idx = (u_char)info->buffer[0];\n  int idxc = (u_char)info->buffer[1];\n  int crc0, crc1;\n  int err;\n\n  info->state = YRDataWait;\n\n  if (idxc != 255 - idx) {\n    ZStatus(DataErr, ++info->errCount, nullptr);\n    return rejectPacket(info);\n  }\n\n  if (idx == (info->packetCount % 256)) { /* quietly ignore dup */\n    return acceptPacket(info);\n  }\n\n  if (idx != (info->packetCount + 1) % 256) {\n    /* out of sequence */\n    ZXmitStr(CanStr, 2, info);\n    return ZmErrSequence;\n  }\n\n  crc0 = (u_char)info->buffer[info->pktLen - 2] << 8 | (u_char)info->buffer[info->pktLen - 1];\n  crc1 = calcCrc(info->buffer + 2, info->pktLen - 4);\n  if (crc0 != crc1) {\n    ZStatus(DataErr, ++info->errCount, nullptr);\n    return rejectPacket(info);\n  }\n\n  ++info->packetCount;\n\n  if (info->packetCount == 0) { /* packet 0 is filename */\n    if (info->buffer[2] == '\\0') {\n      /* null filename is FIN */\n      acceptPacket(info);\n      return ZmDone;\n    }\n\n    parseFileName(info, reinterpret_cast<char*>(info->buffer + 2));\n    info->file = ZOpenFile(info->filename, 0, info);\n    if (info->file == nullptr) {\n      ZXmitStr(CanStr, 2, info);\n      return ZmErrCantOpen;\n    }\n    if ((err = acceptPacket(info)) != 0) {\n      return err;\n    }\n    return ZXmitStr((u_char*)\"C\", 1, info);\n  }\n\n  if (ZWriteFile(info->buffer + 2, info->pktLen - 4, info->file, info)) {\n    ZStatus(FileErr, errno, nullptr);\n    ZXmitStr(CanStr, 2, info);\n    return ZmErrSys;\n  }\n  info->offset += info->pktLen - 4;\n  ZStatus(RcvByteCount, info->offset, nullptr);\n\n  acceptPacket(info);\n  return 0;\n}\n\nint rejectPacket(ZModem* info) {\n  info->timeout = 10;\n  return ZXmitStr(NakStr, 1, info);\n}\n\nint acceptPacket(ZModem* info) {\n  info->state = YRDataWait;\n  info->timeout = 10;\n  return ZXmitStr(AckStr, 1, info);\n}\n\nint calcCrc(u_char* str, int len) {\n  int crc = 0;\n  while (--len >= 0) {\n    crc = updcrc(*str++, crc);\n  }\n  crc = updcrc(0, crc);\n  crc = updcrc(0, crc);\n  return crc & 0xffff;\n}\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "bbs/prot/zmodemt.cpp",
    "content": "/**\n *\tZMODEMT - transmit side of zmodem protocol\n *\n * transmit side of zmodem protocol\n *\n * Caller sets flags defined in zmodem.h as appropriate.\n * (default is basic zmodem)\n *\n * functions:\n *\n *\tZmodemTInit(ZModem *info)\n *\tYmodemTInit(ZModem *info)\n *\tXmodemTInit(ZModem *info)\n *\t\tInitiate a connection\n *\n *\tZmodemTFile(char *filename, u_char flags[4], ZModem *info)\n *\t\tInitiate a file transfer.  Flags are as specified\n *\t\tunder \"ZCBIN\" in zmodem.h\n *\n *\tZmodemTFinish(ZModem *info)\n *\t\tlast file\n *\n *\tZmodemTAbort(ZModem *info)\n *\t\tabort transfer\n *\n * all functions return 0 on success, 1 on abort\n *\n *\tCopyright (c) 1995 by Edward A. Falk\n *\tJanuary, 1995\n */\n\n#include \"core/strings.h\"\n#include \"bbs/prot/zmutil.h\"\n#include \"bbs/prot/crctab.h\"\n#include \"bbs/prot/zmodem.h\"\n\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <sys/stat.h>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4706 4127 4244 4100)\n\n#endif // _MSC_VER\n\nint SendMoreFileData(ZModem* info);\nextern int ZXmitData(int, int, u_char, u_char* data, ZModem*);\nextern void ZFlowControl(int onoff, ZModem* info);\n\nint YXmitData(u_char* buffer, int len, ZModem* info);\nint YSendFilename(ZModem* info);\nint YSendData(ZModem* info);\nint YSendFin(ZModem* info);\n\nint sendFilename(ZModem* info);\nint SendZSInit(ZModem* info);\n\nstatic u_char zeros[4] = {0, 0, 0, 0};\n\nint ZPF(ZModem* info);\nint AnswerChallenge(ZModem* info);\nint GotAbort(ZModem* info);\nint Ignore(ZModem* info);\nint RetDone(ZModem* info);\nint GotCommand(ZModem* info);\nint GotStderr(ZModem* info);\n\nint GotRinit(ZModem* info);\nint SendZSInit(ZModem* info);\nint SendFileCrc(ZModem* info);\nint GotSendAck(ZModem* info);\nint GotSendDoneAck(ZModem* info);\nint GotSendNak(ZModem* info);\nint GotSendWaitAck(ZModem* info);\nint SkipFile(ZModem* info);\nint GotSendPos(ZModem* info);\nint SendFileData(ZModem* info);\nint ResendEof(ZModem* info);\nint OverAndOut(ZModem* info);\n\n/* sent ZRQINIT, waiting for response */\nStateTable TStartOps[] = {\n    {ZRINIT, GotRinit, 1, 1, TStart},       {ZCHALLENGE, AnswerChallenge, 1, 0, TStart},\n    {ZABORT, GotAbort, 1, 1, TFinish},      {ZFERR, GotAbort, 1, 1, TFinish},\n    {ZNAK, Ignore, 0, 0, TStart},           {ZCOMMAND, GotCommand, 0, 0, CommandData},\n    {ZSTDERR, GotStderr, 0, 0, StderrData}, {99, ZPF, 0, 0, TStart},\n};\n\n/* sent ZSINIT, waiting for response */\nStateTable TInitOps[] = {\n    {ZACK, RetDone, 1, 0, TInit},\n    {ZNAK, SendZSInit, 1, 0, TInit},\n    {ZRINIT, GotRinit, 1, 1, TInit}, /* redundant, but who cares */\n    {ZCHALLENGE, AnswerChallenge, 1, 0, TInit},\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {ZCOMMAND, GotCommand, 0, 0, CommandData},\n    {ZSTDERR, GotStderr, 0, 0, StderrData},\n    {99, ZPF, 0, 0, TInit},\n};\n\n/* sent ZFILE, waiting for response */\nStateTable FileWaitOps[] = {\n    {ZRPOS, SendFileData, 1, 0, Sending},\n    {ZSKIP, SkipFile, 1, 0, FileWait},\n    {ZCRC, SendFileCrc, 1, 0, FileWait},\n    {ZNAK, sendFilename, 1, 0, FileWait},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {ZCHALLENGE, AnswerChallenge, 1, 0, FileWait},\n    {ZCOMMAND, GotCommand, 0, 0, CommandData},\n    {ZSTDERR, GotStderr, 0, 0, StderrData},\n    {99, ZPF, 0, 0, FileWait},\n};\n\n/* sent file CRC, waiting for response */\nStateTable CrcWaitOps[] = {\n    {ZRPOS, SendFileData, 1, 0, Sending},\n    {ZSKIP, SkipFile, 1, 0, FileWait},\n    {ZNAK, SendFileCrc, 1, 0, CrcWait},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {ZCRC, SendFileCrc, 0, 0, CrcWait},\n    {ZCHALLENGE, AnswerChallenge, 0, 0, CrcWait},\n    {ZCOMMAND, GotCommand, 0, 0, CommandData},\n    {ZSTDERR, GotStderr, 0, 0, StderrData},\n    {99, ZPF, 0, 0, CrcWait},\n};\n\n/* sending data, interruptable */\nStateTable SendingOps[] = {\n    {ZACK, GotSendAck, 0, 0, Sending},\n    {ZRPOS, GotSendPos, 1, 1, Sending},\n    {ZSKIP, SkipFile, 1, 1, FileWait},\n    {ZNAK, GotSendNak, 1, 1, Sending},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {99, ZPF, 0, 0, SendWait},\n};\n\n/* sent data, need to send EOF */\nStateTable SendDoneOps[] = {\n    {ZACK, GotSendDoneAck, 0, 0, SendWait},\n    {ZRPOS, GotSendPos, 1, 1, Sending},\n    {ZSKIP, SkipFile, 1, 1, FileWait},\n    {ZNAK, GotSendNak, 1, 1, Sending},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {99, ZPF, 0, 0, SendWait},\n};\n\n/* sending data, waiting for ACK */\nStateTable SendWaitOps[] = {\n    {ZACK, GotSendWaitAck, 0, 0, Sending},\n    {ZRPOS, GotSendPos, 0, 0, SendWait},\n    {ZSKIP, SkipFile, 1, 1, FileWait},\n    {ZNAK, GotSendNak, 0, 0, Sending},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {99, ZPF, 0, 0, SendWait},\n};\n\n/* sent ZEOF, waiting for new RINIT */\nStateTable SendEofOps[] = {\n    {ZRINIT, SkipFile, 1, 0, TStart}, /* successful completion */\n    {ZACK, Ignore, 0, 0, SendEof},    /* probably ACK from last packet */\n    {ZRPOS, GotSendPos, 1, 1, SendWait},\n    {ZSKIP, SkipFile, 1, 1, TStart},\n    {ZNAK, ResendEof, 1, 0, SendEof},\n    {ZRINIT, sendFilename, 1, 1, FileWait}, /* rcvr confused, retry file */\n    {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},\n    {99, ZPF, 0, 0, SendEof},\n};\n\nStateTable TFinishOps[] = {\n    {ZFIN, OverAndOut, 1, 1, Done},         {ZNAK, ZmodemTFinish, 1, 1, TFinish},\n    {ZRINIT, ZmodemTFinish, 1, 1, TFinish}, {ZABORT, GotAbort, 1, 1, TFinish},\n    {ZFERR, GotAbort, 1, 1, TFinish},       {99, ZPF, 0, 0, TFinish},\n};\n\nextern const char* hdrnames[];\n\n/* called by user to establish protocol */\n\nint ZmodemTInit(ZModem* info) {\n  info->state = TStart;\n  info->Protocol = ZModem::ZMODEM;\n  info->crc32 = 0;\n  info->packetCount = 0;\n  info->errCount = 0;\n  info->escCtrl = info->escHibit = info->atSign = info->escape = 0;\n  info->InputState = ZModem::Idle;\n  info->canCount = info->chrCount = 0;\n  info->windowCount = 0;\n  info->filename = nullptr;\n  info->bufsize = 0;\n  info->interrupt = 0;\n  info->waitflag = 0;\n\n  if (info->packetsize == 0) {\n    info->packetsize = 1024;\n  }\n\n  /* we won't be receiving much data, pick a reasonable buffer\n   * size (largest packet will do)\n   */\n\n  auto i = info->packetsize * 2;\n  if (i < 1024) {\n    i = 1024;\n  }\n  info->buffer = static_cast<u_char*>(malloc(i));\n\n  ZIFlush(info);\n\n  /* optional: send \"rz\\r\" to remote end */\n  int err = 0;\n  if (DoInitRZ) {\n    if ((err = ZXmitStr(reinterpret_cast<const u_char*>(\"rz\\r\"), 3, info))) {\n      return err;\n    }\n  }\n\n  if ((err = ZXmitHdr(ZRQINIT, ZHEX, zeros, info))) { /* nudge receiver */\n    return err;\n  }\n\n  info->timeout = 60;\n\n#if defined(_DEBUG)\n  zmodemlog(\"ZmodemTInit[{}]: sent ZRQINIT\\n\", sname(info));\n#endif\n\n  return 0;\n}\n\n/* called by user to establish Ymodem protocol */\n\nint YmodemTInit(ZModem* info) {\n  info->state = YTStart;\n  info->Protocol = ZModem::YMODEM;\n  info->errCount = 0;\n  info->InputState = ZModem::Ysend;\n  info->canCount = info->chrCount = 0;\n  info->windowCount = 0;\n  info->filename = nullptr;\n\n  if (info->packetsize != 1024) {\n    info->packetsize = 128;\n  }\n\n  info->buffer = (u_char*)malloc(1024);\n\n  ZIFlush(info);\n  ZFlowControl(0, info);\n\n  info->timeout = 60;\n\n  return 0;\n}\n\n/* called by user to establish Xmodem protocol */\nint XmodemTInit(ZModem* info) {\n  YmodemTInit(info);\n  info->Protocol = ZModem::XMODEM;\n  return 0;\n}\n\n/* called by user to begin transmission of a file */\n\nint ZmodemTFile(const char* file_name, const char* pszRemoteFileName, uint8_t f0, uint8_t f1, uint8_t f2,\n                uint8_t f3, int filesRem, int bytesRem, ZModem* info) {\n  if (file_name == nullptr || (info->file = fopen(file_name, \"rb\")) == nullptr) {\n    return ZmErrCantOpen;\n  }\n\n  info->fileEof = 0;\n  info->filename = strdup(file_name);\n  info->rfilename = strdup((pszRemoteFileName != nullptr) ? pszRemoteFileName : \"noname\");\n  info->filesRem = filesRem;\n  info->bytesRem = bytesRem;\n  info->fileFlags[3] = f0;\n  info->fileFlags[2] = f1;\n  info->fileFlags[1] = f2;\n  info->fileFlags[0] = f3;\n  info->offset = info->lastOffset = 0;\n  info->len = info->date = info->fileType = info->mode = 0;\n  if (info->filename != nullptr) {\n    struct stat buf{};\n    if (stat(info->filename, &buf) == 0) {\n      info->len = buf.st_size;\n      info->date = buf.st_mtime;\n      info->fileType = 0;\n      info->mode = (buf.st_mode & 0777) | 0100000;\n    }\n  }\n\n  if (info->Protocol == ZModem::XMODEM)\n    return YSendData(info);\n\n  if (info->Protocol == ZModem::YMODEM) {\n    return YSendFilename(info);\n  }\n\n  info->state = FileWait;\n#if defined(_DEBUG)\n  zmodemlog(\"ZmodemTFile[{}]: send ZFILE({})\\n\", sname(info), info->rfilename);\n#endif\n  return sendFilename(info);\n}\n\n/* send ZFILE header and filename & info.  Wait for response\n * from receiver.\n */\nint sendFilename(ZModem* info) {\n  u_char obuf[2048];\n  u_char* ptr = obuf;\n\n  zmodemlog(\"sendFilename\\n\");\n  info->state = FileWait;\n\n  int err = ZXmitHdr(ZFILE, ZBIN, info->fileFlags, info);\n  if (err) {\n    return err;\n  }\n\n  auto i = wwiv::strings::ssize(info->rfilename);\n  memcpy(ptr, info->rfilename, i + 1);\n  ptr += i + 1;\n  sprintf(reinterpret_cast<char*>(ptr), \"%d %lo %o 0 %d %d 0\", info->len, info->date, info->mode,\n          info->filesRem, info->bytesRem);\n  ptr += strlen(reinterpret_cast<char*>(ptr));\n  *ptr++ = '\\0';\n\n  return ZXmitData(ZBIN, ptr - obuf, ZCRCW, obuf, info);\n}\n\n/* called by user when there are no more files to send */\n\nint ZmodemTFinish(ZModem* info) {\n  if (info->Protocol == ZModem::XMODEM) {\n    return ZmDone;\n  }\n\n  if (info->Protocol == ZModem::YMODEM) {\n    return YSendFin(info);\n  }\n\n  info->state = TFinish;\n  if (info->filename != nullptr) {\n    free(info->filename);\n    info->filename = nullptr;\n  }\n  if (info->rfilename != nullptr) {\n    free(info->rfilename);\n    info->rfilename = nullptr;\n  }\n  if (info->buffer != nullptr) {\n    free(info->buffer);\n    info->buffer = nullptr;\n  }\n#if defined(_DEBUG)\n  zmodemlog(\"ZmodemTFinish[{}]: send ZFIN\\n\", sname(info));\n#endif\n  return ZXmitHdr(ZFIN, ZHEX, zeros, info);\n}\n\n/* Received Rinit.  Usually received while in start state,\n * this can also be an attempt to resync after a protocol\n * failure\n */\nint GotRinit(ZModem* info) {\n  zmodemlog(\"GotRinit\");\n  info->bufsize = info->hdrData[1] + info->hdrData[2] * 256;\n  info->zrinitflags = info->hdrData[4] + info->hdrData[3] * 256;\n  info->crc32 = info->zrinitflags & CANFC32;\n  info->escCtrl = info->zrinitflags & ESCCTL;\n  info->escHibit = info->zrinitflags & ESC8;\n\n  /* Full streaming: If receiver can overlap I/O, and if\n   * the sender can sample the reverse channel without hanging,\n   * and the receiver has not specified a buffer size, then we\n   * can simply blast away with ZCRCG packets.  If the receiver\n   * detects an error, it sends an attn sequence and a new ZRPOS\n   * header to restart the file where the error occurred.\n   *\n   * [note that zmodem8.doc does not define how much noise is\n   * required to trigger a ZCRCW packet.  We arbitrarily choose\n   * 64 bytes]\n   *\n   * If 'windowsize' is nonzero, and the receiver can do full\n   * duplex, ZCRCQ packets are sent instead of ZCRCG, to keep track\n   * of the number of characters in the queue.  If the queue fills\n   * up, we pause and wait for a ZACK.\n   *\n   *\n   * Full Streaming with Reverse Interrupt:  If sender cannot\n   * sample the input stream, then we define an Attn sequence\n   * that will be used to interrupt transmission.\n   *\n   *\n   * Full Streaming with Sliding Window:  If sender cannot\n   * sample input stream or respond to Attn signal, we send\n   * several ZCRCQ packets until we're sure the receiver must\n   * have sent back at least one ZACK.  Then we stop sending and\n   * read that ZACK.  Then we send one more packet and so on.\n   *\n   *\n   * Segmented Streaming:  If receiver cannot overlap I/O or can't do\n   * full duplex and has specified a maximum receive buffer size,\n   * whenever the buffer size is reached, we send a ZCRCW packet.\n   *\n   * TODO: what if receiver can't overlap, but hasn't set a buffer\n   * size?\n   *\n   * ZCRCE: CRC next, frame ends, header follows\n   * ZCRCG: CRC next, frame continues nonstop\n   * ZCRCQ: CRC next, send ZACK, frame continues nonstop\n   * ZCRCW: CRC next, send ZACK, frame ends, header follows\n   */\n\n  ZFlowControl(1, info);\n\n  if ((info->zrinitflags & (CANFDX | CANOVIO)) == (CANFDX | CANOVIO) && info->bufsize == 0) {\n    if (info->windowsize == 0) {\n      info->Streaming = ZModem::Full;\n    } else {\n      info->Streaming = ZModem::StrWindow;\n    }\n  }\n\n  else if ((info->zrinitflags & (CANFDX | CANOVIO)) == (CANFDX | CANOVIO) && info->bufsize == 0) {\n    info->Streaming = ZModem::SlidingWindow;\n  }\n\n  else {\n    info->Streaming = ZModem::Segmented;\n  }\n\n  zmodemlog(\"GotRinit[{}]\\n\", sname(info));\n\n  if (AlwaysSinit || info->zsinitflags != 0 || info->attn != nullptr) {\n    return SendZSInit(info);\n  } else {\n    return ZmDone; /* caller now calls ZmodemTFile() */\n  }\n}\n\nint SendZSInit(ZModem* info) {\n  int err;\n  const char* at = (info->attn != nullptr) ? info->attn : \"\";\n  u_char fbuf[4];\n\n  /* TODO: zmodem8.doc states: \"If the ZSINIT header specifies\n   * ESCCTL or ESC8, a HEX header is used, and the receiver\n   * activates the specified ESC modes before reading the following\n   * data subpacket.\" What does that mean?\n   */\n  zmodemlog(\"SendZSInit[{}]\\n\", sname(info));\n\n  info->state = TInit;\n  fbuf[0] = fbuf[1] = fbuf[2] = 0;\n  fbuf[3] = info->zsinitflags;\n  if ((err = ZXmitHdr(ZSINIT, ZBIN, fbuf, info)) ||\n      (err = ZXmitData(ZBIN, strlen(at) + 1, ZCRCW, (u_char*)at, info))) {\n    zmodemlog(\"SendZSInit ERROR [{}] [{}]\\n\", sname(info), err);\n    return err;\n  }\n  return 0;\n}\n\nint SendFileCrc(ZModem* info) {\n  auto crc = FileCrc(info->filename);\n#if defined(_DEBUG)\n  zmodemlog(\"SendFileCrc[{}]: {:x}\\n\", sname(info), crc);\n#endif\n  return ZXmitHdrHex(ZCRC, ZEnc4(crc), info);\n}\n\n/* Utility: start sending data. */\n\nint startFileData(ZModem* info) {\n  int err;\n\n  info->offset = info->lastOffset = info->zrposOffset = ZDec4(info->hdrData + 1);\n\n  fseek(info->file, info->offset, 0);\n\n  /* TODO: what if fseek fails?  Send EOF? */\n\n#if defined(_DEBUG)\n  zmodemlog(\"startFileData[{}]: {}\\n\", sname(info), info->offset);\n#endif\n\n  if ((err = ZXmitHdr(ZDATA, ZBIN, info->hdrData + 1, info))) {\n#if defined(_DEBUG)\n    zmodemlog(\"startFileData[{}]: return err\", sname(info));\n#endif\n    return err;\n  }\n  return SendMoreFileData(info);\n}\n\n/* send a chunk of file data in response to a ZRPOS.  Whether this\n * is followed by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all\n * sorts of protocol flags\n */\n\nint SendFileData(ZModem* info) {\n  info->waitflag = 0;\n  return startFileData(info);\n}\n\n/* here if an ACK arrived while transmitting data.  Update\n * last known receiver offset, and try to send some more\n * data.\n */\nint GotSendAck(ZModem* info) {\n  uint32_t offset = ZDec4(info->hdrData + 1);\n\n  if (offset > info->lastOffset) {\n    info->lastOffset = offset;\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotSendAck[{}]: {}\\n\", sname(info), info->offset);\n#endif\n\n  return 0; /* DONT send more data, that will happen later anyway */\n}\n\n/* here if an ACK arrived after last file packet sent.  Send\n * the EOF.\n */\n\nint GotSendDoneAck(ZModem* info) {\n  uint32_t offset = ZDec4(info->hdrData + 1);\n\n  if (offset > info->lastOffset) {\n    info->lastOffset = offset;\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotSendDoneAck[{}]: {}\\n\", sname(info), info->offset);\n#endif\n\n  info->state = SendEof;\n  info->timeout = 60;\n  return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info);\n}\n\n/* off to a bad start; ZDATA header was corrupt.  Start\n * from beginning\n */\n\nint GotSendNak(ZModem* info) {\n  info->offset = info->zrposOffset;\n\n  fseek(info->file, info->offset, 0);\n\n  /* TODO: what if fseek fails?  Send EOF? */\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotSendNak[{}]: {}\\n\", sname(info), info->offset);\n#endif\n\n  return SendMoreFileData(info);\n}\n\n/* got a ZSKIP, receiver doesn't want this file.  */\n\nint SkipFile(ZModem* info) {\n#if defined(_DEBUG)\n  zmodemlog(\"SkipFile[{}]\\n\", sname(info));\n#endif\n  fclose(info->file);\n  return ZmDone;\n}\n\n/* got a ZRPOS packet in the middle of sending a file,\n * set new offset and try again\n */\n\nint GotSendPos(ZModem* info) {\n  ZStatus(DataErr, ++info->errCount, nullptr);\n  info->waitflag = 1; /* next pkt should wait, to resync */\n#if defined(_DEBUG)\n  zmodemlog(\"GotSendPos[{}]\\n\", sname(info), info->offset);\n#endif\n  return startFileData(info);\n}\n\n/* here if an ACK arrived while waiting while transmitting data.\n * Update last known receiver offset, and try to send some more\n * data.\n */\n\nint GotSendWaitAck(ZModem* info) {\n  int err;\n\n  uint32_t offset = ZDec4(info->hdrData + 1);\n\n  if (offset > info->lastOffset) {\n    info->lastOffset = offset;\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"GotSendWaitAck[{}]\\n\", sname(info), offset);\n#endif\n\n  if ((err = ZXmitHdr(ZDATA, ZBIN, ZEnc4(info->offset), info))) {\n    return err;\n  }\n\n  return SendMoreFileData(info);\n}\n\n/* utility: send a chunk of file data.  Whether this is followed\n * by a ZCRCE, ZCRCG, ZCRCQ or ZCRCW depends on all\n * sorts of protocol flags, plus 'waitflag'.  Exact amount of file\n * data transmitted is variable, as escape sequences may pad out\n * the buffer.\n */\n\nint SendMoreFileData(ZModem* info) {\n  int type;\n  int qfull = 0;\n  int err;\n  int len;      /* max # chars to send this packet */\n  long pending; /* # of characters sent but not acknowledged */\n\n  /* ZCRCE: CRC next, frame ends, header follows\n   * ZCRCG: CRC next, frame continues nonstop\n   * ZCRCQ: CRC next, send ZACK, frame continues nonstop\n   * ZCRCW: CRC next, send ZACK, frame ends, header follows\n   */\n\n  if (info->interrupt) {\n    /* Bugger, receiver sent an interrupt.  Enter a wait state\n     * and see what they want.  Next header *should* be ZRPOS.\n     */\n    info->state = SendWait;\n    info->timeout = 60;\n    return 0;\n  }\n\n  /* Find out how many bytes we can transfer in the next packet */\n\n  len = info->packetsize;\n\n  pending = info->offset - info->lastOffset;\n\n  if (info->windowsize != 0 && info->windowsize - pending <= len) {\n    len = info->windowsize - pending;\n    qfull = 1;\n  }\n  if (info->bufsize != 0 && info->bufsize - pending <= len) {\n    len = info->bufsize - pending;\n    qfull = 1;\n  }\n\n  if (len == 0) {\n    /* window still full, keep waiting */\n    info->state = SendWait;\n    info->timeout = 60;\n    return 0;\n  }\n\n  /* OK, we can safely transmit 'len' bytes of data.  Start reading\n   * file until buffer is full.\n   */\n\n  // len -= 10;\t/* Pre-deduct 10 bytes for trailing CRC */\n\n  /* find out what kind of packet to send */\n  if (info->waitflag) {\n    type = ZCRCW;\n    info->waitflag = 0;\n  }\n#ifdef COMMENT\n  else if (info->fileEof) {\n    type = ZCRCE;\n  }\n#endif /* COMMENT */\n  else if (qfull) {\n    type = ZCRCW;\n  } else {\n    switch (info->Streaming) {\n    case ZModem::Full:\n    case ZModem::Segmented:\n      type = ZCRCG;\n      break;\n\n    case ZModem::StrWindow:\n      if ((info->windowCount += len) < info->windowsize / 4) {\n        type = ZCRCG;\n      } else {\n        type = ZCRCQ;\n        info->windowCount = 0;\n      }\n      break;\n\n    default:\n    case ZModem::SlidingWindow:\n      type = ZCRCQ;\n      break;\n    }\n  }\n\n  int crc32 = info->crc32;\n  int c = 0, c2, atSign = 0;\n  uint32_t crc;\n  u_char* ptr = info->buffer;\n\n  crc = crc32 ? 0xffffffff : 0;\n\n  /* read characters from file and put into buffer until buffer is\n   * full or file is exhausted\n   */\n\n  while (len > 0 && (c = getc(info->file)) != EOF) {\n    if (!crc32) {\n      crc = updcrc(c, crc);\n    } else {\n      crc = UPDC32(c, crc);\n    }\n\n    /* zmodem protocol requires that CAN(ZDLE), DLE, XON, XOFF and\n     * a CR following '@' be escaped.  In addition, I escape '^]'\n     * to protect telnet, \"<CR>~.\" to protect rlogin, and ESC for good\n     * measure.\n     */\n    c2 = c & 0177;\n    if (c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 || c2 == 0177 || c2 == '\\r' ||\n        c2 == '\\n' || c2 == 033 || c2 == 035 || (c2 < 040 && info->escCtrl)) {\n      *ptr++ = ZDLE;\n      if (c == 0177) {\n        *ptr = ZRUB0;\n      } else if (c == 0377) {\n        *ptr = ZRUB1;\n      } else {\n        *ptr = c ^ 0100;\n      }\n      len -= 2;\n    } else {\n      *ptr = c;\n      --len;\n    }\n    ++ptr;\n\n    atSign = c2 == '@';\n    ++info->offset;\n  }\n\n  /* if we've reached file end, a ZEOF header will follow.  If\n   * there's room in the outgoing buffer for it, end the packet\n   * with ZCRCE and append the ZEOF header.  If there isn't room,\n   * we'll have to do a ZCRCW\n   */\n  if ((info->fileEof = (c == EOF))) {\n    if (qfull || (info->bufsize != 0 && len < 24)) {\n      type = ZCRCW;\n    } else {\n      type = ZCRCE;\n    }\n  }\n\n  *ptr++ = ZDLE;\n  if (!crc32) {\n    crc = updcrc(type, crc);\n  } else {\n    crc = UPDC32(type, crc);\n  }\n  *ptr++ = type;\n\n  if (!crc32) {\n    crc = updcrc(0, crc);\n    crc = updcrc(0, crc);\n    ptr = putZdle(ptr, static_cast<u_char>((crc >> 8) & 0xff), info);\n    ptr = putZdle(ptr, static_cast<u_char>(crc & 0xff), info);\n  } else {\n    crc = ~crc;\n    for (len = 4; --len >= 0; crc >>= 8) {\n      ptr = putZdle(ptr, static_cast<u_char>(crc & 0xff), info);\n    }\n  }\n\n  len = ptr - info->buffer;\n\n  ZStatus(SndByteCount, info->offset, nullptr);\n\n  if ((err = ZXmitStr(info->buffer, len, info))) {\n    return err;\n  }\n\n#ifdef COMMENT\n  if ((err = ZXmitData(ZBIN, info->buffer, len, type, info))) {\n    return err;\n  }\n#endif /* COMMENT */\n\n  /* finally, do we want to wait after this packet? */\n\n  switch (type) {\n  case ZCRCE:\n    info->state = SendEof;\n    info->timeout = 60;\n    return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info);\n  case ZCRCW:\n    info->state = info->fileEof ? SendDone : SendWait;\n    info->timeout = 60;\n    break;\n  default:\n    info->state = Sending;\n    info->timeout = 0;\n    break;\n  }\n\n#ifdef COMMENT\n  if (info->fileEof) {\n    /* Yes, file is done, send EOF and wait */\n    info->state = SendEof;\n    info->timeout = 60;\n    return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info);\n  } else if (type == ZCRCW) {\n    info->state = SendWait;\n    info->timeout = 60;\n  } else {\n    info->state = Sending;\n    info->timeout = 0;\n  }\n#endif /* COMMENT */\n  return 0;\n}\n\nint ResendEof(ZModem* info) { return ZXmitHdrHex(ZEOF, ZEnc4(info->offset), info); }\n\nint OverAndOut(ZModem* info) {\n  ZXmitStr((u_char*)\"OO\", 2, info);\n  return ZmDone;\n}\n\n/* YMODEM */\n\nstatic u_char eotstr[1] = {EOT};\n\n/* ymodem parser */\n\nint YsendChar(char c, ZModem* info) {\n  int err;\n\n  if (info->canCount >= 2) {\n    ZStatus(RmtCancel, 0, nullptr);\n    return ZmErrCancel;\n  }\n\n  switch (info->state) {\n  case YTStart: /* wait for 'G', 'C' or NAK */\n    switch (c) {\n    case 'G': /* streaming YModem */\n    case 'C': /* CRC YModem */\n    case NAK: /* checksum YModem */\n      info->PacketType = c;\n      return ZmDone;\n    default:\n      return 0;\n    }\n\n  case YTFile: /* sent filename, waiting for ACK or NAK */\n    switch (c) {\n    case NAK: /* resend */\n    case 'C':\n    case 'G':\n      ZStatus(DataErr, ++info->errCount, nullptr);\n      return YSendFilename(info);\n    case ACK:\n      info->state = YTDataWait;\n    default:\n      return 0;\n    }\n\n  case YTDataWait: /* sent filename, waiting for G,C or NAK */\n    switch (c) {\n    case NAK:\n    case 'C':\n    case 'G':\n      info->chrCount = 0;\n      if (info->PacketType == 'G') { /* send it all at once */\n        while (info->state == YTData)\n          if ((err = YSendData(info)))\n            return err;\n        return 0;\n      } else\n        return YSendData(info);\n    default:\n      return 0;\n    }\n\n  case YTData: /* sent data, waiting for ACK or NAK */\n    switch (c) {\n    case 'C':\n    case 'G': /* protocol failure, resend filename */\n      if (info->Protocol == ZModem::YMODEM) {\n        ZStatus(DataErr, ++info->errCount, nullptr);\n        info->state = YTFile;\n        rewind(info->file);\n        return YSendFilename(info);\n      }\n    /* else XModem, treat it like a NAK */\n    case NAK:\n      ZStatus(DataErr, ++info->errCount, nullptr);\n      return YXmitData(info->buffer + info->bufp, info->ylen, info);\n    case ACK:\n      info->offset += info->ylen;\n      info->bufp += info->ylen;\n      info->chrCount -= info->ylen;\n      ZStatus(SndByteCount, info->offset, nullptr);\n      return YSendData(info);\n    default:\n      return 0;\n    }\n\n  case YTEOF: /* sent EOF, waiting for ACK or NAK */\n    switch (c) {\n    case NAK:\n      return ZXmitStr(eotstr, 1, info);\n    case ACK:\n      info->state = info->Protocol == ZModem::YMODEM ? YTStart : Done;\n      return ZmDone;\n    default:\n      return 0;\n    }\n\n  case YTFin: /* sent Fin, waiting for ACK or NAK */\n    switch (c) {\n    case NAK:\n      return YSendFin(info);\n    case ACK:\n      return ZmDone;\n    default:\n      return 0;\n    }\n  default:\n    return 0;\n  }\n}\n\nint YXmitData(u_char* buffer, int len, ZModem* info) {\n  u_char hdr[3];\n  u_char trail[2];\n  uint32_t crc = 0;\n  int i, err;\n\n  hdr[0] = len == 1024 ? STX : SOH;\n  hdr[1] = info->packetCount;\n  hdr[2] = ~hdr[1];\n  if ((err = ZXmitStr(hdr, 3, info)) || (err = ZXmitStr(buffer, len, info))) {\n    return err;\n  }\n\n  if (info->PacketType == NAK) {\n    /* checksum */\n    for (i = 0; i < len; ++i) {\n      crc += buffer[i];\n    }\n    trail[0] = static_cast<u_char>(crc % 256);\n    return ZXmitStr(trail, 1, info);\n  } else {\n    for (i = 0; i < len; ++i) {\n      crc = updcrc(buffer[i], crc);\n    }\n    crc = updcrc(0, crc);\n    crc = updcrc(0, crc);\n    trail[0] = static_cast<u_char>(crc / 256);\n    trail[1] = static_cast<u_char>(crc % 256);\n    return ZXmitStr(trail, 2, info);\n  }\n}\n\nint YSendFilename(ZModem* info) {\n  u_char obuf[1024];\n  u_char* ptr = obuf;\n\n  info->state = info->PacketType != 'G' ? YTFile : YTDataWait;\n  info->packetCount = 0;\n  info->offset = 0;\n\n  int i = wwiv::strings::ssize(info->rfilename);\n  memcpy(ptr, info->rfilename, i + 1);\n  ptr += i + 1;\n  sprintf(reinterpret_cast<char*>(ptr), \"%d %lo %o 0\", info->len, info->date, info->mode);\n  ptr += strlen(reinterpret_cast<char*>(ptr));\n  *ptr++ = '\\0';\n  /* pad out to 128 bytes or 1024 bytes */\n  i = ptr - obuf;\n  int len = i > 128 ? 1024 : 128;\n  for (; i < len; ++i) {\n    *ptr++ = '\\0';\n  }\n\n  return YXmitData(obuf, len, info);\n}\n\n/* send next buffer of data */\n\nint YSendData(ZModem* info) {\n  /* are there characters still in the read buffer? */\n\n  if (info->chrCount <= 0) {\n    info->bufp = 0;\n    info->chrCount = fread(info->buffer, 1, info->packetsize, info->file);\n    info->fileEof = feof(info->file);\n  }\n\n  if (info->chrCount <= 0) {\n    fclose(info->file);\n    info->state = YTEOF;\n    return ZXmitStr(eotstr, 1, info);\n  }\n\n  /* pad out to 128 bytes if needed */\n  if (info->chrCount < 128) {\n    int i = 128 - info->chrCount;\n    memset(info->buffer + info->bufp + info->chrCount, 0x1a, i);\n    info->chrCount = 128;\n  }\n\n  info->ylen = info->chrCount >= 1024 ? 1024 : 128;\n  ++info->packetCount;\n\n  info->state = YTData;\n\n  return YXmitData(info->buffer + info->bufp, info->ylen, info);\n}\n\nint YSendFin(ZModem* info) {\n  u_char obuf[128];\n\n  info->state = YTFin;\n  info->packetCount = 0;\n\n  memset(obuf, 0, 128);\n\n  return YXmitData(obuf, 128, info);\n}\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "bbs/prot/zmutil.cpp",
    "content": "/**********\n *\tZMUTIL - utilties used by zmodem protocol.\n *\n *\tRoutines provided here:\n *\n *\tint ZXmitHdrHex(type, data, info)\n *\t\tint\ttype;\n *\t\tu_char\tdata[4];\n *\t\tZModem\t*info;\n *\n *\ttransmit zmodem header in hex.\n *\n *\n *\tint ZXmitHdrBin(type, data, info)\n *\t\tint\ttype;\n *\t\tu_char\tdata[4];\n *\t\tZModem\t*info;\n *\n *\t\ttransmit zmodem header in binary.\n *\n *\n *\tint ZXmitHdrBin32(type, data, info)\n *\t\tint\ttype;\n *\t\tu_char\tdata[4];\n *\t\tZModem\t*info;\n *\n *\t\ttransmit zmodem header in binary with 32-bit crc.\n *\n *\n *\tint ZXmitHdr(type, format, data, info)\n *\t\tint\ttype, format;\n *\t\tu_char\tdata[4];\n *\t\tZModem\t*info;\n *\n *\t\ttransmit zmodem header\n *\n *\n *\tint ZXmitData(format, data, len, term, info)\n *\t\tint\tformat, len;\n *\t\tu_char\tterm;\n *\t\tu_char\t*data;\n *\t\tZModem\t*info;\n *\n *\t\ttransmit buffer of data.\n *\n *\n *\tuint32_t FileCrc(name)\n *\t\tchar\t*name;\n *\n *\t\tcompute 32-bit crc for a file, returns 0 on not found\n *\n *\n *\tu_char\t*ZEnc4(n)\n *\t\tuint32_t\tn;\n *\n *\t\tconvert uint32_t to 4 bytes.\n *\n *\tuint32_t ZDec4(buf)\n *\t\tu_char\tbuf[4];\n *\n *\t\tconvert 4 bytes to uint32_t\n *\n *\n *\n *\tCopyright (c) 1995 by Edward A. Falk\n *\tJanuary, 1995\n **********/\n#include \"bbs/prot/crctab.h\"\n#include \"bbs/prot/zmodem.h\"\n#include \"bbs/prot/zmutil.h\"\n#include \"core/log.h\"\n#include \"fmt/chrono.h\"\n#include \"fmt/format.h\"\n\n#include <cstdint>\n#include <cstdio>\n#include <ctime>\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4706 4127 4244 4100)\n#endif\n\nstatic const char hexChars[] = \"0123456789abcdef\";\nextern const char* hdrnames[];\n\n#define DEBUG_ZMODEMLOG\n\n\n/** put a number as two hex digits */\nu_char* putHex(u_char* ptr, u_char c) {\n  *ptr++ = hexChars[(c >> 4) & 0xf];\n  *ptr++ = hexChars[c & 0xf];\n  return ptr;\n}\n\n/* put a number with ZDLE escape if needed */\n\nu_char* putZdle(u_char* ptr, u_char c, ZModem* info) {\n  u_char c2 = c & 0177;\n\n  if (c == ZDLE || c2 == 020 || c2 == 021 || c2 == 023 || c2 == 0177 ||\n      (c2 == 015 && info->atSign) ||\n#ifdef COMMENT\n      c2 == 035 || (c2 == '~' && info->lastCR) ||\n#endif /* COMMENT */\n      c2 == 035 || (c2 < 040 && info->escCtrl)) {\n    *ptr++ = ZDLE;\n    if (c == 0177) {\n      *ptr = ZRUB0;\n    } else if (c == 0377) {\n      *ptr = ZRUB1;\n    } else {\n      *ptr = c ^ 0100;\n    }\n  } else {\n    *ptr = c;\n  }\n\n  info->atSign = c2 == '@';\n  info->lastCR = c2 == '\\r';\n\n  return ++ptr;\n}\n\nint ZXmitHdrHex(int type, u_char data[4], ZModem* info) {\n  u_char szBuffer[128];\n  u_char* ptr = szBuffer;\n\n#if defined(_DEBUG)\n  zmodemlog(\"ZXmitHdrHex: sending  {}: {:#04x} {:#04x} {:#04x} {:#04x} = {:#010x}\\n\", hdrnames[type], data[0],\n            data[1], data[2], data[3], ZDec4(data));\n#endif\n\n  *ptr++ = ZPAD;\n  *ptr++ = ZPAD;\n  *ptr++ = ZDLE;\n  *ptr++ = ZHEX;\n\n  ptr = putHex(ptr, type);\n  uint32_t crc = updcrc(type, 0);\n  for (int i = 4; --i >= 0; ++data) {\n    ptr = putHex(ptr, *data);\n    crc = updcrc(*data, crc);\n  }\n  crc = updcrc(0, crc);\n  crc = updcrc(0, crc);\n  ptr = putHex(ptr, (crc >> 8) & 0xff);\n  ptr = putHex(ptr, crc & 0xff);\n  *ptr++ = '\\r';\n  *ptr++ = '\\n';\n  if (type != ZACK && type != ZFIN) {\n    *ptr++ = XON;\n  }\n\n  return ZXmitStr(szBuffer, ptr - szBuffer, info);\n}\n\nint ZXmitHdrBin(int type, u_char data[4], ZModem* info) {\n  u_char szBuffer[128];\n  u_char* ptr = szBuffer;\n  int len;\n\n#if defined(_DEBUG)\n  zmodemlog(\"ZXmitHdrBin: sending  {}}: {:#04x} {:#04x} {:#04x} {:#04x} = {:#010x}\\n\", hdrnames[type], data[0],\n            data[1], data[2], data[3], ZDec4(data));\n#endif\n\n  *ptr++ = ZPAD;\n  *ptr++ = ZDLE;\n  *ptr++ = ZBIN;\n\n  ptr = putZdle(ptr, type, info);\n  uint32_t crc = updcrc(type, 0);\n  for (len = 4; --len >= 0; ++data) {\n    ptr = putZdle(ptr, *data, info);\n    crc = updcrc(*data, crc);\n  }\n  crc = updcrc(0, crc);\n  crc = updcrc(0, crc);\n  ptr = putZdle(ptr, (crc >> 8) & 0xff, info);\n  ptr = putZdle(ptr, crc & 0xff, info);\n\n  len = ptr - szBuffer;\n  return ZXmitStr(szBuffer, len, info);\n}\n\nint ZXmitHdrBin32(int type, u_char data[4], ZModem* info) {\n  u_char szBuffer[128];\n  u_char* ptr = szBuffer;\n  uint32_t crc;\n  int len;\n\n#if defined(_DEBUG)\n  zmodemlog(\"ZXmitHdrBin32: sending  {}: {:#04x} {:#04x} {:#04x} {:#04x} = {:#010x}\\n\", hdrnames[type], data[0],\n            data[1], data[2], data[3], ZDec4(data));\n#endif\n\n  *ptr++ = ZPAD;\n  *ptr++ = ZDLE;\n  *ptr++ = ZBIN32;\n  ptr = putZdle(ptr, type, info);\n  crc = UPDC32(type, 0xffffffffL);\n  for (len = 4; --len >= 0; ++data) {\n    ptr = putZdle(ptr, *data, info);\n    crc = UPDC32(*data, crc);\n  }\n  crc = ~crc;\n  for (len = 4; --len >= 0; crc >>= 8) {\n    ptr = putZdle(ptr, static_cast<u_char>(crc & 0xff), info);\n  }\n\n  len = ptr - szBuffer;\n  return ZXmitStr(szBuffer, len, info);\n}\n\nint ZXmitHdr(int type, int format, u_char data[4], ZModem* info) {\n  if (format == ZBIN && info->crc32) {\n    format = ZBIN32;\n  }\n\n  switch (format) {\n  case ZHEX:\n    return ZXmitHdrHex(type, data, info);\n  case ZBIN:\n    return ZXmitHdrBin(type, data, info);\n  case ZBIN32:\n    return ZXmitHdrBin32(type, data, info);\n  default:\n    return 0;\n  }\n}\n\n/* TODO: if input is not a file, need to keep old data\n * for possible retransmission */\n\nint ZXmitData(int format, int len, u_char term, u_char* data, ZModem* info) {\n  u_char* ptr = info->buffer;\n\n  if (format == ZBIN && info->crc32) {\n    format = ZBIN32;\n  }\n\n#if defined(_DEBUG)\n  zmodemlog(\"ZXmiteData: fmt={:c}, len={}, term={:c}\\n\", format, len, term);\n#endif\n\n  uint32_t crc = (format == ZBIN) ? 0 : 0xffffffff;\n\n  while (--len >= 0) {\n    if (format == ZBIN) {\n      crc = updcrc(*data, crc);\n    } else {\n      crc = UPDC32(*data, crc);\n    }\n    ptr = putZdle(ptr, *data++, info);\n  }\n\n  *ptr++ = ZDLE;\n  if (format == ZBIN) {\n    crc = updcrc(term, crc);\n  } else {\n    crc = UPDC32(term, crc);\n  }\n  *ptr++ = term;\n  if (format == ZBIN) {\n    crc = updcrc(0, crc);\n    crc = updcrc(0, crc);\n    ptr = putZdle(ptr, (crc >> 8) & 0xff, info);\n    ptr = putZdle(ptr, crc & 0xff, info);\n  } else {\n    crc = ~crc;\n    for (len = 4; --len >= 0; crc >>= 8) {\n      ptr = putZdle(ptr, crc & 0xff, info);\n    }\n  }\n\n  return ZXmitStr(info->buffer, ptr - info->buffer, info);\n}\n\n/* compute 32-bit crc for a file, returns 0 on not found */\nuint32_t FileCrc(char* name) {\n  FILE* ifile = fopen(name, \"r\");\n  int i;\n\n  if (ifile == nullptr) { /* shouldn't happen, since we did access( 2 ) */\n    return 0;\n  }\n\n  uint32_t crc = 0xffffffff;\n\n  while ((i = fgetc(ifile)) != EOF) {\n    crc = UPDC32(i, crc);\n  }\n\n  fclose(ifile);\n  return ~crc;\n}\n\nu_char* ZEnc4(uint32_t n) {\n  static u_char buf[4];\n  buf[0] = static_cast<u_char>(n & 0xff);\n\n  n >>= 8;\n  buf[1] = static_cast<u_char>(n & 0xff);\n\n  n >>= 8;\n  buf[2] = static_cast<u_char>(n & 0xff);\n\n  n >>= 8;\n  buf[3] = static_cast<u_char>(n & 0xff);\n\n  return buf;\n}\n\nuint32_t ZDec4(u_char buf[4]) { return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); }\n\nstd::string sname2(ZMState state) {\n  static const char* names[] = {\n      \"RStart\",      \"RSinitWait\", \"RFileName\", \"RCrc\",    \"RFile\",      \"RData\",\n      \"RDataErr\",    \"RFinish\",    \"TStart\",    \"TInit\",   \"FileWait\",   \"CrcWait\",\n      \"Sending\",     \"SendWait\",   \"SendDone\",  \"SendEof\", \"TFinish\",    \"CommandData\",\n      \"CommandWait\", \"StderrData\", \"Done\",      \"YTStart\", \"YTFile\",     \"YTDataWait\",\n      \"YTData\",      \"YTEOF\",      \"YTFin\",     \"YRStart\", \"YRDataWait\", \"YRData\",\n      \"YREOF\"};\n  return names[state];\n}\n\nstd::string sname(ZModem* info) { return sname2(info->state); }\n\nvoid zmodemlog_impl(fmt::string_view format, fmt::format_args args) {\n#if !defined(DEBUG_ZMODEMLOG)\n  return;\n#endif\n  static auto do_ts = true;\n  static FILE* zmodemlogfile = nullptr;\n\n  zmodemlogfile = fopen(\"zmodem_log.txt\", \"at\");\n  if (zmodemlogfile == nullptr) {\n    zmodemlogfile = stderr;\n  }\n\n  if (do_ts) {\n    const auto t = time(nullptr);\n    const auto ts = fmt::format(\"{:%Y-%m-%d %H:%M:%S} \", fmt::localtime(t));\n    fputs(ts.c_str(), zmodemlogfile);\n  }\n  do_ts = true; // find_char_at_end(format, '\\n');\n\n  try {\n    const auto s = fmt::vformat(format, args);\n    fputs(s.c_str(), zmodemlogfile);\n  } catch (const fmt::format_error& e) {\n    const auto f = std::string(format.begin(), format.end());\n    LOG(ERROR) << \"Error in zmodemerrorlog:  fmt: '\" << f << \"'; error: \" << e.what();\n  }\n\n  if (zmodemlogfile != stderr) {\n    fclose(zmodemlogfile);\n  }\n}\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "bbs/prot/zmutil.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1999-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_BBS_PROT_ZMUTIL_H\n#define INCLUDED_WWIV_BBS_PROT_ZMUTIL_H\n\n#include \"bbs/prot/zmodem.h\"\n#include \"fmt/format.h\"\n#include <cstdint>\n\nvoid zmodemlog_impl(fmt::string_view format, fmt::format_args args);\n\ntemplate <typename S, typename... Args>\nvoid zmodemlog(const S& format, Args&&... args) {\n  auto a = fmt::make_format_args(args...);\n  zmodemlog_impl(format, a);\n}\n\nstruct ZModem;\n\nuint32_t FileCrc(char* name);\nstd::string sname(ZModem*);\nstd::string sname2(ZMState);\n\n\n#endif\n"
  },
  {
    "path": "bbs/prot/zmwwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1999-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n#include \"bbs/prot/zmodem.h\"\n#include \"bbs/prot/zmutil.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/files/file_record.h\"\n\n#include <chrono>\n#include <cstring>\n#include <filesystem>\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\n// Local Functions\nint doIO(ZModem* info);\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n#pragma warning(disable : 4706 4127 4244 4100)\n#endif\n\nstatic void ZModemWindowStatusImpl(fmt::string_view format, fmt::format_args args) {\n  const auto s = fmt::vformat(format, args);\n  const auto oldX = bout.localIO()->WhereX();\n  const auto oldY = bout.localIO()->WhereY();\n  bout.localIO()->PutsXYA(0, 2, 12, s);\n  bout.localIO()->ClrEol();\n  bout.localIO()->PutsXYA(0, 3, 9, std::string(79, '='));\n  bout.localIO()->GotoXY(oldX, oldY);\n\n  zmodemlog(\"ZModemWindowStatus: [{}]\\r\\n\", s);\n}\n\ntemplate <typename S, typename... Args>\nstatic void ZModemWindowStatus(const S& format, Args&&... args) {\n  ZModemWindowStatusImpl(format, fmt::make_format_args(args...));\n}\n\n/**\n * fmtlib style output function.  Most code should use this when writing locally + remotely.\n */\nstatic void ZModemWindowXferStatusImpl(fmt::string_view format, fmt::format_args args) {\n  const auto s = fmt::vformat(format, args);\n  const auto oldX = bout.localIO()->WhereX();\n  const auto oldY = bout.localIO()->WhereY();\n  bout.localIO()->PutsXYA(0, 0, 3, \"ZModem Transfer Status: \");\n  bout.localIO()->PutsXYA(0, 1, 14, s);\n  bout.localIO()->ClrEol();\n  bout.localIO()->PutsXYA(0, 3, 9, std::string(79, '='));\n  bout.localIO()->GotoXY(oldX, oldY);\n}\n\ntemplate <typename S, typename... Args>\nstatic void ZModemWindowXferStatus(const S& format, Args&&... args) {\n  ZModemWindowXferStatusImpl(format, fmt::make_format_args(args...));\n}\n\nstatic void ProcessLocalKeyDuringZmodem() {\n  if (!bout.localIO()->KeyPressed()) {\n    return;\n  }\n  const auto c = bout.localIO()->GetChar();\n  bin.SetLastKeyLocal(true);\n  if (!c) {\n    a()->handle_sysop_key(bout.localIO()->GetChar());\n  }\n}\n\nbool NewZModemSendFile(const std::filesystem::path& path) {\n  ZModem info{};\n  info.ifd = info.ofd = -1;\n  info.zrinitflags = 0;\n  info.zsinitflags = 0;\n  info.attn = nullptr;\n  info.packetsize = 0;\n  info.windowsize = 0;\n  info.bufsize = 0;\n\n  sleep_for(milliseconds(500)); // Kludge -- Byte thinks this may help on his system\n\n  ZmodemTInit(&info);\n  auto done = doIO(&info);\n  if (done != ZmDone) {\n    zmodemlog(\"Returning False from doIO After ZModemTInit\\r\\n\");\n    return false;\n  }\n\n  uint8_t f0 = ZCBIN;\n  uint8_t f1 = 0; // xferType | noloc\n  uint8_t f2 = 0;\n  uint8_t f3 = 0;\n  int nFilesRem = 0;\n  int nBytesRem = 0;\n  char file_name[1024]; // was MAX_PATH\n  to_char_array(file_name, path.string());\n  zmodemlog(\"NewZModemSendFile: About to call ZmodemTFile\\n\");\n  done = ZmodemTFile(file_name, file_name, f0, f1, f2, f3, nFilesRem, nBytesRem, &info);\n  zmodemlog(\"NewZModemSendFile: After ZmodemTFile; [done: {}]\\n\", done);\n  switch (done) {\n  case 0:\n    ZModemWindowXferStatus(\"Sending File: {}\", file_name);\n    break;\n  case ZmErrCantOpen:\n    ZModemWindowXferStatus(\"ERROR Opening File: {}\", file_name);\n    break;\n  case ZmFileTooLong:\n    ZModemWindowXferStatus(\"ERROR FileName '{}' is too long\", file_name);\n    break;\n  case ZmDone:\n    return true;\n  default:\n    return false;\n  }\n\n  if (!done) {\n    done = doIO(&info);\n#if defined(_DEBUG)\n    zmodemlog(\"Returning {} from doIO After ZmodemTFile\\n\", done);\n#endif\n  }\n  if (done != ZmDone) {\n    return false;\n  }\n\n  sleep_for(milliseconds(500)); // Kludge -- Byte thinks this may help on his system\n\n  done = ZmodemTFinish(&info);\n  if (!done) {\n    done = doIO(&info);\n  }\n\n  return done == ZmDone;\n}\n\nbool NewZModemReceiveFile(const std::filesystem::path& path){\n  ZModem info{};\n  info.ifd = info.ofd = -1;\n  info.zsinitflags = 0;\n  info.attn = nullptr;\n  info.packetsize = 0;\n  info.windowsize = 0;\n  info.bufsize = 0;\n  // This is what receive uses.\n  info.zrinitflags = CANFDX|CANOVIO|CANBRK|CANFC32;\n\n  ZmodemRInit(&info);\n  const auto ret = doIO(&info) == ZmDone;\n  if (ret) {\n    const auto fn = wwiv::sdk::files::unalign(path.filename().string());\n    const auto old_fn = FilePath(a()->sess().dirs().temp_directory(), fn);\n\n    if (auto o = FindFile(old_fn)) {\n      // make case match.\n      LOG(INFO) << \"Move file: \" << o.value().string();\n      LOG(INFO) << \"Move to  : \" << path;\n      File::Move(o.value(), path);\n    }\n\n  }\n  return ret;\n}\n\nstatic constexpr int ZMODEM_RECEIVE_BUFFER_SIZE = 8132;\n// 21 here is just an arbitrary number\nstatic constexpr int ZMODEM_RECEIVE_BUFFER_PADDING = 21;\n\nint doIO(ZModem* info) {\n  u_char buffer[ZMODEM_RECEIVE_BUFFER_SIZE + ZMODEM_RECEIVE_BUFFER_PADDING];\n  auto done = 0;\n  auto doCancel = false; // %%TODO: make this true if the user aborts.\n\n  while (!done) {\n    const auto tThen = time(nullptr);\n    if (info->timeout > 0) {\n      zmodemlog(\"doIO: [{}] [timeout: {}] [state: {}]\\n\", tThen, info->timeout, sname2(info->state));\n    }\n    // Don't loop/sleep if the timeout is 0 (which means streaming), this makes the\n    // performance < 1k/second vs. 8-9k/second locally\n    while (info->timeout > 0 && !bout.remoteIO()->incoming() && !a()->sess().hangup()) {\n      sleep_for(milliseconds(100));\n      const auto tNow = time(nullptr);\n      if ((tNow - tThen) > info->timeout) {\n        zmodemlog(\"Break: [time: {}] Now.  Timedout: {}.  Time: {}\\r\\n\", tNow, info->timeout,\n                  tNow - tThen);\n        break;\n      }\n      ProcessLocalKeyDuringZmodem();\n    }\n\n    ProcessLocalKeyDuringZmodem();\n    if (a()->sess().hangup()) {\n      return ZmErrCancel;\n    }\n    if (!bout.remoteIO()->connected()) {\n      LOG(INFO) << \"Lost connection during ZModem transfer.\";\n      return ZmErrCancel;\n    }\n\n    if (doCancel) {\n      ZmodemAbort(info);\n      fprintf(stderr, \"cancelled by user\\n\");\n      zmodemlog(\"cancelled by user\");\n      // resetCom();\n      //%%TODO: signal parent we aborted.\n      return 1;\n    }\n    if (const auto incomming = bout.remoteIO()->incoming(); !incomming) {\n      done = ZmodemTimeout(info);\n      // zmodemlog(\"ZmodemTimeout State [{}] [done:{}]\\n\", sname(info), done);\n    } else {\n      const int len = bout.remoteIO()->read(reinterpret_cast<char*>(buffer), ZMODEM_RECEIVE_BUFFER_SIZE);\n      zmodemlog(\"ZmodemRcv Before [{}:{}] [{} chars] [done: {}]\\n\", sname(info), sname2(info->state), len, done);\n      done = ZmodemRcv(buffer, len, info);\n      //zmodemlog(\"ZmodemRcv After [{}] [{} chars] [done: {}]\\n\", sname(info), len, done);\n    }\n  }\n  zmodemlog(\"doIO: [done: {}]\\n\", done);\n  return done;\n}\n\nint ZXmitStr(const u_char* str, int len, ZModem* info) {\n  bout.remoteIO()->write(reinterpret_cast<const char*>(str), len);\n  return 0;\n}\n\nvoid ZIFlush(ZModem* info) {\n  zmodemlog(\"ZIFlush\\n\");\n  bout.remoteIO()->purgeIn();\n  //sleep_for(milliseconds(100));\n  // outstr( \"ZIFlush\" );\n  // if( connectionType == ConnectionSerial )\n  //  SerialFlush( 0 );\n}\n\nvoid ZOFlush(ZModem* info) {\n  zmodemlog(\"ZOFlush\\n\");\n  // if( connectionType == ConnectionSerial )\n  //\tSerialFlush( 1 );\n}\n\nint ZAttn(ZModem* info) {\n  zmodemlog(\"ZAttn\\n\");\n  if (info->attn == nullptr) {\n    return 0;\n  }\n\n  int cnt = 0;\n  for (char* ptr = info->attn; *ptr != '\\0'; ++ptr) {\n    if (((cnt++) % 10) == 0) {\n      sleep_for(milliseconds(1));\n    }\n    if (*ptr == ATTNBRK) {\n      // SerialBreak();\n    } else if (*ptr == ATTNPSE) {\n#if defined(_DEBUG)\n      zmodemlog(\"ATTNPSE\\r\\n\");\n#endif\n      sleep_for(milliseconds(1));\n    } else {\n      bout.rputch(*ptr, true);\n      // append_buffer(&outputBuf, ptr, 1, ofd);\n    }\n  }\n  bout.flush();\n  return 0;\n}\n\n/* set flow control as required by protocol.  If original flow\n * control was hardware, do not change it.  Otherwise, toggle\n * software flow control\n */\nvoid ZFlowControl(int /* onoff */, ZModem* /* info */) {\n  // I don't think there is anything to do here.\n}\n\nvoid ZStatus(int type, int value, char* msg) {\n  switch (type) {\n  case RcvByteCount:\n    ZModemWindowXferStatus(\"ZModemWindowXferStatus: {} bytes received\", value);\n    // WindowXferGauge(value);\n    break;\n\n  case SndByteCount:\n    ZModemWindowXferStatus(\"ZModemWindowXferStatus: {} bytes sent\", value);\n    // WindowXferGauge(value);\n    break;\n\n  case RcvTimeout:\n    ZModemWindowStatus(\"ZModemWindowStatus: Receiver did not respond, aborting\");\n    break;\n\n  case SndTimeout:\n    ZModemWindowStatus(\"ZModemWindowStatus: {} send timeouts\", value);\n    break;\n\n  case RmtCancel:\n    ZModemWindowStatus(\"ZModemWindowStatus: Remote end has cancelled\");\n    break;\n\n  case ProtocolErr:\n    ZModemWindowStatus(\"ZModemWindowStatus: Protocol error, header={}\", value);\n    break;\n\n  case RemoteMessage: /* message from remote end */\n    ZModemWindowStatus(\"ZModemWindowStatus: MESSAGE: {}\", msg);\n    break;\n\n  case DataErr: /* data error, val=error count */\n    ZModemWindowStatus(\"ZModemWindowStatus: {} data errors\", value);\n    break;\n\n  case FileErr: /* error writing file, val=errno */\n    ZModemWindowStatus(\"ZModemWindowStatus: Cannot write file: {}\", strerror(errno));\n    break;\n\n  case FileBegin: /* file transfer begins, str=name */\n    ZModemWindowStatus(\"ZModemWindowStatus: Transfering {}\", msg);\n    break;\n\n  case FileEnd: /* file transfer ends, str=name */\n    ZModemWindowStatus(\"ZModemWindowStatus: {} finished\", msg);\n    break;\n\n  case FileSkip: /* file transfer ends, str=name */\n    ZModemWindowStatus(\"ZModemWindowStatus: Skipping {}\", msg);\n    break;\n  }\n}\n\nFILE* ZOpenFile(char* file_name, uint32_t /* crc */, ZModem* /* info */) {\n  const auto tfn = FilePath(a()->sess().dirs().temp_directory(), file_name).string();\n#if defined(_DEBUG)\n  zmodemlog(\"ZOpenFile filename='{}' [full path: {}]\\r\\n\", file_name, tfn);\n#endif\n  return fopen(tfn.c_str(), \"wb\");\n\n  //\tstruct stat\tbuf;\n  //\tbool\t\texists;\t/* file already exists */\n  //\tstatic\tint\t\tchangeCount = 0;\n  //\tchar\t\tfile_name2[MAXPATHLEN];\n  //\tint\t\tapnd = 0;\n  //\tint\t\tf0,f1;\n  //\tFILE\t\t*ofile;\n  //\tchar\t\tpath[1024];\n  //\n  //\t/* TODO: if absolute path, do we want to allow it?\n  //\t * if relative path, do we want to prepend something?\n  //\t */\n  //\n  //\tif( *file_name == '/' )\t/* for now, disallow absolute paths */\n  //\t  return nullptr;\n  //\n  //\tbuf.st_size = 0;\n  //\tif( stat(file_name, &buf) == 0 )\n  //\t  exists = True;\n  //\telse if( errno == ENOENT )\n  //\t  exists = False;\n  //\telse\n  //\t  return nullptr;\n  //\n  //\n  //\t/* if remote end has not specified transfer flags, we can\n  //\t * accept the local definitions\n  //\t */\n  //\n  //\tif( (f0=info->f0) == 0 ) {\n  //\t  if( xferResume )\n  //\t    f0 = ZCRESUM;\n  //\t  else if( xferAscii )\n  //\t    f0 = ZCNL;\n  //#ifdef\tCOMMENT\n  //\t  else if( binary )\n  //\t    f0 = ZCBIN;\n  //#endif\t/* COMMENT */\n  //\t  else\n  //\t    f0 = 0;\n  //\t}\n  //\n  //\tif( (f1=info->f1) == 0 ) {\n  //\t  f1 = xferType;\n  //\t  if( noLoc )\n  //\t    f1 |= ZMSKNOLOC;\n  //\t}\n  //\n  //\tzmodemlog(\"ZOpenFile: {}, f0={:x}, f1={:x}, exists={}, size={}/{}\\n\",\n  //\t  file_name, f0,f1, exists, buf.st_size, info->len);\n  //\n  //\tif( f0 == ZCRESUM ) {\t/* if exists, and we already have it, return */\n  //\t  if( exists  &&  buf.st_size == info->len )\n  //\t    return nullptr;\n  //\t  apnd = 1;\n  //\t}\n  //\n  //\t/* reject if file not found and it must be there (ZMSKNOLOC) */\n  //\tif( !exists && (f1 & ZMSKNOLOC) )\n  //\t  return nullptr;\n  //\n  //\tswitch( f1 & ZMMASK ) {\n  //\t  case 0:\t/* Implementation-dependent.  In this case, we\n  //\t\t\t * reject if file exists (and ZMSKNOLOC not set) */\n  //\t    if( exists && !(f1 & ZMSKNOLOC) )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMNEWL:\t/* take if newer or longer than file on disk */\n  //\t    if( exists  &&  info->date <= buf.st_mtime  &&\n  //\t\tinfo->len <= buf.st_size )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMCRC:\t\t/* take if different CRC or length */\n  //\t    zmodemlog(\"  ZMCRC: crc={:x}, FileCrc={:x}\\n\", crc, FileCrc(file_name) );\n  //\t    if( exists  &&  info->len == buf.st_size && crc == FileCrc(file_name) )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMAPND:\t/* append */\n  //\t    apnd = 1;\n  //\t  case ZMCLOB:\t/* unconditional replace */\n  //\t    break;\n  //\n  //\t  case ZMNEW:\t/* take if newer than file on disk */\n  //\t    if( exists  &&  info->date <= buf.st_mtime )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMDIFF:\t/* take if different date or length */\n  //\t    if( exists  &&  info->date == buf.st_mtime  &&\n  //\t\tinfo->len == buf.st_size )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMPROT:\t/* only if dest does not exist */\n  //\t    if( exists )\n  //\t      return nullptr;\n  //\t    break;\n  //\n  //\t  case ZMCHNG:\t/* invent new filename if exists */\n  //\t    if( exists ) {\n  //\t      while( exists ) {\n  //\t\tsprintf(file_name2, \"%s_%d\", file_name, changeCount++);\n  //\t\texists = stat(file_name2, &buf) == 0 || errno != ENOENT;\n  //\t      }\n  //\t      file_name = file_name2;\n  //\t    }\n  //\t    break;\n  //\t}\n  //\n  //\t/* here if we've decided to accept */\n  //\tif( exists && !apnd && unlink(file_name) != 0 )\n  //\t  return nullptr;\n  //\n  //\t/* TODO: build directory path if needed */\n  //\n  //\tZModemWindowStatus(\"Receiving: \\\"{}\\\"\", file_name);\n  //\n  //\tWindowXferGaugeMax(info->len);\n  //\n  //\tofile = fopen(file_name, apnd ? \"a\" : \"w\");\n  //\n  //\tzmodemlog(\"  ready to open {}/{}: apnd = {}, file = {:x}\\n\",\n  //\t  getcwd(path,sizeof(path)), file_name, apnd, (long)ofile);\n  //\n  //\treturn ofile;\n  // return nullptr;\n}\n\nint ZWriteFile(u_char* buffer, int len, FILE* file, ZModem* info) {\n  /* If ZCNL set in info->f0, convert\n   * newlines to unix convention\n   */\n  // if( info->f0 == ZCNL )\n  //{\n  //  int\ti, j, c;\n  //  static int lastc = '\\0';\n  //  for(i=0; i < len; ++i)\n  //  {\n  //    switch( (c=*buffer++) ) {\n  //      case '\\n': if( lastc != '\\r' ) j = putc('\\n', file); break;\n  //      case '\\r': if( lastc != '\\n' ) j = putc('\\n', file); break;\n  //      default: j = putc(c, file); break;\n  //    }\n  //    lastc = c;\n  //    if( j == EOF )\n  //      return ZmErrSys;\n  //  }\n  //  return 0;\n  //}\n  // else\n  if (info->f0 == ZCNL) {\n#ifdef _DEBUG\n    zmodemlog(\"ZCNL\\n\");\n#endif // _WIN32\n  }\n  return fwrite(buffer, 1, len, file) == static_cast<unsigned int>(len) ? 0 : ZmErrSys;\n}\n\nint ZCloseFile(ZModem* info) {\n  fclose(info->file);\n  //\tstruct timeval tvp[2];\n  //\tfclose(info->file);\n  //#ifdef\tTODO\n  //\tif( ymodem )\n  //\t  truncate(info->filename, info->len);\n  //#endif\t/* TODO */\n  //\tif( info->date != 0 ) {\n  //\t  tvp[0].tv_sec = tvp[1].tv_sec = info->date;\n  //\t  tvp[0].tv_usec = tvp[1].tv_usec = 0;\n  //\t  utimes(info->filename, tvp);\n  //\t}\n  //\tif( info->mode & 01000000 )\n  //\t  chmod(info->filename, info->mode&0777);\n  //\treturn 0;\n  return 0;\n}\n\nvoid ZIdleStr(unsigned char* buf, int len, ZModem* info) {\n  // PutTerm(buf, len);\n  return;\n#if 0\n\tchar szBuffer[1024];\n\tstrcpy( szBuffer, reinterpret_cast<const char *>( buf  ) );\n\tszBuffer[len] = '\\0';\n\tif ( strlen( szBuffer ) == 1 ) {\n\t\tzmodemlog( \"ZIdleStr: #[{}]\\r\\n\", static_cast<unsigned int>( (unsigned char ) szBuffer[0] ) );\n\t} else {\n\t\tzmodemlog( \"ZIdleStr: [{}]\\r\\n\", szBuffer );\n\t}\n#endif\n}\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n"
  },
  {
    "path": "bbs/quote_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2017-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"common/quote.h\"\n\nusing namespace wwiv::common;\nusing namespace wwiv::sdk;\n\nclass QuoteTest : public ::testing::Test {\nprotected:\n  void SetUp() override {}\n};\n\nTEST_F(QuoteTest, Smoke) {\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan\"));\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"RushFan\"));\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"Rushfan\"));\n  EXPECT_EQ(\"RfD\", GetQuoteInitials(\"Rush fan Dude\"));\n  EXPECT_EQ(\"RfDM\", GetQuoteInitials(\"Rush fan Dude Man\"));\n  EXPECT_EQ(\"\", GetQuoteInitials(\"\"));\n}\n\nTEST_F(QuoteTest, WithUserNumber) {\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan #21\"));\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"RushFan #21\"));\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"Rushfan #21\"));\n  EXPECT_EQ(\"RfD\", GetQuoteInitials(\"Rush fan Dude #21\"));\n}\n\nTEST_F(QuoteTest, TrailingOrLeaderSpaces) {\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush    Fan\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"    Rush Fan\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan     \"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan     #21\"));\n}\n\n\nTEST_F(QuoteTest, ParensForNodeOrRealName) {\n  EXPECT_EQ(\"T\", GetQuoteInitials(\"Tiny (21:1/130.4)\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan (21:1/130.4)\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan #1 (21:1/130.4)\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan #1 @1234 (21:1/130.4)\"));\n\n  EXPECT_EQ(\"JM\", GetQuoteInitials(\"Rush Fan (Joe Mama)\"));\n}\n\nTEST_F(QuoteTest, WithNode) {\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"Rushfan #21 @1234\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan #21 @1234\"));\n}\n\nTEST_F(QuoteTest, BracketsForApp) {\n  EXPECT_EQ(\"R\", GetQuoteInitials(\"Rushfan #21 @1234 [Cool Software]\"));\n  EXPECT_EQ(\"RF\", GetQuoteInitials(\"Rush Fan #21 @1234 [Cool Software]\"));\n}\n\nTEST_F(QuoteTest, EscapedNameFormat) {\n  EXPECT_EQ(\"H\", GetQuoteInitials(\"``Hobbit`` #1@4295.WWIVnet\"));\n  EXPECT_EQ(\"TH\", GetQuoteInitials(\"``The Hobbit`` #1@4295.WWIVnet\"));\n\n  // Not sure if this is right but just as wrong as what we used to return.B\n  EXPECT_EQ(\"\", GetQuoteInitials(\"```Hobbit``` #1@4295.WWIVnet\"));\n  EXPECT_EQ(\"H\", GetQuoteInitials(\"``Hobbit``` #1@4295.WWIVnet\"));\n}\n\nTEST_F(QuoteTest, Matt) {\n  EXPECT_EQ(\"M\", GetQuoteInitials(\"Monk #1 @815 \\xfe right winged conspirator \\xfe\"));\n  EXPECT_EQ(\"TM\", GetQuoteInitials(\"The Monk #1 @815 \\xfe right winged conspirator \\xfe\"));\n  EXPECT_EQ(\"M\", GetQuoteInitials(\"Monk #1 @815 [ Windows to the People! ]\"));\n  EXPECT_EQ(\"TM\", GetQuoteInitials(\"The Monk #1 @815 [ Windows to the People! ]\"));\n}\n\n"
  },
  {
    "path": "bbs/qwk/qwk.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/qwk/qwk_mail_packet.h\"\n#include \"bbs/qwk/qwk_reply.h\"\n#include \"bbs/qwk/qwk_ui.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/qwk_config.h\"\n#include \"sdk/vardec.h\"\n\n#include <optional>\n#include <string>\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\n\nnamespace wwiv::bbs::qwk {\n\nvoid qwk_download() {\n  sysoplog(\"Download QWK packet\");\n  build_qwk_packet();\n}\n\nvoid qwk_upload() {\n  sysoplog(\"Upload REP packet\");\n  upload_reply_packet();\n}\n\nvoid qwk_menu() {\n  const auto qwk_cfg = read_qwk_cfg(*a()->config());\n\n  while (!a()->sess().hangup()) {\n    bout.cls();\n    bout.printfile(\"QWK\");\n    std::string allowed = \"QCDU?\";\n    if (so()) {\n      allowed.push_back('*');\n    }\n    bout.nl();\n    if (so()) {\n      bout.outstr(\"|#7(|#1*|#7=|#2Sysop Menu|#7,|#1Q|#7=|#2Quit|#7) |#1C|#7, |#1D|#7, |#1U|#7: \");\n    } else {\n      bout.outstr(\"|#7(|#1Q|#7=|#2Quit|#7) |#1C|#7, |#1D|#7, |#1U|#7: \");\n    }\n\n    switch (const auto key = onek(allowed, true); key) {\n    case 'C':\n      qwk_config_user();\n      break;\n    case 'D':\n      qwk_download();\n      break;\n    case 'Q':\n      return;\n    case 'U':\n      qwk_upload();\n      break;\n    case '*':\n      qwk_config_sysop();\n      break;\n    case '?':\n    default:\n      break;\n    }\n  }\n}\n\nvoid qwk_nscan() {\n#ifdef NEVER // Not ported yet\n#define SETREC(f, i) lseek(f, ((long)(i)) * ((long)sizeof(uploadsrec)), SEEK_SET);\n  static constexpr int DOTS = 5;\n  uploadsrec u;\n  bool abort = false;\n  int od, newfile, i, i1, i5, f, count, color = 3;\n  char s[201];\n  ;\n\n  bout.ansic(3);\n  bout.outstr(\"Building NEWFILES.DAT\");\n\n  sprintf(s, \"%s%s\", a()->sess().dirs().qwk_directory().c_str(), \"NEWFILES.DAT\");\n  newfile = open(s, O_BINARY | O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE;\n  if (newfile < 1) {\n    bout.outstr(\"Open Error\");\n    return;\n  }\n\n  for (i = 0; i < num_dirs && !abort; i++) {\n    bin.checka(&abort);\n    count++;\n\n    bout.printf(\"\u0003%d.\", color);\n    if (count >= DOTS) {\n      bout.outstr(\"\\r\");\n      bout.outstr(\"Searching\");\n      color++;\n      count = 0;\n      if (color == 4) {\n        color++;\n      }\n      if (color == 10) {\n        color = 0;\n      }\n    }\n\n    i1 = a()->udir[i].subnum;\n    if (a()->sess().qsc_n[i1 / 32] & (1L << (i1 % 32))) {\n      if ((dir_dates[a()->udir[i].subnum]) &&\n          (dir_dates[a()->udir[i].subnum] < a()->sess().nscandate())) {\n        continue;\n      }\n\n      od = a()->current_user_dir_num();\n      a()->set_current_user_dir_num(i);\n      dliscan();\n      if (this_date >= a()->sess().nscandate()) {\n        sprintf(s, \"\\r\\n\\r\\n%s - #%s, %d %s.\\r\\n\\r\\n\",\n                a()->dirs()[a()->current_user_dir().subnum].name, a()->current_user_dir().keys,\n                numf, \"files\");\n        write(newfile, s, strlen(s));\n\n        f = open(dlfn, O_RDONLY | O_BINARY);\n        for (i5 = 1; (i5 <= numf) && (!(abort)) && (!a()->sess().hangup()); i5++) {\n          SETREC(f, i5);\n          read(f, &u, sizeof(uploadsrec));\n          if (u.daten >= a()->sess().nscandate()) {\n            sprintf(s, \"%s %5ldk  %s\\r\\n\", u.filename, (long)bytes_to_k(u.numbytes), u.description);\n            write(newfile, s, strlen(s));\n\n#ifndef HUGE_TRAN\n            if (u.mask & mask_extended) {\n              int pos = 0;\n              string ext =\n                  a()->current_file_area()->ReadExtentedDescription(u.filename).value_or(\"\");\n\n              if (!ext.empty(0)) {\n                int spos = 21, x;\n\n                strcpy(s, \"                     \");\n                while (ext[pos]) {\n                  x = ext[pos];\n\n                  if (x != '\\r' && x != '\\n' && x > 2) {\n                    s[spos] = x;\n                  }\n\n                  if (x == '\\n' || x == 0) {\n                    s[spos] = 0;\n                    write(newfile, s, strlen(s));\n                    write(newfile, \"\\r\\n\", 2);\n                    strcpy(s, \"                     \");\n                    spos = 21;\n                  }\n\n                  if (x != '\\r' && x != '\\n' && x > 2) {\n                    ++spos;\n                  }\n\n                  ++pos;\n                }\n              }\n            }\n#endif\n\n          } else if (!empty()) {\n            bin.checka(&abort);\n          }\n        }\n        f = close(f);\n      }\n      a()->set_current_user_dir_num(od);\n    }\n  }\n  newfile = close(newfile);\n#endif // NEVER\n}\n\nstatic std::string qwk_current_text(int pos) {\n  static const char* yesorno[] = {\"Yes\", \"No\"};\n\n  switch (pos) {\n  case 0:\n    return a()->user()->data.qwk_dont_scan_mail ? yesorno[1] : yesorno[0];\n  case 1:\n    return a()->user()->data.qwk_delete_mail ? yesorno[0] : yesorno[1];\n  case 2:\n    return a()->user()->data.qwk_dontsetnscan ? yesorno[1] : yesorno[0];\n  case 3:\n    return a()->user()->data.qwk_remove_color ? yesorno[0] : yesorno[1];\n  case 4:\n    return a()->user()->data.qwk_convert_color ? yesorno[0] : yesorno[1];\n  case 5:\n    return a()->user()->data.qwk_leave_bulletin ? yesorno[1] : yesorno[0];\n  case 6:\n    return a()->user()->data.qwk_dontscanfiles ? yesorno[1] : yesorno[0];\n  case 7:\n    return a()->user()->data.qwk_keep_routing ? yesorno[1] : yesorno[0];\n  case 8:\n    return qwk_which_zip();\n  case 9:\n    return qwk_which_protocol();\n  case 10: {\n    if (!a()->user()->data.qwk_max_msgs_per_sub && !a()->user()->data.qwk_max_msgs) {\n      return \"Unlimited/Unlimited\";\n    }\n    if (!a()->user()->data.qwk_max_msgs_per_sub) {\n      return fmt::format(\"Unlimited/{}\", a()->user()->data.qwk_max_msgs);\n    }\n    if (!a()->user()->data.qwk_max_msgs) {\n      return fmt::format(\"{}/Unlimited\", a()->user()->data.qwk_max_msgs_per_sub);\n    }\n    return fmt::format(\"{}/{}\", a()->user()->data.qwk_max_msgs,\n                       a()->user()->data.qwk_max_msgs_per_sub);\n  }\n  case 11:\n  default:\n    return \"DONE\";\n  }\n}\n\nstatic std::optional<uint16_t> select_qwk_protocol() {\n  const auto protocol = get_protocol(xfertype::xf_down_temp);\n  if (protocol == -1) {\n    return std::nullopt;\n  }\n  return static_cast<uint16_t>(protocol);\n}\n\nvoid qwk_config_user() {\n  sysoplog(\"Config Options\");\n  bool done = false;\n\n  while (!done && !a()->sess().hangup()) {\n    bout.cls();\n    bout.litebar(\"QWK Preferences\");\n    bout.print(\"|#1A|#9) Include E-Mail            : |#2{}\\r\\n\", qwk_current_text(0));\n    bout.print(\"|#1B|#9) Delete Included E-Mail    : |#2{}\\r\\n\", qwk_current_text(1));\n    bout.print(\"|#1C|#9) Update Last Read Pointer  : |#2{}\\r\\n\", qwk_current_text(2));\n    bout.print(\"|#1D|#9) Remove WWIV color codes   : |#2{}\\r\\n\", qwk_current_text(3));\n    bout.print(\"|#1E|#9) Convert WWIV color to ANSI: |#2{}\\r\\n\", qwk_current_text(4));\n    bout.print(\"|#1F|#9) Include Bulletins         : |#2{}\\r\\n\", qwk_current_text(5));\n    // bout.print(\"|#1G|#9) Scan New Files           : |#2{}\\r\\n\", qwk_current_text(6));\n    bout.print(\"|#1H|#9) Remove Routing Information: |#2{}\\r\\n\", qwk_current_text(7));\n    bout.print(\"|#1I|#9) Default Compression Type  : |#2{}\\r\\n\", qwk_current_text(8));\n    bout.print(\"|#1J|#9) Default Transfer Protocol : |#2{}\\r\\n\", qwk_current_text(9));\n    bout.print(\"|#1K|#9) Max Messages To Include   : |#2{}\\r\\n\", qwk_current_text(10));\n    bout.pl(\"|#1Q|#9) Done\");\n    bout.nl(2);\n    bout.outstr(\"|#9Select: \");\n    int key = onek(\"QABCDEFGHIJK\", true);\n\n    if (key == 'Q') {\n      done = true;\n    }\n    key = key - 'A';\n\n    switch (key) {\n    case 0:\n      a()->user()->data.qwk_dont_scan_mail = !a()->user()->data.qwk_dont_scan_mail;\n      break;\n    case 1:\n      a()->user()->data.qwk_delete_mail = !a()->user()->data.qwk_delete_mail;\n      break;\n    case 2:\n      a()->user()->data.qwk_dontsetnscan = !a()->user()->data.qwk_dontsetnscan;\n      break;\n    case 3:\n      a()->user()->data.qwk_remove_color = !a()->user()->data.qwk_remove_color;\n      break;\n    case 4:\n      a()->user()->data.qwk_convert_color = !a()->user()->data.qwk_convert_color;\n      break;\n    case 5:\n      a()->user()->data.qwk_leave_bulletin = !a()->user()->data.qwk_leave_bulletin;\n      break;\n    case 6:\n      a()->user()->data.qwk_dontscanfiles = !a()->user()->data.qwk_dontscanfiles;\n      break;\n    case 7:\n      a()->user()->data.qwk_keep_routing = !a()->user()->data.qwk_keep_routing;\n      break;\n    case 8: {\n      bool abort{false};\n      bout.cls();\n\n      const auto arcno = select_qwk_archiver(abort, true);\n      if (!abort) {\n        a()->user()->data.qwk_archive = arcno;\n      }\n      break;\n    }\n    case 9: {\n      bout.cls();\n      if (const auto prot = select_qwk_protocol()) {\n        a()->user()->data.qwk_protocol = prot.value();\n      }\n    } break;\n    case 10: {\n      if (auto max_msgs = a()->user()->data.qwk_max_msgs,\n          max_per_sub = a()->user()->data.qwk_max_msgs_per_sub;\n          get_qwk_max_msgs(&max_msgs, &max_per_sub)) {\n        a()->user()->data.qwk_max_msgs = max_msgs;\n        a()->user()->data.qwk_max_msgs_per_sub = max_per_sub;\n      }\n    } break;\n    }\n  }\n}\n\nvoid qwk_config_sysop() {\n  if (!so()) {\n    return;\n  }\n  sysoplog(\"Ran Sysop Config\");\n\n  auto c = read_qwk_cfg(*a()->config());\n\n  auto done = false;\n  while (!done && !a()->sess().hangup()) {\n    bout.cls();\n    bout.print(\"|#21|#9) Hello file     : |#5{}\\r\\n\", c.hello.empty() ? \"|#3<None>\" : c.hello);\n    bout.print(\"|#22|#9) News file      : |#5{}\\r\\n\", c.news.empty() ? \"|#3<None>\" : c.news);\n    bout.print(\"|#23|#9) Goodbye file   : |#5{}\\r\\n\", c.bye.empty() ? \"|#3<None>\" : c.bye);\n    auto sn = qwk_system_name(c, a()->config()->system_name());\n    bout.print(\"|#24|#9) Packet name    : |#5{}\\r\\n\", sn);\n    const auto max_msgs = c.max_msgs == 0 ? \"(Unlimited)\" : std::to_string(c.max_msgs);\n    bout.print(\"|#25|#9) Max Msgs/Packet: |#5{}\\r\\n\", max_msgs);\n    bout.print(\"|#26|#9) Modify Bulletins ({})\\r\\n\", c.bulletins.size());\n    bout.print(\"|#2Q|#9) Quit\\r\\n\");\n    bout.nl();\n    bout.outstr(\"|#9Selection? \");\n\n    const int x = onek(\"Q123456\\r\\n\");\n    if (x == '1' || x == '2' || x == '3') {\n      bout.nl();\n      bout.outstr(\"|#9Enter New Filename:\");\n      bout.mpl(12);\n    }\n\n    switch (x) {\n    case '1':\n      c.hello = bin.input(12);\n      break;\n    case '2':\n      c.news = bin.input(12);\n      break;\n    case '3':\n      c.bye = bin.input(12);\n      break;\n    case '4': {\n      sn = qwk_system_name(c, a()->config()->system_name());\n      write_qwk_cfg(*a()->config(), c);\n      bout.nl();\n      bout.print(\"|#9 Current Packet Name:  |#1{}\\r\\n\", sn);\n      bout.outstr(\"|#9Enter new packet name: \");\n      bout.mpl(8);\n      sn = bin.input_text(sn, 8);\n      if (!sn.empty()) {\n        c.packet_name = ToStringLowerCase(sn);\n      }\n      write_qwk_cfg(*a()->config(), c);\n    } break;\n\n    case '5': {\n      bout.outstr(\"|#9(|#10=Unlimited|#9) Enter max messages per packet: \");\n      bout.mpl(5);\n      c.max_msgs = bin.input_number(c.max_msgs, 0, 65535, true);\n    } break;\n    case '6':\n      modify_bulletins(c);\n      break;\n    default:\n      done = true;\n    }\n  }\n\n  write_qwk_cfg(*a()->config(), c);\n}\n\n} // namespace wwiv::bbs::qwk\n"
  },
  {
    "path": "bbs/qwk/qwk.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_H\n#define INCLUDED_BBS_QWK_QWK_H\n\n#define BULL_SIZE     81\n#define BNAME_SIZE    13\n\nnamespace wwiv::bbs::qwk {\n\n// Main QWK functions\nvoid qwk_menu();\nvoid qwk_download();\nvoid qwk_upload();\nvoid qwk_config_sysop();\nvoid qwk_config_user();\n\n}\n\n#endif\n"
  },
  {
    "path": "bbs/qwk/qwk_email.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"qwk_mail_packet.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/email.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/readmail.h\"\n#include \"bbs/qwk/qwk_reply.h\"\n#include \"bbs/qwk/qwk_struct.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"core/file.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/names.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/msgapi/message_utils_wwiv.h\"\n#include \"sdk/net/networks.h\"\n\nnamespace wwiv::bbs::qwk {\n\nusing namespace core;\nusing namespace sdk::msgapi;\n\nvoid qwk_remove_email() {\n  a()->emchg_ = false;\n\n  std::vector<tmpmailrec> mloc;\n  auto f(OpenEmailFile(true));\n\n  if (!f->IsOpen()) {\n    return;\n  }\n\n  const auto mfl = f->length() / sizeof(mailrec);\n  uint8_t mw = 0;\n\n  mailrec m{};\n  for (unsigned long i = 0; (i < mfl) && (mw < MAXMAIL); i++) {\n    f->Seek(i * sizeof(mailrec), File::Whence::begin);\n    f->Read(&m, sizeof(mailrec));\n    if (m.tosys == 0 && m.touser == a()->sess().user_num()) {\n      tmpmailrec r{};\n      r.index = static_cast<int16_t>(i);\n      r.fromsys = m.fromsys;\n      r.fromuser = m.fromuser;\n      r.daten = m.daten;\n      r.msg = m.msg;\n      mloc.emplace_back(r);\n      mw++;\n    }\n  }\n  a()->user()->data.waiting = mw;\n\n  if (mloc.empty()) {\n    return;\n  }\n\n  auto curmail = 0;\n  auto done = false;\n  do {\n    delmail(*f, stl::at(mloc, curmail).index);\n\n    ++curmail;\n    if (curmail >= mw) {\n      done = true;\n    }\n\n  } while (!a()->sess().hangup() && !done);\n}\n\nvoid qwk_gather_email(qwk_state* qwk_info) {\n  mailrec m{};\n  postrec junk{};\n\n  a()->emchg_ = false;\n  std::vector<tmpmailrec> mloc;\n\n  auto f(OpenEmailFile(false));\n  if (!f->IsOpen()) {\n    bout.nl(2);\n    bout.outstr(\"No mail file exists!\");\n    bout.nl();\n    return;\n  }\n  const auto mfl = static_cast<int>(f->length() / sizeof(mailrec));\n  uint8_t mw = 0;\n  for (auto i = 0; i < mfl && mw < MAXMAIL; i++) {\n    f->Seek(static_cast<File::size_type>(i) * sizeof(mailrec), File::Whence::begin);\n    f->Read(&m, sizeof(mailrec));\n    if (m.tosys == 0 && m.touser == a()->sess().user_num()) {\n      tmpmailrec r{};\n      r.index = static_cast<int16_t>(i);\n      r.fromsys = m.fromsys;\n      r.fromuser = m.fromuser;\n      r.daten = m.daten;\n      r.msg = m.msg;\n      mloc.emplace_back(r);\n      mw++;\n    }\n  }\n  f->Close();\n  a()->user()->data.waiting = mw;\n\n  if (mw == 0) {\n    bout.nl();\n    bout.outstr(\"You have no mail.\");\n    bout.nl();\n    return;\n  }\n\n  bout.ansic(7);\n  bout.outstr(\"Gathering Email\");\n\n  auto curmail = 0;\n  auto done = false;\n  qwk_info->in_email = true;\n  const auto index_filemode = File::modeReadWrite | File::modeAppend | File::modeBinary | File::modeCreateFile;\n\n  const auto personal_filename = FilePath(a()->sess().dirs().qwk_directory(), \"PERSONAL.NDX\");\n  qwk_info->personal =\n      std::make_unique<DataFile<qwk_index>>(personal_filename, index_filemode);\n\n\n  const auto zero_filename = FilePath(a()->sess().dirs().qwk_directory(), \"000.NDX\");\n  qwk_info->zero = \n      std::make_unique<DataFile<qwk_index>>(zero_filename, index_filemode);\n\n  do {\n    read_same_email(mloc, mw, curmail, m, false, 0);\n\n    strupr(m.title);\n    strncpy(qwk_info->email_title, stripcolors(m.title), 25);\n    // had crash in stripcolors since this won't null terminate.\n    // qwk_info->email_title[25] = 0;\n\n    //i = (ability_read_email_anony & ss.ability) != 0;\n\n    if (m.fromsys && !m.fromuser) {\n      grab_user_name(&m.msg, \"email\", network_number_from(&m));\n    } else {\n      a()->net_email_name.clear();\n    }\n    set_net_num(network_number_from(&m));\n\n    // Hope this isn't killed in the future\n    strcpy(junk.title, m.title);\n    junk.anony = m.anony;\n    junk.status = m.status;\n    junk.ownersys = m.fromsys;\n    junk.owneruser = m.fromuser;\n    junk.daten = m.daten;\n    junk.msg = m.msg;\n\n    put_in_qwk(&junk, \"email\", curmail, qwk_info);\n\n    ++curmail;\n    if (curmail >= mw) {\n      done = true;\n    }\n\n  } while (!a()->sess().hangup() && !done);\n\n  qwk_info->in_email = false;\n}\n\nvoid qwk_email_text(const char* text, char* title, char* to) {\n  strupr(to);\n\n  // Remove text name from address, if it doesn't contain \" AT \" in it\n  auto* st = strstr(to, \" AT \");\n  if (!st) {\n    st = strchr(to, '#');\n    if (st) {\n      strcpy(to, st + 1);\n    }\n  } else { // Also try and strip off name of a gated user\n    st = strstr(to, \"``\");\n    if (st) {\n      st = strstr(st + 1, \"``\");\n      if (st) {\n        strcpy(to, st + 2);\n      }\n    }\n  }\n\n  a()->sess().clear_irt();\n  auto [un, sy] = parse_email_info(to);\n  clear_quotes(a()->sess());\n\n  if (un || sy) {\n    std::optional<net_system_list_rec> csne;\n\n    if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n      bout.nl();\n      bout.pl(\"Sorry, not enough disk space left.\");\n      bout.pausescr();\n      return;\n    }\n\n    if (ForwardMessage(&un, &sy)) {\n      bout.nl();\n      bout.pl(\"Mail Forwarded.\");\n      if (un == 0 && sy == 0) {\n        bout.pl(\"Forwarded to unknown user.\");\n        bout.pausescr();\n        return;\n      }\n    }\n\n    if (!un && !sy) {\n      return;\n    }\n\n    if (sy) {\n      csne = next_system(sy);\n    }\n\n    std::string send_to_name;\n    if (sy == 0) {\n      set_net_num(0);\n      send_to_name = a()->names()->UserName(un);\n    } else {\n      const auto netname = wwiv::stl::ssize(a()->nets()) > 1 ? a()->network_name() : \"\";\n      send_to_name = username_system_net_as_string(un, a()->net_email_name, sy, netname);\n    }\n\n    if (sy != 0 && csne.has_value()) {\n      bout.nl();\n      bout.print(\"Name of system: {}\\r\\n\", csne->name);\n      bout.print(\"Number of hops: {}\\r\\n\\r\\n\", csne->numhops);\n    }\n\n    bout.cls();\n    bout.print(\"|#2Sending to: {}\\r\\n\", send_to_name);\n    bout.print(\"|#2Titled    : {}\\r\\n\\r\\n\", title);\n    bout.outstr(\"|#5Correct? \");\n\n    if (!bin.yesno()) {\n      return;\n    }\n\n    messagerec msg{};\n    msg.storage_type = EMAIL_STORAGE;\n\n    const auto name = a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n    qwk_inmsg(text, &msg, \"email\", name, DateTime::now());\n\n    if (msg.stored_as == 0xffffffff) {\n      return;\n    }\n\n    bout.ansic(8);\n\n    EmailData email;\n    email.title = title;\n    email.msg = &msg;\n    email.anony = 0;\n    email.user_number = un;\n    email.system_number = sy;\n    email.an = true;\n    email.set_from_user(a()->sess().user_num());\n    email.set_from_system(a()->current_net().sysnum);\n    email.forwarded_code = 0;\n    email.from_network_number = a()->net_num();\n    sendout_email(email);\n  }\n}\n\n}\n"
  },
  {
    "path": "bbs/qwk/qwk_email.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_EMAIL_H\n#define INCLUDED_BBS_QWK_QWK_EMAIL_H\n\nnamespace wwiv::bbs::qwk {\n\nvoid qwk_email_text(const char *text, char *title, char *to);\nvoid qwk_remove_email();\nvoid qwk_gather_email(qwk_state *qwk_info);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk/qwk_mail_packet.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk_mail_packet.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/save_qscan.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/qwk/qwk_email.h\"\n#include \"bbs/qwk/qwk_ui.h\"\n#include \"bbs/qwk/qwk_util.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"core/clock.h\"\n#include \"core/file.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/qscan.h\"\n#include \"sdk/qwk_config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/ansi/makeansi.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::qwk {\n\n\n// Also used in qwk1.cpp\nconst char *QWKFrom = \"\\x04\"\"0QWKFrom:\";\n\nstatic uint16_t max_msgs;\n\n// from xfer.cpp\nextern uint32_t this_date;\n\n\nstatic bool replacefile(const std::string& src, const std::string& dst) {\n  if (dst.empty()) {\n    return false;\n  }\n  return File::Copy(src, dst);\n}\n\nbool build_control_dat(const sdk::qwk_config& qwk_cfg, Clock* clock, qwk_state *qwk_info) {\n  const auto date_time = clock->Now().to_string(\"%m-%d-%Y,%H:%M:%S\"); // 'mm-dd-yyyy,hh:mm:ss'\n\n  TextFile fp(FilePath(a()->sess().dirs().qwk_directory(), \"CONTROL.DAT\"), \"wd\");\n  if (!fp) {\n    return false;\n  }\n\n  const auto system_name = sdk::qwk_system_name(qwk_cfg, a()->config()->system_name());\n  fp.WriteLine(fmt::format(\"{}.qwk\", system_name));\n  fp.WriteLine();  // System City and State\n  fp.WriteLine(a()->config()->system_phone());\n  fp.WriteLine(a()->config()->sysop_name());\n  fp.WriteLine(fmt::format(\"00000,{}\", system_name));\n  fp.WriteLine(date_time);\n  fp.WriteLine(a()->user()->name());\n  fp.WriteLine(\"\");\n  fp.WriteLine(\"0\");\n  fp.WriteLine(qwk_info->qwk_rec_num);\n  \n  const auto max_size = a()->subs().subs().size();\n  const sdk::qscan_bitset qb(a()->sess().qsc_q, max_size);\n  std::vector<std::pair<int, std::string>> subs_list;\n  for (auto cur = 0; cur < size_int(a()->usub); cur++) {\n    const auto subnum = a()->usub[cur].subnum;\n    if (qb.test(subnum)) {\n      // QWK support says this should be truncated to 10 or 13 characters however QWKE allows for\n      // 255 characters. This works fine in multimail which is the only still maintained QWK\n      //  reader that I'm aware of at this time, so we'll allow it to be the full length.\n      subs_list.emplace_back(subnum + 1, stripcolors(a()->subs().sub(subnum).name));\n    }\n  }\n  fp.WriteLine(subs_list.size());\n  \n  fp.WriteLine(\"0\");\n  fp.WriteLine(\"E-Mail\");\n\n  for (const auto& [sub_num, sub_name] : subs_list) {\n    // Write the subs in the format of \"Sub Number\\r\\nSub Name\\r\\n\"\n    fp.WriteLine(sub_num);\n    fp.WriteLine(sub_name);\n  }\n\n  fp.WriteLine(qwk_cfg.hello);\n  fp.WriteLine(qwk_cfg.news);\n  fp.WriteLine(qwk_cfg.bye);\n  return fp.Close();\n}\n\nvoid build_qwk_packet() {\n  auto save_conf = false;\n  SaveQScanPointers save_qscan;\n\n  remove_from_temp(\"*.*\", a()->sess().dirs().qwk_directory(), false);\n\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    save_conf = true;\n    tmp_disable_conf(true);\n  }\n  common::TempDisablePause disable_pause(bout);\n  bout.litebar(\"Download QWK Message Packet\");\n  bout.nl();\n\n  auto qwk_cfg = read_qwk_cfg(*a()->config());\n  max_msgs = qwk_cfg.max_msgs;\n  if (a()->user()->data.qwk_max_msgs < max_msgs && a()->user()->data.qwk_max_msgs) {\n    max_msgs = a()->user()->data.qwk_max_msgs;\n  }\n\n  if (!qwk_cfg.fu) {\n    qwk_cfg.fu = daten_t_now();\n  }\n\n  ++qwk_cfg.timesd;\n  write_qwk_cfg(*a()->config(), qwk_cfg);\n\n  write_inst(INST_LOC_QWK, a()->current_user_sub().subnum, INST_FLAGS_ONLINE);\n\n  const auto filename = FilePath(a()->sess().dirs().batch_directory(), MESSAGES_DAT);\n  const auto filemode = File::modeReadWrite | File::modeBinary | File::modeCreateFile;\n  qwk_state qwk_info{};\n  qwk_info.file = std::make_unique<DataFile<qwk_record>>(filename, filemode);\n\n  if (!qwk_info.file->ok()) {\n    bout.outstr(\"Open error\");\n    sysoplog(\"Couldn't open MESSAGES.DAT\");\n    return;\n  }\n\n  // Required header at the start of MESSAGES.DAT\n  qwk_record header{};\n  memcpy(&header, \"Produced by Qmail...Copyright (c) 1987 by Sparkware.  All Rights Reserved (For Compatibility with Qmail)                        \", 128);\n  qwk_info.file->Write(&header);\n\n  // Logical record number\n  qwk_info.qwk_rec_num = 1;\n  qwk_info.qwk_rec_pos = 2;\n\n  qwk_info.abort = false;\n\n  if (!a()->user()->data.qwk_dont_scan_mail && !qwk_info.abort) {\n    qwk_gather_email(&qwk_info);\n  }\n\n  bin.checka(&qwk_info.abort);\n\n  bout.cls();\n  if (!qwk_info.abort) {\n    bout.print(\"|#7\\xDA{}'\\xC2{}'\\xC2{}'\\xC2{}\\xBF\\r\\n\", std::string(4, '\\xC4'),\n               std::string(52, '\\xC4'), std::string(9, '\\xC4'), std::string(8, '\\xC4'));\n  }\n\n  bin.checka(&qwk_info.abort);\n\n  if (!qwk_info.abort) {\n    bout.print(\"|#7\\xB3|#2Sub |#7\\xB3|#3Sub Name{}|#7\\xB3|#8Total    |#7\\xB3|#5New     |#7\\xB3\\r\\n\", std::string(44, ' '));\n  }\n\n  bin.checka(&qwk_info.abort);\n\n  if (!qwk_info.abort) {\n    bout.print(\"|#7\\xC3{}\\xC5{}\\xC5{}\\xC5{}\\xB4\\r\\n\", std::string(4, '\\xC4'),\n               std::string(52, '\\xC4'), std::string(9, '\\xC4'), std::string(8, '\\xC4'));\n  }\n\n  bool msgs_ok = true;\n  for (uint16_t i = 0; i < a()->usub.size() && !a()->sess().hangup() && !qwk_info.abort && msgs_ok; i++) {\n    msgs_ok = max_msgs ? qwk_info.qwk_rec_num <= max_msgs : true;\n    if (a()->sess().qsc_q[a()->usub[i].subnum / 32] & (1L << (a()->usub[i].subnum % 32))) {\n      qwk_gather_sub(i, &qwk_info);\n    }\n  }\n\n  bout.print(\"|#7\\xC3{}\\xC5{}\\xC5{}\\xC5{}\\xB4\\r\\n\", std::string(4, '\\xC4'), std::string(52, '\\xC4'),\n             std::string(9, '\\xC4'), std::string(8, '\\xC4'));\n  bout.nl(2);\n\n  if (qwk_info.abort) {\n    bout.ansic(1);\n    bout.outstr(\"|#5Abort everything? |#2(|#1NO|#2=Download what I have gathered) ? \");\n    if (!bin.yesno()) {\n      qwk_info.abort = false;\n    }\n  }\n\n  qwk_info.file.reset(nullptr);\n  qwk_info.index.reset(nullptr);\n  qwk_info.personal.reset(nullptr);\n  qwk_info.zero.reset(nullptr);\n\n  if (!qwk_info.abort) {\n    SystemClock clock{};\n    build_control_dat(qwk_cfg, &clock, &qwk_info);\n  }\n  if (!qwk_info.abort) {\n    finish_qwk(&qwk_info);\n  }\n\n  // Restore on a()->sess().hangup() too, someone might have hungup in the middle of building the list\n  if (qwk_info.abort || a()->user()->data.qwk_dontsetnscan || a()->sess().hangup()) {\n    save_qscan.restore();\n    if (qwk_info.abort) {\n      sysoplog(\"Aborted\");\n    }\n  }\n  if (a()->user()->data.qwk_delete_mail && !qwk_info.abort) {\n    qwk_remove_email();  // Delete email\n  }\n\n  if (save_conf) {\n    tmp_disable_conf(false);\n  }\n}\n\n#define qwk_iscan(x) (iscan1(a()->usub[x].subnum))\n\nvoid qwk_gather_sub(uint16_t bn, qwk_state* qwk_info) {\n\n  const auto sn = a()->usub[bn].subnum;\n\n  if (a()->sess().hangup() || (sn < 0)) {\n    return;\n  }\n\n  auto qscnptrx = a()->sess().qsc_p[sn];\n  const auto sd = WWIVReadLastRead(sn);\n\n  if (!sd || sd > qscnptrx) {\n    const auto os = a()->current_user_sub_num();\n    a()->set_current_user_sub_num(bn);\n    int i;\n\n    // Get total amount of messages in base\n    if (!qwk_iscan(a()->current_user_sub_num())) {\n      return;\n    }\n\n    qscnptrx = a()->sess().qsc_p[sn];\n\n    // Find out what message number we are on\n    int amount = 0;\n    {\n      // Pre-open the sub to speed up access.\n      open_sub(false);\n      auto at_exit = finally([]{ close_sub();});\n      const auto total = a()->GetNumMessagesInCurrentMessageArea();\n      for (i = total; i > 1 && get_post(i - 1)->qscan > qscnptrx; i--) {\n        if ((++amount % 1000) == 0) {\n          bout.print(\"\\r|#9Finding Last Read: (|#2{} |#9/ |#1{}|#9)|#0\", amount, total);\n        }\n      }\n    }\n    bout.clear_whole_line();      \n\n    char thissub[81];\n    to_char_array_trim(thissub, a()->current_sub().name);\n    thissub[60] = 0;\n    const auto subinfo = fmt::sprintf(\"|#7\\xB3|#9%-4d|#7\\xB3|#1%-52s|#7\\xB3 |#2%-8d|#7\\xB3|#3%-8d|#7\\xB3\",\n                                      bn + 1, thissub, a()->GetNumMessagesInCurrentMessageArea(),\n                                      a()->GetNumMessagesInCurrentMessageArea() - i + 1);\n    bout.outstr(subinfo);\n    bout.nl();\n\n    bin.checka(&qwk_info->abort);\n\n    {\n      // Open the sub first, so that we don't open/close it repeatedly\n      // in get_post.\n      open_sub(false);\n      auto at_exit = finally([] { close_sub(); });\n\n      if (a()->GetNumMessagesInCurrentMessageArea() > 0 &&\n          i <= a()->GetNumMessagesInCurrentMessageArea() && !qwk_info->abort) {\n        if (get_post(i)->qscan > a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()]) {\n          qwk_start_read(i, qwk_info); // read messsage\n        }\n      }\n    }\n\n    const auto status = a()->status_manager()->get_status();\n    a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()] = status->qscanptr() - 1;\n    a()->set_current_user_sub_num(os);\n  } \n  bout.ansic(0);\n}\n\nvoid qwk_start_read(int msgnum, qwk_state *qwk_info) {\n  a()->sess().clear_irt();\n\n  if (a()->sess().GetCurrentReadMessageArea() < 0) {\n    return;\n  }\n  // Used to be inside do loop\n  if (!a()->current_sub().nets.empty()) {\n    set_net_num(a()->current_sub().nets[0].net_num);\n  } else {\n    set_net_num(0);\n  }\n\n  auto amount = 1;\n  auto done = false;\n  const auto total = a()->GetNumMessagesInCurrentMessageArea();\n  do {\n    if (msgnum > 0 && msgnum <= a()->GetNumMessagesInCurrentMessageArea()) {\n      make_pre_qwk(msgnum, qwk_info);\n    }\n    ++msgnum;\n    if (msgnum > total) {\n      done = true;\n    }\n    if (a()->user()->data.qwk_max_msgs_per_sub ? amount >\n        a()->user()->data.qwk_max_msgs_per_sub : 0) {\n      done = true;\n    }\n    if (max_msgs ? qwk_info->qwk_rec_num > max_msgs : 0) {\n      done = true;\n    }\n    ++amount;\n    bin.checka(&qwk_info->abort);\n    if ((amount % 100) == 0) {\n      bout.print(\"\\r|#9Packing Message(|#2{} |#9/ |#1{}|#9)|#0\", amount, total);\n    }\n  } while (!done && !a()->sess().hangup() && !qwk_info->abort);\n  bout.clear_whole_line();\n}\n\nvoid make_pre_qwk(int msgnum, qwk_state *qwk_info) {\n  auto* p = get_post(msgnum);\n  if ((p->status & (status_unvalidated | status_delete)) && !lcs()) {\n    return;\n  }\n\n  const auto nn = a()->net_num();\n  if (p->status & status_post_new_net) {\n    set_net_num(p->network.network_msg.net_number);\n  }\n\n  put_in_qwk(p, a()->current_sub().filename.c_str(), msgnum, qwk_info);\n  if (nn != a()->net_num()) {\n    set_net_num(nn);\n  }\n\n  a()->user()->messages_read(a()->user()->messages_read() + 1);\n  a()->SetNumMessagesReadThisLogon(a()->GetNumMessagesReadThisLogon() + 1);\n\n  if (p->qscan >\n      a()->sess()\n          .qsc_p[a()->sess().GetCurrentReadMessageArea()]) { // Update qscan pointer right here\n    a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()] = p->qscan; // And here\n  }\n}\n\n\nstatic void insert_after_routing(std::string& text, const std::string& text2insert) {\n  const auto text_to_insert_nc = StrCat(stripcolors(text2insert), \"\\xE3\\xE3\");\n\n  size_t pos = 0;\n  const auto len = text.size();\n  while (pos < len && text[pos] != 0) {\n    if (text[pos] == 4 && text[pos + 1] == '0') {\n      while (pos < len && text[pos] != '\\xE3') {\n        ++pos;\n      }\n\n      if (text[pos] == '\\xE3') {\n        ++pos;\n      }\n    } else if (pos < len) {\n      text.insert(pos, text_to_insert_nc);\n      return;\n    }\n  }\n}\n\n// Give us 3000 extra bytes to play with in the message text\nstatic constexpr int PAD_SPACE = 3000;\n\n// Takes text, deletes all ascii '10' and converts '13' to '227' ()\n// And does other conversions as specified\n// TODO(rushfan): This whole thing needs to be redone.\nstatic std::string make_qwk_ready(const std::string& text, const std::string& address) {\n  std::string::size_type pos = 0;\n\n  std::string temp;\n  temp.reserve(text.size() + PAD_SPACE + 1);\n\n  while (pos < text.size()) {\n    const auto x = static_cast<unsigned char>(text[pos]);\n    const auto xo = text[pos];\n    if (x == 0) {\n      break;\n    }\n    if (x == 13) {\n      temp.push_back('\\xE3');\n      ++pos;\n    } else if (x == 10 || x < 3) {\n      // Strip out Newlines, NULLS, 1's and 2's\n      ++pos;\n    } else if (a()->user()->data.qwk_remove_color && x == 3) {\n      pos += 2;\n    } else if (a()->user()->data.qwk_convert_color && x == 3) {\n      const auto save_curatr = bout.curatr();\n      bout.curatr(255);\n\n      const auto ansi_string = wwiv::sdk::ansi::makeansi(text[pos + 1] - '0', bout.curatr());\n      temp.append(ansi_string);\n\n      pos += 2;\n      bout.setc(save_curatr);\n    } else if (a()->user()->data.qwk_keep_routing == false && x == 4 && text[pos + 1] == '0') {\n      if (text[pos + 1] == 0) {\n        ++pos;\n      } else { \n        while (text[pos] != '\\xE3' && text[pos] != '\\r' && pos < text.size() && text[pos] != 0) {\n          ++pos;\n        }\n      }\n      ++pos;\n      if (pos < text.size() && text[pos] == '\\n') {\n        ++pos;\n      }\n    } else if (x == 4 && text[pos + 1] != '0') {\n      pos += 2;\n    } else {\n      temp.push_back(xo);\n      ++pos;\n    }\n  }\n\n  // Only add address if it does not yet exist\n  if (temp.find(\"QWKFrom:\") != std::string::npos) {\n    // Don't search for diamond or number, just text after that\n    insert_after_routing(temp, address);\n  }\n\n  temp.shrink_to_fit();\n  return temp;\n}\n\nstatic void qwk_remove_null(char *memory, int size) {\n  auto pos = 0;\n\n  while (pos < size) {\n    if (memory[pos] == 0) {\n      memory[pos] = ' ';\n    }\n    ++pos;\n  }\n}\n\nvoid put_in_qwk(postrec *m1, const char *fn, int msgnum, qwk_state *qwk_info) {\n  if (m1->status & (status_unvalidated | status_delete)) {\n    if (!lcs()) {\n      return;\n    }\n  }\n  memset(&qwk_info->qwk_rec, ' ', sizeof(qwk_info->qwk_rec));\n\n  auto o = read_type2_message(&m1->msg, m1->anony & 0x0f, true, fn, m1->ownersys, m1->owneruser);\n  if (!o) {\n    bout.outstr(\"File not found.\");\n    bout.nl();\n    return;\n  }\n  auto& m = o.value();\n  int cur = 0;\n  auto len = m.message_text.length();\n  if (len <= 0) {\n    std::cout << \"we have no text for this message.\" << std::endl;\n    return;\n  }\n  auto ss = m.message_text;\n  auto n = m.from_user_name;\n  auto d = m.date;\n\n  auto qwk_address = StrCat(QWKFrom, n);  // Copy wwivnet address to qwk_address\n  if (qwk_address.find('@') != std::string::npos) {\n    qwk_address.append(fmt::format(\"@{}\", m1->ownersys));\n  }\n\n  // Took the annonomouse stuff out right here\n  if (!qwk_info->in_email) {\n    // Maybe m.to_user_name is valid here?\n    if (!m.to_user_name.empty()) {\n    strncpy(qwk_info->qwk_rec.to, m.to_user_name.c_str(), 25);\n    } else {\n      memcpy(qwk_info->qwk_rec.to, \"ALL\", 3);\n    }\n  } else {\n    auto temp = ToStringUpperCase(a()->user()->name());\n    strncpy(qwk_info->qwk_rec.to, temp.c_str(), 25);\n  }\n  auto temp_from = ToStringUpperCase(stripcolors(n));\n  strncpy(qwk_info->qwk_rec.from, temp_from.c_str(), 25);\n\n  auto dt = DateTime::from_daten(m1->daten);\n  auto date = dt.to_string(\"%m-%d-%y\");\n  // to_char_array uses strncpy_safe which expects buffer to be big enough for\n  // a trailing 0.  Use memcpy instead.\n  memcpy(qwk_info->qwk_rec.date, date.c_str(), sizeof(qwk_info->qwk_rec.date));\n\n  ss = make_qwk_ready(ss, qwk_address);\n  // Update length since we don't do it in make_qwk_ready anymore.\n  len = ss.length();\n  auto amount_blocks = static_cast<int>(len / sizeof(qwk_info->qwk_rec) + 2);\n\n  // Save Qwk Record\n  sprintf(qwk_info->qwk_rec.amount_blocks, \"%d\", amount_blocks);\n  sprintf(qwk_info->qwk_rec.msgnum, \"%d\", msgnum);\n\n  if (!qwk_info->in_email) {\n    strncpy(qwk_info->qwk_rec.subject, stripcolors(m1->title), 25);\n  } else {\n    strncpy(qwk_info->qwk_rec.subject,qwk_info->email_title, 25);\n  }\n\n  qwk_remove_null(reinterpret_cast<char*>(&qwk_info->qwk_rec), 123);\n  if (qwk_info->in_email) {\n    // email conference is always zero.\n    qwk_info->qwk_rec.conf_num = 0;\n  } else {\n    qwk_info->qwk_rec.conf_num = a()->current_user_sub().subnum + 1;\n  }\n  qwk_info->qwk_rec.logical_num = qwk_info->qwk_rec_num;\n\n  if (!qwk_info->file->Write(&qwk_info->qwk_rec)) {\n    qwk_info->abort = true; // Must be out of disk space\n    bout.outstr(\"Write error\");\n    bout.pausescr();\n  }\n\n  // Save Qwk NDX\n  qwk_info->qwk_ndx.pos = static_cast<float>(qwk_info->qwk_rec_pos);\n  float msbin = 0.0f;\n  _fieeetomsbin(&qwk_info->qwk_ndx.pos, &msbin);\n  qwk_info->qwk_ndx.pos = msbin;\n  qwk_info->qwk_ndx.nouse = 0;\n\n  if (!qwk_info->in_email) { // Only if currently doing messages...\n    // Create new index if it hasn't been already\n    if (a()->current_user_sub_num() != static_cast<uint16_t>(qwk_info->cursub) || !qwk_info->index) {\n      qwk_info->cursub = a()->current_user_sub_num();\n      const auto filename =\n          fmt::sprintf(\"%s%03d.NDX\", a()->sess().dirs().qwk_directory().string(), a()->current_user_sub().subnum + 1);\n      const auto index_filemode = File::modeReadWrite | File::modeAppend | File::modeBinary | File::modeCreateFile;\n      qwk_info->index = std::make_unique<DataFile<qwk_index>>(filename, index_filemode);\n    }\n\n    qwk_info->index->Write(&qwk_info->qwk_ndx);\n  } else { // Write to email indexes\n    qwk_info->zero->Write(&qwk_info->qwk_ndx);\n    qwk_info->personal->Write(&qwk_info->qwk_ndx);\n  }\n\n  // Setup next NDX position\n  qwk_info->qwk_rec_pos += static_cast<uint16_t>(amount_blocks);\n\n  int cur_block = 2;\n  while (cur_block <= amount_blocks && !a()->sess().hangup()) {\n    size_t this_pos;\n    memset(&qwk_info->qwk_rec, ' ', sizeof(qwk_info->qwk_rec));\n    this_pos = (cur_block - 2) * sizeof(qwk_info->qwk_rec);\n\n    if (this_pos < len) {\n      size_t size = (this_pos + sizeof(qwk_info->qwk_rec) > static_cast<size_t>(len)) ? (len - this_pos - 1) : sizeof(qwk_info->qwk_rec);\n      memmove(&qwk_info->qwk_rec, ss.data() + cur + this_pos, size);\n    }\n    // Save this block\n    qwk_info->file->Write(&qwk_info->qwk_rec);\n\n    this_pos += sizeof(qwk_info->qwk_rec);\n    ++cur_block;\n  }\n  // Global variable on total amount of records saved\n  ++qwk_info->qwk_rec_num;\n}\n\nstatic void qwk_send_file(const std::string& fn, bool *sent, bool *abort) {\n  // TODO(rushfan): Should this just call send_file from sr.cpp?\n  *sent = false;\n  *abort = false;\n\n  int protocol;\n  if (a()->user()->data.qwk_protocol <= 1) {\n    protocol = get_protocol(xfertype::xf_down_temp);\n  } else {\n    protocol = a()->user()->data.qwk_protocol;\n  }\n  switch (protocol) {\n  case -1:\n    *abort = true;\n\n    break;\n  case 0:\n  case WWIV_INTERNAL_PROT_ASCII:\n    break;\n\n  case WWIV_INTERNAL_PROT_XMODEM:\n  case WWIV_INTERNAL_PROT_XMODEMCRC:\n  case WWIV_INTERNAL_PROT_YMODEM:\n  case WWIV_INTERNAL_PROT_ZMODEM: {\n    double percent = 0.0;\n    maybe_internal(fn, sent, &percent, true, protocol);\n  } break;\n\n  default: {\n    const auto exit_code = extern_prot(protocol - WWIV_NUM_INTERNAL_PROTOCOLS, fn, 1);\n    *abort = false;\n    if (exit_code == a()->externs[protocol - WWIV_NUM_INTERNAL_PROTOCOLS].ok1) {\n      *sent = true;\n    }\n  } break;\n  }\n}\n\n\nvoid finish_qwk(qwk_state *qwk_info) {\n  auto sent = false;\n  long numbytes;\n  auto done = false;\n  int archiver;\n\n\n  if (!a()->user()->data.qwk_dontscanfiles) {\n    qwk_nscan();\n  }\n\n  auto qwk_cfg = read_qwk_cfg(*a()->config());\n  if (!a()->user()->data.qwk_leave_bulletin) {\n    bout.outstr(\"Grabbing hello/news/goodbye text files...\");\n\n    if (!qwk_cfg.hello.empty()) {\n      auto parem1 = FilePath(a()->config()->gfilesdir(), qwk_cfg.hello);\n      auto parem2 = FilePath(a()->sess().dirs().qwk_directory(), qwk_cfg.hello);\n      File::Copy(parem1, parem2);\n    }\n\n    if (!qwk_cfg.news.empty()) {\n      auto parem1 = FilePath(a()->config()->gfilesdir(), qwk_cfg.news);\n      auto parem2 = FilePath(a()->sess().dirs().qwk_directory(), qwk_cfg.news);\n      File::Copy(parem1, parem2);\n    }\n\n    if (!qwk_cfg.bye.empty()) {\n      auto parem1 = FilePath(a()->config()->gfilesdir(), qwk_cfg.bye);\n      auto parem2 = FilePath(a()->sess().dirs().qwk_directory(), qwk_cfg.bye);\n    }\n\n    for (const auto& b : qwk_cfg.bulletins) {\n      if (!File::Exists(b.path)) {\n        // Don't have file_daten anymore\n        continue;\n      }\n\n      // If we want to only copy if bulletin is newer than the users laston date:\n      // if(file_daten(qwk_cfg.blt[x]) > date_to_daten(a()->user()->last_daten()))\n      auto parem2 = FilePath(a()->sess().dirs().qwk_directory(), b.name);\n      File::Copy(b.path, parem2);\n    }\n  }\n\n  auto qwkname = StrCat(qwk_system_name(qwk_cfg, a()->config()->system_name()), \".qwk\");\n\n  if (!a()->user()->data.qwk_archive ||\n      !a()->arcs[a()->user()->data.qwk_archive - 1].extension[0]) {\n    archiver = select_qwk_archiver(qwk_info->abort, false) - 1;\n  } else {\n    archiver = a()->user()->data.qwk_archive - 1;\n  }\n\n  std::string qwk_file_to_send;\n  if (!qwk_info->abort) {\n    auto parem1 = FilePath(a()->sess().dirs().qwk_directory(), qwkname);\n    auto parem2 = FilePath(a()->sess().dirs().qwk_directory(), \"*.*\");\n    wwiv::bbs::CommandLine cl(a()->arcs[archiver].arca);\n    cl.args(parem1.string(), parem2.string());\n    ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_ARCH_A));\n\n    qwk_file_to_send = FilePath(a()->sess().dirs().qwk_directory(), qwkname).string();\n\n    File qwk_file_to_send_file(qwk_file_to_send);\n    if (!File::Exists(qwk_file_to_send)){\n      bout.outstr(\"No such file.\");\n      bout.nl();\n      qwk_info->abort = true;\n      return;\n    }\n    numbytes = qwk_file_to_send_file.length();\n\n    if (numbytes == 0L) {\n      bout.outstr(\"File has nothing in it.\");\n      qwk_info->abort = true;\n      return;\n    }\n  }\n\n  if (a()->sess().incom()) {\n    while (!done && !qwk_info->abort && !a()->sess().hangup()) {\n      bool abort = false;\n      qwk_send_file(qwk_file_to_send, &sent, &abort);\n      if (sent) {\n        done = true;\n      } else {\n        bout.nl();\n        bout.outstr(\"|#6Packet was not successful... \");\n        bout.outstr(\"|#5Try transfer again?\");\n\n        if (!bin.noyes()) {\n          done = true;\n          abort = true;\n          qwk_info->abort = true;\n        } else {\n          abort = false;\n        }\n\n      }\n      if (abort) {\n        qwk_info->abort = true;\n      }\n    }\n  } else while (!done && !a()->sess().hangup() && !qwk_info->abort) {\n    bout.outstr(\"|#5Move to what dir? \");\n    bout.mpl(60);\n    auto new_dir = StringTrim(bin.input_path(60));\n    if (new_dir.empty()) {\n      continue;\n    }\n\n    const auto nfile = FilePath(new_dir, qwkname);\n\n    if (File::Exists(nfile)) {\n      bout.outstr(\"|#5File Exists. Would you like to overrite it?\");\n      if (bin.yesno()) {\n        File::Remove(nfile);\n      }\n    }\n\n    auto ofile = FilePath(a()->sess().dirs().qwk_directory(), qwkname);\n    if (!replacefile(ofile.string(), nfile.string())) {\n      bout.outstr(\"|#6Unable to copy file\\r\\n|#5Would you like to try again?\");\n      if (!bin.noyes()) {\n        qwk_info->abort = true;\n        done = true;\n      }\n    } else {\n      done = true;\n    }\n  }\n}\n\n}\n"
  },
  {
    "path": "bbs/qwk/qwk_mail_packet.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_MAIL_PACKET_H\n#define INCLUDED_BBS_QWK_QWK_MAIL_PACKET_H\n\n#include \"bbs/qwk/qwk_struct.h\"\n#include <cstdint>\n\n\nstruct postrec;\n\nnamespace wwiv::bbs::qwk {\n\n\nvoid build_qwk_packet();\nvoid qwk_gather_sub(uint16_t bn, qwk_state *qwk_info);\nvoid qwk_start_read(int msgnum, qwk_state *qwk_info);\nvoid make_pre_qwk(int msgnum, qwk_state *qwk_info);\nvoid put_in_qwk(postrec *m1, const char *fn, int msgnum, qwk_state *qwk_info);\nvoid qwk_nscan();\nvoid finish_qwk(qwk_state *qwk_info);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk/qwk_reply.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk_reply.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/application.h\"\n#include \"bbs/archivers.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/sublist.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/qwk/qwk_email.h\"\n#include \"bbs/qwk/qwk_text.h\"\n#include \"bbs/qwk/qwk_ui.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/wwivport.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/names.h\"\n#include \"sdk/qwk_config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/net/networks.h\"\n\n#include <chrono>\n#include <optional>\n#include <sstream>\n\nusing std::chrono::milliseconds;\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\n\n#define qwk_iscan_literal(x) (iscan1(x))\n\nnamespace wwiv::bbs::qwk {\n\nstatic void qwk_receive_file(const std::string& fn, bool* received, int prot_num) {\n  if (prot_num <= 1 || prot_num == 5) {\n    prot_num = get_protocol(xfertype::xf_up_temp);\n  }\n\n  switch (prot_num) {\n  case -1:\n  case 0:\n  case WWIV_INTERNAL_PROT_ASCII:\n  case WWIV_INTERNAL_PROT_BATCH:\n    *received = false;\n    break;\n  case WWIV_INTERNAL_PROT_XMODEM:\n  case WWIV_INTERNAL_PROT_XMODEMCRC:\n  case WWIV_INTERNAL_PROT_YMODEM:\n  case WWIV_INTERNAL_PROT_ZMODEM:\n    maybe_internal(fn, received, nullptr, false, prot_num);\n    break;\n  default:\n    if (a()->sess().incom()) {\n      extern_prot(prot_num - WWIV_NUM_INTERNAL_PROTOCOLS, fn, 0);\n      *received = File::Exists(fn);\n    }\n    break;\n  }\n}\n\nstatic std::filesystem::path ready_reply_packet(const std::string& packet_name, const std::string& msg_name) {\n  const auto archiver = match_archiver(a()->arcs, packet_name).value_or(a()->arcs[0]);\n  wwiv::bbs::CommandLine cl(archiver.arce);\n  cl.args(packet_name, msg_name);\n\n  ExecuteExternalProgram(cl, EFLAG_QWK_DIR);\n\n  const auto mask = FilePath(a()->sess().dirs().qwk_directory(), msg_name);\n  FindFiles ff(mask, FindFiles::FindFilesType::files);\n  if (ff.empty()) {\n    return FilePath(a()->sess().dirs().qwk_directory(), msg_name);\n  }\n  const auto fn = *ff.begin();\n  return FilePath(a()->sess().dirs().qwk_directory(), fn.name); \n}\n\nstatic void qwk_post_text(std::string text, const std::string& to, const std::string& title,\n                          int sub) {\n  messagerec m{};\n  postrec p{};\n\n  int dm, done = 0, pass = 0;\n  slrec ss{};\n\n  while (!done && !a()->sess().hangup()) {\n    if (pass > 0) {\n      auto done5 = false;\n\n      while (!done5 && !a()->sess().hangup()) {\n        bout.nl();\n        bout.outstr(\"Then which sub?  ?=List  Q=Don't Post :\");\n        auto substr = bin.input(3);\n\n        StringTrim(&substr);\n        if (substr.empty()) {\n          continue;\n        }\n        if (substr.front() == 'Q') {\n          return;\n        }\n        const auto sub_num = to_number<int>(substr);\n        if (substr[0] == '?' || sub_num == 0) {\n          SubList();\n          continue;\n        }\n        sub = a()->usub[sub_num - 1].subnum;\n        done5 = true;\n      }\n    }\n\n    if (sub >= size_int(a()->usub) || sub < 0) {\n      bout.ansic(5);\n      bout.outstr(\"Sub out of range\");\n\n      ++pass;\n      continue;\n    }\n    a()->set_current_user_sub_num(static_cast<uint16_t>(sub));\n\n    // Busy files... allow to retry\n    while (!a()->sess().hangup()) {\n      if (!qwk_iscan_literal(a()->current_user_sub_num())) {\n        bout.nl();\n        bout.outstr(\"MSG file is busy on another instance, try again?\");\n        if (!bin.noyes()) {\n          ++pass;\n          continue;\n        }\n      } else {\n        break;\n      }\n    }\n\n    if (a()->sess().GetCurrentReadMessageArea() < 0) {\n      bout.ansic(5);\n      bout.outstr(\"Sub out of range\");\n\n      ++pass;\n      continue;\n    }\n\n    ss = a()->config()->sl(a()->sess().effective_sl());\n\n    int xa = 0;\n    // User is restricted from posting\n    if (a()->user()->restrict_post() || a()->user()->data.posttoday >= ss.posts) {\n      bout.nl();\n      bout.outstr(\"Too many messages posted today.\");\n      bout.nl();\n\n      ++pass;\n      continue;\n    }\n\n    // User doesn't have enough sl to post on sub\n    if (!check_acs(a()->current_sub().post_acs)) {\n      bout.nl();\n      bout.outstr(\"You can't post here.\");\n      bout.nl();\n      ++pass;\n      continue;\n    }\n\n    m.storage_type = static_cast<uint8_t>(a()->current_sub().storage_type);\n\n    if (!a()->current_sub().nets.empty()) {\n      xa &= (anony_real_name);\n\n      if (a()->user()->restrict_net()) {\n        bout.nl();\n        bout.outstr(\"You can't post on networked sub-boards.\");\n        bout.nl();\n        ++pass;\n        continue;\n      }\n    }\n\n    bout.cls();\n    bout.outstr(\"|#5Posting New Message.\\r\\n\\n\");\n    bout.print(\"|#9Title      : |#2{}\\r\\n\", title);\n    bout.print(\"|#9To         : |#2{}\\r\\n\", to.empty() ? \"All\" : to);\n    bout.print(\"|#9Area       : |#2{}\\r\\n\", stripcolors(a()->current_sub().name));\n\n    if (!a()->current_sub().nets.empty()) {\n      bout.outstr(\"|#9On Networks: |#5\");\n      for (const auto& xnp : a()->current_sub().nets) {\n        bout.print(\"{} \", a()->nets()[xnp.net_num].name);\n      }\n      bout.nl();\n    }\n\n    bout.nl();\n    bout.outstr(\"|#5Correct? \");\n\n    if (bin.noyes()) {\n      done = true;\n    } else {\n      ++pass;\n    }\n  }\n  bout.nl();\n\n  const auto user_name =\n      a()->current_sub().anony & anony_real_name\n          ? properize(a()->user()->real_name())\n          : a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n\n  if (!to.empty() && !iequals(to, \"ALL\")) {\n    const auto buf = fmt::sprintf(\"%c0FidoAddr: %s\\r\\n\", CD, to);\n    text = StrCat(buf, text);\n  }\n  qwk_inmsg(text.c_str(), &m, a()->current_sub().filename, user_name, DateTime::now());\n\n  if (m.stored_as != 0xffffffff) {\n    while (!a()->sess().hangup()) {\n      const int f = qwk_iscan_literal(a()->sess().GetCurrentReadMessageArea());\n\n      if (f == -1) {\n        bout.nl();\n        bout.outstr(\"MSG file is busy on another instance, try again?\");\n        if (!bin.noyes()) {\n          return;\n        }\n      } else {\n        break;\n      }\n    }\n\n    // Anonymous\n    uint8_t an = 0;\n    if (an) {\n      bout.outstr(\"|#5Anonymous?\");\n      an = bin.yesno() ? 1 : 0;\n    }\n    bout.nl();\n\n    to_char_array(p.title, title);\n    p.anony = an;\n    p.msg = m;\n    p.ownersys = 0;\n    p.owneruser = static_cast<uint16_t>(a()->sess().user_num());\n    {\n      a()->status_manager()->Run([&](Status& s) { p.qscan = s.next_qscanptr(); });\n    }\n    p.daten = daten_t_now();\n    if (a()->user()->restrict_validate()) {\n      p.status = status_unvalidated;\n    } else {\n      p.status = 0;\n    }\n\n    open_sub(true);\n\n    if (!a()->current_sub().nets.empty() && a()->current_sub().anony & anony_val_net &&\n        (!lcs() || !a()->sess().irt().empty())) {\n      p.status |= status_pending_net;\n      dm = 1;\n\n      for (auto i = a()->GetNumMessagesInCurrentMessageArea();\n           (i >= 1) && (i > (a()->GetNumMessagesInCurrentMessageArea() - 28)); i--) {\n        if (get_post(i)->status & status_pending_net) {\n          dm = 0;\n          break;\n        }\n      }\n      if (dm) {\n        ssm(1) << \"Unvalidated net posts on \" << a()->current_sub().name << \".\";\n      }\n    }\n\n    if (a()->GetNumMessagesInCurrentMessageArea() >= a()->current_sub().maxmsgs) {\n      int i = 1;\n      dm = 0;\n      while (dm == 0 && i <= a()->GetNumMessagesInCurrentMessageArea() && !a()->sess().hangup()) {\n        if ((get_post(i)->status & status_no_delete) == 0) {\n          dm = i;\n        }\n        ++i;\n      }\n      if (dm == 0) {\n        dm = 1;\n      }\n      delete_message(dm);\n    }\n\n    add_post(&p);\n\n    ++a()->user()->data.msgpost;\n    ++a()->user()->data.posttoday;\n\n    a()->status_manager()->Run([](Status& s) {\n      s.IncrementNumLocalPosts();\n      s.increment_msgs_today();\n    });\n\n    close_sub();\n\n    sysoplog(fmt::format(\"+ '{}' posted on '{}'\", p.title, a()->current_sub().name));\n\n    if (!a()->current_sub().nets.empty()) {\n      ++a()->user()->data.postnet;\n      if (!(p.status & status_pending_net)) {\n        send_net_post(&p, a()->current_sub());\n      }\n    }\n  }\n}\n\n\nstatic void process_reply_dat(const std::string& name) {\n  qwk_record qwk{};\n  int curpos = 0;\n\n  DataFile<qwk_record> file(name, File::modeReadOnly| File::modeBinary);\n  if (!file) {\n    bout.outstr(\"|#6Can't open packet.\");\n    bout.pausescr();\n    return;\n  }\n  file.Read(curpos++, &qwk);\n  // Should check to make sure first block contains our bbs id\n\n  bout.cls();\n\n  while (!a()->sess().hangup()) {\n    auto to_email = false;\n    if (!file.Read(curpos++, &qwk)) {\n      return;\n    }\n    char blocks[7];\n    char to[201];\n    char title[26];\n    char tosub[8];\n\n    strncpy(blocks, qwk.amount_blocks, 6);\n    blocks[6] = 0;\n\n    strncpy(tosub, qwk.msgnum, 7);\n    tosub[7] = 0;\n\n    strncpy(title, qwk.subject, 25);\n    title[25] = 0;\n\n    strncpy(to, qwk.to, 25);\n    to[25] = 0;\n    strupr(to);\n    StringTrim(to);\n\n    // If in sub 0 or not public, possibly route into email\n    if (to_number<int>(tosub) == 0) {\n      to_email = true;\n    } else if (qwk.status != ' ' && qwk.status != '-') { // if not public\n      bout.cls();\n      bout.print(\"|#9Message '|#2{}|#9' is marked |#3PRIVATE\\r\\n\", title);\n      bout.printf(\"|#9It is addressed to |#2%s\", to);\n      bout.nl(2);\n      bout.outstr(\"|#5Route into E-Mail? \");\n      if (bin.noyes()) {\n        to_email = true;\n      }\n    }\n\n    const auto num_text_blocks = to_number<int>(blocks) - 1;\n\n    file.Seek(curpos);\n    const auto qwk_text_len = sizeof(qwk_record) * num_text_blocks;\n    std::string raw_text;\n    raw_text.resize(qwk_text_len);\n    file.file().Read(&raw_text[0], qwk_text_len);\n\n    const auto text = make_text_ready(raw_text);\n    if (text.empty()) {\n      curpos += num_text_blocks;\n      continue;\n    }\n\n    if (to_email) {\n      auto to_from_msg_opt = get_qwk_from_message(text);\n      if (to_from_msg_opt.has_value()) {\n        bout.nl();\n        bout.printf(\"|#11|#9) |#2%s\", to);\n        bout.nl();\n        bout.printf(\"|#12|#9) |#2%s\", to_from_msg_opt.value());\n        bout.nl(2);\n\n        bout.outstr(\"|#5Which address is correct? \");\n        const int x = onek(\"12\", true);\n\n        if (x == '2') {\n          to_char_array(to, to_from_msg_opt.value());\n        }\n      }\n    }\n\n    if (to_email) {\n      qwk_email_text(text.c_str(), title, to);\n    } else if (File::freespace_for_path(a()->config()->msgsdir()) < 10) {\n      // Not enough disk space\n      bout.nl();\n      bout.outstr(\"Sorry, not enough disk space left.\");\n      bout.pausescr();\n    } else {\n      qwk_post_text(text, to, title, to_number<int16_t>(tosub) - 1);\n    }\n    curpos += num_text_blocks;\n  }\n}\n\n\nvoid upload_reply_packet() {\n  bool rec = true;\n  int save_conf = 0;\n  auto qwk_cfg = read_qwk_cfg(*a()->config());\n\n  if (!qwk_cfg.fu) {\n    qwk_cfg.fu = daten_t_now();\n  }\n\n  ++qwk_cfg.timesu;\n  write_qwk_cfg(*a()->config(), qwk_cfg);\n\n  const auto save_sub = a()->current_user_sub_num();\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    save_conf = 1;\n    tmp_disable_conf(true);\n  }\n\n  const auto rep_name = StrCat(qwk_system_name(qwk_cfg, a()->config()->system_name()), \".rep\");\n  bout.litebar(\"Upload QWK Reply Packet\");\n  bout.nl();\n  bout.print(\"|#9QWK Reply Packet must be named: \\\"|#2{}|#9\\\"\\r\\n\", rep_name);\n  bout.outstr(\"|#5Would you like to upload a QWK Reply Packet? \");\n  const auto rep_path = FilePath(a()->sess().dirs().qwk_directory(), rep_name);\n\n  const auto do_it = bin.yesno();\n\n  if (do_it) {\n    if (a()->sess().incom()) {\n      qwk_receive_file(rep_path.string(), &rec, a()->user()->data.qwk_protocol);\n    } else {\n      bout.pl(\"|#5Please copy the REP file to the following directory: \");\n      bout.print(\"|#2{}\\r\\n\", a()->sess().dirs().qwk_directory().string());\n      bout.pausescr();\n    }\n\n    if (rec) {\n      // The MSG file is always upper case.\n      const auto msg_name = ToStringUpperCase(StrCat(qwk_system_name(qwk_cfg, a()->config()->system_name()), \".MSG\"));\n      auto msg_path = ready_reply_packet(rep_path.string(), msg_name);\n      process_reply_dat(msg_path.string());\n    } else {\n      sysoplog(\"Aborted\");\n      bout.nl();\n      bout.print(\"|#6Reply Packet: |#2{} |#6not found.\\r\\n\", rep_name);\n      bout.nl();\n    }\n  }\n  if (save_conf) {\n    tmp_disable_conf(false);\n  }\n\n  a()->set_current_user_sub_num(save_sub);\n}\n\n\nvoid qwk_inmsg(const char* text, messagerec* m1, const std::string& aux, const std::string& name,\n               const DateTime& dt) {\n  auto at_exit = finally([=]() {\n    // Might not need to do this anymore since quoting\n    // isn't so convoluted.\n    bin.charbufferpointer_ = 0;\n    bin.charbuffer[0] = 0;\n  });\n\n  auto m = *m1;\n  std::ostringstream ss;\n  ss << name << \"\\r\\n\";\n  ss << dt.to_string() << \"\\r\\n\";\n  ss << text << \"\\r\\n\";\n\n  auto message_text = ss.str();\n  if (message_text.back() != CZ) {\n    message_text.push_back(CZ);\n  }\n  savefile(message_text, &m, aux);\n  *m1 = m;\n}\n\n\n\n\n}\n"
  },
  {
    "path": "bbs/qwk/qwk_reply.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_REPLY_H\n#define INCLUDED_BBS_QWK_QWK_REPLY_H\n\n#include \"bbs/qwk/qwk_struct.h\"\n#include \"core/datetime.h\"\n#include <string>\n\nstruct messagerec;\n\nnamespace wwiv::bbs::qwk {\n\n\nvoid qwk_inmsg(const char* text, messagerec* m1, const std::string& aux, const std::string& name,\n               const core::DateTime& dt);\n\nvoid upload_reply_packet();\n\n\n}\n#endif  // _QWK_H_\n"
  },
  {
    "path": "bbs/qwk/qwk_struct.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_STRUCT_H\n#define INCLUDED_BBS_QWK_QWK_STRUCT_H\n\n#include \"core/file.h\"\n#include \"core/datafile.h\"\n#include <cstdint>\n\n\nnamespace wwiv::bbs::qwk {\n#pragma pack(push, 1)\nstruct qwk_record {\n  char status;   // ' ' for public\n\n  char msgnum[7]; // all strings are space padded\n  char date[8];\n  char time[5];\n\n  char to[25]; // Uppercase, left justified\n  char from[25]; // Uppercase left justified\n  char subject[25];\n  char password[12];\n  char reference[8];\n\n  char amount_blocks[6];\n  char flag;\n\n  uint16_t conf_num;\n  uint16_t logical_num;\n  char tagline;\n};\n\nstruct qwk_index {\n  float pos;\n  char nouse;\n};\n\nstruct qwk_state {\n  uint16_t qwk_rec_num{0};\n  uint16_t qwk_rec_pos{0};\n  int cursub{0};\n\n  // File number for the MESSAGES.DAT file\n  std::unique_ptr<wwiv::core::DataFile<qwk_record>> file;\n\n  // File number for the *.NDX files\n  std::unique_ptr<wwiv::core::DataFile<qwk_index>> index;\n  std::unique_ptr<wwiv::core::DataFile<qwk_index>> personal;  // personal.ndx\n  std::unique_ptr<wwiv::core::DataFile<qwk_index>> zero;      // 000.ndx for email\n\n  qwk_record qwk_rec{};\n  qwk_index qwk_ndx{};\n\n  bool abort{false};\n  bool in_email{false};\n  // This should be 25 chars so we want 1 more for null.\n  char email_title[25];\n};\n\n\nstruct qwk_sub_conf {\n  int import_num;\n  char import_name[14];\n  int to_num;\n  char to_name[41];\n};\n\nenum CONFIG_QWK_RETURNS {\n  QWK_SELECT,\n  QWK_ARCHIVER,\n  QWK_MAX_PACKET,\n  QWK_MAX_SUB,\n  QWK_SELECT_PROTOCOL,\n  QWK_QUIT_SAVE,\n  QWK_ABORT\n};\n#pragma pack(pop)\n\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk/qwk_text.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk_text.h\"\n\n#include \"core/strings.h\"\n\nnamespace wwiv::bbs::qwk {\n\nextern const char* QWKFrom;\n\nstd::optional<std::string> get_qwk_from_message(const std::string& text) {\n  const auto* qwk_from_start = strstr(text.c_str(), QWKFrom + 2);\n\n  if (qwk_from_start == nullptr) {\n    return std::nullopt;\n  }\n\n  qwk_from_start += strlen(QWKFrom + 2); // Get past 'QWKFrom:'\n  const auto* qwk_from_end = strchr(qwk_from_start, '\\r');\n\n  if (qwk_from_end && qwk_from_end > qwk_from_start) {\n    std::string temp(qwk_from_start, qwk_from_end - qwk_from_start);\n\n    return strings::ToStringUpperCase(strings::StringTrim(temp));\n  }\n  return std::nullopt;\n}\n\n// Takes reply packet and converts '227' () to '13' and removes QWK style\n// space padding at the end.\nstd::string make_text_ready(const std::string& text) {\n  std::string temp;\n  for (const auto c : text) {\n    if (c == '\\xE3') {\n      temp.push_back(13);\n      temp.push_back(10);\n    } else {\n      temp.push_back(c);\n    }\n  }\n\n  // Remove trailing space character only. wwiv::strings::StringTrimEnd also removes other\n  // whitespace characters like \\t and \\r\\n\n  const auto pos = temp.find_last_not_of(' ');\n  temp.erase(pos + 1);\n  return temp;\n}\n\n\n}\n"
  },
  {
    "path": "bbs/qwk/qwk_text.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_TEXT_H\n#define INCLUDED_BBS_QWK_QWK_TEXT_H\n#include <optional>\n#include <string>\n\nnamespace wwiv::bbs::qwk {\n\n// Takes reply packet and converts '227' () to '13' and removes QWK style\n// space padding at the end.\nstd::string make_text_ready(const std::string& text);\nstd::optional<std::string> get_qwk_from_message(const std::string& text);\n\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk/qwk_ui.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk_ui.h\"\n\n\n\n#include \"qwk.h\"\n#include \"qwk_struct.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/sr.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs::qwk {\n\n\nint select_qwk_archiver(bool& abort, bool allow_ask_each_time) {\n  std::string allowed = \"Q\\r\";\n\n  bout.nl(2);\n  bout.pl(\"|#5Select an archiver\");\n  if (allow_ask_each_time) {\n    bout.pl(\"|#20|#9) Ask each time\");\n  }\n  auto num = 0;\n  for (const auto& arc : a()->arcs) {\n    std::string ext = arc.extension;\n    ++num;\n    if (!StringTrim(ext).empty() && ext != \"EXT\") {\n      allowed.append(std::to_string(num));\n      bout.print(\"|#2{}|#9) {}\\r\\n\", num, ext);\n    }\n  }\n  bout.nl();\n  bout.outstr(\"|#7(|#1Q=Quit|#7,|#1<CR>=1|#7) Enter # :\");\n\n  if (allow_ask_each_time) {\n    allowed.push_back('0');\n  }\n\n  const auto archiver = onek(allowed);\n\n  if (archiver == '\\r') {\n    // default/first archiver\n    return 1;\n  }\n\n  if (archiver == 'Q') {\n    abort = true;\n    // 0 is none.\n    return 0;\n  }\n  return archiver - '0';\n}\n\nstd::string qwk_which_zip() {\n  if (a()->user()->data.qwk_archive == 0) {\n    return \"ASK\";\n  }\n\n  if (a()->user()->data.qwk_archive > 4) {\n    a()->user()->data.qwk_archive = 0;\n    return \"ASK\";\n  }\n\n  if (a()->arcs[a()->user()->data.qwk_archive - 1].extension[0] == '\\0') {\n    a()->user()->data.qwk_archive = 0;\n    return \"ASK\";\n  }\n\n  return a()->arcs[a()->user()->data.qwk_archive - 1].extension;\n}\n\nstd::string qwk_which_protocol() {\n  if (a()->user()->data.qwk_protocol == 1) {\n    a()->user()->data.qwk_protocol = 0;\n  }\n\n  if (a()->user()->data.qwk_protocol == 0) {\n    return std::string(\"ASK\");\n  }\n  auto prot(prot_name(a()->user()->data.qwk_protocol));\n  if (prot.size() > 22) {\n    return prot.substr(0, 21);\n  }\n  return prot;\n}\n\nvoid modify_bulletins(sdk::qwk_config& qwk_cfg) {\n  char s[101], t[101];\n\n  while (!a()->sess().hangup()) {\n    bout.nl();\n    bout.outstr(\"Add - Delete - ? List - Quit\");\n    bout.mpl(1);\n\n    const int key = onek(\"Q\\rAD?\");\n\n    switch (key) {\n    case 'Q':\n    case '\\r':\n      return;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"Which one?\");\n      bout.mpl(2);\n\n      bin.input(s, 2);\n      const auto x = strings::to_number<int>(s);\n      // Delete the one at the right position.\n      if (x >= 0 && x < stl::size_int(qwk_cfg.bulletins)) {\n        stl::erase_at(qwk_cfg.bulletins, x);\n      }\n    } break;\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"Enter complete path to Bulletin\");\n      bin.input(s, 80);\n\n      if (!core::File::Exists(s)) {\n        bout.outstr(\"File doesn't exist, continue?\");\n        if (!bin.yesno()) {\n          break;\n        }\n      }\n\n      bout.outstr(\"Now enter its bulletin name, in the format BLT-????.???\");\n      bin.input(t, BNAME_SIZE);\n\n      if (strncasecmp(t, \"BLT-\", 4) != 0) {\n        bout.outstr(\"Improper format\");\n        break;\n      }\n\n      sdk::qwk_bulletin b{t, s};\n      qwk_cfg.bulletins.emplace_back(b);\n    } break;\n    case '?': {\n      auto x = 1;\n      for (const auto& b : qwk_cfg.bulletins) {\n        if (bin.checka()) {\n          break;\n        }\n        bout.print(\"|#7[{}] |#1{} |#5Is copied over from\\r\\n\", x++, b.name);\n        bout.print(\"|#7{}\\r\\n{}|#1\\r\\n\", std::string(78, '\\xCD'), b.path);\n      }\n    } break;\n    }\n  }\n}\n\nbool get_qwk_max_msgs(uint16_t *qwk_max_msgs, uint16_t *max_per_sub) {\n  bout.nl();\n  bout.outstr(\"|#9(0=Unlimited) Most messages you want per sub? \");\n  *max_per_sub = bin.input_number(*max_per_sub);\n  bout.outstr(\"|#9(0=Unlimited) Most messages per packet?       \");\n  *qwk_max_msgs = bin.input_number(*qwk_max_msgs);\n  return true;\n}\n\n}\n"
  },
  {
    "path": "bbs/qwk/qwk_ui.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_UI_H\n#define INCLUDED_BBS_QWK_QWK_UI_H\n\n#include \"bbs/qwk/qwk_struct.h\"\n#include \"sdk/qwk_config.h\"\n#include <string>\n\nnamespace wwiv::bbs::qwk {\n\nstd::string qwk_which_zip();\n\n/**\n * Gets the archiver # to use for QWK.  \n * \n * If allow_ask_each_time, then add \"ask each time\" to the list.\n * Also update \"abort\" if the caller enters (Q) to quit.\n */\nint select_qwk_archiver(bool& abort, bool allow_ask_each_time);\n\nstd::string qwk_which_protocol();\nvoid modify_bulletins(sdk::qwk_config& qwk_cfg);\nbool get_qwk_max_msgs(uint16_t *max_msgs, uint16_t *max_per_sub);\n\n\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk/qwk_util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/qwk/qwk_util.h\"\n\nnamespace wwiv::bbs::qwk {\n\nint _fieeetomsbin(float *src4, float *dest4) {\n  auto* ieee = reinterpret_cast<unsigned char*>(src4);\n  auto* msbin = reinterpret_cast<unsigned char*>(dest4);\n  unsigned char msbin_exp = 0x00;\n\n  /* See _fmsbintoieee() for details of formats   */\n  const unsigned char sign = ieee[3] & 0x80;\n  msbin_exp |= ieee[3] << 1;\n  msbin_exp |= ieee[2] >> 7;\n\n  /* An ieee exponent of 0xfe overflows in MBF    */\n  if (msbin_exp == 0xfe) {\n    return 1;\n  }\n\n  msbin_exp += 2;     /* actually, -127 + 128 + 1 */\n\n  for (auto i = 0; i < 4; i++) {\n    msbin[i] = 0;\n  }\n\n  msbin[3] = msbin_exp;\n  msbin[2] |= sign;\n  msbin[2] |= ieee[2] & 0x7f;\n  msbin[1] = ieee[1];\n  msbin[0] = ieee[0];\n\n  return 0;\n}\n\n}"
  },
  {
    "path": "bbs/qwk/qwk_util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_QWK_QWK_UTIL_H\n#define INCLUDED_BBS_QWK_QWK_UTIL_H\n\nnamespace wwiv::bbs::qwk {\n  int _fieeetomsbin(float *src4, float *dest4);\n}\n\n#endif"
  },
  {
    "path": "bbs/qwk_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/qwk/qwk_text.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"core/datafile.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/qwk_config.h\"\n#include <string>\n\nusing wwiv::sdk::User;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::bbs::qwk;\nusing namespace wwiv::sdk;\n\nclass QwkTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    helper.SetUp();\n    qwk_config_filename = FilePath(helper.data(), QWK_JSON);\n  }\n\n  BbsHelper helper{};\n  std::filesystem::path qwk_config_filename;\n};\n\nTEST_F(QwkTest, ReadQwkConfig_Read_NoBulletins) {\n\n  qwk_config qc{};\n  qc.packet_name = \"PAKTNAME\";\n  write_qwk_cfg(helper.config(), qc);\n\n  auto q = read_qwk_cfg(helper.config());\n  EXPECT_EQ(\"PAKTNAME\", q.packet_name);\n  EXPECT_EQ(0u, q.bulletins.size());\n}\n\nTEST_F(QwkTest, ReadQwkConfig_Read_TwoBulletins) {\n  {\n    qwk_config qc{};\n    qc.packet_name = \"PAKTNAME\";\n    qc.bulletins.emplace_back(qwk_bulletin{\"name1\", \"path1\"});\n    qc.bulletins.emplace_back(qwk_bulletin{\"name2\", \"path2\"});\n    write_qwk_cfg(helper.config(), qc);\n  }\n\n  auto q = read_qwk_cfg(helper.config());\n  EXPECT_EQ(\"PAKTNAME\", q.packet_name);\n  EXPECT_EQ(2u, q.bulletins.size());\n\n  auto b = q.bulletins.begin();\n  EXPECT_EQ(b->name, \"name1\");\n  EXPECT_EQ(b->path, \"path1\");\n  ++b;\n  EXPECT_EQ(b->name, \"name2\");\n  EXPECT_EQ(b->path, \"path2\");\n}\n\nTEST_F(QwkTest, ReadQwkConfig_Write_NoBulletins) {\n  qwk_config c{};\n  c.packet_name = \"TESTPAKT\";\n\n  ASSERT_FALSE(File::Exists(qwk_config_filename));\n  write_qwk_cfg(helper.config(), c);\n  ASSERT_TRUE(File::Exists(qwk_config_filename));\n\n  auto q = read_qwk_cfg(helper.config());\n  EXPECT_EQ(\"TESTPAKT\", q.packet_name);\n}\n\nTEST_F(QwkTest, ReadQwkConfig_Write_OneBulletins) {\n  qwk_config c{};\n  c.packet_name = \"TESTPAKT\";\n  qwk_bulletin b{\"name1\", \"path1\"};\n  c.bulletins.emplace_back(b);\n\n  ASSERT_FALSE(File::Exists(qwk_config_filename));\n  write_qwk_cfg(helper.config(), c);\n  ASSERT_TRUE(File::Exists(qwk_config_filename));\n\n  auto q = read_qwk_cfg(helper.config());\n  EXPECT_EQ(1u, q.bulletins.size());\n}\n\nTEST(Qwk1Test, TestGetQwkFromMessage) {\n  const auto* const QWKFrom = \"\\x04\"\n                              \"0QWKFrom:\";\n\n  const auto message = StrCat(\"\\x3\", \"0Thisis a test\\r\\n\", QWKFrom,\n                              \" Rushfan #1 @561\\r\\nTitle\\r\\nDate\\r\\nThis is the message\");\n  auto opt_to = get_qwk_from_message(message);\n  ASSERT_TRUE(opt_to.has_value());\n\n  const auto o = opt_to.value();\n  EXPECT_STREQ(\"RUSHFAN #1 @561\", o.c_str());\n}\n\nTEST(Qwk1Test, TestGetQwkFromMessage_NotFound) {\n  const auto message = StrCat(\"\\x3\", \"0Thisis a test\\r\\n\",\n                              \" Rushfan #1 @561\\r\\nTitle\\r\\nDate\\r\\nThis is the message\");\n  const auto opt_to = get_qwk_from_message(message);\n  ASSERT_FALSE(opt_to.has_value());\n}\n\nTEST(Qwk1Test, TestGetQwkFromMessage_Malformed_AtEndOfLine) {\n  const auto* const QWKFrom = \"\\x04\"\n                              \"0QWKFrom:\";\n  const auto message = StrCat(\"\\x3\", \"0Thisis a test\\r\\n\",\n                              \" Rushfan #1 @561\\r\\nTitle\\r\\nDate\\r\\nThis is the message\", QWKFrom);\n  const auto opt_to = get_qwk_from_message(message);\n  ASSERT_FALSE(opt_to.has_value());\n}"
  },
  {
    "path": "bbs/read_message.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/read_message.h\"\n\n#include \"message_find.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/utility.h\"\n#include \"common/full_screen.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/ansi/ansi.h\"\n#include \"sdk/ansi/framebuffer.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/msgapi/message_utils_wwiv.h\"\n#include \"sdk/msgapi/parsed_message.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/networks.h\"\n\n#include <cctype>\n#include <memory>\n#include <stdexcept>\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::ansi;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// N.B: I can't imagine any good reason for this, but I ifdef'ed\n// out the old behavior that's been here since forever\n// with this guard.  I'll probably remove it later unless\n// I hear some good reason to leave it.  Also note that the\n// Message SDK doesn't have this logic.\n// #define UPDATE_SYSTEM_QSCAN_PTR_ON_ADVANCED_POST_POINTER\n\n/**\n * Returns (network name, network location) the outNetworkName and outLocation.\n */\nstatic void UpdateMessageOriginInfo(int system_number, int user_number, Type2MessageData& data) {\n  data.from_sys_loc.clear();\n  data.from_sys_name.clear();\n\n  auto& net = a()->mutable_current_net();\n  if (net.type == network_type_t::internet ||\n      net.type == network_type_t::news) {\n    data.from_sys_name = \"Internet Mail and Newsgroups\";\n  }\n\n  if (net.type == network_type_t::ftn) {\n    // TODO(rushfan): here's where we should try to get it from the bbslist.\n    if (net.try_load_nodelist()) {\n      auto& nl = *net.nodelist;\n      auto addr =\n          system_number == 0\n              ? fido::try_parse_fidoaddr(net.fido.fido_address)\n              : fido::get_address_from_origin(data.message_text);\n      if (!addr.has_value()) {\n        addr = fido::get_address_from_single_line(data.from_user_name);\n        if (!addr.has_value()) {\n          addr = fido::get_address_from_single_line(data.from_user_name);\n        }\n      }\n      if (!addr.has_value()) {\n        LOG(ERROR) << \"Unable to get address from message.\";\n        return;\n      }\n      if (addr->point() != 0) {\n        // Hack to drop points and report parent.\n        if (auto o = fido::try_parse_fidoaddr(to_zone_net_node(addr.value()))) {\n          addr = o.value();\n        }\n      }\n      if (nl.contains(addr.value())) {\n        const auto& e = nl.entry(addr.value());\n        data.from_sys_name = e.name();\n        data.from_sys_loc = e.location();\n        return;\n      }\n    }\n    data.from_sys_name = net.name;\n    data.from_sys_loc = \"Unknown FTN Location\";\n    return;\n  }\n\n  if (net.type == network_type_t::wwivnet) {\n    if (system_number == 0) {\n      system_number = net.sysnum;\n    }\n    if (auto csne = next_system(system_number)) {\n      std::string netstatus;\n      if (user_number == 1) {\n        if (csne->other & other_net_coord) {\n          netstatus = \"{NC}\";\n        } else if (csne->other & other_group_coord) {\n          netstatus = fmt::format(\"{GC{}}\", csne->group);\n        } else if (csne->other & other_area_coord) {\n          netstatus = \"{AC}\";\n        }\n      }\n      const auto phone_fn =\n          fmt::sprintf(\"%s.%-3u\", REGIONS_DIR, to_number<unsigned int>(csne->phone));\n      const auto regions_dir = FilePath(a()->config()->datadir(), REGIONS_DIR);\n      const auto filename = FilePath(regions_dir, phone_fn);\n\n      std::string description;\n      if (File::Exists(filename)) {\n        // Try to use the town first.\n        const auto phone_prefix =\n            fmt::sprintf(\"%c%c%c\", csne->phone[4], csne->phone[5], csne->phone[6]);\n        description = describe_area_code_prefix(to_number<int>(csne->phone),\n                                                to_number<int>(phone_prefix));\n      }\n      if (description.empty()) {\n        // Try area code if we still don't have a description.\n        description = describe_area_code(to_number<int>(csne->phone));\n      }\n      data.from_sys_name = fmt::format(\"{} {}\", csne->name, netstatus);\n      data.from_sys_loc = description;\n      return;\n    }\n    data.from_sys_name = \"Unknown System\";\n    data.from_sys_loc = \"\";\n  }\n}\n\nvoid display_message_text(const std::string& text, bool* next) {\n  auto line_len_ptr = 0;\n  auto ctrld = 0;\n  auto printit = false;\n  auto ctrla = false;\n  auto centre = false;\n  auto abort = false;\n  auto ansi = false;\n  std::string s;\n  s.reserve(160);\n\n  bout.nl();\n  for (auto ch : text) {\n    if (ch == CZ || abort) {\n      break;\n    }\n    if (ch == SOFTRETURN) {\n      ctrld = 0;\n      continue;\n    }\n    if (ch == RETURN || !ch) {\n      printit = true;\n    } else if (ch == CA) {\n      ctrla = true;\n    } else if (ch == CB) {\n      centre = true;\n    } else if (ch == CD) {\n      ctrld = 1;\n    } else if (ctrld == 1) {\n      if (ch >= '0' && ch <= '9') {\n        if (ch == '0') {\n          ctrld = -1; // don't display\n        } else {\n          if (a()->user()->optional_val() == 0) {\n            ctrld = 0; // display\n          } else {\n            if (10 - a()->user()->optional_val() < static_cast<int>(ch - '0')) {\n              ctrld = -1; // don't display\n            } else {\n              ctrld = 0; // display\n            }\n          }\n        }\n      } else {\n        ctrld = 0; // ctrl-d and non-numeric\n      }\n    } else {\n      if (ch == ESC) {\n        ansi = true;\n      }\n      if (bout.ansi_movement_occurred()) {\n        bout.clear_ansi_movement_occurred();\n        bout.clear_lines_listed();\n        if (bout.localIO()->GetTopLine() && bout.localIO()->GetScreenBottom() == 24) {\n          a()->ClearTopScreenProtection();\n        }\n      }\n      s.push_back(ch);\n      if (ch == CC || ch == BACKSPACE) {\n        --line_len_ptr;\n      } else {\n        ++line_len_ptr;\n      }\n    }\n\n    if (printit || ansi || line_len_ptr >= 80) {\n      if (centre && ctrld != -1) {\n        const auto spaces_to_center = (a()->user()->screen_width() - bout.wherex() - line_len_ptr) / 2;\n        bout.outstr(std::string(spaces_to_center, ' '), &abort, next);\n      }\n      if (!s.empty()) {\n        if (ctrld != -1) {\n          if (bout.wherex() + line_len_ptr >= static_cast<int>(a()->user()->screen_width()) &&\n              !centre && !ansi) {\n            bout.nl();\n          }\n          bout.outstr(s, &abort, next);\n          if (ctrla && !s.empty() && s.back() != SPACE && !ansi) {\n            if (bout.wherex() < static_cast<int>(a()->user()->screen_width()) - 1) {\n              bout.outchr(SPACE);\n            } \n            bout.nl();\n            bin.checka(&abort, next);\n          }\n        }\n        line_len_ptr = 0;\n        s.clear();\n      }\n      centre = false;\n    }\n    if (ch == RETURN) {\n      if (ctrla == false) {\n        if (ctrld != -1) {\n          bout.nl();\n          bin.checka(&abort, next);\n        }\n      } else {\n        ctrla = false;\n      }\n      if (printit) {\n        ctrld = 0;\n      }\n    }\n    printit = false;\n  }\n\n  //\n  // After the for loop processing character by character\n  //\n\n  if (!abort && !s.empty()) {\n    bout.pl(s);\n  }\n  bout.ansic(0);\n  bout.nl();\n  if (ansi && bout.localIO()->topdata() != LocalIO::topdata_t::none &&\n      a()->sess().IsUserOnline()) {\n    a()->UpdateTopScreen();\n  }\n  bout.disable_mci();\n}\n\nstatic void UpdateHeaderInformation(int8_t anon_type, bool readit, const std::string default_name,\n                                    std::string* name, std::string* date) {\n  switch (anon_type) {\n  case anony_sender:\n    if (readit) {\n      *name = StrCat(\"<<< \", default_name, \" >>>\");\n    } else {\n      *name = \">UNKNOWN<\";\n    }\n    break;\n  case anony_sender_da:\n  case anony_sender_pp:\n    *date = \">UNKNOWN<\";\n    if (anon_type == anony_sender_da) {\n      *name = \"Abby\";\n    } else {\n      *name = \"Problemed Person\";\n    }\n    if (readit) {\n      *name = StrCat(\"<<< \", default_name, \" >>>\");\n    }\n    break;\n  default:\n    *name = default_name;\n    break;\n  }\n}\n\nstd::optional<Type2MessageData> read_type2_message(messagerec* msg, uint8_t an, bool readit,\n                                                   const std::string& file_name, int from_sys_num,\n                                                   int from_user) {\n\n  Type2MessageData data{};\n  data.email = iequals(\"email\", file_name);\n  if (data.email) {\n    data.message_area = \"WWIV E-mail\";\n  } else {\n    data.sub = a()->current_sub();\n    data.message_area = data.sub.name;\n\n    if (data.sub.nets.empty()) {\n      data.flags.insert(MessageFlags::LOCAL);\n    }\n    for (const auto& nets : data.sub.nets) {\n      const auto& net = a()->nets()[nets.net_num];\n      if (net.type == network_type_t::ftn) {\n        data.flags.insert(MessageFlags::FTN);\n      } else if (net.type == network_type_t::wwivnet) {\n        data.flags.insert(MessageFlags::WWIVNET);\n      }\n    }\n  }\n  auto o = readfile(msg, file_name);\n  if (!o) {\n    return std::nullopt;\n  }\n  // Make a copy of the raw message text.\n  data.message_text = o.value();\n  data.raw_message_text = data.message_text;\n\n  // TODO(rushfan): Use get_control_line from networking code here.\n\n  size_t ptr;\n  for (ptr = 0; ptr < data.message_text.size() && data.message_text[ptr] != RETURN && ptr <= 200;\n       ptr++) {\n    data.from_user_name.push_back(data.message_text[ptr]);\n  }\n  if (ptr < data.message_text.size() && data.message_text[++ptr] == SOFTRETURN) {\n    ++ptr;\n  }\n  for (const auto start = ptr;\n       ptr < data.message_text.size() && data.message_text[ptr] != RETURN && ptr - start <= 60;\n       ptr++) {\n    data.date.push_back(data.message_text[ptr]);\n  }\n  if (ptr + 1 < data.message_text.size()) {\n    // skip trailing \\r\\n\n    while (ptr + 1 < data.message_text.size() &&\n           (data.message_text[ptr] == '\\r' || data.message_text[ptr] == '\\n')) {\n      ptr++;\n    }\n    try {\n      data.message_text = data.message_text.substr(ptr);\n    } catch (const std::out_of_range& e) {\n      LOG(ERROR) << \"Error getting message_text: \" << e.what();\n    }\n    // ptr = 0;\n  }\n\n  auto lines = SplitString(data.message_text, \"\\r\");\n  for (auto line : lines) {\n    StringTrim(&line);\n    if (line.empty()) {\n      continue;\n    }\n    if (starts_with(line, \"\\004\" \"0FidoAddr: \") && line.size() > 12) {\n      if (auto cl = line.substr(12); !cl.empty()) {\n        data.to_user_name = cl;\n        break;\n      }\n    }\n  }\n\n  if (!data.message_text.empty() && data.message_text.back() == CZ) {\n    data.message_text.pop_back();\n  }\n\n  UpdateHeaderInformation(an, readit, data.from_user_name, &data.from_user_name, &data.date);\n  if (an == 0) {\n    bout.disable_mci();\n    UpdateMessageOriginInfo(from_sys_num, from_user, data);\n  }\n\n  data.message_anony = an;\n  return data;\n}\n\nstatic int legacy_display_header_text(Type2MessageData& msg) {\n  auto num_header_lines = 0;\n  if (msg.message_number > 0 && msg.total_messages > 0 && !msg.message_area.empty()) {\n    bout.print(\"|#9 Sub|#7: |#{}{:<35.35}\", a()->GetMessageColor(), msg.message_area);\n    if (a()->user()->screen_width() >= 78) {\n      bout.outstr(\" \");\n    } else {\n      bout.nl();\n      num_header_lines++;\n    }\n    if (msg.message_number > 0 && msg.total_messages > 0) {\n      bout.print(\"|#9Msg#|#7: [|#{}{}|#7 of |#{}{}|#7]\", a()->GetMessageColor(),\n                  msg.message_number, a()->GetMessageColor(), msg.total_messages);\n    }\n    bout.nl();\n    num_header_lines++;\n  }\n\n  bout.print(\"|#9From|#7: |#1{:<35.35}\", msg.from_user_name);\n  if (a()->user()->screen_width() >= 78) {\n    bout.outstr(\" \");\n  } else {\n    bout.nl();\n    num_header_lines++;\n  }\n  bout.print(\"|#9Date|#7: |#1{0:{1}.{1}}\\r\\n\", msg.date, a()->user()->screen_width()-50);\n  num_header_lines++;\n  if (!msg.to_user_name.empty()) {\n    bout.print(\"  |#9To|#7: |#1{}\\r\\n\", msg.to_user_name);\n    num_header_lines++;\n  }\n  bout.print(\"|#9Subj|#7: |#{}{}\\r\\n\", a()->GetMessageColor(), msg.title);\n  num_header_lines++;\n\n  if (!msg.from_sys_name.empty()) {\n    bout.print(\"|#9 Sys|#7: |#1{:<35.35}\", msg.from_sys_name);\n    if (a()->user()->screen_width() >= 78) {\n      bout.outstr(\" \");\n    } else {\n      bout.nl();\n      num_header_lines++;\n    }\n    if (!msg.from_sys_loc.empty()) {\n      bout.print(\" |#9Loc|#7: |#1{0:<{1}.{1}}\\r\\n\", msg.from_sys_loc, a()->user()->screen_width()-49);\n      num_header_lines++;\n    }\n  }\n\n  if (!msg.flags.empty()) {\n    bout.outstr(\"|#9Info|#7: |#1\");\n    for (const auto& f : msg.flags) {\n      switch (f) {\n      case MessageFlags::FORCED:\n        bout.outstr(\"|13[FORCED] \");\n        break;\n      case MessageFlags::NOT_NETWORK_VALIDATED:\n        bout.outstr(\"|12[Not Network Validated] \");\n        break;\n      case MessageFlags::NOT_VALIDATED:\n        bout.outstr(\"|12<<< NOT VALIDATED >>>\");\n        break;\n      case MessageFlags::PERMANENT:\n        bout.outstr(\"|13[Permanent] \");\n        break;\n      case MessageFlags::LOCAL:\n        bout.outstr(\"|10[Local] \");\n        break;\n      case MessageFlags::FTN:\n        bout.outstr(\"|10[Fido] \");\n        break;\n      case MessageFlags::PRIVATE:\n        bout.outstr(\"|10[Pvt] \");\n        break;\n      case MessageFlags::WWIVNET:\n        bout.outstr(\"|10[WWIVnet] \");\n        break;\n      }\n    }\n    bout.nl();\n    num_header_lines++;\n  }\n  return num_header_lines;\n}\n\nstatic std::tuple<bool, int> display_header_file(Type2MessageData& msg) {\n  std::map<std::string, std::string> m;\n  m[\"message_area\"] = trim_to_size(msg.message_area, 35);\n  m[\"message_number\"] = std::to_string(msg.message_number);\n  m[\"total_messages\"] = std::to_string(msg.total_messages);\n  m[\"from\"] =trim_to_size(msg.from_user_name, 35);\n  m[\"date\"] = msg.date;\n  m[\"to\"] = (!msg.to_user_name.empty()) ? msg.to_user_name : \"All\";\n  m[\"title\"] = msg.title;\n  m[\"sys\"] = trim_to_size(msg.from_sys_name, 35);\n  m[\"loc\"] = trim_to_size(msg.from_sys_loc, 35);\n  a()->context().add_context_variable(\"msg\", m);\n\n  std::map<std::string, std::string> flags;\n  // Set defaults.\n  flags[\"forced\"] = \"false\";\n  flags[\"not_net_val\"] = \"false\";\n  flags[\"not_val\"] = \"false\";\n  flags[\"permanent\"] = \"false\";\n  flags[\"local\"] = \"false\";\n  flags[\"ftn\"] = \"false\";\n  flags[\"private\"] = \"false\";\n  flags[\"wwivnet\"] = \"false\";\n  for (const auto& f : msg.flags) {\n    switch (f) {\n    case MessageFlags::FORCED:\n      flags[\"forced\"] = \"true\";\n      break;\n    case MessageFlags::NOT_NETWORK_VALIDATED:\n      flags[\"not_net_val\"] = \"true\";\n      break;\n    case MessageFlags::NOT_VALIDATED:\n      flags[\"not_val\"] = \"true\";\n      break;\n    case MessageFlags::PERMANENT:\n      flags[\"permanent\"] = \"true\";\n      break;\n    case MessageFlags::LOCAL:\n      flags[\"local\"] = \"true\";\n      break;\n    case MessageFlags::FTN:\n      flags[\"ftn\"] = \"true\";\n      break;\n    case MessageFlags::PRIVATE:\n      flags[\"private\"] = \"true\";\n      break;\n    case MessageFlags::WWIVNET:\n      flags[\"wwivnet\"] = \"true\";\n      break;\n    }\n  }\n  a()->context().add_context_variable(\"msg.flags\", flags);\n\n  // TODO(rushfan): Make these always be available like user?\n  const auto& net = a()->current_net();\n  std::map<std::string, std::string> n;\n  n[\"name\"] = net.name;\n  if (net.type == network_type_t::ftn) {\n    n[\"node\"] = net.fido.fido_address;\n  }\n  n[\"node\"] = std::to_string(net.sysnum);\n  a()->context().add_context_variable(\"net\", n);\n\n  const auto saved_mci_enabled = bout.mci_enabled();\n  auto at_exit = finally([=] {\n    a()->context().clear_context_variables();\n    bout.set_mci_enabled(saved_mci_enabled);\n  });\n  bout.set_mci_enabled(true);\n  if (bout.printfile(\"fs_msgread\")) {\n    auto num_header_lines = 5;\n    if (const auto iter = a()->context().return_values().find(\"num_header_lines\");\n        iter != std::end(a()->context().return_values())) {\n      num_header_lines = to_number<int>(iter->second);\n    }\n    return std::make_tuple(true, num_header_lines);\n  }\n  return std::make_tuple(false, 5);\n}\n\nstatic FullScreenView display_type2_message_header(Type2MessageData& msg, bool allow_header_file) {\n  const auto oldcuratr = bout.curatr();\n\n  int num_header_lines = 5;\n  if (allow_header_file) {\n    auto [displayed, nh] = display_header_file(msg);\n    if (!displayed) {\n      nh = legacy_display_header_text(msg);\n    }\n    num_header_lines = nh;\n  } else {\n    num_header_lines = legacy_display_header_text(msg);\n  }\n\n  const auto screen_width = a()->user()->screen_width();\n  const auto screen_length = a()->user()->screen_lines() - 1;\n\n  bout.setc(oldcuratr);\n  return FullScreenView(bout, bin, num_header_lines, screen_width, screen_length);\n}\n\nstatic std::vector<std::string> split_wwiv_message(const std::string& message_text,\n                                                   bool controlcodes) {\n  const auto& user = *a()->user();\n  WWIVParsedMessageText pmt(message_text);\n  parsed_message_lines_style_t style{};\n  style.ctrl_lines = control_lines_t::control_lines;\n  style.add_wrapping_marker = false;\n  style.line_length = user.screen_width() - 1;\n  const auto orig_lines = pmt.to_lines(style);\n\n  // Now handle control chars, and optional lines.\n  const auto optional_lines = user.optional_val();\n  std::vector<std::string> lines;\n  for (auto& line : orig_lines) {\n    if (line.empty()) {\n      lines.emplace_back(\"\");\n      continue;\n    }\n    if (line.front() == CD) {\n      const auto level = line.size() > 1 ? line.at(1) - '0' : 0;\n      if (level == 0 && !controlcodes) {\n        continue;\n      }\n      if (optional_lines != 0 && line.size() >= 2 && 10 - optional_lines < level) {\n        // This is too high of a level, so skip it.\n        continue;\n      }\n    }\n    // Not CD.\n    lines.emplace_back(line);\n  }\n\n  // Render it to the frame buffer to interpret heart codes, ansi, etc.\n  FrameBuffer b(user.screen_width());\n  Ansi ansi(&b, {}, 0x07);\n  HeartAndPipeCodeFilter heart(&ansi, user.colors());\n  for (auto& l : lines) {\n    for (const auto c  : l) {\n      heart.write(c);\n    }\n    // Reset the ANSI state and color at the end of line for lines that start\n    // with control codes.\n    if (!l.empty() && l.front() == 0x04) { // CD\n      ansi.attr(7);\n      ansi.reset();\n    }\n    heart.write('\\n');\n  }\n  heart.close();\n  return b.to_screen_as_lines();\n}\n\n/**\n * returns the colorozed lined color by guessing the type of line.\n */\nstatic std::string get_line_color(std::string& line) {\n  auto& colors = a()->config()->raw_config().colors.msg;\n  if (colors.tear_color.empty()) {\n    colors.tear_color = \"|#8\";\n  }\n  if (colors.origin_color.empty()) {\n    colors.origin_color = \"|#8\";\n  }\n  if (colors.quote_color.empty()) {\n    colors.quote_color = \"|#5\";\n  }\n  if (colors.text_color.empty()) {\n    colors.text_color = \"|#0\";\n  }\n  if (colors.kludge_color.empty()) {\n    colors.kludge_color = \"|08\";\n  }\n  if (line.empty()) {\n    return colors.text_color;\n  }\n  if (starts_with(line, \"---\")) {\n    return colors.tear_color;\n  }\n  if (starts_with(line, \" * Origin:\")) {\n    return colors.origin_color;\n  }\n  \n  if (auto pos = line.find('>'); pos >= 0 && pos <= 4 && line.find('\\x3') == std::string::npos) {\n    return colors.quote_color;\n  }\n\n  return colors.text_color;\n}\n\nstatic void display_message_text_new(const std::vector<std::string>& lines, int start,\n                                     int message_height, int screen_width, int lines_start, Type2MessageData& msg) {\n  auto had_ansi = false;\n  auto& colors = a()->config()->raw_config().colors.msg;\n  if (colors.kludge_color.empty()) {\n    colors.kludge_color = \"|08\";\n  }\n  const auto colorize = msg.sub.colorize_text;\n\n  for (auto i = start; i < start + message_height; i++) {\n    // Do this so we don't pop up a pause for sure.\n    bout.clear_lines_listed();\n    std::string color = \"|#0\";\n\n    if (i >= size_int(lines)) {\n      break;\n    }\n    bout.goxy(1, i - start + lines_start);\n    auto l = lines.at(i);\n    if (l.find(\"\\x1b[\") != std::string::npos) {\n      had_ansi = true;\n      color = \"|16\";\n    }\n    if (!l.empty()) {\n      if (l.back() == CA) {\n        // A line ending in ^A means it soft-wrapped.\n        l.pop_back();\n      } \n      if (l.front() == CB) {\n        // Line starting with ^B is centered.\n        if (ssize(stripcolors(l)) >= screen_width) {\n          // TODO(rushfan): This should be stripped size\n          l = l.substr(1, screen_width);\n        } else {\n          l = StrCat(std::string((screen_width - stripcolors(l).size()) / 2, ' '), l.substr(1));\n        }\n      } else if (l.front() == CD) {\n        l = l.substr(2);\n        color = colors.kludge_color;\n      } else if (!had_ansi && colorize) {\n        color = get_line_color(l);\n      }\n    }\n    bout.ansic(0);\n    bout.outstr(color);\n    bout.outstr(l);\n    bout.clreol();\n  }\n}\n\nstatic std::string percent_read(int start, int end) {\n  const auto d = static_cast<float>(start) / static_cast<float>(end);\n  return fmt::format(\"{:0.0f}%\", d * 100);\n}\n\nstatic ReadMessageResult display_type2_message_new(int& msgno, Type2MessageData& msg, char an, bool* next) {\n  // Reset the color before displaying a message.\n  bout.setc(7);\n  bout.clear_ansi_movement_occurred();\n  *next = false;\n  bout.set_mci_enabled(an != 0);\n\n  bout.cls();\n  auto fs = display_type2_message_header(msg, true);\n\n  const auto controlcodes = a()->user()->has_flag(User::msg_show_controlcodes);\n  const auto lines = split_wwiv_message(msg.message_text, controlcodes);\n\n  fs.DrawTopBar();\n  fs.DrawBottomBar(\"\");\n\n  fs.GotoContentAreaTop();\n  const auto first = 0;\n  const auto last = std::max<int>(0, size_int(lines) - fs.message_height());\n\n  auto start = first;\n  auto dirty = true;\n  ReadMessageResult result{};\n  result.lines_start = fs.lines_start();\n  result.lines_end = fs.lines_end();\n  for ( ;; ) {\n    a()->CheckForHangup();\n\n    if (dirty) {\n      bout.ansic(0);\n      display_message_text_new(lines, start, fs.message_height(), fs.screen_width(),\n                               fs.lines_start(), msg);\n      dirty = false;\n      fs.DrawBottomBar(start == last ? \"END\" : percent_read(start, last));\n      fs.ClearCommandLine();\n      fs.PutsCommandLine(\"|#9(|#2Q|#9=Quit, |#2?|#9=Help): \");\n    }\n    if (!msg.use_msg_command_handler) {\n      result.option = ReadMessageOption::NEXT_MSG;\n      return result;\n    }\n    auto key = bin.bgetch_event(wwiv::common::Input::numlock_status_t::NOTNUMBERS,\n                         [&](wwiv::common::Input::bgetch_timeout_status_t st, int s) {\n                              if (st == wwiv::common::Input::bgetch_timeout_status_t::WARNING) {\n        fs.PrintTimeoutWarning(s);\n                              } else if (st ==\n                                         wwiv::common::Input::bgetch_timeout_status_t::CLEAR) {\n        fs.ClearCommandLine();\n      }\n    });\n    switch (key) {\n    case COMMAND_UP: {\n      if (start > first) {\n        --start;\n        dirty = true;\n      }\n    } break;\n    case COMMAND_PAGEUP: {\n      if (start - fs.message_height() > first) {\n        start -= fs.message_height();\n        dirty = true;\n      } else {\n        dirty = true;\n        start = first;\n      }\n    } break;\n    case COMMAND_HOME: {\n      start = first;\n    } break;\n    case COMMAND_DOWN: {\n      if (start < last) {\n        dirty = true;\n        ++start;\n      }\n    } break;\n    case COMMAND_PAGEDN: {\n      if (start + fs.message_height() < last) {\n        dirty = true;\n        start += fs.message_height();\n      } else if (start != last) {\n        // If start already == last, don't dirty the screen.\n        dirty = true;\n        start = last;\n      }\n    } break;\n    case COMMAND_END: {\n      if (start != last) {\n        start = last;\n        dirty = true;\n      }\n    } break;\n    case COMMAND_RIGHT: {\n      result.option = ReadMessageOption::NEXT_MSG;\n      return result;\n    }\n    case COMMAND_LEFT: {\n      result.option = ReadMessageOption::PREV_MSG;\n      return result;\n    }\n    case SOFTRETURN: {\n      // Do nothing. SyncTerm sends CRLF on enter, not just CR\n      // like we get from the local terminal. So we'll ignore the\n      // SOFTRETURN (10, aka LF).\n    } break;\n    case RETURN: {\n      if (start == last) {\n        result.option = ReadMessageOption::NEXT_MSG;\n        return result;\n      }\n      if (start + fs.message_height() < last) {\n        dirty = true;\n        start += fs.message_height();\n      } else if (start != last) {\n        dirty = true;\n        start = last;\n      }\n    } break;\n    default: {\n      if ((key & 0xff) == key) {\n        key = toupper(key & 0xff);\n        if (key == ']') {\n          result.option = ReadMessageOption::NEXT_MSG;\n        } else if (key == '[') {\n          result.option = ReadMessageOption::PREV_MSG;\n        } else if (key == 'F' && msgno != -1) {\n          const auto r = wwiv::bbs::FindNextMessageFS(fs,msgno);\n          if (r.found) {\n            msgno = r.msgnum;\n          }\n          result.option = ReadMessageOption::READ_MESSAGE;\n        } else if (key == 'J') {\n          result.option = ReadMessageOption::JUMP_TO_MSG;\n        } else if (key == 'T') {\n          result.option = ReadMessageOption::LIST_TITLES;\n        } else if (key == 'K') {\n          result.option = ReadMessageOption::NONE;\n          a()->user()->toggle_flag(User::msg_show_controlcodes);\n        } else if (key == '?') {\n          result.option = ReadMessageOption::NONE;\n          fs.ClearMessageArea();\n          if (!bout.print_help_file(MBFSED_NOEXT)) {\n            fs.ClearCommandLine();\n            bout.print(\"|#6Unable to find file: \", MBFSED_NOEXT);\n          } else {\n            fs.ClearCommandLine();\n          }\n          if (lcs()) {\n            bout.pausescr();\n            fs.ClearMessageArea();\n            if (!bout.print_help_file(MBFSED_SYSOP_NOEXT)) {\n              fs.ClearCommandLine();\n              bout.print(\"|#6Unable to find file: \", MBFSED_SYSOP_NOEXT);\n            }\n          }\n          fs.ClearCommandLine();\n          bout.pausescr();\n          fs.ClearCommandLine();\n        } else {\n          result.option = ReadMessageOption::COMMAND;\n          result.command = static_cast<char>(key);\n        }\n        fs.ClearCommandLine();\n        return result;\n      }\n    }\n    }\n  }\n}\n\nvoid display_type2_message_old_impl(Type2MessageData& msg, bool* next) {\n  const auto info = display_type2_message_header(msg, false);\n  bout.lines_listed(info.num_header_lines());\n  bout.clear_ansi_movement_occurred();\n  *next = false;\n  bout.enable_mci();\n  if (msg.message_anony == 0) {\n    bout.disable_mci();\n  }\n  display_message_text(msg.message_text, next);\n  bout.disable_mci();\n}\n\nReadMessageResult display_type2_message(int& msgno, Type2MessageData& msg, bool* next) {\n  const auto fsreader_enabled =\n      a()->fullscreen_read_prompt() && a()->user()->has_flag(User::fullScreenReader);\n  const auto skip_fs_reader_per_sub = (msg.sub.anony & anony_no_fullscreen) != 0;\n  if (fsreader_enabled && !skip_fs_reader_per_sub && !msg.email) {\n    // N.B.: We don't use the full screen reader for email yet since\n    // It does not work.  Need to figure out how to rearrange email\n    // reading so it does work.\n    return display_type2_message_new(msgno, msg, static_cast<char>(msg.message_anony), next);\n  }\n\n  display_type2_message_old_impl(msg, next);\n\n  ReadMessageResult result{};\n  result.lines_start = 1;\n  result.lines_end = a()->user()->screen_lines() - 1;\n  result.option = ReadMessageOption::NONE;\n  return result;\n}\n\nstatic void update_qscan(uint32_t qscan) {\n  if (qscan > a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()]) {\n    a()->sess().qsc_p[a()->sess().GetCurrentReadMessageArea()] = qscan;\n  }\n\n#ifdef UPDATE_SYSTEM_QSCAN_PTR_ON_ADVANCED_POST_POINTER\n  uint32_t current_qscan_pointer = 0;\n  {\n    auto status = a()->status_manager()->get_status();\n    // not sure why we check this twice...\n    // maybe we need a getCachedQScanPointer?\n    current_qscan_pointer = status->qscanptr();\n  }\n  if (qscan >= current_qscan_pointer) {\n    a()->status_manager()->Run([&](Status& s) {\n      if (qscan >= s.qscanptr()) {\n        s.qscanptr(qscan + 1);\n      }\n    });\n  }\n#endif // UPDATE_SYSTEM_QSCAN_PTR_ON_ADVANCED_POST_POINTER\n}\n\nReadMessageResult read_post(int& msgnum, bool* next, int* val) {\n  if (a()->user()->clear_screen()) {\n    bout.cls();\n  } else {\n    bout.nl();\n  }\n  const auto abort = false;\n  *next = false;\n\n  auto p = *get_post(msgnum);\n  const auto read_it =\n      (lcs() || (a()->config()->sl(a()->sess().effective_sl()).ability & ability_read_post_anony)) ? true : false;\n  const auto& cs = a()->current_sub();\n  auto o =\n      read_type2_message(&p.msg, p.anony & 0x0f, read_it, cs.filename, p.ownersys, p.owneruser);\n  ReadMessageResult result{};\n  if (!o) {\n    result.option = ReadMessageOption::NEXT_MSG;\n    return result;\n  }\n  auto& m = o.value();\n  m.message_number = msgnum;\n  m.total_messages = a()->GetNumMessagesInCurrentMessageArea();\n  if (a()->sess().forcescansub()) {\n    m.flags.insert(MessageFlags::FORCED);\n  }\n\n  if (p.status & (status_unvalidated | status_delete)) {\n    if (!lcs()) {\n      result.option = ReadMessageOption::NEXT_MSG;\n      return result;\n    }\n    m.flags.insert(MessageFlags::NOT_VALIDATED);\n    *val |= 1;\n  }\n  m.title = p.title;\n  strncpy(a()->sess().irt_, p.title, 60);\n\n  if ((p.status & status_no_delete) && lcs()) {\n    m.flags.insert(MessageFlags::PERMANENT);\n  }\n  if ((p.status & status_pending_net) &&\n      a()->user()->sl() >= a()->config()->validated_sl()) {\n    *val |= 2;\n    m.flags.insert(MessageFlags::NOT_NETWORK_VALIDATED);\n  }\n  if (!abort) {\n    const auto saved_net_num = a()->net_num();\n\n    if (p.status & status_post_new_net) {\n      set_net_num(network_number_from(&p));\n    }\n    result = display_type2_message(msgnum, m, next);\n\n    if (saved_net_num != a()->net_num()) {\n      set_net_num(saved_net_num);\n    }\n\n    a()->user()->messages_read(a()->user()->messages_read() + 1);\n    a()->SetNumMessagesReadThisLogon(a()->GetNumMessagesReadThisLogon() + 1);\n  }\n\n  update_qscan(p.qscan);\n  return result;\n}\n"
  },
  {
    "path": "bbs/read_message.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_READ_MESSAGE_H\n#define INCLUDED_BBS_READ_MESSAGE_H\n\n#include <optional>\n#include <set>\n#include <string>\n#include \"sdk/subxtr.h\"\n\nstruct messagerec;\n\nenum class MessageFlags {\n  NOT_VALIDATED,\n  NOT_NETWORK_VALIDATED,\n  FORCED,\n  PERMANENT,\n  LOCAL,\n  PRIVATE,\n  FTN,\n  WWIVNET\n};\n\nstruct Type2MessageData {\n  std::string to_user_name;\n  std::string from_user_name;\n  std::string date;\n  // Parsed out message text, no header information.\n  std::string message_text;\n  // Raw text as it came from readfile\n  std::string raw_message_text;\n  std::string from_sys_name;\n  std::string from_sys_loc;\n\n  std::string title;\n  std::set<MessageFlags> flags;\n  int message_number{0};\n  int total_messages{0};\n  std::string message_area;\n\n  // mailrec.anony flag.\n  uint8_t message_anony{0};\n  bool use_msg_command_handler{true};\n  bool email{false};\n  wwiv::sdk::subboard_t sub;\n};\n\nstd::optional<Type2MessageData> read_type2_message(messagerec* msg, uint8_t an, bool readit,\n                                                   const std::string& file_name, int from_sys_num,\n                                                   int from_user);\n\n\nenum class ReadMessageOption {\n  NONE,\n  // Opens the Jump to Message Dialog\n  JUMP_TO_MSG,\n  NEXT_MSG,\n  PREV_MSG,\n  LIST_TITLES,\n  COMMAND,\n  READ_MESSAGE\n};\n\nstruct ReadMessageResult {\n  ReadMessageOption option = ReadMessageOption::NONE;\n  char command = 0;\n  std::string data;\n  int lines_start = 0;\n  int lines_end = 20;\n  // only used with GOTO_MSG\n  int msgnum{0};\n};\n\nReadMessageResult display_type2_message(int& msgnum, Type2MessageData& msg, bool* next);\n\nReadMessageResult read_post(int& msgnum, bool *next, int *val);\n\n#endif\n"
  },
  {
    "path": "bbs/readmail.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/readmail.h\"\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/email.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/extract.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/message_file.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/showfiles.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/sublist.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"common/workspace.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/msgapi/message_utils_wwiv.h\"\n#include \"sdk/net/networks.h\"\n\n#include <cstdint>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// Implementation\nstatic bool same_email(tmpmailrec& tm, const mailrec& m) {\n  if (tm.fromsys != m.fromsys || tm.fromuser != m.fromuser || m.tosys != 0 ||\n      m.touser != a()->sess().user_num() || tm.daten != m.daten || tm.index == -1 ||\n      memcmp(&tm.msg, &m.msg, sizeof(messagerec)) != 0) {\n    return false;\n  }\n  return true;\n}\n\nstatic void purgemail(std::vector<tmpmailrec>& mloc, int mw, int* curmail, mailrec* m1, slrec* sl) {\n  mailrec m{};\n\n  if (m1->anony & anony_sender && (sl->ability & ability_read_email_anony) == 0) {\n    bout.outstr(\"|#5Delete all mail to you from this user? \");\n  } else {\n    bout.outstr(\"|#5Delete all mail to you from \");\n    if (m1->fromsys) {\n      bout.print(\"#{} @{}? \", m1->fromuser, m1->fromsys);\n    } else {\n      if (m1->fromuser == 65535) {\n        bout.outstr(\"Networks? \");\n      } else {\n        bout.print(\"#{}? \", m1->fromuser);\n      }\n    }\n  }\n  if (bin.yesno()) {\n    auto pFileEmail(OpenEmailFile(true));\n    if (!pFileEmail->IsOpen()) {\n      return;\n    }\n    for (int i = 0; i < mw; i++) {\n      if (mloc[i].index >= 0) {\n        pFileEmail->Seek(mloc[i].index * sizeof(mailrec), File::Whence::begin);\n        pFileEmail->Read(&m, sizeof(mailrec));\n        if (same_email(mloc[i], m)) {\n          if (m.fromuser == m1->fromuser && m.fromsys == m1->fromsys) {\n            bout.print(\"Deleting mail msg #{}\\r\\n\", i + 1);\n            delmail(*pFileEmail, mloc[i].index);\n            mloc[i].index = -1;\n            if (*curmail == i) {\n              ++(*curmail);\n            }\n          }\n        }\n      } else {\n        if (*curmail == i) {\n          ++(*curmail);\n        }\n      }\n    }\n    pFileEmail->Close();\n  }\n}\n\nstatic void resynch_email(std::vector<tmpmailrec>& mloc, int mw, int rec, mailrec* m, bool del,\n                          uint16_t stat) {\n  int i;\n  mailrec m1{};\n\n  auto pFileEmail(OpenEmailFile(del || stat));\n  if (pFileEmail->IsOpen()) {\n    const auto mfl = static_cast<File::size_type>(pFileEmail->length() / sizeof(mailrec));\n\n    for (i = 0; i < mw; i++) {\n      if (mloc[i].index >= 0) {\n        mloc[i].index = -2;\n      }\n    }\n\n    int mp = 0;\n\n    for (i = 0; i < mfl; i++) {\n      pFileEmail->Seek(i * sizeof(mailrec), File::Whence::begin);\n      pFileEmail->Read(&m1, sizeof(mailrec));\n\n      if (m1.tosys == 0 && m1.touser == a()->sess().user_num()) {\n        for (int i1 = mp; i1 < mw; i1++) {\n          if (same_email(mloc[i1], m1)) {\n            mloc[i1].index = static_cast<int16_t>(i);\n            mp = i1 + 1;\n            if (i1 == rec) {\n              *m = m1;\n            }\n            break;\n          }\n        }\n      }\n    }\n\n    for (i = 0; i < mw; i++) {\n      if (mloc[i].index == -2) {\n        mloc[i].index = -1;\n      }\n    }\n\n    if (stat && !del && (mloc[rec].index >= 0)) {\n      m->status |= stat;\n      pFileEmail->Seek(mloc[rec].index * sizeof(mailrec), File::Whence::begin);\n      pFileEmail->Write(m, sizeof(mailrec));\n    }\n    if (del && (mloc[rec].index >= 0)) {\n      delmail(*pFileEmail, mloc[rec].index);\n      mloc[rec].index = -1;\n    }\n    pFileEmail->Close();\n  } else {\n    mloc[rec].index = -1;\n  }\n}\n\n// used in qwk1.cpp\nbool read_same_email(std::vector<tmpmailrec>& mloc, int mw, int rec, mailrec& m, bool del,\n                     uint16_t stat) {\n  if (at(mloc, rec).index < 0) {\n    return false;\n  }\n\n  auto file = OpenEmailFile(del || stat);\n  if (!file->IsOpen()) {\n    LOG(ERROR) << \"read_same_email: Failed to open email file.\";\n    return false;\n  }\n  file->Seek(mloc[rec].index * sizeof(mailrec), File::Whence::begin);\n  file->Read(&m, sizeof(mailrec));\n\n  if (!same_email(mloc[rec], m)) {\n    file->Close();\n    a()->status_manager()->reload_status();\n    if (a()->emchg_) {\n      resynch_email(mloc, mw, rec, &m, del, stat);\n    } else {\n      mloc[rec].index = -1;\n    }\n  } else {\n    if (stat && !del && mloc[rec].index >= 0) {\n      m.status |= stat;\n      file->Seek(mloc[rec].index * sizeof(mailrec), File::Whence::begin);\n      file->Write(&m, sizeof(mailrec));\n    }\n    if (del) {\n      delmail(*file, mloc[rec].index);\n      mloc[rec].index = -1;\n    }\n    file->Close();\n  }\n  return mloc[rec].index != -1;\n}\n\nstatic void add_netsubscriber(const Network& net, int network_number, int system_number) {\n  if (!valid_system(system_number)) {\n    system_number = 0;\n  }\n\n  bout.nl();\n  bout.outstr(\"|#1Adding subscriber to subscriber list...\\r\\n\\n\");\n  bout.outstr(\"|#2SubType: \");\n  const auto subtype = bin.input(7, true);\n  if (subtype.empty()) {\n    return;\n  }\n  const auto fn = FilePath(net.dir, StrCat(\"n\", subtype, \".net\"));\n  if (!File::Exists(fn)) {\n    bout.nl();\n    bout.print(\"|#6Subscriber file not found: {}\\r\\n\", fn.string());\n    return;\n  }\n  bout.nl();\n  if (system_number) {\n    bout.print(\"Add @{}.{} to subtype {}?\", system_number, net.name, subtype);\n  }\n  if (!system_number || !bin.noyes()) {\n    bout.outstr(\"|#2System Number: \");\n    const auto s = bin.input(5, true);\n    if (s.empty()) {\n      return;\n    }\n    system_number = to_number<int>(s);\n    if (!valid_system(system_number)) {\n      bout.print(\"@{} is not a valid system in {}.\\r\\n\\r\\n\", system_number, net.name);\n      return;\n    }\n  }\n  TextFile host_file(fn, \"a+t\");\n  if (host_file.IsOpen()) {\n    host_file.Write(fmt::sprintf(\"%u\\n\", system_number));\n    host_file.Close();\n    // TODO find replacement for autosend.exe\n    if (File::Exists(\"autosend.exe\")) {\n      bout.outstr(\"AutoSend starter messages? \");\n      if (bin.yesno()) {\n        const auto autosend = FilePath(a()->bindir(), \"autosend\");\n        const auto cmd = StrCat(autosend.string(), \" \", subtype, \" \", system_number, \" .\", network_number);\n        wwiv::bbs::CommandLine cl(cmd);\n        ExecuteExternalProgram(cl, EFLAG_NONE);\n      }\n    }\n  }\n}\n\nvoid delete_attachment(unsigned long daten, int forceit) {\n  filestatusrec fsr{};\n\n  auto found = false;\n  File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n  if (fileAttach.Open(File::modeBinary | File::modeReadWrite)) {\n    auto l = fileAttach.Read(&fsr, sizeof(fsr));\n    while (l > 0 && !found) {\n      if (daten == static_cast<unsigned long>(fsr.id)) {\n        found = true;\n        fsr.id = 0;\n        fileAttach.Seek(static_cast<long>(sizeof(filestatusrec)) * -1L, File::Whence::current);\n        fileAttach.Write(&fsr, sizeof(filestatusrec));\n        auto delfile = true;\n        if (!forceit) {\n          if (so()) {\n            bout.outstr(\"|#5Delete attached file? \");\n            delfile = bin.yesno();\n          }\n        }\n        if (delfile) {\n          File::Remove(FilePath(a()->GetAttachmentDirectory(), fsr.filename));\n        } else {\n          bout.print(\"\\r\\nOrphaned attach '{}' remains in '{}'\\r\\n\", fsr.filename, a()->GetAttachmentDirectory());\n          bout.pausescr();\n        }\n      } else {\n        l = fileAttach.Read(&fsr, sizeof(filestatusrec));\n      }\n    }\n    fileAttach.Close();\n  }\n}\n\nstatic std::string from_name(const mailrec& m, const Network& net, const slrec& sl, int nn) {\n  if (m.anony & anony_sender && (sl.ability & ability_read_email_anony) == 0) {\n    return \">UNKNOWN<\";\n  }\n  auto csne = next_system(m.fromsys);\n  const std::string system_name = csne ? csne->name : \"Unknown System\";\n  if (m.fromsys == 0) {\n    if (m.fromuser == 65535) {\n      if (nn != 255) {\n        return net.name;\n      }\n    } else {\n      return a()->names()->UserName(m.fromuser);\n    }\n  } else {\n//    if (nn == 255) {\n//      return fmt::format(\"#{} @{}.\", m.fromuser, m.fromsys, net.name);\n//    }\n    if (auto o = readfile(&m.msg, \"email\")) {\n      if (const auto idx = o.value().find('\\r'); idx != std::string::npos) {\n        const std::string from = o.value().substr(0, idx);\n        if (m.fromsys == INTERNET_EMAIL_FAKE_OUTBOUND_NODE || m.fromsys == FTN_FAKE_OUTBOUND_NODE) {\n          return stripcolors(from);\n        }\n        return fmt::format(\"{} {}@{}.{} ({})\", stripcolors(wwiv::common::strip_to_node(from)),\n                           m.fromuser, m.fromsys, net.name, system_name);\n      }\n    } else {\n      if (ssize(a()->nets()) > 1) {\n        return fmt::format(\"#{} @{}.{} ({})\", m.fromuser, m.fromsys, net.name, system_name);\n      }\n    }\n  }\n  return fmt::format(\"#{} @{} ({})\", m.fromuser, m.fromsys, system_name);\n}\n\nstatic std::tuple<Network, int> network_and_num(const mailrec& m) {\n  Network net{};\n  auto nn = network_number_from(&m);\n  if (nn < a()->nets().size()) {\n    net = a()->nets()[nn];\n  } else {\n    net.sysnum = static_cast<uint16_t>(-1);\n    net.type = network_type_t::unknown;\n    net.name = fmt::format(\"<net #{}>\", nn);\n    nn = 255;\n  }\n  return std::make_tuple(net, nn);\n}\n\nvoid readmail(bool newmail_only) {\n  int i1, curmail = 0;\n  bool done;\n  mailrec m{};\n  mailrec m1{};\n  char ch;\n  filestatusrec fsr{};\n\n  a()->emchg_ = false;\n\n  bool next = false, abort = false;\n  std::vector<tmpmailrec> mloc;\n  write_inst(INST_LOC_RMAIL, 0, INST_FLAGS_NONE);\n  auto sl = a()->config()->sl(a()->sess().effective_sl());\n  auto mw = 0;\n  {\n    auto file(OpenEmailFile(false));\n    if (!file->IsOpen()) {\n      bout.outstr(\"\\r\\n\\nNo mail file exists!\\r\\n\\n\");\n      return;\n    }\n    auto mfl = static_cast<File::size_type>(file->length() / sizeof(mailrec));\n    for (int i = 0; i < mfl && mw < MAXMAIL; i++) {\n      file->Seek(i * sizeof(mailrec), File::Whence::begin);\n      file->Read(&m, sizeof(mailrec));\n      if (m.tosys == 0 && m.touser == a()->sess().user_num()) {\n        tmpmailrec r = {};\n        r.index = static_cast<int16_t>(i);\n        r.fromsys = m.fromsys;\n        r.fromuser = m.fromuser;\n        r.daten = m.daten;\n        r.msg = m.msg;\n        mloc.emplace_back(r);\n        mw++;\n      }\n    }\n    file->Close();\n  }\n  a()->user()->email_waiting(mw);\n  if (mloc.empty()) {\n    bout.outstr(\"\\r\\n\\n|#3You have no mail.\\r\\n\\n\");\n    return;\n  }\n  if (mloc.size() == 1) {\n    curmail = 0;\n  } else {\n    bout.outstr(\"\\r\\n\\n|#2You have mail from:\\r\\n\");\n    std::string box = okansi() ? \"\\xDA\\xC0\\xBF\\xD9\\xC4\\xB3\" : \"++++-|\";\n//   0  upperleft 1 lowerleft 2 upperright 3 lowerright 4 = - 5 = |\"\n    bout.print(\"|#7\\xDA{}\\xBF\\r\\n\", std::string(a()->user()->screen_width() - 3, box[4]));\n    for (auto i = 0; i < mw && !abort; i++) {\n      if (!read_same_email(mloc, mw, i, m, false, 0)) {\n        continue;\n      }\n      if (newmail_only && (m.status & status_seen)) {\n        ++curmail;\n        continue;\n      }\n\n      auto [net, nn] = network_and_num(m);\n      set_net_num(nn);\n      const auto current_line =\n          fmt::format(\"|#7{}|#2{:>3}{}|#1{:<45.45}|#7{} |#1{:<25.25} |#7{}\", box[5], i + 1, (m.status & status_seen ? \" \" : \"|#3*\"),\n                      from_name(m, net, sl, nn), box[5], stripcolors(m.title),box[5]);\n      bout.bpla(current_line, &abort);\n    }\n    bout.print(\"|#7\\xC0{}\\xD9\\r\\n\", std::string(a()->user()->screen_width() - 3, box[4]));\n//    bout.print(\"|#9{}\\r\\n\", std::string(a()->user()->screen_width() - 1, '-'));\n    bout.outstr(\"|#9(|#2Q|#9=|#2Quit|#9, |#2Enter|#9=|#2First Message|#9) \\r\\n\");\n    bout.outstr(\"|#9Enter message number: \");\n    const auto res = bin.input_number_hotkey(curmail + 1, {'Q'}, curmail + 1, mw, true);\n    if (res.key == 'Q') { \n      return;\n    }\n    if (res.num > 0 && !newmail_only) {\n      if (res.num <= mw) {\n        curmail = res.num - 1;\n      } else {\n        curmail = 0;\n      }\n    }\n  }\n  done = false;\n\n  do {\n    bool okmail;\n    auto attach_exists = false;\n    auto found = false;\n    abort = false;\n    bout.nl(2);\n    next = false;\n\n    if (std::string title = m.title; !read_same_email(mloc, mw, curmail, m, false, 0)) {\n      title += \">>> MAIL DELETED <<<\";\n      okmail = false;\n      bout.nl(3);\n    } else {\n      strcpy(a()->sess().irt_, m.title);\n      abort = false;\n      auto readit  = ((ability_read_email_anony & sl.ability) != 0);\n      okmail = true;\n      if (m.fromsys && !m.fromuser) {\n        grab_user_name(&(m.msg), \"email\", network_number_from(&m));\n      } else {\n        a()->net_email_name.clear();\n      }\n      if (m.status & status_source_verified) {\n        if (int sv_type = source_verfied_type(&m); sv_type > 0) {\n          title += StrCat(\"-=> Source Verified Type \", sv_type);\n          if (sv_type == 1) {\n            title += \" (From NC)\";\n          } else if (sv_type > 256 && sv_type < 512) {\n            title += StrCat(\" (From GC-\", sv_type - 256, \")\");\n          }\n        } else {\n          title += \"-=> Source Verified (unknown type)\";\n        }\n      }\n      auto [net, nn] = network_and_num(m);\n      set_net_num(nn);\n      int nFromSystem = 0;\n      int nFromUser = 0;\n      if (nn != 255) {\n        nFromSystem = m.fromsys;\n        nFromUser = m.fromuser;\n      }\n      if (!abort) {\n        // read_type2_message will parse out the title and other fields of the\n        // message, including sender name (which is all we have for FTN messages).\n        // We need to get the full header before that and pass it into this\n        // method to display it.\n\n        // TODO(rushfan): Should we fail here vs. value_or? I don't see any graceful way to do that.\n        auto msg = read_type2_message(&m.msg, m.anony & 0x0f, readit ? true : false, \"email\",\n                                      nFromSystem, nFromUser)\n                       .value_or(Type2MessageData{});\n\n        msg.message_area = \"Personal E-Mail\";\n        msg.title = m.title;\n        msg.message_number = curmail + 1;\n        msg.total_messages = mw;\n        // We set this to false since we do *not* want to use the\n        // command handling from the full screen reader.\n        msg.use_msg_command_handler = false;\n        if (a()->current_net().type == network_type_t::ftn) {\n          // Set email name to be the to address.\n          // This is also done above in grab_user_name, but we should stop using\n          // a()->net_email_name\n          a()->net_email_name = msg.from_user_name;\n        }\n        int fake_msgno = -1;\n        display_type2_message(fake_msgno, msg, &next);\n        if (!(m.status & status_seen)) {\n          read_same_email(mloc, mw, curmail, m, false, status_seen);\n        }\n      }\n      found = false;\n      attach_exists = false;\n      if (m.status & status_file) {\n        File fileAttach(FilePath(a()->config()->datadir(), ATTACH_DAT));\n        if (fileAttach.Open(File::modeBinary | File::modeReadOnly)) {\n          auto l1 = fileAttach.Read(&fsr, sizeof(fsr));\n          while (l1 > 0 && !found) {\n            if (m.daten == static_cast<uint32_t>(fsr.id)) {\n              found = true;\n              if (File::Exists(FilePath(a()->GetAttachmentDirectory(), fsr.filename))) {\n                bout.print(\"'T' to download attached file \\\"{}\\\" ({} bytes).\\r\\n\", fsr.filename,\n                           fsr.numbytes);\n                attach_exists = true;\n              } else {\n                bout.print(\"Attached file \\\"{} ({} bytes) is missing!\\r\\n\", fsr.filename,\n                           fsr.numbytes);\n              }\n            }\n            if (!found) {\n              l1 = fileAttach.Read(&fsr, sizeof(fsr));\n            }\n          }\n          if (!found) {\n            bout.outstr(\"File attached but attachment data missing.  Alert sysop!\\r\\n\");\n          }\n        } else {\n          bout.outstr(\"File attached but attachment data missing.  Alert sysop!\\r\\n\");\n        }\n        fileAttach.Close();\n      }\n    }\n\n    do {\n      char mnu[81];\n      int delme;\n      std::string allowable;\n      write_inst(INST_LOC_RMAIL, 0, INST_FLAGS_NONE);\n      auto [net, nn] = network_and_num(m);\n      set_net_num(nn);\n      i1 = 1;\n      if (!a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n        strcpy(mnu, EMAIL_NOEXT);\n        bout.outstr(\"|#2Mail {?} : \");\n      }\n      if (so()) {\n        strcpy(mnu, SY_EMAIL_NOEXT);\n        if (a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n          bout.outstr(\"|#2Mail |#7{|#1QSRIDAF?-+GEMZPVUOLCNY@|#7} |#2: \");\n        }\n        allowable = \"QSRIDAF?-+GEMZPVUOLCNY@\";\n      } else {\n        if (cs()) {\n          strcpy(mnu, CS_EMAIL_NOEXT);\n          if (a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n            bout.outstr(\"|#2Mail |#7{|#1QSRIDAF?-+GZPVUOCY@|#7} |#2: \");\n          }\n          allowable = \"QSRIDAF?-+GZPVUOCY@\";\n        } else {\n          if (!okmail) {\n            strcpy(mnu, RS_EMAIL_NOEXT);\n            if (a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n              bout.outstr(\"|#2Mail |#7{|#1QI?-+GY|#7} |#2: \");\n            }\n            allowable = \"QI?-+G\";\n          } else {\n            strcpy(mnu, EMAIL_NOEXT);\n            if (a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n              bout.outstr(\"|#2Mail |#7{|#1QSRIDAF?+-GY@|#7} |#2: \");\n            }\n            allowable = \"QSRIDAF?-+GY@\";\n          }\n        }\n      }\n      if ((m.status & status_file) && found && attach_exists) {\n        if (a()->HasConfigFlag(OP_FLAGS_MAIL_PROMPT)) {\n          bout.outstr(\"\\b\\b|#7{|#1T|#7} |#2: |#0\");\n        }\n        allowable += \"T\";\n      }\n      ch = onek(allowable);\n      if (okmail && !read_same_email(mloc, mw, curmail, m, false, 0)) {\n        bout.outstr(\"\\r\\nMail got deleted.\\r\\n\\n\");\n        ch = 'R';\n      }\n      delme = 0;\n      switch (ch) {\n        int num_mail1;\n        int num_mail;\n      case 'T': {\n        bout.nl();\n        auto fn = FilePath(a()->GetAttachmentDirectory(), fsr.filename);\n        bool sentt;\n        bool abortt;\n        send_file(fn.string(), &sentt, &abortt, fsr.filename, -1, fsr.numbytes);\n        if (sentt) {\n          bout.outstr(\"\\r\\nAttached file sent.\\r\\n\");\n          sysoplog(fmt::sprintf(\"Downloaded %ldk of attached file %s.\",\n                                     (fsr.numbytes + 1023) / 1024, fsr.filename));\n        } else {\n          bout.outstr(\"\\r\\nAttached file not completely sent.\\r\\n\");\n          sysoplog(fmt::sprintf(\"Tried to download attached file %s.\", fsr.filename));\n        }\n        bout.nl();\n      } break;\n      case 'N':\n        if (m.fromuser == 1) {\n          add_netsubscriber(net, nn, m.fromsys);\n        } else {\n          add_netsubscriber(net, nn, 0);\n        }\n        break;\n      case 'E':\n        if (so() && okmail) {\n          if (auto o = readfile(&(m.msg), \"email\")) {\n            auto b = o.value();\n            extract_out(b, m.title);\n          }\n        }\n        i1 = 0;\n        break;\n      case 'Q':\n        done = true;\n        break;\n      case 'O': {\n        if (cs() && okmail && m.fromuser != 65535 && nn != 255) {\n          const auto gfilesdir = a()->config()->gfilesdir().string();\n          show_files(\"*.frm\", gfilesdir.c_str());\n          bout.outstr(\"|#2Which form letter: \");\n          auto user_input = bin.input(8, true);\n          if (user_input.empty()) {\n            break;\n          }\n          auto fn = FilePath(a()->config()->gfilesdir(), StrCat(user_input, \".frm\"));\n          if (!File::Exists(fn)) {\n            fn = FilePath(a()->config()->gfilesdir(), StrCat(\"form\", user_input, \".msg\"));\n          }\n          if (File::Exists(fn)) {\n            LoadFileIntoWorkspace(a()->context(), fn, true);\n            num_mail = a()->user()->feedback_sent() + a()->user()->email_sent() +\n                       a()->user()->email_net();\n            clear_quotes(a()->sess());\n            if (m.fromuser != 65535) {\n              email(m.title, m.fromuser, m.fromsys, false, m.anony);\n            }\n            num_mail1 = static_cast<long>(a()->user()->feedback_sent()) +\n                        static_cast<long>(a()->user()->email_sent()) +\n                        static_cast<long>(a()->user()->email_net());\n            if (num_mail != num_mail1) {\n              const auto userandnet =\n                  a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n              std::string msg;\n              if (m.fromsys != 0) {\n                msg = StrCat(a()->network_name(), \": \", userandnet);\n              } else {\n                msg = userandnet;\n              }\n              if (m.anony & anony_receiver) {\n                msg += \">UNKNOWN<\";\n              }\n              msg += \" read your mail on \";\n              msg += fulldate();\n              if (!(m.status & status_source_verified)) {\n                ssm(m.fromuser, m.fromsys, &net) << msg;\n              }\n              read_same_email(mloc, mw, curmail, m, true, 0);\n              ++curmail;\n              if (curmail >= mw) {\n                done = true;\n              }\n            } else {\n              // need instance\n              File::Remove(FilePath(a()->sess().dirs().temp_directory(), INPUT_MSG));\n            }\n          } else {\n            bout.outstr(\"\\r\\nFile not found.\\r\\n\\n\");\n            i1 = 0;\n          }\n        }\n      } break;\n      case 'G': {\n        bout.print(\"|#2Go to which (1-{}) ? |#0\", mw);\n        auto user_input = bin.input(3);\n        i1 = to_number<int>(user_input);\n        if (i1 > 0 && i1 <= mw) {\n          curmail = i1 - 1;\n          i1 = 1;\n        } else {\n          i1 = 0;\n        }\n      } break;\n      case 'I':\n      case '+':\n        ++curmail;\n        if (curmail >= mw) {\n          done = true;\n        }\n        break;\n      case '-':\n        if (curmail) {\n          --curmail;\n        }\n        break;\n      case 'R':\n        break;\n      case '?':\n        bout.printfile(mnu);\n        i1 = 0;\n        break;\n      case 'M':\n        if (!okmail) {\n          break;\n        }\n        if (so()) {\n          if (!a()->sess().IsUserOnline()) {\n            a()->set_current_user_sub_num(0);\n            a()->sess().SetCurrentReadMessageArea(0);\n            a()->sess().set_current_user_sub_conf_num(0);\n          }\n          tmp_disable_conf(true);\n          bout.nl();\n          std::string ss1;\n          do {\n            bout.outstr(\"|#2Move to which sub? \");\n            ss1 = mmkey(MMKeyAreaType::subs);\n            if (ss1[0] == '?') {\n              old_sublist();\n            }\n          } while ((!a()->sess().hangup()) && (ss1[0] == '?'));\n          auto i = -1;\n          if ((ss1[0] == 0) || a()->sess().hangup()) {\n            i1 = 0;\n            bout.nl();\n            tmp_disable_conf(false);\n            break;\n          }\n          for (i1 = 0; i1 < size_int(a()->usub); i1++) {\n            if (ss1 == a()->usub[i1].keys) {\n              i = i1;\n            }\n          }\n          if (i != -1) {\n            const auto& sub = a()->subs().sub(a()->usub[i].subnum);\n            if (!wwiv::bbs::check_acs(sub.post_acs)) {\n              bout.outstr(\"\\r\\nSorry, you don't have post access on that sub.\\r\\n\\n\");\n              i = -1;\n            }\n          }\n          if (i != -1) {\n            auto o = readfile(&(m.msg), \"email\");\n            if (!o) {\n              break;\n            }\n            const auto& b = o.value();\n\n            postrec p{};\n            strcpy(p.title, m.title);\n            p.anony = m.anony;\n            p.ownersys = m.fromsys;\n            a()->SetNumMessagesInCurrentMessageArea(p.owneruser);\n            p.owneruser = static_cast<uint16_t>(a()->sess().user_num());\n            p.msg = m.msg;\n            p.daten = m.daten;\n            p.status = 0;\n\n            iscan(i);\n            open_sub(true);\n            if (!a()->current_sub().nets.empty()) {\n              p.status |= status_pending_net;\n            }\n            p.msg.storage_type = static_cast<uint8_t>(a()->current_sub().storage_type);\n            savefile(b, &(p.msg), a()->current_sub().filename);\n            a()->status_manager()->Run([&](Status& status) {\n              p.qscan = status.next_qscanptr();\n            });\n            if (a()->GetNumMessagesInCurrentMessageArea() >= a()->current_sub().maxmsgs) {\n              int i2;\n              i1 = 1;\n              i2 = 0;\n              while (i2 == 0 && i1 <= a()->GetNumMessagesInCurrentMessageArea()) {\n                if ((get_post(i1)->status & status_no_delete) == 0) {\n                  i2 = i1;\n                }\n                ++i1;\n              }\n              if (i2 == 0) {\n                i2 = 1;\n              }\n              delete_message(i2);\n            }\n            add_post(&p);\n            a()->status_manager()->Run([&](Status& status) {\n              status.increment_msgs_today();\n              status.IncrementNumLocalPosts();\n            });\n            close_sub();\n            tmp_disable_conf(false);\n            iscan(a()->current_user_sub_num());\n            bout.outstr(\"\\r\\n\\n|#9Message moved.\\r\\n\\n\");\n            auto temp_num_msgs = a()->GetNumMessagesInCurrentMessageArea();\n            resynch(&temp_num_msgs, &p);\n            a()->SetNumMessagesInCurrentMessageArea(temp_num_msgs);\n          } else {\n            tmp_disable_conf(false);\n          }\n        } break;\n      case 'D': {\n        std::string message;\n        if (!okmail) {\n          break;\n        }\n        bout.outstr(\"|#5Delete this message? \");\n        if (!bin.noyes()) {\n          break;\n        }\n        if (m.fromsys != 0) {\n          message = StrCat(a()->network_name(), \": \",\n                           a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum));\n        } else {\n          message = a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n        }\n\n        if (m.anony & anony_receiver) {\n          message = \">UNKNOWN<\";\n        }\n\n        message += \" read your mail on \";\n        message += fulldate();\n        if (!(m.status & status_source_verified) && nn != 255) {\n          ssm(m.fromuser, m.fromsys, &net) << message;\n        }\n      } \n      [[fallthrough]];\n      case 'Z':\n        if (!okmail) {\n          break;\n        }\n        read_same_email(mloc, mw, curmail, m, true, 0);\n        ++curmail;\n        if (curmail >= mw) {\n          done = true;\n        }\n        found = false;\n        if (m.status & status_file) {\n          delete_attachment(m.daten, 1);\n        }\n        break;\n      case 'P':\n        if (!okmail) {\n          break;\n        }\n        purgemail(mloc, mw, &curmail, &m, &sl);\n        if (curmail >= mw) {\n          done = true;\n        }\n        break;\n      case 'F': {\n        if (!okmail) {\n          break;\n        }\n        if (m.status & status_multimail) {\n          bout.outstr(\"\\r\\nCan't forward multimail.\\r\\n\\n\");\n          break;\n        }\n        bout.nl(2);\n        if (okfsed() && a()->user()->auto_quote()) {\n          // TODO: optimize this since we also call readfile in grab_user_name\n          auto reply_to_name = grab_user_name(&(m.msg), \"email\", network_number_from(&m));\n          if (auto o = readfile(&(m.msg), \"email\")) {\n            auto_quote(o.value(), reply_to_name, quote_date_format_t::forward, m.daten,\n                       a()->context());\n            send_email();\n          }\n          break;\n        }\n\n        bout.outstr(\"|#2Forward to: \");\n        auto user_input = fixup_user_entered_email(bin.input(75));\n        auto [un, sn] = parse_email_info(user_input);\n        if (un || sn) {\n          if (ForwardMessage(&un, &sn)) {\n            bout.outstr(\"Mail forwarded.\\r\\n\");\n          }\n          if (un == a()->sess().user_num() && sn == 0 && !cs()) {\n            bout.outstr(\"Can't forward to yourself.\\r\\n\");\n            un = 0;\n          }\n          if (un || sn) {\n            std::string fwd_email_name;\n            if (sn) {\n              if (sn == 1 && un == 0 &&\n                  a()->current_net().type == network_type_t::internet) {\n                fwd_email_name = a()->net_email_name;\n              } else {\n                auto netname = size_int(a()->nets()) > 1 ? a()->network_name() : \"\";\n                fwd_email_name = username_system_net_as_string(un, a()->net_email_name,\n                                                                sn, netname);\n              }\n            } else {\n              set_net_num(nn);\n              fwd_email_name = a()->names()->UserName(un, a()->current_net().sysnum);\n            }\n            if (ok_to_mail(un, sn, false)) {\n              bout.print(\"|#5Forward to {}? \", fwd_email_name);\n              if (bin.yesno()) {\n                auto file = OpenEmailFile(true);\n                if (!file->IsOpen()) {\n                  break;\n                }\n                file->Seek(mloc[curmail].index * sizeof(mailrec), File::Whence::begin);\n                file->Read(&m, sizeof(mailrec));\n                if (!same_email(mloc[curmail], m)) {\n                  bout.outstr(\"Error, mail moved.\\r\\n\");\n                  break;\n                }\n                bout.outstr(\"|#5Delete this message? \");\n                if (bin.yesno()) {\n                  if (m.status & status_file) {\n                    delete_attachment(m.daten, 0);\n                  }\n                  delme = 1;\n                  m1.touser = 0;\n                  m1.tosys = 0;\n                  m1.daten = 0xffffffff;\n                  m1.msg.storage_type = 0;\n                  m1.msg.stored_as = 0xffffffff;\n                  file->Seek(mloc[curmail].index * sizeof(mailrec), File::Whence::begin);\n                  file->Write(&m1, sizeof(mailrec));\n                } else {\n                  std::string b;\n                  if (auto o = readfile(&(m.msg), \"email\")) {\n                    savefile(o.value(), &(m.msg), \"email\");\n                  }\n                }\n                m.status |= status_forwarded;\n                m.status |= status_seen;\n                file->Close();\n\n                auto net_num = a()->net_num();\n                const auto fwd_user_name =\n                    a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n                auto s = fmt::sprintf(\"\\r\\nForwarded to %s from %s.\", fwd_email_name, fwd_user_name);\n\n                set_net_num(nn);\n                net = a()->nets()[nn];\n                lineadd(&m.msg, s, \"email\");\n                s = StrCat(fwd_user_name, \" forwarded your mail to \", fwd_email_name);\n                if (!(m.status & status_source_verified)) {\n                  ssm(m.fromuser, m.fromsys, &net) << s;\n                }\n                set_net_num(net_num);\n                s = StrCat(\"Forwarded mail to \", fwd_email_name);\n                if (delme) {\n                  a()->user()->email_waiting(a()->user()->email_waiting() - 1);\n                }\n                bout.outstr(\"Forwarding: \");\n                ::EmailData email;\n                email.title = m.title;\n                email.msg = &m.msg;\n                email.anony = m.anony;\n                email.user_number = un;\n                email.system_number = sn;\n                email.an = true;\n                email.forwarded_code = delme; // this looks totally wrong to me...\n                email.silent_mode = false;\n\n                if (nn != 255 && nn == a()->net_num()) {\n                  email.from_user = m.fromuser;\n                  email.from_system = m.fromsys ? m.fromsys : a()->nets()[nn].sysnum;\n                  email.from_network_number = nn;\n                  sendout_email(email);\n                } else {\n                  email.set_from_user(a()->sess().user_num());\n                  email.from_system = a()->current_net().sysnum;\n                  email.from_network_number = a()->net_num();\n                  sendout_email(email);\n                }\n                ++curmail;\n                if (curmail >= mw) {\n                  done = true;\n                }\n              }\n            }\n          }\n        }\n        delme = 0;\n      } break;\n      case 'A':\n      case 'S':\n      case '@': {\n        if (!okmail) {\n          break;\n        }\n        num_mail = static_cast<long>(a()->user()->feedback_sent()) +\n                   static_cast<long>(a()->user()->email_sent()) +\n                   static_cast<long>(a()->user()->email_net());\n        if (nn == 255) {\n          bout.outstr(\"|#6Deleted network.\\r\\n\");\n          i1 = 0;\n          break;\n        }\n        if (m.fromuser != 65535) {\n          std::string reply_to_name;\n          // TODO: optimize this since we also call readfile in grab_user_name\n          reply_to_name = grab_user_name(&(m.msg), \"email\", network_number_from(&m));\n          if (auto o = readfile(&(m.msg), \"email\")) {\n            if (okfsed() && a()->user()->auto_quote()) {\n              // used to be 1 or 2 depending on s[0] == '@', but\n              // that's allowable now and @ was never in the beginning.\n              auto_quote(o.value(), reply_to_name, quote_date_format_t::email, m.daten,\n                         a()->context());\n            }\n            grab_quotes(o.value(), reply_to_name, a()->context());\n          }\n\n          if (ch == '@') {\n            bout.outstr(\"\\r\\n|#9Enter user name or number:\\r\\n:\");\n            auto user_email = fixup_user_entered_email(bin.input(75, true));\n            auto [un, sy] = parse_email_info(user_email);\n            if (un || sy) {\n              email(\"\", un, sy, false, 0);\n            }\n          } else {\n            email(\"\", m.fromuser, m.fromsys, false, m.anony);\n          }\n          clear_quotes(a()->sess());\n        }\n        num_mail1 = static_cast<long>(a()->user()->feedback_sent()) +\n                    static_cast<long>(a()->user()->email_sent()) +\n                    static_cast<long>(a()->user()->email_net());\n        if (ch == 'A' || ch == '@') {\n          if (num_mail != num_mail1) {\n            std::string message;\n            const auto name = a()->names()->UserName(a()->sess().user_num(), a()->current_net().sysnum);\n            if (m.fromsys != 0) {\n              message = a()->network_name();\n              message += \": \";\n              message += name;\n            } else {\n              message = name;\n            }\n            if (m.anony & anony_receiver) {\n              message = \">UNKNOWN<\";\n            }\n            message += \" read your mail on \";\n            message += fulldate();\n            if (!(m.status & status_source_verified)) {\n              ssm(m.fromuser, m.fromsys, &net) << message;\n            }\n            read_same_email(mloc, mw, curmail, m, true, 0);\n            ++curmail;\n            if (curmail >= mw) {\n              done = true;\n            }\n            found = false;\n            if (m.status & status_file) {\n              delete_attachment(m.daten, 0);\n            }\n          } else {\n            bout.outstr(\"\\r\\nNo mail sent.\\r\\n\\n\");\n            i1 = 0;\n          }\n        } else {\n          if (num_mail != num_mail1) {\n            if (!(m.status & status_replied)) {\n              read_same_email(mloc, mw, curmail, m, false, status_replied);\n            }\n            ++curmail;\n            if (curmail >= mw) {\n              done = true;\n            }\n          }\n        }\n      } break;\n      case 'U':\n      case 'V':\n      case 'C':\n        if (!okmail) {\n          break;\n        }\n        if (m.fromsys == 0 && cs() && m.fromuser != 65535) {\n          if (ch == 'V') {\n            valuser(m.fromuser);\n          }\n        } else if (cs()) {\n          bout.outstr(\"\\r\\nMail from another system.\\r\\n\\n\");\n        }\n        i1 = 0;\n        break;\n      case 'L': {\n        if (!so()) {\n          break;\n        }\n        bout.outstr(\"\\r\\n|#2Filename: \");\n        auto fileName = bin.input_path(50);\n        if (!fileName.empty()) {\n          bout.nl();\n          bout.outstr(\"|#5Allow editing? \");\n          if (bin.yesno()) {\n            bout.nl();\n            LoadFileIntoWorkspace(a()->context(), fileName, false);\n          } else {\n            bout.nl();\n            LoadFileIntoWorkspace(a()->context(), fileName, true);\n          }\n        }\n      } break;\n      case 'Y': // Add from here\n        if (curmail >= 0) {\n          auto o = readfile(&(m.msg), \"email\");\n          if (!o) {\n            break;\n          }\n          auto b = o.value();\n          bout.outstr(\"E-mail download -\\r\\n\\n|#2Filename: \");\n          auto downloadFileName = bin.input(12);\n          if (!okfn(downloadFileName)) {\n            break;\n          }\n          const auto fn = FilePath(a()->sess().dirs().temp_directory(), downloadFileName);\n          File::Remove(fn);\n          TextFile tf(fn, \"w\");\n          tf.Write(b);\n          tf.Close();\n          bool bSent;\n          bool bAbort;\n          send_file(fn.string(), &bSent, &bAbort, fn.string(), -1, ssize(b));\n          if (bSent) {\n            bout.outstr(\"E-mail download successful.\\r\\n\");\n            sysoplog(\"Downloaded E-mail\");\n          } else {\n            bout.outstr(\"E-mail download aborted.\\r\\n\");\n          }\n        }\n        break;\n      }\n    } while (!i1 && !a()->sess().hangup());\n  } while (!a()->sess().hangup() && !done);\n}\n\nint check_new_mail(int user_number) {\n  auto new_messages = 0; // number of new mail\n\n  if (auto file(OpenEmailFile(false)); file->Exists() && file->IsOpen()) {\n    const auto mfLength = static_cast<int>(file->length() / sizeof(mailrec));\n    for (auto i = 0; i < mfLength; i++) {\n      mailrec m{};\n      file->Seek(i * sizeof(mailrec), File::Whence::begin);\n      file->Read(&m, sizeof(mailrec));\n      if (m.tosys == 0 && m.touser == user_number) {\n        if (!(m.status & status_seen)) {\n          ++new_messages;\n        }\n      }\n    }\n    file->Close();\n  }\n  return new_messages;\n}\n"
  },
  {
    "path": "bbs/readmail.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_READMAIL_H\n#define INCLUDED_BBS_READMAIL_H\n\n#include \"sdk/vardec.h\"\n\n#include <vector>\n\n// USED IN READMAIL TO STORE EMAIL INFO\nstruct tmpmailrec {\n  int16_t index; // index into email.dat\n\n  uint16_t fromsys, // originating system\n      fromuser;     // originating user\n\n  daten_t daten; // date it was sent\n\n  messagerec msg; // where to find it\n};\n\nvoid readmail(bool newmail_only);\nint check_new_mail(int user_number);\n// Also used in QWK code.\nbool read_same_email(std::vector<tmpmailrec>& mloc, int mw, int rec, mailrec& m, bool del,\n                     uint16_t stat);\n\n#endif\n"
  },
  {
    "path": "bbs/runnable.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2005-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef __INCLUDED_RUNNABLE_H__\n#define __INCLUDED_RUNNABLE_H__\n\n\nclass Runnable {\n public:\n  /////////////////////////////////////////////////////////////////////////\n  //\n  // Member functions\n  //\n\n  Runnable() {}\n  virtual ~Runnable() {}\n  virtual int Run(int argc, char *argv[]) = 0;\n};\n\n#endif // __INCLUDED_RUNNABLE_H__\n"
  },
  {
    "path": "bbs/save_qscan.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/save_qscan.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"common/context.h\"\n#include \"sdk/config.h\"\n#include <cstdint>\n#include <memory>\n\nnamespace wwiv::bbs {\n\nSaveQScanPointers::SaveQScanPointers() : restore_(false) {\n  save_qsc_p_.reset(new uint32_t[a()->config()->max_subs()]);\n  for (int i = 0; i < a()->config()->max_subs(); i++) {\n    save_qsc_p_[i] = a()->sess().qsc_p[i];\n  }\n}\n\nSaveQScanPointers::~SaveQScanPointers() {\n  if (restore_) {\n    for (int i = 0; i < a()->config()->max_subs(); i++) {\n      a()->sess().qsc_p[i] = save_qsc_p_[i];\n    }\n  }\n}\n  \n}  // namespace\n\n"
  },
  {
    "path": "bbs/save_qscan.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_SAVE_QSCAN_H__\n#define __INCLUDED_SAVE_QSCAN_H__\n\n#include <cstdint>\n#include <memory>\n\nnamespace wwiv {\nnamespace bbs {\n\nclass SaveQScanPointers {\npublic:\n  SaveQScanPointers();\n  virtual ~SaveQScanPointers();\n  void restore() { restore_ = true; }\nprivate:\n  bool restore_;\n  std::unique_ptr<uint32_t[]> save_qsc_p_;\n};\n\n}  // namespace bbs\n}  // namespace wwiv\n\n#endif  // __INCLUDED_SAVE_QSCAN_H__\n"
  },
  {
    "path": "bbs/shortmsg.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WAxRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/shortmsg.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\n/*\n * Handles reading short messages. This is also where PackScan file requests\n * plug in, if such are used.\n */\nvoid rsm(int nUserNum, User *pUser, bool bAskToSaveMsgs) {\n  if (!pUser->ssm()) {\n    return;\n  }\n  DataFile<shortmsgrec> file(FilePath(a()->config()->datadir(), SMW_DAT),\n                             File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  if (!file) {\n    return;\n  }\n  auto bShownAnyMessage = false;\n  auto bShownAllMessages = true;\n  const auto number_of_records = file.number_of_records();\n  shortmsgrec sm{};\n  for (auto cur = 0; cur < number_of_records; cur++) {\n    file.Read(cur, &sm);\n    if (sm.touser == nUserNum && sm.tosys == 0) {\n      bout.print(\"|#9{}\\r\\n\", sm.message);\n      bool bHandledMessage = false;\n      bShownAnyMessage = true;\n      if (!so() || !bAskToSaveMsgs) {\n        bHandledMessage = true;\n      } else {\n        if (a()->HasConfigFlag(OP_FLAGS_CAN_SAVE_SSM)) {\n          if (!bHandledMessage && bAskToSaveMsgs) {\n            bout.outstr(\"|#5Would you like to save this notification? \");\n            bHandledMessage = !bin.yesno();\n          }\n        } else {\n          bHandledMessage = true;\n        }\n\n      }\n      if (bHandledMessage) {\n        sm.touser = 0;\n        sm.tosys = 0;\n        memset(&sm.message, 0, sizeof(sm.message));\n        file.Write(cur, &sm);\n      } else {\n        bShownAllMessages = false;\n      }\n    }\n  }\n  file.Close();\n  received_short_message(true);\n  if (bShownAnyMessage) {\n    bout.nl();\n  }\n  if (bShownAllMessages) {\n    pUser->clear_flag(User::SMW);\n  }\n}\n\nstatic void SendLocalShortMessage(int usernum, const std::string& messageText) {\n  User user;\n  a()->users()->readuser(&user, usernum);\n  if (!user.deleted()) {\n    File file(FilePath(a()->config()->datadir(), SMW_DAT));\n    if (!file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      return;\n    }\n    auto total_msgs_in_file = static_cast<int>(file.length() / sizeof(shortmsgrec));\n    auto new_msg_pos = total_msgs_in_file - 1;\n    shortmsgrec sm{};\n    if (new_msg_pos >= 0) {\n      file.Seek(new_msg_pos * sizeof(shortmsgrec), File::Whence::begin);\n      file.Read(&sm, sizeof(shortmsgrec));\n      while (sm.tosys == 0 && sm.touser == 0 && new_msg_pos > 0) {\n        --new_msg_pos;\n        file.Seek(new_msg_pos * sizeof(shortmsgrec), File::Whence::begin);\n        file.Read(&sm, sizeof(shortmsgrec));\n      }\n      if (sm.tosys != 0 || sm.touser != 0) {\n        new_msg_pos++;\n      }\n    } else {\n      new_msg_pos = 0;\n    }\n    sm.tosys = 0;  // 0 means local\n    sm.touser = static_cast<uint16_t>(usernum);\n    to_char_array(sm.message, messageText);\n    sm.message[80] = '\\0';\n    file.Seek(new_msg_pos * sizeof(shortmsgrec), File::Whence::begin);\n    file.Write(&sm, sizeof(shortmsgrec));\n    file.Close();\n    user.set_flag(User::SMW);\n    a()->users()->writeuser(&user, usernum);\n  }\n}\n\nstatic void SendRemoteShortMessage(int user_num, int system_num, const std::string& text,\n                                   const Network& net) {\n  net_header_rec nh{};\n  nh.tosys = static_cast<uint16_t>(system_num);\n  nh.touser = static_cast<uint16_t>(user_num);\n  nh.fromsys = net.sysnum;\n  nh.fromuser = static_cast<uint16_t>(a()->sess().user_num());\n  nh.main_type = main_type_ssm;\n  nh.minor_type = 0;\n  nh.list_len = 0;\n  nh.daten = daten_t_now();\n  auto msg = text;\n  if (msg.size() > 79) {\n    msg.resize(79);\n  }\n  nh.length = wwiv::stl::size_int(msg);\n  nh.method = 0;\n  File file(FilePath(net.dir, StrCat(\"p0\", a()->network_extension())));\n  file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  file.Seek(0L, File::Whence::end);\n  file.Write(&nh, sizeof(net_header_rec));\n  file.Write(msg.c_str(), msg.size());\n  file.Close();\n}\n\nssm::~ssm() {\n  try {\n    if (un_ == 65535 || un_ == 0 || sn_ == INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n      return;\n    }\n\n    const auto& s = stream_.str();\n\n    if (sn_ == 0) {\n      SendLocalShortMessage(un_, s);\n    } else {\n      if (net_ != nullptr) {\n        SendRemoteShortMessage(un_, sn_, s, *net_);\n      } else {\n        LOG(ERROR) << \"Tried to send remote SSM when net_ was null: \" << s;\n      }\n    }\n  } catch (const std::exception& e) {\n    LOG(INFO) << \"~ssm exception: \" << e.what();\n  }\n}\n\nstatic bool received_short_message_{false};\nbool received_short_message() { return received_short_message_; }\nvoid received_short_message(bool b) { received_short_message_ = b; }\n"
  },
  {
    "path": "bbs/shortmsg.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SHORTMSG_H\n#define INCLUDED_BBS_SHORTMSG_H\n\n#include <sstream>\n\nnamespace wwiv {\nnamespace sdk {\nclass User;\n\nnamespace net {\nclass Network;\n}\n}\n}\n\n\nclass ssm {\npublic:\n  explicit ssm(int un) : ssm(un, 0, nullptr) {}\n  ssm(int un, int sn, const wwiv::sdk::net::Network* net) : un_(un), sn_(sn), net_(net) {}\n  ~ssm();\n\n  template <typename T> ssm& operator<<(T const& value) {\n    stream_ << value;\n    return *this;\n  }\n\nprivate:\n  std::ostringstream stream_;\n  const int un_;\n  const int sn_{0};\n  const wwiv::sdk::net::Network* net_;\n};\n\nvoid rsm(int nUserNum, wwiv::sdk::User* pUser, bool bAskToSaveMsgs);\n\n// True if we've received a short message this session.\nbool received_short_message();\n\n// Set the state if a short message has been received this session.\nvoid received_short_message(bool b);\n\n#endif\n"
  },
  {
    "path": "bbs/showfiles.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/output.h\"\n#include \"core/findfiles.h\"\n#include \"core/strings.h\"\n#include \"core/wwivport.h\"\n#include \"fmt/printf.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n// Displays list of files matching file spec file_name in directory directory_name.\nvoid show_files(const char *file_name, const char *directory_name) {\n  char drive[MAX_PATH], direc[MAX_PATH], file[MAX_PATH], ext[MAX_PATH];\n\n  const auto c = okansi() ? '\\xCD' : '=';\n  bout.nl();\n#if defined (_WIN32)\n  _splitpath(directory_name, drive, direc, file, ext);\n#else\n  strcpy(direc, directory_name);\n  strcpy(drive, \"\");\n  strcpy(file, file_name);\n  strcpy(ext, \"\");\n#endif\n  const auto stripped_fn = ToStringLowerCase(stripfn(file_name));\n  const auto s = fmt::sprintf(\"|#7[|17|15 FileSpec: %s    Dir: %s%s |16|#7]\", stripped_fn, drive, direc);\n  int i = (a()->user()->screen_width() - 1) / 2 - size_without_colors(s) / 2;\n  bout.print(\"|#7{}{}\", std::string(i, c), s);\n  i = a()->user()->screen_width() - 1 - i - size_without_colors(s);\n  bout.print(\"|#7{}\", std::string(i, c));\n\n  auto full_pathname = FilePath(directory_name, ToStringLowerCase(stripfn(file_name)));\n  FindFiles ff(full_pathname, FindFiles::FindFilesType::files);\n  for (const auto& f : ff) {\n    full_pathname = StrCat(\"|#7[|#2\", aligns(f.name), \"|#7]|#1 \");\n    if (bout.wherex() > a()->user()->screen_width() - 15) {\n      bout.nl();\n    }\n    bout.outstr(full_pathname.string());\n  }\n\n  bout.nl();\n  bout.ansic(7);\n  bout.outstr(std::string(a()->user()->screen_width() - 1, c));\n  bout.nl(2);\n}\n"
  },
  {
    "path": "bbs/showfiles.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SHOWFILES_H__\n#define __INCLUDED_BBS_SHOWFILES_H__\n\nvoid show_files(const char *file_name, const char *directory_name);\n\n#endif  // __INCLUDED_BBS_SHOWFILES_H__"
  },
  {
    "path": "bbs/sr.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/sr.h\"\n\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/crc.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/srrcv.h\"\n#include \"bbs/srsend.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/numbers.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n\n#include <algorithm>\n#include <chrono>\n#include <optional>\n#include <string>\n#include <vector>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nunsigned char checksum = 0;\n\nvoid calc_CRC(unsigned char b) {\n  checksum = checksum + b;\n\n  crc ^= (static_cast<uint16_t>(b) << 8);\n  for (auto i = 0; i < 8; i++) {\n    if (crc & 0x8000) {\n      crc = crc << 1;\n      crc ^= 0x1021;\n    } else {\n      crc = crc << 1;\n    }\n  }\n}\n\n\nchar gettimeout(long ds, bool *abort) {\n  if (bin.bkbhitraw()) {\n    return bin.bgetchraw();\n  }\n\n  const seconds d(ds);\n  const auto d1 = steady_clock::now();\n  while (steady_clock::now() - d1 < d && !bin.bkbhitraw() && !a()->sess().hangup() && !*abort) {\n    if (bout.localIO()->KeyPressed()) {\n      if (const auto ch = bout.localIO()->GetChar(); ch == 0) {\n        bout.localIO()->GetChar();\n      } else if (ch == ESC) {\n        *abort = true;\n      }\n    }\n    a()->CheckForHangup();\n  }\n  return bin.bkbhitraw() ? bin.bgetchraw() : 0;\n}\n\n\nint extern_prot(int num, const std::filesystem::path& path, bool bSending) {\n  char s1[81];\n\n  if (bSending) {\n    bout.nl();\n    bout.outstr(\"-=> Beginning file transmission, Ctrl+X to abort.\\r\\n\");\n    if (num < 0) {\n      strcpy(s1, a()->over_intern[(-num) - 1].sendfn);\n    } else {\n      strcpy(s1, a()->externs[num].sendfn);\n    }\n  } else {\n    bout.nl();\n    bout.outstr(\"-=> Ready to receive, Ctrl+X to abort.\\r\\n\");\n    if (num < 0) {\n      strcpy(s1, a()->over_intern[(-num) - 1].receivefn);\n    } else {\n      strcpy(s1, a()->externs[num].receivefn);\n    }\n  }\n  // Use this since fdsz doesn't like 115200\n  const auto xfer_speed = std::to_string(std::min<int>(a()->modem_speed_, 57600));\n  const auto primary_port= fmt::format(\"{:d}\", a()->primary_port());\n  wwiv::bbs::CommandLine cl(s1);\n  cl.args(xfer_speed, primary_port, path.string(), xfer_speed);\n  if (!cl.empty()) {\n    a()->ClearTopScreenProtection();\n    auto at_exit = finally([] { a()->UpdateTopScreen(); });\n    bout.localIO()->Puts(fmt::format(\"{} is currently online at {} bps\\r\\n\\r\\n\",\n                                     a()->user()->name_and_number(), a()->modem_speed_));\n    bout.localIO()->Puts(cl.cmdline());\n    bout.localIO()->Puts(\"\\r\\n\");\n    if (a()->sess().incom()) {\n      return ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_PROT_SINGLE));\n    }\n  }\n  return -5;\n}\n\n\nbool ok_prot(int num, xfertype xt) {\n  if (xt == xfertype::xf_none) {\n    return false;\n  }\n\n  if (num > 0 && num < size_int(a()->externs) + WWIV_NUM_INTERNAL_PROTOCOLS) {\n    switch (num) {\n    case WWIV_INTERNAL_PROT_ASCII:\n      if (xt == xfertype::xf_down || xt == xfertype::xf_down_temp) {\n        return true;\n      }\n      break;\n    // Stop using the legacy XModem\n    case WWIV_INTERNAL_PROT_XMODEM:\n      return false;\n    case WWIV_INTERNAL_PROT_XMODEMCRC:\n    case WWIV_INTERNAL_PROT_YMODEM:\n    case WWIV_INTERNAL_PROT_ZMODEM:\n      if (xt != xfertype::xf_up_batch && xt != xfertype::xf_down_batch) {\n        return true;\n      }\n      if (num == WWIV_INTERNAL_PROT_YMODEM && xt == xfertype::xf_down_batch) {\n        return true;\n      }\n      if (num == WWIV_INTERNAL_PROT_ZMODEM && xt == xfertype::xf_down_batch) {\n        return true;\n      }\n      if (num == WWIV_INTERNAL_PROT_ZMODEM && xt == xfertype::xf_up_temp) {\n        return true;\n      }\n      if (num == WWIV_INTERNAL_PROT_ZMODEM && !a()->IsUseInternalZmodem()) {\n        // If AllowInternalZmodem is not true, don't allow it.\n        return false;\n      }\n      break;\n    case WWIV_INTERNAL_PROT_BATCH:\n      if (xt == xfertype::xf_up) {\n        for (const auto& e : a()->externs) {\n          if (e.receivebatchfn[0]) {\n            return true;\n          }\n        }\n      } else if (xt == xfertype::xf_down) {\n        for (const auto& e : a()->externs) {\n          if (e.sendbatchfn[0]) {\n            return true;\n          }\n        }\n      }\n      if (xt == xfertype::xf_up || xt == xfertype::xf_down) {\n        return true;\n      }\n      break;\n    default:\n      switch (xt) {\n      case xfertype::xf_up:\n      case xfertype::xf_up_temp:\n        if (a()->externs[num - WWIV_NUM_INTERNAL_PROTOCOLS].receivefn[0]) {\n          return true;\n        }\n        break;\n      case xfertype::xf_down:\n      case xfertype::xf_down_temp:\n        if (a()->externs[num - WWIV_NUM_INTERNAL_PROTOCOLS].sendfn[0]) {\n          return true;\n        }\n        break;\n      case xfertype::xf_up_batch:\n        if (a()->externs[num - WWIV_NUM_INTERNAL_PROTOCOLS].receivebatchfn[0]) {\n          return true;\n        }\n        break;\n      case xfertype::xf_down_batch:\n        if (a()->externs[num - WWIV_NUM_INTERNAL_PROTOCOLS].sendbatchfn[0]) {\n          return true;\n        }\n        break;\n      case xfertype::xf_none:\n        break;\n      }\n      break;\n    }\n  }\n  return false;\n}\n\nstatic char prot_key(int num) {\n  const auto s = prot_name(num);\n  return to_upper_case_char(s.front());\n}\n\nstd::string prot_name(int num) {\n  switch (num) {\n  case WWIV_INTERNAL_PROT_ASCII:\n    return \"ASCII\";\n  case WWIV_INTERNAL_PROT_XMODEM:\n    return \"Xmodem\";\n  case WWIV_INTERNAL_PROT_XMODEMCRC:\n    return \"Xmodem-CRC\";\n  case WWIV_INTERNAL_PROT_YMODEM:\n    return \"Ymodem\";\n  case WWIV_INTERNAL_PROT_BATCH:\n    return \"Batch\";\n  case WWIV_INTERNAL_PROT_ZMODEM:\n    return \"Zmodem (Internal)\";\n  default:\n    if (num >= WWIV_NUM_INTERNAL_PROTOCOLS &&\n        num < (size_int(a()->externs) + WWIV_NUM_INTERNAL_PROTOCOLS)) {\n      return a()->externs[num - WWIV_NUM_INTERNAL_PROTOCOLS].description;\n    }\n    return \"-=>NONE<=-\";\n  }\n\n}\n\nstruct AvailableProtocol {\n  int protocol_number{-1};\n  char key{0};\n  std::string name;\n};\n\nstatic constexpr char BASE_CHAR = '!';\n\nstatic char create_default_key(int i) {\n  if (i < 10) {\n    return static_cast<char>('0' + i);\n  }\n  return static_cast<char>(BASE_CHAR + i - 10);\n}\n\nclass AvailableProtocols {\npublic:\n  AvailableProtocols(xfertype t, const std::vector<newexternalrec>& e, wwiv::sdk::User& user)\n      : xt(t), externs(e), u(user) {\n    if (ok_prot(u.default_protocol(), xt)) {\n      default_protocol = u.default_protocol();\n    }\n\n    const auto maxprot = WWIV_NUM_INTERNAL_PROTOCOLS - 1 + size_int(a()->externs);\n    std::set<char> override_keys;\n    for (auto i = 1; i <= maxprot; i++) {\n      if (!ok_prot(i, xt)) {\n        continue;\n      }\n      auto key = prot_key(i);\n      if (auto [_, inserted] = override_keys.insert(key); !inserted) {\n        key = create_default_key(i);\n      }\n      allowed_keys.push_back(key);\n      AvailableProtocol a;\n      a.key = key;\n      a.name = prot_name(i);\n      a.protocol_number = i;\n      prots.emplace_back(a);\n    }\n\n    if (!default_protocol) {\n      default_protocol = only().value_or(0);\n    }\n    if (default_protocol) {\n      allowed_keys.push_back('\\r');\n    }\n  }\n\n  std::optional<int> only() {\n    if (prots.size() != 1) {\n      return std::nullopt;\n    }\n    return prots.front().protocol_number;\n  }\n\n  std::optional<int> protocol_for_key(char key) {\n    if (key == '0' || key == 'Q') {\n      return std::nullopt;\n    }\n    if (key == '\\r') {\n      return default_protocol;\n    }\n    for (const auto& p : prots) {\n      if (key == p.key) {\n        if (!u.default_protocol()) {\n          u.default_protocol(p.protocol_number);\n        }\n        return {p.protocol_number};\n      }\n    }\n    return std::nullopt;\n  }\n\n  int default_protocol{0};\n  std::string allowed_keys{\"Q?0\"};\n  std::vector<AvailableProtocol> prots;\n  xfertype xt{xfertype::xf_none};\n  const std::vector<newexternalrec> &externs;\n  wwiv::sdk::User& u;\n};\n\nbool show_protocols(const std::vector<AvailableProtocol>& prots) {\n  bout.outstr(\"|#1Available Protocols:\\r\\n\\n\");\n  bout.outstr(\"|#9[|#2Q|#9] |#9Abort Transfer(s)\\r\\n\");\n  bout.outstr(\"|#9[|#20|#9] |#9Don't Transfer\\r\\n\");\n\n  for (const auto& p : prots) {\n    bout.print(\"|#9[|#2{}|#9] |#9{}\\r\\n\", p.key, p.name);\n  }\n  bout.nl(2);\n  return true;\n}\n\nint get_protocol(xfertype xt) {\n  AvailableProtocols avail(xt, a()->externs, *a()->user());\n  show_protocols(avail.prots);\n\n  while (true) {\n    std::string prompt = \"Protocol (?=list) : \";\n\n    if (avail.default_protocol) {\n      const auto dname = prot_name(avail.default_protocol);\n      prompt = fmt::format(\"Protocol (?=list, <C/R>={}) : \", dname);\n    }\n\n    bout.print(\"|#7{}\", prompt);\n    if (const auto ch = onek(avail.allowed_keys); ch != '?') {\n      return avail.protocol_for_key(ch).value_or(-1);\n    }\n    show_protocols(avail.prots);\n  }\n}\n\nvoid ascii_send(const std::filesystem::path& path, bool* sent, double* percent) {\n\n  if (File file(path); file.Open(File::modeBinary | File::modeReadOnly)) {\n    auto file_size = file.length();\n    file_size = std::max<File::size_type>(file_size, 1);\n    char b[2048];\n    auto num_read = file.Read(b, 1024);\n    auto total_bytes = 0L;\n    auto abort = false;\n    while (num_read && !a()->sess().hangup() && !abort) {\n      auto buffer_pos = 0;\n      while (!a()->sess().hangup() && !abort && buffer_pos < num_read) {\n        a()->CheckForHangup();\n        bout.outchr(b[buffer_pos++]);\n        bin.checka(&abort);\n      }\n      total_bytes += buffer_pos;\n      bin.checka(&abort);\n      num_read = file.Read(b, 1024);\n    }\n    file.Close();\n    if (!abort) {\n      *sent = true;\n    } else {\n      *sent = false;\n      a()->user()->set_dk(a()->user()->dk() + bytes_to_k(total_bytes));\n    }\n    *percent = static_cast<double>(total_bytes) / static_cast<double>(file_size);\n  } else {\n    bout.nl();\n    bout.outstr(\"File not found.\\r\\n\\n\");\n    *sent = false;\n    *percent = 0.0;\n  }\n}\n\nvoid maybe_internal(const std::filesystem::path& path, bool* xferred, double* percent, bool bSend,\n                    int prot) {\n  if (!a()->over_intern.empty() \n      && a()->over_intern[prot - 2].othr & othr_override_internal\n      && ((bSend && a()->over_intern[prot - 2].sendfn[0]) ||\n          (!bSend && a()->over_intern[prot - 2].receivefn[0]))) {\n    if (extern_prot(-(prot - 1), path, bSend) == a()->over_intern[prot - 2].ok1) {\n      *xferred = true;\n    }\n    return;\n  }\n  if (!a()->sess().incom()) {\n    bout.print(\"Would use internal {}\\r\\n\", prot_name(prot));\n    return;\n  }\n\n  if (bSend) {\n    switch (prot) {\n    case WWIV_INTERNAL_PROT_XMODEM:\n      xymodem_send(path, xferred, percent, false, false, false);\n      break;\n    case WWIV_INTERNAL_PROT_XMODEMCRC:\n      xymodem_send(path, xferred, percent, true, false, false);\n      break;\n    case WWIV_INTERNAL_PROT_YMODEM:\n      xymodem_send(path, xferred, percent, true, true, false);\n      break;\n    case WWIV_INTERNAL_PROT_ZMODEM:\n      zmodem_send(path, xferred, percent);\n      break;\n    default: ;\n    }\n  } else {\n    switch (prot) {\n    case WWIV_INTERNAL_PROT_XMODEM:\n      xymodem_receive(path.filename().string(), xferred, false);\n      break;\n    case WWIV_INTERNAL_PROT_XMODEMCRC:\n      [[fallthrough]];\n    case WWIV_INTERNAL_PROT_YMODEM:\n      xymodem_receive(path.filename().string(), xferred, true);\n      break;\n    case WWIV_INTERNAL_PROT_ZMODEM:\n      *xferred = zmodem_receive(path);\n      break;\n    default:\n      break;\n    }\n  }\n}\n\nvoid send_file(const std::filesystem::path& path, bool* sent, bool* abort, const std::string& sfn,\n               int dn, long fs) {\n  *sent = false;\n  *abort = false;\n  int nProtocol;\n  if (fs < 0) {\n    nProtocol = get_protocol(xfertype::xf_none);\n  } else {\n    nProtocol = get_protocol(dn == -1 ? xfertype::xf_down_temp : xfertype::xf_down);\n  }\n  auto ok = false;\n  auto percent = 0.0;\n  auto opt = wwiv::sdk::files::FileName::FromUnaligned(sfn);\n  if (!opt) {\n    LOG(ERROR) << \"Failed to align filename: \" << sfn;\n    *abort = true;\n    bout.nl();\n    bout.print(\"Internal Error: Failed to align filename: {}\", sfn);\n    return;\n  }\n  if (a()->batch().contains_file(opt.value())) {\n    *sent = false;\n    if (nProtocol > 0) {\n      bout.nl();\n      bout.outstr(\"That file is already in the batch queue.\\r\\n\\n\");\n    } else if (nProtocol == -1) {\n      *abort = true;\n    }\n  } else {\n    switch (nProtocol) {\n    case -1:\n      *abort = true;\n      ok = true;\n      break;\n    case 0:\n      ok = true;\n      break;\n    case WWIV_INTERNAL_PROT_ASCII:\n      ascii_send(path, sent, &percent);\n      break;\n    case WWIV_INTERNAL_PROT_XMODEM:\n    case WWIV_INTERNAL_PROT_XMODEMCRC:\n    case WWIV_INTERNAL_PROT_YMODEM:\n    case WWIV_INTERNAL_PROT_ZMODEM:\n      maybe_internal(path, sent, &percent, true, nProtocol);\n      break;\n    case WWIV_INTERNAL_PROT_BATCH:\n      ok = true;\n      if (a()->batch().size() >= a()->max_batch) {\n        bout.nl();\n        bout.outstr(\"No room left in batch queue.\\r\\n\\n\");\n        *sent = false;\n        *abort = false;\n      } else {\n        if (nsl() <=\n            a()->batch().dl_time_in_secs() + time_to_transfer(fs, a()->modem_speed_).count()) {\n          bout.nl();\n          bout.outstr(\"Not enough time left in queue.\\r\\n\\n\");\n          *sent = false;\n          *abort = false;\n        } else {\n          if (dn == -1) {\n            bout.nl();\n            bout.outstr(\"Can't add temporary file to batch queue.\\r\\n\\n\");\n            *sent = false;\n            *abort = false;\n          } else {\n            const BatchEntry b(sfn, dn, fs, true);\n            a()->batch().AddBatch(b);\n            bout.nl(2);\n            bout.outstr(\"File added to batch queue.\\r\\n\");\n            bout.print(\"Batch: Files - {}  Time - {}\\r\\n\\r\\n\", a()->batch().size(), ctim(a()->batch().dl_time_in_secs()));\n            *sent = false;\n            *abort = false;\n          }\n        }\n      }\n      break;\n    default:\n      const int temp_prot = extern_prot(nProtocol - WWIV_NUM_INTERNAL_PROTOCOLS, path, true);\n      *abort = false;\n      if (temp_prot == a()->externs[nProtocol - WWIV_NUM_INTERNAL_PROTOCOLS].ok1) {\n        *sent = true;\n      }\n      break;\n    }\n  }\n  if (!*sent && !ok) {\n    if (percent == 1.0) {\n      *sent = true;\n    } else {\n      const auto fn = path.filename().string();\n      sysoplog(fmt::sprintf(\"Tried D/L \\\"%s\\\" %3.2f%%\", fn, percent * 100.0));\n    }\n  }\n}\n\nvoid receive_file(const std::filesystem::path& path, int* received, const std::string& sfn, int dn) {\n  switch (const auto prot = get_protocol(dn == -1 ? xfertype::xf_up_temp : xfertype::xf_up); prot) {\n  case 0:\n  case -1:\n    *received = 0;\n    break;\n  case WWIV_INTERNAL_PROT_XMODEM:\n  case WWIV_INTERNAL_PROT_XMODEMCRC:\n  case WWIV_INTERNAL_PROT_YMODEM:\n  case WWIV_INTERNAL_PROT_ZMODEM: {\n    bool xferred;\n    maybe_internal(path, &xferred, nullptr, false, prot);\n    *received = xferred ? 1 : 0;\n  }\n  break;\n  case WWIV_INTERNAL_PROT_BATCH:\n    if (dn != -1) {\n      if (a()->batch().size() >= a()->max_batch) {\n        bout.nl();\n        bout.outstr(\"No room left in batch queue.\\r\\n\\n\");\n        *received = 0;\n      } else {\n        *received = 2;\n        const BatchEntry b(sfn, dn, 0, false);\n        a()->batch().AddBatch(b);\n        bout.nl();\n        bout.outstr(\"File added to batch queue.\\r\\n\\n\");\n        bout.print(\"Batch upload: files - {}\\r\\n\\r\\n\", a()->batch().numbatchul());\n      }\n    } else {\n      bout.nl();\n      bout.outstr(\"Can't batch upload that.\\r\\n\\n\");\n    }\n    break;\n  default:\n    if (prot > WWIV_NUM_INTERNAL_PROTOCOLS - 1 && a()->sess().incom()) {\n      extern_prot(prot - WWIV_NUM_INTERNAL_PROTOCOLS, path, false);\n      *received = File::Exists(path);\n    }\n    break;\n  }\n}\n"
  },
  {
    "path": "bbs/sr.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SR_H\n#define INCLUDED_BBS_SR_H\n\n#include <filesystem>\n#include <string>\n\nenum class xfertype {\n  xf_up,\n  xf_down,\n  xf_up_temp,\n  xf_down_temp,\n  xf_up_batch,\n  xf_down_batch,\n  xf_none\n};\n\nvoid calc_CRC(unsigned char b);\nchar gettimeout(long ds, bool *abort);\nint extern_prot(int nProtocolNum, const std::filesystem::path& path, bool bSending);\nbool ok_prot(int nProtocolNum, xfertype xt);\nstd::string prot_name(int num);\nint  get_protocol(xfertype xt);\nvoid ascii_send(const std::filesystem::path& path, bool* sent, double* percent);\nvoid maybe_internal(const std::filesystem::path& path, bool* xferred, double* percent, bool bSend,\n                    int prot);\nvoid send_file(const std::filesystem::path& path, bool* sent, bool* abort,\n               const std::string& sfn, int dn, long fs);\nvoid receive_file(const std::filesystem::path& path, int* received, const std::string& sfn, int dn);\n\n\n#endif\n"
  },
  {
    "path": "bbs/srrcv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/crc.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/numbers.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/files/file_record.h\"\n#include <chrono>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\n\n// From zmwwiv.cpp\nbool NewZModemReceiveFile(const std::filesystem::path& path);\n\n// from sr.cpp\nextern unsigned char checksum;\n\nchar modemkey(int* tout) {\n  if (bin.bkbhitraw()) {\n    char ch = bin.bgetchraw();\n    calc_CRC(ch);\n    return ch;\n  }\n  if (*tout) {\n    return 0;\n  }\n  auto d1 = steady_clock::now();\n  while (steady_clock::now() - d1 < milliseconds(500) && !bin.bkbhitraw() && !a()->sess().hangup()) {\n    a()->CheckForHangup();\n  }\n  if (bin.bkbhitraw()) {\n    char ch = bin.bgetchraw();\n    calc_CRC(ch);\n    return ch;\n  }\n  *tout = 1;\n  return 0;\n}\n\nint receive_block(char* b, unsigned char* bln, bool use_crc) {\n  bool abort = false;\n  unsigned char ch = gettimeout(5, &abort);\n  int err = 0;\n\n  if (abort) {\n    return CF;\n  }\n  int tout = 0;\n  if (ch == 0x81) {\n    unsigned char bn = modemkey(&tout);\n    unsigned char bn1 = modemkey(&tout);\n    if ((bn ^ bn1) == 0xff) {\n      b[0] = bn;\n      *bln = bn;\n      return 8;\n    } else {\n      return 3;\n    }\n  } else if (ch == 1) {\n    unsigned char bn = modemkey(&tout);\n    unsigned char bn1 = modemkey(&tout);\n    if ((bn ^ bn1) != 0xff) {\n      err = 3;\n    }\n    *bln = bn;\n    crc = 0;\n    checksum = 0;\n    for (int i = 0; (i < 128) && (!a()->sess().hangup()); i++) {\n      b[i] = modemkey(&tout);\n    }\n    if (!use_crc && !a()->sess().hangup()) {\n      unsigned char cs1 = checksum;\n      bn1 = modemkey(&tout);\n      if (bn1 != cs1) {\n        err = 2;\n      }\n    } else if (!a()->sess().hangup()) {\n      int cc1 = crc;\n      bn = modemkey(&tout);\n      bn1 = modemkey(&tout);\n      if ((bn != (unsigned char)(cc1 >> 8)) || (bn1 != (unsigned char)(cc1 & 0x00ff))) {\n        err = 2;\n      }\n    }\n    if (tout) {\n      return 7;\n    }\n    return err;\n  } else if (ch == 2) {\n    unsigned char bn = modemkey(&tout);\n    unsigned char bn1 = modemkey(&tout);\n    crc = 0;\n    checksum = 0;\n    if ((bn ^ bn1) != 0xff) {\n      err = 3;\n    }\n    *bln = bn;\n    for (int i = 0; (i < 1024) && (!a()->sess().hangup()); i++) {\n      b[i] = modemkey(&tout);\n    }\n    if (!use_crc && !a()->sess().hangup()) {\n      unsigned char cs1 = checksum;\n      bn1 = modemkey(&tout);\n      if (bn1 != cs1) {\n        err = 2;\n      }\n    } else if (!a()->sess().hangup()) {\n      int cc1 = crc;\n      bn = modemkey(&tout);\n      bn1 = modemkey(&tout);\n      if ((bn != (unsigned char)(cc1 >> 8)) || (bn1 != (unsigned char)(cc1 & 0x00ff))) {\n        err = 2;\n      }\n    }\n    if (tout) {\n      return 7;\n    }\n    return (err == 0) ? 1 : err;\n  } else if (ch == CX) {\n    return 4;\n  } else if (ch == 4) {\n    return 5;\n  } else if (ch == 0) {\n    return 7;\n  } else {\n    return 9;\n  }\n}\n\nvoid xymodem_receive(const std::string& file_name, bool* received, bool use_crc) {\n  char b[1025], x[81], ch;\n  unsigned char bln;\n\n  File::Remove(file_name);\n  bool ok = true;\n  bool lastcan = false;\n  bool lasteot = false;\n  int nTotalErrors = 0;\n  int nConsecErrors = 0;\n\n  File file(file_name);\n  if (!file.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n    bout.outstr(\"\\r\\n\\nDOS error - Can't create file.\\r\\n\\n\");\n    *received = false;\n    return;\n  }\n  long pos = 0L;\n  long reallen = 0L;\n  time_t filedatetime = 0L;\n  unsigned int bn = 1;\n  bool done = false;\n  bout.outstr(\"\\r\\n-=> Ready to receive, Ctrl+X to abort.\\r\\n\");\n  int nOldXPos = bout.localIO()->WhereX();\n  int nOldYPos = bout.localIO()->WhereY();\n  bout.localIO()->PutsXY(52, 0, \"\\xB3 Filename :               \");\n  bout.localIO()->PutsXY(52, 1, \"\\xB3 Xfer Time:               \");\n  bout.localIO()->PutsXY(52, 2, \"\\xB3 File Size:               \");\n  bout.localIO()->PutsXY(52, 3, \"\\xB3 Cur Block: 1 - 1k        \");\n  bout.localIO()->PutsXY(52, 4, \"\\xB3 Consec Errors: 0         \");\n  bout.localIO()->PutsXY(52, 5, \"\\xB3 Total Errors : 0         \");\n  bout.localIO()->PutsXY(52, 6,\n                         \"\\xC0\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n                         \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\");\n  bout.localIO()->PutsXY(65, 0, stripfn(file_name));\n  int nNumStartTries = 0;\n  do {\n    if (nNumStartTries++ > 9) {\n      *received = false;\n      file.Close();\n      File::Remove(file_name);\n      return;\n    }\n    if (use_crc) {\n      bout.rputch('C');\n    } else {\n      bout.rputch(CU);\n    }\n\n    auto d1 = steady_clock::now();\n    while (steady_clock::now() - d1 < seconds(10) && !bin.bkbhitraw() && !a()->sess().hangup()) {\n      a()->CheckForHangup();\n      if (bout.localIO()->KeyPressed()) {\n        ch = bout.localIO()->GetChar();\n        if (ch == 0) {\n          bout.localIO()->GetChar();\n        } else if (ch == ESC) {\n          done = true;\n          ok = false;\n        }\n      }\n    }\n  } while (!bin.bkbhitraw() && !a()->sess().hangup());\n\n  int i = 0;\n  do {\n    bln = 255;\n    bout.localIO()->PutsXY(69, 4, fmt::sprintf(\"%d  \", nConsecErrors));\n    bout.localIO()->PutsXY(69, 5, std::to_string(nTotalErrors));\n    bout.localIO()->PutsXY(65, 3, fmt::sprintf(\"%ld - %ldk\", pos / 128 + 1, pos / 1024 + 1));\n    const auto tpb = time_to_transfer(reallen-pos, a()->modem_speed_);\n    const auto t = ctim(tpb);\n    if (reallen) {\n      bout.localIO()->PutsXY(65, 1, t);\n    }\n    i = receive_block(b, &bln, use_crc);\n    if (i == 0 || i == 1) {\n      if (bln == 0 && pos == 0L) {\n        int i1 = ssize(b) + 1;\n        int i3 = i1;\n        while (b[i3] >= '0' && b[i3] <= '9' && (i3 - i1) < 15) {\n          x[i3 - i1] = b[i3];\n          i3++;\n        }\n        x[i3 - i1] = '\\0';\n        reallen = to_number<long>(x);\n        bout.localIO()->PutsXY(\n            65, 2, fmt::sprintf(\"%ld - %ldk\", (reallen + 127) / 128, bytes_to_k(reallen)));\n        while ((b[i1] != SPACE) && (i1 < 64)) {\n          ++i1;\n        }\n        if (b[i1] == SPACE) {\n          ++i1;\n          while ((b[i1] >= '0') && (b[i1] <= '8')) {\n            filedatetime = (filedatetime * 8) + static_cast<long>(b[i1] - '0');\n            ++i1;\n          }\n        }\n        bout.rputch(CF);\n      } else if ((bn & 0x00ff) == static_cast<unsigned int>(bln)) {\n        file.Seek(pos, File::Whence::begin);\n        long lx = reallen - pos;\n        int i2 = (i == 0) ? 128 : 1024;\n        if ((static_cast<long>(i2) > lx) && reallen) {\n          i2 = static_cast<int>(lx);\n        }\n        file.Write(b, i2);\n        pos += static_cast<long>(i2);\n        ++bn;\n        bout.rputch(CF);\n      } else if (((bn - 1) & 0x00ff) == static_cast<unsigned int>(bln)) {\n        bout.rputch(CF);\n      } else {\n        bout.rputch(CX);\n        ok = false;\n        done = true;\n      }\n      nConsecErrors = 0;\n    } else if (i == 2 || i == 7 || i == 3) {\n      if (pos == 0L && reallen == 0L && use_crc) {\n        bout.rputch('C');\n      } else {\n        bout.rputch(CU);\n      }\n      ++nConsecErrors;\n      ++nTotalErrors;\n      if (nConsecErrors > 9) {\n        bout.rputch(CX);\n        ok = false;\n        done = true;\n      }\n    } else if (i == CF) {\n      ok = false;\n      done = true;\n      bout.rputch(CX);\n    } else if (i == 4) {\n      if (lastcan) {\n        ok = false;\n        done = true;\n        bout.rputch(CF);\n      } else {\n        lastcan = true;\n        bout.rputch(CU);\n      }\n    } else if (i == 5) {\n      lasteot = true;\n      if (lasteot) {\n        done = true;\n        bout.rputch(CF);\n      } else {\n        lasteot = true;\n        bout.rputch(CU);\n      }\n    } else if (i == 8) {\n      // This used to be where the filetype was set.\n      //*ft = bln;\n      bout.rputch(CF);\n      nConsecErrors = 0;\n    } else if (i == 9) {\n      bout.dump();\n    }\n    if (i != 4) {\n      lastcan = false;\n    }\n    if (i != 5) {\n      lasteot = false;\n    }\n  } while (!a()->sess().hangup() && !done);\n  bout.localIO()->GotoXY(nOldXPos, nOldYPos);\n  if (ok) {\n    file.Close();\n    if (filedatetime) {\n      file.set_last_write_time(filedatetime);\n    }\n    *received = true;\n  } else {\n    file.Close();\n    File::Remove(file_name);\n    *received = false;\n  }\n}\n\nbool zmodem_receive(const std::filesystem::path& path) {\n\n  const auto saved_mode = bout.remoteIO()->binary_mode();\n  bout.remoteIO()->set_binary_mode(true);\n  auto at_exit = finally([=] { bout.remoteIO()->set_binary_mode(saved_mode); });\n\n  auto newpath = path;\n  const auto local_filename(wwiv::sdk::files::unalign(path.filename().string()));\n  newpath.replace_filename(local_filename);\n  return NewZModemReceiveFile(newpath);\n}\n"
  },
  {
    "path": "bbs/srrcv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SRRCV_H\n#define INCLUDED_BBS_SRRCV_H\n\n#include <filesystem>\n#include <string>\n\nvoid xymodem_receive(const std::string& file_name, bool *received, bool use_crc);\nbool zmodem_receive(const std::filesystem::path& path);\n\n#endif\n"
  },
  {
    "path": "bbs/srsend.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n#include \"bbs/crc.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/xfer.h\"\n#include \"common/datetime.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/numbers.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/files/file_record.h\"\n\n#include <chrono>\n#include <cmath>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\n// TODO(rushfan) Make zmwwiv.h?\nbool NewZModemSendFile(const std::filesystem::path& path);\n\n// from sr.cpp\nextern unsigned char checksum;\n\nvoid send_block(char *b, int block_type, bool use_crc, char byBlockNumber) {\n  int nBlockSize = 0;\n\n  a()->CheckForHangup();\n  switch (block_type) {\n  case 5:\n    nBlockSize = 128;\n    bout.rputch(1);\n    break;\n  case 4:\n    bout.rputch('\\x81');\n    bout.rputch(byBlockNumber);\n    bout.rputch(byBlockNumber ^ 0xff);\n    break;\n  case 3:\n    bout.rputch(CX);\n    break;\n  case 2:\n    bout.rputch(4);\n    break;\n  case 1:\n    nBlockSize = 1024;\n    bout.rputch(2);\n    break;\n  case 0:\n    nBlockSize = 128;\n    bout.rputch(1);\n  }\n  if (block_type > 1 && block_type < 5) {\n    return;\n  }\n\n  bout.rputch(byBlockNumber);\n  bout.rputch(byBlockNumber ^ 0xff);\n  crc = 0;\n  checksum = 0;\n  for (int i = 0; i < nBlockSize; i++) {\n    const char ch = b[i];\n    bout.rputch(ch);\n    calc_CRC(ch);\n  }\n\n  if (use_crc) {\n    bout.rputch(static_cast<char>(crc >> 8));\n    bout.rputch(static_cast<char>(crc & 0x00ff));\n  } else {\n    bout.rputch(checksum);\n  }\n  bout.dump();\n}\n\nchar send_b(File &file, long pos, int block_type, char byBlockNumber, bool *use_crc, const wwiv::sdk::files::FileName& file_name,\n            int *terr, bool *abort) {\n  char b[1025];\n\n  int nb = 0;\n  if (block_type == 0) {\n    nb = 128;\n  }\n  if (block_type == 1) {\n    nb = 1024;\n  }\n  if (nb) {\n    file.Seek(pos, File::Whence::begin);\n    const int num_read = file.Read(b, nb);\n    for (auto i = num_read; i < nb; i++) {\n      b[i] = '\\0';\n    }\n  } else if (block_type == 5) {\n    memset(b, 0, 128);\n    nb = 128;\n    to_char_array(b, file_name.unaligned_filename());\n    // We needed this cast to (long) to compile with XCode 1.5 on OS X\n    const auto sb = fmt::sprintf(\"%ld %ld\", pos, static_cast<long>(file.last_write_time()));\n\n    strcpy(&b[strlen(b) + 1], sb.c_str());\n    b[127] = static_cast<unsigned char>((static_cast<int>(pos + 127) / 128) >> 8);\n    b[126] = static_cast<unsigned char>((static_cast<int>(pos + 127) / 128) & 0x00ff);\n  }\n  bool done = false;\n  int nNumErrors = 0;\n  char ch = 0;\n  do {\n    send_block(b, block_type, *use_crc, byBlockNumber);\n    ch = gettimeout(5, abort);\n    if (ch == 'C' && pos == 0) {\n      *use_crc = true;\n    }\n    if (ch == 6 || ch == CX) {\n      done = true;\n    } else {\n      ++nNumErrors;\n      ++(*terr);\n      if (nNumErrors >= 9) {\n        done = true;\n      }\n      bout.localIO()->PutsXY(69, 4, std::to_string(nNumErrors));\n      bout.localIO()->PutsXY(69, 5, std::to_string(*terr));\n    }\n  } while (!done && !a()->sess().hangup() && !*abort);\n\n  if (ch == 6) {\n    return 6;\n  }\n  if (ch == CX) {\n    return CX;\n  }\n  return CU;\n}\n\nbool okstart(bool *use_crc, bool *abort) {\n  auto d = steady_clock::now();\n  bool ok = false;\n  bool done = false;\n\n  const seconds s90(90);\n  while (steady_clock::now() - d < s90 && !done && !a()->sess().hangup() && !*abort) {\n    const char ch = gettimeout(91, abort);\n    if (ch == 'C') {\n      *use_crc = true;\n      ok = true;\n      done = true;\n    }\n    if (ch == CU) {\n      *use_crc = false;\n      ok = true;\n      done = true;\n    }\n    if (ch == CX) {\n      ok = false;\n      done = true;\n    }\n  }\n  return ok;\n}\n\nstatic int GetXYModemBlockSize(bool bBlockSize1K) {\n  return bBlockSize1K ? 1024 : 128;\n}\n\nvoid xymodem_send(const std::filesystem::path& path, bool *sent, double *percent, bool use_crc, bool use_ymodem,\n                  bool use_ymodemBatch) {\n  char ch;\n\n  long cp = 0L;\n  char byBlockNumber = 1;\n  bool abort = false;\n  int terr = 0;\n  wwiv::sdk::files::FileName fn(wwiv::sdk::files::align(path.filename().string()));\n\n  File file(path);\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    if (!use_ymodemBatch) {\n      bout.outstr(\"\\r\\nFile not found.\\r\\n\\n\");\n    }\n    *sent = false;\n    *percent = 0.0;\n    return;\n  }\n  auto file_size = file.length();\n  if (!file_size) {\n    file_size = 1;\n  }\n\n  const auto tpb = 12.656f / static_cast<double>(a()->modem_speed_);\n\n  if (!use_ymodemBatch) {\n    bout.outstr(\"\\r\\n-=> Beginning file transmission, Ctrl+X to abort.\\r\\n\");\n  }\n  int xx1 = bout.localIO()->WhereX();\n  int yy1 = bout.localIO()->WhereY();\n  bout.localIO()->PutsXY(52, 0, \"\\xB3 Filename :               \");\n  bout.localIO()->PutsXY(52, 1, \"\\xB3 Xfer Time:               \");\n  bout.localIO()->PutsXY(52, 2, \"\\xB3 File Size:               \");\n  bout.localIO()->PutsXY(52, 3, \"\\xB3 Cur Block: 1 - 1k        \");\n  bout.localIO()->PutsXY(52, 4, \"\\xB3 Consec Errors: 0         \");\n  bout.localIO()->PutsXY(52, 5, \"\\xB3 Total Errors : 0         \");\n  bout.localIO()->PutsXY(52, 6,\n                                       \"\\xC0\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\");\n  bout.localIO()->PutsXY(65, 0, path.filename().string());\n  bout.localIO()->PutsXY(65, 2,\n                         fmt::format(\"{} - {}k\", (file_size + 127) / 128, bytes_to_k(file_size)));\n\n  if (!okstart(&use_crc, &abort)) {\n    abort = true;\n  }\n  if (use_ymodem && !abort && !a()->sess().hangup()) {\n    ch = send_b(file, file_size, 5, 0, &use_crc, fn, &terr, &abort);\n    if (ch == CX) {\n      abort = true;\n    }\n    if (ch == CU) {\n      send_b(file, 0L, 3, 0, &use_crc, fn, &terr, &abort);\n      abort = true;\n    }\n  }\n  bool bUse1kBlocks = false;\n  while (!a()->sess().hangup() && !abort && cp < file_size) {\n    bUse1kBlocks = (use_ymodem) ? true : false;\n    if ((file_size - cp) < 128L) {\n      bUse1kBlocks = false;\n    }\n    bout.localIO()->PutsXY(65, 3, fmt::sprintf(\"%ld - %ldk\", cp / 128 + 1, cp / 1024 + 1));\n    const std::string t = ctim(std::lround((file_size - cp) * tpb));\n    bout.localIO()->PutsXY(65, 1, t);\n    bout.localIO()->PutsXY(69, 4, \"0\");\n\n    ch = send_b(file, cp, (bUse1kBlocks) ? 1 : 0, byBlockNumber, &use_crc, fn, &terr,\n                &abort);\n    if (ch == CX) {\n      abort = true;\n    } else if (ch == CU) {\n      sleep_for(seconds(1));\n      bout.dump();\n      send_b(file, 0L, 3, 0, &use_crc, fn, &terr, &abort);\n      abort = true;\n    } else {\n      ++byBlockNumber;\n      cp += GetXYModemBlockSize(bUse1kBlocks);\n    }\n  }\n  if (!a()->sess().hangup() && !abort) {\n    send_b(file, 0L, 2, 0, &use_crc, fn, &terr, &abort);\n  }\n  if (!abort) {\n    *sent = true;\n    *percent = 1.0;\n  } else {\n    *sent = false;\n    cp += GetXYModemBlockSize(bUse1kBlocks);\n    if (cp >= file_size) {\n      *percent = 1.0;\n    } else {\n      cp -= GetXYModemBlockSize(bUse1kBlocks);\n      *percent = static_cast<double>(cp) / static_cast<double>(file_size);\n    }\n  }\n  file.Close();\n  bout.localIO()->GotoXY(xx1, yy1);\n  if (*sent && !use_ymodemBatch) {\n    bout.outstr(\"-=> File transmission complete.\\r\\n\\n\");\n  }\n}\n\nvoid zmodem_send(const std::filesystem::path& path, bool *sent, double *percent) {\n  *sent = false;\n  *percent = 0.0;\n\n  const auto old_binary_mode = bout.remoteIO()->binary_mode();\n  bout.remoteIO()->set_binary_mode(true);\n  const auto result = NewZModemSendFile(path);\n  bout.remoteIO()->set_binary_mode(old_binary_mode);\n\n  if (result) {\n    *sent = true;\n    *percent = 100.0;\n  }\n}\n\n"
  },
  {
    "path": "bbs/srsend.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SRSEND_H__\n#define __INCLUDED_BBS_SRSEND_H__\n\n#include \"core/file.h\"\n#include \"sdk/files/file_record.h\"\n#include <filesystem>\n\nvoid send_block(char *b, int block_type, bool use_crc, char byBlockNumber);\nchar send_b(wwiv::core::File& file, long pos, int block_type, char byBlockNumber, bool* use_crc,\n            const wwiv::sdk::files::FileName& file_name, int* terr, bool* abort);\nbool okstart(bool *use_crc, bool *abort);\nvoid xymodem_send(const std::filesystem::path& path, bool* sent, double* percent, bool use_crc,\n                  bool use_ymodem, bool use_ymodemBatch);\nvoid zmodem_send(const std::filesystem::path& path, bool *sent, double *percent);\n\n#endif  // __INCLUDED_BBS_SRSEND_H__"
  },
  {
    "path": "bbs/ssh.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/ssh.h\"\n\n#ifdef _WIN32\n#define NOCRYPT                /* Disable include of wincrypt.h */\n#include <winsock2.h>\n#pragma comment(lib, \"Ws2_32.lib\")\n#include \"WS2tcpip.h\"\n#else\n\n#include <arpa/inet.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <unistd.h>\n\n#endif  // _WIN32\n\n#include \"cryptlib.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include <cstring>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <thread>\n\nusing wwiv::common::RemoteInfo;\nusing wwiv::common::RemoteSocketIO;\nusing wwiv::common::RemoteIO;\n\nnamespace wwiv::bbs{\n\nstruct socket_error: public std::runtime_error {\n  socket_error(const std::string& message): std::runtime_error(message) {}\n};\n\nstatic constexpr char WWIV_SSH_KEY_NAME[] = \"wwiv_ssh_server\";\n#define RETURN_IF_ERROR(s) { if (!cryptStatusOK(s)) return false; }\n#define OK(s) cryptStatusOK(s)\n\nstatic bool ssh_once_init() {\n  // This only should be called once.\n  int status = cryptInit();\n  return OK(status);\n}\n\nbool Key::Open() {\n  static bool once = ssh_once_init();\n  CRYPT_KEYSET keyset;\n  int status = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, filename_.c_str(), CRYPT_KEYOPT_NONE);\n  RETURN_IF_ERROR(status);\n\n  status = cryptGetPrivateKey(keyset, &context_, CRYPT_KEYID_NAME, WWIV_SSH_KEY_NAME, password_.c_str());\n  RETURN_IF_ERROR(status);\n\n  status = cryptKeysetClose(keyset);\n  RETURN_IF_ERROR(status);\n\n  return true;\n}\n\nbool Key::Create() {\n  static bool once = ssh_once_init();\n  CRYPT_KEYSET keyset;\n  int status = CRYPT_ERROR_INVALID;\n\n  status = cryptCreateContext(&context_, CRYPT_UNUSED, CRYPT_ALGO_RSA);\n  RETURN_IF_ERROR(status);\n\n  status = cryptSetAttributeString(context_, CRYPT_CTXINFO_LABEL, WWIV_SSH_KEY_NAME, strlen(WWIV_SSH_KEY_NAME));\n  RETURN_IF_ERROR(status);\n\n  // We want 8K keys.\n  //status = cryptSetAttribute(context_, CRYPT_CTXINFO_KEYSIZE, 2048 / 8);\n  //RETURN_IF_ERROR(status);\n\n  status = cryptGenerateKey(context_);\n  RETURN_IF_ERROR(status);\n\n  status = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, filename_.c_str(), CRYPT_KEYOPT_CREATE);\n  RETURN_IF_ERROR(status);\n\n  status = cryptAddPrivateKey(keyset, context_, password_.c_str());\n  RETURN_IF_ERROR(status);\n\n  status = cryptKeysetClose(keyset);\n  RETURN_IF_ERROR(status);\n\n  return true;\n}\n\nstatic bool GetSSHUserNameAndPassword(CRYPT_HANDLE session, std::string& username, std::string& password) {\n  char username_str[CRYPT_MAX_TEXTSIZE + 1];\n  char password_str[CRYPT_MAX_TEXTSIZE + 1];\n  int usernameLength = 0;\n  int passwordLength = 0;\n\n  username.clear();\n  password.clear();\n\n  // Get the user name and password\n  if (!OK(cryptGetAttributeString(session, CRYPT_SESSINFO_USERNAME, username_str, &usernameLength))) {\n    return false;\n  }\n  username_str[usernameLength] = '\\0';\n\n  if (!OK(cryptGetAttributeString(session, CRYPT_SESSINFO_PASSWORD, password_str, &passwordLength))) {\n    return false;\n  }\n  password_str[passwordLength] = '\\0';\n  username.assign(username_str);\n  password.assign(password_str);\n\n  return true;\n}\n\nSSHSession::SSHSession(int socket_handle, const Key& key) : socket_handle_(socket_handle) {\n  static bool once = ssh_once_init();\n  // GCC 4.9 has issues with assigning this to false in the class.\n  closed_.store(false);\n  int status = CRYPT_ERROR_INVALID;\n\n  status = cryptCreateSession(&session_, CRYPT_UNUSED, CRYPT_SESSION_SSH_SERVER);\n  if (!OK(status)) {\n    VLOG(1) << \"ERROR: Unable to create SSH session.\";\n    return;\n  }\n  \n  VLOG(1) << \"setting private key.\";\n  status = cryptSetAttribute(session_, CRYPT_SESSINFO_PRIVATEKEY, key.context());\n  if (!OK(status)) {\n    VLOG(1) << \"ERROR: Failed to set private key\";\n    return;\n  }\n\n  VLOG(1) << \"setting socket handle.\";\n  status = cryptSetAttribute(session_, CRYPT_SESSINFO_NETWORKSOCKET, socket_handle_);\n  if (!OK(status)) {\n    VLOG(1) << \"ERROR adding socket handle!\";\n    return;\n  }\n\n  bool success = false;\n  for (int i = 0; i < 10; i++) {\n    VLOG(1) << \"Looping to activate SSH Session\" << status;\n    status = cryptSetAttribute(session_, CRYPT_SESSINFO_AUTHRESPONSE, 1);\n    if (!OK(status)) {\n      VLOG(1) << \"Error setting CRYPT_SESSINFO_AUTHRESPONSE \" << status;\n      continue;\n    }\n    status = cryptSetAttribute(session_, CRYPT_SESSINFO_ACTIVE, 1);\n    if (OK(status)) {\n      VLOG(1) << \"Success setting CRYPT_SESSINFO_ACTIVE \" << status;\n      success = true;\n      break;\n    } else {\n      VLOG(1) << \"Error setting CRYPT_SESSINFO_ACTIVE \" << status;\n    }\n  }\n\n#ifdef PAUSE_ON_SSH_CONNECT_FOR_DEBUGGER\n  LOG(ERROR) << \"Waiting for debugger...\" <<;\n  getchar();\n#endif  // PAUSE_ON_SSH_CONNECT_FOR_DEBUGGER\n\n  if (!success) {\n    VLOG(1) << \"We don't have a valid SSH connection here!\";\n  } else {\n    // Clear out any remaining control messages.\n    int bytes_received = 0;\n    char buffer[4096];\n    status = cryptPopData(session_, buffer, 4096, &bytes_received);\n    if (!OK(status)) {\n    \tVLOG(1) << \"ERROR clearing buffer (but that is ok). status: \"\n    \t     << status;\n    }\n\n    GetSSHUserNameAndPassword(session_, remote_username_, remote_password_);\n    VLOG(1) << \"Got Username and Password!\";\n  }\n  initialized_ = success;\n}\n\nint SSHSession::PushData(const char* data, size_t size) {\n  int bytes_copied = 0;\n  VLOG(2) << \"SSHSession::PushData: \" << std::string(data, size);\n  std::lock_guard<std::mutex> lock(mu_);\n  int status = cryptPushData(session_, data, size, &bytes_copied);\n  if (!OK(status)) return 0;\n  status = cryptFlushData(session_);\n  if (!OK(status)) return 0;\n  return bytes_copied;\n}\n\nint SSHSession::PopData(char* data, size_t buffer_size) {\n  int bytes_copied = 0;\n  std::lock_guard<std::mutex> lock(mu_);\n  int status = cryptPopData(session_, data, buffer_size, &bytes_copied);\n  if (!OK(status)) return -1;\n  return bytes_copied;\n}\n\nbool SSHSession::close() {\n  std::lock_guard<std::mutex> lock(mu_);\n  if (closed_.load()) {\n    return false;\n  }\n  cryptDestroySession(session_);\n  closed_.store(true);\n  return true;\n}\n\nstd::string SSHSession::GetAndClearRemoteUserName() {\n  std::string temp = remote_username_;\n  remote_username_.clear();\n  return temp;\n}\n\nstd::string SSHSession::GetAndClearRemotePassword() {\n  std::string temp = remote_password_;\n  remote_password_.clear();\n  return temp;\n}\n\nstatic bool socket_avail(SOCKET sock, int seconds) {\n  fd_set fds;\n  FD_ZERO(&fds);\n  FD_SET(sock, &fds);\n\n  timeval tv;\n  tv.tv_sec = seconds;\n  tv.tv_usec = 0;\n\n  int result = select(sock + 1, &fds, 0, 0, &tv);\n  if (result == SOCKET_ERROR) {\n    throw socket_error(\"Error on select for socket.\");\n  }\n  return result == 1;\n}\n\n// Reads from remote socket using session, writes to socket\nstatic void reader_thread(SSHSession& session, SOCKET socket) {\n  constexpr size_t size = 16 * 1024;\n  std::unique_ptr<char[]> data = std::make_unique<char[]>(size);\n  try {\n    while (true) {\n      if (session.closed()) {\n        break;\n      }\n      if (!socket_avail(session.socket_handle(), 1)) {\n        continue;\n      }\n      memset(data.get(), 0, size);\n      int num_read = session.PopData(data.get(), size);\n      if (num_read == -1) {\n        // error.\n        break;\n      }\n      int num_sent = send(socket, data.get(), num_read, 0);\n      VLOG(1) << \"reader_thread: sent \" << num_sent;\n    }\n  } catch (const socket_error& e) {\n    VLOG(1) << e.what();\n  }\n  closesocket(socket);\n}\n\n// Reads from local socket socket, writes to remote socket using session.\nstatic void writer_thread(SSHSession& session, SOCKET socket) {\n  constexpr size_t size = 16 * 1024;\n  std::unique_ptr<char[]> data = std::make_unique<char[]>(size);\n  try {\n    while (true) {\n        if (session.closed()) {\n          break;\n        }\n      if (!socket_avail(socket, 1)) {\n        continue;\n      }\n      memset(data.get(), 0, size);\n      int num_read = recv(socket, data.get(), size, 0);\n      if (num_read > 0) {\n        int num_sent = session.PushData(data.get(), num_read);\n        VLOG(1) << \"writer_thread: pushed_data: \" << num_sent;\n      }\n    }\n  } catch (const socket_error& e) {\n    VLOG(1) << e.what();\n  }\n  closesocket(socket);\n}\n\nIOSSH::IOSSH(SOCKET ssh_socket, Key& key) \n  : ssh_socket_(ssh_socket), session_(ssh_socket, key) {\n  static bool initialized = RemoteSocketIO::Initialize();\n  if (!ssh_initalize()) {\n    VLOG(1) << \"ERROR INITIALIZING SSH (ssh_initalize)\";\n    closesocket(ssh_socket_);\n    ssh_socket_ = INVALID_SOCKET;\n    return;\n  }\n  if (!session_.initialized()) {\n    //LOG(ERROR) << \"ERROR INITIALIZING SSH (SSHSession::initialized)\";\n    closesocket(ssh_socket_);\n    ssh_socket_ = INVALID_SOCKET;\n    return;\n  }\n  io_.reset(new RemoteSocketIO(plain_socket_, false));\n  RemoteInfo& info = remote_info();\n  info.username = session_.GetAndClearRemoteUserName();\n  info.password = session_.GetAndClearRemotePassword();\n\n  initialized_ = true;\n}\n\nIOSSH::~IOSSH() {\n  if (ssh_receive_thread_.joinable()) {\n    ssh_receive_thread_.join();\n  }\n  if (ssh_send_thread_.joinable()) {\n    ssh_send_thread_.join();\n  }\n\n  // Release the remote before it happens automatically.\n  io_.reset(nullptr);\n\n  std::cerr << \"~IOSSH\";\n}\n\nbool IOSSH::ssh_initalize() {\n  sockaddr_in a{};\n\n  SOCKET listener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);\n  if (listener == INVALID_SOCKET) {\n#ifdef _WIN32    \n    int last_error = WSAGetLastError();\n#else\n    int last_error = errno;\n#endif\n    VLOG(1) << \"WSAGetLastError: \" << last_error;\n    return false;\n  }\n\n  // IP, localhost, any port.\n  a.sin_family = AF_INET;\n  a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n  a.sin_port = 0;\n\n  int result = bind(listener, reinterpret_cast<struct sockaddr*>(&a), sizeof(a));\n  if (result == SOCKET_ERROR) {\n    closesocket(listener);\n    return false;\n  }\n\n  result = listen(listener, 1);\n  if (result == SOCKET_ERROR) {\n    closesocket(listener);\n    return false;\n  }\n\n  socklen_t addr_len = sizeof(a);\n  result = getsockname(listener, reinterpret_cast<struct sockaddr*>(&a), &addr_len);\n  if (result == SOCKET_ERROR) {\n    closesocket(listener);\n    return false;\n  }\n\n  SOCKET pipe_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);\n  result = connect(pipe_socket, reinterpret_cast<struct sockaddr*>(&a), addr_len);\n  if (result == SOCKET_ERROR) {\n    closesocket(listener);\n    return false;\n  }\n\n  plain_socket_ = accept(listener, reinterpret_cast<struct sockaddr*>(&a), &addr_len);\n  if (plain_socket_ == INVALID_SOCKET) {\n    closesocket(listener);\n    closesocket(pipe_socket);\n    return false;\n  }\n\n  // Since we'll only ever accept one connection, we can close\n  // the listener socket.\n  closesocket(listener);\n\n  // assign and start the threads.\n  ssh_receive_thread_ = std::thread(reader_thread, std::ref(session_), pipe_socket);\n  ssh_send_thread_ = std::thread(writer_thread, std::ref(session_), pipe_socket);\n  return true;\n}\n\nbool IOSSH::open() { \n  if (!initialized_) return false;  \n  \n  remote_info().address = wwiv::core::GetRemotePeerAddress(ssh_socket_).value_or(\"\");\n  return io_->open(); \n}\n\nvoid IOSSH::close(bool temporary) { \n  if (!initialized_) return;\n  if (!temporary) {\n    session_.close();\n  }\n  io_->close(temporary);\n}\n\nunsigned char IOSSH::getW() { \n  if (!initialized_) return 0;\n  return io_->getW();\n}\nbool IOSSH::disconnect() {\n  if (!initialized_) return false;\n  return io_->disconnect();\n}\nvoid IOSSH::purgeIn() { \n  if (!initialized_) return;\n  io_->purgeIn();\n}\nunsigned int IOSSH::put(unsigned char ch) { \n  if (!initialized_) return 0;\n  return io_->put(ch);\n}\nunsigned int IOSSH::read(char *buffer, unsigned int count) {\n  if (!initialized_) return 0;\n  return io_->read(buffer, count);\n}\nunsigned int IOSSH::write(const char *buffer, unsigned int count, bool bNoTranslation) {\n  if (!initialized_) return 0;\n  return io_->write(buffer, count, bNoTranslation);\n}\nbool IOSSH::connected() { \n  if (!initialized_) return false;\n  return io_->connected(); \n}\n\nbool IOSSH::incoming() {\n  if (!initialized_) return false;\n  return io_->incoming();\n}\n\nunsigned int IOSSH::GetHandle() const { \n  if (!initialized_) return false;\n  return io_->GetHandle();\n}\n\nunsigned int IOSSH::GetDoorHandle() const {\n  if (!initialized_) return false;\n  return io_->GetDoorHandle();\n}\n\n} // namespace wwiv::bbs\n"
  },
  {
    "path": "bbs/ssh.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SSH_H__\n#define __INCLUDED_BBS_SSH_H__\n\n#include <atomic>\n#include <memory>\n#include <mutex>\n#include <string>\n\n#include \"common/remote_io.h\"\n#include \"common/remote_socket_io.h\"\n\nnamespace wwiv {\nnamespace bbs {\n\nclass Key {\npublic:\n  explicit Key(const std::string& filename, const std::string& password) \n    : filename_(filename), password_(password) {}\n  virtual ~Key() {};\n  bool Open();\n  bool Create();\n  int context() const { return context_; }\n\nprivate:\n  const std::string password_;\n  const std::string filename_;\n  int context_ = 0;\n  bool open_ = false;\n};\n\nclass SSHSession {\npublic:\n  SSHSession(int socket_handle, const Key& key);\n  virtual ~SSHSession() { close(); }\n  int PushData(const char* data, size_t size);\n  int PopData(char* data, size_t buffer_size);\n  int socket_handle() const { return socket_handle_; }\n  bool initialized() const { return initialized_; }\n  bool closed() const { return closed_.load(); }\n  bool close();\n  std::string GetAndClearRemoteUserName();\n  std::string GetAndClearRemotePassword();\n\nprivate:\n  mutable std::mutex mu_;\n  int session_{0};\n  int socket_handle_{-1};\n  bool initialized_{false};\n  std::atomic<bool> closed_;\n  std::string remote_username_;\n  std::string remote_password_;\n};\n\nclass IOSSH: public wwiv::common::RemoteIO {\npublic:\n  IOSSH(SOCKET socket, Key& key);\n  virtual ~IOSSH();\n\n  bool ssh_initalize();\n\n  bool open() override;\n  void close(bool temporary) override;\n  unsigned char getW() override;\n  bool disconnect() override;\n  void purgeIn() override;\n  unsigned int put(unsigned char ch) override;\n  unsigned int read(char *buffer, unsigned int count) override;\n  unsigned int write(const char *buffer, unsigned int count, bool bNoTranslation) override;\n  bool connected() override;\n  bool incoming() override;\n  unsigned int GetHandle() const override;\n  unsigned int GetDoorHandle() const override;\n\nprivate:\n  std::thread ssh_receive_thread_;\n  std::thread ssh_send_thread_;\n  bool initialized_{false};\n  std::unique_ptr<wwiv::common::RemoteSocketIO> io_;\n  SOCKET ssh_socket_;\n  SOCKET plain_socket_;\n  SSHSession session_;\n};\n\n\n}\n}\n\n#endif  // __INCLUDED_BBS_SSH_H__\n"
  },
  {
    "path": "bbs/stuffin.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/stuffin.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/make_abs_cmd.h\"\n#include \"bbs/utility.h\"\n#include \"common/context.h\"\n#include \"common/output.h\"\n#include \"common/remote_io.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::bbs {\n/**\n * Gets the time left in minutes.\n */\nstatic unsigned int GetTimeLeft() {\n  auto d = nsl();\n  if (d < 0) {\n    d += SECONDS_PER_DAY;\n  }\n  return static_cast<unsigned int>(d / MINUTES_PER_HOUR);\n}\n\n\nstd::string CommandLine::stuff_in() const {\n  auto commandline = cmd_;\n  auto iter = begin(commandline);\n  std::ostringstream os;\n  while (iter != end(commandline)) {\n    if (*iter == '%') {\n      ++iter;\n      switch (const auto ch = to_upper_case<char>(*iter); ch) {\n      // fixed strings\n      case '%': // literal %\n        os << \"%\";\n        break;\n      // call-specific numbers\n      case 'A':\n        os << create_dropfile_filename(drop_file_t::CALLINFO_BBS);\n        break;\n      case 'B':\n        os << a()->sess().dirs().batch_directory().string();\n        break;\n      case 'C':\n        os << create_dropfile_filename(drop_file_t::CHAIN_TXT);\n        break;\n      case 'D':\n        os << create_dropfile_filename(drop_file_t::DORINFO_DEF);\n        break;\n      case 'E':\n        os << create_dropfile_filename(drop_file_t::DOOR32_SYS);\n        break;\n      case 'H':\n        os << bout.remoteIO()->GetDoorHandle();\n        break;\n      case 'I':\n        os << a()->sess().dirs().temp_directory().string();\n        break;\n      case 'K':\n        os << FilePath(a()->config()->gfilesdir(), COMMENT_TXT).string();\n        break;\n      case 'M':\n        os << a()->modem_speed_;\n        break;\n      case 'N':\n        os << a()->sess().instance_number();\n        break;\n      case 'O':\n        os << create_dropfile_filename(drop_file_t::PCBOARD_SYS);\n        break;\n      case 'P':\n        os << (a()->sess().incom() ? a()->primary_port() : 0);\n        break;\n      case 'R':\n        os << create_dropfile_filename(drop_file_t::DOOR_SYS);\n        break;\n      // TODO(rushfan): Should we deprecate this? Use modem speed for now.\n      case 'S':\n        os << a()->modem_speed_;\n        break;\n      case 'T':\n        os << GetTimeLeft();\n        break;\n      case 'U':\n        os << a()->user()->name();\n        break;\n      // replacable params + everything else.\n      default: {\n        if (const auto it = args_.find(ch); it != std::end(args_)) {\n          os << it->second;\n        }\n      } break;\n      }\n      ++iter;\n    } else {\n      os << *iter++;\n    }\n  }\n  return os.str();\n}\n\nstd::string CommandLine::cmdline() const { \n  auto cmd = stuff_in();\n  if (cmdtype_ == cmdtype_t::absolute) {\n    make_abs_cmd(bbs_root_, &cmd);\n  }\n  return cmd;\n}\n\nvoid CommandLine::add(char key, std::string value) {\n  args_.emplace(to_upper_case_char(key), value);\n}\n\n}"
  },
  {
    "path": "bbs/stuffin.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_STUFFIN_H\n#define INCLUDED_BBS_STUFFIN_H\n\n#include <filesystem>\n#include <map>\n#include <string>\n\nnamespace wwiv::bbs {\n\n/**\n * \\verbatim\n * Creates a commandline by expanding the replaceable parameters offered by\n * WWIV.\n *\n * If you add one, please update these docs:\n * - http://docs.wwivbbs.org/en/latest/chains/parameters\n *\n * Replaceable parameters:\n * ~~~~~~~~~~~~~~~~~~~~~~\n *  Param    Description                       Example\n *  ----------------------------------------------------------------------------\n *  %%       A single '%'                          \"%\"\n *  %1-%5    Specified passed-in parameter\n *  %A       callinfo full pathname                \"c:\\wwiv\\temp\\callinfo.bbs\"\n *  %B       Full path to BATCH instance directory \"C:\\wwiv\\e\\1\\batch\"\n *  %C       chain.txt full pathname               \"c:\\wwiv\\temp\\chain.txt\"\n *  %D       doorinfo full pathname                \"c:\\wwiv\\temp\\dorinfo1.def\"\n *  %E       door32.sys full pathname              \"C:\\wwiv\\temp\\door32.sys\"\n *  %H       Socket Handle                         \"1234\"\n *  %I       Full Path to TEMP instance directory  \"C:\\wwiv\\e\\1\\temp\"\n *  %K       gfiles comment file for archives      \"c:\\wwiv\\gfiles\\comment.txt\"\n *  %M       Modem BPS rate                         \"38400\"\n *  %N       Instance number                       \"1\"\n *  %O       pcboard full pathname                 \"c:\\wwiv\\temp\\pcboard.sys\"\n *  %P       Com port number                       \"1\"\n *  %R       door full pathname                    \"c:\\wwiv\\temp\\door.sys\"\n *  %S       Com port BPS rate                     \"38400\"\n *  %T       Time remaining (min)                  \"30\"\n *  %U       Username                              \"Rushfan #1\"\n *  %Z       Socket port or path                   \"12345\" or \"/wwiv/bbs/e/1/scratch/wwiv.sock\"\n * \\endverbatim\n */\nclass CommandLine {\npublic:\n  enum class cmdtype_t { relative, absolute };\n  explicit CommandLine(const std::string& cmd) : cmd_(cmd), cmdtype_(cmdtype_t::relative) {}\n  CommandLine(const std::string& cmd, const std::filesystem::path& bbs_root)\n      : cmd_(cmd), bbs_root_(bbs_root), cmdtype_(cmdtype_t::absolute) {}\n  ~CommandLine() = default;\n\n  std::string cmdline() const;\n  bool empty() const noexcept { \n    return cmd_.empty();\n  }\n\n  template <typename... Args> void args(Args... args) {\n    return argss_(1, args...);\n  }\n\n  void add(char key, std::string value);\n\nprivate:\n  std::string stuff_in() const;\n  template <typename T> void argss_(int num, T a) {\n    std::ostringstream ss;\n    ss << a;\n    add(static_cast<char>(num + '0'), ss.str());\n  }\n\n  template <typename T, typename... Args> void argss_(int num, T arg, Args... args) {\n    argss_(num, arg);\n    argss_(num + 1, args...);\n  }\n\n  std::string cmd_;\n  const std::filesystem::path bbs_root_;\n  cmdtype_t cmdtype_{cmdtype_t::relative};\n  std::map<char, const std::string> args_;\n};\n\n} // namespace wwiv::bbs \n\n#endif"
  },
  {
    "path": "bbs/stuffin_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2007-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"gtest/gtest.h\"\r\n\r\n#include \"bbs/stuffin.h\"\r\n#include \"bbs/bbs_helper.h\"\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include \"sdk/filenames.h\"\r\n\r\n#include <string>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::strings;\r\n\r\nclass StuffInTest : public testing::Test {\r\nprotected:\r\n  void SetUp() override {\r\n    helper.SetUp();\r\n    a()->sess().incom(false);\r\n    a()->modem_speed_ = 0;\r\n  }\r\n\r\npublic:\r\n  static std::string t(const std::string& name) {\r\n    return FilePath(a()->sess().dirs().temp_directory(), name).string();\r\n  }\r\n\r\n  BbsHelper helper;\r\n};\r\n\r\nTEST_F(StuffInTest, SimpleCase) {\r\n  wwiv::bbs::CommandLine cl(\"foo %1 %c %2 %k\");\r\n  cl.args(\"one\", \"two\");\r\n\r\n  std::ostringstream os;\r\n  os << \"foo one \" << t(DROPFILE_CHAIN_TXT) << \" two \" << helper.gfiles() << COMMENT_TXT;\r\n  const auto expected = os.str();\r\n\r\n  EXPECT_EQ(expected, cl.cmdline());\r\n}\r\n\r\nTEST_F(StuffInTest, Empty) {\r\n  wwiv::bbs::CommandLine actual(\"\");\r\n  EXPECT_TRUE(actual.empty());\r\n}\r\n\r\n// Param     Description                       Example\r\n// ---------------------------------------------------------------------\r\n//  %%       A single '%'                      \"%\"\r\n//  %1-%5    Specified passed-in parameter\r\nTEST_F(StuffInTest, AllNumbers) {\r\n  wwiv::bbs::CommandLine cl(\"%0%1%2%3%4%5%6%%\");\r\n  cl.args(\"1\", \"2\", \"3\", \"4\", \"5\");\r\n  const std::string expected = \"12345%\";\r\n\r\n  EXPECT_EQ(expected, cl.cmdline());\r\n}\r\n\r\n// Param     Description                       Example\r\n// ---------------------------------------------------------------------\r\n//  %A       callinfo full pathname            \"c:\\wwiv\\temp\\callinfo.bbs\"\r\n//  %C       chain.txt full pathname           \"c:\\wwiv\\temp\\chain.txt\"\r\n//  %D       doorinfo full pathname            \"c:\\wwiv\\temp\\dorinfo1.def\"\r\n//  %E       door32.sys full pathname          \"C:\\wwiv\\temp\\door32.sys\"    string in = \"foo %1 %c\r\n//  %2 %k\"; %O       pcboard full pathname             \"c:\\wwiv\\temp\\pcboard.sys\" %R       door full\r\n//  pathname                \"c:\\wwiv\\temp\\door.sys\"\r\nTEST_F(StuffInTest, AllDropFiles) {\r\n  wwiv::bbs::CommandLine actual_lower(\"%a %c %d %e %o %r \");\r\n  wwiv::bbs::CommandLine actual_upper(\"%A %C %D %E %O %R \");\r\n\r\n  std::ostringstream expected;\r\n  expected << t(\"callinfo.bbs\") << \" \" << t(DROPFILE_CHAIN_TXT) << \" \" << t(\"dorinfo1.def\") << \" \"\r\n           << t(\"door32.sys\") << \" \" << t(\"pcboard.sys\") << \" \" << t(\"door.sys\") << \" \";\r\n\r\n  EXPECT_EQ(expected.str(), actual_lower.cmdline());\r\n  EXPECT_EQ(expected.str(), actual_upper.cmdline());\r\n}\r\n\r\n// Param     Description                       Example\r\n// ---------------------------------------------------------------------\r\n//  %N       Instance number                   \"1\"\r\n//  %P       Com port number                   \"1\"\r\nTEST_F(StuffInTest, PortAndNode) {\r\n  a()->sess().incom(false);\r\n  wwiv::bbs::CommandLine c0(\"%P\");\r\n  EXPECT_EQ(std::string(\"0\"), c0.cmdline());\r\n\r\n  a()->sess().incom(true);\r\n  wwiv::bbs::CommandLine c1(\"%P\");\r\n  EXPECT_EQ(std::string(\"1\"), c1.cmdline());\r\n\r\n  wwiv::bbs::CommandLine cn(\"%N\");\r\n  EXPECT_EQ(std::string(\"42\"), cn.cmdline());\r\n}\r\n\r\n// Param     Description                       Example\r\n// ---------------------------------------------------------------------\r\n//  %M       Modem baud rate                   \"14400\"\r\n//  %S       Com port baud rate                \"38400\"\r\nTEST_F(StuffInTest, Speeds) {\r\n  {\r\n    wwiv::bbs::CommandLine cm(\"%M\");\r\n    EXPECT_EQ(std::string(\"0\"), cm.cmdline());\r\n    wwiv::bbs::CommandLine cs(\"%S\");\r\n    EXPECT_EQ(std::string(\"0\"), cs.cmdline());\r\n  }\r\n\r\n  {\r\n    a()->modem_speed_ = 38400;\r\n    wwiv::bbs::CommandLine cm(\"%M\");\r\n    EXPECT_EQ(std::string(\"38400\"), cm.cmdline());\r\n    wwiv::bbs::CommandLine cs(\"%S\");\r\n    EXPECT_EQ(std::string(\"38400\"), cs.cmdline());\r\n  }\r\n}\r\n\r\nTEST_F(StuffInTest, Add) { \r\n  wwiv::bbs::CommandLine cm(\"FOO %Z\");\r\n  cm.add('z', \"BAR\");\r\n  EXPECT_EQ(cm.cmdline(), \"FOO BAR\");\r\n}\r\n"
  },
  {
    "path": "bbs/subacc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/subacc.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/message_file.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"core/wwivport.h\"\n#include \"sdk/config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// NOTE: This file containts wwiv message base specific code and should\n// move to SDK.\n//\n\nstatic std::unique_ptr<File> fileSub; // File object for '.sub' file\nstatic char subdat_fn[MAX_PATH];      // filename of .sub file\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid close_sub() {\n  if (fileSub) {\n    fileSub.reset();\n  }\n}\n\nbool open_sub(bool wr) {\n  fileSub.reset(new File(subdat_fn));\n  if (wr) {\n    fileSub->Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite);\n    if (fileSub->IsOpen()) {\n      // re-read info from file, to be safe\n      fileSub->Seek(0L, File::Whence::begin);\n      postrec p{};\n      fileSub->Read(&p, sizeof(postrec));\n      a()->SetNumMessagesInCurrentMessageArea(p.owneruser);\n    }\n  } else {\n    fileSub->Open(File::modeReadOnly | File::modeBinary);\n  }\n\n  return fileSub->IsOpen();\n}\n\nuint32_t WWIVReadLastRead(int sub_number) {\n  // open file, and create it if necessary\n  postrec p{};\n\n  const auto fn =\n      FilePath(a()->config()->datadir(), StrCat(a()->subs().sub(sub_number).filename, \".sub\"));\n  if (!File::Exists(fn)) {\n    File subFile(fn);\n    if (!subFile.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n      return 0;\n    }\n    p.owneruser = 0;\n    subFile.Write(&p, sizeof(postrec));\n    return 1;\n  }\n\n  File subFile(fn);\n  if (!subFile.Open(File::modeBinary | File::modeReadOnly)) {\n    return 0;\n  }\n  // read in first rec, specifying # posts\n  // p.owneruser contains # of posts.\n  subFile.Read(&p, sizeof(postrec));\n\n  if (p.owneruser == 0) {\n    // Not sure why but iscan1 returned 1 for empty subs.\n    return 1;\n  }\n\n  // read in sub date, if don't already know it\n  subFile.Seek(p.owneruser * sizeof(postrec), File::Whence::begin);\n  subFile.Read(&p, sizeof(postrec));\n  return p.qscan;\n}\n\n// Initializes use of a sub value (a()->subs().subs()[], not a()->usub[]).  If quick, then\n// don't worry about anything detailed, just grab qscan info.\nbool iscan1(int sub_index) {\n  postrec p{};\n\n  // forget it if an invalid sub #\n  if (sub_index < 0 || sub_index >= size_int(a()->subs().subs())) {\n    return false;\n  }\n\n  // go to correct net #\n  if (!a()->subs().sub(sub_index).nets.empty()) {\n    set_net_num(a()->subs().sub(sub_index).nets[0].net_num);\n  } else {\n    set_net_num(0);\n  }\n\n  // set sub filename\n  const auto subfn = StrCat(a()->subs().sub(sub_index).filename, \".sub\");\n  to_char_array(subdat_fn, FilePath(a()->config()->datadir(), subfn).string());\n\n  // open file, and create it if necessary\n  if (!File::Exists(subdat_fn)) {\n    if (!open_sub(true)) {\n      return false;\n    }\n    p.owneruser = 0;\n    fileSub->Write(&p, sizeof(postrec));\n  } else if (!open_sub(false)) {\n    return false;\n  }\n\n  // set sub\n  a()->sess().SetCurrentReadMessageArea(sub_index);\n  a()->subchg = 0;\n\n  // read in first rec, specifying # posts\n  fileSub->Seek(0L, File::Whence::begin);\n  fileSub->Read(&p, sizeof(postrec));\n  a()->SetNumMessagesInCurrentMessageArea(p.owneruser);\n\n  // We used to read in sub date, if don't already know it\n  // Not callers should use WWIVReadLastRead to get it.\n\n  // close file\n  close_sub();\n\n  // iscanned correctly\n  return true;\n}\n\n// Initializes use of a sub (a()->usub[] value, not a()->subs().subs()[] value).\nint iscan(int b) { return iscan1(a()->usub[b].subnum); }\n\n// Returns info for a post.\npostrec* get_post(int mn) {\n  if (mn < 1) {\n    return nullptr;\n  }\n  if (mn > a()->GetNumMessagesInCurrentMessageArea()) {\n    mn = a()->GetNumMessagesInCurrentMessageArea();\n  }\n  auto need_close = false;\n  if (!fileSub) {\n    if (!open_sub(false)) {\n      return nullptr;\n    }\n    need_close = true;\n  }\n  // read in post\n  static postrec p;\n  fileSub->Seek(mn * sizeof(postrec), File::Whence::begin);\n  fileSub->Read(&p, sizeof(postrec));\n\n  if (need_close) {\n    close_sub();\n  }\n  return &p;\n}\n\nvoid write_post(int mn, postrec* pp) {\n  if (!fileSub || !fileSub->IsOpen()) {\n    return;\n  }\n  fileSub->Seek(mn * sizeof(postrec), File::Whence::begin);\n  fileSub->Write(pp, sizeof(postrec));\n}\n\nvoid add_post(postrec* pp) {\n  bool need_close = false;\n\n  // open the sub, if necessary\n  if (!fileSub) {\n    open_sub(true);\n    need_close = true;\n  }\n  if (!fileSub || !fileSub->IsOpen()) {\n    return;\n  }\n  // get updated info\n  a()->status_manager()->reload_status();\n  fileSub->Seek(0L, File::Whence::begin);\n  subfile_header_t p{};\n  fileSub->Read(&p, sizeof(subfile_header_t));\n\n  if (strncmp(p.signature, \"WWIV\\x1A\", 5) != 0) {\n    const auto saved_count = p.active_message_count;\n    memset(&p, 0, sizeof(subfile_header_t));\n    // We don't have a modern header.\n    strcpy(p.signature, \"WWIV\\x1A\");\n    p.active_message_count = saved_count;\n    p.revision = 1;\n    p.wwiv_version = wwiv_config_version();\n    p.daten_created = DateTime::now().to_daten_t();\n  }\n\n  // one more post\n  p.active_message_count++;\n  p.mod_count++;\n  a()->SetNumMessagesInCurrentMessageArea(p.active_message_count);\n  fileSub->Seek(0L, File::Whence::begin);\n  fileSub->Write(&p, sizeof(postrec));\n\n  // add the new post\n  fileSub->Seek(a()->GetNumMessagesInCurrentMessageArea() * sizeof(postrec), File::Whence::begin);\n  fileSub->Write(pp, sizeof(postrec));\n\n  // we've modified the sub\n  a()->subchg = 0;\n\n  if (need_close) {\n    close_sub();\n  }\n}\n\nstatic constexpr size_t BUFSIZE = 32000;\n\nvoid delete_message(int mn) {\n  bool need_close = false;\n\n  // open file, if needed\n  if (!fileSub || !fileSub->IsOpen()) {\n    open_sub(true);\n    need_close = true;\n  }\n  // see if anything changed\n  a()->status_manager()->reload_status();\n\n  if (fileSub) {\n    if (mn > 0 && mn <= a()->GetNumMessagesInCurrentMessageArea()) {\n      if (auto* buffer = static_cast<char*>(malloc(BUFSIZE))) {\n        const auto* p1 = get_post(mn);\n        remove_link(&(p1->msg), a()->current_sub().filename);\n\n        auto cp = static_cast<long>(mn + 1) * sizeof(postrec);\n        const auto len = static_cast<long>(a()->GetNumMessagesInCurrentMessageArea() + 1) * sizeof(postrec);\n\n        unsigned int nb;\n        do {\n          const auto l = len - cp;\n          nb = l < BUFSIZE ? static_cast<int>(l) : BUFSIZE;\n          if (nb) {\n            fileSub->Seek(cp, File::Whence::begin);\n            fileSub->Read(buffer, nb);\n            fileSub->Seek(cp - sizeof(postrec), File::Whence::begin);\n            fileSub->Write(buffer, nb);\n            cp += nb;\n          }\n        } while (nb == BUFSIZE);\n\n        // update # msgs\n        postrec p{};\n        fileSub->Seek(0L, File::Whence::begin);\n        fileSub->Read(&p, sizeof(postrec));\n        p.owneruser--;\n        a()->SetNumMessagesInCurrentMessageArea(p.owneruser);\n        fileSub->Seek(0L, File::Whence::begin);\n        fileSub->Write(&p, sizeof(postrec));\n        free(buffer);\n      }\n    }\n  }\n  // close file, if needed\n  if (need_close) {\n    close_sub();\n  }\n}\n\nstatic bool IsSamePost(postrec* p1, postrec* p2) {\n  return p1 && p2 && p1->daten == p2->daten && p1->qscan == p2->qscan &&\n         p1->ownersys == p2->ownersys && p1->owneruser == p2->owneruser &&\n         IsEquals(p1->title, p2->title);\n}\n\nvoid resynch(int* msgnum, postrec* pp) {\n  postrec p, *pp1;\n  if (pp) {\n    p = *pp;\n  } else {\n    pp1 = get_post(*msgnum);\n    if (!pp1) {\n      return;\n    }\n    p = *pp1;\n  }\n\n  a()->status_manager()->reload_status();\n\n  if (a()->subchg || pp) {\n    pp1 = get_post(*msgnum);\n    if (IsSamePost(pp1, &p)) {\n      return;\n    } else if (!pp1 || (p.qscan < pp1->qscan)) {\n      if (*msgnum > a()->GetNumMessagesInCurrentMessageArea()) {\n        *msgnum = a()->GetNumMessagesInCurrentMessageArea() + 1;\n      }\n      for (int i = *msgnum - 1; i > 0; i--) {\n        pp1 = get_post(i);\n        if (IsSamePost(&p, pp1) || (p.qscan >= pp1->qscan)) {\n          *msgnum = i;\n          return;\n        }\n      }\n      *msgnum = 0;\n    } else {\n      for (int i = *msgnum + 1; i <= a()->GetNumMessagesInCurrentMessageArea(); i++) {\n        pp1 = get_post(i);\n        if (IsSamePost(&p, pp1) || (p.qscan <= pp1->qscan)) {\n          *msgnum = i;\n          return;\n        }\n      }\n      *msgnum = a()->GetNumMessagesInCurrentMessageArea();\n    }\n  }\n}\n"
  },
  {
    "path": "bbs/subacc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SUBACC_H\n#define INCLUDED_BBS_SUBACC_H\n\n#include <cstdint>\n\nstruct postrec;\n\nvoid close_sub();\nbool open_sub(bool wr);\nuint32_t WWIVReadLastRead(int sub_number);\nbool iscan1(int si);\nint iscan(int b);\npostrec* get_post(int mn);\nvoid delete_message(int mn);\nvoid write_post(int mn, postrec * pp);\nvoid add_post(postrec * pp);\nvoid resynch(int *msgnum, postrec * pp);\n\nnamespace wwiv::bbs {\n\nclass OpenSub {\npublic:\n  OpenSub(bool write_allowed): opened_(open_sub(write_allowed)) {}\n  ~OpenSub() { if (opened_) { close_sub(); } }\nprivate:\n  bool opened_;\n};\n\n}\n\n#endif  // __INCLUDED_BBS_SUBACC_H__"
  },
  {
    "path": "bbs/subedit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/subedit.h\"\n\n\n#include \"bbs/acs.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/subreq.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/subscribers.h\"\n#include <string>\n#include <vector>\n\nusing wwiv::common::InputMode;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic void save_subs() { a()->subs().Save(); }\n\nstatic std::string boarddata(size_t n, const subboard_t& r) {\n  std::string stype;\n  if (!r.nets.empty()) {\n    stype = r.nets[0].stype;\n  }\n  return fmt::sprintf(\"|#2%4d |#1%-37.37s |#2%-8s |#9%-5d |#5%-12s |#1%s\", n, stripcolors(r.name), r.filename,\n                      r.maxmsgs, stype, r.conf.to_string());\n}\n\nstatic void showsubs() {\n  bout.cls();\n  auto abort = false;\n  bout.outstr(\"|#7(|#1Message Areas Editor|#7) Enter Substring: \");\n  const auto substring = bin.input(20, true);\n  bout.cls();\n  bout.bpla(\"|#2NN   Name                                  FN       MSGS  SUBTYPE      CONF\", &abort);\n  bout.bpla(\"|#7==== ------------------------------------- ======== ===== ------------ -------\", &abort);\n  auto subnum = 0;\n  for (const auto& r : a()->subs().subs()) {\n    const auto subdata = StrCat(r.name, \" \", r.filename);\n    if (ifind_first(subdata, substring)) {\n      const auto line = boarddata(subnum, r);\n      bout.bpla(line, &abort);\n      if (abort)\n        break;\n    }\n    ++subnum;\n  }\n}\n\nstatic std::string GetKey(const subboard_t& r) { return (r.key == 0) ? \"None.\" : std::string(1, r.key); }\n\nstatic std::string GetAnon(const subboard_t& r) {\n  switch (r.anony & 0x0f) {\n  case 0:\n    return YesNoString(false);\n  case anony_enable_anony:\n    return YesNoString(true);\n  case anony_enable_dear_abby:\n    return \"Dear Abby\";\n  case anony_force_anony:\n    return \"Forced\";\n  case anony_real_name:\n    return \"Real Name\";\n  default:\n    return \"Real screwed up\";\n  }\n}\n\nstatic void DisplayNetInfo(size_t nSubNum) {\n  if (a()->subs().sub(nSubNum).nets.empty()) {\n    bout.outstr(\"|#2Not networked.\\r\\n\");\n    return;\n  }\n\n  bout.outstr(\"\\r\\n|#9      Network      Host         Type                  Scrb   Flags\\r\\n\");\n  int i = 0;\n  const auto& nets = a()->subs().sub(nSubNum).nets;\n  for (const auto& sn : nets) {\n    const auto auto_info_text =\n        (sn.category) ? fmt::format(\" Auto-Info({})\", sn.category) : \" Auto-Info\";\n    if (ssize(a()->nets()) <= sn.net_num) {\n      bout.print(\"      |#6No network exists at number: {} to display. \\r\\n\", sn.net_num);\n      continue;\n    }\n    const auto& net = a()->nets()[sn.net_num];\n    bout.printf(\"   |#9|#1%c|#9) |#2\", static_cast<char>('a' + i));\n    if (sn.host == 0) {\n      std::string host = \"<HERE>\";\n      const auto net_file_name = fmt::format(\"n{}.net\", sn.stype);\n      const auto subscriber_fn = FilePath(net.dir, net_file_name);\n      auto subscribers = ReadSubcriberFile(subscriber_fn);\n      auto num = size_int(subscribers);\n      bout.printf(\"%-12.12s %-12.12s %-20.20s  %-4d  %s%s\\r\\n\",\n                           net.name, host, sn.stype, num,\n                           (sn.flags & XTRA_NET_AUTO_ADDDROP) ? \" Auto-Req\" : \"\",\n                           (sn.flags & XTRA_NET_AUTO_INFO) ? auto_info_text : \"\");\n    } else if (net.type == network_type_t::ftn) {\n      const auto host = sn.ftn_uplinks.empty() ? \"[-none-]\" : sn.ftn_uplinks.begin()->as_string();\n      bout.printf(\"%-12.12s %-12.12s %s\\r\\n\", net.name, host, sn.stype);\n    } else {\n      auto host = fmt::format(\"{} \", sn.host);\n      bout.printf(\"%-12.12s %-12.12s %-20.20s  %s%s\\r\\n\", net.name,\n                           host, sn.stype, (sn.flags & XTRA_NET_AUTO_ADDDROP) ? \" Auto-Req\" : \"\",\n                           (sn.flags & XTRA_NET_AUTO_INFO) ? auto_info_text : \"\");\n    }\n    ++i;\n  }\n}\n\n// returns the sub name using the file filename or empty string.\nstatic std::string subname_using(const std::string& filename) {\n  for (const auto& sub : a()->subs().subs()) {\n    if (iequals(filename, sub.filename)) {\n      return sub.name;\n    }\n  }\n  return \"\";\n}\n\nstatic void modify_sub(int n) {\n  auto r = a()->subs().sub(n);\n  auto done = false;\n  do {\n    bout.cls();\n    bout.litebar(StrCat(\"Editing Message Sub #\", n));\n    bout.print(\"|#9A) Name         : |#2{}\\r\\n\", r.name);\n    bout.print(\"|#9B) Filename     : |#2{}\\r\\n\", r.filename);\n    bout.print(\"|#9C) Key          : |#2{}\\r\\n\", GetKey(r));\n    bout.print(\"|#9D) Read ACS     : |#2{}\\r\\n\", r.read_acs);\n    bout.print(\"|#9E) Post ACS     : |#2{}\\r\\n\", r.post_acs);\n    bout.print(\"|#9F) Anony        : |#2{}\\r\\n\", GetAnon(r));\n    bout.print(\"|#9H) Max Msgs     : |#2{}\\r\\n\", r.maxmsgs);\n    bout.outstr(\"|#9J) Net info     : |#2\");\n    DisplayNetInfo(n);\n\n    bout.print(\"|#9K) Storage typ  : |#2{}\\r\\n\", static_cast<int>(r.storage_type));\n    bout.print(\"|#9L) Val network  : |#2{}\\r\\n\", YesNoString((r.anony & anony_val_net) ? true : false));\n    bout.print(\"|#9M) Req ANSI     : |#2{}\\r\\n\",\n               YesNoString((r.anony & anony_ansi_only) ? true : false));\n    bout.print(\"|#9N) Disable tag  : |#2{}\\r\\n\", YesNoString((r.anony & anony_no_tag) ? true : false));\n    bout.print(\"|#9O) Description  : |#2{}\\r\\n\",\n               ((!a()->subs().sub(n).desc.empty()) ? a()->subs().sub(n).desc : \"None.\"));\n    bout.print(\"|#9P) Disable FS   : |#2{}\\r\\n\",\n               YesNoString((r.anony & anony_no_fullscreen) ? true : false));\n    bout.print(\"|#9R) Colorize Text: |#2{}\\r\\n\", YesNoString(r.colorize_text));\n    bout.print(\"|#9   Conferences  : |#2{}\\r\\n\", r.conf.to_string());\n    bout.nl();\n    bout.outstr(\"|#7(|#2Q|#7=|#1Quit|#7) Which (|#1A|#7-|#1R|#7,|#1[|#7=|#1Prev|#7,|#1]|#7=|#1Next|#7) : \");\n    auto ch = onek(\"QABCDEFGHIJKLMNOPR[]\", true);\n    bout.nl();\n    switch (ch) {\n    case 'Q':\n      done = true;\n      break;\n    case '[':\n      a()->subs().set_sub(n, r);\n      if (--n < 0) {\n        n = size_int(a()->subs().subs()) - 1;\n      }\n      r = a()->subs().sub(n);\n      break;\n    case ']':\n      a()->subs().set_sub(n, r);\n      if (++n >= size_int(a()->subs().subs())) {\n        n = 0;\n      }\n      r = a()->subs().sub(n);\n      break;\n    case 'A': {\n      bout.outstr(\"|#2New name? \");\n      auto new_name = bin.input_text(r.name, 40);\n      if (!new_name.empty()) {\n        r.name = new_name;\n      }\n    } break;\n    case 'B': {\n      bout.outstr(\"|#2New base filename (e.g. 'GENERAL')? \");\n      auto new_fn = bin.input_filename(r.filename, 8);\n      if (new_fn.empty() || contains(new_fn, '.') || new_fn == r.filename) {\n        break;\n      }\n      auto new_sub_fullpath = FilePath(a()->config()->datadir(), StrCat(new_fn, \".sub\"));\n      if (File::Exists(new_sub_fullpath)) {\n        // Find out which sub was using it.\n        bout.nl();\n        auto sub_name_using_file = subname_using(new_fn);\n        bout.print(\"|#6{} already in use for '{}'\\r\\n\\r\\n|#5Use anyway? \", new_fn,\n                   sub_name_using_file);\n        if (!bin.yesno()) {\n          break;\n        }\n      }\n      auto old_subname(r.filename);\n      r.filename = new_fn;\n\n      if (r.storage_type != 2) {\n        // Only rename files for type2\n        break;\n      }\n\n      const auto old_sub_fullpath = FilePath(a()->config()->datadir(), StrCat(old_subname, \".sub\"));\n      const auto old_msg_fullpath = FilePath(a()->config()->msgsdir(), StrCat(old_subname, \".dat\"));\n      const auto new_msg_fullpath = FilePath(a()->config()->msgsdir(), StrCat(new_fn, \".dat\"));\n\n      if (!File::Exists(new_sub_fullpath) && !File::Exists(new_msg_fullpath) &&\n          new_fn != \"NONAME\" && old_subname != \"NONAME\") {\n        bout.nl();\n        bout.outstr(\"|#7Rename current data files (.SUB/.DAT)? \");\n        if (bin.yesno()) {\n          File::Rename(old_sub_fullpath, new_sub_fullpath);\n          File::Rename(old_msg_fullpath, new_msg_fullpath);\n        }\n      }\n    } break;\n    case 'C': {\n      bout.nl();\n      bout.outstr(\"|#2New Key (space = none) ? \");\n      auto ch2 = onek(\"@%^&()_=\\\\|;:'\\\",` \");\n      r.key = (ch2 == SPACE) ? '\\0' : ch2;\n    } break;\n    case 'D': {\n      bout.nl();\n      r.read_acs = wwiv::bbs::input_acs(bin, bout, \"New Read ACS?\", r.read_acs, 78);\n    } break;\n    case 'E': {\n      bout.nl();\n      r.post_acs = wwiv::bbs::input_acs(bin, bout, \"New Post ACS?\", r.post_acs, 78);\n    } break;\n    case 'F': {\n      std::string allowed(\"NYDFR\");\n      bout.nl();\n      bout.outstr(\"|#2New Anony (Y,N,D,F,R) ? \");\n      const auto Y = YesNoString(true)[0];\n      const auto N = YesNoString(false)[0];\n      allowed.push_back(Y);\n      allowed.push_back(N);\n      char ch2 = onek(allowed, true);\n      if (ch2 == N) {\n        ch2 = 0;\n      } else if (ch2 == Y) {\n        ch2 = 1;\n      }\n      r.anony &= 0xf0;\n      switch (ch2) {\n      case 0:\n        break;\n      case 1:\n        r.anony |= anony_enable_anony;\n        break;\n      case 'D':\n        r.anony |= anony_enable_dear_abby;\n        break;\n      case 'F':\n        r.anony |= anony_force_anony;\n        break;\n      case 'R':\n        r.anony |= anony_real_name;\n        break;\n      }\n    } break;\n    case 'H': {\n      bout.nl();\n      bout.outstr(\"|#2New Max Msgs? \");\n      r.maxmsgs = bin.input_number(r.maxmsgs);\n    } break;\n    case 'J': {\n      const auto num_nets = wwiv::stl::ssize(a()->nets());\n      if (!num_nets) {\n        break;\n      }\n      a()->subs().set_sub(n, r);\n      auto ch2 = 'A';\n      if (!r.nets.empty()) {\n        bout.nl();\n        bout.outstr(\"|#2A)dd, D)elete, or M)odify net reference (Q=Quit)? \");\n        ch2 = onek(\"QAMD\");\n      }\n\n      if (ch2 == 'A') {\n        if (!sub_xtr_add(n, -1)) {\n          continue;\n        }\n        if (a()->subs().sub(n).name == \"** New WWIV Message Sub **\") {\n          a()->subs().sub(n).name = a()->subs().sub(n).desc;\n        }\n        const auto stype = a()->subs().sub(n).nets[0].stype;\n        if (a()->subs().sub(n).filename == \"NONAME\" && stype.size() <= 8) {\n          a()->subs().sub(n).filename = stype;\n        }\n      } else if (ch2 == 'D' || ch2 == 'M') {\n        bout.nl();\n        if (ch2 == 'D') {\n          bout.outstr(\"|#2Delete which (a-\");\n        } else {\n          bout.outstr(\"|#2Modify which (a-\");\n        }\n        bout.print(\"{:c}), <space>=Quit? \", static_cast<char>('a' + a()->subs().sub(n).nets.size() - 1));\n        std::string charstring;\n        charstring = \" \";\n        for (size_t i = 0; i < a()->subs().sub(n).nets.size(); i++) {\n          charstring.push_back(static_cast<char>('A' + i));\n        }\n        bout.ansic(0);\n        auto ch3 = onek(charstring);\n        if (ch3 != ' ') {\n          int i = ch3 - 'A';\n          if (i >= 0 && i < size_int(a()->subs().sub(n).nets)) {\n            if (ch2 == 'D') {\n              sub_xtr_del(n, i, 1);\n            } else {\n              sub_xtr_del(n, i, 0);\n              if (!sub_xtr_add(n, i)) {\n                continue;\n              }\n            }\n          }\n        }\n      }\n      r = a()->subs().sub(n);\n    } break;\n    case 'K': {\n      bout.nl();\n      //bout.outstr(\"|#2New Storage Type ( 2 ) ? \");\n      //auto new_type = bin.input_number<uint8_t>(r.storage_type, 2, 2);\n      r.storage_type = 2;\n    } break;\n    case 'L':\n      bout.nl();\n      bout.outstr(\"|#5Require sysop validation for network posts? \");\n      r.anony &= ~anony_val_net;\n      if (bin.yesno()) {\n        r.anony |= anony_val_net;\n      }\n      break;\n    case 'M':\n      bout.nl();\n      bout.outstr(\"|#5Require ANSI to read this sub? \");\n      r.anony &= ~anony_ansi_only;\n      if (bin.yesno()) {\n        r.anony |= anony_ansi_only;\n      }\n      break;\n    case 'N':\n      bout.nl();\n      bout.outstr(\"|#5Disable tag lines for this sub? \");\n      r.anony &= ~anony_no_tag;\n      if (bin.yesno()) {\n        r.anony |= anony_no_tag;\n      }\n      break;\n    case 'O': {\n      bout.nl();\n      bout.outstr(\"|#2Enter new Description : \\r\\n|#7:\");\n      a()->subs().sub(n).desc = bin.input_text(a()->subs().sub(n).desc, 60);\n    } break;\n    case 'P':\n      bout.nl();\n      bout.outstr(\"|#5Disable the Full Screen Reader for this sub? \");\n      r.anony &= ~anony_no_fullscreen;\n      if (bin.yesno()) {\n        r.anony |= anony_no_fullscreen;\n      }\n      break;\n    case 'R':\n      bout.nl();\n      bout.outstr(\"|#5Attempt to colorize uncolorized message text for this sub? \");\n      r.colorize_text = bin.yesno();\n      break;\n    }\n  } while (!done && !a()->sess().hangup());\n  a()->subs().set_sub(n, r);\n}\n\nstatic void swap_subs(int sub1, int sub2) {\n  if (sub1 < 0 || sub1 >= size_int(a()->subs().subs()) || sub2 < 0 ||\n      sub2 >= size_int(a()->subs().subs())) {\n    return;\n  }\n\n  const auto num_user_records = a()->users()->num_user_records();\n\n  auto pTempQScan = std::make_unique<uint32_t[]>(a()->config()->qscn_len());\n  for (auto i = 1; i <= num_user_records; i++) {\n    int i1, i2;\n    read_qscn(i, pTempQScan.get(), true);\n    uint32_t* pTempQScan_n = &pTempQScan.get()[1];\n    uint32_t* pTempQScan_q = pTempQScan_n + (a()->config()->max_dirs() + 31) / 32;\n    uint32_t* pTempQScan_p = pTempQScan_q + (a()->config()->max_subs() + 31) / 32;\n\n    if (pTempQScan_q[sub1 / 32] & (1L << (sub1 % 32))) {\n      i1 = 1;\n    } else {\n      i1 = 0;\n    }\n\n    if (pTempQScan_q[sub2 / 32] & (1L << (sub2 % 32))) {\n      i2 = 1;\n    } else {\n      i2 = 0;\n    }\n    if (i1 + i2 == 1) {\n      pTempQScan_q[sub1 / 32] ^= (1L << (sub1 % 32));\n      pTempQScan_q[sub2 / 32] ^= (1L << (sub2 % 32));\n    }\n    const auto tl = pTempQScan_p[sub1];\n    pTempQScan_p[sub1] = pTempQScan_p[sub2];\n    pTempQScan_p[sub2] = tl;\n\n    write_qscn(i, pTempQScan.get(), true);\n  }\n  close_qscn();\n\n  const auto sbt = a()->subs().sub(sub1);\n  a()->subs().set_sub(sub1, a()->subs().sub(sub2));\n  a()->subs().set_sub(sub2, sbt);\n\n  save_subs();\n}\n\nstatic void insert_sub(int n) {\n  int i2;\n  if (n < 0 || n > size_int(a()->subs().subs())) {\n    return;\n  }\n\n\n  subboard_t r = {};\n  r.name = \"** New WWIV Message Sub **\";\n  r.filename = \"NONAME\";\n  r.key = 0;\n  r.read_acs = \"user.sl >= 10\";\n  r.post_acs = \"user.sl >= 20\";\n  r.anony = 0;\n  r.maxmsgs = 5000;\n  r.storage_type = 2;\n\n  // Insert new item.\n  a()->subs().insert(n, r);\n\n  const auto num_user_records = a()->users()->num_user_records();\n\n  const auto pTempQScan = std::make_unique<uint32_t[]>(a()->config()->qscn_len());\n  const auto pTempQScan_n = &pTempQScan.get()[1];\n  const auto pTempQScan_q = pTempQScan_n + (a()->config()->max_dirs() + 31) / 32;\n  const auto pTempQScan_p = pTempQScan_q + (a()->config()->max_subs() + 31) / 32;\n\n  const uint32_t m1 = 1L << (n % 32);\n  const uint32_t m2 = 0xffffffff << ((n % 32) + 1);\n  const uint32_t m3 = 0xffffffff >> (32 - (n % 32));\n\n  for (auto i = 1; i <= num_user_records; i++) {\n    read_qscn(i, pTempQScan.get(), true);\n\n    if (pTempQScan[0] != 999 && pTempQScan[0] >= static_cast<uint32_t>(n)) {\n      pTempQScan[0]++;\n    }\n\n    for (auto i1 = size_int(a()->subs().subs()) - 1; i1 > n; i1--) {\n      pTempQScan_p[i1] = pTempQScan_p[i1 - 1];\n    }\n    pTempQScan_p[n] = 0;\n\n    for (i2 = size_int(a()->subs().subs()) / 32; i2 > n / 32; i2--) {\n      pTempQScan_q[i2] = (pTempQScan_q[i2] << 1) | (pTempQScan_q[i2 - 1] >> 31);\n    }\n    pTempQScan_q[i2] = m1 | (m2 & (pTempQScan_q[i2] << 1)) | (m3 & pTempQScan_q[i2]);\n\n    write_qscn(i, pTempQScan.get(), true);\n  }\n  close_qscn();\n  save_subs();\n\n  if (a()->sess().GetCurrentReadMessageArea() >= n) {\n    a()->sess().SetCurrentReadMessageArea(a()->sess().GetCurrentReadMessageArea() + 1);\n  }\n}\n\nstatic void delete_sub(int n) {\n  if (n < 0 || n >= size_int(a()->subs().subs())) {\n    return;\n  }\n  while (size_int(a()->subs().subs()) > n && !a()->subs().sub(n).nets.empty()) {\n    sub_xtr_del(n, 0, 1);\n  }\n  a()->subs().erase(n);\n  const auto num_user_records = a()->users()->num_user_records();\n\n  const auto pTempQScan = std::make_unique<uint32_t[]>(a()->config()->qscn_len() + 1);\n  auto pTempQScan_n = &pTempQScan.get()[1];\n  auto pTempQScan_q = pTempQScan_n + (a()->config()->max_dirs() + 31) / 32;\n  unsigned* pTempQScan_p = pTempQScan_q + (a()->config()->max_subs() + 31) / 32;\n\n  auto m2 = 0xffffffff << (n % 32);\n  auto m3 = 0xffffffff >> (32 - (n % 32));\n\n  for (int i = 1; i <= num_user_records; i++) {\n    read_qscn(i, pTempQScan.get(), true);\n\n    if (pTempQScan[0] != 999) {\n      if (pTempQScan[0] == static_cast<uint32_t>(n)) {\n        pTempQScan[0] = 999;\n      } else if (pTempQScan[0] > static_cast<uint32_t>(n)) {\n        pTempQScan[0]--;\n      }\n    }\n    for (auto i1 = n; i1 < size_int(a()->subs().subs()); i1++) {\n      pTempQScan_p[i1] = pTempQScan_p[i1 + 1];\n    }\n\n    pTempQScan_q[n / 32] = (pTempQScan_q[n / 32] & m3) | ((pTempQScan_q[n / 32] >> 1) & m2) |\n                           (pTempQScan_q[(n / 32) + 1] << 31);\n\n    for (auto i2 = (n / 32) + 1; i2 <= size_int(a()->subs().subs()) / 32; i2++) {\n      pTempQScan_q[i2] = (pTempQScan_q[i2] >> 1) | (pTempQScan_q[i2 + 1] << 31);\n    }\n\n    write_qscn(i, pTempQScan.get(), true);\n  }\n  close_qscn();\n  save_subs();\n\n  if (a()->sess().GetCurrentReadMessageArea() == n) {\n    a()->sess().SetCurrentReadMessageArea(-1);\n  } else if (a()->sess().GetCurrentReadMessageArea() > n) {\n    a()->sess().SetCurrentReadMessageArea(a()->sess().GetCurrentReadMessageArea() - 1);\n  }\n}\n\nvoid boardedit() {\n  if (!ValidateSysopPassword()) {\n    return;\n  }\n  showsubs();\n  auto done = false;\n  a()->status_manager()->reload_status();\n  do {\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9)uit (|#2D|#9)elete, (|#2I|#9)nsert, (|#2M|#9)odify, (|#2S|#9)wapSubs, (|#2C|#9)onferences : \");\n    switch (const auto ch = onek(\"QSDIMC?\"); ch) {\n    case '?':\n      showsubs();\n      break;\n    case 'C':\n      edit_conf_subs(a()->all_confs().subs_conf());\n      break;\n    case 'Q':\n      done = true;\n      break;\n    case 'M': {\n      bout.nl();\n      bout.outstr(\"|#2Sub number? \");\n      const int subnum = bin.input_number(-1, 0, size_int(a()->subs().subs()) - 1, false);\n      if (subnum >= 0) {\n        modify_sub(subnum);\n      }\n    } break;\n    case 'S': {\n      if (a()->subs().subs().size() < a()->config()->max_subs()) {\n        bout.nl();\n        bout.outstr(\"|#2Take sub number? \");\n        auto subnum1 = bin.input_number(-1, 0, size_int(a()->subs().subs()) - 1, false);\n        if (subnum1 <= 0) {\n          break;\n        }\n        bout.nl();\n        bout.outstr(\"|#2And move before sub number? \");\n        const auto subnum2 = bin.input_number(-1, 1, size_int(a()->subs().subs()) - 1, false);\n        if (subnum2 <= 0) {\n          break;\n        }\n        bout.nl();\n        if (subnum2 < subnum1) {\n          subnum1++;\n        }\n        write_qscn(a()->sess().user_num(), a()->sess().qsc, true);\n        bout.outstr(\"|#1Moving sub now...Please wait...\");\n        insert_sub(subnum2);\n        swap_subs(subnum1, subnum2);\n        delete_sub(subnum1);\n        showsubs();\n      } else {\n        bout.outstr(\"\\r\\nYou must increase the number of subs in WWIVconfig first.\\r\\n\");\n      }\n    } break;\n    case 'I': {\n      if (a()->subs().subs().size() >= a()->config()->max_subs()) {\n        break;\n      }\n      bout.nl();\n      bout.outstr(\"|#2Insert before which sub ('Q' to quit, '$' for end) : \");\n      auto r = bin.input_number_hotkey(-1, {'Q', '$'}, 0, size_int(a()->subs().subs()), false);\n      int subnum;\n      if (r.key == 'Q') {\n        break;\n      }\n      if (r.key == '$') {\n        subnum = static_cast<subconf_t>(size_int(a()->subs().subs()));\n      } else {\n        subnum = r.num;\n      }\n      if (subnum <= size_int(a()->subs().subs())) {\n        insert_sub(subnum);\n        modify_sub(subnum);\n        const auto confs_size = a()->all_confs().subs_conf().size();\n        if (confs_size > 1) {\n          bout.nl();\n          if (auto o = select_conf(\"Put in which conference? \", a()->all_confs().subs_conf(), true)) {\n            a()->subs().sub(subnum).conf.insert(o.value());\n          }\n        } else if (confs_size == 1) {\n          a()->subs().sub(subnum).conf.insert(a()->all_confs().subs_conf().front().key.key());\n        }\n      }\n    } break;\n    case 'D': {\n      bout.nl();\n      bout.outstr(\"|#2Delete which sub? \");\n      const int subnum = bin.input_number(-1, 0, size_int(a()->subs().subs()) - 1, false);\n      if (subnum >= 0) {\n        bout.nl();\n        bout.print(\"|#5Delete {}? \", a()->subs().sub(subnum).name);\n        if (bin.yesno()) {\n          const auto fn = a()->subs().sub(subnum).filename;\n          delete_sub(subnum);\n          bout.nl();\n          bout.outstr(\"|#5Delete data files (including messages) for sub also? \");\n          if (bin.yesno()) {\n            File::Remove(FilePath(a()->config()->datadir(), StrCat(fn, \".sub\")));\n            File::Remove(FilePath(a()->config()->msgsdir(), StrCat(fn, \".dat\")));\n          }\n        }\n      }\n    } break;\n    }\n  } while (!done && !a()->sess().hangup());\n  save_subs();\n  if (!a()->at_wfc()) {\n    changedsl();\n  }\n  a()->subchg = 1;\n}\n"
  },
  {
    "path": "bbs/subedit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SUBEDIT_H__\n#define __INCLUDED_BBS_SUBEDIT_H__\n\nvoid boardedit();\n\n#endif  // __INCLUDED_BBS_SUBEDIT_H__"
  },
  {
    "path": "bbs/sublist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/sublist.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/subacc.h\"\n#include \"bbs/utility.h\"\n#include \"common/com.h\"\n#include \"common/output.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/net/networks.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid old_sublist() {\n  int oc = a()->sess().current_user_sub_conf_num();\n  int os = a()->current_user_sub().subnum;\n\n  bool abort = false;\n  auto sn = std::begin(a()->uconfsub);\n  auto en = std::end(a()->uconfsub);\n  if (okconf(a()->user())) {\n    if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n      bout.nl();\n      bout.outstr(\"|#2A)ll conferences, Q)uit, <space> for current conference: \");\n      const auto ch = onek(\"Q A\");\n      bout.nl();\n      switch (ch) {\n      case ' ':\n        std::advance(sn, a()->sess().current_user_sub_conf_num());\n        en = sn;\n        break;\n      case 'Q':\n        return;\n      }\n    }\n  } else {\n    oc = -1;\n  }\n\n  bout.nl();\n  bout.bpla(\"|#9Sub-Conferences Available: \", &abort);\n  bout.nl();\n  auto iter = sn;\n  auto count = 0;\n  while (iter != en && !abort) {\n    if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n      const auto pos = std::distance(std::begin(a()->uconfsub), iter);\n      setuconf(ConferenceType::CONF_SUBS, pos, -1);\n      const auto s =\n          fmt::format(\"|#1Conference {}|#0:|#2 {}\", iter->key.key(), stripcolors(iter->conf_name));\n      bout.bpla(s, &abort);\n    }\n    size_t i1 = 0;\n    while (i1 < a()->usub.size() && !abort) {\n      std::ostringstream os1;\n      os1 << fmt::sprintf(\"  |#5%4.4s|#2\", a()->usub[i1].keys);\n      if (a()->sess().qsc_q[a()->usub[i1].subnum / 32] & (1L << (a()->usub[i1].subnum % 32))) {\n        os1 << \" - \";\n      } else {\n        os1 << \"  \";\n      }\n      if (a()->current_net().sysnum || wwiv::stl::ssize(a()->nets()) > 1) {\n        if (!a()->subs().sub(a()->usub[i1].subnum).nets.empty()) {\n          std::string ss;\n          if (a()->subs().sub(a()->usub[i1].subnum).nets.size() > 1) {\n            ss = \"Gated\";\n          } else {\n            ss = stripcolors(a()->nets()[a()->subs().sub(a()->usub[i1].subnum).nets[0].net_num].name);\n          }\n\n          if (a()->subs().sub(a()->usub[i1].subnum).anony & anony_val_net) {\n            os1 << fmt::sprintf(\"|17|15[%-8.8s]|#9 \", ss);\n          } else {\n            os1 << fmt::sprintf(\"|17|15<%-8.8s>|#9 \", ss);\n          }\n        } else {\n          os1 << std::string(11, ' ');\n        }\n        os1 << \"|#9\";\n      }\n      os1 << stripcolors(a()->subs().sub(a()->usub[i1].subnum).name);\n      bout.bpla(os1.str(), &abort);\n      i1++;\n      ++count;\n    }\n    ++iter;\n    bout.nl();\n    if (!okconf(a()->user())) {\n      break;\n    }\n  }\n\n  if (!count) {\n    bout.bpla(\"|#6None.\", &abort);\n    bout.nl();\n  }\n\n  if (okconf(a()->user())) {\n    setuconf(ConferenceType::CONF_SUBS, oc, os);\n  }\n}\n\n/**\n * Gets the count of new posts in subnum.\n *\n * Starts at the end and will search backwards from the midpoint before starting\n * from the front.  This assumes most people have read most of the messages, and\n * will prioritize performance for those people. Afterwards will start at the\n * start and search forward.\n *\n * If we need to optimize more ever, we can use a binary search if needed or just\n * load all of the postrecs and search in memory.\n */\nint get_new_posts_count(int subnum) {\n  const auto num = a()->GetNumMessagesInCurrentMessageArea();\n  const auto q = a()->sess().qsc_p[subnum];\n  if (num == 0) {\n    return 0;\n  }\n  const auto midpoint = num / 2;\n  auto msgIndex = num;\n  int64_t last_qscan = 0;\n  open_sub(false);\n  auto at_exit = finally([] { close_sub(); });\n  while(msgIndex > midpoint) {\n    const auto cur = get_post(msgIndex)->qscan;\n    if (cur <= q) {\n      last_qscan = cur;\n      ++msgIndex;\n      break;\n    }\n    --msgIndex;\n  }\n  if (last_qscan < static_cast<int64_t>(q)) {\n    msgIndex = 1;\n    while (msgIndex <= a()->GetNumMessagesInCurrentMessageArea() &&\n           get_post(msgIndex)->qscan <= a()->sess().qsc_p[subnum]) {\n      ++msgIndex;\n    }\n  }\n  return a()->GetNumMessagesInCurrentMessageArea() - msgIndex + 1;\n}\n\nvoid SubList() {\n  int p, wc; // color code\n  char ch;\n  bool next;\n\n  int oc = a()->sess().current_user_sub_conf_num();\n  int old_sub = a()->current_user_sub().subnum;\n  auto sn = std::begin(a()->uconfsub);  // current sub number\n  auto en = std::end(a()->uconfsub);\n\n  if (okconf(a()->user())) {\n    if (a()->uconfsub.size() > 1) {\n      bout.nl();\n      bout.outstr(\"|#2A)ll conferences, Q)uit, <space> for current conference: \");\n      ch = onek(\"Q A\");\n      bout.nl();\n      switch (ch) {\n      case ' ':\n        sn = std::begin(a()->uconfsub);\n        std::advance(sn, a()->sess().current_user_sub_conf_num());\n        en = sn + 1;\n        break;\n      case 'Q':\n        return;\n      }\n    }\n  } else {\n    oc = -1;\n  }\n\n  auto abort = false;\n  auto done = false;\n  do {\n    p = 1;\n    auto i1 = 0;\n    for(auto iter = sn;  iter != en && !abort; ++iter) {\n      auto ns = 0;\n      if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n        auto pos = std::distance(std::begin(a()->uconfsub), iter);\n        setuconf(ConferenceType::CONF_SUBS, pos, -1);\n        i1 = 0;\n      }\n      size_t firstp = 0;\n      while (i1 < size_int(a()->usub) && !abort) {\n        if (p) {\n          p = 0;\n          firstp = i1;\n          bout.cls();\n          std::string s;\n          if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n            s = fmt::format(\"Conference {}: {}\", iter->key.key(), stripcolors(iter->conf_name));\n          } else {\n            s = fmt::format(\"{} Message Areas\", a()->config()->system_name());\n          }\n          bout.litebar(s);\n          DisplayHorizontalBar(78, 7);\n          bout.outstr(\"|#2 Sub   Scan   Net/Local   Sub Name                                 Old   New\\r\\n\");\n          DisplayHorizontalBar(78, 7);\n        }\n        ++ns;\n        std::string yns =\n            (a()->sess().qsc_q[a()->usub[i1].subnum / 32] & (1L << (a()->usub[i1].subnum % 32)))\n                ? \"|#5Yes\"\n                : \"|#6No \";\n        iscan(i1);\n        std::string net_info;\n        if (a()->current_net().sysnum || wwiv::stl::ssize(a()->nets()) > 1) {\n          if (!a()->subs().sub(a()->usub[i1].subnum).nets.empty()) {\n\t          std::string net_name;\n            if (a()->subs().sub(a()->usub[i1].subnum).nets.size() > 1) {\n              wc = 6;\n              net_name = \"Gated\";\n            } else {\n              const auto nn = a()->nets()[a()->subs().sub(a()->usub[i1].subnum).nets[0].net_num].name;\n              net_name = stripcolors(nn);\n              wc = a()->net_num() % 8;\n            }\n            if (a()->subs().sub(a()->usub[i1].subnum).anony & anony_val_net) {\n              net_info = fmt::sprintf(\"|#7[|#%i%-8.8s|#7]\", wc, net_name);\n            } else {\n              net_info = fmt::sprintf(\"|#7<|#%i%-8.8s|#7>\", wc, net_name);\n            }\n          } else {\n            net_info = \" |#7>|#1LOCAL|#7<  \";\n          }\n        } else {\n          net_info = \"|#7>|#1LOCAL|#7<  \";\n        }\n        const auto num_new_posts = get_new_posts_count(a()->usub[i1].subnum);\n        const auto subname_color = (a()->current_user_sub().subnum == a()->usub[i1].subnum) ? \"|#4\" : \"|#1\";\n        const auto sdf = fmt::sprintf(\" |#9%-3.3d |#9\\xB3 %3s |#9\\xB3 %6s |#9\\xB3 %s%-36.36s |#9\\xB3 \"\n                           \"|#9%5d |#9\\xB3 |#%c%5u |#9\",\n                           i1 + 1, yns, net_info, subname_color, a()->subs().sub(a()->usub[i1].subnum).name,\n                           a()->GetNumMessagesInCurrentMessageArea(), num_new_posts ? '6' : '3',\n                           num_new_posts);\n        bout.outstr(sdf, &abort, &next);\n        bout.nl();\n        auto lastp = i1++;\n        if (bout.lines_listed() >= a()->sess().num_screen_lines() - 2) {\n          p = 1;\n          bout.clear_lines_listed();\n          DisplayHorizontalBar(78, 7);\n          bout.printf(\"|#1Select |#9[|#2%d-%d, [N]ext Page, [Q]uit|#9]|#0 : \", firstp + 1, lastp + 1);\n          const auto ss = mmkey(MMKeyAreaType::subs, true);\n          if (isdigit(ss[0])) {\n            for (auto i2 = 0; i2 < size_int(a()->usub); i2++) {\n              if (ss == a()->usub[i2].keys) {\n                a()->set_current_user_sub_num(i2);\n                old_sub = a()->current_user_sub().subnum;\n                done = true;\n                abort = true;\n              }\n            }\n          } else {\n            switch (ss[0]) {\n            case 'Q': {\n              if (okconf(a()->user())) {\n                setuconf(ConferenceType::CONF_SUBS, oc, old_sub);\n              }\n              done = true;\n              abort = true;\n            }\n            break;\n            default:\n              bout.backline();\n              break;\n            }\n          }\n        }\n      }\n      //if (ns) {\n      //  ++iter;\n      //}\n\n      if (!abort) {\n        p = 1;\n        DisplayHorizontalBar(78, 7);\n        if (okconf(a()->user())) {\n          if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n            bout.printf(\"|#1Select |#9[|#21-%d, J=Join Conference, ?=List Again, Q=Quit|#9]|#0 : \", ns);\n          } else {\n            bout.printf(\"|#1Select |#9[|#21-%d, ?=List Again, Q=Quit|#9]|#0 : \", ns);\n          }\n        } else {\n          bout.printf(\"|#1Select |#9[|#21-%d, ?=List Again, Q=Quit|#9]|#0 : \", ns);\n        }\n        const auto ss = mmkey(MMKeyAreaType::subs, true);\n\n        if (ss == \"?\") {\n          p = 1;\n          ns = i1 = 0;\n          iter = std::begin(a()->uconfsub);\n        }\n\n        if (ss == \" \" || ss == \"Q\" || ss == \"\\r\") {\n          bout.nl(2);\n          done = true;\n          if (!okconf(a()->user())) {\n            abort = true;\n          }\n        }\n        if (ss == \"J\") {\n          if (okconf(a()->user())) {\n            jump_conf(ConferenceType::CONF_SUBS);\n          }\n          oc = a()->sess().current_user_sub_conf_num();\n          sn = std::begin(a()->uconfsub);\n          std::advance(sn, a()->sess().current_user_sub_conf_num());\n          en = sn + 1;\n          iter = sn;\n          ns = 0;\n        }\n        if (isdigit(ss.front())) {\n          for (uint16_t i2 = 0; i2 < a()->usub.size(); i2++) {\n            if (ss == a()->usub[i2].keys) {\n              a()->set_current_user_sub_num(i2);\n              old_sub = a()->current_user_sub().subnum;\n              done = true;\n              abort = true;\n            }\n          }\n        }\n      } else {\n        if (okconf(a()->user())) {\n          setuconf(ConferenceType::CONF_SUBS, oc, old_sub);\n        }\n        done = true;\n      }\n    }\n    //if (i == 0) {\n    //  bout.bpla(\"None.\", &abort);\n    //  bout.nl();\n    //}\n  } while (!a()->sess().hangup() && !done);\n\n  if (okconf(a()->user())) {\n    setuconf(ConferenceType::CONF_SUBS, oc, old_sub);\n  }\n}\n\n\n"
  },
  {
    "path": "bbs/sublist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SUBLIST_H__\n#define __INCLUDED_BBS_SUBLIST_H__\n\nvoid old_sublist();\nvoid SubList();\n\n#endif // __INCLUDED_BBS_SUBLIST_H__"
  },
  {
    "path": "bbs/subreq.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/subreq.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/email.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/utility.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/subscribers.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic void maybe_netmail(subboard_network_data_t* ni, bool bAdd) {\n  bout.outstr(\"|#5Send email request to the host now? \");\n  if (bin.yesno()) {\n    auto title = StrCat(\"Sub type \", ni->stype);\n    if (bAdd) {\n      title += \" - ADD request\";\n    } else {\n      title += \" - DROP request\";\n    }\n    set_net_num(ni->net_num);\n    email(title, 1, ni->host, false, 0);\n  }\n}\n\nstatic bool display_sub_categories(const Network& net) {\n  if (!net.sysnum) {\n    return false;\n  }\n\n  TextFile ff(FilePath(net.dir, CATEG_NET), \"rt\");\n  if (!ff.IsOpen()) {\n    return false;\n  }\n  bout.nl();\n  bout.outstr(\"Available sub categories are:\\r\\n\");\n  auto abort = false;\n  std::string s;\n  while (!abort && ff.ReadLine(&s)) {\n    StringTrim(&s);\n    bout.bpla(s, &abort);\n  }\n  ff.Close();\n  return true;\n}\n\nstatic void sub_req(uint16_t main_type, int tosys, const std::string& stype,\n                    const Network& net) {\n  net_header_rec nh{};\n\n  nh.tosys = static_cast<uint16_t>(tosys);\n  nh.touser = 1;\n  nh.fromsys = net.sysnum;\n  nh.fromuser = 1;\n  nh.main_type = main_type;\n  // always use 0 since we use the \"stype\" field\n  nh.minor_type = 0;\n  nh.list_len = 0;\n  nh.daten = daten_t_now();\n  nh.method = 0;\n  // This is an alphanumeric sub type.\n  auto text = stype;\n  text.push_back(0);\n  nh.length = size_uint32(text);\n  send_net(&nh, {}, text, \"\");\n\n  bout.nl();\n  if (main_type == main_type_sub_add_req) {\n    bout.print(\"Automated add request sent to @{}\\r\\n\",tosys);\n  } else {\n    bout.print(\"Automated drop request sent to @{}\\r\\n\", tosys);\n  }\n  bout.pausescr();\n}\n\nstatic constexpr short OPTION_AUTO = 0x0001;\nstatic constexpr short OPTION_NO_TAG = 0x0002;\nstatic constexpr short OPTION_GATED = 0x0004;\nstatic constexpr short OPTION_NETVAL = 0x0008;\nstatic constexpr short OPTION_ANSI = 0x0010;\n\nstatic int find_hostfor(const Network& net, const std::string& type, short* ui,\n                        char* description, short* opt) {\n  int rc = 0;\n\n  if (description) {\n    *description = 0;\n  }\n  *opt = 0;\n\n  bool done = false;\n  for (int i = 0; i < 256 && !done; i++) {\n    std::filesystem::path fn;\n    if (i) {\n      fn = FilePath(net.dir, StrCat(SUBS_NOEXT, \".\", i));\n    } else {\n      fn = FilePath(net.dir, StrCat(SUBS_LST));\n    }\n    TextFile file(fn, \"r\");\n    if (!file) {\n      return rc;\n    }\n    char s[255];\n    while (!done && file.ReadLine(s, 160)) {\n      if (s[0] <= ' ') {\n        continue;\n      }\n      auto* ss = strtok(s, \" \\r\\n\\t\");\n      if (!ss) {\n        continue;\n      }\n      if (!iequals(ss, type)) {\n        continue;\n      }\n      ss = strtok(nullptr, \" \\r\\n\\t\");\n      if (!ss) {\n        continue;\n      }\n      auto h = to_number<short>(ss);\n      short o = 0;\n      ss = strtok(nullptr, \"\\r\\n\");\n      if (!ss) {\n        continue;\n      }\n      int i1 = 0;\n      while (*ss && ((*ss == ' ') || (*ss == '\\t'))) {\n        ++ss;\n        ++i1;\n      }\n      if (i1 < 4) {\n        while (*ss && (*ss != ' ') && (*ss != '\\t')) {\n          switch (*ss) {\n          case 'T':\n            o |= OPTION_NO_TAG;\n            break;\n          case 'R':\n            o |= OPTION_AUTO;\n            break;\n          case 'G':\n            o |= OPTION_GATED;\n            break;\n          case 'N':\n            o |= OPTION_NETVAL;\n            break;\n          case 'A':\n            o |= OPTION_ANSI;\n            break;\n          }\n          ++ss;\n        }\n        while (*ss && ((*ss == ' ') || (*ss == '\\t'))) {\n          ++ss;\n        }\n      }\n      if (*ui) {\n        if (*ui == h) {\n          done = true;\n          *opt = o;\n          rc = h;\n          if (description) {\n            strcpy(description, ss);\n          }\n        }\n      } else {\n        bout.nl();\n        bout.print(\"Type: {}\\r\\n\", type);\n        bout.print(\"Host: {}\\r\\n\", h);\n        bout.print(\"Sub : {}\\r\\n\", ss);\n        bout.nl();\n        bout.outstr(\"|#5Is this the sub you want? \");\n        if (bin.yesno()) {\n          done = true;\n          *ui = h;\n          *opt = o;\n          rc = h;\n          if (description) {\n            strcpy(description, ss);\n          }\n        }\n      }\n    }\n  }\n\n  return rc;\n}\n\nvoid sub_xtr_del(int n, int nn, int f) {\n  // make a copy of the old network info.\n  auto xn = a()->subs().sub(n).nets[nn];\n\n  if (f) {\n    erase_at(a()->subs().sub(n).nets, nn);\n  }\n  set_net_num(xn.net_num);\n  const auto& net = a()->nets().at(xn.net_num);\n\n  if (xn.host != 0 && valid_system(xn.host)) {\n    short opt;\n    const auto ok = find_hostfor(net, xn.stype, &xn.host, nullptr, &opt);\n    if (ok) {\n      if (opt & OPTION_AUTO) {\n        bout.outstr(\"|#5Attempt automated drop request? \");\n        if (bin.yesno()) {\n          sub_req(main_type_sub_drop_req, xn.host, xn.stype, net);\n        }\n      } else {\n        maybe_netmail(&xn, false);\n      }\n    } else {\n      bout.outstr(\"|#5Attempt automated drop request? \");\n      if (bin.yesno()) {\n        sub_req(main_type_sub_drop_req, xn.host, xn.stype, net);\n      } else {\n        maybe_netmail(&xn, false);\n      }\n    }\n  }\n}\n\nbool sub_xtr_add(int n, int nn) {\n  // nn may be -1\n  while (nn >= size_int(a()->subs().sub(n).nets)) {\n    a()->subs().sub(n).nets.push_back({});\n  }\n  subboard_network_data_t xnp = {};\n  // Start with the first network number, only ask if\n  // we have more than 1 network to choose from.\n  int network_number = 0;\n  const auto num_nets = wwiv::stl::ssize(a()->nets());\n  if (num_nets == 0) {\n    LOG(ERROR) << \"Called sub_xtr_add when no networks defined.\";\n    return false;\n  }\n\n  if (num_nets > 1) {\n    std::set<char> odc;\n    char onx[20];\n    onx[0] = 'Q';\n    onx[1] = 0;\n    auto onxi = 1;\n    bout.nl();\n    for (auto ii = 0; ii < wwiv::stl::ssize(a()->nets()); ii++) {\n      if (ii < 9) {\n        onx[onxi++] = static_cast<char>(ii + '1');\n        onx[onxi] = 0;\n      } else {\n        auto odci = (ii + 1) / 10;\n        odc.insert(static_cast<char>(odci + '0'));\n      }\n      bout.print(\"({}) {}\\r\\n\", ii + 1, a()->nets()[ii].name);\n    }\n    bout.outstr(\"Q. Quit\\r\\n\\n\");\n    bout.outstr(\"|#2Which network (number): \");\n    if (wwiv::stl::ssize(a()->nets()) < 9) {\n      auto ch = onek(onx);\n      if (ch == 'Q') {\n        return false;\n      }\n      network_number = ch - '1';\n    } else {\n      auto mmk = mmkey(odc);\n      if (mmk == \"Q\") {\n        return false;\n      }\n      network_number = to_number<int>(mmk) - 1;\n    }\n    if (network_number >= 0 && network_number < wwiv::stl::ssize(a()->nets())) {\n      set_net_num(network_number);\n    } else {\n      return false;\n    }\n  }\n  xnp.net_num = static_cast<int16_t>(network_number);\n  const auto& net = a()->nets()[network_number];\n\n  bout.nl();\n  auto stype_len = 7;\n  if (net.type == network_type_t::ftn) {\n    bout.outstr(\"|#2What echomail area: \");\n    stype_len = 40;\n  } else {\n    bout.outstr(\"|#2What sub type? \");\n  }\n  xnp.stype = bin.input(stype_len, true);\n  if (xnp.stype.empty()) {\n    return false;\n  }\n\n  bool is_hosting = false;\n  if (net.type == network_type_t::wwivnet || net.type == network_type_t::internet ||\n      net.type == network_type_t::news) {\n    bout.outstr(\"|#5Will you be hosting the sub? \");\n    is_hosting = bin.yesno();\n  }\n\n  if (is_hosting) {\n    auto file_name = StrCat(net.dir, \"n\", xnp.stype, \".net\");\n    File file(file_name);\n    if (file.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n      file.Close();\n    }\n\n    bout.outstr(\"|#5Allow auto add/drop requests? \");\n    if (bin.noyes()) {\n      xnp.flags |= XTRA_NET_AUTO_ADDDROP;\n    }\n\n    bout.outstr(\"|#5Make this sub public (in subs.lst)?\");\n    if (bin.noyes()) {\n      xnp.flags |= XTRA_NET_AUTO_INFO;\n      if (display_sub_categories(net)) {\n        auto gc = 0;\n        while (!gc) {\n          bout.nl();\n          bout.outstr(\"|#2Which category is this sub in (0 for unknown/misc)? \");\n          auto s = bin.input(3);\n          auto i = to_number<uint16_t>(s);\n          if (i || s == \"0\") {\n            TextFile ff(FilePath(net.dir, CATEG_NET), \"rt\");\n            while (ff.ReadLine(&s)) {\n              int i1 = to_number<uint16_t>(s);\n              if (i1 == i) {\n                gc = 1;\n                xnp.category = i;\n                break;\n              }\n            }\n            file.Close();\n            if (s == \"0\") {\n              gc = 1;\n            } else if (!xnp.category) {\n              bout.outstr(\"Illegal/invalid category.\\r\\n\\n\");\n            }\n          } else {\n            if (s.size() == 1 && s.front() == '?') {\n              display_sub_categories(net);\n              continue;\n            }\n          } \n        }\n      }\n    }\n  } else if (net.type == network_type_t::ftn) {\n    // Set the fake fido node up as the host.\n    xnp.host = FTN_FAKE_OUTBOUND_NODE;\n    const auto sub_file_name = FilePath(net.dir, StrCat(\"n\", xnp.stype, \".net\"));\n\n    auto addresses = ReadFidoSubcriberFile(sub_file_name);\n    bool done = false;\n    do {\n      a()->CheckForHangup();\n      bout.nl();\n      bout.outstr(\"|#2Which FTN system (address) is the host? \");\n      const auto host = bin.input_text(20);\n      try {\n        fido::FidoAddress a(host);\n        addresses.insert(a);\n        if (!WriteFidoSubcriberFile(sub_file_name, addresses)) {\n          bout.outstr(\"ERROR: Unable to add host to subscriber file\");\n        }\n        done = true;\n      } catch (const fido::bad_fidonet_address& e) {\n        bout.print(\"Bad Address: {}\", e.what());\n      }\n    } while (!done && !a()->sess().hangup());\n\n  } else {\n    char description[100];\n    short opt;\n    auto ok = find_hostfor(net, xnp.stype, &(xnp.host), description, &opt);\n\n    if (!ok) {\n      bout.nl();\n      bout.outstr(\"|#2Which system (number) is the host? \");\n      bin.input(description, 6);\n      xnp.host = to_number<uint16_t>(description);\n      description[0] = '\\0';\n    }\n    if (!a()->subs().sub(n).desc[0]) {\n      a()->subs().sub(n).desc = description;\n    }\n\n    if (xnp.host == net.sysnum) {\n      xnp.host = 0;\n    }\n\n    if (xnp.host) {\n      if (valid_system(xnp.host)) {\n        if (ok) {\n          if (opt & OPTION_NO_TAG) {\n            a()->subs().sub(n).anony |= anony_no_tag;\n          }\n          bout.nl();\n          if (opt & OPTION_AUTO) {\n            bout.outstr(\"|#5Attempt automated add request? \");\n            if (bin.yesno()) {\n              sub_req(main_type_sub_add_req, xnp.host, xnp.stype, net);\n            }\n          } else {\n            maybe_netmail(&xnp, true);\n          }\n        } else {\n          bout.nl();\n          bout.outstr(\"|#5Attempt automated add request? \");\n          auto bTryAutoAddReq = bin.yesno();\n          if (bTryAutoAddReq) {\n            sub_req(main_type_sub_add_req, xnp.host, xnp.stype, net);\n          } else {\n            maybe_netmail(&xnp, true);\n          }\n        }\n      } else {\n        bout.nl();\n        bout.outstr(\"The host is not listed in the network.\\r\\n\");\n        bout.pausescr();\n      }\n    }\n  }\n  if (nn == -1 || nn >= size_int(a()->subs().sub(n).nets)) {\n    // nn will be -1 when adding a new sub.\n    a()->subs().sub(n).nets.push_back(xnp);\n  } else {\n    a()->subs().sub(n).nets[nn] = xnp;\n  }\n  return true;\n}\n"
  },
  {
    "path": "bbs/subreq.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SUBREQ_H\n#define INCLUDED_BBS_SUBREQ_H\n\nvoid sub_xtr_del(int n, int nn, int f);\n/**\n * Adds a new sub network reference to the network n\n * Returns true on success, false if aborted.\n */\nbool sub_xtr_add(int n, int nn);\n\n#endif\n"
  },
  {
    "path": "bbs/syschat.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/syschat.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/email.h\"\n#include \"common/input.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/config.h\"\n#include \"sdk/names.h\"\n#include \"sdk/filenames.h\"\n#include <algorithm>\n#include <chrono>\n#include <string>\n\nusing std::chrono::duration_cast;\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n// module private functions\nvoid chatsound(int sf, int ef, int uf, int dly1, int dly2, int rp);\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// static variables for use in two_way_chat\n//\n\n#define MAXLEN 160\n#define MAXLINES_SIDE 13\n\nstatic int wwiv_x1, wwiv_y1, wwiv_x2, wwiv_y2, cp0, cp1;\nstatic char (*side0)[MAXLEN], (*side1)[MAXLEN];\n\nstatic bool s_chat_file = false;\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Makes various (local-only) sounds based upon input params. The params are:\n//     sf = starting frequency, in hertz\n//     ef = ending frequency, in hertz\n//     uf = frequency change, in hertz, for each step\n//   dly1 = delay, in milliseconds, between each step, when going from sf\n//             to ef\n//   dly2 = delay, in milliseconds, between each repetition of the sound\n//             sequence\n//     rp = number of times to play the whole sound sequence\n//\n\nvoid toggle_chat_file() {\n  s_chat_file = !s_chat_file;\n}\n\nvoid chatsound(int sf, int ef, int uf, int dly1, int dly2, int rp) {\n  for (int i1 = 0; i1 < rp; i1++) {\n    if (sf < ef) {\n      for (int i = sf; i < ef; i += uf) {\n        sound(i, milliseconds(dly1));\n      }\n    } else {\n      for (int i = ef; i > sf; i -= uf) {\n        sound(i, milliseconds(dly1));\n      }\n    }\n    sleep_for(milliseconds(dly2));\n  }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n//\n// Function called when user requests chat w/sysop.\n//\n\nvoid RequestChat() {\n  bout.nl(2);\n  if (sysop2() && !a()->user()->restrict_chat()) {\n    if (a()->sess().chatcall()) {\n      a()->sess().clear_chatcall();\n      bout.outstr(\"Chat call turned off.\\r\\n\");\n      a()->UpdateTopScreen();\n    } else {\n      bout.outstr(\"|#9Enter Reason for chat: \\r\\n|#0:\");\n      auto chatReason = bin.input_text(70);\n      if (!chatReason.empty()) {\n        if (!play_sdf(CHAT_NOEXT, false)) {\n          chatsound(100, 800, 10, 10, 25, 5);\n        }\n        const auto cr = fmt::format(\"Chat: {}\", chatReason);\n        bout.nl();\n        sysoplog(cr);\n        a()->sess().chat_reason(cr);\n        a()->UpdateTopScreen();\n        bout.outstr(\"Chat call turned ON.\\r\\n\");\n        bout.nl();\n      }\n    }\n  } else {\n    bout.print(\"|#6{} is not available.\\r\\n\\n|#5Try sending feedback instead.\\r\\n\",\n               a()->config()->sysop_name());\n    imail(\"|#1Tried Chatting\", 1, 0);\n  }\n}\n\n//////////////////////////////////////////////////////////////////////////////\n//\n//\n// Allows selection of a name to \"chat as\". Returns selected string in *s.\n//\n\nstatic std::string select_chat_name() {\n  a()->DisplaySysopWorkingIndicator(true);\n  bout.localIO()->savescreen();\n  auto sysop_name = a()->config()->sysop_name();\n  bout.curatr(a()->GetChatNameSelectionColor());\n  bout.localIO()->MakeLocalWindow(20, 5, 43, 3);\n  bout.localIO()->PutsXY(22, 6, \"Chat As: \");\n  bout.curatr(bout.localIO()->GetEditLineColor());\n  bout.localIO()->PutsXY(31, 6, std::string(30, SPACE));\n\n  bout.localIO()->GotoXY(31, 6);\n  const auto rc = bout.localIO()->EditLine(sysop_name, 30, AllowedKeys::ALL);\n  if (rc != EditlineResult::ABORTED) { // ABORTED\n    StringTrimEnd(&sysop_name);\n    const auto user_number = to_number<int>(sysop_name);\n    if (user_number > 0 && user_number <= a()->config()->max_users()) {\n      sysop_name =  a()->names()->UserName(user_number);\n    } else {\n      if (sysop_name.empty()) {\n        sysop_name = a()->config()->sysop_name();\n      }\n    }\n  } else {\n    sysop_name.clear();\n  }\n  bout.localIO()->restorescreen();\n  a()->DisplaySysopWorkingIndicator(false);\n\n  return sysop_name;\n}\n\n// Allows two-way chatting until sysop aborts/exits chat. or the end of line is hit,\n// then chat1 is back in control.\nstatic void two_way_chat(std::string* rollover, int max_length, bool crend, const std::string& sysop_name) {\n  char s2[100], temp1[100];\n  int i;\n  int i1;\n\n  const auto cm = a()->sess().chatting();\n  const auto begx = bout.localIO()->WhereX();\n  if (!rollover->empty()) {\n    if (bin.charbufferpointer_) {\n      char szTempBuffer[255];\n      to_char_array(szTempBuffer, *rollover);\n      strcat(szTempBuffer, &bin.charbuffer[bin.charbufferpointer_]);\n      strcpy(&bin.charbuffer[1], szTempBuffer);\n      bin.charbufferpointer_ = 1;\n    } else {\n      strcpy(&bin.charbuffer[1], rollover->c_str());\n      bin.charbufferpointer_ = 1;\n    }\n    rollover->clear();\n  }\n  bool done = false;\n  int side = 0;\n  char ch;\n  do {\n    ch = bin.getkey();\n    if (bin.IsLastKeyLocal()) {\n      if (bout.localIO()->WhereY() == 11) {\n        bout.goxy(1, 12);\n        for (auto screencount = 0; screencount < a()->user()->screen_width(); screencount++) {\n          s2[screencount] = '\\xCD';\n        }\n        const auto unn = a()->user()->name_and_number();\n        sprintf(temp1, \"|17|#2 %s chatting with %s |16|#1\", sysop_name.c_str(), unn.c_str());\n        const auto chars_to_move = (a()->user()->screen_width() - size_int(stripcolors(temp1))) / 2;\n        if (chars_to_move) {\n          strncpy(&s2[chars_to_move - 1], temp1, (strlen(temp1)));\n        } else {\n          to_char_array(s2, std::string(a()->user()->screen_width() - 1, '\\xCD'));\n        }\n        s2[a()->user()->screen_width()] = '\\0';\n        bout.outstr(s2);\n        s2[0] = '\\0';\n        temp1[0] = '\\0';\n        for (int cntr = 1; cntr < 12; cntr++) {\n          sprintf(s2, \"\\x1b[%d;%dH\", cntr, 1);\n          bout.outstr(s2);\n          if (cntr >= 0 && cntr < 5) {\n            bout.ansic(1);\n            bout.outstr(side0[cntr + 6]);\n          }\n          bout.clreol();\n          s2[0] = 0;\n        }\n        bout.goxy(1, 5);\n        s2[0] = 0;\n      } else if (bout.localIO()->WhereY() > 11) {\n        wwiv_x2 = (bout.localIO()->WhereX() + 1);\n        wwiv_y2 = (bout.localIO()->WhereY() + 1);\n        bout.goxy(wwiv_x1, wwiv_y1);\n        s2[0] = 0;\n      }\n      side = 0;\n      bout.ansic(1);\n    } else {\n      if (bout.localIO()->WhereY() >= 23) {\n        for (int cntr = 13; cntr < 25; cntr++) {\n          sprintf(s2, \"\\x1b[%d;%dH\", cntr, 1);\n          bout.outstr(s2);\n          if ((cntr >= 13) && (cntr < 17)) {\n            bout.ansic(5);\n            bout.outstr(side1[cntr - 7]);\n          }\n          bout.clreol();\n          s2[0] = '\\0';\n        }\n        sprintf(s2, \"\\x1b[%d;%dH\", 17, 1);\n        bout.outstr(s2);\n        s2[0] = '\\0';\n      } else if (bout.localIO()->WhereY() < 12 && side == 0) {\n        wwiv_x1 = (bout.localIO()->WhereX() + 1);\n        wwiv_y1 = (bout.localIO()->WhereY() + 1);\n        sprintf(s2, \"\\x1b[%d;%dH\", wwiv_y2, wwiv_x2);\n        bout.outstr(s2);\n        s2[0] = 0;\n      }\n      side = 1;\n      bout.ansic(5);\n    }\n    if (cm != chatting_t::none && a()->sess().chatting() == chatting_t::none) {\n      ch = RETURN;\n    }\n    if (ch >= SPACE) {\n      if (side == 0) {\n        if (bout.localIO()->WhereX() < (a()->user()->screen_width() - 1) && cp0 < max_length) {\n          if (bout.localIO()->WhereY() < 11) {\n            side0[bout.localIO()->WhereY()][cp0++] = ch;\n            bout.outchr(ch);\n          } else {\n            side0[bout.localIO()->WhereY()][cp0++] = ch;\n            side0[bout.localIO()->WhereY()][cp0] = 0;\n            for (int cntr = 0; cntr < 12; cntr++) {\n              sprintf(s2, \"\\x1b[%d;%dH\", cntr, 1);\n              bout.outstr(s2);\n              if ((cntr >= 0) && (cntr < 6)) {\n                bout.ansic(1);\n                bout.outstr(side0[cntr + 6]);\n                wwiv_y1 = bout.localIO()->WhereY() + 1;\n                wwiv_x1 = bout.localIO()->WhereX() + 1;\n              }\n              bout.outstr(\"\\x1b[K\");\n              s2[0] = 0;\n            }\n            sprintf(s2, \"\\x1b[%d;%dH\", wwiv_y1, wwiv_x1);\n            bout.outstr(s2);\n            s2[0] = 0;\n          }\n          if (bout.localIO()->WhereX() == (a()->user()->screen_width() - 1)) {\n            done = true;\n          }\n        } else {\n          if (bout.localIO()->WhereX() >= (a()->user()->screen_width() - 1)) {\n            done = true;\n          }\n        }\n      } else {\n        if ((bout.localIO()->WhereX() < (a()->user()->screen_width() - 1)) &&\n            (cp1 < max_length)) {\n          if (bout.localIO()->WhereY() < 23) {\n            side1[bout.localIO()->WhereY() - 13][cp1++] = ch;\n            bout.outchr(ch);\n          } else {\n            side1[bout.localIO()->WhereY() - 13][cp1++] = ch;\n            side1[bout.localIO()->WhereY() - 13][cp1] = 0;\n            for (int cntr = 13; cntr < 25; cntr++) {\n              sprintf(s2, \"\\x1b[%d;%dH\", cntr, 1);\n              bout.outstr(s2);\n              if (cntr >= 13 && cntr < 18) {\n                bout.ansic(5);\n                bout.outstr(side1[cntr - 7]);\n                wwiv_y2 = bout.localIO()->WhereY() + 1;\n                wwiv_x2 = bout.localIO()->WhereX() + 1;\n              }\n              bout.outstr(\"\\x1b[K\");\n              s2[0] = '\\0';\n            }\n            sprintf(s2, \"\\x1b[%d;%dH\", wwiv_y2, wwiv_x2);\n            bout.outstr(s2);\n            s2[0] = '\\0';\n          }\n          if (bout.localIO()->WhereX() == (a()->user()->screen_width() - 1)) {\n            done = true;\n          }\n        } else {\n          if (bout.localIO()->WhereX() >= (a()->user()->screen_width() - 1)) {\n            done = true;\n          }\n        }\n      }\n    } else\n      switch (ch) {\n      case 7: {\n        if (a()->sess().chatting() != chatting_t::none && a()->sess().outcom()) {\n          bout.rputch(7);\n        }\n      } break;\n      case RETURN: /* C/R */\n        if (side == 0) {\n          side0[bout.localIO()->WhereY()][cp0] = 0;\n        } else {\n          side1[bout.localIO()->WhereY() - 13][cp1] = 0;\n        }\n        done = true;\n        break;\n      case BACKSPACE: { /* Backspace */\n        if (side == 0) {\n          if (cp0) {\n            if (side0[bout.localIO()->WhereY()][cp0 - 2] == 3) {\n              cp0 -= 2;\n              bout.ansic(0);\n            } else if (side0[bout.localIO()->WhereY()][cp0 - 1] == 8) {\n              cp0--;\n              bout.outchr(SPACE);\n            } else {\n              cp0--;\n              bout.bs();\n            }\n          }\n        } else if (cp1) {\n          if (side1[bout.localIO()->WhereY() - 13][cp1 - 2] == CC) {\n            cp1 -= 2;\n            bout.ansic(0);\n          } else if (side1[bout.localIO()->WhereY() - 13][cp1 - 1] == BACKSPACE) {\n            cp1--;\n            bout.outchr(SPACE);\n          } else {\n            cp1--;\n            bout.bs();\n          }\n        }\n      } break;\n      case CX: /* Ctrl-X */\n        while (bout.localIO()->WhereX() > begx) {\n          bout.bs();\n          if (side == 0) {\n            cp0 = 0;\n          } else {\n            cp1 = 0;\n          }\n        }\n        bout.ansic(0);\n        break;\n      case CW: /* Ctrl-W */\n        if (side == 0) {\n          if (cp0) {\n            do {\n              if (side0[bout.localIO()->WhereY()][cp0 - 2] == CC) {\n                cp0 -= 2;\n                bout.ansic(0);\n              } else if (side0[bout.localIO()->WhereY()][cp0 - 1] == BACKSPACE) {\n                cp0--;\n                bout.outchr(SPACE);\n              } else {\n                cp0--;\n                bout.bs();\n              }\n            } while ((cp0) && (side0[bout.localIO()->WhereY()][cp0 - 1] != SPACE) &&\n                     (side0[bout.localIO()->WhereY()][cp0 - 1] != BACKSPACE) &&\n                     (side0[bout.localIO()->WhereY()][cp0 - 2] != CC));\n          }\n        } else {\n          if (cp1) {\n            do {\n              if (side1[bout.localIO()->WhereY() - 13][cp1 - 2] == CC) {\n                cp1 -= 2;\n                bout.ansic(0);\n              } else if (side1[bout.localIO()->WhereY() - 13][cp1 - 1] == BACKSPACE) {\n                cp1--;\n                bout.outchr(SPACE);\n              } else {\n                cp1--;\n                bout.bs();\n              }\n            } while ((cp1) && (side1[bout.localIO()->WhereY() - 13][cp1 - 1] != SPACE) &&\n                     (side1[bout.localIO()->WhereY() - 13][cp1 - 1] != BACKSPACE) &&\n                     (side1[bout.localIO()->WhereY() - 13][cp1 - 2]));\n          }\n        }\n        break;\n      case CN: /* Ctrl-N */\n        if (side == 0) {\n          if ((bout.localIO()->WhereX()) && (cp0 < max_length)) {\n            bout.outchr(BACKSPACE);\n            side0[bout.localIO()->WhereY()][cp0++] = BACKSPACE;\n          }\n        } else if ((bout.localIO()->WhereX()) && (cp1 < max_length)) {\n          bout.outchr(BACKSPACE);\n          side1[bout.localIO()->WhereY() - 13][cp1++] = BACKSPACE;\n        }\n        break;\n      case CP: /* Ctrl-P */\n        if (side == 0) {\n          if (cp0 < max_length - 1) {\n            ch = bin.getkey();\n            if ((ch >= SPACE) && (ch <= 126)) {\n              side0[bout.localIO()->WhereY()][cp0++] = CC;\n              side0[bout.localIO()->WhereY()][cp0++] = ch;\n              bout.ansic(ch - 48);\n            }\n          }\n        } else {\n          if (cp1 < max_length - 1) {\n            ch = bin.getkey();\n            if ((ch >= SPACE) && (ch <= 126)) {\n              side1[bout.localIO()->WhereY() - 13][cp1++] = CC;\n              side1[bout.localIO()->WhereY() - 13][cp1++] = ch;\n              bout.ansic(ch - 48);\n            }\n          }\n        }\n        break;\n      case TAB: /* Tab */\n        if (side == 0) {\n          i = 5 - (cp0 % 5);\n          if (((cp0 + i) < max_length) &&\n              ((bout.localIO()->WhereX() + i) < a()->user()->screen_width())) {\n            i = 5 - ((bout.localIO()->WhereX() + 1) % 5);\n            for (i1 = 0; i1 < i; i1++) {\n              side0[bout.localIO()->WhereY()][cp0++] = SPACE;\n              bout.outchr(SPACE);\n            }\n          }\n        } else {\n          i = 5 - (cp1 % 5);\n          if (((cp1 + i) < max_length) &&\n              ((bout.localIO()->WhereX() + i) < a()->user()->screen_width())) {\n            i = 5 - ((bout.localIO()->WhereX() + 1) % 5);\n            for (i1 = 0; i1 < i; i1++) {\n              side1[bout.localIO()->WhereY() - 13][cp1++] = SPACE;\n              bout.outchr(SPACE);\n            }\n          }\n        }\n        break;\n      }\n  } while (!done && !a()->sess().hangup());\n\n  if (ch != RETURN) {\n    if (side == 0) {\n      i = cp0 - 1;\n      while ((i > 0) && (side0[bout.localIO()->WhereY()][i] != SPACE) &&\n             ((side0[bout.localIO()->WhereY()][i] != BACKSPACE) ||\n              (side0[bout.localIO()->WhereY()][i - 1] == CC))) {\n        i--;\n      }\n      if ((i > static_cast<int>(bout.localIO()->WhereX() / 2)) && (i != (cp0 - 1))) {\n        i1 = cp0 - i - 1;\n        for (i = 0; i < i1; i++) {\n          bout.outchr(BACKSPACE);\n        }\n        for (i = 0; i < i1; i++) {\n          bout.outchr(SPACE);\n        }\n        rollover->clear();\n        for (i = 0; i < i1; i++) {\n          rollover->push_back(side0[bout.localIO()->WhereY()][cp0 - i1 + i]);\n        }\n        cp0 -= i1;\n      }\n      side0[bout.localIO()->WhereY()][cp0] = '\\0';\n    } else {\n      i = cp1 - 1;\n      while ((i > 0) && (side1[bout.localIO()->WhereY() - 13][i] != SPACE) &&\n             ((side1[bout.localIO()->WhereY() - 13][i] != BACKSPACE) ||\n              (side1[bout.localIO()->WhereY() - 13][i - 1] == CC))) {\n        i--;\n      }\n      if ((i > static_cast<int>(bout.localIO()->WhereX() / 2)) && (i != (cp1 - 1))) {\n        i1 = cp1 - i - 1;\n        for (i = 0; i < i1; i++) {\n          bout.outchr(BACKSPACE);\n        }\n        for (i = 0; i < i1; i++) {\n          bout.outchr(SPACE);\n        }\n        rollover->clear();\n        for (i = 0; i < i1; i++) {\n          rollover->push_back(side1[bout.localIO()->WhereY() - 13][cp1 - i1 + i]);\n        }\n        cp1 -= i1;\n      }\n      side1[bout.localIO()->WhereY() - 13][cp1] = '\\0';\n    }\n  }\n  if (crend && bout.localIO()->WhereY() != 11 && bout.localIO()->WhereY() < 23) {\n    bout.nl();\n  }\n  if (side == 0) {\n    cp0 = 0;\n  } else {\n    cp1 = 0;\n  }\n}\n\n/****************************************************************************/\n\n/*\n * High-level chat function, calls two_way_chat() if appropriate, else\n * uses normal TTY chat.\n */\n\nvoid chat1(const char* chat_line, bool two_way) {\n  if (!okansi()) {\n    two_way = false;\n  }\n\n  auto sysop_name = select_chat_name();\n  if (sysop_name.empty()) {\n    return;\n  }\n\n  a()->sess().clear_chatcall();\n  if (two_way) {\n    write_inst(INST_LOC_CHAT2, 0, INST_FLAGS_NONE);\n    a()->sess().chatting(chatting_t::two_way);\n  } else {\n    write_inst(INST_LOC_CHAT, 0, INST_FLAGS_NONE);\n    a()->sess().chatting(chatting_t::one_way);\n  }\n  auto tc_start = steady_clock::now();\n  File chatFile(FilePath(a()->config()->gfilesdir(), DROPFILE_CHAIN_TXT));\n\n  auto line = bout.SaveCurrentLine();\n\n  bout.nl(2);\n  const auto saved_topdata = bout.localIO()->topdata();\n  if (two_way) {\n    a()->Cls();\n    cp0 = cp1 = 0;\n    if (bout.localIO()->GetDefaultScreenBottom() == 24) {\n      bout.localIO()->topdata(LocalIO::topdata_t::none);\n      a()->UpdateTopScreen();\n    }\n    bout.cls();\n    wwiv_x2 = 1;\n    wwiv_y2 = 13;\n    bout.goxy(1, 1);\n    wwiv_x1 = bout.localIO()->WhereX();\n    wwiv_y1 = bout.localIO()->WhereY();\n    bout.goxy(1, 12);\n    bout.ansic(7);\n    for (auto screencount = 0; screencount < a()->user()->screen_width(); screencount++) {\n      bout.outchr('\\xCD', true);\n    }\n    bout.flush();\n    const auto unn = a()->user()->name_and_number();\n    const auto s = fmt::format(\"|#4 {} chatting with {} \", sysop_name, unn);\n    const auto x = a()->user()->screen_width() - wwiv::stl::size_int(stripcolors(s)) / 2;\n    bout.goxy(std::max<int>(x, 0), 12);\n    bout.outstr(s);\n    bout.goxy(1, 1);\n  }\n  bout.print(\"|#7{}'s here...\", sysop_name);\n  bout.nl(2);\n  std::string rollover = chat_line;\n\n  if (two_way) {\n    side0 = new char[MAXLINES_SIDE][MAXLEN];\n    side1 = new char[MAXLINES_SIDE][MAXLEN];\n    if (!side0 || !side1) {\n      two_way = false;\n    }\n  }\n  do {\n    std::string s;\n    if (two_way) {\n      two_way_chat(&rollover, MAXLEN, true, sysop_name);\n    } else {\n      inli(&s, &rollover, MAXLEN, true, false);\n    }\n    if (s_chat_file && !two_way) {\n      if (!chatFile.IsOpen()) {\n        bout.localIO()->Puts(\"-] Chat file opened.\\r\\n\");\n        if (chatFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n          chatFile.Seek(0L, File::Whence::end);\n          const auto t = times();\n          const auto f = fulldate();\n          chatFile.Write(fmt::format(\"\\r\\n\\r\\nChat file opened {} {}\\r\\n\", f, t));\n          chatFile.Write(\"----------------------------------\\r\\n\\r\\n\");\n        }\n      }\n      s.append(\"\\r\\n\");\n    } else if (chatFile.IsOpen()) {\n      chatFile.Close();\n      bout.localIO()->Puts(\"-] Chat file closed.\\r\\n\");\n    }\n    if (a()->sess().hangup()) {\n      a()->sess().chatting(chatting_t::none);\n    }\n  } while (a()->sess().chatting() != chatting_t::none);\n\n  s_chat_file = false;\n  if (side0) {\n    delete[] side0;\n    side0 = nullptr;\n  }\n  if (side1) {\n    delete[] side1;\n    side1 = nullptr;\n  }\n  bout.ansic(0);\n\n  if (two_way) {\n    bout.cls();\n  }\n\n  bout.nl();\n  bout.outstr(\"|#7Chat mode over...\\r\\n\\n\");\n  a()->sess().chatting(chatting_t::none);\n  auto tc_used = duration_cast<seconds>(steady_clock::now() - tc_start);\n  a()->add_extratimecall(tc_used);\n  bout.localIO()->topdata(saved_topdata);\n  if (a()->sess().IsUserOnline()) {\n    a()->UpdateTopScreen();\n  }\n  bout.RestoreCurrentLine(line);\n  bout.clreol();\n}\n"
  },
  {
    "path": "bbs/syschat.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_SYSCHAT_H__\n#define __INCLUDED_BBS_SYSCHAT_H__\n\nvoid toggle_chat_file();\nvoid RequestChat();\nvoid chat1(const char *chat_line, bool two_way);\n\n#endif  // __INCLUDED_BBS_SYSCHAT_H__"
  },
  {
    "path": "bbs/sysopf.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/sysopf.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/bbsutl1.h\"\n#include \"bbs/bbsutl2.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/email.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/finduser.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/multinst.h\"\n#include \"bbs/read_message.h\"\n#include \"bbs/shortmsg.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/uedit.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/arword.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/msgapi/message_utils_wwiv.h\"\n#include \"sdk/net/networks.h\"\n\n#include <memory>\n#include <string>\n\nusing wwiv::core::IniFile;\nusing wwiv::core::FilePath;\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::msgapi;\n\nvoid prstatus() {\n  a()->status_manager()->reload_status();\n  bout.cls();\n  if (!a()->config()->newuser_password().empty()) {\n    bout.print(\"|#9New User Pass   : {}\\r\\n\", a()->config()->newuser_password());\n  }\n  bout.print(\"|#9Board is        : {}\\r\\n\", a()->config()->closed_system() ? \"Closed\" : \"Open\");\n\n  const auto status = a()->status_manager()->get_status();\n  const auto t = times();\n  bout.print(\"|#9Number Users    : |#2{}\\r\\n\", status->num_users());\n  bout.print(\"|#9Number Calls    : |#2{}\\r\\n\", status->caller_num());\n  bout.print(\"|#9Last Date       : |#2{}\\r\\n\", status->last_date());\n  bout.print(\"|#9Time            : |#2{}\\r\\n\", t);\n  bout.print(\"|#9Active Today    : |#2{}\\r\\n\", status->active_today_minutes());\n  bout.print(\"|#9Calls Today     : |#2{}\\r\\n\", status->calls_today());\n  bout.print(\"|#9Net Posts Today : |#2{}\\r\\n\", status->msgs_today() - status->localposts());\n  bout.print(\"|#9Local Post Today: |#2{}\\r\\n\", status->localposts());\n  bout.print(\"|#9E Sent Today    : |#2{}\\r\\n\", status->email_today());\n  bout.print(\"|#9F Sent Today    : |#2{}\\r\\n\", status->feedback_today());\n  bout.print(\"|#9Uploads Today   : |#2{}\\r\\n\", status->uploads_today());\n\n  auto feedback_waiting = 0;\n  if (const auto sysop = a()->users()->readuser(1)) {\n    feedback_waiting = sysop->email_waiting();\n  }\n  bout.print(\"|#9Feedback Waiting: |#2{}\\r\\n\", feedback_waiting);\n  bout.print(\"|#9Sysop           : |#2{}\\r\\n\", sysop2() ? \"Available\" : \"NOT Available\");\n  bout.print(\"|#9Q-Scan Pointer  : |#2{}\\r\\n\", status->qscanptr());\n\n  if (num_instances() > 1) {\n    multi_instance();\n  }\n}\n\n// returns true if user deleted.\nstatic bool valuser_delete(int user_number) {\n  bout.nl();\n  bout.outstr(\"|#5Delete? \");\n  if (bin.yesno()) {\n    a()->users()->delete_user(user_number);\n    bout.outstr(\"\\r\\n|#6Deleted.\\r\\n\\n\");\n    return true;\n  }\n  bout.outstr(\"\\r\\n|#3NOT deleted.\\r\\n\");\n  return false;\n}\n\nstatic void valuser_manual(User& user) {\n  bout.print(\"|#9SL  : |#2{}\\r\\n\", user.sl());\n  if (user.sl() < a()->sess().effective_sl()) {\n    bout.outstr(\"|#9New : \");\n    const auto sl = bin.input_number(user.sl(), 0, 255);\n    user.sl(sl);\n  }\n  bout.nl();\n  bout.print(\"|#9DSL : |#2{}\\r\\n\", user.dsl());\n  if (user.dsl() < a()->user()->dsl()) {\n    bout.outstr(\"|#9New ? \");\n    const auto dsl = bin.input_number(user.dsl(), 0, 255);\n    user.dsl(dsl);\n  }\n  bout.nl();\n  if (auto allowed_ar = word_to_arstr(a()->user()->ar_int(), \"\"); !allowed_ar.empty()) {\n    allowed_ar.push_back(RETURN);\n    do {\n      bout.print(\"|#9AR  : |#2{}\\r\\n\", word_to_arstr(user.ar_int(), \"\"));\n      bout.outstr(\"|#9Togl? \");\n      const auto ch_ar = onek(allowed_ar);\n      if (ch_ar == RETURN) {\n        break;\n      }\n      const auto ar = ch_ar - 'A';\n      user.toggle_ar(1 << ar);\n    } while (!a()->sess().hangup());\n  }\n  bout.nl();\n  if (auto allowed_dar = word_to_arstr(a()->user()->dar_int(), \"\"); !allowed_dar.empty()) {\n    allowed_dar.push_back(RETURN);\n    do {\n      bout.print(\"|#9DAR : |#2{}\\r\\n\", word_to_arstr(user.dar_int(), \"\"));\n      bout.outstr(\"|#9Togl? \");\n      const auto ch_dar = onek(allowed_dar);\n      if (ch_dar == RETURN) {\n        break;\n      }\n      const auto dar = ch_dar - 'A';\n      user.toggle_dar(1 << dar);\n    } while (!a()->sess().hangup());\n  }\n  bout.nl();\n\n  const std::string r{restrict_string};\n  std::string allowed{restrict_string};\n  allowed.push_back(' ');\n  allowed.push_back(RETURN);\n  do {\n    std::string user_rs;\n    for (auto i = 0; i <= 15; i++) {\n      user_rs.push_back(user.has_restrict(1 << i) ? restrict_string[i] : ' ');\n    }\n    bout.print(\"      |#2{}\\r\\n\", restrict_string);\n    bout.print(\"|#9Rstr: |#2{}\\r\\n\", user_rs);\n    bout.outstr(\"|#9Togl? \");\n    const auto ch = onek(allowed);\n    if (ch != RETURN && ch != SPACE && ch != '?') {\n      if (const auto pos = r.find(ch); pos != std::string::npos) {\n        user.toggle_restrict(1 << pos);\n      }\n    }\n    if (ch == RETURN) {\n      break;\n    }\n    if (ch == '?') {\n      bout.print_help_file(SRESTRCT_NOEXT);\n    }\n  } while (!a()->sess().hangup());\n}\n\nstatic void valuser_auto(User& user) {\n  for (auto i = 1; i <= 10; i++) {\n    const auto& v = a()->config()->auto_val(i);\n    bout.print(\"|#2{:>2}|#9) |#1{:<30.30} |#9(SL: |#5{:<3}|#9 DSL: |#5{:<3}|#9)\\r\\n\", i, v.name, v.sl, v.dsl);\n  }\n  bout.nl();\n  bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) Which Auto Validation: \");\n  const auto [num, key] = bin.input_number_hotkey(0, {'Q'}, 1, 10);\n  if (key == 'Q') {\n    return;\n  }\n  auto_val(num, &user);\n}\n\n// TODO(rushfan): This is copied from wwivconfig, hard to share there but\n// If we need this somewhere else, should move to SDK class.\nstatic void write_semaphore_if_user_online(const Config& config, int current_usernum) {\n  Instances instances(config);\n  if (!instances) {\n    std::cout << \"Unable to read Instance information.\";\n    return;\n  }\n\n  for (const auto& inst : instances) {\n    if (!inst.online()) {\n      continue;\n    }\n    if (inst.user_number() != current_usernum) {\n      continue;\n    }\n    // we have user.\n    const auto path = config.scratch_dir(inst.node_number());\n    const auto fn = FilePath(path, \"readuser.wwiv\");\n    if (TextFile tf(fn, \"wt\"); tf) {\n      tf.Write(\"User edited in wwivconfig usereditor\");\n    }\n    return;\n  }\n}\n\nvoid valuser(int user_number) {\n\n  bout.nl();\n  auto o = a()->users()->readuser(user_number);\n  if (!o) {\n    bout.outstr(\"\\r\\n|#6No Such User.\\r\\n\\n\");\n    return;\n  }\n  auto user = o.value();\n  while (true) {\n    bout.cls();\n    bout.litebar(\"WWIV Quick User Validation\");\n    bout.nl();\n    const auto unn = a()->names()->UserName(user_number);\n    bout.print(\"|#9Name: |#2{}\\r\\n\", unn);\n    if (a()->config()->newuser_config().use_real_name != newuser_item_type_t::unused) {\n      bout.print(\"|#9RN  : |#2{}\\r\\n\", user.real_name());\n    }\n    if (a()->config()->newuser_config().use_voice_phone != newuser_item_type_t::unused) {\n      bout.print(\"|#9PH  : |#2{}\\r\\n\", user.voice_phone());\n    }\n    if (a()->config()->newuser_config().use_birthday != newuser_item_type_t::unused) {\n      bout.print(\"|#9Age : |#2{} {}\\r\\n\", user.age(), user.gender());\n    }\n    if (a()->config()->newuser_config().use_computer_type != newuser_item_type_t::unused) {\n      bout.print(\"|#9Comp: |#2{}\\r\\n\", ctypes(user.computer_type()));\n    }\n    if (user.note().empty()) {\n      bout.print(\"|#9Note: |#2{}\\r\\n\", user.note());\n    }\n    bout.print(\"|#9SL  : |#2{}\\r\\n\", user.sl());\n    bout.print(\"|#9DSL : |#2{}\\r\\n\", user.sl());\n    bout.nl(2);\n    bout.outstr(\"|#9(|#2Q|#9=|#1Quit|#9) (|#2D|#9)elete, (|#2M|#9)anual, (|#2A|#9)utoval : \");\n    switch (onek(\"ADMQ\", true)) { \n    case 'A':\n      valuser_auto(user);\n      write_semaphore_if_user_online(*a()->config(), user.usernum());\n      break;\n    case 'D':\n      if (valuser_delete(user_number)) {\n        return;\n      }\n      break;\n    case 'M':\n      valuser_manual(user);\n      write_semaphore_if_user_online(*a()->config(), user.usernum());\n      break;\n    case 'Q':\n      bout.nl(2);\n      return;\n    }\n    if (!a()->users()->writeuser(&user, user_number)) {\n      bout.print(\"|#6Error writing user #{}\\r\\n\", user_number);\n      bout.pausescr();\n    }\n  }\n}\n\nenum class net_search_type_t {\n  UNKNOWN, NET_SEARCH_SUBSTR, NET_SEARCH_AREACODE, NET_SEARCH_GROUP, NET_SEARCH_SC,\n  NET_SEARCH_AC, NET_SEARCH_GC, NET_SEARCH_NC, NET_SEARCH_PHSUBSTR,\n  NET_SEARCH_NOCONNECT, NET_SEARCH_ALL };\n\nbool print_wwivnet_net_listing(const Network& net) {\n  int gn = 0;\n  char s2[101], bbstype;\n\n  while (!a()->sess().hangup()) {\n    char s[255];\n    auto abort = false;\n    auto cmdbit = net_search_type_t::UNKNOWN;\n    uint16_t slist = 0;\n    char substr[81], acstr[4], phstr[13];\n    substr[0] = 0;\n    acstr[0] = 0;\n    phstr[0] = 0;\n\n    bout.cls();\n    bout.nl();\n    bout.print(\"|#9Network|#2: |#1{}\\r\\n\", net.name);\n    bout.nl();\n\n    bout.outstr(\"|#21|#9) List All\\r\\n\");\n    bout.outstr(\"|#22|#9) Area Code\\r\\n\");\n    bout.outstr(\"|#23|#9) Group\\r\\n\");\n    bout.outstr(\"|#24|#9) Subs Coordinators\\r\\n\");\n    bout.outstr(\"|#25|#9) Area Coordinators\\r\\n\");\n    bout.outstr(\"|#26|#9) Group Coordinators\\r\\n\");\n    bout.outstr(\"|#27|#9) Net Coordinator\\r\\n\");\n    bout.outstr(\"|#28|#9) BBS Name SubString\\r\\n\");\n    bout.outstr(\"|#29|#9) Phone SubString\\r\\n\");\n    bout.outstr(\"|#20|#9) Unconnected Systems\\r\\n\");\n    bout.outstr(\"|#2Q|#9) Quit NetList\\r\\n\");\n    bout.nl();\n    bout.outstr(\"|#9Select: |#2\");\n    switch (auto cmd = onek(\"Q1234567890\"); cmd) {\n    case 'Q':\n      return true;\n    case '1':\n      cmdbit = net_search_type_t::NET_SEARCH_ALL;\n      break;\n    case '2':\n      cmdbit = net_search_type_t::NET_SEARCH_AREACODE;\n      bout.nl();\n      bout.outstr(\"|#1Enter Area Code|#2: |#0\");\n      bin.input(acstr, 3);\n      if (strlen(acstr) != 3) {\n        abort = true;\n      }\n      if (!abort) {\n        for (int i = 0; i < 3; i++) {\n          if (acstr[i] < '0' || acstr[i] > '9') {\n            abort = true;\n          }\n        }\n      }\n      if (abort) {\n        bout.outstr(\"|#6Area code must be a 3-digit number!\\r\\n\");\n        bout.pausescr();\n        continue;\n      }\n      break;\n    case '3':\n      cmdbit = net_search_type_t::NET_SEARCH_GROUP;\n      bout.nl();\n      bout.outstr(\"|#1Enter group number|#2: |#0\");\n      bin.input(s, 2);\n      if (s[0] == 0 || to_number<int>(s) < 1) {\n        bout.outstr(\"|#6Invalid group number!\\r\\n\");\n        bout.pausescr();\n        continue;\n      }\n      gn = to_number<int>(s);\n      break;\n    case '4':\n      cmdbit = net_search_type_t::NET_SEARCH_SC;\n      break;\n    case '5':\n      cmdbit = net_search_type_t::NET_SEARCH_AC;\n      break;\n    case '6':\n      cmdbit = net_search_type_t::NET_SEARCH_GC;\n      break;\n    case '7':\n      cmdbit = net_search_type_t::NET_SEARCH_NC;\n      break;\n    case '8':\n      cmdbit = net_search_type_t::NET_SEARCH_SUBSTR;\n      bout.nl();\n      bout.outstr(\"|#1Enter SubString|#2: |#0\");\n      bin.input(substr, 40);\n      if (substr[0] == 0) {\n        bout.outstr(\"|#6Enter a substring!\\r\\n\");\n        bout.pausescr();\n        continue;\n      }\n      break;\n    case '9':\n      cmdbit = net_search_type_t::NET_SEARCH_PHSUBSTR;\n      bout.nl();\n      bout.outstr(\"|#1Enter phone substring|#2: |#0\");\n      bin.input(phstr, 12);\n      if (phstr[0] == 0) {\n        bout.outstr(\"|#6Enter a phone substring!\\r\\n\");\n        bout.pausescr();\n        continue;\n      }\n      break;\n    case '0':\n      cmdbit = net_search_type_t::NET_SEARCH_NOCONNECT;\n      break;\n    default: \n      return true;\n    }\n\n    if (cmdbit == net_search_type_t::UNKNOWN) {\n      continue;\n    }\n\n    bout.nl();\n    bout.outstr(\"|#1Print BBS region info? \");\n    bool useregion = bin.yesno();\n\n    auto bbslist = BbsListNet::ReadBbsDataNet(net.dir);\n    if (bbslist.empty()) {\n      bout.print(\"|#6Error opening bbsdata.net in {}\\r\\n\", net.dir.string());\n      bout.pausescr();\n      continue;\n    }\n    to_char_array(s, \"000-000-0000\");\n    bout.nl(2);\n\n    bout.cls();\n    bout.litebar(fmt::format(\"Network list for: {}\", net.name));\n    for (const auto& b : bbslist.node_config()) {\n      char s1[101];\n      auto matched = false;\n      const auto& csne = b.second;\n      if (csne.forsys == net::WWIVNET_NO_NODE && cmdbit != net_search_type_t::NET_SEARCH_NOCONNECT) {\n        continue;\n      }\n      strcpy(s1, csne.phone);\n\n      if (csne.other & other_net_coord) {\n        bbstype = '&';\n      } else if (csne.other & other_group_coord) {\n        bbstype = '%';\n      } else if (csne.other & other_area_coord) {\n        bbstype = '^';\n      } else if (csne.other & other_subs_coord) {\n        bbstype = '~';\n      } else {\n        bbstype = ' ';\n      }\n\n      strcpy(s2, csne.name);\n      for (size_t i1 = 0; i1 < size(s2); i1++) {\n        s2[i1] = to_upper_case_char(s2[i1]);\n      }\n\n      switch (cmdbit) {\n      case net_search_type_t::NET_SEARCH_ALL:\n        matched = true;\n        break;\n      case net_search_type_t::NET_SEARCH_AREACODE:\n        if (strncmp(acstr, csne.phone, 3) == 0) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_GROUP:\n        if (gn == csne.group) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_SC:\n        if (csne.other & other_subs_coord) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_AC:\n        if (csne.other & other_area_coord) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_GC:\n        if (csne.other & other_group_coord) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_NC:\n        if (csne.other & other_net_coord) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_SUBSTR:\n        if (strstr(s2, substr) != nullptr) {\n          matched = true;\n        } else {\n          char s3[81];\n          sprintf(s3, \"@%u\", csne.sysnum);\n          if (strstr(s3, substr) != nullptr) {\n            matched = true;\n          }\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_PHSUBSTR:\n        if (strstr(s1, phstr) != nullptr) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::NET_SEARCH_NOCONNECT:\n        if (csne.forsys == WWIVNET_NO_NODE) {\n          matched = true;\n        }\n        break;\n      case net_search_type_t::UNKNOWN:\n        continue;\n      }\n\n      if (matched) {\n        slist++;\n        if (!useregion && slist == 1) {\n          bout.bpla(\"|#1 Node  Phone         BBS Name                                 Hop  Next Gr\",\n                    &abort);\n          bout.bpla(\"|#7-----  ============  ---------------------------------------- === ----- --\",\n                    &abort);\n        } else {\n          if (useregion && strncmp(s, csne.phone, 3) != 0) {\n            strcpy(s, csne.phone);\n            const auto regions_dir = FilePath(a()->config()->datadir(), REGIONS_DIR);\n            const auto town_fn =\n                fmt::sprintf(\"%s.%-3u\", REGIONS_DIR, to_number<unsigned int>(csne.phone));\n            std::string areacode;\n            if (File::Exists(FilePath(regions_dir, town_fn))) {\n              auto town = fmt::sprintf(\"%c%c%c\", csne.phone[4], csne.phone[5], csne.phone[6]);\n              areacode =\n                  describe_area_code_prefix(to_number<int>(csne.phone), to_number<int>(town));\n            } else {\n              areacode = describe_area_code(to_number<int>(csne.phone));\n            }\n            const auto line = fmt::sprintf(\"\\r\\n%s%s\\r\\n\", \"|#2Region|#0: |#2\", areacode);\n            bout.bpla(line, &abort);\n            bout.bpla(\n                \"|#1 Node  Phone         BBS Name                                 Hop  Next Gr\",\n                &abort);\n            bout.bpla(\n                \"|#7-----  ============  ---------------------------------------- === ----- --\",\n                &abort);\n          }\n        }\n        std::string line;\n        if (cmdbit != net_search_type_t::NET_SEARCH_NOCONNECT) {\n          line = fmt::sprintf(\"%5u%c %12s  %-40s %3d %5u %2d\", csne.sysnum, bbstype, csne.phone,\n                              csne.name, csne.numhops, csne.forsys, csne.group);\n        } else {\n          line = fmt::sprintf(\"%5u%c %12s  %-40s%s%2d\", csne.sysnum, bbstype, csne.phone, csne.name,\n                              \" |17|15--- ----- |#0\", csne.group);\n        }\n        bout.bpla(line, &abort);\n      }\n    }\n    if (!abort && slist) {\n      bout.nl();\n      bout.print(\"|#1Systems Listed |#7: |#2{}\", slist);\n    }\n    bout.nl(2);\n    bout.pausescr();\n  }\n  return false;\n}\n\nstatic bool print_ftn_net_listing(Network& net) {\n  if (!net.try_load_nodelist()) {\n    return false;\n  }\n\n  bout.cls();\n  bout.nl();\n  bout.print(\"|#9Network|#2: |#1{}\\r\\n\", net.name);\n  bout.nl();\n\n  bout.outstr(\"|#21|#9) List All\\r\\n\");\n  bout.outstr(\"|#22|#9) Zone\\r\\n\");\n  bout.outstr(\"|#23|#9) BBS Name SubString\\r\\n\");\n  bout.outstr(\"|#2Q|#9) Quit NetList\\r\\n\");\n  bout.nl();\n  bout.outstr(\"|#9Select: |#2\");\n  auto zone = 0;\n  std::string name_part;\n  switch (const auto cmd = onek(\"Q123\"); cmd) {\n  case 'Q': {\n    return true;\n  }\n  case '2': {\n    bout.nl();\n    bout.outstr(\"|#9Enter Zone Number|#7: |#0\");\n    const auto r = bin.input_number_hotkey(zone, {'Q'}, 0, 37627);\n    if (r.key == 'Q') {\n      return false;\n    }\n    zone = r.num;\n  } break;\n  case '3': {\n    zone = 0;\n    bout.nl();\n    bout.outstr(\"|#9Enter Name Substring|#7: |#0\");\n    name_part = bin.input_upper(20);\n  } break;\n  }\n  bool abort = false;\n  bout.cls();\n  bout.litebar(fmt::format(\"Network list for: {}\", net.name));\n  bout.nl(2);\n  bout.bpla(\"|#2 Address             BBS Name\", &abort);\n  bout.bpla(\"|#9 ------------------  =============================================\", &abort);\n\n  auto count = 0;\n  if (net.nodelist->initialized()) {\n    for (const auto& e : net.nodelist->entries()) {\n      if (zone != 0 && e.first.zone() != zone) {\n        continue;\n      }\n      if (!name_part.empty()) {\n        const auto bbs_name = ToStringUpperCase(e.second.name());\n        const auto idx = bbs_name.find(name_part);\n        if (idx == std::string::npos) {\n          continue;\n        }\n      }\n      bout.print(\" |#5{:<18.18}  |#1{}\\r\\n\", e.first.as_string(false, false), e.second.name());\n      if (bin.checka()) {\n        break;\n      }\n      ++count;\n    }\n  }\n  if (!abort) {\n    bout.nl();\n    bout.print(\"|#9Systems Listed |#7: |#2{}\", count);\n  }\n  bout.nl(2);\n  bout.pausescr();\n  return false;\n}\n\nvoid query_print_net_listing(bool force_pause) {\n  bool had_pause{false};\n\n  a()->status_manager()->reload_status();\n\n  if (a()->nets().empty()) {\n    return;\n  }\n\n  write_inst(INST_LOC_NETLIST, 0, INST_FLAGS_NONE);\n\n  if (force_pause) {\n    had_pause = a()->user()->pause();\n    if (had_pause) {\n      a()->user()->toggle_flag(User::pauseOnPage);\n    }\n  }\n  auto at_exit = finally([=] {\n  if (force_pause && had_pause) {\n    a()->user()->toggle_flag(User::pauseOnPage);\n  }\n    \n  });\n\n  while (!a()->sess().hangup()) {\n    auto current_net = 0;\n    bout.cls();\n    if (wwiv::stl::ssize(a()->nets()) > 1) {\n      std::set<char> odc;\n      std::string onx{'Q'};\n      bout.nl();\n      for (int i = 0; i < size_int(a()->nets()); i++) {\n        if (i < 9) {\n          onx.push_back(static_cast<char>(i + '1'));\n        } else {\n          const int odci = (i + 1) / 10;\n          odc.insert(static_cast<char>(odci + '0'));\n        }\n        bout.print(\"|#2{}|#9)|#1 {}\\r\\n\", i + 1, a()->nets()[i].name);\n      }\n      bout.outstr(\"|#2Q|#9)|#1 Quit\\r\\n\\n\");\n      bout.outstr(\"|#9Which network? |#2\");\n      if (wwiv::stl::ssize(a()->nets()) < 9) {\n        if (const char ch = onek(onx); ch == 'Q') {\n          return;\n        } else {\n          current_net = ch - '1';\n        }\n      } else {\n        if (auto mmk = mmkey(odc); mmk == \"Q\") {\n          return;\n        } else {\n          current_net = to_number<int>(mmk) - 1;\n        }\n      }\n\n      if (current_net < 0 || current_net > size_int(a()->nets())) {\n        continue;\n      }\n    }\n    if (auto & net = a()->nets()[current_net]; net.type == network_type_t::wwivnet) {\n      if (print_wwivnet_net_listing(net)) {\n        return;\n      }\n    } else if (net.type == network_type_t::ftn) {\n      if (!net.try_load_nodelist()) {\n        continue;\n      }\n      if (print_ftn_net_listing(net)) {\n        return;\n      }\n    }\n    \n  }\n}\n\nvoid mailr() {\n  mailrec m, m1;\n  filestatusrec fsr;\n\n  auto pFileEmail(OpenEmailFile(false));\n  if (!pFileEmail->IsOpen()) {\n    return;\n  }\n  auto nRecordNumber = (pFileEmail->length() / sizeof(mailrec)) - 1;\n  char c = ' ';\n  while (nRecordNumber >= 0 && c != 'Q' && !a()->sess().hangup()) {\n    pFileEmail->Seek(nRecordNumber * sizeof(mailrec), File::Whence::begin);\n    pFileEmail->Read(&m, sizeof(mailrec));\n    if (m.touser != 0) {\n      pFileEmail->Close();\n      do {\n        User user;\n        a()->users()->readuser(&user, m.touser);\n        const auto unn = a()->names()->UserName(m.touser);\n        bout.outstr(\"|#9  To|#7: \");\n        bout.ansic(a()->GetMessageColor());\n        bout.pl(unn);\n        set_net_num(network_number_from(&m));\n        bout.outstr(\"|#9Subj|#7: \");\n        bout.ansic(a()->GetMessageColor());\n        bout.pl(m.title);\n        if (m.status & status_file) {\n          File attachDat(FilePath(a()->config()->datadir(), ATTACH_DAT));\n          if (attachDat.Open(File::modeReadOnly | File::modeBinary)) {\n            bool found = false;\n            auto lAttachFileSize = attachDat.Read(&fsr, sizeof(fsr));\n            while (lAttachFileSize > 0 && !found) {\n              if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                bout.print(\"|#9Filename.... |#2{} ({} bytes)|#0\\r\\n\", fsr.filename, fsr.numbytes);\n                found = true;\n              }\n              if (!found) {\n                lAttachFileSize = attachDat.Read(&fsr, sizeof(fsr));\n              }\n            }\n            if (!found) {\n              bout.outstr(\"|#1Filename|#0.... |#2File : Unknown or Missing|#0\\r\\n\");\n            }\n            attachDat.Close();\n          } else {\n            bout.outstr(\"|#1Filename|#0.... |#2|#2File : Unknown or Missing|#0\\r\\n\");\n          }\n        }\n        bool next{false};\n        int fake_msgno = -1;\n        if (auto msg =\n                read_type2_message(&m.msg, m.anony & 0x0f, true, \"email\", m.fromsys, m.fromuser)) {\n          display_type2_message(fake_msgno, msg.value(), &next);\n        }\n        bout.outstr(\"|#2R,D,Q,<space>  : \");\n        if (next) {\n          c = ' ';\n        } else {\n          c = onek(\"QRD \");\n        }\n        if (c == 'D') {\n          pFileEmail = OpenEmailFile(true);\n          pFileEmail->Seek(nRecordNumber * sizeof(mailrec), File::Whence::begin);\n          pFileEmail->Read(&m1, sizeof(mailrec));\n          if (memcmp(&m, &m1, sizeof(mailrec)) == 0) {\n            delmail(*pFileEmail.get(), nRecordNumber);\n            bool found = false;\n            if (m.status & status_file) {\n              File attachFile(FilePath(a()->config()->datadir(), ATTACH_DAT));\n              if (attachFile.Open(File::modeReadWrite | File::modeBinary)) {\n                auto lAttachFileSize = attachFile.Read(&fsr, sizeof(fsr));\n                while (lAttachFileSize > 0 && !found) {\n                  if (m.daten == static_cast<uint32_t>(fsr.id)) {\n                    found = true;\n                    fsr.id = 0;\n                    attachFile.Seek(static_cast<long>(sizeof(filestatusrec)) * -1L, File::Whence::current);\n                    attachFile.Write(&fsr, sizeof(filestatusrec));\n                    File::Remove(FilePath(a()->GetAttachmentDirectory(), fsr.filename));\n                  } else {\n                    attachFile.Read(&fsr, sizeof(filestatusrec));\n                  }\n                }\n                attachFile.Close();\n              }\n            }\n          } else {\n            bout.outstr(\"Mail file changed; try again.\\r\\n\");\n          }\n          pFileEmail->Close();\n          if (!a()->sess().IsUserOnline() && m.touser == 1 && m.tosys == 0) {\n            a()->user()->email_waiting(a()->user()->email_waiting() - 1);\n          }\n        }\n        bout.nl(2);\n      } while (c == 'R' && !a()->sess().hangup());\n\n      pFileEmail = OpenEmailFile(false);\n      if (!pFileEmail->IsOpen()) {\n        break;\n      }\n    }\n    nRecordNumber -= 1;\n  }\n}\n\nvoid chuser() {\n  if (!ValidateSysopPassword() || !so()) {\n    return;\n  }\n\n  bout.outstr(\"|#9Enter user to change to: \");\n  const auto userName = bin.input(30, true);\n  const auto user_number = finduser1(userName);\n  if (user_number <= 0) {\n    bout.outstr(\"|#6Unknown user.\\r\\n\");\n    return;\n  }\n  a()->WriteCurrentUser();\n  write_qscn(a()->sess().user_num(), a()->sess().qsc, false);\n  a()->ReadCurrentUser(user_number);\n  read_qscn(user_number, a()->sess().qsc, false);\n  a()->sess().user_num(static_cast<uint16_t>(user_number));\n  a()->sess().effective_sl(255);\n  sysoplog(StrCat(\"#*#*#* Changed to \", a()->user()->name_and_number()));\n  changedsl();\n  a()->UpdateTopScreen();\n}\n\nvoid zlog() {\n  File file(FilePath(a()->config()->datadir(), ZLOG_DAT));\n  if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n  int i = 0;\n  bool abort = false;\n  zlogrec z;\n  file.Read(&z, sizeof(zlogrec));\n  bout.nl();\n  bout.cls();\n  bout.nl(2);\n  bout.bpla(\"|#2  Date     Calls  Active   Posts   Email   Fback    U/L    %Act   T/user\", &abort);\n  bout.bpla(\"|#7--------   -----  ------   -----   -----   -----    ---    ----   ------\", &abort);\n  while (i < 97 && !abort && !a()->sess().hangup() && z.date[0] != 0) {\n    int nTimePerUser = 0;\n    if (z.calls) {\n      nTimePerUser = z.active / z.calls;\n    }\n    auto buffer = fmt::sprintf(\n        \"%s    %4d    %4d     %3d     %3d     %3d    %3d     %3d      %3d|16\", z.date, z.calls,\n        z.active, z.posts, z.email, z.fback, z.up, 10 * z.active / 144, nTimePerUser);\n    // alternate colors to make it easier to read across the lines\n    if (i % 2) {\n      bout.outstr(\"|#1\");\n      bout.bpla(buffer, &abort);\n    } else {\n      bout.outstr(\"|#3\");\n      bout.bpla(buffer, &abort);\n    }\n    ++i;\n    if (i < 97) {\n      file.Seek(i * sizeof(zlogrec), File::Whence::begin);\n      file.Read(&z, sizeof(zlogrec));\n    }\n  }\n  file.Close();\n}\n\nvoid auto_purge() {\n  int days = 0;\n  int skipsl = 0;\n  {\n    IniFile ini(FilePath(a()->bbspath(), WWIV_INI),\n                StrCat(\"WWIV-\", a()->sess().instance_number()), INI_TAG);\n    if (ini.IsOpen()) {\n      days = ini.value<int>(\"AUTO_USER_PURGE\");\n      skipsl = ini.value<int>(\"NO_PURGE_SL\");\n    }\n  }\n\n  if (days < 60) {\n    if (days > 0) {\n      sysoplog(false, \"!!! WARNING: Auto-Purge canceled [AUTO_USER_PURGE < 60]\");\n      sysoplog(false, \"!!! WARNING: Edit WWIV.INI and Fix this\");\n    }\n    return;\n  }\n\n  const auto current_daten = daten_t_now();\n  int user_number = 1;\n  sysoplog(false, fmt::format(\"Auto-Purged Inactive Users (over {} days, SL less than {})\", days, skipsl));\n\n  do {\n    User user;\n    a()->users()->readuser(&user, user_number);\n    if (!user.exempt_auto_delete()) {\n      auto d = static_cast<int>((current_daten - user.last_daten()) / SECONDS_PER_DAY);\n      // if user is not already deleted && SL<NO_PURGE_SL && last_logon\n      // greater than AUTO_USER_PURGE days ago\n      if (!user.deleted() && user.sl() < skipsl && d > days) {\n        sysoplog(false, fmt::format(\"*** AUTOPURGE: Deleted User: #{} {}\", user_number, user.name()));\n        a()->users()->delete_user(user_number);\n      }\n    }\n    ++user_number;\n  } while (user_number <= a()->status_manager()->user_count());\n}\n\nvoid beginday(bool displayStatus) {\n  if (a()->GetBeginDayNodeNumber() > 0\n      && (a()->sess().instance_number() != a()->GetBeginDayNodeNumber())) {\n    // If BEGINDAYNODENUMBER is > 0 or defined in WWIV.INI only handle beginday events on that node number\n    a()->status_manager()->reload_status();\n    return;\n  }\n\n  const auto st = a()->status_manager()->get_status();\n  if (date() == st->last_date()) {\n    return;\n  }\n\n  a()->status_manager()->Run([&](Status& status) {\n    status.ensure_dates_valid();\n\n    if (displayStatus) {\n      bout.outstr(\"|#7* |#1Running Daily Maintenance...\\r\\n\");\n      bout.outstr(\"  |#7* |#1Updating system activity...\\r\\n\");\n    }\n\n    zlogrec z{};\n    to_char_array(z.date, status.last_date());\n    z.active = status.active_today_minutes();\n    z.calls = status.calls_today();\n    z.posts = status.localposts();\n    z.email = status.email_today();\n    z.fback = status.feedback_today();\n    z.up = status.uploads_today();\n    status.NewDay();\n\n    if (displayStatus) {\n      bout.outstr(\"  |#7* |#1Updating ZLOG information...\\r\\n\");\n    }\n    File fileZLog(FilePath(a()->config()->datadir(), ZLOG_DAT));\n    zlogrec z1{};\n    if (!fileZLog.Open(File::modeReadWrite | File::modeBinary)) {\n      fileZLog.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile, File::shareDenyNone);\n      z1.date[0] = '\\0';\n      z1.active = 0;\n      z1.calls = 0;\n      z1.posts = 0;\n      z1.email = 0;\n      z1.fback = 0;\n      z1.up = 0;\n      for (auto i = 0; i < 97; i++) {\n        fileZLog.Write(&z1, sizeof(zlogrec));\n      }\n    } else {\n      for (int i = 96; i >= 1; i--) {\n        fileZLog.Seek((i - 1) * sizeof(zlogrec), File::Whence::begin);\n        fileZLog.Read(&z1, sizeof(zlogrec));\n        fileZLog.Seek(i * sizeof(zlogrec), File::Whence::begin);\n        fileZLog.Write(&z1, sizeof(zlogrec));\n      }\n    }\n    fileZLog.Seek(0L, File::Whence::begin);\n    fileZLog.Write(&z, sizeof(zlogrec));\n    fileZLog.Close();\n\n    if (displayStatus) {\n      bout.outstr(\"  |#7* |#1Updating STATUS.DAT...\\r\\n\");\n    }\n  });\n  const auto nus = a()->config()->max_users() - st->num_users();\n  if (displayStatus) {\n    bout.outstr(\"  |#7* |#1Checking system directories and user space...\\r\\n\");\n  }\n\n  const auto fk = File::freespace_for_path(a()->config()->datadir());\n\n  if (fk < 512) {\n    ssm(1) << \"Only \" << fk << \"k free in data directory.\";\n  }\n  if (!a()->config()->closed_system() && nus < 15) {\n    ssm(1) << \"Only \" << nus << \" new user slots left.\";\n  }\n  if (!a()->beginday_cmd.empty()) {\n    LOG(INFO) << \"Beginday command not empty, executing: \" << a()->beginday_cmd;\n    wwiv::bbs::CommandLine cl(a()->beginday_cmd);\n    cl.args(create_chain_file());\n    ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_BEGINDAY));\n  }\n  if (displayStatus) {\n    bout.outstr(\"  |#7* |#1Purging inactive users (if enabled)...\\r\\n\");\n  }\n  auto_purge();\n  if (displayStatus) {\n    bout.outstr(\"|#7* |#1Done!\\r\\n\");\n  }\n\n  sysoplog(false, \"* Ran Daily Maintenance...\");\n  LOG(INFO) << \"Completed executing beginday\";\n}\n\n\n"
  },
  {
    "path": "bbs/sysopf.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_SYSOPF_H\n#define INCLUDED_BBS_SYSOPF_H\n\nvoid prstatus();\nvoid valuser(int user_number);\nvoid query_print_net_listing(bool force_pause);\nvoid mailr();\nvoid chuser();\nvoid zlog();\nvoid auto_purge();\nvoid beginday(bool displayStatus);\n\n\n#endif\n"
  },
  {
    "path": "bbs/sysoplog.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/sysoplog.h\"\n\n#include \"bbs/bbs.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"common/context.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n// Local function prototypes\nenum class log_cmd_t{ log_string, log_char };\nvoid AddLineToSysopLogImpl(log_cmd_t cmd, const std::string& text);\n\n\n/*\n* Creates sysop log filename in s, from date string.\n*/\nstd::string sysoplog_filename(const std::string& d) {\n  return fmt::sprintf(\"%c%c%c%c%c%c.log\", d[6], d[7], d[0], d[1], d[3], d[4]);\n}\n\n/*\n* Returns instance (temporary) sysop log filename in s.\n*/\nstd::string instance_sysoplog_filename() {\n  return fmt::sprintf(\"inst-%3.3u.log\", a()->sess().instance_number());\n}\n\n/*\n* Copies temporary/instance sysop log to primary sysop log file.\n*/\nvoid catsl() {\n  const auto templog_fn = FilePath(a()->config()->gfilesdir(), instance_sysoplog_filename());\n  if (!File::Exists(templog_fn)) {\n    return;\n  }\n\n  std::string instance_text;\n  {\n    TextFile tmplog(templog_fn, \"rt\");\n    if (!tmplog) {\n      return;\n    }\n    instance_text = tmplog.ReadFileIntoString();\n  }\n\n  const auto basename = sysoplog_filename(date());\n  TextFile sysoplog_fn(FilePath(a()->config()->gfilesdir(), basename), \"at\");\n  if (sysoplog_fn) {\n    sysoplog_fn.WriteLine(instance_text);\n    File::Remove(templog_fn);\n  }\n}\n\n/*\n* Writes a line to the sysop log.\n*/\nvoid AddLineToSysopLogImpl(log_cmd_t cmd, const std::string& text) {\n  static size_t midline = 0;\n  \n  if (a()->config()->gfilesdir().empty()) {\n    LOG(ERROR) << \"gfilesdir empty, can't write to sysop log: \" << text;\n    return;\n  }\n  const static auto s_sysoplog_filename =\n      FilePath(a()->config()->gfilesdir(), instance_sysoplog_filename());\n\n  switch (cmd) {\n  case log_cmd_t::log_string: {  // Write line to sysop log\n    File logFile(s_sysoplog_filename);\n    if (!logFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      return;\n    }\n    if (logFile.length()) {\n      logFile.Seek(0L, File::Whence::end);\n    }\n    std::string logLine;\n    if (midline > 0) {\n      logLine = StrCat(\"\\r\\n\", text);\n      midline = 0;\n    } else {\n      logLine = text;\n    }\n    logLine += \"\\r\\n\";\n    logFile.Write(logLine);\n    logFile.Close();\n  }\n  break;\n  case log_cmd_t::log_char: {\n    File logFile(s_sysoplog_filename);\n    if (!logFile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      // sysop log ?\n      return;\n    }\n    if (logFile.length()) {\n      logFile.Seek(0L, File::Whence::end);\n    }\n    std::string logLine;\n    if (midline == 0 || (midline + 2 + text.length()) > 78) {\n      logLine = (midline) ? \"\\r\\n   \" : \"  \";\n      midline = 3 + text.length();\n    } else {\n      logLine = \", \";\n      midline += 2 + text.length();\n    }\n    logLine += text;\n    logFile.Write(logLine);\n    logFile.Close();\n  }\n  break;\n  }\n}\n\n/*\n* Writes a string to the sysop log.\n*/\nvoid sysopchar(const std::string& text) {\n  if (!text.empty()) {\n    AddLineToSysopLogImpl(log_cmd_t::log_char, text);\n  }\n}\n\nvoid sysoplog(bool indent, const std::string& text) {\n  if (indent) {\n    AddLineToSysopLogImpl(log_cmd_t::log_string, StrCat(\"   \", text));\n  } else {\n    AddLineToSysopLogImpl(log_cmd_t::log_string, text);\n  }\n}\n\nvoid sysoplog(const std::string& text) { sysoplog(true, text); }\n"
  },
  {
    "path": "bbs/sysoplog.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/**************************************************************************/\r\n#ifndef __INCLUDED_SYSOPLOG_H__\r\n#define __INCLUDED_SYSOPLOG_H__\r\n\r\n#include <string>\r\n\r\nstd::string sysoplog_filename(const std::string& date);\r\nstd::string instance_sysoplog_filename();\r\nvoid catsl();\r\nvoid sysopchar(const std::string& text);\r\nvoid sysoplog(bool indent, const std::string& text);\r\nvoid sysoplog(const std::string& text);\r\n\r\n\r\n#endif  // __INCLUDED_SYSOPLOG_H__"
  },
  {
    "path": "bbs/tag.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_TAG_H\n#define INCLUDED_BBS_TAG_H\n\n#include \"sdk/vardec.h\"\n#include <cstdint>\n\n// Holds information about tagged files.\nstruct tagrec_t {\n  // file information\n  uploadsrec u;\n  // directory number\n  int16_t directory;\n  // directory mask\n  uint16_t dir_mask;\n};\n\n\n#endif\n"
  },
  {
    "path": "bbs/test/SIZE.DOS",
    "content": "sizeof (net_header_rec) = 24\nsizeof (userrec) = 1024\nsizeof (slrec) = 14\nsizeof (valrec) = 8\nsizeof (arcrec) = 336\nsizeof (configrec) = 6228\nsizeof (configoverrec) = 512\nsizeof (statusrec) = 151\nsizeof (colorrec) = 240\nsizeof (subboardrec) = 63\nsizeof (directoryrec_422_t) = 141\nsizeof (smalrec) = 33\nsizeof (messagerec) = 5\nsizeof (postrec) = 100\nsizeof (mailrec) = 100\nsizeof (tmpmailrec) = 15\nsizeof (shortmsgrec) = 85\nsizeof (voting_response) = 83\nsizeof (uploadsrec) = 144\nsizeof (tagrec) = 148\nsizeof (zlogrec) = 21\nsizeof (chainfilerec_422) = 166\nsizeof (chainregrec_422) = 64\nsizeof (newexternalrec) = 512\nsizeof (editorrec) = 366\nsizeof (usersubrec) = 7\nsizeof (batchrec) = 24\nsizeof (ext_desc_type) = 15\nsizeof (gfiledirrec) = 56\nsizeof (gfilerec) = 98\nsizeof (languagerec) = 258\nsizeof (filestatusrec) = 23\nsizeof (phonerec) = 15\nsizeof (ext_desc_rec) = 17\nsizeof (instancerec) = 100\nsizeof (Network) = 100\n"
  },
  {
    "path": "bbs/test/size.apple",
    "content": "sizeof (net_header_rec) = 24\nsizeof (userrec) = 1024\nsizeof (slrec) = 14\nsizeof (valrec) = 8\nsizeof (arcrec) = 336\nsizeof (configrec) = 6228\nsizeof (configoverrec) = 512\nsizeof (statusrec) = 151\nsizeof (colorrec) = 240\nsizeof (subboardrec) = 63\nsizeof (directoryrec_422_t) = 141\nsizeof (smalrec) = 33\nsizeof (messagerec) = 5\nsizeof (postrec) = 100\nsizeof (mailrec) = 100\nsizeof (tmpmailrec) = 15\nsizeof (shortmsgrec) = 85\nsizeof (voting_response) = 83\nsizeof (uploadsrec) = 144\nsizeof (tagrec) = 148\nsizeof (zlogrec) = 21\nsizeof (chainfilerec_422) = 166\nsizeof (chainregrec_422) = 64\nsizeof (newexternalrec) = 512\nsizeof (editorrec) = 366\nsizeof (usersubrec) = 7\nsizeof (batchrec) = 24\nsizeof (ext_desc_type) = 15\nsizeof (gfiledirrec) = 56\nsizeof (gfilerec) = 98\nsizeof (languagerec) = 258\nsizeof (result_info) = 82\nsizeof (modem_info) = 905\nsizeof (filestatusrec) = 23\nsizeof (asv_rec) = 9\nsizeof (adv_asv_rec) = 4\nsizeof (cbv_rec) = 12\nsizeof (phonerec) = 15\nsizeof (ext_desc_rec) = 17\nsizeof (instancerec) = 100\n"
  },
  {
    "path": "bbs/test/size.gcc",
    "content": "sizeof (userrec) = 1024\nsizeof (slrec) = 14\nsizeof (valrec) = 8\nsizeof (oldarcrec) = 100\nsizeof (arcrec) = 336\nsizeof (configrec) = 6228\nsizeof (configoverrec) = 512\nsizeof (statusrec) = 151\nsizeof (colorrec) = 240\nsizeof (subboardrec) = 63\nsizeof (directoryrec_422_t) = 141\nsizeof (smalrec) = 33\nsizeof (messagerec) = 5\nsizeof (postrec) = 100\nsizeof (mailrec) = 100\nsizeof (tmpmailrec) = 15\nsizeof (shortmsgrec) = 85\nsizeof (voting_response) = 83\nsizeof (uploadsrec) = 144\nsizeof (tagrec) = 148\nsizeof (zlogrec) = 21\nsizeof (chainfilerec_422) = 166\nsizeof (chainregrec_422) = 64\nsizeof (newexternalrec) = 512\nsizeof (editorrec) = 366\nsizeof (usersubrec) = 7\nsizeof (batchrec) = 24\nsizeof (ext_desc_type) = 15\nsizeof (gfiledirrec) = 56\nsizeof (gfilerec) = 98\nsizeof (resultrec) = 50\nsizeof (languagerec) = 258\nsizeof (result_info) = 82\nsizeof (modem_info) = 905\nsizeof (filestatusrec) = 23\nsizeof (asv_rec) = 9\nsizeof (adv_asv_rec) = 4\nsizeof (cbv_rec) = 12\nsizeof (phonerec) = 15\nsizeof (ext_desc_rec) = 17\nsizeof (instancerec) = 100\n"
  },
  {
    "path": "bbs/test/size.linux",
    "content": "sizeof (net_header_rec) = 24\nsizeof (userrec) = 1024\nsizeof (slrec) = 14\nsizeof (valrec) = 8\nsizeof (arcrec) = 336\nsizeof (configrec) = 6228\nsizeof (configoverrec) = 512\nsizeof (statusrec) = 151\nsizeof (colorrec) = 240\nsizeof (subboardrec) = 63\nsizeof (directoryrec_422_t) = 141\nsizeof (smalrec) = 33\nsizeof (messagerec) = 5\nsizeof (postrec) = 100\nsizeof (mailrec) = 100\nsizeof (tmpmailrec) = 15\nsizeof (shortmsgrec) = 85\nsizeof (voting_response) = 83\nsizeof (uploadsrec) = 144\nsizeof (tagrec) = 148\nsizeof (zlogrec) = 21\nsizeof (chainfilerec_422) = 166\nsizeof (chainregrec_422) = 64\nsizeof (newexternalrec) = 512\nsizeof (editorrec) = 366\nsizeof (usersubrec) = 7\nsizeof (batchrec) = 24\nsizeof (ext_desc_type) = 15\nsizeof (gfiledirrec) = 56\nsizeof (gfilerec) = 98\nsizeof (languagerec) = 258\nsizeof (result_info) = 82\nsizeof (modem_info) = 905\nsizeof (filestatusrec) = 23\nsizeof (asv_rec) = 9\nsizeof (adv_asv_rec) = 4\nsizeof (cbv_rec) = 12\nsizeof (phonerec) = 15\nsizeof (ext_desc_rec) = 17\nsizeof (instancerec) = 100\n"
  },
  {
    "path": "bbs/test/size.w32",
    "content": "sizeof (userrec) = 1024\nsizeof (slrec) = 14\nsizeof (valrec) = 8\nsizeof (oldarcrec) = 100\nsizeof (arcrec) = 336\nsizeof (configrec) = 6228\nsizeof (configoverrec) = 512\nsizeof (statusrec) = 151\nsizeof (colorrec) = 240\nsizeof (subboardrec) = 63\nsizeof (directoryrec_422_t) = 141\nsizeof (smalrec) = 33\nsizeof (messagerec) = 5\nsizeof (postrec) = 100\nsizeof (mailrec) = 100\nsizeof (tmpmailrec) = 15\nsizeof (shortmsgrec) = 85\nsizeof (voting_response) = 83\nsizeof (uploadsrec) = 144\nsizeof (tagrec) = 148\nsizeof (zlogrec) = 21\nsizeof (chainfilerec_422) = 166\nsizeof (chainregrec_422) = 64\nsizeof (newexternalrec) = 512\nsizeof (editorrec) = 366\nsizeof (usersubrec) = 7\nsizeof (batchrec) = 24\nsizeof (ext_desc_type) = 15\nsizeof (gfiledirrec) = 56\nsizeof (gfilerec) = 98\nsizeof (resultrec) = 50\nsizeof (languagerec) = 258\nsizeof (result_info) = 82\nsizeof (modem_info) = 905\nsizeof (filestatusrec) = 23\nsizeof (asv_rec) = 9\nsizeof (adv_asv_rec) = 4\nsizeof (cbv_rec) = 12\nsizeof (phonerec) = 15\nsizeof (ext_desc_rec) = 17\nsizeof (instancerec) = 100\n"
  },
  {
    "path": "bbs/test/testqwk.cpp",
    "content": "#include \"bbs/qwk/qwk_struct.h\"\n\n#include <iostream>\n\nint main(char** argv) {\n  std::cout << \"qwk_record=\" << sizeof(wwiv::bbs::qwk::qwk_record) << std::endl;\n  std::cout << \"qwk_index=\" << sizeof(wwiv::bbs::qwk::qwk_index) << std::endl;\n}\n\n"
  },
  {
    "path": "bbs/test/testsize.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n/////////////////////////////////////////////////////////////////////////////\n// WWIV 5.x Structure Size test application\n\n#include <stdio.h>\n#ifdef __MSDOS__\n#include <io.h>\n#endif\n\n#ifdef _WIN32\n#define WIN32_LEAN_AND_MEAN\n#define STRICT\n#include <io.h>\n#include <windows.h>\n#endif // _WIN32\n\n#include \"sdk/vardec.h\"\n#include \"sdk/net/net.h\"\n\n#define EXIT_NORMAL     0\n#define EXIT_BAD_PARAMS 1\n#define EXIT_BAD_FNAME  2\n\n#define WRITE_SIZE(x) fprintf(hOut, \"sizeof (%s) = %d\\n\", #x, sizeof(x));\n\nint main(int argc, char * argv[])\n{\n        FILE* hOut = NULL;\n        if (argc != 2)\n        {\n                printf(\"WWIV 5.X structure size test utility\\r\\n\");\n                printf(\"Copyright 2000-2023, WWIV Software Services\\r\\n\\n\");\n                printf(\"Usage:\\n\\tTESTSIZE <output filename>\\n\\n\");\n                return EXIT_BAD_PARAMS;\n        }\n\n        hOut = fopen(argv[1], \"wt\");\n        if (NULL == hOut)\n        {\n                printf(\"* ERROR: Unable to open file '%s'\\r\\n\\n\", argv[1]);\n                return EXIT_BAD_FNAME;\n        }\n\n        WRITE_SIZE(net_header_rec);\n        WRITE_SIZE(userrec);\n        WRITE_SIZE(slrec);\n        WRITE_SIZE(valrec);\n        WRITE_SIZE(arcrec);\n        WRITE_SIZE(configrec);\n        WRITE_SIZE(configoverrec);\n        WRITE_SIZE(statusrec);\n        WRITE_SIZE(colorrec);\n        WRITE_SIZE(subboardrec);\n        WRITE_SIZE(directoryrec_422_t);\n        WRITE_SIZE(smalrec);\n        WRITE_SIZE(messagerec);\n        WRITE_SIZE(postrec);\n        WRITE_SIZE(mailrec);\n        WRITE_SIZE(tmpmailrec);\n        WRITE_SIZE(shortmsgrec);\n        WRITE_SIZE(voting_response);\n        WRITE_SIZE(uploadsrec);\n        WRITE_SIZE(tagrec);\n        WRITE_SIZE(zlogrec);\n        WRITE_SIZE(chainfilerec_422);\n        WRITE_SIZE(chainregrec_422);\n        WRITE_SIZE(newexternalrec);\n        WRITE_SIZE(editorrec);\n        WRITE_SIZE(usersubrec);\n        WRITE_SIZE(ext_desc_type);\n        WRITE_SIZE(gfiledirrec);\n        WRITE_SIZE(gfilerec);\n        WRITE_SIZE(filestatusrec);\n        WRITE_SIZE(phonerec);\n        WRITE_SIZE(ext_desc_rec);\n        WRITE_SIZE(instancerec);\n        WRITE_SIZE(net_networks_rec_disk);\n        fclose(hOut);\n        return EXIT_NORMAL;\n}\n"
  },
  {
    "path": "bbs/test/testsize_assert.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                                WWIV Version 5                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n/////////////////////////////////////////////////////////////////////////////\n// WWIV 5.0 Structure Size test application\n\n#include <stdio.h>\n#ifdef __MSDOS__\n#include <io.h>\n#endif\n\n#ifdef _WIN32\n#define WIN32_LEAN_AND_MEAN\n#define STRICT\n#include <io.h>\n#include <windows.h>\n#endif // _WIN32\n\n#include \"../vardec.h\"\n\n#define WRITE_SIZE(x) printf(\"static_assert(sizeof(%s) == %d, \\\"%s == %d\\\");\\n\", #x, sizeof(x), #x, sizeof(x));\n\nint main(int argc, char * argv[]) {\n  WRITE_SIZE(userrec);\n  WRITE_SIZE(slrec);\n  WRITE_SIZE(valrec);\n  WRITE_SIZE(arcrec);\n  WRITE_SIZE(configrec);\n  WRITE_SIZE(configoverrec);\n  WRITE_SIZE(statusrec);\n  WRITE_SIZE(colorrec);\n  WRITE_SIZE(subboardrec);\n  WRITE_SIZE(directoryrec_422_t);\n  WRITE_SIZE(smalrec);\n  WRITE_SIZE(messagerec);\n  WRITE_SIZE(postrec);\n  WRITE_SIZE(mailrec);\n  WRITE_SIZE(tmpmailrec);\n  WRITE_SIZE(shortmsgrec);\n  WRITE_SIZE(voting_response);\n  WRITE_SIZE(uploadsrec);\n  WRITE_SIZE(tagrec);\n  WRITE_SIZE(zlogrec);\n  WRITE_SIZE(chainfilerec_422);\n  WRITE_SIZE(chainregrec_422);\n  WRITE_SIZE(newexternalrec);\n  WRITE_SIZE(editorrec);\n  WRITE_SIZE(usersubrec);\n  WRITE_SIZE(ext_desc_type);\n  WRITE_SIZE(gfiledirrec);\n  WRITE_SIZE(gfilerec);\n  WRITE_SIZE(result_info);\n  WRITE_SIZE(modem_info);\n  WRITE_SIZE(filestatusrec);\n  WRITE_SIZE(asv_rec);\n  WRITE_SIZE(adv_asv_rec);\n  WRITE_SIZE(cbv_rec);\n  WRITE_SIZE(phonerec);\n  WRITE_SIZE(ext_desc_rec);\n  WRITE_SIZE(instancerec);\n  return 0;\n}\n"
  },
  {
    "path": "bbs/trashcan.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/trashcan.h\"\n\n#include \"core/inifile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nTrashcan::Trashcan(wwiv::sdk::Config& config)\n    : file_(FilePath(config.gfilesdir(), TRASHCAN_TXT)) {}\n\nTrashcan::~Trashcan() = default;\n\nstatic bool Matches(std::string whole, std::string pattern) {\n  if (!contains(pattern, '*')) {\n    return whole == pattern;\n  }\n\n  if (pattern.length() == 1) {\n    // We have 1 char and it is a '*'.\n    return false;\n  }\n  StringUpperCase(&pattern);\n  if ((pattern.length() > 2) && pattern.front() == '*' && pattern.back() == '*') {\n    // We have *foo*\n    auto s = pattern.substr(1);\n    s.pop_back();\n    return whole.find(s) != std::string::npos;\n  }\n  if (pattern.front() == '*') {\n    return ends_with(whole, pattern.substr(1));\n  }\n  if (pattern.back() == '*') {\n    auto s = pattern;\n    s.pop_back();\n    return starts_with(whole, s);\n  }\n  // Don't have a * at either end, so we don't support that pattern.\n  return false;\n}\n\nbool Trashcan::IsTrashName(const std::string& rawname) {\n  if (!File::Exists(file_.path())) {\n    return false;\n  }\n  // Gotta have a name to be in the trashcan.\n  if (rawname.empty()) {\n    return false;\n  }\n  TextFile file(file_.path(), \"rt\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n\n  const auto name{ToStringUpperCase(rawname)};\n\n  std::string line;\n  while (file.ReadLine(&line)) {\n    StringUpperCase(&line);\n    if (Matches(name, line)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "bbs/trashcan.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_TRASHCAN_H__\n#define __INCLUDED_BBS_TRASHCAN_H__\n\n#include <string>\n#include \"core/file.h\"\n#include \"sdk/config.h\"\n\nclass Trashcan {\npublic:\n  Trashcan(wwiv::sdk::Config& config);\n  virtual ~Trashcan();\n  bool IsTrashName(const std::string& name);\n\nprivate:\n  wwiv::core::File file_;\n};\n\n#endif  // __INCLUDED_BBS_TRASHCAN_H__\n"
  },
  {
    "path": "bbs/trashcan_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2007-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/trashcan.h\"\n#include \"bbs/bbs_helper.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::strings;\n\nclass TrashcanTest : public testing::Test {\nprotected:\n  void SetUp() override {\n    helper.SetUp();\n    const std::string text = \"all\\n*end\\nstart*\\n*sub*\\n\";\n    helper.files().CreateTempFile(StrCat(\"gfiles/\", TRASHCAN_TXT), text);\n  }\n\npublic:\n  BbsHelper helper;\n};\n\nTEST_F(TrashcanTest, SimpleCase) {\n  Trashcan t(*a()->config());\n  EXPECT_TRUE(t.IsTrashName(\"all\"));\n  EXPECT_FALSE(t.IsTrashName(\"al\"));\n  EXPECT_FALSE(t.IsTrashName(\"a\"));\n\n  EXPECT_TRUE(t.IsTrashName(\"end\"));\n  EXPECT_TRUE(t.IsTrashName(\"send\"));\n  EXPECT_FALSE(t.IsTrashName(\"ends\"));\n\n  EXPECT_TRUE(t.IsTrashName(\"start\"));\n  EXPECT_TRUE(t.IsTrashName(\"starting\"));\n  EXPECT_FALSE(t.IsTrashName(\"sstart\"));\n\n  EXPECT_TRUE(t.IsTrashName(\"sub\"));\n  EXPECT_TRUE(t.IsTrashName(\"ssub\"));\n  EXPECT_TRUE(t.IsTrashName(\"subs\"));\n\n  EXPECT_FALSE(t.IsTrashName(\"dude\"));\n  EXPECT_FALSE(t.IsTrashName(\"a\"));\n}\n"
  },
  {
    "path": "bbs/trytoul.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"common/com.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/dirlist.h\"\n#include \"common/input.h\"\n#include \"bbs/listplus.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/numbers.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/files/files.h\"\n#include <chrono>\n#include <string>\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic void t2u_error(const std::string& file_name, const std::string& msg) {\n  bout.nl(2);\n  const auto s1 = StrCat(\"**  \", file_name, \" failed T2U qualifications\");\n  bout.pl(s1);\n  sysoplog(s1);\n\n  const auto s2 = StrCat(\"** Reason : \", msg);\n  bout.pl(s2);\n  bout.nl();\n  sysoplog(s2);\n}\n\nstatic int try_to_ul_wh(const std::string& orig_file_name) {\n  wwiv::sdk::files::directory_t d{};\n  char key;\n  auto ok = 0, dn = 0;\n\n  auto file_name = files::unalign(orig_file_name);\n\n  if (!okfn(file_name)) {\n    t2u_error(file_name, \"Bad filename\");          // bad filename\n    return 1;\n  }\n  bout.cls();\n  bout.nl(3);\n\n  bool done = false;\n  if (a()->user()->restrict_validate() || a()->user()->restrict_upload() ||\n      (a()->config()->sysconfig_flags() & sysconfig_all_sysop)) {\n    dn = (a()->config()->new_uploads_dir() < a()->dirs().size()) \n      ? a()->config()->new_uploads_dir() : 0;\n  } else {\n    char temp[10];\n\n    // The a()->sess().hangup() check is below so uploads get uploaded even on a()->sess().hangup()\n    done = false;\n    while (!done) {\n      if (a()->sess().hangup()) {\n        if (a()->config()->new_uploads_dir() < a()->dirs().size()) {\n          dn = a()->config()->new_uploads_dir();\n        } else {\n          dn = 0;\n        }\n        done = true;\n        break;\n      }\n      // The sleep_for used to be a wait_sec_or_hit( 1 )\n      sleep_for(milliseconds(500));\n      bout.print(\"\\r\\nUpload {} to which dir? <CR>=0 ?=List \\r\\n\", file_name);\n      bin.input(temp, 5, true);\n      StringTrim(temp);\n      if (temp[0] == '?') {\n        dirlist(1);\n        break;\n      }\n      if (!temp[0]) {\n        dn = 0;\n        done = true;\n        break;\n      }\n      int x = to_number<int>(temp);\n      if (a()->udir[x].subnum >= 0) {\n        dliscan1(a()->udir[x].subnum);\n        d = a()->dirs()[dn];\n        if (d.mask & mask_no_uploads && !dcs()) {\n          bout.outstr(\"Can't upload there...\\r\\n\");\n          bout.pausescr();\n        } else {\n          dn = a()->udir[x].subnum;\n          done = true;\n        }\n      }\n    }\n  }\n\n  d = a()->dirs()[dn];\n  dliscan1(d);\n  if (a()->current_file_area()->number_of_files() >= d.maxfiles) {\n    t2u_error(file_name, \"This directory is currently full.\");\n    return 1;\n  }\n  if (d.mask & mask_no_uploads && !dcs()) {\n    t2u_error(file_name, \"Uploads are not allowed to this directory.\");\n    return 1;\n  }\n  if (!is_uploadable(file_name)) {\n    if (so()) {\n      bout.nl();\n      bout.outstr(\"|#5In filename database - add anyway? \");\n      if (!bin.yesno()) {\n        t2u_error(file_name, \"|#6File either already here or unwanted.\");\n        return 1;\n      }\n    } else {\n      t2u_error(file_name, \"|#6File either already here or unwanted.\");\n      return 1;\n    }\n  }\n  std::string aligned_file_name = aligns(file_name);\n  if (contains(aligned_file_name, '?')) {\n    t2u_error(file_name, \"Contains wildcards\");\n    return 1;\n  }\n  if (d.mask & mask_archive) {\n    ok = 0;\n    std::string s1;\n    for (size_t i = 0; i < MAX_ARCS; i++) {\n      if (a()->arcs[i].extension[0] && a()->arcs[i].extension[0] != ' ') {\n        if (!s1.empty()) s1 += \", \";\n        s1 += a()->arcs[i].extension;\n        if (wwiv::strings::IsEquals(aligned_file_name.c_str() + 9, a()->arcs[i].extension)) {\n          ok = 1;\n        }\n      }\n    }\n    if (!ok) {\n      bout.nl();\n      bout.outstr(\"Sorry, all uploads to this directory must be archived.  Supported types are:\\r\\n\");\n      bout.outstr(s1);\n      bout.nl(2);\n\n      t2u_error(file_name, \"Unsupported archive\");\n      return 1;\n    }\n  }\n  files::FileRecord f;\n  f.set_filename(aligned_file_name);\n  f.u().ownerusr = static_cast<uint16_t>(a()->sess().user_num());\n  const auto unn = a()->user()->name_and_number();\n  to_char_array(f.u().upby, unn);\n  f.set_date(DateTime::now());\n\n  const auto dir_path = File::absolute(a()->bbspath(), d.path);\n  if (File::Exists(FilePath(dir_path, files::unalign(aligned_file_name)))) {\n    if (dcs()) {\n      bout.nl(2);\n      bout.outstr(\"File already exists.\\r\\n|#5Add to database anyway? \");\n      if (bin.yesno() == 0) {\n        t2u_error(file_name, \"That file is already here.\");\n        return 1;\n      }\n    } else {\n      t2u_error(file_name, \"That file is already here.\");\n      return 1;\n    }\n  }\n  const auto src = FilePath(a()->sess().dirs().batch_directory(), file_name);\n  const auto dest = FilePath(dir_path, file_name);\n\n  if (File::Exists(dest)) {\n    File::Remove(dest);\n  }\n\n  // s1 and s2 should remain set,they are used below\n  File::Move(src, dest);\n  f.set_description(\"NO DESCRIPTION GIVEN\");\n  auto file_id_avail = get_file_idz(f, a()->dirs()[dn]);\n  done = false;\n\n  while (!done && !a()->sess().hangup() && !file_id_avail) {\n    bout.cls();\n    bout.nl();\n    bout.print(\"|#1Upload going to |#7{}\\r\\n\\n\", d.name);\n    bout.print(\"   |#1Filename    |01: |#7{}\\r\\n\", file_name);\n    bout.print(\"|#2A|#7] |#1Description |01: |#7{}\\r\\n\", f.description());\n    bout.outstr(\"|#2B|#7] |#1Modify extended description\\r\\n\\n\");\n    print_extended(f.aligned_filename(), 10, -1, Color::YELLOW, nullptr);\n    bout.outstr(\"|#2<|#7CR|#2> |#1to continue, |#7Q|#1 to abort upload: \");\n    key = onek(\"\\rQABC\", true);\n    switch (key) {\n    case 'Q':\n      bout.outstr(\"Are you sure, file will be lost? \");\n      if (bin.yesno()) {\n        t2u_error(file_name, \"Changed mind\");\n        // move file back to batch dir\n        File::Move(dest, src);\n        return 1;\n      }\n      break;\n\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"Please enter a one line description.\\r\\n:\");\n      auto desc = bin.input_text(58);\n      f.set_description(desc);\n    } break;\n\n    case 'B':\n    {\n      auto* area = a()->current_file_area();\n      bout.nl();\n      auto ss = area->ReadExtendedDescriptionAsString(f).value_or(\"\");\n      bout.outstr(\"|#5Modify extended description? \");\n      if (bin.yesno()) {\n        bout.nl();\n        if (!ss.empty()) {\n          bout.outstr(\"|#5Delete it? \");\n          if (bin.yesno()) {\n            area->DeleteExtendedDescription(f.filename());\n            f.set_mask(mask_extended, false);\n          } else {\n            f.set_mask(mask_extended, true);\n            modify_extended_description(&ss, a()->dirs()[a()->current_user_dir().subnum].name);\n            if (!ss.empty()) {\n              area->DeleteExtendedDescription(f.filename());\n              area->AddExtendedDescription(f.filename(), ss);\n            }\n          }\n        } else {\n          modify_extended_description(&ss, a()->dirs()[a()->current_user_dir().subnum].name);\n          if (!ss.empty()) {\n            area->AddExtendedDescription(f.filename(), ss);\n            f.set_mask(mask_extended, true);\n          } else {\n            f.set_mask(mask_extended, false);\n          }\n        }\n      } else if (!ss.empty()) {\n        f.set_mask(mask_extended, true);\n      } else {\n        f.set_mask(mask_extended, false);\n      }\n    } break;\n\n    case '\\r':\n      bout.nl();\n      done = true;\n    }\n  }\n\n  bout.nl(3);\n\n  File file(FilePath(dir_path, files::unalign(aligned_file_name)));\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    // dos error, file not found\n    if (f.mask(mask_extended)) {\n      a()->current_file_area()->DeleteExtendedDescription(f.filename());\n    }\n    t2u_error(file_name, \"DOS error - File not found.\");\n    return 1;\n  }\n  if (!a()->upload_cmd.empty()) {\n    file.Close();\n    bout.outstr(\"Please wait...\\r\\n\");\n    if (!check_ul_event(dn, &f.u())) {\n      if (f.mask(mask_extended)) {\n        a()->current_file_area()->DeleteExtendedDescription(f.filename());\n      }\n      t2u_error(file_name, \"Failed upload event\");\n      return 1;\n    }\n    file.Open(File::modeBinary | File::modeReadOnly);\n  }\n  f.set_numbytes(file.length());\n  file.Close();\n  a()->user()->increment_uploaded();\n\n  f.set_date(DateTime::now());\n  auto* area = a()->current_file_area();\n  if (!area->AddFile(f)) {\n    LOG(ERROR) << \"Error adding file: \" << f;\n  } else {\n    area->Save();\n  }\n  add_to_file_database(f);\n\n  a()->user()->set_uk(a()->user()->uk() + bytes_to_k(f.numbytes()));\n\n  a()->status_manager()->Run([&](Status& status) {\n    status.increment_uploads_today();\n    status.increment_filechanged(Status::file_change_upload);\n  });\n  sysoplog(fmt::format(\"+ \\\"{}\\\" uploaded on {}\", f, a()->dirs()[dn].name));\n  return 0;                                 // This means success\n}\n\nint try_to_ul(const std::string& file_name) {\n  auto ac = false;\n\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    ac = true;\n    tmp_disable_conf(true);\n  }\n  if (!try_to_ul_wh(file_name)) {\n    if (ac) {\n      tmp_disable_conf(false);\n    }\n    return 0;  // success\n  }\n\n  const auto dest_dir = FilePath(a()->config()->dloadsdir(), \"TRY2UL\");\n  File::mkdirs(dest_dir);\n\n  bout.outstr(\"|#2Your file had problems, it is being moved to a special dir for sysop review\\r\\n\");\n\n  sysoplog(fmt::format(\"Failed to upload {}, moving to TRY2UL dir\", file_name));\n\n  const auto src = FilePath(a()->sess().dirs().batch_directory(), file_name);\n  const auto dest = FilePath(FilePath(a()->config()->dloadsdir(), \"TRY2UL\"), file_name);\n\n  if (File::Exists(dest)) {                        // this is iffy <sp?/who care I choose to\n    File::Remove(dest);                           // remove duplicates in try2ul dir, so keep\n  }\n  // it clean and up to date\n  File::Copy(src, dest); // copy file from batch dir,to try2ul dir */\n\n  if (a()->sess().IsUserOnline()) {\n    a()->UpdateTopScreen();\n  }\n\n  if (ac) {\n    tmp_disable_conf(false);\n  }\n\n  return 1;                                 // return failure, removes ul k credits etc...\n}\n"
  },
  {
    "path": "bbs/uedit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/uedit.h\"\n\n#include \"bbs/bbs.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n\nvoid auto_val(int n, wwiv::sdk::User *u) {\n  if (u->sl() == 255) {\n    return;\n  }\n  const auto& avr = a()->config()->auto_val(n);\n  u->sl(avr.sl);\n  u->dsl(avr.dsl);\n  u->ar_int(avr.ar);\n  u->dar_int(avr.dar);\n  u->restriction(avr.restrict);\n}\n"
  },
  {
    "path": "bbs/uedit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_UEDIT_H__\n#define __INCLUDED_BBS_UEDIT_H__\n\n#include \"sdk/user.h\"\n\nvoid auto_val(int n, wwiv::sdk::User* pUser);\n\n\n#endif  // __INCLUDED_BBS_UEDIT_H__"
  },
  {
    "path": "bbs/utility.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/utility.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/common.h\"\n#include \"bbs/connect1.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/workspace.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/files/files_ext.h\"\n\n#include <algorithm>\n#include <chrono>\n#include <string>\n#include <vector>\n#ifdef _WIN32\n#include <sys/utime.h>\n#else\n#include <utime.h>\n#endif // WIN32\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\nextern const unsigned char* translate_letters[];\n\ntemplate <class _Ty>\n_Ty in_range(const _Ty& minValue, const _Ty& maxValue, const _Ty& value) {\n  auto v = std::min(maxValue, value);\n  return std::max(v, minValue);\n}\n\n/**\n * Deletes files from a directory.  This is meant to be used only in the temp\n * directories of WWIV.\n *\n * @param file_name       Wildcard file specification to delete\n * @param directory_name  Name of the directory to delete files from\n * @param bPrintStatus    Print out locally as files are deleted\n */\nvoid remove_from_temp(const std::string& file_name, const std::filesystem::path& directory_name,\n                      bool bPrintStatus) {\n  const auto filespec = FilePath(directory_name, stripfn(file_name));\n  FindFiles ff(filespec, FindFiles::FindFilesType::any);\n  bout.nl();\n  for (const auto& f : ff) {\n    // We don't want to delete \".\", \"..\".\n    const auto fullpath = FilePath(directory_name, f.name);\n    LOG_IF(bPrintStatus, INFO) << \"Deleting TEMP file: '\" << fullpath << \"'\";\n    File::Remove(fullpath);\n  }\n}\n\n/**\n * Does the currently online user have ANSI.  The user record is\n * checked for this information\n *\n * @return true if the user wants ANSI, false otherwise.\n */\nbool okansi() { return a()->user()->ansi(); }\n\n/**\n * Gets the current users post/call ratio.\n */\nfloat post_ratio() {\n  if (a()->user()->logons() == 0) {\n    return 99.999f;\n  }\n  const auto r = static_cast<float>(a()->user()->messages_posted()) /\n                 static_cast<float>(a()->user()->logons());\n  return r > 99.998f ? 99.998f : r;\n}\n\nlong nsl() {\n  const auto dd = system_clock::now();\n  if (!a()->sess().IsUserOnline()) {\n    return 1;\n  }\n\n  const auto tot = duration_cast<seconds>(dd - a()->sess().system_logon_time());\n\n  const auto tpl = minutes(a()->config()->sl(a()->sess().effective_sl()).time_per_logon);\n  const auto tpd = minutes(a()->config()->sl(a()->sess().effective_sl()).time_per_day);\n  const auto extra_time_call =\n      duration_cast<seconds>(a()->user()->extra_time() + a()->extratimecall());\n  const auto tlc = std::chrono::duration_cast<seconds>(tpl - tot + extra_time_call);\n  // time left today\n  const auto timeontoday = a()->user()->timeontoday();\n  const auto extra_time = a()->user()->extra_time();\n  const auto tld = std::chrono::duration_cast<seconds>(tpd - tot - timeontoday + extra_time);\n  //VLOG(3) << \"TLD: \" << tld.count();\n  const auto tlt = std::min<seconds>(tlc, tld);\n  a()->sess().SetTimeOnlineLimited(false);\n  const auto v = static_cast<int>(duration_cast<seconds>(tlt).count());\n  return in_range<long>(0, 32767, v);\n}\n\nvoid send_net(net_header_rec* nh, std::vector<uint16_t> list, const std::string& text,\n              const std::string& byname) {\n  const auto filename = StrCat(a()->network_directory(), \"p1\", a()->network_extension());\n  File file(filename);\n  if (!file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    return;\n  }\n  file.Seek(0L, File::Whence::end);\n  if (list.empty()) {\n    nh->list_len = 0;\n  }\n  if (text.empty()) {\n    nh->length = 0;\n  }\n  if (nh->list_len) {\n    nh->tosys = 0;\n  }\n  if (!byname.empty()) {\n    nh->length += wwiv::stl::size_uint32(byname) + 1;\n  }\n  file.Write(nh, sizeof(net_header_rec));\n  if (nh->list_len) {\n    file.Write(&list[0], sizeof(uint16_t) * (nh->list_len));\n  }\n  if (!byname.empty()) {\n    file.Write(byname);\n    char nul[1] = {0};\n    file.Write(nul, 1);\n  }\n  if (nh->length) {\n    file.Write(text);\n  }\n  file.Close();\n}\n\nstd::string stripfn(const std::string& file_name) {\n  const std::filesystem::path p(file_name);\n  if (!p.has_filename()) {\n    return {};\n  }\n  auto orig = wwiv::sdk::files::unalign(p.filename().string());\n  // Since WWIV has a heavy DOS legacy, sometimes we have files in\n  // DOS slash format.  On Windows std::filesystem handles both since\n  // Windows uses either format internally.\n#if !defined (_WIN32)\n  const auto idx = orig.rfind(\"\\\\\");\n  if (idx != std::string::npos) {\n    orig = orig.substr(idx + 1);\n  }\n#endif  // !defined(_WIN32)\n  return orig;\n}\n\nstd::string get_wildlist(const std::string& orig_file_mask) {\n  char file_mask[1024];\n  to_char_array(file_mask, orig_file_mask);\n  auto mark = 0;\n\n  FindFiles ff(file_mask, FindFiles::FindFilesType::any);\n  if (ff.empty()) {\n    bout.outstr(\"No files found\\r\\n\");\n    return {};\n  }\n  auto f = ff.begin();\n  bout.printf(\"%12.12s \", f->name);\n\n  if (strchr(file_mask, File::pathSeparatorChar) == nullptr) {\n    file_mask[0] = '\\0';\n  } else {\n    for (int i = 0; i < ssize(file_mask); i++) {\n      if (file_mask[i] == File::pathSeparatorChar) {\n        mark = i + 1;\n      }\n    }\n  }\n  const auto m = file_mask[mark];\n  file_mask[mark] = 0;\n  auto* pszPath = file_mask;\n  file_mask[mark] = m;\n  const auto t = static_cast<int>(size(pszPath));\n  strcat(pszPath, f->name.c_str());\n  int i;\n  for (i = 1;; i++) {\n    if (i % 5 == 0) {\n      bout.nl();\n    }\n    if (f == ff.end()) {\n      break;\n    }\n    ++f;\n    bout.printf(\"%12.12s \", f->name);\n    if (bin.getkey() == SPACE) {\n      bout.nl();\n      break;\n    }\n  }\n  bout.nl();\n  if (i == 1) {\n    bout.print(\"One file found: {}\\r\\n\", f->name);\n    bout.outstr(\"Use this file? \");\n    if (bin.yesno()) {\n      return pszPath;\n    }\n    pszPath[0] = '\\0';\n    return pszPath;\n  }\n  pszPath[t] = '\\0';\n  bout.outstr(\"Filename: \");\n  bin.input(file_mask, 12, true);\n  strcat(pszPath, file_mask);\n  return pszPath;\n}\n\nint side_menu(int* menu_pos, bool bNeedsRedraw, const std::vector<std::string>& menu_items, int xpos,\n              int ypos, side_menu_colors* smc) {\n  static int positions[20];\n  a()->tleft(true);\n\n  if (bNeedsRedraw) {\n    int amount = 1;\n    positions[0] = xpos;\n    for (const auto& menu_item : menu_items) {\n      positions[amount] = positions[amount - 1] + wwiv::stl::ssize(menu_item) + 2;\n      ++amount;\n    }\n\n    int x = 0;\n    bout.setc(smc->normal_menu_item);\n\n    for (const auto& menu_item : menu_items) {\n      if (a()->sess().hangup()) {\n        break;\n      }\n      bout.goxy(positions[x], ypos);\n\n      if (*menu_pos == x) {\n        bout.setc(smc->current_highlight);\n        bout.outchr(menu_item[0]);\n        bout.setc(smc->current_menu_item);\n        bout.outstr(menu_item.substr(1));\n      } else {\n        bout.setc(smc->normal_highlight);\n        bout.outchr(menu_item[0]);\n        bout.setc(smc->normal_menu_item);\n        bout.outstr(menu_item.substr(1));\n      }\n      ++x;\n    }\n  }\n  bout.setc(smc->normal_menu_item);\n\n  while (!a()->sess().hangup()) {\n    const auto event = bin.bgetch_event(wwiv::common::Input::numlock_status_t::NOTNUMBERS);\n    if (event < 128) {\n      int x = 0;\n      for (const auto& menu_item : menu_items) {\n        if (event == to_upper_case<int>(menu_item[0]) ||\n            event == to_lower_case<int>(menu_item[0])) {\n          bout.goxy(positions[*menu_pos], ypos);\n          bout.setc(smc->normal_highlight);\n          bout.outchr(menu_items[*menu_pos][0]);\n          bout.setc(smc->normal_menu_item);\n          bout.outstr(menu_items[*menu_pos].substr(1));\n          *menu_pos = x;\n          bout.setc(smc->current_highlight);\n          bout.goxy(positions[*menu_pos], ypos);\n          bout.outchr(menu_items[*menu_pos][0]);\n          bout.setc(smc->current_menu_item);\n          bout.outstr(menu_items[*menu_pos].substr(1));\n          bout.goxy(positions[*menu_pos], ypos);\n          return EXECUTE;\n        }\n        ++x;\n      }\n      return event;\n    }\n    switch (event) {\n    case COMMAND_LEFT:\n      bout.goxy(positions[*menu_pos], ypos);\n      bout.setc(smc->normal_highlight);\n      bout.outchr(menu_items[*menu_pos][0]);\n      bout.setc(smc->normal_menu_item);\n      bout.outstr(menu_items[*menu_pos].substr(1));\n      if (!*menu_pos) {\n        *menu_pos = wwiv::stl::size_int(menu_items) - 1;\n      } else {\n        --*menu_pos;\n      }\n      bout.setc(smc->current_highlight);\n      bout.goxy(positions[*menu_pos], ypos);\n      bout.outchr(menu_items[*menu_pos][0]);\n      bout.setc(smc->current_menu_item);\n      bout.outstr(menu_items[*menu_pos].substr(1));\n      bout.goxy(positions[*menu_pos], ypos);\n      break;\n\n    case COMMAND_RIGHT:\n      bout.goxy(positions[*menu_pos], ypos);\n      bout.setc(smc->normal_highlight);\n      bout.outchr(menu_items[*menu_pos][0]);\n      bout.setc(smc->normal_menu_item);\n      bout.outstr(menu_items[*menu_pos].substr(1));\n      if (*menu_pos == static_cast<int>(menu_items.size() - 1)) {\n        *menu_pos = 0;\n      } else {\n        ++*menu_pos;\n      }\n      bout.setc(smc->current_highlight);\n      bout.goxy(positions[*menu_pos], ypos);\n      bout.outchr(menu_items[*menu_pos][0]);\n      bout.setc(smc->current_menu_item);\n      bout.outstr(menu_items[*menu_pos].substr(1));\n      bout.goxy(positions[*menu_pos], ypos);\n      break;\n    default:\n      return event;\n    }\n  }\n  return 0;\n}\n\nbool okfsed() { return ok_internal_fsed() || ok_external_fsed(); }\n\nbool ok_external_fsed() {\n  const auto ed = a()->user()->default_editor();\n  return okansi() && ed > 0 && ed != 0xff && ed <= wwiv::stl::ssize(a()->editors);\n}\n\nbool ok_internal_fsed() { return okansi() && a()->user()->default_editor() == 0xff; }\n\n\n\nuint32_t ansir_to_flags(uint16_t ansir) {\n  uint32_t flags = 0;\n  if (!(ansir & ansir_no_DOS)) {\n    flags |= EFLAG_COMIO;\n  }\n  if (ansir & ansir_emulate_fossil) {\n    flags |= EFLAG_SYNC_FOSSIL;\n  }\n  if (ansir & ansir_netfoss) {\n    flags |= EFLAG_NETFOSS;\n    // NetFoss implies temp dir too.\n    flags |= EFLAG_TEMP_DIR;\n  }\n  if (ansir & ansir_temp_dir) {\n    flags |= EFLAG_TEMP_DIR;\n  }\n  if (ansir & ansir_stdio) {\n    flags |= EFLAG_STDIO;\n  }\n  if (ansir & ansir_binary) {\n    flags |= EFLAG_BINARY;\n  }\n  return flags;\n}\n"
  },
  {
    "path": "bbs/utility.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*              Copyright (C)2014-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_BBS_UTILITY_H\r\n#define INCLUDED_BBS_UTILITY_H\r\n\r\n#include <cstdint>\r\n#include <filesystem>\r\n#include <string>\r\n#include <vector>\r\n\r\nstruct net_header_rec;\r\nvoid remove_from_temp(const std::string& file_name, const std::filesystem::path& directory_name,\r\n                      bool bPrintStatus);\r\nfloat post_ratio();\r\nvoid reset_disable_conf();\r\nbool okansi();\r\nlong nsl();\r\nvoid send_net(net_header_rec* nh, std::vector<uint16_t> list, const std::string& text,\r\n              const std::string& byname);\r\nstd::string stripfn(const std::string& file_name);\r\nstd::string get_wildlist(const std::string& file_mask);\r\nint side_menu(int* menu_pos, bool redraw, const std::vector<std::string>& menu_items, int xpos,\r\n              int ypos, struct side_menu_colors* smc);\r\n/** True if an external fsed is defined and user has ansi */\r\nbool ok_external_fsed();\r\n/** True if an external or internal fsed is allowed */\r\nbool okfsed();\r\n/** True if an internal fsed is enabled and user has ansi */\r\nbool ok_internal_fsed();\r\nuint32_t ansir_to_flags(uint16_t ansir);\r\n\r\n#endif\r\n"
  },
  {
    "path": "bbs/utility_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2014-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n\r\n#include \"bbs/utility.h\"\r\n#include \"bbs/bbs_helper.h\"\r\n\r\n#include \"gtest/gtest.h\"\r\n\r\nTEST(UtilityTest, StripFnSmoke) {\r\n  EXPECT_EQ(\"\", stripfn(\"\"));\r\n  EXPECT_EQ(\"\", stripfn(\"/\"));\r\n  EXPECT_EQ(\"\", stripfn(\"///\"));\r\n  EXPECT_EQ(\"\", stripfn(\"C:\\\\\"));\r\n\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"foo     .zip\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"foo.zip\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"X\\\\FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"X/FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"/X/FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"//X/FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"C:\\\\X\\\\FOO.ZIP\"));\r\n  EXPECT_EQ(\"foo.zip\", stripfn(\"C:\\\\X\\\\FOO  .ZIP\"));\r\n  EXPECT_EQ(\"foo\", stripfn(\"C:\\\\X\\\\FOO\"));\r\n\r\n\r\n  EXPECT_EQ(\"*\", stripfn(\"*\"));\r\n  EXPECT_EQ(\".*\", stripfn(\".*\"));\r\n}\r\n"
  },
  {
    "path": "bbs/valscan.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/valscan.h\"\n\n#include <algorithm>\n#include \"bbs/bbs.h\"\n#include \"common/com.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"common/datetime.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/subacc.h\"\n#include \"common/input.h\"\n#include \"bbs/msgbase1.h\"\n#include \"bbs/read_message.h\"\n#include \"common/output.h\"\n#include \"core/strings.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid valscan() {\n  // Must be local cosysop or better\n  if (!lcs()) {\n    return;\n  }\n\n  int ac = 0;\n  auto os = a()->current_user_sub_num();\n\n  if (ok_multiple_conf(a()->user(), a()->uconfsub)) {\n    ac = 1;\n    tmp_disable_conf(true);\n  }\n  bool done = false;\n  for (auto usubn = 0; usubn < wwiv::stl::size_int(a()->usub) && !a()->sess().hangup() && !done; usubn++) {\n    if (!iscan(usubn)) {\n      continue;\n    }\n    if (a()->sess().GetCurrentReadMessageArea() < 0) {\n      return;\n    }\n\n    uint32_t sq = a()->sess().qsc_p[usubn];\n\n    // Must be sub with validation \"on\"\n    if (a()->current_sub().nets.empty()\n        || !(a()->current_sub().anony & anony_val_net)) {\n      continue;\n    }\n\n    bout.nl();\n    bout.ansic(2);\n    bout.clreol();\n    bout.print(\"{{ ValScanning {} }}\\r\\n\", a()->current_sub().name);\n    bout.clear_lines_listed();\n    bout.clreol();\n\n    bout.move_up_if_newline(2);\n\n    for (int i = 1; i <= a()->GetNumMessagesInCurrentMessageArea() && !a()->sess().hangup() && !done; i++) {    // was i = 0\n      if (get_post(i)->status & status_pending_net) {\n        a()->CheckForHangup();\n        a()->tleft(true);\n        if (i > 0 && i <= a()->GetNumMessagesInCurrentMessageArea()) {\n          bool next;\n          int val;\n          read_post(i, &next, &val);\n          bout.print(\"|#4[|#4Subboard: {}|#1]\\r\\n\", a()->current_sub().name);\n          bout.outstr(\"|#1D|#9)elete, |#1R|#9)eread |#1V|#9)alidate, |#1M|#9)ark Validated, |#1Q|#9)uit: |#2\");\n          char ch = onek(\"QDVMR\");\n          switch (ch) {\n          case 'Q':\n            done = true;\n            break;\n          case 'R':\n            i--;\n            continue;\n          case 'V': {\n            open_sub(true);\n            resynch(&i, nullptr);\n            postrec *p1 = get_post(i);\n            p1->status &= ~status_pending_net;\n            write_post(i, p1);\n            close_sub();\n            send_net_post(p1, a()->current_sub());\n            bout.nl();\n            bout.outstr(\"|#7Message sent.\\r\\n\\n\");\n          }\n          break;\n          case 'M':\n            if (lcs() && i > 0 && i <= a()->GetNumMessagesInCurrentMessageArea() &&\n                a()->current_sub().anony & anony_val_net &&\n                !a()->current_sub().nets.empty()) {\n              wwiv::bbs::OpenSub opened_sub(true);\n              resynch(&i, nullptr);\n              postrec *p1 = get_post(i);\n              p1->status &= ~status_pending_net;\n              write_post(i, p1);\n              bout.nl();\n              bout.outstr(\"|#9Not set for net pending now.\\r\\n\\n\");\n            }\n            break;\n          case 'D':\n            if (lcs()) {\n              if (i > 0) {\n                open_sub(true);\n                resynch(&i, nullptr);\n                postrec p2 = *get_post(i);\n                delete_message(i);\n                close_sub();\n                if (p2.ownersys == 0) {\n                  User tu;\n                  a()->users()->readuser(&tu, p2.owneruser);\n                  if (!tu.deleted()) {\n                    if (date_to_daten(tu.firston()) < p2.daten) {\n                      bout.nl();\n                      bout.outstr(\"|#2Remove how many posts credit? \");\n                      char szNumCredits[ 11 ];\n                      bin.input(szNumCredits, 3, true);\n                      int num_post_credits = 1;\n                      if (szNumCredits[0]) {\n                        num_post_credits = to_number<int>(szNumCredits);\n                      }\n                      num_post_credits = std::min<int>(tu.messages_posted(), num_post_credits);\n                      if (num_post_credits) {\n                        tu.messages_posted(tu.messages_posted() - static_cast<uint16_t>(num_post_credits));\n                      }\n                      bout.nl();\n                      bout.print(\"|#3Post credit removed = {}\\r\\n\", num_post_credits);\n                      tu.deleted_posts(tu.deleted_posts() + 1);\n                      a()->users()->writeuser(&tu, p2.owneruser);\n                      a()->UpdateTopScreen();\n                    }\n                  }\n                }\n                resynch(&i, &p2);\n              }\n            }\n            break;\n          }\n        }\n      }\n    }\n    a()->sess().qsc_p[usubn] = sq;\n  }\n\n  if (ac) {\n    tmp_disable_conf(false);\n  }\n\n  a()->set_current_user_sub_num(os);\n  bout.nl(2);\n}\n"
  },
  {
    "path": "bbs/valscan.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_VALSCAN_H__\n#define __INCLUDED_BBS_VALSCAN_H__\n\nvoid valscan();\n\n\n#endif  // __INCLUDED_BBS_VALSCAN_H__"
  },
  {
    "path": "bbs/vote.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/vote.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/mmkey.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nstatic void print_quest(int mapp, int map[21]) {\n  votingrec v;\n\n  bout.cls();\n  bout.litebar(StrCat(a()->config()->system_name(), \" Voting Questions\"));\n  bool abort = false;\n  File voteFile(FilePath(a()->config()->datadir(), VOTING_DAT));\n  if (!voteFile.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n\n  for (int i = 1; i <= mapp && !abort; i++) {\n    voteFile.Seek(map[i] * sizeof(votingrec), File::Whence::begin);\n    voteFile.Read(&v, sizeof(votingrec));\n\n    auto buffer = fmt::sprintf(\"|#6%c |#2%2d|#7) |#1%s\",\n             a()->user()->votes(map[i]) ? ' ' : '*', i, v.question);\n    bout.bpla(buffer, &abort);\n  }\n  voteFile.Close();\n  bout.nl();\n  if (abort) {\n    bout.nl();\n  }\n}\n\nstatic bool print_question(int i, int ii) {\n  votingrec v;\n\n  File voteFile(FilePath(a()->config()->datadir(), VOTING_DAT));\n  if (!voteFile.Open(File::modeReadOnly | File::modeBinary)) {\n    return false;\n  }\n  voteFile.Seek(ii * sizeof(votingrec), File::Whence::begin);\n  voteFile.Read(&v, sizeof(votingrec));\n  voteFile.Close();\n  bool abort = false;\n\n  if (!v.numanswers) {\n    return false;\n  }\n\n  bout.cls();\n  bout.bpla(fmt::format(\"|#5Voting question #{}\", i), &abort);\n  bout.ansic(1);\n  bout.bpla(v.question, &abort);\n  bout.nl();\n  int t = 0;\n  voting_response vr{};\n  for (int i1 = 0; i1 < v.numanswers; i1++) {\n    vr = v.responses[i1];\n    t += vr.numresponses;\n  }\n\n  a()->status_manager()->reload_status();\n  const auto b = fmt::sprintf(\"|#9Users voting: |#2%4.1f%%\\r\\n\",\n                       static_cast<double>(t) /\n                           static_cast<double>(a()->status_manager()->user_count()) * 100.0);\n  bout.bpla(b, &abort);\n  int t1 = (t) ? t : 1;\n  bout.bpla(\" |#20|#9) |#9No Comment\", &abort);\n  std::set<char> odc;\n  for (int i3 = 0; i3 < v.numanswers && !abort; i3++) {\n    vr = v.responses[ i3 ];\n    if (((i3 + 1) % 10) == 0) {\n      odc.insert('0' + static_cast<char>((i3 + 1) / 10));\n    }\n    const auto l = fmt::sprintf(\"|#2%2d|#9) |#9%-60s   |#3%4d  |#1%5.1f%%\",\n            i3 + 1, vr.response, vr.numresponses,\n            static_cast<float>(vr.numresponses) / static_cast<float>(t1) * 100.0);\n    bout.bpla(l , &abort);\n  }\n  bout.nl();\n  if (abort) {\n    bout.nl();\n  }\n  return !abort;\n}\n\nstatic void vote_question(int i, int ii) {\n  votingrec v;\n\n  bool pqo = print_question(i, ii);\n  if (a()->user()->restrict_vote() || a()->sess().effective_sl() <= 10 || !pqo) {\n    return;\n  }\n\n  File file(FilePath(a()->config()->datadir(), VOTING_DAT));\n  if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n  file.Seek(ii * sizeof(votingrec), File::Whence::begin);\n  file.Read(&v, sizeof(votingrec));\n  file.Close();\n\n  if (!v.numanswers) {\n    return;\n  }\n\n  std::string message = \"|#9Your vote: |#1\";\n  if (a()->user()->votes(ii)) {\n    message.append(v.responses[ a()->user()->votes(ii) - 1 ].response);\n  } else {\n    message +=  \"No Comment\";\n  }\n  bout.outstr(message);\n  bout.nl(2);\n  bout.outstr(\"|#5Change it? \");\n  if (!bin.yesno()) {\n    return;\n  }\n\n  bout.print(\"|#5Which (0-{})? \", static_cast<int>(v.numanswers));\n  bout.mpl(2);\n  auto empty_set = std::set<char>();\n  const auto ans = mmkey(empty_set);\n  int i1 = to_number<int>(ans);\n  if (i1 > v.numanswers) {\n    i1 = 0;\n  }\n  if (i1 == 0 && ans != \"0\") {\n    return;\n  }\n\n  if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n  file.Seek(ii * sizeof(votingrec), File::Whence::begin);\n  file.Read(&v, sizeof(votingrec));\n\n  if (!v.numanswers) {\n    file.Close();\n    return;\n  }\n  if (a()->user()->votes(ii)) {\n    v.responses[ a()->user()->votes(ii) - 1 ].numresponses--;\n  }\n  a()->user()->votes(ii, i1);\n  if (i1) {\n    v.responses[ a()->user()->votes(ii) - 1 ].numresponses++;\n  }\n  file.Seek(ii * sizeof(votingrec), File::Whence::begin);\n  file.Write(&v, sizeof(votingrec));\n  file.Close();\n  bout.nl(2);\n}\n\nvoid vote() {\n  votingrec v;\n\n  File voteFile(FilePath(a()->config()->datadir(), VOTING_DAT));\n  if (!voteFile.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n\n  if (const auto n = static_cast<int>(voteFile.length() / sizeof(votingrec)) - 1; n < 20) {\n    v.question[0] = 0;\n    v.numanswers = 0;\n    for (int i = n; i < 20; i++) {\n      voteFile.Write(&v, sizeof(votingrec));\n    }\n  }\n\n  std::set<char> odc;\n\n  int map[21], mapp = 0;\n  for (int i1 = 0; i1 < 20; i1++) {\n    voteFile.Seek(i1 * sizeof(votingrec), File::Whence::begin);\n    voteFile.Read(&v, sizeof(votingrec));\n    if (v.numanswers) {\n      map[++mapp] = i1;\n      if ((mapp % 10) == 0) {\n        odc.insert('0' + static_cast<char>(mapp / 10));\n      }\n    }\n  }\n  voteFile.Close();\n\n  if (mapp == 0) {\n    bout.outstr(\"\\r\\n\\n|#6No voting questions currently.\\r\\n\\n\");\n    return;\n  }\n  bool done = false;\n  do {\n    print_quest(mapp, &map[0]);\n    bout.nl();\n    bout.outstr(\"|#9(|#2Q|#9=|#2Quit|#9) Voting: |#2# |#9: \");\n    bout.outstr(\"|#9(|#2Q|#9=|#2Quit|#9) Voting: |#2# |#9: \");\n    bout.mpl(2);\n    std::string answer= mmkey(odc);\n    int nQuestionNum = to_number<int>(answer);\n    if (nQuestionNum > 0 && nQuestionNum <= mapp) {\n      vote_question(nQuestionNum, map[ nQuestionNum ]);\n    } else if (answer == \"Q\") {\n      done = true;\n    } else if (answer == \"?\") {\n      print_quest(mapp, &map[0]);\n    }\n  } while (!done && !a()->sess().hangup());\n}\n"
  },
  {
    "path": "bbs/vote.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_VOTE_H__\n#define __INCLUDED_BBS_VOTE_H__\n\nvoid vote();\n\n#endif  // __INCLUDED_BBS_VOTE_H__"
  },
  {
    "path": "bbs/voteedit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/voteedit.h\"\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/utility.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic void print_quests() {\n  File file(FilePath(a()->config()->datadir(), VOTING_DAT));\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    return;\n  }\n  bool abort = false;\n  for (int i = 1; (i <= 20) && !abort; i++) {\n    file.Seek(static_cast<long>(i - 1) * sizeof(votingrec), File::Whence::begin);\n\n    votingrec v{};\n    file.Read(&v, sizeof(votingrec));\n    auto buffer = fmt::sprintf(\"|#2%2d|#7) |#1%s\", i, v.numanswers ? v.question : \">>> NO QUESTION <<<\");\n    bout.bpla(buffer, &abort);\n  }\n  bout.nl();\n  if (abort) {\n    bout.nl();\n  }\n}\n\nstatic void set_question(int ii) {\n  votingrec v{};\n  voting_response vr{};\n\n  bout.outstr(\"|#7Enter new question or just press [|#1Enter|#7] for none.\\r\\n: \");\n  const auto question = bin.input_text(75);\n  to_char_array(v.question, question);\n  v.numanswers = 0;\n  vr.numresponses = 0;\n  vr.response[0] = 'X';\n  vr.response[1] = 0;\n  for (auto& response : v.responses) {\n    response = vr;\n  }\n  if (question.empty()) {\n    bout.nl();\n    bout.print(\"|#6Delete Question #{}, Are you sure? \", ii+1);\n    if (!bin.yesno()) {\n      return;\n    }\n  } else {\n    bout.nl();\n    bout.outstr(\"|#5Enter answer choices, Enter a blank line when finished.\");\n    bout.nl(2);\n    while (v.numanswers < 19) {\n      bout.print(\"|#2{}|#7: \", v.numanswers + 1);\n      auto response = bin.input_text(63);\n      to_char_array(vr.response, response);\n      vr.numresponses = 0;\n      v.responses[v.numanswers] = vr;\n      if (response.empty()) {\n        // empty reponse means break.\n        break;\n      }\n      ++v.numanswers;\n    }\n  }\n\n  File file(FilePath(a()->config()->datadir(), VOTING_DAT));\n  file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  file.Seek(ii * sizeof(votingrec), File::Whence::begin);\n  file.Write(&v, sizeof(votingrec));\n  file.Close();\n\n  const int num_users = a()->users()->num_user_records();\n  for (int user_number = 1; user_number <= num_users; user_number++) {\n    if (auto u = a()->users()->readuser(user_number)) {\n      u->votes(ii, 0);\n      a()->users()->writeuser(u, user_number);\n    }\n  }\n}\n\n\nvoid ivotes() {\n  votingrec v{};\n\n  File votingDat(FilePath(a()->config()->datadir(), VOTING_DAT));\n  votingDat.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  int n = static_cast<int>((votingDat.length() / sizeof(votingrec)) - 1);\n  if (n < 20) {\n    v.question[0] = '\\0';\n    v.numanswers = 0;\n    for (int i = n; i < 20; i++) {\n      votingDat.Write(&v, sizeof(votingrec));\n    }\n  }\n  votingDat.Close();\n  bool done = false;\n  do {\n    print_quests();\n    bout.nl();\n    bout.outstr(\"|#2Which (Q=Quit) ? \");\n    std::string questionum = bin.input(2);\n    if (questionum == \"Q\") {\n      done = true;\n    }\n    int i = to_number<int>(questionum);\n    if (i > 0 && i < 21) {\n      set_question(i - 1);\n    }\n  } while (!done && !a()->sess().hangup());\n}\n\n\nvoid voteprint() {\n  const int num_user_records = a()->users()->num_user_records();\n  auto* x = static_cast<char *>(BbsAllocA(20 * (2 + num_user_records)));\n  if (x == nullptr) {\n    return;\n  }\n  for (int i = 0; i <= num_user_records; i++) {\n    User u;\n    a()->users()->readuser(&u, i);\n    for (int i1 = 0; i1 < 20; i1++) {\n      x[ i1 + i * 20 ] = static_cast<char>(u.votes(i1));\n    }\n  }\n  File votingText(FilePath(a()->config()->gfilesdir(), VOTING_TXT));\n  votingText.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile | File::modeText);\n  votingText.Write(votingText.full_pathname());\n\n  File votingDat(FilePath(a()->config()->datadir(), VOTING_DAT));\n  a()->status_manager()->reload_status();\n\n  for (int i1 = 0; i1 < 20; i1++) {\n    if (!votingDat.Open(File::modeReadOnly | File::modeBinary)) {\n      continue;\n    }\n    votingrec v{};\n    votingDat.Seek(i1 * sizeof(votingrec), File::Whence::begin);\n    votingDat.Read(&v, sizeof(votingrec));\n    votingDat.Close();\n    if (v.numanswers) {\n      bout.outstr(v.question);\n      bout.nl();\n      std::ostringstream text;\n      text << \"\\r\\n\" << v.question << \"\\r\\n\";\n      votingText.Write(text.str());\n      for (int i2 = 0; i2 < v.numanswers; i2++) {\n        text.clear();\n        text.str(\"     \");\n        text << v.responses[i2].response << \"\\r\\n\";\n        votingText.Write(text.str());\n        for (const auto& n : a()->names()->names_vector()) {\n          if (x[i1 + 20 * n.number] == i2 + 1) {\n            text.clear();\n            text.str(\"          \");\n            text << n.name << \" #\" << n.number << \"\\r\\n\";\n            votingText.Write(text.str());\n          }\n        }\n      }\n    }\n  }\n  votingText.Close();\n  free(x);\n}\n"
  },
  {
    "path": "bbs/voteedit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_BBS_VOTEEDIT_H__\n#define __INCLUDED_BBS_VOTEEDIT_H__\n\nvoid ivotes();\nvoid voteprint();\n\n\n#endif  // __INCLUDED_BBS_VOTEEDIT_H__"
  },
  {
    "path": "bbs/wfc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/wfc.h\"\n\n#include \"bbs/application.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsovl1.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/chnedit.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/diredit.h\"\n#include \"bbs/exec.h\"\n#include \"bbs/external_edit.h\"\n#include \"bbs/gfileedit.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/multinst.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/readmail.h\"\n#include \"bbs/ssh.h\"\n#include \"bbs/subedit.h\"\n#include \"bbs/sysopf.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/voteedit.h\"\n#include \"bbs/wqscn.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/workspace.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/net/networks.h\"\n\n#include <chrono>\n#include <memory>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace std::chrono_literals;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\n// Local Functions\nstatic std::unique_ptr<char[]> screen_buffer;\nstatic int inst_num;\nstatic constexpr int sysop_usernum = 1;\n\nvoid wfc_cls(Application* a) {\n  bout.ResetColors();\n  a->Cls();\n  bout.localIO()->SetCursor(LocalIO::cursorNormal);\n  // Every time we clear the WFC, reset the lines listed.\n  bout.clear_lines_listed();\n}\n\nnamespace wwiv::bbs {\n\nstatic void wfc_update() {\n  // Every time we update the WFC, reset the lines listed.\n  bout.clear_lines_listed();\n\n  bout.localIO()->PutsXYA(57, 18, 15, fmt::format(\"{:<3}\", inst_num));\n  if (const auto ir = a()->instances().at(inst_num); ir.online()) {\n    const auto unn = a()->names()->UserName(ir.user_number());\n    bout.localIO()->PutsXYA(42, 19, 14, fmt::format(\"{:<25}\", unn));\n  } else {\n    bout.localIO()->PutsXYA(42, 19, 14, fmt::format(\"{:<25}\", \"Nobody\"));\n  }\n\n  auto activity_string = make_inst_str(inst_num, INST_FORMAT_WFC);\n  bout.localIO()->PutsXYA(42, 20, 14, fmt::format(\"{:<25}\", activity_string));\n  if (num_instances() > 1) {\n    do {\n      ++inst_num;\n      if (inst_num > num_instances()) {\n        inst_num = 1;\n      }\n    } while (inst_num == a()->sess().instance_number());\n  }\n}\n\nvoid WFC::Clear() {\n  wfc_cls(a_);\n  status_ = 0;\n}\n\nvoid WFC::DrawScreen() {\n  static steady_clock::time_point wfc_time;\n  static steady_clock::time_point poll_time;\n\n  auto nNumNewMessages = check_new_mail(sysop_usernum);\n  auto status = a()->status_manager()->get_status();\n  if (status_ == 0) {\n    bout.localIO()->SetCursor(LocalIO::cursorNone);\n    a()->Cls();\n    if (!screen_buffer) {\n      screen_buffer = std::make_unique<char[]>(80 * 25 * sizeof(uint16_t));\n      File wfcFile(FilePath(a()->config()->datadir(), WFC_DAT));\n      if (!wfcFile.Open(File::modeBinary | File::modeReadOnly)) {\n        Clear();\n        LOG(FATAL) << wfcFile << \" NOT FOUND.\";\n      }\n      wfcFile.Read(screen_buffer.get(), 80 * 25 * sizeof(uint16_t));\n    }\n    bout.localIO()->WriteScreenBuffer(screen_buffer.get());\n    const auto title = fmt::format(\"Activity and Statistics of {} Node {}\",\n                                   a()->config()->system_name(), a()->sess().instance_number());\n    bout.localIO()->PutsXYA(1 + (76 - wwiv::strings::ssize(title)) / 2, 4, 15, title);\n    bout.localIO()->PutsXYA(8, 1, 14, fulldate());\n    bout.localIO()->PutsXYA(40, 1, 3, \"OS: \");\n    bout.localIO()->PutsXYA(44, 1, 14, wwiv::os::os_version_string());\n    bout.localIO()->PutsXYA(21, 6, 14, std::to_string(status->calls_today()));\n    auto feedback_waiting = 0;\n    if (const auto sysop = a()->users()->readuser(sysop_usernum)) {\n      feedback_waiting = sysop->email_waiting();\n    }\n    bout.localIO()->PutsXYA(21, 7, 14, std::to_string(feedback_waiting));\n    if (nNumNewMessages) {\n      bout.localIO()->PutsXYA(29, 7, 3, \"New:\");\n      bout.localIO()->PutsXYA(34, 7, 12, std::to_string(nNumNewMessages));\n    }\n    bout.localIO()->PutsXYA(21, 8, 14, std::to_string(status->uploads_today()));\n    bout.localIO()->PutsXYA(21, 9, 14, std::to_string(status->msgs_today()));\n    bout.localIO()->PutsXYA(21, 10, 14, std::to_string(status->localposts()));\n    bout.localIO()->PutsXYA(21, 11, 14, std::to_string(status->email_today()));\n    bout.localIO()->PutsXYA(21, 12, 14, std::to_string(status->feedback_today()));\n    const auto percent = static_cast<double>(status->active_today_minutes()) / 1440.0;\n    bout.localIO()->PutsXYA(\n        21, 13, 14,\n        fmt::format(\"{} Mins ({:.2}%)  \", status->active_today_minutes(), 100.0 * percent));\n    bout.localIO()->PutsXYA(58, 6, 14, full_version());\n\n    bout.localIO()->PutsXYA(58, 7, 14, std::to_string(status->status_net_version()));\n    bout.localIO()->PutsXYA(58, 8, 14, std::to_string(status->num_users()));\n    bout.localIO()->PutsXYA(58, 9, 14, std::to_string(status->caller_num()));\n    const auto percent_active =\n        status->days_active() == 0\n            ? \"N/A\"\n            : fmt::sprintf(\"%.2f\", static_cast<float>(status->caller_num()) /\n                                       static_cast<float>(status->days_active()));\n    bout.localIO()->PutsXYA(58, 10, 14, percent_active);\n    bout.localIO()->PutsXYA(58, 11, 14, sysop2() ? \"Available    \" : \"Not Available\");\n\n    auto ir = a()->instances().at(a()->sess().instance_number());\n    if (ir.user_number() < a()->config()->max_users() && ir.user_number() > 0) {\n      const auto unn = a()->names()->UserName(ir.user_number());\n      bout.localIO()->PutsXYA(33, 16, 14, fmt::format(\"{:<20}\", unn));\n    } else {\n      bout.localIO()->PutsXYA(33, 16, 14, fmt::format(\"{:<20}\", \"Nobody\"));\n    }\n\n    status_ = 1;\n    wfc_update();\n    poll_time = wfc_time = steady_clock::now();\n  } else {\n    auto screen_saver_time = seconds(a()->screen_saver_time);\n    if (a()->screen_saver_time == 0 || steady_clock::now() - wfc_time < screen_saver_time) {\n      auto t = times();\n      bout.localIO()->PutsXYA(28, 1, 14, t);\n      bout.localIO()->PutsXYA(58, 11, 14, sysop2() ? \"Available    \" : \"Not Available\");\n      if (steady_clock::now() - poll_time > seconds(10)) {\n        wfc_update();\n        poll_time = steady_clock::now();\n      }\n    } else {\n      if ((steady_clock::now() - poll_time > seconds(10)) || status_ == 1) {\n        status_ = 2;\n        a_->Cls();\n        bout.localIO()->PutsXYA(random_number(38), random_number(24), random_number(14) + 1,\n                                \"WWIV Screen Saver - Press Any Key For WWIV\");\n        wfc_time = steady_clock::now() - seconds(a()->screen_saver_time) - seconds(1);\n        poll_time = steady_clock::now();\n      }\n    }\n  }\n}\n\nWFC::WFC(Application* a) : a_(a) {\n  bout.localIO()->SetCursor(LocalIO::cursorNormal);\n  status_ = 0;\n  inst_num = 1;\n  Clear();\n\n  bout.remoteIO()->remote_info().clear();\n  a_->frequent_init();\n  a_->sess().user_num(0);\n  // Since hang_it_up sets hangup_ = true, let's ensure we're always\n  // not in this state when we enter the WFC.\n  a_->sess().hangup(false);\n  a_->set_at_wfc(false);\n  write_inst(INST_LOC_WFC, 0, INST_FLAGS_NONE);\n  // We'll read the sysop record for defaults, but let's set\n  // usernum to 0 here since we don't want to botch up the\n  // sysop's record if things go wrong.\n  // TODO(rushfan): Let's make record 0 the logon defaults\n  // and stop using the sysop record.\n  a_->ReadCurrentUser(1);\n  read_qscn(1, a_->sess().qsc, false);\n  // N.B. This used to be 1.\n  a_->sess().user_num(0);\n\n  a_->reset_effective_sl();\n  if (a_->user()->deleted()) {\n    a_->user()->screen_width(80);\n    a_->user()->screen_lines(25);\n  }\n  a_->sess().num_screen_lines(bout.localIO()->GetDefaultScreenBottom() + 1);\n}\n\nWFC::~WFC() {\n  a_->set_at_wfc(false);\n  \n};\n\nstd::tuple<wfc_events_t, int> WFC::doWFCEvents() {\n  auto* io = bout.localIO();\n\n  auto last_date_status = a()->status_manager()->get_status();\n  for (;;) {\n    sleep_for(milliseconds(100));\n    yield();\n\n    write_inst(INST_LOC_WFC, 0, INST_FLAGS_NONE);\n    a_->set_net_num(0);\n    a_->set_at_wfc(true);\n\n    // If the date has changed since we last checked, then then run the beginday event.\n    if (date() != last_date_status->last_date()) {\n      if (a_->GetBeginDayNodeNumber() == 0 ||\n          a_->sess().instance_number() == a_->GetBeginDayNodeNumber()) {\n        beginday(true);\n        Clear();\n        // Update the status for the last date now that beginday has run.\n        last_date_status = a()->status_manager()->get_status();\n        continue;\n      }\n    }\n\n    a_->SetCurrentSpeed(\"KB\");\n    // try to check for packets to send every minute.\n    DrawScreen();\n    bin.okskey(false);\n    if (!io->KeyPressed()) {\n      // extra sleep.\n      sleep_for(milliseconds(100));\n      yield();\n      continue;\n    }\n    a_->set_at_wfc(false);\n    a_->ReadCurrentUser(sysop_usernum);\n    read_qscn(1, a()->sess().qsc, false);\n    a_->set_at_wfc(true);\n    auto ch = to_upper_case<char>(io->GetChar());\n    if (ch == 0) {\n      ch = io->GetChar();\n      a_->handle_sysop_key(ch);\n      continue;\n    }\n\n    a_->set_at_wfc(true);\n    bin.okskey(true);\n    bin.resetnsp();\n    io->SetCursor(LocalIO::cursorNormal);\n    switch (ch) {\n      // Local Logon\n    case SPACE: {\n      auto [ll, unx] = LocalLogon();\n      if (ll == local_logon_t::fast) {\n        return std::make_tuple(wfc_events_t::login_fast, unx);\n      }\n      if (ll == local_logon_t::prompt) {\n        return std::make_tuple(wfc_events_t::login, -1);\n      }\n      break;\n    }\n    // Show WFC Menu\n    case '?': {\n      std::string helpFileName = SWFC_NOEXT;\n      char chHelp;\n      do {\n        io->Cls();\n        bout.nl();\n        bout.print_help_file(helpFileName);\n        chHelp = bin.getkey();\n        helpFileName = (helpFileName == SWFC_NOEXT) ? SONLINE_NOEXT : SWFC_NOEXT;\n      } while (chHelp != SPACE && chHelp != ESC);\n    } break;\n    // Force Network Callout\n    case '/':\n      if (a_->current_net().sysnum) {\n        force_callout();\n      }\n      break;\n    case ',':\n      // Print NetLogs\n      if (a_->current_net().sysnum > 0 || !a_->nets().empty()) {\n        io->GotoXY(2, 23);\n        bout.outstr(\"|#7(|#2Q|#7=|#2Quit|#7) Display Which NETDAT Log File (|#10|#7-|#12|#7): \");\n        const auto netdat_num = onek(\"Q012\");\n        switch (netdat_num) {\n        case '0':\n        case '1':\n        case '2': {\n          bout.print_local_file(fmt::format(\"netdat{}.log\", netdat_num));\n        } break;\n        default:;\n        }\n      }\n      break;\n      // Net List\n    case '`':\n      if (a_->current_net().sysnum) {\n        query_print_net_listing(true);\n      }\n      break;\n      // [ESC] Quit the BBS\n    case ESC:\n      io->GotoXY(2, 23);\n      bout.outstr(\"|#7Exit the BBS? \");\n      if (bin.yesno()) {\n        return std::make_tuple(wfc_events_t::exit, -1);\n      }\n      io->Cls();\n      break;\n      // BoardEdit\n    case 'B':\n      write_inst(INST_LOC_BOARDEDIT, 0, INST_FLAGS_NONE);\n      boardedit();\n      cleanup_net();\n      break;\n      // ChainEdit\n    case 'C':\n      write_inst(INST_LOC_CHAINEDIT, 0, INST_FLAGS_NONE);\n      chainedit();\n      break;\n      // DirEdit\n    case 'D':\n      write_inst(INST_LOC_DIREDIT, 0, INST_FLAGS_NONE);\n      dlboardedit();\n      break;\n      // Send Email\n    case 'E':\n      Clear();\n      a_->sess().user_num(1);\n      bout.outstr(\"|#1Send Email:\");\n      send_email();\n      a_->WriteCurrentUser(sysop_usernum);\n      cleanup_net();\n      break;\n    // GfileEdit\n    case 'G':\n      write_inst(INST_LOC_GFILEEDIT, 0, INST_FLAGS_NONE);\n      gfileedit();\n      break;\n    // ConfEdit\n    case 'J':\n      Clear();\n      edit_confs();\n      break;\n      // SendMailFile\n    case 'K': {\n      Clear();\n      a_->sess().user_num(1);\n      bout.outstr(\"|#1Send any Text File in Email:\\r\\n\\n|#2Filename: \");\n      auto buffer = bin.input_path(50);\n      LoadFileIntoWorkspace(a()->context(), buffer, false);\n      send_email();\n      a_->WriteCurrentUser(sysop_usernum);\n      cleanup_net();\n    } break;\n    // Print Log Daily logs\n    case 'L': {\n      Clear();\n      const auto status = a()->status_manager()->get_status();\n      bout.print_local_file(status->log_filename(0));\n    } break;\n    // Read User Mail\n    case 'M': {\n      Clear();\n      a_->sess().user_num(sysop_usernum);\n      readmail(false);\n      a_->WriteCurrentUser(sysop_usernum);\n      cleanup_net();\n    } break;\n    // Print Net Log\n    case 'N': {\n      Clear();\n      bout.print_local_file(NET_LOG);\n    } break;\n    // EditTextFile\n    case 'O': {\n      Clear();\n      write_inst(INST_LOC_TEDIT, 0, INST_FLAGS_NONE);\n      bout.outstr(\"\\r\\n|#1Edit any Text File: \\r\\n\\n|#2Filename: \");\n      const auto current_dir_slash = File::EnsureTrailingSlash(File::current_directory());\n      auto net_filename = bin.input_path(current_dir_slash, 50);\n      if (!net_filename.empty()) {\n        fsed_text_edit(net_filename, \"\", 500, MSGED_FLAG_NO_TAGLINE);\n      }\n    } break;\n    // Print Network Pending list\n    case 'P': {\n      Clear();\n      print_pending_list();\n    } break;\n    // Quit BBS\n    case 'Q':\n      io->GotoXY(2, 23);\n      return std::make_tuple(wfc_events_t::exit, -1);\n      // Read All Mail\n    case 'R':\n      Clear();\n      write_inst(INST_LOC_MAILR, 0, INST_FLAGS_NONE);\n      mailr();\n      break;\n      // Print Current Status\n    case 'S':\n      prstatus();\n      bin.getkey();\n      break;\n    case 'T': {\n      if (a()->terminal_command.empty()) {\n        bout.pl(\"Terminal Command not specified. \");\n        bout.pl(\" Please set TERMINAL_CMD in wwiv.ini\");\n        bin.getkey();\n        break;\n      }\n      wwiv::bbs::CommandLine cl(a()->terminal_command);\n      exec_cmdline(cl, INST_FLAGS_NONE);\n    } break;\n    case 'U': {\n      // User edit\n      auto exe = FilePath(a()->bindir(), \"wwivconfig\");\n#ifdef _WIN32\n      // CreateProcess is failing on Windows with the .exe extension, and since\n      // we don't use MakeAbsCmd on this, it's without .exe.\n      exe.replace_extension(\".exe\");\n#endif // _WIN32\n      wwiv::bbs::CommandLine cl(StrCat(exe.string(), \" --user_editor\"));\n      exec_cmdline(cl, INST_FLAGS_NONE);\n    } break;\n    case 'V': {\n      // InitVotes\n      Clear();\n      write_inst(INST_LOC_VOTEEDIT, 0, INST_FLAGS_NONE);\n      ivotes();\n    } break;\n    // Edit Gfile\n    case 'W': {\n      Clear();\n      write_inst(INST_LOC_TEDIT, 0, INST_FLAGS_NONE);\n      bout.print(\"|#1Edit {}<filename>: \\r\\n\", a()->config()->gfilesdir().string());\n      text_edit();\n    } break;\n    // Print Yesterday's Log\n    case 'Y': {\n      Clear();\n      const auto status = a()->status_manager()->get_status();\n      bout.print_local_file(status->log_filename(1));\n    } break;\n    // Print Activity (Z) Log\n    case 'Z': {\n      zlog();\n      bout.nl();\n      bin.getkey();\n    } break;\n    }\n    Clear();\n    a_->frequent_init();\n    a_->ReadCurrentUser(sysop_usernum);\n    read_qscn(1, a()->sess().qsc, false);\n    a_->reset_effective_sl();\n    a_->sess().user_num(sysop_usernum);\n\n    catsl();\n    write_inst(INST_LOC_WFC, 0, INST_FLAGS_NONE);\n  }\n}\n\nstd::tuple<local_logon_t, int> WFC::LocalLogon() {\n  bout.localIO()->GotoXY(2, 23);\n  bout.outstr(\"|#9Log on to the BBS?\");\n  auto d = steady_clock::now();\n  // TODO(rushfan): use wwiv::os::wait_for\n  while (!bout.localIO()->KeyPressed() && (steady_clock::now() - d < minutes(1))) {\n    sleep_for(10ms);\n  }\n\n  if (!bout.localIO()->KeyPressed()) {\n    a_->Cls();\n    return std::make_tuple(local_logon_t::exit, -1);\n  }\n\n  auto unx = -1;\n  const auto ch = static_cast<unsigned char>(to_upper_case<char>(bout.localIO()->GetChar()));\n  switch (ch) {\n  case 'Y': {\n    bout.localIO()->Puts(YesNoString(true));\n    bout.nl();\n    return std::make_tuple(local_logon_t::prompt, -1);\n  }\n  case 0:\n  case 0xE0: {\n    // The ch == 224 is a Win32'ism\n    bout.localIO()->GetChar();\n    return std::make_tuple(local_logon_t::exit, -1);\n  }\n  case 'F': // 'F' for Fast\n  case '1':\n    unx = 1;\n    break;\n  case '2':\n  case '3':\n  case '4':\n  case '5':\n  case '6':\n  case '7':\n  case '8':\n  case '9':\n    unx = ch - '0';\n    break;\n  default:\n    return std::make_tuple(local_logon_t::exit, -1);\n  }\n\n  // We have a user number to try in unx to use for a\n  // fast login.\n\n  if (unx > a_->status_manager()->user_count()) {\n    return std::make_tuple(local_logon_t::exit, -1);\n  }\n\n  if (const auto tu = a_->users()->readuser(unx); tu->sl() != 255 || tu->deleted()) {\n    return std::make_tuple(local_logon_t::exit, -1);\n  }\n\n  a_->sess().user_num(unx);\n  const auto saved_at_wfc = a_->at_wfc();\n  a_->set_at_wfc(false);\n  a_->ReadCurrentUser();\n  read_qscn(a_->sess().user_num(), a()->sess().qsc, false);\n  a_->set_at_wfc(saved_at_wfc);\n  bout.outchr(ch);\n  bout.localIO()->Puts(\"\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\");\n  a_->reset_effective_sl();\n  changedsl();\n  return std::make_tuple(local_logon_t::fast, unx);\n}\n\n} // namespace wwiv::bbs\n"
  },
  {
    "path": "bbs/wfc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_WFC_H\n#define INCLUDED_BBS_WFC_H\n\n#include \"bbs/application.h\"\n\nvoid wfc_cls(Application* a);\n\nnamespace wwiv::bbs {\n\nenum class local_logon_t { exit, prompt, fast };\nenum class wfc_events_t { exit, login, login_fast };\n\nclass WFC {\npublic:\n  explicit WFC(Application* a);\n  virtual ~WFC();\n\n  std::tuple<wfc_events_t, int> doWFCEvents();\n\nprivate:\n  std::tuple<local_logon_t, int> LocalLogon();\n  void DrawScreen();\n  void Clear();\n\n  Application* a_{nullptr};\n  int status_{0};\n};\n\n}  // namespace wwiv::bbs\n\n#endif\n"
  },
  {
    "path": "bbs/wqscn.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/wqscn.h\"\n\n#include \"bbs/bbs.h\"\n#include \"common/context.h\"\n#include \"core/file.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include <memory>\n\nusing namespace wwiv::core;\n\nstatic std::unique_ptr<File> qscanFile;\n\nstatic bool open_qscn() {\n  if (!qscanFile) {\n    qscanFile.reset(new File(FilePath(a()->config()->datadir(), USER_QSC)));\n    if (!qscanFile->Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nvoid close_qscn() {\n  if (qscanFile->IsOpen()) {\n    qscanFile.reset();\n  }\n}\n\nvoid read_qscn(int user_number, uint32_t* qscn, bool stay_open, bool force_read) {\n  if (!force_read) {\n    if ((a()->sess().IsUserOnline() && user_number == a()->sess().user_num()) ||\n        (a()->at_wfc() && user_number == 1)) {\n      if (qscn != a()->sess().qsc) {\n        for (int i = (a()->config()->qscn_len() / 4) - 1; i >= 0; i--) {\n          qscn[i] = a()->sess().qsc[i];\n        }\n      }\n      return;\n    }\n  }\n  if (open_qscn()) {\n    if (const auto pos =\n            static_cast<long>(a()->config()->qscn_len()) * static_cast<long>(user_number);\n        pos + static_cast<long>(a()->config()->qscn_len()) <= qscanFile->length()) {\n      qscanFile->Seek(pos, File::Whence::begin);\n      qscanFile->Read(qscn, a()->config()->qscn_len());\n      if (!stay_open) {\n        close_qscn();\n      }\n      return;\n    }\n  }\n  if (!stay_open) {\n    close_qscn();\n  }\n\n  a()->sess().ResetQScanPointers(*a()->config());\n}\n\nvoid write_qscn(int user_number, uint32_t *qscn, bool stay_open) {\n  if (user_number < 1 || user_number > a()->config()->max_users() ||\n      a()->user()->guest_user()) {\n    return;\n  }\n\n  if ((a()->sess().IsUserOnline() && (user_number == a()->sess().user_num())) ||\n      (a()->at_wfc() && user_number == 1)) {\n    if (a()->sess().qsc != qscn) {\n      for (int i = (a()->config()->qscn_len() / 4) - 1; i >= 0; i--) {\n        a()->sess().qsc[i] = qscn[i];\n      }\n    }\n  }\n  if (open_qscn()) {\n    const auto pos = static_cast<long>(a()->config()->qscn_len()) * static_cast<long>(user_number);\n    qscanFile->Seek(pos, File::Whence::begin);\n    qscanFile->Write(qscn, a()->config()->qscn_len());\n    if (!stay_open) {\n      close_qscn();\n    }\n  }\n}\n\n"
  },
  {
    "path": "bbs/wqscn.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_WQSCN_H\n#define INCLUDED_BBS_WQSCN_H\n\n#include <cstdint>\n\nvoid close_qscn();\nvoid read_qscn(int user_number, uint32_t* qscn, bool stay_open, bool force_read = false);\nvoid write_qscn(int user_number, uint32_t* qscn, bool stay_open);\n\n#endif\n"
  },
  {
    "path": "bbs/wutil_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*              Copyright (C)2014-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"gtest/gtest.h\"\r\n\r\n#include \"core/os.h\"\r\n\r\nusing namespace wwiv::os;\r\n\r\nTEST(GetRandomNumberTest, Basic) {\r\n  auto sum = 0;\r\n  for (auto i=0; i < 100; i++) {\r\n    sum += random_number(1000);\r\n  }\r\n  ASSERT_NE(0, sum) << \"Sum should not be zero\";\r\n}\r\n"
  },
  {
    "path": "bbs/xfer.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/xfer.h\"\n\n#include \"bbs/archivers.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/dropfile.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/listplus.h\"\n#include \"bbs/stuffin.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/tag.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/arc.h\"\n#include \"sdk/files/files.h\"\n\n#include <string>\n#include <vector>\n\nusing wwiv::sdk::files::FileName;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nint foundany;\ndaten_t this_date;\n\n/**\n * returns true if everything is ok, false if the file\n */\nbool check_ul_event(int directory_num, uploadsrec * u) {\n  if (a()->upload_cmd.empty()) {\n    return true;\n  }\n  const auto comport = std::to_string(a()->sess().incom() ? a()->primary_port() : 0);\n  const auto& d = a()->dirs()[directory_num];\n  const auto dir_path = File::absolute(a()->bbspath(), d.path);\n  wwiv::bbs::CommandLine cl(a()->upload_cmd);\n  cl.args(create_chain_file(), dir_path.string(), FileName(u->filename).unaligned_filename(),\n          comport);\n  ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_ULCHK));\n\n  if (const auto file = FilePath(dir_path, FileName(u->filename)); !File::Exists(file)) {\n    sysoplog(fmt::format(\"File \\\"{}\\\" to {} deleted by UL event.\", u->filename, a()->dirs()[directory_num].name));\n    bout.print(\"{} was deleted by the upload event.\\r\\n\", u->filename);\n    return false;\n  }\n  return true;\n}\n\nstatic const std::vector<std::string> device_names = {\n  \"KBD$\", \"PRN\", \"COM1\", \"COM2\", \"COM3\", \"COM4\", \"COM5\", \"COM6\", \"COM7\",\n  \"COM8\", \"LPT1\", \"LPT2\", \"LPT3\", \"CLOCK$\", \"SCREEN$\", \"POINTER$\", \"MOUSE$\"\n};\n\nbool okfn(const std::string& filename) {\n  if (filename.empty()) {\n    return false;\n  }\n\n  if (const auto len = filename.length(); len == 0) {\n    return false;\n  }\n  if (filename[0] == '-' || filename[0] == ' ' || filename[0] == '.' || filename[0] == '@') {\n    return false;\n  }\n  for (auto c : filename) {\n    const unsigned char ch = c;\n    if (ch == ' '  || ch == '/' || ch == '\\\\' || ch == ':'  ||\n        ch == '>'  || ch == '<' || ch == '|'  || ch == '+'  ||\n        ch == ','  || ch == ';' || ch == '^'  || ch == '\\\"' ||\n        ch == '\\'' || ch == '`' || ch > 126) {\n      return false;\n    }\n  }\n\n\n  for (const auto& device : device_names) {\n    if (const auto deviceLen = device.length();\n        filename.length() >= deviceLen && filename.substr(0, deviceLen) == device) {\n      if (filename[deviceLen] == '\\0' || filename[deviceLen] == '.' || deviceLen == 8) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nvoid print_devices() {\n  for (const auto& device : device_names) {\n    bout.pl(device);\n  }\n}\n\n\nint list_arc_out(const std::string& file_name, const std::string& dir) {\n  std::string name_to_delete;\n\n  if (a()->dirs()[a()->current_user_dir().subnum].mask & mask_cdrom) {\n    if (const auto full_pathname = FilePath(a()->sess().dirs().temp_directory(), file_name); !File::Exists(full_pathname)) {\n      const auto name_in_dir = FilePath(dir, file_name);\n      File::Copy(name_in_dir, full_pathname);\n      name_to_delete = full_pathname.string();\n    }\n  }\n  const auto full_pathname = FilePath(dir, file_name);\n  auto opt_cmd = get_arc_cmd(full_pathname.string(), arc_command_type_t::list, \"\");\n  if (!okfn(file_name)) {\n    opt_cmd.reset();\n  }\n\n  auto return_code = 0;\n  if (File::Exists(full_pathname) && opt_cmd.has_value()) {\n    bout.print(\"\\r\\n\\nArchive listing for {}\\r\\n\\n\", file_name);\n    if (const auto cmd = opt_cmd.value(); cmd.internal) {\n      auto o = wwiv::sdk::files::list_archive(full_pathname);\n      if (!o) {\n        bout.print(\"Unable to view archive: '{}'.\", full_pathname.string());\n        return 1;\n      }\n      const auto& files = o.value();\n      bout.pl(\"|#2CompSize     Size   Date   Time  CRC-32   File Name\");\n      bout.pl(\"|#7======== -------- ======== ----- ======== ----------------------------------\");\n      int line_num = 0;\n      for (const auto& f : files) {\n        const auto dt = DateTime::from_time_t(f.dt);\n        auto d = dt.to_string(\"%m/%d/%y\");\n        auto t = dt.to_string(\"%I:%M\");\n        auto line = fmt::format(\"{:>8} {:>8} {:<8} {:<5} {:>08x} {}\", f.compress_size,\n                                f.uncompress_size, d, t, f.crc32, f.filename);\n        bout.print(\"{}{}\\r\\n\", (++line_num % 2) ? \"|#9\" : \"|#1\", line);\n      }\n    } else {\n      wwiv::bbs::CommandLine cl(cmd.cmd);\n      return_code = ExecuteExternalProgram(cl, a()->spawn_option(SPAWNOPT_ARCH_L));\n    }\n  } else {\n    bout.print(\"\\r\\nUnknown archive: {}\\r\\n\", file_name);\n  }\n  bout.nl();\n\n  if (!name_to_delete.empty()) {\n    File::Remove(name_to_delete);\n  }\n  return return_code;\n}\n\nbool ratio_ok() {\n  if (!a()->user()->exempt_ratio()) {\n    if (a()->config()->req_ratio() > 0.0001f && a()->user()->ratio() < a()->config()->req_ratio()) {\n      bout.cls();\n      bout.nl();\n      bout.printf(\n          \"Your up/download ratio is %-5.3f.  You need a ratio of %-5.3f to download.\\r\\n\\n\",\n          a()->user()->ratio(), a()->config()->req_ratio());\n      return false;\n    }\n  }\n  if (!a()->user()->exempt_post()) {\n    if (a()->config()->post_to_call_ratio() > 0.0001f &&\n        post_ratio() < a()->config()->post_to_call_ratio()) {\n      bout.nl();\n      bout.printf(\"%s %-5.3f.  %s %-5.3f %s.\\r\\n\\n\", \"Your post/call ratio is\",\n                           post_ratio(), \"You need a ratio of\", a()->config()->post_to_call_ratio(),\n                           \"to download.\");\n      return false;\n    }\n  }\n  return true;\n}\n\nbool dcs() {\n  return cs() || a()->user()->dsl() >= 100;\n}\n\nvoid dliscan1(int directory_num) {\n  dliscan1(a()->dirs()[directory_num]);\n}\n\nvoid dliscan1(const wwiv::sdk::files::directory_t& dir) {\n  if (!a()->fileapi()->Exist(dir.filename)) {\n    if (!a()->fileapi()->Create(dir.filename)) {\n      LOG(ERROR) << \"Failed to create file area: \" << dir.filename;\n    }\n  }\n\n  a()->set_current_file_area(a()->fileapi()->Open(dir));\n  this_date = a()->current_file_area()->header().daten();\n}\n\nvoid dliscan() {\n  dliscan1(a()->dirs()[a()->current_user_dir().subnum]);\n}\n\nstd::string aligns(const std::string& file_name) {\n  return wwiv::sdk::files::align(file_name);\n}\n\nvoid printinfo(uploadsrec* u, bool *abort) {\n  bool next;\n\n  {\n    tagrec_t t{};\n    t.u = *u;\n    const auto subnum = a()->current_user_dir().subnum;\n    t.directory = subnum;\n    t.dir_mask = a()->dirs()[subnum].mask;\n    a()->filelist.emplace_back(t);\n    const FileName fn(u->filename);\n    const auto s = fmt::format(\"\\r|#{}{:<2} |#1{} \", a()->batch().contains_file(u->filename) ? 6 : 0,\n                               size_int(a()->filelist), fn.aligned_filename());\n    bout.outstr(s, abort, &next);\n  }\n\n  auto size = humanize(u->numbytes);\n\n  if (const auto& dir = a()->dirs()[a()->udir[a()->current_user_dir_num()].subnum];\n      !(dir.mask & mask_cdrom)) {\n    if (const auto dir_path = File::absolute(a()->bbspath(), dir.path);\n        !File::Exists(FilePath(dir_path, FileName(u->filename)))) {\n      size = \"N/A\";\n    }\n  }\n  const auto desc = trim_to_size_ignore_colors(u->description, a()->user()->screen_width() - 28);\n  const auto s = fmt::format(\"|#2{:>5} {:>4} |#1{}\", size, u->numdloads, desc);\n  bout.bpla(s, abort);\n\n  if (*abort) {\n    a()->filelist.clear();\n  }\n}\n\nvoid printtitle(bool *abort) {\n  bout.ansic(FRAME_COLOR);\n  bout.print(\"\\r{}\\r\\n\", std::string(78, '-'));\n\n  bin.checka(abort);\n  bout.ansic(2);\n  bout.print(\"\\r{} - #{}, {} files.\\r\\n\", a()->dirs()[a()->current_user_dir().subnum].name,\n             a()->current_user_dir().keys, a()->current_file_area()->number_of_files());\n\n  bout.ansic(FRAME_COLOR);\n  bout.print(\"\\r{}\\r\\n\", std::string(78, '-'));\n}\nstd::string file_mask() {\n  return file_mask(\"|#2File mask: \");\n}\n\nstd::string file_mask(const std::string& prompt) {\n  if (!prompt.empty()) {\n    bout.nl();\n    bout.outstr(prompt);\n  }\n  auto s = bin.input(12);\n  if (s.empty()) {\n    s = \"*.*\";\n  }\n  if (!contains(s, '.')) {\n    s += \".*\";\n  }\n  bout.nl();\n  return aligns(s);\n}\n\nvoid listfiles() {\n  if (a()->current_user_dir().subnum < 0 || a()->udir.empty()) {\n    // We don't have any current directory, can not list files.\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n\n  if (okansi() && a()->user()->data.lp_options & cfl_enable ) {\n    listfiles_plus(LP_LIST_DIR);\n    return;\n  }\n\n  dliscan();\n  const auto filemask = file_mask();\n  auto need_title = true;\n  bout.clear_lines_listed();\n\n  auto* area = a()->current_file_area();\n  auto abort = false;\n  for (auto i = 1; i <= area->number_of_files() && !abort && !a()->sess().hangup(); i++) {\n    if (auto f = area->ReadFile(i);\n        wwiv::sdk::files::aligned_wildcard_match(filemask, f.aligned_filename())) {\n      if (need_title) {\n        printtitle(&abort);\n        need_title = false;\n      }\n\n      printinfo(&f.u(), &abort);\n\n      // Moved to here from bputch.cpp\n      if (bout.lines_listed() >= a()->sess().num_screen_lines() - 3) {\n        if (!a()->filelist.empty()) {\n          tag_files(need_title);\n          bout.clear_lines_listed();\n        }\n      }\n    } else if (bin.bkbhit()) {\n      bin.checka(&abort);\n    }\n  }\n  endlist(1);\n}\n\nvoid nscandir(uint16_t nDirNum, bool& need_title, bool *abort) {\n  if (a()->udir.empty()) {\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n  const auto old_cur_dir = a()->current_user_dir_num();\n  a()->set_current_user_dir_num(nDirNum);\n  dliscan();\n  if (this_date >= a()->sess().nscandate()) {\n    if (okansi() && a()->user()->data.lp_options & cfl_enable) {\n      *abort = listfiles_plus(LP_NSCAN_DIR) ? 1 : 0;\n      a()->set_current_user_dir_num(old_cur_dir);\n      return;\n    }\n    auto* area = a()->current_file_area();\n    for (auto i = 1; i <= a()->current_file_area()->number_of_files() && !*abort && !a()->sess().hangup();\n         i++) {\n      a()->CheckForHangup();\n      if (auto f = area->ReadFile(i); f.u().daten >= a()->sess().nscandate()) {\n        if (need_title) {\n          if (bout.lines_listed() >= a()->sess().num_screen_lines() - 7 && !a()->filelist.empty()) {\n            tag_files(need_title);\n          }\n          if (need_title) {\n            printtitle(abort);\n            need_title = false;\n          }\n        }\n\n        printinfo(&f.u(), abort);\n      } else if (bin.bkbhit()) {\n        bin.checka(abort);\n      }\n    }\n  }\n  a()->set_current_user_dir_num(old_cur_dir);\n}\n\nvoid nscanall() {\n  a()->sess().scanned_files(true);\n\n  if (a()->udir.empty()) {\n    return;\n  }\n  bool scan_all_confs = false;\n\n  if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n    bout.nl();\n    bout.outstr(\"|#5All conferences? \");\n    scan_all_confs = bin.yesno();\n    bout.nl();\n    if (scan_all_confs) {\n      tmp_disable_conf(true);\n    }\n  }\n  if (okansi() && a()->user()->data.lp_options & cfl_enable) {\n    const auto save_dir = a()->current_user_dir_num();\n    listfiles_plus(LP_NSCAN_NSCAN);\n    if (scan_all_confs) {\n      tmp_disable_conf(false);\n    }\n    a()->set_current_user_dir_num(save_dir);\n    return;\n  }\n  bool abort = false;\n  int count = 0;\n  int color = 3;\n  bout.outstr(\"\\r|#2Searching \");\n  for (uint16_t i = 0; i < size_int(a()->udir) && !abort; i++) {\n    count++;\n    bout.ansic(color);\n    bout.outstr(\".\");\n    if (count >= NUM_DOTS) {\n      bout.outstr(\"\\r|#2Searching \");\n      color++;\n      count = 0;\n      if (color == 4) {\n        color++;\n      }\n      if (color == 10) {\n        color = 0;\n      }\n    }\n    int nSubNum = a()->udir[i].subnum;\n    if (a()->sess().qsc_n[nSubNum / 32] & (1L << (nSubNum % 32))) {\n      bool need_title = true;\n      nscandir(i, need_title, &abort);\n    }\n  }\n  endlist(2);\n  if (scan_all_confs) {\n    tmp_disable_conf(false);\n  }\n}\n\nvoid searchall() {\n  if (a()->udir.empty()) {\n    bout.pl(\"|#6No directories available.\");\n    return;\n  }\n  if (okansi() && a()->user()->data.lp_options & cfl_enable ) {\n    listfiles_plus(LP_SEARCH_ALL);\n    return;\n  }\n\n  bool bScanAllConfs = false;\n  if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n    bout.nl();\n    bout.outstr(\"|#5All conferences? \");\n    bScanAllConfs = bin.yesno();\n    bout.nl();\n    if (bScanAllConfs) {\n      tmp_disable_conf(true);\n    }\n  }\n  auto abort = false;\n  const auto old_cur_dir = a()->current_user_dir_num();\n  bout.nl(2);\n  bout.outstr(\"Search all directories.\\r\\n\");\n  const auto filemask = file_mask();\n  bout.nl();\n  bout.outstr(\"|#2Searching \");\n  bout.clear_lines_listed();\n  int count = 0;\n  int color = 3;\n  for (auto i = 0; i < size_int(a()->udir) && !abort && !a()->sess().hangup(); i++) {\n    const int nDirNum = a()->udir[i].subnum;\n    // ReSharper disable once CppInitializedValueIsAlwaysRewritten\n    bool bIsDirMarked =  a()->sess().qsc_n[nDirNum / 32] & (1L << (nDirNum % 32));\n    bIsDirMarked = true;\n    // remove bIsDirMarked=true to search only marked directories\n    if (bIsDirMarked) {\n      count++;\n      bout.ansic(color);\n      bout.outstr(\".\");\n      if (count >= NUM_DOTS) {\n        bout.outstr(\"\\r|#2Searching \");\n        color++;\n        count = 0;\n        if (color == 4) {\n          color++;\n        }\n        if (color == 10) {\n          color = 0;\n        }\n      }\n      a()->set_current_user_dir_num(i);\n      dliscan();\n      bool need_title = true;\n      auto* area = a()->current_file_area();\n      for (int i1 = 1; i1 <= a()->current_file_area()->number_of_files() && !abort && !a()->sess().hangup();\n           i1++) {\n        if (auto f = area->ReadFile(i1);\n            wwiv::sdk::files::aligned_wildcard_match(filemask, f.aligned_filename())) {\n          if (need_title) {\n            if (bout.lines_listed() >= a()->sess().num_screen_lines() - 7 && !a()->filelist.empty()) {\n              tag_files(need_title);\n            }\n            if (need_title) {\n              printtitle(&abort);\n              need_title = false;\n            }\n          }\n          printinfo(&f.u(), &abort);\n        } else if (bin.bkbhit()) {\n          bin.checka(&abort);\n        }\n      }\n    }\n  }\n  a()->set_current_user_dir_num(old_cur_dir);\n  endlist(1);\n  if (bScanAllConfs) {\n    tmp_disable_conf(false);\n  }\n}\n\nint recno(const std::string& file_mask) {\n  return nrecno(file_mask, 0);\n}\n\nint nrecno(const std::string& file_mask, int start_recno) {\n  auto* area = a()->current_file_area();\n  return !area ? -1 : area->SearchFile(file_mask, start_recno + 1).value_or(-1);\n}\n\nstatic long xfer_time_in_seconds(long b) {\n  if (a()->modem_speed_ == 0) {\n    return 0;\n  }\n  return (b + 127) * 10 / a()->modem_speed_;\n}\n\nint printfileinfo(const uploadsrec* u, const wwiv::sdk::files::directory_t& dir) {\n  const auto d = xfer_time_in_seconds(u->numbytes);\n  bout.print(\"|#9Filename:    |#2{}\\r\\n\", FileName(u->filename).unaligned_filename());\n  bout.print(\"|#9Description: |#2{}\\r\\n\", u->description);\n  bout.print(\"|#9File size:   |#2{}\\r\\n\", humanize(u->numbytes));\n  bout.print(\"|#9Apprx. time: |#2{}\\r\\n\", ctim(d));\n  bout.print(\"|#9Uploaded on: |#2{}\\r\\n\", u->date);\n  if (u->actualdate[2] == '/' && u->actualdate[5] == '/') {\n    bout.print(\"|#9File date:  |#2 {}\\r\\n\", u->actualdate);\n  }\n  bout.print(\"|#9Uploaded by: |#2{}\\r\\n\", u->upby);\n  bout.print(\"|#9Times D/L'd: |#2{}\\r\\n\", u->numdloads);\n  bout.nl();\n  if (u->mask & mask_extended) {\n    bout.outstr(\"|#9Extended Description: \\r\\n\");\n    print_extended(u->filename, 255, -1, wwiv::sdk::Color::YELLOW, nullptr);\n\n  }\n\n  if (dir.mask & mask_cdrom) {\n    bout.nl();\n    bout.outstr(\"|#3CD ROM DRIVE\\r\\n\");\n  } else {\n    if (const auto dir_path = File::absolute(a()->bbspath(), dir.path);\n        !File::Exists(FilePath(dir_path, FileName(u->filename)))) {\n      bout.outstr(\"\\r\\n-=>FILE NOT THERE<=-\\r\\n\\n\");\n      return -1;\n    }\n  }\n\n  return nsl() >= d ? 1 : 0;\n}\n\nvoid remlist(const std::string& file_name) {\n  const auto fn = aligns(file_name);\n\n  if (a()->filelist.empty()) {\n    return;\n  }\n  for (auto b = a()->filelist.begin(); b != a()->filelist.end(); ++b) {\n    if (const auto list_fn = aligns(b->u.filename); fn == list_fn) {\n      a()->filelist.erase(b);\n      return;\n    }\n  }\n}\n"
  },
  {
    "path": "bbs/xfer.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_XFER_H\n#define INCLUDED_BBS_XFER_H\n\n#include \"core/file.h\"\n#include <string>\n\nstruct uploadsrec;\n\nnamespace wwiv::sdk::files {\nstruct directory_t;\n}\n\n/** return true if file_name is in the queue */\nbool check_ul_event(int directory_num, uploadsrec* upload_record);\nbool okfn(const std::string& filename);\nvoid print_devices();\nint list_arc_out(const std::string& file_name, const std::string& dir);\nbool ratio_ok();\nbool dcs();\nvoid dliscan1(int directory_num);\nvoid dliscan1(const wwiv::sdk::files::directory_t& dir);\nvoid dliscan();\nstd::string aligns(const std::string& file_name);\nvoid printinfo(uploadsrec* u, bool* abort);\nvoid printtitle(bool* abort);\nstd::string file_mask(const std::string& prompt);\nstd::string file_mask();\nvoid listfiles();\nvoid nscandir(uint16_t nDirNum, bool& need_title, bool* abort);\nvoid nscanall();\nvoid searchall();\nint recno(const std::string& file_mask);\nint nrecno(const std::string& file_mask, int start_recno);\nint printfileinfo(const uploadsrec* u, const wwiv::sdk::files::directory_t& dir);\nvoid remlist(const std::string& file_name);\n\n#endif \n"
  },
  {
    "path": "bbs/xfer_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2007-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"bbs/xfer.h\"\r\n\r\n#include \"gtest/gtest.h\"\r\n#include <string>\r\n\r\nTEST(XferTest, Okfn) {\r\n  EXPECT_TRUE(!okfn(\"\"));\r\n  EXPECT_TRUE(okfn(\"foo\"));\r\n  EXPECT_TRUE(okfn(\"foo.bar\"));\r\n  EXPECT_TRUE(!okfn(\"/foo\"));\r\n  EXPECT_TRUE(!okfn(\"<foo\"));\r\n  EXPECT_TRUE(!okfn(\">foo\"));\r\n  EXPECT_TRUE(!okfn(\"`foo\"));\r\n  EXPECT_TRUE(!okfn(\"-foo\"));\r\n  EXPECT_TRUE(!okfn(\" foo\"));\r\n  EXPECT_TRUE(!okfn(\"@foo\"));\r\n  EXPECT_TRUE(!okfn(\".foo\"));\r\n  EXPECT_TRUE(!okfn(\"COM1\"));\r\n  EXPECT_TRUE(!okfn(\"PRN\"));\r\n  EXPECT_TRUE(!okfn(\"KBD$\"));\r\n  EXPECT_TRUE(okfn(\"COM1A\"));\r\n}\r\n"
  },
  {
    "path": "bbs/xferovl.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/xferovl.h\"\n#include \"bbs/application.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/defaults.h\"\n#include \"bbs/dirlist.h\"\n#include \"bbs/listplus.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/tag.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl1.h\"\n#include \"common/com.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/findfiles.h\"\n#include \"core/numbers.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/status.h\"\n#include \"sdk/files/allow.h\"\n#include \"sdk/files/files.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid move_file() {\n  int d1 = 0;\n\n  bool ok = false;\n  bout.nl();\n  const auto fm = file_mask(\"|#2Filename to move: \");\n  dliscan();\n  int nCurRecNum = recno(fm);\n  if (nCurRecNum < 0) {\n    bout.outstr(\"\\r\\nFile not found.\\r\\n\");\n    return;\n  }\n  bool done = false;\n  tmp_disable_conf(true);\n\n  while (!a()->sess().hangup() && nCurRecNum > 0 && !done) {\n    int nCurrentPos = nCurRecNum;\n    auto f = a()->current_file_area()->ReadFile(nCurRecNum);\n    const auto dir = a()->dirs()[a()->current_user_dir().subnum];\n    bout.nl();\n    printfileinfo(&f.u(), dir);\n    bout.nl();\n    bout.outstr(\"|#5Move this (Y/N/Q)? \");\n    const auto ch = bin.ynq();\n    std::filesystem::path src_fn;\n    if (ch == 'Q') {\n      done = true;\n    } else if (ch == 'Y') {\n      src_fn = FilePath(dir.path, f);\n      std::string ss;\n      do {\n        bout.nl(2);\n        bout.outstr(\"|#2To which directory? \");\n        ss = mmkey(MMKeyAreaType::dirs);\n        if (ss[0] == '?') {\n          dirlist(1);\n          dliscan();\n        }\n      }\n      while (!a()->sess().hangup() && ss[0] == '?');\n      d1 = -1;\n      if (!ss.empty()) {\n        for (auto i1 = 0; i1 < wwiv::stl::size_int(a()->udir); i1++) {\n          if (ss == a()->udir[i1].keys) {\n            d1 = i1;\n          }\n        }\n      }\n      if (d1 != -1) {\n        ok = true;\n        d1 = a()->udir[d1].subnum;\n        dliscan1(d1);\n        if (recno(f.aligned_filename()) > 0) {\n          ok = false;\n          bout.outstr(\"\\r\\nFilename already in use in that directory.\\r\\n\");\n        }\n        if (a()->current_file_area()->number_of_files() >= a()->dirs()[d1].maxfiles) {\n          ok = false;\n          bout.outstr(\"\\r\\nToo many files in that directory.\\r\\n\");\n        }\n        if (File::freespace_for_path(a()->dirs()[d1].path) <\n            static_cast<long>(f.numbytes() / 1024L) + 3) {\n          ok = false;\n          bout.outstr(\"\\r\\nNot enough disk space to move it.\\r\\n\");\n        }\n        dliscan();\n      } else {\n        ok = false;\n      }\n    } else {\n      ok = false;\n    }\n    if (ok && !done) {\n      bout.outstr(\"|#5Reset upload time for file? \");\n      if (bin.yesno()) {\n        f.set_date(DateTime::now());\n      }\n      --nCurrentPos;\n      std::string ss = a()->current_file_area()->ReadExtendedDescriptionAsString(f).value_or(\"\");\n      if (a()->current_file_area()->DeleteFile(nCurRecNum)) {\n        a()->current_file_area()->Save();\n      }\n\n      dliscan1(d1);\n      auto dest_fn = FilePath(a()->dirs()[d1].path, f);\n      if (a()->current_file_area()->AddFile(f, ss)) {\n        a()->current_file_area()->Save();\n      }\n      if (src_fn != dest_fn && File::Exists(src_fn)) {\n        File::Rename(src_fn, dest_fn);\n      }\n      bout.outstr(\"\\r\\nFile moved.\\r\\n\");\n    }\n    dliscan();\n    nCurRecNum = nrecno(fm, nCurrentPos);\n  }\n\n  tmp_disable_conf(false);\n}\n\nstatic files::FileAreaSortType sort_type_from_wwiv_type(int t) {\n  switch (t) {\n  case 0:\n    return files::FileAreaSortType::FILENAME_ASC;\n  case 1:\n    return files::FileAreaSortType::DATE_ASC;\n  case 2:\n    return files::FileAreaSortType::DATE_DESC;\n  default:\n    return files::FileAreaSortType::FILENAME_ASC;\n  }\n}\n\nvoid sortdir(int directory_num, int type) {\n  dliscan1(directory_num);\n\n  if (a()->current_file_area()->Sort(sort_type_from_wwiv_type(type))) {\n    a()->current_file_area()->Save();\n  }\n}\n\nvoid sort_all(int type) {\n  tmp_disable_conf(true);\n  for (auto i = 0; i < wwiv::stl::size_int(a()->udir) && !bout.localIO()->KeyPressed(); i++) {\n    bout.print(\"\\r\\n|#1Sorting {}\\r\\n\", a()->dirs()[a()->udir[i].subnum].name);\n    sortdir(i, type);\n  }\n  tmp_disable_conf(false);\n}\n\nvoid rename_file() {\n  bout.nl(2);\n  bout.outstr(\"|#2File to rename: \");\n  auto s = bin.input(12);\n  if (s.empty()) {\n    return;\n  }\n  if (strchr(s.c_str(), '.') == nullptr) {\n    s += \".*\";\n  }\n  s = aligns(s);\n  dliscan();\n  bout.nl();\n  const auto original_filename = s;\n  int nRecNum = recno(s);\n  while (nRecNum > 0 && !a()->sess().hangup()) {\n    int nCurRecNum = nRecNum;\n    auto f = a()->current_file_area()->ReadFile(nRecNum);\n    const auto& dir = a()->dirs()[a()->current_user_dir().subnum];\n    bout.nl();\n    printfileinfo(&f.u(), dir);\n    bout.nl();\n    bout.outstr(\"|#5Change info for this file (Y/N/Q)? \");\n    const char ch = bin.ynq();\n    if (ch == 'Q') {\n      break;\n    }\n    if (ch == 'N') {\n      nRecNum = nrecno(original_filename, nCurRecNum);\n      continue;\n    }\n    bout.nl();\n    bout.outstr(\"|#2New filename? \");\n    s = bin.input(12);\n    if (!okfn(s)) {\n      s.clear();\n    }\n    if (!s.empty()) {\n      s = aligns(s);\n      if (!iequals(s, \"        .   \")) {\n        const std::string p = dir.path;\n        auto dest_fn = FilePath(p, s);\n        if (File::Exists(dest_fn)) {\n          bout.outstr(\"Filename already in use; not changed.\\r\\n\");\n        } else {\n          File::Rename(FilePath(p, f), dest_fn);\n          if (File::Exists(dest_fn)) {\n            auto* area = a()->current_file_area();\n            auto ss = area->ReadExtendedDescriptionAsString(f).value_or(\"\");\n            if (!ss.empty()) {\n              area->DeleteExtendedDescription(f, nCurRecNum);\n              area->AddExtendedDescription(s, ss);\n              f.set_extended_description(true);\n            }\n            f.set_filename(s);\n          } else {\n            bout.outstr(\"Bad filename.\\r\\n\");\n          }\n        }\n      }\n    }\n    bout.outstr(\"\\r\\nNew description:\\r\\n|#2: \");\n    auto* area = a()->current_file_area();\n    auto desc = bin.input_text(58);\n    if (!desc.empty()) {\n      f.set_description(desc);\n    }\n    auto ss = area->ReadExtendedDescriptionAsString(f).value_or(\"\");\n    bout.nl(2);\n    bout.outstr(\"|#5Modify extended description? \");\n    if (bin.yesno()) {\n      bout.nl();\n      if (!ss.empty()) {\n        bout.outstr(\"|#5Delete it? \");\n        if (bin.yesno()) {\n          area->DeleteExtendedDescription(f, nCurRecNum);\n          f.set_extended_description(false);\n        } else {\n          f.set_extended_description(true);\n          modify_extended_description(&ss, a()->dirs()[a()->current_user_dir().subnum].name);\n          if (!ss.empty()) {\n            area->DeleteExtendedDescription(f, nCurRecNum);\n            area->AddExtendedDescription(f, nCurRecNum, ss);\n          }\n        }\n      } else {\n        modify_extended_description(&ss, a()->dirs()[a()->current_user_dir().subnum].name);\n        if (!ss.empty()) {\n          area->AddExtendedDescription(f, nCurRecNum, ss);\n          f.set_extended_description(true);\n        } else {\n          f.set_extended_description(false);\n        }\n      }\n    } else if (!ss.empty()) {\n      f.set_extended_description(true);\n    } else {\n      f.set_extended_description(false);\n    }\n    if (a()->current_file_area()->UpdateFile(f, nRecNum)) {\n      a()->current_file_area()->Save();\n    }\n    nRecNum = nrecno(original_filename, nCurRecNum);\n  }\n}\n\nstatic bool upload_file(const std::string& file_name, uint16_t directory_num,\n                        const std::string& description) {\n  auto d = a()->dirs()[directory_num];\n  const auto temp_filename = aligns(file_name);\n  files::FileRecord f{};\n  f.set_filename(temp_filename);\n  f.u().ownerusr = static_cast<uint16_t>(a()->sess().user_num());\n  if (!(d.mask & mask_cdrom) && !check_ul_event(directory_num, &f.u())) {\n    bout.print(\"{} was deleted by upload event.\\r\\n\", file_name);\n  } else {\n    const auto unaligned_filename = files::unalign(file_name);\n    const auto full_path = FilePath(d.path, unaligned_filename);\n\n    File fileUpload(full_path);\n    if (!fileUpload.Open(File::modeBinary | File::modeReadOnly)) {\n      if (!description.empty()) {\n        bout.print(\"ERR: {}:{}\\r\\n\", unaligned_filename, description);\n      } else {\n        bout.print(\"|#1{} does not exist.\\r\\n\", unaligned_filename);\n      }\n      return true;\n    }\n    const auto fs = fileUpload.length();\n    f.set_numbytes(fs);\n    fileUpload.Close();\n    to_char_array(f.u().upby, a()->user()->name_and_number());\n    f.set_date(DateTime::now());\n\n    auto t = DateTime::from_time_t(File::last_write_time(full_path));\n    f.set_actual_date(t);\n\n    if (d.mask & mask_PD) {\n      d.mask = mask_PD;\n    }\n    bout.nl();\n\n    bout.print(\"|#9File name   : |#2{}\\r\\n\", f);\n    bout.print(\"|#9File size   : |#2{}\\r\\n\", humanize(f.numbytes()));\n    if (!description.empty()) {\n      f.set_description(description);\n      bout.print(\"|#1 Description: {}\\r\\n\", f.description());\n    } else {\n      bout.outstr(\"|#9Enter a description for this file.\\r\\n|#7: \");\n      auto desc = bin.input_text(58);\n      f.set_description(desc);\n    }\n    bout.nl();\n    if (f.description().empty()) {\n      return false;\n    }\n    get_file_idz(f, a()->dirs()[directory_num]);\n    a()->user()->increment_uploaded();\n    if (!(d.mask & mask_cdrom)) {\n      add_to_file_database(f);\n    }\n    a()->user()->set_uk(a()->user()->uk() + bytes_to_k(fs));\n    f.set_date(DateTime::now());\n    if (a()->current_file_area()->AddFile(f)) {\n      a()->current_file_area()->Save();\n    }\n    a()->status_manager()->Run([&](Status& status) {\n      status.increment_uploads_today();\n      status.increment_filechanged(Status::file_change_upload);\n    });\n    sysoplog(fmt::format(\"+ '{}' uploaded on \", f, d.name));\n    a()->UpdateTopScreen();\n  }\n  return true;\n}\n\nbool maybe_upload(const std::string& file_name, int directory_num, const std::string& description) {\n  auto abort = false;\n  const auto i = recno(aligns(file_name));\n\n  if (i == -1) {\n    if (!is_uploadable(file_name) && dcs()) {\n      bout.print(\"{:<12}: |#5In filename database - add anyway? \", file_name);\n      const auto ch = bin.ynq();\n      const auto key_quit = bout.lang().value(\"KEY_QUIT\", \"Q\").front();\n      if (ch == key_quit) {\n        return false;\n      }\n      if (ch == YesNoString(false)[0]) {\n        bout.outstr(\"|#5Delete it? \");\n        if (bin.yesno()) {\n          File::Remove(FilePath(a()->dirs()[directory_num].path, file_name));\n        }\n        bout.nl();\n        return true;\n      }\n    }\n    if (!upload_file(file_name, a()->udir[directory_num].subnum, description)) {\n      return false;\n    }\n  } else {\n    auto f = a()->current_file_area()->ReadFile(i);\n    const auto ocd = a()->current_user_dir_num();\n    a()->set_current_user_dir_num(directory_num);\n    printinfo(&f.u(), &abort);\n    a()->set_current_user_dir_num(ocd);\n    if (abort) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/* This assumes the file holds listings of files, one per line, to be\n * uploaded.  The first word (delimited by space/tab) must be the filename.\n * after the filename are optional tab/space separated words (such as file\n * size or date/time).  After the optional words is the description, which\n * is from that position to the end of the line.  the \"type\" parameter gives\n * the number of optional words between the filename and description.\n * the optional words (size, date/time) are ignored completely.\n */\nvoid upload_files(const std::string& file_name, int directory_num, int type) {\n  char s[255], *fn1, *description = nullptr, *ext = nullptr;\n  bool abort = false;\n  bool ok = true;\n\n  std::string last_fn;\n  const auto& dir = a()->dirs()[a()->udir[directory_num].subnum];\n  dliscan1(dir);\n\n  auto file = std::make_unique<TextFile>(file_name, \"r\");\n  if (!file->IsOpen()) {\n    const auto default_fn = FilePath(dir.path, file_name);\n    file.reset(new TextFile(default_fn, \"r\"));\n  }\n  if (!file->IsOpen()) {\n    bout.print(\"{}: not found.\\r\\n\", file_name);\n  } else {\n    while (ok && file->ReadLine(s, 250)) {\n      if (s[0] < SPACE) {\n        continue;\n      }\n      if (s[0] == SPACE) {\n        if (!last_fn.empty()) {\n          if (!ext) {\n            ext = static_cast<char*>(BbsAllocA(4096L));\n            *ext = 0;\n          }\n          for (description = s; *description == ' ' || *description == '\\t'; description++)\n            ;\n          if (*description == '|') {\n            do {\n              description++;\n            }\n            while (*description == ' ' || *description == '\\t');\n          }\n          fn1 = strchr(description, '\\n');\n          if (fn1) {\n            *fn1 = 0;\n          }\n          strcat(ext, description);\n          strcat(ext, \"\\r\\n\");\n        }\n      } else {\n        int ok1 = 0;\n        fn1 = strtok(s, \" \\t\\n\");\n        if (fn1) {\n          ok1 = 1;\n          for (int i = 0; ok1 && (i < type); i++) {\n            if (strtok(nullptr, \" \\t\\n\") == nullptr) {\n              ok1 = 0;\n            }\n          }\n          if (ok1) {\n            description = strtok(nullptr, \"\\n\");\n            if (!description) {\n              ok1 = 0;\n            }\n          }\n        }\n        if (ok1) {\n          if (!last_fn.empty() && ext && *ext) {\n            auto f = a()->current_file_area()->ReadFile(1);\n            if (iequals(last_fn, f.aligned_filename())) {\n              add_to_file_database(f);\n              if (a()->current_file_area()->UpdateFile(f, 1, ext)) {\n                a()->current_file_area()->Save();\n              }\n            }\n            *ext = 0;\n          }\n          while (*description == ' ' || *description == '\\t') {\n            ++description;\n          }\n          ok = maybe_upload(fn1, directory_num, description);\n          bin.checka(&abort);\n          if (abort) {\n            ok = false;\n          }\n          if (ok) {\n            last_fn = fn1;\n            last_fn = aligns(last_fn);\n            if (ext) {\n              *ext = 0;\n            }\n          }\n        }\n      }\n    }\n    file->Close();\n    if (ok && last_fn[0] && ext && *ext) {\n      auto f = a()->current_file_area()->ReadFile(1);\n      if (iequals(last_fn, f.aligned_filename())) {\n        add_to_file_database(f);\n        if (a()->current_file_area()->UpdateFile(f, 1, ext)) {\n          a()->current_file_area()->Save();\n        }\n      }\n    }\n  }\n\n  if (ext) {\n    free(ext);\n  }\n}\n\n// returns false on abort\nbool uploadall(int directory_num) {\n  const auto& dir = a()->dirs()[a()->udir[directory_num].subnum];\n  dliscan1(dir);\n\n  FindFiles ff(FilePath(dir.path, \"*.*\"), FindFiles::FindFilesType::files);\n  auto aborted = false;\n  for (const auto& f : ff) {\n    aborted = bin.checka();\n    if (aborted || a()->sess().hangup() || a()->current_file_area()->number_of_files() >= dir.maxfiles) {\n      break;\n    }\n    if (!maybe_upload(f.name, directory_num, \"\")) {\n      break;\n    }\n  }\n  if (aborted) {\n    bout.outstr(\"|#6Aborted.\\r\\n\");\n    return false;\n  }\n  if (a()->current_file_area()->number_of_files() >= dir.maxfiles) {\n    bout.outstr(\"directory full.\\r\\n\");\n  }\n  return true;\n}\n\nvoid relist() {\n  if (a()->filelist.empty()) {\n    return;\n  }\n  auto abort = false;\n  auto next = true;\n\n  bout.cls();\n  bout.clear_lines_listed();\n  bout.pl(std::string(78, '-'));\n  for (size_t i = 0; i < a()->filelist.size() && !abort; i++) {\n    const auto& f = a()->filelist[i];\n    files::FileName fn(f.u.filename);\n    const auto s =\n        fmt::format(\"|#{}{:<2} |#1{}\", a()->batch().contains_file(f.u.filename) ? 6 : 0, i + 1,\n          fn.aligned_filename());\n    bout.outstr(s, &abort, &next);\n\n    const auto width = a()->user()->screen_width() - 28;\n    const auto bd = fmt::format(\" |#2{:>5} |#2{:>5} |#1{}\", \n      humanize(f.u.numbytes), f.u.numdloads, trim_to_size_ignore_colors(f.u.description, width));\n    bout.bpla(bd, &abort);\n  }\n  bout.ansic(FRAME_COLOR);\n  bout.outchr('\\r');\n  bout.pl(std::string(78, '-'));\n  bout.clear_lines_listed();\n}\n\n/*\n * Allows user to add or remove ALLOW.DAT entries.\n */\nvoid edit_database() {\n  do {\n    bout.nl();\n    bout.outstr(\"|#2A|#7)|#9 Add to ALLOW.DAT\\r\\n\");\n    bout.outstr(\"|#2R|#7)|#9 Remove from ALLOW.DAT\\r\\n\");\n    bout.outstr(\"|#2Q|#7)|#9 Quit\\r\\n\");\n    bout.nl();\n    bout.outstr(\"|#7Select: \");\n    const auto ch = onek(\"QAR\");\n    switch (ch) {\n    case 'A': {\n      bout.nl();\n      bout.outstr(\"|#2Filename: \");\n      auto s = bin.input(12, true);\n      if (!s.empty()) {\n        add_to_file_database(s);\n      }\n    } break;\n    case 'R': {\n      bout.nl();\n      bout.outstr(\"|#2Filename: \");\n      auto s = bin.input(12, true);\n      if (!s.empty()) {\n        remove_from_file_database(s);\n      }\n    } break;\n    case 'Q':\n      return;\n    }\n  }\n  while (!a()->sess().hangup());\n}\n\nvoid add_to_file_database(const std::string& file_name) {\n  files::Allow allow(*a()->config());\n  allow.Add(file_name);\n  allow.Save();\n}\n\nvoid add_to_file_database(const files::FileRecord& f) {\n  add_to_file_database(f.aligned_filename());\n}\n\nvoid remove_from_file_database(const std::string& file_name) {\n  files::Allow allow(*a()->config());\n  allow.Remove(file_name);\n  allow.Save();\n}\n\n/*\n * Returns 1 if file not found in filename database.\n */\n\nbool is_uploadable(const std::string& file_name) {\n  files::Allow allow(*a()->config());\n  return allow.IsAllowed(file_name);\n}\n\nstatic void l_config_nscan() {\n  bool abort = false;\n  bout.nl();\n  bout.outstr(\"|#9Directories to new-scan marked with '|#2*|#9'\\r\\n\\n\");\n  for (auto i = 0; i < wwiv::stl::size_int(a()->udir) && !abort; i++) {\n    const int i1 = a()->udir[i].subnum;\n    std::string s{\"  \"};\n    if (a()->sess().qsc_n[i1 / 32] & (1L << (i1 % 32))) {\n      s = \"* \";\n    }\n    bout.bpla(fmt::format(\"{}{}. {}\", s, a()->udir[i].keys, a()->dirs()[i1].name), &abort);\n  }\n  bout.nl(2);\n}\n\nstatic void config_nscan() {\n  char ch;\n  bool abort = false;\n\n  if (okansi()) {\n    config_scan_plus(NSCAN);\n    return;\n  }\n  bool done1 = false;\n  const int oc = a()->sess().current_user_dir_conf_num();\n  const int os = a()->current_user_dir().subnum;\n\n  do {\n    if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n      abort = false;\n      std::string s1 = \" \";\n      bout.nl();\n      bout.outstr(\"Select Conference: \\r\\n\\n\");\n      for (auto i = 0; i < wwiv::stl::size_int(a()->uconfdir) && !abort; i++) {\n        const auto& conf = a()->uconfdir[i];\n        const auto s2 = fmt::format(\"{}) {}\", conf.key.key(), stripcolors(conf.conf_name));\n        bout.bpla(s2, &abort);\n        s1.push_back(conf.key.key());\n      }\n      bout.nl();\n      bout.print(\" Select [{}, <space> to quit]: \", s1.substr(1));\n      ch = onek(s1);\n    } else {\n      ch = '-';\n    }\n    switch (ch) {\n    case ' ':\n      done1 = true;\n      break;\n    default:\n      if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n        const auto o = a()->all_confs().dirs_conf().try_conf(ch);\n        if (!o) {\n          break;\n        }\n        setuconf(a()->all_confs().dirs_conf(), o.value().key.key(), -1);\n      }\n      l_config_nscan();\n      bool done = false;\n      do {\n        bout.nl();\n        bout.outstr(\"|#9Enter directory number (|#1C=Clr All, Q=Quit, S=Set All|#9): |#0\");\n        auto s = mmkey(MMKeyAreaType::dirs);\n        if (s[0]) {\n          for (auto i = 0; i < wwiv::stl::size_int(a()->udir); i++) {\n            const int i1 = a()->udir[i].subnum;\n            if (s == a()->udir[i].keys) {\n              a()->sess().qsc_n[i1 / 32] ^= 1L << (i1 % 32);\n            }\n            if (s == \"S\") {\n              a()->sess().qsc_n[i1 / 32] |= 1L << (i1 % 32);\n            }\n            if (s == \"C\") {\n              a()->sess().qsc_n[i1 / 32] &= ~(1L << (i1 % 32));\n            }\n          }\n          if (s == \"Q\") {\n            done = true;\n          }\n          if (s == \"?\") {\n            l_config_nscan();\n          }\n        }\n      }\n      while (!done && !a()->sess().hangup());\n      break;\n    }\n    if (!ok_multiple_conf(a()->user(), a()->uconfdir)) {\n      done1 = true;\n    }\n  }\n  while (!done1 && !a()->sess().hangup());\n\n  if (okconf(a()->user())) {\n    setuconf(ConferenceType::CONF_DIRS, oc, os);\n  }\n}\n\nvoid xfer_defaults() {\n  char s[81];\n  int i;\n  bool done = false;\n\n  do {\n    bout.cls();\n    bout.outstr(\"|#7[|#21|#7]|#1 Set New-Scan Directories.\\r\\n\");\n    bout.print(\"|#7[|#22|#7]|#1 Set Default Protocol: |#7(|#2{}|#7).\\r\\n\",prot_name(a()->user()->default_protocol()));\n    bout.print(\"|#7[|#23|#7]|#1 New-Scan Transfer after Message Base: |#7(|#2{}|#7)\\r\\n\",\n               YesNoString(a()->user()->newscan_files()));\n    bout.print(\"|#7[|#24|#7]|#1 Number of lines of extended description to print: #|7[|#2{} line(s)|#7]|#1.\\r\\n\",\n               a()->user()->GetNumExtended());\n    if (okansi()) {\n      bout.print(\"|#7[|#2L|#7]|#1 ListPlus Enabled: |#7(|#2{}|#7)\\r\\n\", YesNoString(a()->user()->data.lp_options & cfl_enable));\n    }\n    std::string onek_options = \"Q12345L\";\n    if (a()->user()->data.lp_options & cfl_enable) {\n\tbout.print(\"|#7[|#2K|#7]|#1 Configure ListPlus\\r\\n\");\n\tonek_options.append(\"K\");\n    }\n\n    bout.outstr(\"|#7[|#2Q|#7]|#1 Quit.\\r\\n\\n\");\n    bout.outstr(\"|#5Which? \");\n    char ch = onek(onek_options);\n    switch (ch) {\n    case 'Q':\n      done = true;\n      break;\n    case '1':\n      config_nscan();\n      break;\n    case '2':\n      bout.nl(2);\n      bout.outstr(\"|#9Enter your default protocol, |#20|#9 for none.\\r\\n\\n\");\n      i = get_protocol(xfertype::xf_down);\n      if (i >= 0) {\n        a()->user()->default_protocol(i);\n      }\n      break;\n    case '3':\n      a()->user()->toggle_flag(User::nscanFileSystem);\n      break;\n    case '4':\n      bout.nl(2);\n      bout.outstr(\"|#9How many lines of an extended description\\r\\n\");\n      bout.print(\"|#9do you want to see when listing files (|#20-{}|#7)\\r\\n\", a()->max_extend_lines);\n      bout.print(\"|#9Current # lines: |#2{}\\r\\n\", a()->user()->GetNumExtended());\n      bout.outstr(\"|#7: \");\n      bin.input(s, 3);\n      if (s[0]) {\n        i = to_number<int>(s);\n        if ((i >= 0) && (i <= a()->max_extend_lines)) {\n          a()->user()->SetNumExtended(i);\n        }\n      }\n      break;\n    case 'L':\n      a()->user()->data.lp_options ^= cfl_enable;\n      break;\n    case 'K':\n      config_file_list();\n      break;\n    }\n  }\n  while (!done && !a()->sess().hangup());\n}\n\nvoid finddescription() {\n  if (okansi() && a()->user()->data.lp_options & cfl_enable ) {\n    listfiles_plus(LP_SEARCH_ALL);\n    return;\n  }\n\n  bout.nl();\n  bool ac = false;\n  if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n    bout.outstr(\"|#5All conferences? \");\n    ac = bin.yesno();\n    if (ac) {\n      tmp_disable_conf(true);\n    }\n  }\n  bout.outstr(\"\\r\\nFind description -\\r\\n\\n\");\n  bout.outstr(\"Enter string to search for in file description:\\r\\n:\");\n  const auto search_string = bin.input(58);\n  if (search_string.empty()) {\n    tmp_disable_conf(false);\n    return;\n  }\n  const auto ocd = a()->current_user_dir_num();\n  auto abort = false;\n  auto count = 0;\n  auto color = 3;\n  bout.outstr(\"\\r|#2Searching \");\n  bout.clear_lines_listed();\n  for (auto i = 0; i < wwiv::stl::size_int(a()->udir) && !abort && !a()->sess().hangup(); i++) {\n    const auto ii1 = a()->udir[i].subnum;\n    int pts;\n    auto need_title = true;\n    if (a()->sess().qsc_n[ii1 / 32] & (1L << (ii1 % 32))) {\n      pts = 1;\n    }\n    pts = 1;\n    // remove pts=1 to search only marked directories\n    if (pts && !abort) {\n      count++;\n      bout.ansic(color);\n      bout.outchr('.');\n      if (count == NUM_DOTS) {\n        bout.outstr(\"\\r|#2Searching \");\n        color++;\n        count = 0;\n        if (color == 4) {\n          color++;\n        }\n        if (color == 10) {\n          color = 0;\n        }\n      }\n      a()->set_current_user_dir_num(i);\n      dliscan();\n      for (auto i1 = 1;\n           i1 <= a()->current_file_area()->number_of_files() && !abort && !a()->sess().hangup(); i1++) {\n        auto f = a()->current_file_area()->ReadFile(i1);\n        auto desc = ToStringUpperCase(f.description());\n\n        if (desc.find(search_string) != std::string::npos) {\n          if (need_title) {\n            if (bout.lines_listed() >= a()->sess().num_screen_lines() - 7 && !a()->filelist.empty()) {\n              tag_files(need_title);\n            }\n            if (need_title) {\n              printtitle(&abort);\n              need_title = false;\n            }\n          }\n\n          printinfo(&f.u(), &abort);\n        } else if (bin.bkbhit()) {\n          bin.checka(&abort);\n        }\n      }\n    }\n  }\n  if (ac) {\n    tmp_disable_conf(false);\n  }\n  a()->set_current_user_dir_num(ocd);\n  endlist(1);\n}\n\nvoid arc_l() {\n  bout.nl();\n  bout.outstr(\"|#2File for listing: \");\n  auto file_spec = bin.input(12);\n  if (file_spec.find('.') == std::string::npos) {\n    file_spec += \".*\";\n  }\n  if (!okfn(file_spec)) {\n    file_spec.clear();\n  }\n  file_spec = aligns(file_spec);\n  dliscan();\n  bool abort = false;\n  int nRecordNum = recno(file_spec);\n  do {\n    if (nRecordNum > 0) {\n      auto f = a()->current_file_area()->ReadFile(nRecordNum);\n      int i1 = list_arc_out(f.unaligned_filename(),\n                            a()->dirs()[a()->current_user_dir().subnum].path);\n      if (i1) {\n        abort = true;\n      }\n      bin.checka(&abort);\n      nRecordNum = nrecno(file_spec, nRecordNum);\n    }\n  }\n  while (nRecordNum > 0 && !a()->sess().hangup() && !abort);\n}\n"
  },
  {
    "path": "bbs/xferovl.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_XFEROVL_H\n#define INCLUDED_BBS_XFEROVL_H\n\n#include <string>\n\nnamespace wwiv::sdk::files {\nclass FileRecord;\n}\n\nvoid move_file();\nvoid sortdir(int directory_num, int type);\nvoid sort_all(int type);\nvoid rename_file();\nbool maybe_upload(const std::string& file_name, int directory_num, const std::string& description);\nvoid upload_files(const std::string& file_name, int directory_num, int type);\nbool uploadall(int directory_num);\nvoid relist();\nvoid edit_database();\nvoid add_to_file_database(const std::string& file_name);\nvoid add_to_file_database(const wwiv::sdk::files::FileRecord& f);\nvoid remove_from_file_database(const std::string& file_name);\nbool is_uploadable(const std::string& file_name);\nvoid xfer_defaults();\nvoid finddescription();\nvoid arc_l();\n\n#endif\n"
  },
  {
    "path": "bbs/xferovl1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/xferovl1.h\"\n\n#include \"bbs/archivers.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/bbsutl.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/confutil.h\"\n#include \"bbs/execexternal.h\"\n#include \"bbs/external_edit.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/sr.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/tag.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"bbs/xfertmp.h\"\n#include \"common/com.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/numbers.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/diz.h\"\n#include \"sdk/files/files.h\"\n#include <memory>\n#include <string>\n#include <vector>\n\n// How far to indent extended descriptions\nstatic const int INDENTION = 24;\n\nextern int foundany;\n\nusing namespace wwiv::bbs;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid modify_extended_description(std::string* sss, const std::string& dest) {\n  char s[255], s1[255];\n  int i, i2;\n\n  bool ii = !sss->empty();\n  int i4 = 0;\n  bout.print(\"File Name: {}\\r\\n\", dest);\n  do {\n    if (ii) {\n      bout.nl();\n      if (okfsed() && a()->HasConfigFlag(OP_FLAGS_FSED_EXT_DESC)) {\n        bout.outstr(\"|#5Modify the extended description? \");\n      } else {\n        bout.outstr(\"|#5Enter a new extended description? \");\n      }\n      if (!bin.yesno()) {\n        return;\n      }\n    } else {\n      bout.nl();\n      bout.outstr(\"|#5Enter an extended description? \");\n      if (!bin.yesno()) {\n        return;\n      }\n    }\n    if (okfsed() && a()->HasConfigFlag(OP_FLAGS_FSED_EXT_DESC)) {\n      if (!sss->empty()) {\n        TextFile file(FilePath(a()->sess().dirs().temp_directory(), \"extended.dsc\"), \"w\");\n        file.Write(*sss);\n      } else {\n        File::Remove(FilePath(a()->sess().dirs().temp_directory(), \"extended.dsc\"));\n      }\n\n      const auto saved_screen_chars = a()->user()->screen_width();\n      if (a()->user()->screen_width() > (76 - INDENTION)) {\n        a()->user()->screen_width(76 - INDENTION);\n      }\n\n      const auto edit_ok = fsed_text_edit(\"extended.dsc\", a()->sess().dirs().temp_directory(),\n                                              a()->max_extend_lines, MSGED_FLAG_NO_TAGLINE);\n      a()->user()->screen_width(saved_screen_chars);\n      if (edit_ok) {\n        TextFile file(FilePath(a()->sess().dirs().temp_directory(), \"extended.dsc\"), \"r\");\n        *sss = file.ReadFileIntoString();\n\n        for (auto i3 = wwiv::stl::ssize(*sss) - 1; i3 >= 0; i3--) {\n          if ((*sss)[i3] == 1) {\n            (*sss)[i3] = ' ';\n          }\n        }\n      }\n    } else {\n      sss->clear();\n      i = 1;\n      bout.nl();\n      bout.print(\"Enter up to  {} lines, {} chars each.\\r\\n\", a()->max_extend_lines,\n                 78 - INDENTION);\n      bout.nl();\n      s[0] = '\\0';\n      const int nSavedScreenSize = a()->user()->screen_width();\n      if (a()->user()->screen_width() > (76 - INDENTION)) {\n        a()->user()->screen_width(76 - INDENTION);\n      }\n      do {\n        bout.print(\"|#2{}: |#0\", i);\n        s1[0] = '\\0';\n        const auto allow_previous = i4 > 0;\n        while (inli(s1, s, 90, true, allow_previous, false, true)) {\n          if (i > 1) {\n            --i;\n          }\n          sprintf(s1, \"%d:\", i);\n          bout.print(\"|#2{}\", s1);\n          i2 = 0;\n          i4 -= 2;\n          do {\n            s[i2] = sss->at(i4 - 1);\n            ++i2;\n            --i4;\n          }\n          while (sss->at(i4) != 10 && i4 != 0);\n          if (i4) {\n            ++i4;\n          }\n          sss->resize(i4);\n          s[i2] = 0;\n          strrev(s);\n          if (strlen(s) > static_cast<unsigned int>(a()->user()->screen_width() - 1)) {\n            s[a()->user()->screen_width() - 2] = '\\0';\n          }\n        }\n        i2 = strlen(s1);\n        if (i2 && (s1[i2 - 1] == 1)) {\n          s1[i2 - 1] = '\\0';\n        }\n        if (s1[0]) {\n          strcat(s1, \"\\r\\n\");\n          *sss += s1;\n          i4 += strlen(s1);\n        }\n      }\n      while (i++ < a()->max_extend_lines && s1[0]);\n      a()->user()->screen_width(nSavedScreenSize);\n    }\n    bout.outstr(\"|#5Is this what you want? \");\n    i = !bin.yesno();\n    if (i) {\n      sss->clear();\n    }\n  }\n  while (i);\n}\n\nstatic bool has_arc_cmd_for_ext(const std::string& ext) {\n  for (auto i = 0; i < MAX_ARCS; i++) {\n    if (iequals(ext, a()->arcs[i].extension)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic std::optional<std::filesystem::path> PathToTempdDiz(const std::filesystem::path& p) {\n  VLOG(1) << \"PathToTempDiz: \" << p;\n  File::Remove(FilePath(a()->sess().dirs().temp_directory(), FILE_ID_DIZ));\n  File::Remove(FilePath(a()->sess().dirs().temp_directory(), DESC_SDI));\n\n  if (!p.has_extension() || !has_arc_cmd_for_ext(p.extension().string().substr(1))) {\n    return std::nullopt;\n  }\n\n  const auto cmd = get_arc_cmd(p.string(), arc_command_type_t::extract, \"FILE_ID.DIZ DESC.SDI\");\n  if (!cmd.has_value() || cmd->internal) {\n    // Can't handle internal extract\n    return std::nullopt;\n  }\n  wwiv::bbs::CommandLine cl(cmd.value().cmd);\n  ExecuteExternalProgram(cl, EFLAG_NOHUP | EFLAG_TEMP_DIR);\n  auto diz_fn = FilePath(a()->sess().dirs().temp_directory(), FILE_ID_DIZ);\n  VLOG(1) << \"Checking for diz: \" << diz_fn;\n  if (auto o = FindFile(diz_fn)) {\n    VLOG(1) << \"Found: \" << diz_fn;\n    return { o.value() };\n  }\n  diz_fn = FilePath(a()->sess().dirs().temp_directory(), DESC_SDI);\n  VLOG(1) << \"Checking for diz: \" << diz_fn;\n  if (auto o = FindFile(diz_fn)) {\n    VLOG(1) << \"Found: \" << diz_fn;\n    return { o.value() };\n  }\n  VLOG(1) << \"No diz.\";\n  return std::nullopt;\n}\n\nbool get_file_idz(FileRecord& fr, const directory_t& dir) {\n  auto at_exit = finally([] {\n    File::Remove(FilePath(a()->sess().dirs().temp_directory(), FILE_ID_DIZ));\n    File::Remove(FilePath(a()->sess().dirs().temp_directory(), DESC_SDI));\n  });\n\n  if (!a()->HasConfigFlag(OP_FLAGS_READ_CD_IDZ) && dir.mask & mask_cdrom) {\n    return false;\n  }\n\n  const auto dir_path = File::absolute(a()->bbspath(), dir.path);\n  fr.set_date(DateTime::from_time_t(File::last_write_time(FilePath(dir_path, fr))));\n  auto o = PathToTempdDiz(FilePath(dir_path, fr));\n  if (!o) {\n    LOG(INFO) << \"File had no DIZ: \" << fr;\n    return true;\n  }\n  const auto& diz_fn = o.value();\n  bout.nl();\n  bout.print(\"|#9Reading in |#2{}|#9 as extended description...\", diz_fn.filename().string());\n  const auto old_ext = a()->current_file_area()->ReadExtendedDescriptionAsString(fr).value_or(\"\");\n\n  const DizParser dp(a()->HasConfigFlag(OP_FLAGS_IDZ_DESC));\n  if (auto odiz = dp.parse(diz_fn)) {\n    auto& diz = odiz.value();\n    fr.set_description(diz.description());\n    const auto ext_desc = diz.extended_description();\n\n    VLOG(1) << \"Diz Desc: \" << diz.description();\n    VLOG(1) << \"Diz Ext:  \" << ext_desc;\n    if (!ext_desc.empty()) {\n      if (!old_ext.empty()) {\n        a()->current_file_area()->DeleteExtendedDescription(fr.filename());\n      }\n      a()->current_file_area()->AddExtendedDescription(fr.filename(), ext_desc);\n      fr.set_extended_description(true);\n    }\n  } else {\n    VLOG(1) << \"Failed to parse DIZ: \" << diz_fn;\n  }\n\n  bout.outstr(\"Done!\\r\\n\");\n  return true;\n}\n\nint read_idz_all() {\n  int count = 0;\n\n  tmp_disable_conf(true);\n  TempDisablePause disable_pause(bout);\n  a()->ClearTopScreenProtection();\n  for (auto i = 0; i < a()->dirs().size() && !bout.localIO()->KeyPressed(); i++) {\n    count += read_idz(false, i);\n  }\n  tmp_disable_conf(false);\n  a()->UpdateTopScreen();\n  return count;\n}\n\nint read_idz(bool prompt_for_mask, int tempdir) {\n  int count = 0;\n  bool abort = false;\n  const auto dir_num = a()->udir[tempdir].subnum;\n  const auto dir = a()->dirs()[dir_num];\n\n  std::unique_ptr<TempDisablePause> disable_pause;\n  std::string s = \"*.*\";\n  if (prompt_for_mask) {\n    disable_pause.reset(new TempDisablePause(bout));\n    a()->ClearTopScreenProtection();\n    dliscan();\n    s = file_mask();\n  } else {\n    s = aligns(s);\n    dliscan1(dir_num);\n  }\n  bout.printf(\"|#9Checking for external description files in |#2%-25.25s #%s...\\r\\n\", dir.name,\n               a()->udir[tempdir].keys);\n  auto* area = a()->current_file_area();\n  for (auto i = 1; i <= area->number_of_files() && !a()->sess().hangup() && !abort; i++) {\n    auto f = area->ReadFile(i);\n    const auto fn = f.aligned_filename();\n    if (aligned_wildcard_match(s, fn) && !ends_with(fn, \".COM\") && !ends_with(fn, \".EXE\")) {\n      if (File::Exists(FilePath(dir.path, f))) {\n        if (get_file_idz(f, dir)) {\n          count++;\n        }\n        if (area->UpdateFile(f, i)) {\n          area->Save();\n        }\n      }\n    }\n    bin.checka(&abort);\n  }\n  if (prompt_for_mask) {\n    a()->UpdateTopScreen();\n  }\n  return count;\n}\n\nvoid tag_it() {\n  long fs = 0;\n\n  if (a()->batch().size() >= a()->max_batch) {\n    bout.outstr(\"|#6No room left in batch queue.\");\n    bin.getkey();\n    return;\n  }\n  bout.print(\"|#2Which file(s) (1-{}, *=All, 0=Quit)? \", a()->filelist.size());\n  auto s3 = bin.input(30, true);\n  if (!s3.empty() && s3.front() == '*') {\n    s3.clear();\n    for (size_t i2 = 0; i2 < a()->filelist.size() && i2 < 78; i2++) {\n      auto s2 = fmt::format(\"{} \", i2 + 1);\n      s3 += s2;\n      if (s3.size() > 250 /* was sizeof(s3)-10 */) {\n        break;\n      }\n    }\n    bout.print(\"\\r\\n|#2Tagging: |#4{}\\r\\n\", s3);\n  }\n  for (int i2 = 0; i2 < wwiv::strings::ssize(s3); i2++) {\n    auto s1 = s3.substr(i2);\n    int i4 = 0;\n    bool bad = false;\n    for (int i3 = 0; i3 < wwiv::strings::ssize(s1); i3++) {\n      if (s1[i3] == ' ' || s1[i3] == ',' || s1[i3] == ';') {\n        s1 = s1.substr(0, i3);\n        i4 = 1;\n      } else {\n        if (i4 == 0) {\n          i2++;\n        }\n      }\n    }\n    int i = to_number<int>(s1);\n    if (i == 0) {\n      break;\n    }\n    i--;\n    if (!s1.empty() && i >= 0 && i < size_int(a()->filelist)) {\n      auto& f = a()->filelist[i];\n      if (a()->batch().contains_file(f.u.filename)) {\n        bout.print(\"|#6{} is already in the batch queue.\\r\\n\", f.u.filename);\n        bad = true;\n      }\n      if (a()->batch().size() >= a()->max_batch) {\n        bout.print(\"|#6Batch file limit of {} has been reached.\\r\\n\", a()->max_batch);\n        bad = true;\n      }\n      if (a()->config()->req_ratio() > 0.0001f &&\n          a()->user()->ratio() < a()->config()->req_ratio() && !a()->user()->exempt_ratio() &&\n          !bad) {\n        bout.printf(\n            \"|#2Your up/download ratio is %-5.3f.  You need a ratio of %-5.3f to download.\\r\\n\",\n            a()->user()->ratio(), a()->config()->req_ratio());\n        bad = true;\n      }\n      if (!bad) {\n        auto s = FilePath(a()->dirs()[f.directory].path, FileName(f.u.filename));\n        if (f.dir_mask & mask_cdrom) {\n          auto s2 = FilePath(a()->dirs()[f.directory].path, FileName(f.u.filename));\n          s = FilePath(a()->sess().dirs().temp_directory(), FileName(f.u.filename));\n          if (!File::Exists(s)) {\n            File::Copy(s2, s);\n          }\n        }\n        File fp(s);\n        if (!fp.Open(File::modeBinary | File::modeReadOnly)) {\n          bout.print(\"|#6The file {} is not there.\\r\\n\", FileName(f.u.filename).unaligned_filename());\n          bad = true;\n        } else {\n          fs = fp.length();\n          fp.Close();\n        }\n      }\n      if (!bad) {\n        const auto t = time_to_transfer(a()->modem_speed_,fs).count();\n        if (nsl() <= a()->batch().dl_time_in_secs() + t) {\n          bout.print(\"|#6Not enough time left in queue for {}.\\r\\n\", f.u.filename);\n          bad = true;\n        }\n      }\n      if (!bad) {\n        BatchEntry b(f.u.filename, f.directory, fs, true);\n        a()->batch().AddBatch(std::move(b));\n        bout.print(\"|#1{} added to batch queue.\\r\\n\", f.u.filename);\n      }\n    } else {\n      bout.print(\"|#6Bad file number {}\\r\\n\", i + 1);\n    }\n    bout.clear_lines_listed();\n  }\n}\n\nstatic char fancy_prompt(const char* pszPrompt, const char* pszAcceptChars) {\n  char ch;\n\n  a()->tleft(true);\n  const auto s1 = fmt::format(\"\\r|#2{} (|#1{}|#2)? |#0\", pszPrompt, pszAcceptChars);\n  const auto s2 = fmt::format(\"{} ({})? \", pszPrompt, pszAcceptChars);\n  const int i1 = ssize(s2);\n  const auto s3 = StrCat(pszAcceptChars,\" \\r\");\n  a()->tleft(true);\n  if (okansi()) {\n    bout.outstr(s1);\n    ch = onek_ncr(s3);\n    bout.Left(i1);\n    for (int i = 0; i < i1; i++) {\n      bout.outchr(' ');\n    }\n    bout.Left(i1);\n  } else {\n    bout.outstr(s2);\n    ch = onek_ncr(s3);\n    for (auto i = 0; i < i1; i++) {\n      bout.bs();\n    }\n  }\n  return ch;\n}\n\nvoid tag_files(bool& need_title) {\n  if (bout.lines_listed() == 0) {\n    return;\n  }\n  a()->tleft(true);\n  if (a()->sess().hangup()) {\n    return;\n  }\n  bout.clear_lines_listed();\n  bout.ansic(FRAME_COLOR);\n  bout.outstr(\"\\r\");\n  bout.pl(std::string(78, '-'));\n\n  auto done = false;\n  while (!done && !a()->sess().hangup()) {\n    bout.clear_lines_listed();\n    const auto ch = fancy_prompt(\"File Tagging\", \"CDEMQRTV?\");\n    bout.clear_lines_listed();\n    switch (ch) {\n    case '?': {\n      bout.print_help_file(TTAGGING_NOEXT);\n      bout.pausescr();\n      relist();\n    }\n    break;\n    case 'C':\n    case SPACE:\n    case RETURN:\n      bout.clear_lines_listed();\n      a()->filelist.clear();\n      need_title = true;\n      //bout.cls();\n      done = true;\n      break;\n    case 'D':\n      batchdl(1);\n      bout.nl();\n      bout.pausescr();\n      bout.cls();\n      done = true;\n      break;\n    case 'E': {\n      bout.clear_lines_listed();\n      bout.print(\"|#9Which file (1-{})?\", a()->filelist.size());\n      auto s = bin.input(2, true);\n      const auto i = to_number<int>(s) - 1;\n      if (!s.empty() && i >= 0 && i < size_int(a()->filelist)) {\n        auto& f = a()->filelist[i];\n        bout.nl();\n        int i2;\n        for (i2 = 0; i2 < size_int(a()->udir); i2++) {\n          if (a()->udir[i2].subnum == f.directory) {\n            break;\n          }\n        }\n        std::string keys = i2 < size_int(a()->udir) ? a()->udir[i2].keys : \"??\";\n        const auto& dir = a()->dirs()[f.directory];\n        bout.print(\"|#1Directory  : |#2#{}, {}\\r\\n\", keys, dir.name);\n        printfileinfo(&f.u, dir);\n        bout.nl();\n        bout.pausescr();\n        relist();\n      }\n    }\n    break;\n    case 'M':\n      if (dcs()) {\n        move_file_t();\n        if (a()->filelist.empty()) {\n          return;\n        }\n        relist();\n      }\n      break;\n    case 'Q':\n      a()->filelist.clear();\n      bout.clear_lines_listed();\n      need_title = false;\n      return;\n    case 'R':\n      relist();\n      break;\n    case 'T':\n      tag_it();\n      break;\n    case 'V': {\n      bout.print(\"|#2Which file (1-|#2{})? \", a()->filelist.size());\n      auto s = bin.input(2, true);\n      int i = to_number<int>(s) - 1;\n      if (!s.empty() && i >= 0 && i < size_int(a()->filelist)) {\n        auto& f = a()->filelist[i];\n        auto s1 = FilePath(a()->dirs()[f.directory].path, FileName(f.u.filename));\n        if (a()->dirs()[f.directory].mask & mask_cdrom) {\n          auto s2 = FilePath(a()->dirs()[f.directory].path, FileName(f.u.filename));\n          s1 = FilePath(a()->sess().dirs().temp_directory(), FileName(f.u.filename));\n          if (!File::Exists(s1)) {\n            File::Copy(s2, s1);\n          }\n        }\n        if (!File::Exists(s1)) {\n          bout.outstr(\"|#6File not there.\\r\\n\");\n          bout.pausescr();\n          break;\n        }\n        list_arc_out(s1.string(), \"\");\n        bout.pausescr();\n        a()->UpdateTopScreen();\n        bout.cls();\n        relist();\n      }\n    }\n    break;\n    default:\n      bout.cls();\n      done = true;\n      break;\n    }\n  }\n  a()->filelist.clear();\n  bout.clear_lines_listed();\n}\n\n\nint add_batch(std::string& description, const std::string& aligned_file_name, int dn, long fs) {\n  if (a()->batch().FindBatch(aligned_file_name) > -1) {\n    return 0;\n  }\n\n  const auto t = time_to_transfer(a()->modem_speed_,fs).count();\n\n  if (nsl() <= a()->batch().dl_time_in_secs() + t) {\n    bout.outstr(\"|#6 Insufficient time remaining... press any key.\");\n    bin.getkey();\n  } else {\n    if (dn == -1) {\n      return 0;\n    }\n    for (auto& c : description) {\n      if (c == '\\r')\n        c = ' ';\n    }\n    bout.backline();\n    bout.printf(\" |#6? |#1%s %3.3s |#5%-43.43s |#7[|#2Y/N/Q|#7] |#0\", aligned_file_name,\n                 humanize(fs), stripcolors(description));\n    auto ch = onek_ncr(\"QYN\\r\");\n    bout.backline();\n    const auto ufn = wwiv::sdk::files::unalign(aligned_file_name);\n    const auto dir = a()->dirs()[dn];\n    if (to_upper_case<char>(ch) == 'Y') {\n      if (dir.mask & mask_cdrom) {\n        const auto src = FilePath(dir.path, ufn);\n        const auto dest = FilePath(a()->sess().dirs().temp_directory(), ufn);\n        if (!File::Exists(dest)) {\n          if (!File::Copy(src, dest)) {\n            bout.outstr(\"|#6 file unavailable... press any key.\");\n            bin.getkey();\n          }\n          bout.backline();\n          bout.clreol();\n        }\n      } else {\n        auto f = FilePath(a()->dirs()[dn].path, ufn);\n        if (!File::Exists(f) && !so()) {\n          bout.outstr(\"\\r\");\n          bout.clreol();\n          bout.outstr(\"|#6 file unavailable... press any key.\");\n          bin.getkey();\n          bout.outstr(\"\\r\");\n          bout.clreol();\n          return 0;\n        }\n      }\n      const BatchEntry b(aligned_file_name, dn, fs, true);\n      bout.outstr(\"\\r\");\n      const auto bt = ctim(b.time(a()->modem_speed_));\n      bout.printf(\"|#2%3d |#1%s |#2%-7ld |#1%s  |#2%s\\r\\n\", \n                           a()->batch().size() + 1,\n                           b.aligned_filename(), b.len(), bt, a()->dirs()[b.dir()].name);\n      a()->batch().AddBatch(b);\n      bout.outstr(\"\\r|#5    Continue search? \");\n      ch = onek_ncr(\"YN\\r\");\n      if (to_upper_case<char>(ch) == 'N') {\n        return -3;\n      }\n      return 1;\n    }\n    if (ch == 'Q') {\n      bout.backline();\n      return -3;\n    }\n    bout.backline();\n  }\n  return 0;\n}\n\nint try_to_download(const std::string& file_mask, int dn) {\n  int rtn;\n  bool abort = false;\n\n  dliscan1(dn);\n  int i = recno(file_mask);\n  if (i <= 0) {\n    bin.checka(&abort);\n    return abort ? -1 : 0;\n  }\n  bool ok = true;\n  foundany = 1;\n  do {\n    a()->tleft(true);\n    auto* area = a()->current_file_area();\n    auto f = area->ReadFile(i);\n\n    if (!(f.u().mask & mask_no_ratio) && !ratio_ok()) {\n      return -2;\n    }\n\n    write_inst(INST_LOC_DOWNLOAD, a()->current_user_dir().subnum, INST_FLAGS_ONLINE);\n    auto d = fmt::sprintf(\"%-40.40s\", f.description());\n    abort = false;\n    rtn = add_batch(d, f.aligned_filename(), dn, f.numbytes());\n\n    if (abort || rtn == -3) {\n      ok = false;\n    } else {\n      i = nrecno(file_mask, i);\n    }\n  } while (i > 0 && ok && !a()->sess().hangup());\n\n  if (rtn == -2) {\n    return -2;\n  }\n  if (abort || rtn == -3) {\n    return -1;\n  }\n  return 1;\n}\n\nvoid download() {\n  int i = 0, color = 0;\n  bool ok;\n  int rtn = 0;\n  bool done = false;\n\n  int useconf = 0;\n\n  bout.cls();\n  bout.litebar(StrCat(a()->config()->system_name(), \" Batch Downloads\"));\n  do {\n    if (!i) {\n      bout.outstr(\"|#2Enter files, one per line, wildcards okay.  [Space] aborts a search.\\r\\n\");\n      bout.nl();\n      bout.outstr(\"|#1 #  File Name    Size    Time      Directory\\r\\n\");\n      bout.outstr(\n          \"|#7\\xC4\\xC4\\xC4 \\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4 \"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4 \\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4 \"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\"\n          \"\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\r\\n\");\n    }\n    if (i < size_int(a()->batch().entry)) {\n      const auto& b = a()->batch().entry[i];\n      if (b.sending()) {\n        const auto t = ctim(b.time(a()->modem_speed_));\n        bout.printf(\"|#2%3d |#1%s |#2%-7ld |#1%s  |#2%s\\r\\n\", \n                             i + 1, b.aligned_filename(), b.len(), t, a()->dirs()[b.dir()].name);\n      }\n    } else {\n      do {\n        int count = 0;\n        ok = true;\n        bout.backline();\n        bout.printf(\"|#2%3d \", a()->batch().size() + 1);\n        bout.ansic(1);\n        const bool onl = bout.newline;\n        bout.newline = false;\n        auto s = bin.input(12);\n        bout.newline = onl;\n        if (!s.empty() && s.front() != ' ') {\n          if (strchr(s.c_str(), '.') == nullptr) {\n            s += \".*\";\n          }\n          s = aligns(s);\n          rtn = try_to_download(s, a()->current_user_dir().subnum);\n          if (rtn == 0) {\n            if (ok_multiple_conf(a()->user(), a()->uconfdir)) {\n              bout.backline();\n              bout.outstr(\" |#5Search all conferences? \");\n              const auto ch = onek_ncr(\"YN\\r\");\n              if (ch == '\\r' || to_upper_case<char>(ch) == 'Y') {\n                tmp_disable_conf(true);\n                useconf = 1;\n              }\n            }\n            bout.backline();\n            auto s1 = fmt::sprintf(\"%3d %s\", a()->batch().size() + 1, s);\n            bout.ansic(1);\n            bout.outstr(s1);\n            foundany = 0;\n            int dn = 0;\n            while (dn < size_int(a()->udir)) {\n              count++;\n              bout.ansic(color);\n              if (count == NUM_DOTS) {\n                bout.outstr(\"\\r\");\n                bout.ansic(color);\n                bout.outstr(s1);\n                color++;\n                count = 0;\n                if (color == 4) {\n                  color++;\n                }\n                if (color == 10) {\n                  color = 0;\n                }\n              }\n              rtn = try_to_download(s, a()->udir[dn].subnum);\n              if (rtn < 0) {\n                break;\n              }\n              dn++;\n            }\n            if (useconf) {\n              tmp_disable_conf(false);\n            }\n            if (!foundany) {\n              bout.outstr(\"|#6 File not found... press any key.\");\n              bin.getkey();\n              bout.backline();\n              ok = false;\n            }\n          }\n        } else {\n          bout.backline();\n          done = true;\n        }\n      }\n      while (!ok && !a()->sess().hangup());\n    }\n    i++;\n    if (rtn == -2) {\n      rtn = 0;\n      i = 0;\n    }\n  } while (!done && !a()->sess().hangup() && i <= size_int(a()->batch().entry));\n\n  if (!a()->batch().numbatchdl()) {\n    return;\n  }\n\n  bout.nl();\n  if (!ratio_ok()) {\n    bout.outstr(\"\\r\\nSorry, your ratio is too low.\\r\\n\\n\");\n    return;\n  }\n  bout.nl();\n  bout.print(\"|#1Files in Batch Queue   : |#2{}\\r\\n\", a()->batch().size());\n  bout.print(\"|#1Estimated Download Time: |#2{}\\r\\n\", ctim(a()->batch().dl_time_in_secs()));\n  bout.nl();\n  rtn = batchdl(3);\n  if (rtn) {\n    return;\n  }\n  bout.nl();\n  if (a()->batch().empty()) {\n    return;\n  }\n  bout.outstr(\"|#5Hang up after transfer? \");\n  const bool had = bin.yesno();\n  const int ip = get_protocol(xfertype::xf_down_batch);\n  if (ip > 0) {\n    switch (ip) {\n    case WWIV_INTERNAL_PROT_YMODEM: {\n      if (!a()->over_intern.empty()\n          && a()->over_intern[2].othr & othr_override_internal\n          && a()->over_intern[2].sendbatchfn[0]) {\n        dszbatchdl(had, a()->over_intern[2].sendbatchfn, prot_name(WWIV_INTERNAL_PROT_YMODEM));\n      } else {\n        ymbatchdl(had);\n      }\n    }\n    break;\n    case WWIV_INTERNAL_PROT_ZMODEM: {\n      zmbatchdl(had);\n    }\n    break;\n    default: {\n      dszbatchdl(had, a()->externs[ip - WWIV_NUM_INTERNAL_PROTOCOLS].sendbatchfn,\n                 a()->externs[ip - WWIV_NUM_INTERNAL_PROTOCOLS].description);\n    }\n    }\n    if (!had) {\n      bout.nl();\n      bout.print(\"Your ratio is now: {}\\r\\n\", a()->user()->ratio());\n    }\n  }\n}\n\nvoid endlist(int mode) {\n  // if mode == 1, list files\n  // if mode == 2, new files\n  if (a()->filelist.empty()) {\n    bout.outstr(\"\\r\");\n    if (mode == 1) {\n      bout.outstr(\"|#3No matching files found.\\r\\n\\n\");\n    } else {\n      bout.outstr(\"\\r|#1No new files found.\\r\\n\\n\");\n    }\n    return;\n  }\n  bool need_title = false;\n  if (!a()->filelist.empty()) {\n    tag_files(need_title);\n    return;\n  }\n  bout.ansic(FRAME_COLOR);\n  bout.print(\"\\r{}\\r\\n\", std::string(78, '-'));\n  bout.print(\"\\r|#9Files listed: |#2 {}\", a()->filelist.size());\n}\n\n// TODO(rushfan): Move to datetime.h? either in bbs or core?\n// Converts a mm/dd/yyyy string into int for month, day, year and OK \nstatic std::optional<DateTime> mmddyy_to_mdyo(std::string s) {\n  if (s.size() != 10) {\n    return std::nullopt;\n  }\n  const auto m = to_number<int>(StrCat(s[0], s[1]));\n  const auto d = to_number<int>(StrCat(s[3], s[4]));\n  const auto y = to_number<int>(StrCat(s[6], s[7], s[8], s[9]));\n  // These parens are not redundant\n  if (((m == 2 || m == 9 || m == 4 || m == 6 || m == 11) && d >= 31) ||\n      (m == 2 && ((y % 4 != 0 && d == 29) || d == 30)) ||\n      d > 31 || (m == 0 || y == 0 || d == 0) ||\n      (m > 12 || d > 31)) {\n      return std::nullopt;\n  }\n\n  tm t{};\n  t.tm_min = 0;\n  t.tm_hour = 1;\n  t.tm_sec = 0;\n  t.tm_year = y - 1900;\n  t.tm_mday = d;\n  t.tm_mon = m - 1;\n\n  return {DateTime::from_tm(&t)};\n}\n\nvoid SetNewFileScanDate() {\n  bout.nl();\n  const auto current_dt = DateTime::from_daten(a()->sess().nscandate());\n  bout.print(\"|#9Current limiting date: |#2{}\\r\\n\", current_dt.to_string(\"%m/%d/%Y\"));\n  bout.nl();\n  bout.outstr(\"|#9Enter new limiting date in the following format:\\r\\n\");\n  bout.outstr(\"|#1 MM/DD/YYYY\\r\\n|#7:\");\n  bout.mpl(8);\n  const auto ag = bin.input_date_mmddyyyy(\"\");\n  bout.nl();\n  if (!ag.empty()) {\n    auto o = mmddyy_to_mdyo(ag);\n    if (o.has_value()) {\n      const auto& dt = o.value();\n      a()->sess().nscandate(dt.to_daten_t());\n\n      // Display the new nscan date\n      bout.print(\"|#9New Limiting Date: |#2{}\\r\\n\", dt.to_string(\"%m/%d/%Y\"));\n\n      // Hack to make sure the date covers everything since we had to increment the hour by one\n      // to show the right date on some versions of MSVC\n      a()->sess().nscandate(a()->sess().nscandate() - SECONDS_PER_HOUR);\n    }\n  }\n}\n\n\nvoid removefilesnotthere(int dn, int* autodel) {\n  char ch;\n  dliscan1(dn);\n  const auto all_files = aligns(\"*.*\");\n  int i = recno(all_files);\n  bool abort = false;\n  while (!a()->sess().hangup() && i > 0 && !abort) {\n    auto* area = a()->current_file_area();\n    auto f = area->ReadFile(i);\n    auto candidate_fn = FilePath(a()->dirs()[dn].path, f);\n    if (!File::Exists(candidate_fn)) {\n      StringTrim(f.u().description);\n      candidate_fn = fmt::sprintf(\"|#2%s :|#1 %-40.40s\", f.aligned_filename(), f.description());\n      if (!*autodel) {\n        bout.backline();\n        bout.outstr(candidate_fn.string());\n        bout.nl();\n        bout.outstr(\"|#5Remove Entry (Yes/No/Quit/All) : \");\n        ch = onek_ncr(\"QYNA\");\n      } else {\n        bout.nl();\n        bout.print(\"|#1Removing entry {}\", candidate_fn.string());\n        ch = 'Y';\n      }\n      if (ch == 'Y' || ch == 'A') {\n        if (ch == 'A') {\n          bout.outstr(\"ll\");\n          *autodel = 1;\n        }\n        sysoplog(fmt::format(\"- '{}' Removed from {}\", f, a()->dirs()[dn].name));\n        if (area->DeleteFile(f, i)) {\n          area->Save();\n        }\n        --i;\n      } else if (ch == 'Q') {\n        abort = true;\n      }\n    }\n    i = nrecno(all_files, i);\n    bool next = true;\n    bin.checka(&abort, &next);\n    if (!next) {\n      i = 0;\n    }\n  }\n}\n\nvoid removenotthere() {\n  if (!so()) {\n    return;\n  }\n\n  tmp_disable_conf(true);\n  TempDisablePause disable_pause(bout);\n  int autodel = 0;\n  bout.nl();\n  bout.outstr(\"|#5Remove N/A files in all directories? \");\n  if (bin.yesno()) {\n    for (auto i = 0; i < size_int(a()->udir) && !bout.localIO()->KeyPressed(); i++) {\n      bout.nl();\n      bout.print(\"|#1Removing N/A|#0 in {}\", a()->dirs()[a()->udir[i].subnum].name);\n      bout.nl(2);\n      removefilesnotthere(a()->udir[i].subnum, &autodel);\n    }\n  } else {\n    bout.nl();\n    bout.print(\"Removing N/A|#0 in {}\", a()->dirs()[a()->current_user_dir().subnum].name);\n    bout.nl(2);\n    removefilesnotthere(a()->current_user_dir().subnum, &autodel);\n  }\n  tmp_disable_conf(false);\n  a()->UpdateTopScreen();\n}\n"
  },
  {
    "path": "bbs/xferovl1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_XFEROVL1_H\n#define INCLUDED_BBS_XFEROVL1_H\n\n#include <string>\n\nnamespace wwiv::sdk::files {\nstruct directory_t;\nclass FileRecord;\n}\n\nvoid modify_extended_description(std::string* sss, const std::string& dest);\nbool valid_desc(const std::string& description);\nbool get_file_idz(wwiv::sdk::files::FileRecord& fr, const wwiv::sdk::files::directory_t& dir);\nint read_idz_all();\nint read_idz(bool prompt_for_mask, int tempdir);\nvoid tag_it();\nvoid tag_files(bool& need_title);\nint add_batch(std::string& description, const std::string& aligned_file_name, int dn, long fs);\nint try_to_download(const std::string& file_mask, int dn);\nvoid download();\nvoid endlist(int mode);\nvoid SetNewFileScanDate();\nvoid removefilesnotthere(int dn, int* autodel);\nvoid removenotthere();\n\n#endif\n"
  },
  {
    "path": "bbs/xfertmp.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/xfertmp.h\"\n#include \"bbs/batch.h\"\n#include \"bbs/bbs.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/dirlist.h\"\n#include \"bbs/mmkey.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/xfer.h\"\n#include \"bbs/xferovl.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/numbers.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/files.h\"\n#include <functional>\n#include <string>\n#include <vector>\n\nusing wwiv::sdk::files::FileName;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid move_file_t() {\n  int d1 = -1;\n\n  tmp_disable_conf(true);\n\n  bout.nl();\n  if (a()->batch().empty()) {\n    bout.nl();\n    bout.outstr(\"|#6No files have been tagged for movement.\\r\\n\");\n    bout.pausescr();\n  }\n  // TODO(rushfan): rewrite using iterators.\n  for (auto pos = a()->batch().ssize() - 1; pos >= 0; pos--) {\n    bool ok;\n    auto cur_batch_fn = aligns(a()->batch().entry[pos].aligned_filename());\n    dliscan1(a()->batch().entry[pos].dir());\n    int temp_record_num = recno(cur_batch_fn);\n    if (temp_record_num < 0) {\n      bout.outstr(\"File not found.\\r\\n\");\n      bout.pausescr();\n    }\n    while (!a()->sess().hangup() && temp_record_num > 0) {\n      auto cur_pos = temp_record_num;\n      auto f = a()->current_file_area()->ReadFile(temp_record_num);\n      const auto& dir = a()->dirs()[a()->batch().entry[pos].dir()];\n      printfileinfo(&f.u(), dir);\n      bout.outstr(\"|#5Move this (Y/N/Q)? \");\n      const auto ch = bin.ynq();\n      if (ch == 'Q') {\n        tmp_disable_conf(false);\n        dliscan();\n        return;\n      }\n      std::filesystem::path s1;\n      if (ch == 'Y') {\n        s1 = FilePath(dir.path, f);\n        std::string dirnum;\n        do {\n          bout.outstr(\"|#2To which directory? \");\n          dirnum = mmkey(MMKeyAreaType::dirs);\n          if (dirnum.front() == '?') {\n            dirlist(1);\n            dliscan1(a()->batch().entry[pos].dir());\n          }\n        }\n        while (!a()->sess().hangup() && (dirnum.front() == '?'));\n        d1 = -1;\n        if (!dirnum.empty()) {\n          for (auto i1 = 0; i1 < size_int(a()->udir); i1++) {\n            if (dirnum == a()->udir[i1].keys) {\n              d1 = i1;\n            }\n          }\n        }\n        if (d1 != -1) {\n          ok = true;\n          d1 = a()->udir[d1].subnum;\n          dliscan1(d1);\n          if (recno(f.aligned_filename()) > 0) {\n            ok = false;\n            bout.outstr(\"Filename already in use in that directory.\\r\\n\");\n          }\n          if (a()->current_file_area()->number_of_files() >= a()->dirs()[d1].maxfiles) {\n            ok = false;\n            bout.outstr(\"Too many files in that directory.\\r\\n\");\n          }\n          if (File::freespace_for_path(a()->dirs()[d1].path) <\n              static_cast<long>(f.numbytes() / 1024L) + 3) {\n            ok = false;\n            bout.outstr(\"Not enough disk space to move it.\\r\\n\");\n          }\n          dliscan();\n        } else {\n          ok = false;\n        }\n      } else {\n        ok = false;\n      }\n      if (ok) {\n        bout.outstr(\"|#5Reset upload time for file? \");\n        if (bin.yesno()) {\n          f.set_date(DateTime::now());\n        }\n        --cur_pos;\n        auto ext_desc = a()->current_file_area()->ReadExtendedDescriptionAsString(f);\n        if (a()->current_file_area()->DeleteFile(f, temp_record_num)) {\n          a()->current_file_area()->Save();\n        }\n        auto s2 = FilePath(a()->dirs()[d1].path, f);\n        dliscan1(d1);\n        // N.B. the current file area changes with calls to dliscan*\n        if (a()->current_file_area()->AddFile(f)) {\n          a()->current_file_area()->Save();\n        }\n        if (ext_desc) {\n          const auto fpos = a()->current_file_area()->FindFile(f).value_or(-1);\n          a()->current_file_area()->AddExtendedDescription(f, fpos, ext_desc.value());\n        }\n        if (s1 != s2 && File::Exists(s1)) {\n          File::Rename(s1, s2);\n          remlist(a()->batch().entry[pos].aligned_filename());\n          didnt_upload(a()->batch().entry[pos]);\n          a()->batch().delbatch(pos);\n        }\n        bout.outstr(\"File moved.\\r\\n\");\n      }\n      dliscan();\n      temp_record_num = nrecno(cur_batch_fn, cur_pos);\n    }\n  }\n  tmp_disable_conf(false);\n}\n\nvoid removefile() {\n  dliscan();\n  bout.nl();\n  bout.outstr(\"|#9Enter filename to remove.\\r\\n:\");\n  auto remove_fn = bin.input(12, true);\n  if (remove_fn.empty()) {\n    return;\n  }\n  if (strchr(remove_fn.c_str(), '.') == nullptr) {\n    remove_fn += \".*\";\n  }\n  remove_fn = aligns(remove_fn);\n  auto record_num = recno(remove_fn);\n  auto abort = false;\n  while (!a()->sess().hangup() && record_num > 0 && !abort) {\n    auto f = a()->current_file_area()->ReadFile(record_num);\n    if (dcs() || (f.u().ownersys == 0 && f.u().ownerusr == a()->sess().user_num())) {\n      const auto& dir = a()->dirs()[a()->current_user_dir().subnum];\n      bout.nl();\n      if (a()->batch().contains_file(f.filename())) {\n        bout.outstr(\"|#6That file is in the batch queue; remove it from there.\\r\\n\\n\");\n      } else {\n        printfileinfo(&f.u(), dir);\n        bout.outstr(\"|#9Remove (|#2Y/N/Q|#9) |#0: |#2\");\n        auto ch = bin.ynq();\n        if (ch == 'Q') {\n          abort = true;\n        } else if (ch == 'Y') {\n          bool bRemoveDlPoints = true;\n          bool bDeleteFileToo;\n          if (dcs()) {\n            bout.outstr(\"|#5Delete file too? \");\n            bDeleteFileToo = bin.yesno();\n            if (bDeleteFileToo && (f.u().ownersys == 0)) {\n              bout.outstr(\"|#5Remove DL points? \");\n              bRemoveDlPoints = bin.yesno();\n            }\n            bout.nl();\n            bout.outstr(\"|#5Remove from ALLOW.DAT? \");\n            if (bin.yesno()) {\n              remove_from_file_database(f.aligned_filename());\n            }\n          } else {\n            bDeleteFileToo = true;\n            remove_from_file_database(f.aligned_filename());\n          }\n          if (bDeleteFileToo) {\n            auto del_fn = FilePath(dir.path, f);\n            File::Remove(del_fn);\n            if (bRemoveDlPoints && f.u().ownersys == 0) {\n              User uu{};\n              a()->users()->readuser(&uu, f.u().ownerusr);\n              if (!uu.deleted()) {\n                if (date_to_daten(uu.firston()) < f.u().daten) {\n                  uu.decrement_uploaded();\n                  uu.set_uk(uu.uk() - bytes_to_k(f.numbytes()));\n                  a()->users()->writeuser(&uu, f.u().ownerusr);\n                }\n              }\n            }\n          }\n          sysoplog(fmt::format(\"- \\\"{}\\\" removed off of {}\", f, dir.name));\n          if (a()->current_file_area()->DeleteFile(f, record_num)) {\n            a()->current_file_area()->Save();\n            --record_num;\n          }\n        }\n      }\n    }\n    record_num = nrecno(remove_fn, record_num);\n  }\n}\n"
  },
  {
    "path": "bbs/xfertmp.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_XFERTMP_H\n#define INCLUDED_BBS_XFERTMP_H\n\nvoid move_file_t();\nvoid removefile();\n\n#endif\n"
  },
  {
    "path": "bbs/xinit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"bbs/bbs.h\"\n#include \"bbs/bbs_event_handlers.h\"\n#include \"bbs/conf.h\"\n#include \"bbs/connect1.h\"\n#include \"bbs/instmsg.h\"\n#include \"bbs/interpret.h\"\n#include \"bbs/netsup.h\"\n#include \"bbs/sysoplog.h\"\n#include \"bbs/utility.h\"\n#include \"bbs/xinitini.h\"\n#include \"common/datetime.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/pause.h\"\n#include \"common/workspace.h\"\n#include \"core/datafile.h\"\n#include \"core/eventbus.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/arword.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/gfiles.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/names.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/networks.h\"\n#include <algorithm>\n#include <chrono>\n#include <memory>\n#include <string>\n\nusing std::chrono::duration;\nusing std::chrono::duration_cast;\nusing std::chrono::seconds;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nvoid StatusManagerCallback(int i) {\n  switch (i) {\n  case Status::file_change_names: {\n    // re-read names.lst\n    if (a()->names()) {\n      // We may not have the BBS initialized yet, so only\n      // re-read the names file if it's changed from another node.\n      a()->names()->Load();\n    }\n  } break;\n  case Status::file_change_upload:\n    break;\n  case Status::file_change_posts:\n    a()->subchg = 1;\n    break;\n  case Status::file_change_email:\n    a()->emchg_ = true;\n    break;\n  case Status::file_change_net: {\n    set_net_num(a()->net_num());\n  } break;\n  default: // NOP\n    break;\n  }\n}\n\n// Turns a string into a bit mapped uint16_t flag for use with ExecuteExternalProgram.\nstatic uint32_t str2spawnopt(const std::string& s) {\n  auto return_val = EFLAG_NONE;\n  const auto ts = ToStringUpperCase(s);\n\n  if (ts.find(\"NOHUP\") != std::string::npos) {\n    return_val |= EFLAG_NOHUP;\n  }\n  if (ts.find(\"COMIO\") != std::string::npos) {\n    return_val |= EFLAG_COMIO;\n  }\n  if (ts.find(\"BINARY\") != std::string::npos) {\n    return_val |= EFLAG_BINARY;\n  }\n  if (ts.find(\"FOSSIL\") != std::string::npos) {\n    return_val |= EFLAG_SYNC_FOSSIL;\n  }\n  if (ts.find(\"NETFOSS\") != std::string::npos) {\n    return_val |= EFLAG_NETFOSS;\n  }\n  if (ts.find(\"NETPROG\") != std::string::npos) {\n    return_val |= EFLAG_NETPROG;\n  }\n  if (ts.find(\"STDIO\") != std::string::npos) {\n    return_val |= EFLAG_STDIO;\n  }\n  if (ts.find(\"NOSCRIPT\") != std::string::npos) {\n    return_val |= EFLAG_NOSCRIPT;\n  }\n  if (ts.find(\"NO_CHANGE_DIR\") != std::string::npos) {\n    return_val |= EFLAG_NO_CHANGE_DIR;\n  }\n  if (ts.find(\"TEMP_DIR\") != std::string::npos) {\n    return_val |= EFLAG_TEMP_DIR;\n  }\n  if (ts.find(\"BATCH_DIR\") != std::string::npos) {\n    return_val |= EFLAG_BATCH_DIR;\n  }\n  if (ts.find(\"QWK_DIR\") != std::string::npos) {\n    return_val |= EFLAG_QWK_DIR;\n  }\n  if (ts.find(\"LISTEN_SOCK\") != std::string::npos) {\n    return_val |= EFLAG_LISTEN_SOCK;\n  }\n  if (ts.find(\"UNIX_SOCK\") != std::string::npos) {\n    return_val |= EFLAG_UNIX_SOCK;\n  }\n  return return_val;\n}\n\n// Takes string s and creates restrict val\nstatic uint16_t str2restrict(const std::string& s) {\n  const auto s1 = ToStringUpperCase(s);\n  uint16_t r = 0;\n  for (auto i = ssize(restrict_string) - 1; i >= 0; i--) {\n    if (s1.find(restrict_string[i]) != std::string::npos) {\n      r |= 1 << i;\n    }\n  }\n\n  return r;\n}\n\n// Reads WWIV.INI info from [WWIV] subsection, overrides some config.dat\n// settings (as appropriate), updates config.dat with those values. Also\n// tries to read settings from [WWIV-<instnum>] subsection - this overrides\n// those in [WWIV] subsection.\n\n// See #defines SPAWNOPT_XXXX in vardec.h for these.\nstatic std::map<std::string, uint32_t> eventinfo = {\n    {\"NEWUSER\", EFLAG_NONE},     {\"BEGINDAY\", EFLAG_NONE},\n    {\"LOGON\", EFLAG_NONE},       {\"ULCHK\", EFLAG_NOHUP},\n    {\"PROT_SINGLE\", EFLAG_NONE}, {\"PROT_BATCH\", EFLAG_BATCH_DIR},\n    {\"ARCH_E\", EFLAG_NONE},      {\"ARCH_L\", EFLAG_NONE},      {\"ARCH_A\", EFLAG_NONE},\n    {\"ARCH_D\", EFLAG_NONE},      {\"ARCH_K\", EFLAG_NONE},      {\"ARCH_T\", EFLAG_NONE},\n    {\"NET_CMD1\", EFLAG_NETPROG}, {\"NET_CMD2\", EFLAG_NETPROG}, {\"LOGOFF\", EFLAG_NONE},\n    {\"CLEANUP\", EFLAG_NONE},\n};\n\n// TODO(rushfan): If we need this elsewhere add it into IniFile\nstatic std::string to_array_key(const std::string& n, const std::string& index) {\n  return StrCat(n, \"[\", index, \"]\");\n}\n\n#define INI_GET_ASV(s, f, func, d)                                                                 \\\n  do {                                                                                                \\\n    const auto ss = ini.value<std::string>(to_array_key(INI_STR_SIMPLE_ASV, s));                   \\\n    if (!ss.empty()) {                                                                             \\\n      (f) = func(ss);                                                                                \\\n    } else {                                                                                       \\\n      (f) = d;                                                                                       \\\n    }                                                                                              \\\n  } while(0)\n\nstatic std::vector<ini_flags_type> sysinfo_flags = {\n    {INI_STR_FORCE_FBACK, OP_FLAGS_FORCE_NEWUSER_FEEDBACK},\n    //{INI_STR_CHECK_DUP_PHONES, OP_FLAGS_CHECK_DUPE_PHONENUM},\n    //{INI_STR_HANGUP_DUP_PHONES, OP_FLAGS_HANGUP_DUPE_PHONENUM},\n    {INI_STR_USE_SIMPLE_ASV, OP_FLAGS_SIMPLE_ASV},\n    {INI_STR_POSTTIME_COMPENS, OP_FLAGS_POSTTIME_COMPENSATE},\n    {INI_STR_IDZ_DESC, OP_FLAGS_IDZ_DESC},\n//    {INI_STR_SETLDATE, OP_FLAGS_SETLDATE},\n    {INI_STR_READ_CD_IDZ, OP_FLAGS_READ_CD_IDZ},\n    {INI_STR_FSED_EXT_DESC, OP_FLAGS_FSED_EXT_DESC},\n//    {INI_STR_FAST_TAG_RELIST, OP_FLAGS_FAST_TAG_RELIST},\n    {INI_STR_MAIL_PROMPT, OP_FLAGS_MAIL_PROMPT},\n    {INI_STR_SHOW_CITY_ST, OP_FLAGS_SHOW_CITY_ST},\n//    {INI_STR_WFC_SCREEN, OP_FLAGS_WFC_SCREEN},\n    {INI_STR_MSG_TAG, OP_FLAGS_MSG_TAG},\n//    {INI_STR_CHAIN_REG, OP_FLAGS_CHAIN_REG},\n    {INI_STR_CAN_SAVE_SSM, OP_FLAGS_CAN_SAVE_SSM},\n    {INI_STR_USE_FORCE_SCAN, OP_FLAGS_USE_FORCESCAN},\n    //{INI_STR_NEWUSER_MIN, OP_FLAGS_NEWUSER_MIN},\n};\n\nstatic std::vector<ini_flags_type> sysconfig_flags = {\n    {INI_STR_2WAY_CHAT, sysconfig_2_way},\n    {INI_STR_NO_NEWUSER_FEEDBACK, sysconfig_no_newuser_feedback},\n    {INI_STR_TITLEBAR, sysconfig_titlebar},\n    {INI_STR_LOG_DOWNLOADS, sysconfig_log_dl},\n    //{INI_STR_CLOSE_XFER, sysconfig_no_xfer},\n    {INI_STR_ALL_UL_TO_SYSOP, sysconfig_all_sysop},\n    {INI_STR_ALLOW_ALIASES, sysconfig_allow_alias},\n    //{INI_STR_EXTENDED_USERINFO, sysconfig_extended_info},\n    {INI_STR_FREE_PHONE, sysconfig_free_phone}};\n\nvoid Application::ReadINIFile(IniFile& ini) {\n  // Setup default  data\n  chatname_color_ = 95;\n  message_color_ = 2;\n  max_batch = 50;\n  max_extend_lines = 10;\n  max_chains = 50;\n  max_gfilesec = 32;\n\n  // Found something, pull out event flags.\n  for (const auto& kv : eventinfo) {\n    spawn_opts_[kv.first] = kv.second;\n    const auto key_name = to_array_key(INI_STR_SPAWNOPT, kv.first);\n    const auto ss = ini.value<std::string>(key_name);\n    if (!ss.empty()) {\n      spawn_opts_[kv.first] = str2spawnopt(ss);\n    }\n  }\n\n  // pull out new user colors\n  for (int i = 0; i < 10; i++) {\n    auto index = std::to_string(i);\n    auto num = ini.value<uint8_t>(to_array_key(INI_STR_NUCOLOR, index));\n    if (num != 0) {\n      newuser_colors[i] = num;\n    }\n    num = ini.value<uint8_t>(to_array_key(INI_STR_NUCOLORBW, index));\n    if (num != 0) {\n      newuser_bwcolors[i] = num;\n    }\n  }\n\n  SetCarbonCopyEnabled(ini.value<bool>(\"ALLOW_CC_BCC\"));\n\n  // pull out sysop-side colors\n  bout.localIO()->SetTopScreenColor(ini.value<uint8_t>(INI_STR_TOPCOLOR, bout.localIO()->GetTopScreenColor()));\n  bout.localIO()->SetUserEditorColor(ini.value<uint8_t>(INI_STR_F1COLOR, bout.localIO()->GetUserEditorColor()));\n  bout.localIO()->SetEditLineColor(ini.value<uint8_t>(INI_STR_EDITLINECOLOR, bout.localIO()->GetEditLineColor()));\n  chatname_color_ = ini.value<int>(INI_STR_CHATSELCOLOR, GetChatNameSelectionColor());\n\n  // pull out sizing options\n  max_batch = ini.value<uint16_t>(INI_STR_MAX_BATCH, max_batch);\n  max_extend_lines = ini.value<uint16_t>(INI_STR_MAX_EXTEND_LINES, max_extend_lines);\n  max_chains = ini.value<uint16_t>(INI_STR_MAX_CHAINS, max_chains);\n  max_gfilesec = ini.value<uint16_t>(INI_STR_MAX_GFILESEC, max_gfilesec);\n\n  // pull out strings\n  upload_cmd = ini.value<std::string>(INI_STR_UPLOAD_CMD);\n  beginday_cmd = ini.value<std::string>(INI_STR_BEGINDAY_CMD);\n  newuser_cmd = ini.value<std::string>(INI_STR_NEWUSER_CMD);\n  logon_cmd = ini.value<std::string>(INI_STR_LOGON_CMD);\n  logoff_cmd = ini.value<std::string>(INI_STR_LOGOFF_CMD);\n  cleanup_cmd = ini.value<std::string>(INI_STR_CLEANUP_CMD);\n  terminal_command = ini.value<std::string>(INI_STR_TERMINAL_CMD);\n\n  forced_read_subnum_ = ini.value<uint16_t>(INI_STR_FORCE_SCAN_SUBNUM, forced_read_subnum_);\n  internal_zmodem_ = ini.value<bool>(INI_STR_INTERNALZMODEM, true);\n  internal_fsed_ = ini.value<bool>(INI_STR_INTERNAL_FSED, true);\n  newscan_at_login_ = ini.value<bool>(INI_STR_NEW_SCAN_AT_LOGIN, true);\n  exec_log_syncfoss_ = ini.value<bool>(INI_STR_EXEC_LOG_SYNCFOSS, false);\n  exec_child_process_wait_time_ = ini.value<int>(INI_STR_EXEC_CHILD_WAIT_TIME, 500);\n  beginday_node_number_ = ini.value<int>(INI_STR_BEGINDAYNODENUMBER, 1);\n\n  // pull out sysinfo_flags\n  flags_ = ini.GetFlags(sysinfo_flags, flags_);\n\n  // allow override of Application::message_color_\n  message_color_ = ini.value<int>(INI_STR_MSG_COLOR, GetMessageColor());\n\n  // get asv values\n  if (HasConfigFlag(OP_FLAGS_SIMPLE_ASV)) {\n    INI_GET_ASV(\"SL\", asv.sl, to_number<uint8_t>, asv.sl);\n    INI_GET_ASV(\"DSL\", asv.dsl, to_number<uint8_t>, asv.dsl);\n    INI_GET_ASV(\"EXEMPT\", asv.exempt, to_number<uint8_t>, asv.exempt);\n    INI_GET_ASV(\"AR\", asv.ar, str_to_arword, asv.ar);\n    INI_GET_ASV(\"DAR\", asv.dar, str_to_arword, asv.dar);\n    INI_GET_ASV(\"RESTRICT\", asv.restrict, str2restrict, asv.restrict);\n  }\n\n  // sysconfig flags\n  config()->set_sysconfig(ini.GetFlags(sysconfig_flags, config()->sysconfig_flags()));\n\n  // Sets up the default attach directory.\n  const auto attach_dir = ini.value<std::string>(INI_STR_ATTACH_DIR);\n  attach_dir_ = !attach_dir.empty() ? attach_dir : FilePath(bbspath(), \"attach\").string();\n  attach_dir_ = File::EnsureTrailingSlash(attach_dir_);\n\n  // Sets up the default net fossil directory.\n  const std::filesystem::path netfoss_dir = ini.value<std::string>(INI_STR_NETFOSS_DIR);\n  netfoss_dir_ = !netfoss_dir.empty() ? netfoss_dir : FilePath(bbspath(), \"netfoss\");\n  netfoss_dir_ = File::EnsureTrailingSlash(netfoss_dir_);\n\n  screen_saver_time = ini.value<uint16_t>(\"SCREEN_SAVER_TIME\", screen_saver_time);\n\n  max_extend_lines = std::min<uint16_t>(max_extend_lines, 99);\n  max_batch = std::min<uint16_t>(max_batch, 999);\n  max_chains = std::min<uint16_t>(max_chains, 999);\n  max_gfilesec = std::min<uint16_t>(max_gfilesec, 999);\n\n  full_screen_read_prompt_ = ini.value<bool>(\"FULL_SCREEN_READER\", true);\n  bin.set_logon_key_timeout(seconds(std::max<int>(10, ini.value<int>(\"LOGON_KEY_TIMEOUT\", 30))));\n  bin.set_default_key_timeout(seconds(std::max<int>(30, ini.value<int>(\"USER_KEY_TIMEOUT\", 180))));\n  bin.set_sysop_key_timeout(seconds(std::max<int>(30, ini.value<int>(\"SYSOP_KEY_TIMEOUT\", 600))));\n\n  // Set the system wide BPS.\n  const auto system_bps = ini.value<int>(\"SYSTEM_BPS\", 0);\n  sess().set_system_bps(system_bps);\n}\n\nbool Application::ReadInstanceSettings(int instance_number) {\n  auto temp_directory = config_->temp_format();\n  if (temp_directory.empty()) {\n    temp_directory = \"e/%n/temp\";\n  }\n  auto batch_directory = config_->batch_format();\n  if (batch_directory.empty()) {\n    batch_directory = temp_directory;\n  }\n  auto scratch_directory = config_->scratch_format();\n  if (scratch_directory.empty()) {\n    scratch_directory = temp_directory;\n  }\n  temp_directory = File::FixPathSeparators(temp_directory);\n  batch_directory = File::FixPathSeparators(batch_directory);\n  scratch_directory = File::FixPathSeparators(scratch_directory);\n\n  // Replace %n with instance number value.\n  const auto instance_num_string = std::to_string(instance_number);\n  StringReplace(&temp_directory, \"%n\", instance_num_string);\n  StringReplace(&batch_directory, \"%n\", instance_num_string);\n  StringReplace(&scratch_directory, \"%n\", instance_num_string);\n  \n  // Set the directories (temp, batch, language)\n  const auto temp = File::EnsureTrailingSlash(File::absolute(bbspath(), temp_directory));\n  const auto batch = File::EnsureTrailingSlash(File::absolute(bbspath(), batch_directory));\n  const auto scratch = File::EnsureTrailingSlash(File::absolute(bbspath(), scratch_directory));\n\n  Dirs d(temp, batch, batch, config()->gfilesdir(), scratch);\n  sess().dirs(d);\n\n  // Set config for macro processing.\n  bbs_macro_context_->set_config(config());\n\n  if (instance_number > config_->num_instances()) {\n    LOG(ERROR) << \"Not enough instances configured in wwivconfig. Currently: \" << config_->num_instances();\n    return false;\n  }\n  return true;\n}\n\nbool Application::ReadConfig() {\n  config_ = std::make_unique<Config>(bbspath());\n  if (!config_->IsInitialized()) {\n    LOG(ERROR) << config_->config_filename() << \" NOT FOUND.\";\n    return false;\n  }\n\n  if (!config_->versioned_config_dat()) {\n    const auto msg = fmt::format(\n        \"Please run WWIVconfig to upgrade {} to the most recent version.\", \n        config_->config_filename().string());\n    std::cerr << msg << std::endl;\n    LOG(ERROR) << msg;\n    sleep_for(seconds(2));\n    return false;\n  }\n\n  // initialize the user manager\n  user_manager_ = std::make_unique<UserManager>(*config_);\n  statusMgr = std::make_unique<StatusMgr>(config_->datadir(), StatusManagerCallback);\n\n  IniFile ini(FilePath(bbspath(), WWIV_INI), StrCat(\"WWIV-\", sess().instance_number()), INI_TAG);\n  if (!ini.IsOpen()) {\n    LOG(ERROR) << \"Unable to read WWIV.INI.\";\n    return false;\n  }\n  ReadINIFile(ini);\n  if (!ReadInstanceSettings(sess().instance_number())) {\n    return false;\n  }\n\n  // Since the BBS's config has been read, we can actually shut down the BBS when we exit.\n  shutdown_on_exit_allowed_ = true;\n  return true;\n}\n\nvoid Application::read_nextern() {\n  externs.clear();\n  if (auto externalFile = DataFile<newexternalrec>(FilePath(config()->datadir(), NEXTERN_DAT))) {\n    externalFile.ReadVector(externs, 15);\n  }\n}\n\nvoid Application::read_arcs() {\n  arcs.clear();\n  if (auto file = DataFile<arcrec>(FilePath(config()->datadir(), ARCHIVER_DAT))) {\n    file.ReadVector(arcs, MAX_ARCS);\n  }\n}\n\nvoid Application::read_editors() {\n  editors.clear();\n  if (auto file = DataFile<editorrec>(FilePath(config()->datadir(), EDITORS_DAT))) {\n    file.ReadVector(editors, 10);\n  }\n}\n\nvoid Application::read_nintern() {\n  over_intern.clear();\n  if (auto file = DataFile<newexternalrec>(FilePath(config()->datadir(), NINTERN_DAT))) {\n    file.ReadVector(over_intern, 3);\n  }\n}\n\nbool Application::read_subs() {\n  subs_ = std::make_unique<Subs>(config_->datadir(), nets_->networks(), config_->max_backups());\n  return subs_->Load();\n}\n\nclass BBSLastReadImpl final : public msgapi::WWIVLastReadImpl {\n  [[nodiscard]] uint32_t last_read(int area) const override { return a()->sess().qsc_p[area]; }\n\n  void set_last_read(int area, uint32_t last_read) override {\n    if (area >= 0) {\n      a()->sess().qsc_p[area] = last_read;\n    }\n  }\n\n  void Load() override {\n    // Handled by the BBS in read_qscn(usernum, qsc, false);\n  }\n\n  void Save() override {\n    // Handled by the BBS in write_qscn(usernum, qsc, false);\n  }\n};\n\nbool Application::create_message_api() {\n  // TODO(rushfan): Create the right API type for the right message area.\n\n  msgapi::MessageApiOptions options;\n  // Delete ONE matches classic WWIV behavior.\n  options.overflow_strategy = msgapi::OverflowStrategy::delete_one;\n\n  // We only support type-2\n  msgapis_[2] = std::make_unique<msgapi::WWIVMessageApi>(\n      options, *config_, nets_->networks(), new BBSLastReadImpl());\n\n  fileapi_ = std::make_unique<files::FileApi>(config_->datadir());\n  return true;\n}\n\nseconds Application::extratimecall() const {\n  return duration_cast<seconds>(extratimecall_);\n}\n\nseconds Application::set_extratimecall(duration<double> et) {\n  extratimecall_ = et;\n  return duration_cast<seconds>(extratimecall_);\n}\n\nseconds Application::add_extratimecall(duration<double> et) {\n  extratimecall_ += et;\n  return duration_cast<seconds>(extratimecall_);\n}\n\nseconds Application::subtract_extratimecall(duration<double> et) {\n  extratimecall_ -= et;\n  return duration_cast<seconds>(extratimecall_);\n}\n\nvoid Application::read_networks() {\n  nets_ = std::make_unique<Networks>(*config());\n}\n\nbool Application::read_names() {\n  // Load the SDK Names class too.\n  names_.reset(new Names(*config_));\n  return true;\n}\n\nbool Application::read_dirs() {\n  dirs_ = std::make_unique<wwiv::sdk::files::Dirs>(config_->datadir(), config_->max_backups());\n  return dirs_->Load();\n}\n\nvoid Application::read_chains() {\n  chains = std::make_unique<Chains>(*config());\n  if (chains->IsInitialized()) {\n    chains->Save();\n  }\n}\n\nvoid Application::read_gfile() {\n  gfiles_ = std::make_unique<GFiles>(config()->datadir(), config()->max_backups());\n  gfiles_->Load();\n}\n\nstatic bool mkdir_or_warn(const std::filesystem::path& dir, const std::string& name) {\n  if (!File::Exists(dir)) {\n    if (!File::mkdirs(dir)) {\n      LOG(ERROR) << \"Your \" << name << \" dir isn't valid.\";\n      LOG(ERROR) << \"It is now set to: '\" << dir.string() << \"'\";\n      return false;\n    }\n  }\n  return true;\n}\n\nbool Application::InitializeBBS(bool cleanup_network) {\n  Cls();\n  std::clog << std::endl\n            << full_version() << \", Copyright (c) 1998-2023, WWIV Software Services.\"\n            << std::endl\n            << std::endl\n            << \"\\r\\nInitializing BBS...\" << std::endl;\n\n  instances_ = std::make_unique<Instances>(*config());\n  use_workspace = false;\n\n  bin.clearnsp();\n\n  // Set dirs in the session context first.\n  mkdir_or_warn(sess().dirs().temp_directory(), \"temp\");\n  mkdir_or_warn(sess().dirs().batch_directory(), \"batch\");\n  mkdir_or_warn(sess().dirs().scratch_directory(), \"scratch\");\n  mkdir_or_warn(sess().dirs().current_menu_gfiles_directory(), \"menus/gfiles\");\n  mkdir_or_warn(sess().dirs().current_menu_script_directory(), \"menus/scripts\");\n  // Note that the sess().dirs().current_menu_directory() won't be set till the user\n  // picks a menuset.\n  mkdir_or_warn(config_->menudir(), \"menus\");\n  write_inst(INST_LOC_INIT, 0, INST_FLAGS_NONE);\n\n  // make sure it is the new USERREC structure\n  VLOG(1) << \"Reading user scan pointers.\";\n  if (const auto qs_fn = FilePath(config()->datadir(), USER_QSC); !File::Exists(qs_fn)) {\n    LOG(ERROR) << \"Could not open file '\" << qs_fn << \"'\";\n    LOG(ERROR) << \"You must go into WWIVconfig and convert your userlist before running the BBS.\";\n    return false;\n  }\n\n  read_networks();\n  if (!create_message_api()) {\n    return false;\n  }\n\n  VLOG(1) << \"Reading status information.\";\n  a()->status_manager()->Run([&](Status& status) {\n    status.status_wwiv_version(wwiv_config_version());\n    status.ensure_callernum_valid();\n  });\n\n  VLOG(1) << \"Reading Gfiles.\";\n  read_gfile();\n\n  VLOG(1) << \"Reading user names.\";\n  if (!read_names()) {\n    return false;\n  }\n\n  VLOG(1) << \"Reading Message Areas.\";\n  if (!read_subs()) {\n    return false;\n  }\n\n  VLOG(1) << \"Reading File Areas.\";\n  if (!read_dirs()) {\n    return false;\n  }\n\n  VLOG(1) << \"Reading Chains.\";\n  read_chains();\n\n  VLOG(1) << \"Reading File Transfer Protocols.\";\n  read_nextern();\n  read_nintern();\n\n  VLOG(1) << \"Reading File Archivers.\";\n  read_arcs();\n\n  VLOG(1) << \"Reading Full Screen Message Editors.\";\n  read_editors();\n\n  if (!File::mkdirs(attach_dir_)) {\n    LOG(ERROR) << \"Your file attachment directory is invalid.\";\n    LOG(ERROR) << \"It is now set to: \" << attach_dir_ << \"'\";\n    return false;\n  }\n  File::set_current_directory(bbs_dir_);\n\n  check_phonenum(); // dupphone addition\n\n  VLOG(1) << \"Reading User Information.\";\n  ReadCurrentUser(1);\n\n  statusMgr->reload_status();\n  bout.localIO()->topdata(LocalIO::topdata_t::user);\n\n  // Set DSZLOG\n  dsz_logfile_name_ = FilePath(sess().dirs().temp_directory(), \"dsz.log\").string();\n  if (environment_variable(\"DSZLOG\").empty()) {\n    set_environment_variable(\"DSZLOG\", dsz_logfile_name_);\n  }\n  // SET BBS environment variable.\n  set_environment_variable(\"BBS\", full_version());\n  sess().InitalizeContext(*config());\n\n  network_extension_ = \".net\";\n  if (const auto wwiv_instance = environment_variable(\"WWIV_INSTANCE\"); !wwiv_instance.empty()) {\n    if (const auto inst_num = to_number<int>(wwiv_instance); inst_num > 0) {\n      network_extension_ = fmt::sprintf(\".%3.3d\", inst_num);\n      // Fix... Set the global instance variable to match this.  When you run WWIV with the\n      // -n<instance> parameter it sets the WWIV_INSTANCE environment variable, however it wasn't\n      // doing the reverse.\n      sess().instance_number(inst_num);\n    }\n  }\n\n  frequent_init();\n  VLOG(1) << \"Reading Conferences.\";\n  all_confs_ = std::make_unique<Conferences>(\n    config()->datadir(), *subs_, *dirs_, config()->max_backups());\n  if (!all_confs_->Load()) {\n    LOG(ERROR) << \"Error Loading Conferences\";\n  }\n\n  TempDisablePause disable_pause(bout);\n  const auto t = sess().dirs().temp_directory();\n  remove_from_temp(\"*.*\", sess().dirs().temp_directory(), false);\n  remove_from_temp(\"*.*\", sess().dirs().batch_directory(), false);\n  remove_from_temp(\"*.*\", sess().dirs().qwk_directory(), false);\n  remove_from_temp(\"*.*\", sess().dirs().scratch_directory(), false);\n\n  if (cleanup_network) {\n    cleanup_net();\n    sysoplog(false, \"\");\n    sysoplog(false, fmt::format(\"WWIV {}, inst {}, brought up at {} on {}.\", full_version(),\n                                sess().instance_number(), times(), fulldate()));\n  }\n\n  catsl();\n  VLOG(1) << \"Saving Instance information.\";\n  write_inst(INST_LOC_WFC, 0, INST_FLAGS_NONE);\n\n  wwiv::bbs::bbs_callbacks();\n\n  return true;\n}\n\n// begin dupphone additions\n\nvoid Application::check_phonenum() {\n  if (!File::Exists(FilePath(config()->datadir(), PHONENUM_DAT))) {\n    create_phone_file();\n  }\n}\n\n// TODO(rushfan): maybe move this to SDK, but pass in a vector of numbers.\nvoid Application::create_phone_file() {\n  phonerec p{};\n\n  File file(FilePath(config()->datadir(), USER_LST));\n  if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n    return;\n  }\n  const auto file_size = file.length();\n  file.Close();\n  const auto numOfRecords = static_cast<int16_t>(file_size / sizeof(userrec));\n\n  File phoneNumFile(FilePath(config()->datadir(), PHONENUM_DAT));\n  if (!phoneNumFile.Open(File::modeReadWrite | File::modeAppend | File::modeBinary |\n                         File::modeCreateFile)) {\n    return;\n  }\n\n  for (int16_t temp_user_number = 1; temp_user_number <= numOfRecords; temp_user_number++) {\n    if (auto o = users()->readuser(temp_user_number, UserManager::mask::non_deleted)) {\n      const auto& user = o.value();\n      p.usernum = temp_user_number;\n      auto voice_num = user.voice_phone();\n      auto data_num = user.data_phone();\n      if (!voice_num.empty() && voice_num.find(\"000-\") == std::string::npos) {\n        to_char_array(p.phone, voice_num);\n        phoneNumFile.Write(&p, sizeof(phonerec));\n      }\n      if (!data_num.empty() && !iequals(voice_num, data_num) && voice_num.find(\"000-\") == std::string::npos) {\n        to_char_array(p.phone, data_num);\n        phoneNumFile.Write(&p, sizeof(phonerec));\n      }\n    }\n  }\n}\n\n// end dupphone additions\n"
  },
  {
    "path": "bbs/xinitini.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_BBS_XINITINI_H\n#define INCLUDED_BBS_XINITINI_H\n\n//---SYSTEM OPTIONS--\nconstexpr const char* INI_STR_SPAWNOPT = \"SPAWNOPT\";\nconstexpr const char* INI_STR_NUCOLOR = \"NUCOLOR\";\nconstexpr const char* INI_STR_NUCOLORBW = \"NUCOLORBW\";\nconstexpr const char* INI_STR_TOPCOLOR = \"TOPCOLOR\";\nconstexpr const char* INI_STR_F1COLOR = \"F1COLOR\";\nconstexpr const char* INI_STR_EDITLINECOLOR = \"EDITLINECOLOR\";\nconstexpr const char* INI_STR_CHATSELCOLOR = \"CHATSELCOLOR\";\nconstexpr const char* INI_STR_MSG_COLOR = \"MSG_COLOR\";\n\n//---SYSTEM COMMANDS--\nconstexpr const char* INI_STR_UPLOAD_CMD = \"UPLOAD_CMD\";\nconstexpr const char* INI_STR_BEGINDAY_CMD = \"BEGINDAY_CMD\";\nconstexpr const char* INI_STR_NEWUSER_CMD = \"NEWUSER_CMD\";\nconstexpr const char* INI_STR_LOGON_CMD = \"LOGON_CMD\";\nconstexpr const char* INI_STR_LOGOFF_CMD = \"LOGOFF_CMD\";\nconstexpr const char* INI_STR_CLEANUP_CMD = \"CLEANUP_CMD\";\nconstexpr const char* INI_STR_V_SCAN_CMD = \"VSCAN_CMD\";\nconstexpr const char* INI_STR_TERMINAL_CMD = \"TERMINAL_CMD\";\n\n//---SYSTEM SETTINGS--\nconstexpr const char* INI_STR_FORCE_FBACK = \"FORCE_FBACK\";\n//constexpr const char* INI_STR_FORCE_NEWUSER = \"FORCE_NEWUSER\";\nconstexpr const char* INI_STR_USE_FORCE_SCAN = \"FORCE_SCAN\";\nconstexpr const char* INI_STR_FORCE_SCAN_SUBNUM = \"FORCE_SCAN_SUBNUM\";\n//constexpr const char* INI_STR_CHECK_DUP_PHONES = \"CHECK_HANGUP\";\n//constexpr const char* INI_STR_HANGUP_DUP_PHONES = \"HANGUP_DUP_PHONES\";\nconstexpr const char* INI_STR_POSTTIME_COMPENS = \"POSTTIME_COMPENS\";\nconstexpr const char* INI_STR_SHOW_HIER = \"SHOW_HIER\";\nconstexpr const char* INI_STR_IDZ_DESC = \"IDZ_DESC\";\n//constexpr const char* INI_STR_SETLDATE = \"SETLDATE\";\nconstexpr const char* INI_STR_READ_CD_IDZ = \"READ_CD_IDZ\";\nconstexpr const char* INI_STR_FSED_EXT_DESC = \"FSED_EXT_DESC\";\n//constexpr const char* INI_STR_FAST_TAG_RELIST = \"FAST_TAG_RELIST\";\nconstexpr const char* INI_STR_MAIL_PROMPT = \"MAIL_PROMPT\";\nconstexpr const char* INI_STR_SHOW_CITY_ST = \"SHOW_CITY_ST\";\nconstexpr const char* INI_STR_2WAY_CHAT = \"2WAY_CHAT\";\nconstexpr const char* INI_STR_NO_NEWUSER_FEEDBACK = \"NO_NEWUSER_FEEDBACK\";\nconstexpr const char* INI_STR_TITLEBAR = \"TITLEBAR\";\nconstexpr const char* INI_STR_LOG_DOWNLOADS = \"LOG_DOWNLOADS\";\n//constexpr const char* INI_STR_CLOSE_XFER = \"CLOSE_XFER\";\nconstexpr const char* INI_STR_ALL_UL_TO_SYSOP = \"ALL_UL_TO_SYSOP\";\nconstexpr const char* INI_STR_MSG_TAG = \"MSG_TAG\";\n//constexpr const char* INI_STR_CHAIN_REG = \"CHAIN_REG\";\nconstexpr const char* INI_STR_CAN_SAVE_SSM = \"CAN_SAVE_SSM\";\nconstexpr const char* INI_STR_TWO_COLOR_CHAT = \"TWO_COLOR_CHAT\";\nconstexpr const char* INI_STR_ALLOW_ALIASES = \"ALLOW_ALIASES\";\nconstexpr const char* INI_STR_FREE_PHONE = \"FREE_PHONE\";\nconstexpr const char* INI_STR_ALLOW_CC_BCC = \"ALLOW_CC_BCC\";\nconstexpr const char* INI_STR_ATTACH_DIR = \"ATTACH_DIR\";\nconstexpr const char* INI_STR_NETFOSS_DIR = \"NETFOSS_DIR\";\n\n\n//---SYSTEM MAXIMUMS--\nconstexpr const char* INI_STR_MAX_BATCH = \"MAX_BATCH\";\nconstexpr const char* INI_STR_MAX_EXTEND_LINES = \"MAX_EXTEND_LINES\";\nconstexpr const char* INI_STR_MAX_CHAINS = \"MAX_CHAINS\";\nconstexpr const char* INI_STR_MAX_GFILESEC = \"MAX_GFILESEC\";\n\n//---CALLOUT/WFC--\nconstexpr const char* INI_STR_SCREEN_SAVER_TIME = \"SCREEN_SAVER_TIME\";\n\n//---ASV SETTINGS---\nconstexpr const char* INI_STR_USE_SIMPLE_ASV = \"USE_SIMPLE_ASV\";\nconstexpr const char* INI_STR_SIMPLE_ASV = \"SIMPLE_ASV\";\nconstexpr const char* INI_STR_ADVANCED_ASV = \"ADVANCED_ASV\";\nconstexpr const char* INI_STR_AUTO_USER_PURGE = \"AUTO_USER_PURGE\";\nconstexpr const char* INI_STR_NO_PURGE_SL = \"NO_PURGE_SL\";\n\n// --- New WWIV 5 Settings ---\nconstexpr const char* INI_STR_BEGINDAYNODENUMBER = \"BEGINDAYNODENUMBER\";\nconstexpr const char* INI_STR_INTERNALZMODEM = \"INTERNALZMODEM\";\nconstexpr const char* INI_STR_INTERNAL_FSED = \"INTERNAL_FSED\";\nconstexpr const char* INI_STR_EXEC_LOG_SYNCFOSS = \"EXEC_LOG_SYNCFOSS\";\nconstexpr const char* INI_STR_EXEC_CHILD_WAIT_TIME =   \"EXEC_CHILD_WAIT_TIME\";\nconstexpr const char* INI_STR_NEW_SCAN_AT_LOGIN  = \"NEW_SCAN_AT_LOGIN\";\n\n#endif  // INCLUDED_BBS_XINITINI_H\n"
  },
  {
    "path": "binkp/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(SOURCES \n binkp.cpp\n binkp_commands.cpp\n binkp_config.cpp\n cram.cpp\n file_manager.cpp\n net_log.cpp\n ppp_config.cpp\n remote.cpp\n transfer_file.cpp\n wfile_transfer_file.cpp\n)\n\nadd_library(binkp_lib ${SOURCES})\ntarget_link_libraries(binkp_lib fmt::fmt-header-only)\nset_max_warnings(binkp_lib)\n\n# Tests\nif (WWIV_BUILD_TESTS)\n    add_executable(binkp_tests \n        binkp_test.cpp\n        binkp_config_test.cpp\n        cram_test.cpp\n        fake_connection.cpp\n        file_manager_test.cpp\n        transfer_file_test.cpp\n        net_log_test.cpp\n        ppp_config_test.cpp\n        binkp_test_main.cpp\n    )\n    set_max_warnings(binkp_tests)\n    target_link_libraries(binkp_tests binkp_lib core core_fixtures GTest::gmock GTest::gtest sdk)\n    \n    gtest_discover_tests(binkp_tests)\n\nendif()\n"
  },
  {
    "path": "binkp/binkp.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp.h\"\n\n#include \"binkp/binkp_commands.h\"\n#include \"binkp/binkp_config.h\"\n#include \"binkp/cram.h\"\n#include \"binkp/file_manager.h\"\n#include \"binkp/net_log.h\"\n#include \"binkp/transfer_file.h\"\n#include \"core/connection.h\"\n#include \"core/crc32.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/socket_exceptions.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/contact.h\"\n#include <algorithm>\n#include <chrono>\n#include <cstring>\n#include <functional>\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nnamespace wwiv::net {\n\nstatic int System(const std::string& bbsdir, const std::string& cmd) {\n  const auto path = FilePath(bbsdir, cmd).string();\n\n  const auto err = system(path.c_str());\n  VLOG(1) << \"       executed: '\" << path << \"' with an error code: \" << err;\n  return err;\n}\n\nstd::string expected_password_for(const net_call_out_rec* con) {\n  if (con != nullptr && !con->session_password.empty()) {\n    // If the password is not empty string.\n    return con->session_password;\n  }\n  // return default password of \"-\"\n  return \"-\";\n}\n\nBinkP::BinkP(Connection* conn, BinkConfig* config, BinkSide side,\n             const std::string& expected_remote_node,\n             received_transfer_file_factory_t& received_transfer_file_factory)\n    : config_(config), conn_(conn), side_(side), expected_remote_node_(expected_remote_node),\n      received_transfer_file_factory_(received_transfer_file_factory),\n      remote_(config, side_ == BinkSide::ANSWERING, expected_remote_node) {\n  if (side_ == BinkSide::ORIGINATING) {\n    crc_ = config_->crc();\n  }\n}\n\nBinkP::~BinkP() { files_to_send_.clear(); }\n\nbool BinkP::process_opt(const std::string& opt) {\n  VLOG(1) << \"OPT line: '\" << opt << \"'\";\n\n  const auto opts = SplitString(opt, \" \");\n  for (const auto& s : opts) {\n    if (starts_with(s, \"CRAM\")) {\n      LOG(INFO) << \"       CRAM Requested by Remote Side.\";\n      if (const auto last_dash = s.find_last_of('-'); last_dash != std::string::npos) {\n        // we really have CRAM-MD5\n        auto challenge = s.substr(last_dash + 1);\n        VLOG(1) << \"        challenge: '\" << challenge << \"'\";\n        cram_.set_challenge_data(challenge);\n        if (config_->cram_md5()) {\n          auth_type_ = AuthType::CRAM_MD5;\n        } else {\n          LOG(INFO) << \"       CRAM-MD5 disabled in net.ini; Using plain text passwords.\";\n        }\n      }\n    } else if (s == \"CRC\") {\n      if (config_->crc()) {\n        LOG(INFO) << \"       Enabling CRC support\";\n        // If we support crc. Let's use it at receiving time now.\n        crc_ = true;\n      } else {\n        LOG(INFO) << \"       Not enabling CRC support (disabled in net.ini).\";\n      }\n    } else {\n      LOG(INFO) << \"       Unknown OPT: '\" << s << \"'\";\n    }\n  }\n  return true;\n}\n\nbool BinkP::process_command(int16_t length, duration<double> d) {\n  if (!conn_->is_open()) {\n    LOG(INFO) << \"       process_frames(returning false, connection is not open.)\";\n    return false;\n  }\n  const auto command_id = conn_->read_uint8(d);\n  VLOG(3) << \"       process_frames(command_id: '\" << static_cast<int>(command_id) << \"')\";\n\n  // In the header, SIZE should be set to the total length of \"Data string\"\n  // plus one for the octet to store the command number.\n  // So we read one less than the original length as that\n  // included the command number.  If the length is 1, we shouldn't read 0\n  // and just let the log_line and command data be the empty string.  Argus likes\n  // to not put data after M_EOB and M_OK commands.\n  std::string s;\n  if (length > 1) {\n    s = conn_->receive(length - 1, d);\n  }\n\n  std::string log_line = s;\n  if (command_id == BinkpCommands::M_PWD) {\n    log_line = std::string(12, '*');\n  }\n  LOG(INFO) << \"RECV:  \" << BinkpCommands::command_id_to_name(command_id) << \": \" << log_line;\n  switch (command_id) {\n  case BinkpCommands::M_NUL: {\n    // TODO(rushfan): process these.\n    if (starts_with(s, \"OPT\")) {\n      s = s.substr(3);\n      StringTrimBegin(&s);\n\n      process_opt(s);\n    } else if (starts_with(s, \"SYS \")) {\n      remote_.set_system_name(s.substr(4));\n    } else if (starts_with(s, \"VER \")) {\n      remote_.set_version(s.substr(4));\n    }\n  } break;\n  case BinkpCommands::M_ADR: {\n    remote_.set_address_list(s);\n  } break;\n  case BinkpCommands::M_OK: {\n    ok_received_ = true;\n  } break;\n  case BinkpCommands::M_GET: {\n    HandleFileGetRequest(s);\n  } break;\n  case BinkpCommands::M_GOT: {\n    HandleFileGotRequest(s);\n  } break;\n  case BinkpCommands::M_EOB: {\n    eob_received_ = true;\n  } break;\n  case BinkpCommands::M_PWD: {\n    HandlePassword(s);\n  } break;\n  case BinkpCommands::M_FILE: {\n    HandleFileRequest(s);\n  } break;\n  case BinkpCommands::M_ERR: {\n    LOG(ERROR) << \"RECV:  M_ERR: \" << s;\n    error_received_ = true;\n  } break;\n  default: {\n    LOG(ERROR) << \"       ** Unhandled Command: \" << BinkpCommands::command_id_to_name(command_id)\n               << \": \" << s;\n  } break;\n  }\n  return true;\n}\n\nbool BinkP::process_data(int16_t length, duration<double> d) {\n  if (!conn_->is_open()) {\n    return false;\n  }\n  const auto s = conn_->receive(length, d);\n  LOG_IF(length != static_cast<int16_t>(s.size()), ERROR)\n      << \"RECV:  DATA PACKET; ** unexpected size** len: \" << s.size() << \"; expected: \" << length\n      << \" duration:\" << wwiv::core::to_string(d);\n  if (!current_receive_file_) {\n    LOG(ERROR) << \"ERROR: Received M_DATA with no current file.\";\n    return false;\n  }\n  current_receive_file_->WriteChunk(s);\n  if (current_receive_file_->length() >= current_receive_file_->expected_length()) {\n    LOG(INFO) << \"       file finished; bytes_received: \" << current_receive_file_->length();\n\n    auto data_line =\n        fmt::format(\"{} {} {}\", current_receive_file_->filename(), current_receive_file_->length(),\n                    current_receive_file_->timestamp());\n\n    const auto crc = current_receive_file_->crc();\n    // If we want to use CRCs and we don't have a zero CRC.\n    if (crc_ && crc != 0) {\n      data_line += fmt::sprintf(\" %08X\", current_receive_file_->crc());\n    }\n\n    // Increment the number of bytes received.\n    bytes_received_ += current_receive_file_->length();\n\n    // Close the current file, add the name to the list of received files.\n    if (!current_receive_file_->Close()) {\n      LOG(ERROR) << \"Failed to close file: \" << current_receive_file_->filename();\n    }\n\n    // If we have a crc; check it.\n    if (crc_ && crc != 0) {\n      const auto rdir = config_->receive_dir(remote_.network_name());\n      const auto dir = File::absolute(config_->config().root_directory(), rdir);\n      const File received_file(FilePath(dir, current_receive_file_->filename()));\n      if (const auto file_crc = crc32file(received_file.path()); file_crc == 0) {\n        LOG(ERROR) << \"Error calculating CRC32 of: \" << current_receive_file_->filename();\n      } else {\n        if (file_crc != current_receive_file_->crc()) {\n          // TODO(rushfan): Once we're sure this works, make it mark the file bad.\n          LOG(ERROR) << \"Wrong CRC32 of: \" << current_receive_file_->filename()\n                     << \"; expected: \" << std::hex << current_receive_file_->crc()\n                     << \"; actual: \" << std::hex << file_crc;\n        }\n      }\n    }\n\n    file_manager_->ReceiveFile(current_receive_file_->filename());\n\n    // Delete the reference to this file and signal the other side we received it.\n    current_receive_file_.reset();\n    send_command_packet(BinkpCommands::M_GOT, data_line);\n  } else {\n    //    VLOG(3) << \"       file still transferring; bytes_received: \" <<\n    //    current_receive_file_->length()\n    //        << \" and: \" << current_receive_file_->expected_length() << \" bytes expected.\";\n  }\n\n  return true;\n}\n\nbool BinkP::process_frames(duration<double> d) {\n  VLOG(3) << \"       process_frames(\" << wwiv::core::to_string(d) << \")\";\n  return process_frames([&]() -> bool { return false; }, d);\n}\n\nbool BinkP::process_frames(const std::function<bool()>& predicate, duration<double> d) {\n  if (!conn_->is_open()) {\n    return false;\n  }\n  try {\n    while (!predicate()) {\n      VLOG(3) << \"       process_frames(pred)\";\n      if (const auto header = conn_->read_uint16(d); header & 0x8000) {\n        if (!process_command(header & 0x7fff, d)) {\n          // false return value means an error occurred.\n          return false;\n        }\n      } else {\n        // process data frame.\n        // note: always use a timeout of 10s to process data since dropping bytes\n        // causes real problems.\n        if (!process_data(header & 0x7fff, seconds(10))) {\n          // false return value mean san error occurred.\n          return false;\n        }\n      }\n    }\n  } catch (const timeout_error& e) {\n    VLOG(3) << \"timeout in process_frames: \" << e.what();\n  }\n  return true;\n}\n\nbool BinkP::send_command_packet(uint8_t command_id, const std::string& data) {\n  if (!conn_->is_open()) {\n    return false;\n  }\n  const auto size = 3 + size_int(data); /* header + command + data + null*/\n  const auto packet = std::make_unique<uint8_t[]>(size);\n  // Actual packet size parameter does not include the size parameter itself.\n  // And for sending a command this will be 2 less than our actual packet size.\n  const auto packet_length = static_cast<uint16_t>(data.size() + sizeof(uint8_t)) | 0x8000;\n  const uint8_t b0 = ((packet_length & 0xff00) >> 8) | 0x80;\n  const uint8_t b1 = packet_length & 0x00ff;\n\n  auto* p = packet.get();\n  *p++ = b0;\n  *p++ = b1;\n  *p++ = command_id;\n  memcpy(p, data.data(), data.size());\n\n  conn_->send(packet.get(), size, seconds(3));\n  if (command_id != BinkpCommands::M_PWD) {\n    LOG(INFO) << \"SEND:  \" << BinkpCommands::command_id_to_name(command_id) << \": \" << data;\n  } else {\n    // Mask the password.\n    LOG(INFO) << \"SEND:  \" << BinkpCommands::command_id_to_name(command_id) << \": \"\n              << std::string(8, '*');\n  }\n  return true;\n}\n\nbool BinkP::send_data_packet(const char* data, int packet_length) {\n  if (!conn_->is_open()) {\n    return false;\n  }\n  // for now assume everything fits within a single frame.\n  const std::unique_ptr<char[]> packet(new char[packet_length + 2]);\n  packet_length &= 0x7fff;\n  uint8_t b0 = ((packet_length & 0xff00) >> 8);\n  uint8_t b1 = packet_length & 0x00ff;\n  auto* p = packet.get();\n  *p++ = b0;\n  *p++ = b1;\n  memcpy(p, data, packet_length);\n\n  conn_->send(packet.get(), packet_length + 2, seconds(10));\n  VLOG(3) << \"SEND:  data packet: packet_length: \" << packet_length;\n  return true;\n}\n\nBinkState BinkP::ConnInit() {\n  VLOG(1) << \"STATE: ConnInit\";\n  process_frames(seconds(2));\n  return BinkState::WAIT_CONN;\n}\n\nstatic std::string wwiv_version_string() { return full_version(); }\n\nstatic std::string wwiv_version_string_with_date() {\n  return fmt::format(\"{} ({})\", full_version(), wwiv_compile_datetime());\n}\n\nBinkState BinkP::WaitConn() {\n  VLOG(1) << \"STATE: WaitConn\";\n  // Send initial CRAM command.\n  if (side_ == BinkSide::ANSWERING) {\n    if (config_->cram_md5()) {\n      cram_.GenerateChallengeData();\n      const auto opt_cram = StrCat(\"OPT CRAM-MD5-\", cram_.challenge_data());\n      send_command_packet(BinkpCommands::M_NUL, opt_cram);\n    }\n  }\n  send_command_packet(BinkpCommands::M_NUL, StrCat(\"WWIVVER \", wwiv_version_string_with_date()));\n  send_command_packet(BinkpCommands::M_NUL, StrCat(\"SYS \", config_->system_name()));\n  const auto sysop_name_packet = StrCat(\"ZYZ \", config_->sysop_name());\n  send_command_packet(BinkpCommands::M_NUL, sysop_name_packet);\n  const auto version_packet = StrCat(\"VER networkb/\", wwiv_version_string(), \" binkp/1.0\");\n  send_command_packet(BinkpCommands::M_NUL, version_packet);\n  send_command_packet(BinkpCommands::M_NUL, \"LOC Unknown\");\n  if (config_->crc()) {\n    send_command_packet(BinkpCommands::M_NUL, \"OPT CRC\");\n  }\n\n  std::string network_addresses;\n  if (side_ == BinkSide::ANSWERING) {\n    // Present all addresses on answering side.\n    for (const auto& net : config_->networks().networks()) {\n      if (net.type == network_type_t::wwivnet) {\n        std::string lower_case_network_name = ToStringLowerCase(net.name);\n        send_command_packet(BinkpCommands::M_NUL, fmt::format(\"WWIV @{}.{}\", net.sysnum,\n                                                               lower_case_network_name));\n        if (!network_addresses.empty()) {\n          network_addresses.push_back(' ');\n        }\n        network_addresses += fmt::format(\"20000:20000/{}@{}\", net.sysnum, lower_case_network_name);\n      } else if (config_->config().is_5xx_or_later()) {\n        if (!network_addresses.empty()) {\n          network_addresses.push_back(' ');\n        }\n        try {\n          FidoAddress address(net.fido.fido_address);\n          network_addresses += address.as_string(true);\n        } catch (const bad_fidonet_address&) {\n          LOG(WARNING) << \"Bad FTN Address: '\" << net.fido.fido_address << \"' for network: '\"\n                       << net.name << \"'.\";\n        }\n      }\n    }\n  } else {\n    // Sending side:\n    const auto& net = config_->networks()[config_->callout_network_name()];\n    if (net.type == network_type_t::wwivnet) {\n      // Present single primary WWIVnet address.\n      send_command_packet(BinkpCommands::M_NUL,\n                          fmt::format(\"WWIV @{}.{}\", config_->callout_node_number(),\n                                      config_->callout_network_name()));\n      const auto lower_case_network_name = ToStringLowerCase(net.name);\n      network_addresses = fmt::format(\"20000:20000/{}@{}\", net.sysnum, lower_case_network_name);\n    } else if (config_->config().is_5xx_or_later()) {\n      // We don't support FTN on 4.x\n      try {\n        // Present single FTN address.\n        const FidoAddress address(net.fido.fido_address);\n        network_addresses = address.as_string(true);\n      } catch (const bad_fidonet_address& e) {\n        LOG(WARNING) << \"Bad FTN Address: '\" << net.fido.fido_address << \"' for network: '\"\n                     << net.name << \"'.\" << \"; exception: \" << e.what();\n        // We should terminate here, so rethrow the exception after\n        // letting the user know the network name that is borked.\n        throw;\n      }\n    }\n  }\n  send_command_packet(BinkpCommands::M_ADR, network_addresses);\n\n  // Try to process any inbound frames before leaving this state.\n  process_frames(milliseconds(100));\n  return BinkState::WAIT_ADDR;\n}\n\nBinkState BinkP::SendPasswd() {\n  // This is on the sending side.\n  VLOG(1) << \"STATE: SendPasswd for network '\" << remote_.network_name()\n          << \"' for node: \" << expected_remote_node_;\n  const auto* callout = at(config_->callouts(), remote_.domain()).get();\n  const auto password = expected_password_for(callout, expected_remote_node_);\n  VLOG(1) << \"       sending password packet for node: \" << expected_remote_node_;\n  switch (auth_type_) {\n  case AuthType::CRAM_MD5: {\n    const auto hashed_password = cram_.CreateHashedSecret(cram_.challenge_data(), password);\n    const auto hashed_password_command = StrCat(\"CRAM-MD5-\", hashed_password);\n    send_command_packet(BinkpCommands::M_PWD, hashed_password_command);\n  } break;\n  case AuthType::PLAIN_TEXT:\n    send_command_packet(BinkpCommands::M_PWD, password);\n    break;\n  }\n  return BinkState::AUTH_REMOTE;\n}\n\nBinkState BinkP::WaitAddr() {\n  VLOG(1) << \"STATE: WaitAddr\";\n  auto predicate = [&]() -> bool { return !remote_.address_list().empty(); };\n  for (auto i = 0; i < 10; i++) {\n    process_frames(predicate, seconds(1));\n    if (!remote_.address_list().empty()) {\n      break;\n    }\n  }\n  return side_ == BinkSide::ORIGINATING ? BinkState::SEND_PASSWORD : BinkState::AUTH_REMOTE;\n}\n\nbool BinkP::CheckPassword(const FidoAddress& address) {\n  VLOG(1) << \"       CheckPassword: \" << address;\n  const auto* callout = at(config_->callouts(), address.domain()).get();\n  const auto* ncn = callout->net_call_out_for(address.as_string(true));\n  const auto expected_password = expected_password_for(ncn);\n  if (auth_type_ == AuthType::PLAIN_TEXT) {\n    VLOG(2) << \"       PLAIN_TEXT expected_password = '\" << expected_password << \"'\";\n    if (remote_password_ == expected_password) {\n      return true;\n    }\n  } else if (auth_type_ == AuthType::CRAM_MD5) {\n    VLOG(1) << \"       CRAM_MD5 expected_password = '\" << expected_password << \"'\";\n    VLOG(1) << \"       received password: \" << remote_password_;\n    if (cram_.ValidatePassword(cram_.challenge_data(), expected_password, remote_password_)) {\n      return true;\n    }\n  }\n  VLOG(1) << \"Password doesn't match.  Received '\" << remote_password_ << \"' expected '\"\n          << expected_password << \"'.\";\n  return false;\n}\n\nBinkState BinkP::PasswordAck() {\n  VLOG(1) << \"STATE: PasswordAck\";\n  // This is only on the answering side.\n  // This should only happen in the originating side.\n  if (side_ != BinkSide::ANSWERING) {\n    LOG(ERROR) << \"**** ERROR: WaitPwd Called on ORIGINATING side\";\n  }\n\n  if (remote_.ftn_addresses().empty()) {\n    LOG(ERROR) << \"Unable to parse addresses.\";\n    send_command_packet(BinkpCommands::M_ERR, \"Unable to find common address to validate password.\");\n    return BinkState::DONE;\n  }\n\n  for (const auto& a : remote_.ftn_addresses()) {\n    VLOG(1) << \"       Checking password for address: \" << a;\n    if (!CheckPassword(a)) {\n      // Passwords do not match, send error.\n      send_command_packet(BinkpCommands::M_ERR,\n                          \"Incorrect password received.  Please check your configuration.\");\n      return BinkState::DONE;\n    }\n  }\n\n  if (auth_type_ == AuthType::CRAM_MD5) {\n    send_command_packet(BinkpCommands::M_OK, \"Passwords match; secure session.\");\n    // No need to wait for OK since we are the answering side.\n    return BinkState::TRANSFER_FILES;\n  }\n  // auth_type_ == AuthType::PLAIN_TEXT\n  // VLOG(3) << \"       PLAIN_TEXT expected_password = '\" << expected_password << \"'\";\n  // No need to wait for OK since we are the answering side.\n  send_command_packet(BinkpCommands::M_OK, \"Passwords match; insecure session\");\n  return BinkState::TRANSFER_FILES;\n}\n\nBinkState BinkP::WaitPwd() {\n  // This should only happen in the originating side.\n  if (side_ != BinkSide::ANSWERING) {\n    LOG(ERROR) << \"**** ERROR: WaitPwd Called on ORIGINATING side\";\n  }\n  VLOG(1) << \"STATE: WaitPwd\";\n  auto predicate = [&]() -> bool { return !remote_password_.empty(); };\n  for (auto i = 0; i < 30; i++) {\n    process_frames(predicate, seconds(1));\n    if (predicate()) {\n      break;\n    }\n  }\n\n  return BinkState::PASSWORD_ACK;\n}\n\nBinkState BinkP::WaitOk() {\n  // TODO(rushfan): add proper timeout to wait for OK.\n  VLOG(1) << \"STATE: WaitOk\";\n  for (int i = 0; i < 30; i++) {\n    process_frames([&]() -> bool { return ok_received_; }, seconds(1));\n    if (ok_received_) {\n      return BinkState::TRANSFER_FILES;\n    }\n  }\n\n  LOG(ERROR) << \"       after WaitOk: M_OK never received.\";\n  send_command_packet(BinkpCommands::M_ERR, \"M_OK never received. Timed out waiting for it.\");\n  return BinkState::DONE;\n}\n\nBinkState BinkP::IfSecure() {\n  VLOG(1) << \"STATE: IfSecure\";\n  // Wait for OK if we sent a password.\n  // Log an insecure session of there is no password.\n  return BinkState::WAIT_OK;\n}\n\nBinkState BinkP::AuthRemoteAnswering() {\n  VLOG(1) << \"       AuthRemoteAnswering\";\n\n  std::set<FidoAddress> known_addresses;\n  for (const auto& kv : config_->address_pw_map) {\n    known_addresses.insert(kv.first);\n  }\n\n  const auto addrs = ftn_addresses_from_address_list(remote_.address_list(), known_addresses);\n  VLOG(1) << \"       addrs.size: \" << addrs.size();\n  if (addrs.empty()) {\n    send_command_packet(\n        BinkpCommands::M_ERR,\n        StrCat(\"Error (NETWORKB-0004): Unable to find common nodes in: \", remote_.address_list()));\n    return BinkState::FATAL_ERROR;\n  }\n  if (addrs.size() == 1) {\n    const auto a = *addrs.begin();\n    // We only have one address, so set the domain or wwivnet node depending on\n    // the type of network.\n    if (a.zone() == 20000) {\n      remote_.set_wwivnet_node(a.node(), a.domain());\n    } else {\n      remote_.set_domain(a.domain());\n    }\n  }\n\n  remote_.set_ftn_addresses(addrs);\n  return BinkState::WAIT_PWD;\n}\n\nBinkState BinkP::AuthRemoteCalling() {\n  VLOG(1) << \"       AuthRemoteCalling\";\n  VLOG(1) << \"       expected_ftn: '\" << expected_remote_node_ << \"'\";\n  if (remote_.address_list().find(expected_remote_node_) != std::string::npos) {\n    return side_ == BinkSide::ORIGINATING ? BinkState::IF_SECURE : BinkState::WAIT_PWD;\n  }\n  send_command_packet(\n      BinkpCommands::M_ERR,\n      fmt::format(\"Error (NETWORKB-0001): Unexpected Addresses: '{}'; expected: '{}'\",\n                  remote_.address_list(), expected_remote_node_));\n  return BinkState::FATAL_ERROR;\n}\n\n\n// Check that the address matches who we thought we called.\nBinkState BinkP::AuthRemote() {\n  VLOG(1) << \"STATE: AuthRemote\";\n  VLOG(1) << \"       remote address_list: \" << remote_.address_list();\n  const auto result = side_ == BinkSide::ANSWERING ?  AuthRemoteAnswering() : AuthRemoteCalling();\n  if (result != BinkState::FATAL_ERROR) {\n    const auto rdir = config_->receive_dir(remote_.network().name);\n    VLOG(1) << \"       Creating file manager for network: \" << remote_.network().name << \"; dir: \" << rdir;\n    file_manager_ = std::make_unique<FileManager>(config_->config(), remote_.network(), rdir);\n  }\n  return result;\n}\n\nBinkState BinkP::TransferFiles() {\n  if (remote_.network().type == network_type_t::wwivnet) {\n    VLOG(1) << \"STATE: TransferFiles to node: \" << remote_.wwivnet_node() << \" :\" << remote_.network_name();\n  } else {\n    VLOG(1) << \"STATE: TransferFiles to node: \" << remote_.ftn_address() << \" :\" << remote_.network_name();\n  }\n  VLOG(1) << \"       receive dir: \" << config_->receive_dir(remote_.network_name());\n\n  // Quickly let the inbound event loop percolate.\n  process_frames(milliseconds(500));\n  const auto list = file_manager_->CreateTransferFileList(remote_);\n  for (auto* file : list) {\n    SendFilePacket(file);\n  }\n\n  VLOG(1) << \"STATE: After SendFilePacket for all files.\";\n  // Quickly let the inbound event loop percolate.\n  for (auto i = 0; i < 5; i++) {\n    process_frames(milliseconds(500));\n  }\n\n  // TODO(rushfan): Should this be in a new state?\n  if (files_to_send_.empty()) {\n    // All files are sent, let's let the remote know we are done.\n    VLOG(1) << \"       Sending EOB\";\n    // Kinda a hack, but trying to send a 3 byte packet was stalling on Windows.  Making it larger\n    // makes it send (yes, even with TCP_NODELAY set).\n    send_command_packet(BinkpCommands::M_EOB, \"All files to send have been sent. Thank you.\");\n    process_frames(seconds(1));\n  } else {\n    VLOG(1) << \"       files_to_send_ is not empty, Not sending EOB\";\n    std::ostringstream files;\n    for (const auto& f : files_to_send_) {\n      files << f.first << \" \";\n    }\n    VLOG(2) << \"Files: \" << files.str();\n  }\n  return BinkState::WAIT_EOB;\n}\n\nBinkState BinkP::Unknown() {\n  VLOG(1) << \"STATE: Unknown\";\n  auto count = 0;\n  auto predicate = [&]() -> bool { return count++ > 4; };\n  process_frames(predicate, seconds(3));\n  return BinkState::DONE;\n}\n\nBinkState BinkP::FatalError() {\n  LOG(ERROR) << \"STATE: FatalError\";\n  auto count = 0;\n  auto predicate = [&]() -> bool { return count++ > 4; };\n  process_frames(predicate, seconds(3));\n  return BinkState::DONE;\n}\n\nBinkState BinkP::WaitEob() {\n  VLOG(1) << \"STATE: WaitEob: ENTERING eob_received: \" << std::boolalpha << eob_received_;\n  if (eob_received_) {\n    // If we've already received an EOB, don't process_frames or do anything else.\n    // We're done.\n    return BinkState::DONE;\n  }\n\n  const auto eob_retries = 12;\n  const auto eob_wait_seconds = 5;\n  for (auto count = 1; count < eob_retries; count++) {\n    // Loop for up to one minute waiting for an EOB before exiting.\n    try {\n      process_frames([&]() -> bool { return eob_received_; }, seconds(eob_wait_seconds));\n      if (eob_received_) {\n        return BinkState::DONE;\n      }\n      LOG(INFO) << \"       WaitEob: still waiting for M_EOB to be received. will wait up to \"\n                << (eob_retries * eob_wait_seconds) << \" seconds.\";\n    } catch (const timeout_error& e) {\n      LOG(ERROR) << \"       WaitEob: ERROR while waiting for more data: \" << e.what();\n    }\n  }\n  return BinkState::DONE;\n}\n\nbool BinkP::SendFilePacket(TransferFile* file) {\n  const auto filename(file->filename());\n  VLOG(1) << \"       SendFilePacket: \" << filename;\n  files_to_send_[filename] = std::unique_ptr<TransferFile>(file);\n  send_command_packet(BinkpCommands::M_FILE, file->as_packet_data(0));\n  process_frames(seconds(2));\n\n  // file* may not be viable anymore if it was already send.\n  if (contains(files_to_send_, filename)) {\n    // We have the file still to send.\n    SendFileData(file);\n  }\n  return true;\n}\n\nbool BinkP::SendFileData(TransferFile* file) {\n  VLOG(1) << \"       SendFileData: \" << file->filename();\n  const auto file_length = file->file_size();\n  const auto chunk_size = 16384; // This is 1<<14.  The max per spec is (1 << 15) - 1\n  const auto chunk = std::make_unique<char[]>(chunk_size);\n  for (long start = 0; start < file_length; start += chunk_size) {\n    const auto size = std::min<int>(chunk_size, file_length - start);\n    if (!file->GetChunk(chunk.get(), start, size)) {\n      // Bad chunk. Abort\n    }\n    send_data_packet(chunk.get(), size);\n    // sending multi-chunk files was not reliable.  check after each frame if we have\n    // an inbound command.\n    process_frames(seconds(1));\n  }\n  return true;\n}\n\nbool BinkP::HandlePassword(const std::string& password_line) {\n  VLOG(1) << \"        HandlePassword: \";\n  VLOG(2) << \"        password_line: \" << password_line;\n  if (!starts_with(password_line, \"CRAM\")) {\n    LOG(INFO) << \"        HandlePassword: Received Plain text password\";\n    auth_type_ = AuthType::PLAIN_TEXT;\n    remote_password_ = password_line;\n    return true;\n  }\n\n  static const std::string CRAM_MD5_PREFIX = \"CRAM-MD5-\";\n  if (!starts_with(password_line, CRAM_MD5_PREFIX)) {\n    send_command_packet(BinkpCommands::M_ERR,\n                        \"CRAM authentication required, no common hash function\");\n    return false;\n  }\n  const auto hashed_password = password_line.substr(CRAM_MD5_PREFIX.size());\n  LOG(INFO) << \"        HandlePassword: Received CRAM-MD5 hashed password\";\n  auth_type_ = AuthType::CRAM_MD5;\n  remote_password_ = hashed_password;\n  return true;\n}\n\n// M_FILE received.\nbool BinkP::HandleFileRequest(const std::string& request_line) {\n  VLOG(1) << \"       HandleFileRequest; request_line: \" << request_line;\n  auto* old_file = current_receive_file_.release();\n  if (old_file != nullptr) {\n    LOG(ERROR) << \"** ERROR: Got HandleFileRequest while still having an open receive file!\";\n  }\n  std::string filename;\n  long expected_length;\n  time_t timestamp;\n  long starting_offset = 0;\n  uint32_t crc = 0;\n  if (!ParseFileRequestLine(request_line, &filename, &expected_length, &timestamp, &starting_offset,\n                            &crc)) {\n    return false;\n  }\n  const auto net = remote_.network_name();\n  auto* p = new ReceiveFile(received_transfer_file_factory_(net, filename), filename,\n                            expected_length, timestamp, crc);\n  current_receive_file_.reset(p);\n  return true;\n}\n\nbool BinkP::HandleFileGetRequest(const std::string& request_line) {\n  LOG(INFO) << \"       HandleFileGetRequest: request_line: [\" << request_line << \"]\";\n  const auto s = SplitString(request_line, \" \");\n  const auto& filename = s.at(0);\n  //const auto length = to_number<long>(s.at(1));\n  //const auto timestamp = to_number<time_t>(s.at(2));\n  long offset = 0;\n  if (s.size() >= 4) {\n    offset = to_number<long>(s.at(3));\n  }\n  if (offset != 0) {\n    LOG(WARNING) << \"offset specified in FileGetRequest.  We don't support offset != 0\";\n  }\n\n  const auto iter = files_to_send_.find(filename);\n  if (iter == end(files_to_send_)) {\n    LOG(ERROR) << \"File not found: \" << filename;\n    return false;\n  }\n  return SendFileData(iter->second.get());\n  // File was sent but wait until we receive M_GOT before we remove it from the list.\n}\n\nbool BinkP::HandleFileGotRequest(const std::string& request_line) {\n  LOG(INFO) << \"       HandleFileGotRequest: request_line: [\" << request_line << \"]\";\n  const auto s = SplitString(request_line, \" \");\n  const auto& filename = s.at(0);\n  const auto length = to_number<int>(s.at(1));\n\n  const auto iter = files_to_send_.find(filename);\n  if (iter == end(files_to_send_)) {\n    LOG(ERROR) << \"File not found: \" << filename;\n    return false;\n  }\n\n  auto* file = iter->second.get();\n  // Increment the number of bytes sent.\n  // Also don't increment with -1 if there's an error with the file.\n  bytes_sent_ += std::max(0, file->file_size());\n\n  if (length != file->file_size()) {\n    LOG(ERROR) << \"NON-FATAL ERROR: Size didn't match M_GOT. Please log a bug. M_GOT: \" << length\n               << \"; file_size: \" << file->file_size();\n  }\n\n  // This is a file that we sent.\n  if (!file->Delete()) {\n    LOG(ERROR) << \"       *** UNABLE TO DELETE FILE: \" << file->filename();\n  }\n  files_to_send_.erase(iter);\n  return true;\n}\n\nvoid BinkP::Run(const wwiv::core::CommandLine& cmdline) {\n  const auto now = DateTime::now();\n  config_->session_identifier(fmt::format(\"in-{}\", now.to_time_t()));\n  LOG(INFO) << \"session id:  \" << config_->session_identifier();\n\n  VLOG(1) << \"STATE: Run(): side:\" << static_cast<int>(side_);\n  auto state = (side_ == BinkSide::ORIGINATING) ? BinkState::CONN_INIT : BinkState::WAIT_CONN;\n  const auto start_time = system_clock::now();\n  try {\n    bool done = false;\n    while (!done) {\n      switch (state) {\n      case BinkState::CONN_INIT:\n        state = ConnInit();\n        break;\n      case BinkState::WAIT_CONN:\n        state = WaitConn();\n        break;\n      case BinkState::SEND_PASSWORD:\n        state = SendPasswd();\n        break;\n      case BinkState::WAIT_ADDR:\n        state = WaitAddr();\n        break;\n      case BinkState::AUTH_REMOTE:\n        state = AuthRemote();\n        break;\n      case BinkState::IF_SECURE:\n        state = IfSecure();\n        break;\n      case BinkState::WAIT_PWD:\n        state = WaitPwd();\n        break;\n      case BinkState::PASSWORD_ACK:\n        state = PasswordAck();\n        break;\n      case BinkState::WAIT_OK:\n        state = WaitOk();\n        break;\n      case BinkState::TRANSFER_FILES:\n        state = TransferFiles();\n        break;\n      case BinkState::WAIT_EOB:\n        state = WaitEob();\n        break;\n      case BinkState::UNKNOWN:\n        state = Unknown();\n        break;\n      case BinkState::FATAL_ERROR:\n        state = FatalError();\n        break;\n      case BinkState::DONE:\n        VLOG(1) << \"STATE: Done.\";\n        conn_->close();\n        done = true;\n        break;\n      }\n\n      if (error_received_) {\n        LOG(ERROR) << \"STATE: Error Received.\";\n        done = true;\n      }\n      process_frames(milliseconds(100));\n    }\n  } catch (const socket_closed_error& e) {\n    // The other end closed the socket before we did.\n    LOG(INFO) << \"       connection was closed by the other side.\";\n    VLOG(1)   << \"       details: \" << e.what();\n  } catch (const socket_error& e) {\n    LOG(ERROR) << \"STATE: BinkP::RunOriginatingLoop() socket_error: \" << e.what();\n  }\n\n  const auto network_log_side = side_ == BinkSide::ORIGINATING ? NetworkSide::TO : NetworkSide::FROM;\n  NetworkLog net_log(config_->gfiles_directory());\n  const auto end_time = system_clock::now();\n  const auto log_seconds = duration_cast<seconds>(end_time - start_time);\n  if (remote_.network().type == network_type_t::wwivnet) {\n    // Handle WWIVnet inbound files.\n    if (file_manager_) {\n      // file_manager_ is null in some tests (BinkpTest).\n      file_manager_->rename_wwivnet_pending_files();\n      if (!config_->skip_net()) {\n        process_network_files(cmdline);\n      }\n    }\n\n    // Log to net.log\n    // Update WWIVnet net.log and contact.net for WWIVnet connections.\n    net_log.Log(system_clock::to_time_t(start_time), network_log_side, remote_.wwivnet_node(),\n                bytes_sent_, bytes_received_, log_seconds, remote_.network_name());\n\n    // Update contact.net\n    Contact c(config_->network(remote_.network_name()), true);\n    const auto dt = DateTime::from_time_t(system_clock::to_time_t(start_time));\n    if (error_received_) {\n      c.add_failure(remote_.wwivnet_node(), dt);\n    } else {\n      c.add_connect(remote_.wwivnet_node(), dt, bytes_sent_, bytes_received_);\n    }\n  } else {\n\n    // Handle FTN inbound files.\n    if (file_manager_) {\n      // file_manager_ is null in some tests (BinkpTest).\n      file_manager_->rename_ftn_pending_files(remote_);\n      if (!config_->skip_net()) {\n        const auto network_number = config_->networks().network_number(remote_.network_name());\n        System(cmdline.bindir(), StrCat(\"networkc .\", network_number, \" --v=\", config_->verbose()));\n      }\n    }\n\n    // Log to net.log using fake outbound node (32765)\n    net_log.Log(system_clock::to_time_t(start_time), network_log_side, FTN_FAKE_OUTBOUND_NODE,\n                bytes_sent_, bytes_received_, log_seconds, remote_.network_name());\n\n  }\n\n  // Cleanup receive directory if it's not empty.\n  const auto rdir = config_->receive_dir(remote_.network_name());\n  if (!rdir.empty()) {\n    if (!File::Remove(rdir)) {\n      LOG(ERROR) << \"Unable to remove directory: \" << rdir;\n    }\n  }\n\n}\n\nvoid BinkP::process_network_files(const wwiv::core::CommandLine& cmdline) const {\n  const auto network_name = remote_.network_name();\n  VLOG(1) << \"STATE: process_network_files for network: \" << network_name;\n  const auto network_number = config_->networks().network_number(network_name);\n  if (network_number == wwiv::sdk::Networks::npos) {\n    return;\n  }\n  System(cmdline.bindir(), StrCat(\"networkc .\", network_number, \" --v=\", config_->verbose()));\n}\n\nbool ParseFileRequestLine(const std::string& request_line, std::string* filename, long* length,\n                          time_t* timestamp, long* offset, uint32_t* crc) {\n  auto s = SplitString(request_line, \" \");\n  if (s.size() < 3) {\n    LOG(ERROR) << \"ERROR: INVALID request_line: \" << request_line\n               << \"; had < 3 parts.  # parts: \" << s.size();\n    return false;\n  }\n  *filename = s.at(0);\n  *length = to_number<long>(s.at(1));\n  *timestamp = to_number<time_t>(s.at(2));\n  *offset = 0;\n  if (s.size() >= 4) {\n    *offset = to_number<long>(s.at(3));\n  }\n  if (s.size() >= 5) {\n    *crc = to_number<uint32_t>(s.at(4), 16);\n  }\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/binkp.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BINKP_BINKP_H\n#define INCLUDED_BINKP_BINKP_H\n\n#include \"core/command_line.h\"\n#include \"core/connection.h\"\n#include \"binkp/cram.h\"\n#include \"binkp/file_manager.h\"\n#include \"binkp/receive_file.h\"\n#include \"binkp/remote.h\"\n#include \"sdk/net/callout.h\"\n#include <chrono>\n#include <cstdint>\n#include <functional>\n#include <map>\n#include <memory>\n#include <string>\n\nnamespace wwiv::net {\n  \nclass BinkConfig;\nclass TransferFile;\n\nenum class BinkState {\n  CONN_INIT,\n  WAIT_CONN,\n  SEND_PASSWORD,\n  WAIT_ADDR,\n  AUTH_REMOTE,\n  IF_SECURE,\n  WAIT_OK,\n  WAIT_PWD,\n  PASSWORD_ACK,\n  TRANSFER_FILES,\n  WAIT_EOB,\n  UNKNOWN,\n  FATAL_ERROR,\n  DONE\n};\n\nenum class BinkSide {\n  ORIGINATING,\n  ANSWERING\n};\n\nenum class AuthType {\n  PLAIN_TEXT,\n  CRAM_MD5\n};\n\n// Main protocol driver class for BinkP derived sessions.\nclass BinkP {\npublic:\n  typedef std::function<TransferFile*(\n      const std::string& network_name, const std::string& filename)>\n      received_transfer_file_factory_t;\n  BinkP(wwiv::core::Connection* conn, BinkConfig* config, BinkSide side,\n        const std::string& expected_remote_node,\n        received_transfer_file_factory_t& received_transfer_file_factory);\n  virtual ~BinkP();\n\n  void Run(const wwiv::core::CommandLine& cmdline);\n\nprivate:\n  // Process frames until we time out waiting for a new frame.\n  bool process_frames(std::chrono::duration<double> d);\n  // Process frames until predicate is satisfied (returns true) or we time out waiting\n  // for a new frame.\n  bool process_frames(const std::function<bool()>& predicate, std::chrono::duration<double> d);\n \n  bool process_opt(const std::string& opt);\n  bool process_command(int16_t length, std::chrono::duration<double> d);\n  bool process_data(int16_t length, std::chrono::duration<double> d);\n\n  bool send_command_packet(uint8_t command_id, const std::string& data);\n  bool send_data_packet(const char* data, int size);\n\n  void process_network_files(const wwiv::core::CommandLine& cmdline) const;\n\n  BinkState ConnInit();\n  BinkState WaitConn();\n  BinkState SendPasswd();\n  BinkState WaitAddr();\n  BinkState WaitOk();\n  BinkState WaitPwd();\n  BinkState PasswordAck();\n  BinkState IfSecure();\n  BinkState AuthRemote();\n  BinkState AuthRemoteAnswering();\n  BinkState AuthRemoteCalling();\n  BinkState TransferFiles();\n  BinkState WaitEob();\n  BinkState Unknown();\n  BinkState FatalError();\n  bool SendFilePacket(TransferFile* file);\n  bool SendFileData(TransferFile* file);\n  bool HandleFileGetRequest(const std::string& request_line);\n  bool HandleFileGotRequest(const std::string& request_line);\n  bool HandlePassword(const std::string& password_line);\n  bool HandleFileRequest(const std::string& request_line);\n\n  bool CheckPassword(const sdk::fido::FidoAddress& address);\n\n  BinkConfig* config_ = nullptr;\n  wwiv::core::Connection* conn_ = nullptr;\n  bool ok_received_ = false;\n  bool eob_received_ = false;\n  std::map<std::string, std::unique_ptr<TransferFile>> files_to_send_;\n  BinkSide side_;\n  const std::string expected_remote_node_;\n  std::string remote_password_;\n  bool error_received_ = false;\n  received_transfer_file_factory_t received_transfer_file_factory_;\n  std::unique_ptr<ReceiveFile> current_receive_file_;\n  unsigned int bytes_received_ = 0;\n  unsigned int bytes_sent_ = 0;\n\n  // Handles CRAM-MD5 authentication\n  Cram cram_;\n  // Auth type used.\n  AuthType auth_type_ = AuthType::PLAIN_TEXT;\n  bool crc_ = false;\n\n  std::unique_ptr<FileManager> file_manager_;\n  Remote remote_;\n};\n\n// Parses a M_FILE request line into it's parts.\n// TODO(rushfan): Support the 5th CRC parameter in FRL-1022\n// See  http://www.filegate.net/ftsc/FRL-1022.001\nbool ParseFileRequestLine(const std::string& request_line, \n\t\t\t  std::string* filename,\n\t\t\t  long* length,\n\t\t\t  time_t* timestamp,\n\t\t\t  long* offset,\n        uint32_t* crc);\n\n// Returns just the expected password for a node (node) contained in the\n// callout.net file used by the wwiv::sdk::Callout class.\nstd::string expected_password_for(const sdk::net::net_call_out_rec* con);\n\ntemplate <typename N>\nstd::string expected_password_for(const wwiv::sdk::Callout* callout, N node) {\n  return expected_password_for(callout->net_call_out_for(node));\n}\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "binkp/binkp_commands.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp_commands.h\"\n#include <map>\n#include <string>\n\nnamespace wwiv::net {\n\nconst int BinkpCommands::M_NUL;\nconst int BinkpCommands::M_ADR;\nconst int BinkpCommands::M_PWD;\nconst int BinkpCommands::M_FILE;\nconst int BinkpCommands::M_OK;\nconst int BinkpCommands::M_EOB;\nconst int BinkpCommands::M_GOT;\nconst int BinkpCommands::M_ERR;\nconst int BinkpCommands::M_BSY;\nconst int BinkpCommands::M_GET;\nconst int BinkpCommands::M_SKIP;\n\n// static\nstd::string BinkpCommands::command_id_to_name(int command_id) {\n  static const std::map<int, std::string> map = {\n    {M_NUL, \"M_NUL\"},\n    {M_ADR, \"M_ADR\"},\n    {M_PWD, \"M_PWD\"},\n    {M_FILE, \"M_FILE\"},\n    {M_OK, \"M_OK\"},\n    {M_EOB, \"M_EOB\"},\n    {M_GOT, \"M_GOT\"},\n    {M_ERR, \"M_ERR\"},\n    {M_BSY, \"M_BSY\"},\n    {M_GET, \"M_GET\"},\n    {M_SKIP, \"M_SKIP\"},\n  };\n  return map.at(command_id);\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/binkp_commands.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORKB_BINKP_COMMANDS_H__\n#define __INCLUDED_NETWORKB_BINKP_COMMANDS_H__\n#pragma once\n\n#include <string>\n\nnamespace wwiv {\nnamespace net {\n\nclass BinkpCommands {\npublic:\nstatic const int M_NUL  = 0;\nstatic const int M_ADR  = 1;\nstatic const int M_PWD  = 2;\nstatic const int M_FILE = 3;\nstatic const int M_OK   = 4;\nstatic const int M_EOB  = 5;\nstatic const int M_GOT  = 6;\nstatic const int M_ERR  = 7;\nstatic const int M_BSY  = 8;\nstatic const int M_GET  = 9;\nstatic const int M_SKIP = 10;\n\nstatic std::string command_id_to_name(int command_id);\n\nprivate:\nBinkpCommands() {}\n~BinkpCommands() {}\n};\n\n}  // namespace net\n} // namespace wwiv\n\n#endif  // __INCLUDED_NETWORKB_BINKP_COMMANDS_H__"
  },
  {
    "path": "binkp/binkp_config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp_config.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"binkp/config_exceptions.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include <memory>\n#include <string>\n\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk::fido;\n\nnamespace wwiv::net {\n\nBinkConfig::BinkConfig(const std::string& callout_network_name, const Config& config,\n                       const Networks& networks)\n    : config_(config), callout_network_name_(ToStringLowerCase(callout_network_name)),\n      networks_(networks) {\n  // network names will alwyas be compared lower case.\n  system_name_ = config.system_name();\n  if (system_name_.empty()) {\n    system_name_ = \"Unnamed WWIV BBS\";\n  }\n  sysop_name_ = config.sysop_name();\n  if (sysop_name_.empty()) {\n    sysop_name_ = \"Unknown WWIV SysOp\";\n  }\n  gfiles_directory_ = config.gfilesdir();\n\n  if (networks.contains(callout_network_name)) {\n    const Network& net = networks[callout_network_name];\n    if (net.type == network_type_t::wwivnet) {\n      callout_wwivnet_node_ = net.sysnum;\n      if (callout_wwivnet_node_ == 0) {\n        throw config_error(\n            fmt::format(\"NODE not specified for network: '{}'\", callout_network_name));\n      }\n      binkp_.reset(new Binkp(net.dir));\n    } else if (net.type == network_type_t::ftn) {\n      callout_fido_node_ = net.fido.fido_address;\n      if (callout_fido_node_.empty()) {\n        throw config_error(\n            fmt::format(\"NODE not specified for network: '{}'\", callout_network_name));\n      }\n    } else {\n      throw config_error(\"BinkP is not supported for this network type.\");\n    }\n    // TODO(rushfan): This needs to be a shim binkp that reads from the nodelist\n    // or overrides.\n    binkp_.reset(new Binkp(net.dir));\n  }\n}\n\nconst Network& BinkConfig::network(const std::string& network_name) const {\n  return networks_[network_name];\n}\n\nconst Network& BinkConfig::callout_network() const {\n  return network(callout_network_name_);\n}\n\nvoid BinkConfig::session_identifier(std::string id) {\n  session_identifier_ = std::move(id);\n}\n\nstd::filesystem::path BinkConfig::network_dir(const std::string& network_name) const {\n  return network(network_name).dir;\n}\n\nstd::string BinkConfig::receive_dir(const std::string& network_name) const {\n  auto dir = wwiv::core::FilePath(network_dir(network_name), session_identifier_).string();\n  VLOG(1) << \"       BinkConfig::receive_dir: \" << dir;\n  return dir;\n}\n\nstatic Network test_net(const std::string& network_dir) {\n  Network net(network_type_t::wwivnet, \"WWIVnet\");\n  net.sysnum = 1;\n  net.dir = network_dir;\n  return net;\n}\n\n// For testing\nBinkConfig::BinkConfig(int node_number, const wwiv::sdk::Config& config,\n                       const std::string& network_dir)\n    : config_(config), callout_wwivnet_node_(node_number),\n      networks_({test_net(network_dir)}) {\n  binkp_.reset(new Binkp(network_dir));\n  system_name_ = config.system_name();\n  sysop_name_ = config.sysop_name();\n  gfiles_directory_ = config.gfilesdir();\n}\n\nBinkConfig::~BinkConfig() = default;\n\nconst binkp_session_config_t* BinkConfig::binkp_session_config_for(const std::string& node) const {\n  static binkp_session_config_t static_session{};\n\n  if (callout_network().type == network_type_t::wwivnet) {\n    if (!binkp_) {\n      return nullptr;\n    }\n    return binkp_->binkp_session_config_for(node);\n  } else if (callout_network().type == network_type_t::ftn) {\n    try {\n      FidoAddress address(node);\n      FidoCallout fc(config_.root_directory(), config_.max_backups(), callout_network());\n      if (!fc.IsInitialized())\n        return nullptr;\n      auto fido_node = fc.fido_node_config_for(address);\n\n      if (fido_node.binkp_config.host.empty()) {\n        // We must have a host at least, otherwise we know this\n        // is a completely empty record and we must return nullptr\n        // since the node config is not found.\n        return nullptr;\n      }\n\n      static_session = fido_node.binkp_config;\n      if (static_session.port == 0) {\n        // Set to default port.\n        static_session.port = 24554;\n      }\n\n      if (static_session.port == 0 && static_session.host.empty()) {\n        return nullptr;\n      }\n\n      return &static_session;\n    } catch (const std::exception&) {\n      return nullptr;\n    }\n  }\n  return nullptr;\n}\n\nconst binkp_session_config_t* BinkConfig::binkp_session_config_for(uint16_t node) const {\n  return binkp_session_config_for(std::to_string(node));\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/binkp_config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORKB_BINKP_CONFIG_H\n#define INCLUDED_NETWORKB_BINKP_CONFIG_H\n\n#include \"sdk/net/binkp.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/networks.h\"\n#include <cstdint>\n#include <filesystem>\n#include <map>\n#include <memory>\n#include <string>\n\nnamespace wwiv::net {\n\nclass BinkConfig final {\npublic:\n  BinkConfig(const std::string& callout_network_name, const wwiv::sdk::Config& config,\n             const wwiv::sdk::Networks& networks);\n  BinkConfig(int node_number, const wwiv::sdk::Config& config, const std::string& network_dir);\n  ~BinkConfig();\n  // Gets the binkp_session_config_t or nullptr if one can not be found.\n  [[nodiscard]] const sdk::net::binkp_session_config_t* binkp_session_config_for(const std::string& node) const;\n  // Gets the binkp_session_config_t or nullptr if one can not be found.\n  [[nodiscard]] const sdk::net::binkp_session_config_t* binkp_session_config_for(uint16_t node) const;\n\n  [[nodiscard]] int callout_node_number() const { return callout_wwivnet_node_; }\n  [[nodiscard]] std::string callout_fido_address() const { return callout_fido_node_; }\n  [[nodiscard]] std::string system_name() const { return system_name_; }\n  [[nodiscard]] std::string sysop_name() const { return sysop_name_; }\n  [[nodiscard]] std::filesystem::path gfiles_directory() const { return gfiles_directory_; }\n  [[nodiscard]] std::string callout_network_name() const { return callout_network_name_; }\n  /** Gets net.dir in absolute form for the network named network_name */\n  [[nodiscard]] std::filesystem::path network_dir(const std::string& network_name) const;\n  /** Get the directory to receive files into for network named network_name */\n  [[nodiscard]] std::string receive_dir(const std::string& network_name) const;\n\n  [[nodiscard]] const sdk::net::Network& network(const std::string& network_name) const;\n  [[nodiscard]] const sdk::net::Network& callout_network() const;\n  [[nodiscard]] const wwiv::sdk::Networks& networks() { return networks_; }\n  /*\n   * Key/Value mapping of domain to callout class.\n   * The domain and network name *should* match, but not always, so prefer domain\n   * if you have both.\n   */\n  std::map<const std::string, std::unique_ptr<sdk::Callout>>& callouts() { return callouts_; }\n\n  void set_skip_net(bool skip_net) { skip_net_ = skip_net; }\n  [[nodiscard]] bool skip_net() const { return skip_net_; }\n  void set_verbose(int verbose) { verbose_ = verbose; }\n  [[nodiscard]] int verbose() const { return verbose_; }\n  void set_network_version(int network_version) { network_version_ = network_version; }\n  [[nodiscard]] int network_version() const { return network_version_; }\n  [[nodiscard]] bool crc() const { return crc_; }\n  [[nodiscard]] bool cram_md5() const { return cram_md5_; }\n  [[nodiscard]] const sdk::Config& config() const { return config_; }\n\n  [[nodiscard]] std::string session_identifier() const { return session_identifier_; }\n  void session_identifier(std::string id);\n\n  std::map<sdk::fido::FidoAddress, std::string> address_pw_map;\n\nprivate:\n  const sdk::Config& config_;\n\n  int callout_wwivnet_node_{0};\n  std::string callout_fido_node_;\n  std::string system_name_;\n  std::string callout_network_name_ = \"wwivnet\";\n  std::string sysop_name_;\n  std::filesystem::path gfiles_directory_;\n  const wwiv::sdk::Networks networks_;\n  std::map<const std::string, std::unique_ptr<wwiv::sdk::Callout>> callouts_;\n  std::unique_ptr<wwiv::sdk::Binkp> binkp_;\n\n  bool skip_net_{false};\n  int verbose_{0};\n  int network_version_{38};\n  bool crc_{true};\n  bool cram_md5_{true};\n  std::string session_identifier_;\n};\n\n} // namespace \n\n#endif // INCLUDED_NETWORKB_BINKP_CONFIG_H\n"
  },
  {
    "path": "binkp/binkp_config_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"binkp/binkp_config.h\"\n#include \"sdk/config.h\"\n#include <string>\n\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nclass ParseBinkConfigLineTest : public testing::Test {};\n\nTEST_F(ParseBinkConfigLineTest, NoPort) {\n  const std::string line = \"@1234 myhost\";\n  auto r = ParseBinkConfigLine(line);\n  ASSERT_TRUE(r.has_value());\n  auto& [node, config] = r.value();\n  EXPECT_EQ(\"1234\", node);\n  EXPECT_EQ(\"myhost\", config.host);\n  EXPECT_EQ(24554, config.port);\n}\n\nTEST_F(ParseBinkConfigLineTest, Port) {\n  const std::string line = \"@1234 myhost:2345\";\n  auto r = ParseBinkConfigLine(line);\n  ASSERT_TRUE(r.has_value());\n  auto& [node, config] = r.value();\n  EXPECT_EQ(\"1234\", node);\n  EXPECT_EQ(\"myhost\", config.host);\n  EXPECT_EQ(2345, config.port);\n}\n\nTEST_F(ParseBinkConfigLineTest, InvalidLine) {\n  const std::string line = \"*@1234 myhost\";\n  const auto r = ParseBinkConfigLine(line);\n  ASSERT_FALSE(r.has_value());\n}\n\nTEST(BinkConfigTest, NodeConfig) {\n  wwiv::core::test::FileHelper files;\n  ASSERT_TRUE(files.Mkdir(\"network\"));\n  const std::string line(\"@2 example.com\");\n  files.CreateTempFile(\"network/binkp.net\", line);\n  const auto network_dir = files.DirName(\"network\");\n  const Config wwiv_config(files.TempDir());\n  const BinkConfig config(1, wwiv_config, network_dir);\n  const auto* node_config = config.binkp_session_config_for(2);\n  ASSERT_TRUE(node_config != nullptr);\n  EXPECT_EQ(\"example.com\", node_config->host);\n  EXPECT_EQ(24554, node_config->port);\n}\n"
  },
  {
    "path": "binkp/binkp_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp.h\"\n#include \"binkp/binkp_commands.h\"\n#include \"binkp/binkp_config.h\"\n#include \"binkp/transfer_file.h\"\n#include \"binkp/fake_connection.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/net/callout.h\"\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n#include <string>\n#include <thread>\n\nusing wwiv::sdk::Callout;\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nstatic const std::string ANSWERING_ADDRESS = \"20000/20000:1\";\nstatic const int ORIGINATING_ADDRESS = 2;\n\nclass BinkTest : public testing::Test {\nprotected:\n  void StartBinkpReceiver() {\n    CHECK(files_.Mkdir(\"network\"));\n    CHECK(files_.Mkdir(\"gfiles\"));\n    const std::string line(\"@1 example.com\");\n    files_.CreateTempFile(\"binkp.net\", line);\n    const auto network_dir = files_.DirName(\"network\");\n    const auto gfiles_dir = files_.DirName(\"gfiles\");\n    wwiv::sdk::config_t wwiv_config_{};\n    wwiv_config_.systemname = \"Test System\";\n    wwiv_config_.sysopname = \"Test Sysop\";\n    wwiv::sdk::Config config(File::current_directory(), wwiv_config_);\n    config.gfilesdir(gfiles_dir);\n    Network net(network_type_t::wwivnet, \"Dummy Network\");\n    net.dir = network_dir;\n    binkp_config_ = std::make_unique<BinkConfig>(ORIGINATING_ADDRESS, config, network_dir);\n    auto dummy_callout = std::make_unique<Callout>(net, 0);\n    BinkP::received_transfer_file_factory_t null_factory = [](const std::string&, const std::string& filename) { \n      return new InMemoryTransferFile(filename, \"\");\n    };\n    binkp_config_->callouts()[\"wwivnet\"] = std::move(dummy_callout);\n    binkp_.reset(new BinkP(&conn_, binkp_config_.get(), BinkSide::ANSWERING, ANSWERING_ADDRESS, null_factory));\n    CommandLine cmdline({ \"networkb_tests.exe\" }, \"\");\n    thread_ = std::thread([&]() { binkp_->Run(cmdline); });\n  } \n\n  void Stop() {\n    thread_.join();\n  }\n\n  std::unique_ptr<BinkP> binkp_;\n  std::unique_ptr<BinkConfig> binkp_config_;\n  FakeConnection conn_;\n  std::thread thread_;\n  wwiv::core::test::FileHelper files_;\n};\n\nTEST_F(BinkTest, ErrorAbortsSession) {\n  StartBinkpReceiver();\n  conn_.ReplyCommand(BinkpCommands::M_ERR, \"Doh!\");\n  Stop();\n  \n  while (conn_.has_sent_packets()) {\n    std::clog << conn_.GetNextPacket().debug_string() << std::endl;\n  }\n}\n\nstatic int node_number_from_address_list(const std::string& addresses,\n                                         const std::string& network_name) {\n  const auto a = ftn_address_from_address_list(addresses, network_name);\n  return wwivnet_node_number_from_ftn_address(a);\n}\n\nTEST(NodeFromAddressTest, SingleAddress) {\n  const std::string address = \"20000:20000/1234@foonet\";\n  EXPECT_EQ(1234, node_number_from_address_list(address, \"foonet\"));\n  EXPECT_EQ(WWIVNET_NO_NODE, node_number_from_address_list(address, \"wwivnet\"));\n}\n\nTEST(NodeFromAddressTest, MultipleAddresses) {\n  const std::string address = \"1:369/23@fidonet 20000:20000/1234@foonet 20000:369/24@dorknet\";\n  EXPECT_EQ(\"20000:20000/1234@foonet\", ftn_address_from_address_list(address, \"foonet\"));\n  EXPECT_EQ(1234, node_number_from_address_list(address, \"foonet\"));\n  EXPECT_EQ(WWIVNET_NO_NODE, node_number_from_address_list(address, \"wwivnet\"));\n  EXPECT_EQ(WWIVNET_NO_NODE, node_number_from_address_list(address, \"fidonet\"));\n  EXPECT_EQ(WWIVNET_NO_NODE, node_number_from_address_list(address, \"dorknet\"));\n}\n\nTEST(NodeFromAddressTest, MultipleAddresses_SameNetwork) {\n  const std::string address = \"1:369/-1@coolnet 1:369/23@coolnet\";\n  EXPECT_EQ(\"1:369/23@coolnet\", ftn_address_from_address_list(address, \"coolnet\"));\n}\n\n// string expected_password_for(Callout* callout, int node)\nTEST(ExpectedPasswordTest, Basic) {\n  const net_call_out_rec n{ \"20000:20000/1234\", 1234, 1, unused_options_sendback, 2, 3, 4, \"pass\", 5, 6 };\n  Callout callout({ n });\n  const std::string actual = expected_password_for(&callout, 1234);\n  EXPECT_EQ(\"pass\", actual);\n}\n\nTEST(ExpectedPasswordTest, WrongNode) {\n  const net_call_out_rec n{\"20000:20000/1234\", 1234, 1, unused_options_sendback, 2, 3, 4, \"pass\", 5, 6 };\n  Callout callout({ n });\n  const std::string actual = expected_password_for(&callout, 12345);\n  EXPECT_EQ(\"-\", actual);\n}\n\n\nTEST(FtnFromAddressListSet, Smoke) {\n  const std::string address = \"3:57/0@fidonet 3:770/1@fidonet 3:770/0@fidonet 3:772/1@fidonet \"\n                              \"3:772/0@fidonet 21:1/100@fsxnet 21:1/3@fsxnet 21:1/2@fsxnet \"\n                              \"21:1/1@fsxnet 21:1/0@fsxnet 39:970/0@amiganet 46:3/103@agoranet\";\n  const FidoAddress a(\"21:1/0@fsxnet\");\n  const std::set addresses{FidoAddress(\"21:1/0@fsxnet\")};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  EXPECT_THAT(known, testing::ElementsAre(a));\n}\n\n\nTEST(FtnFromAddressListSet, Smoke_Same) {\n  const std::string address = \"3:57/0@fidonet 3:770/1@fidonet 3:770/0@fidonet 3:772/1@fidonet \"\n                              \"3:772/0@fidonet 21:1/100@fsxnet 21:1/3@fsxnet 21:1/2@fsxnet \"\n                              \"21:1/1@fsxnet 21:1/0@fsxnet 39:970/0@amiganet 46:3/103@agoranet\";\n  const FidoAddress a(\"21:1/0@fsxnet\");\n  const std::set addresses{FidoAddress(a)};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  EXPECT_THAT(known, testing::ElementsAre(a));\n}\n\nTEST(FtnFromAddressListSet, WithoutDomainInKnown) {\n  const std::string address = \"3:57/0@fidonet 3:770/1@fidonet 3:770/0@fidonet 3:772/1@fidonet \"\n                              \"3:772/0@fidonet 21:1/100@fsxnet 21:1/3@fsxnet 21:1/2@fsxnet \"\n                              \"21:1/1@fsxnet 21:1/0@fsxnet 39:970/0@amiganet 46:3/103@agoranet\";\n  const FidoAddress a(\"21:1/2\");\n  const std::set addresses{FidoAddress(a)};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  const FidoAddress expected(\"21:1/2@fsxnet\");\n  EXPECT_THAT(known, testing::ElementsAre(expected));\n}\n\nTEST(FtnFromAddressListSet, WithoutDomainInADR) {\n  const std::string address = \"3:57/0 3:770/1 3:770/0 3:772/1 \"\n                              \"3:772/0 21:1/100 21:1/3 21:1/2 \"\n                              \"21:1/1 21:1/0 39:970/0 46:3/103\";\n  const FidoAddress a(\"21:1/2@fsxnet\");\n  const std::set addresses{FidoAddress(a)};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  EXPECT_THAT(known, testing::ElementsAre(a));\n}\n\nTEST(FtnFromAddressListSet, WithoutDomain_NotFound) {\n  const std::string address = \"3:57/0@fidonet 3:770/1@fidonet 3:770/0@fidonet 3:772/1@fidonet \"\n                              \"3:772/0@fidonet 21:1/100@fsxnet 21:1/3@fsxnet 21:1/2@fsxnet \"\n                              \"21:1/1@fsxnet 21:1/0@fsxnet 39:970/0@amiganet 46:3/103@agoranet\";\n  const FidoAddress a(\"21:1/2112\");\n  const std::set addresses{FidoAddress(a)};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  EXPECT_THAT(known, testing::IsEmpty());\n}\n\nTEST(FtnFromAddressListSet, WithoutDomainInADR_NotFound) {\n  const std::string address = \"3:57/0 3:770/1 3:770/0 3:772/1 \"\n                              \"3:772/0 21:1/100 21:1/3 21:1/2 \"\n                              \"21:1/1 21:1/0 39:970/0 46:3/103\";\n  const FidoAddress a(\"21:1/2001@fsxnet\");\n  const std::set addresses{FidoAddress(a)};\n  const auto known = ftn_addresses_from_address_list(address, addresses);\n  EXPECT_THAT(known, testing::IsEmpty());\n}\n"
  },
  {
    "path": "binkp/binkp_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/log.h\"\n#include \"core/test/file_helper.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  testing::InitGoogleTest(&argc, argv);\n  LoggerConfig log_config{};\n  log_config.log_startup = false;\n  Logger::Init(argc, argv, log_config);\n\n  tzset();\n  wwiv::core::test::FileHelper::set_wwiv_test_tempdir_from_commandline(argc, argv);\n  return RUN_ALL_TESTS();\n} \n"
  },
  {
    "path": "binkp/config_exceptions.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETORKB_CONFIG_EXCEPTIONS_H__\n#define __INCLUDED_NETORKB_CONFIG_EXCEPTIONS_H__\n\n#include <exception>\n#include <stdexcept>\n\nnamespace wwiv {\nnamespace net {\n\n\nstruct config_error : public std::runtime_error {\n config_error(const std::string& message) : std::runtime_error(message) {}\n};\n\n}  // namespace net\n}  // namespace wwiv\n\n\n#endif  // __INCLUDED_NETORKB_CONFIG_EXCEPTIONS_H__\n"
  },
  {
    "path": "binkp/cram.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"binkp/cram.h\"\n\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/md5.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include <cstring>\n#include <iomanip>\n#include <sstream>\n#include <string>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::net {\n\nbool Cram::GenerateChallengeData() {\n  if (challenge_data_.empty()) {\n    const auto raw = fmt::format(\"WWIV {} {} {}\", core::full_version(),\n                                 os::random_number(std::numeric_limits<int>::max()),\n                                 core::DateTime::now().to_string()); \n    challenge_data_ = md5(raw);\n  }\n  initialized_ = true;\n  return true;\n}\n\nbool Cram::ValidatePassword(const std::string& challenge,\n                            const std::string& secret, \n                            const std::string& given_hashed_secret) {\n  const auto expected = CreateHashedSecret(challenge, secret);\n  VLOG(1) << \"       CRAM Challenge: \" << challenge;\n  VLOG(1) << \"       expected pw: \" << expected << \"; given: \" << given_hashed_secret;\n  return expected == given_hashed_secret;\n}\n \nstatic std::string FromHex(const std::string& hex) {\n  if ((hex.length() % 2) != 0) {\n    throw std::logic_error(\n        StrCat(\"FromHex needs length of size a multiple of 2.  hex: '\", hex, \"' len:\", hex.size()));\n  }\n\n  if (hex.length() > 256) {\n    throw std::logic_error(\"FromHex needs length of < 256\");\n  }\n\n  char result[128];\n  auto len = 0;\n  auto it = hex.begin();\n  while (it != hex.end()) {\n    std::string s;\n    s.push_back(*it++);\n    s.push_back(*it++);\n\n    const auto chl = to_number<unsigned long>(s, 16);\n    const char ch = chl & 0xff;\n    result[len++] = ch;\n  }\n  return std::string(result, len);\n}\n\nstatic std::string SecretOrHash(const std::string& secret) {\n  if (secret.size() <= 64) {\n    return secret;\n  }\n\n  VLOG(1) << \"secret is >64 bytes\";\n\n  MD5_CTX ctx;\n  MD5_Init(&ctx);\n\n  unsigned char hash[16];\n  MD5_Update(&ctx, &secret[0], secret.size());\n  MD5_Final(hash, &ctx);\n\n  return std::string(reinterpret_cast<const char*>(hash), 16);\n}\n\nstd::string Cram::CreateHashedSecret(\n    const std::string& original_challenge_hex, const std::string& secret) {\n  if (!initialized_) {\n    if (!GenerateChallengeData()) {\n      // TODO: Go Boom\n    }\n  }\n  \n  auto c = StringTrim(original_challenge_hex);\n  while (c.back() == '\\0') {\n    // Radius adds a trailing null character here.\n    c.pop_back();\n  }\n  const auto original_challenge = FromHex(c);\n\n  auto challenge = SecretOrHash(original_challenge);\n  unsigned char ipad[65];\n  unsigned char opad[65];\n  memset(ipad, 0, sizeof(ipad));\n  memset(opad, 0, sizeof(opad));\n  memcpy(ipad, secret.data(), secret.size());\n  memcpy(opad, secret.data(), secret.size());\n\n  for (auto i = 0; i < 65; i++) {\n    ipad[i] ^= 0x36;\n    opad[i] ^= 0x5c;\n  }\n\n  // Inner\n  MD5_CTX ctx;\n  unsigned char digest[17];\n  MD5_Init(&ctx);\n  MD5_Update(&ctx, ipad, 64);\n  MD5_Update(&ctx, challenge.data(), challenge.size());\n  MD5_Final(digest, &ctx);\n\n  // Outer\n  MD5_Init(&ctx);\n  MD5_Update(&ctx, opad, 64);\n  MD5_Update(&ctx, digest, 16);\n  MD5_Final(digest, &ctx);\n\n  std::ostringstream ss;\n  for (int i = 0; i < 16; i++) {\n    ss << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(digest[i]);\n  }\n  return ss.str();\n}\n\n}\n"
  },
  {
    "path": "binkp/cram.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORKB_CRAM_H__\n#define __INCLUDED_NETWORKB_CRAM_H__\n\n#include <string>\n\nnamespace wwiv {\nnamespace net {\n  \nclass Cram {\npublic:\n  Cram() = default;\n  virtual ~Cram() = default;\n\n  bool ValidatePassword(const std::string& challenge, \n                        const std::string& secret, \n                        const std::string& given_hashed_secret);\n  std::string CreateHashedSecret(const std::string& challenge, const std::string& secret);\n\n  bool GenerateChallengeData();\n  [[nodiscard]] std::string challenge_data() const { return challenge_data_; }\n  void set_challenge_data(const std::string& challenge_data) { challenge_data_ = challenge_data; }\n\nprivate:\n  std::string challenge_data_;\n  bool initialized_ = false;\n};\n\n\n}  // namespace net\n}  // namespace wwiv\n\n#endif  // __INCLUDED_NETWORKB_CRAM_H__\n"
  },
  {
    "path": "binkp/cram_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"binkp/cram.h\"\n#include <string>\n\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\n\n\nTEST(CramTest, Basic) {\n  Cram c;\n  std::string h = c.CreateHashedSecret(\"cafebabecafebabecafebabecafebabe\", \"WELCOME\");\n  // fidopoll from mystic returned bfd5323f395243161863e7a9cd1de854\n  EXPECT_EQ(\"bfd5323f395243161863e7a9cd1de854\", h);\n}\n"
  },
  {
    "path": "binkp/fake_connection.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/fake_connection.h\"\n\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/socket_exceptions.h\"\n#include \"core/strings.h\"\n#include \"binkp/binkp_commands.h\"\n#include <chrono>\n#include <cstring>\n#include <iostream>\n#include <memory>\n#include <sstream>\n#include <stdexcept>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\nusing namespace wwiv::net;\n\nFakeBinkpPacket::FakeBinkpPacket(const void* data, int size) {\n  auto p = static_cast<const char*>(data);\n  header_ = *p++ << 8;\n  header_ = header_ | *p++;\n  is_command_ = (header_ | 0x8000) != 0;\n  header_ &= 0x7fff;\n\n  if (is_command_) {\n    command_ = *p;\n  }\n  // size doesn't include the uint16_t header.\n  data_ = std::string(p, size - 2);  \n}\n\nFakeBinkpPacket::~FakeBinkpPacket() = default;\n\nFakeBinkpPacket::FakeBinkpPacket(const FakeBinkpPacket& o)\n    : is_command_(o.is_command_), command_(o.command_), header_(o.header_), data_(o.data_) {}\n\n\nstd::string FakeBinkpPacket::debug_string() const {\n  // since data_ doesn't have a trailing nullptr, use stringstream.\n  std::stringstream ss;\n  if (is_command_) {\n    const auto s = !data_.empty() ? data_.substr(1) : data_;\n    ss << \"[\" << BinkpCommands::command_id_to_name(command_) << \"] data ='\" << s << \"'\";\n  } else {\n    ss << \"[DATA] data = '\" << data_ << \"'\";\n  }\n  return ss.str();\n}\n\nFakeConnection::FakeConnection() = default;\nFakeConnection::~FakeConnection() = default;\n\nuint16_t FakeConnection::read_uint16(std::chrono::duration<double> d) {\n  auto predicate = [&]() { \n    std::lock_guard<std::mutex> lock(mu_);\n    return !receive_queue_.empty();\n  };\n  if (!wait_for(predicate, d)) {\n    throw timeout_error(\"timedout on read_uint16\");\n  }\n  std::lock_guard<std::mutex> lock(mu_);\n  const auto& packet = receive_queue_.front();\n  auto header = packet.header();\n  if (packet.is_command()) {\n    header |= 0x8000;\n  }\n  return header;\n}\n\nuint8_t FakeConnection::read_uint8(std::chrono::duration<double> d) {\n  auto predicate = [&]() { \n    std::lock_guard<std::mutex> lock(mu_);\n    return !receive_queue_.empty();\n  };\n  if (!wait_for(predicate, d)) {\n    throw timeout_error(\"timedout on read_uint8\");\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  const FakeBinkpPacket& front = receive_queue_.front();\n  if (!front.is_command()) {\n    throw std::logic_error(\"called read_uint8 on a data packet\");\n  }\n  return front.command();\n}\n\nint FakeConnection::receive(void* data, int size, duration<double> d) {\n  std::string s = receive(size, d);\n  memcpy(data, s.data(), size);\n  return size;\n}\n\nstd::string FakeConnection::receive(int, duration<double> d) {\n  auto predicate = [&]() {\n    std::lock_guard<std::mutex> lock(mu_);\n    return !receive_queue_.empty();\n  };\n  if (!wait_for(predicate, d)) {\n    throw timeout_error(\"timedout on receive\");\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  auto on_exit = finally([=] { receive_queue_.pop(); });\n  const FakeBinkpPacket& front = receive_queue_.front();\n  return front.data();\n}\n\nint FakeConnection::send(const void* data, int size, std::chrono::duration<double>) {\n  std::lock_guard<std::mutex> lock(mu_);\n  send_queue_.push(FakeBinkpPacket(data, size));\n  return size;\n}\n\n\nint FakeConnection::send(const std::string& s, std::chrono::duration<double> d) {\n  return send(s.data(), s.length(), d);\n}\n\nbool FakeConnection::has_sent_packets() const {\n  std::lock_guard<std::mutex> lock(mu_);\n  return !send_queue_.empty();\n}\n\nFakeBinkpPacket FakeConnection::GetNextPacket() {\n  std::lock_guard<std::mutex> lock(mu_);\n  if (send_queue_.empty()) {\n    throw std::logic_error(\"GetNextPacket called on empty queue.\");\n  }\n  FakeBinkpPacket packet = send_queue_.front();\n  send_queue_.pop();\n  return packet;\n}\n\n// Reply to the BinkP with a command.\nvoid FakeConnection::ReplyCommand(int8_t command_id, const std::string& data) {\n  const int size = 3u + data.size(); /* header + command + data + null*/\n  std::unique_ptr<char[]> packet(new char[size]);\n  // Actual packet size parameter does not include the size parameter itself.\n  // And for sending a command this will be 2 less than our actual packet size.\n  const uint16_t packet_length = static_cast<uint16_t>(data.size() + sizeof(uint8_t)) | 0x8000;\n  const uint8_t b0 = ((packet_length & 0xff00) >> 8) | 0x80;\n  const uint8_t b1 = packet_length & 0x00ff;\n\n  auto* p = packet.get();\n  *p++ = b0;\n  *p++ = b1;\n  *p++ = command_id;\n  memcpy(p, data.data(), data.size());  // NOLINT(bugprone-not-null-terminated-result)\n\n  std::lock_guard<std::mutex> lock(mu_);\n  receive_queue_.push(FakeBinkpPacket(packet.get(), size));\n}\n\nbool FakeConnection::is_open() const { return open_; }\nbool FakeConnection::close() { open_ = false; return true; }"
  },
  {
    "path": "binkp/fake_connection.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BINKP_TEST_FAKE_CONNECTION_H\n#define INCLUDED_BINKP_TEST_FAKE_CONNECTION_H\n\n#include \"core/connection.h\"\n#include <chrono>\n#include <cstdint>\n#include <mutex>\n#include <queue>\n#include <string>\n\nclass FakeBinkpPacket {\npublic:\n  FakeBinkpPacket(const void* data, int size);\n  FakeBinkpPacket(const FakeBinkpPacket& o);\n  ~FakeBinkpPacket();\n\n  [[nodiscard]] bool is_command() const { return is_command_; }\n  [[nodiscard]] uint8_t command() const { return command_; }\n  [[nodiscard]] uint16_t header() const { return header_; }\n  [[nodiscard]] std::string data() const { return data_; }\n\n  [[nodiscard]] std::string debug_string() const;\n\nprivate:\n  bool is_command_;\n  uint8_t command_;\n  uint16_t header_;\n  std::string data_;\n};\n\nclass FakeConnection : public wwiv::core::Connection\n{\npublic:\n  // Connection implementation.\n  FakeConnection();\n  virtual ~FakeConnection();\n\n  int receive(void* data, int size, std::chrono::duration<double> d) override;\n  std::string receive(int size, std::chrono::duration<double> d) override;\n  int send(const void* data, int size, std::chrono::duration<double> d) override;\n  int send(const std::string& s, std::chrono::duration<double> d) override;\n\n  uint16_t read_uint16(std::chrono::duration<double> d) override;\n  uint8_t read_uint8(std::chrono::duration<double> d) override;\n  bool is_open() const override;\n  bool close() override;\n\n  bool has_sent_packets() const;\n  FakeBinkpPacket GetNextPacket();\n  void ReplyCommand(int8_t command_id, const std::string& data);\n\n  // GUARDED_BY(mu_)\n  std::queue<FakeBinkpPacket> receive_queue_;\n  // GUARDED_BY(mu_)\n  std::queue<FakeBinkpPacket> send_queue_;\nprivate:\n  mutable std::mutex mu_;\n  bool open_{};\n};\n\n#endif"
  },
  {
    "path": "binkp/file_manager.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"binkp/file_manager.h\"\n\n#include \"binkp/wfile_transfer_file.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/files/tic.h\"\n#include <map>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::net {\n\nstd::vector<TransferFile*> FileManager::CreateWWIVnetTransferFileList(int destination_node) const {\n  std::vector<TransferFile*> result;\n  const auto node_net = fmt::format(\"s{}.net\", destination_node);\n  const auto path = FilePath(dirs_.net_dir(), node_net);\n  VLOG(2) << \"       CreateWWIVnetTransferFileList: search_path: \" << path;\n  if (File::Exists(path)) {\n    const auto fn = path.filename().string();\n    result.push_back(\n        new WFileTransferFile(fn, std::make_unique<File>(FilePath(dirs_.net_dir(), fn))));\n    VLOG(1) << \"       CreateWWIVnetTransferFileList: found file: \" << fn;\n  }\n  return result;\n}\n\nstd::vector<TransferFile*> FileManager::CreateFtnTransferFileList(const std::string& address) const {\n  VLOG(1) << \"CreateFtnTransferFileList: \" << address;\n\n  std::vector<fido_bundle_status_t> statuses{\n      fido_bundle_status_t::crash,\n      fido_bundle_status_t::normal,\n      fido_bundle_status_t::direct, \n      fido_bundle_status_t::immediate\n  };\n\n  std::map<std::string, TransferFile*> result_map;\n\n  FidoAddress dest(address);\n  const auto dir = dirs_.outbound_dir();\n  VLOG(2) << \"CreateFtnTransferFileList: \" << dir;\n  for (const auto& st : statuses) {\n    const auto name = flo_name(dest, st);\n    const auto path = FilePath(dir, name);\n    VLOG(2) << \"Looking for FLO file named: \" << path.string();\n    if (File::Exists(path)) {\n      LOG(INFO) << \"Found FLO file: \" << dir << \"; name: \" << name;\n      FloFile flo(net_, path);\n      if (!flo.Load()) {\n        continue;\n      }\n      for (const auto& e : flo.flo_entries()) {\n        File f(e.first);\n        const auto basename = f.path().filename().string();\n        auto* w = new WFileTransferFile(basename, std::make_unique<File>(e.first));\n        w->set_flo_file(std::make_unique<FloFile>(net_, path));\n        // emplace won't add another entry if one exists already.\n        result_map.emplace(basename, w);\n      }\n    }\n  }\n  // Return a vector of the transfer files.  This way we don't\n  // have duplicate entries.\n  std::vector<TransferFile*> result;\n  for (const auto& e : result_map) {\n    result.push_back(e.second);\n  }\n  return result;\n}\n\nFileManager::FileManager(const wwiv::sdk::Config& config, const Network& net,\n                         const std::string& receive_dir)\n  : config_(config), net_(net), dirs_(config.root_directory(), net, receive_dir) {\n  const auto dir = dirs_.receive_dir();\n  VLOG(1) << \"FileManager: receive_dir: \" << dir;\n  if (!File::Exists(dir)) {\n    LOG(INFO) << \"Creating receive directory for session: '\" << dir << \"'\";\n    if (!File::mkdirs(dir)) {\n      LOG(ERROR) << \"Failed to create receive directory: \" << dir;\n    }\n  }\n}\n\nstd::vector<TransferFile*> FileManager::CreateTransferFileList(const Remote& remote) const {\n  if (net_.type == network_type_t::wwivnet) {\n    return CreateWWIVnetTransferFileList(remote.wwivnet_node());\n  }\n  if (net_.type == network_type_t::ftn) {\n    return CreateFtnTransferFileList(remote.ftn_address());\n  }\n  return{};\n}\n\nvoid FileManager::ReceiveFile(const std::string& filename) {\n  VLOG(1) << \"FileManager::ReceiveFile: \" << filename;\n  received_files_.push_back(filename);\n}\n\nstatic void rename_wwivnet_pend(const std::filesystem::path& receive_directory, \n  const std::filesystem::path& net_dir, \n  const std::string& filename) {\n  const auto pend_filename = FilePath(receive_directory, filename);\n  if (!File::Exists(pend_filename)) {\n    LOG(ERROR) << \" pending file does not exist: \" << pend_filename;\n    return;\n  }\n  const auto num = filename.substr(1);\n  const std::string prefix = (to_number<int>(num)) ? \"1\" : \"0\";\n\n  for (auto i = 0; i < 1000; i++) {\n    const auto new_basename = fmt::format(\"p{}-0-{}.net\", prefix, i);\n    const auto new_filename = FilePath(net_dir, new_basename);\n    VLOG(2) << new_filename;\n    if (File::Rename(pend_filename, new_filename)) {\n      LOG(INFO) << \"renamed file: '\" << pend_filename << \"' to: '\" << new_filename << \"'\";\n      return;\n    }\n  }\n  LOG(ERROR) << \"all attempts failed to rename_wwivnet_pend\";\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nvoid FileManager::rename_wwivnet_pending_files() {\n  VLOG(1) << \"STATE: rename_wwivnet_pending_files\";\n  for (const auto& file : received_files()) {\n    const auto rdir = dirs_.receive_dir();\n    const auto net_dir = dirs_.net_dir();\n    VLOG(1) << \"       renaming_pending_file: dir: \" << rdir << \"; file: \" << file;\n    rename_wwivnet_pend(rdir, net_dir, file);\n  }\n}\n\nstatic bool is_tic_file(const std::string& fn) {\n  const auto idx = fn.rfind('.');\n  if (idx == std::string::npos) {\n    return false;\n  }\n  const auto ext = ToStringUpperCase(fn.substr(idx + 1));\n  return ext == \"TIC\";\n}\n\nstatic bool move_without_overrite(const std::filesystem::path& src,\n                                  const std::filesystem::path& dest, const std::string& msg) {\n  LOG(INFO) << \"       Attempting to move \" << src.string() << \" => \" << dest.string();\n  if (!File::Exists(dest)) {\n    return File::Move(src, dest);\n  }\n  LOG(ERROR) << \"       Skipping Move since file already exists: \" << dest.string();\n  if (!msg.empty()) {\n    LOG(ERROR) << msg;\n  }\n  return false;\n}\n\nvoid FileManager::rename_ftn_pending_files(const Remote& remote) {\n  VLOG(1) << \"STATE: rename_ftn_pending_files\";\n  const auto rdir = dirs_.receive_dir();\n  const sdk::files::TicParser tic_parser(rdir);\n  for (const auto& file : received_files()) {\n    const auto ipath = FilePath(dirs_.inbound_dir(), file);\n    const auto rpath = FilePath(rdir, file);\n    const auto upath = FilePath(dirs_.unknown_dir(), file);\n    if (!File::Exists(rpath)) {\n      VLOG(1) << \"[pass 1] rfile does not exist: \" << rpath;\n      continue;\n    }\n    if (is_bundle_file(file) || is_packet_file(file)) {\n      LOG(INFO) << \"       renaming_pending_file: dir: \" << rdir << \"; file: \" << file;\n      move_without_overrite(rpath, ipath,\n                            \"already exists in fido inbound dir. Please move manually.\");\n      continue;\n    }\n    if (is_tic_file(file) && net_.fido.process_tic) {\n      // TODO: here is where we can do the TIC support.\n      // If TIC file, process tic file and move it and archive to the net_dir\n      // then pass to networkt to process. For now HACK - let's just move all unknown\n      // to the tick dir.\n      const auto ticpath = FilePath(rdir, file);\n      auto otick = tic_parser.parse(file);\n      if (!otick) {\n        LOG(ERROR) << \"Unable to parse TIC file: \" << ticpath;\n        continue;\n      }\n      auto tic = otick.value();\n      if (!tic.IsValid()) {\n        LOG(ERROR) << \"       Tic file \" << ticpath.string() << \" IS NOT VALID.\";\n        continue;\n      }\n      LOG(INFO) << \"Tic file \" << ticpath.string() << \" is valid.\";\n      FidoCallout callout(config_.root_directory(), config_.max_backups(), remote.network());\n      std::string expected_tic_pw;\n      try {\n        FidoAddress address(remote.ftn_address());\n        auto packet_config = callout.packet_config_for(address);\n        expected_tic_pw = packet_config.tic_password;\n      } catch (const bad_fidonet_address&) {\n      }\n      if (!expected_tic_pw.empty()) {\n        // We expect a password.\n        if (!iequals(expected_tic_pw, tic.pw)) {\n          LOG(ERROR) << \"       Tic Password was not correct for tic: \" << ticpath.string()\n                     << \"; skipping.\";\n          continue;\n        }\n      } else {\n        LOG(INFO) << \"No password configured for node: \" << remote.ftn_address();\n      }\n      move_without_overrite(FilePath(rdir, tic.file), FilePath(dirs_.tic_dir(), tic.file),\n                            \"File (from TIC) file already exists in TIC path.\");\n      move_without_overrite(rpath, FilePath(dirs_.tic_dir(), file),\n                            \"TIC file already exists in TIC path.\");\n    } else {\n      LOG(ERROR) << \"       tic processing disabled and unknown file received: '\" << file << \"' moving to TIC dir.\";\n    }\n  }\n  // pass 2: anything remaining move to unknown dir.\n  // note that things missing were already processed.\n  for (const auto& file : received_files()) {\n    const auto rpath = FilePath(rdir, file);\n    if (File::Exists(rpath)) {\n      const auto upath = FilePath(dirs_.unknown_dir(), file);\n      File::Move(rpath, upath);\n    }\n  }\n}\n\n} // namespace wwiv::net\n"
  },
  {
    "path": "binkp/file_manager.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BINKP_FILE_MANAGER_H\n#define INCLUDED_BINKP_FILE_MANAGER_H\n\n#include \"binkp/remote.h\"\n#include \"binkp/transfer_file.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/net/net.h\"\n#include <string>\n#include <vector>\n\nnamespace wwiv::net {\n  \nclass FileManager final {\npublic:\n  FileManager(const wwiv::sdk::Config& config, const sdk::net::Network& net,\n                       const std::string& receive_dir);\n  ~FileManager() = default;\n\n  [[nodiscard]] std::vector<TransferFile*> CreateTransferFileList(const Remote& remote) const;\n  void ReceiveFile(const std::string& filename);\n  [[nodiscard]] const std::vector<std::string>& received_files() const { return received_files_; }\n  void rename_wwivnet_pending_files();\n  void rename_ftn_pending_files(const Remote& remote);\n\n  // For tests.\n  [[nodiscard]] const wwiv::sdk::fido::FtnDirectories& dirs() const { return dirs_; }\n\nprivate:\n  [[nodiscard]] std::vector<TransferFile*> CreateWWIVnetTransferFileList(int destination_node) const;\n  [[nodiscard]] std::vector<TransferFile*> CreateFtnTransferFileList(const std::string& address) const;\n\n  const wwiv::sdk::Config& config_;\n  const sdk::net::Network net_;\n  const wwiv::sdk::fido::FtnDirectories dirs_;\n  const std::string network_directory_;\n  std::vector<std::string> received_files_;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "binkp/file_manager_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"core/file.h\"\n#include \"binkp/file_manager.h\"\n#include \"core/textfile.h\"\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nclass FileManagerTest : public testing::Test {\npublic:\n  FileManagerTest() {\n    const auto& root = file_helper_.TempDir();\n    config_ = std::make_unique<wwiv::sdk::Config>(root);\n    config_->set_initialized_for_test(true);\n    net.name = \"WWIVnet\";\n    net.fido.process_tic = true;\n    net.type = network_type_t::ftn;\n    net.fido.bad_packets_dir = \"b\";\n    net.fido.inbound_dir = \"in\";\n    net.fido.netmail_dir = \"netmail\";\n    net.fido.outbound_dir = \"out\";\n    net.fido.temp_inbound_dir = \"tin\";\n    net.fido.temp_outbound_dir = \"tout\";\n    net.fido.tic_dir = \"tic\";\n    net.fido.unknown_dir = \"unknown\";\n    net.dir = FilePath(root, \"net\").string();\n    File::mkdirs(net.dir);\n\n    const auto dir_data_ = file_helper_.DirName(\"data\");\n    const auto dir_gfiles_ = file_helper_.DirName(\"gfiles\");\n    const auto dir_menus_ = file_helper_.DirName(\"menus\");\n    const auto dir_msgs_ = file_helper_.DirName(\"msgs\");\n    const auto dir_dloads_ = file_helper_.DirName(\"dloads\");\n\n    config_->set_initialized_for_test(true);\n    config_->set_paths_for_test(dir_data_, dir_msgs_, dir_gfiles_, dir_menus_, dir_dloads_,\n                                dir_data_);\n\n    const auto receive_dir = FilePath(root, \"r\");\n    fm = std::make_unique<FileManager>(*config_, net, receive_dir.string());\n    r = fm->dirs().receive_dir();\n    t = fm->dirs().tic_dir();\n    u = fm->dirs().unknown_dir();\n    bink_config_ = std::make_unique<BinkConfig>(1, *config_, net.dir.string());\n  }\n\n  [[nodiscard]] bool CreateTic(const std::filesystem::path& dir, const std::string& filename, const std::string& pw) {\n    // Create TIC file\n    std::filesystem::path fn{filename};\n    const auto tic_name = fn.replace_extension(\".tic\");\n    TextFile out(dir / tic_name, \"wt\");\n    out.WriteLine(\"File \" + filename);\n    out.WriteLine(\"Crc 00000000\");\n    out.WriteLine(\"Size 0\");\n    out.WriteLine(\"Area Foo\");\n    if (!pw.empty()) {\n      out.WriteLine(\"Pw \" + pw);\n    }\n    out.Close();\n\n    {\n      // Create filename\n      File f(dir / filename);\n      f.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite);\n      f.Close();\n    }\n    return true;\n  }\n\n  [[nodiscard]] bool CreateTic(const std::filesystem::path& dir, const std::string& filename) {\n    return CreateTic(dir, filename, \"\");\n  }\n\n  wwiv::core::test::FileHelper file_helper_;\n  Network net{};\n  std::unique_ptr<FileManager> fm;\n  std::unique_ptr<wwiv::sdk::Config> config_;\n  std::unique_ptr<BinkConfig> bink_config_;\n  std::filesystem::path r;\n  std::filesystem::path t;\n  std::filesystem::path u;\n};\n\nTEST_F(FileManagerTest, Basic) {\n  ASSERT_TRUE(CreateTic(r, \"foo.zip\"));\n\n  fm->ReceiveFile(\"foo.zip\");\n  fm->ReceiveFile(\"foo.tic\");\n  const Remote remote(bink_config_.get(), false, \"1:1/1\");\n  fm->rename_ftn_pending_files(remote);\n\n  EXPECT_FALSE(File::Exists(r / \"foo.zip\"));\n  EXPECT_FALSE(File::Exists(r / \"foo.tic\"));\n\n  EXPECT_TRUE(File::Exists(t / \"foo.zip\"));\n  EXPECT_TRUE(File::Exists(t / \"foo.tic\"));\n}\n\nTEST_F(FileManagerTest, NoProcessTic) {\n  ASSERT_TRUE(CreateTic(r, \"foo.zip\"));\n\n  net.fido.process_tic = false;\n  const auto receive_dir = FilePath(file_helper_.TempDir(), \"r\");\n  fm = std::make_unique<FileManager>(*config_, net, receive_dir.string());\n  r = fm->dirs().receive_dir();\n  t = fm->dirs().tic_dir();\n  u = fm->dirs().unknown_dir();\n  fm->ReceiveFile(\"foo.zip\");\n  fm->ReceiveFile(\"foo.tic\");\n\n  const Remote remote(bink_config_.get(), false, \"1:1/1\");\n  fm->rename_ftn_pending_files(remote);\n\n  EXPECT_FALSE(File::Exists(r / \"foo.zip\"));\n  EXPECT_FALSE(File::Exists(r / \"foo.tic\"));\n  EXPECT_FALSE(File::Exists(t / \"foo.zip\"));\n  EXPECT_FALSE(File::Exists(t / \"foo.tic\"));\n\n  EXPECT_TRUE(File::Exists(u / \"foo.zip\"));\n  EXPECT_TRUE(File::Exists(u / \"foo.tic\"));\n}\n\nTEST_F(FileManagerTest, WithPassword) {\n  ASSERT_TRUE(CreateTic(r, \"foo.zip\", \"rush\"));\n\n  fm->ReceiveFile(\"foo.zip\");\n  fm->ReceiveFile(\"foo.tic\");\n  wwiv::sdk::fido::FidoCallout callout(config_->root_directory(), config_->max_backups(), net);\n  const wwiv::sdk::fido::FidoAddress remote_addr(\"1:1/1\");\n  fido_node_config_t node_config{};\n  node_config.packet_config.tic_password = \"rush\";\n  callout.insert(remote_addr, node_config);\n  const Remote remote(bink_config_.get(), false, \"1:1/1\");\n  fm->rename_ftn_pending_files(remote);\n\n  EXPECT_TRUE(File::Exists(t / \"foo.zip\"));\n  EXPECT_TRUE(File::Exists(t / \"foo.tic\"));\n}\n\nTEST_F(FileManagerTest, WithPassword_WrongPassword) {\n  ASSERT_TRUE(CreateTic(r, \"foo.zip\", \"styx\"));\n\n  fm->ReceiveFile(\"foo.zip\");\n  fm->ReceiveFile(\"foo.tic\");\n  wwiv::sdk::fido::FidoCallout callout(config_->root_directory(), config_->max_backups(), net);\n  const wwiv::sdk::fido::FidoAddress remote_addr(\"1:1/1\");\n  fido_node_config_t node_config{};\n  node_config.packet_config.tic_password = \"rush\";\n  node_config.binkp_config.host = \"mystic.wwivbbs.org\";\n  callout.insert(remote_addr, node_config);\n  callout.Save();\n  const Remote remote(bink_config_.get(), false, \"1:1/1\");\n  fm->rename_ftn_pending_files(remote);\n\n  EXPECT_TRUE(File::Exists(u / \"foo.zip\"));\n  EXPECT_TRUE(File::Exists(u / \"foo.tic\"));\n}"
  },
  {
    "path": "binkp/net_log.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/net_log.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/networks.h\"\n\n#include <chrono>\n#include <sstream>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::net {\n\nNetworkLog::NetworkLog(const std::filesystem::path& d) : gfiles_directory_(d) {}\nNetworkLog::~NetworkLog() = default;\n\nstd::string NetworkLog::CreateLogLine(time_t time, NetworkSide side, int node,\n                                      int bytes_sent, int bytes_received,\n                                      std::chrono::seconds seconds_elapsed,\n                                      const std::string& network_name) const {\n\n  // Format: 01/03/15 20:26:23 To     1, S: 419k, R: 223k,           0.1 min  wwivnet\n  // sprintf(s2, \"S:%4ldk, R:%4ldk,\", sent, recd);\n  // sprintf(s, \"%s To %5d, %s         %5s min  %s\\r\\n\", s1, sn, s2, tmused, net_name);\n\n  std::ostringstream ss;\n  const auto dt = DateTime::from_time_t(time);\n  ss << dt.to_string(\"%m/%d/%y %H:%M:%S\") << \" \";\n  if (side == NetworkSide::FROM) {\n    ss << \"Fr \";\n  } else {\n    ss << \"To \";\n  }\n  ss << fmt::sprintf(\"%5d\", node);\n  ss << fmt::sprintf(\", S:%4dk\", (bytes_sent + 1023) / 1024);\n  ss << fmt::sprintf(\", R:%4dk\", (bytes_received + 1023) / 1024);\n  ss << \"          \"; // should be \", %4.0f cps\";\n  ss << \" \";          // last space before time.\n\n  using float_minutes = std::chrono::duration<float, std::ratio<60>>;\n  const auto minutes = std::chrono::duration_cast<float_minutes>(seconds_elapsed);\n  ss << fmt::sprintf(\"%4.1f min \", minutes.count());\n  ss << \" \" << network_name;\n\n  return ss.str();\n}\n\nstd::string NetworkLog::GetContents() const {\n  TextFile file(FilePath(gfiles_directory_, NET_LOG), \"r\");\n  if (!file.IsOpen()) {\n    return \"\";\n  }\n  return file.ReadFileIntoString();\n}\n\nbool NetworkLog::Log(time_t time, NetworkSide side, int node, unsigned int bytes_sent,\n                     unsigned int bytes_received, std::chrono::seconds seconds_elapsed,\n                     const std::string& network_name) {\n\n  const auto log_line =\n      CreateLogLine(time, side, node, bytes_sent, bytes_received, seconds_elapsed, network_name);\n\n  // Opening for \"w\" should truncate the existing file.\n  TextFile file(FilePath(gfiles_directory_, NET_LOG), \"a+t\");\n  file.WriteLine(log_line);\n\n  return true;\n}\n\nstd::string NetworkLog::ToString() const {\n  return FilePath(gfiles_directory_, NET_LOG).string();\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/net_log.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BINKP_NET_LOG_H\n#define INCLUDED_BINKP_NET_LOG_H\n\n#include \"sdk/config.h\"\n#include <chrono>\n#include <ctime>\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::net {\n\n/**\n * Handles writing new log entries into net.log.\n\n * Format of gfiles/net.log:\n *\n * 01/03/15 20:26:23 To 32767,                             0.1 min  wwivnet\n * 01/03/15 20:26:23 To     1, S : 4k, R : 3k,             0.1 min  wwivnet\n */\n\nenum class NetworkSide { FROM, TO };\n\nclass NetworkLog final {\npublic:\n  explicit NetworkLog(const std::filesystem::path& gfiles_directory);\n  ~NetworkLog();\n\n  bool Log(time_t time, NetworkSide side, int node, unsigned int bytes_sent,\n           unsigned int bytes_received, std::chrono::seconds seconds_elapsed,\n           const std::string& network_name);\n  [[nodiscard]] std::string GetContents() const;\n\n  [[nodiscard]] std::string ToString() const;\n\n  [[nodiscard]] std::string CreateLogLine(time_t time, NetworkSide side, int node, int bytes_sent,\n                                          int bytes_received, std::chrono::seconds seconds_elapsed,\n                                          const std::string& network_name) const;\n\nprivate:\n  const std::filesystem::path gfiles_directory_;\n};\n\n} // namespace wwiv::net\n\n#endif"
  },
  {
    "path": "binkp/net_log_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/net_log.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"fmt/printf.h\"\n#include \"gtest/gtest.h\"\n#include <chrono>\n#include <string>\n#include <thread>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\n\nclass NetworkLogTest : public testing::Test {\npublic:\n  NetworkLogTest() {\n    CHECK(helper_.Mkdir(\"gfiles\"));\n    const auto dt = DateTime::now();\n    now_ = dt.to_time_t();\n    now_string_ = dt.to_string(\"%m/%d/%y %H:%M:%S\");\n  }\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n  time_t now_;\n  std::string now_string_;\n};\n\nTEST_F(NetworkLogTest, CreateLogLine_Fr_S1K_R2K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::FROM, 12345, 1024 * 1024,\n                                            2048 * 1024, std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} Fr 12345, S:1024k, R:2048k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(NetworkLogTest, CreateLogLine_To_S1K_R2K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::TO, 12345, 1024 * 1024, 2048 * 1024,\n                                            std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} To 12345, S:1024k, R:2048k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(NetworkLogTest, CreateLogLine_Fr_S1K_R0K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::FROM, 12345, 1024 * 1024, 0,\n                                            std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} Fr 12345, S:1024k, R:   0k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(NetworkLogTest, CreateLogLine_To_S1K_R0K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::TO, 12345, 1024 * 1024, 0,\n                                            std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} To 12345, S:1024k, R:   0k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(NetworkLogTest, CreateLogLine_Fr_S0K_R3K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::FROM, 12345, 0, 3072 * 1024,\n                                            std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} Fr 12345, S:   0k, R:3072k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(NetworkLogTest, CreateLogLine_To_S0K_R3K_101s) {\n  const NetworkLog net_log(helper_.DirName(\"gfiles\"));\n  const auto actual = net_log.CreateLogLine(now_, NetworkSide::TO, 12345, 0, 3072 * 1024,\n                                            std::chrono::seconds(101), \"rushnet\");\n  const auto expected =\n      fmt::format(\"{} To 12345, S:   0k, R:3072k            1.7 min  rushnet\", now_string_);\n  EXPECT_EQ(expected, actual);\n}\n"
  },
  {
    "path": "binkp/ppp_config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/ppp_config.h\"\n\n#include \"binkp/config_exceptions.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/networks.h\"\n\n#include <filesystem>\n#include <map>\n#include <sstream>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::net {\n\n// [[ VisibleForTesting ]]\nbool ParseAddressNetLine(const std::string& line, uint16_t* node, PPPNodeConfig* config) {\n  if (line.empty() || line[0] != '@') {\n    // skip empty lines and those not starting with @.\n    return false;\n  }\n  \n  std::stringstream stream(line);\n  std::string node_str;\n  stream >> node_str;\n  *node = to_number<uint16_t>(node_str.substr(1));\n  std::string email_address;\n  stream >> config->email_address;\n  \n  return true;\n}\n\nstatic bool ParseAddressesFile(std::map<int, PPPNodeConfig>* node_config_map, const std::filesystem::path& network_dir) {\n  TextFile node_config_file(FilePath(network_dir, ADDRESS_NET), \"rt\");\n  if (!node_config_file.IsOpen()) {\n    return false;\n  }\n  // A line will be of the format @node host:port [password].\n  std::string line;\n  while (node_config_file.ReadLine(&line)) {\n    uint16_t node_number;\n    PPPNodeConfig node_config;\n    if (ParseAddressNetLine(line, &node_number, &node_config)) {\n      // Parsed a line correctly.\n      node_config_map->emplace(node_number, node_config);\n    }\n  }\n  return true;\n}\n\nPPPConfig::PPPConfig(const std::string& callout_network_name, const Config& config, const Networks& networks)\n    : callout_network_name_(callout_network_name) {\n  system_name_ = config.system_name();\n  if (system_name_.empty()) {\n    system_name_ = \"Unnamed WWIV BBS\";\n  }\n\n  const auto& net = networks[callout_network_name];\n  node_ = net.sysnum;\n  if (node_ == 0) {\n    throw config_error(fmt::format(\"NODE not specified for network: '{}'\", callout_network_name));\n  }\n\n  ParseAddressesFile(&node_config_, net.dir);\n}\n\nPPPConfig::PPPConfig(int node_number, std::string system_name, const std::string& network_dir)\n    : node_(node_number), system_name_(std::move(system_name)) {\n  ParseAddressesFile(&node_config_, network_dir);\n}\n\nPPPConfig::~PPPConfig() = default;\n\nconst PPPNodeConfig* PPPConfig::ppp_node_config_for(int node) const {\n  const auto iter = node_config_.find(node);\n  if (iter != end(node_config_)) {\n    return &iter->second;\n  }\n  return nullptr;\n}\n\n\n} // namespace wwiv\n\n"
  },
  {
    "path": "binkp/ppp_config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORKB_PPP_CONFIG_H__\n#define __INCLUDED_NETWORKB_PPP_CONFIG_H__\n\n#include \"sdk/config.h\"\n#include \"sdk/net/networks.h\"\n#include <cstdint>\n#include <map>\n#include <string>\n\nnamespace wwiv {\nnamespace net {\n\nstruct PPPNodeConfig {\n  std::string email_address;\n};\n\nclass PPPConfig {\n public:\n  PPPConfig(const std::string& network_name, const wwiv::sdk::Config& config, const wwiv::sdk::Networks& networks);\n  // For Testing\n  PPPConfig(int node_number, std::string system_name, const std::string& network_dir);\n  virtual ~PPPConfig();\n  [[nodiscard]] const PPPNodeConfig* ppp_node_config_for(int node) const;\n\n  [[nodiscard]] int callout_node_number() const { return node_; }\n  [[nodiscard]] const std::string& system_name() const { return system_name_; }\n  [[nodiscard]] const std::string& callout_network_name() const { return callout_network_name_; }\n\n private:\n  std::map<int, PPPNodeConfig> node_config_;\n  std::string home_dir_;\n  int node_;\n  std::string system_name_;\n  std::string callout_network_name_;\n};\n\nbool ParseAddressNetLine(const std::string& line,\n\t\t\t uint16_t* node,\n\t\t\t PPPNodeConfig* config);\n\n}  // namespace net\n}  // namespace wwiv\n\n\n#endif  // __INCLUDED_NETWORKB_PPP_CONFIG_H__\n"
  },
  {
    "path": "binkp/ppp_config_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"binkp/ppp_config.h\"\n#include <cstdint>\n#include <string>\n\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\n\nclass ParsePPPConfigLineTest : public testing::Test {};\n\nTEST_F(ParsePPPConfigLineTest, Basic) {\n  uint16_t node;\n  PPPNodeConfig config;\n\n  std::string line = \"@1234 addy@example.com\";\n  ASSERT_TRUE(ParseAddressNetLine(line, &node, &config));\n  EXPECT_EQ(1234, node);\n  EXPECT_EQ(\"addy@example.com\", config.email_address);\n}\n\nTEST_F(ParsePPPConfigLineTest, InvalidLine) {\n  uint16_t node;\n  PPPNodeConfig config;\n\n  const std::string line = \"*@1234 myhost -\";\n  ASSERT_FALSE(ParseAddressNetLine(line, &node, &config));\n}\n\nTEST(PPPConfigTest, NodeConfig) {\n  wwiv::core::test::FileHelper files;\n  files.Mkdir(\"network\");\n  const std::string line(\"@2 foo@example.com\");\n  files.CreateTempFile(\"network/address.net\", line);\n  const auto network_dir = files.DirName(\"network\");\n  PPPConfig config(1, \"mybbs\", network_dir);\n  const PPPNodeConfig* node_config = config.ppp_node_config_for(2);\n  ASSERT_TRUE(node_config != nullptr);\n  EXPECT_EQ(\"foo@example.com\", node_config->email_address);\n}\n"
  },
  {
    "path": "binkp/receive_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETORKB_RECEIVE_FILE_H\n#define INCLUDED_NETORKB_RECEIVE_FILE_H\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"binkp/transfer_file.h\"\n#include <cstdint>\n#include <ctime>\n#include <memory>\n#include <string>\n#include <utility>\n\nnamespace wwiv::net {\n\nclass ReceiveFile {\npublic:\n  ReceiveFile(TransferFile* file, std::string filename, long expected_length, time_t timestamp,\n              uint32_t crc)\n      : file_(file), filename_(std::move(filename)), expected_length_(expected_length),\n        timestamp_(timestamp), length_(0), crc_(crc) {\n    VLOG(1) << \"ReceiveFile: \" << filename;\n  }\n  ~ReceiveFile() = default;\n\n  bool WriteChunk(const char* chunk, int size) {\n    const auto ok = file_->WriteChunk(chunk, size);\n    if (ok) {\n      length_ += size;\n    }\n    return ok;\n  }\n\n  bool WriteChunk(const std::string& chunk) {\n    const auto cs = wwiv::strings::ssize(chunk);\n    if (!file_->WriteChunk(chunk.data(), cs)) {\n      return false;\n    }\n    length_ += cs;\n    return true;\n  }\n\n  [[nodiscard]] std::string filename() const { return filename_; }\n  [[nodiscard]] long expected_length() const { return expected_length_; }\n  [[nodiscard]] long length() const { return length_; }\n  [[nodiscard]] time_t timestamp() const { return timestamp_; }\n  [[nodiscard]] bool Close() { return file_->Close(); }\n  [[nodiscard]] uint32_t crc() const { return crc_; }\n\n  std::unique_ptr<TransferFile> file_;\n  std::string filename_;\n  long expected_length_{0};\n  time_t timestamp_{0};\n  long length_{0};\n  uint32_t crc_{0};\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "binkp/remote.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"binkp/remote.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"binkp/binkp_config.h\"\n#include \"sdk/fido/fido_address.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net {\n\nstd::string ftn_address_from_address_list(const std::string& address_list, const std::string& domain) {\n  VLOG(1) << \"       ftn_address_from_address_list: '\" << address_list << \"'; domain: \" << domain;\n  auto v = SplitString(address_list, \" \");\n  std::string first;\n  for (auto s : v) {\n    StringTrim(&s);\n    VLOG(1) << \"       ftn_address_from_address_list(s): '\" << s << \"'\";\n    if (ends_with(s, StrCat(\"@\", domain))) {\n      if (first.empty()) {\n        first = s;\n      }\n      try {\n        // Let's ensure we have a well formed FidoAddress.\n        const sdk::fido::FidoAddress a(s);\n        // Check for zero zone, node or net.\n        if (a.net() == -1 || a.node() == -1 || a.zone() == -1) {\n          continue;\n        }\n      }\n      catch (const sdk::fido::bad_fidonet_address& e) {\n        LOG(WARNING) << \"Caught bad_fidonet_address: \" << e.what();\n        // Just like above, we don't have a well formed FidoAddress\n        // so we keep looping through the list.\n        continue;\n      }\n      return s;\n    }\n  }\n  return first;\n}\n\nstd::set<sdk::fido::FidoAddress>\nftn_addresses_from_address_list(const std::string& address_list,\n                              const std::set<sdk::fido::FidoAddress>& known_addresses) {\n  std::set<sdk::fido::FidoAddress> valid_addresses;\n  for (const auto& s : SplitString(address_list, \" \")) {\n    VLOG(2) << \"       ftn_addresses_from_address_list: try_parse_fidoaddr: \" << s;\n    if (auto o = sdk::fido::try_parse_fidoaddr(s)) {\n      for (const auto& a : known_addresses) {\n        if (o->approx_equals(a)) {\n          VLOG(2) << \"       ftn_addresses_from_address_list: Adding address: \"\n                  << o.value().as_string(true, true);\n          // Insert the one that has the domain on it.\n          if (o->has_domain()) {\n            valid_addresses.insert(o.value());\n          } else {\n            valid_addresses.insert(a);\n          }\n        }\n      }\n    }\n  }\n  return valid_addresses;\n}\n\nuint16_t wwivnet_node_number_from_ftn_address(const std::string& address) {\n  std::string s = address;\n  LOG(INFO) << \"wwivnet_node_number_from_ftn_address: '\" << s << \"'\";\n  if (starts_with(s, \"20000:20000/\")) {\n    s = s.substr(12);\n    s = s.substr(0, s.find('/'));\n\n    if (contains(s, '@')) {\n      s = s.substr(0, s.find('@'));\n    }\n    return to_number<uint16_t>(s);\n  }\n\n  return WWIVNET_NO_NODE;\n}\n\nstd::string fixup_address(const std::string& addr, const Network& net, const std::string& default_domain) {\n  if (auto o = sdk::fido::try_parse_fidoaddr(addr)) {\n    if (o->has_domain()) {\n      return o->as_string(true, true);\n    }\n    if (net.type == network_type_t::ftn) {\n      if (auto no = sdk::fido::try_parse_fidoaddr(net.fido.fido_address); no->has_domain()) {\n        return StrCat(o->as_string(false, true), \"@\", no->domain());\n      }\n    }\n    return StrCat(o->as_string(false, true), \"@\", default_domain);\n  }\n  // We don't have a parsable address here.\n  return addr;\n}\n\nRemote::Remote(BinkConfig* config, bool remote_is_caller, const std::string& expected_remote_addr)\n  : config_(config),\n  default_domain_(config_->callout_network_name()),\n  remote_is_caller_(remote_is_caller),\n  expected_remote_node_(expected_remote_addr),\n  domain_(default_domain_),\n  network_name_(domain_) {\n\n  // When sending, we should be talking to who we wanted to.\n  if (!remote_is_caller) {\n    const auto& n = config_->networks().at(config_->callout_network_name());\n    const auto addr = fixup_address(expected_remote_addr, n, default_domain_);\n\n    VLOG(3) << \"*********** REMOTE IS NOT CALLER ****************: \" << addr;\n    if (auto o = sdk::fido::try_parse_fidoaddr(addr)) {\n      ftn_addresses_.insert(o.value());\n      if (o->has_domain()) {\n        set_domain(o->domain());\n      }\n    }\n    if (config->callout_network().type == network_type_t::wwivnet) {\n      wwivnet_node_ = wwivnet_node_number_from_ftn_address(addr);\n    }\n  }\n}\n\nvoid Remote::set_address_list(const std::string& a) {\n  address_list_ = ToStringLowerCase(a);\n}\n\nstd::string Remote::network_name() const {\n  if (!network_name_.empty()) {\n    return network_name_;\n  }\n  VLOG(2) << \"       Remote::network_name: returning default domain for network_name: \" << default_domain_;\n  return default_domain_;\n}\n\nstd::string Remote::domain() const {\n  return domain_;\n}\n\nvoid Remote::set_domain(const std::string& d) {\n  VLOG(2) << \"       Remote::set_domain: \" << d;\n  domain_ = ToStringLowerCase(d);\n  network_name_ = domain_;\n\n  for (const auto& n : config_->networks().networks()) {\n    if (n.type == network_type_t::ftn) {\n      if (const auto nd = sdk::fido::try_parse_fidoaddr(n.fido.fido_address)) {\n        if (d == nd->domain()) {\n          const auto lcnn = ToStringLowerCase(n.name);\n          network_name_ = lcnn;\n          VLOG(2) << \"       Remote::set_domain: Setting Network Name: \" << lcnn;\n          return;\n        }        \n      }\n    }\n  }\n}\n\nconst Network& Remote::network() const {\n  return config_->network(network_name());\n}\n\nstd::string Remote::ftn_address() const {\n  if (ftn_addresses_.empty()) {\n    return {};\n  }\n  return std::begin(ftn_addresses_)->as_string(true, true);\n}\n\nvoid Remote::set_ftn_addresses(const std::set<sdk::fido::FidoAddress>& a) {\n  VLOG(1) << \"       Remote::set_ftn_addresses; domain: \" << domain_ << \"; size: \" << a.size();\n  ftn_addresses_ = a;\n  if (!a.empty()) {\n    for (const auto& a1 : a) {\n      VLOG(1) << \"       Remote::set_ftn_addresses: \" << a1;\n      if (a1.has_domain()) {\n        set_domain(a1.domain());\n        VLOG(1) << \"       Setting domain to: \" << domain_;\n        break;\n      }\n    }\n  }\n}\n\n}\n"
  },
  {
    "path": "binkp/remote.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORKB_REMOTE_USER_H\n#define INCLUDED_NETWORKB_REMOTE_USER_H\n\n#include \"binkp/binkp_config.h\"\n#include <cstdint>\n#include <set>\n#include <string>\n\nnamespace wwiv::net {\n  \nclass Remote final {\npublic:\n  Remote(BinkConfig* config, bool remote_is_caller, const std::string& expected_remote_addr);\n  ~Remote() = default;\n\n  void set_system_name(const std::string& s) { system_name_ = s; }\n  void set_sysop_name(const std::string& s) { sysop_name_ = s; }\n  void set_version(const std::string& v) { version_ = v; }\n  void set_address_list(const std::string& a);\n  [[nodiscard]] std::string address_list() const { return address_list_; }\n  [[nodiscard]] std::string network_name() const;\n  [[nodiscard]] std::string domain() const;\n  void set_domain(const std::string& d);\n  [[nodiscard]] const sdk::net::Network& network() const;\n\n  [[nodiscard]] int wwivnet_node() const { return wwivnet_node_; }\n  void set_wwivnet_node(int n, const std::string& domain) { wwivnet_node_ = static_cast<uint16_t>(n); domain_ = domain; }\n  [[nodiscard]] std::string ftn_address() const;\n  [[nodiscard]] std::set<sdk::fido::FidoAddress> ftn_addresses() const { return ftn_addresses_; }\n  void set_ftn_addresses(const std::set<sdk::fido::FidoAddress>& a);\n\nprivate:\n  BinkConfig* config_;\n  const std::string default_domain_;\n  bool remote_is_caller_;\n  const std::string expected_remote_node_;\n  std::string domain_;\n  std::string network_name_;\n\n  std::string system_name_;\n  std::string sysop_name_;\n  std::string version_;\n  std::set<sdk::fido::FidoAddress> ftn_addresses_;\n  uint16_t wwivnet_node_{0};\n  std::string address_list_;\n};\n\n// Returns just the node number (such as \"1\") from a FTN address like\n// (such as \"20000:20000/1@wwivnet\")\nuint16_t wwivnet_node_number_from_ftn_address(const std::string& address);\n\n// Returns a FTN address like \"20000:20000/1@wwivnet\".\nstd::string ftn_address_from_address_list(const std::string& address_list, const std::string& domain);\nstd::set<sdk::fido::FidoAddress> ftn_addresses_from_address_list(const std::string& address_list, const std::set<sdk::fido::FidoAddress>& known_addresses);\n\n}  // namespace wwiv::net\n\n#endif\n"
  },
  {
    "path": "binkp/todo.txt",
    "content": "TODO for networkb\n=================\n\n5.3?\n====\n* create daemon process to be the listener side\n* create unit tests (started)\n* create way to auto-set password (like wwiv networking did) with binkp\n"
  },
  {
    "path": "binkp/transfer_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/transfer_file.h\"\n\n#include \"core/crc32.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include <chrono>\n#include <cstring>\n#include <string>\n#include <utility>\n\nusing std::chrono::seconds;\nusing std::chrono::system_clock;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net {\n\nTransferFile::TransferFile(std::string filename, time_t timestamp, uint32_t crc)\n  : filename_(std::move(filename)), timestamp_(timestamp), crc_(crc) {}\n\nTransferFile::~TransferFile() = default;\n\nstd::string TransferFile::as_packet_data(int size, int offset) const {\n  auto dataline = fmt::format(\"{} {} {} {}\", filename_, size, timestamp_, offset);\n  if (crc_ != 0) {\n    dataline += fmt::sprintf(\" %08X\", crc_);\n  }\n  return dataline;\n}\n\nInMemoryTransferFile::InMemoryTransferFile(const std::string& filename, const std::string& contents, time_t timestamp)\n  : TransferFile(filename, timestamp, wwiv::core::crc32string(contents)), \n    contents_(contents) {}\n\nInMemoryTransferFile::InMemoryTransferFile(const std::string& filename, const std::string& contents)\n  : InMemoryTransferFile(filename, contents, system_clock::to_time_t(std::chrono::system_clock::now())) {}\n\nInMemoryTransferFile::~InMemoryTransferFile() = default;\n\nbool InMemoryTransferFile::GetChunk(char* chunk, int start, int size) {\n  if (start + size > wwiv::strings::ssize(contents_)) {\n    LOG(ERROR) << \"ERROR InMemoryTransferFile::GetChunk (start + size) > file_size():\"\n        << \"values[ start: \" << start << \"; size: \" << size\n\t      << \"; file_size(): \" << file_size() << \" ]\";\n    return false;\n  }\n  memcpy(chunk, &contents_[start], size);\n  return true;\n}\n\nbool InMemoryTransferFile::WriteChunk(const char* chunk, int size) {\n  contents_.append(std::string(chunk, size));\n  return true;\n}\n\nbool InMemoryTransferFile::Close() {\n  return true;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/transfer_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORKB_TRANSFER_FILE_H\n#define INCLUDED_NETWORKB_TRANSFER_FILE_H\n\n#include \"core/stl.h\"\n#include <chrono>\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::net {\n  \nclass TransferFile {\npublic:\n  TransferFile(std::string filename, time_t timestamp, uint32_t crc);\n  virtual ~TransferFile();\n\n  [[nodiscard]] std::string filename() const { return filename_; }\n  [[nodiscard]] std::string as_packet_data(int offset) const {\n    return as_packet_data(file_size(), offset);\n  }\n\n  [[nodiscard]] virtual int file_size() const = 0;\n  virtual bool Delete() = 0;\n  virtual bool GetChunk(char* chunk, int start, int size) = 0;\n  virtual bool WriteChunk(const char* chunk, int size) = 0;\n  virtual bool Close() = 0;\n\n protected:\n  [[nodiscard]] std::string as_packet_data(int size, int offset) const;\n\n  const std::string filename_;\n  const time_t timestamp_ = 0;\n  const uint32_t crc_ = 0;\n};\n\nclass InMemoryTransferFile : public TransferFile {\npublic:\n  InMemoryTransferFile(const std::string& filename, const std::string& contents, time_t timestamp);\n\n  InMemoryTransferFile(const std::string& filename, const std::string& contents);\n  virtual ~InMemoryTransferFile();\n\n  // for testing.\n  [[nodiscard]] virtual const std::string& contents() const final { return contents_; }\n\n  [[nodiscard]] int file_size() const override final { return stl::size_int(contents_); }\n  bool Delete() override { contents_.clear(); return true; }\n  bool GetChunk(char* chunk, int start, int size) override final;\n  bool WriteChunk(const char* chunk, int size) override final;\n  bool Close() override final;\n\nprivate:\n  std::string contents_;\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "binkp/transfer_file_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"fmt/printf.h\"\n#include \"binkp/transfer_file.h\"\n#include \"binkp/wfile_transfer_file.h\"\n#include <chrono>\n#include <filesystem>\n#include <string>\n\nusing std::chrono::system_clock;\nusing std::chrono::time_point;\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\n\nclass TransferFileTest : public testing::Test {\npublic:\n  TransferFileTest() \n    : now(system_clock::now()), contents(\"ASDF\"), filename(\"test1\"), file(filename, contents, system_clock::to_time_t(now)) {\n    full_filename = file_helper_.CreateTempFile(filename, contents);\n  }\n\n  const time_point<system_clock> now;\n  const std::string contents;\n  const std::string filename;\n  InMemoryTransferFile file;\n  std::filesystem::path full_filename;\n  wwiv::core::test::FileHelper file_helper_;\n};\n\nTEST_F(TransferFileTest, AsPacketData) {\n  const auto expected = fmt::format(\"test1 4 {} 0 67BC1E09\", system_clock::to_time_t(now));\n  ASSERT_EQ(expected, file.as_packet_data(0));\n}\n\nTEST_F(TransferFileTest, Filename) {\n  ASSERT_EQ(filename, file.filename());\n}\n\nTEST_F(TransferFileTest, FileSize) {\n  ASSERT_EQ(wwiv::stl::ssize(contents), file.file_size());\n}\n\nTEST_F(TransferFileTest, GetChunk) {\n  char chunk[100];\n\n  // Partial file.\n  memset(chunk, 0, 100);\n  ASSERT_TRUE(file.GetChunk(chunk, 0, 1));\n  EXPECT_EQ('A', chunk[0]);\n\n  // Entire file.\n  memset(chunk, 0, 100);\n  ASSERT_TRUE(file.GetChunk(chunk, 0, contents.size()));\n  EXPECT_EQ('A', chunk[0]);\n  EXPECT_EQ('S', chunk[1]);\n  EXPECT_EQ('D', chunk[2]);\n  EXPECT_EQ('F', chunk[3]);\n\n  // Goes past the end.\n  memset(chunk, 0, 100);\n  EXPECT_FALSE(file.GetChunk(chunk, 0, contents.size() + 1));\n\n  // Goes past the end.\n  EXPECT_FALSE(file.GetChunk(chunk, contents.size() - 1, 2));\n}\n\nTEST_F(TransferFileTest, WriteChunk) {\n  char chunk[100];\n\n  // Partial file.\n  memset(chunk, 0, 100);\n  memcpy(chunk, \"AB\", 2);\n  ASSERT_TRUE(file.WriteChunk(chunk, 2));\n  EXPECT_EQ(\"ASDFAB\", file.contents());\n}\n\nTEST_F(TransferFileTest, WFileTest_Read) {\n  WFileTransferFile wfile_file(filename, std::make_unique<File>(full_filename));\n  ASSERT_EQ(filename, wfile_file.filename());\n  ASSERT_EQ(wwiv::stl::ssize(contents), wfile_file.file_size());\n\n  char chunk[100];\n\n  // Partial file.\n  memset(chunk, 0, 100);\n  ASSERT_TRUE(wfile_file.GetChunk(chunk, 0, 1));\n  EXPECT_EQ('A', chunk[0]);\n\n  // Entire wfile_file.\n  memset(chunk, 0, 100);\n  ASSERT_TRUE(wfile_file.GetChunk(chunk, 0, contents.size()));\n  EXPECT_EQ('A', chunk[0]);\n  EXPECT_EQ('S', chunk[1]);\n  EXPECT_EQ('D', chunk[2]);\n  EXPECT_EQ('F', chunk[3]);\n\n  // Goes past the end.\n  memset(chunk, 0, 100);\n  EXPECT_FALSE(wfile_file.GetChunk(chunk, 0, contents.size() + 1));\n\n  // Goes past the end.\n  EXPECT_FALSE(wfile_file.GetChunk(chunk, contents.size() - 1, 2));\n  wfile_file.Close();\n}\n\nTEST_F(TransferFileTest, WFileTest_Write) {\n  const std::string empty_filename = StrCat(filename, \"_empty\");\n  const auto empty_file_fullpath = file_helper_.CreateTempFilePath(empty_filename);\n  {\n    WFileTransferFile wfile_file(empty_filename, std::make_unique<File>(empty_file_fullpath));\n    EXPECT_EQ(empty_filename, wfile_file.filename());\n    EXPECT_LE(wfile_file.file_size(), 0);\n\n    wfile_file.WriteChunk(contents.c_str(), contents.size());\n    EXPECT_EQ(wwiv::stl::ssize(contents), wfile_file.file_size());\n    wfile_file.Close();\n  }\n  // Needed wfile_file to go out of scope before the file can be read.\n  EXPECT_EQ(contents, file_helper_.ReadFile(empty_file_fullpath));\n}\n"
  },
  {
    "path": "binkp/wfile_transfer_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/wfile_transfer_file.h\"\n\n#include \"core/crc32.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/fido/fido_util.h\"\n#include <algorithm>\n#include <chrono>\n#include <string>\n\nusing std::chrono::seconds;\nusing std::chrono::system_clock;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net {\n\nWFileTransferFile::WFileTransferFile(const std::string& filename, std::unique_ptr<File>&& file)\n    : TransferFile(filename, file->Exists() ? file->last_write_time() : time_t_now(),\n                   crc32file(file->path())),\n      file_(std::move(file)) {\n  VLOG(1) << \"WFileTransferFile: \" << filename;\n  if (filename.find(File::pathSeparatorChar) != std::string::npos) {\n    // Don't allow filenames with slashes in it.\n    throw std::invalid_argument(\"filename can not be relative pathed\");\n  }\n}\n\nWFileTransferFile::~WFileTransferFile() = default;\n\n// TODO(rushfan): This needs to be fixed to handle >2GB files.\nint WFileTransferFile::file_size() const { return static_cast<int>(file_->length()); }\n\nbool WFileTransferFile::Delete() {\n  // Since this file may still be open, need to ensure\n  // that it is closed so File::Remove will work.\n  if (file_->IsOpen()) {\n    file_->Close();\n  }\n  if (!File::Remove(file_->full_pathname())) {\n    return false;\n  }\n  if (!flo_file_) {\n    return true;\n  }\n  flo_file_->Load();\n  if (flo_file_->flo_entries().size() <= 1) {\n    flo_file_->clear();\n  } else {\n    flo_file_->erase(file_->full_pathname());\n  }\n  return flo_file_->Save();\n}\n\nbool WFileTransferFile::GetChunk(char* chunk, int start, int size) {\n  if (!file_->IsOpen()) {\n    if (!file_->Open(File::modeBinary | File::modeReadOnly)) {\n      return false;\n    }\n  }\n\n  if (static_cast<int>(start + size) > file_size()) {\n    LOG(ERROR) << \"ERROR WFileTransferFile::GetChunk (start + size) > file_size():\"\n               << \"values[ start: \" << start << \"; size: \" << size\n               << \"; file_size(): \" << file_size() << \" ]\";\n    return false;\n  }\n\n  // TODO(rushfan): Cache the current file pointer and only re-seek\n  // if needed (realistically we should ever have to seek after the\n  // first time.\n  file_->Seek(start, File::Whence::begin);\n  return file_->Read(chunk, size) == size;\n}\n\nbool WFileTransferFile::WriteChunk(const char* chunk, int size) {\n  VLOG(3) << \"WFileTransferFile::WriteChunk\";\n  if (!file_->IsOpen()) {\n    if (file_->Exists()) {\n      // Don't overwrite an existing file.  Rename it away to: FILENAME.timestamp\n      auto newpath = file_->path();\n      newpath += StrCat(\".\", system_clock::to_time_t(system_clock::now()));\n      File::Rename(file_->path(), newpath);\n    }\n    if (!file_->Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile)) {\n      return false;\n    }\n  }\n  return file_->Write(chunk, size) == size;\n}\n\nbool WFileTransferFile::Close() {\n  VLOG(1) << \"WFileTransferFile::Close \" << file_->path().string();\n  file_->Close();\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "binkp/wfile_transfer_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORKB_WFILE_TRANSFER_FILE_H__\n#define __INCLUDED_NETWORKB_WFILE_TRANSFER_FILE_H__\n\n#include \"binkp/transfer_file.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/fido/flo_file.h\"\n#include <memory>\n#include <string>\n#include <core/file.h>\n\nnamespace wwiv {\nnamespace net {\n  \nclass WFileTransferFile : public TransferFile {\npublic:\n  WFileTransferFile(const std::string& filename, std::unique_ptr<wwiv::core::File>&& file);\n  virtual ~WFileTransferFile();\n\n  [[nodiscard]] int file_size() const override final;\n  bool Delete() override final;\n  bool GetChunk(char* chunk, int start, int size) override final;\n  bool WriteChunk(const char* chunk, int size) override final;\n  bool Close() override final;\n  void set_flo_file(std::unique_ptr<wwiv::sdk::fido::FloFile>&& f) { flo_file_ = std::move(f); }\n\n private:\n  std::unique_ptr<wwiv::core::File> file_; \n  std::unique_ptr<wwiv::sdk::fido::FloFile> flo_file_;\n};\n\n}  // namespace net\n}  // namespace wwiv\n\n#endif  // __INCLUDED_NETWORKB_WFILE_TRANSFER_FILE_H__\n"
  },
  {
    "path": "brware/bredit/argument.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"ARGUMENT.H\"\r\n#include \"EDITOR.H\"\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#define GetFileString(s, stream) fgets(s, 81, stream); \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t if (strchr(s, '\\n'))  \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t *strchr(s,'\\n')=0;\r\n\r\n\r\nBREditArguments::BREditArguments(int argc, char **argv)\r\n\r\n// BREDIT can accept three different types of command lines:\r\n//\r\n// 1. BREDIT filename.  This is for general purpose editing (perhaps\r\n//    from a //DOS prompt.  It assumes no WWIV handling of codes,\r\n//    sysop mode, and enhanced editing.\r\n//\r\n// 2. BREDIT filename 80 25 200 [params]\r\n//    where [params] is a space-delimited set of options (in any order):\r\n//\r\n//    S   Local Mode\r\n//    D   Disables Enhanced mode\r\n//    E   Disable built-in handling of enhanced mode\r\n//    H   Disables BREDIT's built in extended ANSI handler\r\n//\r\n\r\n{\r\n// Set up defaults\r\n\r\n\tScreenLines=24;\r\n\tMaxColumns=80;\r\n\tAnonymousStatus=0;\r\n\tMaxLines=300;\r\n\tEnhancedMode=AUTO;\r\n        DoEnhancedIO=0;\r\n\tWWIVColorChanges=(getenv(\"BBS\")==NULL) ? 0 : 1;\r\n\tSysOpMode=0;\r\n\tEditFilename=NULL;\r\n\tstrcpy(HelpFile, argv[0]);\r\n\tstrcpy(strchr(HelpFile, '.'), \".HLP\");\r\n        if (argc==2)\r\n        {\r\n                SysOpMode=1;\r\n                WWIVColorChanges=0;\r\n                EditFilename=argv[1];\r\n        }\r\n        else if (argc > 4)\r\n        {\r\n\t\tEditFilename=argv[1];\r\n\t\tMaxColumns=atoi(argv[2]);\r\n\t\tScreenLines=atoi(argv[3])-1;\r\n\t\tMaxLines=atoi(argv[4]);\r\n\r\n\t\tint i;\r\n\r\n\t\tfor(i=5;i<argc;i++) {\r\n                        switch(toupper(argv[i][0]))\r\n                        {\r\n\t\t\tcase 'S':\r\n\t\t\t\tSysOpMode=1;\r\n\t\t\t\tEnhancedMode=ON;\r\n                                DoEnhancedIO=1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'D':\r\n\t\t\t\tEnhancedMode=OFF;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'E':\r\n\t\t\t\tEnhancedMode=ON;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'H':\r\n\t\t\t\tDoEnhancedIO=0;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tFILE *stream;\r\n\t\tchar s[81];\r\n\r\n\t\tTitleChangeable=0;\r\n\t\tEnableTag=1;\r\n                if ((stream=fopen(\"EDITOR.INF\", \"rb\"))!=NULL)\r\n                {\r\n\t\t\tTitleChangeable=1;\r\n\t\t\tGetFileString(Title, stream);\r\n\t\t\tGetFileString(Destination, stream);\r\n\t\t\tif (strchr(Destination, '#'))\r\n                        {\r\n\t\t\t\tEnableTag=0;\r\n                        }\r\n\t\t\tGetFileString(s, stream); // User number\r\n\t\t\tGetFileString(s, stream); // User name\r\n\t\t\tGetFileString(s, stream); // User real name\r\n\t\t\tGetFileString(s, stream); // User SL\r\n\r\n\t\t\tif (atoi(s)==255)\r\n                        {\r\n\t\t\t\tSysOpMode=1;\r\n                        }\r\n\t\t\tGetFileString(s, stream);\r\n\t\t\tif (atoi(s)==1)\r\n                        {\r\n\t\t\t\tEnableTag=0;\r\n                        }\r\n\t\t\tfclose(stream);\r\n\t\t}\r\n        }\r\n        else\r\n        {\r\n\t\tprintf(\"\\n\\nBREdit - Full Screen Editor version %s\\n\\n\"\r\n\t\t\t\t\t\"Invalid parameters given\\n\\n\"\r\n                                        \"BREDIT Filename [Columns Rows MaxLines [S D E H]]\\n\\n\"\r\n\t\t\t\t\t\"See BREDIT.DOC for more information on paramters.\\n\\n\", VERSION);\r\n\t\texit(1);\r\n\t}\r\n}\r\n\r\nBREditArguments::~BREditArguments(void)\r\n{\r\n        if (TitleChangeable)\r\n        {\r\n\t\tFILE *stream;\r\n\t\tstream=fopen(\"RESULT.ED\", \"wt\");\r\n\t\tfprintf(stream, \"%d\\n%s\\n\", AnonymousStatus, Title);\r\n\t\tfclose(stream);\r\n\t}\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "brware/bredit/argument.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef FEDITARG_DOT_H\r\n\r\nclass BREditArguments\r\n{\r\npublic:\r\n\tint ScreenLines, MaxColumns, MaxLines, EnhancedMode,\r\n\t\t\tDoEnhancedIO, WWIVColorChanges, SysOpMode,\r\n\t\t\tTitleChangeable, AnonymousStatus, EnableTag;\r\n\tchar Title[81], Destination[81];\r\n\tchar *EditFilename, HelpFile[81];\r\n\tBREditArguments(int argc, char **argv);\r\n\t~BREditArguments(void);\r\n};\r\n\r\n#define OFF  1\r\n#define ON   2\r\n#define AUTO 3\r\n\r\n#define ANONYMOUS_UNDEFINED 0\r\n#define ANONYMOUS_YES 1\r\n#define ANONYMOUS_NO 2\r\n\r\n#define FEDITARG_DOT_H\r\n\r\n#endif\r\n"
  },
  {
    "path": "brware/bredit/bredit.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"EDITOR.H\"\r\n#include \"ARGUMENT.H\"\r\n\r\nextern unsigned _stklen=8192;\r\n\r\nvoid main(int argc, char **argv)\r\n{\r\n\tBREditArguments FA(argc, argv);\r\n\tIOClass IO(&FA);\r\n\r\n\tEditorClass(&IO, &FA);\r\n}"
  },
  {
    "path": "brware/bredit/bredit.doc",
    "content": "               Ŀ\r\n                              BREdit Version 1.0              \r\n                     Full Screen Message Editor For WWIV      \r\n                Copyright 1999 Art Johnston, BRWare Authors   \r\n                   Based on the code from FEditby Rob Raper   \r\n                    Portions Copyright 1993-1999 Rob Raper    \r\n               \r\n\r\n\r\n\r\n\r\nINSTALLATION\r\n============\r\n\r\nInstallation of BREdit is very striaght forward.\r\n\r\n1) Create a directory to hold BREdit (i.e. C:\\WWIV\\BREDIT)\r\n2) Unzip the distribution (or copy BREDIT.*) to the directory\r\n   2a) i.e. PkUnZip BREDIT10.ZIP C:\\WWIV\\BREDIT\r\n        -or-\r\n   2b) COPY BREDIT* C:\\WWIV\\BREDIT\r\n\r\n\r\n\r\nCONFIGURATION\r\n=============\r\n\r\nAdd an external editor to WWIV via the INIT.EXE command from a dos shell.\r\nHere are the settings to use for BREdit\r\n\r\n      Ŀ\r\n       Description     : BREdit                      \r\n       Filename to run remotely                      \r\n       X:\\WWIV\\BREDIT\\BREDIT %1 %2 %3 %4             \r\n       Filename to run locally                       \r\n       X:\\wwiv\\BREDIT\\BREDIT %1 %2 %3 %4 S           \r\n                                                     \r\n       <ESC> when done.                              \r\n                                                     \r\n       %1 = filename to edit                         \r\n       %2 = chars per line                           \r\n       %3 = lines per page                           \r\n       %4 = max lines                                \r\n       %5 = instance number                          \r\n      \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nACKNOWLEDGEMENTS\r\n================\r\n\r\nSpecial thanks to Rob Raper for allowing BRWare to use the code from FEdit\r\nto create BREdit.\r\n\r\n"
  },
  {
    "path": "brware/bredit/bredit.hlp",
    "content": "If you cannot use the arrow keys due to term program limitations, check to see\r\nif your term program has DOORWAY capability.  If it does, the arrow keys can\r\nbe accessed through it.  \r\n\r\n                            \u00037Ŀ \r\n                            \u00037 \u00031Full Screen Editor \u00037\r\n                            \u00037\r\n\r\n               \u00030(C) Copyright 1999 by Art Johnston, BRWare Authors\r\n                 \u00030(C) Portions Copyright 1990-1995 by Rob Raper\r\n                              All Rights Reserved\r\n\r\nThis editor has been designed with the WWIV standard editor in mind.  Most\r\ncommands are the same, and therefore, macros made for use with the single line\r\neditor will work with this editor.  \r\n\r\n\u00031/S\u00037 or \u00031/ES   -  \u00037Save message                \u00031Ctrl-P  -  \u00037Change colors\r\n\u00031/ABT        -  \u00037Abort message               \u00031Ctrl-W  -  \u00037Delete word\r\n\u00031/C:         -  \u00037Center current line         \u00031Ctrl-N  -  \u00037Same as backspace\r\n\u00031/LI         -  \u00037Text preview                \u00031Ctrl-X  -  \u00037Clear current line\r\n\u00031/CLR        -  \u00037Clear message               \u00031Ctrl-R  -  \u00037Redraw Screen\r\n\u00031HOME        -  \u00037Move to start of line       \u00031Ctrl-Y  -  \u00037Remove current line\r\n\u00031END         -  \u00037Move to end of line         \u00031DEL     -  \u00037Delete character\r\n\u00031Arrow Keys  -  \u00037Maneuver around text        \u00031INS     -  \u00037Toggle insert mode\r\n\r\nThese commands may or may not be available to you:\r\n\r\n\u00031/SY         -  \u00037Save anonymously            \u00031/TI     -  \u00037Change title of post\r\n\u00031/SN         -  \u00037Save non-anonymously\r\n\r\nThe editor will beep when the max lines (displayed on status line) has been\r\nreached.  Macros are fully implimented.  Lines can be broken by hitting return\r\nwhere you want to separate lines, and can be re-joined by using the backspace\r\nor del keys, as many word processors will.\r\n\r\n                       \u00037Ŀ\r\n                       \u00037 \u00031Keyboard Equivalences \u00037\r\n                       \u00037\r\n\r\nSome terminal programs don't follow the ANSI standard for certain keys, but\r\nuse Word Star's command structure instead.  Because WWIV's macros interfere\r\nwith this command set, FEdit can't support it.  It only works with the ANSI\r\nstandard.  This standard is as follows (^[ means Esc):\r\n\r\n\u00031^[[A  \u00037 Up         \u00031^[[B  \u00037 Down         \u00031^[[D  \u00037Left     \u00031   ^[[C  \u00037Right\r\n\u00031^V     \u00037Insert     \u00031^G     \u00037Delete       \u00031^[[H  \u00037Home        \u00031^[[K  \u00037End\r\n\r\n"
  },
  {
    "path": "brware/bredit/bredit.txt",
    "content": "               Ŀ\r\n                              BREdit Version 1.0              \r\n                     Full Screen Message Editor For WWIV      \r\n                Copyright 1999 Art Johnston, BRWare Authors   \r\n                   Based on the code from FEditby Rob Raper   \r\n                    Portions Copyright 1993-1999 Rob Raper    \r\n               \r\n\r\n\r\n\r\n\r\nINSTALLATION\r\n============\r\n\r\nInstallation of BREdit is very striaght forward.\r\n\r\n1) Create a directory to hold BREdit (i.e. C:\\WWIV\\BREDIT)\r\n2) Unzip the distribution (or copy BREDIT.*) to the directory\r\n   2a) i.e. PkUnZip BREDIT10.ZIP C:\\WWIV\\BREDIT\r\n        -or-\r\n   2b) COPY BREDIT* C:\\WWIV\\BREDIT\r\n\r\n\r\n\r\nCONFIGURATION\r\n=============\r\n\r\nAdd an external editor to WWIV via the INIT.EXE command from a dos shell.\r\nHere are the settings to use for BREdit\r\n\r\n      Ŀ\r\n       Description     : BREdit                      \r\n       Filename to run remotely                      \r\n       X:\\WWIV\\BREDIT\\BREDIT %1 %2 %3 %4             \r\n       Filename to run locally                       \r\n       X:\\wwiv\\BREDIT\\BREDIT %1 %2 %3 %4 S           \r\n                                                     \r\n       <ESC> when done.                              \r\n                                                     \r\n       %1 = filename to edit                         \r\n       %2 = chars per line                           \r\n       %3 = lines per page                           \r\n       %4 = max lines                                \r\n       %5 = instance number                          \r\n      \r\n\r\n\r\n\r\n\r\n\r\n\r\nACKNOWLEDGEMENTS\r\n================\r\n\r\nSpecial thanks to Rob Raper for allowing BRWare to use the code from FEdit\r\nto create BREdit.\r\n\r\n"
  },
  {
    "path": "brware/bredit/changelog",
    "content": "BREdit ChangeLog\r\n================\r\n\r\nBREdit 1.1.1\r\n============\r\nAdded /IM for importing files\r\nCleaned up some ANSI display problems.\r\nChanged recommended configuration to 'H' for remote users.\r\n\r\n\r\nBREdit 1.0.2\r\n============\r\nCleaned up some source code.\r\nChanged Fedit* to BREdit*\r\nChanged numbering scheme to three digits\r\n\r\n\r\nBREdit 1.0 (Build 1)\r\n============\r\nChanged name to BREdit\r\nUpdated copyright notices\r\nInitial public release\r\n\r\n\r\n\r\n"
  },
  {
    "path": "brware/bredit/editor.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n// BREdit 2.0 -- Editor Core\r\n// Copyright (C) 1990-1993 by Rob Raper\r\n\r\n#include \"EDITOR.H\"\r\n\r\nEditorClass::EditorClass(IOClass *IOClassPtr, BREditArguments *FA)\r\n{\r\n\tBREditArgs=FA;\r\n\tIO=IOClassPtr;\r\n\r\n\tint ch, FoundWord, i, TabSpacesRemaining=0;\r\n\tint Save=0;\r\n\r\n\r\n\tInsertMode=1;\r\n\tCursorX=0;\r\n\tCursorY=0;\r\n\tPage=0;\r\n\tColor=0;\r\n\tBottomLineUsed=0;\r\n\r\n\tEditorFileClass MainEditorFile(BREditArgs->EditFilename, BREditArgs);\r\n\tQuoteClass Quoter(\"QUOTES.TXT\", IO, &MainEditorFile, BREditArgs);\r\n\r\n\tQuotesAvailable=Quoter.QuotesAvailable;\r\n\r\n\tMainFile=&MainEditorFile;\r\n\r\n        IO->SetColor(1);\r\n        IO->ClearScreen();\r\n        IO->SetColor(0);\r\n\tDrawScreen();\r\n        for(;;)\r\n        {\r\n\t\tIO->MoveTo(CursorX, CursorY+TopLine);\r\n\t\tSetCurrentLine();\r\n                if (TabSpacesRemaining)\r\n                {\r\n\t\t\tch=' ';\r\n\t\t\tTabSpacesRemaining--;\r\n                }\r\n                else\r\n                {\r\n                        ch=IO->GetChar();\r\n                }\r\n                switch(ch)\r\n                {\r\n\t\tcase UNKNOWN:\r\n\t\t\tbreak;\r\n\t\tcase GOT_EANSI:\r\n                        // %%TODO: Remove this\r\n                        sound(200);\r\n                        delay(50);\r\n\t\t\tIO->EANSI_DefineRegion(TopLine, DisplayLines+TopLine);\r\n\t\t\tbreak;\r\n\t\tcase KB_LEFT:\r\n\t\t\tif (CursorX)\r\n                        {\r\n\t\t\t\tCursorX--;\r\n                        }\r\n\t\t\tbreak;\r\n\t\tcase KB_RIGHT:\r\n\t\t\tif (CursorX<CurrentLine->Length)\r\n                        {\r\n\t\t\t\tCursorX++;\r\n                        }\r\n\t\t\tbreak;\r\n\t\tcase KB_UP:\r\n                        if (CurrentLineNumber>0)\r\n                        {\r\n\t\t\t\tDecreaseCursorY();\r\n\t\t\t\tSetCurrentLine();\r\n\t\t\t\tif (CursorX>CurrentLine->Length)\r\n                                {\r\n\t\t\t\t\tCursorX=CurrentLine->Length;\r\n                                }\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase KB_DOWN:\r\n                        if (CurrentLineNumber<MainFile->FileLines-1)\r\n                        {\r\n\t\t\t\tIncreaseCursorY();\r\n\t\t\t\tMainFile->Next(CurrentLine);\r\n\t\t\t\tif (CursorX>CurrentLine->Length)\r\n                                {\r\n                                        CursorX=CurrentLine->Length;\r\n                                }\r\n                        }\r\n\t\t\tbreak;\r\n\t\tcase KB_HOME:\r\n\t\t\tCursorX=0;\r\n\t\t\tbreak;\r\n\t\tcase KB_END:\r\n\t\t\tCursorX=CurrentLine->Length;\r\n\t\t\tbreak;\r\n\t\tcase TAB:\r\n\t\t\tTabSpacesRemaining= (((CursorX + TAB_SIZE) / TAB_SIZE) * TAB_SIZE) - CursorX;\r\n\t\t\tbreak;\r\n\t\tcase ENTER:\r\n\t\t\tColor=0;\r\n                        if (CheckForCommand(\"/SN\") || CheckForCommand(\"/ESN\"))\r\n                        {\r\n\t\t\t\tBREditArgs->AnonymousStatus=ANONYMOUS_NO;\r\n\t\t\t\tSave=1;\r\n                        }\r\n                        else if (CheckForCommand(\"/SY\") || CheckForCommand(\"/ESY\"))\r\n                        {\r\n\t\t\t\tBREditArgs->AnonymousStatus=ANONYMOUS_YES;\r\n\t\t\t\tSave=1;\r\n                        }\r\n                        else if (CheckForCommand(\"/S\") ||  CheckForCommand(\"/ES\"))\r\n                        {\r\n\t\t\t\tBREditArgs->AnonymousStatus=ANONYMOUS_UNDEFINED;\r\n\t\t\t\tSave=1;\r\n\t\t\t}\r\n                        if (Save)\r\n                        {\r\n\t\t\t\tIO->MoveTo(0, BottomLineUsed+TopLine+1);\r\n\t\t\t\tIO->EraseToEnd();\r\n\t\t\t\tMainFile->SaveFile();\r\n\t\t\t\treturn;\r\n                        }\r\n                        else if (CheckForCommand(\"/IN\"))\r\n                        {\r\n\t\t\t\tShowInfo();\r\n\t\t\t\tDrawScreen();\r\n                        }\r\n                        else if (CheckForCommand(\"/IM\"))\r\n                        {\r\n                                if (BREditArgs->SysOpMode)\r\n                                {\r\n                                        char szImportFilename[255];\r\n                                        IO->MoveTo(0,0);\r\n                                        IO->Output(\"Filename: \");\r\n                                        IO->InputLine(szImportFilename, 60);\r\n                                        IO->MoveTo(0,0);\r\n                                        IO->SetColor(1);\r\n                                        IO->EraseToEnd();\r\n                                        ShowTitle();\r\n                                        IO->SetColor(Color);\r\n                                        IO->MoveTo(CursorX, CursorY+TopLine);\r\n                                        IO->EraseToEnd();\r\n                                        if (szImportFilename[0])\r\n                                        {\r\n                                                MainFile->ImportFile(szImportFilename, 0, CurrentLineNumber);\r\n                                        }\r\n                                        else\r\n                                        {\r\n                                                ShowMessage(\"No filename given, File Not Imported.\");\r\n                                        }\r\n                                }\r\n                                else\r\n                                {\r\n                                        ShowMessage(\"You must be a sysop to use this command.\");\r\n                                }\r\n\t\t\t\tDrawScreen();\r\n                        }\r\n                        else if (CheckForCommand(\"/T\"))\r\n                        {\r\n                                if (BREditArgs->TitleChangeable)\r\n                                {\r\n\t\t\t\t\tIO->MoveTo(0,0);\r\n\t\t\t\t\tIO->Output(\"Title: \");\r\n\t\t\t\t\tIO->InputLine(BREditArgs->Title, 60);\r\n\t\t\t\t\tIO->MoveTo(0,0);\r\n\t\t\t\t\tIO->SetColor(1);\r\n\t\t\t\t\tIO->EraseToEnd();\r\n\t\t\t\t\tShowTitle();\r\n\t\t\t\t\tIO->SetColor(Color);\r\n\t\t\t\t\tIO->MoveTo(CursorX, CursorY+TopLine);\r\n\t\t\t\t\tIO->EraseToEnd();\r\n                                }\r\n                                else\r\n                                {\r\n\t\t\t\t\tShowMessage(\"Cannot change title.\");\r\n                                }\r\n                        }\r\n                        else if (CheckForCommand(\"/Q\"))\r\n                        {\r\n                                if (QuotesAvailable)\r\n                                {\r\n\t\t\t\t\tint CurFileLines;\r\n\r\n\t\t\t\t\tCurFileLines=MainFile->FileLines;\r\n\t\t\t\t\tQuoter.Quote(CurrentLineNumber);\r\n\t\t\t\t\tCursorY+=MainFile->FileLines-CurFileLines;\r\n                                        if (CursorY>=DisplayLines)\r\n                                        {\r\n\t\t\t\t\t\tPage+=(CursorY-(DisplayLines-VIEW_LINES));\r\n\t\t\t\t\t\tCursorY-=(CursorY-(DisplayLines-VIEW_LINES));\r\n\t\t\t\t\t}\r\n\t\t\t\t\tDrawScreen();\r\n                                }\r\n                                else\r\n                                {\r\n\t\t\t\t\tShowMessage(\"Quotes not available\");\r\n                                }\r\n                        }\r\n                        else if (CheckForCommand(\"/L\"))\r\n                        {\r\n\t\t\t\tFileView *PreviewScreen;\r\n\t\t\t\tPreviewScreen=new FileView(IO, BREditArgs, MainFile, \"Message Preview\");\r\n\t\t\t\tdelete PreviewScreen;\r\n\t\t\t\tDrawScreen();\r\n                        }\r\n                        else if (CheckForCommand(\"/H\") || CheckForCommand(\"/?\"))\r\n                        {\r\n\t\t\t\tFileView *HelpScreen;\r\n\t\t\t\tEditorFileClass HelpFile(BREditArgs->HelpFile, BREditArgs);\r\n\t\t\t\tHelpScreen=new FileView(IO, BREditArgs, &HelpFile, \"BREdit Help\");\r\n\t\t\t\tdelete HelpScreen;\r\n\t\t\t\tDrawScreen();\r\n                        }\r\n                        else if (CheckForCommand(\"/A\"))\r\n                        {\r\n\t\t\t\tIO->MoveTo(0,0);\r\n\t\t\t\tIO->SetColor(2);\r\n\t\t\t\tIO->Output(\"Abort edit (Y/N)? \");\r\n\t\t\t\tIO->EraseToEnd();\r\n                                if (toupper(IO->GetChar())=='Y')\r\n                                {\r\n\t\t\t\t\tIO->SetColor(1);\r\n\t\t\t\t\tIO->Output(\"Yes\");\r\n\t\t\t\t\tIO->MoveTo(0, BottomLineUsed+TopLine+1);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\tShowTitle();\r\n\t\t\t\tIO->SetColor(Color);\r\n\t\t\t\tIO->MoveTo(CursorX, CursorY+TopLine);\r\n\t\t\t\tIO->EraseToEnd();\r\n                        }\r\n                        else\r\n                        {\r\n\t\t\t\tIncreaseCursorY();\r\n\t\t\t\tDisplay(BREAK_LINE, CursorY-1+Page, CursorX, 1);\r\n\t\t\t\tCursorX=0;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase BACKSPACE:\r\n                        if (CursorX)\r\n                        {\r\n\t\t\t\tCursorX--;\r\n\t\t\t\tMainFile->DeleteCharacter(CursorX, CurrentLineNumber);\r\n                        }\r\n                        else if (CurrentLineNumber)\r\n                        {\r\n\t\t\t\tDecreaseCursorY();\r\n\t\t\t\tSetCurrentLine();\r\n\t\t\t\tCursorX=CurrentLine->Length;\r\n\t\t\t\tCurrentLine->Wrap=1;\r\n\t\t\t}\r\n\t\t\tDisplay(JOIN_LINE, CurrentLineNumber);\r\n\t\t\tbreak;\r\n\t\tcase KB_INS:\r\n\t\t\tInsertMode=!InsertMode;\r\n\t\t\tShowInsertStatus();\r\n\t\t\tbreak;\r\n#ifdef MACRO_SUPPORT\r\n\t\tcase CTRL_A:\r\n\t\tcase CTRL_D:\r\n\t\tcase CTRL_F:\r\n\t\t\tStuffKey(CTRL_P);\r\n\t\t\tStuffKey(ch);\r\n\t\t\tbreak;\r\n#endif\r\n\t\tcase KB_DEL:\r\n\t\tcase CTRL_G:\r\n\t\t\tif (CursorX<CurrentLine->Length)\r\n                        {\r\n\t\t\t\tMainFile->DeleteCharacter(CursorX, CurrentLineNumber);\r\n                        }\r\n\t\t\telse if (CurrentLine->Next)\r\n                        {\r\n\t\t\t\tCurrentLine->Wrap=1;\r\n                        }\r\n\t\t\tDisplay(JOIN_LINE, CurrentLineNumber);\r\n\t\t\tbreak;\r\n\t\tcase CTRL_R:\r\n\t\t\tDrawScreen();\r\n\t\t\tbreak;\r\n\t\tcase CTRL_W:\r\n                        if (CursorX>0)\r\n                        {\r\n\t\t\t\tFoundWord=0;\r\n                                for(i=CursorX-1;i>0;i--)\r\n                                {\r\n\t\t\t\t\tif (CurrentLine->Text[i]!=' ')\r\n                                        {\r\n\t\t\t\t\t\tFoundWord=1;\r\n                                        }\r\n                                        if (CurrentLine->Text[i]==' ' && FoundWord)\r\n                                        {\r\n\t\t\t\t\t\ti++;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tFoundWord=i;\r\n                                for (i=CursorX; i<CurrentLine->Length; i++)\r\n                                {\r\n\t\t\t\t\tCurrentLine->Text[i-(CursorX-FoundWord)]=CurrentLine->Text[i];\r\n\t\t\t\t\tCurrentLine->Color[i-(CursorX-FoundWord)]=CurrentLine->Color[i];\r\n\t\t\t\t}\r\n\t\t\t\tCurrentLine->Length-=CursorX-FoundWord;\r\n\t\t\t\tCursorX=FoundWord;\r\n\t\t\t\tShowOneLine(CursorX, CursorY, ERASE_END);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CTRL_Y:\r\n                        if (CurrentLineNumber+1 < MainFile->FileLines)\r\n                        {\r\n\t\t\t\tCursorX=0;\r\n\t\t\t\tMainFile->RemoveLine(CurrentLineNumber);\r\n                                if (CurrentLineNumber==MainFile->FileLines)\r\n                                {\r\n\t\t\t\t\tDecreaseCursorY();\r\n\t\t\t\t\tShowLines(CursorY+1);\r\n                                }\r\n                                else\r\n                                        if (BREditArgs->EnhancedMode==ON)\r\n                                        {\r\n\t\t\t\t\t\tIO->EANSI_DefineRegion(TopLine+CursorY, DisplayLines+TopLine);\r\n\t\t\t\t\t\tIO->EANSI_ScrollRegionUp();\r\n\t\t\t\t\t\tIO->EANSI_DefineRegion(TopLine, DisplayLines+TopLine);\r\n\t\t\t\t\t\tif (DisplayLines+Page<MainFile->FileLines)\r\n\t\t\t\t\t\t\tShowOneLine(0, DisplayLines, NO_ERASE);\r\n                                        }\r\n                                        else\r\n                                        {\r\n\t\t\t\t\t\tShowLines(CursorY);\r\n                                        }\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\tcase CTRL_X:\r\n\t\t\tCurrentLine->Length=0;\r\n\t\t\tCursorX=0;\r\n\t\t\tIO->MoveTo(CursorX, CursorY+TopLine);\r\n\t\t\tIO->EraseToEnd();\r\n\t\t\tbreak;\r\n\t\tcase CTRL_P:\r\n\t\t\tch=IO->GetChar();\r\n\t\t\tif (ch>='0' && ch<='9')\r\n                        {\r\n\t\t\t\tColor=(ch-'0');\r\n                        }\r\n\t\t\tif (ch>='A' && ch<='Z')\r\n                        {\r\n\t\t\t\tColor=10+(ch-'A');\r\n                        }\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n                        if (ch>31)\r\n                        {\r\n\t\t\t\tMainFile->AddAtX(ch, CursorX, CurrentLineNumber, Color, InsertMode);\r\n\t\t\t\tCursorX++;\r\n\t\t\t\tif ((CursorX==BREditArgs->MaxColumns-1) ||\r\n                                    (InsertMode && (CurrentLine->Length>=BREditArgs->MaxColumns-1)))\r\n                                    {\r\n\t\t\t\t\tFoundWord=0;\r\n                                        for(i=CurrentLine->Length-1; i>=0; i--)\r\n                                        {\r\n\t\t\t\t\t\tif (CurrentLine->Text[i]!=' ')\r\n                                                {\r\n\t\t\t\t\t\t\tFoundWord=1;\r\n                                                }\r\n                                                if (CurrentLine->Text[i]==' ' && FoundWord)\r\n                                                {\r\n\t\t\t\t\t\t\tCursorX--;\r\n\t\t\t\t\t\t\tDisplay(BREAK_LINE, CurrentLineNumber, i+1, NOT_FORCED);\r\n\t\t\t\t\t\t\tCursorX++;\r\n\t\t\t\t\t\t\tSetCurrentLine();\r\n                                                        if (CursorX > CurrentLine->Length)\r\n                                                        {  // Did cursor get wrapped?\r\n\t\t\t\t\t\t\t\tCursorX-=CurrentLine->Length;\r\n\t\t\t\t\t\t\t\tIncreaseCursorY();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n                                        if (i<0)\r\n                                        {\r\n\t\t\t\t\t\tCursorX--;\r\n\t\t\t\t\t\tDisplay(BREAK_LINE, CurrentLineNumber, CursorX, NOT_FORCED);\r\n\t\t\t\t\t\tIncreaseCursorY();\r\n\t\t\t\t\t\tCursorX=1;\r\n\t\t\t\t\t}\r\n                                }\r\n                                else\r\n                                {\r\n\t\t\t\t\tif (InsertMode)\r\n                                        {\r\n\t\t\t\t\t\tShowOneLine(CursorX-1, CursorY, NO_ERASE);\r\n                                        }\r\n                                        else\r\n                                        {\r\n\t\t\t\t\t\tIO->SetColor(Color);\r\n\t\t\t\t\t\tIO->Output((char)ch);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid EditorClass::SetCurrentLine(void)\r\n{\r\n\tCurrentLine=MainFile->GetLine(CurrentLineNumber);\r\n}\r\n\r\n#ifdef MACRO_SUPPORT\r\n\r\nvoid EditorClass::StuffKey(char ch)\r\n// Stuffs a key into the keyboard buffer.  Used for macro implementation.\r\n{\r\n\tint i;\r\n\r\n\tdisable();\r\n\ti = peekb(0, 1052);\r\n\tpokeb(0, i + 1024, ch);\r\n\tif (i == 60)\r\n\t\ti = 28;\r\n\tpokeb(0, 1052, i + 2);\r\n\tenable();\r\n}\r\n\r\n#endif\r\n\r\n#define ADD_TO_ACCEPTABLE(x, desc) AcceptableKeys[NumAcceptable++]=x;  \\\r\n\t\t\t\t\t\t\tstrcat(CommandString, desc);\r\n\r\n/*\r\nvoid EditorClass::BlockCommands()\r\n{\r\n\tchar AcceptableKeys[20], CommandString[81];\r\n\tint NumAcceptable=0;\r\n\r\n\r\n\tstrcpy(CommandString(\"Block: \");\r\n\tADD_TO_ACCEPTABLE('B', \"[B]egin \");\r\n\tADD_TO_ACCEPTABLE('E', \"[E]nd \");\r\n\tADD_TO_ACCEPTABLE('H', \"[H]ide \");\r\n\tif (BREditArgs->SysOpMode)\r\n\t\tADD_TO_ACCEPTABLE('R', \"[R]ead\");\r\n\tif (\r\n\r\n\tIO->MoveTo(0,0);\r\n\tIO->SetColor(1);\r\n}  */\r\n\r\nvoid EditorClass::Display(int Action, int Line, int X, int Type)\r\n{\r\n\tint CurNumLines=MainFile->FileLines, LastJoinedLine;\r\n\r\n\tif (X==NO_PARAMETER)\r\n\t\tX=CursorX;\r\n        switch(Action)\r\n        {\r\n\tcase BREAK_LINE:\r\n\t\tLastJoinedLine=MainFile->BreakLine(X, Line, Type);\r\n\t\tif (LastJoinedLine<0)      // BreakLine ALWAYS modifies next line at least\r\n\t\t\tLastJoinedLine=Line+1;\r\n\t\tbreak;\r\n\tcase JOIN_LINE:\r\n\t\tLastJoinedLine=MainFile->JoinLines(Line);\r\n\t\tbreak;\r\n\t}\r\n\tLine-=Page;\r\n\tShowOneLine(min(X, CursorX), Line, ERASE_END);\r\n\tif (LastJoinedLine<0)\r\n\t\treturn;\r\n\tLastJoinedLine-=Page;  // Put last joined line into page context\r\n\tif (BREditArgs->EnhancedMode==ON && CurNumLines!=MainFile->FileLines) {\r\n\t\tif ((CursorY+Page)<MainFile->FileLines-1) {\r\n\t\t\tIO->EANSI_DefineRegion(LastJoinedLine+TopLine, DisplayLines+TopLine);\r\n\t\t\tif (CurNumLines < MainFile->FileLines) {\r\n\t\t\t\tIO->EANSI_ScrollRegionDown();\r\n\t\t\t\tif (BottomLineUsed<DisplayLines)\r\n\t\t\t\t\tBottomLineUsed++;\r\n\t\t\t} else {\r\n\t\t\t\tIO->EANSI_ScrollRegionUp();\r\n\t\t\t\tif (DisplayLines+Page<MainFile->FileLines) {\r\n\t\t\t\t\tShowOneLine(0, DisplayLines, NO_ERASE);\r\n\t\t\t\t} else\r\n\t\t\t\t\tBottomLineUsed--;\r\n\t\t\t}\r\n\t\t\tIO->EANSI_DefineRegion(TopLine, DisplayLines+TopLine);\r\n\t\t} else\r\n\t\t\tShowOneLine(0, Line+1, ERASE_END);\r\n\t}\r\n\tShowLines(Line+1, LastJoinedLine);\r\n\tif (BREditArgs->EnhancedMode!=ON && CurNumLines!=MainFile->FileLines)\r\n\t\tShowLines(LastJoinedLine+1, DisplayLines);\r\n}\r\n\r\n\r\nint EditorClass::CheckForCommand(char *CompareTo)\r\n{\r\n\tint i;\r\n\r\n\tfor(i=0;i<strlen(CompareTo);i++)\r\n\t\tif (i>=CurrentLine->Length || toupper(CurrentLine->Text[i])!=CompareTo[i])\r\n\t\t\treturn NO_MATCH;\r\n\tCurrentLine->Length=0;\r\n\tCursorX=0;\r\n\treturn MATCH;\r\n}\r\n\r\n\r\nvoid EditorClass::IncreaseCursorY(void)\r\n{\r\n\tLineStruct *OldCurrentLine;\r\n\r\n\tOldCurrentLine=CurrentLine;\r\n\tCursorY++;\r\n\tif (CursorY>=DisplayLines) {\r\n\t\tif (BREditArgs->EnhancedMode==ON) {\r\n\t\t\tPage++;\r\n\t\t\tIO->EANSI_ScrollRegionUp();\r\n\t\t\tif (DisplayLines+Page<MainFile->FileLines)\r\n\t\t\t\tShowOneLine(0, DisplayLines, NO_ERASE);\r\n\t\t\telse\r\n\t\t\t\tBottomLineUsed--;\r\n\t\t\tCursorY--;\r\n\t\t} else {\r\n\t\t\tPage+=(DisplayLines-VIEW_LINES);\r\n\t\t\tCursorY-=(DisplayLines-VIEW_LINES);\r\n\t\t\tShowLines(0);\r\n\t\t}\r\n\t}\r\n\tCurrentLine=OldCurrentLine;\r\n}\r\n\r\nvoid EditorClass::DecreaseCursorY(void)\r\n{\r\n\tLineStruct *OldCurrentLine;\r\n\r\n\tOldCurrentLine=CurrentLine;\r\n\t\tCursorY--;\r\n\tif (CursorY<0) {\r\n\t\tif (BREditArgs->EnhancedMode==ON) {\r\n\t\t\tCursorY=0;\r\n\t\t\tPage--;\r\n\t\t\tIO->EANSI_ScrollRegionDown();\r\n\t\t\tif (BottomLineUsed<DisplayLines)\r\n\t\t\t\tBottomLineUsed++;\r\n\t\t\tShowOneLine(0, CursorY, NO_ERASE);\r\n\t\t} else {\r\n\t\t\tPage-=(DisplayLines-VIEW_LINES);\r\n\t\t\tCursorY+=(DisplayLines-VIEW_LINES);\r\n\t\t\tif (Page<0) {\r\n\t\t\t\tCursorY-=0-Page;\r\n\t\t\t\tPage=0;\r\n\t\t\t}\r\n\t\t\tShowLines(0);\r\n\t\t}\r\n\t}\r\n\tCurrentLine=OldCurrentLine;\r\n}\r\n\r\n\r\nvoid EditorClass::DrawScreen(void)\r\n{\r\n\tIO->SetColor(0);\r\n\tIO->ClearScreen();\r\n\tShowTitleAndBar();\r\n\tShowLines(0);\r\n}\r\n\r\nvoid EditorClass::ShowLines(int FromLine, int StopLine)\r\n{\r\n\tint ToLine, i;\r\n\r\n\tif (StopLine==NO_PARAMETER)\r\n\t\tStopLine=DisplayLines;\r\n\r\n\t#define LastLine (MainFile->FileLines-Page-1)\r\n\r\n\tif (BottomLineUsed>LastLine)\r\n\t\tToLine=BottomLineUsed;\r\n\telse\r\n\t\tToLine=LastLine;\r\n\tif (ToLine>StopLine)\r\n\t\tToLine=StopLine;\r\n\tfor(i=FromLine;i<=ToLine;i++)\r\n\t\tShowOneLine(0, i, ERASE_END);\r\n}\r\n\r\nvoid EditorClass::ShowOneLine(int FromChar, int AtLine, int EraseMode)\r\n{\r\n\tLineStruct *Line;\r\n\tint i;\r\n\r\n\tLine=MainFile->GetLine(Page+AtLine);\r\n\tIO->MoveTo(FromChar, AtLine+TopLine);\r\n\tif (Line) {\r\n\t\tfor(i=FromChar;i<Line->Length;i++) {\r\n\t\t\tIO->SetColor(Line->Color[i]);\r\n\t\t\tIO->Output(Line->Text[i]);\r\n\t\t}\r\n\t\tif (AtLine>BottomLineUsed)\r\n\t\t\tBottomLineUsed=AtLine;\r\n\t}\r\n\tswitch(EraseMode) {\r\n\tcase NO_ERASE:\r\n\t\tbreak;\r\n\tcase ERASE_END:\r\n\t\tIO->EraseToEnd();\r\n\t\tbreak;\r\n\tcase ERASE_SINGLE:\r\n\t\tIO->Output(' ');\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\n\r\nvoid EditorClass::ShowTitleAndBar(void)\r\n{\r\n\tint i;\r\n\r\n\tShowTitle();\r\n\tIO->MoveTo(0, 1);\r\n        IO->SetColor(7);       // 7\r\n\tfor(i=0;i<(BREditArgs->MaxColumns/2)-1;i++)\r\n                IO->Output('');    // \r\n        IO->Output('');            // \r\n\tfor(i=0;i<(BREditArgs->MaxColumns/2)-1;i++)\r\n                IO->Output('');   // \r\n\tIO->SetColor(0);\r\n\tTopLine=2;\r\n\tIO->EANSI_DefineRegion(TopLine, DisplayLines+TopLine);\r\n}\r\n\r\nvoid EditorClass::ShowMessage(char *Message)\r\n{\r\n\tIO->MoveTo(0,0);\r\n\tIO->SetColor(2);\r\n\tIO->Output(Message);\r\n\tIO->Output(\" - Hit a key\");\r\n\tIO->EraseToEnd();\r\n\tIO->GetChar();\r\n\tShowTitle();\r\n\tIO->SetColor(Color);\r\n\tIO->MoveTo(CursorX, CursorY+TopLine);\r\n\tIO->EraseToEnd();\r\n}\r\n\r\n\r\n\r\nvoid EditorClass::ShowTitle()\r\n{\r\n\tIO->SetColor(1);\r\n\tIO->MoveTo(0,0);\r\n\tIO->Output(\"[ BREdit v\");\r\n\tIO->Output(VERSION);\r\n\tIO->Output(\"  /H for help \");\r\n\tif (QuotesAvailable)\r\n\t\tIO->Output(\" /Q to quote \");\r\n\tIO->Output(\" Max \");\r\n\tIO->Output(BREditArgs->MaxLines);\r\n\tIO->Output(\" lines ]\");\r\n\tShowInsertStatus();\r\n}\r\n\r\n\r\nvoid EditorClass::ShowInsertStatus(void)\r\n{\r\n\tIO->MoveTo(75, 0);\r\n\tif (InsertMode) {\r\n\t\tIO->SetColor(2);\r\n\t\tIO->Output(\"Ins\");\r\n\t} else\r\n\t\tIO->Output(\"   \");\r\n}\r\n\r\nvoid EditorClass::ShowInfoLine(char *Item, char *Setting, int &Line)\r\n{\r\n\tIO->MoveTo(0, Line);\r\n\tIO->SetColor(0);\r\n\tIO->Output(Item);\r\n\tIO->MoveTo(30, Line);\r\n\tIO->SetColor(5);\r\n\tIO->Output(Setting);\r\n\tLine++;\r\n}\r\n\r\n\r\nvoid EditorClass::ShowInfo(void)\r\n{\r\n\tchar s[81];\r\n\tint i;\r\n\r\n\tIO->ClearScreen();\r\n\tIO->SetColor(1);\r\n\tIO->MoveTo(0,0);\r\n\tIO->Output(\"BREdit Version \");\r\n\tIO->Output(VERSION);\r\n\tIO->Output(\"  (C)Copyright 1999 by BRWare\");\r\n\tIO->MoveTo(0,1);\r\n\tIO->SetColor(7);\r\n\tfor(i=0;i<79;i++)\r\n\t\tIO->Output('');\r\n\ti=3;\r\n\tShowInfoLine(\"Enhanced Mode\", (BREditArgs->EnhancedMode==ON) ? \"ON\" :\r\n\t\t\t\t\t\t\t \"OFF (Try using VT102 Emulation)\", i);\r\n\tShowInfoLine(\"SysOp Mode\", (BREditArgs->SysOpMode) ? \"ON\" : \"OFF\", i);\r\n\tsprintf(s, \"%d lines, %d columns\", BREditArgs->MaxLines, BREditArgs->MaxColumns);\r\n\tShowInfoLine(\"Limits\", s, i);\r\n\tShowInfoLine(\"Quotes\", QuotesAvailable ? \"Available\" : \"Not Available\", i);\r\n\tif (BREditArgs->TitleChangeable) {\r\n\t\tShowInfoLine(\"Title\", BREditArgs->Title, i);\r\n\t\tShowInfoLine(\"Destination\", BREditArgs->Destination, i);\r\n\t\tShowInfoLine(\"Tag Line\", (BREditArgs->EnableTag) ? \"Enabled\" : \"Disabled\", i);\r\n\t} else {\r\n\t\tShowInfoLine(\"Message Information\", \"Not Available\", i);\r\n\t}\r\n        ShowInfoLine(\"DoEnahancedIO\", (BREditArgs->DoEnhancedIO) ? \"ON\" : \"OFF\", i);\r\n\tIO->GetChar();\r\n}\r\n\r\n"
  },
  {
    "path": "brware/bredit/editor.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef EDTIOR_DOT_H\r\n\r\n#include \"FEDITIO.H\"\r\n#include \"ARGUMENT.H\"\r\n#include \"FILEMGR.H\"\r\n#include \"QUOTE.H\"\r\n#include \"FILEVIEW.H\"\r\n\r\n#include <string.h>\r\n#include <stdlib.h>\r\n\r\n#include \"version.h\"\r\n\r\n#define VIEW_LINES 3\r\n\r\n#define NO_PARAMETER -1\r\n\r\n#define FORCED 1\r\n#define NOT_FORCED 0\r\n\r\n#define MATCH 1\r\n#define NO_MATCH 0\r\n\r\n#define ERASE_END 1\r\n#define ERASE_SINGLE 2\r\n#define NO_ERASE 0\r\n\r\n#define TAB_SIZE 5\r\n\r\n#define JOIN_LINE 1\r\n#define BREAK_LINE 2\r\n\r\n#ifndef min\r\n#define min(a, b) ((a < b) ? a : b)\r\n#endif\r\n\r\n#define DisplayLines ((BREditArgs->ScreenLines-1)-TopLine)\r\n#define CurrentLineNumber (CursorY+Page)\r\n\r\n#define MACRO_SUPPORT\r\n\r\nclass EditorClass\r\n{\r\npublic:\r\n\tint CursorX, CursorY, Color, Page, TopLine;\r\n\tint InsertMode, BottomLineUsed, QuotesAvailable;\r\n\tLineStruct *CurrentLine;\r\n\r\n\tIOClass *IO;\r\n\tBREditArguments *BREditArgs;\r\n\tEditorFileClass *MainFile;\r\n\r\n\tvoid Display(int Action, int Line, int X=NO_PARAMETER, int Type=NO_PARAMETER);\r\n\tvoid RedrawScreen(void);\r\n\tvoid ShowTitle(void);\r\n\tvoid ShowTitleAndBar(void);\r\n\tvoid ShowInsertStatus(void);\r\n\tvoid PrintCurrentLine(int StartX);\r\n\tvoid DrawScreen(void);\r\n\tvoid IncreaseCursorY(void);\r\n\tvoid DecreaseCursorY(void);\r\n\tvoid ShowLines(int FromLine, int ToLine=NO_PARAMETER);\r\n\tvoid SetCurrentLine(void);\r\n\tint CheckForCommand(char *CompareTo);\r\n\tvoid ShowInfoLine(char *Item, char *Setting, int &Line);\r\n\tvoid ShowInfo(void);\r\n\tvoid ShowOneLine(int Xpos, int LineNumber, int EraseMode);\r\n\tvoid BlockCommands();\r\n\tvoid ShowMessage(char *Message);\r\n\tvoid StuffKey(char ch);\r\n\tEditorClass(IOClass *IO, BREditArguments *FA);\r\n};\r\n\r\n#define EDITOR_DOT_H\r\n\r\n#endif\r\n"
  },
  {
    "path": "brware/bredit/feditio.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n// FEDIT 2.0 Intelligent Optimizing ANSI IO routines\r\n// with Enhanced ANSI support.  Enhanced ANSI commands are\r\n// actually supported by VT100, but since VT100 is actually\r\n// a superset of ANSI, most term programs allow the commands\r\n// to go through.   If not, all the user must do is turn\r\n// VT100 emulation on.  Definitely worth while for the speed increase\r\n//\r\n// (C) 1990-1993 by Rob Raper\r\n\r\n#include \"FEDITIO.H\"\r\n#include <conio.h>\r\n#include <mem.h>\r\n\r\n//#define DEBUG\r\n\r\nIOClass::IOClass(BREditArguments *FA)\r\n{\r\n        // Rushfan add - tidy up 1st\r\n        textattr(0x07);\r\n        clrscr();\r\n\r\n\tBREditArgs=FA;\r\n\tScreen = (int *)MK_FP((peekb(0x0, 0x449)==0x07) ? 0xb000 : 0xb800, 0);\r\n\tint21 = (void (interrupt *)())getvect(0x21);\r\n\tif (FA->EnhancedMode==AUTO)\r\n\t\tOutput(\"\\x1bZ\");  // Tell VT100 type terminal to return some value\r\n}\r\n\r\nIOClass::~IOClass()\r\n{\r\n        // EANSI_DefineRegion();\r\n        EANSI_DefineRegion(0, 24);\r\n}\r\n\r\nvoid IOClass::ClearScreen(void)\r\n{\r\n\tXTracking=0;\r\n\tYTracking=0;\r\n\tOutput(\"\\x1b[2J\");\r\n}\r\n\r\n\r\nvoid IOClass::MoveTo(int x, int y)\r\n\r\n// Optimizing MoveTo command.  Finds the smallest possible\r\n// code to perform the function necessary.  Note that if the\r\n// screen scrolls inadvertently, tracking becomes incorrect, however\r\n// FEDIT assumes a never-scrolling screen.\r\n\r\n{\r\n\tchar s[20];\r\n\r\n\tif (y==YTracking && x==XTracking)\r\n\t\treturn;\r\n\ts[0]=0;\r\n\tif (x==0)\r\n\t\tOutput('\\r');\r\n\tif (y==YTracking+1)\r\n\t\tOutput('\\n');\r\n\tif (y==YTracking+1)\r\n\t\tOutput('\\n');\r\n\tif (y==YTracking && x==XTracking)\r\n\t\treturn;\r\n\tif (y==YTracking) {\r\n\t\tif (x>XTracking)\r\n\t\t\tOutputMovementCode(x-XTracking, 'C');\r\n\t\telse if (x<XTracking)\r\n\t\t\tOutputMovementCode(XTracking-x, 'D');\r\n\t} else\r\n\t\tsprintf(s, \"\\x1b[%d;%dH\", y+1, x+1);\r\n\tOutput(s);\r\n\tXTracking=x;\r\n\tYTracking=y;\r\n}\r\n\r\nvoid IOClass::OutputMovementCode(int num, char code)\r\n{\r\n\tOutput('\\x1b');\r\n\tOutput('[');\r\n\tif (num > 1)\r\n\t\tOutput(num);\r\n\tOutput(code);\r\n}\r\n\r\nvoid IOClass::SaveCursorPosition(void)\r\n{\r\n\tXTrackingSave=XTracking;\r\n\tYTrackingSave=YTracking;\r\n\tOutput(\"\\x1b[s\");\r\n}\r\n\r\nvoid IOClass::RestoreCursorPosition(void)\r\n{\r\n\tOutput(\"\\x1b[u\");\r\n\tXTracking=XTrackingSave;\r\n\tYTracking=YTrackingSave;\r\n}\r\n\r\n#define SCREEN_LOCATION(x,y) (x*80+y)\r\n\r\nvoid IOClass::EraseToEnd(void)\r\n{\r\n\tSetColor(0);\r\n\tOutput(\"\\x1b[K\");\r\n}\r\n\r\n\r\nvoid IOClass::EANSI_InsertCharacter(void)\r\n{\r\n#ifndef DEBUG\r\n\tOutput(\"\\x1b[@\");\r\n#endif\r\n\tif (BREditArgs->DoEnhancedIO) {\r\n\r\n\t\tint Location;\r\n\r\n\t\tLocation=SCREEN_LOCATION(XTracking, YTracking);\r\n\t\tmemmove(&Screen[Location+1], &Screen[Location], (79-XTracking) * sizeof(int));\r\n\t\tScreen[Location]=0x0700;\r\n\t}\r\n}\r\n\r\nvoid IOClass::EANSI_DeleteCharacter(void)\r\n{\r\n#ifndef DEBUG\r\n\tOutput(\"\\x1b[P\");\r\n#endif\r\n\tif (BREditArgs->DoEnhancedIO) {\r\n\r\n\t\tint Location;\r\n\r\n\t\tLocation=SCREEN_LOCATION(XTracking, YTracking);\r\n\t\tmemmove(&Screen[Location], &Screen[Location+1], (79-XTracking) * sizeof(int));\r\n\t}\r\n}\r\n\r\n\r\nvoid IOClass::EANSI_DefineRegion(void)\r\n{\r\n\tSaveCursorPosition();\r\n\tOutput(\"\\x1b[r\");\r\n\tRestoreCursorPosition();\r\n\tCurScrollStart=0;\r\n\tCurScrollEnd=BREditArgs->ScreenLines-1;\r\n}\r\n\r\nvoid IOClass::EANSI_DefineRegion(int from, int to)\r\n{\r\n\tchar s[81];\r\n\r\n#ifdef DEBUG\r\n\tsound(200);\r\n\tdelay(10);\r\n\tnosound();\r\n#endif\r\n        // Change (wrapped in DoEnhancedIO)\r\n\tif (BREditArgs->DoEnhancedIO) {\r\n                SaveCursorPosition();\r\n                sprintf(s,\"\\x1b[%d;%dr\", from+1, to+1);\r\n                Output(s);\r\n                RestoreCursorPosition();\r\n                CurScrollStart=from;\r\n                CurScrollEnd=to;\r\n        }\r\n}\r\n\r\nvoid IOClass::EANSI_ScrollRegionUp(void)\r\n{\r\n\tint y;\r\n#ifndef DEBUG\r\n\tMoveTo(0, CurScrollEnd);\r\n\tif (BREditArgs->DoEnhancedIO)\r\n\t\tgotoxy(1, CurScrollEnd);\r\n\tOutput('\\n');\r\n#endif\r\n\tif (BREditArgs->DoEnhancedIO) {\r\n\t\tunion REGS regs;\r\n\r\n\t\tregs.h.ah = 6;\r\n\t\tregs.h.al = 1;\r\n\t\tregs.h.ch = CurScrollStart;\r\n\t\tregs.h.cl = 0;\r\n\t\tregs.h.dh = CurScrollEnd;\r\n\t\tregs.h.dl = 79;\r\n\t\tregs.h.bh = 0x07;\r\n\t\tint86(0x10, &regs, &regs);\r\n\t}\r\n}\r\n\r\n\r\nvoid IOClass::EANSI_ScrollRegionDown(void)\r\n{\r\n\tchar s[81];\r\n\tint y;\r\n\r\n#ifndef DEBUG\r\n\tMoveTo(0, CurScrollStart);\r\n\tOutput(\"\\x1bM\");\r\n#endif\r\n\tif (BREditArgs->DoEnhancedIO) {\r\n\t\tunion REGS regs;\r\n\r\n\t\tregs.h.ah = 7;\r\n\t\tregs.h.al = 1;\r\n\t\tregs.h.ch = CurScrollStart;\r\n\t\tregs.h.cl = 0;\r\n\t\tregs.h.dh = CurScrollEnd;\r\n\t\tregs.h.dl = 79;\r\n\t\tregs.h.bh = 0x07;\r\n\t\tint86(0x10, &regs, &regs);\r\n\t}\r\n}\r\n\r\nvoid IOClass::SetColor(color_t NewColor)\r\n\r\n// Num is a color number from 0-36.  0-9 are represented as digits,\r\n// 10-36 are represented as A-Z.  If a color is not supported (i.e. standard\r\n// DOS mode is enabled.  Set_color attempts to remember the last\r\n// color set.  It will not attempt to change the color again unless\r\n// it differs from the last value.\r\n\r\n{\r\n\tstatic int LastColor=255;   // Force first color to be different\r\n\r\n\tchar *AnsiColors[] = {\r\n\t\t\t\t \"\\x1b[0m\",\r\n\t\t\t\t \"\\x1b[0;1;36m\",\r\n\t\t\t\t \"\\x1b[0;1;33m\",\r\n\t\t\t\t \"\\x1b[0;35m\",\r\n\t\t\t\t \"\\x1b[0;1;44m\",\r\n\t\t\t\t \"\\x1b[0;0;32m\",\r\n\t\t\t\t \"\\x1b[0;1;5;31m\",\r\n\t\t\t\t \"\\x1b[0;1;34m\"};\r\n\r\n\tif (NewColor==LastColor)\r\n\t\treturn;\r\n\tif (!BREditArgs->WWIVColorChanges) {\r\n\t\tif (NewColor<8)\r\n\t\t\tOutput(AnsiColors[NewColor]);\r\n\t} else {\r\n\t\tOutput(COLOR_CHANGE_CODE);\r\n\t\tif (NewColor<10)\r\n\t\t\tOutput(NewColor);\r\n\t\telse\r\n\t\t\tOutput('A'+(char)(NewColor-10));\r\n\t}\r\n\tLastColor=NewColor;\r\n}\r\n\r\n\r\nvoid IOClass::Output(char ch)\r\n{\r\n\tstatic int TrackingHold;\r\n\r\n\tswitch(TrackingHold) {\r\n\tcase WAITING_ANSI_CODE:\r\n\t\tif (ch!='[' && ch!=';' && !isdigit(ch))\r\n\t\t\tTrackingHold=0;\r\n\t\tbreak;\r\n\tcase WAITING_WWIV_CODE:\r\n\t\tTrackingHold=0;\r\n\t\tbreak;\r\n\tcase NOT_WAITING:\r\n\t\tswitch(ch) {\r\n\t\tcase ESC:\r\n\t\t\tTrackingHold=WAITING_ANSI_CODE;\r\n\t\t\tbreak;\r\n\t\tcase CTRL_C:\r\n\t\t\tTrackingHold=WAITING_WWIV_CODE;\r\n\t\t\tbreak;\r\n\t\tcase ENTER:\r\n\t\t\tXTracking=0;\r\n\t\t\tbreak;\r\n\t\tcase BACKSPACE:\r\n\t\t\tXTracking--;\r\n\t\t\tbreak;\r\n\t\tcase LINEFEED:\r\n\t\t\tYTracking++;\r\n\t\t\tbreak;\r\n\t\tcase BEEP:\r\n      break;\r\n\t\tdefault:\r\n\t\t\tXTracking++;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tenable();\r\n\t_AH = 2;\r\n\t_DL = ch;\r\n\tint21();\r\n}\r\n\r\n\r\nvoid IOClass::Output(int n)\r\n{\r\n\tchar s[21];\r\n\r\n\titoa(n, s, 10);\r\n\tOutput(s);\r\n}\r\n\r\n\r\n\r\nvoid IOClass::Output(char *s)\r\n{\r\n\tint i;\r\n\r\n\tfor(i=0;s[i];i++)\r\n\t\tOutput(s[i]);\r\n}\r\n\r\n\r\nint IOClass::GetChar(void)\r\n{\r\n\tclock_t t;\r\n\tunsigned char ch;\r\n\tstatic char ForcedCh=0;\r\n\r\n\tif (ForcedCh) {\r\n\t\tch=ForcedCh;\r\n\t\tForcedCh=0;\r\n\t\treturn(ch);\r\n\t}\r\n\tswitch((ch=GetRawChar())) {\r\n\tcase 0:\r\n\t\tswitch(GetRawChar()) {\r\n\t\tcase 71:\r\n\t\t\treturn KB_HOME;\r\n\t\tcase 72:\r\n\t\t\treturn KB_UP;\r\n\t\tcase 73:\r\n\t\t\treturn KB_PGUP;\r\n\t\tcase 75:\r\n\t\t\treturn KB_LEFT;\r\n\t\tcase 77:\r\n\t\t\treturn KB_RIGHT;\r\n\t\tcase 79:\r\n\t\t\treturn KB_END;\r\n\t\tcase 80:\r\n\t\t\treturn KB_DOWN;\r\n\t\tcase 81:\r\n\t\t\treturn KB_PGDN;\r\n\t\tcase 82:\r\n\t\t\treturn KB_INS;\r\n\t\tcase 83:\r\n\t\t\treturn KB_DEL;\r\n\t\t}\r\n\t\tbreak;\r\n\tcase 27:\r\n\t\tt=clock()+8;\r\n\t\twhile(clock()<t && !IsKeyWaiting());\r\n\t\tch=0;\r\n\t\tif (!IsKeyWaiting() || (ch=GetRawChar()) != '[') {\r\n\t\t\tForcedCh=ch;\r\n\t\t\treturn 27;\r\n\t\t}\r\n\t\tif (ch=='[') switch(GetRawChar()) {\r\n\t\tcase 'A':\r\n\t\t\treturn KB_UP;\r\n\t\tcase 'B':\r\n\t\t\treturn KB_DOWN;\r\n\t\tcase 'C':\r\n\t\t\treturn KB_RIGHT;\r\n\t\tcase 'D':\r\n\t\t\treturn KB_LEFT;\r\n\t\tcase 'H':\r\n\t\t\treturn KB_HOME;\r\n\t\tcase 'K':\r\n\t\t\treturn KB_END;\r\n\t\tcase '?':  // Got VT100 EANSI support\r\n\t\t\twhile(GetRawChar()!='c');\r\n\t\t\tBREditArgs->EnhancedMode=ON;\r\n\t\t\treturn GOT_EANSI;\r\n\t\t}\r\n\t\tbreak;\r\n\tdefault:\r\n\t\treturn(ch);\r\n\t}\r\n\treturn(0);\r\n}\r\n\r\n\r\nunsigned char IOClass::GetRawChar(void)\r\n{\r\n\tenable();\r\n\t_AH=8;\r\n\tint21();\r\n\treturn (_AL);\r\n}\r\n\r\n\r\nint IOClass::IsKeyWaiting(void)\r\n{\r\n  return(kbhit());\r\n}\r\n\r\n\r\nvoid IOClass::InputLine(char *s, int MaxChars)\r\n{\r\n\tint CurrentLength=0, ch, i;\r\n\r\n\tSetColor(4);\r\n\tSaveCursorPosition();\r\n\tfor(i=0;i<MaxChars;i++)\r\n\t\tOutput(' ');\r\n\tRestoreCursorPosition();\r\n\tfor(;;) {\r\n\t\tswitch(ch=GetChar()) {\r\n\t\tcase BACKSPACE:\r\n\t\t\tif (CurrentLength>0) {\r\n\t\t\t\tOutput(\"\\b \\b\");\r\n\t\t\t\tCurrentLength--;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ENTER:\r\n\t\t\ts[CurrentLength]=0;\r\n\t\t\treturn;\r\n\t\tdefault:\r\n\t\t\tif (ch>31 && CurrentLength<MaxChars) {\r\n\t\t\t\ts[CurrentLength++]=(char)ch;\r\n\t\t\t\tOutput((char)ch);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "brware/bredit/feditio.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef FEDITIO_DOT_H\r\n\r\n#include \"ARGUMENT.H\"\r\n\r\n#include <stdio.h>\r\n#include <string.h>\r\n#include <ctype.h>\r\n#include <stdlib.h>\r\n#include <dos.h>\r\n#include <time.h>\r\n\r\n#define KB_UP       -1\r\n#define KB_DOWN     -2\r\n#define KB_LEFT     -3\r\n#define KB_RIGHT    -4\r\n#define KB_PGUP     -5\r\n#define KB_PGDN     -6\r\n#define KB_HOME     -7\r\n#define KB_END      -8\r\n#define KB_INS      -9\r\n#define KB_DEL      -10\r\n#define KB_ESC      -11\r\n#define GOT_EANSI   -100\r\n\r\n#define NOT_WAITING         0\r\n#define WAITING_ANSI_CODE   1\r\n#define WAITING_WWIV_CODE   2\r\n\r\nenum CTRL_CODES\r\n{\r\n    UNKNOWN=0, CTRL_A=1,CTRL_B, CTRL_C, CTRL_D, CTRL_E, CTRL_F,\r\n    CTRL_G, BACKSPACE, TAB, CTRL_J, CTRL_K, CTRL_L,\r\n    ENTER, CTRL_N, CTRL_O, CTRL_P, CTRL_Q, CTRL_R,\r\n    CTRL_S, CTRL_T, CTRL_U, CTRL_V, CTRL_W, CTRL_X,\r\n    CTRL_Y, CTRL_Z, ESC\r\n};\r\n\r\n\r\n#define LINEFEED            '\\x0a'\r\n#define BEEP                '\\x07'\r\n#define COLOR_CHANGE_CODE   '\\x03'\r\n\r\n#define color_t unsigned char\r\n\r\nclass IOClass\r\n{\r\n\tint XTracking, YTracking;\r\n\tint XTrackingSave, YTrackingSave;\r\n\tint CurScrollStart, CurScrollEnd;\r\n\tint far *Screen;\r\n\tBREditArguments *BREditArgs;\r\n\tvoid far interrupt(*int21) ();\r\n\tunsigned char GetRawChar(void);\r\n\tvoid OutputMovementCode(int num, char code);\r\n\r\npublic:\r\n\tIOClass(BREditArguments *FA);\r\n\t~IOClass();\r\n\tvoid Output(char ch);\r\n\tvoid Output(char *s);\r\n\tvoid Output(int n);\r\n\tint GetChar(void);\r\n\tint IsKeyWaiting(void);\r\n\tvoid SetColor(color_t num);\r\n\tvoid ClearScreen(void);\r\n\tvoid MoveTo(int x, int y);\r\n\tvoid EraseToEnd(void);\r\n\tvoid SaveCursorPosition();\r\n\tvoid RestoreCursorPosition();\r\n\tvoid EANSI_DefineRegion(void);\r\n\tvoid EANSI_DefineRegion(int start, int end);\r\n\tvoid EANSI_InsertCharacter(void);\r\n\tvoid EANSI_DeleteCharacter(void);\r\n\tvoid EANSI_ScrollRegionUp(void);\r\n\tvoid EANSI_ScrollRegionDown(void);\r\n\tvoid InputLine(char *s, int MaxChars);\r\n};\r\n\r\n#define FEDITIO_DOT_H\r\n\r\n#endif\r\n"
  },
  {
    "path": "brware/bredit/filemgr.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include <stdio.h>\r\n#include \"EDITOR.H\"\r\n#include \"FILEMGR.H\"\r\n\r\nEditorFileClass::EditorFileClass(char *Fn, BREditArguments *FA)\r\n{\r\n\tFirstLine=NULL;\r\n\tFileLines=0;\r\n\tBREditArgs=FA;\r\n\tFilename=Fn;\r\n\tMakeNewLine(0);\r\n\tImportFile(Filename, 0, 0);\r\n}\r\n\r\nEditorFileClass::~EditorFileClass(void)\r\n{\r\n\twhile(FileLines)\r\n\t\tRemoveLine(0);\r\n}\r\n\r\nint EditorFileClass::ImportFile(char *Filename, int x, int AtLine)\r\n{\r\n\tFILE *stream;\r\n\tint CurrentColor=0, ch, i;\r\n\tint Done=0; \t\t\t// LineCount=0;\r\n\tint LineNumber=AtLine;\r\n\tLineStruct *Line;\r\n\r\n\tif ((stream=fopen(Filename, \"rb\"))==NULL)\r\n\t\treturn(FILE_NOT_FOUND);\r\n\tBreakLine(x, LineNumber, 0);\r\n\tLineNumber++;\r\n\tLine=MakeNewLine(LineNumber);\r\n\twhile(!feof(stream)) {\r\n\t\tch=fgetc(stream);\r\n\t\tswitch(ch) {\r\n\t\tcase 2:\r\n\t\t\tstrcpy(Line->Text, \"/C:\");\r\n\t\t\tmemset(Line->Color, 0, 3);\r\n\t\t\tLine->Length=3;\r\n\t\t\tbreak;\r\n\t\tcase 4:\r\n\t\t\tDone=0;\r\n\t\t\twhile(!Done) {\r\n\t\t\t\tswitch(fgetc(stream)) {\r\n\t\t\t\tcase EOF:\r\n\t\t\t\t\tDone=1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 13:\r\n\t\t\t\t\tDone=1;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tch=fgetc(stream);\r\n\t\t\tif (ch>='0' && ch<='9')\r\n\t\t\t\tCurrentColor=ch-'0';\r\n\t\t\tif (ch>='A' && ch<='Z')\r\n\t\t\t\tCurrentColor=10+ch-'A';\r\n\t\t\tbreak;\r\n\t\tcase 13:\r\n\t\t\twhile(Line->Length && Line->Text[Line->Length-1]==' ')\r\n\t\t\t\t(Line->Length)--;\r\n\t\t\tLineNumber++;\r\n\t\t\tLine=MakeNewLine(LineNumber);\r\n\t\t\tCurrentColor=0;\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tLine->Wrap=1;\r\n\t\t\tbreak;\r\n\t\tcase TAB:\r\n\t\t\tif (Line->Length < BREditArgs->MaxColumns-5) {\r\n\t\t\t\tint AddSpaces;\r\n\t\t\t\tAddSpaces= (((Line->Length + TAB_SIZE) / TAB_SIZE) * TAB_SIZE) - Line->Length;\r\n\t\t\t\tfor(i=0;i<AddSpaces;i++) {\r\n\t\t\t\t\tLine->Text[Line->Length]=' ';\r\n\t\t\t\t\tLine->Color[(Line->Length++)]=CurrentColor;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase BACKSPACE:\r\n\t\t\tif (Line->Length)\r\n\t\t\t\tLine->Length--;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif (ch>31 && (Line->Length) < BREditArgs->MaxColumns) {\r\n\t\t\t\tLine->Text[Line->Length]=ch;\r\n\t\t\t\tLine->Color[Line->Length]=CurrentColor;\r\n\t\t\t\t(Line->Length)++;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tLine->Wrap=1;\r\n\tJoinLines(LineNumber);\r\n\tJoinLines(AtLine);\r\n\tfclose(stream);\r\n\treturn(FILE_OK);\r\n}\r\n\r\nvoid EditorFileClass::ExportLine(FILE *stream, LineStruct *Line, int FromColumn, int ToColumn)\r\n{\r\n\tint CurrentColor=0, i;\r\n\r\n\tfor(i=FromColumn;i<=ToColumn;i++) {\r\n\t\tif (i==0 && !strnicmp(\"/C:\", Line->Text, 3)) {\r\n\t\t\tfputc('\\x02', stream);\r\n\t\t\ti=3;\r\n\t\t}\r\n\t\tif (Line->Color[i]!=CurrentColor) {\r\n\t\t\tCurrentColor=Line->Color[i];\r\n\t\t\tfputc('\\x03', stream);\r\n\t\t\tif (CurrentColor<10)\r\n\t\t\t\tfputc(CurrentColor+'0', stream);\r\n\t\t\telse\r\n\t\t\t\tfputc(CurrentColor+'A'-10, stream);\r\n\t\t}\r\n\t\tfputc(Line->Text[i], stream);\r\n\t}\r\n\tif (Line->Wrap)\r\n\t\tfputc('\\x01', stream);\r\n\tfputc('\\r', stream);\r\n\tfputc('\\n', stream);\r\n}\r\n\r\nvoid EditorFileClass::SaveFile()\r\n{\r\n\tLineStruct *CurrentLine;\r\n\tFILE *stream;\r\n\tint i;\r\n\r\n\tstream=fopen(Filename, \"wb\");\r\n\tCurrentLine=FirstLine;\r\n\tfor(i=0;i<FileLines;i++) {\r\n\t\tExportLine(stream, CurrentLine, 0, CurrentLine->Length-1);\r\n\t\tNext(CurrentLine);\r\n\t}\r\n\tfclose(stream);\r\n}\r\n\r\n\r\n\r\nLineStruct *EditorFileClass::GetLine(int LineNum)\r\n{\r\n\tLineStruct *Line;\r\n\tint i;\r\n\r\n\tLine=FirstLine;\r\n\tfor(i=0;i<LineNum;i++)\r\n\t\tNext(Line);\r\n\treturn(Line);\r\n}\r\n\r\nvoid EditorFileClass::AddAtX(char ch, int x, int LineNum, int Color, int InsertMode)\r\n{\r\n\tLineStruct *Line;\r\n\tint i;\r\n\r\n\tLine=GetLine(LineNum);\r\n\tif (InsertMode) {\r\n\t\tfor(i=Line->Length;i>x;i--) {\r\n\t\t\tLine->Text[i]=Line->Text[i-1];\r\n\t\t\tLine->Color[i]=Line->Color[i-1];\r\n\t\t}\r\n\t\t(Line->Length)++;\r\n\t}\r\n\tLine->Text[x]=ch;\r\n\tLine->Color[x]=Color;\r\n\tif (x==Line->Length)\r\n\t\t(Line->Length)++;\r\n}\r\n\r\nvoid EditorFileClass::DeleteCharacter(int x, int LineNum)\r\n{\r\n\tLineStruct *Line;\r\n\tint i;\r\n\r\n\tLine=GetLine(LineNum);\r\n\tif (x<Line->Length) {\r\n\t\tfor(i=x;i<Line->Length-1;i++) {\r\n\t\t\tLine->Text[i]=Line->Text[i+1];\r\n\t\t\tLine->Color[i]=Line->Color[i+1];\r\n\t\t}\r\n\t\t(Line->Length)--;\r\n\t} else\r\n\t\tif (Line->Next)\r\n\t\t\tLine->Wrap=1;\r\n}\r\n\r\n\r\n\r\nLineStruct *EditorFileClass::MakeNewLine(int LineNumber)\r\n{\r\n\tLineStruct *NewLine, *PreviousLine, *CurrentLine;\r\n\tint i;\r\n\r\n\tNewLine=new LineStruct;\r\n\tif (NewLine==NULL) {\r\n\t\tprintf(\"Out of memory!\");\r\n\t\texit(1);\r\n\t}\r\n\tmemset(NewLine, 0, sizeof(LineStruct));\r\n\tif (LineNumber==0) {\r\n\t\tCurrentLine=FirstLine;\r\n\t\tFirstLine=NewLine;\r\n\t\tNewLine->Next=CurrentLine;\r\n\t\tCurrentLine=FirstLine;\r\n\t} else {\r\n\t\tCurrentLine=FirstLine;\r\n\t\tfor(i=1;i<LineNumber;i++)\r\n\t\t\tNext(CurrentLine);\r\n\t\tNewLine->Next=CurrentLine->Next;\r\n\t\tCurrentLine->Next=NewLine;\r\n\t\tCurrentLine=NewLine;\r\n\t}\r\n\tFileLines++;\r\n  return(NewLine);\r\n}\r\n\r\n\r\n\r\n\r\nint EditorFileClass::BreakLine(int BreakBeginX, int LineNumber, int Forced)\r\n\r\n// Breaks a line into two parts.  \"Forced\" is true when\r\n// a user presses <return> to break up two lines.  False\r\n// when the editor breaks up the lines in the case of word\r\n// wrap.\r\n\r\n{\r\n\tLineStruct *NewLine, *CurrentLine;\r\n\tint i;\r\n\r\n\tCurrentLine=GetLine(LineNumber);\r\n\tif (!CurrentLine)\r\n\t\treturn 0;\r\n\tNewLine=MakeNewLine(LineNumber+1);\r\n\tfor(i=BreakBeginX; i<CurrentLine->Length; i++) {\r\n\t\tNewLine->Text[i-BreakBeginX]=CurrentLine->Text[i];\r\n\t\tNewLine->Color[i-BreakBeginX]=CurrentLine->Color[i];\r\n\t}\r\n\tNewLine->Length=CurrentLine->Length-BreakBeginX;\r\n\tCurrentLine->Length=BreakBeginX;\r\n\tNewLine->Wrap=CurrentLine->Wrap;\r\n\tCurrentLine->Wrap=(!Forced);\r\n\treturn(JoinLines(LineNumber+1));\r\n}\r\n\r\nvoid EditorFileClass::RemoveLine(int LineNumber)\r\n// Removes CurrentLine.\r\n\r\n{\r\n\tLineStruct *Line, *DeleteLine;\r\n\r\n\tif (LineNumber==0) {\r\n\t\tLine=FirstLine->Next;\r\n\t\tdelete FirstLine;\r\n\t\tFirstLine=Line;\r\n\t} else {\r\n\t\tLine=GetLine(LineNumber-1);\r\n\t\tDeleteLine=Line->Next;\r\n\t\tLine->Next=DeleteLine->Next;\r\n\t\tdelete DeleteLine;\r\n\t}\r\n  FileLines--;\r\n}\r\n\r\nint EditorFileClass::JoinLines(int LineNumber)\r\n\r\n// Returns line number if something has changed\r\n\r\n{\r\n\tLineStruct *NextLine, *Line;\r\n\tint i, WordLengthCount, CompleteWordLength, LineJoinComplete;\r\n\tint SomethingDone=-1;\r\n\r\n\r\n\tLine=GetLine(LineNumber);\r\n\twhile(Line->Wrap && Line->Next) {\r\n\t\tLineNumber++;\r\n\t\tNextLine=Line->Next;\r\n\t\tLineJoinComplete=0;\r\n\t\twhile(!LineJoinComplete) {\r\n\t\t\tif (NextLine->Length==0) {\r\n\t\t\t\tSomethingDone=LineNumber;\r\n\t\t\t\tLine->Wrap=NextLine->Wrap;\r\n\t\t\t\tRemoveLine(LineNumber);\r\n\t\t\t\tLineJoinComplete=1;\r\n\t\t\t} else {\r\n\t\t\t\tCompleteWordLength=0;\r\n\t\t\t\tfor(i=0;i<NextLine->Length;i++) {\r\n\t\t\t\t\tif (NextLine->Text[i]==' ' || i==(NextLine->Length-1))\r\n\t\t\t\t\t\tCompleteWordLength=i+1;\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tif (CompleteWordLength)\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (CompleteWordLength && CompleteWordLength+Line->Length < BREditArgs->MaxColumns) {\r\n\t\t\t\t\tSomethingDone=LineNumber;\r\n\t\t\t\t\tfor(i=0;i<CompleteWordLength;i++) {\r\n\t\t\t\t\t\tLine->Text[i+Line->Length]=NextLine->Text[i];\r\n\t\t\t\t\t\tLine->Color[i+Line->Length]=NextLine->Color[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tfor(i=CompleteWordLength;i<NextLine->Length; i++) {\r\n\t\t\t\t\t\tNextLine->Text[i-CompleteWordLength]=NextLine->Text[i];\r\n\t\t\t\t\t\tNextLine->Color[i-CompleteWordLength]=NextLine->Color[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\t(Line->Length)+=CompleteWordLength;\r\n\t\t\t\t\t(NextLine->Length)-=CompleteWordLength;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tLineJoinComplete=1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tNext(Line);\r\n\t}\r\n\treturn SomethingDone;\r\n}\r\n\r\n\r\nvoid EditorFileClass::Next(LineStruct *(&CurrentLine))\r\n{\r\n\tif (CurrentLine==NULL)\r\n\t\treturn;\r\n\tCurrentLine=CurrentLine->Next;\r\n}\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "brware/bredit/filemgr.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"FEDITIO.H\"\r\n\r\n#ifndef FEDITFIL_DOT_H\r\n\r\n#define FILE_NOT_FOUND 1\r\n#define FILE_OK 0\r\n#define LINE_LENGTH 81\r\n\r\ntypedef struct ls\r\n{\r\n\tunsigned int Length : 7;\r\n\tint Wrap : 1;\r\n\tchar Text[LINE_LENGTH];\r\n\tcolor_t Color[LINE_LENGTH];\r\n\tls *Next;\r\n} LineStruct;\r\n\r\n\r\nclass EditorFileClass\r\n{\r\npublic:\r\n\r\n\tchar *Filename;\r\n\tint FileLines;\r\n\r\n\tLineStruct *FirstLine;\r\n\tBREditArguments *BREditArgs;\r\n\r\n\tEditorFileClass(char *fn, BREditArguments *FA);\r\n\t~EditorFileClass(void);\r\n\r\n\r\n\tvoid ExportLine(FILE *stream, LineStruct *Line, int FromColumn, int ToColumn);\r\n\tint ImportFile(char *Filename, int x, int AtLine);\r\n\tvoid SaveFile(void);\r\n\tvoid ExportFile(char *Filename,\r\n\t\t\t\t\t\t\t\t\tint BeginX, int BeginLine, int EndX, int EndLine);\r\n\tLineStruct *MakeNewLine(int LineNumber);\r\n\tvoid RemoveLine(int LineNumber);\r\n\tvoid Next(LineStruct *(&CurrentLine));\r\n\tint BreakLine(int BreakBeginX, int LineNumber, int Forced);\r\n\tint JoinLines(int LineNumber);\r\n\tvoid DeleteCharacter(int x, int LineNum);\r\n\tvoid AddAtX(char ch, int x, int Color, int LineNumber, int InsertMode);\r\n\tLineStruct *GetLine(int LineNumber);\r\n};\r\n\r\n#define FEDITFIL_DOT_H\r\n\r\n#endif\r\n"
  },
  {
    "path": "brware/bredit/fileview.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"fileview.h\"\r\n\r\n#define HELP_TOP_LINE 2\r\n#define HELP_DISPLAY_LINES ((BREditArgs->ScreenLines-1)-HELP_TOP_LINE)\r\n\r\n\r\nvoid FileView::ShowTopInfo(void)\r\n{\r\n\tIO->MoveTo(0,0);\r\n\tIO->EraseToEnd();\r\n\tIO->SetColor(1);\r\n\tIO->Output(Title);\r\n\tIO->Output(\" - Use arrows to move up and down, any other key to exit\");\r\n}\r\n\r\n\r\nvoid FileView::ShowLine(LineStruct *Line)\r\n{\r\n\tint i;\r\n\r\n\tif (Line) {\r\n\t\ti=0;\r\n\t\tif (strnicmp(Line->Text, \"/c:\", 3)==0) {\r\n\t\t\tIO->SetColor(0);\r\n\t\t\tfor(i=0;i<40-(Line->Length-3)/2;i++)\r\n\t\t\t\tIO->Output(' ');\r\n\t\t\ti=3;\r\n\t\t}\r\n\t\tfor(;i<Line->Length;i++) {\r\n\t\t\tIO->SetColor(Line->Color[i]);\r\n\t\t\tIO->Output(Line->Text[i]);\r\n\t\t}\r\n\t}\r\n\tIO->EraseToEnd();\r\n}\r\n\r\n\r\nvoid FileView::ShowHelpPage(EditorFileClass *File)\r\n{\r\n\tint i;\r\n\tLineStruct *Line;\r\n\r\n\tLine=File->GetLine(HelpBrowseLine);\r\n\tfor(i=0;i<=HELP_DISPLAY_LINES;i++) {\r\n\t\tif (Line || i<=BottomLineUsed) {\r\n\t\t\tIO->MoveTo(0, i+HELP_TOP_LINE);\r\n\t\t\tShowLine(Line);\r\n\t\t\tif (Line)\r\n\t\t\t\tBottomLineUsed=i;\r\n\t\t\tFile->Next(Line);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint FileView::GetHelpKey()\r\n{\r\n\tint ch;\r\n\r\n\tch=IO->GetChar();\r\n\tswitch(ch) {\r\n\tcase KB_UP:\r\n\tcase KB_DOWN:\r\n\tcase KB_PGUP:\r\n\tcase KB_PGDN:\r\n\tcase ENTER:\r\n\tcase ESC:\r\n\t\tif (BREditArgs->EnhancedMode!=ON) {\r\n\t\t\tswitch(ch) {\r\n\t\t\tcase KB_UP:\r\n\t\t\t\treturn KB_PGUP;\r\n\t\t\tcase KB_DOWN:\r\n\t\t\t\treturn KB_PGDN;\r\n\t\t\tdefault:\r\n\t\t\t\treturn(ch);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn(ch);\r\n\tdefault:\r\n\t\treturn(ch);\r\n\t}\r\n}\r\n\r\n\r\n\r\nFileView::FileView(IOClass *InputOutput, BREditArguments *FA, EditorFileClass *File, char *Description)\r\n{\r\n\tIO=InputOutput;\r\n\tBREditArgs=FA;\r\n   strcpy(Title, Description);\r\n\tHelpBrowseLine=0;\r\n\tBottomLineUsed=0;\r\n\tIO->SetColor(0);\r\n\tIO->ClearScreen();\r\n\tShowTopInfo();\r\n\tIO->SetColor(7);\r\n\tIO->MoveTo(0, 1);\r\n\tint i;\r\n\tfor(i=1;i<BREditArgs->MaxColumns;i++)\r\n\t\tIO->Output('');\r\n\tShowHelpPage(File);\r\n\tif (BREditArgs->EnhancedMode==ON)\r\n\t\tIO->EANSI_DefineRegion(HELP_TOP_LINE, HELP_DISPLAY_LINES+HELP_TOP_LINE);\r\n\tint Done=0;\r\n\twhile(!Done) {\r\n\t\tswitch(GetHelpKey()) {\r\n\t\tcase KB_PGUP:\r\n\t\t\tif (HelpBrowseLine>0) {\r\n\t\t\t\tHelpBrowseLine-=HELP_DISPLAY_LINES-3;\r\n\t\t\t\tif (HelpBrowseLine<0)\r\n\t\t\t\t\tHelpBrowseLine=0;\r\n\t\t\t\tShowHelpPage(File);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase KB_PGDN:\r\n\t\t\tif (HelpBrowseLine+HELP_DISPLAY_LINES < File->FileLines-1) {\r\n\t\t\t\tHelpBrowseLine+=HELP_DISPLAY_LINES-3;\r\n\t\t\t\tif (HelpBrowseLine+HELP_DISPLAY_LINES >= File->FileLines)\r\n\t\t\t\t\tHelpBrowseLine=File->FileLines-1-HELP_DISPLAY_LINES;\r\n\t\t\t\tShowHelpPage(File);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\t\t // NOTE: EnhancedMode must be on for these keys   //\r\n\t\t\t\t\t // to be generated.  InputNumber translates these //\r\n\t\t\t\t\t // keys into PGUP and PGDN for non enhanced mode  //\r\n\t\t\t\t\t // users.                                         //\r\n\t\tcase KB_UP:\r\n\t\t\tif (HelpBrowseLine>0) {\r\n\t\t\t\tHelpBrowseLine--;\r\n\t\t\t\tIO->EANSI_ScrollRegionDown();\r\n\t\t\t\tIO->MoveTo(0, HELP_TOP_LINE);\r\n\t\t\t\tShowLine(File->GetLine(HelpBrowseLine));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase KB_DOWN:\r\n\t\t\tif (HelpBrowseLine+HELP_DISPLAY_LINES < File->FileLines-1) {\r\n\t\t\t\tHelpBrowseLine++;\r\n\t\t\t\tIO->EANSI_ScrollRegionUp();\r\n\t\t\t\tIO->MoveTo(0, HELP_TOP_LINE+HELP_DISPLAY_LINES);\r\n\t\t\t\tShowLine(File->GetLine(HelpBrowseLine+HELP_DISPLAY_LINES));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tDone=1;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "brware/bredit/fileview.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef FILEVIEW_DOT_H\r\n#define FILEVIEW_DOT_H\r\n\r\n#include \"FEDITIO.H\"\r\n#include \"FILEMGR.H\"\r\n\r\nclass FileView\r\n{\r\n\tint HelpBrowseLine, BottomLineUsed;\r\n\tchar Title[81];\r\n\tIOClass *IO;\r\n\tBREditArguments *BREditArgs;\r\n\r\n\tint GetHelpKey();\r\n\tvoid ShowTopInfo();\r\n\tvoid ShowHelpPage(EditorFileClass *File);\r\n\tvoid ShowLine(LineStruct *Line);\r\n\r\npublic:\r\n\tFileView(IOClass *InputOutput, BREditArguments *BREditArguments, EditorFileClass *File, char *Description);\r\n};\r\n\r\n#endif"
  },
  {
    "path": "brware/bredit/header-template.txt",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/"
  },
  {
    "path": "brware/bredit/makefile.bcc",
    "content": "COMPILER_HOME   = C:\\TC\r\nBIN             = $(COMPILER_HOME)\\bin\r\nINCLUDE         = $(COMPILER_HOME)\\include\r\nLIB             = $(COMPILER_HOME)\\lib\r\nCC              = $(BIN)\\tcc.exe\r\nOBJ             = .\\obj\r\nOPTS            = -ml -c -I$(INCLUDE) -L$(LIB) -n$(OBJ) -eBREdit\r\nOPTS2           = -ml -ll -I$(INCLUDE) -L$(LIB) -n$(OBJ) -eBREdit\r\n\r\n#.CPP.OBJ:        $(CC) $(OPTS2) $(OBJ)\\*.OBJ\r\n\r\n\r\nall: ARGUMENT.OBJ BREDIT.OBJ EDITOR.OBJ FEDITIO.OBJ FILEMGR.OBJ FILEVIEW.OBJ QUOTE.OBJ\r\n        $(CC) $(OPTS2) $(OBJ)\\*.OBJ\r\n\r\nARGUMENT.OBJ:   ARGUMENT.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nBREDIT.OBJ:     BREDIT.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nEDITOR.OBJ:     EDITOR.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nFEDITIO.OBJ:    FEDITIO.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nFILEMGR.OBJ:    FILEMGR.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nFILEVIEW.OBJ:   FILEVIEW.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\nQUOTE.OBJ:      QUOTE.CPP\r\n        $(CC) $(OPTS) $*.CPP\r\n\r\n\r\n"
  },
  {
    "path": "brware/bredit/quote.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"QUOTE.H\"\r\n\r\n#define QUOTE_TOP_LINE 3\r\n#define QUOTE_DISPLAY_LINES ((BREditArgs->ScreenLines-1)-QUOTE_TOP_LINE)\r\n\r\nQuoteClass::QuoteClass(char *QuoteFN, IOClass *InputOutput, EditorFileClass *MainEditorFile, BREditArguments *FA)\r\n{\r\n\tffblk ff;\r\n\r\n\tBREditArgs=FA;\r\n\tQuoteFileName=QuoteFN;\r\n\tMainFile=MainEditorFile;\r\n\tQuotesAvailable=(findfirst(QuoteFileName, &ff, 0)==0) ? 1 : 0;\r\n\tIO=InputOutput;\r\n\tQuoteBrowseLine=0;\r\n}\r\n\r\nvoid QuoteClass::ShowLine(LineStruct *Line)\r\n{\r\n\tint i;\r\n\r\n\tif (Line) {\r\n\t\tfor(i=0;i<Line->Length;i++) {\r\n\t\t\tIO->SetColor(Line->Color[i]);\r\n\t\t\tIO->Output(Line->Text[i]);\r\n\t\t}\r\n\t}\r\n\tIO->EraseToEnd();\r\n}\r\n\r\nvoid QuoteClass::ShowTopInfo(void)\r\n{\r\n\tIO->MoveTo(0,0);\r\n\tIO->EraseToEnd();\r\n\tIO->SetColor(2);\r\n\tIO->Output(\"Quote from line : \");\r\n\tIO->SetColor(1);\r\n\tIO->MoveTo(58,0);\r\n\tIO->Output(\"Use arrows to browse,\");\r\n\tIO->MoveTo(8,1);\r\n\tIO->EraseToEnd();\r\n\tIO->SetColor(2);\r\n\tIO->Output(\"to line : \");\r\n\tIO->MoveTo(58, 1);\r\n\tIO->SetColor(1);\r\n\tIO->Output(\"ESC to abort quote\");\r\n}\r\n\r\nvoid QuoteClass::ShowQuotePage(EditorFileClass *QuoteFile)\r\n{\r\n\tint i;\r\n\tLineStruct *Line;\r\n\r\n\tLine=QuoteFile->GetLine(QuoteBrowseLine);\r\n\tfor(i=0;i<=QUOTE_DISPLAY_LINES;i++) {\r\n\t\tif (Line || i<=BottomLineUsed) {\r\n\t\t\tIO->MoveTo(0, i+QUOTE_TOP_LINE);\r\n\t\t\tShowLine(Line);\r\n\t\t\tif (Line)\r\n\t\t\t\tBottomLineUsed=i;\r\n\t\t\tQuoteFile->Next(Line);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint QuoteClass::InputNumber(char *s)\r\n{\r\n\tint ch, CurrentStringLength;\r\n\r\n\tfor(;;) {\r\n\t\tCurrentStringLength=strlen(s);\r\n\t\tch=IO->GetChar();\r\n\t\tswitch(ch) {\r\n\t\tcase KB_UP:\r\n\t\tcase KB_DOWN:\r\n\t\tcase KB_PGUP:\r\n\t\tcase KB_PGDN:\r\n\t\tcase ENTER:\r\n\t\tcase ESC:\r\n\t\t\tif (BREditArgs->EnhancedMode!=ON) {\r\n\t\t\t\tswitch(ch) {\r\n\t\t\t\tcase KB_UP:\r\n\t\t\t\t\treturn KB_PGUP;\r\n\t\t\t\tcase KB_DOWN:\r\n\t\t\t\t\treturn KB_PGDN;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn(ch);\r\n\t\tcase BACKSPACE:\r\n\t\t\tif (CurrentStringLength>0) {\r\n\t\t\t\ts[--CurrentStringLength]=0;\r\n\t\t\t\tIO->Output(\"\\b \\b\");\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tif (CurrentStringLength<3 && isdigit(ch)) {\r\n\t\t\t\ts[CurrentStringLength++]=(char)ch;\r\n\t\t\t\ts[CurrentStringLength]=0;\r\n\t\t\t\tIO->SetColor(4);\r\n\t\t\t\tIO->Output((char)ch);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n#define HIGHLIGHT 1\r\n#define UNHIGHLIGHT 0\r\n\r\n#define INPUT_X 18\r\n\r\nvoid QuoteClass::HighlightInput(int Number, int State, char *Data)\r\n{\r\n\tchar s[10];\r\n\r\n\tIO->SetColor((State==HIGHLIGHT) ? 4 : 0);\r\n\tsprintf(s,\"%-3s\", Data);\r\n\tIO->MoveTo(INPUT_X, Number);\r\n\tIO->Output(s);\r\n}\r\n\r\n#define NOT_DONE 0\r\n#define DO_QUOTE 1\r\n#define ABORT_QUOTE 2\r\n\r\n#define ARROW_SIZE 5\r\n\r\n#define FROM 0\r\n#define TO 1\r\n\r\nvoid QuoteClass::Quote(int LineNumber)\r\n{\r\n\tint i;\r\n\tLineStruct *Line, *NextLine;\r\n\r\n\tEditorFileClass QuoteFile(QuoteFileName, BREditArgs);\r\n\r\n\tif (strchr(QuoteFile.GetLine(0)->Text, '#')!=NULL) { // Quote file contains author info\r\n\t\tQuoteFile.RemoveLine(0);\r\n\t\tQuoteFile.RemoveLine(0);\r\n\t}\r\n\tBottomLineUsed=0;\r\n\tfor(i=0;i<QuoteFile.FileLines;i++) {\r\n\t\tLine=QuoteFile.MakeNewLine(i);\r\n\t\tsprintf(Line->Text, \"%-3d> \", i+1);\r\n\t\tmemset(Line->Color, 2, sizeof(color_t) * 3);\r\n\t\tLine->Length=ARROW_SIZE;\r\n\t\tLine->Color[3]=7;\r\n\t\tLine->Color[4]=0;\r\n\t\tLine->Wrap=1;\r\n\t\tNextLine=QuoteFile.GetLine(i+1);\r\n\t\tif (NextLine->Length+(ARROW_SIZE+1)>BREditArgs->MaxColumns)\r\n\t\t\tNextLine->Length=BREditArgs->MaxColumns-(ARROW_SIZE+1);\r\n  /*\t\tif (NextLine->Length+(ARROW_SIZE+1)>BREditArgs->MaxColumns) {\r\n\t\t\tint Count, NoSpaces=1;\r\n\t\t\tfor(Count=BREditArgs->MaxColumns-(ARROW_SIZE+1);(Count>=0 && NoSpaces);Count--)\r\n\t\t\t\tif (NextLine->Text[Count]==' ')\r\n\t\t\t\t\tNoSpaces=0;\r\n\t\t\tif (NoSpaces)\r\n\t\t\t\tNextLine->Length=BREditArgs->MaxColumns-(ARROW_SIZE+1);\r\n\t\t}    */\r\n\t\tQuoteFile.JoinLines(i);\r\n\t}\r\n\tIO->SetColor(0);\r\n\tIO->ClearScreen();\r\n\tShowTopInfo();\r\n\tIO->SetColor(7);\r\n\tIO->MoveTo(0, 2);\r\n\tfor(i=1;i<BREditArgs->MaxColumns;i++)\r\n\t\tIO->Output('');\r\n\tShowQuotePage(&QuoteFile);\r\n\tif (BREditArgs->EnhancedMode==ON)\r\n\t\tIO->EANSI_DefineRegion(QUOTE_TOP_LINE, QUOTE_DISPLAY_LINES+QUOTE_TOP_LINE);\r\n\r\n\tint QuoteAction=NOT_DONE, CurrentInputField=0;\r\n\tchar QuoteData[2][4];\r\n\r\n\tfor(i=0;i<2;i++)\r\n\t\tQuoteData[i][0]=0;\r\n\r\n\tHighlightInput(FROM, HIGHLIGHT, QuoteData[FROM]);\r\n\twhile(QuoteAction==NOT_DONE) {\r\n\t\tIO->MoveTo(INPUT_X+strlen(QuoteData[CurrentInputField]), CurrentInputField);\r\n\t\tswitch(InputNumber(QuoteData[CurrentInputField])) {\r\n\t\tcase ESC:\r\n\t\t\tQuoteAction=ABORT_QUOTE;\r\n\t\t\tbreak;\r\n\t\tcase ENTER:\r\n\t\t\tif (strlen(QuoteData[CurrentInputField])==0) {\r\n\t\t\t\tQuoteAction=ABORT_QUOTE;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\ti=atoi(QuoteData[CurrentInputField]);\r\n\t\t\tif (i<1 || i>QuoteFile.FileLines ||\r\n\t\t\t\t (CurrentInputField==1 && i<atoi(QuoteData[FROM]))) {\r\n\t\t\t\tIO->Output(BEEP);\r\n\t\t\t\tfor(i=0;i<2;i++)\r\n\t\t\t\t\tQuoteData[i][0]=0;\r\n\t\t\t\tHighlightInput(TO, UNHIGHLIGHT, QuoteData[TO]);\r\n\t\t\t\tHighlightInput(FROM, HIGHLIGHT, QuoteData[FROM]);\r\n\t\t\t\tCurrentInputField=FROM;\r\n\t\t\t} else if (CurrentInputField==FROM) {\r\n\t\t\t\tCurrentInputField=TO;\r\n\t\t\t\tHighlightInput(FROM, UNHIGHLIGHT, QuoteData[FROM]);\r\n\t\t\t\tHighlightInput(TO, HIGHLIGHT, QuoteData[TO]);\r\n\t\t\t} else\r\n\t\t\t\tQuoteAction=DO_QUOTE;\r\n\t\t\tbreak;\r\n\t\tcase KB_PGUP:\r\n\t\t\tif (QuoteBrowseLine>0) {\r\n\t\t\t\tQuoteBrowseLine-=QUOTE_DISPLAY_LINES-3;\r\n\t\t\t\tif (QuoteBrowseLine<0)\r\n\t\t\t\t\tQuoteBrowseLine=0;\r\n\t\t\t\tShowQuotePage(&QuoteFile);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase KB_PGDN:\r\n\t\t\tif (QuoteBrowseLine+QUOTE_DISPLAY_LINES < QuoteFile.FileLines-1) {\r\n\t\t\t\tQuoteBrowseLine+=QUOTE_DISPLAY_LINES-3;\r\n\t\t\t\tif (QuoteBrowseLine+QUOTE_DISPLAY_LINES >= QuoteFile.FileLines)\r\n\t\t\t\t\tQuoteBrowseLine=QuoteFile.FileLines-1-QUOTE_DISPLAY_LINES;\r\n\t\t\t\tShowQuotePage(&QuoteFile);\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\t\t\t // NOTE: EnhancedMode must be on for these keys   //\r\n\t\t\t\t\t // to be generated.  InputNumber translates these //\r\n\t\t\t\t\t // keys into PGUP and PGDN for non enhanced mode  //\r\n\t\t\t\t\t // users.                                         //\r\n\t\tcase KB_UP:\r\n\t\t\tif (QuoteBrowseLine>0) {\r\n\t\t\t\tQuoteBrowseLine--;\r\n\t\t\t\tIO->EANSI_ScrollRegionDown();\r\n\t\t\t\tIO->MoveTo(0, QUOTE_TOP_LINE);\r\n\t\t\t\tShowLine(QuoteFile.GetLine(QuoteBrowseLine));\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase KB_DOWN:\r\n\t\t\tif (QuoteBrowseLine+QUOTE_DISPLAY_LINES < QuoteFile.FileLines-1) {\r\n\t\t\t\tQuoteBrowseLine++;\r\n\t\t\t\tIO->EANSI_ScrollRegionUp();\r\n\t\t\t\tIO->MoveTo(0, QUOTE_TOP_LINE+QUOTE_DISPLAY_LINES);\r\n\t\t\t\tShowLine(QuoteFile.GetLine(QuoteBrowseLine+QUOTE_DISPLAY_LINES));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (QuoteAction==DO_QUOTE) {\r\n\r\n\t\tLineStruct *NewMainLine;\r\n\t\tint j;\r\n\r\n\t\tfor(i=atoi(QuoteData[FROM])-1;i<=atoi(QuoteData[TO])-1;i++) {\r\n\t\t\tNewMainLine=MainFile->MakeNewLine(LineNumber);\r\n\t\t\tLine=QuoteFile.GetLine(i);\r\n\t\t\tfor(j=3;j<Line->Length;j++) {\r\n\t\t\t\tNewMainLine->Text[j-3]=Line->Text[j];\r\n\t\t\t\tNewMainLine->Color[j-3]=Line->Color[j];\r\n\t\t\t\tNewMainLine->Length=Line->Length-3;\r\n\t\t\t}\r\n\t\t\tLineNumber++;\r\n\t\t}\r\n\t\tNewMainLine=MainFile->MakeNewLine(LineNumber);\r\n\t\tNewMainLine->Length=0;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "brware/bredit/quote.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef QUOTE_DOT_H\r\n\r\n#include \"FILEMGR.H\"\r\n#include \"FEDITIO.H\"\r\n#include \"ARGUMENT.H\"\r\n#include <dos.h>\r\n#include <dir.h>\r\n#include <string.h>\r\n#include <ctype.h>\r\n\r\nclass QuoteClass\r\n{\r\n\tchar *QuoteFileName;\r\n\tint QuoteBrowseLine, BottomLineUsed;\r\n\tIOClass *IO;\r\n\tBREditArguments *BREditArgs;\r\n\tEditorFileClass *MainFile;\r\n\tint InputNumber(char *s);\r\n\tvoid HighlightInput(int Number, int State, char *);\r\n\r\n\r\npublic:\r\n\tint QuotesAvailable;\r\n\tvoid ShowQuotePage(EditorFileClass *QuoteFile);\r\n\tvoid ShowLine(LineStruct *Line);\r\n\r\n\tvoid Quote(int LineNumber);\r\n\tvoid ShowTopInfo(void);\r\n\tQuoteClass(char *QuoteFileName, IOClass *InputOutput, EditorFileClass *MainEditorFile, BREditArguments *BREditArgs);\r\n};\r\n\r\n#define QUOTE_DOT_H\r\n\r\n#endif\r\n"
  },
  {
    "path": "brware/bredit/version.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                                BREdit                                  */\r\n/*             Copyright 1999 Art Johnston, BRWare Authors                */\r\n/*               Based on the code from FEditby Rob Raper                 */ \r\n/*                 Portions Copyright 1993-1999 Rob Raper                 */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef __BREDIT_VERSION_H__\r\n#define __BREDIT_VERSION_H__\r\n\r\n#define VERSION_NUMBER \"1.1.2\"\r\n#define VERSION        \"1.1.2 (Beta)\"\r\n\r\n#endif // __BREDIT_VERSION_H__\r\n"
  },
  {
    "path": "builds/jenkins/wwiv/build",
    "content": "#!/bin/bash\n# WWIV Build Script.\n#\n# Required Variables:\n#   WORKSPACE - Jenkins workspace\n#   BUILD_NUMBER - Jenkins Build number\n#   WWIV_DISTRO - Linux build label (i.e. centos7)\n\n# Ensure we have CC and CXX set\nexport CXX=$(which g++)\nexport CC=$(which gcc)\n\necho \"=============================================================================\"\necho \"Workspace:        ${WORKSPACE}\"\necho \"CMake:            ${CMAKE_BIN}; Test: ${CTEST_BIN}; Pack: ${CPACK_BIN}\"\necho \"CMake Build:      ${CMAKE_BINARY_DIR}\"\necho \"Release Dir:      ${WWIV_RELEASE_DIR}\"\necho \"Archive:          ${WWIV_RELEASE_ARCHIVE_FILE}\"\necho \"WWIV_DISTRO:      ${WWIV_DISTRO}\"\necho \"CC:               ${CC}\"\necho \"CXX:              ${CXX}\"\necho \"GCC version:      $(${CC} --version | head -1)\"\necho \"=============================================================================\"\n\n# Delete any previous release archives before starting the build with set -e\n\necho \"Creating ${CMAKE_BINARY_DIR} and ${WWIV_RELEASE_DIR}\"\nmkdir -p \"${CMAKE_BINARY_DIR}\"\nmkdir -p \"${WWIV_RELEASE_DIR}\"\n\nset -x\nset -e\necho \"Building binaries\"\npushd ${CMAKE_BINARY_DIR}\n${CMAKE_BIN} -G \"Ninja\" \\\n      -DCMAKE_CXX_COMPILER=g++ \\\n      -DCMAKE_C_COMPILER=gcc \\\n      -DCMAKE_BUILD_TYPE=Debug \\\n      -DWWIV_RELEASE=${WWIV_RELEASE} \\\n      -DWWIV_ARCH=${WWIV_ARCH}  \\\n      -DWWIV_BUILD_NUMBER=${BUILD_NUMBER} \\\n      -DWWIV_DISTRO=${WWIV_DISTRO} \\\n      ${WORKSPACE} || exit /b\n\n${CMAKE_BIN} --build . --config Debug\n\necho \"=============================================================================\"\necho \"                          **** RUNNING TESTS ****\"\necho \"=============================================================================\"\n\n${CTEST_BIN} --no-compress-output --output-on-failure -T Test || /bin/true\n${CPACK_BIN} -G TGZ\n\npopd\ncd ${WORKSPACE}\nmv ${CMAKE_BINARY_DIR}/${WWIV_RELEASE_ARCHIVE_FILE} ${WORKSPACE}/${WWIV_RELEASE_ARCHIVE_FILE}\n\necho \"Archive file: ${WORKSPACE}/${WWIV_RELEASE_ARCHIVE_FILE}\"\necho \"Contents:\"\ntar ztvf ${WORKSPACE}/${WWIV_RELEASE_ARCHIVE_FILE}\n"
  },
  {
    "path": "builds/jenkins/wwiv/build-os2.cmd",
    "content": "@rem **************************************************************************\r\n@rem WWIV Build Script.\r\n@rem\r\n@rem Required Variables:\r\n@rem WORKSPACE - git root directory\r\n@rem BUILD_NUMBER - Jenkins Build number\r\n@rem\r\n@rem Installed Software (all via apt)\r\n@rem   GCC 9.2\r\n@rem   7-Zip [C:\\usr\\bin\\7z.exe]\r\n@rem   cmake [in PATH]\r\n@rem \r\n@rem **************************************************************************\r\n\r\n@echo off\r\ndel wwiv-*.zip\r\n\r\nset WWIV_ARCH=x86\r\nset WWIV_DISTRO=os2\r\nset ZIP_EXE=7z.exe\r\nset WWIV_RELEASE=5.7.2\r\nset WWIV_RELEASE_ARCHIVE_FILE=wwiv-%WWIV_DISTRO%-%WWIV_RELEASE%.%BUILD_NUMBER%.zip\r\nset CMAKE_BINARY_DIR=%WORKSPACE%\\_build\r\nset WWIV_RELEASE_DIR=%CMAKE_BINARY_DIR%\\release\r\n\r\n@echo =============================================================================\r\n@echo Workspace:            %WORKSPACE% \r\n@echo WWIV_ARCHitecture:    %WWIV_ARCH%\r\n@echo WWIV_DISTRO:          %WWIV_DISTRO%\r\n@echo WWIV Release:         %WWIV_RELEASE%        \r\n@echo Build Number:         %BUILD_NUMBER%\r\n@echo WWIV CMake Root:      %CMAKE_BINARY_DIR%\r\n@echo WWIV_ARCHive:         %WWIV_RELEASE_ARCHIVE_FILE%\r\n@echo Release Dir:          %WWIV_RELEASE_DIR%\r\n@echo INCLUDE               %INCLUDE%\r\n@echo =============================================================================\r\n\r\nmkdir %CMAKE_BINARY_DIR%\r\ndel %CMAKE_BINARY_DIR%\\CMakeCache.txt\r\nrmdir /s/q %CMAKE_BINARY_DIR%\\CMakeFiles\r\nrmdir /s/q %CMAKE_BINARY_DIR%\\Testing\r\n\r\ncd %WORKSPACE%\r\nmkdir %WWIV_RELEASE_DIR%\r\ndel /q %WWIV_RELEASE_DIR%\r\ndel /q wwiv-*.zip\r\ndel /q wwiv-*.exe\r\n\r\necho * Building WWIV\r\ncd %CMAKE_BINARY_DIR%\r\ncmake -DCMAKE_BUILD_TYPE=Release ^\r\n      -DWWIV_RELEASE=%WWIV_RELEASE% ^\r\n      -DWWIV_ARCH=%WWIV_ARCH%  ^\r\n      -DWWIV_BUILD_NUMBER=%BUILD_NUMBER% ^\r\n      -DWWIV_DISTRO=%WWIV_DISTRO% ^\r\n      %WORKSPACE%\r\n\r\ncmake --build . --config Release\r\n\r\n@echo =============================================================================\r\n@echo                           **** RUNNING TESTS ****\r\n@echo =============================================================================\r\nctest --no-compress-output --output-on-failure -T Test \r\n\r\necho * Creating release Archive: %WWIV_RELEASE_ARCHIVE_FILE%\r\ncpack -G ZIP\r\n"
  },
  {
    "path": "builds/jenkins/wwiv/build.cmd",
    "content": "@rem **************************************************************************\r\n@rem WWIV Build Script.\r\n@rem\r\n@rem Required Variables:\r\n@rem WORKSPACE - git root directory\r\n@rem BUILD_NUMBER - Jenkins Build number\r\n@rem\r\n@rem Installed Software:\r\n@rem   7-Zip [C:\\Program Files\\7-Zip\\7z.exe]\r\n@rem   Visual Studio [C:\\Program Files (x86)\\Microsoft Visual Studio\\VER]\r\n@rem   cmake [in PATH, set by vcvarsall.bat]\r\n@rem \r\n@rem **************************************************************************\r\n\r\nsetlocal\r\nset ZIP_EXE=\"C:\\Program Files\\7-Zip\\7z.exe\"\r\n\r\n@echo =============================================================================\r\n@echo Workspace:                 %WORKSPACE% \r\n@echo WWIV_ARCHitecture:         %WWIV_ARCH%\r\n@echo WWIV_DISTRO:               %WWIV_DISTRO%\r\n@echo WWIV Release:              %WWIV_RELEASE%        \r\n@echo Build Number:              %BUILD_NUMBER%\r\n@echo CMAKE_BINARY_DIR:          %CMAKE_BINARY_DIR%\r\n@echo WWIV_RELEASE_ARCHIVE_FILE: %WWIV_RELEASE_ARCHIVE_FILE%\r\n@echo Release Dir:               %WWIV_RELEASE_DIR%\r\n@echo Visual Studio Shell:       %VCVARS_ALL%\r\n@echo WindowsSdkVerBinPath       %WindowsSdkVerBinPath%\r\n@echo WindowsLibPath             %WindowsLibPath%\r\n@echo INCLUDE                    %INCLUDE%\r\n@echo =============================================================================\r\n\r\nmkdir \"%CMAKE_BINARY_DIR%\"\r\n\r\ncd \"%WORKSPACE%\"\r\nmkdir \"%WWIV_RELEASE_DIR%\"\r\n\r\necho * Building WWIV\r\ncd \"%CMAKE_BINARY_DIR%\"\r\ncmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=Release ^\r\n    -DWWIV_RELEASE=%WWIV_RELEASE% ^\r\n    -DWWIV_ARCH=%WWIV_ARCH%  ^\r\n    -DWWIV_BUILD_NUMBER=%BUILD_NUMBER% ^\r\n    -DWWIV_DISTRO=%WWIV_DISTRO% ^\r\n    %WORKSPACE% || exit /b\r\n\r\necho \"Copy CL32.DLL so tests can use it in post-config\"\r\ncopy /y/v %WORKSPACE%\\install\\platform\\win32\\cl32.dll \"%CMAKE_BINARY_DIR%\"\r\n\r\ncmake --build . --config Release || exit /b\r\n\r\n@echo =============================================================================\r\n@echo                           **** RUNNING TESTS ****\r\n@echo =============================================================================\r\nctest --no-compress-output --output-on-failure -T Test \r\n\r\necho * Creating release Archive: %WWIV_RELEASE_ARCHIVE_FILE%\r\ncpack -G ZIP || exit /b \r\n\r\ncd %WORKSPACE%\r\ncopy /y/v \"%CMAKE_BINARY_DIR%\\%WWIV_RELEASE_ARCHIVE_FILE%\" \"%WORKSPACE%\\%WWIV_RELEASE_ARCHIVE_FILE%\"\r\n\r\necho **** SUCCESS ****\r\necho ** Archive File: \"%WORKSPACE%\\%WWIV_RELEASE_ARCHIVE_FILE%\"\r\necho ** Archive contents:\r\n%ZIP_EXE% l %WORKSPACE%\\%WWIV_RELEASE_ARCHIVE_FILE%\r\nendlocal\r\n"
  },
  {
    "path": "builds/jenkins/wwiv/rushfan-build",
    "content": "#!/bin/bash\n#\n# WWIV Build Script for RushFan\n#\n\nexport WORKSPACE=${HOME}/git/wwiv\nexport BUILD_NUMBER=2112\npushd ${WORKSPACE}\n./builds/jenkins/wwiv/build \"$@\" || echo \"Build FAILED!\"\npopd >/dev/null\n"
  },
  {
    "path": "builds/jenkins/wwiv/rushfan-build.cmd",
    "content": "SET WORKSPACE=W:\\wwiv\r\nSET BUILD_NUMBER=2112\r\nset label=win-x86\r\nset VCVARS_ALL=\"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Preview\\VC\\Auxiliary\\Build\\\\vcvarsall.bat\"\r\npushd %WORKSPACE%\r\ncall %WORKSPACE%\\builds\\jenkins\\wwiv\\build.cmd || echo \"Build FAILED!\"\r\npopd\r\n\r\n"
  },
  {
    "path": "builds/linux/asan.sh",
    "content": "#!/bin/bash\ncmake -DCMAKE_BUILD_TYPE:STRING=Asan -DHAVE_ADDRESS_SANITIZER=On\n"
  },
  {
    "path": "builds/linux/clean.sh",
    "content": "make clean\nrm -rf CMakeCache.txt CMakeFiles \n"
  },
  {
    "path": "builds/linux/install-prereqs.sh",
    "content": "#!/bin/bash\nset -e\n\nif [[ $(id -u) -ne 0 ]]; then\n   echo \"$0 must be executed as root.\"\n   exit 1\nfi\n\necho \"Installing prerequistes for Debian/Ubuntu\"\n\napt-get update\napt-get install -y libncurses-dev libncurses5-dev build-essential git cmake zip ninja-build gettext zlib1g-dev pkg-config\n# gettext is in there since some versions of git don't express that dep properly.\n"
  },
  {
    "path": "builds/linux/start-agent.sh",
    "content": "#!/bin/bash\n\n# Download latest agent\nwget -N https://build.wwivbbs.org/jenkins/jnlpJars/agent.jar\n\n# start agent\njava -jar agent.jar \\\n-jnlpUrl https://build.wwivbbs.org/jenkins/computer/[NODENAME]/slave-agent.jnlp \\\n-secret @secret-file \\\n-workDir \"/jenkins\" &\ndisown"
  },
  {
    "path": "builds/os2/cc11.cmd",
    "content": "rem WWIV Version 5.x\r\nset CXX=C:\\usr\\local11\\bin\\g++\r\nset CC=C:\\usr\\local11\\bin\\gcc\r\n\r\necho: Runing cmake on \"%1\"\r\ncmake -DCMAKE_BUILD_TYPE=Release -DWWIV_ARCH=x86 -DWWIV_DISTRO=os2 %1\r\n\r\n"
  },
  {
    "path": "builds/os2/cconfig.cmd",
    "content": "rem WWIV Version 5.x\r\nset CXX=C:\\usr\\bin\\g++\r\nset CC=C:\\usr\\bin\\gcc\r\n\r\necho: Runing cmake on \"%1\"\r\ncmake -DCMAKE_BUILD_TYPE=Release -DWWIV_ARCH=x86 -DWWIV_DISTRO=os2 %1\r\n\r\n"
  },
  {
    "path": "builds/os2/prereq.cmd",
    "content": "@rem echo \"Installing prerequistes for Debian/Ubuntu\"\r\n\r\nyum -y update\r\nyum -y install cmake gcc watcom-wlink-hll gcc-wlink gcc-wrc gcc-c++ p7zip libc libcx kbuild-make binutils libc-devel libcx-devel\r\n"
  },
  {
    "path": "builds/tools/linux/use-built-bin.sh",
    "content": "#!/bin/bash\n###############################################################\n# use-built-bin.sh: Replaces file with symlink to the built\n# version from cmake.\n#\n# BUILT_DIR_INCLUDING_WWIV: Example /home/rushfan/out/wwiv\n# file: example: bbs\n#\n# Example use:\n#\n# ln -s $HOME/git/wwiv/builds/tools/linux/use-built-bin.sh\n# export BUILT_BIN=$HOME/out/wwiv\n# ./use-built-bin.sh ${BUILT_BIN} bbs wwivd wwivconfig network network?\n#\n\nif (( $# < 2 )); then\n    echo \"$0 BUILT_DIR_INCLUDING_WWIV file [file...]\"\n    exit 1\nelse\n    BIN=$1\n    shift\nfi\n\nfor file in $@; do\n    if [[ -x \"$file\" ]]; then\n\techo \"Linking file: $file\"\n\trm $file && ln -s ${BIN}/$file/$file\n    else\n\techo \"$file was not an executable, skipping...\"\n    fi\ndone\n\n"
  },
  {
    "path": "builds/tools/mkhdr.py",
    "content": "#!/usr/bin/python\n\nimport string\nimport sys\n\n\ndef convert_template(fn):\n    with open('template.h', 'r') as tmpl:\n        s=tmpl.read()\n        with open(fn+'.h', 'w') as out:\n            part = fn.upper()\n            new_s = s.replace('TEMPLATE', part)\n            out.write(new_s)\n            print ('created file: %s.h' % fn)\n\nfor arg in sys.argv[1:]:\n    convert_template(arg)\n\n  \n"
  },
  {
    "path": "builds/win/clean.cmd",
    "content": "rm -r CMakeCache.txt CMakeFiles \n"
  },
  {
    "path": "cmake/Common.cmake",
    "content": "#\r\n# Common CMake module for WWIV\r\n\r\nmessage(VERBOSE \"WWIV Common CMake Module.\")\r\n\r\nlist(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)\r\nlist(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules/sanitizers)\r\n# Need https://github.com/USCiLab/cereal/issues/631 in a build we pull first to move to 20.\r\nset (CMAKE_CXX_STANDARD 17)\r\nset (CMAKE_CXX_STANDARD_REQUIRED ON)\r\n\r\noption(WWIV_BUILD_TESTS \"Build WWIV test programs\" ON)\r\noption(WWIV_SSH_CRYPTLIB \"Include support for SSH using Cryptlib\" ON)\r\noption(WWIV_ZIP_INSTALL_FILES \"Create the zip files for data, gfiles, etc\" ON)\r\noption(WWIV_INSTALL \"Create install packages for both zip files and binaries.\" ON)\r\noption(WWIV_USE_PIPES \"Enable Named Pipes support for WWIV.\" ON)\r\n\r\n############################################################################### \r\n#\r\n# Build variables to come from Jenkins, environment, etc.\r\n\r\nset(WWIV_RELEASE \"5.9.0\" CACHE STRING \"WWIV Release Major Version to 3 digits\")\r\nset(WWIV_BUILD_NUMBER \"development\" CACHE STRING \"WWIV Build Number\")\r\nset(WWIV_ARCH \"x86\" CACHE STRING \"x86 or x64\")\r\nset(WWIV_DISTRO \"unknown\" CACHE STRING \"WWIV OS Distribution e.g. (win-x86 | linux-debian10) \")\r\nset(CPACK_PACKAGE_FILE_NAME \"wwiv-${WWIV_DISTRO}-${WWIV_RELEASE}.${WWIV_BUILD_NUMBER}\")\r\n\r\nset(WWIV_INSTALL_SRC \"${CMAKE_SOURCE_DIR}/install\" CACHE STRING \"By default this is: ${CMAKE_SOURCE_DIR}/install\")\r\nset(WWIV_RELEASE_DIR \"${CMAKE_BINARY_DIR}/release\" CACHE STRING \"By default this is: ${CMAKE_BINARY_DIR}/release\")\r\nfile(MAKE_DIRECTORY ${WWIV_RELEASE_DIR})\r\n#set(MY_CACHE_VARIABLE \"VALUE\" CACHE STRING \"Description\")\r\n\r\n# Packaging support\r\nset(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)\r\nset(CPACK_PACKAGE_NAME \"WWIV\")\r\nset(CPACK_PACKAGE_VENDOR \"WWIV Software Services\")\r\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"WWIV Computer bulletin board system (BBS)\")\r\n\r\nstring(REPLACE \".\" \";\" VERSION_LIST ${WWIV_RELEASE})\r\nlist(GET VERSION_LIST 0 CPACK_PACKAGE_VERSION_MAJOR)\r\nlist(GET VERSION_LIST 1 CPACK_PACKAGE_VERSION_MINOR)\r\nlist(GET VERSION_LIST 2 CPACK_PACKAGE_VERSION_PATCH)\r\n\r\nmessage(STATUS \"Set CPACK_PACKAGE_FILE_NAME: ${CPACK_PACKAGE_FILE_NAME}\")\r\nmessage(STATUS \"Set CPACK_PACKAGE_VERSION: ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\")\r\n\r\nset(CPACK_RESOURCE_FILE_LICENSE \"${CMAKE_SOURCE_DIR}/LICENSE\")\r\nset(CPACK_RESOURCE_FILE_README \"${CMAKE_SOURCE_DIR}/README.md\")\r\nset(CPACK_SOURCE_GENERATOR \"TGZ;ZIP\")\r\n\r\nfile(TO_NATIVE_PATH \"C:/wwiv\" C_WWIV_PATH)\r\nset(CPACK_NSIS_INSTALL_ROOT \"C:/wwiv\")\r\n\r\nset(CPACK_NSIS_PACKAGE_NAME \"WWIV BBS Software\")\r\nset(CPACK_NSIS_URL_INFO_ABOUT \"http://www.wwivbbs.org\")\r\nset(CPACK_NSIS_CONTACT \"http://docs.wwivbbs.org\")\r\n\r\nset(CPACK_PACKAGE_INSTALL_DIRECTORY \"\")\r\ninclude(CPack)\r\n\r\n\r\nmessage(STATUS \"WWIV Build Number: ${WWIV_RELEASE}.${WWIV_BUILD_NUMBER}\")\r\n\r\n\r\nmacro(ENSURE_MINIMUM_COMPILER_VERSIONS)\r\n  # Set minimum GCC version\r\n  # See https://stackoverflow.com/questions/14933172/how-can-i-add-a-minimum-compiler-version-requisite\r\n  if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.3)\r\n      message(FATAL_ERROR \"Require at least gcc-10.0; found: ${CMAKE_CXX_COMPILER_VERSION}\")\r\n  endif()\r\n\r\n  if (MSVC)\r\n    if (${MSVC_VERSION} LESS 1932)\r\n      # See https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros\r\n      # for versions\r\n      message(FATAL_ERROR \"Require at least MSVC 2022 16.2 (1932); Found: ${MSVC_VERSION}\")\r\n    endif()\r\n  endif()\r\nendmacro(ENSURE_MINIMUM_COMPILER_VERSIONS)\r\n\r\nif (UNIX)\r\nmessage(STATUS \"Platform: UNIX\")\r\nif (CMAKE_SYSTEM_NAME MATCHES \"Linux\")\r\n    message(STATUS \"Platform: Linux\")\r\n    set(LINUX TRUE)\r\n  endif()\r\n\r\nelseif (OS2)\r\n  message(STATUS \"Platform: OS/2\")\r\n  set(CMAKE_CXX_EXTENSIONS OFF)\r\n\r\nelseif (WIN32)\r\n  message(STATUS \"Platform: WIN32\") \r\n\r\n  if (MSVC)\r\n    # Don't show warnings on using normal POSIX functions.  Maybe one day\r\n    # We'll be using all C++ replacements for most things and can get rid of this.\r\n    add_definitions(/D_CRT_SECURE_NO_WARNINGS)\r\n    add_definitions(/D_CRT_NONSTDC_NO_DEPRECATE)\r\n    \r\n    # Warning 26444 is too noisy to be useful for passing parameters to functions.\r\n    # See https://developercommunity.visualstudio.com/content/problem/422153/warning-c26444-not-aligned-with-cppcoreguidelines.html\r\n    add_definitions(/wd26444)\r\n\r\n    # To silence cereal warnings that they know about already\r\n    # bug: https://github.com/USCiLab/cereal/issues/456\r\n    add_definitions(/D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING)\r\n  endif()\r\n  #\r\n  # Non MSVC Windows Specific settings\r\n  #\r\n  \r\n  # Make Windows.h not so awful if included\r\n  add_definitions(/D_WINSOCK_DEPRECATED_NO_WARNINGS)\r\n  add_definitions(/DNOMINMAX)\r\n  add_definitions(/DWIN32_LEAN_AND_MEAN=1)\r\n  # Otherwise fmt will include windows.h and that breaks everything\r\n  add_definitions(/DFMT_USE_WINDOWS_H=0)\r\n\r\nendif()\r\n\r\nif(WWIV_USE_PIPES AND (WIN32 OR OS2))\r\n  add_definitions(/DWWIV_USE_PIPES)\r\nendif()\r\n\r\nif( NOT CMAKE_BUILD_TYPE )\r\n  set( CMAKE_BUILD_TYPE \"Debug\" )\r\n  message(STATUS \"CMAKE_BUILD_TYPE not set; defaulting to Debug\")\r\nendif()\r\nmessage(VERBOSE \"CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\")\r\n\r\n\r\nmacro(set_max_warnings target)\r\n  if(UNIX) \r\n    target_compile_options(\"${target}\" PRIVATE -Wall -Wextra)\r\n  endif()\r\n  if(WIN32)\r\n    message(VERBOSE \"target_compile_options[${target} PRIVATE /W4)]\")\r\n    target_compile_options(\"${target}\" PRIVATE /W4)\r\n  endif()\r\nendmacro()\r\n\r\nMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)\r\n  STRING(COMPARE EQUAL \"${${PROJECT_NAME}_SOURCE_DIR}\"\r\n    \"${${PROJECT_NAME}_BINARY_DIR}\" insource)\r\n  GET_FILENAME_COMPONENT(PARENTDIR ${${PROJECT_NAME}_SOURCE_DIR} PATH)\r\n  STRING(COMPARE EQUAL \"${${PROJECT_NAME}_SOURCE_DIR}\"\r\n    \"${PARENTDIR}\" insourcesubdir)\r\n  IF(insource OR insourcesubdir)\r\n    MESSAGE(FATAL_ERROR \r\n    \"${PROJECT_NAME} requires an out of source build.\r\n     Please see https://github.com/wwivbbs/wwiv#out-of-source-build-warning\r\n     This process created the file `CMakeCache.txt' and the directory `CMakeFiles'.\r\n     Please delete them before re-running cmake.\"\r\n    )\r\n  ENDIF(insource OR insourcesubdir)\r\nENDMACRO(MACRO_ENSURE_OUT_OF_SOURCE_BUILD)\r\n\r\n  \r\nmessage(VERBOSE \"CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}\")\r\n\r\nfunction(zip output_file input_files working_dir)\r\n  #message(DEBUG \"zip: ${output_file} : ${input_files}\")\r\n  add_custom_command(\r\n    COMMAND ${CMAKE_COMMAND} -E tar \"cf\" \"${output_file}\" --format=zip -- ${input_files}\r\n    WORKING_DIRECTORY \"${working_dir}\"\r\n    OUTPUT  \"${output_file}\"\r\n    DEPENDS ${input_files}\r\n    COMMENT \"Creating ZIP file: ${output_file}.\"\r\n    )\r\nendfunction()\r\n\r\nfunction(create_datafile_archive arc dir)\r\n  message(DEBUG \"create_datafile_archive: dir: ${dir}: ${WWIV_RELEASE_DIR}/${arc}.zip\")\r\n  file(GLOB_RECURSE DATA_FILES \"${dir}/*\")\r\n  zip(\"${WWIV_RELEASE_DIR}/${arc}.zip\" \"${DATA_FILES}\" \"${dir}/\")\r\n  set(ARC_PATH \"${WWIV_RELEASE_DIR}/${arc}.zip\")\r\n  add_custom_target(\"${arc}_archive\" ALL DEPENDS \"${ARC_PATH}\")\r\n  install(FILES \"${ARC_PATH}\" DESTINATION .)\r\nendfunction()\r\n\r\nIF(${CMAKE_BUILD_TYPE} STREQUAL \"Debug\")\r\n  message(VERBOSE \"Defining _DEBUG macro for debug build\")\r\n  ADD_DEFINITIONS(-D_DEBUG)\r\nENDIF()\r\n"
  },
  {
    "path": "cmake/FindWWIVCurses.cmake",
    "content": "#\n# FindWWIVCurses.\n#\n# On Windows, WWIV uses PDCurses. On all other platforms, use ncurses.\n\nif(UNIX)\n  # message(\"FindWWIVCurses: Using NCurses\")\n  set(CURSES_NEED_NCURSES TRUE)\n  set(CURSES_NEED_WIDE TRUE)\n  find_package(Curses REQUIRED)\nelseif(WIN32 OR OS2)\n  # message(\"FindWWIVCurses: Using PDCurses\")\n  include_directories(${PDCURSES_INCLUDE_DIRS})\n  # message(\"FindWWIVCurses: PDCURSES_INCLUDE_DIRS: ${PDCURSES_INCLUDE_DIRS}\")\n  message(VERBOSE \"FindWWIVCurses: CURSES_LIBRARIES: ${CURSES_LIBRARIES}\")\nendif()\n# message(\"FindWWIVCurses: Curses Library: ${CURSES_LIBRARIES}\") \n"
  },
  {
    "path": "cmake/Modules/Findbenchmark.cmake",
    "content": "# Findbenchmark.cmake\n# - Try to find benchmark\n#\n# The following variables are optionally searched for defaults\n#  benchmark_ROOT_DIR:  Base directory where all benchmark components are found\n#\n# Once done this will define\n#  benchmark_FOUND - System has benchmark\n#  benchmark_INCLUDE_DIRS - The benchmark include directories\n#  benchmark_LIBRARIES - The libraries needed to use benchmark\nmessage(\"WWIV Findbenchmark\")\nset(benchmark_ROOT_DIR \"${CMAKE_SOURCE_DIR}/deps/benchmark\" CACHE PATH \"Folder containing benchmark\")\n\nfind_path(benchmark_INCLUDE_DIRS \"benchmark/benchmark.h\"\n  PATHS ${benchmark_ROOT_DIR}\n  PATH_SUFFIXES include\n  NO_DEFAULT_PATH)\n\nset(benchmark_LIBRARY benchmark CACHE STRING \"benchmark target\" FORCE)\n\ninclude(FindPackageHandleStandardArgs)\n# handle the QUIETLY and REQUIRED arguments and set benchmark_FOUND to TRUE\n# if all listed variables are TRUE\nfind_package_handle_standard_args(benchmark FOUND_VAR benchmark_FOUND\n  REQUIRED_VARS benchmark_LIBRARY\n  benchmark_INCLUDE_DIRS)\n\nif(benchmark_FOUND)\n  set(benchmark_LIBRARIES ${benchmark_LIBRARY})\nendif()\nmessage(\"benchmark_INCLUDE_DIRS ${benchmark_INCLUDE_DIRS}\")\n\nmark_as_advanced(benchmark_INCLUDE_DIR benchmark_LIBRARY)"
  },
  {
    "path": "cmake/Modules/sanitizers/FindASan.cmake",
    "content": "#\n# The MIT License (MIT)\n#\n# Copyright (c) 2013 Matthew Arsenault\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n# This module tests if address sanitizer is supported by the compiler,\n# and creates a ASan build type (i.e. set CMAKE_BUILD_TYPE=ASan to use\n# it). This sets the following variables:\n#\n# CMAKE_C_FLAGS_ASAN - Flags to use for C with asan\n# CMAKE_CXX_FLAGS_ASAN  - Flags to use for C++ with asan\n# HAVE_ADDRESS_SANITIZER - True or false if the ASan build type is available\n\ninclude(CheckCCompilerFlag)\n\n# Set -Werror to catch \"argument unused during compilation\" warnings\nset(CMAKE_REQUIRED_FLAGS \"-Werror -faddress-sanitizer\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-faddress-sanitizer\" HAVE_FLAG_ADDRESS_SANITIZER)\n\nset(CMAKE_REQUIRED_FLAGS \"-Werror -fsanitize=address\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-fsanitize=address\" HAVE_FLAG_SANITIZE_ADDRESS)\n\nunset(CMAKE_REQUIRED_FLAGS)\n\nif(HAVE_FLAG_SANITIZE_ADDRESS)\n  # Clang 3.2+ use this version\n  set(ADDRESS_SANITIZER_FLAG \"-fsanitize=address\")\nelseif(HAVE_FLAG_ADDRESS_SANITIZER)\n  # Older deprecated flag for ASan\n  set(ADDRESS_SANITIZER_FLAG \"-faddress-sanitizer\")\nendif()\n\nif(NOT ADDRESS_SANITIZER_FLAG)\n  return()\nelse(NOT ADDRESS_SANITIZER_FLAG)\n  set(HAVE_ADDRESS_SANITIZER FALSE)\nendif()\n\nset(HAVE_ADDRESS_SANITIZER TRUE)\n\nset(CMAKE_C_FLAGS_ASAN \"-O1 -g ${ADDRESS_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls\"\n    CACHE STRING \"Flags used by the C compiler during ASan builds.\"\n    FORCE)\nset(CMAKE_CXX_FLAGS_ASAN \"-O1 -g ${ADDRESS_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls\"\n    CACHE STRING \"Flags used by the C++ compiler during ASan builds.\"\n    FORCE)\nset(CMAKE_EXE_LINKER_FLAGS_ASAN \"${ADDRESS_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used for linking binaries during ASan builds.\"\n    FORCE)\nset(CMAKE_SHARED_LINKER_FLAGS_ASAN \"${ADDRESS_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used by the shared libraries linker during ASan builds.\"\n    FORCE)\nmark_as_advanced(CMAKE_C_FLAGS_ASAN\n                 CMAKE_CXX_FLAGS_ASAN\n                 CMAKE_EXE_LINKER_FLAGS_ASAN\n                 CMAKE_SHARED_LINKER_FLAGS_ASAN)\n"
  },
  {
    "path": "cmake/Modules/sanitizers/FindMSan.cmake",
    "content": "#\n# The MIT License (MIT)\n#\n# Copyright (c) 2013 Matthew Arsenault\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n# This module tests if memory sanitizer is supported by the compiler,\n# and creates a MSan build type (i.e. set CMAKE_BUILD_TYPE=MSan to use\n# it). This sets the following variables:\n#\n# CMAKE_C_FLAGS_MSAN - Flags to use for C with msan\n# CMAKE_CXX_FLAGS_MSAN  - Flags to use for C++ with msan\n# HAVE_MEMORY_SANITIZER - True or false if the MSan build type is available\n\ninclude(CheckCCompilerFlag)\n\n# Set -Werror to catch \"argument unused during compilation\" warnings\nset(CMAKE_REQUIRED_FLAGS \"-Werror -fmemory-sanitizer\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-fmemory-sanitizer\" HAVE_FLAG_MEMORY_SANITIZER)\n\nset(CMAKE_REQUIRED_FLAGS \"-Werror -fsanitize=memory\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-fsanitize=memory\" HAVE_FLAG_SANITIZE_MEMORY)\n\nunset(CMAKE_REQUIRED_FLAGS)\n\nif(HAVE_FLAG_SANITIZE_MEMORY)\n  # Clang 3.2+ use this version\n  set(MEMORY_SANITIZER_FLAG \"-fsanitize=memory\")\nelseif(HAVE_FLAG_MEMORY_SANITIZER)\n  # Older deprecated flag for MSan\n  set(MEMORY_SANITIZER_FLAG \"-fmemory-sanitizer\")\nendif()\n\nif(NOT MEMORY_SANITIZER_FLAG)\n  return()\nelse(NOT MEMORY_SANITIZER_FLAG)\n  set(HAVE_MEMORY_SANITIZER TRUE)\nendif()\n\nset(HAVE_MEMORY_SANITIZER TRUE)\n\nset(CMAKE_C_FLAGS_MSAN \"-O1 -g ${MEMORY_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls\"\n    CACHE STRING \"Flags used by the C compiler during MSan builds.\"\n    FORCE)\nset(CMAKE_CXX_FLAGS_MSAN \"-O1 -g ${MEMORY_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls\"\n    CACHE STRING \"Flags used by the C++ compiler during MSan builds.\"\n    FORCE)\nset(CMAKE_EXE_LINKER_FLAGS_MSAN \"${MEMORY_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used for linking binaries during MSan builds.\"\n    FORCE)\nset(CMAKE_SHARED_LINKER_FLAGS_MSAN \"${MEMORY_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used by the shared libraries linker during MSan builds.\"\n    FORCE)\nmark_as_advanced(CMAKE_C_FLAGS_MSAN\n                 CMAKE_CXX_FLAGS_MSAN\n                 CMAKE_EXE_LINKER_FLAGS_MSAN\n                 CMAKE_SHARED_LINKER_FLAGS_MSAN)\n"
  },
  {
    "path": "cmake/Modules/sanitizers/FindTSan.cmake",
    "content": "#\n# The MIT License (MIT)\n#\n# Copyright (c) 2013 Matthew Arsenault\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n# This module tests if thread sanitizer is supported by the compiler,\n# and creates a TSan build type (i.e. set CMAKE_BUILD_TYPE=TSan to use\n# it). This sets the following variables:\n#\n# CMAKE_C_FLAGS_TSAN - Flags to use for C with tsan\n# CMAKE_CXX_FLAGS_TSAN  - Flags to use for C++ with tsan\n# HAVE_THREAD_SANITIZER - True or false if the TSan build type is available\n\ninclude(CheckCCompilerFlag)\n\n\n# Set -Werror to catch \"argument unused during compilation\" warnings\nset(CMAKE_REQUIRED_FLAGS \"-Werror -fthread-sanitizer\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-fthread-sanitizer\" HAVE_FLAG_THREAD_SANITIZER)\n\nset(CMAKE_REQUIRED_FLAGS \"-Werror -fsanitize=thread\") # Also needs to be a link flag for test to pass\ncheck_c_compiler_flag(\"-fsanitize=thread\" HAVE_FLAG_SANITIZE_THREAD)\nunset(CMAKE_REQUIRED_FLAGS)\n\n# A special test that uses threads seems to not be necessary. tsan\n# symbols are used even in just int main() { return 0; }\n\n\nif(HAVE_FLAG_SANITIZE_THREAD)\n  # Clang 3.2+ use this version\n  set(THREAD_SANITIZER_FLAG \"-fsanitize=thread\")\nelseif(HAVE_FLAG_THREAD_SANITIZER)\n  # Older deprecated flag for TSan\n  set(THREAD_SANITIZER_FLAG_FLAG \"-fthread-sanitizer\")\nelse()\n  set(HAVE_THREAD_SANITIZER FALSE)\n  return()\nendif()\n\nset(HAVE_THREAD_SANITIZER TRUE)\n\nset(CMAKE_C_FLAGS_TSAN \"-O1 -g ${THREAD_SANITIZER_FLAG} -fno-omit-frame-pointer\"\n    CACHE STRING \"Flags used by the C compiler during TSan builds.\"\n    FORCE\n    )\nset(CMAKE_CXX_FLAGS_TSAN \"-O1 -g ${THREAD_SANITIZER_FLAG} -fno-omit-frame-pointer\"\n    CACHE STRING \"Flags used by the C++ compiler during TSan builds.\"\n    FORCE)\nset(CMAKE_EXE_LINKER_FLAGS_TSAN \"${THREAD_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used for linking binaries during TSan builds.\"\n    FORCE)\nset(CMAKE_SHARED_LINKER_FLAGS_TSAN \"${THREAD_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used by the shared libraries linker during TSan builds.\"\n    FORCE)\nmark_as_advanced(CMAKE_C_FLAGS_TSAN\n                 CMAKE_CXX_FLAGS_TSAN\n                 CMAKE_EXE_LINKER_FLAGS_TSAN\n                 CMAKE_SHARED_LINKER_FLAGS_TSAN)\n"
  },
  {
    "path": "cmake/Modules/sanitizers/FindUBSan.cmake",
    "content": "#\n# The MIT License (MIT)\n#\n# Copyright (c) 2013 Matthew Arsenault\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n#\n\n# Check if the compiler supports a working ubsan. Provides a UBSan\n# build type, which is essentially Debug + ubsan. The flag can be used\n# independently to compose it with other build types or sanitizers.\n#\n# Sets these variables:\n#\n# HAVE_UNDEFINED_BEHAVIOR_SANITIZER - True or false if the UBSan is available\n# UNDEFINED_BEHAVIOR_SANITIZER_FLAG - Flag to add to compiler to use ubsan if supported\n#\n# CMAKE_C_FLAGS_UBSAN - Flags to use for C with ubsan\n# CMAKE_CXX_FLAGS_UBSAN  - Flags to use for C++ with ubsan\n##\n#\n\n\ninclude(CheckCXXCompilerFlag)\ninclude(CheckCXXSourceRuns)\n\n# Set -Werror to catch \"argument unused during compilation\" warnings\nset(CMAKE_REQUIRED_FLAGS \"-Werror\")\ncheck_cxx_compiler_flag(\"-fsanitize=undefined\" HAVE_FLAG_SANITIZE_UNDEFINED)\ncheck_cxx_compiler_flag(\"-fcatch-undefined-behavior\" HAVE_FLAG_CATCH_UNDEFINED_BEHAVIOR)\nif(HAVE_FLAG_SANITIZE_UNDEFINED)\n  set(UNDEFINED_BEHAVIOR_SANITIZER_FLAG \"-fsanitize=undefined\")\nelseif(HAVE_FLAG_CATCH_UNDEFINED_BEHAVIOR)\n  set(UNDEFINED_BEHAVIOR_SANITIZER_FLAG \"-fcatch-undefined-behavior\")\nelse()\n  set(HAVE_UNDEFINED_BEHAVIOR_SANITIZER FALSE)\n  return()\nendif()\nunset(CMAKE_REQUIRED_FLAGS)\n\n\n# It isn't sufficient to check if the flag works since the\n# check_c_compiler_flag test doesn't link the output.\n#\n# Most clang packages ship broken packages (the autotools build\n# produces a broken package which doesn't include the ubsan\n# compiler-rt, so check that it actually works with a linked program\n# before trying to use it\nset(CMAKE_REQUIRED_FLAGS \"${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -Wno-error=delete-non-virtual-dtor\")\n\ncheck_cxx_source_runs(\n\"\n#include <cstdio>\n#include <cstdlib>\n#include <iostream>\n\nclass BarB\n{\n    public:\n        float y;\n        /* Include something that uses a virtual function. The symbols\n           that are broken on current OS X libc++ involve this */\n        virtual int arst(int o)\n        {\n            return 4 + o;\n        }\n    };\n\n/* Just include something that ubsan will need to check */\nint main(int argc, const char* argv[])\n{\n    BarB* b = new BarB();\n    if (argc > 1)\n    {\n        fputs(argv[atoi(argv[1])], stdout);\n        std::cout << b->arst(atoi(argv[1]));\n    }\n\n    delete b;\n    return 0;\n}\n\"\n  HAVE_UNDEFINED_BEHAVIOR_SANITIZER)\nunset(CMAKE_REQUIRED_FLAGS)\n\nif(NOT HAVE_UNDEFINED_BEHAVIOR_SANITIZER)\n  return()\nendif()\n\n\nset(CMAKE_C_FLAGS_UBSAN \"-O0 -g ${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -fno-omit-frame-pointer\"\n    CACHE STRING \"Flags used by the C compiler during UBSan builds.\"\n    FORCE)\nset(CMAKE_CXX_FLAGS_UBSAN \"-O0 -g ${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -fno-omit-frame-pointer\"\n    CACHE STRING \"Flags used by the C++ compiler during UBSan builds.\"\n    FORCE)\nset(CMAKE_EXE_LINKER_FLAGS_UBSAN \"${UNDEFINED_BEHAVIOR_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used for linking binaries during UBSan builds.\"\n    FORCE)\nset(CMAKE_SHARED_LINKER_FLAGS_UBSAN \"${UNDEFINED_BEHAVIOR_SANITIZER_FLAG}\"\n    CACHE STRING \"Flags used by the shared libraries linker during UBSan builds.\"\n    FORCE)\nmark_as_advanced(CMAKE_C_FLAGS_UBSAN\n                 CMAKE_CXX_FLAGS_UBSAN\n                 CMAKE_EXE_LINKER_FLAGS_UBSAN\n                 CMAKE_SHARED_LINKER_FLAGS_UBSAN)\n\n\n"
  },
  {
    "path": "cmake/Modules/sanitizers/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 Matt Arsenault\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "cmake/Modules/sanitizers/README",
    "content": "Downloaded from: https://github.com/arsenm/sanitizers-cmake\n\n"
  },
  {
    "path": "cmake/Modules/sanitizers/README.md",
    "content": "sanitizers-cmake\n================\n\nCMake modules to help use sanitizers\n"
  },
  {
    "path": "cmake-config.sh",
    "content": "#!/bin/bash\n\n# WWIV Version 5.x\n# Copyright (C)2014-2022, WWIV Software Services\n#\n# Licensed  under the  Apache License, Version  2.0 (the \"License\");\n# you may not use this  file  except in compliance with the License.\n# You may obtain a copy of the License at\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless  required  by  applicable  law  or agreed to  in  writing,\n# software  distributed  under  the  License  is  distributed on an\n# AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,\n# either  express  or implied.  See  the  License for  the specific\n# language governing permissions and limitations under the License.\n#\n\ndeclare -r OS=$(uname)\ndeclare -r FULLOS=$(uname -a)\ndeclare -r ARCH=$(uname -m)\ndeclare -r HERE=$(dirname $(realpath $0))\ndeclare -r NINJA=$(which ninja)\n\necho \"Debug Info [OS] - ${OS}\"\necho \"Debug Info [FULLOS] - ${FULLOS}\"\necho \"Debug Info [ARCH] - ${ARCH}\"\necho \"Debug Info [HERE] - ${HERE}\"\necho \"Debug Info [NINJA] - ${NINJA}\"\n\nif [ \"${ARCH}\" == \"aarch64\" ]; then\n\techo \"Configuring for ARM64\"\n\texport VCPKG_FORCE_SYSTEM_BINARIES=1\nfi\n\n\nS_MODLIST=$(git submodule status)\nif [ -z \"$S_MODLIST\" ]\nthen\n      echo \"No Submodules Required - OK\"\n      SUBSOK=\"true\"\nelse\n\tSUBSOK=\"true\"\n\twhile IFS= read -r line; do\n\t\tS_MODNAME=$(echo \"${line}\" | awk -F ' ' '{print $2}')\n\t\tif [[ ${line} = -* ]]; then\n\t\t\techo \"Submodule [${S_MODNAME}] - Missing\"\n\t\t\tSUBSOK=\"false\"\n\t\telse\n\t\t\techo \"Submodule [${S_MODNAME}] - OK\"\n\t\tfi\n\tdone <<< \"${S_MODLIST}\"\n\tif ! [ \"${SUBSOK}\" == \"true\" ]; then\n\t\techo \"Required submodules not found: Aborting\"\n\t\techo \"Please run \\\"git submodule update --init --recursive\\\" to pull required submodules.\"\n\t\texit 1\n\tfi\nfi\n\nif ! [ -x \"$(command -v cmake)\" ]; then\n\techo \"** ERROR: Please install cmake\"\n\texit 1\nfi\n\nif ! [ -x \"$(command -v ninja)\" ]; then\n\techo \"** ERROR: Please install ninja\"\n\techo \"\"\n\techo \"   Debian/Ubuntu: apt install ninja-build\"\n\techo \"   CentOS:        yum install ninja-build\"\n\texit 1\nfi\n\nif [[ \"${OS}\" == \"SunOS\" ]]; then\n    echo \"Setting compiler to gcc for SunOS\"\n    export CXX=/usr/bin/g++\n    export CC=/usr/bin/gcc\nfi\n\necho \"Using Ninja Build Tool: ${NINJA}\"\necho \"Using Source Root:      ${HERE}\"\n\ncmake -G \"Ninja\" ${HERE}  -DCMAKE_TOOLCHAIN_FILE=${HERE}/vcpkg/scripts/buildsystems/vcpkg.cmake \"${@}\"\n"
  },
  {
    "path": "common/CMakeLists.txt",
    "content": "# CMake for WWIV\nInclude(FindWWIVCurses)\n\nset(COMMON_SOURCES \n \"bgetch.cpp\"\n \"checka.cpp\"\n \"com.cpp\"\n \"context.cpp\"\n \"datetime.cpp\"\n \"full_screen.cpp\"\n \"input.cpp\"\n \"input_range.cpp\"\n \"iobase.cpp\"\n \"language.cpp\"\n \"macro_context.cpp\"\n \"menus/menu_data_util.cpp\"\n \"menus/menu_generator.cpp\"\n \"message_editor_data.cpp\"\n \"null_remote_io.cpp\"\n \"output.cpp\"\n \"pause.cpp\"\n \"pipe_expr.cpp\"\n \"printfile.cpp\"\n \"quote.cpp\"\n \"remote_io.cpp\"\n \"remote_socket_io.cpp\"\n \"value/bbsvalueprovider.cpp\"\n \"value/uservalueprovider.cpp\"\n \"workspace.cpp\"\n)\n\nadd_library(\n  common \n  ${COMMON_SOURCES} \n) \n\ntarget_link_libraries(\n  common \n  fmt::fmt-header-only\n  local_io \n  core \n  sdk \n)\n\nif (OS2 OR WIN32)\n  target_sources(common PRIVATE \"remote_pipe_io.cpp\")\nendif()\n\nset_max_warnings(common)\n\ntarget_include_directories(common PRIVATE ${CMAKE_CURRENT_BINARY_DIR})\n\n# Tests\n\nif (WWIV_BUILD_TESTS)\n\n  set(common_test_sources\n    \"acs_test.cpp\"\n    \"input_range_test.cpp\"\n    \"common_test_main.cpp\"\n    \"menu_data_util_test.cpp\"\n    \"pipe_expr_test.cpp\"\n    \"remote_socket_io_test.cpp\"\n  )\n\n  set(common_fixture_sources\n    common_helper.cpp \n  )\n\n  add_library(common_fixtures ${common_fixture_sources})\n  target_link_libraries(common_fixtures common core core_fixtures)\n\n  add_executable(common_tests ${common_test_sources})\n  target_link_libraries(common_tests common_fixtures common GTest::gmock GTest::gtest)\n  gtest_discover_tests(common_tests)\n\nendif()\n"
  },
  {
    "path": "common/acs_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/value/uservalueprovider.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/eval.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::common::value;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\n\nclass AcsTest : public ::testing::Test {\npublic:\n  AcsTest() : config_(\"\", wwiv::sdk::config_t{}) {\n    config_.set_initialized_for_test(true);\n    config_.newuser_sl(10);\n    config_.validated_sl(20);\n  }\n\n  void createEval(const std::string& expr) { \n    eval = std::make_unique<Eval>(expr);\n    eval->add(std::make_unique<UserValueProvider>(config_, user_, user_.sl(), sl_));\n\n  }\n  std::unique_ptr<Eval> eval;\n  wwiv::sdk::Config config_;\n  wwiv::sdk::User user_{};\n  slrec sl_{};\n};\n\nTEST_F(AcsTest, SL_GT_Pass) {\n  user_.sl(201);\n  createEval(\"user.sl>200\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, SL_GT_False) {\n  user_.sl(10);\n  createEval(\"user.sl>200\");\n  EXPECT_FALSE(eval->eval());\n}\n\nTEST_F(AcsTest, DummySL_LT) {\n  user_.sl(10);\n  createEval(\"user.sl<200\");\n\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, DummySL_LT_False) {\n  user_.sl(25);\n  createEval(\"user.sl<20\");\n\n  EXPECT_FALSE(eval->eval());\n}\n\nTEST_F(AcsTest, Or) {\n  user_.sl(201);\n  createEval(\"user.sl>200 || user.dsl > 200 || user.name == \\\"Rushfan\\\"\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Multiple_Group_SL) {\n  user_.sl(201);\n  user_.dsl(100);\n  user_.set_name(\"SYSOP\");\n  createEval(\"(user.sl>200 || user.dsl > 200) || user.name == \\\"Rushfan\\\"\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Multiple_Group_DSL) {\n  user_.sl(10);\n  user_.dsl(201);\n  user_.set_name(\"SYSOP\");\n  createEval(\"(user.sl>200 || user.dsl > 200) || user.name == \\\"Rushfan\\\"\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Multiple_Group_None) {\n  user_.sl(22);\n  user_.dsl(12);\n  user_.set_name(\"SYSOP\");\n  createEval(\"(user.sl>200 || user.dsl > 200) || user.name == \\\"Rushfan\\\"\");\n  EXPECT_FALSE(eval->eval());\n  LOG(INFO) << wwiv::strings::JoinStrings(eval->debug_info(), \"\\r\\n\");\n}\n\nTEST_F(AcsTest, Ar_Pass) {\n  user_.ar_int(2);  // B\n  createEval(\"user.ar == 'B'\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Ar_Fail) {\n  user_.ar_int(5); // a || c\n  createEval(\"user.ar == 'B'\");\n  EXPECT_FALSE(eval->eval());\n}\n\nTEST_F(AcsTest, BadAttrOnUser) {\n  createEval(\"user.foo<20\");\n\n  EXPECT_FALSE(eval->eval());\n  EXPECT_EQ(eval->error_text(), \"No user attribute named 'user.foo' exists.\");\n  LOG(INFO) << wwiv::strings::JoinStrings(eval->debug_info(), \"\\r\\n\");\n}\n\nTEST_F(AcsTest, BadExpression) { \n  createEval(\"foo == ~ foo\");\n  EXPECT_FALSE(eval->eval());\n  LOG(INFO) << wwiv::strings::JoinStrings(eval->debug_info(), \"\\r\\n\");\n}\n\nTEST_F(AcsTest, Sysop_Pass) {\n  user_.sl(255);\n  createEval(\"user.sysop == \\\"true\\\"\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Sysop_Pass_Literal) {\n  user_.sl(255);\n  createEval(\"user.sysop == true\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Sysop_Fail) {\n  user_.sl(200);\n  createEval(\"user.sysop == true\");\n  EXPECT_FALSE(eval->eval());\n}\n\nTEST_F(AcsTest, Sysop_Pass_Negated) {\n  user_.sl(200);\n  createEval(\"user.sysop == false\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Regnum_Pass) {\n  user_.sl(12);\n  user_.wwiv_regnum(12345);\n  createEval(\"user.registered == true\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, Regnum_Fail) {\n  user_.sl(12);\n  user_.wwiv_regnum(0);\n  createEval(\"user.registered == true\");\n  EXPECT_FALSE(eval->eval());\n}\n\nTEST_F(AcsTest, CoSysop_Pass) {\n  user_.sl(200);\n  sl_.ability |= ability_cosysop;\n  createEval(\"user.cosysop == true\");\n  EXPECT_TRUE(eval->eval());\n}\n\nTEST_F(AcsTest, CoSysop_Fail) {\n  user_.sl(200);\n  sl_.ability &= ~ability_cosysop;\n  createEval(\"user.cosysop == true\");\n  EXPECT_FALSE(eval->eval());\n}\n"
  },
  {
    "path": "common/bgetch.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/common_events.h\"\n#include \"common/context.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/eventbus.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/ansi/ansi.h\"\n\n#include <chrono>\n\nusing std::chrono::minutes;\nusing std::chrono::seconds;\nusing std::chrono::steady_clock;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic steady_clock::time_point time_lastchar_pressed;\nstatic void lastchar_pressed() { time_lastchar_pressed = steady_clock::now(); }\n\nstatic bool so(const SessionContext& sess) { return (sess.effective_sl() == 255); }\n\nvoid Output::RedrawCurrentLine() {\n  const auto line = SaveCurrentLine();\n  nl();\n  RestoreCurrentLine(line);\n}\n\n\nbool Output::RestoreCurrentLine(const SavedLine& line) {\n  if (wherex()) {\n    nl();\n  }\n  for (const auto& c : line.line) {\n    setc(c.second);\n    outchr(c.first, true);\n  }\n  flush();\n  setc(line.color);\n\n  return true;\n}\n\nSavedLine Output::SaveCurrentLine() const { return {current_line_, curatr()}; }\n\nvoid Output::dump() {\n  if (sess().ok_modem_stuff()) {\n    remoteIO()->purgeIn();\n  }\n}\n\nint Output::wherex() const {\n  const auto x = localIO()->WhereX();\n  if (x != x_) {\n    VLOG(1) << \"x: \" << x << \" != x_: \" << x_;\n  }\n  return x_;\n}\n\nstd::chrono::duration<double> Input::key_timeout() const {\n  if (so(sess())) {\n    return sysop_key_timeout_;\n  }\n  return non_sysop_key_timeout_;\n}\n\n/* This function returns one character from either the local keyboard or\n * remote com port (if applicable).  After 1.5 minutes of inactivity, a\n * beep is sounded.  After 3 minutes of inactivity, the user is hung up.\n */\nchar Input::getkey(bool allow_extended_input) {\n  resetnsp();\n  auto beepyet = false;\n  lastchar_pressed();\n\n  const auto tv = key_timeout();\n  auto tv1 = tv - minutes(1);\n  if (tv1 < seconds(10)) {\n    tv1 = seconds(10);\n  }\n\n  // Since were waiting for a key, reset the # of lines we've displayed since a pause.\n  bout.clear_lines_listed();\n  while (!sess().hangup()) {\n    bus().invoke<CheckForHangupEvent>();\n    while (!bkbhit() && !sess().hangup()) {\n      // Try to make hangups happen faster.\n      if (sess().incom() && sess().ok_modem_stuff() && !remoteIO()->connected()) {\n        bus().invoke<HangupEvent>(HangupEvent{hangup_type_t::user_disconnected});\n      }\n      bus().invoke<CheckForHangupEvent>();\n      bus().invoke<ProcessInstanceMessages>();\n      bus().invoke<GiveupTimeslices>();\n      \n      auto dd = steady_clock::now();\n      auto diff = dd - time_lastchar_pressed;\n      if (diff > tv1 && !beepyet) {\n        beepyet = true;\n        bout.outchr(CG);\n      }\n      if (diff > tv) {\n        bout.nl();\n        bout.outstr(\"Call back later when you are there.\\r\\n\");\n        bus().invoke<HangupEvent>();\n      }\n    }\n    if (const auto ch = bgetch(allow_extended_input)) {\n      return ch;\n    }\n  }\n  DLOG(FATAL) << \"getkey: Should not happen\";\n  return 0;\n}\n\nvoid Output::reset() {\n  newline = true;\n  ansi_->reset();\n  curatr(0x07);\n  clear_lines_listed();\n}\n\n\nnamespace wwiv::common {\n\n\nstatic char HandleControlKey(const char c, const SessionContext& context, wwiv::sdk::User& user) {\n  if (c == CBACKSPACE) {\n    return BACKSPACE;\n  }\n  if (!bin.okskey()) {\n    return c;\n  }\n  switch (c) {\n  case CA: // CTRL-A\n  case CD: // CTRL-D\n  case CF: // CTRL-F\n    if (context.okmacro() && !bin.charbufferpointer_) {\n      static constexpr int MACRO_KEY_TABLE[] = {0, 2, 0, 0, 0, 0, 1};\n      const auto macroNum = MACRO_KEY_TABLE[static_cast<int>(c)];\n      to_char_array(bin.charbuffer, user.macro(macroNum));\n      const auto nextchar = bin.charbuffer[0];\n      if (nextchar) {\n        bin.charbufferpointer_ = 1;\n      }\n      return nextchar;\n    }\n    break;\n  case CT: // CTRL - T\n    bus().invoke<DisplayTimeLeft>();\n    break;\n  case CU: { // CTRL-U\n    const auto line = bout.SaveCurrentLine();\n    bout.ansic(0);\n    bout.nl(2);\n    bus().invoke<DisplayMultiInstanceStatus>();\n    bout.nl();\n    bout.RestoreCurrentLine(line);\n  } break;\n  case 18: // CR\n    bout.RedrawCurrentLine();\n    break;\n  case CL: // CTRL - L\n    if (so(context)) {\n      bus().invoke<ToggleInvisble>();\n    }\n    break;\n  case CN: // CTRL - N\n    bus().invoke<ToggleAvailable>();\n    break;\n  case CY:\n    user.toggle_flag(User::pauseOnPage);\n    break;\n  default:\n    return c;\n  }\n  // Nothing to do here.\n  return 0;\n}\n\n/* This function checks both the local keyboard, and the remote terminal\n * (if any) for input.  If there is input, the key is returned.  If there\n * is no input, a zero is returned.  Function keys hit are interpreted as\n * such within the routine and not returned.\n */\nchar Input::bgetch(bool allow_extended_input) {\n  char ch = 0;\n\n  if (charbufferpointer_) {\n    if (!charbuffer[charbufferpointer_]) {\n      charbufferpointer_ = 0;\n      charbuffer[0] = 0;\n    } else {\n      if (charbuffer[charbufferpointer_] == CC) {\n        charbuffer[charbufferpointer_] = CP;\n      }\n      return charbuffer[charbufferpointer_++];\n    }\n  }\n  if (localIO()->KeyPressed()) {\n    ch = localIO()->GetChar();\n    bin.SetLastKeyLocal(true);\n    if (!allow_extended_input) {\n      if (!ch) {\n        ch = localIO()->GetChar();\n        bus().invoke<HandleSysopKey>(HandleSysopKey{static_cast<uint8_t>(ch)});\n        ch = static_cast<char>(((ch == F10) || (ch == CF10)) ? 2 : 0);\n      }\n    }\n    lastchar_pressed();\n  } else if (sess().incom() && bkbhitraw()) {\n    ch = bgetchraw();\n    bin.SetLastKeyLocal(false);\n  }\n\n  if (!allow_extended_input) {\n    return HandleControlKey(ch, sess(), user());\n  }\n\n  return ch;\n}\n\nchar Input::bgetchraw() {\n  if (sess().ok_modem_stuff() && nullptr != remoteIO()) {\n    if (remoteIO()->incoming()) {\n      return static_cast<char>(remoteIO()->getW());\n    }\n    if (localIO()->KeyPressed()) {\n      return static_cast<char>(localIO()->GetChar());\n    }\n  }\n  return 0;\n}\n\nbool Input::bkbhitraw() {\n  if (sess().ok_modem_stuff()) {\n    return remoteIO()->incoming() || localIO()->KeyPressed();\n  }\n  return localIO()->KeyPressed();\n}\n\nbool Input::bkbhit() {\n  if (localIO()->KeyPressed() || (sess().incom() && bkbhitraw()) ||\n      (charbufferpointer_ && charbuffer[charbufferpointer_])) {\n    return true;\n  }\n  return false;\n}\n\n// The final character of an ansi sequence\n#define OB ('[')\n#define O ('O')\n#define A_HOME ('H')\n#define A_LEFT ('D')\n#define A_END ('K')\n#define A_UP ('A')\n#define A_DOWN ('B')\n#define A_RIGHT ('C')\n#define A_PAGEUP ('V')\n#define A_PAGEDOWN ('U')\n#define A_INSERT ('r')\n#define A_DELETE ('s')\n\nstatic int get_numpad_command(int key) {\n  switch (key) {\n  case '8': return COMMAND_UP;\n  case '4': return COMMAND_LEFT;\n  case '2': return COMMAND_DOWN;\n  case '6': return COMMAND_RIGHT;\n  case '0': return COMMAND_INSERT;\n  case '.': return COMMAND_DELETE;\n  case '9': return COMMAND_PAGEUP;\n  case '3': return COMMAND_PAGEDN;\n  case '7': return COMMAND_HOME;\n  case '1': return COMMAND_END;\n  }\n  return 0;\n}\n\n\nstatic int get_command_for_ansi_key(int key) {\n  switch (key) {\n  case A_UP: return COMMAND_UP;\n  case A_LEFT: return COMMAND_LEFT;\n  case A_DOWN: return COMMAND_DOWN;\n  case A_RIGHT: return COMMAND_RIGHT;\n  case A_INSERT: return COMMAND_INSERT;\n  case A_DELETE: return COMMAND_DELETE;\n  case A_HOME: return COMMAND_HOME;\n  case A_END: return COMMAND_END;\n  case A_PAGEUP: return COMMAND_PAGEUP;\n  case A_PAGEDOWN: return COMMAND_PAGEDN;\n  default: return key;\n  }\n}\n\nint Input::bgetch_event(numlock_status_t numlock_mode) {\n  return bgetch_event(numlock_mode, [](bgetch_timeout_status_t, int) {});\n}\n\nint Input::bgetch_handle_escape(int key) {\n  const auto esc_time1 = time(nullptr);\n  auto esc_time2 = time(nullptr);\n  do {\n    esc_time2 = time(nullptr);\n    if (bkbhitraw()) {\n      key = static_cast<int>(getkey(true));\n      if (key == OB || key == O) {\n        key = static_cast<int>(getkey(true));\n\n        // Check for a second set of brackets\n        if (key == OB || key == O) {\n          key = static_cast<int>(getkey(true));\n        }\n        return get_command_for_ansi_key(key);\n      }\n      return GET_OUT;\n    }\n  } while (difftime(esc_time2, esc_time1) < 1);\n\n  if (difftime(esc_time2, esc_time1) >= 1) { // if no keys followed ESC\n    return GET_OUT;\n  }\n  return key;\n}\n\nint Input::bgetch_handle_key_translation(int key, numlock_status_t numlock_mode) {\n  if (key == CBACKSPACE) {\n    return BACKSPACE;\n  }\n  if (key == CV) {\n    return COMMAND_INSERT;\n  }\n  if (key == RETURN || key == CL) {\n    return EXECUTE;\n  }\n  if ((key == 0 || key == 224) && localIO()->KeyPressed()) {\n    // 224 is E0. See https://msdn.microsoft.com/en-us/library/078sfkak(v=vs.110).aspx\n    return localIO()->GetChar() + 256;\n  }\n  if (numlock_mode == numlock_status_t::NOTNUMBERS) {\n    if (const auto ret = get_numpad_command(key); ret)\n      return ret;\n  }\n  if (key < 127) {\n    return HandleControlKey(static_cast<char>(key), sess(), user());\n  }\n  return key;\n}\n\nint Input::bgetch_event(numlock_status_t numlock_mode, bgetch_callback_fn cb) {\n  return bgetch_event(numlock_mode, std::chrono::hours(24), cb);\n}\n\nint Input::bgetch_event(numlock_status_t numlock_mode, std::chrono::duration<double> idle_time,\n                 bgetch_callback_fn cb) {\n  bus().invoke<UpdateTimeLeft>(UpdateTimeLeft{true});\n  resetnsp();\n  lastchar_pressed();\n  bout.clear_lines_listed();\n\n\n  auto beepyet{false};\n  const auto tv = key_timeout();\n  const auto tv1 = tv - std::chrono::minutes(1);\n  bool once = true;\n\n  while (true) {\n    bus().invoke<CheckForHangupEvent>();\n    if (sess().hangup()) {\n      return 0;\n    }\n    auto dd = steady_clock::now();\n    auto diff = dd - time_lastchar_pressed;\n    if (diff > tv1 && !beepyet) {\n      beepyet = true;\n      bout.outchr(CG);\n      cb(bgetch_timeout_status_t::WARNING, 60);\n    }\n    if (diff > tv) {\n      bout.nl();\n      bout.outstr(\"Call back later when you are there.\\r\\n\");\n      bus().invoke<HangupEvent>();\n      return 0;\n    }\n    if (once && diff > idle_time) {\n      once = false;\n      cb(bgetch_timeout_status_t::IDLE, 0);\n    }\n\n    if (!bkbhitraw() && !localIO()->KeyPressed()) {\n      bus().invoke<GiveupTimeslices>();\n      continue;\n    }\n    if (beepyet) {\n      cb(bgetch_timeout_status_t::CLEAR, 0);\n    }\n\n    if (!sess().incom() || localIO()->KeyPressed()) {\n      // Check for local keys\n      return bgetch_handle_key_translation(localIO()->GetChar(), numlock_mode);\n    }\n    if (bkbhitraw()) {\n      const auto key = static_cast<int>(getkey(true));\n      return key == ESC ? bgetch_handle_escape(key)\n               : bgetch_handle_key_translation(key, numlock_mode);\n    }\n  }\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/checka.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/input.h\"\n\n#include \"core/eventbus.h\"\n#include \"common/common_events.h\"\n#include \"common/output.h\"\n#include \"local_io/keycodes.h\"\n\nnamespace wwiv::common {\n\nusing namespace wwiv::local::io;\n\n/**\n * Checks to see if user aborted whatever he/she was doing.\n * Sets abort to true if control-C/X or Q was pressed.\n * returns the value of abort\n */\nbool Input::checka() {\n  auto ignored_abort = false;\n  auto ignored_next = false;\n  return checka(&ignored_abort, &ignored_next);\n}\n\n/**\n * Checks to see if user aborted whatever he/she was doing.\n * Sets abort to true if control-C/X or Q was pressed.\n * returns the value of abort\n */\nbool Input::checka(bool* abort) {\n  auto ignored_next = false;\n  return checka(abort, &ignored_next);\n}\n\n/**\n * Checks to see if user aborted whatever he/she was doing.\n * Sets next to true if control-N was hit, for zipping past messages quickly.\n * Sets abort to true if control-C/X or Q was pressed.\n * returns the value of abort\n */\nbool Input::checka(bool* abort, bool* next) {\n  if (nsp() == -1) {\n    *abort = true;\n    bout.clear_lines_listed();\n    clearnsp();\n  }\n  while (bkbhit() && !*abort && !sess().hangup()) {\n    core::bus().invoke<CheckForHangupEvent>();\n    const auto ch = bgetch();\n    switch (ch) {\n    case CN:\n      bout.clear_lines_listed();\n      *next = true;\n      break;\n    case CC:\n    case SPACE:\n    case CX:\n    case 'Q':\n    case 'q':\n      bout.clear_lines_listed();\n      *abort = true;\n      break;\n    case 'P':\n    case 'p':\n    case CS:\n      bout.clear_lines_listed();\n      (void) getkey();\n      break;\n    }\n  }\n  return *abort;\n}\n\n} // namespace wwiv::common"
  },
  {
    "path": "common/com.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/com.h\"\n\n#include \"common/common_events.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/eventbus.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n\nusing namespace wwiv::common;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nchar onek(const std::string& allowable, bool auto_mpl) {\n  if (auto_mpl) {\n    bout.mpl(1);\n  }\n  const auto ch = onek_ncr(allowable);\n  bout.nl();\n  return ch;\n}\n\n// Like onek but does not put cursor down a line\n// One key, no carriage return\nchar onek_ncr(const std::string& allowable) {\n  while (true) {\n    wwiv::core::bus().invoke<CheckForHangupEvent>();\n    if (const auto ch = to_upper_case(bin.getkey()); contains(allowable, ch)) {\n      return ch;\n    }\n  }\n}\n"
  },
  {
    "path": "common/com.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_COM_H\n#define INCLUDED_COMMON_COM_H\n\n#include <string>\n\nchar onek(const std::string& allowable, bool auto_mpl = false);\nchar onek_ncr(const std::string& allowable);\n\n#endif"
  },
  {
    "path": "common/common_events.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_EVENTS_H\n#define INCLUDED_COMMON_EVENTS_H\n\n#include \"common/exceptions.h\"\n\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::common {\n\n// The BBS Should attempt to process inter-instance messages.\nstruct ProcessInstanceMessages {};\n\n// The BBS Should attempt to process inter-instance messages.\nstruct ResetProcessingInstanceMessages {};\n\n// The BBS Should attempt to process inter-instance messages.\nstruct PauseProcessingInstanceMessages {};\n\n// The BBS Should check if the user hungup.\nstruct CheckForHangupEvent {};\n\n// Notify the BBS that the user has hungup, forcefully if needed.\nstruct HangupEvent { hangup_type_t t{hangup_type_t::user_logged_off}; };\n\n// Needs to update the topscreen on local IO.\nstruct UpdateTopScreenEvent {};\n\n// Needs to update the time left in the BBS and optionally\n// check for a timeout.\nstruct UpdateTimeLeft {\n  bool check_for_timeout{false};\n};\n\n// Needs to handle a sysop key pressed locally. This is the second key\n// of the two key sequence returned from Win32 for extended input.\nstruct HandleSysopKey {\n  uint8_t key{0};\n};\n\n// Should return time slices to other processes\n// The BBS Should attempt to process inter-instance messages.\nstruct GiveupTimeslices {};\n\n// Display the time on and time left.\nstruct DisplayTimeLeft {};\n\n// Display the instance status in a multi-instance system.\nstruct DisplayMultiInstanceStatus {};\n\n// Display the invisible status for multi-node chat\nstruct ToggleInvisble {};\n\n// Display the available status for multi-node chat\nstruct ToggleAvailable {};\n\n// Needs to update the current menu set.\nstruct UpdateMenuSet {\n  std::string name;\n};\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/common_helper.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WIT`OUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/common_helper.h\"\n\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n\n#include \"gtest/gtest.h\"\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\n\nCommonHelper::CommonHelper(int) {\n  io_.reset(new TestIO());\n  const auto& temp = files_.TempDir();\n  // We want the \"BBS Home\" to be our temp dir.\n  CHECK(chdir(temp.string().c_str()) == 0);\n\n  CHECK(files_.Mkdir(\"data\"));\n  CHECK(files_.Mkdir(\"gfiles\"));\n  CHECK(files_.Mkdir(\"en\"));\n  CHECK(files_.Mkdir(\"en/gfiles\"));\n\n  dir_data_ = files_.DirName(\"data\");\n  dir_gfiles_ = files_.DirName(\"gfiles\");\n  dir_menus_ = files_.DirName(\"menus\");\n  current_menu_dir_ = files_.DirName(\"menus/wwiv\");\n  dir_msgs_ = files_.DirName(\"msgs\");\n  dir_dloads_ = files_.DirName(\"dloads\");\n#ifdef _WIN32\n  dir_gfiles_ = File::FixPathSeparators(dir_gfiles_);\n  current_menu_dir_ = File::FixPathSeparators(current_menu_dir_);\n#endif  // _WIN32\n\n  config_ = std::make_unique<Config>(temp);\n  // Grab a raw pointer before moving it to Application\n  config_->set_initialized_for_test(true);\n  config_->set_paths_for_test(dir_data_, dir_msgs_, dir_gfiles_, dir_menus_, dir_dloads_,\n                              dir_data_);\n}\n\nCommonHelper::CommonHelper() : CommonHelper(42) {\n  // Use our own local IO class that will capture the output.\n  const auto& temp = files_.TempDir();\n  common_session_context_ = std::make_unique<wwiv::common::SessionContext>(io_->local_io(), temp);\n  context_ = std::make_unique<TestContext>(*this);\n}\n\nvoid CommonHelper::SetUp() {\n\n  sess().dirs().current_menu_directory(current_menu_dir_);\n  user()->clear_flag(User::pauseOnPage);\n  sess().num_screen_lines(std::numeric_limits<int>::max());\n\n  // Create a reasonable default user.  Some tests (bputch/bputs tests)\n  // Require a properly constructed user.\n  User::CreateNewUserRecord(user(), 50, 20, 0, 0.1234f, \n  { 7, 11, 14, 13, 31, 10, 12, 9, 5, 3 }, { 7, 15, 15, 15, 112, 15, 15, 7, 7, 7 });\n  user()->set_flag(User::flag_ansi);\n  user()->set_flag(User::status_color);\n\n  // Reset the color attribute to 7 between tests.\n  bout.curatr(7);\n  // We need this true so our outchr tests can capture remote.\n  sess().outcom(true);\n  sess().ok_modem_stuff(true);\n}\n\nConfig& CommonHelper::config() const {\n  return *config_;\n}\n\nwwiv::common::SessionContext& CommonHelper::sess() {\n  CHECK(common_session_context_.get());\n  return *common_session_context_;\n}\n\n\nwwiv::common::Context& CommonHelper::context() {\n  return *context_;\n}\n\nTestIO::TestIO() {\n  local_io_ = new TestLocalIO(&this->captured_);\n  remote_io_ = new TestRemoteIO(&this->rcaptured_);\n}\n\nstd::string TestIO::captured() {\n  auto captured(captured_);\n  captured_.clear();\n  return captured;\n}\n\nstd::string TestIO::rcaptured() {\n  auto captured(rcaptured_);\n  rcaptured_.clear();\n  return captured;\n}\n\nTestLocalIO::TestLocalIO(std::string* captured) : wwiv::local::io::LocalIO(), captured_(captured) {}\n\nvoid TestLocalIO::Putch(unsigned char ch) {\n  captured_->push_back(ch);\n}\n\nTestRemoteIO::TestRemoteIO(std::string* captured) : RemoteIO(), captured_(captured) {}\n\nunsigned int TestRemoteIO::put(unsigned char ch) {\n  captured_->push_back(ch);\n  return 1;\n}\n\nunsigned int TestRemoteIO::write(const char *buffer, unsigned int count, bool) {\n  captured_->append(std::string(buffer, count));\n  return count;\n}\n\nTestContext::TestContext(CommonHelper& helper)\n    : helper_(helper), sess_ctx_(helper_.io()->local_io()), chains_(helper.config()) {}\n\n"
  },
  {
    "path": "common/common_helper.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_TEST_COMMON_HELPER_H\n#define INCLUDED_COMMON_TEST_COMMON_HELPER_H\n\n#include \"common/context.h\"\n#include \"common/remote_io.h\"\n#include \"core/test/file_helper.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include <memory>\n#include <string>\n\nclass TestIO;\nclass TestContext;\n\n\n/*\n * \n * Test helper for using code with heavy BBS dependencies.\n * \n * To use, add an instance as a field in the test class.  Then invoke.\n * BbsHelper::SetUp before use. typically from Test::SetUp.\n */\nclass CommonHelper {\npublic:\n  explicit CommonHelper(int instance_num);\n  CommonHelper();\n  virtual ~CommonHelper() = default;\n  virtual void SetUp();\n  [[nodiscard]] virtual wwiv::sdk::Config& config() const;\n  [[nodiscard]] virtual wwiv::sdk::User* user() { return &common_user; }\n  [[nodiscard]] TestIO* io() const { return io_.get(); }\n  [[nodiscard]] virtual wwiv::common::SessionContext& sess();\n  [[nodiscard]] virtual wwiv::common::Context& context();\n\n  // Accessors for various directories\n  wwiv::core::test::FileHelper& files() { return files_; }\n  [[nodiscard]] const std::string& data() const { return dir_data_; }\n  [[nodiscard]] const std::string& gfiles() const { return dir_gfiles_; }\n  [[nodiscard]] const std::string& menus() const { return dir_menus_; }\n\n  wwiv::core::test::FileHelper files_;\n  std::string dir_data_;\n  std::string dir_gfiles_;\n  std::string dir_menus_;\n  std::string current_menu_dir_;\n  std::string dir_dloads_;\n  std::string dir_msgs_;\n  std::unique_ptr<TestIO> io_;\n\nprotected:\n  std::unique_ptr<wwiv::sdk::Config> config_;\n\nprivate:\n  std::unique_ptr<wwiv::common::SessionContext> common_session_context_;\n  wwiv::sdk::User common_user{};\n  std::unique_ptr<TestContext> context_;\n};\n\n\nclass TestIO {\npublic:\n  TestIO();\n  void Clear() { captured_.clear(); rcaptured_.clear(); }\n  std::string captured();\n  std::string rcaptured();\n  [[nodiscard]] wwiv::local::io::LocalIO* local_io() const { return local_io_; }\n  [[nodiscard]] wwiv::common::RemoteIO* remote_io() const { return remote_io_; }\n\nprivate:\n  wwiv::local::io::LocalIO* local_io_;\n  wwiv::common::RemoteIO* remote_io_;\n  std::string captured_;\n  std::string rcaptured_;\n};\n\nclass TestLocalIO : public wwiv::local::io::LocalIO {\npublic:\n  explicit TestLocalIO(std::string* captured);\n  void Putch(unsigned char ch) override;\n  void GotoXY(int, int) override {}\n  [[nodiscard]] int WhereX() const noexcept override { return 0; }\n  [[nodiscard]] int WhereY() const noexcept override { return 0; }\n  void Lf() override {}\n  void Cr() override {}\n  void Cls() override {}\n  void Backspace() override {}\n  void PutchRaw(unsigned char) override {}\n  void Puts(const std::string& ) override {}\n  void PutsXY(int, int, const std::string&) override {}\n  void PutsXYA(int, int, int, const std::string&) override {}\n  void FastPuts(const std::string&) override {}\n  void set_protect(int) override {}\n  void savescreen() override {}\n  void restorescreen() override {}\n  bool KeyPressed() override { return false; }\n  [[nodiscard]] unsigned char GetChar() override { return static_cast<unsigned char>(getchar()); }\n  void MakeLocalWindow(int, int, int, int) override {}\n  void SetCursor(int) override {}\n  void ClrEol() override {}\n  void WriteScreenBuffer(const char *) override {}\n  [[nodiscard]] int GetDefaultScreenBottom() const noexcept override { return 25; }\n  void EditLine(char*, int, wwiv::local::io::AllowedKeys, wwiv::local::io::EditlineResult*,\n                const char*) override {}\n  void UpdateNativeTitleBar(const std::string&, int) override {}\n\n  std::string* captured_;\n};\n\nclass TestRemoteIO final : public wwiv::common::RemoteIO {\npublic:\n  explicit TestRemoteIO(std::string* captured);\n  ~TestRemoteIO() override = default;\n\n  bool open() override { return true; }\n  void close(bool) override {}\n  unsigned char getW() override { return 0; }\n  bool disconnect() override { return true; }\n  void purgeIn() override {}\n  unsigned int put(unsigned char ch) override;\n  unsigned int write(const char *buffer, unsigned int count, bool bNoTranslation = false) override;\n  unsigned int read(char *, unsigned int) override { return 0; }\n  bool connected() override { return true; }\n  bool incoming() override { return false; }\n  [[nodiscard]] unsigned int GetHandle() const override { return 0; }\n\nprivate:\n  std::string* captured_;\n};\n\nclass TestContext final : public wwiv::common::Context {\npublic:\n  explicit TestContext(CommonHelper& helper);\n  [[nodiscard]] wwiv::sdk::Config& config() override { return helper_.config(); }\n  [[nodiscard]] wwiv::sdk::User& u() override { return *helper_.user(); }\n  wwiv::common::SessionContext& session_context() override { return sess_ctx_; }\n  [[nodiscard]] bool mci_enabled() const override { return true; }\n  [[nodiscard]] const std::vector<editorrec>& editors() const { return editors_; }\n  [[nodiscard]] const wwiv::sdk::Chains& chains() const { return chains_; }\n\n  CommonHelper& helper_;\n  wwiv::common::SessionContext sess_ctx_;\n  std::vector<editorrec> editors_;\n  wwiv::sdk::Chains chains_;\n};\n\n#endif\n"
  },
  {
    "path": "common/common_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5.x                            */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/log.h\"\n\nint main(int argc, char* argv[]) {\n  try {\n    testing::InitGoogleTest(&argc, argv);\n    wwiv::core::LoggerConfig logger_config{};\n    logger_config.register_file_destinations = false;\n    logger_config.log_startup = false;\n    wwiv::core::Logger::Init(argc, argv, logger_config);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what() << std::endl;\n  }\n  return 1;\n} "
  },
  {
    "path": "common/context.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/context.h\"\n\n#include \"common/common_events.h\"\n#include \"core/eventbus.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/config.h\"\n#include \"sdk/menus/menu_set.h\"\n#include <chrono>\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::common {\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::sdk::menus;\nusing namespace wwiv::strings;\nusing namespace std::chrono;\n\nDirs::Dirs(const std::filesystem::path& bbsdir)\n    : Dirs(FilePath(bbsdir, \"temp\"), FilePath(bbsdir, \"batch\"),\n           FilePath(bbsdir, \"batch\"), FilePath(bbsdir, \"gfiles\"),\n           FilePath(bbsdir, \"scratch\")) {}\n\nstd::filesystem::path Dirs::current_menu_gfiles_directory() const noexcept {\n  return FilePath(current_menu_directory_, \"gfiles\");\n}\n\nstd::filesystem::path Dirs::current_menu_script_directory() const noexcept {\n  return FilePath(current_menu_directory_, \"scripts\");\n}\n\nSessionContext::SessionContext(LocalIO* io)\n    : SessionContext(io, File::current_directory()) {\n  VLOG(4) << \"SessionContext::SessionContext\";\n}\n\nSessionContext::SessionContext(LocalIO* io, const std::filesystem::path& root_directory)\n    : irt_{}, io_(io), dirs_(root_directory),\n      current_menu_set_(std::make_unique<MenuSet56>()) {}\n\n// This has to be here since ~MenuSet56 can be found here.\nSessionContext::~SessionContext() = default;\n\nvoid SessionContext::InitalizeContext(const wwiv::sdk::Config& c) {\n  const auto qscan_length = c.qscn_len() / sizeof(uint32_t);\n  qscan_ = std::make_unique<uint32_t[]>(qscan_length);\n  qsc = qscan_.get();\n  qsc_n = qsc + 1;\n  qsc_q = qsc_n + (c.max_dirs() + 31) / 32;\n  qsc_p = qsc_q + (c.max_subs() + 31) / 32;\n  ResetQScanPointers(c);\n}\n\nvoid SessionContext::ResetQScanPointers(const wwiv::sdk::Config& c) {\n  memset(qsc, 0, c.qscn_len());\n  *qsc = 999;\n  memset(qsc_n, 0xff, ((c.max_dirs() + 31) / 32) * 4);\n  memset(qsc_q, 0xff, ((c.max_subs() + 31) / 32) * 4);\n}\n\nvoid SessionContext::reset() {\n  SetCurrentReadMessageArea(-1);\n  set_current_user_sub_conf_num(0);\n  set_current_user_dir_conf_num(0);\n  SetUserOnline(false);\n  SetTimeOnlineLimited(false);\n\n  chat_reason(\"\");\n  num_screen_lines(io_->GetDefaultScreenBottom() + 1);\n  hangup(false);\n  chatting(chatting_t::none);\n  using_modem(false);\n  clear_irt();\n  outcom(false);\n  incom(false);\n  okmacro(true);\n}\n\nvoid SessionContext::reset_local_io(LocalIO* io) { \n  DCHECK_NE(io, nullptr);\n  io_ = io; \n}\n\nvoid SessionContext::irt(const std::string& irt) { \n  to_char_array(irt_, irt); \n}\n\nvoid SessionContext::SetLogonTime() { system_logon_time_ = std::chrono::system_clock::now(); }\n\nseconds SessionContext::duration_used_this_session() const {\n  return duration_cast<seconds>(std::chrono::system_clock::now() - system_logon_time_);\n}\n\nint SessionContext::bps() const noexcept {\n  const auto f = file_bps();\n  return f > 0 ? f : system_bps();\n}\n\nconst MenuSet56& SessionContext::current_menu_set() const noexcept {\n  /* To listen to this use code like\n  bus().add_handler<UpdateMenuSet>(\n      [this](const UpdateMenuSet& u) {\n        current_menu_set(u.name);\n      });\n   */\n  DCHECK(current_menu_set_.get());\n  return *current_menu_set_;\n}\n\nvoid SessionContext::load_menu_set(const std::filesystem::path& menusdir,\n                                   const std::string& menuset) {\n  if (current_menu_set_->menu_set.name != menuset) {\n    current_menu_set_ = std::make_unique<MenuSet56>(FilePath(menusdir, menuset));\n    bus().invoke<UpdateMenuSet>(UpdateMenuSet{menuset});\n    dirs().current_menu_directory(current_menu_set_->menuset_dir());\n  }\n}\n\nint SessionContext::debug_wwivbasic_port() const { return debug_wwivbasic_port_; }\nbool SessionContext::debug_wwivbasic() const { return debug_wwivbasic_port_ > 0; }\nvoid SessionContext::debug_wwivbasic_port(int d) { debug_wwivbasic_port_ = d; }\n\nstd::optional<sdk::value::Value> MapValueProvider::value(const std::string& name) const {\n  if (const auto& iter = map_.find(name); iter != std::end(map_)) {\n    return sdk::value::Value(iter->second);\n  }\n  return std::nullopt;\n}\n\nconst std::map<std::string, std::string>& MapValueProvider::map() const {\n  return map_;\n}\n\nbool Context::add_context_variable(const std::string& prefix, std::map<std::string, std::string> map) {\n  value_providers_.emplace_back(std::make_unique<MapValueProvider>(prefix, std::move(map)));\n  return true;\n}\n\nbool Context::remove_context_variable(const std::string& prefix) {\n  for (auto it = std::begin(value_providers_); it != std::end(value_providers_); ++it) {\n    if (prefix == it->get()->prefix()) {\n      value_providers_.erase(it);\n      return true;\n    }\n  }\n  return false;\n}\n\nbool Context::clear_context_variables() {\n  value_providers_.clear();\n  return_values_.clear();\n  return true;\n}\n\n\n\n}\n"
  },
  {
    "path": "common/context.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_CONTEXT_H\n#define INCLUDED_COMMON_CONTEXT_H\n\n#include \"core/wwivport.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include \"sdk/value/valueprovider.h\"\n#include \"sdk/files/dirs.h\"\n\n#include <cstdint>\n#include <filesystem>\n#include <memory>\n#include <string>\n#include <utility>\n\nnamespace wwiv {\nnamespace sdk {\nclass Chains;\n\nnamespace menus {\nclass MenuSet56;\n}\n}\n}\n\nnamespace wwiv::local::io {\nclass LocalIO;\n}\n\nnamespace wwiv::common {\n\nclass Dirs {\npublic:\n  explicit Dirs(const std::filesystem::path& bbsdir);\n  Dirs(const std::filesystem::path& temp, const std::filesystem::path& batch,\n       const std::filesystem::path& qwk, const std::filesystem::path& gfiles,\n       const std::filesystem::path& scratch)\n      : temp_directory_(temp), batch_directory_(batch), qwk_directory_(qwk),\n        gfiles_directory_(gfiles), scratch_directory_(scratch) {}\n\n  [[nodiscard]] const std::filesystem::path& temp_directory() const noexcept { return temp_directory_; }\n  void temp_directory(const std::string& d) { temp_directory_ = d; }\n\n  [[nodiscard]] const std::filesystem::path& batch_directory() const noexcept { return batch_directory_; }\n  void batch_directory(const std::string& d) { batch_directory_ = d; }\n\n  [[nodiscard]] const std::filesystem::path& scratch_directory() const noexcept { return scratch_directory_; }\n\n  /**\n   * Used instead of QWK_DIRECTORY.  Today it is the same as batch but wanted to\n   * leave it open for changing in the future.\n   */\n  [[nodiscard]] const std::filesystem::path& qwk_directory() const noexcept { return qwk_directory_; }\n  void qwk_directory(const std::string& d) { qwk_directory_ = d; }\n\n  [[nodiscard]] const std::filesystem::path& gfiles_directory() const noexcept { return gfiles_directory_; }\n  void gfiles_directory(const std::string& d) { gfiles_directory_ = d; }\n\n  [[nodiscard]] std::filesystem::path current_menu_directory() const noexcept {\n    return current_menu_directory_;\n  }\n  void current_menu_directory(const std::filesystem::path& l) {\n    current_menu_directory_ = l;\n  }\n\n  /**\n   * Current directory for this menus set's gfiles dir. i.e. where menus specific\n   * display files reside.\n   */\n  [[nodiscard]] std::filesystem::path current_menu_gfiles_directory() const noexcept;\n\n  /**\n   * Current directory for this menus set's script dir. i.e. where menus specific\n   * script files reside.\n   */\n  [[nodiscard]] std::filesystem::path current_menu_script_directory() const noexcept;\n\nprivate:\n  std::filesystem::path temp_directory_;\n  std::filesystem::path batch_directory_;\n  std::filesystem::path qwk_directory_;\n  std::filesystem::path current_menu_directory_;\n  std::filesystem::path gfiles_directory_;\n  std::filesystem::path scratch_directory_;\n};\n\nenum class chatting_t { none, one_way, two_way };\n\nclass SessionContext final {\npublic:\n  explicit SessionContext(wwiv::local::io::LocalIO* io);\n  SessionContext(wwiv::local::io::LocalIO* io, const std::filesystem::path& root_directory);\n  ~SessionContext();\n\n  /**\n   * Initializes an empty context, called after Config.dat\n   * has been read and processed.\n   */\n  void InitalizeContext(const sdk::Config& config);\n\n  /**\n   * Clears the qscan pointers.\n   */\n  void ResetQScanPointers(const wwiv::sdk::Config& config);\n\n  /**\n   * Resets the application level context.\n   */\n  void reset();\n\n  /** Resets the local IO pointer */\n  void reset_local_io(wwiv::local::io::LocalIO* io);\n\n  [[nodiscard]] bool ok_modem_stuff() const noexcept { return ok_modem_stuff_; }\n  void ok_modem_stuff(bool o) { ok_modem_stuff_ = o; }\n\n  [[nodiscard]] int instance_number() const { return instance_number_; }\n  void instance_number(int i) { instance_number_ = i; }\n\n  [[nodiscard]] bool debug_wwivbasic() const;\n  [[nodiscard]] int debug_wwivbasic_port() const;\n  void debug_wwivbasic_port(int d);\n\n  [[nodiscard]] bool incom() const noexcept { return incom_; }\n  void incom(bool i) { incom_ = i; }\n  [[nodiscard]] bool outcom() const noexcept { return outcom_; }\n  void outcom(bool o) { outcom_ = o; }\n\n  [[nodiscard]] bool okmacro() const noexcept { return okmacro_; }\n  void okmacro(bool o) { okmacro_ = o; }\n\n  [[nodiscard]] bool forcescansub() const noexcept { return forcescansub_; }\n  void forcescansub(bool g) { forcescansub_ = g; }\n\n  [[nodiscard]] daten_t nscandate() const noexcept { return nscandate_; }\n  void nscandate(daten_t d) { nscandate_ = d; }\n\n  [[nodiscard]] bool disable_conf() const noexcept { return disable_conf_; }\n  void disable_conf(bool b) { disable_conf_ = b; }\n  [[nodiscard]] bool disable_pause() const noexcept { return disable_pause_; }\n  void disable_pause(bool b) { disable_pause_ = b; }\n  [[nodiscard]] bool scanned_files() const noexcept { return scanned_files_; }\n  void scanned_files(bool b) { scanned_files_ = b; }\n  \n  // qsc is the qscan pointer. The 1st 4 bytes are the sysop sub number.\n  uint32_t* qsc{nullptr};\n  // A bitfield controlling if the directory should be included in the new scan.\n  uint32_t* qsc_n{nullptr};\n  // A bitfield controlling if the sub should be included in the new scan.\n  uint32_t* qsc_q{nullptr};\n  // Array of 32-bit unsigned integers for the qscan pointer value\n  // aka high message read pointer) for each sub.\n  uint32_t* qsc_p{nullptr};\n\n  [[nodiscard]] std::string irt() const { return std::string(irt_); }\n  void irt(const std::string& irt);\n  void clear_irt() { irt_[0] = '\\0'; }\n\n  [[nodiscard]] bool hangup() const noexcept { return hangup_; }\n  void hangup(bool h) { hangup_ = h; }\n\n  [[nodiscard]] int num_screen_lines() const noexcept { return num_screen_lines_; }\n  void num_screen_lines(int n) { num_screen_lines_ = n; }\n\n  [[nodiscard]] chatting_t chatting() const noexcept { return chatting_; }\n  void chatting(chatting_t n) { chatting_ = n; }\n\n  [[nodiscard]] bool using_modem() const noexcept { return using_modem_; }\n  void using_modem(bool n) { using_modem_ = n; }\n\n  void chat_reason(const std::string& chat_reason) {\n    chat_reason_ = chat_reason;\n    chatcall_ = !chat_reason.empty();\n  }\n\n  [[nodiscard]] std::string chat_reason() const noexcept { return chat_reason_; }\n\n  /** Is the chat call alert (user wanted to chat with the sysop. enabled? */\n  [[nodiscard]] bool chatcall() const { return chatcall_; }\n  /** Clears the chat call alert (user wanted to chat with the sysop. enabled? */\n  void clear_chatcall() { chatcall_ = false; }\n\n  [[nodiscard]] bool chatline() const { return chatline_; }\n  void chatline(bool n) { chatline_ = n; }\n\n  [[nodiscard]] bool in_chatroom() const { return in_chatroom_; }\n  void in_chatroom(bool n) { in_chatroom_ = n; }\n\n  // Note: This may be set to -1 to mean no area.\n  [[nodiscard]] int GetCurrentReadMessageArea() const { return current_read_message_area; }\n  void SetCurrentReadMessageArea(int n) { current_read_message_area = n; }\n\n  [[nodiscard]] uint16_t current_user_sub_conf_num() const { return current_conf_msgarea_; }\n  void set_current_user_sub_conf_num(int n) { current_conf_msgarea_ = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t current_user_dir_conf_num() const { return current_conf_filearea_; }\n  void set_current_user_dir_conf_num(int n) { current_conf_filearea_ = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] bool IsUserOnline() const { return user_online_; }\n  void SetUserOnline(bool b) { user_online_ = b; }\n\n  [[nodiscard]] bool IsTimeOnlineLimited() const { return time_limited_; }\n  void SetTimeOnlineLimited(bool b) { time_limited_ = b; }\n\n  // Sets the time that the user has logged in.\n  void SetLogonTime();\n\n  // Returns the time that the user has logged in.  If the user has not yet\n  // logged in, return the time the bbs started.\n  [[nodiscard]] std::chrono::system_clock::time_point system_logon_time() const {\n    return system_logon_time_;\n  }\n\n  // Returns the duration used this bbs session.\n  [[nodiscard]] std::chrono::seconds duration_used_this_session() const;\n\n  [[nodiscard]] const Dirs& dirs() const noexcept { return dirs_; }\n  [[nodiscard]] Dirs& dirs() { return dirs_; }\n  void dirs(Dirs d) { dirs_ = std::move(d); }\n\n  [[nodiscard]] const wwiv::sdk::files::directory_t& current_dir() const { return current_dir_; }\n  void current_dir(const wwiv::sdk::files::directory_t& dir) { current_dir_ = dir; }\n\n  void effective_sl(int n) { effective_sl_ = n; }\n  [[nodiscard]] int effective_sl() const { return effective_sl_; }\n\n  void current_language(const std::string& l) { current_lang_name_ = l; }\n  [[nodiscard]] std::string current_language() const noexcept { return current_lang_name_; }\n\n  void user_num(int usernum) { user_num_ = usernum; }\n  [[nodiscard]] int user_num() const noexcept { return user_num_; };\n\n  /**\n   * Sets the effective BPS to use for the system.  This ay be overridden by\n   * on a per file basis.\n   */\n  void set_system_bps(int bps) { system_bps_ = bps; }\n\n  /**\n   * The effective BPS to use for the system.  This ay be overridden by on a\n   * per file basis.\n   */\n  [[nodiscard]] int system_bps() const noexcept { return system_bps_; }\n\n  /**\n   * Sets the effective BPS to use for the current file.  This will be reset\n   * after the file is complete.\n   */\n  void set_file_bps(int bps) { file_bps_ = bps; }\n\n  /**\n   * The effective BPS to use for the current file.  This will be reset\n   * after the file is complete.\n   */\n  [[nodiscard]] int file_bps() const noexcept { return file_bps_; }\n\n  /**\n   * The effective BPS to use to display files.\n   *\n   * If the current file sets an explicit BPS then we'll use that, otherwise\n   * we'll use the system BPS.\n   */\n  [[nodiscard]] int bps() const noexcept;\n\n  /**\n   * The current user's menus set\n   */\n  [[nodiscard]] const wwiv::sdk::menus::MenuSet56& current_menu_set() const noexcept;\n\n  void load_menu_set(const std::filesystem::path& menusdir, const std::string& menuset);\n\n\n  // TODO(rushfan): Move this to private later\n  char irt_[81];\n\nprivate:\n  wwiv::local::io::LocalIO* io_;\n  std::unique_ptr<uint32_t[]> qscan_;\n\n  bool ok_modem_stuff_{false};\n  int instance_number_{-1};\n  bool incom_{false};\n  bool outcom_{false};\n  bool okmacro_{true};\n  bool forcescansub_{false};\n  daten_t nscandate_{0};\n  bool disable_conf_{false};\n  bool disable_pause_{false};\n  bool scanned_files_{false};\n  bool hangup_{false};\n  int num_screen_lines_{25};\n  chatting_t chatting_{chatting_t::none};\n  bool using_modem_{false};\n  bool chatcall_{false};\n  std::string chat_reason_;\n  bool chatline_{false};\n  bool in_chatroom_{false};\n\n  int current_read_message_area{0};\n  uint16_t current_conf_msgarea_{0};\n  uint16_t current_conf_filearea_{0};\n  bool user_online_{false};\n  bool time_limited_{false};\n  std::chrono::system_clock::time_point system_logon_time_;\n  Dirs dirs_;\n  sdk::files::directory_t current_dir_{};\n  int effective_sl_{0};\n  std::string current_lang_name_{\"English\"};\n  int user_num_{-1};\n\n  int file_bps_{0};\n  int system_bps_{0};\n  std::unique_ptr<wwiv::sdk::menus::MenuSet56> current_menu_set_;\n  int debug_wwivbasic_port_{0};\n};\n\nclass MapValueProvider : public sdk::value::ValueProvider {\npublic:\n  explicit MapValueProvider(std::string prefix, std::map<std::string, std::string> map)\n      : ValueProvider(std::move(prefix)), map_(std::move(map)) {}\n\n  ~MapValueProvider() override = default;\n\n  /** \n   * Optionally gets the attribute for this object.  name should just be\n   * the 'attribute' and not the full object.attribute name. *\n   */\n  [[nodiscard]] std::optional<sdk::value::Value> value(const std::string& name) const override;\n\n  [[nodiscard]] const std::map<std::string, std::string>& map() const;\n\nprivate:\n  const std::map<std::string, std::string> map_;\n};\n\n\n/**\n * WWIV Full Context.\n *\n * This is a smaller context class than what the Application class contains,\n * and should be enough to run displays and most activities outside of the BBS.\n *\n * This holds other sub-contexts (like SessionContext), as well as the current\n * User and Config used by the BBS.\n */\nclass Context {\npublic:\n  virtual ~Context() = default;\n  [[nodiscard]] virtual sdk::Config& config() = 0;\n  [[nodiscard]] virtual sdk::User& u() = 0;\n  [[nodiscard]] virtual SessionContext& session_context() = 0;\n  [[nodiscard]] virtual bool mci_enabled() const = 0;\n  [[nodiscard]] virtual const std::vector<editorrec>& editors() const = 0;\n  [[nodiscard]] virtual const sdk::Chains& chains() const = 0;\n\n\n  /**\n   * Adds a set of context variables for use in pipe expressions.  An example for the current\n   * message being read may be:\n   * add_context_variable(\"msg\", { { \"num\", \"100\" }, { \"title\", \"A message on nothing\" } });\n   */\n  bool add_context_variable(const std::string& prefix, std::map<std::string, std::string> map);\n  bool remove_context_variable(const std::string& prefix);\n  bool clear_context_variables();\n  [[nodiscard]] const std::vector<std::unique_ptr<MapValueProvider>>& value_providers() const { return value_providers_; }\n\n  /**\n   * Return values to be returned from scripts to the BBS.\n   * example: num_header_lines is returned from the full screen reader and editor.\n   */\n  [[nodiscard]] std::map<std::string, std::string>& return_values() { return return_values_; }\n\nprivate:\n  std::vector<std::unique_ptr<MapValueProvider>> value_providers_;\n  std::map<std::string, std::string> return_values_;\n};\n\n} // namespace wwiv::common\n\n#endif // INCLUDED_COMMON_CONTEXT_H"
  },
  {
    "path": "common/datetime.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"common/datetime.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/wconstants.h\"\n#include <string>\n\nnamespace wwiv::common {\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\n\n//\n// This kludge will get us through 2019 and should not interfere anywhere\n// else.\n//\n\nvoid ToggleScrollLockKey() {\n#if defined(_WIN32)\n  // Simulate a key press\n  keybd_event(VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);\n  // Simulate a key release\n  keybd_event(VK_SCROLL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);\n#endif // _WIN32\n}\n\n/* This function returns the status of scoll lock.  If scroll lock is active\n * (ie, the user has hit scroll lock + the light is lit if there is a\n * scroll lock LED), the sysop is assumed to be available.\n */\nbool sysop1() {\n#if defined(_WIN32)\n  return (GetKeyState(VK_SCROLL) & 0x1);\n#else\n  return false;\n#endif\n}\n\nbool isleap(int year) { return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); }\n\n/*\n * Returns current time as string formatted like HH:MM:SS (01:13:00).\n */\nstd::string ctim(long d) {\n  if (d < 0) {\n    d += SECONDS_PER_DAY;\n  }\n  const auto hour = (d / SECONDS_PER_HOUR);\n  d -= (hour * SECONDS_PER_HOUR);\n  const auto minute = static_cast<long>(d / MINUTES_PER_HOUR);\n  d -= (minute * MINUTES_PER_HOUR);\n  const auto second = static_cast<long>(d);\n  return fmt::sprintf(\"%2.2ld:%2.2ld:%2.2ld\", hour, minute, second);\n}\n\nstd::string ctim(std::chrono::duration<double> d) {\n  return ctim(static_cast<long>(std::chrono::duration_cast<seconds>(d).count()));\n}\n\nsystem_clock::duration duration_since_midnight(system_clock::time_point now) {\n  auto tnow = system_clock::to_time_t(now);\n  tm* date = std::localtime(&tnow);\n  date->tm_hour = 0;\n  date->tm_min = 0;\n  date->tm_sec = 0;\n  const auto midnight = system_clock::from_time_t(std::mktime(date));\n\n  return now - midnight;\n}\n\nsystem_clock::time_point minutes_after_midnight(int minutes) {\n  const auto tnow = time_t_now();\n  auto* date = std::localtime(&tnow);\n  date->tm_hour = minutes / 60;\n  date->tm_min = minutes % 60;\n  date->tm_sec = 0;\n\n  return system_clock::from_time_t(std::mktime(date));\n}\n\nint minutes_since_midnight() {\n  const auto d = duration_since_midnight(system_clock::now());\n  return duration_cast<minutes>(d).count();\n}\n\n} // namespace wwiv::common"
  },
  {
    "path": "common/datetime.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_DATETIME_H\n#define INCLUDED_COMMON_DATETIME_H\n\n#include \"core/datetime.h\"\n#include <chrono>\n#include <ctime>\n#include <string>\n\nnamespace wwiv::common {\n\nbool isleap(int nYear);\nstd::string ctim(long d);\nstd::string ctim(std::chrono::duration<double> d);\n\n/**\n * Returns a duration representing the duration since midnight of the current day.\n */\nstd::chrono::system_clock::duration\nduration_since_midnight(std::chrono::system_clock::time_point now);\n\n/**\n * Returns a time_point representing minutes past midnight in the current day.\n */\nstd::chrono::system_clock::time_point minutes_after_midnight(int minutes);\n/**\n * Returns an integer for the number of minutes since midnight.\n * N.B. This is the same as duration_cast<minutes>(duration_since_midnight(now())).count();\n */\nint minutes_since_midnight();\n\n// This really shouldn't be here.\nbool sysop1();\nvoid ToggleScrollLockKey();\n\n} // namespace wwiv::common \n\n#endif\n"
  },
  {
    "path": "common/exceptions.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_EXCEPTIONS_H\n#define INCLUDED_COMMON_EXCEPTIONS_H\n\n#include \"core/strings.h\"\n#include <stdexcept>\n\nnamespace wwiv::common {\n\nenum class hangup_type_t { user_logged_off, user_disconnected, sysop_forced };\n\nclass hangup_error final : public std::runtime_error {\npublic:\n  hangup_error(hangup_type_t t, const std::string& username)\n   : std::runtime_error(wwiv::strings::StrCat(username, \" hung up.\")), t_(t) {}\n\n  [[nodiscard]] hangup_type_t hangup_type() const noexcept { return t_; }\n\n  hangup_type_t t_;\n};\n\n}  // namespace wwiv::common\n\n\n#endif\n"
  },
  {
    "path": "common/full_screen.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2016-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/full_screen.h\"\n\n#include \"common/common_events.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/eventbus.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nFullScreenView::FullScreenView(Output& output, Input& input, int numlines, int swidth, int slength)\n    : bin_(input), bout_(output), num_header_lines_(numlines), screen_width_(swidth),\n      screen_length_(slength) {\n  message_height_ = screen_length_ - num_header_lines_ - 2 - 1;\n  lines_start_ = num_header_lines_ + 2;\n  lines_end_ = lines_start_ + message_height_;\n  command_line_ = screen_length_;\n  \n  // Save the topdata.\n  saved_topdata = output.localIO()->topdata();\n  if (output.localIO()->topdata() != LocalIO::topdata_t::none) {\n    output.localIO()->topdata(LocalIO::topdata_t::none);\n    bus().invoke<UpdateTopScreenEvent>();\n  }\n}\n\nFullScreenView::~FullScreenView() {\n  bout_.localIO()->topdata(saved_topdata);\n  bus().invoke<UpdateTopScreenEvent>();\n}\n\nvoid FullScreenView::PrintTimeoutWarning(int) {\n  bout_.goxy(1, command_line_);\n  bout_.outstr(\"|12Press space if you are still there.\");\n  bout_.clreol();\n}\n\nvoid FullScreenView::ClearCommandLine() {\n  bout_.goxy(1, command_line_);\n  bout_.clreol();\n  bout_.goxy(1, command_line_);\n}\n\nvoid FullScreenView::PutsCommandLine(const std::string& text) {\n  bout_.goxy(1, command_line_);\n  bout_.outstr(text);\n  bout_.clreol();\n}\n\nvoid FullScreenView::ClearMessageArea() {\n  for (int y = lines_start_; y < lines_end_; y++) {\n    bout_.goxy(1, y);\n    bout_.clreol();\n  }\n  bout_.goxy(1, lines_start_);\n}\n\nvoid FullScreenView::DrawTopBar() {\n  bout_.goxy(1, num_header_lines_ + 1);\n  bout_.print(\"|#7{:c}{}{:c}\", static_cast<unsigned char>(198),\n              std::string(std::max<int>(40, screen_width_) - 2, static_cast<unsigned char>(205)),\n              static_cast<unsigned char>(181));\n}\n\nvoid FullScreenView::DrawBottomBar(const std::string& text) {\n  const auto y = screen_length_ - 1;\n  bout_.goxy(1, y);\n  const auto saved_color = bout.curatr();\n  auto at_exit = finally([=] { bout.setc(saved_color); });\n\n  bout_.print(\"|#7{:c}{}{:c}\", static_cast<unsigned char>(198),\n              std::string(screen_width_ - 2, static_cast<unsigned char>(205)),\n              static_cast<unsigned char>(181));\n\n  if (text.empty()) {\n    return;\n  }\n\n  const auto x = screen_width_ - 10 - ssize(text);\n  bout_.goxy(x, y);\n  bout_.print(\"|#7{:c}|17|14 {} |16|09{:c}\", static_cast<unsigned char>(181), text,\n              static_cast<unsigned char>(198));\n}\n\nvoid FullScreenView::GotoContentAreaTop() { bout_.goxy(1, num_header_lines_ + 2); }\n\nint FullScreenView::bgetch() {\n  return bin.bgetch_event(Input::numlock_status_t::NUMBERS,\n                          [&](Input::bgetch_timeout_status_t status, int s) {\n                            if (status == Input::bgetch_timeout_status_t::WARNING) {\n                              PrintTimeoutWarning(s);\n                            } else if (status == Input::bgetch_timeout_status_t::CLEAR) {\n                              ClearCommandLine();\n                            }\n                          });\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/full_screen.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2016-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_FULL_SCREEN_H\n#define INCLUDED_COMMON_FULL_SCREEN_H\n\n#include \"local_io/local_io.h\"\n#include <string>\n\nnamespace wwiv::common {\nclass Input;\nclass Output;\n\nclass FullScreenView final {\npublic:\n  FullScreenView(Output& output, Input& input, int numlines, int swidth, int slength);\n  ~FullScreenView();\n\n  /** Displays a timeout warning in the command line area */\n  void PrintTimeoutWarning(int);\n  /** Clears the command line area */\n  void ClearCommandLine();\n  /** Displays a text in the command line area */\n  void PutsCommandLine(const std::string& text);\n  /** Clears the message area (the main body of the full screen view */\n  void ClearMessageArea();\n  /** Displays the horizontal bar between the header area and body */\n  void DrawTopBar();\n  /** Displays the horizontal bar between the body and command line*/\n  void DrawBottomBar(const std::string& text);\n  /** Places the cursor at the top of the body */\n  void GotoContentAreaTop();\n\n  [[nodiscard]] int message_height() const noexcept { return message_height_; }\n  [[nodiscard]] int lines_start() const noexcept { return lines_start_; }\n  [[nodiscard]] int lines_end() const noexcept { return lines_end_; }\n  [[nodiscard]] int num_header_lines() const noexcept { return num_header_lines_; }\n  [[nodiscard]] int screen_width() const noexcept { return screen_width_; }\n\n  // Runs bgetch_event with error message and warning displayed\n  // on the status line.\n  int bgetch();\n\n  // Read through to this full screen's input.\n  [[nodiscard]] Input& in() const { return bin_; }\n  // Write through to this full screen's output.\n  [[nodiscard]] Output& out() const { return bout_; }\n\nprivate:\n  Input& bin_;\n  Output& bout_;\n\n  int num_header_lines_{0};\n  int screen_width_{0};\n  int screen_length_{0};\n  int message_height_{0};\n  int lines_start_{0};\n  int lines_end_{0};\n  int command_line_{0};\n\n  local::io::LocalIO::topdata_t saved_topdata{local::io::LocalIO::topdata_t::none};\n};\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/input.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/input.h\"\n\n#include \"common/common_events.h\"\n#include \"common/output.h\"\n#include \"core/eventbus.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include \"local_io/local_io.h\"\n\n#include <algorithm>\n#include <cctype>\n#include <cmath>\n#include <set>\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// static global bin.\nInput bin;\n\nnamespace wwiv::common {\n\nstatic const char* FILENAME_DISALLOWED = \"/\\\\<>|*?\\\";:\";\nstatic const char* FULL_PATH_NAME_DISALLOWED = \"<>|*?\\\";\";\n\n// TODO: put back in high ascii characters after finding proper hex codes\nstatic const std::string valid_letters(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");\n\n// This needs to work across input1 and input_password\nstatic unsigned char last_input_char;\n\n// TODO(rushfan): Make this a WWIV ini setting.\nstatic const uint8_t input_background_char = 32; // Was '\\xB1';\n\nstatic bool okansi(const wwiv::sdk::User& user) { return user.ansi(); }\n\nInput::Input() { memset(charbuffer, 0, sizeof(charbuffer)); }\nInput::~Input() = default;\n\n// This will input an upper-case string\nvoid Input::input(char* out_text, int max_length, bool auto_mpl) {\n  input1(out_text, max_length, InputMode::UPPER, true, auto_mpl);\n}\n\n// This will input an upper-case string\nstd::string Input::input(int max_length, bool auto_mpl) {\n  const auto line = std::make_unique<char[]>(max_length + 1);\n  input(line.get(), max_length, auto_mpl);\n  return line.get();\n}\n\n\nstatic int max_length_for_number(int64_t n) {\n  return n == 0 ? 1 : static_cast<int>(std::floor(std::log10(std::abs(n)))) + 1;\n}\n\nstatic bool colorize(bool last_ok, int64_t result, int64_t minv, int64_t maxv) {\n  const auto ok = (result >= minv && result <= maxv);\n  if (ok != last_ok) {\n    bout.RestorePosition();\n    bout.SavePosition();\n    bout.mpl(max_length_for_number(maxv));\n    bout.ansic(ok ? 4 : 6);\n    bout.outstr(std::to_string(result));\n  }\n  return ok;\n}\n\n// TODO(rushfan): HACK - Fix this and put back language support\nstatic std::string YesNoString(bool b) {\n  if (b) {\n   return bout.lang().value(\"KEY_YES\", \"Yes\"); \n  }\n  return bout.lang().value(\"KEY_NO\", \"No\"); \n}\n\nstatic char YesNoKey(bool b) {\n  return YesNoString(b).front();\n}\n\nstatic void print_yn(bool yes) {\n  if (yes) {\n    bout.str(\"YES\");\n  } else {\n    bout.str(\"NO\");\n  }\n  bout.nl();\n}\n\n/* The keyboard is checked for either a Y, N, or C/R to be hit.  C/R is\n * assumed to be the same as a N.  Yes or No is output, and yn is set to\n * zero if No was returned, and bin.yesno() is non-zero if Y was hit.\n */\nbool Input::yesno() {\n  char ch = 0;\n\n  bout.ansic(1);\n  while (!sess().hangup() && (ch = to_upper_case(bin.getkey())) != YesNoKey(true) &&\n         ch != YesNoKey(false) && ch != RETURN)\n    ;\n\n  const bool mci_enabled = bout.mci_enabled();\n  bout.enable_mci();\n  if (ch == YesNoKey(true)) {\n    print_yn(true);\n  } else {\n    print_yn(false);\n  }\n  bout.set_mci_enabled(mci_enabled);\n  return ch == YesNoKey(true);\n}\n\n/**\n * This is the same as bin.yesno(), except C/R is assumed to be \"Y\"\n */\nbool Input::noyes() {\n  char ch = 0;\n\n  bout.ansic(1);\n  while (!sess().hangup() && (ch = to_upper_case(bin.getkey())) != YesNoKey(true) &&\n         ch != YesNoKey(false) && ch != RETURN)\n    ;\n\n  const bool mci_enabled = bout.mci_enabled();\n  bout.enable_mci();\n  if (ch == YesNoKey(false)) {\n    print_yn(false);\n  } else {\n    print_yn(true);\n  }\n  bout.set_mci_enabled(mci_enabled);\n  return ch == YesNoKey(true) || ch == RETURN;\n}\n\nchar Input::ynq() {\n  char ch = 0;\n\n  bout.ansic(1);\n  const auto key_quit = bout.lang().value(\"KEY_QUIT\", \"Q\").front();\n  while (!sess().hangup() && (ch = to_upper_case(bin.getkey())) != YesNoKey(true) &&\n         ch != YesNoKey(false) && ch != key_quit && ch != RETURN) {\n    // NOP\n  }\n  const bool mci_enabled = bout.mci_enabled();\n  bout.enable_mci();\n  if (ch == YesNoKey(true)) {\n    ch = 'Y';\n    print_yn(true);\n  } else if (ch == key_quit) {\n    ch = 'Q';\n    bout.str(\"QUIT\");\n    bout.nl();\n  } else {\n    ch = 'N';\n    print_yn(false);\n  }\n  bout.set_mci_enabled(mci_enabled);\n  return ch;\n}\n\n//==================================================================\n// Function: Input1\n//\n// Purpose:  Input a line of text of specified length using a ansi\n//           formatted input line\n//\n// Parameters:  *out_text   = variable to save the input to\n//              *orig_text     = line to edit.  appears in edit box\n//              max_length      = max characters allowed\n//              insert     = insert mode false = off, true = on\n//              mode      = formatting mode.\n//\n// Returns: length of string\n//==================================================================\nvoid Input::Input1(char* out_text, const std::string& orig_text, int max_length, bool insert,\n                   InputMode mode, bool auto_mpl) {\n  char szTemp[255];\n  static const auto dash = '-';\n  static const auto slash = '/';\n\n  if (!okansi(user())) {\n    input1(szTemp, max_length, mode, true, false);\n    strcpy(out_text, szTemp);\n    return;\n  }\n  const auto saved_topdata = localIO()->topdata();\n  if (localIO()->topdata() != LocalIO::topdata_t::none) {\n    localIO()->topdata(LocalIO::topdata_t::none);\n    bus().invoke<UpdateTopScreenEvent>();\n  }\n  if (mode == InputMode::DATE || mode == InputMode::PHONE) {\n    insert = false;\n  }\n  const auto saved_topline = localIO()->GetTopLine();\n  localIO()->SetTopLine(0);\n  auto pos = 0;\n  auto nLength = 0;\n  szTemp[0] = '\\0';\n\n  max_length = std::min<int>(max_length, 78);\n\n  bout.SavePosition();\n  if (auto_mpl) {\n    bout.ansic(4);\n    for (auto i = 0; i < max_length; i++) {\n      bout.outchr(input_background_char);\n    }\n    bout.RestorePosition();\n    bout.SavePosition();\n  }\n  if (!orig_text.empty()) {\n    to_char_array(szTemp, orig_text);\n    bout.outstr(szTemp);\n    bout.RestorePosition();\n    bout.SavePosition();\n    pos = nLength = strings::ssize(szTemp);\n  }\n\n  auto done = false;\n  do {\n    bout.RestorePosition();\n    bout.SavePosition();\n    bout.Right(pos);\n\n    auto c = bin.bgetch_event(wwiv::common::Input::numlock_status_t::NUMBERS);\n    last_input_char = static_cast<char>(c & 0xff);\n    switch (c) {\n    case CX:  // Control-X\n    case ESC: // ESC\n      if (nLength) {\n        bout.RestorePosition();\n        bout.SavePosition();\n        bout.Right(nLength);\n        while (nLength--) {\n          bout.RestorePosition();\n          bout.SavePosition();\n          bout.Right(nLength);\n          bout.outchr(input_background_char);\n        }\n        nLength = pos = szTemp[0] = 0;\n      }\n      break;\n    case COMMAND_LEFT: // Left Arrow\n    case CS:\n      if ((mode != InputMode::DATE) && (mode != InputMode::PHONE)) {\n        if (pos) {\n          pos--;\n        }\n      }\n      break;\n    case COMMAND_RIGHT: // Right Arrow\n    case CD:\n      if (mode != InputMode::DATE && mode != InputMode::PHONE) {\n        if (pos != nLength && pos != max_length) {\n          pos++;\n        }\n      }\n      break;\n    case CA:\n    case COMMAND_HOME: // Home\n    case CW:\n      pos = 0;\n      break;\n    case CE:\n    case COMMAND_END: // End\n    case CP:\n      pos = nLength;\n      break;\n    case COMMAND_INSERT: // Insert\n      if (mode == InputMode::UPPER) {\n        insert = !insert;\n      }\n      break;\n    case COMMAND_DELETE: // Delete\n    case CG:\n      if (pos == nLength || mode == InputMode::DATE || mode == InputMode::PHONE) {\n        break;\n      }\n      for (auto i = pos; i < nLength; i++) {\n        szTemp[i] = szTemp[i + 1];\n      }\n      nLength--;\n      for (auto i = pos; i < nLength; i++) {\n        bout.outchr(szTemp[i]);\n      }\n      bout.outchr(input_background_char);\n      break;\n    // Backspace (0x08)\n    case BACKSPACE:\n      if (pos) {\n        if (pos != nLength) {\n          if (mode != InputMode::DATE && mode != InputMode::PHONE) {\n            for (int i = pos - 1; i < nLength; i++) {\n              szTemp[i] = szTemp[i + 1];\n            }\n            pos--;\n            nLength--;\n            bout.RestorePosition();\n            bout.SavePosition();\n            bout.Right(pos);\n            for (int i = pos; i < nLength; i++) {\n              bout.outchr(szTemp[i]);\n            }\n            bout.outchr(input_background_char);\n          }\n        } else {\n          bout.RestorePosition();\n          bout.SavePosition();\n          bout.Right(pos - 1);\n          bout.outchr(input_background_char);\n          pos = --nLength;\n          // ReSharper disable once CppRedundantParentheses\n          if ((mode == InputMode::DATE && (pos == 2 || pos == 5)) ||\n              (mode == InputMode::PHONE && (pos == 3 || pos == 7))) {\n            bout.RestorePosition();\n            bout.SavePosition();\n            bout.Right(pos - 1);\n            bout.outchr(input_background_char);\n            pos = --nLength;\n          }\n        }\n      }\n      break;\n      // Enter\n    case RETURN:\n      done = true;\n      break;\n    // All others < 256\n    default:\n      if (c < 255 && c > 31 &&\n          ((insert && nLength < max_length) || (!insert && pos < max_length))) {\n        if (mode != InputMode::MIXED && mode != InputMode::FILENAME && mode != InputMode::CMDLINE &&\n            mode != InputMode::FULL_PATH_NAME) {\n          c = upcase(static_cast<unsigned char>(c));\n        }\n        if (mode == InputMode::FILENAME || mode == InputMode::FULL_PATH_NAME ||\n            mode == InputMode::CMDLINE) {\n          // This was causing issues (see https://github.com/wwivbbs/wwiv/issues/1515)\n          // N.B. I'm not sure what issues removing this will cause, but people on @nix\n          // will need to be more careful about the case of files they enter.\n          // We're early enough in 5.8 cycle that hopefully we'll shake out any problems\n          // caused by this before we finalize it.\n          \n          //if (mode == InputMode::FILENAME || mode == InputMode::FULL_PATH_NAME) {\n          //  // Force lowercase filenames but not command lines.\n          //  c = to_lower_case<unsigned char>(static_cast<unsigned char>(c));\n          //}\n          if (mode == InputMode::FILENAME && strchr(\"/\\\\<>|*?\\\";:\", c)) {\n            c = 0;\n          } else if (mode == InputMode::FILENAME && strchr(\"<>|*?\\\";\", c)) {\n            c = 0;\n          }\n        }\n        if (mode == InputMode::PROPER && pos) {\n          const auto cc = static_cast<unsigned char>(c);\n          const auto found = valid_letters.find(cc) != std::string::npos;\n          // if it's a valid char and the previous char was a space\n          if (found && szTemp[pos - 1] != 32) {\n            c = locase(cc);\n          }\n        }\n        if (mode == InputMode::DATE && (pos == 2 || pos == 5)) {\n          bout.outchr(slash);\n          for (auto i = nLength++; i >= pos; i--) {\n            szTemp[i + 1] = szTemp[i];\n          }\n          szTemp[pos++] = slash;\n          bout.RestorePosition();\n          bout.SavePosition();\n          bout.Right(pos);\n          bout.outstr(&szTemp[pos]);\n        }\n        if (mode == InputMode::PHONE && (pos == 3 || pos == 7)) {\n          bout.outchr(dash);\n          for (auto i = nLength++; i >= pos; i--) {\n            szTemp[i + 1] = szTemp[i];\n          }\n          szTemp[pos++] = dash;\n          bout.RestorePosition();\n          bout.SavePosition();\n          bout.Right(pos);\n          bout.outstr(&szTemp[pos]);\n        }\n        // ReSharper disable once CppRedundantParentheses\n        if ((mode == InputMode::DATE && c != slash) || (mode == InputMode::PHONE && c != dash) ||\n        // ReSharper disable once CppRedundantParentheses\n            (mode != InputMode::DATE && mode != InputMode::PHONE && c != 0)) {\n          if (!insert || pos == nLength) {\n            bout.outchr(static_cast<char>(c));\n            szTemp[pos++] = static_cast<char>(c);\n            if (pos > nLength) {\n              nLength++;\n            }\n          } else {\n            bout.outchr(static_cast<char>(c));\n            for (auto i = nLength++; i >= pos; i--) {\n              szTemp[i + 1] = szTemp[i];\n            }\n            szTemp[pos++] = static_cast<char>(c);\n            bout.RestorePosition();\n            bout.SavePosition();\n            bout.Right(pos);\n            bout.outstr(&szTemp[pos]);\n          }\n        }\n      }\n      break;\n    }\n    szTemp[nLength] = '\\0';\n    bus().invoke<CheckForHangupEvent>();\n  } while (!done && !sess().hangup());\n  if (nLength) {\n    strcpy(out_text, szTemp);\n  } else {\n    out_text[0] = '\\0';\n  }\n\n  localIO()->topdata(saved_topdata);\n  localIO()->SetTopLine(saved_topline);\n\n  bout.ansic(0);\n  bout.nl();\n}\n\nstd::string Input::Input1(const std::string& orig_text, int max_length, bool bInsert, InputMode mode, bool auto_mpl) {\n  const auto line = std::make_unique<char[]>(max_length + 1);\n  Input1(line.get(), orig_text, max_length, bInsert, mode, auto_mpl);\n  return line.get();\n}\n\n/**\n * This will input a line of data, maximum max_length characters long, terminated\n * by a C/R.  if (lc) is non-zero, lowercase is allowed, otherwise all\n * characters are converted to uppercase.\n * @param out_text the text entered by the user (output value)\n * @param max_length Maximum length to allow for the input text\n * @param lc The case to return, this can be InputMode::UPPER, InputMode::MIXED, InputMode::PROPER,\n * or InputMode::FILENAME\n * @param crend output the CR/LF if one is entered.\n * @param auto_mpl Call bout.mpl(max_length) automatically.\n */\nvoid Input::input1(char* out_text, int max_length, InputMode lc, bool crend, bool auto_mpl) {\n  if (auto_mpl) {\n    bout.mpl(max_length);\n  }\n\n  auto curpos = 0, in_ansi = 0;\n  auto done = false;\n\n  while (!done && !sess().hangup()) {\n    unsigned char chCurrent = bin.getkey();\n\n    sess().chatline(curpos != 0);\n\n    if (in_ansi) {\n      if (in_ansi == 1 && chCurrent != '[') {\n        in_ansi = 0;\n      } else {\n        if (in_ansi == 1) {\n          in_ansi = 2;\n        } else {\n          if ((chCurrent < '0' || chCurrent > '9') && chCurrent != ';') {\n            in_ansi = 3;\n          } else {\n            in_ansi = 2;\n          }\n        }\n      }\n    }\n    if (!in_ansi) {\n      if (chCurrent > 31) {\n        switch (lc) {\n        case InputMode::UPPER:\n          chCurrent = upcase(chCurrent);\n          break;\n        case InputMode::MIXED:\n          break;\n        case InputMode::PROPER:\n          chCurrent = upcase(chCurrent);\n          if (curpos) {\n            const auto found = valid_letters.find(out_text[curpos - 1]) != std::string::npos;\n            if (found || out_text[curpos - 1] == 39) {\n              if (curpos < 2 || out_text[curpos - 2] != 77 || out_text[curpos - 1] != 99) {\n                chCurrent = locase(chCurrent);\n              }\n            }\n          }\n          break;\n        case InputMode::CMDLINE:\n        case InputMode::FILENAME:\n        case InputMode::FULL_PATH_NAME: {\n          std::string disallowed =\n              lc == InputMode::FILENAME ? FILENAME_DISALLOWED : FULL_PATH_NAME_DISALLOWED;\n          if (disallowed.find(chCurrent) != std::string::npos) {\n            chCurrent = 0;\n          } else if (lc != InputMode::CMDLINE) {\n            // Lowercase filenames on all platforms, not just Win32.\n            // Leave command lines alone.\n            chCurrent = to_lower_case(chCurrent);\n          }\n        } break;\n        }\n        if (curpos < max_length && chCurrent) {\n          out_text[curpos++] = chCurrent;\n          bout.outchr(chCurrent);\n        }\n      } else {\n        switch (chCurrent) {\n        case SOFTRETURN:\n          if (last_input_char != RETURN) {\n            //\n            // Handle the \"one-off\" case where UNIX telnet clients only return\n            // '\\n' (#10) instead of '\\r' (#13).\n            //\n            out_text[curpos] = '\\0';\n            done = true;\n            if (bout.newline || crend) {\n              bout.nl();\n            }\n          }\n          break;\n        case CN:\n        case RETURN:\n          out_text[curpos] = '\\0';\n          done = true;\n          if (bout.newline || crend) {\n            bout.nl();\n          }\n          break;\n        case CW: // Ctrl-W\n          if (curpos) {\n            do {\n              curpos--;\n              bout.bs();\n              if (out_text[curpos] == CZ) {\n                bout.bs();\n              }\n            } while (curpos && out_text[curpos - 1] != SPACE);\n          }\n          break;\n        case CZ:\n          break;\n        case BACKSPACE:\n          if (curpos) {\n            curpos--;\n            bout.bs();\n            if (out_text[curpos] == CZ) {\n              bout.bs();\n            }\n          }\n          break;\n        case CU:\n        case CX:\n          while (curpos) {\n            curpos--;\n            bout.bs();\n            if (out_text[curpos] == CZ) {\n              bout.bs();\n            }\n          }\n          break;\n        case ESC:\n          in_ansi = 1;\n          break;\n        }\n        last_input_char = chCurrent;\n      }\n    }\n    if (in_ansi == 3) {\n      in_ansi = 0;\n    }\n  }\n  if (sess().hangup()) {\n    out_text[0] = '\\0';\n  }\n}\n\n// private\nstd::string Input::input_password_minimal(int max_length) {\n  const char mask_char = okansi(user()) ? '\\xFE' : 'X';\n  std::string pw;\n  bout.mpl(max_length);\n\n  while (!sess().hangup()) {\n    unsigned char ch = bin.getkey();\n\n    if (ch > 31) {\n      ch = upcase(ch);\n      if (ssize(pw) < max_length && ch) {\n        pw.push_back(ch);\n        bout.outchr(mask_char);\n      }\n      continue;\n    }\n    switch (ch) {\n    case SOFTRETURN:\n      // Handle the case where some telnet clients only return \\n vs \\r\\n\n      if (last_input_char != RETURN) {\n        bout.nl();\n        last_input_char = ch;\n        return pw;\n      }\n      break;\n    case CN:\n    case RETURN:\n      bout.nl();\n      last_input_char = ch;\n      return pw;\n    case CW: // Ctrl-W\n      while (!pw.empty() && pw.back() != SPACE) {\n        pw.pop_back();\n        bout.bs();\n      }\n      break;\n    case BACKSPACE:\n      if (!pw.empty()) {\n        pw.pop_back();\n        bout.bs();\n      }\n      break;\n    case CU:\n    case CX:\n      while (!pw.empty()) {\n        pw.pop_back();\n        bout.bs();\n      }\n      break;\n    }\n    last_input_char = ch;\n  }\n  return \"\";\n}\n\nstd::string Input::input_password(const std::string& prompt_text, int max_length) {\n  if (!prompt_text.empty()) {\n    bout.outstr(prompt_text);\n  }\n  return input_password_minimal(max_length);\n}\n\n/**\n * Raw input_number method. Clients should use input_number or  input_number_hotkey instead.\n */\ninput_result_t<int64_t> Input::input_number_or_key_raw(int64_t cur, int64_t minv, int64_t maxv,\n                                                       bool setdefault,\n                                                       const std::set<char>& hotkeys) {\n  const auto max_length = max_length_for_number(maxv);\n  std::string text;\n  bout.mpl(max_length);\n  auto allowed = hotkeys;\n  auto last_ok = false;\n  auto keypressed_ever = false;\n  allowed.insert(\n      {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '\\r', '\\n', '\\b', '\\x15', '\\x17', '\\x18'});\n  bout.SavePosition();\n  int64_t result = 0;\n  if (setdefault) {\n    result = cur;\n    text = std::to_string(result);\n    last_ok = colorize(last_ok, result, minv, maxv);\n  }\n  while (!sess().hangup()) {\n    auto ch = bin.getkey();\n    if (std::isdigit(ch)) {\n      if (!keypressed_ever) {\n        // We have a digit key, clear the input and start taking the caller's text.\n        keypressed_ever = true;\n        while (!text.empty()) {\n          text.pop_back();\n          bout.bs();\n        }\n      }\n      // digit\n      if (ssize(text) < max_length && ch) {\n        text.push_back(ch);\n        bout.outchr(ch);\n        result = to_number<int64_t>(text);\n        last_ok = colorize(last_ok, result, minv, maxv);\n      }\n      last_input_char = ch;\n      continue;\n    }\n    keypressed_ever = true;\n\n    if (ch > 31) {\n      // Only non-control characters should be upper cased.\n      // this way it covers the hotkeys.\n      ch = to_upper_case(ch);\n    }\n    if (!contains(allowed, ch)) {\n      continue;\n    }\n    switch (ch) {\n    case '\\n':\n      // Handle the case where some telnet clients only return \\n vs \\r\\n\n      if (last_input_char != '\\r') {\n        last_input_char = ch;\n        if (result >= minv && result <= maxv) {\n          bout.nl();\n          return {result, '\\0'};\n        }\n      } else {\n        last_input_char = ch;\n      }\n      break;\n    case '\\r':\n      last_input_char = ch;\n      if (result >= minv && result <= maxv) {\n        bout.nl();\n        return {result, '\\0'};\n      }\n      break;\n    case '\\b':\n      last_input_char = ch;\n      if (!text.empty()) {\n        text.pop_back();\n        bout.bs();\n      }\n      result = to_number<int64_t>(text);\n      last_ok = colorize(last_ok, result, minv, maxv);\n      break;\n    case CW: // Ctrl-W\n    case CX: {\n      last_input_char = ch;\n      while (!text.empty()) {\n        text.pop_back();\n        bout.bs();\n      }\n      bout.mpl(max_length);\n    } break;\n    default:\n      // This is a hotkey.\n      return {0, ch};\n    }\n  }\n  return {0, 0};\n}\n\nstd::string Input::input_filename(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::FILENAME, true);\n}\n\nstd::string Input::input_filename(int max_length) { return input_filename(\"\", max_length); }\n\nstd::string Input::input_path(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::FULL_PATH_NAME, true);\n}\n\nstd::string Input::input_path(int max_length) { return input_path(\"\", max_length); }\n\nstd::string Input::input_cmdline(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::CMDLINE, true);\n}\n\n\nstd::string Input::input_phonenumber(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::PHONE, true);\n}\n\nstd::string Input::input_text(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::MIXED, true);\n}\n\nstd::string Input::input_text(const std::string& orig_text, bool mpl, int max_length) {\n  if (mpl) {\n    return Input1(orig_text, max_length, true, InputMode::MIXED, mpl);\n  }\n  if (max_length > 255) {\n    return \"\";\n  }\n  char s[255];\n  input1(s, max_length, InputMode::MIXED, true, false);\n  return s;\n}\n\nstd::string Input::input_text(int max_length) {\n  return Input1(\"\", max_length, true, InputMode::MIXED, true);\n}\n\nstd::string Input::input_upper(const std::string& orig_text, int max_length, bool auto_mpl) {\n  return Input1(orig_text, max_length, true, InputMode::UPPER, auto_mpl);\n}\n\nstd::string Input::input_upper(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::UPPER, true);\n}\n\nstd::string Input::input_upper(int max_length) { return input_upper(\"\", max_length); }\n\nstd::string Input::input_proper(const std::string& orig_text, int max_length) {\n  return Input1(orig_text, max_length, true, InputMode::PROPER, true);\n}\n\nstd::string Input::input_date_mmddyyyy(const std::string& orig_text) {\n  return Input1(orig_text, 10, true, InputMode::DATE, true);\n}\n\nvoid Input::resetnsp() {\n  if (nsp() == 1 && !user().pause()) {\n    user().toggle_flag(wwiv::sdk::User::pauseOnPage);\n  }\n  clearnsp();\n}\n\nvoid Input::clearnsp() { nsp_ = 0; }\n\nint Input::nsp() const noexcept { return nsp_; }\n\nvoid Input::nsp(int n) { nsp_ = n; }\n\nstd::optional<ScreenPos> Input::screen_size() {\n  bout.SavePosition();\n  // Use puts so the local ansi interpretation will work.\n  // This should position it one past the end.\n  bout.outstr(\"\\x1b[999;999H\");\n  auto pos = remoteIO()->screen_position();\n  bout.RestorePosition();\n  if (!pos) {\n    return std::nullopt;\n  }\n  if (pos->x < 20 || pos->y < 10) {\n    // If the screensize is less than 20 wide or 10 tall, this seems sus,\n    // so fail to detect it by returning a nullopt.\n    return std::nullopt;\n  }\n  return {ScreenPos{pos->x, pos->y}};\n}\n\n}"
  },
  {
    "path": "common/input.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_INPUT_H\n#define INCLUDED_COMMON_INPUT_H\n\n#include \"common/iobase.h\"\n#include \"common/context.h\"\n#include \"common/remote_io.h\"\n#include <chrono>\n#include <cstdint>\n#include <functional>\n#include <set>\n#include <string>\n\nnamespace wwiv::common {\n  class Input;\n}\n\nextern wwiv::common::Input bin;\n\nnamespace wwiv::common {\n\n// Text editing modes for input routines\nenum class InputMode { UPPER, MIXED, PROPER, FILENAME, FULL_PATH_NAME, CMDLINE, DATE, PHONE };\n\ntemplate <typename T> struct input_result_t {\n  T num{0};\n  char key{0};\n};\n\n/**\n * Creates the Output class responsible for displaying information both\n * locally and remotely.\n *\n * To use this class you must set the needed fields from IOBase.\n */\nclass Input final : public IOBase {\npublic:\n  Input();\n  ~Input();\n\n  [[nodiscard]] bool IsLastKeyLocal() const noexcept { return last_key_local_; }\n  void SetLastKeyLocal(bool b) { last_key_local_ = b; }\n\n  char bgetch(bool allow_extended_input = false);\n  char bgetchraw();\n  bool bkbhitraw();\n  bool bkbhit();\n  char getkey(bool allow_extended_input = false);\n\n  // Key Timeouts\n  [[nodiscard]] std::chrono::duration<double> key_timeout() const;\n  void set_key_timeout(std::chrono::duration<double> k) { non_sysop_key_timeout_ = k; }\n  void set_sysop_key_timeout(std::chrono::duration<double> k) { sysop_key_timeout_ = k; }\n  void set_default_key_timeout(std::chrono::duration<double> k) { default_key_timeout_ = k; }\n  void set_logon_key_timeout(std::chrono::duration<double> k) { logon_key_timeout_ = k; }\n\n  //\n  // Key Timeout manipulators.\n  //\n\n  void set_logon_key_timeout() { non_sysop_key_timeout_ = logon_key_timeout_; };\n  void reset_key_timeout() { non_sysop_key_timeout_ = default_key_timeout_; }\n  \n  //\n  // bgetch_event - bgetch with cursor keys and such.\n  //\n\n  // For bgetch_event, decides if the number pad turns '8' into an arrow etc.. or not\n  enum class numlock_status_t { NUMBERS, NOTNUMBERS };\n\n  enum class bgetch_timeout_status_t { WARNING, CLEAR, IDLE };\n\n  typedef std::function<void(bgetch_timeout_status_t, int)> bgetch_callback_fn;\n  int bgetch_event(numlock_status_t numlock_mode, std::chrono::duration<double> idle_time,\n                   bgetch_callback_fn cb);\n  int bgetch_event(numlock_status_t numlock_mode, bgetch_callback_fn cb);\n  int bgetch_event(numlock_status_t numlock_mode);\n\n  //\n  // Yes/No/Quit prompts\n  //\n\n  bool yesno();\n  bool noyes();\n  char ynq();\n\n  //\n  // Need Screen Pause. Used by Yes/No/Continue prompts.\n  //\n\n  void clearnsp();\n  void resetnsp();\n  int nsp() const noexcept;\n  void nsp(int n);\n\n  [[nodiscard]] bool okskey() const noexcept { return okskey_; }\n  void okskey(bool n) { okskey_ = n; }\n\n  /**\n   * Inputs password up to length max_length.\n   */\n  std::string input_password(const std::string& prompt_text, int max_length);\n\n  /**\n   * Inputs number or a key contained in hotkeys.\n   */\n  input_result_t<int64_t> input_number_or_key_raw(int64_t cur, int64_t minv, int64_t maxv,\n                                                  bool setdefault, const std::set<char>& hotkeys);\n\n  /**\n   * Inputs filename up to length max_length.\n   */\n  std::string input_filename(int max_length);\n\n  /**\n   * Inputs filename (without directory separators) up to length max_length.\n   */\n  std::string input_filename(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs path (including directory separators) up to length max_length.\n   */\n  std::string input_path(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs path (including directory separators) up to length max_length.\n   */\n  std::string input_path(int max_length);\n\n  /**\n   * Inputs command-line up to length max_length.\n   */\n  std::string input_cmdline(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs phone number up to length max_length.\n   */\n  std::string input_phonenumber(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs random text (upper and lower case) up to length max_length.\n   */\n  std::string input_text(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs random text (upper and lower case) up to length max_length\n   * with the ability to turn on or off the MPL.\n   */\n  std::string input_text(const std::string& orig_text, bool mpl, int max_length);\n\n  /**\n   * Inputs random text (upper and lower case) up to length max_length.\n   */\n  std::string input_text(int max_length);\n\n  /**\n   * Inputs random text (upper case) up to length max_length.\n   */\n  std::string input_upper(const std::string& orig_text, int max_length, bool auto_mpl);\n\n  /**\n   * Inputs random text (upper case) up to length max_length.\n   */\n  std::string input_upper(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs random text (upper case) up to length max_length.\n   */\n  std::string input_upper(int max_length);\n\n  /**\n   * Inputs random text (In Proper Case) up to length max_length.\n   */\n  std::string input_proper(const std::string& orig_text, int max_length);\n\n  /**\n   * Inputs a date (10-digit) of MM/DD/YYYY.\n   */\n  std::string input_date_mmddyyyy(const std::string& orig_text);\n\n  /**\n   * Inputs a string in upper case.  These should probably all be replaced\n   * by calling the appropriate input_xxx routine.\n   */\n  void input(char* out_text, int max_length, bool auto_mpl = false);\n  std::string input(int max_length, bool auto_mpl = false);\n\n  // TODO(rushfan): Using an int64_t for the min/max both here and in input_number_or_key_raw\n  //               is a bit wonky, but works for probably all case in WWIV since it won't be\n  //               using int64_t user input most likely ever.  Otherwise need to wait till compilers\n  //               are happy enough with auto everywhere to pass through caller types.\n  /**\n   * Inputs a number of type T within the range of min_value and max_value.\n   * If set_default_value is true (the default) then the input box will have\n   * the current_value populated.\n   */\n  template <typename T>\n  T input_number(T current_value, int64_t min_value = std::numeric_limits<T>::min(),\n                 int64_t max_value = std::numeric_limits<T>::max(), bool set_default_value = true) {\n    if (current_value < min_value) {\n      current_value = static_cast<T>(min_value);\n    } else if (current_value > max_value) {\n      current_value = static_cast<T>(max_value);\n    }\n    auto r =\n        bin.input_number_or_key_raw(current_value, min_value, max_value, set_default_value, {'Q'});\n    return (r.key != 0) ? current_value : static_cast<T>(r.num);\n  }\n\n  template <typename T>\n  wwiv::common::input_result_t<T> input_number_hotkey(T current_value, const std::set<char>& keys,\n                                                      int min_value = std::numeric_limits<T>::min(),\n                                                      int max_value = std::numeric_limits<T>::max(),\n                                                      bool set_default_value = false) {\n    auto orig =\n        bin.input_number_or_key_raw(current_value, min_value, max_value, set_default_value, keys);\n    wwiv::common::input_result_t<T> r{static_cast<T>(orig.num), orig.key};\n    return r;\n  }\n\n  /**\n   * Returns the screen size as a coordnate (x, y) denoting the position\n   * of the lower right corner.\n   */\n  std::optional<ScreenPos> screen_size();\n\n\n  //\n  // Check for Abort\n  //\n\n  bool checka();\n  bool checka(bool* abort);\n  bool checka(bool* abort, bool* next);\n\n  // Used for macros.  TODO: Make this private\n  int charbufferpointer_{0};\n  char charbuffer[255]{};\n\nprivate:\n  // Used by input_xxx\n  void Input1(char* out_text, const std::string& orig_text, int max_length, bool insert,\n              InputMode mode, bool auto_mpl);\n  // Used by input_xxx\n  std::string Input1(const std::string& orig_text, int max_length, bool bInsert, InputMode mode, bool auto_mpl);\n  // used by input_xxx\n  void input1(char* out_text, int max_length, InputMode lc, bool crend, bool auto_mpl);\n  // used by input_password\n  std::string input_password_minimal(int max_length);\n  // used by bgetch_event\n  int bgetch_handle_key_translation(int key, numlock_status_t numlock_mode);\n  // used by bgetch_event\n  int bgetch_handle_escape(int key);\n\n\nprivate:\n  local::io::LocalIO* local_io_{nullptr};\n  RemoteIO* comm_{nullptr};\n  bool last_key_local_{true};\n  int nsp_{0};\n  bool okskey_{true};\n\n  std::chrono::duration<double> non_sysop_key_timeout_ = std::chrono::minutes(3);\n  std::chrono::duration<double> default_key_timeout_ = std::chrono::minutes(3);\n  std::chrono::duration<double> sysop_key_timeout_ = std::chrono::minutes(10);\n  std::chrono::duration<double> logon_key_timeout_ = std::chrono::minutes(3);\n};\n\n} // namespace wwiv::common\n\n\n#endif\n"
  },
  {
    "path": "common/input_range.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/input_range.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nstd::vector<std::string> split_distinct_ranges(std::string s) {\n  s.erase(std::remove(std::begin(s), std::end(s), ' '), std::end(s));\n  return SplitString(s, \",\", true);\n}\n\nbool is_consecutive_range(const std::string& text) {\n  if (text.empty()) {\n    return false;\n  }\n\n  const auto idx = text.find('-');\n  return idx != std::string::npos && idx != 0 && idx != text.size() - 1;\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/input_range.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_INPUT_RANGE_H\n#define INCLUDED_COMMON_INPUT_RANGE_H\n\n#include \"common/input.h\"\n#include \"core/strings.h\"\n#include \"common/context.h\"\n#include <optional>\n#include <set>\n#include <string>\n\nnamespace wwiv::common {\n\nstd::vector<std::string> split_distinct_ranges(std::string s);\n\nbool is_consecutive_range(const std::string& text);\n\n\ntemplate<typename T> std::set<T> expand_consecutive_range(const std::string& text) {\n  if (!is_consecutive_range(text)) {\n    return {};\n  }\n  auto v = strings::SplitString(text, \"-\", true);\n  if (v.size() != 2) {\n    return {};\n  }\n  if constexpr (std::is_same_v<char, T>) {\n    if (v.at(0).size() != 1 || v.at(1).size() != 1) {\n      return {};\n    }\n    const auto start = v.at(0).front();\n    const auto end = v.at(1).front();\n    std::set<T> out;\n    for (auto i = start; i <= end; ++i) {\n      out.emplace(i);\n    }\n    return out;\n  } else if constexpr (std::is_integral_v<T>) {\n    const auto start = strings::to_number<T>(v.at(0));\n    const auto end = strings::to_number<T>(v.at(1));\n    std::set<T> out;\n    for (auto i = start; i <= end; ++i) {\n      out.emplace(i);\n    }\n    return out;\n  } else {\n    return {};\n  }\n}\n\ntemplate<typename T>\nstd::set<T> expand_ranges(const std::string& text, const std::set<T>& range) {\n  const auto v = split_distinct_ranges(text);\n  if (v.empty()) {\n    return {};\n  }\n  std::set<T> out;\n  for (const auto& r : v) {\n    if (r.empty()) {\n      continue;\n    }\n    if (is_consecutive_range(r)) {\n      const auto r1 = expand_consecutive_range<T>(r);\n      out.insert(std::begin(r1), std::end(r1));\n    } else {\n      if constexpr (std::is_same_v<char, T>) {\n        out.insert(r.front());\n      } else if constexpr (std::is_integral_v<T>) {\n        out.insert(strings::to_number<T>(r));\n      }\n    }\n  }\n\n  std::set<T> intersection;\n  std::set_intersection(std::begin(out), std::end(out), \n    std::begin(range), std::end(range),\n           std::inserter(intersection, std::begin(intersection)));\n  return intersection;\n}\n\ntemplate<typename T>\nstd::optional<std::set<T>> input_range(Input& in, int maxlen, const std::set<T>& range) {\n  const auto s = in.input_text(\"\", maxlen);\n  if (s.empty()) {\n    return std::nullopt;\n  }\n  return expand_ranges(s, range);\n}\n\n} // namespace\n\n\n#endif\n"
  },
  {
    "path": "common/input_range_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5.x                            */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n#include \"common/input_range.h\"\n\nusing namespace wwiv::common;\nusing namespace testing;\n\nTEST(InputRangeTest, ConsecutiveRange_Numbers) {\n  EXPECT_TRUE(is_consecutive_range(\"1-3\"));\n\n  EXPECT_FALSE(is_consecutive_range(\"1,3\"));\n  EXPECT_FALSE(is_consecutive_range(\"1,2\"));\n  EXPECT_FALSE(is_consecutive_range(\"\"));\n  EXPECT_FALSE(is_consecutive_range(\",2\"));\n  EXPECT_FALSE(is_consecutive_range(\"1,\"));\n}\n\nTEST(InputRangeTest, ConsecutiveRange_Chars) {\n  EXPECT_TRUE(is_consecutive_range(\"A-Z\"));\n\n  EXPECT_FALSE(is_consecutive_range(\"A,C\"));\n  EXPECT_FALSE(is_consecutive_range(\"A,B\"));\n  EXPECT_FALSE(is_consecutive_range(\"\"));\n  EXPECT_FALSE(is_consecutive_range(\",B\"));\n  EXPECT_FALSE(is_consecutive_range(\"Z,\"));\n}\n\nTEST(InputRangeTest, SplitDistinctRanges) {\n  auto r = split_distinct_ranges(\"1-3,5\");\n  EXPECT_THAT(r, ElementsAre(\"1-3\", \"5\"));\n\n  r = split_distinct_ranges(\",5,8\");\n  EXPECT_THAT(r, ElementsAre(\"5\", \"8\"));\n\n  r = split_distinct_ranges(\"\");\n  EXPECT_THAT(r, IsEmpty());\n\n  r = split_distinct_ranges(\",5,8,9-10,11\");\n  EXPECT_THAT(r, ElementsAre(\"5\", \"8\", \"9-10\", \"11\"));\n}\n\nTEST(InputRangeTest, SplitDistinctRanges_Char) {\n  auto r = split_distinct_ranges(\"A-C,E\");\n  EXPECT_THAT(r, ElementsAre(\"A-C\", \"E\"));\n}\n\nTEST(InputRangeTest, ExpandConsecutiveRange) {\n  auto r = expand_consecutive_range<int>(\"1-3\");\n  EXPECT_THAT(r, ElementsAre(1, 2, 3));\n}\n\nTEST(InputRangeTest, ExpandConsecutiveRange_Char) {\n  auto r = expand_consecutive_range<char>(\"B-D\");\n  EXPECT_THAT(r, ElementsAre('B', 'C', 'D'));\n}\n\nTEST(InputRangeTest, ExpandRanges) {\n  auto r = expand_ranges<int>(\"2,5-7,9\", std::set<int>{1,2,3,4,5,6,7,8,9,10});\n  EXPECT_THAT(r, ElementsAre(2, 5, 6, 7, 9));\n}\n\nTEST(InputRangeTest, ExpandRanges_Char) {\n  auto r = expand_ranges<char>(\"A,C-E,G\", std::set<char>{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'});\n  EXPECT_THAT(r, ElementsAre('A', 'C', 'D', 'E', 'G'));\n}\n"
  },
  {
    "path": "common/iobase.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/iobase.h\"\n\n#include \"core/log.h\"\n#include <functional>\n\nusing namespace wwiv::core;\n\nnamespace wwiv::common {\n\n// Context stuff\n\nsdk::User& IOBase::user() const { \n  DCHECK(context_provider_);\n  return context_provider_().u();\n}\n\nSessionContext& IOBase::sess() { \n  DCHECK(context_provider_);\n  return context_provider_().session_context();\n}\n\nSessionContext& IOBase::sess() const { \n  DCHECK(context_provider_);\n  return context_provider_().session_context();\n}\n\nContext& IOBase::context() { \n  DCHECK(context_provider_);\n  return context_provider_(); \n}\n\n}"
  },
  {
    "path": "common/iobase.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_IOBASE_H\n#define INCLUDED_COMMON_IOBASE_H\n\n#include \"common/context.h\"\n#include \"common/remote_io.h\"\n#include \"core/strings.h\"\n#include \"sdk/user.h\"\n#include <functional>\n\nnamespace wwiv::common {\n\n/**\n * Base class for Input and Output.\n *\n * To use this class you must set the following:\n * - LocalIO\n * - RemoteIO\n * - Context Provider\n *\n * These may be modified after being set, so RAII does not work.\n */\nclass IOBase {\npublic:\n  typedef std::function<wwiv::common::Context&()> context_provider_t;\n  IOBase() = default;\n  virtual ~IOBase() = default;\n\n  virtual void SetLocalIO(local::io::LocalIO* local_io) { local_io_ = local_io; }\n  [[nodiscard]] local::io::LocalIO* localIO() const noexcept { return local_io_; }\n\n  void SetComm(RemoteIO* comm) { comm_ = comm; }\n  [[nodiscard]] RemoteIO* remoteIO() const noexcept { return comm_; }\n\n  /** Sets the provider for the session context */\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  void set_context_provider(context_provider_t c) { context_provider_ = std::move(c); }\n\n  sdk::User& user() const;\n  SessionContext& sess();\n  SessionContext& sess() const;\n  Context& context();\n\nprotected:\n  local::io::LocalIO* local_io_{nullptr};\n  RemoteIO* comm_{nullptr};\n  mutable context_provider_t context_provider_;\n};\n\n} // namespace wwiv::common\n\n\n#endif\n"
  },
  {
    "path": "common/language.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/language.h\"\n\n#include \"core/inifile.h\"\n\nwwiv::common::Language::Language(const std::filesystem::path& menu_path,\n                                 const std::filesystem::path& gfiles)\n    : mi(menu_path, {\"lang\"}), gi(gfiles, {\"lang\"}) {\n}\n\nstd::string wwiv::common::Language::value(const std::string& key) const {\n  if (auto v = mi.value<std::string>(key); !v.empty()) {\n    return v;\n  }\n  return gi.value<std::string>(key);\n}\n\nstd::string wwiv::common::Language::value(const std::string& key, const std::string& default_value) const {\n  if (auto v = mi.value<std::string>(key); !v.empty()) {\n    return v;\n  }\n  if (auto v = gi.value<std::string>(key); !v.empty()) {\n    return v;\n  }\n  return default_value;\n}\n"
  },
  {
    "path": "common/language.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_LANGUAGE_H\n#define INCLUDED_COMMON_LANGUAGE_H\n\n#include \"core/inifile.h\"\n\n#include <filesystem>\n#include <string>\n\nnamespace  wwiv::common {\n\nclass Language {\npublic:\n  Language(const std::filesystem::path& menu_path, const std::filesystem::path& gfiles);\n  [[nodiscard]] std::string value(const std::string& key) const;\n  [[nodiscard]] std::string value(const std::string& key, const std::string& default_value) const;\n\nprivate:\n  core::IniFile mi;\n  core::IniFile gi;\n};\n\n}\n\n#endif"
  },
  {
    "path": "common/macro_context.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/macro_context.h\"\n\n#include \"common/context.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\ntemplate <typename K>\nstatic bool in(K const& k, std::initializer_list<K> list) {\n  for (const auto& l : list) {\n    if (l == k) {\n      return true;\n    }\n  }\n  return false;\n}\n\nMacroContext::MacroContext(Context* context) : context_(context) {}\n\nInterpreted MacroContext::interpret(std::string::const_iterator& it,\n                                    std::string::const_iterator end) const {  // NOLINT(performance-unnecessary-value-param)\n  Interpreted res{};\n  const auto code = *it++;\n  std::string text;\n  text.push_back(code);\n  switch (code) {\n  case '[': { // movement\n    while (it != end) {\n      if (std::isdigit(*it) || *it == ';') {\n        text.push_back(*it);\n      } else if (in(*it, {'A', 'B', 'C', 'D', 'H', 'J', 'K'})) {\n        text.push_back(*it++);\n        return interpret_string(text);\n      } else {\n        return text;\n      }\n      ++it;\n    }\n    return text;\n  }\n  case '{': { // long form expression\n    if (!context_ || !context_->mci_enabled()) {\n      res.text = \"|{\";\n      return res;\n    }\n\n    while (it != end) {\n      const auto ch = *it++;\n      text.push_back(ch);\n      if (ch == '}') {\n        // TODO(rushfan): Maybe here is where we should handle cases where the expressions\n        // return Pipe codes (like {if \"system.use_realnames\", \"|@N\", \"|@n\"}\n        return evaluate_expression(text);\n      }\n    }\n    return text;\n  }\n  case '@': { // macro\n    res.text = interpret_macro_char(*it++);\n    return res;\n  }\n  case '|': { // pipe char\n    res.text = \"|\";\n    return res;\n  }\n  default:\n    res.text = code;\n    return res;\n  }\n}\n\n}\n\n"
  },
  {
    "path": "common/macro_context.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_MACRO_CONTEXT_H\n#define INCLUDED_COMMON_MACRO_CONTEXT_H\n\n#include <string>\n\nnamespace wwiv::common {\n\nclass Context;\n\nenum class interpreted_cmd_t { text, movement, expression };\nstruct Interpreted {\n  Interpreted(std::string t, interpreted_cmd_t c) : text(std::move(t)), cmd(c) {}\n  // ReSharper disable once CppNonExplicitConvertingConstructor\n  Interpreted(std::string t) : text(std::move(t)) {}\n  Interpreted() = default;\n  int left{0};\n  int right{0};\n  int up{0};\n  int down{0};\n  int x{-1};\n  int y{-1};\n  std::string text;\n  interpreted_cmd_t cmd{interpreted_cmd_t::text};\n  bool cls{false};\n  bool clreol{false};\n  bool clrbol{false};\n  int nl{0};\n  bool needs_reinterpreting{false};\n};\n\n/**\n * Context and interpreter class for MCI codes and friends.\n */\nclass MacroContext {\npublic:\n  explicit MacroContext(Context* context);\n  virtual ~MacroContext() = default;\n\n  // Interprets only a macro code.\n  [[nodiscard]] virtual std::string interpret_macro_char(char c) const = 0;\n  // Interprets a macro, movement or command.\n  // Expects the leading '@', '{', or '[' to be present.\n  [[nodiscard]] virtual Interpreted interpret_string(const std::string&) const = 0;\n  // Executes a Macro's expression.  This is likely to be done only by\n  // the BBS.\n  [[nodiscard]] virtual Interpreted evaluate_expression(const std::string&) const = 0;\n  // Interprets a macro, movement or command.\n  // Expects the leading '@', '{', or '[' to be present.\n  [[nodiscard]] virtual Interpreted interpret(std::string::const_iterator& it,\n                                              std::string::const_iterator end) const;\n  // Context to use when evaluating macros, movements and commands\n  [[nodiscard]] Context* context() const { return context_; }\n\nprotected:\n  Context* context_{nullptr};\n};\n\n} // namespace wwiv::common\n\n#endif // __INCLUDED_BBS_INTERPRET_H__\n"
  },
  {
    "path": "common/menu_data_util_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5.x                            */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/input_range.h\"\n\n#include \"gtest/gtest.h\"\n#include \"common/menus/menu_data_util.h\"\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::common::menus;\nusing namespace testing;\n\nTEST(MenuDataUtil, NoOpts) {\n  menu_data_and_options_t t(\"FILENAME\");\n  EXPECT_EQ(t.data(), \"FILENAME\");\n  EXPECT_TRUE(t.opts_empty());\n}\n\nTEST(MenuDataUtil, OneOpt) {\n  menu_data_and_options_t t(\"filename pause=on\");\n  EXPECT_EQ(t.data(), \"filename\");\n  ASSERT_EQ(1u, t.size());\n  auto o = t.opts(\"pause\");\n  ASSERT_EQ(1u, o.size());\n  EXPECT_EQ(*std::begin(o), \"on\");\n}\n\nTEST(MenuDataUtil, OneOpt_UpperCase) {\n  menu_data_and_options_t t(\"filename PAUSE=ON\");\n  EXPECT_EQ(t.data(), \"filename\");\n  ASSERT_EQ(1u, t.size());\n  auto o = t.opts(\"pause\");\n  ASSERT_EQ(1u, o.size());\n  EXPECT_EQ(*std::begin(o), \"on\");\n}\n\nTEST(MenuDataUtil, TwoOpt) {\n  menu_data_and_options_t t(\"filename pause=on mci=off\");\n  EXPECT_EQ(t.data(), \"filename\");\n  EXPECT_EQ(2u, t.size());\n  auto pause = t.opts(\"pause\");\n  EXPECT_EQ(*std::begin(pause), \"on\");\n  ASSERT_EQ(1u, pause.size());\n\n  auto mci = t.opts(\"mci\");\n  EXPECT_EQ(*std::begin(mci), \"off\");\n  ASSERT_EQ(1u, mci.size());\n}\n\nTEST(MenuDataUtil, TwoOpt_SameKey) {\n  menu_data_and_options_t t(\"filename pause=off pause=end\");\n  EXPECT_EQ(t.data(), \"filename\");\n  EXPECT_EQ(2u, t.size());\n  auto pause = t.opts(\"pause\");\n  EXPECT_EQ(2u, pause.size());\n  auto it = std::begin(pause);\n  EXPECT_EQ(*it++, \"end\");\n  EXPECT_EQ(*it++, \"off\");\n  EXPECT_EQ(std::end(pause), it);\n}\n\nTEST(MenuDataUtil, MissingOpt) {\n  menu_data_and_options_t t(\"filename\");\n  EXPECT_EQ(t.data(), \"filename\");\n  ASSERT_EQ(0u, t.size());\n  auto o = t.opts(\"pause\");\n  ASSERT_TRUE(o.empty());\n}\n\nTEST(MenuDataUtil, Nothing) {\n  menu_data_and_options_t t(\"\");\n  ASSERT_EQ(0u, t.size());\n  auto o = t.opts(\"pause\");\n  ASSERT_TRUE(o.empty());\n}\n"
  },
  {
    "path": "common/menus/menu_data_util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/menus/menu_data_util.h\"\n\n#include \"core/strings.h\"\n\nnamespace wwiv::common::menus {\n\n\nmenu_data_and_options_t::menu_data_and_options_t(const std::string& raw) {\n  const auto idx = raw.find(' ');\n  if (idx == std::string::npos) {\n    data_ = raw;\n    return;\n  }\n  data_ = raw.substr(0, idx);\n  const auto o = raw.substr(idx + 1);\n  const auto v = strings::SplitString(o, \" \");\n  for (const auto& f : v) {\n    if (const auto fidx = f.find('='); fidx != std::string::npos) {\n      auto key = strings::ToStringLowerCase(strings::StringTrim(f.substr(0, fidx))); \n      auto val = strings::ToStringLowerCase(strings::StringTrim(f.substr(fidx + 1))); \n      opts_.emplace(key, val);\n    }\n  }\n}\n\nstd::set<std::string> menu_data_and_options_t::opts(const std::string& key) const {\n  std::set<std::string> r;\n  for (auto [s, e] = opts_.equal_range(key); s != e; ++s) {\n    r.insert(s->second);\n  }\n  return r;\n}\n\nconst std::string& menu_data_and_options_t::data() const {\n  return data_;\n}\n\n}\n"
  },
  {
    "path": "common/menus/menu_data_util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_MENUS_MENU_DATA_UTIL_H\n#define INCLUDED_COMMON_MENUS_MENU_DATA_UTIL_H\n\n#include <map>\n#include <set>\n#include <string>\n\nnamespace wwiv::common::menus {\n\nclass menu_data_and_options_t {\npublic:\n  explicit menu_data_and_options_t(const std::string& raw);\n\n  [[nodiscard]] std::set<std::string> opts(const std::string&) const;\n  [[nodiscard]] const std::string& data() const;\n  [[nodiscard]] auto size() const noexcept { return opts_.size(); }\n  [[nodiscard]] bool opts_empty() const noexcept { return opts_.empty(); }\n  [[nodiscard]] const std::multimap<std::string, std::string>& opts() const { return opts_; }\nprivate:\n  std::string data_;\n  std::multimap<std::string, std::string> opts_;\n};\n\n}\n\n#endif "
  },
  {
    "path": "common/menus/menu_generator.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/menus/menu_generator.h\"\n\n#include \"common/value/uservalueprovider.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/acs/acs.h\"\n#include \"sdk/menus/menu_set.h\"\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::menus;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common::menus {\n\n/**\n * Returns a string to display for a key.\n * Examples:\n *   'A' for a key 'A'\n *   '/A' for a key '/A'\n *   '//KEY' for a key 'KEY'\n */\nstatic std::string display_key(const std::string& item_key) {\n  if (item_key.size() == 1) {\n    return item_key;\n  }\n  if (item_key.size() == 2 && item_key.front() == '/') {\n    return item_key;\n  }\n  if (item_key.size() == 2) {\n    return fmt::format(\"//{}\", item_key);\n  }\n  if (starts_with(item_key, \"//\")) {\n    return item_key;\n  }\n  return fmt::format(\"//{}\", item_key);\n}\n\nstatic std::string generate_menu_item_line(generated_menu_56_t g, const std::string& key,\n                                           const std::string& text, int max_width) {\n  std::ostringstream ss;\n  ss << g.color_item_braces << \"(\" << g.color_item_key << display_key(key) << g.color_item_braces\n     << \")\" << g.color_item_text;\n  if (key.size() == 1 && !text.empty() &&\n      to_upper_case_char(text.front()) == to_upper_case_char(key.front())) {\n    ss << text.substr(1);\n  } else {\n    ss << \" \" << text;\n  }\n  ss << \" \";\n  const auto line = trim_to_size_ignore_colors(ss.str(), max_width);\n  const auto len = size_without_colors(line);\n  return fmt::format(\"{}{}\", line, std::string(max_width - len, ' '));\n}\n\nstatic bool GenerateMenuLine(const Config& config, const menu_item_56_t& mi,\n                             const generated_menu_56_t& g, bool& just_nled,\n                             const std::vector<const wwiv::sdk::value::ValueProvider*>& providers,\n                             menu_type_t typ, int num_cols, int screen_width,\n                             std::ostringstream& ss) {\n  if (mi.item_key.empty()) {\n    return false;\n  }\n  if (auto [result, debug_lines] = acs::check_acs(config, mi.acs, providers); !result) {\n    return false;\n  }\n  if (!g.show_empty_text && StringTrim(mi.item_text).empty()) {\n    return false;\n  }\n  if (!mi.visible) {\n    return false;\n  }\n  just_nled = false;\n  const auto col_width =\n      typ == menu_type_t::short_menu ? screen_width / num_cols : screen_width - 1;\n  const auto key = display_key(mi.item_key);\n  const auto& text = typ == menu_type_t::short_menu ? mi.item_text : mi.help_text;\n  ss << generate_menu_item_line(g, key, text, col_width);\n  return true;\n}\n\n\nstd::vector<std::string> GenerateMenuLines(\n                  const Config& config, const wwiv::sdk::menus::MenuSet56& menu_set,\n                  const menu_56_t& menu, const sdk::User& user,\n                  const std::vector<const wwiv::sdk::value::ValueProvider*>& providers,\n                  menu_type_t typ) {\n  std::vector<std::string> out;\n  out.emplace_back(\"|#0\");\n\n  auto lines_displayed = 0;\n  const auto& g = menu.generated_menu;\n  const auto& title = menu.title;\n  const auto num_cols = typ == menu_type_t::short_menu ? g.num_cols : 1;\n  const auto screen_width = user.screen_width() - num_cols + 1;\n  const auto col_width =\n      typ == menu_type_t::short_menu ? screen_width / num_cols : screen_width - 1;\n  if (!title.empty()) {\n    const auto title_len = size_without_colors(title);\n    const auto pad_len = (screen_width - title_len) / 2;\n    out.emplace_back(fmt::format(\"{}{}{}|#0\", std::string(pad_len, ' '), g.color_title, title));\n  }\n  std::ostringstream ss;\n  if (menu.num_action != menu_numflag_t::none) {\n    ss << generate_menu_item_line(g, \"#\", \"Change Sub/Dir #\", col_width);\n    ++lines_displayed;\n  }\n  auto just_nled = false;\n  for (const auto& mi : menu.items) {\n    if (!GenerateMenuLine(config, mi, g, just_nled, providers, typ, num_cols, screen_width, ss)) {\n      continue;\n    }\n    if (++lines_displayed % num_cols == 0) {\n      out.emplace_back(ss.str());\n      ss.str({});\n      just_nled = true;\n    }\n  }\n\n  std::set<std::string> keys;\n  for (const auto& m : menu.items) {\n    keys.insert(m.item_key);\n  }\n  for (const auto& mi : menu_set.menu_set.items) {\n    if (wwiv::stl::contains(keys, mi.item_key)) {\n      continue;\n    }\n    if (!GenerateMenuLine(config, mi, g, just_nled, providers, typ, num_cols, screen_width, ss)) {\n      continue;\n    }\n    if (++lines_displayed % num_cols == 0) {\n      out.emplace_back(ss.str());\n      ss.str({});\n      just_nled = true;\n    }\n  }\n\n  if (!just_nled) {\n    out.emplace_back(ss.str());\n    ss.str({});\n  }\n  for (auto i = 0; i < g.num_newlines_at_end; i++) {\n    out.emplace_back(\"\");\n  }\n  return out;\n}\n\n} // namespace wwiv::common::menus\n"
  },
  {
    "path": "common/menus/menu_generator.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_MENUS_MENU_GENERATOR_H\n#define INCLUDED_COMMON_MENUS_MENU_GENERATOR_H\n\n#include \"sdk/menus/menu.h\"\n\n#include <map>\n#include <set>\n#include <string>\n\nnamespace wwiv::sdk::value {\nclass ValueProvider;\n}\n\nnamespace wwiv::common::menus {\n\nstd::vector<std::string>\nGenerateMenuLines(const sdk::Config& config,\n                  const wwiv::sdk::menus::MenuSet56& menu_set, const sdk::menus::menu_56_t& menu,\n                  const sdk::User& user, const std::vector<const sdk::value::ValueProvider*>& providers,\n                  sdk::menus::menu_type_t typ);\n\n}\n\n#endif "
  },
  {
    "path": "common/message_editor_data.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2018-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/message_editor_data.h\"\n\n#include \"core/strings.h\"\n#include <string>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nMessageEditorData::MessageEditorData(std::string fn) : from_name(std::move(fn)) {}\n\nbool MessageEditorData::is_email() const { return iequals(aux, \"email\"); }\n\n} // namespace wwiv::common"
  },
  {
    "path": "common/message_editor_data.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_MESSAGE_EDITOR_DATA_H\n#define INCLUDED_COMMON_MESSAGE_EDITOR_DATA_H\n\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::common {\n\nconstexpr int MSGED_FLAG_NONE = 0;\nconstexpr int MSGED_FLAG_NO_TAGLINE = 1;\nconstexpr int MSGED_FLAG_HAS_REPLY_NAME = 2;\nconstexpr int MSGED_FLAG_HAS_REPLY_TITLE = 4;\n\nenum class FsedFlags {\n  NOFSED, \n  FSED,\n  WORKSPACE\n};\n\nclass MessageEditorData {\npublic:\n  explicit MessageEditorData(std::string fn);\n  MessageEditorData() = delete;\n  ~MessageEditorData() = default;\n\n  [[nodiscard]] bool is_email() const;\n\n  // Title to use. If set it will be used without prompting the user.\n  std::string title;\n  std::string to_name;  // szDestination (to or sub name)\n  std::string sub_name;\n  // This should be the username or real name depending on the base. It's\n  // set to the default username in the constructor.\n  std::string from_name;\n\n  bool need_title{true};\n  uint8_t anonymous_flag{0};   // an\n  int msged_flags{MSGED_FLAG_NONE};      // used to be flags\n  FsedFlags fsed_flags{FsedFlags::NOFSED};       // fsed\n  bool silent_mode{false};     // Used for ASV and new email emails.  No questions, etc.\n\n  // legacy filename, used to see if it's email or not.\n  std::string aux;\n\n  // output only\n  std::string text;\n};\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/null_remote_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/null_remote_io.h\"\n#include \"common/remote_io.h\"\n#include \"local_io/local_io.h\"\n\nnamespace wwiv::common {\n\nstd::optional<ScreenPos> NullRemoteIO::screen_position() { \n  if (!local_io_) {\n    return std::nullopt;  \n  }\n  auto x = local_io_->WhereX() + 1;\n  auto y = local_io_->WhereY() + 1;\n  return {ScreenPos{x, y}};\n}\n\n} // namespace wwiv::comon\n"
  },
  {
    "path": "common/null_remote_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_COMMON_NULL_REMOTE_IO_H\n#define INCLUDED_COMMON_NULL_REMOTE_IO_H\n\n#include \"common/remote_io.h\"\n\nnamespace wwiv::local::io {\nclass LocalIO;\n}\n\nnamespace wwiv::common {\n\n/** Null remote session. */\n/**\n * Base Communication Class.\n */\nclass NullRemoteIO final : public RemoteIO {\npublic:\n  NullRemoteIO(wwiv::local::io::LocalIO* local_io) : RemoteIO(), local_io_(local_io) {}\n  virtual ~NullRemoteIO() {}\n\n  // Nothing is always able to be open.\n  bool open() override { return true; }\n  void close(bool) override {}\n  unsigned char getW() override { return 0; }\n  bool disconnect() override { return true; }\n  void purgeIn() override {}\n  unsigned int put(unsigned char) override { return 0; }\n  unsigned int read(char*, unsigned int) override { return 0; }\n  unsigned int write(const char*, unsigned int, bool) override { return 0; }\n  bool connected() override { return false; }\n  bool incoming() override { return false; }\n\n  unsigned int GetHandle() const override { return 0; }\n  std::optional<ScreenPos> screen_position() override;\n\nprivate:\n  wwiv::local::io::LocalIO* local_io_;\n};\n\n} // namespace wwiv::comon \n\n#endif\n"
  },
  {
    "path": "common/output.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/output.h\"\n\n#include \"common/common_events.h\"\n#include \"common/input.h\"\n#include \"common/macro_context.h\"\n#include \"core/eventbus.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/ansi/ansi.h\"\n#include \"sdk/ansi/localio_screen.h\"\n#include \"sdk/ansi/makeansi.h\"\n#include <algorithm>\n#include <cctype>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::common;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::ansi;\n\n// static global \"bout\"\nOutput bout;\n\nstatic constexpr char BBS_STR_INI[] = \"bbs.str.ini\";\n\nOutput::Output() = default;\n\nLanguage& Output::lang() {\n  if (!lang_) {\n    auto mi = wwiv::core::FilePath(context().session_context().dirs().current_menu_directory(),\n                                   BBS_STR_INI);\n    auto gi =\n        wwiv::core::FilePath(context().session_context().dirs().gfiles_directory(), BBS_STR_INI);\n    lang_ = std::make_unique<Language>(mi, gi);\n  }\n  DCHECK(lang_);\n  return *lang_;\n}\n\nOutput::~Output() = default;\n\nstatic bool okansi(const wwiv::sdk::User& user) {\n  return user.ansi();\n}\n\nvoid Output::SetLocalIO(LocalIO* local_io) {\n  // We would use user().screen_width() but I don't think we\n  // have a live user when we create this.\n  screen_ = std::make_unique<LocalIOScreen>(local_io, 80);\n  AnsiCallbacks cb;\n  cb.move_ = [&](int /* x */, int /* y */) { ansi_movement_occurred_ = true; };\n  ansi_ = std::make_unique<Ansi>(screen_.get(), cb, static_cast<uint8_t>(0x07));\n\n  IOBase::SetLocalIO(local_io);\n  // Reset the curatr_provider on local_io since screen resets it.\n  localIO()->set_curatr_provider(this);\n\n  // This is kinda a hack to do it here, but the constructor is too early.  By\n  // this point the system is started up, bout created, and also all other global\n  // static objects have been constructed.\n  // If this is a problem, we can make a new method to do this and have the bbs,\n  // fsed, etc all call it after setting the LocalIO.\n  core::bus().add_handler<UpdateMenuSet>([this](const UpdateMenuSet& u) {\n    if (current_menu_set_ != u.name) {\n      current_menu_set_ = u.name;\n      // Reload language support.\n      auto mi = core::FilePath(context().session_context().dirs().current_menu_directory(),\n                               BBS_STR_INI);\n      auto gi = core::FilePath(context().session_context().dirs().gfiles_directory(),\n                               BBS_STR_INI);\n      lang_ = std::make_unique<Language>(mi, gi);\n    }\n  });\n}\n\nvoid Output::ansic(int wwiv_color) {\n  const auto saved_x{x_};\n  outstr(MakeColor(wwiv_color));\n  x_ = saved_x;\n}\n\nvoid Output::ResetColors() {\n  const auto saved_x{x_};\n  // ANSI Clear Attributes String\n  outstr(\"\\x1b[0m\");\n  x_ = saved_x;\n}\n\nvoid Output::goxy(int x, int y) {\n  if (okansi(user())) {\n    // Don't get Y get too big or mTelnet will not be happy\n    y = std::min<int>(y, sess().num_screen_lines());\n    outstr(StrCat(\"\\x1b[\", y, \";\", x, \"H\"));\n  }\n  x_ = x;\n}\n\nvoid Output::Up(int num) {\n  if (num == 0) {\n    return;\n  }\n  std::ostringstream ss;\n  ss << \"\\x1b[\";\n  if (num > 1) {\n    ss << num;\n  }\n  ss << \"A\";\n  outstr(ss.str());\n}\n\nvoid Output::Down(int num) {\n  if (num == 0) {\n    return;\n  }\n  std::ostringstream ss;\n  ss << \"\\x1b[\";\n  if (num > 1) {\n    ss << num;\n  }\n  ss << \"B\";\n  outstr(ss.str());\n}\n\nvoid Output::Left(int num) {\n  const auto saved_x = x_;\n  if (num == 0) {\n    return;\n  }\n  std::ostringstream ss;\n  ss << \"\\x1b[\";\n  if (num > 1) {\n    ss << num;\n  }\n  ss << \"D\";\n  outstr(ss.str());\n  x_ = std::max<int>(0, saved_x - num);\n}\n\nvoid Output::Right(int num) {\n  const auto saved_x{x_};\n  if (num == 0) {\n    return;\n  }\n  std::ostringstream ss;\n  ss << \"\\x1b[\";\n  if (num > 1) {\n    ss << num;\n  }\n  ss << \"C\";\n  outstr(ss.str());\n  x_ = std::max<int>(0, saved_x + num);\n\n}\n\nvoid Output::SavePosition() {\n  outstr(\"\\x1b[s\");\n}\n\nvoid Output::RestorePosition() {\n  outstr(\"\\x1b[u\");\n}\n\nvoid Output::nl(int num_lines) {\n  if (num_lines == 0) {\n    return;\n  }\n  for (auto i = 0; i < num_lines; i++) {\n    outstr(\"\\r\\n\");\n    core::bus().invoke(ProcessInstanceMessages{});\n  }\n  x_ = 1;\n}\n\nvoid Output::bs() {\n  if (okansi(user())) {\n    Left(1);\n    outchr(' ');\n    Left(1);\n  } else {\n    outstr(\"\\b \\b\");\n  }\n}\n\n\nvoid Output::setc(wwiv::sdk::Color c) {\n  setc(static_cast<uint8_t>(c));\n}\n\nvoid Output::setc(int c) {\n  outstr(MakeSystemColor(c));\n}\n\nstd::string Output::MakeColor(int wwiv_color) {\n  const auto c = user().color(wwiv_color);\n  if (c == curatr()) {\n    return \"\";\n  }\n\n  needs_color_reset_at_newline_ = true;\n  return MakeSystemColor(c);\n}\n\nstd::string Output::MakeSystemColor(int c) const {\n  if (!okansi(user())) {\n    return \"\";\n  }\n  return makeansi(c, curatr());\n}\n\nstd::string Output::MakeSystemColor(sdk::Color color) const {\n  return MakeSystemColor(static_cast<uint8_t>(color));\n}\n\nvoid Output::litebar(const std::string& msg) {\n  const auto len = user().screen_width() - 2;\n  if (okansi(user())) {\n    outstr(fmt::format(\"|17|15 {:<{}}|#0\\r\\n\\n\", msg, len));\n  }\n  else {\n    print(\"|#5 {}|#0\\r\\n\\n\", msg);\n  }\n}\n\nvoid Output::backline() {\n  ansic(0);\n  outchr(SPACE);\n  for (auto i = wherex() + 1; i >= 0; i--) {\n    this->bs();\n  }\n}\n\n/**\n * Clears the local and remote screen using ANSI (if enabled), otherwise DEC 12\n */\nvoid Output::cls() {\n  // Adding color 0 so previous color would not be picked up. #1245\n  ansic(0);  \n  if (okansi(user())) {\n    outstr(\"\\x1b[2J\");\n    goxy(1, 1);\n  } else {\n    outchr(CL);\n  }\n  clear_lines_listed();\n}\n\n/**\n * Clears the current line to the end.\n */\nvoid Output::clreol(int ct) {\n  const auto saved_x{x_};\n  if (okansi(user())) {\n    if (ct == 0) {\n      outstr(\"\\x1b[K\");\n    } else {\n      print(\"\\x1b[{}K\", ct);\n    }\n  }\n  x_ = saved_x;\n}\n\nvoid Output::clear_whole_line() {\n  outchr('\\r');\n  clreol();\n}\n\nvoid Output::mpl(int length) {\n  if (!okansi(user())) {\n    return;\n  }\n  ansic(4);\n  outstr(std::string(length, ' '));\n  Left(length);\n}\n\nint Output::PutsXY(int x, int y, const std::string& text) {\n  goxy(x, y);\n  return outstr(text);\n}\n\nint Output::PutsXYSC(int x, int y, int a, const std::string& text) {\n  goxy(x, y);\n  setc(a);\n  return outstr(text);\n}\n\nint Output::PutsXYA(int x, int y, int color, const std::string& text) {\n  goxy(x, y);\n  ansic(color);\n  return outstr(text);\n}\n\nvoid Output::do_movement(const Interpreted& r) {\n  if (r.left) {\n    Left(r.left);\n  }\n  if (r.right) {\n    Right(r.right);\n  }\n  if (r.up) {\n    Up(r.up);\n  }\n  if (r.down) {\n    Down(r.down);\n  }\n  if (r.x != -1 && r.y != -1) {\n    goxy(r.x, r.y);\n  }\n  if (r.clreol) {\n    clreol();\n  }\n  if (r.clrbol) {\n    clreol();\n  }\n  if (r.cls) {\n    cls();\n  }\n  if (r.nl) {\n    nl(r.nl);\n  }\n}\n\ntemplate <typename T>\nstatic int pipecode_int(T& it, const T end, int num_chars) {\n  std::string s;\n  while (it != end && num_chars-- > 0 && std::isdigit(static_cast<uint8_t>(*it))) {\n    s.push_back(*it);\n    ++it; \n  }\n  return to_number<int>(s);\n}\n\nint Output::pl(const std::string& text) {\n  const auto ret = outstr(text);\n  nl();\n  return ret;\n}\n\nint Output::outstr(const std::string& text) {\n  core::bus().invoke<CheckForHangupEvent>();\n  if (text.empty() || sess().hangup()) {\n    return 0;\n  }\n  auto& ctx = macro_context_provider_();\n\n  auto it = std::cbegin(text);\n  const auto fin = std::cend(text);\n  const auto start_time = system_clock::now();\n  auto num_written = 0;\n  const auto cps = sess().bps() / 10;\n  while (it != fin) {\n    if (cps > 0) {\n      while (duration_cast<milliseconds>(system_clock::now() - start_time).count() <\n             (num_written * 1000 / cps)) {\n        flush();\n        os::sleep_for(milliseconds(10));\n      }\n    }\n\n    // pipe codes.\n    if (*it == '|') {\n      ++it;\n      if (it == fin) {\n        num_written += outchr('|', true);\n        break;\n      }\n      if (std::isdigit(*it)) {\n        if (const auto color = pipecode_int(it, fin, 2); color < 16) {\n          setc(color | (curatr() & 0xf0));\n        } else {\n          const auto bg = static_cast<uint8_t>(color << 4);\n          const uint8_t fg = curatr() & 0x0f;\n          setc(bg | fg);\n        }\n      } else if (*it == '@' || *it == '{' || *it == '[') {\n        if (auto r = ctx.interpret(it, fin); r.cmd == interpreted_cmd_t::text) {\n          // Don't use bout here since we can loop.\n          if (r.needs_reinterpreting) {\n            num_written += outstr(r.text);\n          } else {\n            for (const auto rich : r.text) {\n              num_written += outchr(rich, true);\n            }\n          }\n        } else if (r.cmd == interpreted_cmd_t::movement) {\n          do_movement(r);\n        }\n      } else if (*it == '#') {\n        ++it;\n        const auto color = pipecode_int(it, fin, 1);\n        ansic(color);\n      } else {\n        num_written += outchr('|', true);\n      }\n    }\n    else if (*it == CC) {\n      ++it;\n      if (it == fin) {\n        num_written += outchr(CC, true);\n        break;\n      }\n      if (const unsigned char c = *it++; c >= SPACE && c <= 126) {\n        ansic(c-'0');\n      }\n    }\n    else if (*it == CO) {\n      ++it;\n      if (it == fin) {\n        num_written += outchr(CO, true);\n        break;\n      }\n      ++it;\n      if (it == fin) {\n        num_written += outchr(CO, true);\n        break;\n      }\n      auto s = ctx.interpret_macro_char(*it++);\n      num_written += outstr(s);\n    } else if (it == fin) { \n      break; \n    }\n    else { \n      num_written += outchr(*it++, true);\n    }\n  }\n\n  flush();\n  return num_written;\n}\n\n// This one does a newline.  Since it used to be pla. Should make\n// it consistent.\nint Output::bpla(const std::string& text, bool *abort) {\n  bool dummy;\n  const auto ret = outstr(text, abort, &dummy);\n  if (!bin.checka(abort, &dummy)) {\n    nl();\n  }\n  return ret;\n}\n\n// This one doesn't do a newline. (used to be osan)\nint Output::outstr(const std::string& text, bool *abort, bool *next) {\n  core::bus().invoke<CheckForHangupEvent>();\n  if (bin.checka(abort, next)) {\n    return 0;\n  }\n  return outstr(text);\n}\n\nvoid Output::move_up_if_newline(int num_lines) {\n  if (okansi(user()) && !newline) {\n    Up(num_lines);\n  }\n}\n\n/**\n * Displays the text in the strings file referred to by key.\n */\nint Output::str(const std::string& key) {\n  // Process arguments\n  const auto format_str = lang().value(key);\n  return outstr(format_str);\n}\n\nvoid Output::back_outstr(const std::string& text, int color, duration<double> char_dly, duration<double> string_dly) {\n  ansic(color);\n  sleep_for(char_dly);\n  for (const auto ch : text) {\n    outchr(ch);\n    sleep_for(char_dly);\n  }\n\n  sleep_for(string_dly);\n  for (int i = 0; i < stl::size_int(text); i++) {\n    bs();\n    sleep_for(5ms);\n  }  \n}\n\nvoid Output::rainbow(const std::string& text) {\n  int c = 0;\n  for (char ch : text) {\n    ansic(c++);\n    outchr(ch, true);\n    c %= 8;\n  }\n  flush();\n}\n\nvoid Output::spin_outstr(const std::string& text, int color) {\n  if (!okansi(user())) {\n    outstr(text);\n    return;\n  }\n  ansic(color);\n  const auto dly = milliseconds(30);\n  for (const auto ch : text) {\n    sleep_for(dly);\n    outchr('/', false);\n    Left(1);\n    sleep_for(dly);\n    outchr('-', false);\n    Left(1);\n    sleep_for(dly);\n    outchr('\\\\', false);\n    Left(1);\n    sleep_for(dly);\n    outchr('|', false);\n    Left(1);\n    sleep_for(dly);\n    outchr(ch);\n  }\n}\n\n/**\n * This function outoutstr one character to the screen, and if output to the\n * com port is enabled, the character is output there too.  ANSI graphics\n * are also trapped here, and the ansi function is called to execute the\n * ANSI codes\n */\nint Output::outchr(char c, bool use_buffer) {\n  int displayed = 0;\n\n  if (c == SOFTRETURN && needs_color_reset_at_newline_) {\n    ansic(0);\n    needs_color_reset_at_newline_ = false;\n  }\n\n  if (sess().outcom() && c != TAB) {\n    if (c == SOFTRETURN) {\n#ifdef __unix__\n      rputch('\\r', use_buffer);\n#endif  // __unix__\n      rputch('\\n', use_buffer);\n    } else {\n      rputch(c, use_buffer);\n    }\n    displayed = 1;\n  }\n  if (c == TAB) {\n    const auto screen_pos = wherex();\n    for (auto i = screen_pos; i < (((screen_pos / 8) + 1) * 8); i++) {\n      displayed += outchr(SPACE);\n    }\n  } else {\n    displayed = 1;\n    // Pass through to SDK ansi interpreter.\n    const auto last_state = ansi_->state();\n    ansi_->write(c);\n\n    if (ansi_->state() == wwiv::sdk::ansi::AnsiMode::not_in_sequence &&\n        last_state == wwiv::sdk::ansi::AnsiMode::not_in_sequence) {\n      // Only add to the current line if we're not in an ansi sequence.\n      // Otherwise we get gibberish ansi strings that will be displayed\n      // raw to the user.\n      current_line_.emplace_back(c, static_cast<uint8_t>(curatr()));\n    }\n\n    const auto screen_width = user().screen_width();\n    if (c == BACKSPACE) {\n      --x_;  \n      if (x_ < 0) {\n        x_ = screen_width - 1;\n      }\n    } else {\n      ++x_;\n    }\n    // Wrap at screen_width\n    if (x_ >= static_cast<int>(screen_width)) {\n      x_ %= screen_width;\n    }\n    if (c == '\\r') {\n      x_ = 0;\n    }\n    if (c == SOFTRETURN) {\n      current_line_.clear();\n      x_ = 0;\n      lines_listed_++;\n      // change Build3 + 5.0 to fix message read.\n      const auto ll = lines_listed();\n      if (const auto num_sclines = sess().num_screen_lines() - 1; ll >= num_sclines) {\n        if (user().pause()) {\n          bout.pausescr();\n        }\n        bout.clear_lines_listed();   // change Build3\n      }\n    }\n  }\n\n  return displayed;\n}\n\n\n/* This function outoutstr a string to the com port.  This is mainly used\n * for modem commands\n */\nvoid Output::rputs(const std::string& text) {\n  // Rushfan fix for COM/IP weirdness\n  if (sess().ok_modem_stuff()) {\n    remoteIO()->write(text.c_str(), wwiv::stl::size_int(text));\n  }\n}\n\nvoid Output::flush() {\n  if (!outchr_buffer_.empty()) {\n    remoteIO()->write(outchr_buffer_.c_str(), stl::size_int(outchr_buffer_));\n    outchr_buffer_.clear();\n  }\n}\n\nvoid Output::rputch(char ch, bool use_buffer_) {\n  if (!sess().ok_modem_stuff() || remoteIO() == nullptr) {\n    return;\n  }\n  if (use_buffer_) {\n    if (outchr_buffer_.size() > 1024) {\n      flush();\n    }\n    outchr_buffer_.push_back(ch);\n  } else if (!outchr_buffer_.empty()) {\n    // If we have stuff in the buffer, and now are asked\n    // to send an unbuffered character, we must send the\n    // contents of the buffer 1st.\n    outchr_buffer_.push_back(ch);\n    flush();\n  }\n  else {\n    remoteIO()->put(ch);\n  }\n}\n\n"
  },
  {
    "path": "common/output.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_OUTPUT_H\n#define INCLUDED_COMMON_OUTPUT_H\n\n#include \"common/iobase.h\"\n#include \"common/language.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/curatr_provider.h\"\n#include \"sdk/wwivcolors.h\"\n#include <memory>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk::ansi {\nclass Ansi;\nclass LocalIOScreen;\n}\n\nnamespace wwiv::common {\nstruct Interpreted;\n\nclass MacroContext;\n\n\ntypedef std::basic_ostream<char>&(ENDL_TYPE_O)(std::basic_ostream<char>&);\n\nclass SavedLine {\npublic:\n  SavedLine(std::vector<std::pair<char, uint8_t>> l, int c) : line(std::move(l)), color(c) {}\n  std::vector<std::pair<char, uint8_t>> line;\n  int color;\n};\n\n/**\n * Creates the Output class responsible for displaying information both\n * locally and remotely.\n *\n * To use this class you must set the following:\n * - LocalIO\n * - RemoteIO\n * - Context Provider\n * - User Provider\n * [Optional] Instance Message Processor.\n *\n * These may be modified after being set, so RAII does not work.\n */\nclass Output final : public local::io::curatr_provider, public IOBase {\npublic:\n  typedef std::function<MacroContext&()> macro_context_provider_t;\n  Output();\n  Output(const Output&) = delete;\n  Output(Output&&) = delete;\n  Output& operator=(const Output&) = delete;\n  Output& operator=(Output&&) = delete;\n  ~Output() override;\n\n  /** Sets the LocalIO instance to use locally for output */\n  void SetLocalIO(local::io::LocalIO* local_io) override;\n\n  /** Sets the provider for the session context */\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  void set_macro_context_provider(macro_context_provider_t c) { macro_context_provider_ = std::move(c); }\n\n  /**\n   * This sets the current color (both locally and remotely) to that\n   * specified (in WWIV format).\n   */\n  void ansic(int wwiv_color);\n\n  /** Resets all ANSI color attributes back to the default gray on black. */\n  void ResetColors();\n\n  /** Moves the cursor position to x, y.  Note this is 1 based, not 0. */\n  void goxy(int x, int y);\n  void Up(int num);\n  void Down(int num);\n  void Left(int num);\n  void Right(int num);\n  void SavePosition();\n  void RestorePosition();\n  void nl(int num_lines = 1);\n  void bs();\n\n  /**\n   * This sets the current color (both locally and remotely) to that\n   * specified (in IBM format).\n   */\n  void setc(int c);\n  /**\n   * This sets the current color (both locally and remotely) to that\n   * specified (in IBM format).\n   */\n  void setc(wwiv::sdk::Color color);\n  [[nodiscard]] std::string MakeColor(int wwiv_color);\n  [[nodiscard]] std::string MakeSystemColor(int c) const;\n  [[nodiscard]] std::string MakeSystemColor(sdk::Color color) const;\n\n  /** Displays msg in a light bar header. */\n  void litebar(const std::string& msg);\n\n  /** Backspaces from the current cursor position to the beginning of a line */\n  void backline();\n\n  /**\n   * Clears from the cursor to the end of the line using ANSI sequences.  If the user\n   * does not have ansi, this this function does nothing.\n   */\n  void clreol(int ct = 0);\n\n  /**\n   * Moves the cursor to the beginning of the line and clears the whole like.\n   * If the user does not have ansi, this this function does nothing.\n   */\n  void clear_whole_line();\n\n  /**\n   * Clears the local and remote screen using ANSI (if enabled), otherwise DEC 12\n   */\n  void cls();\n\n  /**\n   * This will make a reverse-video prompt line i characters long, repositioning\n   * the cursor at the beginning of the input prompt area.  Of course, if the\n   * user does not want ansi, this routine does nothing.\n   */\n  void mpl(int length);\n\n  /**\n   * Writes text at position (x, y) using the current color.\n   *\n   * Note that x and y are zero based and (0, 0) is the top left corner of the screen.\n   *\n   * Returns the number of characters displayed.\n   */\n  int PutsXY(int x, int y, const std::string& text);\n\n  /**\n   * Writes text at position (x, y) using the system color attribute specified by a.\n   *\n   * Note that x and y are zero based and (0, 0) is the top left corner of the screen.\n   *\n   * Returns the number of characters displayed.\n   */\n  int PutsXYSC(int x, int y, int a, const std::string& text);\n\n  /**\n   * Writes text at position (x, y) using the user color specified by color.\n   *\n   * Note that x and y are zero based and (0, 0) is the top left corner of the screen.\n   *\n   * Returns the number of characters displayed.\n   */\n  int PutsXYA(int x, int y, int color, const std::string& text);\n\n  /**\n   * Executes the movement commands (up, down, left, right) specified by r.\n   */\n  void do_movement(const Interpreted& r);\n\n  /**\n   * This function outoutstr a string of characters to the screen (and remotely\n   * if applicable).  The com port is also checked first to see if a remote\n   * user has hung up.  Returns the number of characters displayed.\n   */\n  int outstr(const std::string& text);\n\n  /**\n   * This function outoutstr a string of characters to the screen (and remotely if applicable) \n   * and follows with a newline.  The com port is also checked first to see if a remote user \n   * has hung up.  Returns the number of characters displayed.\n   */\n  int pl(const std::string& text);\n\n  // Prints an abort-able string (contained in *text). Returns 1 in *abort if the\n  // string was aborted, else *abort should be zero.\n  int bpla(const std::string& text, bool* abort);\n\n  /**\n   * Displays s which checking for abort and next\n   * @see checka\n   * Note: bout.outstr means \"Output String And Next\".\n   *\n   * @param text The text to display\n   * @param abort The abort flag (Output Parameter)\n   * @param next The next flag (Output Parameter)\n   */\n  int outstr(const std::string& text, bool* abort, bool* next);\n\n  template <class... Args> int printf(const char* format_str, Args&&... args) {\n    // Process arguments\n    return outstr(fmt::sprintf(format_str, std::forward<Args>(args)...));\n  }\n\n  template <typename... Args> int print(const char* format_str, Args&&... args) {\n    // Process arguments\n    try {\n      return outstr(fmt::format(format_str, args...));\n    } catch (const fmt::format_error& e) {\n      LOG(ERROR) << \"caught fmt::format_error\" << e.what();\n      LOG(ERROR) << \"fmt::format_error original string: '\" << format_str << \"'\";\n      DLOG(FATAL) << \"bout.print crash\";\n    }\n    return outstr(format_str);\n  }\n\n  /**\n   * Displays the text in the strings file referred to by key.\n   */\n  int str(const std::string& key);\n\n  /**\n   * Displays text slowly coming out of a spinning wheel using\n   * {@code}\n   * | / - \\ | - \\ - /\n   * {@endcode}\n   */\n  void spin_outstr(const std::string& text, int color);\n\n  /**\n   * This function prints out a string, with a user-specifiable delay between\n   * each character, and a user-definable pause after the entire string has\n   * been printed, then it backspaces the string. The color is also definable.\n   * The parameters are as follows:\n   * \n   * Note: ANSI is not required.\n   * \n   * Example:\n   * \n   * back_outstr(\"This is an example.\", 3, 20ms, 500ms);\n   *\n   * @param[in] text:       The string to print\n   * @param[in] color:      The color of the string\n   * @param[in] char_dly:   Delay between each character, in milliseconds\n   * @param[in] string_dly: Delay between completion of string and backspacing\n   */\n  void back_outstr(const std::string& text, int color, std::chrono::duration<double> char_dly, std::chrono::duration<double> string_dly);\n\n  /**\n   * Displays the text using a rainbow effect, cycling through the 1st 8 colors.\n   */\n  void rainbow(const std::string& text);\n\n  /**\n   * Displays the text in the \"strings file\" referred to by key adding all\n   * key/value pairs from 'map' into the unnamed context.\n   * \n   * @param[in] key:     The key into the string file to locate the text to display\n   * @param[in] map:     The map of replacable parameters to display using the pipe code \n   *                     variables.  for example to display a variable \"foo\", use: \"|{foo}\"\n   */\n  int str(const std::string& key, const std::map<std::string, std::string>& map) {\n    // Process arguments\n    const auto format_str = lang().value(key);\n    if (!map.empty()) {\n      context().add_context_variable(\"\", map);\n    }\n    const int r = outstr(format_str);\n    context().remove_context_variable(\"\");\n    return r;\n  }\n\n  int outchr(char c, bool use_buffer = false);\n\n  /**\n   * Writes any remaining buffered text remotely.\n   */\n  void flush();\n\n  /**\n   * writes a character remotely only, optionally buffering it possible.\n   */\n  void rputch(char ch, bool use_buffer = false);\n\n  /**\n   * Writes a string remotely only.\n   */\n  void rputs(const std::string& text);\n\n  /**\n   * Redraws the line to the screen.\n   */\n  bool RestoreCurrentLine(const SavedLine& line);\n\n  /**\n   * Saves the current line and returns it.\n   */\n  SavedLine SaveCurrentLine() const;\n\n  /**\n   * Purges the inbound buffer of any unprocessed characters.\n   */\n  void dump();\n\n  /** Clears the number of lines displayed since last pause */\n  void clear_lines_listed() { lines_listed_ = 0; }\n\n  /** Gets the number of lines displayed since last pause */\n  [[nodiscard]] int lines_listed() const noexcept { return lines_listed_; }\n\n  /** Sets the number of lines displayed since last pause */\n  void lines_listed(int l) { lines_listed_ = l; }\n\n  /** Returns the current x position according to a best guess */\n  int wherex() const;\n\n  /** Redraws the current line */\n  void RedrawCurrentLine();\n\n  // ANSI helpers.\n  void move_up_if_newline(int num_lines);\n\n  // ANSI movement happened.\n  [[nodiscard]] bool ansi_movement_occurred() const noexcept { return ansi_movement_occurred_; }\n  void clear_ansi_movement_occurred() { ansi_movement_occurred_ = false; }\n\n  // curatr_provider\n  [[nodiscard]] uint8_t curatr() const noexcept override { return curatr_; }\n  void curatr(int n) override { curatr_ = static_cast<uint8_t>(n); }\n\n  // reset the state of Output\n  void reset();\n\n  //\n  // Handles enabling, disabling, and status of MCI/pipe expressions.\n  //\n  [[nodiscard]] bool mci_enabled() const noexcept { return mci_enabled_; }\n  void enable_mci() { mci_enabled_ = true; }\n  void disable_mci() { mci_enabled_ = false; }\n  void set_mci_enabled(bool e) { mci_enabled_ = e; }\n\n  /** Pause output, displaying the [PAUSE] message, and wait a key to be hit. */\n  void pausescr();\n\n  //\n  // PrintFile and friends.  Used to display a file (msg/ans/b&w/etc).\n  //\n\n /**\n   * Displays a file locally, meaning it pauses at the end.  In the future this\n   * could use LIST.COM or spawn some other viewer program (it used to on dos)\n   * \n   * @param[in] data: The filename, optionally without extension and `data` options to display.\n   *                  See menu_data_and_options_t for more information on the options.\n   */\n  void print_local_file(const std::string& data);\n\n /**\n   * Displays a file from either the menu set, language dir, or root gfiles directory, allowing\n   * for options such pause or speed.\n   * \n   * Example: `FOO BPS=2400`\n   *\n   * @param[in] data: The filename, optionally without extension and `data` options to display. \n   *                  See menu_data_and_options_t for more information on the options. \n   * @param[in] abortable: If `true` a caller can press a key to stop display.\n   * @param[in] force_pause: pause on screen even when ansi movement would have caused\n   *                         no pause to occur.\n   */\n  bool printfile(const std::string& data, bool abortable = true, bool force_pause = true);\n\n /**\n   * Displays the file using the full path to locate it.\n   *\n   * Example: `/opt/wwiv/gfiles/foo.msg`\n   *\n   * @param[in] path: The full file path to display including both directory and file extension.\n   * @param[in] abortable: If `true` a caller can press a key to stop display.\n   * @param[in] force_pause: pause on screen even when ansi movement would have caused\n   *                         no pause to occur.\n   */\n  bool printfile_path(const std::filesystem::path& file_path, bool abortable = true,\n                      bool force_pause = true);\n\n  /**\n   * Displays a help file or an error that no help is available. A help file is a normal \n   * file displayed with printfile.\n   * \n   * @param[in] filename: The file name, optionally without extension, to display.\n   */\n  bool print_help_file(const std::string& filename);\n\n\n  /**\n   * Displays a random file from either the menu set, language dir, or root gfiles \n   * directory, allowing for options such pause or speed.\n   * \n   * A random file has an extension of \".0\" through \".999\" instead of `.ans`\n   *\n   * Example: `FOO BPS=2400`\n   *\n   * @param[in] data: The base filename (without extension) and `data` options to display.\n   *                  See menu_data_and_options_t for more information on the options.\n   */\n  bool printfile_random(const std::string& data);\n\n  /** Gets the current language instance. */\n  [[nodiscard]] Language& lang();\n\n  bool newline{true};\n\nprivate:\n  int lines_listed_{0};\n  char GetKeyForPause();\n\n  // This will pause output without ANSI, displaying the [PAUSE] message, and wait a key to be hit.\n  // in pause.cpp\n  void pausescr_noansi();\n\n  std::string outchr_buffer_;\n  std::vector<std::pair<char, uint8_t>> current_line_;\n  int x_{0};\n  // Means we need to reset the color before displaying our\n  // next newline character.\n  bool needs_color_reset_at_newline_{false};\n\n  bool ansi_movement_occurred_{false};\n  uint8_t curatr_{7};\n  bool mci_enabled_{true};\n  std::unique_ptr<sdk::ansi::LocalIOScreen> screen_;\n  std::unique_ptr<sdk::ansi::Ansi> ansi_;\n  mutable macro_context_provider_t macro_context_provider_;\n  std::string current_menu_set_;\n  std::unique_ptr<Language> lang_;\n};\n\n} // namespace wwiv::common \n\n// Extern for everyone else.\nextern wwiv::common::Output bout;\n\n#endif"
  },
  {
    "path": "common/pause.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/pause.h\"\n\n#include \"common/common_events.h\"\n#include \"common/context.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/eventbus.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include <chrono>\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nTempDisablePause::TempDisablePause(Output& out)\n    : Transaction([&out] {\n    if (out.sess().disable_pause()) {\n      out.sess().disable_pause(false);\n      out.user().set_flag(User::pauseOnPage);\n    }\n  }, nullptr) {\n  if (out.user().pause()) {\n    out.sess().disable_pause(true);\n    out.user().clear_flag(User::pauseOnPage);\n  }\n}\n\nchar Output::GetKeyForPause() {\n  char ch = 0;\n  while (ch == 0 && !sess().hangup()) {\n    ch = bin.bgetch();\n    sleep_for(milliseconds(50));\n    bus().invoke<CheckForHangupEvent>();\n  }\n  const auto k = to_upper_case<int>(ch);\n  switch (k) {\n  case ESC:\n  case 'Q':\n  case 'N':\n    if (!bin.bkbhit()) {\n      bin.nsp(-1);\n    }\n    break;\n  case 'C':\n  case '=':\n    if (user().pause()) {\n      bin.nsp(1);\n      user().toggle_flag(User::pauseOnPage);\n    }\n    break;\n  default:\n    break;\n  }\n\n  dump();\n  return ch;\n}\n\nstatic bool okansi(const User& user) { return user.ansi(); }\n\nvoid Output::pausescr_noansi() {\n  const auto str_pause = bout.lang().value(\"PAUSE\", \"|#3More? [Y/n/c]\"); \n  const auto stripped_size = ssize(stripcolors(str_pause));\n  outstr(str_pause);\n  GetKeyForPause();\n  for (auto i = 0; i < stripped_size; i++) {\n    bs();\n  }\n}\n\nvoid Output::pausescr() {\n  const auto saved_curatr = curatr();\n  bin.clearnsp();\n  bus().invoke<PauseProcessingInstanceMessages>();\n  auto at_exit = finally(\n      [] { wwiv::core::bus().invoke<ResetProcessingInstanceMessages>(); });\n  if (!okansi(user())) {\n    pausescr_noansi();\n    return;\n  }\n\n  if (!sess().incom() && sess().outcom()) {\n    sess().incom(true);\n  }\n\n  const auto str_pause = bout.lang().value(\"PAUSE\", \"|#3More? [Y/n/c]\"); \n  ResetColors();\n\n  const auto stripped_size = ssize(stripcolors(str_pause));\n  const auto com_freeze = sess().incom();\n  outstr(str_pause);\n  Left(stripped_size);\n  setc(saved_curatr);\n\n  const auto tstart = time_t_now();\n\n  clear_lines_listed();\n  auto warned = false;\n  char ch;\n  do {\n    while (!bin.bkbhit() && !sess().hangup()) {\n      const auto tstop = time_t_now();\n      const auto ttotal = static_cast<time_t>(difftime(tstop, tstart));\n      if (ttotal == 120) {\n        if (!warned) {\n          warned = true;\n          // Strip the colors and display the pause prompt all red here.\n          outchr(CG);\n          setc(user().color(6));\n          outstr(stripcolors(str_pause));\n          Left(stripped_size);\n          setc(saved_curatr);\n        }\n      } else {\n        if (ttotal > 180) {\n          outchr(CG);\n          for (auto i3 = 0; i3 < stripped_size; i3++) {\n            outchr(' ');\n          }\n          Left(stripped_size);\n          setc(saved_curatr);\n          return;\n        }\n      }\n      sleep_for(milliseconds(50));\n      bus().invoke<CheckForHangupEvent>();\n    }\n    ch = GetKeyForPause();\n  } while (!ch && !sess().hangup());\n  for (int i3 = 0; i3 < stripped_size; i3++) {\n    outchr(' ');\n  }\n  Left(stripped_size);\n  setc(saved_curatr);\n\n  if (!com_freeze) {\n    sess().incom(false);\n  }\n}\n\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/pause.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_PAUSE_H\n#define INCLUDED_COMMON_PAUSE_H\n\n#include \"core/transaction.h\"\n\nnamespace wwiv::common {\n\nclass Output;\n\nclass TempDisablePause : public core::Transaction {\npublic:\n  explicit TempDisablePause(Output& out);\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "common/pipe_expr.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/pipe_expr.h\"\n\n#include \"common/output.h\"\n#include \"common/value/bbsvalueprovider.h\"\n#include \"common/value/uservalueprovider.h\"\n#include \"core/log.h\"\n#include \"sdk/acs/acs.h\"\n#include \"sdk/acs/eval.h\"\n#include \"sdk/value/valueprovider.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::value;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nenum class pipe_expr_token_type_t {\n  variable,\n  number_literal,\n  string_literal,\n  fn\n};\n\nclass pipe_expr_token_t {\npublic:\n  pipe_expr_token_t() : type(pipe_expr_token_type_t::string_literal) {}\n  pipe_expr_token_t(pipe_expr_token_type_t t, std::string l) : type(t), lexeme(std::move(l)) {}\n  pipe_expr_token_type_t type;\n  std::string lexeme;\n};\n\nstatic std::optional<pipe_expr_token_t> parse_string(std::string::const_iterator& it,\n                                                     const std::string::const_iterator& end) {\n  if (*it != '\"') {\n    LOG(ERROR) << \"Parse String called without string!\";\n    return std::nullopt;\n  }\n  ++it;\n  for (std::string s; it != end; ++it) {\n    const auto c = *it;\n    if (c == '\"') {\n      // end if string. advance one more.\n      ++it;\n      pipe_expr_token_t e{};\n      e.type = pipe_expr_token_type_t::string_literal;\n      e.lexeme = s;\n      return std::make_optional(e);\n    }\n    s.push_back(c);\n  }\n  return std::nullopt;\n}\n\nstatic std::optional<pipe_expr_token_t> parse_number(std::string::const_iterator& it,\n                                                     const std::string::const_iterator& end) {  \n  std::string s;\n  for (; it != end && isdigit(*it); ++it) {\n    const auto c = *it;\n    s.push_back(c);\n  }\n  if (s.empty()) {\n    s =\"0\";\n  }\n  pipe_expr_token_t e{};\n  e.type = pipe_expr_token_type_t::number_literal;\n  e.lexeme = s;\n  return std::make_optional(e);\n}\n\nstd::optional<pipe_expr_token_t> PipeEval::parse_variable(std::string::const_iterator& it,\n                                                          const std::string::const_iterator& end) {  \n  std::string s;\n  for (; it != end && (isalpha(*it) || *it == '.' || *it == '_'); ++it) {\n    s.push_back(*it);\n  }\n  StringTrim(&s);\n  StringLowerCase(&s);\n  pipe_expr_token_t e{};\n  if (stl::contains(fn_map_, s)) {\n    e.type = pipe_expr_token_type_t::fn;\n  } else {\n    e.type = pipe_expr_token_type_t::variable;\n  }\n  e.lexeme = s;\n  return std::make_optional(e);\n}\n\nstd::vector<pipe_expr_token_t> PipeEval::tokenize(std::string::const_iterator& it,\n                                                  const std::string::const_iterator& end) {\n  std::vector<pipe_expr_token_t> r;\n\n  std::string l;\n  for (; it != end;) {\n    const auto c = *it;\n    if (iswspace(c)) {\n      ++it;\n      continue;\n    }\n    if (c == '\"') {\n      if (auto o = parse_string(it, end)) {\n        r.emplace_back(o.value());\n      }\n    } else if (isdigit(c)) {\n      if (auto o = parse_number(it, end)) {\n        r.emplace_back(o.value());\n      }\n    } else if (isalpha(c) || c == '.' || c == '_') {\n      if (auto o = parse_variable(it, end)) {\n        r.emplace_back(o.value());\n      }\n    } else {\n      ++it;\n    }\n  }\n\n  return r;\n}\n\n// TODO(rushfan): We need a unit test for this.\npipe_fmt_mask parse_mask(const std::string& mask) {\n  pipe_fmt_mask r{};\n\n  std::string l;\n  bool seen_alignment{false};\n  for (char c : mask) {\n    if (c == '<' && !seen_alignment) {\n      seen_alignment = true;\n      r.align = pipe_fmt_align_t::left;\n      if (!l.empty()) {\n        r.pad = l.front();\n        l.clear();\n      }\n      continue;\n    }\n    if (c == '>' && !seen_alignment) {\n      seen_alignment = true;\n      r.align = pipe_fmt_align_t::right;\n      if (!l.empty()) {\n        r.pad = l.front();\n        l.clear();\n      }\n      continue;\n    }\n    if (c == '^' && !seen_alignment) {\n      seen_alignment = true;\n      r.align = pipe_fmt_align_t::mid;\n      if (!l.empty()) {\n        r.pad = l.front();\n        l.clear();\n      }\n      continue;\n    }\n    l.push_back(c);\n  }\n  if (!seen_alignment) {\n    \n  }\n  if (!l.empty()) {\n    r.len = to_number<int>(l);\n  }\n  return r;\n}\n\nstatic std::string pipe_fmt(const std::string& var, const std::string& mask) {\n  if (mask.empty()) {\n    return var;\n  }\n  const auto m = parse_mask(mask);\n  auto s = var;\n  if (m.len != 0) {\n    if (const auto siz = stl::size_int(s); siz > m.len) {\n      s = s.substr(0, m.len);\n    } else if (siz < m.len) {\n      switch (m.align) {\n      case pipe_fmt_align_t::left:\n        StringJustify(&s, m.len, m.pad, JustificationType::LEFT);\n        break;\n      case pipe_fmt_align_t::mid: {\n        const auto rlen = (m.len - siz) / 2;\n        const auto llen = m.len - siz - rlen;\n        s = StrCat(std::string(llen, m.pad), s, std::string(rlen, m.pad));\n      } break;\n      case pipe_fmt_align_t::right:\n        StringJustify(&s, m.len, m.pad, JustificationType::RIGHT);\n        break;\n      }\n    }\n  }\n  return s;\n}\n\nstd::string PipeEval::eval_variable(const std::string& var, const std::vector<pipe_expr_token_t>& remaining) {\n  const auto [prefix, suffix] = SplitOnceLast(var, \".\");\n  const auto mask = !remaining.empty() ? remaining.front().lexeme : \"\";\n  if (prefix == \"user\") {\n    // Only create user if we need it, also don't cache it since eff_sl can change\n    const value::UserValueProvider user(context_);\n    return pipe_fmt(user.value(suffix)->as_string(), mask);\n  }\n  if (prefix == \"bbs\") {\n    const value::BbsValueProvider bbs_provider(context_.config(), context_.session_context());\n    return pipe_fmt(bbs_provider.value(suffix)->as_string(), mask);\n  }\n\n  for (const auto& v : context_.value_providers()) {\n    // O(N) is on for small values of n\n    if (iequals(prefix, v->prefix())) {\n      return pipe_fmt(v->value(suffix)->as_string(), mask);\n    }\n  }\n\n  // Passthrough unknown variables.\n  return StrCat(\"{\", var, \"}\"); // HACK\n}\n\nstatic bool is_truthy(const std::string& s) {\n  if (s == \"yes\" || s == \"on\" || s == \"true\" || s == \"y\") {\n    return true;\n  }\n  return false;\n}\n\nstd::string eval_fn_mpl(Context&, const std::vector<pipe_expr_token_t>& args) {\n  if (args.size() != 1) {\n    return \"ERROR: MPL expression requires 1 argument.\";\n  }\n  const auto var = args.at(0).lexeme;\n  if (var.empty()) {\n    return {};\n  }\n  if (const auto num = to_number<int>(var); num > 0) {\n    bout.mpl(num);\n  }\n  return {};\n}\n\nstd::string eval_fn_set(Context& context_, const std::vector<pipe_expr_token_t>& args) {\n  // Set command only\n  if (args.size() != 2) {\n    return \"ERROR: Set expression requires two arguments.\";\n  }\n  if (args.at(0).type != pipe_expr_token_type_t::variable) {\n    return \"ERROR: Set expression requires first arg to be variable\";\n  }\n  if (const auto var = args.at(0).lexeme; var == \"pause\") {\n    \n    const auto val = is_truthy(args.at(1).lexeme);\n    context_.u().set_flag(User::pauseOnPage, val);\n    context_.session_context().disable_pause(!val);\n  } else if (var == \"bps\") {\n    if (args.at(1).type != pipe_expr_token_type_t::number_literal) {\n      return \"ERROR: 'set bps' requires number argument\";\n    }\n    const auto bps = to_number<int>(args.at(1).lexeme);\n    context_.session_context().set_file_bps(bps);\n  } else if (var == \"lines\") {\n    if (args.at(1).type != pipe_expr_token_type_t::number_literal) {\n      return \"ERROR: 'set lines' requires number argument\";\n    }\n    if (const auto n = to_number<int>(args.at(1).lexeme); n == 0) {\n      bout.clear_lines_listed();\n    } else {\n      return \"ERROR: 'set lines' requires number argument to be 0\";\n    }\n  } else {\n    // Handle return values from scripts back to the BBS\n    context_.return_values().emplace(var, args.at(1).lexeme);\n  }\n  return {};\n}\n\ntemplate <typename... Args>\nstd::vector<const ValueProvider*> make_vector(Args&&... args) {\n    return {std::forward<Args>(args)...};\n}\n\ntemplate <typename... Args>\nstatic bool check_acs_pipe(const std::string& expression, const std::vector<std::unique_ptr<MapValueProvider>>& maps,\n  Args... args) {\n  if (StringTrim(expression).empty()) {\n    // Empty expression is always allowed.\n    return true;\n  }\n\n  acs::Eval eval(expression);\n  auto v = make_vector(args...);\n  for (const auto& vp : v) {\n    eval.add(vp);\n  }\n\n  for (const auto& m : maps) {\n    eval.add(m.get());\n  }\n\n  const auto res = eval.eval();\n  if (eval.error()) {\n    LOG(WARNING) << eval.error_text();\n  }\n  return res;\n}\n\n\nstatic std::string eval_fn_if(Context& context_, const std::vector<pipe_expr_token_t>& args) {\n  // Set command only\n  if (args.size() < 3) {\n    return \"ERROR: Set expression requires three arguments.\";\n  }\n  for (const auto& a : args) {\n    if (a.type != pipe_expr_token_type_t::string_literal) {\n      return \"ERROR: IF expression requires all args be strings\";\n    }\n  }\n\n  const auto expr = args.at(0).lexeme;\n  const auto yes = args.at(1).lexeme;\n  const auto no = args.at(2).lexeme;\n\n  const value::BbsValueProvider bbs_provider(context_);\n  const value::UserValueProvider user_provider(context_);\n  const auto b = check_acs_pipe(expr, context_.value_providers(), &user_provider, &bbs_provider);\n  std::string res = b ? yes : no;\n  if (args.size() > 3) {\n    const auto mask = args.at(3).lexeme;\n    return pipe_fmt(res, mask);\n  }\n  return res;\n}\n\nstatic std::string eval_fn_yesno(Context& context, const std::vector<pipe_expr_token_t>& args) {\n  // Set command only\n  if (args.empty()) {\n    return \"ERROR: YesNo expression requires at least one argument.\";\n  }\n  const auto& a = args.front();\n\n  std::vector<pipe_expr_token_t> ifargs{a};\n  ifargs.emplace_back(pipe_expr_token_type_t::string_literal, bout.lang().value(\"FIXED_YES\"));\n  ifargs.emplace_back(pipe_expr_token_type_t::string_literal, bout.lang().value(\"FIXED_NO\"));\n  if (args.size() > 1) {\n    const auto mask = args.at(1).lexeme;\n    ifargs.emplace_back(pipe_expr_token_type_t::string_literal, mask);\n  }\n  return eval_fn_if(context, ifargs);\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nstd::string eval_fn_random(Context&, const std::vector<pipe_expr_token_t>& args) {\n  const auto num = os::random_number(stl::size_int(args) - 1);\n  return args.at(num).lexeme;\n}\n\nstd::string PipeEval::eval_fn(const std::string& fn, const std::vector<pipe_expr_token_t>& args) {\n  if (const auto it = fn_map_.find(fn); it != std::end(fn_map_)) {\n    if (it->second) {\n      return it->second(context_, args);\n    }\n  }\n\n  return fmt::format(\"ERROR: Unknown function: {}\", fn);\n}\n\n\nstd::string PipeEval::eval(std::vector<pipe_expr_token_t>& tokens) {\n  if (tokens.empty()) {\n    return {};\n  }\n  const auto f = tokens.front();\n  if (f.type == pipe_expr_token_type_t::string_literal) {\n    return f.lexeme;\n  }\n  if  (f.type == pipe_expr_token_type_t::number_literal) {\n    return f.lexeme;\n  }\n  const std::vector<pipe_expr_token_t> remaining(std::begin(tokens)+1, std::end(tokens));\n  if (f.type == pipe_expr_token_type_t::variable) {\n    return eval_variable(f.lexeme, remaining);\n  }\n  if (f.type == pipe_expr_token_type_t::fn) {\n    return eval_fn(f.lexeme, remaining);\n  }\n  return {};\n}\n\n// Evaluates a pipe expression without the {} around it.\nstd::string PipeEval::evaluate_pipe_expression_string(const std::string& expr) {\n  auto it = std::cbegin(expr);\n  const auto end = std::cend(expr);\n  auto tokens = tokenize(it, end);\n\n  return eval(tokens);\n}\n\nPipeEval::PipeEval(Context& context) : context_(context) {\n  fn_map_.try_emplace(\"pausescr\", [](Context&, const std::vector<pipe_expr_token_t>&) -> std::string {\n    bout.pausescr();\n    return {};\n  });\n  fn_map_.try_emplace(\"random\", eval_fn_random);\n  fn_map_.try_emplace(\"yesno\", eval_fn_yesno);\n  fn_map_.try_emplace(\"if\", eval_fn_if);\n  fn_map_.try_emplace(\"mpl\", eval_fn_mpl);\n  fn_map_.try_emplace(\"set\", eval_fn_set);\n  fn_map_.try_emplace(\"sleep\", [](Context&, const std::vector<pipe_expr_token_t>& a) -> std::string {\n    if (a.empty()) {\n      return {};\n    }\n    const auto num = to_number<int>(a.front().lexeme);\n    os::sleep_for(std::chrono::milliseconds(num));\n    return {};\n  });\n  fn_map_.try_emplace(\"spin\", [](Context&, const std::vector<pipe_expr_token_t>& a) -> std::string {\n    if (a.size() < 2) {\n      return {};\n    }\n    const auto text = a.at(0).lexeme;\n    const auto color = to_number<int>(a.at(1).lexeme);\n    bout.spin_outstr(text, color);\n    return {};\n  });\n  fn_map_.try_emplace(\"backprint\", [](Context&, const std::vector<pipe_expr_token_t>& a) -> std::string {\n    if (a.size() < 4) {\n      return {};\n    }\n    const auto& text = a.at(0).lexeme;\n    const auto color = to_number<int>(a.at(1).lexeme);\n    const auto char_delay = std::chrono::milliseconds(to_number<int>(a.at(2).lexeme));\n    const auto str_delay = std::chrono::milliseconds(to_number<int>(a.at(3).lexeme));\n    bout.back_outstr(text, color, char_delay, str_delay);\n    return {};\n  });\n  fn_map_.try_emplace(\"rainbow\", [](Context&, const std::vector<pipe_expr_token_t>& a) -> std::string {\n    const auto text = a.at(0).lexeme;\n    bout.rainbow(text);\n    return {};\n  });\n}\n\nstd::string PipeEval::eval(std::string expr) {\n  auto temp = std::move(expr);\n  if (temp.length() <= 2) {\n    // Cant' be {..} if length < 2\n    return {};\n  }\n  temp.pop_back();\n  temp = temp.substr(1);\n  // Now we have ... not {...}\n\n  return evaluate_pipe_expression_string(temp);\n}\n\n}\n"
  },
  {
    "path": "common/pipe_expr.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_PIPE_EXPR_H\n#define INCLUDED_COMMON_PIPE_EXPR_H\n\n#include \"common/context.h\"\n#include <string>\nnamespace wwiv::common {\nclass pipe_expr_token_t;\n\nclass PipeEval {\npublic:\n  explicit PipeEval(Context& context);\n  std::string eval(std::string);\n\nprivate:\n  std::string eval_variable(const std::string& var,\n                            const std::vector<pipe_expr_token_t>& remaining);\n\n  std::optional<pipe_expr_token_t> parse_variable(std::string::const_iterator& it,\n                                                  const std::string::const_iterator& end);\n  std::vector<pipe_expr_token_t> tokenize(std::string::const_iterator& it,\n                                          const std::string::const_iterator& end);\n\n  std::string eval_fn(const std::string& fn, const std::vector<pipe_expr_token_t>& args);\n  std::string eval(std::vector<pipe_expr_token_t>& tokens);\n  std::string evaluate_pipe_expression_string(const std::string& expr);\n  // Not owned\n  Context& context_;\n  typedef std::function<std::string(Context&, const std::vector<pipe_expr_token_t>&)> fn_fn;\n  std::map<std::string, fn_fn> fn_map_;\n};\n\nenum class pipe_fmt_align_t { left, mid, right };\n\nstruct pipe_fmt_mask {\n  int len = 0;\n  pipe_fmt_align_t align{pipe_fmt_align_t::left};\n  char pad{' '};\n};\n\npipe_fmt_mask parse_mask(const std::string& mask);\n\n}\n#endif\n"
  },
  {
    "path": "common/pipe_expr_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5.x                            */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n#include \"common/pipe_expr.h\"\n#include \"common/common_helper.h\"\n\nusing namespace wwiv::common;\nusing namespace testing;\n\nTEST(PipeExprTest, Smoke) {\n  CommonHelper helper;\n  helper.user()->set_name(\"Rushfan\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"Rushfan\", eval.eval(\"{user.name}\"));\n  EXPECT_EQ(\"{unknown}\", eval.eval(\"{unknown}\"));\n}\n\nTEST(PipeExprTest, If) {\n  CommonHelper helper;\n  helper.user()->set_name(\"Rushfan\");\n  helper.user()->sl(200);\n  helper.sess().effective_sl(200);\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"Senior Level\", eval.eval(R\"({if \"user.sl >= 200\", \"Senior Level\", \"Junior Level\"})\"));\n  helper.user()->sl(100);\n  helper.sess().effective_sl(100);\n  EXPECT_EQ(\"Junior Level\", eval.eval(R\"({if \"user.sl >= 200\", \"Senior Level\", \"Junior Level\"})\"));\n}\n\nTEST(PipeExprTest, Fmt_LeftPad) {\n  CommonHelper helper;\n  helper.user()->set_name(\"rf\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"rf  \", eval.eval(R\"({user.name, \"<4\"})\"));\n}\n\nTEST(PipeExprTest, Fmt_RightPad) {\n  CommonHelper helper;\n  helper.user()->set_name(\"rf\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"  rf\", eval.eval(R\"({user.name, \">4\"})\"));\n}\n\nTEST(PipeExprTest, Fmt_MidPad) {\n  CommonHelper helper;\n  helper.user()->set_name(\"rf\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"  rf \", eval.eval(R\"({user.name, \"^5\"})\"));\n}\n\nTEST(PipeExpr_ParseFmtMaskTest, Smoke) {\n  const auto m = parse_mask(\"<20\");\n  EXPECT_EQ(m.align, pipe_fmt_align_t::left);\n  EXPECT_EQ(20, m.len);\n  EXPECT_EQ(' ', m.pad);\n}\n\nTEST(PipeExpr_ParseFmtMaskTest, PadChar) {\n  const auto m = parse_mask(\"X<10\");\n  EXPECT_EQ(m.align, pipe_fmt_align_t::left);\n  EXPECT_EQ(10, m.len);\n  EXPECT_EQ('X', m.pad);\n}\n\nTEST(PipeExprTest, Fmt_LeftPadCustomChar) {\n  CommonHelper helper;\n  helper.user()->set_name(\"rf\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"rf**\", eval.eval(R\"({user.name, \"*<4\"})\"));\n}\n\nTEST(PipeExprTest, Fmt_MidPadCustomChar) {\n  CommonHelper helper;\n  helper.user()->set_name(\"rf\");\n  PipeEval eval(helper.context());\n  EXPECT_EQ(\"***rf**\", eval.eval(R\"({user.name, \"*^7\"})\"));\n}\n\nTEST(PipeExpr_ParseFmtMaskTest, Right) {\n  const auto m = parse_mask(\">10\");\n  EXPECT_EQ(m.align, pipe_fmt_align_t::right);\n  EXPECT_EQ(10, m.len);\n}\n\nTEST(PipeExpr_ParseFmtMaskTest, OnlyLength) {\n  const auto m = parse_mask(\"10\");\n  EXPECT_EQ(m.align, pipe_fmt_align_t::left);\n  EXPECT_EQ(10, m.len);\n  EXPECT_EQ(' ', m.pad);\n}\n\n"
  },
  {
    "path": "common/printfile.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/printfile.h\"\n\n#include \"common/input.h\"\n#include \"common/menus/menu_data_util.h\"\n#include \"core/file.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"local_io/keycodes.h\"\n#include <chrono>\n#include <regex>\n#include <string>\n#include <vector>\n\nnamespace wwiv::common {\n\nusing namespace std::chrono;\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstd::filesystem::path CreateFullPathToPrintWithCols(const std::filesystem::path& filename,\n                                                    int screen_length) {\n  // this shouldn't happen but let's warn about it\n  if (filename.empty() || !File::Exists(filename)) {\n    LOG(WARNING) << \"CreateFullPathToPrintWithCols: filename does not exist: \"\n                 << filename.string();\n    return filename;\n  }\n\n  const auto base = filename.stem();\n  const auto ext = filename.extension();\n  const auto dir = filename.parent_path();\n\n  // u8string didn' twork with regex_match on C++20\n  const std::regex pieces_regex(fmt::format(\"{}\\\\.(\\\\d+)\\\\{}\", filename.stem().string(), ext.string()));\n  std::smatch pieces_match;\n  std::map<int, std::filesystem::path> col_fn_map;\n  for (const auto& f : std::filesystem::directory_iterator(dir)) {\n    auto fname = f.path().filename().string();\n    if (std::regex_match(fname, pieces_match, pieces_regex)) {\n      col_fn_map[wwiv::strings::to_number<int>(pieces_match[1].str())] = f.path();\n    }\n  }\n\n  // be explicit that we need this to be non-empty.\n  if (col_fn_map.empty()) {\n    return filename;\n  }\n\n  for (auto it = std::rbegin(col_fn_map); it != std::rend(col_fn_map); it++) {\n    if (it->first <= screen_length) {\n      return it->second;\n    }\n  }\n  return filename;\n}\n\nstd::filesystem::path CreateFullPathToPrint(const std::vector<std::filesystem::path>& dirs,\n                                            const User& user, const std::string& basename) {\n  for (const auto& base : dirs) {\n    auto file{FilePath(base, basename)};\n    if (basename.find('.') != std::string::npos) {\n      // We have a file with extension.\n      if (File::Exists(file)) {\n        return file;\n      }\n      // Since no wwiv file names contain embedded dots skip to the next directory.\n      continue;\n    }\n    auto candidate{file};\n    if (user.ansi()) {\n      if (user.color()) {\n        // ANSI and color\n        candidate.replace_extension(\".ans\");\n        if (File::Exists(candidate)) {\n          return CreateFullPathToPrintWithCols(candidate, user.screen_width());\n        }\n      }\n      // ANSI.\n      candidate.replace_extension(\".b&w\");\n      if (File::Exists(candidate)) {\n        return CreateFullPathToPrintWithCols(candidate, user.screen_width());\n      }\n    }\n    // ANSI/Color optional\n    candidate.replace_extension(\".msg\");\n    if (File::Exists(candidate)) {\n      return CreateFullPathToPrintWithCols(candidate, user.screen_width());\n    }\n  }\n  // Nothing matched, return the input.\n  return basename;\n}\n\nclass printfile_opts {\npublic:\n  printfile_opts(SessionContext& sc, Output& out, const std::string& raw, bool abtable, bool forcep)\n    : sess(sc), out_(out), abortable(abtable), force_pause(forcep) {\n    menus::menu_data_and_options_t t(raw);\n    data_ = t.data();\n    saved_disable_pause = sess.disable_pause();\n    saved_user_has_pause = out.user().pause();\n    if (!t.opts_empty()) {\n      for (const auto& [key, value] : t.opts()) {\n        if (key == \"pause\") {\n          if (value == \"on\") {\n            sess.disable_pause(false);\n            out.user().set_flag(User::pauseOnPage, true);\n          } else if (value == \"off\") {\n            sess.disable_pause(true);\n            out.user().set_flag(User::pauseOnPage, false);\n          } else if (value == \"start\") {\n            bout.pausescr();\n          } else if (value == \"end\") {\n            pause_at_end = true;\n          }\n        } else if (key == \"bps\") {\n          bps = to_number<int>(value);\n          sess.set_file_bps(bps);\n        }\n      }\n    }\n  }\n  ~printfile_opts() {\n    sess.disable_pause(saved_disable_pause);\n    out_.user().set_flag(User::pauseOnPage, saved_user_has_pause);\n    if (pause_at_end) {\n      bout.pausescr();\n    }\n  }\n\n  [[nodiscard]] std::string data() const noexcept { return data_; }\n\nprivate:\n  std::string data_;\n  SessionContext& sess;\n  Output& out_;\npublic:\n  bool abortable{true};\n  bool force_pause{true};\n  bool pause_at_start{false};\n  bool pause_at_end{false};\n  bool saved_disable_pause{false};\n  bool saved_user_has_pause{false};\n  int bps{0};\n};\n\n\n/**\n * Prints the file file_name.  Returns true if the file exists and is not\n * zero length.  Returns false if the file does not exist or is zero length\n *\n * @param file_path Full path to the file to display\n * @param abortable If true, a keyboard input may abort the display\n * @param force_pause Should pauses be used even for ANSI files - Normally\n *        pause on screen is disabled for ANSI files.\n *\n * @return true if the file exists and is not zero length\n */\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool Output::printfile_path(const std::filesystem::path& file_path, bool abortable, bool force_pause) {\n  auto at_exit = finally([this]() { sess().set_file_bps(0); });\n  if (!File::Exists(file_path)) {\n    // No need to print a file that does not exist.\n    return false;\n  }\n  if (std::error_code ec; !is_regular_file(file_path, ec)) {\n    // Not a file, no need to print a file that is not a file.\n    return false;\n  }\n\n  const auto save_mci = bout.mci_enabled();\n  auto at_exit_mci = finally([=]() { bout.set_mci_enabled(save_mci); });\n  bout.enable_mci();\n  TextFile tf(file_path, \"rb\");\n  const auto v = tf.ReadFileIntoVector();\n\n  const auto start_time = system_clock::now();\n  auto num_written = 0;\n  for (const auto& s : v) {\n    num_written += bout.outstr(s);\n    bout.nl();\n    // If this is an ANSI file, then don't pause\n    // (since we may be moving around\n    // on the screen, unless the caller tells us to pause anyway)\n    if (const auto has_ansi = contains(s, local::io::ESC); has_ansi && !force_pause) {\n      bout.clear_lines_listed();\n    }\n    if (contains(s, local::io::CZ)) {\n      // We are done here on a control-Z since that's DOS EOF.  Also ANSI\n      // files created with PabloDraw expect that anything after a Control-Z\n      // is fair game for metadata and includes SAUCE metadata after it which\n      // we do not want to render in the bbs.\n      break;\n    }\n    if (abortable && bin.checka()) {\n      break;\n    }\n  }\n  bout.flush();\n\n  if (sess().bps() > 0) {\n    const auto elapsed_ms = duration_cast<milliseconds>(system_clock::now() - start_time);\n    const auto actual_cps = static_cast<long>(num_written) * 1000 / (elapsed_ms.count() + 1);\n    VLOG(1) << \"Record CPS for file: \" << file_path.string() << \"; CPS: \" << actual_cps;\n  }\n  return !v.empty();\n}\n\nbool Output::printfile(const std::string& data, bool abortable, bool force_pause) {\n  const printfile_opts opts(sess(), *this, data, abortable, force_pause);\n\n  const std::vector<std::filesystem::path> dirs{sess().dirs().current_menu_gfiles_directory(), \n    sess().dirs().gfiles_directory()};\n\n  const auto full_path_name = CreateFullPathToPrint(dirs, context().u(), opts.data());\n  return printfile_path(full_path_name, abortable, force_pause);\n}\n\nbool Output::print_help_file(const std::string& filename) {\n  if (!printfile(filename)) {\n    bout.print(\"No help available.  File '{}' does not exist.\\r\\n\", filename);\n    return false;\n  }\n  return true;\n}\n\nvoid Output::print_local_file(const std::string& data) {\n  printfile(data);\n  bout.nl(2);\n  bout.pausescr();\n}\n\nbool Output::printfile_random(const std::string& data) {\n  const printfile_opts opts(sess(), *this, data, true, true);\n  const auto& dir = sess().dirs().current_menu_gfiles_directory();\n  const auto base_fn = opts.data();\n  if (const auto dot_zero = FilePath(dir, StrCat(base_fn, \".0\")); !File::Exists(dot_zero)) {\n    return false;\n  }\n  auto screens = 0;\n  for (auto i = 0; i < 1000; i++) {\n    if (const auto dot_n = FilePath(dir, StrCat(base_fn, \".\", i)); File::Exists(dot_n)) {\n      ++screens;\n    } else {\n      break;\n    }\n  }\n  return printfile_path(FilePath(dir, StrCat(base_fn, \".\", os::random_number(screens))),\n                        opts.abortable, opts.force_pause);\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/printfile.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*              Copyright (C)2014-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_COMMON_PRINTFILE_H\r\n#define INCLUDED_COMMON_PRINTFILE_H\r\n\r\n#include \"common/output.h\"\r\n#include <string>\r\n#include <filesystem>\r\n#include <vector>\r\n\r\nnamespace wwiv::common {\r\n\r\n/**\r\n * Creates the best fully qualified filename to display including support for embedding\r\n * column number into the path as basename.COLUMNS.extension.\r\n */\r\nstd::filesystem::path CreateFullPathToPrintWithCols(const std::filesystem::path& filename,\r\n                                                    int screen_length);\r\n\r\n /**\r\n  * Creates the fully qualified filename to display adding extensions and directories as needed.\r\n  */\r\nstd::filesystem::path CreateFullPathToPrint(const std::vector<std::filesystem::path>& dirs,\r\n                                            const sdk::User& user,\r\n                                            const std::string& basename);\r\n\r\n} // namespace wwiv::common\r\n\r\n#endif"
  },
  {
    "path": "common/quote.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/quote.h\"\n\n#include \"common/common_events.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"core/datetime.h\"\n#include \"core/eventbus.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/msgapi/parsed_message.h\"\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common {\n\nstatic std::unique_ptr<std::vector<std::string>> quotes_ind;\n\n\nstatic std::string FirstLettersOfVectorAsString(const std::vector<std::string>& parts) {\n  std::string result;\n  for (const auto& part : parts) {\n    result.push_back(part.front());\n  }\n  return result;\n}\n\nvoid set_quotes_ind(std::unique_ptr<std::vector<std::string>>&& u) { quotes_ind = std::move(u); }\n\nstd::string GetQuoteInitials(const std::string& orig_name) {\n  if (orig_name.empty()) {\n    return {};\n  }\n  auto name = orig_name;\n  if (starts_with(name, \"``\")) {\n    name = name.substr(2);\n  }\n\n  if (const auto paren_start = name.find('(');\n      paren_start != std::string::npos && !isdigit(name.at(paren_start + 1))) {\n    const auto inner = name.substr(paren_start + 1);\n    return GetQuoteInitials(inner);\n  }\n\n  const auto last = name.find_first_of(\"#<>()[]`\");\n  const auto parts =\n      last != std::string::npos ? SplitString(name.substr(0, last), \" \") : SplitString(name, \" \");\n  return FirstLettersOfVectorAsString(parts);\n}\n\nvoid clear_quotes(wwiv::common::SessionContext& ctx) {\n  File::Remove(FilePath(ctx.dirs().temp_directory(), QUOTES_TXT), true);\n\n  quotes_ind.reset();\n}\n\nstatic std::string to_quote_date_format(time_t t, bool use_24h_format) {\n  const auto dt = DateTime::from_time_t(t);\n  std::ostringstream ss;\n  ss << dt.to_string(\"%A,%B %d, %Y\") << \" at \";\n  if (use_24h_format) {\n    ss << dt.to_string(\"%H:%M\");\n  } else {\n    ss << dt.to_string(\"%I:%M %p\");\n  }\n  return ss.str();\n}\n\nstatic std::string to_quote_date_line(quote_date_format_t type, bool use_24h_format, time_t tt,\n                                      const std::string& tb) {\n  const auto datetime = to_quote_date_format(tt, use_24h_format);\n  std::string date_line;\n  switch (type) {\n  case quote_date_format_t::generic:\n    date_line =\n        fmt::sprintf(\"%c3On %c1%s, %c2%s%c3 wrote:%c0\", 0x03, 0x03, datetime, 0x03, tb, 0x03, 0x03);\n    break;\n  case quote_date_format_t::email:\n    date_line = fmt::sprintf(\"%c3In your e-mail of %c2%s%c3, you wrote:%c0\", 0x03, 0x03, datetime,\n                             0x03, 0x03);\n    break;\n  case quote_date_format_t::post:\n    date_line = fmt::sprintf(\"%c3In a message posted %c2%s%c3, you wrote:%c0\", 0x03, 0x03, datetime,\n                             0x03, 0x03);\n    break;\n  case quote_date_format_t::forward:\n    date_line = fmt::sprintf(\"%c3Message forwarded from %c2%s%c3, sent on %s.%c0\", 0x03, 0x03, tb,\n                             0x03, datetime, 0x03);\n    break;\n  case quote_date_format_t::no_quote:\n  default:\n    return {};\n  }\n  date_line.append(\"\\r\\n\");\n  return date_line;\n}\n\nstd::vector<std::string> create_quoted_text_from_message(std::string& raw_text,\n                                                         const std::string& to_name,\n                                                         quote_date_format_t type,\n                                                         bool use_24h_format, time_t tt) {\n  const msgapi::WWIVParsedMessageText pmt(raw_text);\n  msgapi::parsed_message_lines_style_t style{};\n  style.line_length = 72;\n  style.ctrl_lines = msgapi::control_lines_t::no_control_lines;\n  style.add_wrapping_marker = false;\n  // experimental\n  style.reattribute_quotes = true;\n\n  auto lines = pmt.to_lines(style);\n  auto it = std::begin(lines);\n  const auto end = std::end(lines);\n\n  if (lines.size() < 2) {\n    return {};\n  }\n  const auto to_node = *it++;\n  ++it;\n\n  const auto quote_initials = GetQuoteInitials(to_name);\n  std::vector<std::string> out;\n  if (type != quote_date_format_t::no_quote) {\n    out.emplace_back(\n        to_quote_date_line(type, use_24h_format, tt, properize(strip_to_node(to_node))));\n  }\n\n  for (; it != end; ++it) {\n    auto line = *it;\n    StringReplace(&line,\n                  \"\\x03\"\n                  \"0\",\n                  \"\\x03\"\n                  \"5\");\n    out.emplace_back(fmt::sprintf(\"%c%c%s%c%c> %c%c%s%c0\", 0x03, '1', quote_initials, 0x03, '7',\n                                  0x03, '5', line, 0x03));\n  }\n  return out;\n}\n\nvoid auto_quote(std::string& raw_text, const std::string& to_name, quote_date_format_t type,\n                time_t tt, wwiv::common::Context& ctx) {\n  const auto fn = FilePath(ctx.session_context().dirs().temp_directory(), INPUT_MSG);\n  File::Remove(fn);\n\n  TextFile f(fn, \"w\");\n  if (!f) {\n    return;\n  }\n  const auto use_24h_format = ctx.u().twentyfour_clock();\n  auto lines = create_quoted_text_from_message(raw_text, to_name, type, use_24h_format, tt);\n  for (const auto& l : lines) {\n    f.WriteLine(l);\n  }\n  if (ctx.u().messages_posted() < 10) {\n    bout.printfile(QUOTE_NOEXT);\n  }\n}\n\nvoid grab_quotes(std::string& raw_text, const std::string& to_name, wwiv::common::Context& ctx) {\n  if (raw_text.back() == CZ) {\n    // Since CZ isn't special on Win32/Linux. Don't write it out\n    // to the quotes file.\n    raw_text.pop_back();\n  }\n\n  clear_quotes(ctx.session_context());\n  File f(FilePath(ctx.session_context().dirs().temp_directory(), QUOTES_TXT));\n  if (f.Open(File::modeDefault | File::modeCreateFile | File::modeTruncate, File::shareDenyNone)) {\n    f.Write(raw_text);\n  }\n\n  const auto use_24h_format = ctx.u().twentyfour_clock();\n  quotes_ind = std::make_unique<std::vector<std::string>>(create_quoted_text_from_message(\n      raw_text, to_name, quote_date_format_t::no_quote, use_24h_format, 0));\n}\n\nstd::vector<std::string> query_quote_lines(wwiv::common::SessionContext& ctx) {\n  std::vector<std::string> lines;\n\n  if (!quotes_ind || quotes_ind->empty()) {\n    return {};\n  }\n  int start_line;\n  int end_line;\n  auto num_lines = 0;\n  do {\n    start_line = 0;\n    end_line = 0;\n    auto iter = std::begin(*quotes_ind);\n    auto end = std::end(*quotes_ind);\n    num_lines = 1;\n    auto abort = false;\n    for (; iter != end; ++iter) {\n      // Skip control line (^D)\n      auto& line = *iter;\n      if (!line.empty() && line.front() == 0x04) {\n        continue;\n      }\n      StringTrimCRLF(&line);\n      bout.bpla(fmt::format(\"{:>3} {}\", num_lines++, line), &abort);\n      if (abort) {\n        break;\n      }\n      // Add line s to the list of lines.\n      lines.emplace_back(line);\n    }\n    --num_lines;\n    bout.nl();\n    // If the user has hungup, this will throw an exception.\n    bus().invoke<CheckForHangupEvent>();\n    if (lines.empty() || ctx.hangup()) {\n      return {};\n    }\n    bout.print(\"|#2Quote from line 1-{}? (?=relist, Q=quit) \", num_lines);\n    auto k = bin.input_number_hotkey(1, {'Q', '?'}, 1, num_lines);\n\n    if (k.key == 'Q') {\n      return {};\n    }\n    if (k.key == '?') {\n      bout.nl();\n      continue;\n    }\n    start_line = k.num;\n    if (start_line == num_lines) {\n      end_line = start_line;\n    } else {\n      bout.print(\"|#2through line {} - {} ? (Q=quit) \", start_line, num_lines);\n      k = bin.input_number_hotkey(start_line, {'Q', '?'}, start_line, num_lines);\n      if (k.key == 'Q') {\n        return {};\n      }\n      if (k.key == '?') {\n        bout.nl();\n        continue;\n      }\n      end_line = k.num;\n    }\n\n    if (start_line == end_line) {\n      bout.print(\"|#5Quote line {}? \", start_line);\n    } else {\n      bout.print(\"|#5Quote lines {}-{}? \", start_line, end_line);\n    }\n    if (!bin.noyes()) {\n      return {};\n    }\n    break;\n  } while (!ctx.hangup());\n  return std::vector<std::string>(std::begin(lines) + start_line - 1, std::begin(lines) + end_line);\n}\n\nstd::string strip_to_node(const std::string& txt) {\n  std::ostringstream os;\n  if (txt.find('@') != std::string::npos) {\n    bool ok = true;\n    for (auto i = txt.begin(); i != txt.end(); i++) {\n      if (ok) {\n        os << *i;\n      }\n      if ((i + 1) != txt.end() && (i + 2) != txt.end() && *(i + 2) == '#') {\n        ok = false;\n      }\n    }\n    return os.str();\n  } else if (txt.find(\"AT\") != std::string::npos) {\n    bool ok = true;\n    for (std::string::const_iterator i = txt.begin() + 2; i != txt.end(); ++i) {\n      if (ok) {\n        os << *i;\n      }\n      if (*(i + 1) == '`') {\n        ok = false;\n      }\n    }\n    return os.str();\n  }\n  return txt;\n}\n\n} // namespace wwiv::common"
  },
  {
    "path": "common/quote.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_QUOTE_H\n#define INCLUDED_COMMON_QUOTE_H\n\n#include \"common/context.h\"\n#include <string>\n#include <vector>\n\nnamespace wwiv::common {\n\nenum class quote_date_format_t { no_quote, generic, email, post, forward };\n\nvoid grab_quotes(std::string& raw_text, const std::string& to_name,\n                 wwiv::common::Context& ctx);\nvoid clear_quotes(wwiv::common::SessionContext& ctx);\nvoid auto_quote(std::string& raw_text, const std::string& to_name, quote_date_format_t type,\n                time_t tt, wwiv::common::Context& ctx);\nstd::vector<std::string> query_quote_lines(wwiv::common::SessionContext& ctx);\n\nstd::string strip_to_node(const std::string& txt);\n\nstd::vector<std::string> create_quoted_text_from_message(\n    std::string& raw_text, const std::string& to_name, quote_date_format_t type,\n    bool use_24h_format,\n    time_t tt);\nvoid set_quotes_ind(std::unique_ptr<std::vector<std::string>>&&);\n\n\n    // [[ VisibleForTesting ]]\nstd::string GetQuoteInitials(const std::string& reply_to_name);\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/remote_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"common/remote_io.h\"\n#include \"core/scope_exit.h\"\n#include \"fmt/format.h\"\n#include <string>\n\n#ifndef _WIN32\n// for strerror_r\n#include <string.h>\n#endif  // !_WIN32\n\nusing wwiv::core::finally;\n\nnamespace wwiv::common {\n\n// static\nstd::string RemoteIO::error_text_;\n\nvoid RemoteIO::set_binary_mode(bool b) {\n  binary_mode_ = b;\n}\n\nstd::string RemoteIO::GetLastErrorText() {\n#if defined ( _WIN32 )\n  char* error_text;\n  \n  FormatMessage(\n    FORMAT_MESSAGE_ALLOCATE_BUFFER |\n    FORMAT_MESSAGE_FROM_SYSTEM |\n    FORMAT_MESSAGE_IGNORE_INSERTS,\n    nullptr,\n    GetLastError(),\n    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\n    LPTSTR(&error_text),\n    0,\n    nullptr\n  );\n  error_text_.assign(error_text);\n  LocalFree(error_text);\n#else\n  // int strerror_r(int errnum, char *buf, size_t buflen);\n  char buf[500];\n  if (strerror_r(errno, buf, sizeof(buf)) != 0) {\n    buf[0] = '\\0';\n  }\n  return fmt::format(\"errno: {} (num: {})\", buf, errno);\n#endif\n  return error_text_;\n}\n\nstd::optional<ScreenPos> RemoteIO::screen_position() { \n  return ScreenPos{0, 0};\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/remote_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_COMMON_REMOTE_IO_H\n#define INCLUDED_COMMON_REMOTE_IO_H\n\n#include <optional>\n#include <string>\n\nnamespace wwiv::common {\n\n  enum class CommunicationType {\n  NONE,\n  TELNET,\n  SSH,\n  STDIO,\n  PIPE\n};\n\n/** Information about the remote session. */\nclass RemoteInfo {\npublic:\n  void clear() {\n    address.clear();\n    address_name.clear();\n    username.clear();\n    password.clear();\n  }\n\n  std::string address;\n  std::string address_name;\n  std::string username;\n  std::string password;\n};\n\nstruct ScreenPos {\n  int x{0};\n  int y{0};\n};\n\n/**\n * Base Communication Class.\n */\nclass RemoteIO {\n public:\n  RemoteIO() = default;\n  virtual ~RemoteIO() = default;\n\n  virtual bool open() = 0;\n  virtual void close(bool temporary) = 0;\n  virtual unsigned char getW() = 0;\n  virtual bool disconnect() = 0;\n  virtual void purgeIn() = 0;\n  virtual unsigned int put(unsigned char ch) = 0;\n  virtual unsigned int read(char *buffer, unsigned int count) = 0;\n  virtual unsigned int write(const char *buffer, unsigned int count, bool bNoTranslation = false) = 0;\n  virtual bool connected() = 0;\n  virtual bool incoming() = 0;\n\n  [[nodiscard]] virtual unsigned int GetHandle() const = 0;\n  [[nodiscard]] virtual unsigned int GetDoorHandle() const { return GetHandle(); }\n\n  virtual void set_binary_mode(bool b);\n  [[nodiscard]] bool binary_mode() const { return binary_mode_; }\n\n  virtual RemoteInfo& remote_info() { return remote_info_; }\n\n  virtual std::optional<ScreenPos> screen_position();\n\nprotected:\n  bool binary_mode_{false};\n\n  static std::string GetLastErrorText();\n\nprivate:\n  // used by the GetLastErrorText() method\n  static std::string error_text_;\n  RemoteInfo remote_info_;\n};\n\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/remote_pipe_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/remote_pipe_io.h\"\n\n#include \"common/remote_socket_io.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/pipe.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include <iostream>\n#include <memory>\n#include <system_error>\n\nnamespace wwiv::common {\n\nusing std::chrono::milliseconds;\nusing wwiv::os::sleep_for;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nRemotePipeIO::RemotePipeIO(unsigned int node_number, bool telnet)\n    : data_pipe_(fmt::format(\"WWIV{}\", node_number)),\n      control_pipe_(fmt::format(\"WWIV{}C\", node_number)), \n      node_number_(node_number),\n      telnet_(telnet) {\n  // Make sure our signal event is not set to the \"signaled\" state.\n  stop_.store(false);\n}\n\nunsigned int RemotePipeIO::GetHandle() const { return 0; }\n\nbool RemotePipeIO::open() {\n  LOG(INFO) << \"RemotePipeIO::open(): \" << data_pipe_.name();\n  VLOG(2) << \"RemotePipeIO::open(): \" << data_pipe_.name();\n  if (!data_pipe_.Open()) {\n    LOG(WARNING) << \"Failed to open data pipe: \" << data_pipe_.name();\n  }\n  if (!control_pipe_.Open()) {\n    LOG(WARNING) << \"Failed to open control pipe: \" << control_pipe_.name();\n  }\n  StartThreads();\n\n  if (telnet_) {\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_DONT,\n                            RemoteSocketIO::TELNET_OPTION_ECHO};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_WILL,\n                            RemoteSocketIO::TELNET_OPTION_ECHO};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_WILL,\n                            RemoteSocketIO::TELNET_OPTION_SUPPRESSS_GA};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_DONT,\n                            RemoteSocketIO::TELNET_OPTION_LINEMODE};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n  }\n\n  return true;\n}\n\nvoid RemotePipeIO::close(bool /* temporary */) {\n  data_pipe_.Close();\n  control_pipe_.Close();\n  StopThreads();\n}\n\nunsigned int RemotePipeIO::put(unsigned char ch) {\n  // Early return on invalid sockets.\n  if (!data_pipe_.IsOpen()) {\n    return 0;\n  }\n\n  unsigned char szBuffer[3] = {ch, 0, 0};\n  if (ch == RemoteSocketIO::TELNET_OPTION_IAC) {\n    szBuffer[1] = ch;\n  }\n\n  if (const auto o = data_pipe_.write(reinterpret_cast<char*>(szBuffer), ssize(szBuffer))) {\n    //LOG(INFO) << \"Wrote to pipe: \" << szBuffer;\n    return o.value();\n  }\n  LOG(ERROR) << \"Writing to pipe failed: \" << data_pipe_.name();\n  return 0;\n}\n\nunsigned char RemotePipeIO::getW() {\n  if (!data_pipe_.IsOpen()) {\n    return 0;\n  }\n\n  char ch = 0;\n  std::lock_guard<std::mutex> lock(mu_);\n  if (!queue_.empty()) {\n    ch = queue_.front();\n    queue_.pop_front();\n  }\n  return static_cast<unsigned char>(ch);\n}\n\nbool RemotePipeIO::disconnect() {\n  if (!data_pipe_.IsOpen()) {\n    return false;\n  }\n\n  data_pipe_.Close();\n  control_pipe_.Close();\n  return true;\n}\n\nvoid RemotePipeIO::purgeIn() {\n  // Early return on invalid sockets.\n  if (!data_pipe_.IsOpen()) {\n    return;\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  queue_.clear();\n}\n\nunsigned int RemotePipeIO::read(char* buffer, unsigned int count) {\n  if (!data_pipe_.IsOpen()) {\n    return 0;\n  }\n\n  unsigned int num_read = 0;\n  auto* temp = buffer;\n\n  std::lock_guard<std::mutex> lock(mu_);\n  while (!queue_.empty() && num_read <= count) {\n    const auto ch = queue_.front();\n    queue_.pop_front();\n    *temp++ = ch;\n    num_read++;\n  }\n  *temp = '\\0';\n  return num_read;\n}\n\nstatic const char CHAR_TELNET_OPTION_IAC = '\\xFF';\n\nunsigned int RemotePipeIO::write(const char* buffer, unsigned int count, bool no_translation) {\n  // Early return on invalid sockets.\n  if (!data_pipe_.IsOpen()) {\n    return 0;\n  }\n\n  const auto tmp_buffer = std::make_unique<char[]>(count * 2 + 100);\n  memset(tmp_buffer.get(), 0, count * 2 + 100);\n  int nCount = count;\n\n  if (no_translation || !memchr(buffer, CHAR_TELNET_OPTION_IAC, count)) {\n    memcpy(tmp_buffer.get(), buffer, count);\n  } else {\n    // If there is a #255 then escape the #255's\n    const auto* p = buffer;\n    auto* p2 = tmp_buffer.get();\n    for (unsigned int i = 0; i < count; i++) {\n      if (*p == CHAR_TELNET_OPTION_IAC && !no_translation) {\n        *p2++ = CHAR_TELNET_OPTION_IAC;\n        *p2++ = CHAR_TELNET_OPTION_IAC;\n        nCount++;\n      } else {\n        *p2++ = *p;\n      }\n      p++;\n    }\n    *p2 = '\\0';\n  }\n\n  return data_pipe_.write(tmp_buffer.get(), nCount).value_or(0);\n}\n\nbool RemotePipeIO::connected() {\n  if (!data_pipe_.IsOpen()) {\n    LOG(ERROR) << \"!connected(); threads_started_ = \" << std::boolalpha << threads_started_;\n    return false;\n  }\n  return true;\n}\n\nbool RemotePipeIO::incoming() {\n  if (!data_pipe_.IsOpen()) {\n    return false;\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  return !queue_.empty();\n}\n\nvoid RemotePipeIO::StopThreads() {\n  {\n    std::lock_guard<std::mutex> lock(threads_started_mu_);\n    if (!threads_started_) {\n      return;\n    }\n    stop_.store(true);\n    threads_started_ = false;\n  }\n  os::yield();\n\n  try {\n    // Wait for read thread to exit.\n    if (read_thread_.joinable()) {\n      read_thread_.join();\n    }\n  } catch (const std::system_error& e) {\n    LOG(ERROR) << \"Caught system_error with code: \" << e.code() << \"; meaning: \" << e.what();\n  }\n}\n\nvoid RemotePipeIO::StartThreads() {\n  {\n    std::lock_guard<std::mutex> lock(threads_started_mu_);\n    if (threads_started_) {\n      return;\n    }\n    threads_started_ = true;\n  }\n  \n  stop_.store(false);\n  read_thread_ = std::thread(&RemotePipeIO::PipeLoop, this);\n}\n\nRemotePipeIO::~RemotePipeIO() {\n  try {\n    StopThreads();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n  }\n}\n\n\nvoid RemotePipeIO::PipeLoop() {\n  constexpr size_t size = 4 * 1024;\n  const auto data = std::make_unique<char[]>(size);\n  try {\n    while (true) {\n      if (stop_.load()) {\n        return;\n      }\n      if (!data_pipe_.peek()) {\n        os::sleep_for(std::chrono::milliseconds(200));\n        continue;\n      }\n      const auto num_read = data_pipe_.read(data.get(), size).value_or(0);\n      if (num_read == 0) {\n        // The other side has gracefully closed the socket.\n        data_pipe_.Close();\n        control_pipe_.Close();\n        return;\n      }\n      AddStringToInputBuffer(0, num_read, data.get());\n    }\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"PipeLoop exiting. Caught socket_error: \" << e.what();\n    data_pipe_.Close();\n  }\n}\n\nvoid RemotePipeIO::set_binary_mode(bool b) {\n  binary_mode_ = b;\n  skip_next_ = false;\n}\n\nstd::optional<ScreenPos> RemotePipeIO::screen_position() { \n  // Clear inbound\n  purgeIn();\n\n  write(\"\\x1b[6n\", 4);\n\n  const auto now = std::chrono::steady_clock::now();\n  auto l = now + std::chrono::seconds(3);\n\n  std::string dsr_response;\n  while (std::chrono::steady_clock::now() < l && connected()) {\n    auto ch = getW();\n    if (ch == '\\x1b') {\n      l = std::chrono::steady_clock::now() + std::chrono::seconds(1);\n      while (std::chrono::steady_clock::now() < l && connected()) {\n        ch = getW();\n        if (ch) {\n          if (isdigit(ch) || ch == ';') {\n            dsr_response.push_back(ch);\n          }\n          if (ch == 'R') {\n            VLOG(1) << \"RemoteSocketIO::screen_position(): DSR: \" << dsr_response;\n            if (auto idx = dsr_response.find(';'); idx != std::string::npos) {\n              auto y = to_number<int>(dsr_response.substr(0, idx));\n              auto x = to_number<int>(dsr_response.substr(idx+1));\n              return {ScreenPos{x, y}};\n            }\n            return std::nullopt;\n          }\n        }\n      }\n      return std::nullopt;\n    }\n  }\n  return std::nullopt;\n}\n\nvoid RemotePipeIO::HandleTelnetIAC(unsigned char nCmd, unsigned char nParam) {\n  // We should probably start responding to the DO and DONT options....\n  switch (nCmd) {\n  case RemoteSocketIO::TELNET_OPTION_NOP : {\n    // TELNET_OPTION_NOP\n  } break;\n  case RemoteSocketIO::TELNET_OPTION_BRK: {\n    // TELNET_OPTION_BRK;\n  } break;\n  case RemoteSocketIO::TELNET_OPTION_WILL: {\n    // const string s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_WILL\",\n    // nParam);\n    // ::OutputDebugString(s.c_str());\n  } break;\n  case RemoteSocketIO::TELNET_OPTION_WONT: {\n    // const string s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_WONT\",\n    // nParam);\n    // ::OutputDebugString(s.c_str());\n  } break;\n  case RemoteSocketIO::TELNET_OPTION_DO: {\n    // const string do_s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_DO\",\n    // nParam);\n    // ::OutputDebugString(do_s.c_str());\n    switch (nParam) {\n    case RemoteSocketIO::TELNET_OPTION_SUPPRESSS_GA: {\n      char s[4];\n      s[0] = RemoteSocketIO::TELNET_OPTION_IAC;\n      s[1] = RemoteSocketIO::TELNET_OPTION_WILL;\n      s[2] = RemoteSocketIO::TELNET_OPTION_SUPPRESSS_GA;\n      s[3] = 0;\n      write(s, 3, true);\n      // Sent TELNET IAC WILL SUPPRESS GA\n    } break;\n    }\n  } break;\n  case RemoteSocketIO::TELNET_OPTION_DONT: {\n    // const string dont_s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_DONT\",\n    // nParam);\n    // ::OutputDebugString(dont_s.c_str());\n  } break;\n  }\n}\n\nvoid RemotePipeIO::AddStringToInputBuffer(int start, int end, const char* buffer) {\n  // Add the data to the input buffer\n  for (auto num_sleeps = 0; num_sleeps < 10 && queue_.size() > 32678; ++num_sleeps) {\n    sleep_for(milliseconds(100));\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n\n  if (binary_mode()) {\n    for (auto i = start; i < end; i++) {\n      const uint8_t c = buffer[i];\n      if (skip_next_ && c == 0xff) {\n        skip_next_ = false;\n        continue;\n      }\n      if (c == 0xff) {\n        // TODO(rushfan): If this causes problems, we can add a setting for this\n        VLOG(2) << \"Got an escaped 255 possibly\";\n        skip_next_ = true;\n      } else {\n        skip_next_ = false;\n      }\n      queue_.push_back(c);\n    }\n    return;\n  }\n  for (auto i = start; i < end; i++) {\n    if (static_cast<unsigned char>(buffer[i]) == 255) {\n      if ((i + 1) < end && static_cast<unsigned char>(buffer[i + 1]) == 255) {\n        queue_.push_back(buffer[i + 1]);\n        i++;\n      } else if ((i + 2) < end) {\n        HandleTelnetIAC(buffer[i + 1], buffer[i + 2]);\n        i += 2;\n      } else {\n        // ::OutputDebugString(\"WHAT THE HECK?!?!?!? 255 w/o any options or anything\\r\\n\");\n      }\n    } else if (buffer[i] != '\\0') {\n      // RF20020906: I think the nulls in the input buffer were being bad...\n      // This fixed the problem with CRT to a linux machine and then telnet from\n      // that linux box to the bbs... Hopefully this will fix the Win9x built-in\n      // telnet client as well as TetraTERM.\n      queue_.push_back(buffer[i]);\n    }\n  }\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/remote_pipe_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_REMOTE_PIPE_IO_H\n#define INCLUDED_COMMON_REMOTE_PIPE_IO_H\n\n#include \"common/remote_io.h\"\n#include \"core/pipe.h\"\n#include <atomic>\n#include <cstdint>\n#include <mutex>\n#include <deque>\n#include <thread>\n\nnamespace wwiv::common {\n\nclass RemotePipeIO final : public RemoteIO {\n public:\n  RemotePipeIO(unsigned int node_number, bool telnet);\n  ~RemotePipeIO() override;\n\n  bool open() override;\n  void close(bool bIsTemporary) override;\n  unsigned char getW() override;\n  bool disconnect() override;\n  void purgeIn() override;\n  unsigned int put(unsigned char ch) override;\n  unsigned int read(char *buffer, unsigned int count) override;\n  unsigned int write(const char *buffer, unsigned int count, bool no_translation = false) override;\n  bool connected() override;\n  bool incoming() override;\n  void StopThreads();\n  void StartThreads();\n  unsigned int GetHandle() const override;\n\n  void set_binary_mode(bool b) override;\n  std::optional<ScreenPos> screen_position() override;\n\n  // These aren't part of RemoteIO\n\n  // VisibleForTesting\n  void AddStringToInputBuffer(int start, int end, const char* buffer);\n  std::deque<char>& queue() { return queue_; }\n\n\nprivate:\n  void HandleTelnetIAC(unsigned char nCmd, unsigned char nParam);\n  void PipeLoop();\n\n  std::deque<char> queue_;\n  mutable std::mutex mu_;\n  mutable std::mutex threads_started_mu_;\n  core::Pipe data_pipe_;\n  core::Pipe control_pipe_;\n  int node_number_{0};\n  std::thread read_thread_;\n  std::atomic<bool> stop_;\n  bool threads_started_{false};\n  bool telnet_{true};\n  bool skip_next_{false};\n};\n\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/remote_socket_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/remote_socket_io.h\"\n\n#ifdef _WIN32\n#pragma comment(lib, \"Ws2_32.lib\")\n#include \"WS2tcpip.h\"\n// Really windows?\ntypedef int socklen_t;\n#else\n\n#include <arpa/inet.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <unistd.h>\n\n#endif  // _WIN32\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include <iostream>\n#include <memory>\n#include <system_error>\n\nnamespace wwiv::common {\n\nusing std::chrono::milliseconds;\nusing wwiv::os::sleep_for;\nusing wwiv::stl::size_int;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n// N.B. mutex and yield are defines in Solaris.\n\nstruct socket_error final : std::runtime_error {\n  explicit socket_error(const std::string& message) : std::runtime_error(message) {}\n};\n\nstatic bool socket_avail(SOCKET sock, int seconds) {\n  fd_set fds;\n  FD_ZERO(&fds);\n  FD_SET(sock, &fds);\n\n  timeval tv;\n  tv.tv_sec = seconds;\n  tv.tv_usec = 0;\n\n  const auto result = select(sock + 1, &fds, nullptr, nullptr, &tv);\n  if (result == SOCKET_ERROR) {\n    throw socket_error(\"Error on select for socket.\");\n  }\n  return result == 1;\n}\n\nRemoteSocketIO::RemoteSocketIO(SOCKET socket_handle, bool telnet)\n    : socket_(socket_handle), telnet_(telnet) {\n  // assigning the value to a static causes this only to be initialized once.\n  [[maybe_unused]] static auto once = Initialize();\n\n  // Make sure our signal event is not set to the \"signaled\" state.\n  stop_.store(false);\n\n  if (socket_handle == 0 || socket_handle == INVALID_SOCKET) {\n    // This means we don't have a real socket handle, for example running in local mode.\n    // so we set it to INVALID_SOCKET and don't initialize anything.\n    socket_ = INVALID_SOCKET;\n  }\n}\n\nunsigned int RemoteSocketIO::GetHandle() const { return static_cast<unsigned int>(socket_); }\n\nbool RemoteSocketIO::open() {\n  if (socket_ == INVALID_SOCKET) {\n    // We can not open an invalid socket.\n    return false;\n  }\n  StartThreads();\n\n  remote_info().address = GetRemotePeerAddress(socket_).value_or(\"\");\n  remote_info().address_name = GetRemotePeerHostname(socket_).value_or(\"\");\n  if (telnet_) {\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_DONT,\n                            RemoteSocketIO::TELNET_OPTION_ECHO};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_WILL,\n                            RemoteSocketIO::TELNET_OPTION_ECHO};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_WILL,\n                            RemoteSocketIO::TELNET_OPTION_SUPPRESSS_GA};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n    {\n      unsigned char s[3] = {RemoteSocketIO::TELNET_OPTION_IAC, RemoteSocketIO::TELNET_OPTION_DONT,\n                            RemoteSocketIO::TELNET_OPTION_LINEMODE};\n      write(reinterpret_cast<char*>(s), 3, true);\n    }\n  }\n\n  return true;\n}\n\nvoid RemoteSocketIO::close(bool temporary) {\n  if (socket_ == INVALID_SOCKET) {\n    // Early return on invalid sockets.\n    return;\n  }\n  if (!temporary) {\n    // this will stop the threads\n    closesocket(socket_);\n  }\n  StopThreads();\n}\n\nunsigned int RemoteSocketIO::put(unsigned char ch) {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return 0;\n  }\n\n  unsigned char szBuffer[3] = {ch, 0, 0};\n  if (ch == TELNET_OPTION_IAC) {\n    szBuffer[1] = ch;\n  }\n\n  const auto num_sent = send(socket_, reinterpret_cast<char*>(szBuffer), ssize(szBuffer), 0);\n  if (num_sent == SOCKET_ERROR) {\n    return 0;\n  }\n  return num_sent;\n}\n\nunsigned char RemoteSocketIO::getW() {\n  if (!valid_socket()) {\n    return 0;\n  }\n  char ch = 0;\n  std::lock_guard<std::mutex> lock(mu_);\n  if (!queue_.empty()) {\n    ch = queue_.front();\n    queue_.pop_front();\n  }\n  return static_cast<unsigned char>(ch);\n}\n\nbool RemoteSocketIO::disconnect() {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return false;\n  }\n\n  closesocket(socket_);\n  socket_ = INVALID_SOCKET;\n  return true;\n}\n\nvoid RemoteSocketIO::purgeIn() {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return;\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  queue_.clear();\n}\n\nunsigned int RemoteSocketIO::read(char* buffer, unsigned int count) {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return 0;\n  }\n\n  unsigned int num_read = 0;\n  auto* temp = buffer;\n\n  std::lock_guard<std::mutex> lock(mu_);\n  while (!queue_.empty() && num_read <= count) {\n    const auto ch = queue_.front();\n    queue_.pop_front();\n    *temp++ = ch;\n    num_read++;\n  }\n  *temp = '\\0';\n  return num_read;\n}\n\nstatic const char CHAR_TELNET_OPTION_IAC = '\\xFF';\n\nunsigned int RemoteSocketIO::write(const char* buffer, unsigned int count, bool no_translation) {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return 0;\n  }\n\n  const auto tmp_buffer = std::make_unique<char[]>(count * 2 + 100);\n  memset(tmp_buffer.get(), 0, count * 2 + 100);\n  int nCount = count;\n\n  if (no_translation || !memchr(buffer, CHAR_TELNET_OPTION_IAC, count)) {\n    memcpy(tmp_buffer.get(), buffer, count);\n  } else {\n    // If there is a #255 then escape the #255's\n    const auto* p = buffer;\n    auto* p2 = tmp_buffer.get();\n    for (unsigned int i = 0; i < count; i++) {\n      if (*p == CHAR_TELNET_OPTION_IAC && !no_translation) {\n        *p2++ = CHAR_TELNET_OPTION_IAC;\n        *p2++ = CHAR_TELNET_OPTION_IAC;\n        nCount++;\n      } else {\n        *p2++ = *p;\n      }\n      p++;\n    }\n    *p2 = '\\0';\n  }\n\n  const auto num_sent = send(socket_, tmp_buffer.get(), nCount, 0);\n  if (num_sent == SOCKET_ERROR) {\n    return 0;\n  }\n  return num_sent;\n}\n\nbool RemoteSocketIO::connected() {\n  const auto connected = valid_socket();\n  if (!connected) {\n    LOG(ERROR) << \"!connected(); threads_started_ = \" << std::boolalpha << threads_started_;\n  }\n  return connected;\n}\n\nbool RemoteSocketIO::incoming() {\n  // Early return on invalid sockets.\n  if (!valid_socket()) {\n    return false;\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  return !queue_.empty();\n}\n\nvoid RemoteSocketIO::StopThreads() {\n  {\n    std::lock_guard<std::mutex> lock(threads_started_mu_);\n    if (!threads_started_) {\n      return;\n    }\n    stop_.store(true);\n    threads_started_ = false;\n  }\n  os::yield();\n\n  // Wait for read thread to exit.\n  if (!read_thread_.joinable()) {\n    LOG(ERROR) << \"read_thread_ is not JOINABLE.  Should not happen.\";\n  }\n  try {\n    if (read_thread_.joinable()) {\n      read_thread_.join();\n    }\n  } catch (const std::system_error& e) {\n    LOG(ERROR) << \"Caught system_error with code: \" << e.code() << \"; meaning: \" << e.what();\n  }\n}\n\nvoid RemoteSocketIO::StartThreads() {\n  {\n    std::lock_guard<std::mutex> lock(threads_started_mu_);\n    if (threads_started_) {\n      return;\n    }\n    threads_started_ = true;\n  }\n\n  stop_.store(false);\n  read_thread_ = std::thread(&RemoteSocketIO::InboundTelnetProc, this);\n}\n\nRemoteSocketIO::~RemoteSocketIO() {\n  try {\n    StopThreads();\n\n#ifdef _WIN32\n    WSACleanup();\n#endif // _WIN32\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n  }\n}\n\n// Static Class Members.\n\nbool RemoteSocketIO::Initialize() {\n#ifdef _WIN32\n  WSADATA wsaData;\n  const auto err = WSAStartup(0x0101, &wsaData);\n\n  if (err != 0) {\n    switch (err) {\n    case WSASYSNOTREADY:\n      LOG(ERROR) << \"Error from WSAStartup: WSASYSNOTREADY\";\n      break;\n    case WSAVERNOTSUPPORTED:\n      LOG(ERROR) << \"Error from WSAStartup: WSAVERNOTSUPPORTED\";\n      break;\n    case WSAEINPROGRESS:\n      LOG(ERROR) << \"Error from WSAStartup: WSAEINPROGRESS\";\n      break;\n    case WSAEPROCLIM:\n      LOG(ERROR) << \"Error from WSAStartup: WSAEPROCLIM\";\n      break;\n    case WSAEFAULT:\n      LOG(ERROR) << \"Error from WSAStartup: WSAEFAULT\";\n      break;\n    default:\n      LOG(ERROR) << \"Error from WSAStartup: ** unknown error code **\";\n      break;\n    }\n  }\n  return err == 0;\n#else\n  return true;\n#endif\n}\n\nvoid RemoteSocketIO::InboundTelnetProc() {\n  constexpr size_t size = 4 * 1024;\n  const auto data = std::make_unique<char[]>(size);\n  try {\n    while (true) {\n      if (stop_.load()) {\n        return;\n      }\n      if (!socket_avail(socket_, 1)) {\n        os::sleep_for(std::chrono::milliseconds(200));\n        continue;\n      }\n      const auto num_read = recv(socket_, data.get(), size, 0);\n      if (num_read == SOCKET_ERROR) {\n        // Got Socket error.\n        closesocket(socket_);\n        socket_ = INVALID_SOCKET;\n        return;\n      }\n      if (num_read == 0) {\n        // The other side has gracefully closed the socket.\n        closesocket(socket_);\n        socket_ = INVALID_SOCKET;\n        return;\n      }\n      AddStringToInputBuffer(0, num_read, data.get());\n    }\n  } catch (const socket_error& e) {\n    LOG(ERROR) << \"InboundTelnetProc exiting. Caught socket_error: \" << e.what();\n    closesocket(socket_);\n    socket_ = INVALID_SOCKET;\n  }\n}\n\nvoid RemoteSocketIO::set_binary_mode(bool b) {\n  binary_mode_ = b;\n  skip_next_ = false;\n}\n\nstd::optional<ScreenPos> RemoteSocketIO::screen_position() { \n  // Clear inbound\n  purgeIn();\n\n  write(\"\\x1b[6n\", 4);\n\n  const auto now = std::chrono::steady_clock::now();\n  auto l = now + std::chrono::seconds(3);\n\n  std::string dsr_response;\n  while (std::chrono::steady_clock::now() < l && connected()) {\n    auto ch = getW();\n    if (ch == '\\x1b') {\n      l = std::chrono::steady_clock::now() + std::chrono::seconds(1);\n      while (std::chrono::steady_clock::now() < l && connected()) {\n        ch = getW();\n        if (ch) {\n          if (isdigit(ch) || ch == ';') {\n            dsr_response.push_back(ch);\n          }\n          if (ch == 'R') {\n            VLOG(1) << \"RemoteSocketIO::screen_position(): DSR: \" << dsr_response;\n            if (auto idx = dsr_response.find(';'); idx != std::string::npos) {\n              auto y = to_number<int>(dsr_response.substr(0, idx));\n              auto x = to_number<int>(dsr_response.substr(idx+1));\n              return {ScreenPos{x, y}};\n            }\n            return std::nullopt;\n          }\n        }\n      }\n      return std::nullopt;\n    }\n  }\n  return std::nullopt;\n}\n\nvoid RemoteSocketIO::HandleTelnetIAC(unsigned char nCmd, unsigned char nParam) {\n  // We should probably start responding to the DO and DONT options....\n  switch (nCmd) {\n  case TELNET_OPTION_NOP: {\n    // TELNET_OPTION_NOP\n  } break;\n  case TELNET_OPTION_BRK: {\n    // TELNET_OPTION_BRK;\n  } break;\n  case TELNET_OPTION_WILL: {\n    // const string s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_WILL\",\n    // nParam);\n    // ::OutputDebugString(s.c_str());\n  } break;\n  case TELNET_OPTION_WONT: {\n    // const string s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_WONT\",\n    // nParam);\n    // ::OutputDebugString(s.c_str());\n  } break;\n  case TELNET_OPTION_DO: {\n    // const string do_s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_DO\",\n    // nParam);\n    // ::OutputDebugString(do_s.c_str());\n    switch (nParam) {\n    case TELNET_OPTION_SUPPRESSS_GA: {\n      char s[4];\n      s[0] = TELNET_OPTION_IAC;\n      s[1] = TELNET_OPTION_WILL;\n      s[2] = TELNET_OPTION_SUPPRESSS_GA;\n      s[3] = 0;\n      write(s, 3, true);\n      // Sent TELNET IAC WILL SUPPRESS GA\n    } break;\n    }\n  } break;\n  case TELNET_OPTION_DONT: {\n    // const string dont_s = fmt::sprintf(\"[Command: %s] [Option: {%d}]\\n\", \"TELNET_OPTION_DONT\",\n    // nParam);\n    // ::OutputDebugString(dont_s.c_str());\n  } break;\n  }\n}\n\nvoid RemoteSocketIO::AddStringToInputBuffer(int start, int end, const char* buffer) {\n  // Add the data to the input buffer\n  for (auto num_sleeps = 0; num_sleeps < 10 && queue_.size() > 32678; ++num_sleeps) {\n    sleep_for(milliseconds(100));\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n\n  if (binary_mode()) {\n    for (auto i = start; i < end; i++) {\n      const uint8_t c = buffer[i];\n      if (skip_next_ && c == 0xff) {\n        skip_next_ = false;\n        continue;\n      }\n      if (c == 0xff) {\n        // TODO(rushfan): If this causes problems, we can add a setting for this\n        VLOG(2) << \"Got an escaped 255 possibly\";\n        skip_next_ = true;\n      } else {\n        skip_next_ = false;\n      }\n      queue_.push_back(c);\n    }\n    return;\n  }\n  for (auto i = start; i < end; i++) {\n    if (static_cast<unsigned char>(buffer[i]) == 255) {\n      if ((i + 1) < end && static_cast<unsigned char>(buffer[i + 1]) == 255) {\n        queue_.push_back(buffer[i + 1]);\n        i++;\n      } else if ((i + 2) < end) {\n        HandleTelnetIAC(buffer[i + 1], buffer[i + 2]);\n        i += 2;\n      } else {\n        // ::OutputDebugString(\"WHAT THE HECK?!?!?!? 255 w/o any options or anything\\r\\n\");\n      }\n    } else if (buffer[i] != '\\0') {\n      // RF20020906: I think the nulls in the input buffer were being bad...\n      // This fixed the problem with CRT to a linux machine and then telnet from\n      // that linux box to the bbs... Hopefully this will fix the Win9x built-in\n      // telnet client as well as TetraTERM.\n      queue_.push_back(buffer[i]);\n    }\n  }\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/remote_socket_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_REMOTE_SOCKET_IO_H\n#define INCLUDED_COMMON_REMOTE_SOCKET_IO_H\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"core/net.h\" // INVALID_SOCKET\n#include \"common/remote_io.h\"\n#include <atomic>\n#include <cstdint>\n#include <mutex>\n#include <deque>\n#include <thread>\n\n#if defined( _WIN32 )\n#define NOCRYPT // Disable include of wincrypt.h\n#include <winsock2.h>\n#else \n\ntypedef int HANDLE;\ntypedef int SOCKET;\n#endif // _WIN32\n\nnamespace wwiv::common {\n\nclass RemoteSocketIO final : public RemoteIO {\n public:\n  static const uint8_t TELNET_OPTION_IAC = 255;\n  static const uint8_t TELNET_OPTION_NOP = 241;\n  static const uint8_t TELNET_OPTION_BRK = 243;\n\n  static const uint8_t TELNET_OPTION_WILL = 251;\n  static const uint8_t TELNET_OPTION_WONT = 252;\n  static const uint8_t TELNET_OPTION_DO = 253;\n  static const uint8_t TELNET_OPTION_DONT = 254;\n\n  static const uint8_t TELNET_SB = 250;\n  static const uint8_t TELNET_SE = 240;\n\n  static const uint8_t TELNET_OPTION_BINARY = 0;\n  static const uint8_t TELNET_OPTION_ECHO = 1;\n  static const uint8_t TELNET_OPTION_RECONNECTION = 2;\n  static const uint8_t TELNET_OPTION_SUPPRESSS_GA = 3;\n  static const uint8_t TELNET_OPTION_TERMINAL_TYPE = 24;\n  static const uint8_t TELNET_OPTION_WINDOW_SIZE = 31;\n  static const uint8_t TELNET_OPTION_TERMINAL_SPEED = 32;\n  static const uint8_t TELNET_OPTION_LINEMODE = 34;\n\n  static bool Initialize();\n\n  RemoteSocketIO(SOCKET socket_handle, bool telnet);\n  ~RemoteSocketIO() override;\n\n  bool open() override;\n  void close(bool bIsTemporary) override;\n  unsigned char getW() override;\n  bool disconnect() override;\n  void purgeIn() override;\n  unsigned int put(unsigned char ch) override;\n  unsigned int read(char *buffer, unsigned int count) override;\n  unsigned int write(const char *buffer, unsigned int count, bool no_translation = false) override;\n  bool connected() override;\n  bool incoming() override;\n  void StopThreads();\n  void StartThreads();\n  unsigned int GetHandle() const override;\n  bool valid_socket() const { return (socket_ != INVALID_SOCKET); }\n\n  // VisibleForTesting\n  void AddStringToInputBuffer(int start, int end, const char* buffer);\n  std::deque<char>& queue() { return queue_; }\n\n  void set_binary_mode(bool b) override;\n  std::optional<ScreenPos> screen_position() override;\n\nprivate:\n  void HandleTelnetIAC(unsigned char nCmd, unsigned char nParam);\n  void InboundTelnetProc();\n\n  std::deque<char> queue_;\n  mutable std::mutex mu_;\n  mutable std::mutex threads_started_mu_;\n  SOCKET socket_{INVALID_SOCKET};\n  std::thread read_thread_;\n  std::atomic<bool> stop_;\n  bool threads_started_{false};\n  bool telnet_{true};\n  bool skip_next_{false};\n};\n\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "common/remote_socket_io_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5.x                            */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/input_range.h\"\n\n#include \"fmt/format.h\"\n#include \"gtest/gtest.h\"\n#include \"common/remote_socket_io.h\"\n\n#include <deque>\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace testing;\n\nstd::string DumpQueue(std::deque<char>& q) {\n  std::ostringstream ss;\n  while (!q.empty()) {\n    uint8_t c = q.front();\n    ss << fmt::format(\"[{:x}]\", c);\n    q.pop_front();\n  }\n  return ss.str();\n}\n\n\nTEST(RemoteSocketIOTest, OneFF) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 4, \"\\x1\\xff\\x0\\x2\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\nTEST(RemoteSocketIOTest, OneFFAtEnd) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 4, \"\\x1\\x0\\x2\\xff\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\nTEST(RemoteSocketIOTest, OneFFAtEndAndOnePast) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 4, \"\\x1\\x0\\x2\\xff\\xff\\xff\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\nTEST(RemoteSocketIOTest, TwoFF) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 5, \"\\x1\\xff\\xff\\x0\\x2\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\nTEST(RemoteSocketIOTest, SplitTwoFF) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 2, \"\\x1\\xff\");\n  io.AddStringToInputBuffer(0, 3,\"\\xff\\x0\\x2\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\nTEST(RemoteSocketIOTest, TwoFFAtEnd) {\n  RemoteSocketIO io(1, true);\n  io.set_binary_mode(true);\n  io.AddStringToInputBuffer(0, 5, \"\\x1\\x0\\x2\\xff\\xff\");\n  EXPECT_EQ(io.queue().size(), 4u) << DumpQueue(io.queue());\n}\n\n//TEST(RemoteSocketIOTest, DSR_Smoke) {\n//  RemoteSocketIO io(2, true);\n//  io.AddStringToInputBuffer(0, 4, \"\\x1b[21;12R\");\n// \n//   Need some way to wait until we receive the write before calling screen_position().\n//  auto pos = io.screen_position();\n//  EXPECT_EQ(21, pos.value().x);\n//  EXPECT_EQ(12, pos.value().y);\n//}\n"
  },
  {
    "path": "common/value/bbsvalueprovider.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/value/bbsvalueprovider.h\"\n\n#include \"core/strings.h\"\n#include \"common/context.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/eval_error.h\"\n\n#include <optional>\n#include <string>\n\nusing namespace wwiv::common::value;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\nusing namespace parser;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common::value {\n\n\n/** Shorthand to create an optional Value */\ntemplate <typename T> static std::optional<Value> val(T&& v) {\n  return std::make_optional<Value>(std::forward<T>(v));\n}\n\nBbsValueProvider::BbsValueProvider(const Config& config,  const common::SessionContext& sess)\n  : ValueProvider(\"bbs\"), config_(config), sess_(sess) {\n}\n\nBbsValueProvider::BbsValueProvider(common::Context& context)\n  : BbsValueProvider(context.config(), context.session_context()) {\n}\n\nstd::optional<Value> BbsValueProvider::value(const std::string& name) const {\n  if (iequals(name, \"name\")) {\n    return val(config_.system_name());\n  }\n  if (iequals(name, \"sysopname\")) {\n    return val(config_.sysop_name());\n  }\n  if (iequals(name, \"phone\")) {\n    return val(config_.system_phone());\n  }\n  if (iequals(name, \"node\")) {\n    return val(sess_.instance_number());\n  }\n  if (iequals(name, \"reg\")) {\n    return val(static_cast<int>(config_.wwiv_reg_number()));\n  }\n  if (iequals(name, \"os\")) {\n    return val(os::os_version_string());\n  }\n  if (iequals(name, \"version\")) {\n    return val(full_version());\n  }\n  if (iequals(name, \"compiletime\")) {\n    return val(wwiv_compile_datetime());\n  }\n  throw eval_error(fmt::format(\"No attribute named 'bbs.{}' exists.\", name));\n}\n\n}"
  },
  {
    "path": "common/value/bbsvalueprovider.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_VALUE_BBSVALUEPROVIDER_H\n#define INCLUDED_SDK_VALUE_BBSVALUEPROVIDER_H\n\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include \"sdk/value/value.h\"\n#include \"sdk/value/valueprovider.h\"\n#include <optional>\n#include <string>\n\nnamespace wwiv {\nnamespace common {\nclass Context;\nclass SessionContext;\n}\n}\n\nnamespace wwiv::common::value {\n\n/**\n * ValueProvider for \"bbs\" or system attributes.\n */\nclass BbsValueProvider final : public sdk::value::ValueProvider {\npublic:\n  /** \n   * Constructs a new ValueProvider.  'user' must remain valid for \n   * the duration of this instance lifetime.\n   */\n  BbsValueProvider(const sdk::Config& config, const SessionContext& sess);\n  explicit BbsValueProvider(Context& context);\n  [[nodiscard]] std::optional<sdk::value::Value> value(const std::string& name) const override;\n\nprivate:\n  const sdk::Config& config_;\n  const SessionContext& sess_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "common/value/uservalueprovider.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"common/value/uservalueprovider.h\"\n\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/eval_error.h\"\n\n#include <optional>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\nusing namespace parser;\nusing namespace wwiv::strings;\n\nnamespace wwiv::common::value {\n\n\n/** Shorthand to create an optional Value */\ntemplate <typename T> static std::optional<sdk::value::Value> val(T&& v) {\n  return std::make_optional<Value>(std::forward<T>(v));\n}\n\nUserValueProvider::UserValueProvider(Context& c, int effective_sl)\n  : UserValueProvider(c.config(), c.u(), effective_sl, c.config().sl(effective_sl)) {\n  fns_.try_emplace(\"editorname\", [&]() {\n    const auto editor_num = user_.default_editor();\n    if (editor_num == 0xff) {\n      return val(\"Full Screen\");\n    }\n    if (editor_num > 0 && editor_num <= stl::size_int(editors_)) {\n      return val(editors_[editor_num - 1].description);\n    }\n    return val(\"Line\");\n  });\n}\n\nUserValueProvider::UserValueProvider(const sdk::Config& config, const sdk::User& user, int effective_sl,\n                                     slrec sl)\n  : ValueProvider(\"user\"), config_(config), user_(user), effective_sl_(effective_sl), sl_(sl) {\n  fns_.try_emplace(\"sl\", [&]() { return val(user_.sl()); });\n  fns_.try_emplace(\"dsl\", [&]() { return val(user_.dsl()); });\n  fns_.try_emplace(\"age\", [&]() { return val(user_.age()); });\n  fns_.try_emplace(\"ar\", [&]() { return val(Ar(user_.ar_int(), true)); });\n  fns_.try_emplace(\"dar\", [&]() { return val(Ar(user_.dar_int(), true)); });\n  fns_.try_emplace(\"name\", [&]() { return val(user_.name()); });\n  fns_.try_emplace(\"real_name\", [&]() { return val(user_.real_name_or_empty()); });\n  fns_.try_emplace(\"regnum\", [&]() { return val(static_cast<int>(user_.wwiv_regnum())); });\n  fns_.try_emplace(\"registered\", [&]() { return val(user_.wwiv_regnum() != 0); });\n  fns_.try_emplace(\"sysop\", [&]() { return val(user_.sl() == 255); });\n  fns_.try_emplace(\"cosysop\", [&]() {\n    const auto so = user_.sl() == 255;\n    const auto cs = (sl_.ability & ability_cosysop) != 0;\n    return val(so || cs);\n  });\n  fns_.try_emplace(\"guest\", [&]() { return val(user_.guest_user()); });\n  fns_.try_emplace(\"validated\", [&]() { return val(effective_sl_ >= config_.validated_sl()); });\n  fns_.try_emplace(\"screenlines\", [&]() { return val(user_.screen_lines()); });\n  fns_.try_emplace(\"screenwidth\", [&]() { return val(user_.screen_width()); });\n  fns_.try_emplace(\"ansi\", [&]() { return val(user_.ansi()); });\n  fns_.try_emplace(\"color\", [&]() { return val(user_.color()); });\n  fns_.try_emplace(\"ansistr\", [&]() { return val(\n    user_.ansi() ? (user_.color() ? \"Color\" : \"Monochrome\") : \"No ANSI\");\n  });\n  fns_.try_emplace(\"pause\", [&]() { return val(user_.pause()); });\n  fns_.try_emplace(\"mailbox_state\", [&]() { return val(user_.mailbox_state()); });\n  fns_.try_emplace(\"extcolors\", [&]() { return val(user_.extra_color()); });\n  fns_.try_emplace(\"optional_lines\", [&]() { return val(user_.optional_val()); });\n  fns_.try_emplace(\"conferencing\", [&]() { return val(user_.use_conference()); });\n  fns_.try_emplace(\"fs_reader\", [&]()\n  {\n    return val(user_.has_flag(User::fullScreenReader));\n  });\n  fns_.try_emplace(\"email\", [&]() { return val(user_.email_address()); });\n  fns_.try_emplace(\"ignore_msgs\", [&]() { return val(user_.ignore_msgs()); });\n  fns_.try_emplace(\"clear_screen\", [&]() { return val(user_.clear_screen()); });\n  fns_.try_emplace(\"auto_quote\", [&]() { return val(user_.auto_quote()); });\n  fns_.try_emplace(\"protocol\", [&]() { return val(user_.default_protocol()); });\n  fns_.try_emplace(\"callsign\", [&]() { return val(user_.callsign()); });\n  fns_.try_emplace(\"street\", [&]() { return val(user_.street()); });\n  fns_.try_emplace(\"city\", [&]() { return val(user_.city()); });\n  fns_.try_emplace(\"state\", [&]() { return val(user_.state()); });\n  fns_.try_emplace(\"zip_code\", [&]() { return val(user_.zip_code()); });\n  fns_.try_emplace(\"last_ipaddress\", [&]() { return val(user_.last_address().to_string()); });\n  fns_.try_emplace(\"last_bps\", [&]() { return val(user_.last_bps()); });\n  fns_.try_emplace(\"laston\", [&]() { return val(user_.laston()); });\n  fns_.try_emplace(\"voice_phone\", [&]() { return val(user_.voice_phone()); });\n  fns_.try_emplace(\"data_phone\", [&]() { return val(user_.data_phone()); });\n  fns_.try_emplace(\"gender\", [&]() { return val(user_.gender()); });\n  fns_.try_emplace(\"menuset\", [&]() { return val(user_.menu_set()); });\n  fns_.try_emplace(\"birthday_mmddyy\", [&]() { return val(user_.birthday_mmddyy()); });\n  fns_.try_emplace(\"email_waiting\", [&]() { return val(user_.email_waiting()); });\n  fns_.try_emplace(\"messages_posted\", [&]() { return val(user_.messages_posted()); });\n  fns_.try_emplace(\"posts_today\", [&]() { return val(user_.posts_today()); });\n  fns_.try_emplace(\"posts_net\", [&]() { return val(user_.posts_net()); });\n  fns_.try_emplace(\"messages_read\", [&]() { return val(user_.messages_read()); });\n  fns_.try_emplace(\"email_today\", [&]() { return val(user_.email_today()); });\n  fns_.try_emplace(\"email_sent_local\", [&]() { return val(user_.email_sent()); });\n  fns_.try_emplace(\"feedback_sent\", [&]() { return val(user_.feedback_sent()); });\n  fns_.try_emplace(\"email_sent_net\", [&]() { return val(user_.email_net()); });\n  fns_.try_emplace(\"chains_run\", [&]() { return val(user_.chains_run()); });\n  fns_.try_emplace(\"uploaded\", [&]() { return val(user_.uploaded()); });\n  fns_.try_emplace(\"uk\", [&]() { return val(user_.uk()); });\n  fns_.try_emplace(\"downloaded\", [&]() { return val(user_.downloaded()); });\n  fns_.try_emplace(\"dk\", [&]() { return val(user_.dk()); });\n  fns_.try_emplace(\"show_controlcodes\", [&]() { return val(user_.has_flag(User::msg_show_controlcodes)); });\n  fns_.try_emplace(\"twentyfour_clock\", [&]() { return val(user_.twentyfour_clock()); });\n\n}\n\nUserValueProvider::UserValueProvider(Context& c)\n    : UserValueProvider(c, c.session_context().effective_sl() != 0\n                               ? c.session_context().effective_sl()\n                               : c.u().sl()) {}\n\n\nstd::optional<Value> UserValueProvider::value(const std::string& name) const {\n  if (const auto it = fns_.find(name); it != std::end(fns_)) {\n    return it->second();\n  }\n  throw eval_error(fmt::format(\"No user attribute named 'user.{}' exists.\", name));\n}\n\n}"
  },
  {
    "path": "common/value/uservalueprovider.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_VALUEPROVIDER_USERVALUEPROVIDER_H\n#define INCLUDED_SDK_VALUEPROVIDER_USERVALUEPROVIDER_H\n\n#include \"common/context.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include \"sdk/value/value.h\"\n#include \"sdk/value/valueprovider.h\"\n#include <optional>\n#include <string>\n\nnamespace wwiv::common::value {\n\n/**\n * ValueProvider for \"user\" record attributes.\n */\nclass UserValueProvider final : public sdk::value::ValueProvider {\npublic:\n  /** \n   * Constructs a new ValueProvider.  'user' must remain valid for \n   * the duration of this instance lifetime.\n   */\n  UserValueProvider(const sdk::Config& config, const sdk::User& user, int effective_sl, slrec sl);\n  explicit UserValueProvider(Context& c);\n  UserValueProvider(Context& context, int effective_sl);\n  [[nodiscard]] std::optional<sdk::value::Value> value(const std::string& name) const override;\n\nprivate:\n  typedef std::function<std::optional<sdk::value::Value>()> makeval_fn;\n  std::map<const std::string, makeval_fn> fns_;\n  const sdk::Config& config_;\n  const sdk::User& user_;\n  int effective_sl_;\n  slrec sl_;\n  std::vector<editorrec> editors_;\n  sdk::Chains chains_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "common/workspace.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"common/workspace.h\"\n\n#include \"common/context.h\"\n#include \"common/output.h\"\n#include \"core/file.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include <string>\n\nusing namespace wwiv::core;\n\nnamespace wwiv::common {\n\nbool use_workspace;\n\nvoid LoadFileIntoWorkspace(Context& context, const std::filesystem::path& filename,\n                           bool no_edit_allowed, bool silent_mode) {\n  TextFile tf(filename, \"rt\");\n  if (!tf) {\n    return;\n  }\n  const auto contents = tf.ReadFileIntoString();\n  if (contents.empty()) {\n    return;\n  }\n\n  TextFile input_msg(FilePath(context.session_context().dirs().temp_directory(), INPUT_MSG), \"wt\");\n  input_msg.Write(contents);\n\n  const auto ok_fsed = context.u().default_editor() != 0;\n  use_workspace = (no_edit_allowed || !ok_fsed);\n\n  if (!silent_mode) {\n    bout.outstr(\"\\r\\nFile loaded into workspace.\\r\\n\\n\");\n    if (!use_workspace) {\n      bout.outstr(\"Editing will be allowed.\\r\\n\");\n    }\n  }\n}\n\n} // namespace wwiv::common\n"
  },
  {
    "path": "common/workspace.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_COMMON_WORKSPACE_H\n#define INCLUDED_COMMON_WORKSPACE_H\n\n#include \"common/context.h\"\n#include <filesystem>\n\nnamespace wwiv::common {\n\nextern bool use_workspace;\n\nvoid LoadFileIntoWorkspace(Context& context,\n                           const std::filesystem::path& file_path, bool no_edit_allowed,\n                           bool silent_mode = false);\n\n} // namespace wwiv::common\n\n#endif\n"
  },
  {
    "path": "contributing.md",
    "content": "# Contributing\n\nThank you for your interest in contributing to WWIV. \n<strong>We love pull requests from everyone. Here's how you can help!</strong>\n\n## GitHub Issue Tracker\n\n* WWIV uses the [Github issue tracker](https://github.com/wwivbbs/wwiv/issues) as the main venue for\nbug reports, feature requests, enhancement requests, and pull requests.\n* Please do not use the issue tracker for general support, please drop in on \nIRC and feel free to ask questions.  Bear in mind that most of us are idling\non IRC using an IRC bouncer, so expect high latency on replies.\n\n## IRC\n\nThe dev team and fellow SysOps hangs out on IRC at:\n\n* Server: irc.wwivbbs.org:6667\n* Channel: #WWIV\n* <a href=\"irc://irc.wwivbbs.org:6667/wwiv\">Click to Join IRC</a>\n* For IRC logs and stats check out [Venom's Lair IRC Page](http://venomslair.com/irc.php)\n\n## Issues and Labels\n\n* WWIV uses labels to track platform, feature, enhancement, and type of bug. \n* Here are some labels:\n...\n\n[WWIV Releases and Versioning](http://wwivbbs.readthedocs.org/en/latest/Development/wwiv_releases_and_versioning/)\n\n## Bug Reports\n\nWe love good bug reports!  A good bug report is:\n* Specific: Ideally somebody can fix the bug without needing to figure our where to look.  \n* Actionable: Knowing what was expected vs. what actually happened is critical.\n* Not a duplicate: Please search the existing issues to see if this has already been reported\n* Versioned: Please indicate what version of the software you are using (a build number of jenkins, or sha of the repository if you built it from git.\n* Environmental: Please indicate the OS and version you are using.  If you have multiple OSes available knowing if this is specific to one operating system or version of operating system is helpful.\n\nYes, this is a lot to ask for, but the more specific bug reports are, the more quickly someone can grab it and fix it.  As much (or as little) information you have helps, but the more the merrier and the more likely it'll get quickly fixed.\n\n## Pull Requests\n\nWe love Pull Requests! Good pull requests for features, enhancements and bug reports are the key to any open source project. Ideally they will also solve or implement one feature, enhancement request or bug report so it is easy to merge, and in the case of problems, revert. \n\n<strong>Please talk to us first</strong> before you spend a nontrivial amount of time on a new coding project.  We're happy to help offer suggestions, help vet design ideas, and also warn about gotchas in the code before you wander down a path that can cause problems that can keep a PR from being merged.  Please drop by IRC and ask away.\n\nHere's the best way to work with the WWIV git repository:\n\n1. [Fork](https://help.github.com/articles/fork-a-repo/), then clone your fork, and configure the remotes:\n    \n    ```bash\n    # Create a directory for your fork's clone.\n    mkdir git\n    chdir git\n    # Clone your fork into the current directory (git).\n    # Use your GitHub username instead of <em>YOUR-USERNAME</em>\n    git clone https://github.com/<em>YOUR-USERNAME</em>/wwiv.git\n    # Change directory into the wwiv directory of your clone/\n    chdir wwiv\n    # Add the remotes for the upstream repository (wwivbbs/wwiv)\n    git remote add upstream https://github.com/wwivbbs/wwiv.git\n    ```\n    \n2. If you have done step 1 a while ago, pull from the upstream repository to update your clone with the latest from wwivbbs/wwiv.\n    ```bash\n    # make sure your branch is back onto the \"main\" branch\n    git checkout main\n    # pull (this is a fetch + merge) in the changes from the wwivbbs/wwiv repository.\n    git pull --recurse upstream main\n    # push the changes from wwivbbs/wwiv to your fork on github.\n    git push\n    ```\n    \n3. Create a new branch off of main for your feature, enhancement, or bug fix and let GitHub know about your branch.\n\n    ```bash\n    git checkout -b <MY-BRANCH-NAME>\n    git push origin <MY-BRANCH-NAME>\n    ```    \n\n4. Make your changes by editing the files and committing changes to your local repository.  Please use good commit messages that explain the changes and also reference github issues as necessary.\n\n5. Merge any new changes from the wwivbbs/wwiv repository into your development branch\n\n    ```bash\n    git pull --recurse upstream main\n    ```    \n    \n6. Push your changes from your local machine to your fork on github.\n\n    ```bash\n    git push origin <MY-BRANCH-NAME>\n    ```\n    \n7. Open a [Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear and concise\n   title and description of the changes.  Please reference any issues on GitHub as needed. \n   [pr]: https://github.com/wwivbbs/wwiv/compare\n\n8. At this point you're waiting on us. We will endeavour to approve requests or comment within a week.\nPlease remember this is a just hobby. :-) We may suggest\nsome changes or improvements or alternatives to your suggestions or approve them outright.\n\n9. Some things that will increase the chance that your pull request is accepted:\n\n* Drop in on IRC and talk about your changes.\n* Fix an open issue.\n* Write a [good commit message][commit].\n* Explain how you tested the changes, any known limitations on Windows version or Linux.\n\n[commit]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html\n"
  },
  {
    "path": "core/CMakeLists.txt",
    "content": "# CMake for WWIV\r\n\r\nfind_package(cereal CONFIG REQUIRED)\r\n\r\nadd_library(core\r\n  \"clock.cpp\"\r\n  \"cp437.cpp\"\r\n  \"crc32.cpp\"\r\n  \"command_line.cpp\"\r\n  \"connection.cpp\"\r\n  \"datetime.cpp\"\r\n  \"eventbus.cpp\"\r\n  \"fake_clock.cpp\"\r\n  \"file.cpp\"\r\n  \"file_lock.cpp\"\r\n  \"findfiles.cpp\"\r\n  \"graphs.cpp\"\r\n  \"inifile.cpp\"\r\n  \"ip_address.cpp\"\r\n  \"jsonfile.cpp\"\r\n  \"log.cpp\"\r\n  \"md5.cpp\"\r\n  \"net.cpp\"\r\n  \"os.cpp\"\r\n  \"semaphore_file.cpp\"\r\n  \"socket_connection.cpp\"\r\n  \"socket_exceptions.cpp\"\r\n  \"strcasestr.cpp\"\r\n  \"strings.cpp\"\r\n  \"textfile.cpp\"\r\n  \"uuid.cpp\"\r\n  \"version.cpp\"\r\n  \"parser/ast.cpp\"\r\n  \"parser/lexer.cpp\"\r\n  \"parser/token.cpp\"\r\n  )\r\n\r\nif(UNIX) \r\n  target_sources(core PRIVATE\r\n    \"file_unix.cpp\"\r\n    \"os_unix.cpp\"\r\n    \"wfndfile_unix.cpp\"\r\n  )\r\nendif()\r\n\r\nif(WIN32)\r\n\r\n  target_sources(core PRIVATE\r\n    \"file_win32.cpp\"\r\n    \"os_win.cpp\"\r\n    \"pipe.cpp\"\r\n    \"pipe_win32.cpp\"\r\n    \"wfndfile_win32.cpp\"\r\n  )\r\nendif()\r\n\r\nif(OS2) \r\n  target_link_libraries(core PUBLIC libcx)\r\n  target_sources(core PRIVATE\r\n    \"file_os2.cpp\"\r\n    \"os_os2.cpp\"\r\n    \"pipe.cpp\"\r\n    \"pipe_os2.cpp\"\r\n    \"wfndfile_os2.cpp\"\r\n  )\r\nendif()\r\n\r\n\r\nconfigure_file(version_internal.h.in version_internal.h @ONLY)\r\n\r\n#target_compile_options(core PRIVATE  /fsanitize=address)\r\ntarget_link_libraries(core PUBLIC fmt::fmt-header-only)\r\ntarget_link_libraries(core PUBLIC cereal::cereal)\r\ntarget_include_directories(core PRIVATE ${CMAKE_CURRENT_BINARY_DIR})\r\n\r\nif (UNIX)\r\n  if (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\r\n    # using regular Clang or AppleClang\r\n  \ttarget_link_libraries(core PUBLIC c++fs)\r\n  else()\r\n  \ttarget_link_libraries(core PUBLIC stdc++fs)\r\n  endif()\r\nendif()\r\n\r\n# Tests\r\nif (WWIV_BUILD_TESTS)\r\n\r\n  add_library(core_fixtures \r\n    \"test/file_helper.cpp\"\r\n    \"test/wwivtest.cpp\"\r\n  )\r\n  set_max_warnings(core_fixtures)\r\n\r\n  target_link_libraries(core_fixtures core GTest::gtest)\r\n  add_executable(core_tests\r\n    \"core_test_main.cpp\"\r\n    \"clock_test.cpp\"\r\n    \"cp437_test.cpp\"\r\n    \"crc32_test.cpp\"\r\n    \"command_line_test.cpp\"\r\n    \"datetime_test.cpp\"\r\n    \"datafile_test.cpp\"\r\n    \"eventbus_test.cpp\"\r\n    \"fake_clock_test.cpp\"\r\n    \"findfiles_test.cpp\"\r\n    \"file_test.cpp\"\r\n    \"inifile_test.cpp\"\r\n    \"ip_address_test.cpp\"\r\n    \"log_test.cpp\"\r\n    \"md5_test.cpp\"\r\n    \"net_test.cpp\"\r\n    \"os_test.cpp\"\r\n    \"scope_exit_test.cpp\"\r\n    \"semaphore_file_test.cpp\"\r\n    \"stl_test.cpp\"\r\n    \"strings_test.cpp\"\r\n    \"textfile_test.cpp\"\r\n    \"transaction_test.cpp\"\r\n    \"uuid_test.cpp\"\r\n    \"parser/ast_test.cpp\"\r\n    \"parser/lexer_test.cpp\"\r\n  )\r\n\r\n  include(GoogleTest)\r\n  target_link_libraries(core_tests core_fixtures core GTest::gtest)\r\n  gtest_discover_tests(core_tests EXTRA_ARGS \"--wwiv_testdata=${CMAKE_CURRENT_SOURCE_DIR}/testdata\")\r\n  \r\n  if(WIN32)\r\n    target_sources(core_tests PRIVATE\r\n    \"pipe_test.cpp\"\r\n    )\r\n  endif()\r\n\r\n  if(OS2)\r\n    target_sources(core_tests PRIVATE\r\n    \"pipe_test.cpp\"\r\n    )\r\n    target_link_libraries(core_tests libcx)\r\n  endif()\r\n\r\nendif()\r\n"
  },
  {
    "path": "core/callable/LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2013, 2016 Stephan Hohe\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "core/callable/README.md",
    "content": "# callable.hpp\n\nA C++ 11 template for type traits of callables (like functions, objects\nwith `operator()`, lambda functions, ...).\n\nThe template, `callable_traits`, can be used to determine\nuseful properties of callable objects, like return type, number of\narguments and types of the individual arguments.\n\nIt is especially useful in template functions/... that handle callable\nobjects, for example as callbacks. `callable_traits` allows the code \nto treat different types of callables uniformly without wrapping them\nin a `std::function<>`.\n\n## Features\n### Callables\n\nCallables are things that can be called with `()`:\n\n- Functions\n- Function pointers\n- Objects with `operator()`\n- `std::function<...>`\n- Lambda functions\n\n`callable_traits` can be used to treat all these different kinds of \ncallables uniformly in a template function.\n\n### Traits\n\n`callable_traits` deduces the following properties from the\ntype `T` of a callable:\n\n- The return type\n\n        typename callable_traits<T>::return_type\n\n- The number of arguments\n\n        callable_traits<T>::argc\n\n- The individual argument types\n\n        typename callable_traits<T>::template argument_type<N>\n\n- A function type representing the call:\n\n        typename callable_traits<T>::function_type\n\n### Example\n\n    template<typename Callable>\n    void metainfo(Callable f) {\n       std::cout << callable_traits<Callable>::argc << \" arguments\" << std:endl;\n    }\n\n## Compilation\n\n### Library\n\nThe library is header only, so it doesn't need to be compiled. Just\ninclude the header file when you need it.\n\n### Test cases\n\nTo compile the test cases, you need:\n\n- SCons as a build tool\n- Boost.Test for the test cases\n\nWith these tools you can compile `callable_test` by running scons in the\nmain directory:\n\n    scons\n\n## License\n\nMIT. See `LICENSE.txt` for more details.\n\n"
  },
  {
    "path": "core/callable/callable.hpp",
    "content": "\n#if !defined(CALLABLE_CALLABLE_HPP_INCLUDED)\n#define CALLABLE_CALLABLE_HPP_INCLUDED\n\n#include <stddef.h>\n#include <functional>\n#include \"helpers.hpp\"\n#include \"function.hpp\"\n#include \"member_function.hpp\"\n#include \"functor.hpp\"\n\n// There are three basic kinds of callable types\n// function types\nstruct function_tag {};\n// function pointer types\nstruct function_ptr_tag {};\n// classes with operator()\nstruct functor_tag {};\n\n\nnamespace detail {\n\n/** Define traits for a operator() member function pointer type */\n\n// classes with operator()\ntemplate<typename Callable>\nstruct callable_traits : functor_traits<Callable> {\n\ttypedef functor_tag callable_category;\n};\n\n// functions\ntemplate<typename Ret, typename... Args>\nstruct callable_traits<Ret (Args...)> : function_traits<Ret (Args...)> {\n\ttypedef function_tag callable_category;\n};\n\n// function pointers\ntemplate<typename Ret, typename... Args>\nstruct callable_traits<Ret (*)(Args...)> : function_traits<Ret (Args...)> {\n\ttypedef function_ptr_tag callable_category;\n};\n\n} // namespace detail\n\n\n// Main template\n\n/** Traits for a callable (function/functor/lambda/...) */\ntemplate<typename Callable>\nstruct callable_traits : detail::callable_traits<detail::remove_cvref_t<Callable>> {\n};\n\n\n/** Convert a callable to a std::function<> */\ntemplate<typename Callable>\nstd::function<typename callable_traits<Callable>::function_type> to_stdfunction(Callable fun) {\n\tstd::function<typename callable_traits<Callable>::function_type> stdfun(std::forward<Callable>(fun));\n\treturn stdfun;\n}\n\n#endif // CALLABLE_CALLABLE_HPP_INCLUDED\n\n"
  },
  {
    "path": "core/callable/function.hpp",
    "content": "\n#if !defined(CALLABLE_FUNCTION_HPP_INCLUDED)\n#define CALLABLE_FUNCTION_HPP_INCLUDED\n\n#include \"helpers.hpp\"\n#include <cstddef>\n\nnamespace detail {\n\nnamespace {\n\n/** Define traits for a function type */\ntemplate<typename Fun>\nstruct function_traits;\n\ntemplate<typename Ret, typename... Args>\nstruct function_traits<Ret (Args...)> {\n\ttypedef Ret function_type(Args...);\n\ttypedef Ret return_type;\n\tstatic constexpr std::size_t argc = types_count<Args...>::value;\n\n\ttemplate<std::size_t N>\n\tusing argument_type = typename types_n<N, Args...>::type;\n};\n\ntemplate<typename Ret, typename... Args>\nconst std::size_t function_traits<Ret (Args...)>::argc;\n\n} // namespace\n\n} // namespace detail\n\n\ntemplate<typename Func>\nstruct function_traits : detail::function_traits<detail::remove_cvref_t<Func>> {\n};\n\ntemplate<typename Func>\nstruct function_traits<Func*> : detail::function_traits<detail::remove_cvref_t<Func>> {\n};\n\n#endif // CALLABLE_FUNCTION_HPP_INCLUDED\n\n"
  },
  {
    "path": "core/callable/functor.hpp",
    "content": "\n#if !defined(CALLABLE_FUNCTOR_HPP_INCLUDED)\n#define CALLABLE_FUNCTOR_HPP_INCLUDED\n\n#include \"helpers.hpp\"\n#include \"function.hpp\"\n#include \"member_function.hpp\"\n\nnamespace detail {\n\ntemplate<typename Class>\nusing call_operator_traits = member_function_traits<decltype(&Class::operator())>;\n\n// classes with operator()\ntemplate<typename Class>\nstruct functor_traits : function_traits<typename call_operator_traits<Class>::function_type> {\n\ttypedef call_operator_traits<Class> call_operator; \n};\n\n} // namespace detail\n\n\ntemplate<typename Class>\nstruct functor_traits : detail::functor_traits<detail::remove_cvref_t<Class>> {\n};\n\n#endif // CALLABLE_FUNCTOR_HPP_INCLUDED\n\n"
  },
  {
    "path": "core/callable/helpers.hpp",
    "content": "\n#if !defined(CALLABLE_HELPERS_HPP_INCLUDED)\n#define CALLABLE_HELPERS_HPP_INCLUDED\n\n#include <cstddef>\n\nnamespace detail {\n\n/** Remove reference and cv qualification */\ntemplate<typename T>\nusing remove_cvref_t = typename std::remove_cv< typename std::remove_reference<T>::type >::type;\n\n\n/** Count the number of types given to the template */\ntemplate<typename... Types>\nstruct types_count;\n\ntemplate<>\nstruct types_count<> {\n\tstatic constexpr std::size_t value = 0;\n};\n\n\ntemplate<typename Type, typename... Types>\nstruct types_count<Type, Types...> {\n\tstatic constexpr std::size_t value = types_count<Types...>::value + 1;\n};\n\n\n/** Get the nth type given to the template */\ntemplate<std::size_t n, typename... Types>\nstruct types_n;\n\ntemplate<std::size_t N, typename Type, typename... Types>\nstruct types_n<N, Type, Types...> : types_n<N-1, Types...> {\n};\n\ntemplate<typename Type, typename... Types>\nstruct types_n<0, Type, Types...> {\n\ttypedef Type type;\n};\n\n\n/** Test if a type is in a list given types */\ntemplate<typename Q, typename... Ts>\nstruct types_has;\n\ntemplate<typename Q>\nstruct types_has<Q> {\n\tstatic constexpr bool value = false;\n};\n\ntemplate<typename Q, typename... Ts>\nstruct types_has<Q, Q, Ts...> {\n\tstatic constexpr bool value = true;\n};\n\ntemplate<typename Q, typename T, typename... Ts>\nstruct types_has<Q, T, Ts...> : types_has<Q, Ts...> {\n};\n\n\n} // namespace detail\n\n#endif // CALLABLE_HELPERS_HPP_INCLUDED\n\n"
  },
  {
    "path": "core/callable/member_function.hpp",
    "content": "\n#if !defined(CALLABLE_MEMBER_FUNCTION_HPP_INCLUDED)\n#define CALLABLE_MEMBER_FUNCTION_HPP_INCLUDED\n\n#include \"helpers.hpp\"\n\nnamespace detail {\n\n// Tags for member function qualifiers\nstruct const_tag {};\nstruct volatile_tag {};\nstruct lref_tag {};\nstruct rref_tag {};\nstruct noexcept_tag {};\n\nnamespace {\n\ntemplate<typename Class, typename Func, typename... Qual>\nstruct member_function_traits_q : function_traits<Func> {\n\ttypedef Class class_type;\n\tstatic constexpr bool is_const = types_has<const_tag, Qual...>::value;\n\tstatic constexpr bool is_volatile = types_has<volatile_tag, Qual...>::value;\n\tstatic constexpr bool is_lref = types_has<lref_tag, Qual...>::value;\n\tstatic constexpr bool is_rref = types_has<rref_tag, Qual...>::value;\n#if __cpp_noexcept_function_type\n\tstatic constexpr bool is_noexcept = types_has<noexcept_tag, Qual...>::value;\n#endif\n};\n\n// We need these until C++17 in case someone takes the address of one\n// of those static variables or passses it by reference to a function\ntemplate<typename Class, typename Func, typename... Qual>\nconst bool member_function_traits_q<Class, Func, Qual...>::is_const;\ntemplate<typename Class, typename Func, typename... Qual>\nconst bool member_function_traits_q<Class, Func, Qual...>::is_volatile;\ntemplate<typename Class, typename Func, typename... Qual>\nconst bool member_function_traits_q<Class, Func, Qual...>::is_lref;\ntemplate<typename Class, typename Func, typename... Qual>\nconst bool member_function_traits_q<Class, Func, Qual...>::is_rref;\n#if __cpp_noexcept_function_type\ntemplate<typename Class, typename Func, typename... Qual>\nconst bool member_function_traits_q<Class, Func, Qual...>::is_noexcept;\n#endif\n\n} // namespace\n\n\ntemplate<typename MemFun>\nstruct member_function_traits;\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...)>\n\t: member_function_traits_q<Class, Ret (Args...)> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) &>\n\t: member_function_traits_q<Class, Ret (Args...), lref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const &>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, lref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile &>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag, lref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile &>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag, lref_tag> {\n};\n\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) &&>\n\t: member_function_traits_q<Class, Ret (Args...), rref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const &&>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, rref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile &&>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag, rref_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile &&>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag, rref_tag> {\n};\n\n\n#if __cpp_noexcept_function_type\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) & noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), lref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const & noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, lref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile & noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag, lref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile & noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag, lref_tag, noexcept_tag> {\n};\n\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) && noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), rref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const && noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, rref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) volatile && noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), volatile_tag, rref_tag, noexcept_tag> {\n};\n\ntemplate<typename Class, typename Ret, typename... Args>\nstruct member_function_traits<Ret (Class::*)(Args...) const volatile && noexcept>\n\t: member_function_traits_q<Class, Ret (Args...), const_tag, volatile_tag, rref_tag, noexcept_tag> {\n};\n#endif // __cpp_noexcept_function_type\n\n} // namespace detail\n\n\ntemplate<typename MemFunPtr>\nstruct member_function_traits : detail::member_function_traits<detail::remove_cvref_t<MemFunPtr>> {\n};\n\n#endif // CALLABLE_MEMBER_FUNCTION_HPP_INCLUDED\n\n"
  },
  {
    "path": "core/cereal_utils.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CEREAL_UTILS_H\n#define INCLUDED_SDK_CEREAL_UTILS_H\n\n// ReSharper disable CppUnusedIncludeDirective\n#include \"core/stl.h\"\n#include <stdexcept>\n#include <vector>\n#include <cereal/access.hpp>\n#include <cereal/cereal.hpp>\n#include <cereal/types/memory.hpp>\n#include <cereal/types/map.hpp>\n#include <cereal/types/set.hpp>\n#include <cereal/types/string.hpp>\n#include <cereal/types/vector.hpp>\n\n\nnamespace cereal {\n\n#define SERIALIZE(n, field)                                                                        \\\n  do {                                                                                             \\\n    try {                                                                                          \\\n      ar(cereal::make_nvp(#field, (n).field));                                                     \\\n    } catch (const cereal::Exception&) {                                                           \\\n      ar.setNextName(nullptr);                                                                     \\\n    }                                                                                              \\\n  } while (false)\n\n#define SERIALIZE_NVP(name, field)                                                                        \\\n  do {                                                                                             \\\n    try {                                                                                          \\\n      ar(cereal::make_nvp(name, field));                                                     \\\n    } catch (const cereal::Exception&) {                                                           \\\n      ar.setNextName(nullptr);                                                                     \\\n    }                                                                                              \\\n  } while (false)\n\n\ntemplate <typename T>\nstd::string to_enum_string(const T& t, const std::vector<std::string>& names) {\n  try {\n    return names.at(static_cast<int>(t));\n  } catch (std::out_of_range&) {\n    return names.at(0);\n  }\n}\n\ntemplate <typename T>\nT from_enum_string(const std::string& v, const std::vector<std::string>& names) {\n  try {\n    for (auto i = 0; i < wwiv::stl::ssize(names); i++) {\n      if (v == names.at(i)) {\n        return static_cast<T>(i);\n      }\n    }\n  } catch (std::out_of_range&) {\n    // NOP\n  }\n  return static_cast<T>(0);\n}\n\n} // namespace cereal\n\n#endif"
  },
  {
    "path": "core/clock.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/clock.h\"\n\n#include \"core/datetime.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\nDateTime SystemClock::Now() const noexcept {\n  return DateTime::now();\n}\n\nvoid SystemClock::SleepFor(std::chrono::duration<double> d) { wwiv::os::sleep_for(d); }\n\n}\n"
  },
  {
    "path": "core/clock.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_CLOCK_H\n#define INCLUDED_CORE_CLOCK_H\n\n#include \"core/datetime.h\"\n#include <chrono>\n\nnamespace wwiv::core {\n\nclass Clock {\npublic:\n  Clock() = default;\n\n  [[nodiscard]] virtual DateTime Now() const noexcept = 0;\n  virtual void SleepFor(std::chrono::duration<double>) = 0;\n\n  virtual ~Clock() = default;\n};\n\nclass SystemClock final : public Clock {\npublic:\n  SystemClock() = default;\n\n  virtual ~SystemClock() = default;\n\n  [[nodiscard]] DateTime Now() const noexcept override;\n  void SleepFor(std::chrono::duration<double>);\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/clock_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/clock.h\"\n#include \"core/datetime.h\"\n\nusing namespace wwiv::core;\n\nTEST(Clock, Simple) {\n  const auto start = DateTime::now();\n\n  const SystemClock c{};\n  const auto mid = c.Now();\n\n  const auto end = DateTime::now();\n\n  EXPECT_GE(mid, start);\n  EXPECT_LE(mid, end);\n}\n"
  },
  {
    "path": "core/command_line.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include <cctype>\n#include <filesystem>\n#include <iomanip>\n#include <iostream>\n#include <map>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\n\nnamespace wwiv::core {\n\nCommandLineArgument::CommandLineArgument(std::string name, char key,\n                                         std::string help_text,\n                                         std::string default_value,\n                                         std::string environment_variable)\n  : name_(std::move(name)), key_(static_cast<char>(std::toupper(key))), help_text_(\n        std::move(help_text)),\n    default_value_(std::move(default_value)), environment_variable_(std::move(environment_variable)) {\n}\n\nstd::string CommandLineArgument::help_text() const { return help_text_; }\n\nstd::string CommandLineArgument::default_value() const {\n  const auto env = environment_variable(environment_variable_);\n  return env.empty() ? default_value_ : env;\n}\n\nCommandLineCommand::CommandLineCommand(std::string name, std::string help_text)\n  : name_(std::move(name)), help_text_(std::move(help_text)) {\n}\n\nstatic std::string CreateProgramName(const std::string& arg) {\n  const std::filesystem::path p{arg};\n  return p.filename().string();\n}\n\nCommandLine::CommandLine(const std::vector<std::string>& args, const std::string& dot_argument)\n  : CommandLineCommand(\"\", \"\"), \n    program_name_(CreateProgramName(args[0])),\n    program_path_(std::filesystem::path(args[0])) {\n  set_raw_args(args);\n  set_dot_argument(dot_argument);\n}\r\n\r\nint CommandLineValue::as_int() const noexcept {\r\n    try {\r\n      return std::stoi(value_);\r\n    } catch (const std::logic_error&) {\r\n      return 0;\r\n    }\r\n  }\r\n\r\n\nstatic std::vector<std::string> make_args(int argc, char** argv) {\n  std::vector<std::string> v;\n  for (auto i = 0; i < argc; i++) {\n    v.emplace_back(argv[i]);\n  }\n  return v;\n}\n\nCommandLine::CommandLine(int argc, char** argv, const std::string& dot_argument)\n  : CommandLine(make_args(argc, argv), dot_argument) {\n}\n\nbool CommandLine::Parse() {\n  try {\n    if (!ParseImpl()) {\n      std::clog << \"Unable to parse command line.\" << std::endl;\n      return false;\n    }\n  } catch (const unknown_argument_error& e) {\n    std::clog << \"Unable to parse command line.\" << std::endl;\n    std::clog << e.what() << std::endl;\n    return false;\n  }\n\n  if (raw_args_.size() <= 1 && !no_args_allowed()) {\n    std::clog << \"No command line arguments specified.\" << std::endl;\n    std::cout << GetUsage();\n    std::cout << GetHelp();\n    return false;\n  }\n\n  bbsdir_ = sarg(\"bbsdir\");\n  bindir_ = sarg(\"bindir\");\n  configdir_ = sarg(\"configdir\");\n  logdir_ = sarg(\"logdir\");\n  verbose_ = iarg(\"v\");\n  return true;\n}\n\nbool CommandLine::ParseImpl() {\n  return CommandLineCommand::Parse(1) >= size_int(raw_args_);\n}\n\nint CommandLine::Execute() { return CommandLineCommand::Execute(); }\n\nbool CommandLineCommand::add_argument(const CommandLineArgument& cmd) {\n  // Add cmd to the list of allowable arguments, and also set\n  // a default empty value.\n  args_allowed_.emplace(cmd.name_, cmd);\n  args_.emplace(cmd.name_, CommandLineValue(cmd.default_value(), true));\n  return true;\n}\n\nbool CommandLineCommand::SetNewDefault(const std::string& key, const std::string& value) {\n  return SetCommandLineArgument(key, value, true);\n}\n\nbool CommandLineCommand::HandleCommandLineArgument(const std::string& key,\n                                                   const std::string& value) {\n  return SetCommandLineArgument(key, value, false);\n}\n\n\nbool CommandLineCommand::SetCommandLineArgument(const std::string& key, const std::string& value,\n                                                bool default_value) {\n  args_.erase(key); // \"emplace\" doesn't replace, so erase it first.\n  if (!contains(args_allowed_, key)) {\n    VLOG(1) << \"No arg: \" << key << \" to use for dot argument.\";\n    return false;\n  }\n  if (at(args_allowed_, key).is_boolean) {\n    if (value == \"N\" || value == \"0\" || value == \"n\" || iequals(value, \"false\")) {\n      args_.emplace(key, CommandLineValue(\"false\", default_value));\n    } else {\n      args_.emplace(key, CommandLineValue(\"true\", default_value));\n    }\n  } else {\n    args_.emplace(key, CommandLineValue(value, default_value));\n  }\n  return true;\n}\n\nbool CommandLineCommand::contains_arg(const std::string& name) const noexcept {\n  return contains(args_, name);\n}\n\nCommandLineValue CommandLineCommand::arg(const std::string& name) const {\n  if (!contains(args_, name)) {\n    VLOG(1) << \"Unknown argument name: \" << name << std::endl;\n    return CommandLineValue(\"\", true);\n  }\n  return at(args_, name);\n}\n\nbool CommandLineCommand::AddStandardArgs() {\n  add_argument(BooleanCommandLineArgument(\"help\", '?', \"Displays Help\", false));\n  return true;\n}\n\nstd::string CommandLineCommand::ArgNameForKey(char key) {\n  for (const auto& a : args_allowed_) {\n    if (key == a.second.key_) {\n      return a.first;\n    }\n  }\n  return {};\n}\n\nstatic bool is_shortarg_start(char c) {\n#ifdef _WIN32\n  return (c == '/' || c == '-');\n#else\n  return (c == '-');\n#endif\n}\n\nint CommandLineCommand::Parse(int start_pos) {\n  for (auto i = start_pos; i < wwiv::stl::ssize(raw_args_); i++) {\n    const std::string& s{raw_args_[i]};\n    if (s.empty()) {\n      continue;\n    }\n    if (s == \"--\") {\n      // Everything after this should be positional args.\n      for (++i; i < wwiv::stl::ssize(raw_args_); i++) {\n        remaining_.emplace_back(raw_args_[i]);\n      }\n      continue;\n    }\n    if (starts_with(s, \"--\")) {\n      const auto delims = SplitString(s, \"=\");\n      const auto key = delims[0].substr(2);\n      const auto value = (delims.size() > 1) ? delims[1] : \"\";\n      if (!contains(args_allowed_, key)) {\n        if (unknown_args_allowed()) {\n          continue;\n        }\n        throw unknown_argument_error(StrCat(\"Command: \", name(), \"; arg: \", key));\n      }\n      HandleCommandLineArgument(key, value);\n    } else if (is_shortarg_start(s.front())) {\n      if (s.size() < 2) {\n        throw unknown_argument_error(\"Missing argument letter, args must be -X or --XXXX\");\n      }\n      const auto letter = static_cast<char>(std::toupper(s[1]));\n      const auto key = ArgNameForKey(letter);\n      if (key.empty()) {\n        if (unknown_args_allowed()) {\n          continue;\n        }\n        throw unknown_argument_error(StrCat(\"Command: \", name(), \"; letter: '\", letter, \"'\"));\n      }\n      const auto value = s.substr(2);\n      HandleCommandLineArgument(key, value);\n    } else if (s.front() == '.') {\n      // Were handling dot arguments.\n      if (!dot_argument_.empty()) {\n        // LOG's use of command_line never defines dot arguments.\n        VLOG(3) << \"Ignoring dot argument since no mapping is defined by the application.\";\n        const auto value = s.substr(1);\n        HandleCommandLineArgument(dot_argument_, value);\n      }\n    } else {\n      if (contains(commands_allowed_, s)) {\n        // If s is a sub-command, parse it, incrementing our pointer.\n        command_ = at(commands_allowed_, s).get();\n        i = command_->Parse(++i);\n      } else {\n        // Add all residue to list of remaining args.\n        // These usually are the positional arguments.\n        for (; i < wwiv::stl::ssize(raw_args_); i++) {\n          remaining_.emplace_back(raw_args_[i]);\n        }\n      }\n    }\n  }\n  return wwiv::stl::size_int(raw_args_);\n}\n\nstd::string CommandLineCommand::ToString() const {\n  std::ostringstream ss;\n  ss << \"name: \" << name_ << \"; args: \";\n  for (const auto& [key, value] : args_) {\n    ss << \"{\" << key << \": \\\"\" << value.as_string() << \"\\\"}\";\n  }\n  if (!remaining_.empty()) {\n    ss << \"; remaining: \";\n    for (const auto& a : remaining_) {\n      ss << a << \", \";\n    }\n  }\n  return ss.str();\n}\n\nint CommandLineCommand::Execute() {\n  if (help_requested()) {\n    // Help was selected.\n    std::cout << GetUsage();\n    std::cout << GetHelp();\n    return 0;\n  }\n\n  if (command_ != nullptr) {\n    // We have sub command, so execute that.\n    if (command_->help_requested()) {\n      std::clog << command_->GetUsage();\n      std::clog << command_->GetHelp();\n      return 0;\n    }\n    return command_->Execute();\n  }\n\n  if (name_.empty() || !remaining_.empty()) {\n    // If name is empty, we're at the root command and\n    // no valid command was specified.\n    std::clog << \"Invalid command specified: \";\n    for (const auto& a : remaining_) {\n      std::clog << a << \" \";\n    }\n    std::clog << std::endl;\n    std::cout << GetUsage() << GetHelp();\n    return 0;\n  }\n\n  // Nothing was able to be executed.\n  std::clog << \"Nothing to do for command: \" << name_ << std::endl;\n  std::cout << std::endl;\n  std::cout << GetUsage() << GetHelp();\n  return 1;\n}\n\nstd::string CommandLineCommand::GetHelpForArg(const CommandLineArgument& c, int max_len) const {\n  std::ostringstream ss;\n  if (c.key_ != 0) {\n    ss << \"-\" << c.key_ << \" \";\n  } else {\n    ss << \"   \";\n  }\n  ss << \"--\" << std::left << std::setw(max_len) << c.name_ << \"  \";\n  if (c.is_boolean) {\n    ss << \"[boolean] \";\n  }\n  ss << c.help_text() << std::endl;\n  return ss.str();\n}\n\nstd::string CommandLineCommand::GetHelpForCommand(const CommandLineCommand& c, int max_len) const {\n  std::ostringstream ss;\n  ss << \"     \" << std::setw(max_len) << std::left << c.name() << \"  \" << c.help_text() << std::endl;\n  return ss.str();\n}\n\nstd::string CommandLineCommand::GetHelp() const {\n  std::ostringstream ss;\n  const auto program_name = name_.empty() ? \"program\" : name_;\n  ss << program_name << \" arguments:\" << std::endl;\n  auto max_len = 8;\n  for (const auto& [_, c] : args_allowed_) {\n    max_len = std::max<size_t>(max_len, c.name_.size());\n  }\n  for (const auto& a : commands_allowed_) {\n    max_len = std::max<size_t>(max_len, a.second->name().size());\n  }\n\n  for (const auto& [_, c] : args_allowed_) {\n    ss << GetHelpForArg(c, max_len);\n  }\n  if (!commands_allowed_.empty()) {\n    ss << std::endl;\n    ss << \"commands:\" << std::endl;\n    for (const auto& a : commands_allowed_) {\n      ss << GetHelpForCommand(*a.second, max_len);\n    }\n  }\n  return ss.str();\n}\n\nbool CommandLine::AddStandardArgs() {\n  if (!CommandLineCommand::AddStandardArgs()) {\n    return false;\n  }\n  add_argument({\"bindir\", \"Main BBS binary directory.\", File::current_directory().string(),\n                \"WWIV_BIN_DIR\"});\n  add_argument(\n  {\"bbsdir\", \"Root BBS directory (i.e. C:\\\\bbs)\", File::current_directory().string(),\n   \"WWIV_DIR\"});\n  add_argument({\"configdir\", \"Main BBS Directory containing CONFIG.DAT\",\n                File::current_directory().string(), \"WWIV_CONFIG_DIR\"});\n  add_argument({\"logdir\", \"Directory where log files are written.\",\n                File::current_directory().string(), \"WWIV_LOG_DIR\"});\n\n  add_argument(\n      BooleanCommandLineArgument{\"log_startup\", \"Should the start/stop/args be logged.\", false});\n\n  // Ignore these. used by logger\n  add_argument({\"v\", \"verbose log\", \"0\"});\n  return true;\n}\n\nstd::string CommandLine::GetHelp() const {\n  std::ostringstream ss;\n  ss << program_name_ << \" [\" << full_version() << \"]\" << std::endl << std::endl;\n  ss << \"Usage:\" << std::endl;\n  ss << program_name_ << \" [args]\";\n  if (!commands_allowed_.empty()) {\n    ss << \" <command> [command args]\";\n  }\n  ss << std::endl << std::endl;\n  ss << CommandLineCommand::GetHelp();\n  return ss.str();\n}\n\nunknown_argument_error::unknown_argument_error(const std::string& message)\n  : std::runtime_error(StrCat(\"unknown_argument_error: \", message)) {\n}\n\n\nvoid SetNewStringDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key) {\n  if (cmdline.contains_arg(key) && cmdline.arg(key).is_default()) {\n    const auto f = ini.value<std::string>(key, cmdline.sarg(key));\n    cmdline.SetNewDefault(key, f);\n  }\n}\n\nvoid SetNewBooleanDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key) {\n  if (cmdline.contains_arg(key) && cmdline.arg(key).is_default()) {\n    const auto f = ini.value<bool>(key, cmdline.barg(key));\n    cmdline.SetNewDefault(key, f ? \"Y\" : \"N\");\n  }\n}\n\nvoid SetNewIntDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key) {\n  if (cmdline.contains_arg(key) && cmdline.arg(key).is_default()) {\n    const auto f = ini.value<int>(key, cmdline.iarg(key));\n    cmdline.SetNewDefault(key, std::to_string(f));\n  }\n}\n\nvoid SetNewIntDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key,\n                             const std::function<void(int)>& f) {\n  if (cmdline.contains_arg(key) && cmdline.arg(key).is_default()) {\n    const auto v = ini.value<int>(key, cmdline.iarg(key));\n    cmdline.SetNewDefault(key, std::to_string(v));\n    f(v);\n  }\n}\n\n} // namespace\n"
  },
  {
    "path": "core/command_line.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIV_CORE_COMMAND_LINE_H\r\n#define INCLUDED_WWIV_CORE_COMMAND_LINE_H\r\n\r\n#include \"core/inifile.h\"\r\n#include \"core/log.h\"\r\n#include <functional>\r\n#include <filesystem>\r\n#include <map>\r\n#include <memory>\r\n#include <stdexcept>\r\n#include <string>\r\n#include <utility>\r\n#include <vector>\r\n\r\n/**\r\n * CommandLine support.\r\n *\r\n * 1) Create a tree of allowed values.\r\n * 2) Parse the actual commandline, reporting any errors.\r\n * 3) Get the values as needed.\r\n *\r\n * 1) Example:\r\n * program: foo [--name, -n] [--location, -l] command\r\n * command: bar [--barname]\r\n * command: baz [--bazname]\r\n * CommandLine cmdline(argc, argv, \"set_style\");\r\n * cmdline.add_argument({\"name\", 'n', \"Sets Name\"});\r\n * cmdline.add_argument({\"location\", 'l', \"Sets Location\"});\r\n *\r\n * CommandLineCommand& bar = cmdline.add_command(\"bar\", \"Bar Commands\");\r\n * bar.add_argument({\"barname\", \"Sets Bar Name\"});\r\n * CommandLineCommand& baz = cmdline.add_command(\"baz\", \"Baz Commands\");\r\n * baz.add_argument({\"bazname\", \"Sets Baz Name\"});\r\n * cmdLine.Parse();\r\n *\r\n * const string name = cmdline.arg(\"name\").as_string();\r\n * CommandLineCommand cmd = cmdline.command();\r\n * const string command_name = cmd->name();\r\n * const string bazname = cmd->arg(\"bazname\").as_string();\r\n */\r\n\r\nnamespace wwiv::core {\r\n\r\nstruct unknown_argument_error : public std::runtime_error {\r\n  explicit unknown_argument_error(const std::string& message);\r\n};\r\n\r\nclass CommandLineValue {\r\npublic:\r\n  CommandLineValue() noexcept\r\n    : default_(true) {\r\n  }\r\n\r\n  explicit CommandLineValue(const std::string& s) noexcept\r\n    : CommandLineValue(s, false) {\r\n  }\r\n\r\n  CommandLineValue(std::string value, bool default_value) noexcept\r\n    : value_(std::move(value)), default_(default_value) {\r\n  }\r\n\r\n  [[nodiscard]] std::string as_string() const noexcept { return value_; }\r\n\r\n  [[nodiscard]] int as_int() const noexcept;\r\n\r\n  [[nodiscard]] bool as_bool() const noexcept { return value_ == \"true\"; }\r\n\r\n  [[nodiscard]] bool is_default() const noexcept { return default_; }\r\n\r\nprivate:\r\n  const std::string value_;\r\n  const bool default_;\r\n};\r\n\r\nclass CommandLineArgument {\r\npublic:\r\n  CommandLineArgument(std::string name, char key, std::string help_text,\r\n                      std::string default_value, std::string environment_variable);\r\n\r\n  CommandLineArgument(const std::string& name, char key, const std::string& help_text,\r\n                      const std::string& default_value)\r\n    : CommandLineArgument(name, key, help_text, default_value, \"\") {\r\n  }\r\n\r\n  CommandLineArgument(const std::string& name, const std::string& help_text,\r\n                      const std::string& default_value, const std::string& environment_variable)\r\n    : CommandLineArgument(name, 0, help_text, default_value, environment_variable) {\r\n  }\r\n\r\n  CommandLineArgument(const std::string& name, const std::string& help_text,\r\n                      const std::string& default_value)\r\n    : CommandLineArgument(name, 0, help_text, default_value, \"\") {\r\n  }\r\n\r\n  CommandLineArgument(const std::string& name, char key, const std::string& help_text)\r\n    : CommandLineArgument(name, key, help_text, \"\", \"\") {\r\n  }\r\n\r\n  CommandLineArgument(const std::string& name, const std::string& help_text)\r\n    : CommandLineArgument(name, 0, help_text, \"\", \"\") {\r\n  }\r\n\r\n  [[nodiscard]] std::string help_text() const;\r\n  [[nodiscard]] std::string default_value() const;\r\n  const std::string name_;\r\n  const char key_{0};\r\n  const std::string help_text_;\r\n  const std::string default_value_;\r\n  const std::string environment_variable_;\r\n  bool is_boolean{false};\r\n};\r\n\r\nclass BooleanCommandLineArgument : public CommandLineArgument {\r\npublic:\r\n  BooleanCommandLineArgument(const std::string& name, char key, const std::string& help_text,\r\n                             bool default_value)\r\n    : CommandLineArgument(name, key, help_text, default_value ? \"true\" : \"false\") {\r\n    is_boolean = true;\r\n  }\r\n\r\n  BooleanCommandLineArgument(const std::string& name, const std::string& help_text,\r\n                             bool default_value)\r\n    : CommandLineArgument(name, 0, help_text, default_value ? \"true\" : \"false\") {\r\n    is_boolean = true;\r\n  }\r\n\r\n  BooleanCommandLineArgument(const std::string& name, const std::string& help_text)\r\n    : CommandLineArgument(name, 0, help_text, \"false\") {\r\n    is_boolean = true;\r\n  }\r\n\r\n};\r\n\r\nclass Command {\r\nprotected:\r\n  Command() = default;\r\npublic:\r\n  virtual ~Command() = default;\r\n  virtual int Execute() = 0;\r\n  [[nodiscard]] virtual std::string GetUsage() const = 0;\r\n  [[nodiscard]] virtual std::string GetHelp() const = 0;\r\n};\r\n\r\n/** Generic command implementation for using the CommandLine support in core */\r\nclass CommandLineCommand : public Command {\r\npublic:\r\n  CommandLineCommand(std::string name, std::string help_text);\r\n  ~CommandLineCommand() override = default;\r\n  bool add_argument(const CommandLineArgument& cmd);\r\n\r\n  virtual bool add(std::shared_ptr<CommandLineCommand> cmd) {\r\n    cmd->set_raw_args(raw_args_);\r\n    cmd->set_dot_argument(dot_argument_);\r\n    commands_allowed_[cmd->name()] = std::move(cmd);\r\n    return true;\r\n  }\r\n\r\n  [[nodiscard]] std::string ArgNameForKey(char key);\r\n  virtual bool AddStandardArgs();\r\n\r\n  [[nodiscard]] bool subcommand_selected() const { return command_ != nullptr; }\r\n  [[nodiscard]] const std::string& name() const { return name_; }\r\n  [[nodiscard]] const std::string& help_text() const { return help_text_; }\r\n\r\n  [[nodiscard]] CommandLineValue arg(const std::string& name) const;\r\n  [[nodiscard]] bool contains_arg(const std::string& name) const noexcept;\r\n  [[nodiscard]] std::string sarg(const std::string& name) const { return arg(name).as_string(); }\r\n  template<typename T = int>\r\n  [[nodiscard]] T iarg(const std::string& name) const { return static_cast<T>(arg(name).as_int()); }\r\n  [[nodiscard]] bool barg(const std::string& name) const { return arg(name).as_bool(); }\r\n  [[nodiscard]] bool help_requested() const { return barg(\"help\"); }\r\n  [[nodiscard]] const CommandLineCommand* command() const { return command_; }\r\n  [[nodiscard]] const std::vector<std::string>& remaining() const { return remaining_; }\r\n  [[nodiscard]] std::string ToString() const;\r\n  int Execute() override;\r\n  [[nodiscard]] std::string GetHelpForArg(const CommandLineArgument&, int max_len = 25) const;\r\n  [[nodiscard]] std::string GetHelpForCommand(const CommandLineCommand&, int max_len = 25) const;\r\n  [[nodiscard]] std::string GetHelp() const override;\r\n  [[nodiscard]] std::string GetUsage() const override { return \"\"; }\r\n  void set_unknown_args_allowed(bool u) { unknown_args_allowed_ = u; }\r\n  [[nodiscard]] bool unknown_args_allowed() const { return unknown_args_allowed_; }\r\n\r\n  /**\r\n   * Sets a new default value. NetworkCommandLine will get these from\r\n   * an ini file for each of the network commands and call this.\r\n   * TODO(rushfan): Should we generalize this and let all defaults\r\n   * come from INI files?\r\n   */\r\n  bool SetNewDefault(const std::string& key, const std::string& value);\r\n\r\n  /**\r\n   * Public metadata about which command line args and subcommands are allowed. This\r\n   * lets consumers display customized help and possibly command line completion.\r\n   */\r\n\r\n  /** Which arguments are allowed for this command */\r\n  [[nodiscard]] const std::map<const std::string, CommandLineArgument>& args_allowed() const {\r\n    return args_allowed_;\r\n  }\r\n\r\n  /** Which sub-commands are allowed for this command */\r\n  [[nodiscard]] const std::map<const std::string, std::shared_ptr<CommandLineCommand>>& commands_allowed() const {\r\n    return commands_allowed_;\r\n  }\r\n\r\nprotected:\r\n  /** Handles a command line argument passed on the commandline */\r\n  bool HandleCommandLineArgument(const std::string& key, const std::string& value);\r\n  bool SetCommandLineArgument(const std::string& key, const std::string& value, bool default_value);\r\n  int Parse(int start_pos);\r\n\r\n  void set_raw_args(const std::vector<std::string>& args) { raw_args_ = args; }\r\n  void set_dot_argument(const std::string& dot_argument) { dot_argument_ = dot_argument; }\r\n\r\n  std::vector<std::string> raw_args_;\r\n  // Values as allowed to be specified on the commandline.\r\n  std::map<const std::string, CommandLineArgument> args_allowed_;\r\n  std::map<const std::string, std::shared_ptr<CommandLineCommand>> commands_allowed_;\r\n  std::vector<std::string> remaining_;\r\n\r\nprivate:\r\n  // Values as entered on the commandline.\r\n  std::map<std::string, CommandLineValue> args_;\r\n  CommandLineCommand* command_ = nullptr;\r\n  const std::string name_;\r\n  const std::string help_text_;\r\n  std::string dot_argument_;\r\n  bool unknown_args_allowed_{false};\r\n};\r\n\r\n/**\r\n * Class to parse command line arguments and populate the commands.\r\n */\r\nclass CommandLine final : public CommandLineCommand {\r\npublic:\r\n  /**\r\n   * Common constructor.  Note that the dot_argument specific the\r\n   * command line to replace . with (i.e. \"network\" means that .0\r\n   * will be replaced by --network=0.  An empty dot_argument means\r\n   * that no replacement will happen.\r\n   */\r\n  CommandLine(const std::vector<std::string>& args, const std::string& dot_argument);\r\n  CommandLine(int argc, char** argv, const std::string& dot_argument);\r\n  ~CommandLine() override = default;\r\n  CommandLine() = delete;\r\n  CommandLine(const CommandLine&) = delete;\r\n  bool Parse();\r\n  int Execute() override;\r\n  bool AddStandardArgs() override;\r\n  [[nodiscard]] std::string GetHelp() const override;\r\n\r\n  void set_no_args_allowed(bool no_args_allowed) { no_args_allowed_ = no_args_allowed; }\r\n  [[nodiscard]] bool no_args_allowed() const { return no_args_allowed_; }\r\n\r\n  [[nodiscard]] std::string program_name() const noexcept { return program_name_; }\r\n  [[nodiscard]] std::filesystem::path program_path() const noexcept { return program_path_; }\r\n  [[nodiscard]] std::string bindir() const noexcept { return bindir_; }\r\n  [[nodiscard]] std::string bbsdir() const noexcept { return bbsdir_; }\r\n  [[nodiscard]] std::string configdir() const noexcept { return configdir_; }\r\n  [[nodiscard]] std::string logdir() const noexcept { return logdir_; }\r\n  [[nodiscard]] int verbose() const noexcept { return verbose_; }\r\n\r\nprivate:\r\n  const std::string program_name_;\r\n  const std::filesystem::path program_path_;\r\n  std::string bbsdir_;\r\n  std::string bindir_;\r\n  std::string configdir_;\r\n  std::string logdir_;\r\n  int verbose_{0};\r\n  bool no_args_allowed_{false};\r\n\r\n  bool ParseImpl();\r\n};\r\n\r\n// Utility methods for setting defaults from INI files.\r\n\r\n/**\r\n * Sets a default value for the command line parameter for to be the value\r\n * of an INI file key of the same name and type.\r\n */\r\nvoid SetNewStringDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key);\r\n\r\n/**\r\n * Sets a default value for the command line parameter for to be the value\r\n * of an INI file key of the same name and type.\r\n */\r\nvoid SetNewBooleanDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key);\r\n\r\n/**\r\n * Sets a default value for the command line parameter for to be the value\r\n * of an INI file key of the same name and type.\r\n */\r\nvoid SetNewIntDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key);\r\n\r\n/**\r\n * Sets a default value for the command line parameter for to be the value\r\n * of an INI file key of the same name and type.\r\n *\r\n * Also invokes function f with the default value pass to it as a parameter.\r\n */\r\nvoid SetNewIntDefault(CommandLine& cmdline, const IniFile& ini, const std::string& key,\r\n                      const std::function<void(int)>& f);\r\n\r\n} // namespace\r\n\r\n#endif\r\n"
  },
  {
    "path": "core/command_line_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/command_line.h\"\n#include \"gtest/gtest.h\"\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\n\nclass CommandLineTest: public ::testing::Test {};\n\nclass NoopCommandLineCommand: public CommandLineCommand {\npublic:\n  explicit NoopCommandLineCommand(const std::string& name)\n      : CommandLineCommand(name, name) {}\n  int Execute() override final { return 0; }\n  [[nodiscard]] std::string GetHelp() const override final { return \"\"; }\n};\n\nTEST_F(CommandLineTest, Basic) {\n  CommandLine cmdline({\"\", \"--foo\", \"--bar=baz\"}, \"\");\n  cmdline.add_argument({\"foo\", \"help for foo\", \"asdf\"});\n  cmdline.add_argument({\"bar\", \"help for bar\"});\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(\"baz\", cmdline.arg(\"bar\").as_string());\n}\n\nTEST_F(CommandLineTest, Remainder) {\n  CommandLine cmdline({\"\", \"--foo=baz\", \"bar\"}, \"\");\n  cmdline.add_argument({\"foo\", \"help for foo\", \"asdf\"});\n  cmdline.add_argument({\"bar\", \"help for bar\"});\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(\"baz\", cmdline.arg(\"foo\").as_string());\n  ASSERT_EQ(1u, cmdline.remaining().size());\n  EXPECT_EQ(\"bar\", cmdline.remaining().front());\n}\n\nTEST_F(CommandLineTest, Remainder_DoubleDash) {\n  CommandLine cmdline({\"\", \"--foo=baz\", \"--\", \"--bar\"}, \"\");\n  cmdline.add_argument({\"foo\", \"help for foo\", \"asdf\"});\n  cmdline.add_argument({\"bar\", \"help for bar\"});\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(\"baz\", cmdline.arg(\"foo\").as_string());\n  ASSERT_EQ(1u, cmdline.remaining().size());\n  EXPECT_EQ(\"--bar\", cmdline.remaining().front());\n}\n\nTEST_F(CommandLineTest, Command) {\n  CommandLine cmdline({\"\", \"--foo=bar\", \"print\", \"--all\", \"--some=false\", \"myfile.txt\"}, \"\");\n  cmdline.add_argument({\"foo\", ' ', \"\", \"asdf\"});\n  auto print = std::make_unique<NoopCommandLineCommand>(\"print\");\n  print->add_argument(BooleanCommandLineArgument(\"all\", ' ', \"\", false));\n  print->add_argument(BooleanCommandLineArgument(\"some\", ' ', \"\", true));\n  cmdline.add(std::move(print));\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(\"bar\", cmdline.arg(\"foo\").as_string());\n\n  ASSERT_TRUE(cmdline.subcommand_selected());\n  EXPECT_EQ(\"print\", cmdline.command()->name());\n  std::clog << cmdline.command()->ToString() << std::endl;\n\n  EXPECT_TRUE(cmdline.command()->arg(\"all\").as_bool());\n  EXPECT_FALSE(cmdline.command()->arg(\"some\").as_bool());\n}\n\nTEST_F(CommandLineTest, Several_Commands) {\n  CommandLine cmdline({\"\", \"--foo=bar\", \"print\",}, \"\");\n  cmdline.add_argument({\"foo\", ' ', \"\", \"asdf\"});\n  cmdline.add(std::make_unique<NoopCommandLineCommand>(\"print\"));\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(\"bar\", cmdline.arg(\"foo\").as_string());\n\n  ASSERT_TRUE(cmdline.subcommand_selected());\n  EXPECT_EQ(\"print\", cmdline.command()->name());\n  std::clog << cmdline.command()->ToString() << std::endl;\n}\n\nTEST_F(CommandLineTest, SlashArg) {\n  CommandLine cmdline({\"foo.exe\", \"-n500\", \".1\"}, \"net\");\n  cmdline.add_argument({\"node\", 'n', \"node to dial\", \"0\"});\n  cmdline.add_argument({\"net\", \"network number to use.\", \"0\"});\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(500, cmdline.arg(\"node\").as_int());\n}\n\nTEST_F(CommandLineTest, DotArg) {\n  CommandLine cmdline({\"foo.exe\", \"-n500\", \".123\"}, \"net\");\n  cmdline.add_argument({\"node\", 'n', \"node to dial\", \"0\"});\n  cmdline.add_argument({\"net\", \"network number to use.\", \"0\"});\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_EQ(123, cmdline.arg(\"net\").as_int());\n}\n\nTEST_F(CommandLineTest, Help) {\n  CommandLine cmdline({\"foo.exe\", \"-?\"}, \"net\");\n  cmdline.add_argument(BooleanCommandLineArgument(\"help\", '?', \"display help\", false));\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_TRUE(cmdline.arg(\"help\").as_bool());\n}\n\n#ifdef _WIN32\nTEST_F(CommandLineTest, Help_WIN32) {\n  CommandLine cmdline({\"foo.exe\", \"/?\"}, \"net\");\n  cmdline.add_argument(BooleanCommandLineArgument(\"help\", '?', \"display help\", false));\n\n  ASSERT_TRUE(cmdline.Parse());\n  EXPECT_TRUE(cmdline.arg(\"help\").as_bool());\n}\n#endif"
  },
  {
    "path": "core/connection.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/connection.h\"\n\nnamespace wwiv::core {\n\nConnection::Connection() noexcept = default;\n\nConnection::~Connection() = default;\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/connection.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORKB_CONNECTION_H\n#define INCLUDED_NETWORKB_CONNECTION_H\n\n#include <chrono>\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::core {\n\nclass Connection {\npublic:\n  Connection() noexcept;\n  virtual ~Connection();\n\n  virtual int receive(void* data, int size, std::chrono::duration<double> d) = 0;\n  virtual std::string receive(int size, std::chrono::duration<double> d) = 0;\n  virtual int send(const void* data, int size, std::chrono::duration<double> d) = 0;\n  virtual int send(const std::string& s, std::chrono::duration<double> d) = 0;\n\n  virtual uint16_t read_uint16(std::chrono::duration<double> d) = 0;\n  virtual uint8_t read_uint8(std::chrono::duration<double> d) = 0;\n  [[nodiscard]] virtual bool is_open() const = 0;\n  virtual bool close() = 0;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/core_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/test/wwivtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n} \n"
  },
  {
    "path": "core/cp437.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/cp437.h\"\n\n#include \"core/stl.h\"\n#include <clocale>\n#include <cstdint>\n\n#ifdef _WIN32\n#include \"core/wwiv_windows.h\"\n#endif\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Data from ftp://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT\n//\n//\n// Main table generated as:\n// cat CP437.TXT | grep -v \"^#\" | awk '{print  $2 \", //  [\" $1 \"] \" $3} '\n\nnamespace wwiv::core {\n\nusing namespace wwiv::stl;\n\nstatic wchar_t dos_to_utf8_[] =\n{\n0x0000, //  [0x00] #NULL\n0x0001, //  [0x01] #START\n0x0002, //  [0x02] #START\n0x0003, //  [0x03] #END\n0x0004, //  [0x04] #END\n0x0005, //  [0x05] #ENQUIRY\n0x0006, //  [0x06] #ACKNOWLEDGE\n0x0007, //  [0x07] #BELL\n0x0008, //  [0x08] #BACKSPACE\n0x0009, //  [0x09] #HORIZONTAL\n0x000a, //  [0x0a] #LINE\n0x000b, //  [0x0b] #VERTICAL\n0x000c, //  [0x0c] #FORM\n0x000d, //  [0x0d] #CARRIAGE\n0x000e, //  [0x0e] #SHIFT\n0x000f, //  [0x0f] #SHIFT\n0x0010, //  [0x10] #DATA\n0x0011, //  [0x11] #DEVICE\n0x0012, //  [0x12] #DEVICE\n0x0013, //  [0x13] #DEVICE\n0x0014, //  [0x14] #DEVICE\n0x0015, //  [0x15] #NEGATIVE\n0x0016, //  [0x16] #SYNCHRONOUS\n0x0017, //  [0x17] #END\n0x0018, //  [0x18] #CANCEL\n0x0019, //  [0x19] #END\n0x001a, //  [0x1a] #SUBSTITUTE\n0x001b, //  [0x1b] #ESCAPE\n0x001c, //  [0x1c] #FILE\n0x001d, //  [0x1d] #GROUP\n0x001e, //  [0x1e] #RECORD\n0x001f, //  [0x1f] #UNIT\n0x0020, //  [0x20] #SPACE\n0x0021, //  [0x21] #EXCLAMATION\n0x0022, //  [0x22] #QUOTATION\n0x0023, //  [0x23] #NUMBER\n0x0024, //  [0x24] #DOLLAR\n0x0025, //  [0x25] #PERCENT\n0x0026, //  [0x26] #AMPERSAND\n0x0027, //  [0x27] #APOSTROPHE\n0x0028, //  [0x28] #LEFT\n0x0029, //  [0x29] #RIGHT\n0x002a, //  [0x2a] #ASTERISK\n0x002b, //  [0x2b] #PLUS\n0x002c, //  [0x2c] #COMMA\n0x002d, //  [0x2d] #HYPHEN-MINUS\n0x002e, //  [0x2e] #FULL\n0x002f, //  [0x2f] #SOLIDUS\n0x0030, //  [0x30] #DIGIT\n0x0031, //  [0x31] #DIGIT\n0x0032, //  [0x32] #DIGIT\n0x0033, //  [0x33] #DIGIT\n0x0034, //  [0x34] #DIGIT\n0x0035, //  [0x35] #DIGIT\n0x0036, //  [0x36] #DIGIT\n0x0037, //  [0x37] #DIGIT\n0x0038, //  [0x38] #DIGIT\n0x0039, //  [0x39] #DIGIT\n0x003a, //  [0x3a] #COLON\n0x003b, //  [0x3b] #SEMICOLON\n0x003c, //  [0x3c] #LESS-THAN\n0x003d, //  [0x3d] #EQUALS\n0x003e, //  [0x3e] #GREATER-THAN\n0x003f, //  [0x3f] #QUESTION\n0x0040, //  [0x40] #COMMERCIAL\n0x0041, //  [0x41] #LATIN\n0x0042, //  [0x42] #LATIN\n0x0043, //  [0x43] #LATIN\n0x0044, //  [0x44] #LATIN\n0x0045, //  [0x45] #LATIN\n0x0046, //  [0x46] #LATIN\n0x0047, //  [0x47] #LATIN\n0x0048, //  [0x48] #LATIN\n0x0049, //  [0x49] #LATIN\n0x004a, //  [0x4a] #LATIN\n0x004b, //  [0x4b] #LATIN\n0x004c, //  [0x4c] #LATIN\n0x004d, //  [0x4d] #LATIN\n0x004e, //  [0x4e] #LATIN\n0x004f, //  [0x4f] #LATIN\n0x0050, //  [0x50] #LATIN\n0x0051, //  [0x51] #LATIN\n0x0052, //  [0x52] #LATIN\n0x0053, //  [0x53] #LATIN\n0x0054, //  [0x54] #LATIN\n0x0055, //  [0x55] #LATIN\n0x0056, //  [0x56] #LATIN\n0x0057, //  [0x57] #LATIN\n0x0058, //  [0x58] #LATIN\n0x0059, //  [0x59] #LATIN\n0x005a, //  [0x5a] #LATIN\n0x005b, //  [0x5b] #LEFT\n0x005c, //  [0x5c] #REVERSE\n0x005d, //  [0x5d] #RIGHT\n0x005e, //  [0x5e] #CIRCUMFLEX\n0x005f, //  [0x5f] #LOW\n0x0060, //  [0x60] #GRAVE\n0x0061, //  [0x61] #LATIN\n0x0062, //  [0x62] #LATIN\n0x0063, //  [0x63] #LATIN\n0x0064, //  [0x64] #LATIN\n0x0065, //  [0x65] #LATIN\n0x0066, //  [0x66] #LATIN\n0x0067, //  [0x67] #LATIN\n0x0068, //  [0x68] #LATIN\n0x0069, //  [0x69] #LATIN\n0x006a, //  [0x6a] #LATIN\n0x006b, //  [0x6b] #LATIN\n0x006c, //  [0x6c] #LATIN\n0x006d, //  [0x6d] #LATIN\n0x006e, //  [0x6e] #LATIN\n0x006f, //  [0x6f] #LATIN\n0x0070, //  [0x70] #LATIN\n0x0071, //  [0x71] #LATIN\n0x0072, //  [0x72] #LATIN\n0x0073, //  [0x73] #LATIN\n0x0074, //  [0x74] #LATIN\n0x0075, //  [0x75] #LATIN\n0x0076, //  [0x76] #LATIN\n0x0077, //  [0x77] #LATIN\n0x0078, //  [0x78] #LATIN\n0x0079, //  [0x79] #LATIN\n0x007a, //  [0x7a] #LATIN\n0x007b, //  [0x7b] #LEFT\n0x007c, //  [0x7c] #VERTICAL\n0x007d, //  [0x7d] #RIGHT\n0x007e, //  [0x7e] #TILDE\n0x007f, //  [0x7f] #DELETE\n0x00c7, //  [0x80] #LATIN\n0x00fc, //  [0x81] #LATIN\n0x00e9, //  [0x82] #LATIN\n0x00e2, //  [0x83] #LATIN\n0x00e4, //  [0x84] #LATIN\n0x00e0, //  [0x85] #LATIN\n0x00e5, //  [0x86] #LATIN\n0x00e7, //  [0x87] #LATIN\n0x00ea, //  [0x88] #LATIN\n0x00eb, //  [0x89] #LATIN\n0x00e8, //  [0x8a] #LATIN\n0x00ef, //  [0x8b] #LATIN\n0x00ee, //  [0x8c] #LATIN\n0x00ec, //  [0x8d] #LATIN\n0x00c4, //  [0x8e] #LATIN\n0x00c5, //  [0x8f] #LATIN\n0x00c9, //  [0x90] #LATIN\n0x00e6, //  [0x91] #LATIN\n0x00c6, //  [0x92] #LATIN\n0x00f4, //  [0x93] #LATIN\n0x00f6, //  [0x94] #LATIN\n0x00f2, //  [0x95] #LATIN\n0x00fb, //  [0x96] #LATIN\n0x00f9, //  [0x97] #LATIN\n0x00ff, //  [0x98] #LATIN\n0x00d6, //  [0x99] #LATIN\n0x00dc, //  [0x9a] #LATIN\n0x00a2, //  [0x9b] #CENT\n0x00a3, //  [0x9c] #POUND\n0x00a5, //  [0x9d] #YEN\n0x20a7, //  [0x9e] #PESETA\n0x0192, //  [0x9f] #LATIN\n0x00e1, //  [0xa0] #LATIN\n0x00ed, //  [0xa1] #LATIN\n0x00f3, //  [0xa2] #LATIN\n0x00fa, //  [0xa3] #LATIN\n0x00f1, //  [0xa4] #LATIN\n0x00d1, //  [0xa5] #LATIN\n0x00aa, //  [0xa6] #FEMININE\n0x00ba, //  [0xa7] #MASCULINE\n0x00bf, //  [0xa8] #INVERTED\n0x2310, //  [0xa9] #REVERSED\n0x00ac, //  [0xaa] #NOT\n0x00bd, //  [0xab] #VULGAR\n0x00bc, //  [0xac] #VULGAR\n0x00a1, //  [0xad] #INVERTED\n0x00ab, //  [0xae] #LEFT-POINTING\n0x00bb, //  [0xaf] #RIGHT-POINTING\n0x2591, //  [0xb0] #LIGHT\n0x2592, //  [0xb1] #MEDIUM\n0x2593, //  [0xb2] #DARK\n0x2502, //  [0xb3] #BOX\n0x2524, //  [0xb4] #BOX\n0x2561, //  [0xb5] #BOX\n0x2562, //  [0xb6] #BOX\n0x2556, //  [0xb7] #BOX\n0x2555, //  [0xb8] #BOX\n0x2563, //  [0xb9] #BOX\n0x2551, //  [0xba] #BOX\n0x2557, //  [0xbb] #BOX\n0x255d, //  [0xbc] #BOX\n0x255c, //  [0xbd] #BOX\n0x255b, //  [0xbe] #BOX\n0x2510, //  [0xbf] #BOX\n0x2514, //  [0xc0] #BOX\n0x2534, //  [0xc1] #BOX\n0x252c, //  [0xc2] #BOX\n0x251c, //  [0xc3] #BOX\n0x2500, //  [0xc4] #BOX\n0x253c, //  [0xc5] #BOX\n0x255e, //  [0xc6] #BOX\n0x255f, //  [0xc7] #BOX\n0x255a, //  [0xc8] #BOX\n0x2554, //  [0xc9] #BOX\n0x2569, //  [0xca] #BOX\n0x2566, //  [0xcb] #BOX\n0x2560, //  [0xcc] #BOX\n0x2550, //  [0xcd] #BOX\n0x256c, //  [0xce] #BOX\n0x2567, //  [0xcf] #BOX\n0x2568, //  [0xd0] #BOX\n0x2564, //  [0xd1] #BOX\n0x2565, //  [0xd2] #BOX\n0x2559, //  [0xd3] #BOX\n0x2558, //  [0xd4] #BOX\n0x2552, //  [0xd5] #BOX\n0x2553, //  [0xd6] #BOX\n0x256b, //  [0xd7] #BOX\n0x256a, //  [0xd8] #BOX\n0x2518, //  [0xd9] #BOX\n0x250c, //  [0xda] #BOX\n0x2588, //  [0xdb] #FULL\n0x2584, //  [0xdc] #LOWER\n0x258c, //  [0xdd] #LEFT\n0x2590, //  [0xde] #RIGHT\n0x2580, //  [0xdf] #UPPER\n0x03b1, //  [0xe0] #GREEK\n0x00df, //  [0xe1] #LATIN\n0x0393, //  [0xe2] #GREEK\n0x03c0, //  [0xe3] #GREEK\n0x03a3, //  [0xe4] #GREEK\n0x03c3, //  [0xe5] #GREEK\n0x00b5, //  [0xe6] #MICRO\n0x03c4, //  [0xe7] #GREEK\n0x03a6, //  [0xe8] #GREEK\n0x0398, //  [0xe9] #GREEK\n0x03a9, //  [0xea] #GREEK\n0x03b4, //  [0xeb] #GREEK\n0x221e, //  [0xec] #INFINITY\n0x03c6, //  [0xed] #GREEK\n0x03b5, //  [0xee] #GREEK\n0x2229, //  [0xef] #INTERSECTION\n0x2261, //  [0xf0] #IDENTICAL\n0x00b1, //  [0xf1] #PLUS-MINUS\n0x2265, //  [0xf2] #GREATER-THAN\n0x2264, //  [0xf3] #LESS-THAN\n0x2320, //  [0xf4] #TOP\n0x2321, //  [0xf5] #BOTTOM\n0x00f7, //  [0xf6] #DIVISION\n0x2248, //  [0xf7] #ALMOST\n0x00b0, //  [0xf8] #DEGREE\n0x2219, //  [0xf9] #BULLET\n0x00b7, //  [0xfa] #MIDDLE\n0x221a, //  [0xfb] #SQUARE\n0x207f, //  [0xfc] #SUPERSCRIPT\n0x00b2, //  [0xfd] #SUPERSCRIPT\n0x25a0, //  [0xfe] #BLACK\n0x00a0 //  [0xff] #NO-BREAK\n};\n\n\nbool set_wwiv_codepage(wwiv_codepage_t cp) {\n  std::string default_locale;\n#ifdef _WIN32\n  if (cp == wwiv_codepage_t::utf8) {\n    default_locale = \".UTF-8\";\n    ::SetConsoleOutputCP(65001); // CP_UTF8\n  } else {\n    // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?view=msvc-140\n    // OCP is OEM code page, which is OEM 437, IBM 437, etc.\n    default_locale = \".OCP\";\n    ::SetConsoleOutputCP(437); // CP_437\n  }\n\n#endif\n  // Note, we use LC_CTYPE not LC_ALL so we only affect characters to be UTF-8, but we leave\n  // the number formatting, etc as-is (in 'C')\n  const auto* new_locale = std::setlocale(LC_CTYPE, default_locale.c_str());\n  \n  if (new_locale) {\n    VLOG(1) << \"Resetting Locale: \" << new_locale;\n  }\n  return true;\n}\n\nint cp437_to_utf8(uint8_t ch, char* out) {\n  const auto unicode = dos_to_utf8_[ch];\n  const auto res = wctomb(out, unicode);\n  if (res == -1) {\n    out[0] = '\\0';\n    return 0;\n  }\n  out[res] = '\\0';\n  return res;\n}\n\nwchar_t cp437_to_utf8(char ch) {\n  return cp437_to_utf8(static_cast<uint8_t>(ch));\n}\n\nwchar_t cp437_to_utf8(uint8_t ch) {\n  return dos_to_utf8_[ch];\n}\n\nstd::wstring cp437_to_utf8w(const std::string& in) {\n  std::wstring s;\n  s.reserve(in.size());\n  for (auto ch : in) {\n    s.push_back(dos_to_utf8_[static_cast<uint8_t>(ch)]);\n  }\n  s.shrink_to_fit();\n  return s;\n}\n\nstd::string cp437_to_utf8(const std::string& in) {\n  const auto s = cp437_to_utf8w(in);\n  std::string contents;\n  const auto max_len = size_int(s) * 3 + 1;\n  contents.resize(1024 * 3 + 1);\n  const auto new_size = wcstombs(&contents[0], s.c_str(), max_len);\n  contents.resize(new_size);\n  return contents;\n}\n\n}\n\n"
  },
  {
    "path": "core/cp437.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_CP437_H\n#define INCLUDED_LOCAL_IO_CP437_H\n\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::core {\n\nenum class wwiv_codepage_t { cp437, utf8 };\n\nbool set_wwiv_codepage(wwiv_codepage_t);\n\nint cp437_to_utf8(uint8_t ch, char* out);\nwchar_t cp437_to_utf8(char ch);\nwchar_t cp437_to_utf8(uint8_t ch);\nstd::wstring cp437_to_utf8w(const std::string& in);\nstd::string cp437_to_utf8(const std::string& in);\n\n}\n\n#endif"
  },
  {
    "path": "core/cp437_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/cp437.h\"\n#include \"gtest/gtest.h\"\n#include <clocale>\n#include <string>\n\nusing namespace wwiv::core;\n\nTEST(Cp437Test, Smoke_Char) {\n  char s[81];\n  ASSERT_EQ(1, cp437_to_utf8('A', s));\n  EXPECT_EQ('A', s[0]);\n  EXPECT_EQ('\\0', s[1]);\n}\n\nTEST(Cp437Test, CharMultiple) {\n  char s[81];\n  EXPECT_EQ(3, cp437_to_utf8(0xfe, s));\n  EXPECT_STREQ(\"\\xe2\\x96\\xa0\", s) << s;\n}\n\nTEST(Cp437Test, Smoke_String) {\n  const auto s = cp437_to_utf8(\"Hello World\");\n  EXPECT_EQ(\"Hello World\", s);\n}\n\nTEST(Cp437Test, Block_String) {\n  const auto s = cp437_to_utf8(\"\\xdb\\xdb\\xdb\");\n  EXPECT_EQ(9u, s.length());\n  EXPECT_EQ(\"\\xE2\\x96\\x88\\xE2\\x96\\x88\\xE2\\x96\\x88\", s);\n}\n\nTEST(Cp437Test, EmptyString) {\n  const auto s = cp437_to_utf8(\"\");\n  EXPECT_EQ(\"\", s);\n}\n"
  },
  {
    "path": "core/crc32.cpp",
    "content": "/*\n*  Crc - 32 BIT ANSI X3.66 CRC checksum files\n*/\n#include \"core/file.h\"\n#include <memory>\n#include <string>\n\nnamespace wwiv::core {\n\n/**********************************************************************\\\n|*                                                                    *|\n|* Demonstration program to compute the 32-bit CRC used as the frame  *|\n|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|\n|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|\n|* protocol).  The 32-bit FCS was added via the Federal Register,     *|\n|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|\n|* this polynomial is or will be included in CCITT V.41, which        *|\n|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|\n|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|\n|* errors by a factor of 10^-5 over 16-bit FCS.                       *|\n|*                                                                    *|\n\\**********************************************************************/\n\n/*\n* Copyright (C) 1986 Gary S. Brown.  You may use this program, or\n* code or tables extracted from it, as desired without restriction.\n*/\n/* First, the polynomial itself and its table of feedback terms.  The  */\n/* polynomial is                                                       */\n/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */\n/* Note that we take it \"backwards\" and put the highest-order term in  */\n/* the lowest-order bit.  The X^32 term is \"implied\"; the LSB is the   */\n/* X^31 term, etc.  The X^0 term (usually shown as \"+1\") results in    */\n/* the MSB being 1.                                                    */\n\n/* Note that the usual hardware shift register implementation, which   */\n/* is what we're using (we're merely optimizing it by doing eight-bit  */\n/* chunks at a time) shifts bits into the lowest-order term.  In our   */\n/* implementation, that means shifting towards the right.  Why do we   */\n/* do it this way?  Because the calculated CRC must be transmitted in  */\n/* order from highest-order term to lowest-order term.  UARTs transmit */\n/* characters in order from LSB to MSB.  By storing the CRC this way,  */\n/* we hand it to the UART in the order low-byte to high-byte; the UART */\n/* sends each low-bit to hight-bit; and the result is transmission bit */\n/* by bit from highest- to lowest-order term without requiring any bit */\n/* shuffling on our part.  Reception works similarly.                  */\n\n/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */\n/*                                                                     */\n/*  1. The table can be generated at runtime if desired; code to do so */\n/*     is shown later.  It might not be obvious, but the feedback      */\n/*     terms simply represent the results of eight shift/xor opera-    */\n/*     tions for all combinations of data and CRC register values.     */\n/*                                                                     */\n/*  2. The CRC accumulation logic is the same for all CRC polynomials, */\n/*     be they sixteen or thirty-two bits wide.  You simply choose the */\n/*     appropriate table.  Alternatively, because the table can be     */\n/*     generated at runtime, you can start by generating the table for */\n/*     the polynomial in question and use exactly the same \"updcrc\",   */\n/*     if your application needn't simultaneously handle two CRC       */\n/*     polynomials.  (Note, however, that XMODEM is strange.)          */\n/*                                                                     */\n/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */\n/*     of course, 32-bit entries work OK if the high 16 bits are zero. */\n/*                                                                     */\n/*  4. The values must be right-shifted by eight bits by the \"updcrc\"  */\n/*     logic; the shift must be unsigned (bring in zeroes).  On some   */\n/*     hardware you could probably optimize the shift in assembler by  */\n/*     using byte-swap instructions.                                   */\n\nstatic uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */\n    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\n    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\n    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\n    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\n    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\n    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\n    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\n    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\n    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\n    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\n    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\n    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n};\n\n#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))\n\nuint32_t crc32file(const std::filesystem::path& path) {\n  uint32_t crc = 0xFFFFFFFF;\n  File file(path);\n  if (!file.Open(File::modeReadOnly | File::modeBinary, File::shareDenyWrite)) {\n    return false;\n  }\n  const auto size = file.length();\n  const auto buffer = std::make_unique<uint8_t[]>(size);\n  if (!file.Read(buffer.get(), size)) {\n    return false;\n  }\n  for (auto i = 0; i < size; i++) {\n    crc = UPDC32(buffer[i], crc);\n  }\n  return ~crc;\n}\n\nuint32_t crc32string(const std::string& contents) {\n  uint32_t crc = 0xFFFFFFFF;\n  for (const auto& c : contents) {\n    crc = UPDC32(c, crc);\n  }\n  return ~crc;\n}\n\n}\n"
  },
  {
    "path": "core/crc32.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_CRC32_H\n#define INCLUDED_CORE_CRC32_H\n\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::core {\n\n[[nodiscard]] uint32_t crc32file(const std::filesystem::path& path);\n[[nodiscard]] uint32_t crc32string(const std::string& contents);\n\n}\n\n#endif"
  },
  {
    "path": "core/crc32_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/crc32.h\"\n#include \"core/file.h\"\n#include \"core/test/file_helper.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\n\nTEST(Crc32Test, Simple) {\n  wwiv::core::test::FileHelper file;\n  const auto path = file.CreateTempFile(\"helloworld.txt\", \"Hello World\");\n\n  ASSERT_TRUE(File::Exists(path));\n\n  const auto crc = crc32file(path);\n  const uint32_t expected = 0x4a17b156;\n\n  // use wwiv/scripts/crc32.py to generate golden values as needed.\n  EXPECT_EQ(expected, crc) << \" was \" << std::hex << crc;\n}\n"
  },
  {
    "path": "core/datafile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2014-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_DATAFILE_H\n#define INCLUDED_CORE_DATAFILE_H\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/wwivport.h\"\n#include <filesystem>\n#include <vector>\n\nnamespace wwiv::core {\n\n/**\n * File: Provides a high level, cross-platform common wrapper for file\n * of repeating structs (like Pascal records).  Many of the common WWIV\n * datafiles are multiple copies of the same struct type.\n *\n * Example:\n *   vector<mailrec> emails;\n *   DataFile<mailrec> f(FilePath(\"/opt/wwiv/bbs/data\", \"email.dat\"));\n *   if (!f) { LOG(FATAL) << \"email.dat does not exist!; }\n *   if (!f.ReadVector(emails) { LOG(FATAL) << \"unable to load email.dat\"; }\n *   // No need to close f since when f goes out of scope it'll close automatically.\n */\ntemplate <typename RECORD, ssize_t SIZE = sizeof(RECORD)> class DataFile final {\npublic:\n  using size_type = ssize_t;\n\n  explicit DataFile(const std::filesystem::path& full_file_name,\n                    int nFileMode = File::modeDefault,\n                    int nShareMode = File::shareUnknown)\n    : file_(full_file_name) {\n    file_.Open(nFileMode, nShareMode);\n  }\n\n  ~DataFile() = default;\n\n  [[nodiscard]] File& file() { return file_; }\n\n  void Close() { file_.Close(); }\n\n  [[nodiscard]] bool ok() const { return file_.IsOpen(); }\n\n  bool ReadVector(std::vector<RECORD>& records, size_type max_records = 0) {\n    auto num_to_read = number_of_records();\n    if (num_to_read == 0) {\n      // Reading nothing is always successful.\n      return true;\n    }\n    if (max_records != 0 && max_records < num_to_read) {\n      num_to_read = max_records;\n    }\n    if (stl::ssize(records) < num_to_read) {\n      records.resize(num_to_read);\n    }\n    return Read(&records[0], num_to_read);\n  }\n\n  bool Read(RECORD* record, size_type num_records = 1) {\n    if (num_records == 0) {\n      // Reading nothing is always successful.\n      return true;\n    }\n    return file_.Read(record, num_records * SIZE) == static_cast<int>(num_records * SIZE);\n  }\n\n  bool Read(size_type record_number, RECORD* record) {\n    if (!Seek(record_number)) {\n      return false;\n    }\n    return Read(record);\n  }\n\n  bool WriteVector(const std::vector<RECORD>& records, size_type max_records = 0) {\n    if (records.empty()) {\n      return true;\n    }\n    size_type num = stl::ssize(records);\n    if (max_records != 0 && max_records < num) {\n      num = max_records;\n    }\n    return Write(&records[0], num);\n  }\n\n  bool WriteVectorAndTruncate(const std::vector<RECORD>& records, size_type max_records = 0) {\n    if (!WriteVector(records, max_records)) {\n      return false;\n    }\n    file_.Close();\n    file_.set_length(wwiv::stl::ssize(records) * SIZE);\n    return true;\n  }\n\n  bool Write(const RECORD* record, size_type num_records = 1) {\n    return file_.Write(record, num_records * SIZE) == (num_records * SIZE);\n  }\n\n  bool Write(size_type record_number, const RECORD* record) {\n    if (!Seek(record_number)) {\n      return false;\n    }\n    return Write(record);\n  }\n\n  bool Seek(size_type record_number) {\n    return file_.Seek(record_number * SIZE, File::Whence::begin) ==\n           static_cast<File::size_type>(record_number * SIZE);\n  }\n\n  [[nodiscard]] size_type number_of_records() const noexcept {\n    return static_cast<int>(file_.length() / SIZE);\n  }\n\n  explicit operator bool() const noexcept { return file_.IsOpen(); }\n\nprivate:\n  File file_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "core/datafile_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nTEST(DataFileTest, Read) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  File x(FilePath(tmp, \"Read\"));\n  ASSERT_TRUE(x.Open(File::modeCreateFile | File::modeBinary | File::modeReadWrite));\n  T t1{1, 2};\n  T t2{3, 4};\n  x.Write(&t1, sizeof(T));\n  x.Write(&t2, sizeof(T));\n  x.Close();\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"Read\"), File::modeReadOnly);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    EXPECT_EQ(2, datafile.number_of_records());\n    T t{0, 0};\n    EXPECT_TRUE(datafile.Read(&t));\n    EXPECT_EQ(1, t.a);\n    EXPECT_EQ(2, t.b);\n\n    EXPECT_TRUE(datafile.Read(&t));\n    EXPECT_EQ(3, t.a);\n    EXPECT_EQ(4, t.b);\n\n    EXPECT_TRUE(datafile.Read(1, &t));\n    EXPECT_EQ(3, t.a);\n    EXPECT_EQ(4, t.b);\n\n    EXPECT_TRUE(datafile.Read(0, &t));\n    EXPECT_EQ(1, t.a);\n    EXPECT_EQ(2, t.b);\n  }\n}\n\nTEST(DataFileTest, ReadVector) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  File x(FilePath(tmp, \"ReadVector\"));\n  ASSERT_TRUE(x.Open(File::modeCreateFile | File::modeBinary | File::modeReadWrite));\n  T t1{1, 2};\n  T t2{3, 4};\n  T t3{5, 6};\n  x.Write(&t1, sizeof(T));\n  x.Write(&t2, sizeof(T));\n  x.Write(&t3, sizeof(T));\n  x.Close();\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"ReadVector\"), File::modeReadOnly);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    EXPECT_EQ(3, datafile.number_of_records());\n    std::vector<T> t;\n    EXPECT_TRUE(datafile.ReadVector(t));\n    EXPECT_EQ(static_cast<size_t>(3), t.size());\n    EXPECT_EQ(1, t[0].a);\n    EXPECT_EQ(2, t[0].b);\n    EXPECT_EQ(3, t[1].a);\n    EXPECT_EQ(4, t[1].b);\n    EXPECT_EQ(5, t[2].a);\n    EXPECT_EQ(6, t[2].b);\n  }\n}\n\nTEST(DataFileTest, ReadVector_Empty) {\n  struct T {\n    int a;\n    int b;\n  };\n  const wwiv::core::test::FileHelper file{};\n  const auto& tmp = file.TempDir();\n\n  {\n    File x(FilePath(tmp, \"ReadVector_Empty\"));\n    ASSERT_TRUE(x.Open(File::modeCreateFile | File::modeBinary | File::modeReadWrite));\n    x.Close();\n  }\n\n  DataFile<T> datafile(FilePath(tmp, \"ReadVector_Empty\"), File::modeReadOnly);\n  ASSERT_TRUE(static_cast<bool>(datafile));\n  EXPECT_EQ(0, datafile.number_of_records());\n  std::vector<T> t{};\n  EXPECT_TRUE(datafile.ReadVector(t));\n  EXPECT_EQ(static_cast<size_t>(0), t.size());\n}\n\nTEST(DataFileTest, ReadVector_MaxRecords) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  File x(FilePath(tmp, \"ReadVector_MaxRecords\"));\n  ASSERT_TRUE(x.Open(File::modeCreateFile | File::modeBinary | File::modeReadWrite));\n  T t1{1, 2};\n  T t2{3, 4};\n  T t3{5, 6};\n  x.Write(&t1, sizeof(T));\n  x.Write(&t2, sizeof(T));\n  x.Write(&t3, sizeof(T));\n  x.Close();\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"ReadVector_MaxRecords\"), File::modeReadOnly);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    EXPECT_EQ(3, datafile.number_of_records());\n    std::vector<T> t;\n    EXPECT_TRUE(datafile.ReadVector(t, 2));\n    EXPECT_EQ(static_cast<size_t>(2), t.size());\n    EXPECT_EQ(1, t[0].a);\n    EXPECT_EQ(2, t[0].b);\n    EXPECT_EQ(3, t[1].a);\n    EXPECT_EQ(4, t[1].b);\n  }\n}\n\nTEST(DataFileTest, Write) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  T t1{1, 2};\n  T t2{3, 4};\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"Write\"),\n                         File::modeCreateFile | File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    datafile.Write(&t1);\n    datafile.Write(&t2);\n  }\n  File x(FilePath(tmp, \"Write\"));\n  ASSERT_TRUE(x.Open(File::modeBinary | File::modeReadOnly));\n  x.Read(&t1, sizeof(T));\n  x.Read(&t2, sizeof(T));\n  x.Close();\n  EXPECT_EQ(1, t1.a);\n  EXPECT_EQ(2, t1.b);\n  EXPECT_EQ(3, t2.a);\n  EXPECT_EQ(4, t2.b);\n}\n\nTEST(DataFileTest, WriteVector) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  T t1{1, 2};\n  T t2{3, 4};\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"WriteVector\"),\n                         File::modeCreateFile | File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    std::vector<T> t = {t1, t2};\n    datafile.WriteVector(t);\n  }\n  File x(FilePath(tmp, \"WriteVector\"));\n  ASSERT_TRUE(x.Open(File::modeBinary | File::modeReadOnly));\n  x.Read(&t1, sizeof(T));\n  EXPECT_EQ(1, t1.a);\n  EXPECT_EQ(2, t1.b);\n  x.Read(&t2, sizeof(T));\n  EXPECT_EQ(3, t2.a);\n  EXPECT_EQ(4, t2.b);\n  x.Close();\n}\n\nTEST(DataFileTest, WriteVector_Empty) {\n  struct T {\n    int a;\n    int b;\n  };\n  const wwiv::core::test::FileHelper file{};\n  const auto& tmp = file.TempDir();\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"WriteVector_Empty\"),\n                         File::modeCreateFile | File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    const std::vector<T> t{};\n    EXPECT_TRUE(datafile.WriteVector(t));\n  }\n  File x(FilePath(tmp, \"WriteVector_Empty\"));\n  ASSERT_TRUE(x.Open(File::modeBinary | File::modeReadOnly));\n  EXPECT_EQ(0, x.length());\n}\n\nTEST(DataFileTest, WriteVector_MaxRecords) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  T t1{1, 2};\n  T t2{3, 4};\n  T t3{5, 6};\n\n  {\n    DataFile<T> datafile(FilePath(tmp, \"WriteVector_MaxRecords\"),\n                         File::modeCreateFile | File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    std::vector<T> t = {t1, t2, t3};\n    datafile.WriteVector(t, 2);\n  }\n  File x(FilePath(tmp, \"WriteVector_MaxRecords\"));\n  ASSERT_TRUE(x.Open(File::modeBinary | File::modeReadOnly));\n  ASSERT_EQ(static_cast<long>(2 * sizeof(T)), x.length());\n  x.Read(&t1, sizeof(T));\n  EXPECT_EQ(1, t1.a);\n  EXPECT_EQ(2, t1.b);\n  x.Read(&t2, sizeof(T));\n  EXPECT_EQ(3, t2.a);\n  EXPECT_EQ(4, t2.b);\n  x.Close();\n}\n\nTEST(DataFileTest, WriteVectorAndTruncate) {\n  struct T {\n    int a;\n    int b;\n  };\n  wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  T t1{1, 2};\n  T t2{3, 4};\n  const auto path = FilePath(tmp, \"WriteVectorAndTruncate\");\n  File f(path);\n\n  {\n    // Create file containing two files.\n    DataFile<T> datafile(path, File::modeCreateFile | File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    std::vector<T> t = {t1, t2};\n    datafile.WriteVector(t);\n    ASSERT_EQ(f.length(), static_cast<File::size_type>(2 * sizeof(T)));\n  }\n\n  {\n    DataFile<T> datafile(path, File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    datafile.WriteVector({t1});\n    // Should still\n    ASSERT_EQ(f.length(), static_cast<File::size_type>(2 * sizeof(T)));\n  }\n\n  {\n    DataFile<T> datafile(path, File::modeBinary | File::modeReadWrite);\n    ASSERT_TRUE(static_cast<bool>(datafile));\n    datafile.WriteVectorAndTruncate({t1});\n    datafile.Close();\n    ASSERT_EQ(f.length(), static_cast<File::size_type>(sizeof(T)));\n  }\n}\n\nTEST(DataFileTest, Read_DoesNotExist) {\n  struct T {\n    int a;\n  };\n  const wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n  const DataFile<T> datafile(FilePath(tmp, \"DoesNotExist\"), File::modeBinary | File::modeReadWrite);\n  if (datafile) {\n    FAIL() << \"file should not exist.\";\n  }\n  EXPECT_FALSE(datafile);\n}\n"
  },
  {
    "path": "core/datetime.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/datetime.h\"\n\n#include \"core/clock.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include <chrono>\n#include <ctime>\n#include <iomanip>\n#include <regex>\n#include <sstream>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\ntime_t time_t_now() { return time(nullptr); }\n\ndaten_t daten_t_now() { return time_t_to_daten(time_t_now()); }\n\n// This kludge will get us through 2029 and should not interfere anywhere else.\ndaten_t date_to_daten(const std::string& datet) {\n  if (datet.size() != 8) {\n    return 0;\n  }\n\n  auto t = time_t_now();\n  auto pTm = localtime(&t);\n  pTm->tm_mon = to_number<int>(datet) - 1;\n  pTm->tm_mday = atoi(datet.c_str() + 3);\n  // N.B. tm_year is years since 1900\n  pTm->tm_year = atoi(datet.c_str() + 6); // fixed for 1930-2029\n  if (datet[6] < '3') {\n    pTm->tm_year += 100;\n  }\n  pTm->tm_hour = 0;\n  pTm->tm_min = 0;\n  pTm->tm_sec = 0;\n  pTm->tm_isdst = 0; // Since this is used for arbitrary compare of date strings, this is ok.\n\n  return time_t_to_daten(mktime(pTm));\n}\n\nstd::string daten_to_wwivnet_time(daten_t t) {\n  return time_t_to_wwivnet_time(static_cast<time_t>(t));\n}\n\nstd::string time_t_to_wwivnet_time(time_t t) {\n  const auto dt = DateTime::from_time_t(t);\n  return dt.to_string();\n}\n\ndaten_t time_t_to_daten(time_t t) { return static_cast<daten_t>(t); }\n\nstd::string date() {\n  const auto dt = DateTime::now();\n  return dt.to_string(\"%m/%d/%y\");\n}\n\nstd::string fulldate() {\n  const auto dt = DateTime::now();\n  return dt.to_string(\"%m/%d/%Y\");\n}\n\nstd::string times() {\n  const auto dt = DateTime::now();\n  return dt.to_string(\"%H:%M:%S\");\n}\n\nstd::string to_string(duration<double> dd) {\n  auto ns = duration_cast<nanoseconds>(dd);\n  typedef duration<int, std::ratio<86400>> days;\n  std::ostringstream os;\n  const auto d = duration_cast<days>(ns);\n  ns -= d;\n  const auto h = duration_cast<hours>(ns);\n  ns -= h;\n  const auto m = duration_cast<minutes>(ns);\n  ns -= m;\n  const auto s = duration_cast<seconds>(ns);\n  ns -= s;\n  const auto ms = duration_cast<milliseconds>(ns);\n  ns -= ms;\n  auto has_one = false;\n  if (d.count() > 0) {\n    os << d.count() << \"d\";\n    has_one = true;\n  }\n  if (h.count() > 0) {\n    if (has_one) {\n      os << \" \";\n    } else {\n      has_one = true;\n    }\n    os << h.count() << \"h\";\n  }\n  if (m.count() > 0) {\n    if (has_one) {\n      os << \" \";\n    } else {\n      has_one = true;\n    }\n    os << m.count() << \"m\";\n  }\n  if (s.count() > 0) {\n    if (has_one) {\n      os << \" \";\n    } else {\n      has_one = true;\n    }\n    os << s.count() << \"s\";\n  }\n  if (ms.count() > 0) {\n    if (has_one) {\n      os << \" \";\n    }\n    os << ms.count() << \"ms\";\n  }\n  return os.str();\n}\n\nstd::optional<duration<double>> parse_time_span(const std::string& s) {\n  if (s.length() < 2) {\n    return std::nullopt;\n  }\n\n  // we don't allow negative timespans, so we'll fail on those.\n  if (!isdigit(s.front())) {\n    return std::nullopt;\n  }\n  const auto num = wwiv::strings::to_number<int>(s.substr(0, s.size() - 1));\n  if (num == 0) {\n    return std::nullopt;\n  }\n\n  switch (to_lower_case(s.back())) {\n  case 's':\n    return seconds(num);\n  case 'm':\n    return minutes(num);\n  case 'h':\n    return hours(num);\n  case 'd':\n    return hours(num * 24);\n  default:\n    return std::nullopt;\n  }\n}\n\nint years_old(int m, int d, int y, Clock& clock) {\n  const auto t = clock.Now();\n  const auto tm_now = t.to_tm();\n  y -= 1900;\n  --m; // Reduce by one because tm_mon is 0-11, not 1-12\n\n  // Find the range of impossible dates (ie, pTm can't be\n  // less than the input date)\n  if (tm_now.tm_year < y) {\n    return 0;\n  }\n  if (tm_now.tm_year == y) {\n    if (tm_now.tm_mon < m) {\n      return 0;\n    }\n    if (tm_now.tm_mon == m) {\n      if (tm_now.tm_mday < d) {\n        return 0;\n      }\n    }\n  }\n\n  auto age = tm_now.tm_year - y;\n  // ReSharper disable once CppRedundantParentheses\n  if (tm_now.tm_mon < m || (tm_now.tm_mon == m && tm_now.tm_mday < d)) {\n    --age;\n  }\n  return age;\n}\n\nDateTime parse_yyyymmdd(const std::string& date_str) {\n  // Avoid https://developercommunity.visualstudio.com/content/problem/18311/stdget-time-asserts-with-istreambuf-iterator-is-no.html\n  std::regex date_time_regex(\"([0-9]{4})-([0-9]{2})-([0-9]{2})\");\n  if (!std::regex_match(date_str, date_time_regex)) {\n    return DateTime::now();\n  }\n\n  std::istringstream ss{date_str};\n  ss.exceptions(std::ios::goodbit);\n  std::tm dt{};\n  ss >> std::get_time(&dt, \"%Y-%m-%d\");\n  if (ss.fail()) {\n    return DateTime::now();\n  }\n  dt.tm_hour = 12;\n  dt.tm_min = 0;\n  dt.tm_sec = 0;\n  return DateTime::from_tm(&dt);\n}\n\nDateTime parse_yyyymmdd_with_optional_hms(const std::string& date_str) {\n  // Avoid https://developercommunity.visualstudio.com/content/problem/18311/stdget-time-asserts-with-istreambuf-iterator-is-no.html\n  std::regex date_time_regex(\"([0-9]{4})-([0-9]{2})-([0-9]{2})\\\\s([0-9]{2}):([0-9]{2}):([0-9]{2})\");\n  if (!std::regex_match(date_str, date_time_regex)) {\n    return parse_yyyymmdd(date_str);\n  }\n\n  std::istringstream ss{date_str};\n  ss.exceptions(std::ios::goodbit);\n  std::tm dt{};\n  ss >> std::get_time(&dt, \"%Y-%m-%d %H:%M:%S\");\n  if (ss.fail()) {\n    return parse_yyyymmdd(date_str);\n  }\n  return DateTime::from_tm(&dt);\n}\n\nDateTime::DateTime(system_clock::time_point t)\n  : t_(system_clock::to_time_t(t)),\n    millis_(static_cast<int>(duration_cast<milliseconds>(t.time_since_epoch()).count() % 1000)) {\n  update_tm();\n}\n\nstatic time_t mktime_no_dst_changes(tm* t) noexcept {\n  // Kludge to match the is_dst match so that our hour\n  // matches exactly in the tm struct and isn't offset\n  // for daylight savings time.\n  auto t2{*t};\n  mktime(&t2);\n  t->tm_isdst = t2.tm_isdst;\n  return mktime(t);\n}\n\nDateTime::DateTime(tm* t)\n  : t_(mktime_no_dst_changes(t)), tm_(*t), millis_(0) {\n  if (t_ < 0) {\n    t_ = 0;\n    update_tm();\n  }\n}\n\nDateTime::DateTime(time_t t) : t_(t), millis_(0) { update_tm(); }\n\nDateTime::DateTime()\n  : DateTime(static_cast<time_t>(0)) {\n}\n\nDateTime::DateTime(const DateTime& other) : DateTime(other.to_time_t()) {\n  millis_ = other.millis_;\n}\n\nDateTime::DateTime(DateTime&& other) noexcept : DateTime(other.to_time_t()) {\n  millis_ = other.millis_;\n}\n\nDateTime& DateTime::operator=(const DateTime& o) {\n  t_ = o.to_time_t();\n  millis_ = o.millis_;\n  update_tm();\n  return *this;\n}\n\nDateTime& DateTime::operator=(DateTime&& o) noexcept {\n  t_ = o.to_time_t();\n  millis_ = o.millis_;\n  update_tm();\n  return *this;\n}\n\nstd::string DateTime::to_string(const std::string& format) const {\n  std::ostringstream ss;\n  ss << std::put_time(&tm_, format.c_str());\n  return ss.str();\n}\n\nstd::string DateTime::to_string() const {\n  const auto* t = asctime(&tm_);\n  if (!t) {\n    return {};\n  }\n  auto s = std::string(t);\n  StringTrimEnd(&s);\n  return s;\n}\n\n// static\nDateTime DateTime::now() { return DateTime(system_clock::now()); }\n\nstruct tm DateTime::to_tm() const noexcept {\n  return tm_;\n}\n\nvoid DateTime::update_tm() noexcept {\n  if (t_ < 0) {\n    t_ = 1;\n  }\n  if (const auto * tm = localtime(&t_);tm) {\n    tm_ = *tm;\n  } else {\n    LOG(ERROR) << \"Invalid Time passed to update_tm\";    \n    auto tnow = time(nullptr);\n    const auto* nowtm = localtime(&tnow);\n    tm_ = *nowtm;\n  }\n}\n\nsystem_clock::time_point DateTime::to_system_clock() const noexcept {\n  return system_clock::from_time_t(t_);\n}\n\nbool operator==(const DateTime& lhs, const DateTime& rhs) {\n  return lhs.to_time_t() == rhs.to_time_t();\n}\n\nbool operator!=(const DateTime& lhs, const DateTime& rhs) {\n  return lhs.to_time_t() != rhs.to_time_t();\n}\n\nbool operator>(const DateTime& lhs, const DateTime& rhs) { return rhs < lhs; }\n\nbool operator<=(const DateTime& lhs, const DateTime& rhs) { return !(lhs > rhs); }\n\nbool operator>=(const DateTime& lhs, const DateTime& rhs) { return !(lhs < rhs); }\n\nDateTime operator+(const DateTime& lhs, duration<double> d) {\n  const auto du = std::chrono::duration_cast<seconds>(d);\n  return DateTime::from_time_t(lhs.to_time_t() + static_cast<time_t>(du.count()));\n}\n\nDateTime operator-(const DateTime& lhs, duration<double> d) {\n  const auto du = std::chrono::duration_cast<seconds>(d);\n  return DateTime::from_time_t(lhs.to_time_t() - static_cast<time_t>(du.count()));\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/datetime.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_DATETIME_H\n#define INCLUDED_CORE_DATETIME_H\n\n#include \"core/wwivport.h\"\n#include <chrono>\n#include <ctime>\n#include <optional>\n#include <string>\n\nnamespace wwiv::core {\n\n[[nodiscard]] time_t time_t_now();\n\n[[nodiscard]] daten_t daten_t_now();\n\n/**\n * Constructs a daten_t from a date of the format \"MM/DD/YY\"\n */\n[[nodiscard]] daten_t date_to_daten(const std::string& datet);\n\n[[nodiscard]] std::string daten_to_wwivnet_time(daten_t t);\n[[nodiscard]] std::string time_t_to_wwivnet_time(time_t t);\n[[nodiscard]] daten_t time_t_to_daten(time_t t);\n\nclass Clock;\n\n/** Returns the age of a person both on month m, day d in year y */\n[[nodiscard]] int years_old(int m, int d, int y, Clock& clock);\n\n\n/**\n * Returns the current date as 'MM/DD/YY'\n */\n[[nodiscard]] std::string date();\n\n/**\n * Returns the current date as 'MM/DD/YYYY'\n */\n[[nodiscard]] std::string fulldate();\n\n/**\n * Returns the current time as 'HH:MM:SS'\n */\n[[nodiscard]] std::string times();\n\n/** Displays dd as a human readable time */\nstd::string to_string(std::chrono::duration<double> dd);\n\n/**\n * Parses a duration or timespan into a std::chrono::duration.\n *\n * The timespan should be of the form:\n * \\code \n * [integer][quantum]\n * \\endcode\n *\n * quantum is one of:\n * \\verbatim \n * +---+---------+\n * | s | second  |\n * | m | minute  |\n * | h | hour    |\n * | d | day     |\n * +---+---------+\n * \\endverbatim\n */\nstd::optional<std::chrono::duration<double>> parse_time_span(const std::string&);\n\nclass DateTime final {\npublic:\n  [[nodiscard]] static DateTime from_time_t(time_t t) { return DateTime(t); }\n\n  [[nodiscard]] static DateTime from_tm(tm* t) { return DateTime(t); }\n\n  [[nodiscard]] static DateTime from_daten(daten_t t) {\n    return from_time_t(static_cast<time_t>(t));\n  }\n\n  [[nodiscard]] static DateTime now();\n\n  [[nodiscard]] int hour() const noexcept { return tm_.tm_hour; }\n  [[nodiscard]] int minute() const noexcept { return tm_.tm_min; }\n  [[nodiscard]] int second() const noexcept { return tm_.tm_sec; }\n\n  /** Month starting at 1 for this DateTime */\n  [[nodiscard]] int month() const noexcept { return tm_.tm_mon + 1; }\n\n  /** Day starting at 1 for this DateTime */\n  [[nodiscard]] int day() const noexcept { return tm_.tm_mday; }\n\n  /** Year starting at 0 for this DateTime */\n  [[nodiscard]] int year() const noexcept { return tm_.tm_year + 1900; }\n\n  [[nodiscard]] int dow() const noexcept { return tm_.tm_wday; }\n\n  /** Prints a date using the strftime format specified.  */\n  [[nodiscard]] std::string to_string(const std::string& format) const;\n\n  /** Prints a Date using asctime but without the trailing linefeed. */\n  [[nodiscard]] std::string to_string() const;\n\n  /** Returns this Datetime as a UNIX time_t */\n  [[nodiscard]] time_t to_time_t() const noexcept { return t_; }\n\n  /** Returns this Datetime as a WWIV BBS daten_t */\n  [[nodiscard]] daten_t to_daten_t() const noexcept { return time_t_to_daten(t_); }\n\n  /** Returns this Datetime as a POSIX tm structure. */\n  [[nodiscard]] struct tm to_tm() const noexcept;\n\n  /** Returns this Datetime as a time_point in the std::chrono::system_clock */\n  [[nodiscard]] std::chrono::system_clock::time_point to_system_clock() const noexcept;\n\n  friend DateTime operator+(const DateTime& lhs, std::chrono::duration<double> d);\n\n  DateTime& operator+=(std::chrono::duration<double> d) {\n    const auto du = std::chrono::duration_cast<std::chrono::seconds>(d);\n    t_ += static_cast<time_t>(du.count());\n    update_tm();\n    return *this;\n  }\n\n  friend DateTime operator-(const DateTime& lhs, std::chrono::duration<double> d);\n\n  DateTime& operator-=(std::chrono::duration<double> d) {\n    const auto du = std::chrono::duration_cast<std::chrono::seconds>(d);\n    t_ -= static_cast<time_t>(du.count());\n    update_tm();\n    return *this;\n  }\n\n  friend bool operator<(const DateTime& lhs, const DateTime& rhs) {\n    if (lhs.t_ == rhs.t_) {\n      return lhs.millis_ < rhs.millis_;\n    }\n    return lhs.t_ < rhs.t_;\n  }\n\n  friend bool operator==(const DateTime& lhs, const DateTime& rhs);\n  friend bool operator!=(const DateTime& lhs, const DateTime& rhs);\n\n  friend bool operator>(const DateTime& lhs, const DateTime& rhs);\n\n  friend bool operator<=(const DateTime& lhs, const DateTime& rhs);\n\n  friend bool operator>=(const DateTime& lhs, const DateTime& rhs);\n\n  DateTime();\n  DateTime(const DateTime&);\n  DateTime(DateTime&&) noexcept;\n  DateTime& operator=(const DateTime&);\n  DateTime& operator=(DateTime&&) noexcept;\n  ~DateTime() = default;\n\nprivate:\n  explicit DateTime(std::chrono::system_clock::time_point t);\n  explicit DateTime(tm* t);\n  explicit DateTime(time_t t);\n  /** Updates the tm_ structure, should be called anytime the time_t value is changed */\n  void update_tm() noexcept;\n\n  time_t t_;\n  tm tm_{};\n  int millis_;\n};\n\n[[nodiscard]] DateTime parse_yyyymmdd(const std::string& date_str);\n[[nodiscard]] DateTime parse_yyyymmdd_with_optional_hms(const std::string& date_str);\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/datetime_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2018-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/datetime.h\"\n#include \"core/fake_clock.h\"\n#include \"sdk/user.h\"\n#include <cstdlib>\n#include <ctime>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\n\nstatic std::string daten_to_mmddyyyy(daten_t n) {\n  const auto dt = DateTime::from_daten(n);\n  return dt.to_string(\"%m/%d/%Y\");\n}\n\nTEST(DateTime, Now) {\n  const auto start = DateTime::now();\n  const auto start_t = time(nullptr);\n  EXPECT_LE(std::abs(start.to_time_t() - start_t), 1);\n}\n\nTEST(DateTime, ToDatenT) {\n  const auto start = DateTime::now();\n  const auto t = start.to_time_t();\n  const auto d = start.to_daten_t();\n  EXPECT_EQ(static_cast<time_t>(d), t);\n}\n\nTEST(DateTime, ToSystemClock) {\n  const auto start = DateTime::now();\n  const auto now = system_clock::now();\n  EXPECT_LE(std::abs(start.to_time_t() - system_clock::to_time_t(now)), 1);\n}\n\nTEST(DateTime, OperatorPlus) {\n  const auto start = DateTime::now();\n  const auto start_t = start.to_time_t();\n  const auto start_3s = start + 3s;\n  EXPECT_EQ(start_3s.to_time_t(), start_t + 3);\n}\n\nTEST(DateTime, OperatorMinus) {\n  const auto start = DateTime::now();\n  const auto start_t = start.to_time_t();\n  const auto start_5s = start - 5s;\n  EXPECT_EQ(start_5s.to_time_t(), start_t - 5);\n}\n\nTEST(DateTime, OperatorPlusEquals) {\n  auto start = DateTime::now();\n  const auto start_t = start.to_time_t();\n  start += 3s;\n  EXPECT_EQ(start.to_time_t(), start_t + 3);\n}\n\nTEST(DateTime, OperatorMinusEquals) {\n  auto start = DateTime::now();\n  const auto start_t = start.to_time_t();\n  start -= 5s;\n  EXPECT_EQ(start.to_time_t(), start_t - 5);\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_good_nondst) {\n  const auto dt = parse_yyyymmdd(\"2003-01-02\");\n  EXPECT_EQ(daten_to_mmddyyyy(dt.to_daten_t()), \"01/02/2003\");\n  EXPECT_EQ(12, dt.hour());\n  EXPECT_EQ(0, dt.minute());\n  EXPECT_EQ(0, dt.second());\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_good_dst) {\n  const auto dt = parse_yyyymmdd(\"2003-06-07\");\n  EXPECT_EQ(daten_to_mmddyyyy(dt.to_daten_t()), \"06/07/2003\");\n  EXPECT_EQ(12, dt.hour());\n  EXPECT_EQ(0, dt.minute());\n  EXPECT_EQ(0, dt.second());\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_with_optional_hms_good) {\n  const auto dt = parse_yyyymmdd_with_optional_hms(\"2003-01-02 01:02:03\");\n  EXPECT_EQ(daten_to_mmddyyyy(dt.to_daten_t()), \"01/02/2003\");\n  EXPECT_EQ(1, dt.hour());\n  EXPECT_EQ(2, dt.minute());\n  EXPECT_EQ(3, dt.second());\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_with_optional_hms_good_dst) {\n  const auto dt = parse_yyyymmdd_with_optional_hms(\"2003-06-07 01:02:03\");\n  EXPECT_EQ(daten_to_mmddyyyy(dt.to_daten_t()), \"06/07/2003\");\n  EXPECT_EQ(1, dt.hour());\n  EXPECT_EQ(2, dt.minute());\n  EXPECT_EQ(3, dt.second());\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_with_optional_hms_without_hms) {\n  const auto dt = parse_yyyymmdd_with_optional_hms(\"2003-04-05\");\n  EXPECT_EQ(daten_to_mmddyyyy(dt.to_daten_t()), \"04/05/2003\");\n  EXPECT_EQ(12, dt.hour());\n  EXPECT_EQ(0, dt.minute());\n  EXPECT_EQ(0, dt.second());\n}\n\nTEST(DateTime_Parsing, Parse_yyyymmdd_fail) {\n  const auto dt = parse_yyyymmdd(\"2003-04-05x\");\n  EXPECT_NE(daten_to_mmddyyyy(dt.to_daten_t()), \"04/05/2003\");\n}\n\nTEST(DateTime, Plus_Duration) {\n  const auto t1 = DateTime::now();\n  const auto t2s{t1 + 2s};\n  auto t2{t1};\n  t2 += 2s;\n\n  ASSERT_EQ(2, t2s.to_time_t() - t1.to_time_t());\n  ASSERT_EQ(2, t2.to_time_t() - t1.to_time_t());\n}\n\nTEST(DateTime, Minus_Duration) {\n  const auto t1 = DateTime::now();\n  const auto t2s{t1 - 2s};\n  auto t2{t1};\n  t2 -= 2s;\n\n  ASSERT_EQ(2, t1.to_time_t() - t2s.to_time_t());\n  ASSERT_EQ(2, t1.to_time_t() - t2.to_time_t());\n}\n\nTEST(DateTime, Comparisons) {\n  const auto t1 = DateTime::now();\n  auto t2{t1};\n  t2 += 1s;\n  const auto t1a{t1};\n\n  EXPECT_TRUE(t1 == t1a);\n  ASSERT_EQ(t1, t1a);\n\n  EXPECT_FALSE(t1 == t2);\n  EXPECT_NE(t1, t2);\n\n  EXPECT_GT(t2, t1);\n  EXPECT_LT(t1, t2);\n  EXPECT_LE(t1, t2);\n  EXPECT_LE(t1, t1a) << \"t1: \" << t1.to_string() << \"; t1a: \" << t1a.to_string();\n  EXPECT_GE(t2, t1);\n  EXPECT_GE(t1, t1a);\n}\n\nTEST(DateTime, YearsOld_AfterBirthday) {\n  tm t{};\n  t.tm_mon = 9;\n  t.tm_mday = 25;\n  t.tm_year = 120;\n  const auto now = DateTime::from_tm(&t);\n  FakeClock clock(now);\n  EXPECT_EQ(50, years_old(10, 24, 1970, clock));\n}\n\nTEST(DateTime, YearsOld_OnBirthday) {\n  tm t{};\n  t.tm_mon = 9;\n  t.tm_mday = 25;\n  t.tm_year = 120;\n  const auto now = DateTime::from_tm(&t);\n  FakeClock clock(now);\n  EXPECT_EQ(50, years_old(10, 25, 1970, clock));\n}\n\nTEST(DateTime, YearsOld_BeforeBirthday) {\n  tm t{};\n  t.tm_mon = 9;\n  t.tm_mday = 25;\n  t.tm_year = 120;\n  const auto now = DateTime::from_tm(&t);\n  FakeClock clock(now);\n  EXPECT_EQ(49, years_old(10, 26, 1970, clock));\n}\n\nTEST(DateTime, ParseTimeSpan_Second) {\n  auto o = parse_time_span(\"2s\");\n  ASSERT_TRUE(o);\n\n  EXPECT_EQ(std::chrono::seconds(2), o.value());\n}\n\nTEST(DateTime, ParseTimeSpan_Minute) {\n  auto o = parse_time_span(\"3m\");\n  ASSERT_TRUE(o);\n\n  EXPECT_EQ(std::chrono::minutes(3), o.value());\n}\n\nTEST(DateTime, ParseTimeSpan_Hour) {\n  auto o = parse_time_span(\"4h\");\n  ASSERT_TRUE(o);\n\n  EXPECT_EQ(std::chrono::hours(4), o.value());\n}\n\nTEST(DateTime, ParseTimeSpan_Day) {\n  auto o = parse_time_span(\"5d\");\n  ASSERT_TRUE(o);\n\n  EXPECT_EQ(std::chrono::hours(120), o.value());\n}\n\nTEST(DateTime, ParseTimeSpan_Invalid) {\n  ASSERT_FALSE(parse_time_span(\"\"));\n  ASSERT_FALSE(parse_time_span(\"d1\"));\n  ASSERT_FALSE(parse_time_span(\"1q\"));\n  ASSERT_FALSE(parse_time_span(\"q\"));\n  ASSERT_FALSE(parse_time_span(\"s\"));\n  ASSERT_FALSE(parse_time_span(\"d\"));\n  ASSERT_FALSE(parse_time_span(\"h\"));\n  ASSERT_FALSE(parse_time_span(\"m\"));\n  ASSERT_FALSE(parse_time_span(\"-1s\"));\n}\n\nTEST(DateTime, MinusOne) {\n  const auto d = DateTime::from_time_t(-1);\n  EXPECT_EQ(d.year(), 1969);\n  EXPECT_EQ(d.month(), 12);\n  EXPECT_EQ(d.day(), 31);\n}\n"
  },
  {
    "path": "core/eventbus.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/eventbus.h\"\n\nnamespace wwiv::core {\n\nEventBus bus_;\n\n// Returns the singleton global instance.\nEventBus& bus() { return bus_; }\n\n} // namespace wwiv::core\n"
  },
  {
    "path": "core/eventbus.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_EVENTBUS_H\n#define INCLUDED_CORE_EVENTBUS_H\n\n#include \"core/log.h\"\n#include \"core/callable/callable.hpp\"\n#include <any>\n#include <functional>\n#include <string>\n#include <type_traits>\n#include <unordered_map>\n\nnamespace wwiv::core {\n\nclass EventBus final {\npublic:\n  EventBus() = default;\n  EventBus(const EventBus&) = delete;\n  EventBus(EventBus&&) = delete;\n  EventBus& operator=(const EventBus&) = delete;\n  EventBus& operator=(EventBus&&) = delete;\n  ~EventBus() = default;\n\n  template<typename T, typename H> void add_handler(H handler) {\n    static_assert(!std::is_reference<T>::value, \"add_handler: Handler param must not be reference\");\n    const std::string name = typeid(T).name();\n    if constexpr (callable_traits<H>::argc == 0) {\n      handlers_.emplace(name, [handler](std::any) { handler(); });\n    } else {\n      handlers_.emplace(name,\n                        [f = std::forward<H>(handler)](auto value) { f(std::any_cast<T>(value)); });\n    }\n  }\n\n  template <typename T, typename M, typename I> void add_handler(M method, I instance) {\n    const std::string name = typeid(T).name();\n    std::function<void(T)> f = std::bind(method, instance, std::placeholders::_1);\n    handlers_.emplace(name, [f](auto value) { f(std::any_cast<T>(value)); });\n  }\n\n  template <typename T> void invoke() { invoke(T{}); }\n\n  template <typename T> void invoke(const T& event_type) {\n    const std::string name = typeid(T).name();\n    auto [first_hdandler, last_handler] = handlers_.equal_range(name);\n    for (auto& it = first_hdandler; it != last_handler; ++it) {\n      try {\n        it->second(std::make_any<T>(event_type));\n      } catch (const std::bad_cast& e) {\n        LOG(INFO) << e.what();\n      }\n    }\n  }\n\n\n  std::unordered_multimap<std::string, std::function<void(std::any)>> handlers_;\n};\n\nEventBus& bus();\n\n} // namespace wwiv::core\n\n#endif\n"
  },
  {
    "path": "core/eventbus_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/eventbus.h\"\n#include <iostream>\n\nusing namespace wwiv::core;\n\nclass EventBusTest : public ::testing::Test {\npublic:\n  EventBus b;\n};\n\nstruct MessagePosted {\n  int num;\n};\n\nTEST_F(EventBusTest, Function) {\n  auto num = 1;\n  b.add_handler<MessagePosted>([&num](MessagePosted m) { num += m.num; });\n\n  const MessagePosted m{1};\n  b.invoke(m);\n  EXPECT_EQ(2, num);\n}\n\nTEST_F(EventBusTest, Function_Zero_Args) {\n  auto num = 1;\n  b.add_handler<MessagePosted>([&num]() { num++; });\n\n  const MessagePosted m{1};\n  b.invoke(m);\n  EXPECT_EQ(2, num);\n}\nTEST_F(EventBusTest, Function_Const) {\n  auto num = 1;\n  b.add_handler<MessagePosted>([&num](const MessagePosted& m) { num += m.num; });\n\n  const MessagePosted m{1};\n  b.invoke(m);\n  EXPECT_EQ(2, num);\n}\nTEST_F(EventBusTest, Function_Any) {\n  auto num = 1;\n  b.add_handler<MessagePosted>([&num](std::any m) {\n    const auto n = std::any_cast<MessagePosted>(m).num;\n    std::cout << \"n: \" << n << std::endl;\n    num += n;\n  });\n\n  const MessagePosted m{1};\n  b.invoke(m);\n  EXPECT_EQ(2, num);\n}\n\nstatic int method_num = 1;\nvoid Method(MessagePosted m) { method_num += m.num; };\n\nTEST_F(EventBusTest, Method) {\n  b.add_handler<MessagePosted>(Method);\n\n  const MessagePosted m{1};\n  b.invoke(m);\n  EXPECT_EQ(2, method_num);\n}\n\nTEST_F(EventBusTest, Class) {\n  struct Empty {\n    int x;\n  };\n\n  class Class {\n  public:\n    int num{1};\n    void Method(MessagePosted m) { num += m.num; }\n  };\n\n  Class c;\n  b.add_handler<MessagePosted>(&Class::Method, &c);\n  b.invoke(MessagePosted{1});\n  EXPECT_EQ(2, c.num);\n}\n"
  },
  {
    "path": "core/fake_clock.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/fake_clock.h\"\n\n#include \"core/datetime.h\"\n#include <chrono>\n\nusing namespace std::chrono;\n\nnamespace wwiv::core {\n\nDateTime FakeClock::Now() const noexcept {\n  return date_time_;\n}\n\nvoid FakeClock::tick(duration<double> d) { date_time_ += d; }\n\nvoid FakeClock::SleepFor(duration<double> d) { tick(d); }\n\n}\n"
  },
  {
    "path": "core/fake_clock.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_FAKE_CLOCK_H\n#define INCLUDED_CORE_FAKE_CLOCK_H\n\n#include \"core/clock.h\"\n#include \"core/datetime.h\"\n\n#include <chrono>\n\nnamespace wwiv::core {\n\nclass FakeClock final : public Clock {\npublic:\n  explicit FakeClock(const DateTime& dt)\n    : date_time_(dt) {\n  }\n\n  [[nodiscard]] DateTime Now() const noexcept override;\n  void tick(std::chrono::duration<double> inc);\n  void SleepFor(std::chrono::duration<double>);\n\nprivate:\n  DateTime date_time_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/fake_clock_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/fake_clock.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace std::chrono;\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\n\nTEST(FakeClock, Simple) { \n  FakeClock c{DateTime::now()};\n  const auto start = c.Now();\n  c.tick(2s);\n  const auto mid = c.Now();\n  c.tick(3s);\n  const auto end = c.Now();\n\n  auto duration = duration_cast<seconds>(mid.to_system_clock() - start.to_system_clock());\n  EXPECT_EQ(2s, duration);\n  duration = duration_cast<seconds>(end.to_system_clock() - mid.to_system_clock());\n  EXPECT_EQ(3s, duration);\n}\n"
  },
  {
    "path": "core/file.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"core/file.h\"\r\n\r\n#include \"core/datetime.h\"\r\n#include \"core/log.h\"\r\n#include \"core/os.h\"\r\n#include \"core/strings.h\"\r\n#include \"core/wfndfile.h\"\r\n#include <cerrno>\r\n#include <cstring>\r\n#include <string>\r\n#include \"core/findfiles.h\"\r\n\r\n// Keep all of these\r\n#ifdef _WIN32\r\n// This makes it clear that we want the POSIX names without\r\n// leading underscores  This makes resharper happy with fcntl.h too.\r\n#define _CRT_DECLARE_NONSTDC_NAMES 1  \r\n#endif // _WIN32\r\n\r\n#include <fcntl.h>\r\n#include <sys/stat.h>\r\n#include <system_error>\r\n#include <utility>\r\n\r\n#ifdef _WIN32\r\n#include \"sys/utime.h\"\r\n#include <io.h>\r\n\r\n#else\r\n#include <sys/file.h>\r\n#include <sys/types.h>\r\n#include <unistd.h>\r\n#include <utime.h>\r\n#endif // _WIN32\r\n\r\n\r\n#ifdef _WIN32\r\n#include \"core/wwiv_windows.h\"\r\n\r\nstatic int flock(int, int) { return 0; }\r\n\r\nstatic constexpr int LOCK_SH = 1;\r\nstatic constexpr int LOCK_EX = 2;\r\n//static constexpr int LOCK_NB = 4;\r\nstatic constexpr int LOCK_UN = 8;\r\n\r\n#else\r\n\r\n// Not Win32\r\n#define _sopen(n, f, s, p) open(n, f, 0644)\r\n\r\n#endif // _WIN32\r\n\r\nusing std::chrono::milliseconds;\r\nusing namespace wwiv::os;\r\nusing namespace std::filesystem;\r\n\r\nnamespace wwiv::core {\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Constants\r\n\r\nconst int File::modeDefault = O_RDWR | O_BINARY;\r\nconst int File::modeAppend = O_APPEND;\r\nconst int File::modeBinary = O_BINARY;\r\nconst int File::modeCreateFile = O_CREAT;\r\nconst int File::modeReadOnly = O_RDONLY;\r\nconst int File::modeReadWrite = O_RDWR;\r\nconst int File::modeText = O_TEXT;\r\nconst int File::modeWriteOnly = O_WRONLY;\r\nconst int File::modeTruncate = O_TRUNC;\r\nconst int File::modeExclusive = O_EXCL;\r\nconst int File::modeUnknown = -1;\r\nconst int File::shareUnknown = -1;\r\n\r\nconst int File::invalid_handle = -1;\r\n\r\nstatic const milliseconds wait_time(10);\r\n\r\nstatic constexpr int TRIES = 100;\r\n\r\nusing namespace strings;\r\n\r\npath FilePath(const path& directory_name, const path& file_name) {\r\n  if (directory_name.empty()) {\r\n    return file_name;\r\n  }\r\n  if (File::is_absolute(file_name)) {\r\n    LOG(INFO) << \"Passed absolute filename to FilePath: \" << file_name;\r\n    // TODO(rushfan): here once we are sure this won't break things.\r\n    // return file_name; \r\n  }\r\n  return directory_name / file_name;\r\n}\r\n\r\nvoid trim_backups(const path& from, int max_backups) {\r\n  auto mask{from};\r\n  mask += \".backup.*\";\r\n  FindFiles ff(mask, FindFiles::FindFilesType::files, FindFiles::WinNameType::long_name);\r\n  if (!from.has_filename()) {\r\n    LOG(WARNING) << \"Called trim_backups on file without a filename: '\" << from.string() << \"'\";\r\n    return;\r\n  }\r\n\r\n  const auto tot = static_cast<int>(ff.size());\r\n  if (tot <= max_backups) {\r\n    return;\r\n  }\r\n  auto num_to_remove = tot - max_backups;\r\n  for (const auto& f : ff) {\r\n    if (num_to_remove-- == 0) {\r\n      break;\r\n    }\r\n    auto file{from};\r\n    VLOG(1) << \"Delete backup: \" << file.replace_filename(f.name);\r\n    File::Remove(file.replace_filename(f.name));\r\n  }\r\n}\r\n\r\nbool backup_file(const path& from, int max_backups) {\r\n  auto to{from};\r\n  to += StrCat(\".backup.\", DateTime::now().to_string(\"%Y%m%d%H%M%S\"));\r\n  VLOG(1) << \"Backing up file: '\" << from << \"'; to: '\" << to << \"'\";\r\n  std::error_code ec;\r\n  if (!copy_file(from, to, ec)) {\r\n    return false;\r\n  }\r\n  if (max_backups > 0) {\r\n    trim_backups(from, max_backups);\r\n  }\r\n  return true;\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Constructors/Destructors\r\n\r\n// File::File(const string& full_file_name) : full_path_name_(full_file_name) {}\r\n\r\n/** Constructs a file from a path. */\r\nFile::File(std::filesystem::path full_path_name)\r\n  : full_path_name_(std::move(full_path_name)) {\r\n}\r\n\r\nFile::File(File&& other) noexcept\r\n  : handle_(other.handle_) {\r\n  other.handle_ = -1;\r\n  full_path_name_.swap(other.full_path_name_);\r\n  error_text_.swap(other.error_text_);\r\n}\r\n\r\nFile& File::operator=(File&& other) noexcept {\r\n  if (this != &other) {\r\n    handle_ = other.handle_;\r\n    full_path_name_.swap(other.full_path_name_);\r\n    error_text_.swap(other.error_text_);\r\n    other.handle_ = -1;\r\n  }\r\n  return *this;\r\n}\r\n\r\n\r\nFile::~File() {\r\n  if (this->IsOpen()) {\r\n    this->Close();\r\n  }\r\n}\r\n\r\nbool File::Open(int file_mode, int share_mode) {\r\n  DCHECK_EQ(this->IsOpen(), false) << \"File \" << full_path_name_ << \" is already open.\";\r\n\r\n  // Set default share mode\r\n  if (share_mode == shareUnknown) {\r\n    share_mode = shareDenyWrite;\r\n    if (file_mode & modeReadWrite || file_mode & modeWriteOnly) {\r\n      share_mode = shareDenyReadWrite;\r\n    }\r\n  }\r\n\r\n  CHECK_NE(share_mode, File::shareUnknown);\r\n  CHECK_NE(file_mode, File::modeUnknown);\r\n\r\n  VLOG(5) << \"File::Open (before _sopen) \" << full_path_name_ << \", access=\" << file_mode;\r\n\r\n#if defined(__OS2__)\r\n  if (file_mode & O_CREAT) {\r\n    // See https://lists.mysql.com/internals/312\r\n    VLOG(4) << \"Using OS/2 O_CREAT path\";\r\n    handle_ = open(full_path_name_.string().c_str(), file_mode, S_IREAD | S_IWRITE);\r\n    if (handle_ == invalid_handle) {\r\n      this->error_text_ = strerror(errno);\r\n    }\r\n    \r\n    return IsFileHandleValid(handle_);\r\n  }\r\n#endif  // __OS2__\r\n\r\n  handle_ = _sopen(full_path_name_.string().c_str(), file_mode, share_mode, _S_IREAD | _S_IWRITE);\r\n  if (handle_ < 0) {\r\n    VLOG(4) << \"1st _sopen: handle: \" << handle_ << \"; error: \" << strerror(errno);\r\n    auto count = 1;\r\n    if (access(full_path_name_.string().c_str(), 0) != -1) {\r\n      sleep_for(wait_time);\r\n      handle_ =\r\n          _sopen(full_path_name_.string().c_str(), file_mode, share_mode, _S_IREAD | _S_IWRITE);\r\n      while (handle_ < 0 && errno == EACCES && count < TRIES) {\r\n        sleep_for(count % 2 ? wait_time : milliseconds(0));\r\n        VLOG(4) << \"Waiting to access \" << full_path_name_ << \"  \" << TRIES - count;\r\n        count++;\r\n        handle_ =\r\n            _sopen(full_path_name_.string().c_str(), file_mode, share_mode, _S_IREAD | _S_IWRITE);\r\n      }\r\n\r\n      if (handle_ < 0) {\r\n        VLOG(4) << \"The file \" << full_path_name_ << \" is busy.  Try again later.\";\r\n      }\r\n    }\r\n  }\r\n\r\n  VLOG(3) << \"File::Open '\" << full_path_name_ << \"', access=\" << file_mode << \", handle=\" << handle_;\r\n\r\n  if (IsFileHandleValid(handle_)) {\r\n    flock(handle_,\r\n          (share_mode == shareDenyReadWrite || share_mode == shareDenyWrite) ? LOCK_EX : LOCK_SH);\r\n  }\r\n\r\n  if (handle_ == invalid_handle) {\r\n    this->error_text_ = strerror(errno);\r\n  }\r\n\r\n  return IsFileHandleValid(handle_);\r\n}\r\n\r\nbool File::IsOpen() const noexcept { return IsFileHandleValid(handle_); }\r\n\r\nvoid File::Close() noexcept {\r\n  VLOG(4) << \"CLOSE \" << full_path_name_ << \", handle=\" << handle_;\r\n  if (IsFileHandleValid(handle_)) {\r\n    flock(handle_, LOCK_UN);\r\n    close(handle_);\r\n    handle_ = invalid_handle;\r\n  }\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Member functions\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nFile::size_type File::Read(void* buffer, File::size_type size) {\r\n  const auto ret = read(handle_, buffer, static_cast<unsigned int>(size));\r\n  if (ret == -1) {\r\n    LOG(ERROR) << \"[DEBUG]: Read errno: \" << errno << \" filename: \" << full_path_name_\r\n        << \" size: \" << size;\r\n    LOG(ERROR) << \"Error String:        \" << strerror(errno);\r\n#ifdef _WIN32\r\n    LOG(ERROR) << \"Error String (DOS):  \" << strerror(_doserrno);\r\n#endif \r\n    LOG(ERROR) << \" -- Please screen capture this and attach to a bug here: \" << std::endl;\r\n    LOG(ERROR) << \"https://github.com/wwivbbs/wwiv/issues\" << std::endl;\r\n  }\r\n  return ret;\r\n}\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nFile::size_type File::Write(const void* buffer, File::size_type size) {\r\n  const auto r = write(handle_, buffer, static_cast<unsigned int>(size));\r\n  if (r == -1) {\r\n    LOG(ERROR) << \"[DEBUG: Write errno: \" << errno << \" filename: \" << full_path_name_\r\n        << \" size: \" << size;\r\n    LOG(ERROR) << \"Error String:        \" << strerror(errno);\r\n#ifdef _WIN32\r\n    LOG(ERROR) << \"Error String (DOS):  \" << strerror(_doserrno);\r\n#endif \r\n    LOG(ERROR) << \" -- Please screen capture this and attach to a bug here: \" << std::endl;\r\n    LOG(ERROR) << \"https://github.com/wwivbbs/wwiv/issues\" << std::endl;\r\n  }\r\n  return r;\r\n}\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nFile::size_type File::Seek(size_type offset, Whence whence) {\r\n  CHECK(File::IsFileHandleValid(handle_));\r\n  CHECK(whence == File::Whence::begin || whence == File::Whence::current ||\r\n      whence == File::Whence::end);\r\n\r\n  return static_cast<size_type>(lseek(handle_, static_cast<long>(offset), static_cast<int>(whence)));\r\n}\r\n\r\nFile::size_type File::current_position() const { return lseek(handle_, 0, SEEK_CUR); }\r\n\r\nbool File::Exists() const noexcept {\r\n  std::error_code ec;\r\n  return exists(full_path_name_, ec);\r\n}\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nbool File::set_length(size_type l) {\r\n  if (IsOpen()) {\r\n#if defined (_WIN32) \r\n    return _chsize_s(handle_, l) == 0;\r\n#else\r\n    return ftruncate(handle_, l) == 0;\r\n#endif\r\n  }\r\n\r\n  std::error_code ec;\r\n  if (resize_file(full_path_name_, l, ec); ec.value() != 0) {\r\n    LOG(WARNING) << \"Errror on resize_file: '\" << full_path_name_ << \"': \" << ec.value() << \"; \"\r\n                 << ec.message() << \"; open: \" << IsOpen();\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n\r\n// static\r\nbool File::is_directory(const std::filesystem::path& path) noexcept {\r\n  std::error_code ec;\r\n  return std::filesystem::is_directory(path, ec);\r\n}\r\n\r\nFile::size_type File::length() const noexcept {\r\n  std::error_code ec;\r\n  const auto sz = static_cast<size_type>(file_size(full_path_name_, ec));\r\n  if (ec.value() != 0) {\r\n    return 0;\r\n  }\r\n  return sz;\r\n}\r\n\r\ntime_t File::last_write_time() const { return last_write_time(full_path_name_); }\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Static functions\r\n\r\n\r\n// static\r\ntime_t File::creation_time(const std::filesystem::path& path) {\r\n  const auto p = path.string();\r\n  // Stick with calling stat vs. filesystem:last_write_time until C++20 since\r\n  // C++20 will allow portable output\r\n  struct stat buf {};\r\n  return stat(p.c_str(), &buf) == -1 ? 0 : buf.st_ctime;\r\n}\r\n\r\n// static\r\ntime_t File::last_write_time(const std::filesystem::path& path) {\r\n  const auto p = path.string();\r\n  // Stick with calling stat vs. filesystem:last_write_time until C++20 since\r\n  // C++20 will allow portable output\r\n  struct stat buf {};\r\n  return stat(p.c_str(), &buf) == -1 ? 0 : buf.st_mtime;\r\n}\r\n\r\nbool File::Rename(const std::filesystem::path& o, const std::filesystem::path& n) {\r\n  if (o == n) {\r\n    // Nothing to do.\r\n    return true;\r\n  }\r\n  std::error_code ec{};\r\n  std::filesystem::rename(o, n, ec);\r\n  return ec.value() == 0;\r\n}\r\n\r\nbool File::Remove(const std::filesystem::path& path, bool force) {\r\n  if (!Exists(path)) {\r\n    // Don't try to delete a file that doesn't exist.\r\n    return true;\r\n  }\r\n\r\n  if (force) {\r\n    // Reset permissions to read/write, some apps set funky permissions\r\n    // that keep unlink from working.\r\n    SetFilePermissions(path, permReadWrite);\r\n  }\r\n  std::error_code ec;\r\n  const auto result = std::filesystem::remove(path, ec);\r\n  if (!result) {\r\n    LOG(ERROR) << \"File::Remove failed: \" << path.string() << \"; error code: \" << ec.value() << \"; msg: \" << ec.message();\r\n  }\r\n  return result;\r\n}\r\n\r\nbool File::Exists(const std::filesystem::path& p) {\r\n  if (p.empty()) {\r\n    // An empty filename can not exist.\r\n    // The question is should we assert here?\r\n    return false;\r\n  }\r\n\r\n  std::error_code ec;\r\n  return exists(p, ec);\r\n}\r\n\r\n// static\r\nbool File::ExistsWildcard(const std::filesystem::path& wildcard) {\r\n  WFindFile fnd;\r\n  return fnd.open(wildcard, WFindFileTypeMask::WFINDFILE_ANY);\r\n}\r\n\r\nbool File::SetFilePermissions(const std::filesystem::path& path, int perm) {\r\n  CHECK(!path.empty());\r\n  return chmod(path.string().c_str(), perm) == 0;\r\n}\r\n\r\n// static\r\nbool File::IsFileHandleValid(int handle) noexcept { return handle != invalid_handle; }\r\n\r\n// static\r\nstd::string File::EnsureTrailingSlash(const std::filesystem::path& path) {\r\n  if (path.empty()) {\r\n    return {};\r\n  }\r\n  auto newpath{path.string()};\r\n  if (newpath.back() == pathSeparatorChar) {\r\n    return newpath;\r\n  }\r\n  newpath.push_back(pathSeparatorChar);\r\n  return newpath;\r\n}\r\n\r\n// static\r\npath File::current_directory() {\r\n  std::error_code ec;\r\n  return current_path(ec);\r\n}\r\n\r\n// static\r\nbool File::set_current_directory(const std::filesystem::path& dir) {\r\n  std::error_code ec;\r\n  current_path(dir, ec);\r\n  return ec.value() == 0;\r\n}\r\n\r\n// static\r\nstd::string File::FixPathSeparators(const std::string& path) {\r\n  std::filesystem::path p{path};\r\n  return p.make_preferred().string();\r\n}\r\n\r\n// static\r\nbool File::is_absolute(const std::filesystem::path& p) {\r\n#ifdef __OS2__\r\n  if (!p.empty()) {\r\n    const auto s = p.string();\r\n    if (s.length() >= 3) {\r\n      // Maybe X:\\\\ or X://\r\n      const auto s1 = s.at(1);\r\n      const auto s2 = s.at(2);\r\n      if (s1 == ':' && (s2 == '/' || s2 == '\\\\')) {\r\n\treturn true;\r\n      }\r\n    }\r\n    const auto s0 = s.front();\r\n    if (s0 == '/' || s0 == '\\\\') {\r\n      return true;\r\n    }\r\n  }\r\n#endif\r\n\r\n  return p.is_absolute();\r\n}\r\n\r\n// static\r\nstd::filesystem::path File::absolute(const std::filesystem::path& p) {\r\n#ifdef __OS2__\r\n  if (is_absolute(p)) {\r\n    return p;\r\n  }\r\n#endif\r\n  return std::filesystem::absolute(p);\r\n}\r\n\r\n// static\r\npath File::absolute(const std::filesystem::path& base, const std::filesystem::path& relative) {\r\n  if (is_absolute(relative)) {\r\n    return relative;\r\n  }\r\n  return FilePath(base, relative);\r\n}\r\n\r\n// static\r\nbool File::mkdir(const std::filesystem::path& p) {\r\n  std::error_code ec;\r\n  if (exists(p, ec)) {\r\n    return true;\r\n  }\r\n\r\n  if (create_directory(p, ec)) {\r\n    return true;\r\n  }\r\n  return ec.value() == 0;\r\n}\r\n\r\n// static\r\nbool File::mkdirs(const std::filesystem::path& p) {\r\n  std::error_code ec;\r\n  if (exists(p, ec)) {\r\n    return true;\r\n  }\r\n  if (create_directories(p, ec)) {\r\n    return true;\r\n  }\r\n  return ec.value() == 0;\r\n}\r\n\r\nstd::ostream& operator<<(std::ostream& os, const File& file) {\r\n  os << file.full_pathname();\r\n  return os;\r\n}\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nbool File::set_last_write_time(time_t last_write_time) noexcept {\r\n  return File::set_last_write_time(full_path_name_, last_write_time);\r\n}\r\n\r\n// static \r\nbool File::set_last_write_time(const std::filesystem::path& path,\r\n  time_t last_write_time) noexcept {\r\n  // Stick with calling utime vs. filesystem:last_write_time until C++20 since\r\n  // C++20 will allow portable output\r\n\r\n  // ReSharper disable once CppInitializedValueIsAlwaysRewritten\r\n  struct utimbuf ut {};\r\n  ut.actime = ut.modtime = last_write_time;\r\n  return utime(path.string().c_str(), &ut) != -1;\r\n}\r\n\r\nstd::unique_ptr<FileLock> File::lock(FileLockType lock_type) {\r\n#ifdef _WIN32\r\n  auto* h = reinterpret_cast<HANDLE>(_get_osfhandle(handle_));\r\n  OVERLAPPED overlapped{};\r\n  DWORD dwLockType = 0;\r\n  if (lock_type == FileLockType::write_lock) {\r\n    dwLockType = LOCKFILE_EXCLUSIVE_LOCK;\r\n  }\r\n  if (!::LockFileEx(h, dwLockType, 0, MAXDWORD, MAXDWORD, &overlapped)) {\r\n    LOG(ERROR) << \"Error Locking file: \" << full_path_name_;\r\n  }\r\n#else\r\n\r\n  // TODO: unlock here\r\n\r\n#endif // _WIN32\r\n  return std::make_unique<FileLock>(handle_, full_path_name_.string(), lock_type);\r\n}\r\n\r\nstd::string File::full_pathname() const noexcept {\r\n  try {\r\n    return full_path_name_.string();\r\n  } catch (const std::exception& e) {\r\n    LOG(ERROR) << \"Exception in File::full_pathname: \" << e.what();\r\n    DLOG(FATAL) << \"Exception in File::full_pathname: \" << e.what();\r\n  }\r\n  return {};\r\n}\r\n\r\nbool File::Copy(const std::filesystem::path& from, const std::filesystem::path& to) {\r\n  std::error_code ec;\r\n  copy_file(from, to, copy_options::overwrite_existing, ec);\r\n  return ec.value() == 0;\r\n}\r\n\r\nbool File::Move(const std::filesystem::path& from, const std::filesystem::path& to) {\r\n  return Rename(from, to);\r\n}\r\n\r\n// static\r\nstd::filesystem::path File::canonical(const std::filesystem::path& path) {\r\n#if defined(__OS2__) \r\n  //TODO(rushfan): Hack until std::filesystem is fixed on OS/2\r\n  {\r\n    char buf[4000];\r\n    char* p = _realrealpath(path.c_str(), buf, sizeof(buf));\r\n    if (p != nullptr) {\r\n      return std::filesystem::path(FixPathSeparators(p));\r\n    }\r\n  }\r\n#endif \r\n  std::error_code ec;\r\n  if (auto res = std::filesystem::canonical(path, ec).string(); ec.value() == 0) {\r\n    return res;\r\n  }\r\n  // We can't make this canonical, so try to make it absolute instead.\r\n  return absolute(path);\r\n}\r\n\r\nlong File::freespace_for_path(const std::filesystem::path& p) {\r\n  std::error_code ec;\r\n  const auto devi = space(p, ec);\r\n  if (ec.value() == EOVERFLOW) {\r\n    // Hack for really large partitions that seems to return EOVERFLOW on some linux.\r\n    // https://bugzilla.redhat.com/show_bug.cgi?id=1758001 is likely the bug.\r\n    return 1024 * 1024;\r\n  }\r\n  if (ec.value() != 0) {\r\n    return 0;\r\n  }\r\n  return static_cast<long>(devi.available / 1024);\r\n}\r\n\r\n} // namespace wwiv\r\n"
  },
  {
    "path": "core/file.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services            */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n\r\n#ifndef INCLUDED_CORE_FILE_H\r\n#define INCLUDED_CORE_FILE_H\r\n\r\n#include \"core/file_lock.h\"\r\n#include \"core/wwivport.h\"\r\n#include <ctime>\r\n#include <filesystem>\r\n#include <memory>\r\n#include <string>\r\n\r\n#ifndef MAX_PATH\r\n#define MAX_PATH 260\r\n#endif\r\n\r\n#if !defined(_WIN32) && !defined(__OS2__)\r\n#if !defined(O_BINARY)\r\n#define O_BINARY 0\r\n#endif\r\n#if !defined(O_TEXT)\r\n#define O_TEXT 0\r\n#endif\r\n#endif // !_WIN32 && !__OS2__\r\n\r\nnamespace wwiv::core {\r\n\r\n\r\n/**\r\n * Creates a full std::filesystem::path of directory_name + file_name ensuring that any\r\n * path separators are added as needed.\r\n */\r\nstd::filesystem::path FilePath(const std::filesystem::path& directory_name,\r\n                                   const std::filesystem::path& file_name);\r\n\r\n/**\r\n * File: Provides a high level, cross-platform common wrapper for file handling using C++.\r\n *\r\n * Example:\r\n *   File f(\"/opt/wwiv/bbs/config.dat\");\r\n *   if (!f) { LOG(FATAL) << \"config.dat does not exist!\"; }\r\n *   if (!f.Read(config, sizeof(configrec)) { LOG(FATAL) << \"unable to load config.dat\"; }\r\n *   // No need to close f since when f goes out of scope it'll close automatically.\r\n */\r\nclass File final {\r\npublic:\r\n  // Constants\r\n  static const int modeDefault;\r\n  static const int modeUnknown;\r\n  static const int modeAppend;\r\n  static const int modeBinary;\r\n  static const int modeCreateFile;\r\n  static const int modeReadOnly;\r\n  static const int modeReadWrite;\r\n  static const int modeText;\r\n  static const int modeWriteOnly;\r\n  static const int modeTruncate;\r\n  static const int modeExclusive;\r\n\r\n  static const int shareUnknown;\r\n  static const int shareDenyReadWrite;\r\n  static const int shareDenyWrite;\r\n  static const int shareDenyRead;\r\n  static const int shareDenyNone;\r\n\r\n  static const int permReadWrite;\r\n\r\n  enum class Whence : int { begin = SEEK_SET, current = SEEK_CUR, end = SEEK_END };\r\n\r\n  static const int invalid_handle;\r\n\r\n  static const char pathSeparatorChar;\r\n\r\n  // Types.  This should eventually switch to a type supporting\r\n  // Large files.   long is what off_t was.\r\n  using size_type = ssize_t;\r\n\r\n  // Constructor/Destructor\r\n\r\n  /** Constructs a file from a path. */\r\n  explicit File(std::filesystem::path full_path_name);\r\n  /** Destructs File. Closes any open file handles. */\r\n  File(File&& other) noexcept;\r\n  File& operator=(File&& other) noexcept;\r\n\r\n  ~File();\r\n\r\n  // Public Member functions\r\n  bool Open(int nFileMode = modeDefault, int nShareMode = shareUnknown);\r\n  void Close() noexcept;\r\n  [[nodiscard]] bool IsOpen() const noexcept;\r\n\r\n  size_type Read(void* buf, size_type size);\r\n  size_type Write(const void* buffer, size_type count);\r\n\r\n  size_type Write(const std::string& s) { return this->Write(s.data(), s.length()); }\r\n\r\n  size_type Writeln(const void* buffer, size_type count) {\r\n    auto ret = this->Write(buffer, count);\r\n    ret += this->Write(\"\\r\\n\", 2);\r\n    return ret;\r\n  }\r\n\r\n  size_type Writeln(const std::string& s) { return this->Writeln(s.c_str(), s.length()); }\r\n\r\n  [[nodiscard]] size_type length() const noexcept;\r\n  size_type Seek(size_type offset, Whence whence);\r\n  bool set_length(size_type l);\r\n  [[nodiscard]] size_type current_position() const;\r\n\r\n  [[nodiscard]] bool Exists() const noexcept;\r\n\r\n  [[nodiscard]] time_t last_write_time() const;\r\n  bool set_last_write_time(time_t last_write_time) noexcept;\r\n\r\n  std::unique_ptr<FileLock> lock(FileLockType lock_type);\r\n\r\n  /** Returns the file path as a std::string path */\r\n  [[nodiscard]] std::string full_pathname() const noexcept;\r\n\r\n  /** Returns the file path as a std::filesystem path */\r\n  [[nodiscard]] const std::filesystem::path& path() const noexcept { return full_path_name_; }\r\n\r\n  [[nodiscard]] std::string last_error() const noexcept { return error_text_; }\r\n\r\n  // operators\r\n\r\n  /** Returns true if the file is open */\r\n  explicit operator bool() const noexcept { return IsOpen(); }\r\n  friend std::ostream& operator<<(std::ostream& os, const File& f);\r\n\r\n  // static functions\r\n  /**\r\n   * Removes a file or empty directory referred to by path.\r\n   * If force is true, then also reset the permissions to Read/Write before\r\n   * calling delete in case the permissions were read-only.\r\n   */\r\n  static bool Remove(const std::filesystem::path& path, bool force = false);\r\n  static bool Rename(const std::filesystem::path& origFileName,\r\n                     const std::filesystem::path& newFileName);\r\n  [[nodiscard]] static bool Exists(const std::filesystem::path& p);\r\n  [[nodiscard]] static bool ExistsWildcard(const std::filesystem::path& wildCard);\r\n  static bool Copy(const std::filesystem::path& from,\r\n                   const std::filesystem::path& to);\r\n  static bool Move(const std::filesystem::path& from,\r\n                   const std::filesystem::path& to);\r\n\r\n  static bool SetFilePermissions(const std::filesystem::path& path, int perm);\r\n\r\n  [[nodiscard]] static std::string EnsureTrailingSlash(const std::filesystem::path& path);\r\n  [[nodiscard]] static std::filesystem::path current_directory();\r\n  static bool set_current_directory(const std::filesystem::path& dir);\r\n  [[nodiscard]] static std::string FixPathSeparators(const std::string& path);\r\n\r\n  /**\r\n   * Returns true if the path p is in absolute form.\r\n   */\r\n  [[nodiscard]] static bool is_absolute(const std::filesystem::path& p);\r\n\r\n  /**\r\n   * Returns a new path referencing the same path as p.\r\n   */\r\n  [[nodiscard]] static std::filesystem::path absolute(const std::filesystem::path& p);\r\n\r\n  /**\r\n   * Returns a new path referencing the same path as base / relative.\r\n   */\r\n  [[nodiscard]] static std::filesystem::path absolute(const std::filesystem::path& base,\r\n                                                      const std::filesystem::path& relative);\r\n\r\n  // Time the file was created.\r\n  [[nodiscard]] static time_t creation_time(const std::filesystem::path& path);\r\n\r\n  [[nodiscard]] static time_t last_write_time(const std::filesystem::path& path);\r\n  [[nodiscard]] static bool set_last_write_time(const std::filesystem::path& path,\r\n                                                time_t last_write_time) noexcept;\r\n\r\n  /**\r\n   * Returns an canonical absolute path.\r\n   *\r\n   * That means there are no dot or dot-dots or double-slashes in a non-UNC\r\n   * portion of the path.  On POSIX systems, this is congruent with how\r\n   * realpath behaves.\r\n   */\r\n  [[nodiscard]] static std::filesystem::path canonical(const std::filesystem::path& path);\r\n\r\n  /**\r\n   * Creates the directory {path} by creating the leaf most directory.\r\n   *\r\n   * Returns true if the new directory is created.\r\n   * Also returns true if there is nothing to do. This is unlike\r\n   * filesystem::mkdir which returns false if {path} already exists.\r\n   */\r\n  static bool mkdir(const std::filesystem::path& path);\r\n\r\n  /**\r\n   * Creates the directory {path} and all parent directories needed\r\n   * along the way.\r\n   *\r\n   * Returns true if the new directory is created.\r\n   * Also returns true if there is nothing to do. This is unlike\r\n   * filesystem::mkdir which returns false if {path} already exists.\r\n   */\r\n  static bool mkdirs(const std::filesystem::path& path);\r\n\r\n  /**\r\n   * Creates the directory {path} by calling File::mkdir on the\r\n   * full pathname of this file object.\r\n   */\r\n  static bool mkdir(const File& dir) { return mkdir(dir.full_pathname()); }\r\n\r\n  /**\r\n   * Creates the directory {path} by calling File::mkdirs on the\r\n   * full pathname of this file object.\r\n   */\r\n  static bool mkdirs(const File& dir) { return mkdirs(dir.full_pathname()); }\r\n\r\n  /** Returns the number of free space in kilobytes. i.e. 1 = 1024 free bytes. */\r\n  [[nodiscard]] static long freespace_for_path(const std::filesystem::path& p);\r\n  [[nodiscard]] static bool is_directory(const std::filesystem::path& path) noexcept;\r\n\r\n  /** For debugging and testing only */\r\n  [[nodiscard]] int handle() const noexcept { return handle_; }\r\n\r\nprivate:\r\n  // Helper functions\r\n  [[nodiscard]] static bool IsFileHandleValid(int handle) noexcept;\r\n\r\nprivate:\r\n  int handle_{-1};\r\n  std::filesystem::path full_path_name_;\r\n  std::string error_text_;\r\n};\r\n\r\n/** Makes a backup of path using a custom suffix with the time and date */\r\nbool backup_file(const std::filesystem::path& from, int max_backups = 0);\r\n\r\n} // namespace\r\n\r\n#endif\r\n"
  },
  {
    "path": "core/file_lock.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file_lock.h\"\n#ifdef _WIN32\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n#include \"Shlwapi.h\"\n#endif  // _WIN32\n\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include <algorithm>\n#include <string>\n#ifdef _WIN32\n#include <direct.h>\n#include <io.h>\n#else // _WIN32\n#include <sys/file.h>\n#include <unistd.h>\n#include <utime.h>\n#endif // _WIN32\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::os;\n\n\nnamespace wwiv {\nnamespace core {\n\nFileLock::FileLock(int fd, const std::string& filename, FileLockType lock_type)\n  : fd_(fd), filename_(filename), lock_type_(lock_type) {\n}\n\nFileLock::~FileLock() {\n#ifdef _WIN32\n  auto h = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));\n  OVERLAPPED overlapped = {0};\n  if (!UnlockFileEx(h, 0, MAXDWORD, MAXDWORD, &overlapped)) {\n    LOG(ERROR) << \"Error Unlocking file: \" << filename_;\n  }\n#else\n\n  // TODO: unlock here\n\n#endif  // _WIN32\n}\n\n\n} // namespace core\n} // namespace wwiv\n"
  },
  {
    "path": "core/file_lock.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef __INCLUDED_CORE_FILE_LOCK_H__\n#define __INCLUDED_CORE_FILE_LOCK_H__\n\n#include <cstring>\n#include <ctime>\n#include <iostream>\n#include <string>\n#include <sys/types.h>\n\n\nnamespace wwiv {\nnamespace core {\n\nenum class FileLockType {\n  read_lock,\n  write_lock\n};\n\nclass FileLock {\npublic:\n  FileLock(int fd, const std::string& filename, FileLockType lock_type);\n  virtual ~FileLock();\nprivate:\n  int fd_;\n  const std::string filename_;\n  FileLockType lock_type_;\n};\n\n} // namespace core\n} // namespace wwiv\n\n\n#endif // __INCLUDED_CORE_FILE_LOCK_H__\n"
  },
  {
    "path": "core/file_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n\n#include <share.h>\n#include <sys/stat.h>\n\nnamespace wwiv::core {\n\nconst int File::shareDenyReadWrite = SH_DENYRW;\nconst int File::shareDenyWrite = SH_DENYWR;\nconst int File::shareDenyRead = SH_DENYRD;\n  const int File::shareDenyNone = SH_DENYRD; \n  // SH_DENYNO was causing a permission denied error for some strange reason\n// SH_DENYNO;\n\nconst int File::permReadWrite = (S_IREAD | S_IWRITE);\n\nconst char File::pathSeparatorChar = '\\\\';\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/file_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"core/test/wwivtest.h\"\n#include \"fmt/format-inl.h\"\n#include \"gtest/gtest.h\"\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n\nclass FileTestDataTest : public wwiv::core::test::TestDataTest {};\n\n\n// Real File Tests\n\nTEST_F(FileTestDataTest, Length_RealFile) {\n  wwiv::core::test::FileHelper helper;\n  auto path = wwiv::core::FilePath(wwiv::core::test::FileHelper::TestData(), \"len.txt\");\n  File file(path);\n  ASSERT_EQ(11, file.length());\n}\n\n// Fake File Tests\nTEST(FileTest, DoesNotExist) {\n  wwiv::core::test::FileHelper file;\n  auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  const auto fn = FilePath(tmp, \"doesnotexist\");\n  ASSERT_FALSE(File::Exists(fn));\n}\n\nTEST(FileTest, DoesNotExist_Static) {\n  wwiv::core::test::FileHelper file;\n  auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  File dne(FilePath(tmp, \"doesnotexist\"));\n  ASSERT_FALSE(File::Exists(dne.path()));\n}\n\nTEST(FileTest, Exists) {\n  wwiv::core::test::FileHelper file;\n  const auto tmp{file.TempDir()};\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  const auto f{FilePath(tmp, \"newdir\")};\n  ASSERT_TRUE(File::Exists(f)) << f;\n}\n\nTEST(FileTest, ExistsWildCard) {\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(\"msg00000.001\", \"msg00000.001\");\n  ASSERT_TRUE(File::Exists(path));\n\n  auto wildcard_path = FilePath(helper.TempDir(), \"msg*\");\n  ASSERT_TRUE(File::ExistsWildcard(wildcard_path)) << path << \"; w: \" << wildcard_path;\n\n  wildcard_path = FilePath(helper.TempDir(), \"msg*.*\");\n  EXPECT_TRUE(File::ExistsWildcard(wildcard_path)) << path << \"; w: \" << wildcard_path;\n\n  wildcard_path = FilePath(helper.TempDir(), \"msg*.???\");\n  EXPECT_TRUE(File::ExistsWildcard(wildcard_path)) << path << \"; w: \" << wildcard_path;\n}\n\nTEST(FileTest, ExistsWildCard_Extension) {\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(\"msg00000.001\", \"msg00000.001\");\n  ASSERT_TRUE(File::Exists(path));\n\n  auto wildcard_path = FilePath(helper.TempDir(), \"msg*.001\").string();\n  ASSERT_TRUE(File::ExistsWildcard(wildcard_path)) << path << \"; w: \" << wildcard_path;\n\n  wildcard_path = FilePath(helper.TempDir(), \"msg*.??1\").string();\n  ASSERT_TRUE(File::ExistsWildcard(wildcard_path)) << path << \"; w: \" << wildcard_path;\n}\n\nTEST(FileTest, Exists_Static) {\n  wwiv::core::test::FileHelper file{};\n  const auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  const File dne(FilePath(tmp, \"newdir\"));\n  ASSERT_TRUE(File::Exists(dne.path())) << dne.path();\n}\n\nTEST(FileTest, Exists_TrailingSlash) {\n  wwiv::core::test::FileHelper file;\n  const auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  File dne(FilePath(tmp, \"newdir\"));\n  const auto path = File::EnsureTrailingSlash(dne.full_pathname());\n  ASSERT_TRUE(File::Exists(path)) << path;\n  ASSERT_EQ(File::pathSeparatorChar, path.back());\n}\n\nTEST(FileTest, Length_Open) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  ASSERT_EQ(static_cast<long>(kHelloWorld.size()), file.length());\n}\n\nTEST(FileTest, Length_NotOpen) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_EQ(static_cast<long>(kHelloWorld.size()), file.length());\n}\n\nTEST(FileTest, IsDirectory_NotOpen) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  std::error_code ec;\n  ASSERT_FALSE(std::filesystem::is_directory(path, ec));\n  ASSERT_TRUE(std::filesystem::is_regular_file(path, ec));\n}\n\nTEST(FileTest, IsDirectory_Open) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  std::error_code ec;\n  ASSERT_FALSE(std::filesystem::is_directory(path, ec));\n  ASSERT_TRUE(std::filesystem::is_regular_file(path, ec));\n}\n\n\nTEST(FileTest, CreationTime_NotOpen) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  const auto now = time(nullptr);\n  const auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  ASSERT_LE(now, File::creation_time(path));\n}\n\nTEST(FileTest, CreationTime_Open) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  time_t now = time(nullptr);\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  ASSERT_LE(now, File::creation_time(path));\n}\n\n\nTEST(FileTest, LastWriteTime_NotOpen) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  const auto now = time(nullptr);\n  const auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_LE(now, file.last_write_time());\n}\n\nTEST(FileTest, LastWriteTime_Open) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  time_t now = time(nullptr);\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  ASSERT_LE(now, file.last_write_time());\n}\n\nTEST(FileTest, Read) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  char buf[255];\n  ASSERT_EQ(static_cast<int>(kHelloWorld.length()), file.Read(buf, kHelloWorld.length()));\n  buf[11] = 0;\n  ASSERT_STREQ(kHelloWorld.c_str(), buf);\n}\n\nTEST(FileTest, GetName) {\n  static const std::string kFileName = test_info_->name();\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(kFileName, \"Hello World\");\n  File file{path};\n  ASSERT_EQ(kFileName, file.path().filename().string());\n}\n\nTEST(FileTest, EnsureTrailingSlash) {\n  const auto single_slash = fmt::format(\"temp{}\", File::pathSeparatorChar);\n  const auto double_slash =\n      fmt::format(\"temp{}{}\", File::pathSeparatorChar, File::pathSeparatorChar);\n  const std::string no_slash = \"temp\";\n\n  EXPECT_EQ(single_slash, File::EnsureTrailingSlash(single_slash));\n\n  EXPECT_EQ(double_slash, File::EnsureTrailingSlash(double_slash));\n\n  EXPECT_EQ(single_slash, File::EnsureTrailingSlash(no_slash));\n}\n\nTEST(FileTest, CurrentDirectory) {\n  char buf[MAX_PATH];\n  char* expected = getcwd(buf, MAX_PATH);\n  const auto actual = File::current_directory().string();\n  EXPECT_STREQ(expected, actual.c_str());\n}\n\nTEST(FileTest, SetCurrentDirectory) {\n  char buf[MAX_PATH];\n  char* expected = getcwd(buf, MAX_PATH);\n  const auto original_dir = File::current_directory().string();\n  ASSERT_STREQ(expected, original_dir.c_str());\n\n  wwiv::core::test::FileHelper helper;\n  File::set_current_directory(helper.TempDir());\n  EXPECT_EQ(helper.TempDir(), File::current_directory().string());\n\n  File::set_current_directory(original_dir);\n}\n\nTEST(FileTest, MakeAbsolutePath_Relative) {\n  static const std::string kFileName{test_info_->name()};\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(kFileName, \"Hello World\");\n\n  const auto relative = File::absolute(helper.TempDir().string(), kFileName);\n  EXPECT_EQ(path, relative);\n}\n\nTEST(FileTest, MakeAbsolutePath_AlreadyAbsolute) {\n  static const std::string kFileName = test_info_->name();\n  wwiv::core::test::FileHelper helper;\n  const auto expected = helper.CreateTempFile(kFileName, \"Hello World\");\n\n  const auto path = File::absolute(helper.TempDir().string(), expected.string());\n  EXPECT_EQ(expected, path);\n}\n\nTEST(FileTest, MakeAbsolutePath_AlreadyAbsolute_Returning) {\n  static const std::string kFileName = test_info_->name();\n  wwiv::core::test::FileHelper helper;\n  const auto expected = helper.CreateTempFile(kFileName, \"Hello World\");\n\n  const auto path = File::absolute(helper.TempDir().string(), expected.string());\n  EXPECT_EQ(expected, path);\n}\n\nTEST(FileTest, RealPath_Same) {\n  static const std::string kFileName = test_info_->name();\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(kFileName, \"Hello World\");\n\n  const auto c = File::canonical(path);\n  EXPECT_EQ(path, c.string());\n}\n\nTEST(FileTest, RealPath_Different) {\n  static const std::string kFileName{test_info_->name()};\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(kFileName, \"Hello World\");\n\n  // Add an extra ./ into the path.\n  const auto suffix = FilePath(\".\", kFileName).string();\n  const auto full = FilePath(helper.TempDir(), suffix);\n  const auto canonical = File::canonical(full);\n  EXPECT_EQ(path, canonical) << \"Canonical: \" << canonical;\n}\n\nTEST(FileTest, mkdir) {\n  const wwiv::core::test::FileHelper helper{};\n  const auto path = FilePath(helper.TempDir(), \"a\");\n  const auto l = FilePath(\"b\", \"c\").string();\n\n  const auto path_missing_middle = FilePath(path, l);\n  ASSERT_FALSE(File::Exists(path));\n\n  ASSERT_TRUE(File::mkdir(path));\n  ASSERT_TRUE(File::mkdir(path));                 // 2nd time should still return true.\n  EXPECT_FALSE(File::mkdir(path_missing_middle)); // Can't create missing path elements.\n\n  ASSERT_TRUE(File::Exists(path));\n}\n\nTEST(FileTest, mkdirs) {\n  wwiv::core::test::FileHelper helper;\n  const auto f = FilePath(helper.TempDir(), \"a\");\n  const auto l = FilePath(\"b\", \"c\");\n  const auto path = FilePath(f, l.string());\n  ASSERT_FALSE(File::Exists(path));\n\n  ASSERT_TRUE(File::mkdirs(path));\n  ASSERT_TRUE(File::mkdirs(path));\n\n  ASSERT_TRUE(File::Exists(path));\n}\n\nTEST(FileTest, Stream) {\n  wwiv::core::test::FileHelper file{};\n  File f(FilePath(file.TempDir(), \"newdir\"));\n  std::stringstream s;\n  s << f;\n  ASSERT_EQ(f.full_pathname(), s.str());\n}\n\nTEST(FileTest, IsOpen_Open) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n  EXPECT_TRUE(file.IsOpen());\n  EXPECT_TRUE(static_cast<bool>(file));\n}\n\nTEST(FileTest, IsOpen_NotOpen) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  File file(path.concat(\"DNE\"));\n  EXPECT_FALSE(file.IsOpen());\n  EXPECT_FALSE(file);\n}\n\nTEST(FileTest, Seek) {\n  static const std::string kContents = \"0123456789\";\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(test_info_->name(), kContents);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n\n  EXPECT_EQ(0, file.Seek(0, File::Whence::begin));\n  char c{};\n  file.Read(&c, 1);\n  EXPECT_EQ('0', c);\n\n  EXPECT_EQ(3, file.Seek(2, File::Whence::current));\n  file.Read(&c, 1);\n  EXPECT_EQ('3', c);\n\n  EXPECT_EQ(static_cast<File::size_type>(kContents.size()), file.Seek(0, File::Whence::end));\n  EXPECT_EQ(0, file.Read(&c, 1));\n}\n\nTEST(FileTest, CurrentPosition) {\n  static const std::string kContents = \"0123456789\";\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(test_info_->name(), kContents);\n  File file(path);\n  ASSERT_TRUE(file.Open(File::modeBinary | File::modeReadOnly));\n\n  EXPECT_EQ(3, file.Seek(3, File::Whence::begin));\n  EXPECT_EQ(3, file.current_position());\n\n  EXPECT_EQ(static_cast<int>(kContents.size()), file.Seek(0, File::Whence::end));\n  EXPECT_EQ(static_cast<int>(kContents.size()), file.current_position());\n}\n\nTEST(FileTest, FsCopyFile) {\n  wwiv::core::test::FileHelper file;\n  auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  auto from = FilePath(tmp, \"f1\");\n  File f(from);\n  f.Open(File::modeWriteOnly | File::modeCreateFile);\n  f.Write(\"ok\");\n  f.Close();\n  ASSERT_TRUE(File::Exists(f.path())) << f.full_pathname();\n\n  auto to = FilePath(tmp, \"f2\");\n  std::error_code ec;\n  EXPECT_FALSE(File::Exists(to.string()));\n  copy_file(from, to, std::filesystem::copy_options::overwrite_existing, ec);\n  EXPECT_TRUE(File::Exists(to.string()));\n}\n\nTEST(FileTest, CopyFile) {\n  wwiv::core::test::FileHelper file;\n  auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  auto f1 = FilePath(tmp, \"f1\");\n  File f(f1);\n  f.Open(File::modeWriteOnly | File::modeCreateFile);\n  f.Write(\"ok\");\n  f.Close();\n  ASSERT_TRUE(File::Exists(f.path())) << f.full_pathname();\n\n  auto f2 = FilePath(tmp, \"f2\");\n  EXPECT_FALSE(File::Exists(f2));\n  File::Copy(f1, f2);\n  EXPECT_TRUE(File::Exists(f2));\n}\n\nTEST(FileTest, MoveFile) {\n  wwiv::core::test::FileHelper file;\n  auto tmp = file.TempDir();\n  GTEST_ASSERT_NE(\"\", tmp);\n  ASSERT_TRUE(file.Mkdir(\"newdir\"));\n  auto f1 = FilePath(tmp, \"f1\");\n  File f(f1);\n  f.Open(File::modeWriteOnly | File::modeCreateFile);\n  f.Write(\"ok\");\n  f.Close();\n  ASSERT_TRUE(File::Exists(f.path())) << f.full_pathname();\n\n  auto f2 = FilePath(tmp, \"f2\");\n  EXPECT_TRUE(File::Exists(f1)) << f1;\n  EXPECT_FALSE(File::Exists(f2));\n  File::Move(f1, f2);\n  EXPECT_TRUE(File::Exists(f2));\n  EXPECT_FALSE(File::Exists(f1));\n}\n\nTEST(FileTest, Remove_String) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  ASSERT_TRUE(File::Exists(path));\n  File::Remove(path.string());\n  EXPECT_FALSE(File::Exists(path));\n}\n\nTEST(FileTest, Remove_Path) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  const auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n  ASSERT_TRUE(File::Exists(path));\n  File::Remove(path);\n  EXPECT_FALSE(File::Exists(path));\n}\n\nTEST(FileTest, Free) {\n  const wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n\n  const auto fs = File::freespace_for_path(tmp);\n  EXPECT_GT(fs, 0);\n}\n\nTEST(FileTest, Move_Ctor) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n\n  File f(path);\n  ASSERT_TRUE(f.Open(File::modeReadOnly));\n  ASSERT_TRUE(f.IsOpen());\n  ASSERT_NE(-1, f.handle());\n\n  auto f2(std::move(f));\n  ASSERT_TRUE(f2.IsOpen());\n  ASSERT_NE(-1, f2.handle());\n\n  ASSERT_FALSE(f.IsOpen());  // NOLINT\n  ASSERT_EQ(-1, f.handle());\n}\n\nTEST(FileTest, Move_Operator) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper helper;\n  auto path = helper.CreateTempFile(test_info_->name(), kHelloWorld);\n\n  File f(path);\n  ASSERT_TRUE(f.Open(File::modeReadOnly));\n  ASSERT_TRUE(f.IsOpen());\n  ASSERT_NE(-1, f.handle());\n\n  File f2(path);\n  f2 = std::move(f);\n  ASSERT_TRUE(f2.IsOpen());\n  ASSERT_NE(-1, f2.handle());\n\n  ASSERT_FALSE(f.IsOpen());  // NOLINT\n  ASSERT_EQ(-1, f.handle());\n}\n\nTEST(FileSystemTest, Empty) {\n  const std::filesystem::path p{\"\"};\n  ASSERT_TRUE(p.empty());\n}\n\nTEST(FileSystemTest, Path_IsDir) {\n  const wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n  auto p{tmp};\n  std::cerr << p << std::endl;\n  ASSERT_TRUE(std::filesystem::is_directory(p));\n}\n\nTEST(FileSystemTest, Path_WithoutDir) {\n  std::filesystem::path p{\"hello.txt\"};\n  EXPECT_FALSE(wwiv::stl::contains(p.string(), File::pathSeparatorChar)) << \"p: \" << p.string();\n}\n\nTEST(FileSystemTest, Path_WithWildCard) {\n  std::filesystem::path p{\"hello.*\"};\n  EXPECT_FALSE(wwiv::stl::contains(p.string(), File::pathSeparatorChar)) << \"p: \" << p.string();\n  EXPECT_TRUE(wwiv::strings::ends_with(p.string(), \"hello.*\")) << \"p: \" << p.string();\n}\n\nTEST(FileSystemTest, PathFilePath_Nested) {\n  auto p = FilePath(\"foo\", FilePath(\"bar\", \"baz\"));\n  auto expected = StrCat(\"foo\", File::pathSeparatorChar, \"bar\", File::pathSeparatorChar, \"baz\");\n  EXPECT_EQ(expected, p.string());\n}\n\n\n"
  },
  {
    "path": "core/file_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n\n#include <fcntl.h>\n#include <sys/stat.h>\n\nnamespace wwiv {\nnamespace core {\n\nconst int File::shareDenyReadWrite = S_IWRITE;\nconst int File::shareDenyWrite = 0;\nconst int File::shareDenyRead = S_IREAD;\nconst int File::shareDenyNone = 0;\n\nconst int File::permReadWrite = O_RDWR;\n\nconst char File::pathSeparatorChar = '/';\n\n}\n}\n"
  },
  {
    "path": "core/file_win32.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n\n#include <share.h>\n\nnamespace wwiv::core {\n\nconst int File::shareDenyReadWrite = SH_DENYRW;\nconst int File::shareDenyWrite = SH_DENYWR;\nconst int File::shareDenyRead = SH_DENYRD;\nconst int File::shareDenyNone = SH_DENYNO;\n\nconst int File::permReadWrite = (_S_IREAD | _S_IWRITE);\n\nconst char File::pathSeparatorChar = '\\\\';\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/findfiles.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/findfiles.h\"\n\n#include <iostream>\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/wfndfile.h\"\n\nnamespace wwiv::core {\n\nstatic WFindFileTypeMask FindFilesTypeToInt(FindFiles::FindFilesType type) {\n  switch (type) {\n  case FindFiles::FindFilesType::any:\n    return WFindFileTypeMask::WFINDFILE_ANY;\n  case FindFiles::FindFilesType::directories:\n    return WFindFileTypeMask::WFINDFILE_DIRS;\n  case FindFiles::FindFilesType::files:\n    return WFindFileTypeMask::WFINDFILE_FILES;\n  }\n  LOG(FATAL) << \"Invalid FindFilesType: \" << static_cast<int>(type);\n  // Make Compiler happy\n  return WFindFileTypeMask::WFINDFILE_ANY;\n}\n\nFindFiles::FindFiles(const std::filesystem::path& mask, const FindFilesType type, WinNameType name_type) {\n  WFindFile fnd;\n  if (name_type == WinNameType::long_name) {\n    fnd.set_use_long_filenames(true);\n  }\n  if (!fnd.open(mask, FindFilesTypeToInt(type))) {\n    VLOG(3) << \"Unable to open mask: \" << mask;\n    return;\n  }\n  do {\n    // file_mask_ doesn't work on windows... sigh.\n    // good thing WFindFiles will go away.\n    if (fnd.IsDirectory() && type == FindFilesType::files) {\n      continue;\n    }\n    if (fnd.IsFile() && type == FindFilesType::directories) {\n      continue;\n    }\n    std::string fn = fnd.GetFileName();\n    if (fnd.IsDirectory()) {\n      if (fn == \".\" || fn == \"..\") {\n        // Skip . and .. directories.\n        continue;\n      }\n    }\n    entries_.emplace(fn, fnd.GetFileSize());\n  }\n  while (fnd.next());\n}\n\nFindFiles::FindFiles(const std::filesystem::path& mask, FindFilesType type)\n: FindFiles(mask, type, WinNameType::short_name) {}\n\nstd::optional<std::filesystem::path> FindFile(const std::filesystem::path& candidate) {\n  FindFiles ff(candidate, FindFiles::FindFilesType::files);\n  if (ff.empty()) {\n    return std::nullopt;\n  }\n  auto path = candidate;\n  return { path.replace_filename(ff.begin()->name) };\n}\n\n\n}\n"
  },
  {
    "path": "core/findfiles.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_CORE_FINDFILES_H\n#define INCLUDED_CORE_FINDFILES_H\n\n#include <filesystem>\n#include <optional>\n#include <set>\n#include <string>\n#include <utility>\n\nnamespace wwiv::core {\n\nclass FileEntry {\npublic:\n  FileEntry(std::string n, long s) : name(std::move(n)), size(s) {}\n\n  bool operator<(const FileEntry& other) const {\n    return name < other.name;\n  }\n  bool operator == (const FileEntry& other) const {\n    return name == other.name;\n  }\n  const std::string name;\n  long size;\n  \n};\n\nclass FindFiles {\npublic:\n  typedef std::set<FileEntry>::iterator iterator;\n  typedef std::set<FileEntry>::const_iterator const_iterator;\n  typedef std::set<FileEntry>::size_type size_type;\n\n  enum class FindFilesType { directories, files, any };\n  enum class WinNameType { short_name, long_name };\n\n  FindFiles(const std::filesystem::path& mask, FindFilesType type, WinNameType name_type);\n  FindFiles(const std::filesystem::path& mask, FindFilesType type);\n\n  [[nodiscard]] iterator begin() { return entries_.begin(); }\n  [[nodiscard]] const_iterator begin() const { return entries_.begin(); }\n  [[nodiscard]] const_iterator cbegin() const { return entries_.cbegin(); }\n  [[nodiscard]] iterator end() { return entries_.end(); }\n  [[nodiscard]] const_iterator end() const { return entries_.end(); }\n  [[nodiscard]] const_iterator cend() const { return entries_.cend(); }\n  [[nodiscard]] bool empty() const { return entries_.empty(); }\n  [[nodiscard]] size_type size() const noexcept { return entries_.size(); }\n\nprivate:\n  std::set<FileEntry> entries_;\n  \n};\n\nstd::optional<std::filesystem::path> FindFile(const std::filesystem::path& candidate);\n\n}\n\n\n#endif\n"
  },
  {
    "path": "core/findfiles_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"gtest/gtest.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nTEST(FindFiles, Suffix) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"msg00000.001\", \"\");\n  FindFiles ff(FilePath(helper.TempDir(), \"msg*\"), FindFiles::FindFilesType::any);\n  auto f = ff.begin();\n  EXPECT_EQ(\"msg00000.001\", f->name);\n  ++f;\n  EXPECT_EQ(f, ff.end());\n}\n\nTEST(FindFiles, Prefix) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"msg00000.001\", \"\");\n  FindFiles ff(FilePath(helper.TempDir(), \"*001\"), FindFiles::FindFilesType::files);\n  auto f = ff.begin();\n  EXPECT_EQ(\"msg00000.001\", f->name);\n  ++f;\n  EXPECT_EQ(f, ff.end());\n}\n\nTEST(FindFiles, SingleCharSuffix) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"msg00000.001\", \"\");\n  FindFiles ff(FilePath(helper.TempDir(), \"msg00000.00?\"), FindFiles::FindFilesType::files);\n  auto f = ff.begin();\n  EXPECT_EQ(\"msg00000.001\", f->name);\n  ++f;\n  EXPECT_EQ(f, ff.end());\n}\n\nTEST(FindFiles, SingleCharPrefix) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"msg00000.001\", \"\");\n  FindFiles ff(FilePath(helper.TempDir(), \"?sg00000.001\"), FindFiles::FindFilesType::files);\n  auto f = ff.begin();\n  EXPECT_EQ(\"msg00000.001\", f->name);\n  ++f;\n  EXPECT_EQ(f, ff.end());\n}\n\nTEST(FindFiles, SingleCharExtensionPrefix) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"msg00000.001\", \"\");\n  FindFiles ff(FilePath(helper.TempDir(), \"msg00000.?01\"), FindFiles::FindFilesType::files);\n  auto f = ff.begin();\n  EXPECT_EQ(\"msg00000.001\", f->name);\n  ++f;\n  EXPECT_EQ(f, ff.end());\n}\n\nTEST(FindFileTest, Smoke) {\n  wwiv::core::test::FileHelper helper;\n  helper.CreateTempFile(\"FOO\", \"\");\n  EXPECT_TRUE(FindFile(FilePath(helper.TempDir(), \"FOO\")));\n  EXPECT_TRUE(FindFile(FilePath(helper.TempDir(), \"foo\")));\n  EXPECT_FALSE(FindFile(FilePath(helper.TempDir(), \"bad\")));\n}\n"
  },
  {
    "path": "core/graphs.cpp",
    "content": "// From http://rosettacode.org/wiki/Dijkstra%27s_algorithm\n// Also http://stackoverflow.com/a/22566583/1270019\n#include \"core/graphs.h\"\n\n#include <cmath>\n#include <iostream>\n#include <limits>\n#include <list>\n#include <set>\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::graphs {\n\nstatic constexpr uint16_t NO_NODE = 0;\nstatic constexpr float max_cost = std::numeric_limits<float>::infinity();\n\nGraph::Graph(uint16_t node, uint16_t max_size)\n  : node_(node), adjacency_list_(max_size) {\n  cost_.clear();\n  cost_.resize(max_size, max_cost);\n  cost_[node] = 0;\n  previous_.clear();\n  previous_.resize(max_size, NO_NODE);\n}\n\nGraph::~Graph() = default;\n\nbool Graph::add_edge(uint16_t source, uint16_t dest, float cost) {\n  if (computed_) {\n    return false;\n  }\n\n  //VLOG(3) << \"adding edge: \" << source << \" \" << dest << \" \" << cost << \" \" << std::boolalpha << computed_ << std::endl;\n  adjacency_list_[source].emplace_back(dest, cost);\n  return true;\n}\n\nbool Graph::has_node(uint16_t source) {\n  return !adjacency_list_[source].empty();\n}\n\n\nvoid Graph::Compute() {\n  computed_ = true;\n  std::set<std::pair<float, uint16_t>> queue;\n  queue.insert(std::make_pair(cost_[node_], node_));\n\n  while (!queue.empty()) {\n    const auto dist = queue.begin()->first;\n    const auto u = queue.begin()->second;\n    queue.erase(queue.begin());\n\n    // Visit each edge exiting u\n    const auto& edges = adjacency_list_[u];\n    for (const auto& e : edges) {\n      auto v = e.node_;\n      if (const auto cost_through_u = dist + e.cost_; cost_through_u < cost_[v]) {\n        queue.erase(std::make_pair(cost_[v], v));\n        cost_[v] = cost_through_u;\n        previous_[v] = u;\n        queue.insert(std::make_pair(cost_[v], v));\n      }\n    }\n  }\n  //DumpCosts();\n}\n\nfloat Graph::cost_to(uint16_t destination) {\n  if (!computed_) {\n    Compute();\n  }\n  return cost_[destination];\n}\n\n\nstd::string Graph::DumpCosts() const {\n  std::ostringstream ss;\n  ss << \"costs_: \";\n  for (auto i = 0; i < std::numeric_limits<uint16_t>::max(); i++) {\n    if (const auto cost = cost_[i]; std::isfinite(cost)) {\n      ss << i << \"[\" << cost_[i] << \"] \";\n    }\n  }\n  return ss.str();\n}\n\n\nstd::list<uint16_t> Graph::shortest_path_to(uint16_t destination) {\n  if (!computed_) {\n    Compute();\n  }\n  std::list<uint16_t> path;\n  for (; destination != NO_NODE; destination = previous_[destination]) {\n    path.push_front(destination);\n  }\n  return path;\n}\n} // namespace wwiv\n"
  },
  {
    "path": "core/graphs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_GRAPHS_OS_H\n#define INCLUDED_WWIV_GRAPHS_OS_H\n\n#include \"core/stl.h\"\n#include <cstdint>\n#include <list>\n#include <string>\n#include <vector>\n\nnamespace wwiv::graphs {\n\n\nstruct edge {\n  uint16_t node_;\n  float cost_;\n\n  edge(uint16_t node, float cost)\n    : node_(node),\n      cost_(cost) {\n  }\n};\n\ntypedef std::vector<std::vector<edge>> adjacency_list_t;\n\n/*\n Use:\n Graph net(1, 200);\n net.add_edge(1, 2, 0);\n net.add_edge(2, 3, 0);\n net.add_edge(2, 1, 0);\n net.add_edge(3, 2, 0);\n\n list<uint16_t> path = net.shortest_path_to(3);\n */\nclass Graph final {\npublic:\n  Graph(uint16_t node, uint16_t max_size);\n  ~Graph();\n\n  bool add_edge(uint16_t source, uint16_t dest, float cost);\n  [[nodiscard]] bool has_node(uint16_t source);\n  [[nodiscard]] std::list<uint16_t> shortest_path_to(uint16_t destination);\n  [[nodiscard]] float cost_to(uint16_t destination);\n  [[nodiscard]] std::string DumpCosts() const;\n\n  [[nodiscard]] int num_hops_to(uint16_t destination) {\n    const auto path = shortest_path_to(destination);\n    if (path.empty()) {\n      return 0;\n    }\n    return stl::size_int(path) - 1;\n  }\n\nprivate:\n  uint16_t node_;\n  adjacency_list_t adjacency_list_;\n  bool computed_{false};\n  std::vector<float> cost_;\n  std::vector<uint16_t> previous_;\n\n  void Compute();\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/graphs_main.cpp",
    "content": "using namespace wwiv::graphs;\n\nint main() {\n  // remember to insert edges both ways for an undirected graph\n  adjacency_list_t adjacency_list(std::numeric_limits<uint16_t>::max());\n  adjacency_list[1].push_back(edge(2, 10));\n  adjacency_list[1].push_back(edge(3, 15));\n\n  adjacency_list[2].push_back(edge(1, 10));\n  adjacency_list[2].push_back(edge(3, 11));\n  adjacency_list[2].push_back(edge(5, 2));\n\n  adjacency_list[3].push_back(edge(1, 15));\n  adjacency_list[3].push_back(edge(2, 11));\n  adjacency_list[3].push_back(edge(4, 6));\n\n  adjacency_list[4].push_back(edge(3, 6));\n  adjacency_list[4].push_back(edge(5, 9));\n\n  adjacency_list[5].push_back(edge(2, 2));\n  adjacency_list[5].push_back(edge(4, 9));\n\n  std::vector<float> cost_;\n  std::vector<uint16_t> previous;\n  all_paths(1, adjacency_list, cost_, previous);\n  std::cout << \"Cost from 1 to 5: \" << cost_[5] << std::endl;\n  std::copy_if(previous.begin(), previous.end(),\n               std::ostream_iterator<uint16_t>(std::cout, \" \"),\n               [](uint16_t i) { return i != NO_NODE; });\n  std::list<uint16_t> path = shortest_path(5, previous);\n  std::cout << \"Path : \";\n  std::copy(path.begin(), path.end(), std::ostream_iterator<uint16_t>(std::cout, \" \"));\n  std::cout << std::endl;\n\n  return 0;\n}\n"
  },
  {
    "path": "core/inifile.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/inifile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include <initializer_list>\n#include <map>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\nnamespace {\n/**\n * Reads a specified value from INI file data. The\n * name of the value to read is contained in *value_name. If such a name\n * does not exist in this INI file subsection, then *val is nullptr, else *val\n * will be set to the string value of that value name. If *val has been set\n * to something, then this function returns 1, else it returns 0.\n */\nbool StringToBoolean(const std::string& s) {\n  if (s.empty()) {\n    return false;\n  }\n  const auto ch = to_upper_case<char>(s.front());\n  return ch == 'Y' || ch == 'T' || ch == '1';\n}\n\n} // namespace {}\n\nstatic bool ParseIniFile(const std::filesystem::path& filename, std::map<std::string, std::string>& data) {\n  if (!File::Exists(filename)) {\n    // No need to try to open a file that does not exist.\n    return false;\n  }\n\n  data.clear();\n  TextFile file(filename, \"rt\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n\n  bool in_multiline_string = false;\n  std::string full_key;\n  std::string section;\n  std::string line;\n  while (file.ReadLine(&line)) {\n    StringTrim(&line);\n    if (line.empty()) {\n      continue;\n    }\n\n    if (in_multiline_string) {\n      // We use whole line here for the value.\n      if (const auto end = line.find(R\"(\"\"\")\"); end != std::string::npos) {\n        line = line.substr(0, end);\n        in_multiline_string = false;\n      }\n      auto& existing_value = data[full_key];\n      if (!existing_value.empty()) {\n        existing_value.append(\"\\r\\n\");\n      }\n      existing_value.append(line);\n      continue;\n    }\n    if (line.front() == '[' && line.back() == ']') {\n      // Section header.\n      section = line.substr(1, line.size() - 2);\n    } else {\n      // Not a section.\n      if (line.find(';') != std::string::npos) {\n        // we have a comment, remove it.\n        line.erase(line.find(';'));\n      }\n\n      const auto equals = line.find('=');\n      if (equals == std::string::npos) {\n        // not a line of the form full_key = value [; comment]\n        continue;\n      }\n      const auto partial_key = StringTrim(line.substr(0, equals));\n      auto value = StringTrim(line.substr(equals + 1));\n      if (const auto mlstart = value.find(R\"(\"\"\")\"); mlstart != std::string::npos) {\n        // We have a multi-line string here.\n        in_multiline_string = true;\n        // Skip \"\"\"\n        value = value.substr(mlstart + 3);\n      } else {\n        // Trim leading and traling single quotes.\n        if (value.size() >= 2 && value.front() == '\"' && value.back() == '\"') {\n          value = value.substr(1, value.size() - 2);\n        }\n      }\n      full_key = StrCat(section, \".\", partial_key);\n      data[full_key] = value;\n    }\n  }\n  return true;\n}\n\nIniFile::IniFile(std::filesystem::path filename, std::string_view section)\n    : IniFile(filename, {section}) {}\n\nIniFile::IniFile(std::filesystem::path filename, std::string_view section0,\n                 std::string_view section1)\n    : IniFile(filename, {section0, section1}) {}\n\nIniFile::IniFile(std::filesystem::path filename,\n                 const std::initializer_list<std::string_view> sections)\n  : path_(std::move(filename)) {\n  // Can't use initializer_list to go from const string -> vector<string>\n  // and can't use vector<const string>\n  for (const auto& s : sections) {\n    sections_.emplace_back(s);\n  }\n  open_ = ParseIniFile(path_, data_);\n}\n\nIniFile::~IniFile() {\n  open_ = false;\n}\n\n/* Close is now a NOP */\n// ReSharper disable once CppMemberFunctionMayBeStatic\nvoid IniFile::Close() noexcept {\n}\n\nstd::optional<std::string> IniFile::GetValue(const std::string& raw_key) const {\n  for (const auto& section : sections_) {\n    const auto full_key = StrCat(section, \".\", raw_key);\n    if (const auto & it = data_.find(full_key); it != data_.end()) {\n      return it->second;\n    }\n  }\n  return std::nullopt;\n}\n\nstd::string IniFile::\nGetStringValue(const std::string& key, const std::string& default_value) const {\n  if (const auto s = GetValue(key)) {\n    return s.value();\n  }\n  return default_value;\n}\n\nbool IniFile::GetBooleanValue(const std::string& key, bool default_value) const {\n  if (const auto s = GetValue(key)) {\n    return StringToBoolean(s.value());\n  }\n  return default_value;\n}\n\nlong IniFile::GetNumericValueT(const std::string& key, long default_value) const {\n  if (const auto s = GetValue(key)) {\n    return wwiv::strings::to_number<long>(s.value());\n  }\n  return default_value;\n}\n\nstd::string IniFile::full_pathname() const noexcept {\n  try {\n    return path_.string();\n  } catch (const std::exception& e) {\n    DLOG(FATAL) << \"IniFile::full_pathname() threw exception: \" << e.what();\n  } catch (...) {\n    DLOG(FATAL) << \"IniFile::full_pathname() threw exception\";\n  }\n  return {};\n}\n\n[[nodiscard]] std::vector<int> IniFile::GetIntList(const std::string& key) const {\n  const auto s = GetStringValue(key, \"\");\n  if (s.empty()) {\n    return {};\n  }\n  auto list = SplitString(s, \",\");\n  std::vector<int> out;\n  out.reserve(list.size());\n  for (const auto& i : list) {\n    out.push_back(wwiv::strings::to_number<long>(i));\n  }\n  return out;\n} \n\n\ntemplate <>\nstd::string IniFile::value<std::string>(const std::string& key,\n                                        const std::string& default_value) const {\n  return GetStringValue(key, default_value);\n}\n\ntemplate <>\nstd::string IniFile::value<std::string>(const std::string& key) const {\n  return GetStringValue(key, \"\");\n}\n\ntemplate <>\nbool IniFile::value<bool>(const std::string& key, const bool& default_value) const {\n  return GetBooleanValue(key, default_value);\n}\n\ntemplate <>\nbool IniFile::value<bool>(const std::string& key) const {\n  return GetBooleanValue(key, false);\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/inifile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_INIFILE_H\n#define INCLUDED_CORE_INIFILE_H\n\n#include <filesystem>\n#include <initializer_list>\n#include <map>\n#include <optional>\n#include <string>\n#include <string_view>\n#include <vector>\n\nnamespace wwiv::core {\n\nstruct ini_flags_type {\n  const std::string strnum;\n  uint32_t value;\n};\n\n\nclass IniFile final {\npublic:\n  // Constructor/Destructor\n  IniFile(std::filesystem::path filename, std::string_view section);\n  IniFile(std::filesystem::path filename, std::string_view section0, std::string_view section1);\n  IniFile(std::filesystem::path filename, std::initializer_list<std::string_view> sections);\n  ~IniFile();\n\n  // Member functions\n  void Close() noexcept;\n  [[nodiscard]] bool IsOpen() const noexcept { return open_; }\n\n  template <typename T>\n  [[nodiscard]] T value(const std::string& key, const T& default_value) const {\n    return static_cast<T>(GetNumericValueT(key, default_value));\n  }\n\n  template <typename T>\n  [[nodiscard]] T value(const std::string& key) const {\n    return static_cast<T>(GetNumericValueT(key, T()));\n  }\n\n  [[nodiscard]] std::string full_pathname() const noexcept;\n  [[nodiscard]] std::filesystem::path path() const noexcept { return path_; }\n\ntemplate <typename T>\n  [[nodiscard]] T GetFlags(const std::vector<ini_flags_type>& flag_definitions, T flags) {\n  for (const auto& [key, v] : flag_definitions) {\n    if (key.empty()) {\n      continue;\n    }\n    if (const auto val = value<std::string>(key); val.empty()) {\n      continue;\n    }\n    if (value<bool>(key)) {\n      flags |= v;\n    } else {\n      flags &= ~v;\n    }\n  }\n  return flags;\n}\n\n/**\n * Gets a std::vector of int from key. In the INI file the list should be\n * a comma separated list.\n */\n[[nodiscard]] std::vector<int> GetIntList(const std::string& key) const;\n\n// This class should not be assignable via '=' so remove the implicit operator=\n// and Copy constructor.\nIniFile(const IniFile& other) = delete;\nIniFile& operator=(const IniFile& other) = delete;\n\nprivate:\n  [[nodiscard]] std::optional<std::string> GetValue(const std::string& key) const;\n\n  [[nodiscard]] std::string GetStringValue(const std::string& key, const std::string& default_value) const;\n  [[nodiscard]] long GetNumericValueT(const std::string& key, long default_value = 0) const;\n  [[nodiscard]] bool GetBooleanValue(const std::string& key, bool default_value = false) const;\n\n\n  const std::filesystem::path path_;\n  bool open_{false};\n  std::vector<std::string> sections_;\n  std::map<std::string, std::string> data_;\n};\n\ntemplate <>\n[[nodiscard]] std::string IniFile::value<std::string>(const std::string& key,\n                                                      const std::string& default_value) const;\n\ntemplate <>\n[[nodiscard]] std::string IniFile::value<std::string>(const std::string& key) const;\n\ntemplate <>\n[[nodiscard]] bool IniFile::value<bool>(const std::string& key, const bool& default_value) const;\ntemplate <>\n[[nodiscard]] bool IniFile::value<bool>(const std::string& key) const;\n\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/inifile_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include <cstdio>\n#include <string>\n#include <vector>\n\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n\nusing namespace wwiv::core;\n\nclass IniFileTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    const auto* test_info = ::testing::UnitTest::GetInstance()->current_test_info();\n    test_name_ = test_info->name();\n  }\n\n  [[nodiscard]] const std::string& test_name() const { return test_name_; }\n\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  std::filesystem::path CreateIniFile(const std::string& section, const std::vector<std::string>& lines) {\n    auto [file, path] = helper_.OpenTempFile(test_name_);\n    fprintf(file, \"[%s]\\n\", section.c_str());\n    for (const auto& line : lines) {\n      fprintf(file, \"%s\\n\", line.c_str());\n    }\n    fclose(file);\n    return path;\n  }\n\n  bool WriteLineToFile(FILE* file, const std::string& line) {\n    return fprintf(file, \"%s\\n\", line.c_str()) > 0;\n  }\n\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  std::filesystem::path CreateIniFile(const std::string& section1, const std::vector<std::string>& lines1,\n                                      const std::string& section2, const std::vector<std::string>& lines2) {\n    auto [file, path] = helper_.OpenTempFile(test_name_);\n    fprintf(file, \"[%s]\\n\", section1.c_str());\n    for (const auto& line : lines1) {\n      WriteLineToFile(file, line);\n    }\n\n    fprintf(file, \"[%s]\\n\", section2.c_str());\n    for (const auto& line : lines2) {\n      WriteLineToFile(file, line);\n    }\n\n    fclose(file);\n    return path;\n  }\n\n  wwiv::core::test::FileHelper helper_;\n  std::string test_name_;\n};\n\nTEST_F(IniFileTest, Single_GetValue) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=BAR\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(\"BAR\", ini.value<std::string>(\"FOO\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, Single_GetValue_Comment) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=BAR  ; BAZ\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(\"BAR\", ini.value<std::string>(\"FOO\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, Single_GetNumericValue) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=1234\", \"BAR=4321\", \"baz=12345\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(1234, ini.value<int>(\"FOO\"));\n  EXPECT_EQ(4321, ini.value<int>(\"BAR\"));\n  EXPECT_EQ(12345, ini.value<int>(\"baz\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, Single_GetBooleanValue) {\n  const auto path =\n      this->CreateIniFile(\"TEST\", {\"T1=TRUE\", \"T2=1\", \"T3=Y\", \"F1=FALSE\", \"F2=0\", \"F3=N\", \"U=WTF\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_TRUE(ini.value<bool>(\"T1\"));\n  EXPECT_TRUE(ini.value<bool>(\"T2\"));\n  EXPECT_TRUE(ini.value<bool>(\"T3\"));\n  EXPECT_FALSE(ini.value<bool>(\"F1\"));\n  EXPECT_FALSE(ini.value<bool>(\"F2\"));\n  EXPECT_FALSE(ini.value<bool>(\"F3\"));\n\n  EXPECT_FALSE(ini.value<bool>(\"U\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, Reopen_GetValue) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=BAR\"}, \"TEST2\", {\"BAR=BAZ\"});\n  {\n    IniFile ini(path, \"TEST\");\n    ASSERT_TRUE(ini.IsOpen());\n    EXPECT_EQ(\"BAR\", ini.value<std::string>(\"FOO\"));\n    ini.Close();\n  }\n\n  IniFile ini(path, \"TEST2\");\n  EXPECT_EQ(\"BAZ\", ini.value<std::string>(\"BAR\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, TwoSection_GetValue) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=BAR\"}, \"TEST-1\", {\"FOO=BAZ\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(\"BAZ\", ini.value<std::string>(\"FOO\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, TwoSection_GetValue_OnlyInSecondary) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=BAR\"}, \"TEST-1\", {\"FOO1=BAZ\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(\"BAR\", ini.value<std::string>(\"FOO\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, CommentAtStart) {\n  const auto path = this->CreateIniFile(\"TEST\", {\";FOO=BAR\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  EXPECT_EQ(\"\", ini.value<std::string>(\"FOO\"));\n  ini.Close();\n}\n\nTEST_F(IniFileTest, MultiLine_Smoke) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=\\\"\\\"\\\"\\nBAR\\nBAZ\\n\\\"\\\"\\\"\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  const auto actual = ini.value<std::string>(\"FOO\");\n  EXPECT_EQ(\"BAR\\r\\nBAZ\\r\\n\", actual) << \"A:\" << actual;\n  ini.Close();\n}\n\nTEST_F(IniFileTest, MultiLine_OnFirstLine) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=\\\"\\\"\\\"BAR\\nBAZ\\n\\\"\\\"\\\"\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  const auto actual = ini.value<std::string>(\"FOO\");\n  EXPECT_EQ(\"BAR\\r\\nBAZ\\r\\n\", actual) << \"A:\" << actual;\n  ini.Close();\n}\n\nTEST_F(IniFileTest, MultiLine_OnLastLine) {\n  const auto path = this->CreateIniFile(\"TEST\", {\"FOO=\\\"\\\"\\\"\\nBAR\\nBAZ\\\"\\\"\\\"\"});\n  IniFile ini(FilePath(helper_.TempDir(), this->test_name()), \"TEST-1\", \"TEST\");\n  ASSERT_TRUE(ini.IsOpen());\n  const auto actual = ini.value<std::string>(\"FOO\");\n  EXPECT_EQ(\"BAR\\r\\nBAZ\", actual) << \"A:\" << actual;\n  ini.Close();\n}"
  },
  {
    "path": "core/ip_address.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/ip_address.h\"\n\n#include \"core/strings.h\"\n#include \"core/stl.h\"\n#include <array>\n#include <iomanip>\n#include <ios>\n#include <random>\n#include <sstream>\n#ifdef _WIN32\n#pragma comment(lib, \"Ws2_32.lib\")\n#include \"WS2tcpip.h\"\n#include <ws2def.h>\n#elif defined (__OS2__)\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#else\n#include <arpa/inet.h>\n#include <sys/types.h>\n#endif // _WIN32\n\n\nnamespace wwiv::core {\n\nusing namespace wwiv::strings;\n\n// Guarantee the size is 16 bytes and we're trivially copyable\n// i.e. memcmp works on the class and also standard layout\n// so that we can write to disk and back with write/read.\nstatic_assert(sizeof(ip_address) == 16, \"ip_address == 16\");\nstatic_assert(std::is_trivially_copyable<ip_address>::value == true,\n              \"ip_address !is_trivially_copyable\");\nstatic_assert(std::is_standard_layout<ip_address>::value == true,\n              \"ip_address !is_trivially_copyable\");\n\nstd::ostream& operator<<(std::ostream& os, const ip_address& a) {\n  os << a.to_string();\n  return os;\n}\n\nip_address::ip_address(char* data) { \n  memcpy(data_, data, 16); \n}\n\nstd::string ip_address::to_string() const {\n  char buf[255];\n#ifdef __OS2__\n  auto af = AF_INET; \n#else\n  auto af = AF_INET6; \n#endif\n  std::string s = inet_ntop(af, &data_, buf, sizeof(buf));\n  if (starts_with(s, \"::ffff:\") && s.find('.') != std::string::npos) {\n    // Even though we store it IPv6 internally, display as IPv4\n    return s.substr(7);\n  }\n  return s;\n}\n\nbool ip_address::empty() const {\n  for (const auto d : data_) {\n    if (d != 0) {\n      return false;\n    }\n  }\n  return true;\n}\n\nstd::optional<ip_address> ip_address::from_string(const std::string& s) { \n  char d[16];\n  auto addr{s};\n  if (s.length() < 2) {\n    return std::nullopt;\n  }\n  if (s.find(':') == std::string::npos) {\n    //make this into a ipv6 address for an ipv4 address\n    addr = wwiv::strings::StrCat(\"0:0:0:0:0:FFFF:\", s);\n  }\n#ifdef __OS2__\n  memset(&d, 0x00, 10);\n  memset(&d[10], 0x01, 2);\n  const auto ret = inet_pton(AF_INET, addr.c_str(), &d[12]);\n#else\n  const auto ret = inet_pton(AF_INET6, addr.c_str(), &d);\n#endif\n  if (ret != 1) {\n    LOG(INFO) << \"result code: \" << ret;\n    return std::nullopt;\n  }\n  return {ip_address(d)};\n}\n\n} // namespace wwiv::core \n"
  },
  {
    "path": "core/ip_address.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_IP_ADDRESS_H\n#define INCLUDED_CORE_IP_ADDRESS_H\n\n#include <cstring>\n#include <optional>\n#include <string>\n\nnamespace wwiv::core {\n\nclass ip_address final {\npublic:\n  explicit ip_address(char* data);\n  ip_address() = default;\n  ~ip_address() = default;\n\n\n  [[nodiscard]] std::string to_string() const;\n\n  /** True if this IP Address is an empty address (i.e. 0.0.0.0 or ::) */\n  [[nodiscard]] bool empty() const;\n  [[nodiscard]] static std::optional<ip_address> from_string(const std::string&);\n  friend inline bool operator==(const ip_address& lhs, const ip_address& rhs);\n  friend inline bool operator!=(const ip_address& lhs, const ip_address& rhs);\n  friend std::ostream& operator<<(std::ostream& os, const ip_address& u);\n  \nprivate:\n  char data_[16];\n};\n\ninline bool operator==(const ip_address& lhs, const ip_address& rhs) {\n  return memcmp(lhs.data_, rhs.data_, sizeof(lhs.data_)) == 0;\n}\ninline bool operator!=(const ip_address& lhs, const ip_address& rhs) {\n  return memcmp(lhs.data_, rhs.data_, sizeof(lhs.data_)) != 0;\n}\n\nstatic_assert(sizeof(wwiv::core::ip_address) == 16, \"wwiv::core::ip_address == 16\");\n\n}\n\n#endif\n"
  },
  {
    "path": "core/ip_address_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/ip_address.h\"\n#include <sstream>\n#include <string>\n\nusing namespace wwiv::core;\n\nclass IpAddressTest : public ::testing::Test {\npublic:\n  IpAddressTest()  {}\n};\n\nTEST_F(IpAddressTest, Smoke_Home_V4) {\n  auto o = ip_address::from_string(\"127.0.0.1\");\n  ASSERT_TRUE(o.has_value());\n  const auto a = o.value();\n  EXPECT_EQ(\"127.0.0.1\", a.to_string());\n}\n\nTEST_F(IpAddressTest, Smoke_Home_V6) {\n  auto o = ip_address::from_string(\"::1\");\n  ASSERT_TRUE(o.has_value());\n  const auto a = o.value();\n  EXPECT_EQ(\"::1\", a.to_string());\n}\n\nTEST_F(IpAddressTest, Empty) {\n  const auto e = ip_address();\n  EXPECT_TRUE(e.empty());\n}\n\nTEST_F(IpAddressTest, Empty_NotEmpty) {\n  auto o = ip_address::from_string(\"::1\");\n  EXPECT_FALSE(o.value().empty());\n}\n\nTEST_F(IpAddressTest, Chevron) {\n  auto o = ip_address::from_string(\"127.0.0.1\");\n  ASSERT_TRUE(o.has_value());\n  std::ostringstream ss;\n  ss << o.value();\n  EXPECT_EQ(\"127.0.0.1\", ss.str());\n}\n\nTEST_F(IpAddressTest, Equality) {\n  const auto ip4 = ip_address::from_string(\"127.0.0.1\").value();\n  const auto ip4a = ip_address::from_string(\"127.0.0.1\").value();\n  const auto ip4dif = ip_address::from_string(\"10.0.0.1\").value();\n  const auto ip6 = ip_address::from_string(\"::1\").value();\n  const auto ip6a = ip_address::from_string(\"::1\").value();\n\n  EXPECT_EQ(ip4, ip4a);\n  EXPECT_EQ(ip6, ip6a);\n\n  EXPECT_NE(ip4, ip6);\n  EXPECT_NE(ip4, ip4dif);\n}\n"
  },
  {
    "path": "core/jsonfile.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2016-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/jsonfile.h\"\n\n#include \"cereal/external/rapidjson/document.h\"\n\nnamespace wwiv::core {\n\nstd::optional<std::string> read_json_file(const std::filesystem::path& p) {\n  TextFile file(p, \"r\");\n  if (!file.IsOpen()) {\n    return std::nullopt;\n  }\n  const auto text = file.ReadFileIntoString();\n  if (text.empty()) {\n    return std::nullopt;\n  }\n\n  return { text };\n}\n\nint json_file_version(const std::filesystem::path& p) {\n  if (auto o = read_json_file(p)) {\n    rapidjson::Document doc;\n    doc.Parse(o.value().c_str());\n\n    if (!doc.IsObject()) {\n      LOG(WARNING) << \"document is not an object: \" << p.string();\n      return 0;\n    }\n  }\n  return 0;\n}\n\n} // namespace\n"
  },
  {
    "path": "core/jsonfile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2016-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_JSONFILE_H\n#define INCLUDED_CORE_JSONFILE_H\n\n#include \"core/cereal_utils.h\"\n#include \"core/log.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include <filesystem>\n#include <optional>\n#include <sstream>\n#include <string>\n#include <utility>\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/access.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/cereal.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/archives/json.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/map.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/memory.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/set.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/vector.hpp>\n\n\nnamespace wwiv::core {\n\nstd::optional<std::string> read_json_file(const std::filesystem::path& p);\nint json_file_version(const std::filesystem::path& p);\n\nstruct json_version_error : public std::runtime_error {\n  json_version_error(const std::string& filename, int min_ver, int actual_ver)\n      : std::runtime_error(fmt::format(\"Invalid version for file '{}', expected: {}, actual: {}. \"\n                                       \"Please run WWIVconfig to update it.\",\n                                       filename, min_ver, actual_ver)) {}\n};\n\n\ntemplate <typename T>\nclass JsonFile final {\npublic:\n  JsonFile(std::filesystem::path file_name, std::string key, T& t, int version = 0)\n    : file_name_(std::move(file_name)), key_(std::move(key)), t_(t), version_(version) {\n  }\n  JsonFile(const JsonFile&) = delete;\n  JsonFile(JsonFile&&) = delete;\n  JsonFile& operator=(const JsonFile&) = delete;\n  JsonFile& operator=(JsonFile&&) = delete;\n\n  ~JsonFile() = default;\n\n  bool Load() {\n    try {\n      if (!File::Exists(file_name_)) {\n        VLOG(3) << \"JSON File does not exist: \" << file_name_.string();\n        return false;\n      }\n      if (const auto o = read_json_file(file_name_)) {\n        std::stringstream ss(o.value());\n        cereal::JSONInputArchive ar(ss);\n        SERIALIZE_NVP(\"version\", loaded_version_);\n        if (version_ > 0 && loaded_version_ < version_) {\n          throw json_version_error(file_name_.string(), version_, loaded_version_);\n        }\n        ar(cereal::make_nvp(key_, t_));\n        return true;\n      }\n      return false;\n    } catch (const cereal::RapidJSONException& e) {\n      LOG(ERROR) << \"Caught cereal::RapidJSONException: \" << e.what();\n      return false;\n    }\n  }\n\n  bool Save() {\n    std::ostringstream ss;\n    try {\n      cereal::JSONOutputArchive ar(ss);\n      if (version_ != 0) {\n        SERIALIZE_NVP(\"version\", version_);\n      }\n      ar(cereal::make_nvp(key_, t_));\n    } catch (const cereal::RapidJSONException& e) {\n      LOG(ERROR) << \"Caught cereal::RapidJSONException: \" << e.what();\n      return false;\n    }\n\n    TextFile file(file_name_, \"w\");\n    if (!file.IsOpen()) {\n      return false;\n    }\n\n    return file.Write(ss.str());\n  }\n\n  [[nodiscard]] int loaded_version() const noexcept { return loaded_version_; }\n\nprivate:\n  const std::filesystem::path file_name_;\n  const std::string key_;\n  T& t_;\n  int version_;\n  int loaded_version_{0};\n};\n\n// C++17 Deduction Guide for JsonFile\ntemplate <typename X, typename Y, typename Z> JsonFile(X, Y, Z&, int) -> JsonFile<Z>;\n\n}\n\n#endif\n"
  },
  {
    "path": "core/log.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/log.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/core.h\"\n#include \"fmt/printf.h\"\n#include <chrono>\n#include <cstdlib>\n#include <functional>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <unordered_map>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\nstatic constexpr char log_date_format[] = \"%Y-%m-%d %H:%M:%S\";\n\nstatic std::shared_ptr<Appender> console_appender;\nstatic std::shared_ptr<Appender> logfile_appender;\nLoggerConfig Logger::config_;\n\nclass ConsoleAppender : public Appender {\n  bool append(const std::string& message) override {\n    std::cerr << message << std::endl;\n    return true;\n  }\n};\n\nclass LogFileAppender : public Appender {\npublic:\n  explicit LogFileAppender(const std::filesystem::path& fn) : filename_(fn) {}\n\n  bool append(const std::string& message) override {\n    // Not super performant, but we'll start here and see how far this\n    // gets us.\n    if (message.empty()) {\n      return true;\n    }\n    TextFile out(filename_, \"a\");\n    if (!out.IsOpen()) {\n      // We don't want to crash if we can't log, but what\n      // should we do instead?\n      return false;\n    }\n    return out.WriteLine(message) > 0;\n  }\n\nprivate:\n  const std::filesystem::path filename_;\n};\n\nstatic std::string FormatLogLevel(LoggerLevel l, int v) noexcept {\n  try {\n    if (l == LoggerLevel::verbose) {\n      return StrCat(\"VER-\", v);\n    }\n    static const std::unordered_map<LoggerLevel, std::string> map = {\n        {LoggerLevel::ignored, \"\"},\n        {LoggerLevel::start, \"START\"},\n        {LoggerLevel::debug, \"DEBUG\"},\n        {LoggerLevel::verbose, \"VER- \"},\n        {LoggerLevel::error, \"ERROR\"},\n        {LoggerLevel::info, \"INFO \"},\n        {LoggerLevel::warning, \"WARN \"},\n        {LoggerLevel::fatal, \"FATAL\"},\n    };\n    return map.at(l);\n  } catch (...) {\n    return \"\";\n  }\n}\n\nstd::string Logger::FormatLogMessage(LoggerLevel level, int verbosity,\n                                     const std::string& msg) const noexcept {\n  try {\n    return StrCat(config_.timestamp_fn_(), FormatLogLevel(level, verbosity), \" \", msg);\n  } catch (...) {\n    return msg;\n  }\n}\n\nLogger::Logger(LoggerLevel level, int verbosity) noexcept\n  : level_(level), verbosity_(verbosity) {\n}\n\nLogger::~Logger() noexcept {\n  try {\n    if (level_ == LoggerLevel::verbose) {\n      if (!vlog_is_on(verbosity_)) {\n        return;\n      }\n    }\n    const auto msg = FormatLogMessage(level_, verbosity_, ss_.str());\n    const auto& appenders = config_.log_to[level_];\n    if (appenders.empty()) {\n      // probably should never happen.\n      if (console_appender) {\n        console_appender->append(StrCat(\"No appenders specified; : \", msg));\n      }\n    }\n    for (const auto& a : appenders) {\n      a->append(msg);\n    }\n    if (level_ == LoggerLevel::fatal) {\n      abort();\n    }\n  } catch (...) {\n    // NOOP\n  }\n}\n\n// static\nvoid Logger::set_cmdline_verbosity(int cmdline_verbosity) {\n  config_.cmdline_verbosity = cmdline_verbosity;\n}\n\n// static\nbool Logger::vlog_is_on(int level) { return level <= config_.cmdline_verbosity; }\n\n// static\nvoid Logger::StartupLog(int argc, char* argv[]) {\n  const auto dt = DateTime::now();\n  LOG(STARTUP) << config_.exit_filename << \" version \" << full_version() << \" (\"\n               << wwiv_compile_datetime() << \")\";\n  LOG(STARTUP) << config_.exit_filename << \" starting at \" << dt.to_string();\n  if (argc > 1) {\n    std::string cmdline;\n    for (auto i = 1; i < argc; i++) {\n      cmdline += argv[i];\n      cmdline += \" \";\n    }\n    LOG(STARTUP) << \"command line: \" << cmdline;\n  }\n}\n\n// static\nvoid Logger::ExitLogger() {\n  const auto dt = DateTime::now();\n  LOG(STARTUP) << config_.exit_filename << \" exiting at \" << dt.to_string();\n}\n\n// static\nvoid Logger::Init(int argc, char** argv, LoggerConfig& c) {\n  config_ = c;\n  config_.cmdline_verbosity = 0;\n  CommandLine cmdline(argc, argv, \"\");\n  cmdline.AddStandardArgs();\n  cmdline.set_no_args_allowed(true);\n  cmdline.set_unknown_args_allowed(true);\n  cmdline.Parse();\n\n  const auto l = cmdline.arg(\"logdir\");\n  auto logdir = std::filesystem::path(cmdline.logdir());\n  if (l.is_default() && c.logdir_fn_) {\n    if (const auto logdir_from_fn = c.logdir_fn_(cmdline.bbsdir()); !logdir_from_fn.empty()) {\n      logdir = logdir_from_fn;\n    }\n  }\n\n  // Set --v from commandline\n  config_.cmdline_verbosity = cmdline.iarg(\"v\");\n\n  std::string filename(argv[0]);\n  if (ends_with(filename, \".exe\") || ends_with(filename, \".EXE\")) {\n    filename = filename.substr(0, filename.size() - 4);\n  }\n  if (const auto last_slash = filename.rfind(File::pathSeparatorChar); last_slash != std::string::npos) {\n    filename = filename.substr(last_slash + 1);\n  }\n  config_.log_filename = FilePath(logdir, StrCat(filename, \".log\")).string();\n  config_.exit_filename = filename;\n\n  // Setup the default appenders.\n  console_appender.reset(new ConsoleAppender{});\n  logfile_appender.reset(new LogFileAppender{config_.log_filename});\n\n  if (config_.register_console_destinations) {\n    config_.add_appender(LoggerLevel::error, console_appender);\n    config_.add_appender(LoggerLevel::fatal, console_appender);\n    config_.add_appender(LoggerLevel::warning, console_appender);\n    config_.add_appender(LoggerLevel::info, console_appender);\n    config_.add_appender(LoggerLevel::verbose, console_appender);\n  }\n  if (config_.register_file_destinations) {\n    config_.add_appender(LoggerLevel::error, logfile_appender);\n    config_.add_appender(LoggerLevel::fatal, logfile_appender);\n    config_.add_appender(LoggerLevel::warning, logfile_appender);\n    config_.add_appender(LoggerLevel::info, logfile_appender);\n    config_.add_appender(LoggerLevel::verbose, logfile_appender);\n    config_.add_appender(LoggerLevel::start, logfile_appender);\n  }\n  if (config_.log_startup || cmdline.barg(\"log_startup\")) {\n    StartupLog(argc, argv);\n  }\n}\n\nstatic std::string DefaultTimestamp() {\n  const auto dt = DateTime::now();\n  const auto nowc = std::chrono::system_clock::now();\n  const auto duration = nowc.time_since_epoch();\n  const auto millis = static_cast<int>(\n    std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000);\n  const auto ymd_hms = dt.to_string(log_date_format);\n  return fmt::format(\"{},{:03} \", ymd_hms, millis);\n}\n\n\nLoggerConfig::LoggerConfig()\n  : timestamp_fn_(DefaultTimestamp) {\n}\n\nLoggerConfig::LoggerConfig(logdir_fn f)\n  : LoggerConfig(std::move(f), DefaultTimestamp) {\n}\n\nLoggerConfig::LoggerConfig(logdir_fn l, timestamp_fn t)\n  : logdir_fn_(std::move(l)), timestamp_fn_(std::move(t)) {\n}\n\n\nvoid LoggerConfig::add_appender(LoggerLevel level, const std::shared_ptr<Appender>& appender) {\n  log_to[level].emplace(appender);\n}\n\nvoid LoggerConfig::reset() {\n  timestamp_fn_ = DefaultTimestamp;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/log.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n// ReSharper disable CppClangTidyCppcoreguidelinesMacroUsage\n#ifndef INCLUDED_CORE_LOG_H\n#define INCLUDED_CORE_LOG_H\n\n#include \"core/os.h\"\n\n#include <filesystem>\n#include <functional>\n#include <memory>\n#include <sstream>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n\n#ifdef _MSC_VER\n#include <sal.h>\n#endif\n\ntypedef std::basic_ostream<char>&(ENDL_TYPE)(std::basic_ostream<char>&);\n\n#if defined(_DEBUG) || !defined(NDEBUG)\n#define WWIV_CORE_LOG_DEBUG\n#endif\n\n#ifdef _MSC_VER\n#define WWIV_ANALYSIS_ASSUME(expr) _Analysis_assume_(expr)\n#else\n#define WWIV_ANALYSIS_ASSUME(expr)\n#endif\n\n\n#define LOG(LEVEL) LOG_##LEVEL\n#define VLOG(LEVEL) LOG_VERBOSE(LEVEL)\n\n#define LOG_IGNORED(x) wwiv::core::NullLogger()\n#ifdef _MSC_VER\n#define LOG_FATAL_IGNORED(x) __assume(x), wwiv::core::NullLogger()\n#else\n#define LOG_FATAL_IGNORED(x) wwiv::core::NullLogger()\n#endif\n#define LOG_STARTUP wwiv::core::Logger(wwiv::core::LoggerLevel::start, 0)\n#define LOG_INFO wwiv::core::Logger(wwiv::core::LoggerLevel::info, 0)\n#define LOG_WARNING wwiv::core::Logger(wwiv::core::LoggerLevel::warning, 0)\n#define LOG_ERROR wwiv::core::Logger(wwiv::core::LoggerLevel::error, 0)\n#define LOG_FATAL wwiv::core::Logger(wwiv::core::LoggerLevel::fatal, 0)\n#define LOG_VERBOSE(verbosity) wwiv::core::Logger(wwiv::core::LoggerLevel::verbose, verbosity)\n\n#define CHECK(x)                                                                                   \\\n  if (!(x))                                                                                        \\\n  wwiv::core::Logger(wwiv::core::LoggerLevel::fatal, 0)                                            \\\n      << \"Failed Precondition: at \" << __FILE__ << \":\" << __LINE__ << \" Condition: \" #x \" \"        \\\n      << wwiv::os::stacktrace()\n\n#define CHECK_LE(x, y) LOG_IF(!((x) <= (y)), FATAL)\n#define CHECK_EQ(x, y) LOG_IF(!((x) == (y)), FATAL)\n#define CHECK_NE(x, y) LOG_IF(!((x) != (y)), FATAL)\n#define CHECK_GE(x, y) LOG_IF(!((x) >= (y)), FATAL)\n#define CHECK_GT(x, y) LOG_IF(!((x) > (y)), FATAL)\n\n#ifdef WWIV_CORE_LOG_DEBUG\n#define DCHECK(x) CHECK(x)\n\n#define DCHECK_LE(x, y) CHECK_LE(x, y)\n\n#define DCHECK_EQ(x, y) CHECK_EQ(x, y)\n\n#define DCHECK_NE(x, y) CHECK_NE(x, y)\n\n#define DCHECK_GE(x, y) CHECK_GE(x, y)\n\n#define DCHECK_GT(x, y) CHECK_GT(x, y)\n\n#define DLOG(LEVEL) LOG_##LEVEL\n\n#else\n#define DCHECK(x) LOG_FATAL_IGNORED(x)\n#define DCHECK_LE(x, y) LOG_FATAL_IGNORED(x)\n#define DCHECK_EQ(x, y) LOG_FATAL_IGNORED(x)\n#define DCHECK_NE(x, y) LOG_FATAL_IGNORED(x)\n#define DCHECK_GE(x, y) LOG_FATAL_IGNORED(x)\n#define DCHECK_GT(x, y) LOG_FATAL_IGNORED(x)\n#define DLOG(LEVEL) LOG_IGNORED(LEVEL)\n#endif\n\n#define CHECK_NOTNULL(x) CHECK((x) != nullptr)\n#define LOG_IF(condition, LEVEL)                                                                   \\\n  if (condition)                                                                                   \\\n  LOG(LEVEL)\n\n#define VLOG_IS_ON(level) wwiv::core::Logger::vlog_is_on(level)\n\nnamespace wwiv::core {\n\nenum class LoggerLevel { ignored, start, debug, verbose, info, warning, error, fatal };\n\nclass Appender {\npublic:\n  virtual ~Appender() = default;\n\n  Appender() = default;\n  virtual bool append(const std::string& message) = 0;\n};\n\ntypedef std::unordered_map<LoggerLevel, std::unordered_set<std::shared_ptr<Appender>>>\nlog_to_map_t;\ntypedef std::function<std::string()> timestamp_fn;\ntypedef std::function<std::filesystem::path(std::filesystem::path)> logdir_fn;\n\n\nclass LoggerConfig {\npublic:\n  LoggerConfig();\n  explicit LoggerConfig(logdir_fn f);\n  LoggerConfig(logdir_fn l, timestamp_fn t);\n  void add_appender(LoggerLevel level, const std::shared_ptr<Appender>& appender);\n  void reset();\n\n  // Change to true to enabled the startup log globally for all binaries.\n  bool log_startup{false};\n  std::string exit_filename;\n  std::string log_filename;\n  int cmdline_verbosity{0};\n  bool register_file_destinations{true};\n  bool register_console_destinations{true};\n  log_to_map_t log_to;\n  logdir_fn logdir_fn_;\n  timestamp_fn timestamp_fn_;\n};\n\nclass NullLogger {\npublic:\n  NullLogger() noexcept = default;\n\n  void operator&(std::ostream&) const noexcept {}\n\n  template <class T> NullLogger& operator<<(const T&) noexcept { return *this; }\n  NullLogger& operator<<(ENDL_TYPE*) noexcept { return *this; }\n};\n\n/**\n * Logger class for WWIV.\n * Usage:\n *\n * Once near your main() method, invoke Logger::Init(argc, argv) to initialize\n * the logger. This will initialize the logger filename to be your\n * executable's name with .log appended. You should also also invoke ExitLogger\n * when exiting your binary,\n *\n * Example:\n *\n *   LoggerConfig lc(LogDirFromConfig);\n *   Logger::Init(argc, argv, lc);\n *   auto at_exit = finally(Logger::ExitLogger);\n *\n * In code, just use \"LOG(INFO) << messages\" and it will end up in the information logs.\n */\nclass Logger {\npublic:\n  Logger() noexcept\n    : Logger(LoggerLevel::info, 0) {\n  }\n\n  explicit Logger(LoggerLevel level) noexcept\n    : Logger(level, 0) {\n  }\n\n  Logger(LoggerLevel level, int verbosity) noexcept;\n  ~Logger() noexcept;\n\n  /** Initializes the WWIV Loggers.  Must be invoked once per binary. */\n  static void Init(int argc, char** argv, LoggerConfig& config);\n  static void ExitLogger();\n  static bool vlog_is_on(int level);\n  static LoggerConfig& config() noexcept { return config_; }\n  static void set_cmdline_verbosity(int cmdline_verbosity);\n\n  template <class T> Logger& operator<<(const T& msg) noexcept {\n    try {\n      ss_ << msg;\n    } catch (...) {\n      // NOOP\n    }\n    used_ = true;\n    return *this;\n  }\n\n  Logger& operator<<(ENDL_TYPE* m) noexcept {\n    used_ = true;\n    try {\n      ss_ << m;\n    } catch (...) {\n      // NOOP\n    }\n    return *this;\n  }\n\nprivate:\n  static void StartupLog(int argc, char* argv[]);\n  [[nodiscard]] std::string FormatLogMessage(LoggerLevel level, int verbosity,\n                                             const std::string& msg) const noexcept;\n  static LoggerConfig config_;\n  LoggerLevel level_;\n  int verbosity_;\n  bool used_{false};\n  std::ostringstream ss_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/log_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\n\nclass TestAppender : public Appender {\npublic:\n  TestAppender() : Appender() {}\n  bool append(const std::string& message) override {\n    log_lines.push_back(message);\n    return true;\n  }\n\n  mutable std::vector<std::string> log_lines;\n};\n\nclass LogTest : public ::testing::Test {\nprotected:\n  void SetUp() override { \n    // Clear all of the loggers\n    info = std::make_shared<TestAppender>();\n    warning = std::make_shared<TestAppender>();\n    Logger::config().log_to.clear();\n    Logger::config().add_appender(LoggerLevel::info, info);\n    Logger::config().add_appender(LoggerLevel::warning, warning); \n\n    timestamp.assign(\"2018-01-01 21:12:00,530 \");\n    const auto fn = [this]() { return timestamp; };\n    Logger::config().timestamp_fn_ = fn;\n  }\n\n  void TearDown() override { Logger::config().reset(); }\n\n  std::shared_ptr<TestAppender> info;\n  std::shared_ptr<TestAppender> warning;\n  std::string timestamp;\n};\n\nTEST_F(LogTest, Smoke) {\n  LOG(INFO) << \"Hello World!\";\n  EXPECT_EQ(1, wwiv::stl::ssize(info->log_lines));\n  EXPECT_EQ(\"2018-01-01 21:12:00,530 INFO  Hello World!\", info->log_lines.front());\n  EXPECT_TRUE(warning->log_lines.empty());\n}\n"
  },
  {
    "path": "core/md5.cpp",
    "content": "/*\n* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.\n* MD5 Message-Digest Algorithm (RFC 1321).\n*\n* Homepage:\n* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5\n*\n* Author:\n* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>\n*\n* This software was written by Alexander Peslyak in 2001.  No copyright is\n* claimed, and the software is hereby placed in the public domain.\n* In case this attempt to disclaim copyright and place the software in the\n* public domain is deemed null and void, then the software is\n* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the\n* general public under the following terms:\n*\n* Redistribution and use in source and binary forms, with or without\n* modification, are permitted.\n*\n* There's ABSOLUTELY NO WARRANTY, express or implied.\n*\n* (This is a heavily cut-down \"BSD license\".)\n*\n* This differs from Colin Plumb's older public domain implementation in that\n* no exactly 32-bit integer data type is required (any 32-bit or wider\n* unsigned integer data type will do), there's no compile-time endianness\n* configuration, and the function prototypes match OpenSSL's.  No code from\n* Colin Plumb's implementation has been reused; this comment merely compares\n* the properties of the two independent implementations.\n*\n* The primary goals of this implementation are portability and ease of use.\n* It is meant to be fast, but not as fast as possible.  Some known\n* optimizations are not included to reduce source code size and avoid\n* compile-time configuration.\n*/\n\n#ifndef HAVE_OPENSSL\n\n#include <cstdint>\n#include <cstring>\n#include <iomanip>\n#include <string>\n#include <sstream>\n\n#include \"md5.h\"\n\n/*\n* The basic MD5 functions.\n*\n* F and G are optimized compared to their RFC 1321 definitions for\n* architectures that lack an AND-NOT instruction, just like in Colin Plumb's\n* implementation.\n*/\n#define F(x, y, z)\t\t\t((z) ^ ((x) & ((y) ^ (z))))\n#define G(x, y, z)\t\t\t((y) ^ ((z) & ((x) ^ (y))))\n#define H(x, y, z)\t\t\t(((x) ^ (y)) ^ (z))\n#define H2(x, y, z)\t\t\t((x) ^ ((y) ^ (z)))\n#define I(x, y, z)\t\t\t((y) ^ ((x) | ~(z)))\n\n/*\n* The MD5 transformation for all four rounds.\n*/\n#define STEP(f, a, b, c, d, x, t, s) \\\n\t(a) += f((b), (c), (d)) + (x) + (t); \\\n\t(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \\\n\t(a) += (b);\n\n/*\n* SET reads 4 input bytes in little-endian byte order and stores them\n* in a properly aligned word in host byte order.\n*\n* The check for little-endian architectures that tolerate unaligned\n* memory accesses is just an optimization.  Nothing will break if it\n* doesn't work.\n*/\n#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)\n#define SET(n) \\\n\t(*(MD5_u32plus *)&ptr[(n) * 4])\n#define GET(n) \\\n\tSET(n)\n#else\n#define SET(n) \\\n\t(ctx->block[(n)] = \\\n\t(MD5_u32plus)ptr[(n) * 4] | \\\n\t((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \\\n\t((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \\\n\t((MD5_u32plus)ptr[(n) * 4 + 3] << 24))\n#define GET(n) \\\n\t(ctx->block[(n)])\n#endif\n\n/*\n* This processes one or more 64-byte data blocks, but does NOT update\n* the bit counters.  There are no alignment requirements.\n*/\nstatic const void* body(MD5_CTX* ctx, const void* data, unsigned long size) {\n  const unsigned char* ptr;\n  MD5_u32plus a, b, c, d;\n  MD5_u32plus saved_a, saved_b, saved_c, saved_d;\n\n  ptr = static_cast<const unsigned char *>(data);\n\n  a = ctx->a;\n  b = ctx->b;\n  c = ctx->c;\n  d = ctx->d;\n\n  do {\n    saved_a = a;\n    saved_b = b;\n    saved_c = c;\n    saved_d = d;\n\n    /* Round 1 */\n    STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)\n    STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)\n    STEP(F, c, d, a, b, SET(2), 0x242070db, 17)\n    STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)\n    STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)\n    STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)\n    STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)\n    STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)\n    STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)\n    STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)\n    STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)\n    STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)\n    STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)\n    STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)\n    STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)\n    STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)\n\n    /* Round 2 */\n    STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)\n    STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)\n    STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)\n    STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)\n    STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)\n    STEP(G, d, a, b, c, GET(10), 0x02441453, 9)\n    STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)\n    STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)\n    STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)\n    STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)\n    STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)\n    STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)\n    STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)\n    STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)\n    STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)\n    STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)\n\n    /* Round 3 */\n    STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)\n    STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)\n    STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)\n    STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)\n    STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)\n    STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)\n    STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)\n    STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)\n    STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)\n    STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)\n    STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)\n    STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)\n    STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)\n    STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)\n    STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)\n    STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)\n\n    /* Round 4 */\n    STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)\n    STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)\n    STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)\n    STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)\n    STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)\n    STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)\n    STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)\n    STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)\n    STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)\n    STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)\n    STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)\n    STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)\n    STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)\n    STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)\n    STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)\n    STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)\n\n    a += saved_a;\n    b += saved_b;\n    c += saved_c;\n    d += saved_d;\n\n    ptr += 64;\n  }\n  while (size -= 64);\n\n  ctx->a = a;\n  ctx->b = b;\n  ctx->c = c;\n  ctx->d = d;\n\n  return ptr;\n}\n\nvoid MD5_Init(MD5_CTX* ctx) {\n  ctx->a = 0x67452301;\n  ctx->b = 0xefcdab89;\n  ctx->c = 0x98badcfe;\n  ctx->d = 0x10325476;\n\n  ctx->lo = 0;\n  ctx->hi = 0;\n}\n\nvoid MD5_Update(MD5_CTX* ctx, const void* data, unsigned long size) {\n  MD5_u32plus saved_lo;\n  unsigned long used, available;\n\n  saved_lo = ctx->lo;\n  if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)\n    ctx->hi++;\n  ctx->hi += size >> 29;\n\n  used = saved_lo & 0x3f;\n\n  if (used) {\n    available = 64 - used;\n\n    if (size < available) {\n      memcpy(&ctx->buffer[used], data, size);\n      return;\n    }\n\n    memcpy(&ctx->buffer[used], data, available);\n    data = static_cast<const unsigned char *>(data) + available;\n    size -= available;\n    body(ctx, ctx->buffer, 64);\n  }\n\n  if (size >= 64) {\n    data = body(ctx, data, size & ~static_cast<unsigned long>(0x3f));\n    size &= 0x3f;\n  }\n\n  memcpy(ctx->buffer, data, size);\n}\n\nvoid MD5_Final(unsigned char* result, MD5_CTX* ctx) {\n  unsigned long used, available;\n\n  used = ctx->lo & 0x3f;\n\n  ctx->buffer[used++] = 0x80;\n\n  available = 64 - used;\n\n  if (available < 8) {\n    memset(&ctx->buffer[used], 0, available);\n    body(ctx, ctx->buffer, 64);\n    used = 0;\n    available = 64;\n  }\n\n  memset(&ctx->buffer[used], 0, available - 8);\n\n  ctx->lo <<= 3;\n  ctx->buffer[56] = static_cast<uint8_t>(ctx->lo);\n  ctx->buffer[57] = static_cast<uint8_t>(ctx->lo >> 8);\n  ctx->buffer[58] = static_cast<uint8_t>(ctx->lo >> 16);\n  ctx->buffer[59] = static_cast<uint8_t>(ctx->lo >> 24);\n  ctx->buffer[60] = static_cast<uint8_t>(ctx->hi);\n  ctx->buffer[61] = static_cast<uint8_t>(ctx->hi >> 8);\n  ctx->buffer[62] = static_cast<uint8_t>(ctx->hi >> 16);\n  ctx->buffer[63] = static_cast<uint8_t>(ctx->hi >> 24);\n\n  body(ctx, ctx->buffer, 64);\n\n  result[0] = static_cast<uint8_t>(ctx->a);\n  result[1] = static_cast<uint8_t>(ctx->a >> 8);\n  result[2] = static_cast<uint8_t>(ctx->a >> 16);\n  result[3] = static_cast<uint8_t>(ctx->a >> 24);\n  result[4] = static_cast<uint8_t>(ctx->b);\n  result[5] = static_cast<uint8_t>(ctx->b >> 8);\n  result[6] = static_cast<uint8_t>(ctx->b >> 16);\n  result[7] = static_cast<uint8_t>(ctx->b >> 24);\n  result[8] = static_cast<uint8_t>(ctx->c);\n  result[9] = static_cast<uint8_t>(ctx->c >> 8);\n  result[10] = static_cast<uint8_t>(ctx->c >> 16);\n  result[11] = static_cast<uint8_t>(ctx->c >> 24);\n  result[12] = static_cast<uint8_t>(ctx->d);\n  result[13] = static_cast<uint8_t>(ctx->d >> 8);\n  result[14] = static_cast<uint8_t>(ctx->d >> 16);\n  result[15] = static_cast<uint8_t>(ctx->d >> 24);\n\n  memset(ctx, 0, sizeof(*ctx));\n}\n\nstd::string md5(const std::string& text) {\n  MD5_CTX ctx;\n  MD5_Init(&ctx);\n\n  unsigned char hash[16];\n  MD5_Update(&ctx, text.data(), text.size());\n  MD5_Final(hash, &ctx);\n\n  std::ostringstream ss;\n  for (unsigned char c : hash) {\n    ss << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(c);\n  }\n  return ss.str();\n}\n\n#endif\n"
  },
  {
    "path": "core/md5.h",
    "content": "/*\n * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.\n * MD5 Message-Digest Algorithm (RFC 1321).\n *\n * Homepage:\n * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5\n *\n * Author:\n * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>\n *\n * This software was written by Alexander Peslyak in 2001.  No copyright is\n * claimed, and the software is hereby placed in the public domain.\n * In case this attempt to disclaim copyright and place the software in the\n * public domain is deemed null and void, then the software is\n * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the\n * general public under the following terms:\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted.\n *\n * There's ABSOLUTELY NO WARRANTY, express or implied.\n *\n * See md5.c for more information.\n */\n\n#ifdef HAVE_OPENSSL\n#include <openssl/md5.h>\n#elif !defined(_MD5_H)\n#define _MD5_H\n\n#include <string>\n\n/* Any 32-bit or wider unsigned integer data type will do */\ntypedef unsigned int MD5_u32plus;\n\ntypedef struct {\n  MD5_u32plus lo, hi;\n  MD5_u32plus a, b, c, d;\n  unsigned char buffer[64];\n  MD5_u32plus block[16];\n} MD5_CTX;\n\nextern void MD5_Init(MD5_CTX* ctx);\nextern void MD5_Update(MD5_CTX* ctx, const void* data, unsigned long size);\nextern void MD5_Final(unsigned char* result, MD5_CTX* ctx);\n\n[[nodiscard]] std::string md5(const std::string& text);\n\n#endif\n"
  },
  {
    "path": "core/md5_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/md5.h\"\n#include <vector>\n\nTEST(Md5Test, Welcome) {\n  EXPECT_EQ(\"f851256dff2a8825ad4af615111b6a4f\", md5(\"WELCOME\"));\n}\n"
  },
  {
    "path": "core/net.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2016-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/net.h\"\n\n// Put these before the windows and os/2 includes. This was barfing on Win64\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/socket_exceptions.h\"\n#include \"core/strings.h\"\n\n#ifdef _WIN32\n\n#pragma comment(lib, \"Ws2_32.lib\")\n#pragma comment(lib, \"Mswsock.lib\")\n#pragma comment(lib, \"AdvApi32.lib\")\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif \n\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif \n\n#ifndef NOCRYPT\n#define NOCRYPT // Disable include of wincrypt.h\n#endif \n\n#include <winsock2.h>\n#include <MSWSock.h>\n#include <WS2tcpip.h>\n\n#else\n\n#include <fcntl.h>\n#include <unistd.h>\n\n#endif // _WIN32\n\n#ifdef __OS2__\n#include <libcx/net.h>\n#endif  // __OS2__\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\nbool InitializeSockets() {\n#ifdef _WIN32\n  WSADATA wsadata;\n  const auto result = WSAStartup(MAKEWORD(2, 2), &wsadata);\n  if (result != 0) {\n    LOG(ERROR) << \"WSAStartup failed with error: \" << result;\n    return false;\n  }\n#endif // _WIN32\n  return true;\n}\n\nstd::optional<std::string> GetRemotePeerAddress(SOCKET socket) {\n  sockaddr_in addr{};\n  socklen_t nAddrSize = sizeof(sockaddr);\n\n  const auto result = getpeername(socket, reinterpret_cast<sockaddr*>(&addr), &nAddrSize);\n  if (result == -1) {\n    return std::nullopt;\n  }\n\n  char buf[255];\n  std::string ip = inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf));\n  return ip;\n}\n\nstd::optional<std::string> GetRemotePeerHostname(SOCKET socket) {\n  sockaddr_in addr{};\n  socklen_t nAddrSize = sizeof(sockaddr);\n\n  char host[1024];\n  char service[81];\n\n  if (getpeername(socket, reinterpret_cast<sockaddr*>(&addr), &nAddrSize) == -1) {\n    return std::nullopt;\n  }\n\n  // pretend sa is full of good information about the host and port...\n  if (getnameinfo(reinterpret_cast<sockaddr*>(&addr), sizeof(addr), host, sizeof(host), service,\n                  sizeof(service), 0) != 0) {\n    return std::nullopt;\n  }\n\n  return std::string(host);\n}\n\nSOCKET CreateListenSocket(int port) {\n  struct sockaddr_in my_addr{};\n  memset(&my_addr, 0, sizeof(sockaddr_in));\n\n  const auto sock = socket(AF_INET, SOCK_STREAM, 0);\n  if (sock == INVALID_SOCKET) {\n    throw socket_error(\"Unable to create socket [socket]\");\n  }\n  int optval = 1;\n  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&optval),\n                 sizeof(optval)) == -1) {\n    throw socket_error(\"Unable to create socket [SO_REUSEADDR]\");\n  }\n  if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<char*>(&optval),\n                 sizeof(optval)) == -1) {\n    throw socket_error(\"Unable to create socket [SO_KEEPALIVE]\");\n  }\n  // Try to set nodelay.\n  setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&optval), sizeof(optval));\n\n  my_addr.sin_family = AF_INET;\n  my_addr.sin_port = htons(static_cast<decltype(my_addr.sin_port)>(port));\n  memset(&(my_addr.sin_zero), 0, 8);\n  my_addr.sin_addr.s_addr = INADDR_ANY;\n\n  if (bind(sock, reinterpret_cast<sockaddr*>(&my_addr), sizeof(my_addr)) == -1) {\n    const auto msg =\n        StrCat(\"Error binding to socket, make sure nothing else is listening on port: \", port,\n               \"; errno: \", errno);\n    throw socket_error(msg);\n  }\n  if (listen(sock, 10) == -1) {\n    throw socket_error(StrCat(\"Error listening. errno: \", errno));\n  }\n\n  return sock;\n}\n\nbool is_rfc1918_private_address(const std::string& ip) {\n  // RFC 1918 defined private address space:\n  // 10.0.0.0/8 IP addresses: 10.0.0.0  10.255.255.255\n  // 172.16.0.0/12 IP addresses: 172.16.0.0  172.31.255.255\n  // 192.168.0.0/16 IP addresses: 192.168.0.0  192.168.255.255\n  auto parts = SplitString(ip, \".\");\n  if (parts.size() != 4) {\n    return false;\n  }\n  \n  std::vector<int> o;\n  o.reserve(4);\n  for (const auto& part : parts) {\n    const auto num = to_number<int>(part);\n    // Validate octet is in valid range (0-255)\n    if (num < 0 || num > 255) {\n      return false;\n    }\n    o.push_back(num);\n  }\n  \n  if (o.size() != 4) {\n    return false;\n  }\n  \n  const auto octet0 = o.at(0);\n  const auto octet1 = o.at(1);\n  \n  // 10.0.0.0/8 - first octet must be exactly 10\n  if (octet0 == 10) {\n    return true;\n  }\n  \n  // 172.16.0.0/12 - first octet must be 172, second octet must be 16-31\n  if (octet0 == 172 && octet1 >= 16 && octet1 <= 31) {\n    return true;\n  }\n  \n  // 192.168.0.0/16 - first octet must be 192, second octet must be 168\n  if (octet0 == 192 && octet1 == 168) {\n    return true;\n  }\n  return false;\n}\n\n/**\n * DBSRBL uses a special format for the IP addresses, so this function\n * maps the FQDN a.b.c.d to d.c.b.a.rbl_address so it may be used to\n * lookup against a DNSRBL.\n */\nstatic std::string dns_rbl_name(const std::string& address, const std::string& rbl_address) {\n  std::string out;\n  auto v = SplitString(address, \".\");\n  for (auto it = v.rbegin(); it != v.rend(); ++it) {\n    out.append(*it);\n    out.push_back('.');\n  }\n  out.append(rbl_address);\n  return out;\n}\n\nbool on_dns_dbl(const std::string& address, const std::string& rbl_address) {\n  const auto s = dns_rbl_name(address, rbl_address);\n  struct addrinfo* res = nullptr;\n  const auto result = getaddrinfo(s.c_str(), nullptr, nullptr, &res);\n  if (result != 0) {\n    return false;\n  }\n  freeaddrinfo(res);\n  return true;\n}\n\nint get_dns_cc(const std::string& address, const std::string& rbl_address) {\n  const auto s = dns_rbl_name(address, rbl_address);\n  struct addrinfo* res = nullptr;\n  const auto result = getaddrinfo(s.c_str(), nullptr, nullptr, &res);\n  if (result != 0) {\n    return 0;\n  }\n\n  auto at_exit = finally([res] { freeaddrinfo(res); });\n  if (res->ai_family == AF_INET) {\n    const auto ipv4 = reinterpret_cast<struct sockaddr_in*>(res->ai_addr);\n    const uint32_t b = htonl(ipv4->sin_addr.s_addr) & 0x0000ffff;\n    return b;\n  }\n  return 0;\n}\n\nbool SetBlockingMode(SOCKET sock) {\n  if (sock == INVALID_SOCKET) {\n    return false;\n  }\n\n#ifdef _WIN32\n  u_long blocking = 1;\n  return ioctlsocket(sock, FIONBIO, &blocking) == NO_ERROR;\n#else  // _WIN32\n  int flags = fcntl(sock, F_GETFL, 0 /* ignored */);\n  flags &= ~O_NONBLOCK;\n  return fcntl(sock, F_SETFL, flags) != -1;\n#endif // _WIN32\n}\n\nSocketSet::SocketSet()\n  : SocketSet(2) {\n};\n\nSocketSet::SocketSet(int timeout_seconds)\n  : timeout_seconds_(timeout_seconds) {\n};\n\nSocketSet::~SocketSet() = default;\n\nbool SocketSet::add(int port, const socketset_accept_fn& fn, const std::string& description) {\n  auto s = CreateListenSocket(port);\n  if (s == INVALID_SOCKET) {\n    return false;\n  }\n  LOG(INFO) << \"Listening to \" << description << \" on port: \" << port;\n  socket_fn_map_.emplace(s, fn);\n  socket_port_map_.emplace(s, port);\n  return true;\n}\n\nbool SocketSet::Run(std::atomic<bool>& exit_signal) {\n  while (true) {\n    if (exit_signal.load() == true) {\n      return true;\n    }\n    if (!RunOnce()) {\n      return false;\n    }\n  }\n}\n\nbool SocketSet::RunOnce() {\n  SOCKET max_fd = 0;\n  fd_set fds{};\n  FD_ZERO(&fds);\n  for (const auto& e : socket_fn_map_) {\n    if (e.first > max_fd) {\n      max_fd = e.first;\n    }\n    FD_SET(e.first, &fds);\n  }\n\n  if (max_fd == INVALID_SOCKET) {\n    LOG(ERROR) << \"Nothing to do!\";\n    return false;\n  }\n\n  VLOG(3) << \"About to call select. (\" << max_fd << \"); timeout: \"\n\t  << timeout_seconds_;\n  int status;\n  if (timeout_seconds_ > 0) {\n    timeval timeout{};\n    timeout.tv_usec = 0;\n    timeout.tv_sec = timeout_seconds_;\n    status = select(max_fd + 1, &fds, nullptr, nullptr, &timeout);\n  } else {\n    status = select(max_fd + 1, &fds, nullptr, nullptr, nullptr);\n  }\n\n  VLOG(3) << \"After select; status: \" << status << \"; errno: \" << errno;\n  if (status < 0 && errno == EINTR) {\n    LOG(ERROR) << \"Caught signal calling select\";\n    // return true so we can check for exit signal.\n    return true;\n  }\n  if (status < 0) {\n    LOG(ERROR) << \"Error calling select; errno: [\" << errno << \"]\";\n    // return false here since we know this wasn't a signal.\n    return false;\n  }\n  if (status == 0) {\n    // Timeout expired.  Keep on trucking.\n    VLOG(4) << \"timeout expired on select\";\n    return true;\n  }\n  VLOG(4) << \"After status checks for: \" << status;\n\n  for (const auto& e : socket_fn_map_) {\n    VLOG(4) << \"Checking Socket map for: \" << e.first;\n    if (FD_ISSET(e.first, &fds)) {\n      VLOG(4) << \"FD Set: \" << e.first;\n      socklen_t addr_size = sizeof(sockaddr_in);\n      struct sockaddr_in saddr{};\n      const auto client_sock = accept(e.first, reinterpret_cast<sockaddr*>(&saddr), &addr_size);\n\n#ifdef _WIN32\n      auto newvalue = SO_SYNCHRONOUS_NONALERT;\n      setsockopt(client_sock, SOL_SOCKET, SO_OPENTYPE, reinterpret_cast<char*>(&newvalue),\n                 sizeof(newvalue));\n#endif\n      VLOG(4) << \"Calling e.second\";\n      e.second({client_sock, socket_port_map_.at(e.first)});\n    }\n  }\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/net.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                 Copyright (C)2016-2022, WWIV Software Services         */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_NET_H\n#define INCLUDED_CORE_NET_H\n\n#include <atomic>\n#include <functional>\n#include <map>\n#include <optional>\n#include <string>\n\n#if defined( _WIN32 )\n\ntypedef int socklen_t;\n\n#if defined(_WIN64)\ntypedef unsigned __int64 SOCKET;\n#else\ntypedef unsigned int SOCKET;\n#endif\n\n#ifndef INVALID_SOCKET\n#define INVALID_SOCKET (SOCKET)(~0)\n#endif\n\n#else\n\n#include <netdb.h>\n#include <unistd.h>\n#include <arpa/inet.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n\ntypedef int HANDLE;\ntypedef int SOCKET;\nconstexpr int INVALID_SOCKET = -1;\nconstexpr int SOCKET_ERROR = -1;\nconstexpr int NO_ERROR = -1;\n#define closesocket(s) ::close(s)\n#endif // _WIN32\n\nnamespace wwiv::core {\n\nbool InitializeSockets();\n\nstd::optional<std::string> GetRemotePeerAddress(SOCKET socket);\nstd::optional<std::string> GetRemotePeerHostname(SOCKET socket);\n\nSOCKET CreateListenSocket(int port);\n\n/**\n * Returns true if address is a private IP address as defined in RFC1918.\n */\nbool is_rfc1918_private_address(const std::string& address);\n\n/**\n * Returns true if address is contained in the DNSRBL rbl_address.\n */\nbool on_dns_dbl(const std::string& address, const std::string& rbl_address);\n\n/**\n * Gets the DNS country code using rbl_address\n */\nint get_dns_cc(const std::string& address, const std::string& rbl_address);\n\n/** Sets the socket to blocking mode. */\nbool SetBlockingMode(SOCKET sock);\n\n/** \n * Once a socket is accepted from the remote system.  Return\n * the socket and also the port that it was accepted from.\n */\nstruct accepted_socket_t {\n  SOCKET client_socket;\n  int port;\n};\n\n/**\n * Handles select over a set of sockets.\n */\nclass SocketSet final {\npublic:\n  SocketSet();\n  explicit SocketSet(int timeout_seconds);\n  ~SocketSet();\n\n  typedef std::function<void(accepted_socket_t)> socketset_accept_fn;\n\n  /** \n   * Adds a port that the SocketSet will listen to and the function (fn)\n   * that will be invoked on the current thread when a connection is\n   * accepted.  If fn should be handled asynchronously, then it should\n   * dispatch to a worker thread.\n   */\n  bool add(int port, const socketset_accept_fn& fn, const std::string& description);\n\n  /** \n   * Runs the select/accept/execute loop until exit_signal is true.\n   * returning false on error or true of signaled to exit.\n   */\n  bool Run(std::atomic<bool>& exit_signal);\n\nprivate:\n  /** Runs the select/accept/execute loops once, returning false on error. */\n  bool RunOnce();\n\n  std::map<SOCKET, int> socket_port_map_;\n  std::map<SOCKET, socketset_accept_fn> socket_fn_map_;\n  const int timeout_seconds_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/net_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                   Copyright (C)2023, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/net.h\"\n#include <string>\n\nusing namespace wwiv::core;\n\nclass NetTest : public ::testing::Test {\npublic:\n  NetTest() {}\n};\n\nTEST_F(NetTest, Rfc1918_In) {\n  // 10.0.0.0/8 range\n  ASSERT_TRUE(is_rfc1918_private_address(\"10.0.0.0\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"10.2.3.4\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"10.255.255.255\"));\n  \n  // 172.16.0.0/12 range (16 contiguous Class B networks)\n  ASSERT_TRUE(is_rfc1918_private_address(\"172.16.0.0\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"172.16.3.3\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"172.17.1.2\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"172.31.255.255\"));\n  \n  // 192.168.0.0/16 range\n  ASSERT_TRUE(is_rfc1918_private_address(\"192.168.0.0\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"192.168.12.34\"));\n  ASSERT_TRUE(is_rfc1918_private_address(\"192.168.255.255\"));\n}\n\nTEST_F(NetTest, Rfc1918_Out) {\n  // Just outside 10.0.0.0/8\n  ASSERT_FALSE(is_rfc1918_private_address(\"9.255.255.255\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"11.0.0.0\"));\n  \n  // Just outside 172.16.0.0/12\n  ASSERT_FALSE(is_rfc1918_private_address(\"172.15.255.255\")); // One below lower bound\n  ASSERT_FALSE(is_rfc1918_private_address(\"172.32.0.0\"));      // One above upper bound\n  ASSERT_FALSE(is_rfc1918_private_address(\"172.59.191.140\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"172.255.255.255\"));\n  \n  // Just outside 192.168.0.0/16\n  ASSERT_FALSE(is_rfc1918_private_address(\"192.167.255.255\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"192.169.0.0\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"192.162.12.34\"));\n  \n  // Other public addresses\n  ASSERT_FALSE(is_rfc1918_private_address(\"1.2.3.4\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"8.8.8.8\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"127.0.0.1\"));\n}\n\nTEST_F(NetTest, Rfc1918_Malformed) {\n  ASSERT_FALSE(is_rfc1918_private_address(\"\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"1.2.3.4.5\"));\n  ASSERT_FALSE(is_rfc1918_private_address(\"Geddy Lee\"));\n}\n"
  },
  {
    "path": "core/numbers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/numbers.h\"\n\nnamespace wwiv::core {\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/numbers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_CORE_NUMBERS_H\n#define INCLUDED_WWIV_CORE_NUMBERS_H\n\n#include \"core/strings.h\"\n#include <string>\n\ntemplate<typename T>\nT bytes_to_k(T b) {\n  if (b <= 0) {\n    return static_cast<T>(0);\n  }\n  return static_cast<T>((b + 1023) / 1024);\n}\n\ntemplate<typename T>\nstd::string humanize(T num) {\n  static constexpr T KB = 1024;\n  static constexpr T MB = KB * 1024;\n  static constexpr T GB = MB * 1024;\n  if (num >= GB) {\n    return wwiv::strings::StrCat(std::to_string(num / GB), \"G\");\n  }\n  if (num >= MB) {\n    return wwiv::strings::StrCat(std::to_string(num / MB), \"M\");\n  }\n  if (num >= KB) {\n    return wwiv::strings::StrCat(std::to_string(num / KB), \"k\");\n  }\n  return wwiv::strings::StrCat(std::to_string(bytes_to_k(num)), \"k\");\n}\n\n#endif"
  },
  {
    "path": "core/os.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/os.h\"\n\n#include \"core/strings.h\"\n#include <chrono>\n#include <random>\n\nusing namespace std::chrono;\nusing namespace wwiv::strings;\n\nnamespace wwiv::os {\n\nbool wait_for(std::function<bool()> predicate, duration<double> d) {\n  auto now = steady_clock::now();\n  const auto end = now + d;\n  while (!predicate() && now < end) {\n    now = steady_clock::now();\n    sleep_for(milliseconds(100));\n  }\n  return predicate();\n}\n\nvoid yield() {\n  // TODO(rushfan): use this_thread::yield once it's been\n  // tested on MSVC and GCC (Maybe with MSVC 2015).\n  // Then we'll call this:\n  // std::this_thread::yield();\n\n  // Also TODO is to investigate if we should use sleep(1) vs. sleep(0) so that we'll\n  // yield to threads on other processors.\n  // See http://stackoverflow.com/questions/1413630/switchtothread-thread-yield-vs-thread-sleep0-vs-thead-sleep1\n  sleep_for(milliseconds(0));\n}\n\nint random_number(int max_value) {\n  static std::random_device rdev;\n  static std::default_random_engine re(rdev());\n\n  // Can't be const or it won't compile on gcc.\n  std::uniform_int_distribution<int> dist(0, max_value);\n  return dist(re);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/os.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_CORE_OS_H\n#define INCLUDED_WWIV_CORE_OS_H\n\n#include \"core/wwivport.h\"\n#include <chrono>\n#include <cstdint>\n#include <functional>\n#include <string>\n\nnamespace wwiv::os {\n\n// Sleeps for a duration of time d, or until predicate returns true.\n// returns the value of predicate.\nbool wait_for(std::function<bool()> predicate, std::chrono::duration<double> d);\n\n// Sleeps for a duration of time d\nvoid sleep_for(std::chrono::duration<double> d);\n\n// Yields the CPU to other threads or processes.\nvoid yield();\n\n// Gets the OS Version Number.\nstd::string os_version_string();\n\n// plays a sound at frequency for duration\nvoid sound(uint32_t frequency, std::chrono::duration<double> d);\n\n// returns a random number.\nint random_number(int max_value);\n\nstd::string environment_variable(const std::string& variable_name);\nbool set_environment_variable(const std::string& variable_name, const std::string& value);\n\n// Returns a stacktrace as a string.\nstd::string stacktrace();\n\n// Gets the PID\npid_t get_pid();\n\n// terminates a process\nbool terminate_process(pid_t pid);\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/os_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/os.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include <chrono>\n#include <cstdint>\n#include <cstdlib>\n#include <sstream>\n\n// OS/2 headers\n#define INCL_DOSPROCESS\n#include <os2.h>\n#include <sys/process.h>\n\nusing namespace std::chrono;\nusing namespace wwiv::strings;\n\nnamespace wwiv::os {\n\nvoid sleep_for(duration<double> d) {\n  auto count = duration_cast<milliseconds>(d).count();\n  if (count > std::numeric_limits<uint32_t>::max()) {\n    count = std::numeric_limits<uint32_t>::max();\n  }\n  ::DosSleep(static_cast<ULONG>(count));\n}\n\nvoid sound(uint32_t frequency, duration<double> d) {\n  const auto count = duration_cast<milliseconds>(d).count();\n  DosBeep(frequency, static_cast<uint32_t>(count));\n}\n\nstd::string os_version_string() {\n  return \"OS/2\";\n}\n\nbool set_environment_variable(const std::string& variable_name, const std::string& value) {\n  return setenv(variable_name.c_str(), value.c_str(), 1) == 0;\n}\n\nstd::string environment_variable(const std::string& variable_name) {\n  if (const auto* s = getenv(variable_name.c_str()); s != nullptr) {\n    return s;\n  }\n  return {};\n}\n\nstd::string stacktrace() { return {};\n}\n\npid_t get_pid() { return getpid(); }\n\nbool terminate_process(pid_t pid) {\n  return false;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/os_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include <iostream>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::os;\nusing namespace wwiv::strings;\n\n\nTEST(OsTest, WaitFor_PredicateTrue) {\n  auto predicate = []() { return true; };\n  const auto start = system_clock::now();\n  const auto d = seconds(1);\n  const auto is_predicate_true = wait_for(predicate, d);\n  ASSERT_TRUE(system_clock::now() < start + d);\n  EXPECT_TRUE(is_predicate_true);\n}\n\nTEST(OsTest, WaitFor_PredicateFalse) {\n  auto predicate = []() { return false; };\n  const auto start = system_clock::now();\n  const auto d = milliseconds(100);\n  const auto is_predicate_true = wait_for(predicate, d);\n  ASSERT_TRUE(system_clock::now() >= start + d);\n  EXPECT_FALSE(is_predicate_true);\n}\n\nTEST(OsTest, SleepFor) {\n  const auto start = system_clock::now();\n  const auto d = milliseconds(100);\n  sleep_for(d);\n  const auto now = system_clock::now();\n  ASSERT_TRUE(now - start - d < d) << (now - start - d).count();\n}\n\nTEST(OsTest, EnvironmentVariable_Exists) {\n  char s[81];\n  strcpy(s, \"QWERTYUIOP=ASDF2\");\n  ASSERT_EQ(0, putenv(s));\n\n  EXPECT_EQ(\"ASDF2\", environment_variable(\"QWERTYUIOP\"));\n}\n\nTEST(OsTest, EnvironmentVariable_DoesNotExist) {\n  std::string name = test_info_->name();\n  StringUpperCase(&name);\n  EXPECT_EQ(\"\", environment_variable(name));\n}\n\nTEST(OsTest, SetEnvironmentVariable) {\n  std::string name = test_info_->name();\n  StringUpperCase(&name);\n  // Clear the environment\n  std::cout << name;\n  ASSERT_EQ(\"\", environment_variable(name));\n  ASSERT_TRUE(set_environment_variable(name, \"ASDF\"));\n  ASSERT_EQ(\"ASDF\", environment_variable(name));\n}\n"
  },
  {
    "path": "core/os_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                  Copyright (C)2015-2020 WWIV Software Services         */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/os.h\"\n\n#include \"core/strings.h\"\n#include \"core/file.h\"\n#include \"fmt/format.h\"\n#include <string>\n\n#include <signal.h>\n#include <unistd.h>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::os {\n\nvoid sleep_for(duration<double> d) {\n  // usleep is microseconds.\n  const auto ns = duration_cast<microseconds>(d);\n  usleep(static_cast<__useconds_t>(ns.count()));\n}\n\nvoid sound(uint32_t frequency, duration<double> d) {\n  // NOP\n}\n\nstd::string os_version_string() {\n#if defined ( __linux__ )\n  const auto fn = FilePath(\"/proc/sys/kernel\", \"osrelease\").string();\n  if (File::Exists(fn)) {\n    File info(fn);\n    FILE* kernel_file;\n    struct k_version { unsigned major, minor, update, iteration; };\n    struct k_version k_version;\n    kernel_file = fopen(\"/proc/sys/kernel/osrelease\",\"r\");\n    fscanf(kernel_file,\"%u%*c%u%*c%u%*c%u\",\n\t   &k_version.major,\n\t   &k_version.minor,\n\t   &k_version.update,\n\t   &k_version.iteration);\n    fclose(kernel_file);\n    char osrelease[100];\n    sprintf(osrelease,\"%u.%u.%u-%u\", k_version.major,\n\t    k_version.minor,\n\t    k_version.update,\n\t    k_version.iteration);\n    return fmt::format(\"Linux {}\", osrelease);\n  }\n  return \"Linux\";\n#elif defined ( __APPLE__ )\n  return \"MacOSX\"; // fmt::format(\"{} {}\", GetOSNameString(), GetMacVersionString());\n#elif defined(__OS2__)\n  return \"OS/2\";\n#elif defined(__FreeBSD__)\n  return \"FreeBSD\";\n#elif defined(__OpenBSD__)\n  return \"OpenBSD\";\n#elif defined(__NetBSD__)\n  return \"NetBSD\";\n#elif defined(BSD)\n  return \"BSD\";\n#elif defined(__solaris__)\n  return \"Solaris\";\n#elif defined(__sun__)\n  return \"SunOS\";\n#elif defined(__gnu__)\n  return \"GNU/Hurd\";\n#elif defined(__QNX__)\n  return \"QNX\";\n#elif defined(__unix__)\n  return \"UNIX\";\n#elif defined(__HAIKU__)\n  return \"Haiku\";\n#endif\n  return \"UNKNOWN OS\";\n}\n\nbool set_environment_variable(const std::string& variable_name, const std::string& value) {\n  return setenv(variable_name.c_str(), value.c_str(), 1) == 0;\n}\n\nstd::string environment_variable(const std::string& variable_name) {\n  if (const auto* s = getenv(variable_name.c_str()); s != nullptr) {\n    return s;\n  }\n  return {};\n}\n\nstd::string stacktrace() { \n  return {};\n}\n\npid_t get_pid() {\n  return getpid();\n}\n\nbool terminate_process(pid_t pid) {\n  kill(pid, SIGKILL);\n  return true;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/os_win.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                 Copyright (C)2015-2022, WWIV Software Services         */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/os.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include <chrono>\n#include <cstdint>\n#include <cstdlib>\n#include <sstream>\n\n// Windows headers\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif \n\n#ifndef NOCRYPT\n#define NOCRYPT // Disable include of wincrypt.h\n#endif\n\n#include <Windows.h>\n#include <DbgHelp.h>\n#include <process.h>\n\n#ifdef min\n#undef min\n#endif\n#ifdef max\n#undef max\n#endif\n\n\n#pragma comment (lib, \"DbgHelp.lib\")\n\nusing namespace std::chrono;\nusing namespace wwiv::strings;\n\nnamespace wwiv::os {\n\nvoid sleep_for(duration<double> d) {\n  auto count = duration_cast<milliseconds>(d).count();\n  if (count > std::numeric_limits<uint32_t>::max()) {\n    count = std::numeric_limits<uint32_t>::max();\n  }\n  Sleep(static_cast<uint32_t>(count));\n}\n\nvoid sound(uint32_t frequency, duration<double> d) {\n  const auto count = duration_cast<milliseconds>(d).count();\n  Beep(frequency, static_cast<uint32_t>(count));\n}\n\nstd::string os_version_string() {\n  return \"Windows\";\n}\n\nbool set_environment_variable(const std::string& variable_name, const std::string& value) {\n  return ::SetEnvironmentVariable(variable_name.c_str(), value.c_str()) ? true : false;\n}\n\nstd::string environment_variable(const std::string& variable_name) {\n  // See http://techunravel.blogspot.com/2011/08/win32-env-variable-pitfall-of.html\n  // Use Win32 functions to get since we do to set...\n  char buffer[4096];\n  if (const auto size = GetEnvironmentVariable(variable_name.c_str(), buffer, 4096); size == 0) {\n    // error or does not exits.\n    return \"\";\n  }\n  return std::string(buffer);\n}\n\nstd::string stacktrace() {\n  // ReSharper disable once CppUseAuto\n  // ReSharper disable once CppLocalVariableMayBeConst\n  auto process = GetCurrentProcess();\n  if (process == nullptr) {\n    return \"\";\n  }\n  SymInitialize(process, nullptr, TRUE);\n  void* stack[100];\n  const auto frames = CaptureStackBackTrace(0, 100, stack, nullptr);\n  auto* symbol = static_cast<SYMBOL_INFO *>(calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1));\n  if (symbol == nullptr) {\n    return \"\";\n  }\n  symbol->MaxNameLen = 255;\n  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);\n\n  std::stringstream out;\n  // start at one to skip this current frame.\n  for (auto i = 1; i < frames; i++) {\n    if (SymFromAddr(process, reinterpret_cast<DWORD64>(stack[i]), nullptr, symbol)) {\n      out << frames - i - 1 << \": \" << symbol->Name << \" = \" << std::hex << symbol->Address;\n    }\n    IMAGEHLP_LINE64 line;\n    DWORD displacement;\n    if (SymGetLineFromAddr64(process, reinterpret_cast<DWORD64>(stack[i]), &displacement, &line)) {\n      out << \" (\" << line.FileName << \": \" << std::dec << line.LineNumber << \") \";\n    }\n    out << std::endl;\n  }\n  free(symbol);\n  return out.str();\n}\n\npid_t get_pid() {\n  return _getpid();\n}\n\nbool terminate_process(pid_t pid) {\n  return TerminateProcess(reinterpret_cast<HANDLE>(pid), 127);\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/parser/ast.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/parser/ast.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <iomanip>\n#include <memory>\n#include <sstream>\n#include <stack>\n#include <stdexcept>\n#include <utility>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::core::parser {\n\nparse_error::parse_error(const std::string& m)\n      : ::std::runtime_error(m) {}\n\n///////////////////////////////////////////////////////////////////////////\n// Factor\n\nstd::string to_string(Operator o) {\n  switch (o) {\n  case Operator::add:\n    return \"add\";\n  case Operator::div:\n    return \"div\";\n  case Operator::eq:\n    return \"eq\";\n  case Operator::ge:\n    return \"ge\";\n  case Operator::gt:\n    return \"gt\";\n  case Operator::le:\n    return \"le\";\n  case Operator::mul:\n    return \"mul\";\n  case Operator::ne:\n    return \"ne\";\n  case Operator::sub:\n    return \"sub\";\n  case Operator::logical_or:\n    return \"or\";\n  case Operator::logical_and:\n    return \"and\";\n  case Operator::lt:\n    return \"lt\";\n  case Operator::UNKNOWN:\n    return fmt::format(\"UNKNOWN ({})\", static_cast<int>(o));\n  }\n  return fmt::format(\"UNKNOWN ({})\", static_cast<int>(o));\n}\n\nstd::string to_symbol(Operator o) {\n  switch (o) {\n  case Operator::add:\n    return \"+\";\n  case Operator::div:\n    return \"/\";\n  case Operator::eq:\n    return \"==\";\n  case Operator::ge:\n    return \">=\";\n  case Operator::gt:\n    return \">\";\n  case Operator::le:\n    return \"<=\";\n  case Operator::lt:\n    return \"<\";\n  case Operator::mul:\n    return \"*\";\n  case Operator::ne:\n    return \"!=\";\n  case Operator::sub:\n    return \"-\";\n  case Operator::logical_or:\n    return \"||\";\n  case Operator::logical_and:\n    return \"&&\";\n  case Operator::UNKNOWN:\n    return fmt::format(\"UNKNOWN ({})\", static_cast<int>(o));\n  }\n  return fmt::format(\"UNKNOWN ({})\", static_cast<int>(o));\n}\n\nstd::string to_string(const AstNode& n) { \n  return n.ToString();\n}\n\nstd::string to_string(AstType t) {\n  switch (t) {\n  case AstType::LOGICAL_OP:\n    return \"LOGICAL_OP\";\n  case AstType::BINOP:\n    return \"binop\";\n  case AstType::UNOP:\n    return \"unop\";\n  case AstType::PAREN:\n    return \"paren\";\n  case AstType::EXPR:\n    return \"expr\";\n  case AstType::FACTOR:\n    return \"factor\";\n  case AstType::TAUTOLOGY:\n    return \"tautology\";\n  case AstType::AST_ERROR:\n    return \"error\";\n  case AstType::ROOT:\n    return \"root\";\n  }\n  return \"unknown\";\n}\n\n///////////////////////////////////////////////////////////////////////////\n// Factor\n\nFactor::Factor(FactorType t, int v, std::string s)\n    : Expression(AstType::FACTOR), factor_type_(t), val(v), sval(std::move(s)) {}\n\nstd::string to_string(FactorType t) {\n  switch (t) {\n  case FactorType::int_value:\n    return \"int_value\";\n  case FactorType::string_val:\n    return \"string_val\";\n  case FactorType::variable:\n    return \"variable\";\n  }\n  return \"FactorType::UNKNOWN\";\n}\n\nstd::string Factor::ToString(int indent) const {\n  auto pad = std::string(indent, ' ');\n  return fmt::format(\"{}Factor #{}: {} '{}'\", pad, id(), to_string(factor_type_),\n                     factor_type_ == FactorType::int_value ? std::to_string(val) : sval);\n}\n\nvoid Factor::accept(AstVisitor* visitor) { visitor->visit(this); }\n\nstatic std::unique_ptr<Factor> createFactor(const Token& token) {\n  const auto& l = token.lexeme;\n\n  if (token.type == TokenType::string || token.type == TokenType::character) {\n    return std::make_unique<String>(l);\n  } else if (isdigit(l.front())) {\n    return std::make_unique<Number>(to_number<int>(l));\n  } else {\n    return std::make_unique<Variable>(l);\n  }\n}\n\nstatic std::unique_ptr<LogicalOperatorNode> createLogicalOperator(const Token& token) {\n  switch (token.type) {\n  case TokenType::logical_or:\n    return std::make_unique<LogicalOperatorNode>(Operator::logical_or);\n  case TokenType::logical_and:\n    return std::make_unique<LogicalOperatorNode>(Operator::logical_and);\n  }\n  throw parse_error(fmt::format(\"Unexpected token found trying to create logical operator: \",\n                                to_string(token)));\n}\n\nstatic std::unique_ptr<BinaryOperatorNode> createBinaryOperator(const Token& token) {\n  switch (token.type) {\n  case TokenType::add:\n    return std::make_unique<BinaryOperatorNode>(Operator::add);\n  case TokenType::assign:\n    throw parse_error(\"Assignment operators are not allowed.\");\n  case TokenType::div:\n    return std::make_unique<BinaryOperatorNode>(Operator::div);\n  case TokenType::eq:\n    return std::make_unique<BinaryOperatorNode>(Operator::eq);\n  case TokenType::ge:\n    return std::make_unique<BinaryOperatorNode>(Operator::ge);\n  case TokenType::gt:\n    return std::make_unique<BinaryOperatorNode>(Operator::gt);\n  case TokenType::le:\n    return std::make_unique<BinaryOperatorNode>(Operator::le);\n  case TokenType::lt:\n    return std::make_unique<BinaryOperatorNode>(Operator::lt);\n  case TokenType::mul:\n    return std::make_unique<BinaryOperatorNode>(Operator::mul);\n  case TokenType::ne:\n    return std::make_unique<BinaryOperatorNode>(Operator::ne);\n  case TokenType::sub:\n    return std::make_unique<BinaryOperatorNode>(Operator::sub);\n  }\n  throw parse_error(\n      fmt::format(\"Unexpected token found trying to create logical operator: \", to_string(token)));\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool Ast::reduce(std::stack<std::unique_ptr<AstNode>>& stack) {\n  VLOG(2) << \"Ast::reduce. Stack Size: \" << stack.size();\n  if (stack.size() < 3) {\n    std::ostringstream ss;\n    while (!stack.empty()) {\n      ss << \"[\" << stack.top()->ToString() << \"] \";\n      stack.pop();\n    }\n    throw parse_error(fmt::format(\"[CNTREDUCE3] Invalid expression provided: \\r\\nHere's what was understood: {} \", ss.str()));\n  }\n  auto right_ast = std::move(stack.top());\n  stack.pop();\n  const auto op_ast = std::move(stack.top());\n  stack.pop();\n  auto left_ast = std::move(stack.top());\n  stack.pop();\n  \n  // Set op\n  auto op{Operator::UNKNOWN};\n  if (auto* oper = dynamic_cast<OperatorNode*>(op_ast.get())) {\n    op = oper->oper;\n  } else {\n    throw parse_error(fmt::format(\"Expected BINOP at: {}\", to_string(*op_ast.get())));\n  }\n  // Set left\n  std::unique_ptr<Expression> left;\n  if (left_ast->ast_type() == AstType::FACTOR) {\n    auto* factor = dynamic_cast<Factor*>(left_ast.release());\n    left = std::unique_ptr<Factor>(factor);\n  } else if (left_ast->ast_type() == AstType::EXPR) {\n    auto* factor = dynamic_cast<Expression*>(left_ast.release());\n    left = std::unique_ptr<Expression>(factor);\n  }\n  std::unique_ptr<Expression> right;\n  // Set right\n  if (right_ast->ast_type() == AstType::FACTOR) {\n    auto* factor = dynamic_cast<Factor*>(right_ast.release());\n    right = std::unique_ptr<Factor>(factor);\n  } else if (right_ast->ast_type() == AstType::EXPR) {\n    auto* factor = dynamic_cast<Expression*>(right_ast.release());\n    right = std::unique_ptr<Expression>(factor);\n  }\n  stack.push(std::make_unique<Expression>(std::move(left), op, std::move(right)));\n  return true;\n}\n\nstd::unique_ptr<AstNode> Ast::parseExpression(std::vector<Token>::iterator& it,\n                                              const std::vector<Token>::iterator& end) {\n  std::stack<std::unique_ptr<AstNode>> stack;\n  for (; it != end; ++it) {\n    switch (it->type) { \n    case TokenType::rparen: {\n      // If we have a right parens, we are no longer in an expression.\n      // exit now before advancing it;\n\n      // Flatten out any repeating logical conditions here,  we should end with\n      // one single tree node at the root.\n      while (stack.size() > 1) {\n        if (!reduce(stack)) {\n          break;\n        }\n      }\n      if (stack.size() != 1) {\n        throw parse_error(\n            fmt::format(\"The Stack size should be one at the root, we have: \", stack.size()));\n      }\n      return std::move(stack.top());\n    }\n    case TokenType::comment:\n      // skip\n      LOG(INFO) << \"comment: \" << it->lexeme;\n      break;\n    case TokenType::string:\n    case TokenType::character:\n    case TokenType::number:\n    case TokenType::identifier: {\n      const auto l = it->lexeme;\n      if (l.empty()) {\n        return std::make_unique<ErrorNode>(\n            StrCat(\"Unable to parse expression starting at: \", it->lexeme));\n      }\n      const auto nr = need_reduce(stack, false);\n      stack.push(createFactor(*it));\n      if (nr) {\n        // One identifier and one operator\n        reduce(stack);\n      }\n    } break;\n    case TokenType::add:\n    case TokenType::assign:\n    case TokenType::div:\n    case TokenType::eq:\n    case TokenType::ge:\n    case TokenType::gt:\n    case TokenType::le:\n    case TokenType::lt:\n    case TokenType::mul:\n    case TokenType::ne:\n    case TokenType::sub: {\n      stack.push(createBinaryOperator(*it));\n    } break;\n    case TokenType::logical_or: \n    case TokenType::logical_and: {\n      stack.push(createLogicalOperator(*it));\n    } break;\n    default: {\n      LOG(INFO) << \"Unexpected token: \" << *it;\n    } break;\n      // ignore\n    }\n  }\n  // Flatten out any repeating logical conditions here,  we should end with\n  // one single tree node at the root.\n  while (stack.size() > 1) {\n    if (!reduce(stack)) {\n      break;\n    }\n  }\n  if (stack.size() != 1) {\n    throw parse_error(\n        fmt::format(\"The Stack size should be one at the root, we have: \", stack.size()));\n  }\n  return std::move(stack.top());\n}\n\nstd::unique_ptr<AstNode> Ast::parseGroup(std::vector<Token>::iterator& it,\n                                         const std::vector<Token>::iterator& end) {\n  if (it+1 == end) {\n    return std::make_unique<ErrorNode>(\n        StrCat(\"Unable to parse expression starting at: \", it->lexeme));\n  }\n  // Skip left paren\n  ++it;\n\n  std::stack<std::unique_ptr<AstNode>> stack;\n  while (it != end && it->type != TokenType::rparen) {\n    auto expr = parseExpression(it, end);\n    if (!expr) {\n      return std::make_unique<ErrorNode>(\n          StrCat(\"Unable to parse expression starting at: \", it->lexeme));\n    }\n    stack.push(std::move(expr));\n    if (it == end || it->type != TokenType::rparen) {\n      VLOG(1) << \"Missing right parens\";\n      const auto pos = it == end ? \"end\" : it->lexeme;\n      return std::make_unique<ErrorNode>(StrCat(\"Missing right parens at: \", pos));\n    }\n  }\n  // Flatten out any repeating logical conditions here,  we should end with\n  // one single tree node at the root.\n  while (stack.size() > 1) {\n    if (!reduce(stack)) {\n      break;\n    }\n  }\n  if (stack.size() != 1) {\n    throw parse_error(\n        fmt::format(\"The Stack size should be one at the root, we have: \", stack.size()));\n  }\n  return std::move(stack.top());\n}\n\n/** \n * True if we need to reduce the stack.  We only allow logical_operations to trigger\n * reduce if we are between expressions (this happens at parse, not at parseExpression\n */\n// ReSharper disable once CppMemberFunctionMayBeStatic\nbool Ast::need_reduce(const std::stack<std::unique_ptr<AstNode>>& stack, bool allow_logical) {\n  if (stack.empty()) {\n    return false;\n  }\n  const auto t = stack.top()->ast_type();\n  const auto nr = t == AstType::BINOP;\n  if (allow_logical && t == AstType::LOGICAL_OP) {\n    return true;\n  }\n  return nr;\n}  \n\nstd::unique_ptr<RootNode> Ast::parse(\n    std::vector<Token>::iterator& begin, const std::vector<Token>::iterator& end) {\n  std::stack<std::unique_ptr<AstNode>> stack;\n  try {\n    for (auto it = begin; it != end;) {\n      const auto& t = *it;\n      switch (t.type) { \n      case TokenType::lparen: {\n        auto expr = parseGroup(it, end);\n        if (!expr || it == end) {\n          return std::make_unique<RootNode>(std::make_unique<ErrorNode>(\n              StrCat(\"Unable to parse expression starting at: \", t)));\n        }\n        stack.push(std::move(expr));\n        } break;\n\n      case TokenType::logical_and:\n      case TokenType::logical_or: {\n        stack.push(createLogicalOperator(*it));\n      } break;\n\n      default: {\n        // Try to reduce.\n        const auto nr = need_reduce(stack, true);\n        auto expr = parseExpression(it, end);\n        if (!expr) {\n          return std::make_unique<RootNode>(std::make_unique<ErrorNode>(\n              StrCat(\"Unable to parse expression starting at: \", t)));\n        }\n        stack.push(std::move(expr));\n        if (nr) {\n          reduce(stack);\n        }\n      } break;\n      }\n\n      if (it != end) {\n        ++it;\n      }\n    }\n    if (stack.size() != 1) {\n      throw parse_error(\n          fmt::format(\"The Stack size should be one at the root, we have: \", stack.size()));\n    }\n    return std::make_unique<RootNode>(std::move(stack.top()));\n  } catch (const parse_error& e) {\n    return std::make_unique<RootNode>(std::make_unique<ErrorNode>(e.what()));\n  }\n}\n\nbool Ast::parse(const Lexer& l) {\n  auto tokens = l.tokens();\n  auto it = std::begin(tokens);\n  root_ = parse(it, std::end(tokens));\n  if (!root_) {\n    return false;\n  }\n  return true;\n}\n\nAstNode* Ast::root() const { \n  return root_->node.get();\n}\n\nstd::string AstNode::ToString() const { \n  return fmt::format(\"AstNode: {}\", to_string(ast_type_)); \n}\n\nvoid AstNode::accept(AstVisitor* visitor) { \n  auto* expr = dynamic_cast<Expression*>(this);\n  if (expr) {\n    visitor->visit(expr);\n    return;\n  }\n  visitor->visit(this); \n}\n\nint Expression::expression_id = 0;\n\nExpression::Expression(std::unique_ptr<Expression>&& left, Operator op,\n                       std::unique_ptr<Expression>&& right) \n  : AstNode(AstType::EXPR), id_(++expression_id), left_(std::move(left)), op_(op),\n      right_(std::move(right)) {}\n\nstd::string Expression::ToString() const { return ToString(true, 0); }\n\nstd::string Expression::ToString(bool include_children) const {\n  return ToString(include_children, 0);\n}\n\nstd::string Expression::ToString(bool include_children, int indent) const { \n  std::ostringstream ss;\n  std::string pad{\"  \"};\n  if (indent > 0) {\n    pad.append(std::string(indent, ' '));\n  }\n  ss << \"\\r\\n\";\n  ss << pad << \"Expression (\" << id_ << \"): \";\n  if (auto* l = dynamic_cast<Factor*>(left())) {\n    ss << pad << \"[Left: \" << l->ToString(0) << \"]\";\n  } else if (left_ && include_children) {\n    ss << pad << \"[Left: \" << left_->ToString(indent + 4) << \" ]\";\n  } else if (left_) {\n    ss << pad << \"[Left: EXPRESSION #\" << left_->id() << \"]\";\n  }\n  ss << \"\\r\\n\";\n  ss << pad << \"[OP: '\" << to_string(op_) << \"'](\" << id_ << \")\";\n  ss << \"\\r\\n\";\n  if (auto* f = dynamic_cast<Factor*>(right())) {\n    ss << pad << \"[Right: \" << f->ToString(0) << \"]\";\n  } else if (right_ && include_children) {\n    ss << pad << \"[Right: \" << right_->ToString(indent + 4) << \"]\";\n  } else if (right_) {\n    ss << pad << \"[Right: EXPRESSION #\" << right_->id() << \"]\";\n  }\n  return ss.str();\n}\n\nvoid Expression::accept(AstVisitor* visitor) { \n  if (auto* f = dynamic_cast<Factor*>(left())) {\n    f->accept(visitor);\n  } else if (auto* e = dynamic_cast<Expression*>(left())) {\n    e->accept(visitor);\n  }\n  if (auto* r = dynamic_cast<Factor*>(right())) {\n    r->accept(visitor);\n  } else if (auto* e = dynamic_cast<Expression*>(right())) {\n    e->accept(visitor);\n  }\n  visitor->visit(this);\n}\n\nVariable::Variable(std::string s) : Factor(FactorType::variable, -1, std::move(s)) {}\n\nstd::string RootNode::ToString() const { return fmt::format(\"ROOT: {}\\n\", node->ToString()); }\n\n\nstd::string BinaryOperatorNode::ToString() const { \n  return fmt::format(\"BinOp: \", to_string(oper));\n}\n\nstd::string LogicalOperatorNode::ToString() const {\n  return fmt::format(\"LogOp: \", to_string(oper));\n}\n\n} // namespace wwiv::core::parser\n"
  },
  {
    "path": "core/parser/ast.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_CORE_AST_H\n#define INCLUDED_WWIV_CORE_AST_H\n\n#include \"core/parser/lexer.h\"\n#include \"core/parser/token.h\"\n#include <memory>\n#include <stack>\n#include <stdexcept>\n#include <string>\n#include <vector>\n\nnamespace wwiv::core::parser {\n\nclass AstVisitor;\n\nenum class AstType {\n  LOGICAL_OP,\n  BINOP,\n  UNOP,\n  PAREN,\n  EXPR,\n  FACTOR, \n  TAUTOLOGY,\n  AST_ERROR,\n  ROOT\n};\n\n\nclass AstNode {\npublic:\n  AstNode(AstType t) : ast_type_(t) {}\n  virtual ~AstNode() = default;\n  AstType ast_type() const noexcept { return ast_type_; }\n  virtual std::string ToString() const;\n  virtual void accept(AstVisitor* visitor);\n\nprivate:\n  const AstType ast_type_;\n};\n\nenum class Operator { add, sub, mul, div, gt, ge, lt, le, eq, ne, logical_or, logical_and, UNKNOWN };\n\nenum class FactorType { int_value, string_val, variable };\n\nclass Factor;\n\n//[[DebuggerDisplay(\"op={op_} l={left_} r={right_}\")]]\nclass Expression : public AstNode {\npublic:\n  static int expression_id;\n  //Expression() : AstNode(AstType::EXPR), id_(++expression_id) {}\n  Expression(std::unique_ptr<Expression>&& left, Operator op, std::unique_ptr<Expression>&& right);\n\n  [[nodiscard]] Expression* left() const { return left_.get(); }\n  [[nodiscard]] Expression* right() const { return right_.get(); }\n  [[nodiscard]] Operator op() const noexcept { return op_; }\n  [[nodiscard]] int id() const noexcept { return id_; }\n  [[nodiscard]] std::string ToString() const override;\n  [[nodiscard]] virtual std::string ToString(bool include_children) const;\n  [[nodiscard]] virtual std::string ToString(bool include_children, int indent) const;\n  void accept(AstVisitor* visitor) override;\n\n  // Used when constructing these.\n  // TODO(rushfan): Move into constructor and construct these fully.\n  int id_;\n  std::unique_ptr<Expression> left_;\n  Operator op_;\n  std::unique_ptr<Expression> right_;\n\nprotected:\n  // Constructor for subclasses of expressions to use to eval.\n  explicit Expression(AstType t) : AstNode(t), id_(++expression_id), op_(Operator::UNKNOWN) {}\n};\n\nclass Factor : public Expression {\nprotected:\n  Factor(FactorType t, int v, std::string s);\n\npublic:\n  [[nodiscard]] std::string ToString() const override { return ToString(0); };\n\n  [[nodiscard]] virtual std::string ToString(int indent) const;\n\n  [[nodiscard]] FactorType factor_type() const noexcept { return factor_type_; }\n\n  [[nodiscard]] std::string value() const {\n    return factor_type_ == FactorType::int_value ? std::to_string(val) : sval;\n  }\n\n  [[nodiscard]] int int_value() const {\n    return factor_type_ == FactorType::int_value ? val : -1;\n  }\n\n  void accept(AstVisitor* visitor) override;\n\nprivate:\n  FactorType factor_type_;\n  int val;\n  std::string sval;\n};\n\nclass Number final : public Factor {\npublic:\n  explicit Number(int v) : Factor(FactorType::int_value, v, \"\") {}\n};\n\nclass String final : public Factor {\npublic:\n  explicit String(std::string s) : Factor(FactorType::string_val, -1, s) {}\n};\n\nclass Variable final : public Factor {\npublic:\n  explicit Variable(std::string s);\n};\n\nclass RootNode final : public AstNode {\npublic:\n  explicit RootNode(std::unique_ptr<AstNode>&& n) : AstNode(AstType::ROOT), node(std::move(n)) {}\n  [[nodiscard]] std::string ToString() const override;\n\n  std::unique_ptr<AstNode> node;\n};\n\nclass TautologyNode final : public AstNode {\npublic:\n  TautologyNode() : AstNode(AstType::TAUTOLOGY) {}\n};\n\nclass ErrorNode final : public AstNode {\npublic:\n  explicit ErrorNode(const std::string& m) : AstNode(AstType::AST_ERROR), message(m) {}\n  std::string message;\n};\n\nclass OperatorNode : public AstNode {\nprotected:\n  OperatorNode(Operator o, AstType t) : AstNode(t), oper(o) {}\n\npublic:\n  [[nodiscard]] std::string ToString() const override = 0;\n  const Operator oper;\n};\n\nclass BinaryOperatorNode final : public OperatorNode {\npublic:\n  explicit BinaryOperatorNode(Operator o) : OperatorNode(o, AstType::BINOP) {}\n  std::string ToString() const override;\n};\n\nclass LogicalOperatorNode final : public OperatorNode {\npublic:\n  explicit LogicalOperatorNode(Operator o) : OperatorNode(o, AstType::LOGICAL_OP) {}\n  std::string ToString() const override;\n};\n\nstruct parse_error : std::runtime_error {\n  explicit parse_error(const std::string& m);\n};\n\nclass AstVisitor {\npublic:\n  virtual ~AstVisitor() = default;\n  virtual void visit(AstNode* n) = 0;\n  virtual void visit(Expression* n) = 0;\n  virtual void visit(Factor* n) = 0;\n};\n\nclass Ast final {\npublic:\n  Ast() = default;\n  \n  bool parse(const Lexer& l);\n  AstNode* root() const;\n\nprivate:\n  [[nodiscard]] std::unique_ptr<AstNode> parseExpression(std::vector<Token>::iterator& begin,\n                                                         const std::vector<Token>::iterator& end);\n  [[nodiscard]] std::unique_ptr<AstNode> parseGroup(std::vector<Token>::iterator& begin,\n                                                    const std::vector<Token>::iterator& end);\n  [[nodiscard]] std::unique_ptr<RootNode> parse(std::vector<Token>::iterator& begin,\n                                                const std::vector<Token>::iterator& end);\n  bool need_reduce(const std::stack<std::unique_ptr<AstNode>>& stack, bool allow_logical);\n  bool reduce(std::stack<std::unique_ptr<AstNode>>& stack);\n\n  std::unique_ptr<RootNode> root_;\n};\n\nstd::string to_string(Operator o);\nstd::string to_symbol(Operator o);\nstd::string to_string(const AstNode& n);\n\n} // namespace wwiv::core\n\n#endif\n"
  },
  {
    "path": "core/parser/ast_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/log.h\"\n#include \"core/parser/ast.h\"\n#include \"core/parser/lexer.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\n\n#define EXPECT_TOKEN_EQ(tok, typ, m)                                                               \\\n  {                                                                                                \\\n    EXPECT_EQ((tok).type, typ);                                                                    \\\n    EXPECT_EQ((tok).lexeme, m);                                                                    \\\n  }\n\nclass AstTest : public ::testing::Test {\npublic:\n  AstTest() {}\n\n  ::testing::AssertionResult HasOp(Expression *e, Operator op) {\n    if (e->op() == op)\n      return ::testing::AssertionSuccess();\n    return ::testing::AssertionFailure()\n           << to_string(e->op()) << \" was not: \" << to_string(op) << \"; Expr: \" << e->ToString();\n  }\n\n  ::testing::AssertionResult HasFactor(Expression* e, std::string expected, const std::string& lr) {\n    auto* f = dynamic_cast<Factor*>(e);\n    if (!f)\n      return ::testing::AssertionFailure() << \"missing \" << lr << \" factor: \" << expected;\n    auto val = f->value();\n    if (val == expected) {\n      return ::testing::AssertionSuccess();\n    }\n    return ::testing::AssertionFailure()\n           << expected << \" != \" << val << \"; Expr: \" << e->ToString();\n  }\n  ::testing::AssertionResult HasLeftFactor(Expression* e, std::string expected) {\n    return HasFactor(e->left(), expected, \"left\");\n  }\n  ::testing::AssertionResult HasRightFactor(Expression* e, std::string expected) {\n    return HasFactor(e->right(), expected, \"right\");\n  }\n  ::testing::AssertionResult HasExpression(Expression* e, std::string l, Operator op,\n                                           std::string r) {\n    if (auto has_op = HasOp(e, op); !has_op) {\n      return has_op;\n    }\n    if (auto has_left = HasLeftFactor(e, l); !has_left) {\n      return has_left;\n    }\n    if (auto has_right = HasRightFactor(e, r); !has_right) {\n      return has_right;\n    }\n    return ::testing::AssertionSuccess();\n  }\n};\n\nTEST_F(AstTest, Expr_Add) {\n  const Lexer l(\"1+2\"); \n\n  Ast ast;\n  ASSERT_TRUE(ast.parse(l));\n  auto* root = dynamic_cast<Expression*>(ast.root());\n  VLOG(1) << root->ToString();\n\n  EXPECT_TRUE(HasLeftFactor(root, \"1\"));\n  EXPECT_TRUE(HasOp(root, Operator::add));\n  EXPECT_TRUE(HasRightFactor(root, \"2\"));\n}\n\nTEST_F(AstTest, Expr_Eq) {\n  Lexer l(\"user.sl>200\");\n\n  Ast ast;\n  ASSERT_TRUE(ast.parse(l));\n  auto* root = dynamic_cast<Expression*>(ast.root());\n  VLOG(1) << root->ToString();\n\n  EXPECT_TRUE(HasLeftFactor(root, \"user.sl\"));\n  EXPECT_TRUE(HasOp(root, Operator::gt));\n  EXPECT_TRUE(HasRightFactor(root, \"200\"));\n\n  EXPECT_TRUE(HasExpression(root, \"user.sl\", Operator::gt, \"200\"));\n}\n\nTEST_F(AstTest, Expr_Parens) {\n  Lexer l(\"(user.sl>200) || user.ar == 'A'\");\n\n  Ast ast;\n  ASSERT_TRUE(ast.parse(l));\n  auto* root = ast.root();\n  VLOG(1) << root->ToString();\n\n  auto* expr = dynamic_cast<Expression*>(root);\n  CHECK_NOTNULL(expr);\n  EXPECT_TRUE(HasOp(expr, Operator::logical_or)) << root->ToString();\n  ASSERT_NE(nullptr, expr);\n\n  auto* left = expr->left();\n  VLOG(1) << \"Left: \" << left->ToString();\n  EXPECT_TRUE(HasExpression(left, \"user.sl\", Operator::gt, \"200\"));\n  auto* right = expr->right();\n  VLOG(1) << \"Right: \" << right->ToString();\n  EXPECT_TRUE(HasExpression(right, \"user.ar\", Operator::eq, \"A\"));\n}\n\n\nTEST_F(AstTest, Visitor) {\n  Lexer l(\"((user.sl>200) || user.ar == 'A') || user.sl == 255\");\n\n  class PrintVisitor : public AstVisitor {\n  public:\n    void visit(AstNode* n) override {\n      LOG(INFO) << \"Visit AstNode: \" << n->ToString();\n    };\n\n    void visit(Expression* n) override {\n      LOG(INFO) << \"Visit Expression: \" << n->ToString(false);\n      ++count;\n    };\n\n    void visit(Factor* n) override {\n      LOG(INFO) << \"Visit Factor: \" << n->ToString();\n      ++count;\n    };\n    int count{0};\n  };\n\n  Ast ast;\n  ASSERT_TRUE(ast.parse(l));\n  auto* root = ast.root();\n  PrintVisitor v{};\n  root->accept(&v);\n\n  EXPECT_EQ(11, v.count);\n\n  LOG(INFO) << \"======================================================================\";\n  LOG(INFO) << root->ToString();\n}\n"
  },
  {
    "path": "core/parser/lexer.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/parser/lexer.h\"\n\n#include \"core/stl.h\"\n#include \"fmt/format.h\"\n#include <array>\n#include <iomanip>\n#include <ios>\n#include <sstream>\n#include <unordered_set>\n\nnamespace wwiv::core::parser {\n\nstd::optional<char> peek(std::string::iterator& it, const std::string::iterator& end) {\n  if (it == end) {\n    return std::nullopt;\n  }\n  if (it + 1 == end) {\n    return std::nullopt;\n  }\n  return *(it + 1);\n}\n\nstatic std::unordered_set<char> WS = {' ', '\\r', '\\n', '\\t'};\n\nLexer::Lexer(std::string source)\n    : source_(std::move(source)), tok_eof(TokenType::eof, wwiv::stl::size_int(source_)), \n      start(std::begin(source_)), end(std::end(source_)), it_(start) { \n\n  while (it_ != end) {\n    auto c = *it_;\n    switch (c) {\n    case '(':\n      emit(TokenType::lparen);\n      break;\n    case ')':\n      emit(TokenType::rparen);\n      break;\n    case '=': {\n      if (peek(it_, end) == '=') {\n        emit(TokenType::eq);\n        ++it_;\n      } else {\n        emit(TokenType::assign);\n      }\n    } break;\n    case '!': {\n      if (peek(it_, end) == '=') {\n        emit(TokenType::ne);\n        ++it_;\n      } else {\n        emit(TokenType::negate);\n      }\n    } break;\n    case '>': {\n      if (peek(it_, end) == '=') {\n        emit(TokenType::ge);\n        ++it_;\n      } else {\n        emit(TokenType::gt);\n      }\n    } break;\n    case '<': {\n      if (peek(it_, end) == '=') {\n        emit(TokenType::le);\n        ++it_;\n      } else {\n        emit(TokenType::lt);\n      }\n    } break;\n    case '+':\n      emit(TokenType::add);\n      break;\n    case '-':\n      emit(TokenType::sub);\n      break;\n    case '*':\n      emit(TokenType::mul);\n      break;\n    case '/':\n      if (peek(it_, end) == '*') {\n        ++it_; // skip / and *\n        ++it_; // skip / and *\n        comment();\n      } else {\n        emit(TokenType::div);\n      }\n      break;\n    case '\\'': // char\n      ++it_;   // skip '\n      character();\n      break;\n    case '\"': // string\n      ++it_;  // skip \"\n      string();\n      break;\n    case ';':\n      emit(TokenType::semicolon);\n      break;\n    case '&': {\n      if (peek(it_, end) == '&') {\n        emit(TokenType::logical_and);\n        ++it_;\n      } else {\n        error(\"& is not a valid token; did you mean '&&'?\");\n      }\n    } break;\n    case '|': {\n      if (peek(it_, end) == '|') {\n        emit(TokenType::logical_or);\n        ++it_;\n      } else {\n        error(\"| is not a valid token; did you mean '||'?\");\n      }\n    } break;\n    default: {\n      if (wwiv::stl::contains(WS, c)) {\n        // skip WS\n        break;\n      }\n      if (isalpha(*it_)) {\n        identifier();\n      } else if (isdigit(*it_)) {\n        number();\n      }\n    } break;\n    }\n\n    // advance iterator\n    if (it_ == end) {\n      break;\n    }\n    ++it_;\n  }\n\n  token_iter_ = std::begin(tokens_);\n}\n\nvoid Lexer::comment() { \n  std::string tx;\n  while ( it_ != end) {\n    if (*it_ == '*' && peek(it_, end) == '/') {\n      // end if comment.\n      ++it_; // skip end of comment.\n      emit(TokenType::comment, tx);\n      return;\n    }\n    tx.push_back(*it_++);\n  }\n}\n\nvoid Lexer::string() {\n  std::string tx;\n  while (it_ != end) {\n    if (*it_ == '\"') {\n      // end if comment.\n      emit(TokenType::string, tx);\n      return;\n    }\n    tx.push_back(*it_++);\n  }\n  if (!tx.empty()) {\n    error(\"EOF before end of string\");\n  }\n}\n\nvoid Lexer::character() {\n  std::string tx;\n  while (it_ != end) {\n    if (*it_ == '\\'') {\n      // end if comment.\n      if (tx.size() == 1) {\n        emit(TokenType::character, tx);\n        return;\n      } else {\n        error(fmt::format(\"Expected a single character, got '{}'\"));\n        return;\n      }\n      return;\n    }\n    tx.push_back(*it_++);\n  }\n  if (!tx.empty()) {\n    error(\"EOF before end of character\");\n  }\n}\n\nvoid Lexer::identifier() {\n  std::string tx;\n  while (it_ != end) {\n    const auto c = *it_;\n    if (!isalnum(c) && c != '.' && c != '_' && c != '-') {\n      // end if identifier.\n      if (it_ != start) {\n        // put back token\n        --it_;\n      }\n      emit(TokenType::identifier, tx);\n      return;\n    }\n    tx.push_back(*it_++);\n  }\n  if (!tx.empty()) {\n    emit(TokenType::identifier, tx);\n  }\n}\n\nvoid Lexer::number() {\n  std::string tx;\n  while (it_ != end) {\n    const auto c = *it_;\n    if (!isdigit(c)) {\n      // end if identifier.\n      if (it_ != start) {\n        // put back token\n        --it_;\n      }\n      emit(TokenType::number, tx);\n      return;\n    }\n    tx.push_back(*it_++);\n  }\n  if (!tx.empty()) {\n    emit(TokenType::number, tx);\n  }\n}\n\nToken& Lexer::next() {\n  if (token_iter_ == std::end(tokens_)) {\n    return tok_eof;\n  }\n  return *token_iter_++;\n}\n\nbool Lexer::ok() { \n  if (!state_.ok) {\n    VLOG(1) << \"Lexer state !ok: \" << state_.err;\n  }\n  return state_.ok;\n}\n\nconst std::vector<Token>& Lexer::tokens() const { return tokens_; }\n\nvoid Lexer::emit(TokenType t) { \n  //VLOG(1) << \"Emitting TokenType: \" << static_cast<int>(t);\n  const auto pos = static_cast<int>(std::distance(start, it_));\n  tokens_.emplace_back(t, pos);\n}\n\nvoid Lexer::emit(TokenType t, std::string l) { \n  //VLOG(1) << \"Emitting TokenType: \" << static_cast<int>(t) << \"; l: '\" << l << \"'\";\n  const auto pos = std::distance(start, it_);\n  tokens_.emplace_back(t, std::move(l), pos);\n}\n\nvoid Lexer::error(std::string message) { \n  const auto pos = std::distance(start, it_);\n  const auto msg = fmt::format(\"Error at pos: '{}', {}\", pos, message);\n  emit(TokenType::error, msg);\n  state_.ok = false;\n  state_.err = msg;\n}\n\nstd::ostream& operator<<(std::ostream& os, const Lexer& a) {\n  os << \"Lexer: expression: '\" << a.source_ << \"'; Tokens: \";\n  for (const auto& t : a.tokens()) {\n    os << t << \", \";\n  }\n  return os;\n}\n\n} // namespace wwiv::core::parser\n"
  },
  {
    "path": "core/parser/lexer.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_CORE_LEXER_H\n#define INCLUDED_WWIV_CORE_LEXER_H\n\n#include \"core/parser/token.h\"\n#include <string>\n#include <vector>\n\nnamespace wwiv::core::parser {\n\nstruct LexerState {\n  bool ok{true};\n  std::string err;\n};\n\nclass Lexer final {\npublic:\n  explicit Lexer(std::string source);\n  void comment();\n  void character();\n  void string();\n  void identifier();\n  void number();\n\n  Token& next();\n  bool ok();\n\n  const std::vector<Token>& tokens() const;\n\n  std::vector<Token> tokens_;\n  std::string source_;\n  LexerState state_;\n  Token tok_eof;\n  std::string::iterator start;\n  std::string::iterator end;\n  std::string::iterator it_;\n  decltype(tokens_)::iterator token_iter_;\n\nprivate:\n  void emit(TokenType);\n  void emit(TokenType, std::string);\n  void error(std::string message);\n};\n\nstd::ostream& operator<<(std::ostream& os, const Lexer& l);\n\n} // namespace wwiv::core::parser\n\n#endif\n"
  },
  {
    "path": "core/parser/lexer_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/parser/lexer.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\n\n#define EXPECT_TOKEN_EQ(tok, typ, m)                                                               \\\n  {                                                                                                \\\n    EXPECT_EQ((tok).type, typ);                                                                    \\\n    EXPECT_EQ((tok).lexeme, m);                                                                    \\\n  }\n\n#define EXPECT_ID_OP_NUM(t, m, o, n)                                                               \\\n  {                                                                                                \\\n    EXPECT_EQ(3u, t.size());                                                                       \\\n    EXPECT_TOKEN_EQ((t[0]), TokenType::identifier, m);                                           \\\n    EXPECT_TOKEN_EQ((t[1]), o, \"\");                                                                    \\\n    EXPECT_TOKEN_EQ((t[2]), TokenType::number, n);                                           \\\n  }\n\n#define EXPECT_LEXER_ID_OP_NUM(l, m, o, n)                                                         \\\n  {                                                                                                \\\n    ASSERT_TRUE(l.ok());                                                                             \\\n    const auto t = l.tokens();                                                                     \\\n    EXPECT_EQ(3u, t.size());                                                                       \\\n    EXPECT_TOKEN_EQ((t[0]), TokenType::identifier, m);                                             \\\n    EXPECT_TOKEN_EQ((t[1]), o, \"\");                                                                \\\n    EXPECT_TOKEN_EQ((t[2]), TokenType::number, n);                                                 \\\n  }\n\nclass LexerTest : public ::testing::Test {\npublic:\n  LexerTest() {}\n};\n\nTEST_F(LexerTest, Add) { \n  Lexer l(\"1+2\"); \n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(3u, t.size());\n  EXPECT_TOKEN_EQ(t[0], TokenType::number, \"1\");\n  EXPECT_TOKEN_EQ(t[1], TokenType::add, \"\");\n  EXPECT_TOKEN_EQ(t[2], TokenType::number, \"2\");\n}\n\nTEST_F(LexerTest, Sub) {\n  Lexer l(\"3-4\");\n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(3u, t.size());\n  EXPECT_TOKEN_EQ(t[0], TokenType::number, \"3\");\n  EXPECT_TOKEN_EQ(t[1], TokenType::sub, \"\");\n  EXPECT_TOKEN_EQ(t[2], TokenType::number, \"4\");\n}\n\nTEST_F(LexerTest, Parens) {\n  Lexer l(\"(1+2)*3\");\n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(7u, t.size());\n  EXPECT_TOKEN_EQ(t[0], TokenType::lparen, \"\");\n  EXPECT_TOKEN_EQ(t[1], TokenType::number, \"1\");\n  EXPECT_TOKEN_EQ(t[2], TokenType::add, \"\");\n  EXPECT_TOKEN_EQ(t[3], TokenType::number, \"2\");\n  EXPECT_TOKEN_EQ(t[4], TokenType::rparen, \"\");\n  EXPECT_TOKEN_EQ(t[5], TokenType::mul, \"\");\n  EXPECT_TOKEN_EQ(t[6], TokenType::number, \"3\");\n}\n\nTEST_F(LexerTest, Eq) {\n  Lexer l(\"user.sl == 10\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.sl\", TokenType::eq, \"10\");\n}\n\nTEST_F(LexerTest, NotEq) {\n  Lexer l(\"user.sl != 11\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.sl\", TokenType::ne, \"11\");\n}\n\nTEST_F(LexerTest, UserSlGt) {\n  Lexer l(\"user.sl>200\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.sl\", TokenType::gt, \"200\");\n}\n\nTEST_F(LexerTest, UserDSlGe) {\n  Lexer l(\"user.dsl>=201\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.dsl\", TokenType::ge, \"201\");\n}\n\nTEST_F(LexerTest, UserSlLt) {\n  Lexer l(\"user.sl<255\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.sl\", TokenType::lt, \"255\");\n}\n\nTEST_F(LexerTest, UserSlLe) {\n  Lexer l(\"user.sl<=255\");\n  EXPECT_LEXER_ID_OP_NUM(l, \"user.sl\", TokenType::le, \"255\");\n}\n\nTEST_F(LexerTest, Or) {\n  Lexer l(\"(user.sl>200) || user.ar == 'A'\");\n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(9u, t.size());\n  EXPECT_TOKEN_EQ(t[5], TokenType::logical_or, \"\");\n}\n\nTEST_F(LexerTest, And) {\n  Lexer l(\"(user.sl>20) && user.ar == 'A'\");\n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(9u, t.size());\n  EXPECT_TOKEN_EQ(t[5], TokenType::logical_and, \"\");\n}\n\nTEST_F(LexerTest, Smoke_Error) {\n  Lexer l(\"user.sl&10\");\n  EXPECT_FALSE(l.ok());\n  const auto& t = l.tokens();\n  ASSERT_GE(t.size(), 2u) << l;\n  EXPECT_EQ(t[1].type, TokenType::error) << l;\n}\n\nTEST_F(LexerTest, Underscore) { \n  Lexer l(\"user.fs_reader\"); \n  ASSERT_TRUE(l.ok());\n\n  const auto& t = l.tokens();\n  EXPECT_EQ(1u, t.size());\n  EXPECT_TOKEN_EQ(t[0], TokenType::identifier, \"user.fs_reader\");\n}\n\n"
  },
  {
    "path": "core/parser/token.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/parser/token.h\"\n\n#include \"core/stl.h\"\n#include \"fmt/format.h\"\n#include <array>\n#include <iomanip>\n#include <ios>\n#include <random>\n#include <sstream>\n\nnamespace wwiv::core::parser {\n\nToken::Token(TokenType t, int p) : type(t), pos(p) {}\n\nToken::Token(TokenType t, std::string l, int p) : type(t), lexeme(l), pos(p) {}\n\nstd::ostream& operator<<(std::ostream& os, const TokenType& t) {\n  os << to_string(t);\n  return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const Token& t) {\n  os << to_string(t);\n  return os;\n}\n\nstd::string to_string(TokenType t) { \n  switch (t) {\n  case TokenType::lparen:      //  (\n    return \"lparen\";\n  case TokenType::rparen:      //  )\n    return \"rparen\";\n  case TokenType::eq:          //  ==\n    return \"eq\";\n  case TokenType::assign:      //  =\n    return \"assign\";\n  case TokenType::ne:          //  !=\n    return \"ne\";\n  case TokenType::negate:      //  !\n    return \"negate\";\n  case TokenType::gt:          //  >\n    return \"gt\";\n  case TokenType::ge:          //  >=\n    return \"ge\";\n  case TokenType::lt:          //  <\n    return \"lt\";\n  case TokenType::le:          //  <\n    return \"le\";\n  case TokenType::add:         //  +\n    return \"add\";\n  case TokenType::sub:         //  -\n    return \"sub\";\n  case TokenType::mul:         //  *\n    return \"mul\";\n  case TokenType::div:         //  /\n    return \"div\";\n  case TokenType::semicolon:   //  ;\n    return \"semicolon\";\n  case TokenType::comment:     //  /*\n    return \"comment\";\n  case TokenType::character:   //  '?'\n    return \"character\";\n  case TokenType::string:      // \"???\"\n    return \"string\";\n  case TokenType::eof:         // EOF of ^Z\n    return \"eof\";\n  case TokenType::identifier:  // [A-Za-z0-9.]\n    return \"identifier\";\n  case TokenType::number:      // [0-9]\n    return \"number\";\n  case TokenType::logical_and: // &&\n    return \"logical_and\";\n  case TokenType::logical_or: // ||\n    return \"logical_or\";\n  case TokenType::error:\n    return \"error\";\n  }\n  return \"**UNKNOWN**\";\n}\n\nstd::string to_string(Token t) {\n  return fmt::format(\"[Token: {}({}), pos: {}]\", to_string(t.type), t.lexeme, t.pos);\n}\n\n} \n"
  },
  {
    "path": "core/parser/token.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_CORE_TOKEN_H\n#define INCLUDED_WWIV_CORE_TOKEN_H\n\n#include <string>\n\nnamespace wwiv::core::parser {\n\nenum class TokenType {\n  lparen,     //  (\n  rparen,     //  )\n  eq,         //  ==\n  assign,     //  =\n  ne,         //  !=\n  negate,     //  !\n  gt,         //  >\n  ge,         //  >=\n  lt,         //  <\n  le,         //  <\n  add,        //  +\n  sub,        //  -\n  mul,        //  *\n  div,        //  /\n  semicolon,  //  ;\n  comment,    //  /* \n  character,  //  '?'\n  string,     // \"???\"\n  eof,        // EOF of ^Z\n  identifier, // [A-Za-z0-9.]\n  number,     // [0-9]\n  logical_and, // &&\n  logical_or,  // ||\n  error\n};\n\nclass Token final {\npublic:\n  Token(TokenType t, int pos);\n  Token(TokenType t, std::string l, int pos);\n  TokenType type;\n  std::string lexeme;\n  int pos;\n};\n\nstd::ostream& operator<<(std::ostream& os, const TokenType& a);\nstd::ostream& operator<<(std::ostream& os, const Token& a);\nstd::string to_string(TokenType t);\nstd::string to_string(Token t);\n\n} // namespace wwiv::core\n\n#endif\n"
  },
  {
    "path": "core/pipe.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/pipe.h\"\n\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"core/log.h\"\n#include \"fmt/format.h\"\n\nnamespace wwiv::core {\n\nPipe::Pipe(const std::string_view name) : pipe_name_(pipe_name(name)) {}\n\nPipe::Pipe(int node_number, bool control_pipe)\n    : Pipe(fmt::format(\"WWIV{}{}\", node_number, control_pipe ? \"C\" : \"\")) {}\n  \nPipe::Pipe(int node_number) : Pipe(node_number, false) {}\n\n\nbool Pipe::Create() {\n  handle_ = create_pipe(pipe_name_);\n  return handle_ != Pipe::PIPE_INVALID_HANDLE_VALUE;\n}\n\nbool Pipe::Close() {\n  auto ret = close_pipe(handle_, server_);\n  handle_ = Pipe::PIPE_INVALID_HANDLE_VALUE;\n  return ret;\n}\n\n\nPipe::~Pipe() {\n  if (!IsOpen()) {\n    return;\n  }\n  Close();\n}\n\nbool Pipe::IsOpen() const noexcept { \n  return handle_ != Pipe::PIPE_INVALID_HANDLE_VALUE;\n}\n\nstd::string Pipe::name() const noexcept { \n  return pipe_name_;\n}\n\n\n// Implemented in pipe_PLATFORM.cpp\n// std::optional<int> Pipe::write(const char* data, int size);\n// std::optional<int> Pipe::read(char* data, int size)\n// bool Pipe::Open() {}\n// bool WaitForClient(std::chrono::duration<double> timeout);\n\n\n}\n"
  },
  {
    "path": "core/pipe.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_PIPE_H\n#define INCLUDED_CORE_PIPE_H\n\n#include <chrono>\n#include <optional>\n#include <string>\n#include <string_view>\n\nnamespace wwiv::core {\n\nclass Pipe {\npublic:\n\n#ifdef _WIN32\n  typedef void* PIPE_HANDLE;\n#elif defined(__OS2__)\n  // HFILE is unsigned long\n  typedef unsigned long HFILE;\n  typedef HFILE PIPE_HANDLE;\n#endif\n\n  static constexpr int PIPE_BUFFER_SIZE = 4000;\n\n  static constexpr PIPE_HANDLE PIPE_INVALID_HANDLE_VALUE = ((PIPE_HANDLE)-1);\n\n  explicit Pipe(const std::string_view name);\n  Pipe(int node_number, bool control_pipe);\n  Pipe(int node_number);\n  ~Pipe();\n\n  /** Creates a new Named Pipe */\n  bool Create();\n\n  /** Opens an existing named pipe */\n  bool Open();\n\n  /** Waits for a client to connect up time timeout */\n  bool WaitForClient(std::chrono::duration<double> timeout);\n\n  /** returns the number of bytes written on success */\n  std::optional<int> write(const char* data, int size);\n\n  /** returns the number of bytes read on success */\n  std::optional<int> read(char* data, int size);\n\n  /** returns the last error code */\n  int last_error() const noexcept { return last_error_ ; }\n\n  /** Returns the optional character that will be returned next */\n  std::optional<char> peek();\n\n  [[nodiscard]] bool IsOpen() const noexcept;\n\n  /** Close the pipe */\n  bool Close();\n\n  [[nodiscard]] std::string name() const noexcept;\n\n  /** returns true if this end is the server of the pipe */\n  [[nodiscard]] bool IsServer() const noexcept { return server_; }\n \nprivate:\n  std::string pipe_name_;\n\n  PIPE_HANDLE handle_{PIPE_INVALID_HANDLE_VALUE};\n  int last_error_{0};\n  bool server_{false};\n};\n\n// Platform specific bits\nPipe::PIPE_HANDLE create_pipe(const std::string& name);\nbool connect_pipe(Pipe::PIPE_HANDLE h);\nstd::string pipe_name(const std::string_view part);\nbool close_pipe(Pipe::PIPE_HANDLE h, bool server);\n\n}\n\n#endif  // INCLUDED_CORE_PIPE_H\n"
  },
  {
    "path": "core/pipe_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/pipe.h\"\n\n#define INCL_DOSERRORS\n#define INCL_DOSPROCESS\n#include <os2.h>\n\n#include \"core/log.h\"\n#include \"fmt/format.h\"\n\n// Values from: The Art Of OS/2 Warp Programming. Chapter 5\nstatic constexpr ULONG PIPE_OPEN_FLAG = OPEN_ACTION_OPEN_IF_EXISTS;\nstatic constexpr ULONG PIPE_OPEN_MODE = (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | \n                                         OPEN_FLAGS_RANDOM | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE);\n\nnamespace wwiv::core {\n\nPipe::PIPE_HANDLE create_pipe(const std::string& name) {\n  Pipe::PIPE_HANDLE hPipe;\n  auto rc = DosCreateNPipe((const unsigned char*)name.c_str(), &hPipe, NP_ACCESS_DUPLEX,\n                           NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 0xFF, \n\t\t\t   Pipe::PIPE_BUFFER_SIZE,\n                           Pipe::PIPE_BUFFER_SIZE,\n                           0); // 0 == No Wait.\n  VLOG(2) << \"create_pipe(\" << name << \"); handle: \" << hPipe;\n  return hPipe;\n}\n\nbool Pipe::WaitForClient(std::chrono::duration<double> timeout) {\n  auto end = std::chrono::system_clock::now() + timeout;\n  do {\n    if (DosConnectNPipe(handle_) == NO_ERROR) {\n      return true;\n    }\n    DosSleep(200);\n  } while (std::chrono::system_clock::now() <= end);\n  return false;\n}\n\nstd::string pipe_name(const std::string_view part) { \n  return fmt::format(\"\\\\PIPE\\\\{}\", part); \n}\n\nbool close_pipe(Pipe::PIPE_HANDLE h, bool server) {\n  if (server) {\n    auto rc = DosDisConnectNPipe(h) == NO_ERROR;\n    VLOG(2) << \"close_pipe(\" << h << \"); Disconnect: rc: \" << rc;\n  }\n  auto rc = DosClose(h);\n  VLOG(2) << \"close_pipe(\" << h << \"); DosClose: rc: \" << rc;\n  return rc == NO_ERROR;\n}\n\n\n/** returns the number of bytes written on success */\nstd::optional<int> Pipe::write(const char* data, int size) {\n  unsigned long num_written;\n  VLOG(4) << \"Pipe::Write: \" << std::string(data, size);\n  auto rc = DosWrite(handle_, data, size, &num_written);\n  VLOG(4) << \"Wrote bytes to pipe: \" << num_written;\n  if (rc == NO_ERROR) {\n    return {num_written};\n  }\n  DosSleep(1);\n  return std::nullopt;\n}\n\n/** returns the number of bytes read on success */\nstd::optional<int> Pipe::read(char* data, int size) {\n  unsigned long num_read;\n  if (auto rc = DosRead(handle_, data, size, &num_read); rc == NO_ERROR && num_read > 0) {\n    VLOG(4) << \"Read bytes from pipe: \" << num_read;\n    return {num_read};\n  } else if (rc != 232 && rc != 0) {\n    last_error_ = rc;\n    return std::nullopt;\n  } else {\n    return {0};\n  }\n}\n\nbool Pipe::Open() {\n  VLOG(2) << \"Pipe::Open: \" << pipe_name_;\n  for (int i=0; i<10; i++) { // 10s\n    HFILE h;\n    ULONG ulAction;\n    auto rc = DosOpen((const unsigned char*)pipe_name_.c_str(), \n\t\t      &h, \n\t\t      &ulAction, \n\t\t      0, \n\t\t      FILE_NORMAL, \n\t\t      PIPE_OPEN_FLAG,\n\t\t      PIPE_OPEN_MODE,\n\t\t      0L);\n    if (rc == NO_ERROR) {\n      VLOG(3) << \"Pipe::Open: exiting: \" << pipe_name_;\n      handle_ = h;\n      return true;\n    }\n    LOG(WARNING) << \"Could not open pipe: '\" << pipe_name_ << \"'; Error: \" << rc;\n    DosSleep(1000);\n  }\n  LOG(WARNING) << \"Pipe::Open: failed to open: \" << pipe_name_;\n  return false;\n}\n\nstd::optional<char> Pipe::peek() {\n  char ch;\n  ULONG num_read, pipe_state;\n  AVAILDATA num_avail;\n\n  VLOG(3) << \"Peek: \" << ch;\n  if (auto rc = DosPeekNPipe(handle_, &ch, 1, &num_read, &num_avail, &pipe_state); rc  == NO_ERROR) {\n    if (num_read > 0) {\n      return {ch};\n    } else {\n      VLOG(4) << \"Peek: PipeState: \" << pipe_state;\n    }\n  } else {\n    VLOG(1) << \"Peek error: \" << rc;\n  }\n  if (pipe_state == 4) {\n    // NP_STATE_CLOSING\n    VLOG(1) << \"Pipe in NP_STATE_CLOSING; Closing Pipe.\";\n    Close();\n  } else if (pipe_state != 3) {\n    // 3 = connected\n    VLOG(1) << \"Pipe state != 3: == \" << pipe_state;\n  }\n  return std::nullopt;\n}\n\n\n\n\n}\n"
  },
  {
    "path": "core/pipe_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/pipe.h\"\n\n#include \"gtest/gtest.h\"\n#include \"core/log.h\"\n#include \"core/pipe.h\"\n\n#include <chrono>\n#include <string>\n#include <thread>\n\nusing namespace wwiv::core;\n\nstatic void client() {\n  Pipe cp(\"1\");\n  if (!cp.Open()) {\n    return;\n  }\n  cp.write(\"Hello\\0\", 6);\n}\n\nTEST(PipeTest, Smoke) {\n  Pipe sp(\"1\");\n  auto client_thread = std::thread(client);\n  ASSERT_TRUE(sp.Create());\n  EXPECT_TRUE(sp.WaitForClient(std::chrono::seconds(2)));\n\n  char s[81];\n  auto o = sp.read(s, 6);\n  ASSERT_TRUE(o);\n  EXPECT_STREQ(\"Hello\", s);\n\n  client_thread.join();\n}"
  },
  {
    "path": "core/pipe_win32.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/pipe.h\"\n\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"core/log.h\"\n#include \"fmt/format.h\"\n\nnamespace wwiv::core {\n\nstatic std::string ErrorAsString(DWORD last_error) {\n  LPSTR messageBuffer{nullptr};\n  const auto size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |\n                                       FORMAT_MESSAGE_IGNORE_INSERTS,\n                                   nullptr, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\n                                   reinterpret_cast<LPSTR>(&messageBuffer), 0, nullptr);\n\n  std::string message{messageBuffer, size};\n\n  // Free the buffer.\n  LocalFree(messageBuffer);\n  return fmt::format(\"({}): {}\", last_error, message);\n}\n\n \nPipe::PIPE_HANDLE create_pipe(const std::string& name) {\n  VLOG(2) << \"create_pipe: \" << name;\n  Pipe::PIPE_HANDLE hPipe =\n      CreateNamedPipe(name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,\n                      0xff, Pipe::PIPE_BUFFER_SIZE, Pipe::PIPE_BUFFER_SIZE, 0 /* default timeout */, NULL);\n  VLOG(4) << \"create_pipe(\" << name << \"); handle: \" << hPipe;\n  return hPipe;\n}\n\nstd::string pipe_name(const std::string_view part) {\n  return fmt::format(\"\\\\\\\\.\\\\PIPE\\\\{}\", part);\n}\n\nbool close_pipe(Pipe::PIPE_HANDLE h, bool server) {\n  VLOG(2) << \"close_pipe(\" << h << \")\";\n  if (h == INVALID_HANDLE_VALUE) {\n    return true;\n  }\n  if (server) {\n    VLOG(2) << \"Flushing File Buffers before shutdown.\";\n    FlushFileBuffers(h);\n  }\n  DisconnectNamedPipe(reinterpret_cast<HANDLE>(h));\n  CloseHandle(reinterpret_cast<HANDLE>(h));\n  return true;\n}\n\nbool Pipe::Open() {\n  VLOG(2) << \"Pipe::Open: \" << pipe_name_;\n  for (int i=0; i<30 * 5; i++) {\n    HANDLE h = CreateFile(pipe_name_.c_str(), GENERIC_READ | GENERIC_WRITE,\n                          0,             // no sharing\n                          NULL,          // default security attributes\n                          OPEN_EXISTING, // opens existing pipe\n                          0,             // default attributes\n                          NULL);         // no template file\n    if (h != INVALID_HANDLE_VALUE) {\n      handle_ = h;\n      VLOG(3) << \"Pipe::Open: sucess opened: \" << pipe_name_;\n      return true;\n    }\n    // Exit if an error other than ERROR_PIPE_BUSY occurs.\n    const auto e = GetLastError();\n    if (e != ERROR_PIPE_BUSY && e != ERROR_FILE_NOT_FOUND) {\n      LOG(WARNING) << \"Could not open pipe. Error: \" << ErrorAsString(e);\n      return false;\n    }\n    Sleep(200);\n  }\n  VLOG(3) << \"Pipe::Open: exiting: \" << pipe_name_;\n  return false;\n}\n\nbool Pipe::WaitForClient(std::chrono::duration<double> timeout) { \n  auto end = std::chrono::system_clock::now() + timeout;\n  do {\n    if (ConnectNamedPipe(handle_, nullptr) || GetLastError() == ERROR_PIPE_CONNECTED) {\n      return true;\n    }\n    LOG(WARNING) << \"WaitForClient: \" << ErrorAsString(GetLastError());\n    Sleep(250);\n  } while (std::chrono::system_clock::now() <= end);\n  return false;\n}\n\n\n/** returns the number of bytes written on success */\nstd::optional<int> Pipe::write(const char* data, int size) { \n  DWORD cbBytesWritten;\n  if (WriteFile(handle_, data, size, &cbBytesWritten, NULL)) {\n    return {cbBytesWritten};\n  }\n  return std::nullopt; \n}\n\n/** returns the number of bytes read on success */\nstd::optional<int> Pipe::read(char* data, int size) { \n  DWORD cbBytesRead;\n  if (ReadFile(handle_, data, size, &cbBytesRead, NULL)) {\n    return { cbBytesRead };\n  }\n  return std::nullopt;\n}\n\nstd::optional<char> Pipe::peek() {\n  char ch;\n  DWORD num_read, num_avail, num_leftmsg;\n  if (PeekNamedPipe(handle_, &ch, 1, &num_read, &num_avail, &num_leftmsg) && num_read>0) {\n    return {ch};\n  }\n  return std::nullopt;\n}\n\n}\n"
  },
  {
    "path": "core/scope_exit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_SCOPE_EXIT_H\n#define INCLUDED_CORE_SCOPE_EXIT_H\n\n#include <functional>\n#include <utility>\n\nnamespace wwiv::core {\n\n/**\n * \\short \n * A general-purpose scope guard to call the exit function <void()> when a scope\n * is exited, either by normal exit or an exception being thrown.\n * \\note \n * This class is not copyable, but is movable.\n *\n * Example use:\n * \\code\n *  // We need to call do_cleanup after everything else is done.\n *  auto on_exit = finally([=] { do_cleanup() });\n *  if (!foo()) {\n *    do_something()\n *    return false\n *  }\n *  do_something_else();\n *  return true;\n *  \\endcode \n */\ntemplate <class F = std::function<void()>> class ScopeExit final {\npublic:\n  ScopeExit() noexcept = default;\n  ScopeExit(const ScopeExit&) = delete;\n  ScopeExit(ScopeExit&& other) noexcept {\n    fn_.swap(other.fn_);\n    invoke_ = other.invoke_;\n  }\n\n  ScopeExit& operator=(const ScopeExit&) = delete;\n  ScopeExit& operator=(ScopeExit&& other) noexcept {\n    fn_(std::move(other.fn_));\n    invoke_ = other.invoke_;\n    return *this;\n  }\n\n  /**\n   * Construct a  scope guard with the exit function \"<void()>\".\n   */\n// GCC seems to display a warning on this, at least in 8.3.  MSVC can handle this in recent\n// builds of the compiler.\n#if defined(_MSC_VER)\n  [[nodiscard]]\n#endif // _MSC_VER\n  explicit ScopeExit(F fn)\n    : fn_(std::move(fn)), invoke_(true) {\n  }\n\n  ~ScopeExit() { if (invoke_) { fn_(); } }\n  void swap(std::function<void()> fn) {\n    invoke_ = false;\n    fn_.swap(fn);\n    if (fn_) {\n      invoke_ = true;\n    }\n  }\n\nprivate:\n  F fn_;\n  bool invoke_{false};\n};\n\ntemplate <class F> [[nodiscard]] auto finally(F&& f) noexcept {\n  return ScopeExit<std::decay_t<F>>{std::forward<F>(f)};\n}\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/scope_exit_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/scope_exit.h\"\n\nusing wwiv::core::ScopeExit;\nusing wwiv::core::finally;\n\nTEST(ScopeExitTest, Basic) {\n  auto committed = false;\n  auto f = [&] { committed = true; };\n  {\n    ScopeExit e(f);\n    ASSERT_FALSE(committed);\n  }\n  ASSERT_TRUE(committed);\n}\n\nTEST(ScopeExitTest, BasicFinally) {\n  auto committed = false;\n  auto f = [&] { committed = true; };\n  {\n    auto e = finally(f);\n    ASSERT_FALSE(committed);\n  }\n  ASSERT_TRUE(committed);\n}\n\nTEST(ScopeExitTest, Empty) {\n  // Should not crash on exit.\n  ScopeExit e;\n}\n\nTEST(ScopeExitTest, Swap) {\n  auto committed = false;\n  auto f = [&] { committed = true; };\n  {\n    ScopeExit e;\n    e.swap(f);\n    ASSERT_FALSE(committed);\n  }\n  ASSERT_TRUE(committed);\n}\n"
  },
  {
    "path": "core/semaphore_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/semaphore_file.h\"\n\n#include \"stl.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"fmt/format.h\"\n#include <cerrno>\n#include <fcntl.h>\n#include <string>\n#include <utility>\n\n#ifdef _WIN32\n//#include <direct.h>\n#include <io.h>\n//#include <share.h>\n\n#else // _WIN32\n#include <sys/file.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <utime.h>\n#endif  // _WIN32\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::os;\n\nnamespace wwiv::core {\n\n#ifndef _WIN32\n#ifndef O_TEMPORARY\n#define O_TEMPORARY 0\n#endif  // O_TEMPORARY\n#endif  // _WIN32\n\n// static \nSemaphoreFile SemaphoreFile::try_acquire(const std::filesystem::path& filepath,\n                                         const std::string& text,\n                                         std::chrono::duration<double> timeout) {\n  VLOG(2) << \"SemaphoreFile::try_acquire: '\" << filepath << \"'\";\n\n  if (File::Exists(filepath)) {\n    // Try to delete any stale semaphore files if they are over a day old.\n    auto ctime = std::chrono::system_clock::from_time_t(File::last_write_time(filepath));\n    auto oldest_allowed = std::chrono::system_clock::now() - std::chrono::hours(24);\n    auto minutes_old = std::chrono::duration_cast<std::chrono::minutes>(std::chrono::system_clock::now() - ctime);\n    VLOG(1) << fmt::format(\"Found BSY file: '{}'; minutes old: {}\", filepath.string(), minutes_old.count());\n    if (ctime < oldest_allowed) {\n      LOG(WARNING) << fmt::format(\"Found stale BSY file: '{}'; minutes old: {}\", filepath.string(), minutes_old.count());\n      File::Remove(filepath, true);\n    }\n  }\n  const auto mode = O_CREAT | O_EXCL | O_TEMPORARY | O_RDWR;\n  const auto pmode = S_IREAD | S_IWRITE;\n  auto step = timeout / 10;\n  if (step > std::chrono::seconds(1)) {\n    step = std::chrono::seconds(1);\n  }\n  const auto start = std::chrono::steady_clock::now();\n  const auto end = start + timeout;\n  while (true) {\n    const auto fn = filepath.string();\n    if (const auto fd = open(fn.c_str(), mode, pmode); fd >= 0) {\n      if (const auto written = write(fd, text.c_str(), wwiv::stl::size_int(text));\n          written != wwiv::stl::ssize(text)) {\n        LOG(WARNING) << \"Short write on Semaphore file: \" << written << \"; vs: \" << text.size();\n      }\n      return {filepath, fd};\n    }\n    if (std::chrono::steady_clock::now() > end) {\n      VLOG(1) << \"FAILED: SemaphoreFile::try_acquire: '\" << filepath << \"'\";\n      throw semaphore_not_acquired(filepath);\n    }\n    sleep_for(step);\n  }\n}\n\n// static \nSemaphoreFile SemaphoreFile::acquire(const std::filesystem::path& filepath,\n                                     const std::string& text) {\n  return try_acquire(filepath, text, std::chrono::duration<double>::max());\n}\n\nSemaphoreFile::SemaphoreFile(std::filesystem::path path, int fd)\n  : path_(std::move(path)), fd_(fd) {\n}\n\nSemaphoreFile::~SemaphoreFile() {\n  VLOG(1) << \"~SemaphoreFile(): \" << path_ << \"; fd: \" << fd_;\n  if (fd_ < 0) {\n    LOG(ERROR) << \"Skipping closing since file already closed: \" << path_;\n    return;\n  }\n  if (close(fd_) == -1) {\n    LOG(ERROR) << \"Failed to close file: \" << path_ << \"; error: \" << errno;\n  }\n  fd_ = -1;\n#ifndef _WIN32\n  // Since we don't have O_TEMPORARY outside of WIN32, we unlink the file\n  // which will delete it once the last file handle is closed.\n  if (!File::Remove(path_, true)) {\n    LOG(ERROR) << \"Failed to unlink file: \" << path_ << \"; error: \" << errno;\n  }\n#endif  // _WIN32\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/semaphore_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_CORE_SEMAPHORE_FILE_H\n#define INCLUDED_CORE_SEMAPHORE_FILE_H\n\n#include <chrono>\n#include <filesystem>\n#include <stdexcept>\n#include <string>\n\nnamespace wwiv::core {\n\nstruct semaphore_not_acquired final : std::runtime_error {\n  explicit semaphore_not_acquired(const std::filesystem::path& filename)\n    : std::runtime_error(filename.string()) {\n  }\n};\n\nclass SemaphoreFile final {\npublic:\n  SemaphoreFile() = delete;\n\n  /** \n   * Tries to create the semaphore file, waiting up to timeout and then\n   * failing by throwing a semaphore_not_acquired exception.\n   * Will write 'text' into the semaphore file.\n   */\n  static SemaphoreFile try_acquire(const std::filesystem::path& filepath,\n                                   const std::string& text,\n                                   std::chrono::duration<double> timeout);\n\n  /**\n   * Tries to create the semaphore file, waiting up to timeout and then\n   * failing by throwing a semaphore_not_acquired exception.\n   */\n  static SemaphoreFile try_acquire(const std::filesystem::path& filepath,\n                                   std::chrono::duration<double> timeout) {\n    return try_acquire(filepath, \"\", timeout);\n  }\n\n  /**\n   * Tries to create the semaphore file, waiting forever.\n   * Will write 'text' into the semaphore file.\n   */\n  static SemaphoreFile acquire(const std::filesystem::path& filepath, const std::string& text);\n\n  /**\n   * Tries to create the semaphore file, waiting forever.\n   */\n  static SemaphoreFile acquire(const std::filesystem::path& filepath) {\n    return acquire(filepath, \"\");\n  }\n\n  ~SemaphoreFile();\n\n  [[nodiscard]] const std::filesystem::path& path() const { return path_; }\n  [[nodiscard]] int fd() const { return fd_; }\n\n  SemaphoreFile(SemaphoreFile&&) = default;\n  SemaphoreFile(const SemaphoreFile&) = delete;\n  SemaphoreFile& operator=(const SemaphoreFile&) = delete;\n\nprivate:\n  SemaphoreFile(std::filesystem::path, int fd);\n\n  const std::filesystem::path path_;\n  int fd_{-1};\n};\n\n} // namespace\n\n\n#endif\n"
  },
  {
    "path": "core/semaphore_file_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"gtest/gtest.h\"\n#include <chrono>\n#include <string>\n\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nTEST(SemaphoreFileTest, AlreadyAcqired) {\n  const wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n  std::filesystem::path path;\n  {\n    // Will throw if it can't acquire.\n    const auto ok =\n        SemaphoreFile::try_acquire(FilePath(tmp, \"x.sem\"), \"\", std::chrono::milliseconds(100));\n\n    path = ok.path();\n    LOG(INFO) << \"fd: \" << ok.fd() << \"; fn: \" << path;\n\n    EXPECT_TRUE(File::Exists(path));\n\n    try {\n      auto nok =\n          SemaphoreFile::try_acquire(FilePath(tmp, \"x.sem\"), \"\", std::chrono::milliseconds(10));\n      FAIL() << \"semaphore_not_acquired expected\";\n    } catch (const wwiv::core::semaphore_not_acquired&) {\n      // expected to happen.\n    }\n  }\n  EXPECT_FALSE(File::Exists(path)) << path;\n}\n\nTEST(SemaphoreFileTest, Smoke) {\n  const wwiv::core::test::FileHelper file;\n  const auto& tmp = file.TempDir();\n  // Will throw if it can't acquire.\n  const auto ok =\n      SemaphoreFile::try_acquire(FilePath(tmp, \"x.sem\"), \"\", std::chrono::milliseconds(100));\n\n  const auto& fn = ok.path();\n  LOG(INFO) << \"fd: \" << ok.fd() << \"; fn: \" << fn;\n\n  EXPECT_TRUE(File::Exists(fn)) << fn;\n}\n\nTEST(SemaphoreFileTest, OldFile) {\n  static const std::string kHelloWorld = \"Hello World\";\n  wwiv::core::test::FileHelper file;\n  const auto path = file.CreateTempFile(\"x.sem\", kHelloWorld);  \n\n  // Make it ~ one day ago\n  auto l = File::last_write_time(path);\n  l -= (60 * 60 * 25);\n  ASSERT_TRUE(File::set_last_write_time(path, l));\n\n  // Will throw if it can't acquire.\n  const auto ok =\n    SemaphoreFile::try_acquire(path, \"\", std::chrono::milliseconds(100));\n\n  const auto& fn = ok.path();\n  LOG(INFO) << \"fd: \" << ok.fd() << \"; fn: \" << fn;\n\n  EXPECT_TRUE(File::Exists(fn)) << fn;\n}\n"
  },
  {
    "path": "core/socket_connection.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/socket_connection.h\"\n\n#include <cerrno>\n#include <chrono>\n#include <cstring>\n#include <thread>\n#ifdef _WIN32\n#include <WS2tcpip.h>\n#include <WinSock2.h>\n#pragma comment(lib, \"Ws2_32.lib\")\n#pragma comment(lib, \"Mswsock.lib\")\n#pragma comment(lib, \"AdvApi32.lib\")\n#else // _WIN32\n#include <arpa/inet.h>\n#include <fcntl.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <unistd.h>\n#endif // _WIN32\n\n#ifdef __OS2__\n#include <libcx/net.h>\n#endif  // __OS2__\n\n#include \"scope_exit.h\"\n#include \"stl.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/socket_exceptions.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n\nusing std::chrono::duration;\nusing std::chrono::duration_cast;\nusing std::chrono::milliseconds;\nusing std::chrono::seconds;\nusing std::chrono::system_clock;\nusing std::chrono::time_point;\nusing wwiv::os::sleep_for;\nusing namespace wwiv::strings;\n\nnamespace wwiv::core {\n\nnamespace {\n\nconst auto SLEEP_MS = milliseconds(100);\n\nbool SetBlockingMode(SOCKET sock, bool blocking_mode) {\n  if (sock == INVALID_SOCKET) {\n    return false;\n  }\n\n#ifdef _WIN32\n  u_long nonblocking = blocking_mode ? 0 : 1;\n  return ioctlsocket(sock, FIONBIO, &nonblocking) == NO_ERROR;\n#else  // _WIN32\n  int flags = fcntl(sock, F_GETFL, 0 /* ignored */);\n  return fcntl(sock, F_SETFL, flags | O_NONBLOCK) != -1;\n#endif // _WIN32\n}\n\nbool SetNoDelayMode(SOCKET sock, bool no_delay) {\n#ifdef _WIN32\n  int one = no_delay ? 1 : 0;\n  return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&one), sizeof(one)) !=\n         SOCKET_ERROR;\n\n#else // _WIN32\n  // TODO(rushfan): set TCP_NODELAY\n  return true;\n\n#endif // _WIN32\n}\n\nbool WouldSocketBlock() {\n#ifdef _WIN32\n  return WSAGetLastError() == WSAEWOULDBLOCK;\n#else  // _WIN32\n  return errno == EWOULDBLOCK;\n#endif // _WIN32\n}\n\nstd::string GetLastErrorText() {\n#if defined ( _WIN32 )\n  char* error_text{nullptr};\n  auto on_exit = finally([&error_text] { LocalFree(error_text); });\n  const auto last_error = GetLastError();\n  FormatMessage(\n    FORMAT_MESSAGE_ALLOCATE_BUFFER |\n    FORMAT_MESSAGE_FROM_SYSTEM |\n    FORMAT_MESSAGE_IGNORE_INSERTS,\n    nullptr,\n    last_error,\n    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language\n    LPTSTR(&error_text),\n    0,\n    nullptr\n  );\n  return fmt::format(\"last_error: {} {}\", last_error, error_text);\n#else\n  return fmt::format(\"errno: {} {}\", errno, strerror(errno));\n#endif\n}\n\n} // namespace\n\nSocketConnection::SocketConnection(SOCKET sock)\n  : SocketConnection(sock, ExitMode::CLOSE_SOCKET) {\n}\n\nSocketConnection::SocketConnection(SOCKET sock, ExitMode exit_mode)\n  : sock_(sock), open_(true), exit_mode_(exit_mode) {\n  static auto initialized = InitializeSockets();\n  if (!initialized) {\n    throw socket_error(\"Unable to initialize sockets.\");\n  }\n\n  if (!SetBlockingMode(sock_, false)) {\n    LOG(ERROR) << \"SocketConnection: Unable to put socket into nonblocking mode.\";\n    closesocket(sock_);\n    sock_ = INVALID_SOCKET;\n    throw socket_error(\"SocketConnection: Unable to set nonblocking mode on the socket.\");\n  }\n  if (!SetNoDelayMode(sock_, true)) {\n    LOG(ERROR) << \"SocketConnection: Unable to put socket into nodelay mode.\";\n    closesocket(sock_);\n    sock_ = INVALID_SOCKET;\n    throw socket_error(\"SocketConnection: Unable to set nodelay mode on the socket.\");\n  }\n}\n\nstd::unique_ptr<SocketConnection> Connect(const std::string& host, int port) {\n  static auto initialized = InitializeSockets();\n  if (!initialized) {\n    throw socket_error(\"SocketConnection::Connect Unable to initialize sockets.\");\n  }\n\n  struct addrinfo hints{};\n  hints.ai_family = PF_UNSPEC;\n  hints.ai_socktype = SOCK_STREAM;\n  hints.ai_protocol = IPPROTO_IP;\n\n  const auto port_string = std::to_string(port);\n  struct addrinfo* address = nullptr;\n  const auto result_addrinfo = getaddrinfo(host.c_str(), port_string.c_str(), &hints, &address);\n  if (result_addrinfo != 0) {\n    LOG(ERROR) << \"ERROR calling getaddrinfo: \" << result_addrinfo;\n    // TODO(rushfan): Throw connection error here?\n  }\n  for (auto* res = address; res != nullptr; res = res->ai_next) {\n    auto s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);\n    if (s == INVALID_SOCKET) {\n      continue;\n    }\n    const auto result = connect(s, res->ai_addr, static_cast<int>(res->ai_addrlen));\n    if (result == SOCKET_ERROR) {\n      closesocket(s);\n    } else {\n      // success;\n      freeaddrinfo(address);\n      try {\n        return std::make_unique<SocketConnection>(s);\n      } catch (const socket_error&) {\n      }\n    }\n  }\n  throw connection_error(host, port);\n}\n\n/*\n ** Leaving here in case I need it again\n// From: http://stackoverflow.com/questions/2493136/how-can-i-obtain-the-ipv4-address-of-the-client\n// get sockaddr, IPv4 or IPv6:\nstatic void *get_in_addr(struct sockaddr* sa) {\n  if (sa->sa_family == AF_INET) {\n    return &(((struct sockaddr_in*)sa)->sin_addr);\n  }\n\n  return &(((struct sockaddr_in6*)sa)->sin6_addr);\n}\n*/\n\nSocketConnection::~SocketConnection() {\n\n  if (exit_mode_ == ExitMode::LEAVE_SOCKET_OPEN || sock_ == INVALID_SOCKET) {\n    // Bail out of here, either we ignore the socket or it is invalid.\n    return;\n  }\n\n  if (exit_mode_ == ExitMode::RESET_TO_BLOCKING && sock_ != INVALID_SOCKET) {\n    SetBlockingMode(sock_, true);\n    SetNoDelayMode(sock_, false);\n  } else if (exit_mode_ == ExitMode::CLOSE_SOCKET && sock_ != INVALID_SOCKET) {\n    closesocket(sock_);\n    sock_ = INVALID_SOCKET;\n  }\n}\n\ntemplate <typename TYPE, std::size_t SIZE = sizeof(TYPE)>\nstatic int read_TYPE(const SOCKET sock, TYPE* data, const duration<double> d, bool throw_on_timeout,\n                     std::size_t size = SIZE) {\n  const auto end = system_clock::now() + d;\n  auto* p = reinterpret_cast<char*>(data);\n  auto total_read = 0;\n  auto remaining = static_cast<int>(size);\n  bool first = true;\n  while (true) {\n    if (!first && system_clock::now() > end) {\n      if (throw_on_timeout) {\n        throw timeout_error(\"timeout error reading from socket.\");\n      }\n      return total_read;\n    }\n    first = false;\n    const auto result = recv(sock, p, remaining, 0);\n    if (result == SOCKET_ERROR) {\n      const auto saved_errno = errno;\n      const auto saved_errno_text = GetLastErrorText();\n      if (WouldSocketBlock()) {\n        sleep_for(SLEEP_MS);\n        continue;\n      }\n      if (saved_errno != ECONNRESET) {\n        // This happens normally as the other side disconnects.\n        LOG(ERROR) << \"Got Socket Error on recv: \" << saved_errno_text;\n      }\n      return total_read;\n    }\n    if (result <= 0) {\n      return total_read;\n    }\n    total_read += result;\n    if (total_read < static_cast<int>(size)) {\n      p += result;\n      remaining -= result;\n      continue;\n    }\n    return total_read;\n  }\n}\n\nint SocketConnection::receive(void* data, const int size, duration<double> d) {\n  const auto num_read = read_TYPE<void, 0>(sock_, data, d, true, size);\n  if (open_ && num_read == 0) {\n    throw socket_closed_error(fmt::sprintf(\"receive: got zero read from socket. expected: \", size));\n  }\n  return num_read;\n}\n\nint SocketConnection::receive_upto(void* data, const int size, duration<double> d) {\n  return read_TYPE<void, 0>(sock_, data, d, false, size);\n}\n\nstd::string SocketConnection::receive(int size, duration<double> d) {\n  const auto data = std::make_unique<char[]>(size);\n  const auto num_read = receive(data.get(), size, d);\n  return std::string(data.get(), num_read);\n}\n\nstd::string SocketConnection::receive_upto(int size, duration<double> d) {\n  const auto data = std::make_unique<char[]>(size);\n  const auto num_read = receive_upto(data.get(), size, d);\n  return std::string(data.get(), num_read);\n}\n\nstd::string SocketConnection::read_line(int max_size, duration<double> d) {\n  std::string s;\n  auto size = 0;\n  try {\n    while (true) {\n      char data = 0;\n      const auto num_read = read_TYPE<char>(sock_, &data, d, true);\n      if (!open_) {\n        throw socket_closed_error(\"read_line: socket not open\");\n      }\n      if (num_read == 0) {\n        break;\n      }\n      s.push_back(data);\n      size++;\n      if (data == '\\n') {\n        break;\n      }\n      if (size > max_size) {\n        break;\n      }\n    }\n  } catch (const timeout_error&) {\n  }\n  return s;\n}\n\n#ifndef MSG_NOSIGNAL\n#define MSG_NOSIGNAL 0\n#endif  // MSG_NOSIGNAL \n\nint SocketConnection::send(const void* data, int size, duration<double>) {\n  const auto sent = ::send(sock_, static_cast<const char*>(data), size, MSG_NOSIGNAL);\n  if (open_ && sent != size) {\n    if (sent == -1) {\n      throw socket_closed_error(\n          StrCat(\"Socket Closed; errno: \", strerror(errno)));\n    }\n    LOG(ERROR) << \"ERROR: send != packet size.  size: \" << size << \"; sent: \" << sent;\n  }\n  return size;\n}\n\nint SocketConnection::send(const std::string& s, duration<double> d) {\n  return send(s.data(), stl::size_int(s), d);\n}\n\nint SocketConnection::send_line(const std::string& s, duration<double> d) {\n  return send(s + \"\\r\\n\", d);\n}\n\nuint16_t SocketConnection::read_uint16(duration<double> d) {\n  uint16_t data = 0;\n  const auto num_read = read_TYPE<uint16_t>(sock_, &data, d, true);\n  if (open_ && num_read == 0) {\n    throw socket_closed_error(\n        StrCat(\"read_uint16: got zero read from socket. expected: \", sizeof(uint16_t)));\n  }\n  return ntohs(data);\n}\n\nuint8_t SocketConnection::read_uint8(duration<double> d) {\n  uint8_t data = 0;\n  const auto num_read = read_TYPE<uint8_t>(sock_, &data, d, true);\n  if (open_ && num_read == 0) {\n    throw socket_closed_error(\n        StrCat(\"read_uint8: got zero read from socket. expected: \", sizeof(uint8_t)));\n  }\n  return data;\n}\n\nbool SocketConnection::close() {\n  if (open_) {\n    open_ = false;\n    closesocket(sock_);\n  }\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/socket_connection.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_SOCKET_CONNECTION_H\n#define INCLUDED_CORE_SOCKET_CONNECTION_H\n\n#include \"core/connection.h\"\n#include \"core/net.h\" // SOCKET\n#include <chrono>\n#include <cstdint>\n#include <memory>\n#include <string>\n\n#ifdef _WIN32\n#include <WinSock2.h>\n\n#else  // _WIN32\n#endif  // _WIN32\n\nnamespace wwiv::core {\n\nclass SocketConnection;\n\nstd::unique_ptr<SocketConnection> Connect(const std::string& host, int port);\n\nclass SocketConnection : public Connection {\npublic:\n\n  enum class ExitMode { LEAVE_SOCKET_OPEN, RESET_TO_BLOCKING, CLOSE_SOCKET };\n\n  explicit SocketConnection(SOCKET sock);\n  SocketConnection(SOCKET sock, ExitMode exit_mode);\n  SocketConnection(const SocketConnection& other) = delete;\n  SocketConnection& operator=(const SocketConnection& other) = delete;\n\n  virtual ~SocketConnection();\n\n  int receive(void* data, int size, std::chrono::duration<double> d) override;\n  std::string receive(int size, std::chrono::duration<double> d) override;\n\n  /** Receives up to size bytes and will return partial reads. */\n  int receive_upto(void* data, int size, std::chrono::duration<double> d);\n  std::string receive_upto(int size, std::chrono::duration<double> d);\n\n  std::string read_line(int max_size, std::chrono::duration<double> d);\n  int send(const void* data, int size, std::chrono::duration<double> d) override;\n  int send(const std::string& s, std::chrono::duration<double> d) override;\n\n  /** Sends a line s and \\r\\n */\n  int send_line(const std::string& s, std::chrono::duration<double> d);\n\n  uint16_t read_uint16(std::chrono::duration<double> d) override;\n  uint8_t read_uint8(std::chrono::duration<double> d) override;\n\n  bool is_open() const override { return open_; }\n  bool close() override;\n  /** returns the raw socket handle */\n  SOCKET socket() const { return sock_; }\n\nprivate:\n  SOCKET sock_;\n  bool open_;\n  ExitMode exit_mode_ = ExitMode::LEAVE_SOCKET_OPEN;\n};\n\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/socket_exceptions.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/socket_exceptions.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <stdexcept>\n\nnamespace wwiv::core {\n\nconnection_error::connection_error(const std::string& host, int port)\n  : socket_error(fmt::format(\"Error connecting to: {}:{}\", host, port)) {\n  LOG(ERROR) << \"connection_error: \" << host << \":\" << port;\n}\n\nsocket_error::socket_error(const std::string& message)\n  : std::runtime_error(message) {\n  // Don't log this since we *often* hit a timeout since we use nonblocking\n  // sockets and that's OK.\n  VLOG(4) << \"socket_error: \" << message;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "core/socket_exceptions.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_SOCKET_EXCEPTIONS_H\n#define INCLUDED_CORE_SOCKET_EXCEPTIONS_H\n\n#include <stdexcept>\n#include <string>\n\nnamespace wwiv::core {\n\nstruct socket_error : std::runtime_error {\n  explicit socket_error(const std::string& message);\n};\n\nstruct socket_closed_error : socket_error {\n  explicit socket_closed_error(const std::string& message)\n    : socket_error(message) {\n  }\n};\n\nstruct timeout_error : socket_error {\n  explicit timeout_error(const std::string& message)\n    : socket_error(message) {\n  }\n};\n\nstruct connection_error : socket_error {\n  connection_error(const std::string& host, int port);\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "core/stl.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/stl.h\"\n\nnamespace wwiv::stl {\n\n} // namespace wwiv::tl\n"
  },
  {
    "path": "core/stl.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_STL_H\n#define INCLUDED_CORE_STL_H\n\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include <algorithm>\n#include <iterator>\n#include <map>\n#include <optional>\n#include <string>\n\nnamespace wwiv::stl {\n\ntemplate <typename C>\nbool contains(C const& container, typename C::const_reference key) {\n  return std::find(std::begin(container), std::end(container), key) != std::end(container);\n}\n\ntemplate <typename K, typename V, typename C, typename A>\nbool contains(std::map<K, V, C, A> const& m, K const& key) {\n  return m.find(key) != std::end(m);\n}\n\n// Partial specialization for maps with string keys (allows using const char* for lookup values)\ntemplate <typename V, typename C, typename A>\nbool contains(std::map<std::string, V, C, A> const& m, const std::string& key) {\n  return m.find(key) != std::end(m);\n}\n\n// Partial specialization for maps with const string keys.\ntemplate <typename V, typename C, typename A>\nbool contains(std::map<const std::string, V, C, A> const& m, const std::string& key) {\n  return m.find(key) != std::end(m);\n}\n\nstruct ci_less {\n  bool operator()(const std::string& left, const std::string& right) const {\n    return strcasecmp(left.c_str(), right.c_str()) < 0;\n  }\n};\n\ntemplate <typename C>\ntypename C::mapped_type get_or_default(C const& c,\n                                       const typename C::key_type& key,\n                                       const typename C::mapped_type default_value) {\n  typename C::const_iterator iter = c.find(key);\n  if (iter == std::end(c)) {\n    return default_value;\n  }\n  return iter->second;\n}\n\ntemplate <typename C>\nint32_t size_int32(const C& c) {\n  const auto size = c.size();\n  CHECK_LE(size, static_cast<typename C::size_type>(std::numeric_limits<int32_t>::max()));\n  return static_cast<int32_t>(size);\n}\n\ntemplate <typename C>\nuint32_t size_uint32(const C& c) {\n  const auto size = c.size();\n  CHECK_LE(size, static_cast<typename C::size_type>(std::numeric_limits<uint32_t>::max()));\n  return static_cast<uint32_t>(size);\n}\n\ntemplate <typename C>\nint16_t size_int16(C const& c) {\n  const auto size = c.size();\n  CHECK_LE(size, static_cast<typename C::size_type>(std::numeric_limits<int16_t>::max()));\n  return static_cast<int16_t>(size);\n}\n\ntemplate <typename C>\nint8_t size_int8(C const& c) {\n  const auto size = c.size();\n  CHECK_LE(size, static_cast<typename C::size_type>(std::numeric_limits<int8_t>::max()));\n  return static_cast<int8_t>(size);\n}\n\n// From https://en.cppreference.com/w/cpp/iterator/size (The C++20 version)\ntemplate <class C>\nconstexpr auto ssize(const C& c) \n    -> std::common_type_t<std::ptrdiff_t,\n                          std::make_signed_t<decltype(c.size())>> \n{\n    using R = std::common_type_t<std::ptrdiff_t, std::make_signed_t<decltype(c.size())>>;\n    return static_cast<R>(c.size());\n}\n\ntemplate <typename C>\nint size_int(const C& c) {\n  return static_cast<int>(::wwiv::stl::ssize(c));\n}\n\ntemplate <typename C, typename S = std::size_t, typename R>\nbool insert_at(C& c, S pos, R r) {\n  auto n = static_cast<decltype(c.size())>(pos);\n\n  if (n < 0 || n > c.size()) {\n    return false;\n  }\n  auto it = std::begin(c);\n  std::advance(it, n);\n  c.insert(it, r);\n  return true;\n}\n\ntemplate <typename C, typename S = std::size_t>\nbool erase_at(C& c, S on) {\n  auto n = static_cast<decltype(c.size())>(on);\n  if (n >= c.size()) {\n    return false;\n  }\n  auto it = std::begin(c);\n  std::advance(it, n);\n  c.erase(it);\n  return true;\n}\n\n// Specialization for std::map\ntemplate <typename K, typename V, typename C, class A=std::allocator<C>>\nauto at(std::map<K, V, C, A> const& map, typename std::decay<K>::type key) ->\nconst V& {\n  \n  const auto pos = map.find(key);\n  if (pos != std::end(map)) {\n    return pos->second;\n  }\n  LOG(ERROR) << \"Caught std::out_of_range on pos: \" << key;\n  LOG(ERROR) << wwiv::os::stacktrace();\n  DLOG(FATAL) << \"Terminating in debug build.\";\n  throw std::out_of_range(\"Out of range on key\");\n}\n\n// Specialization for std::map\ntemplate <typename K, typename V, typename C, class A=std::allocator<C>>\nauto at(std::map<K, V, C, A> & map, typename std::decay<K>::type key) ->\nV& {\n  \n  auto pos = map.find(key);\n  if (pos != std::end(map)) {\n    return pos->second;\n  }\n  LOG(ERROR) << \"Caught std::out_of_range on pos: \" << key;\n  LOG(ERROR) << wwiv::os::stacktrace();\n  DLOG(FATAL) << \"Terminating in debug build.\";\n  throw std::out_of_range(\"Out of range on key\");\n}\n\n\ntemplate <typename C, class Allocator=std::allocator<C>>\ntypename C::const_reference at(C const& container, typename C::size_type pos) {\n  try {\n    return container.at(pos);\n  } catch (const std::out_of_range&) {\n    LOG(ERROR) << \"Caught std::out_of_range on pos: \" << pos;\n    LOG(ERROR) << wwiv::os::stacktrace();\n    DLOG(FATAL) << \"Terminating in debug build.\";\n    throw;\n  }\n}\n\n/**\n * like Container::at except will log a stack trace on failure before\n * logging an exception.\n */\ntemplate <typename C, class Allocator=std::allocator<C>>\ntypename C::reference at(C& container, typename C::size_type pos) {\n  try {\n    return container.at(pos);\n  } catch (const std::out_of_range&) {\n    LOG(ERROR) << \"Caught std::out_of_range on pos: \" << pos;\n    LOG(ERROR) << wwiv::os::stacktrace();\n    DLOG(FATAL) << \"Terminating in debug build.\";\n    throw;\n  }\n}\n\n/**\n * like Container::at except returns an optional of the value type the\n * container returns.\n */\ntemplate <typename C, class Allocator=std::allocator<C>>\nstd::optional<typename C::value_type> optional_at(C& container, typename C::size_type pos) {\n  try {\n    return container.at(pos);\n  } catch (const std::out_of_range&) {\n    return std::nullopt;\n  }\n}\n\n\n} // namespace\n\n\n#endif"
  },
  {
    "path": "core/stl_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/stl.h\"\n#include <deque>\n#include <map>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::stl;\n\nTEST(StlTest, Contains_VectorInts) {\n  const std::vector<int> ints = { 1, 2, 3 };\n\n  EXPECT_TRUE(contains(ints, 1));\n  EXPECT_FALSE(contains(ints, 0));\n  EXPECT_FALSE(contains(ints, 4));\n}\n\nTEST(StlTest, Contains_VectorStrings) {\n  const std::vector<std::string> strings = { \"one\", \"two\", \"three\" };\n\n  EXPECT_TRUE(contains(strings, \"one\"));\n  EXPECT_FALSE(contains(strings, \"\"));\n  EXPECT_FALSE(contains(strings, \"four\"));\n}\n\nTEST(StlTest, Contains_MapStringInts) {\n  const std::map<std::string, int> ints = { { \"one\", 1}, {\"two\", 2}, {\"three\", 3} };\n\n  EXPECT_TRUE(contains(ints, \"one\"));\n  EXPECT_FALSE(contains(ints, \"zero\"));\n}\n\nTEST(StlTest, Contains_MapStringStrings) {\n  const std::map<std::string, std::string> strings = { { \"one\", \"1\" }, { \"two\", \"2\" }, { \"three\", \"3\" } };\n\n  EXPECT_TRUE(contains(strings, \"one\"));\n  EXPECT_FALSE(contains(strings, \"zero\"));\n}\n\nTEST(StlTest, Contains_MapIntInts) {\n  const std::map<int, int> ints = { { 0, 1}, {1, 2}, {2, 3} };\n\n  EXPECT_TRUE(contains(ints, 1));\n  EXPECT_FALSE(contains(ints, 3));\n}\n\nTEST(StlTest, Contains_MapConstStringStrings) {\n  const std::map<const std::string, std::string> strings = {{\"one\", \"1\"},{\"two\", \"2\"},{\"three\", \"3\"}};\n\n  EXPECT_TRUE(contains(strings, \"one\"));\n  EXPECT_FALSE(contains(strings, \"zero\"));\n}\n\nTEST(StlTest, SizeAsInt) {\n  const std::vector<int> v = {1, 2, 3};\n  const auto vs = wwiv::stl::ssize(v);\n  EXPECT_EQ(3, vs);\n}\n\nTEST(StlTest, SizeAsInt32) {\n  const std::vector<int> v = {1, 2, 3};\n  const auto vs = size_int32(v);\n  EXPECT_EQ(3, vs);\n}\n\nTEST(StlTest, SizeAsInt16) {\n  const std::vector<int> v = {1, 2, 3};\n  const auto vs = size_int16(v);\n  EXPECT_EQ(3, vs);\n}\n\nTEST(StlTest, SizeAsInt8) {\n  const std::vector<int> v = {1, 2, 3};\n  const auto vs = size_int8(v);\n  EXPECT_EQ(3, vs);\n}\n\nTEST(StlTest, InsertAt) {\n  struct Foo { int a; };\n  std::vector<Foo> v = {Foo{1}};\n  const std::vector<Foo>::size_type pos = 0;\n  insert_at(v, pos, Foo{0});\n  EXPECT_EQ(0, v[0].a);\n  EXPECT_EQ(1, v[1].a);\n}\n\nTEST(StlTest, EraseAt) {\n  struct Foo { int a; };\n  std::vector<Foo> v = {Foo{0}, Foo{1}, Foo{2}};\n  const std::vector<Foo>::size_type pos = 1;\n  erase_at(v, pos);\n  EXPECT_EQ(0, v[0].a);\n  EXPECT_EQ(2, v[1].a);\n}\n\n\nTEST(StlTest, At_Vector_Smoke) {\n  // ReSharper disable once CppLocalVariableMayBeConst\n  /**NOCONST */ std::vector<int> v{ 1, 2, 3 };\n\n  EXPECT_EQ(1, at(v, 0));\n}\n\nTEST(StlTest, At_Vector_Smoke_Const) {\n  const std::vector<int> v{ 1, 2, 3 };\n\n  EXPECT_EQ(1, at(v, 0));\n}\n\nTEST(StlTest, At_Dequeue_Smoke_Const) {\n  const std::deque<int> v{ 1, 2, 3 };\n\n  EXPECT_EQ(1, at(v, 0));\n}\n\nTEST(StlTest, At_Map_Smoke_Const) {\n  const std::map<int, char> v{ {1,'a'}, {2,'b'}, {3,'c'} };\n\n  EXPECT_EQ('a', at(v, 1));\n}\n\n//TEST(StlTest, At_Map_Death) {\n//  const std::map<int, char> v{ {1,'a'}, {2,'b'}, {3,'c'} };\n//\n//  EXPECT_DEATH_IF_SUPPORTED(at(v, 20), \".*\");\n//}\n"
  },
  {
    "path": "core/strcasestr.cpp",
    "content": "/*\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies of the Software and its Copyright notices. In addition publicly\ndocumented acknowledgment must be given that this software has been used if no\nsource code of this software is made available publicly. Making the source\navailable publicly means including the source for this software with the\ndistribution, or a method to get this software via some reasonable mechanism\n(electronic transfer via a network or media) as well as making an offer to\nsupply the source on request. This Copyright notice serves as an offer to\nsupply the source on on request as well. Instead of this, supplying\nacknowledgments of use of this software in either Copyright notices, Manuals,\nPublicity and Marketing documents or any documentation provided with any\nproduct containing this software. This License does not apply to any software\nthat links to the libraries provided by this software (statically or\ndynamically), but only to the software provided.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nSource:\nEvil 1.7.4\nThe Evil library tried to port some convenient Unix functions\nto the Windows (XP or CE) platform. They are planned to be used\n\nhttp://git.enlightenment.org/legacy/evil.git/tree/src/lib/evil_string.c?id=eeaddf80d0d547d4c216974038c0599b34359695\n*/\n\n#include <cctype>\n#include <cstring>\n\nchar* strcasestr_i(const char* haystack, const char* needle) {\n\n  if (!haystack || !needle) {\n    return nullptr;\n  }\n\n  const auto length_needle = strlen(needle);\n  auto length_haystack = strlen(haystack);\n\n  if (length_haystack < length_needle) {\n    return nullptr;\n  }\n\n  length_haystack -= length_needle;\n\n  for (size_t i = 0; i <= length_haystack; i++) {\n\n    for (size_t j = 0; j < length_needle; j++) {\n\n      unsigned char c1 = haystack[i + j];\n      unsigned char c2 = needle[j];\n      if (toupper(c1) != toupper(c2))\n        goto next;\n    }\n    return const_cast<char*>(haystack + i);\n  next:\n    ;\n  }\n\n  return nullptr;\n}"
  },
  {
    "path": "core/strings-ng.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_STRINGS_NG_H\n#define INCLUDED_STRINGS_NG_H\n#include <cctype>\n#include <type_traits>\n\n\n\n#endif  // __INCLUDED_STRINGS_NG_H__"
  },
  {
    "path": "core/strings.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/strings.h\"\n\n#include \"stl.h\"\n#include \"core/log.h\"\n#include \"fmt/format.h\"\n\n#include <algorithm>\n#include <cctype>\n#include <cstring>\n#include <iostream>\n#include <string>\n#include <vector>\n\n#ifdef _MSC_VER\n#include <sal.h>\n#endif\n\n\nconst unsigned char* translate_letters[] = {\n    reinterpret_cast<const unsigned char *>(\"abcdefghijklmnopqrstuvwxyz�������\"),\n    reinterpret_cast<const unsigned char *>(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ�������\"),\n    nullptr,\n};\nconst char* DELIMS_WHITE = \" \\t\\r\\n\";\nconst char* DELIMS_CRLF = \"\\r\\n\";\n\nnamespace wwiv::strings {\n\n/**\n * Compares the strings\n * @param str1 string to compare\n * @param str2 other string to compare\n * @return true of the strings contain the same contents\n */\nbool IsEquals(const char* str1, const char* str2) {\n  return StringCompare(str1, str2) == 0;\n}\n\n/**\n * Compares the strings, ignoring case\n * @param str1 string to compare\n * @param str2 other string to compare\n * @return true of the strings contain the same contents ignoring case\n */\nbool iequals(const char* str1, const char* str2) {\n  CHECK(str1 != nullptr);\n  CHECK(str2 != nullptr);\n\n  return StringCompareIgnoreCase(str1, str2) == 0;\n}\n\nbool iequals(const std::string& s1, const std::string& s2) {\n  return s1.size() == s2.size() &&\n         std::equal(s1.begin(), s1.end(), s2.begin(),\n                    [](const char& c1, const char& c2)\n                    {\n                      return (std::tolower(c1) == std::tolower(c2));\n                    });\n}\n\n\nint StringCompareIgnoreCase(const char* str1, const char* str2) {\n  CHECK(str1 != nullptr);\n  CHECK(str2 != nullptr);\n  WWIV_ANALYSIS_ASSUME(str1 != nullptr);\n  WWIV_ANALYSIS_ASSUME(str2 != nullptr);\n\n  return strcasecmp(str1, str2);\n}\n\nint StringCompare(const char* str1, const char* str2) {\n  CHECK(str1 != nullptr);\n  CHECK(str2 != nullptr);\n  WWIV_ANALYSIS_ASSUME(str1 != nullptr);\n  WWIV_ANALYSIS_ASSUME(str2 != nullptr);\n\n  return strcmp(str1, str2);\n}\n\nvoid StringReplace(std::string* orig, const std::string& old_string,\n                   const std::string& new_string) {\n  auto pos = orig->find(old_string, 0);\n  while (pos != std::string::npos) {\n    orig->replace(pos, old_string.length(), new_string);\n    pos = orig->find(old_string, pos + new_string.length());\n  }\n}\n\nstd::vector<std::string> SplitString(const std::string& original_string, const std::string& delims) {\n  return SplitString(original_string, delims, true);\n}\n\nstd::vector<std::string> SplitString(const std::string& original_string, const std::string& delims, bool skip_empty) {\n  std::vector<std::string> v;\n  SplitString(original_string, delims, skip_empty, &v);\n  return v;\n}\n\nvoid SplitString(const std::string& original_string, const std::string& delims, std::vector<std::string>* out) {\n  SplitString(original_string, delims, true, out);\n}\n\nvoid SplitString(const std::string& original_string, const std::string& delims, bool skip_empty,\n                 std::vector<std::string>* out) {\n  auto s(original_string);\n  for (auto found = s.find_first_of(delims); found != std::string::npos;\n       s = s.substr(found + 1), found = s.find_first_of(delims)) {\n    if (found > 0) {\n      out->push_back(s.substr(0, found));\n    } else if (!skip_empty && found == 0) {\n      // Add empty lines.\n      out->push_back({});\n    }\n  }\n  if (!s.empty()) {\n    out->push_back(s);\n  }\n}\n\nstd::tuple<std::string, std::string> SplitOnce(const std::string& original_string, const std::string& delims) {\n  if (const auto idx = original_string.find_first_of(delims); idx != std::string::npos) {\n    return std::make_tuple(original_string.substr(0, idx), original_string.substr(idx + 1));\n  }\n  return std::make_tuple(original_string, \"\");\n}\n\nstd::tuple<std::string, std::string> SplitOnceLast(const std::string& original_string,\n    const std::string& delims) {\n  if (const auto idx = original_string.find_last_of(delims); idx != std::string::npos) {\n    return std::make_tuple(original_string.substr(0, idx), original_string.substr(idx + 1));\n  }\n  return std::make_tuple(original_string, \"\");\n}\n\n\nbool starts_with(const std::string& input, const std::string& match) {\n  return input.size() >= match.size()\n         && std::equal(std::begin(match), std::end(match), std::begin(input));\n}\n\nbool ends_with(const std::string& input, const std::string& match) {\n  return input.size() >= match.size()\n         && std::equal(match.rbegin(), match.rend(), input.rbegin());\n}\n\n/**\n * Returns a string justified and padded with \"bg\".\n *\n * @param s The text to justify\n * @param length the length of the text\n * @param bg the character to use as the background\n * @param just_type one of the following: LEFT, RIGHT\n */\nvoid StringJustify(std::string* s, int length, char bg, JustificationType just_type) {\n  if (ssize(*s) > length) {\n    *s = s->substr(0, length);\n    return;\n  }\n  if (ssize(*s) == length) {\n    return;\n  }\n\n  const auto delta = length - s->size();\n  switch (just_type) {\n  case JustificationType::LEFT: {\n    s->resize(length, bg);\n  }\n  break;\n  case JustificationType::RIGHT: {\n    const auto tmp(*s);\n    *s = StrCat(std::string(delta, bg), tmp);\n  }\n  break;\n  }\n}\n\n\n/**\n * Removes spaces from the beginning and the end of the string s.\n *\n * @param str the string from which to remove spaces\n */\nvoid StringTrim(char* str) {\n  std::string s(str);\n  StringTrim(&s);\n  strcpy(str, s.c_str());\n}\n\n/**\n* Removes spaces from the beginning and the end of the string s.\n*\n* @param s the string from which to remove spaces\n*/\nvoid StringTrim(std::string* s) {\n  auto pos = s->find_first_not_of(DELIMS_WHITE);\n  s->erase(0, pos);\n\n  pos = s->find_last_not_of(DELIMS_WHITE);\n  s->erase(pos + 1);\n}\n\n/**\n* Removes CF and LF from the beginning and the end of the string s.\n*\n* @param s the string from which to remove spaces\n*/\nvoid StringTrimCRLF(std::string* s) {\n  auto pos = s->find_first_not_of(DELIMS_CRLF);\n  s->erase(0, pos);\n\n  pos = s->find_last_not_of(DELIMS_CRLF);\n  s->erase(pos + 1);\n}\n\n/**\n* Removes spaces from the beginning and the end of the string s and\n* returns it as a new string\n*\n* @param orig the string from which to remove spaces\n* @return orig with spaces removed.\n*/\nstd::string StringTrim(const std::string& orig) {\n  if (orig.empty()) {\n    return {};\n  }\n  auto s(orig);\n  auto pos = s.find_first_not_of(DELIMS_WHITE);\n  s.erase(0, pos);\n\n  pos = s.find_last_not_of(DELIMS_WHITE);\n  s.erase(pos + 1);\n  return s;\n}\n\nvoid StringTrimBegin(std::string* s) {\n  const auto pos = s->find_first_not_of(DELIMS_WHITE);\n  s->erase(0, pos);\n}\n\nvoid StringTrimEnd(std::string* s) {\n  const auto pos = s->find_last_not_of(DELIMS_WHITE);\n  s->erase(pos + 1);\n}\n\nstd::string StringTrimEnd(std::string_view s) {\n  const auto pos = s.find_last_not_of(DELIMS_WHITE);\n  return std::string(s.data(), pos + 1);\n}\n\n/**\n * Removes the whitespace from the end of the string\n * @param str The string from which to remove the trailing whitespace\n */\nvoid StringTrimEnd(char* str) {\n  std::string s(str);\n  StringTrimEnd(&s);\n  strcpy(str, s.c_str());\n}\n\nvoid StringUpperCase(std::string* s) {\n  std::transform(std::begin(*s), std::end(*s), std::begin(*s), to_upper_case<char>);\n}\n\nstd::string ToStringUpperCase(const std::string& orig) {\n  auto s(orig);\n  StringUpperCase(&s);\n  return s;\n}\n\nstatic char tolower_char(int c) {\n  return static_cast<char>(tolower(c));\n}\n\nvoid StringLowerCase(std::string* s) {\n  std::transform(std::begin(*s), std::end(*s), std::begin(*s), tolower_char);\n}\n\nstd::string ToStringLowerCase(const std::string& orig) {\n  std::string s(orig);\n  StringLowerCase(&s);\n  return s;\n}\n\n\nstd::string JoinStrings(const std::vector<std::string>& lines, const std::string& end_of_line) {\n  std::string out;\n  for (const auto& line : lines) {\n    out += line;\n    out += end_of_line;\n  }\n  return out;\n}\n\nint size_without_colors(const std::string& s) {\n  const auto stripped = stripcolors(s);\n  return stl::size_int(stripped);\n}\n\nstd::string trim_to_size_ignore_colors(const std::string& orig, int size) {\n  auto s{orig};\n  while (size_without_colors(s) > size) {\n    s.pop_back();\n  }\n  return s;\n}\n\nstd::string pad_to_ignore_colors(const std::string& orig, int size) {\n  const auto len = size_without_colors(orig);\n  if (size <= len) {\n    return orig;\n  }\n  return orig + std::string(size - len, ' ');\n}\n\nstd::string::size_type size(const std::string& s) {\n  return s.size();\n}\n\nstd::string::size_type size(const char* s) {\n  if (s == nullptr) {\n    return 0;\n  }\n  return static_cast<std::string::size_type>(strlen(s));\n}\n\n// String length without colors as an int. size_int for compatibility\n// with stl::size_int\nint ssize(const char* s) { return static_cast<int>(size(s)); }\nint size_int(const char* s) { return static_cast<int>(size(s)); }\n\n// String length without colors as an int\nint ssize(const unsigned char* s) {\n  return static_cast<int>(size(reinterpret_cast<const char*>(s)));\n}\n\n// String length without colors as an int\nint size_int(const unsigned char* s) {\n  return static_cast<int>(size(reinterpret_cast<const char*>(s)));\n}\n\nint ssize(const std::string& s) { return static_cast<int>(s.size()); }\n\nint size_int(const std::string& s) { return static_cast<int>(s.size()); }\n\nstd::string trim_to_size(const std::string& orig, int max_size) {\n  auto s(orig);\n  while (ssize(s) > max_size) {\n    s.pop_back();\n  }\n  return s;\n}\n\n} // namespace wwiv\n\n/**\n * Is the character c a possible color code. (is it #, B, or a digit)\n * @param c The Character to test.\n */\nstatic bool IsColorCode(char c) {\n  if (!c) {\n    return false;\n  }\n  return c == '#' || isdigit(c);\n}\n\nbool wwiv::strings::contains(const std::string& haystack, const std::string_view& needle) noexcept {\n  try {\n    return haystack.find(needle) != std::string::npos;\n  } catch (...) {\n    DLOG(FATAL) << \"Caught exeption in wwiv::strings::contains: '\"\n                <<  haystack << \"' : '\" << needle << \"'\";\n    return false;\n  }\n}\n\nchar* stripcolors(const char* str) {\n  CHECK(str);\n  WWIV_ANALYSIS_ASSUME(str != nullptr);\n  static char s[255];\n  const auto result = stripcolors(std::string(str));\n  strcpy(s, result.c_str());\n  return s;\n}\n\ntemplate <typename I>\nstatic bool is_ansi_seq_start(I& i, const std::string& orig) {\n  auto left = std::string(i, end(orig));\n  if (left.size() < 3) {\n    return false;\n  }\n  if (left.at(1) != '[') {\n    return false;\n  }\n  return left.find('m') != std::string::npos;\n}\n\n/**\n * Removes the WWIV color codes and pipe codes from the string\n *\n * @param orig The text from which to remove the color codes.\n * @return A new string without the color codes\n */\nstd::string stripcolors(const std::string& orig) {\n  std::string out;\n  for (auto i = begin(orig); i != end(orig); ++i) {\n    if (*i == 27 && (i + 1) != end(orig)) {\n      auto left = std::string(i, end(orig));\n      if (!is_ansi_seq_start(i, orig)) {\n        out.push_back(*i);\n        continue;\n      }\n      // skip everything until we have the end of the ansi sequence.\n      while (i != end(orig) && !std::isalpha(*i)) {\n        ++i;\n      }\n      if (i != end(orig)) {\n        ++i;\n      }\n    }\n    if (i == end(orig)) {\n      break;\n    }\n    if ((i + 1) != end(orig)\n        && (i + 2) != end(orig)\n        && *i == '|'\n        && IsColorCode(*(i + 1))\n        && IsColorCode(*(i + 2))) {\n      ++i;\n      ++i;\n    } else if ((i + 1) != end(orig)\n               && *i == 3\n               && isdigit(*(i + 1))) {\n      ++i;\n    } else {\n      out.push_back(*i);\n    }\n  }\n  return out;\n}\n\n/**\n * Translates the character ch into uppercase using WWIV's translation tables\n * @param ch The character to translate\n * @return The uppercase version of the character\n */\nunsigned char upcase(unsigned char ch) {\n  if (const auto * ss = reinterpret_cast<const unsigned char*>(strchr(reinterpret_cast<const char*>(translate_letters[0]), ch)); ss) {\n    ch = translate_letters[1][ss - translate_letters[0]];\n  }\n  return ch;\n}\n\n/**\n * Translates the character ch into lower using WWIV's translation tables\n * @param ch The character to translate\n * @return The lowercase version of the character\n */\nunsigned char locase(unsigned char ch) {\n  if (auto * ss = (unsigned char*)strchr((const char*)translate_letters[1], ch); ss) {\n    ch = translate_letters[0][ss - translate_letters[1]];\n  }\n  return ch;\n}\n\nvoid properize(char* text) {\n  if (text == nullptr) {\n    return;\n  }\n\n  for (auto i = 0; i < wwiv::strings::ssize(text); i++) {\n    if ((i == 0) || ((i > 0) && ((text[i - 1] == ' ') || (text[i - 1] == '-') ||\n                                 (text[i - 1] == '.')))) {\n      text[i] = wwiv::strings::to_upper_case<char>(text[i]);\n    } else {\n      text[i] = wwiv::strings::to_lower_case(text[i]);\n    }\n  }\n}\n\nstd::string properize(const std::string& text) {\n  if (text.empty()) {\n    return std::string(\"\");\n  }\n\n  char last = ' ';\n  std::ostringstream os;\n  for (auto ch : text) {\n    if (last == ' ' || last == '-' || last == '.') {\n      os << wwiv::strings::to_upper_case<char>(ch);\n    } else {\n      os << wwiv::strings::to_lower_case<char>(ch);\n    }\n    last = ch;\n  }\n  return os.str();\n}\n\nbool ifind_first(const std::string& haystack, const std::string& needle) {\n  const auto it =\n      std::search(std::begin(haystack), std::end(haystack), std::begin(needle), std::end(needle),\n                  [](char a, char b) { return std::toupper(a) == std::toupper(b); });\n  return it != std::end(haystack);\n}\n\n#ifdef _WIN32\n// from strcasestr\nchar* strcasestr_i(const char* haystack, const char* needle);\n\nchar* strcasestr(const char* haystack, const char* needle) {\n  if (strlen(needle) == 0) {\n    // unlike strstr() and wcsstr() passing an empty string results in NULL being returned.\n    // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb773439%28v=vs.85%29.aspx\n    return const_cast<char*>(haystack);\n  }\n  return strcasestr_i(haystack, needle);\n}\n#else\n\n/** Converts string to uppercase */\nchar *strupr(char *s) {\n  for (int i = 0; s[i] != 0; i++) {\n    s[i] = wwiv::strings::to_upper_case<char>(s[i]);\n  }\n\n  return s;\n}\n\n// Reverses a string\nchar *strrev(char *s) {\n  CHECK(s != nullptr);\n  char szTempBuffer[255];\n  auto str = static_cast<int>(strlen(s));\n  CHECK_LE(str, 255);\n\n  for (int i = str; i > - 1; i--) {\n    s[i] = szTempBuffer[str - i];\n  }\n  strcpy(s, szTempBuffer);\n  return s;\n}\n\n#endif  // _WIN32\n"
  },
  {
    "path": "core/strings.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_STRINGS_H\n#define INCLUDED_CORE_STRINGS_H\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cstring> // strncpy\n// ReSharper disable once CppUnusedIncludeDirective\n#include <ctime>   // struct tm\n#include <functional>\n#include <limits>\n#include <sstream>\n#include <string>\n#include <string_view>\n#include <type_traits>\n#include <vector>\n\n// NOTE(rushfan): Keep all of these since sometimes windows headers get\n// included before this one.\n#ifdef StrCat\n#undef StrCat\n#endif // StrCat\n#ifdef min\n#undef min\n#endif\n#ifdef max\n#undef max\n#endif\n\n\nnamespace wwiv::strings {\n\nenum class JustificationType { LEFT, RIGHT };\n\ntemplate <typename A> std::string StrCat(const A& a) noexcept {\n  try {\n    std::ostringstream ss;\n    ss << a;\n    return ss.str();\n  } catch (...) {\n    return {};\n  }\n}\n\ntemplate <typename A, typename... Args> std::string StrCat(const A& a, const Args&... args) noexcept {\n  try {\n    std::ostringstream ss;\n    ss << a << StrCat(args...);\n    return ss.str();\n  } catch (...) {\n    return {};\n  }\n}\n\n  /**\n   * Safe string -> character array. Ensures the character\n   * array is null-terminated.\n   * NB: Will assert on Windows if out is too small. Will attempt\n   * to use safe versions of the CRT as possible in the future.\n   */\n  template <size_t SIZE> bool to_char_array(char (&out)[SIZE], const std::string& s) noexcept {\n#ifdef _MSC_VER\n    strncpy_s(out, s.c_str(), SIZE);\n#else\n    strncpy(out, s.c_str(), SIZE);\n#endif // _WIN32\n    out[SIZE - 1] = '\\0';\n    return s.size() <= SIZE;\n  }\n\n  /**\n   * Safe string -> character array.\n   * ** NB: ** Does not ensure the character array is null-terminated.\n   * Also won't assert on Windows if out is too small.\n   */\n  template <size_t SIZE> bool to_char_array_no_null(char (&out)[SIZE], const std::string& s) {\n    strncpy(out, s.c_str(), SIZE);\n    return s.size() <= SIZE;\n  }\n\n  /**\n   * Safe string -> character array. Ensures the character\n   * array is null-terminated.\n   * NB: will trim the output if it's too long.\n   */\n  template <size_t SIZE> bool to_char_array_trim(char (&out)[SIZE], const std::string& s) noexcept {\n    strncpy(out, s.c_str(), SIZE);\n    out[SIZE - 1] = '\\0';\n    return s.size() <= SIZE;\n  }\n\n  // Comparisons\n  [[nodiscard]] bool IsEquals(const char* str1, const char* str2);\n  [[nodiscard]] bool iequals(const char* str1, const char* str2);\n  [[nodiscard]] bool iequals(const std::string& s1, const std::string& s2);\n  [[nodiscard]] int StringCompareIgnoreCase(const char* str1, const char* str2);\n  [[nodiscard]] int StringCompare(const char* str1, const char* str2);\n\n  /**\n   * @brief Replace all occurences in `orig` of `old_string` with `new_string`.\n   * @param[in,out] orig original string containing the text to which to apply substitutions\n   * @param[in]     old_string    substrings to be replaced by new_string\n   * @param[in]     new_string    substrings to replace old_string\n  */\n  void StringReplace(std::string* orig, const std::string& old_string,\n                     const std::string& new_string);\n\n  /**\n   * @brief Splits a string on the boundaries defined by delims \n   * \n   * @param[in] original_string The string to be split\n   * @param[in] delims          the boundaries at which to split the strong\n   * @return                    A vector containing original_string split at delims\n  */\n  std::vector<std::string> SplitString(const std::string& original_string,\n                                       const std::string& delims);\n\n  /**\n   * @brief Splits a string on the boundaries defined by delims\n   * \n   * @param[in] original_string The string to be split\n   * @param[in] delims          the boundaries at which to split the strong\n   * @param[in[ skip_empty      Should empty strings be not included in the returned std::vector.\n   * @return                    A vector containing original_string split at delims\n   */\n  [[nodiscard]] std::vector<std::string> SplitString(const std::string& original_string,\n                                       const std::string& delims, bool skip_empty);\n\n  /**\n   * @brief Splits a string on the boundaries defined by delims\n   * \n   * @param[in] original_string The string to be split\n   * @param[in] delims          the boundaries at which to split the strong\n   * @param[out] out            A vector containing original_string split at delims\n   */\n  void SplitString(const std::string& original_string, const std::string& delims,\n                   std::vector<std::string>* out);\n\n  /**\n   * @brief Splits a string on the boundaries defined by delims\n   * \n   * @param[in] original_string The string to be split\n   * @param[in] delims          the boundaries at which to split the strong\n   * @param[in[ skip_empty      Should empty strings be not included in the returned std::vector.\n   * @param[out] out            A vector containing original_string split at delims\n   */\n  void SplitString(const std::string& original_string, const std::string& delims, bool skip_empty,\n                   std::vector<std::string>* out);\n\n  /**\n   * Splits a string once on the first occurrence of any character in delims.\n   */\n  std::tuple<std::string, std::string> SplitOnce(const std::string& original_string, const std::string& delims);\n\n  /**\n   * Splits a string once on the last occurrence of any character in delims.\n   */\n  std::tuple<std::string, std::string> SplitOnceLast(const std::string& original_string, const std::string& delims);\n\n  [[nodiscard]] bool starts_with(const std::string& input, const std::string& match);\n  [[nodiscard]] bool ends_with(const std::string& input, const std::string& match);\n\n  void StringJustify(std::string* s, int length, char bg,\n                     JustificationType just_type);\n  void StringTrim(char* str);\n  void StringTrim(std::string* s);\n  [[nodiscard]] std::string StringTrim(const std::string& orig);\n\n  void StringTrimCRLF(std::string* s);\n\n  /**\n   * Removes the whitespace from the end of the string\n   * \n   * @param str The string from which to remove the trailing whitespace\n   */\n  void StringTrimEnd(std::string* s);\n  std::string StringTrimEnd(std::string_view s);\n\n  void StringTrimBegin(std::string* s);\n  void StringUpperCase(std::string* s);\n  [[nodiscard]] std::string ToStringUpperCase(const std::string& s);\n  void StringLowerCase(std::string* s);\n  [[nodiscard]] std::string ToStringLowerCase(const std::string& s);\n\n  /**\n   * Joints the strings in lines, using end_of_line in between each line.\n   */\n  [[nodiscard]] std::string JoinStrings(const std::vector<std::string>& lines, const std::string& end_of_line);\n\n  // String length without colors\n  [[nodiscard]] int size_without_colors(const std::string& s);\n\n  /** returns a copy of orig trimmed to size, excluding colors. */\n  [[nodiscard]] std::string trim_to_size_ignore_colors(const std::string& orig, int size);\n\n  /**\n   * Returns orig padded to size, excluding color codes.\n   */\n  [[nodiscard]] std::string pad_to_ignore_colors(const std::string& orig, int size);\n\n  // String length\n  [[nodiscard]] std::string::size_type size(const std::string& s);\n\n  // String length\n  [[nodiscard]] std::string::size_type size(const char* s);\n\n  // String length as an int\n  [[nodiscard]] int ssize(const char* s);\n\n  // String length as an int\n  [[nodiscard]] int ssize(const unsigned char* s);\n\n  // String length as an int\n  [[nodiscard]] int ssize(const std::string& s);\n\n  // String length as an int\n  [[nodiscard]] int size_int(const char* s);\n\n  // String length as an int\n  [[nodiscard]] int size_int(const unsigned char* s);\n\n  // String length as an int\n  [[nodiscard]] int size_int(const std::string& s);\n\n  /** returns a copy of orig trimmed to size, excluding colors. */\n  std::string trim_to_size(const std::string& orig, int size);\n\n  /** Type-safe version of toupper */\n  template<class T, typename = std::enable_if_t<std::is_convertible_v<T, char>, char>>\n  T to_upper_case(const T a) { return static_cast<T>(::toupper(a)); }\n\n  template<class T>\n  std::enable_if_t<std::is_convertible_v<T, char>, char>\n  to_upper_case_char(const T a) { return static_cast<T>(::toupper(a)); }\n\n  /** Type safe version of toupper */\n  template<class T, typename = std::enable_if_t<std::is_convertible_v<T, char>, char>>\n  T to_lower_case(const T a) { return static_cast<T>(::tolower(a)); }\n\n  template<class T>\n  std::enable_if_t<std::is_convertible_v<T, char>, char>\n  to_lower_case_char(const T a) { return static_cast<T>(::tolower(a)); }\n\n  template <typename T, typename std::enable_if<std::is_unsigned<T>::value, T>::type* = nullptr>\n  T to_number(const std::string& s, int b = 10) {\n    char* end;\n    auto result = strtoul(s.c_str(), &end, b);\n    if (errno == ERANGE) {\n      return 0;\n    }\n    if (result > std::numeric_limits<T>::max()) {\n      return std::numeric_limits<T>::max();\n    }\n    if (result < std::numeric_limits<T>::min()) {\n      return std::numeric_limits<T>::min();\n    }\n    return static_cast<T>(result);\n  }\n\n  template <typename T, typename std::enable_if<std::is_signed<T>::value, T>::type* = nullptr>\n  T to_number(const std::string& s, int b = 10) {\n    char* end;\n    auto result = strtol(s.c_str(), &end, b);\n    if (errno == ERANGE) {\n      return 0;\n    }\n    if (result > std::numeric_limits<T>::max()) {\n      return std::numeric_limits<T>::max();\n    }\n    if (result < std::numeric_limits<T>::min()) {\n      return std::numeric_limits<T>::min();\n    }\n    return static_cast<T>(result);\n  }\n\n  /**\n   * Return true if haystack contains needed as a substring.\n   *\n   * Like boost::contains.\n   * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1679r3.html\n   * for proposal to add as std::string::contains.\n   */\n  bool contains(const std::string& haystack, const std::string_view& needle) noexcept;\n\n  } // namespace wwiv\n\n  // Function Prototypes\n  [[nodiscard]] char* stripcolors(const char* str);\n  [[nodiscard]] std::string stripcolors(const std::string& orig);\n  [[nodiscard]] unsigned char upcase(unsigned char ch);\n  [[nodiscard]] unsigned char locase(unsigned char ch);\n\n  void properize(char* text);\n  [[nodiscard]] std::string properize(const std::string& text);\n\n  extern const char* DELIMS_WHITE;\n\n  /** returns true if needle is found in haystack ,ignoring case */\n  [[nodiscard]] bool ifind_first(const std::string& haystack, const std::string& needle);\n\n#ifdef _WIN32\n#ifndef strcasecmp\n  #define strcasecmp(a, b) _stricmp(a, b)\n#endif\n#ifndef strncasecmp\n  #define strncasecmp(a, b, c) _strnicmp(a, b, c)\n#endif\n\n  char* strcasestr(const char* haystack, const char* needle);\n\n#else // _WIN32\n  char* strupr(char* s);\n  char* strrev(char* s);\n\n#endif // _WIN32\n\n#endif // __INCLUDED_STRINGS_H__\n"
  },
  {
    "path": "core/strings_test.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2008-2022, WWIV Software Services                */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"gtest/gtest.h\"\r\n\r\n#include <chrono>\r\n#include <iomanip>\r\n#include <sstream>\r\n#include <string>\r\n#include <vector>\r\n#include \"core/strings.h\"\r\n\r\nusing namespace wwiv::strings;\r\n\r\nTEST(StringsTest, StripColors) {\r\n  EXPECT_EQ(std::string(\"\"), stripcolors(std::string(\"\")));\r\n  EXPECT_EQ(std::string(\"|\"), stripcolors(std::string(\"|\")));\r\n  EXPECT_EQ(std::string(\"|0\"), stripcolors(std::string(\"|0\")));\r\n  EXPECT_EQ(std::string(\"12345\"), stripcolors(std::string(\"12345\")));\r\n  EXPECT_EQ(std::string(\"abc\"), stripcolors(std::string(\"abc\")));\r\n  EXPECT_EQ(std::string(\"1 abc\"), stripcolors(std::string(\"\\x031 abc\")));\r\n  EXPECT_EQ(std::string(\"\\x03 abc\"), stripcolors(std::string(\"\\x03 abc\")));\r\n  EXPECT_EQ(std::string(\"abc\"), stripcolors(std::string(\"|15abc\")));\r\n}\r\n\r\nTEST(StringsTest, StripColors_AnsiSeq) {\r\n  EXPECT_EQ(std::string(\"\"), stripcolors(std::string(\"\\x1b[0m\")));\r\n  EXPECT_EQ(std::string(\"\"), stripcolors(std::string(\"\\x1b[0;33;46;1m\")));\r\n  EXPECT_EQ(std::string(\"|\"), stripcolors(std::string(\"|\\x1b[0;33;46;1m\")));\r\n  EXPECT_EQ(std::string(\"abc\"), stripcolors(std::string(\"|15\\x1b[0;33;46;1mabc\")));\r\n  EXPECT_EQ(std::string(\"abc\"),\r\n            stripcolors(std::string(\"\\x1b[0m|15\\x1b[0;33;46;1ma\\x1b[0mb\\x1b[0mc\\x1b[0m\")));\r\n}\r\n\r\nTEST(StringsTest, StringColors_CharStarVersion) {\r\n  EXPECT_STREQ(\"\", stripcolors(\"\"));\r\n  EXPECT_STREQ(\"|\", stripcolors(\"|\"));\r\n  EXPECT_STREQ(\"|0\", stripcolors(\"|0\"));\r\n  EXPECT_STREQ(\"12345\", stripcolors(\"12345\"));\r\n}\r\n\r\nTEST(StringsTest, Properize) {\r\n  EXPECT_EQ(std::string(\"Rushfan\"), properize(std::string(\"rushfan\")));\r\n  EXPECT_EQ(std::string(\"Rushfan\"), properize(std::string(\"rUSHFAN\")));\r\n  EXPECT_EQ(std::string(\"\"), properize(std::string(\"\")));\r\n  EXPECT_EQ(std::string(\" \"), properize(std::string(\" \")));\r\n  EXPECT_EQ(std::string(\"-\"), properize(std::string(\"-\")));\r\n  EXPECT_EQ(std::string(\".\"), properize(std::string(\".\")));\r\n  EXPECT_EQ(std::string(\"R\"), properize(std::string(\"R\")));\r\n  EXPECT_EQ(std::string(\"R\"), properize(std::string(\"r\")));\r\n  EXPECT_EQ(std::string(\"Ru\"), properize(std::string(\"RU\")));\r\n  EXPECT_EQ(std::string(\"R.U\"), properize(std::string(\"r.u\")));\r\n  EXPECT_EQ(std::string(\"R U\"), properize(std::string(\"r u\")));\r\n  EXPECT_EQ(std::string(\"Rushfan\"), properize(std::string(\"Rushfan\")));\r\n}\r\n\r\nTEST(StringsTest, StrCat_Smoke) {\r\n  static const std::string kRushfan = \"rushfan\";\r\n  EXPECT_EQ(kRushfan, StrCat(\"rush\", \"fan\"));\r\n  EXPECT_EQ(kRushfan, StrCat(\"ru\", \"sh\", \"fan\"));\r\n  EXPECT_EQ(kRushfan, StrCat(\"ru\", \"sh\", \"f\", \"an\"));\r\n  EXPECT_EQ(kRushfan, StrCat(\"r\", \"u\", \"sh\", \"f\", \"an\"));\r\n  EXPECT_EQ(kRushfan, StrCat(\"r\", \"u\", \"s\", \"h\", \"f\", \"an\"));\r\n}\r\n\r\nTEST(StringsTest, StrCat_AlphaNumeric) {\r\n  static const std::string kWoot = \"w00t\";\r\n  EXPECT_EQ(kWoot, StrCat(\"w\", 0, 0, \"t\"));\r\n}\r\n\r\nTEST(StringsTest, StringReplace_EntireString) {\r\n  std::string s = \"Hello\";\r\n  const std::string world = \"World\";\r\n  StringReplace(&s, \"Hello\", \"World\");\r\n  EXPECT_EQ(world, s);\r\n}\r\n\r\nTEST(StringsTest, StringReplace_PartialString) {\r\n  std::string s = \"Hello World\";\r\n  const std::string expected = \"World World\";\r\n  StringReplace(&s, \"Hello\", \"World\");\r\n  EXPECT_EQ(expected, s);\r\n}\r\n\r\nTEST(StringsTest, StringReplace_NotFound) {\r\n  std::string s = \"Hello World\";\r\n  const std::string expected(s);\r\n  StringReplace(&s, \"Dude\", \"Where's my car\");\r\n  EXPECT_EQ(expected, s);\r\n}\r\n\r\nTEST(StringsTest, SplitString_Basic) {\r\n  const std::string s = \"Hello World\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"World\"};\r\n  std::vector<std::string> actual;\r\n  SplitString(s, \" \", &actual);\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST(StringsTest, SplitString_BasicReturned) {\r\n  const std::string s = \"Hello World\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"World\"};\r\n  const auto actual = SplitString(s, \" \");\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST(StringsTest, SplitString_ExtraSingleDelim) {\r\n  const std::string s = \"Hello   World\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"World\"};\r\n  std::vector<std::string> actual;\r\n  SplitString(s, \" \", &actual);\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST(StringsTest, SplitString_ExtraSingleDelim_NoSkipEmpty) {\r\n  const std::string s = \"Hello   World\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"\", \"\", \"World\"};\r\n  std::vector<std::string> actual;\r\n  SplitString(s, \" \", false, &actual);\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST(StringsTest, SplitString_TwoDelims) {\r\n  const std::string s = \"Hello\\tWorld Everyone\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"World\", \"Everyone\"};\r\n  std::vector<std::string> actual;\r\n  SplitString(s, \" \\t\", &actual);\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\nTEST(StringsTest, SplitString_TwoDelimsBackToBack) {\r\n  const std::string s = \"Hello\\t\\tWorld  \\t\\t  Everyone\";\r\n  const std::vector<std::string> expected = {\"Hello\", \"World\", \"Everyone\"};\r\n  std::vector<std::string> actual;\r\n  SplitString(s, \" \\t\", &actual);\r\n  EXPECT_EQ(expected, actual);\r\n}\r\n\r\n\r\nTEST(StringsTest, SplitOnce_Smoke) {\r\n  auto [p, s] = SplitOnce(\"user.name\", \".\");\r\n  EXPECT_EQ(\"user\", p);\r\n  EXPECT_EQ(\"name\", s);\r\n}\r\n\r\nTEST(StringsTest, SplitOnce_Empty) {\r\n  auto [p, s] = SplitOnce(\"\", \".\");\r\n  EXPECT_EQ(\"\", p);\r\n  EXPECT_EQ(\"\", s);\r\n}\r\n\r\nTEST(StringsTest, SplitOnce_End) {\r\n  auto [p, s] = SplitOnce(\"user.\", \".\");\r\n  EXPECT_EQ(\"user\", p);\r\n  EXPECT_EQ(\"\", s);\r\n}\r\n\r\nTEST(StringsTest, SplitOnce_Start) {\r\n  auto [p, s] = SplitOnce(\".user\", \".\");\r\n  EXPECT_EQ(\"\", p);\r\n  EXPECT_EQ(\"user\", s);\r\n}\r\n\r\nTEST(StringsTest, String_int16_t) {\r\n  EXPECT_EQ(1234, to_number<int16_t>(\"1234\"));\r\n  EXPECT_EQ(0, to_number<int16_t>(\"0\"));\r\n  EXPECT_EQ(-1234, to_number<int16_t>(\"-1234\"));\r\n\r\n  EXPECT_EQ(std::numeric_limits<int16_t>::max(), to_number<int16_t>(\"999999\"));\r\n  EXPECT_EQ(std::numeric_limits<int16_t>::min(), to_number<int16_t>(\"-999999\"));\r\n\r\n  EXPECT_EQ(0, to_number<int16_t>(\"\"));\r\n  EXPECT_EQ(0, to_number<int16_t>(\"ASDF\"));\r\n}\r\n\r\nTEST(StringsTest, String_uint16_t) {\r\n  EXPECT_EQ(1234, to_number<uint16_t>(\"1234\"));\r\n  EXPECT_EQ(0, to_number<uint16_t>(\"0\"));\r\n\r\n  EXPECT_EQ(std::numeric_limits<uint16_t>::max(), to_number<uint16_t>(\"999999\"));\r\n\r\n  EXPECT_EQ(0, to_number<uint16_t>(\"\"));\r\n  EXPECT_EQ(0, to_number<uint16_t>(\"ASDF\"));\r\n}\r\n\r\nTEST(StringsTest, String_unsigned_int) {\r\n  EXPECT_EQ(1234u, to_number<unsigned int>(\"1234\"));\r\n  EXPECT_EQ(static_cast<unsigned int>(0), to_number<unsigned int>(\"0\"));\r\n\r\n  EXPECT_EQ(999999u, to_number<unsigned int>(\"999999\"));\r\n\r\n  EXPECT_EQ(0u, to_number<unsigned int>(\"\"));\r\n  EXPECT_EQ(0u, to_number<unsigned int>(\"ASDF\"));\r\n}\r\n\r\nTEST(StringsTest, String_int) {\r\n  EXPECT_EQ(1234, to_number<int>(\"1234\"));\r\n  EXPECT_EQ(0, to_number<int>(\"0\"));\r\n\r\n  EXPECT_EQ(999999, to_number<int>(\"999999\"));\r\n  EXPECT_EQ(-999999, to_number<int>(\"-999999\"));\r\n\r\n  EXPECT_EQ(0, to_number<int>(\"\"));\r\n  EXPECT_EQ(0, to_number<int>(\"ASDF\"));\r\n}\r\n\r\nTEST(StringsTest, String_int8_t) {\r\n  EXPECT_EQ(std::numeric_limits<int8_t>::max(), to_number<int8_t>(\"1234\"));\r\n  EXPECT_EQ(0, to_number<int8_t>(\"0\"));\r\n  EXPECT_EQ(std::numeric_limits<int8_t>::min(), to_number<int8_t>(\"-1234\"));\r\n\r\n  EXPECT_EQ(std::numeric_limits<int8_t>::max(), to_number<int8_t>(\"999999\"));\r\n  EXPECT_EQ(std::numeric_limits<int8_t>::min(), to_number<int8_t>(\"-999999\"));\r\n\r\n  EXPECT_EQ(0, to_number<int8_t>(\"\"));\r\n  EXPECT_EQ(0, to_number<int8_t>(\"ASDF\"));\r\n}\r\n\r\nTEST(StringsTest, String_uint8_t) {\r\n  EXPECT_EQ(12, to_number<uint8_t>(\"12\"));\r\n  EXPECT_EQ(255, to_number<uint8_t>(\"255\"));\r\n  EXPECT_EQ(0, to_number<uint8_t>(\"0\"));\r\n\r\n  EXPECT_EQ(std::numeric_limits<uint8_t>::max(), to_number<uint8_t>(\"999999\"));\r\n\r\n  EXPECT_EQ(0, to_number<uint8_t>(\"\"));\r\n  EXPECT_EQ(0, to_number<uint8_t>(\"ASDF\"));\r\n}\r\n\r\n\r\nTEST(StringsTest, StartsWith) {\r\n  EXPECT_TRUE(starts_with(\"--foo\", \"--\"));\r\n  EXPECT_TRUE(starts_with(\"asdf\", \"a\"));\r\n  EXPECT_TRUE(starts_with(\"asdf\", \"as\"));\r\n  EXPECT_TRUE(starts_with(\"asdf\", \"asd\"));\r\n  EXPECT_TRUE(starts_with(\"asdf\", \"asdf\"));\r\n  EXPECT_FALSE(starts_with(\"asdf\", \"asf\"));\r\n  EXPECT_FALSE(starts_with(\"asdf\", \"asdfe\"));\r\n}\r\n\r\nTEST(StringsTest, EndssWith) {\r\n  EXPECT_TRUE(ends_with(\"--foo\", \"foo\"));\r\n  EXPECT_TRUE(ends_with(\"asdf\", \"f\"));\r\n  EXPECT_TRUE(ends_with(\"asdf\", \"df\"));\r\n  EXPECT_TRUE(ends_with(\"asdf\", \"sdf\"));\r\n  EXPECT_TRUE(ends_with(\"asdf\", \"asdf\"));\r\n  EXPECT_FALSE(ends_with(\"asdf\", \"adf\"));\r\n  EXPECT_FALSE(ends_with(\"asdf\", \"easdf\"));\r\n}\r\n\r\nTEST(StringsTest, StringJustify_Left) {\r\n  std::string a(\"a\");\r\n  StringJustify(&a, 2, ' ', JustificationType::LEFT);\r\n  EXPECT_EQ(\"a \", a);\r\n\r\n  std::string b(\"b\");\r\n  StringJustify(&b, 2, ' ', JustificationType::LEFT);\r\n  EXPECT_EQ(\"b \", b);\r\n}\r\n\r\nTEST(StringsTest, StringJustify_LeftOtherChar) {\r\n  std::string a(\"a\");\r\n  StringJustify(&a, 2, '.', JustificationType::LEFT);\r\n  EXPECT_EQ(\"a.\", a);\r\n\r\n  std::string b(\"b\");\r\n  StringJustify(&b, 2, '.', JustificationType::LEFT);\r\n  EXPECT_EQ(\"b.\", b);\r\n}\r\n\r\nTEST(StringsTest, StringJustify_Right) {\r\n  std::string a(\"a\");\r\n  StringJustify(&a, 2, ' ', JustificationType::RIGHT);\r\n  EXPECT_EQ(\" a\", a);\r\n\r\n  std::string b(\"b\");\r\n  StringJustify(&b, 2, ' ', JustificationType::RIGHT);\r\n  EXPECT_EQ(\" b\", b);\r\n}\r\n\r\nTEST(StringsTest, StringJustify_RightOtherChar) {\r\n  std::string a(\"a\");\r\n  StringJustify(&a, 2, '.', JustificationType::RIGHT);\r\n  EXPECT_EQ(\".a\", a);\r\n\r\n  std::string b(\"b\");\r\n  StringJustify(&b, 2, '.', JustificationType::RIGHT);\r\n  EXPECT_EQ(\".b\", b);\r\n}\r\n\r\nTEST(StringsTest, StringJustify_LongerString) {\r\n  std::string a(\"aaa\");\r\n  StringJustify(&a, 2, ' ', JustificationType::LEFT);\r\n  EXPECT_EQ(\"aa\", a);\r\n\r\n  std::string b(\"bbb\");\r\n  StringJustify(&b, 2, ' ', JustificationType::RIGHT);\r\n  EXPECT_EQ(\"bb\", b);\r\n}\r\n\r\nTEST(StringsTest, StringTrim) {\r\n  std::string a = \" a \";\r\n  StringTrim(&a);\r\n  EXPECT_EQ(\"a\", a);\r\n\r\n  std::string b = \"b\";\r\n  StringTrim(&b);\r\n  EXPECT_EQ(\"b\", b);\r\n}\r\n\r\nTEST(StringsTest, StringTrimBegin) {\r\n  std::string a = \" a \";\r\n  StringTrimBegin(&a);\r\n  EXPECT_EQ(\"a \", a);\r\n}\r\n\r\nTEST(StringsTest, StringTrimEnd) {\r\n  std::string a = \" a \";\r\n  StringTrimEnd(&a);\r\n  EXPECT_EQ(\" a\", a);\r\n}\r\n\r\nTEST(StringsTest, StringTrimEnd_NoTrailingSpace) {\r\n  std::string a = \" a\";\r\n  StringTrimEnd(&a);\r\n  EXPECT_EQ(\" a\", a);\r\n}\r\n\r\nTEST(StringsTest, StringTrimEnd_Empty) {\r\n  std::string a;\r\n  StringTrimEnd(&a);\r\n  EXPECT_TRUE(a.empty());\r\n}\r\n\r\nTEST(StringsTest, StringTrimEnd_StringView) {\r\n  const auto a = StringTrimEnd(\" a \");\r\n  EXPECT_EQ(\" a\", a);\r\n}\r\n\r\nTEST(StringsTest, StringTrimEnd_StringView_Empty) {\r\n  const auto a = StringTrimEnd(\"\");\r\n  EXPECT_TRUE(a.empty());\r\n}\r\n\r\nTEST(StringsTest, StringUpperCase) {\r\n  std::string a = \"aB\";\r\n  StringUpperCase(&a);\r\n  EXPECT_EQ(\"AB\", a);\r\n}\r\n\r\nTEST(StringsTest, StringLowerCase) {\r\n  std::string a = \"aB\";\r\n  StringLowerCase(&a);\r\n  EXPECT_EQ(\"ab\", a);\r\n}\r\n\r\nTEST(StringsTest, IEQuals_charstar) {\r\n  EXPECT_TRUE(iequals(\"foo\", \"foo\"));\r\n  EXPECT_FALSE(iequals(\"foo\", \"fo\"));\r\n  EXPECT_FALSE(iequals(\"fo\", \"foo\"));\r\n  EXPECT_FALSE(iequals(\"\", \"foo\"));\r\n  EXPECT_FALSE(iequals(\"foo\", \"\"));\r\n}\r\n\r\nTEST(StringsTest, IEQuals) {\r\n  EXPECT_TRUE(iequals(std::string(\"foo\"), std::string(\"foo\")));\r\n  EXPECT_FALSE(iequals(std::string(\"foo\"), std::string(\"fo\")));\r\n  EXPECT_FALSE(iequals(std::string(\"fo\"), std::string(\"foo\")));\r\n  EXPECT_FALSE(iequals(std::string(\"\"), std::string(\"foo\")));\r\n  EXPECT_FALSE(iequals(std::string(\"foo\"), std::string(\"\")));\r\n}\r\n\r\nTEST(StringsTest, SizeWithoutColors) {\r\n  EXPECT_EQ(1, size_without_colors(\"a\"));\r\n  EXPECT_EQ(1, size_without_colors(\"|#1a\"));\r\n  EXPECT_EQ(1, size_without_colors(\"|09a\"));\r\n  EXPECT_EQ(1, size_without_colors(\"|17|10a\"));\r\n}\r\n\r\nTEST(StringsTest, SizeWithoutColors_AnsiStr) {\r\n  EXPECT_EQ(0, size_without_colors(\"\\x1b[0m\"));\r\n  EXPECT_EQ(0, size_without_colors(\"\\x1b[0;33;46;1m\"));\r\n  EXPECT_EQ(1, size_without_colors(\"|\\x1b[0;33;46;1m\"));\r\n  EXPECT_EQ(3, size_without_colors(\"|15\\x1b[0;33;46;1mabc\"));\r\n  EXPECT_EQ(3, size_without_colors(\"\\x1b[0m|15\\x1b[0;33;46;1ma\\x1b[0mb\\x1b[0mc\\x1b[0m\"));\r\n}\r\n\r\nTEST(StringsTest, TrimToSizeIgnoreColors) {\r\n  EXPECT_EQ(\"a\", trim_to_size_ignore_colors(\"a\", 1));\r\n  EXPECT_EQ(\"|#5a\", trim_to_size_ignore_colors(\"|#5a\", 1));\r\n  EXPECT_EQ(\"|09|16a\", trim_to_size_ignore_colors(\"|09|16a\", 1));\r\n  EXPECT_EQ(\"|09|16a|09\", trim_to_size_ignore_colors(\"|09|16a|09\", 1));\r\n  EXPECT_EQ(\"|09|16a\", trim_to_size_ignore_colors(\"|09|16aa|09\", 1));\r\n}\r\n\r\nTEST(StringsTest, Test_Compiler_Supports_PutTime) {\r\n  using std::chrono::system_clock;\r\n\r\n  auto t = system_clock::to_time_t(system_clock::now());\r\n  auto tm = *std::localtime(&t);\r\n  std::ostringstream ss;\r\n  ss << std::put_time(&tm, \"%Z\");\r\n  const auto s = ss.str();\r\n\r\n  ASSERT_FALSE(s.empty());\r\n}\r\n\r\nTEST(StringsTest, Size) {\r\n  EXPECT_EQ(3u, wwiv::strings::size(\"Yo!\"));\r\n  EXPECT_EQ(0u, wwiv::strings::size(\"\"));\r\n  const std::string yo = \"Yo!\";\r\n  EXPECT_EQ(3u, wwiv::strings::size(yo));\r\n  EXPECT_EQ(0u, wwiv::strings::size(std::string(\"\")));\r\n}\r\n\r\nTEST(StringsTest, SSize) {\r\n  EXPECT_EQ(3, wwiv::strings::ssize(\"Yo!\"));\r\n  EXPECT_EQ(0, wwiv::strings::ssize(\"\"));\r\n  const std::string yo = \"Yo!\";\r\n  EXPECT_EQ(3, wwiv::strings::ssize(yo));\r\n  EXPECT_EQ(0, wwiv::strings::ssize(std::string(\"\")));\r\n}\r\n"
  },
  {
    "path": "core/test/file_helper.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*           Copyright (C)2014-2022, WWIV Software Services               */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"core/test/file_helper.h\"\r\n\r\n#include \"core/command_line.h\"\r\n#include \"core/datetime.h\"\r\n#include \"core/file.h\"\r\n#include \"core/log.h\"\r\n#include \"core/os.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"gtest/gtest.h\"\r\n#include <cerrno>\r\n#include <cstdio>\r\n#include <filesystem>\r\n#include <string>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::strings;\r\n\r\nnamespace wwiv::core::test {\r\n\r\n// Base test directory.\r\nstd::filesystem::path FileHelper::basedir_;\r\nstd::filesystem::path FileHelper::testdata_;\r\n\r\nFileHelper::FileHelper() {\r\n  const auto* const test_info = testing::UnitTest::GetInstance()->current_test_info();\r\n  const auto dir = fmt::format(\"{}_{}\", test_info->test_suite_name(), test_info->name());\r\n  tmp_ = File::canonical(CreateTempDir(dir));\r\n}\r\n\r\nstd::string FileHelper::DirName(const std::string& oname) const {\r\n  const auto name = File::FixPathSeparators(oname);\r\n  const auto tmpname = FilePath(tmp_, name).string();\r\n  return File::EnsureTrailingSlash(tmpname);\r\n}\r\n\r\nstd::filesystem::path FileHelper::Dir(const std::string& oname) const {\r\n  const auto name = File::FixPathSeparators(oname);\r\n  return FilePath(tmp_, name);\r\n}\r\n\r\nbool FileHelper::Mkdir(const std::string& oname) const {\r\n  return File::mkdir(Dir(File::FixPathSeparators(oname)));\r\n}\r\n\r\n// static\r\nvoid FileHelper::set_wwiv_test_tempdir(const std::string& d) noexcept {\r\n  // Use absolute vs. canonical here so that if you have symlinks\r\n  // or other things (like subst drives), you can use that to shorten\r\n  // the path -- making it less likely wwiv 4.x data structures will\r\n  // blow up on path length.\r\n  basedir_ = File::absolute(d);\r\n}\r\n\r\nvoid FileHelper::set_wwiv_test_tempdir_from_commandline(int argc, char* argv[]) noexcept {\r\n  CommandLine cmdline(argc, argv, \"net\");\r\n  cmdline.AddStandardArgs();\r\n  cmdline.add_argument(\r\n      {\"wwiv_test_tempdir\", \"Use instead of WWIV_TEST_TEMPDIR environment variable.\", \"\"});\r\n  cmdline.add_argument(\r\n      {\"wwiv_testdata\", \"Sets the location of the testdata directory for this test.\", \"\"});\r\n  cmdline.set_no_args_allowed(true);\r\n  if (!cmdline.Parse()) {\r\n    LOG(ERROR) << \"Failed to parse cmdline.\";\r\n  }\r\n\r\n  auto tmpdir = cmdline.arg(\"wwiv_test_tempdir\").as_string();\r\n  if (tmpdir.empty()) {\r\n    tmpdir = wwiv::os::environment_variable(\"WWIV_TEST_TEMPDIR\");\r\n  }\r\n  if (!tmpdir.empty()) {\r\n    if (!File::Exists(tmpdir)) {\r\n      File::mkdirs(tmpdir);\r\n    }\r\n    File::set_current_directory(tmpdir);\r\n    set_wwiv_test_tempdir(tmpdir);\r\n  }\r\n\r\n  auto testdata = cmdline.arg(\"wwiv_testdata\").as_string();\r\n  if (testdata.empty()) {\r\n    testdata = wwiv::os::environment_variable(\"WWIV_TESTDATA\");\r\n  }\r\n  FileHelper::testdata_ = testdata;\r\n}\r\n\r\n// static\r\nstd::filesystem::path FileHelper::TestData() {\r\n  CHECK(!testdata_.empty()) << \"WWIV_TESTDATA must be set for using testdata.\";\r\n  CHECK(File::Exists(testdata_))\r\n      << \"WWIV_TESTDATA must be set to a directory that exists for using testdata.\";\r\n  LOG(INFO) << \"TestData: \" << testdata_;\r\n  return testdata_;\r\n}\r\n\r\n// static\r\nbool FileHelper::HasTestData() { return !testdata_.empty(); }\r\n\r\n  // static\r\nstd::filesystem::path FileHelper::GetTestTempDir() {\r\n  if (!basedir_.empty()) {\r\n    return basedir_;\r\n  }\r\n  const auto raw_temp_path = File::canonical(std::filesystem::temp_directory_path());\r\n  VLOG(2) << \"raw_temp_path: \" << raw_temp_path;\r\n  const auto temp_path = File::absolute(raw_temp_path);\r\n  VLOG(1) << \"temp_path: \" << temp_path;\r\n  auto path = temp_path / \"wwiv_test_out\";\r\n  if (!exists(path)) {\r\n    create_directories(path);\r\n  }\r\n  return path;\r\n}\r\n\r\n// static\r\nstd::filesystem::path FileHelper::CreateTempDir(const std::string& base) {\r\n  const auto temp_path = GetTestTempDir();\r\n  // TODO(rushfan): This may be good enough for linux too.\r\n#if defined(_WIN32) || defined(__OS2__)\r\n  auto dir = FilePath(temp_path, StrCat(base, \".\", time_t_now()));\r\n  if (std::error_code ec; create_directories(dir, ec)) {\r\n    return dir;\r\n  }\r\n#else\r\n  char local_dir_template[MAX_PATH];\r\n  const auto template_ = StrCat(temp_path.string(), \"/\", base, \"XXXXXX\");\r\n  to_char_array(local_dir_template, template_);\r\n  char* result = mkdtemp(local_dir_template);\r\n  if (result) {\r\n    return std::filesystem::path{result};\r\n  }\r\n#endif\r\n  return {};\r\n}\r\n\r\nstd::filesystem::path FileHelper::CreateTempFilePath(const std::string& orig_name) const {\r\n  const auto name{File::FixPathSeparators(orig_name)};\r\n  return File::canonical(FilePath(TempDir(), name));\r\n}\r\n\r\nstd::tuple<FILE*, std::filesystem::path>\r\nFileHelper::OpenTempFile(const std::string& orig_name) const {\r\n  const auto path = CreateTempFilePath(orig_name);\r\n  const auto fn = path.string();\r\n  auto* fp = fopen(fn.c_str(), \"wt\");\r\n  assert(fp);\r\n  return std::make_tuple(fp, path);\r\n}\r\n\r\n// ReSharper disable once CppMemberFunctionMayBeConst\r\nstd::filesystem::path FileHelper::CreateTempFile(const std::string& orig_name,\r\n                                                 const std::string& contents) {\r\n  auto [file, path] = OpenTempFile(orig_name);\r\n  assert(file);\r\n  fputs(contents.c_str(), file);\r\n  fclose(file);\r\n  return path;\r\n}\r\n\r\n// N.B.: We don't use TextFile::ReadFileIntoString since we are\r\n// testing TextFile with this helper.\r\nstd::string FileHelper::ReadFile(const std::filesystem::path& name) const {\r\n  const auto name_string = name.string();\r\n  // ReSharper disable once CppLocalVariableMayBeConst\r\n  auto* fp = fopen(name_string.c_str(), \"rt\");\r\n  if (!fp) {\r\n    const auto msg = StrCat(\"Unable to open file: \", name_string, \"; errno: \", errno);\r\n    throw std::runtime_error(msg);\r\n  }\r\n  std::string contents;\r\n  fseek(fp, 0, SEEK_END);\r\n  contents.resize(ftell(fp));\r\n  rewind(fp);\r\n  const auto num_read = fread(&contents[0], 1, contents.size(), fp);\r\n  contents.resize(num_read);\r\n  fclose(fp);\r\n  return contents;\r\n}\r\n\r\n} // namespace wwiv::core::test\r\n"
  },
  {
    "path": "core/test/file_helper.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                              WWIV Version 5.x                          */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_CORE_TEST_FILE_HELPER_H\r\n#define INCLUDED_CORE_TEST_FILE_HELPER_H\r\n\r\n#include <cstdio>\r\n#include <string>\r\n#include <tuple>\r\n#include <filesystem>\r\n\r\nnamespace wwiv::core::test {\r\n\r\n/**\r\n * Helper class for tests requiring local filesystem access.\r\n *\r\n * Note: This class can not use File since it is used by the tests for File.\r\n */\r\nclass FileHelper {\r\npublic:\r\n  FileHelper();\r\n  // Returns a fully qualified path name to \"name\" under the temporary directory.\r\n  // This will end with a pathSeparator and is suitable for use\r\n  // in wwiv data structures.\r\n  [[nodiscard]] std::string DirName(const std::string& name) const;\r\n  // Returns a fully qualified path to \"name\" under the temporary directory.\r\n  // This is suitable for use in constructing paths\r\n  [[nodiscard]] std::filesystem::path Dir(const std::string& name) const;\r\n  // Creates a directory under TempDir.\r\n  bool Mkdir(const std::string& name) const; // NOLINT(modernize-use-nodiscard)\r\n  // Creates a path to a filename under TempDir named 'name'.  Does not create nor\r\n  // write any contents to this file.\r\n  [[nodiscard]] std::filesystem::path CreateTempFilePath(const std::string& name) const;\r\n  // Opens a FILE* handle to a file named 'name' under TempDir\r\n  [[nodiscard]] std::tuple<FILE*, std::filesystem::path>\r\n  OpenTempFile(const std::string& name) const;\r\n  // Creates a a file under TempDir named 'name' containing the text 'contents'\r\n  std::filesystem::path CreateTempFile(const std::string& name, const std::string& contents);\r\n  // Returns the path of the temp directory for this testcase.\r\n  [[nodiscard]] const std::filesystem::path& TempDir() const { return tmp_; }\r\n  // Reads and returns all of the text in a file under TempDir named 'name'\r\n  [[nodiscard]] std::string ReadFile(const std::filesystem::path& name) const;\r\n  static void set_wwiv_test_tempdir(const std::string& d) noexcept;\r\n  static void set_wwiv_test_tempdir_from_commandline(int argc, char* argv[]) noexcept;\r\n\r\n  // Gets the root testdata directory specified as \"WWIV_TESTDATA\" on the environment\r\n  [[nodiscard]] static std::filesystem::path TestData();\r\n  [[nodiscard]] static bool HasTestData();\r\n\r\nprivate:\r\n  static std::filesystem::path GetTestTempDir();\r\n  static std::filesystem::path CreateTempDir(const std::string& base);\r\n  std::filesystem::path tmp_;\r\n  static std::filesystem::path basedir_;\r\n  static std::filesystem::path testdata_;\r\n};\r\n\r\n} // namespace wwiv::core::test\r\n\r\n#endif\r\n"
  },
  {
    "path": "core/test/wwivtest.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n\n#include \"gtest/gtest.h\"\n#include \"core/cp437.h\"\n#include \"core/test/file_helper.h\"\n#include \"core/log.h\"\n#include <ctime>\n#include <string>\n\nnamespace wwiv::core::test {\n\n/**\n * Initializes much of the WWIV Environment for a GTest main method.\n *\n * Specifically:\n *\n * - Sets codepage to UTF8\n * - Initialies WWIV's global logger\n * - Initialies GoogleTest\n * - Sets WWIV's test tempdir and testdata directories from the commandline.\n */\nvoid InitTestForMain(int argc, char** argv) {\n  set_wwiv_codepage(wwiv_codepage_t::utf8);\n  tzset();\n  testing::InitGoogleTest(&argc, argv);\n  LoggerConfig logger_config{};\n  logger_config.register_file_destinations = false;\n  logger_config.log_startup = false;\n  Logger::Init(argc, argv, logger_config);\n  FileHelper::set_wwiv_test_tempdir_from_commandline(argc, argv);\n}\n\n\nvoid TestDataTest::SetUp() {\n  if (!wwiv::core::test::FileHelper::HasTestData()) {\n    GTEST_SKIP() << \"Skipping all tests that use real files since FileHelper::TestData() is empty.\";\n  }\n}\n\n} // namespace wwiv::core::test\n\n"
  },
  {
    "path": "core/test/wwivtest.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_TEST_WWIVTEST_H\n#define INCLUDED_CORE_TEST_WWIVTEST_H\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nnamespace wwiv::core::test {\n\n/**\n * Initializes much of the WWIV Environment for a GTest main method. \n * \n * Specifically:\n * \n * - Sets codepage to UTF8\n * - Initialies WWIV's global logger\n * - Initialies GoogleTest\n * - Sets WWIV's test tempdir and testdata directories from the commandline.\n */\nvoid InitTestForMain(int argc, char** argv);\n\n/**\n * Specialized ::testing::Test class that skips tests that depend on WWIV_TESTDATA being set\n * if it's not specified in the environment or from the commandline.\n * \n * Example:\n * \n * class FileTestDataTest : public wwiv::core::test::TestDataTest {};\n * \n * TEST_F(FileTestDataTest, ...) ...\n */\nclass TestDataTest : public ::testing::Test {\nprotected:\n  void SetUp() override;\n};\n\n\n}\n\n#endif // INCLUDED_CORE_TEST_WWIVTEST_H"
  },
  {
    "path": "core/testdata/len.txt",
    "content": "Hello World"
  },
  {
    "path": "core/textfile.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2005-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/textfile.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/wwivport.h\"\n#include <cerrno>\n#include <chrono>\n#include <cstring>\n#include <cstdarg>\n#include <fcntl.h>\n#include <string>\n#include <sys/stat.h>\n\n#ifdef _WIN32\n#include <io.h>\n\n#else  // _WIN32\n#include <sys/file.h>\n#include <unistd.h>\n#endif  // _WIN32\n\nusing std::chrono::milliseconds;\nusing wwiv::core::File;\nusing wwiv::strings::StringReplace;\nusing namespace wwiv::os;\n\nnamespace {\nconst int WAIT_TIME = 10;\nconst int TRIES = 100;\n}\n\n#ifdef _WIN32\nFILE* OpenImpl(const std::string& name, const std::string& mode) {\n  auto share = SH_DENYWR;\n  auto md = O_RDONLY;\n  if (strchr(mode.c_str(), 'w') != nullptr) {\n    share = SH_DENYRD;\n    md = O_RDWR | O_CREAT | O_TRUNC;\n  } else if (strchr(mode.c_str(), 'a') != nullptr) {\n    share = SH_DENYRD;\n    md = O_RDWR | O_CREAT;\n  }\n\n  if (strchr(mode.c_str(), 'b') != nullptr) {\n    md |= O_BINARY;\n  }\n  if (strchr(mode.c_str(), '+') != nullptr) {\n    md &= ~O_RDONLY;\n    md |= O_RDWR;\n    share = SH_DENYRD;\n  }\n\n  auto fd = _sopen(name.c_str(), md, share, S_IREAD | S_IWRITE);\n  if (fd < 0) {\n    auto count = 1;\n    if (File::Exists(name)) {\n      sleep_for(milliseconds(WAIT_TIME));\n      fd = _sopen(name.c_str(), md, share, S_IREAD | S_IWRITE);\n      while ((fd < 0 && errno == EACCES) && count < TRIES) {\n        sleep_for(milliseconds(WAIT_TIME));\n        count++;\n        fd = _sopen(name.c_str(), md, share, S_IREAD | S_IWRITE);\n      }\n    }\n  }\n\n  if (fd > 0) {\n    if (strchr(mode.c_str(), 'a')) {\n      _lseek(fd, 0L, SEEK_END);\n    }\n\n    auto* hFile = _fdopen(fd, mode.c_str());\n    if (!hFile) {\n      _close(fd);\n    }\n    return hFile;\n  }\n  VLOG(1) << \"TextFile::OpenImpl; fopen failed on file: '\" << name;  \n  return nullptr;\n}\n\n#else  // _WIN32\nFILE* OpenImpl(const std::string& name, const std::string& mode) {\n  FILE* f = fopen(name.c_str(), mode.c_str());\n  if (f != nullptr) {\n    flock(fileno(f), (strpbrk(mode.c_str(), \"wa+\")) ? LOCK_EX : LOCK_SH);\n  } else {\n    VLOG(1) << \"TextFile::OpenImpl; fopen failed on file: '\" << name << \"'; errno: \" << errno;\n  }\n  return f;\n}\n#endif // _WIN32\n\nstatic std::string fopen_compatible_mode(const std::string& m) noexcept {\n  if (m.find('d') == std::string::npos) {\n    return m;\n  }\n  auto s{m};\n  StringReplace(&s, \"d\", \"t\");\n  return s;\n}\n\nTextFile::TextFile(const std::filesystem::path& file_name, const std::string& file_mode) noexcept\n  : file_name_(file_name), file_(OpenImpl(file_name.string(), fopen_compatible_mode(file_mode))),\n    open_(file_ != nullptr), dos_mode_(strchr(file_mode.c_str(), 'd') != nullptr) {\n}\n\nbool TextFile::Close() noexcept {\n  if (file_ == nullptr) {\n    return false;\n  }\n  fclose(file_);\n  file_ = nullptr;\n  open_ = false;\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nssize_t TextFile::WriteChar(char ch) noexcept {\n  DCHECK(file_);\n  return fputc(ch, file_);\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nssize_t TextFile::Write(const std::string& text) noexcept {\n  DCHECK(file_);\n  return static_cast<ssize_t>((fputs(text.c_str(), file_) >= 0) ? text.size() : 0);\n}\n\nssize_t TextFile::WriteLine(const std::string& text) noexcept {\n  if (file_ == nullptr) {\n    return -1;\n  }\n  auto num_written = Write(text);\n  // fopen in text mode will force \\n -> \\r\\n on win32\n#if defined(_WIN32) || defined(__OS2__)\n  fputs(\"\\n\", file_);\n#else\n  if (dos_mode_) {\n    fputs(\"\\r\\n\", file_);\n  } else {\n    fputs(\"\\n\", file_);\n  }\n#endif\n  // TODO(rushfan): Should we just +=1 on non-win32?\n  num_written += 2;\n  return num_written;\n}\n\nstatic void StripLineEnd(char* str) noexcept {\n  auto i = strlen(str);\n  while ((i > 0) && ((str[i - 1] == 10) || str[i - 1] == 13)) {\n    --i;\n  }\n  str[i] = '\\0';\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool TextFile::ReadLine(std::string* out) noexcept {\n  try {\n    if (file_ == nullptr) {\n      out->clear();\n      return false;\n    }\n    char s[4096];\n    auto* p = fgets(s, sizeof(s), file_);\n    if (p == nullptr) {\n      out->clear();\n      return false;\n    }\n    // Strip off trailing \\r\\n\n    StripLineEnd(p);\n    out->assign(p);\n    return true;\n  } catch (...) {\n    return false;\n  }\n}\n\nFile::size_type TextFile::position() const noexcept {\n  DCHECK(file_);\n  if (!file_) {\n    return 0;\n  }\n  return ftell(file_);\n}\n\nconst std::filesystem::path& TextFile::path() const noexcept {\n  return file_name_;\n}\n\nstd::string TextFile::full_pathname() const { return file_name_.string(); }\n\nTextFile::~TextFile() noexcept {\n  Close();\n}\n\nstd::string TextFile::ReadFileIntoString() {\n  VLOG(3) << \"ReadFileIntoString: \";\n  if (file_ == nullptr) {\n    return {};\n  }\n\n  fseek(file_, 0, SEEK_END);\n  const auto len = static_cast<unsigned long>(ftell(file_));\n  rewind(file_);\n  if (len == 0) {\n    return {};\n  }\n\n  std::string contents;\n  contents.resize(len);\n  const auto num_read = fread(&contents[0], 1, contents.size(), file_);\n  contents.resize(num_read);\n  return contents;\n}\n\nstd::vector<std::string> TextFile::ReadFileIntoVector(int64_t max_lines) {\n  if (max_lines <= 0) {\n    max_lines = std::numeric_limits<int64_t>::max();\n  }\n  std::vector<std::string> result;\n  std::string line;\n  while (ReadLine(&line) && max_lines-- > 0) {\n    result.push_back(line);\n  }\n  return result;\n}\n\nstd::vector<std::string> TextFile::ReadLastLinesIntoVector(int num_lines) {\n  fseek(file_, 0, SEEK_END);\n  const auto len = static_cast<unsigned long>(ftell(file_));\n  const auto pos = std::max<int>(0, len - (num_lines * 1024));\n  // move to new pos\n  fseek(file_, pos, SEEK_SET);\n  std::string contents;\n  contents.resize(len - pos + 1);\n  const auto num_read = fread(&contents[0], 1, contents.size(), file_);\n  contents.resize(num_read);\n\n  if (contents.back() == '\\n') {\n    contents.pop_back();\n  }\n\n  auto cur_num = 0;\n  auto count = 0;\n  for (auto it = std::rbegin(contents); it != std::rend(contents); ++it) {\n    if (*it == '\\n') {\n      ++cur_num;\n    }\n    count++;\n    if (cur_num == num_lines) {\n      break;\n    }\n  }\n  auto f = wwiv::stl::size_int(contents) - count;\n  if (f > 0)  {\n    ++f;\n  }\n  contents = contents.substr(f);\n  return wwiv::strings::SplitString(contents, \"\\n\", true);\n}\n\nstd::ostream& operator<<(std::ostream& os, const TextFile& file) {\n  os << file.full_pathname();\n  return os;\n}\n"
  },
  {
    "path": "core/textfile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2005-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_TEXTFILE_H\n#define INCLUDED_CORE_TEXTFILE_H\n\n#include \"core/file.h\"\n#include \"core/wwivport.h\"\n#include <cstdio>\n#include <filesystem>\n#include <sstream>\n#include <string>\n#include <vector>\n\ntypedef std::basic_ostream<char>&(ENDL_TYPE2)(std::basic_ostream<char>&);\n\n/**\n \\class TextFile\n \\brief A class that represents a text file.\n\n Used to read and write text files.\n\n When creating a `TextFile` You should specify the following\n subset of the POSIX file modes.\n\n - - -\n ### File Modes ###\n mode | Description\n -----|-----------------------------\n    r | Read\n    w | Write, Truncate if exists\n    a | Append/Write.\n    d | DOS Text mode (always use \\r\\n, even on *nix)\n    t | Text Mode (default)\n    b | Binary Mode\n    + | Read and Write\n\n ### Example: ###\n \\code{.cpp}\n   TextFile f(\"/tmp/foo.txt\", \"wt\");\n   f.WriteLine(\"Hello World\");\n \\endcode\n */\nclass TextFile final {\npublic:\n  /**\n   * Constructs a TextFile.\n   * Constructs a TextFile using the full path `file_name` and mode of `file_mode`.\n   */\n  TextFile(const std::filesystem::path& file_name, const std::string& file_mode) noexcept;\n\n  ~TextFile() noexcept;\n\n  /**\n   * Explicitly closes an existing TextFile.\n   *\n   * Normally this isn't needed since it will be invoked by the destructor.\n   */\n  bool Close() noexcept;\n\n  /**\n   * Used to check if the file has been successfully open.\n   * Usually code should use `operator bool()` vs. this method.\n   */\n  [[nodiscard]] bool IsOpen() const noexcept { return file_ != nullptr; }\n  [[nodiscard]] bool IsEndOfFile() const noexcept { return feof(file_) != 0; }\n\n  /** Writes a line of text without `\\r\\n` */\n  ssize_t Write(const std::string& text) noexcept;\n\n  /** Writes a line of text including `\\r\\n`. */\n  ssize_t WriteLine(const char* text) noexcept { return WriteLine(std::string(text)); }\n\n  /** Writes a line of text including `\\r\\n`. */\n  // Add this since WriteLine(T) below will match that and this\n  // explicit match keeps that from happening\n  ssize_t WriteLine(char* text) noexcept { return WriteLine(std::string(text)); }\n\n  ssize_t WriteLine() noexcept { return WriteLine(\"\"); }\n\n  /** Writes a char[N] representing a line of text including `\\r\\n`. */\n  template <size_t N> ssize_t WriteLine(const char t[N]) noexcept {\n    return WriteLine(std::string(t));\n  }\n\n  /**\n   * Writes a T that is transformable to a string using std::to_string(T)\n   * representing a line of text including `\\r\\n`.\n   */\n  template <typename T> ssize_t WriteLine(T t) noexcept { return WriteLine(std::to_string(t)); }\n\n  /** Writes a std::string representing a line of text including `\\r\\n`. */\n  ssize_t WriteLine(const std::string& text) noexcept;\n\n  /** Writes a single character to a text file. */\n  ssize_t WriteChar(char ch) noexcept;\n\n  /** Writes a binary blob as binary data. */\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  ssize_t WriteBinary(const void* buffer, ssize_t num) noexcept {\n    return static_cast<int>(fwrite(buffer, num, 1, file_));\n  }\n\n  /** Reads one line of text, removing the `\\r\\n` in the end of the line. */\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  [[nodiscard]] bool ReadLine(char* buffer, int nBufferSize) noexcept {\n    return fgets(buffer, nBufferSize, file_) != nullptr;\n  }\n\n  /** Reads one line of text, removing the `\\r\\n` in the end of the line. */\n  [[nodiscard]] bool ReadLine(std::string* out) noexcept;\n  [[nodiscard]] wwiv::core::File::size_type position() const noexcept;\n  [[nodiscard]] const std::filesystem::path& path() const noexcept;\n  [[nodiscard]] std::string full_pathname() const;\n  [[nodiscard]] FILE* GetFILE() const noexcept { return file_; }\n\n  /**\n    Reads the entire contents of the file into the returned string.\n\n    Note: The file position will be at the end of the file after returning.\n   */\n  [[nodiscard]] std::string ReadFileIntoString();\n\n  /**\n   * Reads up to max_lines, the contents of the file into a vector of strings.\n   * \n   * Note: The file position will be at the end of the file after returning.\n   * Note: max_lines defaults to max size for an int64_t.\n   */\n  [[nodiscard]] std::vector<std::string> ReadFileIntoVector(int64_t max_lines = std::numeric_limits<int64_t>::max());\n\n  /**\n   * Reads up to max_lines, the contents of the file into a vector of strings.\n   * \n   * Note: The file position will be at the end of the file after returning.\n   * Note: max_lines defaults to max size for an int64_t.\n   */\n  [[nodiscard]] std::vector<std::string> ReadLastLinesIntoVector(int num_lines);\n\n  // operators\n\n  /**\n   * Used to check if the file has been successfully open.\n   * This operator is preferred over the function IsOpen.\n  */\n  explicit operator bool() const { return IsOpen(); }\n  friend std::ostream& operator<<(std::ostream& os, const TextFile& f);\n\n  template <typename T> TextFile& operator<<(T const& value) {\n    std::ostringstream ss;\n    ss << value;\n    Write(ss.str());\n    return *this;\n  }\n\n  TextFile& operator<<(ENDL_TYPE2* value) {\n    std::ostringstream ss;\n    ss << value;\n    Write(ss.str());\n    return *this;\n  }\n\nprivate:\n  const std::filesystem::path file_name_;\n  mutable FILE* file_;\n  bool open_{false};\n  const bool dos_mode_{false};\n};\n\n#endif\n"
  },
  {
    "path": "core/textfile_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"core/textfile.h\"\n#include \"gtest/gtest.h\"\n#include <filesystem>\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nclass TextFileTest : public ::testing::Test {\nprotected:\n  void SetUp() override {\n    const auto* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();\n    test_name_ = test_info->name();\n    hello_world_path_ = helper_.CreateTempFile(test_name_, kHelloWorld);\n  }\n\n  [[nodiscard]] const std::string& test_name() const { return test_name_; }\n\n  wwiv::core::test::FileHelper helper_;\n  std::filesystem::path hello_world_path_;\n  std::string test_name_;\n  static const std::string kHelloWorld;\n};\n\nconst std::string TextFileTest::kHelloWorld = \"Hello World\\n\";\n\nTEST_F(TextFileTest, Constructor_SunnyCase) {\n  TextFile file(hello_world_path_, \"rt\");\n  std::string s;\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"Hello World\", s);\n}\n\nTEST_F(TextFileTest, Constructor_Path_And_Name) {\n  TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"rt\");\n  std::string s;\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"Hello World\", s);\n}\n\nTEST_F(TextFileTest, Append) {\n  std::unique_ptr<TextFile> file(\n      new TextFile(FilePath(helper_.TempDir(), this->test_name()), \"a+t\"));\n  EXPECT_EQ(3, file->Write(\"abc\"));\n  const auto filename = file->full_pathname();\n  file.reset();\n\n  const auto actual = helper_.ReadFile(filename);\n  EXPECT_EQ(\"Hello World\\nabc\", actual);\n}\n\nTEST_F(TextFileTest, ReadLine_CA) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"a\\nb\\nc\\n\");\n  TextFile file(path, \"rt\");\n  char s[255];\n  EXPECT_TRUE(file.ReadLine(s, sizeof(s)));\n  EXPECT_STREQ(\"a\\n\", s);\n  EXPECT_TRUE(file.ReadLine(s, sizeof(s)));\n  EXPECT_STREQ(\"b\\n\", s);\n  EXPECT_TRUE(file.ReadLine(s, sizeof(s)));\n  EXPECT_STREQ(\"c\\n\", s);\n  EXPECT_FALSE(file.ReadLine(s, sizeof(s)));\n}\n\nTEST_F(TextFileTest, ReadLine_String) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"a\\nb\\nc\\n\");\n  TextFile file(path, \"rt\");\n  std::string s;\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"a\", s);\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"b\", s);\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"c\", s);\n  EXPECT_FALSE(file.ReadLine(&s));\n}\n\nTEST_F(TextFileTest, Write) {\n  std::string filename;\n  {\n    TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"wt\");\n    file.Write(\"Hello\");\n    filename = file.full_pathname();\n  }\n  const auto actual = helper_.ReadFile(filename);\n  EXPECT_EQ(\"Hello\", actual);\n}\n\nTEST_F(TextFileTest, Insertion_Basic) {\n  std::string filename;\n  {\n    TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"wt\");\n    file << \"Hello\" << \" \" << \"World\";\n    filename = file.full_pathname();\n  }\n  const auto actual = helper_.ReadFile(filename);\n  EXPECT_EQ(\"Hello World\", actual);\n}\n\nTEST_F(TextFileTest, Insertion_TwoLines) {\n  std::string filename;\n  {\n    TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"wt\");\n    file << \"Hello\" << std::endl;\n    file << \"World\" << std::endl;\n    filename = file.full_pathname();\n  }\n  const auto actual = helper_.ReadFile(filename);\n  auto lines = wwiv::strings::SplitString(actual, \"\\r\\n\", true);\n  EXPECT_EQ(2u, lines.size());\n  EXPECT_EQ(\"Hello\", lines.at(0));\n  EXPECT_EQ(\"World\", lines.at(1));\n}\n\nTEST_F(TextFileTest, WriteChar) {\n  std::string filename;\n  {\n    TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"wt\");\n    file.WriteChar('H');\n    filename = file.full_pathname();\n  }\n  const auto actual = helper_.ReadFile(filename);\n  EXPECT_EQ(\"H\", actual);\n}\n\nTEST_F(TextFileTest, WriteBinary) {\n  std::string filename;\n  {\n    TextFile file(FilePath(helper_.TempDir(), this->test_name()), \"wt\");\n    file.WriteBinary(kHelloWorld.c_str(), kHelloWorld.size() - 1); // trim off \\n\n    filename = file.full_pathname();\n    // Let the file close.\n  }\n  const auto actual = helper_.ReadFile(filename);\n  EXPECT_EQ(\"Hello World\", actual);\n}\n\nTEST_F(TextFileTest, Close) {\n  TextFile file(hello_world_path_, \"rt\");\n  ASSERT_TRUE(file.IsOpen());\n  EXPECT_TRUE(file.Close());\n  EXPECT_FALSE(file.IsOpen());\n}\n\nTEST_F(TextFileTest, Close_SecondCloseReturnsFalse) {\n  TextFile file(hello_world_path_, \"rt\");\n  ASSERT_TRUE(file.IsOpen());\n  EXPECT_TRUE(file.Close());\n  EXPECT_FALSE(file.Close());\n  EXPECT_FALSE(file.IsOpen());\n}\n\nTEST_F(TextFileTest, IsEOF) {\n  TextFile file(hello_world_path_, \"rt\");\n  std::string s;\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"Hello World\", s);\n\n  EXPECT_FALSE(file.ReadLine(&s));\n  EXPECT_TRUE(file.IsEndOfFile());\n}\n\nTEST_F(TextFileTest, GetPosition) {\n  const auto path = helper_.CreateTempFile(test_name_, \"a\\nb\\nc\\n\");\n  TextFile file(path, \"rt\");\n  ASSERT_EQ(0, file.position());\n  std::string s;\n  EXPECT_TRUE(file.ReadLine(&s));\n  EXPECT_EQ(\"a\", s);\n#if defined (_WIN32) || defined (__OS2__)\n  EXPECT_EQ(3, file.position());\n#else  // _WIN32\n  EXPECT_EQ(2, file.position());\n#endif // _WIN32\n}\n\nTEST_F(TextFileTest, ReadFileIntoString) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"a\\nb\\nc\\n\");\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadFileIntoString();\n  EXPECT_EQ(\"a\\nb\\nc\\n\", s);\n}\n\nTEST_F(TextFileTest, ReadFileIntoString_EmptyFile) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"\");\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadFileIntoString();\n  EXPECT_EQ(\"\", s);\n}\n\nTEST_F(TextFileTest, ReadFileNLinesIntoString) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\\n\");\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadLastLinesIntoVector(4);\n  EXPECT_EQ(4u, s.size());\n}\n\n\nTEST_F(TextFileTest, ReadFileNLinesIntoString_NoCRLF) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\");\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadLastLinesIntoVector(4);\n  EXPECT_EQ(4u, s.size());\n}\n\nTEST_F(TextFileTest, ReadFileNLinesIntoString_HugeFile) {\n  std::string contents(1000, 'x');\n  contents += \"1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n10\";\n  const auto path = helper_.CreateTempFile(this->test_name(), contents);\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadLastLinesIntoVector(4);\n  EXPECT_EQ(4u, s.size());\n}\n\nTEST_F(TextFileTest, ReadFileNLinesIntoString_SmallerFileThanN) {\n  const auto path = helper_.CreateTempFile(this->test_name(), \"1\\n2\\n\");\n  TextFile file(path, \"rt\");\n  const auto s = file.ReadLastLinesIntoVector(4);\n  EXPECT_EQ(2u, s.size());\n}\n\n"
  },
  {
    "path": "core/transaction.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_TRANSACTION_H\n#define INCLUDED_CORE_TRANSACTION_H\n\n#include <functional>\n\nnamespace wwiv::core {\n\nclass Transaction {\npublic:\n  Transaction(std::function<void()> commit_fn, std::function<void()> rollback_fn)\n      : commit_fn_(commit_fn), rollback_fn_(rollback_fn) {}\n\n  ~Transaction() {\n    if (rollback_) {\n      if (rollback_fn_) {\n        rollback_fn_();\n      }\n    } else {\n      if (commit_fn_) {\n        commit_fn_();\n      }\n    }\n  }\n\n  void Rollback() { rollback_ = true; }\n\nprivate:\n  std::function<void()> commit_fn_;\n  std::function<void()> rollback_fn_;\n  bool rollback_{false};\n};\n\n} // namespace wwiv::core\n\n#endif\n"
  },
  {
    "path": "core/transaction_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/transaction.h\"\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing wwiv::core::Transaction;\n\nTEST(TransactionTest, Commit) {\n  bool committed = false;\n  bool rolledback = false;\n  auto c = [&] { committed = true; };\n  auto r = [&] { rolledback = true; };\n  {\n    Transaction t(c, r);\n    ASSERT_FALSE(rolledback);\n    ASSERT_FALSE(committed);\n  }\n  ASSERT_TRUE(committed);\n  ASSERT_FALSE(rolledback);\n}\n\nTEST(TransactionTest, Rollback) {\n  bool committed = false;\n  bool rolledback = false;\n  auto c = [&] { committed = true; };\n  auto r = [&] { rolledback = true; };\n  {\n    Transaction t(c, r);\n    ASSERT_FALSE(rolledback);\n    ASSERT_FALSE(committed);\n    t.Rollback();\n  }\n  ASSERT_FALSE(committed);\n  ASSERT_TRUE(rolledback);\n}\n\nTEST(TransactionTest, Rollback_RolebackNull) {\n  bool committed = false;\n  auto c = [&] { committed = true; };\n  {\n    Transaction t(c, nullptr);\n    ASSERT_FALSE(committed);\n    t.Rollback();\n  }\n  ASSERT_FALSE(committed);\n}\n\nTEST(TransactionTest, Commit_RollbackNull) {\n  bool committed = false;\n  auto c = [&] { committed = true; };\n  {\n    Transaction t(c, nullptr);\n    ASSERT_FALSE(committed);\n  }\n  ASSERT_TRUE(committed);\n}\n\nTEST(TransactionTest, Commit_CommitNull) {\n  bool rolledback = false;\n  auto r = [&] { rolledback = true; };\n  {\n    Transaction t(nullptr, r);\n    ASSERT_FALSE(rolledback);\n  }\n  ASSERT_FALSE(rolledback);\n}\n"
  },
  {
    "path": "core/uuid.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/uuid.h\"\n\n#include \"core/stl.h\"\n#include <array>\n#include <iomanip>\n#include <ios>\n#include <random>\n#include <sstream>\n\nnamespace wwiv::core {\n\nuuid_t::uuid_t() = default;\n\nuuid_t::uuid_t(std::array<uint8_t, 16> s) : bytes_(s) {\n  for (const auto& i : bytes_) {\n    if (i != 0) {\n      empty_ = false;\n    }\n  }\n\n}\n\nuuid_t::uuid_t(const uuid_t& that) {\n  this->bytes_ = that.bytes_;\n  this->empty_ = that.empty_;\n}\n\nuuid_t& uuid_t::operator=(const uuid_t& that) {\n  this->bytes_ = that.bytes_;\n  this->empty_ = that.empty_;\n  return *this;\n}\n\nstd::ostream& operator<<(std::ostream& os, const uuid_t& u) {\n  os << u.to_string();\n  return os;\n}\n\n\nstd::string uuid_t::to_string() const {\n  std::ostringstream ss;\n  ss << std::hex << std::setfill('0')\n     << std::setw(2) << static_cast<int>(bytes_[0])\n     << std::setw(2) << static_cast<int>(bytes_[1])\n     << std::setw(2) << static_cast<int>(bytes_[2])\n     << std::setw(2) << static_cast<int>(bytes_[3])\n     << '-'\n     << std::setw(2) << static_cast<int>(bytes_[4])\n     << std::setw(2) << static_cast<int>(bytes_[5])\n     << '-'\n     << std::setw(2) << static_cast<int>(bytes_[6])\n     << std::setw(2) << static_cast<int>(bytes_[7])\n     << '-'\n     << std::setw(2) << static_cast<int>(bytes_[8])\n     << std::setw(2) << static_cast<int>(bytes_[9])\n     << '-'\n     << std::setw(2) << static_cast<int>(bytes_[10])\n     << std::setw(2) << static_cast<int>(bytes_[11])\n     << std::setw(2) << static_cast<int>(bytes_[12])\n     << std::setw(2) << static_cast<int>(bytes_[13])\n     << std::setw(2) << static_cast<int>(bytes_[14])\n     << std::setw(2) << static_cast<int>(bytes_[15]);\n   return ss.str();\n}\n\nint from_single_hex_byte(const char r) {\n  const auto b = std::tolower(r);\n  if (b >= 'a' && b <= 'f') {\n    return b - 'a' + 10;\n  }\n  if (b >= '0' && b <= '9') {\n    return b - '0';\n  }\n  return 0;\n}\nuint8_t from_hex_bytes(char l, char r) {\n  return (from_single_hex_byte(l) << 4 & 0xf0) | (from_single_hex_byte(r) & 0x0f);\n}\n\nstd::optional<uuid_t> uuid_t::from_string(const std::string& s) {\n  if (s.empty()) {\n    return std::nullopt;\n  }\n  const auto has_braces = s.front() == '{';\n  const auto expected_size = has_braces ? 38 : 36;\n  if (wwiv::stl::ssize(s) != expected_size) {\n    return std::nullopt;\n  }\n\n  auto sit = std::begin(s);\n  if (has_braces) {\n    ++sit;\n  }\n  // fde5e4ff-8053-43ff-9696-5bffc2cdf3ff\n  std::array<uint8_t, 16> out{};\n  for (auto outit = std::begin(out); outit != std::end(out); ++outit) {\n    while (sit != std::end(s) && *sit == '-') { ++sit; }\n    if (sit == std::end(s)) {\n      break;\n    }\n    const auto l = *sit++;\n    while (sit != std::end(s) && *sit == '-') { ++sit; }\n    if (sit == std::end(s)) {\n      break;\n    }\n    const auto r = *sit++;\n    *outit = from_hex_bytes(l, r);\n  }\n  return uuid_t(out);\n}\n\nint uuid_t::version() const {\n  return bytes_[6] >> 4;\n}\n\nint uuid_t::variant() const {\n  const int v = bytes_[8] >> 6;\n  return v;\n}\n\nuuid_t uuid_generator::generate() {\n  std::mt19937 gen(rd_());\n  std::array<uint8_t, 16> data{};\n  for (auto i = 0; i < 4; i++) {\n    const auto u = distribution_(gen);\n    data[(i * 4) + 0] = (u >> 24) & 0xff;\n    data[(i * 4) + 1] = (u >> 16) & 0xff;\n    data[(i * 4) + 2] = (u >> 8) & 0xff;\n    data[(i * 4) + 3] = u & 0xff;\n  }\n\n  // From https://tools.ietf.org/html/rfc4122#page-6\n  // A Universally Unique IDentifier (UUID) URN Namespace\n\n  // 4.1.1: The variant field determines the layout of the UUID.\n  // Variant (10?xxxxx) is \"The variant specified in this document.\"\n  data[8] &= 0xBF;\n  data[8] |= 0x80;\n  // 4.1.3 Version: 4 (0100xxxx) is \"The randomly or pseudo-randomly\n  // generated version specified in this document.\n  data[6] &= 0x4F;\n  data[6] |= 0x40;\n  \n  return uuid_t(data);\n}\n\n} \n"
  },
  {
    "path": "core/uuid.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_UUID_H\n#define INCLUDED_CORE_UUID_H\n\n#include <array>\n#include <optional>\n#include <random>\n#include <string>\n\nnamespace wwiv::core {\n\nclass uuid_t final {\npublic:\n  uuid_t();\n  ~uuid_t() = default;\n  explicit uuid_t(std::array<uint8_t, 16> s);\n  uuid_t(const uuid_t&);\n  uuid_t& operator=(const uuid_t&);\n\n  [[nodiscard]] bool empty() const { return empty_; }\n  [[nodiscard]] std::string to_string() const;\n  [[nodiscard]] static std::optional<uuid_t> from_string(const std::string&);\n  [[nodiscard]] int version() const;\n  [[nodiscard]] int variant() const;\n  [[nodiscard]] std::array<uint8_t, 16> bytes() const { return bytes_; }\n  friend inline bool operator==(const uuid_t& lhs, const uuid_t& rhs);\n  friend inline bool operator!=(const uuid_t& lhs, const uuid_t& rhs);\n  friend std::ostream& operator<<(std::ostream& os, const uuid_t& u);\n\n  \nprivate:\n  std::array<uint8_t, 16> bytes_{};\n  bool empty_{true};\n};\n\ninline bool operator==(const uuid_t& lhs, const uuid_t& rhs) {\n  return lhs.bytes_ == rhs.bytes_;\n}\ninline bool operator!=(const uuid_t& lhs, const uuid_t& rhs) {\n  return lhs.bytes_ != rhs.bytes_;\n}\n\nclass uuid_generator {\npublic:\n  explicit uuid_generator(std::random_device& rd) :rd_(rd) {}\n  [[nodiscard]] uuid_t generate();\nprivate:\n  std::uniform_int_distribution<uint32_t>  distribution_;\n  std::random_device& rd_;\n};\n\n}\n\n\n#endif\n"
  },
  {
    "path": "core/uuid_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/log.h\"\n#include \"core/uuid.h\"\n#include <string>\n\nusing namespace wwiv::core;\n\nclass UuidTest : public ::testing::Test {\npublic:\n  UuidTest() : g(rd) {}\n\n  std::random_device rd{};\n  uuid_generator g;\n};\n\nTEST_F(UuidTest, Smoke) {\n  const auto u = g.generate();\n  LOG(INFO) << u.to_string();\n  EXPECT_FALSE(u.empty());\n}\n\nTEST_F(UuidTest, ToString) {\n  const auto u = g.generate();\n  const auto s = u.to_string();\n  LOG(INFO) << s;\n  EXPECT_EQ(36u, s.size());\n  EXPECT_EQ(u.to_string(), s);\n}\n\nTEST_F(UuidTest, Version) {\n  const auto u = g.generate();\n  LOG(INFO) << u.to_string();\n  EXPECT_EQ(4, u.version());\n}\n\nTEST_F(UuidTest, Varint) {\n  const auto u = g.generate();\n  LOG(INFO) << u.to_string();\n  EXPECT_EQ(2, u.variant());\n}\n\nTEST_F(UuidTest, RoundTrip) {\n  const auto u = g.generate();\n  const auto orig = u.to_string();\n  LOG(INFO) << orig;\n  const auto u2 = uuid_t::from_string(orig);\n  ASSERT_TRUE(u2.has_value());\n  EXPECT_EQ(u.to_string(), u2.value().to_string());\n}\n\nTEST_F(UuidTest, Eq) {\n  const auto u = g.generate();\n  const auto us = u.to_string();\n  const auto u2(u);\n  const auto u2s = u2.to_string();\n  const auto u3 = g.generate();\n  const auto u3s = u3.to_string();\n  EXPECT_EQ(u, u2);\n  EXPECT_EQ(us, u2s);\n\n  EXPECT_NE(u, u3);\n  EXPECT_NE(us, u3s);\n}\n\nTEST_F(UuidTest, FromString) {\n  const std::string s = \"f9545e4d-74db-4dad-b9d9-e3e8d1f59036\";\n  const auto u = uuid_t::from_string(\"f9545e4d-74db-4dad-b9d9-e3e8d1f59036\");\n  EXPECT_EQ(u.value().to_string(), s);\n}\n\nTEST_F(UuidTest, FromString_Braces) {\n  const std::string s = \"f9545e4d-74db-4dad-b9d9-e3e8d1f59036\";\n  const auto u = uuid_t::from_string(\"{f9545e4d-74db-4dad-b9d9-e3e8d1f59036}\");\n  EXPECT_EQ(u.value().to_string(), s);\n}\n\nTEST_F(UuidTest, FromString_Invalid) {\n  EXPECT_FALSE(uuid_t::from_string(\"x{f9545e4d-74db-4dad-b9d9-e3e8d1f59036}\").has_value());\n  EXPECT_FALSE(uuid_t::from_string(\"x-f9545e4d-74db-4dad-b9d9-e3e8d1f59036}\").has_value());\n  EXPECT_FALSE(uuid_t::from_string(\"\").has_value());\n  EXPECT_FALSE(uuid_t::from_string(\"x\").has_value());\n  EXPECT_FALSE(uuid_t::from_string(\"e3e8d1f59036\").has_value());\n}\n"
  },
  {
    "path": "core/version.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"version_internal.h\"\n#include <cstdint>\n#include <string>\n\n// The statusrec.wwiv_version\nstatic constexpr uint16_t wwiv_num_version = 520;\n// The statusrec.network_version\nstatic constexpr int wwiv_net_version = 53;\n\nnamespace wwiv::core {\nstd::string wwiv_compile_datetime() {\n  return INTERNAL_BUILD_DATE;\n}\n\nstd::string full_version() {\n#ifdef WWIV_RELEASE\n  return fmt::format(\"{}{}\", WWIV_RELEASE, WWIV_BUILD_NUMBER);\n#else\n  return {};\n#endif\n}\n\nstd::string short_version() {\n#ifdef WWIV_RELEASE\n  return WWIV_RELEASE; \n#else \n  return {};\n#endif\n}\n\nuint16_t wwiv_config_version() {\n  return wwiv_num_version;\n}\n\nint wwiv_network_compatible_version() {\n  return wwiv_net_version;\n}\n\n}\n"
  },
  {
    "path": "core/version.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2015-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_VERSION_H\n#define INCLUDED_CORE_VERSION_H\n\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::core {\n\n// Returns the full WWIV version (like 5.5.0.2020) as a string.\nstd::string full_version();\n\n// Returns the short version (Like 5.5.0) as a string.\nstd::string short_version();\n\n// Returns the wwiv modern config version #.  Used to run upgrade\n// activities on WWIV.\nuint16_t wwiv_config_version();\n\n// Returns the network compatible version as an int. i.e. 53\nint wwiv_network_compatible_version();\n\n// Returns the compile date for WWIV\nstd::string wwiv_compile_datetime();\n\n}\n\n#endif\n"
  },
  {
    "path": "core/version_internal.h.in",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2015-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_VERSION_INTERNAL_H\n#define INCLUDED_CORE_VERSION_INTERNAL_H\n\n# cmakedefine WWIV_RELEASE \"@WWIV_RELEASE@\"\n# cmakedefine WWIV_BUILD_NUMBER \"@WWIV_BUILD_NUMBER@\"\n\n#define INTERNAL_BUILD_DATE __DATE__ \", \" __TIME__;\n\n\n#endif  // INCLUDED_CORE_VERSION_INTERNAL_H\n"
  },
  {
    "path": "core/wfndfile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_CORE_WFNDFILE_H\n#define INCLUDED_CORE_WFNDFILE_H\n\n#include <any>\n#include <filesystem>\n#include <string>\n\n/**\n * Values for what WFindFile is searching\n */\nenum class WFindFileTypeMask {\n  WFINDFILE_ANY = 0x00,\n  WFINDFILE_FILES = 0x01,\n  WFINDFILE_DIRS = 0x02\n};\n\nclass WFindFile {\nprotected:\n  std::filesystem::path dir_;\n  std::string filename_;\n  std::filesystem::path filespec_;\n  long file_size_{0};\n  WFindFileTypeMask type_mask_{WFindFileTypeMask::WFINDFILE_ANY};\n  unsigned char file_type_{0};\n  bool open_{false};\n  bool use_long_filenames_{false};\n\n  void __open(const std::filesystem::path& file_spec, WFindFileTypeMask type_mask) {\n    filespec_ = file_spec;\n    type_mask_ = type_mask;\n  }\n\n  void __close() {\n    filespec_.clear();\n    filename_.clear();\n    file_size_ = 0;\n    type_mask_ = WFindFileTypeMask::WFINDFILE_ANY;\n    open_ = false;\n  }\n\n#if defined(_WIN32)\n  typedef void* HANDLE;\n  std::any ffdata_;\n  HANDLE hFind{nullptr};\n#elif defined ( __OS2__ )\n  struct dirent **entries = nullptr;\n  int nMatches = 0;\n  int nCurrentEntry = 0;\n#elif defined ( __unix__ )\n  struct dirent **entries = nullptr;\n  int nMatches = 0;\n  int nCurrentEntry = 0;\n#endif\n\npublic:\n  WFindFile() noexcept { this->__close(); }\n  bool open(const std::filesystem::path& filespec, WFindFileTypeMask nTypeMask);\n  bool next();\n  bool close();\n  virtual ~WFindFile() { close(); }\n  /** Should WFindFile use long filenames. */\n  void set_use_long_filenames(bool u) { use_long_filenames_ = u; }\n\n  [[nodiscard]] std::string GetFileName() const { return filename_; }\n  [[nodiscard]] long GetFileSize() const { return file_size_; }\n  [[nodiscard]] bool IsDirectory() const;\n  [[nodiscard]] bool IsFile() const;\n};\n\n\n#endif\n"
  },
  {
    "path": "core/wfndfile_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/wfndfile.h\"\n\n#include <cstring>\n#include <string>\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include <dirent.h>\n#include <errno.h>\n#include <fnmatch.h>\n#include <iostream>\n#include <libgen.h>\n#include <limits.h>\n#include <sys/stat.h>\n#include <os2.h>\n\nstatic WFindFileTypeMask s_typemask;\nstatic const char* filespec_ptr;\nstatic std::string s_path;\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Local functions\n//\n\nstatic int fname_ok(struct dirent* ent) {\n  if (IsEquals(ent->d_name, \".\") || IsEquals(ent->d_name, \"..\")) {\n    return 0;\n  }\n\n  if (s_typemask != WFindFileTypeMask::WFINDFILE_ANY) {\n    mode_t mode = 0;\n#ifdef _DIRENT_HAVE_D_TYPE\n    mode = DTTOIF(ent->d_type);\n#else\n    struct stat s;\n    auto fullpath = FilePath(s_path, ent->d_name).string();\n    stat(fullpath.c_str(), &s);\n    mode = s.st_mode;\n#endif // _DIRENT_HAVE_D_TYPE\n    if ((S_ISDIR(mode)) && !(s_typemask == WFindFileTypeMask::WFINDFILE_DIRS)) {\n      return 0;\n    }\n    if ((S_ISREG(mode)) && !(s_typemask == WFindFileTypeMask::WFINDFILE_FILES)) {\n      return 0;\n    }\n  }\n#if defined(__sun)\n  int result = fnmatch(filespec_ptr, ent->d_name, FNM_PATHNAME | FNM_IGNORECASE);\n#else\n  int result = fnmatch(filespec_ptr, ent->d_name, FNM_PATHNAME | FNM_CASEFOLD);\n#endif\n  VLOG(3) << \"fnmatch: \" << filespec_ptr << \";\" << ent->d_name << \"; \" << result << \"\\r\\n\";\n\n  if (result == 0) {\n    // fnmatch returns 0 on match. We return nonzero.\n    return 1;\n  }\n  return 0;\n}\n\nint scandir(const char* dir, struct dirent*** namelist, int (*sel)(/* const */ struct dirent*),\n            int (*compare)(const /* struct dirent ** */ void*,\n                           const /* struct dirent ** */ void*)) {\n  struct dirent** list = nullptr;\n  size_t list_size = 0;\n  int list_count = 0;\n  struct dirent* d;\n  int saved_errno;\n\n  auto* dp = opendir(dir);\n  if (dp == NULL) {\n    return -1;\n  }\n\n  /* Save original errno */\n  saved_errno = errno;\n  errno = 0;\n\n  while ((d = readdir(dp)) != nullptr) {\n    int selected = !sel || sel(d);\n    errno = 0;\n\n    if (selected) {\n      struct dirent* d1;\n      size_t len;\n\n      /* List full ? */\n      if (list_count == list_size) {\n        struct dirent** new_list;\n\n        if (list_size == 0)\n          list_size = 20;\n        else\n          list_size += list_size;\n\n        new_list = (struct dirent**)realloc(list, list_size * sizeof(*list));\n        if (!new_list) {\n          errno = ENOMEM;\n          break;\n        }\n\n        list = new_list;\n      }\n\n      /* On OS/2 kLIBC, d_name is not the last member of struct dirent.\n       * So just allocate as many as the size of struct dirent. */\n      len = sizeof(struct dirent);\n      d1 = (struct dirent*)malloc(len);\n      if (!d1) {\n        errno = ENOMEM;\n\n        break;\n      }\n\n      memcpy(d1, d, len);\n\n      list[list_count++] = d1;\n    }\n  }\n\n  if (errno) {\n    /* Store errno to use later */\n    saved_errno = errno;\n\n    /* Free a directory list */\n    while (list_count > 0) {\n      free(list[--list_count]);\n    }\n    free(list);\n\n    /* Indicate an error */\n    list_count = -1;\n  } else {\n    /* If compare is present, sort */\n    if (compare != NULL) {\n      qsort(list, list_count, sizeof(*list), compare);\n    }\n\n    *namelist = list;\n  }\n\n  /* Ignore error of closedir() */\n  closedir(dp);\n  errno = saved_errno;\n  return list_count;\n}\n\nint alphasort (const void *a, const void *b)\n{\n  return strcmp((*(const struct dirent **)a)->d_name,\n                (*(const struct dirent **)b)->d_name);\n}\n\nbool WFindFile::open(const std::filesystem::path& filespec, WFindFileTypeMask nTypeMask) {\n  __open(filespec, nTypeMask);\n  filename_.clear();\n\n  {\n    char path[FILENAME_MAX];\n    to_char_array(path, filespec.string());\n    dir_ = dirname(path);\n  }\n  {\n    char path[FILENAME_MAX];\n    to_char_array(path, filespec.string());\n    filespec_ = basename(path);\n    filespec_ptr = filespec_.c_str();\n  }\n\n  s_typemask = type_mask_;\n  s_path = dir_.string();\n  nMatches = scandir(s_path.c_str(), &entries, fname_ok, alphasort);\n  if (nMatches < 0) {\n    perror(\"scandir\");\n    return false;\n  }\n  nCurrentEntry = 0;\n\n  next();\n  return nMatches > 0;\n}\n\nbool WFindFile::next() {\n  if (nCurrentEntry >= nMatches) {\n    return false;\n  }\n  struct dirent* entry = entries[nCurrentEntry++];\n\n  filename_ = entry->d_name;\n  file_size_ = entry->d_reclen;\n\n#ifdef _DIRENT_HAVE_D_TYPE\n  file_type_ = DTTOIF(entry->d_type);\n\n#else\n  struct stat s {};\n  auto fullpath = FilePath(dir_, entry->d_name).string();\n  if (stat(fullpath.c_str(), &s) == 0) {\n    file_type_ = s.st_mode;\n  } else {\n    file_type_ = 0;\n  }\n#endif // _DIRENT_HAVE_D_TYPE\n\n  return true;\n}\n\nbool WFindFile::close() {\n  __close();\n  return true;\n}\n\nbool WFindFile::IsDirectory() const {\n  if (nCurrentEntry > nMatches) {\n    return false;\n  }\n  return S_ISDIR(file_type_);\n}\n\nbool WFindFile::IsFile() const {\n  if (nCurrentEntry > nMatches) {\n    return false;\n  }\n  return S_ISREG(file_type_);\n}\n"
  },
  {
    "path": "core/wfndfile_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/wfndfile.h\"\n\n#include <cstring>\n#include <string>\n\n#include <dirent.h>\n#include <fnmatch.h>\n#include <libgen.h>\n#include <limits.h>\n#include <iostream>\n#include <sys/stat.h>\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n\nstatic WFindFileTypeMask s_typemask;\nstatic const char* filespec_ptr;\nstatic std::string s_path;\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n//////////////////////////////////////////////////////////////////////////////\n//\n// Local functions\n//\n\nstatic int fname_ok(const struct dirent* ent) {\n  if (IsEquals(ent->d_name, \".\") || IsEquals(ent->d_name, \"..\")) {\n    return 0;\n  }\n\n  if (s_typemask != WFindFileTypeMask::WFINDFILE_ANY) {\n    mode_t mode = 0;\n#ifdef _DIRENT_HAVE_D_TYPE\n    mode = DTTOIF(ent->d_type);\n#else\n    struct stat s;\n    auto fullpath = FilePath(s_path, ent->d_name).string();\n    stat(fullpath.c_str(), &s);\n    mode = s.st_mode;\n#endif  // _DIRENT_HAVE_D_TYPE\n    if ((S_ISDIR(mode)) && !(s_typemask == WFindFileTypeMask::WFINDFILE_DIRS)) {\n      return 0;\n    }\n    if ((S_ISREG(mode)) && !(s_typemask == WFindFileTypeMask::WFINDFILE_FILES)) {\n      return 0;\n    }\n  }\n#if defined(__sun)\n  int result = fnmatch(filespec_ptr, ent->d_name, FNM_PATHNAME | FNM_IGNORECASE);\n#else\n  int result = fnmatch(filespec_ptr, ent->d_name, FNM_PATHNAME | FNM_CASEFOLD);\n#endif\n  VLOG(3) << \"fnmatch: \" << filespec_ptr << \";\" << ent->d_name << \"; \" << result << \"\\r\\n\";\n\n  if (result == 0) {\n    // fnmatch returns 0 on match. We return nonzero.\n    return 1;\n  }\n  return 0;\n}\n\nbool WFindFile::open(const std::filesystem::path& filespec, WFindFileTypeMask nTypeMask) {\n  __open(filespec, nTypeMask);\n  filename_.clear();\n\n  {\n    char path[FILENAME_MAX];\n    to_char_array(path, filespec.string());\n    dir_ = dirname(path);\n  }\n  {\n    char path[FILENAME_MAX];\n    to_char_array(path, filespec.string());\n    filespec_ = basename(path);\n    filespec_ptr = filespec_.c_str();\n  }\n\n  s_typemask = type_mask_;\n  s_path = dir_.string();\n  nMatches = scandir(s_path.c_str(), &entries, fname_ok, alphasort);\n  if (nMatches < 0) {\n    perror(\"scandir\");\n    return false;\n  }\n  nCurrentEntry = 0;\n\n  next();\n  return nMatches > 0;\n}\n\nbool WFindFile::next() {\n  if (nCurrentEntry >= nMatches) {\n    return false;\n  }\n  struct dirent* entry = entries[nCurrentEntry++];\n\n  filename_ = entry->d_name;\n  file_size_ = entry->d_reclen;\n\n#ifdef _DIRENT_HAVE_D_TYPE\n  file_type_ = DTTOIF(entry->d_type);\n\n#else\n  struct stat s{};\n  auto fullpath = FilePath(dir_, entry->d_name).string();\n  if (stat(fullpath.c_str(), &s) == 0) {\n    file_type_ = s.st_mode;\n  } else {\n    file_type_ = 0;\n  }\n#endif  // _DIRENT_HAVE_D_TYPE\n\n  return true;\n}\n\nbool WFindFile::close() {\n  __close();\n  return true;\n}\n\nbool WFindFile::IsDirectory() const {\n  if (nCurrentEntry > nMatches) {\n    return false;\n  }\n  return S_ISDIR(file_type_);\n}\n\nbool WFindFile::IsFile() const {\n  if (nCurrentEntry > nMatches) {\n    return false;\n  }\n  return S_ISREG(file_type_);\n}\n"
  },
  {
    "path": "core/wfndfile_win32.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/wfndfile.h\"\n\n#include \"core/strings.h\"\n#include \"core/wwiv_windows.h\"\n\nbool WFindFile::open(const std::filesystem::path& file_spec, WFindFileTypeMask nTypeMask) {\n  ffdata_ =  std::make_any<WIN32_FIND_DATA>();\n  __open(file_spec, nTypeMask);\n\n  auto* f = std::any_cast<WIN32_FIND_DATA>(&ffdata_);\n\n  const auto fs = file_spec.string();\n  hFind = FindFirstFile(fs.c_str(), f);\n  if (hFind == INVALID_HANDLE_VALUE) {\n    return false;\n  }\n\n  if (use_long_filenames_ || f->cAlternateFileName[0] == '\\0') {\n    filename_ = f->cFileName;\n  } else {\n    filename_ = f->cAlternateFileName;\n  }\n  file_size_ = f->nFileSizeHigh * MAXDWORD + std::any_cast<\n                 WIN32_FIND_DATA>(ffdata_).nFileSizeLow;\n  return true;\n}\n\nbool WFindFile::next() {\n  auto* f = std::any_cast<WIN32_FIND_DATA>(&ffdata_);\n  if (!FindNextFile(hFind, f)) {\n    return false;\n  }\n  if (hFind == INVALID_HANDLE_VALUE) {\n    return false;\n  }\n\n  if (use_long_filenames_ || f->cAlternateFileName[0] == '\\0') {\n    filename_ = f->cFileName;\n  } else {\n    filename_ = f->cAlternateFileName;\n  }\n  file_size_ = static_cast<decltype(file_size_)>((f->nFileSizeHigh * MAXDWORD) + f->nFileSizeLow);\n  return true;\n}\n\nbool WFindFile::close() {\n  __close();\n  FindClose(hFind);\n  return true;\n}\n\nbool WFindFile::IsDirectory() const {\n  return !IsFile();\n}\n\nbool WFindFile::IsFile() const {\n  const auto* f = std::any_cast<WIN32_FIND_DATA>(&ffdata_);\n  return f->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY\n           ? false\n           : true;\n}\n"
  },
  {
    "path": "core/wwiv_windows.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_CORE_WWIV_WINDOWS_H\n#define INCLUDED_CORE_WWIV_WINDOWS_H\n\n// Wrapper header file for including windows.h from wwiv.  This sets all of\n// the numerous #defines to remove much of the windows header files since the\n// surface area used by wwiv is tiny.\n\n#ifdef _WIN32\n\n#ifdef MOUSE_MOVED\n#undef MOUSE_MOVED\n#endif  // MOUSE_MOVED\n\n#ifdef CY\n#undef CY\n#endif\n\n#define NOGDICAPMASKS\n#define NOSYSMETRICS\n#define NOMENUS\n#define NOICONS\n#define NOKEYSTATES\n#define NOSYSCOMMANDS\n#define NORASTEROPS\n#define NOATOM\n#define NOCLIPBOARD\n#define NODRAWTEXT\n#define NOKERNEL\n#define NONLS\n#define NOMEMMGR\n#define NOMETAFILE\n#define NOOPENFILE\n#define NOSCROLL\n#define NOSERVICE\n#define NOSOUND\n#define NOTEXTMETRIC\n#define NOWH\n#define NOCOMM\n#define NOKANJI\n#define NOHELP\n#define NOPROFILER\n#define NODEFERWINDOWPOS\n#define NOMCX\n#define NOCRYPT\n#define VC_EXTRALEAN\n#include <windows.h>\n\n#ifdef min\n#undef min\n#endif  // min\n\n#ifdef max\n#undef max\n#endif  // max\n\n#ifdef CopyFile\n#undef CopyFile\n#endif  // CopyFile\n\n#ifdef MOUSE_MOVED\n#undef MOUSE_MOVED\n#endif  // MOUSE_MOVED\n\n#ifdef CY\n#undef CY\n#endif\n\n#endif // _WIN32\n\n#endif\n"
  },
  {
    "path": "core/wwivport.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_CORE_WWIVPORT_H\n#define INCLUDED_CORE_WWIVPORT_H\n\n// WWIV's daten type is a 32-bit unsigned int. It can never be used for date\n// arithmetic since negative values don't exist.  This will allow us to\n// truncate a 64-bit time_t value for use till 2106.\n#ifndef DATEN_T_DEFINED\n#include <cstdint>\ntypedef uint32_t daten_t;\n#define DATEN_T_DEFINED\n#endif\n\n#if !defined(__unix__) && !defined(_WIN32) && defined(__APPLE__) && defined(__MACH__)\n#define __unix__\n#endif\n\n#if defined(_MSC_VER)\n#if (_MSC_VER < 1932)\n// See https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros\n#error \"Visual Studio 2022 version 17.2.0 or later is required\"\n#endif // _MSC_VER < 1932\n\n#ifdef _WIN64\ntypedef int64_t ssize_t;\n#else\n// Most places seem to use long, and httplib grumbles\ntypedef long ssize_t;\n#endif // _WIN64\n\n#ifdef _WIN32\ntypedef int pid_t;\n#endif // _WIN32\n\n#endif // _MSC_VER\n\n#if defined(__GNUC__) && !defined(__clang__)\n#if (__GNUC__ < 8)\n#error \"GNC C++ 8.3 or later is required\"\n#endif // __GNUC__ < 8\n#endif // __GNUC__\n\n#endif\n"
  },
  {
    "path": "cpp.hint",
    "content": "// Hint files help the Visual Studio IDE interpret Visual C++ identifiers\n// such as names of functions and macros.\n// For more information see https://go.microsoft.com/fwlink/?linkid=865984\n#define VLOG(LEVEL) LOG_VERBOSE(LEVEL)\n"
  },
  {
    "path": "deps/README.md",
    "content": "# How to add a new dependency:\n***\n\n1. Fork the repo to github under wwivbbs.  We use this\n   as a way to version the dependencies we use, also can\n   test them from there.\n2. Add a submodule, usually like this:\n   ```git submodule add https://github.com/wwivbbs/module deps/module```\n3. Add a reference to it into the top level CMakeFile.txt file.\n4. Commit the change."
  },
  {
    "path": "deps/cl345/CMakeLists.txt",
    "content": "# This is needed to put it in to the root CMakeCache.txt\n# but only works if it's been built... sigh \n  add_library(CL345_LIB STATIC IMPORTED GLOBAL)\nif (WIN32) \n  set_property(\n  TARGET \n    CL345_LIB PROPERTY \n  IMPORTED_LOCATION \n    ${CMAKE_CURRENT_SOURCE_DIR}/cl32.lib)\n  set (CL32_DLL ${CMAKE_CURRENT_SOURCE_DIR}/cl32.dll PARENT_SCOPE)\n  message(STATUS \"Setting CL32_DLL: ${CL32_DLL}\")\nelse()\n  set (LIBCL_A ${CMAKE_CURRENT_SOURCE_DIR}/libcl.a)\n  add_custom_command(\n    OUTPUT ${LIBCL_A}\n    COMMAND cmake -E environment\n    COMMAND env\n    COMMAND make\n    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n    COMMENT \"Cryptlib makefile target.\"\n    )\n  add_custom_target(\n    cl345_lib_builder\n    DEPENDS ${LIBCL_A}\n  )  \n  add_dependencies(CL345_LIB cl345_lib_builder)\n  set_property(TARGET CL345_LIB PROPERTY IMPORTED_LOCATION ${LIBCL_A})\nendif()\nset_property(\n  TARGET CL345_LIB\n  APPEND PROPERTY\n      INCLUDE_DIRECTORIES \"${CMAKE_CURRENT_SOURCE_DIR}\"\n)\nmessage (DEBUG \"CL: ${cl345_lib}:${LIBCL_A}\")\n"
  },
  {
    "path": "deps/cl345/COPYING",
    "content": "This file contains the usage terms for cryptlib.  The full details of cryptlib\nusage are provided on the cryptlib home page; although this file and the\ninformation on the web page should be identical, in case of any dispute the\nweb page takes precedence.  This file is included because some distributions\nrequire the presence of a COPYING file.\n\ncryptlib is distributed under a dual license that allows free, open-source use\nunder a GPL-compatible license and closed-source use under a standard\ncommercial license.  The GPL-compatible license (a.k.a. the Sleepycat license)\nis given below.  Further details on this license are available from the\ncryptlib home page.\n\n  Copyright 1992-2018 Peter Gutmann. All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice, this\n     list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright notice,\n     this list of conditions and the following disclaimer in the documentation\n     and/or other materials provided with the distribution.\n\n  3. Redistributions in any form must be accompanied by information on how to\n     obtain complete source code for the cryptlib software and any accompanying\n     software that uses the cryptlib software.  The source code must either be\n     included in the distribution or be available for no more than the cost of\n     distribution, and must be freely redistributable under reasonable\n     conditions.  For an executable file, complete source code means the source\n     code for all modules it contains or uses.  It does not include source code\n     for modules or files that typically accompany the major components of the\n     operating system on which the executable file runs.\n\n  THIS SOFTWARE IS PROVIDED \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  IN NO\n  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n  OF SUCH DAMAGE.\n\nNote that decoupling the software from the user, for example by running in a\nSaaS configuration, does not exempt you from these requirements.\n\nIf you're unable to comply with the above license then the following,\nalternate usage conditions apply:\n\n  Any large-scale commercial use of cryptlib requires a license.  \"Large-scale\n  commercial use\" means any revenue-generating purpose such as use for\n  company-internal purposes, or use of cryptlib in an application or product,\n  with a total gross revenue of over US$5,000.  This allows cryptlib to be\n  used in freeware and shareware applications, for evaluation and research\n  purposes, and for non-revenue-generating or personal use without charge.  In\n  addition the author reserves the right to grant free licenses for commercial\n  use in special cases (for example where there is a general benefit to the\n  public), contact the author for details if you think you qualify.\n"
  },
  {
    "path": "deps/cl345/README",
    "content": "Changes in 3.4.5 release\n========================\n\nThis release now officially supports the WebSockets client/server\nimplementation that was added in 3.4.4.1 as a developmental feature.\n\nThe entropy-polling code has been improved to add polling of further entropy\nsources on different systems, including environmental monitoring such as\nthermal data, CPU instruction execution statistics, and similar low-level\nhardware-based information.\n\nSupport for hardware-based crypto outside of instruction/CPU-level support\nlike AES-NI and VIA Padlock has been added.  If present and enabled on the\nsystem, cryptlib will automatically use crypto hardware capabilities provided\nby CPUs such as Allwinner A-series, Marvell Kirkwood, NVIDIA Tegra, NXP i.MX,\nPowerPC, Rockchip RK-series, Qualcomm Snapdragon, Samsung Exynos, and TI OMAP.\n\nThe build process has been improved to take better advantage of system- and\ncompiler-specific capabilities, for example use of enhanced compiler\nfacilities like LLVM's SafeStack/CPI are now enabled if available, and\nparallel makes are supported on systems that support it.  In addition the\nautomatic detection and enabling of system facilities like hardware crypto and\nPKCS #11 devices has been improved.\n\nBeyond this, further changes to enhance stability and code/data safety and\ndiagnose problems interoperating with other systems have been implemented.\n\nChanges in 3.4.4.1 release\n==========================\n\nThis release updates the TLS cipher suite selection to deal with the problem\nthat several large Internet CDNs and service providers have recently chosen to\ndisable the standard PFS cipher suites, leaving only the rather unsafe RSA\nsuites available for use with older versions of TLS.\n\nIn addition this release contains a number of additional diagnostic\ncapabilities to identify interoperability problems with other crypto protocol\nimplementations.\n\nChanges in 3.4.4 release\n========================\n\nThis release adds support for TLS-LTS, fixing every (known) attack on TLS and\nproviding extra security against any future attacks (the previous addition of\nencrypt-then-MAC and extended master secret were part of this move).\n\nThis release also adds support for the final version of the SCEP standard,\nwhich replaces eighteen years worth of draft versions.\n\nPerformance in memory-constrained environments such as embedded devices has\nbeen improved, with additional configuration options to reduce memory usage to\nas little as 150-200K of code space for an SSH or TLS server.\n\nBeyond this, further changes to enhance stability and code/data safety have\nbeen implemented.\n\nChanges in 3.4.3 release\n========================\n\nThis release adds support for TLS encrypt-then-MAC, which fixes about fifteen\nyears' worth of oracle attacks against the SSL/TLS protocol, and TLS Extended\nMaster Secret, which fixes another collection of attacks.  It also adds\nsupport for the protocol-downgrade signalling cipher suite (SCSV), which helps\ndetect protocol-downgrade attacks.\n\nThe default build environment under Windows has been updated from VS 2010 to\nVS 2015, alongside the long-standing existing option to use VC++ 6.0.\n\nAll CRYPT_xxx_FINGERPRINT attributes now have explicit types as part of their\nnames in order to reduce confusion about their sizes.\nCRYPT_CERTINFO_FINGERPRINT is now CRYPT_CERTINFO_FINGERPRINT_SHA1 (the\nobsolete CRYPT_CERTINFO_FINGERPRINT_MD5 is no longer supported, as part of the\ngeneral removal of MD5 from circulation), and\nCRYPT_SESSINFO_SERVER_FINGERPRINT is now\nCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1.\n\nSupport for the obsolete and/or patented and/or insecure algorithms Blowfish,\nDES, RC2, RC5, Skipjack, MD2, MD4, MD5, HMAC-MD5, RIPEMD-160, and HMAC-RIPEMD\nhave been removed.\n\nThe SCEP implementation now supports both initialisation requests (protected\nby user name and password) and certificate update requests (protected by user\nname and signature).  Because of this you need to specify the SCEP request\ntype using the (slightly misnamed) CRYPT_SESSINFO_CMP_REQUESTTYPE attribute,\nwhich can be either CRYPT_REQUESTTYPE_INITIALISATION or\nCRYPT_REQUESTTYPE_CERTIFICATE.\n\nThe cryptlib keyset types CRYPT_KEYSET_ODBC and CRYPT_KEYSET_DATABASE have\nbeen unified under the name CRYPT_KEYSET_DATABASE, since they represented the\nsame thing.\n\nThe encryption mode CRYPT_MODE_OFB, which wasn't used in any known protocol,\nhas been removed, and replaced with CRYPT_MODE_GCM where available (in this\ncase only for AES).\n\nThe default key sizes used for PKC algorithms have been increased to provide a\nhigher margin of security.\n\nThe default hash algorithm used in various protocols is now SHA-2 rather than\nSHA-1.  Previous versions of cryptlib would automatically upgrade the hash\nalgorithm used to the strongest one supported by the peer if this was\ndetectable (for example by examining the hash algorithm used in the peer's\ncertificate), this version now makes SHA-2 the default.  Note that some\nprotocols that use hash algorithms employ them in the HMAC construct, which\nrenders them immune to standard attacks, so use of HMAC-SHA1 doesn't carry the\nsame concerns as use of pure SHA-1.\n\nAlongside the switch to SHA-2 as the default, support for the obsolete PGP2\nand SSLv3 protocols has been disabled.  If you need to work with them, you can\nenable them by building with USE_PGP2 or USE_SSL3, however these protocols are\nnow unsupported and the code for them will be removed in a future release.  In\nconjunction with this, support for the IDEA cipher, which is only used with\nPGP2, will also be removed.\n\ncryptlib now supports the Quantis quantum random number generator.  If you\nhave a quantum random number generator attached to your system, cryptlib will\nautomatically identify it and use it as an additional source of entropy for\nkey generation.\n\nChanges in 3.4.2 release\n========================\n\nThis is a maintenance release that adds better text-string diagnostics for a\nnumber of operations, fixing a long-standing PGP authenticated-encryption\ninteroperability issue that was obscure enough that no-one's ever noticed,\nincreasing compatibility (meaning adding lots of bug-workarounds) with\nMicrosoft's NDES SCEP server, providing more flexible handling of a variety of\nrarely-used protocol options and capabilities added at the request of users,\nand the usual ongoing updates for OSes and compiler versions.\n\nChanges in 3.4.1 release\n========================\n\nThis is a maintenance release for new OS and compiler versions, and\nspecifically VS 2010, which has trouble with the VS 2005 project files that\nwere included in previous releases.  Apart from various code updates, it adds\nclient-side SSL/TLS session resumption alongside the existing server-side\nsession resumption.\n\nChanges in 3.4 release\n======================\n\nThis version of cryptlib is a minor-version stepping from the 3.3.x code base\nto the 3.4.x code base.  Minor-version steppings are source-code compatible\nwith previous versions but not binary compatible.  This means that you need to\nrebuild the application calling cryptlib when you move to cryptlib 3.4.0 in\norder to add support for new attributes introduced for the post-3.3 API. In\naddition the cryptGenerateKeyAsync()/cryptAsyncQuery()/cryptAsyncCancel()\nfunctions, deprecated since 2007, have been removed for the 3.4 API change,\nand the transparent rewriting of CRYPT_CERTINFO_SUBJECTNAME and\nCRYPT_CERTINFO_ISSUERNAME selection commands to the pre-2007 form has been\ndisabled.\n\nThis release features the usual ongoing updates for new OS and compiler\nversions.  One significant update is direct support for x86-64 under 64-bit\nversions of Windows (this previously required a custom build), with the 64-bit\ntarget in the project file building a cl64.dll that's analogous to the 32-bit\ncl32.dll.\n\nThe TLS code has been updated to add support for TLS 1.2.  Since TLS 1.2 uses\ncryptographic mechanisms that are gratuitously incompatible with any other\nversion of SSL or TLS, the default version that cryptlib will advertise in a\nhandshake remains TLS 1.1.  If you want to use TLS 1.2 you need to explicitly\nenable it as described in the manual.  Note that because of the incompatible\nchanges made in TLS 1.2 there is (two years after its introduction) still very\nlittle support for it among vendors.  Expect interoperability problems.\n\nThis version of cryptlib implements RFC 5083 authenticated encryption.  PKCS\n#15 private keys are now protected in this manner (private-key data from older\nversions of cryptlib can still be read, but newer keys will be protected with\nfull authenticated encryption).  In addition data enveloped using\nCRYPT_FORMAT_CRYPTLIB will automatically use authenticated encryption while\nother formats (CRYPT_FORMAT_CMS, CRYPT_FORMAT_SMIME) will stay with\nunauthenticated encryption for compatibility with existing implementations.\nYou can enable authenticated encryption for the other formats (or turn it off\nfor the cryptlib format) as described in the manual.\n\nElliptic-curve cryptography is now supported, both at the low-level crypto\nmechanism level and in high-level protocols like X.509, SSL/TLS, S/MIME, and\nSSH.  To enable it, define USE_ECDH and/or USE_ECDSA in misc/config.h when you\nbuild cryptlib.\n\nCertificate fingerprints using SHA-2 and the future SHA-3 (when it's\nfinalised) is now supported with CRYPT_CERTINFO_FINGERPRINT_SHA2 and\nCRYPT_CERTINFO_FINGERPRINT_SHAng (use of the latter will return a\nCRYPT_ERROR_NOTAVAIL, it's only present as a placeholder for future releases).\n\nSupport for the Internet routing resource PKI (RPKI) has been added, see the\nmanual for details.\n\ncryptlib 3.4.0 has been updated to use zlib 1.2.4, the first zlib update in\nfive years.  As always, users concerned about security issues should disable\nthe compression code (undefine USE_COMPRESSION in misc/config.h) unless it's\nactually required.\n\nSeveral ambiguous attributes have been removed or renamed to make their role\nclearer.  For the keyset types, CRYPT_KEYSET_PLUGIN and\nCRYPT_KEYSET_PLUGIN_STORE have been removed since these have always been\nhandled identically to CRYPT_KEYSET_DATABASE and CRYPT_KEYSET_DATABASE_STORE.\nFor the error attributes, CRYPT_ATTRIBUTE_INT_ERRORCODE has been removed since\nthis wasn't very useful outside of cryptlib and\nCRYPT_ATTRIBUTE_INT_ERRORMESSAGE has been renamed CRYPT_ATTRIBUTE_ERRORMESSAGE\nto reflect its role alongside CRYPT_ATTRIBUTE_ERRORTYPE and\nCRYPT_ATTRIBUTE_ERRORLOCUS.\n\nChanges in 3.3.3 release\n========================\n\nThis is another maintenance release with updates for new compiler versions and\nOS releases, as well as code changes to handle upgrades to newer hash\nalgorithms in the SHA-2 family for protocols that previously used SHA-1.  In\naddition the Windows DLL version included with the release is now built with\nVS 2005 instead of VC 6, since it's unlikely that there are any systems left\nthat don't have the runtime libraries needed for this.\n\nA number of rarely-used facilities that, due to their complexity, have a large\nattack surface or considerable potential for abuse, have been disabled by\ndefault in this release.  These are DNS SRV, LDAP, string-format X.500 DNs,\nand SSH subsystems and channel multiplexing.  If you really require any of\nthese you can enable them as described in \"Optional cryptlib Components\" in\nthe manual.  You should only enable these facilities if you absolutely need\nthem, and your security guarantee is void if you do.\n\nThere's one small change made to the handling of certificate attribute\nselection, currently all attributes except certificate subject and issuer\nnames are selected with 'cryptSetAttribute( cryptCert,\nCRYPT_CERTINFO_CURRENT_ATTRIBUTE, <attribute-type> )' while the certificate\nsubject and issuer names are selected with 'cryptSetAttribute( cryptCert,\nCRYPT_CERTINFO_SUBJECTNAME, CRYPT_UNUSED )' (this is done for historical\nreasons because the subject and issuer names aren't X.509 certificate\nextensions and so exist in a different space than standard certificate\nextensions, putting them outside the reach of the standard attribute cursor\nmechanisms).\n\nThis version of cryptlib now allows issuer and subject names to be selected in\nthe same way as other attributes, 'cryptSetAttribute( cryptCert,\nCRYPT_CERTINFO_CURRENT_ATTRIBUTE, CRYPT_CERTINFO_SUBJECTNAME )'.  The previous\nmethod is still supported for backwards-compatibility purposes, but for\nforwards compatibility you should search your code for occurrences of\nCRYPT_CERTINFO_SUBJECTNAME/ISSUERNAME and switch the attributes around to use\nthe new form.  To alert you to cases where you're using the old way of doing\nthings, the debug build of cryptlib will thrown an exception if it detects\nthis (the standard build will continue to function as before, it's only the\ndebug build that will notify you of the superseded usage).\n\nChanges in 3.3.2 release\n========================\n\nThis release features numerous updates to the build mechanism and code to\nhandle new compiler versions, as well as workarounds for interoperability\nproblems with other implementations.  This version also features various\nreliability and stability enhancements.\n\nChanges in 3.3.1 release\n========================\n\nThis release features ongoing minor updates and changes requested by users, as\nwell as updates to work with the (almost-) TR 24731 stdlib replacements in VS\n2005.  This is mainly a cleanup and consolidation release after 3.3.0, however\none important reason to upgrade is that the pre-generated test keys will\nexpire shortly after the 3.3.1 release, which will produce warnings in the\nself-test and self-test failures (X.509 certificates have limited lifetimes\ndue to their expiry dates, and the code is warning that they're past their\nuse-by date).  cryptlib has to set some sort of expiry date for the keys\nbecause the format requires it, but an unfortunate side-effect of this is that\nevery now and then the test keys needed for the self-test expire.  This\nrelease updates the test keys for another few years.\n\nChanges in 3.3 release\n======================\n\nThis version of cryptlib is a minor-version stepping from the 3.2.x code base\nto the 3.3.x code base.  Minor-version steppings are source-code compatible\nwith previous versions but not binary compatible.  This means that you need to\nrebuild the application calling cryptlib when you rebuild cryptlib.  In\nparticular two facilities that have been included for backwards-compatibility\nwith code from up to five years ago have now been removed: It's no longer\npossible to call cryptPushData() with NULL pointers as an alternative to\ncalling cryptFlushData(), and the obsolete CRYPT_CERTINFO_CURRENT_xxx\nattributes, which were mapped internally to the CRYPT_ATTRIBUTE_CURRENT_xxx\nattributes, have been removed.\n\nThis release features more internal changes to handle internal consistency\nchecking, as well as fixes for a few minor issues arising from the 3.2.3\nrelease.\n\nChanges in 3.2.3 release\n========================\n\nThis release features a considerable number of internal changes to clean up\nsome sections of the code that had grown beyond their original design, as well\nas ongoing minor updates and changes requested by users.  This is mainly a\ncleanup and consolidation release after 3.2.2.\n\nChanges in 3.2.2 release\n========================\n\nThe bignum code has been updated to the latest version, which is no less\nghastly than before but somewhat faster, particularly on x86 systems.\n\nChanges in 3.2.1 release\n========================\n\nThe zlib code has exhibited a number of security vulnerabilities, both in the\nrather dated 1998-vintage zlib 1.1.x code and the much newer zlib 1.2.x code.\nIn order to avoid exposing cryptlib users to any new technology until it's\nproven itself in the field, cryptlib has stayed with the old zlib code base,\nwhich has avoided problems arising from the vulnerabilities found in the 1.2.x\ncode.  However, the 1.2.x code base does have a number of advantages over the\nold 1.1.4 code, including better compression, much faster compression and\ndecompression, and significantly less memory consumption, particularly for\ndecompression.  Another potential problem with 1.1.4 is that there may be as\nyet undiscovered problems in it that no-one's found yet because they're\nconcentrating on the newer 1.2.x instead.\n\nBecause zlib 1.2.x includes a significant rewrite of a fair portion of the\ncode, it's not possible to simply switch from one version of zlib to the other\nat the flip of a compiler switch.  Based on user feedback, the preferred\nbehaviour is to have cryptlib move from the old 1.1.x to the current 1.2.x\ncode base, so cryptlib 3.2.1 uses zlib 1.2.3 (those values are pure\ncoincidence).  Users concerned about security issues should disable the\ncompression code (undefine USE_COMPRESSION in cryptini.h) unless it's actually\nrequired.\n\nSupport of autoproxy configuration (under operating systems that implement\nautomatic network proxy discovery) has been added.  This includes support for\nSOCKS-style HTTP proxies as well as the originally implemented HTTP-\napplication-gateway HTTP proxies.\n\nSeveral minor portability issues in 3.2 have been fixed, among other things a\nworkaround for a problem in gcc 4.0 that prevented the code from compiling.\n\nChanges in 3.2 release\n======================\n\nThe version that would have been released as 3.11 has been released as 3.2 to\navoid version-numbering confusion. Future releases will use a three-digit\nnumbering scheme x.y.z, where each of x, y, and z will constitute a single\ndigit, to avoid confusion over whether the '11' in '3.11' is 11 or 0.11.\n\nThe network timeout handling has been split into distinct read and write\ntimeouts to allow more flexible configuration of network data handling,\ntypically very small read timeouts to ensure that cryptlib never blocks while\nwaiting for data, and slightly larger write timeouts to ensure that all data\nis completely written when requested.\n\nClient authentication for sessions that support this (only the secure data\nsessions, SSH and SSL/TLS, use client authentication) has been changed\nslightly.  In previous releases, cryptlib would always allow the client's\nauthentication and complete the handshake, leaving it to the caller to shut\ndown the session later on if there was a problem.  As of this release, server\nsessions will return a CRYPT_ENVELOPE_RESOURCE in the same way that envelopes\ndo when you activate them, to indicate that you need to provide further\ninformation in order to continue.  If you receive this status when you try to\nactivate a server session, you can read the user details via the\nCRYPT_SESSINFO_USERNAME and CRYPT_SESSINFO_PASSWORD attributes, and either\nconfirm the authentication by setting the CRYPT_SESSINFO_AUTHRESPONSE to true\nor deny it by setting it to false.  You then re-activate the session, and\ncryptlib will complete the handshake.  This allows you to check the\nauthentication details before allowing the handshake to continue.  If you'd\nprefer the previous behaviour, just set CRYPT_SESSINFO_AUTHRESPONSE to true\nbefore you activate the session and cryptlib will handle confirmation of\nauthentication itself.\n\nBecause the handshake is now controlled by the server rather than the client\n(that is, cryptlib won't sit in a loop reading all data from the client, but\nwill return to the caller to await further input), it's possible that the\nclient will send further session-control information after the handshake has\ncompleted.  To respond to any additional information that the client may send,\nyour server should try and pop client data before it sends any of its own\ndata.  If the server sends its data first, the client may interpret the\nserver's data as an (invalid) response to a request that it has in progress.\nThe manual contains more details on the new client authentication and server\ndata handling process.\n\nStarting with releases after 3.2, the attribute cursor manipulation functions\nwill be unified so that they work identically for all container objects that\nmaintain lists of attributes (most of this interface is already available in\n3.2 for forwards-compatibility reasons).  This means that the three attribute-\nlist mechanisms CRYPT_CERTINFO_CURRENT_EXTENSION,\nCRYPT_CERTINFO_CURRENT_FIELD, and CRYPT_CERTINFO_CURRENT_COMPONENT (for\ncertificates), CRYPT_ATTRIBUTE_CURRENT_GROUP (formerly\nCRYPT_ENVINFO_CURRENT_COMPONENT) for envelopes, and the future\nCRYPT_ATTRIBUTE_CURRENT_GROUP for session objects will be folded into the\nsingle mechanism CRYPT_ATTRIBUTE_CURRENT_GROUP, CRYPT_ATTRIBUTE_CURRENT, and\nCRYPT_ATTRIBUTE_CURRENT_INSTANCE.  This provides both a unified, consistent\ninterface across the different object types and allows envelope and session\nattributes to be handled in the same way as certificates currently are.  For\nexample under the older cryptlib 3.1 behaviour envelope signatures were\nimplicitly selected by reading the signature attribute, which changed the\ncurrent selection of the signature result and extra signature information\nattributes.  From releases after this one envelope signature attributes are\ngrouped by signature, so selecting the first signature explicitly selects the\nassociated signature key, signature result, and extra signature information\nattributes, selecting the second signature explicitly selects the associated\ninformation for that, and so on.  In addition reading this information under\n3.1 and earlier was something of a hunt-and-peck approach that required\nreading each possible attribute in turn to see whether it was present.  The\nattribute cursor interface allows each present attribute to be enumerated\nusing the attribute cursor, with cryptlib doing the work of sorting out what's\npresent and what isn't.  Finally, cryptlib 3.2 allows more session attributes\nto be accessed by the caller, which requires the use of attribute cursors\nsince many of them are composite values or multi-valued attributes.\n\nAs part of this unification of mechanisms, the CRYPT_ENVINFO_CURRENT_COMPONENT\nattribute has been renamed CRYPT_ATTRIBUTE_CURRENT_GROUP for compatibility\nwith future cryptlib releases.  For certificates, cryptlib 3.11 supports both\nthe legacy CRYPT_CERTINFO_CURRENT_xxx attributes and the new\nCRYPT_ATTRIBUTE_CURRENT_xxx ones, so you can either keep using the\ncertificate-specific cursor attributes for now or move to the universal cursor\nattributes for compatibility with future versions.  All that's necessary to\nupgrade is a search and replace in your code to rename the attributes.  More\ninformation on the unified attribute cursor mechanism is given in the\nIntroduction section of the manual.\n\nThe various situation-specific SSH attributes like\nCRYPT_SESSINFO_SSH_SUBSYSTEM and CRYPT_SESSINFO_SSH_PORTFORWARD have been\nreplaced with more generic forms for compatibility with future cryptlib\nversions, which allow more complete control over SSH channel types and\nparameters.  See the manual for details on creating and controlling SSH\nchannels using the new attributes.\n\nThe SHA-2 algorithm is now enabled by default (previously it had to be\nexplicitly enabled via a compile-time option).  Note that this algorithm isn't\nsupported by most software and standards, so using it in anything other than\nclosed environments will lead to interoperability problems.  If you want to\nuse SHA-2, you should test it against any other software that you need to\ninteroperate with to ensure that it can handle this algorithm.\n\nThe Unix randomness slow poll now has an early-out mechanism that avoids the\nfull heavyweight slow poll if sufficient entropy is available without it.\nThis typically occurs on systems with both built-in randomness sources and\neither a kernel statistics interface or an advanced /proc interface, which\nprovide the same data as the full slow poll at a fraction of the overhead.\n\nChanges in 3.11 beta 1\n======================\n\nAs noted in the 3.1 release notes, releases after 3.1 update the cryptlib 2.x\nlegacy functions cryptImport/ExportKey(Ex), cryptCreate/CheckSignature(Ex),\nand cryptQueryObject to take a length parameter as their second argument.\nThese functions never took a length parameter in their original form because\nthey dealt with encoded signature/key exchange data, for which it's always\npossible to determine the length by parsing it.  However, this makes checking\nof user-supplied parameters difficult - cryptlib always knows how much output\nit'll produce, but it can't be sure that the user wants (or expects) that much\noutput, particularly if they've forgotten to perform a length check before\nexporting a key or creating a signature.  In order to avoid this problem,\nreleases after 3.1 make this minor API change, which fixes the last of the old\ncryptlib 2.x functions.  Since most people use the higher-level API functions,\nthis change shouldn't affect the majority of users.\n\nIn addition to the cryptlib 2.x legacy functions, two standard data-returning\nfunctions cryptExportCert and the rarely-used cryptGetCertExtension now also\ntake a length parameter to specify the maximum buffer size.  This brings them\ninto line with the (updated) legacy functions, and allows cryptlib to perform\nbetter checking of user-supplied parameters, particularly in the case of\nlanguages like Visual Basic and Java where the mapping of language-native data\ntypes to the blocks of memory used by a C-language library can be tricky.\n\nChanges in 3.1 release\n======================\n\nThe final release contains mostly minor tweaks based on user feedback from the\n3.1 final betas, with no noticeable external changes.  Internally, the HTTP\nengine has been significantly improved, TLS 1.1 is now supported (although at\nrelease time there were no other known implementations of this to test\nagainst), the BeOS port has been re-done to handle the current state of the OS\nusing GNU development tools instead of the original Be ones (thanks to Simon\nTaylor for providing access to his system to do the work on), and the\nperpetual tweaking of the networking subsystem to handle OS-specific quirks\nhas continued.\n\nChanges in 3.1 beta 5\n=====================\n\nThis release contains an extensive rewrite of the network-layer code to handle\nvarious quirks and system-specific peculiarities in sockets implementations.\nFor this reason it's strongly recommended that if you're using secure sessions\nor networking, you move to this version as quickly as possible.  In addition\nthe code is now IPv6-enabled as part of the rewrite.  In connection with this,\nit's now possible to specify connect and network timeouts at the per-session\nlevel rather than only as a cryptlib-wide option. To do this, set the timeout\nvalue giving a specific session as the target object rather than CRYPT_UNUSED\nfor all of cryptlib:\n\n  cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_TIMEOUT, timeout );\n\nAll of the session objects now provide extensive text diagnostics of errors\nvia the CRYPT_ATTRIBUTE_INT_ERRORMESSAGE attribute.  This means that if a\nsession encounters a problem in communicating with another system, the\nextended error message will usually provide additional information that goes\nbeyond the standard error code.\n\nSupport for SSHv2 subsystems such as SFTP has been added via the\nCRYPT_SESSINFO_SSH_SUBSYSTEM attribute, and support for SSL/TLS with shared\nkeys (e.g. passwords) has been added.  This allows secure SSL with mutual\nauthentication of both client and server, without the need for either\nexpensive server certificates or the complexity of client certificates.  In\naddition the shared-key mechanism is significantly faster than operations\ninvolving certificates and private keys, and places far less load on both\nclient and server.\n\nThe CRYPT_OPTION_CERT_OBLIVIOUS option introduced in beta 4 has been changed\nfrom a simple boolean value to a multivalued option\nCRYPT_OPTION_CERT_COMPLIANCELEVEL, which indicates the level of checking\napplied to certificates.  This ranges from CRYPT_COMPLIANCELEVEL_OBLIVIOUS\n(almost no checking except for the signature) through to\nCRYPT_COMPLIANCELEVEL_PKIX_FULL (full compliance with PKIX certificate\nstandards).  The default is CRYPT_COMPLIANCELEVEL_STANDARD, which provides a\nreduced level of checking for compliance with other certificate software.\n\nThe CRYPT_ERROR_BUSY status has been renamed to CRYPT_ERROR_TIMEOUT to make it\nmore consistent with conditions like network timeouts, which is where it most\ncommonly occurs.\n\nSome of the database keyset types have been renamed to make the names more\nconsistent.  The three types are now CRYPT_KEYSET_ODBC for databases accessed\nthrough an ODBC interface, CRYPT_KEYSET_DATABASE for databases with the\nbackend-specific interface code compiled into cryptlib, and\nCRYPT_KEYSET_PLUGIN for databases accessed via the cryptlib database plugin\ninterface.  The CRYPT_KEYSET_DATABASE type can be selected in the usual manner\nat compile time with the USE_xxx compile options, see the manual for more\ndetails on databases and compile options.\n\nChanges in 3.1 beta 4\n=====================\n\nThe changes in this release are mostly to fix a variety of minor problems that\ncropped up in beta 3 related to portability across different systems.  One\nnotable change is the inclusion of the CRYPT_OPTION_CERT_OBLIVIOUS\nconfiguration option.  This option is present in order to allow cryptlib to\nhandle the large number of broken certificates in use.  Enabling this option\n(setting it to TRUE) will cause cryptlib to ignore all certificate extensions\nexcept key usage and the CA flag, making it compatible with other PKI\nsoftware.  A future version of cryptlib will replace this option with a\nmultivalue selection allowing a choice of checking ranging from very little\n(in order to be compatible with existing software and to process existing\ncertificates) through to full PKIX compliance (which will, however, reject a\nlarge number of certificates in use today).\n\nChanges in 3.1 beta 3\n=====================\n\nThe way in which GeneralNames and DNs in GeneralNames are selected has\nchanged.  Until now GeneralNames were selected with:\n\n  cryptSetAttribute( cryptCert, attributeID, CRYPT_UNUSED );\n\nwhich selected the GeneralName with the given attributeID and also updated the\nattribute cursor.  Selecting the DN within the GeneralName required a second\nselection to specify the DN.  This special-case behaviour was inconsistent\nwith the way other attributes were handled, and caused some confusion for\nusers, as well as obscuring the fact that the attribute cursor was being\nupdated as it would be for an explicit attribute selection.  Beta 3 changes\nthe selection mechanism so that it matches that used for all other attributes:\n\n  cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CURRENT_EXTENSION,\n                     attributeID );\n\n(or whatever alternative attribute cursor mechanism is preferred).  In\naddition, it's no longer necessary to perform a two-stage select for DNs in\nGeneralNames, since these are now implicitly selected by selecting the\nGeneralName that contains them.  This means that handling of GeneralName\nattributes is now consistent with all other attribute types.\n\nBecause GeneralNames are now automatically selected, you need to be careful\nwhen working with a DN such as the certificate subject name after selecting a\nGeneralName, since a GeneralName contains its own DN which will be the one\nthat's accessed after selecting the GeneralName.  For example if you set an\nemail address (which is part of the GeneralName), this will select the\nGeneralName, and any subsequent DN accesses will refer to the DN inside the\nGeneralName rather than the subject name DN.  It's good practice to move back\nto the subject name with:\n\n  cryptSetAttribute( cryptCert, CRYPT_CERTINFO_SUBJECTNAME,\n                     CRYPT_UNUSED );\n\nafter working with a GeneralName to make sure that you're referring to the\ncorrect DN.\n\nMicrosoft broke the Jet (MS Access) database engine at around SP4 (opinions on\nthe exact time vary).  This version, or newer versions, may be installed\nautomatically when applying service packs or installing other software\n(different broken versions of Jet are installed in Win2K SP2 and SP3, for\nexample, and it's built into Windows XP).  The symptoms are that when running\nthe self-test you'll get an error message \"Cannot open any more tables\" even\nthough no tables are open, or more seriously a deadlock inside the VC++\nruntime file access routines.  The details of this problem are discussed in\nMicrosoft Knowledge Base Article 304536, Microsoft Knowledge Base Article\n282010, and Microsoft Knowledge Base Article 239114.\n\nThe Microsoft-recommended fix is to upgrade to Jet SP6.  This typically\nrequires downloading and installing the SP6 upgrade from the Microsoft\nDownload Centre, simply installing recent MDAC components won't work since\nthere were no Jet components included after MDAC 2.5 SP2, and installing\nOffice XP or Access 2002 may not work either since the setup programs only\nupdate system files in certain situations and to a certain level.  On the\nother hand Jet SP6 may not install unless it detects an appropriate service\npack level on the system.\n\nNon-Microsoft advice is to downgrade to a version of Jet at SP3 or earlier by\nreplacing msjetoledb40.dll and msjet40.dll with files from JET OLE DB SP3,\nsince even the latest version (SP6) still appears to exhibit these problems.\nA better solution is to avoid the use of Jet entirely, and in particular you\nshould *never* use Jet in a production environment since it's far too buggy\nand unstable to trust live data to (it was probably named Jet because it both\nsucks and blows).\n\nChanges in 3.1 beta 2\n=====================\n\nThe last two type names that didn't follow the pattern xxx_TYPE, CRYPT_ALGO\nand CRYPT_MODE, have now been brought into line with the other names, so you\nneed to change the type names to CRYPT_ALGO_TYPE and CRYPT_MODE_TYPE if you're\nusing them in your code.\n\nSSHv2 server support is now present.\n\nPKCS #11 devices can now be auto-detected by specifying the device name as\n\"[Autodetect]\" if the device name isn't known.\n\nPre-connected network sockets can be supplied to sessions as the\nCRYPT_SESSINFO_NETWORKSOCKET attribute, rather than having cryptlib\nconnect/disconnect the socket itself.\n\nThe PKCS #15 format has had various features added to it over time (see the\nnote for 3.0 beta 1), cryptlib has supported these in a read-only manner,\nmeaning that it creates keysets that are as backwards-compatible as possible\nwith old versions of the code that used earlier versions of PKCS #15.  In\norder to make some features like certificate update in a keyset possible, it's\nnecessary to write keyset fields from newer versions of PKCS #15.  All betas\nafter this one will write these newer fields in order to enable advanced\nfeatures of PKCS #15.  Anyone still using very old betas should upgrade to a\ncurrent version in order to take advantage of the advanced features supported\nby newer-format PKCS #15 keysets.\n\nChanges in 3.1 beta 1\n=====================\n\nBeta 1 includes support for PGP and OpenPGP, which is handled in standard\nenvelope fashion with a data format of CRYPT_FORMAT_PGP.  Note that there are\na number of incompatible and semi-compatible variants of PGP in existence,\nwith the major types being PGP 2.x, PGP 5.x, NAI PGP, GPG, and the ckt PGP\nbuilds, and many interesting lesser variations such as the disastry builds\nthat take PGP 2.x and update it to support OpenPGP ciphers without actually\nbeing OpenPGP.  An overview of different PGP versions can be found at\nhttp://rmarq.pair.com/pgp/, and detailed information on incompatibilities can\nbe found at http://www.spywarewarrior.com/uiuc/pgp-summ.htm.  cryptlib has\nbeen tested against most normal versions of PGP, but there will certainly be\nversions out there that produce data that cryptlib can't read (one example\nbeing a version that uses random key IDs in encrypted data in order to obscure\nwho the data is encrypted for, which also makes it impossible to decrypt with\nany normal PGP version).  If you run into something produced by one of these\noddball versions, please send me a copy so that I can determine whether it's\nworth adding custom code to support it.\n\nThe PGP data format imposes a number of restrictions on the standard\nenveloping process, which include:\n\n - Use of nested signed data is discouraged unless you add an intermediate\n   layer of encryption, since PGP doesn't directly handle nested signatures.\n - When signing data, the nested content type can only be the default (data)\n   for the reason given above.\n - It's not possible to mix password and public-key key exchange actions in\n   the same message.  Similarly, it's not possible to have more than one\n   password key exchange action in one message.\n - Handling of separate hashing for detached signatures is somewhat peculiar\n   and requires special care.\n\nChanges in 3.0 release\n======================\n\ncryptlib 3.1 will introduce a new function cryptFlushData() to replace the\ncurrent practice of calling cryptPushData() will all-null parameters, a change\nrequired for languages like Delphi and VB that don't handle C null pointers\ntoo well.  This function is already present in 3.0 for forwards-compatibility\npurposes, it's recommended that you update your code to call cryptFlushData()\nin place of cryptPushData() with null parameters (although the existing\ncryptPushData() mechanism will still work).\n\nThe Unix randomness-gathering code will now check for and use EGD/PRNGD if\nthey're available.\n\nThe requirement that cryptlib be built via a network share under Windows has\nbeen removed.\n\nHTTP keyset access (CRYPT_KEYSET_HTTP) formerly required that the keyset be\nopened without a name being given, with the full URL being specified as the\nkey ID to retrieve keys.  This was both somewhat inconsistent with the other\nkeyset types, and didn't work well with persistent connections, for example\nwhere multiple certificates were being read from a single server.  This has\nbeen changed so that the server URL is given when the keyset is opened as it\nis for other keyset types, and a key ID is given when reading individual keys.\nWhen reading keys with a fixed URL (with no per-key ID), the special ID\n\"[none]\" can be used to indicate that the server URL points directly at the\ncertificate.  In the simplest case the previous usage:\n\n  cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP, NULL,\n                   CRYPT_KEYOPT_READONLY );\n  cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n                     \"http://www.server.com/cert.der\" );\n\nnow becomes:\n\n  cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n                   \"http://www.server.com/cert.der\", CRYPT_KEYOPT_READONLY );\n  cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n                     \"[none]\" );\n\nReading multiple certificates, for example via a CGI interface on the server,\nis done with:\n\n  cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n                   \"http://www.server.com/certstore.cgi\",\n                   CRYPT_KEYOPT_READONLY );\n  cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n                     \"user1\" );\n  cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n                     \"user2\" );\n  cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n                     \"user3\" );\n\nChanges in 3.0 final beta\n=========================\n\nThe cryptlib 3.0 final release divides the network timeout parameter into two\nparts, a CRYPT_OPTION_NET_CONNECTTIMEOUT which is applied during the\nconnection setup process and a CRYPT_OPTION_NET_TIMEOUT which is applied\nduring reads and writes (although in practice writes are almost always\ninstantaneous).  This means that it's now possible to avoid nonblocking I/O if\nrequired.\n\nUse of SSL/TLS client certificates is now enabled.\n\nThe final version of the S/MIME PasswordRecipientInfo (PWRI) RFC contained a\nchange in the way the key wrap algorithm is identified.  The cryptlib final\nrelease produces a PWRI that follows the final RFC, but will also read the\nolder format produced by earlier versions of cryptlib.  If it's necessary to\ngenerate PWRI data in the old format, you can change the \"#if 1\" in\nkeymgmt/asn1objs.c to \"#if 0\" to produce the older format.\n\nSupport for extended CMP user configurability via PKIUser objects has been\nadded, this allows user details to be pre-configured at the CA rather than\nrequiring the user to know them.\n\nChanges in 3.0 beta 6\n=====================\n\nBeta 6 reduces the plethora of key generation functions by allowing the\nkeysize to be specified in the more standard way of setting the corresponding\nattribute rather than having extraneous ...Ex() versions of the function that\nparallel the standard form.  If you were previously using the standard or\nasynchronous ...Ex() functions:\n\n\tcryptGenerateKeyEx( cryptContext, keySize );\n\nyou can change to the newer form with a simple cut and paste:\n\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, keySize );\n\tcryptGenerateKey( cryptContext );\n\nThe table format for certificate stores has changed slightly to accommodate the\nrequirements of CMP servers (specifically the fact that they can cause things\nto fail at inopportune moments), in order to handle this you need to recreate\nthe cert store (drop the previous table and create a new one with\nCRYPT_KEYOPT_CREATE), if you need to move information across then create a new\ntable and insert into <newTable> select * from <oldTable> to copy the existing\ncertificates across.  The newly-created table will support the storing of\nextra information needed to handle restarts during CMP operations.\n\nSupport for the proposed AES algorithm is now included.  Since this hasn't\nbeen finalised by NIST yet, it is strongly recommended that you not use it\nuntil the AES FIPS has been published.  cryptlib will implement the form\npresented in the final FIPS, which may be incompatible with the current\nversion.\n\nSSL and TLS support (both client and server) is now enabled, thanks to\nendergone Zwiebeltuete for his help in getting this going.\n\nChanges in 3.0 beta 5\n=====================\n\nBeta 5 removes the configuration options CRYPT_OPTION_FIXSTRINGS and\nCRYPT_OPTION_CHECKENCODING since they shouldn't be needed any more as the\nASN.1 code has been modified to handle all but the most broken certificates\nout there.\n\nUnder Unix the library is now called libcl rather than libcrypt to reduce\nproblems with naming conflicts on some systems.\n\nSupport for the creation of one-step certificates that automatically work for\nany purpose has been added and is enabled by setting the certificate's\nCRYPT_CERTINFO_XYZZY attribute, more details are given in the manual.\n\nOCSP, TSP, and SSH server support is now enabled (this complements the OCSP,\nTSP, and SSH client support added in beta 3 and beta 4).\n\nChanges in 3.0 beta 4\n=====================\n\nBeta 4 removes the need to use the TCP4U library for the network interface and\nshould now have networking enabled automatically on Unix and Windows systems.\nWith the enhanced networking support comes support for SSH secure sessions and\nCMP (Certificate Mismanagement Protocol).\n\nThe creation of arbitrary-format DN's containing any sort of component in any\norder or combination is now supported via the CRYPT_CERTINFO_DN attribute.\n\nChanges in 3.0 beta 3\n=====================\n\nBeta 3 required one unfortunate change to the object creation functions which\ninvolves the addition of a parameter that specifies the user who is to own the\nobject.  For cryptlib 3.0 this means that as the second parameter for the\nobject creation functions (cryptCreateContext, cryptKeysetOpen,\ncryptCreateEnvelope, etc etc) you should specify CRYPT_UNUSED for forwards\ncompatibility with cryptlib 3.1 and later releases.  The user parameter has\nexisted since the first 3.0 releases but until now has been hidden beneath the\ncryptlib API, unfortunately it's necessary to un-hide this parameter, which is\nrequired by certain 3.1 features such as the CA management functionality.\n\nThe use of multiple certificates with the same DN/email address but different\nkey usage types is now supported (previous versions treated the appearance of\nmultiple certificates issued to the same person as a duplicate cert problem,\neither interpretation is valid but popular opinion seems to be that the beta 3\nbehaviour is better).  In order to support this in public key keysets you need\nto recreate them (drop the previous table and create a new one with\nCRYPT_KEYOPT_CREATE), if you need to move certificates across then create a\nnew table and insert into <newTable> select * from <oldTable> to copy the\nexisting certificates across.  The newly-created table will support the\nstoring of multiple identical certificates.\n\nIn order to take advantage of this capability with encrypted enveloping, you\nneed to add the recipient's public key with the CRYPT_ENVINFO_RECIPIENT option\nthat will allow cryptlib to automatically select the most appropriate\ncertificate.  The selection of an appropriate signature checking certificate\nis handled automatically.\n\nHandling of detached signatures with externally-supplied hash values is now\nsupported, see the manual for details.  This allows signature checking for\narbitrary data without it having to be hashed via the envelope.\n\nCertificate revocation checking via OCSP is now supported if you can manage to\nfind an OCSP responder anywhere.  Timestamping of signatures is also\nsupported, although you'll have even less chance of locating a TSA than an\nOCSP responder.\n\nSupport for mSQL has been dropped since MySQL is now GPL'd and provides far\nmore functionality than mSQL (even cryptlib 2.x was pushing the limits of\nmSQL, with cryptlib 3.x it's not really sufficient any more).\n\nChanges in 3.0 beta 2\n=====================\n\nBeta 2 has three minor API changes over beta 1 that are intended to clarify\nareas that have caused problems for users in the past.\n\nThe first change is that the third, usually unnecessary, parameter for\ncryptCreateContext() has been eliminated:\n\n  cryptCreateContext( &cryptContext, cryptAlgo );\n\nOnly the conventional-encryption algorithms required the encryption mode\nparameter, the default is CBC but if another value is required you can specify\nit using the CRYPT_CTXINFO_MODE attribute:\n\n  cryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE, cryptMode );\n\nThis attribute isn't required for anything except conventional encryption\nalgorithms, and even then it's only required for the use of encryption modes\nother than the default mode of CBC.  This change simplifies the creation of\ncontexts, since there's no longer any need to juggle CRYPT_USE_DEFAULT,\nCRYPT_MODE_PKC, CRYPT_MODE_NONE, or any of the other special cases that were\nused for algorithms that don't have different encryption modes.\n\nThe second change (which probably won't affect most users since it's rather\nobscure) is that previously when loading raw public keys with the\nCRYPT_PKCINFO_RSA or CRYPT_PKCINFO_DLP structure the attribute used was\nCRYPT_CTXINFO_KEY and the length was given as CRYPT_UNUSED.  This required a\nnumber of special-case checks in the code and made error-checking of user-\nsupplied data impossible because it wasn't possible to determine how much data\nwas being passed in.\n\nIn beta 2 this attribute now follows the pattern for every other attribute in\nthat it's necessary to give the structure size (i.e. sizeof(\nCRYPT_PKCINFO_xxx)) as the length parameter rather than CRYPT_UNUSED.  In\naddition the attribute for key components is now CRYPT_CTXINFO_KEY_COMPONENTS\nto make explicit the fact that what's being loaded is a composite structure\ncontaining multiple components and not just a single byte string as with\nCRYPT_CTXINFO_KEY.\n\nSimilarly, the length parameter when using cryptEncrypt()/cryptDecrypt() for\npublic-key encryption is now the key/data length in bytes rather than\nCRYPT_UNUSED, following the standard pattern of requiring an actual length\nrather than using magic values.\n\nThe third change is that the functionality of cryptCreateEnvelopeEx() has been\nfolded into cryptCreateEnvelope(), which now takes a second parameter\nspecifying the type of envelope to create\n\n  cryptCreateEnvelope( &cryptEnvelope, formatType );\n\nThe envelope buffer size can optionally be specified with the\nCRYPT_ATTRIBUTE_BUFFERSIZE attribute once the envelope has been created:\n\n  cryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE, size );\n\nalthough this should only be necessary in special cases when enveloping\nlarger-than-usual data quantities.  This change both simplifies the interface\nand makes it easier for cryptlib to efficiently handle resources, since it can\nallocate a small envelope buffer when enveloping begins rather than having to\ncreate a one-size-fits-all one on envelope creation.\n\nIn addition to these changes, beta 2 includes the ability to read the label\nfor the private key which is required for de-enveloping data, so you can use\nthe key name in prompts when asking the user for a password.  You can do this\nwith:\n\n  char label[ CRYPT_MAX_TEXTSIZE + 1 ];\n  int labelLength;\n\n  cryptGetAttributeString( cryptEnvelope, CRYPT_ENVINFO_PRIVATEKEY_LABEL,\n                           label, &labelLength );\n  label[ labelLength ] = '\\0';\n\nSee the manual for more information on this.\n\nChanges in 3.0 beta 1\n=====================\n\ncryptlib 3.0 features a large number of improvements over 2.1, the most\nvisible one being that there is now a unified object model that applies to all\ncryptlib objects, so that the old object-type-specific functions like\ncryptGetCertComponentString() and cryptSetEnvelopeComponentNumeric() have been\nreplaced by cryptSetAttribute(), which works across all object types.  This\nmeans that cryptlib 3.0 has a much simpler interface than 2.1 did (even with\nall the features added in 3.0, the manual is 25 pages shorter than the 2.1\nmanual).\n\nBackwards compatibility with 2.1 is maintained through the use of the 2.1\ninclude file capi.h, which contains macros that map the 3.0 functions and\nattributes back to 2.1 versions.  Three of the more obscure functions don't\ntranslate cleanly, these are documented at the start of capi.h.  If you've got\nexisting 2.1 code then it should work with 3.0 with a recompile.\n\nThis is a beta release of the code, some sections are still subject to change\nbecause the standards they are based on haven't been finalised yet. The most\nobvious one is the PKCS #15 keyset format, when the cryptlib code was frozen\nthe PKCS #15 file format existed only in an informal manner so that some of\nthe data formatting used by cryptlib is speculative and will probably change\nwhen the standard stabilises.  What this means in practice is that you\nshouldn't store any long-term keys in file keysets since the format will have\nto change in the future to track changes in the standard.\n\nTo a lesser extent, the compressed-data and password-protected-data formats\nare based on S/MIME drafts that may also be changed at some point.\n\nFinally, the AS/400, MVS, and VM/CMS versions have somewhat specialised\nrequirements (some of this is covered in the manual), please contact me before\ntrying to do anything with these versions.\n"
  },
  {
    "path": "deps/cl345/Test32.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseOfMfc>false</UseOfMfc>\n    <PlatformToolset>v140</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseOfMfc>false</UseOfMfc>\n    <PlatformToolset>v140</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseOfMfc>false</UseOfMfc>\n    <PlatformToolset>v140</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseOfMfc>false</UseOfMfc>\n    <PlatformToolset>v140</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">.\\binaries32_vs10\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">.\\binaries32_vs10\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</LinkIncremental>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">.\\binaries64_vs10\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">.\\binaries64_vs10\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">false</LinkIncremental>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">.\\binaries32_vs10\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">.\\binaries32_vs10\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</LinkIncremental>\n    <OutDir Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">.\\binaries64_vs10\\</OutDir>\n    <IntDir Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">.\\binaries64_vs10\\</IntDir>\n    <LinkIncremental Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">false</LinkIncremental>\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" />\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" />\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" />\n    <CodeAnalysisRuleSet Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">AllRules.ruleset</CodeAnalysisRuleSet>\n    <CodeAnalysisRules Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" />\n    <CodeAnalysisRuleAssemblies Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" />\n    <TargetName Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">test64</TargetName>\n    <TargetName Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">test64</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\binaries/Test32.tlb</TypeLibraryName>\n      <HeaderFileName>\n      </HeaderFileName>\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>.\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>false</MinimalRebuild>\n      <ExceptionHandling>\n      </ExceptionHandling>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x1409</Culture>\n    </ResourceCompile>\n    <Link>\n      <AdditionalOptions>/FIXED:NO %(AdditionalOptions)</AdditionalOptions>\n      <AdditionalDependencies>wsock32.lib;odbccp32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>.\\binaries32_vs10\\test32.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n      <Profile>true</Profile>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Midl>\n      <TargetEnvironment>X64</TargetEnvironment>\n      <TypeLibraryName>.\\binaries/Test32.tlb</TypeLibraryName>\n      <HeaderFileName>\n      </HeaderFileName>\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>.\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>false</MinimalRebuild>\n      <ExceptionHandling>\n      </ExceptionHandling>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x1409</Culture>\n    </ResourceCompile>\n    <Link>\n      <AdditionalOptions>/FIXED:NO %(AdditionalOptions)</AdditionalOptions>\n      <AdditionalDependencies>wsock32.lib;odbccp32.lib;$(TargetDir)cl64.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(TargetDir)Test64.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX64</TargetMachine>\n      <Profile>true</Profile>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\binaries/Test32.tlb</TypeLibraryName>\n      <HeaderFileName>\n      </HeaderFileName>\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <AdditionalIncludeDirectories>.\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x1409</Culture>\n    </ResourceCompile>\n    <Link>\n      <AdditionalDependencies>wsock32.lib;odbccp32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>.\\binaries32_vs10\\Test32.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <IgnoreSpecificDefaultLibraries>oldnames.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Midl>\n      <TargetEnvironment>X64</TargetEnvironment>\n      <TypeLibraryName>.\\binaries/Test32.tlb</TypeLibraryName>\n      <HeaderFileName>\n      </HeaderFileName>\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <AdditionalIncludeDirectories>.\\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x1409</Culture>\n    </ResourceCompile>\n    <Link>\n      <AdditionalDependencies>wsock32.lib;odbccp32.lib;$(TargetDir)cl64.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(TargetDir)Test64.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX64</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"test\\certimp.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\certproc.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\certs.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\devices.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\envelope.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\highlvl.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\keydbx.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\keyfile.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\loadkey.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\lowlvl.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\s_cmp.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\s_scep.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\sreqresp.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\ssh.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\ssl.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\stress.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\testfunc.c\" />\n    <ClCompile Include=\"test\\testlib.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <ClCompile Include=\"test\\utils.c\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"cryptlib.h\" />\n    <ClInclude Include=\"test\\filename.h\" />\n    <ClInclude Include=\"test\\test.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <CustomBuildStep Include=\"binaries32\\cl32.lib\">\n      <FileType>Document</FileType>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\n    </CustomBuildStep>\n    <CustomBuildStep Include=\"binaries64\\cl64.lib\">\n      <FileType>Document</FileType>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n    </CustomBuildStep>\n  </ItemGroup>\n  <ItemGroup>\n    <Library Include=\"binaries32_vs10\\cl32.lib\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</ExcludedFromBuild>\n    </Library>\n    <Library Include=\"binaries64_vs10\\cl64.lib\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">false</ExcludedFromBuild>\n    </Library>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/cl345/Test32.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{eef00743-11c7-44d1-bb2a-eb715884fe57}</UniqueIdentifier>\n      <Extensions>cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{1fb840ba-c626-408b-a264-9679e2c28e07}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;fi;fd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{72d71195-a477-40b0-8247-e336d504931b}</UniqueIdentifier>\n      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"test\\certimp.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\certproc.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\certs.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\devices.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\envelope.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\highlvl.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\keydbx.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\keyfile.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\loadkey.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\lowlvl.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\s_cmp.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\s_scep.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\sreqresp.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\ssh.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\ssl.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\stress.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\testfunc.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\testlib.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"test\\utils.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"cryptlib.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"test\\filename.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"test\\test.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <Library Include=\"binaries64_vs10\\cl64.lib\" />\n    <Library Include=\"binaries32_vs10\\cl32.lib\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "deps/cl345/bindings/Makefile.PL",
    "content": "use 5.008;\nuse ExtUtils::MakeMaker;\nuse Data::Dumper;\nuse File::Find;\n\nmy @search_in = ( '/usr/local/include', '/usr/lib/gcc-lib', '/usr/include' );\npush @search_in, $ENV{HOME} if defined( $ENV{HOME} );\n\nmy $CRYPT_LIB_HEADER      = 'cryptlib.h';\nmy $PERL_CRYPT_LIB_HEADER = $ENV{PERL_CRYPT_LIB_HEADER};\n\nunless ( defined $PERL_CRYPT_LIB_HEADER ) {\n\tprint \"Looking for '$CRYPT_LIB_HEADER', in:\\n\";\n\tprint \"\\t- $_\\n\" foreach @search_in;\n\tprint \"Please wait... \";\n\tmy @found =\n\t  qx{find @search_in -type f -iname '$CRYPT_LIB_HEADER' 2>/dev/null};\n\tif ( scalar(@found) == 0 ) {\n\t\tprint \"NOT FOUND\",   \"\\n\";\n\t\tprint \"$0 ABORTED!\", \"\\n\";\n\t\tprint \"\\n\";\n\t\tprint\n\"You need CryptLib source code distribution in order to build PerlCryptLib.\",\n\t\t  \"\\n\";\n\t\texit 1;\n\t}\n\tprint \"DONE\",       \"\\n\";\n\tprint \"Found(ed):\", \"\\n\";\n\tmy %found  = ();\n\tmy $recent = 0;\n\tforeach my $h (@found) {\n\t\tchomp $h;\n\t\tprint \"\\t\", $h;\n\t\tmy $v = qx{grep 'CRYPTLIB_VERSION' $h 2>/dev/null};\n\t\t$v =~ m/(\\d+)/;\n\t\t$found{$1} = $h;\n\t\t$recent = int($1) if int($1) gt $recent;\n\t\tprint \"\\t\", \"(Ver. \", $1, \")\";\n\t\tprint \"\\n\";\n\t}\n\n#\tif ( scalar(@found) > 1 ) {\n#\t\tprint \"$0 ABORTED!\", \"\\n\";\n#\t\tprint \"\\n\";\n#\t\tprint \"You have to set environment variable PERL_CRYPT_LIB_HEADER to specify which one of the headers founded is to be used.\", \"\\n\";\n#\t\tprint \"\\n\";\n#\t\tprint \"ie:\", \"\\n\";\n#\t\tprint \"\\n\";\n#\t\tprint \"export PERL_CRYPT_LIB_HEADER='$found[0]'\", \"\\n\";\n#\t\tprint \"\\n\";\n#\t\texit 1;\n#\t}\n#\t$PERL_CRYPT_LIB_HEADER = $found[0];\n\t$PERL_CRYPT_LIB_HEADER = $found{$recent};\n\tprint \"Using version '$recent' from '$found{$recent}'\\n\";\n}\n\nprint \"Writing 'PerlCryptLib.ph', please wait... \";\nprint\n  qx{perl ./GenPerl.pl $PERL_CRYPT_LIB_HEADER ./PerlCryptLib.ph 1>/dev/null};\nif ( $? != 0 ) {\n\tprint \"ERROR $?\", \"\\n\";\n\texit 1;\n}\nprint \"OK\", \"\\n\";\n\nWriteMakefile(\n\t'NAME'         => 'PerlCryptLib',\n\t'DISTNAME'     => 'PerlCryptLib',\n\t'VERSION_FROM' => 'PerlCryptLib.pm',\n\t'PREREQ_PM'    => {},\n\t'PM'           => {\n\t\t'PerlCryptLib.pm' => '$(INST_LIBDIR)/PerlCryptLib.pm',\n\t\t'PerlCryptLib.ph' => '$(INST_LIBDIR)/PerlCryptLib.ph'\n\t},\n\t(\n\t\t$] >= 5.005\n\t\t? (\n\t\t\tABSTRACT =>\n\t\t\t  'PerlCryptLib - Perl interface to Peter Guttman\\'s cryptlib API',\n\t\t\tAUTHOR => 'Alvaro Livraghi <perlcryptlib@gmail.com>'\n\t\t  )\n\t\t: ()\n\t),\n\t,\n\t'LIBS' => [\n\t\tjoin( \" \", map { \"-L$_\" } split \":\", $ENV{LD_LIBRARY_PATH} )\n\t\t  . ' -lresolv -lpthread -lcl'\n\t],\n\t'DEFINE'    => \"-DCRYPTLIB_H=\\\\\\\"$PERL_CRYPT_LIB_HEADER\\\\\\\"\",\n\t'INC'       => '-I.',\n\t'clean'     => { FILE => '*.ph .*_h __debug*' },\n\t'realclean' => { FILES => '*.ph .*_h __debug* *.inc' }\n);\n\nif ( eval { require ExtUtils::Constant; 1 } ) {\n\n\tmy @names = ();\n\tExtUtils::Constant::WriteConstants(\n\t\tNAME         => 'PerlCryptLib',\n\t\tNAMES        => \\@names,\n\t\tDEFAULT_TYPE => 'IV',\n\t\tC_FILE       => 'const-c.inc',\n\t\tXS_FILE      => 'const-xs.inc'\n\t);\n\tprint join( \"\\n\", @names ), \"\\n\";\n\n}\nelse {\n\n\tuse File::Copy;\n\tuse File::Spec;\n\tforeach my $file ( 'const-c.inc', 'const-xs.inc' ) {\n\t\tmy $fallback = File::Spec->catfile( 'fallback', $file );\n\t\tcopy( $fallback, $file ) or die \"Can't copy $fallback to $file: $!\";\n\t}\n\n}\n"
  },
  {
    "path": "deps/cl345/bindings/PerlCryptLib.ph",
    "content": "\n# *****************************************************************************\n# *                                                                           *\n# *                        cryptlib External API Interface                    *\n# *                       Copyright Peter Gutmann 1997-2019                   *\n# *                                                                           *\n# *                 adapted for Perl Version 5.x  by Alvaro Livraghi          *\n# *****************************************************************************\n#\n#\n# ----------------------------------------------------------------------------\n#\n# This file has been created automatically by a perl script from the file:\n#\n# \"cryptlib.h\" dated Thu Dec 27 23:27:20 2018, filesize = 99183.\n#\n# Please check twice that the file matches the version of cryptlib.h\n# in your cryptlib source! If this is not the right version, try to download an\n# update from CPAN web site. If the filesize or file creation date do not match,\n# then please do not complain about problems.\n#\n# Published by Alvaro Livraghi, \n# mailto: perlcryptlib@gmail.com if you find errors in this file.\n#\n# -----------------------------------------------------------------------------\n#\n\n\tsub CRYPTLIB_VERSION { 3441 }\n\n#  Additional defines for compilers that provide extended function and \n#  function-parameter checking \n\n\n\n#****************************************************************************\n#*                                                                           *\n#*                           Algorithm and Object Types                      *\n#*                                                                           *\n#****************************************************************************\n\n# Algorithm and mode types \n\n##### BEGIN ENUM CRYPT_ALGO_TYPE \t# Algorithms\n\t# No encryption\n\t# No encryption\n\tsub CRYPT_ALGO_NONE { 0 }\n\n\t# Conventional encryption\n\t# DES\n\tsub CRYPT_ALGO_DES { 1 }\n\t# Triple DES\n\tsub CRYPT_ALGO_3DES { 2 }\n\t# IDEA (only used for PGP 2.x)\n\tsub CRYPT_ALGO_IDEA { 3 }\n\t# CAST-128 (only used for OpenPGP)\n\tsub CRYPT_ALGO_CAST { 4 }\n\t# RC2 (disabled by default, used for PKCS #12)\n\tsub CRYPT_ALGO_RC2 { 5 }\n\t# RC4 (insecure, deprecated)\n\tsub CRYPT_ALGO_RC4 { 6 }\n\t# Formerly RC5\n\tsub CRYPT_ALGO_RESERVED1 { 7 }\n\t# AES\n\tsub CRYPT_ALGO_AES { 8 }\n\t# Formerly Blowfish\n\tsub CRYPT_ALGO_RESERVED2 { 9 }\n\n\t# Public-key encryption\n\t# Diffie-Hellman\n\tsub CRYPT_ALGO_DH { 100 }\n\t# RSA\n\tsub CRYPT_ALGO_RSA { 101 }\n\t# DSA\n\tsub CRYPT_ALGO_DSA { 102 }\n\t# ElGamal\n\tsub CRYPT_ALGO_ELGAMAL { 103 }\n\t# Formerly KEA\n\tsub CRYPT_ALGO_RESERVED3 { 104 }\n\t# ECDSA\n\tsub CRYPT_ALGO_ECDSA { 105 }\n\t# ECDH\n\tsub CRYPT_ALGO_ECDH { 106 }\n\n\t# Hash algorithms\n\t# Formerly MD2\n\tsub CRYPT_ALGO_RESERVED4 { 200 }\n\t# Formerly MD4\n\tsub CRYPT_ALGO_RESERVED5 { 201 }\n\t# MD5 (only used for TLS 1.0/1.1)\n\tsub CRYPT_ALGO_MD5 { 202 }\n\t# SHA/SHA1\n\tsub CRYPT_ALGO_SHA1 { 203 }\n\t# Formerly RIPE-MD 160\n\tsub CRYPT_ALGO_RESERVED6 { 204 }\n\t# SHA-256\n\tsub CRYPT_ALGO_SHA2 { 205 }\n\t# Alternate name\n\tsub CRYPT_ALGO_SHA256 { 205 }\n\t# Future SHA-nextgen standard\n\tsub CRYPT_ALGO_SHAng { 206 }\n\n\t# MACs\n\t# Formerly HMAC-MD5\n\tsub CRYPT_ALGO_RESREVED_7 { 300 }\n\t# HMAC-SHA\n\tsub CRYPT_ALGO_HMAC_SHA1 { 301 }\n\t# Formerly HMAC-RIPEMD-160\n\tsub CRYPT_ALGO_RESERVED8 { 302 }\n\t# HMAC-SHA2\n\tsub CRYPT_ALGO_HMAC_SHA2 { 303 }\n\t# HMAC-future-SHA-nextgen\n\tsub CRYPT_ALGO_HMAC_SHAng { 304 }\n\n\n\t# Vendors may want to use their own algorithms that aren't part of the\n\t# general cryptlib suite.  The following values are for vendor-defined\n\t# algorithms, and can be used just like the named algorithm types (it's\n\t# up to the vendor to keep track of what _VENDOR1 actually corresponds\n\t# to)\n\n\t# Last possible crypt algo value\n\tsub CRYPT_ALGO_LAST { 305 }\n\n\t# In order that we can scan through a range of algorithms with\n\t# cryptQueryCapability(), we define the following boundary points for\n\t# each algorithm class\n\n\tsub CRYPT_ALGO_FIRST_CONVENTIONAL { 1 }\n\n\tsub CRYPT_ALGO_LAST_CONVENTIONAL { 99 }\n\n\tsub CRYPT_ALGO_FIRST_PKC { 100 }\n\n\tsub CRYPT_ALGO_LAST_PKC { 199 }\n\n\tsub CRYPT_ALGO_FIRST_HASH { 200 }\n\n\tsub CRYPT_ALGO_LAST_HASH { 299 }\n\n\tsub CRYPT_ALGO_FIRST_MAC { 300 }\n\n\tsub CRYPT_ALGO_LAST_MAC { 399 }\n\n\n##### END ENUM CRYPT_ALGO_TYPE\n\n##### BEGIN ENUM CRYPT_MODE_TYPE\n\t# Block cipher modes\n\t# No encryption mode\n\tsub CRYPT_MODE_NONE { 0 }\n\t# ECB\n\tsub CRYPT_MODE_ECB { 1 }\n\t# CBC\n\tsub CRYPT_MODE_CBC { 2 }\n\t# CFB\n\tsub CRYPT_MODE_CFB { 3 }\n\t# GCM\n\tsub CRYPT_MODE_GCM { 4 }\n\t# Last possible crypt mode value\n\tsub CRYPT_MODE_LAST { 5 }\n\n\n##### END ENUM CRYPT_MODE_TYPE\n\n\n# Keyset subtypes \n\n##### BEGIN ENUM CRYPT_KEYSET_TYPE\n\t# Keyset types\n\t# No keyset type\n\tsub CRYPT_KEYSET_NONE { 0 }\n\t# Generic flat file keyset\n\tsub CRYPT_KEYSET_FILE { 1 }\n\t# Web page containing cert/CRL\n\tsub CRYPT_KEYSET_HTTP { 2 }\n\t# LDAP directory service\n\tsub CRYPT_KEYSET_LDAP { 3 }\n\t# Generic ODBC interface\n\tsub CRYPT_KEYSET_ODBC { 4 }\n\t# Generic RDBMS interface\n\tsub CRYPT_KEYSET_DATABASE { 5 }\n\t# ODBC certificate store\n\tsub CRYPT_KEYSET_ODBC_STORE { 6 }\n\t# Database certificate store\n\tsub CRYPT_KEYSET_DATABASE_STORE { 7 }\n\t# Last possible keyset type\n\tsub CRYPT_KEYSET_LAST { 8 }\n\n\n\n##### END ENUM CRYPT_KEYSET_TYPE\n\n# Device subtypes \n\n##### BEGIN ENUM CRYPT_DEVICE_TYPE\n\t# Crypto device types\n\t# No crypto device\n\tsub CRYPT_DEVICE_NONE { 0 }\n\t# Fortezza card - Placeholder only\n\tsub CRYPT_DEVICE_FORTEZZA { 1 }\n\t# PKCS #11 crypto token\n\tsub CRYPT_DEVICE_PKCS11 { 2 }\n\t# Microsoft CryptoAPI\n\tsub CRYPT_DEVICE_CRYPTOAPI { 3 }\n\t# Generic crypo HW plugin\n\tsub CRYPT_DEVICE_HARDWARE { 4 }\n\t# Last possible crypto device type\n\tsub CRYPT_DEVICE_LAST { 5 }\n\n\n##### END ENUM CRYPT_DEVICE_TYPE\n\n# Certificate subtypes \n\n##### BEGIN ENUM CRYPT_CERTTYPE_TYPE\n\t# Certificate object types\n\t# No certificate type\n\tsub CRYPT_CERTTYPE_NONE { 0 }\n\t# Certificate\n\tsub CRYPT_CERTTYPE_CERTIFICATE { 1 }\n\t# Attribute certificate\n\tsub CRYPT_CERTTYPE_ATTRIBUTE_CERT { 2 }\n\t# PKCS #7 certificate chain\n\tsub CRYPT_CERTTYPE_CERTCHAIN { 3 }\n\t# PKCS #10 certification request\n\tsub CRYPT_CERTTYPE_CERTREQUEST { 4 }\n\t# CRMF certification request\n\tsub CRYPT_CERTTYPE_REQUEST_CERT { 5 }\n\t# CRMF revocation request\n\tsub CRYPT_CERTTYPE_REQUEST_REVOCATION { 6 }\n\t# CRL\n\tsub CRYPT_CERTTYPE_CRL { 7 }\n\t# CMS attributes\n\tsub CRYPT_CERTTYPE_CMS_ATTRIBUTES { 8 }\n\t# RTCS request\n\tsub CRYPT_CERTTYPE_RTCS_REQUEST { 9 }\n\t# RTCS response\n\tsub CRYPT_CERTTYPE_RTCS_RESPONSE { 10 }\n\t# OCSP request\n\tsub CRYPT_CERTTYPE_OCSP_REQUEST { 11 }\n\t# OCSP response\n\tsub CRYPT_CERTTYPE_OCSP_RESPONSE { 12 }\n\t# PKI user information\n\tsub CRYPT_CERTTYPE_PKIUSER { 13 }\n\t# Last possible cert.type\n\tsub CRYPT_CERTTYPE_LAST { 14 }\n\n\n##### END ENUM CRYPT_CERTTYPE_TYPE\n\n# Envelope/data format subtypes \n\n##### BEGIN ENUM CRYPT_FORMAT_TYPE\n\n\t# No format type\n\tsub CRYPT_FORMAT_NONE { 0 }\n\t# Deenv, auto-determine type\n\tsub CRYPT_FORMAT_AUTO { 1 }\n\t# cryptlib native format\n\tsub CRYPT_FORMAT_CRYPTLIB { 2 }\n\t# PKCS #7 / CMS / S/MIME fmt.\n\tsub CRYPT_FORMAT_CMS { 3 }\n\n\tsub CRYPT_FORMAT_PKCS7 { 3 }\n\t# As CMS with MSG-style behaviour\n\tsub CRYPT_FORMAT_SMIME { 4 }\n\t# PGP format\n\tsub CRYPT_FORMAT_PGP { 5 }\n\t# Last possible format type\n\tsub CRYPT_FORMAT_LAST { 6 }\n\n\n##### END ENUM CRYPT_FORMAT_TYPE\n\n# Session subtypes \n\n##### BEGIN ENUM CRYPT_SESSION_TYPE\n\n\t# No session type\n\tsub CRYPT_SESSION_NONE { 0 }\n\t# SSH\n\tsub CRYPT_SESSION_SSH { 1 }\n\t# SSH server\n\tsub CRYPT_SESSION_SSH_SERVER { 2 }\n\t# SSL/TLS\n\tsub CRYPT_SESSION_SSL { 3 }\n\n\tsub CRYPT_SESSION_TLS { 3 }\n\t# SSL/TLS server\n\tsub CRYPT_SESSION_SSL_SERVER { 4 }\n\n\tsub CRYPT_SESSION_TLS_SERVER { 4 }\n\t# RTCS\n\tsub CRYPT_SESSION_RTCS { 5 }\n\t# RTCS server\n\tsub CRYPT_SESSION_RTCS_SERVER { 6 }\n\t# OCSP\n\tsub CRYPT_SESSION_OCSP { 7 }\n\t# OCSP server\n\tsub CRYPT_SESSION_OCSP_SERVER { 8 }\n\t# TSP\n\tsub CRYPT_SESSION_TSP { 9 }\n\t# TSP server\n\tsub CRYPT_SESSION_TSP_SERVER { 10 }\n\t# CMP\n\tsub CRYPT_SESSION_CMP { 11 }\n\t# CMP server\n\tsub CRYPT_SESSION_CMP_SERVER { 12 }\n\t# SCEP\n\tsub CRYPT_SESSION_SCEP { 13 }\n\t# SCEP server\n\tsub CRYPT_SESSION_SCEP_SERVER { 14 }\n\t# HTTP cert store interface\n\tsub CRYPT_SESSION_CERTSTORE_SERVER { 15 }\n\t# Last possible session type\n\tsub CRYPT_SESSION_LAST { 16 }\n\n\n##### END ENUM CRYPT_SESSION_TYPE\n\n# User subtypes \n\n##### BEGIN ENUM CRYPT_USER_TYPE\n\n\t# No user type\n\tsub CRYPT_USER_NONE { 0 }\n\t# Normal user\n\tsub CRYPT_USER_NORMAL { 1 }\n\t# Security officer\n\tsub CRYPT_USER_SO { 2 }\n\t# CA user\n\tsub CRYPT_USER_CA { 3 }\n\t# Last possible user type\n\tsub CRYPT_USER_LAST { 4 }\n\n\n##### END ENUM CRYPT_USER_TYPE\n\n#****************************************************************************\n#*                                                                           *\n#*                               Attribute Types                             *\n#*                                                                           *\n#****************************************************************************\n\n#  Attribute types.  These are arranged in the following order:\n#\n#   PROPERTY    - Object property\n#   ATTRIBUTE   - Generic attributes\n#   OPTION      - Global or object-specific config.option\n#   CTXINFO     - Context-specific attribute\n#   CERTINFO    - Certificate-specific attribute\n#   KEYINFO     - Keyset-specific attribute\n#   DEVINFO     - Device-specific attribute\n#   ENVINFO     - Envelope-specific attribute\n#   SESSINFO    - Session-specific attribute\n#   USERINFO    - User-specific attribute \n\n##### BEGIN ENUM CRYPT_ATTRIBUTE_TYPE \n\t# Non-value\n\tsub CRYPT_ATTRIBUTE_NONE { 0 }\n\n\t# Used internally\n\n\tsub CRYPT_PROPERTY_FIRST { 1 }\n\n\t# *******************\n\t# Object attributes\n\t# *******************\n\n\t# Object properties\n\t# Owned+non-forwardcount+locked\n\tsub CRYPT_PROPERTY_HIGHSECURITY { 2 }\n\t# Object owner\n\tsub CRYPT_PROPERTY_OWNER { 3 }\n\t# No.of times object can be forwarded\n\tsub CRYPT_PROPERTY_FORWARDCOUNT { 4 }\n\t# Whether properties can be chged/read\n\tsub CRYPT_PROPERTY_LOCKED { 5 }\n\t# Usage count before object expires\n\tsub CRYPT_PROPERTY_USAGECOUNT { 6 }\n\t# Whether key is nonexp.from context\n\tsub CRYPT_PROPERTY_NONEXPORTABLE { 7 }\n\n\t# Used internally\n\n\tsub CRYPT_PROPERTY_LAST { 8 }\n\tsub CRYPT_GENERIC_FIRST { 9 }\n\n\t# Extended error information\n\t# Type of last error\n\tsub CRYPT_ATTRIBUTE_ERRORTYPE { 10 }\n\t# Locus of last error\n\tsub CRYPT_ATTRIBUTE_ERRORLOCUS { 11 }\n\t# Detailed error description\n\tsub CRYPT_ATTRIBUTE_ERRORMESSAGE { 12 }\n\n\t# Generic information\n\t# Cursor mgt: Group in attribute list\n\tsub CRYPT_ATTRIBUTE_CURRENT_GROUP { 13 }\n\t# Cursor mgt: Entry in attribute list\n\tsub CRYPT_ATTRIBUTE_CURRENT { 14 }\n\t# Cursor mgt: Instance in attribute list\n\tsub CRYPT_ATTRIBUTE_CURRENT_INSTANCE { 15 }\n\t# Internal data buffer size\n\tsub CRYPT_ATTRIBUTE_BUFFERSIZE { 16 }\n\n\t# Used internally\n\n\tsub CRYPT_GENERIC_LAST { 17 }\n\tsub CRYPT_OPTION_FIRST { 100 }\n\n\t# **************************\n\t# Configuration attributes\n\t# **************************\n\n\t# cryptlib information (read-only)\n\t# Text description\n\tsub CRYPT_OPTION_INFO_DESCRIPTION { 101 }\n\t# Copyright notice\n\tsub CRYPT_OPTION_INFO_COPYRIGHT { 102 }\n\t# Major release version\n\tsub CRYPT_OPTION_INFO_MAJORVERSION { 103 }\n\t# Minor release version\n\tsub CRYPT_OPTION_INFO_MINORVERSION { 104 }\n\t# Release stepping\n\tsub CRYPT_OPTION_INFO_STEPPING { 105 }\n\n\t# Encryption options\n\t# Conventional ncryption algorithm\n\tsub CRYPT_OPTION_ENCR_ALGO { 106 }\n\t# Hash algorithm\n\tsub CRYPT_OPTION_ENCR_HASH { 107 }\n\t# MAC algorithm\n\tsub CRYPT_OPTION_ENCR_MAC { 108 }\n\n\t# PKC options\n\t# PKC algorithm\n\tsub CRYPT_OPTION_PKC_ALGO { 109 }\n\t# PKC key size\n\tsub CRYPT_OPTION_PKC_KEYSIZE { 110 }\n\n\t# Placeholder for obsolete options\n\n\tsub CRYPT_OPTION_DUMMY1 { 111 }\n\n\tsub CRYPT_OPTION_DUMMY2 { 112 }\n\n\t# Keying options\n\t# Key processing algorithm\n\tsub CRYPT_OPTION_KEYING_ALGO { 113 }\n\t# Key processing iterations\n\tsub CRYPT_OPTION_KEYING_ITERATIONS { 114 }\n\n\t# Certificate options\n\t# Whether to sign unrecog.attrs\n\tsub CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES { 115 }\n\t# Certificate validity period\n\tsub CRYPT_OPTION_CERT_VALIDITY { 116 }\n\t# CRL update interval\n\tsub CRYPT_OPTION_CERT_UPDATEINTERVAL { 117 }\n\t# PKIX compliance level for cert chks.\n\tsub CRYPT_OPTION_CERT_COMPLIANCELEVEL { 118 }\n\t# Whether explicit policy req'd for certs\n\tsub CRYPT_OPTION_CERT_REQUIREPOLICY { 119 }\n\n\t# CMS/SMIME options\n\t# Add default CMS attributes\n\tsub CRYPT_OPTION_CMS_DEFAULTATTRIBUTES { 120 }\n\n\tsub CRYPT_OPTION_SMIME_DEFAULTATTRIBUTES { 120 }\n\n\t# LDAP keyset options\n\t# Object class\n\tsub CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS { 121 }\n\t# Object type to fetch\n\tsub CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE { 122 }\n\t# Query filter\n\tsub CRYPT_OPTION_KEYS_LDAP_FILTER { 123 }\n\t# CA certificate attribute name\n\tsub CRYPT_OPTION_KEYS_LDAP_CACERTNAME { 124 }\n\t# Certificate attribute name\n\tsub CRYPT_OPTION_KEYS_LDAP_CERTNAME { 125 }\n\t# CRL attribute name\n\tsub CRYPT_OPTION_KEYS_LDAP_CRLNAME { 126 }\n\t# Email attribute name\n\tsub CRYPT_OPTION_KEYS_LDAP_EMAILNAME { 127 }\n\n\t# Crypto device options\n\t# Name of first PKCS #11 driver\n\tsub CRYPT_OPTION_DEVICE_PKCS11_DVR01 { 128 }\n\t# Name of second PKCS #11 driver\n\tsub CRYPT_OPTION_DEVICE_PKCS11_DVR02 { 129 }\n\t# Name of third PKCS #11 driver\n\tsub CRYPT_OPTION_DEVICE_PKCS11_DVR03 { 130 }\n\t# Name of fourth PKCS #11 driver\n\tsub CRYPT_OPTION_DEVICE_PKCS11_DVR04 { 131 }\n\t# Name of fifth PKCS #11 driver\n\tsub CRYPT_OPTION_DEVICE_PKCS11_DVR05 { 132 }\n\t# Use only hardware mechanisms\n\tsub CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY { 133 }\n\n\t# Network access options\n\t# Socks server name\n\tsub CRYPT_OPTION_NET_SOCKS_SERVER { 134 }\n\t# Socks user name\n\tsub CRYPT_OPTION_NET_SOCKS_USERNAME { 135 }\n\t# Web proxy server\n\tsub CRYPT_OPTION_NET_HTTP_PROXY { 136 }\n\t# Timeout for network connection setup\n\tsub CRYPT_OPTION_NET_CONNECTTIMEOUT { 137 }\n\t# Timeout for network reads\n\tsub CRYPT_OPTION_NET_READTIMEOUT { 138 }\n\t# Timeout for network writes\n\tsub CRYPT_OPTION_NET_WRITETIMEOUT { 139 }\n\n\t# Miscellaneous options\n\t# Whether to init cryptlib async'ly\n\tsub CRYPT_OPTION_MISC_ASYNCINIT { 140 }\n\t# Protect against side-channel attacks\n\tsub CRYPT_OPTION_MISC_SIDECHANNELPROTECTION { 141 }\n\n\t# cryptlib state information\n\t# Whether in-mem.opts match on-disk ones\n\tsub CRYPT_OPTION_CONFIGCHANGED { 142 }\n\t# Whether self-test was completed and OK\n\tsub CRYPT_OPTION_SELFTESTOK { 143 }\n\n\t# Used internally\n\n\tsub CRYPT_OPTION_LAST { 144 }\n\tsub CRYPT_CTXINFO_FIRST { 1000 }\n\n\t# ********************\n\t# Context attributes\n\t# ********************\n\n\t# Algorithm and mode information\n\t# Algorithm\n\tsub CRYPT_CTXINFO_ALGO { 1001 }\n\t# Mode\n\tsub CRYPT_CTXINFO_MODE { 1002 }\n\t# Algorithm name\n\tsub CRYPT_CTXINFO_NAME_ALGO { 1003 }\n\t# Mode name\n\tsub CRYPT_CTXINFO_NAME_MODE { 1004 }\n\t# Key size in bytes\n\tsub CRYPT_CTXINFO_KEYSIZE { 1005 }\n\t# Block size\n\tsub CRYPT_CTXINFO_BLOCKSIZE { 1006 }\n\t# IV size\n\tsub CRYPT_CTXINFO_IVSIZE { 1007 }\n\t# Key processing algorithm\n\tsub CRYPT_CTXINFO_KEYING_ALGO { 1008 }\n\t# Key processing iterations\n\tsub CRYPT_CTXINFO_KEYING_ITERATIONS { 1009 }\n\t# Key processing salt\n\tsub CRYPT_CTXINFO_KEYING_SALT { 1010 }\n\t# Value used to derive key\n\tsub CRYPT_CTXINFO_KEYING_VALUE { 1011 }\n\n\t# State information\n\t# Key\n\tsub CRYPT_CTXINFO_KEY { 1012 }\n\t# Public-key components\n\tsub CRYPT_CTXINFO_KEY_COMPONENTS { 1013 }\n\t# IV\n\tsub CRYPT_CTXINFO_IV { 1014 }\n\t# Hash value\n\tsub CRYPT_CTXINFO_HASHVALUE { 1015 }\n\n\t# Misc.information\n\t# Label for private/secret key\n\tsub CRYPT_CTXINFO_LABEL { 1016 }\n\t# Obj.is backed by device or keyset\n\tsub CRYPT_CTXINFO_PERSISTENT { 1017 }\n\n\t# Used internally\n\n\tsub CRYPT_CTXINFO_LAST { 1018 }\n\tsub CRYPT_CERTINFO_FIRST { 2000 }\n\n\t# ************************\n\t# Certificate attributes\n\t# ************************\n\n\t# Because there are so many cert attributes, we break them down into\n\t# blocks to minimise the number of values that change if a new one is\n\t# added halfway through\n\n\t# Pseudo-information on a cert object or meta-information which is used\n\t# to control the way that a cert object is processed\n\t# Cert is self-signed\n\tsub CRYPT_CERTINFO_SELFSIGNED { 2001 }\n\t# Cert is signed and immutable\n\tsub CRYPT_CERTINFO_IMMUTABLE { 2002 }\n\t# Cert is a magic just-works cert\n\tsub CRYPT_CERTINFO_XYZZY { 2003 }\n\t# Certificate object type\n\tsub CRYPT_CERTINFO_CERTTYPE { 2004 }\n\t# Certificate fingerprints\n\tsub CRYPT_CERTINFO_FINGERPRINT_SHA1 { 2005 }\n\n\tsub CRYPT_CERTINFO_FINGERPRINT_SHA2 { 2006 }\n\n\tsub CRYPT_CERTINFO_FINGERPRINT_SHAng { 2007 }\n\t# Cursor mgt: Rel.pos in chain/CRL/OCSP\n\tsub CRYPT_CERTINFO_CURRENT_CERTIFICATE { 2008 }\n\t# Usage that cert is trusted for\n\tsub CRYPT_CERTINFO_TRUSTED_USAGE { 2009 }\n\t# Whether cert is implicitly trusted\n\tsub CRYPT_CERTINFO_TRUSTED_IMPLICIT { 2010 }\n\t# Amount of detail to include in sigs.\n\tsub CRYPT_CERTINFO_SIGNATURELEVEL { 2011 }\n\n\t# General certificate object information\n\t# Cert.format version\n\tsub CRYPT_CERTINFO_VERSION { 2012 }\n\t# Serial number\n\tsub CRYPT_CERTINFO_SERIALNUMBER { 2013 }\n\t# Public key\n\tsub CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO { 2014 }\n\t# User certificate\n\tsub CRYPT_CERTINFO_CERTIFICATE { 2015 }\n\n\tsub CRYPT_CERTINFO_USERCERTIFICATE { 2015 }\n\t# CA certificate\n\tsub CRYPT_CERTINFO_CACERTIFICATE { 2016 }\n\t# Issuer DN\n\tsub CRYPT_CERTINFO_ISSUERNAME { 2017 }\n\t# Cert valid-from time\n\tsub CRYPT_CERTINFO_VALIDFROM { 2018 }\n\t# Cert valid-to time\n\tsub CRYPT_CERTINFO_VALIDTO { 2019 }\n\t# Subject DN\n\tsub CRYPT_CERTINFO_SUBJECTNAME { 2020 }\n\t# Issuer unique ID\n\tsub CRYPT_CERTINFO_ISSUERUNIQUEID { 2021 }\n\t# Subject unique ID\n\tsub CRYPT_CERTINFO_SUBJECTUNIQUEID { 2022 }\n\t# Cert.request (DN + public key)\n\tsub CRYPT_CERTINFO_CERTREQUEST { 2023 }\n\t# CRL/OCSP current-update time\n\tsub CRYPT_CERTINFO_THISUPDATE { 2024 }\n\t# CRL/OCSP next-update time\n\tsub CRYPT_CERTINFO_NEXTUPDATE { 2025 }\n\t# CRL/OCSP cert-revocation time\n\tsub CRYPT_CERTINFO_REVOCATIONDATE { 2026 }\n\t# OCSP revocation status\n\tsub CRYPT_CERTINFO_REVOCATIONSTATUS { 2027 }\n\t# RTCS certificate status\n\tsub CRYPT_CERTINFO_CERTSTATUS { 2028 }\n\t# Currently selected DN in string form\n\tsub CRYPT_CERTINFO_DN { 2029 }\n\t# PKI user ID\n\tsub CRYPT_CERTINFO_PKIUSER_ID { 2030 }\n\t# PKI user issue password\n\tsub CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD { 2031 }\n\t# PKI user revocation password\n\tsub CRYPT_CERTINFO_PKIUSER_REVPASSWORD { 2032 }\n\t# PKI user is an RA\n\tsub CRYPT_CERTINFO_PKIUSER_RA { 2033 }\n\n\t# X.520 Distinguished Name components.  This is a composite field, the\n\t# DN to be manipulated is selected through the addition of a\n\t# pseudocomponent, and then one of the following is used to access the\n\t# DN components directly\n\t# countryName\n\tsub CRYPT_CERTINFO_COUNTRYNAME { 2100 }\n\t# stateOrProvinceName\n\tsub CRYPT_CERTINFO_STATEORPROVINCENAME { 2101 }\n\t# localityName\n\tsub CRYPT_CERTINFO_LOCALITYNAME { 2102 }\n\t# organizationName\n\tsub CRYPT_CERTINFO_ORGANIZATIONNAME { 2103 }\n\n\tsub CRYPT_CERTINFO_ORGANISATIONNAME { 2103 }\n\t# organizationalUnitName\n\tsub CRYPT_CERTINFO_ORGANIZATIONALUNITNAME { 2104 }\n\n\tsub CRYPT_CERTINFO_ORGANISATIONALUNITNAME { 2104 }\n\t# commonName\n\tsub CRYPT_CERTINFO_COMMONNAME { 2105 }\n\n\t# X.509 General Name components.  These are handled in the same way as\n\t# the DN composite field, with the current GeneralName being selected by\n\t# a pseudo-component after which the individual components can be\n\t# modified through one of the following\n\t# otherName.typeID\n\tsub CRYPT_CERTINFO_OTHERNAME_TYPEID { 2106 }\n\t# otherName.value\n\tsub CRYPT_CERTINFO_OTHERNAME_VALUE { 2107 }\n\t# rfc822Name\n\tsub CRYPT_CERTINFO_RFC822NAME { 2108 }\n\n\tsub CRYPT_CERTINFO_EMAIL { 2108 }\n\t# dNSName\n\tsub CRYPT_CERTINFO_DNSNAME { 2109 }\n\t# directoryName\n\tsub CRYPT_CERTINFO_DIRECTORYNAME { 2110 }\n\t# ediPartyName.nameAssigner\n\tsub CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER { 2111 }\n\t# ediPartyName.partyName\n\tsub CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME { 2112 }\n\t# uniformResourceIdentifier\n\tsub CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER { 2113 }\n\n\tsub CRYPT_CERTINFO_URL { 2113 }\n\t# iPAddress\n\tsub CRYPT_CERTINFO_IPADDRESS { 2114 }\n\t# registeredID\n\tsub CRYPT_CERTINFO_REGISTEREDID { 2115 }\n\n\t# X.509 certificate extensions.  Although it would be nicer to use names\n\t# that match the extensions more closely (e.g.\n\t# CRYPT_CERTINFO_BASICCONSTRAINTS_PATHLENCONSTRAINT), these exceed the\n\t# 32-character ANSI minimum length for unique names, and get really\n\t# hairy once you get into the weird policy constraints extensions whose\n\t# names wrap around the screen about three times.\n\n\t# The following values are defined in OID order, this isn't absolutely\n\t# necessary but saves an extra layer of processing when encoding them\n\n\t# 1 2 840 113549 1 9 7 challengePassword.  This is here even though it's\n\t# a CMS attribute because SCEP stuffs it into PKCS #10 requests\n\n\tsub CRYPT_CERTINFO_CHALLENGEPASSWORD { 2200 }\n\n\t# 1 3 6 1 4 1 3029 3 1 4 cRLExtReason\n\n\tsub CRYPT_CERTINFO_CRLEXTREASON { 2201 }\n\n\t# 1 3 6 1 4 1 3029 3 1 5 keyFeatures\n\n\tsub CRYPT_CERTINFO_KEYFEATURES { 2202 }\n\n\t# 1 3 6 1 5 5 7 1 1 authorityInfoAccess\n\n\tsub CRYPT_CERTINFO_AUTHORITYINFOACCESS { 2203 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_AUTHORITYINFO_RTCS { 2204 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_AUTHORITYINFO_OCSP { 2205 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS { 2206 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE { 2207 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_AUTHORITYINFO_CRLS { 2208 }\n\n\t# 1 3 6 1 5 5 7 1 2 biometricInfo\n\n\tsub CRYPT_CERTINFO_BIOMETRICINFO { 2209 }\n\t# biometricData.typeOfData\n\tsub CRYPT_CERTINFO_BIOMETRICINFO_TYPE { 2210 }\n\t# biometricData.hashAlgorithm\n\tsub CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO { 2211 }\n\t# biometricData.dataHash\n\tsub CRYPT_CERTINFO_BIOMETRICINFO_HASH { 2212 }\n\t# biometricData.sourceDataUri\n\tsub CRYPT_CERTINFO_BIOMETRICINFO_URL { 2213 }\n\n\t# 1 3 6 1 5 5 7 1 3 qcStatements\n\n\tsub CRYPT_CERTINFO_QCSTATEMENT { 2214 }\n\n\tsub CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS { 2215 }\n\t# qcStatement.statementInfo.semanticsIdentifier\n\n\tsub CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY { 2216 }\n\t# qcStatement.statementInfo.nameRegistrationAuthorities\n\n\t# 1 3 6 1 5 5 7 1 7 ipAddrBlocks\n\n\tsub CRYPT_CERTINFO_IPADDRESSBLOCKS { 2217 }\n\t# addressFamily\n\tsub CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY { 2218 }\n\t# CRYPT_CERTINFO_IPADDRESSBLOCKS_INHERIT, // ipAddress.inherit\n\t# ipAddress.addressPrefix\n\tsub CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX { 2219 }\n\t# ipAddress.addressRangeMin\n\tsub CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN { 2220 }\n\t# ipAddress.addressRangeMax\n\tsub CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX { 2221 }\n\n\t# 1 3 6 1 5 5 7 1 8 autonomousSysIds\n\n\tsub CRYPT_CERTINFO_AUTONOMOUSSYSIDS { 2222 }\n\t# CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_INHERIT,// asNum.inherit\n\t# asNum.id\n\tsub CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID { 2223 }\n\t# asNum.min\n\tsub CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN { 2224 }\n\t# asNum.max\n\tsub CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX { 2225 }\n\n\t# 1 3 6 1 5 5 7 48 1 2 ocspNonce\n\t# nonce\n\tsub CRYPT_CERTINFO_OCSP_NONCE { 2226 }\n\n\t# 1 3 6 1 5 5 7 48 1 4 ocspAcceptableResponses\n\n\tsub CRYPT_CERTINFO_OCSP_RESPONSE { 2227 }\n\t# OCSP standard response\n\tsub CRYPT_CERTINFO_OCSP_RESPONSE_OCSP { 2228 }\n\n\t# 1 3 6 1 5 5 7 48 1 5 ocspNoCheck\n\n\tsub CRYPT_CERTINFO_OCSP_NOCHECK { 2229 }\n\n\t# 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff\n\n\tsub CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF { 2230 }\n\n\t# 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess\n\n\tsub CRYPT_CERTINFO_SUBJECTINFOACCESS { 2231 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING { 2232 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY { 2233 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY { 2234 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST { 2235 }\n\t# accessDescription.accessLocation\n\tsub CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT { 2236 }\n\n\t# 1 3 36 8 3 1 siggDateOfCertGen\n\n\tsub CRYPT_CERTINFO_SIGG_DATEOFCERTGEN { 2237 }\n\n\t# 1 3 36 8 3 2 siggProcuration\n\n\tsub CRYPT_CERTINFO_SIGG_PROCURATION { 2238 }\n\t# country\n\tsub CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY { 2239 }\n\t# typeOfSubstitution\n\tsub CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION { 2240 }\n\t# signingFor.thirdPerson\n\tsub CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR { 2241 }\n\n\t# 1 3 36 8 3 3 siggAdmissions\n\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS { 2242 }\n\t# authority\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY { 2243 }\n\t# namingAuth.iD\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID { 2244 }\n\t# namingAuth.uRL\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL { 2245 }\n\t# namingAuth.text\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT { 2246 }\n\t# professionItem\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM { 2247 }\n\t# professionOID\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID { 2248 }\n\t# registrationNumber\n\tsub CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER { 2249 }\n\n\t# 1 3 36 8 3 4 siggMonetaryLimit\n\n\tsub CRYPT_CERTINFO_SIGG_MONETARYLIMIT { 2250 }\n\t# currency\n\tsub CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY { 2251 }\n\t# amount\n\tsub CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT { 2252 }\n\t# exponent\n\tsub CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT { 2253 }\n\n\t# 1 3 36 8 3 5 siggDeclarationOfMajority\n\n\tsub CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY { 2254 }\n\t# fullAgeAtCountry\n\tsub CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY { 2255 }\n\n\t# 1 3 36 8 3 8 siggRestriction\n\n\tsub CRYPT_CERTINFO_SIGG_RESTRICTION { 2256 }\n\n\t# 1 3 36 8 3 13 siggCertHash\n\n\tsub CRYPT_CERTINFO_SIGG_CERTHASH { 2257 }\n\n\t# 1 3 36 8 3 15 siggAdditionalInformation\n\n\tsub CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION { 2258 }\n\n\t# 1 3 101 1 4 1 strongExtranet\n\n\tsub CRYPT_CERTINFO_STRONGEXTRANET { 2259 }\n\t# sxNetIDList.sxNetID.zone\n\tsub CRYPT_CERTINFO_STRONGEXTRANET_ZONE { 2260 }\n\t# sxNetIDList.sxNetID.id\n\tsub CRYPT_CERTINFO_STRONGEXTRANET_ID { 2261 }\n\n\t# 2 5 29 9 subjectDirectoryAttributes\n\n\tsub CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES { 2262 }\n\t# attribute.type\n\tsub CRYPT_CERTINFO_SUBJECTDIR_TYPE { 2263 }\n\t# attribute.values\n\tsub CRYPT_CERTINFO_SUBJECTDIR_VALUES { 2264 }\n\n\t# 2 5 29 14 subjectKeyIdentifier\n\n\tsub CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER { 2265 }\n\n\t# 2 5 29 15 keyUsage\n\n\tsub CRYPT_CERTINFO_KEYUSAGE { 2266 }\n\n\t# 2 5 29 16 privateKeyUsagePeriod\n\n\tsub CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD { 2267 }\n\t# notBefore\n\tsub CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE { 2268 }\n\t# notAfter\n\tsub CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER { 2269 }\n\n\t# 2 5 29 17 subjectAltName\n\n\tsub CRYPT_CERTINFO_SUBJECTALTNAME { 2270 }\n\n\t# 2 5 29 18 issuerAltName\n\n\tsub CRYPT_CERTINFO_ISSUERALTNAME { 2271 }\n\n\t# 2 5 29 19 basicConstraints\n\n\tsub CRYPT_CERTINFO_BASICCONSTRAINTS { 2272 }\n\t# cA\n\tsub CRYPT_CERTINFO_CA { 2273 }\n\n\tsub CRYPT_CERTINFO_AUTHORITY { 2273 }\n\t# pathLenConstraint\n\tsub CRYPT_CERTINFO_PATHLENCONSTRAINT { 2274 }\n\n\t# 2 5 29 20 cRLNumber\n\n\tsub CRYPT_CERTINFO_CRLNUMBER { 2275 }\n\n\t# 2 5 29 21 cRLReason\n\n\tsub CRYPT_CERTINFO_CRLREASON { 2276 }\n\n\t# 2 5 29 23 holdInstructionCode\n\n\tsub CRYPT_CERTINFO_HOLDINSTRUCTIONCODE { 2277 }\n\n\t# 2 5 29 24 invalidityDate\n\n\tsub CRYPT_CERTINFO_INVALIDITYDATE { 2278 }\n\n\t# 2 5 29 27 deltaCRLIndicator\n\n\tsub CRYPT_CERTINFO_DELTACRLINDICATOR { 2279 }\n\n\t# 2 5 29 28 issuingDistributionPoint\n\n\tsub CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT { 2280 }\n\t# distributionPointName.fullName\n\tsub CRYPT_CERTINFO_ISSUINGDIST_FULLNAME { 2281 }\n\t# onlyContainsUserCerts\n\tsub CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY { 2282 }\n\t# onlyContainsCACerts\n\tsub CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY { 2283 }\n\t# onlySomeReasons\n\tsub CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY { 2284 }\n\t# indirectCRL\n\tsub CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL { 2285 }\n\n\t# 2 5 29 29 certificateIssuer\n\n\tsub CRYPT_CERTINFO_CERTIFICATEISSUER { 2286 }\n\n\t# 2 5 29 30 nameConstraints\n\n\tsub CRYPT_CERTINFO_NAMECONSTRAINTS { 2287 }\n\t# permittedSubtrees\n\tsub CRYPT_CERTINFO_PERMITTEDSUBTREES { 2288 }\n\t# excludedSubtrees\n\tsub CRYPT_CERTINFO_EXCLUDEDSUBTREES { 2289 }\n\n\t# 2 5 29 31 cRLDistributionPoint\n\n\tsub CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT { 2290 }\n\t# distributionPointName.fullName\n\tsub CRYPT_CERTINFO_CRLDIST_FULLNAME { 2291 }\n\t# reasons\n\tsub CRYPT_CERTINFO_CRLDIST_REASONS { 2292 }\n\t# cRLIssuer\n\tsub CRYPT_CERTINFO_CRLDIST_CRLISSUER { 2293 }\n\n\t# 2 5 29 32 certificatePolicies\n\n\tsub CRYPT_CERTINFO_CERTIFICATEPOLICIES { 2294 }\n\t# policyInformation.policyIdentifier\n\tsub CRYPT_CERTINFO_CERTPOLICYID { 2295 }\n\n\tsub CRYPT_CERTINFO_CERTPOLICY_CPSURI { 2296 }\n\t# policyInformation.policyQualifiers.qualifier.cPSuri\n\n\tsub CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION { 2297 }\n\t# policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization\n\n\tsub CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS { 2298 }\n\t# policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers\n\n\tsub CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT { 2299 }\n\t# policyInformation.policyQualifiers.qualifier.userNotice.explicitText\n\n\t# 2 5 29 33 policyMappings\n\n\tsub CRYPT_CERTINFO_POLICYMAPPINGS { 2300 }\n\t# policyMappings.issuerDomainPolicy\n\tsub CRYPT_CERTINFO_ISSUERDOMAINPOLICY { 2301 }\n\t# policyMappings.subjectDomainPolicy\n\tsub CRYPT_CERTINFO_SUBJECTDOMAINPOLICY { 2302 }\n\n\t# 2 5 29 35 authorityKeyIdentifier\n\n\tsub CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER { 2303 }\n\t# keyIdentifier\n\tsub CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER { 2304 }\n\t# authorityCertIssuer\n\tsub CRYPT_CERTINFO_AUTHORITY_CERTISSUER { 2305 }\n\t# authorityCertSerialNumber\n\tsub CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER { 2306 }\n\n\t# 2 5 29 36 policyConstraints\n\n\tsub CRYPT_CERTINFO_POLICYCONSTRAINTS { 2307 }\n\t# policyConstraints.requireExplicitPolicy\n\tsub CRYPT_CERTINFO_REQUIREEXPLICITPOLICY { 2308 }\n\t# policyConstraints.inhibitPolicyMapping\n\tsub CRYPT_CERTINFO_INHIBITPOLICYMAPPING { 2309 }\n\n\t# 2 5 29 37 extKeyUsage\n\n\tsub CRYPT_CERTINFO_EXTKEYUSAGE { 2310 }\n\t# individualCodeSigning\n\tsub CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING { 2311 }\n\t# commercialCodeSigning\n\tsub CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING { 2312 }\n\t# certTrustListSigning\n\tsub CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING { 2313 }\n\t# timeStampSigning\n\tsub CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING { 2314 }\n\t# serverGatedCrypto\n\tsub CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO { 2315 }\n\t# encrypedFileSystem\n\tsub CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM { 2316 }\n\t# serverAuth\n\tsub CRYPT_CERTINFO_EXTKEY_SERVERAUTH { 2317 }\n\t# clientAuth\n\tsub CRYPT_CERTINFO_EXTKEY_CLIENTAUTH { 2318 }\n\t# codeSigning\n\tsub CRYPT_CERTINFO_EXTKEY_CODESIGNING { 2319 }\n\t# emailProtection\n\tsub CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION { 2320 }\n\t# ipsecEndSystem\n\tsub CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM { 2321 }\n\t# ipsecTunnel\n\tsub CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL { 2322 }\n\t# ipsecUser\n\tsub CRYPT_CERTINFO_EXTKEY_IPSECUSER { 2323 }\n\t# timeStamping\n\tsub CRYPT_CERTINFO_EXTKEY_TIMESTAMPING { 2324 }\n\t# ocspSigning\n\tsub CRYPT_CERTINFO_EXTKEY_OCSPSIGNING { 2325 }\n\t# directoryService\n\tsub CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE { 2326 }\n\t# anyExtendedKeyUsage\n\tsub CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE { 2327 }\n\t# serverGatedCrypto\n\tsub CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO { 2328 }\n\t# serverGatedCrypto CA\n\tsub CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA { 2329 }\n\n\tsub CRYPT_CERTINFO_EXTKEYUSAGE_LAST { 2329 }\n\n\t# 2 5 29 40 crlStreamIdentifier\n\n\tsub CRYPT_CERTINFO_CRLSTREAMIDENTIFIER { 2330 }\n\n\t# 2 5 29 46 freshestCRL\n\n\tsub CRYPT_CERTINFO_FRESHESTCRL { 2331 }\n\t# distributionPointName.fullName\n\tsub CRYPT_CERTINFO_FRESHESTCRL_FULLNAME { 2332 }\n\t# reasons\n\tsub CRYPT_CERTINFO_FRESHESTCRL_REASONS { 2333 }\n\t# cRLIssuer\n\tsub CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER { 2334 }\n\n\t# 2 5 29 47 orderedList\n\n\tsub CRYPT_CERTINFO_ORDEREDLIST { 2335 }\n\n\t# 2 5 29 51 baseUpdateTime\n\n\tsub CRYPT_CERTINFO_BASEUPDATETIME { 2336 }\n\n\t# 2 5 29 53 deltaInfo\n\n\tsub CRYPT_CERTINFO_DELTAINFO { 2337 }\n\t# deltaLocation\n\tsub CRYPT_CERTINFO_DELTAINFO_LOCATION { 2338 }\n\t# nextDelta\n\tsub CRYPT_CERTINFO_DELTAINFO_NEXTDELTA { 2339 }\n\n\t# 2 5 29 54 inhibitAnyPolicy\n\n\tsub CRYPT_CERTINFO_INHIBITANYPOLICY { 2340 }\n\n\t# 2 5 29 58 toBeRevoked\n\n\tsub CRYPT_CERTINFO_TOBEREVOKED { 2341 }\n\t# certificateIssuer\n\tsub CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER { 2342 }\n\t# reasonCode\n\tsub CRYPT_CERTINFO_TOBEREVOKED_REASONCODE { 2343 }\n\t# revocationTime\n\tsub CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME { 2344 }\n\t# certSerialNumber\n\tsub CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER { 2345 }\n\n\t# 2 5 29 59 revokedGroups\n\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS { 2346 }\n\t# certificateIssuer\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER { 2347 }\n\t# reasonCode\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE { 2348 }\n\t# invalidityDate\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE { 2349 }\n\t# startingNumber\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER { 2350 }\n\t# endingNumber\n\tsub CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER { 2351 }\n\n\t# 2 5 29 60 expiredCertsOnCRL\n\n\tsub CRYPT_CERTINFO_EXPIREDCERTSONCRL { 2352 }\n\n\t# 2 5 29 63 aaIssuingDistributionPoint\n\n\tsub CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT { 2353 }\n\t# distributionPointName.fullName\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME { 2354 }\n\t# onlySomeReasons\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY { 2355 }\n\t# indirectCRL\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL { 2356 }\n\t# containsUserAttributeCerts\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS { 2357 }\n\t# containsAACerts\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_AACERTS { 2358 }\n\t# containsSOAPublicKeyCerts\n\tsub CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS { 2359 }\n\n\t# 2 16 840 1 113730 1 x Netscape extensions\n\t# netscape-cert-type\n\tsub CRYPT_CERTINFO_NS_CERTTYPE { 2360 }\n\t# netscape-base-url\n\tsub CRYPT_CERTINFO_NS_BASEURL { 2361 }\n\t# netscape-revocation-url\n\tsub CRYPT_CERTINFO_NS_REVOCATIONURL { 2362 }\n\t# netscape-ca-revocation-url\n\tsub CRYPT_CERTINFO_NS_CAREVOCATIONURL { 2363 }\n\t# netscape-cert-renewal-url\n\tsub CRYPT_CERTINFO_NS_CERTRENEWALURL { 2364 }\n\t# netscape-ca-policy-url\n\tsub CRYPT_CERTINFO_NS_CAPOLICYURL { 2365 }\n\t# netscape-ssl-server-name\n\tsub CRYPT_CERTINFO_NS_SSLSERVERNAME { 2366 }\n\t# netscape-comment\n\tsub CRYPT_CERTINFO_NS_COMMENT { 2367 }\n\n\t# 2 23 42 7 0 SET hashedRootKey\n\n\tsub CRYPT_CERTINFO_SET_HASHEDROOTKEY { 2368 }\n\t# rootKeyThumbPrint\n\tsub CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT { 2369 }\n\n\t# 2 23 42 7 1 SET certificateType\n\n\tsub CRYPT_CERTINFO_SET_CERTIFICATETYPE { 2370 }\n\n\t# 2 23 42 7 2 SET merchantData\n\n\tsub CRYPT_CERTINFO_SET_MERCHANTDATA { 2371 }\n\t# merID\n\tsub CRYPT_CERTINFO_SET_MERID { 2372 }\n\t# merAcquirerBIN\n\tsub CRYPT_CERTINFO_SET_MERACQUIRERBIN { 2373 }\n\t# merNames.language\n\tsub CRYPT_CERTINFO_SET_MERCHANTLANGUAGE { 2374 }\n\t# merNames.name\n\tsub CRYPT_CERTINFO_SET_MERCHANTNAME { 2375 }\n\t# merNames.city\n\tsub CRYPT_CERTINFO_SET_MERCHANTCITY { 2376 }\n\t# merNames.stateProvince\n\tsub CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE { 2377 }\n\t# merNames.postalCode\n\tsub CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE { 2378 }\n\t# merNames.countryName\n\tsub CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME { 2379 }\n\t# merCountry\n\tsub CRYPT_CERTINFO_SET_MERCOUNTRY { 2380 }\n\t# merAuthFlag\n\tsub CRYPT_CERTINFO_SET_MERAUTHFLAG { 2381 }\n\n\t# 2 23 42 7 3 SET certCardRequired\n\n\tsub CRYPT_CERTINFO_SET_CERTCARDREQUIRED { 2382 }\n\n\t# 2 23 42 7 4 SET tunneling\n\n\tsub CRYPT_CERTINFO_SET_TUNNELING { 2383 }\n\n\tsub CRYPT_CERTINFO_SET_TUNNELLING { 2383 }\n\t# tunneling\n\tsub CRYPT_CERTINFO_SET_TUNNELINGFLAG { 2384 }\n\n\tsub CRYPT_CERTINFO_SET_TUNNELLINGFLAG { 2384 }\n\t# tunnelingAlgID\n\tsub CRYPT_CERTINFO_SET_TUNNELINGALGID { 2385 }\n\n\tsub CRYPT_CERTINFO_SET_TUNNELLINGALGID { 2385 }\n\n\t# S/MIME attributes\n\n\t# 1 2 840 113549 1 9 3 contentType\n\n\tsub CRYPT_CERTINFO_CMS_CONTENTTYPE { 2500 }\n\n\t# 1 2 840 113549 1 9 4 messageDigest\n\n\tsub CRYPT_CERTINFO_CMS_MESSAGEDIGEST { 2501 }\n\n\t# 1 2 840 113549 1 9 5 signingTime\n\n\tsub CRYPT_CERTINFO_CMS_SIGNINGTIME { 2502 }\n\n\t# 1 2 840 113549 1 9 6 counterSignature\n\t# counterSignature\n\tsub CRYPT_CERTINFO_CMS_COUNTERSIGNATURE { 2503 }\n\n\t# 1 2 840 113549 1 9 13 signingDescription\n\n\tsub CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION { 2504 }\n\n\t# 1 2 840 113549 1 9 15 sMIMECapabilities\n\n\tsub CRYPT_CERTINFO_CMS_SMIMECAPABILITIES { 2505 }\n\t# 3DES encryption\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_3DES { 2506 }\n\t# AES encryption\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_AES { 2507 }\n\t# CAST-128 encryption\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_CAST128 { 2508 }\n\t# SHA2-ng hash\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_SHAng { 2509 }\n\t# SHA2-256 hash\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_SHA2 { 2510 }\n\t# SHA1 hash\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_SHA1 { 2511 }\n\t# HMAC-SHA2-ng MAC\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng { 2512 }\n\t# HMAC-SHA2-256 MAC\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2 { 2513 }\n\t# HMAC-SHA1 MAC\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1 { 2514 }\n\t# AuthEnc w.256-bit key\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256 { 2515 }\n\t# AuthEnc w.128-bit key\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128 { 2516 }\n\t# RSA with SHA-ng signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng { 2517 }\n\t# RSA with SHA2-256 signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2 { 2518 }\n\t# RSA with SHA1 signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1 { 2519 }\n\t# DSA with SHA-1 signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1 { 2520 }\n\t# ECDSA with SHA-ng signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng { 2521 }\n\t# ECDSA with SHA2-256 signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2 { 2522 }\n\t# ECDSA with SHA-1 signing\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1 { 2523 }\n\t# preferSignedData\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA { 2524 }\n\t# canNotDecryptAny\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY { 2525 }\n\t# preferBinaryInside\n\tsub CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE { 2526 }\n\n\t# 1 2 840 113549 1 9 16 2 1 receiptRequest\n\n\tsub CRYPT_CERTINFO_CMS_RECEIPTREQUEST { 2527 }\n\t# contentIdentifier\n\tsub CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER { 2528 }\n\t# receiptsFrom\n\tsub CRYPT_CERTINFO_CMS_RECEIPT_FROM { 2529 }\n\t# receiptsTo\n\tsub CRYPT_CERTINFO_CMS_RECEIPT_TO { 2530 }\n\n\t# 1 2 840 113549 1 9 16 2 2 essSecurityLabel\n\n\tsub CRYPT_CERTINFO_CMS_SECURITYLABEL { 2531 }\n\t# securityPolicyIdentifier\n\tsub CRYPT_CERTINFO_CMS_SECLABEL_POLICY { 2532 }\n\t# securityClassification\n\tsub CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION { 2533 }\n\t# privacyMark\n\tsub CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK { 2534 }\n\t# securityCategories.securityCategory.type\n\tsub CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE { 2535 }\n\t# securityCategories.securityCategory.value\n\tsub CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE { 2536 }\n\n\t# 1 2 840 113549 1 9 16 2 3 mlExpansionHistory\n\n\tsub CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY { 2537 }\n\t# mlData.mailListIdentifier.issuerAndSerialNumber\n\tsub CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER { 2538 }\n\t# mlData.expansionTime\n\tsub CRYPT_CERTINFO_CMS_MLEXP_TIME { 2539 }\n\t# mlData.mlReceiptPolicy.none\n\tsub CRYPT_CERTINFO_CMS_MLEXP_NONE { 2540 }\n\t# mlData.mlReceiptPolicy.insteadOf.generalNames.generalName\n\tsub CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF { 2541 }\n\t# mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName\n\tsub CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO { 2542 }\n\n\t# 1 2 840 113549 1 9 16 2 4 contentHints\n\n\tsub CRYPT_CERTINFO_CMS_CONTENTHINTS { 2543 }\n\t# contentDescription\n\tsub CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION { 2544 }\n\t# contentType\n\tsub CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE { 2545 }\n\n\t# 1 2 840 113549 1 9 16 2 9 equivalentLabels\n\n\tsub CRYPT_CERTINFO_CMS_EQUIVALENTLABEL { 2546 }\n\t# securityPolicyIdentifier\n\tsub CRYPT_CERTINFO_CMS_EQVLABEL_POLICY { 2547 }\n\t# securityClassification\n\tsub CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION { 2548 }\n\t# privacyMark\n\tsub CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK { 2549 }\n\t# securityCategories.securityCategory.type\n\tsub CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE { 2550 }\n\t# securityCategories.securityCategory.value\n\tsub CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE { 2551 }\n\n\t# 1 2 840 113549 1 9 16 2 12 signingCertificate\n\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE { 2552 }\n\t# certs.essCertID\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID { 2553 }\n\t# policies.policyInformation.policyIdentifier\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES { 2554 }\n\n\t# 1 2 840 113549 1 9 16 2 47 signingCertificateV2\n\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2 { 2555 }\n\t# certs.essCertID\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2 { 2556 }\n\t# policies.policyInformation.policyIdentifier\n\tsub CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES { 2557 }\n\n\t# 1 2 840 113549 1 9 16 2 15 signaturePolicyID\n\n\tsub CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID { 2558 }\n\t# sigPolicyID\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICYID { 2559 }\n\t# sigPolicyHash\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICYHASH { 2560 }\n\t# sigPolicyQualifiers.sigPolicyQualifier.cPSuri\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI { 2561 }\n\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION { 2562 }\n\t# sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization\n\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS { 2563 }\n\t# sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers\n\n\tsub CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT { 2564 }\n\t# sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText\n\n\t# 1 2 840 113549 1 9 16 9 signatureTypeIdentifier\n\n\tsub CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER { 2565 }\n\t# originatorSig\n\tsub CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG { 2566 }\n\t# domainSig\n\tsub CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG { 2567 }\n\t# additionalAttributesSig\n\tsub CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES { 2568 }\n\t# reviewSig\n\tsub CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG { 2569 }\n\n\t# 1 2 840 113549 1 9 25 3 randomNonce\n\t# randomNonce\n\tsub CRYPT_CERTINFO_CMS_NONCE { 2570 }\n\n\t# SCEP attributes:\n\t# 2 16 840 1 113733 1 9 2 messageType\n\t# 2 16 840 1 113733 1 9 3 pkiStatus\n\t# 2 16 840 1 113733 1 9 4 failInfo\n\t# 2 16 840 1 113733 1 9 5 senderNonce\n\t# 2 16 840 1 113733 1 9 6 recipientNonce\n\t# 2 16 840 1 113733 1 9 7 transID\n\t# messageType\n\tsub CRYPT_CERTINFO_SCEP_MESSAGETYPE { 2571 }\n\t# pkiStatus\n\tsub CRYPT_CERTINFO_SCEP_PKISTATUS { 2572 }\n\t# failInfo\n\tsub CRYPT_CERTINFO_SCEP_FAILINFO { 2573 }\n\t# senderNonce\n\tsub CRYPT_CERTINFO_SCEP_SENDERNONCE { 2574 }\n\t# recipientNonce\n\tsub CRYPT_CERTINFO_SCEP_RECIPIENTNONCE { 2575 }\n\t# transID\n\tsub CRYPT_CERTINFO_SCEP_TRANSACTIONID { 2576 }\n\n\t# 1 3 6 1 4 1 311 2 1 10 spcAgencyInfo\n\n\tsub CRYPT_CERTINFO_CMS_SPCAGENCYINFO { 2577 }\n\t# spcAgencyInfo.url\n\tsub CRYPT_CERTINFO_CMS_SPCAGENCYURL { 2578 }\n\n\t# 1 3 6 1 4 1 311 2 1 11 spcStatementType\n\n\tsub CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE { 2579 }\n\t# individualCodeSigning\n\tsub CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING { 2580 }\n\t# commercialCodeSigning\n\tsub CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING { 2581 }\n\n\t# 1 3 6 1 4 1 311 2 1 12 spcOpusInfo\n\n\tsub CRYPT_CERTINFO_CMS_SPCOPUSINFO { 2582 }\n\t# spcOpusInfo.name\n\tsub CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME { 2583 }\n\t# spcOpusInfo.url\n\tsub CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL { 2584 }\n\n\t# Used internally\n\n\tsub CRYPT_CERTINFO_LAST { 2585 }\n\tsub CRYPT_KEYINFO_FIRST { 3000 }\n\n\t# *******************\n\t# Keyset attributes\n\t# *******************\n\n\t# Keyset query\n\tsub CRYPT_KEYINFO_QUERY { 3001 }\n\t# Query of requests in cert store\n\tsub CRYPT_KEYINFO_QUERY_REQUESTS { 3002 }\n\n\t# Used internally\n\n\tsub CRYPT_KEYINFO_LAST { 3003 }\n\tsub CRYPT_DEVINFO_FIRST { 4000 }\n\n\t# *******************\n\t# Device attributes\n\t# *******************\n\n\t# Initialise device for use\n\tsub CRYPT_DEVINFO_INITIALISE { 4001 }\n\n\tsub CRYPT_DEVINFO_INITIALIZE { 4001 }\n\t# Authenticate user to device\n\tsub CRYPT_DEVINFO_AUTHENT_USER { 4002 }\n\t# Authenticate supervisor to dev.\n\tsub CRYPT_DEVINFO_AUTHENT_SUPERVISOR { 4003 }\n\t# Set user authent.value\n\tsub CRYPT_DEVINFO_SET_AUTHENT_USER { 4004 }\n\t# Set supervisor auth.val.\n\tsub CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR { 4005 }\n\t# Zeroise device\n\tsub CRYPT_DEVINFO_ZEROISE { 4006 }\n\n\tsub CRYPT_DEVINFO_ZEROIZE { 4006 }\n\t# Whether user is logged in\n\tsub CRYPT_DEVINFO_LOGGEDIN { 4007 }\n\t# Device/token label\n\tsub CRYPT_DEVINFO_LABEL { 4008 }\n\n\t# Used internally\n\n\tsub CRYPT_DEVINFO_LAST { 4009 }\n\tsub CRYPT_ENVINFO_FIRST { 5000 }\n\n\t# *********************\n\t# Envelope attributes\n\t# *********************\n\n\t# Pseudo-information on an envelope or meta-information which is used to\n\t# control the way that data in an envelope is processed\n\t# Data size information\n\tsub CRYPT_ENVINFO_DATASIZE { 5001 }\n\t# Compression information\n\tsub CRYPT_ENVINFO_COMPRESSION { 5002 }\n\t# Inner CMS content type\n\tsub CRYPT_ENVINFO_CONTENTTYPE { 5003 }\n\t# Detached signature\n\tsub CRYPT_ENVINFO_DETACHEDSIGNATURE { 5004 }\n\t# Signature check result\n\tsub CRYPT_ENVINFO_SIGNATURE_RESULT { 5005 }\n\t# Integrity-protection level\n\tsub CRYPT_ENVINFO_INTEGRITY { 5006 }\n\n\t# Resources required for enveloping/deenveloping\n\t# User password\n\tsub CRYPT_ENVINFO_PASSWORD { 5007 }\n\t# Conventional encryption key\n\tsub CRYPT_ENVINFO_KEY { 5008 }\n\t# Signature/signature check key\n\tsub CRYPT_ENVINFO_SIGNATURE { 5009 }\n\t# Extra information added to CMS sigs\n\tsub CRYPT_ENVINFO_SIGNATURE_EXTRADATA { 5010 }\n\t# Recipient email address\n\tsub CRYPT_ENVINFO_RECIPIENT { 5011 }\n\t# PKC encryption key\n\tsub CRYPT_ENVINFO_PUBLICKEY { 5012 }\n\t# PKC decryption key\n\tsub CRYPT_ENVINFO_PRIVATEKEY { 5013 }\n\t# Label of PKC decryption key\n\tsub CRYPT_ENVINFO_PRIVATEKEY_LABEL { 5014 }\n\t# Originator info/key\n\tsub CRYPT_ENVINFO_ORIGINATOR { 5015 }\n\t# Session key\n\tsub CRYPT_ENVINFO_SESSIONKEY { 5016 }\n\t# Hash value\n\tsub CRYPT_ENVINFO_HASH { 5017 }\n\t# Timestamp information\n\tsub CRYPT_ENVINFO_TIMESTAMP { 5018 }\n\n\t# Keysets used to retrieve keys needed for enveloping/deenveloping\n\t# Signature check keyset\n\tsub CRYPT_ENVINFO_KEYSET_SIGCHECK { 5019 }\n\t# PKC encryption keyset\n\tsub CRYPT_ENVINFO_KEYSET_ENCRYPT { 5020 }\n\t# PKC decryption keyset\n\tsub CRYPT_ENVINFO_KEYSET_DECRYPT { 5021 }\n\n\t# Used internally\n\n\tsub CRYPT_ENVINFO_LAST { 5022 }\n\tsub CRYPT_SESSINFO_FIRST { 6000 }\n\n\t# ********************\n\t# Session attributes\n\t# ********************\n\n\t# Pseudo-information about the session\n\t# Whether session is active\n\tsub CRYPT_SESSINFO_ACTIVE { 6001 }\n\t# Whether network connection is active\n\tsub CRYPT_SESSINFO_CONNECTIONACTIVE { 6002 }\n\n\t# Security-related information\n\t# User name\n\tsub CRYPT_SESSINFO_USERNAME { 6003 }\n\t# Password\n\tsub CRYPT_SESSINFO_PASSWORD { 6004 }\n\t# Server/client private key\n\tsub CRYPT_SESSINFO_PRIVATEKEY { 6005 }\n\t# Certificate store\n\tsub CRYPT_SESSINFO_KEYSET { 6006 }\n\t# Session authorisation OK\n\tsub CRYPT_SESSINFO_AUTHRESPONSE { 6007 }\n\n\t# Client/server information\n\t# Server name\n\tsub CRYPT_SESSINFO_SERVER_NAME { 6008 }\n\t# Server port number\n\tsub CRYPT_SESSINFO_SERVER_PORT { 6009 }\n\t# Server key fingerprint\n\tsub CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 { 6010 }\n\t# Client name\n\tsub CRYPT_SESSINFO_CLIENT_NAME { 6011 }\n\t# Client port number\n\tsub CRYPT_SESSINFO_CLIENT_PORT { 6012 }\n\t# Transport mechanism\n\tsub CRYPT_SESSINFO_SESSION { 6013 }\n\t# User-supplied network socket\n\tsub CRYPT_SESSINFO_NETWORKSOCKET { 6014 }\n\n\t# Generic protocol-related information\n\t# Protocol version\n\tsub CRYPT_SESSINFO_VERSION { 6015 }\n\t# Cert.request object\n\tsub CRYPT_SESSINFO_REQUEST { 6016 }\n\t# Cert.response object\n\tsub CRYPT_SESSINFO_RESPONSE { 6017 }\n\t# Issuing CA certificate\n\tsub CRYPT_SESSINFO_CACERTIFICATE { 6018 }\n\n\t# Protocol-specific information\n\t# Request type\n\tsub CRYPT_SESSINFO_CMP_REQUESTTYPE { 6019 }\n\t# Private-key keyset\n\tsub CRYPT_SESSINFO_CMP_PRIVKEYSET { 6020 }\n\t# SSH current channel\n\tsub CRYPT_SESSINFO_SSH_CHANNEL { 6021 }\n\t# SSH channel type\n\tsub CRYPT_SESSINFO_SSH_CHANNEL_TYPE { 6022 }\n\t# SSH channel argument 1\n\tsub CRYPT_SESSINFO_SSH_CHANNEL_ARG1 { 6023 }\n\t# SSH channel argument 2\n\tsub CRYPT_SESSINFO_SSH_CHANNEL_ARG2 { 6024 }\n\t# SSH channel active\n\tsub CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE { 6025 }\n\t# SSL/TLS protocol options\n\tsub CRYPT_SESSINFO_SSL_OPTIONS { 6026 }\n\t# SSL/TLS additional sub-protocol\n\tsub CRYPT_SESSINFO_SSL_SUBPROTOCOL { 6027 }\n\t# SSL/TLS WebSockets sub-protocol\n\tsub CRYPT_SESSINFO_SSL_WSPROTOCOL { 6028 }\n\t# SSL/TLS EAP challenge\n\tsub CRYPT_SESSINFO_SSL_EAPCHALLENGE { 6029 }\n\t# SSL/TLS EAP key\n\tsub CRYPT_SESSINFO_SSL_EAPKEY { 6030 }\n\t# TSP message imprint\n\tsub CRYPT_SESSINFO_TSP_MSGIMPRINT { 6031 }\n\n\t# Used internally\n\n\tsub CRYPT_SESSINFO_LAST { 6032 }\n\tsub CRYPT_USERINFO_FIRST { 7000 }\n\n\t# ********************\n\t# User attributes\n\t# ********************\n\n\t# Security-related information\n\t# Password\n\tsub CRYPT_USERINFO_PASSWORD { 7001 }\n\n\t# User role-related information\n\t# CA cert signing key\n\tsub CRYPT_USERINFO_CAKEY_CERTSIGN { 7002 }\n\t# CA CRL signing key\n\tsub CRYPT_USERINFO_CAKEY_CRLSIGN { 7003 }\n\t# CA RTCS signing key\n\tsub CRYPT_USERINFO_CAKEY_RTCSSIGN { 7004 }\n\t# CA OCSP signing key\n\tsub CRYPT_USERINFO_CAKEY_OCSPSIGN { 7005 }\n\n\t# Used internally for range checking\n\n\tsub CRYPT_USERINFO_LAST { 7006 }\n\tsub CRYPT_ATTRIBUTE_LAST { 7006 }\n\n\n\n##### END ENUM CRYPT_ATTRIBUTE_TYPE\n\n#****************************************************************************\n#*                                                                           *\n#*                       Attribute Subtypes and Related Values               *\n#*                                                                           *\n#****************************************************************************\n\n# Flags for the X.509 keyUsage extension \n\n\tsub CRYPT_KEYUSAGE_NONE { 0x000 }\n\tsub CRYPT_KEYUSAGE_DIGITALSIGNATURE { 0x001 }\n\tsub CRYPT_KEYUSAGE_NONREPUDIATION { 0x002 }\n\tsub CRYPT_KEYUSAGE_KEYENCIPHERMENT { 0x004 }\n\tsub CRYPT_KEYUSAGE_DATAENCIPHERMENT { 0x008 }\n\tsub CRYPT_KEYUSAGE_KEYAGREEMENT { 0x010 }\n\tsub CRYPT_KEYUSAGE_KEYCERTSIGN { 0x020 }\n\tsub CRYPT_KEYUSAGE_CRLSIGN { 0x040 }\n\tsub CRYPT_KEYUSAGE_ENCIPHERONLY { 0x080 }\n\tsub CRYPT_KEYUSAGE_DECIPHERONLY { 0x100 }\n\tsub CRYPT_KEYUSAGE_LAST { 0x200 }\n# Last possible value \n\n# X.509 cRLReason and cryptlib cRLExtReason codes \n\n  sub CRYPT_CRLREASON_UNSPECIFIED { 0 }\n  sub CRYPT_CRLREASON_KEYCOMPROMISE { 1 }\n  sub CRYPT_CRLREASON_CACOMPROMISE { 2 }\n  sub CRYPT_CRLREASON_AFFILIATIONCHANGED { 3 }\n  sub CRYPT_CRLREASON_SUPERSEDED { 4 }\n  sub CRYPT_CRLREASON_CESSATIONOFOPERATION { 5 }\n  sub CRYPT_CRLREASON_CERTIFICATEHOLD { 6 }\n  sub CRYPT_CRLREASON_REMOVEFROMCRL { 8 }\n  sub CRYPT_CRLREASON_PRIVILEGEWITHDRAWN { 9 }\n  sub CRYPT_CRLREASON_AACOMPROMISE { 10 }\n  sub CRYPT_CRLREASON_LAST { 11 }\n  sub CRYPT_CRLREASON_NEVERVALID { 20 }\n  sub CRYPT_CRLEXTREASON_LAST  { 21 }\n\n\n#  X.509 CRL reason flags.  These identify the same thing as the cRLReason\n#  codes but allow for multiple reasons to be specified.  Note that these\n#  don't follow the X.509 naming since in that scheme the enumerated types\n#  and bitflags have the same names \n\n\tsub CRYPT_CRLREASONFLAG_UNUSED { 0x001 }\n\tsub CRYPT_CRLREASONFLAG_KEYCOMPROMISE { 0x002 }\n\tsub CRYPT_CRLREASONFLAG_CACOMPROMISE { 0x004 }\n\tsub CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED { 0x008 }\n\tsub CRYPT_CRLREASONFLAG_SUPERSEDED { 0x010 }\n\tsub CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION { 0x020 }\n\tsub CRYPT_CRLREASONFLAG_CERTIFICATEHOLD { 0x040 }\n\tsub CRYPT_CRLREASONFLAG_LAST { 0x080 }\n# Last poss.value \n\n# X.509 CRL holdInstruction codes \n\n  sub CRYPT_HOLDINSTRUCTION_NONE { 0 }\n  sub CRYPT_HOLDINSTRUCTION_CALLISSUER { 1 }\n  sub CRYPT_HOLDINSTRUCTION_REJECT { 2 }\n  sub CRYPT_HOLDINSTRUCTION_PICKUPTOKEN { 3 }\n  sub CRYPT_HOLDINSTRUCTION_LAST  { 4 }\n\n\n# Certificate checking compliance levels \n\n##### BEGIN ENUM CRYPT_COMPLIANCELEVEL_TYPE\n\n\n\tsub CRYPT_COMPLIANCELEVEL_OBLIVIOUS { 0 }\n\tsub CRYPT_COMPLIANCELEVEL_REDUCED { 1 }\n\n\tsub CRYPT_COMPLIANCELEVEL_STANDARD { 2 }\n\tsub CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL { 3 }\n\n\tsub CRYPT_COMPLIANCELEVEL_PKIX_FULL { 4 }\n\tsub CRYPT_COMPLIANCELEVEL_LAST { 5 }\n\n\n##### END ENUM CRYPT_COMPLIANCELEVEL_TYPE\n\n# Flags for the Netscape netscape-cert-type extension \n\n\tsub CRYPT_NS_CERTTYPE_SSLCLIENT { 0x001 }\n\tsub CRYPT_NS_CERTTYPE_SSLSERVER { 0x002 }\n\tsub CRYPT_NS_CERTTYPE_SMIME { 0x004 }\n\tsub CRYPT_NS_CERTTYPE_OBJECTSIGNING { 0x008 }\n\tsub CRYPT_NS_CERTTYPE_RESERVED { 0x010 }\n\tsub CRYPT_NS_CERTTYPE_SSLCA { 0x020 }\n\tsub CRYPT_NS_CERTTYPE_SMIMECA { 0x040 }\n\tsub CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA { 0x080 }\n\tsub CRYPT_NS_CERTTYPE_LAST { 0x100 }\n# Last possible value \n\n# Flags for the SET certificate-type extension \n\n\tsub CRYPT_SET_CERTTYPE_CARD { 0x001 }\n\tsub CRYPT_SET_CERTTYPE_MER { 0x002 }\n\tsub CRYPT_SET_CERTTYPE_PGWY { 0x004 }\n\tsub CRYPT_SET_CERTTYPE_CCA { 0x008 }\n\tsub CRYPT_SET_CERTTYPE_MCA { 0x010 }\n\tsub CRYPT_SET_CERTTYPE_PCA { 0x020 }\n\tsub CRYPT_SET_CERTTYPE_GCA { 0x040 }\n\tsub CRYPT_SET_CERTTYPE_BCA { 0x080 }\n\tsub CRYPT_SET_CERTTYPE_RCA { 0x100 }\n\tsub CRYPT_SET_CERTTYPE_ACQ { 0x200 }\n\tsub CRYPT_SET_CERTTYPE_LAST { 0x400 }\n# Last possible value \n\n# CMS contentType values \n\n##### BEGIN ENUM CRYPT_CONTENT_TYPE\n\n\tsub CRYPT_CONTENT_NONE { 0 }\n\tsub CRYPT_CONTENT_DATA { 1 }\n\n\tsub CRYPT_CONTENT_SIGNEDDATA { 2 }\n\tsub CRYPT_CONTENT_ENVELOPEDDATA { 3 }\n\n\tsub CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA { 4 }\n\n\tsub CRYPT_CONTENT_DIGESTEDDATA { 5 }\n\tsub CRYPT_CONTENT_ENCRYPTEDDATA { 6 }\n\n\tsub CRYPT_CONTENT_COMPRESSEDDATA { 7 }\n\tsub CRYPT_CONTENT_AUTHDATA { 8 }\n\n\tsub CRYPT_CONTENT_AUTHENVDATA { 9 }\n\tsub CRYPT_CONTENT_TSTINFO { 10 }\n\n\tsub CRYPT_CONTENT_SPCINDIRECTDATACONTEXT { 11 }\n\n\tsub CRYPT_CONTENT_RTCSREQUEST { 12 }\n\tsub CRYPT_CONTENT_RTCSRESPONSE { 13 }\n\n\tsub CRYPT_CONTENT_RTCSRESPONSE_EXT { 14 }\n\tsub CRYPT_CONTENT_MRTD { 15 }\n\n\tsub CRYPT_CONTENT_LAST { 16 }\n\n\n##### END ENUM CRYPT_CONTENT_TYPE\n\n# ESS securityClassification codes \n\n  sub CRYPT_CLASSIFICATION_UNMARKED { 0 }\n  sub CRYPT_CLASSIFICATION_UNCLASSIFIED { 1 }\n  sub CRYPT_CLASSIFICATION_RESTRICTED { 2 }\n  sub CRYPT_CLASSIFICATION_CONFIDENTIAL { 3 }\n  sub CRYPT_CLASSIFICATION_SECRET { 4 }\n  sub CRYPT_CLASSIFICATION_TOP_SECRET { 5 }\n  sub CRYPT_CLASSIFICATION_LAST { 255 }\n\n\n# RTCS certificate status \n\n##### BEGIN ENUM CRYPT_CERTSTATUS_TYPE\n\n\t# No certificate status\n\tsub CRYPT_CERTSTATUS_NONE { 0 }\n\t# Certificate valid\n\tsub CRYPT_CERTSTATUS_VALID { 1 }\n\t# Certificate isn't valid\n\tsub CRYPT_CERTSTATUS_NOTVALID { 2 }\n\t# Response is non-authoritative\n\tsub CRYPT_CERTSTATUS_NONAUTHORITATIVE { 3 }\n\t# Certificate status unknown\n\tsub CRYPT_CERTSTATUS_UNKNOWN { 4 }\n\t# Last possible certificate status\n\tsub CRYPT_CERTSTATUS_LAST { 5 }\n\n\n##### END ENUM CRYPT_CERTSTATUS_TYPE\n\n# OCSP revocation status \n\n  sub CRYPT_OCSPSTATUS_NOTREVOKED { 0 }\n  sub CRYPT_OCSPSTATUS_REVOKED { 1 }\n  sub CRYPT_OCSPSTATUS_UNKNOWN  { 2 }\n\n\n#  The amount of detail to include in signatures when signing certificate\n#  objects \n\n##### BEGIN ENUM CRYPT_SIGNATURELEVEL_TYPE\n\n\t# Include only signature\n\tsub CRYPT_SIGNATURELEVEL_NONE { 0 }\n\t# Include signer cert\n\tsub CRYPT_SIGNATURELEVEL_SIGNERCERT { 1 }\n\t# Include all relevant info\n\tsub CRYPT_SIGNATURELEVEL_ALL { 2 }\n\t# Last possible sig.level type\n\tsub CRYPT_SIGNATURELEVEL_LAST { 3 }\n\n\n##### END ENUM CRYPT_SIGNATURELEVEL_TYPE\n\n#  The level of integrity protection to apply to enveloped data.  The \n#  default envelope protection for an envelope with keying information \n#  applied is encryption, this can be modified to use MAC-only protection\n#  (with no encryption) or hybrid encryption + authentication \n\n##### BEGIN ENUM CRYPT_INTEGRITY_TYPE\n\n\t# No integrity protection\n\tsub CRYPT_INTEGRITY_NONE { 0 }\n\t# MAC only, no encryption\n\tsub CRYPT_INTEGRITY_MACONLY { 1 }\n\t# Encryption + ingerity protection\n\tsub CRYPT_INTEGRITY_FULL { 2 }\n\n\n##### END ENUM CRYPT_INTEGRITY_TYPE\n\n#  The certificate export format type, which defines the format in which a\n#  certificate object is exported \n\n##### BEGIN ENUM CRYPT_CERTFORMAT_TYPE\n\n\t# No certificate format\n\tsub CRYPT_CERTFORMAT_NONE { 0 }\n\t# DER-encoded certificate\n\tsub CRYPT_CERTFORMAT_CERTIFICATE { 1 }\n\t# PKCS #7 certificate chain\n\tsub CRYPT_CERTFORMAT_CERTCHAIN { 2 }\n\t# base-64 wrapped cert\n\tsub CRYPT_CERTFORMAT_TEXT_CERTIFICATE { 3 }\n\t# base-64 wrapped cert chain\n\tsub CRYPT_CERTFORMAT_TEXT_CERTCHAIN { 4 }\n\t# XML wrapped cert\n\tsub CRYPT_CERTFORMAT_XML_CERTIFICATE { 5 }\n\t# XML wrapped cert chain\n\tsub CRYPT_CERTFORMAT_XML_CERTCHAIN { 6 }\n\t# Last possible cert.format type\n\tsub CRYPT_CERTFORMAT_LAST { 7 }\n\n\n##### END ENUM CRYPT_CERTFORMAT_TYPE\n\n# CMP request types \n\n##### BEGIN ENUM CRYPT_REQUESTTYPE_TYPE\n\n\t# No request type\n\tsub CRYPT_REQUESTTYPE_NONE { 0 }\n\t# Initialisation request\n\tsub CRYPT_REQUESTTYPE_INITIALISATION { 1 }\n\n\tsub CRYPT_REQUESTTYPE_INITIALIZATION { 1 }\n\t# Certification request\n\tsub CRYPT_REQUESTTYPE_CERTIFICATE { 2 }\n\t# Key update request\n\tsub CRYPT_REQUESTTYPE_KEYUPDATE { 3 }\n\t# Cert revocation request\n\tsub CRYPT_REQUESTTYPE_REVOCATION { 4 }\n\t# PKIBoot request\n\tsub CRYPT_REQUESTTYPE_PKIBOOT { 5 }\n\t# Last possible request type\n\tsub CRYPT_REQUESTTYPE_LAST { 6 }\n\n\n##### END ENUM CRYPT_REQUESTTYPE_TYPE\n\n# Key ID types \n\n##### BEGIN ENUM CRYPT_KEYID_TYPE\n\n\t# No key ID type\n\tsub CRYPT_KEYID_NONE { 0 }\n\t# Key owner name\n\tsub CRYPT_KEYID_NAME { 1 }\n\t# Key owner URI\n\tsub CRYPT_KEYID_URI { 2 }\n\t# Synonym: owner email addr.\n\tsub CRYPT_KEYID_EMAIL { 2 }\n\t# Last possible key ID type\n\tsub CRYPT_KEYID_LAST { 3 }\n\n\n##### END ENUM CRYPT_KEYID_TYPE\n\n# The encryption object types \n\n##### BEGIN ENUM CRYPT_OBJECT_TYPE\n\n\t# No object type\n\tsub CRYPT_OBJECT_NONE { 0 }\n\t# Conventionally encrypted key\n\tsub CRYPT_OBJECT_ENCRYPTED_KEY { 1 }\n\t# PKC-encrypted key\n\tsub CRYPT_OBJECT_PKCENCRYPTED_KEY { 2 }\n\t# Key agreement information\n\tsub CRYPT_OBJECT_KEYAGREEMENT { 3 }\n\t# Signature\n\tsub CRYPT_OBJECT_SIGNATURE { 4 }\n\t# Last possible object type\n\tsub CRYPT_OBJECT_LAST { 5 }\n\n\n##### END ENUM CRYPT_OBJECT_TYPE\n\n# Object/attribute error type information \n\n##### BEGIN ENUM CRYPT_ERRTYPE_TYPE\n\n\t# No error information\n\tsub CRYPT_ERRTYPE_NONE { 0 }\n\t# Attribute data too small or large\n\tsub CRYPT_ERRTYPE_ATTR_SIZE { 1 }\n\t# Attribute value is invalid\n\tsub CRYPT_ERRTYPE_ATTR_VALUE { 2 }\n\t# Required attribute missing\n\tsub CRYPT_ERRTYPE_ATTR_ABSENT { 3 }\n\t# Non-allowed attribute present\n\tsub CRYPT_ERRTYPE_ATTR_PRESENT { 4 }\n\t# Cert: Constraint violation in object\n\tsub CRYPT_ERRTYPE_CONSTRAINT { 5 }\n\t# Cert: Constraint viol.in issuing cert\n\tsub CRYPT_ERRTYPE_ISSUERCONSTRAINT { 6 }\n\t# Last possible error info type\n\tsub CRYPT_ERRTYPE_LAST { 7 }\n\n\n##### END ENUM CRYPT_ERRTYPE_TYPE\n\n# Cert store management action type \n\n##### BEGIN ENUM CRYPT_CERTACTION_TYPE\n\n\t# No cert management action\n\tsub CRYPT_CERTACTION_NONE { 0 }\n\t# Create cert store\n\tsub CRYPT_CERTACTION_CREATE { 1 }\n\t# Connect to cert store\n\tsub CRYPT_CERTACTION_CONNECT { 2 }\n\t# Disconnect from cert store\n\tsub CRYPT_CERTACTION_DISCONNECT { 3 }\n\t# Error information\n\tsub CRYPT_CERTACTION_ERROR { 4 }\n\t# Add PKI user\n\tsub CRYPT_CERTACTION_ADDUSER { 5 }\n\t# Delete PKI user\n\tsub CRYPT_CERTACTION_DELETEUSER { 6 }\n\t# Cert request\n\tsub CRYPT_CERTACTION_REQUEST_CERT { 7 }\n\t# Cert renewal request\n\tsub CRYPT_CERTACTION_REQUEST_RENEWAL { 8 }\n\t# Cert revocation request\n\tsub CRYPT_CERTACTION_REQUEST_REVOCATION { 9 }\n\t# Cert creation\n\tsub CRYPT_CERTACTION_CERT_CREATION { 10 }\n\t# Confirmation of cert creation\n\tsub CRYPT_CERTACTION_CERT_CREATION_COMPLETE { 11 }\n\t# Cancellation of cert creation\n\tsub CRYPT_CERTACTION_CERT_CREATION_DROP { 12 }\n\t# Cancel of creation w.revocation\n\tsub CRYPT_CERTACTION_CERT_CREATION_REVERSE { 13 }\n\t# Delete reqs after restart\n\tsub CRYPT_CERTACTION_RESTART_CLEANUP { 14 }\n\t# Complete revocation after restart\n\tsub CRYPT_CERTACTION_RESTART_REVOKE_CERT { 15 }\n\t# Cert issue\n\tsub CRYPT_CERTACTION_ISSUE_CERT { 16 }\n\t# CRL issue\n\tsub CRYPT_CERTACTION_ISSUE_CRL { 17 }\n\t# Cert revocation\n\tsub CRYPT_CERTACTION_REVOKE_CERT { 18 }\n\t# Cert expiry\n\tsub CRYPT_CERTACTION_EXPIRE_CERT { 19 }\n\t# Clean up on restart\n\tsub CRYPT_CERTACTION_CLEANUP { 20 }\n\t# Last possible cert store log action\n\tsub CRYPT_CERTACTION_LAST { 21 }\n\n\n##### END ENUM CRYPT_CERTACTION_TYPE\n\n# Session sub-protocol types \n\n##### BEGIN ENUM CRYPT_SUBPROTOCOL_TYPE\n\n\t# No sub-protocol type\n\tsub CRYPT_SUBPROTOCOL_NONE { 0 }\n\t# Websockets\n\tsub CRYPT_SUBPROTOCOL_WEBSOCKETS { 1 }\n\t# EAP-TTLS\n\tsub CRYPT_SUBPROTOCOL_EAPTTLS { 2 }\n\t# Last possible sub-protocol type\n\tsub CRYPT_SUBPROTOCOL_LAST { 3 }\n\n\n##### END ENUM CRYPT_SUBPROTOCOL_TYPE\n\n#  SSL/TLS protocol options.  CRYPT_SSLOPTION_MINVER_SSLV3 is the same as \n#  CRYPT_SSLOPTION_NONE since this is the baseline, although it'll never be\n#  encountered since SSLv3 is disabled \n\n\tsub CRYPT_SSLOPTION_NONE { 0x000 }\n\tsub CRYPT_SSLOPTION_MINVER_SSLV3 { 0x000 }\n# Min.protocol version \n\tsub CRYPT_SSLOPTION_MINVER_TLS10 { 0x001 }\n\tsub CRYPT_SSLOPTION_MINVER_TLS11 { 0x002 }\n\tsub CRYPT_SSLOPTION_MINVER_TLS12 { 0x003 }\n\tsub CRYPT_SSLOPTION_MINVER_TLS13 { 0x004 }\n\tsub CRYPT_SSLOPTION_MANUAL_CERTCHECK { 0x008 }\n# Require manual cert.verif.\n\tsub CRYPT_SSLOPTION_DISABLE_NAMEVERIFY { 0x010 }\n# Disable cert hostname check \n\tsub CRYPT_SSLOPTION_DISABLE_CERTVERIFY { 0x020 }\n# Disable certificate check \n\tsub CRYPT_SSLOPTION_SUITEB_128 { 0x100 }\n# SuiteB security levels (may \n\tsub CRYPT_SSLOPTION_SUITEB_256 { 0x200 }\n#  vanish in future releases) \n\n#****************************************************************************\n#*                                                                           *\n#*                               General Constants                           *\n#*                                                                           *\n#****************************************************************************\n\n# The maximum user key size - 2048 bits \n\n\tsub CRYPT_MAX_KEYSIZE { 256 }\n\n# The maximum IV/cipher block size - 256 bits \n\n\tsub CRYPT_MAX_IVSIZE { 32 }\n\n#  The maximum public-key component size - 4096 bits, and maximum component\n#  size for ECCs - 576 bits (to handle the P521 curve) \n\n\tsub CRYPT_MAX_PKCSIZE { 512 }\n\tsub CRYPT_MAX_PKCSIZE_ECC { 72 }\n\n#  The maximum hash size - 512 bits.  Before 3.4 this was 256 bits, in the \n#  3.4 release it was increased to 512 bits to accommodate SHA-3 \n\n\tsub CRYPT_MAX_HASHSIZE { 64 }\n\n# The maximum size of a text string (e.g.key owner name) \n\n\tsub CRYPT_MAX_TEXTSIZE { 64 }\n\n#  A magic value indicating that the default setting for this parameter\n#  should be used.  The parentheses are to catch potential erroneous use \n#  in an expression \n\n\tsub CRYPT_USE_DEFAULT { -100 }\n\n# A magic value for unused parameters \n\n\tsub CRYPT_UNUSED { -101 }\n\n#  Cursor positioning codes for certificate/CRL extensions.  The parentheses \n#  are to catch potential erroneous use in an expression \n\n\tsub CRYPT_CURSOR_FIRST { -200 }\n\tsub CRYPT_CURSOR_PREVIOUS { -201 }\n\tsub CRYPT_CURSOR_NEXT { -202 }\n\tsub CRYPT_CURSOR_LAST { -203 }\n\n#  The type of information polling to perform to get random seed \n#  information.  These values have to be negative because they're used\n#  as magic length values for cryptAddRandom().  The parentheses are to \n#  catch potential erroneous use in an expression \n\n\tsub CRYPT_RANDOM_FASTPOLL { -300 }\n\tsub CRYPT_RANDOM_SLOWPOLL { -301 }\n\n# Whether the PKC key is a public or private key \n\n\tsub CRYPT_KEYTYPE_PRIVATE { 0 }\n\tsub CRYPT_KEYTYPE_PUBLIC { 1 }\n\n# Keyset open options \n\n##### BEGIN ENUM CRYPT_KEYOPT_TYPE\n\n\t# No options\n\tsub CRYPT_KEYOPT_NONE { 0 }\n\t# Open keyset in read-only mode\n\tsub CRYPT_KEYOPT_READONLY { 1 }\n\t# Create a new keyset\n\tsub CRYPT_KEYOPT_CREATE { 2 }\n\t# Last possible key option type\n\tsub CRYPT_KEYOPT_LAST { 3 }\n\n\n##### END ENUM CRYPT_KEYOPT_TYPE\n\n# The various cryptlib objects - these are just integer handles \n\nsub CRYPT_CERTIFICATE { 0 }\nsub CRYPT_CONTEXT { 0 }\nsub CRYPT_DEVICE { 0 }\nsub CRYPT_ENVELOPE { 0 }\nsub CRYPT_KEYSET { 0 }\nsub CRYPT_SESSION { 0 }\nsub CRYPT_USER { 0 }\n\n#  Sometimes we don't know the exact type of a cryptlib object, so we use a\n#  generic handle type to identify it \n\nsub CRYPT_HANDLE { 0 }\n\n#****************************************************************************\n#*                                                                           *\n#*                           Encryption Data Structures                      *\n#*                                                                           *\n#****************************************************************************\n\n# Results returned from the capability query \n\nsub CRYPT_QUERY_INFO\n{\n\t{\n\t#  Algorithm information \n     algoName => ' ' x CRYPT_MAX_TEXTSIZE\t#  Algorithm name \n    ,blockSize => 0\t#  Block size of the algorithm \n    ,minKeySize => 0\t#  Minimum key size in bytes \n    ,keySize => 0\t#  Recommended key size in bytes \n    ,maxKeySize => 0\t#  Maximum key size in bytes \n    \n\t}\n}\n\n#  Results returned from the encoded object query.  These provide\n#  information on the objects created by cryptExportKey()/\n#  cryptCreateSignature() \n\nsub CRYPT_OBJECT_INFO\n{\n\t{\n\t#  The object type \n     objectType => 0\t#  The encryption algorithm and mode \n    ,cryptAlgo => 0\n    ,cryptMode => 0\t#       The hash algorithm for signature objects or PRF algorithm for derived \n\t#       keys \n    ,hashAlgo => 0\t#  The salt and PRF iterations for derived keys \n    ,salt => ' ' x CRYPT_MAX_HASHSIZE\n    ,saltSize => 0\n    ,iterations => 0\n    \n\t}\n}\n\n#  Key information for the public-key encryption algorithms.  These fields\n#  are not accessed directly, but can be manipulated with the init/set/\n#  destroyComponents() macros \n\nsub CRYPT_PKCINFO_RSA\n{\n\t{\n\t#  Status information \n     isPublicKey => 0\t#  Whether this is a public or private key \n\t#  Public components \n    ,n => ' ' x CRYPT_MAX_PKCSIZE\t#  Modulus \n    ,nLen => 0\t#  Length of modulus in bits \n    ,e => ' ' x CRYPT_MAX_PKCSIZE\t#  Public exponent \n    ,eLen => 0\t#  Length of public exponent in bits \n\t#  Private components \n    ,d => ' ' x CRYPT_MAX_PKCSIZE\t#  Private exponent \n    ,dLen => 0\t#  Length of private exponent in bits \n    ,p => ' ' x CRYPT_MAX_PKCSIZE\t#  Prime factor 1 \n    ,pLen => 0\t#  Length of prime factor 1 in bits \n    ,q => ' ' x CRYPT_MAX_PKCSIZE\t#  Prime factor 2 \n    ,qLen => 0\t#  Length of prime factor 2 in bits \n    ,u => ' ' x CRYPT_MAX_PKCSIZE\t#  Mult.inverse of q, mod p \n    ,uLen => 0\t#  Length of private exponent in bits \n    ,e1 => ' ' x CRYPT_MAX_PKCSIZE\t#  Private exponent 1 (PKCS) \n    ,e1Len => 0\t#  Length of private exponent in bits \n    ,e2 => ' ' x CRYPT_MAX_PKCSIZE\t#  Private exponent 2 (PKCS) \n    ,e2Len => 0\t#  Length of private exponent in bits \n    \n\t}\n}\n\nsub CRYPT_PKCINFO_DLP\n{\n\t{\n\t#  Status information \n     isPublicKey => 0\t#  Whether this is a public or private key \n\t#  Public components \n    ,p => ' ' x CRYPT_MAX_PKCSIZE\t#  Prime modulus \n    ,pLen => 0\t#  Length of prime modulus in bits \n    ,q => ' ' x CRYPT_MAX_PKCSIZE\t#  Prime divisor \n    ,qLen => 0\t#  Length of prime divisor in bits \n    ,g => ' ' x CRYPT_MAX_PKCSIZE\t#  h^( ( p - 1 ) / q ) mod p \n    ,gLen => 0\t#  Length of g in bits \n    ,y => ' ' x CRYPT_MAX_PKCSIZE\t#  Public random integer \n    ,yLen => 0\t#  Length of public integer in bits \n\t#  Private components \n    ,x => ' ' x CRYPT_MAX_PKCSIZE\t#  Private random integer \n    ,xLen => 0\t#  Length of private integer in bits \n    \n\t}\n}\n\n##### BEGIN ENUM CRYPT_ECCCURVE_TYPE\n\n\t# Named ECC curves.  Since these need to be mapped to all manner of\n\t# protocol- and mechanism-specific identifiers, when updating this list\n\t# grep for occurrences of the string \"P256\" (the most common one) and\n\t# check whether any related mapping tables need to be updated\n\t# No ECC curve type\n\tsub CRYPT_ECCCURVE_NONE { 0 }\n\t# NIST P256/X9.62 P256v1/SECG p256r1 curve\n\tsub CRYPT_ECCCURVE_P256 { 1 }\n\t# NIST P384, SECG p384r1 curve\n\tsub CRYPT_ECCCURVE_P384 { 2 }\n\t# NIST P521, SECG p521r1\n\tsub CRYPT_ECCCURVE_P521 { 3 }\n\t# Brainpool p256r1\n\tsub CRYPT_ECCCURVE_BRAINPOOL_P256 { 4 }\n\t# Brainpool p384r1\n\tsub CRYPT_ECCCURVE_BRAINPOOL_P384 { 5 }\n\t# Brainpool p512r1\n\tsub CRYPT_ECCCURVE_BRAINPOOL_P512 { 6 }\n\t# Last valid ECC curve type\n\tsub CRYPT_ECCCURVE_LAST { 7 }\n\n\n##### END ENUM CRYPT_ECCCURVE_TYPE\n\nsub CRYPT_PKCINFO_ECC\n{\n\t{\n\t#  Status information \n     isPublicKey => 0\t#  Whether this is a public or private key \n\t#       Curve domain parameters.  Either the curveType or the explicit domain\n\t#       parameters must be provided \n    ,curveType => 0\t#  Named curve \n    ,p => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Prime defining Fq \n    ,pLen => 0\t#  Length of prime in bits \n    ,a => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Element in Fq defining curve \n    ,aLen => 0\t#  Length of element a in bits \n    ,b => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Element in Fq defining curve \n    ,bLen => 0\t#  Length of element b in bits \n    ,gx => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Element in Fq defining point \n    ,gxLen => 0\t#  Length of element gx in bits \n    ,gy => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Element in Fq defining point \n    ,gyLen => 0\t#  Length of element gy in bits \n    ,n => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Order of point \n    ,nLen => 0\t#  Length of order in bits \n    ,h => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Optional cofactor \n    ,hLen => 0\t#  Length of cofactor in bits \n\t#  Public components \n    ,qx => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Point Q on the curve \n    ,qxLen => 0\t#  Length of point xq in bits \n    ,qy => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Point Q on the curve \n    ,qyLen => 0\t#  Length of point xy in bits \n\t#  Private components \n    ,d => ' ' x CRYPT_MAX_PKCSIZE_ECC\t#  Private random integer \n    ,dLen => 0\t#  Length of integer in bits \n    \n\t}\n}\n\n#  Macros to initialise and destroy the structure that stores the components\n#  of a public key \n\n# C-macro not translated to Perl code but implemented apart: \n#   #define cryptInitComponents( componentInfo, componentKeyType ) \n#    { memset( ( componentInfo ), 0, sizeof( *componentInfo ) ); \n#      ( componentInfo )->isPublicKey = ( ( componentKeyType ) ? 1 : 0 ); }\n#\n\n# C-macro not translated to Perl code but implemented apart: \n#   #define cryptDestroyComponents( componentInfo ) \n#    memset( ( componentInfo ), 0, sizeof( *componentInfo ) )\n#\n\n# Macros to set a component of a public key \n\n# C-macro not translated to Perl code but implemented apart: \n#   #define cryptSetComponent( destination, source, length ) \n#    { memcpy( ( destination ), ( source ), ( ( length ) + 7 ) >> 3 ); \n#      ( destination##Len ) = length; }\n#\n\n#****************************************************************************\n#*                                                                           *\n#*                               Status Codes                                *\n#*                                                                           *\n#****************************************************************************\n\n# No error in function call \n\n\tsub CRYPT_OK { 0 }\n# No error \n\n#  Error in parameters passed to function.  The parentheses are to catch \n#  potential erroneous use in an expression \n\n\tsub CRYPT_ERROR_PARAM1 { -1 }\n# Bad argument, parameter 1 \n\tsub CRYPT_ERROR_PARAM2 { -2 }\n# Bad argument, parameter 2 \n\tsub CRYPT_ERROR_PARAM3 { -3 }\n# Bad argument, parameter 3 \n\tsub CRYPT_ERROR_PARAM4 { -4 }\n# Bad argument, parameter 4 \n\tsub CRYPT_ERROR_PARAM5 { -5 }\n# Bad argument, parameter 5 \n\tsub CRYPT_ERROR_PARAM6 { -6 }\n# Bad argument, parameter 6 \n\tsub CRYPT_ERROR_PARAM7 { -7 }\n# Bad argument, parameter 7 \n\n# Errors due to insufficient resources \n\n\tsub CRYPT_ERROR_MEMORY { -10 }\n# Out of memory \n\tsub CRYPT_ERROR_NOTINITED { -11 }\n# Data has not been initialised \n\tsub CRYPT_ERROR_INITED { -12 }\n# Data has already been init'd \n\tsub CRYPT_ERROR_NOSECURE { -13 }\n# Opn.not avail.at requested sec.level \n\tsub CRYPT_ERROR_RANDOM { -14 }\n# No reliable random data available \n\tsub CRYPT_ERROR_FAILED { -15 }\n# Operation failed \n\tsub CRYPT_ERROR_INTERNAL { -16 }\n# Internal consistency check failed \n\n# Security violations \n\n\tsub CRYPT_ERROR_NOTAVAIL { -20 }\n# This type of opn.not available \n\tsub CRYPT_ERROR_PERMISSION { -21 }\n# No permiss.to perform this operation \n\tsub CRYPT_ERROR_WRONGKEY { -22 }\n# Incorrect key used to decrypt data \n\tsub CRYPT_ERROR_INCOMPLETE { -23 }\n# Operation incomplete/still in progress \n\tsub CRYPT_ERROR_COMPLETE { -24 }\n# Operation complete/can't continue \n\tsub CRYPT_ERROR_TIMEOUT { -25 }\n# Operation timed out before completion \n\tsub CRYPT_ERROR_INVALID { -26 }\n# Invalid/inconsistent information \n\tsub CRYPT_ERROR_SIGNALLED { -27 }\n# Resource destroyed by extnl.event \n\n# High-level function errors \n\n\tsub CRYPT_ERROR_OVERFLOW { -30 }\n# Resources/space exhausted \n\tsub CRYPT_ERROR_UNDERFLOW { -31 }\n# Not enough data available \n\tsub CRYPT_ERROR_BADDATA { -32 }\n# Bad/unrecognised data format \n\tsub CRYPT_ERROR_SIGNATURE { -33 }\n# Signature/integrity check failed \n\n# Data access function errors \n\n\tsub CRYPT_ERROR_OPEN { -40 }\n# Cannot open object \n\tsub CRYPT_ERROR_READ { -41 }\n# Cannot read item from object \n\tsub CRYPT_ERROR_WRITE { -42 }\n# Cannot write item to object \n\tsub CRYPT_ERROR_NOTFOUND { -43 }\n# Requested item not found in object \n\tsub CRYPT_ERROR_DUPLICATE { -44 }\n# Item already present in object \n\n# Data enveloping errors \n\n\tsub CRYPT_ENVELOPE_RESOURCE { -50 }\n# Need resource to proceed \n\n# Macros to examine return values \n\n# C-macro not translated to Perl code but implemented apart: \n#   #define cryptStatusError( status )  ( ( status ) < CRYPT_OK )\n#\n# C-macro not translated to Perl code but implemented apart: \n#   #define cryptStatusOK( status )     ( ( status ) == CRYPT_OK )\n#\n\n#****************************************************************************\n#*                                                                           *\n#*                                   General Functions                       *\n#*                                                                           *\n#****************************************************************************\n\n# The following is necessary to stop C++ name mangling \n\n\n# Initialise and shut down cryptlib \n\n# C_CHECK_RETVAL \n###C_RET cryptInit( void );\n###C_RET cryptEnd( void );\n#\n# Query cryptlibs capabilities \n\n# C_CHECK_RETVAL \n###C_RET cryptQueryCapability( C_IN CRYPT_ALGO_TYPE cryptAlgo,\n##                            C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo );\n##\n# Create and destroy an encryption context \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCreateContext( C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n##                          C_IN CRYPT_USER cryptUser,\n##                          C_IN CRYPT_ALGO_TYPE cryptAlgo );\n###C_RET cryptDestroyContext( C_IN CRYPT_CONTEXT cryptContext );\n#\n# Generic \"destroy an object\" function \n\n#C_RET cryptDestroyObject( C_IN CRYPT_HANDLE cryptObject );\n#\n# Generate a key into a context \n\n# C_CHECK_RETVAL \n###C_RET cryptGenerateKey( C_IN CRYPT_CONTEXT cryptContext );\n##\n# Encrypt/decrypt/hash a block of memory \n\n# C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptEncrypt( C_IN CRYPT_CONTEXT cryptContext, C_INOUT void C_PTR buffer,\n##                    C_IN int length );\n### C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptDecrypt( C_IN CRYPT_CONTEXT cryptContext, C_INOUT void C_PTR buffer,\n##                    C_IN int length );\n##\n# Get/set/delete attribute functions \n\n#C_RET cryptSetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n#                         C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n#                         C_IN int value );\n## C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptSetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n##                               C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n##                               C_IN void C_PTR value, C_IN int valueLength );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptGetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n##                         C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n##                         C_OUT int C_PTR value );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 4 ) ) \n###C_RET cryptGetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n##                               C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n##                               C_OUT_OPT void C_PTR value,\n##                               C_OUT int C_PTR valueLength );\n###C_RET cryptDeleteAttribute( C_IN CRYPT_HANDLE cryptHandle,\n#                            C_IN CRYPT_ATTRIBUTE_TYPE attributeType );\n#\n#  Oddball functions: Add random data to the pool, query an encoded signature\n#  or key data.  These are due to be replaced once a suitable alternative can\n#  be found \n\n#C_RET cryptAddRandom( C_IN void C_PTR randomData, C_IN int randomDataLength );\n## C_CHECK_RETVAL C_NONNULL_ARG( ( 1, 3 ) ) \n###C_RET cryptQueryObject( C_IN void C_PTR objectData,\n##                        C_IN int objectDataLength,\n##                        C_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo );\n##\n#****************************************************************************\n#*                                                                           *\n#*                           Mid-level Encryption Functions                  *\n#*                                                                           *\n#****************************************************************************\n\n# Export and import an encrypted session key \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptExportKey( C_OUT_OPT void C_PTR encryptedKey,\n##                      C_IN int encryptedKeyMaxLength,\n##                      C_OUT int C_PTR encryptedKeyLength,\n##                      C_IN CRYPT_HANDLE exportKey,\n##                      C_IN CRYPT_CONTEXT sessionKeyContext );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptExportKeyEx( C_OUT_OPT void C_PTR encryptedKey,\n##                        C_IN int encryptedKeyMaxLength,\n##                        C_OUT int C_PTR encryptedKeyLength,\n##                        C_IN CRYPT_FORMAT_TYPE formatType,\n##                        C_IN CRYPT_HANDLE exportKey,\n##                        C_IN CRYPT_CONTEXT sessionKeyContext );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptImportKey( C_IN void C_PTR encryptedKey,\n##                      C_IN int encryptedKeyLength,\n##                      C_IN CRYPT_CONTEXT importKey,\n##                      C_IN CRYPT_CONTEXT sessionKeyContext );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,\n##                        C_IN int encryptedKeyLength,\n##                        C_IN CRYPT_CONTEXT importKey,\n##                        C_IN CRYPT_CONTEXT sessionKeyContext,\n##                        C_OUT_OPT CRYPT_CONTEXT C_PTR returnedContext );\n##\n# Create and check a digital signature \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptCreateSignature( C_OUT_OPT void C_PTR signature,\n##                            C_IN int signatureMaxLength,\n##                            C_OUT int C_PTR signatureLength,\n##                            C_IN CRYPT_CONTEXT signContext,\n##                            C_IN CRYPT_CONTEXT hashContext );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptCreateSignatureEx( C_OUT_OPT void C_PTR signature,\n##                              C_IN int signatureMaxLength,\n##                              C_OUT int C_PTR signatureLength,\n##                              C_IN CRYPT_FORMAT_TYPE formatType,\n##                              C_IN CRYPT_CONTEXT signContext,\n##                              C_IN CRYPT_CONTEXT hashContext,\n##                              C_IN CRYPT_CERTIFICATE extraData );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCheckSignature( C_IN void C_PTR signature,\n##                           C_IN int signatureLength,\n##                           C_IN CRYPT_HANDLE sigCheckKey,\n##                           C_IN CRYPT_CONTEXT hashContext );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCheckSignatureEx( C_IN void C_PTR signature,\n##                             C_IN int signatureLength,\n##                             C_IN CRYPT_HANDLE sigCheckKey,\n##                             C_IN CRYPT_CONTEXT hashContext,\n##                             C_OUT_OPT CRYPT_HANDLE C_PTR extraData );\n##\n#****************************************************************************\n#*                                                                           *\n#*                                   Keyset Functions                        *\n#*                                                                           *\n#****************************************************************************\n\n# Open and close a keyset \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \n###C_RET cryptKeysetOpen( C_OUT CRYPT_KEYSET C_PTR keyset,\n##                       C_IN CRYPT_USER cryptUser,\n##                       C_IN CRYPT_KEYSET_TYPE keysetType,\n##                       C_IN C_STR name, C_IN CRYPT_KEYOPT_TYPE options );\n###C_RET cryptKeysetClose( C_IN CRYPT_KEYSET keyset );\n#\n# Get a key from a keyset or device \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptGetPublicKey( C_IN CRYPT_KEYSET keyset,\n##                         C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n##                         C_IN CRYPT_KEYID_TYPE keyIDtype,\n##                         C_IN_OPT C_STR keyID );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \n###C_RET cryptGetPrivateKey( C_IN CRYPT_KEYSET keyset,\n##                          C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n##                          C_IN CRYPT_KEYID_TYPE keyIDtype,\n##                          C_IN C_STR keyID, C_IN_OPT C_STR password );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \n#C_RET cryptGetKey( C_IN CRYPT_KEYSET keyset,\n#                   C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n#                   C_IN CRYPT_KEYID_TYPE keyIDtype, C_IN C_STR keyID, \n#                   C_IN_OPT C_STR password );\n\n# Add/delete a key to/from a keyset or device \n\n# C_CHECK_RETVAL \n###C_RET cryptAddPublicKey( C_IN CRYPT_KEYSET keyset,\n##                         C_IN CRYPT_CERTIFICATE certificate );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptAddPrivateKey( C_IN CRYPT_KEYSET keyset,\n##                          C_IN CRYPT_HANDLE cryptKey,\n##                          C_IN C_STR password );\n### C_NONNULL_ARG( ( 3 ) ) \n###C_RET cryptDeleteKey( C_IN CRYPT_KEYSET keyset,\n##                      C_IN CRYPT_KEYID_TYPE keyIDtype,\n##                      C_IN C_STR keyID );\n##\n#****************************************************************************\n#*                                                                           *\n#*                               Certificate Functions                       *\n#*                                                                           *\n#****************************************************************************\n\n# Create/destroy a certificate \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCreateCert( C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n##                       C_IN CRYPT_USER cryptUser,\n##                       C_IN CRYPT_CERTTYPE_TYPE certType );\n###C_RET cryptDestroyCert( C_IN CRYPT_CERTIFICATE certificate );\n#\n#  Get/add/delete certificate extensions.  These are direct data insertion\n#  functions whose use is discouraged, so they fix the string at char *\n#  rather than C_STR \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3, 6 ) ) \n###C_RET cryptGetCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n##                             C_IN char C_PTR oid,\n##                             C_OUT int C_PTR criticalFlag,\n##                             C_OUT_OPT void C_PTR extension,\n##                             C_IN int extensionMaxLength,\n##                             C_OUT int C_PTR extensionLength );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \n###C_RET cryptAddCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n##                             C_IN char C_PTR oid, C_IN int criticalFlag,\n##                             C_IN void C_PTR extension,\n##                             C_IN int extensionLength );\n### C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptDeleteCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n##                                C_IN char C_PTR oid );\n##\n# Sign/sig.check a certificate/certification request \n\n# C_CHECK_RETVAL \n###C_RET cryptSignCert( C_IN CRYPT_CERTIFICATE certificate,\n##                     C_IN CRYPT_CONTEXT signContext );\n### C_CHECK_RETVAL \n###C_RET cryptCheckCert( C_IN CRYPT_CERTIFICATE certificate,\n##                      C_IN CRYPT_HANDLE sigCheckKey );\n##\n# Import/export a certificate/certification request \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \n###C_RET cryptImportCert( C_IN void C_PTR certObject,\n##                       C_IN int certObjectLength,\n##                       C_IN CRYPT_USER cryptUser,\n##                       C_OUT CRYPT_CERTIFICATE C_PTR certificate );\n### C_CHECK_RETVAL \n###C_RET cryptExportCert( C_OUT_OPT void C_PTR certObject,\n##                       C_IN int certObjectMaxLength,\n##                       C_OUT int C_PTR certObjectLength,\n##                       C_IN CRYPT_CERTFORMAT_TYPE certFormatType,\n##                       C_IN CRYPT_CERTIFICATE certificate );\n##\n# CA management functions \n\n# C_CHECK_RETVAL \n###C_RET cryptCAAddItem( C_IN CRYPT_KEYSET keyset,\n##                      C_IN CRYPT_CERTIFICATE certificate );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptCAGetItem( C_IN CRYPT_KEYSET keyset,\n##                      C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n##                      C_IN CRYPT_CERTTYPE_TYPE certType,\n##                      C_IN CRYPT_KEYID_TYPE keyIDtype,\n##                      C_IN_OPT C_STR keyID );\n### C_NONNULL_ARG( ( 4 ) ) \n###C_RET cryptCADeleteItem( C_IN CRYPT_KEYSET keyset,\n##                         C_IN CRYPT_CERTTYPE_TYPE certType,\n##                         C_IN CRYPT_KEYID_TYPE keyIDtype,\n##                         C_IN C_STR keyID );\n### C_CHECK_RETVAL \n###C_RET cryptCACertManagement( C_OUT_OPT CRYPT_CERTIFICATE C_PTR certificate,\n##                             C_IN CRYPT_CERTACTION_TYPE action,\n##                             C_IN CRYPT_KEYSET keyset,\n##                             C_IN CRYPT_CONTEXT caKey,\n##                             C_IN CRYPT_CERTIFICATE certRequest );\n##\n#****************************************************************************\n#*                                                                           *\n#*                           Envelope and Session Functions                  *\n#*                                                                           *\n#****************************************************************************\n\n# Create/destroy an envelope \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCreateEnvelope( C_OUT CRYPT_ENVELOPE C_PTR envelope,\n##                           C_IN CRYPT_USER cryptUser,\n##                           C_IN CRYPT_FORMAT_TYPE formatType );\n###C_RET cryptDestroyEnvelope( C_IN CRYPT_ENVELOPE envelope );\n#\n# Create/destroy a session \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptCreateSession( C_OUT CRYPT_SESSION C_PTR session,\n##                          C_IN CRYPT_USER cryptUser,\n##                          C_IN CRYPT_SESSION_TYPE formatType );\n###C_RET cryptDestroySession( C_IN CRYPT_SESSION session );\n#\n# Add/remove data to/from and envelope or session \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \n###C_RET cryptPushData( C_IN CRYPT_HANDLE envelope, C_IN void C_PTR buffer,\n##                     C_IN int length, C_OUT int C_PTR bytesCopied );\n### C_CHECK_RETVAL \n###C_RET cryptFlushData( C_IN CRYPT_HANDLE envelope );\n### C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \n###C_RET cryptPopData( C_IN CRYPT_HANDLE envelope, C_OUT void C_PTR buffer,\n##                    C_IN int length, C_OUT int C_PTR bytesCopied );\n##\n#****************************************************************************\n#*                                                                           *\n#*                               Device Functions                            *\n#*                                                                           *\n#****************************************************************************\n\n# Open and close a device \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \n###C_RET cryptDeviceOpen( C_OUT CRYPT_DEVICE C_PTR device,\n##                       C_IN CRYPT_USER cryptUser,\n##                       C_IN CRYPT_DEVICE_TYPE deviceType,\n##                       C_IN_OPT C_STR name );\n###C_RET cryptDeviceClose( C_IN CRYPT_DEVICE device );\n#\n# Query a devices capabilities \n\n# C_CHECK_RETVAL \n###C_RET cryptDeviceQueryCapability( C_IN CRYPT_DEVICE device,\n##                                  C_IN CRYPT_ALGO_TYPE cryptAlgo,\n##                                  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo );\n##\n# Create an encryption context via the device \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \n###C_RET cryptDeviceCreateContext( C_IN CRYPT_DEVICE device,\n##                                C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n##                                C_IN CRYPT_ALGO_TYPE cryptAlgo );\n##\n#****************************************************************************\n#*                                                                           *\n#*                           User Management Functions                       *\n#*                                                                           *\n#****************************************************************************\n\n# Log on and off (create/destroy a user object) \n\n# C_CHECK_RETVAL C_NONNULL_ARG( ( 1, 2, 3 ) ) \n###C_RET cryptLogin( C_OUT CRYPT_USER C_PTR user,\n##                  C_IN C_STR name, C_IN C_STR password );\n###C_RET cryptLogout( C_IN CRYPT_USER user );\n#\n#****************************************************************************\n#*                                                                           *\n#*                               Direct API Functions                        *\n#*                                                                           *\n#****************************************************************************\n\n\n\n#\n# *****************************************************************************\n# *                                                                           *\n# *                    End of Perl Functions                                  *\n# *                                                                           *\n# *****************************************************************************\n#\n\n1; ##### End-of perl header file!\n\n"
  },
  {
    "path": "deps/cl345/bindings/PerlCryptLib.pm",
    "content": "package PerlCryptLib;\n\nuse 5.008;\nuse strict;\nuse warnings;\nuse Carp;\n\nrequire Exporter;\nuse AutoLoader;\n\nour $VERSION = '1.11';\n\n\n#############################################################################\n# PRIVATE SUB\n#############################################################################\n\n\t##### Returns list containing constants and enumerated constants\n\tsub __symbolList($;$) {\n\t\tmy $pkg = shift;\n\t\tmy $filter = shift || '^.*?$';\n\t\tmy @list = ();\n\t\t$pkg = eval('*{' . $pkg . '::}');\n\t\tmy $count = 0;\n\t\tforeach my $key ( sort keys %{$pkg} ) {\n\t\t\tif ($key =~ /$filter/) { \n\t\t\t\tpush @list, $key;\n\t\t\t}\n\t\t}\n\t\treturn @list;\n\t}\n\n\n#############################################################################\n# Includes 'cryptlib' constants and enumarations porting definitions\n#############################################################################\n\n\trequire 'PerlCryptLib.ph';\n\n\n#############################################################################\n# Perl posrting for 'cryptlib' macros to examine return values\n#############################################################################\n\n\tsub cryptStatusError($) {\n\t\tmy $status = shift;\n\t\treturn ( $status < &CRYPT_OK );\n\t}\n\n\tsub cryptStatusOK($) {\n\t\tmy $status = shift;\n\t\treturn ( $status == &CRYPT_OK );\n\t}\n\n\n#############################################################################\n# Perl porting for 'cryptlib' macros to manage low-level components\n#############################################################################\n\n\tsub cryptInitComponents(;$$@) {\n\t\tdie \"Usage: cryptInitComponents(\\$componentInfo, \\$componentKeyType)\\n\" if scalar(@_) != 2;\n\t\tmy ($componentInfo, $componentKeyType) = @_;\n\t\t$componentInfo->{isPublicKey} = ( $componentKeyType == &CRYPT_KEYTYPE_PUBLIC ? 1 : 0 );\n\t\treturn &CRYPT_OK;\n\t}\n\n\tsub cryptDestroyComponents(;$@) {\n\t\tdie \"Usage: cryptDestroyComponents(\\$componentInfo)\\n\" if scalar(@_) != 1;\n\t\tmy $componentInfo = shift;\n\t\tundef $componentInfo;\n\t\treturn &CRYPT_OK;\n\t}\n\n\tsub cryptSetComponent(;$$$$@) {\n\t\tdie \"Usage: cryptSetComponent(\\$componentInfo, \\$element, \\$source, \\$length)\\nFor more info see README file.\" if scalar(@_) != 4;\n\t\tmy ($componentInfo, $element, $source, $length) = @_;\n\t\t$componentInfo->{$element} = join('', $source, (\"\\0\" x (&CRYPT_MAX_PKCSIZE - length($source))) );\n\t\t$componentInfo->{$element.'Len'} = $length;\n\t\treturn &CRYPT_OK;\n\t}\n\n\tsub cryptFinalizeComponents(;$\\$\\$@) {\n\t\tdie \"Usage: cryptFinalizeComponents(\\$componentInfo, \\$blob, \\$size)\\nFor more info see README file.\" if scalar(@_) != 3;\n\t\tmy ($componentInfo, $blob, $size) = @_;\n\t\tmy @rsaFields = qw(isPublicKey n nLen e eLen d dLen p pLen q qLen u uLen e1 e1Len e2 e2Len);\n\t        my @dlpFields = qw(isPublicKey p pLen q qLen g gLen y yLen x xLen);\n\t\tmy @values = ();\n\t\tmap {\n\t\t\tmy $field = $_;\n\t\t\tmy $value = $componentInfo->{$field};\n\t\t\tif ( $field =~ /Len$/  ||  $field eq 'isPublicKey' ) {\n\t\t\t    $value = sprintf(\"%08x\", $componentInfo->{$field});\n\t\t\t    $value = pack(\"H8\", join('', reverse($value =~ /(..)/g))); # inverte l'ordine dei byte e impacka\n\t\t\t}\n\t\t\tpush @values, $value;\n\t\t\t$$size += length($values[$#values]);\n\t\t    } ( scalar(keys(%{$componentInfo})) == scalar(@rsaFields) ? @rsaFields : @dlpFields );\n\t\t$$blob = join('', @values);\n\t\treturn &CRYPT_OK;\n\t}\n\n\n#############################################################################\n# SYMBOL PACKAGE EXPORT\n#############################################################################\n\n\t##### Array for cryptlib's constant names export\n\tmy @CONSTANTS = __symbolList(__PACKAGE__, '^CRYPT_');\n\n\t##### Array for cryptlib's function names export\n\tmy @FUNCTIONS = qw\t(\n\t\t\t\t\t\t\tcryptStatusError cryptStatusOK\n\t\t\t\t\t\t\tcryptInitComponents cryptDestroyComponents cryptSetComponent cryptFinalizeComponents\n\t\t\t\t\t\t\tcryptInit cryptEnd \n\t\t\t\t\t\t\tcryptQueryCapability \n\t\t\t\t\t\t\tcryptCreateContext cryptDestroyContext cryptDestroyObject \n\t\t\t\t\t\t\tcryptGenerateKey  \n\t\t\t\t\t\t\tcryptEncrypt cryptDecrypt \n\t\t\t\t\t\t\tcryptSetAttribute cryptSetAttributeString cryptGetAttribute cryptGetAttributeString cryptDeleteAttribute \n\t\t\t\t\t\t\tcryptAddRandom \n\t\t\t\t\t\t\tcryptQueryObject \n\t\t\t\t\t\t\tcryptExportKey cryptExportKeyEx cryptImportKey cryptImportKeyEx \n\t\t\t\t\t\t\tcryptCreateSignature cryptCreateSignatureEx cryptCheckSignature cryptCheckSignatureEx \n\t\t\t\t\t\t\tcryptKeysetOpen cryptKeysetClose cryptGetPublicKey cryptGetPrivateKey cryptAddPublicKey cryptAddPrivateKey cryptDeleteKey \n\t\t\t\t\t\t\tcryptCreateCert cryptDestroyCert cryptGetCertExtension cryptAddCertExtension cryptDeleteCertExtension cryptSignCert cryptCheckCert cryptImportCert cryptExportCert \n\t\t\t\t\t\t\tcryptCAAddItem cryptCAGetItem cryptCADeleteItem cryptCACertManagement \n\t\t\t\t\t\t\tcryptCreateEnvelope cryptDestroyEnvelope \n\t\t\t\t\t\t\tcryptCreateSession cryptDestroySession \n\t\t\t\t\t\t\tcryptPushData cryptFlushData cryptPopData \n\t\t\t\t\t\t\tcryptDeviceOpen cryptDeviceClose cryptDeviceQueryCapability cryptDeviceCreateContext \n\t\t\t\t\t\t\tcryptLogin cryptLogout \n\t\t\t\t\t\t);\n\t# Add deprecated functions when CRYPTLIB_VERSION prior 3.4.0\n\tpush @FUNCTIONS, qw(cryptGenerateKeyAsync cryptAsyncQuery cryptAsyncCancel) if &CRYPTLIB_VERSION < 3400;\n\n\t# Esportazione costanti e funzioni\n\tour @ISA = qw(Exporter);\n\tour @EXPORT_OK = ( @CONSTANTS , @FUNCTIONS );\n\tour @EXPORT = ();\n\tour %EXPORT_TAGS =\t( \n\t\t\t\t\t\t\tall\t\t\t=> [ @CONSTANTS , @FUNCTIONS ] ,\n\t\t\t\t\t\t\tconstants\t=> [ @CONSTANTS ] ,\n\t\t\t\t\t\t\tfunctions\t=> [ @FUNCTIONS ]\n\t\t\t\t\t\t);\n\n\nsub AUTOLOAD {\n    # This AUTOLOAD is used to 'autoload' constants from the constant()\n    # XS function.\n\n    my $constname;\n    our $AUTOLOAD;\n    ($constname = $AUTOLOAD) =~ s/.*:://;\n    croak \"&PerlCryptLib::constant not defined\" if $constname eq 'constant';\n    my ($error, $val) = constant($constname);\n    if ($error) { croak $error; }\n    {\n\tno strict 'refs';\n\t# Fixed between 5.005_53 and 5.005_61\n#XXX\tif ($] >= 5.00561) {\n#XXX\t    *$AUTOLOAD = sub () { $val };\n#XXX\t}\n#XXX\telse {\n\t    *$AUTOLOAD = sub { $val };\n#XXX\t}\n    }\n    goto &$AUTOLOAD;\n}\n\nrequire XSLoader;\nXSLoader::load('PerlCryptLib', $VERSION);\n## Add deprecated functions if CRYPTLIB_VERSION is less than 3.4.0\n#XSLoader::load('PerlCryptLib-deprecated-340', $VERSION) if &CRYPTLIB_VERSION < 3400;\n\nif ( __FILE__ eq \"$0\" ) {\n\t# TEST PACKAGE SPACE\n}\n\n1;\n__END__\n\n\n=head1 NAME\n\nPerlCryptLib - Perl interface to Peter Guttman's cryptlib API\n\n=head1 DESCRIPTION\n\nPerlCryptLib is an interface module to access cryptlib API.\n\n=over 8\n\ncryptlib (Copyright 1992-2005 Peter Gutmann. All rights reserved.) is a powerful \nencryption and security software toolkit that allows even inexperienced \ncrypto-programmers to easily add world-leading encryption and authentication \nservices to their software.\n\nFor more information about cryptlib features and state-of-the-art, please visit\nits official web-site at:\n\n=over 4\n\n=item * http://www.cs.auckland.ac.nz/~pgut001/cryptlib\n\n=back\n\n=back\n\n=head1 INSTALLATION\n\nStarting from version 1.04, PerlCryptLib got the capability to match the correct \nversion of the 'cryptlib' library used by the guest system. \nThis is done translating on-the-fly the cryptlib.h header file into a \ncorrespondent Perl header file (named PerlCryptLib.ph) that will be used by\nthe main module.\nPerlCryptLib need to know the path to cryptlib.h header file for the libcl\ninstalled in the system.\nYou can set (export) environment variable B<PERL_CRYPT_LIB_HEADER> or,\nalternatively, Makefile.PL try itself to search for B<cryptlib.h> in B</usr> \nand B</home> directories.\nIf it found more than one version of B<cryptlib.h>, it will use the one with greater version number.\n\n perl Makefile.PL\n make\n make test TEST_VERBOSE=1  # or, simply, the canonical  make test\n sudo make install\n\n=head1 SYNOPSIS\n\n use PerlCryptLib qw(:all);\n\n my $envelope = CRYPT_ENVELOPE;\n if ( cryptInit() == CRYPT_OK ) {\n   if ( cryptCreateEnvelope($envelope, \n                            CRYPT_UNUSED, \n                            CRYPT_FORMAT_CRYPTLIB) == CRYPT_OK ) {\n\n     # set some attributes with cryptSetAttribute() or cryptSetAttributeString()\n     # set some other crypto-stuff\n     # push or pop data with cryptPushData() and cryptPopData()\n\n     cryptDestroyEnvelope($envelope);\n   }\n   cryptEnd();\n }\n\n=head2 Notes\n\ncryptUIDisplayCert() and cryptUIGenerateKey() cryptlib functions are \nnot implemented.\n\n=head1 EXPORT/IMPORT\n\nPerlCryptLib doesn't export anything by default.\nYou can choose to explicitly import specifics exported tags:\n\n=over 4\n\n=item :constants\n\nall of the CRYPT_* cryptlib constants\n\n=item :functions\n\nall of the crypt* cryptlib functions\n\n=item :all\n\nall of the cryptlib constants and functions\n\n=back\n\nFor example, to import only functions name:\n\n use PerlCryptLib ':functions';\n\nAlternatively, you can import such functions or constants by specifying each\nof them in the 'use' statement:\n\n use PerlCryptLib qw(cryptInit cryptEnd CRYPT_OK);\n\n=head1 CONVENTIONS\n\n=head2 Object-type declaration\n\n=over 4\n\ncryptlib object-handles MUST BE INITIALIZED with the appropriated object-type \nconstant (CRYPT_CERTIFICATE, CRYPT_CONTEXT, CRYPT_DEVICE, CRYPT_ENVELOPE, \nCRYPT_KEYSET, CRYPT_SESSION, CRYPT_USER, CRYPT_HANDLE) or, at least, with a\nnumeric value (generally 0).\n\nSo, using\n\n my $envelope = CRYPT_ENVELOPE;\n my $context = CRYPT_CONTEXT;\n my $certificate = CRYPT_CERTIFICATE;\n \nis the same as using\n\n my $envelope = 0;\n my $context = 0;\n my $certificate = 0;\n\nbut is much more comprehensive.\n\n=back\n\n=head2 Pass-by-reference\n\n=over 4\n\nTo pass-by-reference cryptlib object-handles, as shown in the above \nexample in SYNOPSIS section, it's not necessary to use the 'back-slash' \nreference operator ('\\').\n\n=back\n\n=head2 Buffers\n\n=over 4\n\nTo handle binary buffers (i.e., while enveloping data), you need to initialize \nthem \"allocating\" the needed space, for example using:\n \n my $maxLength = 1024;\n my $key = ' ' x $maxLength;\n cryptExportKey($key, $maxLength, $keyLength, $context, $cert);\n\n=back\n\n=head2 NULL values\n\n=over 4\n\nNULL values can be handled in different ways:\n\n # Those three calls are all valid calls\n use constant NULL => 0x0;\n $null = 0x0;\n cryptGetPublicKey($cryptKeyset, $cert, CRYPT_KEYID_NONE, 0);\n cryptGetPublicKey($cryptKeyset, $cert, CRYPT_KEYID_NONE, NULL);\n cryptGetPublicKey($cryptKeyset, $cert, CRYPT_KEYID_NONE, $null); \n\nHowever, when used in pass-by-reference calls, MUST be declared as 0x0 \nscalar values:\n\n $null = 0x0;\n cryptExportKey($null, 0, $maxLength, $context, $cert);\n\n=back\n\n=head2 Accessing low-level components\n\n=over 4\n\nIn order to allow the access to low-level components, I've made some small \nchanges to the cryptlib macro cryptSetComponent(), for which Perl syntax became:\n \n cryptSetComponent($componentInfo, $element, $source, $length)\n \nwhere $componentInfo is the data-structure itself and $element is the \ndata-structure element-name to set.\nIn addition I've added a NEW low-level macro to retrieve data-structure in\nthe appropriated format:\n\n cryptFinalizeComponents($componentInfo, $blob, $size)\n  \nHere is an example \"translated\" in PerlCryptLib:\n  \n ##### Create objects\n $cryptContext = CRYPT_CONTEXT;\n $rsaKey = CRYPT_PKCINFO_RSA;\n\n ##### Initialize objects\n cryptCreateContext($cryptContext, $cryptUser, CRYPT_ALGO_RSA);\n cryptSetAttributeString($cryptContext, CRYPT_CTXINFO_LABEL, \"RSA key\", 7);\n cryptInitComponents($rsaKey, CRYPT_KEYTYPE_PRIVATE);\n\n ##### Set data-structure elements: note arguments syntax\n cryptSetComponent($rsaKey, 'n', $modulus, 2048);\n cryptSetComponent($rsaKey, 'e', $pubExponent, 17);\n cryptSetComponent($rsaKey, 'd', $privExponent, 2047);\n cryptSetComponent($rsaKey, 'p', $primeFactor1, 1024);\n cryptSetComponent($rsaKey, 'q', $primeFactor2, 1024);\n cryptSetComponent($rsaKey, 'u', $multInverse, 1020);\n cryptSetComponent($rsaKey, 'e1', $privExponent1, 1024);\n cryptSetComponent($rsaKey, 'e2', $privExponent2, 1019);\n \n ##### Finalize component to retrieve data to pass to cryptSetAttributeString\n $rsaKeyBlob = '';\n $rsaKeyBlobSize = 0;\n cryptFinalizeComponents($rsaKey, $rsaKeyBlob, $rsaKeyBlobSize);\n cryptSetAttributeString($cryptContext, CRYPT_CTXINFO_KEY_COMPONENTS,\n                         $rsaKeyBlob, $rsaKeyBlobSize );\n \n ##### Destroy objects\n cryptDestroyComponents($rsaKey);\n cryptDestroyContext($cryptContext);\n\nNote: to access single data-structure elements (if really needed) you can do \nas follow:\n\n print \"rsaKey modulus length: \", $rsaKey->{nLen}, \"\\n\";\n\n=back\n\n=head2 Querying objects\n\n=over 4\n\nTo query objects such exported keys, signatures or cryptlib capabilities,\nyou can use standard functions cryptQueryObject() and cryptQueryCapability() \nas follow:\n\n $cryptObjectInfo = CRYPT_OBJECT_INFO;\n cryptQueryObject($encryptedKey, $encryptedKeyLength, $cryptObjectInfo);\n if ( $cryptObjectInfo->{objectType} == CRYPT_OBJECT_ENCRYPTED_KEY ) {\n     warn \"Import the key using conventional encryption!\", \"\\n\";\n }\n\n $cryptQueryInfo = CRYPT_QUERY_INFO;\n cryptQueryCapability(CRYPT_ALGO_3DES, $cryptQueryInfo);\n print \"Algo-name: \", $cryptQueryInfo->{algoName}, \"\\n\";\n\n=back\n\n=head1 PREREQUIREMENT\n\n=over 4\n\n=item * cryptlib v. 3.2.2 (or later)\n\nCRYPTLIB Security Toolkit(c) by Peter Guttman\n\n=back\n\n=head1 SEE ALSO\n\nSee Peter Guttman's cryptlib web site:\n\n=over 4\n\n=item * http://www.cs.auckland.ac.nz/~pgut001/cryptlib/\n\n=back\n\nand cryptlib official mailing-list:\n\n=over 4\n\n=item * http://news.gmane.org/gmane.comp.encryption.cryptlib\n\n=back\n\n=head1 BUGS AND REQUESTS\n\nPlease report any bugs or feature requests to perlcryptlib@gmail.com, or \nthrough the web interface at http://rt.cpan.org/Public/.\nI will be notified, and then you'll automatically be notified of progress on \nyour bug as I make changes.\n\n=head1 AUTHOR\n\nAlvaro Livraghi, <perlcryptlib@gmail.com>\n\n=head1 COPYRIGHT AND LICENSE\n\nCopyright (C) 2006-2010 Alvaro Livraghi. All Rights Reserved.\n\nThis library is free software; you can redistribute it and/or modify\nit under the same terms as Perl itself. \n\n=cut\n\n"
  },
  {
    "path": "deps/cl345/bindings/PerlCryptLib.xs",
    "content": "/*******************************************************************************\n\n Perl extesione interface (XS) to 'cryptlib' library (PerlCryptLib)\n\n Copyright (C) 2006-2010 Alvaro Livraghi. All Rights Reserved.\n Alvaro Livraghi, <perlcryptlib@gmail.com>\n\n*******************************************************************************/\n\n#include \"EXTERN.h\"\n#include \"perl.h\"\n#include \"XSUB.h\"\n#include <stdlib.h>\n\n#include \"ppport.h\"\n\n#include CRYPTLIB_H\n\n#include \"const-c.inc\"\n\nMODULE = PerlCryptLib\t\tPACKAGE = PerlCryptLib\t\t\n\nINCLUDE: const-xs.inc\n\n################################################################################\n#                                                                              #\n# Funzioni di utilita' generale                                                #\n#                                                                              #\n################################################################################\n\n#\n# Simula (per Perl) la seguente operazione su un generico buffer:\n#\n#      void * buffer = \"Questo e' un buffer\";\n#      buffer += offset;\n#\nvoid * shift_buffer(buffer, length, offset)\n\tvoid * buffer;\n\tint length;\n\tconst int offset;\n\tINIT:\n\t\tvoid * __buffer;\n\tCODE:\n\t\t__buffer = (void *)malloc(length);\n\t\tif ( __buffer != 0 ) {\n\t\t\tlength -= offset;\n\t\t\tbuffer += offset;\n\t\t\tmemcpy(__buffer, buffer, length);\n\t\t\tsv_setpvn(ST(0), __buffer, length);\n\t\t\tRETVAL = newSVpvn(__buffer, length);\n\t\t\tfree(__buffer);\n\t\t}\n\tOUTPUT:\n\t\tlength\n\n\n\n\n################################################################################\n#                                                                              #\n# Trascodifica funzioni di cryptlib                                            #\n#                                                                              #\n################################################################################\n\n\nint cryptInit()\n\n\nint cryptEnd()\n\n\nint cryptLogin(user, name, password)\n\tint user;\n\tconst char * name;\n\tconst char * password;\n\tCODE:\n\t\tRETVAL = cryptLogin(&user, name, password);\n\tOUTPUT:\n\t\tRETVAL\n\t\tuser\n\n\nint cryptLogout(user)\n\tconst int user;\n\n\nint cryptCreateEnvelope(cryptEnvelope, cryptUser, formatType)\n\tint cryptEnvelope;\n\tconst int cryptUser;\n\tconst int formatType;\n\tCODE:\n\t\tRETVAL = cryptCreateEnvelope(&cryptEnvelope, cryptUser, formatType);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptEnvelope\n\n\nint cryptDestroyEnvelope(cryptEnvelope)\n\tconst int cryptEnvelope;\n\n\nint cryptSetAttribute(cryptEnvelope, attributeType, value)\n\tconst int cryptEnvelope;\n\tconst int attributeType;\n\tconst int value;\n\n\nint cryptSetAttributeString(cryptEnvelope, attributeType, value, valueLength)\n\tconst int cryptEnvelope;\n\tconst int attributeType;\n\tconst void * value;\n\tconst int valueLength;\n\n\nint cryptGetAttribute(cryptObject, attributeType, value)\n\tconst int cryptObject;\n\tconst int attributeType;\n\tint value;\n\tCODE:\n\t\tRETVAL = cryptGetAttribute(cryptObject, attributeType, &value);\n\tOUTPUT:\n\t\tRETVAL\n\t\tvalue\n\n\nint cryptGetAttributeString(cryptObject, attributeType, value, valueLength)\n\tconst int cryptObject;\n\tconst int attributeType;\n\tvoid * value = (SvIOK(ST(2)) ? (void *)SvIV(ST(2)) : (void *)SvPV_nolen(ST(2)));\n\tint valueLength;\n\tCODE:\n\t\tRETVAL = cryptGetAttributeString(cryptObject, attributeType, value, &valueLength);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(2), value, valueLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tvalueLength\n\n\nint cryptPushData(cryptEnvelope, buffer, length, bytesCopied)\n\tconst int cryptEnvelope;\n\tconst void * buffer = (SvIOK(ST(1)) ? (const void *)SvIV(ST(1)) : (const void *)SvPV_nolen(ST(1)));\n\tconst int length;\n\tint bytesCopied;\n\tCODE:\n\t\tRETVAL = cryptPushData(cryptEnvelope, buffer, length, &bytesCopied);\n\tOUTPUT:\n\t\tRETVAL\n\t\tbytesCopied\n\n\nint cryptFlushData(cryptEnvelope)\n\tconst int cryptEnvelope;\n\n\nint cryptPopData(cryptEnvelope, buffer, length, bytesCopied)\n\tconst int cryptEnvelope;\n\tvoid * buffer;\n\tconst int length;\n\tint bytesCopied;\n\tCODE:\n\t\tRETVAL = cryptPopData(cryptEnvelope, buffer, length, &bytesCopied);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(1), buffer, bytesCopied);\n\tOUTPUT:\n\t\tRETVAL\n\t\tbytesCopied\n\n\nint cryptCreateContext(cryptContext, cryptUser, cryptAlgo)\n\tint cryptContext;\n\tconst int cryptUser;\n\tconst int cryptAlgo;\n\tCODE:\n\t\tRETVAL = cryptCreateContext(&cryptContext, cryptUser, cryptAlgo);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptContext\n\n\nint cryptDestroyContext(cryptContext)\n\tconst int cryptContext;\n\n\nint cryptKeysetOpen(keyset, cryptUser, keysetType, name, options)\n\tint keyset;\n\tconst int cryptUser;\n\tconst int keysetType;\n\tconst char * name;\n\tconst int options;\n\tCODE:\n\t\tRETVAL = cryptKeysetOpen(&keyset, cryptUser, keysetType, name, options);\n\tOUTPUT:\n\t\tRETVAL\n\t\tkeyset\n\n\nint cryptKeysetClose(keyset)\n\tconst int keyset\n\n\nint cryptGenerateKey(cryptContext)\n\tconst int cryptContext\n\n\nint cryptExportKey(encryptedKey, encryptedKeyMaxLength, encryptedKeyLength, exportKey, sessionKeyContext)\n\tvoid * encryptedKey = (SvIOK(ST(0)) ? (void *)SvIV(ST(0)) : (void *)SvPV_nolen(ST(0)));\n\tconst int encryptedKeyMaxLength;\n\tint encryptedKeyLength;\n\tconst int exportKey;\n\tconst int sessionKeyContext;\n\tCODE:\n\t\tRETVAL = cryptExportKey(encryptedKey, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(0), encryptedKey, encryptedKeyLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tencryptedKeyLength\n\n\nint cryptCreateCert(cryptCert, cryptUser, certType)\n\tint cryptCert;\n\tconst int cryptUser;\n\tconst int certType;\n\tCODE:\n\t\tRETVAL = cryptCreateCert(&cryptCert, cryptUser, certType);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptCert\n\n\nint cryptSignCert(certificate, signContext)\n\tconst int certificate;\n\tconst int signContext;\n\n\nint cryptImportCert(certObject, certObjectLength, cryptUser, certificate)\n\tconst void * certObject;\n\tconst int certObjectLength;\n\tconst int cryptUser;\n\tint certificate;\n\tCODE:\n\t\tRETVAL = cryptImportCert(certObject, certObjectLength, cryptUser, &certificate);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcertificate\n\n\nint cryptExportCert(certObject, certObjectMaxLength, certObjectLength, certFormatType, certificate)\n\tvoid * certObject = (SvIOK(ST(0)) ? (void *)SvIV(ST(0)) : (void *)SvPV_nolen(ST(0)));\n\tconst int certObjectMaxLength;\n\tint certObjectLength;\n\tconst int certFormatType;\n\tconst int certificate;\n\tCODE:\n\t\tRETVAL = cryptExportCert(certObject, certObjectMaxLength, &certObjectLength, certFormatType, certificate);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(0), certObject, certObjectLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcertObjectLength\n\n\nint cryptCheckCert(certRequest, cryptCA)\n\tconst int certRequest;\n\tconst int cryptCA;\n\n\nint cryptDestroyCert(cryptCert)\n\tconst int cryptCert;\n\n\nint cryptImportKey(encryptedKey, encryptedKeyLength, importContext, sessionKeyContext)\n\tconst void * encryptedKey;\n\tconst int encryptedKeyLength;\n\tconst int importContext;\n\tconst int sessionKeyContext;\n\n\nint cryptImportKeyEx(encryptedKey, encryptedKeyLength, importContext, sessionKeyContext, returnedContext)\n\tconst void * encryptedKey;\n\tconst int encryptedKeyLength;\n\tconst int importContext;\n\tconst int sessionKeyContext;\n\tint returnedContext;\n\tCODE:\n\t\tRETVAL = cryptImportKeyEx(encryptedKey, encryptedKeyLength, importContext, sessionKeyContext, &returnedContext);\n\tOUTPUT:\n\t\tRETVAL\n\t\treturnedContext\n\n\nint cryptAddPublicKey(keyset, certificate)\n\tconst int keyset;\n\tconst int certificate;\n\n\nint cryptAddPrivateKey(keyset, cryptKey, password)\n\tconst int keyset;\n\tconst int cryptKey;\n\tconst char * password;\n\n\nint cryptGetPrivateKey(cryptHandle, cryptContext, keyIDtype, keyID, password)\n\tconst int cryptHandle;\n\tint cryptContext;\n\tconst int keyIDtype;\n\tconst void * keyID = (SvIOK(ST(3)) ? (const void *)SvIV(ST(3)) : (const void *)SvPV_nolen(ST(3)));\n\tconst char * password = (SvIOK(ST(4)) ? (const char *)SvIV(ST(4)) : (const char *)SvPV_nolen(ST(4)));\n\tCODE:\n\t\tRETVAL = cryptGetPrivateKey(cryptHandle, &cryptContext, keyIDtype, keyID, password);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptContext\n\n\nint cryptGetPublicKey(cryptObject, publicKey, keyIDtype, keyID)\n\tconst int cryptObject;\n\tint publicKey;\n\tconst int keyIDtype;\n\tconst void * keyID = (SvIOK(ST(3)) ? (const void *)SvIV(ST(3)) : (const void *)SvPV_nolen(ST(3))); /* Consente di passare 0 come NULL */\n\tCODE:\n\t\tRETVAL = cryptGetPublicKey(cryptObject, &publicKey, keyIDtype, keyID);\n\tOUTPUT:\n\t\tRETVAL\n\t\tpublicKey\n\n\nint cryptAddCertExtension(certificate, oid, criticalFlag, extension, extensionLength)\n\tconst int certificate;\n\tconst char * oid;\n\tconst int criticalFlag;\n\tconst void * extension;\n\tconst int extensionLength;\n\n\nint cryptAddRandom(randomData, randomDataLength)\n\tconst void * randomData = (SvIOK(ST(0)) ? (const void *)SvIV(ST(0)) : (const void *)SvPV_nolen(ST(0)));\n\tconst int randomDataLength;\n\n\nint cryptCAAddItem(keyset, certificate)\n\tconst int keyset;\n\tconst int certificate;\n\n\nint cryptCADeleteItem(keyset, certType, keyIDtype, keyID)\n\tconst int keyset;\n\tconst int certType;\n\tconst int keyIDtype;\n\tconst void * keyID;\n\n\nint cryptCACertManagement(cryptCert, action, keyset, caKey, certRequest)\n\tint cryptCert;\n\tconst int action;\n\tconst int keyset;\n\tconst int caKey;\n\tconst int certRequest;\n\tCODE:\n\t\tRETVAL = cryptCACertManagement(&cryptCert, action, keyset, caKey, certRequest);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptCert\n\n\nint cryptCAGetItem(keyset, certificate, certType, keyIDtype, keyID)\n\tconst int keyset;\n\tint certificate;\n\tconst int certType;\n\tconst int keyIDtype;\n\tconst void * keyID = (SvIOK(ST(4)) ? (const void *)SvIV(ST(4)) : (const void *)SvPV_nolen(ST(4)));\n\tCODE:\n\t\tRETVAL = cryptCAGetItem(keyset, &certificate, certType, keyIDtype, keyID);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcertificate\n\n\nint cryptCheckSignature(signature, signatureLength, sigCheckKey, hashContext)\n\tconst void * signature;\n\tconst int signatureLength;\n\tconst int sigCheckKey;\n\tconst int hashContext;\n\n\nint cryptCheckSignatureEx(signature, signatureLength, sigCheckKey, hashContext, extraData)\n\tconst void * signature;\n\tconst int signatureLength;\n\tconst int sigCheckKey;\n\tconst int hashContext;\n\tint extraData;\n\tCODE:\n\t\tRETVAL = cryptCheckSignatureEx(signature, signatureLength, sigCheckKey, hashContext, &extraData);\n\tOUTPUT:\n\t\tRETVAL\n\t\textraData\n\n\nint cryptCreateSession(cryptSession, cryptUser, sessionType)\n\tint cryptSession;\n\tconst int cryptUser;\n\tconst int sessionType;\n\tCODE:\n\t\tRETVAL = cryptCreateSession(&cryptSession, cryptUser, sessionType);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptSession\n\n\nint cryptCreateSignature(signature, signatureMaxLength, signatureLength, signContext, hashContext)\n\tvoid * signature = (SvIOK(ST(0)) ? (void *)SvIV(ST(0)) : (void *)SvPV_nolen(ST(0)));\n\tconst int signatureMaxLength;\n\tint signatureLength;\n\tconst int signContext;\n\tconst int hashContext;\n\tCODE:\n\t\tRETVAL = cryptCreateSignature(signature, signatureMaxLength, &signatureLength, signContext, hashContext);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(0), signature, signatureLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tsignatureLength\n\n\nint cryptCreateSignatureEx(signature, signatureMaxLength, signatureLength, formatType, signContext, hashContext, extraData)\n\tvoid * signature = (SvIOK(ST(0)) ? (void *)SvIV(ST(0)) : (void *)SvPV_nolen(ST(0)));\n\tconst int signatureMaxLength;\n\tint signatureLength;\n\tconst int formatType;\n\tconst int signContext;\n\tconst int hashContext;\n\tconst int extraData;\n\tCODE:\n\t\tRETVAL = cryptCreateSignatureEx(signature, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(0), signature, signatureLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tsignatureLength\n\n\nint cryptDecrypt(cryptContext, buffer, length)\n\tconst int cryptContext;\n\tvoid * buffer;\n\tconst int length;\n\tCODE:\n\t\tRETVAL = cryptDecrypt(cryptContext, buffer, length);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(1), buffer, length);\n\tOUTPUT:\n\t\tRETVAL\n\n\nint cryptDeleteAttribute(cryptObject, attributeType)\n\tconst int cryptObject;\n\tconst int attributeType;\n\n\nint cryptDeleteCertExtension(certificate, oid)\n\tconst int certificate;\n\tconst char * oid;\n\n\nint cryptDeleteKey(cryptObject, keyIDtype, keyID)\n\tconst int cryptObject;\n\tconst int keyIDtype;\n\tconst void * keyID;\n\n\nint cryptDestroyObject(cryptObject)\n\tconst int cryptObject;\n\n\nint cryptDestroySession(cryptSession)\n\tconst int cryptSession;\n\n\nint cryptDeviceClose(device)\n\tconst int device;\n\n\nint cryptDeviceCreateContext(cryptDevice, cryptContext, cryptAlgo)\n\tconst int cryptDevice;\n\tint cryptContext;\n\tconst int cryptAlgo;\n\tCODE:\n\t\tRETVAL = cryptDeviceCreateContext(cryptDevice, &cryptContext, cryptAlgo);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcryptContext\n\n\nint cryptDeviceOpen(device, cryptUser, deviceType, name)\n\tint device;\n\tconst int cryptUser;\n\tconst int deviceType;\n\tconst char * name = (SvIOK(ST(0)) ? (const char *)SvIV(ST(0)) : (const char *)SvPV_nolen(ST(0)));\n\tCODE:\n\t\tRETVAL = cryptDeviceOpen(&device, cryptUser, deviceType, name);\n\tOUTPUT:\n\t\tRETVAL\n\t\tdevice\n\n\nint cryptDeviceQueryCapability(cryptDevice, cryptAlgo, cryptQueryInfo)\n\tconst int cryptDevice;\n\tconst int cryptAlgo;\n\tHV * cryptQueryInfo;\n\tINIT:\n\t\tCRYPT_QUERY_INFO dummy;\n\tCODE:\n\t\tRETVAL = cryptDeviceQueryCapability(cryptDevice, cryptAlgo, &dummy);\n\t\tif ( RETVAL == CRYPT_OK ) {\n\t\t\thv_store(cryptQueryInfo, \"algoName\",    8, newSVpv(dummy.algoName, strlen(dummy.algoName)), 0);\n\t\t\thv_store(cryptQueryInfo, \"blockSize\",   9, newSVnv(dummy.blockSize), 0);\n\t\t\thv_store(cryptQueryInfo, \"minKeySize\", 10, newSVnv(dummy.minKeySize), 0);\n\t\t\thv_store(cryptQueryInfo, \"keySize\",     7, newSVnv(dummy.keySize), 0);\n\t\t\thv_store(cryptQueryInfo, \"maxKeySize\", 10, newSVnv(dummy.maxKeySize), 0);\n\t\t}\n\tOUTPUT:\n\t\tRETVAL\n\n\nint cryptEncrypt(cryptContext, buffer, length)\n\tconst int cryptContext;\n\tvoid * buffer;\n\tconst int length;\n\tCODE:\n\t\tRETVAL = cryptEncrypt(cryptContext, buffer, length);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(1), buffer, length);\n\tOUTPUT:\n\t\tRETVAL\n\n\nint cryptExportKeyEx(encryptedKey, encryptedKeyMaxLength, encryptedKeyLength, formatType, exportKey, sessionKeyContext)\n\tvoid * encryptedKey = (SvIOK(ST(0)) ? (void *)SvIV(ST(0)) : (void *)SvPV_nolen(ST(0)));\n\tconst int encryptedKeyMaxLength;\n\tint encryptedKeyLength;\n\tconst int formatType;\n\tconst int exportKey;\n\tconst int sessionKeyContext;\n\tCODE:\n\t\tRETVAL = cryptExportKeyEx(encryptedKey, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(0), encryptedKey, encryptedKeyLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tencryptedKeyLength\n\n\nint cryptGetCertExtension(certificate, oid, criticalFlag, extension, extensionMaxLength, extensionLength)\n\tconst int certificate;\n\tconst char * oid;\n\tint criticalFlag;\n\tvoid * extension;\n\tconst int extensionMaxLength;\n\tint extensionLength;\n\tCODE:\n\t\tRETVAL = cryptGetCertExtension(certificate, oid, &criticalFlag, extension, extensionMaxLength, &extensionLength);\n\t\tif ( RETVAL == CRYPT_OK ) sv_setpvn(ST(3), extension, extensionLength);\n\tOUTPUT:\n\t\tRETVAL\n\t\tcriticalFlag\n\t\textensionLength\n\n\nint cryptQueryCapability(cryptAlgo, cryptQueryInfo)\n\tconst int cryptAlgo;\n\tHV * cryptQueryInfo;\n\tINIT:\n\t\tCRYPT_QUERY_INFO dummy;\n\tCODE:\n\t\tRETVAL = cryptQueryCapability(cryptAlgo, &dummy);\n\t\tif ( RETVAL == CRYPT_OK ) {\n\t\t\thv_store(cryptQueryInfo, \"algoName\",    8, newSVpv(dummy.algoName, strlen(dummy.algoName)), 0);\n\t\t\thv_store(cryptQueryInfo, \"blockSize\",   9, newSVnv(dummy.blockSize), 0);\n\t\t\thv_store(cryptQueryInfo, \"minKeySize\", 10, newSVnv(dummy.minKeySize), 0);\n\t\t\thv_store(cryptQueryInfo, \"keySize\",     7, newSVnv(dummy.keySize), 0);\n\t\t\thv_store(cryptQueryInfo, \"maxKeySize\", 10, newSVnv(dummy.maxKeySize), 0);\n\t\t}\n\tOUTPUT:\n\t\tRETVAL\n\n\nint cryptQueryObject(objectData, objectDataLength, cryptObjectInfo)\n\tconst void * objectData;\n\tconst int objectDataLength;\n\tHV * cryptObjectInfo;\n\tINIT:\n\t\tCRYPT_OBJECT_INFO dummy;\n\tCODE:\n\t\tRETVAL = cryptQueryObject(objectData, objectDataLength, &dummy);\n\t\tif ( RETVAL == CRYPT_OK ) {\n\t\t\thv_store(cryptObjectInfo, \"objectType\", 10, newSVnv(dummy.objectType), 0);\n\t\t\thv_store(cryptObjectInfo, \"cryptAlgo\",   9, newSVnv(dummy.cryptAlgo), 0);\n\t\t\thv_store(cryptObjectInfo, \"cryptMode\",   9, newSVnv(dummy.cryptMode), 0);\n\t\t\thv_store(cryptObjectInfo, \"hashAlgo\",    8, newSVnv(dummy.hashAlgo), 0);\n\t\t\thv_store(cryptObjectInfo, \"salt\",        4, newSVpv(dummy.salt, dummy.saltSize), 0);\n\t\t\thv_store(cryptObjectInfo, \"saltSize\",    8, newSVnv(dummy.saltSize), 0);\n\t\t}\n\tOUTPUT:\n\t\tRETVAL\n\n# Add deprecated functions when CRYPTLIB_VERSION prior 3.4.0\n#if CRYPTLIB_VERSION < 3400\n\nint cryptAsyncCancel(cryptObject)\n\tconst int cryptObject;\n\n\nint cryptAsyncQuery(cryptObject)\n\tconst int cryptObject;\n\n\nint cryptGenerateKeyAsync(cryptContext)\n\tconst int cryptContext;\n\n#endif\n"
  },
  {
    "path": "deps/cl345/bindings/VMBuild.exec",
    "content": "&TRACE ON\n\n* Set the LE runtime library and various global values\n\nGLOBAL LOADLIB SCEERUN\n\n&LIBNAME = CRYPTLIB\n\n* Compile all cryptlib modules\n\n&TYPE Building cryptlib modules...\n\n* Main\nEXEC CC cryptapi c (def(__VMCMS__) lo\nEXEC CC cryptcfg c (def(__VMCMS__) lo\nEXEC CC cryptcrt c (def(__VMCMS__) lo\nEXEC CC cryptctx c (def(__VMCMS__) lo\nEXEC CC cryptdev c (def(__VMCMS__) lo\nEXEC CC cryptenv c (def(__VMCMS__) lo\nEXEC CC cryptkey c (def(__VMCMS__) lo\nEXEC CC cryptlib c (def(__VMCMS__) lo\nEXEC CC cryptses c (def(__VMCMS__) lo\nEXEC CC cryptusr c (def(__VMCMS__) lo\n\n* Bignum\nEXEC CC bn_add c (def(__VMCMS__) lo\nEXEC CC bn_ctx c (def(__VMCMS__) lo\nEXEC CC bn_div c (def(__VMCMS__) lo\nEXEC CC bn_exp c (def(__VMCMS__) lo\nEXEC CC bn_exp2 c (def(__VMCMS__) lo\nEXEC CC bn_gcd c (def(__VMCMS__) lo\nEXEC CC bn_lib c (def(__VMCMS__) lo\nEXEC CC bn_mod c (def(__VMCMS__) lo\nEXEC CC bn_mont c (def(__VMCMS__) lo\nEXEC CC bn_mul c (def(__VMCMS__) lo\nEXEC CC bn_recp c (def(__VMCMS__) lo\nEXEC CC bn_shift c (def(__VMCMS__) lo\nEXEC CC bn_sqr c (def(__VMCMS__) lo\nEXEC CC bn_word c (def(__VMCMS__) lo\n\n* Cert\nEXEC CC certrev c (def(__VMCMS__) lo\nEXEC CC certschk c (def(__VMCMS__) lo\nEXEC CC certsign c (def(__VMCMS__) lo\nEXEC CC certval c (def(__VMCMS__) lo\nEXEC CC chain c (def(__VMCMS__) lo\nEXEC CC chk_cert c (def(__VMCMS__) lo\nEXEC CC chk_chn c (def(__VMCMS__) lo\nEXEC CC chk_use c (def(__VMCMS__) lo\nEXEC CC comp_get c (def(__VMCMS__) lo\nEXEC CC comp_set c (def(__VMCMS__) lo\nEXEC CC dn c (def(__VMCMS__) lo\nEXEC CC dnstring c (def(__VMCMS__) lo\nEXEC CC ext c (def(__VMCMS__) lo\nEXEC CC ext_add c (def(__VMCMS__) lo\nEXEC CC ext_chk c (def(__VMCMS__) lo\nEXEC CC ext_copy c (def(__VMCMS__) lo\nEXEC CC ext_def c (def(__VMCMS__) lo\nEXEC CC ext_rd c (def(__VMCMS__) lo\nEXEC CC ext_wr c (def(__VMCMS__) lo\nEXEC CC imp_exp c (def(__VMCMS__) lo\nEXEC CC read c (def(__VMCMS__) lo\nEXEC CC trustmgr c (def(__VMCMS__) lo\nEXEC CC write c (def(__VMCMS__) lo\n\n* Context\nEXEC CC ctx_3des c (def(__VMCMS__) lo\nEXEC CC ctx_aes c (def(__VMCMS__) lo\nEXEC CC ctx_bf c (def(__VMCMS__) lo\nEXEC CC ctx_cast c (def(__VMCMS__) lo\nEXEC CC ctx_des c (def(__VMCMS__) lo\nEXEC CC ctx_dh c (def(__VMCMS__) lo\nEXEC CC ctx_dsa c (def(__VMCMS__) lo\nEXEC CC ctx_elg c (def(__VMCMS__) lo\nEXEC CC ctx_hmd5 c (def(__VMCMS__) lo\nEXEC CC ctx_hrmd c (def(__VMCMS__) lo\nEXEC CC ctx_hsha c (def(__VMCMS__) lo\nEXEC CC ctx_idea c (def(__VMCMS__) lo\nEXEC CC ctx_md2 c (def(__VMCMS__) lo\nEXEC CC ctx_md4 c (def(__VMCMS__) lo\nEXEC CC ctx_md5 c (def(__VMCMS__) lo\nEXEC CC ctx_misc c (def(__VMCMS__) lo\nEXEC CC ctx_rc2 c (def(__VMCMS__) lo\nEXEC CC ctx_rc4 c (def(__VMCMS__) lo\nEXEC CC ctx_rc5 c (def(__VMCMS__) lo\nEXEC CC ctx_ripe c (def(__VMCMS__) lo\nEXEC CC ctx_rsa c (def(__VMCMS__) lo\nEXEC CC ctx_sha c (def(__VMCMS__) lo\nEXEC CC ctx_sha2 c (def(__VMCMS__) lo\nEXEC CC ctx_skip c (def(__VMCMS__) lo\nEXEC CC kg_dlp c (def(__VMCMS__) lo\nEXEC CC kg_prime c (def(__VMCMS__) lo\nEXEC CC kg_rsa c (def(__VMCMS__) lo\nEXEC CC keyload c (def(__VMCMS__) lo\nEXEC CC key_rd c (def(__VMCMS__) lo\nEXEC CC key_wr c (def(__VMCMS__) lo\n\n* Crypt (encryption algorithms)\nEXEC CC aes_modes c (def(__VMCMS__) lo\nEXEC CC aescrypt c (def(__VMCMS__) lo\nEXEC CC aeskey c (def(__VMCMS__) lo\nEXEC CC aestab c (def(__VMCMS__) lo\nEXEC CC bfecb c (def(__VMCMS__) lo\nEXEC CC bfenc c (def(__VMCMS__) lo\nEXEC CC bfskey c (def(__VMCMS__) lo\nEXEC CC castecb c (def(__VMCMS__) lo\nEXEC CC castenc c (def(__VMCMS__) lo\nEXEC CC castskey c (def(__VMCMS__) lo\nEXEC CC descbc c (def(__VMCMS__) lo\nEXEC CC desecb c (def(__VMCMS__) lo\nEXEC CC desecb3 c (def(__VMCMS__) lo\nEXEC CC desenc c (def(__VMCMS__) lo\nEXEC CC desskey c (def(__VMCMS__) lo\nEXEC CC icbc c (def(__VMCMS__) lo\nEXEC CC iecb c (def(__VMCMS__) lo\nEXEC CC iskey c (def(__VMCMS__) lo\nEXEC CC rc2cbc c (def(__VMCMS__) lo\nEXEC CC rc2ecb c (def(__VMCMS__) lo\nEXEC CC rc2skey c (def(__VMCMS__) lo\nEXEC CC rc4enc c (def(__VMCMS__) lo\nEXEC CC rc4skey c (def(__VMCMS__) lo\nEXEC CC rc5ecb c (def(__VMCMS__) lo\nEXEC CC rc5enc c (def(__VMCMS__) lo\nEXEC CC rc5skey c (def(__VMCMS__) lo\nEXEC CC skipjack c (def(__VMCMS__) lo\n\n* Crypt (hash algorithms)\nEXEC CC md2dgst c (def(__VMCMS__) lo\nEXEC CC md4dgst c (def(__VMCMS__) lo\nEXEC CC md5dgst c (def(__VMCMS__) lo\nEXEC CC rmddgst c (def(__VMCMS__) lo\nEXEC CC sha1dgst c (def(__VMCMS__) lo\nEXEC CC sha2 c (def(__VMCMS__) lo\n\n* Device\nEXEC CC system c (def(__VMCMS__) lo\n\n* Envelope\nEXEC CC cms_denv c (def(__VMCMS__) lo\nEXEC CC cms_env c (def(__VMCMS__) lo\nEXEC CC decode c (def(__VMCMS__) lo\nEXEC CC encode c (def(__VMCMS__) lo\nEXEC CC pgp_denv c (def(__VMCMS__) lo\nEXEC CC pgp_env c (def(__VMCMS__) lo\nEXEC CC res_actn c (def(__VMCMS__) lo\nEXEC CC res_denv c (def(__VMCMS__) lo\nEXEC CC res_env c (def(__VMCMS__) lo\n\n* I/O\nEXEC CC file c (def(__VMCMS__) lo\nEXEC CC memory c (def(__VMCMS__) lo\nEXEC CC stream c (def(__VMCMS__) lo\n\n* Kernel\nEXEC CC attr_acl c (def(__VMCMS__) lo\nEXEC CC certm_acl c (def(__VMCMS__) lo\nEXEC CC init c (def(__VMCMS__) lo\nEXEC CC int_msg c (def(__VMCMS__) lo\nEXEC CC key_acl c (def(__VMCMS__) lo\nEXEC CC mech_acl c (def(__VMCMS__) lo\nEXEC CC msg_acl c (def(__VMCMS__) lo\nEXEC CC obj_acc c (def(__VMCMS__) lo\nEXEC CC objects c (def(__VMCMS__) lo\nEXEC CC sec_mem c (def(__VMCMS__) lo\nEXEC CC semaphore c (def(__VMCMS__) lo\nEXEC CC sendmsg c (def(__VMCMS__) lo\n\n* Keyset\nEXEC CC pgp c (def(__VMCMS__) lo\nEXEC CC pkcs12 c (def(__VMCMS__) lo\nEXEC CC pkcs15 c (def(__VMCMS__) lo\nEXEC CC pkcs15_add c (def(__VMCMS__) lo\nEXEC CC pkcs15_att c (def(__VMCMS__) lo\nEXEC CC pkcs15_rd c (def(__VMCMS__) lo\nEXEC CC pkcs15_wr c (def(__VMCMS__) lo\n\n* Mechanism\nEXEC CC keyex c (def(__VMCMS__) lo\nEXEC CC keyex_int c (def(__VMCMS__) lo\nEXEC CC keyex_rw c (def(__VMCMS__) lo\nEXEC CC mech_drv c (def(__VMCMS__) lo\nEXEC CC mech_enc c (def(__VMCMS__) lo\nEXEC CC mech_int c (def(__VMCMS__) lo\nEXEC CC mech_sig c (def(__VMCMS__) lo\nEXEC CC mech_wrp c (def(__VMCMS__) lo\nEXEC CC obj_qry c (def(__VMCMS__) lo\nEXEC CC sign c (def(__VMCMS__) lo\nEXEC CC sign_cms c (def(__VMCMS__) lo\nEXEC CC sign_int c (def(__VMCMS__) lo\nEXEC CC sign_pgp c (def(__VMCMS__) lo\nEXEC CC sign_rw c (def(__VMCMS__) lo\nEXEC CC sign_x509 c (def(__VMCMS__) lo\n\n* Misc\nEXEC CC asn1_chk c (def(__VMCMS__) lo\nEXEC CC asn1_ext c (def(__VMCMS__) lo\nEXEC CC asn1_rd c (def(__VMCMS__) lo\nEXEC CC asn1_wr c (def(__VMCMS__) lo\nEXEC CC base64 c (def(__VMCMS__) lo\nEXEC CC int_api c (def(__VMCMS__) lo\nEXEC CC int_attr c (def(__VMCMS__) lo\nEXEC CC int_env c (def(__VMCMS__) lo\nEXEC CC misc_rw c (def(__VMCMS__) lo\nEXEC CC os_spec c (def(__VMCMS__) lo\nEXEC CC pgp_misc c (def(__VMCMS__) lo\nEXEC CC random c (def(__VMCMS__) lo\nEXEC CC user c (def(__VMCMS__) lo\nEXEC CC user_cfg c (def(__VMCMS__) lo\nEXEC CC vmcms c (def(__VMCMS__) lo\n\n* Zlib\nEXEC CC adler32 c (def(__VMCMS__) lo\nEXEC CC deflate c (def(__VMCMS__) lo\nEXEC CC inffast c (def(__VMCMS__) lo\nEXEC CC inflate c (def(__VMCMS__) lo\nEXEC CC inftrees c (def(__VMCMS__) lo\nEXEC CC trees c (def(__VMCMS__) lo\nEXEC CC zutil c (def(__VMCMS__) lo\n\n* Build the cryptlib library from the object modules\n\n&TYPE Building cryptlib...\nEXEC C370LIB GEN &LIBNAME cryptapi cryptcfg cryptcrt cryptctx cryptdev\nEXEC C370LIB ADD &LIBNAME cryptenv cryptkey cryptlib cryptses cryptusr\nEXEC C370LIB ADD &LIBNAME bn_add bn_ctx bn_div bn_exp bn_exp2 bn_gcd\nEXEC C370LIB ADD &LIBNAME bn_lib bn_mod bn_mont bn_mul bn_recp bn_shift\nEXEC C370LIB ADD &LIBNAME bn_sqr bn_word\nEXEC C370LIB ADD &LIBNAME certrev certschk certsign certval chain chk_cert\nEXEC C370LIB ADD &LIBNAME chk_chn chk_use comp_get comp_set dn dnstring\nEXEC C370LIB ADD &LIBNAME ext ext_add ext_chk ext_copy ext_def ext_rd\nEXEC C370LIB ADD &LIBNAME ext_wr imp_exp read trustmgr write\nEXEC C370LIB ADD &LIBNAME ctx_3des ctx_aes ctx_bf ctx_cast ctx_des ctx_dh\nEXEC C370LIB ADD &LIBNAME ctx_dsa ctx_elg ctx_hmd5 ctx_hrmd ctx_hsha\nEXEC C370LIB ADD &LIBNAME ctx_idea ctx_md2 ctx_md4 ctx_md5 ctx_misc\nEXEC C370LIB ADD &LIBNAME ctx_rc2 ctx_rc4 ctx_rc5 ctx_ripe ctx_rsa\nEXEC C370LIB ADD &LIBNAME ctx_sha ctx_sha2 ctx_skip kg_dlp kg_prime\nEXEC C370LIB ADD &LIBNAME kg_rsa keyload key_rd key_wr\nEXEC C370LIB ADD &LIBNAME aes_modes aescrypt aeskey aestab bfecb bfenc\nEXEC C370LIB ADD &LIBNAME bfskey castecb castenc castskey descbc desecb\nEXEC C370LIB ADD &LIBNAME desecb3 desenc desskey icbc iecb iskey rc2cbc\nEXEC C370LIB ADD &LIBNAME rc2ecb rc2skey rc4enc rc4skey rc5ecb rc5enc\nEXEC C370LIB ADD &LIBNAME rc5skey skipjack\nEXEC C370LIB ADD &LIBNAME md2dgst md4dgst md5dgst rmddgst sha1dgst sha2\nEXEC C370LIB ADD &LIBNAME system\nEXEC C370LIB ADD &LIBNAME cms_denv cms_env decode encode pgp_denv\nEXEC C370LIB ADD &LIBNAME pgp_env res_actn res_denv res_env\nEXEC C370LIB ADD &LIBNAME file memory stream\nEXEC C370LIB ADD &LIBNAME attr_acl certm_acl init int_msg key_acl\nEXEC C370LIB ADD &LIBNAME mech_acl msg_acl obj_acc objects sec_mem\nEXEC C370LIB ADD &LIBNAME semaphore sendmsg\nEXEC C370LIB ADD &LIBNAME pgp pkcs12 pkcs15 pkcs15_add pkcs15_att\nEXEC C370LIB ADD &LIBNAME pkcs15_rd pkcs15_wr\nEXEC C370LIB ADD &LIBNAME keyex keyex_int keyex_rw mech_drv mech_enc\nEXEC C370LIB ADD &LIBNAME mech_int mech_sig mech_wrp obj_qry sign\nEXEC C370LIB ADD &LIBNAME sign_cms sign_int sign_pgp sign_rw sign_x509\nEXEC C370LIB ADD &LIBNAME asn1_chk asn1_ext asn1_rd asn1_wr base64\nEXEC C370LIB ADD &LIBNAME int_api int_attr int_env misc_rw os_spec\nEXEC C370LIB ADD &LIBNAME pgp_misc random user user_cfg vmcms\nEXEC C370LIB ADD &LIBNAME adler32 deflate inffast inflate inftrees\nEXEC C370LIB ADD &LIBNAME trees zutil\n\n* Make the newly-generated modules available for use\n\nGLOBAL TXTLIB &LIBNAME\n\n* Compile the test code\n\n&TYPE Building test routines...\n\nEXEC CC utils c (def(__VMCMS__) lo\nEXEC CC certs c (def(__VMCMS__) lo\nEXEC CC devices c (def(__VMCMS__) lo\nEXEC CC envelope c (def(__VMCMS__) lo\nEXEC CC highlvl c (def(__VMCMS__) lo\nEXEC CC keydbx c (def(__VMCMS__) lo\nEXEC CC keyfile c (def(__VMCMS__) lo\nEXEC CC loadkey c (def(__VMCMS__) lo\nEXEC CC lowlvl c (def(__VMCMS__) lo\nEXEC CC scert c (def(__VMCMS__) lo\nEXEC CC sreqresp c (def(__VMCMS__) lo\nEXEC CC ssh c (def(__VMCMS__) lo\nEXEC CC ssl c (def(__VMCMS__) lo\nEXEC CC stress c (def(__VMCMS__) lo\nEXEC CC testlib c (def(__VMCMS__) lo\n\n* Build the executable\n\n&TYPE Building test program...\nEXEC CMOD testlib utils certs devices envelope highlvl keydbx keyfile loadkey lowlvl scert sreqresp ssh ssl stress\n"
  },
  {
    "path": "deps/cl345/bindings/cryptkit.tcl",
    "content": "#\n#   Cryptkit - Tcl interface to Cryptlib Encryption Toolkit\n#   (http://www.cs.auckland.ac.nz/~pgut001/cryptlib/)\n#\n#   Development by Steve Landers <steve@DigitalSmarties.com>\n#   \n#   $Id: cryptkit.tcl,v 1.28 2004/12/07 02:15:07 steve Exp $\n\npackage provide cryptkit 1.0\n\nif {[catch {package require critcl}]} {\n    puts stderr \"This extension requires Critcl to be compiled\"\n    exit 1\n}\n\nif {![critcl::compiling]} {\n    puts stderr \"Critcl can't compile on this platform\"\n    exit 1\n}\n\nnamespace eval cryptkit {\n\n    namespace export crypt*\n\n    critcl::cheaders -I[pwd]\n\n    critcl::clibraries -L[pwd] -lcl_[critcl::platform]\n\n    # platform specific stuff\n    switch [critcl::platform] {\n        Linux-x86 {\n            critcl::clibraries -lresolv\n        }\n    }\n\n    # force this source file into the resulting package so that the\n    # pure Tcl procedures are available at run time\n    critcl::tsources [file tail [info script]]\n\n    # map Cryptlib #defines and enums into the current namespace\n    critcl::cdefines CRYPT_* [namespace current]\n\n    # other defines\n    critcl::cdefines {\n        NULL\n        TRUE\n        FALSE\n        TCL_OK\n        TCL_ERROR\n    } [namespace current]\n        \n    critcl::ccode {\n        #include <string.h>\n        #include \"cryptlib.h\"\n\n        int\n        GetIntOrConstArg(Tcl_Interp *ip, Tcl_Obj *obj, int *val) {\n            Tcl_Obj *obj1;\n            if (Tcl_GetIntFromObj(NULL, obj, val) != TCL_OK) {\n                Tcl_Obj *constObj = Tcl_NewStringObj(\"::cryptkit::\",-1);\n                Tcl_AppendObjToObj(constObj, obj);\n                Tcl_IncrRefCount(constObj);\n                if ((obj1 = Tcl_ObjGetVar2(ip, constObj, NULL,\n                         TCL_LEAVE_ERR_MSG)) == NULL) {\n                    Tcl_DecrRefCount(constObj);\n                    return TCL_ERROR;\n                }\n                Tcl_DecrRefCount(constObj);\n                if (Tcl_GetIntFromObj(ip, obj1, val) != TCL_OK) {\n                    Tcl_AddErrorInfo(ip, \" in '\");\n                    Tcl_AddErrorInfo(ip, Tcl_GetString(obj));\n                    return TCL_ERROR;\n                }\n            }\n            return TCL_OK;\n        }\n\n        int\n        GetIntArg(Tcl_Interp *ip, Tcl_Obj *obj, int *val) {\n            if (Tcl_GetIntFromObj(ip, obj, val) != TCL_OK) {\n                Tcl_AddErrorInfo(ip, \" in '\");\n                Tcl_AddErrorInfo(ip, Tcl_GetString(obj));\n                return TCL_ERROR;\n            }\n            return TCL_OK;\n        }\n\n        int\n        GetStringArg(Tcl_Interp *ip, Tcl_Obj *obj, char **val) {\n            if ((*val = Tcl_GetStringFromObj(obj, NULL)) == NULL) {\n                Tcl_AddErrorInfo(ip, \" in '\");\n                Tcl_AddErrorInfo(ip, Tcl_GetString(obj));\n                return TCL_ERROR;\n            }\n            return TCL_OK;\n        }\n\n        int\n        GetByteArrayArg(Tcl_Interp *ip, Tcl_Obj *obj, void **val, int *len) {\n            if (strcmp(Tcl_GetString(obj), \"NULL\") == 0) {\n                *val = NULL;\n                *len = 0;\n            } else if ((*val = Tcl_GetByteArrayFromObj(obj, len)) == NULL) {\n                Tcl_AddErrorInfo(ip, \" in '\");\n                Tcl_AddErrorInfo(ip, Tcl_GetString(obj));\n                return TCL_ERROR;\n            }\n            return TCL_OK;\n        }\n\n        void\n        cryptSetQueryInfo(Tcl_Interp *ip, Tcl_Obj *info, \\\n                                         CRYPT_QUERY_INFO qinfo) {\n            Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"algoName\", -1), \\\n                                     Tcl_NewStringObj(qinfo.algoName, -1),\n                                     TCL_LEAVE_ERR_MSG);\n            Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"blockSize\", -1), \\\n                                     Tcl_NewIntObj(qinfo.blockSize),\n                                     TCL_LEAVE_ERR_MSG);\n            Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"minKeySize\", -1), \\\n                                     Tcl_NewIntObj(qinfo.minKeySize),\n                                     TCL_LEAVE_ERR_MSG);\n            Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"keySize\", -1), \\\n                                     Tcl_NewIntObj(qinfo.keySize),\n                                     TCL_LEAVE_ERR_MSG);\n            Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"maxKeySize\", -1), \\\n                                     Tcl_NewIntObj(qinfo.maxKeySize),\n                                     TCL_LEAVE_ERR_MSG);\n        }\n\n        int\n        cryptReturn(Tcl_Interp *ip, int ret) {\n            Tcl_Obj *resultObj, *objv[2];\n\n            objv[0] = Tcl_NewStringObj(\"::cryptkit::ReturnMsg\", -1);\n            objv[1] = Tcl_NewIntObj(ret);\n            if (Tcl_EvalObjv(ip, 2, objv, TCL_EVAL_GLOBAL) != TCL_OK) {\n                Tcl_AppendResult(ip, \"oops\", (char *) NULL);\n                return TCL_ERROR;\n            }\n            resultObj = Tcl_GetObjResult(ip);\n            if (Tcl_SetVar2Ex(ip, \"::cryptkit::errmsg\", NULL, resultObj,\n                      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) {\n                return TCL_ERROR;\n            }\n            if (ret < CRYPT_OK) {\n                Tcl_SetObjErrorCode(ip, resultObj);\n                return TCL_ERROR;\n            }\n            return TCL_OK;\n        }\n\n    }\n\n    # Return message (either number or text, or generate error)\n    proc ReturnMsg {num} {\n        variable errtype\n        variable status\n        if {![info exists errtype]} {\n            # probably means cryptInit not called\n            cryptInit\n        }\n        if {$errtype ne \"text\"} {\n            return $num\n        }\n        if {[info exists status($num)]} {\n            if {$num < 0} {\n                return $status($num)\n            } else {\n                return $status($num)\n            }\n        } else {\n            return \"unknown Cryptlib error $num\"\n        }\n    }\n\n    # append to variable holding generated C code - makes code more readable\n    # and allows it to be split over multiple lines\n    proc code {args} {\n        variable code\n        set tmp \"\"\n        foreach arg $args {\n            append tmp $arg\n        }\n        lappend code $tmp\n    }\n\n    # generate critcl::ccomands to call C cryptlib functions\n    proc generate {cmds} {\n        if {[critcl::done]} {\n            # we don't want to generate C code when the cryptkit package\n            # is loaded at runtime\n            return\n        }\n        variable code \"\"\n        foreach {name arglist} $cmds {\n            generate_function crypt$name [parse_arguments $arglist]\n        }\n        # uncomment the following line to view generated code\n        # puts \\n[join $code \\n]\n        eval [join $code \\n]\n    }\n\n    proc parse_arguments {arglist} {\n        set args [list]\n        set argnum 0\n        foreach arg $arglist {\n            set suffix [string index $arg end]\n            if {[string is alnum $suffix]} {\n                set suffix \"\"\n            } else {\n                set arg [string range $arg 0 end-1]\n            }\n            lappend args [incr argnum] $arg $suffix\n        }\n        return $args\n    }\n\n    proc generate_function {name arguments} {\n        # generate the critcl::cccomand\n        variable allocated \"\"   ;# any Tcl_Alloc'd variables\n        variable carglist \"\"    ;# list of arguments to the Cryptlib function\n        variable numargs 0      ;# number of arguments to the Cryptlib function\n        variable skiparg 0      ;# number of arguments skipped in Tcl API\n        code \"critcl::ccommand $name {data ip objc objv} \\{\"\n        code \"  int ret;\"\n        set objects \"\"      ;# Tcl objects to create\n        set vararg 0        ;# indicates we have an option argument\n        set usage \"\"        ;# usage message\n        # generate definitions for arguments to Cryptlib function\n        foreach {n arg suffix} $arguments {\n            switch $suffix {\n                *       { code \"  char *arg$n;\" }\n                %       -\n                :       -\n                =       { code \"  void *arg$n; int len$n;\" }\n                default { code \"  int arg$n;\" }\n            }\n            if {$suffix ne \"#\" && $suffix ne \"!\"} {\n                lappend usage $arg\n                lappend objects \"*obj$n\"\n                incr numargs \n            }\n        }\n        # create Tcl objects for each argument to Cryptkit Tcl procedure\n        if {$objects ne {}} {\n            code \"  Tcl_Obj [join $objects {, }];\"\n        }\n        # check number of arguments\n        code \"  if (objc != [expr {$numargs + 1}]) \\{\"\n        code \"    Tcl_WrongNumArgs(ip, 1, objv, \\\"$usage\\\");\"\n        code \"    return TCL_ERROR;\"\n        code \"  \\}\"\n        # first get all args that can be extracted from the Tcl argument list\n        foreach {n arg suffix} $arguments {\n            get_argument_values $name $n $arg $suffix\n            if {$suffix eq \"&\"} {\n                lappend carglist \"&arg$n\"\n            } else {\n                lappend carglist \"arg$n\"\n            }\n        }\n        # now get any that are derived from later arguments\n        foreach {n arg suffix} $arguments {\n            if {$suffix eq \"%\"} {\n                # get length of buffer from the next argument\n                code \"  arg$n = (void *) Tcl_Alloc(arg[expr {$n + 1}]);\"\n                lappend allocated arg$n\n            }\n        }\n        query_return_buffer_size $name $arguments\n        code \"  ret = $name\\([join $carglist {, }]\\);\" ;# call cryptlib function\n        set_return_values $arguments\n        foreach alloc $allocated {\n            code \"  Tcl_Free($alloc);\"\n        }\n        code \"  return cryptReturn(ip, ret);\"\n        code \"\\}\"\n        code \"\"\n    }\n\n    proc code_check {n name func} {\n        variable skiparg\n        set argnum [expr {$n - $skiparg}]\n        code \"  if ($func == TCL_ERROR) \\{\"\n        code \"    Tcl_AddErrorInfo(ip, \\\"' (argument $argnum to $name)\\\");\" \n        code \"    return TCL_ERROR;\"\n        code \"  \\}\"\n    }\n\n    proc get_argument_values {name n arg suffix} {\n        variable allocated\n        variable numargs\n        variable skiparg\n        set r [expr {$n - $skiparg}]\n        switch $suffix {\n            & { # return integer value\n              }\n            ? { # if not specified set optional argument to length of\n                # previous argument\n                code \"  if (objc != $numargs)\"\n                code \"    arg$n = len[expr {$n - 1}];\"\n                code \"  else\"\n                code_check $n $name \"GetIntArg(ip, objv\\[$r\\], &arg$n)\"\n              }\n            \"#\" { # use length of previous void *\n                code \"  arg$n = len[expr {$n - 1}];\"\n                incr skiparg\n              }\n            ! { # arbitrary value for maximum length of a void * \n                code \"  arg$n = 32000;\"\n                incr skiparg\n              }\n            ^ { # integer or Cryptlib constant\n                code_check $n $name \"GetIntOrConstArg(ip, objv\\[$r\\], &arg$n)\"\n              }\n            * { # char *\n                code_check $n $name  \"GetStringArg(ip, objv\\[$r\\], &arg$n)\"\n              }\n            = { # void *\n                  code_check $n $name \\\n                        \"GetByteArrayArg(ip, objv\\[$r\\], &arg$n, &len$n)\"\n              }\n            % { # handle specially }\n            : { # we handle these specially in query_return_buffer_size\n              }\n            default { # integer\n                 code_check $n $name \"GetIntArg(ip, objv\\[$r\\], &arg$n)\"\n              }\n        } \n    }\n\n    # a number of cryptlib functions can be called with a NULL argument\n    # to get the length of the data buffer  that will be returned\n    proc query_return_buffer_size {name arguments} {\n        variable allocated\n        variable carglist\n        # now look for candidates\n        foreach {n arg suffix} $arguments {\n            if {$suffix eq \":\"} {\n                set idx [expr {$n - 1}]\n                set args [join [lreplace $carglist $idx $idx NULL] ,]\n                code \"  if \\(ret = \\($name\\($args\\)\\) != CRYPT_OK\\)\"\n                code \"    return cryptReturn(ip, ret);\"\n                # need to check if next suffix is ! and ignore it\n                set next [expr {($n+1)*3+2}]\n                set x [expr {$n + 1}]\n                while {[lindex $arguments $next] eq \"!\"} {\n                    incr next 3\n                    incr x\n                }\n                # create a buffer big enough to hold returned value\n                code \"  arg$n = (void *) Tcl_Alloc(arg$x);\"\n                lappend allocated arg$n\n            }\n        }\n    }\n\n    proc set_return_values {arguments} {\n        set skip 0\n        foreach {n arg suffix} $arguments {\n            set r [expr {$n - $skip}]\n            switch $suffix {\n                % -\n                : { # void *\n                    code \"  if (Tcl_ObjSetVar2(ip, objv\\[$r\\], NULL, \" \\\n                                \"Tcl_NewByteArrayObj(arg$n, \" \\\n                                \"arg[expr {$n+1}]), \" \\\n                                \"TCL_LEAVE_ERR_MSG) == NULL)\"\n                    code \"    return TCL_ERROR;\"\n                  }\n                & { # integer\n                    code \"  if (Tcl_ObjSetVar2(ip, objv\\[$r\\], NULL, \" \\\n                                \"Tcl_NewIntObj(arg$n),\" \\\n                                \"TCL_LEAVE_ERR_MSG) == NULL)\"\n                    code \"    return TCL_ERROR;\"\n                  }\n                ! -\n                \"#\" { incr skip }\n            }\n        } \n    }\n\n    proc mapping {name pattern} {\n        variable $name\n        foreach tmp [info vars [namespace current]::$pattern] {\n            variable $tmp\n            set var [namespace tail $tmp]\n            set val [set $tmp]\n            array set $name [list $val $var]\n        }\n    }\n\n    # handle cryptInit specially, because we need to do some other setup as well\n    proc cryptInit {{type text}} {\n        # create a mapping from the C #defined errors to the textual\n        # equivalent (note we introspect using [namespace current] since\n        # namespace variables aren't visible unless explicitly declared\n        mapping status CRYPT_ERROR_*\n        mapping status CRYPT_OK\n        mapping status CRYPT_ENVELOPE_RESOURCE\n        # create a mapping from enums/defines for use in cryptQueryObject\n        mapping objects CRYPT_ALGO_*\n        mapping objects CRYPT_OBJECT_*\n        mapping objects CRYPT_MODE_*\n        variable errtype\n        switch -glob $type {\n            num* -\n            text {\n                set errtype $type\n            }\n            default {\n                error \"cryptInit: unknown error handling type '$type'\"\n            }\n        }\n        return [ReturnMsg [_cryptInit]]\n    }\n\n    critcl::cproc _cryptInit {} int {\n        return cryptInit();\n    }\n\n    # functions that return structures are handled specially and the\n    # structures are mapped into Tcl arrays\n    #  DeviceQueryCapability { cryptDevice cryptAlgo &cryptQueryInfo }\n    #  QueryCapability       { cryptAlgo &cryptQueryInfo }\n    #  QueryObject           { objectPtr= &algocryptObjectInfo }\n\n    critcl::cproc cryptDeviceQueryCapability \\\n            {Tcl_Interp* ip Tcl_Obj* dev Tcl_Obj* algo Tcl_Obj* info} ok {\n        int ret, device, algorithm;\n        CRYPT_QUERY_INFO qinfo;\n\n        if (GetIntOrConstArg(ip, algo, &algorithm) != CRYPT_OK)\n            return TCL_ERROR;\n        if (GetIntOrConstArg(ip, dev, &device) != CRYPT_OK)\n            return TCL_ERROR;\n        if (GetIntOrConstArg(ip, algo, &algorithm) != CRYPT_OK)\n            return TCL_ERROR;\n        ret = cryptDeviceQueryCapability(device, algorithm, &qinfo);\n        cryptSetQueryInfo(ip, info, qinfo);\n        cryptReturn(ip, ret);\n        return TCL_OK;\n    }\n\n    critcl::cproc cryptQueryCapability \\\n                {Tcl_Interp* ip Tcl_Obj* algo Tcl_Obj* info} ok {\n        int ret, algorithm;\n        CRYPT_QUERY_INFO qinfo;\n\n        if (GetIntOrConstArg(ip, algo, &algorithm) != CRYPT_OK)\n            return TCL_ERROR;\n        ret = cryptQueryCapability(algorithm, &qinfo);\n        cryptSetQueryInfo(ip, info, qinfo);\n        cryptReturn(ip, ret);\n        return TCL_OK;\n    }\n\n    critcl::cproc cryptQueryObject \\\n                {Tcl_Interp* ip Tcl_Obj* obj Tcl_Obj* info} ok {\n        void *objbuf;\n        CRYPT_OBJECT_INFO oinfo;\n        int ret, len;\n        Tcl_Obj *objects, *name;\n        objbuf = Tcl_GetByteArrayFromObj(obj,&len);\n        ret = cryptQueryObject(objbuf, len, &oinfo);\n        if ((objects = Tcl_NewStringObj(\"::cryptkit::objects\", -1)) == NULL)\n            return TCL_ERROR;\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"objectType\", -1), \\\n                Tcl_ObjGetVar2(ip, objects, Tcl_NewIntObj(oinfo.objectType),\n                        TCL_LEAVE_ERR_MSG), TCL_LEAVE_ERR_MSG);\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"cryptAlgo\", -1), \\\n                Tcl_ObjGetVar2(ip, objects, Tcl_NewIntObj(oinfo.cryptAlgo),\n                        TCL_LEAVE_ERR_MSG), TCL_LEAVE_ERR_MSG);\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"cryptMode\", -1), \\\n                Tcl_ObjGetVar2(ip, objects, Tcl_NewIntObj(oinfo.cryptMode),\n                        TCL_LEAVE_ERR_MSG), TCL_LEAVE_ERR_MSG);\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"hashAlgo\", -1), \\\n                Tcl_ObjGetVar2(ip, objects, Tcl_NewIntObj(oinfo.hashAlgo),\n                        TCL_LEAVE_ERR_MSG), TCL_LEAVE_ERR_MSG);\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"salt\", CRYPT_MAX_HASHSIZE), \\\n                                     Tcl_NewStringObj(oinfo.salt, -1),\n                                     TCL_LEAVE_ERR_MSG);\n        Tcl_ObjSetVar2(ip, info, Tcl_NewStringObj(\"saltSize\", -1), \\\n                                     Tcl_NewIntObj(oinfo.saltSize),\n                                     TCL_LEAVE_ERR_MSG);\n        cryptReturn(ip, ret);\n        return TCL_OK;\n    }\n\n    # generate remaining functions\n    # function arguments\n    #   default is \"const int\"\n    # suffix modifiers to alter this\n    #   ^   arg is name of #define/enum in cryptkit namespace\n    #   *   char *\n    #   =   void *\n    #   &   return int\n    #   %   return void *, next arg is length\n    #   :   return void *, call with NULL to get length of string\n    #   #   use length of previous void * (C API only)\n    #   !   pass $maxlength to Cryptlib (C API only) \n\n    # Notes \n    #   - even though the GetPrivateKey documentation specifies the keyID\n    #     should be \"void *\" it needed to be \"char *\" to work\n\n    generate {\n      AddCertExtension    { certificate oid* criticalFlag extension= \\\n                                extensionLength# }\n      AddPrivateKey       { keyset cryptKey password* }\n      AddPublicKey        { keyset certificate }\n      AddRandom           { randomData= randomDataLength^ }\n      AsyncCancel         { cryptObject }\n      AsyncQuery          { cryptObject }\n      CAAddItem           { keyset certificate }\n      CACertManagement    { cryptCert& action keyset caKey certRequest }\n      CAGetItem           { keyset certificate& certType keyIDtype keyID= }\n      CheckCert           { certificate sigCheckKey }\n      CheckSignature      { signature= length# sigCheckKey hashContext }\n      CheckSignatureEx    { signature= length# sigCheckKey hashContext \\\n                                extraData& }\n      CreateCert          { cryptCert& cryptUser^ certType^ }\n      CreateContext       { cryptContext& cryptUser^ cryptAlgo^ }\n      CreateEnvelope      { cryptEnvelope& cryptUser^ formatType^ }\n      CreateSession       { cryptSession& cryptUser^ sessionType^ }\n      CreateSignature     { signature: maxlength! signatureLength& \\\n                                signContext hashContext }\n      CreateSignatureEx   { signature: maxlength! signatureLength& formatType \\\n                                signContext hashContext extraData }\n      Decrypt             { cryptContext buffer= length# }\n      DeleteAttribute     { cryptObject attributeType }\n      DeleteCertExtension { certificate oid* }\n      DeleteKey           { cryptObject keyIDtype keyID= }\n      DestroyCert         { cryptCert }\n      DestroyContext      { cryptContext }\n      DestroyEnvelope     { cryptEnvelope }\n      DestroyObject       { cryptObject }\n      DestroySession      { cryptSession }\n      DeviceClose         { device }\n      DeviceCreateContext { cryptDevice cryptContext& cryptAlgo }\n      DeviceOpen          { device& cryptUser^ deviceType name* }\n      Encrypt             { cryptContext buffer= length# }\n      End                 { }\n      ExportCert          { certObject% maxlength! certObjectLength& \\\n                                certFormatType^ certificate }\n      ExportKey           { encryptedKey% maxlength! encryptedKeyLength& \\\n                                exportKey sessionKeyContext }\n      ExportKeyEx         { encryptedKey: maxlength! encryptedKeyLength& \\\n                                formatType exportKey sessionKeyContext }\n      FlushData           { cryptHandle }\n      GenerateKey         { cryptContext }\n      GenerateKeyAsync    { cryptContext }\n      GetAttribute        { cryptObject attributeType^ value& }\n      GetAttributeString  { cryptObject attributeType^ value: valueLength& }\n      GetCertExtension    { certificate oid* criticalFlag& extension: \\\n                                maxlength! extensionLength& }\n      GetPrivateKey       { cryptHandle cryptContext& keyIDtype^ keyID* \\\n                                password* }\n      GetPublicKey        { cryptObject publicKey& keyIDtype keyID= }\n      ImportCert          { certObject= certObjectLength cryptUser^ \\\n                                certificate& }\n      ImportKey           { encryptedKey= maxlength# importContext \\\n                                sessionKeyContext }\n      KeysetClose         { keyset }\n      KeysetOpen          { keyset& cryptUser^ keysetType^ name* options^ }\n      PopData             { envelope buffer% length bytesCopied& }\n      PushData            { envelope buffer= length# bytesCopied& }\n      SetAttribute        { cryptObject^ attributeType^ value^ }\n      SetAttributeString  { cryptObject^ attributeType^ value= valueLength# }\n      SignCert            { certificate signContext }\n    }\n\n}\n"
  },
  {
    "path": "deps/cl345/bindings/cryptlib.bas",
    "content": "Attribute VB_Name = \"CRYPTLIB\"\n\nOption Explicit\n\n'*****************************************************************************\n'*                                                                           *\n'*                        cryptlib External API Interface                    *\n'*                       Copyright Peter Gutmann 1997-2019                   *\n'*                                                                           *\n'*                 adapted for Visual Basic Version 6  by W. Gothier         *\n'*****************************************************************************\n\n\n'-----------------------------------------------------------------------------\n\n'This file has been created automatically by a perl script from the file:\n'\n'\"cryptlib.h\" dated Thu Dec 27 23:27:20 2018, filesize = 99183.\n'\n'Please check twice that the file matches the version of cryptlib.h\n'in your cryptlib source! If this is not the right version, try to download an\n'update from \"http://cryptlib.sogot.de/\". If the filesize or file creation\n'date do not match, then please do not complain about problems.\n'\n'Examples using Visual Basic are available on the same web address.\n'\n'Published by W. Gothier, \n'mailto: problems@cryptlib.sogot.de if you find errors in this file.\n\n'-----------------------------------------------------------------------------\n\n  Public Const CRYPTLIB_VERSION As Long = 3441\n\n'****************************************************************************\n'*                                                                           *\n'*                           Algorithm and Object Types                      *\n'*                                                                           *\n'****************************************************************************\n\n' Algorithm and mode types \n\nPublic Enum CRYPT_ALGO_TYPE\n                      ' Algorithms \n    ' No encryption \n    CRYPT_ALGO_NONE                 ' No encryption \n\n    ' Conventional encryption \n    CRYPT_ALGO_DES                  ' DES \n    CRYPT_ALGO_3DES                 ' Triple DES \n    CRYPT_ALGO_IDEA                 ' IDEA (only used for PGP 2.x) \n    CRYPT_ALGO_CAST                 ' CAST-128 (only used for OpenPGP) \n    CRYPT_ALGO_RC2                  ' RC2 (disabled by default, used for PKCS #12) \n    CRYPT_ALGO_RC4                  ' RC4 (insecure, deprecated) \n    CRYPT_ALGO_RESERVED1            ' Formerly RC5 \n    CRYPT_ALGO_AES                  ' AES \n    CRYPT_ALGO_RESERVED2            ' Formerly Blowfish \n\n    ' Public-key encryption \n    CRYPT_ALGO_DH = 100             ' Diffie-Hellman \n    CRYPT_ALGO_RSA                  ' RSA \n    CRYPT_ALGO_DSA                  ' DSA \n    CRYPT_ALGO_ELGAMAL              ' ElGamal \n    CRYPT_ALGO_RESERVED3            ' Formerly KEA \n    CRYPT_ALGO_ECDSA                ' ECDSA \n    CRYPT_ALGO_ECDH                 ' ECDH \n\n    ' Hash algorithms \n    CRYPT_ALGO_RESERVED4 = 200      ' Formerly MD2 \n    CRYPT_ALGO_RESERVED5            ' Formerly MD4 \n    CRYPT_ALGO_MD5                  ' MD5 (only used for TLS 1.0/1.1) \n    CRYPT_ALGO_SHA1                 ' SHA/SHA1 \n    CRYPT_ALGO_RESERVED6            ' Formerly RIPE-MD 160 \n    CRYPT_ALGO_SHA2                 ' SHA-256 \n        CRYPT_ALGO_SHA256 = CRYPT_ALGO_SHA2 ' Alternate name \n    CRYPT_ALGO_SHAng                ' Future SHA-nextgen standard \n\n    ' MACs \n    CRYPT_ALGO_RESREVED_7 = 300     ' Formerly HMAC-MD5 \n    CRYPT_ALGO_HMAC_SHA1            ' HMAC-SHA \n    CRYPT_ALGO_RESERVED8            ' Formerly HMAC-RIPEMD-160 \n    CRYPT_ALGO_HMAC_SHA2            ' HMAC-SHA2 \n    CRYPT_ALGO_HMAC_SHAng           ' HMAC-future-SHA-nextgen \n\n\n'      Vendors may want to use their own algorithms that aren't part of the\n'      general cryptlib suite.  The following values are for vendor-defined\n'      algorithms, and can be used just like the named algorithm types (it's\n'      up to the vendor to keep track of what _VENDOR1 actually corresponds\n'      to) \n\n    CRYPT_ALGO_LAST                 ' Last possible crypt algo value \n\n'      In order that we can scan through a range of algorithms with\n'      cryptQueryCapability(), we define the following boundary points for\n'      each algorithm class \n    CRYPT_ALGO_FIRST_CONVENTIONAL = 1\n    CRYPT_ALGO_LAST_CONVENTIONAL = 99\n    CRYPT_ALGO_FIRST_PKC = 100\n    CRYPT_ALGO_LAST_PKC = 199\n    CRYPT_ALGO_FIRST_HASH = 200\n    CRYPT_ALGO_LAST_HASH = 299\n    CRYPT_ALGO_FIRST_MAC = 300\n    CRYPT_ALGO_LAST_MAC = 399\n    \n\nEnd Enum\n\nPublic Enum CRYPT_MODE_TYPE\n                      ' Block cipher modes \n    CRYPT_MODE_NONE                 ' No encryption mode \n    CRYPT_MODE_ECB                  ' ECB \n    CRYPT_MODE_CBC                  ' CBC \n    CRYPT_MODE_CFB                  ' CFB \n    CRYPT_MODE_GCM                  ' GCM \n    CRYPT_MODE_LAST                 ' Last possible crypt mode value \n    \n\nEnd Enum\n\n\n' Keyset subtypes \n\nPublic Enum CRYPT_KEYSET_TYPE\n                      ' Keyset types \n    CRYPT_KEYSET_NONE               ' No keyset type \n    CRYPT_KEYSET_FILE               ' Generic flat file keyset \n    CRYPT_KEYSET_HTTP               ' Web page containing cert/CRL \n    CRYPT_KEYSET_LDAP               ' LDAP directory service \n    CRYPT_KEYSET_ODBC               ' Generic ODBC interface \n    CRYPT_KEYSET_DATABASE           ' Generic RDBMS interface \n    CRYPT_KEYSET_ODBC_STORE         ' ODBC certificate store \n    CRYPT_KEYSET_DATABASE_STORE     ' Database certificate store \n    CRYPT_KEYSET_LAST               ' Last possible keyset type \n\n    \n\nEnd Enum\n\n' Device subtypes \n\nPublic Enum CRYPT_DEVICE_TYPE\n                      ' Crypto device types \n    CRYPT_DEVICE_NONE               ' No crypto device \n    CRYPT_DEVICE_FORTEZZA           ' Fortezza card - Placeholder only \n    CRYPT_DEVICE_PKCS11             ' PKCS #11 crypto token \n    CRYPT_DEVICE_CRYPTOAPI          ' Microsoft CryptoAPI \n    CRYPT_DEVICE_HARDWARE           ' Generic crypo HW plugin \n    CRYPT_DEVICE_LAST               ' Last possible crypto device type \n    \n\nEnd Enum\n\n' Certificate subtypes \n\nPublic Enum CRYPT_CERTTYPE_TYPE\n                      ' Certificate object types \n    CRYPT_CERTTYPE_NONE             ' No certificate type \n    CRYPT_CERTTYPE_CERTIFICATE      ' Certificate \n    CRYPT_CERTTYPE_ATTRIBUTE_CERT   ' Attribute certificate \n    CRYPT_CERTTYPE_CERTCHAIN        ' PKCS #7 certificate chain \n    CRYPT_CERTTYPE_CERTREQUEST      ' PKCS #10 certification request \n    CRYPT_CERTTYPE_REQUEST_CERT     ' CRMF certification request \n    CRYPT_CERTTYPE_REQUEST_REVOCATION   ' CRMF revocation request \n    CRYPT_CERTTYPE_CRL              ' CRL \n    CRYPT_CERTTYPE_CMS_ATTRIBUTES   ' CMS attributes \n    CRYPT_CERTTYPE_RTCS_REQUEST     ' RTCS request \n    CRYPT_CERTTYPE_RTCS_RESPONSE    ' RTCS response \n    CRYPT_CERTTYPE_OCSP_REQUEST     ' OCSP request \n    CRYPT_CERTTYPE_OCSP_RESPONSE    ' OCSP response \n    CRYPT_CERTTYPE_PKIUSER          ' PKI user information \n    CRYPT_CERTTYPE_LAST             ' Last possible cert.type \n    \n\nEnd Enum\n\n' Envelope/data format subtypes \n\nPublic Enum CRYPT_FORMAT_TYPE\n\n    CRYPT_FORMAT_NONE               ' No format type \n    CRYPT_FORMAT_AUTO               ' Deenv, auto-determine type \n    CRYPT_FORMAT_CRYPTLIB           ' cryptlib native format \n    CRYPT_FORMAT_CMS                ' PKCS #7 / CMS / S/MIME fmt.\n        CRYPT_FORMAT_PKCS7 = CRYPT_FORMAT_CMS\n    CRYPT_FORMAT_SMIME              ' As CMS with MSG-style behaviour \n    CRYPT_FORMAT_PGP                ' PGP format \n    CRYPT_FORMAT_LAST               ' Last possible format type \n    \n\nEnd Enum\n\n' Session subtypes \n\nPublic Enum CRYPT_SESSION_TYPE\n\n    CRYPT_SESSION_NONE              ' No session type \n    CRYPT_SESSION_SSH               ' SSH \n    CRYPT_SESSION_SSH_SERVER        ' SSH server \n    CRYPT_SESSION_SSL               ' SSL/TLS \n        CRYPT_SESSION_TLS = CRYPT_SESSION_SSL\n    CRYPT_SESSION_SSL_SERVER        ' SSL/TLS server \n        CRYPT_SESSION_TLS_SERVER = CRYPT_SESSION_SSL_SERVER\n    CRYPT_SESSION_RTCS              ' RTCS \n    CRYPT_SESSION_RTCS_SERVER       ' RTCS server \n    CRYPT_SESSION_OCSP              ' OCSP \n    CRYPT_SESSION_OCSP_SERVER       ' OCSP server \n    CRYPT_SESSION_TSP               ' TSP \n    CRYPT_SESSION_TSP_SERVER        ' TSP server \n    CRYPT_SESSION_CMP               ' CMP \n    CRYPT_SESSION_CMP_SERVER        ' CMP server \n    CRYPT_SESSION_SCEP              ' SCEP \n    CRYPT_SESSION_SCEP_SERVER       ' SCEP server \n    CRYPT_SESSION_CERTSTORE_SERVER  ' HTTP cert store interface \n    CRYPT_SESSION_LAST              ' Last possible session type \n    \n\nEnd Enum\n\n' User subtypes \n\nPublic Enum CRYPT_USER_TYPE\n\n    CRYPT_USER_NONE                 ' No user type \n    CRYPT_USER_NORMAL               ' Normal user \n    CRYPT_USER_SO                   ' Security officer \n    CRYPT_USER_CA                   ' CA user \n    CRYPT_USER_LAST                 ' Last possible user type \n    \n\nEnd Enum\n\n'****************************************************************************\n'*                                                                           *\n'*                               Attribute Types                             *\n'*                                                                           *\n'****************************************************************************\n\n'  Attribute types.  These are arranged in the following order:\n'\n'   PROPERTY    - Object property\n'   ATTRIBUTE   - Generic attributes\n'   OPTION      - Global or object-specific config.option\n'   CTXINFO     - Context-specific attribute\n'   CERTINFO    - Certificate-specific attribute\n'   KEYINFO     - Keyset-specific attribute\n'   DEVINFO     - Device-specific attribute\n'   ENVINFO     - Envelope-specific attribute\n'   SESSINFO    - Session-specific attribute\n'   USERINFO    - User-specific attribute \n\nPublic Enum CRYPT_ATTRIBUTE_TYPE\n\n    CRYPT_ATTRIBUTE_NONE            ' Non-value \n\n    ' Used internally \n    CRYPT_PROPERTY_FIRST\n\n    '*******************\n    ' Object attributes \n    '*******************\n\n    ' Object properties \n    CRYPT_PROPERTY_HIGHSECURITY     ' Owned+non-forwardcount+locked \n    CRYPT_PROPERTY_OWNER            ' Object owner \n    CRYPT_PROPERTY_FORWARDCOUNT     ' No.of times object can be forwarded \n    CRYPT_PROPERTY_LOCKED           ' Whether properties can be chged/read \n    CRYPT_PROPERTY_USAGECOUNT       ' Usage count before object expires \n    CRYPT_PROPERTY_NONEXPORTABLE    ' Whether key is nonexp.from context \n\n    ' Used internally \n    CRYPT_PROPERTY_LAST\n    CRYPT_GENERIC_FIRST\n\n    ' Extended error information \n    CRYPT_ATTRIBUTE_ERRORTYPE       ' Type of last error \n    CRYPT_ATTRIBUTE_ERRORLOCUS      ' Locus of last error \n    CRYPT_ATTRIBUTE_ERRORMESSAGE    ' Detailed error description \n\n    ' Generic information \n    CRYPT_ATTRIBUTE_CURRENT_GROUP   ' Cursor mgt: Group in attribute list \n    CRYPT_ATTRIBUTE_CURRENT         ' Cursor mgt: Entry in attribute list \n    CRYPT_ATTRIBUTE_CURRENT_INSTANCE    ' Cursor mgt: Instance in attribute list \n    CRYPT_ATTRIBUTE_BUFFERSIZE      ' Internal data buffer size \n\n    ' Used internally \n    CRYPT_GENERIC_LAST\n    CRYPT_OPTION_FIRST = 100\n\n    '**************************\n    ' Configuration attributes \n    '**************************\n\n    ' cryptlib information (read-only) \n    CRYPT_OPTION_INFO_DESCRIPTION   ' Text description \n    CRYPT_OPTION_INFO_COPYRIGHT     ' Copyright notice \n    CRYPT_OPTION_INFO_MAJORVERSION  ' Major release version \n    CRYPT_OPTION_INFO_MINORVERSION  ' Minor release version \n    CRYPT_OPTION_INFO_STEPPING      ' Release stepping \n\n    ' Encryption options \n    CRYPT_OPTION_ENCR_ALGO          ' Conventional ncryption algorithm \n    CRYPT_OPTION_ENCR_HASH          ' Hash algorithm \n    CRYPT_OPTION_ENCR_MAC           ' MAC algorithm \n\n    ' PKC options \n    CRYPT_OPTION_PKC_ALGO           ' PKC algorithm \n    CRYPT_OPTION_PKC_KEYSIZE        ' PKC key size \n\n    ' Placeholder for obsolete options \n    CRYPT_OPTION_DUMMY1\n    CRYPT_OPTION_DUMMY2\n\n    ' Keying options \n    CRYPT_OPTION_KEYING_ALGO        ' Key processing algorithm \n    CRYPT_OPTION_KEYING_ITERATIONS  ' Key processing iterations \n\n    ' Certificate options \n    CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES    ' Whether to sign unrecog.attrs \n    CRYPT_OPTION_CERT_VALIDITY      ' Certificate validity period \n    CRYPT_OPTION_CERT_UPDATEINTERVAL    ' CRL update interval \n    CRYPT_OPTION_CERT_COMPLIANCELEVEL   ' PKIX compliance level for cert chks.\n    CRYPT_OPTION_CERT_REQUIREPOLICY     ' Whether explicit policy req'd for certs \n\n    ' CMS/SMIME options \n    CRYPT_OPTION_CMS_DEFAULTATTRIBUTES  ' Add default CMS attributes \n        CRYPT_OPTION_SMIME_DEFAULTATTRIBUTES = CRYPT_OPTION_CMS_DEFAULTATTRIBUTES\n\n    ' LDAP keyset options \n    CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS  ' Object class \n    CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE   ' Object type to fetch \n    CRYPT_OPTION_KEYS_LDAP_FILTER       ' Query filter \n    CRYPT_OPTION_KEYS_LDAP_CACERTNAME   ' CA certificate attribute name \n    CRYPT_OPTION_KEYS_LDAP_CERTNAME     ' Certificate attribute name \n    CRYPT_OPTION_KEYS_LDAP_CRLNAME      ' CRL attribute name \n    CRYPT_OPTION_KEYS_LDAP_EMAILNAME    ' Email attribute name \n\n    ' Crypto device options \n    CRYPT_OPTION_DEVICE_PKCS11_DVR01    ' Name of first PKCS #11 driver \n    CRYPT_OPTION_DEVICE_PKCS11_DVR02    ' Name of second PKCS #11 driver \n    CRYPT_OPTION_DEVICE_PKCS11_DVR03    ' Name of third PKCS #11 driver \n    CRYPT_OPTION_DEVICE_PKCS11_DVR04    ' Name of fourth PKCS #11 driver \n    CRYPT_OPTION_DEVICE_PKCS11_DVR05    ' Name of fifth PKCS #11 driver \n    CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY ' Use only hardware mechanisms \n\n    ' Network access options \n    CRYPT_OPTION_NET_SOCKS_SERVER       ' Socks server name \n    CRYPT_OPTION_NET_SOCKS_USERNAME     ' Socks user name \n    CRYPT_OPTION_NET_HTTP_PROXY         ' Web proxy server \n    CRYPT_OPTION_NET_CONNECTTIMEOUT     ' Timeout for network connection setup \n    CRYPT_OPTION_NET_READTIMEOUT        ' Timeout for network reads \n    CRYPT_OPTION_NET_WRITETIMEOUT       ' Timeout for network writes \n\n    ' Miscellaneous options \n    CRYPT_OPTION_MISC_ASYNCINIT     ' Whether to init cryptlib async'ly \n    CRYPT_OPTION_MISC_SIDECHANNELPROTECTION  ' Protect against side-channel attacks \n\n    ' cryptlib state information \n    CRYPT_OPTION_CONFIGCHANGED      ' Whether in-mem.opts match on-disk ones \n    CRYPT_OPTION_SELFTESTOK         ' Whether self-test was completed and OK \n\n    ' Used internally \n    CRYPT_OPTION_LAST\n    CRYPT_CTXINFO_FIRST = 1000\n\n    '********************\n    ' Context attributes \n    '********************\n\n    ' Algorithm and mode information \n    CRYPT_CTXINFO_ALGO              ' Algorithm \n    CRYPT_CTXINFO_MODE              ' Mode \n    CRYPT_CTXINFO_NAME_ALGO         ' Algorithm name \n    CRYPT_CTXINFO_NAME_MODE         ' Mode name \n    CRYPT_CTXINFO_KEYSIZE           ' Key size in bytes \n    CRYPT_CTXINFO_BLOCKSIZE         ' Block size \n    CRYPT_CTXINFO_IVSIZE            ' IV size \n    CRYPT_CTXINFO_KEYING_ALGO       ' Key processing algorithm \n    CRYPT_CTXINFO_KEYING_ITERATIONS ' Key processing iterations \n    CRYPT_CTXINFO_KEYING_SALT       ' Key processing salt \n    CRYPT_CTXINFO_KEYING_VALUE      ' Value used to derive key \n\n    ' State information \n    CRYPT_CTXINFO_KEY               ' Key \n    CRYPT_CTXINFO_KEY_COMPONENTS    ' Public-key components \n    CRYPT_CTXINFO_IV                ' IV \n    CRYPT_CTXINFO_HASHVALUE         ' Hash value \n\n    ' Misc.information \n    CRYPT_CTXINFO_LABEL             ' Label for private/secret key \n    CRYPT_CTXINFO_PERSISTENT        ' Obj.is backed by device or keyset \n\n    ' Used internally \n    CRYPT_CTXINFO_LAST\n    CRYPT_CERTINFO_FIRST = 2000\n\n    '************************\n    ' Certificate attributes \n    '************************\n\n'      Because there are so many cert attributes, we break them down into\n'      blocks to minimise the number of values that change if a new one is\n'      added halfway through \n\n'      Pseudo-information on a cert object or meta-information which is used\n'      to control the way that a cert object is processed \n    CRYPT_CERTINFO_SELFSIGNED       ' Cert is self-signed \n    CRYPT_CERTINFO_IMMUTABLE        ' Cert is signed and immutable \n    CRYPT_CERTINFO_XYZZY            ' Cert is a magic just-works cert \n    CRYPT_CERTINFO_CERTTYPE         ' Certificate object type \n    CRYPT_CERTINFO_FINGERPRINT_SHA1 ' Certificate fingerprints \n    CRYPT_CERTINFO_FINGERPRINT_SHA2\n    CRYPT_CERTINFO_FINGERPRINT_SHAng\n    CRYPT_CERTINFO_CURRENT_CERTIFICATE ' Cursor mgt: Rel.pos in chain/CRL/OCSP \n    CRYPT_CERTINFO_TRUSTED_USAGE    ' Usage that cert is trusted for \n    CRYPT_CERTINFO_TRUSTED_IMPLICIT ' Whether cert is implicitly trusted \n    CRYPT_CERTINFO_SIGNATURELEVEL   ' Amount of detail to include in sigs.\n\n    ' General certificate object information \n    CRYPT_CERTINFO_VERSION          ' Cert.format version \n    CRYPT_CERTINFO_SERIALNUMBER     ' Serial number \n    CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO     ' Public key \n    CRYPT_CERTINFO_CERTIFICATE      ' User certificate \n        CRYPT_CERTINFO_USERCERTIFICATE = CRYPT_CERTINFO_CERTIFICATE\n    CRYPT_CERTINFO_CACERTIFICATE    ' CA certificate \n    CRYPT_CERTINFO_ISSUERNAME       ' Issuer DN \n    CRYPT_CERTINFO_VALIDFROM        ' Cert valid-from time \n    CRYPT_CERTINFO_VALIDTO          ' Cert valid-to time \n    CRYPT_CERTINFO_SUBJECTNAME      ' Subject DN \n    CRYPT_CERTINFO_ISSUERUNIQUEID   ' Issuer unique ID \n    CRYPT_CERTINFO_SUBJECTUNIQUEID  ' Subject unique ID \n    CRYPT_CERTINFO_CERTREQUEST      ' Cert.request (DN + public key) \n    CRYPT_CERTINFO_THISUPDATE       ' CRL/OCSP current-update time \n    CRYPT_CERTINFO_NEXTUPDATE       ' CRL/OCSP next-update time \n    CRYPT_CERTINFO_REVOCATIONDATE   ' CRL/OCSP cert-revocation time \n    CRYPT_CERTINFO_REVOCATIONSTATUS ' OCSP revocation status \n    CRYPT_CERTINFO_CERTSTATUS       ' RTCS certificate status \n    CRYPT_CERTINFO_DN               ' Currently selected DN in string form \n    CRYPT_CERTINFO_PKIUSER_ID       ' PKI user ID \n    CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD    ' PKI user issue password \n    CRYPT_CERTINFO_PKIUSER_REVPASSWORD      ' PKI user revocation password \n    CRYPT_CERTINFO_PKIUSER_RA       ' PKI user is an RA \n\n'      X.520 Distinguished Name components.  This is a composite field, the\n'      DN to be manipulated is selected through the addition of a\n'      pseudocomponent, and then one of the following is used to access the\n'      DN components directly \n    CRYPT_CERTINFO_COUNTRYNAME = CRYPT_CERTINFO_FIRST + 100     ' countryName \n    CRYPT_CERTINFO_STATEORPROVINCENAME  ' stateOrProvinceName \n    CRYPT_CERTINFO_LOCALITYNAME         ' localityName \n    CRYPT_CERTINFO_ORGANIZATIONNAME     ' organizationName \n        CRYPT_CERTINFO_ORGANISATIONNAME = CRYPT_CERTINFO_ORGANIZATIONNAME\n    CRYPT_CERTINFO_ORGANIZATIONALUNITNAME   ' organizationalUnitName \n        CRYPT_CERTINFO_ORGANISATIONALUNITNAME = CRYPT_CERTINFO_ORGANIZATIONALUNITNAME\n    CRYPT_CERTINFO_COMMONNAME       ' commonName \n\n'      X.509 General Name components.  These are handled in the same way as\n'      the DN composite field, with the current GeneralName being selected by\n'      a pseudo-component after which the individual components can be\n'      modified through one of the following \n    CRYPT_CERTINFO_OTHERNAME_TYPEID         ' otherName.typeID \n    CRYPT_CERTINFO_OTHERNAME_VALUE          ' otherName.value \n    CRYPT_CERTINFO_RFC822NAME               ' rfc822Name \n        CRYPT_CERTINFO_EMAIL = CRYPT_CERTINFO_RFC822NAME\n    CRYPT_CERTINFO_DNSNAME                  ' dNSName \n    CRYPT_CERTINFO_DIRECTORYNAME            ' directoryName \n    CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER    ' ediPartyName.nameAssigner \n    CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME   ' ediPartyName.partyName \n    CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER    ' uniformResourceIdentifier \n        CRYPT_CERTINFO_URL = CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER\n    CRYPT_CERTINFO_IPADDRESS                ' iPAddress \n    CRYPT_CERTINFO_REGISTEREDID             ' registeredID \n\n'      X.509 certificate extensions.  Although it would be nicer to use names\n'      that match the extensions more closely (e.g.\n'      CRYPT_CERTINFO_BASICCONSTRAINTS_PATHLENCONSTRAINT), these exceed the\n'      32-character ANSI minimum length for unique names, and get really\n'      hairy once you get into the weird policy constraints extensions whose\n'      names wrap around the screen about three times.\n'\n'      The following values are defined in OID order, this isn't absolutely\n'      necessary but saves an extra layer of processing when encoding them \n\n'      1 2 840 113549 1 9 7 challengePassword.  This is here even though it's\n'      a CMS attribute because SCEP stuffs it into PKCS #10 requests \n    CRYPT_CERTINFO_CHALLENGEPASSWORD = CRYPT_CERTINFO_FIRST + 200\n\n    ' 1 3 6 1 4 1 3029 3 1 4 cRLExtReason \n    CRYPT_CERTINFO_CRLEXTREASON\n\n    ' 1 3 6 1 4 1 3029 3 1 5 keyFeatures \n    CRYPT_CERTINFO_KEYFEATURES\n\n    ' 1 3 6 1 5 5 7 1 1 authorityInfoAccess \n    CRYPT_CERTINFO_AUTHORITYINFOACCESS\n    CRYPT_CERTINFO_AUTHORITYINFO_RTCS       ' accessDescription.accessLocation \n    CRYPT_CERTINFO_AUTHORITYINFO_OCSP       ' accessDescription.accessLocation \n    CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS  ' accessDescription.accessLocation \n    CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE  ' accessDescription.accessLocation \n    CRYPT_CERTINFO_AUTHORITYINFO_CRLS       ' accessDescription.accessLocation \n\n    ' 1 3 6 1 5 5 7 1 2 biometricInfo \n    CRYPT_CERTINFO_BIOMETRICINFO\n    CRYPT_CERTINFO_BIOMETRICINFO_TYPE       ' biometricData.typeOfData \n    CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO   ' biometricData.hashAlgorithm \n    CRYPT_CERTINFO_BIOMETRICINFO_HASH       ' biometricData.dataHash \n    CRYPT_CERTINFO_BIOMETRICINFO_URL        ' biometricData.sourceDataUri \n\n    ' 1 3 6 1 5 5 7 1 3 qcStatements \n    CRYPT_CERTINFO_QCSTATEMENT\n    CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS\n                    ' qcStatement.statementInfo.semanticsIdentifier \n    CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY\n                    ' qcStatement.statementInfo.nameRegistrationAuthorities \n\n    ' 1 3 6 1 5 5 7 1 7 ipAddrBlocks \n    CRYPT_CERTINFO_IPADDRESSBLOCKS\n    CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY    ' addressFamily \n'  CRYPT_CERTINFO_IPADDRESSBLOCKS_INHERIT, // ipAddress.inherit \n    CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX   ' ipAddress.addressPrefix \n    CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN      ' ipAddress.addressRangeMin \n    CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX      ' ipAddress.addressRangeMax \n\n    ' 1 3 6 1 5 5 7 1 8 autonomousSysIds \n    CRYPT_CERTINFO_AUTONOMOUSSYSIDS\n'  CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_INHERIT,// asNum.inherit \n    CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID    ' asNum.id \n    CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN   ' asNum.min \n    CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX   ' asNum.max \n\n    ' 1 3 6 1 5 5 7 48 1 2 ocspNonce \n    CRYPT_CERTINFO_OCSP_NONCE               ' nonce \n\n    ' 1 3 6 1 5 5 7 48 1 4 ocspAcceptableResponses \n    CRYPT_CERTINFO_OCSP_RESPONSE\n    CRYPT_CERTINFO_OCSP_RESPONSE_OCSP       ' OCSP standard response \n\n    ' 1 3 6 1 5 5 7 48 1 5 ocspNoCheck \n    CRYPT_CERTINFO_OCSP_NOCHECK\n\n    ' 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff \n    CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF\n\n    ' 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess \n    CRYPT_CERTINFO_SUBJECTINFOACCESS\n    CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING ' accessDescription.accessLocation \n    CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY ' accessDescription.accessLocation \n    CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY ' accessDescription.accessLocation \n    CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST ' accessDescription.accessLocation \n    CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT ' accessDescription.accessLocation \n\n    ' 1 3 36 8 3 1 siggDateOfCertGen \n    CRYPT_CERTINFO_SIGG_DATEOFCERTGEN\n\n    ' 1 3 36 8 3 2 siggProcuration \n    CRYPT_CERTINFO_SIGG_PROCURATION\n    CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY     ' country \n    CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION  ' typeOfSubstitution \n    CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR  ' signingFor.thirdPerson \n\n    ' 1 3 36 8 3 3 siggAdmissions \n    CRYPT_CERTINFO_SIGG_ADMISSIONS\n    CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY    ' authority \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID     ' namingAuth.iD \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL    ' namingAuth.uRL \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT   ' namingAuth.text \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM   ' professionItem \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID    ' professionOID \n    CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER   ' registrationNumber \n\n    ' 1 3 36 8 3 4 siggMonetaryLimit \n    CRYPT_CERTINFO_SIGG_MONETARYLIMIT\n    CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY   ' currency \n    CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT     ' amount \n    CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT   ' exponent \n\n    ' 1 3 36 8 3 5 siggDeclarationOfMajority \n    CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY\n    CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY   ' fullAgeAtCountry \n\n    ' 1 3 36 8 3 8 siggRestriction \n    CRYPT_CERTINFO_SIGG_RESTRICTION\n\n    ' 1 3 36 8 3 13 siggCertHash \n    CRYPT_CERTINFO_SIGG_CERTHASH\n\n    ' 1 3 36 8 3 15 siggAdditionalInformation \n    CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION\n\n    ' 1 3 101 1 4 1 strongExtranet \n    CRYPT_CERTINFO_STRONGEXTRANET\n    CRYPT_CERTINFO_STRONGEXTRANET_ZONE      ' sxNetIDList.sxNetID.zone \n    CRYPT_CERTINFO_STRONGEXTRANET_ID        ' sxNetIDList.sxNetID.id \n\n    ' 2 5 29 9 subjectDirectoryAttributes \n    CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES\n    CRYPT_CERTINFO_SUBJECTDIR_TYPE          ' attribute.type \n    CRYPT_CERTINFO_SUBJECTDIR_VALUES        ' attribute.values \n\n    ' 2 5 29 14 subjectKeyIdentifier \n    CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER\n\n    ' 2 5 29 15 keyUsage \n    CRYPT_CERTINFO_KEYUSAGE\n\n    ' 2 5 29 16 privateKeyUsagePeriod \n    CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD\n    CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE     ' notBefore \n    CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER      ' notAfter \n\n    ' 2 5 29 17 subjectAltName \n    CRYPT_CERTINFO_SUBJECTALTNAME\n\n    ' 2 5 29 18 issuerAltName \n    CRYPT_CERTINFO_ISSUERALTNAME\n\n    ' 2 5 29 19 basicConstraints \n    CRYPT_CERTINFO_BASICCONSTRAINTS\n    CRYPT_CERTINFO_CA                       ' cA \n        CRYPT_CERTINFO_AUTHORITY = CRYPT_CERTINFO_CA\n    CRYPT_CERTINFO_PATHLENCONSTRAINT        ' pathLenConstraint \n\n    ' 2 5 29 20 cRLNumber \n    CRYPT_CERTINFO_CRLNUMBER\n\n    ' 2 5 29 21 cRLReason \n    CRYPT_CERTINFO_CRLREASON\n\n    ' 2 5 29 23 holdInstructionCode \n    CRYPT_CERTINFO_HOLDINSTRUCTIONCODE\n\n    ' 2 5 29 24 invalidityDate \n    CRYPT_CERTINFO_INVALIDITYDATE\n\n    ' 2 5 29 27 deltaCRLIndicator \n    CRYPT_CERTINFO_DELTACRLINDICATOR\n\n    ' 2 5 29 28 issuingDistributionPoint \n    CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT\n    CRYPT_CERTINFO_ISSUINGDIST_FULLNAME     ' distributionPointName.fullName \n    CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY    ' onlyContainsUserCerts \n    CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY  ' onlyContainsCACerts \n    CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY  ' onlySomeReasons \n    CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL  ' indirectCRL \n\n    ' 2 5 29 29 certificateIssuer \n    CRYPT_CERTINFO_CERTIFICATEISSUER\n\n    ' 2 5 29 30 nameConstraints \n    CRYPT_CERTINFO_NAMECONSTRAINTS\n    CRYPT_CERTINFO_PERMITTEDSUBTREES        ' permittedSubtrees \n    CRYPT_CERTINFO_EXCLUDEDSUBTREES         ' excludedSubtrees \n\n    ' 2 5 29 31 cRLDistributionPoint \n    CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT\n    CRYPT_CERTINFO_CRLDIST_FULLNAME         ' distributionPointName.fullName \n    CRYPT_CERTINFO_CRLDIST_REASONS          ' reasons \n    CRYPT_CERTINFO_CRLDIST_CRLISSUER        ' cRLIssuer \n\n    ' 2 5 29 32 certificatePolicies \n    CRYPT_CERTINFO_CERTIFICATEPOLICIES\n    CRYPT_CERTINFO_CERTPOLICYID         ' policyInformation.policyIdentifier \n    CRYPT_CERTINFO_CERTPOLICY_CPSURI\n        ' policyInformation.policyQualifiers.qualifier.cPSuri \n    CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION\n        ' policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization \n    CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS\n        ' policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers \n    CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT\n        ' policyInformation.policyQualifiers.qualifier.userNotice.explicitText \n\n    ' 2 5 29 33 policyMappings \n    CRYPT_CERTINFO_POLICYMAPPINGS\n    CRYPT_CERTINFO_ISSUERDOMAINPOLICY   ' policyMappings.issuerDomainPolicy \n    CRYPT_CERTINFO_SUBJECTDOMAINPOLICY  ' policyMappings.subjectDomainPolicy \n\n    ' 2 5 29 35 authorityKeyIdentifier \n    CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER\n    CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER  ' keyIdentifier \n    CRYPT_CERTINFO_AUTHORITY_CERTISSUER     ' authorityCertIssuer \n    CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER   ' authorityCertSerialNumber \n\n    ' 2 5 29 36 policyConstraints \n    CRYPT_CERTINFO_POLICYCONSTRAINTS\n    CRYPT_CERTINFO_REQUIREEXPLICITPOLICY    ' policyConstraints.requireExplicitPolicy \n    CRYPT_CERTINFO_INHIBITPOLICYMAPPING     ' policyConstraints.inhibitPolicyMapping \n\n    ' 2 5 29 37 extKeyUsage \n    CRYPT_CERTINFO_EXTKEYUSAGE\n    CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING  ' individualCodeSigning \n    CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING  ' commercialCodeSigning \n    CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING   ' certTrustListSigning \n    CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING   ' timeStampSigning \n    CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO  ' serverGatedCrypto \n    CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM    ' encrypedFileSystem \n    CRYPT_CERTINFO_EXTKEY_SERVERAUTH        ' serverAuth \n    CRYPT_CERTINFO_EXTKEY_CLIENTAUTH        ' clientAuth \n    CRYPT_CERTINFO_EXTKEY_CODESIGNING       ' codeSigning \n    CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION   ' emailProtection \n    CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM    ' ipsecEndSystem \n    CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL       ' ipsecTunnel \n    CRYPT_CERTINFO_EXTKEY_IPSECUSER         ' ipsecUser \n    CRYPT_CERTINFO_EXTKEY_TIMESTAMPING      ' timeStamping \n    CRYPT_CERTINFO_EXTKEY_OCSPSIGNING       ' ocspSigning \n    CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE  ' directoryService \n    CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE       ' anyExtendedKeyUsage \n    CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO  ' serverGatedCrypto \n    CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA   ' serverGatedCrypto CA \n        CRYPT_CERTINFO_EXTKEYUSAGE_LAST = CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA\n\n    ' 2 5 29 40 crlStreamIdentifier \n    CRYPT_CERTINFO_CRLSTREAMIDENTIFIER\n\n    ' 2 5 29 46 freshestCRL \n    CRYPT_CERTINFO_FRESHESTCRL\n    CRYPT_CERTINFO_FRESHESTCRL_FULLNAME     ' distributionPointName.fullName \n    CRYPT_CERTINFO_FRESHESTCRL_REASONS      ' reasons \n    CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER    ' cRLIssuer \n\n    ' 2 5 29 47 orderedList \n    CRYPT_CERTINFO_ORDEREDLIST\n\n    ' 2 5 29 51 baseUpdateTime \n    CRYPT_CERTINFO_BASEUPDATETIME\n\n    ' 2 5 29 53 deltaInfo \n    CRYPT_CERTINFO_DELTAINFO\n    CRYPT_CERTINFO_DELTAINFO_LOCATION       ' deltaLocation \n    CRYPT_CERTINFO_DELTAINFO_NEXTDELTA      ' nextDelta \n\n    ' 2 5 29 54 inhibitAnyPolicy \n    CRYPT_CERTINFO_INHIBITANYPOLICY\n\n    ' 2 5 29 58 toBeRevoked \n    CRYPT_CERTINFO_TOBEREVOKED\n    CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER   ' certificateIssuer \n    CRYPT_CERTINFO_TOBEREVOKED_REASONCODE   ' reasonCode \n    CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME   ' revocationTime \n    CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER ' certSerialNumber \n\n    ' 2 5 29 59 revokedGroups \n    CRYPT_CERTINFO_REVOKEDGROUPS\n    CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER ' certificateIssuer \n    CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE ' reasonCode \n    CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE ' invalidityDate \n    CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER ' startingNumber \n    CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER   ' endingNumber \n\n    ' 2 5 29 60 expiredCertsOnCRL \n    CRYPT_CERTINFO_EXPIREDCERTSONCRL\n\n    ' 2 5 29 63 aaIssuingDistributionPoint \n    CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT\n    CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME   ' distributionPointName.fullName \n    CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY ' onlySomeReasons \n    CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL    ' indirectCRL \n    CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS  ' containsUserAttributeCerts \n    CRYPT_CERTINFO_AAISSUINGDIST_AACERTS    ' containsAACerts \n    CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS   ' containsSOAPublicKeyCerts \n\n    ' 2 16 840 1 113730 1 x Netscape extensions \n    CRYPT_CERTINFO_NS_CERTTYPE              ' netscape-cert-type \n    CRYPT_CERTINFO_NS_BASEURL               ' netscape-base-url \n    CRYPT_CERTINFO_NS_REVOCATIONURL         ' netscape-revocation-url \n    CRYPT_CERTINFO_NS_CAREVOCATIONURL       ' netscape-ca-revocation-url \n    CRYPT_CERTINFO_NS_CERTRENEWALURL        ' netscape-cert-renewal-url \n    CRYPT_CERTINFO_NS_CAPOLICYURL           ' netscape-ca-policy-url \n    CRYPT_CERTINFO_NS_SSLSERVERNAME         ' netscape-ssl-server-name \n    CRYPT_CERTINFO_NS_COMMENT               ' netscape-comment \n\n    ' 2 23 42 7 0 SET hashedRootKey \n    CRYPT_CERTINFO_SET_HASHEDROOTKEY\n    CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT    ' rootKeyThumbPrint \n\n    ' 2 23 42 7 1 SET certificateType \n    CRYPT_CERTINFO_SET_CERTIFICATETYPE\n\n    ' 2 23 42 7 2 SET merchantData \n    CRYPT_CERTINFO_SET_MERCHANTDATA\n    CRYPT_CERTINFO_SET_MERID                ' merID \n    CRYPT_CERTINFO_SET_MERACQUIRERBIN       ' merAcquirerBIN \n    CRYPT_CERTINFO_SET_MERCHANTLANGUAGE     ' merNames.language \n    CRYPT_CERTINFO_SET_MERCHANTNAME         ' merNames.name \n    CRYPT_CERTINFO_SET_MERCHANTCITY         ' merNames.city \n    CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE ' merNames.stateProvince \n    CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE   ' merNames.postalCode \n    CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME  ' merNames.countryName \n    CRYPT_CERTINFO_SET_MERCOUNTRY           ' merCountry \n    CRYPT_CERTINFO_SET_MERAUTHFLAG          ' merAuthFlag \n\n    ' 2 23 42 7 3 SET certCardRequired \n    CRYPT_CERTINFO_SET_CERTCARDREQUIRED\n\n    ' 2 23 42 7 4 SET tunneling \n    CRYPT_CERTINFO_SET_TUNNELING\n        CRYPT_CERTINFO_SET_TUNNELLING = CRYPT_CERTINFO_SET_TUNNELING\n    CRYPT_CERTINFO_SET_TUNNELINGFLAG        ' tunneling \n        CRYPT_CERTINFO_SET_TUNNELLINGFLAG = CRYPT_CERTINFO_SET_TUNNELINGFLAG\n    CRYPT_CERTINFO_SET_TUNNELINGALGID       ' tunnelingAlgID \n        CRYPT_CERTINFO_SET_TUNNELLINGALGID = CRYPT_CERTINFO_SET_TUNNELINGALGID\n\n    ' S/MIME attributes \n\n    ' 1 2 840 113549 1 9 3 contentType \n    CRYPT_CERTINFO_CMS_CONTENTTYPE = CRYPT_CERTINFO_FIRST + 500\n\n    ' 1 2 840 113549 1 9 4 messageDigest \n    CRYPT_CERTINFO_CMS_MESSAGEDIGEST\n\n    ' 1 2 840 113549 1 9 5 signingTime \n    CRYPT_CERTINFO_CMS_SIGNINGTIME\n\n    ' 1 2 840 113549 1 9 6 counterSignature \n    CRYPT_CERTINFO_CMS_COUNTERSIGNATURE     ' counterSignature \n\n    ' 1 2 840 113549 1 9 13 signingDescription \n    CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION\n\n    ' 1 2 840 113549 1 9 15 sMIMECapabilities \n    CRYPT_CERTINFO_CMS_SMIMECAPABILITIES\n    CRYPT_CERTINFO_CMS_SMIMECAP_3DES        ' 3DES encryption \n    CRYPT_CERTINFO_CMS_SMIMECAP_AES         ' AES encryption \n    CRYPT_CERTINFO_CMS_SMIMECAP_CAST128     ' CAST-128 encryption \n    CRYPT_CERTINFO_CMS_SMIMECAP_SHAng       ' SHA2-ng hash \n    CRYPT_CERTINFO_CMS_SMIMECAP_SHA2        ' SHA2-256 hash \n    CRYPT_CERTINFO_CMS_SMIMECAP_SHA1        ' SHA1 hash \n    CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng  ' HMAC-SHA2-ng MAC \n    CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2   ' HMAC-SHA2-256 MAC \n    CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1   ' HMAC-SHA1 MAC \n    CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256  ' AuthEnc w.256-bit key \n    CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128  ' AuthEnc w.128-bit key \n    CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng   ' RSA with SHA-ng signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2    ' RSA with SHA2-256 signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1    ' RSA with SHA1 signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1    ' DSA with SHA-1 signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng ' ECDSA with SHA-ng signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2  ' ECDSA with SHA2-256 signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1  ' ECDSA with SHA-1 signing \n    CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA    ' preferSignedData \n    CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY    ' canNotDecryptAny \n    CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE  ' preferBinaryInside \n\n    ' 1 2 840 113549 1 9 16 2 1 receiptRequest \n    CRYPT_CERTINFO_CMS_RECEIPTREQUEST\n    CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER  ' contentIdentifier \n    CRYPT_CERTINFO_CMS_RECEIPT_FROM         ' receiptsFrom \n    CRYPT_CERTINFO_CMS_RECEIPT_TO           ' receiptsTo \n\n    ' 1 2 840 113549 1 9 16 2 2 essSecurityLabel \n    CRYPT_CERTINFO_CMS_SECURITYLABEL\n    CRYPT_CERTINFO_CMS_SECLABEL_POLICY      ' securityPolicyIdentifier \n    CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION  ' securityClassification \n    CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK ' privacyMark \n    CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE     ' securityCategories.securityCategory.type \n    CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE    ' securityCategories.securityCategory.value \n\n    ' 1 2 840 113549 1 9 16 2 3 mlExpansionHistory \n    CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY\n    CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER  ' mlData.mailListIdentifier.issuerAndSerialNumber \n    CRYPT_CERTINFO_CMS_MLEXP_TIME           ' mlData.expansionTime \n    CRYPT_CERTINFO_CMS_MLEXP_NONE           ' mlData.mlReceiptPolicy.none \n    CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF      ' mlData.mlReceiptPolicy.insteadOf.generalNames.generalName \n    CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO   ' mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName \n\n    ' 1 2 840 113549 1 9 16 2 4 contentHints \n    CRYPT_CERTINFO_CMS_CONTENTHINTS\n    CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION  ' contentDescription \n    CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE     ' contentType \n\n    ' 1 2 840 113549 1 9 16 2 9 equivalentLabels \n    CRYPT_CERTINFO_CMS_EQUIVALENTLABEL\n    CRYPT_CERTINFO_CMS_EQVLABEL_POLICY      ' securityPolicyIdentifier \n    CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION  ' securityClassification \n    CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK ' privacyMark \n    CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE     ' securityCategories.securityCategory.type \n    CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE    ' securityCategories.securityCategory.value \n\n    ' 1 2 840 113549 1 9 16 2 12 signingCertificate \n    CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE\n    CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID  ' certs.essCertID \n    CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES ' policies.policyInformation.policyIdentifier \n\n    ' 1 2 840 113549 1 9 16 2 47 signingCertificateV2 \n    CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2\n    CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2  ' certs.essCertID \n    CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES ' policies.policyInformation.policyIdentifier \n\n    ' 1 2 840 113549 1 9 16 2 15 signaturePolicyID \n    CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID\n    CRYPT_CERTINFO_CMS_SIGPOLICYID          ' sigPolicyID \n    CRYPT_CERTINFO_CMS_SIGPOLICYHASH        ' sigPolicyHash \n    CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI     ' sigPolicyQualifiers.sigPolicyQualifier.cPSuri \n    CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION\n        ' sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization \n    CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS\n        ' sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers \n    CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT\n        ' sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText \n\n    ' 1 2 840 113549 1 9 16 9 signatureTypeIdentifier \n    CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER\n    CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG  ' originatorSig \n    CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG  ' domainSig \n    CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES  ' additionalAttributesSig \n    CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG  ' reviewSig \n\n    ' 1 2 840 113549 1 9 25 3 randomNonce \n    CRYPT_CERTINFO_CMS_NONCE                ' randomNonce \n\n'      SCEP attributes:\n'      2 16 840 1 113733 1 9 2 messageType\n'      2 16 840 1 113733 1 9 3 pkiStatus\n'      2 16 840 1 113733 1 9 4 failInfo\n'      2 16 840 1 113733 1 9 5 senderNonce\n'      2 16 840 1 113733 1 9 6 recipientNonce\n'      2 16 840 1 113733 1 9 7 transID \n    CRYPT_CERTINFO_SCEP_MESSAGETYPE         ' messageType \n    CRYPT_CERTINFO_SCEP_PKISTATUS           ' pkiStatus \n    CRYPT_CERTINFO_SCEP_FAILINFO            ' failInfo \n    CRYPT_CERTINFO_SCEP_SENDERNONCE         ' senderNonce \n    CRYPT_CERTINFO_SCEP_RECIPIENTNONCE      ' recipientNonce \n    CRYPT_CERTINFO_SCEP_TRANSACTIONID       ' transID \n\n    ' 1 3 6 1 4 1 311 2 1 10 spcAgencyInfo \n    CRYPT_CERTINFO_CMS_SPCAGENCYINFO\n    CRYPT_CERTINFO_CMS_SPCAGENCYURL         ' spcAgencyInfo.url \n\n    ' 1 3 6 1 4 1 311 2 1 11 spcStatementType \n    CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE\n    CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING    ' individualCodeSigning \n    CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING    ' commercialCodeSigning \n\n    ' 1 3 6 1 4 1 311 2 1 12 spcOpusInfo \n    CRYPT_CERTINFO_CMS_SPCOPUSINFO\n    CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME     ' spcOpusInfo.name \n    CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL      ' spcOpusInfo.url \n\n    ' Used internally \n    CRYPT_CERTINFO_LAST\n    CRYPT_KEYINFO_FIRST = 3000\n\n    '*******************\n    ' Keyset attributes \n    '*******************\n\n    CRYPT_KEYINFO_QUERY             ' Keyset query \n    CRYPT_KEYINFO_QUERY_REQUESTS    ' Query of requests in cert store \n\n    ' Used internally \n    CRYPT_KEYINFO_LAST\n    CRYPT_DEVINFO_FIRST = 4000\n\n    '*******************\n    ' Device attributes \n    '*******************\n\n    CRYPT_DEVINFO_INITIALISE    ' Initialise device for use \n        CRYPT_DEVINFO_INITIALIZE = CRYPT_DEVINFO_INITIALISE\n    CRYPT_DEVINFO_AUTHENT_USER  ' Authenticate user to device \n    CRYPT_DEVINFO_AUTHENT_SUPERVISOR    ' Authenticate supervisor to dev.\n    CRYPT_DEVINFO_SET_AUTHENT_USER  ' Set user authent.value \n    CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR    ' Set supervisor auth.val.\n    CRYPT_DEVINFO_ZEROISE   ' Zeroise device \n        CRYPT_DEVINFO_ZEROIZE = CRYPT_DEVINFO_ZEROISE\n    CRYPT_DEVINFO_LOGGEDIN      ' Whether user is logged in \n    CRYPT_DEVINFO_LABEL         ' Device/token label \n\n    ' Used internally \n    CRYPT_DEVINFO_LAST\n    CRYPT_ENVINFO_FIRST = 5000\n\n    '*********************\n    ' Envelope attributes \n    '*********************\n\n'      Pseudo-information on an envelope or meta-information which is used to\n'      control the way that data in an envelope is processed \n    CRYPT_ENVINFO_DATASIZE          ' Data size information \n    CRYPT_ENVINFO_COMPRESSION       ' Compression information \n    CRYPT_ENVINFO_CONTENTTYPE       ' Inner CMS content type \n    CRYPT_ENVINFO_DETACHEDSIGNATURE ' Detached signature \n    CRYPT_ENVINFO_SIGNATURE_RESULT  ' Signature check result \n    CRYPT_ENVINFO_INTEGRITY         ' Integrity-protection level \n\n    ' Resources required for enveloping/deenveloping \n    CRYPT_ENVINFO_PASSWORD          ' User password \n    CRYPT_ENVINFO_KEY               ' Conventional encryption key \n    CRYPT_ENVINFO_SIGNATURE         ' Signature/signature check key \n    CRYPT_ENVINFO_SIGNATURE_EXTRADATA   ' Extra information added to CMS sigs \n    CRYPT_ENVINFO_RECIPIENT         ' Recipient email address \n    CRYPT_ENVINFO_PUBLICKEY         ' PKC encryption key \n    CRYPT_ENVINFO_PRIVATEKEY        ' PKC decryption key \n    CRYPT_ENVINFO_PRIVATEKEY_LABEL  ' Label of PKC decryption key \n    CRYPT_ENVINFO_ORIGINATOR        ' Originator info/key \n    CRYPT_ENVINFO_SESSIONKEY        ' Session key \n    CRYPT_ENVINFO_HASH              ' Hash value \n    CRYPT_ENVINFO_TIMESTAMP         ' Timestamp information \n\n    ' Keysets used to retrieve keys needed for enveloping/deenveloping \n    CRYPT_ENVINFO_KEYSET_SIGCHECK   ' Signature check keyset \n    CRYPT_ENVINFO_KEYSET_ENCRYPT    ' PKC encryption keyset \n    CRYPT_ENVINFO_KEYSET_DECRYPT    ' PKC decryption keyset \n\n    ' Used internally \n    CRYPT_ENVINFO_LAST\n    CRYPT_SESSINFO_FIRST = 6000\n\n    '********************\n    ' Session attributes \n    '********************\n\n    ' Pseudo-information about the session \n    CRYPT_SESSINFO_ACTIVE           ' Whether session is active \n    CRYPT_SESSINFO_CONNECTIONACTIVE ' Whether network connection is active \n\n    ' Security-related information \n    CRYPT_SESSINFO_USERNAME         ' User name \n    CRYPT_SESSINFO_PASSWORD         ' Password \n    CRYPT_SESSINFO_PRIVATEKEY       ' Server/client private key \n    CRYPT_SESSINFO_KEYSET           ' Certificate store \n    CRYPT_SESSINFO_AUTHRESPONSE     ' Session authorisation OK \n\n    ' Client/server information \n    CRYPT_SESSINFO_SERVER_NAME      ' Server name \n    CRYPT_SESSINFO_SERVER_PORT      ' Server port number \n    CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 ' Server key fingerprint \n    CRYPT_SESSINFO_CLIENT_NAME      ' Client name \n    CRYPT_SESSINFO_CLIENT_PORT      ' Client port number \n    CRYPT_SESSINFO_SESSION          ' Transport mechanism \n    CRYPT_SESSINFO_NETWORKSOCKET    ' User-supplied network socket \n\n    ' Generic protocol-related information \n    CRYPT_SESSINFO_VERSION          ' Protocol version \n    CRYPT_SESSINFO_REQUEST          ' Cert.request object \n    CRYPT_SESSINFO_RESPONSE         ' Cert.response object \n    CRYPT_SESSINFO_CACERTIFICATE    ' Issuing CA certificate \n\n    ' Protocol-specific information \n    CRYPT_SESSINFO_CMP_REQUESTTYPE  ' Request type \n    CRYPT_SESSINFO_CMP_PRIVKEYSET   ' Private-key keyset \n    CRYPT_SESSINFO_SSH_CHANNEL      ' SSH current channel \n    CRYPT_SESSINFO_SSH_CHANNEL_TYPE ' SSH channel type \n    CRYPT_SESSINFO_SSH_CHANNEL_ARG1 ' SSH channel argument 1 \n    CRYPT_SESSINFO_SSH_CHANNEL_ARG2 ' SSH channel argument 2 \n    CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE ' SSH channel active \n    CRYPT_SESSINFO_SSL_OPTIONS      ' SSL/TLS protocol options \n    CRYPT_SESSINFO_SSL_SUBPROTOCOL  ' SSL/TLS additional sub-protocol \n    CRYPT_SESSINFO_SSL_WSPROTOCOL   ' SSL/TLS WebSockets sub-protocol \n    CRYPT_SESSINFO_SSL_EAPCHALLENGE ' SSL/TLS EAP challenge \n    CRYPT_SESSINFO_SSL_EAPKEY       ' SSL/TLS EAP key \n    CRYPT_SESSINFO_TSP_MSGIMPRINT   ' TSP message imprint \n\n    ' Used internally \n    CRYPT_SESSINFO_LAST\n    CRYPT_USERINFO_FIRST = 7000\n\n    '********************\n    ' User attributes \n    '********************\n\n    ' Security-related information \n    CRYPT_USERINFO_PASSWORD         ' Password \n\n    ' User role-related information \n    CRYPT_USERINFO_CAKEY_CERTSIGN   ' CA cert signing key \n    CRYPT_USERINFO_CAKEY_CRLSIGN    ' CA CRL signing key \n    CRYPT_USERINFO_CAKEY_RTCSSIGN   ' CA RTCS signing key \n    CRYPT_USERINFO_CAKEY_OCSPSIGN   ' CA OCSP signing key \n\n    ' Used internally for range checking \n    CRYPT_USERINFO_LAST\n    CRYPT_ATTRIBUTE_LAST = CRYPT_USERINFO_LAST\n\n    \n\nEnd Enum\n\n'****************************************************************************\n'*                                                                           *\n'*                       Attribute Subtypes and Related Values               *\n'*                                                                           *\n'****************************************************************************\n\n' Flags for the X.509 keyUsage extension \n\n  Public Const CRYPT_KEYUSAGE_NONE As Long = &H000\n  Public Const CRYPT_KEYUSAGE_DIGITALSIGNATURE As Long = &H001\n  Public Const CRYPT_KEYUSAGE_NONREPUDIATION As Long = &H002\n  Public Const CRYPT_KEYUSAGE_KEYENCIPHERMENT As Long = &H004\n  Public Const CRYPT_KEYUSAGE_DATAENCIPHERMENT As Long = &H008\n  Public Const CRYPT_KEYUSAGE_KEYAGREEMENT As Long = &H010\n  Public Const CRYPT_KEYUSAGE_KEYCERTSIGN As Long = &H020\n  Public Const CRYPT_KEYUSAGE_CRLSIGN As Long = &H040\n  Public Const CRYPT_KEYUSAGE_ENCIPHERONLY As Long = &H080\n  Public Const CRYPT_KEYUSAGE_DECIPHERONLY As Long = &H100\n  Public Const CRYPT_KEYUSAGE_LAST As Long = &H200   ' Last possible value \n\n' X.509 cRLReason and cryptlib cRLExtReason codes \n\n  Public Const CRYPT_CRLREASON_UNSPECIFIED As Long = 0\n  Public Const CRYPT_CRLREASON_KEYCOMPROMISE As Long = 1\n  Public Const CRYPT_CRLREASON_CACOMPROMISE As Long = 2\n  Public Const CRYPT_CRLREASON_AFFILIATIONCHANGED As Long = 3\n  Public Const CRYPT_CRLREASON_SUPERSEDED As Long = 4\n  Public Const CRYPT_CRLREASON_CESSATIONOFOPERATION As Long = 5\n  Public Const CRYPT_CRLREASON_CERTIFICATEHOLD As Long = 6\n  Public Const CRYPT_CRLREASON_REMOVEFROMCRL As Long = 8\n  Public Const CRYPT_CRLREASON_PRIVILEGEWITHDRAWN As Long = 9\n  Public Const CRYPT_CRLREASON_AACOMPROMISE As Long = 10\n  Public Const CRYPT_CRLREASON_LAST As Long = 11\n  Public Const CRYPT_CRLREASON_NEVERVALID As Long = 20\n  Public Const CRYPT_CRLEXTREASON_LAST  As Long = 21\n\n\n'  X.509 CRL reason flags.  These identify the same thing as the cRLReason\n'  codes but allow for multiple reasons to be specified.  Note that these\n'  don't follow the X.509 naming since in that scheme the enumerated types\n'  and bitflags have the same names \n\n  Public Const CRYPT_CRLREASONFLAG_UNUSED As Long = &H001\n  Public Const CRYPT_CRLREASONFLAG_KEYCOMPROMISE As Long = &H002\n  Public Const CRYPT_CRLREASONFLAG_CACOMPROMISE As Long = &H004\n  Public Const CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED As Long = &H008\n  Public Const CRYPT_CRLREASONFLAG_SUPERSEDED As Long = &H010\n  Public Const CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION As Long = &H020\n  Public Const CRYPT_CRLREASONFLAG_CERTIFICATEHOLD As Long = &H040\n  Public Const CRYPT_CRLREASONFLAG_LAST As Long = &H080   ' Last poss.value \n\n' X.509 CRL holdInstruction codes \n\n  Public Const CRYPT_HOLDINSTRUCTION_NONE As Long = 0\n  Public Const CRYPT_HOLDINSTRUCTION_CALLISSUER As Long = 1\n  Public Const CRYPT_HOLDINSTRUCTION_REJECT As Long = 2\n  Public Const CRYPT_HOLDINSTRUCTION_PICKUPTOKEN As Long = 3\n  Public Const CRYPT_HOLDINSTRUCTION_LAST  As Long = 4\n\n\n' Certificate checking compliance levels \n\nPublic Enum CRYPT_COMPLIANCELEVEL_TYPE\n \n    CRYPT_COMPLIANCELEVEL_OBLIVIOUS\n    CRYPT_COMPLIANCELEVEL_REDUCED\n    CRYPT_COMPLIANCELEVEL_STANDARD\n    CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\n    CRYPT_COMPLIANCELEVEL_PKIX_FULL\n    CRYPT_COMPLIANCELEVEL_LAST \n    \n\nEnd Enum\n\n' Flags for the Netscape netscape-cert-type extension \n\n  Public Const CRYPT_NS_CERTTYPE_SSLCLIENT As Long = &H001\n  Public Const CRYPT_NS_CERTTYPE_SSLSERVER As Long = &H002\n  Public Const CRYPT_NS_CERTTYPE_SMIME As Long = &H004\n  Public Const CRYPT_NS_CERTTYPE_OBJECTSIGNING As Long = &H008\n  Public Const CRYPT_NS_CERTTYPE_RESERVED As Long = &H010\n  Public Const CRYPT_NS_CERTTYPE_SSLCA As Long = &H020\n  Public Const CRYPT_NS_CERTTYPE_SMIMECA As Long = &H040\n  Public Const CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA As Long = &H080\n  Public Const CRYPT_NS_CERTTYPE_LAST As Long = &H100   ' Last possible value \n\n' Flags for the SET certificate-type extension \n\n  Public Const CRYPT_SET_CERTTYPE_CARD As Long = &H001\n  Public Const CRYPT_SET_CERTTYPE_MER As Long = &H002\n  Public Const CRYPT_SET_CERTTYPE_PGWY As Long = &H004\n  Public Const CRYPT_SET_CERTTYPE_CCA As Long = &H008\n  Public Const CRYPT_SET_CERTTYPE_MCA As Long = &H010\n  Public Const CRYPT_SET_CERTTYPE_PCA As Long = &H020\n  Public Const CRYPT_SET_CERTTYPE_GCA As Long = &H040\n  Public Const CRYPT_SET_CERTTYPE_BCA As Long = &H080\n  Public Const CRYPT_SET_CERTTYPE_RCA As Long = &H100\n  Public Const CRYPT_SET_CERTTYPE_ACQ As Long = &H200\n  Public Const CRYPT_SET_CERTTYPE_LAST As Long = &H400   ' Last possible value \n\n' CMS contentType values \n\nPublic Enum CRYPT_CONTENT_TYPE\n CRYPT_CONTENT_NONE\n CRYPT_CONTENT_DATA\n               CRYPT_CONTENT_SIGNEDDATA\n               CRYPT_CONTENT_ENVELOPEDDATA\n               CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA\n               CRYPT_CONTENT_DIGESTEDDATA\n               CRYPT_CONTENT_ENCRYPTEDDATA\n               CRYPT_CONTENT_COMPRESSEDDATA\n               CRYPT_CONTENT_AUTHDATA\n               CRYPT_CONTENT_AUTHENVDATA\n               CRYPT_CONTENT_TSTINFO\n               CRYPT_CONTENT_SPCINDIRECTDATACONTEXT\n               CRYPT_CONTENT_RTCSREQUEST\n               CRYPT_CONTENT_RTCSRESPONSE\n               CRYPT_CONTENT_RTCSRESPONSE_EXT\n               CRYPT_CONTENT_MRTD\n               CRYPT_CONTENT_LAST\n             \n\nEnd Enum\n\n' ESS securityClassification codes \n\n  Public Const CRYPT_CLASSIFICATION_UNMARKED As Long = 0\n  Public Const CRYPT_CLASSIFICATION_UNCLASSIFIED As Long = 1\n  Public Const CRYPT_CLASSIFICATION_RESTRICTED As Long = 2\n  Public Const CRYPT_CLASSIFICATION_CONFIDENTIAL As Long = 3\n  Public Const CRYPT_CLASSIFICATION_SECRET As Long = 4\n  Public Const CRYPT_CLASSIFICATION_TOP_SECRET As Long = 5\n  Public Const CRYPT_CLASSIFICATION_LAST As Long = 255\n\n\n' RTCS certificate status \n\nPublic Enum CRYPT_CERTSTATUS_TYPE\n \n    CRYPT_CERTSTATUS_NONE           ' No certificate status \n    CRYPT_CERTSTATUS_VALID          ' Certificate valid \n    CRYPT_CERTSTATUS_NOTVALID       ' Certificate isn't valid \n    CRYPT_CERTSTATUS_NONAUTHORITATIVE  ' Response is non-authoritative \n    CRYPT_CERTSTATUS_UNKNOWN        ' Certificate status unknown \n    CRYPT_CERTSTATUS_LAST           ' Last possible certificate status \n    \n\nEnd Enum\n\n' OCSP revocation status \n\n  Public Const CRYPT_OCSPSTATUS_NOTREVOKED As Long = 0\n  Public Const CRYPT_OCSPSTATUS_REVOKED As Long = 1\n  Public Const CRYPT_OCSPSTATUS_UNKNOWN  As Long = 2\n\n\n'  The amount of detail to include in signatures when signing certificate\n'  objects \n\nPublic Enum CRYPT_SIGNATURELEVEL_TYPE\n\n    CRYPT_SIGNATURELEVEL_NONE       ' Include only signature \n    CRYPT_SIGNATURELEVEL_SIGNERCERT ' Include signer cert \n    CRYPT_SIGNATURELEVEL_ALL        ' Include all relevant info \n    CRYPT_SIGNATURELEVEL_LAST       ' Last possible sig.level type \n    \n\nEnd Enum\n\n'  The level of integrity protection to apply to enveloped data.  The \n'  default envelope protection for an envelope with keying information \n'  applied is encryption, this can be modified to use MAC-only protection\n'  (with no encryption) or hybrid encryption + authentication \n\nPublic Enum CRYPT_INTEGRITY_TYPE\n\n    CRYPT_INTEGRITY_NONE            ' No integrity protection \n    CRYPT_INTEGRITY_MACONLY         ' MAC only, no encryption \n    CRYPT_INTEGRITY_FULL            ' Encryption + ingerity protection \n    \n\nEnd Enum\n\n'  The certificate export format type, which defines the format in which a\n'  certificate object is exported \n\nPublic Enum CRYPT_CERTFORMAT_TYPE\n\n    CRYPT_CERTFORMAT_NONE           ' No certificate format \n    CRYPT_CERTFORMAT_CERTIFICATE    ' DER-encoded certificate \n    CRYPT_CERTFORMAT_CERTCHAIN      ' PKCS #7 certificate chain \n    CRYPT_CERTFORMAT_TEXT_CERTIFICATE   ' base-64 wrapped cert \n    CRYPT_CERTFORMAT_TEXT_CERTCHAIN     ' base-64 wrapped cert chain \n    CRYPT_CERTFORMAT_XML_CERTIFICATE    ' XML wrapped cert \n    CRYPT_CERTFORMAT_XML_CERTCHAIN  ' XML wrapped cert chain \n    CRYPT_CERTFORMAT_LAST           ' Last possible cert.format type \n    \n\nEnd Enum\n\n' CMP request types \n\nPublic Enum CRYPT_REQUESTTYPE_TYPE\n\n    CRYPT_REQUESTTYPE_NONE          ' No request type \n    CRYPT_REQUESTTYPE_INITIALISATION    ' Initialisation request \n        CRYPT_REQUESTTYPE_INITIALIZATION = CRYPT_REQUESTTYPE_INITIALISATION\n    CRYPT_REQUESTTYPE_CERTIFICATE   ' Certification request \n    CRYPT_REQUESTTYPE_KEYUPDATE     ' Key update request \n    CRYPT_REQUESTTYPE_REVOCATION    ' Cert revocation request \n    CRYPT_REQUESTTYPE_PKIBOOT       ' PKIBoot request \n    CRYPT_REQUESTTYPE_LAST          ' Last possible request type \n    \n\nEnd Enum\n\n' Key ID types \n\nPublic Enum CRYPT_KEYID_TYPE\n\n    CRYPT_KEYID_NONE                ' No key ID type \n    CRYPT_KEYID_NAME                ' Key owner name \n    CRYPT_KEYID_URI                 ' Key owner URI \n        CRYPT_KEYID_EMAIL = CRYPT_KEYID_URI  ' Synonym: owner email addr.\n    CRYPT_KEYID_LAST                ' Last possible key ID type \n    \n\nEnd Enum\n\n' The encryption object types \n\nPublic Enum CRYPT_OBJECT_TYPE\n\n    CRYPT_OBJECT_NONE               ' No object type \n    CRYPT_OBJECT_ENCRYPTED_KEY      ' Conventionally encrypted key \n    CRYPT_OBJECT_PKCENCRYPTED_KEY   ' PKC-encrypted key \n    CRYPT_OBJECT_KEYAGREEMENT       ' Key agreement information \n    CRYPT_OBJECT_SIGNATURE          ' Signature \n    CRYPT_OBJECT_LAST               ' Last possible object type \n    \n\nEnd Enum\n\n' Object/attribute error type information \n\nPublic Enum CRYPT_ERRTYPE_TYPE\n\n    CRYPT_ERRTYPE_NONE              ' No error information \n    CRYPT_ERRTYPE_ATTR_SIZE         ' Attribute data too small or large \n    CRYPT_ERRTYPE_ATTR_VALUE        ' Attribute value is invalid \n    CRYPT_ERRTYPE_ATTR_ABSENT       ' Required attribute missing \n    CRYPT_ERRTYPE_ATTR_PRESENT      ' Non-allowed attribute present \n    CRYPT_ERRTYPE_CONSTRAINT        ' Cert: Constraint violation in object \n    CRYPT_ERRTYPE_ISSUERCONSTRAINT  ' Cert: Constraint viol.in issuing cert \n    CRYPT_ERRTYPE_LAST              ' Last possible error info type \n    \n\nEnd Enum\n\n' Cert store management action type \n\nPublic Enum CRYPT_CERTACTION_TYPE\n\n    CRYPT_CERTACTION_NONE           ' No cert management action \n    CRYPT_CERTACTION_CREATE         ' Create cert store \n    CRYPT_CERTACTION_CONNECT        ' Connect to cert store \n    CRYPT_CERTACTION_DISCONNECT     ' Disconnect from cert store \n    CRYPT_CERTACTION_ERROR          ' Error information \n    CRYPT_CERTACTION_ADDUSER        ' Add PKI user \n    CRYPT_CERTACTION_DELETEUSER     ' Delete PKI user \n    CRYPT_CERTACTION_REQUEST_CERT   ' Cert request \n    CRYPT_CERTACTION_REQUEST_RENEWAL ' Cert renewal request \n    CRYPT_CERTACTION_REQUEST_REVOCATION ' Cert revocation request \n    CRYPT_CERTACTION_CERT_CREATION  ' Cert creation \n    CRYPT_CERTACTION_CERT_CREATION_COMPLETE ' Confirmation of cert creation \n    CRYPT_CERTACTION_CERT_CREATION_DROP     ' Cancellation of cert creation \n    CRYPT_CERTACTION_CERT_CREATION_REVERSE  ' Cancel of creation w.revocation \n    CRYPT_CERTACTION_RESTART_CLEANUP  ' Delete reqs after restart \n    CRYPT_CERTACTION_RESTART_REVOKE_CERT  ' Complete revocation after restart \n    CRYPT_CERTACTION_ISSUE_CERT     ' Cert issue \n    CRYPT_CERTACTION_ISSUE_CRL      ' CRL issue \n    CRYPT_CERTACTION_REVOKE_CERT    ' Cert revocation \n    CRYPT_CERTACTION_EXPIRE_CERT    ' Cert expiry \n    CRYPT_CERTACTION_CLEANUP        ' Clean up on restart \n    CRYPT_CERTACTION_LAST           ' Last possible cert store log action \n    \n\nEnd Enum\n\n' Session sub-protocol types \n\nPublic Enum CRYPT_SUBPROTOCOL_TYPE\n\n    CRYPT_SUBPROTOCOL_NONE          ' No sub-protocol type \n    CRYPT_SUBPROTOCOL_WEBSOCKETS    ' Websockets \n    CRYPT_SUBPROTOCOL_EAPTTLS       ' EAP-TTLS \n    CRYPT_SUBPROTOCOL_LAST          ' Last possible sub-protocol type \n    \n\nEnd Enum\n\n'  SSL/TLS protocol options.  CRYPT_SSLOPTION_MINVER_SSLV3 is the same as \n'  CRYPT_SSLOPTION_NONE since this is the baseline, although it'll never be\n'  encountered since SSLv3 is disabled \n\n  Public Const CRYPT_SSLOPTION_NONE As Long = &H000\n  Public Const CRYPT_SSLOPTION_MINVER_SSLV3 As Long = &H000   ' Min.protocol version \n  Public Const CRYPT_SSLOPTION_MINVER_TLS10 As Long = &H001\n  Public Const CRYPT_SSLOPTION_MINVER_TLS11 As Long = &H002\n  Public Const CRYPT_SSLOPTION_MINVER_TLS12 As Long = &H003\n  Public Const CRYPT_SSLOPTION_MINVER_TLS13 As Long = &H004\n  Public Const CRYPT_SSLOPTION_MANUAL_CERTCHECK As Long = &H008   ' Require manual cert.verif.\n  Public Const CRYPT_SSLOPTION_DISABLE_NAMEVERIFY As Long = &H010   ' Disable cert hostname check \n  Public Const CRYPT_SSLOPTION_DISABLE_CERTVERIFY As Long = &H020   ' Disable certificate check \n  Public Const CRYPT_SSLOPTION_SUITEB_128 As Long = &H100   ' SuiteB security levels (may \n  Public Const CRYPT_SSLOPTION_SUITEB_256 As Long = &H200   '  vanish in future releases) \n\n'****************************************************************************\n'*                                                                           *\n'*                               General Constants                           *\n'*                                                                           *\n'****************************************************************************\n\n' The maximum user key size - 2048 bits \n\n  Public Const CRYPT_MAX_KEYSIZE As Long = 256\n\n' The maximum IV/cipher block size - 256 bits \n\n  Public Const CRYPT_MAX_IVSIZE As Long = 32\n\n'  The maximum public-key component size - 4096 bits, and maximum component\n'  size for ECCs - 576 bits (to handle the P521 curve) \n\n  Public Const CRYPT_MAX_PKCSIZE As Long = 512\n  Public Const CRYPT_MAX_PKCSIZE_ECC As Long = 72\n\n'  The maximum hash size - 512 bits.  Before 3.4 this was 256 bits, in the \n'  3.4 release it was increased to 512 bits to accommodate SHA-3 \n\n  Public Const CRYPT_MAX_HASHSIZE As Long = 64\n\n' The maximum size of a text string (e.g.key owner name) \n\n  Public Const CRYPT_MAX_TEXTSIZE As Long = 64\n\n'  A magic value indicating that the default setting for this parameter\n'  should be used.  The parentheses are to catch potential erroneous use \n'  in an expression \n\n  Public Const CRYPT_USE_DEFAULT As Long = -100\n\n' A magic value for unused parameters \n\n  Public Const CRYPT_UNUSED As Long = -101\n\n'  Cursor positioning codes for certificate/CRL extensions.  The parentheses \n'  are to catch potential erroneous use in an expression \n\n  Public Const CRYPT_CURSOR_FIRST As Long = -200\n  Public Const CRYPT_CURSOR_PREVIOUS As Long = -201\n  Public Const CRYPT_CURSOR_NEXT As Long = -202\n  Public Const CRYPT_CURSOR_LAST As Long = -203\n\n'  The type of information polling to perform to get random seed \n'  information.  These values have to be negative because they're used\n'  as magic length values for cryptAddRandom().  The parentheses are to \n'  catch potential erroneous use in an expression \n\n  Public Const CRYPT_RANDOM_FASTPOLL As Long = -300\n  Public Const CRYPT_RANDOM_SLOWPOLL As Long = -301\n\n' Whether the PKC key is a public or private key \n\n  Public Const CRYPT_KEYTYPE_PRIVATE As Long = 0\n  Public Const CRYPT_KEYTYPE_PUBLIC As Long = 1\n\n' Keyset open options \n\nPublic Enum CRYPT_KEYOPT_TYPE\n\n    CRYPT_KEYOPT_NONE               ' No options \n    CRYPT_KEYOPT_READONLY           ' Open keyset in read-only mode \n    CRYPT_KEYOPT_CREATE             ' Create a new keyset \n    CRYPT_KEYOPT_LAST               ' Last possible key option type \n    \n\nEnd Enum\n\n' The various cryptlib objects - these are just integer handles \n\nREM  CRYPT_CERTIFICATE = Long\nREM  CRYPT_CONTEXT = Long\nREM  CRYPT_DEVICE = Long\nREM  CRYPT_ENVELOPE = Long\nREM  CRYPT_KEYSET = Long\nREM  CRYPT_SESSION = Long\nREM  CRYPT_USER = Long\n\n'  Sometimes we don't know the exact type of a cryptlib object, so we use a\n'  generic handle type to identify it \n\nREM  CRYPT_HANDLE = Long\n\n'****************************************************************************\n'*                                                                           *\n'*                           Encryption Data Structures                      *\n'*                                                                           *\n'****************************************************************************\n\n' Results returned from the capability query \n\nPublic Type CRYPT_QUERY_INFO \n    ' Algorithm information \n    algoName(CRYPT_MAX_TEXTSIZE-1) As Byte' Algorithm name \n    blockSize As Long                  ' Block size of the algorithm \n    minKeySize As Long                 ' Minimum key size in bytes \n    keySize As Long                    ' Recommended key size in bytes \n    maxKeySize As Long                 ' Maximum key size in bytes \n    \n\nEnd Type\n\n'  Results returned from the encoded object query.  These provide\n'  information on the objects created by cryptExportKey()/\n'  cryptCreateSignature() \n\nPublic Type CRYPT_OBJECT_INFO \n    ' The object type \n    objectType As CRYPT_OBJECT_TYPE\n\n    ' The encryption algorithm and mode \n    cryptAlgo As CRYPT_ALGO_TYPE\n    cryptMode As CRYPT_MODE_TYPE\n\n'      The hash algorithm for signature objects or PRF algorithm for derived \n'      keys \n    hashAlgo As CRYPT_ALGO_TYPE\n\n    ' The salt and PRF iterations for derived keys \n    salt(CRYPT_MAX_HASHSIZE-1) As Byte\n    saltSize As Long\n    iterations As Long\n    \n\nEnd Type\n\n'  Key information for the public-key encryption algorithms.  These fields\n'  are not accessed directly, but can be manipulated with the init/set/\n'  destroyComponents() macros \n\nPublic Type CRYPT_PKCINFO_RSA \n    ' Status information \n    isPublicKey As Long            ' Whether this is a public or private key \n\n    ' Public components \n    n(CRYPT_MAX_PKCSIZE-1) As Byte   ' Modulus \n    nLen As Long                   ' Length of modulus in bits \n    e(CRYPT_MAX_PKCSIZE-1) As Byte   ' Public exponent \n    eLen As Long                   ' Length of public exponent in bits \n\n    ' Private components \n    d(CRYPT_MAX_PKCSIZE-1) As Byte   ' Private exponent \n    dLen As Long                   ' Length of private exponent in bits \n    p(CRYPT_MAX_PKCSIZE-1) As Byte   ' Prime factor 1 \n    pLen As Long                   ' Length of prime factor 1 in bits \n    q(CRYPT_MAX_PKCSIZE-1) As Byte   ' Prime factor 2 \n    qLen As Long                   ' Length of prime factor 2 in bits \n    u(CRYPT_MAX_PKCSIZE-1) As Byte   ' Mult.inverse of q, mod p \n    uLen As Long                   ' Length of private exponent in bits \n    e1(CRYPT_MAX_PKCSIZE-1) As Byte  ' Private exponent 1 (PKCS) \n    e1Len As Long                  ' Length of private exponent in bits \n    e2(CRYPT_MAX_PKCSIZE-1) As Byte  ' Private exponent 2 (PKCS) \n    e2Len As Long                  ' Length of private exponent in bits \n    \n\nEnd Type\n\nPublic Type CRYPT_PKCINFO_DLP \n    ' Status information \n    isPublicKey As Long            ' Whether this is a public or private key \n\n    ' Public components \n    p(CRYPT_MAX_PKCSIZE-1) As Byte   ' Prime modulus \n    pLen As Long                   ' Length of prime modulus in bits \n    q(CRYPT_MAX_PKCSIZE-1) As Byte   ' Prime divisor \n    qLen As Long                   ' Length of prime divisor in bits \n    g(CRYPT_MAX_PKCSIZE-1) As Byte   ' h^( ( p - 1 ) / q ) mod p \n    gLen As Long                   ' Length of g in bits \n    y(CRYPT_MAX_PKCSIZE-1) As Byte   ' Public random integer \n    yLen As Long                   ' Length of public integer in bits \n\n    ' Private components \n    x(CRYPT_MAX_PKCSIZE-1) As Byte   ' Private random integer \n    xLen As Long                   ' Length of private integer in bits \n    \n\nEnd Type\n\nPublic Enum CRYPT_ECCCURVE_TYPE\n\n'      Named ECC curves.  Since these need to be mapped to all manner of\n'      protocol- and mechanism-specific identifiers, when updating this list \n'      grep for occurrences of the string \"P256\" (the most common one) and \n'      check whether any related mapping tables need to be updated \n    CRYPT_ECCCURVE_NONE         ' No ECC curve type \n    CRYPT_ECCCURVE_P256         ' NIST P256/X9.62 P256v1/SECG p256r1 curve \n    CRYPT_ECCCURVE_P384         ' NIST P384, SECG p384r1 curve \n    CRYPT_ECCCURVE_P521         ' NIST P521, SECG p521r1 \n    CRYPT_ECCCURVE_BRAINPOOL_P256  ' Brainpool p256r1 \n    CRYPT_ECCCURVE_BRAINPOOL_P384  ' Brainpool p384r1 \n    CRYPT_ECCCURVE_BRAINPOOL_P512  ' Brainpool p512r1 \n    CRYPT_ECCCURVE_LAST         ' Last valid ECC curve type \n    \n\nEnd Enum\n\nPublic Type CRYPT_PKCINFO_ECC \n    ' Status information \n    isPublicKey As Long            ' Whether this is a public or private key \n\n'      Curve domain parameters.  Either the curveType or the explicit domain\n'      parameters must be provided \n    curveType As CRYPT_ECCCURVE_TYPE  ' Named curve \n    p(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Prime defining Fq \n    pLen As Long                   ' Length of prime in bits \n    a(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Element in Fq defining curve \n    aLen As Long                   ' Length of element a in bits \n    b(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Element in Fq defining curve \n    bLen As Long                   ' Length of element b in bits \n    gx(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Element in Fq defining point \n    gxLen As Long                  ' Length of element gx in bits \n    gy(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Element in Fq defining point \n    gyLen As Long                  ' Length of element gy in bits \n    n(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Order of point \n    nLen As Long                   ' Length of order in bits \n    h(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Optional cofactor \n    hLen As Long                   ' Length of cofactor in bits \n\n    ' Public components \n    qx(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Point Q on the curve \n    qxLen As Long                  ' Length of point xq in bits \n    qy(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Point Q on the curve \n    qyLen As Long                  ' Length of point xy in bits \n\n    ' Private components \n    d(CRYPT_MAX_PKCSIZE_ECC-1) As Byte' Private random integer \n    dLen As Long                   ' Length of integer in bits \n    \n\nEnd Type\n\n'  Macros to initialise and destroy the structure that stores the components\n'  of a public key \n\n' C-macro not translated to Visual Basic code: \n'   #define cryptInitComponents( componentInfo, componentKeyType ) \n'    { memset( ( componentInfo ), 0, sizeof( *componentInfo ) ); \n'      ( componentInfo )->isPublicKey = ( ( componentKeyType ) ? 1 : 0 ); }\n'\n\n' C-macro not translated to Visual Basic code: \n'   #define cryptDestroyComponents( componentInfo ) \n'    memset( ( componentInfo ), 0, sizeof( *componentInfo ) )\n'\n\n' Macros to set a component of a public key \n\n' C-macro not translated to Visual Basic code: \n'   #define cryptSetComponent( destination, source, length ) \n'    { memcpy( ( destination ), ( source ), ( ( length ) + 7 ) >> 3 ); \n'      ( destination##Len ) = length; }\n'\n\n'****************************************************************************\n'*                                                                           *\n'*                               Status Codes                                *\n'*                                                                           *\n'****************************************************************************\n\n' No error in function call \n\n  Public Const CRYPT_OK As Long = 0       ' No error \n\n'  Error in parameters passed to function.  The parentheses are to catch \n'  potential erroneous use in an expression \n\n  Public Const CRYPT_ERROR_PARAM1 As Long = -1  ' Bad argument, parameter 1 \n  Public Const CRYPT_ERROR_PARAM2 As Long = -2  ' Bad argument, parameter 2 \n  Public Const CRYPT_ERROR_PARAM3 As Long = -3  ' Bad argument, parameter 3 \n  Public Const CRYPT_ERROR_PARAM4 As Long = -4  ' Bad argument, parameter 4 \n  Public Const CRYPT_ERROR_PARAM5 As Long = -5  ' Bad argument, parameter 5 \n  Public Const CRYPT_ERROR_PARAM6 As Long = -6  ' Bad argument, parameter 6 \n  Public Const CRYPT_ERROR_PARAM7 As Long = -7  ' Bad argument, parameter 7 \n\n' Errors due to insufficient resources \n\n  Public Const CRYPT_ERROR_MEMORY As Long = -10 ' Out of memory \n  Public Const CRYPT_ERROR_NOTINITED As Long = -11 ' Data has not been initialised \n  Public Const CRYPT_ERROR_INITED As Long = -12 ' Data has already been init'd \n  Public Const CRYPT_ERROR_NOSECURE As Long = -13 ' Opn.not avail.at requested sec.level \n  Public Const CRYPT_ERROR_RANDOM As Long = -14 ' No reliable random data available \n  Public Const CRYPT_ERROR_FAILED As Long = -15 ' Operation failed \n  Public Const CRYPT_ERROR_INTERNAL As Long = -16 ' Internal consistency check failed \n\n' Security violations \n\n  Public Const CRYPT_ERROR_NOTAVAIL As Long = -20 ' This type of opn.not available \n  Public Const CRYPT_ERROR_PERMISSION As Long = -21 ' No permiss.to perform this operation \n  Public Const CRYPT_ERROR_WRONGKEY As Long = -22 ' Incorrect key used to decrypt data \n  Public Const CRYPT_ERROR_INCOMPLETE As Long = -23 ' Operation incomplete/still in progress \n  Public Const CRYPT_ERROR_COMPLETE As Long = -24 ' Operation complete/can't continue \n  Public Const CRYPT_ERROR_TIMEOUT As Long = -25 ' Operation timed out before completion \n  Public Const CRYPT_ERROR_INVALID As Long = -26 ' Invalid/inconsistent information \n  Public Const CRYPT_ERROR_SIGNALLED As Long = -27 ' Resource destroyed by extnl.event \n\n' High-level function errors \n\n  Public Const CRYPT_ERROR_OVERFLOW As Long = -30 ' Resources/space exhausted \n  Public Const CRYPT_ERROR_UNDERFLOW As Long = -31 ' Not enough data available \n  Public Const CRYPT_ERROR_BADDATA As Long = -32 ' Bad/unrecognised data format \n  Public Const CRYPT_ERROR_SIGNATURE As Long = -33 ' Signature/integrity check failed \n\n' Data access function errors \n\n  Public Const CRYPT_ERROR_OPEN As Long = -40 ' Cannot open object \n  Public Const CRYPT_ERROR_READ As Long = -41 ' Cannot read item from object \n  Public Const CRYPT_ERROR_WRITE As Long = -42 ' Cannot write item to object \n  Public Const CRYPT_ERROR_NOTFOUND As Long = -43 ' Requested item not found in object \n  Public Const CRYPT_ERROR_DUPLICATE As Long = -44 ' Item already present in object \n\n' Data enveloping errors \n\n  Public Const CRYPT_ENVELOPE_RESOURCE As Long = -50 ' Need resource to proceed \n\n' Macros to examine return values \n\n' C-macro not translated to Visual Basic code: \n'   #define cryptStatusError( status )  ( ( status ) < CRYPT_OK )\n'\n' C-macro not translated to Visual Basic code: \n'   #define cryptStatusOK( status )     ( ( status ) == CRYPT_OK )\n'\n\n'****************************************************************************\n'*                                                                           *\n'*                                   General Functions                       *\n'*                                                                           *\n'****************************************************************************\n\n' The following is necessary to stop C++ name mangling \n\n\n' Initialise and shut down cryptlib \n\n \nPublic Declare Function cryptInit Lib \"CL32.DLL\" () As Long\n\n\nPublic Declare Function cryptEnd Lib \"CL32.DLL\" () As Long\n\n\n\n' Query cryptlibs capabilities \n\nPublic Declare Function cryptQueryCapability Lib \"CL32.DLL\" ( ByVal cryptAlgo As CRYPT_ALGO_TYPE, _\n ByRef cryptQueryInfo As CRYPT_QUERY_INFO) As Long\n\n\n' Create and destroy an encryption context \n\nPublic Declare Function cryptCreateContext Lib \"CL32.DLL\" ( ByRef cryptContext As Long, _\n ByVal cryptUser As Long, _\n ByVal cryptAlgo As CRYPT_ALGO_TYPE) As Long\n\nPublic Declare Function cryptDestroyContext Lib \"CL32.DLL\" ( ByVal cryptContext As Long) As Long\n\n\n' Generic \"destroy an object\" function \n\nPublic Declare Function cryptDestroyObject Lib \"CL32.DLL\" ( ByVal cryptObject As Long) As Long\n\n\n' Generate a key into a context \n\nPublic Declare Function cryptGenerateKey Lib \"CL32.DLL\" ( ByVal cryptContext As Long) As Long\n\n\n' Encrypt/decrypt/hash a block of memory \n\n' ***Warning: function 'cryptEncrypt' will replace the String 'buffer'\nPublic Declare Function cryptEncrypt Lib \"CL32.DLL\" ( ByVal cryptContext As Long, _\n ByVal buffer As String, _\n ByVal length As Long) As Long\n\n' ***Warning: function 'cryptDecrypt' will replace the String 'buffer'\nPublic Declare Function cryptDecrypt Lib \"CL32.DLL\" ( ByVal cryptContext As Long, _\n ByVal buffer As String, _\n ByVal length As Long) As Long\n\n\n' Get/set/delete attribute functions \n\nPublic Declare Function cryptSetAttribute Lib \"CL32.DLL\" ( ByVal cryptHandle As Long, _\n ByVal attributeType As CRYPT_ATTRIBUTE_TYPE, _\n ByVal value As Long) As Long\n\nPublic Declare Function cryptSetAttributeString Lib \"CL32.DLL\" ( ByVal cryptHandle As Long, _\n ByVal attributeType As CRYPT_ATTRIBUTE_TYPE, _\n ByVal value As String, _\n ByVal valueLength As Long) As Long\n\nPublic Declare Function cryptGetAttribute Lib \"CL32.DLL\" ( ByVal cryptHandle As Long, _\n ByVal attributeType As CRYPT_ATTRIBUTE_TYPE, _\n ByRef value As Long) As Long\n\n' ***Warning: function 'cryptGetAttributeString' will modify the String 'value'\nPublic Declare Function cryptGetAttributeString Lib \"CL32.DLL\" ( ByVal cryptHandle As Long, _\n ByVal attributeType As CRYPT_ATTRIBUTE_TYPE, _\n ByVal value As String, _\n ByRef valueLength As Long) As Long\n\nPublic Declare Function cryptDeleteAttribute Lib \"CL32.DLL\" ( ByVal cryptHandle As Long, _\n ByVal attributeType As CRYPT_ATTRIBUTE_TYPE) As Long\n\n\n'  Oddball functions: Add random data to the pool, query an encoded signature\n'  or key data.  These are due to be replaced once a suitable alternative can\n'  be found \n\nPublic Declare Function cryptAddRandom Lib \"CL32.DLL\" ( ByVal randomData As String, _\n ByVal randomDataLength As Long) As Long\n\nPublic Declare Function cryptQueryObject Lib \"CL32.DLL\" ( ByVal objectData As String, _\n ByVal objectDataLength As Long, _\n ByRef cryptObjectInfo As CRYPT_OBJECT_INFO) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                           Mid-level Encryption Functions                  *\n'*                                                                           *\n'****************************************************************************\n\n' Export and import an encrypted session key \n\n' ***Warning: function 'cryptExportKey' will modify the String 'encryptedKey'\nPublic Declare Function cryptExportKey Lib \"CL32.DLL\" ( ByVal encryptedKey As String, _\n ByVal encryptedKeyMaxLength As Long, _\n ByRef encryptedKeyLength As Long, _\n ByVal exportKey As Long, _\n ByVal sessionKeyContext As Long) As Long\n\n' ***Warning: function 'cryptExportKeyEx' will modify the String 'encryptedKey'\nPublic Declare Function cryptExportKeyEx Lib \"CL32.DLL\" ( ByVal encryptedKey As String, _\n ByVal encryptedKeyMaxLength As Long, _\n ByRef encryptedKeyLength As Long, _\n ByVal formatType As CRYPT_FORMAT_TYPE, _\n ByVal exportKey As Long, _\n ByVal sessionKeyContext As Long) As Long\n\nPublic Declare Function cryptImportKey Lib \"CL32.DLL\" ( ByVal encryptedKey As String, _\n ByVal encryptedKeyLength As Long, _\n ByVal importKey As Long, _\n ByVal sessionKeyContext As Long) As Long\n\nPublic Declare Function cryptImportKeyEx Lib \"CL32.DLL\" ( ByVal encryptedKey As String, _\n ByVal encryptedKeyLength As Long, _\n ByVal importKey As Long, _\n ByVal sessionKeyContext As Long, _\n ByRef returnedContext As Long) As Long\n\n\n' Create and check a digital signature \n\n' ***Warning: function 'cryptCreateSignature' will modify the String 'signature'\nPublic Declare Function cryptCreateSignature Lib \"CL32.DLL\" ( ByVal signature As String, _\n ByVal signatureMaxLength As Long, _\n ByRef signatureLength As Long, _\n ByVal signContext As Long, _\n ByVal hashContext As Long) As Long\n\n' ***Warning: function 'cryptCreateSignatureEx' will modify the String 'signature'\nPublic Declare Function cryptCreateSignatureEx Lib \"CL32.DLL\" ( ByVal signature As String, _\n ByVal signatureMaxLength As Long, _\n ByRef signatureLength As Long, _\n ByVal formatType As CRYPT_FORMAT_TYPE, _\n ByVal signContext As Long, _\n ByVal hashContext As Long, _\n ByVal extraData As Long) As Long\n\nPublic Declare Function cryptCheckSignature Lib \"CL32.DLL\" ( ByVal signature As String, _\n ByVal signatureLength As Long, _\n ByVal sigCheckKey As Long, _\n ByVal hashContext As Long) As Long\n\nPublic Declare Function cryptCheckSignatureEx Lib \"CL32.DLL\" ( ByVal signature As String, _\n ByVal signatureLength As Long, _\n ByVal sigCheckKey As Long, _\n ByVal hashContext As Long, _\n ByRef extraData As Long) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                                   Keyset Functions                        *\n'*                                                                           *\n'****************************************************************************\n\n' Open and close a keyset \n\nPublic Declare Function cryptKeysetOpen Lib \"CL32.DLL\" ( ByRef keyset As Long, _\n ByVal cryptUser As Long, _\n ByVal keysetType As CRYPT_KEYSET_TYPE, _\n ByVal name As String, _\n ByVal options As CRYPT_KEYOPT_TYPE) As Long\n\nPublic Declare Function cryptKeysetClose Lib \"CL32.DLL\" ( ByVal keyset As Long) As Long\n\n\n' Get a key from a keyset or device \n\nPublic Declare Function cryptGetPublicKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByRef cryptContext As Long, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String) As Long\n\nPublic Declare Function cryptGetPrivateKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByRef cryptContext As Long, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String, _\n ByVal password As String) As Long\n\nPublic Declare Function cryptGetKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByRef cryptContext As Long, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String, _\n ByVal password As String) As Long\n\n\n' Add/delete a key to/from a keyset or device \n\nPublic Declare Function cryptAddPublicKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByVal certificate As Long) As Long\n\nPublic Declare Function cryptAddPrivateKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByVal cryptKey As Long, _\n ByVal password As String) As Long\n\nPublic Declare Function cryptDeleteKey Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                               Certificate Functions                       *\n'*                                                                           *\n'****************************************************************************\n\n' Create/destroy a certificate \n\nPublic Declare Function cryptCreateCert Lib \"CL32.DLL\" ( ByRef certificate As Long, _\n ByVal cryptUser As Long, _\n ByVal certType As CRYPT_CERTTYPE_TYPE) As Long\n\nPublic Declare Function cryptDestroyCert Lib \"CL32.DLL\" ( ByVal certificate As Long) As Long\n\n\n'  Get/add/delete certificate extensions.  These are direct data insertion\n'  functions whose use is discouraged, so they fix the string at char *\n'  rather than C_STR \n\n' ***Warning: function 'cryptGetCertExtension' will modify the String 'extension'\nPublic Declare Function cryptGetCertExtension Lib \"CL32.DLL\" ( ByVal certificate As Long, _\n ByVal oid As String, _\n ByRef criticalFlag As Long, _\n ByVal extension As String, _\n ByVal extensionMaxLength As Long, _\n ByRef extensionLength As Long) As Long\n\nPublic Declare Function cryptAddCertExtension Lib \"CL32.DLL\" ( ByVal certificate As Long, _\n ByVal oid As String, _\n ByVal criticalFlag As Long, _\n ByVal extension As String, _\n ByVal extensionLength As Long) As Long\n\nPublic Declare Function cryptDeleteCertExtension Lib \"CL32.DLL\" ( ByVal certificate As Long, _\n ByVal oid As String) As Long\n\n\n' Sign/sig.check a certificate/certification request \n\nPublic Declare Function cryptSignCert Lib \"CL32.DLL\" ( ByVal certificate As Long, _\n ByVal signContext As Long) As Long\n\nPublic Declare Function cryptCheckCert Lib \"CL32.DLL\" ( ByVal certificate As Long, _\n ByVal sigCheckKey As Long) As Long\n\n\n' Import/export a certificate/certification request \n\nPublic Declare Function cryptImportCert Lib \"CL32.DLL\" ( ByVal certObject As String, _\n ByVal certObjectLength As Long, _\n ByVal cryptUser As Long, _\n ByRef certificate As Long) As Long\n\n' ***Warning: function 'cryptExportCert' will modify the String 'certObject'\nPublic Declare Function cryptExportCert Lib \"CL32.DLL\" ( ByVal certObject As String, _\n ByVal certObjectMaxLength As Long, _\n ByRef certObjectLength As Long, _\n ByVal certFormatType As CRYPT_CERTFORMAT_TYPE, _\n ByVal certificate As Long) As Long\n\n\n' CA management functions \n\nPublic Declare Function cryptCAAddItem Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByVal certificate As Long) As Long\n\nPublic Declare Function cryptCAGetItem Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByRef certificate As Long, _\n ByVal certType As CRYPT_CERTTYPE_TYPE, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String) As Long\n\nPublic Declare Function cryptCADeleteItem Lib \"CL32.DLL\" ( ByVal keyset As Long, _\n ByVal certType As CRYPT_CERTTYPE_TYPE, _\n ByVal keyIDtype As CRYPT_KEYID_TYPE, _\n ByVal keyID As String) As Long\n\nPublic Declare Function cryptCACertManagement Lib \"CL32.DLL\" ( ByRef certificate As Long, _\n ByVal action As CRYPT_CERTACTION_TYPE, _\n ByVal keyset As Long, _\n ByVal caKey As Long, _\n ByVal certRequest As Long) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                           Envelope and Session Functions                  *\n'*                                                                           *\n'****************************************************************************\n\n' Create/destroy an envelope \n\nPublic Declare Function cryptCreateEnvelope Lib \"CL32.DLL\" ( ByRef envelope As Long, _\n ByVal cryptUser As Long, _\n ByVal formatType As CRYPT_FORMAT_TYPE) As Long\n\nPublic Declare Function cryptDestroyEnvelope Lib \"CL32.DLL\" ( ByVal envelope As Long) As Long\n\n\n' Create/destroy a session \n\nPublic Declare Function cryptCreateSession Lib \"CL32.DLL\" ( ByRef session As Long, _\n ByVal cryptUser As Long, _\n ByVal formatType As CRYPT_SESSION_TYPE) As Long\n\nPublic Declare Function cryptDestroySession Lib \"CL32.DLL\" ( ByVal session As Long) As Long\n\n\n' Add/remove data to/from and envelope or session \n\nPublic Declare Function cryptPushData Lib \"CL32.DLL\" ( ByVal envelope As Long, _\n ByVal buffer As String, _\n ByVal length As Long, _\n ByRef bytesCopied As Long) As Long\n\nPublic Declare Function cryptFlushData Lib \"CL32.DLL\" ( ByVal envelope As Long) As Long\n\n' ***Warning: function 'cryptPopData' will modify the String 'buffer'\nPublic Declare Function cryptPopData Lib \"CL32.DLL\" ( ByVal envelope As Long, _\n ByVal buffer As String, _\n ByVal length As Long, _\n ByRef bytesCopied As Long) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                               Device Functions                            *\n'*                                                                           *\n'****************************************************************************\n\n' Open and close a device \n\nPublic Declare Function cryptDeviceOpen Lib \"CL32.DLL\" ( ByRef device As Long, _\n ByVal cryptUser As Long, _\n ByVal deviceType As CRYPT_DEVICE_TYPE, _\n ByVal name As String) As Long\n\nPublic Declare Function cryptDeviceClose Lib \"CL32.DLL\" ( ByVal device As Long) As Long\n\n\n' Query a devices capabilities \n\nPublic Declare Function cryptDeviceQueryCapability Lib \"CL32.DLL\" ( ByVal device As Long, _\n ByVal cryptAlgo As CRYPT_ALGO_TYPE, _\n ByRef cryptQueryInfo As CRYPT_QUERY_INFO) As Long\n\n\n' Create an encryption context via the device \n\nPublic Declare Function cryptDeviceCreateContext Lib \"CL32.DLL\" ( ByVal device As Long, _\n ByRef cryptContext As Long, _\n ByVal cryptAlgo As CRYPT_ALGO_TYPE) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                           User Management Functions                       *\n'*                                                                           *\n'****************************************************************************\n\n' Log on and off (create/destroy a user object) \n\nPublic Declare Function cryptLogin Lib \"CL32.DLL\" ( ByRef user As Long, _\n ByVal name As String, _\n ByVal password As String) As Long\n\nPublic Declare Function cryptLogout Lib \"CL32.DLL\" ( ByVal user As Long) As Long\n\n\n'****************************************************************************\n'*                                                                           *\n'*                               Direct API Functions                        *\n'*                                                                           *\n'****************************************************************************\n\n\n\n'*****************************************************************************\n'*                                                                           *\n'*                    End of Visual Basic Functions                          *\n'*                                                                           *\n'****************************************************************************}\n\n"
  },
  {
    "path": "deps/cl345/bindings/cryptlib.cs",
    "content": "using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace cryptlib\n{\n\npublic class crypt\n{\n    \n\t/* Additional defines for compilers that provide extended function and \n\t   function-parameter checking */\n\t\n\t\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\tAlgorithm and Object Types\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Algorithm and mode types */\n\t\n\t// CRYPT_ALGO_TYPE\n\tpublic const int ALGO_NONE               = 0  ; // No encryption\n\tpublic const int ALGO_DES                = 1  ; // DES\n\tpublic const int ALGO_3DES               = 2  ; // Triple DES\n\tpublic const int ALGO_IDEA               = 3  ; // IDEA (only used for PGP 2.x)\n\tpublic const int ALGO_CAST               = 4  ; // CAST-128 (only used for OpenPGP)\n\tpublic const int ALGO_RC2                = 5  ; // RC2 (disabled by default, used for PKCS #12)\n\tpublic const int ALGO_RC4                = 6  ; // RC4 (insecure, deprecated)\n\tpublic const int ALGO_RESERVED1          = 7  ; // Formerly RC5\n\tpublic const int ALGO_AES                = 8  ; // AES\n\tpublic const int ALGO_RESERVED2          = 9  ; // Formerly Blowfish\n\tpublic const int ALGO_DH                 = 100; // Diffie-Hellman\n\tpublic const int ALGO_RSA                = 101; // RSA\n\tpublic const int ALGO_DSA                = 102; // DSA\n\tpublic const int ALGO_ELGAMAL            = 103; // ElGamal\n\tpublic const int ALGO_RESERVED3          = 104; // Formerly KEA\n\tpublic const int ALGO_ECDSA              = 105; // ECDSA\n\tpublic const int ALGO_ECDH               = 106; // ECDH\n\tpublic const int ALGO_RESERVED4          = 200; // Formerly MD2\n\tpublic const int ALGO_RESERVED5          = 201; // Formerly MD4\n\tpublic const int ALGO_MD5                = 202; // MD5 (only used for TLS 1.0/1.1)\n\tpublic const int ALGO_SHA1               = 203; // SHA/SHA1\n\tpublic const int ALGO_RESERVED6          = 204; // Formerly RIPE-MD 160\n\tpublic const int ALGO_SHA2               = 205; // SHA-256\n\tpublic const int ALGO_SHA256             = 205; // Alternate name\n\tpublic const int ALGO_SHAng              = 206; // Future SHA-nextgen standard\n\tpublic const int ALGO_RESREVED_7         = 300; // Formerly HMAC-MD5\n\tpublic const int ALGO_HMAC_SHA1          = 301; // HMAC-SHA\n\tpublic const int ALGO_RESERVED8          = 302; // Formerly HMAC-RIPEMD-160\n\tpublic const int ALGO_HMAC_SHA2          = 303; // HMAC-SHA2\n\tpublic const int ALGO_HMAC_SHAng         = 304; // HMAC-future-SHA-nextgen\n\tpublic const int ALGO_LAST               = 305; // Last possible crypt algo value\n\tpublic const int ALGO_FIRST_CONVENTIONAL = 1  ;\n\tpublic const int ALGO_LAST_CONVENTIONAL  = 99 ;\n\tpublic const int ALGO_FIRST_PKC          = 100;\n\tpublic const int ALGO_LAST_PKC           = 199;\n\tpublic const int ALGO_FIRST_HASH         = 200;\n\tpublic const int ALGO_LAST_HASH          = 299;\n\tpublic const int ALGO_FIRST_MAC          = 300;\n\tpublic const int ALGO_LAST_MAC           = 399;\n\t\n\t// CRYPT_MODE_TYPE\n\tpublic const int MODE_NONE = 0; // No encryption mode\n\tpublic const int MODE_ECB  = 1; // ECB\n\tpublic const int MODE_CBC  = 2; // CBC\n\tpublic const int MODE_CFB  = 3; // CFB\n\tpublic const int MODE_GCM  = 4; // GCM\n\tpublic const int MODE_LAST = 5; // Last possible crypt mode value\n\t\n\t\n\t/* Keyset subtypes */\n\t\n\t// CRYPT_KEYSET_TYPE\n\tpublic const int KEYSET_NONE           = 0; // No keyset type\n\tpublic const int KEYSET_FILE           = 1; // Generic flat file keyset\n\tpublic const int KEYSET_HTTP           = 2; // Web page containing cert/CRL\n\tpublic const int KEYSET_LDAP           = 3; // LDAP directory service\n\tpublic const int KEYSET_ODBC           = 4; // Generic ODBC interface\n\tpublic const int KEYSET_DATABASE       = 5; // Generic RDBMS interface\n\tpublic const int KEYSET_ODBC_STORE     = 6; // ODBC certificate store\n\tpublic const int KEYSET_DATABASE_STORE = 7; // Database certificate store\n\tpublic const int KEYSET_LAST           = 8; // Last possible keyset type\n\t\n\t/* Device subtypes */\n\t\n\t// CRYPT_DEVICE_TYPE\n\tpublic const int DEVICE_NONE      = 0; // No crypto device\n\tpublic const int DEVICE_FORTEZZA  = 1; // Fortezza card - Placeholder only\n\tpublic const int DEVICE_PKCS11    = 2; // PKCS #11 crypto token\n\tpublic const int DEVICE_CRYPTOAPI = 3; // Microsoft CryptoAPI\n\tpublic const int DEVICE_HARDWARE  = 4; // Generic crypo HW plugin\n\tpublic const int DEVICE_LAST      = 5; // Last possible crypto device type\n\t\n\t/* Certificate subtypes */\n\t\n\t// CRYPT_CERTTYPE_TYPE\n\tpublic const int CERTTYPE_NONE               = 0 ; // No certificate type\n\tpublic const int CERTTYPE_CERTIFICATE        = 1 ; // Certificate\n\tpublic const int CERTTYPE_ATTRIBUTE_CERT     = 2 ; // Attribute certificate\n\tpublic const int CERTTYPE_CERTCHAIN          = 3 ; // PKCS #7 certificate chain\n\tpublic const int CERTTYPE_CERTREQUEST        = 4 ; // PKCS #10 certification request\n\tpublic const int CERTTYPE_REQUEST_CERT       = 5 ; // CRMF certification request\n\tpublic const int CERTTYPE_REQUEST_REVOCATION = 6 ; // CRMF revocation request\n\tpublic const int CERTTYPE_CRL                = 7 ; // CRL\n\tpublic const int CERTTYPE_CMS_ATTRIBUTES     = 8 ; // CMS attributes\n\tpublic const int CERTTYPE_RTCS_REQUEST       = 9 ; // RTCS request\n\tpublic const int CERTTYPE_RTCS_RESPONSE      = 10; // RTCS response\n\tpublic const int CERTTYPE_OCSP_REQUEST       = 11; // OCSP request\n\tpublic const int CERTTYPE_OCSP_RESPONSE      = 12; // OCSP response\n\tpublic const int CERTTYPE_PKIUSER            = 13; // PKI user information\n\tpublic const int CERTTYPE_LAST               = 14; // Last possible cert.type\n\t\n\t/* Envelope/data format subtypes */\n\t\n\t// CRYPT_FORMAT_TYPE\n\tpublic const int FORMAT_NONE     = 0; // No format type\n\tpublic const int FORMAT_AUTO     = 1; // Deenv, auto-determine type\n\tpublic const int FORMAT_CRYPTLIB = 2; // cryptlib native format\n\tpublic const int FORMAT_CMS      = 3; // PKCS #7 / CMS / S/MIME fmt.\n\tpublic const int FORMAT_PKCS7    = 3;\n\tpublic const int FORMAT_SMIME    = 4; // As CMS with MSG-style behaviour\n\tpublic const int FORMAT_PGP      = 5; // PGP format\n\tpublic const int FORMAT_LAST     = 6; // Last possible format type\n\t\n\t/* Session subtypes */\n\t\n\t// CRYPT_SESSION_TYPE\n\tpublic const int SESSION_NONE             = 0 ; // No session type\n\tpublic const int SESSION_SSH              = 1 ; // SSH\n\tpublic const int SESSION_SSH_SERVER       = 2 ; // SSH server\n\tpublic const int SESSION_SSL              = 3 ; // SSL/TLS\n\tpublic const int SESSION_TLS              = 3 ;\n\tpublic const int SESSION_SSL_SERVER       = 4 ; // SSL/TLS server\n\tpublic const int SESSION_TLS_SERVER       = 4 ;\n\tpublic const int SESSION_RTCS             = 5 ; // RTCS\n\tpublic const int SESSION_RTCS_SERVER      = 6 ; // RTCS server\n\tpublic const int SESSION_OCSP             = 7 ; // OCSP\n\tpublic const int SESSION_OCSP_SERVER      = 8 ; // OCSP server\n\tpublic const int SESSION_TSP              = 9 ; // TSP\n\tpublic const int SESSION_TSP_SERVER       = 10; // TSP server\n\tpublic const int SESSION_CMP              = 11; // CMP\n\tpublic const int SESSION_CMP_SERVER       = 12; // CMP server\n\tpublic const int SESSION_SCEP             = 13; // SCEP\n\tpublic const int SESSION_SCEP_SERVER      = 14; // SCEP server\n\tpublic const int SESSION_CERTSTORE_SERVER = 15; // HTTP cert store interface\n\tpublic const int SESSION_LAST             = 16; // Last possible session type\n\t\n\t/* User subtypes */\n\t\n\t// CRYPT_USER_TYPE\n\tpublic const int USER_NONE   = 0; // No user type\n\tpublic const int USER_NORMAL = 1; // Normal user\n\tpublic const int USER_SO     = 2; // Security officer\n\tpublic const int USER_CA     = 3; // CA user\n\tpublic const int USER_LAST   = 4; // Last possible user type\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tAttribute Types\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Attribute types.  These are arranged in the following order:\n\t\n\t\tPROPERTY\t- Object property\n\t\tATTRIBUTE\t- Generic attributes\n\t\tOPTION\t\t- Global or object-specific config.option\n\t\tCTXINFO\t\t- Context-specific attribute\n\t\tCERTINFO\t- Certificate-specific attribute\n\t\tKEYINFO\t\t- Keyset-specific attribute\n\t\tDEVINFO\t\t- Device-specific attribute\n\t\tENVINFO\t\t- Envelope-specific attribute\n\t\tSESSINFO\t- Session-specific attribute\n\t\tUSERINFO\t- User-specific attribute */\n\t\n\t// CRYPT_ATTRIBUTE_TYPE\n\tpublic const int ATTRIBUTE_NONE                              = 0   ; // Non-value\n\tpublic const int PROPERTY_FIRST                              = 1   ; // *******************\n\tpublic const int PROPERTY_HIGHSECURITY                       = 2   ; // Owned+non-forwardcount+locked\n\tpublic const int PROPERTY_OWNER                              = 3   ; // Object owner\n\tpublic const int PROPERTY_FORWARDCOUNT                       = 4   ; // No.of times object can be forwarded\n\tpublic const int PROPERTY_LOCKED                             = 5   ; // Whether properties can be chged/read\n\tpublic const int PROPERTY_USAGECOUNT                         = 6   ; // Usage count before object expires\n\tpublic const int PROPERTY_NONEXPORTABLE                      = 7   ; // Whether key is nonexp.from context\n\tpublic const int PROPERTY_LAST                               = 8   ;\n\tpublic const int GENERIC_FIRST                               = 9   ; // Extended error information\n\tpublic const int ATTRIBUTE_ERRORTYPE                         = 10  ; // Type of last error\n\tpublic const int ATTRIBUTE_ERRORLOCUS                        = 11  ; // Locus of last error\n\tpublic const int ATTRIBUTE_ERRORMESSAGE                      = 12  ; // Detailed error description\n\tpublic const int ATTRIBUTE_CURRENT_GROUP                     = 13  ; // Cursor mgt: Group in attribute list\n\tpublic const int ATTRIBUTE_CURRENT                           = 14  ; // Cursor mgt: Entry in attribute list\n\tpublic const int ATTRIBUTE_CURRENT_INSTANCE                  = 15  ; // Cursor mgt: Instance in attribute list\n\tpublic const int ATTRIBUTE_BUFFERSIZE                        = 16  ; // Internal data buffer size\n\tpublic const int GENERIC_LAST                                = 17  ;\n\tpublic const int OPTION_FIRST                                = 100 ; // **************************\n\tpublic const int OPTION_INFO_DESCRIPTION                     = 101 ; // Text description\n\tpublic const int OPTION_INFO_COPYRIGHT                       = 102 ; // Copyright notice\n\tpublic const int OPTION_INFO_MAJORVERSION                    = 103 ; // Major release version\n\tpublic const int OPTION_INFO_MINORVERSION                    = 104 ; // Minor release version\n\tpublic const int OPTION_INFO_STEPPING                        = 105 ; // Release stepping\n\tpublic const int OPTION_ENCR_ALGO                            = 106 ; // Conventional ncryption algorithm\n\tpublic const int OPTION_ENCR_HASH                            = 107 ; // Hash algorithm\n\tpublic const int OPTION_ENCR_MAC                             = 108 ; // MAC algorithm\n\tpublic const int OPTION_PKC_ALGO                             = 109 ; // PKC algorithm\n\tpublic const int OPTION_PKC_KEYSIZE                          = 110 ; // PKC key size\n\tpublic const int OPTION_DUMMY1                               = 111 ;\n\tpublic const int OPTION_DUMMY2                               = 112 ; // Keying options\n\tpublic const int OPTION_KEYING_ALGO                          = 113 ; // Key processing algorithm\n\tpublic const int OPTION_KEYING_ITERATIONS                    = 114 ; // Key processing iterations\n\tpublic const int OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES      = 115 ; // Whether to sign unrecog.attrs\n\tpublic const int OPTION_CERT_VALIDITY                        = 116 ; // Certificate validity period\n\tpublic const int OPTION_CERT_UPDATEINTERVAL                  = 117 ; // CRL update interval\n\tpublic const int OPTION_CERT_COMPLIANCELEVEL                 = 118 ; // PKIX compliance level for cert chks.\n\tpublic const int OPTION_CERT_REQUIREPOLICY                   = 119 ; // Whether explicit policy req'd for certs\n\tpublic const int OPTION_CMS_DEFAULTATTRIBUTES                = 120 ; // Add default CMS attributes\n\tpublic const int OPTION_SMIME_DEFAULTATTRIBUTES              = 120 ; // LDAP keyset options\n\tpublic const int OPTION_KEYS_LDAP_OBJECTCLASS                = 121 ; // Object class\n\tpublic const int OPTION_KEYS_LDAP_OBJECTTYPE                 = 122 ; // Object type to fetch\n\tpublic const int OPTION_KEYS_LDAP_FILTER                     = 123 ; // Query filter\n\tpublic const int OPTION_KEYS_LDAP_CACERTNAME                 = 124 ; // CA certificate attribute name\n\tpublic const int OPTION_KEYS_LDAP_CERTNAME                   = 125 ; // Certificate attribute name\n\tpublic const int OPTION_KEYS_LDAP_CRLNAME                    = 126 ; // CRL attribute name\n\tpublic const int OPTION_KEYS_LDAP_EMAILNAME                  = 127 ; // Email attribute name\n\tpublic const int OPTION_DEVICE_PKCS11_DVR01                  = 128 ; // Name of first PKCS #11 driver\n\tpublic const int OPTION_DEVICE_PKCS11_DVR02                  = 129 ; // Name of second PKCS #11 driver\n\tpublic const int OPTION_DEVICE_PKCS11_DVR03                  = 130 ; // Name of third PKCS #11 driver\n\tpublic const int OPTION_DEVICE_PKCS11_DVR04                  = 131 ; // Name of fourth PKCS #11 driver\n\tpublic const int OPTION_DEVICE_PKCS11_DVR05                  = 132 ; // Name of fifth PKCS #11 driver\n\tpublic const int OPTION_DEVICE_PKCS11_HARDWAREONLY           = 133 ; // Use only hardware mechanisms\n\tpublic const int OPTION_NET_SOCKS_SERVER                     = 134 ; // Socks server name\n\tpublic const int OPTION_NET_SOCKS_USERNAME                   = 135 ; // Socks user name\n\tpublic const int OPTION_NET_HTTP_PROXY                       = 136 ; // Web proxy server\n\tpublic const int OPTION_NET_CONNECTTIMEOUT                   = 137 ; // Timeout for network connection setup\n\tpublic const int OPTION_NET_READTIMEOUT                      = 138 ; // Timeout for network reads\n\tpublic const int OPTION_NET_WRITETIMEOUT                     = 139 ; // Timeout for network writes\n\tpublic const int OPTION_MISC_ASYNCINIT                       = 140 ; // Whether to init cryptlib async'ly\n\tpublic const int OPTION_MISC_SIDECHANNELPROTECTION           = 141 ; // Protect against side-channel attacks\n\tpublic const int OPTION_CONFIGCHANGED                        = 142 ; // Whether in-mem.opts match on-disk ones\n\tpublic const int OPTION_SELFTESTOK                           = 143 ; // Whether self-test was completed and OK\n\tpublic const int OPTION_LAST                                 = 144 ;\n\tpublic const int CTXINFO_FIRST                               = 1000; // ********************\n\tpublic const int CTXINFO_ALGO                                = 1001; // Algorithm\n\tpublic const int CTXINFO_MODE                                = 1002; // Mode\n\tpublic const int CTXINFO_NAME_ALGO                           = 1003; // Algorithm name\n\tpublic const int CTXINFO_NAME_MODE                           = 1004; // Mode name\n\tpublic const int CTXINFO_KEYSIZE                             = 1005; // Key size in bytes\n\tpublic const int CTXINFO_BLOCKSIZE                           = 1006; // Block size\n\tpublic const int CTXINFO_IVSIZE                              = 1007; // IV size\n\tpublic const int CTXINFO_KEYING_ALGO                         = 1008; // Key processing algorithm\n\tpublic const int CTXINFO_KEYING_ITERATIONS                   = 1009; // Key processing iterations\n\tpublic const int CTXINFO_KEYING_SALT                         = 1010; // Key processing salt\n\tpublic const int CTXINFO_KEYING_VALUE                        = 1011; // Value used to derive key\n\tpublic const int CTXINFO_KEY                                 = 1012; // Key\n\tpublic const int CTXINFO_KEY_COMPONENTS                      = 1013; // Public-key components\n\tpublic const int CTXINFO_IV                                  = 1014; // IV\n\tpublic const int CTXINFO_HASHVALUE                           = 1015; // Hash value\n\tpublic const int CTXINFO_LABEL                               = 1016; // Label for private/secret key\n\tpublic const int CTXINFO_PERSISTENT                          = 1017; // Obj.is backed by device or keyset\n\tpublic const int CTXINFO_LAST                                = 1018;\n\tpublic const int CERTINFO_FIRST                              = 2000; // ************************\n\tpublic const int CERTINFO_SELFSIGNED                         = 2001; // Cert is self-signed\n\tpublic const int CERTINFO_IMMUTABLE                          = 2002; // Cert is signed and immutable\n\tpublic const int CERTINFO_XYZZY                              = 2003; // Cert is a magic just-works cert\n\tpublic const int CERTINFO_CERTTYPE                           = 2004; // Certificate object type\n\tpublic const int CERTINFO_FINGERPRINT_SHA1                   = 2005; // Certificate fingerprints\n\tpublic const int CERTINFO_FINGERPRINT_SHA2                   = 2006;\n\tpublic const int CERTINFO_FINGERPRINT_SHAng                  = 2007;\n\tpublic const int CERTINFO_CURRENT_CERTIFICATE                = 2008; // Cursor mgt: Rel.pos in chain/CRL/OCSP\n\tpublic const int CERTINFO_TRUSTED_USAGE                      = 2009; // Usage that cert is trusted for\n\tpublic const int CERTINFO_TRUSTED_IMPLICIT                   = 2010; // Whether cert is implicitly trusted\n\tpublic const int CERTINFO_SIGNATURELEVEL                     = 2011; // Amount of detail to include in sigs.\n\tpublic const int CERTINFO_VERSION                            = 2012; // Cert.format version\n\tpublic const int CERTINFO_SERIALNUMBER                       = 2013; // Serial number\n\tpublic const int CERTINFO_SUBJECTPUBLICKEYINFO               = 2014; // Public key\n\tpublic const int CERTINFO_CERTIFICATE                        = 2015; // User certificate\n\tpublic const int CERTINFO_USERCERTIFICATE                    = 2015;\n\tpublic const int CERTINFO_CACERTIFICATE                      = 2016; // CA certificate\n\tpublic const int CERTINFO_ISSUERNAME                         = 2017; // Issuer DN\n\tpublic const int CERTINFO_VALIDFROM                          = 2018; // Cert valid-from time\n\tpublic const int CERTINFO_VALIDTO                            = 2019; // Cert valid-to time\n\tpublic const int CERTINFO_SUBJECTNAME                        = 2020; // Subject DN\n\tpublic const int CERTINFO_ISSUERUNIQUEID                     = 2021; // Issuer unique ID\n\tpublic const int CERTINFO_SUBJECTUNIQUEID                    = 2022; // Subject unique ID\n\tpublic const int CERTINFO_CERTREQUEST                        = 2023; // Cert.request (DN + public key)\n\tpublic const int CERTINFO_THISUPDATE                         = 2024; // CRL/OCSP current-update time\n\tpublic const int CERTINFO_NEXTUPDATE                         = 2025; // CRL/OCSP next-update time\n\tpublic const int CERTINFO_REVOCATIONDATE                     = 2026; // CRL/OCSP cert-revocation time\n\tpublic const int CERTINFO_REVOCATIONSTATUS                   = 2027; // OCSP revocation status\n\tpublic const int CERTINFO_CERTSTATUS                         = 2028; // RTCS certificate status\n\tpublic const int CERTINFO_DN                                 = 2029; // Currently selected DN in string form\n\tpublic const int CERTINFO_PKIUSER_ID                         = 2030; // PKI user ID\n\tpublic const int CERTINFO_PKIUSER_ISSUEPASSWORD              = 2031; // PKI user issue password\n\tpublic const int CERTINFO_PKIUSER_REVPASSWORD                = 2032; // PKI user revocation password\n\tpublic const int CERTINFO_PKIUSER_RA                         = 2033; // PKI user is an RA\n\tpublic const int CERTINFO_COUNTRYNAME                        = 2100; // countryName\n\tpublic const int CERTINFO_STATEORPROVINCENAME                = 2101; // stateOrProvinceName\n\tpublic const int CERTINFO_LOCALITYNAME                       = 2102; // localityName\n\tpublic const int CERTINFO_ORGANIZATIONNAME                   = 2103; // organizationName\n\tpublic const int CERTINFO_ORGANISATIONNAME                   = 2103;\n\tpublic const int CERTINFO_ORGANIZATIONALUNITNAME             = 2104; // organizationalUnitName\n\tpublic const int CERTINFO_ORGANISATIONALUNITNAME             = 2104;\n\tpublic const int CERTINFO_COMMONNAME                         = 2105; // commonName\n\tpublic const int CERTINFO_OTHERNAME_TYPEID                   = 2106; // otherName.typeID\n\tpublic const int CERTINFO_OTHERNAME_VALUE                    = 2107; // otherName.value\n\tpublic const int CERTINFO_RFC822NAME                         = 2108; // rfc822Name\n\tpublic const int CERTINFO_EMAIL                              = 2108;\n\tpublic const int CERTINFO_DNSNAME                            = 2109; // dNSName\n\tpublic const int CERTINFO_DIRECTORYNAME                      = 2110; // directoryName\n\tpublic const int CERTINFO_EDIPARTYNAME_NAMEASSIGNER          = 2111; // ediPartyName.nameAssigner\n\tpublic const int CERTINFO_EDIPARTYNAME_PARTYNAME             = 2112; // ediPartyName.partyName\n\tpublic const int CERTINFO_UNIFORMRESOURCEIDENTIFIER          = 2113; // uniformResourceIdentifier\n\tpublic const int CERTINFO_URL                                = 2113;\n\tpublic const int CERTINFO_IPADDRESS                          = 2114; // iPAddress\n\tpublic const int CERTINFO_REGISTEREDID                       = 2115; // registeredID\n\tpublic const int CERTINFO_CHALLENGEPASSWORD                  = 2200; // 1 3 6 1 4 1 3029 3 1 4 cRLExtReason\n\tpublic const int CERTINFO_CRLEXTREASON                       = 2201; // 1 3 6 1 4 1 3029 3 1 5 keyFeatures\n\tpublic const int CERTINFO_KEYFEATURES                        = 2202; // 1 3 6 1 5 5 7 1 1 authorityInfoAccess\n\tpublic const int CERTINFO_AUTHORITYINFOACCESS                = 2203;\n\tpublic const int CERTINFO_AUTHORITYINFO_RTCS                 = 2204; // accessDescription.accessLocation\n\tpublic const int CERTINFO_AUTHORITYINFO_OCSP                 = 2205; // accessDescription.accessLocation\n\tpublic const int CERTINFO_AUTHORITYINFO_CAISSUERS            = 2206; // accessDescription.accessLocation\n\tpublic const int CERTINFO_AUTHORITYINFO_CERTSTORE            = 2207; // accessDescription.accessLocation\n\tpublic const int CERTINFO_AUTHORITYINFO_CRLS                 = 2208; // accessDescription.accessLocation\n\tpublic const int CERTINFO_BIOMETRICINFO                      = 2209;\n\tpublic const int CERTINFO_BIOMETRICINFO_TYPE                 = 2210; // biometricData.typeOfData\n\tpublic const int CERTINFO_BIOMETRICINFO_HASHALGO             = 2211; // biometricData.hashAlgorithm\n\tpublic const int CERTINFO_BIOMETRICINFO_HASH                 = 2212; // biometricData.dataHash\n\tpublic const int CERTINFO_BIOMETRICINFO_URL                  = 2213; // biometricData.sourceDataUri\n\tpublic const int CERTINFO_QCSTATEMENT                        = 2214;\n\tpublic const int CERTINFO_QCSTATEMENT_SEMANTICS              = 2215; // qcStatement.statementInfo.semanticsIdentifier\n\tpublic const int CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY  = 2216; // qcStatement.statementInfo.nameRegistrationAuthorities\n\tpublic const int CERTINFO_IPADDRESSBLOCKS                    = 2217;\n\tpublic const int CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY      = 2218; // addressFamily */\tCRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX,\t/* ipAddress.addressPrefix\n\tpublic const int CERTINFO_IPADDRESSBLOCKS_PREFIX             = 2219; // ipAddress.addressPrefix\n\tpublic const int CERTINFO_IPADDRESSBLOCKS_MIN                = 2220; // ipAddress.addressRangeMin\n\tpublic const int CERTINFO_IPADDRESSBLOCKS_MAX                = 2221; // ipAddress.addressRangeMax\n\tpublic const int CERTINFO_AUTONOMOUSSYSIDS                   = 2222;\n\tpublic const int CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID          = 2223; // asNum.id\n\tpublic const int CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN         = 2224; // asNum.min\n\tpublic const int CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX         = 2225; // asNum.max\n\tpublic const int CERTINFO_OCSP_NONCE                         = 2226; // nonce\n\tpublic const int CERTINFO_OCSP_RESPONSE                      = 2227;\n\tpublic const int CERTINFO_OCSP_RESPONSE_OCSP                 = 2228; // OCSP standard response\n\tpublic const int CERTINFO_OCSP_NOCHECK                       = 2229; // 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff\n\tpublic const int CERTINFO_OCSP_ARCHIVECUTOFF                 = 2230; // 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess\n\tpublic const int CERTINFO_SUBJECTINFOACCESS                  = 2231;\n\tpublic const int CERTINFO_SUBJECTINFO_TIMESTAMPING           = 2232; // accessDescription.accessLocation\n\tpublic const int CERTINFO_SUBJECTINFO_CAREPOSITORY           = 2233; // accessDescription.accessLocation\n\tpublic const int CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY = 2234; // accessDescription.accessLocation\n\tpublic const int CERTINFO_SUBJECTINFO_RPKIMANIFEST           = 2235; // accessDescription.accessLocation\n\tpublic const int CERTINFO_SUBJECTINFO_SIGNEDOBJECT           = 2236; // accessDescription.accessLocation\n\tpublic const int CERTINFO_SIGG_DATEOFCERTGEN                 = 2237; // 1 3 36 8 3 2 siggProcuration\n\tpublic const int CERTINFO_SIGG_PROCURATION                   = 2238;\n\tpublic const int CERTINFO_SIGG_PROCURE_COUNTRY               = 2239; // country\n\tpublic const int CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION    = 2240; // typeOfSubstitution\n\tpublic const int CERTINFO_SIGG_PROCURE_SIGNINGFOR            = 2241; // signingFor.thirdPerson\n\tpublic const int CERTINFO_SIGG_ADMISSIONS                    = 2242;\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_AUTHORITY          = 2243; // authority\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID       = 2244; // namingAuth.iD\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL      = 2245; // namingAuth.uRL\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT     = 2246; // namingAuth.text\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM     = 2247; // professionItem\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID      = 2248; // professionOID\n\tpublic const int CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER = 2249; // registrationNumber\n\tpublic const int CERTINFO_SIGG_MONETARYLIMIT                 = 2250;\n\tpublic const int CERTINFO_SIGG_MONETARY_CURRENCY             = 2251; // currency\n\tpublic const int CERTINFO_SIGG_MONETARY_AMOUNT               = 2252; // amount\n\tpublic const int CERTINFO_SIGG_MONETARY_EXPONENT             = 2253; // exponent\n\tpublic const int CERTINFO_SIGG_DECLARATIONOFMAJORITY         = 2254;\n\tpublic const int CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY = 2255; // fullAgeAtCountry\n\tpublic const int CERTINFO_SIGG_RESTRICTION                   = 2256; // 1 3 36 8 3 13 siggCertHash\n\tpublic const int CERTINFO_SIGG_CERTHASH                      = 2257; // 1 3 36 8 3 15 siggAdditionalInformation\n\tpublic const int CERTINFO_SIGG_ADDITIONALINFORMATION         = 2258; // 1 3 101 1 4 1 strongExtranet\n\tpublic const int CERTINFO_STRONGEXTRANET                     = 2259;\n\tpublic const int CERTINFO_STRONGEXTRANET_ZONE                = 2260; // sxNetIDList.sxNetID.zone\n\tpublic const int CERTINFO_STRONGEXTRANET_ID                  = 2261; // sxNetIDList.sxNetID.id\n\tpublic const int CERTINFO_SUBJECTDIRECTORYATTRIBUTES         = 2262;\n\tpublic const int CERTINFO_SUBJECTDIR_TYPE                    = 2263; // attribute.type\n\tpublic const int CERTINFO_SUBJECTDIR_VALUES                  = 2264; // attribute.values\n\tpublic const int CERTINFO_SUBJECTKEYIDENTIFIER               = 2265; // 2 5 29 15 keyUsage\n\tpublic const int CERTINFO_KEYUSAGE                           = 2266; // 2 5 29 16 privateKeyUsagePeriod\n\tpublic const int CERTINFO_PRIVATEKEYUSAGEPERIOD              = 2267;\n\tpublic const int CERTINFO_PRIVATEKEY_NOTBEFORE               = 2268; // notBefore\n\tpublic const int CERTINFO_PRIVATEKEY_NOTAFTER                = 2269; // notAfter\n\tpublic const int CERTINFO_SUBJECTALTNAME                     = 2270; // 2 5 29 18 issuerAltName\n\tpublic const int CERTINFO_ISSUERALTNAME                      = 2271; // 2 5 29 19 basicConstraints\n\tpublic const int CERTINFO_BASICCONSTRAINTS                   = 2272;\n\tpublic const int CERTINFO_CA                                 = 2273; // cA\n\tpublic const int CERTINFO_AUTHORITY                          = 2273;\n\tpublic const int CERTINFO_PATHLENCONSTRAINT                  = 2274; // pathLenConstraint\n\tpublic const int CERTINFO_CRLNUMBER                          = 2275; // 2 5 29 21 cRLReason\n\tpublic const int CERTINFO_CRLREASON                          = 2276; // 2 5 29 23 holdInstructionCode\n\tpublic const int CERTINFO_HOLDINSTRUCTIONCODE                = 2277; // 2 5 29 24 invalidityDate\n\tpublic const int CERTINFO_INVALIDITYDATE                     = 2278; // 2 5 29 27 deltaCRLIndicator\n\tpublic const int CERTINFO_DELTACRLINDICATOR                  = 2279; // 2 5 29 28 issuingDistributionPoint\n\tpublic const int CERTINFO_ISSUINGDISTRIBUTIONPOINT           = 2280;\n\tpublic const int CERTINFO_ISSUINGDIST_FULLNAME               = 2281; // distributionPointName.fullName\n\tpublic const int CERTINFO_ISSUINGDIST_USERCERTSONLY          = 2282; // onlyContainsUserCerts\n\tpublic const int CERTINFO_ISSUINGDIST_CACERTSONLY            = 2283; // onlyContainsCACerts\n\tpublic const int CERTINFO_ISSUINGDIST_SOMEREASONSONLY        = 2284; // onlySomeReasons\n\tpublic const int CERTINFO_ISSUINGDIST_INDIRECTCRL            = 2285; // indirectCRL\n\tpublic const int CERTINFO_CERTIFICATEISSUER                  = 2286; // 2 5 29 30 nameConstraints\n\tpublic const int CERTINFO_NAMECONSTRAINTS                    = 2287;\n\tpublic const int CERTINFO_PERMITTEDSUBTREES                  = 2288; // permittedSubtrees\n\tpublic const int CERTINFO_EXCLUDEDSUBTREES                   = 2289; // excludedSubtrees\n\tpublic const int CERTINFO_CRLDISTRIBUTIONPOINT               = 2290;\n\tpublic const int CERTINFO_CRLDIST_FULLNAME                   = 2291; // distributionPointName.fullName\n\tpublic const int CERTINFO_CRLDIST_REASONS                    = 2292; // reasons\n\tpublic const int CERTINFO_CRLDIST_CRLISSUER                  = 2293; // cRLIssuer\n\tpublic const int CERTINFO_CERTIFICATEPOLICIES                = 2294;\n\tpublic const int CERTINFO_CERTPOLICYID                       = 2295; // policyInformation.policyIdentifier\n\tpublic const int CERTINFO_CERTPOLICY_CPSURI                  = 2296; // policyInformation.policyQualifiers.qualifier.cPSuri\n\tpublic const int CERTINFO_CERTPOLICY_ORGANIZATION            = 2297; // policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization\n\tpublic const int CERTINFO_CERTPOLICY_NOTICENUMBERS           = 2298; // policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers\n\tpublic const int CERTINFO_CERTPOLICY_EXPLICITTEXT            = 2299; // policyInformation.policyQualifiers.qualifier.userNotice.explicitText\n\tpublic const int CERTINFO_POLICYMAPPINGS                     = 2300;\n\tpublic const int CERTINFO_ISSUERDOMAINPOLICY                 = 2301; // policyMappings.issuerDomainPolicy\n\tpublic const int CERTINFO_SUBJECTDOMAINPOLICY                = 2302; // policyMappings.subjectDomainPolicy\n\tpublic const int CERTINFO_AUTHORITYKEYIDENTIFIER             = 2303;\n\tpublic const int CERTINFO_AUTHORITY_KEYIDENTIFIER            = 2304; // keyIdentifier\n\tpublic const int CERTINFO_AUTHORITY_CERTISSUER               = 2305; // authorityCertIssuer\n\tpublic const int CERTINFO_AUTHORITY_CERTSERIALNUMBER         = 2306; // authorityCertSerialNumber\n\tpublic const int CERTINFO_POLICYCONSTRAINTS                  = 2307;\n\tpublic const int CERTINFO_REQUIREEXPLICITPOLICY              = 2308; // policyConstraints.requireExplicitPolicy\n\tpublic const int CERTINFO_INHIBITPOLICYMAPPING               = 2309; // policyConstraints.inhibitPolicyMapping\n\tpublic const int CERTINFO_EXTKEYUSAGE                        = 2310;\n\tpublic const int CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING    = 2311; // individualCodeSigning\n\tpublic const int CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING    = 2312; // commercialCodeSigning\n\tpublic const int CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING     = 2313; // certTrustListSigning\n\tpublic const int CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING         = 2314; // timeStampSigning\n\tpublic const int CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO        = 2315; // serverGatedCrypto\n\tpublic const int CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM      = 2316; // encrypedFileSystem\n\tpublic const int CERTINFO_EXTKEY_SERVERAUTH                  = 2317; // serverAuth\n\tpublic const int CERTINFO_EXTKEY_CLIENTAUTH                  = 2318; // clientAuth\n\tpublic const int CERTINFO_EXTKEY_CODESIGNING                 = 2319; // codeSigning\n\tpublic const int CERTINFO_EXTKEY_EMAILPROTECTION             = 2320; // emailProtection\n\tpublic const int CERTINFO_EXTKEY_IPSECENDSYSTEM              = 2321; // ipsecEndSystem\n\tpublic const int CERTINFO_EXTKEY_IPSECTUNNEL                 = 2322; // ipsecTunnel\n\tpublic const int CERTINFO_EXTKEY_IPSECUSER                   = 2323; // ipsecUser\n\tpublic const int CERTINFO_EXTKEY_TIMESTAMPING                = 2324; // timeStamping\n\tpublic const int CERTINFO_EXTKEY_OCSPSIGNING                 = 2325; // ocspSigning\n\tpublic const int CERTINFO_EXTKEY_DIRECTORYSERVICE            = 2326; // directoryService\n\tpublic const int CERTINFO_EXTKEY_ANYKEYUSAGE                 = 2327; // anyExtendedKeyUsage\n\tpublic const int CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO        = 2328; // serverGatedCrypto\n\tpublic const int CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA     = 2329; // serverGatedCrypto CA\n\tpublic const int CERTINFO_EXTKEYUSAGE_LAST                   = 2329; // 2 5 29 40 crlStreamIdentifier\n\tpublic const int CERTINFO_CRLSTREAMIDENTIFIER                = 2330; // 2 5 29 46 freshestCRL\n\tpublic const int CERTINFO_FRESHESTCRL                        = 2331;\n\tpublic const int CERTINFO_FRESHESTCRL_FULLNAME               = 2332; // distributionPointName.fullName\n\tpublic const int CERTINFO_FRESHESTCRL_REASONS                = 2333; // reasons\n\tpublic const int CERTINFO_FRESHESTCRL_CRLISSUER              = 2334; // cRLIssuer\n\tpublic const int CERTINFO_ORDEREDLIST                        = 2335; // 2 5 29 51 baseUpdateTime\n\tpublic const int CERTINFO_BASEUPDATETIME                     = 2336; // 2 5 29 53 deltaInfo\n\tpublic const int CERTINFO_DELTAINFO                          = 2337;\n\tpublic const int CERTINFO_DELTAINFO_LOCATION                 = 2338; // deltaLocation\n\tpublic const int CERTINFO_DELTAINFO_NEXTDELTA                = 2339; // nextDelta\n\tpublic const int CERTINFO_INHIBITANYPOLICY                   = 2340; // 2 5 29 58 toBeRevoked\n\tpublic const int CERTINFO_TOBEREVOKED                        = 2341;\n\tpublic const int CERTINFO_TOBEREVOKED_CERTISSUER             = 2342; // certificateIssuer\n\tpublic const int CERTINFO_TOBEREVOKED_REASONCODE             = 2343; // reasonCode\n\tpublic const int CERTINFO_TOBEREVOKED_REVOCATIONTIME         = 2344; // revocationTime\n\tpublic const int CERTINFO_TOBEREVOKED_CERTSERIALNUMBER       = 2345; // certSerialNumber\n\tpublic const int CERTINFO_REVOKEDGROUPS                      = 2346;\n\tpublic const int CERTINFO_REVOKEDGROUPS_CERTISSUER           = 2347; // certificateIssuer\n\tpublic const int CERTINFO_REVOKEDGROUPS_REASONCODE           = 2348; // reasonCode\n\tpublic const int CERTINFO_REVOKEDGROUPS_INVALIDITYDATE       = 2349; // invalidityDate\n\tpublic const int CERTINFO_REVOKEDGROUPS_STARTINGNUMBER       = 2350; // startingNumber\n\tpublic const int CERTINFO_REVOKEDGROUPS_ENDINGNUMBER         = 2351; // endingNumber\n\tpublic const int CERTINFO_EXPIREDCERTSONCRL                  = 2352; // 2 5 29 63 aaIssuingDistributionPoint\n\tpublic const int CERTINFO_AAISSUINGDISTRIBUTIONPOINT         = 2353;\n\tpublic const int CERTINFO_AAISSUINGDIST_FULLNAME             = 2354; // distributionPointName.fullName\n\tpublic const int CERTINFO_AAISSUINGDIST_SOMEREASONSONLY      = 2355; // onlySomeReasons\n\tpublic const int CERTINFO_AAISSUINGDIST_INDIRECTCRL          = 2356; // indirectCRL\n\tpublic const int CERTINFO_AAISSUINGDIST_USERATTRCERTS        = 2357; // containsUserAttributeCerts\n\tpublic const int CERTINFO_AAISSUINGDIST_AACERTS              = 2358; // containsAACerts\n\tpublic const int CERTINFO_AAISSUINGDIST_SOACERTS             = 2359; // containsSOAPublicKeyCerts\n\tpublic const int CERTINFO_NS_CERTTYPE                        = 2360; // netscape-cert-type\n\tpublic const int CERTINFO_NS_BASEURL                         = 2361; // netscape-base-url\n\tpublic const int CERTINFO_NS_REVOCATIONURL                   = 2362; // netscape-revocation-url\n\tpublic const int CERTINFO_NS_CAREVOCATIONURL                 = 2363; // netscape-ca-revocation-url\n\tpublic const int CERTINFO_NS_CERTRENEWALURL                  = 2364; // netscape-cert-renewal-url\n\tpublic const int CERTINFO_NS_CAPOLICYURL                     = 2365; // netscape-ca-policy-url\n\tpublic const int CERTINFO_NS_SSLSERVERNAME                   = 2366; // netscape-ssl-server-name\n\tpublic const int CERTINFO_NS_COMMENT                         = 2367; // netscape-comment\n\tpublic const int CERTINFO_SET_HASHEDROOTKEY                  = 2368;\n\tpublic const int CERTINFO_SET_ROOTKEYTHUMBPRINT              = 2369; // rootKeyThumbPrint\n\tpublic const int CERTINFO_SET_CERTIFICATETYPE                = 2370; // 2 23 42 7 2 SET merchantData\n\tpublic const int CERTINFO_SET_MERCHANTDATA                   = 2371;\n\tpublic const int CERTINFO_SET_MERID                          = 2372; // merID\n\tpublic const int CERTINFO_SET_MERACQUIRERBIN                 = 2373; // merAcquirerBIN\n\tpublic const int CERTINFO_SET_MERCHANTLANGUAGE               = 2374; // merNames.language\n\tpublic const int CERTINFO_SET_MERCHANTNAME                   = 2375; // merNames.name\n\tpublic const int CERTINFO_SET_MERCHANTCITY                   = 2376; // merNames.city\n\tpublic const int CERTINFO_SET_MERCHANTSTATEPROVINCE          = 2377; // merNames.stateProvince\n\tpublic const int CERTINFO_SET_MERCHANTPOSTALCODE             = 2378; // merNames.postalCode\n\tpublic const int CERTINFO_SET_MERCHANTCOUNTRYNAME            = 2379; // merNames.countryName\n\tpublic const int CERTINFO_SET_MERCOUNTRY                     = 2380; // merCountry\n\tpublic const int CERTINFO_SET_MERAUTHFLAG                    = 2381; // merAuthFlag\n\tpublic const int CERTINFO_SET_CERTCARDREQUIRED               = 2382; // 2 23 42 7 4 SET tunneling\n\tpublic const int CERTINFO_SET_TUNNELING                      = 2383;\n\tpublic const int CERTINFO_SET_TUNNELLING                     = 2383;\n\tpublic const int CERTINFO_SET_TUNNELINGFLAG                  = 2384; // tunneling\n\tpublic const int CERTINFO_SET_TUNNELLINGFLAG                 = 2384;\n\tpublic const int CERTINFO_SET_TUNNELINGALGID                 = 2385; // tunnelingAlgID\n\tpublic const int CERTINFO_SET_TUNNELLINGALGID                = 2385; // S/MIME attributes\n\tpublic const int CERTINFO_CMS_CONTENTTYPE                    = 2500; // 1 2 840 113549 1 9 4 messageDigest\n\tpublic const int CERTINFO_CMS_MESSAGEDIGEST                  = 2501; // 1 2 840 113549 1 9 5 signingTime\n\tpublic const int CERTINFO_CMS_SIGNINGTIME                    = 2502; // 1 2 840 113549 1 9 6 counterSignature\n\tpublic const int CERTINFO_CMS_COUNTERSIGNATURE               = 2503; // counterSignature\n\tpublic const int CERTINFO_CMS_SIGNINGDESCRIPTION             = 2504; // 1 2 840 113549 1 9 15 sMIMECapabilities\n\tpublic const int CERTINFO_CMS_SMIMECAPABILITIES              = 2505;\n\tpublic const int CERTINFO_CMS_SMIMECAP_3DES                  = 2506; // 3DES encryption\n\tpublic const int CERTINFO_CMS_SMIMECAP_AES                   = 2507; // AES encryption\n\tpublic const int CERTINFO_CMS_SMIMECAP_CAST128               = 2508; // CAST-128 encryption\n\tpublic const int CERTINFO_CMS_SMIMECAP_SHAng                 = 2509; // SHA2-ng hash\n\tpublic const int CERTINFO_CMS_SMIMECAP_SHA2                  = 2510; // SHA2-256 hash\n\tpublic const int CERTINFO_CMS_SMIMECAP_SHA1                  = 2511; // SHA1 hash\n\tpublic const int CERTINFO_CMS_SMIMECAP_HMAC_SHAng            = 2512; // HMAC-SHA2-ng MAC\n\tpublic const int CERTINFO_CMS_SMIMECAP_HMAC_SHA2             = 2513; // HMAC-SHA2-256 MAC\n\tpublic const int CERTINFO_CMS_SMIMECAP_HMAC_SHA1             = 2514; // HMAC-SHA1 MAC\n\tpublic const int CERTINFO_CMS_SMIMECAP_AUTHENC256            = 2515; // AuthEnc w.256-bit key\n\tpublic const int CERTINFO_CMS_SMIMECAP_AUTHENC128            = 2516; // AuthEnc w.128-bit key\n\tpublic const int CERTINFO_CMS_SMIMECAP_RSA_SHAng             = 2517; // RSA with SHA-ng signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_RSA_SHA2              = 2518; // RSA with SHA2-256 signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_RSA_SHA1              = 2519; // RSA with SHA1 signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_DSA_SHA1              = 2520; // DSA with SHA-1 signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_ECDSA_SHAng           = 2521; // ECDSA with SHA-ng signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_ECDSA_SHA2            = 2522; // ECDSA with SHA2-256 signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_ECDSA_SHA1            = 2523; // ECDSA with SHA-1 signing\n\tpublic const int CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA      = 2524; // preferSignedData\n\tpublic const int CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY      = 2525; // canNotDecryptAny\n\tpublic const int CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE    = 2526; // preferBinaryInside\n\tpublic const int CERTINFO_CMS_RECEIPTREQUEST                 = 2527;\n\tpublic const int CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER      = 2528; // contentIdentifier\n\tpublic const int CERTINFO_CMS_RECEIPT_FROM                   = 2529; // receiptsFrom\n\tpublic const int CERTINFO_CMS_RECEIPT_TO                     = 2530; // receiptsTo\n\tpublic const int CERTINFO_CMS_SECURITYLABEL                  = 2531;\n\tpublic const int CERTINFO_CMS_SECLABEL_POLICY                = 2532; // securityPolicyIdentifier\n\tpublic const int CERTINFO_CMS_SECLABEL_CLASSIFICATION        = 2533; // securityClassification\n\tpublic const int CERTINFO_CMS_SECLABEL_PRIVACYMARK           = 2534; // privacyMark\n\tpublic const int CERTINFO_CMS_SECLABEL_CATTYPE               = 2535; // securityCategories.securityCategory.type\n\tpublic const int CERTINFO_CMS_SECLABEL_CATVALUE              = 2536; // securityCategories.securityCategory.value\n\tpublic const int CERTINFO_CMS_MLEXPANSIONHISTORY             = 2537;\n\tpublic const int CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER         = 2538; // mlData.mailListIdentifier.issuerAndSerialNumber\n\tpublic const int CERTINFO_CMS_MLEXP_TIME                     = 2539; // mlData.expansionTime\n\tpublic const int CERTINFO_CMS_MLEXP_NONE                     = 2540; // mlData.mlReceiptPolicy.none\n\tpublic const int CERTINFO_CMS_MLEXP_INSTEADOF                = 2541; // mlData.mlReceiptPolicy.insteadOf.generalNames.generalName\n\tpublic const int CERTINFO_CMS_MLEXP_INADDITIONTO             = 2542; // mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName\n\tpublic const int CERTINFO_CMS_CONTENTHINTS                   = 2543;\n\tpublic const int CERTINFO_CMS_CONTENTHINT_DESCRIPTION        = 2544; // contentDescription\n\tpublic const int CERTINFO_CMS_CONTENTHINT_TYPE               = 2545; // contentType\n\tpublic const int CERTINFO_CMS_EQUIVALENTLABEL                = 2546;\n\tpublic const int CERTINFO_CMS_EQVLABEL_POLICY                = 2547; // securityPolicyIdentifier\n\tpublic const int CERTINFO_CMS_EQVLABEL_CLASSIFICATION        = 2548; // securityClassification\n\tpublic const int CERTINFO_CMS_EQVLABEL_PRIVACYMARK           = 2549; // privacyMark\n\tpublic const int CERTINFO_CMS_EQVLABEL_CATTYPE               = 2550; // securityCategories.securityCategory.type\n\tpublic const int CERTINFO_CMS_EQVLABEL_CATVALUE              = 2551; // securityCategories.securityCategory.value\n\tpublic const int CERTINFO_CMS_SIGNINGCERTIFICATE             = 2552;\n\tpublic const int CERTINFO_CMS_SIGNINGCERT_ESSCERTID          = 2553; // certs.essCertID\n\tpublic const int CERTINFO_CMS_SIGNINGCERT_POLICIES           = 2554; // policies.policyInformation.policyIdentifier\n\tpublic const int CERTINFO_CMS_SIGNINGCERTIFICATEV2           = 2555;\n\tpublic const int CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2      = 2556; // certs.essCertID\n\tpublic const int CERTINFO_CMS_SIGNINGCERTV2_POLICIES         = 2557; // policies.policyInformation.policyIdentifier\n\tpublic const int CERTINFO_CMS_SIGNATUREPOLICYID              = 2558;\n\tpublic const int CERTINFO_CMS_SIGPOLICYID                    = 2559; // sigPolicyID\n\tpublic const int CERTINFO_CMS_SIGPOLICYHASH                  = 2560; // sigPolicyHash\n\tpublic const int CERTINFO_CMS_SIGPOLICY_CPSURI               = 2561; // sigPolicyQualifiers.sigPolicyQualifier.cPSuri\n\tpublic const int CERTINFO_CMS_SIGPOLICY_ORGANIZATION         = 2562; // sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization\n\tpublic const int CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS        = 2563; // sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers\n\tpublic const int CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT         = 2564; // sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText\n\tpublic const int CERTINFO_CMS_SIGTYPEIDENTIFIER              = 2565;\n\tpublic const int CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG        = 2566; // originatorSig\n\tpublic const int CERTINFO_CMS_SIGTYPEID_DOMAINSIG            = 2567; // domainSig\n\tpublic const int CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES = 2568; // additionalAttributesSig\n\tpublic const int CERTINFO_CMS_SIGTYPEID_REVIEWSIG            = 2569; // reviewSig\n\tpublic const int CERTINFO_CMS_NONCE                          = 2570; // randomNonce\n\tpublic const int CERTINFO_SCEP_MESSAGETYPE                   = 2571; // messageType\n\tpublic const int CERTINFO_SCEP_PKISTATUS                     = 2572; // pkiStatus\n\tpublic const int CERTINFO_SCEP_FAILINFO                      = 2573; // failInfo\n\tpublic const int CERTINFO_SCEP_SENDERNONCE                   = 2574; // senderNonce\n\tpublic const int CERTINFO_SCEP_RECIPIENTNONCE                = 2575; // recipientNonce\n\tpublic const int CERTINFO_SCEP_TRANSACTIONID                 = 2576; // transID\n\tpublic const int CERTINFO_CMS_SPCAGENCYINFO                  = 2577;\n\tpublic const int CERTINFO_CMS_SPCAGENCYURL                   = 2578; // spcAgencyInfo.url\n\tpublic const int CERTINFO_CMS_SPCSTATEMENTTYPE               = 2579;\n\tpublic const int CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING  = 2580; // individualCodeSigning\n\tpublic const int CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING  = 2581; // commercialCodeSigning\n\tpublic const int CERTINFO_CMS_SPCOPUSINFO                    = 2582;\n\tpublic const int CERTINFO_CMS_SPCOPUSINFO_NAME               = 2583; // spcOpusInfo.name\n\tpublic const int CERTINFO_CMS_SPCOPUSINFO_URL                = 2584; // spcOpusInfo.url\n\tpublic const int CERTINFO_LAST                               = 2585;\n\tpublic const int KEYINFO_FIRST                               = 3000; // *******************\n\tpublic const int KEYINFO_QUERY                               = 3001; // Keyset query\n\tpublic const int KEYINFO_QUERY_REQUESTS                      = 3002; // Query of requests in cert store\n\tpublic const int KEYINFO_LAST                                = 3003;\n\tpublic const int DEVINFO_FIRST                               = 4000; // *******************\n\tpublic const int DEVINFO_INITIALISE                          = 4001; // Initialise device for use\n\tpublic const int DEVINFO_INITIALIZE                          = 4001;\n\tpublic const int DEVINFO_AUTHENT_USER                        = 4002; // Authenticate user to device\n\tpublic const int DEVINFO_AUTHENT_SUPERVISOR                  = 4003; // Authenticate supervisor to dev.\n\tpublic const int DEVINFO_SET_AUTHENT_USER                    = 4004; // Set user authent.value\n\tpublic const int DEVINFO_SET_AUTHENT_SUPERVISOR              = 4005; // Set supervisor auth.val.\n\tpublic const int DEVINFO_ZEROISE                             = 4006; // Zeroise device\n\tpublic const int DEVINFO_ZEROIZE                             = 4006;\n\tpublic const int DEVINFO_LOGGEDIN                            = 4007; // Whether user is logged in\n\tpublic const int DEVINFO_LABEL                               = 4008; // Device/token label\n\tpublic const int DEVINFO_LAST                                = 4009;\n\tpublic const int ENVINFO_FIRST                               = 5000; // *********************\n\tpublic const int ENVINFO_DATASIZE                            = 5001; // Data size information\n\tpublic const int ENVINFO_COMPRESSION                         = 5002; // Compression information\n\tpublic const int ENVINFO_CONTENTTYPE                         = 5003; // Inner CMS content type\n\tpublic const int ENVINFO_DETACHEDSIGNATURE                   = 5004; // Detached signature\n\tpublic const int ENVINFO_SIGNATURE_RESULT                    = 5005; // Signature check result\n\tpublic const int ENVINFO_INTEGRITY                           = 5006; // Integrity-protection level\n\tpublic const int ENVINFO_PASSWORD                            = 5007; // User password\n\tpublic const int ENVINFO_KEY                                 = 5008; // Conventional encryption key\n\tpublic const int ENVINFO_SIGNATURE                           = 5009; // Signature/signature check key\n\tpublic const int ENVINFO_SIGNATURE_EXTRADATA                 = 5010; // Extra information added to CMS sigs\n\tpublic const int ENVINFO_RECIPIENT                           = 5011; // Recipient email address\n\tpublic const int ENVINFO_PUBLICKEY                           = 5012; // PKC encryption key\n\tpublic const int ENVINFO_PRIVATEKEY                          = 5013; // PKC decryption key\n\tpublic const int ENVINFO_PRIVATEKEY_LABEL                    = 5014; // Label of PKC decryption key\n\tpublic const int ENVINFO_ORIGINATOR                          = 5015; // Originator info/key\n\tpublic const int ENVINFO_SESSIONKEY                          = 5016; // Session key\n\tpublic const int ENVINFO_HASH                                = 5017; // Hash value\n\tpublic const int ENVINFO_TIMESTAMP                           = 5018; // Timestamp information\n\tpublic const int ENVINFO_KEYSET_SIGCHECK                     = 5019; // Signature check keyset\n\tpublic const int ENVINFO_KEYSET_ENCRYPT                      = 5020; // PKC encryption keyset\n\tpublic const int ENVINFO_KEYSET_DECRYPT                      = 5021; // PKC decryption keyset\n\tpublic const int ENVINFO_LAST                                = 5022;\n\tpublic const int SESSINFO_FIRST                              = 6000; // ********************\n\tpublic const int SESSINFO_ACTIVE                             = 6001; // Whether session is active\n\tpublic const int SESSINFO_CONNECTIONACTIVE                   = 6002; // Whether network connection is active\n\tpublic const int SESSINFO_USERNAME                           = 6003; // User name\n\tpublic const int SESSINFO_PASSWORD                           = 6004; // Password\n\tpublic const int SESSINFO_PRIVATEKEY                         = 6005; // Server/client private key\n\tpublic const int SESSINFO_KEYSET                             = 6006; // Certificate store\n\tpublic const int SESSINFO_AUTHRESPONSE                       = 6007; // Session authorisation OK\n\tpublic const int SESSINFO_SERVER_NAME                        = 6008; // Server name\n\tpublic const int SESSINFO_SERVER_PORT                        = 6009; // Server port number\n\tpublic const int SESSINFO_SERVER_FINGERPRINT_SHA1            = 6010; // Server key fingerprint\n\tpublic const int SESSINFO_CLIENT_NAME                        = 6011; // Client name\n\tpublic const int SESSINFO_CLIENT_PORT                        = 6012; // Client port number\n\tpublic const int SESSINFO_SESSION                            = 6013; // Transport mechanism\n\tpublic const int SESSINFO_NETWORKSOCKET                      = 6014; // User-supplied network socket\n\tpublic const int SESSINFO_VERSION                            = 6015; // Protocol version\n\tpublic const int SESSINFO_REQUEST                            = 6016; // Cert.request object\n\tpublic const int SESSINFO_RESPONSE                           = 6017; // Cert.response object\n\tpublic const int SESSINFO_CACERTIFICATE                      = 6018; // Issuing CA certificate\n\tpublic const int SESSINFO_CMP_REQUESTTYPE                    = 6019; // Request type\n\tpublic const int SESSINFO_CMP_PRIVKEYSET                     = 6020; // Private-key keyset\n\tpublic const int SESSINFO_SSH_CHANNEL                        = 6021; // SSH current channel\n\tpublic const int SESSINFO_SSH_CHANNEL_TYPE                   = 6022; // SSH channel type\n\tpublic const int SESSINFO_SSH_CHANNEL_ARG1                   = 6023; // SSH channel argument 1\n\tpublic const int SESSINFO_SSH_CHANNEL_ARG2                   = 6024; // SSH channel argument 2\n\tpublic const int SESSINFO_SSH_CHANNEL_ACTIVE                 = 6025; // SSH channel active\n\tpublic const int SESSINFO_SSL_OPTIONS                        = 6026; // SSL/TLS protocol options\n\tpublic const int SESSINFO_SSL_SUBPROTOCOL                    = 6027; // SSL/TLS additional sub-protocol\n\tpublic const int SESSINFO_SSL_WSPROTOCOL                     = 6028; // SSL/TLS WebSockets sub-protocol\n\tpublic const int SESSINFO_SSL_EAPCHALLENGE                   = 6029; // SSL/TLS EAP challenge\n\tpublic const int SESSINFO_SSL_EAPKEY                         = 6030; // SSL/TLS EAP key\n\tpublic const int SESSINFO_TSP_MSGIMPRINT                     = 6031; // TSP message imprint\n\tpublic const int SESSINFO_LAST                               = 6032;\n\tpublic const int USERINFO_FIRST                              = 7000; // ********************\n\tpublic const int USERINFO_PASSWORD                           = 7001; // Password\n\tpublic const int USERINFO_CAKEY_CERTSIGN                     = 7002; // CA cert signing key\n\tpublic const int USERINFO_CAKEY_CRLSIGN                      = 7003; // CA CRL signing key\n\tpublic const int USERINFO_CAKEY_RTCSSIGN                     = 7004; // CA RTCS signing key\n\tpublic const int USERINFO_CAKEY_OCSPSIGN                     = 7005; // CA OCSP signing key\n\tpublic const int USERINFO_LAST                               = 7006;\n\tpublic const int ATTRIBUTE_LAST                              = 7006;\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\tAttribute Subtypes and Related Values\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Flags for the X.509 keyUsage extension */\n\t\n\tpublic const int KEYUSAGE_NONE                            = 0x000;\n\tpublic const int KEYUSAGE_DIGITALSIGNATURE                = 0x001;\n\tpublic const int KEYUSAGE_NONREPUDIATION                  = 0x002;\n\tpublic const int KEYUSAGE_KEYENCIPHERMENT                 = 0x004;\n\tpublic const int KEYUSAGE_DATAENCIPHERMENT                = 0x008;\n\tpublic const int KEYUSAGE_KEYAGREEMENT                    = 0x010;\n\tpublic const int KEYUSAGE_KEYCERTSIGN                     = 0x020;\n\tpublic const int KEYUSAGE_CRLSIGN                         = 0x040;\n\tpublic const int KEYUSAGE_ENCIPHERONLY                    = 0x080;\n\tpublic const int KEYUSAGE_DECIPHERONLY                    = 0x100;\n\tpublic const int KEYUSAGE_LAST                            = 0x200; // Last possible value\n\t\n\t/* X.509 cRLReason and cryptlib cRLExtReason codes */\n\t\n\tpublic const int CRLREASON_UNSPECIFIED          = 0 ;\n\tpublic const int CRLREASON_KEYCOMPROMISE        = 1 ;\n\tpublic const int CRLREASON_CACOMPROMISE         = 2 ;\n\tpublic const int CRLREASON_AFFILIATIONCHANGED   = 3 ;\n\tpublic const int CRLREASON_SUPERSEDED           = 4 ;\n\tpublic const int CRLREASON_CESSATIONOFOPERATION = 5 ;\n\tpublic const int CRLREASON_CERTIFICATEHOLD      = 6 ;\n\tpublic const int CRLREASON_REMOVEFROMCRL        = 8 ;\n\tpublic const int CRLREASON_PRIVILEGEWITHDRAWN   = 9 ;\n\tpublic const int CRLREASON_AACOMPROMISE         = 10;\n\tpublic const int CRLREASON_LAST                 = 11; // End of standard CRL reasons\n\tpublic const int CRLREASON_NEVERVALID           = 20;\n\tpublic const int CRLEXTREASON_LAST              = 21;\n\t\n\t/* X.509 CRL reason flags.  These identify the same thing as the cRLReason\n\t   codes but allow for multiple reasons to be specified.  Note that these\n\t   don't follow the X.509 naming since in that scheme the enumerated types\n\t   and bitflags have the same names */\n\t\n\tpublic const int CRLREASONFLAG_UNUSED                     = 0x001;\n\tpublic const int CRLREASONFLAG_KEYCOMPROMISE              = 0x002;\n\tpublic const int CRLREASONFLAG_CACOMPROMISE               = 0x004;\n\tpublic const int CRLREASONFLAG_AFFILIATIONCHANGED         = 0x008;\n\tpublic const int CRLREASONFLAG_SUPERSEDED                 = 0x010;\n\tpublic const int CRLREASONFLAG_CESSATIONOFOPERATION       = 0x020;\n\tpublic const int CRLREASONFLAG_CERTIFICATEHOLD            = 0x040;\n\tpublic const int CRLREASONFLAG_LAST                       = 0x080; // Last poss.value\n\t\n\t/* X.509 CRL holdInstruction codes */\n\t\n\tpublic const int HOLDINSTRUCTION_NONE        = 0;\n\tpublic const int HOLDINSTRUCTION_CALLISSUER  = 1;\n\tpublic const int HOLDINSTRUCTION_REJECT      = 2;\n\tpublic const int HOLDINSTRUCTION_PICKUPTOKEN = 3;\n\tpublic const int HOLDINSTRUCTION_LAST        = 4;\n\t\n\t/* Certificate checking compliance levels */\n\t\n\t// CRYPT_COMPLIANCELEVEL_TYPE\n\tpublic const int COMPLIANCELEVEL_OBLIVIOUS    = 0;\n\tpublic const int COMPLIANCELEVEL_REDUCED      = 1;\n\tpublic const int COMPLIANCELEVEL_STANDARD     = 2;\n\tpublic const int COMPLIANCELEVEL_PKIX_PARTIAL = 3;\n\tpublic const int COMPLIANCELEVEL_PKIX_FULL    = 4;\n\tpublic const int COMPLIANCELEVEL_LAST         = 5;\n\t\n\t/* Flags for the Netscape netscape-cert-type extension */\n\t\n\tpublic const int NS_CERTTYPE_SSLCLIENT                    = 0x001;\n\tpublic const int NS_CERTTYPE_SSLSERVER                    = 0x002;\n\tpublic const int NS_CERTTYPE_SMIME                        = 0x004;\n\tpublic const int NS_CERTTYPE_OBJECTSIGNING                = 0x008;\n\tpublic const int NS_CERTTYPE_RESERVED                     = 0x010;\n\tpublic const int NS_CERTTYPE_SSLCA                        = 0x020;\n\tpublic const int NS_CERTTYPE_SMIMECA                      = 0x040;\n\tpublic const int NS_CERTTYPE_OBJECTSIGNINGCA              = 0x080;\n\tpublic const int NS_CERTTYPE_LAST                         = 0x100; // Last possible value\n\t\n\t/* Flags for the SET certificate-type extension */\n\t\n\tpublic const int SET_CERTTYPE_CARD                        = 0x001;\n\tpublic const int SET_CERTTYPE_MER                         = 0x002;\n\tpublic const int SET_CERTTYPE_PGWY                        = 0x004;\n\tpublic const int SET_CERTTYPE_CCA                         = 0x008;\n\tpublic const int SET_CERTTYPE_MCA                         = 0x010;\n\tpublic const int SET_CERTTYPE_PCA                         = 0x020;\n\tpublic const int SET_CERTTYPE_GCA                         = 0x040;\n\tpublic const int SET_CERTTYPE_BCA                         = 0x080;\n\tpublic const int SET_CERTTYPE_RCA                         = 0x100;\n\tpublic const int SET_CERTTYPE_ACQ                         = 0x200;\n\tpublic const int SET_CERTTYPE_LAST                        = 0x400; // Last possible value\n\t\n\t/* CMS contentType values */\n\t\n\t// CRYPT_CONTENT_TYPE\n\tpublic const int CONTENT_NONE                   = 0 ;\n\tpublic const int CONTENT_DATA                   = 1 ;\n\tpublic const int CONTENT_SIGNEDDATA             = 2 ;\n\tpublic const int CONTENT_ENVELOPEDDATA          = 3 ;\n\tpublic const int CONTENT_SIGNEDANDENVELOPEDDATA = 4 ;\n\tpublic const int CONTENT_DIGESTEDDATA           = 5 ;\n\tpublic const int CONTENT_ENCRYPTEDDATA          = 6 ;\n\tpublic const int CONTENT_COMPRESSEDDATA         = 7 ;\n\tpublic const int CONTENT_AUTHDATA               = 8 ;\n\tpublic const int CONTENT_AUTHENVDATA            = 9 ;\n\tpublic const int CONTENT_TSTINFO                = 10;\n\tpublic const int CONTENT_SPCINDIRECTDATACONTEXT = 11;\n\tpublic const int CONTENT_RTCSREQUEST            = 12;\n\tpublic const int CONTENT_RTCSRESPONSE           = 13;\n\tpublic const int CONTENT_RTCSRESPONSE_EXT       = 14;\n\tpublic const int CONTENT_MRTD                   = 15;\n\tpublic const int CONTENT_LAST                   = 16;\n\t\n\t/* ESS securityClassification codes */\n\t\n\tpublic const int CLASSIFICATION_UNMARKED     = 0  ;\n\tpublic const int CLASSIFICATION_UNCLASSIFIED = 1  ;\n\tpublic const int CLASSIFICATION_RESTRICTED   = 2  ;\n\tpublic const int CLASSIFICATION_CONFIDENTIAL = 3  ;\n\tpublic const int CLASSIFICATION_SECRET       = 4  ;\n\tpublic const int CLASSIFICATION_TOP_SECRET   = 5  ;\n\tpublic const int CLASSIFICATION_LAST         = 255;\n\t\n\t/* RTCS certificate status */\n\t\n\t// CRYPT_CERTSTATUS_TYPE\n\tpublic const int CERTSTATUS_NONE             = 0; // No certificate status\n\tpublic const int CERTSTATUS_VALID            = 1; // Certificate valid\n\tpublic const int CERTSTATUS_NOTVALID         = 2; // Certificate isn't valid\n\tpublic const int CERTSTATUS_NONAUTHORITATIVE = 3; // Response is non-authoritative\n\tpublic const int CERTSTATUS_UNKNOWN          = 4; // Certificate status unknown\n\tpublic const int CERTSTATUS_LAST             = 5; // Last possible certificate status\n\t\n\t/* OCSP revocation status */\n\t\n\tpublic const int OCSPSTATUS_NOTREVOKED = 0;\n\tpublic const int OCSPSTATUS_REVOKED    = 1;\n\tpublic const int OCSPSTATUS_UNKNOWN    = 2;\n\t\n\t/* The amount of detail to include in signatures when signing certificate\n\t   objects */\n\t\n\t// CRYPT_SIGNATURELEVEL_TYPE\n\tpublic const int SIGNATURELEVEL_NONE       = 0; // Include only signature\n\tpublic const int SIGNATURELEVEL_SIGNERCERT = 1; // Include signer cert\n\tpublic const int SIGNATURELEVEL_ALL        = 2; // Include all relevant info\n\tpublic const int SIGNATURELEVEL_LAST       = 3; // Last possible sig.level type\n\t\n\t/* The level of integrity protection to apply to enveloped data.  The \n\t   default envelope protection for an envelope with keying information \n\t   applied is encryption, this can be modified to use MAC-only protection\n\t   (with no encryption) or hybrid encryption + authentication */\n\t\n\t// CRYPT_INTEGRITY_TYPE\n\tpublic const int INTEGRITY_NONE    = 0; // No integrity protection\n\tpublic const int INTEGRITY_MACONLY = 1; // MAC only, no encryption\n\tpublic const int INTEGRITY_FULL    = 2; // Encryption + ingerity protection\n\t\n\t/* The certificate export format type, which defines the format in which a\n\t   certificate object is exported */\n\t\n\t// CRYPT_CERTFORMAT_TYPE\n\tpublic const int CERTFORMAT_NONE             = 0; // No certificate format\n\tpublic const int CERTFORMAT_CERTIFICATE      = 1; // DER-encoded certificate\n\tpublic const int CERTFORMAT_CERTCHAIN        = 2; // PKCS #7 certificate chain\n\tpublic const int CERTFORMAT_TEXT_CERTIFICATE = 3; // base-64 wrapped cert\n\tpublic const int CERTFORMAT_TEXT_CERTCHAIN   = 4; // base-64 wrapped cert chain\n\tpublic const int CERTFORMAT_XML_CERTIFICATE  = 5; // XML wrapped cert\n\tpublic const int CERTFORMAT_XML_CERTCHAIN    = 6; // XML wrapped cert chain\n\tpublic const int CERTFORMAT_LAST             = 7; // Last possible cert.format type\n\t\n\t/* CMP request types */\n\t\n\t// CRYPT_REQUESTTYPE_TYPE\n\tpublic const int REQUESTTYPE_NONE           = 0; // No request type\n\tpublic const int REQUESTTYPE_INITIALISATION = 1; // Initialisation request\n\tpublic const int REQUESTTYPE_INITIALIZATION = 1;\n\tpublic const int REQUESTTYPE_CERTIFICATE    = 2; // Certification request\n\tpublic const int REQUESTTYPE_KEYUPDATE      = 3; // Key update request\n\tpublic const int REQUESTTYPE_REVOCATION     = 4; // Cert revocation request\n\tpublic const int REQUESTTYPE_PKIBOOT        = 5; // PKIBoot request\n\tpublic const int REQUESTTYPE_LAST           = 6; // Last possible request type\n\t\n\t/* Key ID types */\n\t\n\t// CRYPT_KEYID_TYPE\n\tpublic const int KEYID_NONE  = 0; // No key ID type\n\tpublic const int KEYID_NAME  = 1; // Key owner name\n\tpublic const int KEYID_URI   = 2; // Key owner URI\n\tpublic const int KEYID_EMAIL = 2; // Synonym: owner email addr.\n\tpublic const int KEYID_LAST  = 3; // Last possible key ID type\n\t\n\t/* The encryption object types */\n\t\n\t// CRYPT_OBJECT_TYPE\n\tpublic const int OBJECT_NONE             = 0; // No object type\n\tpublic const int OBJECT_ENCRYPTED_KEY    = 1; // Conventionally encrypted key\n\tpublic const int OBJECT_PKCENCRYPTED_KEY = 2; // PKC-encrypted key\n\tpublic const int OBJECT_KEYAGREEMENT     = 3; // Key agreement information\n\tpublic const int OBJECT_SIGNATURE        = 4; // Signature\n\tpublic const int OBJECT_LAST             = 5; // Last possible object type\n\t\n\t/* Object/attribute error type information */\n\t\n\t// CRYPT_ERRTYPE_TYPE\n\tpublic const int ERRTYPE_NONE             = 0; // No error information\n\tpublic const int ERRTYPE_ATTR_SIZE        = 1; // Attribute data too small or large\n\tpublic const int ERRTYPE_ATTR_VALUE       = 2; // Attribute value is invalid\n\tpublic const int ERRTYPE_ATTR_ABSENT      = 3; // Required attribute missing\n\tpublic const int ERRTYPE_ATTR_PRESENT     = 4; // Non-allowed attribute present\n\tpublic const int ERRTYPE_CONSTRAINT       = 5; // Cert: Constraint violation in object\n\tpublic const int ERRTYPE_ISSUERCONSTRAINT = 6; // Cert: Constraint viol.in issuing cert\n\tpublic const int ERRTYPE_LAST             = 7; // Last possible error info type\n\t\n\t/* Cert store management action type */\n\t\n\t// CRYPT_CERTACTION_TYPE\n\tpublic const int CERTACTION_NONE                   = 0 ; // No cert management action\n\tpublic const int CERTACTION_CREATE                 = 1 ; // Create cert store\n\tpublic const int CERTACTION_CONNECT                = 2 ; // Connect to cert store\n\tpublic const int CERTACTION_DISCONNECT             = 3 ; // Disconnect from cert store\n\tpublic const int CERTACTION_ERROR                  = 4 ; // Error information\n\tpublic const int CERTACTION_ADDUSER                = 5 ; // Add PKI user\n\tpublic const int CERTACTION_DELETEUSER             = 6 ; // Delete PKI user\n\tpublic const int CERTACTION_REQUEST_CERT           = 7 ; // Cert request\n\tpublic const int CERTACTION_REQUEST_RENEWAL        = 8 ; // Cert renewal request\n\tpublic const int CERTACTION_REQUEST_REVOCATION     = 9 ; // Cert revocation request\n\tpublic const int CERTACTION_CERT_CREATION          = 10; // Cert creation\n\tpublic const int CERTACTION_CERT_CREATION_COMPLETE = 11; // Confirmation of cert creation\n\tpublic const int CERTACTION_CERT_CREATION_DROP     = 12; // Cancellation of cert creation\n\tpublic const int CERTACTION_CERT_CREATION_REVERSE  = 13; // Cancel of creation w.revocation\n\tpublic const int CERTACTION_RESTART_CLEANUP        = 14; // Delete reqs after restart\n\tpublic const int CERTACTION_RESTART_REVOKE_CERT    = 15; // Complete revocation after restart\n\tpublic const int CERTACTION_ISSUE_CERT             = 16; // Cert issue\n\tpublic const int CERTACTION_ISSUE_CRL              = 17; // CRL issue\n\tpublic const int CERTACTION_REVOKE_CERT            = 18; // Cert revocation\n\tpublic const int CERTACTION_EXPIRE_CERT            = 19; // Cert expiry\n\tpublic const int CERTACTION_CLEANUP                = 20; // Clean up on restart\n\tpublic const int CERTACTION_LAST                   = 21; // Last possible cert store log action\n\t\n\t/* Session sub-protocol types */\n\t\n\t// CRYPT_SUBPROTOCOL_TYPE\n\tpublic const int SUBPROTOCOL_NONE       = 0; // No sub-protocol type\n\tpublic const int SUBPROTOCOL_WEBSOCKETS = 1; // Websockets\n\tpublic const int SUBPROTOCOL_EAPTTLS    = 2; // EAP-TTLS\n\tpublic const int SUBPROTOCOL_LAST       = 3; // Last possible sub-protocol type\n\t\n\t/* SSL/TLS protocol options.  CRYPT_SSLOPTION_MINVER_SSLV3 is the same as \n\t   CRYPT_SSLOPTION_NONE since this is the baseline, although it'll never be\n\t   encountered since SSLv3 is disabled */\n\t\n\tpublic const int SSLOPTION_NONE                           = 0x000;\n\tpublic const int SSLOPTION_MINVER_SSLV3                   = 0x000; // Min.protocol version\n\tpublic const int SSLOPTION_MINVER_TLS10                   = 0x001;\n\tpublic const int SSLOPTION_MINVER_TLS11                   = 0x002;\n\tpublic const int SSLOPTION_MINVER_TLS12                   = 0x003;\n\tpublic const int SSLOPTION_MINVER_TLS13                   = 0x004;\n\tpublic const int SSLOPTION_MANUAL_CERTCHECK               = 0x008; // Require manual cert.verif.\n\tpublic const int SSLOPTION_DISABLE_NAMEVERIFY             = 0x010; // Disable cert hostname check\n\tpublic const int SSLOPTION_DISABLE_CERTVERIFY             = 0x020; // Disable certificate check\n\tpublic const int SSLOPTION_SUITEB_128                     = 0x100; // SuiteB security levels (may\n\tpublic const int SSLOPTION_SUITEB_256                     = 0x200; // vanish in future releases)\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tGeneral Constants\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* The maximum user key size - 2048 bits */\n\t\n\tpublic const int MAX_KEYSIZE                              = 256 ;\n\t\n\t/* The maximum IV/cipher block size - 256 bits */\n\t\n\tpublic const int MAX_IVSIZE                               = 32  ;\n\t\n\t/* The maximum public-key component size - 4096 bits, and maximum component\n\t   size for ECCs - 576 bits (to handle the P521 curve) */\n\t\n\tpublic const int MAX_PKCSIZE                              = 512 ;\n\tpublic const int MAX_PKCSIZE_ECC                          = 72  ;\n\t\n\t/* The maximum hash size - 512 bits.  Before 3.4 this was 256 bits, in the \n\t   3.4 release it was increased to 512 bits to accommodate SHA-3 */\n\t\n\tpublic const int MAX_HASHSIZE                             = 64  ;\n\t\n\t/* The maximum size of a text string (e.g.key owner name) */\n\t\n\tpublic const int MAX_TEXTSIZE                             = 64  ;\n\t\n\t/* A magic value indicating that the default setting for this parameter\n\t   should be used.  The parentheses are to catch potential erroneous use \n\t   in an expression */\n\t\n\tpublic const int USE_DEFAULT                              = -100;\n\t\n\t/* A magic value for unused parameters */\n\t\n\tpublic const int UNUSED                                   = -101;\n\t\n\t/* Cursor positioning codes for certificate/CRL extensions.  The parentheses \n\t   are to catch potential erroneous use in an expression */\n\t\n\tpublic const int CURSOR_FIRST                             = -200;\n\tpublic const int CURSOR_PREVIOUS                          = -201;\n\tpublic const int CURSOR_NEXT                              = -202;\n\tpublic const int CURSOR_LAST                              = -203;\n\t\n\t/* The type of information polling to perform to get random seed \n\t   information.  These values have to be negative because they're used\n\t   as magic length values for cryptAddRandom().  The parentheses are to \n\t   catch potential erroneous use in an expression */\n\t\n\tpublic const int RANDOM_FASTPOLL                          = -300;\n\tpublic const int RANDOM_SLOWPOLL                          = -301;\n\t\n\t/* Whether the PKC key is a public or private key */\n\t\n\tpublic const int KEYTYPE_PRIVATE                          = 0   ;\n\tpublic const int KEYTYPE_PUBLIC                           = 1   ;\n\t\n\t/* Keyset open options */\n\t\n\t// CRYPT_KEYOPT_TYPE\n\tpublic const int KEYOPT_NONE     = 0; // No options\n\tpublic const int KEYOPT_READONLY = 1; // Open keyset in read-only mode\n\tpublic const int KEYOPT_CREATE   = 2; // Create a new keyset\n\tpublic const int KEYOPT_LAST     = 3; // Last possible key option type\n\t\n\t/* The various cryptlib objects - these are just integer handles */\n\t\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_CERTIFICATE;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_CONTEXT;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_DEVICE;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_ENVELOPE;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_KEYSET;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_SESSION;\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_USER;\n\t\n\t/* Sometimes we don't know the exact type of a cryptlib object, so we use a\n\t   generic handle type to identify it */\n\t\n\t//CRYPTLIBCONVERTER - NOT NEEDED: typedef int CRYPT_HANDLE;\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\tEncryption Data Structures\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Results returned from the capability query */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//typedef struct {\n\t//\t/* Algorithm information */\n\t//\tC_CHR algoName[ CRYPT_MAX_TEXTSIZE ];/* Algorithm name */\n\t//\tint blockSize;\t\t\t\t\t/* Block size of the algorithm */\n\t//\tint minKeySize;\t\t\t\t\t/* Minimum key size in bytes */\n\t//\tint keySize;\t\t\t\t\t/* Recommended key size in bytes */\n\t//\tint maxKeySize;\t\t\t\t\t/* Maximum key size in bytes */\n\t//\t} CRYPT_QUERY_INFO;\n\t\n\t/* Results returned from the encoded object query.  These provide\n\t   information on the objects created by cryptExportKey()/\n\t   cryptCreateSignature() */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//typedef struct {\n\t//\t/* The object type */\n\t//\tCRYPT_OBJECT_TYPE objectType;\n\t//\n\t//\t/* The encryption algorithm and mode */\n\t//\tCRYPT_ALGO_TYPE cryptAlgo;\n\t//\tCRYPT_MODE_TYPE cryptMode;\n\t//\n\t//\t/* The hash algorithm for signature objects or PRF algorithm for derived \n\t//\t   keys */\n\t//\tCRYPT_ALGO_TYPE hashAlgo;\n\t//\n\t//\t/* The salt and PRF iterations for derived keys */\n\t//\tunsigned char salt[ CRYPT_MAX_HASHSIZE ];\n\t//\tint saltSize;\n\t//\tint iterations;\n\t//\t} CRYPT_OBJECT_INFO;\n\t\n\t/* Key information for the public-key encryption algorithms.  These fields\n\t   are not accessed directly, but can be manipulated with the init/set/\n\t   destroyComponents() macros */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//typedef struct {\n\t//\t/* Status information */\n\t//\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\t//\n\t//\t/* Public components */\n\t//\tunsigned char n[ CRYPT_MAX_PKCSIZE ];\t/* Modulus */\n\t//\tint nLen;\t\t\t\t\t/* Length of modulus in bits */\n\t//\tunsigned char e[ CRYPT_MAX_PKCSIZE ];\t/* Public exponent */\n\t//\tint eLen;\t\t\t\t\t/* Length of public exponent in bits */\n\t//\n\t//\t/* Private components */\n\t//\tunsigned char d[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent */\n\t//\tint dLen;\t\t\t\t\t/* Length of private exponent in bits */\n\t//\tunsigned char p[ CRYPT_MAX_PKCSIZE ];\t/* Prime factor 1 */\n\t//\tint pLen;\t\t\t\t\t/* Length of prime factor 1 in bits */\n\t//\tunsigned char q[ CRYPT_MAX_PKCSIZE ];\t/* Prime factor 2 */\n\t//\tint qLen;\t\t\t\t\t/* Length of prime factor 2 in bits */\n\t//\tunsigned char u[ CRYPT_MAX_PKCSIZE ];\t/* Mult.inverse of q, mod p */\n\t//\tint uLen;\t\t\t\t\t/* Length of private exponent in bits */\n\t//\tunsigned char e1[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent 1 (PKCS) */\n\t//\tint e1Len;\t\t\t\t\t/* Length of private exponent in bits */\n\t//\tunsigned char e2[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent 2 (PKCS) */\n\t//\tint e2Len;\t\t\t\t\t/* Length of private exponent in bits */\n\t//\t} CRYPT_PKCINFO_RSA;\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//typedef struct {\n\t//\t/* Status information */\n\t//\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\t//\n\t//\t/* Public components */\n\t//\tunsigned char p[ CRYPT_MAX_PKCSIZE ];\t/* Prime modulus */\n\t//\tint pLen;\t\t\t\t\t/* Length of prime modulus in bits */\n\t//\tunsigned char q[ CRYPT_MAX_PKCSIZE ];\t/* Prime divisor */\n\t//\tint qLen;\t\t\t\t\t/* Length of prime divisor in bits */\n\t//\tunsigned char g[ CRYPT_MAX_PKCSIZE ];\t/* h^( ( p - 1 ) / q ) mod p */\n\t//\tint gLen;\t\t\t\t\t/* Length of g in bits */\n\t//\tunsigned char y[ CRYPT_MAX_PKCSIZE ];\t/* Public random integer */\n\t//\tint yLen;\t\t\t\t\t/* Length of public integer in bits */\n\t//\n\t//\t/* Private components */\n\t//\tunsigned char x[ CRYPT_MAX_PKCSIZE ];\t/* Private random integer */\n\t//\tint xLen;\t\t\t\t\t/* Length of private integer in bits */\n\t//\t} CRYPT_PKCINFO_DLP;\n\t\n\t// CRYPT_ECCCURVE_TYPE\n\tpublic const int ECCCURVE_NONE           = 0; // No ECC curve type\n\tpublic const int ECCCURVE_P256           = 1; // NIST P256/X9.62 P256v1/SECG p256r1 curve\n\tpublic const int ECCCURVE_P384           = 2; // NIST P384, SECG p384r1 curve\n\tpublic const int ECCCURVE_P521           = 3; // NIST P521, SECG p521r1\n\tpublic const int ECCCURVE_BRAINPOOL_P256 = 4; // Brainpool p256r1\n\tpublic const int ECCCURVE_BRAINPOOL_P384 = 5; // Brainpool p384r1\n\tpublic const int ECCCURVE_BRAINPOOL_P512 = 6; // Brainpool p512r1\n\tpublic const int ECCCURVE_LAST           = 7; // Last valid ECC curve type\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//typedef struct {\n\t//\t/* Status information */\n\t//\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\t//\n\t//\t/* Curve domain parameters.  Either the curveType or the explicit domain\n\t//\t   parameters must be provided */\n\t//\tCRYPT_ECCCURVE_TYPE curveType;\t/* Named curve */\n\t//\tunsigned char p[ CRYPT_MAX_PKCSIZE_ECC ];/* Prime defining Fq */\n\t//\tint pLen;\t\t\t\t\t/* Length of prime in bits */\n\t//\tunsigned char a[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining curve */\n\t//\tint aLen;\t\t\t\t\t/* Length of element a in bits */\n\t//\tunsigned char b[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining curve */\n\t//\tint bLen;\t\t\t\t\t/* Length of element b in bits */\n\t//\tunsigned char gx[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining point */\n\t//\tint gxLen;\t\t\t\t\t/* Length of element gx in bits */\n\t//\tunsigned char gy[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining point */\n\t//\tint gyLen;\t\t\t\t\t/* Length of element gy in bits */\n\t//\tunsigned char n[ CRYPT_MAX_PKCSIZE_ECC ];/* Order of point */\n\t//\tint nLen;\t\t\t\t\t/* Length of order in bits */\n\t//\tunsigned char h[ CRYPT_MAX_PKCSIZE_ECC ];/* Optional cofactor */\n\t//\tint hLen;\t\t\t\t\t/* Length of cofactor in bits */\n\t//\n\t//\t/* Public components */\n\t//\tunsigned char qx[ CRYPT_MAX_PKCSIZE_ECC ];/* Point Q on the curve */\n\t//\tint qxLen;\t\t\t\t\t/* Length of point xq in bits */\n\t//\tunsigned char qy[ CRYPT_MAX_PKCSIZE_ECC ];/* Point Q on the curve */\n\t//\tint qyLen;\t\t\t\t\t/* Length of point xy in bits */\n\t//\n\t//\t/* Private components */\n\t//\tunsigned char d[ CRYPT_MAX_PKCSIZE_ECC ];/* Private random integer */\n\t//\tint dLen;\t\t\t\t\t/* Length of integer in bits */\n\t//\t} CRYPT_PKCINFO_ECC;\n\t\n\t/* Macros to initialise and destroy the structure that stores the components\n\t   of a public key */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//#define cryptInitComponents( componentInfo, componentKeyType ) \\\n\t//\t{ memset( ( componentInfo ), 0, sizeof( *componentInfo ) ); \\\n\t//\t  ( componentInfo )->isPublicKey = ( ( componentKeyType ) ? 1 : 0 ); }\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//#define cryptDestroyComponents( componentInfo ) \\\n\t//\tmemset( ( componentInfo ), 0, sizeof( *componentInfo ) )\n\t\n\t/* Macros to set a component of a public key */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//#define cryptSetComponent( destination, source, length ) \\\n\t//\t{ memcpy( ( destination ), ( source ), ( ( length ) + 7 ) >> 3 ); \\\n\t//\t  ( destination##Len ) = length; }\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tStatus Codes\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* No error in function call */\n\t\n\tpublic const int OK                                       = 0   ; // No error\n\t\n\t/* Error in parameters passed to function.  The parentheses are to catch \n\t   potential erroneous use in an expression */\n\t\n\tpublic const int ERROR_PARAM1                             = -1  ; // Bad argument, parameter 1\n\tpublic const int ERROR_PARAM2                             = -2  ; // Bad argument, parameter 2\n\tpublic const int ERROR_PARAM3                             = -3  ; // Bad argument, parameter 3\n\tpublic const int ERROR_PARAM4                             = -4  ; // Bad argument, parameter 4\n\tpublic const int ERROR_PARAM5                             = -5  ; // Bad argument, parameter 5\n\tpublic const int ERROR_PARAM6                             = -6  ; // Bad argument, parameter 6\n\tpublic const int ERROR_PARAM7                             = -7  ; // Bad argument, parameter 7\n\t\n\t/* Errors due to insufficient resources */\n\t\n\tpublic const int ERROR_MEMORY                             = -10 ; // Out of memory\n\tpublic const int ERROR_NOTINITED                          = -11 ; // Data has not been initialised\n\tpublic const int ERROR_INITED                             = -12 ; // Data has already been init'd\n\tpublic const int ERROR_NOSECURE                           = -13 ; // Opn.not avail.at requested sec.level\n\tpublic const int ERROR_RANDOM                             = -14 ; // No reliable random data available\n\tpublic const int ERROR_FAILED                             = -15 ; // Operation failed\n\tpublic const int ERROR_INTERNAL                           = -16 ; // Internal consistency check failed\n\t\n\t/* Security violations */\n\t\n\tpublic const int ERROR_NOTAVAIL                           = -20 ; // This type of opn.not available\n\tpublic const int ERROR_PERMISSION                         = -21 ; // No permiss.to perform this operation\n\tpublic const int ERROR_WRONGKEY                           = -22 ; // Incorrect key used to decrypt data\n\tpublic const int ERROR_INCOMPLETE                         = -23 ; // Operation incomplete/still in progress\n\tpublic const int ERROR_COMPLETE                           = -24 ; // Operation complete/can't continue\n\tpublic const int ERROR_TIMEOUT                            = -25 ; // Operation timed out before completion\n\tpublic const int ERROR_INVALID                            = -26 ; // Invalid/inconsistent information\n\tpublic const int ERROR_SIGNALLED                          = -27 ; // Resource destroyed by extnl.event\n\t\n\t/* High-level function errors */\n\t\n\tpublic const int ERROR_OVERFLOW                           = -30 ; // Resources/space exhausted\n\tpublic const int ERROR_UNDERFLOW                          = -31 ; // Not enough data available\n\tpublic const int ERROR_BADDATA                            = -32 ; // Bad/unrecognised data format\n\tpublic const int ERROR_SIGNATURE                          = -33 ; // Signature/integrity check failed\n\t\n\t/* Data access function errors */\n\t\n\tpublic const int ERROR_OPEN                               = -40 ; // Cannot open object\n\tpublic const int ERROR_READ                               = -41 ; // Cannot read item from object\n\tpublic const int ERROR_WRITE                              = -42 ; // Cannot write item to object\n\tpublic const int ERROR_NOTFOUND                           = -43 ; // Requested item not found in object\n\tpublic const int ERROR_DUPLICATE                          = -44 ; // Item already present in object\n\t\n\t/* Data enveloping errors */\n\t\n\tpublic const int ENVELOPE_RESOURCE                        = -50 ; // Need resource to proceed\n\t\n\t/* Macros to examine return values */\n\t\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//#define cryptStatusError( status )\t( ( status ) < CRYPT_OK )\n\t//CRYPTLIBCONVERTER - NOT SUPPORTED:\n\t//#define cryptStatusOK( status )\t\t( ( status ) == CRYPT_OK )\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\tGeneral Functions\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* The following is necessary to stop C++ name mangling */\n\t\n\t\n\t/* Initialise and shut down cryptlib */\n\t\n\tpublic static void Init()\n\t{\n\t\tprocessStatus(wrapped_Init());\n\t}\n\t\n\tpublic static void End()\n\t{\n\t\tprocessStatus(wrapped_End());\n\t}\n\t\n\t/* Query cryptlibs capabilities */\n\t\n\tpublic static CRYPT_QUERY_INFO QueryCapability(\n\t\t\t\t\t\t\t\tint cryptAlgo // CRYPT_ALGO_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptQueryInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_QUERY_INFO)));\n\t\tCRYPT_QUERY_INFO cryptQueryInfo = new CRYPT_QUERY_INFO();\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_QueryCapability(cryptAlgo, cryptQueryInfoPtr));\n\t\t\tMarshal.PtrToStructure(cryptQueryInfoPtr, cryptQueryInfo);\n\t\t\treturn cryptQueryInfo;\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptQueryInfoPtr);\n\t\t}\n\t}\n\t\n\t/* Create and destroy an encryption context */\n\t\n\tpublic static int CreateContext(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint cryptAlgo // CRYPT_ALGO_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptContextPtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateContext(cryptContextPtr, cryptUser, cryptAlgo));\n\t\t\treturn Marshal.ReadInt32(cryptContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptContextPtr);\n\t\t}\n\t}\n\t\n\tpublic static void DestroyContext(\n\t\t\t\t\t\t\t\tint cryptContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DestroyContext(cryptContext));\n\t}\n\t\n\t/* Generic \"destroy an object\" function */\n\t\n\tpublic static void DestroyObject(\n\t\t\t\t\t\t\t\tint cryptObject // CRYPT_HANDLE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DestroyObject(cryptObject));\n\t}\n\t\n\t/* Generate a key into a context */\n\t\n\tpublic static void GenerateKey(\n\t\t\t\t\t\t\t\tint cryptContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_GenerateKey(cryptContext));\n\t}\n\t\n\t/* Encrypt/decrypt/hash a block of memory */\n\t\n\tpublic static void Encrypt(\n\t\t\t\t\t\t\t\tint cryptContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tbyte[] buffer,\n\t\t\t\t\t\t\t\tint bufferOffset,\n\t\t\t\t\t\t\t\tint length\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle bufferHandle = new GCHandle();\n\t\tIntPtr bufferPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(buffer, bufferOffset, length);\n\t\t\tgetPointer(buffer, bufferOffset, ref bufferHandle, ref bufferPtr);\n\t\t\tprocessStatus(wrapped_Encrypt(cryptContext, bufferPtr, length));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(bufferHandle);\n\t\t}\n\t}\n\tpublic static void Encrypt(\n\t\t\t\t\t\t\tint cryptContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tbyte[] buffer\n\t\t\t\t\t\t\t) { Encrypt(cryptContext, buffer, 0, buffer == null ? 0 : buffer.Length); }\n\t\n\tpublic static void Decrypt(\n\t\t\t\t\t\t\t\tint cryptContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tbyte[] buffer,\n\t\t\t\t\t\t\t\tint bufferOffset,\n\t\t\t\t\t\t\t\tint length\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle bufferHandle = new GCHandle();\n\t\tIntPtr bufferPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(buffer, bufferOffset, length);\n\t\t\tgetPointer(buffer, bufferOffset, ref bufferHandle, ref bufferPtr);\n\t\t\tprocessStatus(wrapped_Decrypt(cryptContext, bufferPtr, length));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(bufferHandle);\n\t\t}\n\t}\n\tpublic static void Decrypt(\n\t\t\t\t\t\t\tint cryptContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tbyte[] buffer\n\t\t\t\t\t\t\t) { Decrypt(cryptContext, buffer, 0, buffer == null ? 0 : buffer.Length); }\n\t\n\t/* Get/set/delete attribute functions */\n\t\n\tpublic static void SetAttribute(\n\t\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\t\tint value\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_SetAttribute(cryptHandle, attributeType, value));\n\t}\n\t\n\tpublic static void SetAttributeString(\n\t\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\t\tbyte[] value,\n\t\t\t\t\t\t\t\tint valueOffset,\n\t\t\t\t\t\t\t\tint valueLength\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle valueHandle = new GCHandle();\n\t\tIntPtr valuePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(value, valueOffset, valueLength);\n\t\t\tgetPointer(value, valueOffset, ref valueHandle, ref valuePtr);\n\t\t\tprocessStatus(wrapped_SetAttributeString(cryptHandle, attributeType, valuePtr, valueLength));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(valueHandle);\n\t\t}\n\t}\n\tpublic static void SetAttributeString(\n\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\tbyte[] value\n\t\t\t\t\t\t\t) { SetAttributeString(cryptHandle, attributeType, value, 0, value == null ? 0 : value.Length); }\n\tpublic static void SetAttributeString(\n\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\tString value\n\t\t\t\t\t\t\t) { SetAttributeString(cryptHandle, attributeType, value == null ? null : new UTF8Encoding().GetBytes(value), 0, value == null ? 0 : new UTF8Encoding().GetByteCount(value)); }\n\t\n\tpublic static int GetAttribute(\n\t\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint attributeType // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr valuePtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_GetAttribute(cryptHandle, attributeType, valuePtr));\n\t\t\treturn Marshal.ReadInt32(valuePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(valuePtr);\n\t\t}\n\t}\n\t\n\tpublic static int GetAttributeString(\n\t\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\t\tbyte[] value,\n\t\t\t\t\t\t\t\tint valueOffset\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr valueLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle valueHandle = new GCHandle();\n\t\tIntPtr valuePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_GetAttributeString(cryptHandle, attributeType, valuePtr, valueLengthPtr));\n\t\t\tint valueLength = Marshal.ReadInt32(valueLengthPtr);\n\t\t\tcheckIndices(value, valueOffset, valueLength);\n\t\t\tgetPointer(value, valueOffset, ref valueHandle, ref valuePtr);\n\t\t\tprocessStatus(wrapped_GetAttributeString(cryptHandle, attributeType, valuePtr, valueLengthPtr));\n\t\t\treturn Marshal.ReadInt32(valueLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(valueLengthPtr);\n\t\t\treleasePointer(valueHandle);\n\t\t}\n\t}\n\tpublic static int GetAttributeString(\n\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint attributeType, // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\tbyte[] value\n\t\t\t\t\t\t\t) { return GetAttributeString(cryptHandle, attributeType, value, 0); }\n\tpublic static String GetAttributeString(\n\t                    int cryptHandle, // CRYPT_HANDLE\n\t                    int attributeType // CRYPT_ATTRIBUTE_TYPE\n\t                    )\n\t                    {\n\t                        int length = GetAttributeString(cryptHandle, attributeType, null);\n\t                        byte[] bytes = new byte[length];\n\t                        length = GetAttributeString(cryptHandle, attributeType, bytes);\n\t                        return new UTF8Encoding().GetString(bytes, 0, length);\n\t                    }\n\t\n\t\n\tpublic static void DeleteAttribute(\n\t\t\t\t\t\t\t\tint cryptHandle, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint attributeType // CRYPT_ATTRIBUTE_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DeleteAttribute(cryptHandle, attributeType));\n\t}\n\t\n\t/* Oddball functions: Add random data to the pool, query an encoded signature\n\t   or key data.  These are due to be replaced once a suitable alternative can\n\t   be found */\n\t\n\tpublic static void AddRandom(\n\t\t\t\t\t\t\t\tbyte[] randomData,\n\t\t\t\t\t\t\t\tint randomDataOffset,\n\t\t\t\t\t\t\t\tint randomDataLength\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle randomDataHandle = new GCHandle();\n\t\tIntPtr randomDataPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(randomData, randomDataOffset, randomDataLength);\n\t\t\tgetPointer(randomData, randomDataOffset, ref randomDataHandle, ref randomDataPtr);\n\t\t\tprocessStatus(wrapped_AddRandom(randomDataPtr, randomDataLength));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(randomDataHandle);\n\t\t}\n\t}\n\tpublic static void AddRandom(\n\t\t\t\t\t\t\tbyte[] randomData\n\t\t\t\t\t\t\t) { AddRandom(randomData, 0, randomData == null ? 0 : randomData.Length); }\n\tpublic static void AddRandom(\n\t\t\t\t\t\t\tString randomData\n\t\t\t\t\t\t\t) { AddRandom(randomData == null ? null : new UTF8Encoding().GetBytes(randomData), 0, randomData == null ? 0 : new UTF8Encoding().GetByteCount(randomData)); }\n\tpublic static void AddRandom(\n\t\t                    int pollType\n\t\t                    )\n\t{\n\t\tprocessStatus(wrapped_AddRandom(IntPtr.Zero, pollType));\n\t}\n\t\n\t\n\tpublic static CRYPT_OBJECT_INFO QueryObject(\n\t\t\t\t\t\t\t\tbyte[] objectData,\n\t\t\t\t\t\t\t\tint objectDataOffset,\n\t\t\t\t\t\t\t\tint objectDataLength\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptObjectInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_OBJECT_INFO)));\n\t\tCRYPT_OBJECT_INFO cryptObjectInfo = new CRYPT_OBJECT_INFO();\n\t\tGCHandle objectDataHandle = new GCHandle();\n\t\tIntPtr objectDataPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(objectData, objectDataOffset, objectDataLength);\n\t\t\tgetPointer(objectData, objectDataOffset, ref objectDataHandle, ref objectDataPtr);\n\t\t\tprocessStatus(wrapped_QueryObject(objectDataPtr, objectDataLength, cryptObjectInfoPtr));\n\t\t\tMarshal.PtrToStructure(cryptObjectInfoPtr, cryptObjectInfo);\n\t\t\treturn cryptObjectInfo;\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptObjectInfoPtr);\n\t\t\treleasePointer(objectDataHandle);\n\t\t}\n\t}\n\tpublic static CRYPT_OBJECT_INFO QueryObject(\n\t\t\t\t\t\t\tbyte[] objectData\n\t\t\t\t\t\t\t) { return QueryObject(objectData, 0, objectData == null ? 0 : objectData.Length); }\n\tpublic static CRYPT_OBJECT_INFO QueryObject(\n\t\t\t\t\t\t\tString objectData\n\t\t\t\t\t\t\t) { return QueryObject(objectData == null ? null : new UTF8Encoding().GetBytes(objectData), 0, objectData == null ? 0 : new UTF8Encoding().GetByteCount(objectData)); }\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\tMid-level Encryption Functions\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Export and import an encrypted session key */\n\t\n\tpublic static int ExportKey(\n\t\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\t\tint encryptedKeyOffset,\n\t\t\t\t\t\t\t\tint encryptedKeyMaxLength,\n\t\t\t\t\t\t\t\tint exportKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr encryptedKeyLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle encryptedKeyHandle = new GCHandle();\n\t\tIntPtr encryptedKeyPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_ExportKey(encryptedKeyPtr, encryptedKeyMaxLength, encryptedKeyLengthPtr, exportKey, sessionKeyContext));\n\t\t\tint encryptedKeyLength = Marshal.ReadInt32(encryptedKeyLengthPtr);\n\t\t\tcheckIndices(encryptedKey, encryptedKeyOffset, encryptedKeyLength);\n\t\t\tgetPointer(encryptedKey, encryptedKeyOffset, ref encryptedKeyHandle, ref encryptedKeyPtr);\n\t\t\tprocessStatus(wrapped_ExportKey(encryptedKeyPtr, encryptedKeyMaxLength, encryptedKeyLengthPtr, exportKey, sessionKeyContext));\n\t\t\treturn Marshal.ReadInt32(encryptedKeyLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(encryptedKeyLengthPtr);\n\t\t\treleasePointer(encryptedKeyHandle);\n\t\t}\n\t}\n\tpublic static int ExportKey(\n\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\tint encryptedKeyMaxLength,\n\t\t\t\t\t\t\tint exportKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return ExportKey(encryptedKey, 0, encryptedKeyMaxLength, exportKey, sessionKeyContext); }\n\t\n\tpublic static int ExportKeyEx(\n\t\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\t\tint encryptedKeyOffset,\n\t\t\t\t\t\t\t\tint encryptedKeyMaxLength,\n\t\t\t\t\t\t\t\tint formatType, // CRYPT_FORMAT_TYPE\n\t\t\t\t\t\t\t\tint exportKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr encryptedKeyLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle encryptedKeyHandle = new GCHandle();\n\t\tIntPtr encryptedKeyPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_ExportKeyEx(encryptedKeyPtr, encryptedKeyMaxLength, encryptedKeyLengthPtr, formatType, exportKey, sessionKeyContext));\n\t\t\tint encryptedKeyLength = Marshal.ReadInt32(encryptedKeyLengthPtr);\n\t\t\tcheckIndices(encryptedKey, encryptedKeyOffset, encryptedKeyLength);\n\t\t\tgetPointer(encryptedKey, encryptedKeyOffset, ref encryptedKeyHandle, ref encryptedKeyPtr);\n\t\t\tprocessStatus(wrapped_ExportKeyEx(encryptedKeyPtr, encryptedKeyMaxLength, encryptedKeyLengthPtr, formatType, exportKey, sessionKeyContext));\n\t\t\treturn Marshal.ReadInt32(encryptedKeyLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(encryptedKeyLengthPtr);\n\t\t\treleasePointer(encryptedKeyHandle);\n\t\t}\n\t}\n\tpublic static int ExportKeyEx(\n\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\tint encryptedKeyMaxLength,\n\t\t\t\t\t\t\tint formatType, // CRYPT_FORMAT_TYPE\n\t\t\t\t\t\t\tint exportKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return ExportKeyEx(encryptedKey, 0, encryptedKeyMaxLength, formatType, exportKey, sessionKeyContext); }\n\t\n\tpublic static void ImportKey(\n\t\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\t\tint encryptedKeyOffset,\n\t\t\t\t\t\t\t\tint encryptedKeyLength,\n\t\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle encryptedKeyHandle = new GCHandle();\n\t\tIntPtr encryptedKeyPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(encryptedKey, encryptedKeyOffset, encryptedKeyLength);\n\t\t\tgetPointer(encryptedKey, encryptedKeyOffset, ref encryptedKeyHandle, ref encryptedKeyPtr);\n\t\t\tprocessStatus(wrapped_ImportKey(encryptedKeyPtr, encryptedKeyLength, importKey, sessionKeyContext));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(encryptedKeyHandle);\n\t\t}\n\t}\n\tpublic static void ImportKey(\n\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { ImportKey(encryptedKey, 0, encryptedKey == null ? 0 : encryptedKey.Length, importKey, sessionKeyContext); }\n\tpublic static void ImportKey(\n\t\t\t\t\t\t\tString encryptedKey,\n\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { ImportKey(encryptedKey == null ? null : new UTF8Encoding().GetBytes(encryptedKey), 0, encryptedKey == null ? 0 : new UTF8Encoding().GetByteCount(encryptedKey), importKey, sessionKeyContext); }\n\t\n\tpublic static int ImportKeyEx(\n\t\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\t\tint encryptedKeyOffset,\n\t\t\t\t\t\t\t\tint encryptedKeyLength,\n\t\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr returnedContextPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle encryptedKeyHandle = new GCHandle();\n\t\tIntPtr encryptedKeyPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(encryptedKey, encryptedKeyOffset, encryptedKeyLength);\n\t\t\tgetPointer(encryptedKey, encryptedKeyOffset, ref encryptedKeyHandle, ref encryptedKeyPtr);\n\t\t\tprocessStatus(wrapped_ImportKeyEx(encryptedKeyPtr, encryptedKeyLength, importKey, sessionKeyContext, returnedContextPtr));\n\t\t\treturn Marshal.ReadInt32(returnedContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(returnedContextPtr);\n\t\t\treleasePointer(encryptedKeyHandle);\n\t\t}\n\t}\n\tpublic static int ImportKeyEx(\n\t\t\t\t\t\t\tbyte[] encryptedKey,\n\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return ImportKeyEx(encryptedKey, 0, encryptedKey == null ? 0 : encryptedKey.Length, importKey, sessionKeyContext); }\n\tpublic static int ImportKeyEx(\n\t\t\t\t\t\t\tString encryptedKey,\n\t\t\t\t\t\t\tint importKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint sessionKeyContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return ImportKeyEx(encryptedKey == null ? null : new UTF8Encoding().GetBytes(encryptedKey), 0, encryptedKey == null ? 0 : new UTF8Encoding().GetByteCount(encryptedKey), importKey, sessionKeyContext); }\n\t\n\t/* Create and check a digital signature */\n\t\n\tpublic static int CreateSignature(\n\t\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\t\tint signatureOffset,\n\t\t\t\t\t\t\t\tint signatureMaxLength,\n\t\t\t\t\t\t\t\tint signContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr signatureLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle signatureHandle = new GCHandle();\n\t\tIntPtr signaturePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateSignature(signaturePtr, signatureMaxLength, signatureLengthPtr, signContext, hashContext));\n\t\t\tint signatureLength = Marshal.ReadInt32(signatureLengthPtr);\n\t\t\tcheckIndices(signature, signatureOffset, signatureLength);\n\t\t\tgetPointer(signature, signatureOffset, ref signatureHandle, ref signaturePtr);\n\t\t\tprocessStatus(wrapped_CreateSignature(signaturePtr, signatureMaxLength, signatureLengthPtr, signContext, hashContext));\n\t\t\treturn Marshal.ReadInt32(signatureLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(signatureLengthPtr);\n\t\t\treleasePointer(signatureHandle);\n\t\t}\n\t}\n\tpublic static int CreateSignature(\n\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\tint signatureMaxLength,\n\t\t\t\t\t\t\tint signContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return CreateSignature(signature, 0, signatureMaxLength, signContext, hashContext); }\n\t\n\tpublic static int CreateSignatureEx(\n\t\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\t\tint signatureOffset,\n\t\t\t\t\t\t\t\tint signatureMaxLength,\n\t\t\t\t\t\t\t\tint formatType, // CRYPT_FORMAT_TYPE\n\t\t\t\t\t\t\t\tint signContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint hashContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint extraData // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr signatureLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle signatureHandle = new GCHandle();\n\t\tIntPtr signaturePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateSignatureEx(signaturePtr, signatureMaxLength, signatureLengthPtr, formatType, signContext, hashContext, extraData));\n\t\t\tint signatureLength = Marshal.ReadInt32(signatureLengthPtr);\n\t\t\tcheckIndices(signature, signatureOffset, signatureLength);\n\t\t\tgetPointer(signature, signatureOffset, ref signatureHandle, ref signaturePtr);\n\t\t\tprocessStatus(wrapped_CreateSignatureEx(signaturePtr, signatureMaxLength, signatureLengthPtr, formatType, signContext, hashContext, extraData));\n\t\t\treturn Marshal.ReadInt32(signatureLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(signatureLengthPtr);\n\t\t\treleasePointer(signatureHandle);\n\t\t}\n\t}\n\tpublic static int CreateSignatureEx(\n\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\tint signatureMaxLength,\n\t\t\t\t\t\t\tint formatType, // CRYPT_FORMAT_TYPE\n\t\t\t\t\t\t\tint signContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint hashContext, // CRYPT_CONTEXT\n\t\t\t\t\t\t\tint extraData // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t) { return CreateSignatureEx(signature, 0, signatureMaxLength, formatType, signContext, hashContext, extraData); }\n\t\n\tpublic static void CheckSignature(\n\t\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\t\tint signatureOffset,\n\t\t\t\t\t\t\t\tint signatureLength,\n\t\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle signatureHandle = new GCHandle();\n\t\tIntPtr signaturePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(signature, signatureOffset, signatureLength);\n\t\t\tgetPointer(signature, signatureOffset, ref signatureHandle, ref signaturePtr);\n\t\t\tprocessStatus(wrapped_CheckSignature(signaturePtr, signatureLength, sigCheckKey, hashContext));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(signatureHandle);\n\t\t}\n\t}\n\tpublic static void CheckSignature(\n\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { CheckSignature(signature, 0, signature == null ? 0 : signature.Length, sigCheckKey, hashContext); }\n\tpublic static void CheckSignature(\n\t\t\t\t\t\t\tString signature,\n\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { CheckSignature(signature == null ? null : new UTF8Encoding().GetBytes(signature), 0, signature == null ? 0 : new UTF8Encoding().GetByteCount(signature), sigCheckKey, hashContext); }\n\t\n\tpublic static int CheckSignatureEx(\n\t\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\t\tint signatureOffset,\n\t\t\t\t\t\t\t\tint signatureLength,\n\t\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr extraDataPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle signatureHandle = new GCHandle();\n\t\tIntPtr signaturePtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(signature, signatureOffset, signatureLength);\n\t\t\tgetPointer(signature, signatureOffset, ref signatureHandle, ref signaturePtr);\n\t\t\tprocessStatus(wrapped_CheckSignatureEx(signaturePtr, signatureLength, sigCheckKey, hashContext, extraDataPtr));\n\t\t\treturn Marshal.ReadInt32(extraDataPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(extraDataPtr);\n\t\t\treleasePointer(signatureHandle);\n\t\t}\n\t}\n\tpublic static int CheckSignatureEx(\n\t\t\t\t\t\t\tbyte[] signature,\n\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return CheckSignatureEx(signature, 0, signature == null ? 0 : signature.Length, sigCheckKey, hashContext); }\n\tpublic static int CheckSignatureEx(\n\t\t\t\t\t\t\tString signature,\n\t\t\t\t\t\t\tint sigCheckKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\tint hashContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t) { return CheckSignatureEx(signature == null ? null : new UTF8Encoding().GetBytes(signature), 0, signature == null ? 0 : new UTF8Encoding().GetByteCount(signature), sigCheckKey, hashContext); }\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\tKeyset Functions\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Open and close a keyset */\n\t\n\tpublic static int KeysetOpen(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint keysetType, // CRYPT_KEYSET_TYPE\n\t\t\t\t\t\t\t\tString name,\n\t\t\t\t\t\t\t\tint options // CRYPT_KEYOPT_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr keysetPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle nameHandle = new GCHandle();\n\t\tIntPtr namePtr = IntPtr.Zero;\n\t\tbyte[] nameArray = new UTF8Encoding().GetBytes(name);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(nameArray, 0, ref nameHandle, ref namePtr);\n\t\t\tprocessStatus(wrapped_KeysetOpen(keysetPtr, cryptUser, keysetType, namePtr, options));\n\t\t\treturn Marshal.ReadInt32(keysetPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(keysetPtr);\n\t\t\treleasePointer(nameHandle);\n\t\t}\n\t}\n\t\n\tpublic static void KeysetClose(\n\t\t\t\t\t\t\t\tint keyset // CRYPT_KEYSET\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_KeysetClose(keyset));\n\t}\n\t\n\t/* Get a key from a keyset or device */\n\t\n\tpublic static int GetPublicKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptContextPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tprocessStatus(wrapped_GetPublicKey(keyset, cryptContextPtr, keyIDtype, keyIDPtr));\n\t\t\treturn Marshal.ReadInt32(cryptContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptContextPtr);\n\t\t\treleasePointer(keyIDHandle);\n\t\t}\n\t}\n\t\n\tpublic static int GetPrivateKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID,\n\t\t\t\t\t\t\t\tString password\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptContextPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\tGCHandle passwordHandle = new GCHandle();\n\t\tIntPtr passwordPtr = IntPtr.Zero;\n\t\tbyte[] passwordArray = new UTF8Encoding().GetBytes(password);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tgetPointer(passwordArray, 0, ref passwordHandle, ref passwordPtr);\n\t\t\tprocessStatus(wrapped_GetPrivateKey(keyset, cryptContextPtr, keyIDtype, keyIDPtr, passwordPtr));\n\t\t\treturn Marshal.ReadInt32(cryptContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptContextPtr);\n\t\t\treleasePointer(keyIDHandle);\n\t\t\treleasePointer(passwordHandle);\n\t\t}\n\t}\n\t\n\tpublic static int GetKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID,\n\t\t\t\t\t\t\t\tString password\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptContextPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\tGCHandle passwordHandle = new GCHandle();\n\t\tIntPtr passwordPtr = IntPtr.Zero;\n\t\tbyte[] passwordArray = new UTF8Encoding().GetBytes(password);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tgetPointer(passwordArray, 0, ref passwordHandle, ref passwordPtr);\n\t\t\tprocessStatus(wrapped_GetKey(keyset, cryptContextPtr, keyIDtype, keyIDPtr, passwordPtr));\n\t\t\treturn Marshal.ReadInt32(cryptContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptContextPtr);\n\t\t\treleasePointer(keyIDHandle);\n\t\t\treleasePointer(passwordHandle);\n\t\t}\n\t}\n\t\n\t/* Add/delete a key to/from a keyset or device */\n\t\n\tpublic static void AddPublicKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint certificate // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_AddPublicKey(keyset, certificate));\n\t}\n\t\n\tpublic static void AddPrivateKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint cryptKey, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tString password\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle passwordHandle = new GCHandle();\n\t\tIntPtr passwordPtr = IntPtr.Zero;\n\t\tbyte[] passwordArray = new UTF8Encoding().GetBytes(password);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(passwordArray, 0, ref passwordHandle, ref passwordPtr);\n\t\t\tprocessStatus(wrapped_AddPrivateKey(keyset, cryptKey, passwordPtr));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(passwordHandle);\n\t\t}\n\t}\n\t\n\tpublic static void DeleteKey(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tprocessStatus(wrapped_DeleteKey(keyset, keyIDtype, keyIDPtr));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(keyIDHandle);\n\t\t}\n\t}\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tCertificate Functions\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Create/destroy a certificate */\n\t\n\tpublic static int CreateCert(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint certType // CRYPT_CERTTYPE_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr certificatePtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateCert(certificatePtr, cryptUser, certType));\n\t\t\treturn Marshal.ReadInt32(certificatePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(certificatePtr);\n\t\t}\n\t}\n\t\n\tpublic static void DestroyCert(\n\t\t\t\t\t\t\t\tint certificate // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DestroyCert(certificate));\n\t}\n\t\n\t/* Get/add/delete certificate extensions.  These are direct data insertion\n\t   functions whose use is discouraged, so they fix the string at char *\n\t   rather than C_STR */\n\t\n\tpublic static int GetCertExtension(\n\t\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\tString oid,\n\t\t\t\t\t\t\t\tbyte[] extension,\n\t\t\t\t\t\t\t\tint extensionOffset,\n\t\t\t\t\t\t\t\tint extensionMaxLength\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr extensionLengthPtr = Marshal.AllocHGlobal(4);\n\t\tIntPtr criticalFlagPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle oidHandle = new GCHandle();\n\t\tIntPtr oidPtr = IntPtr.Zero;\n\t\tbyte[] oidArray = new UTF8Encoding().GetBytes(oid);\n\t\tGCHandle extensionHandle = new GCHandle();\n\t\tIntPtr extensionPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tgetPointer(oidArray, 0, ref oidHandle, ref oidPtr);\n\t\t\tprocessStatus(wrapped_GetCertExtension(certificate, oidPtr, criticalFlagPtr, extensionPtr, extensionMaxLength, extensionLengthPtr));\n\t\t\tint extensionLength = Marshal.ReadInt32(extensionLengthPtr);\n\t\t\tcheckIndices(extension, extensionOffset, extensionLength);\n\t\t\tgetPointer(extension, extensionOffset, ref extensionHandle, ref extensionPtr);\n\t\t\tprocessStatus(wrapped_GetCertExtension(certificate, oidPtr, criticalFlagPtr, extensionPtr, extensionMaxLength, extensionLengthPtr));\n\t\t\treturn Marshal.ReadInt32(extensionLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(extensionLengthPtr);\n\t\t\treleasePointer(extensionHandle);\n\t\t\treleasePointer(oidHandle);\n\t\t}\n\t}\n\tpublic static int GetCertExtension(\n\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\tString oid,\n\t\t\t\t\t\t\tbyte[] extension,\n\t\t\t\t\t\t\tint extensionMaxLength\n\t\t\t\t\t\t\t) { return GetCertExtension(certificate, oid, extension, 0, extensionMaxLength); }\n\t\n\tpublic static void AddCertExtension(\n\t\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\tString oid,\n\t\t\t\t\t\t\t\tint criticalFlag,\n\t\t\t\t\t\t\t\tbyte[] extension,\n\t\t\t\t\t\t\t\tint extensionOffset,\n\t\t\t\t\t\t\t\tint extensionLength\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle oidHandle = new GCHandle();\n\t\tIntPtr oidPtr = IntPtr.Zero;\n\t\tbyte[] oidArray = new UTF8Encoding().GetBytes(oid);\n\t\tGCHandle extensionHandle = new GCHandle();\n\t\tIntPtr extensionPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tgetPointer(oidArray, 0, ref oidHandle, ref oidPtr);\n\t\t\tcheckIndices(extension, extensionOffset, extensionLength);\n\t\t\tgetPointer(extension, extensionOffset, ref extensionHandle, ref extensionPtr);\n\t\t\tprocessStatus(wrapped_AddCertExtension(certificate, oidPtr, criticalFlag, extensionPtr, extensionLength));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(extensionHandle);\n\t\t\treleasePointer(oidHandle);\n\t\t}\n\t}\n\tpublic static void AddCertExtension(\n\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\tString oid,\n\t\t\t\t\t\t\tint criticalFlag,\n\t\t\t\t\t\t\tbyte[] extension\n\t\t\t\t\t\t\t) { AddCertExtension(certificate, oid, criticalFlag, extension, 0, extension == null ? 0 : extension.Length); }\n\tpublic static void AddCertExtension(\n\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\tString oid,\n\t\t\t\t\t\t\tint criticalFlag,\n\t\t\t\t\t\t\tString extension\n\t\t\t\t\t\t\t) { AddCertExtension(certificate, oid, criticalFlag, extension == null ? null : new UTF8Encoding().GetBytes(extension), 0, extension == null ? 0 : new UTF8Encoding().GetByteCount(extension)); }\n\t\n\tpublic static void DeleteCertExtension(\n\t\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\tString oid\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle oidHandle = new GCHandle();\n\t\tIntPtr oidPtr = IntPtr.Zero;\n\t\tbyte[] oidArray = new UTF8Encoding().GetBytes(oid);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(oidArray, 0, ref oidHandle, ref oidPtr);\n\t\t\tprocessStatus(wrapped_DeleteCertExtension(certificate, oidPtr));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(oidHandle);\n\t\t}\n\t}\n\t\n\t/* Sign/sig.check a certificate/certification request */\n\t\n\tpublic static void SignCert(\n\t\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\tint signContext // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_SignCert(certificate, signContext));\n\t}\n\t\n\tpublic static void CheckCert(\n\t\t\t\t\t\t\t\tint certificate, // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\tint sigCheckKey // CRYPT_HANDLE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_CheckCert(certificate, sigCheckKey));\n\t}\n\t\n\t/* Import/export a certificate/certification request */\n\t\n\tpublic static int ImportCert(\n\t\t\t\t\t\t\t\tbyte[] certObject,\n\t\t\t\t\t\t\t\tint certObjectOffset,\n\t\t\t\t\t\t\t\tint certObjectLength,\n\t\t\t\t\t\t\t\tint cryptUser // CRYPT_USER\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr certificatePtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle certObjectHandle = new GCHandle();\n\t\tIntPtr certObjectPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tcheckIndices(certObject, certObjectOffset, certObjectLength);\n\t\t\tgetPointer(certObject, certObjectOffset, ref certObjectHandle, ref certObjectPtr);\n\t\t\tprocessStatus(wrapped_ImportCert(certObjectPtr, certObjectLength, cryptUser, certificatePtr));\n\t\t\treturn Marshal.ReadInt32(certificatePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(certificatePtr);\n\t\t\treleasePointer(certObjectHandle);\n\t\t}\n\t}\n\tpublic static int ImportCert(\n\t\t\t\t\t\t\tbyte[] certObject,\n\t\t\t\t\t\t\tint cryptUser // CRYPT_USER\n\t\t\t\t\t\t\t) { return ImportCert(certObject, 0, certObject == null ? 0 : certObject.Length, cryptUser); }\n\tpublic static int ImportCert(\n\t\t\t\t\t\t\tString certObject,\n\t\t\t\t\t\t\tint cryptUser // CRYPT_USER\n\t\t\t\t\t\t\t) { return ImportCert(certObject == null ? null : new UTF8Encoding().GetBytes(certObject), 0, certObject == null ? 0 : new UTF8Encoding().GetByteCount(certObject), cryptUser); }\n\t\n\tpublic static int ExportCert(\n\t\t\t\t\t\t\t\tbyte[] certObject,\n\t\t\t\t\t\t\t\tint certObjectOffset,\n\t\t\t\t\t\t\t\tint certObjectMaxLength,\n\t\t\t\t\t\t\t\tint certFormatType, // CRYPT_CERTFORMAT_TYPE\n\t\t\t\t\t\t\t\tint certificate // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr certObjectLengthPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle certObjectHandle = new GCHandle();\n\t\tIntPtr certObjectPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_ExportCert(certObjectPtr, certObjectMaxLength, certObjectLengthPtr, certFormatType, certificate));\n\t\t\tint certObjectLength = Marshal.ReadInt32(certObjectLengthPtr);\n\t\t\tcheckIndices(certObject, certObjectOffset, certObjectLength);\n\t\t\tgetPointer(certObject, certObjectOffset, ref certObjectHandle, ref certObjectPtr);\n\t\t\tprocessStatus(wrapped_ExportCert(certObjectPtr, certObjectMaxLength, certObjectLengthPtr, certFormatType, certificate));\n\t\t\treturn Marshal.ReadInt32(certObjectLengthPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(certObjectLengthPtr);\n\t\t\treleasePointer(certObjectHandle);\n\t\t}\n\t}\n\tpublic static int ExportCert(\n\t\t\t\t\t\t\tbyte[] certObject,\n\t\t\t\t\t\t\tint certObjectMaxLength,\n\t\t\t\t\t\t\tint certFormatType, // CRYPT_CERTFORMAT_TYPE\n\t\t\t\t\t\t\tint certificate // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t) { return ExportCert(certObject, 0, certObjectMaxLength, certFormatType, certificate); }\n\t\n\t/* CA management functions */\n\t\n\tpublic static void CAAddItem(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint certificate // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_CAAddItem(keyset, certificate));\n\t}\n\t\n\tpublic static int CAGetItem(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint certType, // CRYPT_CERTTYPE_TYPE\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr certificatePtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tprocessStatus(wrapped_CAGetItem(keyset, certificatePtr, certType, keyIDtype, keyIDPtr));\n\t\t\treturn Marshal.ReadInt32(certificatePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(certificatePtr);\n\t\t\treleasePointer(keyIDHandle);\n\t\t}\n\t}\n\t\n\tpublic static void CADeleteItem(\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint certType, // CRYPT_CERTTYPE_TYPE\n\t\t\t\t\t\t\t\tint keyIDtype, // CRYPT_KEYID_TYPE\n\t\t\t\t\t\t\t\tString keyID\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tGCHandle keyIDHandle = new GCHandle();\n\t\tIntPtr keyIDPtr = IntPtr.Zero;\n\t\tbyte[] keyIDArray = new UTF8Encoding().GetBytes(keyID);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(keyIDArray, 0, ref keyIDHandle, ref keyIDPtr);\n\t\t\tprocessStatus(wrapped_CADeleteItem(keyset, certType, keyIDtype, keyIDPtr));\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\treleasePointer(keyIDHandle);\n\t\t}\n\t}\n\t\n\tpublic static int CACertManagement(\n\t\t\t\t\t\t\t\tint action, // CRYPT_CERTACTION_TYPE\n\t\t\t\t\t\t\t\tint keyset, // CRYPT_KEYSET\n\t\t\t\t\t\t\t\tint caKey, // CRYPT_CONTEXT\n\t\t\t\t\t\t\t\tint certRequest // CRYPT_CERTIFICATE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr certificatePtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CACertManagement(certificatePtr, action, keyset, caKey, certRequest));\n\t\t\treturn Marshal.ReadInt32(certificatePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(certificatePtr);\n\t\t}\n\t}\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\tEnvelope and Session Functions\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Create/destroy an envelope */\n\t\n\tpublic static int CreateEnvelope(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint formatType // CRYPT_FORMAT_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr envelopePtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateEnvelope(envelopePtr, cryptUser, formatType));\n\t\t\treturn Marshal.ReadInt32(envelopePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(envelopePtr);\n\t\t}\n\t}\n\t\n\tpublic static void DestroyEnvelope(\n\t\t\t\t\t\t\t\tint envelope // CRYPT_ENVELOPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DestroyEnvelope(envelope));\n\t}\n\t\n\t/* Create/destroy a session */\n\t\n\tpublic static int CreateSession(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint formatType // CRYPT_SESSION_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr sessionPtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_CreateSession(sessionPtr, cryptUser, formatType));\n\t\t\treturn Marshal.ReadInt32(sessionPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(sessionPtr);\n\t\t}\n\t}\n\t\n\tpublic static void DestroySession(\n\t\t\t\t\t\t\t\tint session // CRYPT_SESSION\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DestroySession(session));\n\t}\n\t\n\t/* Add/remove data to/from and envelope or session */\n\t\n\tpublic static int PushData(\n\t\t\t\t\t\t\t\tint envelope, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tbyte[] buffer,\n\t\t\t\t\t\t\t\tint bufferOffset,\n\t\t\t\t\t\t\t\tint length\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr bytesCopiedPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle bufferHandle = new GCHandle();\n\t\tIntPtr bufferPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tint bytesCopied = 0;\n\t\t\tint status;\n\t\t\tcheckIndices(buffer, bufferOffset, length);\n\t\t\tgetPointer(buffer, bufferOffset, ref bufferHandle, ref bufferPtr);\n\t\t\tstatus = wrapped_PushData(envelope, bufferPtr, length, bytesCopiedPtr);\n\t\t\tbytesCopied = Marshal.ReadInt32(bytesCopiedPtr);\n\t\t\tprocessStatus(status, bytesCopied);\n\t\t\treturn bytesCopied;\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(bytesCopiedPtr);\n\t\t\treleasePointer(bufferHandle);\n\t\t}\n\t}\n\tpublic static int PushData(\n\t\t\t\t\t\t\tint envelope, // CRYPT_HANDLE\n\t\t\t\t\t\t\tbyte[] buffer\n\t\t\t\t\t\t\t) { return PushData(envelope, buffer, 0, buffer == null ? 0 : buffer.Length); }\n\tpublic static int PushData(\n\t\t\t\t\t\t\tint envelope, // CRYPT_HANDLE\n\t\t\t\t\t\t\tString buffer\n\t\t\t\t\t\t\t) { return PushData(envelope, buffer == null ? null : new UTF8Encoding().GetBytes(buffer), 0, buffer == null ? 0 : new UTF8Encoding().GetByteCount(buffer)); }\n\t\n\tpublic static void FlushData(\n\t\t\t\t\t\t\t\tint envelope // CRYPT_HANDLE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_FlushData(envelope));\n\t}\n\t\n\tpublic static int PopData(\n\t\t\t\t\t\t\t\tint envelope, // CRYPT_HANDLE\n\t\t\t\t\t\t\t\tbyte[] buffer,\n\t\t\t\t\t\t\t\tint bufferOffset,\n\t\t\t\t\t\t\t\tint length\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr bytesCopiedPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle bufferHandle = new GCHandle();\n\t\tIntPtr bufferPtr = IntPtr.Zero;\n\t\ttry\n\t\t{\n\t\t\tint bytesCopied = 0;\n\t\t\tint status;\n\t\t\tcheckIndices(buffer, bufferOffset, bytesCopied);\n\t\t\tgetPointer(buffer, bufferOffset, ref bufferHandle, ref bufferPtr);\n\t\t\tstatus = wrapped_PopData(envelope, bufferPtr, length, bytesCopiedPtr);\n\t\t\tbytesCopied = Marshal.ReadInt32(bytesCopiedPtr);\n\t\t\tprocessStatus(status, bytesCopied);\n\t\t\treturn bytesCopied;\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(bytesCopiedPtr);\n\t\t\treleasePointer(bufferHandle);\n\t\t}\n\t}\n\tpublic static int PopData(\n\t\t\t\t\t\t\tint envelope, // CRYPT_HANDLE\n\t\t\t\t\t\t\tbyte[] buffer,\n\t\t\t\t\t\t\tint length\n\t\t\t\t\t\t\t) { return PopData(envelope, buffer, 0, length); }\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tDevice Functions\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Open and close a device */\n\t\n\tpublic static int DeviceOpen(\n\t\t\t\t\t\t\t\tint cryptUser, // CRYPT_USER\n\t\t\t\t\t\t\t\tint deviceType, // CRYPT_DEVICE_TYPE\n\t\t\t\t\t\t\t\tString name\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr devicePtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle nameHandle = new GCHandle();\n\t\tIntPtr namePtr = IntPtr.Zero;\n\t\tbyte[] nameArray = new UTF8Encoding().GetBytes(name);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(nameArray, 0, ref nameHandle, ref namePtr);\n\t\t\tprocessStatus(wrapped_DeviceOpen(devicePtr, cryptUser, deviceType, namePtr));\n\t\t\treturn Marshal.ReadInt32(devicePtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(devicePtr);\n\t\t\treleasePointer(nameHandle);\n\t\t}\n\t}\n\t\n\tpublic static void DeviceClose(\n\t\t\t\t\t\t\t\tint device // CRYPT_DEVICE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_DeviceClose(device));\n\t}\n\t\n\t/* Query a devices capabilities */\n\t\n\tpublic static CRYPT_QUERY_INFO DeviceQueryCapability(\n\t\t\t\t\t\t\t\tint device, // CRYPT_DEVICE\n\t\t\t\t\t\t\t\tint cryptAlgo // CRYPT_ALGO_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptQueryInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_QUERY_INFO)));\n\t\tCRYPT_QUERY_INFO cryptQueryInfo = new CRYPT_QUERY_INFO();\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_DeviceQueryCapability(device, cryptAlgo, cryptQueryInfoPtr));\n\t\t\tMarshal.PtrToStructure(cryptQueryInfoPtr, cryptQueryInfo);\n\t\t\treturn cryptQueryInfo;\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptQueryInfoPtr);\n\t\t}\n\t}\n\t\n\t/* Create an encryption context via the device */\n\t\n\tpublic static int DeviceCreateContext(\n\t\t\t\t\t\t\t\tint device, // CRYPT_DEVICE\n\t\t\t\t\t\t\t\tint cryptAlgo // CRYPT_ALGO_TYPE\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr cryptContextPtr = Marshal.AllocHGlobal(4);\n\t\ttry\n\t\t{\n\t\t\tprocessStatus(wrapped_DeviceCreateContext(device, cryptContextPtr, cryptAlgo));\n\t\t\treturn Marshal.ReadInt32(cryptContextPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(cryptContextPtr);\n\t\t}\n\t}\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\tUser Management Functions\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t/* Log on and off (create/destroy a user object) */\n\t\n\tpublic static int Login(\n\t\t\t\t\t\t\t\tString name,\n\t\t\t\t\t\t\t\tString password\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tIntPtr userPtr = Marshal.AllocHGlobal(4);\n\t\tGCHandle nameHandle = new GCHandle();\n\t\tIntPtr namePtr = IntPtr.Zero;\n\t\tbyte[] nameArray = new UTF8Encoding().GetBytes(name);\n\t\tGCHandle passwordHandle = new GCHandle();\n\t\tIntPtr passwordPtr = IntPtr.Zero;\n\t\tbyte[] passwordArray = new UTF8Encoding().GetBytes(password);\n\t\ttry\n\t\t{\n\t\t\tgetPointer(nameArray, 0, ref nameHandle, ref namePtr);\n\t\t\tgetPointer(passwordArray, 0, ref passwordHandle, ref passwordPtr);\n\t\t\tprocessStatus(wrapped_Login(userPtr, namePtr, passwordPtr));\n\t\t\treturn Marshal.ReadInt32(userPtr);\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\tMarshal.FreeHGlobal(userPtr);\n\t\t\treleasePointer(nameHandle);\n\t\t\treleasePointer(passwordHandle);\n\t\t}\n\t}\n\t\n\tpublic static void Logout(\n\t\t\t\t\t\t\t\tint user // CRYPT_USER\n\t\t\t\t\t\t\t\t)\n\t{\n\t\tprocessStatus(wrapped_Logout(user));\n\t}\n\t\n\t/****************************************************************************\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\tDirect API Functions\t\t\t\t\t\t*\n\t*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\t****************************************************************************/\n\t\n\t\n\t\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptInit\")]\n\tprivate static extern int wrapped_Init();\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptEnd\")]\n\tprivate static extern int wrapped_End();\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptQueryCapability\")]\n\tprivate static extern int wrapped_QueryCapability(int cryptAlgo, IntPtr cryptQueryInfo);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateContext\")]\n\tprivate static extern int wrapped_CreateContext(IntPtr cryptContext, int cryptUser, int cryptAlgo);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDestroyContext\")]\n\tprivate static extern int wrapped_DestroyContext(int cryptContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDestroyObject\")]\n\tprivate static extern int wrapped_DestroyObject(int cryptObject);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGenerateKey\")]\n\tprivate static extern int wrapped_GenerateKey(int cryptContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptEncrypt\")]\n\tprivate static extern int wrapped_Encrypt(int cryptContext, IntPtr buffer, int length);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDecrypt\")]\n\tprivate static extern int wrapped_Decrypt(int cryptContext, IntPtr buffer, int length);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptSetAttribute\")]\n\tprivate static extern int wrapped_SetAttribute(int cryptHandle, int attributeType, int value);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptSetAttributeString\")]\n\tprivate static extern int wrapped_SetAttributeString(int cryptHandle, int attributeType, IntPtr value, int valueLength);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetAttribute\")]\n\tprivate static extern int wrapped_GetAttribute(int cryptHandle, int attributeType, IntPtr value);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetAttributeString\")]\n\tprivate static extern int wrapped_GetAttributeString(int cryptHandle, int attributeType, IntPtr value, IntPtr valueLength);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeleteAttribute\")]\n\tprivate static extern int wrapped_DeleteAttribute(int cryptHandle, int attributeType);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptAddRandom\")]\n\tprivate static extern int wrapped_AddRandom(IntPtr randomData, int randomDataLength);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptQueryObject\")]\n\tprivate static extern int wrapped_QueryObject(IntPtr objectData, int objectDataLength, IntPtr cryptObjectInfo);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptExportKey\")]\n\tprivate static extern int wrapped_ExportKey(IntPtr encryptedKey, int encryptedKeyMaxLength, IntPtr encryptedKeyLength, int exportKey, int sessionKeyContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptExportKeyEx\")]\n\tprivate static extern int wrapped_ExportKeyEx(IntPtr encryptedKey, int encryptedKeyMaxLength, IntPtr encryptedKeyLength, int formatType, int exportKey, int sessionKeyContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptImportKey\")]\n\tprivate static extern int wrapped_ImportKey(IntPtr encryptedKey, int encryptedKeyLength, int importKey, int sessionKeyContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptImportKeyEx\")]\n\tprivate static extern int wrapped_ImportKeyEx(IntPtr encryptedKey, int encryptedKeyLength, int importKey, int sessionKeyContext, IntPtr returnedContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateSignature\")]\n\tprivate static extern int wrapped_CreateSignature(IntPtr signature, int signatureMaxLength, IntPtr signatureLength, int signContext, int hashContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateSignatureEx\")]\n\tprivate static extern int wrapped_CreateSignatureEx(IntPtr signature, int signatureMaxLength, IntPtr signatureLength, int formatType, int signContext, int hashContext, int extraData);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCheckSignature\")]\n\tprivate static extern int wrapped_CheckSignature(IntPtr signature, int signatureLength, int sigCheckKey, int hashContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCheckSignatureEx\")]\n\tprivate static extern int wrapped_CheckSignatureEx(IntPtr signature, int signatureLength, int sigCheckKey, int hashContext, IntPtr extraData);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptKeysetOpen\")]\n\tprivate static extern int wrapped_KeysetOpen(IntPtr keyset, int cryptUser, int keysetType, IntPtr name, int options);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptKeysetClose\")]\n\tprivate static extern int wrapped_KeysetClose(int keyset);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetPublicKey\")]\n\tprivate static extern int wrapped_GetPublicKey(int keyset, IntPtr cryptContext, int keyIDtype, IntPtr keyID);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetPrivateKey\")]\n\tprivate static extern int wrapped_GetPrivateKey(int keyset, IntPtr cryptContext, int keyIDtype, IntPtr keyID, IntPtr password);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetKey\")]\n\tprivate static extern int wrapped_GetKey(int keyset, IntPtr cryptContext, int keyIDtype, IntPtr keyID, IntPtr password);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptAddPublicKey\")]\n\tprivate static extern int wrapped_AddPublicKey(int keyset, int certificate);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptAddPrivateKey\")]\n\tprivate static extern int wrapped_AddPrivateKey(int keyset, int cryptKey, IntPtr password);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeleteKey\")]\n\tprivate static extern int wrapped_DeleteKey(int keyset, int keyIDtype, IntPtr keyID);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateCert\")]\n\tprivate static extern int wrapped_CreateCert(IntPtr certificate, int cryptUser, int certType);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDestroyCert\")]\n\tprivate static extern int wrapped_DestroyCert(int certificate);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptGetCertExtension\")]\n\tprivate static extern int wrapped_GetCertExtension(int certificate, IntPtr oid, IntPtr criticalFlag, IntPtr extension, int extensionMaxLength, IntPtr extensionLength);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptAddCertExtension\")]\n\tprivate static extern int wrapped_AddCertExtension(int certificate, IntPtr oid, int criticalFlag, IntPtr extension, int extensionLength);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeleteCertExtension\")]\n\tprivate static extern int wrapped_DeleteCertExtension(int certificate, IntPtr oid);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptSignCert\")]\n\tprivate static extern int wrapped_SignCert(int certificate, int signContext);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCheckCert\")]\n\tprivate static extern int wrapped_CheckCert(int certificate, int sigCheckKey);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptImportCert\")]\n\tprivate static extern int wrapped_ImportCert(IntPtr certObject, int certObjectLength, int cryptUser, IntPtr certificate);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptExportCert\")]\n\tprivate static extern int wrapped_ExportCert(IntPtr certObject, int certObjectMaxLength, IntPtr certObjectLength, int certFormatType, int certificate);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCAAddItem\")]\n\tprivate static extern int wrapped_CAAddItem(int keyset, int certificate);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCAGetItem\")]\n\tprivate static extern int wrapped_CAGetItem(int keyset, IntPtr certificate, int certType, int keyIDtype, IntPtr keyID);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCADeleteItem\")]\n\tprivate static extern int wrapped_CADeleteItem(int keyset, int certType, int keyIDtype, IntPtr keyID);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCACertManagement\")]\n\tprivate static extern int wrapped_CACertManagement(IntPtr certificate, int action, int keyset, int caKey, int certRequest);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateEnvelope\")]\n\tprivate static extern int wrapped_CreateEnvelope(IntPtr envelope, int cryptUser, int formatType);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDestroyEnvelope\")]\n\tprivate static extern int wrapped_DestroyEnvelope(int envelope);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptCreateSession\")]\n\tprivate static extern int wrapped_CreateSession(IntPtr session, int cryptUser, int formatType);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDestroySession\")]\n\tprivate static extern int wrapped_DestroySession(int session);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptPushData\")]\n\tprivate static extern int wrapped_PushData(int envelope, IntPtr buffer, int length, IntPtr bytesCopied);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptFlushData\")]\n\tprivate static extern int wrapped_FlushData(int envelope);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptPopData\")]\n\tprivate static extern int wrapped_PopData(int envelope, IntPtr buffer, int length, IntPtr bytesCopied);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeviceOpen\")]\n\tprivate static extern int wrapped_DeviceOpen(IntPtr device, int cryptUser, int deviceType, IntPtr name);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeviceClose\")]\n\tprivate static extern int wrapped_DeviceClose(int device);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeviceQueryCapability\")]\n\tprivate static extern int wrapped_DeviceQueryCapability(int device, int cryptAlgo, IntPtr cryptQueryInfo);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptDeviceCreateContext\")]\n\tprivate static extern int wrapped_DeviceCreateContext(int device, IntPtr cryptContext, int cryptAlgo);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptLogin\")]\n\tprivate static extern int wrapped_Login(IntPtr user, IntPtr name, IntPtr password);\n\n\t[DllImport(\"cl32.dll\", EntryPoint=\"cryptLogout\")]\n\tprivate static extern int wrapped_Logout(int user);\n\n\n    /* Helper Functions */\n\n    private static void processStatus(int status)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status);\n    }\n\n\n    private static void processStatus(int status, int extraInfo)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status, extraInfo);\n    }\n\n    private static void checkIndices(byte[] array, int sequenceOffset, int sequenceLength)\n    {\n        if (array == null)\n        {\n            if (sequenceOffset == 0)\n                return;\n            else\n                throw new IndexOutOfRangeException();\n        }\n\n        int arrayLength = array.Length;\n\n        if (sequenceOffset < 0 ||\n            sequenceOffset >= arrayLength ||\n            sequenceOffset + sequenceLength > arrayLength)\n            throw new IndexOutOfRangeException();\n    }\n\n    private static void getPointer(byte[] buffer, int bufferOffset, ref GCHandle bufferHandle, ref IntPtr bufferPtr)\n    {\n        if (buffer == null)\n            return;\n        bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);\n        bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset);\n    }\n\n    private static void releasePointer(GCHandle bufferHandle)\n    {\n        if (bufferHandle.IsAllocated)\n            bufferHandle.Free();\n    }\n}\n\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_QUERY_INFO\n{\n    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String algoName;\n    public int blockSize;\n    public int minKeySize;\n    public int keySize;\n    public int maxKeySize;\n\n    public CRYPT_QUERY_INFO(){}\n\n    public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)\n    {\n        algoName = newAlgoName;\n        blockSize = newBlockSize;\n        minKeySize = newMinKeySize;\n        keySize = newKeySize;\n        maxKeySize = newMaxKeySize;\n    }\n}\n\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_OBJECT_INFO\n{\n    public int objectType;\n    public int cryptAlgo;\n    public int cryptMode;\n    public int hashAlgo;\n    [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]public byte[] salt;\n    public int saltSize;\n\n    public CRYPT_OBJECT_INFO()\n    {\n        salt = new byte[64];\n        saltSize = 64;\n    }\n\n    public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)\n    {\n        objectType = newObjectType;\n        cryptAlgo = newCryptAlgo;\n        cryptMode = newCryptMode;\n        hashAlgo = newHashAlgo;\n    }\n}\n\npublic class CryptException : ApplicationException\n{\n    public int Status { get { return (int)Data[\"Status\"]; } }\n\n    public int ExtraInfo { get { return (int)Data[\"ExtraInfo\"]; } }\n\n    public CryptException(int status)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n    }\n\n    public CryptException(int status, int extra)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n        Data.Add(\"ExtraInfo\", extra);\n    }\n\n    private static string convertMessage(int status)\n    {\n        String prefix = Convert.ToString(status) + \": \";\n        switch (status)\n        {\n\t\tcase crypt.ERROR_PARAM1: return prefix + \"Bad argument, parameter 1\";\n\t\tcase crypt.ERROR_PARAM2: return prefix + \"Bad argument, parameter 2\";\n\t\tcase crypt.ERROR_PARAM3: return prefix + \"Bad argument, parameter 3\";\n\t\tcase crypt.ERROR_PARAM4: return prefix + \"Bad argument, parameter 4\";\n\t\tcase crypt.ERROR_PARAM5: return prefix + \"Bad argument, parameter 5\";\n\t\tcase crypt.ERROR_PARAM6: return prefix + \"Bad argument, parameter 6\";\n\t\tcase crypt.ERROR_PARAM7: return prefix + \"Bad argument, parameter 7\";\n\t\tcase crypt.ERROR_MEMORY: return prefix + \"Out of memory\";\n\t\tcase crypt.ERROR_NOTINITED: return prefix + \"Data has not been initialised\";\n\t\tcase crypt.ERROR_INITED: return prefix + \"Data has already been init'd\";\n\t\tcase crypt.ERROR_NOSECURE: return prefix + \"Opn.not avail.at requested sec.level\";\n\t\tcase crypt.ERROR_RANDOM: return prefix + \"No reliable random data available\";\n\t\tcase crypt.ERROR_FAILED: return prefix + \"Operation failed\";\n\t\tcase crypt.ERROR_INTERNAL: return prefix + \"Internal consistency check failed\";\n\t\tcase crypt.ERROR_NOTAVAIL: return prefix + \"This type of opn.not available\";\n\t\tcase crypt.ERROR_PERMISSION: return prefix + \"No permiss.to perform this operation\";\n\t\tcase crypt.ERROR_WRONGKEY: return prefix + \"Incorrect key used to decrypt data\";\n\t\tcase crypt.ERROR_INCOMPLETE: return prefix + \"Operation incomplete/still in progress\";\n\t\tcase crypt.ERROR_COMPLETE: return prefix + \"Operation complete/can't continue\";\n\t\tcase crypt.ERROR_TIMEOUT: return prefix + \"Operation timed out before completion\";\n\t\tcase crypt.ERROR_INVALID: return prefix + \"Invalid/inconsistent information\";\n\t\tcase crypt.ERROR_SIGNALLED: return prefix + \"Resource destroyed by extnl.event\";\n\t\tcase crypt.ERROR_OVERFLOW: return prefix + \"Resources/space exhausted\";\n\t\tcase crypt.ERROR_UNDERFLOW: return prefix + \"Not enough data available\";\n\t\tcase crypt.ERROR_BADDATA: return prefix + \"Bad/unrecognised data format\";\n\t\tcase crypt.ERROR_SIGNATURE: return prefix + \"Signature/integrity check failed\";\n\t\tcase crypt.ERROR_OPEN: return prefix + \"Cannot open object\";\n\t\tcase crypt.ERROR_READ: return prefix + \"Cannot read item from object\";\n\t\tcase crypt.ERROR_WRITE: return prefix + \"Cannot write item to object\";\n\t\tcase crypt.ERROR_NOTFOUND: return prefix + \"Requested item not found in object\";\n\t\tcase crypt.ERROR_DUPLICATE: return prefix + \"Item already present in object\";\n\t\tcase crypt.ENVELOPE_RESOURCE: return prefix + \"Need resource to proceed\";\n            default: return prefix + \"Unknown Exception ?!?!\";\n        }\n    }\n}\n\n}"
  },
  {
    "path": "deps/cl345/bindings/cryptlib.pas",
    "content": "unit cryptlib;\n\ninterface\n\n{****************************************************************************\n*                                                                           *\n*                     Cryptlib external API interface                       *\n*                    Copyright Peter Gutmann 1997-2019                      *\n*                                                                           *\n*        adapted for Delphi Version 5 (32 bit) and Kylix Version 3          *\n*                              by W. Gothier                                *\n****************************************************************************}\n\n\n{------------------------------------------------------------------------------\n\n This file has been created automatically by a perl script from the file:\n\n \"cryptlib.h\" dated Thu Dec 27 23:27:20 2018, filesize = 99183.\n\n Please check twice that the file matches the version of cryptlib.h\n in your cryptlib source! If this is not the right version, try to download an\n update from \"http://cryptlib.sogot.de/\". If the filesize or file creation\n date do not match, then please do not complain about problems.\n\n Published by W. Gothier, \n mailto: problems@cryptlib.sogot.de if you find errors in this file.\n\n-------------------------------------------------------------------------------}\n\n{$A+}  {Set Alignment on}\n{$F+}  {Force function calls to FAR}\n{$Z+}  {Force all enumeration values to Integer size}\n\nconst\n  {$IFDEF WIN32}\n    cryptlibname = 'CL32.DLL';  { dynamic linkname for Windows (Delphi) }\n  {$ELSE}\n    cryptlibname = 'libcl.so';  { library name for Unix/Linux  (Kylix) }\n                 { symbolic link should be used for libcl.so -> libcl.so.3.x.y }\n  {$ENDIF}\n\n\nconst\n  CRYPTLIB_VERSION = 3441;\n\n{****************************************************************************\n*                                                                           *\n*                           Algorithm and Object Types                      *\n*                                                                           *\n****************************************************************************}\n\n{  Algorithm and mode types  }\n\n\ntype\n CRYPT_ALGO_TYPE = Integer;\nconst\n  { Algorithms }\n  { No encryption }\n  CRYPT_ALGO_NONE = 0;  { No encryption }\n  \n  { Conventional encryption }\n  CRYPT_ALGO_DES = 1;  { DES }\n  CRYPT_ALGO_3DES = 2;  { Triple DES }\n  CRYPT_ALGO_IDEA = 3;  { IDEA (only used for PGP 2.x) }\n  CRYPT_ALGO_CAST = 4;  { CAST-128 (only used for OpenPGP) }\n  CRYPT_ALGO_RC2 = 5;  { RC2 (disabled by default, used for PKCS #12) }\n  CRYPT_ALGO_RC4 = 6;  { RC4 (insecure, deprecated) }\n  CRYPT_ALGO_RESERVED1 = 7;  { Formerly RC5 }\n  CRYPT_ALGO_AES = 8;  { AES }\n  CRYPT_ALGO_RESERVED2 = 9;  { Formerly Blowfish }\n  \n  { Public-key encryption }\n  CRYPT_ALGO_DH = 100;  { Diffie-Hellman }\n  CRYPT_ALGO_RSA = 101;  { RSA }\n  CRYPT_ALGO_DSA = 102;  { DSA }\n  CRYPT_ALGO_ELGAMAL = 103;  { ElGamal }\n  CRYPT_ALGO_RESERVED3 = 104;  { Formerly KEA }\n  CRYPT_ALGO_ECDSA = 105;  { ECDSA }\n  CRYPT_ALGO_ECDH = 106;  { ECDH }\n  \n  { Hash algorithms }\n  CRYPT_ALGO_RESERVED4 = 200;  { Formerly MD2 }\n  CRYPT_ALGO_RESERVED5 = 201;  { Formerly MD4 }\n  CRYPT_ALGO_MD5 = 202;  { MD5 (only used for TLS 1.0/1.1) }\n  CRYPT_ALGO_SHA1 = 203;  { SHA/SHA1 }\n  CRYPT_ALGO_RESERVED6 = 204;  { Formerly RIPE-MD 160 }\n  CRYPT_ALGO_SHA2 = 205;  { SHA-256 }\n  CRYPT_ALGO_SHA256 = 205; { = CRYPT_ALGO_SHA2 }  { Alternate name }\n  CRYPT_ALGO_SHAng = 206;  { Future SHA-nextgen standard }\n  \n  { MACs }\n  CRYPT_ALGO_RESREVED_7 = 300;  { Formerly HMAC-MD5 }\n  CRYPT_ALGO_HMAC_SHA1 = 301;  { HMAC-SHA }\n  CRYPT_ALGO_RESERVED8 = 302;  { Formerly HMAC-RIPEMD-160 }\n  CRYPT_ALGO_HMAC_SHA2 = 303;  { HMAC-SHA2 }\n  CRYPT_ALGO_HMAC_SHAng = 304;  { HMAC-future-SHA-nextgen }\n  \n  \n  { Vendors may want to use their own algorithms that aren't part of the\n  general cryptlib suite.  The following values are for vendor-defined\n  algorithms, and can be used just like the named algorithm types (it's\n  up to the vendor to keep track of what _VENDOR1 actually corresponds\n  to) }\n  \n  CRYPT_ALGO_LAST = 305;  { Last possible crypt algo value }\n  \n  { In order that we can scan through a range of algorithms with\n  cryptQueryCapability(), we define the following boundary points for\n  each algorithm class }\n  CRYPT_ALGO_FIRST_CONVENTIONAL = 1;  \n  CRYPT_ALGO_LAST_CONVENTIONAL = 99;  \n  CRYPT_ALGO_FIRST_PKC = 100;  \n  CRYPT_ALGO_LAST_PKC = 199;  \n  CRYPT_ALGO_FIRST_HASH = 200;  \n  CRYPT_ALGO_LAST_HASH = 299;  \n  CRYPT_ALGO_FIRST_MAC = 300;  \n  CRYPT_ALGO_LAST_MAC = 399;  \n  \n\n\n\n\ntype\n  CRYPT_MODE_TYPE = (                        {  Block cipher modes  }\n    CRYPT_MODE_NONE,                {  No encryption mode  }\n    CRYPT_MODE_ECB,                 {  ECB  }\n    CRYPT_MODE_CBC,                 {  CBC  }\n    CRYPT_MODE_CFB,                 {  CFB  }\n    CRYPT_MODE_GCM,                 {  GCM  }\n    CRYPT_MODE_LAST                 {  Last possible crypt mode value  }\n    \n  );\n\n\n{  Keyset subtypes  }\n\n  CRYPT_KEYSET_TYPE = (                        {  Keyset types  }\n    CRYPT_KEYSET_NONE,              {  No keyset type  }\n    CRYPT_KEYSET_FILE,              {  Generic flat file keyset  }\n    CRYPT_KEYSET_HTTP,              {  Web page containing cert/CRL  }\n    CRYPT_KEYSET_LDAP,              {  LDAP directory service  }\n    CRYPT_KEYSET_ODBC,              {  Generic ODBC interface  }\n    CRYPT_KEYSET_DATABASE,          {  Generic RDBMS interface  }\n    CRYPT_KEYSET_ODBC_STORE,        {  ODBC certificate store  }\n    CRYPT_KEYSET_DATABASE_STORE,    {  Database certificate store  }\n    CRYPT_KEYSET_LAST               {  Last possible keyset type  }\n\n    \n  );\n\n{  Device subtypes  }\n\n  CRYPT_DEVICE_TYPE = (                        {  Crypto device types  }\n    CRYPT_DEVICE_NONE,              {  No crypto device  }\n    CRYPT_DEVICE_FORTEZZA,          {  Fortezza card - Placeholder only  }\n    CRYPT_DEVICE_PKCS11,            {  PKCS #11 crypto token  }\n    CRYPT_DEVICE_CRYPTOAPI,         {  Microsoft CryptoAPI  }\n    CRYPT_DEVICE_HARDWARE,          {  Generic crypo HW plugin  }\n    CRYPT_DEVICE_LAST               {  Last possible crypto device type  }\n    \n  );\n\n{  Certificate subtypes  }\n\n  CRYPT_CERTTYPE_TYPE = (                        {  Certificate object types  }\n    CRYPT_CERTTYPE_NONE,            {  No certificate type  }\n    CRYPT_CERTTYPE_CERTIFICATE,     {  Certificate  }\n    CRYPT_CERTTYPE_ATTRIBUTE_CERT,  {  Attribute certificate  }\n    CRYPT_CERTTYPE_CERTCHAIN,       {  PKCS #7 certificate chain  }\n    CRYPT_CERTTYPE_CERTREQUEST,     {  PKCS #10 certification request  }\n    CRYPT_CERTTYPE_REQUEST_CERT,    {  CRMF certification request  }\n    CRYPT_CERTTYPE_REQUEST_REVOCATION,  {  CRMF revocation request  }\n    CRYPT_CERTTYPE_CRL,             {  CRL  }\n    CRYPT_CERTTYPE_CMS_ATTRIBUTES,  {  CMS attributes  }\n    CRYPT_CERTTYPE_RTCS_REQUEST,    {  RTCS request  }\n    CRYPT_CERTTYPE_RTCS_RESPONSE,   {  RTCS response  }\n    CRYPT_CERTTYPE_OCSP_REQUEST,    {  OCSP request  }\n    CRYPT_CERTTYPE_OCSP_RESPONSE,   {  OCSP response  }\n    CRYPT_CERTTYPE_PKIUSER,         {  PKI user information  }\n    CRYPT_CERTTYPE_LAST             {  Last possible cert.type  }\n    \n  );\n\n{  Envelope/data format subtypes  }\n\n  CRYPT_FORMAT_TYPE = (  \n    CRYPT_FORMAT_NONE,              {  No format type  }\n    CRYPT_FORMAT_AUTO,              {  Deenv, auto-determine type  }\n    CRYPT_FORMAT_CRYPTLIB,          {  cryptlib native format  }\n    CRYPT_FORMAT_CMS,               {  PKCS #7 / CMS / S/MIME fmt.}\n    CRYPT_FORMAT_SMIME,             {  As CMS with MSG-style behaviour  }\n    CRYPT_FORMAT_PGP,               {  PGP format  }\n    CRYPT_FORMAT_LAST               {  Last possible format type  }\n    \n  );\n\nconst\n  CRYPT_FORMAT_PKCS7: CRYPT_FORMAT_TYPE = CRYPT_FORMAT_CMS;\n\n{  Session subtypes  }\n\n\ntype\n  CRYPT_SESSION_TYPE = (  \n    CRYPT_SESSION_NONE,             {  No session type  }\n    CRYPT_SESSION_SSH,              {  SSH  }\n    CRYPT_SESSION_SSH_SERVER,       {  SSH server  }\n    CRYPT_SESSION_SSL,              {  SSL/TLS  }\n    CRYPT_SESSION_SSL_SERVER,       {  SSL/TLS server  }\n    CRYPT_SESSION_RTCS,             {  RTCS  }\n    CRYPT_SESSION_RTCS_SERVER,      {  RTCS server  }\n    CRYPT_SESSION_OCSP,             {  OCSP  }\n    CRYPT_SESSION_OCSP_SERVER,      {  OCSP server  }\n    CRYPT_SESSION_TSP,              {  TSP  }\n    CRYPT_SESSION_TSP_SERVER,       {  TSP server  }\n    CRYPT_SESSION_CMP,              {  CMP  }\n    CRYPT_SESSION_CMP_SERVER,       {  CMP server  }\n    CRYPT_SESSION_SCEP,             {  SCEP  }\n    CRYPT_SESSION_SCEP_SERVER,      {  SCEP server  }\n    CRYPT_SESSION_CERTSTORE_SERVER, {  HTTP cert store interface  }\n    CRYPT_SESSION_LAST              {  Last possible session type  }\n    \n  );\n\nconst\n  CRYPT_SESSION_TLS_SERVER: CRYPT_SESSION_TYPE = CRYPT_SESSION_SSL_SERVER;\n\n{  User subtypes  }\n\n\ntype\n  CRYPT_USER_TYPE = (  \n    CRYPT_USER_NONE,                {  No user type  }\n    CRYPT_USER_NORMAL,              {  Normal user  }\n    CRYPT_USER_SO,                  {  Security officer  }\n    CRYPT_USER_CA,                  {  CA user  }\n    CRYPT_USER_LAST                 {  Last possible user type  }\n    \n  );\n\n{****************************************************************************\n*                                                                           *\n*                               Attribute Types                             *\n*                                                                           *\n****************************************************************************}\n\n{  Attribute types.  These are arranged in the following order:\n\n    PROPERTY    - Object property\n    ATTRIBUTE   - Generic attributes\n    OPTION      - Global or object-specific config.option\n    CTXINFO     - Context-specific attribute\n    CERTINFO    - Certificate-specific attribute\n    KEYINFO     - Keyset-specific attribute\n    DEVINFO     - Device-specific attribute\n    ENVINFO     - Envelope-specific attribute\n    SESSINFO    - Session-specific attribute\n    USERINFO    - User-specific attribute  }\n\n CRYPT_ATTRIBUTE_TYPE = Integer;\nconst\n  \n  CRYPT_ATTRIBUTE_NONE = 0;  { Non-value }\n  \n  { Used internally }\n  CRYPT_PROPERTY_FIRST = 1;  \n  \n  {*******************}\n  { Object attributes }\n  {*******************}\n  \n  { Object properties }\n  CRYPT_PROPERTY_HIGHSECURITY = 2;  { Owned+non-forwardcount+locked }\n  CRYPT_PROPERTY_OWNER = 3;  { Object owner }\n  CRYPT_PROPERTY_FORWARDCOUNT = 4;  { No.of times object can be forwarded }\n  CRYPT_PROPERTY_LOCKED = 5;  { Whether properties can be chged/read }\n  CRYPT_PROPERTY_USAGECOUNT = 6;  { Usage count before object expires }\n  CRYPT_PROPERTY_NONEXPORTABLE = 7;  { Whether key is nonexp.from context }\n  \n  { Used internally }\n  CRYPT_PROPERTY_LAST = 8;  CRYPT_GENERIC_FIRST = 9;  \n  \n  { Extended error information }\n  CRYPT_ATTRIBUTE_ERRORTYPE = 10;  { Type of last error }\n  CRYPT_ATTRIBUTE_ERRORLOCUS = 11;  { Locus of last error }\n  CRYPT_ATTRIBUTE_ERRORMESSAGE = 12;  { Detailed error description }\n  \n  { Generic information }\n  CRYPT_ATTRIBUTE_CURRENT_GROUP = 13;  { Cursor mgt: Group in attribute list }\n  CRYPT_ATTRIBUTE_CURRENT = 14;  { Cursor mgt: Entry in attribute list }\n  CRYPT_ATTRIBUTE_CURRENT_INSTANCE = 15;  { Cursor mgt: Instance in attribute list }\n  CRYPT_ATTRIBUTE_BUFFERSIZE = 16;  { Internal data buffer size }\n  \n  { Used internally }\n  CRYPT_GENERIC_LAST = 17;  CRYPT_OPTION_FIRST = 100;  \n  \n  {**************************}\n  { Configuration attributes }\n  {**************************}\n  \n  { cryptlib information (read-only) }\n  CRYPT_OPTION_INFO_DESCRIPTION = 101;  { Text description }\n  CRYPT_OPTION_INFO_COPYRIGHT = 102;  { Copyright notice }\n  CRYPT_OPTION_INFO_MAJORVERSION = 103;  { Major release version }\n  CRYPT_OPTION_INFO_MINORVERSION = 104;  { Minor release version }\n  CRYPT_OPTION_INFO_STEPPING = 105;  { Release stepping }\n  \n  { Encryption options }\n  CRYPT_OPTION_ENCR_ALGO = 106;  { Conventional ncryption algorithm }\n  CRYPT_OPTION_ENCR_HASH = 107;  { Hash algorithm }\n  CRYPT_OPTION_ENCR_MAC = 108;  { MAC algorithm }\n  \n  { PKC options }\n  CRYPT_OPTION_PKC_ALGO = 109;  { PKC algorithm }\n  CRYPT_OPTION_PKC_KEYSIZE = 110;  { PKC key size }\n  \n  { Placeholder for obsolete options }\n  CRYPT_OPTION_DUMMY1 = 111;  \n  CRYPT_OPTION_DUMMY2 = 112;  \n  \n  { Keying options }\n  CRYPT_OPTION_KEYING_ALGO = 113;  { Key processing algorithm }\n  CRYPT_OPTION_KEYING_ITERATIONS = 114;  { Key processing iterations }\n  \n  { Certificate options }\n  CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES = 115;  { Whether to sign unrecog.attrs }\n  CRYPT_OPTION_CERT_VALIDITY = 116;  { Certificate validity period }\n  CRYPT_OPTION_CERT_UPDATEINTERVAL = 117;  { CRL update interval }\n  CRYPT_OPTION_CERT_COMPLIANCELEVEL = 118;  { PKIX compliance level for cert chks.}\n  CRYPT_OPTION_CERT_REQUIREPOLICY = 119;  { Whether explicit policy req'd for certs }\n  \n  { CMS/SMIME options }\n  CRYPT_OPTION_CMS_DEFAULTATTRIBUTES = 120;  { Add default CMS attributes }\n  CRYPT_OPTION_SMIME_DEFAULTATTRIBUTES = 120; { = CRYPT_OPTION_CMS_DEFAULTATTRIBUTES }  \n  \n  { LDAP keyset options }\n  CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS = 121;  { Object class }\n  CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE = 122;  { Object type to fetch }\n  CRYPT_OPTION_KEYS_LDAP_FILTER = 123;  { Query filter }\n  CRYPT_OPTION_KEYS_LDAP_CACERTNAME = 124;  { CA certificate attribute name }\n  CRYPT_OPTION_KEYS_LDAP_CERTNAME = 125;  { Certificate attribute name }\n  CRYPT_OPTION_KEYS_LDAP_CRLNAME = 126;  { CRL attribute name }\n  CRYPT_OPTION_KEYS_LDAP_EMAILNAME = 127;  { Email attribute name }\n  \n  { Crypto device options }\n  CRYPT_OPTION_DEVICE_PKCS11_DVR01 = 128;  { Name of first PKCS #11 driver }\n  CRYPT_OPTION_DEVICE_PKCS11_DVR02 = 129;  { Name of second PKCS #11 driver }\n  CRYPT_OPTION_DEVICE_PKCS11_DVR03 = 130;  { Name of third PKCS #11 driver }\n  CRYPT_OPTION_DEVICE_PKCS11_DVR04 = 131;  { Name of fourth PKCS #11 driver }\n  CRYPT_OPTION_DEVICE_PKCS11_DVR05 = 132;  { Name of fifth PKCS #11 driver }\n  CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY = 133;  { Use only hardware mechanisms }\n  \n  { Network access options }\n  CRYPT_OPTION_NET_SOCKS_SERVER = 134;  { Socks server name }\n  CRYPT_OPTION_NET_SOCKS_USERNAME = 135;  { Socks user name }\n  CRYPT_OPTION_NET_HTTP_PROXY = 136;  { Web proxy server }\n  CRYPT_OPTION_NET_CONNECTTIMEOUT = 137;  { Timeout for network connection setup }\n  CRYPT_OPTION_NET_READTIMEOUT = 138;  { Timeout for network reads }\n  CRYPT_OPTION_NET_WRITETIMEOUT = 139;  { Timeout for network writes }\n  \n  { Miscellaneous options }\n  CRYPT_OPTION_MISC_ASYNCINIT = 140;  { Whether to init cryptlib async'ly }\n  CRYPT_OPTION_MISC_SIDECHANNELPROTECTION = 141;  { Protect against side-channel attacks }\n  \n  { cryptlib state information }\n  CRYPT_OPTION_CONFIGCHANGED = 142;  { Whether in-mem.opts match on-disk ones }\n  CRYPT_OPTION_SELFTESTOK = 143;  { Whether self-test was completed and OK }\n  \n  { Used internally }\n  CRYPT_OPTION_LAST = 144;  CRYPT_CTXINFO_FIRST = 1000;  \n  \n  {********************}\n  { Context attributes }\n  {********************}\n  \n  { Algorithm and mode information }\n  CRYPT_CTXINFO_ALGO = 1001;  { Algorithm }\n  CRYPT_CTXINFO_MODE = 1002;  { Mode }\n  CRYPT_CTXINFO_NAME_ALGO = 1003;  { Algorithm name }\n  CRYPT_CTXINFO_NAME_MODE = 1004;  { Mode name }\n  CRYPT_CTXINFO_KEYSIZE = 1005;  { Key size in bytes }\n  CRYPT_CTXINFO_BLOCKSIZE = 1006;  { Block size }\n  CRYPT_CTXINFO_IVSIZE = 1007;  { IV size }\n  CRYPT_CTXINFO_KEYING_ALGO = 1008;  { Key processing algorithm }\n  CRYPT_CTXINFO_KEYING_ITERATIONS = 1009;  { Key processing iterations }\n  CRYPT_CTXINFO_KEYING_SALT = 1010;  { Key processing salt }\n  CRYPT_CTXINFO_KEYING_VALUE = 1011;  { Value used to derive key }\n  \n  { State information }\n  CRYPT_CTXINFO_KEY = 1012;  { Key }\n  CRYPT_CTXINFO_KEY_COMPONENTS = 1013;  { Public-key components }\n  CRYPT_CTXINFO_IV = 1014;  { IV }\n  CRYPT_CTXINFO_HASHVALUE = 1015;  { Hash value }\n  \n  { Misc.information }\n  CRYPT_CTXINFO_LABEL = 1016;  { Label for private/secret key }\n  CRYPT_CTXINFO_PERSISTENT = 1017;  { Obj.is backed by device or keyset }\n  \n  { Used internally }\n  CRYPT_CTXINFO_LAST = 1018;  CRYPT_CERTINFO_FIRST = 2000;  \n  \n  {************************}\n  { Certificate attributes }\n  {************************}\n  \n  { Because there are so many cert attributes, we break them down into\n  blocks to minimise the number of values that change if a new one is\n  added halfway through }\n  \n  { Pseudo-information on a cert object or meta-information which is used\n  to control the way that a cert object is processed }\n  CRYPT_CERTINFO_SELFSIGNED = 2001;  { Cert is self-signed }\n  CRYPT_CERTINFO_IMMUTABLE = 2002;  { Cert is signed and immutable }\n  CRYPT_CERTINFO_XYZZY = 2003;  { Cert is a magic just-works cert }\n  CRYPT_CERTINFO_CERTTYPE = 2004;  { Certificate object type }\n  CRYPT_CERTINFO_FINGERPRINT_SHA1 = 2005;  { Certificate fingerprints }\n  CRYPT_CERTINFO_FINGERPRINT_SHA2 = 2006;  \n  CRYPT_CERTINFO_FINGERPRINT_SHAng = 2007;  \n  CRYPT_CERTINFO_CURRENT_CERTIFICATE = 2008;  { Cursor mgt: Rel.pos in chain/CRL/OCSP }\n  CRYPT_CERTINFO_TRUSTED_USAGE = 2009;  { Usage that cert is trusted for }\n  CRYPT_CERTINFO_TRUSTED_IMPLICIT = 2010;  { Whether cert is implicitly trusted }\n  CRYPT_CERTINFO_SIGNATURELEVEL = 2011;  { Amount of detail to include in sigs.}\n  \n  { General certificate object information }\n  CRYPT_CERTINFO_VERSION = 2012;  { Cert.format version }\n  CRYPT_CERTINFO_SERIALNUMBER = 2013;  { Serial number }\n  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO = 2014;  { Public key }\n  CRYPT_CERTINFO_CERTIFICATE = 2015;  { User certificate }\n  CRYPT_CERTINFO_USERCERTIFICATE = 2015; { = CRYPT_CERTINFO_CERTIFICATE }  \n  CRYPT_CERTINFO_CACERTIFICATE = 2016;  { CA certificate }\n  CRYPT_CERTINFO_ISSUERNAME = 2017;  { Issuer DN }\n  CRYPT_CERTINFO_VALIDFROM = 2018;  { Cert valid-from time }\n  CRYPT_CERTINFO_VALIDTO = 2019;  { Cert valid-to time }\n  CRYPT_CERTINFO_SUBJECTNAME = 2020;  { Subject DN }\n  CRYPT_CERTINFO_ISSUERUNIQUEID = 2021;  { Issuer unique ID }\n  CRYPT_CERTINFO_SUBJECTUNIQUEID = 2022;  { Subject unique ID }\n  CRYPT_CERTINFO_CERTREQUEST = 2023;  { Cert.request (DN + public key) }\n  CRYPT_CERTINFO_THISUPDATE = 2024;  { CRL/OCSP current-update time }\n  CRYPT_CERTINFO_NEXTUPDATE = 2025;  { CRL/OCSP next-update time }\n  CRYPT_CERTINFO_REVOCATIONDATE = 2026;  { CRL/OCSP cert-revocation time }\n  CRYPT_CERTINFO_REVOCATIONSTATUS = 2027;  { OCSP revocation status }\n  CRYPT_CERTINFO_CERTSTATUS = 2028;  { RTCS certificate status }\n  CRYPT_CERTINFO_DN = 2029;  { Currently selected DN in string form }\n  CRYPT_CERTINFO_PKIUSER_ID = 2030;  { PKI user ID }\n  CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD = 2031;  { PKI user issue password }\n  CRYPT_CERTINFO_PKIUSER_REVPASSWORD = 2032;  { PKI user revocation password }\n  CRYPT_CERTINFO_PKIUSER_RA = 2033;  { PKI user is an RA }\n  \n  { X.520 Distinguished Name components.  This is a composite field, the\n  DN to be manipulated is selected through the addition of a\n  pseudocomponent, and then one of the following is used to access the\n  DN components directly }\n  CRYPT_CERTINFO_COUNTRYNAME = 2100;  { countryName }\n  CRYPT_CERTINFO_STATEORPROVINCENAME = 2101;  { stateOrProvinceName }\n  CRYPT_CERTINFO_LOCALITYNAME = 2102;  { localityName }\n  CRYPT_CERTINFO_ORGANIZATIONNAME = 2103;  { organizationName }\n  CRYPT_CERTINFO_ORGANISATIONNAME = 2103; { = CRYPT_CERTINFO_ORGANIZATIONNAME }  \n  CRYPT_CERTINFO_ORGANIZATIONALUNITNAME = 2104;  { organizationalUnitName }\n  CRYPT_CERTINFO_ORGANISATIONALUNITNAME = 2104; { = CRYPT_CERTINFO_ORGANIZATIONALUNITNAME }  \n  CRYPT_CERTINFO_COMMONNAME = 2105;  { commonName }\n  \n  { X.509 General Name components.  These are handled in the same way as\n  the DN composite field, with the current GeneralName being selected by\n  a pseudo-component after which the individual components can be\n  modified through one of the following }\n  CRYPT_CERTINFO_OTHERNAME_TYPEID = 2106;  { otherName.typeID }\n  CRYPT_CERTINFO_OTHERNAME_VALUE = 2107;  { otherName.value }\n  CRYPT_CERTINFO_RFC822NAME = 2108;  { rfc822Name }\n  CRYPT_CERTINFO_EMAIL = 2108; { = CRYPT_CERTINFO_RFC822NAME }  \n  CRYPT_CERTINFO_DNSNAME = 2109;  { dNSName }\n  CRYPT_CERTINFO_DIRECTORYNAME = 2110;  { directoryName }\n  CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER = 2111;  { ediPartyName.nameAssigner }\n  CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME = 2112;  { ediPartyName.partyName }\n  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER = 2113;  { uniformResourceIdentifier }\n  CRYPT_CERTINFO_URL = 2113; { = CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER }  \n  CRYPT_CERTINFO_IPADDRESS = 2114;  { iPAddress }\n  CRYPT_CERTINFO_REGISTEREDID = 2115;  { registeredID }\n  \n  { X.509 certificate extensions.  Although it would be nicer to use names\n  that match the extensions more closely (e.g.\n  CRYPT_CERTINFO_BASICCONSTRAINTS_PATHLENCONSTRAINT), these exceed the\n  32-character ANSI minimum length for unique names, and get really\n  hairy once you get into the weird policy constraints extensions whose\n  names wrap around the screen about three times.\n  \n  The following values are defined in OID order, this isn't absolutely\n  necessary but saves an extra layer of processing when encoding them }\n  \n  { 1 2 840 113549 1 9 7 challengePassword.  This is here even though it's\n  a CMS attribute because SCEP stuffs it into PKCS #10 requests }\n  CRYPT_CERTINFO_CHALLENGEPASSWORD = 2200;  \n  \n  { 1 3 6 1 4 1 3029 3 1 4 cRLExtReason }\n  CRYPT_CERTINFO_CRLEXTREASON = 2201;  \n  \n  { 1 3 6 1 4 1 3029 3 1 5 keyFeatures }\n  CRYPT_CERTINFO_KEYFEATURES = 2202;  \n  \n  { 1 3 6 1 5 5 7 1 1 authorityInfoAccess }\n  CRYPT_CERTINFO_AUTHORITYINFOACCESS = 2203;  \n  CRYPT_CERTINFO_AUTHORITYINFO_RTCS = 2204;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_AUTHORITYINFO_OCSP = 2205;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS = 2206;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE = 2207;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_AUTHORITYINFO_CRLS = 2208;  { accessDescription.accessLocation }\n  \n  { 1 3 6 1 5 5 7 1 2 biometricInfo }\n  CRYPT_CERTINFO_BIOMETRICINFO = 2209;  \n  CRYPT_CERTINFO_BIOMETRICINFO_TYPE = 2210;  { biometricData.typeOfData }\n  CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO = 2211;  { biometricData.hashAlgorithm }\n  CRYPT_CERTINFO_BIOMETRICINFO_HASH = 2212;  { biometricData.dataHash }\n  CRYPT_CERTINFO_BIOMETRICINFO_URL = 2213;  { biometricData.sourceDataUri }\n  \n  { 1 3 6 1 5 5 7 1 3 qcStatements }\n  CRYPT_CERTINFO_QCSTATEMENT = 2214;  \n  CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS = 2215;  \n  { qcStatement.statementInfo.semanticsIdentifier }\n  CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY = 2216;  \n  { qcStatement.statementInfo.nameRegistrationAuthorities }\n  \n  { 1 3 6 1 5 5 7 1 7 ipAddrBlocks }\n  CRYPT_CERTINFO_IPADDRESSBLOCKS = 2217;  \n  CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY = 2218;  { addressFamily }\n  {  CRYPT_CERTINFO_IPADDRESSBLOCKS_INHERIT, // ipAddress.inherit }\n  CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX = 2219;  { ipAddress.addressPrefix }\n  CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN = 2220;  { ipAddress.addressRangeMin }\n  CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX = 2221;  { ipAddress.addressRangeMax }\n  \n  { 1 3 6 1 5 5 7 1 8 autonomousSysIds }\n  CRYPT_CERTINFO_AUTONOMOUSSYSIDS = 2222;  \n  {  CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_INHERIT,// asNum.inherit }\n  CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID = 2223;  { asNum.id }\n  CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN = 2224;  { asNum.min }\n  CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX = 2225;  { asNum.max }\n  \n  { 1 3 6 1 5 5 7 48 1 2 ocspNonce }\n  CRYPT_CERTINFO_OCSP_NONCE = 2226;  { nonce }\n  \n  { 1 3 6 1 5 5 7 48 1 4 ocspAcceptableResponses }\n  CRYPT_CERTINFO_OCSP_RESPONSE = 2227;  \n  CRYPT_CERTINFO_OCSP_RESPONSE_OCSP = 2228;  { OCSP standard response }\n  \n  { 1 3 6 1 5 5 7 48 1 5 ocspNoCheck }\n  CRYPT_CERTINFO_OCSP_NOCHECK = 2229;  \n  \n  { 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff }\n  CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF = 2230;  \n  \n  { 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess }\n  CRYPT_CERTINFO_SUBJECTINFOACCESS = 2231;  \n  CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING = 2232;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY = 2233;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY = 2234;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST = 2235;  { accessDescription.accessLocation }\n  CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT = 2236;  { accessDescription.accessLocation }\n  \n  { 1 3 36 8 3 1 siggDateOfCertGen }\n  CRYPT_CERTINFO_SIGG_DATEOFCERTGEN = 2237;  \n  \n  { 1 3 36 8 3 2 siggProcuration }\n  CRYPT_CERTINFO_SIGG_PROCURATION = 2238;  \n  CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY = 2239;  { country }\n  CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION = 2240;  { typeOfSubstitution }\n  CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR = 2241;  { signingFor.thirdPerson }\n  \n  { 1 3 36 8 3 3 siggAdmissions }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS = 2242;  \n  CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY = 2243;  { authority }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID = 2244;  { namingAuth.iD }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL = 2245;  { namingAuth.uRL }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT = 2246;  { namingAuth.text }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM = 2247;  { professionItem }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID = 2248;  { professionOID }\n  CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER = 2249;  { registrationNumber }\n  \n  { 1 3 36 8 3 4 siggMonetaryLimit }\n  CRYPT_CERTINFO_SIGG_MONETARYLIMIT = 2250;  \n  CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY = 2251;  { currency }\n  CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT = 2252;  { amount }\n  CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT = 2253;  { exponent }\n  \n  { 1 3 36 8 3 5 siggDeclarationOfMajority }\n  CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY = 2254;  \n  CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY = 2255;  { fullAgeAtCountry }\n  \n  { 1 3 36 8 3 8 siggRestriction }\n  CRYPT_CERTINFO_SIGG_RESTRICTION = 2256;  \n  \n  { 1 3 36 8 3 13 siggCertHash }\n  CRYPT_CERTINFO_SIGG_CERTHASH = 2257;  \n  \n  { 1 3 36 8 3 15 siggAdditionalInformation }\n  CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION = 2258;  \n  \n  { 1 3 101 1 4 1 strongExtranet }\n  CRYPT_CERTINFO_STRONGEXTRANET = 2259;  \n  CRYPT_CERTINFO_STRONGEXTRANET_ZONE = 2260;  { sxNetIDList.sxNetID.zone }\n  CRYPT_CERTINFO_STRONGEXTRANET_ID = 2261;  { sxNetIDList.sxNetID.id }\n  \n  { 2 5 29 9 subjectDirectoryAttributes }\n  CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES = 2262;  \n  CRYPT_CERTINFO_SUBJECTDIR_TYPE = 2263;  { attribute.type }\n  CRYPT_CERTINFO_SUBJECTDIR_VALUES = 2264;  { attribute.values }\n  \n  { 2 5 29 14 subjectKeyIdentifier }\n  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER = 2265;  \n  \n  { 2 5 29 15 keyUsage }\n  CRYPT_CERTINFO_KEYUSAGE = 2266;  \n  \n  { 2 5 29 16 privateKeyUsagePeriod }\n  CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD = 2267;  \n  CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE = 2268;  { notBefore }\n  CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER = 2269;  { notAfter }\n  \n  { 2 5 29 17 subjectAltName }\n  CRYPT_CERTINFO_SUBJECTALTNAME = 2270;  \n  \n  { 2 5 29 18 issuerAltName }\n  CRYPT_CERTINFO_ISSUERALTNAME = 2271;  \n  \n  { 2 5 29 19 basicConstraints }\n  CRYPT_CERTINFO_BASICCONSTRAINTS = 2272;  \n  CRYPT_CERTINFO_CA = 2273;  { cA }\n  CRYPT_CERTINFO_AUTHORITY = 2273; { = CRYPT_CERTINFO_CA }  \n  CRYPT_CERTINFO_PATHLENCONSTRAINT = 2274;  { pathLenConstraint }\n  \n  { 2 5 29 20 cRLNumber }\n  CRYPT_CERTINFO_CRLNUMBER = 2275;  \n  \n  { 2 5 29 21 cRLReason }\n  CRYPT_CERTINFO_CRLREASON = 2276;  \n  \n  { 2 5 29 23 holdInstructionCode }\n  CRYPT_CERTINFO_HOLDINSTRUCTIONCODE = 2277;  \n  \n  { 2 5 29 24 invalidityDate }\n  CRYPT_CERTINFO_INVALIDITYDATE = 2278;  \n  \n  { 2 5 29 27 deltaCRLIndicator }\n  CRYPT_CERTINFO_DELTACRLINDICATOR = 2279;  \n  \n  { 2 5 29 28 issuingDistributionPoint }\n  CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT = 2280;  \n  CRYPT_CERTINFO_ISSUINGDIST_FULLNAME = 2281;  { distributionPointName.fullName }\n  CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY = 2282;  { onlyContainsUserCerts }\n  CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY = 2283;  { onlyContainsCACerts }\n  CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY = 2284;  { onlySomeReasons }\n  CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL = 2285;  { indirectCRL }\n  \n  { 2 5 29 29 certificateIssuer }\n  CRYPT_CERTINFO_CERTIFICATEISSUER = 2286;  \n  \n  { 2 5 29 30 nameConstraints }\n  CRYPT_CERTINFO_NAMECONSTRAINTS = 2287;  \n  CRYPT_CERTINFO_PERMITTEDSUBTREES = 2288;  { permittedSubtrees }\n  CRYPT_CERTINFO_EXCLUDEDSUBTREES = 2289;  { excludedSubtrees }\n  \n  { 2 5 29 31 cRLDistributionPoint }\n  CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT = 2290;  \n  CRYPT_CERTINFO_CRLDIST_FULLNAME = 2291;  { distributionPointName.fullName }\n  CRYPT_CERTINFO_CRLDIST_REASONS = 2292;  { reasons }\n  CRYPT_CERTINFO_CRLDIST_CRLISSUER = 2293;  { cRLIssuer }\n  \n  { 2 5 29 32 certificatePolicies }\n  CRYPT_CERTINFO_CERTIFICATEPOLICIES = 2294;  \n  CRYPT_CERTINFO_CERTPOLICYID = 2295;  { policyInformation.policyIdentifier }\n  CRYPT_CERTINFO_CERTPOLICY_CPSURI = 2296;  \n  { policyInformation.policyQualifiers.qualifier.cPSuri }\n  CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION = 2297;  \n  { policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization }\n  CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS = 2298;  \n  { policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers }\n  CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT = 2299;  \n  { policyInformation.policyQualifiers.qualifier.userNotice.explicitText }\n  \n  { 2 5 29 33 policyMappings }\n  CRYPT_CERTINFO_POLICYMAPPINGS = 2300;  \n  CRYPT_CERTINFO_ISSUERDOMAINPOLICY = 2301;  { policyMappings.issuerDomainPolicy }\n  CRYPT_CERTINFO_SUBJECTDOMAINPOLICY = 2302;  { policyMappings.subjectDomainPolicy }\n  \n  { 2 5 29 35 authorityKeyIdentifier }\n  CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER = 2303;  \n  CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER = 2304;  { keyIdentifier }\n  CRYPT_CERTINFO_AUTHORITY_CERTISSUER = 2305;  { authorityCertIssuer }\n  CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER = 2306;  { authorityCertSerialNumber }\n  \n  { 2 5 29 36 policyConstraints }\n  CRYPT_CERTINFO_POLICYCONSTRAINTS = 2307;  \n  CRYPT_CERTINFO_REQUIREEXPLICITPOLICY = 2308;  { policyConstraints.requireExplicitPolicy }\n  CRYPT_CERTINFO_INHIBITPOLICYMAPPING = 2309;  { policyConstraints.inhibitPolicyMapping }\n  \n  { 2 5 29 37 extKeyUsage }\n  CRYPT_CERTINFO_EXTKEYUSAGE = 2310;  \n  CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING = 2311;  { individualCodeSigning }\n  CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING = 2312;  { commercialCodeSigning }\n  CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING = 2313;  { certTrustListSigning }\n  CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING = 2314;  { timeStampSigning }\n  CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO = 2315;  { serverGatedCrypto }\n  CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM = 2316;  { encrypedFileSystem }\n  CRYPT_CERTINFO_EXTKEY_SERVERAUTH = 2317;  { serverAuth }\n  CRYPT_CERTINFO_EXTKEY_CLIENTAUTH = 2318;  { clientAuth }\n  CRYPT_CERTINFO_EXTKEY_CODESIGNING = 2319;  { codeSigning }\n  CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION = 2320;  { emailProtection }\n  CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM = 2321;  { ipsecEndSystem }\n  CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL = 2322;  { ipsecTunnel }\n  CRYPT_CERTINFO_EXTKEY_IPSECUSER = 2323;  { ipsecUser }\n  CRYPT_CERTINFO_EXTKEY_TIMESTAMPING = 2324;  { timeStamping }\n  CRYPT_CERTINFO_EXTKEY_OCSPSIGNING = 2325;  { ocspSigning }\n  CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE = 2326;  { directoryService }\n  CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE = 2327;  { anyExtendedKeyUsage }\n  CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO = 2328;  { serverGatedCrypto }\n  CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA = 2329;  { serverGatedCrypto CA }\n  CRYPT_CERTINFO_EXTKEYUSAGE_LAST = 2329; { = CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA }  \n  \n  { 2 5 29 40 crlStreamIdentifier }\n  CRYPT_CERTINFO_CRLSTREAMIDENTIFIER = 2330;  \n  \n  { 2 5 29 46 freshestCRL }\n  CRYPT_CERTINFO_FRESHESTCRL = 2331;  \n  CRYPT_CERTINFO_FRESHESTCRL_FULLNAME = 2332;  { distributionPointName.fullName }\n  CRYPT_CERTINFO_FRESHESTCRL_REASONS = 2333;  { reasons }\n  CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER = 2334;  { cRLIssuer }\n  \n  { 2 5 29 47 orderedList }\n  CRYPT_CERTINFO_ORDEREDLIST = 2335;  \n  \n  { 2 5 29 51 baseUpdateTime }\n  CRYPT_CERTINFO_BASEUPDATETIME = 2336;  \n  \n  { 2 5 29 53 deltaInfo }\n  CRYPT_CERTINFO_DELTAINFO = 2337;  \n  CRYPT_CERTINFO_DELTAINFO_LOCATION = 2338;  { deltaLocation }\n  CRYPT_CERTINFO_DELTAINFO_NEXTDELTA = 2339;  { nextDelta }\n  \n  { 2 5 29 54 inhibitAnyPolicy }\n  CRYPT_CERTINFO_INHIBITANYPOLICY = 2340;  \n  \n  { 2 5 29 58 toBeRevoked }\n  CRYPT_CERTINFO_TOBEREVOKED = 2341;  \n  CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER = 2342;  { certificateIssuer }\n  CRYPT_CERTINFO_TOBEREVOKED_REASONCODE = 2343;  { reasonCode }\n  CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME = 2344;  { revocationTime }\n  CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER = 2345;  { certSerialNumber }\n  \n  { 2 5 29 59 revokedGroups }\n  CRYPT_CERTINFO_REVOKEDGROUPS = 2346;  \n  CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER = 2347;  { certificateIssuer }\n  CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE = 2348;  { reasonCode }\n  CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE = 2349;  { invalidityDate }\n  CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER = 2350;  { startingNumber }\n  CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER = 2351;  { endingNumber }\n  \n  { 2 5 29 60 expiredCertsOnCRL }\n  CRYPT_CERTINFO_EXPIREDCERTSONCRL = 2352;  \n  \n  { 2 5 29 63 aaIssuingDistributionPoint }\n  CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT = 2353;  \n  CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME = 2354;  { distributionPointName.fullName }\n  CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY = 2355;  { onlySomeReasons }\n  CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL = 2356;  { indirectCRL }\n  CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS = 2357;  { containsUserAttributeCerts }\n  CRYPT_CERTINFO_AAISSUINGDIST_AACERTS = 2358;  { containsAACerts }\n  CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS = 2359;  { containsSOAPublicKeyCerts }\n  \n  { 2 16 840 1 113730 1 x Netscape extensions }\n  CRYPT_CERTINFO_NS_CERTTYPE = 2360;  { netscape-cert-type }\n  CRYPT_CERTINFO_NS_BASEURL = 2361;  { netscape-base-url }\n  CRYPT_CERTINFO_NS_REVOCATIONURL = 2362;  { netscape-revocation-url }\n  CRYPT_CERTINFO_NS_CAREVOCATIONURL = 2363;  { netscape-ca-revocation-url }\n  CRYPT_CERTINFO_NS_CERTRENEWALURL = 2364;  { netscape-cert-renewal-url }\n  CRYPT_CERTINFO_NS_CAPOLICYURL = 2365;  { netscape-ca-policy-url }\n  CRYPT_CERTINFO_NS_SSLSERVERNAME = 2366;  { netscape-ssl-server-name }\n  CRYPT_CERTINFO_NS_COMMENT = 2367;  { netscape-comment }\n  \n  { 2 23 42 7 0 SET hashedRootKey }\n  CRYPT_CERTINFO_SET_HASHEDROOTKEY = 2368;  \n  CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT = 2369;  { rootKeyThumbPrint }\n  \n  { 2 23 42 7 1 SET certificateType }\n  CRYPT_CERTINFO_SET_CERTIFICATETYPE = 2370;  \n  \n  { 2 23 42 7 2 SET merchantData }\n  CRYPT_CERTINFO_SET_MERCHANTDATA = 2371;  \n  CRYPT_CERTINFO_SET_MERID = 2372;  { merID }\n  CRYPT_CERTINFO_SET_MERACQUIRERBIN = 2373;  { merAcquirerBIN }\n  CRYPT_CERTINFO_SET_MERCHANTLANGUAGE = 2374;  { merNames.language }\n  CRYPT_CERTINFO_SET_MERCHANTNAME = 2375;  { merNames.name }\n  CRYPT_CERTINFO_SET_MERCHANTCITY = 2376;  { merNames.city }\n  CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE = 2377;  { merNames.stateProvince }\n  CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE = 2378;  { merNames.postalCode }\n  CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME = 2379;  { merNames.countryName }\n  CRYPT_CERTINFO_SET_MERCOUNTRY = 2380;  { merCountry }\n  CRYPT_CERTINFO_SET_MERAUTHFLAG = 2381;  { merAuthFlag }\n  \n  { 2 23 42 7 3 SET certCardRequired }\n  CRYPT_CERTINFO_SET_CERTCARDREQUIRED = 2382;  \n  \n  { 2 23 42 7 4 SET tunneling }\n  CRYPT_CERTINFO_SET_TUNNELING = 2383;  \n  CRYPT_CERTINFO_SET_TUNNELLING = 2383; { = CRYPT_CERTINFO_SET_TUNNELING }  \n  CRYPT_CERTINFO_SET_TUNNELINGFLAG = 2384;  { tunneling }\n  CRYPT_CERTINFO_SET_TUNNELLINGFLAG = 2384; { = CRYPT_CERTINFO_SET_TUNNELINGFLAG }  \n  CRYPT_CERTINFO_SET_TUNNELINGALGID = 2385;  { tunnelingAlgID }\n  CRYPT_CERTINFO_SET_TUNNELLINGALGID = 2385; { = CRYPT_CERTINFO_SET_TUNNELINGALGID }  \n  \n  { S/MIME attributes }\n  \n  { 1 2 840 113549 1 9 3 contentType }\n  CRYPT_CERTINFO_CMS_CONTENTTYPE = 2500;  \n  \n  { 1 2 840 113549 1 9 4 messageDigest }\n  CRYPT_CERTINFO_CMS_MESSAGEDIGEST = 2501;  \n  \n  { 1 2 840 113549 1 9 5 signingTime }\n  CRYPT_CERTINFO_CMS_SIGNINGTIME = 2502;  \n  \n  { 1 2 840 113549 1 9 6 counterSignature }\n  CRYPT_CERTINFO_CMS_COUNTERSIGNATURE = 2503;  { counterSignature }\n  \n  { 1 2 840 113549 1 9 13 signingDescription }\n  CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION = 2504;  \n  \n  { 1 2 840 113549 1 9 15 sMIMECapabilities }\n  CRYPT_CERTINFO_CMS_SMIMECAPABILITIES = 2505;  \n  CRYPT_CERTINFO_CMS_SMIMECAP_3DES = 2506;  { 3DES encryption }\n  CRYPT_CERTINFO_CMS_SMIMECAP_AES = 2507;  { AES encryption }\n  CRYPT_CERTINFO_CMS_SMIMECAP_CAST128 = 2508;  { CAST-128 encryption }\n  CRYPT_CERTINFO_CMS_SMIMECAP_SHAng = 2509;  { SHA2-ng hash }\n  CRYPT_CERTINFO_CMS_SMIMECAP_SHA2 = 2510;  { SHA2-256 hash }\n  CRYPT_CERTINFO_CMS_SMIMECAP_SHA1 = 2511;  { SHA1 hash }\n  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng = 2512;  { HMAC-SHA2-ng MAC }\n  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2 = 2513;  { HMAC-SHA2-256 MAC }\n  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1 = 2514;  { HMAC-SHA1 MAC }\n  CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256 = 2515;  { AuthEnc w.256-bit key }\n  CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128 = 2516;  { AuthEnc w.128-bit key }\n  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng = 2517;  { RSA with SHA-ng signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2 = 2518;  { RSA with SHA2-256 signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1 = 2519;  { RSA with SHA1 signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1 = 2520;  { DSA with SHA-1 signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng = 2521;  { ECDSA with SHA-ng signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2 = 2522;  { ECDSA with SHA2-256 signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1 = 2523;  { ECDSA with SHA-1 signing }\n  CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA = 2524;  { preferSignedData }\n  CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY = 2525;  { canNotDecryptAny }\n  CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE = 2526;  { preferBinaryInside }\n  \n  { 1 2 840 113549 1 9 16 2 1 receiptRequest }\n  CRYPT_CERTINFO_CMS_RECEIPTREQUEST = 2527;  \n  CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER = 2528;  { contentIdentifier }\n  CRYPT_CERTINFO_CMS_RECEIPT_FROM = 2529;  { receiptsFrom }\n  CRYPT_CERTINFO_CMS_RECEIPT_TO = 2530;  { receiptsTo }\n  \n  { 1 2 840 113549 1 9 16 2 2 essSecurityLabel }\n  CRYPT_CERTINFO_CMS_SECURITYLABEL = 2531;  \n  CRYPT_CERTINFO_CMS_SECLABEL_POLICY = 2532;  { securityPolicyIdentifier }\n  CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION = 2533;  { securityClassification }\n  CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK = 2534;  { privacyMark }\n  CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE = 2535;  { securityCategories.securityCategory.type }\n  CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE = 2536;  { securityCategories.securityCategory.value }\n  \n  { 1 2 840 113549 1 9 16 2 3 mlExpansionHistory }\n  CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY = 2537;  \n  CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER = 2538;  { mlData.mailListIdentifier.issuerAndSerialNumber }\n  CRYPT_CERTINFO_CMS_MLEXP_TIME = 2539;  { mlData.expansionTime }\n  CRYPT_CERTINFO_CMS_MLEXP_NONE = 2540;  { mlData.mlReceiptPolicy.none }\n  CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF = 2541;  { mlData.mlReceiptPolicy.insteadOf.generalNames.generalName }\n  CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO = 2542;  { mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName }\n  \n  { 1 2 840 113549 1 9 16 2 4 contentHints }\n  CRYPT_CERTINFO_CMS_CONTENTHINTS = 2543;  \n  CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION = 2544;  { contentDescription }\n  CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE = 2545;  { contentType }\n  \n  { 1 2 840 113549 1 9 16 2 9 equivalentLabels }\n  CRYPT_CERTINFO_CMS_EQUIVALENTLABEL = 2546;  \n  CRYPT_CERTINFO_CMS_EQVLABEL_POLICY = 2547;  { securityPolicyIdentifier }\n  CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION = 2548;  { securityClassification }\n  CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK = 2549;  { privacyMark }\n  CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE = 2550;  { securityCategories.securityCategory.type }\n  CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE = 2551;  { securityCategories.securityCategory.value }\n  \n  { 1 2 840 113549 1 9 16 2 12 signingCertificate }\n  CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE = 2552;  \n  CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID = 2553;  { certs.essCertID }\n  CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES = 2554;  { policies.policyInformation.policyIdentifier }\n  \n  { 1 2 840 113549 1 9 16 2 47 signingCertificateV2 }\n  CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2 = 2555;  \n  CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2 = 2556;  { certs.essCertID }\n  CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES = 2557;  { policies.policyInformation.policyIdentifier }\n  \n  { 1 2 840 113549 1 9 16 2 15 signaturePolicyID }\n  CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID = 2558;  \n  CRYPT_CERTINFO_CMS_SIGPOLICYID = 2559;  { sigPolicyID }\n  CRYPT_CERTINFO_CMS_SIGPOLICYHASH = 2560;  { sigPolicyHash }\n  CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI = 2561;  { sigPolicyQualifiers.sigPolicyQualifier.cPSuri }\n  CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION = 2562;  \n  { sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization }\n  CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS = 2563;  \n  { sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers }\n  CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT = 2564;  \n  { sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText }\n  \n  { 1 2 840 113549 1 9 16 9 signatureTypeIdentifier }\n  CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER = 2565;  \n  CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG = 2566;  { originatorSig }\n  CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG = 2567;  { domainSig }\n  CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES = 2568;  { additionalAttributesSig }\n  CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG = 2569;  { reviewSig }\n  \n  { 1 2 840 113549 1 9 25 3 randomNonce }\n  CRYPT_CERTINFO_CMS_NONCE = 2570;  { randomNonce }\n  \n  { SCEP attributes:\n  2 16 840 1 113733 1 9 2 messageType\n  2 16 840 1 113733 1 9 3 pkiStatus\n  2 16 840 1 113733 1 9 4 failInfo\n  2 16 840 1 113733 1 9 5 senderNonce\n  2 16 840 1 113733 1 9 6 recipientNonce\n  2 16 840 1 113733 1 9 7 transID }\n  CRYPT_CERTINFO_SCEP_MESSAGETYPE = 2571;  { messageType }\n  CRYPT_CERTINFO_SCEP_PKISTATUS = 2572;  { pkiStatus }\n  CRYPT_CERTINFO_SCEP_FAILINFO = 2573;  { failInfo }\n  CRYPT_CERTINFO_SCEP_SENDERNONCE = 2574;  { senderNonce }\n  CRYPT_CERTINFO_SCEP_RECIPIENTNONCE = 2575;  { recipientNonce }\n  CRYPT_CERTINFO_SCEP_TRANSACTIONID = 2576;  { transID }\n  \n  { 1 3 6 1 4 1 311 2 1 10 spcAgencyInfo }\n  CRYPT_CERTINFO_CMS_SPCAGENCYINFO = 2577;  \n  CRYPT_CERTINFO_CMS_SPCAGENCYURL = 2578;  { spcAgencyInfo.url }\n  \n  { 1 3 6 1 4 1 311 2 1 11 spcStatementType }\n  CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE = 2579;  \n  CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING = 2580;  { individualCodeSigning }\n  CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING = 2581;  { commercialCodeSigning }\n  \n  { 1 3 6 1 4 1 311 2 1 12 spcOpusInfo }\n  CRYPT_CERTINFO_CMS_SPCOPUSINFO = 2582;  \n  CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME = 2583;  { spcOpusInfo.name }\n  CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL = 2584;  { spcOpusInfo.url }\n  \n  { Used internally }\n  CRYPT_CERTINFO_LAST = 2585;  CRYPT_KEYINFO_FIRST = 3000;  \n  \n  {*******************}\n  { Keyset attributes }\n  {*******************}\n  \n  CRYPT_KEYINFO_QUERY = 3001;  { Keyset query }\n  CRYPT_KEYINFO_QUERY_REQUESTS = 3002;  { Query of requests in cert store }\n  \n  { Used internally }\n  CRYPT_KEYINFO_LAST = 3003;  CRYPT_DEVINFO_FIRST = 4000;  \n  \n  {*******************}\n  { Device attributes }\n  {*******************}\n  \n  CRYPT_DEVINFO_INITIALISE = 4001;  { Initialise device for use }\n  CRYPT_DEVINFO_INITIALIZE = 4001; { = CRYPT_DEVINFO_INITIALISE }  \n  CRYPT_DEVINFO_AUTHENT_USER = 4002;  { Authenticate user to device }\n  CRYPT_DEVINFO_AUTHENT_SUPERVISOR = 4003;  { Authenticate supervisor to dev.}\n  CRYPT_DEVINFO_SET_AUTHENT_USER = 4004;  { Set user authent.value }\n  CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR = 4005;  { Set supervisor auth.val.}\n  CRYPT_DEVINFO_ZEROISE = 4006;  { Zeroise device }\n  CRYPT_DEVINFO_ZEROIZE = 4006; { = CRYPT_DEVINFO_ZEROISE }  \n  CRYPT_DEVINFO_LOGGEDIN = 4007;  { Whether user is logged in }\n  CRYPT_DEVINFO_LABEL = 4008;  { Device/token label }\n  \n  { Used internally }\n  CRYPT_DEVINFO_LAST = 4009;  CRYPT_ENVINFO_FIRST = 5000;  \n  \n  {*********************}\n  { Envelope attributes }\n  {*********************}\n  \n  { Pseudo-information on an envelope or meta-information which is used to\n  control the way that data in an envelope is processed }\n  CRYPT_ENVINFO_DATASIZE = 5001;  { Data size information }\n  CRYPT_ENVINFO_COMPRESSION = 5002;  { Compression information }\n  CRYPT_ENVINFO_CONTENTTYPE = 5003;  { Inner CMS content type }\n  CRYPT_ENVINFO_DETACHEDSIGNATURE = 5004;  { Detached signature }\n  CRYPT_ENVINFO_SIGNATURE_RESULT = 5005;  { Signature check result }\n  CRYPT_ENVINFO_INTEGRITY = 5006;  { Integrity-protection level }\n  \n  { Resources required for enveloping/deenveloping }\n  CRYPT_ENVINFO_PASSWORD = 5007;  { User password }\n  CRYPT_ENVINFO_KEY = 5008;  { Conventional encryption key }\n  CRYPT_ENVINFO_SIGNATURE = 5009;  { Signature/signature check key }\n  CRYPT_ENVINFO_SIGNATURE_EXTRADATA = 5010;  { Extra information added to CMS sigs }\n  CRYPT_ENVINFO_RECIPIENT = 5011;  { Recipient email address }\n  CRYPT_ENVINFO_PUBLICKEY = 5012;  { PKC encryption key }\n  CRYPT_ENVINFO_PRIVATEKEY = 5013;  { PKC decryption key }\n  CRYPT_ENVINFO_PRIVATEKEY_LABEL = 5014;  { Label of PKC decryption key }\n  CRYPT_ENVINFO_ORIGINATOR = 5015;  { Originator info/key }\n  CRYPT_ENVINFO_SESSIONKEY = 5016;  { Session key }\n  CRYPT_ENVINFO_HASH = 5017;  { Hash value }\n  CRYPT_ENVINFO_TIMESTAMP = 5018;  { Timestamp information }\n  \n  { Keysets used to retrieve keys needed for enveloping/deenveloping }\n  CRYPT_ENVINFO_KEYSET_SIGCHECK = 5019;  { Signature check keyset }\n  CRYPT_ENVINFO_KEYSET_ENCRYPT = 5020;  { PKC encryption keyset }\n  CRYPT_ENVINFO_KEYSET_DECRYPT = 5021;  { PKC decryption keyset }\n  \n  { Used internally }\n  CRYPT_ENVINFO_LAST = 5022;  CRYPT_SESSINFO_FIRST = 6000;  \n  \n  {********************}\n  { Session attributes }\n  {********************}\n  \n  { Pseudo-information about the session }\n  CRYPT_SESSINFO_ACTIVE = 6001;  { Whether session is active }\n  CRYPT_SESSINFO_CONNECTIONACTIVE = 6002;  { Whether network connection is active }\n  \n  { Security-related information }\n  CRYPT_SESSINFO_USERNAME = 6003;  { User name }\n  CRYPT_SESSINFO_PASSWORD = 6004;  { Password }\n  CRYPT_SESSINFO_PRIVATEKEY = 6005;  { Server/client private key }\n  CRYPT_SESSINFO_KEYSET = 6006;  { Certificate store }\n  CRYPT_SESSINFO_AUTHRESPONSE = 6007;  { Session authorisation OK }\n  \n  { Client/server information }\n  CRYPT_SESSINFO_SERVER_NAME = 6008;  { Server name }\n  CRYPT_SESSINFO_SERVER_PORT = 6009;  { Server port number }\n  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 = 6010;  { Server key fingerprint }\n  CRYPT_SESSINFO_CLIENT_NAME = 6011;  { Client name }\n  CRYPT_SESSINFO_CLIENT_PORT = 6012;  { Client port number }\n  CRYPT_SESSINFO_SESSION = 6013;  { Transport mechanism }\n  CRYPT_SESSINFO_NETWORKSOCKET = 6014;  { User-supplied network socket }\n  \n  { Generic protocol-related information }\n  CRYPT_SESSINFO_VERSION = 6015;  { Protocol version }\n  CRYPT_SESSINFO_REQUEST = 6016;  { Cert.request object }\n  CRYPT_SESSINFO_RESPONSE = 6017;  { Cert.response object }\n  CRYPT_SESSINFO_CACERTIFICATE = 6018;  { Issuing CA certificate }\n  \n  { Protocol-specific information }\n  CRYPT_SESSINFO_CMP_REQUESTTYPE = 6019;  { Request type }\n  CRYPT_SESSINFO_CMP_PRIVKEYSET = 6020;  { Private-key keyset }\n  CRYPT_SESSINFO_SSH_CHANNEL = 6021;  { SSH current channel }\n  CRYPT_SESSINFO_SSH_CHANNEL_TYPE = 6022;  { SSH channel type }\n  CRYPT_SESSINFO_SSH_CHANNEL_ARG1 = 6023;  { SSH channel argument 1 }\n  CRYPT_SESSINFO_SSH_CHANNEL_ARG2 = 6024;  { SSH channel argument 2 }\n  CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE = 6025;  { SSH channel active }\n  CRYPT_SESSINFO_SSL_OPTIONS = 6026;  { SSL/TLS protocol options }\n  CRYPT_SESSINFO_SSL_SUBPROTOCOL = 6027;  { SSL/TLS additional sub-protocol }\n  CRYPT_SESSINFO_SSL_WSPROTOCOL = 6028;  { SSL/TLS WebSockets sub-protocol }\n  CRYPT_SESSINFO_SSL_EAPCHALLENGE = 6029;  { SSL/TLS EAP challenge }\n  CRYPT_SESSINFO_SSL_EAPKEY = 6030;  { SSL/TLS EAP key }\n  CRYPT_SESSINFO_TSP_MSGIMPRINT = 6031;  { TSP message imprint }\n  \n  { Used internally }\n  CRYPT_SESSINFO_LAST = 6032;  CRYPT_USERINFO_FIRST = 7000;  \n  \n  {********************}\n  { User attributes }\n  {********************}\n  \n  { Security-related information }\n  CRYPT_USERINFO_PASSWORD = 7001;  { Password }\n  \n  { User role-related information }\n  CRYPT_USERINFO_CAKEY_CERTSIGN = 7002;  { CA cert signing key }\n  CRYPT_USERINFO_CAKEY_CRLSIGN = 7003;  { CA CRL signing key }\n  CRYPT_USERINFO_CAKEY_RTCSSIGN = 7004;  { CA RTCS signing key }\n  CRYPT_USERINFO_CAKEY_OCSPSIGN = 7005;  { CA OCSP signing key }\n  \n  { Used internally for range checking }\n  CRYPT_USERINFO_LAST = 7006;  CRYPT_ATTRIBUTE_LAST = 7006; { = CRYPT_USERINFO_LAST }  \n  \n  \n\n\n\n{****************************************************************************\n*                                                                           *\n*                       Attribute Subtypes and Related Values               *\n*                                                                           *\n****************************************************************************}\n\n{  Flags for the X.509 keyUsage extension  }\n\n  CRYPT_KEYUSAGE_NONE = $000;\n  CRYPT_KEYUSAGE_DIGITALSIGNATURE = $001;\n  CRYPT_KEYUSAGE_NONREPUDIATION = $002;\n  CRYPT_KEYUSAGE_KEYENCIPHERMENT = $004;\n  CRYPT_KEYUSAGE_DATAENCIPHERMENT = $008;\n  CRYPT_KEYUSAGE_KEYAGREEMENT = $010;\n  CRYPT_KEYUSAGE_KEYCERTSIGN = $020;\n  CRYPT_KEYUSAGE_CRLSIGN = $040;\n  CRYPT_KEYUSAGE_ENCIPHERONLY = $080;\n  CRYPT_KEYUSAGE_DECIPHERONLY = $100;\n  CRYPT_KEYUSAGE_LAST = $200;   {  Last possible value  }\n\n{  X.509 cRLReason and cryptlib cRLExtReason codes  }\n\n\n  CRYPT_CRLREASON_UNSPECIFIED = 0;\n  CRYPT_CRLREASON_KEYCOMPROMISE = 1;\n  CRYPT_CRLREASON_CACOMPROMISE = 2;\n  CRYPT_CRLREASON_AFFILIATIONCHANGED = 3;\n  CRYPT_CRLREASON_SUPERSEDED = 4;\n  CRYPT_CRLREASON_CESSATIONOFOPERATION = 5;\n  CRYPT_CRLREASON_CERTIFICATEHOLD = 6;\n  CRYPT_CRLREASON_REMOVEFROMCRL = 8;\n  CRYPT_CRLREASON_PRIVILEGEWITHDRAWN = 9;\n  CRYPT_CRLREASON_AACOMPROMISE = 10;\n  CRYPT_CRLREASON_LAST = 11;\n  { End of standard CRL reasons }\n       CRYPT_CRLREASON_NEVERVALID = 20;\n  CRYPT_CRLEXTREASON_LAST  = 21;\n\n\n\n{  X.509 CRL reason flags.  These identify the same thing as the cRLReason\n   codes but allow for multiple reasons to be specified.  Note that these\n   don't follow the X.509 naming since in that scheme the enumerated types\n   and bitflags have the same names  }\n\n  CRYPT_CRLREASONFLAG_UNUSED = $001;\n  CRYPT_CRLREASONFLAG_KEYCOMPROMISE = $002;\n  CRYPT_CRLREASONFLAG_CACOMPROMISE = $004;\n  CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED = $008;\n  CRYPT_CRLREASONFLAG_SUPERSEDED = $010;\n  CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION = $020;\n  CRYPT_CRLREASONFLAG_CERTIFICATEHOLD = $040;\n  CRYPT_CRLREASONFLAG_LAST = $080;   {  Last poss.value  }\n\n{  X.509 CRL holdInstruction codes  }\n\n\n  CRYPT_HOLDINSTRUCTION_NONE = 0;\n  CRYPT_HOLDINSTRUCTION_CALLISSUER = 1;\n  CRYPT_HOLDINSTRUCTION_REJECT = 2;\n  CRYPT_HOLDINSTRUCTION_PICKUPTOKEN = 3;\n  CRYPT_HOLDINSTRUCTION_LAST  = 4;\n\n\n\n{  Certificate checking compliance levels  }\n\n\ntype\n  CRYPT_COMPLIANCELEVEL_TYPE = (   \n    CRYPT_COMPLIANCELEVEL_OBLIVIOUS, CRYPT_COMPLIANCELEVEL_REDUCED,\n    CRYPT_COMPLIANCELEVEL_STANDARD, CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL,\n    CRYPT_COMPLIANCELEVEL_PKIX_FULL, CRYPT_COMPLIANCELEVEL_LAST \n    \n  );\n\n{  Flags for the Netscape netscape-cert-type extension  }\n\n\nconst\n  CRYPT_NS_CERTTYPE_SSLCLIENT = $001;\n  CRYPT_NS_CERTTYPE_SSLSERVER = $002;\n  CRYPT_NS_CERTTYPE_SMIME = $004;\n  CRYPT_NS_CERTTYPE_OBJECTSIGNING = $008;\n  CRYPT_NS_CERTTYPE_RESERVED = $010;\n  CRYPT_NS_CERTTYPE_SSLCA = $020;\n  CRYPT_NS_CERTTYPE_SMIMECA = $040;\n  CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA = $080;\n  CRYPT_NS_CERTTYPE_LAST = $100;   {  Last possible value  }\n\n{  Flags for the SET certificate-type extension  }\n\n  CRYPT_SET_CERTTYPE_CARD = $001;\n  CRYPT_SET_CERTTYPE_MER = $002;\n  CRYPT_SET_CERTTYPE_PGWY = $004;\n  CRYPT_SET_CERTTYPE_CCA = $008;\n  CRYPT_SET_CERTTYPE_MCA = $010;\n  CRYPT_SET_CERTTYPE_PCA = $020;\n  CRYPT_SET_CERTTYPE_GCA = $040;\n  CRYPT_SET_CERTTYPE_BCA = $080;\n  CRYPT_SET_CERTTYPE_RCA = $100;\n  CRYPT_SET_CERTTYPE_ACQ = $200;\n  CRYPT_SET_CERTTYPE_LAST = $400;   {  Last possible value  }\n\n{  CMS contentType values  }\n\n\ntype\n  CRYPT_CONTENT_TYPE = (   CRYPT_CONTENT_NONE, CRYPT_CONTENT_DATA,\n               CRYPT_CONTENT_SIGNEDDATA, CRYPT_CONTENT_ENVELOPEDDATA,\n               CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA,\n               CRYPT_CONTENT_DIGESTEDDATA, CRYPT_CONTENT_ENCRYPTEDDATA,\n               CRYPT_CONTENT_COMPRESSEDDATA, CRYPT_CONTENT_AUTHDATA, \n               CRYPT_CONTENT_AUTHENVDATA, CRYPT_CONTENT_TSTINFO,\n               CRYPT_CONTENT_SPCINDIRECTDATACONTEXT,\n               CRYPT_CONTENT_RTCSREQUEST, CRYPT_CONTENT_RTCSRESPONSE,\n               CRYPT_CONTENT_RTCSRESPONSE_EXT, CRYPT_CONTENT_MRTD, \n               CRYPT_CONTENT_LAST\n             \n  );\n\n{  ESS securityClassification codes  }\n\n\n\nconst\n  CRYPT_CLASSIFICATION_UNMARKED = 0;\n  CRYPT_CLASSIFICATION_UNCLASSIFIED = 1;\n  CRYPT_CLASSIFICATION_RESTRICTED = 2;\n  CRYPT_CLASSIFICATION_CONFIDENTIAL = 3;\n  CRYPT_CLASSIFICATION_SECRET = 4;\n  CRYPT_CLASSIFICATION_TOP_SECRET = 5;\n  CRYPT_CLASSIFICATION_LAST = 255 ;\n\n\n\n{  RTCS certificate status  }\n\n\ntype\n  CRYPT_CERTSTATUS_TYPE = (   \n    CRYPT_CERTSTATUS_NONE,          {  No certificate status  }\n    CRYPT_CERTSTATUS_VALID,         {  Certificate valid  }\n    CRYPT_CERTSTATUS_NOTVALID,      {  Certificate isn't valid  }\n    CRYPT_CERTSTATUS_NONAUTHORITATIVE, {  Response is non-authoritative  }\n    CRYPT_CERTSTATUS_UNKNOWN,       {  Certificate status unknown  }\n    CRYPT_CERTSTATUS_LAST           {  Last possible certificate status  }\n    \n  );\n\n{  OCSP revocation status  }\n\n\n\nconst\n  CRYPT_OCSPSTATUS_NOTREVOKED = 0;\n  CRYPT_OCSPSTATUS_REVOKED = 1;\n  CRYPT_OCSPSTATUS_UNKNOWN  = 2;\n\n\n\n{  The amount of detail to include in signatures when signing certificate\n   objects  }\n\n\ntype\n  CRYPT_SIGNATURELEVEL_TYPE = (  \n    CRYPT_SIGNATURELEVEL_NONE,      {  Include only signature  }\n    CRYPT_SIGNATURELEVEL_SIGNERCERT,{  Include signer cert  }\n    CRYPT_SIGNATURELEVEL_ALL,       {  Include all relevant info  }\n    CRYPT_SIGNATURELEVEL_LAST       {  Last possible sig.level type  }\n    \n  );\n\n{  The level of integrity protection to apply to enveloped data.  The \n   default envelope protection for an envelope with keying information \n   applied is encryption, this can be modified to use MAC-only protection\n   (with no encryption) or hybrid encryption + authentication  }\n\n  CRYPT_INTEGRITY_TYPE = (  \n    CRYPT_INTEGRITY_NONE,           {  No integrity protection  }\n    CRYPT_INTEGRITY_MACONLY,        {  MAC only, no encryption  }\n    CRYPT_INTEGRITY_FULL            {  Encryption + ingerity protection  }\n    \n  );\n\n{  The certificate export format type, which defines the format in which a\n   certificate object is exported  }\n\n  CRYPT_CERTFORMAT_TYPE = (  \n    CRYPT_CERTFORMAT_NONE,          {  No certificate format  }\n    CRYPT_CERTFORMAT_CERTIFICATE,   {  DER-encoded certificate  }\n    CRYPT_CERTFORMAT_CERTCHAIN,     {  PKCS #7 certificate chain  }\n    CRYPT_CERTFORMAT_TEXT_CERTIFICATE,  {  base-64 wrapped cert  }\n    CRYPT_CERTFORMAT_TEXT_CERTCHAIN,    {  base-64 wrapped cert chain  }\n    CRYPT_CERTFORMAT_XML_CERTIFICATE,   {  XML wrapped cert  }\n    CRYPT_CERTFORMAT_XML_CERTCHAIN, {  XML wrapped cert chain  }\n    CRYPT_CERTFORMAT_LAST           {  Last possible cert.format type  }\n    \n  );\n\n{  CMP request types  }\n\n  CRYPT_REQUESTTYPE_TYPE = (  \n    CRYPT_REQUESTTYPE_NONE,         {  No request type  }\n    CRYPT_REQUESTTYPE_INITIALISATION,   {  Initialisation request  }\n    CRYPT_REQUESTTYPE_CERTIFICATE,  {  Certification request  }\n    CRYPT_REQUESTTYPE_KEYUPDATE,    {  Key update request  }\n    CRYPT_REQUESTTYPE_REVOCATION,   {  Cert revocation request  }\n    CRYPT_REQUESTTYPE_PKIBOOT,      {  PKIBoot request  }\n    CRYPT_REQUESTTYPE_LAST          {  Last possible request type  }\n    \n  );\n\nconst\n  CRYPT_REQUESTTYPE_INITIALIZATION: CRYPT_REQUESTTYPE_TYPE = CRYPT_REQUESTTYPE_INITIALISATION;\n\n{  Key ID types  }\n\n\ntype\n  CRYPT_KEYID_TYPE = (  \n    CRYPT_KEYID_NONE,               {  No key ID type  }\n    CRYPT_KEYID_NAME,               {  Key owner name  }\n    CRYPT_KEYID_URI,                {  Key owner URI  } {  Synonym: owner email addr.}\n    CRYPT_KEYID_LAST                {  Last possible key ID type  }\n    \n  );\n\nconst\n  CRYPT_KEYID_EMAIL: CRYPT_KEYID_TYPE = CRYPT_KEYID_URI;\n\n{  The encryption object types  }\n\n\ntype\n  CRYPT_OBJECT_TYPE = (  \n    CRYPT_OBJECT_NONE,              {  No object type  }\n    CRYPT_OBJECT_ENCRYPTED_KEY,     {  Conventionally encrypted key  }\n    CRYPT_OBJECT_PKCENCRYPTED_KEY,  {  PKC-encrypted key  }\n    CRYPT_OBJECT_KEYAGREEMENT,      {  Key agreement information  }\n    CRYPT_OBJECT_SIGNATURE,         {  Signature  }\n    CRYPT_OBJECT_LAST               {  Last possible object type  }\n    \n  );\n\n{  Object/attribute error type information  }\n\n  CRYPT_ERRTYPE_TYPE = (  \n    CRYPT_ERRTYPE_NONE,             {  No error information  }\n    CRYPT_ERRTYPE_ATTR_SIZE,        {  Attribute data too small or large  }\n    CRYPT_ERRTYPE_ATTR_VALUE,       {  Attribute value is invalid  }\n    CRYPT_ERRTYPE_ATTR_ABSENT,      {  Required attribute missing  }\n    CRYPT_ERRTYPE_ATTR_PRESENT,     {  Non-allowed attribute present  }\n    CRYPT_ERRTYPE_CONSTRAINT,       {  Cert: Constraint violation in object  }\n    CRYPT_ERRTYPE_ISSUERCONSTRAINT, {  Cert: Constraint viol.in issuing cert  }\n    CRYPT_ERRTYPE_LAST              {  Last possible error info type  }\n    \n  );\n\n{  Cert store management action type  }\n\n  CRYPT_CERTACTION_TYPE = (  \n    CRYPT_CERTACTION_NONE,          {  No cert management action  }\n    CRYPT_CERTACTION_CREATE,        {  Create cert store  }\n    CRYPT_CERTACTION_CONNECT,       {  Connect to cert store  }\n    CRYPT_CERTACTION_DISCONNECT,    {  Disconnect from cert store  }\n    CRYPT_CERTACTION_ERROR,         {  Error information  }\n    CRYPT_CERTACTION_ADDUSER,       {  Add PKI user  }\n    CRYPT_CERTACTION_DELETEUSER,    {  Delete PKI user  }\n    CRYPT_CERTACTION_REQUEST_CERT,  {  Cert request  }\n    CRYPT_CERTACTION_REQUEST_RENEWAL,{  Cert renewal request  }\n    CRYPT_CERTACTION_REQUEST_REVOCATION,{  Cert revocation request  }\n    CRYPT_CERTACTION_CERT_CREATION, {  Cert creation  }\n    CRYPT_CERTACTION_CERT_CREATION_COMPLETE,{  Confirmation of cert creation  }\n    CRYPT_CERTACTION_CERT_CREATION_DROP,    {  Cancellation of cert creation  }\n    CRYPT_CERTACTION_CERT_CREATION_REVERSE, {  Cancel of creation w.revocation  }\n    CRYPT_CERTACTION_RESTART_CLEANUP, {  Delete reqs after restart  }\n    CRYPT_CERTACTION_RESTART_REVOKE_CERT, {  Complete revocation after restart  }\n    CRYPT_CERTACTION_ISSUE_CERT,    {  Cert issue  }\n    CRYPT_CERTACTION_ISSUE_CRL,     {  CRL issue  }\n    CRYPT_CERTACTION_REVOKE_CERT,   {  Cert revocation  }\n    CRYPT_CERTACTION_EXPIRE_CERT,   {  Cert expiry  }\n    CRYPT_CERTACTION_CLEANUP,       {  Clean up on restart  }\n    CRYPT_CERTACTION_LAST           {  Last possible cert store log action  }\n    \n  );\n\n{  Session sub-protocol types  }\n\n  CRYPT_SUBPROTOCOL_TYPE = (  \n    CRYPT_SUBPROTOCOL_NONE,         {  No sub-protocol type  }\n    CRYPT_SUBPROTOCOL_WEBSOCKETS,   {  Websockets  }\n    CRYPT_SUBPROTOCOL_EAPTTLS,      {  EAP-TTLS  }\n    CRYPT_SUBPROTOCOL_LAST          {  Last possible sub-protocol type  }\n    \n  );\n\n{  SSL/TLS protocol options.  CRYPT_SSLOPTION_MINVER_SSLV3 is the same as \n   CRYPT_SSLOPTION_NONE since this is the baseline, although it'll never be\n   encountered since SSLv3 is disabled  }\n\n\nconst\n  CRYPT_SSLOPTION_NONE = $000;\n  CRYPT_SSLOPTION_MINVER_SSLV3 = $000;   {  Min.protocol version  }\n  CRYPT_SSLOPTION_MINVER_TLS10 = $001;\n  CRYPT_SSLOPTION_MINVER_TLS11 = $002;\n  CRYPT_SSLOPTION_MINVER_TLS12 = $003;\n  CRYPT_SSLOPTION_MINVER_TLS13 = $004;\n  CRYPT_SSLOPTION_MANUAL_CERTCHECK = $008;   {  Require manual cert.verif.}\n  CRYPT_SSLOPTION_DISABLE_NAMEVERIFY = $010;   {  Disable cert hostname check  }\n  CRYPT_SSLOPTION_DISABLE_CERTVERIFY = $020;   {  Disable certificate check  }\n  CRYPT_SSLOPTION_SUITEB_128 = $100;   {  SuiteB security levels (may  }\n  CRYPT_SSLOPTION_SUITEB_256 = $200;   {   vanish in future releases)  }\n\n{****************************************************************************\n*                                                                           *\n*                               General Constants                           *\n*                                                                           *\n****************************************************************************}\n\n{  The maximum user key size - 2048 bits  }\n\n  CRYPT_MAX_KEYSIZE = 256;\n\n{  The maximum IV/cipher block size - 256 bits  }\n\n  CRYPT_MAX_IVSIZE = 32;\n\n{  The maximum public-key component size - 4096 bits, and maximum component\n   size for ECCs - 576 bits (to handle the P521 curve)  }\n\n  CRYPT_MAX_PKCSIZE = 512;\n  CRYPT_MAX_PKCSIZE_ECC = 72;\n\n{  The maximum hash size - 512 bits.  Before 3.4 this was 256 bits, in the \n   3.4 release it was increased to 512 bits to accommodate SHA-3  }\n\n  CRYPT_MAX_HASHSIZE = 64;\n\n{  The maximum size of a text string (e.g.key owner name)  }\n\n  CRYPT_MAX_TEXTSIZE = 64;\n\n{  A magic value indicating that the default setting for this parameter\n   should be used.  The parentheses are to catch potential erroneous use \n   in an expression  }\n\n  CRYPT_USE_DEFAULT = -100;\n\n{  A magic value for unused parameters  }\n\n  CRYPT_UNUSED = -101;\n\n{  Cursor positioning codes for certificate/CRL extensions.  The parentheses \n   are to catch potential erroneous use in an expression  }\n\n  CRYPT_CURSOR_FIRST = -200;\n  CRYPT_CURSOR_PREVIOUS = -201;\n  CRYPT_CURSOR_NEXT = -202;\n  CRYPT_CURSOR_LAST = -203;\n\n{  The type of information polling to perform to get random seed \n   information.  These values have to be negative because they're used\n   as magic length values for cryptAddRandom().  The parentheses are to \n   catch potential erroneous use in an expression  }\n\n  CRYPT_RANDOM_FASTPOLL = -300;\n  CRYPT_RANDOM_SLOWPOLL = -301;\n\n{  Whether the PKC key is a public or private key  }\n\n  CRYPT_KEYTYPE_PRIVATE = 0;\n  CRYPT_KEYTYPE_PUBLIC = 1;\n\n{  Keyset open options  }\n\n\ntype\n  CRYPT_KEYOPT_TYPE = (  \n    CRYPT_KEYOPT_NONE,              {  No options  }\n    CRYPT_KEYOPT_READONLY,          {  Open keyset in read-only mode  }\n    CRYPT_KEYOPT_CREATE,            {  Create a new keyset  }\n    CRYPT_KEYOPT_LAST               {  Last possible key option type  }\n    \n  );\n\n{  The various cryptlib objects - these are just integer handles  }\n\n  CRYPT_CERTIFICATE = Integer;\n  CRYPT_CONTEXT = Integer;\n  CRYPT_DEVICE = Integer;\n  CRYPT_ENVELOPE = Integer;\n  CRYPT_KEYSET = Integer;\n  CRYPT_SESSION = Integer;\n  CRYPT_USER = Integer;\n\n{  Sometimes we don't know the exact type of a cryptlib object, so we use a\n   generic handle type to identify it  }\n\n  CRYPT_HANDLE = Integer;\n\n{****************************************************************************\n*                                                                           *\n*                           Encryption Data Structures                      *\n*                                                                           *\n****************************************************************************}\n\n{  Results returned from the capability query  }\n\n  CRYPT_QUERY_INFO = record  \n    { Algorithm information }\n    algoName: array[0 .. CRYPT_MAX_TEXTSIZE-1] of char;{ Algorithm name }\n    blockSize: Integer;                  { Block size of the algorithm }\n    minKeySize: Integer;                 { Minimum key size in bytes }\n    keySize: Integer;                    { Recommended key size in bytes }\n    maxKeySize: Integer;                 { Maximum key size in bytes }\n    \n\n  end;\n\n{  Results returned from the encoded object query.  These provide\n   information on the objects created by cryptExportKey()/\n   cryptCreateSignature()  }\n\n  CRYPT_OBJECT_INFO = record  \n    { The object type }\n    objectType: CRYPT_OBJECT_TYPE;\n\n    { The encryption algorithm and mode }\n    cryptAlgo: CRYPT_ALGO_TYPE;\n    cryptMode: CRYPT_MODE_TYPE;\n\n    { The hash algorithm for signature objects or PRF algorithm for derived \n       keys }\n    hashAlgo: CRYPT_ALGO_TYPE;\n\n    { The salt and PRF iterations for derived keys }\n    salt: array[0 .. CRYPT_MAX_HASHSIZE-1] of byte;\n    saltSize: Integer;\n    iterations: Integer;\n    \n\n  end;\n\n{  Key information for the public-key encryption algorithms.  These fields\n   are not accessed directly, but can be manipulated with the init/set/\n   destroyComponents() macros  }\n\n  CRYPT_PKCINFO_RSA = record  \n    { Status information }\n    isPublicKey: Integer;            { Whether this is a public or private key  }\n\n    {  Public components }\n    n: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Modulus }\n    nLen: Integer;                   { Length of modulus in bits }\n    e: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Public exponent }\n    eLen: Integer;                   { Length of public exponent in bits  }\n\n    {  Private components }\n    d: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Private exponent }\n    dLen: Integer;                   { Length of private exponent in bits }\n    p: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Prime factor 1 }\n    pLen: Integer;                   { Length of prime factor 1 in bits }\n    q: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Prime factor 2 }\n    qLen: Integer;                   { Length of prime factor 2 in bits }\n    u: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Mult.inverse of q, mod p }\n    uLen: Integer;                   { Length of private exponent in bits }\n    e1: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;  { Private exponent 1 (PKCS) }\n    e1Len: Integer;                  { Length of private exponent in bits }\n    e2: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;  { Private exponent 2 (PKCS) }\n    e2Len: Integer;                  { Length of private exponent in bits }\n    \n\n  end;\n\n  CRYPT_PKCINFO_DLP = record  \n    { Status information }\n    isPublicKey: Integer;            { Whether this is a public or private key  }\n\n    {  Public components }\n    p: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Prime modulus }\n    pLen: Integer;                   { Length of prime modulus in bits }\n    q: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Prime divisor }\n    qLen: Integer;                   { Length of prime divisor in bits }\n    g: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { h^( ( p - 1 ) / q ) mod p }\n    gLen: Integer;                   { Length of g in bits }\n    y: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Public random integer }\n    yLen: Integer;                   { Length of public integer in bits  }\n\n    {  Private components }\n    x: array[0 .. CRYPT_MAX_PKCSIZE-1] of byte;   { Private random integer }\n    xLen: Integer;                   { Length of private integer in bits }\n    \n\n  end;\n\n  CRYPT_ECCCURVE_TYPE = (  \n    {  Named ECC curves.  Since these need to be mapped to all manner of\n       protocol- and mechanism-specific identifiers, when updating this list \n       grep for occurrences of the string \"P256\" (the most common one) and \n       check whether any related mapping tables need to be updated  }\n    CRYPT_ECCCURVE_NONE,        {  No ECC curve type  }\n    CRYPT_ECCCURVE_P256,        {  NIST P256/X9.62 P256v1/SECG p256r1 curve  }\n    CRYPT_ECCCURVE_P384,        {  NIST P384, SECG p384r1 curve  }\n    CRYPT_ECCCURVE_P521,        {  NIST P521, SECG p521r1  }\n    CRYPT_ECCCURVE_BRAINPOOL_P256, {  Brainpool p256r1  }\n    CRYPT_ECCCURVE_BRAINPOOL_P384, {  Brainpool p384r1  }\n    CRYPT_ECCCURVE_BRAINPOOL_P512, {  Brainpool p512r1  }\n    CRYPT_ECCCURVE_LAST         {  Last valid ECC curve type  }\n    \n  );\n\n  CRYPT_PKCINFO_ECC = record  \n    { Status information }\n    isPublicKey: Integer;            { Whether this is a public or private key  }\n\n    {  Curve domain parameters.  Either the curveType or the explicit domain\n       parameters must be provided }\n    curveType: CRYPT_ECCCURVE_TYPE;  { Named curve }\n    p: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Prime defining Fq }\n    pLen: Integer;                   { Length of prime in bits }\n    a: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Element in Fq defining curve }\n    aLen: Integer;                   { Length of element a in bits }\n    b: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Element in Fq defining curve }\n    bLen: Integer;                   { Length of element b in bits }\n    gx: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Element in Fq defining point }\n    gxLen: Integer;                  { Length of element gx in bits }\n    gy: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Element in Fq defining point }\n    gyLen: Integer;                  { Length of element gy in bits }\n    n: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Order of point }\n    nLen: Integer;                   { Length of order in bits }\n    h: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Optional cofactor }\n    hLen: Integer;                   { Length of cofactor in bits  }\n\n    {  Public components }\n    qx: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Point Q on the curve }\n    qxLen: Integer;                  { Length of point xq in bits }\n    qy: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Point Q on the curve }\n    qyLen: Integer;                  { Length of point xy in bits  }\n\n    {  Private components }\n    d: array[0 .. CRYPT_MAX_PKCSIZE_ECC-1] of byte;{ Private random integer }\n    dLen: Integer;                   { Length of integer in bits }\n    \n\n  end;\n\n{  Macros to initialise and destroy the structure that stores the components\n   of a public key  }\n\n{ C-macro not translated to Delphi code: \n{   #define cryptInitComponents( componentInfo, componentKeyType ) \n    < memset( ( componentInfo ), 0, sizeof( *componentInfo ) ); \n      ( componentInfo )->isPublicKey = ( ( componentKeyType ) ? 1 : 0 ); > }\n\n{ C-macro not translated to Delphi code: \n{   #define cryptDestroyComponents( componentInfo ) \n    memset( ( componentInfo ), 0, sizeof( *componentInfo ) ) }\n\n{  Macros to set a component of a public key  }\n\n{ C-macro not translated to Delphi code: \n{   #define cryptSetComponent( destination, source, length ) \n    < memcpy( ( destination ), ( source ), ( ( length ) + 7 ) >> 3 ); \n      ( destination##Len ) = length; > }\n\n{****************************************************************************\n*                                                                           *\n*                               Status Codes                                *\n*                                                                           *\n****************************************************************************}\n\n{  No error in function call  }\n\n\nconst\n  CRYPT_OK = 0;       {  No error  }\n\n{  Error in parameters passed to function.  The parentheses are to catch \n   potential erroneous use in an expression  }\n\n  CRYPT_ERROR_PARAM1 = -1;  {  Bad argument, parameter 1  }\n  CRYPT_ERROR_PARAM2 = -2;  {  Bad argument, parameter 2  }\n  CRYPT_ERROR_PARAM3 = -3;  {  Bad argument, parameter 3  }\n  CRYPT_ERROR_PARAM4 = -4;  {  Bad argument, parameter 4  }\n  CRYPT_ERROR_PARAM5 = -5;  {  Bad argument, parameter 5  }\n  CRYPT_ERROR_PARAM6 = -6;  {  Bad argument, parameter 6  }\n  CRYPT_ERROR_PARAM7 = -7;  {  Bad argument, parameter 7  }\n\n{  Errors due to insufficient resources  }\n\n  CRYPT_ERROR_MEMORY = -10; {  Out of memory  }\n  CRYPT_ERROR_NOTINITED = -11; {  Data has not been initialised  }\n  CRYPT_ERROR_INITED = -12; {  Data has already been init'd  }\n  CRYPT_ERROR_NOSECURE = -13; {  Opn.not avail.at requested sec.level  }\n  CRYPT_ERROR_RANDOM = -14; {  No reliable random data available  }\n  CRYPT_ERROR_FAILED = -15; {  Operation failed  }\n  CRYPT_ERROR_INTERNAL = -16; {  Internal consistency check failed  }\n\n{  Security violations  }\n\n  CRYPT_ERROR_NOTAVAIL = -20; {  This type of opn.not available  }\n  CRYPT_ERROR_PERMISSION = -21; {  No permiss.to perform this operation  }\n  CRYPT_ERROR_WRONGKEY = -22; {  Incorrect key used to decrypt data  }\n  CRYPT_ERROR_INCOMPLETE = -23; {  Operation incomplete/still in progress  }\n  CRYPT_ERROR_COMPLETE = -24; {  Operation complete/can't continue  }\n  CRYPT_ERROR_TIMEOUT = -25; {  Operation timed out before completion  }\n  CRYPT_ERROR_INVALID = -26; {  Invalid/inconsistent information  }\n  CRYPT_ERROR_SIGNALLED = -27; {  Resource destroyed by extnl.event  }\n\n{  High-level function errors  }\n\n  CRYPT_ERROR_OVERFLOW = -30; {  Resources/space exhausted  }\n  CRYPT_ERROR_UNDERFLOW = -31; {  Not enough data available  }\n  CRYPT_ERROR_BADDATA = -32; {  Bad/unrecognised data format  }\n  CRYPT_ERROR_SIGNATURE = -33; {  Signature/integrity check failed  }\n\n{  Data access function errors  }\n\n  CRYPT_ERROR_OPEN = -40; {  Cannot open object  }\n  CRYPT_ERROR_READ = -41; {  Cannot read item from object  }\n  CRYPT_ERROR_WRITE = -42; {  Cannot write item to object  }\n  CRYPT_ERROR_NOTFOUND = -43; {  Requested item not found in object  }\n  CRYPT_ERROR_DUPLICATE = -44; {  Item already present in object  }\n\n{  Data enveloping errors  }\n\n  CRYPT_ENVELOPE_RESOURCE = -50; {  Need resource to proceed  }\n\n{  Macros to examine return values  }\n\n{ C-macro not translated to Delphi code: \n{   #define cryptStatusError( status )  ( ( status ) < CRYPT_OK ) }\n{ C-macro not translated to Delphi code: \n{   #define cryptStatusOK( status )     ( ( status ) == CRYPT_OK ) }\n\n{****************************************************************************\n*                                                                           *\n*                                   General Functions                       *\n*                                                                           *\n****************************************************************************}\n\n{  The following is necessary to stop C++ name mangling  }\n\n\n{  Initialise and shut down cryptlib  }\n\n \nfunction cryptInit: Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\nfunction cryptEnd: Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n\n{  Query cryptlibs capabilities  }\n\nfunction cryptQueryCapability( const cryptAlgo: CRYPT_ALGO_TYPE;\n  var cryptQueryInfo: CRYPT_QUERY_INFO ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Create and destroy an encryption context  }\n\nfunction cryptCreateContext( var cryptContext: CRYPT_CONTEXT;\n  const cryptUser: CRYPT_USER;\n  const cryptAlgo: CRYPT_ALGO_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDestroyContext( const cryptContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Generic \"destroy an object\" function  }\n\nfunction cryptDestroyObject( const cryptObject: CRYPT_HANDLE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Generate a key into a context  }\n\nfunction cryptGenerateKey( const cryptContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Encrypt/decrypt/hash a block of memory  }\n\nfunction cryptEncrypt( const cryptContext: CRYPT_CONTEXT;\n  buffer: Pointer;\n  const length: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDecrypt( const cryptContext: CRYPT_CONTEXT;\n  buffer: Pointer;\n  const length: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Get/set/delete attribute functions  }\n\nfunction cryptSetAttribute( const cryptHandle: CRYPT_HANDLE;\n  const attributeType: CRYPT_ATTRIBUTE_TYPE;\n  const value: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptSetAttributeString( const cryptHandle: CRYPT_HANDLE;\n  const attributeType: CRYPT_ATTRIBUTE_TYPE;\n  const value: Pointer;\n  const valueLength: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptGetAttribute( const cryptHandle: CRYPT_HANDLE;\n  const attributeType: CRYPT_ATTRIBUTE_TYPE;\n  var value: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptGetAttributeString( const cryptHandle: CRYPT_HANDLE;\n  const attributeType: CRYPT_ATTRIBUTE_TYPE;\n  value: Pointer;\n  var valueLength: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDeleteAttribute( const cryptHandle: CRYPT_HANDLE;\n  const attributeType: CRYPT_ATTRIBUTE_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Oddball functions: Add random data to the pool, query an encoded signature\n   or key data.  These are due to be replaced once a suitable alternative can\n   be found  }\n\nfunction cryptAddRandom( const randomData: Pointer;\n  const randomDataLength: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptQueryObject( const objectData: Pointer;\n  const objectDataLength: Integer;\n  var cryptObjectInfo: CRYPT_OBJECT_INFO ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                           Mid-level Encryption Functions                  *\n*                                                                           *\n****************************************************************************}\n\n{  Export and import an encrypted session key  }\n\nfunction cryptExportKey( encryptedKey: Pointer;\n  const encryptedKeyMaxLength: Integer;\n  var encryptedKeyLength: Integer;\n  const exportKey: CRYPT_HANDLE;\n  const sessionKeyContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptExportKeyEx( encryptedKey: Pointer;\n  const encryptedKeyMaxLength: Integer;\n  var encryptedKeyLength: Integer;\n  const formatType: CRYPT_FORMAT_TYPE;\n  const exportKey: CRYPT_HANDLE;\n  const sessionKeyContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptImportKey( const encryptedKey: Pointer;\n  const encryptedKeyLength: Integer;\n  const importKey: CRYPT_CONTEXT;\n  const sessionKeyContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptImportKeyEx( const encryptedKey: Pointer;\n  const encryptedKeyLength: Integer;\n  const importKey: CRYPT_CONTEXT;\n  const sessionKeyContext: CRYPT_CONTEXT;\n  var returnedContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Create and check a digital signature  }\n\nfunction cryptCreateSignature( signature: Pointer;\n  const signatureMaxLength: Integer;\n  var signatureLength: Integer;\n  const signContext: CRYPT_CONTEXT;\n  const hashContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCreateSignatureEx( signature: Pointer;\n  const signatureMaxLength: Integer;\n  var signatureLength: Integer;\n  const formatType: CRYPT_FORMAT_TYPE;\n  const signContext: CRYPT_CONTEXT;\n  const hashContext: CRYPT_CONTEXT;\n  const extraData: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCheckSignature( const signature: Pointer;\n  const signatureLength: Integer;\n  const sigCheckKey: CRYPT_HANDLE;\n  const hashContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCheckSignatureEx( const signature: Pointer;\n  const signatureLength: Integer;\n  const sigCheckKey: CRYPT_HANDLE;\n  const hashContext: CRYPT_CONTEXT;\n  var extraData: CRYPT_HANDLE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                                   Keyset Functions                        *\n*                                                                           *\n****************************************************************************}\n\n{  Open and close a keyset  }\n\nfunction cryptKeysetOpen( var keyset: CRYPT_KEYSET;\n  const cryptUser: CRYPT_USER;\n  const keysetType: CRYPT_KEYSET_TYPE;\n  const name: PAnsiChar;\n  const options: CRYPT_KEYOPT_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptKeysetClose( const keyset: CRYPT_KEYSET ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Get a key from a keyset or device  }\n\nfunction cryptGetPublicKey( const keyset: CRYPT_KEYSET;\n  var cryptContext: CRYPT_CONTEXT;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptGetPrivateKey( const keyset: CRYPT_KEYSET;\n  var cryptContext: CRYPT_CONTEXT;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar;\n  const password: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptGetKey( const keyset: CRYPT_KEYSET;\n  var cryptContext: CRYPT_CONTEXT;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar;\n  const password: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Add/delete a key to/from a keyset or device  }\n\nfunction cryptAddPublicKey( const keyset: CRYPT_KEYSET;\n  const certificate: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptAddPrivateKey( const keyset: CRYPT_KEYSET;\n  const cryptKey: CRYPT_HANDLE;\n  const password: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDeleteKey( const keyset: CRYPT_KEYSET;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                               Certificate Functions                       *\n*                                                                           *\n****************************************************************************}\n\n{  Create/destroy a certificate  }\n\nfunction cryptCreateCert( var certificate: CRYPT_CERTIFICATE;\n  const cryptUser: CRYPT_USER;\n  const certType: CRYPT_CERTTYPE_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDestroyCert( const certificate: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Get/add/delete certificate extensions.  These are direct data insertion\n   functions whose use is discouraged, so they fix the string at char *\n   rather than C_STR  }\n\nfunction cryptGetCertExtension( const certificate: CRYPT_CERTIFICATE;\n  const oid: PAnsiChar;\n  var criticalFlag: Integer;\n  extension: Pointer;\n  const extensionMaxLength: Integer;\n  var extensionLength: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptAddCertExtension( const certificate: CRYPT_CERTIFICATE;\n  const oid: PAnsiChar;\n  const criticalFlag: Integer;\n  const extension: Pointer;\n  const extensionLength: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDeleteCertExtension( const certificate: CRYPT_CERTIFICATE;\n  const oid: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Sign/sig.check a certificate/certification request  }\n\nfunction cryptSignCert( const certificate: CRYPT_CERTIFICATE;\n  const signContext: CRYPT_CONTEXT ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCheckCert( const certificate: CRYPT_CERTIFICATE;\n  const sigCheckKey: CRYPT_HANDLE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Import/export a certificate/certification request  }\n\nfunction cryptImportCert( const certObject: Pointer;\n  const certObjectLength: Integer;\n  const cryptUser: CRYPT_USER;\n  var certificate: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptExportCert( certObject: Pointer;\n  const certObjectMaxLength: Integer;\n  var certObjectLength: Integer;\n  const certFormatType: CRYPT_CERTFORMAT_TYPE;\n  const certificate: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  CA management functions  }\n\nfunction cryptCAAddItem( const keyset: CRYPT_KEYSET;\n  const certificate: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCAGetItem( const keyset: CRYPT_KEYSET;\n  var certificate: CRYPT_CERTIFICATE;\n  const certType: CRYPT_CERTTYPE_TYPE;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCADeleteItem( const keyset: CRYPT_KEYSET;\n  const certType: CRYPT_CERTTYPE_TYPE;\n  const keyIDtype: CRYPT_KEYID_TYPE;\n  const keyID: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptCACertManagement( var certificate: CRYPT_CERTIFICATE;\n  const action: CRYPT_CERTACTION_TYPE;\n  const keyset: CRYPT_KEYSET;\n  const caKey: CRYPT_CONTEXT;\n  const certRequest: CRYPT_CERTIFICATE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                           Envelope and Session Functions                  *\n*                                                                           *\n****************************************************************************}\n\n{  Create/destroy an envelope  }\n\nfunction cryptCreateEnvelope( var envelope: CRYPT_ENVELOPE;\n  const cryptUser: CRYPT_USER;\n  const formatType: CRYPT_FORMAT_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDestroyEnvelope( const envelope: CRYPT_ENVELOPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Create/destroy a session  }\n\nfunction cryptCreateSession( var session: CRYPT_SESSION;\n  const cryptUser: CRYPT_USER;\n  const formatType: CRYPT_SESSION_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDestroySession( const session: CRYPT_SESSION ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Add/remove data to/from and envelope or session  }\n\nfunction cryptPushData( const envelope: CRYPT_HANDLE;\n  const buffer: Pointer;\n  const length: Integer;\n  var bytesCopied: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptFlushData( const envelope: CRYPT_HANDLE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptPopData( const envelope: CRYPT_HANDLE;\n  buffer: Pointer;\n  const length: Integer;\n  var bytesCopied: Integer ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                               Device Functions                            *\n*                                                                           *\n****************************************************************************}\n\n{  Open and close a device  }\n\nfunction cryptDeviceOpen( var device: CRYPT_DEVICE;\n  const cryptUser: CRYPT_USER;\n  const deviceType: CRYPT_DEVICE_TYPE;\n  const name: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptDeviceClose( const device: CRYPT_DEVICE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Query a devices capabilities  }\n\nfunction cryptDeviceQueryCapability( const device: CRYPT_DEVICE;\n  const cryptAlgo: CRYPT_ALGO_TYPE;\n  var cryptQueryInfo: CRYPT_QUERY_INFO ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{  Create an encryption context via the device  }\n\nfunction cryptDeviceCreateContext( const device: CRYPT_DEVICE;\n  var cryptContext: CRYPT_CONTEXT;\n  const cryptAlgo: CRYPT_ALGO_TYPE ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                           User Management Functions                       *\n*                                                                           *\n****************************************************************************}\n\n{  Log on and off (create/destroy a user object)  }\n\nfunction cryptLogin( var user: CRYPT_USER;\n  const name: PAnsiChar;\n  const password: PAnsiChar ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\nfunction cryptLogout( const user: CRYPT_USER ): Integer;\n{$IFDEF WIN32} stdcall; {$ELSE} cdecl; {$ENDIF} external cryptlibname;\n\n\n{****************************************************************************\n*                                                                           *\n*                               Direct API Functions                        *\n*                                                                           *\n****************************************************************************}\n\n\n\n\nimplementation\n\n{ no implementation code now }\n\nend.\n"
  },
  {
    "path": "deps/cl345/bindings/java_jni.c",
    "content": "\n#include \"../crypt.h\"\n\n#ifdef USE_JAVA\n\n#include <jni.h>\n#include <stdio.h>  //printf\n#include <stdlib.h> //malloc, free\n\n#undef cryptlib_crypt_ALGO_NONE\n#define cryptlib_crypt_ALGO_NONE 0L\n#undef cryptlib_crypt_ALGO_DES\n#define cryptlib_crypt_ALGO_DES 1L\n#undef cryptlib_crypt_ALGO_3DES\n#define cryptlib_crypt_ALGO_3DES 2L\n#undef cryptlib_crypt_ALGO_IDEA\n#define cryptlib_crypt_ALGO_IDEA 3L\n#undef cryptlib_crypt_ALGO_CAST\n#define cryptlib_crypt_ALGO_CAST 4L\n#undef cryptlib_crypt_ALGO_RC2\n#define cryptlib_crypt_ALGO_RC2 5L\n#undef cryptlib_crypt_ALGO_RC4\n#define cryptlib_crypt_ALGO_RC4 6L\n#undef cryptlib_crypt_ALGO_RESERVED1\n#define cryptlib_crypt_ALGO_RESERVED1 7L\n#undef cryptlib_crypt_ALGO_AES\n#define cryptlib_crypt_ALGO_AES 8L\n#undef cryptlib_crypt_ALGO_RESERVED2\n#define cryptlib_crypt_ALGO_RESERVED2 9L\n#undef cryptlib_crypt_ALGO_DH\n#define cryptlib_crypt_ALGO_DH 100L\n#undef cryptlib_crypt_ALGO_RSA\n#define cryptlib_crypt_ALGO_RSA 101L\n#undef cryptlib_crypt_ALGO_DSA\n#define cryptlib_crypt_ALGO_DSA 102L\n#undef cryptlib_crypt_ALGO_ELGAMAL\n#define cryptlib_crypt_ALGO_ELGAMAL 103L\n#undef cryptlib_crypt_ALGO_RESERVED3\n#define cryptlib_crypt_ALGO_RESERVED3 104L\n#undef cryptlib_crypt_ALGO_ECDSA\n#define cryptlib_crypt_ALGO_ECDSA 105L\n#undef cryptlib_crypt_ALGO_ECDH\n#define cryptlib_crypt_ALGO_ECDH 106L\n#undef cryptlib_crypt_ALGO_RESERVED4\n#define cryptlib_crypt_ALGO_RESERVED4 200L\n#undef cryptlib_crypt_ALGO_RESERVED5\n#define cryptlib_crypt_ALGO_RESERVED5 201L\n#undef cryptlib_crypt_ALGO_MD5\n#define cryptlib_crypt_ALGO_MD5 202L\n#undef cryptlib_crypt_ALGO_SHA1\n#define cryptlib_crypt_ALGO_SHA1 203L\n#undef cryptlib_crypt_ALGO_RESERVED6\n#define cryptlib_crypt_ALGO_RESERVED6 204L\n#undef cryptlib_crypt_ALGO_SHA2\n#define cryptlib_crypt_ALGO_SHA2 205L\n#undef cryptlib_crypt_ALGO_SHA256\n#define cryptlib_crypt_ALGO_SHA256 205L\n#undef cryptlib_crypt_ALGO_SHAng\n#define cryptlib_crypt_ALGO_SHAng 206L\n#undef cryptlib_crypt_ALGO_RESREVED_7\n#define cryptlib_crypt_ALGO_RESREVED_7 300L\n#undef cryptlib_crypt_ALGO_HMAC_SHA1\n#define cryptlib_crypt_ALGO_HMAC_SHA1 301L\n#undef cryptlib_crypt_ALGO_RESERVED8\n#define cryptlib_crypt_ALGO_RESERVED8 302L\n#undef cryptlib_crypt_ALGO_HMAC_SHA2\n#define cryptlib_crypt_ALGO_HMAC_SHA2 303L\n#undef cryptlib_crypt_ALGO_HMAC_SHAng\n#define cryptlib_crypt_ALGO_HMAC_SHAng 304L\n#undef cryptlib_crypt_ALGO_LAST\n#define cryptlib_crypt_ALGO_LAST 305L\n#undef cryptlib_crypt_ALGO_FIRST_CONVENTIONAL\n#define cryptlib_crypt_ALGO_FIRST_CONVENTIONAL 1L\n#undef cryptlib_crypt_ALGO_LAST_CONVENTIONAL\n#define cryptlib_crypt_ALGO_LAST_CONVENTIONAL 99L\n#undef cryptlib_crypt_ALGO_FIRST_PKC\n#define cryptlib_crypt_ALGO_FIRST_PKC 100L\n#undef cryptlib_crypt_ALGO_LAST_PKC\n#define cryptlib_crypt_ALGO_LAST_PKC 199L\n#undef cryptlib_crypt_ALGO_FIRST_HASH\n#define cryptlib_crypt_ALGO_FIRST_HASH 200L\n#undef cryptlib_crypt_ALGO_LAST_HASH\n#define cryptlib_crypt_ALGO_LAST_HASH 299L\n#undef cryptlib_crypt_ALGO_FIRST_MAC\n#define cryptlib_crypt_ALGO_FIRST_MAC 300L\n#undef cryptlib_crypt_ALGO_LAST_MAC\n#define cryptlib_crypt_ALGO_LAST_MAC 399L\n#undef cryptlib_crypt_MODE_NONE\n#define cryptlib_crypt_MODE_NONE 0L\n#undef cryptlib_crypt_MODE_ECB\n#define cryptlib_crypt_MODE_ECB 1L\n#undef cryptlib_crypt_MODE_CBC\n#define cryptlib_crypt_MODE_CBC 2L\n#undef cryptlib_crypt_MODE_CFB\n#define cryptlib_crypt_MODE_CFB 3L\n#undef cryptlib_crypt_MODE_GCM\n#define cryptlib_crypt_MODE_GCM 4L\n#undef cryptlib_crypt_MODE_LAST\n#define cryptlib_crypt_MODE_LAST 5L\n#undef cryptlib_crypt_KEYSET_NONE\n#define cryptlib_crypt_KEYSET_NONE 0L\n#undef cryptlib_crypt_KEYSET_FILE\n#define cryptlib_crypt_KEYSET_FILE 1L\n#undef cryptlib_crypt_KEYSET_HTTP\n#define cryptlib_crypt_KEYSET_HTTP 2L\n#undef cryptlib_crypt_KEYSET_LDAP\n#define cryptlib_crypt_KEYSET_LDAP 3L\n#undef cryptlib_crypt_KEYSET_ODBC\n#define cryptlib_crypt_KEYSET_ODBC 4L\n#undef cryptlib_crypt_KEYSET_DATABASE\n#define cryptlib_crypt_KEYSET_DATABASE 5L\n#undef cryptlib_crypt_KEYSET_ODBC_STORE\n#define cryptlib_crypt_KEYSET_ODBC_STORE 6L\n#undef cryptlib_crypt_KEYSET_DATABASE_STORE\n#define cryptlib_crypt_KEYSET_DATABASE_STORE 7L\n#undef cryptlib_crypt_KEYSET_LAST\n#define cryptlib_crypt_KEYSET_LAST 8L\n#undef cryptlib_crypt_DEVICE_NONE\n#define cryptlib_crypt_DEVICE_NONE 0L\n#undef cryptlib_crypt_DEVICE_FORTEZZA\n#define cryptlib_crypt_DEVICE_FORTEZZA 1L\n#undef cryptlib_crypt_DEVICE_PKCS11\n#define cryptlib_crypt_DEVICE_PKCS11 2L\n#undef cryptlib_crypt_DEVICE_CRYPTOAPI\n#define cryptlib_crypt_DEVICE_CRYPTOAPI 3L\n#undef cryptlib_crypt_DEVICE_HARDWARE\n#define cryptlib_crypt_DEVICE_HARDWARE 4L\n#undef cryptlib_crypt_DEVICE_LAST\n#define cryptlib_crypt_DEVICE_LAST 5L\n#undef cryptlib_crypt_CERTTYPE_NONE\n#define cryptlib_crypt_CERTTYPE_NONE 0L\n#undef cryptlib_crypt_CERTTYPE_CERTIFICATE\n#define cryptlib_crypt_CERTTYPE_CERTIFICATE 1L\n#undef cryptlib_crypt_CERTTYPE_ATTRIBUTE_CERT\n#define cryptlib_crypt_CERTTYPE_ATTRIBUTE_CERT 2L\n#undef cryptlib_crypt_CERTTYPE_CERTCHAIN\n#define cryptlib_crypt_CERTTYPE_CERTCHAIN 3L\n#undef cryptlib_crypt_CERTTYPE_CERTREQUEST\n#define cryptlib_crypt_CERTTYPE_CERTREQUEST 4L\n#undef cryptlib_crypt_CERTTYPE_REQUEST_CERT\n#define cryptlib_crypt_CERTTYPE_REQUEST_CERT 5L\n#undef cryptlib_crypt_CERTTYPE_REQUEST_REVOCATION\n#define cryptlib_crypt_CERTTYPE_REQUEST_REVOCATION 6L\n#undef cryptlib_crypt_CERTTYPE_CRL\n#define cryptlib_crypt_CERTTYPE_CRL 7L\n#undef cryptlib_crypt_CERTTYPE_CMS_ATTRIBUTES\n#define cryptlib_crypt_CERTTYPE_CMS_ATTRIBUTES 8L\n#undef cryptlib_crypt_CERTTYPE_RTCS_REQUEST\n#define cryptlib_crypt_CERTTYPE_RTCS_REQUEST 9L\n#undef cryptlib_crypt_CERTTYPE_RTCS_RESPONSE\n#define cryptlib_crypt_CERTTYPE_RTCS_RESPONSE 10L\n#undef cryptlib_crypt_CERTTYPE_OCSP_REQUEST\n#define cryptlib_crypt_CERTTYPE_OCSP_REQUEST 11L\n#undef cryptlib_crypt_CERTTYPE_OCSP_RESPONSE\n#define cryptlib_crypt_CERTTYPE_OCSP_RESPONSE 12L\n#undef cryptlib_crypt_CERTTYPE_PKIUSER\n#define cryptlib_crypt_CERTTYPE_PKIUSER 13L\n#undef cryptlib_crypt_CERTTYPE_LAST\n#define cryptlib_crypt_CERTTYPE_LAST 14L\n#undef cryptlib_crypt_FORMAT_NONE\n#define cryptlib_crypt_FORMAT_NONE 0L\n#undef cryptlib_crypt_FORMAT_AUTO\n#define cryptlib_crypt_FORMAT_AUTO 1L\n#undef cryptlib_crypt_FORMAT_CRYPTLIB\n#define cryptlib_crypt_FORMAT_CRYPTLIB 2L\n#undef cryptlib_crypt_FORMAT_CMS\n#define cryptlib_crypt_FORMAT_CMS 3L\n#undef cryptlib_crypt_FORMAT_PKCS7\n#define cryptlib_crypt_FORMAT_PKCS7 3L\n#undef cryptlib_crypt_FORMAT_SMIME\n#define cryptlib_crypt_FORMAT_SMIME 4L\n#undef cryptlib_crypt_FORMAT_PGP\n#define cryptlib_crypt_FORMAT_PGP 5L\n#undef cryptlib_crypt_FORMAT_LAST\n#define cryptlib_crypt_FORMAT_LAST 6L\n#undef cryptlib_crypt_SESSION_NONE\n#define cryptlib_crypt_SESSION_NONE 0L\n#undef cryptlib_crypt_SESSION_SSH\n#define cryptlib_crypt_SESSION_SSH 1L\n#undef cryptlib_crypt_SESSION_SSH_SERVER\n#define cryptlib_crypt_SESSION_SSH_SERVER 2L\n#undef cryptlib_crypt_SESSION_SSL\n#define cryptlib_crypt_SESSION_SSL 3L\n#undef cryptlib_crypt_SESSION_TLS\n#define cryptlib_crypt_SESSION_TLS 3L\n#undef cryptlib_crypt_SESSION_SSL_SERVER\n#define cryptlib_crypt_SESSION_SSL_SERVER 4L\n#undef cryptlib_crypt_SESSION_TLS_SERVER\n#define cryptlib_crypt_SESSION_TLS_SERVER 4L\n#undef cryptlib_crypt_SESSION_RTCS\n#define cryptlib_crypt_SESSION_RTCS 5L\n#undef cryptlib_crypt_SESSION_RTCS_SERVER\n#define cryptlib_crypt_SESSION_RTCS_SERVER 6L\n#undef cryptlib_crypt_SESSION_OCSP\n#define cryptlib_crypt_SESSION_OCSP 7L\n#undef cryptlib_crypt_SESSION_OCSP_SERVER\n#define cryptlib_crypt_SESSION_OCSP_SERVER 8L\n#undef cryptlib_crypt_SESSION_TSP\n#define cryptlib_crypt_SESSION_TSP 9L\n#undef cryptlib_crypt_SESSION_TSP_SERVER\n#define cryptlib_crypt_SESSION_TSP_SERVER 10L\n#undef cryptlib_crypt_SESSION_CMP\n#define cryptlib_crypt_SESSION_CMP 11L\n#undef cryptlib_crypt_SESSION_CMP_SERVER\n#define cryptlib_crypt_SESSION_CMP_SERVER 12L\n#undef cryptlib_crypt_SESSION_SCEP\n#define cryptlib_crypt_SESSION_SCEP 13L\n#undef cryptlib_crypt_SESSION_SCEP_SERVER\n#define cryptlib_crypt_SESSION_SCEP_SERVER 14L\n#undef cryptlib_crypt_SESSION_CERTSTORE_SERVER\n#define cryptlib_crypt_SESSION_CERTSTORE_SERVER 15L\n#undef cryptlib_crypt_SESSION_LAST\n#define cryptlib_crypt_SESSION_LAST 16L\n#undef cryptlib_crypt_USER_NONE\n#define cryptlib_crypt_USER_NONE 0L\n#undef cryptlib_crypt_USER_NORMAL\n#define cryptlib_crypt_USER_NORMAL 1L\n#undef cryptlib_crypt_USER_SO\n#define cryptlib_crypt_USER_SO 2L\n#undef cryptlib_crypt_USER_CA\n#define cryptlib_crypt_USER_CA 3L\n#undef cryptlib_crypt_USER_LAST\n#define cryptlib_crypt_USER_LAST 4L\n#undef cryptlib_crypt_ATTRIBUTE_NONE\n#define cryptlib_crypt_ATTRIBUTE_NONE 0L\n#undef cryptlib_crypt_PROPERTY_FIRST\n#define cryptlib_crypt_PROPERTY_FIRST 1L\n#undef cryptlib_crypt_PROPERTY_HIGHSECURITY\n#define cryptlib_crypt_PROPERTY_HIGHSECURITY 2L\n#undef cryptlib_crypt_PROPERTY_OWNER\n#define cryptlib_crypt_PROPERTY_OWNER 3L\n#undef cryptlib_crypt_PROPERTY_FORWARDCOUNT\n#define cryptlib_crypt_PROPERTY_FORWARDCOUNT 4L\n#undef cryptlib_crypt_PROPERTY_LOCKED\n#define cryptlib_crypt_PROPERTY_LOCKED 5L\n#undef cryptlib_crypt_PROPERTY_USAGECOUNT\n#define cryptlib_crypt_PROPERTY_USAGECOUNT 6L\n#undef cryptlib_crypt_PROPERTY_NONEXPORTABLE\n#define cryptlib_crypt_PROPERTY_NONEXPORTABLE 7L\n#undef cryptlib_crypt_PROPERTY_LAST\n#define cryptlib_crypt_PROPERTY_LAST 8L\n#undef cryptlib_crypt_GENERIC_FIRST\n#define cryptlib_crypt_GENERIC_FIRST 9L\n#undef cryptlib_crypt_ATTRIBUTE_ERRORTYPE\n#define cryptlib_crypt_ATTRIBUTE_ERRORTYPE 10L\n#undef cryptlib_crypt_ATTRIBUTE_ERRORLOCUS\n#define cryptlib_crypt_ATTRIBUTE_ERRORLOCUS 11L\n#undef cryptlib_crypt_ATTRIBUTE_ERRORMESSAGE\n#define cryptlib_crypt_ATTRIBUTE_ERRORMESSAGE 12L\n#undef cryptlib_crypt_ATTRIBUTE_CURRENT_GROUP\n#define cryptlib_crypt_ATTRIBUTE_CURRENT_GROUP 13L\n#undef cryptlib_crypt_ATTRIBUTE_CURRENT\n#define cryptlib_crypt_ATTRIBUTE_CURRENT 14L\n#undef cryptlib_crypt_ATTRIBUTE_CURRENT_INSTANCE\n#define cryptlib_crypt_ATTRIBUTE_CURRENT_INSTANCE 15L\n#undef cryptlib_crypt_ATTRIBUTE_BUFFERSIZE\n#define cryptlib_crypt_ATTRIBUTE_BUFFERSIZE 16L\n#undef cryptlib_crypt_GENERIC_LAST\n#define cryptlib_crypt_GENERIC_LAST 17L\n#undef cryptlib_crypt_OPTION_FIRST\n#define cryptlib_crypt_OPTION_FIRST 100L\n#undef cryptlib_crypt_OPTION_INFO_DESCRIPTION\n#define cryptlib_crypt_OPTION_INFO_DESCRIPTION 101L\n#undef cryptlib_crypt_OPTION_INFO_COPYRIGHT\n#define cryptlib_crypt_OPTION_INFO_COPYRIGHT 102L\n#undef cryptlib_crypt_OPTION_INFO_MAJORVERSION\n#define cryptlib_crypt_OPTION_INFO_MAJORVERSION 103L\n#undef cryptlib_crypt_OPTION_INFO_MINORVERSION\n#define cryptlib_crypt_OPTION_INFO_MINORVERSION 104L\n#undef cryptlib_crypt_OPTION_INFO_STEPPING\n#define cryptlib_crypt_OPTION_INFO_STEPPING 105L\n#undef cryptlib_crypt_OPTION_ENCR_ALGO\n#define cryptlib_crypt_OPTION_ENCR_ALGO 106L\n#undef cryptlib_crypt_OPTION_ENCR_HASH\n#define cryptlib_crypt_OPTION_ENCR_HASH 107L\n#undef cryptlib_crypt_OPTION_ENCR_MAC\n#define cryptlib_crypt_OPTION_ENCR_MAC 108L\n#undef cryptlib_crypt_OPTION_PKC_ALGO\n#define cryptlib_crypt_OPTION_PKC_ALGO 109L\n#undef cryptlib_crypt_OPTION_PKC_KEYSIZE\n#define cryptlib_crypt_OPTION_PKC_KEYSIZE 110L\n#undef cryptlib_crypt_OPTION_DUMMY1\n#define cryptlib_crypt_OPTION_DUMMY1 111L\n#undef cryptlib_crypt_OPTION_DUMMY2\n#define cryptlib_crypt_OPTION_DUMMY2 112L\n#undef cryptlib_crypt_OPTION_KEYING_ALGO\n#define cryptlib_crypt_OPTION_KEYING_ALGO 113L\n#undef cryptlib_crypt_OPTION_KEYING_ITERATIONS\n#define cryptlib_crypt_OPTION_KEYING_ITERATIONS 114L\n#undef cryptlib_crypt_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES\n#define cryptlib_crypt_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES 115L\n#undef cryptlib_crypt_OPTION_CERT_VALIDITY\n#define cryptlib_crypt_OPTION_CERT_VALIDITY 116L\n#undef cryptlib_crypt_OPTION_CERT_UPDATEINTERVAL\n#define cryptlib_crypt_OPTION_CERT_UPDATEINTERVAL 117L\n#undef cryptlib_crypt_OPTION_CERT_COMPLIANCELEVEL\n#define cryptlib_crypt_OPTION_CERT_COMPLIANCELEVEL 118L\n#undef cryptlib_crypt_OPTION_CERT_REQUIREPOLICY\n#define cryptlib_crypt_OPTION_CERT_REQUIREPOLICY 119L\n#undef cryptlib_crypt_OPTION_CMS_DEFAULTATTRIBUTES\n#define cryptlib_crypt_OPTION_CMS_DEFAULTATTRIBUTES 120L\n#undef cryptlib_crypt_OPTION_SMIME_DEFAULTATTRIBUTES\n#define cryptlib_crypt_OPTION_SMIME_DEFAULTATTRIBUTES 120L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_OBJECTCLASS\n#define cryptlib_crypt_OPTION_KEYS_LDAP_OBJECTCLASS 121L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_OBJECTTYPE\n#define cryptlib_crypt_OPTION_KEYS_LDAP_OBJECTTYPE 122L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_FILTER\n#define cryptlib_crypt_OPTION_KEYS_LDAP_FILTER 123L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_CACERTNAME\n#define cryptlib_crypt_OPTION_KEYS_LDAP_CACERTNAME 124L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_CERTNAME\n#define cryptlib_crypt_OPTION_KEYS_LDAP_CERTNAME 125L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_CRLNAME\n#define cryptlib_crypt_OPTION_KEYS_LDAP_CRLNAME 126L\n#undef cryptlib_crypt_OPTION_KEYS_LDAP_EMAILNAME\n#define cryptlib_crypt_OPTION_KEYS_LDAP_EMAILNAME 127L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR01\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR01 128L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR02\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR02 129L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR03\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR03 130L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR04\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR04 131L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR05\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_DVR05 132L\n#undef cryptlib_crypt_OPTION_DEVICE_PKCS11_HARDWAREONLY\n#define cryptlib_crypt_OPTION_DEVICE_PKCS11_HARDWAREONLY 133L\n#undef cryptlib_crypt_OPTION_NET_SOCKS_SERVER\n#define cryptlib_crypt_OPTION_NET_SOCKS_SERVER 134L\n#undef cryptlib_crypt_OPTION_NET_SOCKS_USERNAME\n#define cryptlib_crypt_OPTION_NET_SOCKS_USERNAME 135L\n#undef cryptlib_crypt_OPTION_NET_HTTP_PROXY\n#define cryptlib_crypt_OPTION_NET_HTTP_PROXY 136L\n#undef cryptlib_crypt_OPTION_NET_CONNECTTIMEOUT\n#define cryptlib_crypt_OPTION_NET_CONNECTTIMEOUT 137L\n#undef cryptlib_crypt_OPTION_NET_READTIMEOUT\n#define cryptlib_crypt_OPTION_NET_READTIMEOUT 138L\n#undef cryptlib_crypt_OPTION_NET_WRITETIMEOUT\n#define cryptlib_crypt_OPTION_NET_WRITETIMEOUT 139L\n#undef cryptlib_crypt_OPTION_MISC_ASYNCINIT\n#define cryptlib_crypt_OPTION_MISC_ASYNCINIT 140L\n#undef cryptlib_crypt_OPTION_MISC_SIDECHANNELPROTECTION\n#define cryptlib_crypt_OPTION_MISC_SIDECHANNELPROTECTION 141L\n#undef cryptlib_crypt_OPTION_CONFIGCHANGED\n#define cryptlib_crypt_OPTION_CONFIGCHANGED 142L\n#undef cryptlib_crypt_OPTION_SELFTESTOK\n#define cryptlib_crypt_OPTION_SELFTESTOK 143L\n#undef cryptlib_crypt_OPTION_LAST\n#define cryptlib_crypt_OPTION_LAST 144L\n#undef cryptlib_crypt_CTXINFO_FIRST\n#define cryptlib_crypt_CTXINFO_FIRST 1000L\n#undef cryptlib_crypt_CTXINFO_ALGO\n#define cryptlib_crypt_CTXINFO_ALGO 1001L\n#undef cryptlib_crypt_CTXINFO_MODE\n#define cryptlib_crypt_CTXINFO_MODE 1002L\n#undef cryptlib_crypt_CTXINFO_NAME_ALGO\n#define cryptlib_crypt_CTXINFO_NAME_ALGO 1003L\n#undef cryptlib_crypt_CTXINFO_NAME_MODE\n#define cryptlib_crypt_CTXINFO_NAME_MODE 1004L\n#undef cryptlib_crypt_CTXINFO_KEYSIZE\n#define cryptlib_crypt_CTXINFO_KEYSIZE 1005L\n#undef cryptlib_crypt_CTXINFO_BLOCKSIZE\n#define cryptlib_crypt_CTXINFO_BLOCKSIZE 1006L\n#undef cryptlib_crypt_CTXINFO_IVSIZE\n#define cryptlib_crypt_CTXINFO_IVSIZE 1007L\n#undef cryptlib_crypt_CTXINFO_KEYING_ALGO\n#define cryptlib_crypt_CTXINFO_KEYING_ALGO 1008L\n#undef cryptlib_crypt_CTXINFO_KEYING_ITERATIONS\n#define cryptlib_crypt_CTXINFO_KEYING_ITERATIONS 1009L\n#undef cryptlib_crypt_CTXINFO_KEYING_SALT\n#define cryptlib_crypt_CTXINFO_KEYING_SALT 1010L\n#undef cryptlib_crypt_CTXINFO_KEYING_VALUE\n#define cryptlib_crypt_CTXINFO_KEYING_VALUE 1011L\n#undef cryptlib_crypt_CTXINFO_KEY\n#define cryptlib_crypt_CTXINFO_KEY 1012L\n#undef cryptlib_crypt_CTXINFO_KEY_COMPONENTS\n#define cryptlib_crypt_CTXINFO_KEY_COMPONENTS 1013L\n#undef cryptlib_crypt_CTXINFO_IV\n#define cryptlib_crypt_CTXINFO_IV 1014L\n#undef cryptlib_crypt_CTXINFO_HASHVALUE\n#define cryptlib_crypt_CTXINFO_HASHVALUE 1015L\n#undef cryptlib_crypt_CTXINFO_LABEL\n#define cryptlib_crypt_CTXINFO_LABEL 1016L\n#undef cryptlib_crypt_CTXINFO_PERSISTENT\n#define cryptlib_crypt_CTXINFO_PERSISTENT 1017L\n#undef cryptlib_crypt_CTXINFO_LAST\n#define cryptlib_crypt_CTXINFO_LAST 1018L\n#undef cryptlib_crypt_CERTINFO_FIRST\n#define cryptlib_crypt_CERTINFO_FIRST 2000L\n#undef cryptlib_crypt_CERTINFO_SELFSIGNED\n#define cryptlib_crypt_CERTINFO_SELFSIGNED 2001L\n#undef cryptlib_crypt_CERTINFO_IMMUTABLE\n#define cryptlib_crypt_CERTINFO_IMMUTABLE 2002L\n#undef cryptlib_crypt_CERTINFO_XYZZY\n#define cryptlib_crypt_CERTINFO_XYZZY 2003L\n#undef cryptlib_crypt_CERTINFO_CERTTYPE\n#define cryptlib_crypt_CERTINFO_CERTTYPE 2004L\n#undef cryptlib_crypt_CERTINFO_FINGERPRINT_SHA1\n#define cryptlib_crypt_CERTINFO_FINGERPRINT_SHA1 2005L\n#undef cryptlib_crypt_CERTINFO_FINGERPRINT_SHA2\n#define cryptlib_crypt_CERTINFO_FINGERPRINT_SHA2 2006L\n#undef cryptlib_crypt_CERTINFO_FINGERPRINT_SHAng\n#define cryptlib_crypt_CERTINFO_FINGERPRINT_SHAng 2007L\n#undef cryptlib_crypt_CERTINFO_CURRENT_CERTIFICATE\n#define cryptlib_crypt_CERTINFO_CURRENT_CERTIFICATE 2008L\n#undef cryptlib_crypt_CERTINFO_TRUSTED_USAGE\n#define cryptlib_crypt_CERTINFO_TRUSTED_USAGE 2009L\n#undef cryptlib_crypt_CERTINFO_TRUSTED_IMPLICIT\n#define cryptlib_crypt_CERTINFO_TRUSTED_IMPLICIT 2010L\n#undef cryptlib_crypt_CERTINFO_SIGNATURELEVEL\n#define cryptlib_crypt_CERTINFO_SIGNATURELEVEL 2011L\n#undef cryptlib_crypt_CERTINFO_VERSION\n#define cryptlib_crypt_CERTINFO_VERSION 2012L\n#undef cryptlib_crypt_CERTINFO_SERIALNUMBER\n#define cryptlib_crypt_CERTINFO_SERIALNUMBER 2013L\n#undef cryptlib_crypt_CERTINFO_SUBJECTPUBLICKEYINFO\n#define cryptlib_crypt_CERTINFO_SUBJECTPUBLICKEYINFO 2014L\n#undef cryptlib_crypt_CERTINFO_CERTIFICATE\n#define cryptlib_crypt_CERTINFO_CERTIFICATE 2015L\n#undef cryptlib_crypt_CERTINFO_USERCERTIFICATE\n#define cryptlib_crypt_CERTINFO_USERCERTIFICATE 2015L\n#undef cryptlib_crypt_CERTINFO_CACERTIFICATE\n#define cryptlib_crypt_CERTINFO_CACERTIFICATE 2016L\n#undef cryptlib_crypt_CERTINFO_ISSUERNAME\n#define cryptlib_crypt_CERTINFO_ISSUERNAME 2017L\n#undef cryptlib_crypt_CERTINFO_VALIDFROM\n#define cryptlib_crypt_CERTINFO_VALIDFROM 2018L\n#undef cryptlib_crypt_CERTINFO_VALIDTO\n#define cryptlib_crypt_CERTINFO_VALIDTO 2019L\n#undef cryptlib_crypt_CERTINFO_SUBJECTNAME\n#define cryptlib_crypt_CERTINFO_SUBJECTNAME 2020L\n#undef cryptlib_crypt_CERTINFO_ISSUERUNIQUEID\n#define cryptlib_crypt_CERTINFO_ISSUERUNIQUEID 2021L\n#undef cryptlib_crypt_CERTINFO_SUBJECTUNIQUEID\n#define cryptlib_crypt_CERTINFO_SUBJECTUNIQUEID 2022L\n#undef cryptlib_crypt_CERTINFO_CERTREQUEST\n#define cryptlib_crypt_CERTINFO_CERTREQUEST 2023L\n#undef cryptlib_crypt_CERTINFO_THISUPDATE\n#define cryptlib_crypt_CERTINFO_THISUPDATE 2024L\n#undef cryptlib_crypt_CERTINFO_NEXTUPDATE\n#define cryptlib_crypt_CERTINFO_NEXTUPDATE 2025L\n#undef cryptlib_crypt_CERTINFO_REVOCATIONDATE\n#define cryptlib_crypt_CERTINFO_REVOCATIONDATE 2026L\n#undef cryptlib_crypt_CERTINFO_REVOCATIONSTATUS\n#define cryptlib_crypt_CERTINFO_REVOCATIONSTATUS 2027L\n#undef cryptlib_crypt_CERTINFO_CERTSTATUS\n#define cryptlib_crypt_CERTINFO_CERTSTATUS 2028L\n#undef cryptlib_crypt_CERTINFO_DN\n#define cryptlib_crypt_CERTINFO_DN 2029L\n#undef cryptlib_crypt_CERTINFO_PKIUSER_ID\n#define cryptlib_crypt_CERTINFO_PKIUSER_ID 2030L\n#undef cryptlib_crypt_CERTINFO_PKIUSER_ISSUEPASSWORD\n#define cryptlib_crypt_CERTINFO_PKIUSER_ISSUEPASSWORD 2031L\n#undef cryptlib_crypt_CERTINFO_PKIUSER_REVPASSWORD\n#define cryptlib_crypt_CERTINFO_PKIUSER_REVPASSWORD 2032L\n#undef cryptlib_crypt_CERTINFO_PKIUSER_RA\n#define cryptlib_crypt_CERTINFO_PKIUSER_RA 2033L\n#undef cryptlib_crypt_CERTINFO_COUNTRYNAME\n#define cryptlib_crypt_CERTINFO_COUNTRYNAME 2100L\n#undef cryptlib_crypt_CERTINFO_STATEORPROVINCENAME\n#define cryptlib_crypt_CERTINFO_STATEORPROVINCENAME 2101L\n#undef cryptlib_crypt_CERTINFO_LOCALITYNAME\n#define cryptlib_crypt_CERTINFO_LOCALITYNAME 2102L\n#undef cryptlib_crypt_CERTINFO_ORGANIZATIONNAME\n#define cryptlib_crypt_CERTINFO_ORGANIZATIONNAME 2103L\n#undef cryptlib_crypt_CERTINFO_ORGANISATIONNAME\n#define cryptlib_crypt_CERTINFO_ORGANISATIONNAME 2103L\n#undef cryptlib_crypt_CERTINFO_ORGANIZATIONALUNITNAME\n#define cryptlib_crypt_CERTINFO_ORGANIZATIONALUNITNAME 2104L\n#undef cryptlib_crypt_CERTINFO_ORGANISATIONALUNITNAME\n#define cryptlib_crypt_CERTINFO_ORGANISATIONALUNITNAME 2104L\n#undef cryptlib_crypt_CERTINFO_COMMONNAME\n#define cryptlib_crypt_CERTINFO_COMMONNAME 2105L\n#undef cryptlib_crypt_CERTINFO_OTHERNAME_TYPEID\n#define cryptlib_crypt_CERTINFO_OTHERNAME_TYPEID 2106L\n#undef cryptlib_crypt_CERTINFO_OTHERNAME_VALUE\n#define cryptlib_crypt_CERTINFO_OTHERNAME_VALUE 2107L\n#undef cryptlib_crypt_CERTINFO_RFC822NAME\n#define cryptlib_crypt_CERTINFO_RFC822NAME 2108L\n#undef cryptlib_crypt_CERTINFO_EMAIL\n#define cryptlib_crypt_CERTINFO_EMAIL 2108L\n#undef cryptlib_crypt_CERTINFO_DNSNAME\n#define cryptlib_crypt_CERTINFO_DNSNAME 2109L\n#undef cryptlib_crypt_CERTINFO_DIRECTORYNAME\n#define cryptlib_crypt_CERTINFO_DIRECTORYNAME 2110L\n#undef cryptlib_crypt_CERTINFO_EDIPARTYNAME_NAMEASSIGNER\n#define cryptlib_crypt_CERTINFO_EDIPARTYNAME_NAMEASSIGNER 2111L\n#undef cryptlib_crypt_CERTINFO_EDIPARTYNAME_PARTYNAME\n#define cryptlib_crypt_CERTINFO_EDIPARTYNAME_PARTYNAME 2112L\n#undef cryptlib_crypt_CERTINFO_UNIFORMRESOURCEIDENTIFIER\n#define cryptlib_crypt_CERTINFO_UNIFORMRESOURCEIDENTIFIER 2113L\n#undef cryptlib_crypt_CERTINFO_URL\n#define cryptlib_crypt_CERTINFO_URL 2113L\n#undef cryptlib_crypt_CERTINFO_IPADDRESS\n#define cryptlib_crypt_CERTINFO_IPADDRESS 2114L\n#undef cryptlib_crypt_CERTINFO_REGISTEREDID\n#define cryptlib_crypt_CERTINFO_REGISTEREDID 2115L\n#undef cryptlib_crypt_CERTINFO_CHALLENGEPASSWORD\n#define cryptlib_crypt_CERTINFO_CHALLENGEPASSWORD 2200L\n#undef cryptlib_crypt_CERTINFO_CRLEXTREASON\n#define cryptlib_crypt_CERTINFO_CRLEXTREASON 2201L\n#undef cryptlib_crypt_CERTINFO_KEYFEATURES\n#define cryptlib_crypt_CERTINFO_KEYFEATURES 2202L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFOACCESS\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFOACCESS 2203L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFO_RTCS\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFO_RTCS 2204L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFO_OCSP\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFO_OCSP 2205L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFO_CAISSUERS\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFO_CAISSUERS 2206L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFO_CERTSTORE\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFO_CERTSTORE 2207L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYINFO_CRLS\n#define cryptlib_crypt_CERTINFO_AUTHORITYINFO_CRLS 2208L\n#undef cryptlib_crypt_CERTINFO_BIOMETRICINFO\n#define cryptlib_crypt_CERTINFO_BIOMETRICINFO 2209L\n#undef cryptlib_crypt_CERTINFO_BIOMETRICINFO_TYPE\n#define cryptlib_crypt_CERTINFO_BIOMETRICINFO_TYPE 2210L\n#undef cryptlib_crypt_CERTINFO_BIOMETRICINFO_HASHALGO\n#define cryptlib_crypt_CERTINFO_BIOMETRICINFO_HASHALGO 2211L\n#undef cryptlib_crypt_CERTINFO_BIOMETRICINFO_HASH\n#define cryptlib_crypt_CERTINFO_BIOMETRICINFO_HASH 2212L\n#undef cryptlib_crypt_CERTINFO_BIOMETRICINFO_URL\n#define cryptlib_crypt_CERTINFO_BIOMETRICINFO_URL 2213L\n#undef cryptlib_crypt_CERTINFO_QCSTATEMENT\n#define cryptlib_crypt_CERTINFO_QCSTATEMENT 2214L\n#undef cryptlib_crypt_CERTINFO_QCSTATEMENT_SEMANTICS\n#define cryptlib_crypt_CERTINFO_QCSTATEMENT_SEMANTICS 2215L\n#undef cryptlib_crypt_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY\n#define cryptlib_crypt_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY 2216L\n#undef cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS\n#define cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS 2217L\n#undef cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY\n#define cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY 2218L\n#undef cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_PREFIX\n#define cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_PREFIX 2219L\n#undef cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_MIN\n#define cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_MIN 2220L\n#undef cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_MAX\n#define cryptlib_crypt_CERTINFO_IPADDRESSBLOCKS_MAX 2221L\n#undef cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS\n#define cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS 2222L\n#undef cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID\n#define cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID 2223L\n#undef cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN\n#define cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN 2224L\n#undef cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX\n#define cryptlib_crypt_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX 2225L\n#undef cryptlib_crypt_CERTINFO_OCSP_NONCE\n#define cryptlib_crypt_CERTINFO_OCSP_NONCE 2226L\n#undef cryptlib_crypt_CERTINFO_OCSP_RESPONSE\n#define cryptlib_crypt_CERTINFO_OCSP_RESPONSE 2227L\n#undef cryptlib_crypt_CERTINFO_OCSP_RESPONSE_OCSP\n#define cryptlib_crypt_CERTINFO_OCSP_RESPONSE_OCSP 2228L\n#undef cryptlib_crypt_CERTINFO_OCSP_NOCHECK\n#define cryptlib_crypt_CERTINFO_OCSP_NOCHECK 2229L\n#undef cryptlib_crypt_CERTINFO_OCSP_ARCHIVECUTOFF\n#define cryptlib_crypt_CERTINFO_OCSP_ARCHIVECUTOFF 2230L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFOACCESS\n#define cryptlib_crypt_CERTINFO_SUBJECTINFOACCESS 2231L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFO_TIMESTAMPING\n#define cryptlib_crypt_CERTINFO_SUBJECTINFO_TIMESTAMPING 2232L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFO_CAREPOSITORY\n#define cryptlib_crypt_CERTINFO_SUBJECTINFO_CAREPOSITORY 2233L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY\n#define cryptlib_crypt_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY 2234L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFO_RPKIMANIFEST\n#define cryptlib_crypt_CERTINFO_SUBJECTINFO_RPKIMANIFEST 2235L\n#undef cryptlib_crypt_CERTINFO_SUBJECTINFO_SIGNEDOBJECT\n#define cryptlib_crypt_CERTINFO_SUBJECTINFO_SIGNEDOBJECT 2236L\n#undef cryptlib_crypt_CERTINFO_SIGG_DATEOFCERTGEN\n#define cryptlib_crypt_CERTINFO_SIGG_DATEOFCERTGEN 2237L\n#undef cryptlib_crypt_CERTINFO_SIGG_PROCURATION\n#define cryptlib_crypt_CERTINFO_SIGG_PROCURATION 2238L\n#undef cryptlib_crypt_CERTINFO_SIGG_PROCURE_COUNTRY\n#define cryptlib_crypt_CERTINFO_SIGG_PROCURE_COUNTRY 2239L\n#undef cryptlib_crypt_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION\n#define cryptlib_crypt_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION 2240L\n#undef cryptlib_crypt_CERTINFO_SIGG_PROCURE_SIGNINGFOR\n#define cryptlib_crypt_CERTINFO_SIGG_PROCURE_SIGNINGFOR 2241L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS 2242L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_AUTHORITY\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_AUTHORITY 2243L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID 2244L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL 2245L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT 2246L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM 2247L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID 2248L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER\n#define cryptlib_crypt_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER 2249L\n#undef cryptlib_crypt_CERTINFO_SIGG_MONETARYLIMIT\n#define cryptlib_crypt_CERTINFO_SIGG_MONETARYLIMIT 2250L\n#undef cryptlib_crypt_CERTINFO_SIGG_MONETARY_CURRENCY\n#define cryptlib_crypt_CERTINFO_SIGG_MONETARY_CURRENCY 2251L\n#undef cryptlib_crypt_CERTINFO_SIGG_MONETARY_AMOUNT\n#define cryptlib_crypt_CERTINFO_SIGG_MONETARY_AMOUNT 2252L\n#undef cryptlib_crypt_CERTINFO_SIGG_MONETARY_EXPONENT\n#define cryptlib_crypt_CERTINFO_SIGG_MONETARY_EXPONENT 2253L\n#undef cryptlib_crypt_CERTINFO_SIGG_DECLARATIONOFMAJORITY\n#define cryptlib_crypt_CERTINFO_SIGG_DECLARATIONOFMAJORITY 2254L\n#undef cryptlib_crypt_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY\n#define cryptlib_crypt_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY 2255L\n#undef cryptlib_crypt_CERTINFO_SIGG_RESTRICTION\n#define cryptlib_crypt_CERTINFO_SIGG_RESTRICTION 2256L\n#undef cryptlib_crypt_CERTINFO_SIGG_CERTHASH\n#define cryptlib_crypt_CERTINFO_SIGG_CERTHASH 2257L\n#undef cryptlib_crypt_CERTINFO_SIGG_ADDITIONALINFORMATION\n#define cryptlib_crypt_CERTINFO_SIGG_ADDITIONALINFORMATION 2258L\n#undef cryptlib_crypt_CERTINFO_STRONGEXTRANET\n#define cryptlib_crypt_CERTINFO_STRONGEXTRANET 2259L\n#undef cryptlib_crypt_CERTINFO_STRONGEXTRANET_ZONE\n#define cryptlib_crypt_CERTINFO_STRONGEXTRANET_ZONE 2260L\n#undef cryptlib_crypt_CERTINFO_STRONGEXTRANET_ID\n#define cryptlib_crypt_CERTINFO_STRONGEXTRANET_ID 2261L\n#undef cryptlib_crypt_CERTINFO_SUBJECTDIRECTORYATTRIBUTES\n#define cryptlib_crypt_CERTINFO_SUBJECTDIRECTORYATTRIBUTES 2262L\n#undef cryptlib_crypt_CERTINFO_SUBJECTDIR_TYPE\n#define cryptlib_crypt_CERTINFO_SUBJECTDIR_TYPE 2263L\n#undef cryptlib_crypt_CERTINFO_SUBJECTDIR_VALUES\n#define cryptlib_crypt_CERTINFO_SUBJECTDIR_VALUES 2264L\n#undef cryptlib_crypt_CERTINFO_SUBJECTKEYIDENTIFIER\n#define cryptlib_crypt_CERTINFO_SUBJECTKEYIDENTIFIER 2265L\n#undef cryptlib_crypt_CERTINFO_KEYUSAGE\n#define cryptlib_crypt_CERTINFO_KEYUSAGE 2266L\n#undef cryptlib_crypt_CERTINFO_PRIVATEKEYUSAGEPERIOD\n#define cryptlib_crypt_CERTINFO_PRIVATEKEYUSAGEPERIOD 2267L\n#undef cryptlib_crypt_CERTINFO_PRIVATEKEY_NOTBEFORE\n#define cryptlib_crypt_CERTINFO_PRIVATEKEY_NOTBEFORE 2268L\n#undef cryptlib_crypt_CERTINFO_PRIVATEKEY_NOTAFTER\n#define cryptlib_crypt_CERTINFO_PRIVATEKEY_NOTAFTER 2269L\n#undef cryptlib_crypt_CERTINFO_SUBJECTALTNAME\n#define cryptlib_crypt_CERTINFO_SUBJECTALTNAME 2270L\n#undef cryptlib_crypt_CERTINFO_ISSUERALTNAME\n#define cryptlib_crypt_CERTINFO_ISSUERALTNAME 2271L\n#undef cryptlib_crypt_CERTINFO_BASICCONSTRAINTS\n#define cryptlib_crypt_CERTINFO_BASICCONSTRAINTS 2272L\n#undef cryptlib_crypt_CERTINFO_CA\n#define cryptlib_crypt_CERTINFO_CA 2273L\n#undef cryptlib_crypt_CERTINFO_AUTHORITY\n#define cryptlib_crypt_CERTINFO_AUTHORITY 2273L\n#undef cryptlib_crypt_CERTINFO_PATHLENCONSTRAINT\n#define cryptlib_crypt_CERTINFO_PATHLENCONSTRAINT 2274L\n#undef cryptlib_crypt_CERTINFO_CRLNUMBER\n#define cryptlib_crypt_CERTINFO_CRLNUMBER 2275L\n#undef cryptlib_crypt_CERTINFO_CRLREASON\n#define cryptlib_crypt_CERTINFO_CRLREASON 2276L\n#undef cryptlib_crypt_CERTINFO_HOLDINSTRUCTIONCODE\n#define cryptlib_crypt_CERTINFO_HOLDINSTRUCTIONCODE 2277L\n#undef cryptlib_crypt_CERTINFO_INVALIDITYDATE\n#define cryptlib_crypt_CERTINFO_INVALIDITYDATE 2278L\n#undef cryptlib_crypt_CERTINFO_DELTACRLINDICATOR\n#define cryptlib_crypt_CERTINFO_DELTACRLINDICATOR 2279L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDISTRIBUTIONPOINT\n#define cryptlib_crypt_CERTINFO_ISSUINGDISTRIBUTIONPOINT 2280L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDIST_FULLNAME\n#define cryptlib_crypt_CERTINFO_ISSUINGDIST_FULLNAME 2281L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDIST_USERCERTSONLY\n#define cryptlib_crypt_CERTINFO_ISSUINGDIST_USERCERTSONLY 2282L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDIST_CACERTSONLY\n#define cryptlib_crypt_CERTINFO_ISSUINGDIST_CACERTSONLY 2283L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDIST_SOMEREASONSONLY\n#define cryptlib_crypt_CERTINFO_ISSUINGDIST_SOMEREASONSONLY 2284L\n#undef cryptlib_crypt_CERTINFO_ISSUINGDIST_INDIRECTCRL\n#define cryptlib_crypt_CERTINFO_ISSUINGDIST_INDIRECTCRL 2285L\n#undef cryptlib_crypt_CERTINFO_CERTIFICATEISSUER\n#define cryptlib_crypt_CERTINFO_CERTIFICATEISSUER 2286L\n#undef cryptlib_crypt_CERTINFO_NAMECONSTRAINTS\n#define cryptlib_crypt_CERTINFO_NAMECONSTRAINTS 2287L\n#undef cryptlib_crypt_CERTINFO_PERMITTEDSUBTREES\n#define cryptlib_crypt_CERTINFO_PERMITTEDSUBTREES 2288L\n#undef cryptlib_crypt_CERTINFO_EXCLUDEDSUBTREES\n#define cryptlib_crypt_CERTINFO_EXCLUDEDSUBTREES 2289L\n#undef cryptlib_crypt_CERTINFO_CRLDISTRIBUTIONPOINT\n#define cryptlib_crypt_CERTINFO_CRLDISTRIBUTIONPOINT 2290L\n#undef cryptlib_crypt_CERTINFO_CRLDIST_FULLNAME\n#define cryptlib_crypt_CERTINFO_CRLDIST_FULLNAME 2291L\n#undef cryptlib_crypt_CERTINFO_CRLDIST_REASONS\n#define cryptlib_crypt_CERTINFO_CRLDIST_REASONS 2292L\n#undef cryptlib_crypt_CERTINFO_CRLDIST_CRLISSUER\n#define cryptlib_crypt_CERTINFO_CRLDIST_CRLISSUER 2293L\n#undef cryptlib_crypt_CERTINFO_CERTIFICATEPOLICIES\n#define cryptlib_crypt_CERTINFO_CERTIFICATEPOLICIES 2294L\n#undef cryptlib_crypt_CERTINFO_CERTPOLICYID\n#define cryptlib_crypt_CERTINFO_CERTPOLICYID 2295L\n#undef cryptlib_crypt_CERTINFO_CERTPOLICY_CPSURI\n#define cryptlib_crypt_CERTINFO_CERTPOLICY_CPSURI 2296L\n#undef cryptlib_crypt_CERTINFO_CERTPOLICY_ORGANIZATION\n#define cryptlib_crypt_CERTINFO_CERTPOLICY_ORGANIZATION 2297L\n#undef cryptlib_crypt_CERTINFO_CERTPOLICY_NOTICENUMBERS\n#define cryptlib_crypt_CERTINFO_CERTPOLICY_NOTICENUMBERS 2298L\n#undef cryptlib_crypt_CERTINFO_CERTPOLICY_EXPLICITTEXT\n#define cryptlib_crypt_CERTINFO_CERTPOLICY_EXPLICITTEXT 2299L\n#undef cryptlib_crypt_CERTINFO_POLICYMAPPINGS\n#define cryptlib_crypt_CERTINFO_POLICYMAPPINGS 2300L\n#undef cryptlib_crypt_CERTINFO_ISSUERDOMAINPOLICY\n#define cryptlib_crypt_CERTINFO_ISSUERDOMAINPOLICY 2301L\n#undef cryptlib_crypt_CERTINFO_SUBJECTDOMAINPOLICY\n#define cryptlib_crypt_CERTINFO_SUBJECTDOMAINPOLICY 2302L\n#undef cryptlib_crypt_CERTINFO_AUTHORITYKEYIDENTIFIER\n#define cryptlib_crypt_CERTINFO_AUTHORITYKEYIDENTIFIER 2303L\n#undef cryptlib_crypt_CERTINFO_AUTHORITY_KEYIDENTIFIER\n#define cryptlib_crypt_CERTINFO_AUTHORITY_KEYIDENTIFIER 2304L\n#undef cryptlib_crypt_CERTINFO_AUTHORITY_CERTISSUER\n#define cryptlib_crypt_CERTINFO_AUTHORITY_CERTISSUER 2305L\n#undef cryptlib_crypt_CERTINFO_AUTHORITY_CERTSERIALNUMBER\n#define cryptlib_crypt_CERTINFO_AUTHORITY_CERTSERIALNUMBER 2306L\n#undef cryptlib_crypt_CERTINFO_POLICYCONSTRAINTS\n#define cryptlib_crypt_CERTINFO_POLICYCONSTRAINTS 2307L\n#undef cryptlib_crypt_CERTINFO_REQUIREEXPLICITPOLICY\n#define cryptlib_crypt_CERTINFO_REQUIREEXPLICITPOLICY 2308L\n#undef cryptlib_crypt_CERTINFO_INHIBITPOLICYMAPPING\n#define cryptlib_crypt_CERTINFO_INHIBITPOLICYMAPPING 2309L\n#undef cryptlib_crypt_CERTINFO_EXTKEYUSAGE\n#define cryptlib_crypt_CERTINFO_EXTKEYUSAGE 2310L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING 2311L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING 2312L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING 2313L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING 2314L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO 2315L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM\n#define cryptlib_crypt_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM 2316L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_SERVERAUTH\n#define cryptlib_crypt_CERTINFO_EXTKEY_SERVERAUTH 2317L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_CLIENTAUTH\n#define cryptlib_crypt_CERTINFO_EXTKEY_CLIENTAUTH 2318L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_CODESIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_CODESIGNING 2319L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_EMAILPROTECTION\n#define cryptlib_crypt_CERTINFO_EXTKEY_EMAILPROTECTION 2320L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_IPSECENDSYSTEM\n#define cryptlib_crypt_CERTINFO_EXTKEY_IPSECENDSYSTEM 2321L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_IPSECTUNNEL\n#define cryptlib_crypt_CERTINFO_EXTKEY_IPSECTUNNEL 2322L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_IPSECUSER\n#define cryptlib_crypt_CERTINFO_EXTKEY_IPSECUSER 2323L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_TIMESTAMPING\n#define cryptlib_crypt_CERTINFO_EXTKEY_TIMESTAMPING 2324L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_OCSPSIGNING\n#define cryptlib_crypt_CERTINFO_EXTKEY_OCSPSIGNING 2325L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_DIRECTORYSERVICE\n#define cryptlib_crypt_CERTINFO_EXTKEY_DIRECTORYSERVICE 2326L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_ANYKEYUSAGE\n#define cryptlib_crypt_CERTINFO_EXTKEY_ANYKEYUSAGE 2327L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO\n#define cryptlib_crypt_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO 2328L\n#undef cryptlib_crypt_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA\n#define cryptlib_crypt_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA 2329L\n#undef cryptlib_crypt_CERTINFO_EXTKEYUSAGE_LAST\n#define cryptlib_crypt_CERTINFO_EXTKEYUSAGE_LAST 2329L\n#undef cryptlib_crypt_CERTINFO_CRLSTREAMIDENTIFIER\n#define cryptlib_crypt_CERTINFO_CRLSTREAMIDENTIFIER 2330L\n#undef cryptlib_crypt_CERTINFO_FRESHESTCRL\n#define cryptlib_crypt_CERTINFO_FRESHESTCRL 2331L\n#undef cryptlib_crypt_CERTINFO_FRESHESTCRL_FULLNAME\n#define cryptlib_crypt_CERTINFO_FRESHESTCRL_FULLNAME 2332L\n#undef cryptlib_crypt_CERTINFO_FRESHESTCRL_REASONS\n#define cryptlib_crypt_CERTINFO_FRESHESTCRL_REASONS 2333L\n#undef cryptlib_crypt_CERTINFO_FRESHESTCRL_CRLISSUER\n#define cryptlib_crypt_CERTINFO_FRESHESTCRL_CRLISSUER 2334L\n#undef cryptlib_crypt_CERTINFO_ORDEREDLIST\n#define cryptlib_crypt_CERTINFO_ORDEREDLIST 2335L\n#undef cryptlib_crypt_CERTINFO_BASEUPDATETIME\n#define cryptlib_crypt_CERTINFO_BASEUPDATETIME 2336L\n#undef cryptlib_crypt_CERTINFO_DELTAINFO\n#define cryptlib_crypt_CERTINFO_DELTAINFO 2337L\n#undef cryptlib_crypt_CERTINFO_DELTAINFO_LOCATION\n#define cryptlib_crypt_CERTINFO_DELTAINFO_LOCATION 2338L\n#undef cryptlib_crypt_CERTINFO_DELTAINFO_NEXTDELTA\n#define cryptlib_crypt_CERTINFO_DELTAINFO_NEXTDELTA 2339L\n#undef cryptlib_crypt_CERTINFO_INHIBITANYPOLICY\n#define cryptlib_crypt_CERTINFO_INHIBITANYPOLICY 2340L\n#undef cryptlib_crypt_CERTINFO_TOBEREVOKED\n#define cryptlib_crypt_CERTINFO_TOBEREVOKED 2341L\n#undef cryptlib_crypt_CERTINFO_TOBEREVOKED_CERTISSUER\n#define cryptlib_crypt_CERTINFO_TOBEREVOKED_CERTISSUER 2342L\n#undef cryptlib_crypt_CERTINFO_TOBEREVOKED_REASONCODE\n#define cryptlib_crypt_CERTINFO_TOBEREVOKED_REASONCODE 2343L\n#undef cryptlib_crypt_CERTINFO_TOBEREVOKED_REVOCATIONTIME\n#define cryptlib_crypt_CERTINFO_TOBEREVOKED_REVOCATIONTIME 2344L\n#undef cryptlib_crypt_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER\n#define cryptlib_crypt_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER 2345L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS 2346L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS_CERTISSUER\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS_CERTISSUER 2347L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS_REASONCODE\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS_REASONCODE 2348L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE 2349L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER 2350L\n#undef cryptlib_crypt_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER\n#define cryptlib_crypt_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER 2351L\n#undef cryptlib_crypt_CERTINFO_EXPIREDCERTSONCRL\n#define cryptlib_crypt_CERTINFO_EXPIREDCERTSONCRL 2352L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDISTRIBUTIONPOINT\n#define cryptlib_crypt_CERTINFO_AAISSUINGDISTRIBUTIONPOINT 2353L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_FULLNAME\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_FULLNAME 2354L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY 2355L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_INDIRECTCRL\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_INDIRECTCRL 2356L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_USERATTRCERTS\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_USERATTRCERTS 2357L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_AACERTS\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_AACERTS 2358L\n#undef cryptlib_crypt_CERTINFO_AAISSUINGDIST_SOACERTS\n#define cryptlib_crypt_CERTINFO_AAISSUINGDIST_SOACERTS 2359L\n#undef cryptlib_crypt_CERTINFO_NS_CERTTYPE\n#define cryptlib_crypt_CERTINFO_NS_CERTTYPE 2360L\n#undef cryptlib_crypt_CERTINFO_NS_BASEURL\n#define cryptlib_crypt_CERTINFO_NS_BASEURL 2361L\n#undef cryptlib_crypt_CERTINFO_NS_REVOCATIONURL\n#define cryptlib_crypt_CERTINFO_NS_REVOCATIONURL 2362L\n#undef cryptlib_crypt_CERTINFO_NS_CAREVOCATIONURL\n#define cryptlib_crypt_CERTINFO_NS_CAREVOCATIONURL 2363L\n#undef cryptlib_crypt_CERTINFO_NS_CERTRENEWALURL\n#define cryptlib_crypt_CERTINFO_NS_CERTRENEWALURL 2364L\n#undef cryptlib_crypt_CERTINFO_NS_CAPOLICYURL\n#define cryptlib_crypt_CERTINFO_NS_CAPOLICYURL 2365L\n#undef cryptlib_crypt_CERTINFO_NS_SSLSERVERNAME\n#define cryptlib_crypt_CERTINFO_NS_SSLSERVERNAME 2366L\n#undef cryptlib_crypt_CERTINFO_NS_COMMENT\n#define cryptlib_crypt_CERTINFO_NS_COMMENT 2367L\n#undef cryptlib_crypt_CERTINFO_SET_HASHEDROOTKEY\n#define cryptlib_crypt_CERTINFO_SET_HASHEDROOTKEY 2368L\n#undef cryptlib_crypt_CERTINFO_SET_ROOTKEYTHUMBPRINT\n#define cryptlib_crypt_CERTINFO_SET_ROOTKEYTHUMBPRINT 2369L\n#undef cryptlib_crypt_CERTINFO_SET_CERTIFICATETYPE\n#define cryptlib_crypt_CERTINFO_SET_CERTIFICATETYPE 2370L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTDATA\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTDATA 2371L\n#undef cryptlib_crypt_CERTINFO_SET_MERID\n#define cryptlib_crypt_CERTINFO_SET_MERID 2372L\n#undef cryptlib_crypt_CERTINFO_SET_MERACQUIRERBIN\n#define cryptlib_crypt_CERTINFO_SET_MERACQUIRERBIN 2373L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTLANGUAGE\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTLANGUAGE 2374L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTNAME\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTNAME 2375L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTCITY\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTCITY 2376L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTSTATEPROVINCE\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTSTATEPROVINCE 2377L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTPOSTALCODE\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTPOSTALCODE 2378L\n#undef cryptlib_crypt_CERTINFO_SET_MERCHANTCOUNTRYNAME\n#define cryptlib_crypt_CERTINFO_SET_MERCHANTCOUNTRYNAME 2379L\n#undef cryptlib_crypt_CERTINFO_SET_MERCOUNTRY\n#define cryptlib_crypt_CERTINFO_SET_MERCOUNTRY 2380L\n#undef cryptlib_crypt_CERTINFO_SET_MERAUTHFLAG\n#define cryptlib_crypt_CERTINFO_SET_MERAUTHFLAG 2381L\n#undef cryptlib_crypt_CERTINFO_SET_CERTCARDREQUIRED\n#define cryptlib_crypt_CERTINFO_SET_CERTCARDREQUIRED 2382L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELING\n#define cryptlib_crypt_CERTINFO_SET_TUNNELING 2383L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELLING\n#define cryptlib_crypt_CERTINFO_SET_TUNNELLING 2383L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELINGFLAG\n#define cryptlib_crypt_CERTINFO_SET_TUNNELINGFLAG 2384L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELLINGFLAG\n#define cryptlib_crypt_CERTINFO_SET_TUNNELLINGFLAG 2384L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELINGALGID\n#define cryptlib_crypt_CERTINFO_SET_TUNNELINGALGID 2385L\n#undef cryptlib_crypt_CERTINFO_SET_TUNNELLINGALGID\n#define cryptlib_crypt_CERTINFO_SET_TUNNELLINGALGID 2385L\n#undef cryptlib_crypt_CERTINFO_CMS_CONTENTTYPE\n#define cryptlib_crypt_CERTINFO_CMS_CONTENTTYPE 2500L\n#undef cryptlib_crypt_CERTINFO_CMS_MESSAGEDIGEST\n#define cryptlib_crypt_CERTINFO_CMS_MESSAGEDIGEST 2501L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGTIME\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGTIME 2502L\n#undef cryptlib_crypt_CERTINFO_CMS_COUNTERSIGNATURE\n#define cryptlib_crypt_CERTINFO_CMS_COUNTERSIGNATURE 2503L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGDESCRIPTION\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGDESCRIPTION 2504L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAPABILITIES\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAPABILITIES 2505L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_3DES\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_3DES 2506L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AES\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AES 2507L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_CAST128\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_CAST128 2508L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHAng\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHAng 2509L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHA2\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHA2 2510L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHA1\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_SHA1 2511L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHAng\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHAng 2512L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHA2\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHA2 2513L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHA1\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_HMAC_SHA1 2514L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AUTHENC256\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AUTHENC256 2515L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AUTHENC128\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_AUTHENC128 2516L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHAng\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHAng 2517L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHA2\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHA2 2518L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHA1\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_RSA_SHA1 2519L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_DSA_SHA1\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_DSA_SHA1 2520L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng 2521L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2 2522L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1 2523L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA 2524L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY 2525L\n#undef cryptlib_crypt_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE\n#define cryptlib_crypt_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE 2526L\n#undef cryptlib_crypt_CERTINFO_CMS_RECEIPTREQUEST\n#define cryptlib_crypt_CERTINFO_CMS_RECEIPTREQUEST 2527L\n#undef cryptlib_crypt_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER\n#define cryptlib_crypt_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER 2528L\n#undef cryptlib_crypt_CERTINFO_CMS_RECEIPT_FROM\n#define cryptlib_crypt_CERTINFO_CMS_RECEIPT_FROM 2529L\n#undef cryptlib_crypt_CERTINFO_CMS_RECEIPT_TO\n#define cryptlib_crypt_CERTINFO_CMS_RECEIPT_TO 2530L\n#undef cryptlib_crypt_CERTINFO_CMS_SECURITYLABEL\n#define cryptlib_crypt_CERTINFO_CMS_SECURITYLABEL 2531L\n#undef cryptlib_crypt_CERTINFO_CMS_SECLABEL_POLICY\n#define cryptlib_crypt_CERTINFO_CMS_SECLABEL_POLICY 2532L\n#undef cryptlib_crypt_CERTINFO_CMS_SECLABEL_CLASSIFICATION\n#define cryptlib_crypt_CERTINFO_CMS_SECLABEL_CLASSIFICATION 2533L\n#undef cryptlib_crypt_CERTINFO_CMS_SECLABEL_PRIVACYMARK\n#define cryptlib_crypt_CERTINFO_CMS_SECLABEL_PRIVACYMARK 2534L\n#undef cryptlib_crypt_CERTINFO_CMS_SECLABEL_CATTYPE\n#define cryptlib_crypt_CERTINFO_CMS_SECLABEL_CATTYPE 2535L\n#undef cryptlib_crypt_CERTINFO_CMS_SECLABEL_CATVALUE\n#define cryptlib_crypt_CERTINFO_CMS_SECLABEL_CATVALUE 2536L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXPANSIONHISTORY\n#define cryptlib_crypt_CERTINFO_CMS_MLEXPANSIONHISTORY 2537L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER\n#define cryptlib_crypt_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER 2538L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXP_TIME\n#define cryptlib_crypt_CERTINFO_CMS_MLEXP_TIME 2539L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXP_NONE\n#define cryptlib_crypt_CERTINFO_CMS_MLEXP_NONE 2540L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXP_INSTEADOF\n#define cryptlib_crypt_CERTINFO_CMS_MLEXP_INSTEADOF 2541L\n#undef cryptlib_crypt_CERTINFO_CMS_MLEXP_INADDITIONTO\n#define cryptlib_crypt_CERTINFO_CMS_MLEXP_INADDITIONTO 2542L\n#undef cryptlib_crypt_CERTINFO_CMS_CONTENTHINTS\n#define cryptlib_crypt_CERTINFO_CMS_CONTENTHINTS 2543L\n#undef cryptlib_crypt_CERTINFO_CMS_CONTENTHINT_DESCRIPTION\n#define cryptlib_crypt_CERTINFO_CMS_CONTENTHINT_DESCRIPTION 2544L\n#undef cryptlib_crypt_CERTINFO_CMS_CONTENTHINT_TYPE\n#define cryptlib_crypt_CERTINFO_CMS_CONTENTHINT_TYPE 2545L\n#undef cryptlib_crypt_CERTINFO_CMS_EQUIVALENTLABEL\n#define cryptlib_crypt_CERTINFO_CMS_EQUIVALENTLABEL 2546L\n#undef cryptlib_crypt_CERTINFO_CMS_EQVLABEL_POLICY\n#define cryptlib_crypt_CERTINFO_CMS_EQVLABEL_POLICY 2547L\n#undef cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CLASSIFICATION\n#define cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CLASSIFICATION 2548L\n#undef cryptlib_crypt_CERTINFO_CMS_EQVLABEL_PRIVACYMARK\n#define cryptlib_crypt_CERTINFO_CMS_EQVLABEL_PRIVACYMARK 2549L\n#undef cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CATTYPE\n#define cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CATTYPE 2550L\n#undef cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CATVALUE\n#define cryptlib_crypt_CERTINFO_CMS_EQVLABEL_CATVALUE 2551L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTIFICATE\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTIFICATE 2552L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERT_ESSCERTID\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERT_ESSCERTID 2553L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERT_POLICIES\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERT_POLICIES 2554L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTIFICATEV2\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTIFICATEV2 2555L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2 2556L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTV2_POLICIES\n#define cryptlib_crypt_CERTINFO_CMS_SIGNINGCERTV2_POLICIES 2557L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGNATUREPOLICYID\n#define cryptlib_crypt_CERTINFO_CMS_SIGNATUREPOLICYID 2558L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICYID\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICYID 2559L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICYHASH\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICYHASH 2560L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_CPSURI\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_CPSURI 2561L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_ORGANIZATION\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_ORGANIZATION 2562L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS 2563L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT\n#define cryptlib_crypt_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT 2564L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGTYPEIDENTIFIER\n#define cryptlib_crypt_CERTINFO_CMS_SIGTYPEIDENTIFIER 2565L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG\n#define cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG 2566L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_DOMAINSIG\n#define cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_DOMAINSIG 2567L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES\n#define cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES 2568L\n#undef cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_REVIEWSIG\n#define cryptlib_crypt_CERTINFO_CMS_SIGTYPEID_REVIEWSIG 2569L\n#undef cryptlib_crypt_CERTINFO_CMS_NONCE\n#define cryptlib_crypt_CERTINFO_CMS_NONCE 2570L\n#undef cryptlib_crypt_CERTINFO_SCEP_MESSAGETYPE\n#define cryptlib_crypt_CERTINFO_SCEP_MESSAGETYPE 2571L\n#undef cryptlib_crypt_CERTINFO_SCEP_PKISTATUS\n#define cryptlib_crypt_CERTINFO_SCEP_PKISTATUS 2572L\n#undef cryptlib_crypt_CERTINFO_SCEP_FAILINFO\n#define cryptlib_crypt_CERTINFO_SCEP_FAILINFO 2573L\n#undef cryptlib_crypt_CERTINFO_SCEP_SENDERNONCE\n#define cryptlib_crypt_CERTINFO_SCEP_SENDERNONCE 2574L\n#undef cryptlib_crypt_CERTINFO_SCEP_RECIPIENTNONCE\n#define cryptlib_crypt_CERTINFO_SCEP_RECIPIENTNONCE 2575L\n#undef cryptlib_crypt_CERTINFO_SCEP_TRANSACTIONID\n#define cryptlib_crypt_CERTINFO_SCEP_TRANSACTIONID 2576L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCAGENCYINFO\n#define cryptlib_crypt_CERTINFO_CMS_SPCAGENCYINFO 2577L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCAGENCYURL\n#define cryptlib_crypt_CERTINFO_CMS_SPCAGENCYURL 2578L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCSTATEMENTTYPE\n#define cryptlib_crypt_CERTINFO_CMS_SPCSTATEMENTTYPE 2579L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING\n#define cryptlib_crypt_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING 2580L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING\n#define cryptlib_crypt_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING 2581L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO\n#define cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO 2582L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO_NAME\n#define cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO_NAME 2583L\n#undef cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO_URL\n#define cryptlib_crypt_CERTINFO_CMS_SPCOPUSINFO_URL 2584L\n#undef cryptlib_crypt_CERTINFO_LAST\n#define cryptlib_crypt_CERTINFO_LAST 2585L\n#undef cryptlib_crypt_KEYINFO_FIRST\n#define cryptlib_crypt_KEYINFO_FIRST 3000L\n#undef cryptlib_crypt_KEYINFO_QUERY\n#define cryptlib_crypt_KEYINFO_QUERY 3001L\n#undef cryptlib_crypt_KEYINFO_QUERY_REQUESTS\n#define cryptlib_crypt_KEYINFO_QUERY_REQUESTS 3002L\n#undef cryptlib_crypt_KEYINFO_LAST\n#define cryptlib_crypt_KEYINFO_LAST 3003L\n#undef cryptlib_crypt_DEVINFO_FIRST\n#define cryptlib_crypt_DEVINFO_FIRST 4000L\n#undef cryptlib_crypt_DEVINFO_INITIALISE\n#define cryptlib_crypt_DEVINFO_INITIALISE 4001L\n#undef cryptlib_crypt_DEVINFO_INITIALIZE\n#define cryptlib_crypt_DEVINFO_INITIALIZE 4001L\n#undef cryptlib_crypt_DEVINFO_AUTHENT_USER\n#define cryptlib_crypt_DEVINFO_AUTHENT_USER 4002L\n#undef cryptlib_crypt_DEVINFO_AUTHENT_SUPERVISOR\n#define cryptlib_crypt_DEVINFO_AUTHENT_SUPERVISOR 4003L\n#undef cryptlib_crypt_DEVINFO_SET_AUTHENT_USER\n#define cryptlib_crypt_DEVINFO_SET_AUTHENT_USER 4004L\n#undef cryptlib_crypt_DEVINFO_SET_AUTHENT_SUPERVISOR\n#define cryptlib_crypt_DEVINFO_SET_AUTHENT_SUPERVISOR 4005L\n#undef cryptlib_crypt_DEVINFO_ZEROISE\n#define cryptlib_crypt_DEVINFO_ZEROISE 4006L\n#undef cryptlib_crypt_DEVINFO_ZEROIZE\n#define cryptlib_crypt_DEVINFO_ZEROIZE 4006L\n#undef cryptlib_crypt_DEVINFO_LOGGEDIN\n#define cryptlib_crypt_DEVINFO_LOGGEDIN 4007L\n#undef cryptlib_crypt_DEVINFO_LABEL\n#define cryptlib_crypt_DEVINFO_LABEL 4008L\n#undef cryptlib_crypt_DEVINFO_LAST\n#define cryptlib_crypt_DEVINFO_LAST 4009L\n#undef cryptlib_crypt_ENVINFO_FIRST\n#define cryptlib_crypt_ENVINFO_FIRST 5000L\n#undef cryptlib_crypt_ENVINFO_DATASIZE\n#define cryptlib_crypt_ENVINFO_DATASIZE 5001L\n#undef cryptlib_crypt_ENVINFO_COMPRESSION\n#define cryptlib_crypt_ENVINFO_COMPRESSION 5002L\n#undef cryptlib_crypt_ENVINFO_CONTENTTYPE\n#define cryptlib_crypt_ENVINFO_CONTENTTYPE 5003L\n#undef cryptlib_crypt_ENVINFO_DETACHEDSIGNATURE\n#define cryptlib_crypt_ENVINFO_DETACHEDSIGNATURE 5004L\n#undef cryptlib_crypt_ENVINFO_SIGNATURE_RESULT\n#define cryptlib_crypt_ENVINFO_SIGNATURE_RESULT 5005L\n#undef cryptlib_crypt_ENVINFO_INTEGRITY\n#define cryptlib_crypt_ENVINFO_INTEGRITY 5006L\n#undef cryptlib_crypt_ENVINFO_PASSWORD\n#define cryptlib_crypt_ENVINFO_PASSWORD 5007L\n#undef cryptlib_crypt_ENVINFO_KEY\n#define cryptlib_crypt_ENVINFO_KEY 5008L\n#undef cryptlib_crypt_ENVINFO_SIGNATURE\n#define cryptlib_crypt_ENVINFO_SIGNATURE 5009L\n#undef cryptlib_crypt_ENVINFO_SIGNATURE_EXTRADATA\n#define cryptlib_crypt_ENVINFO_SIGNATURE_EXTRADATA 5010L\n#undef cryptlib_crypt_ENVINFO_RECIPIENT\n#define cryptlib_crypt_ENVINFO_RECIPIENT 5011L\n#undef cryptlib_crypt_ENVINFO_PUBLICKEY\n#define cryptlib_crypt_ENVINFO_PUBLICKEY 5012L\n#undef cryptlib_crypt_ENVINFO_PRIVATEKEY\n#define cryptlib_crypt_ENVINFO_PRIVATEKEY 5013L\n#undef cryptlib_crypt_ENVINFO_PRIVATEKEY_LABEL\n#define cryptlib_crypt_ENVINFO_PRIVATEKEY_LABEL 5014L\n#undef cryptlib_crypt_ENVINFO_ORIGINATOR\n#define cryptlib_crypt_ENVINFO_ORIGINATOR 5015L\n#undef cryptlib_crypt_ENVINFO_SESSIONKEY\n#define cryptlib_crypt_ENVINFO_SESSIONKEY 5016L\n#undef cryptlib_crypt_ENVINFO_HASH\n#define cryptlib_crypt_ENVINFO_HASH 5017L\n#undef cryptlib_crypt_ENVINFO_TIMESTAMP\n#define cryptlib_crypt_ENVINFO_TIMESTAMP 5018L\n#undef cryptlib_crypt_ENVINFO_KEYSET_SIGCHECK\n#define cryptlib_crypt_ENVINFO_KEYSET_SIGCHECK 5019L\n#undef cryptlib_crypt_ENVINFO_KEYSET_ENCRYPT\n#define cryptlib_crypt_ENVINFO_KEYSET_ENCRYPT 5020L\n#undef cryptlib_crypt_ENVINFO_KEYSET_DECRYPT\n#define cryptlib_crypt_ENVINFO_KEYSET_DECRYPT 5021L\n#undef cryptlib_crypt_ENVINFO_LAST\n#define cryptlib_crypt_ENVINFO_LAST 5022L\n#undef cryptlib_crypt_SESSINFO_FIRST\n#define cryptlib_crypt_SESSINFO_FIRST 6000L\n#undef cryptlib_crypt_SESSINFO_ACTIVE\n#define cryptlib_crypt_SESSINFO_ACTIVE 6001L\n#undef cryptlib_crypt_SESSINFO_CONNECTIONACTIVE\n#define cryptlib_crypt_SESSINFO_CONNECTIONACTIVE 6002L\n#undef cryptlib_crypt_SESSINFO_USERNAME\n#define cryptlib_crypt_SESSINFO_USERNAME 6003L\n#undef cryptlib_crypt_SESSINFO_PASSWORD\n#define cryptlib_crypt_SESSINFO_PASSWORD 6004L\n#undef cryptlib_crypt_SESSINFO_PRIVATEKEY\n#define cryptlib_crypt_SESSINFO_PRIVATEKEY 6005L\n#undef cryptlib_crypt_SESSINFO_KEYSET\n#define cryptlib_crypt_SESSINFO_KEYSET 6006L\n#undef cryptlib_crypt_SESSINFO_AUTHRESPONSE\n#define cryptlib_crypt_SESSINFO_AUTHRESPONSE 6007L\n#undef cryptlib_crypt_SESSINFO_SERVER_NAME\n#define cryptlib_crypt_SESSINFO_SERVER_NAME 6008L\n#undef cryptlib_crypt_SESSINFO_SERVER_PORT\n#define cryptlib_crypt_SESSINFO_SERVER_PORT 6009L\n#undef cryptlib_crypt_SESSINFO_SERVER_FINGERPRINT_SHA1\n#define cryptlib_crypt_SESSINFO_SERVER_FINGERPRINT_SHA1 6010L\n#undef cryptlib_crypt_SESSINFO_CLIENT_NAME\n#define cryptlib_crypt_SESSINFO_CLIENT_NAME 6011L\n#undef cryptlib_crypt_SESSINFO_CLIENT_PORT\n#define cryptlib_crypt_SESSINFO_CLIENT_PORT 6012L\n#undef cryptlib_crypt_SESSINFO_SESSION\n#define cryptlib_crypt_SESSINFO_SESSION 6013L\n#undef cryptlib_crypt_SESSINFO_NETWORKSOCKET\n#define cryptlib_crypt_SESSINFO_NETWORKSOCKET 6014L\n#undef cryptlib_crypt_SESSINFO_VERSION\n#define cryptlib_crypt_SESSINFO_VERSION 6015L\n#undef cryptlib_crypt_SESSINFO_REQUEST\n#define cryptlib_crypt_SESSINFO_REQUEST 6016L\n#undef cryptlib_crypt_SESSINFO_RESPONSE\n#define cryptlib_crypt_SESSINFO_RESPONSE 6017L\n#undef cryptlib_crypt_SESSINFO_CACERTIFICATE\n#define cryptlib_crypt_SESSINFO_CACERTIFICATE 6018L\n#undef cryptlib_crypt_SESSINFO_CMP_REQUESTTYPE\n#define cryptlib_crypt_SESSINFO_CMP_REQUESTTYPE 6019L\n#undef cryptlib_crypt_SESSINFO_CMP_PRIVKEYSET\n#define cryptlib_crypt_SESSINFO_CMP_PRIVKEYSET 6020L\n#undef cryptlib_crypt_SESSINFO_SSH_CHANNEL\n#define cryptlib_crypt_SESSINFO_SSH_CHANNEL 6021L\n#undef cryptlib_crypt_SESSINFO_SSH_CHANNEL_TYPE\n#define cryptlib_crypt_SESSINFO_SSH_CHANNEL_TYPE 6022L\n#undef cryptlib_crypt_SESSINFO_SSH_CHANNEL_ARG1\n#define cryptlib_crypt_SESSINFO_SSH_CHANNEL_ARG1 6023L\n#undef cryptlib_crypt_SESSINFO_SSH_CHANNEL_ARG2\n#define cryptlib_crypt_SESSINFO_SSH_CHANNEL_ARG2 6024L\n#undef cryptlib_crypt_SESSINFO_SSH_CHANNEL_ACTIVE\n#define cryptlib_crypt_SESSINFO_SSH_CHANNEL_ACTIVE 6025L\n#undef cryptlib_crypt_SESSINFO_SSL_OPTIONS\n#define cryptlib_crypt_SESSINFO_SSL_OPTIONS 6026L\n#undef cryptlib_crypt_SESSINFO_SSL_SUBPROTOCOL\n#define cryptlib_crypt_SESSINFO_SSL_SUBPROTOCOL 6027L\n#undef cryptlib_crypt_SESSINFO_SSL_WSPROTOCOL\n#define cryptlib_crypt_SESSINFO_SSL_WSPROTOCOL 6028L\n#undef cryptlib_crypt_SESSINFO_SSL_EAPCHALLENGE\n#define cryptlib_crypt_SESSINFO_SSL_EAPCHALLENGE 6029L\n#undef cryptlib_crypt_SESSINFO_SSL_EAPKEY\n#define cryptlib_crypt_SESSINFO_SSL_EAPKEY 6030L\n#undef cryptlib_crypt_SESSINFO_TSP_MSGIMPRINT\n#define cryptlib_crypt_SESSINFO_TSP_MSGIMPRINT 6031L\n#undef cryptlib_crypt_SESSINFO_LAST\n#define cryptlib_crypt_SESSINFO_LAST 6032L\n#undef cryptlib_crypt_USERINFO_FIRST\n#define cryptlib_crypt_USERINFO_FIRST 7000L\n#undef cryptlib_crypt_USERINFO_PASSWORD\n#define cryptlib_crypt_USERINFO_PASSWORD 7001L\n#undef cryptlib_crypt_USERINFO_CAKEY_CERTSIGN\n#define cryptlib_crypt_USERINFO_CAKEY_CERTSIGN 7002L\n#undef cryptlib_crypt_USERINFO_CAKEY_CRLSIGN\n#define cryptlib_crypt_USERINFO_CAKEY_CRLSIGN 7003L\n#undef cryptlib_crypt_USERINFO_CAKEY_RTCSSIGN\n#define cryptlib_crypt_USERINFO_CAKEY_RTCSSIGN 7004L\n#undef cryptlib_crypt_USERINFO_CAKEY_OCSPSIGN\n#define cryptlib_crypt_USERINFO_CAKEY_OCSPSIGN 7005L\n#undef cryptlib_crypt_USERINFO_LAST\n#define cryptlib_crypt_USERINFO_LAST 7006L\n#undef cryptlib_crypt_ATTRIBUTE_LAST\n#define cryptlib_crypt_ATTRIBUTE_LAST 7006L\n#undef cryptlib_crypt_KEYUSAGE_NONE\n#define cryptlib_crypt_KEYUSAGE_NONE 0L\n#undef cryptlib_crypt_KEYUSAGE_DIGITALSIGNATURE\n#define cryptlib_crypt_KEYUSAGE_DIGITALSIGNATURE 1L\n#undef cryptlib_crypt_KEYUSAGE_NONREPUDIATION\n#define cryptlib_crypt_KEYUSAGE_NONREPUDIATION 2L\n#undef cryptlib_crypt_KEYUSAGE_KEYENCIPHERMENT\n#define cryptlib_crypt_KEYUSAGE_KEYENCIPHERMENT 4L\n#undef cryptlib_crypt_KEYUSAGE_DATAENCIPHERMENT\n#define cryptlib_crypt_KEYUSAGE_DATAENCIPHERMENT 8L\n#undef cryptlib_crypt_KEYUSAGE_KEYAGREEMENT\n#define cryptlib_crypt_KEYUSAGE_KEYAGREEMENT 16L\n#undef cryptlib_crypt_KEYUSAGE_KEYCERTSIGN\n#define cryptlib_crypt_KEYUSAGE_KEYCERTSIGN 32L\n#undef cryptlib_crypt_KEYUSAGE_CRLSIGN\n#define cryptlib_crypt_KEYUSAGE_CRLSIGN 64L\n#undef cryptlib_crypt_KEYUSAGE_ENCIPHERONLY\n#define cryptlib_crypt_KEYUSAGE_ENCIPHERONLY 128L\n#undef cryptlib_crypt_KEYUSAGE_DECIPHERONLY\n#define cryptlib_crypt_KEYUSAGE_DECIPHERONLY 256L\n#undef cryptlib_crypt_KEYUSAGE_LAST\n#define cryptlib_crypt_KEYUSAGE_LAST 512L\n#undef cryptlib_crypt_CRLREASON_UNSPECIFIED\n#define cryptlib_crypt_CRLREASON_UNSPECIFIED 0L\n#undef cryptlib_crypt_CRLREASON_KEYCOMPROMISE\n#define cryptlib_crypt_CRLREASON_KEYCOMPROMISE 1L\n#undef cryptlib_crypt_CRLREASON_CACOMPROMISE\n#define cryptlib_crypt_CRLREASON_CACOMPROMISE 2L\n#undef cryptlib_crypt_CRLREASON_AFFILIATIONCHANGED\n#define cryptlib_crypt_CRLREASON_AFFILIATIONCHANGED 3L\n#undef cryptlib_crypt_CRLREASON_SUPERSEDED\n#define cryptlib_crypt_CRLREASON_SUPERSEDED 4L\n#undef cryptlib_crypt_CRLREASON_CESSATIONOFOPERATION\n#define cryptlib_crypt_CRLREASON_CESSATIONOFOPERATION 5L\n#undef cryptlib_crypt_CRLREASON_CERTIFICATEHOLD\n#define cryptlib_crypt_CRLREASON_CERTIFICATEHOLD 6L\n#undef cryptlib_crypt_CRLREASON_REMOVEFROMCRL\n#define cryptlib_crypt_CRLREASON_REMOVEFROMCRL 8L\n#undef cryptlib_crypt_CRLREASON_PRIVILEGEWITHDRAWN\n#define cryptlib_crypt_CRLREASON_PRIVILEGEWITHDRAWN 9L\n#undef cryptlib_crypt_CRLREASON_AACOMPROMISE\n#define cryptlib_crypt_CRLREASON_AACOMPROMISE 10L\n#undef cryptlib_crypt_CRLREASON_LAST\n#define cryptlib_crypt_CRLREASON_LAST 11L\n#undef cryptlib_crypt_CRLREASON_NEVERVALID\n#define cryptlib_crypt_CRLREASON_NEVERVALID 20L\n#undef cryptlib_crypt_CRLEXTREASON_LAST\n#define cryptlib_crypt_CRLEXTREASON_LAST 21L\n#undef cryptlib_crypt_CRLREASONFLAG_UNUSED\n#define cryptlib_crypt_CRLREASONFLAG_UNUSED 1L\n#undef cryptlib_crypt_CRLREASONFLAG_KEYCOMPROMISE\n#define cryptlib_crypt_CRLREASONFLAG_KEYCOMPROMISE 2L\n#undef cryptlib_crypt_CRLREASONFLAG_CACOMPROMISE\n#define cryptlib_crypt_CRLREASONFLAG_CACOMPROMISE 4L\n#undef cryptlib_crypt_CRLREASONFLAG_AFFILIATIONCHANGED\n#define cryptlib_crypt_CRLREASONFLAG_AFFILIATIONCHANGED 8L\n#undef cryptlib_crypt_CRLREASONFLAG_SUPERSEDED\n#define cryptlib_crypt_CRLREASONFLAG_SUPERSEDED 16L\n#undef cryptlib_crypt_CRLREASONFLAG_CESSATIONOFOPERATION\n#define cryptlib_crypt_CRLREASONFLAG_CESSATIONOFOPERATION 32L\n#undef cryptlib_crypt_CRLREASONFLAG_CERTIFICATEHOLD\n#define cryptlib_crypt_CRLREASONFLAG_CERTIFICATEHOLD 64L\n#undef cryptlib_crypt_CRLREASONFLAG_LAST\n#define cryptlib_crypt_CRLREASONFLAG_LAST 128L\n#undef cryptlib_crypt_HOLDINSTRUCTION_NONE\n#define cryptlib_crypt_HOLDINSTRUCTION_NONE 0L\n#undef cryptlib_crypt_HOLDINSTRUCTION_CALLISSUER\n#define cryptlib_crypt_HOLDINSTRUCTION_CALLISSUER 1L\n#undef cryptlib_crypt_HOLDINSTRUCTION_REJECT\n#define cryptlib_crypt_HOLDINSTRUCTION_REJECT 2L\n#undef cryptlib_crypt_HOLDINSTRUCTION_PICKUPTOKEN\n#define cryptlib_crypt_HOLDINSTRUCTION_PICKUPTOKEN 3L\n#undef cryptlib_crypt_HOLDINSTRUCTION_LAST\n#define cryptlib_crypt_HOLDINSTRUCTION_LAST 4L\n#undef cryptlib_crypt_COMPLIANCELEVEL_OBLIVIOUS\n#define cryptlib_crypt_COMPLIANCELEVEL_OBLIVIOUS 0L\n#undef cryptlib_crypt_COMPLIANCELEVEL_REDUCED\n#define cryptlib_crypt_COMPLIANCELEVEL_REDUCED 1L\n#undef cryptlib_crypt_COMPLIANCELEVEL_STANDARD\n#define cryptlib_crypt_COMPLIANCELEVEL_STANDARD 2L\n#undef cryptlib_crypt_COMPLIANCELEVEL_PKIX_PARTIAL\n#define cryptlib_crypt_COMPLIANCELEVEL_PKIX_PARTIAL 3L\n#undef cryptlib_crypt_COMPLIANCELEVEL_PKIX_FULL\n#define cryptlib_crypt_COMPLIANCELEVEL_PKIX_FULL 4L\n#undef cryptlib_crypt_COMPLIANCELEVEL_LAST\n#define cryptlib_crypt_COMPLIANCELEVEL_LAST 5L\n#undef cryptlib_crypt_NS_CERTTYPE_SSLCLIENT\n#define cryptlib_crypt_NS_CERTTYPE_SSLCLIENT 1L\n#undef cryptlib_crypt_NS_CERTTYPE_SSLSERVER\n#define cryptlib_crypt_NS_CERTTYPE_SSLSERVER 2L\n#undef cryptlib_crypt_NS_CERTTYPE_SMIME\n#define cryptlib_crypt_NS_CERTTYPE_SMIME 4L\n#undef cryptlib_crypt_NS_CERTTYPE_OBJECTSIGNING\n#define cryptlib_crypt_NS_CERTTYPE_OBJECTSIGNING 8L\n#undef cryptlib_crypt_NS_CERTTYPE_RESERVED\n#define cryptlib_crypt_NS_CERTTYPE_RESERVED 16L\n#undef cryptlib_crypt_NS_CERTTYPE_SSLCA\n#define cryptlib_crypt_NS_CERTTYPE_SSLCA 32L\n#undef cryptlib_crypt_NS_CERTTYPE_SMIMECA\n#define cryptlib_crypt_NS_CERTTYPE_SMIMECA 64L\n#undef cryptlib_crypt_NS_CERTTYPE_OBJECTSIGNINGCA\n#define cryptlib_crypt_NS_CERTTYPE_OBJECTSIGNINGCA 128L\n#undef cryptlib_crypt_NS_CERTTYPE_LAST\n#define cryptlib_crypt_NS_CERTTYPE_LAST 256L\n#undef cryptlib_crypt_SET_CERTTYPE_CARD\n#define cryptlib_crypt_SET_CERTTYPE_CARD 1L\n#undef cryptlib_crypt_SET_CERTTYPE_MER\n#define cryptlib_crypt_SET_CERTTYPE_MER 2L\n#undef cryptlib_crypt_SET_CERTTYPE_PGWY\n#define cryptlib_crypt_SET_CERTTYPE_PGWY 4L\n#undef cryptlib_crypt_SET_CERTTYPE_CCA\n#define cryptlib_crypt_SET_CERTTYPE_CCA 8L\n#undef cryptlib_crypt_SET_CERTTYPE_MCA\n#define cryptlib_crypt_SET_CERTTYPE_MCA 16L\n#undef cryptlib_crypt_SET_CERTTYPE_PCA\n#define cryptlib_crypt_SET_CERTTYPE_PCA 32L\n#undef cryptlib_crypt_SET_CERTTYPE_GCA\n#define cryptlib_crypt_SET_CERTTYPE_GCA 64L\n#undef cryptlib_crypt_SET_CERTTYPE_BCA\n#define cryptlib_crypt_SET_CERTTYPE_BCA 128L\n#undef cryptlib_crypt_SET_CERTTYPE_RCA\n#define cryptlib_crypt_SET_CERTTYPE_RCA 256L\n#undef cryptlib_crypt_SET_CERTTYPE_ACQ\n#define cryptlib_crypt_SET_CERTTYPE_ACQ 512L\n#undef cryptlib_crypt_SET_CERTTYPE_LAST\n#define cryptlib_crypt_SET_CERTTYPE_LAST 1024L\n#undef cryptlib_crypt_CONTENT_NONE\n#define cryptlib_crypt_CONTENT_NONE 0L\n#undef cryptlib_crypt_CONTENT_DATA\n#define cryptlib_crypt_CONTENT_DATA 1L\n#undef cryptlib_crypt_CONTENT_SIGNEDDATA\n#define cryptlib_crypt_CONTENT_SIGNEDDATA 2L\n#undef cryptlib_crypt_CONTENT_ENVELOPEDDATA\n#define cryptlib_crypt_CONTENT_ENVELOPEDDATA 3L\n#undef cryptlib_crypt_CONTENT_SIGNEDANDENVELOPEDDATA\n#define cryptlib_crypt_CONTENT_SIGNEDANDENVELOPEDDATA 4L\n#undef cryptlib_crypt_CONTENT_DIGESTEDDATA\n#define cryptlib_crypt_CONTENT_DIGESTEDDATA 5L\n#undef cryptlib_crypt_CONTENT_ENCRYPTEDDATA\n#define cryptlib_crypt_CONTENT_ENCRYPTEDDATA 6L\n#undef cryptlib_crypt_CONTENT_COMPRESSEDDATA\n#define cryptlib_crypt_CONTENT_COMPRESSEDDATA 7L\n#undef cryptlib_crypt_CONTENT_AUTHDATA\n#define cryptlib_crypt_CONTENT_AUTHDATA 8L\n#undef cryptlib_crypt_CONTENT_AUTHENVDATA\n#define cryptlib_crypt_CONTENT_AUTHENVDATA 9L\n#undef cryptlib_crypt_CONTENT_TSTINFO\n#define cryptlib_crypt_CONTENT_TSTINFO 10L\n#undef cryptlib_crypt_CONTENT_SPCINDIRECTDATACONTEXT\n#define cryptlib_crypt_CONTENT_SPCINDIRECTDATACONTEXT 11L\n#undef cryptlib_crypt_CONTENT_RTCSREQUEST\n#define cryptlib_crypt_CONTENT_RTCSREQUEST 12L\n#undef cryptlib_crypt_CONTENT_RTCSRESPONSE\n#define cryptlib_crypt_CONTENT_RTCSRESPONSE 13L\n#undef cryptlib_crypt_CONTENT_RTCSRESPONSE_EXT\n#define cryptlib_crypt_CONTENT_RTCSRESPONSE_EXT 14L\n#undef cryptlib_crypt_CONTENT_MRTD\n#define cryptlib_crypt_CONTENT_MRTD 15L\n#undef cryptlib_crypt_CONTENT_LAST\n#define cryptlib_crypt_CONTENT_LAST 16L\n#undef cryptlib_crypt_CLASSIFICATION_UNMARKED\n#define cryptlib_crypt_CLASSIFICATION_UNMARKED 0L\n#undef cryptlib_crypt_CLASSIFICATION_UNCLASSIFIED\n#define cryptlib_crypt_CLASSIFICATION_UNCLASSIFIED 1L\n#undef cryptlib_crypt_CLASSIFICATION_RESTRICTED\n#define cryptlib_crypt_CLASSIFICATION_RESTRICTED 2L\n#undef cryptlib_crypt_CLASSIFICATION_CONFIDENTIAL\n#define cryptlib_crypt_CLASSIFICATION_CONFIDENTIAL 3L\n#undef cryptlib_crypt_CLASSIFICATION_SECRET\n#define cryptlib_crypt_CLASSIFICATION_SECRET 4L\n#undef cryptlib_crypt_CLASSIFICATION_TOP_SECRET\n#define cryptlib_crypt_CLASSIFICATION_TOP_SECRET 5L\n#undef cryptlib_crypt_CLASSIFICATION_LAST\n#define cryptlib_crypt_CLASSIFICATION_LAST 255L\n#undef cryptlib_crypt_CERTSTATUS_NONE\n#define cryptlib_crypt_CERTSTATUS_NONE 0L\n#undef cryptlib_crypt_CERTSTATUS_VALID\n#define cryptlib_crypt_CERTSTATUS_VALID 1L\n#undef cryptlib_crypt_CERTSTATUS_NOTVALID\n#define cryptlib_crypt_CERTSTATUS_NOTVALID 2L\n#undef cryptlib_crypt_CERTSTATUS_NONAUTHORITATIVE\n#define cryptlib_crypt_CERTSTATUS_NONAUTHORITATIVE 3L\n#undef cryptlib_crypt_CERTSTATUS_UNKNOWN\n#define cryptlib_crypt_CERTSTATUS_UNKNOWN 4L\n#undef cryptlib_crypt_CERTSTATUS_LAST\n#define cryptlib_crypt_CERTSTATUS_LAST 5L\n#undef cryptlib_crypt_OCSPSTATUS_NOTREVOKED\n#define cryptlib_crypt_OCSPSTATUS_NOTREVOKED 0L\n#undef cryptlib_crypt_OCSPSTATUS_REVOKED\n#define cryptlib_crypt_OCSPSTATUS_REVOKED 1L\n#undef cryptlib_crypt_OCSPSTATUS_UNKNOWN\n#define cryptlib_crypt_OCSPSTATUS_UNKNOWN 2L\n#undef cryptlib_crypt_SIGNATURELEVEL_NONE\n#define cryptlib_crypt_SIGNATURELEVEL_NONE 0L\n#undef cryptlib_crypt_SIGNATURELEVEL_SIGNERCERT\n#define cryptlib_crypt_SIGNATURELEVEL_SIGNERCERT 1L\n#undef cryptlib_crypt_SIGNATURELEVEL_ALL\n#define cryptlib_crypt_SIGNATURELEVEL_ALL 2L\n#undef cryptlib_crypt_SIGNATURELEVEL_LAST\n#define cryptlib_crypt_SIGNATURELEVEL_LAST 3L\n#undef cryptlib_crypt_INTEGRITY_NONE\n#define cryptlib_crypt_INTEGRITY_NONE 0L\n#undef cryptlib_crypt_INTEGRITY_MACONLY\n#define cryptlib_crypt_INTEGRITY_MACONLY 1L\n#undef cryptlib_crypt_INTEGRITY_FULL\n#define cryptlib_crypt_INTEGRITY_FULL 2L\n#undef cryptlib_crypt_CERTFORMAT_NONE\n#define cryptlib_crypt_CERTFORMAT_NONE 0L\n#undef cryptlib_crypt_CERTFORMAT_CERTIFICATE\n#define cryptlib_crypt_CERTFORMAT_CERTIFICATE 1L\n#undef cryptlib_crypt_CERTFORMAT_CERTCHAIN\n#define cryptlib_crypt_CERTFORMAT_CERTCHAIN 2L\n#undef cryptlib_crypt_CERTFORMAT_TEXT_CERTIFICATE\n#define cryptlib_crypt_CERTFORMAT_TEXT_CERTIFICATE 3L\n#undef cryptlib_crypt_CERTFORMAT_TEXT_CERTCHAIN\n#define cryptlib_crypt_CERTFORMAT_TEXT_CERTCHAIN 4L\n#undef cryptlib_crypt_CERTFORMAT_XML_CERTIFICATE\n#define cryptlib_crypt_CERTFORMAT_XML_CERTIFICATE 5L\n#undef cryptlib_crypt_CERTFORMAT_XML_CERTCHAIN\n#define cryptlib_crypt_CERTFORMAT_XML_CERTCHAIN 6L\n#undef cryptlib_crypt_CERTFORMAT_LAST\n#define cryptlib_crypt_CERTFORMAT_LAST 7L\n#undef cryptlib_crypt_REQUESTTYPE_NONE\n#define cryptlib_crypt_REQUESTTYPE_NONE 0L\n#undef cryptlib_crypt_REQUESTTYPE_INITIALISATION\n#define cryptlib_crypt_REQUESTTYPE_INITIALISATION 1L\n#undef cryptlib_crypt_REQUESTTYPE_INITIALIZATION\n#define cryptlib_crypt_REQUESTTYPE_INITIALIZATION 1L\n#undef cryptlib_crypt_REQUESTTYPE_CERTIFICATE\n#define cryptlib_crypt_REQUESTTYPE_CERTIFICATE 2L\n#undef cryptlib_crypt_REQUESTTYPE_KEYUPDATE\n#define cryptlib_crypt_REQUESTTYPE_KEYUPDATE 3L\n#undef cryptlib_crypt_REQUESTTYPE_REVOCATION\n#define cryptlib_crypt_REQUESTTYPE_REVOCATION 4L\n#undef cryptlib_crypt_REQUESTTYPE_PKIBOOT\n#define cryptlib_crypt_REQUESTTYPE_PKIBOOT 5L\n#undef cryptlib_crypt_REQUESTTYPE_LAST\n#define cryptlib_crypt_REQUESTTYPE_LAST 6L\n#undef cryptlib_crypt_KEYID_NONE\n#define cryptlib_crypt_KEYID_NONE 0L\n#undef cryptlib_crypt_KEYID_NAME\n#define cryptlib_crypt_KEYID_NAME 1L\n#undef cryptlib_crypt_KEYID_URI\n#define cryptlib_crypt_KEYID_URI 2L\n#undef cryptlib_crypt_KEYID_EMAIL\n#define cryptlib_crypt_KEYID_EMAIL 2L\n#undef cryptlib_crypt_KEYID_LAST\n#define cryptlib_crypt_KEYID_LAST 3L\n#undef cryptlib_crypt_OBJECT_NONE\n#define cryptlib_crypt_OBJECT_NONE 0L\n#undef cryptlib_crypt_OBJECT_ENCRYPTED_KEY\n#define cryptlib_crypt_OBJECT_ENCRYPTED_KEY 1L\n#undef cryptlib_crypt_OBJECT_PKCENCRYPTED_KEY\n#define cryptlib_crypt_OBJECT_PKCENCRYPTED_KEY 2L\n#undef cryptlib_crypt_OBJECT_KEYAGREEMENT\n#define cryptlib_crypt_OBJECT_KEYAGREEMENT 3L\n#undef cryptlib_crypt_OBJECT_SIGNATURE\n#define cryptlib_crypt_OBJECT_SIGNATURE 4L\n#undef cryptlib_crypt_OBJECT_LAST\n#define cryptlib_crypt_OBJECT_LAST 5L\n#undef cryptlib_crypt_ERRTYPE_NONE\n#define cryptlib_crypt_ERRTYPE_NONE 0L\n#undef cryptlib_crypt_ERRTYPE_ATTR_SIZE\n#define cryptlib_crypt_ERRTYPE_ATTR_SIZE 1L\n#undef cryptlib_crypt_ERRTYPE_ATTR_VALUE\n#define cryptlib_crypt_ERRTYPE_ATTR_VALUE 2L\n#undef cryptlib_crypt_ERRTYPE_ATTR_ABSENT\n#define cryptlib_crypt_ERRTYPE_ATTR_ABSENT 3L\n#undef cryptlib_crypt_ERRTYPE_ATTR_PRESENT\n#define cryptlib_crypt_ERRTYPE_ATTR_PRESENT 4L\n#undef cryptlib_crypt_ERRTYPE_CONSTRAINT\n#define cryptlib_crypt_ERRTYPE_CONSTRAINT 5L\n#undef cryptlib_crypt_ERRTYPE_ISSUERCONSTRAINT\n#define cryptlib_crypt_ERRTYPE_ISSUERCONSTRAINT 6L\n#undef cryptlib_crypt_ERRTYPE_LAST\n#define cryptlib_crypt_ERRTYPE_LAST 7L\n#undef cryptlib_crypt_CERTACTION_NONE\n#define cryptlib_crypt_CERTACTION_NONE 0L\n#undef cryptlib_crypt_CERTACTION_CREATE\n#define cryptlib_crypt_CERTACTION_CREATE 1L\n#undef cryptlib_crypt_CERTACTION_CONNECT\n#define cryptlib_crypt_CERTACTION_CONNECT 2L\n#undef cryptlib_crypt_CERTACTION_DISCONNECT\n#define cryptlib_crypt_CERTACTION_DISCONNECT 3L\n#undef cryptlib_crypt_CERTACTION_ERROR\n#define cryptlib_crypt_CERTACTION_ERROR 4L\n#undef cryptlib_crypt_CERTACTION_ADDUSER\n#define cryptlib_crypt_CERTACTION_ADDUSER 5L\n#undef cryptlib_crypt_CERTACTION_DELETEUSER\n#define cryptlib_crypt_CERTACTION_DELETEUSER 6L\n#undef cryptlib_crypt_CERTACTION_REQUEST_CERT\n#define cryptlib_crypt_CERTACTION_REQUEST_CERT 7L\n#undef cryptlib_crypt_CERTACTION_REQUEST_RENEWAL\n#define cryptlib_crypt_CERTACTION_REQUEST_RENEWAL 8L\n#undef cryptlib_crypt_CERTACTION_REQUEST_REVOCATION\n#define cryptlib_crypt_CERTACTION_REQUEST_REVOCATION 9L\n#undef cryptlib_crypt_CERTACTION_CERT_CREATION\n#define cryptlib_crypt_CERTACTION_CERT_CREATION 10L\n#undef cryptlib_crypt_CERTACTION_CERT_CREATION_COMPLETE\n#define cryptlib_crypt_CERTACTION_CERT_CREATION_COMPLETE 11L\n#undef cryptlib_crypt_CERTACTION_CERT_CREATION_DROP\n#define cryptlib_crypt_CERTACTION_CERT_CREATION_DROP 12L\n#undef cryptlib_crypt_CERTACTION_CERT_CREATION_REVERSE\n#define cryptlib_crypt_CERTACTION_CERT_CREATION_REVERSE 13L\n#undef cryptlib_crypt_CERTACTION_RESTART_CLEANUP\n#define cryptlib_crypt_CERTACTION_RESTART_CLEANUP 14L\n#undef cryptlib_crypt_CERTACTION_RESTART_REVOKE_CERT\n#define cryptlib_crypt_CERTACTION_RESTART_REVOKE_CERT 15L\n#undef cryptlib_crypt_CERTACTION_ISSUE_CERT\n#define cryptlib_crypt_CERTACTION_ISSUE_CERT 16L\n#undef cryptlib_crypt_CERTACTION_ISSUE_CRL\n#define cryptlib_crypt_CERTACTION_ISSUE_CRL 17L\n#undef cryptlib_crypt_CERTACTION_REVOKE_CERT\n#define cryptlib_crypt_CERTACTION_REVOKE_CERT 18L\n#undef cryptlib_crypt_CERTACTION_EXPIRE_CERT\n#define cryptlib_crypt_CERTACTION_EXPIRE_CERT 19L\n#undef cryptlib_crypt_CERTACTION_CLEANUP\n#define cryptlib_crypt_CERTACTION_CLEANUP 20L\n#undef cryptlib_crypt_CERTACTION_LAST\n#define cryptlib_crypt_CERTACTION_LAST 21L\n#undef cryptlib_crypt_SUBPROTOCOL_NONE\n#define cryptlib_crypt_SUBPROTOCOL_NONE 0L\n#undef cryptlib_crypt_SUBPROTOCOL_WEBSOCKETS\n#define cryptlib_crypt_SUBPROTOCOL_WEBSOCKETS 1L\n#undef cryptlib_crypt_SUBPROTOCOL_EAPTTLS\n#define cryptlib_crypt_SUBPROTOCOL_EAPTTLS 2L\n#undef cryptlib_crypt_SUBPROTOCOL_LAST\n#define cryptlib_crypt_SUBPROTOCOL_LAST 3L\n#undef cryptlib_crypt_SSLOPTION_NONE\n#define cryptlib_crypt_SSLOPTION_NONE 0L\n#undef cryptlib_crypt_SSLOPTION_MINVER_SSLV3\n#define cryptlib_crypt_SSLOPTION_MINVER_SSLV3 0L\n#undef cryptlib_crypt_SSLOPTION_MINVER_TLS10\n#define cryptlib_crypt_SSLOPTION_MINVER_TLS10 1L\n#undef cryptlib_crypt_SSLOPTION_MINVER_TLS11\n#define cryptlib_crypt_SSLOPTION_MINVER_TLS11 2L\n#undef cryptlib_crypt_SSLOPTION_MINVER_TLS12\n#define cryptlib_crypt_SSLOPTION_MINVER_TLS12 3L\n#undef cryptlib_crypt_SSLOPTION_MINVER_TLS13\n#define cryptlib_crypt_SSLOPTION_MINVER_TLS13 4L\n#undef cryptlib_crypt_SSLOPTION_MANUAL_CERTCHECK\n#define cryptlib_crypt_SSLOPTION_MANUAL_CERTCHECK 8L\n#undef cryptlib_crypt_SSLOPTION_DISABLE_NAMEVERIFY\n#define cryptlib_crypt_SSLOPTION_DISABLE_NAMEVERIFY 16L\n#undef cryptlib_crypt_SSLOPTION_DISABLE_CERTVERIFY\n#define cryptlib_crypt_SSLOPTION_DISABLE_CERTVERIFY 32L\n#undef cryptlib_crypt_SSLOPTION_SUITEB_128\n#define cryptlib_crypt_SSLOPTION_SUITEB_128 256L\n#undef cryptlib_crypt_SSLOPTION_SUITEB_256\n#define cryptlib_crypt_SSLOPTION_SUITEB_256 512L\n#undef cryptlib_crypt_MAX_KEYSIZE\n#define cryptlib_crypt_MAX_KEYSIZE 256L\n#undef cryptlib_crypt_MAX_IVSIZE\n#define cryptlib_crypt_MAX_IVSIZE 32L\n#undef cryptlib_crypt_MAX_PKCSIZE\n#define cryptlib_crypt_MAX_PKCSIZE 512L\n#undef cryptlib_crypt_MAX_PKCSIZE_ECC\n#define cryptlib_crypt_MAX_PKCSIZE_ECC 72L\n#undef cryptlib_crypt_MAX_HASHSIZE\n#define cryptlib_crypt_MAX_HASHSIZE 64L\n#undef cryptlib_crypt_MAX_TEXTSIZE\n#define cryptlib_crypt_MAX_TEXTSIZE 64L\n#undef cryptlib_crypt_USE_DEFAULT\n#define cryptlib_crypt_USE_DEFAULT -100L\n#undef cryptlib_crypt_UNUSED\n#define cryptlib_crypt_UNUSED -101L\n#undef cryptlib_crypt_CURSOR_FIRST\n#define cryptlib_crypt_CURSOR_FIRST -200L\n#undef cryptlib_crypt_CURSOR_PREVIOUS\n#define cryptlib_crypt_CURSOR_PREVIOUS -201L\n#undef cryptlib_crypt_CURSOR_NEXT\n#define cryptlib_crypt_CURSOR_NEXT -202L\n#undef cryptlib_crypt_CURSOR_LAST\n#define cryptlib_crypt_CURSOR_LAST -203L\n#undef cryptlib_crypt_RANDOM_FASTPOLL\n#define cryptlib_crypt_RANDOM_FASTPOLL -300L\n#undef cryptlib_crypt_RANDOM_SLOWPOLL\n#define cryptlib_crypt_RANDOM_SLOWPOLL -301L\n#undef cryptlib_crypt_KEYTYPE_PRIVATE\n#define cryptlib_crypt_KEYTYPE_PRIVATE 0L\n#undef cryptlib_crypt_KEYTYPE_PUBLIC\n#define cryptlib_crypt_KEYTYPE_PUBLIC 1L\n#undef cryptlib_crypt_KEYOPT_NONE\n#define cryptlib_crypt_KEYOPT_NONE 0L\n#undef cryptlib_crypt_KEYOPT_READONLY\n#define cryptlib_crypt_KEYOPT_READONLY 1L\n#undef cryptlib_crypt_KEYOPT_CREATE\n#define cryptlib_crypt_KEYOPT_CREATE 2L\n#undef cryptlib_crypt_KEYOPT_LAST\n#define cryptlib_crypt_KEYOPT_LAST 3L\n#undef cryptlib_crypt_ECCCURVE_NONE\n#define cryptlib_crypt_ECCCURVE_NONE 0L\n#undef cryptlib_crypt_ECCCURVE_P256\n#define cryptlib_crypt_ECCCURVE_P256 1L\n#undef cryptlib_crypt_ECCCURVE_P384\n#define cryptlib_crypt_ECCCURVE_P384 2L\n#undef cryptlib_crypt_ECCCURVE_P521\n#define cryptlib_crypt_ECCCURVE_P521 3L\n#undef cryptlib_crypt_ECCCURVE_BRAINPOOL_P256\n#define cryptlib_crypt_ECCCURVE_BRAINPOOL_P256 4L\n#undef cryptlib_crypt_ECCCURVE_BRAINPOOL_P384\n#define cryptlib_crypt_ECCCURVE_BRAINPOOL_P384 5L\n#undef cryptlib_crypt_ECCCURVE_BRAINPOOL_P512\n#define cryptlib_crypt_ECCCURVE_BRAINPOOL_P512 6L\n#undef cryptlib_crypt_ECCCURVE_LAST\n#define cryptlib_crypt_ECCCURVE_LAST 7L\n#undef cryptlib_crypt_OK\n#define cryptlib_crypt_OK 0L\n#undef cryptlib_crypt_ERROR_PARAM1\n#define cryptlib_crypt_ERROR_PARAM1 -1L\n#undef cryptlib_crypt_ERROR_PARAM2\n#define cryptlib_crypt_ERROR_PARAM2 -2L\n#undef cryptlib_crypt_ERROR_PARAM3\n#define cryptlib_crypt_ERROR_PARAM3 -3L\n#undef cryptlib_crypt_ERROR_PARAM4\n#define cryptlib_crypt_ERROR_PARAM4 -4L\n#undef cryptlib_crypt_ERROR_PARAM5\n#define cryptlib_crypt_ERROR_PARAM5 -5L\n#undef cryptlib_crypt_ERROR_PARAM6\n#define cryptlib_crypt_ERROR_PARAM6 -6L\n#undef cryptlib_crypt_ERROR_PARAM7\n#define cryptlib_crypt_ERROR_PARAM7 -7L\n#undef cryptlib_crypt_ERROR_MEMORY\n#define cryptlib_crypt_ERROR_MEMORY -10L\n#undef cryptlib_crypt_ERROR_NOTINITED\n#define cryptlib_crypt_ERROR_NOTINITED -11L\n#undef cryptlib_crypt_ERROR_INITED\n#define cryptlib_crypt_ERROR_INITED -12L\n#undef cryptlib_crypt_ERROR_NOSECURE\n#define cryptlib_crypt_ERROR_NOSECURE -13L\n#undef cryptlib_crypt_ERROR_RANDOM\n#define cryptlib_crypt_ERROR_RANDOM -14L\n#undef cryptlib_crypt_ERROR_FAILED\n#define cryptlib_crypt_ERROR_FAILED -15L\n#undef cryptlib_crypt_ERROR_INTERNAL\n#define cryptlib_crypt_ERROR_INTERNAL -16L\n#undef cryptlib_crypt_ERROR_NOTAVAIL\n#define cryptlib_crypt_ERROR_NOTAVAIL -20L\n#undef cryptlib_crypt_ERROR_PERMISSION\n#define cryptlib_crypt_ERROR_PERMISSION -21L\n#undef cryptlib_crypt_ERROR_WRONGKEY\n#define cryptlib_crypt_ERROR_WRONGKEY -22L\n#undef cryptlib_crypt_ERROR_INCOMPLETE\n#define cryptlib_crypt_ERROR_INCOMPLETE -23L\n#undef cryptlib_crypt_ERROR_COMPLETE\n#define cryptlib_crypt_ERROR_COMPLETE -24L\n#undef cryptlib_crypt_ERROR_TIMEOUT\n#define cryptlib_crypt_ERROR_TIMEOUT -25L\n#undef cryptlib_crypt_ERROR_INVALID\n#define cryptlib_crypt_ERROR_INVALID -26L\n#undef cryptlib_crypt_ERROR_SIGNALLED\n#define cryptlib_crypt_ERROR_SIGNALLED -27L\n#undef cryptlib_crypt_ERROR_OVERFLOW\n#define cryptlib_crypt_ERROR_OVERFLOW -30L\n#undef cryptlib_crypt_ERROR_UNDERFLOW\n#define cryptlib_crypt_ERROR_UNDERFLOW -31L\n#undef cryptlib_crypt_ERROR_BADDATA\n#define cryptlib_crypt_ERROR_BADDATA -32L\n#undef cryptlib_crypt_ERROR_SIGNATURE\n#define cryptlib_crypt_ERROR_SIGNATURE -33L\n#undef cryptlib_crypt_ERROR_OPEN\n#define cryptlib_crypt_ERROR_OPEN -40L\n#undef cryptlib_crypt_ERROR_READ\n#define cryptlib_crypt_ERROR_READ -41L\n#undef cryptlib_crypt_ERROR_WRITE\n#define cryptlib_crypt_ERROR_WRITE -42L\n#undef cryptlib_crypt_ERROR_NOTFOUND\n#define cryptlib_crypt_ERROR_NOTFOUND -43L\n#undef cryptlib_crypt_ERROR_DUPLICATE\n#define cryptlib_crypt_ERROR_DUPLICATE -44L\n#undef cryptlib_crypt_ENVELOPE_RESOURCE\n#define cryptlib_crypt_ENVELOPE_RESOURCE -50L\n\n\n/* Helper Functions */\n\nint processStatus(JNIEnv *env, jint status)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jthrowable obj;\n\n    if (status >= cryptlib_crypt_OK)\n        return 1;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CryptException\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatus - no class?!\\n\");\n        return 0;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(I)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatus - no constructor?!\\n\");\n        return 0;\n    }\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, status);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatus - no object?!\\n\");\n        return 0;\n    }\n\n    if ((*env)->Throw(env, obj) < 0)\n    {\n        printf(\"java_jni.c:processStatus - failed to throw?!\\n\");\n        return 0;\n    }\n    return 0;\n}\n\njobject processStatusReturnCryptQueryInfo(JNIEnv *env, int status, CRYPT_QUERY_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jstring algoName;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_QUERY_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(Ljava/lang/String;IIII)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    algoName = (*env)->NewStringUTF(env, returnValue.algoName);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\njobject processStatusReturnCryptObjectInfo(JNIEnv *env, int status, CRYPT_OBJECT_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jbyteArray salt;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_OBJECT_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(IIII[B)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    salt = (*env)->NewByteArray(env, returnValue.saltSize);\n    (*env)->SetByteArrayRegion(env, salt, 0, returnValue.saltSize, returnValue.salt);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, salt);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\nint checkIndicesArray(JNIEnv *env, jbyteArray array, int sequenceOffset, int sequenceLength)\n{\n    jsize arrayLength;\n    jclass exClass;\n\n    if (array == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    arrayLength = (*env)->GetArrayLength(env, array);\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= arrayLength ||\n        sequenceOffset + sequenceLength > arrayLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerArray(JNIEnv* env, jbyteArray array, jbyte** bytesPtrPtr)\n{\n    jboolean isCopy;\n\n    if (array == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetByteArrayElements(env, array, &isCopy);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        printf(\"java_jni.c:getPointer - failed to get elements of array?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerArray(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    (*env)->ReleaseByteArrayElements(env, array, bytesPtr, 0);\n}\n\nint checkIndicesNIO(JNIEnv *env, jobject byteBuffer, int sequenceOffset, int sequenceLength)\n{\n    jlong byteBufferLength;\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer);\n    if (byteBufferLength == -1)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass,\n\"Either a non-direct ByteBuffer was passed or your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= byteBufferLength ||\n        sequenceOffset + sequenceLength > byteBufferLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerNIO(JNIEnv* env, jobject byteBuffer, jbyte** bytesPtrPtr)\n{\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetDirectBufferAddress(env, byteBuffer);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:getPointerNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"Your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:getPointerNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerNIO(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n}\n\nint getPointerString(JNIEnv* env, jstring str, jbyte** bytesPtrPtr)\n{\n   jboolean isCopy;\n   jsize strLength;\n   const jbyte* rawBytesPtr;\n   jclass exClass;\n#ifdef __WINCE__\n   int status;\n#endif // __WINCE__\n\n\n   if (str == NULL)\n   {\n       (*bytesPtrPtr) = NULL;\n       return 1;\n   }\n\n   rawBytesPtr = (*env)->GetStringUTFChars(env, str, &isCopy);\n\n   if (rawBytesPtr == NULL)\n   {\n       printf(\"java_jni.c:getPointerString - failed to get elements of String?!\\n\");\n       return 0;\n   }\n\n   strLength = (*env)->GetStringUTFLength(env, str);\n\n#ifdef __WINCE__\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength*2+2); // this is unicode, therefore \\0 is two bytes long\n#else\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength+1);\n#endif // __WINCE__\n\n   if (*bytesPtrPtr == NULL)\n   {\n       exClass = (*env)->FindClass(env, \"java/lang/OutOfMemoryError\");\n       if (exClass == 0)\n           printf(\"java_jni.c:getPointerString - no class?!\\n\");\n       else\n       if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n           printf(\"java_jni.c:getPointerString - failed to throw?!\\n\");\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n\n#ifdef __WINCE__\n   status = asciiToUnicode (*bytesPtrPtr, strLength*2+2, rawBytesPtr, strLength+1);\n   if (status == CRYPT_ERROR_BADDATA) {\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n#else\n   memcpy(*bytesPtrPtr, rawBytesPtr, strLength);\n   (*bytesPtrPtr)[strLength] = 0;\n#endif // __WINCE__\n\n   (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n\n   return 1;\n}\n\nvoid releasePointerString(JNIEnv* env, jstring str, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    free(bytesPtr);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Init\n * Signature: ()V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Init\n  (JNIEnv * env, jclass cryptClass)\n{\n\tint status = 0;\n\t\n\tstatus = cryptInit();\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    End\n * Signature: ()V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_End\n  (JNIEnv * env, jclass cryptClass)\n{\n\tint status = 0;\n\t\n\tstatus = cryptEnd();\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    QueryCapability\n * Signature: (I)Lcryptlib/CRYPT_QUERY_INFO;\n */\nJNIEXPORT jobject JNICALL Java_cryptlib_crypt_QueryCapability\n  (JNIEnv * env, jclass cryptClass, jint cryptAlgo)\n{\n\tint status = 0;\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\t\n\tstatus = cryptQueryCapability(cryptAlgo, &cryptQueryInfo);\n\t\n\treturn(processStatusReturnCryptQueryInfo(env, status, cryptQueryInfo));\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateContext\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateContext\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint cryptAlgo)\n{\n\tint status = 0;\n\tjint cryptContext = 0;\n\t\n\tstatus = cryptCreateContext(&cryptContext, cryptUser, cryptAlgo);\n\t\n\tprocessStatus(env, status);\n\treturn(cryptContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DestroyContext\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DestroyContext\n  (JNIEnv * env, jclass cryptClass, jint cryptContext)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDestroyContext(cryptContext);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DestroyObject\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DestroyObject\n  (JNIEnv * env, jclass cryptClass, jint cryptObject)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDestroyObject(cryptObject);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GenerateKey\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_GenerateKey\n  (JNIEnv * env, jclass cryptClass, jint cryptContext)\n{\n\tint status = 0;\n\t\n\tstatus = cryptGenerateKey(cryptContext);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Encrypt\n * Signature: (ILjava/nio/ByteBuffer;II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Encrypt__ILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint cryptContext, jobject buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptEncrypt(cryptContext, bufferPtr + bufferOffset, length);\n\t\n\tfinish:\n\treleasePointerNIO(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Encrypt\n * Signature: (I[BII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Encrypt__I_3BII\n  (JNIEnv * env, jclass cryptClass, jint cryptContext, jbyteArray buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesArray(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptEncrypt(cryptContext, bufferPtr + bufferOffset, length);\n\t\n\tfinish:\n\treleasePointerArray(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Decrypt\n * Signature: (ILjava/nio/ByteBuffer;II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Decrypt__ILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint cryptContext, jobject buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDecrypt(cryptContext, bufferPtr + bufferOffset, length);\n\t\n\tfinish:\n\treleasePointerNIO(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Decrypt\n * Signature: (I[BII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Decrypt__I_3BII\n  (JNIEnv * env, jclass cryptClass, jint cryptContext, jbyteArray buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesArray(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDecrypt(cryptContext, bufferPtr + bufferOffset, length);\n\t\n\tfinish:\n\treleasePointerArray(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    SetAttribute\n * Signature: (III)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_SetAttribute\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType, jint value)\n{\n\tint status = 0;\n\t\n\tstatus = cryptSetAttribute(cryptHandle, attributeType, value);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    SetAttributeString\n * Signature: (IILjava/nio/ByteBuffer;II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_SetAttributeString__IILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType, jobject value, jint valueOffset, jint valueLength)\n{\n\tint status = 0;\n\tjbyte* valuePtr = 0;\n\t\n\tif (!checkIndicesNIO(env, value, valueOffset, valueLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, value, &valuePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptSetAttributeString(cryptHandle, attributeType, valuePtr + valueOffset, valueLength);\n\t\n\tfinish:\n\treleasePointerNIO(env, value, valuePtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    SetAttributeString\n * Signature: (II[BII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_SetAttributeString__II_3BII\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType, jbyteArray value, jint valueOffset, jint valueLength)\n{\n\tint status = 0;\n\tjbyte* valuePtr = 0;\n\t\n\tif (!checkIndicesArray(env, value, valueOffset, valueLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, value, &valuePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptSetAttributeString(cryptHandle, attributeType, valuePtr + valueOffset, valueLength);\n\t\n\tfinish:\n\treleasePointerArray(env, value, valuePtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetAttribute\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetAttribute\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType)\n{\n\tint status = 0;\n\tjint value = 0;\n\t\n\tstatus = cryptGetAttribute(cryptHandle, attributeType, &value);\n\t\n\tprocessStatus(env, status);\n\treturn(value);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetAttributeString\n * Signature: (IILjava/nio/ByteBuffer;I)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetAttributeString__IILjava_nio_ByteBuffer_2I\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType, jobject value, jint valueOffset)\n{\n\tint status = 0;\n\tjint valueLength = 0;\n\tjbyte* valuePtr = 0;\n\t\n\tif (!processStatus(env, cryptGetAttributeString(cryptHandle, attributeType, NULL, &valueLength)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, value, valueOffset, valueLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, value, &valuePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetAttributeString(cryptHandle, attributeType, valuePtr + valueOffset, &valueLength);\n\t\n\tfinish:\n\treleasePointerNIO(env, value, valuePtr);\n\tprocessStatus(env, status);\n\treturn(valueLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetAttributeString\n * Signature: (II[BI)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetAttributeString__II_3BI\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType, jbyteArray value, jint valueOffset)\n{\n\tint status = 0;\n\tjint valueLength = 0;\n\tjbyte* valuePtr = 0;\n\t\n\tif (!processStatus(env, cryptGetAttributeString(cryptHandle, attributeType, NULL, &valueLength)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, value, valueOffset, valueLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, value, &valuePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetAttributeString(cryptHandle, attributeType, valuePtr + valueOffset, &valueLength);\n\t\n\tfinish:\n\treleasePointerArray(env, value, valuePtr);\n\tprocessStatus(env, status);\n\treturn(valueLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeleteAttribute\n * Signature: (II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DeleteAttribute\n  (JNIEnv * env, jclass cryptClass, jint cryptHandle, jint attributeType)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDeleteAttribute(cryptHandle, attributeType);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddRandom\n * Signature: (Ljava/nio/ByteBuffer;II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddRandom__Ljava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jobject randomData, jint randomDataOffset, jint randomDataLength)\n{\n\tint status = 0;\n\tjbyte* randomDataPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, randomData, randomDataOffset, randomDataLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, randomData, &randomDataPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddRandom(randomDataPtr + randomDataOffset, randomDataLength);\n\t\n\tfinish:\n\treleasePointerNIO(env, randomData, randomDataPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddRandom\n * Signature: ([BII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddRandom___3BII\n  (JNIEnv * env, jclass cryptClass, jbyteArray randomData, jint randomDataOffset, jint randomDataLength)\n{\n\tint status = 0;\n\tjbyte* randomDataPtr = 0;\n\t\n\tif (!checkIndicesArray(env, randomData, randomDataOffset, randomDataLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, randomData, &randomDataPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddRandom(randomDataPtr + randomDataOffset, randomDataLength);\n\t\n\tfinish:\n\treleasePointerArray(env, randomData, randomDataPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddRandom\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddRandom__I\n  (JNIEnv * env, jclass cryptClass, jint pollType)\n{\n\tint status = 0;\n\t\n\tstatus = cryptAddRandom(NULL, pollType);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    QueryObject\n * Signature: (Ljava/nio/ByteBuffer;II)Lcryptlib/CRYPT_OBJECT_INFO;\n */\nJNIEXPORT jobject JNICALL Java_cryptlib_crypt_QueryObject__Ljava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jobject objectData, jint objectDataOffset, jint objectDataLength)\n{\n\tint status = 0;\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tjbyte* objectDataPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, objectData, objectDataOffset, objectDataLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, objectData, &objectDataPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptQueryObject(objectDataPtr + objectDataOffset, objectDataLength, &cryptObjectInfo);\n\t\n\tfinish:\n\treleasePointerNIO(env, objectData, objectDataPtr);\n\treturn(processStatusReturnCryptObjectInfo(env, status, cryptObjectInfo));\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    QueryObject\n * Signature: ([BII)Lcryptlib/CRYPT_OBJECT_INFO;\n */\nJNIEXPORT jobject JNICALL Java_cryptlib_crypt_QueryObject___3BII\n  (JNIEnv * env, jclass cryptClass, jbyteArray objectData, jint objectDataOffset, jint objectDataLength)\n{\n\tint status = 0;\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tjbyte* objectDataPtr = 0;\n\t\n\tif (!checkIndicesArray(env, objectData, objectDataOffset, objectDataLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, objectData, &objectDataPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptQueryObject(objectDataPtr + objectDataOffset, objectDataLength, &cryptObjectInfo);\n\t\n\tfinish:\n\treleasePointerArray(env, objectData, objectDataPtr);\n\treturn(processStatusReturnCryptObjectInfo(env, status, cryptObjectInfo));\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportKey\n * Signature: (Ljava/nio/ByteBuffer;IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportKey__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject encryptedKey, jint encryptedKeyOffset, jint encryptedKeyMaxLength, jint exportKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint encryptedKeyLength = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportKey(NULL, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKey(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(encryptedKeyLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportKey\n * Signature: ([BIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportKey___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray encryptedKey, jint encryptedKeyOffset, jint encryptedKeyMaxLength, jint exportKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint encryptedKeyLength = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportKey(NULL, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKey(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerArray(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(encryptedKeyLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportKeyEx\n * Signature: (Ljava/nio/ByteBuffer;IIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportKeyEx__Ljava_nio_ByteBuffer_2IIIII\n  (JNIEnv * env, jclass cryptClass, jobject encryptedKey, jint encryptedKeyOffset, jint encryptedKeyMaxLength, jint formatType, jint exportKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint encryptedKeyLength = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportKeyEx(NULL, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKeyEx(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(encryptedKeyLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportKeyEx\n * Signature: ([BIIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportKeyEx___3BIIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray encryptedKey, jint encryptedKeyOffset, jint encryptedKeyMaxLength, jint formatType, jint exportKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint encryptedKeyLength = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportKeyEx(NULL, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKeyEx(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerArray(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(encryptedKeyLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportKey\n * Signature: (Ljava/nio/ByteBuffer;IIII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_ImportKey__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject encryptedKey, jint encryptedKeyOffset, jint encryptedKeyLength, jint importKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKey(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyLength, importKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportKey\n * Signature: ([BIIII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_ImportKey___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray encryptedKey, jint encryptedKeyOffset, jint encryptedKeyLength, jint importKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!checkIndicesArray(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKey(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyLength, importKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointerArray(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportKeyEx\n * Signature: (Ljava/nio/ByteBuffer;IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ImportKeyEx__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject encryptedKey, jint encryptedKeyOffset, jint encryptedKeyLength, jint importKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint returnedContext = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKeyEx(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyLength, importKey, sessionKeyContext, &returnedContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(returnedContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportKeyEx\n * Signature: ([BIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ImportKeyEx___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray encryptedKey, jint encryptedKeyOffset, jint encryptedKeyLength, jint importKey, jint sessionKeyContext)\n{\n\tint status = 0;\n\tjint returnedContext = 0;\n\tjbyte* encryptedKeyPtr = 0;\n\t\n\tif (!checkIndicesArray(env, encryptedKey, encryptedKeyOffset, encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, encryptedKey, &encryptedKeyPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKeyEx(encryptedKeyPtr + encryptedKeyOffset, encryptedKeyLength, importKey, sessionKeyContext, &returnedContext);\n\t\n\tfinish:\n\treleasePointerArray(env, encryptedKey, encryptedKeyPtr);\n\tprocessStatus(env, status);\n\treturn(returnedContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateSignature\n * Signature: (Ljava/nio/ByteBuffer;IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateSignature__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject signature, jint signatureOffset, jint signatureMaxLength, jint signContext, jint hashContext)\n{\n\tint status = 0;\n\tjint signatureLength = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!processStatus(env, cryptCreateSignature(NULL, signatureMaxLength, &signatureLength, signContext, hashContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignature(signaturePtr + signatureOffset, signatureMaxLength, &signatureLength, signContext, hashContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(signatureLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateSignature\n * Signature: ([BIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateSignature___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray signature, jint signatureOffset, jint signatureMaxLength, jint signContext, jint hashContext)\n{\n\tint status = 0;\n\tjint signatureLength = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!processStatus(env, cryptCreateSignature(NULL, signatureMaxLength, &signatureLength, signContext, hashContext)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignature(signaturePtr + signatureOffset, signatureMaxLength, &signatureLength, signContext, hashContext);\n\t\n\tfinish:\n\treleasePointerArray(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(signatureLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateSignatureEx\n * Signature: (Ljava/nio/ByteBuffer;IIIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateSignatureEx__Ljava_nio_ByteBuffer_2IIIIII\n  (JNIEnv * env, jclass cryptClass, jobject signature, jint signatureOffset, jint signatureMaxLength, jint formatType, jint signContext, jint hashContext, jint extraData)\n{\n\tint status = 0;\n\tjint signatureLength = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!processStatus(env, cryptCreateSignatureEx(NULL, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignatureEx(signaturePtr + signatureOffset, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData);\n\t\n\tfinish:\n\treleasePointerNIO(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(signatureLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateSignatureEx\n * Signature: ([BIIIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateSignatureEx___3BIIIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray signature, jint signatureOffset, jint signatureMaxLength, jint formatType, jint signContext, jint hashContext, jint extraData)\n{\n\tint status = 0;\n\tjint signatureLength = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!processStatus(env, cryptCreateSignatureEx(NULL, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignatureEx(signaturePtr + signatureOffset, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData);\n\t\n\tfinish:\n\treleasePointerArray(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(signatureLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CheckSignature\n * Signature: (Ljava/nio/ByteBuffer;IIII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_CheckSignature__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject signature, jint signatureOffset, jint signatureLength, jint sigCheckKey, jint hashContext)\n{\n\tint status = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!checkIndicesNIO(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignature(signaturePtr + signatureOffset, signatureLength, sigCheckKey, hashContext);\n\t\n\tfinish:\n\treleasePointerNIO(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CheckSignature\n * Signature: ([BIIII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_CheckSignature___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray signature, jint signatureOffset, jint signatureLength, jint sigCheckKey, jint hashContext)\n{\n\tint status = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!checkIndicesArray(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignature(signaturePtr + signatureOffset, signatureLength, sigCheckKey, hashContext);\n\t\n\tfinish:\n\treleasePointerArray(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CheckSignatureEx\n * Signature: (Ljava/nio/ByteBuffer;IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CheckSignatureEx__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject signature, jint signatureOffset, jint signatureLength, jint sigCheckKey, jint hashContext)\n{\n\tint status = 0;\n\tjint extraData = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!checkIndicesNIO(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignatureEx(signaturePtr + signatureOffset, signatureLength, sigCheckKey, hashContext, &extraData);\n\t\n\tfinish:\n\treleasePointerNIO(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(extraData);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CheckSignatureEx\n * Signature: ([BIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CheckSignatureEx___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray signature, jint signatureOffset, jint signatureLength, jint sigCheckKey, jint hashContext)\n{\n\tint status = 0;\n\tjint extraData = 0;\n\tjbyte* signaturePtr = 0;\n\t\n\tif (!checkIndicesArray(env, signature, signatureOffset, signatureLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, signature, &signaturePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignatureEx(signaturePtr + signatureOffset, signatureLength, sigCheckKey, hashContext, &extraData);\n\t\n\tfinish:\n\treleasePointerArray(env, signature, signaturePtr);\n\tprocessStatus(env, status);\n\treturn(extraData);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    KeysetOpen\n * Signature: (IILjava/lang/String;I)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_KeysetOpen\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint keysetType, jstring name, jint options)\n{\n\tint status = 0;\n\tjint keyset = 0;\n\tjbyte* namePtr = 0;\n\t\n\tif (!getPointerString(env, name, &namePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptKeysetOpen(&keyset, cryptUser, keysetType, namePtr, options);\n\t\n\tfinish:\n\treleasePointerString(env, name, namePtr);\n\tprocessStatus(env, status);\n\treturn(keyset);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    KeysetClose\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_KeysetClose\n  (JNIEnv * env, jclass cryptClass, jint keyset)\n{\n\tint status = 0;\n\t\n\tstatus = cryptKeysetClose(keyset);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetPublicKey\n * Signature: (IILjava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetPublicKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint keyIDtype, jstring keyID)\n{\n\tint status = 0;\n\tjint cryptContext = 0;\n\tjbyte* keyIDPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetPublicKey(keyset, &cryptContext, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\tprocessStatus(env, status);\n\treturn(cryptContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetPrivateKey\n * Signature: (IILjava/lang/String;Ljava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetPrivateKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint keyIDtype, jstring keyID, jstring password)\n{\n\tint status = 0;\n\tjint cryptContext = 0;\n\tjbyte* keyIDPtr = 0;\n\tjbyte* passwordPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\tif (!getPointerString(env, password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetPrivateKey(keyset, &cryptContext, keyIDtype, keyIDPtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\treleasePointerString(env, password, passwordPtr);\n\tprocessStatus(env, status);\n\treturn(cryptContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetKey\n * Signature: (IILjava/lang/String;Ljava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint keyIDtype, jstring keyID, jstring password)\n{\n\tint status = 0;\n\tjint cryptContext = 0;\n\tjbyte* keyIDPtr = 0;\n\tjbyte* passwordPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\tif (!getPointerString(env, password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetKey(keyset, &cryptContext, keyIDtype, keyIDPtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\treleasePointerString(env, password, passwordPtr);\n\tprocessStatus(env, status);\n\treturn(cryptContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddPublicKey\n * Signature: (II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddPublicKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint certificate)\n{\n\tint status = 0;\n\t\n\tstatus = cryptAddPublicKey(keyset, certificate);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddPrivateKey\n * Signature: (IILjava/lang/String;)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddPrivateKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint cryptKey, jstring password)\n{\n\tint status = 0;\n\tjbyte* passwordPtr = 0;\n\t\n\tif (!getPointerString(env, password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddPrivateKey(keyset, cryptKey, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(env, password, passwordPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeleteKey\n * Signature: (IILjava/lang/String;)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DeleteKey\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint keyIDtype, jstring keyID)\n{\n\tint status = 0;\n\tjbyte* keyIDPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeleteKey(keyset, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateCert\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateCert\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint certType)\n{\n\tint status = 0;\n\tjint certificate = 0;\n\t\n\tstatus = cryptCreateCert(&certificate, cryptUser, certType);\n\t\n\tprocessStatus(env, status);\n\treturn(certificate);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DestroyCert\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DestroyCert\n  (JNIEnv * env, jclass cryptClass, jint certificate)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDestroyCert(certificate);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetCertExtension\n * Signature: (ILjava/lang/String;Ljava/nio/ByteBuffer;II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetCertExtension__ILjava_lang_String_2Ljava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint certificate, jstring oid, jobject extension, jint extensionOffset, jint extensionMaxLength)\n{\n\tint status = 0;\n\tjint extensionLength = 0;\n\tjint criticalFlag = 0;\n\tjbyte* oidPtr = 0;\n\tjbyte* extensionPtr = 0;\n\t\n\tif (!getPointerString(env, oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!processStatus(env, cryptGetCertExtension(certificate, oidPtr, &criticalFlag, NULL, extensionMaxLength, &extensionLength)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, extension, extensionOffset, extensionLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, extension, &extensionPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetCertExtension(certificate, oidPtr, &criticalFlag, extensionPtr + extensionOffset, extensionMaxLength, &extensionLength);\n\t\n\tfinish:\n\treleasePointerNIO(env, extension, extensionPtr);\n\treleasePointerString(env, oid, oidPtr);\n\tprocessStatus(env, status);\n\treturn(extensionLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    GetCertExtension\n * Signature: (ILjava/lang/String;[BII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_GetCertExtension__ILjava_lang_String_2_3BII\n  (JNIEnv * env, jclass cryptClass, jint certificate, jstring oid, jbyteArray extension, jint extensionOffset, jint extensionMaxLength)\n{\n\tint status = 0;\n\tjint extensionLength = 0;\n\tjint criticalFlag = 0;\n\tjbyte* oidPtr = 0;\n\tjbyte* extensionPtr = 0;\n\t\n\tif (!getPointerString(env, oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!processStatus(env, cryptGetCertExtension(certificate, oidPtr, &criticalFlag, NULL, extensionMaxLength, &extensionLength)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, extension, extensionOffset, extensionLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, extension, &extensionPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetCertExtension(certificate, oidPtr, &criticalFlag, extensionPtr + extensionOffset, extensionMaxLength, &extensionLength);\n\t\n\tfinish:\n\treleasePointerArray(env, extension, extensionPtr);\n\treleasePointerString(env, oid, oidPtr);\n\tprocessStatus(env, status);\n\treturn(extensionLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddCertExtension\n * Signature: (ILjava/lang/String;ILjava/nio/ByteBuffer;II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddCertExtension__ILjava_lang_String_2ILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint certificate, jstring oid, jint criticalFlag, jobject extension, jint extensionOffset, jint extensionLength)\n{\n\tint status = 0;\n\tjbyte* oidPtr = 0;\n\tjbyte* extensionPtr = 0;\n\t\n\tif (!getPointerString(env, oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, extension, extensionOffset, extensionLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, extension, &extensionPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddCertExtension(certificate, oidPtr, criticalFlag, extensionPtr + extensionOffset, extensionLength);\n\t\n\tfinish:\n\treleasePointerNIO(env, extension, extensionPtr);\n\treleasePointerString(env, oid, oidPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    AddCertExtension\n * Signature: (ILjava/lang/String;I[BII)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_AddCertExtension__ILjava_lang_String_2I_3BII\n  (JNIEnv * env, jclass cryptClass, jint certificate, jstring oid, jint criticalFlag, jbyteArray extension, jint extensionOffset, jint extensionLength)\n{\n\tint status = 0;\n\tjbyte* oidPtr = 0;\n\tjbyte* extensionPtr = 0;\n\t\n\tif (!getPointerString(env, oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, extension, extensionOffset, extensionLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, extension, &extensionPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddCertExtension(certificate, oidPtr, criticalFlag, extensionPtr + extensionOffset, extensionLength);\n\t\n\tfinish:\n\treleasePointerArray(env, extension, extensionPtr);\n\treleasePointerString(env, oid, oidPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeleteCertExtension\n * Signature: (ILjava/lang/String;)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DeleteCertExtension\n  (JNIEnv * env, jclass cryptClass, jint certificate, jstring oid)\n{\n\tint status = 0;\n\tjbyte* oidPtr = 0;\n\t\n\tif (!getPointerString(env, oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeleteCertExtension(certificate, oidPtr);\n\t\n\tfinish:\n\treleasePointerString(env, oid, oidPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    SignCert\n * Signature: (II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_SignCert\n  (JNIEnv * env, jclass cryptClass, jint certificate, jint signContext)\n{\n\tint status = 0;\n\t\n\tstatus = cryptSignCert(certificate, signContext);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CheckCert\n * Signature: (II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_CheckCert\n  (JNIEnv * env, jclass cryptClass, jint certificate, jint sigCheckKey)\n{\n\tint status = 0;\n\t\n\tstatus = cryptCheckCert(certificate, sigCheckKey);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportCert\n * Signature: (Ljava/nio/ByteBuffer;III)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ImportCert__Ljava_nio_ByteBuffer_2III\n  (JNIEnv * env, jclass cryptClass, jobject certObject, jint certObjectOffset, jint certObjectLength, jint cryptUser)\n{\n\tint status = 0;\n\tjint certificate = 0;\n\tjbyte* certObjectPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, certObject, certObjectOffset, certObjectLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, certObject, &certObjectPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportCert(certObjectPtr + certObjectOffset, certObjectLength, cryptUser, &certificate);\n\t\n\tfinish:\n\treleasePointerNIO(env, certObject, certObjectPtr);\n\tprocessStatus(env, status);\n\treturn(certificate);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ImportCert\n * Signature: ([BIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ImportCert___3BIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray certObject, jint certObjectOffset, jint certObjectLength, jint cryptUser)\n{\n\tint status = 0;\n\tjint certificate = 0;\n\tjbyte* certObjectPtr = 0;\n\t\n\tif (!checkIndicesArray(env, certObject, certObjectOffset, certObjectLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, certObject, &certObjectPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportCert(certObjectPtr + certObjectOffset, certObjectLength, cryptUser, &certificate);\n\t\n\tfinish:\n\treleasePointerArray(env, certObject, certObjectPtr);\n\tprocessStatus(env, status);\n\treturn(certificate);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportCert\n * Signature: (Ljava/nio/ByteBuffer;IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportCert__Ljava_nio_ByteBuffer_2IIII\n  (JNIEnv * env, jclass cryptClass, jobject certObject, jint certObjectOffset, jint certObjectMaxLength, jint certFormatType, jint certificate)\n{\n\tint status = 0;\n\tjint certObjectLength = 0;\n\tjbyte* certObjectPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportCert(NULL, certObjectMaxLength, &certObjectLength, certFormatType, certificate)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesNIO(env, certObject, certObjectOffset, certObjectLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, certObject, &certObjectPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportCert(certObjectPtr + certObjectOffset, certObjectMaxLength, &certObjectLength, certFormatType, certificate);\n\t\n\tfinish:\n\treleasePointerNIO(env, certObject, certObjectPtr);\n\tprocessStatus(env, status);\n\treturn(certObjectLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    ExportCert\n * Signature: ([BIIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_ExportCert___3BIIII\n  (JNIEnv * env, jclass cryptClass, jbyteArray certObject, jint certObjectOffset, jint certObjectMaxLength, jint certFormatType, jint certificate)\n{\n\tint status = 0;\n\tjint certObjectLength = 0;\n\tjbyte* certObjectPtr = 0;\n\t\n\tif (!processStatus(env, cryptExportCert(NULL, certObjectMaxLength, &certObjectLength, certFormatType, certificate)))\n\t\tgoto finish;\n\t\n\tif (!checkIndicesArray(env, certObject, certObjectOffset, certObjectLength))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, certObject, &certObjectPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportCert(certObjectPtr + certObjectOffset, certObjectMaxLength, &certObjectLength, certFormatType, certificate);\n\t\n\tfinish:\n\treleasePointerArray(env, certObject, certObjectPtr);\n\tprocessStatus(env, status);\n\treturn(certObjectLength);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CAAddItem\n * Signature: (II)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_CAAddItem\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint certificate)\n{\n\tint status = 0;\n\t\n\tstatus = cryptCAAddItem(keyset, certificate);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CAGetItem\n * Signature: (IIILjava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CAGetItem\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint certType, jint keyIDtype, jstring keyID)\n{\n\tint status = 0;\n\tjint certificate = 0;\n\tjbyte* keyIDPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCAGetItem(keyset, &certificate, certType, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\tprocessStatus(env, status);\n\treturn(certificate);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CADeleteItem\n * Signature: (IIILjava/lang/String;)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_CADeleteItem\n  (JNIEnv * env, jclass cryptClass, jint keyset, jint certType, jint keyIDtype, jstring keyID)\n{\n\tint status = 0;\n\tjbyte* keyIDPtr = 0;\n\t\n\tif (!getPointerString(env, keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCADeleteItem(keyset, certType, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(env, keyID, keyIDPtr);\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CACertManagement\n * Signature: (IIII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CACertManagement\n  (JNIEnv * env, jclass cryptClass, jint action, jint keyset, jint caKey, jint certRequest)\n{\n\tint status = 0;\n\tjint certificate = 0;\n\t\n\tstatus = cryptCACertManagement(&certificate, action, keyset, caKey, certRequest);\n\t\n\tprocessStatus(env, status);\n\treturn(certificate);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateEnvelope\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateEnvelope\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint formatType)\n{\n\tint status = 0;\n\tjint envelope = 0;\n\t\n\tstatus = cryptCreateEnvelope(&envelope, cryptUser, formatType);\n\t\n\tprocessStatus(env, status);\n\treturn(envelope);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DestroyEnvelope\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DestroyEnvelope\n  (JNIEnv * env, jclass cryptClass, jint envelope)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDestroyEnvelope(envelope);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    CreateSession\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_CreateSession\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint formatType)\n{\n\tint status = 0;\n\tjint session = 0;\n\t\n\tstatus = cryptCreateSession(&session, cryptUser, formatType);\n\t\n\tprocessStatus(env, status);\n\treturn(session);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DestroySession\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DestroySession\n  (JNIEnv * env, jclass cryptClass, jint session)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDestroySession(session);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    PushData\n * Signature: (ILjava/nio/ByteBuffer;II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_PushData__ILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint envelope, jobject buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjint bytesCopied = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesNIO(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptPushData(envelope, bufferPtr + bufferOffset, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointerNIO(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n\treturn(bytesCopied);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    PushData\n * Signature: (I[BII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_PushData__I_3BII\n  (JNIEnv * env, jclass cryptClass, jint envelope, jbyteArray buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjint bytesCopied = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\tif (!checkIndicesArray(env, buffer, bufferOffset, length))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptPushData(envelope, bufferPtr + bufferOffset, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointerArray(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n\treturn(bytesCopied);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    FlushData\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_FlushData\n  (JNIEnv * env, jclass cryptClass, jint envelope)\n{\n\tint status = 0;\n\t\n\tstatus = cryptFlushData(envelope);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    PopData\n * Signature: (ILjava/nio/ByteBuffer;II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_PopData__ILjava_nio_ByteBuffer_2II\n  (JNIEnv * env, jclass cryptClass, jint envelope, jobject buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjint bytesCopied = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\t//CryptPopData is a special case that doesn't have the length querying call\n\t\n\tif (!checkIndicesNIO(env, buffer, bufferOffset, bytesCopied))\n\t\tgoto finish;\n\t\n\tif (!getPointerNIO(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptPopData(envelope, bufferPtr + bufferOffset, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointerNIO(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n\treturn(bytesCopied);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    PopData\n * Signature: (I[BII)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_PopData__I_3BII\n  (JNIEnv * env, jclass cryptClass, jint envelope, jbyteArray buffer, jint bufferOffset, jint length)\n{\n\tint status = 0;\n\tjint bytesCopied = 0;\n\tjbyte* bufferPtr = 0;\n\t\n\t//CryptPopData is a special case that doesn't have the length querying call\n\t\n\tif (!checkIndicesArray(env, buffer, bufferOffset, bytesCopied))\n\t\tgoto finish;\n\t\n\tif (!getPointerArray(env, buffer, &bufferPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptPopData(envelope, bufferPtr + bufferOffset, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointerArray(env, buffer, bufferPtr);\n\tprocessStatus(env, status);\n\treturn(bytesCopied);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeviceOpen\n * Signature: (IILjava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_DeviceOpen\n  (JNIEnv * env, jclass cryptClass, jint cryptUser, jint deviceType, jstring name)\n{\n\tint status = 0;\n\tjint device = 0;\n\tjbyte* namePtr = 0;\n\t\n\tif (!getPointerString(env, name, &namePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeviceOpen(&device, cryptUser, deviceType, namePtr);\n\t\n\tfinish:\n\treleasePointerString(env, name, namePtr);\n\tprocessStatus(env, status);\n\treturn(device);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeviceClose\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_DeviceClose\n  (JNIEnv * env, jclass cryptClass, jint device)\n{\n\tint status = 0;\n\t\n\tstatus = cryptDeviceClose(device);\n\t\n\tprocessStatus(env, status);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeviceQueryCapability\n * Signature: (II)Lcryptlib/CRYPT_QUERY_INFO;\n */\nJNIEXPORT jobject JNICALL Java_cryptlib_crypt_DeviceQueryCapability\n  (JNIEnv * env, jclass cryptClass, jint device, jint cryptAlgo)\n{\n\tint status = 0;\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\t\n\tstatus = cryptDeviceQueryCapability(device, cryptAlgo, &cryptQueryInfo);\n\t\n\treturn(processStatusReturnCryptQueryInfo(env, status, cryptQueryInfo));\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    DeviceCreateContext\n * Signature: (II)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_DeviceCreateContext\n  (JNIEnv * env, jclass cryptClass, jint device, jint cryptAlgo)\n{\n\tint status = 0;\n\tjint cryptContext = 0;\n\t\n\tstatus = cryptDeviceCreateContext(device, &cryptContext, cryptAlgo);\n\t\n\tprocessStatus(env, status);\n\treturn(cryptContext);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Login\n * Signature: (Ljava/lang/String;Ljava/lang/String;)I\n */\nJNIEXPORT jint JNICALL Java_cryptlib_crypt_Login\n  (JNIEnv * env, jclass cryptClass, jstring name, jstring password)\n{\n\tint status = 0;\n\tjint user = 0;\n\tjbyte* namePtr = 0;\n\tjbyte* passwordPtr = 0;\n\t\n\tif (!getPointerString(env, name, &namePtr))\n\t\tgoto finish;\n\tif (!getPointerString(env, password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptLogin(&user, namePtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(env, name, namePtr);\n\treleasePointerString(env, password, passwordPtr);\n\tprocessStatus(env, status);\n\treturn(user);\n}\n\n/*\n * Class:     cryptlib_crypt\n * Method:    Logout\n * Signature: (I)V\n */\nJNIEXPORT void JNICALL Java_cryptlib_crypt_Logout\n  (JNIEnv * env, jclass cryptClass, jint user)\n{\n\tint status = 0;\n\t\n\tstatus = cryptLogout(user);\n\t\n\tprocessStatus(env, status);\n}\n\n\n\n#endif /* USE_JAVA */\n"
  },
  {
    "path": "deps/cl345/bindings/python.c",
    "content": "\n#include <Python.h>\n#include \"../cryptlib.h\"\n\n\nstatic PyObject* cryptHandleClass;\nstatic PyObject* cryptQueryInfoClass;\nstatic PyObject* cryptObjectInfoClass;\nstatic PyObject *CryptException;\n\nstatic int getPointerWrite(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n        return 0;\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerRead(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n    {\n        PyErr_Clear();\n        /*See if it's a string object*/\n        /*This returns the length excluding the NULL if it's a string,\n          which is what we want*/\n        if (PyObject_AsCharBuffer(objPtr, (const char **)bytesPtrPtr, &size) == -1)\n            return 0;\n    }\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerReadNoLength(PyObject* objPtr, unsigned char** bytesPtrPtr)\n{\n    int length;\n    return getPointerRead(objPtr, bytesPtrPtr, &length);\n}\n\nstatic int getPointerWriteCheckIndices(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    int checkLength = *lengthPtr;\n\n    if (getPointerWrite(objPtr, bytesPtrPtr, lengthPtr) == 0)\n        return 0;\n\n    //If sequence is non-NULL and too short...\n    if (*bytesPtrPtr && (*lengthPtr < checkLength))\n    {\n        PyErr_SetString(PyExc_IndexError, \"A sequence passed to cryptlib was too small\");\n        return 0;\n    }\n    return 1;\n}\n\nstatic int getPointerReadString(PyObject* objPtr, char** charPtrPtr)\n{\n    Py_ssize_t length = 0;\n    char* newPtr = NULL;\n\n    if (objPtr == Py_None)\n    {\n        *charPtrPtr = NULL;\n        return 1;\n    }\n\n    /*See if it's a string or a buffer object*/\n    if (PyObject_AsCharBuffer(objPtr, charPtrPtr, &length) == -1)\n    {\n        /*See if it's an array*/\n        PyErr_Clear();\n        if (PyObject_AsWriteBuffer(objPtr, charPtrPtr, &length) == -1)\n            return 0;\n    }\n    /*This code isn't necessary for a string, but it is for arrays and buffers,\n      so we do it always anyway, since the PyObject_AsCharBuffer apparently doesn't\n      guarantee us null-terminated data, and this way releasePointerString() doesn't\n      have to differentiate */\n    newPtr = malloc(length+1);\n    if (newPtr == NULL)\n    {\n        PyErr_NoMemory();\n        return 0;\n    }\n    memcpy(newPtr, *charPtrPtr, length);\n    newPtr[length] = 0;\n    *charPtrPtr = newPtr;\n    return 1;\n}\n\nstatic void releasePointer(PyObject* objPtr, unsigned char* bytesPtr)\n{\n}\n\nstatic void releasePointerString(PyObject* objPtr, char* charPtr)\n{\n    free(charPtr);\n}\n\nstatic PyObject* processStatus(int status)\n{\n    PyObject* o = NULL;\n\n    /* If an error has already occurred, ignore the status and just fall through */\n    if (PyErr_Occurred())\n        return(NULL);\n\n    if (status >= CRYPT_OK)\n        return(Py_BuildValue(\"\"));\n    else if (status == CRYPT_ERROR_PARAM1)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM1, \"Bad argument, parameter 1\");\n    else if (status == CRYPT_ERROR_PARAM2)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM2, \"Bad argument, parameter 2\");\n    else if (status == CRYPT_ERROR_PARAM3)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM3, \"Bad argument, parameter 3\");\n    else if (status == CRYPT_ERROR_PARAM4)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM4, \"Bad argument, parameter 4\");\n    else if (status == CRYPT_ERROR_PARAM5)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM5, \"Bad argument, parameter 5\");\n    else if (status == CRYPT_ERROR_PARAM6)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM6, \"Bad argument, parameter 6\");\n    else if (status == CRYPT_ERROR_PARAM7)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PARAM7, \"Bad argument, parameter 7\");\n    else if (status == CRYPT_ERROR_MEMORY)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_MEMORY, \"Out of memory\");\n    else if (status == CRYPT_ERROR_NOTINITED)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_NOTINITED, \"Data has not been initialised\");\n    else if (status == CRYPT_ERROR_INITED)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_INITED, \"Data has already been init'd\");\n    else if (status == CRYPT_ERROR_NOSECURE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_NOSECURE, \"Opn.not avail.at requested sec.level\");\n    else if (status == CRYPT_ERROR_RANDOM)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_RANDOM, \"No reliable random data available\");\n    else if (status == CRYPT_ERROR_FAILED)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_FAILED, \"Operation failed\");\n    else if (status == CRYPT_ERROR_INTERNAL)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_INTERNAL, \"Internal consistency check failed\");\n    else if (status == CRYPT_ERROR_NOTAVAIL)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_NOTAVAIL, \"This type of opn.not available\");\n    else if (status == CRYPT_ERROR_PERMISSION)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_PERMISSION, \"No permiss.to perform this operation\");\n    else if (status == CRYPT_ERROR_WRONGKEY)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_WRONGKEY, \"Incorrect key used to decrypt data\");\n    else if (status == CRYPT_ERROR_INCOMPLETE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_INCOMPLETE, \"Operation incomplete/still in progress\");\n    else if (status == CRYPT_ERROR_COMPLETE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_COMPLETE, \"Operation complete/can't continue\");\n    else if (status == CRYPT_ERROR_TIMEOUT)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_TIMEOUT, \"Operation timed out before completion\");\n    else if (status == CRYPT_ERROR_INVALID)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_INVALID, \"Invalid/inconsistent information\");\n    else if (status == CRYPT_ERROR_SIGNALLED)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_SIGNALLED, \"Resource destroyed by extnl.event\");\n    else if (status == CRYPT_ERROR_OVERFLOW)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_OVERFLOW, \"Resources/space exhausted\");\n    else if (status == CRYPT_ERROR_UNDERFLOW)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_UNDERFLOW, \"Not enough data available\");\n    else if (status == CRYPT_ERROR_BADDATA)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_BADDATA, \"Bad/unrecognised data format\");\n    else if (status == CRYPT_ERROR_SIGNATURE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_SIGNATURE, \"Signature/integrity check failed\");\n    else if (status == CRYPT_ERROR_OPEN)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_OPEN, \"Cannot open object\");\n    else if (status == CRYPT_ERROR_READ)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_READ, \"Cannot read item from object\");\n    else if (status == CRYPT_ERROR_WRITE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_WRITE, \"Cannot write item to object\");\n    else if (status == CRYPT_ERROR_NOTFOUND)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_NOTFOUND, \"Requested item not found in object\");\n    else if (status == CRYPT_ERROR_DUPLICATE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ERROR_DUPLICATE, \"Item already present in object\");\n    else if (status == CRYPT_ENVELOPE_RESOURCE)\n        o = Py_BuildValue(\"(is)\", CRYPT_ENVELOPE_RESOURCE, \"Need resource to proceed\");\n    PyErr_SetObject(CryptException, o);\n    Py_DECREF(o);\n    return(NULL);\n}\n\nstatic int processStatusBool(int status)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        return(1);\n    }\n}\n\nstatic PyObject* processStatusReturnInt(int status, int returnValue)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o = Py_BuildValue(\"i\", returnValue);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptHandle(int status, int returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(i)\", returnValue);\n        o = PyObject_CallObject(cryptHandleClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptQueryInfo(int status, CRYPT_QUERY_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(siiii)\", returnValue.algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n        o = PyObject_CallObject(cryptQueryInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptObjectInfo(int status, CRYPT_OBJECT_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(iiiis#)\", returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, returnValue.salt, returnValue.saltSize);\n        o = PyObject_CallObject(cryptObjectInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* python_cryptInit(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\t\n\tstatus = cryptInit();\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptEnd(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\t\n\tstatus = cryptEnd();\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptQueryCapability(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\tint cryptAlgo = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &cryptAlgo))\n\t    return(NULL);\n\t\n\tstatus = cryptQueryCapability(cryptAlgo, &cryptQueryInfo);\n\t\n\treturn(processStatusReturnCryptQueryInfo(status, cryptQueryInfo));\n}\n\nstatic PyObject* python_cryptCreateContext(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tint cryptUser = 0;\n\tint cryptAlgo = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptUser, &cryptAlgo))\n\t    return(NULL);\n\t\n\tstatus = cryptCreateContext(&cryptContext, cryptUser, cryptAlgo);\n\t\n\treturn(processStatusReturnCryptHandle(status, cryptContext));\n}\n\nstatic PyObject* python_cryptDestroyContext(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &cryptContext))\n\t    return(NULL);\n\t\n\tstatus = cryptDestroyContext(cryptContext);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptDestroyObject(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptObject = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &cryptObject))\n\t    return(NULL);\n\t\n\tstatus = cryptDestroyObject(cryptObject);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptGenerateKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &cryptContext))\n\t    return(NULL);\n\t\n\tstatus = cryptGenerateKey(cryptContext);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptEncrypt(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tPyObject* buffer = NULL;\n\tint length = 0;\n\tunsigned char* bufferPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iO\", &cryptContext, &buffer))\n\t    return(NULL);\n\t\n\tif (!getPointerWrite(buffer, &bufferPtr, &length))\n\t\tgoto finish;\n\t\n\tstatus = cryptEncrypt(cryptContext, bufferPtr, length);\n\t\n\tfinish:\n\treleasePointer(buffer, bufferPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptDecrypt(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tPyObject* buffer = NULL;\n\tint length = 0;\n\tunsigned char* bufferPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iO\", &cryptContext, &buffer))\n\t    return(NULL);\n\t\n\tif (!getPointerWrite(buffer, &bufferPtr, &length))\n\t\tgoto finish;\n\t\n\tstatus = cryptDecrypt(cryptContext, bufferPtr, length);\n\t\n\tfinish:\n\treleasePointer(buffer, bufferPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptSetAttribute(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptHandle = 0;\n\tint attributeType = 0;\n\tint value = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iii\", &cryptHandle, &attributeType, &value))\n\t    return(NULL);\n\t\n\tstatus = cryptSetAttribute(cryptHandle, attributeType, value);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptSetAttributeString(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptHandle = 0;\n\tint attributeType = 0;\n\tPyObject* value = NULL;\n\tint valueLength = 0;\n\tunsigned char* valuePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &cryptHandle, &attributeType, &value))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(value, &valuePtr, &valueLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptSetAttributeString(cryptHandle, attributeType, valuePtr, valueLength);\n\t\n\tfinish:\n\treleasePointer(value, valuePtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptGetAttribute(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint value = 0;\n\tint cryptHandle = 0;\n\tint attributeType = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptHandle, &attributeType))\n\t    return(NULL);\n\t\n\tstatus = cryptGetAttribute(cryptHandle, attributeType, &value);\n\t\n\treturn(processStatusReturnInt(status, value));\n}\n\nstatic PyObject* python_cryptGetAttributeString(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint valueLength = 0;\n\tint cryptHandle = 0;\n\tint attributeType = 0;\n\tPyObject* value = NULL;\n\tunsigned char* valuePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &cryptHandle, &attributeType, &value))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptGetAttributeString(cryptHandle, attributeType, NULL, &valueLength)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(value, &valuePtr, &valueLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetAttributeString(cryptHandle, attributeType, valuePtr, &valueLength);\n\t\n\tfinish:\n\treleasePointer(value, valuePtr);\n\treturn(processStatusReturnInt(status, valueLength));\n}\n\nstatic PyObject* python_cryptDeleteAttribute(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptHandle = 0;\n\tint attributeType = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptHandle, &attributeType))\n\t    return(NULL);\n\t\n\tstatus = cryptDeleteAttribute(cryptHandle, attributeType);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptAddRandom(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tPyObject* randomData = NULL;\n\tint randomDataLength = 0;\n\tunsigned char* randomDataPtr = 0;\n\t\n\t//Special case to handle SLOWPOLL / FASTPOLL values\n\tif (PyArg_ParseTuple(args, \"i\", &randomDataLength))\n\t    return processStatus(cryptAddRandom(NULL, randomDataLength));\n\t\n\tif (!PyArg_ParseTuple(args, \"O\", &randomData))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(randomData, &randomDataPtr, &randomDataLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddRandom(randomDataPtr, randomDataLength);\n\t\n\tfinish:\n\treleasePointer(randomData, randomDataPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptQueryObject(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tPyObject* objectData = NULL;\n\tint objectDataLength = 0;\n\tunsigned char* objectDataPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"O\", &objectData))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(objectData, &objectDataPtr, &objectDataLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptQueryObject(objectDataPtr, objectDataLength, &cryptObjectInfo);\n\t\n\tfinish:\n\treleasePointer(objectData, objectDataPtr);\n\treturn(processStatusReturnCryptObjectInfo(status, cryptObjectInfo));\n}\n\nstatic PyObject* python_cryptExportKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint encryptedKeyLength = 0;\n\tPyObject* encryptedKey = NULL;\n\tint encryptedKeyMaxLength = 0;\n\tint exportKey = 0;\n\tint sessionKeyContext = 0;\n\tunsigned char* encryptedKeyPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oiii\", &encryptedKey, &encryptedKeyMaxLength, &exportKey, &sessionKeyContext))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptExportKey(NULL, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(encryptedKey, &encryptedKeyPtr, &encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKey(encryptedKeyPtr, encryptedKeyMaxLength, &encryptedKeyLength, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointer(encryptedKey, encryptedKeyPtr);\n\treturn(processStatusReturnInt(status, encryptedKeyLength));\n}\n\nstatic PyObject* python_cryptExportKeyEx(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint encryptedKeyLength = 0;\n\tPyObject* encryptedKey = NULL;\n\tint encryptedKeyMaxLength = 0;\n\tint formatType = 0;\n\tint exportKey = 0;\n\tint sessionKeyContext = 0;\n\tunsigned char* encryptedKeyPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oiiii\", &encryptedKey, &encryptedKeyMaxLength, &formatType, &exportKey, &sessionKeyContext))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptExportKeyEx(NULL, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(encryptedKey, &encryptedKeyPtr, &encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportKeyEx(encryptedKeyPtr, encryptedKeyMaxLength, &encryptedKeyLength, formatType, exportKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointer(encryptedKey, encryptedKeyPtr);\n\treturn(processStatusReturnInt(status, encryptedKeyLength));\n}\n\nstatic PyObject* python_cryptImportKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tPyObject* encryptedKey = NULL;\n\tint encryptedKeyLength = 0;\n\tint importKey = 0;\n\tint sessionKeyContext = 0;\n\tunsigned char* encryptedKeyPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oii\", &encryptedKey, &importKey, &sessionKeyContext))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(encryptedKey, &encryptedKeyPtr, &encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKey(encryptedKeyPtr, encryptedKeyLength, importKey, sessionKeyContext);\n\t\n\tfinish:\n\treleasePointer(encryptedKey, encryptedKeyPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptImportKeyEx(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint returnedContext = 0;\n\tPyObject* encryptedKey = NULL;\n\tint encryptedKeyLength = 0;\n\tint importKey = 0;\n\tint sessionKeyContext = 0;\n\tunsigned char* encryptedKeyPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oii\", &encryptedKey, &importKey, &sessionKeyContext))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(encryptedKey, &encryptedKeyPtr, &encryptedKeyLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportKeyEx(encryptedKeyPtr, encryptedKeyLength, importKey, sessionKeyContext, &returnedContext);\n\t\n\tfinish:\n\treleasePointer(encryptedKey, encryptedKeyPtr);\n\treturn(processStatusReturnCryptHandle(status, returnedContext));\n}\n\nstatic PyObject* python_cryptCreateSignature(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint signatureLength = 0;\n\tPyObject* signature = NULL;\n\tint signatureMaxLength = 0;\n\tint signContext = 0;\n\tint hashContext = 0;\n\tunsigned char* signaturePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oiii\", &signature, &signatureMaxLength, &signContext, &hashContext))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptCreateSignature(NULL, signatureMaxLength, &signatureLength, signContext, hashContext)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(signature, &signaturePtr, &signatureLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignature(signaturePtr, signatureMaxLength, &signatureLength, signContext, hashContext);\n\t\n\tfinish:\n\treleasePointer(signature, signaturePtr);\n\treturn(processStatusReturnInt(status, signatureLength));\n}\n\nstatic PyObject* python_cryptCreateSignatureEx(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint signatureLength = 0;\n\tPyObject* signature = NULL;\n\tint signatureMaxLength = 0;\n\tint formatType = 0;\n\tint signContext = 0;\n\tint hashContext = 0;\n\tint extraData = 0;\n\tunsigned char* signaturePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oiiiii\", &signature, &signatureMaxLength, &formatType, &signContext, &hashContext, &extraData))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptCreateSignatureEx(NULL, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(signature, &signaturePtr, &signatureLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptCreateSignatureEx(signaturePtr, signatureMaxLength, &signatureLength, formatType, signContext, hashContext, extraData);\n\t\n\tfinish:\n\treleasePointer(signature, signaturePtr);\n\treturn(processStatusReturnInt(status, signatureLength));\n}\n\nstatic PyObject* python_cryptCheckSignature(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tPyObject* signature = NULL;\n\tint signatureLength = 0;\n\tint sigCheckKey = 0;\n\tint hashContext = 0;\n\tunsigned char* signaturePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oii\", &signature, &sigCheckKey, &hashContext))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(signature, &signaturePtr, &signatureLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignature(signaturePtr, signatureLength, sigCheckKey, hashContext);\n\t\n\tfinish:\n\treleasePointer(signature, signaturePtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCheckSignatureEx(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint extraData = 0;\n\tPyObject* signature = NULL;\n\tint signatureLength = 0;\n\tint sigCheckKey = 0;\n\tint hashContext = 0;\n\tunsigned char* signaturePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oii\", &signature, &sigCheckKey, &hashContext))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(signature, &signaturePtr, &signatureLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptCheckSignatureEx(signaturePtr, signatureLength, sigCheckKey, hashContext, &extraData);\n\t\n\tfinish:\n\treleasePointer(signature, signaturePtr);\n\treturn(processStatusReturnCryptHandle(status, extraData));\n}\n\nstatic PyObject* python_cryptKeysetOpen(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint cryptUser = 0;\n\tint keysetType = 0;\n\tPyObject* name = NULL;\n\tint options = 0;\n\tunsigned char* namePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiOi\", &cryptUser, &keysetType, &name, &options))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(name, &namePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptKeysetOpen(&keyset, cryptUser, keysetType, namePtr, options);\n\t\n\tfinish:\n\treleasePointerString(name, namePtr);\n\treturn(processStatusReturnCryptHandle(status, keyset));\n}\n\nstatic PyObject* python_cryptKeysetClose(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &keyset))\n\t    return(NULL);\n\t\n\tstatus = cryptKeysetClose(keyset);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptGetPublicKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tint keyset = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tunsigned char* keyIDPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &keyset, &keyIDtype, &keyID))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetPublicKey(keyset, &cryptContext, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treturn(processStatusReturnCryptHandle(status, cryptContext));\n}\n\nstatic PyObject* python_cryptGetPrivateKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tint keyset = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tPyObject* password = NULL;\n\tunsigned char* keyIDPtr = 0;\n\tunsigned char* passwordPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiOO\", &keyset, &keyIDtype, &keyID, &password))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\tif (!getPointerReadString(password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetPrivateKey(keyset, &cryptContext, keyIDtype, keyIDPtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treleasePointerString(password, passwordPtr);\n\treturn(processStatusReturnCryptHandle(status, cryptContext));\n}\n\nstatic PyObject* python_cryptGetKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tint keyset = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tPyObject* password = NULL;\n\tunsigned char* keyIDPtr = 0;\n\tunsigned char* passwordPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiOO\", &keyset, &keyIDtype, &keyID, &password))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\tif (!getPointerReadString(password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetKey(keyset, &cryptContext, keyIDtype, keyIDPtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treleasePointerString(password, passwordPtr);\n\treturn(processStatusReturnCryptHandle(status, cryptContext));\n}\n\nstatic PyObject* python_cryptAddPublicKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint certificate = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &keyset, &certificate))\n\t    return(NULL);\n\t\n\tstatus = cryptAddPublicKey(keyset, certificate);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptAddPrivateKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint cryptKey = 0;\n\tPyObject* password = NULL;\n\tunsigned char* passwordPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &keyset, &cryptKey, &password))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddPrivateKey(keyset, cryptKey, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(password, passwordPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptDeleteKey(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tunsigned char* keyIDPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &keyset, &keyIDtype, &keyID))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeleteKey(keyset, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCreateCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tint cryptUser = 0;\n\tint certType = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptUser, &certType))\n\t    return(NULL);\n\t\n\tstatus = cryptCreateCert(&certificate, cryptUser, certType);\n\t\n\treturn(processStatusReturnCryptHandle(status, certificate));\n}\n\nstatic PyObject* python_cryptDestroyCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &certificate))\n\t    return(NULL);\n\t\n\tstatus = cryptDestroyCert(certificate);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptGetCertExtension(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint extensionLength = 0;\n\tint criticalFlag = 0;\n\tint certificate = 0;\n\tPyObject* oid = NULL;\n\tPyObject* extension = NULL;\n\tint extensionMaxLength = 0;\n\tunsigned char* oidPtr = 0;\n\tunsigned char* extensionPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iOOi\", &certificate, &oid, &extension, &extensionMaxLength))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!processStatusBool(cryptGetCertExtension(certificate, oidPtr, &criticalFlag, NULL, extensionMaxLength, &extensionLength)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(extension, &extensionPtr, &extensionLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptGetCertExtension(certificate, oidPtr, &criticalFlag, extensionPtr, extensionMaxLength, &extensionLength);\n\t\n\tfinish:\n\treleasePointer(extension, extensionPtr);\n\treleasePointerString(oid, oidPtr);\n\treturn(processStatusReturnInt(status, extensionLength));\n}\n\nstatic PyObject* python_cryptAddCertExtension(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tPyObject* oid = NULL;\n\tint criticalFlag = 0;\n\tPyObject* extension = NULL;\n\tint extensionLength = 0;\n\tunsigned char* oidPtr = 0;\n\tunsigned char* extensionPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iOiO\", &certificate, &oid, &criticalFlag, &extension))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tif (!getPointerRead(extension, &extensionPtr, &extensionLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptAddCertExtension(certificate, oidPtr, criticalFlag, extensionPtr, extensionLength);\n\t\n\tfinish:\n\treleasePointer(extension, extensionPtr);\n\treleasePointerString(oid, oidPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptDeleteCertExtension(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tPyObject* oid = NULL;\n\tunsigned char* oidPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iO\", &certificate, &oid))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(oid, &oidPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeleteCertExtension(certificate, oidPtr);\n\t\n\tfinish:\n\treleasePointerString(oid, oidPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptSignCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tint signContext = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &certificate, &signContext))\n\t    return(NULL);\n\t\n\tstatus = cryptSignCert(certificate, signContext);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCheckCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tint sigCheckKey = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &certificate, &sigCheckKey))\n\t    return(NULL);\n\t\n\tstatus = cryptCheckCert(certificate, sigCheckKey);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptImportCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tPyObject* certObject = NULL;\n\tint certObjectLength = 0;\n\tint cryptUser = 0;\n\tunsigned char* certObjectPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oi\", &certObject, &cryptUser))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(certObject, &certObjectPtr, &certObjectLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptImportCert(certObjectPtr, certObjectLength, cryptUser, &certificate);\n\t\n\tfinish:\n\treleasePointer(certObject, certObjectPtr);\n\treturn(processStatusReturnCryptHandle(status, certificate));\n}\n\nstatic PyObject* python_cryptExportCert(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certObjectLength = 0;\n\tPyObject* certObject = NULL;\n\tint certObjectMaxLength = 0;\n\tint certFormatType = 0;\n\tint certificate = 0;\n\tunsigned char* certObjectPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"Oiii\", &certObject, &certObjectMaxLength, &certFormatType, &certificate))\n\t    return(NULL);\n\t\n\tif (!processStatusBool(cryptExportCert(NULL, certObjectMaxLength, &certObjectLength, certFormatType, certificate)))\n\t\tgoto finish;\n\t\n\tif (!getPointerWriteCheckIndices(certObject, &certObjectPtr, &certObjectLength))\n\t\tgoto finish;\n\t\n\tstatus = cryptExportCert(certObjectPtr, certObjectMaxLength, &certObjectLength, certFormatType, certificate);\n\t\n\tfinish:\n\treleasePointer(certObject, certObjectPtr);\n\treturn(processStatusReturnInt(status, certObjectLength));\n}\n\nstatic PyObject* python_cryptCAAddItem(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint certificate = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &keyset, &certificate))\n\t    return(NULL);\n\t\n\tstatus = cryptCAAddItem(keyset, certificate);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCAGetItem(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tint keyset = 0;\n\tint certType = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tunsigned char* keyIDPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiiO\", &keyset, &certType, &keyIDtype, &keyID))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCAGetItem(keyset, &certificate, certType, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treturn(processStatusReturnCryptHandle(status, certificate));\n}\n\nstatic PyObject* python_cryptCADeleteItem(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint keyset = 0;\n\tint certType = 0;\n\tint keyIDtype = 0;\n\tPyObject* keyID = NULL;\n\tunsigned char* keyIDPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiiO\", &keyset, &certType, &keyIDtype, &keyID))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(keyID, &keyIDPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptCADeleteItem(keyset, certType, keyIDtype, keyIDPtr);\n\t\n\tfinish:\n\treleasePointerString(keyID, keyIDPtr);\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCACertManagement(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint certificate = 0;\n\tint action = 0;\n\tint keyset = 0;\n\tint caKey = 0;\n\tint certRequest = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiii\", &action, &keyset, &caKey, &certRequest))\n\t    return(NULL);\n\t\n\tstatus = cryptCACertManagement(&certificate, action, keyset, caKey, certRequest);\n\t\n\treturn(processStatusReturnCryptHandle(status, certificate));\n}\n\nstatic PyObject* python_cryptCreateEnvelope(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint envelope = 0;\n\tint cryptUser = 0;\n\tint formatType = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptUser, &formatType))\n\t    return(NULL);\n\t\n\tstatus = cryptCreateEnvelope(&envelope, cryptUser, formatType);\n\t\n\treturn(processStatusReturnCryptHandle(status, envelope));\n}\n\nstatic PyObject* python_cryptDestroyEnvelope(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint envelope = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &envelope))\n\t    return(NULL);\n\t\n\tstatus = cryptDestroyEnvelope(envelope);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptCreateSession(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint session = 0;\n\tint cryptUser = 0;\n\tint formatType = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &cryptUser, &formatType))\n\t    return(NULL);\n\t\n\tstatus = cryptCreateSession(&session, cryptUser, formatType);\n\t\n\treturn(processStatusReturnCryptHandle(status, session));\n}\n\nstatic PyObject* python_cryptDestroySession(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint session = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &session))\n\t    return(NULL);\n\t\n\tstatus = cryptDestroySession(session);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptPushData(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint bytesCopied = 0;\n\tint envelope = 0;\n\tPyObject* buffer = NULL;\n\tint length = 0;\n\tunsigned char* bufferPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iO\", &envelope, &buffer))\n\t    return(NULL);\n\t\n\tif (!getPointerRead(buffer, &bufferPtr, &length))\n\t\tgoto finish;\n\t\n\tstatus = cryptPushData(envelope, bufferPtr, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointer(buffer, bufferPtr);\n\treturn(processStatusReturnInt(status, bytesCopied));\n}\n\nstatic PyObject* python_cryptFlushData(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint envelope = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &envelope))\n\t    return(NULL);\n\t\n\tstatus = cryptFlushData(envelope);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptPopData(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint bytesCopied = 0;\n\tint envelope = 0;\n\tPyObject* buffer = NULL;\n\tint length = 0;\n\tunsigned char* bufferPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iOi\", &envelope, &buffer, &length))\n\t    return(NULL);\n\t\n\t//CryptPopData is a special case that doesn't have the length querying call\n\t\n\tif (!getPointerWrite(buffer, &bufferPtr, &bytesCopied))\n\t\tgoto finish;\n\t\n\tstatus = cryptPopData(envelope, bufferPtr, length, &bytesCopied);\n\t\n\tfinish:\n\treleasePointer(buffer, bufferPtr);\n\treturn(processStatusReturnInt(status, bytesCopied));\n}\n\nstatic PyObject* python_cryptDeviceOpen(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint device = 0;\n\tint cryptUser = 0;\n\tint deviceType = 0;\n\tPyObject* name = NULL;\n\tunsigned char* namePtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"iiO\", &cryptUser, &deviceType, &name))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(name, &namePtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptDeviceOpen(&device, cryptUser, deviceType, namePtr);\n\t\n\tfinish:\n\treleasePointerString(name, namePtr);\n\treturn(processStatusReturnCryptHandle(status, device));\n}\n\nstatic PyObject* python_cryptDeviceClose(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint device = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &device))\n\t    return(NULL);\n\t\n\tstatus = cryptDeviceClose(device);\n\t\n\treturn(processStatus(status));\n}\n\nstatic PyObject* python_cryptDeviceQueryCapability(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\tint device = 0;\n\tint cryptAlgo = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &device, &cryptAlgo))\n\t    return(NULL);\n\t\n\tstatus = cryptDeviceQueryCapability(device, cryptAlgo, &cryptQueryInfo);\n\t\n\treturn(processStatusReturnCryptQueryInfo(status, cryptQueryInfo));\n}\n\nstatic PyObject* python_cryptDeviceCreateContext(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint cryptContext = 0;\n\tint device = 0;\n\tint cryptAlgo = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"ii\", &device, &cryptAlgo))\n\t    return(NULL);\n\t\n\tstatus = cryptDeviceCreateContext(device, &cryptContext, cryptAlgo);\n\t\n\treturn(processStatusReturnCryptHandle(status, cryptContext));\n}\n\nstatic PyObject* python_cryptLogin(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint user = 0;\n\tPyObject* name = NULL;\n\tPyObject* password = NULL;\n\tunsigned char* namePtr = 0;\n\tunsigned char* passwordPtr = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"OO\", &name, &password))\n\t    return(NULL);\n\t\n\tif (!getPointerReadString(name, &namePtr))\n\t\tgoto finish;\n\tif (!getPointerReadString(password, &passwordPtr))\n\t\tgoto finish;\n\t\n\tstatus = cryptLogin(&user, namePtr, passwordPtr);\n\t\n\tfinish:\n\treleasePointerString(name, namePtr);\n\treleasePointerString(password, passwordPtr);\n\treturn(processStatusReturnCryptHandle(status, user));\n}\n\nstatic PyObject* python_cryptLogout(PyObject* self, PyObject* args)\n{\n\tint status = 0;\n\tint user = 0;\n\t\n\tif (!PyArg_ParseTuple(args, \"i\", &user))\n\t    return(NULL);\n\t\n\tstatus = cryptLogout(user);\n\t\n\treturn(processStatus(status));\n}\n\n\n\nstatic PyMethodDef module_functions[] =\n{\n\t{ \"cryptInit\", python_cryptInit, METH_VARARGS }, \n\t{ \"cryptEnd\", python_cryptEnd, METH_VARARGS }, \n\t{ \"cryptQueryCapability\", python_cryptQueryCapability, METH_VARARGS }, \n\t{ \"cryptCreateContext\", python_cryptCreateContext, METH_VARARGS }, \n\t{ \"cryptDestroyContext\", python_cryptDestroyContext, METH_VARARGS }, \n\t{ \"cryptDestroyObject\", python_cryptDestroyObject, METH_VARARGS }, \n\t{ \"cryptGenerateKey\", python_cryptGenerateKey, METH_VARARGS }, \n\t{ \"cryptEncrypt\", python_cryptEncrypt, METH_VARARGS }, \n\t{ \"cryptDecrypt\", python_cryptDecrypt, METH_VARARGS }, \n\t{ \"cryptSetAttribute\", python_cryptSetAttribute, METH_VARARGS }, \n\t{ \"cryptSetAttributeString\", python_cryptSetAttributeString, METH_VARARGS }, \n\t{ \"cryptGetAttribute\", python_cryptGetAttribute, METH_VARARGS }, \n\t{ \"cryptGetAttributeString\", python_cryptGetAttributeString, METH_VARARGS }, \n\t{ \"cryptDeleteAttribute\", python_cryptDeleteAttribute, METH_VARARGS }, \n\t{ \"cryptAddRandom\", python_cryptAddRandom, METH_VARARGS }, \n\t{ \"cryptQueryObject\", python_cryptQueryObject, METH_VARARGS }, \n\t{ \"cryptExportKey\", python_cryptExportKey, METH_VARARGS }, \n\t{ \"cryptExportKeyEx\", python_cryptExportKeyEx, METH_VARARGS }, \n\t{ \"cryptImportKey\", python_cryptImportKey, METH_VARARGS }, \n\t{ \"cryptImportKeyEx\", python_cryptImportKeyEx, METH_VARARGS }, \n\t{ \"cryptCreateSignature\", python_cryptCreateSignature, METH_VARARGS }, \n\t{ \"cryptCreateSignatureEx\", python_cryptCreateSignatureEx, METH_VARARGS }, \n\t{ \"cryptCheckSignature\", python_cryptCheckSignature, METH_VARARGS }, \n\t{ \"cryptCheckSignatureEx\", python_cryptCheckSignatureEx, METH_VARARGS }, \n\t{ \"cryptKeysetOpen\", python_cryptKeysetOpen, METH_VARARGS }, \n\t{ \"cryptKeysetClose\", python_cryptKeysetClose, METH_VARARGS }, \n\t{ \"cryptGetPublicKey\", python_cryptGetPublicKey, METH_VARARGS }, \n\t{ \"cryptGetPrivateKey\", python_cryptGetPrivateKey, METH_VARARGS }, \n\t{ \"cryptGetKey\", python_cryptGetKey, METH_VARARGS }, \n\t{ \"cryptAddPublicKey\", python_cryptAddPublicKey, METH_VARARGS }, \n\t{ \"cryptAddPrivateKey\", python_cryptAddPrivateKey, METH_VARARGS }, \n\t{ \"cryptDeleteKey\", python_cryptDeleteKey, METH_VARARGS }, \n\t{ \"cryptCreateCert\", python_cryptCreateCert, METH_VARARGS }, \n\t{ \"cryptDestroyCert\", python_cryptDestroyCert, METH_VARARGS }, \n\t{ \"cryptGetCertExtension\", python_cryptGetCertExtension, METH_VARARGS }, \n\t{ \"cryptAddCertExtension\", python_cryptAddCertExtension, METH_VARARGS }, \n\t{ \"cryptDeleteCertExtension\", python_cryptDeleteCertExtension, METH_VARARGS }, \n\t{ \"cryptSignCert\", python_cryptSignCert, METH_VARARGS }, \n\t{ \"cryptCheckCert\", python_cryptCheckCert, METH_VARARGS }, \n\t{ \"cryptImportCert\", python_cryptImportCert, METH_VARARGS }, \n\t{ \"cryptExportCert\", python_cryptExportCert, METH_VARARGS }, \n\t{ \"cryptCAAddItem\", python_cryptCAAddItem, METH_VARARGS }, \n\t{ \"cryptCAGetItem\", python_cryptCAGetItem, METH_VARARGS }, \n\t{ \"cryptCADeleteItem\", python_cryptCADeleteItem, METH_VARARGS }, \n\t{ \"cryptCACertManagement\", python_cryptCACertManagement, METH_VARARGS }, \n\t{ \"cryptCreateEnvelope\", python_cryptCreateEnvelope, METH_VARARGS }, \n\t{ \"cryptDestroyEnvelope\", python_cryptDestroyEnvelope, METH_VARARGS }, \n\t{ \"cryptCreateSession\", python_cryptCreateSession, METH_VARARGS }, \n\t{ \"cryptDestroySession\", python_cryptDestroySession, METH_VARARGS }, \n\t{ \"cryptPushData\", python_cryptPushData, METH_VARARGS }, \n\t{ \"cryptFlushData\", python_cryptFlushData, METH_VARARGS }, \n\t{ \"cryptPopData\", python_cryptPopData, METH_VARARGS }, \n\t{ \"cryptDeviceOpen\", python_cryptDeviceOpen, METH_VARARGS }, \n\t{ \"cryptDeviceClose\", python_cryptDeviceClose, METH_VARARGS }, \n\t{ \"cryptDeviceQueryCapability\", python_cryptDeviceQueryCapability, METH_VARARGS }, \n\t{ \"cryptDeviceCreateContext\", python_cryptDeviceCreateContext, METH_VARARGS }, \n\t{ \"cryptLogin\", python_cryptLogin, METH_VARARGS }, \n\t{ \"cryptLogout\", python_cryptLogout, METH_VARARGS }, \n    {0, 0}\n};\n\n#if PY_MAJOR_VERSION >= 3\nstatic struct PyModuleDef moduledef = {\n        PyModuleDef_HEAD_INIT,\n        \"cryptlib_py\",\n        NULL,\n        -1,\n        module_functions,\n        NULL,\n        NULL,\n        NULL,\n        NULL\n};\n#endif\n\nPyMODINIT_FUNC\n#if PY_MAJOR_VERSION >= 3\nPyInit_cryptlib_py(void)\n#else\ninitcryptlib_py(void)\n#endif\n\n{\n    PyObject* module;\n    #if PY_MAJOR_VERSION >= 3\n    module = PyModule_Create(&moduledef);\n    if (module == NULL){\n        return NULL;\n    }\n    #else\n    module = Py_InitModule(\"cryptlib_py\", module_functions);\n    #endif\n    \n    \n    PyObject* moduleDict;\n\n    PyObject* v = NULL;\n    PyObject *globalsDict;\n\n    moduleDict = PyModule_GetDict(module);\n\n    CryptException = PyErr_NewException(\"cryptlib_py.CryptException\", NULL, NULL);\n    PyDict_SetItemString(moduleDict, \"CryptException\", CryptException);\n\n    globalsDict = PyEval_GetGlobals();\n    PyRun_String(\n\"from array import *\\n\\\nimport types\\n\\\nclass CryptHandle:\\n\\\n    def __init__(self, value):\\n\\\n        self.__dict__['value'] = value\\n\\\n    def __int__(self):\\n\\\n        return self.value\\n\\\n    def __str__(self):\\n\\\n        return str(self.value)\\n\\\n    def __repr__(self):\\n\\\n        return str(self.value)\\n\\\n    def __getattr__(self, name):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        try:\\n\\\n            return cryptGetAttribute(self, nameVal)\\n\\\n        except CryptException:\\n\\\n            length = cryptGetAttributeString(self, nameVal, None)\\n\\\n            buf = array('c', '0' * length)\\n\\\n            length = cryptGetAttributeString(self, nameVal, buf)\\n\\\n            return ''.join(buf[:length])\\n\\\n    def __setattr__(self, name, value):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        if isinstance(value, types.IntType) or isinstance(value, CryptHandle):\\n\\\n            cryptSetAttribute(self, nameVal, value)\\n\\\n        else:\\n\\\n            cryptSetAttributeString(self, nameVal, value)\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n\n    PyRun_String(\n\"class CRYPT_QUERY_INFO:\\n\\\n    def __init__(self, algoName, blockSize, minKeySize, keySize, maxKeySize):\\n\\\n        self.algoName = algoName\\n\\\n        self.blockSize = blockSize\\n\\\n        self.minKeySize = minKeySize\\n\\\n        self.keySize = keySize\\n\\\n        self.maxKeySize = maxKeySize\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    PyRun_String(\n\"class CRYPT_OBJECT_INFO:\\n\\\n    def __init__(self, objectType, cryptAlgo, cryptMode, hashAlgo, salt):\\n\\\n        self.objectType = objectType\\n\\\n        self.cryptAlgo = cryptAlgo\\n\\\n        self.cryptMode = cryptMode\\n\\\n        self.hashAlgo = hashAlgo\\n\\\n        self.salt = salt\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    cryptHandleClass = PyMapping_GetItemString(moduleDict, \"CryptHandle\");\n    cryptQueryInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_QUERY_INFO\");\n    cryptObjectInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_OBJECT_INFO\");\n\n    Py_DECREF(globalsDict);\n\n\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_NONE\", v);\n    Py_DECREF(v); /* No encryption */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_DES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_DES\", v);\n    Py_DECREF(v); /* DES */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_3DES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_3DES\", v);\n    Py_DECREF(v); /* Triple DES */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_IDEA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_IDEA\", v);\n    Py_DECREF(v); /* IDEA (only used for PGP 2.x) */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_CAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_CAST\", v);\n    Py_DECREF(v); /* CAST-128 (only used for OpenPGP) */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RC2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RC2\", v);\n    Py_DECREF(v); /* RC2 (disabled by default, used for PKCS #12) */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RC4);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RC4\", v);\n    Py_DECREF(v); /* RC4 (insecure, deprecated) */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED1\", v);\n    Py_DECREF(v); /* Formerly RC5 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_AES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_AES\", v);\n    Py_DECREF(v); /* AES */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED2\", v);\n    Py_DECREF(v); /* Formerly Blowfish */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_DH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_DH\", v);\n    Py_DECREF(v); /* Diffie-Hellman */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RSA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RSA\", v);\n    Py_DECREF(v); /* RSA */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_DSA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_DSA\", v);\n    Py_DECREF(v); /* DSA */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_ELGAMAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_ELGAMAL\", v);\n    Py_DECREF(v); /* ElGamal */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED3);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED3\", v);\n    Py_DECREF(v); /* Formerly KEA */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_ECDSA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_ECDSA\", v);\n    Py_DECREF(v); /* ECDSA */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_ECDH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_ECDH\", v);\n    Py_DECREF(v); /* ECDH */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED4);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED4\", v);\n    Py_DECREF(v); /* Formerly MD2 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED5);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED5\", v);\n    Py_DECREF(v); /* Formerly MD4 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_MD5);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_MD5\", v);\n    Py_DECREF(v); /* MD5 (only used for TLS 1.0/1.1) */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_SHA1\", v);\n    Py_DECREF(v); /* SHA/SHA1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED6);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED6\", v);\n    Py_DECREF(v); /* Formerly RIPE-MD 160 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_SHA2\", v);\n    Py_DECREF(v); /* SHA-256 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_SHA256);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_SHA256\", v);\n    Py_DECREF(v); /* Alternate name */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_SHAng\", v);\n    Py_DECREF(v); /* Future SHA-nextgen standard */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESREVED_7);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESREVED_7\", v);\n    Py_DECREF(v); /* Formerly HMAC-MD5 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_HMAC_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_HMAC_SHA1\", v);\n    Py_DECREF(v); /* HMAC-SHA */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_RESERVED8);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_RESERVED8\", v);\n    Py_DECREF(v); /* Formerly HMAC-RIPEMD-160 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_HMAC_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_HMAC_SHA2\", v);\n    Py_DECREF(v); /* HMAC-SHA2 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_HMAC_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_HMAC_SHAng\", v);\n    Py_DECREF(v); /* HMAC-future-SHA-nextgen */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_LAST\", v);\n    Py_DECREF(v); /* Last possible crypt algo value */\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_FIRST_CONVENTIONAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_FIRST_CONVENTIONAL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_LAST_CONVENTIONAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_LAST_CONVENTIONAL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_FIRST_PKC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_FIRST_PKC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_LAST_PKC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_LAST_PKC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_FIRST_HASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_FIRST_HASH\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_LAST_HASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_LAST_HASH\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_FIRST_MAC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_FIRST_MAC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ALGO_LAST_MAC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ALGO_LAST_MAC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_NONE\", v);\n    Py_DECREF(v); /* No encryption mode */\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_ECB);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_ECB\", v);\n    Py_DECREF(v); /* ECB */\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_CBC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_CBC\", v);\n    Py_DECREF(v); /* CBC */\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_CFB);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_CFB\", v);\n    Py_DECREF(v); /* CFB */\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_GCM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_GCM\", v);\n    Py_DECREF(v); /* GCM */\n\n    v = Py_BuildValue(\"i\", CRYPT_MODE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MODE_LAST\", v);\n    Py_DECREF(v); /* Last possible crypt mode value */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_NONE\", v);\n    Py_DECREF(v); /* No keyset type */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_FILE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_FILE\", v);\n    Py_DECREF(v); /* Generic flat file keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_HTTP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_HTTP\", v);\n    Py_DECREF(v); /* Web page containing cert/CRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_LDAP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_LDAP\", v);\n    Py_DECREF(v); /* LDAP directory service */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_ODBC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_ODBC\", v);\n    Py_DECREF(v); /* Generic ODBC interface */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_DATABASE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_DATABASE\", v);\n    Py_DECREF(v); /* Generic RDBMS interface */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_ODBC_STORE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_ODBC_STORE\", v);\n    Py_DECREF(v); /* ODBC certificate store */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_DATABASE_STORE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_DATABASE_STORE\", v);\n    Py_DECREF(v); /* Database certificate store */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYSET_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYSET_LAST\", v);\n    Py_DECREF(v); /* Last possible keyset type */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_NONE\", v);\n    Py_DECREF(v); /* No crypto device */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_FORTEZZA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_FORTEZZA\", v);\n    Py_DECREF(v); /* Fortezza card - Placeholder only */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_PKCS11);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_PKCS11\", v);\n    Py_DECREF(v); /* PKCS #11 crypto token */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_CRYPTOAPI);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_CRYPTOAPI\", v);\n    Py_DECREF(v); /* Microsoft CryptoAPI */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_HARDWARE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_HARDWARE\", v);\n    Py_DECREF(v); /* Generic crypo HW plugin */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVICE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVICE_LAST\", v);\n    Py_DECREF(v); /* Last possible crypto device type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_NONE\", v);\n    Py_DECREF(v); /* No certificate type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_CERTIFICATE\", v);\n    Py_DECREF(v); /* Certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_ATTRIBUTE_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_ATTRIBUTE_CERT\", v);\n    Py_DECREF(v); /* Attribute certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_CERTCHAIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_CERTCHAIN\", v);\n    Py_DECREF(v); /* PKCS #7 certificate chain */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_CERTREQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_CERTREQUEST\", v);\n    Py_DECREF(v); /* PKCS #10 certification request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_REQUEST_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_REQUEST_CERT\", v);\n    Py_DECREF(v); /* CRMF certification request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_REQUEST_REVOCATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_REQUEST_REVOCATION\", v);\n    Py_DECREF(v); /* CRMF revocation request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_CRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_CRL\", v);\n    Py_DECREF(v); /* CRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_CMS_ATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_CMS_ATTRIBUTES\", v);\n    Py_DECREF(v); /* CMS attributes */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_RTCS_REQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_RTCS_REQUEST\", v);\n    Py_DECREF(v); /* RTCS request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_RTCS_RESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_RTCS_RESPONSE\", v);\n    Py_DECREF(v); /* RTCS response */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_OCSP_REQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_OCSP_REQUEST\", v);\n    Py_DECREF(v); /* OCSP request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_OCSP_RESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_OCSP_RESPONSE\", v);\n    Py_DECREF(v); /* OCSP response */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_PKIUSER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_PKIUSER\", v);\n    Py_DECREF(v); /* PKI user information */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTTYPE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTTYPE_LAST\", v);\n    Py_DECREF(v); /* Last possible cert.type */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_NONE\", v);\n    Py_DECREF(v); /* No format type */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_AUTO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_AUTO\", v);\n    Py_DECREF(v); /* Deenv, auto-determine type */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_CRYPTLIB);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_CRYPTLIB\", v);\n    Py_DECREF(v); /* cryptlib native format */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_CMS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_CMS\", v);\n    Py_DECREF(v); /* PKCS #7 / CMS / S/MIME fmt. */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_PKCS7);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_PKCS7\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_SMIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_SMIME\", v);\n    Py_DECREF(v); /* As CMS with MSG-style behaviour */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_PGP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_PGP\", v);\n    Py_DECREF(v); /* PGP format */\n\n    v = Py_BuildValue(\"i\", CRYPT_FORMAT_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_FORMAT_LAST\", v);\n    Py_DECREF(v); /* Last possible format type */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_NONE\", v);\n    Py_DECREF(v); /* No session type */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SSH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SSH\", v);\n    Py_DECREF(v); /* SSH */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SSH_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SSH_SERVER\", v);\n    Py_DECREF(v); /* SSH server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SSL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SSL\", v);\n    Py_DECREF(v); /* SSL/TLS */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_TLS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_TLS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SSL_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SSL_SERVER\", v);\n    Py_DECREF(v); /* SSL/TLS server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_TLS_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_TLS_SERVER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_RTCS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_RTCS\", v);\n    Py_DECREF(v); /* RTCS */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_RTCS_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_RTCS_SERVER\", v);\n    Py_DECREF(v); /* RTCS server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_OCSP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_OCSP\", v);\n    Py_DECREF(v); /* OCSP */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_OCSP_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_OCSP_SERVER\", v);\n    Py_DECREF(v); /* OCSP server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_TSP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_TSP\", v);\n    Py_DECREF(v); /* TSP */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_TSP_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_TSP_SERVER\", v);\n    Py_DECREF(v); /* TSP server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_CMP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_CMP\", v);\n    Py_DECREF(v); /* CMP */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_CMP_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_CMP_SERVER\", v);\n    Py_DECREF(v); /* CMP server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SCEP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SCEP\", v);\n    Py_DECREF(v); /* SCEP */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_SCEP_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_SCEP_SERVER\", v);\n    Py_DECREF(v); /* SCEP server */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_CERTSTORE_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_CERTSTORE_SERVER\", v);\n    Py_DECREF(v); /* HTTP cert store interface */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSION_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSION_LAST\", v);\n    Py_DECREF(v); /* Last possible session type */\n\n    v = Py_BuildValue(\"i\", CRYPT_USER_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USER_NONE\", v);\n    Py_DECREF(v); /* No user type */\n\n    v = Py_BuildValue(\"i\", CRYPT_USER_NORMAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USER_NORMAL\", v);\n    Py_DECREF(v); /* Normal user */\n\n    v = Py_BuildValue(\"i\", CRYPT_USER_SO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USER_SO\", v);\n    Py_DECREF(v); /* Security officer */\n\n    v = Py_BuildValue(\"i\", CRYPT_USER_CA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USER_CA\", v);\n    Py_DECREF(v); /* CA user */\n\n    v = Py_BuildValue(\"i\", CRYPT_USER_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USER_LAST\", v);\n    Py_DECREF(v); /* Last possible user type */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_NONE\", v);\n    Py_DECREF(v); /* Non-value */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_FIRST\", v);\n    Py_DECREF(v); /* ******************* */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_HIGHSECURITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_HIGHSECURITY\", v);\n    Py_DECREF(v); /* Owned+non-forwardcount+locked */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_OWNER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_OWNER\", v);\n    Py_DECREF(v); /* Object owner */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_FORWARDCOUNT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_FORWARDCOUNT\", v);\n    Py_DECREF(v); /* No.of times object can be forwarded */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_LOCKED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_LOCKED\", v);\n    Py_DECREF(v); /* Whether properties can be chged/read */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_USAGECOUNT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_USAGECOUNT\", v);\n    Py_DECREF(v); /* Usage count before object expires */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_NONEXPORTABLE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_NONEXPORTABLE\", v);\n    Py_DECREF(v); /* Whether key is nonexp.from context */\n\n    v = Py_BuildValue(\"i\", CRYPT_PROPERTY_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_PROPERTY_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_GENERIC_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_GENERIC_FIRST\", v);\n    Py_DECREF(v); /* Extended error information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_ERRORTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_ERRORTYPE\", v);\n    Py_DECREF(v); /* Type of last error */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_ERRORLOCUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_ERRORLOCUS\", v);\n    Py_DECREF(v); /* Locus of last error */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_ERRORMESSAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_ERRORMESSAGE\", v);\n    Py_DECREF(v); /* Detailed error description */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_CURRENT_GROUP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_CURRENT_GROUP\", v);\n    Py_DECREF(v); /* Cursor mgt: Group in attribute list */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_CURRENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_CURRENT\", v);\n    Py_DECREF(v); /* Cursor mgt: Entry in attribute list */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_CURRENT_INSTANCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_CURRENT_INSTANCE\", v);\n    Py_DECREF(v); /* Cursor mgt: Instance in attribute list */\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_BUFFERSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_BUFFERSIZE\", v);\n    Py_DECREF(v); /* Internal data buffer size */\n\n    v = Py_BuildValue(\"i\", CRYPT_GENERIC_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_GENERIC_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_FIRST\", v);\n    Py_DECREF(v); /* ************************** */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_INFO_DESCRIPTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_INFO_DESCRIPTION\", v);\n    Py_DECREF(v); /* Text description */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_INFO_COPYRIGHT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_INFO_COPYRIGHT\", v);\n    Py_DECREF(v); /* Copyright notice */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_INFO_MAJORVERSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_INFO_MAJORVERSION\", v);\n    Py_DECREF(v); /* Major release version */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_INFO_MINORVERSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_INFO_MINORVERSION\", v);\n    Py_DECREF(v); /* Minor release version */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_INFO_STEPPING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_INFO_STEPPING\", v);\n    Py_DECREF(v); /* Release stepping */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_ENCR_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_ENCR_ALGO\", v);\n    Py_DECREF(v); /* Conventional ncryption algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_ENCR_HASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_ENCR_HASH\", v);\n    Py_DECREF(v); /* Hash algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_ENCR_MAC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_ENCR_MAC\", v);\n    Py_DECREF(v); /* MAC algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_PKC_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_PKC_ALGO\", v);\n    Py_DECREF(v); /* PKC algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_PKC_KEYSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_PKC_KEYSIZE\", v);\n    Py_DECREF(v); /* PKC key size */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DUMMY1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DUMMY1\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DUMMY2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DUMMY2\", v);\n    Py_DECREF(v); /* Keying options */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYING_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYING_ALGO\", v);\n    Py_DECREF(v); /* Key processing algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYING_ITERATIONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYING_ITERATIONS\", v);\n    Py_DECREF(v); /* Key processing iterations */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES\", v);\n    Py_DECREF(v); /* Whether to sign unrecog.attrs */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CERT_VALIDITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CERT_VALIDITY\", v);\n    Py_DECREF(v); /* Certificate validity period */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CERT_UPDATEINTERVAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CERT_UPDATEINTERVAL\", v);\n    Py_DECREF(v); /* CRL update interval */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CERT_COMPLIANCELEVEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CERT_COMPLIANCELEVEL\", v);\n    Py_DECREF(v); /* PKIX compliance level for cert chks. */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CERT_REQUIREPOLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CERT_REQUIREPOLICY\", v);\n    Py_DECREF(v); /* Whether explicit policy req'd for certs */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CMS_DEFAULTATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CMS_DEFAULTATTRIBUTES\", v);\n    Py_DECREF(v); /* Add default CMS attributes */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_SMIME_DEFAULTATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_SMIME_DEFAULTATTRIBUTES\", v);\n    Py_DECREF(v); /* LDAP keyset options */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS\", v);\n    Py_DECREF(v); /* Object class */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE\", v);\n    Py_DECREF(v); /* Object type to fetch */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_FILTER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_FILTER\", v);\n    Py_DECREF(v); /* Query filter */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_CACERTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_CACERTNAME\", v);\n    Py_DECREF(v); /* CA certificate attribute name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_CERTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_CERTNAME\", v);\n    Py_DECREF(v); /* Certificate attribute name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_CRLNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_CRLNAME\", v);\n    Py_DECREF(v); /* CRL attribute name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_KEYS_LDAP_EMAILNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_KEYS_LDAP_EMAILNAME\", v);\n    Py_DECREF(v); /* Email attribute name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_DVR01);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_DVR01\", v);\n    Py_DECREF(v); /* Name of first PKCS #11 driver */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_DVR02);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_DVR02\", v);\n    Py_DECREF(v); /* Name of second PKCS #11 driver */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_DVR03);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_DVR03\", v);\n    Py_DECREF(v); /* Name of third PKCS #11 driver */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_DVR04);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_DVR04\", v);\n    Py_DECREF(v); /* Name of fourth PKCS #11 driver */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_DVR05);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_DVR05\", v);\n    Py_DECREF(v); /* Name of fifth PKCS #11 driver */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY\", v);\n    Py_DECREF(v); /* Use only hardware mechanisms */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_SOCKS_SERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_SOCKS_SERVER\", v);\n    Py_DECREF(v); /* Socks server name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_SOCKS_USERNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_SOCKS_USERNAME\", v);\n    Py_DECREF(v); /* Socks user name */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_HTTP_PROXY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_HTTP_PROXY\", v);\n    Py_DECREF(v); /* Web proxy server */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_CONNECTTIMEOUT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_CONNECTTIMEOUT\", v);\n    Py_DECREF(v); /* Timeout for network connection setup */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_READTIMEOUT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_READTIMEOUT\", v);\n    Py_DECREF(v); /* Timeout for network reads */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_NET_WRITETIMEOUT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_NET_WRITETIMEOUT\", v);\n    Py_DECREF(v); /* Timeout for network writes */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_MISC_ASYNCINIT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_MISC_ASYNCINIT\", v);\n    Py_DECREF(v); /* Whether to init cryptlib async'ly */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_MISC_SIDECHANNELPROTECTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_MISC_SIDECHANNELPROTECTION\", v);\n    Py_DECREF(v); /* Protect against side-channel attacks */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_CONFIGCHANGED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_CONFIGCHANGED\", v);\n    Py_DECREF(v); /* Whether in-mem.opts match on-disk ones */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_SELFTESTOK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_SELFTESTOK\", v);\n    Py_DECREF(v); /* Whether self-test was completed and OK */\n\n    v = Py_BuildValue(\"i\", CRYPT_OPTION_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OPTION_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_FIRST\", v);\n    Py_DECREF(v); /* ******************** */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_ALGO\", v);\n    Py_DECREF(v); /* Algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_MODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_MODE\", v);\n    Py_DECREF(v); /* Mode */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_NAME_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_NAME_ALGO\", v);\n    Py_DECREF(v); /* Algorithm name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_NAME_MODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_NAME_MODE\", v);\n    Py_DECREF(v); /* Mode name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEYSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEYSIZE\", v);\n    Py_DECREF(v); /* Key size in bytes */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_BLOCKSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_BLOCKSIZE\", v);\n    Py_DECREF(v); /* Block size */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_IVSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_IVSIZE\", v);\n    Py_DECREF(v); /* IV size */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEYING_ALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEYING_ALGO\", v);\n    Py_DECREF(v); /* Key processing algorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEYING_ITERATIONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEYING_ITERATIONS\", v);\n    Py_DECREF(v); /* Key processing iterations */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEYING_SALT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEYING_SALT\", v);\n    Py_DECREF(v); /* Key processing salt */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEYING_VALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEYING_VALUE\", v);\n    Py_DECREF(v); /* Value used to derive key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEY\", v);\n    Py_DECREF(v); /* Key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_KEY_COMPONENTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_KEY_COMPONENTS\", v);\n    Py_DECREF(v); /* Public-key components */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_IV);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_IV\", v);\n    Py_DECREF(v); /* IV */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_HASHVALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_HASHVALUE\", v);\n    Py_DECREF(v); /* Hash value */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_LABEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_LABEL\", v);\n    Py_DECREF(v); /* Label for private/secret key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_PERSISTENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_PERSISTENT\", v);\n    Py_DECREF(v); /* Obj.is backed by device or keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_CTXINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CTXINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FIRST\", v);\n    Py_DECREF(v); /* ************************ */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SELFSIGNED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SELFSIGNED\", v);\n    Py_DECREF(v); /* Cert is self-signed */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IMMUTABLE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IMMUTABLE\", v);\n    Py_DECREF(v); /* Cert is signed and immutable */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_XYZZY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_XYZZY\", v);\n    Py_DECREF(v); /* Cert is a magic just-works cert */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTTYPE\", v);\n    Py_DECREF(v); /* Certificate object type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FINGERPRINT_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FINGERPRINT_SHA1\", v);\n    Py_DECREF(v); /* Certificate fingerprints */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FINGERPRINT_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FINGERPRINT_SHA2\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FINGERPRINT_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FINGERPRINT_SHAng\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CURRENT_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CURRENT_CERTIFICATE\", v);\n    Py_DECREF(v); /* Cursor mgt: Rel.pos in chain/CRL/OCSP */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TRUSTED_USAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TRUSTED_USAGE\", v);\n    Py_DECREF(v); /* Usage that cert is trusted for */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TRUSTED_IMPLICIT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TRUSTED_IMPLICIT\", v);\n    Py_DECREF(v); /* Whether cert is implicitly trusted */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGNATURELEVEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGNATURELEVEL\", v);\n    Py_DECREF(v); /* Amount of detail to include in sigs. */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_VERSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_VERSION\", v);\n    Py_DECREF(v); /* Cert.format version */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SERIALNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SERIALNUMBER\", v);\n    Py_DECREF(v); /* Serial number */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO\", v);\n    Py_DECREF(v); /* Public key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTIFICATE\", v);\n    Py_DECREF(v); /* User certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_USERCERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_USERCERTIFICATE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CACERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CACERTIFICATE\", v);\n    Py_DECREF(v); /* CA certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUERNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUERNAME\", v);\n    Py_DECREF(v); /* Issuer DN */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_VALIDFROM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_VALIDFROM\", v);\n    Py_DECREF(v); /* Cert valid-from time */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_VALIDTO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_VALIDTO\", v);\n    Py_DECREF(v); /* Cert valid-to time */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTNAME\", v);\n    Py_DECREF(v); /* Subject DN */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUERUNIQUEID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUERUNIQUEID\", v);\n    Py_DECREF(v); /* Issuer unique ID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTUNIQUEID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTUNIQUEID\", v);\n    Py_DECREF(v); /* Subject unique ID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTREQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTREQUEST\", v);\n    Py_DECREF(v); /* Cert.request (DN + public key) */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_THISUPDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_THISUPDATE\", v);\n    Py_DECREF(v); /* CRL/OCSP current-update time */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NEXTUPDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NEXTUPDATE\", v);\n    Py_DECREF(v); /* CRL/OCSP next-update time */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOCATIONDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOCATIONDATE\", v);\n    Py_DECREF(v); /* CRL/OCSP cert-revocation time */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOCATIONSTATUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOCATIONSTATUS\", v);\n    Py_DECREF(v); /* OCSP revocation status */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTSTATUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTSTATUS\", v);\n    Py_DECREF(v); /* RTCS certificate status */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DN\", v);\n    Py_DECREF(v); /* Currently selected DN in string form */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PKIUSER_ID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PKIUSER_ID\", v);\n    Py_DECREF(v); /* PKI user ID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD\", v);\n    Py_DECREF(v); /* PKI user issue password */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PKIUSER_REVPASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PKIUSER_REVPASSWORD\", v);\n    Py_DECREF(v); /* PKI user revocation password */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PKIUSER_RA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PKIUSER_RA\", v);\n    Py_DECREF(v); /* PKI user is an RA */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_COUNTRYNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_COUNTRYNAME\", v);\n    Py_DECREF(v); /* countryName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_STATEORPROVINCENAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_STATEORPROVINCENAME\", v);\n    Py_DECREF(v); /* stateOrProvinceName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_LOCALITYNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_LOCALITYNAME\", v);\n    Py_DECREF(v); /* localityName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ORGANIZATIONNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ORGANIZATIONNAME\", v);\n    Py_DECREF(v); /* organizationName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ORGANISATIONNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ORGANISATIONNAME\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ORGANIZATIONALUNITNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ORGANIZATIONALUNITNAME\", v);\n    Py_DECREF(v); /* organizationalUnitName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ORGANISATIONALUNITNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ORGANISATIONALUNITNAME\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_COMMONNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_COMMONNAME\", v);\n    Py_DECREF(v); /* commonName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OTHERNAME_TYPEID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OTHERNAME_TYPEID\", v);\n    Py_DECREF(v); /* otherName.typeID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OTHERNAME_VALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OTHERNAME_VALUE\", v);\n    Py_DECREF(v); /* otherName.value */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_RFC822NAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_RFC822NAME\", v);\n    Py_DECREF(v); /* rfc822Name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EMAIL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EMAIL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DNSNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DNSNAME\", v);\n    Py_DECREF(v); /* dNSName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DIRECTORYNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DIRECTORYNAME\", v);\n    Py_DECREF(v); /* directoryName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER\", v);\n    Py_DECREF(v); /* ediPartyName.nameAssigner */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME\", v);\n    Py_DECREF(v); /* ediPartyName.partyName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER\", v);\n    Py_DECREF(v); /* uniformResourceIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_URL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_URL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESS\", v);\n    Py_DECREF(v); /* iPAddress */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REGISTEREDID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REGISTEREDID\", v);\n    Py_DECREF(v); /* registeredID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CHALLENGEPASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CHALLENGEPASSWORD\", v);\n    Py_DECREF(v); /* 1 3 6 1 4 1 3029 3 1 4 cRLExtReason */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLEXTREASON);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLEXTREASON\", v);\n    Py_DECREF(v); /* 1 3 6 1 4 1 3029 3 1 5 keyFeatures */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_KEYFEATURES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_KEYFEATURES\", v);\n    Py_DECREF(v); /* 1 3 6 1 5 5 7 1 1 authorityInfoAccess */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFOACCESS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFOACCESS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFO_RTCS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFO_RTCS\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFO_OCSP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFO_OCSP\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYINFO_CRLS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYINFO_CRLS\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BIOMETRICINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BIOMETRICINFO\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BIOMETRICINFO_TYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BIOMETRICINFO_TYPE\", v);\n    Py_DECREF(v); /* biometricData.typeOfData */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO\", v);\n    Py_DECREF(v); /* biometricData.hashAlgorithm */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BIOMETRICINFO_HASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BIOMETRICINFO_HASH\", v);\n    Py_DECREF(v); /* biometricData.dataHash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BIOMETRICINFO_URL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BIOMETRICINFO_URL\", v);\n    Py_DECREF(v); /* biometricData.sourceDataUri */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_QCSTATEMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_QCSTATEMENT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS\", v);\n    Py_DECREF(v); /* qcStatement.statementInfo.semanticsIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY\", v);\n    Py_DECREF(v); /* qcStatement.statementInfo.nameRegistrationAuthorities */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESSBLOCKS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESSBLOCKS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY\", v);\n    Py_DECREF(v); /* addressFamily */\tCRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX,\t/* ipAddress.addressPrefix */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX\", v);\n    Py_DECREF(v); /* ipAddress.addressPrefix */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN\", v);\n    Py_DECREF(v); /* ipAddress.addressRangeMin */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX\", v);\n    Py_DECREF(v); /* ipAddress.addressRangeMax */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTONOMOUSSYSIDS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTONOMOUSSYSIDS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID\", v);\n    Py_DECREF(v); /* asNum.id */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN\", v);\n    Py_DECREF(v); /* asNum.min */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX\", v);\n    Py_DECREF(v); /* asNum.max */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OCSP_NONCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OCSP_NONCE\", v);\n    Py_DECREF(v); /* nonce */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OCSP_RESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OCSP_RESPONSE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OCSP_RESPONSE_OCSP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OCSP_RESPONSE_OCSP\", v);\n    Py_DECREF(v); /* OCSP standard response */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OCSP_NOCHECK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OCSP_NOCHECK\", v);\n    Py_DECREF(v); /* 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF\", v);\n    Py_DECREF(v); /* 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFOACCESS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFOACCESS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT\", v);\n    Py_DECREF(v); /* accessDescription.accessLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_DATEOFCERTGEN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_DATEOFCERTGEN\", v);\n    Py_DECREF(v); /* 1 3 36 8 3 2 siggProcuration */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_PROCURATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_PROCURATION\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY\", v);\n    Py_DECREF(v); /* country */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION\", v);\n    Py_DECREF(v); /* typeOfSubstitution */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR\", v);\n    Py_DECREF(v); /* signingFor.thirdPerson */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY\", v);\n    Py_DECREF(v); /* authority */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID\", v);\n    Py_DECREF(v); /* namingAuth.iD */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL\", v);\n    Py_DECREF(v); /* namingAuth.uRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT\", v);\n    Py_DECREF(v); /* namingAuth.text */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM\", v);\n    Py_DECREF(v); /* professionItem */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID\", v);\n    Py_DECREF(v); /* professionOID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER\", v);\n    Py_DECREF(v); /* registrationNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_MONETARYLIMIT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_MONETARYLIMIT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY\", v);\n    Py_DECREF(v); /* currency */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT\", v);\n    Py_DECREF(v); /* amount */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT\", v);\n    Py_DECREF(v); /* exponent */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY\", v);\n    Py_DECREF(v); /* fullAgeAtCountry */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_RESTRICTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_RESTRICTION\", v);\n    Py_DECREF(v); /* 1 3 36 8 3 13 siggCertHash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_CERTHASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_CERTHASH\", v);\n    Py_DECREF(v); /* 1 3 36 8 3 15 siggAdditionalInformation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION\", v);\n    Py_DECREF(v); /* 1 3 101 1 4 1 strongExtranet */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_STRONGEXTRANET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_STRONGEXTRANET\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_STRONGEXTRANET_ZONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_STRONGEXTRANET_ZONE\", v);\n    Py_DECREF(v); /* sxNetIDList.sxNetID.zone */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_STRONGEXTRANET_ID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_STRONGEXTRANET_ID\", v);\n    Py_DECREF(v); /* sxNetIDList.sxNetID.id */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTDIR_TYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTDIR_TYPE\", v);\n    Py_DECREF(v); /* attribute.type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTDIR_VALUES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTDIR_VALUES\", v);\n    Py_DECREF(v); /* attribute.values */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER\", v);\n    Py_DECREF(v); /* 2 5 29 15 keyUsage */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_KEYUSAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_KEYUSAGE\", v);\n    Py_DECREF(v); /* 2 5 29 16 privateKeyUsagePeriod */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE\", v);\n    Py_DECREF(v); /* notBefore */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER\", v);\n    Py_DECREF(v); /* notAfter */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTALTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTALTNAME\", v);\n    Py_DECREF(v); /* 2 5 29 18 issuerAltName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUERALTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUERALTNAME\", v);\n    Py_DECREF(v); /* 2 5 29 19 basicConstraints */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BASICCONSTRAINTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BASICCONSTRAINTS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CA\", v);\n    Py_DECREF(v); /* cA */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PATHLENCONSTRAINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PATHLENCONSTRAINT\", v);\n    Py_DECREF(v); /* pathLenConstraint */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLNUMBER\", v);\n    Py_DECREF(v); /* 2 5 29 21 cRLReason */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLREASON);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLREASON\", v);\n    Py_DECREF(v); /* 2 5 29 23 holdInstructionCode */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_HOLDINSTRUCTIONCODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_HOLDINSTRUCTIONCODE\", v);\n    Py_DECREF(v); /* 2 5 29 24 invalidityDate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_INVALIDITYDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_INVALIDITYDATE\", v);\n    Py_DECREF(v); /* 2 5 29 27 deltaCRLIndicator */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DELTACRLINDICATOR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DELTACRLINDICATOR\", v);\n    Py_DECREF(v); /* 2 5 29 28 issuingDistributionPoint */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDIST_FULLNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDIST_FULLNAME\", v);\n    Py_DECREF(v); /* distributionPointName.fullName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY\", v);\n    Py_DECREF(v); /* onlyContainsUserCerts */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY\", v);\n    Py_DECREF(v); /* onlyContainsCACerts */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY\", v);\n    Py_DECREF(v); /* onlySomeReasons */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL\", v);\n    Py_DECREF(v); /* indirectCRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTIFICATEISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTIFICATEISSUER\", v);\n    Py_DECREF(v); /* 2 5 29 30 nameConstraints */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NAMECONSTRAINTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NAMECONSTRAINTS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_PERMITTEDSUBTREES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_PERMITTEDSUBTREES\", v);\n    Py_DECREF(v); /* permittedSubtrees */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXCLUDEDSUBTREES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXCLUDEDSUBTREES\", v);\n    Py_DECREF(v); /* excludedSubtrees */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLDIST_FULLNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLDIST_FULLNAME\", v);\n    Py_DECREF(v); /* distributionPointName.fullName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLDIST_REASONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLDIST_REASONS\", v);\n    Py_DECREF(v); /* reasons */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLDIST_CRLISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLDIST_CRLISSUER\", v);\n    Py_DECREF(v); /* cRLIssuer */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTIFICATEPOLICIES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTIFICATEPOLICIES\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTPOLICYID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTPOLICYID\", v);\n    Py_DECREF(v); /* policyInformation.policyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTPOLICY_CPSURI);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTPOLICY_CPSURI\", v);\n    Py_DECREF(v); /* policyInformation.policyQualifiers.qualifier.cPSuri */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION\", v);\n    Py_DECREF(v); /* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS\", v);\n    Py_DECREF(v); /* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT\", v);\n    Py_DECREF(v); /* policyInformation.policyQualifiers.qualifier.userNotice.explicitText */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_POLICYMAPPINGS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_POLICYMAPPINGS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ISSUERDOMAINPOLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ISSUERDOMAINPOLICY\", v);\n    Py_DECREF(v); /* policyMappings.issuerDomainPolicy */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SUBJECTDOMAINPOLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SUBJECTDOMAINPOLICY\", v);\n    Py_DECREF(v); /* policyMappings.subjectDomainPolicy */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER\", v);\n    Py_DECREF(v); /* keyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITY_CERTISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITY_CERTISSUER\", v);\n    Py_DECREF(v); /* authorityCertIssuer */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER\", v);\n    Py_DECREF(v); /* authorityCertSerialNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_POLICYCONSTRAINTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_POLICYCONSTRAINTS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REQUIREEXPLICITPOLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REQUIREEXPLICITPOLICY\", v);\n    Py_DECREF(v); /* policyConstraints.requireExplicitPolicy */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_INHIBITPOLICYMAPPING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_INHIBITPOLICYMAPPING\", v);\n    Py_DECREF(v); /* policyConstraints.inhibitPolicyMapping */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEYUSAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEYUSAGE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING\", v);\n    Py_DECREF(v); /* individualCodeSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING\", v);\n    Py_DECREF(v); /* commercialCodeSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING\", v);\n    Py_DECREF(v); /* certTrustListSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING\", v);\n    Py_DECREF(v); /* timeStampSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO\", v);\n    Py_DECREF(v); /* serverGatedCrypto */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM\", v);\n    Py_DECREF(v); /* encrypedFileSystem */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_SERVERAUTH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_SERVERAUTH\", v);\n    Py_DECREF(v); /* serverAuth */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_CLIENTAUTH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_CLIENTAUTH\", v);\n    Py_DECREF(v); /* clientAuth */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_CODESIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_CODESIGNING\", v);\n    Py_DECREF(v); /* codeSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION\", v);\n    Py_DECREF(v); /* emailProtection */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM\", v);\n    Py_DECREF(v); /* ipsecEndSystem */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL\", v);\n    Py_DECREF(v); /* ipsecTunnel */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_IPSECUSER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_IPSECUSER\", v);\n    Py_DECREF(v); /* ipsecUser */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_TIMESTAMPING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_TIMESTAMPING\", v);\n    Py_DECREF(v); /* timeStamping */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_OCSPSIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_OCSPSIGNING\", v);\n    Py_DECREF(v); /* ocspSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE\", v);\n    Py_DECREF(v); /* directoryService */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE\", v);\n    Py_DECREF(v); /* anyExtendedKeyUsage */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO\", v);\n    Py_DECREF(v); /* serverGatedCrypto */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA\", v);\n    Py_DECREF(v); /* serverGatedCrypto CA */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXTKEYUSAGE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXTKEYUSAGE_LAST\", v);\n    Py_DECREF(v); /* 2 5 29 40 crlStreamIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CRLSTREAMIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CRLSTREAMIDENTIFIER\", v);\n    Py_DECREF(v); /* 2 5 29 46 freshestCRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FRESHESTCRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FRESHESTCRL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FRESHESTCRL_FULLNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FRESHESTCRL_FULLNAME\", v);\n    Py_DECREF(v); /* distributionPointName.fullName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FRESHESTCRL_REASONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FRESHESTCRL_REASONS\", v);\n    Py_DECREF(v); /* reasons */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER\", v);\n    Py_DECREF(v); /* cRLIssuer */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_ORDEREDLIST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_ORDEREDLIST\", v);\n    Py_DECREF(v); /* 2 5 29 51 baseUpdateTime */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_BASEUPDATETIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_BASEUPDATETIME\", v);\n    Py_DECREF(v); /* 2 5 29 53 deltaInfo */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DELTAINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DELTAINFO\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DELTAINFO_LOCATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DELTAINFO_LOCATION\", v);\n    Py_DECREF(v); /* deltaLocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_DELTAINFO_NEXTDELTA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_DELTAINFO_NEXTDELTA\", v);\n    Py_DECREF(v); /* nextDelta */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_INHIBITANYPOLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_INHIBITANYPOLICY\", v);\n    Py_DECREF(v); /* 2 5 29 58 toBeRevoked */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TOBEREVOKED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TOBEREVOKED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER\", v);\n    Py_DECREF(v); /* certificateIssuer */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TOBEREVOKED_REASONCODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TOBEREVOKED_REASONCODE\", v);\n    Py_DECREF(v); /* reasonCode */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME\", v);\n    Py_DECREF(v); /* revocationTime */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER\", v);\n    Py_DECREF(v); /* certSerialNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER\", v);\n    Py_DECREF(v); /* certificateIssuer */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE\", v);\n    Py_DECREF(v); /* reasonCode */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE\", v);\n    Py_DECREF(v); /* invalidityDate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER\", v);\n    Py_DECREF(v); /* startingNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER\", v);\n    Py_DECREF(v); /* endingNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_EXPIREDCERTSONCRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_EXPIREDCERTSONCRL\", v);\n    Py_DECREF(v); /* 2 5 29 63 aaIssuingDistributionPoint */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME\", v);\n    Py_DECREF(v); /* distributionPointName.fullName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY\", v);\n    Py_DECREF(v); /* onlySomeReasons */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL\", v);\n    Py_DECREF(v); /* indirectCRL */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS\", v);\n    Py_DECREF(v); /* containsUserAttributeCerts */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_AACERTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_AACERTS\", v);\n    Py_DECREF(v); /* containsAACerts */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS\", v);\n    Py_DECREF(v); /* containsSOAPublicKeyCerts */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_CERTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_CERTTYPE\", v);\n    Py_DECREF(v); /* netscape-cert-type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_BASEURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_BASEURL\", v);\n    Py_DECREF(v); /* netscape-base-url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_REVOCATIONURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_REVOCATIONURL\", v);\n    Py_DECREF(v); /* netscape-revocation-url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_CAREVOCATIONURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_CAREVOCATIONURL\", v);\n    Py_DECREF(v); /* netscape-ca-revocation-url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_CERTRENEWALURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_CERTRENEWALURL\", v);\n    Py_DECREF(v); /* netscape-cert-renewal-url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_CAPOLICYURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_CAPOLICYURL\", v);\n    Py_DECREF(v); /* netscape-ca-policy-url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_SSLSERVERNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_SSLSERVERNAME\", v);\n    Py_DECREF(v); /* netscape-ssl-server-name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_NS_COMMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_NS_COMMENT\", v);\n    Py_DECREF(v); /* netscape-comment */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_HASHEDROOTKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_HASHEDROOTKEY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT\", v);\n    Py_DECREF(v); /* rootKeyThumbPrint */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_CERTIFICATETYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_CERTIFICATETYPE\", v);\n    Py_DECREF(v); /* 2 23 42 7 2 SET merchantData */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERID\", v);\n    Py_DECREF(v); /* merID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERACQUIRERBIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERACQUIRERBIN\", v);\n    Py_DECREF(v); /* merAcquirerBIN */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTLANGUAGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTLANGUAGE\", v);\n    Py_DECREF(v); /* merNames.language */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTNAME\", v);\n    Py_DECREF(v); /* merNames.name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTCITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTCITY\", v);\n    Py_DECREF(v); /* merNames.city */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE\", v);\n    Py_DECREF(v); /* merNames.stateProvince */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE\", v);\n    Py_DECREF(v); /* merNames.postalCode */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME\", v);\n    Py_DECREF(v); /* merNames.countryName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERCOUNTRY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERCOUNTRY\", v);\n    Py_DECREF(v); /* merCountry */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_MERAUTHFLAG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_MERAUTHFLAG\", v);\n    Py_DECREF(v); /* merAuthFlag */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_CERTCARDREQUIRED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_CERTCARDREQUIRED\", v);\n    Py_DECREF(v); /* 2 23 42 7 4 SET tunneling */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELING\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELLING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELLING\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELINGFLAG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELINGFLAG\", v);\n    Py_DECREF(v); /* tunneling */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELLINGFLAG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELLINGFLAG\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELINGALGID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELINGALGID\", v);\n    Py_DECREF(v); /* tunnelingAlgID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SET_TUNNELLINGALGID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SET_TUNNELLINGALGID\", v);\n    Py_DECREF(v); /* S/MIME attributes */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_CONTENTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_CONTENTTYPE\", v);\n    Py_DECREF(v); /* 1 2 840 113549 1 9 4 messageDigest */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MESSAGEDIGEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MESSAGEDIGEST\", v);\n    Py_DECREF(v); /* 1 2 840 113549 1 9 5 signingTime */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGTIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGTIME\", v);\n    Py_DECREF(v); /* 1 2 840 113549 1 9 6 counterSignature */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_COUNTERSIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_COUNTERSIGNATURE\", v);\n    Py_DECREF(v); /* counterSignature */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION\", v);\n    Py_DECREF(v); /* 1 2 840 113549 1 9 15 sMIMECapabilities */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAPABILITIES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAPABILITIES\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_3DES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_3DES\", v);\n    Py_DECREF(v); /* 3DES encryption */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_AES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_AES\", v);\n    Py_DECREF(v); /* AES encryption */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_CAST128);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_CAST128\", v);\n    Py_DECREF(v); /* CAST-128 encryption */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_SHAng\", v);\n    Py_DECREF(v); /* SHA2-ng hash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_SHA2\", v);\n    Py_DECREF(v); /* SHA2-256 hash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_SHA1\", v);\n    Py_DECREF(v); /* SHA1 hash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng\", v);\n    Py_DECREF(v); /* HMAC-SHA2-ng MAC */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2\", v);\n    Py_DECREF(v); /* HMAC-SHA2-256 MAC */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1\", v);\n    Py_DECREF(v); /* HMAC-SHA1 MAC */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256\", v);\n    Py_DECREF(v); /* AuthEnc w.256-bit key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128\", v);\n    Py_DECREF(v); /* AuthEnc w.128-bit key */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng\", v);\n    Py_DECREF(v); /* RSA with SHA-ng signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2\", v);\n    Py_DECREF(v); /* RSA with SHA2-256 signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1\", v);\n    Py_DECREF(v); /* RSA with SHA1 signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1\", v);\n    Py_DECREF(v); /* DSA with SHA-1 signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng\", v);\n    Py_DECREF(v); /* ECDSA with SHA-ng signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2\", v);\n    Py_DECREF(v); /* ECDSA with SHA2-256 signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1\", v);\n    Py_DECREF(v); /* ECDSA with SHA-1 signing */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA\", v);\n    Py_DECREF(v); /* preferSignedData */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY\", v);\n    Py_DECREF(v); /* canNotDecryptAny */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE\", v);\n    Py_DECREF(v); /* preferBinaryInside */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_RECEIPTREQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_RECEIPTREQUEST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER\", v);\n    Py_DECREF(v); /* contentIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_RECEIPT_FROM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_RECEIPT_FROM\", v);\n    Py_DECREF(v); /* receiptsFrom */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_RECEIPT_TO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_RECEIPT_TO\", v);\n    Py_DECREF(v); /* receiptsTo */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECURITYLABEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECURITYLABEL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECLABEL_POLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECLABEL_POLICY\", v);\n    Py_DECREF(v); /* securityPolicyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION\", v);\n    Py_DECREF(v); /* securityClassification */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK\", v);\n    Py_DECREF(v); /* privacyMark */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE\", v);\n    Py_DECREF(v); /* securityCategories.securityCategory.type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE\", v);\n    Py_DECREF(v); /* securityCategories.securityCategory.value */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER\", v);\n    Py_DECREF(v); /* mlData.mailListIdentifier.issuerAndSerialNumber */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXP_TIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXP_TIME\", v);\n    Py_DECREF(v); /* mlData.expansionTime */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXP_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXP_NONE\", v);\n    Py_DECREF(v); /* mlData.mlReceiptPolicy.none */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF\", v);\n    Py_DECREF(v); /* mlData.mlReceiptPolicy.insteadOf.generalNames.generalName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO\", v);\n    Py_DECREF(v); /* mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_CONTENTHINTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_CONTENTHINTS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION\", v);\n    Py_DECREF(v); /* contentDescription */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE\", v);\n    Py_DECREF(v); /* contentType */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQUIVALENTLABEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQUIVALENTLABEL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQVLABEL_POLICY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQVLABEL_POLICY\", v);\n    Py_DECREF(v); /* securityPolicyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION\", v);\n    Py_DECREF(v); /* securityClassification */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK\", v);\n    Py_DECREF(v); /* privacyMark */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE\", v);\n    Py_DECREF(v); /* securityCategories.securityCategory.type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE\", v);\n    Py_DECREF(v); /* securityCategories.securityCategory.value */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID\", v);\n    Py_DECREF(v); /* certs.essCertID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES\", v);\n    Py_DECREF(v); /* policies.policyInformation.policyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2\", v);\n    Py_DECREF(v); /* certs.essCertID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES\", v);\n    Py_DECREF(v); /* policies.policyInformation.policyIdentifier */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICYID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICYID\", v);\n    Py_DECREF(v); /* sigPolicyID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICYHASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICYHASH\", v);\n    Py_DECREF(v); /* sigPolicyHash */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI\", v);\n    Py_DECREF(v); /* sigPolicyQualifiers.sigPolicyQualifier.cPSuri */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION\", v);\n    Py_DECREF(v); /* sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS\", v);\n    Py_DECREF(v); /* sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT\", v);\n    Py_DECREF(v); /* sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG\", v);\n    Py_DECREF(v); /* originatorSig */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG\", v);\n    Py_DECREF(v); /* domainSig */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES\", v);\n    Py_DECREF(v); /* additionalAttributesSig */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG\", v);\n    Py_DECREF(v); /* reviewSig */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_NONCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_NONCE\", v);\n    Py_DECREF(v); /* randomNonce */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_MESSAGETYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_MESSAGETYPE\", v);\n    Py_DECREF(v); /* messageType */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_PKISTATUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_PKISTATUS\", v);\n    Py_DECREF(v); /* pkiStatus */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_FAILINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_FAILINFO\", v);\n    Py_DECREF(v); /* failInfo */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_SENDERNONCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_SENDERNONCE\", v);\n    Py_DECREF(v); /* senderNonce */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_RECIPIENTNONCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_RECIPIENTNONCE\", v);\n    Py_DECREF(v); /* recipientNonce */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_SCEP_TRANSACTIONID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_SCEP_TRANSACTIONID\", v);\n    Py_DECREF(v); /* transID */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCAGENCYINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCAGENCYINFO\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCAGENCYURL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCAGENCYURL\", v);\n    Py_DECREF(v); /* spcAgencyInfo.url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING\", v);\n    Py_DECREF(v); /* individualCodeSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING\", v);\n    Py_DECREF(v); /* commercialCodeSigning */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCOPUSINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCOPUSINFO\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME\", v);\n    Py_DECREF(v); /* spcOpusInfo.name */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL\", v);\n    Py_DECREF(v); /* spcOpusInfo.url */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYINFO_FIRST\", v);\n    Py_DECREF(v); /* ******************* */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYINFO_QUERY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYINFO_QUERY\", v);\n    Py_DECREF(v); /* Keyset query */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYINFO_QUERY_REQUESTS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYINFO_QUERY_REQUESTS\", v);\n    Py_DECREF(v); /* Query of requests in cert store */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_FIRST\", v);\n    Py_DECREF(v); /* ******************* */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_INITIALISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_INITIALISE\", v);\n    Py_DECREF(v); /* Initialise device for use */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_INITIALIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_INITIALIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_AUTHENT_USER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_AUTHENT_USER\", v);\n    Py_DECREF(v); /* Authenticate user to device */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_AUTHENT_SUPERVISOR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_AUTHENT_SUPERVISOR\", v);\n    Py_DECREF(v); /* Authenticate supervisor to dev. */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_SET_AUTHENT_USER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_SET_AUTHENT_USER\", v);\n    Py_DECREF(v); /* Set user authent.value */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR\", v);\n    Py_DECREF(v); /* Set supervisor auth.val. */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_ZEROISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_ZEROISE\", v);\n    Py_DECREF(v); /* Zeroise device */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_ZEROIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_ZEROIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_LOGGEDIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_LOGGEDIN\", v);\n    Py_DECREF(v); /* Whether user is logged in */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_LABEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_LABEL\", v);\n    Py_DECREF(v); /* Device/token label */\n\n    v = Py_BuildValue(\"i\", CRYPT_DEVINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_DEVINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_FIRST\", v);\n    Py_DECREF(v); /* ********************* */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_DATASIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_DATASIZE\", v);\n    Py_DECREF(v); /* Data size information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_COMPRESSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_COMPRESSION\", v);\n    Py_DECREF(v); /* Compression information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_CONTENTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_CONTENTTYPE\", v);\n    Py_DECREF(v); /* Inner CMS content type */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_DETACHEDSIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_DETACHEDSIGNATURE\", v);\n    Py_DECREF(v); /* Detached signature */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_SIGNATURE_RESULT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_SIGNATURE_RESULT\", v);\n    Py_DECREF(v); /* Signature check result */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_INTEGRITY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_INTEGRITY\", v);\n    Py_DECREF(v); /* Integrity-protection level */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_PASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_PASSWORD\", v);\n    Py_DECREF(v); /* User password */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_KEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_KEY\", v);\n    Py_DECREF(v); /* Conventional encryption key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_SIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_SIGNATURE\", v);\n    Py_DECREF(v); /* Signature/signature check key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_SIGNATURE_EXTRADATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_SIGNATURE_EXTRADATA\", v);\n    Py_DECREF(v); /* Extra information added to CMS sigs */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_RECIPIENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_RECIPIENT\", v);\n    Py_DECREF(v); /* Recipient email address */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_PUBLICKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_PUBLICKEY\", v);\n    Py_DECREF(v); /* PKC encryption key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_PRIVATEKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_PRIVATEKEY\", v);\n    Py_DECREF(v); /* PKC decryption key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_PRIVATEKEY_LABEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_PRIVATEKEY_LABEL\", v);\n    Py_DECREF(v); /* Label of PKC decryption key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_ORIGINATOR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_ORIGINATOR\", v);\n    Py_DECREF(v); /* Originator info/key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_SESSIONKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_SESSIONKEY\", v);\n    Py_DECREF(v); /* Session key */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_HASH);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_HASH\", v);\n    Py_DECREF(v); /* Hash value */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_TIMESTAMP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_TIMESTAMP\", v);\n    Py_DECREF(v); /* Timestamp information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_KEYSET_SIGCHECK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_KEYSET_SIGCHECK\", v);\n    Py_DECREF(v); /* Signature check keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_KEYSET_ENCRYPT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_KEYSET_ENCRYPT\", v);\n    Py_DECREF(v); /* PKC encryption keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_KEYSET_DECRYPT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_KEYSET_DECRYPT\", v);\n    Py_DECREF(v); /* PKC decryption keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_FIRST\", v);\n    Py_DECREF(v); /* ******************** */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_ACTIVE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_ACTIVE\", v);\n    Py_DECREF(v); /* Whether session is active */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CONNECTIONACTIVE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CONNECTIONACTIVE\", v);\n    Py_DECREF(v); /* Whether network connection is active */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_USERNAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_USERNAME\", v);\n    Py_DECREF(v); /* User name */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_PASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_PASSWORD\", v);\n    Py_DECREF(v); /* Password */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_PRIVATEKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_PRIVATEKEY\", v);\n    Py_DECREF(v); /* Server/client private key */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_KEYSET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_KEYSET\", v);\n    Py_DECREF(v); /* Certificate store */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_AUTHRESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_AUTHRESPONSE\", v);\n    Py_DECREF(v); /* Session authorisation OK */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SERVER_NAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SERVER_NAME\", v);\n    Py_DECREF(v); /* Server name */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SERVER_PORT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SERVER_PORT\", v);\n    Py_DECREF(v); /* Server port number */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1\", v);\n    Py_DECREF(v); /* Server key fingerprint */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CLIENT_NAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CLIENT_NAME\", v);\n    Py_DECREF(v); /* Client name */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CLIENT_PORT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CLIENT_PORT\", v);\n    Py_DECREF(v); /* Client port number */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SESSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SESSION\", v);\n    Py_DECREF(v); /* Transport mechanism */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_NETWORKSOCKET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_NETWORKSOCKET\", v);\n    Py_DECREF(v); /* User-supplied network socket */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_VERSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_VERSION\", v);\n    Py_DECREF(v); /* Protocol version */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_REQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_REQUEST\", v);\n    Py_DECREF(v); /* Cert.request object */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_RESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_RESPONSE\", v);\n    Py_DECREF(v); /* Cert.response object */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CACERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CACERTIFICATE\", v);\n    Py_DECREF(v); /* Issuing CA certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CMP_REQUESTTYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CMP_REQUESTTYPE\", v);\n    Py_DECREF(v); /* Request type */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_CMP_PRIVKEYSET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_CMP_PRIVKEYSET\", v);\n    Py_DECREF(v); /* Private-key keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSH_CHANNEL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSH_CHANNEL\", v);\n    Py_DECREF(v); /* SSH current channel */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSH_CHANNEL_TYPE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSH_CHANNEL_TYPE\", v);\n    Py_DECREF(v); /* SSH channel type */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSH_CHANNEL_ARG1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSH_CHANNEL_ARG1\", v);\n    Py_DECREF(v); /* SSH channel argument 1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSH_CHANNEL_ARG2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSH_CHANNEL_ARG2\", v);\n    Py_DECREF(v); /* SSH channel argument 2 */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE\", v);\n    Py_DECREF(v); /* SSH channel active */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSL_OPTIONS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSL_OPTIONS\", v);\n    Py_DECREF(v); /* SSL/TLS protocol options */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSL_SUBPROTOCOL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSL_SUBPROTOCOL\", v);\n    Py_DECREF(v); /* SSL/TLS additional sub-protocol */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSL_WSPROTOCOL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSL_WSPROTOCOL\", v);\n    Py_DECREF(v); /* SSL/TLS WebSockets sub-protocol */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSL_EAPCHALLENGE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSL_EAPCHALLENGE\", v);\n    Py_DECREF(v); /* SSL/TLS EAP challenge */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_SSL_EAPKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_SSL_EAPKEY\", v);\n    Py_DECREF(v); /* SSL/TLS EAP key */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_TSP_MSGIMPRINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_TSP_MSGIMPRINT\", v);\n    Py_DECREF(v); /* TSP message imprint */\n\n    v = Py_BuildValue(\"i\", CRYPT_SESSINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SESSINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_FIRST\", v);\n    Py_DECREF(v); /* ******************** */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_PASSWORD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_PASSWORD\", v);\n    Py_DECREF(v); /* Password */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_CAKEY_CERTSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_CAKEY_CERTSIGN\", v);\n    Py_DECREF(v); /* CA cert signing key */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_CAKEY_CRLSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_CAKEY_CRLSIGN\", v);\n    Py_DECREF(v); /* CA CRL signing key */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_CAKEY_RTCSSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_CAKEY_RTCSSIGN\", v);\n    Py_DECREF(v); /* CA RTCS signing key */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_CAKEY_OCSPSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_CAKEY_OCSPSIGN\", v);\n    Py_DECREF(v); /* CA OCSP signing key */\n\n    v = Py_BuildValue(\"i\", CRYPT_USERINFO_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USERINFO_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ATTRIBUTE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ATTRIBUTE_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_OBLIVIOUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_OBLIVIOUS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_REDUCED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_REDUCED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_STANDARD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_STANDARD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_PKIX_FULL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_PKIX_FULL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_COMPLIANCELEVEL_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_COMPLIANCELEVEL_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_NONE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_DATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_DATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_SIGNEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_SIGNEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_ENVELOPEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_ENVELOPEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_DIGESTEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_DIGESTEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_ENCRYPTEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_ENCRYPTEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_COMPRESSEDDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_COMPRESSEDDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_AUTHDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_AUTHDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_AUTHENVDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_AUTHENVDATA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_TSTINFO);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_TSTINFO\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_SPCINDIRECTDATACONTEXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_SPCINDIRECTDATACONTEXT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_RTCSREQUEST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_RTCSREQUEST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_RTCSRESPONSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_RTCSRESPONSE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_RTCSRESPONSE_EXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_RTCSRESPONSE_EXT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_MRTD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_MRTD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CONTENT_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CONTENT_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_NONE\", v);\n    Py_DECREF(v); /* No certificate status */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_VALID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_VALID\", v);\n    Py_DECREF(v); /* Certificate valid */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_NOTVALID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_NOTVALID\", v);\n    Py_DECREF(v); /* Certificate isn't valid */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_NONAUTHORITATIVE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_NONAUTHORITATIVE\", v);\n    Py_DECREF(v); /* Response is non-authoritative */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_UNKNOWN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_UNKNOWN\", v);\n    Py_DECREF(v); /* Certificate status unknown */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTSTATUS_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTSTATUS_LAST\", v);\n    Py_DECREF(v); /* Last possible certificate status */\n\n    v = Py_BuildValue(\"i\", CRYPT_SIGNATURELEVEL_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SIGNATURELEVEL_NONE\", v);\n    Py_DECREF(v); /* Include only signature */\n\n    v = Py_BuildValue(\"i\", CRYPT_SIGNATURELEVEL_SIGNERCERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SIGNATURELEVEL_SIGNERCERT\", v);\n    Py_DECREF(v); /* Include signer cert */\n\n    v = Py_BuildValue(\"i\", CRYPT_SIGNATURELEVEL_ALL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SIGNATURELEVEL_ALL\", v);\n    Py_DECREF(v); /* Include all relevant info */\n\n    v = Py_BuildValue(\"i\", CRYPT_SIGNATURELEVEL_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SIGNATURELEVEL_LAST\", v);\n    Py_DECREF(v); /* Last possible sig.level type */\n\n    v = Py_BuildValue(\"i\", CRYPT_INTEGRITY_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_INTEGRITY_NONE\", v);\n    Py_DECREF(v); /* No integrity protection */\n\n    v = Py_BuildValue(\"i\", CRYPT_INTEGRITY_MACONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_INTEGRITY_MACONLY\", v);\n    Py_DECREF(v); /* MAC only, no encryption */\n\n    v = Py_BuildValue(\"i\", CRYPT_INTEGRITY_FULL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_INTEGRITY_FULL\", v);\n    Py_DECREF(v); /* Encryption + ingerity protection */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_NONE\", v);\n    Py_DECREF(v); /* No certificate format */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_CERTIFICATE\", v);\n    Py_DECREF(v); /* DER-encoded certificate */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_CERTCHAIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_CERTCHAIN\", v);\n    Py_DECREF(v); /* PKCS #7 certificate chain */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_TEXT_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_TEXT_CERTIFICATE\", v);\n    Py_DECREF(v); /* base-64 wrapped cert */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_TEXT_CERTCHAIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_TEXT_CERTCHAIN\", v);\n    Py_DECREF(v); /* base-64 wrapped cert chain */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_XML_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_XML_CERTIFICATE\", v);\n    Py_DECREF(v); /* XML wrapped cert */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_XML_CERTCHAIN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_XML_CERTCHAIN\", v);\n    Py_DECREF(v); /* XML wrapped cert chain */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTFORMAT_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTFORMAT_LAST\", v);\n    Py_DECREF(v); /* Last possible cert.format type */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_NONE\", v);\n    Py_DECREF(v); /* No request type */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_INITIALISATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_INITIALISATION\", v);\n    Py_DECREF(v); /* Initialisation request */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_INITIALIZATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_INITIALIZATION\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_CERTIFICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_CERTIFICATE\", v);\n    Py_DECREF(v); /* Certification request */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_KEYUPDATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_KEYUPDATE\", v);\n    Py_DECREF(v); /* Key update request */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_REVOCATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_REVOCATION\", v);\n    Py_DECREF(v); /* Cert revocation request */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_PKIBOOT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_PKIBOOT\", v);\n    Py_DECREF(v); /* PKIBoot request */\n\n    v = Py_BuildValue(\"i\", CRYPT_REQUESTTYPE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_REQUESTTYPE_LAST\", v);\n    Py_DECREF(v); /* Last possible request type */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYID_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYID_NONE\", v);\n    Py_DECREF(v); /* No key ID type */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYID_NAME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYID_NAME\", v);\n    Py_DECREF(v); /* Key owner name */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYID_URI);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYID_URI\", v);\n    Py_DECREF(v); /* Key owner URI */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYID_EMAIL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYID_EMAIL\", v);\n    Py_DECREF(v); /* Synonym: owner email addr. */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYID_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYID_LAST\", v);\n    Py_DECREF(v); /* Last possible key ID type */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_NONE\", v);\n    Py_DECREF(v); /* No object type */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_ENCRYPTED_KEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_ENCRYPTED_KEY\", v);\n    Py_DECREF(v); /* Conventionally encrypted key */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_PKCENCRYPTED_KEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_PKCENCRYPTED_KEY\", v);\n    Py_DECREF(v); /* PKC-encrypted key */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_KEYAGREEMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_KEYAGREEMENT\", v);\n    Py_DECREF(v); /* Key agreement information */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_SIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_SIGNATURE\", v);\n    Py_DECREF(v); /* Signature */\n\n    v = Py_BuildValue(\"i\", CRYPT_OBJECT_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OBJECT_LAST\", v);\n    Py_DECREF(v); /* Last possible object type */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_NONE\", v);\n    Py_DECREF(v); /* No error information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_ATTR_SIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_ATTR_SIZE\", v);\n    Py_DECREF(v); /* Attribute data too small or large */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_ATTR_VALUE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_ATTR_VALUE\", v);\n    Py_DECREF(v); /* Attribute value is invalid */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_ATTR_ABSENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_ATTR_ABSENT\", v);\n    Py_DECREF(v); /* Required attribute missing */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_ATTR_PRESENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_ATTR_PRESENT\", v);\n    Py_DECREF(v); /* Non-allowed attribute present */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_CONSTRAINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_CONSTRAINT\", v);\n    Py_DECREF(v); /* Cert: Constraint violation in object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_ISSUERCONSTRAINT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_ISSUERCONSTRAINT\", v);\n    Py_DECREF(v); /* Cert: Constraint viol.in issuing cert */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERRTYPE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERRTYPE_LAST\", v);\n    Py_DECREF(v); /* Last possible error info type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_NONE\", v);\n    Py_DECREF(v); /* No cert management action */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CREATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CREATE\", v);\n    Py_DECREF(v); /* Create cert store */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CONNECT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CONNECT\", v);\n    Py_DECREF(v); /* Connect to cert store */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_DISCONNECT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_DISCONNECT\", v);\n    Py_DECREF(v); /* Disconnect from cert store */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_ERROR);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_ERROR\", v);\n    Py_DECREF(v); /* Error information */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_ADDUSER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_ADDUSER\", v);\n    Py_DECREF(v); /* Add PKI user */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_DELETEUSER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_DELETEUSER\", v);\n    Py_DECREF(v); /* Delete PKI user */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_REQUEST_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_REQUEST_CERT\", v);\n    Py_DECREF(v); /* Cert request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_REQUEST_RENEWAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_REQUEST_RENEWAL\", v);\n    Py_DECREF(v); /* Cert renewal request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_REQUEST_REVOCATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_REQUEST_REVOCATION\", v);\n    Py_DECREF(v); /* Cert revocation request */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CERT_CREATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CERT_CREATION\", v);\n    Py_DECREF(v); /* Cert creation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CERT_CREATION_COMPLETE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CERT_CREATION_COMPLETE\", v);\n    Py_DECREF(v); /* Confirmation of cert creation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CERT_CREATION_DROP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CERT_CREATION_DROP\", v);\n    Py_DECREF(v); /* Cancellation of cert creation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CERT_CREATION_REVERSE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CERT_CREATION_REVERSE\", v);\n    Py_DECREF(v); /* Cancel of creation w.revocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_RESTART_CLEANUP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_RESTART_CLEANUP\", v);\n    Py_DECREF(v); /* Delete reqs after restart */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_RESTART_REVOKE_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_RESTART_REVOKE_CERT\", v);\n    Py_DECREF(v); /* Complete revocation after restart */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_ISSUE_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_ISSUE_CERT\", v);\n    Py_DECREF(v); /* Cert issue */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_ISSUE_CRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_ISSUE_CRL\", v);\n    Py_DECREF(v); /* CRL issue */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_REVOKE_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_REVOKE_CERT\", v);\n    Py_DECREF(v); /* Cert revocation */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_EXPIRE_CERT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_EXPIRE_CERT\", v);\n    Py_DECREF(v); /* Cert expiry */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_CLEANUP);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_CLEANUP\", v);\n    Py_DECREF(v); /* Clean up on restart */\n\n    v = Py_BuildValue(\"i\", CRYPT_CERTACTION_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CERTACTION_LAST\", v);\n    Py_DECREF(v); /* Last possible cert store log action */\n\n    v = Py_BuildValue(\"i\", CRYPT_SUBPROTOCOL_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SUBPROTOCOL_NONE\", v);\n    Py_DECREF(v); /* No sub-protocol type */\n\n    v = Py_BuildValue(\"i\", CRYPT_SUBPROTOCOL_WEBSOCKETS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SUBPROTOCOL_WEBSOCKETS\", v);\n    Py_DECREF(v); /* Websockets */\n\n    v = Py_BuildValue(\"i\", CRYPT_SUBPROTOCOL_EAPTTLS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SUBPROTOCOL_EAPTTLS\", v);\n    Py_DECREF(v); /* EAP-TTLS */\n\n    v = Py_BuildValue(\"i\", CRYPT_SUBPROTOCOL_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SUBPROTOCOL_LAST\", v);\n    Py_DECREF(v); /* Last possible sub-protocol type */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYOPT_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYOPT_NONE\", v);\n    Py_DECREF(v); /* No options */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYOPT_READONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYOPT_READONLY\", v);\n    Py_DECREF(v); /* Open keyset in read-only mode */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYOPT_CREATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYOPT_CREATE\", v);\n    Py_DECREF(v); /* Create a new keyset */\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYOPT_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYOPT_LAST\", v);\n    Py_DECREF(v); /* Last possible key option type */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_NONE\", v);\n    Py_DECREF(v); /* No ECC curve type */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_P256);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_P256\", v);\n    Py_DECREF(v); /* NIST P256/X9.62 P256v1/SECG p256r1 curve */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_P384);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_P384\", v);\n    Py_DECREF(v); /* NIST P384, SECG p384r1 curve */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_P521);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_P521\", v);\n    Py_DECREF(v); /* NIST P521, SECG p521r1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_BRAINPOOL_P256);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_BRAINPOOL_P256\", v);\n    Py_DECREF(v); /* Brainpool p256r1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_BRAINPOOL_P384);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_BRAINPOOL_P384\", v);\n    Py_DECREF(v); /* Brainpool p384r1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_BRAINPOOL_P512);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_BRAINPOOL_P512\", v);\n    Py_DECREF(v); /* Brainpool p512r1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ECCCURVE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ECCCURVE_LAST\", v);\n    Py_DECREF(v); /* Last valid ECC curve type */\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_UNSPECIFIED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_UNSPECIFIED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_KEYCOMPROMISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_KEYCOMPROMISE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_CACOMPROMISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_CACOMPROMISE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_AFFILIATIONCHANGED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_AFFILIATIONCHANGED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_SUPERSEDED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_SUPERSEDED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_CESSATIONOFOPERATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_CESSATIONOFOPERATION\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_CERTIFICATEHOLD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_CERTIFICATEHOLD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_REMOVEFROMCRL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_REMOVEFROMCRL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_PRIVILEGEWITHDRAWN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_PRIVILEGEWITHDRAWN\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_AACOMPROMISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_AACOMPROMISE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_LAST\", v);\n    Py_DECREF(v); /* End of standard CRL reasons */\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASON_NEVERVALID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASON_NEVERVALID\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLEXTREASON_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLEXTREASON_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_HOLDINSTRUCTION_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_HOLDINSTRUCTION_NONE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_HOLDINSTRUCTION_CALLISSUER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_HOLDINSTRUCTION_CALLISSUER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_HOLDINSTRUCTION_REJECT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_HOLDINSTRUCTION_REJECT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_HOLDINSTRUCTION_PICKUPTOKEN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_HOLDINSTRUCTION_PICKUPTOKEN\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_HOLDINSTRUCTION_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_HOLDINSTRUCTION_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_UNMARKED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_UNMARKED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_UNCLASSIFIED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_UNCLASSIFIED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_RESTRICTED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_RESTRICTED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_CONFIDENTIAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_CONFIDENTIAL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_SECRET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_SECRET\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_TOP_SECRET);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_TOP_SECRET\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CLASSIFICATION_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CLASSIFICATION_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OCSPSTATUS_NOTREVOKED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OCSPSTATUS_NOTREVOKED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OCSPSTATUS_REVOKED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OCSPSTATUS_REVOKED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OCSPSTATUS_UNKNOWN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OCSPSTATUS_UNKNOWN\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_NONE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_DIGITALSIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_DIGITALSIGNATURE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_NONREPUDIATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_NONREPUDIATION\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_KEYENCIPHERMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_KEYENCIPHERMENT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_DATAENCIPHERMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_DATAENCIPHERMENT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_KEYAGREEMENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_KEYAGREEMENT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_KEYCERTSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_KEYCERTSIGN\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_CRLSIGN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_CRLSIGN\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_ENCIPHERONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_ENCIPHERONLY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_DECIPHERONLY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_DECIPHERONLY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYUSAGE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYUSAGE_LAST\", v);\n    Py_DECREF(v); /* Last possible value */\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_UNUSED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_UNUSED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_KEYCOMPROMISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_KEYCOMPROMISE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_CACOMPROMISE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_CACOMPROMISE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_SUPERSEDED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_SUPERSEDED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_CERTIFICATEHOLD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_CERTIFICATEHOLD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CRLREASONFLAG_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CRLREASONFLAG_LAST\", v);\n    Py_DECREF(v); /* Last poss.value */\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_SSLCLIENT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_SSLCLIENT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_SSLSERVER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_SSLSERVER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_SMIME);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_SMIME\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_OBJECTSIGNING);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_OBJECTSIGNING\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_RESERVED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_RESERVED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_SSLCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_SSLCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_SMIMECA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_SMIMECA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_NS_CERTTYPE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_NS_CERTTYPE_LAST\", v);\n    Py_DECREF(v); /* Last possible value */\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_CARD);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_CARD\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_MER);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_MER\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_PGWY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_PGWY\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_CCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_CCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_MCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_MCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_PCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_PCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_GCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_GCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_BCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_BCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_RCA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_RCA\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_ACQ);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_ACQ\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SET_CERTTYPE_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SET_CERTTYPE_LAST\", v);\n    Py_DECREF(v); /* Last possible value */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_NONE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_NONE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MINVER_SSLV3);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MINVER_SSLV3\", v);\n    Py_DECREF(v); /* Min.protocol version */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MINVER_TLS10);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MINVER_TLS10\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MINVER_TLS11);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MINVER_TLS11\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MINVER_TLS12);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MINVER_TLS12\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MINVER_TLS13);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MINVER_TLS13\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_MANUAL_CERTCHECK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_MANUAL_CERTCHECK\", v);\n    Py_DECREF(v); /* Require manual cert.verif. */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_DISABLE_NAMEVERIFY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_DISABLE_NAMEVERIFY\", v);\n    Py_DECREF(v); /* Disable cert hostname check */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_DISABLE_CERTVERIFY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_DISABLE_CERTVERIFY\", v);\n    Py_DECREF(v); /* Disable certificate check */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_SUITEB_128);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_SUITEB_128\", v);\n    Py_DECREF(v); /* SuiteB security levels (may */\n\n    v = Py_BuildValue(\"i\", CRYPT_SSLOPTION_SUITEB_256);\n    PyDict_SetItemString(moduleDict, \"CRYPT_SSLOPTION_SUITEB_256\", v);\n    Py_DECREF(v); /* vanish in future releases) */\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_KEYSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_KEYSIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_IVSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_IVSIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_PKCSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_PKCSIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_PKCSIZE_ECC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_PKCSIZE_ECC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_HASHSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_HASHSIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_MAX_TEXTSIZE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_MAX_TEXTSIZE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYTYPE_PRIVATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYTYPE_PRIVATE\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_KEYTYPE_PUBLIC);\n    PyDict_SetItemString(moduleDict, \"CRYPT_KEYTYPE_PUBLIC\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_OK);\n    PyDict_SetItemString(moduleDict, \"CRYPT_OK\", v);\n    Py_DECREF(v); /* No error */\n\n    v = Py_BuildValue(\"i\", CRYPT_USE_DEFAULT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_USE_DEFAULT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_UNUSED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_UNUSED\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CURSOR_FIRST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CURSOR_FIRST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CURSOR_PREVIOUS);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CURSOR_PREVIOUS\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CURSOR_NEXT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CURSOR_NEXT\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_CURSOR_LAST);\n    PyDict_SetItemString(moduleDict, \"CRYPT_CURSOR_LAST\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_RANDOM_FASTPOLL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_RANDOM_FASTPOLL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_RANDOM_SLOWPOLL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_RANDOM_SLOWPOLL\", v);\n    Py_DECREF(v);\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM1);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM1\", v);\n    Py_DECREF(v); /* Bad argument, parameter 1 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM2);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM2\", v);\n    Py_DECREF(v); /* Bad argument, parameter 2 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM3);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM3\", v);\n    Py_DECREF(v); /* Bad argument, parameter 3 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM4);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM4\", v);\n    Py_DECREF(v); /* Bad argument, parameter 4 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM5);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM5\", v);\n    Py_DECREF(v); /* Bad argument, parameter 5 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM6);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM6\", v);\n    Py_DECREF(v); /* Bad argument, parameter 6 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PARAM7);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PARAM7\", v);\n    Py_DECREF(v); /* Bad argument, parameter 7 */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_MEMORY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_MEMORY\", v);\n    Py_DECREF(v); /* Out of memory */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_NOTINITED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_NOTINITED\", v);\n    Py_DECREF(v); /* Data has not been initialised */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_INITED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_INITED\", v);\n    Py_DECREF(v); /* Data has already been init'd */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_NOSECURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_NOSECURE\", v);\n    Py_DECREF(v); /* Opn.not avail.at requested sec.level */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_RANDOM);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_RANDOM\", v);\n    Py_DECREF(v); /* No reliable random data available */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_FAILED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_FAILED\", v);\n    Py_DECREF(v); /* Operation failed */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_INTERNAL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_INTERNAL\", v);\n    Py_DECREF(v); /* Internal consistency check failed */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_NOTAVAIL);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_NOTAVAIL\", v);\n    Py_DECREF(v); /* This type of opn.not available */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_PERMISSION);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_PERMISSION\", v);\n    Py_DECREF(v); /* No permiss.to perform this operation */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_WRONGKEY);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_WRONGKEY\", v);\n    Py_DECREF(v); /* Incorrect key used to decrypt data */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_INCOMPLETE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_INCOMPLETE\", v);\n    Py_DECREF(v); /* Operation incomplete/still in progress */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_COMPLETE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_COMPLETE\", v);\n    Py_DECREF(v); /* Operation complete/can't continue */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_TIMEOUT);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_TIMEOUT\", v);\n    Py_DECREF(v); /* Operation timed out before completion */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_INVALID);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_INVALID\", v);\n    Py_DECREF(v); /* Invalid/inconsistent information */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_SIGNALLED);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_SIGNALLED\", v);\n    Py_DECREF(v); /* Resource destroyed by extnl.event */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_OVERFLOW);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_OVERFLOW\", v);\n    Py_DECREF(v); /* Resources/space exhausted */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_UNDERFLOW);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_UNDERFLOW\", v);\n    Py_DECREF(v); /* Not enough data available */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_BADDATA);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_BADDATA\", v);\n    Py_DECREF(v); /* Bad/unrecognised data format */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_SIGNATURE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_SIGNATURE\", v);\n    Py_DECREF(v); /* Signature/integrity check failed */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_OPEN);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_OPEN\", v);\n    Py_DECREF(v); /* Cannot open object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_READ);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_READ\", v);\n    Py_DECREF(v); /* Cannot read item from object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_WRITE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_WRITE\", v);\n    Py_DECREF(v); /* Cannot write item to object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_NOTFOUND);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_NOTFOUND\", v);\n    Py_DECREF(v); /* Requested item not found in object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ERROR_DUPLICATE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ERROR_DUPLICATE\", v);\n    Py_DECREF(v); /* Item already present in object */\n\n    v = Py_BuildValue(\"i\", CRYPT_ENVELOPE_RESOURCE);\n    PyDict_SetItemString(moduleDict, \"CRYPT_ENVELOPE_RESOURCE\", v);\n    Py_DECREF(v); /* Need resource to proceed */\n\n#if PY_MAJOR_VERSION >= 3\n    return module;\n#endif\n}"
  },
  {
    "path": "deps/cl345/bindings/setup.py",
    "content": "#!/usr/bin/env python\n\nfrom distutils.core import setup, Extension\nimport sys\n\nif sys.platform == \"win32\":\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['../binaries'],\n                    libraries=['cl32'])\nelse:\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['..'],\n                    libraries=['cl'])\n\nsetup(name=\"cryptlib_py\", ext_modules=[ext])\n"
  },
  {
    "path": "deps/cl345/bindings/testlib.jcl",
    "content": "//TESTLIB  JOB CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID\n//*\n//S1       EXEC PGM=TESTLIB,\n// PARM='ENVAR(_EDC_ADD_ERRNO2=1)/'\n//STEPLIB  DD DISP=SHR,DSN=#HLQ.CRYPTLIB.LOAD\n//*\n//CLBCMP   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBCMP\n//CLBDER   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBDER\n//CLBGPG   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBGPG\n//CLBPGP   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBPGP\n//CLBPKR   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBPKR\n//CLBP12   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBP12\n//CLBP15   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBP15\n//CLBP7S   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBP7S\n//CLBSKR   DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBSKR\n//CLBTEST  DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBTEST\n//CLBTESTA DD DISP=SHR,DSN=#HLQ.CRYPTLIB.CLBTESTA\n//*\n//CEEDUMP  DD SYSOUT=*\n//SYSPRINT DD SYSOUT=*\n//SYSOUT   DD SYSOUT=*\n//SYSIN    DD DUMMY\n"
  },
  {
    "path": "deps/cl345/bindings/ussalloc",
    "content": "#!/bin/sh\n\n#-----------------------------------------------------------------------\n# Cryptlib for MVS\n#\n# Developed on OS/390 2.10.\n#\n# Allocate MVS data sets for the test files used by 'testlib'.\n#-----------------------------------------------------------------------\n\n# The volume and unit on which to allocate the test data sets.\nVOLUME=\"UNIT(3390) VOL(STG001)\"\n\n# The data set types or low-level qualifiers for the test data sets.\nPOTYPES=\"CLBP15 CLBP12 CLBDER CLBPGP CLBGPG CLBPKR CLBSKR CLBP7S CLBCMP\"\nPSTYPES=\"CLBTEST CLBTESTA\"\n\n# The middle-level qualifier of the test data sets.\nMLQ=CRYPTLIB\n\nfor i in $POTYPES; do\n    tso \"DEL $MLQ.$i\"\ndone\n\nfor i in $PSTYPES; do\n    tso \"DEL $MLQ.$i\"\ndone\n\nfor i in $POTYPES; do\n\n    tso \"ALLOC DA($MLQ.$i) NEW CATALOG RECFM(V B) LRECL(256) \\\n         BLKSIZE(27998) DSORG(PO) CYL SPACE(1,10) DIR(20) $VOLUME\"\n    if [ $? -ne 0 ]; then\n        exit 1;\n    fi\n\ndone\n\nfor i in $PSTYPES; do\n\n    tso \"ALLOC DA($MLQ.$i) NEW CATALOG RECFM(V B) LRECL(256) \\\n         BLKSIZE(27998) DSORG(PS) CYL SPACE(1,10) $VOLUME\"\n    if [ $? -ne 0 ]; then\n        exit 1;\n    fi\n\ndone\n"
  },
  {
    "path": "deps/cl345/bindings/usscopy",
    "content": "#!/bin/sh\n\n#-----------------------------------------------------------------------\n# Cryptlib for MVS\n#\n# Developed on OS/390 2.10.\n#\n# Copy files from subdirectories under the 'test' directory to the MVS\n# data sets allocated with ussalloc.  This must be executed from the\n# 'test' directory.\n#-----------------------------------------------------------------------\n\n# The file extensions to copy from the subdirectories.\nBINEXTS=\"p15 p12 der pgp gpg pkr skr p7s\"\n\n# The subdirectories for the test filenames.\nDIRS=\"certs keys misc pgp smime\"\n\n# The middle-level qualifier of the test data sets.\nMLQ=CRYPTLIB\n\nfor d in $DIRS; do\n  cd $d\n  for i in $BINEXTS; do\n    if `ls *.$i > /dev/null 2>&1` ; then\n      for j in `ls *.$i` ; do\n        mbr=`echo $j | awk -F '.' '{print $1}' | tr -d '_'`\n        cp -BA $j \"//$MLQ.CLB$i($mbr)\"\n      done\n    fi\n  done\n  cd ..\ndone\n\ncp -BA test.h \"//$MLQ.CLBCMP\"\n"
  },
  {
    "path": "deps/cl345/bn/bn.h",
    "content": "/* cryptlib uses some of the mid-level OpenSSL bignum routines, but nothing \n   at either a low or high level.  Because of this it needs an equivalent to\n   OpenSSL's bn.h, which this file provides.  The original bn.h is moved to\n   bn_orig.h to ensure that the OpenSSL copyright isn't impacted, and is \n   included here by reference */\n\n#ifndef _BN_DEFINED\n\n#define _BN_DEFINED\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n#else\n  #include \"crypt/osconfig.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBignum Constants and Flags\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The allocation size for the fixed-size bignum data, sized to contain the \n   largest possible bignum in normal use, see the various comments \n   pertaining to bignum _EXT use for more on this.  Worst-case we need to \n   use a base alloc.size of 1024, however by careful use of _EXT bignums only\n   where needed we can use only 512 (= CRYPT_MAX_PKCSIZE).\n   \n\tFor BIGNUM_BASE_ALLOCSIZE = 1024, BIGNUM_ALLOC_WORDS = 260 32-bit words,\n\t\t\t\t\t\t\t\t\t  BIGNUM_ALLOC_BITS = 8320.\n\tFor BIGNUM_BASE_ALLOCSIZE = 512,  BIGNUM_ALLOC_WORDS = 130 32-bit words,\n\t\t\t\t\t\t\t\t\t  BIGNUM_ALLOC_BITS = 4115 */\n\n#if defined( CONFIG_PKC_ALLOCSIZE )\n  #define BIGNUM_BASE_ALLOCSIZE\t\tCONFIG_PKC_ALLOCSIZE\n#else\n  #define BIGNUM_BASE_ALLOCSIZE\t\t512\n  #if defined( CRYPT_MAX_PKCSIZE ) && CRYPT_MAX_PKCSIZE != BIGNUM_BASE_ALLOCSIZE\n\t#error CRYPT_MAX_PKCSIZE doesnt match BIGNUM_BASE_ALLOCSIZE\n  #endif /* CRYPT_MAX_PKCSIZE != 512 */\n#endif /* CONFIG_PKC_ALLOCSIZE */\n#define BIGNUM_ALLOC_WORDS\t\t\t( ( BIGNUM_BASE_ALLOCSIZE / BN_BYTES ) + 4 )\n#define bnWordsToBytes( bnWords )\t( ( bnWords ) * BN_BYTES )\n#define bnWordsToBits( bnWords )\t( ( bnWords ) * BN_BITS2 )\n\n/* Some of the temporary bignums used in multiplies grow to enormous sizes \n   (see the comment for BN_CTX), to avoid having to make every other bignum \n   as huge we provide a few special-case entries, BIGNUM_EXTs, that are \n   twice/four times the normal size */\n\n#define BIGNUM_ALLOC_WORDS_EXT\t( BIGNUM_ALLOC_WORDS * 2 )\n#define BIGNUM_ALLOC_WORDS_EXT2\t( BIGNUM_ALLOC_WORDS * 4 )\n\n/* Symbolic defines for the extended-size bignum that we want to use */\n\ntypedef enum { \n\tBIGNUM_EXT_NONE, \n\t\n\t/* Double-size bignums */\n\tBIGNUM_EXT_MONT, \n\n\t/* Quad-size bignums */\n\tBIGNUM_EXT_MUL1, \n\tBIGNUM_EXT_MUL2, \n\n\tBIGNUM_EXT_LAST \n\t} BIGNUM_EXT_TYPE;\n\n/* Bignum flags.  BN_FLG_SCRATCH is set for bignums that aren't actually used\n   as bignums but merely as scratch storage for data in the 'd' array, which\n   would fail a sanity check as standard bignums */\n\n#define BN_FLG_NONE\t\t\t0x00\t/* No bignum flag */\n#define BN_FLG_MALLOCED\t\t0x01\t/* Bignum is dynamically allocated */\n#define BN_FLG_STATIC_DATA\t0x02\t/* Bignum is in read-only memory */\n#define BN_FLG_CONSTTIME\t0x04\t/* Bignum ops use const-time algorithms */\n#define BN_FLG_SCRATCH\t\t0x08\t/* 'd' array used purely as scratch storage */\n#define BN_FLG_ALLOC_EXT\t0x10\t/* Bignum size BIGNUM_EXT_MUL1 */\n#define BN_FLG_ALLOC_EXT2\t0x20\t/* Bignum size BIGNUM_EXT_MUL2 */\n#define BN_FLG_MAX\t\t\t0x3F\t/* Maximum possible flag value */\n\n/* When copying a bignum, we don't copy most of the flags since they're \n   specific to the underlying bignum when they're things like \n   BN_FLG_MALLOCED, BN_FLG_STATIC_DATA, BN_FLG_ALLOC_EXT and \n   BN_FLG_ALLOC_EXT2, however there are a few flags that need to be \n   propagated, defined by the following mask value */\n\n#define BN_FLG_COPY_MASK\t( BN_FLG_CONSTTIME )\n\n/* Bignum data types and sizes.  These are, as with all things OpenSSL, \n   rather confusing and hard to sort out, with the code doing things in pure \n   assembly language, with inline asm assist, or in pure C.  In addition due \n   to the use of various levels of assembly language there are also \n   different options that control which word size to use depending on what \n   the asm expects, for example whether there are 64 op 64 -> 64 or 64 op 64 \n   -> 128 instructions available. \n\n   So the original OpenSSL code is a complex balancing act where BN_LLONG \n   might be used in some cases (for 32 op 32 -> 64) and native asm or asm \n   assist for pure 32-bit or maybe asm 32 op 32 -> 64.  In particular where \n   the asm requires a particular word size or where the best available \n   option isn't to use the biggest word size, somewhat counterintuitive \n   options are enabled, so Sparc64 uses BN_LLONG and 32 op 32 -> 64 because \n   32 x 32 -> 64 multiplications are the best available even in 64-bit mode, \n   and even 64-bit additions are best done without SIXTY_FOUR_BIT because \n   there's no 64-bit-with-carry instruction.\n\n   In terms of the C-level macros, if possible the code uses BN_LLONG with \n   n op n -> 2n operations (but this is only possible for THIRTY_TWO_BIT \n   when long long is available, for SIXTY_FOUR_BIT you'd need a C-level 128-\n   bit data type).  If that isn't possible (i.e. for SIXTY_FOUR_BIT) it \n   falls back to secondary operations with macros like BN_UMULT_LOHI or \n   BN_UMULT_HIGH, which provide asm assist for n op n -> n or register-pair \n   2 * n operations.  Finally, if all else fails, it does it the hard way, \n   building up something like a mul64() from four mul32()s (see the code \n   towards the end of bn/bn_lcl.h for details).\n\n   No idea how the BN_BITS is supposed to work, it's only used in one \n   location in bn_gcd.c where it's used as if it indicates the machine word \n   size, technically it's OK for THIRTY_TWO_BIT because it assumes there's a \n   64-bit BN_ULLONG, but it's definitely wrong for the others.  We keep it \n   as is because the BN_BITSn defines and therefore the OpenSSL code all \n   depend on it */\n\n#ifdef _MSC_VER \n  #define LONGLONG_TYPE\t\t__int64\n#else\n  #define LONGLONG_TYPE\t\tlong long\n#endif /* Compiler-specific 64-bit type */\n\n/* LP64 architectures where long and long long are 64 bits, e.g. x86-64 \n   Unix, Alpha, PPC64, and Sparc64 */\n\n#ifdef SIXTY_FOUR_BIT_LONG\n  #define BN_ULLONG\t\t\tunsigned LONGLONG_TYPE\t/* 64 bits */\n  #define BN_ULONG\t\t\tunsigned long\t\t\t/* 64 bits */\n  #define BN_BITS\t\t\t128\n  #define BN_MASK2\t\t\t0xFFFFFFFFFFFFFFFFUL\n  #define BN_MASK2l\t\t\t0xFFFFFFFFUL\n  #define BN_MASK2h\t\t\t0xFFFFFFFF00000000UL\n#endif /* SIXTY_FOUR_BIT_LONG */\n\n/* LLP64 architectures where long long is 64 bits but long is 32 bits,\n   x86-64 Windows.  Since we already need long long just to get 64 bits,\n   we can't have BN_ULLONG (and its accompanying flag BN_LLONG).\n   \n   There is pseudo-support for an __int128 type in VC++ and gcc but it's \n   still too preliminary to rely on */\n\n#ifdef SIXTY_FOUR_BIT\n  #define BN_ULONG\t\t\tunsigned LONGLONG_TYPE\t/* 64 bits */\n  #define BN_BITS\t\t\t128\n  #define BN_MASK2\t\t\t0xFFFFFFFFFFFFFFFFULL\n  #define BN_MASK2l\t\t\t0xFFFFFFFFUL\n  #define BN_MASK2h\t\t\t0xFFFFFFFF00000000ULL\n#endif /* SIXTY_FOUR_BIT */\n\n/* 32-bit architectures */\n\n#ifdef THIRTY_TWO_BIT\n  #ifdef BN_LLONG\n\t#define BN_ULLONG\t\tunsigned LONGLONG_TYPE\t/* 64 bits */\n  #endif /* BN_LLONG */\n  #define BN_ULONG\t\t\tunsigned int\t\t\t/* 32 bits */\n  #define BN_BITS\t\t\t64\n  #define BN_MASK2\t\t\t0xFFFFFFFFUL\n  #define BN_MASK2l\t\t\t0xFFFFUL\n  #define BN_MASK2h\t\t\t0xFFFF0000UL\n#endif /* THIRTY_TWO_BIT */\n\n#define BN_BITS2\t\t\t( BN_BITS / 2 )\n#define BN_BITS4\t\t\t( BN_BITS / 4 )\n#define BN_BYTES\t\t\t( BN_BITS2 / 8 )\n\n/* Special-case NaN return value */\n\n#define BN_NAN\t\t\t\t( ( BN_ULONG ) BN_MASK2 )\n\n/* Use double-word divide if available */\n\n#if defined( _MSC_VER ) || defined( __GNUC__ ) || defined( __clang__ )\n  #define BN_DIV2W\n#endif /* Compilers that support double-word divide */\n\n/* Check that everything is set up as required */\n\n#if defined( SIXTY_FOUR_BIT_LONG )\n  #ifdef BN_LLONG\n\t#error BN_LLONG cant be defined for SIXTY_FOUR_BIT_LONG (LP64) systems\n  #endif /* BN_LLONG */\n#elif defined( SIXTY_FOUR_BIT )\n  #if defined( BN_LLONG ) || defined( BN_ULLONG )\n\t#error BN_LLONG or BN_ULLONG cant be defined for SIXTY_FOUR_BIT (LLP64) systems\n  #endif\n#elif defined( THIRTY_TWO_BIT )\n  /* No special conditions */\n#else\n  #error Neither SIXTY_FOUR_BIT_LONG, SIXTY_FOUR_BIT or THIRTY_TWO_BIT is defined for this architecture\n#endif /* Machine word sizes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tBignum Types\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Support functions to mask the OpenSSL memory-allocation mess.  bn_expand()\n   and bn_wexpand() are a particular pain because they're used in situations \n   like:\n\n\tif (bn_wexpand(snum, sdiv->top + 2) == NULL) ...\n\n   Since we don't dynamically reallocate bignums like crazy as OpenSSL does\n   but use fixed-size, big-enough values, the only check that we need to do\n   is a sanity check that there's enough room.  This requires a complex\n   expression that evaluates to NULL if there's insufficient space (a should-\n   never-occur condition) and something that isn't NULL if there's enough\n   space.\n\n   The whole thing is complicated by the fact that MQX, in line with its\n   braindamaged policy of redefining standard C types and values, also \n   redefines NULL (!!), so we need an MQX-specific version to avoid compiler\n   errors.  The weird-looking expression has been chosen to generate a\n   compile error (rather than breaking silently) if in the future MQX \n   decides to redefine NULL to something less insane */\n\n#if defined( WIN32 ) && !defined( NDEBUG ) && 0\n  #define USE_BN_DEBUG_MALLOC\n#endif /* Only enable in Win32 debug version */\n#ifdef USE_BN_DEBUG_MALLOC\n  #define clBnAlloc( string, size ) \\\n\t\t  clBnAllocFn( __FILE__, string, __LINE__, size )\n  void *clBnAllocFn( const char *fileName, const char *fnName,\n\t\t\t\t\t const int lineNo, size_t size );\n#else\n  #define clBnAlloc( string, size )\tmalloc( size )\n#endif /* !USE_BN_DEBUG_MALLOC */\n#define OPENSSL_free\t\t\t\tfree\n#define OPENSSL_cleanse( a, b )\t\tmemset( a, 0, b )\n\nextern int nonNullAddress;\n#if defined( __MQXRTOS__ ) && !defined( _MSC_VER )\n  #define bn_expand( bignum, bits ) \\\n\t\t  ( ( ( bits ) > BIGNUM_ALLOC_BITS ) ? assert( 0 ), NULL : NULL + 1 )\t/* See comment above */\n  #define bn_wexpand( bignum, words ) \\\n\t\t  ( ( ( words ) > getBNMaxSize( bignum ) ) ? assert( 0 ), NULL : NULL + 1 )\n#elif defined( NDEBUG )\n  #define bn_expand( bignum, bits ) \\\n\t\t  ( ( ( bits ) > BIGNUM_ALLOC_BITS ) ? NULL : ( void * ) &nonNullAddress )\n  #define bn_wexpand( bignum, words ) \\\n\t\t  ( ( ( words ) > getBNMaxSize( bignum ) ) ? NULL : ( void * ) &nonNullAddress )\n#elif defined( __xlc__ )\n  /* Some compilers have an assert() defined in such a way that it can't be \n     used as part of the expression in bn_(w)expand(), so we have to use the\n\t basic non-debug form */\n  #define bn_expand( bignum, bits ) \\\n\t\t  ( ( ( bits ) > BIGNUM_ALLOC_BITS ) ? NULL : ( void * ) &nonNullAddress )\n  #define bn_wexpand( bignum, words ) \\\n\t\t  ( ( ( words ) > getBNMaxSize( bignum ) ) ? NULL : ( void * ) &nonNullAddress )\n#else\n  #define bn_expand( bignum, bits ) \\\n\t\t  ( ( ( bits ) > BIGNUM_ALLOC_BITS ) ? assert( 0 ), NULL : ( void * ) &nonNullAddress )\n  #define bn_wexpand( bignum, words ) \\\n\t\t  ( ( ( words ) > getBNMaxSize( bignum ) ) ? assert( 0 ), NULL : ( void * ) &nonNullAddress )\n#endif /* Situation-specific override macros */\n\n/* Overrides of OpenSSL functions that are rendered unnecessary by our \n   versions */\n\n#define BN_clear_free\t\t\tBN_free\n#define BN_cmp\t\t\t\t\tBN_ucmp\n#define BN_is_zero( bignum )\t( !BN_cmp_word( bignum, 0 ) )\n#define BN_is_one( bignum )\t\t( !BN_cmp_word( bignum, 1 ) )\n#define BN_is_word( bignum, word ) ( !BN_cmp_word( bignum, word ) )\n#define BN_is_odd( bignum )\t\tBN_is_bit_set( bignum, 0 )\n#define BN_zero( bignum )\t\tBN_set_word( bignum, 0 )\n#define BN_one( bignum )\t\tBN_set_word( bignum, 1 )\n#define BN_num_bytes( bignum )\t( ( BN_num_bits( bignum ) + 7 ) / 8 )\n#define BN_lshift1( result, a )\tBN_lshift( result, a, 1 )\n#define BN_rshift1( result, a )\tBN_rshift( result, a, 1 )\n#define BN_mod( remainder, modulus, divisor, ctx ) \\\n\t\t\t\t\t\t\t\tBN_div( NULL, remainder, modulus, divisor, ctx )\n#define BN_mod_add( result, a, b, modulus, ctx ) \\\n\t\t\t\t\t\t\t\tBN_mod_add_quick( result, a, b, modulus )\n#define BN_mod_lshift1_quick( result, a, modulus ) \\\n\t\t\t\t\t\t\t\tBN_mod_lshift_quick( result, a, 1, modulus )\n#define BN_MONT_CTX_copy( destMontCTX, srcMontCTX ) \\\n\t\t\t\t\t\t\t\tmemcpy( destMontCTX, srcMontCTX, sizeof( BN_MONT_CTX ) )\n#define BN_set_flags( bignum, flagValue ) \\\n\t\t\t\t\t\t\t\t( ( bignum )->flags |= ( flagValue ) )\n#define BN_get_flags( bignum, flagValue ) \\\n\t\t\t\t\t\t\t\t( ( bignum )->flags & ( flagValue ) )\n#define BN_is_negative( bignum ) ( ( bignum )->neg )\n#define bn_fix_top\t\t\t\tBN_normalise\n#define bn_correct_top\t\t\tBN_normalise\n#define BNerr( a, b )\n#define bn_check_top( a )\n\n/* Get a copy of a bignum with different flags from the original, used for \n   constant-time ops in bn_gcd() to create a read-only copy of a bignum \n   that's processed using a constant-time algorithm.  This really shouldn't\n   be called BN_with_flags() but it's necessary for compatibility with the\n   OpenSSL original */\n\n#define BN_with_flags( dest, src, flagValue ) \\\n\t\tmemcpy( dest, src, sizeof( BIGNUM ) ); \\\n\t\t( dest )->flags = ( ( src )->flags & ~BN_FLG_MALLOCED ) | BN_FLG_STATIC_DATA | ( flagValue )\n\n/* Bignum structures.  The storage array d must be at the end since the \n   basic BIGNUM can be overlaid with the _EXT/_EXT2 forms where larger \n   data quantities are used */\n\ntypedef struct {\n\tint top;\t\t/* Last used word in d[] + 1 */\n\tint neg;\t\t/* Negative true/false */\n\tint flags;\t\t/* Flags */\n\tBN_ULONG d[ BIGNUM_ALLOC_WORDS + 4 ];\n\t} BIGNUM;\n\ntypedef struct {\n\tint top, neg, flags;\n\tBN_ULONG d[ BIGNUM_ALLOC_WORDS_EXT + 4 ];\n\t} BIGNUM_EXT;\n\ntypedef struct {\n\tint top, neg, flags;\n\tBN_ULONG d[ BIGNUM_ALLOC_WORDS_EXT2 + 4 ];\n\t} BIGNUM_EXT2;\n\n/* Montgomery modmult structure */\n\ntypedef struct {\n\tBIGNUM R;\t\t/* Used when converting to Montgomery form aR mod N */\n\tBIGNUM N;\t\t/* Modulus */\n\tBN_ULONG n0;\t/* Low word of some intermediate value from\n\t\t\t\t\t   BN_MONT_CTX_set() */\n\tint flags;\n\t} BN_MONT_CTX;\n\n/* Reciprocal devision/modmult structure */\n\ntypedef struct {\n\tBIGNUM N;\t\t/* Divisor */\n\tBIGNUM Nr;\t\t/* Reciprocal */\n\tint num_bits;\t/* Bits in divisor */\n\tint shift;\t\t/* Whether Nr has been set from N */\n\tint flags;\n\t} BN_RECP_CTX;\n\n/* The purpose, and much of the functioning, of the BN_CTX pool/stack/\n   whatever stuff is more or less incomprehensible, and in any case all \n   of the manipulations actually have a negative effect on memory use \n   because the bookkeeping overhead of dozens of tiny little allocations \n   is more than just allocating a fixed-size block of bignums, which is\n   what we do instead of using the OpenSSL forms */\n\n#define BN_CTX_ARRAY_SIZE\t\t40\n#define BN_CTX_EXTARRAY_SIZE\t1\n#define BN_CTX_EXT2ARRAY_SIZE\t2\n\ntypedef struct {\n\t/* The bignum array and last-used position in the array */\n\tBIGNUM bnArray[ BN_CTX_ARRAY_SIZE ];\n\tint bnArrayMax;\n\n\t/* Special-case bignums used to handle two temporary values in BN_mul()\n\t   that grow to an enormous size, and one temporary value in \n\t   BN_mod_mul_montgomery() that briefly reaches an enormous size */\n\tBIGNUM_EXT bnExtArray[ BN_CTX_EXTARRAY_SIZE ];\n\tBIGNUM_EXT2 bnExt2Array[ BN_CTX_EXT2ARRAY_SIZE ];\n\n\t/* The bignum stack and current position in the stack.  See the long\n\t   explanation in ctx_bn.c for what this is used for */\n\tint stack[ BN_CTX_ARRAY_SIZE ];\n\tint stackPos;\n\t} BN_CTX;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tBignum Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enable various build options */\n\n#define BN_MUL_COMBA\n#define BN_SQR_COMBA\n#define BN_RECURSION\n\n/* Bignum internal/helper functions */\n\nCHECK_RETVAL_LENGTH_SHORT_NOERROR STDC_NONNULL_ARG( ( 1 ) ) \\\nint getBNMaxSize( const BIGNUM *bignum );\n\n/* Bignum init/shutdown/copy/swap functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_clear( INOUT BIGNUM *bignum );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_init( OUT BIGNUM *bignum );\nCHECK_RETVAL_PTR \\\nBIGNUM *BN_new( void );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_free( INOUT BIGNUM *bignum );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_dup( const BIGNUM *bignum );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBIGNUM *BN_copy( INOUT BIGNUM *destBignum, const BIGNUM *srcBignum );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid BN_swap( INOUT BIGNUM *bignum1, INOUT BIGNUM *bignum2 );\nCHECK_RETVAL_PTR \\\nconst BIGNUM *BN_value_one( void );\n\n/* Bignum bit/word functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nBN_ULONG BN_get_word( const BIGNUM *bignum );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_set_word( INOUT BIGNUM *bignum, const BN_ULONG word );\nCHECK_RETVAL_LENGTH_SHORT \\\nint BN_num_bits_word( const BN_ULONG word );\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint BN_num_bits( const BIGNUM *bignum );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_set_bit( INOUT BIGNUM *bignum, \n\t\t\t\t\tIN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tint bitNo );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_is_bit_set( const BIGNUM *bignum, /* See comment */ int bitNo );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_high_bit( const BIGNUM *bignum );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_set_negative( INOUT BIGNUM *bignum, const int value );\nRETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_normalise( INOUT BIGNUM *bignum );\nRETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_clear_top( INOUT BIGNUM *bignum, \n\t\t\t\t\t  IN_RANGE( 0, BIGNUM_ALLOC_WORDS_EXT2 ) const int oldTop );\n\n/* Bignum context init/shutdown functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_init( OUT BN_CTX *bnCTX );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_start( INOUT BN_CTX *bnCTX );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_end( INOUT BN_CTX *bnCTX );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_final( INOUT BN_CTX *bnCTX );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_CTX_get( INOUT BN_CTX *bnCTX );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_CTX_get_ext( INOUT BN_CTX *bnCTX, \n\t\t\t\t\t\tIN_ENUM( BIGNUM_EXT ) const BIGNUM_EXT_TYPE bnExtType );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_end_ext( INOUT BN_CTX *bnCTX, \n\t\t\t\t\t IN_ENUM( BIGNUM_EXT ) const BIGNUM_EXT_TYPE bnExtType );\nCHECK_RETVAL_PTR \\\nBN_CTX *BN_CTX_new( void );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_free( INOUT BN_CTX *bnCTX );\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_RECP_CTX_init( OUT BN_RECP_CTX *bnRecpCTX );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_RECP_CTX_free( INOUT BN_RECP_CTX *bnRecpCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_RECP_CTX_set( INOUT BN_RECP_CTX *bnRecpCTX, const BIGNUM *d, \n\t\t\t\t\t\t STDC_UNUSED const BN_CTX *bnCTX );\n\n/* Bignum Montgomery init/shutdown functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_MONT_CTX_init( OUT BN_MONT_CTX *bnMontCTX );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_MONT_CTX_free( INOUT BN_MONT_CTX *bnMontCTX );\nCHECK_RETVAL_PTR \\\nBN_MONT_CTX *BN_MONT_CTX_new( void );\n\n/* Bignum maths functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_uadd( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_usub( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_add( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_sub( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_lshift( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t   IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tconst int shiftAmount );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_rshift( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t   IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tconst int shiftAmount );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_add_word( INOUT BIGNUM *a, const BN_ULONG w );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_sub_word( INOUT BIGNUM *a, const BN_ULONG w );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_mul_word( INOUT BIGNUM *a, const BN_ULONG w );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_mod_word( OUT BN_ULONG *r, const BIGNUM *a, const BN_ULONG w );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_sqr( INOUT BIGNUM *r, const BIGNUM *a, INOUT BN_CTX *bnCTX );\n\n/* Bignum division/modulus functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 3, 4, 5 ) ) \\\nBOOLEAN BN_div( INOUT_OPT BIGNUM *quotient, INOUT_OPT BIGNUM *remainder, \n\t\t\t\tconst BIGNUM *numerator, const BIGNUM *divisor,\n\t\t\t\tINOUT BN_CTX *bnCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_nnmod( INOUT BIGNUM *r, const BIGNUM *m, const BIGNUM *d, \n\t\t\t\t  INOUT BN_CTX *ctx );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_add_quick( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\t\t  const BIGNUM *m );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_sub_quick( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\t\t  const BIGNUM *m );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN BN_mod_mul( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\tconst BIGNUM *m, INOUT BN_CTX *ctx );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_sqr( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *m, \n\t\t\t\t\tINOUT BN_CTX *ctx );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nBOOLEAN BN_mod_lshift_quick( BIGNUM *r, const BIGNUM *a, \n\t\t\t\t\t\t\t IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\t\t\tconst int shiftAmount,\n\t\t\t\t\t\t\t const BIGNUM *m );\n\n/* Bignum Montgomery functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_MONT_CTX_set( INOUT BN_MONT_CTX *bnMontCTX, const BIGNUM *mod, \n\t\t\t\t\t\t INOUT BN_CTX *bnCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_to_montgomery( INOUT BIGNUM *ret, const BIGNUM *a,\n\t\t\t\t\t\t  const BN_MONT_CTX *bnMontCTX,\n\t\t\t\t\t\t  INOUT BN_CTX *bnCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN BN_mod_mul_montgomery( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t\t\t\t   const BIGNUM *b, const BN_MONT_CTX *bnMontCTX, \n\t\t\t\t\t\t\t   INOUT BN_CTX *bnCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_from_montgomery( INOUT BIGNUM *ret, INOUT BIGNUM *aTmp,\n\t\t\t\t\t\t\tconst BN_MONT_CTX *bnMontCTX,\n\t\t\t\t\t\t\tINOUT BN_CTX *bnCTX );\n\n/* Bignum compare functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint BN_cmp_word( const BIGNUM *bignum, const BN_ULONG word );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint bn_cmp_words( const BN_ULONG *bignumData1, const BN_ULONG *bignumData2, \n\t\t\t\t  IN_RANGE( 0, BIGNUM_ALLOC_WORDS ) const int length );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint BN_ucmp( const BIGNUM *bignum1, const BIGNUM *bignum2 );\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint BN_ucmp_words( const BN_ULONG *bignumData1, \n\t\t\t\t   IN_RANGE( 0, BIGNUM_ALLOC_WORDS ) const int bignum1Length, \n\t\t\t\t   const BIGNUM *bignum2 );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint bn_cmp_part_words( const BN_ULONG *a, const BN_ULONG *b, \n\t\t\t\t\t   IN_RANGE( 0, BIGNUM_ALLOC_WORDS_EXT ) const int cl, \n\t\t\t\t\t   IN_RANGE( -BIGNUM_ALLOC_WORDS_EXT, \\\n\t\t\t\t\t\t\t\t BIGNUM_ALLOC_WORDS_EXT ) const int dl );\n\n/* Bignum read/write functions */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nBIGNUM *BN_bin2bn( IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t   IN_LENGTH_PKC_Z const int length, \n\t\t\t\t   OUT BIGNUM *bignum );\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint BN_bn2bin( const BIGNUM *bignum, BYTE *buffer );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRemaining Original OpenSSL Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"bn_orig.h\"\n#else\n  #include \"bn/bn_orig.h\"\n#endif /* Compiler-specific includes */\n\n#endif /* _BN_DEFINED */\n"
  },
  {
    "path": "deps/cl345/bn/bn_asm.c",
    "content": "/* crypto/bn/bn_asm.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n/* Changes for cryptlib - pcg */\n\n#include <stdio.h>\n#include <assert.h>\n#if defined( _WIN32_WCE ) && _WIN32_WCE < 400\n  #define assert( x )\n#else\n  #include <assert.h>\n#endif /* Systems without assert() */\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( _MSC_VER )\n  /* cryptlib is built with the highest warning level, disable some of the\n     more irritating warnings produced by the OpenSSL code */\n  #pragma warning( disable: 4127 )\t/* Conditional is constant: while( TRUE ) */\n#endif /* Visual C++ */\n\n/* End changes for cryptlib - pcg */\n\n#ifndef BN_ASM\t\t\t\t/* pcg */\n\n#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)\n\nBN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,\n                          BN_ULONG w)\n{\n    BN_ULONG c1 = 0;\n\n    assert(num >= 0);\n    if (num <= 0)\n        return (c1);\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (num & ~3) {\n        mul_add(rp[0], ap[0], w, c1);\n        mul_add(rp[1], ap[1], w, c1);\n        mul_add(rp[2], ap[2], w, c1);\n        mul_add(rp[3], ap[3], w, c1);\n        ap += 4;\n        rp += 4;\n        num -= 4;\n    }\n# endif\n    while (num) {\n        mul_add(rp[0], ap[0], w, c1);\n        ap++;\n        rp++;\n        num--;\n    }\n\n    return (c1);\n}\n\nBN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)\n{\n    BN_ULONG c1 = 0;\n\n    assert(num >= 0);\n    if (num <= 0)\n        return (c1);\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (num & ~3) {\n        mul(rp[0], ap[0], w, c1);\n        mul(rp[1], ap[1], w, c1);\n        mul(rp[2], ap[2], w, c1);\n        mul(rp[3], ap[3], w, c1);\n        ap += 4;\n        rp += 4;\n        num -= 4;\n    }\n# endif\n    while (num) {\n        mul(rp[0], ap[0], w, c1);\n        ap++;\n        rp++;\n        num--;\n    }\n    return (c1);\n}\n\nvoid bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)\n{\n    assert(n >= 0);\n    if (n <= 0)\n        return;\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (n & ~3) {\n        sqr(r[0], r[1], a[0]);\n        sqr(r[2], r[3], a[1]);\n        sqr(r[4], r[5], a[2]);\n        sqr(r[6], r[7], a[3]);\n        a += 4;\n        r += 8;\n        n -= 4;\n    }\n# endif\n    while (n) {\n        sqr(r[0], r[1], a[0]);\n        a++;\n        r += 2;\n        n--;\n    }\n}\n\n#else                           /* !(defined(BN_LLONG) ||\n                                 * defined(BN_UMULT_HIGH)) */\n\nBN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,\n                          BN_ULONG w)\n{\n    BN_ULONG c = 0;\n    BN_ULONG bl, bh;\n\n    assert(num >= 0);\n    if (num <= 0)\n        return ((BN_ULONG)0);\n\n    bl = LBITS(w);\n    bh = HBITS(w);\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (num & ~3) {\n        mul_add(rp[0], ap[0], bl, bh, c);\n        mul_add(rp[1], ap[1], bl, bh, c);\n        mul_add(rp[2], ap[2], bl, bh, c);\n        mul_add(rp[3], ap[3], bl, bh, c);\n        ap += 4;\n        rp += 4;\n        num -= 4;\n    }\n# endif\n    while (num) {\n        mul_add(rp[0], ap[0], bl, bh, c);\n        ap++;\n        rp++;\n        num--;\n    }\n    return (c);\n}\n\nBN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)\n{\n    BN_ULONG carry = 0;\n    BN_ULONG bl, bh;\n\n    assert(num >= 0);\n    if (num <= 0)\n        return ((BN_ULONG)0);\n\n    bl = LBITS(w);\n    bh = HBITS(w);\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (num & ~3) {\n        mul(rp[0], ap[0], bl, bh, carry);\n        mul(rp[1], ap[1], bl, bh, carry);\n        mul(rp[2], ap[2], bl, bh, carry);\n        mul(rp[3], ap[3], bl, bh, carry);\n        ap += 4;\n        rp += 4;\n        num -= 4;\n    }\n# endif\n    while (num) {\n        mul(rp[0], ap[0], bl, bh, carry);\n        ap++;\n        rp++;\n        num--;\n    }\n    return (carry);\n}\n\nvoid bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)\n{\n    assert(n >= 0);\n    if (n <= 0)\n        return;\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (n & ~3) {\n        sqr64(r[0], r[1], a[0]);\n        sqr64(r[2], r[3], a[1]);\n        sqr64(r[4], r[5], a[2]);\n        sqr64(r[6], r[7], a[3]);\n        a += 4;\n        r += 8;\n        n -= 4;\n    }\n# endif\n    while (n) {\n        sqr64(r[0], r[1], a[0]);\n        a++;\n        r += 2;\n        n--;\n    }\n}\n\n#endif                          /* !(defined(BN_LLONG) ||\n                                 * defined(BN_UMULT_HIGH)) */\n\n#if defined(BN_LLONG) && defined(BN_DIV2W)\n\nBN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)\n{\n    return ((BN_ULONG)(((((BN_ULLONG) h) << BN_BITS2) | l) / (BN_ULLONG) d));\n}\n\n#else\n\n/* Divide h,l by d and return the result. */\n/* I need to test this some more :-( */\nBN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)\n{\n    BN_ULONG dh, dl, q, ret = 0, th, tl, t;\n    int i, count = 2;\n\n    if (d == 0)\n        return (BN_MASK2);\n\n    i = BN_num_bits_word(d);\n    assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));\n\n    i = BN_BITS2 - i;\n    if (h >= d)\n        h -= d;\n\n    if (i) {\n        d <<= i;\n        h = (h << i) | (l >> (BN_BITS2 - i));\n        l <<= i;\n    }\n    dh = (d & BN_MASK2h) >> BN_BITS4;\n    dl = (d & BN_MASK2l);\n    for (;;) {\n        if ((h >> BN_BITS4) == dh)\n            q = BN_MASK2l;\n        else\n            q = h / dh;\n\n        th = q * dh;\n        tl = dl * q;\n        for (;;) {\n            t = h - th;\n            if ((t & BN_MASK2h) ||\n                ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4))))\n                break;\n            q--;\n            th -= dh;\n            tl -= dl;\n        }\n        t = (tl >> BN_BITS4);\n        tl = (tl << BN_BITS4) & BN_MASK2h;\n        th += t;\n\n        if (l < tl)\n            th++;\n        l -= tl;\n        if (h < th) {\n            h += d;\n            q--;\n        }\n        h -= th;\n\n        if (--count == 0)\n            break;\n\n        ret = q << BN_BITS4;\n        h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;\n        l = (l & BN_MASK2l) << BN_BITS4;\n    }\n    ret |= q;\n    return (ret);\n}\n#endif                          /* !defined(BN_LLONG) && defined(BN_DIV2W) */\n\n#ifdef BN_LLONG\nBN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\n                      int n)\n{\n    BN_ULLONG ll = 0;\n\n    assert(n >= 0);\n    if (n <= 0)\n        return ((BN_ULONG)0);\n\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (n & ~3) {\n        ll += (BN_ULLONG) a[0] + b[0];\n      r[0] = (BN_ULONG)ll & BN_MASK2;\n\t\tll >>= BN_BITS2;\n        ll += (BN_ULLONG) a[1] + b[1];\n        r[1] = (BN_ULONG)ll & BN_MASK2;\n\t\tll >>= BN_BITS2;\n        ll += (BN_ULLONG) a[2] + b[2];\n        r[2] = (BN_ULONG)ll & BN_MASK2;\n\t\tll >>= BN_BITS2;\n        ll += (BN_ULLONG) a[3] + b[3];\n        r[3] = (BN_ULONG)ll & BN_MASK2;\n\t\tll >>= BN_BITS2;\n        a += 4;\n        b += 4;\n        r += 4;\n        n -= 4;\n    }\n# endif\n    while (n) {\n        ll += (BN_ULLONG) a[0] + b[0];\n        r[0] = (BN_ULONG)ll & BN_MASK2;\n\t\tll >>= BN_BITS2;\n        a++;\n        b++;\n        r++;\n        n--;\n    }\n    return ((BN_ULONG)ll);\n}\n#else                           /* !BN_LLONG */\nBN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\n                      int n)\n{\n    BN_ULONG c, l, t;\n\n    assert(n >= 0);\n    if (n <= 0)\n        return ((BN_ULONG)0);\n\n    c = 0;\n# ifndef OPENSSL_SMALL_FOOTPRINT\n    while (n & ~3) {\n        t = a[0];\n        t = (t + c) & BN_MASK2;\n        c = (t < c);\n        l = (t + b[0]) & BN_MASK2;\n        c += (l < t);\n        r[0] = l;\n        t = a[1];\n        t = (t + c) & BN_MASK2;\n        c = (t < c);\n        l = (t + b[1]) & BN_MASK2;\n        c += (l < t);\n        r[1] = l;\n        t = a[2];\n        t = (t + c) & BN_MASK2;\n        c = (t < c);\n        l = (t + b[2]) & BN_MASK2;\n        c += (l < t);\n        r[2] = l;\n        t = a[3];\n        t = (t + c) & BN_MASK2;\n        c = (t < c);\n        l = (t + b[3]) & BN_MASK2;\n        c += (l < t);\n        r[3] = l;\n        a += 4;\n        b += 4;\n        r += 4;\n        n -= 4;\n    }\n# endif\n    while (n) {\n        t = a[0];\n        t = (t + c) & BN_MASK2;\n        c = (t < c);\n        l = (t + b[0]) & BN_MASK2;\n        c += (l < t);\n        r[0] = l;\n        a++;\n        b++;\n        r++;\n        n--;\n    }\n    return ((BN_ULONG)c);\n}\n#endif                          /* !BN_LLONG */\n\nBN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\n                      int n)\n{\n    BN_ULONG t1, t2;\n    int c = 0;\n\n    assert(n >= 0);\n    if (n <= 0)\n        return ((BN_ULONG)0);\n\n#ifndef OPENSSL_SMALL_FOOTPRINT\n    while (n & ~3) {\n        t1 = a[0];\n        t2 = b[0];\n        r[0] = (t1 - t2 - c) & BN_MASK2;\n        if (t1 != t2)\n            c = (t1 < t2);\n        t1 = a[1];\n        t2 = b[1];\n        r[1] = (t1 - t2 - c) & BN_MASK2;\n        if (t1 != t2)\n            c = (t1 < t2);\n        t1 = a[2];\n        t2 = b[2];\n        r[2] = (t1 - t2 - c) & BN_MASK2;\n        if (t1 != t2)\n            c = (t1 < t2);\n        t1 = a[3];\n        t2 = b[3];\n        r[3] = (t1 - t2 - c) & BN_MASK2;\n        if (t1 != t2)\n            c = (t1 < t2);\n        a += 4;\n        b += 4;\n        r += 4;\n        n -= 4;\n    }\n#endif\n    while (n) {\n        t1 = a[0];\n        t2 = b[0];\n        r[0] = (t1 - t2 - c) & BN_MASK2;\n        if (t1 != t2)\n            c = (t1 < t2);\n        a++;\n        b++;\n        r++;\n        n--;\n    }\n    return (c);\n}\n\n#if defined(BN_MUL_COMBA) && !defined(OPENSSL_SMALL_FOOTPRINT)\n\n# undef bn_mul_comba8\n# undef bn_mul_comba4\n# undef bn_sqr_comba8\n# undef bn_sqr_comba4\n\n/* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */\n/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */\n/* sqr_add_c(a,i,c0,c1,c2)  -- c+=a[i]^2 for three word number c=(c2,c1,c0) */\n/*\n * sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number\n * c=(c2,c1,c0)\n */\n\n# ifdef BN_LLONG\n/*\n * Keep in mind that additions to multiplication result can not\n * overflow, because its high half cannot be all-ones.\n */\n#  define mul_add_c(a,b,c0,c1,c2)       do {    \\\n        BN_ULONG hi;                            \\\n        BN_ULLONG t = (BN_ULLONG)(a)*(b);       \\\n        t += c0;                /* no carry */  \\\n        c0 = (BN_ULONG)Lw(t);                   \\\n        hi = (BN_ULONG)Hw(t);                   \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define mul_add_c2(a,b,c0,c1,c2)      do {    \\\n        BN_ULONG hi;                            \\\n        BN_ULLONG t = (BN_ULLONG)(a)*(b);       \\\n        BN_ULLONG tt = t+c0;    /* no carry */  \\\n        c0 = (BN_ULONG)Lw(tt);                  \\\n        hi = (BN_ULONG)Hw(tt);                  \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        t += c0;                /* no carry */  \\\n        c0 = (BN_ULONG)Lw(t);                   \\\n        hi = (BN_ULONG)Hw(t);                   \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define sqr_add_c(a,i,c0,c1,c2)       do {    \\\n        BN_ULONG hi;                            \\\n        BN_ULLONG t = (BN_ULLONG)a[i]*a[i];     \\\n        t += c0;                /* no carry */  \\\n        c0 = (BN_ULONG)Lw(t);                   \\\n        hi = (BN_ULONG)Hw(t);                   \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define sqr_add_c2(a,i,j,c0,c1,c2) \\\n        mul_add_c2((a)[i],(a)[j],c0,c1,c2)\n\n# elif defined(BN_UMULT_LOHI)\n/*\n * Keep in mind that additions to hi can not overflow, because\n * the high word of a multiplication result cannot be all-ones.\n */\n#  define mul_add_c(a,b,c0,c1,c2)       do {    \\\n        BN_ULONG ta = (a), tb = (b);            \\\n        BN_ULONG lo, hi;                        \\\n        BN_UMULT_LOHI(lo,hi,ta,tb);             \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define mul_add_c2(a,b,c0,c1,c2)      do {    \\\n        BN_ULONG ta = (a), tb = (b);            \\\n        BN_ULONG lo, hi, tt;                    \\\n        BN_UMULT_LOHI(lo,hi,ta,tb);             \\\n        c0 += lo; tt = hi+((c0<lo)?1:0);        \\\n        c1 += tt; c2 += (c1<tt)?1:0;            \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define sqr_add_c(a,i,c0,c1,c2)       do {    \\\n        BN_ULONG ta = (a)[i];                   \\\n        BN_ULONG lo, hi;                        \\\n        BN_UMULT_LOHI(lo,hi,ta,ta);             \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define sqr_add_c2(a,i,j,c0,c1,c2)    \\\n        mul_add_c2((a)[i],(a)[j],c0,c1,c2)\n\n# elif defined(BN_UMULT_HIGH)\n/*\n * Keep in mind that additions to hi can not overflow, because\n * the high word of a multiplication result cannot be all-ones.\n */\n#  define mul_add_c(a,b,c0,c1,c2)       do {    \\\n        BN_ULONG ta = (a), tb = (b);            \\\n        BN_ULONG lo = ta * tb;                  \\\n        BN_ULONG hi = BN_UMULT_HIGH(ta,tb);     \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define mul_add_c2(a,b,c0,c1,c2)      do {    \\\n        BN_ULONG ta = (a), tb = (b), tt;        \\\n        BN_ULONG lo = ta * tb;                  \\\n        BN_ULONG hi = BN_UMULT_HIGH(ta,tb);     \\\n        c0 += lo; tt = hi + ((c0<lo)?1:0);      \\\n        c1 += tt; c2 += (c1<tt)?1:0;            \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define sqr_add_c(a,i,c0,c1,c2)       do {    \\\n        BN_ULONG ta = (a)[i];                   \\\n        BN_ULONG lo = ta * ta;                  \\\n        BN_ULONG hi = BN_UMULT_HIGH(ta,ta);     \\\n        c0 += lo; hi += (c0<lo)?1:0;            \\\n        c1 += hi; c2 += (c1<hi)?1:0;            \\\n        } while(0)\n\n#  define sqr_add_c2(a,i,j,c0,c1,c2)      \\\n        mul_add_c2((a)[i],(a)[j],c0,c1,c2)\n\n# else                          /* !BN_LLONG */\n/*\n * Keep in mind that additions to hi can not overflow, because\n * the high word of a multiplication result cannot be all-ones.\n */\n#  define mul_add_c(a,b,c0,c1,c2)       do {    \\\n        BN_ULONG lo = LBITS(a), hi = HBITS(a);  \\\n        BN_ULONG bl = LBITS(b), bh = HBITS(b);  \\\n        mul64(lo,hi,bl,bh);                     \\\n        c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define mul_add_c2(a,b,c0,c1,c2)      do {    \\\n        BN_ULONG tt;                            \\\n        BN_ULONG lo = LBITS(a), hi = HBITS(a);  \\\n        BN_ULONG bl = LBITS(b), bh = HBITS(b);  \\\n        mul64(lo,hi,bl,bh);                     \\\n        tt = hi;                                \\\n        c0 = (c0+lo)&BN_MASK2; if (c0<lo) tt++; \\\n        c1 = (c1+tt)&BN_MASK2; if (c1<tt) c2++; \\\n        c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define sqr_add_c(a,i,c0,c1,c2)       do {    \\\n        BN_ULONG lo, hi;                        \\\n        sqr64(lo,hi,(a)[i]);                    \\\n        c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \\\n        c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \\\n        } while(0)\n\n#  define sqr_add_c2(a,i,j,c0,c1,c2) \\\n        mul_add_c2((a)[i],(a)[j],c0,c1,c2)\n# endif                         /* !BN_LLONG */\n\nvoid bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)\t/* const - pcg */\n{\n    BN_ULONG c1, c2, c3;\n\n    c1 = 0;\n    c2 = 0;\n    c3 = 0;\n    mul_add_c(a[0], b[0], c1, c2, c3);\n    r[0] = c1;\n    c1 = 0;\n    mul_add_c(a[0], b[1], c2, c3, c1);\n    mul_add_c(a[1], b[0], c2, c3, c1);\n    r[1] = c2;\n    c2 = 0;\n    mul_add_c(a[2], b[0], c3, c1, c2);\n    mul_add_c(a[1], b[1], c3, c1, c2);\n    mul_add_c(a[0], b[2], c3, c1, c2);\n    r[2] = c3;\n    c3 = 0;\n    mul_add_c(a[0], b[3], c1, c2, c3);\n    mul_add_c(a[1], b[2], c1, c2, c3);\n    mul_add_c(a[2], b[1], c1, c2, c3);\n    mul_add_c(a[3], b[0], c1, c2, c3);\n    r[3] = c1;\n    c1 = 0;\n    mul_add_c(a[4], b[0], c2, c3, c1);\n    mul_add_c(a[3], b[1], c2, c3, c1);\n    mul_add_c(a[2], b[2], c2, c3, c1);\n    mul_add_c(a[1], b[3], c2, c3, c1);\n    mul_add_c(a[0], b[4], c2, c3, c1);\n    r[4] = c2;\n    c2 = 0;\n    mul_add_c(a[0], b[5], c3, c1, c2);\n    mul_add_c(a[1], b[4], c3, c1, c2);\n    mul_add_c(a[2], b[3], c3, c1, c2);\n    mul_add_c(a[3], b[2], c3, c1, c2);\n    mul_add_c(a[4], b[1], c3, c1, c2);\n    mul_add_c(a[5], b[0], c3, c1, c2);\n    r[5] = c3;\n    c3 = 0;\n    mul_add_c(a[6], b[0], c1, c2, c3);\n    mul_add_c(a[5], b[1], c1, c2, c3);\n    mul_add_c(a[4], b[2], c1, c2, c3);\n    mul_add_c(a[3], b[3], c1, c2, c3);\n    mul_add_c(a[2], b[4], c1, c2, c3);\n    mul_add_c(a[1], b[5], c1, c2, c3);\n    mul_add_c(a[0], b[6], c1, c2, c3);\n    r[6] = c1;\n    c1 = 0;\n    mul_add_c(a[0], b[7], c2, c3, c1);\n    mul_add_c(a[1], b[6], c2, c3, c1);\n    mul_add_c(a[2], b[5], c2, c3, c1);\n    mul_add_c(a[3], b[4], c2, c3, c1);\n    mul_add_c(a[4], b[3], c2, c3, c1);\n    mul_add_c(a[5], b[2], c2, c3, c1);\n    mul_add_c(a[6], b[1], c2, c3, c1);\n    mul_add_c(a[7], b[0], c2, c3, c1);\n    r[7] = c2;\n    c2 = 0;\n    mul_add_c(a[7], b[1], c3, c1, c2);\n    mul_add_c(a[6], b[2], c3, c1, c2);\n    mul_add_c(a[5], b[3], c3, c1, c2);\n    mul_add_c(a[4], b[4], c3, c1, c2);\n    mul_add_c(a[3], b[5], c3, c1, c2);\n    mul_add_c(a[2], b[6], c3, c1, c2);\n    mul_add_c(a[1], b[7], c3, c1, c2);\n    r[8] = c3;\n    c3 = 0;\n    mul_add_c(a[2], b[7], c1, c2, c3);\n    mul_add_c(a[3], b[6], c1, c2, c3);\n    mul_add_c(a[4], b[5], c1, c2, c3);\n    mul_add_c(a[5], b[4], c1, c2, c3);\n    mul_add_c(a[6], b[3], c1, c2, c3);\n    mul_add_c(a[7], b[2], c1, c2, c3);\n    r[9] = c1;\n    c1 = 0;\n    mul_add_c(a[7], b[3], c2, c3, c1);\n    mul_add_c(a[6], b[4], c2, c3, c1);\n    mul_add_c(a[5], b[5], c2, c3, c1);\n    mul_add_c(a[4], b[6], c2, c3, c1);\n    mul_add_c(a[3], b[7], c2, c3, c1);\n    r[10] = c2;\n    c2 = 0;\n    mul_add_c(a[4], b[7], c3, c1, c2);\n    mul_add_c(a[5], b[6], c3, c1, c2);\n    mul_add_c(a[6], b[5], c3, c1, c2);\n    mul_add_c(a[7], b[4], c3, c1, c2);\n    r[11] = c3;\n    c3 = 0;\n    mul_add_c(a[7], b[5], c1, c2, c3);\n    mul_add_c(a[6], b[6], c1, c2, c3);\n    mul_add_c(a[5], b[7], c1, c2, c3);\n    r[12] = c1;\n    c1 = 0;\n    mul_add_c(a[6], b[7], c2, c3, c1);\n    mul_add_c(a[7], b[6], c2, c3, c1);\n    r[13] = c2;\n    c2 = 0;\n    mul_add_c(a[7], b[7], c3, c1, c2);\n    r[14] = c3;\n    r[15] = c1;\n}\n\nvoid bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)\t/* const - pcg */\n{\n    BN_ULONG c1, c2, c3;\n\n    c1 = 0;\n    c2 = 0;\n    c3 = 0;\n    mul_add_c(a[0], b[0], c1, c2, c3);\n    r[0] = c1;\n    c1 = 0;\n    mul_add_c(a[0], b[1], c2, c3, c1);\n    mul_add_c(a[1], b[0], c2, c3, c1);\n    r[1] = c2;\n    c2 = 0;\n    mul_add_c(a[2], b[0], c3, c1, c2);\n    mul_add_c(a[1], b[1], c3, c1, c2);\n    mul_add_c(a[0], b[2], c3, c1, c2);\n    r[2] = c3;\n    c3 = 0;\n    mul_add_c(a[0], b[3], c1, c2, c3);\n    mul_add_c(a[1], b[2], c1, c2, c3);\n    mul_add_c(a[2], b[1], c1, c2, c3);\n    mul_add_c(a[3], b[0], c1, c2, c3);\n    r[3] = c1;\n    c1 = 0;\n    mul_add_c(a[3], b[1], c2, c3, c1);\n    mul_add_c(a[2], b[2], c2, c3, c1);\n    mul_add_c(a[1], b[3], c2, c3, c1);\n    r[4] = c2;\n    c2 = 0;\n    mul_add_c(a[2], b[3], c3, c1, c2);\n    mul_add_c(a[3], b[2], c3, c1, c2);\n    r[5] = c3;\n    c3 = 0;\n    mul_add_c(a[3], b[3], c1, c2, c3);\n    r[6] = c1;\n    r[7] = c2;\n}\n\nvoid bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)\n{\n    BN_ULONG c1, c2, c3;\n\n    c1 = 0;\n    c2 = 0;\n    c3 = 0;\n    sqr_add_c(a, 0, c1, c2, c3);\n    r[0] = c1;\n    c1 = 0;\n    sqr_add_c2(a, 1, 0, c2, c3, c1);\n    r[1] = c2;\n    c2 = 0;\n    sqr_add_c(a, 1, c3, c1, c2);\n    sqr_add_c2(a, 2, 0, c3, c1, c2);\n    r[2] = c3;\n    c3 = 0;\n    sqr_add_c2(a, 3, 0, c1, c2, c3);\n    sqr_add_c2(a, 2, 1, c1, c2, c3);\n    r[3] = c1;\n    c1 = 0;\n    sqr_add_c(a, 2, c2, c3, c1);\n    sqr_add_c2(a, 3, 1, c2, c3, c1);\n    sqr_add_c2(a, 4, 0, c2, c3, c1);\n    r[4] = c2;\n    c2 = 0;\n    sqr_add_c2(a, 5, 0, c3, c1, c2);\n    sqr_add_c2(a, 4, 1, c3, c1, c2);\n    sqr_add_c2(a, 3, 2, c3, c1, c2);\n    r[5] = c3;\n    c3 = 0;\n    sqr_add_c(a, 3, c1, c2, c3);\n    sqr_add_c2(a, 4, 2, c1, c2, c3);\n    sqr_add_c2(a, 5, 1, c1, c2, c3);\n    sqr_add_c2(a, 6, 0, c1, c2, c3);\n    r[6] = c1;\n    c1 = 0;\n    sqr_add_c2(a, 7, 0, c2, c3, c1);\n    sqr_add_c2(a, 6, 1, c2, c3, c1);\n    sqr_add_c2(a, 5, 2, c2, c3, c1);\n    sqr_add_c2(a, 4, 3, c2, c3, c1);\n    r[7] = c2;\n    c2 = 0;\n    sqr_add_c(a, 4, c3, c1, c2);\n    sqr_add_c2(a, 5, 3, c3, c1, c2);\n    sqr_add_c2(a, 6, 2, c3, c1, c2);\n    sqr_add_c2(a, 7, 1, c3, c1, c2);\n    r[8] = c3;\n    c3 = 0;\n    sqr_add_c2(a, 7, 2, c1, c2, c3);\n    sqr_add_c2(a, 6, 3, c1, c2, c3);\n    sqr_add_c2(a, 5, 4, c1, c2, c3);\n    r[9] = c1;\n    c1 = 0;\n    sqr_add_c(a, 5, c2, c3, c1);\n    sqr_add_c2(a, 6, 4, c2, c3, c1);\n    sqr_add_c2(a, 7, 3, c2, c3, c1);\n    r[10] = c2;\n    c2 = 0;\n    sqr_add_c2(a, 7, 4, c3, c1, c2);\n    sqr_add_c2(a, 6, 5, c3, c1, c2);\n    r[11] = c3;\n    c3 = 0;\n    sqr_add_c(a, 6, c1, c2, c3);\n    sqr_add_c2(a, 7, 5, c1, c2, c3);\n    r[12] = c1;\n    c1 = 0;\n    sqr_add_c2(a, 7, 6, c2, c3, c1);\n    r[13] = c2;\n    c2 = 0;\n    sqr_add_c(a, 7, c3, c1, c2);\n    r[14] = c3;\n    r[15] = c1;\n}\n\nvoid bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)\n{\n    BN_ULONG c1, c2, c3;\n\n    c1 = 0;\n    c2 = 0;\n    c3 = 0;\n    sqr_add_c(a, 0, c1, c2, c3);\n    r[0] = c1;\n    c1 = 0;\n    sqr_add_c2(a, 1, 0, c2, c3, c1);\n    r[1] = c2;\n    c2 = 0;\n    sqr_add_c(a, 1, c3, c1, c2);\n    sqr_add_c2(a, 2, 0, c3, c1, c2);\n    r[2] = c3;\n    c3 = 0;\n    sqr_add_c2(a, 3, 0, c1, c2, c3);\n    sqr_add_c2(a, 2, 1, c1, c2, c3);\n    r[3] = c1;\n    c1 = 0;\n    sqr_add_c(a, 2, c2, c3, c1);\n    sqr_add_c2(a, 3, 1, c2, c3, c1);\n    r[4] = c2;\n    c2 = 0;\n    sqr_add_c2(a, 3, 2, c3, c1, c2);\n    r[5] = c3;\n    c3 = 0;\n    sqr_add_c(a, 3, c1, c2, c3);\n    r[6] = c1;\n    r[7] = c2;\n}\n\n# ifdef OPENSSL_NO_ASM\n#  ifdef OPENSSL_BN_ASM_MONT\n#   include <alloca.h>\n/*\n * This is essentially reference implementation, which may or may not\n * result in performance improvement. E.g. on IA-32 this routine was\n * observed to give 40% faster rsa1024 private key operations and 10%\n * faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only\n * by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a\n * reference implementation, one to be used as starting point for\n * platform-specific assembler. Mentioned numbers apply to compiler\n * generated code compiled with and without -DOPENSSL_BN_ASM_MONT and\n * can vary not only from platform to platform, but even for compiler\n * versions. Assembler vs. assembler improvement coefficients can\n * [and are known to] differ and are to be documented elsewhere.\n */\nint bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                const BN_ULONG *np, const BN_ULONG *n0p, int num)\n{\n    BN_ULONG c0, c1, ml, *tp, n0;\n#   ifdef mul64\n    BN_ULONG mh;\n#   endif\n    volatile BN_ULONG *vp;\n    int i = 0, j;\n\n#   if 0                        /* template for platform-specific\n                                 * implementation */\n    if (ap == bp)\n        return bn_sqr_mont(rp, ap, np, n0p, num);\n#   endif\n    vp = tp = alloca((num + 2) * sizeof(BN_ULONG));\n\n    n0 = *n0p;\n\n    c0 = 0;\n    ml = bp[0];\n#   ifdef mul64\n    mh = HBITS(ml);\n    ml = LBITS(ml);\n    for (j = 0; j < num; ++j)\n        mul(tp[j], ap[j], ml, mh, c0);\n#   else\n    for (j = 0; j < num; ++j)\n        mul(tp[j], ap[j], ml, c0);\n#   endif\n\n    tp[num] = c0;\n    tp[num + 1] = 0;\n    goto enter;\n\n    for (i = 0; i < num; i++) {\n        c0 = 0;\n        ml = bp[i];\n#   ifdef mul64\n        mh = HBITS(ml);\n        ml = LBITS(ml);\n        for (j = 0; j < num; ++j)\n            mul_add(tp[j], ap[j], ml, mh, c0);\n#   else\n        for (j = 0; j < num; ++j)\n            mul_add(tp[j], ap[j], ml, c0);\n#   endif\n        c1 = (tp[num] + c0) & BN_MASK2;\n        tp[num] = c1;\n        tp[num + 1] = (c1 < c0 ? 1 : 0);\n enter:\n        c1 = tp[0];\n        ml = (c1 * n0) & BN_MASK2;\n        c0 = 0;\n#   ifdef mul64\n        mh = HBITS(ml);\n        ml = LBITS(ml);\n        mul_add(c1, np[0], ml, mh, c0);\n#   else\n        mul_add(c1, ml, np[0], c0);\n#   endif\n        for (j = 1; j < num; j++) {\n            c1 = tp[j];\n#   ifdef mul64\n            mul_add(c1, np[j], ml, mh, c0);\n#   else\n            mul_add(c1, ml, np[j], c0);\n#   endif\n            tp[j - 1] = c1 & BN_MASK2;\n        }\n        c1 = (tp[num] + c0) & BN_MASK2;\n        tp[num - 1] = c1;\n        tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0);\n    }\n\n    if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {\n        c0 = bn_sub_words(rp, tp, np, num);\n        if (tp[num] != 0 || c0 == 0) {\n            for (i = 0; i < num + 2; i++)\n                vp[i] = 0;\n            return 1;\n        }\n    }\n    for (i = 0; i < num; i++)\n        rp[i] = tp[i], vp[i] = 0;\n    vp[num] = 0;\n    vp[num + 1] = 0;\n    return 1;\n}\n#  else\n/*\n * Return value of 0 indicates that multiplication/convolution was not\n * performed to signal the caller to fall down to alternative/original\n * code-path.\n */\nint bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                const BN_ULONG *np, const BN_ULONG *n0, int num)\n{\n    return 0;\n}\n#  endif                        /* OPENSSL_BN_ASM_MONT */\n# endif\n\n#else                           /* !BN_MUL_COMBA */\n\n/* hmm... is it faster just to do a multiply? */\n# undef bn_sqr_comba4\nvoid bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)\n{\n    BN_ULONG t[8];\n    bn_sqr_normal(r, a, 4, t);\n}\n\n# undef bn_sqr_comba8\nvoid bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)\n{\n    BN_ULONG t[16];\n    bn_sqr_normal(r, a, 8, t);\n}\n\nvoid bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, const BN_ULONG *b)\t/* const - pcg */\n{\n    r[4] = bn_mul_words(&(r[0]), a, 4, b[0]);\n    r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]);\n    r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]);\n    r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]);\n}\n\nvoid bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b)\t/* const - pcg */\n{\n    r[8] = bn_mul_words(&(r[0]), a, 8, b[0]);\n    r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]);\n    r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]);\n    r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]);\n    r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]);\n    r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]);\n    r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]);\n    r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]);\n}\n\n# ifdef OPENSSL_NO_ASM\n#  ifdef OPENSSL_BN_ASM_MONT\n#   include <alloca.h>\nint bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                const BN_ULONG *np, const BN_ULONG *n0p, int num)\n{\n    BN_ULONG c0, c1, *tp, n0 = *n0p;\n    volatile BN_ULONG *vp;\n    int i = 0, j;\n\n    vp = tp = alloca((num + 2) * sizeof(BN_ULONG));\n\n    for (i = 0; i <= num; i++)\n        tp[i] = 0;\n\n    for (i = 0; i < num; i++) {\n        c0 = bn_mul_add_words(tp, ap, num, bp[i]);\n        c1 = (tp[num] + c0) & BN_MASK2;\n        tp[num] = c1;\n        tp[num + 1] = (c1 < c0 ? 1 : 0);\n\n        c0 = bn_mul_add_words(tp, np, num, tp[0] * n0);\n        c1 = (tp[num] + c0) & BN_MASK2;\n        tp[num] = c1;\n        tp[num + 1] += (c1 < c0 ? 1 : 0);\n        for (j = 0; j <= num; j++)\n            tp[j] = tp[j + 1];\n    }\n\n    if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {\n        c0 = bn_sub_words(rp, tp, np, num);\n        if (tp[num] != 0 || c0 == 0) {\n            for (i = 0; i < num + 2; i++)\n                vp[i] = 0;\n            return 1;\n        }\n    }\n    for (i = 0; i < num; i++)\n        rp[i] = tp[i], vp[i] = 0;\n    vp[num] = 0;\n    vp[num + 1] = 0;\n    return 1;\n}\n#  else\nint bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                const BN_ULONG *np, const BN_ULONG *n0, int num)\n{\n    return 0;\n}\n#  endif                        /* OPENSSL_BN_ASM_MONT */\n# endif\n\n#endif                          /* !BN_MUL_COMBA */\n\n#endif /* !BN_ASM */\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/bn/bn_exp.c",
    "content": "/* crypto/bn/bn_exp.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n/* ====================================================================\n * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n/* Changes for cryptlib - pcg */\n\n/* This version of bn_exp.c uses an older BN_mod_exp_mont_consttime() that \n   uses standard bignum ops rather than overlaying the bignum data onto a \n   fixed memory array that's used by CPU-specific code if RSAZ_ENABLED or \n   SPARC_T4_MONT is defined.  This causes problems because it assumes that \n   we can point BIGNUM.d values into a fixed block of memory and then mess \n   around with that which, as a side-effect, changes the values of the \n   bignums.  Since we're allocating the bignum storage ourselves we can't\n   use this memory-aliasing hack to modify the contents of the bignums via\n   external code */\n\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n#if defined( _MSC_VER )\n  #pragma warning( disable: 4311 )\t/* Warning about ugly 32-bit align ptr.cast */\n#endif /* VC++ */\n\n/* End changes for cryptlib - pcg */\n\n#undef SPARC_T4_MONT\n#if defined(OPENSSL_BN_ASM_MONT) && (defined(__sparc__) || defined(__sparc))\n# include \"sparc_arch.h\"\nextern unsigned int OPENSSL_sparcv9cap_P[];\n# define SPARC_T4_MONT\n#endif\n\n/* maximum precomputation table size for *variable* sliding windows */\n#define TABLE_SIZE      32\n\n/* this one works - simple but works */\nint BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)\n{\n    int i, bits, ret = 0;\n    BIGNUM *v, *rr;\n\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {\n        /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */\n        BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return -1;\n    }\n\n    BN_CTX_start(ctx);\n    if ((r == a) || (r == p))\n        rr = BN_CTX_get(ctx);\n    else\n        rr = r;\n    v = BN_CTX_get(ctx);\n    if (rr == NULL || v == NULL)\n        goto err;\n\n    if (BN_copy(v, a) == NULL)\n        goto err;\n    bits = BN_num_bits(p);\n\n    if (BN_is_odd(p)) {\n        if (BN_copy(rr, a) == NULL)\n            goto err;\n    } else {\n        if (!BN_one(rr))\n            goto err;\n    }\n\n    for (i = 1; i < bits; i++) {\n        if (!BN_sqr(v, v, ctx))\n            goto err;\n        if (BN_is_bit_set(p, i)) {\n            if (!BN_mul(rr, rr, v, ctx))\n                goto err;\n        }\n    }\n\tif (r != rr && rr != NULL) /* Check for rr == NULL - pcg */\n        BN_copy(r, rr);\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(r);\n    return (ret);\n}\n\nint BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,\n               BN_CTX *ctx)\n{\n    int ret;\n\n    bn_check_top(a);\n    bn_check_top(p);\n    bn_check_top(m);\n\n    /*-\n     * For even modulus  m = 2^k*m_odd,  it might make sense to compute\n     * a^p mod m_odd  and  a^p mod 2^k  separately (with Montgomery\n     * exponentiation for the odd part), using appropriate exponent\n     * reductions, and combine the results using the CRT.\n     *\n     * For now, we use Montgomery only if the modulus is odd; otherwise,\n     * exponentiation using the reciprocal-based quick remaindering\n     * algorithm is used.\n     *\n     * (Timing obtained with expspeed.c [computations  a^p mod m\n     * where  a, p, m  are of the same length: 256, 512, 1024, 2048,\n     * 4096, 8192 bits], compared to the running time of the\n     * standard algorithm:\n     *\n     *   BN_mod_exp_mont   33 .. 40 %  [AMD K6-2, Linux, debug configuration]\n     *                     55 .. 77 %  [UltraSparc processor, but\n     *                                  debug-solaris-sparcv8-gcc conf.]\n     *\n     *   BN_mod_exp_recp   50 .. 70 %  [AMD K6-2, Linux, debug configuration]\n     *                     62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]\n     *\n     * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont\n     * at 2048 and more bits, but at 512 and 1024 bits, it was\n     * slower even than the standard algorithm!\n     *\n     * \"Real\" timings [linux-elf, solaris-sparcv9-gcc configurations]\n     * should be obtained when the new Montgomery reduction code\n     * has been integrated into OpenSSL.)\n     */\n\n#define MONT_MUL_MOD\n#define MONT_EXP_WORD\n#define RECP_MUL_MOD\n\n#ifdef MONT_MUL_MOD\n    /*\n     * I have finally been able to take out this pre-condition of the top bit\n     * being set.  It was caused by an error in BN_div with negatives.  There\n     * was also another problem when for a^b%m a >= m.  eay 07-May-97\n     */\n    /* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */\n\n    if (BN_is_odd(m)) {\n# ifdef MONT_EXP_WORD\n        if (a->top == 1 && !a->neg\n            && (BN_get_flags(p, BN_FLG_CONSTTIME) == 0)) \n\t\t\t{\n\t\t\tBN_MONT_CTX *mont;\n\t\t\tBN_ULONG A = a->d[ 0 ];\n\n\t\t\t/* Added code to allocate and free the necessary BN_MONT_CTX \n\t\t\t   rather than requiring that BN_mod_exp_mont_word() sort it\n\t\t\t   out - pcg */\n\t\t\tif( ( mont = BN_MONT_CTX_new() ) == NULL )\n\t\t\t\treturn 0;\n\t\t\tif( !BN_MONT_CTX_set( mont, m, ctx ) )\n\t\t\t\t{\n\t\t\t\tBN_MONT_CTX_free( mont );\n\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\tret = BN_mod_exp_mont_word(r, A, p, m, ctx, mont);\n\t\t\tBN_MONT_CTX_free( mont );\n\t\t\t} \n\t\telse\n# endif\n            ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL);\n    } else\n#endif\n#ifdef RECP_MUL_MOD\n    {\n        ret = BN_mod_exp_recp(r, a, p, m, ctx);\n    }\n#else\n    {\n        ret = BN_mod_exp_simple(r, a, p, m, ctx);\n    }\n#endif\n\n    bn_check_top(r);\n    return (ret);\n}\n\nint BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n                    const BIGNUM *m, BN_CTX *ctx)\n{\n    int i, j, bits, ret = 0, wstart, wend, window, wvalue;\n    int start = 1;\n    BIGNUM *aa;\n    /* Table of variables obtained from 'ctx' */\n    BIGNUM *val[TABLE_SIZE];\n    BN_RECP_CTX recp;\n\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {\n        /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */\n        BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return -1;\n    }\n\n    bits = BN_num_bits(p);\n\n    if (bits == 0) {\n        ret = BN_one(r);\n        return ret;\n    }\n\n\tBN_RECP_CTX_init( &recp );\t/* Moved up - pcg */\n\tBN_CTX_start(ctx);\n    aa = BN_CTX_get(ctx);\n    val[0] = BN_CTX_get(ctx);\n    if (!aa || !val[0])\n        goto err;\n\n    if (m->neg) {\n        /* ignore sign of 'm' */\n        if (!BN_copy(aa, m))\n            goto err;\n        aa->neg = 0;\n        if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0)\n            goto err;\n    } else {\n        if (BN_RECP_CTX_set(&recp, m, ctx) <= 0)\n            goto err;\n    }\n\n    if (!BN_nnmod(val[0], a, m, ctx))\n        goto err;               /* 1 */\n    if (BN_is_zero(val[0])) {\n        BN_zero(r);\n        ret = 1;\n        goto err;\n    }\n\n    window = BN_window_bits_for_exponent_size(bits);\n    if (window > 1) {\n        if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx))\n            goto err;           /* 2 */\n        j = 1 << (window - 1);\n        for (i = 1; i < j; i++) {\n            if (((val[i] = BN_CTX_get(ctx)) == NULL) ||\n                !BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx))\n                goto err;\n        }\n    }\n\n    start = 1;                  /* This is used to avoid multiplication etc\n                                 * when there is only the value '1' in the\n                                 * buffer. */\n    wvalue = 0;                 /* The 'value' of the window */\n    wstart = bits - 1;          /* The top bit of the window */\n    wend = 0;                   /* The bottom bit of the window */\n\n    if (!BN_one(r))\n        goto err;\n\n    for (;;) {\n        if (BN_is_bit_set(p, wstart) == 0) {\n            if (!start)\n                if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx))\n                    goto err;\n            if (wstart == 0)\n                break;\n            wstart--;\n            continue;\n        }\n        /*\n         * We now have wstart on a 'set' bit, we now need to work out how bit\n         * a window to do.  To do this we need to scan forward until the last\n         * set bit before the end of the window\n         */\n        j = wstart;\n        wvalue = 1;\n        wend = 0;\n        for (i = 1; i < window; i++) {\n            if (wstart - i < 0)\n                break;\n            if (BN_is_bit_set(p, wstart - i)) {\n                wvalue <<= (i - wend);\n                wvalue |= 1;\n                wend = i;\n            }\n        }\n\n        /* wend is the size of the current window */\n        j = wend + 1;\n        /* add the 'bytes above' */\n        if (!start)\n            for (i = 0; i < j; i++) {\n                if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx))\n                    goto err;\n            }\n\n        /* wvalue will be an odd number < 2^window */\n        if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx))\n            goto err;\n\n        /* move the 'window' down further */\n        wstart -= wend + 1;\n        wvalue = 0;\n        start = 0;\n        if (wstart < 0)\n            break;\n    }\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    BN_RECP_CTX_free(&recp);\n    bn_check_top(r);\n    return (ret);\n}\n\nint BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,\n                    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)\n{\n    int i, j, bits, ret = 0, wstart, wend, window, wvalue;\n    int start = 1;\n    BIGNUM *d, *r;\n    const BIGNUM *aa;\n    /* Table of variables obtained from 'ctx' */\n    BIGNUM *val[TABLE_SIZE];\n    BN_MONT_CTX *mont = NULL;\n\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {\n        return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);\n    }\n\n    bn_check_top(a);\n    bn_check_top(p);\n    bn_check_top(m);\n\n    if (!BN_is_odd(m)) {\n        BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);\n        return (0);\n    }\n    bits = BN_num_bits(p);\n    if (bits == 0) {\n        ret = BN_one(rr);\n        return ret;\n    }\n\n    BN_CTX_start(ctx);\n    d = BN_CTX_get(ctx);\n    r = BN_CTX_get(ctx);\n    val[0] = BN_CTX_get(ctx);\n    if (!d || !r || !val[0])\n        goto err;\n\n    /*\n     * If this is not done, things will break in the montgomery part\n     */\n\n    if (in_mont != NULL)\n        mont = in_mont;\n    else {\n        if ((mont = BN_MONT_CTX_new()) == NULL)\n            goto err;\n        if (!BN_MONT_CTX_set(mont, m, ctx))\n            goto err;\n    }\n\n    if (a->neg || BN_ucmp(a, m) >= 0) {\n        if (!BN_nnmod(val[0], a, m, ctx))\n            goto err;\n        aa = val[0];\n    } else\n        aa = a;\n    if (BN_is_zero(aa)) {\n        BN_zero(rr);\n        ret = 1;\n        goto err;\n    }\n    if (!BN_to_montgomery(val[0], aa, mont, ctx))\n        goto err;               /* 1 */\n\n    window = BN_window_bits_for_exponent_size(bits);\n    if (window > 1) {\n        if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx))\n            goto err;           /* 2 */\n        j = 1 << (window - 1);\n        for (i = 1; i < j; i++) {\n            if (((val[i] = BN_CTX_get(ctx)) == NULL) ||\n                !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx))\n                goto err;\n        }\n    }\n\n    start = 1;                  /* This is used to avoid multiplication etc\n                                 * when there is only the value '1' in the\n                                 * buffer. */\n    wvalue = 0;                 /* The 'value' of the window */\n    wstart = bits - 1;          /* The top bit of the window */\n    wend = 0;                   /* The bottom bit of the window */\n\n#if 1                           /* by Shay Gueron's suggestion */\n    j = m->top;                 /* borrow j */\n    if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {\n        if (bn_wexpand(r, j) == NULL)\n            goto err;\n        /* 2^(top*BN_BITS2) - m */\n        r->d[0] = (0 - m->d[0]) & BN_MASK2;\n        for (i = 1; i < j; i++)\n            r->d[i] = (~m->d[i]) & BN_MASK2;\n        r->top = j;\n        /*\n         * Upper words will be zero if the corresponding words of 'm' were\n         * 0xfff[...], so decrement r->top accordingly.\n         */\n        bn_correct_top(r);\n    } else\n#endif\n    if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))\n        goto err;\n    for (;;) {\n        if (BN_is_bit_set(p, wstart) == 0) {\n            if (!start) {\n                if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))\n                    goto err;\n            }\n            if (wstart == 0)\n                break;\n            wstart--;\n            continue;\n        }\n        /*\n         * We now have wstart on a 'set' bit, we now need to work out how bit\n         * a window to do.  To do this we need to scan forward until the last\n         * set bit before the end of the window\n         */\n        j = wstart;\n        wvalue = 1;\n        wend = 0;\n        for (i = 1; i < window; i++) {\n            if (wstart - i < 0)\n                break;\n            if (BN_is_bit_set(p, wstart - i)) {\n                wvalue <<= (i - wend);\n                wvalue |= 1;\n                wend = i;\n            }\n        }\n\n        /* wend is the size of the current window */\n        j = wend + 1;\n        /* add the 'bytes above' */\n        if (!start)\n            for (i = 0; i < j; i++) {\n                if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))\n                    goto err;\n            }\n\n        /* wvalue will be an odd number < 2^window */\n        if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx))\n            goto err;\n\n        /* move the 'window' down further */\n        wstart -= wend + 1;\n        wvalue = 0;\n        start = 0;\n        if (wstart < 0)\n            break;\n    }\n#if defined(SPARC_T4_MONT)\n    if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {\n        j = mont->N.top;        /* borrow j */\n        val[0]->d[0] = 1;       /* borrow val[0] */\n        for (i = 1; i < j; i++)\n            val[0]->d[i] = 0;\n        val[0]->top = j;\n        if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx))\n            goto err;\n    } else\n#endif\n    if (!BN_from_montgomery(rr, r, mont, ctx))\n        goto err;\n    ret = 1;\n err:\n    if ((in_mont == NULL) && (mont != NULL))\n        BN_MONT_CTX_free(mont);\n    BN_CTX_end(ctx);\n    bn_check_top(rr);\n    return (ret);\n}\n\n#if defined(SPARC_T4_MONT)\nstatic BN_ULONG bn_get_bits(const BIGNUM *a, int bitpos)\n{\n    BN_ULONG ret = 0;\n    int wordpos;\n\n    wordpos = bitpos / BN_BITS2;\n    bitpos %= BN_BITS2;\n    if (wordpos >= 0 && wordpos < a->top) {\n        ret = a->d[wordpos] & BN_MASK2;\n        if (bitpos) {\n            ret >>= bitpos;\n            if (++wordpos < a->top)\n                ret |= a->d[wordpos] << (BN_BITS2 - bitpos);\n        }\n    }\n\n    return ret & BN_MASK2;\n}\n#endif\n\n/*\n * BN_mod_exp_mont_consttime() stores the precomputed powers in a specific\n * layout so that accessing any of these table values shows the same access\n * pattern as far as cache lines are concerned.  The following functions are\n * used to transfer a BIGNUM from/to that table.\n */\n\nstatic int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top,\n                                        unsigned char *buf, int idx,\n                                        int width)\n{\n    size_t i, j;\n\n    if (top > b->top)\n        top = b->top;           /* this works because 'buf' is explicitly\n                                 * zeroed */\n    for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {\n        buf[j] = ((unsigned char *)b->d)[i];\n    }\n\n    return 1;\n}\n\nstatic int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,\n                                          unsigned char *buf, int idx,\n                                          int width)\n{\n    size_t i, j;\n\n    if (bn_wexpand(b, top) == NULL)\n        return 0;\n\n    for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {\n        ((unsigned char *)b->d)[i] = buf[j];\n    }\n\n    b->top = top;\n    bn_correct_top(b);\n    return 1;\n}\n\n/*\n * Given a pointer value, compute the next address that is a cache line\n * multiple.\n */\n#define MOD_EXP_CTIME_ALIGN(x_) \\\n        ((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))\n\n/*\n * This variant of BN_mod_exp_mont() uses fixed windows and the special\n * precomputation memory layout to limit data-dependency to a minimum to\n * protect secret exponents (cf. the hyper-threading timing attacks pointed\n * out by Colin Percival,\n * http://www.daemong-consideredperthreading-considered-harmful/)\n */\nint BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,\n                              const BIGNUM *m, BN_CTX *ctx,\n                              BN_MONT_CTX *in_mont)\n{\n\tint i, bits, ret = 0, idx, window, wvalue;\n\tint top;\n \tBIGNUM *r;\n\tconst BIGNUM *aa;\n\tBN_MONT_CTX *mont = NULL;\n\n\tint numPowers;\n\tunsigned char *powerbufFree = NULL;\n\tint powerbufLen = 0;\n\tunsigned char *powerbuf = NULL;\n\tBIGNUM *computeTemp = NULL, *am = NULL;\n\n\tbn_check_top(a);\n\tbn_check_top(p);\n\tbn_check_top(m);\n\n\tif (!BN_is_odd(m))\n\t\t{\n\t\tBNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME,BN_R_CALLED_WITH_EVEN_MODULUS);\n\t\treturn(0);\n\t\t}\n\n\ttop = m->top;\n\n\tbits = BN_num_bits(p);\n\tif (bits == 0)\n\t\t{\n\t\tret = BN_one(rr);\n\t\treturn ret;\n\t\t}\n\n \t/* Initialize BIGNUM context and allocate intermediate result */\n\tBN_CTX_start(ctx);\n\tr = BN_CTX_get(ctx);\n\tif (r == NULL) \n\t\tgoto err;\n\n\t/* Allocate a montgomery context if it was not supplied by the caller.\n\t * If this is not done, things will break in the montgomery part.\n \t */\n\tif (in_mont != NULL)\n\t\tmont=in_mont;\n\telse\n\t\t{\n\t\tif ((mont = BN_MONT_CTX_new()) == NULL) \n\t\t\tgoto err;\n\t\tif (!BN_MONT_CTX_set(mont, m, ctx)) \n\t\t\tgoto err;\n\t\t}\n\n\t/* Get the window size to use with size of p. */\n\twindow = BN_window_bits_for_ctime_exponent_size(bits);\n\n\t/* Allocate a buffer large enough to hold all of the pre-computed\n\t * powers of a.\n\t */\n\tnumPowers = 1 << window;\n\tpowerbufLen = sizeof(m->d[0]) * top * numPowers;\n\tif ((powerbufFree = (unsigned char*)clBnAlloc(\"BN_mod_exp_mont_consttime\",\t/* pcg */\n\t\t\t\t\t\t\t\t\t\t\t\tpowerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)\n\t\tgoto err;\n\t\t\n\tpowerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);\n\tmemset(powerbuf, 0, powerbufLen);\n\n \t/* Initialize the intermediate result. Do this early to save double conversion,\n\t * once each for a^0 and intermediate result.\n\t */\n \tif (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) \n\t\tgoto err;\n\tif (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) \n\t\tgoto err;\n\n\t/* Initialize computeTemp as a^1 with montgomery precalcs */\n\tcomputeTemp = BN_CTX_get(ctx);\n\tam = BN_CTX_get(ctx);\n\tif (computeTemp == NULL || am == NULL) \n\t\tgoto err;\n\n\tif (a->neg || BN_ucmp(a, m) >= 0)\n\t\t{\n\t\tif (!BN_mod(am, a, m, ctx))\n\t\t\tgoto err;\n\t\taa = am;\n\t\t}\n\telse\n\t\taa = a;\n\tif (!BN_to_montgomery(am, aa, mont, ctx)) \n\t\tgoto err;\n\tif (!BN_copy(computeTemp, am)) \n\t\tgoto err;\n\tif (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) \n\t\tgoto err;\n\n\t/* If the window size is greater than 1, then calculate\n\t * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)\n\t * (even powers could instead be computed as (a^(i/2))^2\n\t * to use the slight performance advantage of sqr over mul).\n\t */\n\tif (window > 1)\n\t\t{\n\t\tfor (i = 2; i < numPowers; i++)\n\t\t\t{\n\t\t\t/* Calculate a^i = a^(i-1) * a */\n\t\t\tif (!BN_mod_mul_montgomery(computeTemp, am, computeTemp, mont, ctx))\n\t\t\t\tgoto err;\n\t\t\tif (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) \n\t\t\t\tgoto err;\n\t\t\t}\n\t\t}\n\n \t/* Adjust the number of bits up to a multiple of the window size.\n \t * If the exponent length is not a multiple of the window size, then\n \t * this pads the most significant bits with zeros to normalize the\n \t * scanning loop to there's no special cases.\n \t *\n \t * * NOTE: Making the window size a power of two less than the native\n\t * * word size ensures that the padded bits won't go past the last\n \t * * word in the internal BIGNUM structure. Going past the end will\n \t * * still produce the correct result, but causes a different branch\n \t * * to be taken in the BN_is_bit_set function.\n \t */\n \tbits = ((bits + window - 1) / window) * window;\n \tidx = bits - 1;\t/* The top bit of the window */\n\n \t/* Scan the exponent one window at a time starting from the most\n \t * significant bits.\n \t */\n \twhile (idx >= 0)\n  \t\t{\n \t\twvalue = 0; /* The 'value' of the window */\n \t\t\n \t\t/* Scan the window, squaring the result as we go */\n \t\tfor (i = 0; i < window; i++, idx--)\n \t\t\t{\n\t\t\tif (!BN_mod_mul_montgomery(r, r, r, mont, ctx))\t\n\t\t\t\tgoto err;\n\t\t\twvalue = (wvalue << 1) + ( BN_is_bit_set(p, idx) ? 1 : 0 );\t/* pcg */\n  \t\t\t}\n \t\t\n\t\t/* Fetch the appropriate pre-computed value from the pre-buf */\n\t\tif (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) \n\t\t\tgoto err;\n\n \t\t/* Multiply the result into the intermediate result */\n \t\tif (!BN_mod_mul_montgomery(r, r, computeTemp, mont, ctx)) \n\t\t\tgoto err;\n  \t\t}\n\n \t/* Convert the final result from montgomery to standard format */\n\tif (!BN_from_montgomery(rr, r, mont, ctx)) \n\t\tgoto err;\n\tret = 1;\nerr:\n\tif ((in_mont == NULL) && (mont != NULL)) \n\t\tBN_MONT_CTX_free(mont);\n\tif (powerbuf != NULL)\n\t\t{\n\t\tOPENSSL_cleanse(powerbuf, powerbufLen);\n\t\tOPENSSL_free(powerbufFree);\n\t\t}\n \tif (am != NULL) \n\t\tBN_clear(am);\n \tif (computeTemp != NULL) \n\t\tBN_clear(computeTemp);\n\tBN_CTX_end(ctx);\n\treturn(ret);\n}\n\nint BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,\n                         const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *in_mont)\n{\n\tconst BN_MONT_CTX *mont = in_mont;\n    int b, bits, ret = 0;\n    int r_is_one;\n    BN_ULONG w, next_w;\n    BIGNUM *d, *r, *t;\n    BIGNUM *swap_tmp;\n#define BN_MOD_MUL_WORD(r, w, m) \\\n                (BN_mul_word(r, (w)) && \\\n                (/* BN_ucmp(r, (m)) < 0 ? 1 :*/  \\\n                        (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))\n    /*\n     * BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is\n     * probably more overhead than always using BN_mod (which uses BN_copy if\n     * a similar test returns true).\n     */\n    /*\n     * We can use BN_mod and do not need BN_nnmod because our accumulator is\n     * never negative (the result of BN_mod does not depend on the sign of\n     * the modulus).\n     */\n#define BN_TO_MONTGOMERY_WORD(r, w, mont) \\\n                (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))\n\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {\n        /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */\n        BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return -1;\n    }\n\n    bn_check_top(p);\n    bn_check_top(m);\n\n    if (!BN_is_odd(m)) {\n        BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS);\n        return (0);\n    }\n    if (m->top == 1)\n        a %= m->d[0];           /* make sure that 'a' is reduced */\n\n    bits = BN_num_bits(p);\n    if (bits == 0) {\n        /* x**0 mod 1 is still zero. */\n        if (BN_is_one(m)) {\n            ret = 1;\n            BN_zero(rr);\n        } else\n            ret = BN_one(rr);\n        return ret;\n    }\n    if (a == 0) {\n        BN_zero(rr);\n        ret = 1;\n        return ret;\n    }\n\n    BN_CTX_start(ctx);\n    d = BN_CTX_get(ctx);\n    r = BN_CTX_get(ctx);\n    t = BN_CTX_get(ctx);\n    if (d == NULL || r == NULL || t == NULL)\n        goto err;\n\n    r_is_one = 1;               /* except for Montgomery factor */\n\n    /* bits-1 >= 0 */\n\n    /* The result is accumulated in the product r*w. */\n    w = a;                      /* bit 'bits-1' of 'p' is always set */\n    for (b = bits - 2; b >= 0; b--) {\n        /* First, square r*w. */\n        next_w = w * w;\n        if ((next_w / w) != w) { /* overflow */\n            if (r_is_one) {\n                if (!BN_TO_MONTGOMERY_WORD(r, w, mont))\n                    goto err;\n                r_is_one = 0;\n            } else {\n                if (!BN_MOD_MUL_WORD(r, w, m))\n                    goto err;\n            }\n            next_w = 1;\n        }\n        w = next_w;\n        if (!r_is_one) {\n            if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))\n                goto err;\n        }\n\n        /* Second, multiply r*w by 'a' if exponent bit is set. */\n        if (BN_is_bit_set(p, b)) {\n            next_w = w * a;\n            if ((next_w / a) != w) { /* overflow */\n                if (r_is_one) {\n                    if (!BN_TO_MONTGOMERY_WORD(r, w, mont))\n                        goto err;\n                    r_is_one = 0;\n                } else {\n                    if (!BN_MOD_MUL_WORD(r, w, m))\n                        goto err;\n                }\n                next_w = a;\n            }\n            w = next_w;\n        }\n    }\n\n    /* Finally, set r:=r*w. */\n    if (w != 1) {\n        if (r_is_one) {\n            if (!BN_TO_MONTGOMERY_WORD(r, w, mont))\n                goto err;\n            r_is_one = 0;\n        } else {\n            if (!BN_MOD_MUL_WORD(r, w, m))\n                goto err;\n        }\n    }\n\n    if (r_is_one) {             /* can happen only if a == 1 */\n        if (!BN_one(rr))\n            goto err;\n    } else {\n        if (!BN_from_montgomery(rr, r, mont, ctx))\n            goto err;\n    }\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(rr);\n    return (ret);\n}\n\n#ifdef RECP_MUL_MOD\t/* pcg */\n\n/* The old fallback, simple version :-) */\nint BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n                      const BIGNUM *m, BN_CTX *ctx)\n{\n    int i, j, bits, ret = 0, wstart, wend, window, wvalue;\n    int start = 1;\n    BIGNUM *d;\n    /* Table of variables obtained from 'ctx' */\n    BIGNUM *val[TABLE_SIZE];\n\n    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {\n        /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */\n        BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return -1;\n    }\n\n    bits = BN_num_bits(p);\n\n    if (bits == 0) {\n        ret = BN_one(r);\n        return ret;\n    }\n\n    BN_CTX_start(ctx);\n    d = BN_CTX_get(ctx);\n    val[0] = BN_CTX_get(ctx);\n    if (!d || !val[0])\n        goto err;\n\n    if (!BN_nnmod(val[0], a, m, ctx))\n        goto err;               /* 1 */\n    if (BN_is_zero(val[0])) {\n        BN_zero(r);\n        ret = 1;\n        goto err;\n    }\n\n    window = BN_window_bits_for_exponent_size(bits);\n    if (window > 1) {\n        if (!BN_mod_mul(d, val[0], val[0], m, ctx))\n            goto err;           /* 2 */\n        j = 1 << (window - 1);\n        for (i = 1; i < j; i++) {\n            if (((val[i] = BN_CTX_get(ctx)) == NULL) ||\n                !BN_mod_mul(val[i], val[i - 1], d, m, ctx))\n                goto err;\n        }\n    }\n\n    start = 1;                  /* This is used to avoid multiplication etc\n                                 * when there is only the value '1' in the\n                                 * buffer. */\n    wvalue = 0;                 /* The 'value' of the window */\n    wstart = bits - 1;          /* The top bit of the window */\n    wend = 0;                   /* The bottom bit of the window */\n\n    if (!BN_one(r))\n        goto err;\n\n    for (;;) {\n        if (!BN_is_bit_set(p, wstart)) {\t/* pcg */\n            if (!start)\n                if (!BN_mod_mul(r, r, r, m, ctx))\n                    goto err;\n            if (wstart == 0)\n                break;\n            wstart--;\n            continue;\n        }\n        /*\n         * We now have wstart on a 'set' bit, we now need to work out how bit\n         * a window to do.  To do this we need to scan forward until the last\n         * set bit before the end of the window\n         */\n        j = wstart;\n        wvalue = 1;\n        wend = 0;\n        for (i = 1; i < window; i++) {\n            if (wstart - i < 0)\n                break;\n            if (BN_is_bit_set(p, wstart - i)) {\n                wvalue <<= (i - wend);\n                wvalue |= 1;\n                wend = i;\n            }\n        }\n\n        /* wend is the size of the current window */\n        j = wend + 1;\n        /* add the 'bytes above' */\n        if (!start)\n            for (i = 0; i < j; i++) {\n                if (!BN_mod_mul(r, r, r, m, ctx))\n                    goto err;\n            }\n\n        /* wvalue will be an odd number < 2^window */\n        if (!BN_mod_mul(r, r, val[wvalue >> 1], m, ctx))\n            goto err;\n\n        /* move the 'window' down further */\n        wstart -= wend + 1;\n        wvalue = 0;\n        start = 0;\n        if (wstart < 0)\n            break;\n    }\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(r);\n    return (ret);\n}\n#endif /* RECP_MUL_MOD - pcg */\n"
  },
  {
    "path": "deps/cl345/bn/bn_exp2.c",
    "content": "/* crypto/bn/bn_exp2.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n/* ====================================================================\n * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n#include <stdio.h>\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n\n#if defined USE_DSA\t\t/* Only called once from ctx_dsa.c */\n\n/* End changes for cryptlib - pcg */\n\n#define TABLE_SIZE      32\n\nint BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,\n                     const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,\n                     BN_CTX *ctx, BN_MONT_CTX *in_mont)\n{\n    int i, j, bits, b, bits1, bits2, ret =\n        0, wpos1, wpos2, window1, window2, wvalue1, wvalue2;\n    int r_is_one = 1;\n    BIGNUM *d, *r;\n    const BIGNUM *a_mod_m;\n    /* Tables of variables obtained from 'ctx' */\n    BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];\n    BN_MONT_CTX *mont = NULL;\n\n\tassert( in_mont != NULL );\t/* pcg */\n\n    bn_check_top(a1);\n    bn_check_top(p1);\n    bn_check_top(a2);\n    bn_check_top(p2);\n    bn_check_top(m);\n\n    if (!(m->d[0] & 1)) {\n        BNerr(BN_F_BN_MOD_EXP2_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);\n        return (0);\n    }\n    bits1 = BN_num_bits(p1);\n    bits2 = BN_num_bits(p2);\n    if ((bits1 == 0) && (bits2 == 0)) {\n        ret = BN_one(rr);\n        return ret;\n    }\n\n    bits = (bits1 > bits2) ? bits1 : bits2;\n\n    BN_CTX_start(ctx);\n    d = BN_CTX_get(ctx);\n    r = BN_CTX_get(ctx);\n    val1[0] = BN_CTX_get(ctx);\n    val2[0] = BN_CTX_get(ctx);\n    if (!d || !r || !val1[0] || !val2[0])\n        goto err;\n\n    if (in_mont != NULL)\n        mont = in_mont;\n    else {\n        if ((mont = BN_MONT_CTX_new()) == NULL)\n            goto err;\n        if (!BN_MONT_CTX_set(mont, m, ctx))\n            goto err;\n    }\n\n    window1 = BN_window_bits_for_exponent_size(bits1);\n    window2 = BN_window_bits_for_exponent_size(bits2);\n\n    /*\n     * Build table for a1:   val1[i] := a1^(2*i + 1) mod m  for i = 0 .. 2^(window1-1)\n     */\n    if (a1->neg || BN_ucmp(a1, m) >= 0) {\n        if (!BN_mod(val1[0], a1, m, ctx))\n            goto err;\n        a_mod_m = val1[0];\n    } else\n        a_mod_m = a1;\n    if (BN_is_zero(a_mod_m)) {\n        BN_zero(rr);\n        ret = 1;\n        goto err;\n    }\n\n    if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx))\n        goto err;\n    if (window1 > 1) {\n        if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx))\n            goto err;\n\n        j = 1 << (window1 - 1);\n        for (i = 1; i < j; i++) {\n            if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||\n                !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx))\n                goto err;\n        }\n    }\n\n    /*\n     * Build table for a2:   val2[i] := a2^(2*i + 1) mod m  for i = 0 .. 2^(window2-1)\n     */\n    if (a2->neg || BN_ucmp(a2, m) >= 0) {\n        if (!BN_mod(val2[0], a2, m, ctx))\n            goto err;\n        a_mod_m = val2[0];\n    } else\n        a_mod_m = a2;\n    if (BN_is_zero(a_mod_m)) {\n        BN_zero(rr);\n        ret = 1;\n        goto err;\n    }\n    if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx))\n        goto err;\n    if (window2 > 1) {\n        if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx))\n            goto err;\n\n        j = 1 << (window2 - 1);\n        for (i = 1; i < j; i++) {\n            if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||\n                !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx))\n                goto err;\n        }\n    }\n\n    /* Now compute the power product, using independent windows. */\n    r_is_one = 1;\n    wvalue1 = 0;                /* The 'value' of the first window */\n    wvalue2 = 0;                /* The 'value' of the second window */\n    wpos1 = 0;                  /* If wvalue1 > 0, the bottom bit of the\n                                 * first window */\n    wpos2 = 0;                  /* If wvalue2 > 0, the bottom bit of the\n                                 * second window */\n\n    if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))\n        goto err;\n    for (b = bits - 1; b >= 0; b--) {\n        if (!r_is_one) {\n            if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))\n                goto err;\n        }\n\n        if (!wvalue1)\n            if (BN_is_bit_set(p1, b)) {\n                /*\n                 * consider bits b-window1+1 .. b for this window\n                 */\n                i = b - window1 + 1;\n                while (!BN_is_bit_set(p1, i)) /* works for i<0 */\n                    i++;\n                wpos1 = i;\n                wvalue1 = 1;\n                for (i = b - 1; i >= wpos1; i--) {\n                    wvalue1 <<= 1;\n                    if (BN_is_bit_set(p1, i))\n                        wvalue1++;\n                }\n            }\n\n        if (!wvalue2)\n            if (BN_is_bit_set(p2, b)) {\n                /*\n                 * consider bits b-window2+1 .. b for this window\n                 */\n                i = b - window2 + 1;\n                while (!BN_is_bit_set(p2, i))\n                    i++;\n                wpos2 = i;\n                wvalue2 = 1;\n                for (i = b - 1; i >= wpos2; i--) {\n                    wvalue2 <<= 1;\n                    if (BN_is_bit_set(p2, i))\n                        wvalue2++;\n                }\n            }\n\n        if (wvalue1 && b == wpos1) {\n            /* wvalue1 is odd and < 2^window1 */\n            if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx))\n                goto err;\n            wvalue1 = 0;\n            r_is_one = 0;\n        }\n\n        if (wvalue2 && b == wpos2) {\n            /* wvalue2 is odd and < 2^window2 */\n            if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx))\n                goto err;\n            wvalue2 = 0;\n            r_is_one = 0;\n        }\n    }\n    if (!BN_from_montgomery(rr, r, mont, ctx))\n        goto err;\n    ret = 1;\n err:\n    if ((in_mont == NULL) && (mont != NULL))\n        BN_MONT_CTX_free(mont);\n    BN_CTX_end(ctx);\n    bn_check_top(rr);\n    return (ret);\n}\n#endif /* USE_DSA - pcg */\n"
  },
  {
    "path": "deps/cl345/bn/bn_gcd.c",
    "content": "/* crypto/bn/bn_gcd.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n/* ====================================================================\n * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\nstatic BIGNUM *euclid(BIGNUM *a, BIGNUM *b);\n\nint BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)\n{\n    BIGNUM *a, *b, *t;\n    int ret = 0;\n\n    bn_check_top(in_a);\n    bn_check_top(in_b);\n\n    BN_CTX_start(ctx);\n    a = BN_CTX_get(ctx);\n    b = BN_CTX_get(ctx);\n    if (a == NULL || b == NULL)\n        goto err;\n\n    if (BN_copy(a, in_a) == NULL)\n        goto err;\n    if (BN_copy(b, in_b) == NULL)\n        goto err;\n    a->neg = 0;\n    b->neg = 0;\n\n    if (BN_cmp(a, b) < 0) {\n        t = a;\n        a = b;\n        b = t;\n    }\n    t = euclid(a, b);\n    if (t == NULL)\n        goto err;\n\n    if (BN_copy(r, t) == NULL)\n        goto err;\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(r);\n    return (ret);\n}\n\nstatic BIGNUM *euclid(BIGNUM *a, BIGNUM *b)\n{\n    BIGNUM *t;\n    int shifts = 0;\n\n    bn_check_top(a);\n    bn_check_top(b);\n\n    /* 0 <= b <= a */\n    while (!BN_is_zero(b)) {\n        /* 0 < b <= a */\n\n        if (BN_is_odd(a)) {\n            if (BN_is_odd(b)) {\n                if (!BN_sub(a, a, b))\n                    goto err;\n                if (!BN_rshift1(a, a))\n                    goto err;\n                if (BN_cmp(a, b) < 0) {\n                    t = a;\n                    a = b;\n                    b = t;\n                }\n            } else {            /* a odd - b even */\n\n                if (!BN_rshift1(b, b))\n                    goto err;\n                if (BN_cmp(a, b) < 0) {\n                    t = a;\n                    a = b;\n                    b = t;\n                }\n            }\n        } else {                /* a is even */\n\n            if (BN_is_odd(b)) {\n                if (!BN_rshift1(a, a))\n                    goto err;\n                if (BN_cmp(a, b) < 0) {\n                    t = a;\n                    a = b;\n                    b = t;\n                }\n            } else {            /* a even - b even */\n\n                if (!BN_rshift1(a, a))\n                    goto err;\n                if (!BN_rshift1(b, b))\n                    goto err;\n                shifts++;\n            }\n        }\n        /* 0 <= b <= a */\n    }\n\n    if (shifts) {\n        if (!BN_lshift(a, a, shifts))\n            goto err;\n    }\n    bn_check_top(a);\n    return (a);\n err:\n    return (NULL);\n}\n\n/* solves ax == 1 (mod n) */\nstatic BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,\n                                        const BIGNUM *a, const BIGNUM *n,\n                                        BN_CTX *ctx);\n\nBIGNUM *BN_mod_inverse(BIGNUM *in,\n                       const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)\n{\n    BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;\n    BIGNUM *ret = NULL;\n    int sign;\n\n    if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0)\n        || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) {\n        return BN_mod_inverse_no_branch(in, a, n, ctx);\n    }\n\n    bn_check_top(a);\n    bn_check_top(n);\n\n    BN_CTX_start(ctx);\n    A = BN_CTX_get(ctx);\n    B = BN_CTX_get(ctx);\n    X = BN_CTX_get(ctx);\n    D = BN_CTX_get(ctx);\n    M = BN_CTX_get(ctx);\n    Y = BN_CTX_get(ctx);\n    T = BN_CTX_get(ctx);\n    if ( A == NULL || B == NULL || X == NULL || D == NULL || M == NULL || \\\n\t\t Y == NULL || T == NULL)\t/* pcg */\n        goto err;\n\n    if (in == NULL)\n        R = BN_new();\n    else\n        R = in;\n    if (R == NULL)\n        goto err;\n\n    BN_one(X);\n    BN_zero(Y);\n    if (BN_copy(B, a) == NULL)\n        goto err;\n    if (BN_copy(A, n) == NULL)\n        goto err;\n    A->neg = 0;\n    if (B->neg || (BN_ucmp(B, A) >= 0)) {\n        if (!BN_nnmod(B, B, A, ctx))\n            goto err;\n    }\n    sign = -1;\n    /*-\n     * From  B = a mod |n|,  A = |n|  it follows that\n     *\n     *      0 <= B < A,\n     *     -sign*X*a  ==  B   (mod |n|),\n     *      sign*Y*a  ==  A   (mod |n|).\n     */\n\n    if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {\n        /*\n         * Binary inversion algorithm; requires odd modulus. This is faster\n         * than the general algorithm if the modulus is sufficiently small\n         * (about 400 .. 500 bits on 32-bit sytems, but much more on 64-bit\n         * systems)\n         */\n        int shift;\n\n        while (!BN_is_zero(B)) {\n            /*-\n             *      0 < B < |n|,\n             *      0 < A <= |n|,\n             * (1) -sign*X*a  ==  B   (mod |n|),\n             * (2)  sign*Y*a  ==  A   (mod |n|)\n             */\n\n            /*\n             * Now divide B by the maximum possible power of two in the\n             * integers, and divide X by the same value mod |n|. When we're\n             * done, (1) still holds.\n             */\n            shift = 0;\n            while (!BN_is_bit_set(B, shift)) { /* note that 0 < B */\n                shift++;\n\n                if (BN_is_odd(X)) {\n                    if (!BN_uadd(X, X, n))\n                        goto err;\n                }\n                /*\n                 * now X is even, so we can easily divide it by two\n                 */\n                if (!BN_rshift1(X, X))\n                    goto err;\n            }\n            if (shift > 0) {\n                if (!BN_rshift(B, B, shift))\n                    goto err;\n            }\n\n            /*\n             * Same for A and Y.  Afterwards, (2) still holds.\n             */\n            shift = 0;\n            while (!BN_is_bit_set(A, shift)) { /* note that 0 < A */\n                shift++;\n\n                if (BN_is_odd(Y)) {\n                    if (!BN_uadd(Y, Y, n))\n                        goto err;\n                }\n                /* now Y is even */\n                if (!BN_rshift1(Y, Y))\n                    goto err;\n            }\n            if (shift > 0) {\n                if (!BN_rshift(A, A, shift))\n                    goto err;\n            }\n\n            /*-\n             * We still have (1) and (2).\n             * Both  A  and  B  are odd.\n             * The following computations ensure that\n             *\n             *     0 <= B < |n|,\n             *      0 < A < |n|,\n             * (1) -sign*X*a  ==  B   (mod |n|),\n             * (2)  sign*Y*a  ==  A   (mod |n|),\n             *\n             * and that either  A  or  B  is even in the next iteration.\n             */\n            if (BN_ucmp(B, A) >= 0) {\n                /* -sign*(X + Y)*a == B - A  (mod |n|) */\n                if (!BN_uadd(X, X, Y))\n                    goto err;\n                /*\n                 * NB: we could use BN_mod_add_quick(X, X, Y, n), but that\n                 * actually makes the algorithm slower\n                 */\n                if (!BN_usub(B, B, A))\n                    goto err;\n            } else {\n                /*  sign*(X + Y)*a == A - B  (mod |n|) */\n                if (!BN_uadd(Y, Y, X))\n                    goto err;\n                /*\n                 * as above, BN_mod_add_quick(Y, Y, X, n) would slow things\n                 * down\n                 */\n                if (!BN_usub(A, A, B))\n                    goto err;\n            }\n        }\n    } else {\n        /* general inversion algorithm */\n\n        while (!BN_is_zero(B)) {\n            BIGNUM *tmp;\n\n            /*-\n             *      0 < B < A,\n             * (*) -sign*X*a  ==  B   (mod |n|),\n             *      sign*Y*a  ==  A   (mod |n|)\n             */\n\n            /* (D, M) := (A/B, A%B) ... */\n            if (BN_num_bits(A) == BN_num_bits(B)) {\n                if (!BN_one(D))\n                    goto err;\n                if (!BN_sub(M, A, B))\n                    goto err;\n            } else if (BN_num_bits(A) == BN_num_bits(B) + 1) {\n                /* A/B is 1, 2, or 3 */\n                if (!BN_lshift1(T, B))\n                    goto err;\n                if (BN_ucmp(A, T) < 0) {\n                    /* A < 2*B, so D=1 */\n                    if (!BN_one(D))\n                        goto err;\n                    if (!BN_sub(M, A, B))\n                        goto err;\n                } else {\n                    /* A >= 2*B, so D=2 or D=3 */\n                    if (!BN_sub(M, A, T))\n                        goto err;\n                    if (!BN_add(D, T, B))\n                        goto err; /* use D (:= 3*B) as temp */\n                    if (BN_ucmp(A, D) < 0) {\n                        /* A < 3*B, so D=2 */\n                        if (!BN_set_word(D, 2))\n                            goto err;\n                        /*\n                         * M (= A - 2*B) already has the correct value\n                         */\n                    } else {\n                        /* only D=3 remains */\n                        if (!BN_set_word(D, 3))\n                            goto err;\n                        /*\n                         * currently M = A - 2*B, but we need M = A - 3*B\n                         */\n                        if (!BN_sub(M, M, B))\n                            goto err;\n                    }\n                }\n            } else {\n                if (!BN_div(D, M, A, B, ctx))\n                    goto err;\n            }\n\n            /*-\n             * Now\n             *      A = D*B + M;\n             * thus we have\n             * (**)  sign*Y*a  ==  D*B + M   (mod |n|).\n             */\n\n            tmp = A;            /* keep the BIGNUM object, the value does not\n                                 * matter */\n\n            /* (A, B) := (B, A mod B) ... */\n            A = B;\n            B = M;\n            /* ... so we have  0 <= B < A  again */\n\n            /*-\n             * Since the former  M  is now  B  and the former  B  is now  A,\n             * (**) translates into\n             *       sign*Y*a  ==  D*A + B    (mod |n|),\n             * i.e.\n             *       sign*Y*a - D*A  ==  B    (mod |n|).\n             * Similarly, (*) translates into\n             *      -sign*X*a  ==  A          (mod |n|).\n             *\n             * Thus,\n             *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),\n             * i.e.\n             *        sign*(Y + D*X)*a  ==  B  (mod |n|).\n             *\n             * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at\n             *      -sign*X*a  ==  B   (mod |n|),\n             *       sign*Y*a  ==  A   (mod |n|).\n             * Note that  X  and  Y  stay non-negative all the time.\n             */\n\n            /*\n             * most of the time D is very small, so we can optimize tmp :=\n             * D*X+Y\n             */\n            if (BN_is_one(D)) {\n                if (!BN_add(tmp, X, Y))\n                    goto err;\n            } else {\n                if (BN_is_word(D, 2)) {\n                    if (!BN_lshift1(tmp, X))\n                        goto err;\n                } else if (BN_is_word(D, 4)) {\n                    if (!BN_lshift(tmp, X, 2))\n                        goto err;\n                } else if (D->top == 1) {\n                    if (!BN_copy(tmp, X))\n                        goto err;\n                    if (!BN_mul_word(tmp, D->d[0]))\n                        goto err;\n                } else {\n                    if (!BN_mul(tmp, D, X, ctx))\n                        goto err;\n                }\n                if (!BN_add(tmp, tmp, Y))\n                    goto err;\n            }\n\n            M = Y;              /* keep the BIGNUM object, the value does not\n                                 * matter */\n            Y = X;\n            X = tmp;\n            sign = -sign;\n        }\n    }\n\n    /*-\n     * The while loop (Euclid's algorithm) ends when\n     *      A == gcd(a,n);\n     * we have\n     *       sign*Y*a  ==  A  (mod |n|),\n     * where  Y  is non-negative.\n     */\n\n    if (sign < 0) {\n        if (!BN_sub(Y, n, Y))\n            goto err;\n    }\n    /* Now  Y*a  ==  A  (mod |n|).  */\n\n    if (BN_is_one(A)) {\n        /* Y*a == 1  (mod |n|) */\n        if (!Y->neg && BN_ucmp(Y, n) < 0) {\n            if (!BN_copy(R, Y))\n                goto err;\n        } else {\n            if (!BN_nnmod(R, Y, n, ctx))\n                goto err;\n        }\n    } else {\n        BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE);\n        goto err;\n    }\n    ret = R;\n err:\n    if ((ret == NULL) && (in == NULL))\n\t\t{\n\t\tif( R != NULL )\t\t/*  pcg */\n\t        BN_free(R);\n\t\t}\n    BN_CTX_end(ctx);\n    bn_check_top(ret);\n    return (ret);\n}\n\n/*\n * BN_mod_inverse_no_branch is a special version of BN_mod_inverse. It does\n * not contain branches that may leak sensitive information.\n */\nstatic BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,\n                                        const BIGNUM *a, const BIGNUM *n,\n                                        BN_CTX *ctx)\n{\n    BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;\n    BIGNUM local_A, local_B;\n    BIGNUM *pA, *pB;\n    BIGNUM *ret = NULL;\n    int sign;\n\n    bn_check_top(a);\n    bn_check_top(n);\n\n    BN_CTX_start(ctx);\n    A = BN_CTX_get(ctx);\n    B = BN_CTX_get(ctx);\n    X = BN_CTX_get(ctx);\n    D = BN_CTX_get(ctx);\n    M = BN_CTX_get(ctx);\n    Y = BN_CTX_get(ctx);\n    T = BN_CTX_get(ctx);\n    if ( A == NULL || B == NULL || X == NULL || D == NULL || M == NULL || \\\n\t\t Y == NULL || T == NULL)\t/* pcg */\n        goto err;\n\n    if (in == NULL)\n        R = BN_new();\n    else\n        R = in;\n    if (R == NULL)\n        goto err;\n\n    BN_one(X);\n    BN_zero(Y);\n    if (BN_copy(B, a) == NULL)\n        goto err;\n    if (BN_copy(A, n) == NULL)\n        goto err;\n    A->neg = 0;\n\n    if (B->neg || (BN_ucmp(B, A) >= 0)) {\n        /*\n         * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,\n         * BN_div_no_branch will be called eventually.\n         */\n        pB = &local_B;\n        local_B.flags = 0;\n        BN_with_flags(pB, B, BN_FLG_CONSTTIME);\n        if (!BN_nnmod(B, pB, A, ctx))\n            goto err;\n    }\n    sign = -1;\n    /*-\n     * From  B = a mod |n|,  A = |n|  it follows that\n     *\n     *      0 <= B < A,\n     *     -sign*X*a  ==  B   (mod |n|),\n     *      sign*Y*a  ==  A   (mod |n|).\n     */\n\n    while (!BN_is_zero(B)) {\n        BIGNUM *tmp;\n\n        /*-\n         *      0 < B < A,\n         * (*) -sign*X*a  ==  B   (mod |n|),\n         *      sign*Y*a  ==  A   (mod |n|)\n         */\n\n        /*\n         * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,\n         * BN_div_no_branch will be called eventually.\n         */\n        pA = &local_A;\n        local_A.flags = 0;\n        BN_with_flags(pA, A, BN_FLG_CONSTTIME);\n\n        /* (D, M) := (A/B, A%B) ... */\n        if (!BN_div(D, M, pA, B, ctx))\n            goto err;\n\n        /*-\n         * Now\n         *      A = D*B + M;\n         * thus we have\n         * (**)  sign*Y*a  ==  D*B + M   (mod |n|).\n         */\n\n        tmp = A;                /* keep the BIGNUM object, the value does not\n                                 * matter */\n\n        /* (A, B) := (B, A mod B) ... */\n        A = B;\n        B = M;\n        /* ... so we have  0 <= B < A  again */\n\n        /*-\n         * Since the former  M  is now  B  and the former  B  is now  A,\n         * (**) translates into\n         *       sign*Y*a  ==  D*A + B    (mod |n|),\n         * i.e.\n         *       sign*Y*a - D*A  ==  B    (mod |n|).\n         * Similarly, (*) translates into\n         *      -sign*X*a  ==  A          (mod |n|).\n         *\n         * Thus,\n         *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),\n         * i.e.\n         *        sign*(Y + D*X)*a  ==  B  (mod |n|).\n         *\n         * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at\n         *      -sign*X*a  ==  B   (mod |n|),\n         *       sign*Y*a  ==  A   (mod |n|).\n         * Note that  X  and  Y  stay non-negative all the time.\n         */\n\n        if (!BN_mul(tmp, D, X, ctx))\n            goto err;\n        if (!BN_add(tmp, tmp, Y))\n            goto err;\n\n        M = Y;                  /* keep the BIGNUM object, the value does not\n                                 * matter */\n        Y = X;\n        X = tmp;\n        sign = -sign;\n    }\n\n    /*-\n     * The while loop (Euclid's algorithm) ends when\n     *      A == gcd(a,n);\n     * we have\n     *       sign*Y*a  ==  A  (mod |n|),\n     * where  Y  is non-negative.\n     */\n\n    if (sign < 0) {\n        if (!BN_sub(Y, n, Y))\n            goto err;\n    }\n    /* Now  Y*a  ==  A  (mod |n|).  */\n\n    if (BN_is_one(A)) {\n        /* Y*a == 1  (mod |n|) */\n        if (!Y->neg && BN_ucmp(Y, n) < 0) {\n            if (!BN_copy(R, Y))\n                goto err;\n        } else {\n            if (!BN_nnmod(R, Y, n, ctx))\n                goto err;\n        }\n    } else {\n        BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH, BN_R_NO_INVERSE);\n        goto err;\n    }\n    ret = R;\n err:\n    if ((ret == NULL) && (in == NULL))\n\t\t{\n\t\tif( R != NULL )\t/* pcg */\n\t\t\tBN_free(R);\n\t\t}\n    BN_CTX_end(ctx);\n    bn_check_top(ret);\n    return (ret);\n}\n"
  },
  {
    "path": "deps/cl345/bn/bn_lcl.h",
    "content": "/* crypto/bn/bn_lcl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n/* ====================================================================\n * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n#ifndef HEADER_BN_LCL_H\n# define HEADER_BN_LCL_H\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"bn.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"bn/bn.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n/*-\n * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions\n *\n *\n * For window size 'w' (w >= 2) and a random 'b' bits exponent,\n * the number of multiplications is a constant plus on average\n *\n *    2^(w-1) + (b-w)/(w+1);\n *\n * here  2^(w-1)  is for precomputing the table (we actually need\n * entries only for windows that have the lowest bit set), and\n * (b-w)/(w+1)  is an approximation for the expected number of\n * w-bit windows, not counting the first one.\n *\n * Thus we should use\n *\n *    w >= 6  if        b > 671\n *     w = 5  if  671 > b > 239\n *     w = 4  if  239 > b >  79\n *     w = 3  if   79 > b >  23\n *    w <= 2  if   23 > b\n *\n * (with draws in between).  Very small exponents are often selected\n * with low Hamming weight, so we use  w = 1  for b <= 23.\n */\n# if 1\n#  define BN_window_bits_for_exponent_size(b) \\\n                ((b) > 671 ? 6 : \\\n                 (b) > 239 ? 5 : \\\n                 (b) >  79 ? 4 : \\\n                 (b) >  23 ? 3 : 1)\n# else\n/*\n * Old SSLeay/OpenSSL table. Maximum window size was 5, so this table differs\n * for b==1024; but it coincides for other interesting values (b==160,\n * b==512).\n */\n#  define BN_window_bits_for_exponent_size(b) \\\n                ((b) > 255 ? 5 : \\\n                 (b) > 127 ? 4 : \\\n                 (b) >  17 ? 3 : 1)\n# endif\n\n/*\n * BN_mod_exp_mont_conttime is based on the assumption that the L1 data cache\n * line width of the target processor is at least the following value.\n */\n# define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH      ( 64 )\n# define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK       (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)\n\n/*\n * Window sizes optimized for fixed window size modular exponentiation\n * algorithm (BN_mod_exp_mont_consttime). To achieve the security goals of\n * BN_mode_exp_mont_consttime, the maximum size of the window must not exceed\n * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). Window size thresholds are\n * defined for cache line sizes of 32 and 64, cache line sizes where\n * log_2(32)=5 and log_2(64)=6 respectively. A window size of 7 should only be\n * used on processors that have a 128 byte or greater cache line size.\n */\n# if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64\n\n#  define BN_window_bits_for_ctime_exponent_size(b) \\\n                ((b) > 937 ? 6 : \\\n                 (b) > 306 ? 5 : \\\n                 (b) >  89 ? 4 : \\\n                 (b) >  22 ? 3 : 1)\n#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE    (6)\n\n# elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32\n\n#  define BN_window_bits_for_ctime_exponent_size(b) \\\n                ((b) > 306 ? 5 : \\\n                 (b) >  89 ? 4 : \\\n                 (b) >  22 ? 3 : 1)\n#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE    (5)\n\n# endif\n\n/* Pentium pro 16,16,16,32,64 */\n/* Alpha       16,16,16,16.64 */\n# define BN_MULL_SIZE_NORMAL                     (16)/* 32 */\n# define BN_MUL_RECURSIVE_SIZE_NORMAL            (16)/* 32 less than */\n# define BN_SQR_RECURSIVE_SIZE_NORMAL            (16)/* 32 */\n# define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL        (32)/* 32 */\n# define BN_MONT_CTX_SET_SIZE_WORD               (64)/* 32 */\n\n/*\n * 2011-02-22 SMS. In various places, a size_t variable or a type cast to\n * size_t was used to perform integer-only operations on pointers.  This\n * failed on VMS with 64-bit pointers (CC /POINTER_SIZE = 64) because size_t\n * is still only 32 bits.  What's needed in these cases is an integer type\n * with the same size as a pointer, which size_t is not certain to be. The\n * only fix here is VMS-specific.\n */\n# if defined(OPENSSL_SYS_VMS)\n#  if __INITIAL_POINTER_SIZE == 64\n#   define PTR_SIZE_INT long long\n#  else                         /* __INITIAL_POINTER_SIZE == 64 */\n#   define PTR_SIZE_INT int\n#  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */\n# elif !defined(PTR_SIZE_INT)   /* defined(OPENSSL_SYS_VMS) */\n#  define PTR_SIZE_INT size_t\n# endif                         /* defined(OPENSSL_SYS_VMS) [else] */\n\n# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC)\n/*\n * BN_UMULT_HIGH section.\n *\n * No, I'm not trying to overwhelm you when stating that the\n * product of N-bit numbers is 2*N bits wide:-) No, I don't expect\n * you to be impressed when I say that if the compiler doesn't\n * support 2*N integer type, then you have to replace every N*N\n * multiplication with 4 (N/2)*(N/2) accompanied by some shifts\n * and additions which unavoidably results in severe performance\n * penalties. Of course provided that the hardware is capable of\n * producing 2*N result... That's when you normally start\n * considering assembler implementation. However! It should be\n * pointed out that some CPUs (most notably Alpha, PowerPC and\n * upcoming IA-64 family:-) provide *separate* instruction\n * calculating the upper half of the product placing the result\n * into a general purpose register. Now *if* the compiler supports\n * inline assembler, then it's not impossible to implement the\n * \"bignum\" routines (and have the compiler optimize 'em)\n * exhibiting \"native\" performance in C. That's what BN_UMULT_HIGH\n * macro is about:-)\n *\n *                                      <appro@fy.chalmers.se>\n */\n#  if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))\n#   if defined(__DECC)\n#    include <c_asm.h>\n#    define BN_UMULT_HIGH(a,b)   (BN_ULONG)asm(\"umulh %a0,%a1,%v0\",(a),(b))\n#   elif defined(__GNUC__) && __GNUC__>=2\n#    define BN_UMULT_HIGH(a,b)   ({      \\\n        register BN_ULONG ret;          \\\n        asm (\"umulh     %1,%2,%0\"       \\\n             : \"=r\"(ret)                \\\n             : \"r\"(a), \"r\"(b));         \\\n        ret;                    })\n#   endif                       /* compiler */\n//#  elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG)\n#  elif ( defined( _ARCH_PPC64 ) || defined( __powerpc64__ ) ) && defined(SIXTY_FOUR_BIT_LONG)\t/* pcg */\n#   if defined(__GNUC__) && __GNUC__>=2\n#    define BN_UMULT_HIGH(a,b)   ({      \\\n        register BN_ULONG ret;          \\\n        asm (\"mulhdu    %0,%1,%2\"       \\\n             : \"=r\"(ret)                \\\n             : \"r\"(a), \"r\"(b));         \\\n        ret;                    })\n#   endif                       /* compiler */\n#  elif (defined(__x86_64) || defined(__x86_64__)) && \\\n       (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))\n#   if defined(__GNUC__) && __GNUC__>=2\n#    define BN_UMULT_HIGH(a,b)   ({      \\\n        register BN_ULONG ret,discard;  \\\n        asm (\"mulq      %3\"             \\\n             : \"=a\"(discard),\"=d\"(ret)  \\\n             : \"a\"(a), \"g\"(b)           \\\n             : \"cc\");                   \\\n        ret;                    })\n#    define BN_UMULT_LOHI(low,high,a,b)  \\\n        asm (\"mulq      %3\"             \\\n                : \"=a\"(low),\"=d\"(high)  \\\n                : \"a\"(a),\"g\"(b)         \\\n                : \"cc\");\n#   endif\n#  elif (defined(_M_AMD64) || defined(_M_X64)) && defined(SIXTY_FOUR_BIT)\n#   if defined(_MSC_VER) && _MSC_VER>=1400\n#if 0\t/* Already defined by Microsoft - pcg */\nunsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b);\nunsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,\n                          unsigned __int64 *h);\n#    pragma intrinsic(__umulh,_umul128)\n#endif /* 0 */\n#    define BN_UMULT_HIGH(a,b)           __umulh((a),(b))\n#    define BN_UMULT_LOHI(low,high,a,b)  ((low)=_umul128((a),(b),&(high)))\n#   endif\n#  elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG))\n#   if defined(__GNUC__) && __GNUC__>=2\n#    if __GNUC__>4 || (__GNUC__>=4 && __GNUC_MINOR__>=4)\n                                     /* \"h\" constraint is no more since 4.4 */\n#     define BN_UMULT_HIGH(a,b)          (((__uint128_t)(a)*(b))>>64)\n#     define BN_UMULT_LOHI(low,high,a,b) ({     \\\n        __uint128_t ret=(__uint128_t)(a)*(b);   \\\n        (high)=ret>>64; (low)=ret;       })\n#    else\n#     define BN_UMULT_HIGH(a,b) ({      \\\n        register BN_ULONG ret;          \\\n        asm (\"dmultu    %1,%2\"          \\\n             : \"=h\"(ret)                \\\n             : \"r\"(a), \"r\"(b) : \"l\");   \\\n        ret;                    })\n#     define BN_UMULT_LOHI(low,high,a,b)\\\n        asm (\"dmultu    %2,%3\"          \\\n             : \"=l\"(low),\"=h\"(high)     \\\n             : \"r\"(a), \"r\"(b));\n#    endif\n#   endif\n#  elif defined(__aarch64__) && defined(SIXTY_FOUR_BIT_LONG)\n#   if defined(__GNUC__) && __GNUC__>=2\n#    define BN_UMULT_HIGH(a,b)   ({      \\\n        register BN_ULONG ret;          \\\n        asm (\"umulh     %0,%1,%2\"       \\\n             : \"=r\"(ret)                \\\n             : \"r\"(a), \"r\"(b));         \\\n        ret;                    })\n#   endif\n#  endif                        /* cpu */\n# endif                         /* OPENSSL_NO_ASM */\n\n/* As a more portable, and universal, alternative to the above, if the \n   compiler supports 128-bit values (e.g. GCC/Clang/ICC) we build\n   BN_UMULT_LOHI() using those and let the compiler sort it out - pcg */\n\n#if defined( __SIZEOF_INT128__ )\n  #if defined( BN_UMULT_LOHI )\n\t#undef BN_UMULT_LOHI\n  #endif /* BN_UMULT_LOHI */\n  #define BN_UMULT_LOHI( low, high, a, b ) \\\n\t{ \\\n\tunsigned __int128 result = ( unsigned __int128 ) ( a ) * ( b ); \\\n\t( low ) = ( BN_ULONG ) result; \\\n\t( high ) = result >> 64; \\\n\t}\n#endif /* __SIZEOF_INT128__ */\n\n/*************************************************************\n * Using the long long type\n */\n# define Lw(t)    (((BN_ULONG)(t))&BN_MASK2)\n# define Hw(t)    (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)\n\n# ifdef BN_DEBUG_RAND\n#  define bn_clear_top2max(a) \\\n        { \\\n        int      ind = (a)->dmax - (a)->top; \\\n        BN_ULONG *ftl = &(a)->d[(a)->top-1]; \\\n        for (; ind != 0; ind--) \\\n                *(++ftl) = 0x0; \\\n        }\n# else\n#  define bn_clear_top2max(a)\n# endif\n\n# ifdef BN_LLONG\n#  define mul_add(r,a,w,c) { \\\n        BN_ULLONG t; \\\n        t=(BN_ULLONG)w * (a) + (r) + (c); \\\n        (r)= Lw(t); \\\n        (c)= Hw(t); \\\n        }\n\n#  define mul(r,a,w,c) { \\\n        BN_ULLONG t; \\\n        t=(BN_ULLONG)w * (a) + (c); \\\n        (r)= Lw(t); \\\n        (c)= Hw(t); \\\n        }\n\n#  define sqr(r0,r1,a) { \\\n        BN_ULLONG t; \\\n        t=(BN_ULLONG)(a)*(a); \\\n        (r0)=Lw(t); \\\n        (r1)=Hw(t); \\\n        }\n\n# elif defined(BN_UMULT_LOHI)\n#  define mul_add(r,a,w,c) {              \\\n        BN_ULONG high,low,ret,tmp=(a);  \\\n        ret =  (r);                     \\\n        BN_UMULT_LOHI(low,high,w,tmp);  \\\n        ret += (c);                     \\\n        (c) =  (ret<(c))?1:0;           \\\n        (c) += high;                    \\\n        ret += low;                     \\\n        (c) += (ret<low)?1:0;           \\\n        (r) =  ret;                     \\\n        }\n\n#  define mul(r,a,w,c)    {               \\\n        BN_ULONG high,low,ret,ta=(a);   \\\n        BN_UMULT_LOHI(low,high,w,ta);   \\\n        ret =  low + (c);               \\\n        (c) =  high;                    \\\n        (c) += (ret<low)?1:0;           \\\n        (r) =  ret;                     \\\n        }\n\n#  define sqr(r0,r1,a)    {               \\\n        BN_ULONG tmp=(a);               \\\n        BN_UMULT_LOHI(r0,r1,tmp,tmp);   \\\n        }\n\n# elif defined(BN_UMULT_HIGH)\n#  define mul_add(r,a,w,c) {              \\\n        BN_ULONG high,low,ret,tmp=(a);  \\\n        ret =  (r);                     \\\n        high=  BN_UMULT_HIGH(w,tmp);    \\\n        ret += (c);                     \\\n        low =  (w) * tmp;               \\\n        (c) =  (ret<(c))?1:0;           \\\n        (c) += high;                    \\\n        ret += low;                     \\\n        (c) += (ret<low)?1:0;           \\\n        (r) =  ret;                     \\\n        }\n\n#  define mul(r,a,w,c)    {               \\\n        BN_ULONG high,low,ret,ta=(a);   \\\n        low =  (w) * ta;                \\\n        high=  BN_UMULT_HIGH(w,ta);     \\\n        ret =  low + (c);               \\\n        (c) =  high;                    \\\n        (c) += (ret<low)?1:0;           \\\n        (r) =  ret;                     \\\n        }\n\n#  define sqr(r0,r1,a)    {               \\\n        BN_ULONG tmp=(a);               \\\n        (r0) = tmp * tmp;               \\\n        (r1) = BN_UMULT_HIGH(tmp,tmp);  \\\n        }\n\n# else\n/*************************************************************\n * No long long type\n */\n\n#  define LBITS(a)        ((a)&BN_MASK2l)\n#  define HBITS(a)        (((a)>>BN_BITS4)&BN_MASK2l)\n#  define L2HBITS(a)      (((a)<<BN_BITS4)&BN_MASK2)\n\n#  define LLBITS(a)       ((a)&BN_MASKl)\n#  define LHBITS(a)       (((a)>>BN_BITS2)&BN_MASKl)\n#  define LL2HBITS(a)     ((BN_ULLONG)((a)&BN_MASKl)<<BN_BITS2)\n\n#  define mul64(l,h,bl,bh) \\\n        { \\\n        BN_ULONG m,m1,lt,ht; \\\n \\\n        lt=l; \\\n        ht=h; \\\n        m =(bh)*(lt); \\\n        lt=(bl)*(lt); \\\n        m1=(bl)*(ht); \\\n        ht =(bh)*(ht); \\\n        m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS((BN_ULONG)1); \\\n        ht+=HBITS(m); \\\n        m1=L2HBITS(m); \\\n        lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \\\n        (l)=lt; \\\n        (h)=ht; \\\n        }\n\n#  define sqr64(lo,ho,in) \\\n        { \\\n        BN_ULONG l,h,m; \\\n \\\n        h=(in); \\\n        l=LBITS(h); \\\n        h=HBITS(h); \\\n        m =(l)*(h); \\\n        l*=l; \\\n        h*=h; \\\n        h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \\\n        m =(m&BN_MASK2l)<<(BN_BITS4+1); \\\n        l=(l+m)&BN_MASK2; if (l < m) h++; \\\n        (lo)=l; \\\n        (ho)=h; \\\n        }\n\n#  define mul_add(r,a,bl,bh,c) { \\\n        BN_ULONG l,h; \\\n \\\n        h= (a); \\\n        l=LBITS(h); \\\n        h=HBITS(h); \\\n        mul64(l,h,(bl),(bh)); \\\n \\\n        /* non-multiply part */ \\\n        l=(l+(c))&BN_MASK2; if (l < (c)) h++; \\\n        (c)=(r); \\\n        l=(l+(c))&BN_MASK2; if (l < (c)) h++; \\\n        (c)=h&BN_MASK2; \\\n        (r)=l; \\\n        }\n\n#  define mul(r,a,bl,bh,c) { \\\n        BN_ULONG l,h; \\\n \\\n        h= (a); \\\n        l=LBITS(h); \\\n        h=HBITS(h); \\\n        mul64(l,h,(bl),(bh)); \\\n \\\n        /* non-multiply part */ \\\n        l+=(c); if ((l&BN_MASK2) < (c)) h++; \\\n        (c)=h&BN_MASK2; \\\n        (r)=l&BN_MASK2; \\\n        }\n# endif                         /* !BN_LLONG */\n\n# if defined(OPENSSL_DOING_MAKEDEPEND) && defined(OPENSSL_FIPS)\n#  undef bn_div_words\n# endif\n\nvoid bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, int nb);\t/* const - pcg */\nvoid bn_mul_comba8(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b);\t/* const - pcg */\nvoid bn_mul_comba4(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b);\t/* const - pcg */\nvoid bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);\nvoid bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);\nvoid bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);\n#if 0\t/* pcg */\nint bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);\nint bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);\n#endif /* 0 */\nvoid bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2,\t/* const - pcg */\n                      int dna, int dnb, BN_ULONG *t);\nvoid bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\t\t/* const - pcg */\n                           int n, int tna, int tnb, BN_ULONG *t);\nvoid bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t);\nvoid bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);\nvoid bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,\n                          BN_ULONG *t);\nvoid bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,\n                 BN_ULONG *t);\nBN_ULONG bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\n                           int cl, int dl);\nBN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,\n                           int cl, int dl);\nint bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                const BN_ULONG *np, const BN_ULONG *n0, int num);\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/bn/bn_mul.c",
    "content": "/* crypto/bn/bn_mul.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include <stdio.h>\n#include <assert.h>\n\n/* Changes for cryptlib - pcg */\n\n/* Removed NDEBUG redefinition */\n/* NB: See also SunPro compiler bug fix at line 475 */\n\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef BN_ASM\t/* Implies use of x86 asm code */\n  #define OPENSSL_BN_ASM_PART_WORDS\n#endif /* x86 asm code */\n\n/* End changes for cryptlib - pcg */\n\n#if defined(OPENSSL_NO_ASM) || !defined(OPENSSL_BN_ASM_PART_WORDS)\n/*\n * Here follows specialised variants of bn_add_words() and bn_sub_words().\n * They have the property performing operations on arrays of different sizes.\n * The sizes of those arrays is expressed through cl, which is the common\n * length ( basicall, min(len(a),len(b)) ), and dl, which is the delta\n * between the two lengths, calculated as len(a)-len(b). All lengths are the\n * number of BN_ULONGs...  For the operations that require a result array as\n * parameter, it must have the length cl+abs(dl). These functions should\n * probably end up in bn_asm.c as soon as there are assembler counterparts\n * for the systems that use assembler files.\n */\n\nBN_ULONG bn_sub_part_words(BN_ULONG *r,\n                           const BN_ULONG *a, const BN_ULONG *b,\n                           int cl, int dl)\n{\n    BN_ULONG c, t;\n\n    assert(cl >= 0);\n    c = bn_sub_words(r, a, b, cl);\n\n    if (dl == 0)\n        return c;\n\n    r += cl;\n    a += cl;\n    b += cl;\n\n    if (dl < 0) {\n# ifdef BN_COUNT\n        fprintf(stderr, \"  bn_sub_part_words %d + %d (dl < 0, c = %d)\\n\", cl,\n                dl, c);\n# endif\n        for (;;) {\n            t = b[0];\n            r[0] = (0 - t - c) & BN_MASK2;\n            if (t != 0)\n                c = 1;\n            if (++dl >= 0)\n                break;\n\n            t = b[1];\n            r[1] = (0 - t - c) & BN_MASK2;\n            if (t != 0)\n                c = 1;\n            if (++dl >= 0)\n                break;\n\n            t = b[2];\n            r[2] = (0 - t - c) & BN_MASK2;\n            if (t != 0)\n                c = 1;\n            if (++dl >= 0)\n                break;\n\n            t = b[3];\n            r[3] = (0 - t - c) & BN_MASK2;\n            if (t != 0)\n                c = 1;\n            if (++dl >= 0)\n                break;\n\n            b += 4;\n            r += 4;\n        }\n    } else {\n        int save_dl = dl;\n# ifdef BN_COUNT\n        fprintf(stderr, \"  bn_sub_part_words %d + %d (dl > 0, c = %d)\\n\", cl,\n                dl, c);\n# endif\n        while (c) {\n            t = a[0];\n            r[0] = (t - c) & BN_MASK2;\n            if (t != 0)\n                c = 0;\n            if (--dl <= 0)\n                break;\n\n            t = a[1];\n            r[1] = (t - c) & BN_MASK2;\n            if (t != 0)\n                c = 0;\n            if (--dl <= 0)\n                break;\n\n            t = a[2];\n            r[2] = (t - c) & BN_MASK2;\n            if (t != 0)\n                c = 0;\n            if (--dl <= 0)\n                break;\n\n            t = a[3];\n            r[3] = (t - c) & BN_MASK2;\n            if (t != 0)\n                c = 0;\n            if (--dl <= 0)\n                break;\n\n            save_dl = dl;\n            a += 4;\n            r += 4;\n        }\n        if (dl > 0) {\n# ifdef BN_COUNT\n            fprintf(stderr, \"  bn_sub_part_words %d + %d (dl > 0, c == 0)\\n\",\n                    cl, dl);\n# endif\n            if (save_dl > dl) {\n                switch (save_dl - dl) {\n                case 1:\n                    r[1] = a[1];\n                    if (--dl <= 0)\n                        break;\n                case 2:\n                    r[2] = a[2];\n                    if (--dl <= 0)\n                        break;\n                case 3:\n                    r[3] = a[3];\n                    if (--dl <= 0)\n                        break;\n                }\n                a += 4;\n                r += 4;\n            }\n        }\n        if (dl > 0) {\n# ifdef BN_COUNT\n            fprintf(stderr, \"  bn_sub_part_words %d + %d (dl > 0, copy)\\n\",\n                    cl, dl);\n# endif\n            for (;;) {\n                r[0] = a[0];\n                if (--dl <= 0)\n                    break;\n                r[1] = a[1];\n                if (--dl <= 0)\n                    break;\n                r[2] = a[2];\n                if (--dl <= 0)\n                    break;\n                r[3] = a[3];\n                if (--dl <= 0)\n                    break;\n\n                a += 4;\n                r += 4;\n            }\n        }\n    }\n    return c;\n}\n#endif\n\nBN_ULONG bn_add_part_words(BN_ULONG *r,\n                           const BN_ULONG *a, const BN_ULONG *b,\n                           int cl, int dl)\n{\n    BN_ULONG c, l, t;\n\n    assert(cl >= 0);\n    c = bn_add_words(r, a, b, cl);\n\n    if (dl == 0)\n        return c;\n\n    r += cl;\n    a += cl;\n    b += cl;\n\n    if (dl < 0) {\n        int save_dl = dl;\n#ifdef BN_COUNT\n        fprintf(stderr, \"  bn_add_part_words %d + %d (dl < 0, c = %d)\\n\", cl,\n                dl, c);\n#endif\n        while (c) {\n            l = (c + b[0]) & BN_MASK2;\n            c = (l < c);\n            r[0] = l;\n            if (++dl >= 0)\n                break;\n\n            l = (c + b[1]) & BN_MASK2;\n            c = (l < c);\n            r[1] = l;\n            if (++dl >= 0)\n                break;\n\n            l = (c + b[2]) & BN_MASK2;\n            c = (l < c);\n            r[2] = l;\n            if (++dl >= 0)\n                break;\n\n            l = (c + b[3]) & BN_MASK2;\n            c = (l < c);\n            r[3] = l;\n            if (++dl >= 0)\n                break;\n\n            save_dl = dl;\n            b += 4;\n            r += 4;\n        }\n        if (dl < 0) {\n#ifdef BN_COUNT\n            fprintf(stderr, \"  bn_add_part_words %d + %d (dl < 0, c == 0)\\n\",\n                    cl, dl);\n#endif\n            if (save_dl < dl) {\n                switch (dl - save_dl) {\n                case 1:\n                    r[1] = b[1];\n                    if (++dl >= 0)\n                        break;\n                case 2:\n                    r[2] = b[2];\n                    if (++dl >= 0)\n                        break;\n                case 3:\n                    r[3] = b[3];\n                    if (++dl >= 0)\n                        break;\n                }\n                b += 4;\n                r += 4;\n            }\n        }\n        if (dl < 0) {\n#ifdef BN_COUNT\n            fprintf(stderr, \"  bn_add_part_words %d + %d (dl < 0, copy)\\n\",\n                    cl, dl);\n#endif\n            for (;;) {\n                r[0] = b[0];\n                if (++dl >= 0)\n                    break;\n                r[1] = b[1];\n                if (++dl >= 0)\n                    break;\n                r[2] = b[2];\n                if (++dl >= 0)\n                    break;\n                r[3] = b[3];\n                if (++dl >= 0)\n                    break;\n\n                b += 4;\n                r += 4;\n            }\n        }\n    } else {\n        int save_dl = dl;\n#ifdef BN_COUNT\n        fprintf(stderr, \"  bn_add_part_words %d + %d (dl > 0)\\n\", cl, dl);\n#endif\n        while (c) {\n            t = (a[0] + c) & BN_MASK2;\n            c = (t < c);\n            r[0] = t;\n            if (--dl <= 0)\n                break;\n\n            t = (a[1] + c) & BN_MASK2;\n            c = (t < c);\n            r[1] = t;\n            if (--dl <= 0)\n                break;\n\n            t = (a[2] + c) & BN_MASK2;\n            c = (t < c);\n            r[2] = t;\n            if (--dl <= 0)\n                break;\n\n            t = (a[3] + c) & BN_MASK2;\n            c = (t < c);\n            r[3] = t;\n            if (--dl <= 0)\n                break;\n\n            save_dl = dl;\n            a += 4;\n            r += 4;\n        }\n#ifdef BN_COUNT\n        fprintf(stderr, \"  bn_add_part_words %d + %d (dl > 0, c == 0)\\n\", cl,\n                dl);\n#endif\n        if (dl > 0) {\n            if (save_dl > dl) {\n                switch (save_dl - dl) {\n                case 1:\n                    r[1] = a[1];\n                    if (--dl <= 0)\n                        break;\n                case 2:\n                    r[2] = a[2];\n                    if (--dl <= 0)\n                        break;\n                case 3:\n                    r[3] = a[3];\n                    if (--dl <= 0)\n                        break;\n                }\n                a += 4;\n                r += 4;\n            }\n        }\n        if (dl > 0) {\n#ifdef BN_COUNT\n            fprintf(stderr, \"  bn_add_part_words %d + %d (dl > 0, copy)\\n\",\n                    cl, dl);\n#endif\n            for (;;) {\n                r[0] = a[0];\n                if (--dl <= 0)\n                    break;\n                r[1] = a[1];\n                if (--dl <= 0)\n                    break;\n                r[2] = a[2];\n                if (--dl <= 0)\n                    break;\n                r[3] = a[3];\n                if (--dl <= 0)\n                    break;\n\n                a += 4;\n                r += 4;\n            }\n        }\n    }\n    return c;\n}\n\n#ifdef BN_RECURSION\n/*\n * Karatsuba recursive multiplication algorithm (cf. Knuth, The Art of\n * Computer Programming, Vol. 2)\n */\n\n/*-\n * r is 2*n2 words in size,\n * a and b are both n2 words in size.\n * n2 must be a power of 2.\n * We multiply and return the result.\n * t must be 2*n2 words in size\n * We calculate\n * a[0]*b[0]\n * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])\n * a[1]*b[1]\n */\n/* dnX may not be positive, but n2/2+dnX has to be */\nvoid bn_mul_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n2,\n                      int dna, int dnb, BN_ULONG *t)\t/* const - pcg */\n{\n    int n = n2 / 2, c1, c2;\n    int tna = n + dna, tnb = n + dnb;\n    unsigned int neg, zero;\n    BN_ULONG ln, lo, *p;\n\n# ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_recursive %d%+d * %d%+d\\n\", n2, dna, n2, dnb);\n# endif\n# ifdef BN_MUL_COMBA\n#  if 0\n    if (n2 == 4) {\n        bn_mul_comba4(r, a, b);\n        return;\n    }\n#  endif\n    /*\n     * Only call bn_mul_comba 8 if n2 == 8 and the two arrays are complete\n     * [steve]\n     */\n    if (n2 == 8 && dna == 0 && dnb == 0) {\n        bn_mul_comba8(r, a, b);\n        return;\n    }\n# endif                         /* BN_MUL_COMBA */\n    /* Else do normal multiply */\n    if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {\n        bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);\n        if ((dna + dnb) < 0)\n            memset(&r[2 * n2 + dna + dnb], 0,\n                   sizeof(BN_ULONG) * -(dna + dnb));\n        return;\n    }\n    /* r=(a[0]-a[1])*(b[1]-b[0]) */\n    c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);\n    c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);\n#if defined __SUNPRO_C\t/* pcg */\n\tasm(\"\");\n#endif /* Sun compiler bug */\n    zero = neg = 0;\n    switch (c1 * 3 + c2) {\n    case -4:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */\n        break;\n    case -3:\n        zero = 1;\n        break;\n    case -2:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */\n        neg = 1;\n        break;\n    case -1:\n    case 0:\n    case 1:\n        zero = 1;\n        break;\n    case 2:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */\n        neg = 1;\n        break;\n    case 3:\n        zero = 1;\n        break;\n    case 4:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna);\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);\n        break;\n    }\n\n# ifdef BN_MUL_COMBA\n    if (n == 4 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba4 could take\n                                           * extra args to do this well */\n        if (!zero)\n            bn_mul_comba4(&(t[n2]), t, &(t[n]));\n        else\n            memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));\n\n        bn_mul_comba4(r, a, b);\n        bn_mul_comba4(&(r[n2]), &(a[n]), &(b[n]));\n    } else if (n == 8 && dna == 0 && dnb == 0) { /* XXX: bn_mul_comba8 could\n                                                  * take extra args to do\n                                                  * this well */\n        if (!zero)\n            bn_mul_comba8(&(t[n2]), t, &(t[n]));\n        else\n            memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));\n\n        bn_mul_comba8(r, a, b);\n        bn_mul_comba8(&(r[n2]), &(a[n]), &(b[n]));\n    } else\n# endif                         /* BN_MUL_COMBA */\n    {\n        p = &(t[n2 * 2]);\n        if (!zero)\n            bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);\n        else\n            memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));\n        bn_mul_recursive(r, a, b, n, 0, 0, p);\n        bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);\n    }\n\n    /*-\n     * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign\n     * r[10] holds (a[0]*b[0])\n     * r[32] holds (b[1]*b[1])\n     */\n\n    c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));\n\n    if (neg) {                  /* if t[32] is negative */\n        c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));\n    } else {\n        /* Might have a carry */\n        c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));\n    }\n\n    /*-\n     * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])\n     * r[10] holds (a[0]*b[0])\n     * r[32] holds (b[1]*b[1])\n     * c1 holds the carry bits\n     */\n    c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));\n    if (c1) {\n        p = &(r[n + n2]);\n        lo = *p;\n        ln = (lo + c1) & BN_MASK2;\n        *p = ln;\n\n        /*\n         * The overflow will stop before we over write words we should not\n         * overwrite\n         */\n        if (ln < (BN_ULONG)c1) {\n            do {\n                p++;\n                lo = *p;\n                ln = (lo + 1) & BN_MASK2;\n                *p = ln;\n            } while (ln == 0);\n        }\n    }\n}\n\n/*\n * n+tn is the word length t needs to be n*4 is size, as does r\n */\n/* tnX may not be negative but less than n */\nvoid bn_mul_part_recursive(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n,\n                           int tna, int tnb, BN_ULONG *t)\t/* const - pcg */\n{\n    int i, j, n2 = n * 2;\n    int c1, c2, neg;\n    BN_ULONG ln, lo, *p;\n\n# ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_part_recursive (%d%+d) * (%d%+d)\\n\",\n            n, tna, n, tnb);\n# endif\n    if (n < 8) {\n        bn_mul_normal(r, a, n + tna, b, n + tnb);\n        return;\n    }\n\n    /* r=(a[0]-a[1])*(b[1]-b[0]) */\n    c1 = bn_cmp_part_words(a, &(a[n]), tna, n - tna);\n    c2 = bn_cmp_part_words(&(b[n]), b, tnb, tnb - n);\n    neg = 0;\n    switch (c1 * 3 + c2) {\n    case -4:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */\n        break;\n    case -3:\n        /* break; */\n    case -2:\n        bn_sub_part_words(t, &(a[n]), a, tna, tna - n); /* - */\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n); /* + */\n        neg = 1;\n        break;\n    case -1:\n    case 0:\n    case 1:\n        /* break; */\n    case 2:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna); /* + */\n        bn_sub_part_words(&(t[n]), b, &(b[n]), tnb, n - tnb); /* - */\n        neg = 1;\n        break;\n    case 3:\n        /* break; */\n    case 4:\n        bn_sub_part_words(t, a, &(a[n]), tna, n - tna);\n        bn_sub_part_words(&(t[n]), &(b[n]), b, tnb, tnb - n);\n        break;\n    }\n    /*\n     * The zero case isn't yet implemented here. The speedup would probably\n     * be negligible.\n     */\n# if 0\n    if (n == 4) {\n        bn_mul_comba4(&(t[n2]), t, &(t[n]));\n        bn_mul_comba4(r, a, b);\n        bn_mul_normal(&(r[n2]), &(a[n]), tn, &(b[n]), tn);\n        memset(&(r[n2 + tn * 2]), 0, sizeof(BN_ULONG) * (n2 - tn * 2));\n    } else\n# endif\n    if (n == 8) {\n        bn_mul_comba8(&(t[n2]), t, &(t[n]));\n        bn_mul_comba8(r, a, b);\n        bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);\n        memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));\n    } else {\n        p = &(t[n2 * 2]);\n        bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);\n        bn_mul_recursive(r, a, b, n, 0, 0, p);\n        i = n / 2;\n        /*\n         * If there is only a bottom half to the number, just do it\n         */\n        if (tna > tnb)\n            j = tna - i;\n        else\n            j = tnb - i;\n        if (j == 0) {\n            bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]),\n                             i, tna - i, tnb - i, p);\n            memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));\n        } else if (j > 0) {     /* eg, n == 16, i == 8 and tn == 11 */\n            bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]),\n                                  i, tna - i, tnb - i, p);\n            memset(&(r[n2 + tna + tnb]), 0,\n                   sizeof(BN_ULONG) * (n2 - tna - tnb));\n        } else {                /* (j < 0) eg, n == 16, i == 8 and tn == 5 */\n\n            memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);\n            if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL\n                && tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {\n                bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);\n            } else {\n                for (;;) {\n                    i /= 2;\n                    /*\n                     * these simplified conditions work exclusively because\n                     * difference between tna and tnb is 1 or 0\n                     */\n                    if (i < tna || i < tnb) {\n                        bn_mul_part_recursive(&(r[n2]),\n                                              &(a[n]), &(b[n]),\n                                              i, tna - i, tnb - i, p);\n                        break;\n                    } else if (i == tna || i == tnb) {\n                        bn_mul_recursive(&(r[n2]),\n                                         &(a[n]), &(b[n]),\n                                         i, tna - i, tnb - i, p);\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    /*-\n     * t[32] holds (a[0]-a[1])*(b[1]-b[0]), c1 is the sign\n     * r[10] holds (a[0]*b[0])\n     * r[32] holds (b[1]*b[1])\n     */\n\n    c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));\n\n    if (neg) {                  /* if t[32] is negative */\n        c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));\n    } else {\n        /* Might have a carry */\n        c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), t, n2));\n    }\n\n    /*-\n     * t[32] holds (a[0]-a[1])*(b[1]-b[0])+(a[0]*b[0])+(a[1]*b[1])\n     * r[10] holds (a[0]*b[0])\n     * r[32] holds (b[1]*b[1])\n     * c1 holds the carry bits\n     */\n    c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));\n    if (c1) {\n        p = &(r[n + n2]);\n        lo = *p;\n        ln = (lo + c1) & BN_MASK2;\n        *p = ln;\n\n        /*\n         * The overflow will stop before we over write words we should not\n         * overwrite\n         */\n        if (ln < (BN_ULONG)c1) {\n            do {\n                p++;\n                lo = *p;\n                ln = (lo + 1) & BN_MASK2;\n                *p = ln;\n            } while (ln == 0);\n        }\n    }\n}\n\n/*-\n * a and b must be the same size, which is n2.\n * r needs to be n2 words and t needs to be n2*2\n */\nvoid bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,\n                          BN_ULONG *t)\n{\n    int n = n2 / 2;\n\n# ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_low_recursive %d * %d\\n\", n2, n2);\n# endif\n\n    bn_mul_recursive(r, a, b, n, 0, 0, &(t[0]));\n    if (n >= BN_MUL_LOW_RECURSIVE_SIZE_NORMAL) {\n        bn_mul_low_recursive(&(t[0]), &(a[0]), &(b[n]), n, &(t[n2]));\n        bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);\n        bn_mul_low_recursive(&(t[0]), &(a[n]), &(b[0]), n, &(t[n2]));\n        bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);\n    } else {\n        bn_mul_low_normal(&(t[0]), &(a[0]), &(b[n]), n);\n        bn_mul_low_normal(&(t[n]), &(a[n]), &(b[0]), n);\n        bn_add_words(&(r[n]), &(r[n]), &(t[0]), n);\n        bn_add_words(&(r[n]), &(r[n]), &(t[n]), n);\n    }\n}\n\n/*-\n * a and b must be the same size, which is n2.\n * r needs to be n2 words and t needs to be n2*2\n * l is the low words of the output.\n * t needs to be n2*3\n */\nvoid bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,\n                 BN_ULONG *t)\n{\n    int i, n;\n    int c1, c2;\n    int neg, oneg, zero;\n    BN_ULONG ll, lc, *lp, *mp;\n\n# ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_high %d * %d\\n\", n2, n2);\n# endif\n    n = n2 / 2;\n\n    /* Calculate (al-ah)*(bh-bl) */\n    neg = zero = 0;\n    c1 = bn_cmp_words(&(a[0]), &(a[n]), n);\n    c2 = bn_cmp_words(&(b[n]), &(b[0]), n);\n    switch (c1 * 3 + c2) {\n    case -4:\n        bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);\n        bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);\n        break;\n    case -3:\n        zero = 1;\n        break;\n    case -2:\n        bn_sub_words(&(r[0]), &(a[n]), &(a[0]), n);\n        bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);\n        neg = 1;\n        break;\n    case -1:\n    case 0:\n    case 1:\n        zero = 1;\n        break;\n    case 2:\n        bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);\n        bn_sub_words(&(r[n]), &(b[0]), &(b[n]), n);\n        neg = 1;\n        break;\n    case 3:\n        zero = 1;\n        break;\n    case 4:\n        bn_sub_words(&(r[0]), &(a[0]), &(a[n]), n);\n        bn_sub_words(&(r[n]), &(b[n]), &(b[0]), n);\n        break;\n    }\n\n    oneg = neg;\n    /* t[10] = (a[0]-a[1])*(b[1]-b[0]) */\n    /* r[10] = (a[1]*b[1]) */\n# ifdef BN_MUL_COMBA\n    if (n == 8) {\n        bn_mul_comba8(&(t[0]), &(r[0]), &(r[n]));\n        bn_mul_comba8(r, &(a[n]), &(b[n]));\n    } else\n# endif\n    {\n        bn_mul_recursive(&(t[0]), &(r[0]), &(r[n]), n, 0, 0, &(t[n2]));\n        bn_mul_recursive(r, &(a[n]), &(b[n]), n, 0, 0, &(t[n2]));\n    }\n\n    /*-\n     * s0 == low(al*bl)\n     * s1 == low(ah*bh)+low((al-ah)*(bh-bl))+low(al*bl)+high(al*bl)\n     * We know s0 and s1 so the only unknown is high(al*bl)\n     * high(al*bl) == s1 - low(ah*bh+s0+(al-ah)*(bh-bl))\n     * high(al*bl) == s1 - (r[0]+l[0]+t[0])\n     */\n    if (l != NULL) {\n        lp = &(t[n2 + n]);\n        c1 = (int)(bn_add_words(lp, &(r[0]), &(l[0]), n));\n    } else {\n        c1 = 0;\n        lp = &(r[0]);\n    }\n\n    if (neg)\n        neg = (int)(bn_sub_words(&(t[n2]), lp, &(t[0]), n));\n    else {\n        bn_add_words(&(t[n2]), lp, &(t[0]), n);\n        neg = 0;\n    }\n\n    if (l != NULL) {\n        bn_sub_words(&(t[n2 + n]), &(l[n]), &(t[n2]), n);\n    } else {\n        lp = &(t[n2 + n]);\n        mp = &(t[n2]);\n        for (i = 0; i < n; i++)\n            lp[i] = ((~mp[i]) + 1) & BN_MASK2;\n    }\n\n    /*-\n     * s[0] = low(al*bl)\n     * t[3] = high(al*bl)\n     * t[10] = (a[0]-a[1])*(b[1]-b[0]) neg is the sign\n     * r[10] = (a[1]*b[1])\n     */\n    /*-\n     * R[10] = al*bl\n     * R[21] = al*bl + ah*bh + (a[0]-a[1])*(b[1]-b[0])\n     * R[32] = ah*bh\n     */\n    /*-\n     * R[1]=t[3]+l[0]+r[0](+-)t[0] (have carry/borrow)\n     * R[2]=r[0]+t[3]+r[1](+-)t[1] (have carry/borrow)\n     * R[3]=r[1]+(carry/borrow)\n     */\n    if (l != NULL) {\n        lp = &(t[n2]);\n        c1 = (int)(bn_add_words(lp, &(t[n2 + n]), &(l[0]), n));\n    } else {\n        lp = &(t[n2 + n]);\n        c1 = 0;\n    }\n    c1 += (int)(bn_add_words(&(t[n2]), lp, &(r[0]), n));\n    if (oneg)\n        c1 -= (int)(bn_sub_words(&(t[n2]), &(t[n2]), &(t[0]), n));\n    else\n        c1 += (int)(bn_add_words(&(t[n2]), &(t[n2]), &(t[0]), n));\n\n    c2 = (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n2 + n]), n));\n    c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(r[n]), n));\n    if (oneg)\n        c2 -= (int)(bn_sub_words(&(r[0]), &(r[0]), &(t[n]), n));\n    else\n        c2 += (int)(bn_add_words(&(r[0]), &(r[0]), &(t[n]), n));\n\n    if (c1 != 0) {              /* Add starting at r[0], could be +ve or -ve */\n        i = 0;\n        if (c1 > 0) {\n            lc = c1;\n            do {\n                ll = (r[i] + lc) & BN_MASK2;\n                r[i++] = ll;\n                lc = (lc > ll);\n            } while (lc);\n        } else {\n            lc = -c1;\n            do {\n                ll = r[i];\n                r[i++] = (ll - lc) & BN_MASK2;\n                lc = (lc > ll);\n            } while (lc);\n        }\n    }\n    if (c2 != 0) {              /* Add starting at r[1] */\n        i = n;\n        if (c2 > 0) {\n            lc = c2;\n            do {\n                ll = (r[i] + lc) & BN_MASK2;\n                r[i++] = ll;\n                lc = (lc > ll);\n            } while (lc);\n        } else {\n            lc = -c2;\n            do {\n                ll = r[i];\n                r[i++] = (ll - lc) & BN_MASK2;\n                lc = (lc > ll);\n            } while (lc);\n        }\n    }\n}\n#endif                          /* BN_RECURSION */\n\nint BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = 0;\n    int top, al, bl;\n    BIGNUM *rr;\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    int i;\n#endif\n#ifdef BN_RECURSION\n    BIGNUM *t = NULL;\n    int j = 0, k;\n#endif\n\n#ifdef BN_COUNT\n    fprintf(stderr, \"BN_mul %d * %d\\n\", a->top, b->top);\n#endif\n\n    bn_check_top(a);\n    bn_check_top(b);\n    bn_check_top(r);\n\n/* Changes for cryptlib - pcg */\n\t/* If the two input values are the same (which is frequently the case), \n\t   use the more optimal squaring code */\n\tif( a == b )\n\t\treturn( BN_sqr( r, a, ctx ) );\n/* End changes for cryptlib - pcg */\n\n    al = a->top;\n    bl = b->top;\n\n    if ((al == 0) || (bl == 0)) {\n        BN_zero(r);\n        return (1);\n    }\n    top = al + bl;\n\n    BN_CTX_start(ctx);\n    if ((r == a) || (r == b)) {\n        if ((rr = BN_CTX_get(ctx)) == NULL)\n            goto err;\n    } else\n/* Changes for cryptlib - pcg */\n\t\t{\n\t\t/* Usually we can set:\n\t\t\trr = r;\n\t\t   but in the cases where t gets large (see the check further down\n\t\t   for overflow due to k * 2 / k * 4) the value of rr needs to be\n\t\t   large as well.  We can't predict in advance when this will occur \n\t\t   so we have to use an extended-size bignum for rr in all cases */\n\t\trr = ( BIGNUM * ) BN_CTX_get_ext( ctx, BIGNUM_EXT_MUL1 );\n\t\tif( rr == NULL )\n\t\t\tgoto err;\n\t\t}\n/* End changes for cryptlib - pcg */\n    rr->neg = a->neg ^ b->neg;\n\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    i = al - bl;\n#endif\n#ifdef BN_MUL_COMBA\n    if (i == 0) {\n# if 0\n        if (al == 4) {\n            if (bn_wexpand(rr, 8) == NULL)\n                goto err;\n            rr->top = 8;\n            bn_mul_comba4(rr->d, a->d, b->d);\n            goto end;\n        }\n# endif\n        if (al == 8) {\n            if (bn_wexpand(rr, 16) == NULL)\n                goto err;\n            rr->top = 16;\n            bn_mul_comba8(rr->d, a->d, b->d);\n            goto end;\n        }\n    }\n#endif                          /* BN_MUL_COMBA */\n#ifdef BN_RECURSION\n    if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {\n        if (i >= -1 && i <= 1) {\n            /*\n             * Find out the power of two lower or equal to the longest of the\n             * two numbers\n             */\n            if (i >= 0) {\n                j = BN_num_bits_word((BN_ULONG)al);\n            }\n            if (i == -1) {\n                j = BN_num_bits_word((BN_ULONG)bl);\n            }\n            j = 1 << (j - 1);\n            assert(j <= al || j <= bl);\n            k = j + j;\n/* Changes for cryptlib - pcg */\n\t\t\tif( ( k * 2 > BIGNUM_ALLOC_WORDS ) || \\\n\t\t\t\t( ( al > j || bl > j ) && ( k * 4 > BIGNUM_ALLOC_WORDS ) ) )\n\t\t\t\t{\n\t\t\t\t/* We're about to expand the temporary bignum that we're \n\t\t\t\t   using to an enormous size, get a special extended-size \n\t\t\t\t   bignum that won't result in a storage size-check error\n\t\t\t\t   when used */\n\t\t\t\tt = BN_CTX_get_ext( ctx, BIGNUM_EXT_MUL2 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tt = BN_CTX_get(ctx);\n/* End changes for cryptlib - pcg */\n            if (t == NULL)\n                goto err;\n\t\t\tBN_set_flags( t, BN_FLG_SCRATCH );\t/* pcg */\n            if (al > j || bl > j) {\n                if (bn_wexpand(t, k * 4) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 4) == NULL)\n                    goto err;\n                bn_mul_part_recursive(rr->d, a->d, b->d,\n                                      j, al - j, bl - j, t->d);\n            } else {            /* al <= j || bl <= j */\n\n                if (bn_wexpand(t, k * 2) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 2) == NULL)\n                    goto err;\n                bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);\n            }\n            rr->top = top;\n            goto end;\n        }\n# if 0\n        if (i == 1 && !BN_get_flags(b, BN_FLG_STATIC_DATA)) {\n            BIGNUM *tmp_bn = (BIGNUM *)b;\n            if (bn_wexpand(tmp_bn, al) == NULL)\n                goto err;\n            tmp_bn->d[bl] = 0;\n            bl++;\n            i--;\n        } else if (i == -1 && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {\n            BIGNUM *tmp_bn = (BIGNUM *)a;\n            if (bn_wexpand(tmp_bn, bl) == NULL)\n                goto err;\n            tmp_bn->d[al] = 0;\n            al++;\n            i++;\n        }\n        if (i == 0) {\n            /* symmetric and > 4 */\n            /* 16 or larger */\n            j = BN_num_bits_word((BN_ULONG)al);\n            j = 1 << (j - 1);\n            k = j + j;\n            t = BN_CTX_get(ctx);\n            if (al == j) {      /* exact multiple */\n                if (bn_wexpand(t, k * 2) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 2) == NULL)\n                    goto err;\n                bn_mul_recursive(rr->d, a->d, b->d, al, t->d);\n            } else {\n                if (bn_wexpand(t, k * 4) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 4) == NULL)\n                    goto err;\n                bn_mul_part_recursive(rr->d, a->d, b->d, al - j, j, t->d);\n            }\n            rr->top = top;\n            goto end;\n        }\n# endif\n    }\n#endif                          /* BN_RECURSION */\n    if (bn_wexpand(rr, top) == NULL)\n        goto err;\n    rr->top = top;\n    bn_mul_normal(rr->d, a->d, al, b->d, bl);\n\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n end:\n#endif\n    bn_correct_top(rr);\n    if (r != rr)\n        BN_copy(r, rr);\n    ret = 1;\n err:\n    bn_check_top(r);\n\tBN_CTX_end_ext( ctx, BIGNUM_EXT_MUL1 );\t\t\t/* pcg */\n    return (ret);\n}\n\nvoid bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, int na, const BN_ULONG *b, int nb)\t/* const - pcg */\n{\n    BN_ULONG *rr;\n\n#ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_normal %d * %d\\n\", na, nb);\n#endif\n\n    if (na < nb) {\n        int itmp;\n\t\tconst BN_ULONG *ltmp;\t/* const - pcg */\n\n        itmp = na;\n        na = nb;\n        nb = itmp;\n        ltmp = a;\n        a = b;\n        b = ltmp;\n\n    }\n    rr = &(r[na]);\n    if (nb <= 0) {\n        (void)bn_mul_words(r, a, na, 0);\n        return;\n    } else\n        rr[0] = bn_mul_words(r, a, na, b[0]);\n\n    for (;;) {\n        if (--nb <= 0)\n            return;\n        rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]);\n        if (--nb <= 0)\n            return;\n        rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]);\n        if (--nb <= 0)\n            return;\n        rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]);\n        if (--nb <= 0)\n            return;\n        rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]);\n        rr += 4;\n        r += 4;\n        b += 4;\n    }\n}\n\nvoid bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)\n{\n#ifdef BN_COUNT\n    fprintf(stderr, \" bn_mul_low_normal %d * %d\\n\", n, n);\n#endif\n    bn_mul_words(r, a, n, b[0]);\n\n    for (;;) {\n        if (--n <= 0)\n            return;\n        bn_mul_add_words(&(r[1]), a, n, b[1]);\n        if (--n <= 0)\n            return;\n        bn_mul_add_words(&(r[2]), a, n, b[2]);\n        if (--n <= 0)\n            return;\n        bn_mul_add_words(&(r[3]), a, n, b[3]);\n        if (--n <= 0)\n            return;\n        bn_mul_add_words(&(r[4]), a, n, b[4]);\n        r += 4;\n        b += 4;\n    }\n}\n"
  },
  {
    "path": "deps/cl345/bn/bn_orig.h",
    "content": "/* Original bn.h with unnecessary parts removed for clarity.  In other words \n   this represents the leftover portions of the OpenSSL bignum code that \n   cryptlib uses */\n\n/* crypto/bn/bn.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n/* ====================================================================\n * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n *\n * Portions of the attached software (\"Contribution\") are developed by\n * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.\n *\n * The Contribution is licensed pursuant to the Eric Young open source\n * license provided above.\n *\n * The binary polynomial arithmetic software is originally written by\n * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.\n *\n */\n\n#ifndef HEADER_BN_H\n# define HEADER_BN_H\n\nint BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);\nint BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);\nint BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n               const BIGNUM *m, BN_CTX *ctx);\nint BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n                    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);\nint BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,\n                              const BIGNUM *m, BN_CTX *ctx,\n                              BN_MONT_CTX *in_mont);\nint BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,\n                         const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *m_ctx);\t/* const - pcg */\nint BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,\n                     const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,\n                     BN_CTX *ctx, BN_MONT_CTX *m_ctx);\nint BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n                      const BIGNUM *m, BN_CTX *ctx);\nint BN_mask_bits(BIGNUM *a, const int n);\t/* const - pcg */\nint BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);\nint BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);\n\nBIGNUM *BN_mod_inverse(BIGNUM *ret,\n                       const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);\nBIGNUM *BN_mod_sqrt(BIGNUM *ret,\n                    const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);\n\nint BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,\n                          BN_RECP_CTX *recp, BN_CTX *ctx);\nint BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,\n                    const BIGNUM *m, BN_CTX *ctx);\nint BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,\n                BN_RECP_CTX *recp, BN_CTX *ctx);\n\nBN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,\n                          BN_ULONG w);\nBN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);\nvoid bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);\nBN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);\nBN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                      int num);\nBN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,\n                      int num);\n\n#endif\n"
  },
  {
    "path": "deps/cl345/bn/bn_recp.c",
    "content": "/* crypto/bn/bn_recp.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include <stdio.h>\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"bn_lcl.h\"\n#else\n  #include \"bn/bn_lcl.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\n#if 0\t/* pcg */\n\nvoid BN_RECP_CTX_init(BN_RECP_CTX *recp)\n{\n    BN_init(&(recp->N));\n    BN_init(&(recp->Nr));\n    recp->num_bits = 0;\n    recp->flags = 0;\n}\n\nBN_RECP_CTX *BN_RECP_CTX_new(void)\n{\n    BN_RECP_CTX *ret;\n\n\tif ((ret=(BN_RECP_CTX *)clBnAlloc(\"BN_RECP_CTX_new\",sizeof(BN_RECP_CTX))) == NULL)\t/* pcg */\n        return (NULL);\n\n    BN_RECP_CTX_init(ret);\n    ret->flags = BN_FLG_MALLOCED;\n    return (ret);\n}\n\nvoid BN_RECP_CTX_free(BN_RECP_CTX *recp)\n{\n    if (recp == NULL)\n        return;\n\n    BN_free(&(recp->N));\n    BN_free(&(recp->Nr));\n    if (recp->flags & BN_FLG_MALLOCED)\n        OPENSSL_free(recp);\n}\n\nint BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)\n{\n    if (!BN_copy(&(recp->N), d))\n        return 0;\n    BN_zero(&(recp->Nr));\n    recp->num_bits = BN_num_bits(d);\n    recp->shift = 0;\n    return (1);\n}\n#endif /* 0 */\n\nint BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,\n                          BN_RECP_CTX *recp, BN_CTX *ctx)\n{\n    int ret = 0;\n    BIGNUM *a;\n    const BIGNUM *ca;\n\n    BN_CTX_start(ctx);\n    if ((a = BN_CTX_get(ctx)) == NULL)\n        goto err;\n    if (y != NULL) {\n        if (x == y) {\n            if (!BN_sqr(a, x, ctx))\n                goto err;\n        } else {\n            if (!BN_mul(a, x, y, ctx))\n                goto err;\n        }\n        ca = a;\n    } else\n        ca = x;                 /* Just do the mod */\n\n    ret = BN_div_recp(NULL, r, ca, recp, ctx);\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(r);\n    return (ret);\n}\n\nint BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,\n                BN_RECP_CTX *recp, BN_CTX *ctx)\n{\n    int i, j, ret = 0;\n    BIGNUM *a, *b, *d, *r;\n\n    BN_CTX_start(ctx);\n    a = BN_CTX_get(ctx);\n    b = BN_CTX_get(ctx);\n    if (dv != NULL)\n        d = dv;\n    else\n        d = BN_CTX_get(ctx);\n    if (rem != NULL)\n        r = rem;\n    else\n        r = BN_CTX_get(ctx);\n    if (a == NULL || b == NULL || d == NULL || r == NULL)\n        goto err;\n\n    if (BN_ucmp(m, &(recp->N)) < 0) {\n        BN_zero(d);\n        if (!BN_copy(r, m)) {\n            BN_CTX_end(ctx);\n            return 0;\n        }\n        BN_CTX_end(ctx);\n        return (1);\n    }\n\n    /*\n     * We want the remainder Given input of ABCDEF / ab we need multiply\n     * ABCDEF by 3 digests of the reciprocal of ab\n     */\n\n    /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */\n    i = BN_num_bits(m);\n    j = recp->num_bits << 1;\n    if (j > i)\n        i = j;\n\n    /* Nr := round(2^i / N) */\n    if (i != recp->shift)\n        recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);\n    /* BN_reciprocal could have returned -1 for an error */\n    if (recp->shift == -1)\n        goto err;\n\n    /*-\n     * d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|\n     *    = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|\n     *   <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|\n     *    = |m/N|\n     */\n    if (!BN_rshift(a, m, recp->num_bits))\n        goto err;\n    if (!BN_mul(b, a, &(recp->Nr), ctx))\n        goto err;\n    if (!BN_rshift(d, b, i - recp->num_bits))\n        goto err;\n    d->neg = 0;\n\n    if (!BN_mul(b, &(recp->N), d, ctx))\n        goto err;\n    if (!BN_usub(r, m, b))\n        goto err;\n    r->neg = 0;\n\n#if 1\n    j = 0;\n    while (BN_ucmp(r, &(recp->N)) >= 0) {\n        if (j++ > 2) {\n            BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL);\n            goto err;\n        }\n        if (!BN_usub(r, r, &(recp->N)))\n            goto err;\n        if (!BN_add_word(d, 1))\n            goto err;\n    }\n#endif\n\n    r->neg = BN_is_zero(r) ? 0 : m->neg;\n    d->neg = m->neg ^ recp->N.neg;\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(dv);\n    bn_check_top(rem);\n    return (ret);\n}\n\n/*\n * len is the expected size of the result We actually calculate with an extra\n * word of precision, so we can do faster division if the remainder is not\n * required.\n */\n/* r := 2^len / m */\nint BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)\n{\n    int ret = -1;\n    BIGNUM *t;\n\n    BN_CTX_start(ctx);\n    if ((t = BN_CTX_get(ctx)) == NULL)\n        goto err;\n\n    if (!BN_set_bit(t, len))\n        goto err;\n\n    if (!BN_div(r, NULL, t, m, ctx))\n        goto err;\n\n    ret = len;\n err:\n    bn_check_top(r);\n    BN_CTX_end(ctx);\n    return (ret);\n}\n"
  },
  {
    "path": "deps/cl345/bn/ec.h",
    "content": "/* crypto/ec/ec.h */\n/*\n * Originally written by Bodo Moeller for the OpenSSL project.\n */\n/**\n * \\file crypto/ec/ec.h Include file for the OpenSSL EC functions\n * \\author Originally written by Bodo Moeller for the OpenSSL project\n */\n/* ====================================================================\n * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n *\n * Portions of the attached software (\"Contribution\") are developed by\n * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.\n *\n * The Contribution is licensed pursuant to the OpenSSL open source\n * license provided above.\n *\n * The elliptic curve binary polynomial software is originally written by\n * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.\n *\n */\n\n#ifndef HEADER_EC_H\n# define HEADER_EC_H\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"osconfig.h\"\n#else\n  #include \"crypt/osconfig.h\"\n#endif /* Compiler-specific includes */\n#define ECerr(a,b)\n#define ERR_clear_error()\n#define ERR_peek_last_error()\t0\n#define ERR_GET_LIB( dummy )\t0\n#define ERR_GET_REASON( dummy )\t0\n#define ERR_LIB_BN\t\t\t\t0\n#define CRYPTO_add( dummy1, dummy2, dummy3 )\t0\n#define OPENSSL_NO_BIO\n#define OPENSSL_NO_FP_API\n\n/* Disable a pile of bloat that we don't need */\n\n#define OPENSSL_NO_EC2M\n#define OPENSSL_NO_EC_NISTP_64_GCC_128\n\n/* Other changes:\n\n\t- Replace OPENSSL_malloc() with clBnAlloc() in ecp_smpl.c, ec_lib.c,\n\t\tec_mult.c, ec_rand.c.\n\t- Replace OPENSSL_free() with clBnFree() in ec_lib.c */\n\n/* Remove include of OpenSSL-specific headers following OPENSSL_NO_EC check */\n\n/* End changes for cryptlib - pcg */\n\n# ifdef OPENSSL_NO_EC\n#  error EC is disabled.\n# endif\n\n# ifdef  __cplusplus\nextern \"C\" {\n# elif defined(__SUNPRO_C)\n#  if __SUNPRO_C >= 0x520\n#   pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)\n#  endif\n# endif\n\n# ifndef OPENSSL_ECC_MAX_FIELD_BITS\n#  define OPENSSL_ECC_MAX_FIELD_BITS 661\n# endif\n\n/** Enum for the point conversion form as defined in X9.62 (ECDSA)\n *  for the encoding of a elliptic curve point (x,y) */\ntypedef enum {\n        /** the point is encoded as z||x, where the octet z specifies\n         *  which solution of the quadratic equation y is  */\n    POINT_CONVERSION_COMPRESSED = 2,\n        /** the point is encoded as z||x||y, where z is the octet 0x04  */\n    POINT_CONVERSION_UNCOMPRESSED = 4,\n        /** the point is encoded as z||x||y, where the octet z specifies\n         *  which solution of the quadratic equation y is  */\n    POINT_CONVERSION_HYBRID = 6\n} point_conversion_form_t;\n\ntypedef struct ec_method_st EC_METHOD;\n\ntypedef struct ec_group_st\n    /*-\n     EC_METHOD *meth;\n     -- field definition\n     -- curve coefficients\n     -- optional generator with associated information (order, cofactor)\n     -- optional extra data (precomputed table for fast computation of multiples of generator)\n     -- ASN1 stuff\n    */\n    EC_GROUP;\n\ntypedef struct ec_point_st EC_POINT;\n\n/********************************************************************/\n/*               EC_METHODs for curves over GF(p)                   */\n/********************************************************************/\n\n/** Returns the basic GFp ec methods which provides the basis for the\n *  optimized methods.\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_simple_method(void);\n\n/** Returns GFp methods using montgomery multiplication.\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_mont_method(void);\n\n/** Returns GFp methods using optimized methods for NIST recommended curves\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_nist_method(void);\n\n# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128\n/** Returns 64-bit optimized methods for nistp224\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_nistp224_method(void);\n\n/** Returns 64-bit optimized methods for nistp256\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_nistp256_method(void);\n\n/** Returns 64-bit optimized methods for nistp521\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_nistp521_method(void);\n# endif\n\n# ifndef OPENSSL_NO_EC2M\n/********************************************************************/\n/*           EC_METHOD for curves over GF(2^m)                      */\n/********************************************************************/\n\n/** Returns the basic GF2m ec method\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GF2m_simple_method(void);\n\n# endif\n\n/********************************************************************/\n/*                   EC_GROUP functions                             */\n/********************************************************************/\n\n/** Creates a new EC_GROUP object\n *  \\param   meth  EC_METHOD to use\n *  \\return  newly created EC_GROUP object or NULL in case of an error.\n */\nEC_GROUP *EC_GROUP_new(const EC_METHOD *meth);\n\n/** Frees a EC_GROUP object\n *  \\param  group  EC_GROUP object to be freed.\n */\nvoid EC_GROUP_free(EC_GROUP *group);\n\n/** Clears and frees a EC_GROUP object\n *  \\param  group  EC_GROUP object to be cleared and freed.\n */\nvoid EC_GROUP_clear_free(EC_GROUP *group);\n\n/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.\n *  \\param  dst  destination EC_GROUP object\n *  \\param  src  source EC_GROUP object\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);\n\n/** Creates a new EC_GROUP object and copies the copies the content\n *  form src to the newly created EC_KEY object\n *  \\param  src  source EC_GROUP object\n *  \\return newly created EC_GROUP object or NULL in case of an error.\n */\nEC_GROUP *EC_GROUP_dup(const EC_GROUP *src);\n\n/** Returns the EC_METHOD of the EC_GROUP object.\n *  \\param  group  EC_GROUP object\n *  \\return EC_METHOD used in this EC_GROUP object.\n */\nconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);\n\n/** Returns the field type of the EC_METHOD.\n *  \\param  meth  EC_METHOD object\n *  \\return NID of the underlying field type OID.\n */\nint EC_METHOD_get_field_type(const EC_METHOD *meth);\n\n/** Sets the generator and it's order/cofactor of a EC_GROUP object.\n *  \\param  group      EC_GROUP object\n *  \\param  generator  EC_POINT object with the generator.\n *  \\param  order      the order of the group generated by the generator.\n *  \\param  cofactor   the index of the sub-group generated by the generator\n *                     in the group of all points on the elliptic curve.\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,\n                           const BIGNUM *order, const BIGNUM *cofactor);\n\n/** Returns the generator of a EC_GROUP object.\n *  \\param  group  EC_GROUP object\n *  \\return the currently used generator (possibly NULL).\n */\nconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);\n\n/** Returns the montgomery data for order(Generator)\n *  \\param  group  EC_GROUP object\n *  \\return the currently used generator (possibly NULL).\n*/\nBN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group);\n\n/** Gets the order of a EC_GROUP\n *  \\param  group  EC_GROUP object\n *  \\param  order  BIGNUM to which the order is copied\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);\n\n/** Gets the cofactor of a EC_GROUP\n *  \\param  group     EC_GROUP object\n *  \\param  cofactor  BIGNUM to which the cofactor is copied\n *  \\param  ctx       BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,\n                          BN_CTX *ctx);\n\n/** Sets the name of a EC_GROUP object\n *  \\param  group  EC_GROUP object\n *  \\param  nid    NID of the curve name OID\n */\nvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid);\n\n/** Returns the curve name of a EC_GROUP object\n *  \\param  group  EC_GROUP object\n *  \\return NID of the curve name OID or 0 if not set.\n */\nint EC_GROUP_get_curve_name(const EC_GROUP *group);\n\nvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);\nint EC_GROUP_get_asn1_flag(const EC_GROUP *group);\n\nvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group,\n                                        point_conversion_form_t form);\npoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);\n\nunsigned char *EC_GROUP_get0_seed(const EC_GROUP *x);\nsize_t EC_GROUP_get_seed_len(const EC_GROUP *);\nsize_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);\n\n/** Sets the parameter of a ec over GFp defined by y^2 = x^3 + a*x + b\n *  \\param  group  EC_GROUP object\n *  \\param  p      BIGNUM with the prime number\n *  \\param  a      BIGNUM with parameter a of the equation\n *  \\param  b      BIGNUM with parameter b of the equation\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,\n                           const BIGNUM *b, BN_CTX *ctx);\n\n/** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b\n *  \\param  group  EC_GROUP object\n *  \\param  p      BIGNUM for the prime number\n *  \\param  a      BIGNUM for parameter a of the equation\n *  \\param  b      BIGNUM for parameter b of the equation\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,\n                           BIGNUM *b, BN_CTX *ctx);\n\n# ifndef OPENSSL_NO_EC2M\n/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b\n *  \\param  group  EC_GROUP object\n *  \\param  p      BIGNUM with the polynomial defining the underlying field\n *  \\param  a      BIGNUM with parameter a of the equation\n *  \\param  b      BIGNUM with parameter b of the equation\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,\n                            const BIGNUM *b, BN_CTX *ctx);\n\n/** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b\n *  \\param  group  EC_GROUP object\n *  \\param  p      BIGNUM for the polynomial defining the underlying field\n *  \\param  a      BIGNUM for parameter a of the equation\n *  \\param  b      BIGNUM for parameter b of the equation\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,\n                            BIGNUM *b, BN_CTX *ctx);\n# endif\n/** Returns the number of bits needed to represent a field element\n *  \\param  group  EC_GROUP object\n *  \\return number of bits needed to represent a field element\n */\nint EC_GROUP_get_degree(const EC_GROUP *group);\n\n/** Checks whether the parameter in the EC_GROUP define a valid ec group\n *  \\param  group  EC_GROUP object\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 if group is a valid ec group and 0 otherwise\n */\nint EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);\n\n/** Checks whether the discriminant of the elliptic curve is zero or not\n *  \\param  group  EC_GROUP object\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 if the discriminant is not zero and 0 otherwise\n */\nint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);\n\n/** Compares two EC_GROUP objects\n *  \\param  a    first EC_GROUP object\n *  \\param  b    second EC_GROUP object\n *  \\param  ctx  BN_CTX object (optional)\n *  \\return 0 if both groups are equal and 1 otherwise\n */\nint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);\n\n/*\n * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after\n * choosing an appropriate EC_METHOD\n */\n\n/** Creates a new EC_GROUP object with the specified parameters defined\n *  over GFp (defined by the equation y^2 = x^3 + a*x + b)\n *  \\param  p    BIGNUM with the prime number\n *  \\param  a    BIGNUM with the parameter a of the equation\n *  \\param  b    BIGNUM with the parameter b of the equation\n *  \\param  ctx  BN_CTX object (optional)\n *  \\return newly created EC_GROUP object with the specified parameters\n */\nEC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,\n                                 const BIGNUM *b, BN_CTX *ctx);\n# ifndef OPENSSL_NO_EC2M\n/** Creates a new EC_GROUP object with the specified parameters defined\n *  over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)\n *  \\param  p    BIGNUM with the polynomial defining the underlying field\n *  \\param  a    BIGNUM with the parameter a of the equation\n *  \\param  b    BIGNUM with the parameter b of the equation\n *  \\param  ctx  BN_CTX object (optional)\n *  \\return newly created EC_GROUP object with the specified parameters\n */\nEC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,\n                                  const BIGNUM *b, BN_CTX *ctx);\n# endif\n/** Creates a EC_GROUP object with a curve specified by a NID\n *  \\param  nid  NID of the OID of the curve name\n *  \\return newly created EC_GROUP object with specified curve or NULL\n *          if an error occurred\n */\nEC_GROUP *EC_GROUP_new_by_curve_name(int nid);\n\n/********************************************************************/\n/*               handling of internal curves                        */\n/********************************************************************/\n\ntypedef struct {\n    int nid;\n    const char *comment;\n} EC_builtin_curve;\n\n/*\n * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all\n * available curves or zero if a error occurred. In case r ist not zero\n * nitems EC_builtin_curve structures are filled with the data of the first\n * nitems internal groups\n */\nsize_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);\n\nconst char *EC_curve_nid2nist(int nid);\nint EC_curve_nist2nid(const char *name);\n\n/********************************************************************/\n/*                    EC_POINT functions                            */\n/********************************************************************/\n\n/** Creates a new EC_POINT object for the specified EC_GROUP\n *  \\param  group  EC_GROUP the underlying EC_GROUP object\n *  \\return newly created EC_POINT object or NULL if an error occurred\n */\nEC_POINT *EC_POINT_new(const EC_GROUP *group);\n\n/** Frees a EC_POINT object\n *  \\param  point  EC_POINT object to be freed\n */\nvoid EC_POINT_free(EC_POINT *point);\n\n/** Clears and frees a EC_POINT object\n *  \\param  point  EC_POINT object to be cleared and freed\n */\nvoid EC_POINT_clear_free(EC_POINT *point);\n\n/** Copies EC_POINT object\n *  \\param  dst  destination EC_POINT object\n *  \\param  src  source EC_POINT object\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);\n\n/** Creates a new EC_POINT object and copies the content of the supplied\n *  EC_POINT\n *  \\param  src    source EC_POINT object\n *  \\param  group  underlying the EC_GROUP object\n *  \\return newly created EC_POINT object or NULL if an error occurred\n */\nEC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);\n\n/** Returns the EC_METHOD used in EC_POINT object\n *  \\param  point  EC_POINT object\n *  \\return the EC_METHOD used\n */\nconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point);\n\n/** Sets a point to infinity (neutral element)\n *  \\param  group  underlying EC_GROUP object\n *  \\param  point  EC_POINT to set to infinity\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);\n\n/** Sets the jacobian projective coordinates of a EC_POINT over GFp\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM with the x-coordinate\n *  \\param  y      BIGNUM with the y-coordinate\n *  \\param  z      BIGNUM with the z-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                             EC_POINT *p, const BIGNUM *x,\n                                             const BIGNUM *y, const BIGNUM *z,\n                                             BN_CTX *ctx);\n\n/** Gets the jacobian projective coordinates of a EC_POINT over GFp\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM for the x-coordinate\n *  \\param  y      BIGNUM for the y-coordinate\n *  \\param  z      BIGNUM for the z-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                             const EC_POINT *p, BIGNUM *x,\n                                             BIGNUM *y, BIGNUM *z,\n                                             BN_CTX *ctx);\n\n/** Sets the affine coordinates of a EC_POINT over GFp\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM with the x-coordinate\n *  \\param  y      BIGNUM with the y-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,\n                                        const BIGNUM *x, const BIGNUM *y,\n                                        BN_CTX *ctx);\n\n/** Gets the affine coordinates of a EC_POINT over GFp\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM for the x-coordinate\n *  \\param  y      BIGNUM for the y-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,\n                                        const EC_POINT *p, BIGNUM *x,\n                                        BIGNUM *y, BN_CTX *ctx);\n\n/** Sets the x9.62 compressed coordinates of a EC_POINT over GFp\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM with x-coordinate\n *  \\param  y_bit  integer with the y-Bit (either 0 or 1)\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,\n                                            EC_POINT *p, const BIGNUM *x,\n                                            int y_bit, BN_CTX *ctx);\n# ifndef OPENSSL_NO_EC2M\n/** Sets the affine coordinates of a EC_POINT over GF2m\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM with the x-coordinate\n *  \\param  y      BIGNUM with the y-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,\n                                         const BIGNUM *x, const BIGNUM *y,\n                                         BN_CTX *ctx);\n\n/** Gets the affine coordinates of a EC_POINT over GF2m\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM for the x-coordinate\n *  \\param  y      BIGNUM for the y-coordinate\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,\n                                         const EC_POINT *p, BIGNUM *x,\n                                         BIGNUM *y, BN_CTX *ctx);\n\n/** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  x      BIGNUM with x-coordinate\n *  \\param  y_bit  integer with the y-Bit (either 0 or 1)\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,\n                                             EC_POINT *p, const BIGNUM *x,\n                                             int y_bit, BN_CTX *ctx);\n# endif\n/** Encodes a EC_POINT object to a octet string\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  form   point conversion form\n *  \\param  buf    memory buffer for the result. If NULL the function returns\n *                 required buffer size.\n *  \\param  len    length of the memory buffer\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return the length of the encoded octet string or 0 if an error occurred\n */\nsize_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,\n                          point_conversion_form_t form,\n                          unsigned char *buf, size_t len, BN_CTX *ctx);\n\n/** Decodes a EC_POINT from a octet string\n *  \\param  group  underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\param  buf    memory buffer with the encoded ec point\n *  \\param  len    length of the encoded ec point\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,\n                       const unsigned char *buf, size_t len, BN_CTX *ctx);\n\n/* other interfaces to point2oct/oct2point: */\nBIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,\n                          point_conversion_form_t form, BIGNUM *, BN_CTX *);\nEC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,\n                            EC_POINT *, BN_CTX *);\nchar *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,\n                         point_conversion_form_t form, BN_CTX *);\nEC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,\n                             EC_POINT *, BN_CTX *);\n\n/********************************************************************/\n/*         functions for doing EC_POINT arithmetic                  */\n/********************************************************************/\n\n/** Computes the sum of two EC_POINT\n *  \\param  group  underlying EC_GROUP object\n *  \\param  r      EC_POINT object for the result (r = a + b)\n *  \\param  a      EC_POINT object with the first summand\n *  \\param  b      EC_POINT object with the second summand\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                 const EC_POINT *b, BN_CTX *ctx);\n\n/** Computes the double of a EC_POINT\n *  \\param  group  underlying EC_GROUP object\n *  \\param  r      EC_POINT object for the result (r = 2 * a)\n *  \\param  a      EC_POINT object\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                 BN_CTX *ctx);\n\n/** Computes the inverse of a EC_POINT\n *  \\param  group  underlying EC_GROUP object\n *  \\param  a      EC_POINT object to be inverted (it's used for the result as well)\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);\n\n/** Checks whether the point is the neutral element of the group\n *  \\param  group  the underlying EC_GROUP object\n *  \\param  p      EC_POINT object\n *  \\return 1 if the point is the neutral element and 0 otherwise\n */\nint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);\n\n/** Checks whether the point is on the curve\n *  \\param  group  underlying EC_GROUP object\n *  \\param  point  EC_POINT object to check\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 if point if on the curve and 0 otherwise\n */\nint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,\n                         BN_CTX *ctx);\n\n/** Compares two EC_POINTs\n *  \\param  group  underlying EC_GROUP object\n *  \\param  a      first EC_POINT object\n *  \\param  b      second EC_POINT object\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 0 if both points are equal and a value != 0 otherwise\n */\nint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,\n                 BN_CTX *ctx);\n\nint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);\nint EC_POINTs_make_affine(const EC_GROUP *group, size_t num,\n                          EC_POINT *points[], BN_CTX *ctx);\n\n/** Computes r = generator * n sum_{i=0}^{num-1} p[i] * m[i]\n *  \\param  group  underlying EC_GROUP object\n *  \\param  r      EC_POINT object for the result\n *  \\param  n      BIGNUM with the multiplier for the group generator (optional)\n *  \\param  num    number futher summands\n *  \\param  p      array of size num of EC_POINT objects\n *  \\param  m      array of size num of BIGNUM objects\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,\n                  size_t num, const EC_POINT *p[], const BIGNUM *m[],\n                  BN_CTX *ctx);\n\n/** Computes r = generator * n + q * m\n *  \\param  group  underlying EC_GROUP object\n *  \\param  r      EC_POINT object for the result\n *  \\param  n      BIGNUM with the multiplier for the group generator (optional)\n *  \\param  q      EC_POINT object with the first factor of the second summand\n *  \\param  m      BIGNUM with the second factor of the second summand\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n,\n                 const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);\n\n/** Stores multiples of generator for faster point multiplication\n *  \\param  group  EC_GROUP object\n *  \\param  ctx    BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occured\n */\nint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);\n\n/** Reports whether a precomputation has been done\n *  \\param  group  EC_GROUP object\n *  \\return 1 if a pre-computation has been done and 0 otherwise\n */\nint EC_GROUP_have_precompute_mult(const EC_GROUP *group);\n\n/********************************************************************/\n/*                       ASN1 stuff                                 */\n/********************************************************************/\n\n/*\n * EC_GROUP_get_basis_type() returns the NID of the basis type used to\n * represent the field elements\n */\nint EC_GROUP_get_basis_type(const EC_GROUP *);\n# ifndef OPENSSL_NO_EC2M\nint EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);\nint EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,\n                                   unsigned int *k2, unsigned int *k3);\n# endif\n\n# define OPENSSL_EC_NAMED_CURVE  0x001\n\ntypedef struct ecpk_parameters_st ECPKPARAMETERS;\n\nEC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);\nint i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);\n\n# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)\n# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)\n# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \\\n                (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))\n# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \\\n                (unsigned char *)(x))\n\n# ifndef OPENSSL_NO_BIO\nint ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);\n# endif\n# ifndef OPENSSL_NO_FP_API\nint ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);\n# endif\n\n/********************************************************************/\n/*                      EC_KEY functions                            */\n/********************************************************************/\n\ntypedef struct ec_key_st EC_KEY;\n\n/* some values for the encoding_flag */\n# define EC_PKEY_NO_PARAMETERS   0x001\n# define EC_PKEY_NO_PUBKEY       0x002\n\n/* some values for the flags field */\n# define EC_FLAG_NON_FIPS_ALLOW  0x1\n# define EC_FLAG_FIPS_CHECKED    0x2\n\n/** Creates a new EC_KEY object.\n *  \\return EC_KEY object or NULL if an error occurred.\n */\nEC_KEY *EC_KEY_new(void);\n\nint EC_KEY_get_flags(const EC_KEY *key);\n\nvoid EC_KEY_set_flags(EC_KEY *key, int flags);\n\nvoid EC_KEY_clear_flags(EC_KEY *key, int flags);\n\n/** Creates a new EC_KEY object using a named curve as underlying\n *  EC_GROUP object.\n *  \\param  nid  NID of the named curve.\n *  \\return EC_KEY object or NULL if an error occurred.\n */\nEC_KEY *EC_KEY_new_by_curve_name(int nid);\n\n/** Frees a EC_KEY object.\n *  \\param  key  EC_KEY object to be freed.\n */\nvoid EC_KEY_free(EC_KEY *key);\n\n/** Copies a EC_KEY object.\n *  \\param  dst  destination EC_KEY object\n *  \\param  src  src EC_KEY object\n *  \\return dst or NULL if an error occurred.\n */\nEC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);\n\n/** Creates a new EC_KEY object and copies the content from src to it.\n *  \\param  src  the source EC_KEY object\n *  \\return newly created EC_KEY object or NULL if an error occurred.\n */\nEC_KEY *EC_KEY_dup(const EC_KEY *src);\n\n/** Increases the internal reference count of a EC_KEY object.\n *  \\param  key  EC_KEY object\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_up_ref(EC_KEY *key);\n\n/** Returns the EC_GROUP object of a EC_KEY object\n *  \\param  key  EC_KEY object\n *  \\return the EC_GROUP object (possibly NULL).\n */\nconst EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);\n\n/** Sets the EC_GROUP of a EC_KEY object.\n *  \\param  key    EC_KEY object\n *  \\param  group  EC_GROUP to use in the EC_KEY object (note: the EC_KEY\n *                 object will use an own copy of the EC_GROUP).\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);\n\n/** Returns the private key of a EC_KEY object.\n *  \\param  key  EC_KEY object\n *  \\return a BIGNUM with the private key (possibly NULL).\n */\nconst BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);\n\n/** Sets the private key of a EC_KEY object.\n *  \\param  key  EC_KEY object\n *  \\param  prv  BIGNUM with the private key (note: the EC_KEY object\n *               will use an own copy of the BIGNUM).\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);\n\n/** Returns the public key of a EC_KEY object.\n *  \\param  key  the EC_KEY object\n *  \\return a EC_POINT object with the public key (possibly NULL)\n */\nconst EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);\n\n/** Sets the public key of a EC_KEY object.\n *  \\param  key  EC_KEY object\n *  \\param  pub  EC_POINT object with the public key (note: the EC_KEY object\n *               will use an own copy of the EC_POINT object).\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);\n\nunsigned EC_KEY_get_enc_flags(const EC_KEY *key);\nvoid EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags);\npoint_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key);\nvoid EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);\n/* functions to set/get method specific data  */\nvoid *EC_KEY_get_key_method_data(EC_KEY *key,\n                                 void *(*dup_func) (void *),\n                                 void (*free_func) (void *),\n                                 void (*clear_free_func) (void *));\n/** Sets the key method data of an EC_KEY object, if none has yet been set.\n *  \\param  key              EC_KEY object\n *  \\param  data             opaque data to install.\n *  \\param  dup_func         a function that duplicates |data|.\n *  \\param  free_func        a function that frees |data|.\n *  \\param  clear_free_func  a function that wipes and frees |data|.\n *  \\return the previously set data pointer, or NULL if |data| was inserted.\n */\nvoid *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,\n                                    void *(*dup_func) (void *),\n                                    void (*free_func) (void *),\n                                    void (*clear_free_func) (void *));\n/* wrapper functions for the underlying EC_GROUP object */\nvoid EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);\n\n/** Creates a table of pre-computed multiples of the generator to\n *  accelerate further EC_KEY operations.\n *  \\param  key  EC_KEY object\n *  \\param  ctx  BN_CTX object (optional)\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);\n\n/** Creates a new ec private (and optional a new public) key.\n *  \\param  key  EC_KEY object\n *  \\return 1 on success and 0 if an error occurred.\n */\nint EC_KEY_generate_key(EC_KEY *key);\n\n/** Verifies that a private and/or public key is valid.\n *  \\param  key  the EC_KEY object\n *  \\return 1 on success and 0 otherwise.\n */\nint EC_KEY_check_key(const EC_KEY *key);\n\n/** Sets a public key from affine coordindates performing\n *  neccessary NIST PKV tests.\n *  \\param  key  the EC_KEY object\n *  \\param  x    public key x coordinate\n *  \\param  y    public key y coordinate\n *  \\return 1 on success and 0 otherwise.\n */\nint EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,\n                                             BIGNUM *y);\n\n/********************************************************************/\n/*        de- and encoding functions for SEC1 ECPrivateKey          */\n/********************************************************************/\n\n/** Decodes a private key from a memory buffer.\n *  \\param  key  a pointer to a EC_KEY object which should be used (or NULL)\n *  \\param  in   pointer to memory with the DER encoded private key\n *  \\param  len  length of the DER encoded private key\n *  \\return the decoded private key or NULL if an error occurred.\n */\nEC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);\n\n/** Encodes a private key object and stores the result in a buffer.\n *  \\param  key  the EC_KEY object to encode\n *  \\param  out  the buffer for the result (if NULL the function returns number\n *               of bytes needed).\n *  \\return 1 on success and 0 if an error occurred.\n */\nint i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);\n\n/********************************************************************/\n/*        de- and encoding functions for EC parameters              */\n/********************************************************************/\n\n/** Decodes ec parameter from a memory buffer.\n *  \\param  key  a pointer to a EC_KEY object which should be used (or NULL)\n *  \\param  in   pointer to memory with the DER encoded ec parameters\n *  \\param  len  length of the DER encoded ec parameters\n *  \\return a EC_KEY object with the decoded parameters or NULL if an error\n *          occurred.\n */\nEC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);\n\n/** Encodes ec parameter and stores the result in a buffer.\n *  \\param  key  the EC_KEY object with ec paramters to encode\n *  \\param  out  the buffer for the result (if NULL the function returns number\n *               of bytes needed).\n *  \\return 1 on success and 0 if an error occurred.\n */\nint i2d_ECParameters(EC_KEY *key, unsigned char **out);\n\n/********************************************************************/\n/*         de- and encoding functions for EC public key             */\n/*         (octet string, not DER -- hence 'o2i' and 'i2o')         */\n/********************************************************************/\n\n/** Decodes a ec public key from a octet string.\n *  \\param  key  a pointer to a EC_KEY object which should be used\n *  \\param  in   memory buffer with the encoded public key\n *  \\param  len  length of the encoded public key\n *  \\return EC_KEY object with decoded public key or NULL if an error\n *          occurred.\n */\nEC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);\n\n/** Encodes a ec public key in an octet string.\n *  \\param  key  the EC_KEY object with the public key\n *  \\param  out  the buffer for the result (if NULL the function returns number\n *               of bytes needed).\n *  \\return 1 on success and 0 if an error occurred\n */\nint i2o_ECPublicKey(EC_KEY *key, unsigned char **out);\n\n# ifndef OPENSSL_NO_BIO\n/** Prints out the ec parameters on human readable form.\n *  \\param  bp   BIO object to which the information is printed\n *  \\param  key  EC_KEY object\n *  \\return 1 on success and 0 if an error occurred\n */\nint ECParameters_print(BIO *bp, const EC_KEY *key);\n\n/** Prints out the contents of a EC_KEY object\n *  \\param  bp   BIO object to which the information is printed\n *  \\param  key  EC_KEY object\n *  \\param  off  line offset\n *  \\return 1 on success and 0 if an error occurred\n */\nint EC_KEY_print(BIO *bp, const EC_KEY *key, int off);\n\n# endif\n# ifndef OPENSSL_NO_FP_API\n/** Prints out the ec parameters on human readable form.\n *  \\param  fp   file descriptor to which the information is printed\n *  \\param  key  EC_KEY object\n *  \\return 1 on success and 0 if an error occurred\n */\nint ECParameters_print_fp(FILE *fp, const EC_KEY *key);\n\n/** Prints out the contents of a EC_KEY object\n *  \\param  fp   file descriptor to which the information is printed\n *  \\param  key  EC_KEY object\n *  \\param  off  line offset\n *  \\return 1 on success and 0 if an error occurred\n */\nint EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);\n\n# endif\n\n# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)\n\n# ifndef __cplusplus\n#  if defined(__SUNPRO_C)\n#   if __SUNPRO_C >= 0x520\n#    pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)\n#   endif\n#  endif\n# endif\n\n# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \\\n                                EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)\n\n# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \\\n                                EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL)\n\n# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL)\n\n# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL)\n\n# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL)\n\n# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL)\n\n# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)md)\n\n# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)pmd)\n\n# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL)\n\n# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                        EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, (void *)plen)\n\n# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)p)\n\n# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \\\n        EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \\\n                                EVP_PKEY_OP_DERIVE, \\\n                                EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p)\n\n# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID             (EVP_PKEY_ALG_CTRL + 1)\n# define EVP_PKEY_CTRL_EC_PARAM_ENC                      (EVP_PKEY_ALG_CTRL + 2)\n# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR                  (EVP_PKEY_ALG_CTRL + 3)\n# define EVP_PKEY_CTRL_EC_KDF_TYPE                       (EVP_PKEY_ALG_CTRL + 4)\n# define EVP_PKEY_CTRL_EC_KDF_MD                         (EVP_PKEY_ALG_CTRL + 5)\n# define EVP_PKEY_CTRL_GET_EC_KDF_MD                     (EVP_PKEY_ALG_CTRL + 6)\n# define EVP_PKEY_CTRL_EC_KDF_OUTLEN                     (EVP_PKEY_ALG_CTRL + 7)\n# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN                 (EVP_PKEY_ALG_CTRL + 8)\n# define EVP_PKEY_CTRL_EC_KDF_UKM                        (EVP_PKEY_ALG_CTRL + 9)\n# define EVP_PKEY_CTRL_GET_EC_KDF_UKM                    (EVP_PKEY_ALG_CTRL + 10)\n/* KDF types */\n# define EVP_PKEY_ECDH_KDF_NONE                          1\n# define EVP_PKEY_ECDH_KDF_X9_62                         2\n\n/* BEGIN ERROR CODES */\n/*\n * The following lines are auto generated by the script mkerr.pl. Any changes\n * made after this point may be overwritten when the script is next run.\n */\nvoid ERR_load_EC_strings(void);\n\n/* Error codes for the EC functions. */\n\n/* Function codes. */\n# define EC_F_BN_TO_FELEM                                 224\n# define EC_F_COMPUTE_WNAF                                143\n# define EC_F_D2I_ECPARAMETERS                            144\n# define EC_F_D2I_ECPKPARAMETERS                          145\n# define EC_F_D2I_ECPRIVATEKEY                            146\n# define EC_F_DO_EC_KEY_PRINT                             221\n# define EC_F_ECDH_CMS_DECRYPT                            238\n# define EC_F_ECDH_CMS_SET_SHARED_INFO                    239\n# define EC_F_ECKEY_PARAM2TYPE                            223\n# define EC_F_ECKEY_PARAM_DECODE                          212\n# define EC_F_ECKEY_PRIV_DECODE                           213\n# define EC_F_ECKEY_PRIV_ENCODE                           214\n# define EC_F_ECKEY_PUB_DECODE                            215\n# define EC_F_ECKEY_PUB_ENCODE                            216\n# define EC_F_ECKEY_TYPE2PARAM                            220\n# define EC_F_ECPARAMETERS_PRINT                          147\n# define EC_F_ECPARAMETERS_PRINT_FP                       148\n# define EC_F_ECPKPARAMETERS_PRINT                        149\n# define EC_F_ECPKPARAMETERS_PRINT_FP                     150\n# define EC_F_ECP_NISTZ256_GET_AFFINE                     240\n# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE                243\n# define EC_F_ECP_NISTZ256_POINTS_MUL                     241\n# define EC_F_ECP_NISTZ256_PRE_COMP_NEW                   244\n# define EC_F_ECP_NISTZ256_SET_WORDS                      245\n# define EC_F_ECP_NISTZ256_WINDOWED_MUL                   242\n# define EC_F_ECP_NIST_MOD_192                            203\n# define EC_F_ECP_NIST_MOD_224                            204\n# define EC_F_ECP_NIST_MOD_256                            205\n# define EC_F_ECP_NIST_MOD_521                            206\n# define EC_F_EC_ASN1_GROUP2CURVE                         153\n# define EC_F_EC_ASN1_GROUP2FIELDID                       154\n# define EC_F_EC_ASN1_GROUP2PARAMETERS                    155\n# define EC_F_EC_ASN1_GROUP2PKPARAMETERS                  156\n# define EC_F_EC_ASN1_PARAMETERS2GROUP                    157\n# define EC_F_EC_ASN1_PKPARAMETERS2GROUP                  158\n# define EC_F_EC_EX_DATA_SET_DATA                         211\n# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY           208\n# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT     159\n# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE              195\n# define EC_F_EC_GF2M_SIMPLE_OCT2POINT                    160\n# define EC_F_EC_GF2M_SIMPLE_POINT2OCT                    161\n# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162\n# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163\n# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES   164\n# define EC_F_EC_GFP_MONT_FIELD_DECODE                    133\n# define EC_F_EC_GFP_MONT_FIELD_ENCODE                    134\n# define EC_F_EC_GFP_MONT_FIELD_MUL                       131\n# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE                209\n# define EC_F_EC_GFP_MONT_FIELD_SQR                       132\n# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE                 189\n# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP             135\n# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE             225\n# define EC_F_EC_GFP_NISTP224_POINTS_MUL                  228\n# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226\n# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE             230\n# define EC_F_EC_GFP_NISTP256_POINTS_MUL                  231\n# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232\n# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE             233\n# define EC_F_EC_GFP_NISTP521_POINTS_MUL                  234\n# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235\n# define EC_F_EC_GFP_NIST_FIELD_MUL                       200\n# define EC_F_EC_GFP_NIST_FIELD_SQR                       201\n# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE                 202\n# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT      165\n# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE               166\n# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP           100\n# define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR           101\n# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE                   102\n# define EC_F_EC_GFP_SIMPLE_OCT2POINT                     103\n# define EC_F_EC_GFP_SIMPLE_POINT2OCT                     104\n# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE            137\n# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES  167\n# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105\n# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES  168\n# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128\n# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES    169\n# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129\n# define EC_F_EC_GROUP_CHECK                              170\n# define EC_F_EC_GROUP_CHECK_DISCRIMINANT                 171\n# define EC_F_EC_GROUP_COPY                               106\n# define EC_F_EC_GROUP_GET0_GENERATOR                     139\n# define EC_F_EC_GROUP_GET_COFACTOR                       140\n# define EC_F_EC_GROUP_GET_CURVE_GF2M                     172\n# define EC_F_EC_GROUP_GET_CURVE_GFP                      130\n# define EC_F_EC_GROUP_GET_DEGREE                         173\n# define EC_F_EC_GROUP_GET_ORDER                          141\n# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS              193\n# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS                194\n# define EC_F_EC_GROUP_NEW                                108\n# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME                  174\n# define EC_F_EC_GROUP_NEW_FROM_DATA                      175\n# define EC_F_EC_GROUP_PRECOMPUTE_MULT                    142\n# define EC_F_EC_GROUP_SET_CURVE_GF2M                     176\n# define EC_F_EC_GROUP_SET_CURVE_GFP                      109\n# define EC_F_EC_GROUP_SET_EXTRA_DATA                     110\n# define EC_F_EC_GROUP_SET_GENERATOR                      111\n# define EC_F_EC_KEY_CHECK_KEY                            177\n# define EC_F_EC_KEY_COPY                                 178\n# define EC_F_EC_KEY_GENERATE_KEY                         179\n# define EC_F_EC_KEY_NEW                                  182\n# define EC_F_EC_KEY_PRINT                                180\n# define EC_F_EC_KEY_PRINT_FP                             181\n# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES    229\n# define EC_F_EC_POINTS_MAKE_AFFINE                       136\n# define EC_F_EC_POINT_ADD                                112\n# define EC_F_EC_POINT_CMP                                113\n# define EC_F_EC_POINT_COPY                               114\n# define EC_F_EC_POINT_DBL                                115\n# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M        183\n# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP         116\n# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP    117\n# define EC_F_EC_POINT_INVERT                             210\n# define EC_F_EC_POINT_IS_AT_INFINITY                     118\n# define EC_F_EC_POINT_IS_ON_CURVE                        119\n# define EC_F_EC_POINT_MAKE_AFFINE                        120\n# define EC_F_EC_POINT_MUL                                184\n# define EC_F_EC_POINT_NEW                                121\n# define EC_F_EC_POINT_OCT2POINT                          122\n# define EC_F_EC_POINT_POINT2OCT                          123\n# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M        185\n# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP         124\n# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M    186\n# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP     125\n# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP    126\n# define EC_F_EC_POINT_SET_TO_INFINITY                    127\n# define EC_F_EC_PRE_COMP_DUP                             207\n# define EC_F_EC_PRE_COMP_NEW                             196\n# define EC_F_EC_WNAF_MUL                                 187\n# define EC_F_EC_WNAF_PRECOMPUTE_MULT                     188\n# define EC_F_I2D_ECPARAMETERS                            190\n# define EC_F_I2D_ECPKPARAMETERS                          191\n# define EC_F_I2D_ECPRIVATEKEY                            192\n# define EC_F_I2O_ECPUBLICKEY                             151\n# define EC_F_NISTP224_PRE_COMP_NEW                       227\n# define EC_F_NISTP256_PRE_COMP_NEW                       236\n# define EC_F_NISTP521_PRE_COMP_NEW                       237\n# define EC_F_O2I_ECPUBLICKEY                             152\n# define EC_F_OLD_EC_PRIV_DECODE                          222\n# define EC_F_PKEY_EC_CTRL                                197\n# define EC_F_PKEY_EC_CTRL_STR                            198\n# define EC_F_PKEY_EC_DERIVE                              217\n# define EC_F_PKEY_EC_KEYGEN                              199\n# define EC_F_PKEY_EC_PARAMGEN                            219\n# define EC_F_PKEY_EC_SIGN                                218\n\n/* Reason codes. */\n# define EC_R_ASN1_ERROR                                  115\n# define EC_R_ASN1_UNKNOWN_FIELD                          116\n# define EC_R_BIGNUM_OUT_OF_RANGE                         144\n# define EC_R_BUFFER_TOO_SMALL                            100\n# define EC_R_COORDINATES_OUT_OF_RANGE                    146\n# define EC_R_D2I_ECPKPARAMETERS_FAILURE                  117\n# define EC_R_DECODE_ERROR                                142\n# define EC_R_DISCRIMINANT_IS_ZERO                        118\n# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE                119\n# define EC_R_FIELD_TOO_LARGE                             143\n# define EC_R_GF2M_NOT_SUPPORTED                          147\n# define EC_R_GROUP2PKPARAMETERS_FAILURE                  120\n# define EC_R_I2D_ECPKPARAMETERS_FAILURE                  121\n# define EC_R_INCOMPATIBLE_OBJECTS                        101\n# define EC_R_INVALID_ARGUMENT                            112\n# define EC_R_INVALID_COMPRESSED_POINT                    110\n# define EC_R_INVALID_COMPRESSION_BIT                     109\n# define EC_R_INVALID_CURVE                               141\n# define EC_R_INVALID_DIGEST                              151\n# define EC_R_INVALID_DIGEST_TYPE                         138\n# define EC_R_INVALID_ENCODING                            102\n# define EC_R_INVALID_FIELD                               103\n# define EC_R_INVALID_FORM                                104\n# define EC_R_INVALID_GROUP_ORDER                         122\n# define EC_R_INVALID_PENTANOMIAL_BASIS                   132\n# define EC_R_INVALID_PRIVATE_KEY                         123\n# define EC_R_INVALID_TRINOMIAL_BASIS                     137\n# define EC_R_KDF_PARAMETER_ERROR                         148\n# define EC_R_KEYS_NOT_SET                                140\n# define EC_R_MISSING_PARAMETERS                          124\n# define EC_R_MISSING_PRIVATE_KEY                         125\n# define EC_R_NOT_A_NIST_PRIME                            135\n# define EC_R_NOT_A_SUPPORTED_NIST_PRIME                  136\n# define EC_R_NOT_IMPLEMENTED                             126\n# define EC_R_NOT_INITIALIZED                             111\n# define EC_R_NO_FIELD_MOD                                133\n# define EC_R_NO_PARAMETERS_SET                           139\n# define EC_R_PASSED_NULL_PARAMETER                       134\n# define EC_R_PEER_KEY_ERROR                              149\n# define EC_R_PKPARAMETERS2GROUP_FAILURE                  127\n# define EC_R_POINT_AT_INFINITY                           106\n# define EC_R_POINT_IS_NOT_ON_CURVE                       107\n# define EC_R_SHARED_INFO_ERROR                           150\n# define EC_R_SLOT_FULL                                   108\n# define EC_R_UNDEFINED_GENERATOR                         113\n# define EC_R_UNDEFINED_ORDER                             128\n# define EC_R_UNKNOWN_GROUP                               129\n# define EC_R_UNKNOWN_ORDER                               114\n# define EC_R_UNSUPPORTED_FIELD                           131\n# define EC_R_WRONG_CURVE_PARAMETERS                      145\n# define EC_R_WRONG_ORDER                                 130\n\n#ifdef  __cplusplus\n}\n#endif\n#endif\n"
  },
  {
    "path": "deps/cl345/bn/ec_lcl.h",
    "content": "/* crypto/ec/ec_lcl.h */\n/*\n * Originally written by Bodo Moeller for the OpenSSL project.\n */\n/* ====================================================================\n * Copyright (c) 1998-2010 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n *\n * Portions of the attached software (\"Contribution\") are developed by\n * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.\n *\n * The Contribution is licensed pursuant to the OpenSSL open source\n * license provided above.\n *\n * The elliptic curve binary polynomial software is originally written by\n * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.\n *\n */\n\n#include <stdlib.h>\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"bn.h\"\n  #include \"ec.h\"\n#else\n  #include \"bn/bn.h\"\n  #include \"bn/ec.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\n#if defined(__SUNPRO_C)\n# if __SUNPRO_C >= 0x520\n#  pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)\n# endif\n#endif\n\n/* Use default functions for poin2oct, oct2point and compressed coordinates */\n#define EC_FLAGS_DEFAULT_OCT    0x1\n\n/*\n * Structure details are not part of the exported interface, so all this may\n * change in future versions.\n */\n\nstruct ec_method_st {\n    /* Various method flags */\n    int flags;\n    /* used by EC_METHOD_get_field_type: */\n    int field_type;             /* a NID */\n    /*\n     * used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free,\n     * EC_GROUP_copy:\n     */\n    int (*group_init) (EC_GROUP *);\n    void (*group_finish) (EC_GROUP *);\n    void (*group_clear_finish) (EC_GROUP *);\n    int (*group_copy) (EC_GROUP *, const EC_GROUP *);\n    /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */\n    /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */\n    int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a,\n                            const BIGNUM *b, BN_CTX *);\n    int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b,\n                            BN_CTX *);\n    /* used by EC_GROUP_get_degree: */\n    int (*group_get_degree) (const EC_GROUP *);\n    /* used by EC_GROUP_check: */\n    int (*group_check_discriminant) (const EC_GROUP *, BN_CTX *);\n    /*\n     * used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free,\n     * EC_POINT_copy:\n     */\n    int (*point_init) (EC_POINT *);\n    void (*point_finish) (EC_POINT *);\n    void (*point_clear_finish) (EC_POINT *);\n    int (*point_copy) (EC_POINT *, const EC_POINT *);\n    /*-\n     * used by EC_POINT_set_to_infinity,\n     * EC_POINT_set_Jprojective_coordinates_GFp,\n     * EC_POINT_get_Jprojective_coordinates_GFp,\n     * EC_POINT_set_affine_coordinates_GFp,     ..._GF2m,\n     * EC_POINT_get_affine_coordinates_GFp,     ..._GF2m,\n     * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:\n     */\n    int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *);\n    int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,\n                                                  EC_POINT *, const BIGNUM *x,\n                                                  const BIGNUM *y,\n                                                  const BIGNUM *z, BN_CTX *);\n    int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *,\n                                                  const EC_POINT *, BIGNUM *x,\n                                                  BIGNUM *y, BIGNUM *z,\n                                                  BN_CTX *);\n    int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *,\n                                         const BIGNUM *x, const BIGNUM *y,\n                                         BN_CTX *);\n    int (*point_get_affine_coordinates) (const EC_GROUP *, const EC_POINT *,\n                                         BIGNUM *x, BIGNUM *y, BN_CTX *);\n    int (*point_set_compressed_coordinates) (const EC_GROUP *, EC_POINT *,\n                                             const BIGNUM *x, int y_bit,\n                                             BN_CTX *);\n    /* used by EC_POINT_point2oct, EC_POINT_oct2point: */\n    size_t (*point2oct) (const EC_GROUP *, const EC_POINT *,\n                         point_conversion_form_t form, unsigned char *buf,\n                         size_t len, BN_CTX *);\n    int (*oct2point) (const EC_GROUP *, EC_POINT *, const unsigned char *buf,\n                      size_t len, BN_CTX *);\n    /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */\n    int (*add) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a,\n                const EC_POINT *b, BN_CTX *);\n    int (*dbl) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);\n    int (*invert) (const EC_GROUP *, EC_POINT *, BN_CTX *);\n    /*\n     * used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp:\n     */\n    int (*is_at_infinity) (const EC_GROUP *, const EC_POINT *);\n    int (*is_on_curve) (const EC_GROUP *, const EC_POINT *, BN_CTX *);\n    int (*point_cmp) (const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,\n                      BN_CTX *);\n    /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */\n    int (*make_affine) (const EC_GROUP *, EC_POINT *, BN_CTX *);\n    int (*points_make_affine) (const EC_GROUP *, size_t num, EC_POINT *[],\n                               BN_CTX *);\n    /*\n     * used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult,\n     * EC_POINT_have_precompute_mult (default implementations are used if the\n     * 'mul' pointer is 0):\n     */\n    int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                size_t num, const EC_POINT *points[], const BIGNUM *scalars[],\n                BN_CTX *);\n    int (*precompute_mult) (EC_GROUP *group, BN_CTX *);\n    int (*have_precompute_mult) (const EC_GROUP *group);\n    /* internal functions */\n    /*\n     * 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and\n     * 'dbl' so that the same implementations of point operations can be used\n     * with different optimized implementations of expensive field\n     * operations:\n     */\n    int (*field_mul) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                      const BIGNUM *b, BN_CTX *);\n    int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);\n    int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                      const BIGNUM *b, BN_CTX *);\n    /* e.g. to Montgomery */\n    int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                         BN_CTX *);\n    /* e.g. from Montgomery */\n    int (*field_decode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                         BN_CTX *);\n    int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *);\n} /* EC_METHOD */ ;\n\ntypedef struct ec_extra_data_st {\n    struct ec_extra_data_st *next;\n    void *data;\n    void *(*dup_func) (void *);\n    void (*free_func) (void *);\n    void (*clear_free_func) (void *);\n} EC_EXTRA_DATA;                /* used in EC_GROUP */\n\nstruct ec_group_st {\n    const EC_METHOD *meth;\n    EC_POINT *generator;        /* optional */\n    BIGNUM order, cofactor;\n    int curve_name;             /* optional NID for named curve */\n    int asn1_flag;              /* flag to control the asn1 encoding */\n    /*\n     * Kludge: upper bit of ans1_flag is used to denote structure\n     * version. Is set, then last field is present. This is done\n     * for interoperation with FIPS code.\n     */\n#define EC_GROUP_ASN1_FLAG_MASK 0x7fffffff\n#define EC_GROUP_VERSION(p) (p->asn1_flag&~EC_GROUP_ASN1_FLAG_MASK)\n    point_conversion_form_t asn1_form;\n    unsigned char *seed;        /* optional seed for parameters (appears in\n                                 * ASN1) */\n    size_t seed_len;\n    EC_EXTRA_DATA *extra_data;  /* linked list */\n    /*\n     * The following members are handled by the method functions, even if\n     * they appear generic\n     */\n    /*\n     * Field specification. For curves over GF(p), this is the modulus; for\n     * curves over GF(2^m), this is the irreducible polynomial defining the\n     * field.\n     */\n    BIGNUM field;\n    /*\n     * Field specification for curves over GF(2^m). The irreducible f(t) is\n     * then of the form: t^poly[0] + t^poly[1] + ... + t^poly[k] where m =\n     * poly[0] > poly[1] > ... > poly[k] = 0. The array is terminated with\n     * poly[k+1]=-1. All elliptic curve irreducibles have at most 5 non-zero\n     * terms.\n     */\n    int poly[6];\n    /*\n     * Curve coefficients. (Here the assumption is that BIGNUMs can be used\n     * or abused for all kinds of fields, not just GF(p).) For characteristic\n     * > 3, the curve is defined by a Weierstrass equation of the form y^2 =\n     * x^3 + a*x + b. For characteristic 2, the curve is defined by an\n     * equation of the form y^2 + x*y = x^3 + a*x^2 + b.\n     */\n    BIGNUM a, b;\n    /* enable optimized point arithmetics for special case */\n    int a_is_minus3;\n    /* method-specific (e.g., Montgomery structure) */\n    void *field_data1;\n    /* method-specific */\n    void *field_data2;\n    /* method-specific */\n    int (*field_mod_func) (BIGNUM *, const BIGNUM *, const BIGNUM *,\n                           BN_CTX *);\n    BN_MONT_CTX *mont_data;     /* data for ECDSA inverse */\n} /* EC_GROUP */ ;\n\nstruct ec_key_st {\n    int version;\n    EC_GROUP *group;\n    EC_POINT *pub_key;\n    BIGNUM *priv_key;\n    unsigned int enc_flag;\n    point_conversion_form_t conv_form;\n    int references;\n    int flags;\n    EC_EXTRA_DATA *method_data;\n} /* EC_KEY */ ;\n\n/*\n * Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs\n * only (with visibility limited to 'package' level for now). We use the\n * function pointers as index for retrieval; this obviates global\n * ex_data-style index tables.\n */\nint EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,\n                        void *(*dup_func) (void *),\n                        void (*free_func) (void *),\n                        void (*clear_free_func) (void *));\nvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *, void *(*dup_func) (void *),\n                          void (*free_func) (void *),\n                          void (*clear_free_func) (void *));\nvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *),\n                          void (*free_func) (void *),\n                          void (*clear_free_func) (void *));\nvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *),\n                                void (*free_func) (void *),\n                                void (*clear_free_func) (void *));\nvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);\nvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);\n\nstruct ec_point_st {\n    const EC_METHOD *meth;\n    /*\n     * All members except 'meth' are handled by the method functions, even if\n     * they appear generic\n     */\n    BIGNUM X;\n    BIGNUM Y;\n    BIGNUM Z;                   /* Jacobian projective coordinates: (X, Y, Z)\n                                 * represents (X/Z^2, Y/Z^3) if Z != 0 */\n    int Z_is_one;               /* enable optimized point arithmetics for\n                                 * special case */\n} /* EC_POINT */ ;\n\n/*\n * method functions in ec_mult.c (ec_lib.c uses these as defaults if\n * group->method->mul is 0)\n */\nint ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                size_t num, const EC_POINT *points[], const BIGNUM *scalars[],\n                BN_CTX *);\nint ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);\nint ec_wNAF_have_precompute_mult(const EC_GROUP *group);\n\n/* method functions in ecp_smpl.c */\nint ec_GFp_simple_group_init(EC_GROUP *);\nvoid ec_GFp_simple_group_finish(EC_GROUP *);\nvoid ec_GFp_simple_group_clear_finish(EC_GROUP *);\nint ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);\nint ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,\n                                  const BIGNUM *a, const BIGNUM *b, BN_CTX *);\nint ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,\n                                  BIGNUM *b, BN_CTX *);\nint ec_GFp_simple_group_get_degree(const EC_GROUP *);\nint ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);\nint ec_GFp_simple_point_init(EC_POINT *);\nvoid ec_GFp_simple_point_finish(EC_POINT *);\nvoid ec_GFp_simple_point_clear_finish(EC_POINT *);\nint ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);\nint ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);\nint ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *,\n                                                  EC_POINT *, const BIGNUM *x,\n                                                  const BIGNUM *y,\n                                                  const BIGNUM *z, BN_CTX *);\nint ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,\n                                                  const EC_POINT *, BIGNUM *x,\n                                                  BIGNUM *y, BIGNUM *z,\n                                                  BN_CTX *);\nint ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,\n                                               const BIGNUM *x,\n                                               const BIGNUM *y, BN_CTX *);\nint ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,\n                                               const EC_POINT *, BIGNUM *x,\n                                               BIGNUM *y, BN_CTX *);\nint ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,\n                                             const BIGNUM *x, int y_bit,\n                                             BN_CTX *);\nsize_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *,\n                               point_conversion_form_t form,\n                               unsigned char *buf, size_t len, BN_CTX *);\nint ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,\n                            const unsigned char *buf, size_t len, BN_CTX *);\nint ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,\n                      const EC_POINT *b, BN_CTX *);\nint ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,\n                      BN_CTX *);\nint ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);\nint ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);\nint ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);\nint ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,\n                      BN_CTX *);\nint ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);\nint ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num,\n                                     EC_POINT *[], BN_CTX *);\nint ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                            const BIGNUM *b, BN_CTX *);\nint ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                            BN_CTX *);\n\n/* method functions in ecp_mont.c */\nint ec_GFp_mont_group_init(EC_GROUP *);\nint ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,\n                                const BIGNUM *b, BN_CTX *);\nvoid ec_GFp_mont_group_finish(EC_GROUP *);\nvoid ec_GFp_mont_group_clear_finish(EC_GROUP *);\nint ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);\nint ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                          const BIGNUM *b, BN_CTX *);\nint ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                          BN_CTX *);\nint ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                             BN_CTX *);\nint ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                             BN_CTX *);\nint ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);\n\n/* method functions in ecp_nist.c */\nint ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);\nint ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,\n                                const BIGNUM *b, BN_CTX *);\nint ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                          const BIGNUM *b, BN_CTX *);\nint ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                          BN_CTX *);\n\n/* method functions in ec2_smpl.c */\nint ec_GF2m_simple_group_init(EC_GROUP *);\nvoid ec_GF2m_simple_group_finish(EC_GROUP *);\nvoid ec_GF2m_simple_group_clear_finish(EC_GROUP *);\nint ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);\nint ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,\n                                   const BIGNUM *a, const BIGNUM *b,\n                                   BN_CTX *);\nint ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,\n                                   BIGNUM *b, BN_CTX *);\nint ec_GF2m_simple_group_get_degree(const EC_GROUP *);\nint ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);\nint ec_GF2m_simple_point_init(EC_POINT *);\nvoid ec_GF2m_simple_point_finish(EC_POINT *);\nvoid ec_GF2m_simple_point_clear_finish(EC_POINT *);\nint ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);\nint ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);\nint ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,\n                                                const BIGNUM *x,\n                                                const BIGNUM *y, BN_CTX *);\nint ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *,\n                                                const EC_POINT *, BIGNUM *x,\n                                                BIGNUM *y, BN_CTX *);\nint ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,\n                                              const BIGNUM *x, int y_bit,\n                                              BN_CTX *);\nsize_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *,\n                                point_conversion_form_t form,\n                                unsigned char *buf, size_t len, BN_CTX *);\nint ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,\n                             const unsigned char *buf, size_t len, BN_CTX *);\nint ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,\n                       const EC_POINT *b, BN_CTX *);\nint ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,\n                       BN_CTX *);\nint ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);\nint ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);\nint ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);\nint ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,\n                       BN_CTX *);\nint ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);\nint ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num,\n                                      EC_POINT *[], BN_CTX *);\nint ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                             const BIGNUM *b, BN_CTX *);\nint ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                             BN_CTX *);\nint ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,\n                             const BIGNUM *b, BN_CTX *);\n\n/* method functions in ec2_mult.c */\nint ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,\n                       const BIGNUM *scalar, size_t num,\n                       const EC_POINT *points[], const BIGNUM *scalars[],\n                       BN_CTX *);\nint ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);\nint ec_GF2m_have_precompute_mult(const EC_GROUP *group);\n\n#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128\n/* method functions in ecp_nistp224.c */\nint ec_GFp_nistp224_group_init(EC_GROUP *group);\nint ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,\n                                    const BIGNUM *a, const BIGNUM *n,\n                                    BN_CTX *);\nint ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,\n                                                 const EC_POINT *point,\n                                                 BIGNUM *x, BIGNUM *y,\n                                                 BN_CTX *ctx);\nint ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r,\n                        const BIGNUM *scalar, size_t num,\n                        const EC_POINT *points[], const BIGNUM *scalars[],\n                        BN_CTX *);\nint ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,\n                               const BIGNUM *scalar, size_t num,\n                               const EC_POINT *points[],\n                               const BIGNUM *scalars[], BN_CTX *ctx);\nint ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);\nint ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);\n\n/* method functions in ecp_nistp256.c */\nint ec_GFp_nistp256_group_init(EC_GROUP *group);\nint ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,\n                                    const BIGNUM *a, const BIGNUM *n,\n                                    BN_CTX *);\nint ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,\n                                                 const EC_POINT *point,\n                                                 BIGNUM *x, BIGNUM *y,\n                                                 BN_CTX *ctx);\nint ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r,\n                        const BIGNUM *scalar, size_t num,\n                        const EC_POINT *points[], const BIGNUM *scalars[],\n                        BN_CTX *);\nint ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,\n                               const BIGNUM *scalar, size_t num,\n                               const EC_POINT *points[],\n                               const BIGNUM *scalars[], BN_CTX *ctx);\nint ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);\nint ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);\n\n/* method functions in ecp_nistp521.c */\nint ec_GFp_nistp521_group_init(EC_GROUP *group);\nint ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,\n                                    const BIGNUM *a, const BIGNUM *n,\n                                    BN_CTX *);\nint ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,\n                                                 const EC_POINT *point,\n                                                 BIGNUM *x, BIGNUM *y,\n                                                 BN_CTX *ctx);\nint ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r,\n                        const BIGNUM *scalar, size_t num,\n                        const EC_POINT *points[], const BIGNUM *scalars[],\n                        BN_CTX *);\nint ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,\n                               const BIGNUM *scalar, size_t num,\n                               const EC_POINT *points[],\n                               const BIGNUM *scalars[], BN_CTX *ctx);\nint ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);\nint ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);\n\n/* utility functions in ecp_nistputil.c */\nvoid ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,\n                                              size_t felem_size,\n                                              void *tmp_felems,\n                                              void (*felem_one) (void *out),\n                                              int (*felem_is_zero) (const void\n                                                                    *in),\n                                              void (*felem_assign) (void *out,\n                                                                    const void\n                                                                    *in),\n                                              void (*felem_square) (void *out,\n                                                                    const void\n                                                                    *in),\n                                              void (*felem_mul) (void *out,\n                                                                 const void\n                                                                 *in1,\n                                                                 const void\n                                                                 *in2),\n                                              void (*felem_inv) (void *out,\n                                                                 const void\n                                                                 *in),\n                                              void (*felem_contract) (void\n                                                                      *out,\n                                                                      const\n                                                                      void\n                                                                      *in));\nvoid ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,\n                                     unsigned char *digit, unsigned char in);\n#endif\nint ec_precompute_mont_data(EC_GROUP *);\n\n#ifdef ECP_NISTZ256_ASM\n/** Returns GFp methods using montgomery multiplication, with x86-64 optimized\n * P256. See http://eprint.iacr.org/2013/816.\n *  \\return  EC_METHOD object\n */\nconst EC_METHOD *EC_GFp_nistz256_method(void);\n#endif\n\n#ifdef OPENSSL_FIPS\nEC_GROUP *FIPS_ec_group_new_curve_gfp(const BIGNUM *p, const BIGNUM *a,\n                                      const BIGNUM *b, BN_CTX *ctx);\nEC_GROUP *FIPS_ec_group_new_curve_gf2m(const BIGNUM *p, const BIGNUM *a,\n                                       const BIGNUM *b, BN_CTX *ctx);\nEC_GROUP *FIPS_ec_group_new_by_curve_name(int nid);\n#endif\n"
  },
  {
    "path": "deps/cl345/bn/ec_lib.c",
    "content": "/* crypto/ec/ec_lib.c */\n/*\n * Originally written by Bodo Moeller for the OpenSSL project.\n */\n/* ====================================================================\n * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n * Binary polynomial ECC support in OpenSSL originally developed by\n * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.\n */\n\n#include <string.h>\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"ec_lcl.h\"\n#else\n  #include \"bn/ec_lcl.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\t\t/* pcg */\n\n/* functions for EC_GROUP objects */\n\nEC_GROUP *EC_GROUP_new(const EC_METHOD *meth)\n{\n    EC_GROUP *ret;\n\n    if (meth == NULL) {\n        ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);\n        return NULL;\n    }\n    if (meth->group_init == 0) {\n        ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return NULL;\n    }\n\n\tret = clBnAlloc( \"EC_GROUP_new\",sizeof *ret);\t/* pcg */\n    if (ret == NULL) {\n        ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);\n        return NULL;\n    }\n\tmemset( ret, 0, sizeof( EC_GROUP ) );\t\t\t/* pcg */\n\n    ret->meth = meth;\n\n    ret->extra_data = NULL;\n    ret->mont_data = NULL;\n\n    ret->generator = NULL;\n    BN_init(&ret->order);\n    BN_init(&ret->cofactor);\n\n    ret->curve_name = 0;\n    ret->asn1_flag = ~EC_GROUP_ASN1_FLAG_MASK;\n    ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;\n\n    ret->seed = NULL;\n    ret->seed_len = 0;\n\n    if (!meth->group_init(ret)) {\n        OPENSSL_free(ret);\n        return NULL;\n    }\n\n    return ret;\n}\n\nvoid EC_GROUP_free(EC_GROUP *group)\n{\n    if (!group)\n        return;\n\n    if (group->meth->group_finish != 0)\n        group->meth->group_finish(group);\n\n    EC_EX_DATA_free_all_data(&group->extra_data);\n\n    if (EC_GROUP_VERSION(group) && group->mont_data)\n        BN_MONT_CTX_free(group->mont_data);\n\n    if (group->generator != NULL)\n        EC_POINT_free(group->generator);\n    BN_free(&group->order);\n    BN_free(&group->cofactor);\n\n    if (group->seed)\n        OPENSSL_free(group->seed);\n\n    OPENSSL_free(group);\n}\n\nvoid EC_GROUP_clear_free(EC_GROUP *group)\n{\n    if (!group)\n        return;\n\n    if (group->meth->group_clear_finish != 0)\n        group->meth->group_clear_finish(group);\n    else if (group->meth->group_finish != 0)\n        group->meth->group_finish(group);\n\n    EC_EX_DATA_clear_free_all_data(&group->extra_data);\n\n    if (EC_GROUP_VERSION(group) && group->mont_data)\n        BN_MONT_CTX_free(group->mont_data);\n\n    if (group->generator != NULL)\n        EC_POINT_clear_free(group->generator);\n    BN_clear_free(&group->order);\n    BN_clear_free(&group->cofactor);\n\n    if (group->seed) {\n        OPENSSL_cleanse(group->seed, group->seed_len);\n        OPENSSL_free(group->seed);\n    }\n\n    OPENSSL_cleanse(group, sizeof *group);\n    OPENSSL_free(group);\n}\n\nint EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)\n{\n    EC_EXTRA_DATA *d;\n\n    if (dest->meth->group_copy == 0) {\n        ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (dest->meth != src->meth) {\n        ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    if (dest == src)\n        return 1;\n\n    EC_EX_DATA_free_all_data(&dest->extra_data);\n\n    for (d = src->extra_data; d != NULL; d = d->next) {\n        void *t = d->dup_func(d->data);\n\n        if (t == NULL)\n            return 0;\n        if (!EC_EX_DATA_set_data\n            (&dest->extra_data, t, d->dup_func, d->free_func,\n             d->clear_free_func))\n            return 0;\n    }\n\n    if (EC_GROUP_VERSION(src) && src->mont_data != NULL) {\n        if (dest->mont_data == NULL) {\n            dest->mont_data = BN_MONT_CTX_new();\n            if (dest->mont_data == NULL)\n                return 0;\n        }\n        if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))\n            return 0;\n    } else {\n        /* src->generator == NULL */\n        if (EC_GROUP_VERSION(dest) && dest->mont_data != NULL) {\n            BN_MONT_CTX_free(dest->mont_data);\n            dest->mont_data = NULL;\n        }\n    }\n\n    if (src->generator != NULL) {\n        if (dest->generator == NULL) {\n            dest->generator = EC_POINT_new(dest);\n            if (dest->generator == NULL)\n                return 0;\n        }\n        if (!EC_POINT_copy(dest->generator, src->generator))\n            return 0;\n    } else {\n        /* src->generator == NULL */\n        if (dest->generator != NULL) {\n            EC_POINT_clear_free(dest->generator);\n            dest->generator = NULL;\n        }\n    }\n\n    if (!BN_copy(&dest->order, &src->order))\n        return 0;\n    if (!BN_copy(&dest->cofactor, &src->cofactor))\n        return 0;\n\n    dest->curve_name = src->curve_name;\n    dest->asn1_flag = src->asn1_flag;\n    dest->asn1_form = src->asn1_form;\n\n    if (src->seed) {\n        if (dest->seed)\n            OPENSSL_free(dest->seed);\n\t\tdest->seed = clBnAlloc( \"EC_GROUP_copy\",src->seed_len);\t\t/* pcg */\n        if (dest->seed == NULL)\n            return 0;\n        if (!memcpy(dest->seed, src->seed, src->seed_len))\n            return 0;\n        dest->seed_len = src->seed_len;\n    } else {\n        if (dest->seed)\n            OPENSSL_free(dest->seed);\n        dest->seed = NULL;\n        dest->seed_len = 0;\n    }\n\n    return dest->meth->group_copy(dest, src);\n}\n\nEC_GROUP *EC_GROUP_dup(const EC_GROUP *a)\n{\n    EC_GROUP *t = NULL;\n    int ok = 0;\n\n    if (a == NULL)\n        return NULL;\n\n    if ((t = EC_GROUP_new(a->meth)) == NULL)\n        return (NULL);\n    if (!EC_GROUP_copy(t, a))\n        goto err;\n\n    ok = 1;\n\n err:\n    if (!ok) {\n        if (t)\n            EC_GROUP_free(t);\n        return NULL;\n    } else\n        return t;\n}\n\nconst EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)\n{\n    return group->meth;\n}\n\nint EC_METHOD_get_field_type(const EC_METHOD *meth)\n{\n    return meth->field_type;\n}\n\nint EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,\n                           const BIGNUM *order, const BIGNUM *cofactor)\n{\n    if (generator == NULL) {\n        ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);\n        return 0;\n    }\n\n    if (group->generator == NULL) {\n        group->generator = EC_POINT_new(group);\n        if (group->generator == NULL)\n            return 0;\n    }\n    if (!EC_POINT_copy(group->generator, generator))\n        return 0;\n\n    if (order != NULL) {\n        if (!BN_copy(&group->order, order))\n            return 0;\n    } else\n        BN_zero(&group->order);\n\n    if (cofactor != NULL) {\n        if (!BN_copy(&group->cofactor, cofactor))\n            return 0;\n    } else\n        BN_zero(&group->cofactor);\n\n    /*\n     * We ignore the return value because some groups have an order with\n     * factors of two, which makes the Montgomery setup fail.\n     * |group->mont_data| will be NULL in this case.\n     */\n    ec_precompute_mont_data(group);\n\n    return 1;\n}\n\nconst EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)\n{\n    return group->generator;\n}\n\nBN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)\n{\n    return EC_GROUP_VERSION(group) ? group->mont_data : NULL;\n}\n\nint EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)\n{\n    if (!BN_copy(order, &group->order))\n        return 0;\n\n    return !BN_is_zero(order);\n}\n\nint EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,\n                          BN_CTX *ctx)\n{\n    if (!BN_copy(cofactor, &group->cofactor))\n        return 0;\n\n    return !BN_is_zero(&group->cofactor);\n}\n\nvoid EC_GROUP_set_curve_name(EC_GROUP *group, int nid)\n{\n    group->curve_name = nid;\n}\n\nint EC_GROUP_get_curve_name(const EC_GROUP *group)\n{\n    return group->curve_name;\n}\n\nvoid EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)\n{\n    group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK;\n    group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK;\n}\n\nint EC_GROUP_get_asn1_flag(const EC_GROUP *group)\n{\n    return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK;\n}\n\nvoid EC_GROUP_set_point_conversion_form(EC_GROUP *group,\n                                        point_conversion_form_t form)\n{\n    group->asn1_form = form;\n}\n\npoint_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP\n                                                           *group)\n{\n    return group->asn1_form;\n}\n\nsize_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)\n{\n    if (group->seed) {\n        OPENSSL_free(group->seed);\n        group->seed = NULL;\n        group->seed_len = 0;\n    }\n\n    if (!len || !p)\n        return 1;\n\n\tif ((group->seed = clBnAlloc( \"EC_GROUP_set_seed\",len)) == NULL)\t/* pcg */\n        return 0;\n    memcpy(group->seed, p, len);\n    group->seed_len = len;\n\n    return len;\n}\n\nunsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)\n{\n    return group->seed;\n}\n\nsize_t EC_GROUP_get_seed_len(const EC_GROUP *group)\n{\n    return group->seed_len;\n}\n\nint EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,\n                           const BIGNUM *b, BN_CTX *ctx)\n{\n    if (group->meth->group_set_curve == 0) {\n        ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_set_curve(group, p, a, b, ctx);\n}\n\nint EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,\n                           BIGNUM *b, BN_CTX *ctx)\n{\n    if (group->meth->group_get_curve == 0) {\n        ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_get_curve(group, p, a, b, ctx);\n}\n\n#ifndef OPENSSL_NO_EC2M\nint EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,\n                            const BIGNUM *b, BN_CTX *ctx)\n{\n    if (group->meth->group_set_curve == 0) {\n        ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_set_curve(group, p, a, b, ctx);\n}\n\nint EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,\n                            BIGNUM *b, BN_CTX *ctx)\n{\n    if (group->meth->group_get_curve == 0) {\n        ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_get_curve(group, p, a, b, ctx);\n}\n#endif\n\nint EC_GROUP_get_degree(const EC_GROUP *group)\n{\n    if (group->meth->group_get_degree == 0) {\n        ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_get_degree(group);\n}\n\nint EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)\n{\n    if (group->meth->group_check_discriminant == 0) {\n        ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    return group->meth->group_check_discriminant(group, ctx);\n}\n\nint EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)\n{\n    int r = 0;\n    BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;\n    BN_CTX *ctx_new = NULL;\n\n    /* compare the field types */\n    if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=\n        EC_METHOD_get_field_type(EC_GROUP_method_of(b)))\n        return 1;\n    /* compare the curve name (if present in both) */\n    if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&\n        EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))\n        return 1;\n\n    if (!ctx)\n        ctx_new = ctx = BN_CTX_new();\n    if (!ctx)\n        return -1;\n\n    BN_CTX_start(ctx);\n    a1 = BN_CTX_get(ctx);\n    a2 = BN_CTX_get(ctx);\n    a3 = BN_CTX_get(ctx);\n    b1 = BN_CTX_get(ctx);\n    b2 = BN_CTX_get(ctx);\n    b3 = BN_CTX_get(ctx);\n    if (!b3) {\n        BN_CTX_end(ctx);\n        if (ctx_new)\n            BN_CTX_free(ctx);\n        return -1;\n    }\n\n    /*\n     * XXX This approach assumes that the external representation of curves\n     * over the same field type is the same.\n     */\n    if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||\n        !b->meth->group_get_curve(b, b1, b2, b3, ctx))\n        r = 1;\n\n    if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))\n        r = 1;\n\n    /* XXX EC_POINT_cmp() assumes that the methods are equal */\n    if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),\n                          EC_GROUP_get0_generator(b), ctx))\n        r = 1;\n\n    if (!r) {\n        /* compare the order and cofactor */\n        if (!EC_GROUP_get_order(a, a1, ctx) ||\n            !EC_GROUP_get_order(b, b1, ctx) ||\n            !EC_GROUP_get_cofactor(a, a2, ctx) ||\n            !EC_GROUP_get_cofactor(b, b2, ctx)) {\n            BN_CTX_end(ctx);\n            if (ctx_new)\n                BN_CTX_free(ctx);\n            return -1;\n        }\n        if (BN_cmp(a1, b1) || BN_cmp(a2, b2))\n            r = 1;\n    }\n\n    BN_CTX_end(ctx);\n    if (ctx_new)\n        BN_CTX_free(ctx);\n\n    return r;\n}\n\n/* this has 'package' visibility */\nint EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,\n                        void *(*dup_func) (void *),\n                        void (*free_func) (void *),\n                        void (*clear_free_func) (void *))\n{\n    EC_EXTRA_DATA *d;\n\n    if (ex_data == NULL)\n        return 0;\n\n    for (d = *ex_data; d != NULL; d = d->next) {\n        if (d->dup_func == dup_func && d->free_func == free_func\n            && d->clear_free_func == clear_free_func) {\n            ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);\n            return 0;\n        }\n    }\n\n    if (data == NULL)\n        /* no explicit entry needed */\n        return 1;\n\n\td = clBnAlloc( \"EC_EX_DATA_set_data\",sizeof *d);\t/* pcg */\n    if (d == NULL)\n        return 0;\n\n    d->data = data;\n    d->dup_func = dup_func;\n    d->free_func = free_func;\n    d->clear_free_func = clear_free_func;\n\n    d->next = *ex_data;\n    *ex_data = d;\n\n    return 1;\n}\n\n/* this has 'package' visibility */\nvoid *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,\n                          void *(*dup_func) (void *),\n                          void (*free_func) (void *),\n                          void (*clear_free_func) (void *))\n{\n    const EC_EXTRA_DATA *d;\n\n    for (d = ex_data; d != NULL; d = d->next) {\n        if (d->dup_func == dup_func && d->free_func == free_func\n            && d->clear_free_func == clear_free_func)\n            return d->data;\n    }\n\n    return NULL;\n}\n\n/* this has 'package' visibility */\nvoid EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,\n                          void *(*dup_func) (void *),\n                          void (*free_func) (void *),\n                          void (*clear_free_func) (void *))\n{\n    EC_EXTRA_DATA **p;\n\n    if (ex_data == NULL)\n        return;\n\n    for (p = ex_data; *p != NULL; p = &((*p)->next)) {\n        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func\n            && (*p)->clear_free_func == clear_free_func) {\n            EC_EXTRA_DATA *next = (*p)->next;\n\n            (*p)->free_func((*p)->data);\n            OPENSSL_free(*p);\n\n            *p = next;\n            return;\n        }\n    }\n}\n\n/* this has 'package' visibility */\nvoid EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,\n                                void *(*dup_func) (void *),\n                                void (*free_func) (void *),\n                                void (*clear_free_func) (void *))\n{\n    EC_EXTRA_DATA **p;\n\n    if (ex_data == NULL)\n        return;\n\n    for (p = ex_data; *p != NULL; p = &((*p)->next)) {\n        if ((*p)->dup_func == dup_func && (*p)->free_func == free_func\n            && (*p)->clear_free_func == clear_free_func) {\n            EC_EXTRA_DATA *next = (*p)->next;\n\n            (*p)->clear_free_func((*p)->data);\n            OPENSSL_free(*p);\n\n            *p = next;\n            return;\n        }\n    }\n}\n\n/* this has 'package' visibility */\nvoid EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)\n{\n    EC_EXTRA_DATA *d;\n\n    if (ex_data == NULL)\n        return;\n\n    d = *ex_data;\n    while (d) {\n        EC_EXTRA_DATA *next = d->next;\n\n        d->free_func(d->data);\n        OPENSSL_free(d);\n\n        d = next;\n    }\n    *ex_data = NULL;\n}\n\n/* this has 'package' visibility */\nvoid EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)\n{\n    EC_EXTRA_DATA *d;\n\n    if (ex_data == NULL)\n        return;\n\n    d = *ex_data;\n    while (d) {\n        EC_EXTRA_DATA *next = d->next;\n\n        d->clear_free_func(d->data);\n        OPENSSL_free(d);\n\n        d = next;\n    }\n    *ex_data = NULL;\n}\n\n/* functions for EC_POINT objects */\n\nEC_POINT *EC_POINT_new(const EC_GROUP *group)\n{\n    EC_POINT *ret;\n\n    if (group == NULL) {\n        ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);\n        return NULL;\n    }\n    if (group->meth->point_init == 0) {\n        ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return NULL;\n    }\n\n\tret = clBnAlloc( \"EC_POINT_new\",sizeof *ret);\t/* pcg */\n    if (ret == NULL) {\n        ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);\n        return NULL;\n    }\n\tmemset( ret, 0, sizeof( EC_POINT ) );\t\t\t/* pcg */\n\n    ret->meth = group->meth;\n\n    if (!ret->meth->point_init(ret)) {\n        OPENSSL_free(ret);\n        return NULL;\n    }\n\n    return ret;\n}\n\nvoid EC_POINT_free(EC_POINT *point)\n{\n    if (!point)\n        return;\n\n    if (point->meth->point_finish != 0)\n        point->meth->point_finish(point);\n    OPENSSL_free(point);\n}\n\nvoid EC_POINT_clear_free(EC_POINT *point)\n{\n    if (!point)\n        return;\n\n    if (point->meth->point_clear_finish != 0)\n        point->meth->point_clear_finish(point);\n    else if (point->meth->point_finish != 0)\n        point->meth->point_finish(point);\n    OPENSSL_cleanse(point, sizeof *point);\n    OPENSSL_free(point);\n}\n\nint EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)\n{\n    if (dest->meth->point_copy == 0) {\n        ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (dest->meth != src->meth) {\n        ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    if (dest == src)\n        return 1;\n    return dest->meth->point_copy(dest, src);\n}\n\nEC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)\n{\n    EC_POINT *t;\n    int r;\n\n    if (a == NULL)\n        return NULL;\n\n    t = EC_POINT_new(group);\n    if (t == NULL)\n        return (NULL);\n    r = EC_POINT_copy(t, a);\n    if (!r) {\n        EC_POINT_free(t);\n        return NULL;\n    } else\n        return t;\n}\n\nconst EC_METHOD *EC_POINT_method_of(const EC_POINT *point)\n{\n    return point->meth;\n}\n\nint EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)\n{\n    if (group->meth->point_set_to_infinity == 0) {\n        ECerr(EC_F_EC_POINT_SET_TO_INFINITY,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_set_to_infinity(group, point);\n}\n\nint EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                             EC_POINT *point, const BIGNUM *x,\n                                             const BIGNUM *y, const BIGNUM *z,\n                                             BN_CTX *ctx)\n{\n    if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {\n        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,\n                                                              y, z, ctx);\n}\n\nint EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                             const EC_POINT *point, BIGNUM *x,\n                                             BIGNUM *y, BIGNUM *z,\n                                             BN_CTX *ctx)\n{\n    if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {\n        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,\n                                                              y, z, ctx);\n}\n\nint EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,\n                                        EC_POINT *point, const BIGNUM *x,\n                                        const BIGNUM *y, BN_CTX *ctx)\n{\n    if (group->meth->point_set_affine_coordinates == 0) {\n        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);\n}\n\n#ifndef OPENSSL_NO_EC2M\nint EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,\n                                         EC_POINT *point, const BIGNUM *x,\n                                         const BIGNUM *y, BN_CTX *ctx)\n{\n    if (group->meth->point_set_affine_coordinates == 0) {\n        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);\n}\n#endif\n\nint EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,\n                                        const EC_POINT *point, BIGNUM *x,\n                                        BIGNUM *y, BN_CTX *ctx)\n{\n    if (group->meth->point_get_affine_coordinates == 0) {\n        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);\n}\n\n#ifndef OPENSSL_NO_EC2M\nint EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,\n                                         const EC_POINT *point, BIGNUM *x,\n                                         BIGNUM *y, BN_CTX *ctx)\n{\n    if (group->meth->point_get_affine_coordinates == 0) {\n        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,\n              EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);\n}\n#endif\n\nint EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                 const EC_POINT *b, BN_CTX *ctx)\n{\n    if (group->meth->add == 0) {\n        ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if ((group->meth != r->meth) || (r->meth != a->meth)\n        || (a->meth != b->meth)) {\n        ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->add(group, r, a, b, ctx);\n}\n\nint EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                 BN_CTX *ctx)\n{\n    if (group->meth->dbl == 0) {\n        ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if ((group->meth != r->meth) || (r->meth != a->meth)) {\n        ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->dbl(group, r, a, ctx);\n}\n\nint EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)\n{\n    if (group->meth->invert == 0) {\n        ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != a->meth) {\n        ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->invert(group, a, ctx);\n}\n\nint EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)\n{\n    if (group->meth->is_at_infinity == 0) {\n        ECerr(EC_F_EC_POINT_IS_AT_INFINITY,\n              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->is_at_infinity(group, point);\n}\n\n/*\n * Check whether an EC_POINT is on the curve or not. Note that the return\n * value for this function should NOT be treated as a boolean. Return values:\n *  1: The point is on the curve\n *  0: The point is not on the curve\n * -1: An error occurred\n */\nint EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,\n                         BN_CTX *ctx)\n{\n    if (group->meth->is_on_curve == 0) {\n        ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->is_on_curve(group, point, ctx);\n}\n\nint EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,\n                 BN_CTX *ctx)\n{\n    if (group->meth->point_cmp == 0) {\n        ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return -1;\n    }\n    if ((group->meth != a->meth) || (a->meth != b->meth)) {\n        ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);\n        return -1;\n    }\n    return group->meth->point_cmp(group, a, b, ctx);\n}\n\nint EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)\n{\n    if (group->meth->make_affine == 0) {\n        ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    if (group->meth != point->meth) {\n        ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n    return group->meth->make_affine(group, point, ctx);\n}\n\nint EC_POINTs_make_affine(const EC_GROUP *group, size_t num,\n                          EC_POINT *points[], BN_CTX *ctx)\n{\n    size_t i;\n\n    if (group->meth->points_make_affine == 0) {\n        ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);\n        return 0;\n    }\n    for (i = 0; i < num; i++) {\n        if (group->meth != points[i]->meth) {\n            ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);\n            return 0;\n        }\n    }\n    return group->meth->points_make_affine(group, num, points, ctx);\n}\n\n/*\n * Functions for point multiplication. If group->meth->mul is 0, we use the\n * wNAF-based implementations in ec_mult.c; otherwise we dispatch through\n * methods.\n */\n\nint EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                  size_t num, const EC_POINT *points[],\n                  const BIGNUM *scalars[], BN_CTX *ctx)\n{\n    if (group->meth->mul == 0)\n        /* use default */\n        return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);\n\n    return group->meth->mul(group, r, scalar, num, points, scalars, ctx);\n}\n\nint EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,\n                 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)\n{\n    /* just a convenient interface to EC_POINTs_mul() */\n\n    const EC_POINT *points[1];\n    const BIGNUM *scalars[1];\n\n    points[0] = point;\n    scalars[0] = p_scalar;\n\n    return EC_POINTs_mul(group, r, g_scalar,\n                         (point != NULL\n                          && p_scalar != NULL), points, scalars, ctx);\n}\n\nint EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)\n{\n    if (group->meth->mul == 0)\n        /* use default */\n        return ec_wNAF_precompute_mult(group, ctx);\n\n    if (group->meth->precompute_mult != 0)\n        return group->meth->precompute_mult(group, ctx);\n    else\n        return 1;               /* nothing to do, so report success */\n}\n\nint EC_GROUP_have_precompute_mult(const EC_GROUP *group)\n{\n    if (group->meth->mul == 0)\n        /* use default */\n        return ec_wNAF_have_precompute_mult(group);\n\n    if (group->meth->have_precompute_mult != 0)\n        return group->meth->have_precompute_mult(group);\n    else\n        return 0;               /* cannot tell whether precomputation has\n                                 * been performed */\n}\n\n/*\n * ec_precompute_mont_data sets |group->mont_data| from |group->order| and\n * returns one on success. On error it returns zero.\n */\nint ec_precompute_mont_data(EC_GROUP *group)\n{\n    BN_CTX *ctx = BN_CTX_new();\n    int ret = 0;\n\n    if (!EC_GROUP_VERSION(group))\n        goto err;\n\n    if (group->mont_data) {\n        BN_MONT_CTX_free(group->mont_data);\n        group->mont_data = NULL;\n    }\n\n    if (ctx == NULL)\n        goto err;\n\n    group->mont_data = BN_MONT_CTX_new();\n    if (!group->mont_data)\n        goto err;\n\n    if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) {\n        BN_MONT_CTX_free(group->mont_data);\n        group->mont_data = NULL;\n        goto err;\n    }\n\n    ret = 1;\n\n err:\n\n    if (ctx)\n        BN_CTX_free(ctx);\n    return ret;\n}\n#endif /* USE_ECDH || USE_ECDSA */\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/bn/ec_mult.c",
    "content": "/* crypto/ec/ec_mult.c */\n/*\n * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.\n */\n/* ====================================================================\n * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n * Portions of this software developed by SUN MICROSYSTEMS, INC.,\n * and contributed to the OpenSSL project.\n */\n\n#include <string.h>\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"ec_lcl.h\"\n#else\n  #include \"bn/ec_lcl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef _MSC_VER\t\t/* For sizeof <-> int conversion */\n  #pragma warning( disable: 4267 )\n#endif /* _MSC_VER */\n\n/* End changes for cryptlib - pcg */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\t\t/* pcg */\n\n/*\n * This file implements the wNAF-based interleaving multi-exponentation method\n * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);\n * for multiplication with precomputation, we use wNAF splitting\n * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).\n */\n\n/* structure for precomputed multiples of the generator */\ntypedef struct ec_pre_comp_st {\n    const EC_GROUP *group;      /* parent EC_GROUP object */\n    size_t blocksize;           /* block size for wNAF splitting */\n    size_t numblocks;           /* max. number of blocks for which we have\n                                 * precomputation */\n    size_t w;                   /* window size */\n    EC_POINT **points;          /* array with pre-calculated multiples of\n                                 * generator: 'num' pointers to EC_POINT\n                                 * objects followed by a NULL */\n    size_t num;                 /* numblocks * 2^(w-1) */\n    int references;\n} EC_PRE_COMP;\n\n/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */\nstatic void *ec_pre_comp_dup(void *);\nstatic void ec_pre_comp_free(void *);\nstatic void ec_pre_comp_clear_free(void *);\n\nstatic EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)\n{\n    EC_PRE_COMP *ret = NULL;\n\n    if (!group)\n        return NULL;\n\n\tret = (EC_PRE_COMP *)clBnAlloc(\"ec_pre_comp_new\",sizeof(EC_PRE_COMP));\t\t/* pcg */\n    if (!ret) {\n        ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);\n        return ret;\n    }\n    ret->group = group;\n    ret->blocksize = 8;         /* default */\n    ret->numblocks = 0;\n    ret->w = 4;                 /* default */\n    ret->points = NULL;\n    ret->num = 0;\n    ret->references = 1;\n    return ret;\n}\n\nstatic void *ec_pre_comp_dup(void *src_)\n{\n#if 0\t/* pcg */\n\tEC_PRE_COMP *src = src_;\n#endif /* 0 */\n\n    /* no need to actually copy, these objects never change! */\n\n    CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);\n\n    return src_;\n}\n\nstatic void ec_pre_comp_free(void *pre_)\n{\n    int i;\n    EC_PRE_COMP *pre = pre_;\n\n    if (!pre)\n        return;\n\n    i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);\n    if (i > 0)\n        return;\n\n    if (pre->points) {\n        EC_POINT **p;\n\n        for (p = pre->points; *p != NULL; p++)\n            EC_POINT_free(*p);\n        OPENSSL_free(pre->points);\n    }\n    OPENSSL_free(pre);\n}\n\nstatic void ec_pre_comp_clear_free(void *pre_)\n{\n    int i;\n    EC_PRE_COMP *pre = pre_;\n\n    if (!pre)\n        return;\n\n    i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);\n    if (i > 0)\n        return;\n\n    if (pre->points) {\n        EC_POINT **p;\n\n        for (p = pre->points; *p != NULL; p++) {\n            EC_POINT_clear_free(*p);\n            OPENSSL_cleanse(p, sizeof *p);\n        }\n        OPENSSL_free(pre->points);\n    }\n    OPENSSL_cleanse(pre, sizeof *pre);\n    OPENSSL_free(pre);\n}\n\n/*-\n * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.\n * This is an array  r[]  of values that are either zero or odd with an\n * absolute value less than  2^w  satisfying\n *     scalar = \\sum_j r[j]*2^j\n * where at most one of any  w+1  consecutive digits is non-zero\n * with the exception that the most significant digit may be only\n * w-1 zeros away from that next non-zero digit.\n */\nstatic signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)\n{\n    int window_val;\n    int ok = 0;\n    signed char *r = NULL;\n    int sign = 1;\n    int bit, next_bit, mask;\n    size_t len = 0, j;\n\n    if (BN_is_zero(scalar)) {\n\t\tr = clBnAlloc(\"compute_wNAF\",1);\t/* pcg */\n        if (!r) {\n            ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n        r[0] = 0;\n        *ret_len = 1;\n        return r;\n    }\n\n    if (w <= 0 || w > 7) {      /* 'signed char' can represent integers with\n                                 * absolute values less than 2^7 */\n        ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n    bit = 1 << w;               /* at most 128 */\n    next_bit = bit << 1;        /* at most 256 */\n    mask = next_bit - 1;        /* at most 255 */\n\n    if (BN_is_negative(scalar)) {\n        sign = -1;\n    }\n\n    if (scalar->d == NULL || scalar->top == 0) {\n        ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n\n    len = BN_num_bits(scalar);\n\tr = clBnAlloc(\"compute_wNAF\",\t\t/* pcg */\n\t\t\t\t\t   len + 1); /* modified wNAF may be one digit longer\n                                  * than binary representation (*ret_len will\n                                  * be set to the actual length, i.e. at most\n                                  * BN_num_bits(scalar) + 1) */\n    if (r == NULL) {\n        ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    window_val = scalar->d[0] & mask;\n    j = 0;\n    while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len,\n                                                      * window_val will not\n                                                      * increase */\n        int digit = 0;\n\n        /* 0 <= window_val <= 2^(w+1) */\n\n        if (window_val & 1) {\n            /* 0 < window_val < 2^(w+1) */\n\n            if (window_val & bit) {\n                digit = window_val - next_bit; /* -2^w < digit < 0 */\n\n#if 1                           /* modified wNAF */\n                if (j + w + 1 >= len) {\n                    /*\n                     * special case for generating modified wNAFs: no new\n                     * bits will be added into window_val, so using a\n                     * positive digit here will decrease the total length of\n                     * the representation\n                     */\n\n                    digit = window_val & (mask >> 1); /* 0 < digit < 2^w */\n                }\n#endif\n            } else {\n                digit = window_val; /* 0 < digit < 2^w */\n            }\n\n            if (digit <= -bit || digit >= bit || !(digit & 1)) {\n                ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n\n            window_val -= digit;\n\n            /*\n             * now window_val is 0 or 2^(w+1) in standard wNAF generation;\n             * for modified window NAFs, it may also be 2^w\n             */\n            if (window_val != 0 && window_val != next_bit\n                && window_val != bit) {\n                ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n        }\n\n        r[j++] = ( char ) ( sign * digit );\n\n        window_val >>= 1;\n        window_val += bit * ( BN_is_bit_set(scalar, j + w) ? 1 : 0 );\t/* pcg */\n\n        if (window_val > next_bit) {\n            ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n            goto err;\n        }\n    }\n\n    if (j > len + 1) {\n        ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n    len = j;\n    ok = 1;\n\n err:\n    if (!ok) {\n\t\tif( r != NULL )\t\t/* pcg */\n\t\t\tOPENSSL_free(r);\n        r = NULL;\n    }\n    if (ok)\n        *ret_len = len;\n    return r;\n}\n\n/*\n * TODO: table should be optimised for the wNAF-based implementation,\n * sometimes smaller windows will give better performance (thus the\n * boundaries should be increased)\n */\n#define EC_window_bits_for_scalar_size(b) \\\n                ((size_t) \\\n                 ((b) >= 2000 ? 6 : \\\n                  (b) >=  800 ? 5 : \\\n                  (b) >=  300 ? 4 : \\\n                  (b) >=   70 ? 3 : \\\n                  (b) >=   20 ? 2 : \\\n                  1))\n\n/*-\n * Compute\n *      \\sum scalars[i]*points[i],\n * also including\n *      scalar*generator\n * in the addition if scalar != NULL\n */\nint ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,\n                size_t num, const EC_POINT *points[], const BIGNUM *scalars[],\n                BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    const EC_POINT *generator = NULL;\n    EC_POINT *tmp = NULL;\n    size_t totalnum;\n    size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */\n    size_t pre_points_per_block = 0;\n    size_t i, j;\n    int k;\n    int r_is_inverted = 0;\n    int r_is_at_infinity = 1;\n    size_t *wsize = NULL;       /* individual window sizes */\n    signed char **wNAF = NULL;  /* individual wNAFs */\n    size_t *wNAF_len = NULL;\n    size_t max_len = 0;\n    size_t num_val;\n    EC_POINT **val = NULL;      /* precomputation */\n    EC_POINT **v;\n    EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or\n                                 * 'pre_comp->points' */\n    const EC_PRE_COMP *pre_comp = NULL;\n    int num_scalar = 0;         /* flag: will be set to 1 if 'scalar' must be\n                                 * treated like other scalars, i.e.\n                                 * precomputation is not available */\n    int ret = 0;\n\n    if (group->meth != r->meth) {\n        ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n        return 0;\n    }\n\n    if ((scalar == NULL) && (num == 0)) {\n        return EC_POINT_set_to_infinity(group, r);\n    }\n\n    for (i = 0; i < num; i++) {\n        if (group->meth != points[i]->meth) {\n            ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);\n            return 0;\n        }\n    }\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            goto err;\n    }\n\n    if (scalar != NULL) {\n        generator = EC_GROUP_get0_generator(group);\n        if (generator == NULL) {\n            ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);\n            goto err;\n        }\n\n        /* look if we can use precomputed multiples of generator */\n\n        pre_comp =\n            EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup,\n                                ec_pre_comp_free, ec_pre_comp_clear_free);\n\n        if (pre_comp && pre_comp->numblocks\n            && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==\n                0)) {\n            blocksize = pre_comp->blocksize;\n\n            /*\n             * determine maximum number of blocks that wNAF splitting may\n             * yield (NB: maximum wNAF length is bit length plus one)\n             */\n            numblocks = (BN_num_bits(scalar) / blocksize) + 1;\n\n            /*\n             * we cannot use more blocks than we have precomputation for\n             */\n            if (numblocks > pre_comp->numblocks)\n                numblocks = pre_comp->numblocks;\n\n            pre_points_per_block = (size_t)1 << (pre_comp->w - 1);\n\n            /* check that pre_comp looks sane */\n            if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n        } else {\n            /* can't use precomputation */\n            pre_comp = NULL;\n            numblocks = 1;\n            num_scalar = 1;     /* treat 'scalar' like 'num'-th element of\n                                 * 'scalars' */\n        }\n    }\n\n    totalnum = num + numblocks;\n\n\twsize    = clBnAlloc(\"ec_wNAF_mul\",totalnum * sizeof wsize[0]);\t\t/* pcg */\n\twNAF_len = clBnAlloc(\"ec_wNAF_mul\",totalnum * sizeof wNAF_len[0]);\t/* pcg */\n\twNAF     = clBnAlloc(\"ec_wNAF_mul\",(totalnum + 1) * sizeof wNAF[0]); /* includes space for pivot */\n\tval_sub  = clBnAlloc(\"ec_wNAF_mul\",totalnum * sizeof val_sub[0]);\t/* pcg */\n\n    /* Ensure wNAF is initialised in case we end up going to err */\n    if (wNAF)\n        wNAF[0] = NULL;         /* preliminary pivot */\n\n    if (!wsize || !wNAF_len || !wNAF || !val_sub) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n\n    /*\n     * num_val will be the total number of temporarily precomputed points\n     */\n    num_val = 0;\n\n    for (i = 0; i < num + num_scalar; i++) {\n        size_t bits;\n\n        bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);\n        wsize[i] = EC_window_bits_for_scalar_size(bits);\n        num_val += (size_t)1 << (wsize[i] - 1);\n        wNAF[i + 1] = NULL;     /* make sure we always have a pivot */\n        wNAF[i] =\n            compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],\n                         &wNAF_len[i]);\n        if (wNAF[i] == NULL)\n            goto err;\n        if (wNAF_len[i] > max_len)\n            max_len = wNAF_len[i];\n    }\n\n    if (numblocks) {\n        /* we go here iff scalar != NULL */\n\n        if (pre_comp == NULL) {\n            if (num_scalar != 1) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n            /* we have already generated a wNAF for 'scalar' */\n        } else {\n            signed char *tmp_wNAF = NULL;\n            size_t tmp_len = 0;\n\n            if (num_scalar != 0) {\n                ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n\n            /*\n             * use the window size for which we have precomputation\n             */\n            wsize[num] = pre_comp->w;\n            tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);\n            if (!tmp_wNAF)\n                goto err;\n\n            if (tmp_len <= max_len) {\n                /*\n                 * One of the other wNAFs is at least as long as the wNAF\n                 * belonging to the generator, so wNAF splitting will not buy\n                 * us anything.\n                 */\n\n                numblocks = 1;\n                totalnum = num + 1; /* don't use wNAF splitting */\n                wNAF[num] = tmp_wNAF;\n                wNAF[num + 1] = NULL;\n                wNAF_len[num] = tmp_len;\n                if (tmp_len > max_len)\t/* pcg - Can never happen given the earlier check */\n                    max_len = tmp_len;\n                /*\n                 * pre_comp->points starts with the points that we need here:\n                 */\n                val_sub[num] = pre_comp->points;\n            } else {\n                /*\n                 * don't include tmp_wNAF directly into wNAF array - use wNAF\n                 * splitting and include the blocks\n                 */\n\n                signed char *pp;\n                EC_POINT **tmp_points;\n\n                if (tmp_len < numblocks * blocksize) {\n                    /*\n                     * possibly we can do with fewer blocks than estimated\n                     */\n                    numblocks = (tmp_len + blocksize - 1) / blocksize;\n                    if (numblocks > pre_comp->numblocks) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                        goto err;\n                    }\n                    totalnum = num + numblocks;\n                }\n\n                /* split wNAF in 'numblocks' parts */\n                pp = tmp_wNAF;\n                tmp_points = pre_comp->points;\n\n                for (i = num; i < totalnum; i++) {\n                    if (i < totalnum - 1) {\n                        wNAF_len[i] = blocksize;\n                        if (tmp_len < blocksize) {\n                            ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                            goto err;\n                        }\n                        tmp_len -= blocksize;\n                    } else\n                        /*\n                         * last block gets whatever is left (this could be\n                         * more or less than 'blocksize'!)\n                         */\n                        wNAF_len[i] = tmp_len;\n\n                    wNAF[i + 1] = NULL;\n\t\t\t\t\twNAF[i] = clBnAlloc(\"ec_wNAF_mul\",wNAF_len[i]);\t\t/* pcg */\n                    if (wNAF[i] == NULL) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n                        OPENSSL_free(tmp_wNAF);\n                        goto err;\n                    }\n                    memcpy(wNAF[i], pp, wNAF_len[i]);\n                    if (wNAF_len[i] > max_len)\n                        max_len = wNAF_len[i];\n\n                    if (*tmp_points == NULL) {\n                        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n                        OPENSSL_free(tmp_wNAF);\n                        goto err;\n                    }\n                    val_sub[i] = tmp_points;\n                    tmp_points += pre_points_per_block;\n                    pp += blocksize;\n                }\n                OPENSSL_free(tmp_wNAF);\n            }\n        }\n    }\n\n    /*\n     * All points we precompute now go into a single array 'val'.\n     * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a\n     * subarray of 'pre_comp->points' if we already have precomputation.\n     */\n\tval = clBnAlloc(\"ec_wNAF_mul\",(num_val + 1) * sizeof val[0]);\t/* pcg */\n    if (val == NULL) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n    val[num_val] = NULL;        /* pivot element */\n\n    /* allocate points for precomputation */\n    v = val;\n    for (i = 0; i < num + num_scalar; i++) {\n        val_sub[i] = v;\n        for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {\n            *v = EC_POINT_new(group);\n            if (*v == NULL)\n                goto err;\n            v++;\n        }\n    }\n    if (!(v == val + num_val)) {\n        ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n\n\tif ((tmp = EC_POINT_new(group)) == 0 )\t\t/* pcg */\n        goto err;\n\n    /*-\n     * prepare precomputed values:\n     *    val_sub[i][0] :=     points[i]\n     *    val_sub[i][1] := 3 * points[i]\n     *    val_sub[i][2] := 5 * points[i]\n     *    ...\n     */\n    for (i = 0; i < num + num_scalar; i++) {\n        if (i < num) {\n            if (!EC_POINT_copy(val_sub[i][0], points[i]))\n                goto err;\n        } else {\n            if (!EC_POINT_copy(val_sub[i][0], generator))\n                goto err;\n        }\n\n        if (wsize[i] > 1) {\n            if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))\n                goto err;\n            for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {\n                if (!EC_POINT_add\n                    (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))\n                    goto err;\n            }\n        }\n    }\n\n#if 1                           /* optional; EC_window_bits_for_scalar_size\n                                 * assumes we do this step */\n    if (!EC_POINTs_make_affine(group, num_val, val, ctx))\n        goto err;\n#endif\n\n    r_is_at_infinity = 1;\n\n    for (k = max_len - 1; k >= 0; k--) {\n        if (!r_is_at_infinity) {\n            if (!EC_POINT_dbl(group, r, r, ctx))\n                goto err;\n        }\n\n        for (i = 0; i < totalnum; i++) {\n            if (wNAF_len[i] > (size_t)k) {\n                int digit = wNAF[i][k];\n                int is_neg;\n\n                if (digit) {\n                    is_neg = digit < 0;\n\n                    if (is_neg)\n                        digit = -digit;\n\n                    if (is_neg != r_is_inverted) {\n                        if (!r_is_at_infinity) {\n                            if (!EC_POINT_invert(group, r, ctx))\n                                goto err;\n                        }\n                        r_is_inverted = !r_is_inverted;\n                    }\n\n                    /* digit > 0 */\n\n                    if (r_is_at_infinity) {\n                        if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))\n                            goto err;\n                        r_is_at_infinity = 0;\n                    } else {\n                        if (!EC_POINT_add\n                            (group, r, r, val_sub[i][digit >> 1], ctx))\n                            goto err;\n                    }\n                }\n            }\n        }\n    }\n\n    if (r_is_at_infinity) {\n        if (!EC_POINT_set_to_infinity(group, r))\n            goto err;\n    } else {\n        if (r_is_inverted)\n            if (!EC_POINT_invert(group, r, ctx))\n                goto err;\n    }\n\n    ret = 1;\n\n err:\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    if (tmp != NULL)\n        EC_POINT_free(tmp);\n    if (wsize != NULL)\n        OPENSSL_free(wsize);\n    if (wNAF_len != NULL)\n        OPENSSL_free(wNAF_len);\n    if (wNAF != NULL) {\n        signed char **w;\n\n        for (w = wNAF; *w != NULL; w++)\n            OPENSSL_free(*w);\n\n        OPENSSL_free(wNAF);\n    }\n    if (val != NULL) {\n        for (v = val; *v != NULL; v++)\n            EC_POINT_clear_free(*v);\n\n        OPENSSL_free(val);\n    }\n    if (val_sub != NULL) {\n        OPENSSL_free(val_sub);\n    }\n    return ret;\n}\n\n/*-\n * ec_wNAF_precompute_mult()\n * creates an EC_PRE_COMP object with preprecomputed multiples of the generator\n * for use with wNAF splitting as implemented in ec_wNAF_mul().\n *\n * 'pre_comp->points' is an array of multiples of the generator\n * of the following form:\n * points[0] =     generator;\n * points[1] = 3 * generator;\n * ...\n * points[2^(w-1)-1] =     (2^(w-1)-1) * generator;\n * points[2^(w-1)]   =     2^blocksize * generator;\n * points[2^(w-1)+1] = 3 * 2^blocksize * generator;\n * ...\n * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) *  2^(blocksize*(numblocks-2)) * generator\n * points[2^(w-1)*(numblocks-1)]   =              2^(blocksize*(numblocks-1)) * generator\n * ...\n * points[2^(w-1)*numblocks-1]     = (2^(w-1)) *  2^(blocksize*(numblocks-1)) * generator\n * points[2^(w-1)*numblocks]       = NULL\n */\nint ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)\n{\n    const EC_POINT *generator;\n    EC_POINT *tmp_point = NULL, *base = NULL, **var;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *order;\n    size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;\n    EC_POINT **points = NULL;\n    EC_PRE_COMP *pre_comp;\n    int ret = 0;\n\n    /* if there is an old EC_PRE_COMP object, throw it away */\n    EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup,\n                         ec_pre_comp_free, ec_pre_comp_clear_free);\n\n    if ((pre_comp = ec_pre_comp_new(group)) == NULL)\n        return 0;\n\n    generator = EC_GROUP_get0_generator(group);\n    if (generator == NULL) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);\n        goto err;\n    }\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            goto err;\n    }\n\n    BN_CTX_start(ctx);\n    order = BN_CTX_get(ctx);\n    if (order == NULL)\n        goto err;\n\n    if (!EC_GROUP_get_order(group, order, ctx))\n        goto err;\n    if (BN_is_zero(order)) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);\n        goto err;\n    }\n\n    bits = BN_num_bits(order);\n    /*\n     * The following parameters mean we precompute (approximately) one point\n     * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other\n     * bit lengths, other parameter combinations might provide better\n     * efficiency.\n     */\n    blocksize = 8;\n    w = 4;\n    if (EC_window_bits_for_scalar_size(bits) > w) {\n        /* let's not make the window too small ... */\n        w = EC_window_bits_for_scalar_size(bits);\n    }\n\n    numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks\n                                                     * to use for wNAF\n                                                     * splitting */\n\n    pre_points_per_block = (size_t)1 << (w - 1);\n    num = pre_points_per_block * numblocks; /* number of points to compute\n                                             * and store */\n\n\tpoints = clBnAlloc(\"ec_wNAF_precompute_mult\",sizeof (EC_POINT*)*(num + 1));\t\t/* pcg */\n    if (!points) {\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n\n    var = points;\n    var[num] = NULL;            /* pivot */\n    for (i = 0; i < num; i++) {\n        if ((var[i] = EC_POINT_new(group)) == NULL) {\n            ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n    }\n\n\tif ( (tmp_point = EC_POINT_new(group)) == 0 || (base = EC_POINT_new(group)) == 0 ) {\t/* pcg */\n        ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);\n        goto err;\n    }\n\n    if (!EC_POINT_copy(base, generator))\n        goto err;\n\n    /* do the precomputation */\n    for (i = 0; i < numblocks; i++) {\n        size_t j;\n\n        if (!EC_POINT_dbl(group, tmp_point, base, ctx))\n            goto err;\n\n        if (!EC_POINT_copy(*var++, base))\n            goto err;\n\n        for (j = 1; j < pre_points_per_block; j++, var++) {\n            /*\n             * calculate odd multiples of the current base point\n             */\n            if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))\n                goto err;\n        }\n\n        if (i < numblocks - 1) {\n            /*\n             * get the next base (multiply current one by 2^blocksize)\n             */\n            size_t k;\n\n            if (blocksize <= 2) {\n                ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);\n                goto err;\n            }\n\n            if (!EC_POINT_dbl(group, base, tmp_point, ctx))\n                goto err;\n            for (k = 2; k < blocksize; k++) {\n                if (!EC_POINT_dbl(group, base, base, ctx))\n                    goto err;\n            }\n        }\n    }\n\n    if (!EC_POINTs_make_affine(group, num, points, ctx))\n        goto err;\n\n    pre_comp->group = group;\n    pre_comp->blocksize = blocksize;\n    pre_comp->numblocks = numblocks;\n    pre_comp->w = w;\n    pre_comp->points = points;\n    points = NULL;\n    pre_comp->num = num;\n\n    if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,\n                             ec_pre_comp_dup, ec_pre_comp_free,\n                             ec_pre_comp_clear_free))\n        goto err;\n    pre_comp = NULL;\n\n    ret = 1;\n err:\n    if (ctx != NULL)\n        BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    if (pre_comp)\n        ec_pre_comp_free(pre_comp);\n    if (points) {\n        EC_POINT **p;\n\n        for (p = points; *p != NULL; p++)\n            EC_POINT_free(*p);\n        OPENSSL_free(points);\n    }\n    if (tmp_point)\n        EC_POINT_free(tmp_point);\n    if (base)\n        EC_POINT_free(base);\n    return ret;\n}\n\nint ec_wNAF_have_precompute_mult(const EC_GROUP *group)\n{\n    if (EC_EX_DATA_get_data\n        (group->extra_data, ec_pre_comp_dup, ec_pre_comp_free,\n         ec_pre_comp_clear_free) != NULL)\n        return 1;\n    else\n        return 0;\n}\n#endif /* USE_ECDH || USE_ECDSA */\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/bn/ecp_mont.c",
    "content": "/* crypto/ec/ecp_mont.c */\n/*\n * Originally written by Bodo Moeller for the OpenSSL project.\n */\n/* ====================================================================\n * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n * Portions of this software developed by SUN MICROSYSTEMS, INC.,\n * and contributed to the OpenSSL project.\n */\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"ec_lcl.h\"\n#else\n  #include \"bn/ec_lcl.h\"\n#endif /* Compiler-specific includes */\n\n/* End changes for cryptlib - pcg */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\t/* pcg */\n\n#if 0\t/* pcg */\n\nconst EC_METHOD *EC_GFp_mont_method(void)\n{\n    static const EC_METHOD ret = {\n        EC_FLAGS_DEFAULT_OCT,\n        NID_X9_62_prime_field,\n        ec_GFp_mont_group_init,\n        ec_GFp_mont_group_finish,\n        ec_GFp_mont_group_clear_finish,\n        ec_GFp_mont_group_copy,\n        ec_GFp_mont_group_set_curve,\n        ec_GFp_simple_group_get_curve,\n        ec_GFp_simple_group_get_degree,\n        ec_GFp_simple_group_check_discriminant,\n        ec_GFp_simple_point_init,\n        ec_GFp_simple_point_finish,\n        ec_GFp_simple_point_clear_finish,\n        ec_GFp_simple_point_copy,\n        ec_GFp_simple_point_set_to_infinity,\n        ec_GFp_simple_set_Jprojective_coordinates_GFp,\n        ec_GFp_simple_get_Jprojective_coordinates_GFp,\n        ec_GFp_simple_point_set_affine_coordinates,\n        ec_GFp_simple_point_get_affine_coordinates,\n        0, 0, 0,\n        ec_GFp_simple_add,\n        ec_GFp_simple_dbl,\n        ec_GFp_simple_invert,\n        ec_GFp_simple_is_at_infinity,\n        ec_GFp_simple_is_on_curve,\n        ec_GFp_simple_cmp,\n        ec_GFp_simple_make_affine,\n        ec_GFp_simple_points_make_affine,\n        0 /* mul */ ,\n        0 /* precompute_mult */ ,\n        0 /* have_precompute_mult */ ,\n        ec_GFp_mont_field_mul,\n        ec_GFp_mont_field_sqr,\n        0 /* field_div */ ,\n        ec_GFp_mont_field_encode,\n        ec_GFp_mont_field_decode,\n        ec_GFp_mont_field_set_to_one\n    };\n\n#ifdef OPENSSL_FIPS\n    if (FIPS_mode())\n        return fips_ec_gfp_mont_method();\n#endif\n\n    return &ret;\n}\n\n#endif /* 0 - pcg */\n\nint ec_GFp_mont_group_init(EC_GROUP *group)\n{\n    int ok;\n\n    ok = ec_GFp_simple_group_init(group);\n    group->field_data1 = NULL;\n    group->field_data2 = NULL;\n    return ok;\n}\n\nvoid ec_GFp_mont_group_finish(EC_GROUP *group)\n{\n    if (group->field_data1 != NULL) {\n        BN_MONT_CTX_free(group->field_data1);\n        group->field_data1 = NULL;\n    }\n    if (group->field_data2 != NULL) {\n        BN_free(group->field_data2);\n        group->field_data2 = NULL;\n    }\n    ec_GFp_simple_group_finish(group);\n}\n\nvoid ec_GFp_mont_group_clear_finish(EC_GROUP *group)\n{\n    if (group->field_data1 != NULL) {\n        BN_MONT_CTX_free(group->field_data1);\n        group->field_data1 = NULL;\n    }\n    if (group->field_data2 != NULL) {\n        BN_clear_free(group->field_data2);\n        group->field_data2 = NULL;\n    }\n    ec_GFp_simple_group_clear_finish(group);\n}\n\nint ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)\n{\n    if (dest->field_data1 != NULL) {\n        BN_MONT_CTX_free(dest->field_data1);\n        dest->field_data1 = NULL;\n    }\n    if (dest->field_data2 != NULL) {\n        BN_clear_free(dest->field_data2);\n        dest->field_data2 = NULL;\n    }\n\n    if (!ec_GFp_simple_group_copy(dest, src))\n        return 0;\n\n    if (src->field_data1 != NULL) {\n        dest->field_data1 = BN_MONT_CTX_new();\n        if (dest->field_data1 == NULL)\n            return 0;\n        if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1))\n            goto err;\n    }\n    if (src->field_data2 != NULL) {\n        dest->field_data2 = BN_dup(src->field_data2);\n        if (dest->field_data2 == NULL)\n            goto err;\n    }\n\n    return 1;\n\n err:\n    if (dest->field_data1 != NULL) {\n        BN_MONT_CTX_free(dest->field_data1);\n        dest->field_data1 = NULL;\n    }\n    return 0;\n}\n\nint ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,\n                                const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    BN_MONT_CTX *mont = NULL;\n    BIGNUM *one = NULL;\n    int ret = 0;\n\n    if (group->field_data1 != NULL) {\n        BN_MONT_CTX_free(group->field_data1);\n        group->field_data1 = NULL;\n    }\n    if (group->field_data2 != NULL) {\n        BN_free(group->field_data2);\n        group->field_data2 = NULL;\n    }\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    mont = BN_MONT_CTX_new();\n    if (mont == NULL)\n        goto err;\n    if (!BN_MONT_CTX_set(mont, p, ctx)) {\n        ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB);\n        goto err;\n    }\n    one = BN_new();\n    if (one == NULL)\n        goto err;\n    if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))\n        goto err;\n\n    group->field_data1 = mont;\n    mont = NULL;\n    group->field_data2 = one;\n    one = NULL;\n\n    ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);\n\n    if (!ret) {\n        BN_MONT_CTX_free(group->field_data1);\n        group->field_data1 = NULL;\n        BN_free(group->field_data2);\n        group->field_data2 = NULL;\n    }\n\n err:\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    if (mont != NULL)\n        BN_MONT_CTX_free(mont);\n    return ret;\n}\n\nint ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,\n                          const BIGNUM *b, BN_CTX *ctx)\n{\n    if (group->field_data1 == NULL) {\n        ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);\n        return 0;\n    }\n\n    return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);\n}\n\nint ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,\n                          BN_CTX *ctx)\n{\n    if (group->field_data1 == NULL) {\n        ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);\n        return 0;\n    }\n\n    return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);\n}\n\nint ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,\n                             const BIGNUM *a, BN_CTX *ctx)\n{\n    if (group->field_data1 == NULL) {\n        ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);\n        return 0;\n    }\n\n    return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);\n}\n\n#if 0\t/* pcg */\nint ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r,\n                             const BIGNUM *a, BN_CTX *ctx)\n{\n    if (group->field_data1 == NULL) {\n        ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);\n        return 0;\n    }\n\n    return BN_from_montgomery(r, a, group->field_data1, ctx);\n}\n#endif /* 0 */\n\nint ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,\n                                 BN_CTX *ctx)\n{\n    if (group->field_data2 == NULL) {\n        ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);\n        return 0;\n    }\n\n    if (!BN_copy(r, group->field_data2))\n        return 0;\n    return 1;\n}\n#endif /* USE_ECDH || USE_ECDSA */\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/bn/ecp_smpl.c",
    "content": "/* crypto/ec/ecp_smpl.c */\n/*\n * Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>\n * for the OpenSSL project. Includes code written by Bodo Moeller for the\n * OpenSSL project.\n */\n/* ====================================================================\n * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    openssl-core@openssl.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.openssl.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n/* ====================================================================\n * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.\n * Portions of this software developed by SUN MICROSYSTEMS, INC.,\n * and contributed to the OpenSSL project.\n */\n\n/* Changes for cryptlib - pcg */\n\n#if defined( INC_ALL )\n  #include \"ec_lcl.h\"\n#else\n  #include \"bn/ec_lcl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef _MSC_VER\t\t/* For sizeof <-> int conversion */\n  #pragma warning( disable: 4267 )\n#endif /* _MSC_VER */\n\n/* Normally defined in /crypto/objects/obj_mac.h */\n\n#define NID_X9_62_prime_field\t\t406\n#define NID_X9_62_characteristic_two_field\t\t407\n\n/* End changes for cryptlib - pcg */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nconst EC_METHOD *EC_GFp_simple_method(void)\n{\n    static const EC_METHOD ret = {\n        EC_FLAGS_DEFAULT_OCT,\n        NID_X9_62_prime_field,\n        ec_GFp_simple_group_init,\n        ec_GFp_simple_group_finish,\n        ec_GFp_simple_group_clear_finish,\n        ec_GFp_simple_group_copy,\n        ec_GFp_simple_group_set_curve,\n        ec_GFp_simple_group_get_curve,\n        ec_GFp_simple_group_get_degree,\n        ec_GFp_simple_group_check_discriminant,\n        ec_GFp_simple_point_init,\n        ec_GFp_simple_point_finish,\n        ec_GFp_simple_point_clear_finish,\n        ec_GFp_simple_point_copy,\n        ec_GFp_simple_point_set_to_infinity,\n        ec_GFp_simple_set_Jprojective_coordinates_GFp,\n        ec_GFp_simple_get_Jprojective_coordinates_GFp,\n        ec_GFp_simple_point_set_affine_coordinates,\n        ec_GFp_simple_point_get_affine_coordinates,\n        0, 0, 0,\n        ec_GFp_simple_add,\n        ec_GFp_simple_dbl,\n        ec_GFp_simple_invert,\n        ec_GFp_simple_is_at_infinity,\n        ec_GFp_simple_is_on_curve,\n        ec_GFp_simple_cmp,\n        ec_GFp_simple_make_affine,\n        ec_GFp_simple_points_make_affine,\n        0 /* mul */ ,\n        0 /* precompute_mult */ ,\n        0 /* have_precompute_mult */ ,\n        ec_GFp_simple_field_mul,\n        ec_GFp_simple_field_sqr,\n        0 /* field_div */ ,\n        0 /* field_encode */ ,\n        0 /* field_decode */ ,\n        0                       /* field_set_to_one */\n    };\n\n#ifdef OPENSSL_FIPS\n    if (FIPS_mode())\n        return fips_ec_gfp_simple_method();\n#endif\n\n    return &ret;\n}\n\n/*\n * Most method functions in this file are designed to work with\n * non-trivial representations of field elements if necessary\n * (see ecp_mont.c): while standard modular addition and subtraction\n * are used, the field_mul and field_sqr methods will be used for\n * multiplication, and field_encode and field_decode (if defined)\n * will be used for converting between representations.\n *\n * Functions ec_GFp_simple_points_make_affine() and\n * ec_GFp_simple_point_get_affine_coordinates() specifically assume\n * that if a non-trivial representation is used, it is a Montgomery\n * representation (i.e. 'encoding' means multiplying by some factor R).\n */\n\nint ec_GFp_simple_group_init(EC_GROUP *group)\n{\n    BN_init(&group->field);\n    BN_init(&group->a);\n    BN_init(&group->b);\n    group->a_is_minus3 = 0;\n    return 1;\n}\n\nvoid ec_GFp_simple_group_finish(EC_GROUP *group)\n{\n    BN_free(&group->field);\n    BN_free(&group->a);\n    BN_free(&group->b);\n}\n\nvoid ec_GFp_simple_group_clear_finish(EC_GROUP *group)\n{\n    BN_clear_free(&group->field);\n    BN_clear_free(&group->a);\n    BN_clear_free(&group->b);\n}\n\nint ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)\n{\n    if (!BN_copy(&dest->field, &src->field))\n        return 0;\n    if (!BN_copy(&dest->a, &src->a))\n        return 0;\n    if (!BN_copy(&dest->b, &src->b))\n        return 0;\n\n    dest->a_is_minus3 = src->a_is_minus3;\n\n    return 1;\n}\n\nint ec_GFp_simple_group_set_curve(EC_GROUP *group,\n                                  const BIGNUM *p, const BIGNUM *a,\n                                  const BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = 0;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *tmp_a;\n\n    /* p must be a prime > 3 */\n    if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {\n        ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);\n        return 0;\n    }\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    tmp_a = BN_CTX_get(ctx);\n    if (tmp_a == NULL)\n        goto err;\n\n    /* group->field */\n    if (!BN_copy(&group->field, p))\n        goto err;\n    BN_set_negative(&group->field, 0);\n\n    /* group->a */\n    if (!BN_nnmod(tmp_a, a, p, ctx))\n        goto err;\n    if (group->meth->field_encode) {\n        if (!group->meth->field_encode(group, &group->a, tmp_a, ctx))\n            goto err;\n    } else if (!BN_copy(&group->a, tmp_a))\n        goto err;\n\n    /* group->b */\n    if (!BN_nnmod(&group->b, b, p, ctx))\n        goto err;\n    if (group->meth->field_encode)\n        if (!group->meth->field_encode(group, &group->b, &group->b, ctx))\n            goto err;\n\n    /* group->a_is_minus3 */\n    if (!BN_add_word(tmp_a, 3))\n        goto err;\n    group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));\n\n    ret = 1;\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,\n                                  BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = 0;\n    BN_CTX *new_ctx = NULL;\n\n    if (p != NULL) {\n        if (!BN_copy(p, &group->field))\n            return 0;\n    }\n\n    if (a != NULL || b != NULL) {\n        if (group->meth->field_decode) {\n            if (ctx == NULL) {\n                ctx = new_ctx = BN_CTX_new();\n                if (ctx == NULL)\n                    return 0;\n            }\n            if (a != NULL) {\n                if (!group->meth->field_decode(group, a, &group->a, ctx))\n                    goto err;\n            }\n            if (b != NULL) {\n                if (!group->meth->field_decode(group, b, &group->b, ctx))\n                    goto err;\n            }\n        } else {\n            if (a != NULL) {\n                if (!BN_copy(a, &group->a))\n                    goto err;\n            }\n            if (b != NULL) {\n                if (!BN_copy(b, &group->b))\n                    goto err;\n            }\n        }\n    }\n\n    ret = 1;\n\n err:\n    if (new_ctx)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_group_get_degree(const EC_GROUP *group)\n{\n    return BN_num_bits(&group->field);\n}\n\nint ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)\n{\n    int ret = 0;\n    BIGNUM *a, *b, *order, *tmp_1, *tmp_2;\n    const BIGNUM *p = &group->field;\n    BN_CTX *new_ctx = NULL;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL) {\n            ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,\n                  ERR_R_MALLOC_FAILURE);\n            goto err;\n        }\n    }\n    BN_CTX_start(ctx);\n    a = BN_CTX_get(ctx);\n    b = BN_CTX_get(ctx);\n    tmp_1 = BN_CTX_get(ctx);\n    tmp_2 = BN_CTX_get(ctx);\n    order = BN_CTX_get(ctx);\n    if ( a == NULL || b == NULL || tmp_1 == NULL || tmp_2 == NULL || \\\n\t\t order == NULL)\t/* pcg */\n        goto err;\n\n    if (group->meth->field_decode) {\n        if (!group->meth->field_decode(group, a, &group->a, ctx))\n            goto err;\n        if (!group->meth->field_decode(group, b, &group->b, ctx))\n            goto err;\n    } else {\n        if (!BN_copy(a, &group->a))\n            goto err;\n        if (!BN_copy(b, &group->b))\n            goto err;\n    }\n\n    /*-\n     * check the discriminant:\n     * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)\n     * 0 =< a, b < p\n     */\n    if (BN_is_zero(a)) {\n        if (BN_is_zero(b))\n            goto err;\n    } else if (!BN_is_zero(b)) {\n        if (!BN_mod_sqr(tmp_1, a, p, ctx))\n            goto err;\n        if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))\n            goto err;\n        if (!BN_lshift(tmp_1, tmp_2, 2))\n            goto err;\n        /* tmp_1 = 4*a^3 */\n\n        if (!BN_mod_sqr(tmp_2, b, p, ctx))\n            goto err;\n        if (!BN_mul_word(tmp_2, 27))\n            goto err;\n        /* tmp_2 = 27*b^2 */\n\n        if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))\n            goto err;\n        if (BN_is_zero(a))\n            goto err;\n    }\n    ret = 1;\n\n err:\n    if (ctx != NULL)\n        BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_point_init(EC_POINT *point)\n{\n    BN_init(&point->X);\n    BN_init(&point->Y);\n    BN_init(&point->Z);\n    point->Z_is_one = 0;\n\n    return 1;\n}\n\nvoid ec_GFp_simple_point_finish(EC_POINT *point)\n{\n    BN_free(&point->X);\n    BN_free(&point->Y);\n    BN_free(&point->Z);\n}\n\nvoid ec_GFp_simple_point_clear_finish(EC_POINT *point)\n{\n    BN_clear_free(&point->X);\n    BN_clear_free(&point->Y);\n    BN_clear_free(&point->Z);\n    point->Z_is_one = 0;\n}\n\nint ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)\n{\n    if (!BN_copy(&dest->X, &src->X))\n        return 0;\n    if (!BN_copy(&dest->Y, &src->Y))\n        return 0;\n    if (!BN_copy(&dest->Z, &src->Z))\n        return 0;\n    dest->Z_is_one = src->Z_is_one;\n\n    return 1;\n}\n\nint ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,\n                                        EC_POINT *point)\n{\n    point->Z_is_one = 0;\n    BN_zero(&point->Z);\n    return 1;\n}\n\nint ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                                  EC_POINT *point,\n                                                  const BIGNUM *x,\n                                                  const BIGNUM *y,\n                                                  const BIGNUM *z,\n                                                  BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    int ret = 0;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    if (x != NULL) {\n        if (!BN_nnmod(&point->X, x, &group->field, ctx))\n            goto err;\n        if (group->meth->field_encode) {\n            if (!group->meth->field_encode(group, &point->X, &point->X, ctx))\n                goto err;\n        }\n    }\n\n    if (y != NULL) {\n        if (!BN_nnmod(&point->Y, y, &group->field, ctx))\n            goto err;\n        if (group->meth->field_encode) {\n            if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx))\n                goto err;\n        }\n    }\n\n    if (z != NULL) {\n        int Z_is_one;\n\n        if (!BN_nnmod(&point->Z, z, &group->field, ctx))\n            goto err;\n        Z_is_one = BN_is_one(&point->Z);\n        if (group->meth->field_encode) {\n            if (Z_is_one && (group->meth->field_set_to_one != 0)) {\n                if (!group->meth->field_set_to_one(group, &point->Z, ctx))\n                    goto err;\n            } else {\n                if (!group->\n                    meth->field_encode(group, &point->Z, &point->Z, ctx))\n                    goto err;\n            }\n        }\n        point->Z_is_one = Z_is_one;\n    }\n\n    ret = 1;\n\n err:\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,\n                                                  const EC_POINT *point,\n                                                  BIGNUM *x, BIGNUM *y,\n                                                  BIGNUM *z, BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    int ret = 0;\n\n    if (group->meth->field_decode != 0) {\n        if (ctx == NULL) {\n            ctx = new_ctx = BN_CTX_new();\n            if (ctx == NULL)\n                return 0;\n        }\n\n        if (x != NULL) {\n            if (!group->meth->field_decode(group, x, &point->X, ctx))\n                goto err;\n        }\n        if (y != NULL) {\n            if (!group->meth->field_decode(group, y, &point->Y, ctx))\n                goto err;\n        }\n        if (z != NULL) {\n            if (!group->meth->field_decode(group, z, &point->Z, ctx))\n                goto err;\n        }\n    } else {\n        if (x != NULL) {\n            if (!BN_copy(x, &point->X))\n                goto err;\n        }\n        if (y != NULL) {\n            if (!BN_copy(y, &point->Y))\n                goto err;\n        }\n        if (z != NULL) {\n            if (!BN_copy(z, &point->Z))\n                goto err;\n        }\n    }\n\n    ret = 1;\n\n err:\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,\n                                               EC_POINT *point,\n                                               const BIGNUM *x,\n                                               const BIGNUM *y, BN_CTX *ctx)\n{\n    if (x == NULL || y == NULL) {\n        /*\n         * unlike for projective coordinates, we do not tolerate this\n         */\n        ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES,\n              ERR_R_PASSED_NULL_PARAMETER);\n        return 0;\n    }\n\n    return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y,\n                                                    BN_value_one(), ctx);\n}\n\nint ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,\n                                               const EC_POINT *point,\n                                               BIGNUM *x, BIGNUM *y,\n                                               BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *Z, *Z_1, *Z_2, *Z_3;\n    const BIGNUM *Z_;\n    int ret = 0;\n\n    if (EC_POINT_is_at_infinity(group, point)) {\n        ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,\n              EC_R_POINT_AT_INFINITY);\n        return 0;\n    }\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    Z = BN_CTX_get(ctx);\n    Z_1 = BN_CTX_get(ctx);\n    Z_2 = BN_CTX_get(ctx);\n    Z_3 = BN_CTX_get(ctx);\n    if ( Z == NULL || Z_1 == NULL || Z_2 == NULL || Z_3 == NULL)\t/* pcg */\n        goto err;\n\n    /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */\n\n    if (group->meth->field_decode) {\n        if (!group->meth->field_decode(group, Z, &point->Z, ctx))\n            goto err;\n        Z_ = Z;\n    } else {\n        Z_ = &point->Z;\n    }\n\n    if (BN_is_one(Z_)) {\n        if (group->meth->field_decode) {\n            if (x != NULL) {\n                if (!group->meth->field_decode(group, x, &point->X, ctx))\n                    goto err;\n            }\n            if (y != NULL) {\n                if (!group->meth->field_decode(group, y, &point->Y, ctx))\n                    goto err;\n            }\n        } else {\n            if (x != NULL) {\n                if (!BN_copy(x, &point->X))\n                    goto err;\n            }\n            if (y != NULL) {\n                if (!BN_copy(y, &point->Y))\n                    goto err;\n            }\n        }\n    } else {\n        if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {\n            ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,\n                  ERR_R_BN_LIB);\n            goto err;\n        }\n\n        if (group->meth->field_encode == 0) {\n            /* field_sqr works on standard representation */\n            if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))\n                goto err;\n        } else {\n            if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))\n                goto err;\n        }\n\n        if (x != NULL) {\n            /*\n             * in the Montgomery case, field_mul will cancel out Montgomery\n             * factor in X:\n             */\n            if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))\n                goto err;\n        }\n\n        if (y != NULL) {\n            if (group->meth->field_encode == 0) {\n                /*\n                 * field_mul works on standard representation\n                 */\n                if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))\n                    goto err;\n            } else {\n                if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))\n                    goto err;\n            }\n\n            /*\n             * in the Montgomery case, field_mul will cancel out Montgomery\n             * factor in Y:\n             */\n            if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx))\n                goto err;\n        }\n    }\n\n    ret = 1;\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                      const EC_POINT *b, BN_CTX *ctx)\n{\n    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,\n                      const BIGNUM *, BN_CTX *);\n    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);\n    const BIGNUM *p;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;\n    int ret = 0;\n\n    if (a == b)\n        return EC_POINT_dbl(group, r, a, ctx);\n    if (EC_POINT_is_at_infinity(group, a))\n        return EC_POINT_copy(r, b);\n    if (EC_POINT_is_at_infinity(group, b))\n        return EC_POINT_copy(r, a);\n\n    field_mul = group->meth->field_mul;\n    field_sqr = group->meth->field_sqr;\n    p = &group->field;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    n0 = BN_CTX_get(ctx);\n    n1 = BN_CTX_get(ctx);\n    n2 = BN_CTX_get(ctx);\n    n3 = BN_CTX_get(ctx);\n    n4 = BN_CTX_get(ctx);\n    n5 = BN_CTX_get(ctx);\n    n6 = BN_CTX_get(ctx);\n    if ( n0 == NULL || n1 == NULL || n2 == NULL || n3 == NULL || \\\n\t\t n4 == NULL || n5 == NULL || n6 == NULL)\t/* pcg */\n        goto end;\n\n    /*\n     * Note that in this function we must not read components of 'a' or 'b'\n     * once we have written the corresponding components of 'r'. ('r' might\n     * be one of 'a' or 'b'.)\n     */\n\n    /* n1, n2 */\n    if (b->Z_is_one) {\n        if (!BN_copy(n1, &a->X))\n            goto end;\n        if (!BN_copy(n2, &a->Y))\n            goto end;\n        /* n1 = X_a */\n        /* n2 = Y_a */\n    } else {\n        if (!field_sqr(group, n0, &b->Z, ctx))\n            goto end;\n        if (!field_mul(group, n1, &a->X, n0, ctx))\n            goto end;\n        /* n1 = X_a * Z_b^2 */\n\n        if (!field_mul(group, n0, n0, &b->Z, ctx))\n            goto end;\n        if (!field_mul(group, n2, &a->Y, n0, ctx))\n            goto end;\n        /* n2 = Y_a * Z_b^3 */\n    }\n\n    /* n3, n4 */\n    if (a->Z_is_one) {\n        if (!BN_copy(n3, &b->X))\n            goto end;\n        if (!BN_copy(n4, &b->Y))\n            goto end;\n        /* n3 = X_b */\n        /* n4 = Y_b */\n    } else {\n        if (!field_sqr(group, n0, &a->Z, ctx))\n            goto end;\n        if (!field_mul(group, n3, &b->X, n0, ctx))\n            goto end;\n        /* n3 = X_b * Z_a^2 */\n\n        if (!field_mul(group, n0, n0, &a->Z, ctx))\n            goto end;\n        if (!field_mul(group, n4, &b->Y, n0, ctx))\n            goto end;\n        /* n4 = Y_b * Z_a^3 */\n    }\n\n    /* n5, n6 */\n    if (!BN_mod_sub_quick(n5, n1, n3, p))\n        goto end;\n    if (!BN_mod_sub_quick(n6, n2, n4, p))\n        goto end;\n    /* n5 = n1 - n3 */\n    /* n6 = n2 - n4 */\n\n    if (BN_is_zero(n5)) {\n        if (BN_is_zero(n6)) {\n            /* a is the same point as b */\n            BN_CTX_end(ctx);\n            ret = EC_POINT_dbl(group, r, a, ctx);\n            ctx = NULL;\n            goto end;\n        } else {\n            /* a is the inverse of b */\n            BN_zero(&r->Z);\n            r->Z_is_one = 0;\n            ret = 1;\n            goto end;\n        }\n    }\n\n    /* 'n7', 'n8' */\n    if (!BN_mod_add_quick(n1, n1, n3, p))\n        goto end;\n    if (!BN_mod_add_quick(n2, n2, n4, p))\n        goto end;\n    /* 'n7' = n1 + n3 */\n    /* 'n8' = n2 + n4 */\n\n    /* Z_r */\n    if (a->Z_is_one && b->Z_is_one) {\n        if (!BN_copy(&r->Z, n5))\n            goto end;\n    } else {\n        if (a->Z_is_one) {\n            if (!BN_copy(n0, &b->Z))\n                goto end;\n        } else if (b->Z_is_one) {\n            if (!BN_copy(n0, &a->Z))\n                goto end;\n        } else {\n            if (!field_mul(group, n0, &a->Z, &b->Z, ctx))\n                goto end;\n        }\n        if (!field_mul(group, &r->Z, n0, n5, ctx))\n            goto end;\n    }\n    r->Z_is_one = 0;\n    /* Z_r = Z_a * Z_b * n5 */\n\n    /* X_r */\n    if (!field_sqr(group, n0, n6, ctx))\n        goto end;\n    if (!field_sqr(group, n4, n5, ctx))\n        goto end;\n    if (!field_mul(group, n3, n1, n4, ctx))\n        goto end;\n    if (!BN_mod_sub_quick(&r->X, n0, n3, p))\n        goto end;\n    /* X_r = n6^2 - n5^2 * 'n7' */\n\n    /* 'n9' */\n    if (!BN_mod_lshift1_quick(n0, &r->X, p))\n        goto end;\n    if (!BN_mod_sub_quick(n0, n3, n0, p))\n        goto end;\n    /* n9 = n5^2 * 'n7' - 2 * X_r */\n\n    /* Y_r */\n    if (!field_mul(group, n0, n0, n6, ctx))\n        goto end;\n    if (!field_mul(group, n5, n4, n5, ctx))\n        goto end;               /* now n5 is n5^3 */\n    if (!field_mul(group, n1, n2, n5, ctx))\n        goto end;\n    if (!BN_mod_sub_quick(n0, n0, n1, p))\n        goto end;\n    if (BN_is_odd(n0))\n        if (!BN_add(n0, n0, p))\n            goto end;\n    /* now  0 <= n0 < 2*p,  and n0 is even */\n    if (!BN_rshift1(&r->Y, n0))\n        goto end;\n    /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */\n\n    ret = 1;\n\n end:\n    if (ctx)                    /* otherwise we already called BN_CTX_end */\n        BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,\n                      BN_CTX *ctx)\n{\n    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,\n                      const BIGNUM *, BN_CTX *);\n    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);\n    const BIGNUM *p;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *n0, *n1, *n2, *n3;\n    int ret = 0;\n\n    if (EC_POINT_is_at_infinity(group, a)) {\n        BN_zero(&r->Z);\n        r->Z_is_one = 0;\n        return 1;\n    }\n\n    field_mul = group->meth->field_mul;\n    field_sqr = group->meth->field_sqr;\n    p = &group->field;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    n0 = BN_CTX_get(ctx);\n    n1 = BN_CTX_get(ctx);\n    n2 = BN_CTX_get(ctx);\n    n3 = BN_CTX_get(ctx);\n    if ( n0 == NULL || n1 == NULL || n2 == NULL || n3 == NULL)\t/* pcg */\n        goto err;\n\n    /*\n     * Note that in this function we must not read components of 'a' once we\n     * have written the corresponding components of 'r'. ('r' might the same\n     * as 'a'.)\n     */\n\n    /* n1 */\n    if (a->Z_is_one) {\n        if (!field_sqr(group, n0, &a->X, ctx))\n            goto err;\n        if (!BN_mod_lshift1_quick(n1, n0, p))\n            goto err;\n        if (!BN_mod_add_quick(n0, n0, n1, p))\n            goto err;\n        if (!BN_mod_add_quick(n1, n0, &group->a, p))\n            goto err;\n        /* n1 = 3 * X_a^2 + a_curve */\n    } else if (group->a_is_minus3) {\n        if (!field_sqr(group, n1, &a->Z, ctx))\n            goto err;\n        if (!BN_mod_add_quick(n0, &a->X, n1, p))\n            goto err;\n        if (!BN_mod_sub_quick(n2, &a->X, n1, p))\n            goto err;\n        if (!field_mul(group, n1, n0, n2, ctx))\n            goto err;\n        if (!BN_mod_lshift1_quick(n0, n1, p))\n            goto err;\n        if (!BN_mod_add_quick(n1, n0, n1, p))\n            goto err;\n        /*-\n         * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)\n         *    = 3 * X_a^2 - 3 * Z_a^4\n         */\n    } else {\n        if (!field_sqr(group, n0, &a->X, ctx))\n            goto err;\n        if (!BN_mod_lshift1_quick(n1, n0, p))\n            goto err;\n        if (!BN_mod_add_quick(n0, n0, n1, p))\n            goto err;\n        if (!field_sqr(group, n1, &a->Z, ctx))\n            goto err;\n        if (!field_sqr(group, n1, n1, ctx))\n            goto err;\n        if (!field_mul(group, n1, n1, &group->a, ctx))\n            goto err;\n        if (!BN_mod_add_quick(n1, n1, n0, p))\n            goto err;\n        /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */\n    }\n\n    /* Z_r */\n    if (a->Z_is_one) {\n        if (!BN_copy(n0, &a->Y))\n            goto err;\n    } else {\n        if (!field_mul(group, n0, &a->Y, &a->Z, ctx))\n            goto err;\n    }\n    if (!BN_mod_lshift1_quick(&r->Z, n0, p))\n        goto err;\n    r->Z_is_one = 0;\n    /* Z_r = 2 * Y_a * Z_a */\n\n    /* n2 */\n    if (!field_sqr(group, n3, &a->Y, ctx))\n        goto err;\n    if (!field_mul(group, n2, &a->X, n3, ctx))\n        goto err;\n    if (!BN_mod_lshift_quick(n2, n2, 2, p))\n        goto err;\n    /* n2 = 4 * X_a * Y_a^2 */\n\n    /* X_r */\n    if (!BN_mod_lshift1_quick(n0, n2, p))\n        goto err;\n    if (!field_sqr(group, &r->X, n1, ctx))\n        goto err;\n    if (!BN_mod_sub_quick(&r->X, &r->X, n0, p))\n        goto err;\n    /* X_r = n1^2 - 2 * n2 */\n\n    /* n3 */\n    if (!field_sqr(group, n0, n3, ctx))\n        goto err;\n    if (!BN_mod_lshift_quick(n3, n0, 3, p))\n        goto err;\n    /* n3 = 8 * Y_a^4 */\n\n    /* Y_r */\n    if (!BN_mod_sub_quick(n0, n2, &r->X, p))\n        goto err;\n    if (!field_mul(group, n0, n1, n0, ctx))\n        goto err;\n    if (!BN_mod_sub_quick(&r->Y, n0, n3, p))\n        goto err;\n    /* Y_r = n1 * (n2 - X_r) - n3 */\n\n    ret = 1;\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)\n{\n    if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))\n        /* point is its own inverse */\n        return 1;\n\n    return BN_usub(&point->Y, &group->field, &point->Y);\n}\n\nint ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)\n{\n    return BN_is_zero(&point->Z);\n}\n\nint ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,\n                              BN_CTX *ctx)\n{\n    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,\n                      const BIGNUM *, BN_CTX *);\n    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);\n    const BIGNUM *p;\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *rh, *tmp, *Z4, *Z6;\n    int ret = -1;\n\n    if (EC_POINT_is_at_infinity(group, point))\n        return 1;\n\n    field_mul = group->meth->field_mul;\n    field_sqr = group->meth->field_sqr;\n    p = &group->field;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return -1;\n    }\n\n    BN_CTX_start(ctx);\n    rh = BN_CTX_get(ctx);\n    tmp = BN_CTX_get(ctx);\n    Z4 = BN_CTX_get(ctx);\n    Z6 = BN_CTX_get(ctx);\n    if ( rh == NULL || tmp == NULL || Z4 == NULL || Z6 == NULL)\t/* pcg */\n        goto err;\n\n    /*-\n     * We have a curve defined by a Weierstrass equation\n     *      y^2 = x^3 + a*x + b.\n     * The point to consider is given in Jacobian projective coordinates\n     * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).\n     * Substituting this and multiplying by  Z^6  transforms the above equation into\n     *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.\n     * To test this, we add up the right-hand side in 'rh'.\n     */\n\n    /* rh := X^2 */\n    if (!field_sqr(group, rh, &point->X, ctx))\n        goto err;\n\n    if (!point->Z_is_one) {\n        if (!field_sqr(group, tmp, &point->Z, ctx))\n            goto err;\n        if (!field_sqr(group, Z4, tmp, ctx))\n            goto err;\n        if (!field_mul(group, Z6, Z4, tmp, ctx))\n            goto err;\n\n        /* rh := (rh + a*Z^4)*X */\n        if (group->a_is_minus3) {\n            if (!BN_mod_lshift1_quick(tmp, Z4, p))\n                goto err;\n            if (!BN_mod_add_quick(tmp, tmp, Z4, p))\n                goto err;\n            if (!BN_mod_sub_quick(rh, rh, tmp, p))\n                goto err;\n            if (!field_mul(group, rh, rh, &point->X, ctx))\n                goto err;\n        } else {\n            if (!field_mul(group, tmp, Z4, &group->a, ctx))\n                goto err;\n            if (!BN_mod_add_quick(rh, rh, tmp, p))\n                goto err;\n            if (!field_mul(group, rh, rh, &point->X, ctx))\n                goto err;\n        }\n\n        /* rh := rh + b*Z^6 */\n        if (!field_mul(group, tmp, &group->b, Z6, ctx))\n            goto err;\n        if (!BN_mod_add_quick(rh, rh, tmp, p))\n            goto err;\n    } else {\n        /* point->Z_is_one */\n\n        /* rh := (rh + a)*X */\n        if (!BN_mod_add_quick(rh, rh, &group->a, p))\n            goto err;\n        if (!field_mul(group, rh, rh, &point->X, ctx))\n            goto err;\n        /* rh := rh + b */\n        if (!BN_mod_add_quick(rh, rh, &group->b, p))\n            goto err;\n    }\n\n    /* 'lh' := Y^2 */\n    if (!field_sqr(group, tmp, &point->Y, ctx))\n        goto err;\n\n    ret = (0 == BN_ucmp(tmp, rh));\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,\n                      const EC_POINT *b, BN_CTX *ctx)\n{\n    /*-\n     * return values:\n     *  -1   error\n     *   0   equal (in affine coordinates)\n     *   1   not equal\n     */\n\n    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,\n                      const BIGNUM *, BN_CTX *);\n    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *tmp1, *tmp2, *Za23, *Zb23;\n    const BIGNUM *tmp1_, *tmp2_;\n    int ret = -1;\n\n    if (EC_POINT_is_at_infinity(group, a)) {\n        return EC_POINT_is_at_infinity(group, b) ? 0 : 1;\n    }\n\n    if (EC_POINT_is_at_infinity(group, b))\n        return 1;\n\n    if (a->Z_is_one && b->Z_is_one) {\n        return ((BN_cmp(&a->X, &b->X) == 0)\n                && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;\n    }\n\n    field_mul = group->meth->field_mul;\n    field_sqr = group->meth->field_sqr;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return -1;\n    }\n\n    BN_CTX_start(ctx);\n    tmp1 = BN_CTX_get(ctx);\n    tmp2 = BN_CTX_get(ctx);\n    Za23 = BN_CTX_get(ctx);\n    Zb23 = BN_CTX_get(ctx);\n    if (Zb23 == NULL)\n        goto end;\n\n    /*-\n     * We have to decide whether\n     *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),\n     * or equivalently, whether\n     *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).\n     */\n\n    if (!b->Z_is_one) {\n        if (!field_sqr(group, Zb23, &b->Z, ctx))\n            goto end;\n        if (!field_mul(group, tmp1, &a->X, Zb23, ctx))\n            goto end;\n        tmp1_ = tmp1;\n    } else\n        tmp1_ = &a->X;\n    if (!a->Z_is_one) {\n        if (!field_sqr(group, Za23, &a->Z, ctx))\n            goto end;\n        if (!field_mul(group, tmp2, &b->X, Za23, ctx))\n            goto end;\n        tmp2_ = tmp2;\n    } else\n        tmp2_ = &b->X;\n\n    /* compare  X_a*Z_b^2  with  X_b*Z_a^2 */\n    if (BN_cmp(tmp1_, tmp2_) != 0) {\n        ret = 1;                /* points differ */\n        goto end;\n    }\n\n    if (!b->Z_is_one) {\n        if (!field_mul(group, Zb23, Zb23, &b->Z, ctx))\n            goto end;\n        if (!field_mul(group, tmp1, &a->Y, Zb23, ctx))\n            goto end;\n        /* tmp1_ = tmp1 */\n    } else\n        tmp1_ = &a->Y;\n    if (!a->Z_is_one) {\n        if (!field_mul(group, Za23, Za23, &a->Z, ctx))\n            goto end;\n        if (!field_mul(group, tmp2, &b->Y, Za23, ctx))\n            goto end;\n        /* tmp2_ = tmp2 */\n    } else\n        tmp2_ = &b->Y;\n\n    /* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */\n    if (BN_cmp(tmp1_, tmp2_) != 0) {\n        ret = 1;                /* points differ */\n        goto end;\n    }\n\n    /* points are equal */\n    ret = 0;\n\n end:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,\n                              BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *x, *y;\n    int ret = 0;\n\n    if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))\n        return 1;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    x = BN_CTX_get(ctx);\n    y = BN_CTX_get(ctx);\n    if (y == NULL)\n        goto err;\n\n    if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))\n        goto err;\n    if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))\n        goto err;\n    if (!point->Z_is_one) {\n        ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);\n        goto err;\n    }\n\n    ret = 1;\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    return ret;\n}\n\nint ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,\n                                     EC_POINT *points[], BN_CTX *ctx)\n{\n    BN_CTX *new_ctx = NULL;\n    BIGNUM *tmp, *tmp_Z;\n    BIGNUM **prod_Z = NULL;\n    size_t i;\n    int ret = 0;\n\n    if (num == 0)\n        return 1;\n\n    if (ctx == NULL) {\n        ctx = new_ctx = BN_CTX_new();\n        if (ctx == NULL)\n            return 0;\n    }\n\n    BN_CTX_start(ctx);\n    tmp = BN_CTX_get(ctx);\n    tmp_Z = BN_CTX_get(ctx);\n    if (tmp == NULL || tmp_Z == NULL)\n        goto err;\n\n\tprod_Z = clBnAlloc(\"ec_GFp_simple_points_make_affine\", num * sizeof prod_Z[0]);\t\t/* pcg */\n    if (prod_Z == NULL)\n        goto err;\n    for (i = 0; i < num; i++) {\n        prod_Z[i] = BN_new();\n        if (prod_Z[i] == NULL)\n            goto err;\n    }\n\n    /*\n     * Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,\n     * skipping any zero-valued inputs (pretend that they're 1).\n     */\n\n    if (!BN_is_zero(&points[0]->Z)) {\n        if (!BN_copy(prod_Z[0], &points[0]->Z))\n            goto err;\n    } else {\n        if (group->meth->field_set_to_one != 0) {\n            if (!group->meth->field_set_to_one(group, prod_Z[0], ctx))\n                goto err;\n        } else {\n            if (!BN_one(prod_Z[0]))\n                goto err;\n        }\n    }\n\n    for (i = 1; i < num; i++) {\n        if (!BN_is_zero(&points[i]->Z)) {\n            if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1],\n                                        &points[i]->Z, ctx))\n                goto err;\n        } else {\n            if (!BN_copy(prod_Z[i], prod_Z[i - 1]))\n                goto err;\n        }\n    }\n\n    /*\n     * Now use a single explicit inversion to replace every non-zero\n     * points[i]->Z by its inverse.\n     */\n\n    if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) {\n        ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);\n        goto err;\n    }\n    if (group->meth->field_encode != 0) {\n        /*\n         * In the Montgomery case, we just turned R*H (representing H) into\n         * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to\n         * multiply by the Montgomery factor twice.\n         */\n        if (!group->meth->field_encode(group, tmp, tmp, ctx))\n            goto err;\n        if (!group->meth->field_encode(group, tmp, tmp, ctx))\n            goto err;\n    }\n\n    for (i = num - 1; i > 0; --i) {\n        /*\n         * Loop invariant: tmp is the product of the inverses of points[0]->Z\n         * .. points[i]->Z (zero-valued inputs skipped).\n         */\n        if (!BN_is_zero(&points[i]->Z)) {\n            /*\n             * Set tmp_Z to the inverse of points[i]->Z (as product of Z\n             * inverses 0 .. i, Z values 0 .. i - 1).\n             */\n            if (!group->\n                meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx))\n                goto err;\n            /*\n             * Update tmp to satisfy the loop invariant for i - 1.\n             */\n            if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx))\n                goto err;\n            /* Replace points[i]->Z by its inverse. */\n            if (!BN_copy(&points[i]->Z, tmp_Z))\n                goto err;\n        }\n    }\n\n    if (!BN_is_zero(&points[0]->Z)) {\n        /* Replace points[0]->Z by its inverse. */\n        if (!BN_copy(&points[0]->Z, tmp))\n            goto err;\n    }\n\n    /* Finally, fix up the X and Y coordinates for all points. */\n\n    for (i = 0; i < num; i++) {\n        EC_POINT *p = points[i];\n\n        if (!BN_is_zero(&p->Z)) {\n            /* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */\n\n            if (!group->meth->field_sqr(group, tmp, &p->Z, ctx))\n                goto err;\n            if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx))\n                goto err;\n\n            if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx))\n                goto err;\n            if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx))\n                goto err;\n\n            if (group->meth->field_set_to_one != 0) {\n                if (!group->meth->field_set_to_one(group, &p->Z, ctx))\n                    goto err;\n            } else {\n                if (!BN_one(&p->Z))\n                    goto err;\n            }\n            p->Z_is_one = 1;\n        }\n    }\n\n    ret = 1;\n\n err:\n    BN_CTX_end(ctx);\n    if (new_ctx != NULL)\n        BN_CTX_free(new_ctx);\n    if (prod_Z != NULL) {\n        for (i = 0; i < num; i++) {\n            if (prod_Z[i] == NULL)\n                break;\n            BN_clear_free(prod_Z[i]);\n        }\n        OPENSSL_free(prod_Z);\n    }\n    return ret;\n}\n\nint ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,\n                            const BIGNUM *b, BN_CTX *ctx)\n{\n    return BN_mod_mul(r, a, b, &group->field, ctx);\n}\n\nint ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,\n                            BN_CTX *ctx)\n{\n    return BN_mod_sqr(r, a, &group->field, ctx);\n}\n#endif /* USE_ECDH || USE_ECDSA */\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/cert/cert.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Routines Header File \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CERT_DEFINED\n\n#define _CERT_DEFINED\n\n#include <time.h>\n#ifndef _ASN1_DEFINED\n  #if defined( INC_ALL )\n\t#include \"asn1.h\"\n  #else\n\t#include \"enc_dec/asn1.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _ASN1_DEFINED */\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n\n/* The minimum permitted size of an attribute:\n\t\n\tSEQUENCE {\t\t\t\t\t-- 2\n\t\tOID\tbasicConstraints,\t-- 5\n\t\tOCTET STRING {\t\t\t-- 2\n\t\t\tSEQUENCE {}\t\t\t-- 2\n\t\t\t}\n\t\t} */\n\n#define MIN_ATTRIBUTE_SIZE\t\t11\n\n/* The minimum permitted size of a non-null/empty DN:\n\n\t\tname SEQUENCE OF {\t\t\t\t\t\t\t-- 2\n\t\t\tSET {\t\t\t\t\t\t\t\t\t-- 2\n\t\t\t\tSEQUENCE {\t\t\t\t\t\t\t-- 2\n\t\t\t\t\ttype\tOBJECT IDENTIFIER\t\t-- 2 + 3\n\t\t\t\t\tvalue\tANY DEFINED BY type\t\t-- 2\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} */\n\n#define MIN_DN_SIZE\t\t\t\t13\n\n/* The maximum size of a PKCS #7 certificate chain, any chain longer than 8\n   certificates is somewhat suspicious, in fact a limit of 4 or 5 would\n   probably be sufficient for any chains seen in the wild.\n   \n   The built-in bounds value FAILSAFE_ITERATIONS_MED is used as a safety \n   check for an upper limit on chain lengths (that is, if we hit \n   FAILSAFE_ITERATIONS_MED on processing a certificate chain it's an \n   internal error), so it has to be larger than MAX_CHAINLENGTH */\n\n#define MAX_CHAINLENGTH\t\t\t8\n\n#if MAX_CHAINLENGTH > FAILSAFE_ITERATIONS_MED\n  #error FAILSAFE_ITERATIONS_MED must be larger than the maximum certificate chain length\n#endif /* MAX_CHAINLENGTH > FAILSAFE_ITERATIONS_MED */\n\n/* The default size of the serial number, size of the built-in serial number\n   buffer (anything larger than this uses a dynamically-allocated buffer)\n   and the maximum size in bytes of a serial number (for example in a\n   certificate or CRL).  Technically values of any size are allowed but\n   anything larger than this is probably an error */\n\n#define DEFAULT_SERIALNO_SIZE\t8\n#define SERIALNO_BUFSIZE\t\t32\n#define MAX_SERIALNO_SIZE\t\t64\n\n/* The size of the PKI user binary authenticator information before\n   checksumming and encoding and the size of the encrypted user info:\n   sizeofObject( 2 * sizeofObject( PKIUSER_AUTHENTICATOR_SIZE ) ) + PKCS #5\n   padding = 2 + ( 2 + 12 + 2 + 12 ) = 30 + 2 = 32.  This works for both 64-\n   and 128-bit block ciphers */\n\n#define PKIUSER_AUTHENTICATOR_SIZE\t\t12\n#define PKIUSER_ENCR_AUTHENTICATOR_SIZE\t32\n\n/* The size of the FIFO used to encode nested SEQUENCEs */\n\n#define ENCODING_FIFO_SIZE\t\t10\n\n/* Normally we check for a valid time by making sure that it's more recent \n   than MIN_TIME_VALUE, however when reading a certificate the time can be \n   much earlier than this if it's an old certificate.  To handle this we \n   define a certificate-specific time value that we use as the oldest valid \n   time value */\n\n#define MIN_CERT_TIME_VALUE\t\t( ( 1998 - 1970 ) * 365 * 86400L )\n\n/* X.509 certificate version numbers.  These are somewhat tautological, but \n   we define them anyway in order to avoid hardcoding constants into various \n   places in the code */\n\n#define X509_V1\t\t\t\t\t1\n#define X509_V2\t\t\t\t\t2\n#define X509_V3\t\t\t\t\t3\n\n/* Certificate information flags.  These are:\n\n\tFLAG_CERTCOLLECTION: Indicates that a certificate chain object contains \n\t\t\tonly an unordered collection of (non-duplicate) certificates \n\t\t\trather than a true certificate chain.  Note that this is a pure \n\t\t\tcontainer object for which only the certificate chain member \n\t\t\tcontains certificates, the base certificate object doesn't \n\t\t\tcorrespond to an actual certificate.\n\n\tFLAG_CRLENTRY: The CRL object contains the data from a single CRL entry\n\t\t\trather than being a complete CRL.\n\n\tFLAG_DATAONLY: Indicates a pure data object with no attached context.\n\n\tFLAG_PATHKLUDGE: Indicates that although the certificate appears to be a \n\t\t\tself-signed (CA root) certificate it's actually a PKIX path \n\t\t\tkludge certificate that's used to tie a re-issued CA certificate \n\t\t\t(with a new CA key) to existing issued certificates signed with \n\t\t\tthe old CA key.  This kludge requires that issuer DN == subject \n\t\t\tDN, which would denote a CA root certificate under normal \n\t\t\tcircumstances.\n\n\tFLAG_SELFSIGNED: Indicates that the certificate is self-signed.\n\n\tFLAG_SIGCHECKED: Caches the check of the certificate signature.  This is \n\t\t\tdone because it's only necessary to perform this once when the \n\t\t\tcertificate is checked for the first time.  Checking of \n\t\t\tcertificate fields that aren't affected by the issuer \n\t\t\tcertificate is also cached, but this is handled by the \n\t\t\tcompliance-level check value rather than a simple boolean flag \n\t\t\tsince a certificate can be checked at various levels of \n\t\t\tstandards-compliance */\n\n#define CERT_FLAG_NONE\t\t\t0x00\t/* No flag */\n#define CERT_FLAG_SELFSIGNED\t0x01\t/* Certificate is self-signed */\n#define CERT_FLAG_SIGCHECKED\t0x02\t/* Signature has been checked */\n#define CERT_FLAG_DATAONLY\t\t0x04\t/* Certificate is data-only (no context) */\n#define CERT_FLAG_CRLENTRY\t\t0x08\t/* CRL is a standalone single entry */\n#define CERT_FLAG_CERTCOLLECTION 0x10\t/* Certificate chain is unordered collection */\n#define CERT_FLAG_PATHKLUDGE\t0x20\t/* Certificate is a PKIX path kludge */\n#define CERT_FLAG_MAX\t\t\t0x3F\t/* Maximum possible flag value */\n\n/* When creating RTCS responses from a request there are several subtypes\n   that we can use based on a format specifier in the request.  When we turn\n   the request into a response we check the format specifiers and record the\n   response format as being one of the following */\n\ntypedef enum {\n\tRTCSRESPONSE_TYPE_NONE,\t\t\t\t/* No response type */\n\tRTCSRESPONSE_TYPE_BASIC,\t\t\t/* Basic response */\n\tRTCSRESPONSE_TYPE_EXTENDED,\t\t\t/* Extended response */\n\tRTCSRESPONSE_TYPE_LAST\t\t\t\t/* Last valid response type */\n\t} RTCSRESPONSE_TYPE;\n\n/* Set the error locus and type.  This is used for certificate checking \n   functions that need to return extended error information but can't modify \n   the certificate information struct due to it either being a const \n   parameter or only being available via a handle so that setErrorInfo() \n   can't be used */\n\n#define setErrorValues( locus, type ) \\\n\t\t*errorLocus = ( locus ); *errorType = ( type )\n\n/* The are several different classes of attributes that can be used \n   depending on the object that they're associated with.  The following \n   values are used to select the class of attribute that we want to work \n   with */\n\ntypedef enum {\n\tATTRIBUTE_NONE,\t\t\t\t\t\t/* No attribute type */\n\tATTRIBUTE_CERTIFICATE,\t\t\t\t/* Certificate attributes */\n\tATTRIBUTE_CMS,\t\t\t\t\t\t/* CMS / S/MIME attributes */\n\tATTRIBUTE_LAST\t\t\t\t\t\t/* Last valid attribute type */\n\t} ATTRIBUTE_TYPE;\n\n/* When checking policy constraints there are several different types of\n   checking that we can apply depending on the presence of other constraints \n   in the issuing certificate(s) and the level of checking that we're \n   performing.  Policies can be optional, required, or a specific-policy \n   check that disallows the wildcard anyPolicy as a matching policy */\n\ntypedef enum {\t\t\t\t\t\t\t/* Issuer\t\tSubject\t\t*/\n\tPOLICY_NONE,\t\t\t\t\t\t/*\t -\t\t\t -\t\t\t*/\n\tPOLICY_NONE_SPECIFIC,\t\t\t\t/*\t -,  !any\t -,  !any\t*/\n\tPOLICY_SUBJECT,\t\t\t\t\t\t/*\t -\t\t\tyes\t\t\t*/\n\tPOLICY_SUBJECT_SPECIFIC,\t\t\t/*\t -\t\t\tyes, !any\t*/\n\tPOLICY_BOTH,\t\t\t\t\t\t/*\tyes\t\t\tyes\t\t\t*/\n\tPOLICY_BOTH_SPECIFIC,\t\t\t\t/*\tyes, !any\tyes, !any\t*/\n\tPOLICY_LAST\t\t\t\t\t\t\t/* Last valid policy type */\n\t} POLICY_TYPE;\n\n/* Selection options when working with DNs/GeneralNames in extensions.  These\n   are used internally when handling user get/set/delete DN/GeneralName\n   requests */\n\ntypedef enum {\n\tSELECTION_OPTION_NONE,\t/* No selection option type */\n\tMAY_BE_ABSENT,\t\t\t/* Component may be absent */\n\tMUST_BE_PRESENT,\t\t/* Component must be present */\n\tCREATE_IF_ABSENT,\t\t/* Create component if absent */\n\tSELECTION_OPTION_LAST\t/* Last valid selection option type */\n\t} SELECTION_OPTION;\n\n/* Certificate key check flags, used by checkKeyUsage().  These are:\n\n\tFLAG_NONE: No specific check.\n\n\tFLAG_CA: Certificate must contain a CA key.\n\n\tFLAG_PRIVATEKEY: Check for constraints on the corresponding private\n\t\t\tkey's usage, not just the public key usage.\n\n\tFLAG_GENCHECK: Perform a general check that the key usage details are\n\t\t\tin order without checking for a particular usage */\n\n#define CHECKKEY_FLAG_NONE\t\t\t0x00\t/* No specific checks */\n#define CHECKKEY_FLAG_CA\t\t\t0x01\t/* Must be CA key */\n#define CHECKKEY_FLAG_PRIVATEKEY\t0x02\t/* Check priv.key constraints */\n#define CHECKKEY_FLAG_GENCHECK\t\t0x04\t/* General details check */\n#define CHECKKEY_FLAG_MAX\t\t\t0x07\t/* Maximum possible flag value */\n\n/* Before we encode a certificate object we have to perform various final \n   setup actions and check that the object is ready for encoding.  The \n   following setup operations can be requested by the caller via\n   preEncodeCertificate():\n\n\tSET_ISSUERATTR: Copy issuer attributes to subject.\n\n\tSET_ISSUERDN: Copy issuer DN to subject.\n\n\tSET_REVINFO: Set up revocation information.\n\n\tSET_STANDARDATTR: Set up standard extensions/attributes.\n\n\tSET_VALIDITYPERIOD: Constrain subject validity to issuer validity.\n\n\tSET_VALINFO: Set up validity information */\n\n#define PRE_SET_NONE\t\t\t0x0000\t/* No setup actions */\n#define PRE_SET_STANDARDATTR\t0x0001\t/* Set up standard extensions */\n#define PRE_SET_ISSUERATTR\t\t0x0002\t/* Copy issuer attr.to subject */\n#define PRE_SET_ISSUERDN\t\t0x0004\t/* Copy issuer DN to subject */\n#define PRE_SET_VALIDITYPERIOD\t0x0008\t/* Constrain subj.val.to issuer val.*/\n#define PRE_SET_VALINFO\t\t\t0x0010\t/* Set up validity information */\n#define PRE_SET_REVINFO\t\t\t0x0020\t/* Set up revocation information */\n\n#define PRE_SET_FLAG_NONE\t\t0x0000\t/* No setup actions */\n#define PRE_SET_FLAG_MAX\t\t0x003F\t/* Maximum possible flag value */\n\n/* The following checks can be requested by the caller via \n   preCheckCertificate():\n\n\tCHECK_DN: Full subject DN is present.\n\n\tCHECK_DN_PARTIAL: Partial subject DN is present.  This is a DN template\n\t\tso the full DN doesn't have to be present (the CA can fill in the \n\t\trest later), only the CommonName.\n\n\tCHECK_ISSUERDN: Issuer DN is present.\n\n\tCHECK_ISSUERCERTDN: Issuer certificate's subject DN == subject \n\t\tcertificate's issuer DN.\n\n\tCHECK_NONSELFSIGNEDDN: Certificate's subject DN != certificate's issuer \n\t\tDN, which would make it appear to be a self-signed certificate.\n\n\tCHECK_REVENTRIES: At least one revocation entry is present.\n\n\tCHECK_SERIALNO: Serial number is present.\n\n\tCHECK_SPKI: SubjectPublicKeyInfo is present.\n\n\tCHECK_VALENTRIES: At least one validity entry is present */\n\n#define PRE_CHECK_NONE\t\t\t0x0000\t/* No check actions */\n#define PRE_CHECK_SPKI\t\t\t0x0001\t/* SPKI present */\n#define PRE_CHECK_DN\t\t\t0x0002\t/* Subject DN present */\n#define PRE_CHECK_DN_PARTIAL\t0x0004\t/* Partial subject DN present */\n#define PRE_CHECK_ISSUERDN\t\t0x0008\t/* Issuer DN present */\n#define PRE_CHECK_ISSUERCERTDN\t0x0010\t/* Issuer cert DN == subj.issuer DN */\n#define PRE_CHECK_NONSELFSIGNED_DN 0x0020\t/* Issuer DN != subject DN */\n#define PRE_CHECK_SERIALNO\t\t0x0040\t/* SerialNo present */\n#define PRE_CHECK_VALENTRIES\t0x0080\t/* Validity entries present */\n#define PRE_CHECK_REVENTRIES\t0x0100\t/* Revocation entries present */\n\n#define PRE_CHECK_FLAG_NONE\t\t0x0000\t/* No check actions */\n#define PRE_CHECK_FLAG_MAX\t\t0x01FF\t/* Maximum possible flag value */\n\n/* Additional flags that control the checking operations indicated above */\n\n#define PRE_FLAG_NONE\t\t\t0x0000\t/* No special control options */\n#define PRE_FLAG_DN_IN_ISSUERCERT 0x0001/* Issuer DN is in issuer cert */\n#define PRE_FLAG_MAX\t\t\t0x0001\t/* Maximum possible flag value */\n\n/* The following checks can be requested by the caller via checkDN() */\n\n#define CHECKDN_FLAG_NONE\t\t\t0x00\t/* No DN check */\n#define CHECKDN_FLAG_COUNTRY\t\t0x01\t/* Check DN has C */\n#define CHECKDN_FLAG_COMMONNAME\t\t0x02\t/* Check DN has CN */\n#define CHECKDN_FLAG_WELLFORMED\t\t0x04\t/* Check DN is well-formed */\n#define CHECKDN_FLAG_MAX\t\t\t0x0F\t/* Maximum possible flag value */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Element Tags\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Context-specific tags for certificates */\n\nenum { CTAG_CE_VERSION, CTAG_CE_ISSUERUNIQUEID, CTAG_CE_SUBJECTUNIQUEID,\n\t   CTAG_CE_EXTENSIONS };\n\n/* Context-specific tags for attribute certificates */\n\nenum { CTAG_AC_HOLDER_BASECERTIFICATEID, CTAG_AC_HOLDER_ENTITYNAME,\n\t   CTAG_AC_HOLDER_OBJECTDIGESTINFO };\nenum { CTAG_AC_ISSUER_BASECERTIFICATEID, CTAG_AC_ISSUER_OBJECTDIGESTINFO };\n\n/* Context-specific tags for certification requests */\n\nenum { CTAG_CR_ATTRIBUTES };\n\n/* Context-specific tags for CRLs */\n\nenum { CTAG_CL_EXTENSIONS };\n\n/* Context-specific tags for CRMF certification requests.  The second set of \n   tags is for POP of the private key */\n\nenum { CTAG_CF_VERSION, CTAG_CF_SERIALNUMBER, CTAG_CF_SIGNINGALG,\n\t   CTAG_CF_ISSUER, CTAG_CF_VALIDITY, CTAG_CF_SUBJECT, CTAG_CF_PUBLICKEY,\n\t   CTAG_CF_ISSUERUID, CTAG_CF_SUBJECTUID, CTAG_CF_EXTENSIONS };\nenum { CTAG_CF_POP_NONE, CTAG_CF_POP_SIGNATURE, CTAG_CF_POP_ENCRKEY };\n\n/* Context-specific tags for RTCS responses */\n\nenum { CTAG_RP_EXTENSIONS };\n\n/* Context-specific tags for OCSP requests.  The second set of tags\n   is for each request entry in an overall request */\n\nenum { CTAG_OR_VERSION, CTAG_OR_DUMMY, CTAG_OR_EXTENSIONS };\nenum { CTAG_OR_SR_EXTENSIONS };\n\n/* Context-specific tags for OCSP responses */\n\nenum { CTAG_OP_VERSION, CTAG_OP_EXTENSIONS };\n\n/* Context-specific tags for CMS attributes */\n\nenum { CTAG_SI_AUTHENTICATEDATTRIBUTES };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Data Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Symbolic defines to make it more obvious what we're working with for \n   attribute and DN lists */\n\n#define DATAPTR_ATTRIBUTE\t\tDATAPTR\n#define DATAPTR_DN\t\t\t\tDATAPTR\n\n/* Get/set DN pointers */\n\n#define GET_DN_POINTER( attributeListPtr ) \\\n\t\t( attributeListPtr )->dnValue\n#define SET_DN_POINTER( attributeListPtr, dn ) \\\n\t\t( attributeListPtr )->dnValue = dn\n\n/* The structure to hold information on the current selection of attribute/\n   GeneralName/DN data used when adding/reading/deleting certificate \n   components.  The usage of this information is too complex to explain \n   here, see the comments at the start of comp_get.c for more details.\n   \n   Note that the DN pointer stores a pointer to the head of the list of DN\n   elements rather than storing the list head itself since we need to pass \n   it to functions that may modify the list head.  So dnPtr may contain\n   (for example) &certInfoPtr->subjectDN so that it can be passed to \n   functions like deleteDnComponent() which may have to modify the list \n   head if that's the entry that they're being asked to delete.  Storing a\n   copy of certInfoPtr->subjectDN in dnPtr and then passing &dnPtr to\n   deleteDnComponent() would update dnPtr but leave certInfoPtr->subjectDN \n   with a dangling reference to the new-deleted DN element */\n\ntypedef struct {\n\tDATAPTR_DN *dnPtr;\t\t\t\t\t/* Pointer to address of current DN */\n\tCRYPT_ATTRIBUTE_TYPE generalName;\t/* Selected GN */\n\tCRYPT_ATTRIBUTE_TYPE dnComponent;\t/* Selected component of DN */\n\tint dnComponentCount;\t\t\t\t/* Iterator for DN components */\n\tBOOLEAN dnInExtension;\t\t\t\t/* Whether DN is in extension */\n\tBOOLEAN updateCursor;\t\t\t\t/* Whether to upate attr.cursor */\n\t} SELECTION_INFO;\n\n#define initSelectionInfo( certInfoPtr ) \\\n\tmemset( &( certInfoPtr )->currentSelection, 0, sizeof( SELECTION_INFO ) ); \\\n\t( certInfoPtr )->currentSelection.dnPtr = &( ( certInfoPtr )->subjectName )\n\n#define selectSubjectName( certInfoPtr ) \\\n\t( certInfoPtr )->currentSelection.dnPtr = &( ( certInfoPtr )->subjectName )\n#define selectIssuerName( certInfoPtr ) \\\n\t( certInfoPtr )->currentSelection.dnPtr = &( ( certInfoPtr )->issuerName )\n\n#define isSubjectNameSelected( certInfoPtr ) \\\n\t( ( certInfoPtr )->currentSelection.dnPtr == &( certInfoPtr )->subjectName )\n#define isIssuerNameSelected( certInfoPtr ) \\\n\t( ( certInfoPtr )->currentSelection.dnPtr == &( certInfoPtr )->issuerName )\n\n/* Sometimes we need to manipulate an internal component which is addressed\n   indirectly as a side-effect of some other processing operation.  We can't\n   change the selection information for the certificate object since this will \n   affect any future operations that the user performs so we provide the \n   following macros to save and restore the selection state around these \n   operations */\n\ntypedef struct {\n\tint savedChainPos;\t\t\t\t\t/* Current cert.chain position */\n\tSELECTION_INFO savedSelectionInfo;\t/* Current DN/GN selection info */\n\tDATAPTR_ATTRIBUTE savedAttributeCursor;/* Atribute cursor pos.*/\n\t} SELECTION_STATE;\n\n#define saveSelectionState( savedState, certInfoPtr ) \\\n\t{ \\\n\tmemset( &( savedState ), 0, sizeof( SELECTION_STATE ) ); \\\n\tif( ( certInfoPtr )->type == CRYPT_CERTTYPE_CERTCHAIN ) \\\n\t\t( savedState ).savedChainPos = ( certInfoPtr )->cCertCert->chainPos; \\\n\t( savedState ).savedSelectionInfo = ( certInfoPtr )->currentSelection; \\\n\t( savedState ).savedAttributeCursor = ( certInfoPtr )->attributeCursor; \\\n\t}\n\n#define restoreSelectionState( savedState, certInfoPtr ) \\\n\t{ \\\n\tif( ( certInfoPtr )->type == CRYPT_CERTTYPE_CERTCHAIN ) \\\n\t\t( certInfoPtr )->cCertCert->chainPos = ( savedState ).savedChainPos; \\\n\t( certInfoPtr )->currentSelection = ( savedState ).savedSelectionInfo; \\\n\t( certInfoPtr )->attributeCursor = ( savedState ).savedAttributeCursor; \\\n\t}\n\n/* The structure used to store the current policy set if we're doing full\n   policy checking, enabled for CERTLEVEL_PKIX_FULL.  The MAX_POLICY_SIZE\n   value corresponds to MAX_OID_SIZE, unfortunately this define isn't \n   visible at this level so we have to specify the value explicitly (the \n   length is checked on read so there's no chance of an overflow).\n   \n   When we store the policy value (which is just the encoded policy OID) we\n   also store the level in the certificate chain at which it was added\n   (since a policy is only valid below the point at which it was added) and\n   an indication of whether the policy is explicit or mapped, since the \n   latter can be disabled by the inhibitPolicyMapping value */\n\n#if defined( USE_CERTLEVEL_PKIX_FULL )\n\n#define MAX_POLICIES\t\t\t16\n#define MAX_POLICY_SIZE\t\t\t32\n\ntypedef struct {\n\tBYTE data[ MAX_POLICY_SIZE + 8 ];\n\tint length;\t\t\t\t\t/* Policy value and length */\n\tint level;\t\t\t\t\t/* Pos.in chain at which pol.becomes valid */\n\tBOOLEAN isMapped;\t\t\t/* Whether this is a mapped policy */\n\t} POLICY_DATA;\n\ntypedef struct {\n\tPOLICY_DATA policies[ MAX_POLICIES + 4 ];\n\tint noPolicies;\n\t} POLICY_INFO;\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n#ifdef USE_CERTVAL\n\n/* The structure to hold a validity information entry */\n\ntypedef struct VI {\n\t/* Certificate ID information */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE data[ KEYID_SIZE + 8 ];\n\tint dCheck;\t\t\t\t\t\t/* Data checksum for quick match */\n\n\t/* Validity information */\n\tBOOLEAN isValid;\t\t\t\t/* Valid/not valid */\n\tCRYPT_CERTSTATUS_TYPE extStatus;/* Extended validity status */\n\ttime_t invalidityTime;\t\t\t/* Certificate invalidity time */\n\n\t/* Per-entry attributes.  These are a rather ugly special case for the\n\t   user because unlike the attributes for all other certificate objects \n\t   where cryptlib can provide the illusion of a flat type<->value \n\t   mapping there can be multiple sets of identical per-entry attributes \n\t   present if there are multiple RTCS entries present */\n\tDATAPTR_ATTRIBUTE attributes;\t/* RTCS entry attributes */\n\tint attributeSize;\t\t\t\t/* Encoded size of attributes */\n\n\t/* The previous and next elements in the list */\n\tDATAPTR prev, next;\n\t} VALIDITY_INFO;\n\ntypedef struct {\n\t/* A list of RTCS request or response entries and a pointer to the\n\t   request/response which is currently being accessed */\n\tDATAPTR validityInfo;\t\t\t/* List of validity info */\n\tDATAPTR currentValidity;\t\t/* Currently selected validity info */\n\n\t/* The URL for the RTCS responder */\n\tBUFFER_OPT_FIXED( responderUrlSize ) \\\n\tchar *responderUrl;\t\t\t\t/* RTCS responder URL */\n\tint responderUrlSize;\n\n\t/* Since RTCS allows for a variety of response types, we include an\n\t   indication of the request/response format */\n\tRTCSRESPONSE_TYPE responseType;\t/* Request/response format */\n\t} CERT_VAL_INFO;\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\n/* The structure to hold a revocation information entry, either a CRL entry\n   or OCSP request/response information */\n\ntypedef struct RI {\n\t/* Certificate ID information, either a serial number (for CRLs) or a\n\t   certificate hash or issuerID (for OCSP requests/responses).  In \n\t   addition this could also be a pre-encoded OCSP certID, which is \n\t   treated as an opaque blob of type CRYPT_ATTRIBUTE_NONE since it can't \n\t   be used in any useful way.  If we're using OCSP and an alternative ID \n\t   is supplied as an ESSCertID we point to this value (inside the \n\t   ESSCertID) in the altIdPtr field */\n\tCRYPT_KEYID_TYPE idType;\t\t/* ID type */\n\tBUFFER_OPT_FIXED( idLength ) \\\n\tBYTE *id;\t\t\t\t\t\t/* ID information stored in varstruct */\n\tint idLength;\n\tint idCheck;\t\t\t\t\t/* Data checksum for quick match */\n\tCRYPT_KEYID_TYPE altIdType;\t\t/* Alt.ID type for OCSP */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE altID[ KEYID_SIZE + 8 ];\t/* Alt.ID for OCSP */\n\n\t/* Revocation information */\n\tint status;\t\t\t\t\t\t/* OCSP revocation status */\n\ttime_t revocationTime;\t\t\t/* Certificate revocation time */\n\n\t/* Per-entry attributes.  These are a rather ugly special case for the\n\t   user because unlike the attributes for all other certificate objects \n\t   where cryptlib can provide the illusion of a flat type<->value \n\t   mapping there can be multiple sets of identical per-entry attributes \n\t   present if there are multiple CRL/OCSP entries present */\n\tDATAPTR_ATTRIBUTE attributes;\t/* CRL/OCSP entry attributes */\n\tint attributeSize;\t\t\t\t/* Encoded size of attributes */\n\n\t/* The previous and next elements in the list */\n\tDATAPTR prev, next;\n\n\t/* Variable-length storage for the ID information */\n\tDECLARE_VARSTRUCT_VARS;\n\t} REVOCATION_INFO;\n\ntypedef struct {\n\t/* The list of revocations for a CRL or a list of OCSP request or response\n\t   entries, and a pointer to the revocation/request/response which is\n\t   currently being accessed */\n\tDATAPTR_ATTRIBUTE revocations;\t/* List of revocations */\n\tDATAPTR_ATTRIBUTE currentRevocation; /* Currently selected revocation */\n\n\t/* The default revocation time for a CRL, used for if no explicit time\n\t   is set for a revocation */\n\ttime_t revocationTime;\t\t\t/* Default certificate revocation time */\n\n\t/* The URL for the OCSP responder */\n\tBUFFER_OPT_FIXED( responderUrlSize ) \\\n\tchar *responderUrl;\n\tint responderUrlSize;\t\t\t/* OCSP responder URL */\n\n\t/* The hash algorithm used to sign the certificate, see the comment for\n\t   CERT_CERT_INFO for why we record this */\n\tCRYPT_ALGO_TYPE hashAlgo;\n\n\t/* Signed OCSP requests can include varying levels of detail in the\n\t   signature.  The following value determines how much information is\n\t   included in the signature */\n\tCRYPT_SIGNATURELEVEL_TYPE signatureLevel;\n\t} CERT_REV_INFO;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTREQ\n\ntypedef struct {\n\t/* The certificate serial number, used when requesting a revocation by \n\t   issuerAndSerialNumber.  This is stored in the buffer if it fits (it\n\t   almost always does), otherwise in a dynamically-allocated buffer */\n\tBUFFER( SERIALNO_BUFSIZE, serialNumberLength ) \\\n\tBYTE serialNumberBuffer[ SERIALNO_BUFSIZE + 8 ];\n\tBUFFER_OPT_FIXED( serialNumberLength ) \\\n\tvoid *serialNumber;\n\tint serialNumberLength;\t\t\t/* Certificate serial number */\n\n\t/* The certificate ID of the PKI user or certificate that authorised \n\t   this request, and whether this request is coming directly from the \n\t   user (so the PKIUser corresponds to the issuer of the request) or\n\t   via an RA (so the PKIUser is the RA that passed on the request from \n\t   the user).  This is from an external source, supplied when the \n\t   request is used as part of the CMP protocol */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE authCertID[ KEYID_SIZE + 8 ];\n\tBOOLEAN requestFromRA;\n\t} CERT_REQ_INFO;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_PKIUSER\n\ntypedef struct {\n\t/* The authenticator used for authenticating certificate issue and\n\t   revocation requests */\n\tBUFFER_FIXED( 16 ) \\\n\tBYTE pkiIssuePW[ 16 + 8 ];\n\tBUFFER_FIXED( 16 ) \\\n\tBYTE pkiRevPW[ 16 + 8 ];\n\n\t/* Additional PKI user inforation: Whether this PKI user can act as an\n\t   RA */\n\tBOOLEAN isRA;\n\t} CERT_PKIUSER_INFO;\n#endif /* USE_PKIUSER */\n\n/* The internal fields in a certificate that hold subtype-specific data for \n   the various certificate object types */\n\ntypedef struct {\n\t/* The certificate serial number.  This is stored in the buffer if it \n\t   fits (it almost always does), otherwise in a dynamically-allocated \n\t   buffer */\n\tBUFFER( SERIALNO_BUFSIZE, serialNumberLength ) \\\n\tBYTE serialNumberBuffer[ SERIALNO_BUFSIZE + 8 ];\n\tBUFFER_OPT_FIXED( serialNumberLength ) \\\n\tvoid *serialNumber;\n\tint serialNumberLength;\t\t\t/* Certificate serial number */\n\n\t/* The highest compliance level at which a certificate has been checked.\n\t   We have to record this high water-mark level because increasing the\n\t   compliance level may invalidate an earlier check performed at a lower\n\t   level */\n\tCRYPT_COMPLIANCELEVEL_TYPE maxCheckLevel;\n\n\t/* The allowed usage for a certificate can be further controlled by the\n\t   user.  The trustedUsage value is a mask which is applied to the key\n\t   usage extension to further constrain usage, alongside this there is\n\t   an additional implicit trustImplicit value that acts as a boolean \n\t   flag and indicates whether the user implicitly trusts this \n\t   certificate (without requiring further checking upstream).  This \n\t   value isn't stored with the certificate since it's a property of any \n\t   instantiation of the certificate rather than just the current one so \n\t   when the user queries it it's obtained dynamically from the trust \n\t   manager */\n\tint trustedUsage;\n\n\t/* Certificate chains are a special variant of standard certificates, \n\t   being complex container objects that contain further certificates \n\t   leading up to a CA root certificate.  The reason why they're combined \n\t   with standard certificates is because when we're building a chain \n\t   from a certificate collection or assembling it from a certificate \n\t   source we can't tell at the time of certificate creation which \n\t   certificate will be the leaf certificate so that any certificate \n\t   potentially has to be able to act as the chain container (another way \n\t   of looking at this is that all standard certificates are a special \n\t   case of a chain with a length of one).\n\n\t   A possible alternative to this way of handling chains is to make the\n\t   chain object a pure container object used only to hold pointers to\n\t   the actual certificates, but this requires an extra level of \n\t   indirection every time that a certificate chain object is used since \n\t   in virtually all cases what'll be used is the leaf certificate with \n\t   which the chain-as-standard-certificate model is the default \n\t   certificate but with the chain-as-container model requires an extra \n\t   object dereference to obtain.\n\n\t   In theory we should use a linked list to store chains but since the\n\t   longest chain ever seen in the wild has a length of 4 using a fixed\n\t   maximum length several times this size shouldn't be a problem.  The\n\t   certificates in the chain are ordered from the parent of the leaf \n\t   certificate up to the root certificate with the leaf certificate \n\t   corresponding to the [-1]th entry in the list.  We also maintain a \n\t   current position in the certificate chain that denotes the \n\t   certificate in the chain that will be accessed by the \n\t   component-manipulation functions.  This is set to CRYPT_ERROR if the \n\t   current certificate is the leaf certificate */\n\tARRAY( MAX_CHAINLENGTH, chainEnd ) \\\n\tCRYPT_CERTIFICATE chain[ MAX_CHAINLENGTH + 8 ];\n\tint chainEnd;\t\t\t\t\t/* Length of certificate chain */\n\tint chainPos;\t\t\t\t\t/* Currently selected certificate in chain */\n\n\t/* The hash algorithm used to sign the certificate.  Although it's a \n\t   part of the signature, a second copy of the algorithm ID is embedded \n\t   inside the signed certificate data to avert a somewhat obscure attack\n\t   where it's possible to substitute the hash algorithm specified for \n\t   the signature with a broken one.  This isn't possible in practice \n\t   because of the way that the signature data is encoded in PKCS #1 sigs \n\t   (although it's still possible for some of the ISO signature types) or \n\t   because the (EC)DSA sigs have a different size for each hash \n\t   algorithm (SHA-1, SHA-256, SHA-384, SHA-512) so technically there's \n\t   no need to record it, however we record it because CMP uses the hash \n\t   algorithm in the certificate as an implicit indicator of the hash \n\t   algorithm that it uses for CMP messages (!!) and also just because \n\t   it's good practice to do so in case some future hash algorithm of\n\t   the same size as an existing (EC)DSA one but that's breakable turns\n\t   up */\n\tCRYPT_ALGO_TYPE hashAlgo;\n\n#ifdef USE_CERT_OBSOLETE \n\t/* The (deprecated) X.509v2 unique ID */\n\tBUFFER_OPT_FIXED( issuerUniqueIDlength ) \\\n\tvoid *issuerUniqueID;\n\tBUFFER_OPT_FIXED( subjectUniqueIDlength ) \\\n\tvoid *subjectUniqueID;\n\tint issuerUniqueIDlength, subjectUniqueIDlength;\n#endif /* USE_CERT_OBSOLETE */\n\t} CERT_CERT_INFO;\n\n/* Defines to make access to the union fields less messy */\n\n#define cCertCert\t\tcertInfo.certInfo\n#define cCertReq\t\tcertInfo.reqInfo\n#define cCertRev\t\tcertInfo.revInfo\n#define cCertVal\t\tcertInfo.valInfo\n#define cCertUser\t\tcertInfo.pkiUserInfo\n\n/* The structure that stores information on a certificate object */\n\ntypedef struct {\n\t/* General certificate information */\n\tCRYPT_CERTTYPE_TYPE type;\t\t/* Certificate type */\n\tSAFE_FLAGS flags;\t\t\t\t/* Certificate flags */\n\tint version;\t\t\t\t\t/* Certificate format version */\n\n\t/* Certificate type-specific information */\n\tunion {\n\t\tCERT_CERT_INFO *certInfo;\n#ifdef USE_CERTREQ\n\t\tCERT_REQ_INFO *reqInfo;\n#endif /* USE_CERTREQ */\n#ifdef USE_CERTREV\n\t\tCERT_REV_INFO *revInfo;\n#endif /* USE_CERTREV */\n#ifdef USE_CERTVAL\n\t\tCERT_VAL_INFO *valInfo;\n#endif /* USE_CERTVAL */\n#ifdef USE_PKIUSER\n\t\tCERT_PKIUSER_INFO *pkiUserInfo;\n#endif /* USE_PKIUSER */\n\t\t} certInfo;\n\n\t/* The encoded certificate object.  We save this when we import it\n\t   because there are many different interpretations of how a certificate \n\t   should be encoded and if we parse and then try to re-encode the \n\t   object the signature check would most likely fail */\n\tBUFFER_OPT_FIXED( certificateSize ) \\\n\tvoid *certificate;\n\tint certificateSize;\n\n\t/* The public key associated with the certificate.  When the \n\t   certificate is in the low (unsigned state) this consists of the \n\t   encoded public-key data and associated attributes.  When the \n\t   certificate is in the high (signed) state, either by being imported \n\t   from an external source or by being signed by cryptlib, this consists \n\t   of a public-key context.  In addition some certificates are imported \n\t   as data-only certificates, denoted by CERT_FLAG_DATAONLY being set.  \n\t   These constitute a container object that contain no public-key context \n\t   and are used for certificate chains (when read from a trusted source) \n\t   and to store certificate information associated with a private-key \n\t   context.  Since it's not known during the import stage whether a \n\t   certificate in a chain will be a data-only or standard certificate \n\t   (it's not known which certificate is the leaf certificate until the \n\t   entire chain has been processed) certificate chains from a trusted \n\t   source are imported as data-only certificates and then the leaf has \n\t   its context instantiated */\n\tCRYPT_CONTEXT iPubkeyContext;\t/* Public-key context */\n\tCRYPT_ALGO_TYPE publicKeyAlgo;\t/* Key algorithm */\n\tint publicKeyFeatures;\t\t\t/* Key features flags */\n\tBUFFER_OPT_FIXED( publicKeyInfoSize ) \\\n\tvoid *publicKeyInfo;\t\t\t/* Encoded key information */\n\tint publicKeyInfoSize;\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE publicKeyID[ KEYID_SIZE + 8 ];\t/* Key ID */\n\n\t/* General certificate object information */\n\tDATAPTR_DN issuerName, subjectName;/* Issuer and subject name */\n\ttime_t startTime;\t\t\t\t/* Validity start or update time */\n\ttime_t endTime;\t\t\t\t\t/* Validity end or next update time */\n\n\t/* In theory we can just copy the subject DN of a CA certificate into \n\t   the issuer DN of a subject certificate, however due to broken \n\t   implementations this will break chaining if we correct any problems \n\t   in the DN.  Because of this we need to preserve a copy of the \n\t   certificate's subject DN so that we can write it as a blob to the \n\t   issuer DN field of any certificates that it signs.  We also need to \n\t   remember the encoded issuer DN so that we can chain upwards.  The \n\t   following fields identify the size and location of the encoded DNs \n\t   inside the encoded certificate object */\n\tBUFFER_OPT_FIXED( subjectDNsize ) \\\n\tvoid *subjectDNptr;\n\tBUFFER_OPT_FIXED( issuerDNsize ) \\\n\tvoid *issuerDNptr;\t\t\t\t\t/* Pointer to encoded DN blobs */\n\tint subjectDNsize, issuerDNsize;\t/* Size of encoded DN blobs */\n\n\t/* For some objects the public key and/or subject DN and/or issuer DN are\n\t   copied in from an external source before the object is signed so we\n\t   can't just point the relevant pointers at the appropriate location in\n\t   the encoded object, we have to allocate a separate data area to copy \n\t   the data into.  This is used in cases where we don't copy in a full \n\t   public-key context or subject/issuerName but only use an encoded key \n\t   data/DN blob for the reasons described above */\n\tBUFFER_OPT_FIXED( publicKeyInfoSize ) \\\n\tvoid *publicKeyData;\n\tBUFFER_OPT_FIXED( subjectDNsize ) \\\n\tvoid *subjectDNdata;\n\tBUFFER_OPT_FIXED( issuerDNsize ) \\\n\tvoid *issuerDNdata;\n\n\t/* The certificate hash/fingerprint/oobCertID/thumbprint/whatever.  This\n\t   is used so frequently that it's cached here for future re-use */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE certHash[ KEYID_SIZE + 8 ];/* Cached certificate hash */\n\tBOOLEAN certHashSet;\t\t\t/* Whether hash has been set */\n\n\t/* Certificate object attributes and a cursor into the attribute list.\n\t   This can be moved by the user on a per-attribute, per-field, and per-\n\t   component basis */\n\tDATAPTR_ATTRIBUTE attributes, attributeCursor;\n\n\t/* The currently selected GeneralName and DN.  A certificate can contain \n\t   multiple GeneralNames and DNs that can be selected by their field \n\t   types after which adding DN components will affected the currently \n\t   selected DN.  This value contains the details of the currently \n\t   selected GeneralName and DN */\n\tSELECTION_INFO currentSelection;\n\n\t/* Save area for the currently selected GeneralName and DN, and position\n\t   in the certificate chain.  The current values are saved to this area \n\t   when the object receives a lock object message and restored when the \n\t   object receives the corresponding unlock message.  This guarantees \n\t   that any changes made during processing while the certificate is \n\t   locked don't get reflected back to external users */\n\tSELECTION_STATE selectionState;\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the\n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\n\t/* Variable-length storage for the type-specific data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} CERT_INFO;\n\n/* Certificate read/write methods for the different format types.  \n   Specifying input ranges for the process gets a bit complicated because \n   the functions are polymorphic so we have to use the lowest common \n   denominator of all of the functions */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *READCERT_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *WRITECERT_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iIssuerCryptContext );\n\nCHECK_RETVAL_PTR \\\nREADCERT_FUNCTION getCertReadFunction( IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\nCHECK_RETVAL_PTR \\\nWRITECERT_FUNCTION getCertWriteFunction( IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Selection Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine whether an attribute represents a valid extension.  The check\n   covers two possible ranges, certificate extensions and CMS attributes */\n\n#define isValidExtension( attributeID ) \\\n\t\t( ( ( attributeID ) >= CRYPT_CERTINFO_FIRST_EXTENSION && \\\n\t\t\t( attributeID ) <= CRYPT_CERTINFO_LAST_EXTENSION ) || \\\n\t\t  ( ( attributeID ) >= CRYPT_CERTINFO_FIRST_CMS && \\\n\t\t\t( attributeID ) <= CRYPT_CERTINFO_LAST_CMS ) ) \n\n/* Determine whether a component which is being added to a certificate is a \n   special-case DN selection component that selects the current DN without \n   changing the certificate itself or a GeneralName selection component.  \n   The latter is sufficiently complex (GeneralNames are used almost \n   everywhere in certificates where a basic text string would do) that we\n   break it out into a custom function */\n\n#define isDNSelectionComponent( certInfoType ) \\\n\t( ( certInfoType ) == CRYPT_CERTINFO_ISSUERNAME || \\\n\t  ( certInfoType ) == CRYPT_CERTINFO_SUBJECTNAME || \\\n\t  ( certInfoType ) == CRYPT_CERTINFO_DIRECTORYNAME )\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isGeneralNameSelectionComponent( IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType );\n\n/* Determine whether a component which is being added is a DN or GeneralName\n   component */\n\n#define isDNComponent( certInfoType ) \\\n\t( ( certInfoType ) >= CRYPT_CERTINFO_FIRST_DN && \\\n\t  ( certInfoType ) <= CRYPT_CERTINFO_LAST_DN )\n\n#define isGeneralNameComponent( certInfoType ) \\\n\t( ( certInfoType ) >= CRYPT_CERTINFO_FIRST_GENERALNAME && \\\n\t  ( certInfoType ) <= CRYPT_CERTINFO_LAST_GENERALNAME )\n\n/* Determine whether a component which is being added is pseudo-information\n   that corresponds to certificate control information rather than a normal\n   certificate attribute */\n\n#define isPseudoInformation( certInfoType ) \\\n\t( ( certInfoType ) >= CRYPT_CERTINFO_FIRST_PSEUDOINFO && \\\n\t  ( certInfoType ) <= CRYPT_CERTINFO_LAST_PSEUDOINFO )\n\n/* Determine whether a component which is being added to a validity/\n   revocation check request/response is a standard attribute or a per-entry\n   attribute */\n\n#define isRevocationEntryComponent( certInfoType ) \\\n\t( ( certInfoType ) == CRYPT_CERTINFO_CRLREASON || \\\n\t  ( certInfoType ) == CRYPT_CERTINFO_HOLDINSTRUCTIONCODE || \\\n\t  ( certInfoType ) == CRYPT_CERTINFO_INVALIDITYDATE )\n\n/* Check whether an entry in an attribute list is valid.  This checks \n   whether the entry has a non-zero attribute ID, denoting a non blob-type \n   attribute */\n\n#define isValidAttributeField( attributePtr ) \\\n\t\t( ( attributePtr )->attributeID > 0 )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Functions \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The huge complexity of the certificate management code means that there\n   are a sufficient number of functions required that we confine the\n   prototypes to their own file */\n\n#if defined( INC_ALL )\n  #include \"certfn.h\"\n#else\n  #include \"cert/certfn.h\"\n#endif /* Compiler-specific includes */\n\n#endif /* _CERT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/certattr.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Attribute Routines Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CERTATTR_DEFINED\n\n#define _CERTATTR_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tType Information Flags\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The attribute type information.  This is used to both check the validity\n   of encoded attribute data and to describe the structure of an attribute\n   when encoding it.\n   \n   The flags are broken down into the following groups:\n\n\tAttribute-specific flags that apply to an individual field or an\n\toverall attribute.\n\n\tSET/SEQUENCE control flags that indicate the end of a SET/SEQUENCE or\n\tnested SET/SEQUENCE.  These are only used for encoding, for decoding the \n\tdecoder maintains a parse state stack driven by the encoded data \n\t(actually that's not quite correct, when skipping to the end of some \n\tSEQUENCEs containing type-and-value pairs we also use the flags to locate \n\tthe end of the SEQUENCE encoding/start of the next type-and-value entry).  \n\tThe use of SEQEND gets extremely complicated in the presence of optional\n\tnested SEQUENCEs because it's not certain how many levels we need to \n\tundo.  Consider for example name constraints:\n\n\t\tSEQUENCE {\n\t\t\tpermittedSubtrees\t[ 0 ] SEQUENCE OF {\n\t\t\t\tSEQUENCE { GeneralName }\n\t\t\t\t} OPTIONAL,\n\t\t\texcludedSubtrees\t[ 1 ] SEQUENCE OF {\n\t\t\t\tSEQUENCE { GeneralName }\n\t\t\t\t} OPTIONAL,\n\t\t\t}\n\n\tIs the value at the end FL_SEQEND or FL_SEQEND_3?  If excludedSubtrees \n\tare absent then it's FL_SEQEND but if we're encoding the excluded \n\tsubtree then it's FL_SEQEND_3.  Because of this ambiguity the current \n\tencoding routines simply assume that once they reach the end of an \n\textension there's an implicit FL_SEQEND_whatever there.  Luckily all of \n\tthe ambiguous decoding-level points occur at the end of extensions so \n\tthis is a workable way to handle things.\n\n\tDecoding level flags that indicate the compliance level at which this\n\tattribute is decoded.\n\n\tThe object subtypes for which an attribute is valid.  CRLs actually \n\tcontain two sets of extensions, one for the entire CRL (crlExtensions) \n\tand the other for each entry in the CRL (crlEntryExtension).  Sorting \n\tout whether we're adding a CRL extension or per-entry extension is \n\thandled by the higher-level code which references the CRL attribute list \n\tor per-entry attribute list as appropriate.\n\n   The total-attribute flags are:\n\n\tFL_ATTR_ATTRSTART/FL_ATTR_ATTREND: Marks the start and end of an \n\t\tattribute.  This has to be done explicitly because there's no other \n\t\tfield or flag that we can guarantee will always be set for the first \n\t\tor last field in an attribute and never for any other field.\n\n\tFL_ATTR_NOCOPY: The attribute is regarded as sensitive and therefore \n\t\tshouldn't be copied from source to destination (e.g. from a \n\t\tcertificate request into a certificate) when the other attributes \n\t\tare copied.\n    \n\tFL_ATTR_CRITICAL: The overall extension is marked critical when encoding.\n\n   The encoding flags are:\n\n\tFL_DEFAULT: The field has a default value that's set if no field data\n\t\tis present.\n\n\tFL_EXPLICIT: The field is explicitly tagged so instead of being en/\n\t\tdecoded using the tag for the field it's given a second level of \n\t\ttagging that encapsulates the field's actual tag type.\n\n\tFL_IDENTIFIER: Used to mark the encapsulating SEQUENCE in fields of the \n\t\ttype:\n\n\t\tSEQUENCE {\n\t\t\tidentifier\tOBJECT IDENTIFIER\n\t\t\tdata\t\tANY DEFINED BY identifier\n\t\t\t}\n\n\t\tfor which the field identified by a CRYPT_CERTINFO_xxx is the 'data'\n\t\tfield and the whole is only encoded if the data field is present.\n\n\tFL_MULTIVALUED: If a cryptlib-level attribute is part of a SET OF x/\n\t\tSEQUENCE OF x then this flag is set to indicate that more than one \n\t\tinstance can exist at the same time.  If this flag isn't set then \n\t\tcryptlib will detect that an attribute of that type already exists \n\t\tand refuse to allow a second instance to be added.\n\n\tFL_EMPTYOK: Used for a SET/SEQUENCE consisting of nothing but OPTIONAL\n\t\telements to indicate that it's OK to end up with a zero-length \n\t\tentry, by default we don't allow an empty SET/SEQUENCE since if the \n\t\tdata didn't match any of the optional elements then the decoder \n\t\twould get stuck in an endless loop.  At the moment this is OK \n\t\tbecause the only time we can have an empty SEQUENCE is for the \n\t\tbasicConstraints extension, which is an entire extension for which\n\t\tthe termination point is easily detected.\n\n\tFL_NONENCODING: The field is read and written but not associated with \n\t\tany user data.  This is used for fields such as version numbers that \n\t\taren't used for encoding user-supplied data but that must be read and \n\t\twritten when processing an attribute \n\n\tFL_OPTIONAL: The field is optional.\n\n\tFL_SETOF: Applied to the encapsulating SET/SEQUENCE of a SET OF x/\n\t\tSEQUENCE OF x to indicate that one or more inner fields may be \n\t\tpresent.  The field marked with FL_SETOF in the encoding/decoding\n\t\ttable is bookmarked, if all of the SET/SEQUENCE data isn't read the \n\t\tfirst time through then the decoding table position is restarted \n\t\tfrom the bookmark until the SET/SEQUENCE data is exhausted.\n\n\tFL_SPECIALENCODING: The attribute isn't encoded as part of the standard\n\t\tattributes but requires special-case encoding.  This exists for use\n\t\twith certificate requests to indicate that the attribute isn't \n\t\tencoded encapsulated inside an extensionRequest but as a standalone\n\t\tattribute, because certificate request attributes are usually \n\t\tencapsulated inside an extensionRequest wrapper, however occasionally \n\t\tan attribute needs to be encoded in non-encapsulated form.  \n\t\t\n\t\tIn addition this is just as much an attribute flag as an encoding \n\t\tone since it controls the encoding of an entire attribute, we group \n\t\tit with the encoding flags mostly because there's no room for \n\t\texpansion any more in the attribute flags */\n\n/* Type information and whole-attribute flags */\n\n#define FL_VALID_CERT\t\t0x0001\t\t/* Valid in a certificate */\n#define FL_VALID_ATTRCERT\t0x0002\t\t/* Valid in an attribute cert */\n#define FL_VALID_CRL\t\t0x0004\t\t/* Valid in a CRL */\n#define FL_VALID_CERTREQ\t0x0008\t\t/* Valid in a cert.request */\n#define FL_VALID_REVREQ\t\t0x0010\t\t/* Valid in a rev.request */\n#define FL_VALID_OCSPREQ\t0x0010\t\t/* Valid in an OCSP request */\n#define FL_VALID_OCSPRESP\t0x0010\t\t/* Valid in an OCSP response */\n\n#define FL_LEVEL_OBLIVIOUS\t0x0000\t\t/* Process at oblivious compliance level */\n#define FL_LEVEL_REDUCED\t0x0100\t\t/* Process at reduced compliance level */\n#define FL_LEVEL_STANDARD\t0x0200\t\t/* Process at standard compliance level */\n#define FL_LEVEL_PKIX_PARTIAL 0x0300\t/* Process at partial PKIX compliance level */\n#define FL_LEVEL_PKIX_FULL\t0x0400\t\t/* Process at full PKIX compliance level */\n\n#define FL_ATTR_NOCOPY\t\t0x1000\t\t/* Attr.isn't copied when attrs.copied */\n#define FL_ATTR_CRITICAL\t0x2000\t\t/* Extension is marked critical */\n#define FL_ATTR_ATTRSTART\t0x4000\t\t/* Start-of-attribute marker */\n#define FL_ATTR_ATTREND\t\t0x8000\t\t/* End-of-attribute marker */\n\n#define FL_VALID_MASK\t\t0x1F\t\t/* Mask for type-validity value */\n#define FL_LEVEL_SHIFT\t\t8\t\t\t/* Shift amount to get into range 0...n */\n#define FL_LEVEL_MASK\t\t7\t\t\t/* Mask for compliance level value */\n\n/* Encoding flags */\n\n#define FL_SEQEND\t\t\t0x0001\t\t/* End of constructed object */\n#define FL_SEQEND_2\t\t\t0x0002\t\t/*  End of cons.obj + one nesting lvl.*/\n#define FL_SEQEND_3\t\t\t0x0003\t\t/*  End of cons.obj + two nesting lvls.*/\n#define FL_SEQEND_4\t\t\t0x0004\t\t/*  End of cons.obj + three nesting lvls.*/\n#define FL_SEQEND_5\t\t\t0x0005\t\t/*  End of cons.obj + four nesting lvls.*/\n#define FL_SEQEND_6\t\t\t0x0006\t\t/*  End of cons.obj + four nesting lvls.*/\n#define FL_SEQEND_7\t\t\t0x0007\t\t/*  End of cons.obj + four nesting lvls.*/\n\n#define FL_SEQEND_MASK\t\t7\t\t\t/* Mask for sequence control value */\n\n#define FL_OPTIONAL\t\t\t0x0010\t\t/* Field is optional */\n#define FL_DEFAULT\t\t\t0x0020\t\t/* Field has default value */\n#define FL_EXPLICIT\t\t\t0x0040\t\t/* Field is explicitly tagged */\n#define FL_IDENTIFIER\t\t0x0080\t\t/* Following field contains selection OID */\n#define FL_SETOF\t\t\t0x0100\t\t/* Start of SET/SEQ OF values */\n#define FL_EMPTYOK\t\t\t0x0200\t\t/* SET/SEQ may be empty */\n#define FL_NONENCODING\t\t0x0400\t\t/* Field is a non-encoding value */\n#define FL_MULTIVALUED\t\t0x0800\t\t/* Field can occur multiple times */\n#define FL_SPECIALENCODING\t0x1000\t\t/* Attribute requires special-case encoding */\n\n/* If a constructed field is nested (for example a SEQUENCE OF SEQUENCE) \n   then the FL_SEQEND may need to denote multiple levels of unnesting.  This \n   is done by using FL_SEQEND_n, the following macro can be used to extract \n   the actual level of nesting */\n\n#define decodeNestingLevel( value )\t\t( ( value ) & FL_SEQEND_MASK )\n\n/* In order to be able to process broken certificates we allow for \n   processing them at various levels of standards compliance.  If the \n   current processing level is below that required for the extension then \n   we skip it and treat it as a blob extension */\n\n#define decodeComplianceLevel( value ) \\\n\t\t( ( ( value ) >> FL_LEVEL_SHIFT ) & FL_LEVEL_MASK )\n\n/* Usually the field ID for the first field in an entry (the one containing\n   the OID) is the overall attribute ID, however there are one or two\n   exceptions in which the attribute ID and field ID are the same but are\n   given in separate fields (examples of this are the altNames, which have\n   a single field ID SUBJECT/ISSUERALTNAME that applies to the attribute as\n   a whole but also to the one and only field in it.\n\n   If this happens the field ID for the attribute as a whole is given the \n   value FIELDTYPE_ID_FOLLOWS to indicate that the actual ID is present at a \n   later point, with the first field that isn't a FIELDTYPE_ID_FOLLOWS code \n   being treated as the attribute ID */\n\n#define FIELDID_FOLLOWS\t\t\t\t\tCRYPT_XATTRIBUTE_PRIVATE\n\n/* Determine whether an attribute information entry represents the start of \n   the attribute */\n\n#define isAttributeStart( attributeInfoPtr ) \\\n\t\t( ( attributeInfoPtr )->typeInfoFlags & FL_ATTR_ATTRSTART )\n\n/* Determine whether an attribute information entry represents the end of\n   the attribute information table */\n\n#define isAttributeTableEnd( attributeInfoPtr ) \\\n\t\t( ( attributeInfoPtr )->oid == NULL && \\\n\t\t  ( attributeInfoPtr )->fieldID == CRYPT_IATTRIBUTE_LAST )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSpecial-case Field-encoding Values\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some fields have an intrinsic value but no explicitly set value (that is,\n   their mere presence communicates the information they are intended to \n   convey but the fields themselves contain no actual data).  This applies \n   for fields that contain OIDs that denote certain things such as \n   certificate policies or key usage.  To denote these identifier fields \n   the field type is set to FIELDTYPE_IDENTIFIER (note that we start the\n   values at -2 rather than -1, which is the CRYPT_ERROR value).  When a \n   field of this type is encountered no data value is recorded but the OID \n   for the field is written to the certificate when the field is encoded.\n   The parentheses are to catch potential erroneous use in an expression */\n\n#define FIELDTYPE_IDENTIFIER\t-2\n\n/* Some fields have no set value (these arise from ANY DEFINED BY\n   definitions) or an opaque value (typically fixed parameters for type-and-\n   value pairs).  To denote these fields the field type is set to\n   FIELDTYPE_BLOB.  However this causes problems with type-checking since\n   now absolutely anything can be passed in as valid data.  To allow at\n   least some type-checking we provide a hint as to the general encoding of \n   the blob, which can be one of SEQUENCE, BIT STRING, or a genuine blob \n   used in ANY DEFINED BY constructions, for which we can at least check \n   that it's some sort of ASN.1 object.  There are also two cases in which\n   an ANY blob is used where it'd be possible to use more specific blobs\n   for OBJECT IDENTIFIERs and GeneralNames and that's in { OID, value }\n   selection lists in which the ANY blob acts spefically as an end-of-\n   list marker as well as being just a catchall type */\n\n#define FIELDTYPE_BLOB_ANY\t\t-3\n#define FIELDTYPE_BLOB_BITSTRING -4\n#define FIELDTYPE_BLOB_SEQUENCE\t-5\n\n/* When a field contains a CHOICE it can contain any one of the CHOICE \n   fields, as opposed to a FL_SETOF which can contain any of the fields that\n   follow it.  Currently the only CHOICE fields contain OIDs as choices, the\n   CHOICE fieldtype indicates that the value is stored in the field itself\n   but the encoding is handled via a separate encoding table pointed to by\n   extraData that maps the value to an OID */\n\n#define FIELDTYPE_CHOICE\t\t-6\n\n/* Some fields are composite fields that contain complete certificate data\n   structures.  To denote these fields the field type is a special code that \n   specifies the type and the value member contains the handle or the data \n   member contains a pointer to the composite object */\n\n#define FIELDTYPE_DN\t\t\t-7\n\n/* As an extension of the above, some fields are complex enough to require\n   complete alternative encoding tables.  The most obvious one is\n   GeneralName but this is also used for some CHOICE types where the value\n   selects a particular OID or entry from an alternative encoding table.  In\n   this case the extraData member is a pointer to the alternative encoding\n   table */\n\n#define FIELDTYPE_SUBTYPED\t\t-8\n\n/* Another variant of FIELDTYPE_DN is one where the field can contain one of\n   a number of string types chosen from the ASN.1 string menagerie.  The two\n   main classes that seem to be popular in standards are the DirectoryString,\n   { BMPString | PrintableString | TeletexString | UniversalString | \n     UTF8String } and DisplayText, { BMPString | IA5String | UTF8String |\n\t VisibleString }.  Rather than adding a list of the different string \n   types all marked as optional to the en/decoding tables (so that the \n   decoder stops whenever it reaches the one that matches the string value \n   being decoded) we provide a single TextString meta-type which has a \n   custom decoding routine that makes the appropriate choice between the \n   union of all of the above types */\n\n#define FIELDTYPE_TEXTSTRING\t-9\n\n/* The last possible field type */\n\n#define FIELDTYPE_LAST\t\t\tFIELDTYPE_TEXTSTRING\n\n/* Since there are multiple blob fields (due to the use of typing hints) we\n   need a macro to determine whether a field is a blob of any form.  The \n   odd-looking range comparison below is because the fields have negative\n   values */\n\n#define isBlobField( field ) \\\n\t\t( ( field ) <= FIELDTYPE_BLOB_ANY && \\\n\t\t  ( field ) >= FIELDTYPE_BLOB_SEQUENCE )\n\n/* A similar check for string fields.  This isn't used for encoding/decoding\n   but merely for sanity checks for attribute data types, so we simplify the \n   comparison a bit by including BER_TIME_UTC and BER_TIME_GENERALIZED, which\n   lie inside the string types.  This is OK since all that we're checking for\n   is a type stored as a { value, valueLength } pair, and time values are \n   stored in this form */\n\n#define isStringField( field ) \\\n\t\t( ( field ) == BER_STRING_UTF8 || \\\n\t\t  ( field ) == BER_STRING_BMP || \\\n\t\t  ( ( field ) >= BER_STRING_NUMERIC && \\\n\t\t    ( field ) <= BER_STRING_UNIVERSAL ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Data Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The structure to store en/decoding information for an attribute field */\n\ntypedef struct {\n\t/* Information on the overall attribute.  These fields are only set\n\t   for overall attribute definitions */\n\tconst BYTE *oid;\t\t\t\t/* OID for this attribute */\n\n\t/* Information on this particular field in the attribute.  The fieldID \n\t   is the attribute type for this field or one of the FIELDTYPE_xxx\n\t   codes defined above, the fieldType is the field as defined (e.g. \n\t   SEQUENCE, INTEGER), the fieldEncodingType is the field as encoded: 0 \n\t   if it's the same as the field type or the tag if it's a tagged field.  \n\t   The default tagging is to use implicit tags (e.g. [ 0 ] IMPLICIT \n\t   SEQUENCE) with a field of type fieldType and encoding of type \n\t   fieldEncodedType.  If FL_EXPLICIT is set then it's an explicitly \n\t   tagged field and both fields are used for the encoding */\n\tconst CRYPT_ATTRIBUTE_TYPE fieldID;\t/* Magic ID for this field */\n#ifndef NDEBUG\n\tconst char *description;\t\t/* Text description */\n#endif /* NDEBUG */\n\tconst int fieldType;\t\t\t/* ASN.1 tag/type for this field */\n\tconst int fieldEncodedType;\t\t/* ASN.1 tag for field as encoded */\n\n\t/* General status information */\n\tconst int typeInfoFlags;\t\t/* Attribute-processing */\n\tconst int encodingFlags;\t\t/* Encoding flags */\n\n\t/* Information to allow validity checking for this field */\n\tconst int lowRange;\t\t\t\t/* Min/max allowed if numeric/boolean */\n\tconst int highRange;\t\t\t/* Min/max length if string */\n\tconst int defaultValue;\t\t\t/* Default value if FL_DEFAULT set,\n\t\t\t\t\t\t\t\t\t   length if FIELDTYPE_BLOB */\n\n\t/* Extra data needed to process this field, either a pointer to an\n\t   alternative encoding table or a pointer to the validation function to\n\t   allow extended validity checking */\n\tconst void *extraData;\n\t} ATTRIBUTE_INFO;\n\n/* When building the debug version of the code we include a text string \n   describing the field which is being processed, this makes it easier to \n   track down the point in a certificate where cryptlib finds a problem */\n\n#ifndef NDEBUG\n  #define DESCRIPTION( text )\t\ttext,\n#else\n  #define DESCRIPTION( text )\n#endif /* NDEBUG */\n\n/* Attribute information flags.  These are:\n\n\tFLAG_BLOB: Disables all type-checking on the field, needed to handle\n\t\t\tsome certificates that have invalid field encodings.\n\n\tFLAG_BLOB_PAYLOAD: Disables type checking on the field payload, for\n\t\t\texample checking that the chars in the string are valid for the\n\t\t\tgiven ASN.1 string type.\n\n\tFLAG_CRITICAL: The extension containing the field is marked criticial.\n\n\tFLAG_DEFAULTVALUE: The field has a value which is equal to the default\n\t\t\tfor this field, so it doesn't get encoded.  This flag is set\n\t\t\tduring the encoding pre-processing pass.\n\n\tFLAG_IGNORED: The field is recognised but was ignored at this compliance\n\t\t\tlevel.  This prevents the certificate from being rejected if the \n\t\t\tfield is marked critical.\n\n\tFLAG_LOCKED: The attribute can't be deleted once set, needed to handle\n\t\t\tfields that are added internally by cryptlib that shouldn't be\n\t\t\tdeleted by users once set.\n\n\tFLAG_MULTIVALUED: Multiple instantiations of this field are allowed */\n\n#define ATTR_FLAG_NONE\t\t\t0x0000\t/* No flag */\n#define ATTR_FLAG_CRITICAL\t\t0x0001\t/* Critical cert extension */\n#define ATTR_FLAG_LOCKED\t\t0x0002\t/* Field can't be modified */\n#define ATTR_FLAG_BLOB\t\t\t0x0004\t/* Non-type-checked blob data */\n#define ATTR_FLAG_BLOB_PAYLOAD\t0x0008\t/* Payload is non-type-checked blob data */\n#define ATTR_FLAG_MULTIVALUED\t0x0010\t/* Multiple instances allowed */\n#define ATTR_FLAG_DEFAULTVALUE\t0x0020\t/* Field has default value */\n#define ATTR_FLAG_IGNORED\t\t0x0040\t/* Attribute ignored at this compl.level */\n#define ATTR_FLAG_MAX\t\t\t0x007F\t/* Maximum possible flag value */\n\n/* When comparing attribute fields we only want to compare relevant data and\n   not incidental flags related to parsing or encoding actions.  The following\n   mask defines the attribute flags that we want to compare */\n\n#define ATTR_FLAGS_COMPARE_MASK\t( ATTR_FLAG_CRITICAL )\n\n/* The structure to hold a field of a certificate attribute */\n\ntypedef struct AL {\n\t/* Identification and encoding information for this attribute field or\n\t   attribute.  This consists of the field ID for the attribute as a\n\t   whole (e.g. CRYPT_CERTINFO_NAMECONSTRAINTS), for the attribute field \n\t   (that is, one field of a full attribute, e.g. \n\t   CRYPT_CERTINFO_EXCLUDEDSUBTREES) and for the subfield of the attribute \n\t   field in the case of composite fields like GeneralNames, a pointer to \n\t   the sync point used when encoding the attribute, and the encoded size \n\t   of this field.  If it's a special-case attribute field such as a blob\n\t   field or a field with a fixed default value that's present only for\n\t   encoding purposes then the attributeID and fieldID are set to special \n\t   values decoded by the isXXX() macros further down.  The subFieldID is \n\t   only set if the fieldID is for a GeneralName field.\n\n\t   Although the field type information is contained in the\n\t   attributeInfoPtr it's sometimes needed before this has been set up\n\t   to handle special formatting requirements, for example to enable\n\t   special-case handling for a DN attribute field or to specify that an\n\t   OID needs to be decoded into its string representation before being\n\t   returned to the caller.  Because of this we store a copy of the field \n\t   type information here to allow for this special processing */\n\tCRYPT_ATTRIBUTE_TYPE attributeID;/* Attribute ID */\n\tCRYPT_ATTRIBUTE_TYPE fieldID;\t/* Attribute field ID */\n\tCRYPT_ATTRIBUTE_TYPE subFieldID;\t/* Attribute subfield ID */\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\t/* Pointer to encoding sync point */\n\tint encodedSize;\t\t\t\t/* Encoded size of this field */\n\tint fieldType;\t\t\t\t\t/* Attribute field type */\n\tSAFE_FLAGS flags;\t\t\t\t/* Flags for this field */\n\n\t/* Sometimes a field is part of a constructed object or even a nested\n\t   series of constructed objects (these are always SEQUENCEs).  Since\n\t   this is purely an encoding issue there are no attribute list entries\n\t   for the SEQUENCE fields so when we perform the first pass over the\n\t   attribute list prior to encoding we remember the lengths of the\n\t   SEQUENCEs for later use.  Since we can have nested SEQUENCEs\n\t   containing a given field we store the lengths and pointers to the \n\t   ATTRIBUTE_INFO table entries used to encode them in a fifo with the \n\t   innermost one first and successive outer ones following it */\n\tARRAY( ENCODING_FIFO_SIZE, fifoPos ) \\\n\tint sizeFifo[ ENCODING_FIFO_SIZE + 2 ];\t\n\t\t\t\t\t\t\t\t\t/* Encoded size of SEQUENCE containing \n\t\t\t\t\t\t\t\t\t   this field, if present */\n\tARRAY( ENCODING_FIFO_SIZE, fifoPos ) \\\n\tconst ATTRIBUTE_INFO *encodingFifo[ ENCODING_FIFO_SIZE + 2 ];\n\t\t\t\t\t\t\t\t\t/* Encoding table entry used to encode \n\t\t\t\t\t\t\t\t\t   this SEQUENCE */\n\tint fifoEnd;\t\t\t\t\t/* End of list of SEQUENCE sizes */\n\tint fifoPos;\t\t\t\t\t/* Current position in list */\n\n\t/* The data payload for this attribute field or attribute.  If it's\n\t   numeric data such as a simple boolean, bitstring, or small integer\n\t   then we store it in the intValue member, if it's a scalar type then\n\t   we store it in { value, valueLength }, and if it's a DN we store\n\t   it in a DATAPTR */\n\tunion { \n\t\tlong intValue;\t\t\t\t/* Integer value for simple types */\n\t\tstruct {\t\t\t\t\t/* Data value for scalar types */\n\t\t\tBUFFER_OPT_FIXED( valueLength ) \\\n\t\t\tvoid *dataValue;\n\t\t\tint dataValueLength;\n\t\t\t} dataValueInfo;\n\t\tDATAPTR_DN dnValue;\t\t\t/* Safe pointer for DN types */\n\t\t} data;\n\t#define intValue\t\tdata.intValue\n\t#define dataValue\t\tdata.dataValueInfo.dataValue\n\t#define dataValueLength\tdata.dataValueInfo.dataValueLength\n\t#define dnValue\t\t\tdata.dnValue\n\n\t/* The OID, for blob-type attributes */\n\tBYTE *oid;\t\t\t\t\t\t/* Attribute OID */\n\n\t/* The previous and next list element in the linked list of elements */\n\tDATAPTR_ATTRIBUTE prev, next;\n\n\t/* Variable-length storage for the attribute data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} ATTRIBUTE_LIST;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAttribute Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check attribute data.  This operates on an internal ATTRIBUTE_LIST \n   rather than the external DATAPTR_ATTRIBUTE */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckAttributePtr( IN const ATTRIBUTE_LIST *attributeListPtr );\n\n/* The validation function used to perform additional validation on fields */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *VALIDATION_FUNCTION )( const ATTRIBUTE_LIST *attributeListPtr );\n\n/* Look up an ATTRIBUTE_INFO entry based on an OID */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nconst ATTRIBUTE_INFO *oidToAttribute( IN_ENUM( ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength );\n\n/* Select the appropriate attribute info table for encoding/type checking */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getAttributeInfo( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t  OUT const ATTRIBUTE_INFO **attributeInfoPtrPtr,\n\t\t\t\t\t  OUT_INT_Z int *noAttributeEntries );\n\n/* Check an attribute property using and ATTRIBUTE_LIST * rather than a\n   DATAPTR_ATTRIBUTE */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkAttributeListProperty( IN const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property );\n\n/* Get the encoded tag for a field */\n\nCHECK_RETVAL_RANGE( MAKE_CTAG_PRIMITIVE( 0 ), MAX_TAG ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getFieldEncodedTag( const ATTRIBUTE_INFO *attributeInfoPtr );\n\n/* Get the attribute and attributeID for a field ID */\n\nCHECK_RETVAL_PTR \\\nconst ATTRIBUTE_INFO *fieldIDToAttribute( IN_ENUM( ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID, \n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *attributeID );\n\n/* Find an attribute */\n\nCHECK_RETVAL_PTR \\\nconst ATTRIBUTE_LIST *findAttributeStart( IN_OPT const ATTRIBUTE_LIST *attributeListPtr );\n\n/* Determine the encoded size of an attribute field */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofAttributeField( INOUT ATTRIBUTE_LIST *attributeListPtr );\n\n#endif /* _CERTATTR_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/certfn.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Function Header File \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The huge complexity of the certificate management code means that there\n   are a sufficient number of functions required that we confine the\n   prototypes to their own file */\n\n#ifndef _CERTFN_DEFINED\n\n#define _CERTFN_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDN Manipulation Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* DN string functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nint getAsn1StringInfo( IN_BUFFER( stringLen ) const void *string, \n\t\t\t\t\t   IN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t   OUT_RANGE( 0, 20 ) int *stringType, \n\t\t\t\t\t   OUT_TAG_ENCODED_Z int *asn1StringType,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *asn1StringLen,\n\t\t\t\t\t   const BOOLEAN isNativeString );\n\n/* DN manipulation routines */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint insertDNComponent( INOUT_PTR DATAPTR_DN *dnPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE componentType,\n\t\t\t\t\t   IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t   IN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteDNComponent( INOUT DATAPTR_DN *dnPtr, \n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t   IN_BUFFER_OPT( valueLength ) const void *value, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int valueLength );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteDN( INOUT_PTR DATAPTR_DN *dnPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getDNComponentInfo( IN const DATAPTR_DN dn,\n\t\t\t\t\t\tOUT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *type,\n\t\t\t\t\t\tOUT_BOOL BOOLEAN *dnContinues );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 6 ) ) \\\nint getDNComponentValue( IN_DATAPTR_OPT const DATAPTR_DN dnComponentList,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t IN_RANGE( 0, 100 ) const int count,\n\t\t\t\t\t\t OUT_BUFFER_OPT( valueMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *valueLength ) void *value, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int valueMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( valueMaxLength ) \\\n\t\t\t\t\t\t\tint *valueLength );\n\n/* Copy and compare a DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyDN( OUT_DATAPTR DATAPTR_DN *dnDestPtr, \n\t\t\tIN const DATAPTR_DN dnSrc );\nCHECK_RETVAL_BOOL \\\nBOOLEAN compareDN( IN_DATAPTR_OPT const DATAPTR_DN dn1,\n\t\t\t\t   IN_DATAPTR_OPT const DATAPTR_DN dn2,\n\t\t\t\t   const BOOLEAN dn1substring,\n\t\t\t\t   OUT_DATAPTR_xCOND DATAPTR_DN *mismatchPointPtrPtr );\n\n/* Select DN/GeneralName components */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectGeneralName( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_ATTRIBUTE_OPT const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t   IN_ENUM( SELECTION_OPTION ) const SELECTION_OPTION option );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectGeneralNameComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectDN( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_ATTRIBUTE_OPT const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t  IN_ENUM( SELECTION_OPTION ) const SELECTION_OPTION option );\n\n/* Read/write a DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nint checkDN( IN const DATAPTR_DN dn,\n\t\t\t IN_FLAGS( CHECKDN ) const int checkFlags,\n\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL_LENGTH \\\nint sizeofDN( IN_DATAPTR_OPT const DATAPTR_DN dn );\n\t\t\t  /* Non-const because it performs a pre-encoding pass */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readDN( INOUT STREAM *stream, \n\t\t\tOUT_DATAPTR_COND DATAPTR_DN *dnPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeDN( INOUT STREAM *stream, \n\t\t\t IN const DATAPTR_DN dn,\n\t\t\t IN_TAG const int tag );\n#ifdef USE_CERT_DNSTRING\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readDNstring( INOUT_PTR DATAPTR_DN *dnPtr,\n\t\t\t\t  IN_BUFFER( stringLength ) const BYTE *string, \n\t\t\t\t  IN_LENGTH_ATTRIBUTE const int stringLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeDNstring( INOUT STREAM *stream, \n\t\t\t\t   const DATAPTR_DN dn );\n#endif /* USE_CERT_DNSTRING */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Manipulation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check attribute data */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN sanityCheckAttribute( IN const DATAPTR_ATTRIBUTE attributePtr );\n\n/* Print an attribute list, for debugging */\n\n#ifndef NDEBUG\nvoid printAttributeList( IN const DATAPTR_ATTRIBUTE attributeList );\n#endif /* NDEBUG */\n\n/* Find an attribute */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttribute( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\t const BOOLEAN isFieldID );\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeField( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID );\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeFieldEx( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID );\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeByOID( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength );\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findNextFieldInstance( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr );\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findDnInAttribute( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr );\n\n/* Get/set information about an attribute:\n\n\tPROPERTY_BLOBATTRIBUTE: The item contains a single blob-type attribute.\n\n\tPROPERTY_COMPLETEATTRIBUTE: This item isn't explicitly present in the \n\t\tattribute list but represents an entire (constructed) attribute of\n\t\twhich one field is present, see the long comment for \n\t\tfindAttributeFieldEx() in cert/ext.c for a detailed description.\n\n\tPROPERTY_CRITICAL: The item (which should be a complete attribute) has\n\t\tthe critical flag set.\n\n\tPROPERTY_DEFAULTVALUE: The item is a dummy placeholder entry containing\n\t\ta default value for an attribute, this field isn't explicitly \n\t\tpresent in the attribute list but exists only to contain this \n\t\tdefault value.\n\t\n\tPROPERTY_DN: The item contains a composite DN rather than an integer/\n\t\tboolean/data value.\n\n\tPROPERTY_IGNORED: This item is a recognised attribute but is ignored at \n\t\tthe current compliance level.\n\n\tPROPERTY_VALUE: The integer value for the attribute.  This isn't really \n\t\tan attribute property but we need to be able to set it in a few rare \n\t\tcases when we're applying a constraint to an attribute where the \n\t\tconstraint modifies the attribute's integer value.\n\n\tPROPERTY_LOCKED: This item is locked against further changes.\n\n\tPROPERTY_OID: The data in this item is an encoded OID that needs to be\n\t\tdecoded into the OID text representation before being returned to \n\t\tthe caller */\n\ntypedef enum {\n\tATTRIBUTE_PROPERTY_NONE,\t\t/* No attribute property type */\n\tATTRIBUTE_PROPERTY_DEFAULTVALUE,/* Field has default value */\n\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE,\t/* Item is a single blob attribute */\n\tATTRIBUTE_PROPERTY_COMPLETEATRIBUTE,/* Item is a complete attribute */\n\tATTRIBUTE_PROPERTY_LOCKED,\t\t/* Item is locked against changes */\n\tATTRIBUTE_PROPERTY_CRITICAL,\t/* Attribute is critical */\n\tATTRIBUTE_PROPERTY_DN,\t\t\t/* Attribute contains composite DN */\n\tATTRIBUTE_PROPERTY_OID,\t\t\t/* Attribute data is an OID */\n\tATTRIBUTE_PROPERTY_IGNORED,\t\t/* Attribute is ignored */\n\tATTRIBUTE_PROPERTY_VALUE,\t\t/* Attribute integer value */\n\tATTRIBUTE_PROPERTY_LAST\t\t\t/* Last possible property type */\n\t} ATTRIBUTE_PROPERTY_TYPE;\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeProperty( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\tIN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property );\nvoid setAttributeProperty( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   IN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property,\n\t\t\t\t\t\t   IN_INT_Z const int optValue );\nCHECK_RETVAL \\\nint getAttributeIdInfo( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *attributeID,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *fieldID,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *subFieldID );\nCHECK_RETVAL \\\nint getDefaultFieldValue( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID );\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributePresent( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID );\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeFieldPresent( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID );\n\n/* Get attribute data.  See the comment by the SELECTION_INFO definition for\n   why dnPtrPtr uses double indirection for the pointer instead of single\n   indirection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataValue( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   OUT_INT_Z int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataTime( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t  OUT time_t *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataDN( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\tOUT_DATAPTR_COND DATAPTR_DN *dnPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataDNPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   OUT_PTR DATAPTR_DN **dnPtrPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getAttributeDataPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t OUT_BUFFER_ALLOC( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getBlobAttributeDataPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t OUT_BUFFER_ALLOC( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *dataLength );\n\n/* The pattern { findAttributeField(), getAttributeDataXYZ() } is used \n   frequently enough that we provide a common function for it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nint getAttributeFieldValue( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\tIN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\tOUT_INT_Z int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nint getAttributeFieldTime( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t   IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t   OUT time_t *value );\n\n/* Enumerate entries in an attribute list.  This is a somewhat oddball \n   function that's required to handle a small number of special-case\n   situations that can't be easily handled directly.  The alternative to \n   having the hardwired selections is to provide a general-purpose \n   enumeration capability and then have the caller extract whatever's \n   necessary from the attribute and decide whether they want to continue,\n   however this creates really akward attribute-enumeration loops and,\n   since there are only three cases that we need to handle, really isn't \n   worth the effort */\n\ntypedef enum {\n\tATTRIBUTE_ENUM_NONE,\t\t/* No attribute enumeration type */\n\tATTRIBUTE_ENUM_BLOB,\t\t/* Enumerate blob attributes */\n\tATTRIBUTE_ENUM_NONBLOB,\t\t/* Enumerate non-blob attributes */\n\tATTRIBUTE_ENUM_LAST\t\t\t/* Last possible attribute enumeration type */\n\t} ATTRIBUTE_ENUM_TYPE;\n\ntypedef struct {\n\tDATAPTR_ATTRIBUTE attributePtr;\t/* Currently selected attribute entry */\n\tATTRIBUTE_ENUM_TYPE enumType;\t/* Type of enumeration being performed */\n\t} ATTRIBUTE_ENUM_INFO;\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nCONST_RETURN DATAPTR_ATTRIBUTE getFirstAttribute( OUT ATTRIBUTE_ENUM_INFO *attrEnumInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t  IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t\t\t\t  IN_ENUM( ATTRIBUTE_ENUM ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_ENUM_TYPE enumType );\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nCONST_RETURN DATAPTR_ATTRIBUTE getNextAttribute( INOUT ATTRIBUTE_ENUM_INFO *attrEnumInfo );\n\n/* Since many of the attributes can be disabled to save space and reduce \n   complexity, we may need to check that an attribute that we want to use is\n   actually available, for example if we're about to create it as part of an\n   internal operation for which we don't want to present an unexpected error\n   status to the caller.  The following function checks whether an attribute\n   is enabled for use */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeAvailable( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID );\n\n/* Move the current attribute cursor.  The reason for the apparently-\n   reversed values in the IN_RANGE() annotation are because the values are \n   -ve, so last comes before first  */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE certMoveAttributeCursor( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE currentCursor,\n\t\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int position );\n\n/* For range-checking purposes we need to have ATTR_FLAG_NONE and \n   ATTR_FLAG_MAX defined, since these are defined in certattr.h which isn't\n   visible in all certificate-using code we explicitly define the values \n   here if required */\n\n#ifndef ATTR_FLAG_NONE\n  #define ATTR_FLAG_NONE\t0x0000\n  #define ATTR_FLAG_MAX\t\t0x007F\n#endif /* ATTR_FLAG_NONE */\n#if ATTR_FLAG_MAX != 0x007F\n  #error Inconsistent definition of ATTR_FLAG_MAX in certattr.h/certfn.h\n#endif /* ATTR_FLAG_MAX != 0x007F */\n\n/* Add/delete/copy attributes/attribute fields */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 6 ) ) \\\nint addAttribute( IN_ATTRIBUTE const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t  INOUT DATAPTR_ATTRIBUTE *listHeadPtr, \n\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t  IN_LENGTH_OID const int oidLength,\n\t\t\t\t  const BOOLEAN critical, \n\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t  IN_FLAGS_Z( ATTR ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6, 7 ) ) \\\nint addAttributeField( INOUT DATAPTR_ATTRIBUTE *listHeadPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t   IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t   const int value,\n\t\t\t\t\t   IN_FLAGS_Z( ATTR ) const int flags, \n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 7, 8 ) ) \\\nint addAttributeFieldString( INOUT DATAPTR_ATTRIBUTE *listHeadPtr,\n\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t IN_LENGTH_ATTRIBUTE const int dataLength,\n\t\t\t\t\t\t\t IN_FLAGS_Z( ATTR ) const int flags, \n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteAttributeField( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t  INOUT_OPT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t  INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t\t  INOUT_OPT DATAPTR_DN *dnCursor );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteCompositeAttributeField( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_DN *dnCursor );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteAttribute( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t INOUT DATAPTR_DN *dnCursor );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteCompleteAttribute( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t\t const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t INOUT DATAPTR_DN *dnCursor );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteAttributes( INOUT DATAPTR_ATTRIBUTE *attributePtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint copyAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\tIN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint copyIssuerAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\t\t  const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n#ifdef USE_CERTREQ\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCRMFRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr );\n#endif /* USE_CERTREQ */\n#ifdef USE_CERTVAL\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRTCSRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr );\n#endif /* USE_CERTVAL */\n#ifdef USE_CERTREV\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyOCSPRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRevocationAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr );\n#endif /* USE_CERTREV */\n\n/* Read/write a collection of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nint checkAttributes( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t IN const DATAPTR_ATTRIBUTE listHeadPtr,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAttributes( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE type );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAttributes( INOUT STREAM *stream, \n\t\t\t\t\t INOUT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t IN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t IN_LENGTH const int attributeSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 6 ) ) \\\nint readAttributes( INOUT STREAM *stream, \n\t\t\t\t\tINOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\tIN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type, \n\t\t\t\t\tIN_LENGTH_Z const int attributeLength,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tValidity Information Processing Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTVAL\n\n/* Sanity-check the validity info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckValInfo( IN const VALIDITY_INFO *validityInfo );\n\n/* Read/write validity information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readRTCSRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofRtcsRequestEntries( IN const DATAPTR rtcsEntries );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofRtcsResponseEntries( IN const DATAPTR rtcsEntries,\n\t\t\t\t\t\t\t   const BOOLEAN isExtendedResponse );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRtcsRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN const DATAPTR rtcsEntries );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readRTCSResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRtcsResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN const DATAPTR rtcsEntries,\n\t\t\t\t\t\t\t  const BOOLEAN isExtendedResponse );\n\n/* Add/delete a validity entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addValidityEntry( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t  OUT_OPT_PTR_COND VALIDITY_INFO **newEntryPosition,\n\t\t\t\t\t  IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t  IN_LENGTH_FIXED( KEYID_SIZE ) const int valueLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nint prepareValidityEntries( IN_DATAPTR_OPT const DATAPTR listHead, \n\t\t\t\t\t\t\tOUT_PTR_xCOND VALIDITY_INFO **errorEntry,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteValidityEntries( INOUT_PTR DATAPTR *listHeadPtr );\n\n/* Copy a set of validity entries */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyValidityEntries( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t IN const DATAPTR srcList );\n\n/* Check a certificate's validity status */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkRTCSResponse( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE const CRYPT_KEYSET iCryptKeyset );\n\n#endif /* USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRevocation Information Processing Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Sanity-check revocation info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckRevInfo( IN const REVOCATION_INFO *revocationInfo );\n\n/* Read/write revocation information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readCRLentry( INOUT STREAM *stream, \n\t\t\t\t  INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t  IN_LENGTH_Z const int entryNo,\n\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readCRLentries( INOUT STREAM *stream, \n\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 2 ) ) \\\nint sizeofCRLentries( IN const DATAPTR crlEntries,\n\t\t\t\t\t  OUT_BOOL BOOLEAN *isV2CRL );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCRLentry( INOUT STREAM *stream, \n\t\t\t\t   IN const REVOCATION_INFO *crlEntry );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeCRLentries( INOUT STREAM *stream, \n\t\t\t\t\t IN const DATAPTR crlEntries );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readOcspRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readOcspResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofOcspRequestEntries( IN const DATAPTR ocspEntries );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofOcspResponseEntries( IN const DATAPTR ocspEntries );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOcspRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN const DATAPTR ocspEntries );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOcspResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN const DATAPTR ocspEntries,\n\t\t\t\t\t\t\t  const time_t entryTime );\n\n/* Add/delete a revocation entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint addRevocationEntry( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\tOUT_OPT_PTR_COND REVOCATION_INFO **newEntryPosition,\n\t\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE valueType,\n\t\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\t\tconst BOOLEAN noCheck );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6 ) ) \\\nint prepareRevocationEntries( IN_DATAPTR_OPT const DATAPTR listHead, \n\t\t\t\t\t\t\t  const time_t defaultTime,\n\t\t\t\t\t\t\t  OUT_PTR_xCOND REVOCATION_INFO **errorEntry,\n\t\t\t\t\t\t\t  const BOOLEAN isSingleEntry,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteRevocationEntries( INOUT_PTR DATAPTR *listHeadPtr );\n\n/* Copy a set of revocation entries */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRevocationEntries( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t IN const DATAPTR srcList );\n\n/* Check a certificate's revocation status */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCRL( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCRL );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkOCSPResponse( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE const CRYPT_KEYSET iCryptKeyset );\n\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertBasic( INOUT CERT_INFO *subjectCertInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint checkCert( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t   IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t   const BOOLEAN shortCircuitCheck,\n\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertChain( INOUT CERT_INFO *certInfoPtr );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint getKeyUsageFromExtKeyUsage( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( CRYPT_KEYUSAGE ) int *keyUsage,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus, \n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5, 6 ) ) \\\nint checkKeyUsage( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t   IN_FLAGS_Z( CHECKKEY ) const int flags, \n\t\t\t\t   IN_FLAGS_Z( CRYPT_KEYUSAGE ) const int specificUsage,\n\t\t\t\t   IN_RANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \\\n\t\t\t\t\t\t\t CRYPT_COMPLIANCELEVEL_LAST - 1 ) \\\n\t\t\t\t\t\tconst int complianceLevel,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n\n/* Check certificate constraints */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint checkNameConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE issuerAttributes,\n\t\t\t\t\t\t  const BOOLEAN isExcluded,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\nCHECK_RETVAL_BOOL \\\nBOOLEAN isAnyPolicy( IN const DATAPTR_ATTRIBUTE attributePtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 7, 8 ) ) \\\nint checkPolicyConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\tIN const DATAPTR_ATTRIBUTE issuerAttributes,\n\t\t\t\t\t\t\tIN_ENUM_OPT( POLICY ) const POLICY_TYPE policyType,\n\t\t\t\t\t\t\tIN_OPT const POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\tIN_RANGE( 0, MAX_CHAINLENGTH ) const int policyLevel,\n\t\t\t\t\t\t\tconst BOOLEAN allowMappedPolicies,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint checkPathConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int pathLength,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n/* Sign/sig check a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint signCert( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iSignContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertValidity( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_HANDLE iSigCheckObject );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Chain Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write/copy a certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCertChain( INOUT STREAM *stream, \n\t\t\t\t   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t   IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t   IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t   IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t   IN_FLAGS( KEYMGMT ) const int options );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCertChain( INOUT STREAM *stream, \n\t\t\t\t\tconst CERT_INFO *certInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCertChain( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE certChain,\n\t\t\t\t   const BOOLEAN isCertCollection );\n\n/* Read/write certificate collections in assorted formats */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofCertCollection( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCertCollection( INOUT STREAM *stream, \n\t\t\t\t\t\t IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType );\n\n/* Assemble a certificate chain from certificates read from an object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint assembleCertChain( OUT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iCertSource,\n\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t   IN_FLAGS( KEYMGMT ) const int options );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCertificate Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check certificate data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckCert( IN const CERT_INFO *certInfoPtr );\n\n/* Create a certificate object ready for further initialisation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificateInfo( OUT_PTR_COND CERT_INFO **certInfoPtrPtr, \n\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\n\n/* Add/get/delete a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t  const int certInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addCertComponentString( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\tIN_BUFFER( certInfoLength ) const void *certInfo, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int certInfoLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t  OUT_INT_Z int *certInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint getCertComponentString( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\tOUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t*certInfoLength ) void *certInfo, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\t\tint *certInfoLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType );\n\n/* Manage certificate attribute cursors */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setCertificateCursor( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t  IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\tconst int cursorMoveType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAttributeCursor( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\tIN const int value );\n\n/* Import/export a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint importCert( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\tIN_DATALENGTH const int certObjectLength,\n\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *certificate,\n\t\t\t\tIN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\tIN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\tIN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options,\n\t\t\t\tIN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE formatHint );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint exportCert( OUT_BUFFER_OPT( certObjectMaxLength, *certObjectLength ) \\\n\t\t\t\t\tvoid *certObject, \n\t\t\t\tIN_DATALENGTH_Z const int certObjectMaxLength, \n\t\t\t\tOUT_DATALENGTH_Z int *certObjectLength,\n\t\t\t\tIN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType,\n\t\t\t\tIN const CERT_INFO *certInfoPtr );\n\n/* Oddball routines: work with a certificate's serial number */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSerialNumber( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t IN_BUFFER_OPT( serialNumberLength ) const void *serialNumber, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int serialNumberLength );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nBOOLEAN compareSerialNumber( IN_BUFFER( canonSerialNumberLength ) \\\n\t\t\t\t\t\t\t\tconst void *canonSerialNumber,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int canonSerialNumberLength,\n\t\t\t\t\t\t\t IN_BUFFER( serialNumberLength ) \\\n\t\t\t\t\t\t\t\tconst void *serialNumber,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int serialNumberLength );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert a text-form OID to its binary form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint textToOID( IN_BUFFER( textOidLength ) const char *textOID, \n\t\t\t   IN_LENGTH_TEXT const int textOidLength, \n\t\t\t   OUT_BUFFER( binaryOidMaxLen, *binaryOidLen ) BYTE *binaryOID, \n\t\t\t   IN_LENGTH_SHORT const int binaryOidMaxLen, \n\t\t\t   OUT_LENGTH_BOUNDED_Z( binaryOidMaxLen ) \\\n\t\t\t\t\tint *binaryOidLen );\n\n/* Check that a text string contains valid characters for its string type.\n   This is used in non-DN strings where we can't avoid the problem by varying\n   the string type based on the characters being used */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkTextStringData( IN_BUFFER( stringLen ) const char *string, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t\t\t const BOOLEAN isPrintableString );\n\n/* Prototypes for functions in certext.c */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isValidField( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\n\n/* Prototypes for functions in certschk.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 8, 9 ) ) \\\nint checkCertDetails( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t  INOUT_OPT CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerPubKey,\n\t\t\t\t\t  IN_OPT const X509SIG_FORMATINFO *formatInfo,\n\t\t\t\t\t  const BOOLEAN trustAnchorCheck,\n\t\t\t\t\t  const BOOLEAN shortCircuitCheck,\n\t\t\t\t\t  const BOOLEAN basicCheckDone,\n\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n\n/* Prototypes for functions in comp_cert.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyPublicKeyInfo( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   IN_OPT const CERT_INFO *srcCertInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCertObject( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE addedCert,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\tIN const int certInfo );\n\n/* Prototypes for functions in comp_get.c */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\ntime_t *getRevocationTimePtr( IN const CERT_INFO *certInfoPtr );\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nDATAPTR_ATTRIBUTE findAttributeComponent( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType );\n\n/* Prototypes for functions in comp_pkiu.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint copyPkiUserToCertReq( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t  INOUT CERT_INFO *pkiUserInfoPtr );\n\n/* Prototypes for functions in dn.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint convertEmail( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t  INOUT DATAPTR_DN *dnComponentListPtrPtr,\n\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE altNameType );\n\n/* Prototypes for functions in ext.c */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN compareAttribute( IN_DATAPTR const DATAPTR_ATTRIBUTE attribute1,\n\t\t\t\t\t\t  IN_DATAPTR const DATAPTR_ATTRIBUTE attribute2 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fixAttributes( INOUT CERT_INFO *certInfoPtr );\nvoid initAttributes( void );\n\n/* Prototypes for functions in ext_def.c */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN sanityCheckExtensionTables( void );\n\n/* Prototypes for functions in imp_chk.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint getCertObjectInfo( INOUT STREAM *stream,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *objectOffset, \n\t\t\t\t\t   OUT_DATALENGTH_Z int *objectLength, \n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_TYPE *objectType,\n\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE formatHint );\n\n/* Prototypes for functions in write_pre.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint preEncodeCertificate( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t  IN_FLAGS( PRE_SET ) const int actions );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint preCheckCertificate( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t IN_FLAGS( PRE_CHECK ) const int actions, \n\t\t\t\t\t\t IN_FLAGS_Z( PRE ) const int flags );\n\n#endif /* _CERTFN_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/certrev.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Revocation Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* The maximum length of ID that can be stored in a REVOCATION_INFO entry.\n   Larger IDs require external storage */\n\n#define MAX_ID_SIZE\t\t128\n\n/* Usually when we add revocation information we perform various checks such\n   as making sure that we're not adding duplicate information, however when\n   processing the mega-CRLs from some CAs this becomes prohibitively\n   expensive.  To solve this problem we perform checking up to a certain\n   number of entries and after that just drop in any further entries as is\n   in order to provide same-day service.  The following value defines the\n   number of CRL entries at which we stop performing checks when we add new \n   entries */\n\n#define CRL_SORT_LIMIT\t1024\n\n/* Context-specific tags for OCSP certificate identifier types */\n\nenum { CTAG_OI_CERTIFICATE, CTAG_OI_CERTIDWITHSIG, CTAG_OI_RTCS };\n\n/* OCSP certificate status values */\n\nenum { OCSP_STATUS_NOTREVOKED, OCSP_STATUS_REVOKED, OCSP_STATUS_UNKNOWN };\n\n#ifdef USE_CERTREV\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the revocation info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckRevInfo( IN const REVOCATION_INFO *revocationInfo )\n\t{\n\tassert( isReadPtr( revocationInfo, sizeof( REVOCATION_INFO ) ) );\n\n\tif( revocationInfo == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRevInfo: Missing revocation info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check ID type */\n\tif( revocationInfo->idType != CRYPT_KEYID_NONE && \\\n\t\trevocationInfo->idType != CRYPT_IKEYID_CERTID && \\\n\t\trevocationInfo->idType != CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \\\n\t\trevocationInfo->idType != CRYPT_IKEYID_ISSUERID )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRevInfo: ID type\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check ID data */\n\tif( revocationInfo->id == NULL || \\\n\t\t!isShortIntegerRange( revocationInfo->idLength ) || \\\n\t\tchecksumData( revocationInfo->id, \n\t\t\t\t\t  revocationInfo->idLength ) != revocationInfo->idCheck )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRevInfo: ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( revocationInfo->attributes ) || \\\n\t\t!DATAPTR_ISVALID( revocationInfo->prev ) || \\\n\t\t!DATAPTR_ISVALID( revocationInfo->next ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRevInfo: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAdd/Delete/Check Revocation Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an entry in a revocation list.  This is done using a linear search,\n   which isn't very optimal but anyone trying to do anything useful with\n   mega-CRLs (or with CRLs in general) is in more trouble than basic search\n   algorithm choice.  In other words it doesn't really make much difference\n   whether we have an optimal or suboptimal implementation of a\n   fundamentally broken mechanism like CRLs.\n\n   The value is either a serialNumber or a hash of some form (issuerID,\n   certHash), we don't bother distinguishing the exact type since the\n   chances of a hash collision are virtually nonexistant */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int findRevocationEntry( IN const DATAPTR listHead,\n\t\t\t\t\t\t\t\tOUT_PTR_OPT REVOCATION_INFO **insertPoint,\n\t\t\t\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\t\t\t\tconst BOOLEAN sortEntries )\n\t{\n\tconst REVOCATION_INFO *listPtr, *prevElement = NULL;\n\tconst int idCheck = checksumData( value, valueLength );\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( insertPoint, sizeof( REVOCATION_INFO * ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\tREQUIRES( sortEntries == TRUE || sortEntries == FALSE );\n\n\t/* Clear return value */\n\t*insertPoint = NULL;\n\n\t/* Find the correct place in the list to insert the new element and check\n\t   for duplicates.  If requested we sort the entries by serial number\n\t   (or more generally data value) for no adequately explored reason \n\t   (some implementations can optimise the searching of CRLs based on\n\t   this but since there's no agreement on whether to do it or not you \n\t   can't tell whether it's safe to rely on it).  In addition we bound \n\t   the loop with FAILSAFE_ITERATIONS_MAX rather than the more usual\n\t   FAILSAFE_ITERATIONS_LARGE since CRLs can grow enormous */\n\tLOOP_MAX( listPtr = DATAPTR_GET( listHead ),\n\t\t\t  listPtr != NULL, \n\t\t\t  listPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckRevInfo( listPtr ) );\n\n\t\tif( ( sortEntries || idCheck == listPtr->idCheck ) && \\\n\t\t\tlistPtr->idLength == valueLength )\n\t\t\t{\n\t\t\tconst int compareStatus = memcmp( listPtr->id,\n\t\t\t\t\t\t\t\t\t\t\t  value, valueLength );\n\n\t\t\tif( !compareStatus )\n\t\t\t\t{\n\t\t\t\t/* We found a matching entry, tell the caller which one it\n\t\t\t\t   is */\n\t\t\t\t*insertPoint = ( REVOCATION_INFO * ) listPtr;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( sortEntries && compareStatus > 0 )\n\t\t\t\tbreak;\t\t\t\t\t/* Insert before this point */\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( sortEntries && listPtr->idLength > valueLength )\n\t\t\t\tbreak;\t\t\t\t\t/* Insert before this point */\n\t\t\t}\n\n\t\tprevElement = listPtr;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We can't find a matching entry, return the revocation entry that we \n\t   should insert the new value after */\n\t*insertPoint = ( REVOCATION_INFO * ) prevElement;\n\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* Add an entry to a revocation list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint addRevocationEntry( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\tOUT_OPT_PTR_COND REVOCATION_INFO **newEntryPosition,\n\t\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE valueType,\n\t\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\t\tconst BOOLEAN noCheck )\n\t{\n\tDATAPTR listHead = *listHeadPtr;\n\tREVOCATION_INFO *newElement, *insertPoint DUMMY_INIT_PTR;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( newEntryPosition, sizeof( REVOCATION_INFO * ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\t\n\tREQUIRES( valueType == CRYPT_KEYID_NONE || \\\n\t\t\t  valueType == CRYPT_IKEYID_CERTID || \\\n\t\t\t  valueType == CRYPT_IKEYID_ISSUERID || \\\n\t\t\t  valueType == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\tREQUIRES( noCheck == TRUE || noCheck == FALSE );\n\n\t/* Clear return value */\n\t*newEntryPosition = NULL;\n\n\t/* Find the insertion point for the new entry unless we're reading data\n\t   from a large pre-encoded CRL (indicated by the caller setting the \n\t   noCheck flag), in which case we just drop it in at the start.  The \n\t   absence of checking is necessary in order to provide same-day service \n\t   for large CRLs */\n\tif( !noCheck && DATAPTR_ISSET( listHead ) )\n\t\t{\n\t\tint status;\n\n\t\tstatus = findRevocationEntry( listHead, &insertPoint, value, \n\t\t\t\t\t\t\t\t\t  valueLength, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* If we get an OK status it means that we've found an existing\n\t\t\t   entry that matches the one being added, we can't add it \n\t\t\t   again */\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Insert the new element at the start */\n\t\tinsertPoint = NULL;\n\t\t}\n\n\t/* Allocate memory for the new element and copy the information across */\n\tREQUIRES( rangeCheck( valueLength, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( newElement = ( REVOCATION_INFO * ) \\\n\t\t\tclAlloc( \"addRevocationEntry\", \\\n\t\t\t\t\t sizeof( REVOCATION_INFO ) + valueLength ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tinitVarStruct( newElement, REVOCATION_INFO, valueLength, id );\n\tnewElement->idType = valueType;\n\tmemcpy( newElement->id, value, valueLength );\n\tnewElement->idLength = valueLength;\n\tnewElement->idCheck = checksumData( value, valueLength );\n\tDATAPTR_SET( newElement->attributes, NULL );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\tREQUIRES( sanityCheckRevInfo( newElement ) );\n\n\t/* Insert the new element into the list */\n\tinsertDoubleListElement( listHeadPtr, insertPoint, newElement, \n\t\t\t\t\t\t\t REVOCATION_INFO );\n\t*newEntryPosition = newElement;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete a revocation list */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteRevocationEntries( INOUT_PTR DATAPTR *listHeadPtr )\n\t{\n\tDATAPTR listHead = *listHeadPtr;\n\tREVOCATION_INFO *revocationListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\n\t/* If the list was empty, return now */\n\tif( DATAPTR_ISNULL( listHead ) )\n\t\treturn;\n\n\t/* Destroy any remaining list items */\n\tLOOP_MAX_INITCHECK( revocationListCursor = DATAPTR_GET( listHead ),\n\t\t\t\t\t\trevocationListCursor != NULL )\n\t\t{\n\t\tREVOCATION_INFO *itemToFree = revocationListCursor;\n\n\t\tREQUIRES_V( sanityCheckRevInfo( itemToFree ) );\n\n\t\trevocationListCursor = DATAPTR_GET( revocationListCursor->next );\n\t\tif( DATAPTR_ISSET( itemToFree->attributes ) )\n\t\t\tdeleteAttributes( &itemToFree->attributes );\n\t\tzeroise( itemToFree, sizeof( REVOCATION_INFO ) );\n\t\tclFree( \"deleteRevocationEntries\", itemToFree );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\tDATAPTR_SET_PTR( listHeadPtr, NULL );\n\t}\n\n/* Prepare the entries in a revocation list prior to encoding them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6 ) ) \\\nint prepareRevocationEntries( IN_DATAPTR_OPT const DATAPTR listHead, \n\t\t\t\t\t\t\t  const time_t defaultTime,\n\t\t\t\t\t\t\t  OUT_PTR_xCOND REVOCATION_INFO **errorEntry,\n\t\t\t\t\t\t\t  const BOOLEAN isSingleEntry,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tREVOCATION_INFO *revocationEntry;\n\tconst time_t currentTime = ( defaultTime > MIN_TIME_VALUE ) ? \\\n\t\t\t\t\t\t\t   defaultTime : getApproxTime();\n\tint value, LOOP_ITERATOR, status;\n\n\tassert( isWritePtr( errorEntry, sizeof( REVOCATION_INFO * ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\tREQUIRES( isSingleEntry == TRUE || isSingleEntry == FALSE );\n\n\t/* Clear return values */\n\t*errorEntry = NULL;\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If the revocation list is empty there's nothing to do */\n\tif( DATAPTR_ISNULL( listHead ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Set the revocation time if this hasn't already been set.  If there's a\n\t   default time set we use that otherwise we use the current time */\n\tLOOP_LARGE( revocationEntry = DATAPTR_GET( listHead ), \n\t\t\t\trevocationEntry != NULL,\n\t\t\t\trevocationEntry = DATAPTR_GET( revocationEntry->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckRevInfo( revocationEntry ) );\n\n\t\tif( revocationEntry->revocationTime <= MIN_TIME_VALUE )\n\t\t\trevocationEntry->revocationTime = currentTime;\n\n\t\t/* Check whether the certificate was revoked with a reason of \n\t\t   neverValid, which requires special handling of dates because \n\t\t   X.509 doesn't formally define a neverValid reason, assuming that \n\t\t   all CAs are perfect and never issue certificates in error.  The \n\t\t   general idea is to set the two to the same value with the \n\t\t   invalidity date (which should be earlier than the revocation date, \n\t\t   at least in a sanely-run CA) taking precedence.  A revocation \n\t\t   with this reason code will in general only be issued by the \n\t\t   cryptlib CA (where it's required to handle problems in the CMP \n\t\t   protocol) and this always sets the invalidity date so in almost \n\t\t   all cases we'll be setting the revocation date to the \n\t\t   (CA-specified) invalidity date, which is the date of issue of the \n\t\t   certificate being revoked */\n\t\tstatus = getAttributeFieldValue( revocationEntry->attributes,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\t\tif( cryptStatusOK( status ) && value == CRYPT_CRLREASON_NEVERVALID )\n\t\t\t{\n\t\t\ttime_t invalidityDate;\n\n\t\t\t/* The certificate was revoked with the neverValid code, see if \n\t\t\t   there's an invalidity date present */\n\t\t\tstatus = getAttributeFieldTime( revocationEntry->attributes,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_INVALIDITYDATE,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\t\t\t&invalidityDate );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* There's no invalidity date present, set it to the same as\n\t\t\t\t   the revocation date */\n\t\t\t\tstatus = addAttributeFieldString( &revocationEntry->attributes,\n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_INVALIDITYDATE,\n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t\t\t\t  &revocationEntry->revocationTime,\n\t\t\t\t\t\t\t\t\t\t\t\t  sizeof( time_t ), 0,\n\t\t\t\t\t\t\t\t\t\t\t\t  errorLocus, errorType );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Remember the entry that caused the problem */\n\t\t\t\t\t*errorEntry = revocationEntry;\n\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* There's an invalidity date present, make sure that the \n\t\t\t\t   revocation date is the same as the invalidity date */\n\t\t\t\trevocationEntry->revocationTime = invalidityDate;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* If we're only processing a single CRL entry rather than an \n\t\t   entire revocation list we're done */\n\t\tif( isSingleEntry )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Check the attributes for each entry in a revocation list */\n\tLOOP_LARGE( revocationEntry = DATAPTR_GET( listHead ), \n\t\t\t\trevocationEntry != NULL,\n\t\t\t\trevocationEntry = DATAPTR_GET( revocationEntry->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckRevInfo( revocationEntry ) );\n\n\t\tif( DATAPTR_ISSET( revocationEntry->attributes ) )\n\t\t\t{\n\t\t\tstatus = checkAttributes( ATTRIBUTE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t  revocationEntry->attributes,\n\t\t\t\t\t\t\t\t\t  errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Remember the entry that caused the problem */\n\t\t\t\t*errorEntry = revocationEntry;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* If we're only processing a single CRL entry rather than an \n\t\t   entire revocation list we're done */\n\t\tif( isSingleEntry )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRevocation-Checking Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a certificate has been revoked */\n\ntypedef CHECK_RETVAL int ( *CHECKREVOCATIONFUNCTION ) \\\n\t\t\t\t\t\t\t( const CERT_INFO *certInfoPtr, \\\n\t\t\t\t\t\t\t  INOUT CERT_INFO *revocationInfoPtr ) \\\n\t\t\t\t\t\t\t\tSTDC_NONNULL_ARG( ( 1, 2 ) );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkRevocationCRL( IN const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t   INOUT CERT_INFO *revocationInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = revocationInfoPtr->cCertRev;\n\tREVOCATION_INFO *revocationEntry;\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( revocationInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( revocationInfoPtr->type == CRYPT_CERTTYPE_CRL );\n\n\t/* If there's no revocation information present then the certificate \n\t   can't have been revoked */\n\tif( DATAPTR_ISNULL( certRevInfo->revocations ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If the issuers differ then the certificate can't be in this CRL */\n\tif( ( revocationInfoPtr->issuerDNsize != certInfoPtr->issuerDNsize || \\\n\t\tmemcmp( revocationInfoPtr->issuerDNptr, certInfoPtr->issuerDNptr,\n\t\t\t\trevocationInfoPtr->issuerDNsize ) ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether there's an entry for this certificate in the list */\n\tstatus = findRevocationEntry( certRevInfo->revocations, &revocationEntry,\n\t\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t\t\t\t\t  FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* No CRL entry, the certificate is OK */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( revocationEntry != NULL );\n\tREQUIRES( sanityCheckRevInfo( revocationEntry ) );\n\n\t/* Select the entry that contains the revocation information and return\n\t   the certificate's status */\n\tDATAPTR_SET( certRevInfo->currentRevocation, revocationEntry );\n\n\treturn( CRYPT_ERROR_INVALID );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkRevocationOCSP( IN const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t    INOUT CERT_INFO *revocationInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = revocationInfoPtr->cCertRev;\n\tREVOCATION_INFO *revocationEntry;\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( revocationInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( revocationInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\n\t/* If there's no revocation information present then the certificate \n\t   can't have been revoked */\n\tif( DATAPTR_ISNULL( certRevInfo->revocations ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether there's an entry for this certificate in the list */\n\tstatus = findRevocationEntry( certRevInfo->revocations, &revocationEntry,\n\t\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t\t\t\t\t  FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* No revocation entry, the certificate is OK */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( revocationEntry != NULL );\n\tREQUIRES( sanityCheckRevInfo( revocationEntry ) );\n\n\t/* Select the entry that contains the revocation information and return\n\t   the certificate's revocation status.  Because of the inability of a\n\t   blacklist to return a proper status, we have to map anything other\n\t   than \"revoked\" to \"OK\" */\n\tDATAPTR_SET( certRevInfo->currentRevocation, revocationEntry );\n\treturn( ( revocationEntry->status == CRYPT_OCSPSTATUS_REVOKED ) ? \\\n\t\t\tCRYPT_ERROR_INVALID : CRYPT_OK );\n\t}\n\n/* Check a certificate against a CRL or OCSP response (effectively the same \n   thing, an OCSP response is just a custom CRL) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkCertAgainstCRL( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *crlInfoPtr )\n\t{\n\tCHECKREVOCATIONFUNCTION checkRevocationFunction;\n\tint i, LOOP_ITERATOR, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( crlInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Check that the CRL/OCSP response is a complete signed CRL/response \n\t   and not just a newly-created object */\n\tif( crlInfoPtr->certificate == NULL )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\tcheckRevocationFunction = ( crlInfoPtr->type == CRYPT_CERTTYPE_CRL ) ? \\\n\t\t\t\t\t\t\t  checkRevocationCRL : checkRevocationOCSP;\n\n\t/* Check the base certificate against the CRL/OCSP response.  If it's \n\t   been revoked or there's only a single certificate present, exit */\n\tstatus = checkRevocationFunction( certInfoPtr, crlInfoPtr );\n\tif( cryptStatusError( status ) || \\\n\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )\n\t\treturn( status );\n\n\t/* It's a certificate chain, check every remaining certificate in the \n\t   chain against the CRL/OCSP response.  In theory this is pointless \n\t   because a CRL can only contain information for a single certificate \n\t   in the chain, however the caller may have passed us a CRL for an \n\t   intermediate certificate (in which case the check for the leaf \n\t   certificate was pointless).  In any case it's easier to just do the \n\t   check for all certificates than to determine which certificate the \n\t   CRL applies to so we check for all certificates */\n\tLOOP_EXT( i = 0, i < certInfoPtr->cCertCert->chainEnd, i++, \n\t\t\t  MAX_CHAINLENGTH )\n\t\t{\n\t\tCERT_INFO *certChainInfoPtr;\n\n\t\t/* Check this certificate against the CRL/OCSP response */\n\t\tstatus = krnlAcquireObject( certInfoPtr->cCertCert->chain[ i ],\n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tREQUIRES_OBJECT( sanityCheckCert( certChainInfoPtr ), \n\t\t\t\t\t\t\t certChainInfoPtr->objectHandle );\n\t\t\tstatus = checkRevocationFunction( certChainInfoPtr, crlInfoPtr );\n\t\t\tkrnlReleaseObject( certChainInfoPtr->objectHandle );\n\t\t\t}\n\n\t\t/* If the certificate has been revoked remember which one is the \n\t\t   revoked certificate and exit */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcertInfoPtr->cCertCert->chainPos = i;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( i < MAX_CHAINLENGTH );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCRL( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCRL )\n\t{\n\tCERT_INFO *crlInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( iCryptCRL ) );\n\n\t/* Get the CRL/OCSP response and use it to check the certificate */\n\tstatus = krnlAcquireObject( iCryptCRL, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &crlInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_ARGERROR_VALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES_OBJECT( sanityCheckCert( crlInfoPtr ), \n\t\t\t\t\t crlInfoPtr->objectHandle );\n\tstatus = checkCertAgainstCRL( certInfoPtr, crlInfoPtr );\n\tkrnlReleaseObject( crlInfoPtr->objectHandle );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/write CRL Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read CRL entries:\n\n\tRevokedCert ::= SEQUENCE {\n\t\t\tuserCertificate\t\tCertificalSerialNumber,\n\t\t\trevocationDate\t\tUTCTime,\n\t\t\textensions\t\t\tExtensions OPTIONAL\n\t\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readCRLentry( INOUT STREAM *stream, \n\t\t\t\t  INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t  IN_LENGTH_Z const int entryNo,\n\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tREVOCATION_INFO *currentEntry;\n\tBYTE serialNumber[ MAX_SERIALNO_SIZE + 8 ];\n\tint serialNumberLength, endPos, length, status;\n\ttime_t revocationTime;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( isIntegerRange( entryNo ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Determine the overall size of the entry */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the integer component of the serial number (limited to a sane\n\t   length) and the revocation time */\n\treadInteger( stream, serialNumber, MAX_SERIALNO_SIZE,\n\t\t\t\t &serialNumberLength );\n\tstatus = readUTCTime( stream, &revocationTime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the entry to the revocation information list.  The ID type isn't\n\t   quite an issueAndSerialNumber but the checking code eventually\n\t   converts it into this form using the supplied issuer certificate DN */\n\tstatus = addRevocationEntry( listHeadPtr, &currentEntry,\n\t\t\t\t\t\t\t\t CRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\t\t\t serialNumber, serialNumberLength,\n\t\t\t\t\t\t\t\t ( entryNo > CRL_SORT_LIMIT ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcurrentEntry->revocationTime = revocationTime;\n\n\t/* Read the extensions if there are any present.  Since these are per-\n\t   entry extensions we read the extensions themselves as\n\t   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_CRL to make sure\n\t   that they're processed as required */\n\tif( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )\n\t\t{\n\t\tstatus = readAttributes( stream, &currentEntry->attributes,\n\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, length,\n\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readCRLentries( INOUT STREAM *stream, \n\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tlong length;\n\tint noCrlEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Read the outer wrapper.  Since CRLs can be empty (no certificates \n\t   have been revoked in the time the CRL was issued), we need to use\n\t   readLongGenericHoleZ() rather than readLongSequence() to allow for a \n\t   zero-length SEQUENCE */\n\tstatus = readLongGenericHoleZ( stream, &length, BER_SEQUENCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length == CRYPT_UNUSED )\n\t\t{\n\t\t/* If it's an (invalid) indefinite-length encoding \n\t\t   (readLongSequence() accepts those alongside long lengths so we \n\t\t   have to check for this special-case here) then we can't do \n\t\t   anything with it */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( length <= 0 )\n\t\t{\n\t\t/* It's an empty CRL */\n\t\tDATAPTR_SET_PTR( listHeadPtr, NULL );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The following loop is a bit tricky to failsafe because it's actually \n\t   possible to encounter real-world 100MB CRLs that the failsafe would \n\t   otherwise identify as an error.  Because CRLs can range so far \n\t   outside what would be considered sane we can't really bound the loop \n\t   in any way except at a fairly generic maximum-integer value */\n\tLOOP_MAX( noCrlEntries = 0,\n\t\t\t  length > 0 && noCrlEntries < 10000,\n\t\t\t  noCrlEntries++ )\n\t\t{\n\t\tconst long innerStartPos = stell( stream );\n\n\t\tREQUIRES( isIntegerRangeNZ( innerStartPos ) );\n\n\t\tstatus = readCRLentry( stream, listHeadPtr, noCrlEntries, \n\t\t\t\t\t\t\t   errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength -= stell( stream ) - innerStartPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noCrlEntries >= 10000 )\n\t\t{\n\t\t/* We allow longish CRLs, but one with more than ten thousand \n\t\t   entries has something wrong with it */\n\t\tDEBUG_DIAG(( \"CRL contains more than 10,000 entries\" ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write CRL entries */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofCRLentry( INOUT REVOCATION_INFO *crlEntry )\n\t{\n\tint status;\n\n\tassert( isWritePtr( crlEntry, sizeof( REVOCATION_INFO ) ) );\n\n\t/* Remember the encoded attribute size for later when we write the\n\t   attributes */\n\tstatus = crlEntry->attributeSize = \\\n\t\t\t\t\tsizeofAttributes( crlEntry->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( sizeofShortObject( \\\n\t\t\t\tsizeofInteger( crlEntry->id, crlEntry->idLength ) + \\\n\t\t\t\tsizeofUTCTime() + \\\n\t\t\t\t( ( crlEntry->attributeSize > 0 ) ? \\\n\t\t\t\t\tsizeofShortObject( crlEntry->attributeSize ) : 0 ) ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 2 ) ) \\\nint sizeofCRLentries( IN const DATAPTR crlEntries,\n\t\t\t\t\t  OUT_BOOL BOOLEAN *isV2CRL )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint revocationInfoLength = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( isV2CRL, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( crlEntries ) );\n\n\t/* Clear return value */\n\t*isV2CRL = FALSE;\n\n\tLOOP_MAX( revocationInfo = DATAPTR_GET( crlEntries ), \n\t\t\t  revocationInfo != NULL,\n\t\t\t  revocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tint crlEntrySize;\n\t\t\n\t\tENSURES( sanityCheckRevInfo( revocationInfo ) );\n\n\t\tstatus = crlEntrySize = sizeofCRLentry( revocationInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\trevocationInfoLength += crlEntrySize;\n\n\t\t/* If there are per-entry extensions present then it's a v2 CRL */\n\t\tif( DATAPTR_ISSET( revocationInfo->attributes ) )\n\t\t\t*isV2CRL = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( revocationInfoLength );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCRLentry( INOUT STREAM *stream, \n\t\t\t\t   IN const REVOCATION_INFO *crlEntry )\n\t{\n\tconst int revocationLength = \\\n\t\t\t\tsizeofInteger( crlEntry->id, crlEntry->idLength ) + \\\n\t\t\t\tsizeofUTCTime() + \\\n\t\t\t\t( ( crlEntry->attributeSize > 0 ) ? \\\n\t\t\t\t\tsizeofShortObject( crlEntry->attributeSize ) : 0 );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( crlEntry, sizeof( REVOCATION_INFO ) ) );\n\n\tREQUIRES( sanityCheckRevInfo( crlEntry ) );\n\n\t/* Write the CRL entry */\n\twriteSequence( stream, revocationLength );\n\twriteInteger( stream, crlEntry->id, crlEntry->idLength, DEFAULT_TAG );\n\tstatus = writeUTCTime( stream, crlEntry->revocationTime, DEFAULT_TAG );\n\tif( cryptStatusError( status ) || crlEntry->attributeSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the per-entry extensions.  Since these are per-entry extensions\n\t   rather than overall CRL extensions we write them as CRYPT_CERTTYPE_NONE \n\t   rather than CRYPT_CERTTYPE_CRL to make sure that they're processed as \n\t   required */\n\treturn( writeAttributes( stream, crlEntry->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, crlEntry->attributeSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeCRLentries( INOUT STREAM *stream, \n\t\t\t\t\t IN const DATAPTR crlEntries )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Write the SEQUENCE OF revocation information */\n\tLOOP_MAX( revocationInfo = DATAPTR_GET( crlEntries ), \n\t\t\t  revocationInfo != NULL,\n\t\t\t  revocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tENSURES( sanityCheckRevInfo( revocationInfo ) );\n\n\t\tstatus = writeCRLentry( stream, revocationInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOCSP-specific Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy a revocation list from an OCSP request to a response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRevocationEntries( INOUT_PTR DATAPTR *destListHeadPtr,\n\t\t\t\t\t\t   IN const DATAPTR srcList )\n\t{\n\tconst REVOCATION_INFO *srcListCursor;\n\tREVOCATION_INFO *destListCursor DUMMY_INIT_PTR;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( destListHeadPtr, sizeof( DATAPTR ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcList ) );\n\n\t/* Copy all revocation entries from source to destination */\n\tLOOP_LARGE( srcListCursor = DATAPTR_GET( srcList ), \n\t\t\t\tsrcListCursor != NULL, \n\t\t\t\tsrcListCursor = DATAPTR_GET( srcListCursor->next ) )\n\t\t{\n\t\tREVOCATION_INFO *newElement;\n\n\t\tREQUIRES( sanityCheckRevInfo( srcListCursor ) );\n\n\t\t/* Allocate the new entry and copy the data from the existing one\n\t\t   across.  We don't copy the attributes because there aren't any\n\t\t   that should be carried from request to response */\n\t\tREQUIRES( rangeCheck( srcListCursor->idLength, \n\t\t\t\t\t\t\t  1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( newElement = ( REVOCATION_INFO * ) \\\n\t\t\t\t\tclAlloc( \"copyRevocationEntries\",\n\t\t\t\t\t\t\t sizeof( REVOCATION_INFO ) + \\\n\t\t\t\t\t\t\t\tsrcListCursor->idLength ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tcopyVarStruct( newElement, srcListCursor, REVOCATION_INFO, id );\n\t\tDATAPTR_SET( newElement->attributes, NULL );\n\t\tDATAPTR_SET( newElement->prev, NULL );\n\t\tDATAPTR_SET( newElement->next, NULL );\n\n\t\t/* Set the status to 'unknown' by default, this means that any\n\t\t   entries that we can't do anything with automatically get the\n\t\t   correct status associated with them */\n\t\tnewElement->status = CRYPT_OCSPSTATUS_UNKNOWN;\n\n\t\tENSURES( sanityCheckRevInfo( newElement ) );\n\n\t\t/* Link the new element into the list */\n\t\tinsertDoubleListElement( destListHeadPtr, destListCursor, newElement, \n\t\t\t\t\t\t\t\t REVOCATION_INFO );\n\t\tdestListCursor = newElement;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the entries in an OCSP response object against a certificate store.  \n   The semantics for this one are a bit odd, the source information for the \n   check is from a request but the destination information is in a response.  \n   Since we don't have a copy-and-verify function we do the checking from \n   the response even though technically it's the request data that's being \n   checked */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkOCSPResponse( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE const CRYPT_KEYSET iCryptKeyset )\n\t{\n\tconst CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tREVOCATION_INFO *revocationInfo;\n\tBOOLEAN isRevoked = FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( iCryptKeyset ) );\n\n\t/* Walk down the list of revocation entries fetching status information\n\t   on each one from the certificate store */\n\tLOOP_LARGE( revocationInfo = DATAPTR_GET( certRevInfo->revocations ), \n\t\t\t\trevocationInfo != NULL, \n\t\t\t\trevocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tCRYPT_KEYID_TYPE idType;\n\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\t\tCERT_INFO *crlEntryInfoPtr;\n\t\tconst BYTE *id;\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckRevInfo( revocationInfo ) );\n\t\tREQUIRES( revocationInfo->idType == CRYPT_KEYID_NONE || \\\n\t\t\t\t  revocationInfo->idType == CRYPT_IKEYID_CERTID || \\\n\t\t\t\t  revocationInfo->idType == CRYPT_IKEYID_ISSUERID );\n\n\t\t/* If it's an OCSPv1 ID and there's no alternate ID information \n\t\t   present we can't really do anything with it because the one-way \n\t\t   hashing process required by the standard destroys the certificate\n\t\t   identifying information */\n\t\tif( revocationInfo->idType == CRYPT_KEYID_NONE )\n\t\t\t{\n\t\t\tif( revocationInfo->altIdType == CRYPT_KEYID_NONE )\n\t\t\t\t{\n\t\t\t\trevocationInfo->status = CRYPT_OCSPSTATUS_UNKNOWN;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* There's an alternate ID present, use that instead */\n\t\t\tidType = revocationInfo->altIdType;\n\t\t\tid = revocationInfo->altID;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a usable ID, either a certID or an issuerID */\n\t\t\tidType = revocationInfo->idType;\n\t\t\tid = revocationInfo->id;\n\t\t\t}\n\n\t\t/* Determine the revocation status of the object.  Unfortunately\n\t\t   because of the way OCSP returns status information we can't just\n\t\t   return a yes/no response but have to perform multiple queries to\n\t\t   determine whether a certificate is not revoked, revoked, or \n\t\t   unknown.  Optimising the query strategy is complicated by the \n\t\t   fact that although in theory the most common status will be \n\t\t   not-revoked we could also get a large number of status-unknown \n\t\t   queries, for example if a widely-deployed implementation which is \n\t\t   pointed at a cryptlib-based server gets its ID-hashing wrong and \n\t\t   submits huge numbers of queries with IDs that match no known \n\t\t   certificate.  The best that we can do is assume that a not-\n\t\t   revoked status will be the most common and if that fails fall \n\t\t   back to a revoked status check */\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, idType, id, KEYID_SIZE, \n\t\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_CHECK_ONLY );\n\t\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_GETKEY,\n\t\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* The certificate is present and not revoked/OK, we're done */\n\t\t\trevocationInfo->status = CRYPT_OCSPSTATUS_NOTREVOKED;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* The certificate isn't a currently active one, if it weren't for \n\t\t   the need to return the CRL-based OCSP status values we could just \n\t\t   return not-OK now but as it is we have to differentiate between \n\t\t   revoked and unknown so we perform a second query, this time of \n\t\t   the revocation information */\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, idType, id, KEYID_SIZE, \n\t\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\t\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_GETKEY,\n\t\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_REVOCATIONINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* No revocation information found, status is unknown */\n\t\t\trevocationInfo->status = CRYPT_OCSPSTATUS_UNKNOWN;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* The certificate has been revoked, copy the revocation information \n\t\t   across from the CRL entry.  Error handling here gets a bit \n\t\t   complicated because we're supposed to be a (relatively) reliable \n\t\t   server, in the (highly unlikely) event that the call fails it's \n\t\t   not clear that we should abort the entire operation just because \n\t\t   we can't get the specific details for a single object (we already \n\t\t   know its overall status, which is 'revoked') so we skip reporting\n\t\t   the low-level details if there's a problem and continue */\n\t\tstatus = krnlAcquireObject( getkeyInfo.cryptHandle,\n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &crlEntryInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst REVOCATION_INFO *crlRevocationInfo;\n\n\t\t\tREQUIRES_OBJECT( sanityCheckCert( crlEntryInfoPtr ),\n\t\t\t\t\t\t\t crlEntryInfoPtr->objectHandle );\n\n\t\t\tcrlRevocationInfo = DATAPTR_GET( certRevInfo->revocations );\n\t\t\tif( crlRevocationInfo != NULL )\n\t\t\t\t{\n\t\t\t\trevocationInfo->revocationTime = \\\n\t\t\t\t\t\t\t\t\tcrlRevocationInfo->revocationTime;\n\t\t\t\tif( DATAPTR_ISSET( crlRevocationInfo->attributes ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* We don't check for problems in copying the attributes \n\t\t\t\t\t   since bailing out at this late stage is worse than \n\t\t\t\t\t   missing a few obscure annotations to the revocation */\n\t\t\t\t\t( void ) copyRevocationAttributes( &revocationInfo->attributes,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   crlRevocationInfo->attributes );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tkrnlReleaseObject( crlEntryInfoPtr->objectHandle );\n\t\t\t}\n\t\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\n\t\t/* Record the fact that we've seen at least one revoked certificate */\n\t\trevocationInfo->status = CRYPT_OCSPSTATUS_REVOKED;\n\t\tisRevoked = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If at least one certificate was revoked indicate this to the caller.  \n\t   Note that if there are multiple certificates present in the query then \n\t   it's up to the caller to step through the list to find out which ones \n\t   were revoked */\n\treturn( isRevoked ? CRYPT_ERROR_INVALID : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/write OCSP IDs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write an OCSP certificate ID:\n\n\tCertID ::=\tCHOICE {\n\t\tcertID\t\t\tSEQUENCE {\n\t\t\thashAlgo\tAlgorithmIdentifier,\n\t\t\tiNameHash\tOCTET STRING,\t-- Hash of issuerName\n\t\t\tiKeyHash\tOCTET STRING,\t-- Hash of issuer SPKI w/o tag+len\n\t\t\tserialNo\tINTEGER\n\t\t\t\t},\n\t\tcertificate\t[0]\tEXPLICIT [0] EXPLICIT Certificate,\n\t\tcertIdWithSignature\n\t\t\t\t\t[1]\tEXPLICIT SEQUENCE {\n\t\t\tiAndS\t\tIssuerAndSerialNumber,\n\t\t\ttbsCertHash\tBIT STRING,\n\t\t\tcertSig\t\tSEQUENCE {\n\t\t\t\tsigAlgo\tAlgorithmIdentifier,\n\t\t\t\tsigVal\tBIT STRING\n\t\t\t\t}\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL_RANGE( 0, 1024 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofOcspID( IN const REVOCATION_INFO *ocspEntry )\n\t{\n\tassert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\n\tREQUIRES( ocspEntry->idType == CRYPT_KEYID_NONE );\n\n\t/* For now we don't try and handle anything except the v1 ID since the\n\t   status of v2 is uncertain (it doesn't add anything to v1 except even\n\t   more broken IDs) */\n\treturn( ocspEntry->idLength );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int readOcspID( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_KEYID ) CRYPT_KEYID_TYPE *idType,\n\t\t\t\t\t   OUT_BUFFER( idMaxLen, *idLen ) BYTE *id, \n\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) const int idMaxLen,\n\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( idMaxLen ) int *idLen )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tconst int hashedIDlen = min( idMaxLen, KEYID_SIZE );\n\tint length DUMMY_INIT, tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( idType, sizeof( CRYPT_KEYID_TYPE ) ) );\n\tassert( isWritePtrDynamic( id, idMaxLen ) );\n\tassert( isWritePtr( idLen, sizeof( int ) ) );\n\n\tREQUIRES( idMaxLen >= 16 && idMaxLen < MAX_INTLENGTH_SHORT );\n\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\n\t/* Clear return values */\n\t*idType = CRYPT_KEYID_NONE;\n\tmemset( id, 0, min( 16, idMaxLen ) );\n\t*idLen = 0;\n\n\t/* Read the ID */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( tag )\n\t\t{\n\t\tcase BER_SEQUENCE:\n\t\t\t/* We can't really do anything with v1 IDs since the one-way\n\t\t\t   hashing process destroys any chance of being able to work\n\t\t\t   with them and the fact that no useful certificate information \n\t\t\t   is hashed means that we can't use them to identify a \n\t\t\t   certificate.  As a result the following ID type will always \n\t\t\t   produce a result of \"unknown\" */\n\t\t\t*idType = CRYPT_KEYID_NONE;\n\t\t\tstatus = getStreamObjectLength( stream, &length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( length < 8 )\n\t\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t\tif( length > idMaxLen )\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t*idLen = length;\n\t\t\treturn( sread( stream, id, length ) );\n\n\t\tcase MAKE_CTAG( CTAG_OI_CERTIFICATE ):\n\t\t\t/* Convert the certificate to a certID */\n\t\t\t*idType = CRYPT_IKEYID_CERTID;\n\t\t\t*idLen = hashedIDlen;\n\t\t\treadConstructed( stream, NULL, CTAG_OI_CERTIFICATE );\n\t\t\tstatus = readConstructed( stream, &length, 0 );\n\t\t\tif( cryptStatusOK( status ) && length <= MIN_CRYPT_OBJECTSIZE )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tANALYSER_HINT( dataPtr != NULL );\n\t\t\thashFunctionAtomic( id, hashedIDlen, dataPtr, length );\n\t\t\treturn( readUniversal( stream ) );\n\n\t\tcase MAKE_CTAG( CTAG_OI_CERTIDWITHSIG ):\n\t\t\t/* A bizarro ID dreamed up by Denis Pinkas that manages to carry\n\t\t\t   over all the problems of the v1 ID without being compatible\n\t\t\t   with it.  It's almost as unworkable as the v1 original but we \n\t\t\t   can convert the iAndS to an issuerID and use that */\n\t\t\t*idType = CRYPT_IKEYID_ISSUERID;\n\t\t\t*idLen = hashedIDlen;\n\t\t\treadConstructed( stream, NULL, CTAG_OI_CERTIDWITHSIG );\n\t\t\tstatus = readSequence( stream, NULL );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = getStreamObjectLength( stream, &length );\n\t\t\tif( cryptStatusOK( status ) && length <= 16 )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tANALYSER_HINT( dataPtr != NULL );\n\t\t\thashFunctionAtomic( id, hashedIDlen, dataPtr, length );\n\t\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT );\t/* issuerAndSerialNumber */\n\t\t\treadUniversal( stream );\t\t\t/* tbsCertificateHash */\n\t\t\treturn( readUniversal( stream ) );\t/* certSignature */\n\t\t}\n\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeOcspID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN const REVOCATION_INFO *ocspEntry )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\n\treturn( swrite( stream, ocspEntry->id, ocspEntry->idLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/write OCSP Request\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read OCSP request entries:\n\n\tEntry ::= SEQUENCE {\t\t\t\t-- Request\n\t\tcertID\t\t\tCertID,\n\t\textensions\t[0]\tEXPLICIT Extensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readOcspRequestEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tREVOCATION_INFO *currentEntry;\n\tSTREAM certIdStream;\n\tBYTE idBuffer[ MAX_ID_SIZE + 8 ];\n\tCRYPT_KEYID_TYPE idType;\n\tvoid *certIdPtr;\n\tint endPos, certIdLength, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Determine the overall size of the entry */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the ID information */\n\tstatus = readOcspID( stream, &idType, idBuffer, MAX_ID_SIZE, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the entry to the revocation information list */\n\tstatus = addRevocationEntry( listHeadPtr, &currentEntry, idType,\n\t\t\t\t\t\t\t\t idBuffer, length, FALSE );\n\tif( cryptStatusError( status ) || \\\n\t\tstell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )\n\t\treturn( status );\n\n\t/* Read the extensions.  Since these are per-entry extensions rather \n\t   than overall OCSP extensions we read the wrapper here and read the \n\t   extensions themselves as CRYPT_CERTTYPE_NONE rather than \n\t   CRYPT_CERTTYPE_OCSP to make sure that they're processed as required.  \n\t   Note that these are per-request-entry extensions rather than overall \n\t   per-request extensions so the tag is CTAG_OR_SR_EXTENSIONS rather \n\t   than CTAG_OR_EXTENSIONS */\n\tstatus = readConstructed( stream, &length, CTAG_OR_SR_EXTENSIONS );\n\tif( cryptStatusOK( status ) && length > 0 )\n\t\t{\n\t\tstatus = readAttributes( stream, &currentEntry->attributes,\n\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, length, \n\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* OCSPv1 uses a braindamaged certificate identification method that \n\t   breaks the certificate information up into bits and pieces and hashes \n\t   some while leaving others intact, making it impossible to identify \n\t   the certificate from it.  To try and fix this, if the request \n\t   includes an ESSCertID we use that to make it look like there was a \n\t   proper ID present */\n\tif( currentEntry->idType != CRYPT_KEYID_NONE )\n\t\treturn( CRYPT_OK );\t\t/* Proper ID present, we're done */\n\tattributePtr = findAttribute( currentEntry->attributes, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID, \n\t\t\t\t\t\t\t\t  TRUE );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_OK );\t\t/* No ESSCertID present, can't continue */\n\n\t/* Extract the ID information from the ESSCertID and save it alongside\n\t   the OCSP ID, which we need to retain for use in the response:\n\n\t\tessCertID SEQUENCE {\n\t\t\tcertHash\t\t\tOCTET STRING SIZE(20)\n\t\t\t} */\n\tstatus = getAttributeDataPtr( attributePtr, &certIdPtr, &certIdLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( certIdPtr != NULL );\n\tsMemConnect( &certIdStream, certIdPtr, certIdLength );\n\treadSequence( &certIdStream, NULL );\n\tstatus = readOctetString( &certIdStream, idBuffer, &length, KEYID_SIZE, \n\t\t\t\t\t\t\t  KEYID_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tENSURES( length == KEYID_SIZE );\n\n\t\tcurrentEntry->altIdType = CRYPT_IKEYID_CERTID;\n\t\tREQUIRES( rangeCheck( length, 1, KEYID_SIZE ) );\n\t\tmemcpy( currentEntry->altID, idBuffer, length );\n\t\t}\n\tsMemDisconnect( &certIdStream );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readOcspRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint length, noRequestEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Read the outer wrapper */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SEQUENCE OF request information */\n\tLOOP_LARGE( noRequestEntries = 0,\n\t\t\t\tlength > 0 && noRequestEntries < 100,\n\t\t\t\tnoRequestEntries++ )\n\t\t{\n\t\tconst int innerStartPos = stell( stream );\n\n\t\tREQUIRES( isIntegerRangeNZ( innerStartPos ) );\n\n\t\tstatus = readOcspRequestEntry( stream, listHeadPtr,\n\t\t\t\t\t\t\t\t\t   errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength -= stell( stream ) - innerStartPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noRequestEntries >= 100 )\n\t\t{\n\t\t/* We allow reasonable numbers of entries in a request, but one with \n\t\t   more than a hundred entries has something wrong with it */\n\t\tDEBUG_DIAG(( \"OCSP request contains more than 100 entries\" ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write OCSP request entries */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofOcspRequestEntry( INOUT REVOCATION_INFO *ocspEntry )\n\t{\n\tint ocspIDsize, attributeSize = 0, status;\n\n\tassert( isWritePtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\t\n\tREQUIRES( ocspEntry->idType == CRYPT_KEYID_NONE );\n\n\t/* Get the OCSP ID size */\n\tstatus = ocspIDsize = sizeofOcspID( ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Remember the encoded attribute size for later when we write the\n\t   attributes */\n\tstatus = \\\n\t\tocspEntry->attributeSize = sizeofAttributes( ocspEntry->attributes,\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ocspEntry->attributeSize > 0 )\n\t\t{\n\t\tattributeSize = sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofShortObject( ocspEntry->attributeSize ) );\n\t\t}\n\n\treturn( sizeofShortObject( ocspIDsize + attributeSize ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofOcspRequestEntries( IN const DATAPTR ocspEntries )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint requestInfoLength = 0, status, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISVALID( ocspEntries ) );\n\n\t/* Determine how big the encoded OCSP request will be */\n\tLOOP_LARGE( revocationInfo = DATAPTR_GET( ocspEntries ), \n\t\t\t\trevocationInfo != NULL,\n\t\t\t\trevocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tint requestEntrySize;\n\n\t\tREQUIRES( sanityCheckRevInfo( revocationInfo ) );\n\t\t\n\t\tstatus = requestEntrySize = \\\n\t\t\t\t\t\tsizeofOcspRequestEntry( revocationInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\trequestInfoLength += requestEntrySize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( requestInfoLength );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeOcspRequestEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  IN const REVOCATION_INFO *ocspEntry )\n\t{\n\tint ocspIDsize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\n\t/* Get the OCSP ID size */\n\tstatus = ocspIDsize = sizeofOcspID( ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are no attributes, we just write the ID */\n\tif( ocspEntry->attributeSize <= 0 )\n\t\t{\n\t\twriteSequence( stream, ocspIDsize );\n\t\treturn( writeOcspID( stream, ocspEntry ) );\n\t\t}\n\n\t/* Write the header and ID information */\n\twriteSequence( stream, \n\t\t\t\t   ocspIDsize + sizeofShortObject( \\\n\t\t\t\t\t\t\t\t\tsizeofShortObject( ocspEntry->attributeSize ) ) );\n\tstatus = writeOcspID( stream, ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the per-entry extensions.  Since these are per-entry extensions \n\t   rather than overall OCSP extensions we write them as \n\t   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_OCSP to make sure that \n\t   they're processed as required.  Note that these are per-request-entry \n\t   extensions rather than overall per-request extensions so the tag is \n\t   CTAG_OR_SR_EXTENSIONS rather than CTAG_OR_EXTENSIONS */\n\tstatus = writeConstructed( stream, \n\t\t\t\t\t\t\t   sizeofObject( ocspEntry->attributeSize ), \n\t\t\t\t\t\t\t   CTAG_OR_SR_EXTENSIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAttributes( stream, ocspEntry->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_NONE, \n\t\t\t\t\t\t\t\t  ocspEntry->attributeSize );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOcspRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN const DATAPTR ocspEntries )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Write the SEQUENCE OF validity information */\n\tLOOP_LARGE( revocationInfo = DATAPTR_GET( ocspEntries ), \n\t\t\t\trevocationInfo != NULL,\n\t\t\t\trevocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckRevInfo( revocationInfo ) );\n\n\t\tstatus = writeOcspRequestEntry( stream, revocationInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/write OCSP Responses\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read OCSP response entries:\n\n\tEntry ::= SEQUENCE {\n\t\tcertID\t\t\tCertID,\n\t\tcertStatus\t\tCHOICE {\n\t\t\tnotRevd\t[0]\tIMPLICIT NULL,\n\t\t\trevd\t[1]\tSEQUENCE {\n\t\t\t\trevTime\tGeneralizedTime,\n\t\t\t\trevReas\t[0] EXPLICIT CRLReason Optional\n\t\t\t\t\t\t\t},\n\t\t\tunknown\t[2] IMPLICIT NULL\n\t\t\t\t\t\t},\n\t\tthisUpdate\t\tGeneralizedTime,\n\t\tnextUpdate\t[0]\tEXPLICIT GeneralizedTime OPTIONAL,\n\t\textensions\t[1]\tEXPLICIT Extensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int readOcspResponseEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tREVOCATION_INFO *currentEntry;\n\tBYTE idBuffer[ MAX_ID_SIZE + 8 ];\n\tCRYPT_KEYID_TYPE idType;\n\ttime_t dummyTime;\n\tint endPos, length, crlReason = 0, tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Determine the overall size of the entry */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the ID information */\n\tstatus = readOcspID( stream, &idType, idBuffer, MAX_ID_SIZE, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're reading an OCSPv1 ID then the ability to recover any useful \n\t   elements in it apart from the serial number has been destroyed by \n\t   passing them through a one-way hash function, so we dig down into the\n\t   ID to extract just the serial number.  See the comment in \n\t   checkRevocationOCSP() on the implications of this */\n\tif( idType == CRYPT_KEYID_NONE )\n\t\t{\n\t\tSTREAM memStream;\n\t\tBYTE integer[ MAX_SERIALNO_SIZE + 8 ];\n\t\tint integerLength DUMMY_INIT;\n\n\t\tstatic_assert( MAX_SERIALNO_SIZE <= MAX_ID_SIZE, \"Buffer size\" );\n\n\t\t/* Dig down into the ID to extract the serial number and replace the\n\t\t   overall ID with that */\n\t\tsMemConnect( &memStream, idBuffer, length );\n\t\treadSequence( &memStream, NULL );\n\t\treadUniversal( &memStream );\t\t\t/* AlgoID */\n\t\treadUniversal( &memStream );\t\t\t/* Hashed issuer DN */\n\t\tstatus = readUniversal( &memStream );\t/* Hashed partial issuer key */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readInteger( &memStream, integer, MAX_SERIALNO_SIZE, \n\t\t\t\t\t\t\t\t  &integerLength );\n\t\t\t}\n\t\tsMemDisconnect( &memStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( integerLength <= 0 )\n\t\t\t{\n\t\t\t/* Some certificates may have a serial number of zero, which is \n\t\t\t   turned into a zero-length integer by the ASN.1 read code \n\t\t\t   since it truncates leading zeroes that are added due to ASN.1 \n\t\t\t   encoding requirements.  If we get a zero-length integer we \n\t\t\t   turn it into a single zero byte */\n\t\t\tidBuffer[ 0 ] = 0;\n\t\t\tlength = 1;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( integerLength, 1, MAX_ID_SIZE ) );\n\t\t\tmemcpy( idBuffer, integer, integerLength );\n\t\t\tlength = integerLength;\n\t\t\t}\n\t\t}\n\n\t/* Add the entry to the revocation information list */\n\tstatus = addRevocationEntry( listHeadPtr, &currentEntry, idType,\n\t\t\t\t\t\t\t\t idBuffer, length, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the status information */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( tag )\n\t\t{\n\t\tcase MAKE_CTAG_PRIMITIVE( OCSP_STATUS_NOTREVOKED ):\n\t\t\tcurrentEntry->status = CRYPT_OCSPSTATUS_NOTREVOKED;\n\t\t\tstatus = readUniversal( stream );\n\t\t\tbreak;\n\n\t\tcase MAKE_CTAG( OCSP_STATUS_REVOKED ):\n\t\t\tcurrentEntry->status = CRYPT_OCSPSTATUS_REVOKED;\n\t\t\treadConstructed( stream, NULL, OCSP_STATUS_REVOKED );\n\t\t\tstatus = readGeneralizedTime( stream, \n\t\t\t\t\t\t\t\t\t\t  &currentEntry->revocationTime );\n\t\t\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\t\ttag == MAKE_CTAG( 0 ) )\n\t\t\t\t{\n\t\t\t\t/* Remember the crlReason for later */\n\t\t\t\treadConstructed( stream, NULL, 0 );\n\t\t\t\tstatus = readEnumerated( stream, &crlReason );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MAKE_CTAG_PRIMITIVE( OCSP_STATUS_UNKNOWN ):\n\t\t\tcurrentEntry->status = CRYPT_OCSPSTATUS_UNKNOWN;\n\t\t\tstatus = readUniversal( stream );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readGeneralizedTime( stream, &dummyTime );\t/* thisUpdate */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\treadConstructed( stream, NULL, 0 );\t\t\t\t/* nextUpdate */\n\t\tstatus = readGeneralizedTime( stream, &dummyTime );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the extensions if there are any present.  Since these are per-\n\t   entry extensions rather than overall OCSP extensions we read the \n\t   wrapper here and read the extensions themselves as CRYPT_CERTTYPE_NONE \n\t   rather than CRYPT_CERTTYPE_OCSP to make sure that they're processed \n\t   as required */\n\tif( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )\n\t\t{\n\t\tstatus = readConstructed( stream, &length, CTAG_OP_EXTENSIONS );\n\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t{\n\t\t\tstatus = readAttributes( stream, &currentEntry->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, length,\n\t\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's a crlReason present in the response and none as an\n\t   extension add it as an extension (OCSP allows the same information\n\t   to be specified in two different places, to make it easier we always\n\t   return it as a crlReason extension, however some implementations\n\t   return it in both places so we have to make sure that we don't try and\n\t   add it a second time) */\n\tattributePtr = findAttributeField( currentEntry->attributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t{\n\t\tstatus = addAttributeField( &currentEntry->attributes,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CRLREASON, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, crlReason, 0,\n\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readOcspResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint length, noResponseEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Read the outer wrapper */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SEQUENCE OF response information */\n\tLOOP_LARGE( noResponseEntries = 0,\n\t\t\t\tlength > 0 && noResponseEntries < 100,\n\t\t\t\tnoResponseEntries++ )\n\t\t{\n\t\tconst int innerStartPos = stell( stream );\n\n\t\tREQUIRES( isIntegerRangeNZ( innerStartPos ) );\n\n\t\tstatus = readOcspResponseEntry( stream, listHeadPtr,\n\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength -= stell( stream ) - innerStartPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noResponseEntries >= 100 )\n\t\t{\n\t\t/* We allow reasonable numbers of entries in a response, but one with \n\t\t   more than a hundred entries has something wrong with it */\n\t\tDEBUG_DIAG(( \"OCSP response contains more than 100 entries\" ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write OCSP response entries */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofOcspResponseEntry( INOUT REVOCATION_INFO *ocspEntry )\n\t{\n\tint ocspIDsize, certStatusSize = 0, attributeSize = 0, status;\n\n\tassert( isWritePtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\t\n\t/* Get the OCSP ID size */\n\tstatus = ocspIDsize = sizeofOcspID( ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Remember the encoded attribute size for later when we write the\n\t   attributes */\n\tstatus = ocspEntry->attributeSize = \\\n\t\t\t\t\tsizeofAttributes( ocspEntry->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ocspEntry->attributeSize > 0 )\n\t\tattributeSize = sizeofShortObject( ocspEntry->attributeSize );\n\n\t/* Determine the size of the certificate status field */\n\tcertStatusSize = ( ocspEntry->status != CRYPT_OCSPSTATUS_REVOKED ) ? \\\n\t\t\t\t\t sizeofNull() : sizeofShortObject( sizeofGeneralizedTime() );\n\n\treturn( sizeofShortObject( ocspIDsize + certStatusSize + \\\n\t\t\t\t\t\t\t   sizeofGeneralizedTime() + attributeSize ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofOcspResponseEntries( IN const DATAPTR ocspEntries )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint responseInfoLength = 0, status, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISVALID( ocspEntries ) );\n\n\t/* Determine how big the encoded OCSP response will be */\n\tLOOP_LARGE( revocationInfo = DATAPTR_GET( ocspEntries ), \n\t\t\t\trevocationInfo != NULL,\n\t\t\t\trevocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tint responseEntrySize;\n\n\t\tREQUIRES( sanityCheckRevInfo( revocationInfo ) );\n\t\t\n\t\tstatus = responseEntrySize = \\\n\t\t\t\t\t\tsizeofOcspResponseEntry( revocationInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tresponseInfoLength += responseEntrySize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( responseInfoLength );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeOcspResponseEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN const REVOCATION_INFO *ocspEntry,\n\t\t\t\t\t\t\t\t   const time_t entryTime )\n\t{\n\tint ocspIDsize, certStatusSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( ocspEntry, sizeof( REVOCATION_INFO ) ) );\n\n\t/* Get the OCSP ID size */\n\tstatus = ocspIDsize = sizeofOcspID( ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine the size of the certificate status field */\n\tcertStatusSize = ( ocspEntry->status != CRYPT_OCSPSTATUS_REVOKED ) ? \\\n\t\t\t\t\t sizeofNull() : sizeofShortObject( sizeofGeneralizedTime() );\n\n\t/* Write the header and ID information */\n\twriteSequence( stream, ocspIDsize + \\\n\t\t\t\t   certStatusSize + sizeofGeneralizedTime() + \\\n\t\t\t\t   ( ( ocspEntry->attributeSize > 0 ) ? \\\n\t\t\t\t\t\tsizeofShortObject( ocspEntry->attributeSize ) : 0 ) );\n\tstatus = writeOcspID( stream, ocspEntry );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the certificate status */\n\tif( ocspEntry->status == CRYPT_OCSPSTATUS_REVOKED )\n\t\t{\n\t\twriteConstructed( stream, sizeofGeneralizedTime(),\n\t\t\t\t\t\t  CRYPT_OCSPSTATUS_REVOKED );\n\t\tstatus = writeGeneralizedTime( stream, ocspEntry->revocationTime,\n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\telse\n\t\t{\n\t\t/* An other-than-revoked status is communicated as a tagged NULL\n\t\t   value.  For no known reason this portion of OCSP uses implicit\n\t\t   tagging, since it's the one part of the PDU in which an\n\t\t   explicit tag would actually make sense */\n\t\tstatus = writeNull( stream, ocspEntry->status );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the current update time, which should be the current time.\n\t   Since new status information is always available we don't write a\n\t   nextUpdate time (in fact there is some disagreement over whether \n\t   these times are based on CRL information, responder information, the \n\t   response dispatch time, or a mixture of the above, implementations \n\t   can be found that return all manner of peculiar values here) */\n\tstatus = writeGeneralizedTime( stream, entryTime, DEFAULT_TAG );\n\tif( cryptStatusError( status ) || ocspEntry->attributeSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the per-entry extensions.  Since these are per-entry extensions\n\t   rather than overall OCSP extensions we write them as \n\t   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_OCSP to make sure that \n\t   they're processed as required */\n\treturn( writeAttributes( stream, ocspEntry->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, ocspEntry->attributeSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOcspResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN const DATAPTR ocspEntries,\n\t\t\t\t\t\t\t  const time_t entryTime )\n\t{\n\tREVOCATION_INFO *revocationInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Write the SEQUENCE OF validity information */\n\tLOOP_LARGE( revocationInfo = DATAPTR_GET( ocspEntries ), \n\t\t\t\trevocationInfo != NULL,\n\t\t\t\trevocationInfo = DATAPTR_GET( revocationInfo->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckRevInfo( revocationInfo ) );\n\n\t\tstatus = writeOcspResponseEntry( stream, revocationInfo, \n\t\t\t\t\t\t\t\t\t\t entryTime );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n#endif /* USE_CERTREV */\n"
  },
  {
    "path": "deps/cl345/cert/certschk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Signature Checking Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n#else\n  #include \"cert/cert.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\n/* Generate an issuerID, a SHA-1 hash of the issuerAndSerialNumber needed \n   when storing/retrieving a certificate to/from a database keyset, which \n   can't handle the awkward heirarchical IDs usually used in certificates.  \n   This is created by encoding the DN and serial number and hashing it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int generateCertID( IN_BUFFER( dnLength ) const void *dn, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int dnLength,\n\t\t\t\t\t\t   IN_BUFFER( serialNumberLength ) \\\n\t\t\t\t\t\t\t\tconst void *serialNumber,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int serialNumberLength, \n\t\t\t\t\t\t   OUT_BUFFER_FIXED_C( KEYID_SIZE ) BYTE *certID, \n\t\t\t\t\t\t   IN_LENGTH_FIXED( KEYID_SIZE ) const int certIdLength )\n\t{\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tSTREAM stream;\n\tBYTE buffer[ MAX_SERIALNO_SIZE + 8 + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( dn, dnLength ) );\n\tassert( isReadPtrDynamic( serialNumber, serialNumberLength ) );\n\tassert( isWritePtr( certID, certIdLength ) );\n\n\tREQUIRES( serialNumberLength > 0 && \\\n\t\t\t  serialNumberLength <= MAX_SERIALNO_SIZE );\n\tREQUIRES( certIdLength == KEYID_SIZE );\n\n\t/* Clear return value */\n\tmemset( certID, 0, min( 16, certIdLength ) );\n\n\t/* Get the hash algorithm information */\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, NULL );\n\n\t/* Write the relevant information to a buffer and hash the data to get\n\t   the ID:\n\n\t\tSEQUENCE {\n\t\t\tissuer\t\tDN,\n\t\t\tserial\t\tINTEGER\n\t\t\t} */\n\tsMemOpen( &stream, buffer, MAX_SERIALNO_SIZE + 8 );\n\tstatus = writeSequence( &stream, \n\t\t\t\t\t\t\tdnLength + sizeofInteger( serialNumber, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t  serialNumberLength ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\thashFunction( hashInfo, NULL, 0, buffer, stell( &stream ), \n\t\t\t\t  HASH_STATE_START );\n\thashFunction( hashInfo, NULL, 0, dn, dnLength, HASH_STATE_CONTINUE );\n\tsseek( &stream, 0 );\n\tstatus = writeInteger( &stream, serialNumber, serialNumberLength,\n\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thashFunction( hashInfo, certID, certIdLength, buffer, \n\t\t\t\t\t  stell( &stream ), HASH_STATE_END );\n\t\t}\n\tsMemClose( &stream );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tValidity/Revocation Checking \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\n/* Check a certificate using an RTCS or OCSP responder */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkResponder( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_SESSION iCryptSession )\n\t{\n\tCRYPT_CERTIFICATE cryptResponse DUMMY_INIT;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint sessionType, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptSession) );\n\n\tstatus = krnlSendMessage( iCryptSession, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &sessionType, CRYPT_IATTRIBUTE_SUBTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( ( sessionType == SUBTYPE_SESSION_RTCS ) || \\\n\t\t\t  ( sessionType == SUBTYPE_SESSION_OCSP ) );\n\n\t/* Create the request, add the certificate, and add the request to the\n\t   session */\n\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t    ( sessionType == SUBTYPE_SESSION_RTCS ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_RTCS_REQUEST : \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_OCSP_REQUEST );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t&certInfoPtr->objectHandle, CRYPT_CERTINFO_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t&createInfo.cryptHandle, CRYPT_SESSINFO_REQUEST );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_SETATTRIBUTE\" );\n\n\t/* Activate the session and get the response information.  Since the \n\t   session activation can take a fair amount of time, we re-verify the\n\t   certificate object data after it's completed */\n\tstatus = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_SESSINFO_ACTIVE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptSession, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &cryptResponse, CRYPT_SESSINFO_RESPONSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"activateSession\" );\n\tif( sessionType == SUBTYPE_SESSION_RTCS )\n\t\t{\n\t\tint certStatus;\n\n\t\tstatus = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &certStatus, CRYPT_CERTINFO_CERTSTATUS );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( certStatus != CRYPT_CERTSTATUS_VALID ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\telse\n\t\t{\n\t\tint revocationStatus;\n\n\t\tstatus = krnlSendMessage( cryptResponse, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &revocationStatus,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_REVOCATIONSTATUS );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( revocationStatus != CRYPT_OCSPSTATUS_NOTREVOKED ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\tkrnlSendNotifier( cryptResponse, IMESSAGE_DECREFCOUNT );\n\tENSURES( sanityCheckCert( certInfoPtr ) );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_SETATTRIBUTE\", \"activateSession\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE\" ) );\n\n\treturn( status );\n\t}\n\n/* Check a certificate against a CRL stored in a keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkKeyset( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_SESSION iCryptKeyset )\n\t{\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tBYTE issuerID[ KEYID_SIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( isHandleRangeValid( iCryptKeyset ) );\n\n\t/* Generate the issuerID for the certificate */\n\tstatus = generateCertID( certInfoPtr->issuerDNptr,\n\t\t\t\t\t\t\t certInfoPtr->issuerDNsize,\n\t\t\t\t\t\t\t certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t certInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t\t\t\t issuerID, KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"generateCertID\" );\n\t\n\t/* Check whether the object with this issuerID is present in the CRL.  \n\t   Since all that we're interested in is a yes/no answer we tell the \n\t   keyset to perform a check only */\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_ISSUERID, issuerID, \n\t\t\t\t\t\t   KEYID_SIZE, NULL, 0, KEYMGMT_FLAG_CHECK_ONLY );\n\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_GETKEY,\n\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_REVOCATIONINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The certificate is present in the blacklist so it's an invalid\n\t\t   certificate */\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* Some type of error other than the certificate not being present \n\t\t   in the blacklist occurred */\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_KEY_GETKEY\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"generateCertID\", \"IMESSAGE_KEY_GETKEY\" ) );\n\n\t/* The certificate isn't present in the blacklist so it's not revoked \n\t   (although not necessarily valid either) */\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSignature Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a certificate object against a signing certificate object, \n   typically a certificate against an issuer certificate but also a self-\n   signed object like a certificate request against itself.  The flags are\n   as follows:\n\n\ttrustAnchorCheck: Used when we're checking an explicit trust anchor, for \n\t\t\twhich we only need to check the signature if it's self-signed.  \n\n\tshortCircuitCheck: Used when checking subject:issuer pairs inside \n\t\t\tcertificate chains, which have already been checked by the \n\t\t\tchain-handling code so a full (re-)check isn't necessary any \n\t\t\tmore.\n\n\tbasicCheckDone: Used if checkCertBasic() has already been done by the \n\t\t\tcaller (if we're coming from the certificate-chain code then \n\t\t\twe're processing a certificate in the middle of the chain and it \n\t\t\thasn't been done yet, if we're coming from the standalone \n\t\t\tcertificate-checking code then it's already been done) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 8, 9 ) ) \\\nint checkCertDetails( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t  INOUT_OPT CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerPubKey,\n\t\t\t\t\t  IN_OPT const X509SIG_FORMATINFO *formatInfo,\n\t\t\t\t\t  const BOOLEAN trustAnchorCheck,\n\t\t\t\t\t  const BOOLEAN shortCircuitCheck,\n\t\t\t\t\t  const BOOLEAN basicCheckDone,\n\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisWritePtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( formatInfo == NULL || \\\n\t\t\tisReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( ( subjectCertInfoPtr->type > CRYPT_CERTTYPE_NONE && \\\n\t\t\t\tsubjectCertInfoPtr->type <= CRYPT_CERTTYPE_CRL ) || \\\n\t\t\t  subjectCertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tREQUIRES( issuerCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( iIssuerPubKey == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iIssuerPubKey ) );\n\tREQUIRES( trustAnchorCheck == TRUE || trustAnchorCheck == FALSE );\n\tREQUIRES( shortCircuitCheck == TRUE || shortCircuitCheck == FALSE );\n\tREQUIRES( basicCheckDone == TRUE || basicCheckDone == FALSE );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Perform a basic check for obvious invalidity issues if required */\n\tif( !basicCheckDone && \\\n\t\t( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t  subjectCertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t  subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t{\n\t\tstatus = checkCertBasic( subjectCertInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkCertBasic\" );\n\n\t/* If there's an issuer certificate present check the validity of the\n\t   subject certificate based on it.  If it's not present all that we can \n\t   do is perform a pure signature check with the context */\n\tif( issuerCertInfoPtr != NULL )\n\t\t{\n\t\tstatus = checkCert( subjectCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\tshortCircuitCheck, errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkCert\" );\n\n\t/* If the signature has already been checked or there's no signature-\n\t   check key present then we're done.  The latter can occur when we're \n\t   checking a data-only certificate in a certificate chain.  This is \n\t   safe because these certificates can only occur when we're reading \n\t   them from an (implicitly trusted) private key store */\n\tif( TEST_FLAG( subjectCertInfoPtr->flags, CERT_FLAG_SIGCHECKED ) || \\\n\t\tiIssuerPubKey == CRYPT_UNUSED )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"checkCertBasic\", \"checkCert\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're checking an explicit trust anchor and the certificate isn't \n\t   self-signed then there's nothing further left to check */\n\tif( trustAnchorCheck && issuerCertInfoPtr != NULL && \\\n\t\t!TEST_FLAG( issuerCertInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"checkCertBasic\", \"checkCert\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're performing a standard check and it's an explicitly-trusted \n\t   certificate then we're done.  If we're performing a check of a \n\t   certificate chain then the chain-handling code will have performed \n\t   its own handling of trusted certificates/trust anchors so we don't \n\t   peform a second check here */\n\tif( !shortCircuitCheck )\n\t\t{\n\t\tstatus = krnlSendMessage( subjectCertInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT,\n\t\t\t\t\t\t\t\t  &subjectCertInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_CHECK );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_USER_TRUSTMGMT\" );\n\n\t/* If it's an intermediate or leaf certificate and it's not a v3\n\t   certificate, reject it.  This is a peculiar requirement added in RFC \n\t   5280, buried in the 19-page path processing description, that \n\t   \"Conforming implementations may choose to reject all version 1 and \n\t   version 2 intermediate certificates\".  Presumably the purpose of this\n\t   is to deal with the absence of a basicConstraints extension that \n\t   identifies the certificate as a CA certificate, but in that case the\n\t   certificate will be rejected anyway, and since it's DEFAULT FALSE a\n\t   leaf certificate doesn't need it.  Since there's no point to this \n\t   check, our conforming implementation chooses not to reject \n\t   certificates based on it */\n#if defined( USE_CERTLEVEL_PKIX_FULL ) && 0\n\tif( !trustAnchorCheck && subjectCertInfoPtr->version < 3 )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_VERSION, CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Check the signature on the certificate.  If there's a problem with \n\t   the issuer's public key then it'll be reported as a \n\t   CRYPT_ARGERROR_NUM1, which the caller has to convert into an \n\t   appropriate error code */\n\tstatus = checkX509signature( subjectCertInfoPtr->certificate, \n\t\t\t\t\t\t\t\t subjectCertInfoPtr->certificateSize,\n\t\t\t\t\t\t\t\t iIssuerPubKey, formatInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE subjectIssuerID[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tBYTE issuerSubjectID[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tint subjectIDlength, issuerIDlength;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t\t/* There's one special-case situation in which we can get a \n\t\t   signature-check failure that looks like data corruption and \n\t\t   that's when a CA quietly changes its issuing key without changing \n\t\t   anything else so that the certificates chain but the signature \n\t\t   check produces garbage as output due to the use of the incorrect \n\t\t   key.  Although it could be argued that a CA that does this is \n\t\t   broken, we try and accomodate it by performing a backup check \n\t\t   using keyIDs if the signature check produces garbled output.  \n\t\t   Because of the complete chaos present in keyIDs we can't do this \n\t\t   by default (it would result in far too many false positives) but \n\t\t   it's safe as a fallback at this point since we're about to report \n\t\t   an error anyway and the worst that can happen is that we return \n\t\t   a slightly inappropriate error message.\n\t\t   \n\t\t   If there's no issuer certificate provided then we also have to \n\t\t   exit at this point because we can't go any further without it */\n\t\tif( status != CRYPT_ERROR_BADDATA || issuerCertInfoPtr == NULL )\n\t\t\treturn( status );\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t\t/* Get the subject certificate's issuerID and the issuer \n\t\t   certificate's subjectID.  We don't bother with the alternative \n\t\t   awkward DN-based ID since what we're really interested in is the \n\t\t   ID of the signing key and it's not worth the extra pain of dealing \n\t\t   with these awkward cert IDs just to try and fix up a slight \n\t\t   difference in error codes.  Since the overall error status at this \n\t\t   point is CRYPT_ERROR_BADDATA (see the status-code check above) we \n\t\t   return that instead of any ephemeral status values returned from \n\t\t   further function calls */\n\t\tsetMessageData( &msgData, subjectIssuerID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( subjectCertInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tissuerIDlength = msgData.length;\n\t\tsetMessageData( &msgData, issuerSubjectID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( issuerCertInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tsubjectIDlength = msgData.length;\n\n\t\t/* If the keyIDs don't match then it's a signature error due to \n\t\t   false-positive chaining rather than a data corruption error */\n\t\tif( ( issuerIDlength != subjectIDlength ) || \\\n\t\t\tmemcmp( subjectIssuerID, issuerSubjectID, issuerIDlength ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Signature check failed due to mismatched key in \"\n\t\t\t\t\t\t \"CA certificate\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_SIGNATURE );\n\t\t\t}\n\n\t\treturn( CRYPT_ERROR_BADDATA );\n#else\n\t\treturn( status );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkX509signature\" );\n\n\t/* The signature is OK, we don't need to check it again.  There is a\n\t   theoretical situation where this can lead to a false positive which \n\t   requires first checking the certificate using the correct issuing CA \n\t   (which will set the CERT_FLAG_SIGCHECKED flag) and then checking it \n\t   again using a second CA certificate identical to the first but with a \n\t   different key.  In other words the issuer DN chains correctly but the \n\t   issuer key is different.  The appropriate behaviour here is somewhat \n\t   unclear, it could be argued that a CA that uses two otherwise \n\t   identical certificates but with different keys is broken and therefore \n\t   behaviour in this situation is undefined.  However we need to do \n\t   something and returning the result of the check with the correct CA \n\t   certificate even if we're later passed a second incorrect certificate \n\t   from the CA seems to be the most appropriate action since it has in \n\t   the past been validated by a certificate from the same CA.  If we want \n\t   to force the check to be done with a specific CA key (rather than just \n\t   the issuing CA's certificate in general) we could store the \n\t   fingerprint of the signing key alongside the CERT_FLAG_SIGCHECKED \n\t   flag */\n\tSET_FLAG( subjectCertInfoPtr->flags, CERT_FLAG_SIGCHECKED );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"checkCertBasic\", \"checkCert\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_USER_TRUSTMGMT\", \n\t\t\t\t\t\t\t\t\t\"checkX509signature\" ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Check a self-signed certificate object like a certificate request or a \n   self-signed certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkSelfSignedCert( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tIN_OPT const X509SIG_FORMATINFO *formatInfo )\n\t{\n\tCRYPT_CONTEXT iCryptContext = CRYPT_UNUSED;\n\tCERT_INFO *issuerCertInfoPtr;\n\tBOOLEAN trustedCertAcquired = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( formatInfo == NULL || \\\n\t\t\tisReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );\n\n\t/* Perform a basic check for obvious invalidity issues */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tstatus = checkCertBasic( certInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkCertBasic\" );\n\n\t/* Since there's no signer certificate provided it has to be either \n\t   explicitly self-signed or signed by a trusted certificate */\n\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR )\n\t\t\tiCryptContext = certInfoPtr->iPubkeyContext;\n\t\tissuerCertInfoPtr = certInfoPtr;\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_CERTIFICATE iCryptCert = certInfoPtr->objectHandle;\n\n\t\t/* If it's a certificate then it may be implicitly trusted */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT, &iCryptCert,\n\t\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_CHECK );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"checkCertBasic\" ) );\n\n\t\t\t\t/* The certificate is implicitly trusted, we're done */\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* If it's not self-signed then it has to be signed by a trusted \n\t\t   certificate, try and get the trusted certificate */\n\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT, &iCryptCert,\n\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_GETISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* There's no trusted signer present, indicate that we need\n\t\t\t   something to check the certificate with */\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t}\n\t\tstatus = krnlAcquireObject( iCryptCert, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\t\tENSURES_OBJECT( sanityCheckCert( issuerCertInfoPtr ),\n\t\t\t\t\t\tissuerCertInfoPtr->objectHandle );\n\t\tiCryptContext = iCryptCert;\n\t\ttrustedCertAcquired = TRUE;\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_USER_TRUSTMGMT\" );\n\n\t/* Check the certificate against the issuing certificate */\n\tstatus = checkCertDetails( certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t   iCryptContext, formatInfo, FALSE, FALSE, \n\t\t\t\t\t\t\t   TRUE, &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t   &certInfoPtr->errorType );\n\tif( trustedCertAcquired == TRUE )\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_OBJECT : status );\n\tCFI_CHECK_UPDATE( \"checkCertDetails\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"checkCertBasic\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_USER_TRUSTMGMT\", \n\t\t\t\t\t\t\t\t\t\"checkCertDetails\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tGeneral Certificate Validity Checking Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the validity of a certificate object against another object, \n   typically an issuing key or certificate but also a CRL or RTCS/OCSP\n   session.\n\n   Working with certificate chains is different from working with any other \n   type of certificate object because of the presence of multiple \n   certificates in both the item to be checked (the left-hand argument) and \n   the item to use for the checking (the right-hand argument).  Consider the \n   following combinations of objects that we could encounter in terms of \n   verification:\n\n\tLeft\t\tRight\t\tOK\t\tConfiguration\tComment\n\t----\t\t-----\t\t--\t\t-------------\t---------------------\n\tLeaf\t\tIssuer\t\t Y\t\tL: A\t\t\tStandard cert\n\t\t\t\t\t\t\t\t\tR:\t   B\n\n\tChain\t\t-\t\t\t Y\t\tL: A - B - C\tiSigCheckObject = CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tR: -\t\t\tcheck chain\n\n\tChain\t\tRoot\t\t Y\t\tL: A - B - C\tType == chain\n\t\t\t\t\t\t\t\t\tR:\t\t   C\tcheckObjectType == cert\n\n\tLeaf\t\tChain\t\t N\t\tL: A\t\t\tOverlap between checked object \n\t\t\t\t\t\t\t\t\tR: A - B - C\tand checking object, see long\n\t\t\t\t\t\t\t\t\t\t\t\t\tcomment below.\n\n\tLeaf\t\tChain - Lf.\t Y\t\tL: A\t\t\tSee long comment below.\n\t\t\t\t\t\t\t\t\tR:\t   B - C\t(Sent by gnutls for SSL)\n\n\tChain - Rt.\tRoot\t\t Y\t\tL: A - B\t\tType == chain,\n\t\t\t\t\t\t\t\t\tR:\t\t   C\tcheckObjectType == cert\n\n\tChain - Rt.\tChain - Lf.\t N\t\tL: A - B\t\tType == chain,\n\t\t\t\t\t\t\t\t\tR:\t   B - C\tcheckObjectType != cert\n\t\t\t\t\t\t\t\t\t\t\t\t\t(or Enforced by kernel)\n\n   In the worst case we could run into something like:\n\n\tL: A - B - C - D\n\tR: X - Y - C - Z\n\n   Now although some of the certificates on the left and the right appear to \n   be identical, all this means is that the DNs and keys (and optionally \n   keyIDs) match, they could otherwise be completely different certificates \n   (different key usage, policies, altNames, and so on).  Because of this we \n   can't use one chain to verify another chain since although they may \n   logically verify, the principle of least surprise (to the user) indicates \n   that we shouldn't make any security statement about it.  For example in \n   the case of the A - B - ... chain verified by the X - Y - ... chain \n   above, if we report a successful verification then the user could be \n   quite justified in thinking that A - B - C - D was verified rather than \n   A - B - C - Z, or even that both the A - B - ... and the X - Y chains are \n   valid.\n\n   An informal survey of users indicated that no-one was really sure what a \n   success (or failure) status would indicate in this case, or more \n   specifically that everyone had some sort of guess but there was little \n   overlap between them, and people changed their views when questioned \n   about individual details.\n\n   Because of this issue of virtually-guaranteed unexpected results from the \n   user's point of view we don't allow a certificate chain as a right-hand \n   argument for checking any kind of certificate object except for one \n   special-case situation, and that's when we're checking a leaf certificate \n   with a chain containing all of the issuing CA certificates.  This \n   situation is created by a small number of SSL implementations, most \n   notably GnuTLS, that send only the client's leaf certificate for \n   certificate-based auth, with the server being expected to supply the rest \n   of the certificate chain.\n\n   This creates the messy situation alluded to above where it's unclear what \n   a check of { A } using { B - C - D } actually denotes: Does it mean that \n   { B - C - D } was checked and then { A } was checked, in effect checking \n   { A - B - C - D }, or merely that { A } was checked with { B }, with the \n   caller being expected to check { B - C - D } separately since they were \n   the one who supplied it to us?  If the expectation is that \n   { A - B - C - D } is checked, how is a check failure in { B - C - D }  \n   indicated when the error information can only be returned in { A }?\n\n   There isn't any obvious solution to this, any choice will result in \n   unexpected behaviour to at least some subset of users.  Since this \n   particular situation is extremely rare (it took several years before \n   anyone noticed that checks of this type had been disallowed by the \n   kernel), it's not even possible to poll users on what they'd expect to \n   happen.  Since it won't affect any users in most cases, we adopt the most \n   straightforward approach and treat a check of { A } with { B - C - D } to \n   mean a check purely of { A } with { B } and not a check of the entire \n   chain { B - C - D } as a coincidental side effect of checking { A } */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertValidity( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_HANDLE iSigCheckObject )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tCERT_INFO *issuerCertInfoPtr = NULL;\n\tX509SIG_FORMATINFO formatInfo, *formatInfoPtr = NULL;\n\tBOOLEAN issuerCertAcquired = FALSE, unlockChain = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint checkObjectType, checkObjectSubtype = CRYPT_CERTTYPE_NONE;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->certificate != NULL || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tREQUIRES( iSigCheckObject == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSigCheckObject ) );\n\n\t/* CRMF and OCSP use a b0rken signature format (the authors couldn't \n\t   quite manage a cut & paste of two lines of text) so if it's one of \n\t   these then we have to use nonstandard formatting */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\t/* [1] SEQUENCE */\n\t\tsetX509FormatInfo( &formatInfo, 1, FALSE );\n\t\tformatInfoPtr = &formatInfo;\n\t\t}\n\telse\n\t\t{\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST ) \n\t\t\t{\n\t\t\t/* [0] EXPLICIT SEQUENCE */\n\t\t\tsetX509FormatInfo( &formatInfo, 0, TRUE );\n\t\t\tformatInfoPtr = &formatInfo;\n\t\t\t}\n\t\t}\n\n\t/* If there's no signature checking key supplied then the certificate \n\t   must be self-signed, either an implicitly self-signed object like a \n\t   certificate chain or an explicitly self-signed object like a \n\t   certificate request or self-signed certificate */\n\tif( iSigCheckObject == CRYPT_UNUSED )\n\t\t{\n\t\t/* If it's a certificate chain it's a (complex) self-signed object \n\t\t   containing more than one certificate so we need a special \n\t\t   function to check the entire chain */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\treturn( checkCertChain( certInfoPtr ) );\n\n\t\t/* It's an explicitly self-signed object */\n\t\treturn( checkSelfSignedCert( certInfoPtr, formatInfoPtr ) );\n\t\t}\n\n\t/* Find out what the signature check object is */\n\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &checkObjectType, CRYPT_IATTRIBUTE_TYPE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &checkObjectSubtype, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBTYPE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Perform a general validity check on the object being checked and the\n\t   associated verification object.  This is somewhat more strict than\n\t   the kernel checks since the kernel only knows about valid subtypes\n\t   but not that some subtypes are only valid in combination with some\n\t   types of object being checked */\n\tswitch( checkObjectType )\n\t\t{\n\t\tcase OBJECT_TYPE_CERTIFICATE:\n\t\t\tREQUIRES( checkObjectSubtype == SUBTYPE_CERT_CERT || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_CERT_CERTCHAIN || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_CERT_CRL || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_CERT_RTCS_RESP || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_CERT_OCSP_RESP );\n\t\t\tbreak;\t  /* Enforced by the kernel */ \n\n\t\tcase OBJECT_TYPE_CONTEXT:\n\t\t\tREQUIRES( checkObjectSubtype == SUBTYPE_CTX_PKC );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_KEYSET:\n\t\t\t/* A keyset can only be used as a source of revocation\n\t\t\t   information for checking a certificate or to populate the\n\t\t\t   status fields of an RTCS/OCSP response */\n\t\t\tREQUIRES( checkObjectSubtype == SUBTYPE_KEYSET_DBMS || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_KEYSET_DBMS_STORE );\n\t\t\tif( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_RTCS_RESPONSE && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_SESSION:\n\t\t\t/* An (RTCS or OCSP) session can only be used as a source of\n\t\t\t   validity/revocation information for checking a certificate */\n\t\t\tREQUIRES( checkObjectSubtype == SUBTYPE_SESSION_RTCS || \\\n\t\t\t\t\t  checkObjectSubtype == SUBTYPE_SESSION_OCSP );\n\t\t\tif( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkObjectSubtype\" );\n\n\t/* There's one special-case situation in which we don't perform a \n\t   standard check and that's when the object to be checked is a \n\t   certificate chain.  Normally the checking object would be \n\t   CRYPT_UNUSED, but the caller may also pass in a root certificate\n\t   as the checking object for a chain that's missing the root */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\n\t\t/* If we're checking a certificate chain then the only type of \n\t\t   checking object that's valid is a certificate.  This isn't \n\t\t   strictly true since the CRL-checking code will check every\n\t\t   certificate in the chain against the CRL, but the code for OCSP, \n\t\t   RTCS, and keysets doesn't yet do this so until someone requests \n\t\t   it we don't allow entire chains to be checked in this manner */\n\t\tif( checkObjectType != OBJECT_TYPE_CERTIFICATE || \\\n\t\t\tcheckObjectSubtype != SUBTYPE_CERT_CERT )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t/* At this point things get a bit deceptive (for the caller), the\n\t\t   only way in which the check that's being performed here can \n\t\t   succeed is if the certificate being used as the checking object \n\t\t   is a trusted CA certificate that's at the top of the chain.  In \n\t\t   this case there's no need to explicitly make it part of the check \n\t\t   since it'll already be present in the trust store, however for\n\t\t   consistency we verify that it's a CA certificate, that it's\n\t\t   trusted, and that it chains up from the certificate at the top of\n\t\t   the chain.  Once this check has passed we call checkCertChain()\n\t\t   as if the checking object had been specified as CRYPT_UNUSED */\n\t\tif( !checkContextCapability( iSigCheckObject, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGCHECK_CA ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iSigCheckObject, \n\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_CHECK );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\tREQUIRES( certChainInfo->chainEnd > 0 && \\\n\t\t\t\t  certChainInfo->chainEnd <= MAX_CHAINLENGTH );\n\t\tstatus = krnlSendMessage( certChainInfo->chain[ certChainInfo->chainEnd - 1 ], \n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGCHECK, NULL,\n\t\t\t\t\t\t\t\t  iSigCheckObject );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t/* The checking object is a trusted CA certificate that connects to\n\t\t   the top of the chain, check the rest of the chain with the \n\t\t   implicitly-present trusted certificate as the root */\n\t\tstatus = checkCertChain( certInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkCertChain\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertChain\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Perform a basic check for obvious invalidity issues */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tstatus = checkCertBasic( certInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkCertBasic\" );\n\n\t/* If the checking object is a CRL or CRL-equivalent like an RTCS or\n\t   OCSP response, a keyset that may contain a CRL, or an RTCS or OCSP \n\t   session then this is a validity/revocation check that works rather \n\t   differently from a straight signature check */\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\tif( checkObjectType == OBJECT_TYPE_CERTIFICATE )\n\t\t{\n#if defined( USE_CERTREV )\n\t\tif( checkObjectSubtype == SUBTYPE_CERT_CRL || \\\n\t\t\tcheckObjectSubtype == SUBTYPE_CERT_OCSP_RESP )\n\t\t\t{\n\t\t\tstatus = checkCRL( certInfoPtr, iSigCheckObject );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"checkCRL\" );\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkCRL\" ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTREV */\n#if defined( USE_CERTVAL )\n\t\tif( checkObjectSubtype == SUBTYPE_CERT_RTCS_RESP )\n\t\t\t{\n\t\t\t/* This functionality isn't enabled yet, since RTCS is a \n\t\t\t   straight go/no go protocol it seems unlikely that it'll\n\t\t\t   ever be needed, and no-one's ever requested it in more\n\t\t\t   than a decade of use */\n\t\t\tretIntError();\n\t\t\t}\n#endif /* USE_CERTVAL */\n\t\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\tif( checkObjectType == OBJECT_TYPE_KEYSET )\n\t\t{\n\t\t/* If it's an RTCS or OCSP response, use the certificate store to \n\t\t   fill in the status information fields */\n#if defined( USE_CERTVAL )\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t\t{\n\t\t\tstatus = checkRTCSResponse( certInfoPtr, iSigCheckObject );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"checkRTCSResponse\" );\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkRTCSResponse\" ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTVAL */\n#if defined( USE_CERTREV )\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t{\n\t\t\tstatus = checkOCSPResponse( certInfoPtr, iSigCheckObject );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"checkOCSPResponse\" );\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkOCSPResponse\" ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* It's a keyset, check the certificate against the CRL blacklist in \n\t\t   the keyset */\n\t\tstatus = checkKeyset( certInfoPtr, iSigCheckObject );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkKeyset\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkKeyset\" ) );\n\n\t\treturn( CRYPT_OK );\n#else\n\t\treturn( CRYPT_ARGERROR_VALUE );\n#endif /* USE_CERTREV */\n\t\t}\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\tif( checkObjectType == OBJECT_TYPE_SESSION )\n\t\t{\n\t\tstatus = checkResponder( certInfoPtr, iSigCheckObject );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkResponder\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkResponder\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n\t/* Beyond this point we're checking a certificate/certificate chain, \n\t   CRL, or signed RTCS or OCSP response with either another certificate \n\t   or a raw public key.  Certificate chains have been checked above and \n\t   PKCS #10/CRMF requests are self-signed so typically they're checked \n\t   via the iSigCheckObject == CRYPT_UNUSED option aboave, however they \n\t   can also be checked by explicitly supplying a check object */\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tREQUIRES( ( checkObjectType == OBJECT_TYPE_CERTIFICATE && \\\n\t\t\t\t( checkObjectSubtype == SUBTYPE_CERT_CERT || \\\n\t\t\t\t  checkObjectSubtype == SUBTYPE_CERT_CERTCHAIN ) ) || \\\n\t\t\t  ( checkObjectType == OBJECT_TYPE_CONTEXT ) );\n\n\t/* If we've been given a self-signed certificate, make sure that the \n\t   signature check key is the same as the certificate's key.  To test \n\t   this we have to compare both the signing key and, if the signature \n\t   check object is a certificate, the certificate */\n\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE keyID[ KEYID_SIZE + 8 ];\n\n\t\t/* Check that the key in the certificate and the key in the \n\t\t   signature check object are identical */\n\t\tsetMessageData( &msgData, keyID, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_COMPARE\" );\n\n\t\t/* If the signature check object is a certificate (even though \n\t\t   what's being checked is already a self-signed certificate) check \n\t\t   that it's identical to the certificate being checked (which it \n\t\t   must be if the certificate is self-signed).  This may be somewhat \n\t\t   stricter than required but it'll weed out technically valid but \n\t\t   questionable combinations like a certificate request being used \n\t\t   to validate a certificate and misleading ones such as one \n\t\t   certificate chain being used to check a second chain */\n\t\tif( checkObjectType == OBJECT_TYPE_CERTIFICATE )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iSigCheckObject,\n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_CERTOBJ );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t}\n\n\t\t/* If what we're checking is a certificate chain then it's a \n\t\t   (complex) self-signed object containing more than one certificate \n\t\t   so we need a special function to check the entire chain */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t{\n\t\t\tstatus = checkCertChain( certInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"checkCertChain\" );\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \n\t\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_COMPARE\",\n\t\t\t\t\t\t\t\t\t\t\t\"checkCertChain\" ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tstatus = checkSelfSignedCert( certInfoPtr, formatInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkSelfSignedCert\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkObjectSubtype\", \"checkCertBasic\", \n\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_COMPARE\", \n\t\t\t\t\t\t\t\t\t\t\"checkSelfSignedCert\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the check object is a certificate chain, select the leaf \n\t   certificate for use in further checks.  See the long comment at the \n\t   start of this function for more on this */\n\tif( checkObjectType == OBJECT_TYPE_CERTIFICATE && \\\n\t\tcheckObjectSubtype == SUBTYPE_CERT_CERTCHAIN )\n\t\t{\n\t\t/* Before we can use the leaf certificate, we need to check that the\n\t\t   chain, or at least one of the CA certificates in it, is trusted */\n\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iSigCheckObject, \n\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_CHECK );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t/* Select the leaf certificate for use in further checks */\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORLAST,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( iSigCheckObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\treturn( status );\n\t\t\t}\n\t\tunlockChain = TRUE;\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_USER_TRUSTMGMT\" );\n\n\t/* The signature check key may be a certificate or a context.  If it's\n\t   a certificate then we get the issuer certificate information and \n\t   extract the context from it before continuing */\n\tif( checkObjectType == OBJECT_TYPE_CERTIFICATE )\n\t\t{\n\t\t/* Get the context from the issuer certificate */\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t\t  &iCryptContext, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( unlockChain == TRUE )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( iSigCheckObject, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\t\t}\n\t\t\treturn( cryptArgError( status ) ? \\\n\t\t\t\t\tCRYPT_ARGERROR_VALUE : status );\n\t\t\t}\n\n\t\t/* Get the issuer certificate information */\n\t\tstatus = krnlAcquireObject( iSigCheckObject, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ARGERROR_VALUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( unlockChain == TRUE )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( iSigCheckObject, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\t\tENSURES_OBJECT( sanityCheckCert( issuerCertInfoPtr ),\n\t\t\t\t\t\tissuerCertInfoPtr->objectHandle );\n\t\tissuerCertAcquired = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_CERTIFICATE localCert;\n\n\t\tiCryptContext = iSigCheckObject;\n\n\t\t/* It's a context then we may have a certificate present with it so \n\t\t   we try to extract that and use it as the issuer certificate if \n\t\t   possible.  If the issuer certificate isn't present then this \n\t\t   isn't an error since it could be just a raw context */\n\t\tstatus = krnlSendMessage( iSigCheckObject, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t\t  &localCert, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlAcquireObject( localCert, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ARGERROR_VALUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\t\t\tREQUIRES_OBJECT( sanityCheckCert( issuerCertInfoPtr ),\n\t\t\t\t\t\t\t issuerCertInfoPtr->objectHandle );\n\t\t\tissuerCertAcquired = TRUE;\n\t\t\t}\n\n\t\t/* A non-OK status from IMESSAGE_GETDEPENDENT isn't an error so we\n\t\t   don't have to exit on cryptStatusError() at this point */\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETDEPENDENT\" );\n\n\t/* Check the certificate against the issuing certificate */\n\tstatus = checkCertDetails( certInfoPtr, issuerCertAcquired ? \\\n\t\t\t\t\t\t\t\t\tissuerCertInfoPtr : NULL, \n\t\t\t\t\t\t\t   iCryptContext, formatInfoPtr, FALSE, FALSE,\n\t\t\t\t\t\t\t   TRUE, &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t   &certInfoPtr->errorType );\n\tif( issuerCertAcquired == TRUE )\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\tif( unlockChain == TRUE )\n\t\t{\n\t\t( void ) krnlSendMessage( iSigCheckObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );\n\tCFI_CHECK_UPDATE( \"checkCertDetails\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"IMESSAGE_GETATTRIBUTE\", \"checkObjectSubtype\", \n\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"IMESSAGE_USER_TRUSTMGMT\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETDEPENDENT\", \n\t\t\t\t\t\t\t\t\t\"checkCertDetails\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/certsign.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Certificate Signing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n#else\n  #include \"cert/cert.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set the end time for a certificate object.  Because of the Y2038 problem\n   we have to be careful about the maximum time value that we allow, if \n   it'll overflow then we clamp it at MAX_TIME_VALUE */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setEndTime( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_RANGE( 1, 20 * 365 ) const int timeInDays )\n\t{\n\ttime_t timeInSeconds;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( timeInDays >= 1 && timeInDays <= 20 * 365 );\n\n\ttimeInSeconds = timeInDays * 86400L;\n\tif( MAX_TIME_VALUE - certInfoPtr->startTime >= timeInSeconds )\n\t\t{\n\t\t/* The end time is past MAX_TIME_VALUE, clamp it at \n\t\t   MAX_TIME_VALUE */\n\t\tcertInfoPtr->endTime = MAX_TIME_VALUE;\n\t\t}\n\telse\n\t\t{\n\t\tcertInfoPtr->endTime = certInfoPtr->startTime + timeInSeconds;\n\t\t}\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Recover information normally set up on certificate import.  After \n   signing the certificate the data is present without the certificate \n   having been explicitly imported so we have to go back and perform the \n   actions normally performed on import here.  The subject DN and public key \n   data length was recorded when the certificate data was written but the \n   position of the other elements in the certificate can't be determined \n   until the certificate has been signed */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getObjectDataPtr( INOUT STREAM *stream,\n\t\t\t\t\t\t\t OUT_BUFFER_ALLOC_OPT( *dataLength ) void **dataPtrPtr,\n\t\t\t\t\t\t\t OUT_LENGTH_Z int *dataLength )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\t*dataLength = 0;\n\n\t/* Get the length of the object.  This guarantees a non-zero length, \n\t   finding a length of zero results in a CRYPT_ERROR_BADDATA */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( length > 0 );\n\n\t/* Get a reference to the object data */\n\tstatus = sMemGetDataBlock( stream, dataPtrPtr, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*dataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int recoverCertData( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType, \n\t\t\t\t\t\t\tIN_BUFFER( encodedCertDataLength ) \\\n\t\t\t\t\t\t\t\tconst void *encodedCertData,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int encodedCertDataLength )\n\t{\n\tSTREAM stream;\n\tint tag, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( encodedCertData, encodedCertDataLength ) );\n\n\tREQUIRES( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certType == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  certType == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certType == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  certType == CRYPT_CERTTYPE_REQUEST_REVOCATION || \\\n\t\t\t  certType == CRYPT_CERTTYPE_CRL || \\\n\t\t\t  certType == CRYPT_CERTTYPE_PKIUSER );\n\tREQUIRES( encodedCertDataLength >= 16 && \\\n\t\t\t  encodedCertDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* If there's public-key or DN data stored with the certificate, free it \n\t   since we now have a copy as part of the encoded certificate.  Since the \n\t   publicKeyInfo/subject/issuerDNptr pointer points at the public-key/DN \n\t   data, we clear this as well.\n\t   \n\t   Revocation requests present a slight exception to this since they \n\t   store a subject DN that's not needed for the request itself but is \n\t   required by the CMP protocol that they're used with (see the long \n\t   comment in copyCertToRevRequest() in comp_cert.c), so we leave the\n\t   subject DN alone if there's one present and it's a revocation \n\t   request */\n\tif( certInfoPtr->publicKeyData != NULL )\n\t\t{\n\t\tzeroise( certInfoPtr->publicKeyData, certInfoPtr->publicKeyInfoSize );\n\t\tclFree( \"recoverCertData\", certInfoPtr->publicKeyData );\n\t\tcertInfoPtr->publicKeyData = certInfoPtr->publicKeyInfo = NULL;\n\t\t}\n\tif( certInfoPtr->subjectDNdata != NULL && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tzeroise( certInfoPtr->subjectDNdata, certInfoPtr->subjectDNsize );\n\t\tclFree( \"recoverCertData\", certInfoPtr->subjectDNdata );\n\t\tcertInfoPtr->subjectDNdata = certInfoPtr->subjectDNptr = NULL;\n\t\t}\n\tif( certInfoPtr->issuerDNdata != NULL )\n\t\t{\n\t\tzeroise( certInfoPtr->issuerDNdata , certInfoPtr->issuerDNsize );\n\t\tclFree( \"recoverCertData\", certInfoPtr->issuerDNdata );\n\t\tcertInfoPtr->issuerDNdata = certInfoPtr->issuerDNptr = NULL;\n\t\t}\n\n\t/* If it's a PKCS #10 request parse the encoded form to locate the \n\t   subject DN and public key */\n\tif( certType == CRYPT_CERTTYPE_CERTREQUEST )\n\t\t{\n\t\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\t\treadSequence( &stream, NULL );\t\t\t\t/* Outer wrapper */\n\t\treadSequence( &stream, NULL );\t\t\t\t/* Inner wrapper */\n\t\tstatus = readShortInteger( &stream, NULL );\t/* Version */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNsize );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readUniversal( &stream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->publicKeyInfo, \n\t\t\t\t\t\t\t\t\t   &certInfoPtr->publicKeyInfoSize );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\tENSURES( cryptStatusOK( status ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a CRMF request, parse the signed form to locate the start of\n\t   the encoded DN if there is one (the issuer DN is already set up when\n\t   the issuer certificate is added) and the public key.  The public key \n\t   is actually something of a special case in that in the CRMF/CMP \n\t   tradition it has a weird nonstandard tag which means that we can't \n\t   directly use it elsewhere as a SubjectPublicKeyInfo blob.  In order \n\t   to work around this the code that reads SPKIs allows something other\n\t   than a plain SEQUENCE for the outer wrapper */\n\tif( certType == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\t\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\t\treadSequence( &stream, NULL );\n\t\treadUniversal( &stream );\t\t\t\t/* Request ID */\n\t\tstatus = readSequence( &stream, NULL );\t/* Inner wrapper */\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag == MAKE_CTAG( 4 ) )\n\t\t\tstatus = readUniversal( &stream );\t/* Validity */\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag == MAKE_CTAG( 5 ) )\n\t\t\t{\t\t\t\t\t\t\t\t\t/* Subj.name wrapper */\n\t\t\tstatus = readConstructed( &stream, NULL, 5 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNsize );\n\t\t\t\t}\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tstatus = readUniversal( &stream );\t/* Subject name */\n\t\t\t}\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag != MAKE_CTAG( 6 ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\t\t/* Public key */\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->publicKeyInfo, \n\t\t\t\t\t\t\t\t\t   &certInfoPtr->publicKeyInfoSize );\n\t\t\t}\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( certType == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\t\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\t\tstatus = readSequence( &stream, NULL );\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag == MAKE_CTAG_PRIMITIVE( 1 ) )\n\t\t\tstatus = readUniversal( &stream );\t/* Serial number */\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag == MAKE_CTAG( 3 ) )\n\t\t\t{\t\t\t\t\t\t\t\t\t/* Issuer.name wrapper */\n\t\t\tstatus = readConstructed( &stream, NULL, 3 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t\t\t\t   &certInfoPtr->issuerDNsize );\n\t\t\t\t}\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tstatus = readUniversal( &stream );\t/* Subject name */\n\t\t\t}\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a CRL, parse the encoded form to locate the start of the \n\t   issuer DN */\n\tif( certType == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\t\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\t\tstatus = readSequence( &stream, NULL );\n\t\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\t\ttag == BER_INTEGER )\n\t\t\tstatus = readUniversal( &stream );\t/* Version */\n\t\tif( !cryptStatusError( status ) )\n\t\t\tstatus = readUniversal( &stream );\t/* AlgorithmID */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t\t\t   &certInfoPtr->issuerDNsize );\n\t\t\t}\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's PKI user data, parse the encoded form to locate the start of \n\t   the PKI user DN */\n\tif( certType == CRYPT_CERTTYPE_PKIUSER )\n\t\t{\n\t\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\t\tstatus = readSequence( &stream, NULL );\t\t/* Wrapper */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNsize );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\tENSURES( cryptStatusOK( status ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tENSURES( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t certType == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* It's a certificate, parse the signed form to locate the start of the\n\t   encoded issuer and subject DN and public key */\n\tsMemConnect( &stream, encodedCertData, encodedCertDataLength );\n\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\tstatus = readSequence( &stream, NULL );\t/* Inner wrapper */\n\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\treadUniversal( &stream );\t\t\t/* Version */\n\treadUniversal( &stream );\t\t\t\t/* Serial number */\n\tstatus = readUniversal( &stream );\t\t/* Signature algo */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t\t   &certInfoPtr->issuerDNsize );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\treadUniversal( &stream );\t\t\t\t/* Issuer DN */\n\tstatus = readUniversal( &stream );\t\t/* Validity */\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\tconst int startPos = stell( &stream );\n\t\tint length;\n\n\t\t/* Full PKIX allows zero-length DNs, which can't be extracted using\n\t\t   getObjectDataPtr().  To deal with this we have to explicitly read\n\t\t   the SEQUENCE that encapsulates the DN and, if it's zero-length,\n\t\t   call sMemGetDataBlock() with the size of the zero-length object\n\t\t   given explicitly */\n\t\tstatus = readSequenceZ( &stream, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsseek( &stream, startPos );\n\t\t\tif( length > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = getObjectDataPtr( &stream, \n\t\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNsize );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tcertInfoPtr->subjectDNsize = sizeofShortObject( 0 );\n\t\t\t\tstatus = sMemGetDataBlock( &stream, \n\t\t\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNptr,\n\t\t\t\t\t\t\t\t\t\t   certInfoPtr->subjectDNsize );\n\t\t\t\t}\n\t\t\t}\n#else\n\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t   &certInfoPtr->subjectDNsize );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = readUniversal( &stream );\t\t/* Subject DN */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getObjectDataPtr( &stream, &certInfoPtr->publicKeyInfo, \n\t\t\t\t\t\t\t\t   &certInfoPtr->publicKeyInfoSize );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\tsMemDisconnect( &stream );\n\n\t/* Since the certificate may be used for public-key operations as soon \n\t   as it's signed we have to reconstruct the public-key context and \n\t   apply to it the constraints that would be applied on import, the \n\t   latter being done implicitly via the MESSAGE_SETDEPENDENT mechanism */\n\tsMemConnect( &stream, certInfoPtr->publicKeyInfo,\n\t\t\t\t certInfoPtr->publicKeyInfoSize );\n\tstatus = iCryptReadSubjectPublicKey( &stream,\n\t\t\t\t\t\t\t\t\t\t &certInfoPtr->iPubkeyContext,\n\t\t\t\t\t\t\t\t\t\t SYSTEM_OBJECT_HANDLE, FALSE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t  IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t  &certInfoPtr->iPubkeyContext,\n\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\tif( cryptStatusOK( status ) )\n\t\tCLEAR_FLAG( certInfoPtr->flags, CERT_FLAG_DATAONLY );\n\treturn( status );\n\t}\n\n/* Check the key being used to sign a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkSigningKey( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tconst CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\tconst BOOLEAN isCertificate )\n\t{\n\tMESSAGE_DATA msgData;\n\tint complianceLevel, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isCertificate == TRUE || isCertificate == FALSE );\n\n\t/* Determine how much checking we need to perform */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel,\n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the signing key is associated with an issuer \n\t   certificate rather than some other key-related object like a \n\t   certificate request */\n\tif( issuerCertInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\tissuerCertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Make sure that the signing key is associated with a completed issuer \n\t   certificate.  If it's a self-signed certificate then we don't have to \n\t   have a completed certificate present because the self-sign operation \n\t   hasn't created it yet */\n\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) && \\\n\t\tissuerCertInfoPtr->certificate == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* If it's a CRL then the signing certificate has to match the \n\t   certificate(s) being revoked.  If it's an empty CRL then the issuer DN\n\t   isn't set (since no certificates have been added to the CRL, there's \n\t   no issuer DN to copy over) so we only check this if there are entries\n\t   present */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL && \\\n\t\tcertInfoPtr->issuerDNptr != NULL )\n\t\t{\n\t\tREQUIRES( issuerCertInfoPtr->subjectDNptr != NULL );\n\n\t\tif( certInfoPtr->issuerDNsize != issuerCertInfoPtr->subjectDNsize || \\\n\t\t\tmemcmp( certInfoPtr->issuerDNptr, issuerCertInfoPtr->subjectDNptr,\n\t\t\t\t\tcertInfoPtr->issuerDNsize ) )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* If it's an OCSP request or response then the signing certificate has \n\t   to be valid for signing */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t{\n\t\treturn( checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_NONE,\n\t\t\t\t\t\t\t   KEYUSAGE_SIGN, complianceLevel, \n\t\t\t\t\t\t\t   &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t   &certInfoPtr->errorType ) );\n\t\t}\n\n\t/* If it's a non-self-signed object then it must be signed by a CA \n\t   certificate */\n\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\tstatus = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA,\n\t\t\t\t\t\t\t\tisCertificate ? CRYPT_KEYUSAGE_KEYCERTSIGN : \\\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_CRLSIGN,\n\t\t\t\t\t\t\t\tcomplianceLevel, &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\tcertInfoPtr->errorType == CRYPT_ERRTYPE_CONSTRAINT )\n\t\t\t{\n\t\t\t/* If there was a constraint problem then it's something in the \n\t\t\t   issuer's certificate rather than the certificate being signed \n\t\t\t   so we have to change the error type accordingly.  What's \n\t\t\t   reported isn't strictly accurate since the locus is in the \n\t\t\t   issuer rather than subject certificate but it's the best that \n\t\t\t   we can do */\n\t\t\tcertInfoPtr->errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\n\t/* It's a self-signed certificate, the signing key must match the key in \n\t   the certificate */\n\tsetMessageData( &msgData, certInfoPtr->publicKeyID, KEYID_SIZE );\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSigning Setup Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy a signing certificate chain into the certificate being signed */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copySigningCertChain( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext )\n\t{\n\tCERT_CERT_INFO *certInfo = certInfoPtr->cCertCert;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\n\t/* If there's a chain of certificates present (for example from a \n\t   previous signing attempt that wasn't completed due to an error), free \n\t   them */\n\tif( certInfo->chainEnd > 0 )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\t\t\t\n\t\tLOOP_EXT( i = 0, i < certInfo->chainEnd, i++, MAX_CHAINLENGTH )\n\t\t\tkrnlSendNotifier( certInfo->chain[ i ], IMESSAGE_DECREFCOUNT );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tcertInfo->chainEnd = 0;\n\t\t}\n\n\t/* If it's a self-signed certificate then it must be the only one in the \n\t   chain (creating a chain like this doesn't make much sense but we \n\t   handle it anyway) */\n\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\tif( certInfo->chainEnd > 0 )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Copy the certificate chain into the certificate to be signed */\n\treturn( copyCertChain( certInfoPtr, iSignContext, FALSE ) );\n\t}\n\n/* Set up any required timestamp data for a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setCertTimeinfo( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\tconst BOOLEAN isCertificate )\n\t{\n\tconst time_t currentTime = ( iSignContext == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t   getTime() : getReliableTime( iSignContext );\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( iSignContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isCertificate == TRUE || isCertificate == FALSE );\n\n\t/* If it's some certificate variant or a CRL/OCSP response and the \n\t   various timestamps haven't been set yet, start them at the current \n\t   time and give them the default validity period or next update time if \n\t   these haven't been set.  The time used is the local time, this is \n\t   converted to GMT when we write it to the certificate.  Issues like \n\t   validity period nesting and checking for valid time periods are \n\t   handled elsewhere */\n\tif( isCertificate )\n\t\t{\n\t\tif( certInfoPtr->startTime <= MIN_TIME_VALUE )\n\t\t\t{\n\t\t\t/* If the time is screwed up then we can't continue */\n\t\t\tif( currentTime <= MIN_TIME_VALUE )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\tcertInfoPtr->startTime = currentTime;\n\t\t\t}\n\t\tif( certInfoPtr->endTime <= MIN_TIME_VALUE )\n\t\t\t{\n\t\t\tint validity;\n\n\t\t\tENSURES( certInfoPtr->startTime > MIN_TIME_VALUE && \\\n\t\t\t\t\t certInfoPtr->startTime < MAX_TIME_VALUE );\n\n\t\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &validity, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_VALIDITY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = setEndTime( certInfoPtr, validity );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#ifdef USE_CERTREV\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t{\n\t\t/* If the time is messed up then we can't provide an indication of \n\t\t   the revocation time */\n\t\tif( currentTime <= MIN_TIME_VALUE )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\n\t\t/* Set the revocation/validity times */\n\t\tif( certInfoPtr->startTime <= MIN_TIME_VALUE )\n\t\t\tcertInfoPtr->startTime = currentTime;\n\t\tif( certInfoPtr->endTime <= MIN_TIME_VALUE )\n\t\t\t{\n\t\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t\t{\n\t\t\t\t/* OCSP responses come directly from the certificate store \n\t\t\t\t   and represent an atomic (and ephemeral) snapshot of the \n\t\t\t\t   store state.  Because of this the next-update time occurs \n\t\t\t\t   effectively immediately since the next snapshot could \n\t\t\t\t   provide a different response */\n\t\t\t\tcertInfoPtr->endTime = currentTime;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tint updateInterval;\n\n\t\t\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &updateInterval,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_UPDATEINTERVAL );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tstatus = setEndTime( certInfoPtr, updateInterval );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\tif( certInfoPtr->cCertRev->revocationTime <= MIN_TIME_VALUE )\n\t\t\tcertInfoPtr->cCertRev->revocationTime = currentTime;\n\t\t}\n#endif /* USE_CERTREV */\n\n\treturn( CRYPT_OK );\n\t}\n\n\n/* Perform any final initialisation of the certificate object before we sign \n   it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initSignatureInfo( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t  IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t  const BOOLEAN isCertificate,\n\t\t\t\t\t\t\t  OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,\n\t\t\t\t\t\t\t  IN_ENUM_OPT( CRYPT_SIGNATURELEVEL ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_SIGNATURELEVEL_TYPE signatureLevel,\n\t\t\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *extraDataLength )\n\t{\n\tconst CRYPT_ALGO_TYPE signingAlgo = ( issuerCertInfoPtr != NULL ) ? \\\n\t\t\t\tissuerCertInfoPtr->publicKeyAlgo : certInfoPtr->publicKeyAlgo;\n\tint value, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( hashAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( extraDataLength == NULL || \\\n\t\t\tisWritePtr( extraDataLength, sizeof( int ) ) );\n\n\tREQUIRES( iSignContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isCertificate == TRUE || isCertificate == FALSE );\n\tREQUIRES( ( signatureLevel == CRYPT_SIGNATURELEVEL_NONE && \\\n\t\t\t\textraDataLength == NULL ) || \\\n\t\t\t  ( signatureLevel >= CRYPT_SIGNATURELEVEL_SIGNERCERT && \\\n\t\t\t\tsignatureLevel < CRYPT_SIGNATURELEVEL_LAST && \\\n\t\t\t\textraDataLength != NULL ) );\n\n\t/* Clear return values */\n\t*hashAlgo = CRYPT_ALGO_NONE;\n\tif( extraDataLength != NULL )\n\t\t*extraDataLength = 0;\n\n\t/* If we need to include extra data in the signature, make sure that \n\t   it's available and determine how big it'll be.  If there's no issuer \n\t   certificate available and we've been asked for extra signature data \n\t   then we fall back to providing just a raw signature rather than \n\t   bailing out completely */\n\tif( extraDataLength != NULL && issuerCertInfoPtr != NULL )\n\t\t{\n\t\tENSURES( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t\t certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );\n\n\t\tif( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )\n\t\t\t{\n\t\t\tstatus = exportCert( NULL, 0, extraDataLength,\n\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE,\n\t\t\t\t\t\t\t\t issuerCertInfoPtr );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tENSURES( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );\n\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( issuerCertInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_CERTSEQUENCE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t*extraDataLength = msgData.length;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If it's a certificate chain, copy over the signing certificate(s) */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\n\t\tstatus = copySigningCertChain( certInfoPtr, iSignContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Set up any required timestamps */\n\tstatus = setCertTimeinfo( certInfoPtr, iSignContext, isCertificate );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a certificate, set up the certificate serial number */\n\tif( isCertificate )\n\t\t{\n\t\tstatus = setSerialNumber( certInfoPtr, NULL, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine the hash algorithm to use and if it's a certificate or \n\t   CRL remember it for when we write the certificate (the value is \n\t   embedded in the certificate to prevent an obscure attack on unpadded \n\t   RSA signature algorithms or (EC)DSA signatures) */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_HASH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*hashAlgo = value;\t/* int vs. enum */\n\tif( signingAlgo == CRYPT_ALGO_DSA )\n\t\t{\n\t\t/* If we're going to be signing with DSA then things get a bit \n\t\t   complicated, the only OID defined for non-SHA1 DSA is for 256-bit\n\t\t   SHA2, and even then in order to use it with a generic 1024-bit \n\t\t   key we have to truncate the hash.  It's not clear how many \n\t\t   implementations can handle this, and if we're using a hash wider\n\t\t   than SHA-2/256 or a newer hash like SHAng then we can't encode \n\t\t   the result at all.  To deal with this we restrict the hash used \n\t\t   with DSA to SHA-1 only */\n\t\t*hashAlgo = CRYPT_ALGO_SHA1;\n\t\t}\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\tcertInfoPtr->cCertCert->hashAlgo = *hashAlgo;\n#ifdef USE_CERTREV\n\telse\n\t\t{\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL )\n\t\t\tcertInfoPtr->cCertRev->hashAlgo = *hashAlgo;\n\t\t}\n#endif /* USE_CERTREV */\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSigning Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTREQ ) || defined( USE_CERTREV ) || \\\n\tdefined( USE_CERTVAL ) || defined( USE_PKIUSER )\n\n/* Pseudo-sign certificate information by writing the outer wrapper around \n   the certificate object data and moving the object into the initialised \n   state */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int pseudoSignCertificate( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t  INOUT_BUFFER_FIXED( signedObjectMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *signedObject,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int signedObjectMaxLength,\n\t\t\t\t\t\t\t\t  IN_BUFFER( certObjectLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *certObject,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int certObjectLength )\n\t{\n\tSTREAM stream;\n\tint signedObjectLength, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtrDynamic( signedObject, signedObjectMaxLength ) );\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\n\tREQUIRES( signedObjectMaxLength >= 16 && \\\n\t\t\t  signedObjectMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( certObjectLength >= 16 && \\\n\t\t\t  certObjectLength <= signedObjectMaxLength && \\\n\t\t\t  certObjectLength < MAX_INTLENGTH_SHORT );\n\n\tswitch( certInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\t/* It's an unsigned OCSP request or PKI user information, write \n\t\t\t   the outer wrapper */\n\t\t\tsignedObjectLength = sizeofObject( certObjectLength );\n\t\t\tENSURES( signedObjectLength >= 16 && \\\n\t\t\t\t\t signedObjectLength <= signedObjectMaxLength );\n\t\t\tsMemOpen( &stream, signedObject, signedObjectLength );\n\t\t\twriteSequence( &stream, certObjectLength );\n\t\t\tstatus = swrite( &stream, certObject, certObjectLength );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER )\n\t\t\t\t{\n\t\t\t\tstatus = recoverCertData( certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER, \n\t\t\t\t\t\t\t\t\t\t  signedObject, signedObjectLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t/* It's an RTCS request/response or OCSP response, it's already\n\t\t\t   in the form required */\n\t\t\tsignedObjectLength = certObjectLength;\n\t\t\tREQUIRES( rangeCheck( certObjectLength, 16, \n\t\t\t\t\t\t\t\t  signedObjectMaxLength ) );\n\t\t\tmemcpy( signedObject, certObject, certObjectLength );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\t\t{\n\t\t\tconst int dataSize = certObjectLength + \\\n\t\t\t\t\t\t\t\t sizeofObject( sizeofShortInteger( 0 ) );\n\n\t\t\tENSURES( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\n\t\t\t/* It's an encryption-only key, wrap up the certificate data \n\t\t\t   with an indication that private key POP will be performed via \n\t\t\t   out-of-band means and remember where the encoded data \n\t\t\t   starts */\n\t\t\tsignedObjectLength = sizeofObject( dataSize );\n\t\t\tENSURES( signedObjectLength >= 16 && \\\n\t\t\t\t\t signedObjectLength <= signedObjectMaxLength );\n\t\t\tsMemOpen( &stream, signedObject, signedObjectLength );\n\t\t\twriteSequence( &stream, dataSize );\n\t\t\tswrite( &stream, certObject, certObjectLength );\n\t\t\twriteConstructed( &stream, sizeofShortInteger( 0 ), 2 );\n\t\t\tstatus = writeShortInteger( &stream, 0, 1 );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tstatus = recoverCertData( certInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_CERT,\n\t\t\t\t\t\t\t\t\t  signedObject, signedObjectLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Indicate that the pseudo-signature has been checked (since we \n\t\t\t   just created it), this also avoids nasty semantic problems \n\t\t\t   with not-really-signed CRMF requests containing encryption-\n\t\t\t   only keys */\n\t\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t/* Revocation requests can't be signed so the (pseudo-)signed\n\t\t\t   data is just the object data */\n\t\t\tsignedObjectLength = certObjectLength;\n\t\t\tREQUIRES( rangeCheck( certObjectLength, 16, \n\t\t\t\t\t\t\t\t  signedObjectMaxLength ) );\n\t\t\tmemcpy( signedObject, certObject, certObjectLength );\n\t\t\tstatus = recoverCertData( certInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION,\n\t\t\t\t\t\t\t\t\t  signedObject, signedObjectLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Since revocation requests can't be signed we mark them as\n\t\t\t   pseudo-signed to avoid any problems that might arise from\n\t\t\t   this */\n\t\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tcertInfoPtr->certificate = signedObject;\n\tcertInfoPtr->certificateSize = signedObjectLength;\n\n\t/* The object is now (pseudo-)signed and initialised */\n\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SIGCHECKED );\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\t/* If it's a CRMF request with POP done via out-of-band means we\n\t\t   got here via a standard signing action (except that the key was\n\t\t   an encryption-only key), don't change the object state since the\n\t\t   kernel will do this as the post-signing step */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( krnlSendMessage( certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED,\n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED ) );\n\t}\n#endif /* USE_CERTREQ || USE_CERTREV || USE_CERTVAL || USE_PKIUSER */\n\n/* Sign the certificate information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6 ) ) \\\nstatic int signCertInfo( OUT_BUFFER( signedObjectMaxLength, \\\n\t\t\t\t\t\t\t\t\t *signedObjectLength ) \\\n\t\t\t\t\t\t\tvoid *signedObject, \n\t\t\t\t\t\t IN_DATALENGTH const int signedObjectMaxLength, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *signedObjectLength,\n\t\t\t\t\t\t IN_BUFFER( objectLength ) const void *object, \n\t\t\t\t\t\t IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t IN_ENUM( CRYPT_SIGNATURELEVEL ) \\\n\t\t\t\t\t\t\tconst CRYPT_SIGNATURELEVEL_TYPE signatureLevel,\n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int extraDataLength,\n\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr )\n\t{\n\tSTREAM stream;\n\tconst int extraDataType = \\\n\t\t\t( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT ) ? \\\n\t\t\tCRYPT_CERTFORMAT_CERTIFICATE : CRYPT_ICERTFORMAT_CERTSEQUENCE;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtrDynamic( signedObject, signedObjectMaxLength ) );\n\tassert( isWritePtr( signedObjectLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( object, objectLength ) && \\\n\t\t\tcryptStatusOK( checkCertObjectEncoding( object, objectLength ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( signedObjectMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  signedObjectMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( objectLength >= 16 && \\\n\t\t\t  objectLength <= signedObjectMaxLength && \\\n\t\t\t  objectLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( isEnumRangeOpt( signatureLevel, CRYPT_SIGNATURELEVEL ) );\n\tREQUIRES( isShortIntegerRange( extraDataLength ) );\n\tREQUIRES( extraDataLength <= 0 || issuerCertInfoPtr != NULL );\n\n\t/* Sign the certificate information.  CRMF and OCSP use a b0rken\n\t   signature format (the authors couldn't quite manage a cut & paste of\n\t   two lines of text) so if it's one of these we have to use nonstandard\n\t   formatting */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST )\n\t\t{\n\t\tX509SIG_FORMATINFO formatInfo;\n\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\t{\n\t\t\t/* [1] SEQUENCE */\n\t\t\tsetX509FormatInfo( &formatInfo, 1, FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* [0] EXPLICIT SEQUENCE */\n\t\t\tsetX509FormatInfo( &formatInfo, 0, TRUE );\n\t\t\t}\n\t\tif( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )\n\t\t\t{\n\t\t\tformatInfo.extraLength = \\\n\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( extraDataLength ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( signatureLevel == CRYPT_SIGNATURELEVEL_ALL )\n\t\t\t\t{\n\t\t\t\tformatInfo.extraLength = \\\n\t\t\t\t\t\t\tsizeofShortObject( extraDataLength );\n\t\t\t\t}\n\t\t\t}\n\t\tstatus = createX509signature( signedObject, signedObjectMaxLength, \n\t\t\t\t\t\t\t\tsignedObjectLength, object, objectLength, \n\t\t\t\t\t\t\t\tiSignContext, hashAlgo, &formatInfo );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a standard signature */\n\t\tstatus = createX509signature( signedObject, signedObjectMaxLength, \n\t\t\t\t\t\t\t\tsignedObjectLength, object, objectLength, \n\t\t\t\t\t\t\t\tiSignContext, hashAlgo, NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_VALUE : status );\n\n\t/* If there's no extra data to handle then we're done */\n\tif( extraDataLength <= 0 )\n\t\t{\n\t\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( signedObject, \n\t\t\t\t\t\t\t\t\t\t\t *signedObjectLength ) ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\t\n\t/* The extra data consists of signing certificates, so we can't continue\n\t   if there are none provided.  Figuring out how we get to this point is \n\t   rather complex, if we have a certificate, a CRL, or an OCSP object \n\t   with an associated signing key then we have an issuer cert present \n\t   (from signCert()).  If it's an OCSP request then the signature level \n\t   is something other than CRYPT_SIGNATURELEVEL_NONE, at which point if \n\t   there's an issuer certificate present then extraDataLength != 0 (from \n\t   initSignatureInfo()).  After this, signCert() will exit if there's no \n\t   signing key present since there's nothing further to do.  This means \n\t   that when we get here and extraDataLength != 0 then it means that \n\t   there's an issuer certificate present.  The following check ensures \n\t   that this is indeed the case */\n\tENSURES( issuerCertInfoPtr != NULL );\n\n\t/* If we need to include extra data with the signature attach it to the \n\t   end of the signature */\n\tENSURES( boundsCheck( *signedObjectLength, \n\t\t\t\t\t\t  signedObjectMaxLength - *signedObjectLength, \n\t\t\t\t\t\t  signedObjectMaxLength ) );\n\tsMemOpen( &stream, ( BYTE * ) signedObject + *signedObjectLength,\n\t\t\t  signedObjectMaxLength - *signedObjectLength );\n\tif( signatureLevel == CRYPT_SIGNATURELEVEL_SIGNERCERT )\n\t\t{\n\t\twriteConstructed( &stream, sizeofObject( extraDataLength ), 0 );\n\t\tstatus = writeSequence( &stream, extraDataLength );\n\t\t}\n\telse\n\t\t{\n\t\tENSURES( signatureLevel == CRYPT_SIGNATURELEVEL_ALL );\n\n\t\tstatus = writeConstructed( &stream, extraDataLength, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = exportCertToStream( &stream, issuerCertInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t extraDataType );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*signedObjectLength += stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( signedObject, \n\t\t\t\t\t\t\t\t\t\t\t *signedObjectLength ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the signed certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createSignedObject( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t   IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t   IN_ENUM_OPT( CRYPT_SIGNATURELEVEL ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_SIGNATURELEVEL_TYPE signatureLevel,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extraDataLength,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t   const BOOLEAN nonSigningKey )\n\t{\n\tWRITECERT_FUNCTION writeCertFunction;\n\tSTREAM stream;\n\tBYTE certObjectBuffer[ 1024 + 8 ], *certObjectPtr = certObjectBuffer;\n\tvoid *signedCertObject;\n\tint certObjectLength DUMMY_INIT, signedCertObjectLength;\n\tint signedCertAllocSize, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( iSignContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isEnumRangeOpt( signatureLevel, CRYPT_SIGNATURELEVEL ) );\n\tREQUIRES( isShortIntegerRange( extraDataLength ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( nonSigningKey == TRUE || nonSigningKey == FALSE );\n\n\t/* Select the function to use to write the certificate object to be\n\t   signed */\n\twriteCertFunction = getCertWriteFunction( certInfoPtr->type );\n\tENSURES( writeCertFunction != NULL );\n\n\t/* Determine how big the encoded certificate information will be,\n\t   allocate memory for it and the full signed certificate, and write the\n\t   encoded certificate information */\n\tsMemNullOpen( &stream );\n\tstatus = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\tiSignContext );\n\tif( cryptStatusOK( status ) )\n\t\tcertObjectLength = stell( &stream );\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( isIntegerRangeNZ( certObjectLength ) );\n\tsignedCertAllocSize = certObjectLength + 1024 + extraDataLength;\n\tif( certObjectLength > 1024 )\n\t\t{\n\t\tcertObjectPtr = clDynAlloc( \"signCert\", certObjectLength );\n\t\tif( certObjectPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tREQUIRES( rangeCheck( signedCertAllocSize, 1, MAX_BUFFER_SIZE ) );\n\tsignedCertObject = clAlloc( \"signCert\", signedCertAllocSize );\n\tif( signedCertObject == NULL )\n\t\t{\n\t\tif( certObjectPtr != certObjectBuffer )\n\t\t\tclFree( \"signCert\", certObjectPtr );\n\t\tif( signedCertObject != NULL )\n\t\t\tclFree( \"signCert\", signedCertObject );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tsMemOpen( &stream, certObjectPtr, certObjectLength );\n\tstatus = writeCertFunction( &stream, certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\tiSignContext );\n\tENSURES( cryptStatusError( status ) || \\\n\t\t\t certObjectLength == stell( &stream ) );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( certObjectPtr, certObjectLength );\n\t\tif( certObjectPtr != certObjectBuffer )\n\t\t\tclFree( \"signCert\", certObjectPtr );\n\t\tclFree( \"signCert\", signedCertObject );\n\t\treturn( status );\n\t\t}\n\tENSURES( cryptStatusOK( checkCertObjectEncoding( certObjectPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t\t certObjectLength ) ) );\n\n#if defined( USE_CERTREQ ) || defined( USE_CERTREV ) || \\\n\tdefined( USE_CERTVAL ) || defined( USE_PKIUSER )\n\t/* If there's no signing key present we pseudo-sign the certificate \n\t   information by writing the outer wrapper and moving the object into \n\t   the initialised state */\n\tif( nonSigningKey )\n\t\t{\n\t\tstatus = pseudoSignCertificate( certInfoPtr, signedCertObject,\n\t\t\t\t\t\t\t\t\t\tsignedCertAllocSize, certObjectPtr, \n\t\t\t\t\t\t\t\t\t\tcertObjectLength );\n\t\tzeroise( certObjectPtr, certObjectLength );\n\t\tif( certObjectPtr != certObjectBuffer )\n\t\t\tclFree( \"signCert\", certObjectPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"signCert\", signedCertObject );\n\t\t\treturn( status );\n\t\t\t}\n\t\tANALYSER_HINT( certInfoPtr->certificate != NULL );\n\t\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( certInfoPtr->certificate, \n\t\t\t\t\t\t\t\t\t\t\t certInfoPtr->certificateSize ) ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_CERTREQ || USE_CERTREV || USE_CERTVAL || USE_PKIUSER */\n\n\t/* Sign the certificate information */\n\tstatus = signCertInfo( signedCertObject, signedCertAllocSize, \n\t\t\t\t\t\t   &signedCertObjectLength, certObjectPtr, \n\t\t\t\t\t\t   certObjectLength, certInfoPtr, iSignContext, \n\t\t\t\t\t\t   hashAlgo, signatureLevel, extraDataLength,\n\t\t\t\t\t\t   issuerCertInfoPtr );\n\tzeroise( certObjectPtr, certObjectLength );\n\tif( certObjectPtr != certObjectBuffer )\n\t\tclFree( \"signCert\", certObjectPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"signCert\", signedCertObject );\n\t\treturn( status );\n\t\t}\n\tcertInfoPtr->certificate = signedCertObject;\n\tcertInfoPtr->certificateSize = signedCertObjectLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Sign a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint signCert( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iSignContext )\n\t{\n\tCRYPT_ALGO_TYPE hashAlgo;\n\tCERT_INFO *issuerCertInfoPtr = NULL;\n#ifdef USE_CERTREV\n\tconst CRYPT_SIGNATURELEVEL_TYPE signatureLevel = \\\n\t\t\t\t( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST ) ? \\\n\t\t\t\t\tcertInfoPtr->cCertRev->signatureLevel : \\\n\t\t\t\t\tCRYPT_SIGNATURELEVEL_NONE;\n#else\n\tconst CRYPT_SIGNATURELEVEL_TYPE signatureLevel = CRYPT_SIGNATURELEVEL_NONE;\n#endif /* USE_CERTREV */\n\tconst BOOLEAN isCertificate = \\\n\t\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN ) ? TRUE : FALSE;\n\tBOOLEAN issuerCertAcquired = FALSE, nonSigningKey = FALSE;\n\tint extraDataLength = 0, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->certificate == NULL );\n\tREQUIRES( iSignContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSignContext ) );\n\n\t/* If it's a non-signing key then we have to create a special format of \n\t   certificate request that isn't signed but contains an indication that \n\t   the private key POP will be performed by out-of-band means.  We also \n\t   have to check for the iSignContext being absent to handle OCSP \n\t   requests for which the signature is optional so there may be no \n\t   signing key present */\n\tif( iSignContext == CRYPT_UNUSED )\n\t\tnonSigningKey = TRUE;\n\telse\n\t\t{\n\t\t/* We've got a signing key, make sure that it's signature-capable */\n\t\tif( !checkContextCapability( iSignContext, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN_CA ) && \\\n\t\t\t!checkContextCapability( iSignContext, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\tnonSigningKey = TRUE;\n\t\t}\n\n\t/* Obtain the issuer certificate from the private key if necessary \n\t   (aliena nobis, nostra plus aliis placent) */\n\tif( isCertificate || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t( ( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE ) && \\\n\t\t  !nonSigningKey ) )\n\t\t{\n\t\t/* If it's a self-signed certificate then the issuer is also the \n\t\t   subject */\n\t\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t\tissuerCertInfoPtr = certInfoPtr;\n\t\telse\n\t\t\t{\n\t\t\tCRYPT_CERTIFICATE dataOnlyCert;\n\n\t\t\t/* Get the data-only certificate from the context */\n\t\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t\t\t  &dataOnlyCert, OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( ( status == CRYPT_ARGERROR_OBJECT ) ? \\\n\t\t\t\t\t\tCRYPT_ARGERROR_VALUE : status );\n\t\t\t\t}\n\t\t\tstatus = krnlAcquireObject( dataOnlyCert, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ARGERROR_VALUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tREQUIRES_OBJECT( sanityCheckCert( issuerCertInfoPtr ),\n\t\t\t\t\t\t\t issuerCertInfoPtr->objectHandle );\n\t\t\tissuerCertAcquired = TRUE;\n\t\t\t}\n\n\t\t/* Check the signing key */\n\t\tstatus = checkSigningKey( certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\t  iSignContext, isCertificate );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( issuerCertAcquired == TRUE )\n\t\t\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Perform any final initialisation of the certificate object before we \n\t   sign it */\n\tstatus = initSignatureInfo( certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\tiSignContext, isCertificate, &hashAlgo,\n\t\t\t\t\t\t\t\tsignatureLevel,\n\t\t\t\t\t\t\t\t( signatureLevel > CRYPT_SIGNATURELEVEL_NONE ) ? \\\n\t\t\t\t\t\t\t\t\t&extraDataLength : NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( issuerCertAcquired == TRUE )\n\t\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\treturn( status );\n\t\t}\n\n\t/* Create the signed certifcate object */\n\tstatus = createSignedObject( certInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\t iSignContext, signatureLevel, \n\t\t\t\t\t\t\t\t extraDataLength, hashAlgo, nonSigningKey );\n\tif( issuerCertAcquired == TRUE )\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( certInfoPtr->certificate != NULL );\n\n\t/* If it's a pseudo-signed certificate object, we're done */\n\tif( nonSigningKey )\n\t\t{\n\t\tENSURES( sanityCheckCert( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a certification request it's now self-signed.  In addition \n\t   the signature has been checked since we've just created it */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SIGCHECKED );\n\n\t/* If it's not an object type with special-case post-signing\n\t   requirements we're done */\n\tif( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\tcertInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tENSURES( sanityCheckCert( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Recover information such as pointers to encoded certificate data */\n\tstatus = recoverCertData( certInfoPtr, certInfoPtr->type, \n\t\t\t\t\t\t\t  certInfoPtr->certificate, \n\t\t\t\t\t\t\t  certInfoPtr->certificateSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckCert( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/certval.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Validity Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTVAL\n\n/* Mapping of cryptlib certificate status types to and from RTCS validity \n   codes */\n\nstatic const MAP_TABLE certStatusToEnumMapTbl[] = {\n\t{ 0, CRYPT_CERTSTATUS_VALID },\n\t{ 1, CRYPT_CERTSTATUS_NOTVALID },\n\t{ 2, CRYPT_CERTSTATUS_NONAUTHORITATIVE },\n\t{ 3, CRYPT_CERTSTATUS_UNKNOWN },\n\t{ CRYPT_ERROR, 0 }, \n\t\t{ CRYPT_ERROR, 0 }\n\t};\n\nstatic const MAP_TABLE enumToCertStatusMapTbl[] = {\n\t{ CRYPT_CERTSTATUS_VALID, 0 },\n\t{ CRYPT_CERTSTATUS_NOTVALID, 1 },\n\t{ CRYPT_CERTSTATUS_NONAUTHORITATIVE, 2 },\n\t{ CRYPT_CERTSTATUS_UNKNOWN, 3 },\n\t{ CRYPT_ERROR, 0 }, \n\t\t{ CRYPT_ERROR, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the validity info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckValInfo( IN const VALIDITY_INFO *validityInfo )\n\t{\n\tassert( isReadPtr( validityInfo, sizeof( VALIDITY_INFO ) ) );\n\n\tif( validityInfo == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckValInfo: Missing revocation info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check validity information */\n\tif( validityInfo->isValid != TRUE && \\\n\t\tvalidityInfo->isValid != FALSE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckValInfo: Validity status\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRange( validityInfo->extStatus, CRYPT_CERTSTATUS ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckValInfo: Extended validity status\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check ID data */\n\tif( checksumData( validityInfo->data, \n\t\t\t\t\t  KEYID_SIZE ) != validityInfo->dCheck )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckValInfo: ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( validityInfo->attributes ) || \\\n\t\t!DATAPTR_ISVALID( validityInfo->prev ) || \\\n\t\t!DATAPTR_ISVALID( validityInfo->next ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckValInfo: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAdd/Delete/Check Validity Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an entry in a validity information list */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic const VALIDITY_INFO *findValidityEntry( IN const DATAPTR listHead,\n\t\t\t\t\t\t\t\t\t\t\t   IN_BUFFER( valueLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst void *value,\n\t\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_FIXED( KEYID_SIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int valueLength )\n\t{\n\tVALIDITY_INFO *listPtr;\n\tconst int vCheck = checksumData( value, valueLength );\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES_N( valueLength == KEYID_SIZE );\n\n\t/* Check whether this entry is present in the list */\n\tLOOP_LARGE( listPtr = DATAPTR_GET( listHead ),\n\t\t\t\tlistPtr != NULL, \n\t\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tREQUIRES_N( sanityCheckValInfo( listPtr ) );\n\n\t\tif( listPtr->dCheck == vCheck && \\\n\t\t\t!memcmp( listPtr->data, value, valueLength ) )\n\t\t\treturn( listPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/* Add an entry to a validity information list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addValidityEntry( INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t  OUT_OPT_PTR_COND VALIDITY_INFO **newEntryPosition,\n\t\t\t\t\t  IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t  IN_LENGTH_FIXED( KEYID_SIZE ) const int valueLength )\n\t{\n\tDATAPTR listHead = *listHeadPtr;\n\tVALIDITY_INFO *listHeadElement = NULL, *newElement;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( newEntryPosition == NULL || \\\n\t\t\tisWritePtr( newEntryPosition, sizeof( VALIDITY_INFO * ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( DATAPTR_ISVALID_PTR( listHeadPtr ) );\n\tREQUIRES( valueLength == KEYID_SIZE );\n\n\t/* Clear return value */\n\tif( newEntryPosition != NULL )\n\t\t*newEntryPosition = NULL;\n\n\t/* Make sure that this entry isn't already present */\n\tif( DATAPTR_ISSET( listHead ) )\n\t\t{\n\t\tif( findValidityEntry( listHead, value, valueLength ) != NULL )\n\t\t\t{\n\t\t\t/* If we found an entry that matches the one being added then \n\t\t\t   we can't add it again */\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\n\t\t/* Remember the first list element so that we can link in the new\n\t\t   element */\n\t\tlistHeadElement = DATAPTR_GET( listHead );\n\t\tENSURES( listHeadElement != NULL );\n\t\t}\n\n\t/* Allocate memory for the new element and copy the information across */\n\tif( ( newElement = ( VALIDITY_INFO * ) \\\n\t\t\tclAlloc( \"addValidityEntry\", sizeof( VALIDITY_INFO ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( newElement, 0, sizeof( VALIDITY_INFO ) );\n\tREQUIRES( rangeCheck( valueLength, 1, KEYID_SIZE ) );\n\tmemcpy( newElement->data, value, valueLength );\n\tnewElement->dCheck = checksumData( value, valueLength );\n\tDATAPTR_SET( newElement->attributes, NULL );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\n\t/* Set the status to invalid/unknown by default, this means that any \n\t   entries that we can't do anything with automatically get the correct \n\t   status associated with them */\n\tnewElement->isValid = FALSE;\n\tnewElement->extStatus = CRYPT_CERTSTATUS_UNKNOWN;\n\n\tENSURES( sanityCheckValInfo( newElement ) );\n\n\t/* Insert the new element into the list */\n\tinsertDoubleListElement( listHeadPtr, listHeadElement, newElement, \n\t\t\t\t\t\t\t VALIDITY_INFO );\n\tif( newEntryPosition != NULL )\n\t\t*newEntryPosition = newElement;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete a validity information list */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteValidityEntries( INOUT_PTR DATAPTR *listHeadPtr )\n\t{\n\tDATAPTR listHead = *listHeadPtr;\n\tVALIDITY_INFO *validityListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\n\t/* If the list was empty, return now */\n\tif( DATAPTR_ISNULL( listHead ) )\n\t\treturn;\n\n\t/* Destroy any remaining list items */\n\tLOOP_LARGE_INITCHECK( validityListCursor = DATAPTR_GET( listHead ),\n\t\t\t\t\t\t  validityListCursor != NULL )\n\t\t{\n\t\tVALIDITY_INFO *itemToFree = validityListCursor;\n\n\t\tREQUIRES_V( sanityCheckValInfo( itemToFree ) );\n\n\t\tvalidityListCursor = DATAPTR_GET( validityListCursor->next );\n\t\tif( DATAPTR_ISSET( itemToFree->attributes ) )\n\t\t\tdeleteAttributes( &itemToFree->attributes );\n\t\tzeroise( itemToFree, sizeof( VALIDITY_INFO ) );\n\t\tclFree( \"deleteValidityEntries\", itemToFree );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\tDATAPTR_SET_PTR( listHeadPtr, NULL );\n\t}\n\n/* Copy a validity information list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyValidityEntries( INOUT_PTR DATAPTR *destListHeadPtr,\n\t\t\t\t\t\t IN const DATAPTR srcList )\n\t{\n\tconst VALIDITY_INFO *srcListCursor;\n\tVALIDITY_INFO *destListCursor = NULL;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( destListHeadPtr, sizeof( DATAPTR ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcList ) );\n\n\t/* Copy all validation entries from source to destination */\n\tLOOP_LARGE( srcListCursor = DATAPTR_GET( srcList ), \n\t\t\t\tsrcListCursor != NULL,\n\t\t\t\tsrcListCursor = DATAPTR_GET( srcListCursor->next ) )\n\t\t{\n\t\tVALIDITY_INFO *newElement;\n\n\t\tREQUIRES( sanityCheckValInfo( srcListCursor ) );\n\n\t\t/* Allocate the new entry and copy the data from the existing one\n\t\t   across.  We don't copy the attributes because there aren't any\n\t\t   that should be carried from request to response */\n\t\tif( ( newElement = ( VALIDITY_INFO * ) \\\n\t\t\t\t\tclAlloc( \"copyValidityEntries\", \\\n\t\t\t\t\t\t\t sizeof( VALIDITY_INFO ) ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tmemcpy( newElement, srcListCursor, sizeof( VALIDITY_INFO ) );\n\t\tDATAPTR_SET( newElement->attributes, NULL );\n\t\tDATAPTR_SET( newElement->prev, NULL );\n\t\tDATAPTR_SET( newElement->next, NULL );\n\n\t\t/* Set the status to invalid/unknown by default, this means that any\n\t\t   entries that we can't do anything with automatically get the\n\t\t   correct status associated with them */\n\t\tnewElement->isValid = FALSE;\n\t\tnewElement->extStatus = CRYPT_CERTSTATUS_UNKNOWN;\n\n\t\tENSURES( sanityCheckValInfo( newElement ) );\n\n\t\t/* Link the new element into the list */\n\t\tinsertDoubleListElement( destListHeadPtr, destListCursor, newElement, \n\t\t\t\t\t\t\t\t VALIDITY_INFO );\n\t\tdestListCursor = newElement;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Prepare the entries in a certificate validity list prior to encoding \n   them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nint prepareValidityEntries( IN_DATAPTR_OPT const DATAPTR listHead, \n\t\t\t\t\t\t\tOUT_PTR_xCOND VALIDITY_INFO **errorEntry,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst VALIDITY_INFO *validityEntry;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( errorEntry, sizeof( VALIDITY_INFO * ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\n\t/* Clear return values */\n\t*errorEntry = NULL;\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If the validity list is empty there's nothing to do */\n\tif( DATAPTR_ISNULL( listHead ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check the attributes for each entry in a validation list */\n\tLOOP_LARGE( validityEntry = DATAPTR_GET( listHead ), \n\t\t\t\tvalidityEntry != NULL, \n\t\t\t\tvalidityEntry = DATAPTR_GET( validityEntry->next ) )\n\t\t{\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckValInfo( validityEntry ) );\n\n\t\t/* If there's nothing to check, skip this entry */\n\t\tif( DATAPTR_ISNULL( validityEntry->attributes ) )\n\t\t\tcontinue;\n\n\t\tstatus = checkAttributes( ATTRIBUTE_CERTIFICATE,\n\t\t\t\t\t\t\t\t  validityEntry->attributes,\n\t\t\t\t\t\t\t\t  errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Remember the entry that caused the problem */\n\t\t\t*errorEntry = ( VALIDITY_INFO * ) validityEntry;\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the entries in an RTCS response object against a certificate store.  \n   The semantics for this one are a bit odd, the source information for the \n   check is from a request but the destination information is in a response.  \n   Since we don't have a copy-and-verify function we do the checking from \n   the response even though technically it's the request data that's being \n   checked */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkRTCSResponse( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE const CRYPT_KEYSET iCryptKeyset )\n\t{\n\tconst CERT_VAL_INFO *valInfo = certInfoPtr->cCertVal;\n\tVALIDITY_INFO *validityInfo;\n\tBOOLEAN isInvalid = FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( iCryptKeyset ) );\n\n\t/* Walk down the list of validity entries fetching status information\n\t   on each one from the certificate store */\n\tLOOP_LARGE( validityInfo = DATAPTR_GET( valInfo->validityInfo ), \n\t\t\t\tvalidityInfo != NULL, \n\t\t\t\tvalidityInfo = DATAPTR_GET( validityInfo->next ) )\n\t\t{\n\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckValInfo( validityInfo ) );\n\n\t\t/* Determine the validity of the object */\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,\n\t\t\t\t\t\t\t   validityInfo->data, KEYID_SIZE, NULL, 0,\n\t\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\t\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_GETKEY,\n\t\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* The certificate is present and OK */\n\t\t\tvalidityInfo->isValid = TRUE;\n\t\t\tvalidityInfo->extStatus = CRYPT_CERTSTATUS_VALID;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The certificate isn't present/OK, record the fact that we've \n\t\t\t   seen at least one invalid certificate */\n\t\t\tvalidityInfo->isValid = FALSE;\n\t\t\tvalidityInfo->extStatus = CRYPT_CERTSTATUS_NOTVALID;\n\t\t\tisInvalid = TRUE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If at least one certificate was invalid indicate this to the caller.  \n\t   Note that if there are multiple certificates present in the query \n\t   it's up to the caller to step through the list to find out which ones \n\t   were invalid */\n\treturn( isInvalid ? CRYPT_ERROR_INVALID : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead RTCS Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read RTCS resquest entries:\n\n\tEntry ::= SEQUENCE {\n\t\tcertHash\t\tOCTET STRING SIZE(20),\n\t\tlegacyID\t\tIssuerAndSerialNumber OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRtcsRequestEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr )\n\t{\n\tBYTE idBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint endPos, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\n\t/* Determine the overall size of the entry */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the certificate ID */\n\tstatus = readOctetString( stream, idBuffer, &length,\n\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\tif( cryptStatusOK( status ) && \\\n\t\tstell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )\n\t\t{\n\t\t/* Skip the legacy ID */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the entry to the validity information list */\n\treturn( addValidityEntry( listHeadPtr, NULL, idBuffer, KEYID_SIZE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readRTCSRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT_PTR DATAPTR *listHeadPtr )\n\t{\n\tint length, noRequestEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\n\t/* Read the outer wrapper */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SEQUENCE OF request information */\n\tLOOP_LARGE( noRequestEntries = 0,\n\t\t\t\tlength > 0 && noRequestEntries < 100, \n\t\t\t\tnoRequestEntries++ )\n\t\t{\n\t\tconst int innerStartPos = stell( stream );\n\n\t\tREQUIRES( isIntegerRangeNZ( innerStartPos ) );\n\n\t\tstatus = readRtcsRequestEntry( stream, listHeadPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength -= stell( stream ) - innerStartPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noRequestEntries >= 100 )\n\t\t{\n\t\t/* We allow reasonable numbers of entries in a request, but one with \n\t\t   more than a hundred entries has something wrong with it */\n\t\tDEBUG_DIAG(( \"RTCS request contains more than 100 entries\" ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite RTCS Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write RTCS resquest entries */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofRtcsRequestEntry( STDC_UNUSED const VALIDITY_INFO *rtcsEntry )\n\t{\n\tassert( isReadPtr( rtcsEntry, sizeof( VALIDITY_INFO ) ) );\n\n\treturn( sizeofShortObject( sizeofShortObject( KEYID_SIZE ) ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofRtcsRequestEntries( IN const DATAPTR rtcsEntries )\n\t{\n\tVALIDITY_INFO *validityInfo;\n\tint requestInfoLength = 0, status, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISVALID( rtcsEntries ) );\n\n\t/* Determine how big the encoded RTCS request will be */\n\tLOOP_LARGE( validityInfo = DATAPTR_GET( rtcsEntries ), \n\t\t\t\tvalidityInfo != NULL,\n\t\t\t\tvalidityInfo = DATAPTR_GET( validityInfo->next ) )\n\t\t{\n\t\tint requestEntrySize;\n\t\t\n\t\tREQUIRES( sanityCheckValInfo( validityInfo ) );\n\n\t\tstatus = requestEntrySize = \\\n\t\t\t\t\tsizeofRtcsRequestEntry( validityInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\trequestInfoLength += requestEntrySize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( requestInfoLength );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRtcsRequestEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  const VALIDITY_INFO *rtcsEntry )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( rtcsEntry, sizeof( VALIDITY_INFO ) ) );\n\n\t/* Write the header and ID information */\n\twriteSequence( stream, sizeofObject( KEYID_SIZE ) );\n\treturn( writeOctetString( stream, rtcsEntry->data, KEYID_SIZE,\n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRtcsRequestEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN const DATAPTR rtcsEntries )\n\t{\n\tVALIDITY_INFO *validityInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Write the SEQUENCE OF validity information */\n\tLOOP_LARGE( validityInfo = DATAPTR_GET( rtcsEntries ), \n\t\t\t\tvalidityInfo != NULL,\n\t\t\t\tvalidityInfo = DATAPTR_GET( validityInfo->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckValInfo( validityInfo ) );\n\n\t\tstatus = writeRtcsRequestEntry( stream, validityInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read RTCS response entries:\n\n\tEntry ::= SEQUENCE {\t\t\t\t-- Basic response\n\t\tcertHash\t\tOCTET STRING SIZE(20),\n\t\tstatus\t\t\tBOOLEAN\n\t\t}\n\n\tEntry ::= SEQUENCE {\t\t\t\t-- Full response\n\t\tcertHash\t\tOCTET STRING SIZE(20),\n\t\tstatus\t\t\tENUMERATED,\n\t\tstatusInfo\t\tANY DEFINED BY status OPTIONAL,\n\t\textensions\t[0]\tExtensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int readRtcsResponseEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t\t  const BOOLEAN isFullResponse,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tVALIDITY_INFO *newEntry;\n\tBYTE idBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint endPos, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( isFullResponse == TRUE || isFullResponse == FALSE );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Determine the overall size of the entry */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the ID information */\n\tstatus = readOctetString( stream, idBuffer, &length, \\\n\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the entry to the validity information list */\n\tstatus = addValidityEntry( listHeadPtr, &newEntry, idBuffer, \n\t\t\t\t\t\t\t   KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the status information and record the valid/not-valid status  */\n\tif( isFullResponse )\n\t\t{\n\t\tint value;\n\n\t\tstatus = readEnumerated( stream, &value );\n\t\tif( cryptStatusOK( status ) && ( value < 0 || value > 10 ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = mapValue( value, &value, certStatusToEnumMapTbl, \n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( certStatusToEnumMapTbl, \n\t\t\t\t\t\t\t\t\t\t\t\t   MAP_TABLE ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tnewEntry->extStatus = value;\n\t\t\tnewEntry->isValid = \\\n\t\t\t\t\t\t( newEntry->extStatus == CRYPT_CERTSTATUS_VALID ) ? \\\n\t\t\t\t\t\tTRUE : FALSE;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readBoolean( stream, &newEntry->isValid );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tnewEntry->extStatus = ( newEntry->isValid == TRUE ) ? \\\n\t\t\t\t\t\tCRYPT_CERTSTATUS_VALID : CRYPT_CERTSTATUS_NOTVALID;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) || \\\n\t\tstell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )\n\t\treturn( status );\n\n\t/* Read the extensions.  Since these are per-entry extensions we read\n\t   the wrapper here and read the extensions themselves as\n\t   CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_RTCS to make sure\n\t   that they're processed as required */\n\tstatus = readConstructed( stream, &length, 0 );\n\tif( cryptStatusOK( status ) && length > 0 )\n\t\t{\n\t\tstatus = readAttributes( stream, &newEntry->attributes,\n\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, length, \n\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readRTCSResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT_PTR DATAPTR *listHeadPtr,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint length, noResponseEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Read the SEQUENCE OF response information */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#if 0\t/* 11/9/17 See below */\n\tendPos = stell( stream ) + length;\n#endif /* 0 */\n\tLOOP_LARGE( noResponseEntries = 0,\n\t\t\t\tlength > 0 && noResponseEntries < 100,\n\t\t\t\tnoResponseEntries++ )\n\t\t{\n\t\tconst int innerStartPos = stell( stream );\n\n\t\tREQUIRES( isIntegerRangeNZ( innerStartPos ) );\n\n\t\tstatus = readRtcsResponseEntry( stream, listHeadPtr, FALSE,\n\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength -= stell( stream ) - innerStartPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noResponseEntries >= 100 )\n\t\t{\n\t\t/* We allow reasonable numbers of entries in a response, but one with \n\t\t   more than a hundred entries has something wrong with it */\n\t\tDEBUG_DIAG(( \"RTCS response contains more than 100 entries\" ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n#if 0\t/* 11/9/17 Since we always send basic requests/responses, there are \n\t\t\t\t   no attributes to read */\n\t/* Read the extensions if there are any present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\tCRYPT_CERTTYPE_RTCS_RESPONSE, endPos - stell( stream ),\n\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* 0 */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write RTCS response entries */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofRtcsResponseEntry( INOUT VALIDITY_INFO *rtcsEntry,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isFullResponse )\n\t{\n\tint status;\n\n\tassert( isWritePtr( rtcsEntry, sizeof( VALIDITY_INFO ) ) );\n\n\tREQUIRES( isFullResponse == TRUE || isFullResponse == FALSE );\n\n\t/* If it's a basic response the size is fairly easy to calculate */\n\tif( !isFullResponse )\n\t\t{\n\t\treturn( sizeofShortObject( sizeofShortObject( KEYID_SIZE ) + \\\n\t\t\t\t\t\t\t\t   sizeofBoolean() ) );\n\t\t}\n\n\t/* Remember the encoded attribute size for later when we write the\n\t   attributes */\n\tstatus = rtcsEntry->attributeSize = \\\n\t\t\t\t\tsizeofAttributes( rtcsEntry->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( sizeofShortObject( sizeofShortObject( KEYID_SIZE ) + \\\n\t\t\t\t\t\t\t   sizeofEnumerated( 1 ) + \\\n\t\t\t\t\t\t\t   ( ( rtcsEntry->attributeSize ) ? \\\n\t\t\t\t\t\t\t\t sizeofShortObject( rtcsEntry->attributeSize ) : 0 ) ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofRtcsResponseEntries( IN const DATAPTR rtcsEntries,\n\t\t\t\t\t\t\t   const BOOLEAN isExtendedResponse )\n\t{\n\tVALIDITY_INFO *validityInfo;\n\tint responseInfoLength = 0, status, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISVALID( rtcsEntries ) );\n\n\tREQUIRES( isExtendedResponse == TRUE || isExtendedResponse == FALSE );\n\n\t/* Determine how big the encoded RTCS responses will be */\n\tLOOP_LARGE( validityInfo = DATAPTR_GET( rtcsEntries ), \n\t\t\t\tvalidityInfo != NULL,\n\t\t\t\tvalidityInfo = DATAPTR_GET( validityInfo->next ) )\n\t\t{\n\t\tint responseEntrySize;\n\t\t\n\t\tREQUIRES( sanityCheckValInfo( validityInfo ) );\n\n\t\tstatus = responseEntrySize = \\\n\t\t\t\t\t\tsizeofRtcsResponseEntry( validityInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t isExtendedResponse );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tresponseInfoLength += responseEntrySize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( responseInfoLength );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRtcsResponseEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN const VALIDITY_INFO *rtcsEntry,\n\t\t\t\t\t\t\t\t   const BOOLEAN isExtendedResponse )\n\t{\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( rtcsEntry, sizeof( VALIDITY_INFO ) ) );\n\t\n\tREQUIRES( isExtendedResponse == TRUE || isExtendedResponse == FALSE );\n\n\t/* If it's a basic response it's a straightforward fixed-length\n\t   object */\n\tif( !isExtendedResponse )\n\t\t{\n\t\twriteSequence( stream, sizeofObject( KEYID_SIZE ) +\n\t\t\t\t\t\t\t   sizeofBoolean() );\n\t\twriteOctetString( stream, rtcsEntry->data, KEYID_SIZE, DEFAULT_TAG );\n\t\treturn( writeBoolean( stream, rtcsEntry->isValid, DEFAULT_TAG ) );\n\t\t}\n\n\t/* Write an extended response */\n\tstatus = mapValue( rtcsEntry->extStatus, &value, enumToCertStatusMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( enumToCertStatusMapTbl, \n\t\t\t\t\t\t\t\t\t\t   MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\twriteSequence( stream, sizeofObject( KEYID_SIZE ) + sizeofEnumerated( 1 ) );\n\twriteOctetString( stream, rtcsEntry->data, KEYID_SIZE, DEFAULT_TAG );\n\tstatus = writeEnumerated( stream, value, DEFAULT_TAG );\n\tif( cryptStatusError( status ) || rtcsEntry->attributeSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the per-entry extensions.  Since these are per-entry extensions\n\t   we write them as CRYPT_CERTTYPE_NONE rather than CRYPT_CERTTYPE_RTCS\n\t   to make sure that they're processed as required */\n\treturn( writeAttributes( stream, rtcsEntry->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_NONE, rtcsEntry->attributeSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRtcsResponseEntries( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN const DATAPTR rtcsEntries,\n\t\t\t\t\t\t\t  const BOOLEAN isExtendedResponse )\n\t{\n\tVALIDITY_INFO *validityInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isExtendedResponse == TRUE || isExtendedResponse == FALSE );\n\n\t/* Write the SEQUENCE OF validity information */\n\tLOOP_LARGE( validityInfo = DATAPTR_GET( rtcsEntries ), \n\t\t\t\tvalidityInfo != NULL,\n\t\t\t\tvalidityInfo = DATAPTR_GET( validityInfo->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckValInfo( validityInfo ) );\n\n\t\tstatus = writeRtcsResponseEntry( stream, validityInfo, \n\t\t\t\t\t\t\t\t\t\t isExtendedResponse );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTVAL */\n"
  },
  {
    "path": "deps/cl345/cert/chain.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Certificate Chain Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL ) \n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n#endif /* Compiler-specific includes */\n\n/* When matching by subjectKeyIdentifier we don't use values less than 40\n   bits because some CAs use monotonically increasing sequence numbers for \n   the sKID, which can clash with the same values when used by other CAs */\n\n#define MIN_SKID_SIZE\t5\n\n/* A structure for storing pointers to parent and child (issuer and subject)\n   names, key identifiers, and serial numbers (for finding a certificate by \n   issuerAndSerialNumber) and one for storing pointers to chaining \n   information.  We don't bother making these safe pointers because they've \n   live only as long as standard stack-based pointers */\n\ntypedef struct {\n\tBUFFER_FIXED( issuerDNsize ) \\\n\tconst void *issuerDN;\n\tBUFFER_FIXED( subjectDNsize ) \\\n\tconst void *subjectDN;\n\tint issuerDNsize, subjectDNsize;\n\tBUFFER_FIXED( serialNumberSize ) \\\n\tconst void *serialNumber;\n\tint serialNumberSize;\n\tBUFFER_OPT_FIXED( subjectKeyIDsize ) \\\n\tconst void *subjectKeyIdentifier;\n\tint subjectKeyIDsize;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tBUFFER_OPT_FIXED( issuerKeyIDsize ) \\\n\tconst void *issuerKeyIdentifier;\n\tint issuerKeyIDsize;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\tDATAPTR attributes;\n\t} CHAIN_INFO;\n\ntypedef struct {\n\tBUFFER_FIXED( DNsize ) \\\n\tconst void *DN;\n\tint DNsize;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tBUFFER_FIXED( keyIDsize ) \\\n\tconst void *keyIdentifier;\n\tint keyIDsize;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\t} CHAINING_INFO;\n\n/* Match an identifier in a chain information structure against a chaining \n   information structure */\n\n#define matchDN( chainingInfo, chainInfo, type ) \\\n\t\t( ( chainingInfo )->DNsize >= MIN_DN_SIZE && \\\n\t\t  ( chainingInfo )->DNsize == ( chainInfo )->type##DNsize && \\\n\t\t  !memcmp( ( chainingInfo )->DN, ( chainInfo )->type##DN, \\\n\t\t\t\t   ( chainInfo )->type##DNsize ) )\n\n#define matchKeyID( chainingInfo, chainInfo, type ) \\\n\t\t( ( chainingInfo )->keyIDsize > MIN_SKID_SIZE && \\\n\t\t  ( chainingInfo )->keyIDsize == ( chainInfo )->type##KeyIDsize && \\\n\t\t  !memcmp( ( chainingInfo )->keyIdentifier, \\\n\t\t\t\t   ( chainInfo )->type##KeyIdentifier, \\\n\t\t\t\t   ( chainInfo )->type##KeyIDsize ) )\n\n/* Match an identifier in a chain information structure */\n\n#define matchSubjectKeyID( chainInfo, keyID, keyIDlength ) \\\n\t\t( ( chainInfo )->subjectKeyIDsize > MIN_SKID_SIZE && \\\n\t\t  ( chainInfo )->subjectKeyIDsize == keyIDlength && \\\n\t\t  !memcmp( ( chainInfo )->subjectKeyIdentifier, \\\n\t\t\t\t   keyID, keyIDlength ) )\n\n#define matchIssuerDN( chainInfo, issuerDNptr, issuerDNsize ) \\\n\t\t( ( chainInfo )->issuerDNsize >= MIN_DN_SIZE && \\\n\t\t  (\tchainInfo )->issuerDNsize == issuerDNsize && \\\n\t\t\t!memcmp( ( chainInfo)->issuerDN, issuerDNptr, \\\n\t\t\t\t\t issuerDNsize ) )\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy subject or issuer chaining values from the chaining information */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void getSubjectChainingInfo( OUT CHAINING_INFO *chainingInfo,\n\t\t\t\t\t\t\t\t\tconst CHAIN_INFO *chainInfo )\n\t{\n\tassert( isWritePtr( chainingInfo, sizeof( CHAINING_INFO ) ) );\n\tassert( isReadPtr( chainInfo, sizeof( CHAIN_INFO ) ) );\n\n\tmemset( chainingInfo, 0, sizeof( CHAINING_INFO ) );\n\tchainingInfo->DN = chainInfo->subjectDN;\n\tchainingInfo->DNsize = chainInfo->subjectDNsize;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tchainingInfo->keyIdentifier = chainInfo->subjectKeyIdentifier;\n\tchainingInfo->keyIDsize = chainInfo->subjectKeyIDsize;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void getIssuerChainingInfo( OUT CHAINING_INFO *chainingInfo,\n\t\t\t\t\t\t\t\t   const CHAIN_INFO *chainInfo )\n\t{\n\tassert( isWritePtr( chainingInfo, sizeof( CHAINING_INFO ) ) );\n\tassert( isReadPtr( chainInfo, sizeof( CHAIN_INFO ) ) );\n\n\tmemset( chainingInfo, 0, sizeof( CHAINING_INFO ) );\n\tchainingInfo->DN = chainInfo->issuerDN;\n\tchainingInfo->DNsize = chainInfo->issuerDNsize;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tchainingInfo->keyIdentifier = chainInfo->issuerKeyIdentifier;\n\tchainingInfo->keyIDsize = chainInfo->issuerKeyIDsize;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\t}\n\n/* Determine whether a given certificate is the subject or issuer for the \n   requested certificate based on the chaining information.  We chain by \n   issuer DN if possible but if that fails we use the keyID.  This is \n   somewhat dodgy since it can lead to the situation where a certificate \n   supposedly issued by Verisign Class 1 Public Primary Certification \n   Authority is actually issued by Honest Joe's Used Cars but the standard \n   requires this as a fallback (PKIX section 4.2.1.1).\n   \n   There are actually two different interpretations of chaining by keyID, \n   the first says that the keyID is a non-DN identifier that can survive \n   operations such as cross-certification and re-parenting so that if a \n   straight chain by DN fails then a chain by keyID is possible as a \n   fallback option.  The second is that the keyID is a disambiguator if \n   multiple paths in a chain-by-DN scenario are present in a spaghetti PKI.  \n   Since the latter is rather unlikely to occur in a standard PKCS #7/SSL \n   certificate chain (half the implementations around wouldn't be able to \n   assemble the chain any more) we use the former interpretation by default \n   but enable the latter if useStrictChaining is set.\n   \n   If useStrictChaining is enabled we require that the DN *and* the keyID \n   match, which (even without a spaghetti PKI being in effect) is required \n   to handle PKIX weirdness in which multiple potential issuers can be \n   present in a chain due to CA certificate renewals/reparenting.  We don't \n   do this by default because too many CAs get keyID chaining wrong, leading \n   to apparent breaks in the chain when the keyID fails to match.\n   \n   We don't have to worry about strict chaining for the issuer match because\n   we only use it when we're walking down the chain looking for a leaf \n   certificate */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN isSubject( const CHAINING_INFO *chainingInfo,\n\t\t\t\t\t\t  const CHAIN_INFO *chainInfo,\n\t\t\t\t\t\t  const BOOLEAN useStrictChaining )\n\t{\n\tBOOLEAN dnChains = FALSE, keyIDchains = FALSE;\n\n\tassert( isReadPtr( chainingInfo, sizeof( CHAINING_INFO ) ) );\n\tassert( isReadPtr( chainInfo, sizeof( CHAIN_INFO ) ) );\n\n\tREQUIRES_B( useStrictChaining == TRUE || useStrictChaining == FALSE );\n\n\t/* Check for chaining by DN and keyID */\n\tif( matchDN( chainingInfo, chainInfo, subject ) )\n\t\tdnChains = TRUE;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tif( matchKeyID( chainingInfo, chainInfo, subject ) )\n\t\tkeyIDchains = TRUE;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* If we're using strict chaining, both the DN and the keyID must \n\t   chain */\n\tif( useStrictChaining )\n\t\treturn( dnChains && keyIDchains );\n\n\t/* We're not using strict chaining, either can chain */\n\treturn( dnChains || keyIDchains );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN isIssuer( const CHAINING_INFO *chainingInfo,\n\t\t\t\t\t\t const CHAIN_INFO *chainInfo )\n\t{\n\tassert( isReadPtr( chainingInfo, sizeof( CHAINING_INFO ) ) );\n\tassert( isReadPtr( chainInfo, sizeof( CHAIN_INFO ) ) );\n\n\t/* In the simplest case we chain by name.  This works for almost all\n\t   certificates */\n\tif( matchDN( chainingInfo, chainInfo, issuer ) )\n\t\treturn( TRUE );\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* If that fails we chain by keyID */\n\tif( matchKeyID( chainingInfo, chainInfo, issuer ) )\n\t\treturn( TRUE );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\treturn( FALSE );\n\t}\n\n/* Get the location and size of certificate attribute data required for\n   chaining */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int getChainingAttribute( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t OUT_BUFFER_ALLOC_OPT( *attributeLength ) \\\n\t\t\t\t\t\t\t\t\tconst void **attributePtrPtr, \n\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *attributeLength )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( attributePtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( attributeLength, sizeof( int * ) ) );\n\n\tENSURES( attributeType == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER || \\\n\t\t\t attributeType == CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER );\n\n\t/* Clear return values */\n\t*attributePtrPtr = NULL;\n\t*attributeLength = 0;\n\n\t/* Find the requested attribute and return a pointer to it */\n\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t   attributeType, CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t{\n\t\t/* If the chaining attribute data isn't present then this isn't an \n\t\t   error */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( getAttributeDataPtr( attributePtr, ( void ** ) attributePtrPtr, \n\t\t\t\t\t\t\t\t attributeLength ) );\n\t}\n\n/* Free a certificate chain */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void freeCertChain( IN_ARRAY( certChainSize ) \\\n\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertChain,\n\t\t\t\t\t\t   IN_RANGE( 1, MAX_CHAINLENGTH ) \\\n\t\t\t\t\t\t\t\tconst int certChainSize )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( iCertChain, \n\t\t\t\t\t\t\t   sizeof( CRYPT_CERTIFICATE ) * certChainSize ) );\n\n\tREQUIRES_V( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );\n\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\t/* If we ran into an error while working with a certificate in the \n\t\t   chain then this position may be empty, in which case we skip it */\n\t\tif( iCertChain[ i ] == CRYPT_ERROR )\n\t\t\tcontinue;\n\n\t\tREQUIRES_V( isHandleRangeValid( iCertChain[ i ] ) );\n\n\t\t/* Clear the certificate at this position */\n\t\tkrnlSendNotifier( iCertChain[ i ], IMESSAGE_DESTROY );\n\t\tiCertChain[ i ] = CRYPT_ERROR;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\n/* Convert a certificate object into a certificate-chain object.  This is \n   necessary because at the point when we're importing the certificates\n   to build the chain we don't know which one is the leaf so we have to\n   import them all as certificates, and once that's done we can't change\n   the object type any more.  Because of this the only way to change\n   the object type is to re-create it as a certificate-chain object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int convertCertToChain( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertChain,\n\t\t\t\t\t\t\t   IN_HANDLE CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t\t\t   const BOOLEAN isDataOnlyCert )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tDYNBUF certDB;\n\tint status;\n\n\tassert( isWritePtr( iCertChain, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( isDataOnlyCert == TRUE || isDataOnlyCert == FALSE );\n\n\t/* Clear return value */\n\t*iCertChain = CRYPT_ERROR;\n\n\t/* Export the leaf certificate and re-import it to create the required \n\t   certificate-chain object, specifying KEYMGMT_FLAG_CERT_AS_CERTCHAIN \n\t   to ensure that the certificate is imported as a single-entry\n\t   certificate chain */\n\tstatus = dynCreateCert( &certDB, iCertificate, \n\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageCreateObjectIndirectInfoEx( &createInfo, \n\t\t\t\t\t\t\tdynData( certDB ), dynLength( certDB ), \n\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE, isDataOnlyCert ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT | \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_CERT_AS_CERTCHAIN : \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_CERT_AS_CERTCHAIN );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tdynDestroy( &certDB );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've now got the same certificate object as before, but with a \n\t   subtype of certificate chain rather than certificate, replace the \n\t   existing object with the new one */\n\tkrnlSendNotifier( iCertificate, IMESSAGE_DESTROY );\n\t*iCertChain = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBuild a Certificate Chain\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Build up the parent/child pointers for a certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int buildChainInfo( OUT_ARRAY( certChainSize ) CHAIN_INFO *chainInfo,\n\t\t\t\t\t\t   IN_ARRAY( certChainSize ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_CERTIFICATE *iCertChain,\n\t\t\t\t\t\t   IN_RANGE( 1, MAX_CHAINLENGTH ) \\\n\t\t\t\t\t\t\t\tconst int certChainSize )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( chainInfo, \\\n\t\t\t\t\t\t\t   sizeof( CHAIN_INFO ) * certChainSize ) );\n\tassert( isReadPtrDynamic( iCertChain, \\\n\t\t\t\t\t\t\t  sizeof( CRYPT_CERTIFICATE ) * certChainSize ) );\n\n\tREQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );\n\n\t/* Clear return value */\n\tmemset( chainInfo, 0, sizeof( CHAIN_INFO ) * certChainSize );\n\n\t/* Extract the subject and issuer DNs and key identifiers from each\n\t   certificate.  Maintaining an external pointer into the internal\n\t   structure is safe since the objects are reference-counted and won't be\n\t   destroyed until the encapsulating certificate is destroyed */\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tCERT_INFO *certChainPtr;\n\t\tint status;\n\n\t\tstatus = krnlAcquireObject( iCertChain[ i ], OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES_OBJECT( sanityCheckCert( certChainPtr ), \n\t\t\t\t\t certChainPtr->objectHandle );\n\t\tchainInfo[ i ].subjectDN = certChainPtr->subjectDNptr;\n\t\tchainInfo[ i ].subjectDNsize = certChainPtr->subjectDNsize;\n\t\tchainInfo[ i ].issuerDN = certChainPtr->issuerDNptr;\n\t\tchainInfo[ i ].issuerDNsize = certChainPtr->issuerDNsize;\n\t\tchainInfo[ i ].serialNumber = certChainPtr->cCertCert->serialNumber;\n\t\tchainInfo[ i ].serialNumberSize = certChainPtr->cCertCert->serialNumberLength;\n\t\tchainInfo[ i ].attributes = certChainPtr->attributes;\n\t\tstatus = getChainingAttribute( certChainPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t\t\t\t\t\t\t\t\t   &chainInfo[ i ].subjectKeyIdentifier,\n\t\t\t\t\t\t\t\t\t   &chainInfo[ i ].subjectKeyIDsize );\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getChainingAttribute( certChainPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER,\n\t\t\t\t\t\t\t\t\t\t   &chainInfo[ i ].issuerKeyIdentifier,\n\t\t\t\t\t\t\t\t\t\t   &chainInfo[ i ].issuerKeyIDsize );\n\t\t\t}\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\t\tkrnlReleaseObject( certChainPtr->objectHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the leaf node in a (possibly unordered) certificate chain by walking \n   down the chain as far as possible.  The strategy we use is to pick an \n   initial certificate (which is often the leaf certificate anyway) and keep \n   looking for certificates that it (or its successors) have issued until we \n   reach the end of the chain.  Returns the position of the leaf node in the \n   chain.\n\n   In addition to finding just the (nominal) leaf certificate, the caller \n   can also specify a preferred certificate through its usage type, useful \n   when the \"chain\" is actually an arbitrary certificate collection \n   containing multiple leaf certificates.  This isn't quite as simple as it \n   seems because for usage = X alongside the standard case of a single leaf \n   certificate with usage = X we can also have a leaf certificate with usage \n   Y, two leaf certificates with usage X, or a CA certificate (but no leaf \n   certificate) with usage X.  To deal with this we use the caller-specified \n   usage as a preferred-certificate hint rather than an absolute selection \n   criterion, with the different cases illustrated as follows:\n\n\t\t  X\t\t- Return this one.\n\t...../\n\t\t \\\n\t\t  Y\n\n\t\t  X\n\t...../\n\t\t \\\n\t\t  X\t\t- Return this one (because of the way the algorithm is \n\t\t\t\t  implemented, not by any specific policy decision).\n\n\t\t  Y\n\t...../\n\t\t \\\n\t\t  Y\t\t- Return this one, same as above.\n\n\t\t\t\t Y\n\t... CA+X .../\n\t\t\t\t\\\n\t\t\t\t Y\t- Return this one.\n\n   In other words we always try and return a leaf certificate if one exists, \n   and make the selection based on usage if possible.\n\n   Finally, the usage is treated as an absolute match (all usages must \n   match) rather than a selective match (one usage of potentially several \n   must match).  In other words if the caller specifies usage X+Y then the \n   certificate must have both of those usages available */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findLeafNode( IN_ARRAY( certChainSize ) const CHAIN_INFO *chainInfo,\n\t\t\t\t\t\t IN_RANGE( 1, MAX_CHAINLENGTH ) const int certChainSize,\n\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tconst int requestedUsage = \\\n\t\t( options == ( KEYMGMT_FLAG_USAGE_CRYPT | KEYMGMT_FLAG_USAGE_SIGN ) ) ? \\\n\t\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT | CRYPT_KEYUSAGE_DIGITALSIGNATURE : \\\n\t\t( options == KEYMGMT_FLAG_USAGE_CRYPT ) ? \\\n\t\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT : \\\n\t\t( options == KEYMGMT_FLAG_USAGE_SIGN ) ? \\\n\t\t\tCRYPT_KEYUSAGE_DIGITALSIGNATURE : 0;\n\tint bestMatch = CRYPT_ERROR, optionalMatch, currentCertPos, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( chainInfo, \\\n\t\t\t\t\t\t\t  sizeof( CHAIN_INFO ) * certChainSize ) );\n\n\tREQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_USAGEOPTIONS ) == 0 );\n\n\t/* If we don't find a better match, default to using the first \n\t   certificate.  This is required in order to handle self-signed \n\t   certificates, which are their own issuer and so never get passed to\n\t   the match-checking code.  Note that this can't handle sufficiently\n\t   perverse \"chains\" like one that contains two self-signed roots\n\t   with one having a signature usage and the other having an encryption\n\t   usage and the caller is asking for KEYMGMT_FLAG_USAGE_CRYPT, but\n\t   anything that weird shouldn't be expected to work properly in the\n\t   first place */\n\toptionalMatch = 0;\n\n\t/* Walk down the chain from the currently selected certificate checking \n\t   for certificates issued by it until we can't go any further, with\n\t   optional filtering by certificate usage type.  Note that this \n\t   algorithm handles chains with PKIX path-kludge certificates as well \n\t   as normal ones since it marks a certificate as used once it processes \n\t   it for the first time, avoiding potential endless loops on \n\t   subject == issuer path-kludge certificates */\n\tLOOP_EXT( currentCertPos = 0, currentCertPos < certChainSize, \n\t\t\t  currentCertPos++, MAX_CHAINLENGTH )\n\t\t{\n\t\tCHAINING_INFO currentCertInfo;\n\t\tDATAPTR_ATTRIBUTE attributePtr;\n\t\tBOOLEAN certIsIssuer = FALSE;\n\t\tint childCertPos, value, status, LOOP_ITERATOR_ALT;\n\n\t\tgetSubjectChainingInfo( &currentCertInfo, \n\t\t\t\t\t\t\t\t&chainInfo[ currentCertPos ] );\n\n\t\t/* Try and find a certificate issued by the current certificate */\n\t\tLOOP_EXT_ALT( childCertPos = 0, childCertPos < certChainSize, \n\t\t\t\t\t  childCertPos++, MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\t/* If there's another certificate below the current one in the \n\t\t\t   chain, mark the current one as used and move on to the next \n\t\t\t   one */\n\t\t\tif( isIssuer( &currentCertInfo, &chainInfo[ childCertPos ] ) )\n\t\t\t\t{\n\t\t\t\tcertIsIssuer = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\n\t\t/* If the current certificate isn't a leaf certificate, continue to \n\t\t   the next one */\n\t\tif( certIsIssuer )\n\t\t\tcontinue;\n\n\t\t/* If we're not selecting certificates based on a specific usage \n\t\t   type, we're done */\n\t\tif( requestedUsage == KEYMGMT_FLAG_NONE )\n\t\t\t{\n\t\t\tbestMatch = optionalMatch = currentCertPos;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Get the certificate's key usage */\n\t\tattributePtr = findAttributeField( chainInfo[ currentCertPos ].attributes,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t\t{\n\t\t\t/* There's no explicit key usage present, this certificate \n\t\t\t   should be OK unless we find a more specific match */\n\t\t\tbestMatch = optionalMatch = currentCertPos;\n\t\t\tcontinue;\n\t\t\t}\n\t\tstatus = getAttributeDataValue( attributePtr, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\t\tif( ( value & requestedUsage ) == requestedUsage )\n\t\t\tbestMatch = currentCertPos;\n\t\telse\n\t\t\toptionalMatch = currentCertPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( ( bestMatch != CRYPT_ERROR ) ? bestMatch : optionalMatch );\n\t}\n\n/* Find a leaf node as identified by issuerAndSerialNumber,\n   subjectKeyIdentifier, or certificate usage.  Returns the position of the \n   leaf node in the chain */\n\nCHECK_RETVAL_RANGE( 0, MAX_CHAINLENGTH ) STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int findIdentifiedLeafNode( IN_ARRAY( certChainSize ) \\\n\t\t\t\t\t\t\t\t\t\tconst CHAIN_INFO *chainInfo,\n\t\t\t\t\t\t\t\t   IN_RANGE( 1, MAX_CHAINLENGTH ) \\\n\t\t\t\t\t\t\t\t\t\tconst int certChainSize,\n\t\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tSTREAM stream;\n\tvoid *serialNumber DUMMY_INIT_PTR, *issuerDNptr DUMMY_INIT_PTR;\n\tint issuerDNsize DUMMY_INIT, serialNumberSize;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( chainInfo, \n\t\t\t\t\t\t\t  sizeof( CHAIN_INFO ) * certChainSize ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );\n\tREQUIRES( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );\n\tREQUIRES( keyID != NULL && \\\n\t\t\t  keyIDlength >= MIN_SKID_SIZE && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* If it's a subjectKeyIdentifier, walk down the chain looking for a\n\t   match */\n\tif( keyIDtype == CRYPT_IKEYID_KEYID )\n\t\t{\n\t\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tif( matchSubjectKeyID( &chainInfo[ i ], keyID, keyIDlength ) )\n\t\t\t\treturn( i );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* It's an issuerAndSerialNumber, extract the issuer DN and serial \n\t   number */\n\tsMemConnect( &stream, keyID, keyIDlength );\n\tstatus = readSequence( &stream, NULL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getStreamObjectLength( &stream, &issuerDNsize );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( issuerDNsize ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( &stream, &issuerDNptr, issuerDNsize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tsSkip( &stream, issuerDNsize, MAX_INTLENGTH_SHORT );/* Issuer DN */\n\tstatus = readGenericHole( &stream, &serialNumberSize, 1, BER_INTEGER );\n\tif( cryptStatusOK( status ) )\t\t\t\t\t\t/* Serial number */\n\t\t{\n\t\tstatus = sMemGetDataBlock( &stream, &serialNumber, \n\t\t\t\t\t\t\t\t   serialNumberSize );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tANALYSER_HINT( issuerDNptr != NULL );\n\tANALYSER_HINT( serialNumber != NULL );\n\n\t/* Walk down the chain looking for the one identified by the \n\t   issuerAndSerialNumber */\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tif( matchIssuerDN( &chainInfo[ i ], issuerDNptr, issuerDNsize ) && \\\n\t\t\tcompareSerialNumber( chainInfo[ i ].serialNumber, \n\t\t\t\t\t\t\t\t chainInfo[ i ].serialNumberSize,\n\t\t\t\t\t\t\t\t serialNumber, serialNumberSize ) )\n\t\t\t{\n\t\t\treturn( i );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* Sort the issuer certificates in a certificate chain, discarding any \n   unnecessary certificates.  If we're canonicalising an existing chain then \n   the start point in the chain is given by leafCert and the -1th certificate \n   is the end user certificate and isn't part of the ordering process.  If \n   we're building a new chain from an arbitrary set of certificates then the \n   start point is given by the chaining information for the leaf certificate.\n\n   The canonicalisation of the chain can be handled in one of two ways, the \n   logical way and the PKIX way.  The latter allows apparently self-signed\n   certificates in the middle of a chain due to certificate \n   renewals/reparenting, which completely breaks the standard certificate \n   convention that a self-signed certificate is a root CA.  This means that \n   without special handling the chain will terminate at a certificate that \n   appears to be (but isn't) the CA root certificate.  A sample chain of \n   this form (in this case involving an oldWithNew certificate) is as \n   follows:\n\n\tIssuer\t\tSubject\t\tKey/sKID\tSig/aKID\n\t------\t\t-------\t\t--------\t----------\n\tRoot\t\tCA\t\t\tca_new\t\troot\n\tCA\t\t\tCA\t\t\tca_old\t\tca_new\n\tCA\t\t\tEE\t\t\tee\t\t\tca_old\n\n   In order to handle these chains we need to match by both DN *and* keyID,\n   however since so many CAs get keyIDs wrong enabling this by default \n   would break many certificate chains.  To handle this we only enable the \n   extra-match behaviour if the compliance level is \n   CRYPT_COMPLIANCELEVEL_PKIX_FULL, for which people should be expecting all \n   sorts of bizarre behaviour anyway */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int sortCertChain( INOUT_ARRAY( certChainSize ) CRYPT_CERTIFICATE *iCertChain,\n\t\t\t\t\t\t  OUT_RANGE( 0, MAX_CHAINLENGTH ) int *orderedCertChainSize,\n\t\t\t\t\t\t  IN_ARRAY( certChainSize ) const CHAIN_INFO *chainInfo,\n\t\t\t\t\t\t  IN_RANGE( 1, MAX_CHAINLENGTH ) const int certChainSize,\n\t\t\t\t\t\t  IN_OPT const CHAINING_INFO *chainingInfo,\n\t\t\t\t\t\t  IN_RANGE( CRYPT_UNUSED, MAX_CHAINLENGTH ) \\\n\t\t\t\t\t\t\tconst int leafCertEntry,\n\t\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE leafCert,\n\t\t\t\t\t\t  const BOOLEAN useStrictChaining )\n\t{\n\tCRYPT_CERTIFICATE orderedChain[ MAX_CHAINLENGTH + 8 ];\n\tCHAINING_INFO localChainingInfo;\n\tBOOLEAN chainInfoValid[ MAX_CHAINLENGTH + 8 ], moreMatches;\n\tconst int maxMatchLevel = useStrictChaining ? 1 : 0;\n\tint orderedChainIndex, i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( iCertChain, \\\n\t\t\t\t\t\t\t   sizeof( CRYPT_CERTIFICATE ) * certChainSize ) );\n\tassert( isReadPtrDynamic( chainInfo, \\\n\t\t\t\t\t\t\t  sizeof( CHAIN_INFO ) * certChainSize ) );\n\tassert( ( isHandleRangeValid( leafCert ) && chainingInfo == NULL && \\\n\t\t\t  leafCertEntry == CRYPT_UNUSED ) || \\\n\t\t\t( leafCert == CRYPT_UNUSED && \\\n\t\t\t  isReadPtr( chainingInfo, sizeof( CHAINING_INFO ) ) && \\\n\t\t\t  leafCertEntry >= 0 && leafCertEntry <= certChainSize ) );\n\n\tREQUIRES( certChainSize > 0 && certChainSize <= MAX_CHAINLENGTH );\n\tREQUIRES( ( isHandleRangeValid( leafCert ) && chainingInfo == NULL && \\\n\t\t\t\tleafCertEntry == CRYPT_UNUSED ) || \\\n\t\t\t  ( leafCert == CRYPT_UNUSED && chainingInfo != NULL && \\\n\t\t\t\tleafCertEntry >= 0 && leafCertEntry <= certChainSize ) );\n\tREQUIRES( useStrictChaining == TRUE || useStrictChaining == FALSE );\n\n\t/* Clear return value */\n\t*orderedCertChainSize = 0;\n\n\t/* Initially all chain entries except the one for the leaf certificate \n\t   (defined either implicitly as the zero-th entry for leafCert or\n\t   explicitly as leafCertEntry) are valid */\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\tchainInfoValid[ i ] = TRUE;\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we're canonicalising an existing chain then there's a predefined \n\t   chain start that we copy over, after which we can prepare to look for \n\t   the next certificate up the chain */\n\tif( leafCert != CRYPT_UNUSED )\n\t\t{\n\t\tgetIssuerChainingInfo( &localChainingInfo, &chainInfo[ 0 ] );\n\t\torderedChain[ 0 ] = leafCert;\n\t\tchainInfoValid[ 0 ] = FALSE;\n\t\torderedChainIndex = 1;\n\t\t}\n\telse\n\t\t{\n\t\t/* We're building a new chain, the caller has supplied the chaining\n\t\t   information */\n\t\tmemcpy( &localChainingInfo, chainingInfo, sizeof( CHAINING_INFO ) );\n\t\tchainInfoValid[ leafCertEntry ] = FALSE;\n\t\torderedChainIndex = 0;\n\t\t}\n\n\t/* Build an ordered chain of certificates from the leaf to the root */\n\tLOOP_MED_INITCHECK( moreMatches = TRUE, moreMatches )\n\t\t{\n\t\tint matchLevel, LOOP_ITERATOR_ALT;\n\n\t\t/* We don't have a match until we discover otherwise */\n\t\tmoreMatches = FALSE;\n\n\t\t/* Find the certificate with the current issuer as its subject.  If \n\t\t   we're using strict chaining we first try a strict match \n\t\t   (matchLevel = TRUE), if that fails we fall back to a standard \n\t\t   match (matchLevel = FALSE).  This is required to handle the\n\t\t   significant number of CAs that don't get chaining by keyID \n\t\t   right */\n\t\tLOOP_EXT_ALT( matchLevel = maxMatchLevel, \\\n\t\t\t\t\t  !moreMatches && matchLevel >= 0, matchLevel--, 2 )\n\t\t\t{\n\t\t\tint LOOP_ITERATOR_ALT2;\n\n\t\t\tLOOP_EXT_ALT2( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t\t\t{\n\t\t\t\t/* If this isn't the issuer, continue */\n\t\t\t\tif( !chainInfoValid[ i ] || \\\n\t\t\t\t\t!isSubject( &localChainingInfo, &chainInfo[ i ], \n\t\t\t\t\t\t\t\tmatchLevel ) )\n\t\t\t\t\tcontinue;\n\n\t\t\t\t/* We've found the issuer, move the certificate to the \n\t\t\t\t   ordered chain and prepare to find its issuer */\n\t\t\t\torderedChain[ orderedChainIndex++ ] = iCertChain[ i ];\n\t\t\t\tgetIssuerChainingInfo( &localChainingInfo, &chainInfo[ i ] );\n\t\t\t\tchainInfoValid[ i ] = FALSE;\n\t\t\t\tmoreMatches = TRUE;\t/* Exit matchLevel loop as well */\n\t\t\t\tENSURES( orderedChainIndex > 0 && \\\n\t\t\t\t\t\t orderedChainIndex <= certChainSize && \\\n\t\t\t\t\t\t orderedChainIndex < MAX_CHAINLENGTH );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT2 );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If there are any certificates left, they're not needed for anything \n\t   so we can free the resources */\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tif( chainInfoValid[ i ] )\n\t\t\tkrnlSendNotifier( iCertChain[ i ], IMESSAGE_DECREFCOUNT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Replace the existing chain with the ordered version */\n\tLOOP_EXT( i = 0, i < certChainSize, i++, MAX_CHAINLENGTH )\n\t\tiCertChain[ i ] = CRYPT_ERROR;\n\tENSURES( LOOP_BOUND_OK );\n\tif( orderedChainIndex > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( orderedChainIndex, 1, MAX_CHAINLENGTH - 1 ) );\n\t\tmemcpy( iCertChain, orderedChain,\n\t\t\t\tsizeof( CRYPT_CERTIFICATE ) * orderedChainIndex );\n\t\t}\n\t*orderedCertChainSize = orderedChainIndex;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a collection of certificates in a certificate chain into a \n   certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int buildCertChain( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iLeafCert, \n\t\t\t\t\t\t   INOUT_ARRAY( certChainEnd ) CRYPT_CERTIFICATE *iCertChain, \n\t\t\t\t\t\t   IN_RANGE( 1, MAX_CHAINLENGTH ) const int certChainEnd,\n\t\t\t\t\t\t   IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t   IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t   IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\t   IN_FLAGS( KEYMGMT ) const int options )\n\t{\n\tCHAIN_INFO chainInfo[ MAX_CHAINLENGTH + 8 ];\n\tCERT_INFO *certChainPtr;\n\tCHAINING_INFO chainingInfo;\n\tconst int keyUsageOptions = options & KEYMGMT_MASK_USAGEOPTIONS;\n\tint leafNodePos, newCertChainEnd, complianceLevel, status;\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tint LOOP_ITERATOR;\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\tassert( isWritePtr( iLeafCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtrDynamic( iCertChain, \\\n\t\t\t\t\t\t\t   sizeof( CRYPT_CERTIFICATE ) * certChainEnd ) );\n\tassert( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t  keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \\\n\t\t\t  isReadPtrDynamic( keyID, keyIDlength ) ) );\n\n\tREQUIRES( certChainEnd > 0 && certChainEnd <= MAX_CHAINLENGTH );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t  ( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \\\n\t\t\t\tkeyID != NULL && \\\n\t\t\t\tkeyIDlength >= MIN_SKID_SIZE && \\\n\t\t\t\tkeyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyUsageOptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyUsageOptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyUsageOptions != KEYMGMT_FLAG_NONE ) );\n\n\t/* Clear return value */\n\t*iLeafCert = CRYPT_ERROR;\n\n\tstatus = krnlSendMessage( iCertChain[ 0 ], IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We start with a collection of certificates in unknown order (although \n\t   it's common for the first certificate to be the leaf).  First we \n\t   extract the chaining information and search the chain for the leaf \n\t   node */\n\tstatus = buildChainInfo( chainInfo, iCertChain, certChainEnd );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( keyID != NULL )\n\t\t{\n\t\tstatus = leafNodePos = \\\n\t\t\t\t\tfindIdentifiedLeafNode( chainInfo, certChainEnd,\n\t\t\t\t\t\t\t\t\t\t\tkeyIDtype, keyID, keyIDlength );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = leafNodePos = \\\n\t\t\t\t\tfindLeafNode( chainInfo, certChainEnd, keyUsageOptions );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( leafNodePos >= 0 && leafNodePos < certChainEnd );\n\n\t/* We've got the leaf node, remember the leaf certificate */\n\t*iLeafCert = iCertChain[ leafNodePos ];\n\tgetIssuerChainingInfo( &chainingInfo, &chainInfo[ leafNodePos ] );\n\n\t/* Order the remaining certificates up to the root and discard any \n\t   unneeded certificates */\n\tstatus = sortCertChain( iCertChain, &newCertChainEnd, chainInfo, \n\t\t\t\t\tcertChainEnd, &chainingInfo, leafNodePos, CRYPT_UNUSED,\n\t\t\t\t\t( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL ) ? \\\n\t\t\t\t\t  TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( newCertChainEnd <= 0 )\n\t\t{\n\t\t/* There's only one certificate in the chain either due to the \n\t\t   chain containing only a single certificate or due to all other \n\t\t   certificates having been discarded, leave it as a standalone \n\t\t   certificate rather than turning it into a chain */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* Walk up the chain re-setting the pseudo-selfsigned flag on any\n\t   chain-internal path-kludge certificates if necessary.  This means \n\t   that if the chain contains n certificates we reset the flag on \n\t   certificates 0...n-1.  This is required when there's a re-issued \n\t   certificate kludged into the middle of the path to connect a new CA \n\t   signing key with a certificate signed with the old key.  Note that \n\t   this can't detect the case where the first certificate in the chain \n\t   is a path kludge certificate with further certificates held \n\t   externally, e.g. in the trusted certificate store, since it appears \n\t   as a self-signed CA root certificate */\n\tif( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )\n\t\t{\n\t\tint i;\n\n\t\tLOOP_EXT( i = 0, i < newCertChainEnd - 1, i++, MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tCERT_INFO *certInfoPtr;\n\t\t\tBOOLEAN_INT value;\n\n\t\t\t/* Check whether this is a self-signed certificate */\n\t\t\tstatus = krnlSendMessage( iCertChain[ i ], IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_SELFSIGNED );\n\t\t\tif( cryptStatusError( status ) || !value )\n\t\t\t\tcontinue;\n\n\t\t\t/* Convert the self-signed flag into the pseudo self-signed/path\n\t\t\t   kludge flag */\n\t\t\tstatus = krnlAcquireObject( iCertChain[ i ], OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certInfoPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tcontinue;\n\t\t\tENSURES_OBJECT( sanityCheckCert( certInfoPtr ),\n\t\t\t\t\t\t\tcertInfoPtr->objectHandle );\n\t\t\tCLEAR_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_PATHKLUDGE );\n\t\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Since the objects that make up the chain were imported as individual \n\t   certificates because at the time of import we didn't know which one \n\t   was the leaf, we have to convert the leaf's object-type from \n\t   certificate to certificate chain */\n\tstatus = convertCertToChain( iLeafCert, *iLeafCert,\n\t\t\t\t\t\t\t\t ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\t\t   TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Finally, we've got the leaf certificate and a chain up to the root.  \n\t   Make the leaf a certificate-chain type and copy in the chain */\n\tstatus = krnlAcquireObject( *iLeafCert, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES_OBJECT( sanityCheckCert( certChainPtr ), \n\t\t\t\t\tcertChainPtr->objectHandle );\n\tREQUIRES_OBJECT( rangeCheck( newCertChainEnd, 1, MAX_CHAINLENGTH - 1 ),\n\t\t\t\t\t certChainPtr->objectHandle );\n\tmemcpy( certChainPtr->cCertCert->chain, iCertChain,\n\t\t\tsizeof( CRYPT_CERTIFICATE ) * newCertChainEnd );\n\tcertChainPtr->cCertCert->chainEnd = newCertChainEnd;\n\tcertChainPtr->type = CRYPT_CERTTYPE_CERTCHAIN;\n\tkrnlReleaseObject( certChainPtr->objectHandle );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCopy a Certificate Chain\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine whether a certificate is present in a certificate collection \n   based on its fingerprint */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isCertPresent( INOUT_ARRAY( certChainLen ) \\\n\t\t\t\t\t\t\t\t\tBYTE certChainHashes[][ CRYPT_MAX_HASHSIZE + 8 ],\n\t\t\t\t\t\t\t  IN_RANGE( 0, MAX_CHAINLENGTH ) const int certChainLen, \n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tMESSAGE_DATA msgData;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certChainHashes, \\\n\t\t\t\t\t\tMAX_CHAINLENGTH * CRYPT_MAX_HASHSIZE ) );\n\n\tREQUIRES_B( certChainLen >= 0 && certChainLen <= MAX_CHAINLENGTH );\n\t\t\t\t/* Apparent length may be zero for a chain of size 1 since\n\t\t\t\t   the leaf certificate has the effective index value -1 */\n\tREQUIRES_B( isHandleRangeValid( iCryptCert ) );\n\n\t/* Get the fingerprint of the (potential) next certificate in the \n\t   collection.  This leaves it at the end of the existing collection of \n\t   hashes so that if the certificate is then added to the chain its hash \n\t   will also be present */\n\tsetMessageData( &msgData, certChainHashes[ certChainLen ], \n\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that it isn't already present in the collection */\n\tLOOP_EXT( i = 0, i < certChainLen, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tif( !memcmp( certChainHashes[ i ], \n\t\t\t\t\t certChainHashes[ certChainLen ], msgData.length ) )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Copy a certificate chain into a certificate object and canonicalise the \n   chain by ordering the certificates from the leaf certificate up to the \n   root.  This function is used when signing a certificate with a certificate  \n   chain and takes as input ( oldCert, oldCert.chain[ ... ] ) and produces \n   as output ( newCert, chain[ oldCert, oldCert.chain[ ... ] ], i.e. the \n   chain for the new certificate contains the old certificate and its \n   attached certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCertChain( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE certChain,\n\t\t\t\t   const BOOLEAN isCertCollection )\n\t{\n\tCRYPT_CERTIFICATE iChainCert;\n\tCERT_INFO *chainCertInfoPtr;\n\tCERT_CERT_INFO *destCertChainInfo = certInfoPtr->cCertCert;\n\tCERT_CERT_INFO *srcCertChainInfo;\n\tCHAIN_INFO chainInfo[ MAX_CHAINLENGTH + 8 ];\n\tBYTE certChainHashes[ MAX_CHAINLENGTH + 1 + 8 ][ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst int oldChainEnd = destCertChainInfo->chainEnd;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( certChain ) );\n\tREQUIRES( isCertCollection == TRUE || isCertCollection == FALSE );\n\n\tstatus = krnlSendMessage( certChain, IMESSAGE_GETDEPENDENT, &iChainCert, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're building a certificate collection all that we need to ensure \n\t   is non-duplicate certificates rather than a strict chain.  To handle \n\t   duplicate checking we build a list of the fingerprints for each \n\t   certificate in the chain */\n\tmemset( certChainHashes, 0, sizeof( certChainHashes ) );\n\tif( isCertCollection )\n\t\t{\n\t\tLOOP_EXT( i = 0, i < destCertChainInfo->chainEnd, i++, \n\t\t\t\t  MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tsetMessageData( &msgData, certChainHashes[ i ], \n\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\t\t\tstatus = krnlSendMessage( destCertChainInfo->chain[ i ], \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Extract the base certificate from the chain and copy it over (the\n\t   isCertPresent() check also sets up the hash for the new certificate \n\t   in the certChainHashes array) */\n\tstatus = krnlAcquireObject( iChainCert, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &chainCertInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES_OBJECT( sanityCheckCert( chainCertInfoPtr ),\n\t\t\t\t\tchainCertInfoPtr->objectHandle );\n\tsrcCertChainInfo = chainCertInfoPtr->cCertCert;\n\tif( !isCertCollection || \\\n\t\t!isCertPresent( certChainHashes, destCertChainInfo->chainEnd, \\\n\t\t\t\t\t\tiChainCert ) )\n\t\t{\n\t\tif( destCertChainInfo->chainEnd >= MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tkrnlReleaseObject( chainCertInfoPtr->objectHandle );\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\tkrnlSendNotifier( iChainCert, IMESSAGE_INCREFCOUNT );\n\t\tdestCertChainInfo->chain[ destCertChainInfo->chainEnd++ ] = iChainCert;\n\t\t}\n\n\t/* Copy the rest of the chain.  Because we're about to canonicalise it\n\t   (which re-orders the certificates and deletes unused ones) we copy \n\t   individual certificates over rather than copying only the base \n\t   certificate and relying on the chain held in that */\n\tLOOP_EXT( i = 0, i < srcCertChainInfo->chainEnd, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tconst CRYPT_CERTIFICATE iCopyCert = srcCertChainInfo->chain[ i ];\n\n\t\t/* If it's an (unordered) certificate collection, make sure that \n\t\t   there are no duplicates */\n\t\tif( isCertCollection && \\\n\t\t\tisCertPresent( certChainHashes, destCertChainInfo->chainEnd,\n\t\t\t\t\t\t\tsrcCertChainInfo->chain[ i ] ) )\n\t\t\tcontinue;\n\n\t\t/* Copy the next certificate from the source to the destination */\n\t\tif( destCertChainInfo->chainEnd >= MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\tbreak;\n\t\t\t}\n\t\tkrnlSendNotifier( iCopyCert, IMESSAGE_INCREFCOUNT );\n\t\tdestCertChainInfo->chain[ destCertChainInfo->chainEnd++ ] = iCopyCert;\n\t\t}\n\tENSURES_OBJECT( LOOP_BOUND_OK, chainCertInfoPtr->objectHandle );\n\tsrcCertChainInfo = NULL;\t/* Make the release explicit */\n\tkrnlReleaseObject( chainCertInfoPtr->objectHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* An error at this point indicates that the upper limit on chain\n\t\t   length isn't sufficient so we throw a (debug) exception if we \n\t\t   get here */\n\t\tDEBUG_DIAG(( \"Maximum chain length %d exceeded\", MAX_CHAINLENGTH ));\n\t\tassert( DEBUG_WARN );\n\n\t\t/* Clean up the newly-copied certificates if necessary */\n\t\tif( destCertChainInfo->chainEnd > oldChainEnd )\n\t\t\t{\n\t\t\tfreeCertChain( &destCertChainInfo->chain[ oldChainEnd ],\n\t\t\t\t\t\t   destCertChainInfo->chainEnd - oldChainEnd );\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\n\t/* If we're building an unordered certificate collection, mark the \n\t   certificate chain object as a certificate collection only and exit.  \n\t   This is a pure container object for which only the certificate chain \n\t   member contains certificates, the base certificate object doesn't \n\t   correspond to an actual certificate */\n\tif( isCertCollection )\n\t\t{\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_CERTCOLLECTION );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the chain being attached consists of a single certificate (which \n\t   occurs when we're building a new chain by signing a certificate with \n\t   a CA certificate) we don't have to bother doing anything else */\n\tif( oldChainEnd <= 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* Extract the chaining information from each certificate and use it to \n\t   sort the chain.  Since we know what the leaf certificate is and since \n\t   chaining information such as the encoded DN data in the certinfo \n\t   structure may not have been set up yet if it contains an unsigned \n\t   certificate we feed in the leaf certificate and omit the chaining \n\t   information */\n\tstatus = buildChainInfo( chainInfo, destCertChainInfo->chain,\n\t\t\t\t\t\t\t destCertChainInfo->chainEnd );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Clean up the newly-copied certificates if necessary */\n\t\tif( destCertChainInfo->chainEnd > oldChainEnd )\n\t\t\t{\n\t\t\tfreeCertChain( &destCertChainInfo->chain[ oldChainEnd ],\n\t\t\t\t\t\t   destCertChainInfo->chainEnd - oldChainEnd );\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\treturn( sortCertChain( destCertChainInfo->chain, &destCertChainInfo->chainEnd, \n\t\t\t\t\t\t   chainInfo, destCertChainInfo->chainEnd, NULL, \n\t\t\t\t\t\t   CRYPT_UNUSED, iChainCert, FALSE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Certificate-bagging Records\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a single certificate in a chain */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSingleCert( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t   const BOOLEAN dataOnlyCert,\n\t\t\t\t\t\t   const BOOLEAN isIndefiniteLength )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  type == CRYPT_ICERTTYPE_CMS_CERTSET || \\\n\t\t\t  type == CRYPT_ICERTTYPE_SSL_CERTCHAIN );\n\tREQUIRES( dataOnlyCert== TRUE || dataOnlyCert == FALSE );\n\tREQUIRES( isIndefiniteLength == TRUE || isIndefiniteLength == FALSE );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\t/* If it's an SSL certificate chain then there's a 24-bit length field \n\t   between certificates */\n\tif( type == CRYPT_ICERTTYPE_SSL_CERTCHAIN )\n\t\t{\n\t\tstatus = sSkip( stream, 3, 3 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Find out how large the certificate data is and make sure that the \n\t   size is approximately valid before we pass it on to other \n\t   functions */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_CERTSIZE || length >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Since SSL certificate chains contain certificates interspersed with \n\t   non-certificate SSL length data the higher-level code can't check the \n\t   encoding, so we have to perform the check here.  Technically this \n\t   isn't really necessary since importCertFromStream() imports the \n\t   certificate via a kernel message which means that the encoding is \n\t   checked anyway, but this is an implementation-specific detail that we \n\t   can't assume will hold for future versions so we make the check \n\t   explicit here */\n\tif( type == CRYPT_ICERTTYPE_SSL_CERTCHAIN )\n\t\t{\n\t\tvoid *certDataPtr;\n\t\tint complianceLevel;\n\n\t\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &complianceLevel,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( complianceLevel > CRYPT_COMPLIANCELEVEL_OBLIVIOUS )\n\t\t\t{\n\t\t\tstatus = sMemGetDataBlock( stream, &certDataPtr, length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = checkCertObjectEncoding( certDataPtr, length );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Read the next certificate and add it to the chain.  When importing \n\t   the chain from an external (untrusted) source we create standard \n\t   certificates so that we can check the signatures on each link in the \n\t   chain.  When importing from a trusted source we create data-only \n\t   certificates, once we've got all of the certificates and know which \n\t   certificate is the leaf we can go back and decode the public key \n\t   information for it */\n\tstatus = importCertFromStream( stream, iCryptCert, iCryptOwner,\n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTIFICATE, length,\n\t\t\t\t\t\t\t\t   dataOnlyCert ? KEYMGMT_FLAG_DATAONLY_CERT : \\\n\t\t\t\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the certificate chain is encoded using the indefinite form and we \n\t   find the EOC octets following the certificate that we've just read, \n\t   tell the caller */\n\tif( isIndefiniteLength )\n\t\t{\n\t\tstatus = checkEOC( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( *iCryptCert, IMESSAGE_DECREFCOUNT );\n\t\t\t*iCryptCert = CRYPT_ERROR;\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( status == TRUE )\n\t\t\t{\n\t\t\t/* We've seen EOC octets, tell the caller that we're done */\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read certificate chain/sequence information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCertChain( INOUT STREAM *stream, \n\t\t\t\t   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t   IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t   IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t   IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t   IN_FLAGS( KEYMGMT ) const int options )\n\t{\n\tCRYPT_CERTIFICATE iCertChain[ MAX_CHAINLENGTH + 8 ];\n\tconst BOOLEAN dataOnlyCert = ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\t\t   TRUE : FALSE;\n\tint certSequenceLength DUMMY_INIT, endPos = 0, certChainEnd = 0;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( ( keyIDtype == CRYPT_KEYID_NONE && keyID == NULL && \\\n\t\t\t  keyIDlength == 0 ) || \\\n\t\t\t( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \\\n\t\t\t  isReadPtrDynamic( keyID, keyIDlength ) && \\\n\t\t\t  keyIDlength >= MIN_SKID_SIZE ) );\n\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  type == CRYPT_ICERTTYPE_CMS_CERTSET || \\\n\t\t\t  type == CRYPT_ICERTTYPE_SSL_CERTCHAIN );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t  ( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \\\n\t\t\t\tkeyID != NULL && \\\n\t\t\t\tkeyIDlength >= MIN_SKID_SIZE && \\\n\t\t\t\tkeyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~( KEYMGMT_MASK_USAGEOPTIONS | \\\n\t\t\t\t\t\t\t KEYMGMT_MASK_CERTOPTIONS ) ) == 0 );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\toptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\toptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\toptions != KEYMGMT_FLAG_NONE ) );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\t/* The outer wrapper has already been read by the caller so\n\t\t\t   the certificate chain is everything that's left */\n\t\t\tcertSequenceLength = sMemDataLeft( stream );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ICERTTYPE_CMS_CERTSET:\n\t\t\tstatus = readConstructedI( stream, &certSequenceLength, 0 );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ICERTTYPE_SSL_CERTCHAIN:\n\t\t\t/* There's no outer wrapper to give us length information for an \n\t\t\t   SSL certificate chain, however the length will be equal to the \n\t\t\t   total remaining stream size */\n\t\t\tcertSequenceLength = sMemDataLeft( stream );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( ( certSequenceLength == CRYPT_UNUSED ) || \\\n\t\t\t isShortIntegerRangeNZ( certSequenceLength ) );\n\n\t/* If it's a definite-length chain, determine where it ends */\n\tif( certSequenceLength != CRYPT_UNUSED )\n\t\tendPos = stell( stream ) + certSequenceLength;\n\n\t/* We've reached the certificate(s), read the collection of certificates \n\t   into certificate objects.  We allow for a bit of slop for software \n\t   that gets the length encoding wrong by a few bytes.  Note that the \n\t   limit is given as FAILSAFE_ITERATIONS_MED since we're using it as a \n\t   fallback check on the existing MAX_CHAINLENGTH check.  In other words \n\t   anything over MAX_CHAINLENGTH is handled as a normal error and it's \n\t   only if we exceed this that we have an internal error */\n\tLOOP_MED_CHECK( certSequenceLength == CRYPT_UNUSED || \\\n\t\t\t\t\tstell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )\n\t\t{\n\t\tCRYPT_CERTIFICATE iNewCert DUMMY_INIT;\n\n\t\t/* Make sure that we don't overflow the chain.  Note that the chain-\n\t\t   size check is triggered as soon as we reach MAX_CHAINLENGTH (even\n\t\t   though it's coded as a more generic '>='), so we always pass a\n\t\t   valid chain-size value to freeCertChain() */\n\t\tif( certChainEnd >= MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tfreeCertChain( iCertChain, certChainEnd );\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\n\t\t/* Read the next certificate in the chain */\n\t\tstatus = readSingleCert( stream, &iNewCert, iCryptOwner, type, \n\t\t\t\t\t\t\t\t dataOnlyCert,\n\t\t\t\t\t\t\t\t ( certSequenceLength == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t{\n\t\t\tif( certChainEnd > 0 )\n\t\t\t\tfreeCertChain( iCertChain, certChainEnd );\n\t\t\treturn( status );\n\t\t\t}\n\t\tiCertChain[ certChainEnd++ ] = iNewCert;\n\t\tif( status == OK_SPECIAL )\n\t\t\tbreak;\t/* We've reached the end of the chain */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We must have read at least one certificate in order to create a \n\t   chain */\n\tif( certChainEnd <= 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Build the complete chain from the individual certificates */\n\tstatus = buildCertChain( iCryptCert, iCertChain, certChainEnd, \n\t\t\t\t\t\t\t keyIDtype, keyID, keyIDlength, options );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfreeCertChain( iCertChain, certChainEnd );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Fetch a sequence of certificates from an object to create a certificate \n   chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint assembleCertChain( OUT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iCertSource,\n\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t   IN_FLAGS( KEYMGMT ) const int options )\n\t{\n\tCRYPT_CERTIFICATE iCertSet[ MAX_CHAINLENGTH + 8 ], iCertChain, lastCert;\n\tMESSAGE_KEYMGMT_INFO getnextcertInfo;\n\tconst int chainOptions = options & KEYMGMT_FLAG_DATAONLY_CERT;\n\tint stateInfo = CRYPT_ERROR, certSetSize = 1;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyIDlength > 0 && keyIDlength < MAX_ATTRIBUTE_SIZE );\n\t\t\t  /* The keyID can be an arbitrary value, including ones from\n\t\t\t\t PKCS #11 devices, so it can be as little as a single byte */\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* Get the initial certificate based on the key ID */\n\tsetMessageKeymgmtInfo( &getnextcertInfo, keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t   &stateInfo, sizeof( int ), \n\t\t\t\t\t\t   options & KEYMGMT_MASK_CERTOPTIONS );\n\tstatus = krnlSendMessage( iCertSource, IMESSAGE_KEY_GETFIRSTCERT,\n\t\t\t\t\t\t\t  &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCertSet[ 0 ] = lastCert = getnextcertInfo.cryptHandle;\n\n\t/* Make sure that the data source that we're using actually gave us what\n\t   we asked for.  The one situation where we can't do this is when we've\n\t   been given a key ID and we're looking up a data-only certificate, \n\t   since the IDs aren't present in the certificate but are generated \n\t   dynamically in the associated context */\n\tif( !( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t keyIDtype == CRYPT_IKEYID_PGPKEYID ) && \\\n\t\t   ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ) )\n\t\t{\n\t\tstatus = iCryptVerifyID( lastCert, keyIDtype, keyID, keyIDlength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( lastCert, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Fetch subsequent certificates that make up the chain based on the \n\t   state information.  Since the basic options apply only to the leaf \n\t   certificate we only allow the data-only certificate flag at this \n\t   point.  See the comment in readCertChain() for the use of \n\t   FAILSAFE_ITERATIONS_MED for the bounds check */\n\tsetMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0, \n\t\t\t\t\t\t   &stateInfo, sizeof( int ), chainOptions );\n\tLOOP_MED_CHECK( cryptStatusOK( status ) )\n\t\t{\n\t\tBOOLEAN_INT selfSigned;\n\n\t\t/* If we've reached a self-signed (CA root) certificate, stop.  Note \n\t\t   that this can't detect PKIX path-kludge certificates which look \n\t\t   identical to CA root certificates and can only be reliably \n\t\t   identified if they're present in the middle of a pre-built \n\t\t   chain */\n\t\tstatus = krnlSendMessage( lastCert, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &selfSigned, CRYPT_CERTINFO_SELFSIGNED );\n\t\tif( cryptStatusError( status ) || selfSigned == TRUE )\n\t\t\tbreak;\n\n\t\t/* Get the next certificate in the chain from the source, import it,\n\t\t   and add it to the collection */\n\t\tgetnextcertInfo.cryptHandle = CRYPT_ERROR;\t/* Reset result handle */\n\t\tstatus = krnlSendMessage( iCertSource, IMESSAGE_KEY_GETNEXTCERT,\n\t\t\t\t\t\t\t\t  &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we get a notfound error then this is OK since it just \n\t\t\t   means that we've reached the end of the chain */\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\tstatus = CRYPT_OK;\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Make sure that we don't overflow the chain */\n\t\tif( certSetSize >= MAX_CHAINLENGTH )\n\t\t\t{\n\t\t\tkrnlSendNotifier( getnextcertInfo.cryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tiCertSet[ certSetSize++ ] = lastCert = getnextcertInfo.cryptHandle;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfreeCertChain( iCertSet, certSetSize );\n\t\treturn( status );\n\t\t}\n\n\t/* Build the complete chain from the individual certificates */\n\tstatus = buildCertChain( &iCertChain, iCertSet, certSetSize, \n\t\t\t\t\t\t\t CRYPT_KEYID_NONE, NULL, 0, chainOptions );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfreeCertChain( iCertSet, certSetSize );\n\t\treturn( status );\n\t\t}\n\n\t*iCertificate = iCertChain;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Certificate-bagging Records\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine the size of and write a certificate path from a base \n   certificate up to the root.  This gets a bit complicated because \n   alongside the overall length, SSL requires that we return component-by-\n   component lengths that need to be inserted as 24-bit (3 byte) values \n   between each certificate.  To handle this we take as an optional \n   parameter an array used to store the individual path component lengths */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sizeofCertPath( const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *certPathLength,\n\t\t\t\t\t\t   OUT_ARRAY_OPT_C( MAX_CHAINLENGTH ) int *certSizeInfo )\n\t{\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tint length = 0, i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certPathLength, sizeof( int ) ) );\n\tassert( certSizeInfo == NULL || \\\n\t\t\tisWritePtr( certSizeInfo, sizeof( int ) * MAX_CHAINLENGTH ) );\n\n\t/* Clear return values */\n\t*certPathLength = 0;\n\tif( certSizeInfo != NULL )\n\t\tmemset( certSizeInfo, 0, sizeof( int ) * MAX_CHAINLENGTH );\n\n\t/* Evaluate the size of the current certificate and the issuer \n\t   certificates in the chain.  If it's a certificate collection it's \n\t   just a container for random certificates but not a certificate in its \n\t   own right so we skip the leaf certificate */\n\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_CERTCOLLECTION ) )\n\t\t{\n\t\tlength = certInfoPtr->certificateSize;\n\t\tif( certSizeInfo != NULL )\n\t\t\tlength += 3;\n\t\t}\n\tLOOP_EXT( i = 0, i < certChainInfo->chainEnd, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( certChainInfo->chain[ i ], \n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlength += msgData.length;\n\t\tif( certSizeInfo != NULL )\n\t\t\t{\n\t\t\tcertSizeInfo[ i ] = msgData.length;\n\t\t\tlength += 3;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*certPathLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCertPath( INOUT STREAM *stream, \n\t\t\t\t\t\t  const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t  IN_ARRAY_OPT_C( MAX_CHAINLENGTH ) \\\n\t\t\t\t\t\t\t\tconst int *certSizeInfo )\n\n\t{\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tint i, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( certSizeInfo == NULL || \\\n\t\t\tisReadPtr( certSizeInfo, sizeof( int ) * MAX_CHAINLENGTH ) );\n\n\t/* Write the current certificate and the associated certificate chain up \n\t   to the root.  If it's a certificate collection it's just a container \n\t   for random certificates but not a certificate in its own right so we \n\t   skip the leaf certificate */\n\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_CERTCOLLECTION ) )\n\t\t{\n\t\tif( certSizeInfo != NULL )\n\t\t\t{\n\t\t\tsputc( stream, 0 );\n\t\t\twriteUint16( stream, certInfoPtr->certificateSize );\n\t\t\t}\n\t\tstatus = swrite( stream, certInfoPtr->certificate, \n\t\t\t\t\t\t certInfoPtr->certificateSize );\n\t\t}\n\tLOOP_EXT( i = 0, cryptStatusOK( status ) && \\\n\t\t\t\t\t i < certChainInfo->chainEnd, i++, MAX_CHAINLENGTH )\n\t\t{\n\t\tif( certSizeInfo != NULL )\n\t\t\t{\n\t\t\tsputc( stream, 0 );\n\t\t\tstatus = writeUint16( stream, certSizeInfo[ i ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tstatus = exportCertToStream( stream, certChainInfo->chain[ i ], \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n\n/* Write certificate chain/sequence information:\n\n\tCertChain ::= SEQUENCE {\n\t\tcontentType\t\t\t\tOBJECT IDENTIFIER,\t-- signedData\n\t\tcontent\t\t\t  [ 0 ]\tEXPLICIT SEQUENCE {\n\t\t\tversion\t\t\t\tINTEGER (1),\n\t\t\tdigestAlgorithms\tSET OF AlgorithmIdentifier,\t-- SIZE(0)\n\t\t\tcontentInfo\t\t\tSEQUENCE {\n\t\t\t\tsignedData\t\tOBJECT IDENTIFIER\t-- data\n\t\t\t\t}\n\t\t\tcertificates  [ 0 ]\tSET OF {\n\t\t\t\t\t\t\t\t\tCertificate\n\t\t\t\t}\n\t\t\t}\n\t\tsignerInfos\t\t\t\tSET OF SignerInfo\t\t\t-- SIZE(0)\n\t\t} */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofCertCollection( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType )\n\t{\n\tint length, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \\\n\t\t\t  certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \\\n\t\t\t  certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );\n\n\t/* If it's an SSL certificate chain then we have to pass in a dummy\n\t   component-length pointer to ensure that it's evaluated as an SSL \n\t   chain with intermediate lengths rather than a straight PKCS #7/CMS\n\t   chain */\n\tif( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN )\n\t\t{\n\t\tint certSizeInfo[ MAX_CHAINLENGTH + 8 ];\n\n\t\tstatus = sizeofCertPath( certInfoPtr, &length, certSizeInfo );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a standard PKCS #7/CMS chain */\n\t\tstatus = sizeofCertPath( certInfoPtr, &length, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = length = sizeofObject( length );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( length );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCertCollection( INOUT STREAM *stream, \n\t\t\t\t\t\t IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType )\n\t{\n\tint certSizeInfo[ MAX_CHAINLENGTH + 8 ];\n\tint *certSizePtr = \\\n\t\t\t( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN ) ? \\\n\t\t\tcertSizeInfo : NULL;\n\tint certCollectionLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \\\n\t\t\t  certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \\\n\t\t\t  certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );\n\n\tstatus = sizeofCertPath( certInfoPtr, &certCollectionLength, \n\t\t\t\t\t\t\t certSizePtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( certFormatType )\n\t\t{\n\t\tcase CRYPT_ICERTFORMAT_CERTSET:\n\t\t\tstatus = writeConstructed( stream, certCollectionLength, 0 );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ICERTFORMAT_CERTSEQUENCE:\n\t\t\tstatus = writeSequence( stream, certCollectionLength );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ICERTFORMAT_SSL_CERTCHAIN:\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( writeCertPath( stream, certInfoPtr, certSizePtr ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCertChain( INOUT STREAM *stream, \n\t\t\t\t\tconst CERT_INFO *certInfoPtr )\n\t{\n\tint certSetLength, innerLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\tstatus = sizeofCertPath( certInfoPtr, &certSetLength, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine how big the encoded certificate chain/sequence will be */\n\tinnerLength = sizeofShortInteger( 1 ) + sizeofShortObject( 0 ) + \\\n\t\t\t\t\t  sizeofShortObject( sizeofOID( OID_CMS_DATA ) ) + \\\n\t\t\t\t\t  sizeofShortObject( certSetLength ) + \\\n\t\t\t\t\t  sizeofShortObject( 0 );\n\n\t/* Write the outer SEQUENCE wrapper, contentType, and content wrapper */\n\twriteSequence( stream, \n\t\t\t\t   sizeofOID( OID_CMS_SIGNEDDATA ) + \\\n\t\t\t\t\tsizeofShortObject( sizeofShortObject( innerLength ) ) );\n\tswrite( stream, OID_CMS_SIGNEDDATA, sizeofOID( OID_CMS_SIGNEDDATA ) );\n\twriteConstructed( stream, sizeofShortObject( innerLength ), 0 );\n\tstatus = writeSequence( stream, innerLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the inner content */\n\twriteShortInteger( stream, 1, DEFAULT_TAG );\n\twriteSet( stream, 0 );\n\twriteSequence( stream, sizeofOID( OID_CMS_DATA ) );\n\tswrite( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );\n\tstatus = writeConstructed( stream, certSetLength, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeCertPath( stream, certInfoPtr, NULL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeSet( stream, 0 );\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/chk_cert.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Certificate Checking Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\n/* Check whether disallowed CA-only attributes are present in a (non-CA) \n   attribute list.  We report the error as a constraint derived from the CA\n   flag rather than the attribute itself since it's the absence of the flag \n   that renders the presence of the attribute invalid */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nstatic BOOLEAN invalidAttributesPresent( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t\t const BOOLEAN isIssuer,\n\t\t\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus, \n\t\t\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES_B( sanityCheckAttribute( attributePtr ) );\n\tREQUIRES_B( isIssuer== TRUE || isIssuer == FALSE );\n\n\t/* Check for entire disallowed attributes */\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tif( checkAttributePresent( attributePtr, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_NAMECONSTRAINTS ) || \\\n\t\tcheckAttributePresent( attributePtr, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_POLICYCONSTRAINTS ) || \\\n\t\tcheckAttributePresent( attributePtr, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_INHIBITANYPOLICY ) || \\\n\t\tcheckAttributePresent( attributePtr, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_POLICYMAPPINGS ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CA, isIssuer ? \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT : \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( TRUE );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Check for a particular field of an attribute that's invalid rather \n\t   than the entire attribute (the specific exclusion of path-length \n\t   constraints in basicConstraints was introduced in RFC 3280) */\n\tif( checkAttributeFieldPresent( attributePtr, \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PATHLENCONSTRAINT ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CA, isIssuer ? \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT : \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\n/* Check whether a certificate is a PKIX path-kludge certificate, which \n   allows extra certificates to be kludged into the path without violating \n   any constraints */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isPathKludge( IN const CERT_INFO *certInfoPtr )\n\t{\n\tint value, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Perform a quick-reject check for certificates that haven't been \n\t   identified by the certificate chain processing code as path-kludge \n\t   certificates */\n\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_PATHKLUDGE ) )\n\t\treturn( FALSE );\n\n\t/* Only CA path-kludge certificates are exempt from constraint \n\t   enforcement.  Non-CA path kludges shouldn't ever occur but who knows \n\t   what other weirdness future RFCs will dream up, so we perform an \n\t   explicit check here */\n\tstatus = getAttributeFieldValue( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\treturn( ( cryptStatusOK( status ) && value ) ? TRUE : FALSE );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck Name Constraints\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\n/* Perform a wildcarded compare of two strings in attributes.  Certificates\n   don't use standard ? and * regular-expression wildcards but instead \n   specify the constraint as a form of longest-suffix filter that's applied \n   to the string (with the usual pile of special-case exceptions that apply \n   to any certificate-related rules) so that e.g. www.foo.com would be \n   constrained using foo.com (or more usually .foo.com to avoid erroneous \n   matches for strings like www.barfoo.com) */\n\ntypedef enum {\n\tMATCH_NONE,\t\t/* No special-case matching rules */\n\tMATCH_EMAIL,\t/* Match using email address mailbox exception */\n\tMATCH_URI,\t\t/* Match only DNS name portion of URI */\n\tMATCH_LAST\t\t/* Last valid match rule type */\n\t} MATCH_TYPE;\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN wildcardMatch( IN const DATAPTR constrainedAttribute,\n\t\t\t\t\t\t\t  IN const DATAPTR constrainingAttribute,\n\t\t\t\t\t\t\t  IN_ENUM_OPT( MATCH ) const MATCH_TYPE matchType )\n\t{\n\tconst BYTE *constrainingString, *constrainedString;\n\tint constrainingStringLength, constrainedStringLength;\n\tBOOLEAN isWildcardMatch;\n\tint startPos, status;\n\n\tREQUIRES_B( DATAPTR_ISSET( constrainedAttribute ) );\n\tREQUIRES_B( DATAPTR_ISSET( constrainingAttribute ) );\n\tREQUIRES_B( isEnumRangeOpt( matchType, MATCH ) );\n\n\tstatus = getAttributeDataPtr( constrainingAttribute, \n\t\t\t\t\t\t\t\t  ( void ** ) &constrainingString, \n\t\t\t\t\t\t\t\t  &constrainingStringLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = getAttributeDataPtr( constrainedAttribute, \n\t\t\t\t\t\t\t\t  ( void ** ) &constrainedString, \n\t\t\t\t\t\t\t\t  &constrainedStringLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tisWildcardMatch = ( *constrainingString == '.' ) ? TRUE : FALSE;\n\n\t/* Determine the start position of the constraining string within the\n\t   constrained string: \n\n\t\txxxxxyyyyy\t- Constrained string\n\t\t\t yyyyy\t- Constraining string\n\t\t\t^\n\t\t\t|\n\t\tstartPos\n\t   \n\t   If the constraining string is longer than the constrained string \n\t   (making startPos negative), it can never match */\n\tstartPos = constrainedStringLength - constrainingStringLength;\n\tif( !isShortIntegerRange( startPos ) )\n\t\treturn( FALSE );\n\n\t/* Handle special-case match requirements (PKIX section 4.2.1.11) */\n\tswitch( matchType )\n\t\t{\n\t\tcase MATCH_EMAIL:\n\t\t\t/* Email addresses have a special-case requirement where the \n\t\t\t   absence of a wildcard-match indicator (the leading dot)\n\t\t\t   indicates that the mailbox has to be located directly on the \n\t\t\t   constraining hostname rather than merely within that domain, \n\t\t\t   i.e. user@foo.bar.com is a valid match for .bar.com but not \n\t\t\t   for bar.com, which would require user@bar.com to match */\n\t\t\tENSURES_B( startPos <= constrainedStringLength );\n\t\t\tif( !isWildcardMatch && \\\n\t\t\t\t( startPos < 1 || constrainedString[ startPos - 1 ] != '@' ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase MATCH_URI:\n\t\t\t{\n\t\t\tURL_INFO urlInfo;\n\n\t\t\t/* URIs can contain trailing location information that isn't \n\t\t\t   regarded as part of the URI for matching purposes so before \n\t\t\t   performing the match we have to parse the URL and only use \n\t\t\t   the DNS name portion */\n\t\t\tstatus = sNetParseURL( &urlInfo, constrainedString, \n\t\t\t\t\t\t\t\t   constrainedStringLength, URL_TYPE_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Exactly what to do in the case of a URL parse error is a\n\t\t\t\t   bit complicated.  The standard action is to fail closed, \n\t\t\t\t   otherwise anyone who creates a URL that the certificate \n\t\t\t\t   software can't parse but that's still accepted by other \n\t\t\t\t   apps (who in general will bend over backwards to try and \n\t\t\t\t   accept almost any malformed URI, if they didn't do this \n\t\t\t\t   then half the Internet would stop working) would be able \n\t\t\t\t   to bypass the name constraint.  However this mode of \n\t\t\t\t   handling is complicated by the fact that to report a \n\t\t\t\t   failure at this point we need to report a match for \n\t\t\t\t   excluded subtrees but a non-match for permitted subtrees.  \n\t\t\t\t   Since it's more likely that we'll encounter a permitted-\n\t\t\t\t   subtrees whitelist we report the constraint as being not \n\t\t\t\t   matched which will reject the certificate for permitted-\n\t\t\t\t   subtrees (who in their right mind would trust something as \n\t\t\t\t   flaky as PKI software to reliably apply an excluded-\n\t\t\t\t   subtrees blacklist?  Even something as trivial as \n\t\t\t\t   \"ex%41mple.com\", let alone \"ex%u0041mple.com\", \n\t\t\t\t   \"ex&#x41;mple.com\", or \"ex%EF%BC%A1mpple.com\", is likely \n\t\t\t\t   to trivially fool all certificate software in existence, \n\t\t\t\t   so permitted-subtrees will never work anyway).  In \n\t\t\t\t   addition we throw an exception in debug mode */\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Adjust the constrained string information to contain only the \n\t\t\t   DNS name portion of the URI */\n\t\t\tconstrainedString = urlInfo.host;\n\t\t\tstartPos = urlInfo.hostLen - constrainingStringLength;\n\t\t\tif( !isShortIntegerRange( startPos ) )\n\t\t\t\treturn( FALSE );\n\t\t\tENSURES_B( boundsCheckZ( startPos, constrainingStringLength, \\\n\t\t\t\t\t\t\t\t\t urlInfo.hostLen ) );\n\n\t\t\t/* URIs have a special-case requirement where the absence of a\n\t\t\t   wildcard-match indicator (the leading dot) indicates that the\n\t\t\t   constraining DNS name is for a standalone host and not a \n\t\t\t   portion of the constrained string's DNS name.  This means\n\t\t\t   that the DNS-name portion of the URI must be an exact match\n\t\t\t   for the constraining string */\n\t\t\tif( !isWildcardMatch && startPos != 0 )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tENSURES_B( boundsCheckZ( startPos, constrainingStringLength, \\\n\t\t\t\t\t\t\t constrainedStringLength ) );\n\n\t/* Check whether the constraining string is a suffix of the constrained\n\t   string.  For DNS name constraints the rule for RFC 3280 became \n\t   \"adding to the LHS\" as for other constraints, in RFC 2459 it was\n\t   another special case where it had to be a subdomain as if an \n\t   implicit \".\" was present */\n\treturn( !strCompare( constrainedString + startPos, constrainingString, \n\t\t\t\t\t\t constrainingStringLength ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN matchAltnameComponent( IN const DATAPTR constrainedAttribute,\n\t\t\t\t\t\t\t\t\t  IN const DATAPTR constrainingAttribute,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType )\n\t{\n\tREQUIRES_B( DATAPTR_ISSET( constrainedAttribute ) );\n\tREQUIRES_B( DATAPTR_ISSET( constrainingAttribute ) );\n\tREQUIRES_B( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_RFC822NAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_DNSNAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );\n\n\t/* If the attribute being matched is a DN, use a DN-specific match */\n\tif( attributeType == CRYPT_CERTINFO_DIRECTORYNAME )\n\t\t{\n\t\tDATAPTR constrainedDnPtr, constrainingDnPtr;\n\t\tint status;\n\n\t\tstatus = getAttributeDataDN( constrainedAttribute, \n\t\t\t\t\t\t\t\t\t &constrainedDnPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = getAttributeDataDN( constrainingAttribute, &constrainingDnPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\treturn( compareDN( constrainingDnPtr, constrainedDnPtr, TRUE, \n\t\t\t\t\t\t   NULL ) );\n\t\t}\n\n\t/* It's a string name, use a substring match with attribute type-specific\n\t   special cases */\n\treturn( wildcardMatch( constrainedAttribute, constrainingAttribute, \n\t\t\t\t\t( attributeType == CRYPT_CERTINFO_RFC822NAME ) ? \\\n\t\t\t\t\t\tMATCH_EMAIL : \\\n\t\t\t\t\t( attributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER ) ? \\\n\t\t\t\t\t\tMATCH_URI : \\\n\t\t\t\t\t\tMATCH_NONE ) );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkAltnameConstraints( IN const DATAPTR subjectAttributes,\n\t\t\t\t\t\t\t\t\t\tIN const DATAPTR issuerAttributes,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isExcluded )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr, constrainedAttributePtr;\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_B( DATAPTR_ISVALID( subjectAttributes ) );\n\tREQUIRES_B( DATAPTR_ISVALID( issuerAttributes ) );\n\tREQUIRES_B( attributeType == CRYPT_CERTINFO_DIRECTORYNAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_RFC822NAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_DNSNAME || \\\n\t\t\t\tattributeType == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );\n\tREQUIRES_B( isExcluded == TRUE || isExcluded == FALSE );\n\n\t/* Check for the presence of constrained or constraining altName \n\t   components.  If either are absent, there are no constraints to \n\t   apply */\n\tattributePtr = findAttributeField( issuerAttributes,\n\t\t\t\t\t\t\t\t\t   isExcluded ? \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES : \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\t\t\t\t\t\t\t\t   attributeType );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( TRUE );\n\n\tLOOP_LARGE( constrainedAttributePtr = \\\n\t\t\t\t\tfindAttributeField( subjectAttributes, \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME, \\\n\t\t\t\t\t\t\t\t\t\tattributeType ), \\\n\t\t\t\tDATAPTR_ISSET( constrainedAttributePtr ),\n\t\t\t\tconstrainedAttributePtr = \\\n\t\t\t\t\tfindNextFieldInstance( constrainedAttributePtr ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributeCursor;\n\t\tint LOOP_ITERATOR_ALT;\n\t\tBOOLEAN isMatch = FALSE;\n\n\t\t/* Step through the constraining attributes checking if any match \n\t\t   the constrained attribute.  If it's an excluded subtree then none \n\t\t   can match, if it's a permitted subtree then at least one must \n\t\t   match */\n\t\tLOOP_LARGE_ALT( attributeCursor = attributePtr, \n\t\t\t\t\t\tDATAPTR_ISSET( attributeCursor ) && !isMatch,\n\t\t\t\t\t\tattributeCursor = \\\n\t\t\t\t\t\t\tfindNextFieldInstance( attributeCursor ) )\n\t\t\t{\n\t\t\tisMatch = matchAltnameComponent( constrainedAttributePtr,\n\t\t\t\t\t\t\t\t\t\t\t attributeCursor,\n\t\t\t\t\t\t\t\t\t\t\t attributeType );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tif( isExcluded == isMatch )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Check name constraints placed by an issuer, checked if complianceLevel >=\n   CRYPT_COMPLIANCELEVEL_PKIX_FULL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint checkNameConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE issuerAttributes,\n\t\t\t\t\t\t  const BOOLEAN isExcluded,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst CRYPT_ATTRIBUTE_TYPE constraintType = isExcluded ? \\\n\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES : CRYPT_CERTINFO_PERMITTEDSUBTREES;\n\tDATAPTR_ATTRIBUTE subjectAttributes = subjectCertInfoPtr->attributes;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tBOOLEAN isMatch = FALSE;\n\n\tassert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( DATAPTR_ISVALID( issuerAttributes ) );\n\n\t/* If this is a PKIX path-kludge CA certificate then the name \n\t   constraints don't apply to it (PKIX section 4.2.1.11).  This is \n\t   required in order to allow extra certificates to be kludged into the \n\t   path without violating the constraint.  For example with the chain:\n\n\t\tIssuer\tSubject\t\tConstraint\n\t\t------\t-------\t\t----------\n\t\tRoot\tCA\t\t\tpermitted = \"EE\"\n\t\tCA'\t\tCA'\n\t\tCA\t\tEE\n\n\t   the kludge certificate CA' must be excluded from name constraint \n\t   restrictions in order for the path to be valid.  Obviously this is \n\t   only necessary for constraints set by the immediate parent but PKIX \n\t   says it's for constraints set by all certificates in the chain (!!), \n\t   thus making the pathkludge certificate exempt from any name \n\t   constraints and not just the one that would cause problems */\n\tif( isPathKludge( subjectCertInfoPtr ) == TRUE )\n\t\treturn( CRYPT_OK );\n\n\t/* Check the subject DN if constraints exist.  If it's an excluded \n\t   subtree then none can match, if it's a permitted subtree then at \n\t   least one must match.  We also check for the special case of an\n\t   empty subject DN, which acts as a wildcard that matches/doesn't\n\t   match permitted/excluded as required */\n\tREQUIRES( DATAPTR_ISVALID( subjectCertInfoPtr->subjectName ) );\n\tattributePtr = findAttributeField( issuerAttributes, constraintType, \n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_DIRECTORYNAME );\n\tif( DATAPTR_ISSET( attributePtr ) && \\\n\t\tDATAPTR_ISSET( subjectCertInfoPtr->subjectName ) )\n\t\t{\n\t\tint LOOP_ITERATOR;\n\n\t\tLOOP_LARGE_CHECKINC( DATAPTR_ISSET( attributePtr ) && !isMatch,\n\t\t\t\t\t\t\t attributePtr = findNextFieldInstance( attributePtr ) )\n\t\t\t{\n\t\t\tDATAPTR_DN dnPtr;\n\t\t\tint status;\n\n\t\t\tstatus = getAttributeDataDN( attributePtr, &dnPtr );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* Check whether the constraining DN is a substring of the \n\t\t\t\t   subject DN.  For example if the constraining DN is \n\t\t\t\t   C=US/O=Foo/OU=Bar and the subject DN is \n\t\t\t\t   C=US/O=Foo/OU=Bar/CN=Baz then compareDN() will return \n\t\t\t\t   TRUE to indicate that it's a substring */\n\t\t\t\tisMatch = compareDN( dnPtr, subjectCertInfoPtr->subjectName, \n\t\t\t\t\t\t\t\t\t TRUE, NULL );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( isExcluded == isMatch )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_SUBJECTNAME, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* DN constraints apply to both the main subject DN and any other DNs \n\t   that may be present as subject altNames, so after we've checked the \n\t   main DN we check any altName DNs as well */\n\tif( !checkAltnameConstraints( subjectAttributes, issuerAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_DIRECTORYNAME, isExcluded ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, \n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* Compare the Internet-related names if constraints exist.  We don't\n\t   have to check for the special case of an email address in the DN \n\t   since the certificate import code transparently maps this to the \n\t   appropriate altName component */\n\tif( !checkAltnameConstraints( subjectAttributes, issuerAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_RFC822NAME, isExcluded ) || \\\n\t\t!checkAltnameConstraints( subjectAttributes, issuerAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_DNSNAME, isExcluded ) || \\\n\t\t!checkAltnameConstraints( subjectAttributes, issuerAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, \n\t\t\t\t\t\t\t\t  isExcluded ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_SUBJECTALTNAME, \n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Policy Constraints\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\n/* Check whether a policy is the wildcard anyPolicy */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isAnyPolicy( IN const DATAPTR_ATTRIBUTE attributePtr )\n\t{\n\tvoid *policyOidPtr;\n\tint policyOidLength, status;\n\n\tREQUIRES_B( DATAPTR_ISSET( attributePtr ) );\n\n\tstatus = getAttributeDataPtr( attributePtr, &policyOidPtr, \n\t\t\t\t\t\t\t\t  &policyOidLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\treturn( ( policyOidLength == sizeofOID( OID_ANYPOLICY ) && \\\n\t\t\t  !memcmp( policyOidPtr, OID_ANYPOLICY, \n\t\t\t\t\t   sizeofOID( OID_ANYPOLICY ) ) ) ? TRUE : FALSE );\n\t}\n\n/* Check whether a set of policies contains an instance of the anyPolicy\n   wildcard */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN containsAnyPolicy( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_B( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_B( isValidExtension( attributeType ) );\n\t\n\tLOOP_LARGE( attributeCursor = \\\n\t\t\t\t\tfindAttributeField( attributePtr, attributeType, \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE ), \n\t\t\t\tDATAPTR_ISSET( attributeCursor ),\n\t\t\t\tattributeCursor = findNextFieldInstance( attributeCursor ) )\n\t\t{\n\t\tif( isAnyPolicy( attributeCursor ) )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Check the type of policy present in a certificate and make sure that it's \n   valid */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic BOOLEAN checkPolicyType( const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\tOUT_BOOL BOOLEAN *hasPolicy, \n\t\t\t\t\t\t\t\tOUT_BOOL BOOLEAN *hasAnyPolicy,\n\t\t\t\t\t\t\t\tconst BOOLEAN inhibitAnyPolicy )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor = attributePtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( hasPolicy, sizeof( BOOLEAN ) ) );\n\tassert( isWritePtr( hasAnyPolicy, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_B( inhibitAnyPolicy == TRUE || inhibitAnyPolicy == FALSE );\n\n\t/* Clear return values */\n\t*hasPolicy = *hasAnyPolicy = FALSE;\n\n\t/* Make sure that there's a policy present and that it's a specific \n\t   policy if an explicit policy is required (the ability to disallow the \n\t   wildcard policy via inhibitAnyPolicy was introduced in RFC 3280 along \n\t   with the introduction of anyPolicy) */\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn( FALSE );\n\tLOOP_LARGE_CHECKINC( DATAPTR_ISSET( attributeCursor ), \n\t\t\t\t\t\t attributeCursor = findNextFieldInstance( attributeCursor ) )\n\t\t{\n\t\tif( isAnyPolicy( attributeCursor ) )\n\t\t\t*hasAnyPolicy = TRUE;\n\t\telse\n\t\t\t*hasPolicy = TRUE;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( inhibitAnyPolicy )\n\t\t{\n\t\t/* The wildcard anyPolicy isn't valid for the subject, if there's no\n\t\t   other policy set then this is an error, otherwise we continue \n\t\t   without the wildcard match allowed */\n\t\tif( !*hasPolicy )\n\t\t\treturn( FALSE );\n\t\t*hasAnyPolicy = FALSE;\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check whether a given policy is present in a certificate */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 2 ) ) \\\nBOOLEAN isPolicyPresent( const DATAPTR_ATTRIBUTE subjectAttributes,\n\t\t\t\t\t\t IN_BUFFER( issuerPolicyValueLength ) \\\n\t\t\t\t\t\t\t\tconst void *issuerPolicyValue,\n\t\t\t\t\t\t IN_LENGTH_OID const int issuerPolicyValueLength )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( issuerPolicyValue, issuerPolicyValueLength ) );\n\n\tREQUIRES_B( DATAPTR_ISVALID( subjectAttributes ) );\n\tREQUIRES_B( issuerPolicyValueLength > 0 && \\\n\t\t\t\tissuerPolicyValueLength < MAX_POLICY_SIZE );\n\n\tLOOP_LARGE( attributeCursor = subjectAttributes, \n\t\t\t\tDATAPTR_ISSET( attributeCursor ),\n\t\t\t\tattributeCursor = findNextFieldInstance( attributeCursor ) )\n\t\t{\n\t\tvoid *subjectPolicyValuePtr;\n\t\tint subjectPolicyValueLength;\n\n\t\tstatus = getAttributeDataPtr( attributeCursor, &subjectPolicyValuePtr, \n\t\t\t\t\t\t\t\t\t  &subjectPolicyValueLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\t\tif( issuerPolicyValueLength == subjectPolicyValueLength && \\\n\t\t\t!memcmp( issuerPolicyValue, subjectPolicyValuePtr, \n\t\t\t\t\t issuerPolicyValueLength ) )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Check policy constraints placed by an issuer, checked if complianceLevel \n   >= CRYPT_COMPLIANCELEVEL_PKIX_FULL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 7, 8 ) ) \\\nint checkPolicyConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\tIN const DATAPTR_ATTRIBUTE issuerAttributes,\n\t\t\t\t\t\t\tIN_ENUM_OPT( POLICY ) const POLICY_TYPE policyType,\n\t\t\t\t\t\t\tIN_OPT const POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\tIN_RANGE( 0, MAX_CHAINLENGTH ) const int policyLevel,\n\t\t\t\t\t\t\tconst BOOLEAN allowMappedPolicies,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE constrainingAttributePtr, constrainedAttributePtr;\n\tBOOLEAN subjectHasPolicy, issuerHasPolicy;\n\tBOOLEAN subjectHasAnyPolicy, issuerHasAnyPolicy;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( policyInfo == NULL && policyLevel == 0 ) || \\\n\t\t\t( isReadPtr( policyInfo, sizeof( POLICY_INFO ) ) && \\\n\t\t\t  ( policyLevel >= 0 && policyLevel < MAX_CHAINLENGTH ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( DATAPTR_ISSET( issuerAttributes ) );\n\tREQUIRES( isEnumRangeOpt( policyType, POLICY ) );\n\tREQUIRES( policyLevel >= 0 && policyLevel < MAX_CHAINLENGTH );\n\tREQUIRES( allowMappedPolicies == TRUE || allowMappedPolicies == FALSE );\n\n\t/* Get references to the constrained and constraining attributes */\n\tconstrainingAttributePtr = \\\n\t\t\t\t\tfindAttributeField( issuerAttributes, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\tconstrainedAttributePtr = \\\n\t\t\t\t\tfindAttributeField( subjectCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\n\t/* If there's a policy mapping present then neither the issuer nor \n\t   subject domain policies can be the wildcard anyPolicy (PKIX section \n\t   4.2.1.6) */\n\tif( containsAnyPolicy( issuerAttributes, \n\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUERDOMAINPOLICY ) || \\\n\t\tcontainsAnyPolicy( issuerAttributes, \n\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTDOMAINPOLICY ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_POLICYMAPPINGS, \n\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If there's no requirement for a policy and there's none set, we're \n\t   done */\n\tif( policyType == POLICY_NONE && \\\n\t\tDATAPTR_ISNULL( constrainedAttributePtr ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check the subject policy */\n\tif( !checkPolicyType( constrainedAttributePtr, &subjectHasPolicy,\n\t\t\t\t\t\t  &subjectHasAnyPolicy, \n\t\t\t\t\t\t  ( policyType == POLICY_NONE_SPECIFIC || \\\n\t\t\t\t\t\t\tpolicyType == POLICY_SUBJECT_SPECIFIC || \\\n\t\t\t\t\t\t\tpolicyType == POLICY_BOTH_SPECIFIC ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If there's no requirement for an issuer policy and there's none set \n\t   by the issuer, we're done */\n\tif( ( ( policyType == POLICY_SUBJECT ) || \\\n\t\t  ( policyType == POLICY_SUBJECT_SPECIFIC ) ) && \\\n\t\tDATAPTR_ISNULL( constrainingAttributePtr ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check the issuer policy */\n\tif( !checkPolicyType( constrainingAttributePtr , &issuerHasPolicy,\n\t\t\t\t\t\t  &issuerHasAnyPolicy, \n\t\t\t\t\t\t  ( policyType == POLICY_BOTH_SPECIFIC ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* Both the issuer and subject have some sort of policy, if either are \n\t   anyPolicy wildcards (introduced in RFC 3280 section 4.2.1.5) then \n\t   it's considered a match */\n\tif( subjectHasAnyPolicy || issuerHasAnyPolicy )\n\t\treturn( CRYPT_OK );\n\n\t/* An explicit policy is required, make sure that at least one of the \n\t   issuer policies matches at least one of the subject policies.  Note\n\t   that there's no exception for PKIX path-kludge certificates, this is \n\t   an error in the RFC for which the text at this point is unchanged \n\t   from RFC 2459.  In fact this contradicts the path-processing \n\t   pesudocode but since that in turn contradicts the main text in a \n\t   number of places we take the main text as definitive, not the buggy \n\t   pseudocode */\n\tif( policyInfo != NULL )\n\t\t{\n\t\tconst POLICY_DATA *policyData = policyInfo->policies;\n\t\tint i;\n\n\t\tLOOP_MED( i = 0, i < policyInfo->noPolicies, i++ )\n\t\t\t{\n\t\t\tif( policyData[ i ].isMapped && !allowMappedPolicies )\n\t\t\t\tcontinue;\n\t\t\tif( isPolicyPresent( constrainedAttributePtr, \n\t\t\t\t\t\t\t\t policyData[ i ].data, \n\t\t\t\t\t\t\t\t policyData[ i ].length ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\telse\n\t\t{\n\t\tDATAPTR_ATTRIBUTE constrainingAttributeCursor;\n\n\t\tLOOP_LARGE( constrainingAttributeCursor = constrainingAttributePtr, \n\t\t\t\t\t!DATAPTR_ISNULL( constrainingAttributeCursor ), \n\t\t\t\t\tconstrainingAttributeCursor = \\\n\t\t\t\t\t\tfindNextFieldInstance( constrainingAttributeCursor ) )\n\t\t\t{\n\t\t\tvoid *constrainingPolicyValuePtr;\n\t\t\tint constrainingPolicyValueLength, status;\n\n\t\t\tstatus = getAttributeDataPtr( constrainingAttributeCursor, \n\t\t\t\t\t\t\t\t\t\t  &constrainingPolicyValuePtr, \n\t\t\t\t\t\t\t\t\t\t  &constrainingPolicyValueLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tif( isPolicyPresent( constrainedAttributePtr, \n\t\t\t\t\t\t\t\t constrainingPolicyValuePtr, \n\t\t\t\t\t\t\t\t constrainingPolicyValueLength ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* We couldn't find a matching policy, report an error */\n\tsetErrorValues( CRYPT_CERTINFO_CERTPOLICYID, CRYPT_ERRTYPE_CONSTRAINT );\n\n\treturn( CRYPT_ERROR_INVALID );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Path Constraints\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\n/* Check path constraints placed by an issuer, checked if complianceLevel \n   >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint checkPathConstraints( IN const CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int pathLength,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint value, status;\n\n\tassert( isReadPtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( isShortIntegerRange( pathLength ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* If this is a PKIX path-kludge certificate then the path length \n\t   constraints don't apply to it (PKIX section 4.2.1.10).  This is \n\t   required in order to allow extra certificates to be kludged into the \n\t   path without violating the name constraint */\n\tif( isPathKludge( subjectCertInfoPtr ) == TRUE )\n\t\treturn( CRYPT_OK );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* If the path length constraint hasn't been triggered yet we're OK */\n\tif( pathLength > 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* If the certificate is self-signed (i.e. the certificate is applying \n\t   the constraint to itself) then a path length constraint of zero is \n\t   valid.  Checking only the subject certificate information is safe \n\t   because the calling code has guaranteed that if the certificate is \n\t   self-signed then the issuer attributes are the attributes from the \n\t   subject certificate */\n\tif( TEST_FLAG( subjectCertInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The path length constraint is in effect, the next certificate down \n\t   the chain must be an end-entity certificate */\n\tstatus = getAttributeFieldValue( subjectCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) && value > 0 )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck RPKI Attributes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_RPKI\n\n/* Check attributes for a resource RPKI (RPKI) certificate.  This is \n   somewhat ugly in that it entails a number of implicit checks rather\n   than just applying constraints specified in the certificate itself,\n   but then again it's not much different to the range of checks\n   hardcoded into checkCert(), the only real difference is that the latter\n   is specified for all certificates while these are only for RPKI\n   certificates */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4, 5 ) ) \\\nstatic int checkRPKIAttributes( const DATAPTR_ATTRIBUTE subjectAttributes,\n\t\t\t\t\t\t\t\tconst BOOLEAN isCA,\n\t\t\t\t\t\t\t\tconst BOOLEAN isSelfSigned,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tvoid *policyOidPtr;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT( \"checkRPKIAttributes\" );\n\tint policyOidLength, value, status;\n\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE  ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( subjectAttributes ) );\n\tREQUIRES( isCA == TRUE || isCA == FALSE );\n\tREQUIRES( isSelfSigned == TRUE || isSelfSigned == FALSE );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Check that there's a keyUsage present, and that for CA certificates \n\t   it's the CA usages and for EE certificates it's digital signature \n\t   (RPKI section 3.9.4) */\n\tstatus = getAttributeFieldValue( subjectAttributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( isCA )\n\t\t{\n\t\tif( value != CRYPT_KEYUSAGE_DIGITALSIGNATURE )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\telse\n\t\t{\n\t\tif( value != ( CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t   CRYPT_KEYUSAGE_CRLSIGN ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"getAttributeFieldValue\" );\n\n\t/* If it's a CA, check that there's no extendedKeyUsage (RPKI section \n\t   3.9.5) and there's a caRepository SIA (RPKI section 3.9.8) */\n\tif( isCA )\n\t\t{\n\t\tif( checkAttributePresent( subjectAttributes, \n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_EXTKEYUSAGE ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_EXTKEYUSAGE, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tif( !checkAttributeFieldPresent( subjectAttributes,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkAttributePresent\" );\n\n\t/* If it's not self-signed (i.e. not a root certificate) check that\n\t   there's a caIssuers AIA (RPKI section 3.9.7) */\n\tif( !isSelfSigned )\n\t\t{\n\t\tif( !checkAttributeFieldPresent( subjectAttributes,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkAttributeFieldPresent\" );\n\n\t/* Check that there's an RPKI policy present (RPKI section 3.9.9) */\n\tattributePtr = findAttributeField( subjectAttributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CERTPOLICYID,\n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( attributePtr == NULL )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tstatus = getAttributeDataPtr( attributePtr, &policyOidPtr, \n\t\t\t\t\t\t\t\t  &policyOidLength );\n\tif( cryptStatusError( status ) || \\\n\t\tpolicyOidLength != sizeofOID( OID_RPKI_POLICY ) || \\\n\t\tmemcmp( policyOidPtr, OID_RPKI_POLICY, \n\t\t\t\tsizeofOID( OID_RPKI_POLICY ) ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"findAttributeField\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"checkRPKIAttributes\", \n\t\t\t\t\t\t\t\t\t\"getAttributeFieldValue\", \n\t\t\t\t\t\t\t\t\t\"checkAttributePresent\", \n\t\t\t\t\t\t\t\t\t\"checkAttributeFieldPresent\", \n\t\t\t\t\t\t\t\t\t\"findAttributeField\" ) );\n\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_RPKI */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck a Certificate\tObject\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Check the consistency of a CRL against its issuing certificate.  Note \n   that this is the reverse of the usual form of checking the certificate \n   against the CRL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nstatic int checkCrlConsistency( IN const CERT_INFO *crlInfoPtr,\n\t\t\t\t\t\t\t\tIN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\tIN_RANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \\\n\t\t\t\t\t\t\t\t\t\t  CRYPT_COMPLIANCELEVEL_LAST - 1 ) \\\n\t\t\t\t\t\t\t\t\tconst int complianceLevel,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint deltaCRLindicator, status;\n\n\tassert( isReadPtr( crlInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If it's a delta CRL make sure that the CRL numbers make sense (that \n\t   is, that the delta CRL was issued after the full CRL) */\n\tstatus = getAttributeFieldValue( crlInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_DELTACRLINDICATOR, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\t &deltaCRLindicator );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint crlNumber;\n\n\t\tstatus = getAttributeFieldValue( crlInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CRLNUMBER, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &crlNumber );\n\t\tif( cryptStatusOK( status ) && crlNumber >= deltaCRLindicator )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_DELTACRLINDICATOR,\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* If it's a standalone CRL entry used purely as a container for \n\t   revocation data don't try and perform any issuer-based checking */\n\tif( issuerCertInfoPtr == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the issuer can sign CRLs and that the issuer \n\t   certificate in general is in order */\n\treturn( checkKeyUsage( issuerCertInfoPtr, \n\t\t\t\t\t\t   CHECKKEY_FLAG_CA | CHECKKEY_FLAG_GENCHECK, \n\t\t\t\t\t\t   CRYPT_KEYUSAGE_CRLSIGN, complianceLevel, \n\t\t\t\t\t\t   errorLocus, errorType ) );\n\t}\n#endif /* USE_CERTREV */\n\n/* Perform basic checks on a certificate.  Apart from its use as part of the \n   normal certificate-checking process this is also used to provide a quick\n   \"is this certificate obviously invalid\" check without having to check\n   signatures from issuing certificates and other paraphernalia, for example\n   when a full certificate check has been performed earlier and all we want\n   to do is make sure that the certificate hasn't expired or been declared\n   untrusted in the meantime */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertBasic( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE *errorLocus;\n\tCRYPT_ERRTYPE_TYPE *errorType;\n\tconst time_t currentTime = getTime();\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint complianceLevel, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* Get references to the certificate's error information */\n\terrorLocus = &certInfoPtr->errorLocus;\n\terrorType = &certInfoPtr->errorType;\n\n\t/* Determine how much checking we need to perform */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* There is one universal case in which a certificate is regarded as \n\t   invalid and that's when it's explicitly not trusted */\n\tif( certInfoPtr->cCertCert->trustedUsage == 0 )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE,\n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If we're running in oblivious mode, we're done */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"IMESSAGE_GETATTRIBUTE\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_REDUCED\" );\n\n\t/* Check that the validity period is in order.  If we're checking an \n\t   existing certificate then the start time has to be valid, if we're \n\t   creating a new certificate then it doesn't have to be valid since the \n\t   certificate could be created for use in the future */\n\tif( currentTime <= MIN_TIME_VALUE )\n\t\t{\n\t\t/* Time is broken, we can't reliably check for expiry times */\n\t\tsetErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( certInfoPtr->startTime >= certInfoPtr->endTime || \\\n\t\t( certInfoPtr->certificate != NULL && \\\n\t\t  currentTime < certInfoPtr->startTime ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_VALIDFROM, CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( currentTime > certInfoPtr->endTime )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_VALIDTO, CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"timeCheck\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\"timeCheck\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the validity of a subject certificate based on an issuer \n   certificate with the level of checking performed depending on the \n   complianceLevel setting.  If the shortCircuitCheck flag is set (used for \n   certificate issuer : subject pairs that may already have been checked) \n   we skip the constant-result checks if the combination has already been \n   checked at this compliance level */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint checkCert( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t   IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t   const BOOLEAN shortCircuitCheck,\n\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE subjectAttributes, attributePtr;\n\tBOOLEAN subjectSelfSigned;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tDATAPTR_ATTRIBUTE issuerAttributes;\n\tBOOLEAN subjectIsCA = FALSE, issuerIsCA = FALSE;\n\tint value;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint complianceLevel, status;\n\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE  ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( shortCircuitCheck == TRUE || shortCircuitCheck == FALSE );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Get certificate information */\n\tsubjectAttributes = subjectCertInfoPtr->attributes;\n\tsubjectSelfSigned = TEST_FLAG( subjectCertInfoPtr->flags, \n\t\t\t\t\t\t\t\t   CERT_FLAG_SELFSIGNED ) ? TRUE : FALSE;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tif( issuerCertInfoPtr != NULL )\n\t\tissuerAttributes = issuerCertInfoPtr->attributes;\n\telse\n\t\tDATAPTR_SET( issuerAttributes, NULL );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* Determine how much checking we need to perform.  If this is a \n\t   currently-under-construction certificate then we use the maximum \n\t   compliance level to ensure that cryptlib never produces broken \n\t   certificates */\n\tif( subjectCertInfoPtr->certificate == NULL )\n\t\tcomplianceLevel = CRYPT_COMPLIANCELEVEL_PKIX_FULL;\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( subjectCertInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* If it's some form of certificate request or an OCSP object (which \n\t   means that it isn't signed by an issuer in the normal sense) then \n\t   there's nothing to check (yet) */\n\tswitch( subjectCertInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\t/* It's an issuer-signed object, there must be an issuer \n\t\t\t   certificate present */\n\t\t\tREQUIRES( issuerCertInfoPtr != NULL );\n\t\t\tif( TEST_FLAG( subjectCertInfoPtr->flags, \n\t\t\t\t\t\t   CERT_FLAG_CERTCOLLECTION ) )\n\t\t\t\t{\n\t\t\t\t/* Certificate collections are pure container objects for \n\t\t\t\t   which the base certificate object doesn't correspond to \n\t\t\t\t   an actual certificate */\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t/* These are merely templates submitted to a CA, there's nothing \n\t\t\t   to check.  More specifically, the template could contain \n\t\t\t   constraints that only make sense once the issuer certificate \n\t\t\t   is incorporated into a chain or a future-dated validity time \n\t\t\t   or a CA keyUsage for which the CA provides the appropriate \n\t\t\t   matching basicConstraints value(s) so we can't really perform \n\t\t\t   much checking here */\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"IMESSAGE_GETATTRIBUTE\" ) );\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t/* There must be an issuer certificate present unless we're \n\t\t\t   checking a standalone CRL entry that acts purely as a \n\t\t\t   container for revocation data */\n\t\t\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t\t\t/* CRL checking is handled specially */\n\t\t\tstatus = checkCrlConsistency( subjectCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  issuerCertInfoPtr, complianceLevel, \n\t\t\t\t\t\t\t\t\t\t  errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"checkCrlConsistency\" );\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"IMESSAGE_GETATTRIBUTE\",\n\t\t\t\t\t\t\t\t\t\t\t\"checkCrlConsistency\" ) );\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREV */\n\n\t\tcase CRYPT_CERTTYPE_CMS_ATTRIBUTES:\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\tretIntError();\n\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t/* These aren't normal certificate types, there's nothing to \n\t\t\t   check - we can't even check the issuer since they're not \n\t\t\t   normally issued by CAs */\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"IMESSAGE_GETATTRIBUTE\" ) );\n\t\t\treturn( CRYPT_OK );\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tENSURES( issuerCertInfoPtr != NULL );\n\tENSURES( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t subjectCertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* Perform a basic check for obvious invalidity issues */\n\tstatus = checkCertBasic( subjectCertInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkCertBasic\" );\n\n\t/* There is one universal case in which a certificate is regarded as \n\t   invalid and that's when the issuing certificate isn't trusted as an \n\t   issuer.  We perform the check in oblivious mode to ensure that only \n\t   the basic trusted usage gets checked at this point */\n\tif( issuerCertInfoPtr->cCertCert->trustedUsage != CRYPT_ERROR )\n\t\t{\n\t\tstatus = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA, \n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_KEYCERTSIGN,\n\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_OBLIVIOUS, \n\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkKeyUsage\" );\n\n\t/* If we're running in oblivious mode, we're done */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkKeyUsage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_REDUCED\" );\n\n\t/* If it's a self-signed certificate or if we're doing a short-circuit \n\t   check of a certificate in a chain that's already been checked and \n\t   we've already checked it at the appropriate level then there's no \n\t   need to perform any further checks */\n\tif( ( subjectSelfSigned || shortCircuitCheck ) && \\\n\t\t( subjectCertInfoPtr->cCertCert->maxCheckLevel >= complianceLevel ) )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkKeyUsage\",\n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Perform certificate object-type-specific version checks */\n\tif( subjectCertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\t{\n\t\t/* Attribute certificates must be v2 */\n\t\tif( subjectCertInfoPtr->version != 2 )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_VERSION, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* If the certificate isn't v3 or above then it's only allowed under \n\t\t   very specific circumstances */\n\t\tif( subjectCertInfoPtr->version < X509_V3 )\n\t\t\t{\n\t\t\t/* If the certificate isn't self-signed then it has to be \n\t\t\t   version 3 or above.  This is because the only certificates \n\t\t\t   that are still allowed to be X.509v1 are trusted root \n\t\t\t   certificates, any chain-internal certificate must be X.509v3 \n\t\t\t   or higher.  In addition if it's less than version 3 then it \n\t\t\t   can't have any extensions.\n\t\t\t   \n\t\t\t   This is another failure situation for which it's difficult to \n\t\t\t   provide appropriately descriptive error information, however \n\t\t\t   a certificate like this is so broken that it should never be \n\t\t\t   encountered, and if it is then a somewhat odd error code is \n\t\t\t   to be expected */\n\t\t\tif( !subjectSelfSigned || \\\n\t\t\t\tDATAPTR_ISSET( subjectCertInfoPtr->attributes ) )\n\t\t\t\t{\n\t\t\t\tsetErrorValues( CRYPT_CERTINFO_VERSION, \n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"version\" );\n\n\t/* If the certificate isn't self-signed, check name chaining */\n\tif( !subjectSelfSigned )\n\t\t{\n\t\t/* Check that the subject issuer name and issuer subject name chain\n\t\t   properly.  If the DNs are present in pre-encoded form we do a \n\t\t   binary comparison, which is faster than calling compareDN() */\n\t\tif( subjectCertInfoPtr->certificate != NULL )\n\t\t\t{\n\t\t\tif( subjectCertInfoPtr->issuerDNsize != \\\n\t\t\t\t\t\t\tissuerCertInfoPtr->subjectDNsize || \\\n\t\t\t\tmemcmp( subjectCertInfoPtr->issuerDNptr, \n\t\t\t\t\t\tissuerCertInfoPtr->subjectDNptr, \n\t\t\t\t\t\tsubjectCertInfoPtr->issuerDNsize ) )\n\t\t\t\t{\n\t\t\t\tsetErrorValues( CRYPT_CERTINFO_ISSUERNAME, \n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( !compareDN( subjectCertInfoPtr->issuerName,\n\t\t\t\t\t\t\tissuerCertInfoPtr->subjectName, \n\t\t\t\t\t\t\tFALSE, NULL ) )\n\t\t\t\t{\n\t\t\t\tsetErrorValues( CRYPT_CERTINFO_ISSUERNAME, \n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"compareDN\" );\n\n\t/* If we're doing a reduced level of checking, we're done */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )\n\t\t{\n\t\tif( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )\n\t\t\tsubjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t\"version\", \"compareDN\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_STANDARD\" );\n\n\t/* Check that the certificate usage flags are present and consistent.  \n\t   The key usage checking level ranges up to \n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL so we re-do the check even if it's \n\t   already been done at a lower level */\n\tif( subjectCertInfoPtr->cCertCert->maxCheckLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \\\n\t\tsubjectCertInfoPtr->type != CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\t{\n\t\tstatus = checkKeyUsage( subjectCertInfoPtr, CHECKKEY_FLAG_GENCHECK, \n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_NONE, complianceLevel, \n\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n        }\n\tCFI_CHECK_UPDATE( \"checkKeyUsage\" );\n\n\t/* If the certificate isn't self-signed check that the issuer is a CA */\n\tif( !subjectSelfSigned )\n\t\t{\n\t\tstatus = checkKeyUsage( issuerCertInfoPtr, CHECKKEY_FLAG_CA, \n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_KEYCERTSIGN, complianceLevel, \n\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* There was a problem with the issuer certificate, convert the \n\t\t\t   error to an issuer constraint */\n\t\t\t*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkKeyUsageIssuer\" );\n\n\t/* Check all the blob (unrecognised) attributes to see if any are marked \n\t   critical.  We only do this if it's an existing certificate that we've\n\t   imported rather than one that we've just created since applying this \n\t   check to the latter would make it impossible to create certificates \n\t   with unrecognised critical extensions */\n\tif( subjectCertInfoPtr->certificate != NULL )\n\t\t{\n\t\tATTRIBUTE_ENUM_INFO attrEnumInfo;\n\t\tint LOOP_ITERATOR;\n\n\t\tLOOP_LARGE( attributePtr = \\\n\t\t\t\t\t\tgetFirstAttribute( &attrEnumInfo, subjectAttributes, \\\n\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_ENUM_BLOB ), \n\t\t\t\t\tDATAPTR_ISSET( attributePtr ),\n\t\t\t\t\tattributePtr = getNextAttribute( &attrEnumInfo ) )\n\t\t\t{\n\t\t\t/* If we've found an unrecognised critical extension, reject the \n\t\t\t   certificate (PKIX section 4.2).  The one exception to this is \n\t\t\t   if the attribute was recognised but has been ignored at this \n\t\t\t   compliance level, in which case it's treated as a blob\n\t\t\t   attribute */\n\t\t\tif( checkAttributeProperty( attributePtr, \\\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_CRITICAL ) && \\\n\t\t\t\t!checkAttributeProperty( attributePtr, \\\n\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_IGNORED ) )\n\t\t\t\t{\n\t\t\t\tsetErrorValues( CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkAttributeProperty\" );\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* If we're not doing at least partial PKIX checking, we're done */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )\n\t\t{\n\t\tif( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )\n\t\t\tsubjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_10( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t \"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t \"version\", \"compareDN\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t\t \"checkKeyUsage\", \"checkKeyUsageIssuer\",\n\t\t\t\t\t\t\t\t\t\t \"checkAttributeProperty\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\" );\n\n\t/* Determine whether the subject or issuer are CA certificates */\n\tstatus = getAttributeFieldValue( subjectAttributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) )\n\t\tsubjectIsCA = ( value > 0 ) ? TRUE : FALSE;\n\tstatus = getAttributeFieldValue( issuerAttributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) )\n\t\tissuerIsCA = ( value > 0 ) ? TRUE : FALSE;\n\n\t/* Constraints can only be present in CA certificates.  The issuer may \n\t   not be a proper CA if it's a self-signed end entity certificate or \n\t   an X.509v1 CA certificate, which is why we also check for \n\t   !issuerIsCA */\n\tif( DATAPTR_ISSET( subjectAttributes ) )\n\t\t{\n\t\tif( !subjectIsCA && invalidAttributesPresent( subjectAttributes, FALSE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  errorLocus, errorType ) )\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\tif( !issuerIsCA && invalidAttributesPresent( subjectAttributes, TRUE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t errorLocus, errorType ) )\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"invalidAttributesPresent\" );\n\n\t/*  From this point onwards if we're doing a short-circuit check of \n\t    certificates in a chain, we don't apply constraint checks.  This is \n\t\tbecause the certificate-chain code has already performed far more \n\t\tcomplete checks of the various constraints set by all the \n\t\tcertificates in the chain rather than just the current certificate \n\t\tissuer : subject pair */\n\n\t/* If there's a path length constraint present, apply it */\n\tstatus = getAttributeFieldValue( issuerAttributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_PATHLENCONSTRAINT, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) && !shortCircuitCheck )\n\t\t{\n\t\tstatus = checkPathConstraints( subjectCertInfoPtr, value,\n\t\t\t\t\t\t\t\t\t   errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkPathConstraints\" );\n\n\t/* In order to dig itself out of a hole caused by a circular definition, \n\t   RFC 3280 added a new extKeyUsage anyExtendedKeyUsage (rather than the\n\t   more obvious fix of removing the problematic definition).  \n\t   Unfortunately this causes more problems than it solves because the exact\n\t   semantics of this new usage aren't precisely defined.  To fix this \n\t   problem we invent some plausible ones ourselves: If the only eKU is \n\t   anyKU we treat the overall extKeyUsage as empty, i.e. there are no\n\t   particular restrictions on usage.  If any other usage is present then \n\t   the extension has become self-contradictory so we treat the anyKU as\n\t   being absent.  See the comment for getExtendedKeyUsageFlags() for how\n\t   this is handled */\n\tattributePtr = findAttributeField( subjectAttributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) && \\\n\t\tcheckAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL ) )\n\t\t{\n\t\t/* If anyKU is present the extension must be non-critical \n\t\t   (PKIX section 4.2.1.13) */\n\t\tsetErrorValues( CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE, \n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"anyKeyUsage\" );\n\n\t/* If this is a resource PKI (RPKI) certificate, apply RPKI-specific \n\t   checks */\n#ifdef USE_RPKI\n\tif( checkAttributePresent( subjectAttributes, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_IPADDRESSBLOCKS ) || \\\n\t\tcheckAttributePresent( subjectAttributes, \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_AUTONOMOUSSYSIDS ) )\n\t\t{\n\t\tANALYSER_HINT( subjectAttributes != NULL );\n\n\t\tstatus = checkRPKIAttributes( subjectAttributes, subjectIsCA,\n\t\t\t\t\t\t\t\t\t  subjectSelfSigned, errorLocus,\n\t\t\t\t\t\t\t\t\t  errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* USE_RPKI */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* If we're not doing full PKIX checking, we're done.  In addition since \n\t   all of the remaining checks are constraint checks we can exit at this\n\t   point if we're doing a short-circuit check */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL || \\\n\t\tshortCircuitCheck )\n\t\t{\n\t\tif( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )\n\t\t\tsubjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_14( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t \"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t \"version\", \"compareDN\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t\t \"checkKeyUsage\", \"checkKeyUsageIssuer\",\n\t\t\t\t\t\t\t\t\t\t \"checkAttributeProperty\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\",\n\t\t\t\t\t\t\t\t\t\t \"invalidAttributesPresent\", \n\t\t\t\t\t\t\t\t\t\t \"checkPathConstraints\", \"anyKeyUsage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_PKIX_FULL\" );\n\n\t/* If the issuing certificate has name constraints and isn't \n\t   self-signed make sure that the subject name and altName fall within \n\t   the constrained subtrees.  Since excluded subtrees override permitted \n\t   subtrees we check these first */\n\tif( !subjectSelfSigned )\n\t\t{\n\t\tattributePtr = findAttributeField( issuerAttributes, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t{\n\t\t\tstatus = checkNameConstraints( subjectCertInfoPtr, attributePtr, \n\t\t\t\t\t\t\t\t\t\t   TRUE, errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tattributePtr = findAttributeField( issuerAttributes, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t{\n\t\t\tstatus = checkNameConstraints( subjectCertInfoPtr, attributePtr, \n\t\t\t\t\t\t\t\t\t\t   FALSE, errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkNameConstraints\" );\n\n\t/* If there's a policy constraint present and the skip count is set to \n\t   zero (i.e. the constraint applies to the current certificate) check \n\t   the issuer constraints against the subject */\n\tstatus = getAttributeFieldValue( issuerAttributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,\n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) && value <= 0 )\n\t\t{\n\t\tPOLICY_TYPE policyType = POLICY_SUBJECT;\n\n\t\t/* Check whether use of the the wildcard anyPolicy has been \n\t\t   disallowed */\n\t\tattributePtr = findAttribute( issuerCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_INHIBITANYPOLICY, \n\t\t\t\t\t\t\t\t\t  TRUE );\n\t\tif( DATAPTR_ISSET( attributePtr ) && \\\n\t\t\tcryptStatusOK( getAttributeDataValue( attributePtr, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  &value ) ) && \\\n\t\t\tvalue <= 0 )\n\t\t\tpolicyType = POLICY_SUBJECT_SPECIFIC;\n\n\t\t/* Apply the appropriate policy constraint */\n\t\tstatus = checkPolicyConstraints( subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t issuerAttributes, policyType,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, FALSE, errorLocus, \n\t\t\t\t\t\t\t\t\t\t errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkPolicyConstraints\" );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\tif( subjectCertInfoPtr->cCertCert->maxCheckLevel < complianceLevel )\n\t\tsubjectCertInfoPtr->cCertCert->maxCheckLevel = complianceLevel;\n\n#if defined( USE_CERTLEVEL_PKIX_FULL )\n\tREQUIRES( CFI_CHECK_SEQUENCE_17( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t \"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t \"version\", \"compareDN\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t \"checkKeyUsage\", \"checkKeyUsageIssuer\",\n\t\t\t\t\t\t\t\t\t \"checkAttributeProperty\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\",\n\t\t\t\t\t\t\t\t\t \"invalidAttributesPresent\", \n\t\t\t\t\t\t\t\t\t \"checkPathConstraints\", \"anyKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_PKIX_FULL\", \n\t\t\t\t\t\t\t\t\t \"checkNameConstraints\", \n\t\t\t\t\t\t\t\t\t \"checkPolicyConstraints\" ) );\n#elif defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\tREQUIRES( CFI_CHECK_SEQUENCE_14( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t \"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t \"version\", \"compareDN\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t \"checkKeyUsage\", \"checkKeyUsageIssuer\",\n\t\t\t\t\t\t\t\t\t \"checkAttributeProperty\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\",\n\t\t\t\t\t\t\t\t\t \"invalidAttributesPresent\", \n\t\t\t\t\t\t\t\t\t \"checkPathConstraints\", \"anyKeyUsage\" ) );\n#else\n\tREQUIRES( CFI_CHECK_SEQUENCE_10( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t \"checkCertBasic\", \"checkKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t \"version\", \"compareDN\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t \"checkKeyUsage\", \"checkKeyUsageIssuer\",\n\t\t\t\t\t\t\t\t\t \"checkAttributeProperty\" ) );\n#endif /* CFI checks based on PKIX compliance levels */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/chk_chn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Certificate Chain Checking Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n#else\n  #include \"cert/cert.h\"\n#endif /* Compiler-specific includes */\n\n/* This module and chk_cert.c implement the following PKIX checks.  For\n   simplicity we use the more compact form of RFC 2459 rather than the 18\n   page long one from RFC 3280.\n\n\tGeneral:\n\n\t(a) Verify the basic certificate information:\n\t\t(1) The certificate signature is valid.\n\t\t(2a) The certificate has not expired.\n\t\t(2b) If present, the private key usage period is satisfied.\n\t\t(3) The certificate has not been revoked.\n\t\t(4a) The subject and issuer name chains correctly.\n\t\t(4b) If present, the subjectAltName and issuerAltName chains\n\t\t\t correctly.\n\n\tNameConstraints:\n\n\t(b) Verify that the subject name or critical subjectAltName is consistent\n\t\twith the constrained subtrees.\n\n\t(c) Verify that the subject name or critical subjectAltName is consistent\n\t\twith the excluded subtrees.\n\n\tPolicy Constraints:\n\n\t(d) Verify that policy information is consistent with the initial policy \n\t\tset:\n\t\t(1) If the require explicit policy state variable is less than or \n\t\t\tequal to n, a policy identifier in the certificate must be in \n\t\t\tthe initial policy set.\n\t\t(2) If the policy mapping state variable is less than or equal to n, \n\t\t\tthe policy identifier may not be mapped.\n\t\t(3) RFC 3280 addition: If the inhibitAnyPolicy state variable is \n\t\t\tless than or equal to n, the anyPolicy policy is no longer \n\t\t\tconsidered a match (this also extends into (e) and (g) below).\n\n\t(e) Verify that policy information is consistent with the acceptable policy \n\t\tset:\n\t\t(1) If the policies extension is marked critical, the policies\n\t\t\textension must lie within the acceptable policy set.\n\t\t(2) The acceptable policy set is assigned the resulting intersection\n\t\t\tas its new value.\n\n\t(g) Verify that the intersection of the acceptable policy set and the\n\t\tinitial policy set is non-null (this is covered by chaining of e(1)).\n\n\tOther Constraints:\n\n\t(f) Step (f) is missing in the original, it should probably be: Verify \n\t\tthat the current path length is less than the path length constraint.  \n\t\tIf a path length constraint is present in the certificate, update it \n\t\tas for policy constraints in (l).  RFC 3280 addition: If the \n\t\tcertificate is a PKIX path kludge certificate it doesn't count for \n\t\tpath length constraint purposes.\n\n\t(h) Recognize and process any other critical extension present in the\n\t\tcertificate.\n\n\t(i) Verify that the certificate is a CA certificate.\n\n\tUpdate of state:\n\n\t(j) If permittedSubtrees is present in the certificate, set the\n\t\tconstrained subtrees state variable to the intersection of its\n\t\tprevious value and the value indicated in the extension field.\n\n\t(k) If excludedSubtrees is present in the certificate, set the excluded\n\t\tsubtrees state variable to the union of its previous value and the\n\t\tvalue indicated in the extension field.\n\n\t(l) If a policy constraints extension is included in the certificate,\n\t\tmodify the explicit policy and policy mapping state variables as\n\t\tfollows:\n\n\t\tFor any of { requireExplicitPolicy, inhibitPolicyMapping, \n\t\tinhibitAnyPolicy }, if the constraint value is present and has value \n\t\tr, the state variable is set to the minimum of (a) its current value \n\t\tand (b) the sum of r and n (the current certificate in the \n\t\tsequence) \n\n\t(m) If a key usage extension is marked critical, ensure that the \n\t\tkeyCertSign bit is set */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get certificate information for a certificate in the chain.  The index \n   value can go to -1, indicating the leaf certificate itself rather than a\n   certificate in the chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getCertInfo( const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tOUT_PTR_COND CERT_INFO **certChainPtr, \n\t\t\t\t\t\tIN_RANGE( -1, MAX_CHAINLENGTH - 1 ) const int certChainIndex )\n\t{\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certChainPtr, sizeof( CERT_INFO * ) ) );\n\n\tREQUIRES( certChainIndex >= -1 && \\\n\t\t\t  certChainIndex < certChainInfo->chainEnd && \\\n\t\t\t  certChainIndex < MAX_CHAINLENGTH );\n\n\t/* Clear return value */\n\t*certChainPtr = NULL;\n\n\t/* If it's an index into the certificate chain, return information for \n\t   the certificate at that position */\n\tif( certChainIndex >= 0 && certChainIndex < certChainInfo->chainEnd )\n\t\t{\n\t\tCERT_INFO *certChainInfoPtr;\n\t\tint status;\n\n\t\tstatus = krnlAcquireObject( certChainInfo->chain[ certChainIndex ], \n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainInfoPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tREQUIRES_OBJECT( sanityCheckCert( certChainInfoPtr ),\n\t\t\t\t\t\t certChainInfoPtr->objectHandle );\n\t\t*certChainPtr = certChainInfoPtr;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The -1th certificate is the leaf itself */\n\tif( certChainIndex == -1 )\n\t\t{\n\t\t*certChainPtr = ( CERT_INFO * ) certInfoPtr;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've reached the end of the chain */\n\t*certChainPtr = NULL;\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* When checking a particular certificate in a chain via a message sent to \n   the encompassing object we have to explicitly select the certificate that\n   we want to operate on, otherwise all messages will act on the currently-\n   selected certificate in the chain.  To do this we temporarily select the\n   target certificate in the chain and then restore the selection state when\n   we're done */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performAbsTrustOperation( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t\t\t IN_ENUM( MESSAGE_TRUSTMGMT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst MESSAGE_TRUSTMGMT_TYPE operation,\n\t\t\t\t\t\t\t\t\t IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int certChainIndex,\n\t\t\t\t\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iIssuerCert )\n\t{\n\tCRYPT_CERTIFICATE iLocalCert;\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tSELECTION_STATE savedState;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( iIssuerCert == NULL || \\\n\t\t\tisWritePtr( iIssuerCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( certChainIndex >= -1 && \\\n\t\t\t  certChainIndex < certChainInfo->chainEnd && \\\n\t\t\t  certChainIndex < MAX_CHAINLENGTH );\n\n\t/* Clear return value */\n\tif( iIssuerCert != NULL )\n\t\t*iIssuerCert = CRYPT_ERROR;\n\n\t/* Perform the required operation at an absolute chain position */\n\tsaveSelectionState( savedState, certInfoPtr );\n\tcertChainInfo->chainPos = certChainIndex;\n\tif( certChainIndex == -1 )\n\t\t{\n\t\t/* The -1th certificate is the leaf itself */\n\t\tiLocalCert = certInfoPtr->objectHandle;\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an index into the certificate chain, use the certificate at \n\t\t   that position */\n\t\tiLocalCert = certChainInfo->chain[ certChainIndex ];\n\t\t}\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT, &iLocalCert, \n\t\t\t\t\t\t\t  operation );\n\trestoreSelectionState( savedState, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( iIssuerCert != NULL )\n\t\t*iIssuerCert = iLocalCert;\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the trust anchor in a certificate chain.  The definition of a \n   \"trusted certificate\" is somewhat ambiguous and can have at least two \n   different interpretations:\n\n\t1. Trust the identified certificate in the chain and only verify from \n\t   there on down.\n\n\t2. Trust the root of the chain that contains the identified certificate \n\t   (for the purposes of verifying that particular chain only) and verify \n\t   the whole chain.\n\n   Situation 1 is useful where there's a requirement that things go up to an\n   external CA somewhere but no-one particularly cares about (or trusts) the\n   external CA.  In this case the end user can choose to trust the path at \n   the point where it comes under their control (a local CA or directly \n   trusting the leaf certificates) without having to bother about the \n   external CA.\n\n   Situation 2 is useful where there's a requirement to use the full PKI \n   model.  This can be enabled by having the user mark the root CA as\n   trusted, although this means that all certificates issued by that CA also \n   have to be trusted, removing user control over certificate use.  This is \n   required by orthodox PKI theology, followed by all manner of hacks and\n   kludges down the chain to limit what can actually be done with the \n   certificate(s).\n\n   Est autem fides credere quod nondum vides; cuius fidei merces est videre \n   quod credis (St. Augustine) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int findTrustAnchor( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\tOUT_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\tint *trustAnchorIndexPtr, \n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *trustAnchorCert )\n\t{\n\tCRYPT_CERTIFICATE iIssuerCert DUMMY_INIT;\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tint trustAnchorIndex, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( trustAnchorIndexPtr, sizeof( int ) ) );\n\tassert( isWritePtr( trustAnchorCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\t/* Clear return value */\n\t*trustAnchorIndexPtr = CRYPT_ERROR;\n\t*trustAnchorCert = CRYPT_ERROR;\n\n\t/* If the leaf certificate is implicitly trusted, exit.  Since this is a\n\t   certificate chain we have to explicitly perform the operation at an\n\t   absolute position in the chain rather than the currently-selected \n\t   certificate, specifically the leaf at position -1 */\n\tstatus = performAbsTrustOperation( certInfoPtr, MESSAGE_TRUSTMGMT_CHECK,\n\t\t\t\t\t\t\t\t\t   -1, NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Indicate that the leaf is trusted and there's nothing further to \n\t\t   do */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* Walk up the chain looking for the trusted certificate that issued the\n\t   current one.  The evaluated trust anchor certificate position is one \n\t   past the current position since we're looking for the issuer of the \n\t   current certificate at position n, which will be located at position \n\t   n+1:\n\t   \n\t\ttrustAnchorIndex\tCert queried\ttrustAnchorCert\n\t\t----------------\t------------\t---------------\n\t\t\t\t0\t\t\t  cert #-1\t\t issuer( #-1 )\n\t\t\t\t1\t\t\t  cert #0\t\t issuer( #0 )\n\t\t\t\t2\t\t\t  cert #1\t\t issuer( #1 )\n\t   \n\t   This means that trustAnchorIndex may end up referencing a certificate \n\t   past the end of the chain if the trust anchor is present in the trust \n\t   database but not in the chain */\n\tREQUIRES( certChainInfo->chainEnd >= 0 );\n\tLOOP_EXT( trustAnchorIndex = 0,\n\t\t\t  trustAnchorIndex <= certChainInfo->chainEnd,\n\t\t\t  trustAnchorIndex++, MAX_CHAINLENGTH + 1 )\n\t\t{\n\t\tstatus = performAbsTrustOperation( certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   MESSAGE_TRUSTMGMT_GETISSUER, \n\t\t\t\t\t\t\t\t\t\t   trustAnchorIndex - 1, \n\t\t\t\t\t\t\t\t\t\t   &iIssuerCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) || \\\n\t\ttrustAnchorIndex > certChainInfo->chainEnd )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t*trustAnchorIndexPtr = trustAnchorIndex;\n\t*trustAnchorCert = iIssuerCert;\n\n\t/* If there are more certificates in the chain beyond the one that we \n\t   stopped at check to see whether the next certificate is the same as \n\t   the trust anchor.  If it is then we use the copy of the certificate \n\t   in the chain rather than the external one from the trust database */\n\tif( trustAnchorIndex < certChainInfo->chainEnd - 1 )\n\t\t{\n\t\tstatus = krnlSendMessage( certChainInfo->chain[ trustAnchorIndex ],\n\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &iIssuerCert, \n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_CERTOBJ );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*trustAnchorCert = certChainInfo->chain[ trustAnchorIndex ];\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Set error information for the certificate that caused problems when \n   looking for a trust anchor */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setTrustAnchorErrorInfo( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeType;\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tCERT_INFO *subjectCertInfoPtr;\n\tconst int lastCertIndex = certChainInfo->chainEnd - 1;\n\tBOOLEAN_INT selfSigned;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tENSURES( lastCertIndex >= 0 && lastCertIndex < certChainInfo->chainEnd );\n\n\t/* Select the certificate that caused the problem, which is the highest-\n\t   level certificate in the chain */\n\tcertChainInfo->chainPos = lastCertIndex;\n\n\t/* We couldn't find a trust anchor, either there's a missing link in the \n\t   chain (CRYPT_ERROR_STUART) and it was truncated before we got to a \n\t   trusted certificate or it goes to a root certificate but it isn't \n\t   trusted.  Returning error information on this is a bit complex since \n\t   we've selected the certificate that caused the problem, which means \n\t   that any attempt to read error status information will read it from \n\t   this certificate rather than the encapsulating chain object.  To get \n\t   around this we set the error information for the selected certificate \n\t   rather than the chain */\n\tstatus = krnlSendMessage( certChainInfo->chain[ lastCertIndex ], \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &selfSigned, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_SELFSIGNED );\n\tif( cryptStatusOK( status ) && selfSigned == TRUE )\n\t\t{\n\t\t/* We got a root certificate but it's not trusted */\n\t\tattributeType = CRYPT_CERTINFO_TRUSTED_IMPLICIT;\n\t\t}\n\telse\n\t\t{\n\t\t/* There's a missing link in the chain and it stops at this \n\t\t   certificate */\n\t\tattributeType = CRYPT_CERTINFO_CERTIFICATE;\n\t\t}\n\tstatus = getCertInfo( certInfoPtr, &subjectCertInfoPtr, \n\t\t\t\t\t\t  lastCertIndex );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetErrorInfo( subjectCertInfoPtr, attributeType, \n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\n\t\t/* If we're not at the leaf certificate then we have to unlock the \n\t\t   certificate that getCertInfo() provided us */\n\t\tif( certInfoPtr != subjectCertInfoPtr )\n\t\t\tkrnlReleaseObject( subjectCertInfoPtr->objectHandle );\n\t\t}\n\n\treturn( CRYPT_ERROR_INVALID );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPolicy Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\n/* Check whether a policy is already present in the policy set */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic BOOLEAN isPolicyPresent( IN const POLICY_DATA *policyData,\n\t\t\t\t\t\t\t\tIN_RANGE( 0, MAX_POLICIES ) const int policyCount,\n\t\t\t\t\t\t\t\tIN_BUFFER( policyValueLength ) const void *policyValue,\n\t\t\t\t\t\t\t\tIN_LENGTH_OID const int policyValueLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( policyData, sizeof( POLICY_DATA ) ) );\n\tassert( isReadPtrDynamic( policyValue, policyValueLength ) );\n\n\tREQUIRES_B( policyCount >= 0 && policyCount < MAX_POLICIES );\n\tREQUIRES_B( policyValueLength > 0 && policyValueLength < MAX_POLICY_SIZE );\n\n\t/* Check whether the given policy is already present in the set of \n\t   acceptable policies */\n\tLOOP_MED( i = 0, i < policyCount, i++ )\n\t\t{\n\t\tconst POLICY_DATA *policyDataPtr = &policyData[ i ];\n\n\t\tif( policyDataPtr->length == policyValueLength && \\\n\t\t\t!memcmp( policyDataPtr->data, policyValue, policyValueLength ) )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Add a policy to the policy set */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addPolicy( INOUT POLICY_DATA *policyData,\n\t\t\t\t\t  IN_RANGE( 0, MAX_POLICIES ) const int policyCount,\n\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE policyAttributePtr,\n\t\t\t\t\t  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\tconst int certChainIndex,\n\t\t\t\t\t  const BOOLEAN isMapped )\n\t{\n\tPOLICY_DATA *policyDataPtr;\n\tvoid *policyValuePtr;\n\tint policyValueLength, status;\n\n\tassert( isWritePtr( policyData, sizeof( POLICY_DATA ) ) );\n\n\tREQUIRES( policyCount >= 0 && policyCount < MAX_POLICIES );\n\tREQUIRES( DATAPTR_ISVALID( policyAttributePtr ) );\n\tREQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );\n\tREQUIRES( isMapped == TRUE || isMapped == FALSE );\n\n\t/* Get the policy value */\n\tstatus = getAttributeDataPtr( policyAttributePtr, &policyValuePtr,\n\t\t\t\t\t\t\t\t  &policyValueLength );\t\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that this policy isn't already present in the policy set.\n\t   Since policies are asserted all the way up and down a chain we're\n\t   going to find more copies in subsequent certificates so duplicates\n\t   aren't a problem */\n\tif( isPolicyPresent( policyData, policyCount, policyValuePtr, \n\t\t\t\t\t\t policyValueLength ) )\n\t\treturn( OK_SPECIAL );\n\n\t/* Copy the policy data to the next empty slot.  The policy level is \n\t   counted from 0 (the EE certificate) to n (the root certificate) so we \n\t   have to adjust the chain-position indicator by one since it denotes \n\t   the EE, the containing certificate, with the virtual position -1 and \n\t   the remainder of the certificates in the chain with positions 0...n */\n\tpolicyDataPtr = &policyData[ policyCount ];\n\tmemset( policyDataPtr, 0, sizeof( POLICY_DATA ) );\n\tpolicyDataPtr->level = certChainIndex + 1;\n\tpolicyDataPtr->isMapped = isMapped;\n\treturn( attributeCopyParams( policyDataPtr->data, MAX_POLICY_SIZE,\n\t\t\t\t\t\t\t\t &policyDataPtr->length, policyValuePtr, \n\t\t\t\t\t\t\t\t policyValueLength ) );\n\t}\n\n/* Add explicit policies to the policy set */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addExplicitPolicies( INOUT POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\t\tIN const DATAPTR_ATTRIBUTE attributes,\n\t\t\t\t\t\t\t\tIN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\t\tconst int certChainIndex )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tint policyCount = policyInfo->noPolicies, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attributes ) );\n\tREQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );\n\n\t/* Add all policies to the policy set */\n\tLOOP_LARGE( attributeCursor = \\\n\t\t\t\t\tfindAttributeField( attributes, CRYPT_CERTINFO_CERTPOLICYID, \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE ), \n\t\t\t\tDATAPTR_ISSET( attributeCursor ),\n\t\t\t\tattributeCursor = findNextFieldInstance( attributeCursor ) )\n\t\t{\n\t\tif( policyCount >= MAX_POLICIES )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tstatus = addPolicy( policyInfo->policies, policyCount,\n\t\t\t\t\t\t\tattributeCursor, certChainIndex, FALSE );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* This policy is already present, there's nothing further to \n\t\t\t   do */\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpolicyCount++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tpolicyInfo->noPolicies = policyCount;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add mapped policies to the policy set */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addMappedPolicies( INOUT POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE attributes,\n\t\t\t\t\t\t\t  IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\t\tconst int certChainIndex )\n\t{\n\tDATAPTR_ATTRIBUTE sourcePolicyAttributeCursor = \\\n\t\t\t\t\tfindAttributeField( attributes, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ISSUERDOMAINPOLICY,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\tDATAPTR_ATTRIBUTE destPolicyAttributeCursor = \\\n\t\t\t\t\tfindAttributeField( attributes, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTDOMAINPOLICY,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\tint policyCount = policyInfo->noPolicies;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );\n\n\tREQUIRES( certChainIndex >= -1 && certChainIndex < MAX_CHAINLENGTH );\n\tREQUIRES( DATAPTR_ISVALID( attributes ) );\n\tREQUIRES( DATAPTR_ISVALID( sourcePolicyAttributeCursor ) );\n\tREQUIRES( DATAPTR_ISVALID( destPolicyAttributeCursor ) );\n\n\t/* If there are no mapped policies, we're done */\n\tif( DATAPTR_ISNULL( sourcePolicyAttributeCursor ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Add all mapped policies to the policy set */\n\tLOOP_LARGE_CHECKINC( DATAPTR_ISSET( sourcePolicyAttributeCursor ),\n\t\t\t\t\t\t ( sourcePolicyAttributeCursor = \\\n\t\t\t\t\t\t\tfindNextFieldInstance( sourcePolicyAttributeCursor ), \\\n\t\t\t\t\t\t   destPolicyAttributeCursor = \\\n\t\t\t\t\t\t\tfindNextFieldInstance( destPolicyAttributeCursor ) ) )\n\t\t{\n\t\tvoid *policyValuePtr;\n\t\tint policyValueLength;\n\n\t\tREQUIRES( DATAPTR_ISSET( sourcePolicyAttributeCursor ) && \\\n\t\t\t\t  DATAPTR_ISSET( destPolicyAttributeCursor ) );\n\n\t\t/* Make sure that we're not trying to map from or to the special-case \n\t\t   anyPolicy policy */\n\t\tif( isAnyPolicy( sourcePolicyAttributeCursor ) || \\\n\t\t\tisAnyPolicy( destPolicyAttributeCursor ) )\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t/* Get the source policy and check whether it's present in the \n\t\t   policy set */\n\t\tstatus = getAttributeDataPtr( sourcePolicyAttributeCursor, &policyValuePtr,\n\t\t\t\t\t\t\t\t\t  &policyValueLength );\t\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\t\tif( !isPolicyPresent( policyInfo->policies, policyCount, \n\t\t\t\t\t\t\t  policyValuePtr, policyValueLength ) )\n\t\t\tcontinue;\n\n\t\t/* The source policy is present, add the corresponding destination\n\t\t   policy to the policy set */\n\t\tif( policyCount >= MAX_POLICIES )\n\t\t\treturn(  CRYPT_ERROR_OVERFLOW );\n\t\tstatus = addPolicy( policyInfo->policies, policyCount,\n\t\t\t\t\t\t\tdestPolicyAttributeCursor, certChainIndex, TRUE );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* This destination policy is already present, there's nothing \n\t\t\t   further to do.  This can happen if there's two different \n\t\t\t   source policies mapped to a single destination policy */\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpolicyCount++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tpolicyInfo->noPolicies = policyCount;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a certificate policy set from a certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int createPolicySet( OUT POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\tIN const DATAPTR_ATTRIBUTE trustAnchorAttributes,\n\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\tconst int startCertIndex )\n\t{\n\tBOOLEAN addImplicitPolicy = FALSE;\n\tint certIndex = startCertIndex, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( policyInfo, sizeof( POLICY_INFO ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( trustAnchorAttributes ) );\n\tREQUIRES( startCertIndex >= -1 && startCertIndex < MAX_CHAINLENGTH );\n\n\t/* Clear return value */\n\tmemset( policyInfo, 0, sizeof( POLICY_INFO ) );\n\n\t/* Add trust anchor explicit and mapped policies if required */\n\tif( DATAPTR_ISSET( trustAnchorAttributes ) && \\\n\t\tcheckAttributeFieldPresent( trustAnchorAttributes, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICYID ) )\n\t\t{\n\t\tstatus = addExplicitPolicies( policyInfo, trustAnchorAttributes, \n\t\t\t\t\t\t\t\t\t  certIndex );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = addMappedPolicies( policyInfo, trustAnchorAttributes,\n\t\t\t\t\t\t\t\t\tcertIndex );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* We've checked the trust anchor, move on to the next certificate */\n\tcertIndex--;\n\n\t/* If there are no policies in the trust anchor, pick up the policies in\n\t   the first certificate we get to that has any.  This is a bit of an\n\t   ugly hack that's required to deal with things like self-signed CA \n\t   roots in X.509v1 format where the CA policy doesn't appear until the\n\t   second certficiate in the chain */\n\tif( policyInfo->noPolicies <= 0 )\n\t\taddImplicitPolicy = TRUE;\n\n\t/* Add mapped policies from the remainder of the certificate chain.  \n\t   Note that we don't go all the way down to the EE certificate \n\t   (certIndex == -1) because any mapping at the end of the chain won't\n\t   be used any more */\n\tLOOP_EXT_CHECKINC( certIndex >= 0, certIndex--, MAX_CHAINLENGTH + 1 )\n\t\t{\n\t\tCERT_INFO *subjectCertInfoPtr;\n\n\t\t/* Get information for the current certificate in the chain */\n\t\tstatus = getCertInfo( certInfoPtr, &subjectCertInfoPtr, certIndex );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\tif( addImplicitPolicy && \\\n\t\t\tcheckAttributeFieldPresent( subjectCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICYID ) )\n\t\t\t{\n\t\t\tstatus = addExplicitPolicies( policyInfo, \n\t\t\t\t\t\t\t\t\t\t  subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t  certIndex );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( policyInfo->noPolicies > 0 )\n\t\t\t\taddImplicitPolicy = FALSE;\n\t\t\t}\n\n\t\t/* Add any mapped policies present in the current certificate */\n\t\tstatus = addMappedPolicies( policyInfo, \n\t\t\t\t\t\t\t\t\tsubjectCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\tcertIndex );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlReleaseObject( subjectCertInfoPtr->objectHandle );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Release the certificate again.  We don't have to check for it \n\t\t   being the chain certificate as we normally would because we never\n\t\t   process the certificate at the end of the chain */\n\t\tkrnlReleaseObject( subjectCertInfoPtr->objectHandle );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tVerify Constraints on a Certificate Chain\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\n/* Check constraints along a certificate chain in certInfoPtr from \n   startCertIndex on down, checked if complianceLevel >= \n   CRYPT_COMPLIANCELEVEL_PKIX_FULL.  There are three types of constraints \n   that can cover multiple certificates: path constraints, name constraints, \n   and policy constraints.\n\n   Path constraints are the easiest to check, just make sure that the number \n   of certificates from the issuer to the leaf is less than the constraint \n   length with special handling for PKIX path-kludge certificates.\n\n   Name constraints are a bit more difficult, the abstract description\n   requires building and maintaining a (potentially enormous) name \n   constraint tree which is applied to each certificate in turn as it's \n   processed.  Since name constraints are practically nonexistant and chains \n   are short it's more efficient to walk down the certificate chain when a \n   constraint is encountered and check each certificate in turn, which \n   avoids having to maintain massive amounts of state information and is no \n   less efficient than a single monolithic state comparison.  Again there's \n   special handling for PKIX path-kludge certificates, see chk_cert.c for \n   details.\n\n   Policy constraints are the hardest of all to deal with because, with the \n   complex mishmash of policies, policy constraints, qualifiers, and mappings \n   it turns out that no-one actually knows how to apply them and even if \n   people could agree, with the de facto use of the policy extension as the \n   kitchenSink extension it's uncertain how to apply the constraints to \n   typical kitchenSink constructs.  The ambiguity of name constraints when \n   applied to altNames is bad enough, with a 50/50 split in PKIX about \n   whether it should be an AND or OR operation and whether a DN constraint \n   applies to a subjectName or altName or both.  In the absence of any \n   consensus on the issue the latter was fixed in the final version of RFC \n   2459 by somewhat arbitrarily requiring an AND rather than an OR although \n   how many implementations follow exactly this version rather than the \n   dozen earlier drafts or any other profile or interpretation is unknown.  \n   With policy constraints it's even worse and no-one seems to be able to \n   agree on what to do with them, or more specifically the people who write \n   the standards don't seem to be aware that there are ambiguities and \n   inconsistencies in the handling of these extensions.  Anyone who doesn't \n   believe this is invited to try implementing the path-processing algorithm \n   in RFC 3280 as described by the pseudocode there.\n   \n   For example the various policy constraints in effect act as conditional \n   modifiers on the critical flag of the policies extension and/or the \n   various blah-policy-set settings in the path-processing algorithm so \n   that under various conditions imposed by the constraints the extension \n   goes from being non-critical to being (effectively) critical.  In addition \n   the constraint extensions can have their own critical flags which means \n   that we can end up having to chain back through multiple layers of \n   interacting constraint extensions spread across multiple certificates to \n   see what the current interpretation of a particular extension is.  \n   Finally, the presence of PKIX path-kludge certificates can turn \n   enforcement of constraints on and off at various stages of path \n   processing with extra special cases containing exceptions to the \n   exceptions.  In addition the path-kludge exceptions apply to some \n   constraint types but not to others although the main body of the spec \n   and the pseudocode path-processing algorithm disagree on which ones and \n   when they're in effect (this implementation assumes that the body of the \n   spec is authoritative and the pseudocode represents a buggy attempt to \n   implement the spec rather than the other way round).  Since the \n   virtual-criticality can switch itself on and off across certificates \n   depending on where in the path they are, the handling of policy \n   constraints is reduced to complete chaos if we try and interpret them as \n   required by the spec - an independent evaluation of the spec that tried to \n   implement the logic using decision tables ended up with expressions of \n   more than a dozen variables (and that was at a pre-3280 stage before the\n   state space explosion that occurred after that point) which indicates \n   that the issue is more or less incomprehensible.  However since it's only \n   applied at the CRYPT_COMPLIANCELEVEL_PKIX_FULL compliance level it's \n   reasonably safe since users should be expecting all sorts of wierd \n   behaviour at this level anyway. \n\n   The requireExplicitPolicy constraint is particularly bizarre, it \n   specifies the number of additional certificates that can be present in \n   the path before the entire path needs to have policies present.  In other \n   words unlike all other length-based constraints (pathLenConstraint, \n   inhibitPolicyMapping, inhibitAnyPolicy) this works both forwards and\n   *backwards* up and down the path, making it the PKI equivalent of a COME\n   FROM in that at some random point down the path a constraint placed who\n   knows where can suddenly retroactively render the previously-valid path \n   invalid.  No-one seems to know why it runs backwards or what the purpose\n   of the retroactive triggering after n certificates is, for now we only check\n   forwards down the path in the manner of all the other length-based \n   constraints.\n\n   Massa make big magic, gunga din */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int checkConstraints( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\tconst int startCertIndex,\n\t\t\t\t\t\t\t IN const DATAPTR_ATTRIBUTE issuerAttributes,\n\t\t\t\t\t\t\t OUT_RANGE( -1, MAX_CHAINLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\tint *errorCertIndex, \n\t\t\t\t\t\t\t IN const POLICY_INFO *policyInfo,\n\t\t\t\t\t\t\t const BOOLEAN explicitPolicy )\n\t{\n\tDATAPTR_ATTRIBUTE nameConstraintPtr, policyConstraintPtr;\n\tDATAPTR_ATTRIBUTE inhibitPolicyPtr, attributePtr;\n\tBOOLEAN hasExcludedSubtrees = FALSE, hasPermittedSubtrees = FALSE;\n\tBOOLEAN hasPolicy = FALSE, hasPathLength = FALSE;\n\tBOOLEAN hasExplicitPolicy = FALSE, hasInhibitPolicyMap = FALSE;\n\tBOOLEAN hasInhibitAnyPolicy = FALSE;\n\tint requireExplicitPolicyLevel, inhibitPolicyMapLevel;\n\tint inhibitAnyPolicyLevel;\n\tint pathLength DUMMY_INIT, certIndex = startCertIndex;\n\tint value, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorCertIndex, sizeof( int ) ) );\n\tassert( isReadPtr( policyInfo, sizeof( POLICY_INFO ) ) );\n\n\tREQUIRES( startCertIndex >= -1 && startCertIndex < MAX_CHAINLENGTH );\n\tREQUIRES( DATAPTR_ISVALID( issuerAttributes ) );\n\tREQUIRES( explicitPolicy == TRUE || explicitPolicy == FALSE );\n\n\t/* Clear return value */\n\t*errorCertIndex = CRYPT_ERROR;\n\n\t/* Clear the various policies */\n\tDATAPTR_SET( nameConstraintPtr, NULL );\n\tDATAPTR_SET( policyConstraintPtr, NULL );\n\tDATAPTR_SET( inhibitPolicyPtr, NULL );\n\n\t/* Check for path constraints */\n\tstatus = getAttributeFieldValue( issuerAttributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_PATHLENCONSTRAINT, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tpathLength = value;\n\t\thasPathLength = TRUE;\n\t\t}\n\n\t/* Check for policy constraints */\n\tif( explicitPolicy && \\\n\t\tcheckAttributePresent( issuerAttributes, \n\t\t\t\t\t\t\t   CRYPT_CERTINFO_CERTIFICATEPOLICIES ) )\n\t\t{\n\t\t/* Policy chaining purely from the presence of a policy extension\n\t\t   is only enforced if the explicit-policy option is set */\n\t\thasPolicy = TRUE;\n\t\t}\n\tattributePtr = findAttribute( issuerAttributes, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_POLICYCONSTRAINTS, FALSE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\tpolicyConstraintPtr = attributePtr;\n\tattributePtr = findAttribute( issuerAttributes, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_INHIBITANYPOLICY, TRUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\tinhibitPolicyPtr = attributePtr;\n\n\t/* Check for name constraints */\n\tattributePtr = findAttribute( issuerAttributes, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_NAMECONSTRAINTS, FALSE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tnameConstraintPtr = attributePtr;\n\t\thasExcludedSubtrees = \\\n\t\t\tcheckAttributeFieldPresent( nameConstraintPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES );\n\t\thasPermittedSubtrees = \\\n\t\t\tcheckAttributeFieldPresent( nameConstraintPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PERMITTEDSUBTREES );\n\t\t}\n\n\t/* If there aren't any critical policies or constraints present (the \n\t   most common case), we're done */\n\tif( !hasPolicy && !hasPathLength && \\\n\t\tDATAPTR_ISNULL( policyConstraintPtr ) && \\\n\t\tDATAPTR_ISNULL( inhibitPolicyPtr ) && \\\n\t\tDATAPTR_ISNULL( nameConstraintPtr ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether there are requireExplicitPolicy, inhibitPolicyMapping, or \n\t   inhibitAnyPolicy attributes, which act as conditional modifiers on the\n\t   criticality and contents of the policies extension */\n\trequireExplicitPolicyLevel = inhibitPolicyMapLevel = \\\n\t\t\t\t\t\t\t\t\t\t\tinhibitAnyPolicyLevel = 0;\n\tstatus = getAttributeFieldValue( policyConstraintPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_REQUIREEXPLICITPOLICY, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\trequireExplicitPolicyLevel = value;\n\t\thasExplicitPolicy = TRUE;\n\t\t}\n\tstatus = getAttributeFieldValue( policyConstraintPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_INHIBITPOLICYMAPPING, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinhibitPolicyMapLevel = value;\n\t\thasInhibitPolicyMap = TRUE;\n\t\t}\n\tif( DATAPTR_ISSET( inhibitPolicyPtr ) )\n\t\t{\n\t\tstatus = getAttributeDataValue( inhibitPolicyPtr, \n\t\t\t\t\t\t\t\t\t\t&inhibitAnyPolicyLevel );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thasInhibitAnyPolicy = TRUE;\n\t\t}\n\tstatus = CRYPT_OK;\n\n\t/* Walk down the chain checking each certificate against the issuer */\n\tLOOP_EXT( certIndex = startCertIndex, \n\t\t\t  cryptStatusOK( status ) && certIndex >= -1,\n\t\t\t  certIndex--, MAX_CHAINLENGTH + 1 )\n\t\t{\n\t\tCERT_INFO *subjectCertInfoPtr;\n\t\tPOLICY_TYPE policyType;\n\t\tint policyLevel;\n\n\t\t/* Get information for the current certificate in the chain */\n\t\tstatus = getCertInfo( certInfoPtr, &subjectCertInfoPtr, certIndex );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* Check for the presence of further policy constraints.  The path \n\t\t   length value can only ever be decremented once set so if we find \n\t\t   a further value for the length constraint we set the overall \n\t\t   value to the smaller of the two */\n\t\tstatus = getAttributeFieldValue( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_REQUIREEXPLICITPOLICY, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &policyLevel );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( !hasExplicitPolicy || policyLevel < requireExplicitPolicyLevel )\n\t\t\t\trequireExplicitPolicyLevel = policyLevel;\n\t\t\thasExplicitPolicy = TRUE;\n\t\t\t}\n\t\tstatus = getAttributeFieldValue( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_INHIBITPOLICYMAPPING, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &policyLevel );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( !hasInhibitPolicyMap || policyLevel < inhibitPolicyMapLevel )\n\t\t\t\tinhibitPolicyMapLevel = policyLevel;\n\t\t\thasInhibitPolicyMap = TRUE;\n\t\t\t}\n\t\tstatus = getAttributeFieldValue( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_INHIBITANYPOLICY, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &policyLevel );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( !hasInhibitAnyPolicy || policyLevel < inhibitAnyPolicyLevel )\n\t\t\t\tinhibitAnyPolicyLevel = policyLevel;\n\t\t\thasInhibitAnyPolicy = TRUE;\n\t\t\t}\n\t\tstatus = CRYPT_OK;\n\n\t\t/* If any of the policy constraints have triggered then the policy \n\t\t   extension is now treated as critical even if it wasn't before */\n\t\tif( ( hasExplicitPolicy && requireExplicitPolicyLevel <= 0 ) || \\\n\t\t\t( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) )\n\t\t\thasPolicy = TRUE;\n\n\t\t/* Determine the necessary policy check type based on the various\n\t\t   policy constraints */\n\t\tpolicyType = POLICY_NONE;\n\t\tif( hasPolicy )\n\t\t\t{\n\t\t\tconst BOOLEAN inhibitAnyPolicy = \\\n\t\t\t\t( hasInhibitAnyPolicy && inhibitAnyPolicyLevel <= 0 ) ? \\\n\t\t\t\tTRUE : FALSE;\n\n\t\t\tif( hasExplicitPolicy )\n\t\t\t\t{\n\t\t\t\tif( requireExplicitPolicyLevel > 0 )\n\t\t\t\t\t{\n\t\t\t\t\tpolicyType = inhibitAnyPolicy ? \\\n\t\t\t\t\t\t\t\t POLICY_NONE_SPECIFIC : POLICY_NONE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\tif( requireExplicitPolicyLevel == 0 )\n\t\t\t\t\t{\n\t\t\t\t\tpolicyType = inhibitAnyPolicy ? \\\n\t\t\t\t\t\t\t\t POLICY_SUBJECT_SPECIFIC : POLICY_SUBJECT;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\tif( requireExplicitPolicyLevel < 0 )\n\t\t\t\t\t{\n\t\t\t\t\tpolicyType = inhibitAnyPolicy ? \\\n\t\t\t\t\t\t\t\t POLICY_BOTH_SPECIFIC : POLICY_BOTH;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tpolicyType = inhibitAnyPolicy ? \\\n\t\t\t\t\t\t\t POLICY_NONE_SPECIFIC : POLICY_NONE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Check that the current certificate in the chain obeys the \n\t\t   constraints set by the overall issuer, possibly modified by other \n\t\t   certificates in the chain */\n\t\tif( hasExcludedSubtrees )\n\t\t\t{\n\t\t\tstatus = checkNameConstraints( subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   nameConstraintPtr, TRUE,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorType );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && hasPermittedSubtrees )\n\t\t\t{\n\t\t\tstatus = checkNameConstraints( subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   nameConstraintPtr, FALSE,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorType );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && hasPolicy )\n\t\t\t{\n\t\t\t/* When we specify the certificate position we have to add one\n\t\t\t   to it because the policy level is counted from 0 (the EE \n\t\t\t   certificate) to n (the root certificate) while the chain-\n\t\t\t   position indicator statrs from the virtual position -1 for \n\t\t\t   the EE certificate that contains the chain */\n\t\t\tstatus = checkPolicyConstraints( subjectCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t issuerAttributes, policyType, \n\t\t\t\t\t\t\t\t\t\t\t policyInfo, certIndex + 1,\n\t\t\t\t\t\t\t\t\t\t\t ( hasInhibitPolicyMap && \\\n\t\t\t\t\t\t\t\t\t\t\t   inhibitPolicyMapLevel <= 0 ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t\tFALSE : TRUE,\n\t\t\t\t\t\t\t\t\t\t\t &subjectCertInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t\t &subjectCertInfoPtr->errorType );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && hasPathLength )\n\t\t\t{\n\t\t\tstatus = checkPathConstraints( subjectCertInfoPtr, pathLength, \n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorType );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Remember which certificate caused the problem */\n\t\t\t*errorCertIndex = certIndex;\n\t\t\t}\n\n\t\t/* If there are length constraints, decrement them for each \n\t\t   certificate.  At this point we run into another piece of PKIX \n\t\t   weirdness: If there's a path-kludge certificate present it's not \n\t\t   counted for path-length constraint purposes but the exception \n\t\t   only holds for path-length constraint purposes and not for \n\t\t   require/inhibit policy constraint purposes.  This is an error in \n\t\t   the spec, sections 4.2.1.12 (policy constraints) and 4.2.1.15 \n\t\t   (path constraints) don't permit path-kludge certificate \n\t\t   exceptions while section 6.1.4(h) does.  On the other hand given \n\t\t   the confusion in the pseudocode and the fact that it diverges \n\t\t   from the body of the spec in other places as well we treat it as \n\t\t   an error in the (non-authoritative) pseudocode rather than the \n\t\t   (authoritative) spec.\n\t\t    \n\t\t   Unfortunately there's no easy way to tell just from looking at a \n\t\t   certificate whether it's one of these kludge certificates or not \n\t\t   because it looks identical to a CA root certificate (even the \n\t\t   path-building code has to handle this speculatively, falling back \n\t\t   to alternatives if the initial attempt to construct a path fails).\n\n\t\t   However, for chain-internal kludge certificates the \n\t\t   chain-assembly code can determine whether it's a path-kludge by \n\t\t   the presence of further certificates higher up in the chain \n\t\t   (although it can't tell whether the chain ends in a path-kludge \n\t\t   or a true CA root certificate because they appear identical).  In \n\t\t   the case where the chain-assembly code has been able to identify \n\t\t   the certificate as a path-kludge we can skip it for path length \n\t\t   constraint purposes */\n\t\tif( hasPathLength && !TEST_FLAG( subjectCertInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CERT_FLAG_PATHKLUDGE ) )\n\t\t\tpathLength--;\n\t\tif( hasExplicitPolicy )\n\t\t\trequireExplicitPolicyLevel--;\n\t\tif( hasInhibitPolicyMap )\n\t\t\tinhibitPolicyMapLevel--;\n\t\tif( hasInhibitAnyPolicy )\n\t\t\tinhibitAnyPolicyLevel--;\n\n\t\t/* Release the certificate again unless it's the chain certificate \n\t\t   itself, which is returned by getCertInfo() as the last \n\t\t   certificate in the chain */\n\t\tif( certInfoPtr != subjectCertInfoPtr )\n\t\t\tkrnlReleaseObject( subjectCertInfoPtr->objectHandle );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tVerify a Certificate Chain\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Walk down a chain checking each certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertChain( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_CERTIFICATE iIssuerCert;\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\tCERT_INFO *issuerCertInfoPtr, *subjectCertInfoPtr;\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tPOLICY_INFO policyInfo;\n\tBOOLEAN explicitPolicy = TRUE;\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint certIndex, complianceLevel, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Determine how much checking we need to perform */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tif( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )\n\t\t{\n\t\tBOOLEAN_INT requirePolicy;\n\n\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &requirePolicy, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_REQUIREPOLICY );\n\t\tif( cryptStatusOK( status ) && !requirePolicy )\n\t\t\texplicitPolicy = FALSE;\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Try and find a trust anchor for the chain */\n\tstatus = findTrustAnchor( certInfoPtr, &certIndex, &iIssuerCert );\n\tif( status == OK_SPECIAL )\n\t\t{\n\t\t/* The leaf is implicitly trusted, there's nothing more to do */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( setTrustAnchorErrorInfo( certInfoPtr ) );\n\tCFI_CHECK_UPDATE( \"findTrustAnchor\" );\n\n\tstatus = krnlAcquireObject( iIssuerCert, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &issuerCertInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\tREQUIRES_OBJECT( sanityCheckCert( issuerCertInfoPtr ),\n\t\t\t\t\t issuerCertInfoPtr->objectHandle );\n\n\t/* Add policies (both native and mapped) from the trust anchor to the \n\t   policy set */\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tstatus = createPolicySet( &policyInfo, issuerCertInfoPtr->attributes,\n\t\t\t\t\t\t\t  certInfoPtr, certIndex );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\treturn( status );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Check the trust anchor.  Since this is the start of the chain there \n\t   aren't any constraints placed on it by higher-level certificates so \n\t   all that we need to check at this point is the certificate itself and \n\t   its signature if it's self-signed */\n\tif( certIndex >= certChainInfo->chainEnd )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE dummyLocus;\n\t\tCRYPT_ERRTYPE_TYPE dummyType;\n\n\t\t/* The issuer certificate information is coming from the certificate \n\t\t   trust database, don't modify its state when we check it */\n\t\tstatus = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\tissuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,\n\t\t\t\t\t\tNULL, TRUE, TRUE, FALSE, &dummyLocus, &dummyType );\n\n\t\t}\n\telse\n\t\t{\n\t\t/* The issuer certificate is contained in the chain, update its state \n\t\t   when we check it */\n\t\tstatus = checkCertDetails( issuerCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\tissuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,\n\t\t\t\t\t\tNULL, TRUE, TRUE, FALSE, &issuerCertInfoPtr->errorLocus, \n\t\t\t\t\t\t&issuerCertInfoPtr->errorType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\tif( certIndex < certChainInfo->chainEnd )\n\t\t\t{\n\t\t\t/* Remember which certificate caused the problem */\n\t\t\tcertChainInfo->chainPos = certIndex;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkRootCertDetails\" );\n\n\t/* We've checked the trust anchor, move on to the next certificate */\n\tcertIndex--;\n\n\t/* Walk down the chain from the trusted certificate checking each link \n\t   in turn */\n\tLOOP_EXT_CHECKINC( cryptStatusOK( status ) && certIndex >= -1 && \\\n\t\t\t\t\t\t( status = \\\n\t\t\t\t\t\t\tgetCertInfo( certInfoPtr, &subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t certIndex ) ) == CRYPT_OK,\n\t\t\t\t\t   certIndex--, MAX_CHAINLENGTH + 1 )\n\t\t{\n\t\t/* Check the certificate details and signature */\n\t\tstatus = checkCertDetails( subjectCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t( issuerCertInfoPtr->iPubkeyContext != CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\tissuerCertInfoPtr->iPubkeyContext : CRYPT_UNUSED,\n\t\t\t\t\t\tNULL, FALSE, TRUE, FALSE, \n\t\t\t\t\t\t&subjectCertInfoPtr->errorLocus, \n\t\t\t\t\t\t&subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( cryptArgError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If there's a problem with the issuer's public key we'll \n\t\t\t\t   get a parameter error, the most appropriate standard \n\t\t\t\t   error code that we can translate this to is a standard \n\t\t\t\t   signature error */\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t/* Check any constraints that the issuer certificate may place on \n\t\t   the rest of the chain */\n\t\tif( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_FULL )\n\t\t\t{\n\t\t\tint errorCertIndex DUMMY_INIT;\t/* Needed for gcc */\n\n\t\t\tstatus = checkConstraints( certInfoPtr, certIndex, \n\t\t\t\t\t\t\t\t\t   issuerCertInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t   &errorCertIndex, &policyInfo, \n\t\t\t\t\t\t\t\t\t   explicitPolicy );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tcertIndex = errorCertIndex;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t\t/* Move on to the next certificate */\n\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\tissuerCertInfoPtr = subjectCertInfoPtr;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"checkCertDetails\" );\n\n\t/* If we stopped before we processed all of the certificates in the \n\t   chain, select the one that caused the problem.  We also have to \n\t   unlock the last certificate that we got to if it wasn't the leaf, \n\t   which corresponds to the chain itself */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcertChainInfo->chainPos = certIndex ;\n\t\tif( issuerCertInfoPtr != certInfoPtr )\n\t\t\tkrnlReleaseObject( issuerCertInfoPtr->objectHandle );\n\t\treturn( status );\n\t\t}\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"findTrustAnchor\", \n\t\t\t\t\t\t\t\t\t\"checkRootCertDetails\", \n\t\t\t\t\t\t\t\t\t\"checkCertDetails\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/chk_san.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Sanity-check Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"cert.h\"\n#else\n  #include \"cert/cert.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_CERTIFICATES )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check serial number storage */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkSerialNumber( IN_OPT const void *serialNumber,\n\t\t\t\t\t\t\t\t  IN_OPT const void *serialNumberBuffer,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int serialNumberSize )\n\t{\n\tENSURES_B( isShortIntegerRange( serialNumberSize ) );\n\n\t/* If there's no serial number present, we're done */\n\tif( serialNumber == NULL )\n\t\treturn( ( serialNumberSize == 0 ) ? TRUE : FALSE );\n\n\t/* The serial number has to have a nonzero length */\n\tif( serialNumberSize <= 0 )\n\t\treturn( FALSE );\n\n\t/* If the serial number fits into the internal buffer then it has to be \n\t   stored there */\n\tif( serialNumberSize <= SERIALNO_BUFSIZE )\n\t\treturn( ( serialNumber == serialNumberBuffer ) ? TRUE : FALSE );\n\n\t/* It's an over-long serial number, it's held in dynamically-allocated \n\t   storage, not the internal buffer */\n\tif( serialNumber == serialNumberBuffer || \\\n\t\tserialNumberSize > MAX_SERIALNO_SIZE )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/* Check data pointers within objects */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkDataPointers( IN_OPT const void *certificatePtr,\n\t\t\t\t\t\t\t\t  IN_LENGTH_Z const int certificateSize,\n\t\t\t\t\t\t\t\t  IN_OPT const void *dataPtr,\n\t\t\t\t\t\t\t\t  IN_OPT const void *dataStoragePtr,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataSize,\n\t\t\t\t\t\t\t\t  IN const DATAPTR dataObject )\n\t{\n\tassert( ( certificatePtr == NULL && certificateSize == 0 ) || \\\n\t\t\tisReadPtr( certificatePtr, certificateSize ) );\n\tassert( ( dataPtr == NULL ) || isReadPtr( dataPtr, dataSize ) );\n\t\t\t/* dataPtr may be NULL with dataSize non-zero if it's a DN stored\n\t\t\t   in the data object */\n\n\tREQUIRES_B( isIntegerRange( certificateSize ) );\n\tREQUIRES_B( isShortIntegerRange( dataSize ) );\n\n\t/* Checking for data pointers gets somewhat complicated, we can always \n\t   have the value present as an object reference (a pointer to a decoded \n\t   DN or a context handle) but alongside this we can also have a pointer \n\t   to encoded certificate data (dataPtr) or in separately-allocated \n\t   memory (dataStoragePtr).  The latter is only required when there's no \n\t   certificate data present, once this has been instantiated the dataPtr\n\t   points into the certificate data and the dataStoragePtr is freed:\n\n\t\tCertificate\t\tdataPtr\t\t\tdataStoragePtr\t\tObject ref.\n\t\t-----------\t\t-------\t\t\t--------------\t\t-----------\n\t\t  NULL\t\t\t  NULL\t\t\t\tNULL\t\t\t  ---\n\t\t Present\t\tInside cert.\t\tNULL\t\t\t  ---\n\t\t  NULL\t\t\t== dataStgePtr\t  Present\t\t\t  --- */\n\n\t/* If there's no certificate present then the information has to be \n\t   either stored in the dataStoragePtr or as an object reference */\n\tif( certificatePtr == NULL )\n\t\t{\n\t\t/* If there's no storage allocated for it, all values have to be \n\t\t   zero */\n\t\tif( dataStoragePtr == NULL )\n\t\t\t{\n\t\t\t/* If there's a non-zero data size present then it's due to the\n\t\t\t   encoding of a DN stored in the data object, so there must be\n\t\t\t   data present in the data object */\n\t\t\tif( dataSize > 0 )\n\t\t\t\t{\n\t\t\t\tif( !DATAPTR_ISSET( dataObject ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* This is a redundant check, the precondition was that\n\t\t\t\t   dataSize >= 0, so if it's not > 0 as per the check above\n\t\t\t\t   then it must be zero, but we leave the check in to make\n\t\t\t\t   this explicit */\n\t\t\t\tENSURES_B( dataSize == 0 );\n\t\t\t\t}\n\t\t\tif( dataPtr != NULL )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t\n\t\t/* There's storage allocated, it has to match the dataPtr */\n\t\tif( dataPtr != dataStoragePtr || \\\n\t\t\t!isShortIntegerRangeNZ( dataSize ) )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* There's certificate data present, the data pointer has to be \n\t   contained within it */\n\tif( !pointerBoundsCheck( certificatePtr, certificateSize,\n\t\t\t\t\t\t\t dataPtr, dataSize ) )\n\t\treturn( FALSE );\n\tif( dataStoragePtr != NULL )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCheck Certifcate Subtype Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckCertificate( const CERT_INFO *certInfoPtr )\n\t{\n\tconst CERT_CERT_INFO *certInfo = certInfoPtr->cCertCert;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( certInfo, sizeof( CERT_CERT_INFO ) ) );\n\n\t/* Check certificate data */\n\tif( !checkSerialNumber( certInfo->serialNumber, \n\t\t\t\t\t\t\tcertInfo->serialNumberBuffer,\n\t\t\t\t\t\t\tcertInfo->serialNumberLength ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Serial number\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfo->maxCheckLevel < CRYPT_COMPLIANCELEVEL_OBLIVIOUS || \\\n\t\tcertInfo->maxCheckLevel >= CRYPT_COMPLIANCELEVEL_LAST )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Compliance level\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfo->chainEnd != 0 || certInfo->chainPos != CRYPT_ERROR )\n\t\t{\n\t\t/* It's a certificate chain, check that the chain information is in \n\t\t   order.  A chainPos of -1 is valid for the leaf certificate, which \n\t\t   is past the end of the chain */\n\t\tif( certInfo->chainEnd < 0 || \\\n\t\t\tcertInfo->chainEnd >= MAX_CHAINLENGTH || \\\n\t\t\tcertInfo->chainPos < -1 || \\\n\t\t\tcertInfo->chainPos > certInfo->chainEnd )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Chain info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( certInfo->hashAlgo != CRYPT_ALGO_NONE && \\\n\t\t!isHashAlgo( certInfo->hashAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Hash algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n#ifdef USE_CERTREQ\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckCertReq( const CERT_INFO *certInfoPtr )\n\t{\n\tconst CERT_REQ_INFO *reqInfo = certInfoPtr->cCertReq;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( reqInfo, sizeof( CERT_REQ_INFO ) ) );\n\n\t/* Check request data */\n\tif( !checkSerialNumber( reqInfo->serialNumber, \n\t\t\t\t\t\t\treqInfo->serialNumberBuffer,\n\t\t\t\t\t\t\treqInfo->serialNumberLength ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Serial number\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( reqInfo->requestFromRA != TRUE && \\\n\t\treqInfo->requestFromRA != FALSE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: RA flag\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckCertRev( const CERT_INFO *certInfoPtr )\n\t{\n\tconst CERT_REV_INFO *revInfo = certInfoPtr->cCertRev;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( revInfo, sizeof( CERT_REV_INFO ) ) );\n\n\t/* Check revocation data */\n\tif( !( ( revInfo->responderUrl == NULL && \\\n\t\t\t revInfo->responderUrlSize == 0 ) || \\\n\t\t   ( revInfo->responderUrl != NULL && \\\n\t\t\t revInfo->responderUrlSize >= MIN_URL_SIZE && \\\n\t\t\t revInfo->responderUrlSize <= MAX_URL_SIZE ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation responder URL\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( revInfo->hashAlgo != CRYPT_ALGO_NONE && \\\n\t\t!isHashAlgo( revInfo->hashAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation hash algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( revInfo->signatureLevel, CRYPT_SIGNATURELEVEL ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation signature level\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !DATAPTR_ISVALID( revInfo->revocations ) || \\\n\t\t!DATAPTR_ISVALID( revInfo->currentRevocation ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( DATAPTR_ISSET( revInfo->revocations ) )\n\t\t{\n\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\trevInfoPtr = DATAPTR_GET( revInfo->revocations );\n\t\tENSURES_B( revInfoPtr != NULL );\n\t\tif( !sanityCheckRevInfo( revInfoPtr ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( DATAPTR_ISSET( revInfo->currentRevocation ) )\n\t\t{\n\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\trevInfoPtr = DATAPTR_GET( revInfo->currentRevocation );\n\t\tENSURES_B( revInfoPtr != NULL );\n\t\tif( !sanityCheckRevInfo( revInfoPtr ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Revocation current revocation\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckCertVal( const CERT_INFO *certInfoPtr )\n\t{\n\tconst CERT_VAL_INFO *valInfo = certInfoPtr->cCertVal;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( valInfo, sizeof( CERT_VAL_INFO ) ) );\n\n\t/* Check RTCS data */\n\tif( !( ( valInfo->responderUrl == NULL && \\\n\t\t\t valInfo->responderUrlSize == 0 ) || \\\n\t\t   ( valInfo->responderUrl != NULL && \\\n\t\t\t valInfo->responderUrlSize >= MIN_URL_SIZE && \\\n\t\t\t valInfo->responderUrlSize <= MAX_URL_SIZE ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Validity responder URL\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( valInfo->responseType, RTCSRESPONSE_TYPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Validity response type\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !DATAPTR_ISVALID( valInfo->validityInfo ) || \\\n\t\t!DATAPTR_ISVALID( valInfo->currentValidity ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Validity safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( DATAPTR_ISSET( valInfo->validityInfo ) )\n\t\t{\n\t\tconst VALIDITY_INFO *valInfoPtr;\n\n\t\tvalInfoPtr = DATAPTR_GET( valInfo->validityInfo );\n\t\tENSURES_B( valInfoPtr != NULL );\n\t\tif( !sanityCheckValInfo( valInfoPtr ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Validity info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( DATAPTR_ISSET( valInfo->currentValidity ) )\n\t\t{\n\t\tconst VALIDITY_INFO *valInfoPtr;\n\n\t\tvalInfoPtr = DATAPTR_GET( valInfo->currentValidity );\n\t\tENSURES_B( valInfoPtr != NULL );\n\t\tif( !sanityCheckValInfo( valInfoPtr ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Validity current validity\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_PKIUSER\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckCertPKIUser( const CERT_INFO *certInfoPtr )\n\t{\n\tconst CERT_PKIUSER_INFO *pkiUserInfo = certInfoPtr->cCertUser;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( pkiUserInfo, sizeof( CERT_PKIUSER_INFO ) ) );\n\n\t/* Check PKI user data.  The only thing that we can really check is a \n\t   single boolean */\n\tif( pkiUserInfo->isRA != TRUE && pkiUserInfo->isRA != FALSE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: pkiUser RA flag\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* USE_PKIUSER */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Certifcate Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check a certificate */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckCert( IN const CERT_INFO *certInfoPtr )\n\t{\n\tBOOLEAN subjectNameSpecialCheck = FALSE;\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tBOOLEAN nullDN = FALSE;\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Check general certificate data */\n\tif( !isEnumRange( certInfoPtr->type, CRYPT_CERTTYPE ) || \\\n\t\t!CHECK_FLAGS( certInfoPtr->flags, CERT_FLAG_NONE, \n\t\t\t\t\t  CERT_FLAG_MAX ) || \\\n\t\tcertInfoPtr->version < 0 || \\\n\t\tcertInfoPtr->version > 3 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfoPtr->certificate == NULL )\n\t\t{\n\t\tif( certInfoPtr->certificateSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Empty certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* We allow a minimum size of 48 rather than MIN_CRYPT_OBJECTSIZE \n\t\t   since RTCS requests/responses are very compact */\n\t\tif( certInfoPtr->certificateSize < 48 || \\\n\t\t\tcertInfoPtr->certificateSize >= MAX_INTLENGTH )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( certInfoPtr->subjectName ) || \\\n\t\t!DATAPTR_ISVALID( certInfoPtr->issuerName ) || \\\n\t\t!DATAPTR_ISVALID( certInfoPtr->attributes ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check key data */\n\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR && \\\n\t\t!isHandleRangeValid( certInfoPtr->iPubkeyContext ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Public key\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfoPtr->publicKeyAlgo != CRYPT_ALGO_NONE && \\\n\t\t!isPkcAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Public key algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfoPtr->publicKeyInfo == NULL )\n\t\t{\n\t\tif( certInfoPtr->publicKeyInfoSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Spurious public key info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( certInfoPtr->publicKeyInfoSize <= MIN_PKCSIZE_ECC || \\\n\t\t\tcertInfoPtr->publicKeyInfoSize >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Public key info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check DNs */\n\tif( certInfoPtr->subjectDNsize == 0 )\n\t\t{\n\t\tif( certInfoPtr->subjectDNptr != NULL || \\\n\t\t\tcertInfoPtr->subjectDNdata != NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Empty subject DN\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t/* Full PKIX allows null DNs (!!), so we have to handle the\n\t\t   situation where there's no DN given, with the size of a zero-\n\t\t   length SEQUENCE.\n\t\t   \n\t\t   There's an extra combination here in that once the certificate is \n\t\t   created, we save a pointer to its encoded form, so it appears \n\t\t   that there's a DN present even though it's a null DN.  To deal\n\t\t   with this we check for the special case of there being a pointer\n\t\t   to the encoded DN data that corresponds to a zero-length \n\t\t   SEQUENCE */\n\t\tif( DATAPTR_ISNULL( certInfoPtr->subjectName ) && \\\n\t\t\tcertInfoPtr->subjectDNptr == NULL )\n\t\t\t{\n\t\t\tif( certInfoPtr->subjectDNsize != 2 )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Null subject DN\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tnullDN = TRUE;\n\t\t\t}\n\t\tif( certInfoPtr->subjectDNsize < MIN_DN_SIZE || \\\n\t\t\tcertInfoPtr->subjectDNsize >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tif( !nullDN && DATAPTR_ISNULL( certInfoPtr->subjectName ) && \\\n\t\t\t\tcertInfoPtr->subjectDNptr != NULL && \\\n\t\t\t\t!memcmp( certInfoPtr->subjectDNptr, \"\\x30\\x00\", 2 ) )\n\t\t\t\tnullDN = TRUE;\n\t\t\tif( !nullDN )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Non-NULL DN\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n#else\n\t\tif( DATAPTR_ISNULL( certInfoPtr->subjectName ) && \\\n\t\t\tcertInfoPtr->subjectDNptr == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Absent subject DN\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( certInfoPtr->subjectDNsize < MIN_DN_SIZE || \\\n\t\t\tcertInfoPtr->subjectDNsize >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Subject DN size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t}\n\tif( certInfoPtr->issuerDNsize == 0 )\n\t\t{\n\t\tif( certInfoPtr->issuerDNptr != NULL || \\\n\t\t\tcertInfoPtr->issuerDNdata != NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Empty issuer DN\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( DATAPTR_ISNULL( certInfoPtr->issuerName ) && \\\n\t\t\tcertInfoPtr->issuerDNptr == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Absent issuer DN\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( certInfoPtr->issuerDNsize < MIN_DN_SIZE || \\\n\t\t\tcertInfoPtr->issuerDNsize >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Issuer DN size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that data pointers within the certificate are valid: If the \n\t   public key or subject or issuer DN data is dynamically allocated then \n\t   the encoded-value pointers have to point to the same memory location \n\t   as the dynamic pointers, and if encoded certificate data is present \n\t   then the encoded-value pointers have to point within it.\n\n\t   There are some special-case conditions in which these rules don't \n\t   apply, both caused by CRMF, or CRMF in combination with CMP.  For a\n\t   CRMF request we can have both certificate data and a distinct subject \n\t   DN present when we've received a CRMF request that doesn't have a DN \n\t   included and for which the DN has been supplied externally by the CA, \n\t   typically by copying it in from the PKI user info.  The arrangement\n\t   here is:\n\n\t\tCertificate\tsubjDNdata\tsubjDNptr\t\tissDNdata\tissDNptr\n\t\t-----------\t---------\t----------\t\t---------\t---------\n\t\tPresent\t\tPresent\t\t== subjDNdata\t---\t\t\t---\n\n\t   For CRMF revocation requests it gets even more awkward, in this case\n\t   we have a standalone subject DN that exists independently of the \n\t   request because it's needed for CMP use (see the long comment in \n\t   copyCertToRevRequest() in comp_cert.c).  The arrangement here is:\n\n\t\tCertificate\tsubjDNdata\tsubjDNptr\t\tissDNdata\tissDNptr\n\t\t-----------\t---------\t----------\t\t---------\t---------\n\t\tPresent\t\tPresent\t\t== subjDNdata\tNULL\t\t== certificate */\n\tif( ( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) && \\\n\t\tcertInfoPtr->certificate != NULL )\n\t\t{\n\t\t/* It's a CRMF request with certificate data present, if there's a \n\t\t   distinct subject DN present then don't perform sanity checks on\n\t\t   it since it doesn't work like standard subject DNs */\n\t\tif( certInfoPtr->subjectDNdata != NULL && \\\n\t\t\tcertInfoPtr->subjectDNptr == certInfoPtr->subjectDNdata )\n\t\t\tsubjectNameSpecialCheck = TRUE;\n\t\t}\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tif( !subjectNameSpecialCheck && !nullDN && \\\n\t\t!checkDataPointers( certInfoPtr->certificate, certInfoPtr->certificateSize,\n\t\t\t\t\t\t\tcertInfoPtr->subjectDNptr, certInfoPtr->subjectDNdata,\n\t\t\t\t\t\t\tcertInfoPtr->subjectDNsize, certInfoPtr->subjectName ) )\n#else\n\tif( !subjectNameSpecialCheck && \\\n\t\t!checkDataPointers( certInfoPtr->certificate, certInfoPtr->certificateSize,\n\t\t\t\t\t\t\tcertInfoPtr->subjectDNptr, certInfoPtr->subjectDNdata,\n\t\t\t\t\t\t\tcertInfoPtr->subjectDNsize, certInfoPtr->subjectName ) )\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Subject DN data pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !checkDataPointers( certInfoPtr->certificate, certInfoPtr->certificateSize,\n\t\t\t\t\t\t\tcertInfoPtr->issuerDNptr, certInfoPtr->issuerDNdata,\n\t\t\t\t\t\t\tcertInfoPtr->issuerDNsize, certInfoPtr->issuerName ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Issuer DN data pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !checkDataPointers( certInfoPtr->certificate, certInfoPtr->certificateSize,\n\t\t\t\t\t\t\tcertInfoPtr->publicKeyInfo, certInfoPtr->publicKeyData,\n\t\t\t\t\t\t\tcertInfoPtr->publicKeyInfoSize, DATAPTR_NULL ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Public key data pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( certInfoPtr->certificate != NULL && !subjectNameSpecialCheck )\n\t\t{\n\t\tif( 16 + certInfoPtr->subjectDNsize + certInfoPtr->issuerDNsize + \\\n\t\t\t\t certInfoPtr->publicKeyInfoSize > certInfoPtr->certificateSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Certificate component size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check associated handles */\n\tif( !isHandleRangeValid( certInfoPtr->objectHandle ) || \\\n\t\t!( certInfoPtr->ownerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t   isHandleRangeValid( certInfoPtr->ownerHandle ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check subtype-specific data */\n\tswitch( certInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n#ifdef USE_ATTRCERT\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n#endif /* USE_ATTRCERT */\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\tcase CRYPT_ICERTTYPE_CMS_CERTSET:\n\t\tcase CRYPT_ICERTTYPE_SSL_CERTCHAIN:\n\t\t\tif( !sanityCheckCertificate( certInfoPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\tif( !sanityCheckCertReq( certInfoPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\tcase CRYPT_ICERTTYPE_REVINFO:\n\t\t\tif( !sanityCheckCertRev( certInfoPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\tif( !sanityCheckCertVal( certInfoPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n#endif /* USE_CERTVAL */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\tif( !sanityCheckCertPKIUser( certInfoPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n#endif /* USE_PKIUSER */\n\n#if defined( USE_CERTREQ ) || defined( USE_CMSATTR )\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\tcase CRYPT_CERTTYPE_CMS_ATTRIBUTES:\n\t\t\tif( certInfoPtr->cCertCert != NULL )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckCert: Spurious certificate info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n#endif /* USE_CERTREQ || USE_CMSATTR */\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\t/* The SELECTION_INFO and SELECTION_STATE are only used in \n\t   cert/comp_curs.c and are checked there */\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/chk_use.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Usage Checking Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n#else\n  #include \"cert/cert.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tExtKeyUsage to Key Usage Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following keyUsage settings are used based on extendedKeyUsage and\n   Netscape key usage extensions.  In the following 'Y' = required, 'w' =\n   written but apparently not required, 'S' = for signature keys only, 'E' = \n   for encryption keys only, 'KA' = for key agreement keys only.\n\n\t\t\t\t\t\tdig\tnon\tkey\tdat\tkey\tcer\tcrl\tenc\tdec\n\t\t\t\t\t\tsig\trep\tenc\tenc\tagt\tsig\tsig\tonl\tonl\n   PKIX:\t\t\t\t-----------------------------------\n\tserverAuth\t\t\t S\t\t E\t\tKA\t\t\t\t\t[1]\n\tclientAuth\t\t\t S\n\tcodeSign\t\t\t Y\n\temail\t\t\t\t Y\t Y\t E\n\tipsecEndSys\t\t\t S\t\t E\t\tKA\n\tipsecTunnel\t\t\t S\t\t E\t\tKA\n\tipsecUser\t\t\t S\t\t E\t\tKA\n\ttimeStamping\t\t Y\t Y\n\tocsp\t\t\t\t Y\n\tdirectoryService\t ?\n   MS:\t\t\t\t\t-----------------------------------\n\tindividualCodeSign\t Y\n\tcommercialCodeSign\t Y\n\tctlSign\t\t\t\t Y\n\ttsa\t\t\t\t\t Y\n\tsgc\t\t\t\t\t\t\t E\n\tencryptedFS\t\t\t\t\t E\n   NS:\t\t\t\t\t-----------------------------------\n\tsgc\t\t\t\t\t\t\t E\n   NS extensions:\t\t-----------------------------------\n\tsslClient\t\t\t Y\n\tsslServer\t\t\t S\t\t E\t\t\t\t\t\t\t[1]\n\tsMime\t\t\t\t S\t\t E\n\tobjectSign\t\t\t Y\n\tsslCA                               \t Y\t w\n\tsMimeCA\t\t\t\t\t\t\t\t\t Y\t w\n\tobjectSignCA\t\t\t\t\t\t\t Y\t w\n   Verisign:\t\t\t-----------------------------------\n\tsgcCA\t\t\t\t\t\t\t\t\t Y\t w\n\t\t\t\t\t\t-----------------------------------\n\t\t\t\t\t\tdig\tnon\tkey\tdat\tkey\tcer\tcrl\tenc\tdec\n\t\t\t\t\t\tsig\trep\tenc\tenc\tagt\tsig\tsig\tonl\tonl\n\n   [1] These keys need to potentially perform both decryption for RSA key \n       transport and signing for authenticating DH key agreement */\n\n/* Mask for key usage types that we don't check for consistency against\n   extended key usages.  The two CA usages don't occur in extended key usage,\n   and no-one can agree on what non-repudiation is supposed to mean */\n\n#define USAGE_MASK_NONRELEVANT\t( CRYPT_KEYUSAGE_NONREPUDIATION | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_CRLSIGN )\n\n/* Flags to denote the algorithm type */\n\n#define ALGO_TYPE_NONE\t\t\t0\n#define ALGO_TYPE_SIGN\t\t\t1\n#define ALGO_TYPE_CRYPT\t\t\t2\n#define ALGO_TYPE_KEYAGREEMENT\t4\n#define ALGO_TYPE_FLAG_NONE\t\t0\t\t/* Defines for range checking */\n#define ALGO_TYPE_FLAG_MAX\t\t0x07\n\n/* Table mapping extended key usage values to key usage flags */\n\ntypedef struct {\n\tconst CRYPT_ATTRIBUTE_TYPE usageType;\n\tconst int keyUsageFlags;\n\t} EXT_USAGE_INFO;\n\t\nstatic const EXT_USAGE_INFO extendedUsageInfo[] = {\n\t{ CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,/* individualCodeSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,/* commercialCodeSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,/* certTrustListSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING,\t/* timeStampSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO,\t/* serverGatedCrypto */\n\t  CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM,\t/* encrypedFileSystem */\n\t  CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_CERTINFO_EXTKEY_SERVERAUTH,\t\t\t\t/* serverAuth */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_CLIENTAUTH,\t\t\t\t/* clientAuth */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_CODESIGNING,\t\t\t/* codeSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION,\t\t/* emailProtection */\n\t  KEYUSAGE_SIGN },\n\t{ CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM,\t\t\t/* ipsecEndSystem */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL,\t\t\t/* ipsecTunnel */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_IPSECUSER,\t\t\t\t/* ipsecUser */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_TIMESTAMPING,\t\t\t/* timeStamping */\n\t  KEYUSAGE_SIGN },\n\t{ CRYPT_CERTINFO_EXTKEY_OCSPSIGNING,\t\t\t/* ocspSigning */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE,\t\t/* directoryService */\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO,\t/* serverGatedCrypto */\n\t  CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,/* serverGatedCrypto CA */\n\t  KEYUSAGE_CA },\n\t{ CRYPT_ATTRIBUTE_NONE, 0 }, { CRYPT_ATTRIBUTE_NONE, 0 }\n\t};\n\n#ifdef USE_CERT_OBSOLETE\n\n/* Table mapping Netscape certificate-type flags to extended key usage \n   flags */\n\ntypedef struct {\n\tconst int certType;\n\tconst int keyUsageFlags;\n\t} NS_CERT_TYPE_INFO;\n\t\nstatic const NS_CERT_TYPE_INFO nsCertTypeInfo[] = {\n\t{ CRYPT_NS_CERTTYPE_SSLCLIENT,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_NS_CERTTYPE_SSLSERVER,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_NS_CERTTYPE_SMIME,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_NS_CERTTYPE_OBJECTSIGNING,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_NONREPUDIATION },\n\t{ CRYPT_NS_CERTTYPE_RESERVED, 0 },\n\t{ CRYPT_NS_CERTTYPE_SSLCA,\n\t  KEYUSAGE_CA },\n\t{ CRYPT_NS_CERTTYPE_SMIMECA,\n\t  KEYUSAGE_CA },\n\t{ CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA,\n\t  KEYUSAGE_CA },\n\t{ 0, 0 }, { 0, 0 }\n\t};\n#endif /* USE_CERT_OBSOLETE */\n\n/* Build up key usage flags consistent with the extended key usage purpose.  \n   We don't have to perform any special-case handling for \n   anyExtendedKeyUsage (added in RFC 3280, section 4.2.1.13) since it's a \n   no-op extension whose presence is the equivalent of adding \"|| TRUE\" to \n   an expression */\n\nCHECK_RETVAL_RANGE( CRYPT_KEYUSAGE_NONE, CRYPT_KEYUSAGE_FLAG_MAX ) STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getExtendedKeyUsageFlags( IN const DATAPTR_ATTRIBUTE attributes,\n\t\t\t\t\t\t\t\t\t IN_FLAGS( ALGO_TYPE ) const int algorithmType,\n\t\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus )\n\t{\n\tint keyUsage = CRYPT_KEYUSAGE_NONE, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( attributes ) );\n\tREQUIRES( isFlagRange( algorithmType, ALGO_TYPE ) );\n\n\t/* Clear return value */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\n\t/* Many certificates don't contain an extendedKeyUsage extension so \n\t   rather than iterating through a long list of non-present attribute \n\t   fields we perform an early-out check to see whether there's actually\n\t   anything to do */\n\tif( !checkAttributePresent( attributes, CRYPT_CERTINFO_EXTKEYUSAGE ) )\n\t\treturn( CRYPT_KEYUSAGE_NONE );\n\n\t/* There's an extendedKeyUsage extension present, build up the key usage\n\t   flags for it */\n\tLOOP_MED( i = 0, \n\t\t\t  extendedUsageInfo[ i ].usageType != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tint extendedUsage = CRYPT_KEYUSAGE_NONE;\n\n\t\t/* If this usage isn't present, continue */\n\t\tif( !checkAttributeFieldPresent( attributes, \n\t\t\t\t\t\t\t\t\t\t extendedUsageInfo[ i ].usageType ) )\n\t\t\tcontinue;\n\n\t\t/* If the usage is consistent with the algorithm type, add it */\n\t\tif( algorithmType & ALGO_TYPE_SIGN )\n\t\t\t{\n\t\t\textendedUsage |= \\\n\t\t\t\textendedUsageInfo[ i ].keyUsageFlags & ( KEYUSAGE_SIGN | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t KEYUSAGE_CA );\n\t\t\t}\n\t\tif( algorithmType & ALGO_TYPE_CRYPT )\n\t\t\t{\n\t\t\textendedUsage |= \\\n\t\t\t\textendedUsageInfo[ i ].keyUsageFlags & KEYUSAGE_CRYPT;\n\t\t\t}\n\t\tif( algorithmType & ALGO_TYPE_KEYAGREEMENT )\n\t\t\t{\n\t\t\textendedUsage |= \\\n\t\t\t\textendedUsageInfo[ i ].keyUsageFlags & KEYUSAGE_KEYAGREEMENT;\n\t\t\t}\n\n\t\t/* If there's no key usage consistent with the extended usage and the\n\t\t   extended usage isn't some special-case usage, return an error */\n\t\tif( extendedUsage == CRYPT_KEYUSAGE_NONE && \\\n\t\t\textendedUsageInfo[ i ].keyUsageFlags != CRYPT_KEYUSAGE_NONE )\n\t\t\t{\n\t\t\t*errorLocus = extendedUsageInfo[ i ].usageType;\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\tkeyUsage |= extendedUsage;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( extendedUsageInfo, EXT_USAGE_INFO ) );\n\n\treturn( keyUsage );\n\t}\n\n#ifdef USE_CERT_OBSOLETE\n\n/* Build up key usage flags consistent with the Netscape certificate-type \n   purpose */\n\nCHECK_RETVAL_RANGE( CRYPT_KEYUSAGE_NONE, CRYPT_KEYUSAGE_MAX ) STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int getNetscapeCertTypeFlags( IN const DATAPTR_ATTRIBUTE attributes,\n\t\t\t\t\t\t\t\t\t IN_FLAGS( ALGO_TYPE ) const int algorithmType,\n\t\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus )\n\t{\n\tint nsCertType, keyUsage = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributes, sizeof( ATTRIBUTE_PTR_STORAGE ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( attributes ) );\n\tREQUIRES( isFlagRange( algorithmType, ALGO_TYPE ) );\n\n\t/* If there isn't a Netscape certificate-type extension present, exit */\n\tstatus = getAttributeFieldValue( attributes, CRYPT_CERTINFO_NS_CERTTYPE, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &nsCertType );\n\tif( cryptStatusError( status ) )\n\t\treturn( 0 );\n\n\t/* The Netscape certificate-type value is a bitfield containing the \n\t   different certificate types.  For each certificate-type flag that's \n\t   set we set the corresponding keyUsage flags */\n\tLOOP_SMALL( i = 0,\n\t\t\t\tnsCertTypeInfo[ i ].certType && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( nsCertTypeInfo, \\\n\t\t\t\t\t\t\t\t\t\t\tNS_CERT_TYPE_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tint nsUsage = 0;\n\n\t\t/* If this isn't the currently-selected certificate type, continue */\n\t\tif( !( nsCertType & nsCertTypeInfo[ i ].certType ) )\n\t\t\tcontinue;\n\n\t\t/* If the usage is consistent with the algorithm type, add it */\n\t\tif( algorithmType & ALGO_TYPE_SIGN )\n\t\t\tnsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & ( KEYUSAGE_SIGN | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t KEYUSAGE_CA );\n\t\tif( algorithmType & ALGO_TYPE_CRYPT )\n\t\t\tnsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & KEYUSAGE_CRYPT;\n\t\tif( algorithmType & ALGO_TYPE_KEYAGREEMENT )\n\t\t\tnsUsage |= nsCertTypeInfo[ i ].keyUsageFlags & KEYUSAGE_KEYAGREEMENT;\n\n\t\t/* If there's no key usage consistent with the Netscape \n\t\t   certificate-type, return an error */\n\t\tif( nsUsage == 0 )\n\t\t\t{\n\t\t\t*errorLocus = CRYPT_CERTINFO_NS_CERTTYPE;\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\tkeyUsage |= nsUsage;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( nsCertTypeInfo, NS_CERT_TYPE_INFO ) );\n\n\treturn( keyUsage );\n\t}\n#endif /* USE_CERT_OBSOLETE */\n\n/* Get key usage flags for a certificate based on its extended key \n   usage/Netscape cert-type.  Returns 0 if no extKeyUsage/cert-type values \n   present */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint getKeyUsageFromExtKeyUsage( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( CRYPT_KEYUSAGE ) int *keyUsage,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus, \n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint algorithmType = ALGO_TYPE_NONE, localKeyUsage, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Clear return values */\n\t*keyUsage = CRYPT_KEYUSAGE_NONE;\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If there are no attributes present there's nothing to do */\n\tif( DATAPTR_ISNULL( certInfoPtr->attributes ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Determine the possible algorithm usage type(s) */\n\tif( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\talgorithmType |= ALGO_TYPE_CRYPT;\n\tif( isSigAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\talgorithmType |= ALGO_TYPE_SIGN;\n\tif( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\talgorithmType |= ALGO_TYPE_KEYAGREEMENT;\n\tENSURES( algorithmType != ALGO_TYPE_NONE );\n\n\t/* Get the key usage flags for the given extended/Netscape usage type(s)\n\t   and algorithm type */\n\tstatus = localKeyUsage = \\\n\t\tgetExtendedKeyUsageFlags( certInfoPtr->attributes, algorithmType, \n\t\t\t\t\t\t\t\t  errorLocus );\n#ifdef USE_CERT_OBSOLETE\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = getNetscapeCertTypeFlags( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t\t   algorithmType, errorLocus );\n\t\tif( !cryptStatusError( status ) )\n\t\t\tlocalKeyUsage |= status;\n\t\t}\n#endif /* USE_CERT_OBSOLETE */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We only have to set the error type at this point since the error\n\t\t   locus was set when we got the key usage flags */\n\t\t*errorType = CRYPT_ERRTYPE_CONSTRAINT;\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\t*keyUsage = localKeyUsage;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Key/Certificate Usage\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that a certificate/key is valid for a particular purpose.  This \n   function is used in one of two ways:\n\n\t1. Check that a key can be used for a particular purpose, regardless of\n\t   whether the certificate extensions that define the usage make any \n\t   sense or not.  This is used when performing an object usage check \n\t   such as whether a key can be used for signing or encryption.\n\n\t2. Check that the key usage is consistent.  This is used when performing\n\t   a general certificate validity check, indicated by setting the \n\t   CHECKKEY_FLAG_GENCHECK  check flag.\n\n   Processing is done in three phases:\n   \n\t1. Fix up usage flags at lower compliance levels if necessary.\n\t2. Check for strict usability even if the flags don't make sense.\n\t3. Check consistency as per the PKIX and X.509 specs */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5, 6 ) ) \\\nint checkKeyUsage( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t   IN_FLAGS_Z( CHECKKEY ) const int flags, \n\t\t\t\t   IN_FLAGS_Z( CRYPT_KEYUSAGE ) const int specificUsage,\n\t\t\t\t   IN_RANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \\\n\t\t\t\t\t\t\t CRYPT_COMPLIANCELEVEL_LAST - 1 ) \\\n\t\t\t\t\t\tconst int complianceLevel,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tconst BOOLEAN isGeneralCheck = ( flags & CHECKKEY_FLAG_GENCHECK ) ? \\\n\t\t\t\t\t\t\t\t   TRUE : FALSE;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tBOOLEAN keyUsageCritical = FALSE;\n\tint rawExtKeyUsage;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\tBOOLEAN isCA = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint trustedUsage = CRYPT_UNUSED, keyUsage, rawKeyUsage;\n\tint extKeyUsage, caKeyUsage, value, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isFlagRangeZ( flags, CHECKKEY ) );\n\tREQUIRES( isFlagRangeZ( specificUsage, CRYPT_KEYUSAGE ) );\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\tREQUIRES( ( ( flags & CHECKKEY_FLAG_CA ) && \\\n\t\t\t\t( specificUsage & ( CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_CRLSIGN ) ) ) || \\\n\t\t\t  ( !( flags & CHECKKEY_FLAG_CA ) && \\\n\t\t\t\t( ( specificUsage & ( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_KEYENCIPHERMENT | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_KEYAGREEMENT ) ) || \\\n\t\t\t\t  ( specificUsage == CRYPT_KEYUSAGE_NONE ) ) ) );\n\n\t/* There is one universal case in which a key is regarded as invalid for\n\t   the requested use and that's when it's explicitly not trusted for the \n\t   purpose.  Note that this check (in oblivious mode) differs slightly\n\t   from the later check (in reduced mode or higher) in that in oblivious\n\t   mode we ignore the certificate's actual key usage and check only the \n\t   requested against trusted usage */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\ttrustedUsage = certInfoPtr->cCertCert->trustedUsage;\n\t\tif( specificUsage != CRYPT_KEYUSAGE_NONE && \\\n\t\t\t!( trustedUsage & specificUsage ) )\n\t\t\t{\n\t\t\t/* The issuer is explicitly not trusted to perform the requested \n\t\t\t   operation */\n\t\t\tsetErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE,\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"trustedUsage\" );\n\n\t/* If we're running in oblivious mode there's nothing else to check */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_REDUCED )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"trustedUsage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_REDUCED\" );\n\n\t/* Phase 1: Fix up values if required */\n\n\t/* Obtain assorted certificate information */\n\tstatus = getAttributeFieldValue( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) && value > 0 )\n\t\tisCA = TRUE;\n\tstatus = getKeyUsageFromExtKeyUsage( certInfoPtr, &extKeyUsage, \n\t\t\t\t\t\t\t\t\t\t errorLocus, errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a v1 self-signed certificate then the CA status and key usage \n\t   are implicit/undefined */\n\tif( certInfoPtr->version == X509_V1 && \\\n\t\tTEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\t/* If it's claiming to be a CA certificate by virtue of being a v1 \n\t\t   self-signed certificate then there can't be any v3 CA attributes \n\t\t   (or any v3 attributes for that matter) present.  Unfortunately we \n\t\t   can't just check for the complete non-presence of attributes \n\t\t   because the certificate-import code will have converted an email \n\t\t   address in the DN into the appropriate altName component, \n\t\t   creating at least one valid (in this case) attribute */\n\t\tif( isGeneralCheck && \\\n\t\t\t( checkAttributePresent( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_BASICCONSTRAINTS ) || \\\n\t\t\t  checkAttributePresent( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE ) || \\\n\t\t\t  extKeyUsage != 0 ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_VERSION, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* It's a v1 self-signed certificate with no keyUsage present, don't\n\t\t   perform any usage-specific checks */\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"selfSigned\" );\n\n\t/* Get the certificate's keyUsage.  If we're running at a reduced \n\t   compliance level and the CA flag is set and keyUsage isn't or vice \n\t   versa we synthesise the required value from the other value in order \n\t   to pass the checks that follow */\n\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\t/* Check whether the keyUsage extension is critical, needed for \n\t\t   some odd PKIX-defined checks at higher compliance levels */\n\t\tstatus = getAttributeDataValue( attributePtr, &keyUsage );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t\tkeyUsageCritical = \\\n\t\t\tcheckAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_CRITICAL );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t\t/* If the CA key usages are set make sure that the CA flag is set in\n\t\t   an appropriate manner */\n\t\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD && \\\n\t\t\t( keyUsage & specificUsage & KEYUSAGE_CA ) && !isCA )\n\t\t\tisCA = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\t/* There's no keyUsage information present, start with no usage\n\t\t   available */\n\t\tkeyUsage = 0;\n\n\t\t/* If the CA flag is set make sure that the keyUsage is set in an\n\t\t   appropriate manner */\n\t\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && isCA )\n\t\t\tkeyUsage = KEYUSAGE_CA;\n\n\t\t/* Some broken certificates don't have any keyUsage present, which \n\t\t   is meant to imply that the certificate can be used for any usage \n\t\t   that the key is capable of modulo the magic usages keyCertSign \n\t\t   and crlSign.  To handle this we map the algorithm type to the \n\t\t   matching usage types.  In theory the usage may be further \n\t\t   modified by the certificate policy, extKeyUsage, and who knows \n\t\t   what else but in the presence of a certificate like that it's up \n\t\t   to the user to sort out what they want to do with it.\n\t\t\n\t\t   Some even more broken certificates indicate their usage via a \n\t\t   Netscape key usage (even though they use X.509 flags everywhere \n\t\t   else - insanes numquam moriuntur) which means that we fail them \n\t\t   if we're strictly applying the PKIX requirements at a higher \n\t\t   compliance level.  At this lower level fixAttributes() will have \n\t\t   mapped the Netscape usage to the equivalent X.509 usage so \n\t\t   there's always a keyUsage present */\n\t\tif( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\tif( isSigAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\tkeyUsage |= KEYUSAGE_SIGN;\n\t\tif( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;\n\t\t}\n\tcaKeyUsage = keyUsage & KEYUSAGE_CA;\n\tCFI_CHECK_UPDATE( \"keyUsage\" );\n\n\t/* Apply the trusted-usage restrictions if necessary */\n\trawKeyUsage = keyUsage;\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\trawExtKeyUsage = extKeyUsage;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\tif( trustedUsage != CRYPT_UNUSED )\n\t\t{\n\t\tkeyUsage &= trustedUsage;\n\t\textKeyUsage &= trustedUsage;\n\t\t}\n\n\t/* Phase 2: Strict usability check */\n\n\t/* If we're looking for a CA certificate make sure that the \n\t   basicConstraints CA flag is set and the keyUsage indicates a CA usage \n\t   (PKIX sections 4.2.1.3 and 4.2.1.10).  RFC 2459 left this open, it \n\t   was made explicit in RFC 3280.  If we're running at a reduced \n\t   compliance level then the settings will have been adjusted as \n\t   required earlier on */\n\tif( flags & CHECKKEY_FLAG_CA )\n\t\t{\n\t\tif( !isCA )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tif( !( caKeyUsage & specificUsage ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"caKeyUsage\" );\n\n\t/* There is one universal case in which a key is regarded as invalid for\n\t   the requested use and that's when it's explicitly not trusted for the \n\t   purpose */\n\tif( specificUsage != CRYPT_KEYUSAGE_NONE && \\\n\t\ttrustedUsage != CRYPT_UNUSED && !( specificUsage & keyUsage ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_TRUSTED_USAGE,\n\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"trustedUsage\" );\n\n\t/* If we're doing a reduced level of checking, we're done */\n\tif( complianceLevel < CRYPT_COMPLIANCELEVEL_STANDARD )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t\"selfSigned\", \"keyUsage\", \"caKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t\"trustedUsage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CRYPT_COMPLIANCELEVEL_STANDARD\" );\n\n\t/* If we're just performing a key-usability check rather than a general\n\t   check that the key usage is in order, we're done */\n\tif( !isGeneralCheck )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_7( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t\"selfSigned\", \"keyUsage\", \"caKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t\"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_STANDARD\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Phase 3: Consistency check */\n\n\t/* If the CA flag is set make sure that there's a keyUsage with one of \n\t   the CA usages present.  Conversely if there are CA key usages \n\t   present make sure that the CA flag is set.  In other words this\n\t   check tests for an XOR relation, ( CA && kU ) || ( !CA && !kU ).\n\t   \n\t   The CA flag is actually a leftover from an early v3 certificate \n\t   concept and is made entirely redundant by the keyUsage flags but we \n\t   have to check it regardless (PKIX sections 4.2.1.3 and 4.2.1.10).  \n\t   RFC 2459 left this open, it was made explicit in RFC 3280 */\n\tif( isCA )\n\t\t{\n\t\t/* It's a CA certificate, make sure that a CA keyUsage is set */\n\t\tif( !( caKeyUsage | extKeyUsage ) )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\t\n\telse\n\t\t{\n\t\t/* It's a non-CA certificate, make sure that no CA keyUsage is set */\n\t\tif( ( caKeyUsage | extKeyUsage ) & KEYUSAGE_CA )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_CA, CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"caKeyUsage\" );\n\n\t/* Check and enforce the keyUsage if required (PKIX section 4.2.1.3).  \n\t   RFC 2459 included some waffly text about critical vs. non-critical \n\t   usage, RFC 3280 made this explicit regardless of criticality */\n\tif( specificUsage != CRYPT_KEYUSAGE_NONE )\n\t\t{\n\t\tBOOLEAN usageOK = FALSE;\n\n\t\t/* If it's a key agreement usage the checking gets a bit complex\n\t\t   (PKIX-ALGS section 2.3.3), we have to make sure that it's both a \n\t\t   permitted usage and not an excluded usage */\n\t\tif( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL && \\\n\t\t\t( specificUsage & ( CRYPT_KEYUSAGE_ENCIPHERONLY | \\\n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_DECIPHERONLY ) ) )\n\t\t\t{\n\t\t\tconst int excludedUsage = \\\n\t\t\t\t\t( specificUsage & CRYPT_KEYUSAGE_ENCIPHERONLY ) ? \\\n\t\t\t\t\tCRYPT_KEYUSAGE_DECIPHERONLY : CRYPT_KEYUSAGE_ENCIPHERONLY;\n\n\t\t\tif( ( keyUsage & specificUsage ) && !( keyUsage & excludedUsage ) )\n\t\t\t\tusageOK = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Conventional usage flag, do a straight check */\n\t\t\tif( keyUsage & specificUsage )\n\t\t\t\tusageOK = TRUE;\n\t\t\t}\n\t\tif( !usageOK )\n\t\t\t{\n\t\t\tsetErrorValues( ( rawKeyUsage & specificUsage ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_USAGE : \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"usageOK\" );\n\n\t/* Switch back to the original usage values (before adjustment by \n\t   trusted-usage values) because after this point we're performing \n\t   consistency checks on the values and need to check all of the bits */\n\tkeyUsage = rawKeyUsage;\n\n\t/* Make sure that mutually exclusive flags aren't set (RFC 3279 section \n\t   2.3.3) */\n\tif( ( keyUsage & CRYPT_KEYUSAGE_ENCIPHERONLY ) && \\\n\t\t( keyUsage & CRYPT_KEYUSAGE_DECIPHERONLY ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* Make sure that the keyUsage flags represent capabilities that the \n\t   algorithm is actually capable of.  RFC 2459 included some waffly text\n\t   about critical vs. non-critical usage, RFC 3280 made this explicit\n\t   regardless of criticality, although the details were actually moved\n\t   into RFC 3279, which specifies the algorithms used in PKIX */\n\tif( ( ( ( keyUsage & KEYUSAGE_CRYPT ) && \\\n\t\t\t  !isCryptAlgo( certInfoPtr->publicKeyAlgo ) ) || \\\n\t\t  ( ( keyUsage & ( KEYUSAGE_SIGN | KEYUSAGE_CA ) ) && \\\n\t\t\t  !isSigAlgo( certInfoPtr->publicKeyAlgo ) ) || \\\n\t\t  ( ( keyUsage & KEYUSAGE_KEYAGREEMENT ) && \\\n\t\t\t  !isKeyxAlgo( certInfoPtr->publicKeyAlgo ) ) ) ) \n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"validUsage\" );\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* Switch back to the original usage values as above.  This is done here\n\t   because we only use extKeyUsage at a heightened level of compliance\n\t   checking */\n\textKeyUsage = rawExtKeyUsage;\n\n\t/* Mask out any non-relevant usages (e.g. certificate signing, which \n\t   doesn't occur in extended key usages and has already been checked \n\t   above) */\n\tkeyUsage &= ~USAGE_MASK_NONRELEVANT;\n\textKeyUsage &= ~USAGE_MASK_NONRELEVANT;\n\n\t/* If we're being asked to check for private-key constraints, check and \n\t   enforce the privateKeyUsage attribute if there's one present */\n\tif( ( flags & CHECKKEY_FLAG_PRIVATEKEY ) && \\\n\t\tcheckAttributePresent( certInfoPtr->attributes,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD ) )\n\t\t{\n\t\tconst time_t currentTime = getTime();\n\t\ttime_t certTime;\n\n\t\tif( currentTime <= MIN_TIME_VALUE )\n\t\t\t{\n\t\t\t/* Time is broken, we can't reliably check for expiry times */\n\t\t\tsetErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE, \n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tstatus = getAttributeFieldTime( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, &certTime );\n\t\tif( cryptStatusOK( status ) && currentTime < certTime )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE,\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tstatus = getAttributeFieldTime( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PRIVATEKEY_NOTAFTER, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, &certTime );\n\t\tif( cryptStatusOK( status ) && currentTime > certTime )\n\t\t\t{\n\t\t\tsetErrorValues( CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER,\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"privateKeyUsage\" );\n\n\t/* If there's no key usage based on extended key usage present or we're \n\t   not doing at least partial PKIX checking, there's nothing further to \n\t   check */\n\tif( !extKeyUsage || complianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )\n\t\t{\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_11( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t\t \"selfSigned\", \"keyUsage\", \"caKeyUsage\", \n\t\t\t\t\t\t\t\t\t\t \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t\t \"caKeyUsage\", \"usageOK\", \"validUsage\", \n\t\t\t\t\t\t\t\t\t\t \"privateKeyUsage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the CA key usages are set then an encryption key usage shouldn't \n\t   be set (RFC 3279 section 2.3.1) */\n\tif( isCA && ( keyUsage & extKeyUsage & KEYUSAGE_CRYPT ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If the usage and extended usage are critical (but only if both are \n\t   critical, because PKIX says so) make sure that the given usage is \n\t   consistent with the required usage (PKIX section 4.2.1.13).  To \n\t   perform this check we first check for situations where we *don't* \n\t   have to perform the check and only if none of these occur do we \n\t   perform the actual check.\n\t   \n\t   Checking whether the extended usage is critical is a bit nontrivial, \n\t   we have to check each possible extended usage since only one of them \n\t   may be present so we check the criticality of the basic key usage \n\t   first to allow quick short-circuit evaluation.\n\t   \n\t   In addition to the explicit criticality checks we also perform an\n\t   implicit check based on whether this is a freshly-generated, as-yet-\n\t   unsigned cryptlib certificate.  This is done for two reasons, firstly \n\t   because an unsigned certificate won't have had the criticality flag \n\t   set by the signing/encoding process so the extension always appears \n\t   non-critical and secondly because we don't want cryptlib to generate \n\t   inconsistent certificates, whether the extensions are marked critical \n\t   or not (cryptlib always makes the keyUsage critical so at least for \n\t   key usage it's no change from the standard behaviour) */\n\tif( certInfoPtr->certificate != NULL )\n\t\t{\n\t\tint attributeID, LOOP_ITERATOR;\n\n\t\t/* If there's no critical key usage present we can exit without\n\t\t   performing further checks */\n\t\tif( !keyUsageCritical )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If we find an extended key usage and it's non-critical (which \n\t\t   means that all extended usages are non-critical since they're\n\t\t   all in the same extension), return */\n\t\tLOOP_MED( attributeID = CRYPT_CERTINFO_EXTKEYUSAGE + 1, \n\t\t\t\t  attributeID <= CRYPT_CERTINFO_EXTKEYUSAGE_LAST,\n\t\t\t\t  attributeID++ )\n\t\t\t{\n\t\t\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\tattributeID, CRYPT_ATTRIBUTE_NONE );\n\t\t\tif( DATAPTR_ISSET( attributePtr ) && \\\n\t\t\t\t!checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_CRITICAL ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkAttributeProperty\" );\n\n\t/* Make sure that the extended key usage-based key usage is consistent \n\t   with the actual key usage */\n\tif( ( keyUsage & extKeyUsage ) != extKeyUsage )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If the encipherOnly or decipherOnly bits are set then the \n\t   keyAgreement bit most also be set (PKIX section 4.2.1.3).  Actually \n\t   the spec merely says \"undefined\" but we interpret this to mean that \n\t   they should be consistent.  This situation occurs because the \n\t   encipher/decipher-only usages were tacked on as modifiers long after \n\t   keyAgreement was defined and make it entirely redundant, in the same \n\t   way that the CA keyUsages make the basicConstraints CA flag \n\t   redundant */\n\tif( ( keyUsage & ( CRYPT_KEYUSAGE_ENCIPHERONLY | \\\n\t\t\t\t\t   CRYPT_KEYUSAGE_DECIPHERONLY ) ) && \\\n\t\t!( keyUsage & CRYPT_KEYUSAGE_KEYAGREEMENT ) )\n\t\t{\n\t\tsetErrorValues( CRYPT_CERTINFO_KEYUSAGE, CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tCFI_CHECK_UPDATE( \"extUsageChecks\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_13( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t \"selfSigned\", \"keyUsage\", \"caKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t \"caKeyUsage\", \"usageOK\", \"validUsage\", \n\t\t\t\t\t\t\t\t\t \"privateKeyUsage\", \"checkAttributeProperty\",\n\t\t\t\t\t\t\t\t\t \"extUsageChecks\" ) );\n#else\n\tREQUIRES( CFI_CHECK_SEQUENCE_10( \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_REDUCED\", \n\t\t\t\t\t\t\t\t\t \"selfSigned\", \"keyUsage\", \"caKeyUsage\", \n\t\t\t\t\t\t\t\t\t \"trustedUsage\", \n\t\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD\", \n\t\t\t\t\t\t\t\t\t \"caKeyUsage\", \"usageOK\", \"validUsage\" ) );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_cert.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSet Certificate Components\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/* Determine whether anyone ever uses the higher compliance levels */\n\n#if defined( USE_CERTLEVEL_PKIX_FULL ) && \\\n\t!( defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) )\n  #error If you see this message, please let the cryptlib developers know, \\\n\t\t then remove the error directive that caused it and recompile as normal.\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTREQ ) || defined( USE_CERTREV )\n\n/* Copy the encoded issuer DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyIssuerDnData( INOUT CERT_INFO *destCertInfoPtr,\n\t\t\t\t\t\t\t const CERT_INFO *srcCertInfoPtr )\n\t{\n\tvoid *dnDataPtr;\n\n\tassert( isWritePtr( destCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( srcCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( destCertInfoPtr->issuerDNptr == NULL );\n\tREQUIRES( srcCertInfoPtr->issuerDNptr != NULL );\n\n\tREQUIRES( rangeCheck( srcCertInfoPtr->issuerDNsize, \n\t\t\t\t\t\t  1, MAX_INTLENGTH_SHORT ) );\n\tif( ( dnDataPtr = clAlloc( \"copyIssuerDnData\",\n\t\t\t\t\t\t\t   srcCertInfoPtr->issuerDNsize ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemcpy( dnDataPtr, srcCertInfoPtr->issuerDNptr,\n\t\t\tsrcCertInfoPtr->issuerDNsize );\n\tdestCertInfoPtr->issuerDNptr = destCertInfoPtr->issuerDNdata = dnDataPtr;\n\tdestCertInfoPtr->issuerDNsize = srcCertInfoPtr->issuerDNsize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy revocation information into a CRL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyRevocationInfo( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t   const CERT_INFO *revInfoPtr )\n\t{\n\tREVOCATION_INFO *revocationInfoPtr;\n\tconst void *serialNumberPtr;\n\tint serialNumberLength, status = CRYPT_OK;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( revInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( revInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t  revInfoPtr->issuerDNsize ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CRL );\n\tREQUIRES( revInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  revInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  revInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tREQUIRES( revInfoPtr->issuerDNptr != NULL );\n\n\t/* If there's an issuer name recorded, make sure that it matches the one \n\t   in the certificate that's being added */\n\tif( certInfoPtr->issuerDNptr != NULL )\n\t\t{\n\t\tif( certInfoPtr->issuerDNsize != revInfoPtr->issuerDNsize || \\\n\t\t\tmemcmp( certInfoPtr->issuerDNptr, revInfoPtr->issuerDNptr,\n\t\t\t\t\tcertInfoPtr->issuerDNsize ) )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There's no issuer name present yet, set the CRL issuer name to \n\t\t   the certificate's issuer.  This is to make sure that we can't add \n\t\t   certificates or sign the CRL with a different issuer.  We do this \n\t\t   here rather than after setting the revocation list entry because \n\t\t   of the difficulty of undoing the revocation entry addition */\n\t\tstatus = copyIssuerDnData( certInfoPtr, revInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the certificate information to the revocation list and make it \n\t   the currently selected entry.  The ID type isn't quite an\n\t   issuerAndSerialNumber but the checking code eventually converts it \n\t   into this form using the supplied issuer certificate DN */\n\tif( revInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tserialNumberPtr = revInfoPtr->cCertReq->serialNumber;\n\t\tserialNumberLength = revInfoPtr->cCertReq->serialNumberLength;\n\t\t}\n\telse\n\t\t{\n\t\tserialNumberPtr = revInfoPtr->cCertCert->serialNumber;\n\t\tserialNumberLength = revInfoPtr->cCertCert->serialNumberLength;\n\t\t}\n\tstatus = addRevocationEntry( &certInfoPtr->cCertRev->revocations,\n\t\t\t\t\t\t\t\t &revocationInfoPtr, \n\t\t\t\t\t\t\t\t CRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\t\t\t serialNumberPtr, serialNumberLength, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\t/* If this certificate is already present in the list set the \n\t\t\t   extended error code for it */\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tDATAPTR_SET( certInfoPtr->cCertRev->currentRevocation, \n\t\t\t\t revocationInfoPtr );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREQ || USE_CERTREV */\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\n/* Copy an RTCS or OCSP responder URL from a certificate into a request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyResponderURL( INOUT CERT_INFO *requestInfoPtr,\n\t\t\t\t\t\t\t INOUT CERT_INFO *userCertInfoPtr )\n\t{\n\tconst CRYPT_ATTRIBUTE_TYPE aiaAttribute = \\\n\t\t\t\t( requestInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \\\n\t\t\t\tCRYPT_CERTINFO_AUTHORITYINFO_RTCS : \\\n\t\t\t\tCRYPT_CERTINFO_AUTHORITYINFO_OCSP;\n\tSELECTION_STATE savedState;\n\tvoid *responderUrl;\n\tint urlSize DUMMY_INIT, status;\n\n\tREQUIRES( requestInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\t  requestInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );\n\tREQUIRES( userCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  userCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* There's no responder URL set, check whether the user certificate \n\t   contains a responder URL in the RTCS/OCSP authorityInfoAccess \n\t   GeneralName */\n\tsaveSelectionState( savedState, userCertInfoPtr );\n\tstatus = selectGeneralName( userCertInfoPtr, aiaAttribute,\n\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = selectGeneralName( userCertInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\tMUST_BE_PRESENT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getCertComponentString( userCertInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t\t\t\t\t\t\t\tNULL, 0, &urlSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there's no responder URL present then it's not a (fatal) \n\t\t   error */\n\t\trestoreSelectionState( savedState, userCertInfoPtr );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There's a responder URL present, copy it to the request */\n\tREQUIRES( rangeCheck( urlSize, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( responderUrl = clAlloc( \"copyResponderURL\", urlSize ) ) == NULL )\n\t\t{\n\t\trestoreSelectionState( savedState, userCertInfoPtr );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tstatus = getCertComponentString( userCertInfoPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t\t\t\t\t\t\t\t\t responderUrl, urlSize, &urlSize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( requestInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST )\n\t\t\t{\n\t\t\tREQUIRES( requestInfoPtr->cCertVal->responderUrl == NULL );\n\n\t\t\trequestInfoPtr->cCertVal->responderUrl = responderUrl;\n\t\t\trequestInfoPtr->cCertVal->responderUrlSize = urlSize;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( requestInfoPtr->cCertRev->responderUrl == NULL );\n\n\t\t\trequestInfoPtr->cCertRev->responderUrl = responderUrl;\n\t\t\trequestInfoPtr->cCertRev->responderUrlSize = urlSize;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tclFree( \"copyResponderURL\", responderUrl );\n\t\t}\n\trestoreSelectionState( savedState, userCertInfoPtr );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCopy Certificate Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that the key in a XYZZY certificate is signature-capable (or at \n   least sig-check capable, since it may be just the public key that's being \n   used), since XYZZY certificates are self-signed.  Then set the \n   appropriate signature keyUsage and optional encryption usage if the key \n   can also do that */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setXyzzyKeyUsage( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tint keyUsage = KEYUSAGE_SIGN | KEYUSAGE_CA;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Make sure that the key is signature-capable.  We have to check for a \n\t   capability to either sign or sig-check since a pure public key will \n\t   only have a sig-check capability while a private key held in a device \n\t   (from which we're going to extract the public-key components) may be \n\t   only signature-capable */\n\tif( !checkContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGCHECK ) && \\\n\t\t!checkContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If the key is encryption-capable (with the same caveat as for the \n\t   signature check above), enable that usage as well */\n\tif( checkContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_ENCRYPT ) || \\\n\t\tcheckContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_DECRYPT ) )\n\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\n\t/* Clear the existing usage and replace it with our usage.  See the \n\t   comment in setXyzzyInfo() for why it's done this way */\n\t( void ) deleteCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE );\n\treturn( addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t  keyUsage ) );\n\t}\n\n/* Copy public key data into a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyKeyFromCertificate( INOUT CERT_INFO *destCertInfoPtr,\n\t\t\t\t\t\t\t\t   const CERT_INFO *srcCertInfoPtr )\n\t{\n\tvoid *publicKeyInfoPtr;\n\n\tassert( isWritePtr( destCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( srcCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( destCertInfoPtr->publicKeyInfo == NULL );\n\tREQUIRES( srcCertInfoPtr->publicKeyInfo != NULL );\n\n\tREQUIRES( rangeCheck( srcCertInfoPtr->publicKeyInfoSize, \n\t\t\t\t\t\t  1, MAX_INTLENGTH_SHORT ) );\n\tif( ( publicKeyInfoPtr = \\\n\t\t\t\tclAlloc( \"copyPublicKeyInfo\", \n\t\t\t\t\t\t srcCertInfoPtr->publicKeyInfoSize ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemcpy( publicKeyInfoPtr, srcCertInfoPtr->publicKeyInfo, \n\t\t\tsrcCertInfoPtr->publicKeyInfoSize );\n\tdestCertInfoPtr->publicKeyData = destCertInfoPtr->publicKeyInfo = \\\n\t\tpublicKeyInfoPtr;\n\tdestCertInfoPtr->publicKeyInfoSize = srcCertInfoPtr->publicKeyInfoSize;\n\tdestCertInfoPtr->publicKeyAlgo = srcCertInfoPtr->publicKeyAlgo;\n\tdestCertInfoPtr->publicKeyFeatures = srcCertInfoPtr->publicKeyFeatures;\n\tmemcpy( destCertInfoPtr->publicKeyID, srcCertInfoPtr->publicKeyID, \n\t\t\tKEYID_SIZE );\n\tSET_FLAG( destCertInfoPtr->flags, CERT_FLAG_DATAONLY );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyKeyFromContext( INOUT CERT_INFO *destCertInfoPtr,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tvoid *publicKeyInfoPtr;\n\tint length, status;\n\n\tassert( isWritePtr( destCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( destCertInfoPtr->publicKeyInfo == NULL );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Get the key metadata from the context */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &destCertInfoPtr->publicKeyAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &destCertInfoPtr->publicKeyFeatures,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEYFEATURES );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, destCertInfoPtr->publicKeyID, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy over the public-key data.  We perform a copy rather than keeping \n\t   a reference to the context for two reasons.  Firstly, when the \n\t   certificate is transitioned into the high state it will constrain the \n\t   attached context so a context shared between two certificates could \n\t   be constrained in unexpected ways.  Secondly, the context could be a \n\t   private-key context and attaching that to a certificate would be \n\t   rather inappropriate.  Furthermore, the constraint issue is even more \n\t   problematic in that a context constrained by an encryption-only \n\t   request could then no longer be used to sign the request or a PKI \n\t   protocol message containing the request */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = msgData.length;\n\tREQUIRES( rangeCheck( length, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( publicKeyInfoPtr = clAlloc( \"copyPublicKeyInfo\", \n\t\t\t\t\t\t\t\t\t  length ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tsetMessageData( &msgData, publicKeyInfoPtr, length );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdestCertInfoPtr->publicKeyData = destCertInfoPtr->publicKeyInfo = \\\n\t\tpublicKeyInfoPtr;\n\tdestCertInfoPtr->publicKeyInfoSize = length;\n\tSET_FLAG( destCertInfoPtr->flags, CERT_FLAG_DATAONLY );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyPublicKeyInfo( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   IN_OPT const CERT_INFO *srcCertInfoPtr )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tBOOLEAN_INT isXyzzyCert;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( isHandleRangeValid( cryptHandle ) && \\\n\t\t\t  srcCertInfoPtr == NULL ) || \\\n\t\t\t( cryptHandle == CRYPT_UNUSED && \\\n\t\t\t  isReadPtr( srcCertInfoPtr, sizeof( CERT_INFO ) ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( ( isHandleRangeValid( cryptHandle ) && \\\n\t\t\t\tsrcCertInfoPtr == NULL ) || \\\n\t\t\t  ( cryptHandle == CRYPT_UNUSED && \\\n\t\t\t    srcCertInfoPtr != NULL ) );\n\tREQUIRES( srcCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( srcCertInfoPtr ) );\n\tREQUIRES( srcCertInfoPtr == NULL || \\\n\t\t\t  srcCertInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  srcCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\n\t/* Make sure that we haven't already got a public key present */\n\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \\\n\t\tcertInfoPtr->publicKeyInfo != NULL )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* If we've been given a data-only certificate then all that we need to \n\t   do is copy over the public key data */\n\tif( srcCertInfoPtr != NULL )\n\t\treturn( copyKeyFromCertificate( certInfoPtr, srcCertInfoPtr ) );\n\n\t/* Get the context handle.  All other checking has already been \n\t   performed by the kernel */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iCryptContext, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( status );\n\t\t}\n\n\t/* If it's a XYZZY certificate then we need to perform additional\n\t   processing for XYZZY-specific key usage requirements */\n\tstatus = getCertComponent( certInfoPtr, CRYPT_CERTINFO_XYZZY, \n\t\t\t\t\t\t\t   &isXyzzyCert );\n\tif( cryptStatusOK( status ) && isXyzzyCert == TRUE )\n\t\t{\n\t\tstatus = setXyzzyKeyUsage( certInfoPtr, iCryptContext);\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Copy the public-key data from the encryption context */\n\treturn( copyKeyFromContext( certInfoPtr, iCryptContext ) );\n\t}\n\n#ifdef USE_DBMS\t/* Only used by CA code */\n\n/* Sanitise certificate attributes based on a user-supplied template.  This \n   is used to prevent a user from supplying potentially dangerous attributes \n   in a certificate request, for example to request a CA certificate by \n   setting the basicConstraints/keyUsage = CA extensions in the request in a \n   manner that would result in the creation of a CA certificate when the \n   request is processed.  \n   \n   There are two ways to do this, either with a whitelist or with a \n   blacklist.  Obviously the preferred option is the whitelist one, but the\n   problem with this is that without any knowledge of the environment into\n   which it's being deployed we have no idea what should be permitted.  For\n   example an RA, which acts as a trusted agent for the CA, probably wants\n   fuller control over the form of the certificate with a wider selection of \n   attributes permitted while a CA dealing directly with the public probably \n   wants few or no attributes permitted.  This is a variation of the \n   firewall configuration problem, lock it down by default and users will \n   complain, leave it open by default and users are happy but it's not secure.\n\n   What we use here is in effect a blend of whitelist and blacklist.  On\n   the whitelist side the only attributes that are permitted in certificate \n   requests are:\n\n\tCRYPT_CERTINFO_CHALLENGEPASSWORD: Needed for SCEP.\n\tCRYPT_CERTINFO_KEYFEATURES: Only used by cryptlib for its own purposes.\n\tCRYPT_CERTINFO_KEYUSAGE\n\tCRYPT_CERTINFO_SUBJECTALTNAME\n\tCRYPT_CERTINFO_EXTKEYUSAGE\n\n   For revocation requests we allow rather more values since they're \n   required by the client to inform the CA why the certificate is being\n   revoked.  Except for the invalidity date they're not so much of a \n   security threat, and even for the date the consistency vs. accuracy issue \n   for CRLs debate means the CA will put who knows what date in the CRL \n   anyway:\n\n\tCRYPT_CERTINFO_CRLEXTREASON\n\tCRYPT_CERTINFO_CRLREASON\n\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE\n\tCRYPT_CERTINFO_INVALIDITYDATE\n   \n   Everything else, including the all-important basicConstraints, has to be \n   set explicitly by the CA and can't be specified in a request.\n\n   On the blacklist side, multi-AVA RDNs are disallowed in order to prevent\n   an attacker from playing games with DN forms.  This should be safe \n   because the only things that create such weird DNs tend to be European\n   in-house CAs following (or justifying their bugs through) peculiar \n   requirements in digital signature legislation, and those guys will be \n   creating their own certificates from scratch themselves rather than using \n   cryptlib for it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkCertWellFormed( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Check that the subject DN is well-formed */\n\tstatus = checkDN( certInfoPtr->subjectName, \n\t\t\t\t\t  CHECKDN_FLAG_COUNTRY | CHECKDN_FLAG_COMMONNAME | \\\n\t\t\t\t\t\t\tCHECKDN_FLAG_WELLFORMED,\n\t\t\t\t\t  &certInfoPtr->errorLocus,\n\t\t\t\t\t  &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* There can potentially be any number of other DNs in a certificate \n\t   (typically hidden in GeneralName fields), it's not really certain \n\t   what we should do with these or even how we can effectively track \n\t   them all down.  Since the reason why we're doing this in the first \n\t   place is to avoid shenanigans due to the more or less arbitrary \n\t   handling of complex DNs by implementations, and the only one that \n\t   anyone really pays any attention to is the subject name, we check \n\t   the subject name and at least have a go at the subjectAltName, but \n\t   leave the rest (it's not even certain what a DN in, say, an AIA\n\t   would mean, let alone how to check it) */\n\tattributePtr = findAttribute( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTALTNAME, TRUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tattributePtr = findAttributeField( attributePtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_DIRECTORYNAME );\n\t\t}\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\t\tDATAPTR_DN dnPtr;\n\n\t\tstatus = getAttributeDataDN( attributePtr, &dnPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = checkDN( dnPtr, CHECKDN_FLAG_COUNTRY | \\\n\t\t\t\t\t\t\t\t\t CHECKDN_FLAG_COMMONNAME | \\\n\t\t\t\t\t\t\t\t\t CHECKDN_FLAG_WELLFORMED,\n\t\t\t\t\t\t\t  &dummy1, &dummy2 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Reporting this one is a bit complicated because we're \n\t\t\t\t   dealing with a complex nested attribute, the best that we \n\t\t\t\t   can do is report a general problem with the altName */\n\t\t\t\tsetErrorInfo( certInfoPtr, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sanitiseCertAttributes( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t   const DATAPTR_ATTRIBUTE templateListPtr )\n\t{\n\tDATAPTR_ATTRIBUTE templateAttributeCursor;\n\tATTRIBUTE_ENUM_INFO attrEnumInfo;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( DATAPTR_ISVALID( templateListPtr ) );\n\n\t/* If there are no attributes present or there's no disallowed-attribute \n\t   template, we just need to apply the well-formedness check on the way\n\t   out */\n\tif( DATAPTR_ISNULL( certInfoPtr->attributes ) || \\\n\t\tDATAPTR_ISNULL( templateListPtr ) )\n\t\treturn( checkCertWellFormed( certInfoPtr ) );\n\n\t/* Walk down the template attribute list applying each one in turn to\n\t   the certificate attributes */\n\tLOOP_MAX( templateAttributeCursor = \\\n\t\t\t\t\tgetFirstAttribute( &attrEnumInfo, templateListPtr, \\\n\t\t\t\t\t\t\t\t\t   ATTRIBUTE_ENUM_NONBLOB ), \n\t\t\t  DATAPTR_ISSET( templateAttributeCursor ),\n\t\t\t  templateAttributeCursor = getNextAttribute( &attrEnumInfo ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE fieldID, subFieldID;\n\t\tDATAPTR_ATTRIBUTE certAttributePtr;\n\t\tint status;\n\n\t\t/* Check to see whether there's a constrained attribute present in\n\t\t   the certificate attributes and if it is, whether it conflicts \n\t\t   with the constraining attribute */\n\t\tstatus = getAttributeIdInfo( templateAttributeCursor, NULL, \n\t\t\t\t\t\t\t\t\t &fieldID, &subFieldID );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertAttributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\t   fieldID, subFieldID );\n\t\tif( DATAPTR_ISNULL( certAttributePtr ) )\n\t\t\t{\n\t\t\t/* There's nothing to constrain present in the certificate, \n\t\t\t   continue */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If the certificate attribute was provided through the application \n\t\t   of PKI user data (indicated by it having the locked flag set), \n\t\t   allow it even if it conflicts with the constraining attribute.  \n\t\t   This is permitted because the PKI user data was explicitly set by \n\t\t   the issuing CA rather than being user-supplied in the certificate \n\t\t   request so it has to be OK, or at least CA-approved */\n\t\tif( checkAttributeProperty( certAttributePtr, \n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_LOCKED ) )\n\t\t\tcontinue;\n\n\t\t/* There are conflicting attributes present, disallow the \n\t\t   certificate issue */\n\t\tstatus = getAttributeIdInfo( certAttributePtr, NULL, &fieldID, \n\t\t\t\t\t\t\t\t\t NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( fieldID == CRYPT_CERTINFO_KEYUSAGE )\n\t\t\t{\n\t\t\tint constrainedAttributeValue, constrainingAttributeValue;\n\n\t\t\t/* There is one special case in which conflicting attributes \n\t\t\t   are allowed and that's for keyUsage (or more generally \n\t\t\t   bitfields), since we can selectively disallow dangerous bit \n\t\t\t   values while allowing safe ones */\n\t\t\tstatus = getAttributeDataValue( certAttributePtr, \n\t\t\t\t\t\t\t\t\t\t\t&constrainedAttributeValue );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = getAttributeDataValue( templateAttributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t&constrainingAttributeValue );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( !( constrainedAttributeValue & constrainingAttributeValue ) )\n\t\t\t\tcontinue;\n\t\t\t}\n\t\tcertInfoPtr->errorLocus = fieldID;\n\t\tcertInfoPtr->errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( checkCertWellFormed( certInfoPtr ) );\n\t}\n#endif /* USE_DBMS*/\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopy Certificate Request Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREQ\n\n/* Copy certificate request information into a certificate object.  This \n   copies the public key context, the DN, any valid attributes, and any other \n   relevant bits and pieces if it's a CRMF request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCertReqToCert( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  INOUT CERT_INFO *certRequestInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( DATAPTR_ISNULL( certInfoPtr->subjectName ) );\n\tREQUIRES( certRequestInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\n\t/* Copy the public key context, the DN, and the attributes.  Type\n\t   checking has already been performed by the kernel.  We copy the\n\t   attributes across after the DN because that copy is the hardest to\n\t   undo: If there are already attributes present then the copied \n\t   attributes would be mixed in among them so it's not really possible \n\t   to undo the copy later without performing a complex selective \n\t   delete */\n\tstatus = copyDN( &certInfoPtr->subjectName, \n\t\t\t\t\t certRequestInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( certRequestInfoPtr->flags, CERT_FLAG_DATAONLY ) )\n\t\t{\n\t\tstatus = copyPublicKeyInfo( certInfoPtr, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tcertRequestInfoPtr );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = copyPublicKeyInfo( certInfoPtr,\n\t\t\t\t\t\t\t\t\tcertRequestInfoPtr->iPubkeyContext,\n\t\t\t\t\t\t\t\t\tNULL );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tDATAPTR_ISSET( certRequestInfoPtr->attributes ) )\n\t\t{\n\t\tstatus = copyAttributes( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t certRequestInfoPtr->attributes,\n\t\t\t\t\t\t\t\t &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeleteDN( &certInfoPtr->subjectName );\n\t\treturn( status );\n\t\t}\n\n\t/* If it's a CRMF request there could also be a validity period\n\t   specified */\n\tif( certRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\tconst time_t currentTime = getApproxTime();\n\n\t\t/* If there's a valid time present in the request, copy it across */  \n\t\tif( certRequestInfoPtr->startTime > MIN_TIME_VALUE )\n\t\t\t{\n\t\t\t/* We don't allow start times back- or forward-dated by more \n\t\t\t   than a year.  Since these are trivial things we don't abort \n\t\t\t   if there's a problem but leave the value unset so it'll be \n\t\t\t   filled in when the certificate is issued */\n\t\t\tif( certRequestInfoPtr->startTime > currentTime - ( 86400L * 365 ) && \\\n\t\t\t\tcertRequestInfoPtr->startTime < currentTime + ( 86400L * 365 ) ) \n\t\t\t\t{\n\t\t\t\tcertInfoPtr->startTime = certRequestInfoPtr->startTime;\n\t\t\t\t}\n\t\t\t}\n\t\tif( certRequestInfoPtr->endTime > MIN_TIME_VALUE )\n\t\t\t{\n\t\t\t/* We don't allow end times before the current time or before \n\t\t\t   the start time.  Since these are trivial things we don't \n\t\t\t   abort if there's a problem but leave the value unset so it'll \n\t\t\t   be filled in when the certificate is issued */\n\t\t\tif( certRequestInfoPtr->endTime > currentTime && \\\n\t\t\t\tcertRequestInfoPtr->endTime > certInfoPtr->startTime )\n\t\t\t\t{\n\t\t\t\tcertInfoPtr->endTime = certRequestInfoPtr->endTime;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy what we need to identify the certificate to be revoked and any \n   revocation information into a certificate object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyRevReqToCert( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t INOUT CERT_INFO *revRequestInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( revRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CRL );\n\tREQUIRES( revRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\n\tstatus = copyRevocationInfo( certInfoPtr, revRequestInfoPtr );\n\tif( cryptStatusError( status ) || \\\n\t\tDATAPTR_ISNULL( revRequestInfoPtr->attributes ) )\n\t\treturn( status );\n\treturn( copyRevocationAttributes( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  revRequestInfoPtr->attributes ) );\n\t}\n\n/* Copy the public key, DN, and any attributes that need to be copied across.  \n   We copy the full DN rather than just the encoded form in case the user \n   wants to query the request details after creating it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCertToRequest( INOUT CERT_INFO *crmfRequestInfoPtr,\n\t\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  const CRYPT_HANDLE iCryptHandle )\n\t{\n\tint status;\n\n\tassert( isWritePtr( crmfRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( crmfRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( DATAPTR_ISNULL( crmfRequestInfoPtr->subjectName ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\tstatus = copyDN( &crmfRequestInfoPtr->subjectName,\n\t\t\t\t\t certInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( crmfRequestInfoPtr->iPubkeyContext == CRYPT_ERROR && \\\n\t\tcrmfRequestInfoPtr->publicKeyInfo == NULL )\n\t\t{\n\t\t/* Only copy the key across if a key hasn't already been added \n\t\t   earlier as CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO.  Checking for \n\t\t   this special case (rather than returning an error) allows the DN \n\t\t   information from an existing certificate to be copied into a \n\t\t   request for a new key */\n\t\tstatus = copyPublicKeyInfo( crmfRequestInfoPtr, iCryptHandle, NULL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* We copy the attributes across after the DN because that copy is \n\t\t   the hardest to undo: If there are already attributes present then \n\t\t   the copied attributes will be mixed in among them so it's not \n\t\t   really possible to undo the copy later without performing a \n\t\t   complex selective delete */\n\t\tstatus = copyCRMFRequestAttributes( &crmfRequestInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\tcertInfoPtr->attributes );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\tdeleteDN( &crmfRequestInfoPtr->subjectName );\n\n\treturn( status );\n\t}\n\n/* Copy across the issuer and subject DN and serial number */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCertToRevRequest( INOUT CERT_INFO *crmfRevRequestInfoPtr,\n\t\t\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( crmfRevRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( crmfRevRequestInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tREQUIRES( DATAPTR_ISNULL( crmfRevRequestInfoPtr->subjectName ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* If the information is already present then we can't add it again */\n\tif( DATAPTR_ISSET( crmfRevRequestInfoPtr->issuerName ) )\n\t\t{\n\t\tsetErrorInfo( crmfRevRequestInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* Copy across the issuer name and allocate the storage that we need to \n\t   copy the subject name.  We don't care about any internal structure of \n\t   the DNs so we just copy the pre-encoded form, we could in theory copy \n\t   the full DN but it isn't really the issuer (creator) of the object so \n\t   it's better if it appears to have no issuer DN than a misleading one */\n\tstatus = copyIssuerDnData( crmfRevRequestInfoPtr, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = setSerialNumber( crmfRevRequestInfoPtr,\n\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumberLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tREQUIRES( rangeCheck( certInfoPtr->subjectDNsize, \n\t\t\t\t\t\t\t  1, MAX_INTLENGTH_SHORT ) );\n\t\tcrmfRevRequestInfoPtr->subjectDNdata = \\\n\t\t\t\t\t\t\t\t\tclAlloc( \"copyCertToRevRequest\",\n\t\t\t\t\t\t\t\t\t\t\t   certInfoPtr->subjectDNsize );\n\t\tif( crmfRevRequestInfoPtr->subjectDNdata == NULL )\n\t\t\tstatus = CRYPT_ERROR_MEMORY;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"copyCertToRevRequest\", \n\t\t\t\tcrmfRevRequestInfoPtr->issuerDNdata );\n\t\tcrmfRevRequestInfoPtr->issuerDNptr = \\\n\t\t\tcrmfRevRequestInfoPtr->issuerDNdata = NULL;\n\t\tcrmfRevRequestInfoPtr->issuerDNsize = 0;\n\t\tif( crmfRevRequestInfoPtr->cCertCert->serialNumber != NULL && \\\n\t\t\tcrmfRevRequestInfoPtr->cCertCert->serialNumber != \\\n\t\t\t\tcrmfRevRequestInfoPtr->cCertCert->serialNumberBuffer )\n\t\t\t{\n\t\t\tclFree( \"copyCertToRevRequest\",\n\t\t\t\t\tcrmfRevRequestInfoPtr->cCertCert->serialNumber );\n\t\t\t}\n\t\tcrmfRevRequestInfoPtr->cCertCert->serialNumber = NULL;\n\t\tcrmfRevRequestInfoPtr->cCertCert->serialNumberLength = 0;\n\t\treturn( status );\n\t\t}\n\n\t/* Copy the certificate's subject DN for use in CMP.  This isn't used in \n\t   the CRMF/certificate code itself, but it's required by the CMP \n\t   protocol to fill a message header field thay requires a DN.  Since \n\t   the CMP client that's sending the CRMF request only has access to the \n\t   revocation request but not the original certificate that was used to \n\t   create it, we have to save this metadata in the request so that it \n\t   can be read back later when it's required for CMP */\n\tmemcpy( crmfRevRequestInfoPtr->subjectDNdata, certInfoPtr->subjectDNptr,\n\t\t\tcertInfoPtr->subjectDNsize );\n\tcrmfRevRequestInfoPtr->subjectDNptr = crmfRevRequestInfoPtr->subjectDNdata;\n\tcrmfRevRequestInfoPtr->subjectDNsize = certInfoPtr->subjectDNsize;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREQ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopy Certificate Revocation Data\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* The OCSP ID doesn't contain any usable fields so we pre-encode it when \n   the certificate is added to the OCSP request and treat it as a blob \n   thereafter */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeOCSPID( INOUT STREAM *stream, \n\t\t\t\t\t\tconst CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_BUFFER( issuerKeyHashLength ) \\\n\t\t\t\t\t\t\tconst void *issuerKeyHash,\n\t\t\t\t\t\tIN_LENGTH_FIXED( KEYID_SIZE ) \\\n\t\t\t\t\t\t\tconst int issuerKeyHashLength )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( issuerKeyHash, issuerKeyHashLength ) );\n\n\tREQUIRES( issuerKeyHashLength == KEYID_SIZE );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( certInfoPtr->issuerDNptr != NULL );\n\tREQUIRES( certInfoPtr->cCertCert->serialNumber != NULL );\n\n\t/* Get the issuerName hash */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\thashFunctionAtomic( hashBuffer, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\tcertInfoPtr->issuerDNptr,\n\t\t\t\t\t\tcertInfoPtr->issuerDNsize );\n\n\t/* Write the request data */\n\twriteSequence( stream,\n\t\t\tsizeofAlgoID( CRYPT_ALGO_SHA1 ) + \\\n\t\t\tsizeofObject( hashSize ) + sizeofObject( hashSize ) + \\\n\t\t\tsizeofInteger( certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t   certInfoPtr->cCertCert->serialNumberLength ) );\n\twriteAlgoID( stream, CRYPT_ALGO_SHA1 );\n\twriteOctetString( stream, hashBuffer, hashSize, DEFAULT_TAG );\n\twriteOctetString( stream, issuerKeyHash, issuerKeyHashLength, \n\t\t\t\t\t  DEFAULT_TAG );\n\treturn( writeInteger( stream, certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\n/* Copy revocation information from an OCSP request to a response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyOcspReqToResp( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  INOUT CERT_INFO *ocspRequestInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tconst CERT_REV_INFO *requestRevInfo = ocspRequestInfoPtr->cCertRev;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( ocspRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tREQUIRES( DATAPTR_ISNULL( certRevInfo->revocations ) );\n\tREQUIRES( ocspRequestInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );\n\n\t/* Copy the revocation information and extensions */\n\tstatus = copyRevocationEntries( &certRevInfo->revocations,\n\t\t\t\t\t\t\t\t\trequestRevInfo->revocations );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = copyOCSPRequestAttributes( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\tocspRequestInfoPtr->attributes );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy the certificate information to the revocation list.  First we make \n   sure that the CA certificate hash (needed for OCSP's weird certificate \n   ID) is present.  We add the necessary information as a pre-encoded blob \n   since we can't do much with the ID fields */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCertToOCSPRequest( INOUT CERT_INFO *ocspRequestInfoPtr,\n\t\t\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = ocspRequestInfoPtr->cCertRev;\n\tREVOCATION_INFO *revInfoPtr DUMMY_INIT_PTR;\n\tSTREAM stream;\n\tDYNBUF essCertDB;\n\tBYTE idBuffer[ 256 + 8 ], *idBufPtr = idBuffer;\n\tint idLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( ocspRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( ocspRequestInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* Make sure that there's a CA certificate hash present */\n\tif( !ocspRequestInfoPtr->certHashSet )\n\t\t{\n\t\tsetErrorInfo( ocspRequestInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Generate the OCSP certificate ID */\n\tsMemNullOpen( &stream );\n\tstatus = writeOCSPID( &stream, certInfoPtr, \n\t\t\t\t\t\t  ocspRequestInfoPtr->certHash, KEYID_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\tidLength = stell( &stream );\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( idLength > 256 )\n\t\t{\n\t\t/* Allocate a buffer for an oversize ID */\n\t\tif( ( idBufPtr = clDynAlloc( \"copyCertToOCSPRequest\", \\\n\t\t\t\t\t\t\t\t\t idLength ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tsMemOpen( &stream, idBufPtr, idLength );\n\tstatus = writeOCSPID( &stream, certInfoPtr, \n\t\t\t\t\t\t  ocspRequestInfoPtr->certHash, KEYID_SIZE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = addRevocationEntry( &certRevInfo->revocations,\n\t\t\t\t\t\t\t\t\t &revInfoPtr, CRYPT_KEYID_NONE, \n\t\t\t\t\t\t\t\t\t idBufPtr, idLength, FALSE );\n\t\t}\n\tif( idBufPtr != idBuffer )\n\t\tclFree( \"copyCertToOCSPRequest\", idBufPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\t/* If this certificate is already present in the list, set the \n\t\t\t   extended error code for it */\n\t\t\tsetErrorInfo( ocspRequestInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tDATAPTR_SET( certRevInfo->currentRevocation, revInfoPtr );\n\n\t/* Add the certificate information again as an ESSCertID extension to \n\t   work around the problems inherent in OCSP IDs */\n\tstatus = dynCreate( &essCertDB, certInfoPtr->objectHandle, \n\t\t\t\t\t\tCRYPT_IATTRIBUTE_ESSCERTID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\n\t\t/* Since this isn't a critical extension (the ESSCertID is just a \n\t\t   backup for the main, albeit not very useful, ID) we continue if \n\t\t   there's a problem adding it */\n\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\tENSURES( revInfoPtr != NULL );\n\t\t( void ) addAttributeFieldString( &revInfoPtr->attributes,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID, \n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, dynData( essCertDB ), \n\t\t\t\t\t\t\t\tdynLength( essCertDB ), ATTR_FLAG_NONE, \n\t\t\t\t\t\t\t\t&dummy1, &dummy2 );\n\t\tdynDestroy( &essCertDB );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the hash of the public key (for an OCSP request), possibly\n   overwriting a previous hash if there are multiple entries in the\n   request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCaCertToOCSPReq( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tINOUT CERT_INFO *caCertInfoPtr )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tSTREAM stream;\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tint length, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( caCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST );\n\tREQUIRES( caCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  caCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( caCertInfoPtr->publicKeyInfo != NULL );\n\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\n\t/* Dig down into the encoded key data to find the weird bits of key that\n\t   OCSP requires us to hash.  We store the result as the certificate \n\t   hash, this is safe because this value isn't used for an OCSP request \n\t   so it can't be accessed externally */\n\tsMemConnect( &stream, caCertInfoPtr->publicKeyInfo,\n\t\t\t\t caCertInfoPtr->publicKeyInfoSize );\n\treadSequence( &stream, NULL );\t/* Wrapper */\n\treadUniversal( &stream );\t\t/* AlgoID */\n\tstatus = readBitStringHole( &stream, &length, 16, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\t/* BIT STRING wrapper */\n\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There's a problem with the format of the key */\n\t\tDEBUG_DIAG(( \"Invalid certificate data format when hashing \"\n\t\t\t\t\t \"certificate to create OCSP ID\" ));\n\t\tassert( DEBUG_WARN );\n\t\tsMemDisconnect( &stream );\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\thashFunctionAtomic( certInfoPtr->certHash, KEYID_SIZE, dataPtr, length );\n\tcertInfoPtr->certHashSet = TRUE;\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopy Certificate Validation Data\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTVAL\n\n/* Copy validity information from an RTCS request to a response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyRtcsReqToResp( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  IN const CERT_INFO *rtcsRequestInfoPtr )\n\t{\n\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\tconst CERT_VAL_INFO *requestValInfo = rtcsRequestInfoPtr->cCertVal;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( rtcsRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE );\n\tREQUIRES( DATAPTR_ISNULL( certValInfo->validityInfo ) );\n\tREQUIRES( rtcsRequestInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST );\n\n\t/* Copy the certificate validity information and extensions */\n\tstatus = copyValidityEntries( &certValInfo->validityInfo,\n\t\t\t\t\t\t\t\t  requestValInfo->validityInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = copyRTCSRequestAttributes( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\trtcsRequestInfoPtr->attributes );\n\t\t}\n\treturn( status );\n\t}\n\n/* Copy the certificate hash.  We read the value indirectly since it's \n   computed on demand and may not have been evaluated yet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyCertToRTCSRequest( INOUT CERT_INFO *rtcsRequestInfoPtr,\n\t\t\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_VAL_INFO *valInfo = rtcsRequestInfoPtr->cCertVal;\n\tVALIDITY_INFO *validityInfoPtr DUMMY_INIT_PTR;\n\tBYTE certHash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint certHashLength, status;\n\n\tassert( isWritePtr( rtcsRequestInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( rtcsRequestInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\tstatus = getCertComponentString( certInfoPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_FINGERPRINT_SHA1, \n\t\t\t\t\t\t\t\t\t certHash, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t\t &certHashLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = addValidityEntry( &valInfo->validityInfo,\n\t\t\t\t\t\t\t\t   &validityInfoPtr, certHash, \n\t\t\t\t\t\t\t\t   certHashLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\t/* If this certificate is already present in the list, set the \n\t\t\t   extended error code for it */\n\t\t\tsetErrorInfo( rtcsRequestInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tDATAPTR_SET( valInfo->currentValidity, validityInfoPtr );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tCertificate Information Copy External Interface\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy user certificate information into a certificate object, either a\n   CRL, a certification/revocation request, or an RTCS/OCSP request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyUserCertInfo( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t INOUT CERT_INFO *userCertInfoPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptHandle )\n\t{\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( userCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( userCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  userCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( userCertInfoPtr->certificate != NULL );\n\n\t/* If it's an RTCS or OCSP request, remember the responder URL if there's\n\t   one present.  We can't leave it to be read out of the certificate \n\t   because authorityInfoAccess isn't a valid attribute for RTCS/OCSP \n\t   requests */\n#ifdef USE_CERTREV\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST && \\\n\t\tcertInfoPtr->cCertRev->responderUrl == NULL )\n\t\t{\n\t\tint status;\n\n\t\tstatus = copyResponderURL( certInfoPtr, userCertInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* USE_CERTREV */\n#ifdef USE_CERTVAL\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST && \\\n\t\tcertInfoPtr->cCertVal->responderUrl == NULL )\n\t\t{\n\t\tint status;\n\n\t\tstatus = copyResponderURL( certInfoPtr, userCertInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* USE_CERTVAL */\n\n\t/* Copy the required information across to the certificate */\n\tswitch( certInfoPtr->type )\n\t\t{\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\t\treturn( copyCertToRequest( certInfoPtr, userCertInfoPtr,\n\t\t\t\t\t\t\t\t\t   iCryptHandle ) );\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\treturn( copyCertToRevRequest( certInfoPtr, userCertInfoPtr ) );\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\treturn( copyRevocationInfo( certInfoPtr, userCertInfoPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\treturn( copyCertToOCSPRequest( certInfoPtr, userCertInfoPtr ) );\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\t\treturn( copyCertToRTCSRequest( certInfoPtr, userCertInfoPtr ) );\n#endif /* USE_CERTVAL */\n\t\t}\n\n\tretIntError();\n\t}\n\n/* A general dispatch function for copying information from one certificate \n   object to another.  This is a wrapper that acquires the source object's \n   data and then passes a pointer to it to the actual copy function that\n   copies any necessary information to the destination object, releasing the\n   source object after the copy */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCertObject( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE addedCert,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\tIN const int certInfo )\n\t{\n\tCERT_INFO *addedCertInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\tREQUIRES( isHandleRangeValid( addedCert ) );\n\n\tstatus = krnlAcquireObject( addedCert, OBJECT_TYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &addedCertInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_ARGERROR_NUM1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES_OBJECT( sanityCheckCert( addedCertInfoPtr ), \n\t\t\t\t\t addedCertInfoPtr->objectHandle );\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_CERTIFICATE:\n\t\t\tstatus = copyUserCertInfo( certInfoPtr, addedCertInfoPtr, \n\t\t\t\t\t\t\t\t\t   certInfo );\n\t\t\tbreak;\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_CACERTIFICATE:\n\t\t\tstatus = copyCaCertToOCSPReq( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTINFO_CERTREQUEST:\n\t\t\tstatus = copyCertReqToCert( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_IATTRIBUTE_RTCSREQUEST:\n\t\t\tstatus = copyRtcsReqToResp( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_IATTRIBUTE_OCSPREQUEST:\n\t\t\tstatus = copyOcspReqToResp( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_REVREQUEST:\n\t\t\tstatus = copyRevReqToCert( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_IATTRIBUTE_PKIUSERINFO:\n\t\t\tstatus = copyPkiUserToCertReq( certInfoPtr, addedCertInfoPtr );\n\t\t\tbreak;\n#endif /* USE_PKIUSER */\n\n#ifdef USE_DBMS\t/* Only used by CA code */\n\t\tcase CRYPT_IATTRIBUTE_BLOCKEDATTRS:\n\t\t\tstatus = sanitiseCertAttributes( certInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t addedCertInfoPtr->attributes );\n\t\t\tbreak;\n#endif /* USE_DBMS */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tkrnlReleaseObject( addedCertInfoPtr->objectHandle );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_curs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tManage Certificate Attribute Cursors\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1997-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n#endif /* Compiler-specific includes */\n\n/* GeneralNames and DNs are handled via indirect selection.  There are four\n   classes of field type that cover these names:\n\n\tGNSelection\t= EXCLUDEDSUBTREES | ...\n\tGNValue\t\t= OTHERNAME | ... | DIRECTORYNAME\n\tDNSelection\t= SUBJECTNAME | ISSUERNAME | DIRECTORYNAME\n\tDNValue\t\t= C | O | OU | CN | ...\n\n   Note that DIRECTORYNAME is present twice since it's both a component of a\n   GeneralName and a DN in its own right.  GNSelection and DNSelection\n   components merely select a composite component, the primitive elements are\n   read and written via the GN and DN values.  The selection process is as\n   follows:\n\n\tGNSelection --+\t(default = subjectAltName)\n\t\t\t\t  |\n\t\t\t\t  v\n\t\t\t\t GN -+----------------> non-DirectoryName field\n\t\t\t\t\t |\n\t\t\t\t  +--+ DirectoryName\n\t\t\t\t  |\n\tDNSelection --+\t(default = subjectName)\n\t\t\t\t  |\n\t\t\t\t  v\n\t\t\t\t DN ------------------> DN field\n\n   Selecting a component can therefore lead through a complex heirarchy of\n   explicit and implicit selections, in the worst case being something like\n   subjectAltName -> directoryName -> DN field.  DN and GeneralName\n   components may be absent (if we're selecting it in order to create it),\n   present (if we're about to read it), or can be created when accessed (if \n   we're about to write to it).  The handling is selected by the \n   SELECTION_OPTION type, if a certificate is in the high state then \n   MAY/CREATE options are implicitly converted to MUST_BE_PRESENT during the \n   selection process.\n\n   The selection is performed as follows:\n\n\tset attribute:\n\n\t  selectionComponent:\n\t\tselectDN\tsubject | issuer\t\t\t| MAY_BE_ABSENT\n\t\tselectGN\tattributeID\t\t\t\t\t| MAY_BE_ABSENT\n\t\t\t- Select prior to use\n\n\t  valueComponent:\n\t\tselectDN\t-\t\t\t\t\t\t\t| CREATE_IF_ABSENT\n\t\tselectGN\t-\t\t\t\t\t\t\t| CREATE_IF_ABSENT\n\t\t\t- To create DN/GeneralName before adding DN/GN\n\t\t\t  component/setting DN string\n\n\tget attribute:\n\n\t  selectionComponent:\n\t\tcheck\t\tsubject | issuer | other\t| Presence check only\n\t\tcheck\t\tattributeID\n\t\t\t- Return T/F if present\n\n\t  valueComponent:\n\t\tselectDN\tnone\t\t\t\t\t\t| MUST_BE_PRESENT\n\t\tselectGN\tnone\t\t\t\t\t\t| MUST_BE_PRESENT\n\t\t\t- To get DN/GeneralName component\n\n\tdelete attribute:\n\n\t\tselectDN\tsubject | issuers\t\t\t| MUST_BE_PRESENT\n\t\tselectGN\tattributeID\t\t\t\t\t| MUST_BE_PRESENT\n\t\t\t- To delete DN/GeneralName component\n\n   This code is cursed */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether the currently selected extension is a GeneralName */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isGeneralNameSelected( const CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE fieldID;\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\treturn( FALSE );\n\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t NULL, &fieldID, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\treturn( isGeneralNameSelectionComponent( fieldID ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/* Sanity-check the selection state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckSelectionInfo( const CERT_INFO *certInfoPtr )\n\t{\n\tconst SELECTION_INFO *currentSelection = &certInfoPtr->currentSelection;\n\tDATAPTR_DN dnSelection;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tif( currentSelection->generalName != CRYPT_ATTRIBUTE_NONE && \\\n\t\t!( isValidExtension( currentSelection->generalName ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: GN attribute type\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( currentSelection->dnComponent != CRYPT_ATTRIBUTE_NONE && \\\n\t\t( currentSelection->dnComponent < CRYPT_CERTINFO_FIRST_DN || \\\n\t\t  currentSelection->dnComponent > CRYPT_CERTINFO_LAST_DN ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: DN attribute type\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( ( currentSelection->dnInExtension != TRUE && \\\n\t\t  currentSelection->dnInExtension != FALSE ) || \\\n\t\t( currentSelection->updateCursor != TRUE && \\\n\t\t  currentSelection->updateCursor != FALSE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The DN component count must be consistent with the DN selection \n\t   state */\n\tif( currentSelection->dnComponent == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tif( currentSelection->dnComponentCount != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: Spurious DN component count\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isShortIntegerRange( currentSelection->dnComponentCount ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: DN component count\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* If there's a GeneralName selected then there can't also be a saved \n\t   GeneralName present */\n\tif( isGeneralNameSelected( certInfoPtr ) && \\\n\t\tcurrentSelection->generalName != CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: GeneralName selection\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If there's no DN selected then we're done */\n\tif( currentSelection->dnPtr == NULL )\n\t\t{\n\t\tif( currentSelection->dnInExtension )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: Spurious DN in extension\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\treturn( TRUE );\n\t\t}\n\tdnSelection = *currentSelection->dnPtr;\n\n\t/* Make sure that the DN pointer is valid */\n\tif( !DATAPTR_ISVALID( dnSelection ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: DN\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\tif( DATAPTR_ISSET( dnSelection ) )\n\t\t{\n\t\t/* There's a DN selected, if it's not in an extension then it must \n\t\t   be the subject or issuer DN */\n\t\tif( !currentSelection->dnInExtension && \\\n\t\t\t!isSubjectNameSelected( certInfoPtr ) && \\\n\t\t\t!isIssuerNameSelected( certInfoPtr ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSelectionInfo: Selected DN\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check whether there's a DN in the currently-selected GeneralName and \n   update the various selection values if we find one */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findDnInGeneralName( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tconst BOOLEAN updateCursor )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( updateCursor == TRUE || updateCursor == FALSE );\n\n\t/* We're inside a GeneralName, clear any possible saved selection */\n\tcertInfoPtr->currentSelection.generalName = CRYPT_ATTRIBUTE_NONE;\n\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t/* Search for a DN in the current GeneralName */\n\tattributePtr = findDnInAttribute( certInfoPtr->attributeCursor );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* We found a DN, select it */\n\tstatus = getAttributeDataDNPtr( attributePtr, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->currentSelection.dnPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( updateCursor )\n\t\tcertInfoPtr->attributeCursor = attributePtr;\n\tcertInfoPtr->currentSelection.dnInExtension = TRUE;\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Reset the current DN selection state.  Note that this only resets the \n   metadata for the selection but not the selected DN itself */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void resetDNselection( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  const BOOLEAN clearDNPtr )\n\t{\n\tSELECTION_INFO *currentSelection = &certInfoPtr->currentSelection;\n\n\tassert( isWritePtr( currentSelection , sizeof( SELECTION_INFO ) ) );\n\n\tREQUIRES_V( clearDNPtr == TRUE || clearDNPtr == FALSE );\n\n\tcurrentSelection->dnInExtension = FALSE;\n\tcurrentSelection->dnComponent = CRYPT_ATTRIBUTE_NONE;\n\tcurrentSelection->dnComponentCount = 0;\n\tif( clearDNPtr == TRUE )\n\t\tcurrentSelection->dnPtr = NULL;\n\n\tENSURES_V(  sanityCheckSelectionInfo( certInfoPtr ) );\n\t}\n\n/* Synchronise DN/GeneralName selection information after moving the\n   extension cursor */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void syncSelection( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tSELECTION_INFO *currentSelection = &certInfoPtr->currentSelection;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* We don't apply a REQUIRES( sanityCheckSelectionInfo() ) precondition \n\t   here because the purpose of syncSelection() is to restore a\n\t   consistent state after moving the cursor */\n\n\t/* We've moved the cursor, clear any saved GeneralName selection */\n\tcurrentSelection->generalName = CRYPT_ATTRIBUTE_NONE;\n\n\t/* I've we've moved the cursor off the GeneralName or there's no DN in\n\t   the GeneralName, deselect the DN */\n\tif( !isGeneralNameSelected( certInfoPtr ) || \\\n\t\tcryptStatusError( findDnInGeneralName( certInfoPtr, FALSE ) ) )\n\t\t{\n\t\tresetDNselection( certInfoPtr, TRUE );\n\t\t}\n\n\tENSURES_V( sanityCheckSelectionInfo( certInfoPtr ) );\n\t}\n\n/* Move the extension cursor to the given extension field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int moveCursorToField( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( isValidExtension( certInfoType ) );\n\n\t/* Try and locate the given field in the extension */\n\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t   certInfoType, CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* We've found the given field, update the cursor and select the DN within\n\t   it if it's present */\n\tcertInfoPtr->currentSelection.updateCursor = FALSE;\n\tcertInfoPtr->attributeCursor = attributePtr;\n\tif( isGeneralNameSelectionComponent( certInfoType ) )\n\t\t{\n\t\t/* If this is a GeneralName, select the DN within it if there's one\n\t\t   present.  Since this is peripheral to the main operation of \n\t\t   moving the cursor we ignore the return status */\n\t\t( void ) findDnInGeneralName( certInfoPtr, FALSE );\n\n\t\t/* We've selected the GeneralName (possibly as a side-effect of its\n\t\t   on-demand creation), clear the saved GeneralName-to-be-created\n\t\t   value */\n\t\tcertInfoPtr->currentSelection.generalName = CRYPT_ATTRIBUTE_NONE;\n\t\t}\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGeneralName Selection Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine whether a component which is being added to a certificate is a \n   GeneralName selection component */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isGeneralNameSelectionComponent( IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tstatic const CRYPT_ATTRIBUTE_TYPE certGeneralNameTbl[] = {\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_RTCS, \n\t\tCRYPT_CERTINFO_AUTHORITYINFO_OCSP,\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS, \n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE,\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CRLS,\n\t\tCRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY,\n\t\tCRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING,\n\t\tCRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY,\n\t\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY,\n\t\tCRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST,\n\t\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT,\n\t\tCRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR,\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY,\n\t\tCRYPT_CERTINFO_SUBJECTALTNAME,\n\t\tCRYPT_CERTINFO_ISSUERALTNAME,\n\t\tCRYPT_CERTINFO_ISSUINGDIST_FULLNAME,\n\t\tCRYPT_CERTINFO_CERTIFICATEISSUER,\n\t\tCRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t\tCRYPT_CERTINFO_CRLDIST_FULLNAME,\n\t\tCRYPT_CERTINFO_CRLDIST_CRLISSUER,\n\t\tCRYPT_CERTINFO_AUTHORITY_CERTISSUER,\n\t\tCRYPT_CERTINFO_FRESHESTCRL_FULLNAME,\n\t\tCRYPT_CERTINFO_FRESHESTCRL_CRLISSUER,\n\t\tCRYPT_CERTINFO_DELTAINFO_LOCATION,\n\t\tCRYPT_CERTINFO_TOBEREVOKED_CERTISSUER,\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER,\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_FULLNAME,\n\t\tCRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE \n\t\t};\n\tstatic const CRYPT_ATTRIBUTE_TYPE cmsGeneralNameTbl[] = {\n\t\tCRYPT_CERTINFO_CMS_RECEIPT_TO,\n\t\tCRYPT_CERTINFO_CMS_MLEXP_INSTEADOF,\n\t\tCRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO,\n\t\tCRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE \n\t\t};\n\tconst CRYPT_ATTRIBUTE_TYPE *generalNameTbl;\n\tint generalNameTblSize, i, LOOP_ITERATOR;\n\n\tREQUIRES_B( isAttribute( certInfoType ) || \\\n\t\t\t\tisInternalAttribute( certInfoType ) );\n\n\t/* Determine which type of attribute we're dealing with */\n\tif( certInfoType >= CRYPT_CERTINFO_FIRST_EXTENSION && \\\n\t\tcertInfoType <= CRYPT_CERTINFO_LAST_EXTENSION )\n\t\t{\n\t\tgeneralNameTbl = certGeneralNameTbl;\n\t\tgeneralNameTblSize = FAILSAFE_ARRAYSIZE( certGeneralNameTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_TYPE );\n\t\t}\n\telse\n\t\t{\n\t\tif( certInfoType >= CRYPT_CERTINFO_FIRST_CMS && \\\n\t\t\tcertInfoType <= CRYPT_CERTINFO_LAST_CMS )\n\t\t\t{\n\t\t\tgeneralNameTbl = cmsGeneralNameTbl;\n\t\t\tgeneralNameTblSize = FAILSAFE_ARRAYSIZE( cmsGeneralNameTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_TYPE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's neither a certificate nor a CMS attribute extension, it\n\t\t\t   can't be a GeneralName */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check for membership in the GeneralName set.  In theory we could \n\t   divide this further via binary search but we're really reaching the \n\t   law of diminishing returns here */\n\tLOOP_MED( i = 0, \n\t\t\t  i < generalNameTblSize && \\\n\t\t\t\t\tgeneralNameTbl[ i ] != CRYPT_ATTRIBUTE_NONE,\n\t\t\t  i++ )\n\t\t{\n\t\tif( generalNameTbl[ i ] == certInfoType )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < generalNameTblSize );\n\n\treturn( FALSE );\n\t}\n\n/* Handle selection of a GeneralName or GeneralName\tcomponent in a certificate \n   extension */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectGeneralName( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t   IN_ATTRIBUTE_OPT const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t   IN_ENUM( SELECTION_OPTION ) const SELECTION_OPTION option )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( ( option == MAY_BE_ABSENT && \\\n\t\t\t\tisGeneralNameSelectionComponent( certInfoType ) ) || \\\n\t\t\t  ( ( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT ) && \\\n\t\t\t\tcertInfoType == CRYPT_ATTRIBUTE_NONE ) );\n\n\t/* At this point we may be trying to create or access a GeneralName for an \n\t   attribute that's been disabled through configuration options.  This can \n\t   happen if the access is indirect, for example by setting \n\t   CRYPT_ATTRIBUTE_CURRENT to the GeneralName, which won't be blocked by\n\t   the kernel ACLs.  Before we can continue we verify that the attribute\n\t   containing the GeneralName that we want to use is actually available */\n\tif( option == MAY_BE_ABSENT && !checkAttributeAvailable( certInfoType ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\tcertInfoPtr->currentSelection.updateCursor = FALSE;\n\n\tif( option == MAY_BE_ABSENT )\n\t\t{\n\t\t/* If the selection is present, update the extension cursor and\n\t\t   exit */\n\t\tstatus = moveCursorToField( certInfoPtr, certInfoType );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If the certificate is in the high state then the MAY is treated \n\t\t   as a MUST since we can't be selecting something in order to \n\t\t   create it later as we can for a certificate in the low state */\n\t\tif( certInfoPtr->certificate != NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t/* The selection isn't present, remember it for later without\n\t\t   changing any other selection information */\n\t\tcertInfoPtr->currentSelection.generalName = certInfoType;\n\t\tDATAPTR_SET( certInfoPtr->attributeCursor, NULL );\n\n\t\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tENSURES( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT );\n\n\t/* If there's no saved GeneralName selection present, the extension\n\t   cursor must be pointing to a GeneralName */\n\tif( certInfoPtr->currentSelection.generalName == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tif( isGeneralNameSelected( certInfoPtr ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If there's no GeneralName explicitly selected, try for the \n\t\t   default subjectAltName */\n\t\tcertInfoPtr->currentSelection.generalName = \\\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME;\n\t\t}\n\n\t/* Try and move the cursor to the saved GeneralName selection */\n\tstatus = moveCursorToField( certInfoPtr,\n\t\t\t\t\t\t\t    certInfoPtr->currentSelection.generalName );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( option == MUST_BE_PRESENT )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* The GeneralName isn't present, we're creating a new one */\n\tREQUIRES( option == CREATE_IF_ABSENT );\n\n\t/* We're creating the GeneralName extension, deselect the current DN and\n\t   remember that we have to update the extension cursor when we've done\n\t   it */\n\tresetDNselection( certInfoPtr, TRUE );\n\tcertInfoPtr->currentSelection.updateCursor = TRUE;\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectGeneralNameComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE generalName;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( isGeneralNameComponent( certInfoType ) );\n\n\t/* To select a GeneralName component we first need to have a GeneralName\n\t   selected */\n\tstatus = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\tMUST_BE_PRESENT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( isGeneralNameSelected( certInfoPtr ) );\n\t\t\t /* Required for MUST_BE_PRESENT */\n\n\t/* We've got the required GeneralName selected, set the cursor to the \n\t   field within it */\n\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, NULL, \n\t\t\t\t\t\t\t\t &generalName, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tattributePtr = findAttributeField( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t   generalName, certInfoType );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tcertInfoPtr->currentSelection.updateCursor = FALSE;\n\tcertInfoPtr->attributeCursor = attributePtr;\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDN Selection Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle selection of DNs.  The subject and issuer DNs are somewhat special \n   in that they can be selected like any other attribute but aren't actually \n   certificate extensions, so that some things that work with attributes-in-\n   extensions don't work with attributes-in-a-DN.\n   \n   The problem is the depth of the nesting, for a DN in a GeneralName the \n   CURRENT_GROUP is the extension, the CURRENT_ATTRIBUTE is the GeneralName \n   within it, and the CURRENT_INSTANCE is the GeneralName component within \n   that, while for the standalone subject/issuer DNs there's no \n   CURRENT_GROUP, the CURRENT_ATTRIBUTE is the subject or issuer DN, and the \n   CURRENT_INSTANCE is the DN component.\n   \n   This means that we can't select repeated instances of DN components in a \n   GeneralName (at least not without introducing a fourth level of nesting), \n   but the use of DNs in GeneralNames is practically nonexistent so this \n   shouldn't be an issue */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectDN( INOUT CERT_INFO *certInfoPtr, \n\t\t\t  IN_ATTRIBUTE_OPT const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t  IN_ENUM( SELECTION_OPTION ) const SELECTION_OPTION option )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE generalName = \\\n\t\t\t\t\t\t\tcertInfoPtr->currentSelection.generalName;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( ( option == MAY_BE_ABSENT && \\\n\t\t\t\tisDNSelectionComponent( certInfoType ) ) || \\\n\t\t\t  ( ( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT ) && \\\n\t\t\t\tcertInfoType == CRYPT_ATTRIBUTE_NONE ) );\n\n\tif( option == MAY_BE_ABSENT )\n\t\t{\n\t\t/* Try and select a DN based on the supplied attribute ID */\n\t\tswitch( certInfoType )\n\t\t\t{\n\t\t\tcase CRYPT_CERTINFO_SUBJECTNAME:\n\t\t\t\tselectSubjectName( certInfoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_CERTINFO_ISSUERNAME:\n\t\t\t\tselectIssuerName( certInfoPtr );\n\n\t\t\t\t/* If it's a self-signed certificate and the issuer name \n\t\t\t\t   isn't explicitly present then it must be implicitly \n\t\t\t\t   present as the subject name */\n\t\t\t\tif( DATAPTR_ISNULL( certInfoPtr->issuerName ) && \\\n\t\t\t\t\tTEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t\t\t\tselectSubjectName( certInfoPtr );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\n\t\t/* We've selected a built-in DN, remember that this isn't one in an\n\t\t   (optional) extension and clear the current DN component \n\t\t   selection.  In addition we clear the current extension cursor \n\t\t   since we've implicitly moved it away from the extensions to the\n\t\t   non-extension space of the built-in DNs */\n\t\tresetDNselection( certInfoPtr, FALSE );\n\t\tDATAPTR_SET( certInfoPtr->attributeCursor, NULL );\n\n\t\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's a DN already selected and there's no GeneralName selection\n\t   pending, we're done.  The latter can occur when we're selected a \n\t   GeneralName that doesn't exist yet but will be created on-demand when\n\t   the first component is added to it, in which case selecting the DN\n\t   should create it in the pending GeneralName rather than using the\n\t   currently-selected DN */\n\tif( certInfoPtr->currentSelection.dnPtr != NULL && \\\n\t\tcertInfoPtr->currentSelection.generalName == CRYPT_ATTRIBUTE_NONE )\n\t\treturn( CRYPT_OK );\n\n\tENSURES( option == MUST_BE_PRESENT || option == CREATE_IF_ABSENT );\n\n\t/* To select a DN in a GeneralName we first need to have a GeneralName\n\t   selected */\n\tstatus = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE, option );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we've now got a GeneralName selected, try and find a DN in it.  \n\t   The reason why we have to perform the explicit check is because if\n\t   the CREATE_IF_ABSENT option is used then the GeneralName has been\n\t   marked for creation when a field within it is added but won't \n\t   actually be created until the field is added further down */\n\tif( isGeneralNameSelected( certInfoPtr ) )\n\t\t{\n\t\t/* If there's a DN currently selected, we're done */\n\t\tif( checkAttributeProperty( certInfoPtr->attributeCursor, \\\n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_DN ) )\n\t\t\t{\n\t\t\tstatus = getAttributeDataDNPtr( certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t&certInfoPtr->currentSelection.dnPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tresetDNselection( certInfoPtr, FALSE );\n\t\t\tcertInfoPtr->currentSelection.dnInExtension = TRUE;\n\n\t\t\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* There's no DN selected, see if there's one present somewhere in\n\t\t   the extension */\n\t\tif( cryptStatusOK( findDnInGeneralName( certInfoPtr, TRUE ) ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If there's no DN present and we're not about to create one,\n\t\t   exit */\n\t\tif( option == MUST_BE_PRESENT )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t/* Create the DN in the currently selected GeneralName */\n\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, NULL, \n\t\t\t\t\t\t\t\t\t &generalName, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* We're being asked to instantiate the DN, create the attribute field\n\t   that contains it */\n\tstatus = addAttributeField( &certInfoPtr->attributes, generalName,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_DIRECTORYNAME, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tATTR_FLAG_NONE, &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Find the field that we've just created.  This is a newly-created\n\t   attribute so it's the only one present (i.e we don't have to worry\n\t   about finding one added at the end of the sequence of identical\n\t   attributes) and we also know that it must be present since we've\n\t   just created it.\n\t   \n\t   Note that we have to specify MAY_BE_ABSENT (even though we know that \n\t   it's present) because we're selecting an explicitly-specified \n\t   generalName, not an implicitly-present value as for MUST_BE_PRESENT */\n\treturn( selectGeneralName( certInfoPtr, generalName, MAY_BE_ABSENT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int selectDNComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isDNComponent( certInfoType ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t/* To select a DN component we first need to have a DN selected */\n\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE, MUST_BE_PRESENT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Remember the currently selected DN component */\n\tcertInfoPtr->currentSelection.dnComponent = certInfoType;\n\tcertInfoPtr->currentSelection.dnComponentCount = 0;\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Cursor Movement Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set certificate cursor information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setCursorCertChain( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\t\tconst int cursorMoveType )\t/* Values are -ve */\n\t{\n\tCERT_CERT_INFO *certChainInfo = certInfoPtr->cCertCert;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t  cursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\n\tswitch( cursorMoveType )\n\t\t{\n\t\tcase CRYPT_CURSOR_FIRST:\n\t\t\t/* Set the chain position to -1 (= CRYPT_ERROR) to indicate that \n\t\t\t   it's at the leaf certificate, which is logically at position \n\t\t\t   -1 in the chain */\n\t\t\tcertChainInfo->chainPos = CRYPT_ERROR;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_PREVIOUS:\n\t\t\t/* Adjust the chain position.  Note that the value can go to -1 \n\t\t\t   (= CRYPT_ERROR) to indicate that it's at the leaf certificate, \n\t\t\t   which is logically at position -1 in the chain */\n\t\t\tif( certChainInfo->chainPos < 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertChainInfo->chainPos--;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_NEXT:\n\t\t\tif( certChainInfo->chainPos >= certChainInfo->chainEnd - 1 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertChainInfo->chainPos++;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_LAST:\n\t\t\tcertChainInfo->chainPos = certChainInfo->chainEnd - 1;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CERTVAL\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setCursorValInfo( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\tconst int cursorMoveType )\t/* Values are -ve */\n\t{\n\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\tVALIDITY_INFO *validityInfoPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE );\n\tREQUIRES( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t  cursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\n\tswitch( cursorMoveType )\n\t\t{\n\t\tcase CRYPT_CURSOR_FIRST:\n\t\t\tcertValInfo->currentValidity = certValInfo->validityInfo;\n\t\t\tif( DATAPTR_ISNULL( certValInfo->currentValidity ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_PREVIOUS:\n\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->validityInfo );\n\t\t\tif( validityInfoPtr == NULL || \\\n\t\t\t\tDATAPTR_ISNULL( certValInfo->currentValidity ) || \\\n\t\t\t\tDATAPTR_SAME( certValInfo->validityInfo, \\\n\t\t\t\t\t\t\t  certValInfo->currentValidity ) )\n\t\t\t\t{\n\t\t\t\t/* No validity information or we're already at the start of \n\t\t\t\t   the list */\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t}\n\n\t\t\tcertValInfo->currentValidity = validityInfoPtr->prev;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_NEXT:\n\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\tif( validityInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tif( DATAPTR_ISNULL( validityInfoPtr->next ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertValInfo->currentValidity = validityInfoPtr->next;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_LAST:\n\t\t\t{\n\t\t\tVALIDITY_INFO *prevElementPtr;\n\n\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\tif( validityInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t\t/* Go to the end of the list */\n\t\t\tLOOP_LARGE( prevElementPtr = NULL, \n\t\t\t\t\t\tvalidityInfoPtr != NULL,\n\t\t\t\t\t\t( prevElementPtr = validityInfoPtr,\n\t\t\t\t\t\t  validityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( validityInfoPtr->next ) ) );\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tDATAPTR_SET( certValInfo->currentValidity, prevElementPtr );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setCursorRevInfo( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST )\n\t\t\t\t\t\t\t\tconst int cursorMoveType )\t/* Values are -ve */\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tREVOCATION_INFO *revInfoPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tREQUIRES( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t  cursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\n\tswitch( cursorMoveType )\n\t\t{\n\t\tcase CRYPT_CURSOR_FIRST:\n\t\t\tcertRevInfo->currentRevocation = certRevInfo->revocations;\n\t\t\tif( DATAPTR_ISNULL( certRevInfo->currentRevocation ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_PREVIOUS:\n\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->revocations );\n\t\t\tif( revInfoPtr == NULL || \\\n\t\t\t\tDATAPTR_ISNULL( certRevInfo->currentRevocation ) || \\\n\t\t\t\tDATAPTR_SAME( certRevInfo->revocations, \\\n\t\t\t\t\t\t\t  certRevInfo->revocations ) )\n\t\t\t\t{\n\t\t\t\t/* No revocations or we're already at the start of the \n\t\t\t\t   list */\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t}\n\n\t\t\tcertRevInfo->currentRevocation = revInfoPtr->prev;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_NEXT:\n\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\tif( revInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tif( DATAPTR_ISNULL( revInfoPtr->next ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertRevInfo->currentRevocation = revInfoPtr->next;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_LAST:\n\t\t\t{\n\t\t\tREVOCATION_INFO *prevElementPtr;\n\n\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\tif( revInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t\t/* Go to the end of the list.  We use FAILSAFE_ITERATIONS_MAX as \n\t\t\t   the bound because CRLs can become enormous */\n\t\t\tLOOP_LARGE( prevElementPtr = NULL, \n\t\t\t\t\t\trevInfoPtr != NULL,\n\t\t\t\t\t\t( prevElementPtr = revInfoPtr,\n\t\t\t\t\t\t  revInfoPtr = DATAPTR_GET( revInfoPtr->next ) ) );\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tDATAPTR_SET( certRevInfo->currentRevocation, prevElementPtr );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREV */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setCertificateCursor( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t  IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\tconst int cursorMoveType )\t/* Values are -ve */\n\t{\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t  cursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\n\t/* If it's a single certificate, there's nothing to do.  See the \n\t   CRYPT_CERTINFO_CURRENT_CERTIFICATE ACL comment for why we \n\t   (apparently) allow cursor movement movement in single certificates */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\tREQUIRES( certInfoPtr->cCertCert->chainEnd == 0 );\n\n\t\treturn( ( cursorMoveType == CRYPT_CURSOR_FIRST || \\\n\t\t\t\t  cursorMoveType == CRYPT_CURSOR_LAST ) ? \\\n\t\t\t\tCRYPT_OK : CRYPT_ERROR_NOTFOUND );\n\t\t}\n\t\t\t\n\t/* Move the cursor in an object-specific manner */\n\tswitch( certInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\treturn( setCursorCertChain( certInfoPtr, cursorMoveType ) );\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\treturn( setCursorValInfo( certInfoPtr, cursorMoveType ) );\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\treturn( setCursorRevInfo( certInfoPtr, cursorMoveType ) );\n#endif /* USE_CERTREV */\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAttribute Cursor Movement Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set attribute cursor information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setAttributeCursorDN( INOUT SELECTION_INFO *currentSelection,\n\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\t\tconst int moveType )\t/* Values are -ve */\n\t{\n\tDATAPTR_DN dnComponentList;\n\tint count = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtr( currentSelection, sizeof( SELECTION_INFO ) ) );\n\n\tREQUIRES( moveType <= CRYPT_CURSOR_FIRST && \\\n\t\t\t  moveType >= CRYPT_CURSOR_LAST );\t/* Values are -ve */\n\tREQUIRES( currentSelection->dnPtr != NULL );\n\n\tdnComponentList = *currentSelection->dnPtr;\n\n\tswitch( moveType )\n\t\t{\n\t\tcase CRYPT_CURSOR_FIRST:\n\t\t\t/* Select the first instance of this attribute */\n\t\t\tcurrentSelection->dnComponentCount = 0;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_PREVIOUS:\n\t\t\t/* Adjust the instance selection value */\n\t\t\tif( currentSelection->dnComponentCount <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcurrentSelection->dnComponentCount--;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CURSOR_NEXT:\n\t\tcase CRYPT_CURSOR_LAST:\n\t\t\t/* Find the number of occurrences of the DN component that we're \n\t\t\t   enumerating and use that to move the cursor, which is \n\t\t\t   actually just an iteration count of the number of components \n\t\t\t   to skip */\n\t\t\tLOOP_MED_INITINC( count = 0, count++ )\n\t\t\t\t{\n\t\t\t\tint dummy, status;\n\n\t\t\t\tstatus = getDNComponentValue( dnComponentList, \n\t\t\t\t\t\t\t\t\t\t\t  currentSelection->dnComponent,\n\t\t\t\t\t\t\t\t\t\t\t  count + 1, NULL, 0, &dummy );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tif( moveType == CRYPT_CURSOR_LAST )\n\t\t\t\tcurrentSelection->dnComponentCount = count;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( currentSelection->dnComponentCount >= count )\n\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\tcurrentSelection->dnComponentCount++;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setAttributeCursorRelative( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int value )\t/* Values are -ve */\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t  certInfoType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t  certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\tREQUIRES( value <= CRYPT_CURSOR_FIRST && \\\n\t\t\t  value >= CRYPT_CURSOR_LAST );\t\t/* Values are -ve */\n\n\t/* If we're moving to a field in an extension and there's a saved \n\t   GeneralName selection present (which means that it's for a \n\t   GeneralName that's not present yet but has been tagged for creation \n\t   the next time that an attribute is added) then we can't move to a \n\t   field in it since it hasn't been created yet */\n\tif( certInfoType != CRYPT_ATTRIBUTE_CURRENT_GROUP && \\\n\t\tcertInfoPtr->currentSelection.generalName != CRYPT_ATTRIBUTE_NONE )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* The subject and issuer DNs aren't standard certificate extensions but \n\t   (for cursor-positioning purposes) can be manipulated as such by moving\n\t   from one instance (e.g. one OU) to the next.  If there's no current \n\t   attribute selected but there is a subject or issuer DN and a component \n\t   within that DN selected (performing this DN selection inmplicitly de-\n\t   selects any attribute, otherwise the selected DN could be one that's\n\t   within a GeneralName in an attribute), then we allow a pseudo-move \n\t   to/from identical DN components */\n\tif( certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE && \\\n\t\tDATAPTR_ISNULL( certInfoPtr->attributeCursor ) && \\\n\t\tcertInfoPtr->currentSelection.dnPtr != NULL && \\\n\t\tcertInfoPtr->currentSelection.dnComponent != CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\treturn( setAttributeCursorDN( &certInfoPtr->currentSelection, \n\t\t\t\t\t\t\t\t\t  value ) );\n\t\t}\n\n\t/* If it's an absolute positioning code, pre-set the attribute cursor \n\t   if required */\n\tif( value == CRYPT_CURSOR_FIRST || value == CRYPT_CURSOR_LAST )\n\t\t{\n\t\tif( DATAPTR_ISNULL( certInfoPtr->attributes ) )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t/* It's a full-attribute positioning code, reset the attribute \n\t\t   cursor to the start of the list before we try to move it */\n\t\tif( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP )\n\t\t\tcertInfoPtr->attributeCursor = certInfoPtr->attributes;\n\t\telse\n\t\t\t{\n\t\t\t/* It's a field or component positioning code, initialise the \n\t\t\t   attribute cursor if necessary */\n\t\t\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\t\t\tcertInfoPtr->attributeCursor = certInfoPtr->attributes;\n\t\t\t}\n\n\t\t/* If there are no attributes present return the appropriate error \n\t\t   code */\n\t\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a relative positioning code, return a not-inited error \n\t\t   rather than a not-found error if the cursor isn't set since there \n\t\t   may be attributes present but the cursor hasn't been initialised \n\t\t   yet by selecting the first or last absolute attribute */\n\t\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Move the attribute cursor */\n\tattributeCursor = certMoveAttributeCursor( certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t\t\t\t   certInfoType, value );\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tcertInfoPtr->attributeCursor = attributeCursor;\n\tsyncSelection( certInfoPtr );\n\n\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAttributeCursor( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\tIN const int value )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( sanityCheckSelectionInfo( certInfoPtr ) );\n\tREQUIRES( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t  certInfoType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t  certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\tREQUIRES( ( value <= CRYPT_CURSOR_FIRST && \\\n\t\t\t\tvalue >= CRYPT_CURSOR_LAST ) || \\\n\t\t\t  isValidExtension( value ) || \\\n\t\t\t  ( certInfoType == CRYPT_ATTRIBUTE_CURRENT && \\\n\t\t\t\t( value == CRYPT_CERTINFO_ISSUERNAME || \\\n\t\t\t\t  value == CRYPT_CERTINFO_SUBJECTNAME ) ) || \\\n\t\t\t  ( certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE && \\\n\t\t\t\t( isDNComponent( value ) || \\\n\t\t\t\t  isGeneralNameComponent( value ) ) ) );\n\t\t\t  /* See comment below for the odd CRYPT_CURSOR_xxx comparison */\n\n\t/* If the new position is specified relative to a previous position, try\n\t   and move to that position.  Note that the seemingly illogical\n\t   comparison is used because the cursor positioning codes are negative\n\t   values */\n\tif( value <= CRYPT_CURSOR_FIRST && value >= CRYPT_CURSOR_LAST )\n\t\t{\n\t\treturn( setAttributeCursorRelative( certInfoPtr, certInfoType, \n\t\t\t\t\t\t\t\t\t\t\tvalue ) );\n\t\t}\n\tENSURES( value >= CRYPT_CERTINFO_ISSUERNAME && \\\n\t\t\t value <= CRYPT_CERTINFO_LAST );\n\n\t/* It's a field in an extension, try and move to the start of the\n\t   extension that contains this field */\n\tif( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\tattributePtr = findAttribute( certInfoPtr->attributes, value, TRUE );\n\t\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\tcertInfoPtr->attributeCursor = attributePtr;\n\t\tsyncSelection( certInfoPtr );\n\n\t\tENSURES( sanityCheckSelectionInfo( certInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Beyond the standard attribute-selection values there are two special\n\t   cases that we have to deal with.  The subject and issuer DN aren't\n\t   standard attributes but can be selected as if they were in order to\n\t   perform extended operations on them, and GeneralName components are \n\t   deeply nested enough that what's a per-instance operation for any \n\t   other attribute type becomes an attribute subtype in its own right */\n\tENSURES( certInfoType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\tENSURES( isValidExtension( value ) || \\\n\t\t\t ( certInfoType == CRYPT_ATTRIBUTE_CURRENT && \\\n\t\t\t   ( value == CRYPT_CERTINFO_ISSUERNAME || \\\n\t\t\t\t value == CRYPT_CERTINFO_SUBJECTNAME ) ) || \n\t\t\t ( certInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE && \\\n\t\t\t\t( isDNComponent( value ) || \\\n\t\t\t\t  isGeneralNameComponent( value ) ) ) );\n\n\t/* If it's a GeneralName selection or GeneralName component, locate the \n\t   attribute field that it corresponds to.  Note the difference in \n\t   selection options, for the GeneralName as a whole we're indicating\n\t   which GeneralName we want to work with, including potentially \n\t   creating it when we set the first field in it while for a \n\t   GeneralName component we're merely selecting a field in an already-\n\t   existing GeneralName.\n\t   \n\t   If the returned status is a parameter error then we have to translate \n\t   it from the form { certInfoPtr, value } in selectXXX() to \n\t   { certInfoPtr, attribute_cursor, value } in this function, so it goes\n\t   from being a CRYPT_ARGERROR_VALUE to a CRYPT_ARGERROR_NUM1 */\n\tif( isGeneralNameSelectionComponent( value ) )\n\t\t{\n\t\tstatus = selectGeneralName( certInfoPtr, value, MAY_BE_ABSENT );\n\t\treturn( ( status == CRYPT_ARGERROR_VALUE ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tif( isGeneralNameComponent( value ) )\n\t\t{\n\t\tstatus = selectGeneralNameComponent( certInfoPtr, value );\n\t\treturn( ( status == CRYPT_ARGERROR_VALUE ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\n\t/* If it's a DN, select it.  If it's a DN component, locate the RDN that \n\t   it corresponds to */\n\tif( value == CRYPT_CERTINFO_ISSUERNAME || \\\n\t\tvalue == CRYPT_CERTINFO_SUBJECTNAME )\n\t\treturn( selectDN( certInfoPtr, value, MAY_BE_ABSENT ) );\n\tif( isDNComponent( value ) )\n\t\treturn( selectDNComponent( certInfoPtr, value ) );\n\n\t/* It's a standard attribute field, try and locate it */\n\treturn( moveCursorToField( certInfoPtr, value ) );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_del.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDelete Certificate Components\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the head of a list of attributes for per-entry attributes, i.e. ones\n   for an individual entry in an object like a CRL rather than for the CRL \n   as a whole */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic DATAPTR_ATTRIBUTE *getEntryAttributeListHead( const CERT_INFO *certInfoPtr )\n\t{\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tswitch( certInfoPtr->type )\n\t\t{\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\t{\n\t\t\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\t\t\tVALIDITY_INFO *validityInfoPtr;\n\n\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\tif( validityInfoPtr == NULL )\n\t\t\t\treturn( NULL );\n\t\t\treturn( &validityInfoPtr->attributes );\n\t\t\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t{\n\t\t\tconst CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\t\tREVOCATION_INFO *revInfoPtr;\n\n\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\tif( revInfoPtr == NULL )\n\t\t\t\treturn( NULL );\n\t\t\treturn( &revInfoPtr->attributes );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n\t\tdefault:\n\t\t\tretIntError_Null();\n\t\t}\n\n\tretIntError_Null();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDelete a Certificate Component\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete a certificate attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int deleteCertAttribute( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tDATAPTR_ATTRIBUTE *attributeListHeadPtrPtr, attributePtr;\n\tconst BOOLEAN isRevocationEntry = \\\n\t\t\t\tisRevocationEntryComponent( certInfoType ) ? TRUE : FALSE;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\n\t/* Try and find this attribute in the attribute list */\n\tattributePtr = findAttributeComponent( certInfoPtr, certInfoType );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* If this is a non-present field with a default value in a present \n\t   attribute (so that its value can be read but the field itself isn't \n\t   really there) there isn't any terribly satisfactory return code to \n\t   indicate this.  Returning CRYPT_OK is wrong because the caller can \n\t   keep deleting the same field over and over, and returning \n\t   CRYPT_ERROR_NOTFOUND is wrong because the caller may have added the \n\t   attribute at an earlier date but it was never written because it had \n\t   the default value so that to the caller it appears that the field \n\t   they added has been lost.  The least unexpected action is probably to \n\t   return CRYPT_OK */\n\tif( checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_DEFAULTVALUE ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If this is a complete attribute (e.g. CRYPT_CERTINFO_SUBJECTINFOACCESS\n\t   rather than one of its fields like \n\t   CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY), delete the entire attribute */\n\tif( checkAttributeProperty( attributePtr,\n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_COMPLETEATRIBUTE ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE fieldAttributePtr;\n\n\t\t/* If the certificate has a fleur de lis make sure that it can't be \n\t\t   scraped off */\n\t\tfieldAttributePtr = findAttribute( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t   certInfoType, TRUE );\n\t\tif( DATAPTR_ISSET( fieldAttributePtr ) && \\\n\t\t\tcheckAttributeProperty( fieldAttributePtr, \n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_LOCKED ) )\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\t/* This is an ID for an entire (constructed) attribute, delete the \n\t\t   attribute */\n\t\tif( isRevocationEntry )\n\t\t\t{\n\t\t\tattributeListHeadPtrPtr = getEntryAttributeListHead( certInfoPtr );\n\t\t\tENSURES( attributeListHeadPtrPtr != NULL );\n\t\t\t}\n\t\telse\n\t\t\tattributeListHeadPtrPtr = &certInfoPtr->attributes;\n\t\treturn( deleteCompleteAttribute( attributeListHeadPtrPtr, \n\t\t\t\t\t\t\t\t\t\t &certInfoPtr->attributeCursor, certInfoType,\n\t\t\t\t\t\t\t\t\t\t certInfoPtr->currentSelection.dnPtr ) );\n\t\t}\n\n\t/* If the certificate has a fleur de lis make sure that it can't be \n\t   scraped off */\n\tif( checkAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_LOCKED ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* It's a single field, delete that */\n\tif( isRevocationEntry )\n\t\t{\n\t\tattributeListHeadPtrPtr = getEntryAttributeListHead( certInfoPtr );\n\t\tENSURES( attributeListHeadPtrPtr != NULL );\n\t\t}\n\telse\n\t\tattributeListHeadPtrPtr = &certInfoPtr->attributes;\n\n\treturn( deleteAttributeField( attributeListHeadPtrPtr,\n\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, attributePtr,\n\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr ) );\n\t}\n\n/* Delete a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\n\t/* If it's a GeneralName or DN component, delete it.  These are \n\t   special-case attribute values so they have to come before the \n\t   general attribute-handling code */\n\tif( isGeneralNameSelectionComponent( certInfoType ) )\n\t\t{\n\t\t/* Check whether this GeneralName is present */\n\t\tstatus = selectGeneralName( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t\t\tMUST_BE_PRESENT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Delete each field in the GeneralName */\n\t\treturn( deleteCompositeAttributeField( &certInfoPtr->attributes,\n\t\t\t\t\t\t&certInfoPtr->attributeCursor, \n\t\t\t\t\t\tcertInfoPtr->attributeCursor,\n\t\t\t\t\t\tcertInfoPtr->currentSelection.dnPtr ) );\n\t\t}\n\tif( isGeneralNameComponent( certInfoType ) )\n\t\t{\n\t\tSELECTION_STATE selectionState;\n\t\tDATAPTR_ATTRIBUTE attributePtr DUMMY_INIT_STRUCT;\n\n\t\t/* Find the requested GeneralName component.  Since \n\t\t   selectGeneralNameComponent() changes the current selection within \n\t\t   the GeneralName, we save the selection state around the call */\n\t\tsaveSelectionState( selectionState, certInfoPtr );\n\t\tstatus = selectGeneralNameComponent( certInfoPtr, certInfoType );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tattributePtr = certInfoPtr->attributeCursor;\n\t\trestoreSelectionState( selectionState, certInfoPtr );\n\t\tif( cryptStatusError( status ))\n\t\t\treturn( status );\n\t\tENSURES( DATAPTR_ISSET( attributePtr ) );\n\n\t\t/* Delete the field within the GeneralName */\n\t\treturn( deleteAttributeField( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t  attributePtr,\n\t\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr ) );\n\t\t}\n\tif( isDNComponent( certInfoType ) )\n\t\t{\n\t\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t   MUST_BE_PRESENT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = deleteDNComponent( certInfoPtr->currentSelection.dnPtr,\n\t\t\t\t\t\t\t\t\t\tcertInfoType, NULL, 0 );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* If it's standard certificate or CMS attribute, delete it */\n\tif( isValidExtension( certInfoType ) )\n\t\treturn( deleteCertAttribute( certInfoPtr, certInfoType ) );\n\n\t/* If it's anything else, handle it specially */\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_SELFSIGNED:\n\t\t\tif( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tCLEAR_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_CURRENT_CERTIFICATE:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tif( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP )\n\t\t\t\t{\n\t\t\t\treturn( deleteAttribute( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t &certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t\t\t certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t\t\t certInfoPtr->currentSelection.dnPtr ) );\n\t\t\t\t}\n\n\t\t\t/* The current component and field are essentially the same \n\t\t\t   thing since a component is one of a set of entries in a \n\t\t\t   multivalued field, thus they're handled identically */\n\t\t\treturn( deleteAttributeField( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->attributeCursor,\n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr ) );\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_USAGE:\n\t\t\tif( certInfoPtr->cCertCert->trustedUsage == CRYPT_ERROR )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertInfoPtr->cCertCert->trustedUsage = CRYPT_ERROR;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_IMPLICIT:\n\t\t\treturn( krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t\t IMESSAGE_USER_TRUSTMGMT,\n\t\t\t\t\t\t\t\t\t &certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t MESSAGE_TRUSTMGMT_DELETE ) );\n\n\t\tcase CRYPT_CERTINFO_VALIDFROM:\n\t\tcase CRYPT_CERTINFO_THISUPDATE:\n\t\t\tif( certInfoPtr->startTime <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertInfoPtr->startTime = 0;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_VALIDTO:\n\t\tcase CRYPT_CERTINFO_NEXTUPDATE:\n\t\t\tif( certInfoPtr->endTime <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertInfoPtr->endTime = 0;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_SUBJECTNAME:\n\t\t\tif( isSubjectNameSelected( certInfoPtr ) )\n\t\t\t\t{\n\t\t\t\t/* This is the currently selected DN, deselect it before \n\t\t\t\t   deleting it */\n\t\t\t\tcertInfoPtr->currentSelection.dnPtr = NULL;\n\t\t\t\t}\n\t\t\tdeleteDN( &certInfoPtr->subjectName );\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_REVOCATIONDATE:\n\t\t\t{\n\t\t\ttime_t *revocationTimePtr = ( time_t * ) \\\n\t\t\t\t\t\t\tgetRevocationTimePtr( certInfoPtr );\n\n\t\t\tif( revocationTimePtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*revocationTimePtr = 0;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTINFO_PKIUSER_RA:\n\t\t\tif( !certInfoPtr->cCertUser->isRA )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcertInfoPtr->cCertUser->isRA = FALSE;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PKIUSER */\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_get.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGet/Delete Certificate Components\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet Certificate Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an attribute in an attribute list, either in the overall certificate \n   object attribute list or a per-entry attribute list.  This can also \n   return entries with two special-case properties: \n   \n\tATTRIBUTE_PROPERTY_DEFAULTVALUE: The field has a default value and isn't \n\t\tpresent in the list, but some other field in the same attribute is \n\t\tpresent.  For example if CRYPT_CERTINFO_ISSUINGDIST_FULLNAME were \n\t\tpresent in the attribute list than an attempt to read \n\t\tCRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL, which is declared 'DEFAULT \n\t\tFALSE', would return an entry with this property.\n\n\tATTRIBUTE_PROPERTY_COMPLETEATTRIBUTE: The field is an identifier for a\n\t\tcomplete attribute, e.g. CRYPT_CERTINFO_AUTHORITYINFOACCESS, for \n\t\twhich only the individual CRYPT_CERTINFO_AUTHORITYINFO_xyz fields \n\t\tcan be present */\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nDATAPTR_ATTRIBUTE findAttributeComponent( IN const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType )\n\t{\n#ifdef USE_CERTREV\n\tconst CERT_REV_INFO *certRevInfo;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tREVOCATION_INFO *currentRevocation;\n#endif /* USE_CERTREV */\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES_D( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES_D( isEnumRange( certInfoType, CRYPT_ATTRIBUTE ) );\n\n\t/* If it's just a general certificate attribute, return it to the \n\t   caller */\n\tif( !isRevocationEntryComponent( certInfoType ) )\n\t\t{\n\t\treturn( findAttributeFieldEx( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t  certInfoType ) );\n\t\t}\n\n\t/* It's an attribute that's normally present in a CRL or CRL-equivalent\n\t   object, however it may also be present in a revocation request for \n\t   which attributes work like they do for general certificates */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\treturn( findAttributeFieldEx( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t  certInfoType ) );\n\t\t}\n\n#ifdef USE_CERTVAL\n\t/* It's a per-entry attribute, if it's an RTCS per-entry attribute get \n\t   the attribute from the currently selected entry */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t{\n\t\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\t\tVALIDITY_INFO *validityInfoPtr;\n\n\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\tif( validityInfoPtr == NULL )\n\t\t\treturn( DATAPTR_NULL );\n\t\treturn( findAttributeFieldEx( validityInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t  certInfoType ) );\n\t\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\tENSURES_D( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\t   certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\t   certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE || \\\n\t\t\t   certInfoPtr->type == CRYPT_ICERTTYPE_REVINFO );\n\n\t/* It's a CRL or OCSP per-entry attribute, get the attribute from the \n\t   currently selected entry */\n\tcertRevInfo = certInfoPtr->cCertRev;\n\tcurrentRevocation = DATAPTR_GET( certRevInfo->currentRevocation );\n\tif( currentRevocation == NULL )\n\t\treturn( DATAPTR_NULL );\n\tattributePtr = findAttributeFieldEx( currentRevocation->attributes, \n\t\t\t\t\t\t\t\t\t\t certInfoType );\n\tif( DATAPTR_ISNULL( attributePtr ) && \\\n\t\tcertInfoType == CRYPT_CERTINFO_CRLREASON )\n\t\t{\n\t\t/* Revocation reason codes are actually a single range of values \n\t\t   spread across two different extensions so if we don't find the \n\t\t   value as a straight cRLReason we try again for a cRLExtReason.  \n\t\t   If we've been specifically asked for a cRLExtReason we don't go \n\t\t   the other way because the caller (presumably) specifically wants \n\t\t   the extended reason code */\n\t\tattributePtr = findAttributeFieldEx( currentRevocation->attributes,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CRLEXTREASON );\n\t\t}\n\n\treturn( attributePtr );\n#else\n\treturn( DATAPTR_NULL );\n#endif /* USE_CERTREV */\n\t}\n\n/* Get a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int getCertAttributeComponent( const CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\t\t\t  OUT int *value )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( certInfoType, CRYPT_ATTRIBUTE ) );\n\n\t/* Clear return values */\n\t*value = 0;\n\n\t/* Try and find this attribute in the attribute list */\n\tattributePtr = findAttributeComponent( certInfoPtr, certInfoType );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* If this is a non-present field with a default value in an attribute \n\t   for which some other field is present (e.g. if we're trying to read\n\t   CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY, which is declared\n\t   DEFAULT FALSE, and CRYPT_CERTINFO_ISSUINGDIST_FULLNAME is present)\n\t   then we regard any default fields in the same attribute to be\n\t   (pseudo)-present, so we return the default value */\n\tif( checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_DEFAULTVALUE ) )\n\t\t{\n\t\tint defaultValue, status;\n\t\t\n\t\tstatus = defaultValue = getDefaultFieldValue( certInfoType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t*value = defaultValue;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we've been given the ID for a complete attribute (e.g. \n\t   CRYPT_CERTINFO_AUTHORITYINFOACCESS, for which only the individual \n\t   CRYPT_CERTINFO_AUTHORITYINFO_xyz fields can be present), return a \n\t   boolean value indicating that the overall attribute is present */\n\tif( checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_COMPLETEATRIBUTE ) )\n\t\t{\n\t\t*value = TRUE;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the attribute component value */\n\treturn( getAttributeDataValue( attributePtr, value ) );\n\t}\n\n/* Create a copy of a certificate object for external use.  This is used \n   principally to sanitise internal certificate objects, for example if \n   they're attached to a private key or for internal use only.  Since the \n   object can be either a standalone certificate or a complete certificate \n   chain we have to process it somewhat indirectly rather than just \n   instantiating a new certificate from the encoded certificate data.\n\n   It's also used to convert to/from data-only certificates, for example to \n   convert from a stored data-only certificate to a full certificate capable \n   of being used for signature checking, this is easier than trying to \n   retroactively attach a public-key context to a data-only certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getCertCopy( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertCopy,\n\t\t\t\t\t\tconst BOOLEAN isDataOnlyCert )\n\t{\n\tconst CRYPT_CERTFORMAT_TYPE formatType = \\\n\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE ) ? \\\n\t\tCRYPT_CERTFORMAT_CERTIFICATE : CRYPT_CERTFORMAT_CERTCHAIN;\n\tMESSAGE_DATA msgData;\n\tBYTE certData[ 2048 + 8 ], *certDataPtr = certData;\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO  ) ) );\n\tassert( isWritePtr( iCertCopy, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\tREQUIRES( isDataOnlyCert == TRUE || isDataOnlyCert == FALSE );\n\n\t/* Clear return value */\n\t*iCertCopy = CRYPT_ERROR;\n\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( certInfoPtr->objectHandle, \n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t  formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( msgData.length > 2048 )\n\t\t{\n\t\tREQUIRES( rangeCheck( msgData.length, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( certDataPtr = clAlloc( \"getCertCopy\", \\\n\t\t\t\t\t\t\t\t\t msgData.length + 8 ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tsetMessageData( &msgData, certDataPtr, msgData.length );\n\tstatus = krnlSendMessage( certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  formatType );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tsetMessageCreateObjectIndirectInfoEx( &createInfo, certDataPtr,\n\t\t\t\t\t\t\tmsgData.length, certInfoPtr->type,\n\t\t\t\t\t\t\tisDataOnlyCert ? KEYMGMT_FLAG_DATAONLY_CERT : \\\n\t\t\t\t\t\t\t\t\t\t\t KEYMGMT_FLAG_NONE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT, \n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*iCertCopy = createInfo.cryptHandle;\n\t\t}\n\tif( certDataPtr != certData )\n\t\tclFree( \"getCertCopy\", certDataPtr );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet a Certificate Component\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t  OUT_INT_Z int *certInfo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( certInfo, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\n\t/* Clear return value */\n\t*certInfo = 0;\n\n\t/* If it's a GeneralName or DN component, return it.  These are \n\t   special-case attribute values so they have to come before the \n\t   general attribute-handling code */\n\tif( isGeneralNameSelectionComponent( certInfoType ) )\n\t\t{\n\t\tSELECTION_STATE savedState;\n\n\t\t/* Determine whether the given component is present or not.  This\n\t\t   has a somewhat odd status return since it returns the found/\n\t\t   notfound status in the return code as well as the returned value,\n\t\t   which mirrors the behaviour when reading extension-present\n\t\t   pseudo-attributes */\n\t\tsaveSelectionState( savedState, certInfoPtr );\n\t\tstatus = selectGeneralName( certInfoPtr, certInfoType, \n\t\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\t\tMUST_BE_PRESENT );\n\t\t\t}\n\t\trestoreSelectionState( savedState, certInfoPtr );\n\t\t*certInfo = cryptStatusOK( status ) ? TRUE : FALSE;\n\n\t\treturn( status );\n\t\t}\n\tif( isGeneralNameComponent( certInfoType ) )\n\t\t{\n\t\tSELECTION_STATE savedState;\n\n\t\t/* Find the requested GeneralName component and return and \n\t\t   indication of its presence to the caller.  Since \n\t\t   selectGeneralNameComponent() changes the current selection within \n\t\t   the GeneralName, we save the selection state around the call */\n\t\tsaveSelectionState( savedState, certInfoPtr );\n\t\tstatus = selectGeneralNameComponent( certInfoPtr, certInfoType );\n\t\trestoreSelectionState( savedState, certInfoPtr );\n\t\t*certInfo = cryptStatusOK( status ) ? TRUE : FALSE;\n\n\t\treturn( status );\n\t\t}\n\n\t/* If it's standard certificate or CMS attribute, return it */\n\tif( isValidExtension( certInfoType ) )\n\t\t{\n\t\treturn( getCertAttributeComponent( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t\t\t\t   certInfo ) );\n\t\t}\n\n\t/* If it's anything else, handle it specially */\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_SELFSIGNED:\n\t\t\t*certInfo = TEST_FLAG( certInfoPtr->flags, \n\t\t\t\t\t\t\t\t   CERT_FLAG_SELFSIGNED ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_IMMUTABLE:\n\t\t\t*certInfo = ( certInfoPtr->certificate != NULL ) ? TRUE: FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_XYZZY:\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\t\t/* Check for the presence of the XYZZY policy OID */\n\t\t\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CERTPOLICYID,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t\t{\n\t\t\t\tvoid *policyOidPtr;\n\t\t\t\tint policyOidLength;\n\n\t\t\t\tstatus = getAttributeDataPtr( attributePtr, &policyOidPtr, \n\t\t\t\t\t\t\t\t\t\t\t  &policyOidLength );\n\t\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t\tpolicyOidLength == sizeofOID( OID_CRYPTLIB_XYZZYCERT ) && \\\n\t\t\t\t\t!memcmp( policyOidPtr, OID_CRYPTLIB_XYZZYCERT,\n\t\t\t\t\t\t\t sizeofOID( OID_CRYPTLIB_XYZZYCERT ) ) )\n\t\t\t\t\t{\n\t\t\t\t\t*certInfo = TRUE;\n\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* It's not a XYZZY certificate */\n\t\t\t*certInfo = FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_CERTINFO_CERTTYPE:\n\t\t\t*certInfo = certInfoPtr->type;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_CURRENT_CERTIFICATE:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\t{\n\t\t\tCRYPT_ATTRIBUTE_TYPE infoID;\n\n\t\t\t/* The subject and issuer DNs are treated as pseudo-attributes \n\t\t\t   for manipulation purposes, so if these are selected \n\t\t\t   (indicated by there being no attribute selected since \n\t\t\t   selecting the pseudo-attribute DNs deselects any actual\n\t\t\t   attributes) we have to provide special-case handling for \n\t\t\t   them */\n\t\t\tif( DATAPTR_ISNULL( certInfoPtr->attributeCursor ) )\n\t\t\t\t{\n\t\t\t\tconst SELECTION_INFO *currentSelection = \\\n\t\t\t\t\t\t\t&certInfoPtr->currentSelection;\n\n\t\t\t\tswitch( certInfoType )\n\t\t\t\t\t{\n\t\t\t\t\tcase CRYPT_CERTINFO_CURRENT_CERTIFICATE:\n\t\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\t\t\t\t\t/* These selection types don't apply to DNs */\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\t\t\t\t\tif( isSubjectNameSelected( certInfoPtr) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t*certInfo = CRYPT_CERTINFO_SUBJECTNAME;\n\t\t\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tif( isIssuerNameSelected( certInfoPtr ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t*certInfo = CRYPT_CERTINFO_ISSUERNAME;\n\t\t\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\t\t\t\tif( currentSelection->dnComponent != CRYPT_ATTRIBUTE_NONE )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t*certInfo = currentSelection->dnComponent;\n\t\t\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tretIntError();\n\t\t\t\t\t}\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\n\t\t\t/* The current component and field are usually the same thing \n\t\t\t   since a component is one of a set of entries in a multivalued \n\t\t\t   field, however in the case of complex subtypes (attribute ->\n\t\t\t   generalName -> generalName field) they can be distinct \n\t\t\t   values.  To handle this we try for a field ID and if \n\t\t\t   that's not available return the component ID */\n\t\t\tswitch( certInfoType )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\t\t\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t &infoID, NULL, NULL );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRYPT_CERTINFO_CURRENT_CERTIFICATE:\n\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\t\t\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t NULL, &infoID, NULL );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\t\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t NULL, NULL, &infoID );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t\t NULL, &infoID, NULL );\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t*certInfo = infoID;\n\t\t\treturn( status );\n\t\t\t}\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_USAGE:\n\t\t\tif( certInfoPtr->cCertCert->trustedUsage == CRYPT_ERROR )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*certInfo = certInfoPtr->cCertCert->trustedUsage;\n \t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_IMPLICIT:\n\t\t\tstatus = krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_USER_TRUSTMGMT,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  MESSAGE_TRUSTMGMT_CHECK );\n\t\t\t*certInfo = cryptStatusOK( status ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_SIGNATURELEVEL:\n\t\t\t*certInfo = certInfoPtr->cCertRev->signatureLevel;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREV */\n\n\t\tcase CRYPT_CERTINFO_VERSION:\n\t\t\t*certInfo = certInfoPtr->version;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_ISSUERNAME:\n\t\tcase CRYPT_CERTINFO_SUBJECTNAME:\n\t\t\t{\n\t\t\tconst DATAPTR_DN dnPtr = \\\n\t\t\t\t\t( certInfoType == CRYPT_CERTINFO_ISSUERNAME ) ? \\\n\t\t\t\t\tcertInfoPtr->issuerName : certInfoPtr->subjectName;\n\n\t\t\tif( DATAPTR_ISNULL( dnPtr ) ) \n\t\t\t\t{\n\t\t\t\t*certInfo = FALSE;\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t}\n\t\t\t*certInfo = TRUE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_REVOCATIONSTATUS:\n\t\t\t{\n\t\t\tconst CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\tif( revInfoPtr == NULL )\n\t\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->revocations );\n\t\t\tif( revInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*certInfo = revInfoPtr->status;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTINFO_CERTSTATUS:\n\t\t\t{\n\t\t\tconst CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\t\t\tconst VALIDITY_INFO *validityInfoPtr;\n\n\t\t\tif( DATAPTR_ISSET( certValInfo->currentValidity ) )\n\t\t\t\t{\n\t\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\t\tENSURES( validityInfoPtr != NULL );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->validityInfo );\n\n\t\t\tif( validityInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*certInfo = validityInfoPtr->extStatus;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTINFO_PKIUSER_RA:\n\t\t\t*certInfo = certInfoPtr->cCertUser->isRA;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PKIUSER */\n\n\t\tcase CRYPT_IATTRIBUTE_CERTKEYALGO:\n\t\t\t*certInfo = certInfoPtr->publicKeyAlgo;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_CERTHASHALGO:\n\t\t\t*certInfo = certInfoPtr->cCertCert->hashAlgo;\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_IATTRIBUTE_REQFROMRA:\n\t\t\t*certInfo = certInfoPtr->cCertReq->requestFromRA;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREQ */\n\n\t\tcase CRYPT_IATTRIBUTE_CERTCOPY:\n\t\t\t{\n\t\t\tCRYPT_CERTIFICATE certCopy;\n\n\t\t\tstatus = getCertCopy( certInfoPtr, &certCopy, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t*certInfo = certCopy;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tcase CRYPT_IATTRIBUTE_CERTCOPY_DATAONLY:\n\t\t\t{\n\t\t\tCRYPT_CERTIFICATE certCopy;\n\n\t\t\tstatus = getCertCopy( certInfoPtr, &certCopy, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t*certInfo = certCopy;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_gets.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGet Certificate String Components\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\t\t/* For sprintf() */\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The maximum magnitude of an individual OID arc.  Anything larger than \n   this is most likely an error (or something from Microsoft) */\n\n#define OID_ARC_MAX\t\t0x1000000L\t/* 2 ^ 28 */\n\n/* The minimum size for an OBJECT IDENTIFIER expressed as ASCII characters */\n\n#define MIN_ASCII_OIDSIZE\t7\n\n/* Convert a binary OID to its text form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int oidToText( IN_BUFFER( binaryOidLen ) const BYTE *binaryOID, \n\t\t\t\t\t  IN_LENGTH_OID const int binaryOidLen,\n\t\t\t\t\t  OUT_BUFFER( maxOidLen, *oidLen ) char *oid, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int maxOidLen, \n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxOidLen ) int *oidLen )\n\t{\n\tlong value = 0;\n\tint i, length = 0, subLen, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( binaryOID, binaryOidLen ) );\n\tassert( isWritePtrDynamic( oid, maxOidLen ) );\n\tassert( isWritePtr( oidLen, sizeof( int ) ) );\n\n\tREQUIRES( binaryOidLen >= MIN_OID_SIZE && \\\n\t\t\t  binaryOidLen <= MAX_OID_SIZE && \\\n\t\t\t  binaryOidLen == sizeofOID( binaryOID ) );\n\tREQUIRES( maxOidLen >= 16 && maxOidLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( oid, 0, min( 16, maxOidLen ) );\n\t*oidLen = 0;\n\n\tLOOP_MED( i = 2, i < binaryOidLen, i++ )\n\t\t{\n\t\tconst BYTE data = binaryOID[ i ];\n\t\tconst long valTmp = value << 7;\n\n\t\t/* Pick apart the encoding */\n\t\tif( value == 0 && data == 0x80 )\n\t\t\t{\n\t\t\t/* Invalid leading zero value, ( 0x80 & 0x7F ) == 0 */\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tif( value >= ( OID_ARC_MAX >> 7 ) || \\\n\t\t\tvalTmp >= OID_ARC_MAX - ( data & 0x7F ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\t/* Overflow */\n\t\tvalue = valTmp | ( data & 0x7F );\n\t\tif( value < 0 || value > OID_ARC_MAX )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\t/* Range error */\n\t\tif( !( data & 0x80 ) )\n\t\t\t{\n\t\t\t/* Make sure that we don't overflow the buffer.  The value 20 is \n\t\t\t   the maximum magnitude of a 64-bit int plus space plus 1-byte \n\t\t\t   overflow */\n\t\t\tif( length >= maxOidLen - 20 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t\tif( length == 0 )\n\t\t\t\t{\n\t\t\t\tlong x, y;\n\n\t\t\t\t/* The first two levels are encoded into one byte since the \n\t\t\t\t   root level has only 3 nodes (40*x + y), however if x = \n\t\t\t\t   joint-iso-itu-t(2) then y may be > 39, so we have to add \n\t\t\t\t   special-case handling for this */\n\t\t\t\tx = value / 40;\n\t\t\t\ty = value % 40;\n\t\t\t\tif( x > 2 )\n\t\t\t\t\t{\n\t\t\t\t\t/* Handle special case for large y if x == 2 */\n\t\t\t\t\ty += ( x - 2 ) * 40;\n\t\t\t\t\tx = 2;\n\t\t\t\t\t}\n\t\t\t\tif( x < 0 || x > 2 || y < 0 || \\\n\t\t\t\t\t( ( x < 2 && y > 39 ) || \\\n\t\t\t\t\t  ( x == 2 && ( y > 50 && y != 100 ) ) ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If x = 0 or 1 then y has to be 0...39, for x = 2\n\t\t\t\t\t   it can take any value but there are no known \n\t\t\t\t\t   assigned values over 50 except for one contrived\n\t\t\t\t\t   example in X.690 which sets y = 100, so if we see\n\t\t\t\t\t   something outside this range it's most likely an \n\t\t\t\t\t   encoding error rather than some bizarre new ID \n\t\t\t\t\t   that's just appeared */\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t\t}\n\t\t\t\tsubLen = sprintf_s( oid, maxOidLen, \"%ld %ld\", x, y );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tsubLen = sprintf_s( oid + length, maxOidLen - length, \n\t\t\t\t\t\t\t\t\t\" %ld\", value );\n\t\t\t\t}\n\t\t\tif( subLen < 2 || subLen > maxOidLen - length )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tlength += subLen;\n\t\t\tvalue = 0;\n\t\t\t}\n\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( value != 0 )\n\t\t{\n\t\t/* We stopped in the middle of a continued value, it's an invalid\n\t\t   encoding */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\t*oidLen = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Convert an ASCII OID arc sequence into an encoded OID.  We allow dots as \n   well as whitespace for arc separators, these are an IETF-ism but are in \n   common use */\n\nCHECK_RETVAL_RANGE( 0, CRYPT_MAX_TEXTSIZE ) STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int scanValue( IN_BUFFER( strMaxLength ) const char *string, \n\t\t\t\t\t  IN_LENGTH_TEXT const int strMaxLength,\n\t\t\t\t\t  OUT_INT_Z long *value )\n\t{\n\tint intValue, index, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, strMaxLength ) );\n\tassert( isWritePtr( value, sizeof( long ) ) );\n\n\tREQUIRES( strMaxLength > 0 && strMaxLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\t/* Look for the end of the arc */\n\tLOOP_MED( index = 0, index < strMaxLength, index++ )\n\t\t{\n\t\tif( string[ index ] == ' ' || string[ index ] == '.' )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( index <= 0 || index > CRYPT_MAX_TEXTSIZE )\n\t\treturn( -1 );\n\tstatus = strGetNumeric( string, index, &intValue, 0, OID_ARC_MAX );\n\tif( cryptStatusError( status ) )\n\t\treturn( -1 );\n\t*value = intValue;\n\tif( index < strMaxLength && \\\n\t\t( string[ index ] == ' ' || string[ index ] == '.' ) )\n\t\t{\n\t\t/* There's more to go, skip the delimiter */\n\t\tindex++;\n\t\t}\n\treturn( index );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint textToOID( IN_BUFFER( textOidLength ) const char *textOID, \n\t\t\t   IN_LENGTH_TEXT const int textOidLength, \n\t\t\t   OUT_BUFFER( binaryOidMaxLen, *binaryOidLen ) BYTE *binaryOID, \n\t\t\t   IN_LENGTH_SHORT const int binaryOidMaxLen, \n\t\t\t   OUT_LENGTH_BOUNDED_Z( binaryOidMaxLen ) int *binaryOidLen )\n\t{\n\tconst char *textOidPtr;\n\tlong value, value2;\n\tint length = 3, subLen, dataLeft, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( textOID, textOidLength ) );\n\tassert( isWritePtrDynamic( binaryOID, binaryOidMaxLen ) );\n\tassert( isWritePtr( binaryOidLen, sizeof( int ) ) );\n\n\tREQUIRES( textOidLength >= MIN_ASCII_OIDSIZE && \\\n\t\t\t  textOidLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( binaryOidMaxLen >= 5 && \\\n\t\t\t  binaryOidMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\tmemset( binaryOID, 0, min( 16, binaryOidMaxLen ) );\n\t*binaryOidLen = 0;\n\n\t/* Perform some basic checks on the OID data */\n\tstatus = dataLeft = strStripWhitespace( &textOidPtr, textOID, \n\t\t\t\t\t\t\t\t\t\t\ttextOidLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Make sure that the first two arcs are in order */\n\tsubLen = scanValue( textOidPtr, dataLeft, &value );\n\tif( subLen <= 0 || subLen > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\ttextOidPtr += subLen;\n\tdataLeft -= subLen;\n\tif( dataLeft <= 0 || dataLeft > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tsubLen = scanValue( textOidPtr, dataLeft, &value2 );\n\tif( subLen <= 0 || subLen > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\ttextOidPtr += subLen;\n\tdataLeft -= subLen;\n\tif( dataLeft <= 0 || dataLeft > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( value < 0 || value > 2 || value2 < 1 || \\\n\t\t( ( value < 2 && value2 > 39 ) || ( value == 2 && value2 > 175 ) ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tbinaryOID[ 0 ] = 0x06;\t/* OBJECT IDENTIFIER tag */\n\tbinaryOID[ 2 ] = ( BYTE )( ( value * 40 ) + value2 );\n\n\t/* Convert the remaining arcs */\n\tLOOP_MED_CHECK( dataLeft > 0 )\n\t\t{\n\t\tBOOLEAN hasHighBits = FALSE;\n\n\t\t/* Scan the next value and write the high octets (if necessary) with\n\t\t   flag bits set, followed by the final octet */\n\t\tsubLen = scanValue( textOidPtr, dataLeft, &value );\n\t\tif( subLen <= 0 || subLen > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\ttextOidPtr += subLen;\n\t\tdataLeft -= subLen;\n\t\tif( dataLeft < 0 || dataLeft > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tif( value >= 0x200000L )\t\t\t\t\t/* 2^21 */\n\t\t\t{\n\t\t\tif( length >= binaryOidMaxLen )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbinaryOID[ length++ ] = intToByte( 0x80 | ( value >> 21 ) );\n\t\t\tvalue %= 0x200000L;\n\t\t\thasHighBits = TRUE;\n\t\t\t}\n\t\tif( ( value >= 0x4000 ) || hasHighBits )\t/* 2^14 */\n\t\t\t{\n\t\t\tif( length >= binaryOidMaxLen )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbinaryOID[ length++ ] = intToByte( 0x80 | ( value >> 14 ) );\n\t\t\tvalue %= 0x4000;\n\t\t\thasHighBits = TRUE;\n\t\t\t}\n\t\tif( ( value >= 0x80 ) || hasHighBits )\t\t/* 2^7 */\n\t\t\t{\n\t\t\tif( length >= binaryOidMaxLen )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbinaryOID[ length++ ] = intToByte( 0x80 | ( value >> 7 ) );\n\t\t\tvalue %= 128;\n\t\t\t}\n\t\tif( length >= binaryOidMaxLen )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tbinaryOID[ length++ ] = intToByte( value );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tbinaryOID[ 1 ] = intToByte( length - 2 );\n\t*binaryOidLen = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet Certificate Components\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int getCertAttributeComponent( const CERT_INFO *certInfoPtr,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\tOUT_BUFFER_OPT( certInfoMaxLength, *certInfoLength ) \\\n\t\t\t\t\t\tvoid *certInfo, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tvoid *dataPtr;\n\tint dataLength, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( certInfoType, CRYPT_ATTRIBUTE ) );\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* Try and find this attribute in the attribute list */\n\tattributePtr = findAttributeComponent( certInfoPtr, certInfoType );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* String fields never have default values (only BOOLEANs do) and never \n\t   denote complete-attribute entries (these are indicated by a present/\n\t   not-present BOOLEAN) */\n\tENSURES( !checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\t\t  ATTRIBUTE_PROPERTY_DEFAULTVALUE ) );\n\tENSURES( !checkAttributeProperty( attributePtr,\n\t\t\t\t\t\t\t\t\t  ATTRIBUTE_PROPERTY_COMPLETEATRIBUTE ) );\n\n\t/* If the data type is an OID we have to convert it to a human-readable\n\t   form before we return it */\n\tif( checkAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_OID ) )\n\t\t{\n\t\tchar textOID[ ( CRYPT_MAX_TEXTSIZE * 2 ) + 8 ];\n\t\tint textOidLength;\n\n\t\tstatus = getAttributeDataPtr( attributePtr, &dataPtr, &dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = oidToText( dataPtr, dataLength, textOID, \n\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE * 2, &textOidLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*certInfoLength = textOidLength;\n\t\tif( certInfo == NULL )\n\t\t\treturn( CRYPT_OK );\n\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t certInfoLength, textOID, \n\t\t\t\t\t\t\t\t\t textOidLength ) );\n\t\t}\n\n\t/* Get the attribute component data */\n\tstatus = getAttributeDataPtr( attributePtr, &dataPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t certInfoLength, dataPtr, dataLength ) );\n\t}\n\n/* Get the hash of a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int getCertHash( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType, \n\t\t\t\t\t\tOUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t*certInfoLength ) void *certInfo, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tstatic const MAP_TABLE hashAlgoMapTbl[] = {\n\t\t{ CRYPT_CERTINFO_FINGERPRINT_SHA1, CRYPT_ALGO_SHA1 },\n\t\t{ CRYPT_CERTINFO_FINGERPRINT_SHA2, CRYPT_ALGO_SHA2 },\n\t\t{ CRYPT_CERTINFO_FINGERPRINT_SHAng, CRYPT_ALGO_SHAng },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashAlgo, hashSize, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( certInfoType == CRYPT_CERTINFO_FINGERPRINT_SHA1 || \\\n\t\t\t  certInfoType == CRYPT_CERTINFO_FINGERPRINT_SHA2 || \\\n\t\t\t  certInfoType == CRYPT_CERTINFO_FINGERPRINT_SHAng );\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* Get the hash algorithm information */\n\tstatus = mapValue( certInfoType, &hashAlgo, hashAlgoMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( hashAlgoMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tgetHashAtomicParameters( hashAlgo, 0, &hashFunctionAtomic, &hashSize );\n\t*certInfoLength = hashSize;\n\tif( certInfo == NULL )\n\t\treturn( CRYPT_OK );\n\tENSURES( certInfoPtr->certificate != NULL );\n\n\t/* Write the hash (fingerprint) to the output */\n\tif( hashAlgo == CRYPT_ALGO_SHA1 && certInfoPtr->certHashSet )\n\t\t{\n\t\t/* If we've got a cached certificate hash present, return that instead of \n\t\t   re-hashing the certificate */\n\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t certInfoLength, certInfoPtr->certHash, \n\t\t\t\t\t\t\t\t\t KEYID_SIZE ) );\n\t\t}\n\thashFunctionAtomic( hash, CRYPT_MAX_HASHSIZE, certInfoPtr->certificate,\n\t\t\t\t\t\tcertInfoPtr->certificateSize );\n\tif( hashAlgo == CRYPT_ALGO_SHA1 )\n\t\t{\n\t\t/* Remember the hash/fingerprint/oobCertID/certHash/thumbprint/\n\t\t   whatever for later since this is reused frequently */\n\t\tREQUIRES( rangeCheck( hashSize, 1, KEYID_SIZE ) );\n\t\tmemcpy( certInfoPtr->certHash, hash, hashSize );\n\t\tcertInfoPtr->certHashSet = TRUE;\n\t\t}\n\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t certInfoLength, hash, hashSize ) );\n\t}\n\n/* Get the ESSCertID for a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getESSCertID( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t OUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *certInfoLength ) void *certInfo, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tSTREAM stream;\n\tBYTE certHash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint certHashSize, issuerSerialDataSize, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* Get the certificate ID */\n\tstatus = getCertHash( certInfoPtr, CRYPT_CERTINFO_FINGERPRINT_SHA1, \n\t\t\t\t\t\t  certHash, CRYPT_MAX_HASHSIZE, &certHashSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( certInfoPtr->cCertCert->serialNumber != NULL );\n\n\t/* Write the ESSCertID:\n\n\t\tESSCertID ::= SEQUENCE {\n\t\t\tcertHash\t\tOCTET STRING SIZE(20),\n\t\t\tissuerSerial\tSEQUENCE {\n\t\t\t\tissuer\t\tSEQUENCE { [4] EXPLICIT Name },\n\t\t\t\tserial\t\tINTEGER\n\t\t\t\t}\n\t\t\t} */\n\tissuerSerialDataSize = \\\n\t\t\tsizeofShortObject( sizeofShortObject( certInfoPtr->issuerDNsize ) ) + \\\n\t\t\tsizeofInteger( certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t   certInfoPtr->cCertCert->serialNumberLength );\n\t*certInfoLength = \\\n\t\t\tsizeofShortObject( sizeofShortObject( certHashSize ) + \\\n\t\t\t\t\t\t\t   sizeofShortObject( issuerSerialDataSize ) );\n\tif( certInfo == NULL )\n\t\treturn( CRYPT_OK );\n\tif( *certInfoLength <= 0 || *certInfoLength > certInfoMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tsMemOpen( &stream, certInfo, *certInfoLength );\n\twriteSequence( &stream, sizeofShortObject( certHashSize ) + \\\n\t\t\t\t\t\t\tsizeofShortObject( issuerSerialDataSize ) );\n\twriteOctetString( &stream, certHash, certHashSize, DEFAULT_TAG );\n\twriteSequence( &stream, issuerSerialDataSize );\n\twriteSequence( &stream, sizeofShortObject( certInfoPtr->issuerDNsize ) );\n\twriteConstructed( &stream, certInfoPtr->issuerDNsize, 4 );\n\tswrite( &stream, certInfoPtr->issuerDNptr, certInfoPtr->issuerDNsize );\n\tstatus = writeInteger( &stream, certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t   certInfoPtr->cCertCert->serialNumberLength, \n\t\t\t\t\t\t   DEFAULT_TAG );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet Validity Components\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTVAL\n\n/* Get a pointer to the currently selected validity time */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\ntime_t *getValidityTimePtr( const CERT_INFO *certInfoPtr )\n\t{\n\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\tVALIDITY_INFO *validityInfoPtr;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES_N( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES_N( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE );\n\n\t/* If there's a specific validity entry selected get its invalidity time, \n\t   otherwise if there are invalid certificates present get the first \n\t   certificate's invalidity time, otherwise get the default invalidity \n\t   time */\n\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\tif( validityInfoPtr != NULL )\n\t\treturn( &validityInfoPtr->invalidityTime );\n\tvalidityInfoPtr = DATAPTR_GET( certValInfo->validityInfo );\n\tif( validityInfoPtr != NULL )\n\t\treturn( &validityInfoPtr->invalidityTime );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet Revocation Components\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Encode a single CRL entry into the external format, used when storing a\n   CRL to a certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getCrlEntry( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\tOUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t*certInfoLength ) void *certInfo, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tSTREAM stream;\n\tWRITECERT_FUNCTION writeCertFunction;\n\tint crlEntrySize DUMMY_INIT, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CRL );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\tif( DATAPTR_ISNULL( certRevInfo->currentRevocation ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Determine how big the encoded CRL entry will be.  Doing it directly\n\t   in this manner is somewhat ugly but the only other way to do it would \n\t   be to pseudo-sign the certificate object in order to write the data, \n\t   which doesn't work for CRL entries where we could end up pseudo-\n\t   signing it multiple times */\n\twriteCertFunction = getCertWriteFunction( CRYPT_CERTTYPE_CRL );\n\tENSURES( writeCertFunction != NULL );\n\tsMemNullOpen( &stream );\n\tstatus = writeCertFunction( &stream, certInfoPtr, NULL, CRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\tcrlEntrySize = stell( &stream );\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the encoded single CRL entry */\n\t*certInfoLength = crlEntrySize;\n\tif( certInfo == NULL )\n\t\treturn( CRYPT_OK );\n\tif( crlEntrySize <= 0 || crlEntrySize > certInfoMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tsMemOpen( &stream, certInfo, crlEntrySize );\n\tstatus = writeCertFunction( &stream, certInfoPtr, NULL,  CRYPT_UNUSED );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Get a pointer to the currently selected revocation time */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\ntime_t *getRevocationTimePtr( IN const CERT_INFO *certInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tREVOCATION_INFO *revInfoPtr;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES_N( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES_N( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\n\t/* If there's a specific revocation entry selected, get its revocation \n\t   time, otherwise if there are revoked certificates present get the \n\t   first certificate's revocation time, otherwise get the default \n\t   revocation time */\n\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\tif( revInfoPtr != NULL )\n\t\treturn( &revInfoPtr->revocationTime );\n\trevInfoPtr = DATAPTR_GET( certRevInfo->revocations );\n\tif( revInfoPtr != NULL )\n\t\treturn( &revInfoPtr->revocationTime );\n\tif( certRevInfo->revocationTime > MIN_TIME_VALUE )\n\t\treturn( &certRevInfo->revocationTime );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGet Certificate Owner Components\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the issuerAndSerialNumber for a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getIAndS( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t OUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t *certInfoLength ) void *certInfo, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tSTREAM stream;\n\tvoid *serialNumber;\n\tint serialNumberLength, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n#ifdef USE_CERTREV\n\t/* If it's a CRL, use the serial number of the currently selected CRL \n\t   entry */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tconst CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\tREQUIRES( revInfoPtr != NULL );\n\n\t\tserialNumber = revInfoPtr->id;\n\t\tserialNumberLength = revInfoPtr->idLength;\n\t\t}\n\telse\n#endif /* USE_CERTREV */\n\t\t{\n\t\tserialNumber = certInfoPtr->cCertCert->serialNumber;\n\t\tserialNumberLength = certInfoPtr->cCertCert->serialNumberLength;\n\t\t}\n\tENSURES( serialNumber != NULL );\n\t*certInfoLength = sizeofShortObject( \\\n\t\t\t\t\t\t\t\tcertInfoPtr->issuerDNsize + \\\n\t\t\t\t\t\t\t\tsizeofInteger( serialNumber, \\\n\t\t\t\t\t\t\t\t\t\t\t   serialNumberLength ) );\n\tif( certInfo == NULL )\n\t\treturn( CRYPT_OK );\n\tif( *certInfoLength <= 0 || *certInfoLength > certInfoMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tsMemOpen( &stream, certInfo, *certInfoLength );\n\twriteSequence( &stream, certInfoPtr->issuerDNsize + \\\n\t\t\t\t   sizeofInteger( serialNumber, serialNumberLength ) );\n\tswrite( &stream, certInfoPtr->issuerDNptr, certInfoPtr->issuerDNsize );\n\tstatus = writeInteger( &stream, serialNumber, serialNumberLength,\n\t\t\t\t\t\t   DEFAULT_TAG );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Look for a named DN component (e.g. \"surname = Smith\") in an RFC 1779-\n   encoded DN.  We have to use the text-string encoded form because we're\n   looking for arbitrarily odd components not all of which are handled\n   directly by cryptlib */\n\n#if 0\t/* 18/7/08 Unlikely that we'd ever find a certificate this broken,\n\t\t   and it's just a potential attack vector due to the complexity of\n\t\t   the processing */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \\\nstatic int extractDnComponent( IN_BUFFER( encodedDnLength ) \\\n\t\t\t\t\t\t\t\t\tconst char *encodedDn, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int encodedDnLength, \n\t\t\t\t\t\t\t   IN_BUFFER( componentNameLength ) \\\n\t\t\t\t\t\t\t\t\tconst char *componentName, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int componentNameLength,\n\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *startOffset,\n\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *length )\n\t{\n\tint startPos, endPos, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( encodedDn, encodedDnLength ) );\n\tassert( isReadPtrDynamic( componentName, componentNameLength ) );\n\tassert( isWritePtr( startOffset, sizeof( int ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( encodedDnLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( componentNameLength ) );\n\n\t/* Clear return values */\n\t*startOffset = *length = 0;\n\t\n\t/* Try and find the component type name in the RFC 1779-encoded DN \n\t   string.  This scans the DN string for a matching type in a\n\t   type-and-value pair, e.g. \"surname = Smith\" */\n\tstartPos = strFindStr( encodedDn, encodedDnLength, \n\t\t\t\t\t\t   componentName, componentNameLength );\n\tif( startPos < 0 )\n\t\treturn( -1 );\n\tstartPos += componentNameLength;\t/* Skip type indicator */\n\t\n\t/* Extract the component value */\n\tLOOP_LARGE( endPos = startPos,\n\t\t\t\tendPos < encodedDnLength && \\\n\t\t\t\t\tencodedDn[ endPos ] != ',' && \\\n\t\t\t\t\tencodedDn[ endPos ] != '+',\n\t\t\t\tendPos++ );\n\tENSURES( LOOP_BOUND_OK );\n\tif( endPos > startPos && \\\n\t\tencodedDn[ endPos ] == '+' && \\\n\t\tencodedDn[ endPos - 1 ] == ' ' )\n\t\tendPos--;\t/* Strip trailing space */\n\tif( endPos <= startPos )\n\t\treturn( -1 );\n\t\n\t*startOffset = startPos;\n\t*length = endPos - startPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Assemble name components from an RFC 1779-encoded DN string.  We have to \n   use the text-string encoded form because we're looking for arbitrarily \n   odd components not all of which are handled directly by cryptlib */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nstatic int getNameFromDN( OUT_BUFFER_OPT( nameMaxLength, *nameLength ) \\\n\t\t\t\t\t\t\tvoid *name, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int nameMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( nameMaxLength ) \\\n\t\t\t\t\t\t\tint *nameLength, \n\t\t\t\t\t\t  IN_BUFFER( encodedDnLength ) const char *encodedDn, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int encodedDnLength )\n\t{\n\tint startPos, length, status;\n\n\tassert( ( name == NULL && nameMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( name, nameMaxLength ) ) );\n\tassert( isWritePtr( nameLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( encodedDn, encodedDnLength ) );\n\n\tREQUIRES( ( name == NULL && nameMaxLength == 0 ) || \\\n\t\t\t  ( name != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( nameMaxLength ) ) );\n\tREQUIRES( isShortIntegerRangeNZ( encodedDnLength ) );\n\n\t/* Clear return values */\n\tif( name != NULL )\n\t\tmemset( name, 0, min( 16, nameMaxLength ) );\n\t*nameLength = 0;\n\t\n\t/* Look for a pseudonym */\n\tstatus = extractDnComponent( encodedDn, encodedDnLength, \n\t\t\t\t\t\t\t\t \"oid.2.5.4.65=\", 13, &startPos, &length );\n\tif( cryptStatusOK( status ) && \\\n\t\tlength > 0 && length <= nameMaxLength )\n\t\t{\n\t\treturn( attributeCopyParams( name, nameMaxLength, nameLength, \n\t\t\t\t\t\t\t\t\t encodedDn + startPos, length ) );\n\t\t}\n\n\t/* Look for givenName + surname */\n\tstatus = extractDnComponent( encodedDn, encodedDnLength, \n\t\t\t\t\t\t\t\t \"G=\", 2, &startPos, &length );\n\tif( cryptStatusOK( status ) && \\\n\t\tlength > 0 && length <= nameMaxLength )\n\t\t{\n\t\tchar nameBuffer[ MAX_ATTRIBUTE_SIZE + 8 ];\n\t\tint startPos2, length2;\n\n\t\tstatus = extractDnComponent( encodedDn, encodedDnLength, \n\t\t\t\t\t\t\t\t\t \"S=\", 2, &startPos2, &length2 );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tlength2 > 0 && length + length2 <= nameMaxLength && \\\n\t\t\t\t\t\t   length + length2 < MAX_ATTRIBUTE_SIZE )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheckZ( startPos, length, encodedDnLength ) );\n\t\t\tmemcpy( nameBuffer, encodedDn + startPos, length );\n\t\t\tREQUIRES( boundsCheck( length, length2, nameMaxLength ) );\n\t\t\tREQUIRES( boundsCheckZ( startPos2, length2, encodedDnLength ) );\n\t\t\tmemcpy( nameBuffer + length, encodedDn + startPos2, length2 );\n\t\t\treturn( attributeCopyParams( name, nameMaxLength, nameLength, \n\t\t\t\t\t\t\t\t\t\t nameBuffer, length + length2 ) );\n\t\t\t}\n\t\t}\n\n\t/* We couldn't find anything useful */\t\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n#endif /* 0 */\n\n/* Get the certificate holder's name, usually the commonName but if that's\n   not present then some commonName-equivalent */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getHolderName( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t  OUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t  *certInfoLength ) void *certInfo, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* First we try for a CN */\n\tstatus = getDNComponentValue( certInfoPtr->subjectName, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME, 0, certInfo, \n\t\t\t\t\t\t\t\t  certInfoMaxLength, certInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\n#if 0\t/* 18/7/08 Unlikely that we'd ever find a certificate this broken,\n\t\t   and it's just a potential attack vector due to the complexity of\n\t\t   the processing */\n\t/* If that fails we try for either a pseudonym or givenName + surname.\n\t   Since these are part of the vast collection of oddball DN attributes\n\t   that aren't handled directly we have to get the encoded DN form and\n\t   look for them by OID (ugh) */\n\tsMemOpen( &stream, encodedDnBuffer, MAX_ATTRIBUTE_SIZE );\n\tstatus = writeDNstring( &stream, certInfoPtr->subjectName );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getNameFromDN( certInfo, certInfoMaxLength, certInfoLength, \n\t\t\t\t\t\t\t\tencodedDnBuffer, stell( &stream ) );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) )\n\t\treturn( status );\n#endif /* 0 */\n\n\t/* It's possible (although highly unlikely) that a certificate won't \n\t   have a usable CN-equivalent in some form, in which case we use the OU\n\t   instead.  If that also fails we use the O.  This gets a bit messy, \n\t   but duplicating the OU / O into the CN seems to be the best way to \n\t   handle this */\n\tstatus = getDNComponentValue( certInfoPtr->subjectName, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, 0,\n\t\t\t\t\t\t\t\t  certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t  certInfoLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = getDNComponentValue( certInfoPtr->subjectName, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANIZATIONNAME, 0,\n\t\t\t\t\t\t\t\t\t  certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t  certInfoLength );\n\t\t}\n\treturn( status );\n\t}\n\n/* Get the certificate holder's URI, usually an email address but sometimes\n   also a URL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getHolderURI( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t OUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *certInfoLength ) void *certInfo, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tvoid *dataPtr;\n\tint dataLength, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* Find the subjectAltName, which contains the URI information */\n\tattributePtr = findAttribute( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTALTNAME, TRUE );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* There's altName data present, try for an email address and if that \n\t   fails, a URL and an FQDN */\n\tattributePtr = findAttributeField( attributePtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_RFC822NAME );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t{\n\t\tattributePtr = findAttributeField( attributePtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );\n\t\t}\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t{\n\t\tattributePtr = findAttributeField( attributePtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_DNSNAME );\n\t\t}\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Get the attribute component data */\n\tstatus = getAttributeDataPtr( attributePtr, &dataPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t certInfoLength, dataPtr, dataLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tGet Miscellaneous Certificate Components\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKIUSER\n\n/* Encode PKI user information (IDs and passwords) into the external \n   text-encoded format */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int getPkiUserInfo( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType, \n\t\t\t\t\t\t   OUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t   *certInfoLength ) void *certInfo, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tCERT_PKIUSER_INFO *certUserInfo = certInfoPtr->cCertUser;\n\tchar encUserInfo[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBYTE userInfo[ 128 + 8 ], *userInfoPtr = userInfo;\n\tint userInfoLength, encUserInfoLength, status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( certInfoType == CRYPT_CERTINFO_PKIUSER_ID || \\\n\t\t\t  certInfoType == CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD || \\\n\t\t\t  certInfoType == CRYPT_CERTINFO_PKIUSER_REVPASSWORD );\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\tif( certInfoType == CRYPT_CERTINFO_PKIUSER_ID )\n\t\t{\n\t\tstatus = getCertAttributeComponent( certInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t\t\t\t\t\t\t\t\t\t\tuserInfo, 128, &userInfoLength );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\telse\n\t\t{\n\t\tuserInfoPtr = ( certInfoType == CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD ) ? \\\n\t\t\t\t\t  certUserInfo->pkiIssuePW : certUserInfo->pkiRevPW;\n\t\tuserInfoLength = PKIUSER_AUTHENTICATOR_SIZE;\n\t\t}\n\tstatus = encodePKIUserValue( encUserInfo, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t &encUserInfoLength, userInfoPtr,\n\t\t\t\t\t\t\t\t userInfoLength,\n\t\t\t\t\t\t\t\t ( certInfoType == \\\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_PKIUSER_ID ) ? 3 : 4 );\n\tzeroise( userInfo, CRYPT_MAX_TEXTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\tdecodePKIUserValue( userInfo, 128, &userInfoLength,\n\t\t\t\t\t\t\t\t\tencUserInfo, encUserInfoLength ) ) );\n\tstatus = attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t  certInfoLength, encUserInfo, \n\t\t\t\t\t\t\t\t  encUserInfoLength );\n\tzeroise( encUserInfo, CRYPT_MAX_TEXTSIZE );\n\n\treturn( status );\n\t}\n#endif /* USE_PKIUSER */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet a Certificate Component\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint getCertComponentString( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\tOUT_BUFFER_OPT( certInfoMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t*certInfoLength ) void *certInfo, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certInfoMaxLength, \n\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( certInfoMaxLength ) \\\n\t\t\t\t\t\t\t\tint *certInfoLength )\n\t{\n\tconst void *data = NULL;\n\tint dataLength = 0, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t( certInfo != NULL && \\\n\t\t\t  isShortIntegerRangeNZ( certInfoMaxLength ) && \\\n\t\t\t  isWritePtrDynamic( certInfo, certInfoMaxLength ) ) );\n\tassert( isWritePtr( certInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\tREQUIRES( ( certInfo == NULL && certInfoMaxLength == 0 ) || \\\n\t\t\t  ( certInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certInfoMaxLength ) ) );\n\n\t/* Clear return values */\n\tif( certInfo != NULL )\n\t\tmemset( certInfo, 0, min( 16, certInfoMaxLength ) );\n\t*certInfoLength = 0;\n\n\t/* If it's a GeneralName or DN component, return it.  These are \n\t   special-case attribute values so they have to come before the \n\t   general attribute-handling code */\n\tif( isGeneralNameComponent( certInfoType ) )\n\t\t{\n\t\tSELECTION_STATE selectionState;\n\t\tDATAPTR_ATTRIBUTE attributePtr DUMMY_INIT_STRUCT;\n\t\tvoid *dataPtr;\n\n\t\t/* Find the requested GeneralName component and return it to the\n\t\t   caller.  Since selectGeneralNameComponent() changes the current\n\t\t   selection within the GeneralName, we save the selection state\n\t\t   around the call */\n\t\tsaveSelectionState( selectionState, certInfoPtr );\n\t\tstatus = selectGeneralNameComponent( certInfoPtr, certInfoType );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tattributePtr = certInfoPtr->attributeCursor;\n\t\trestoreSelectionState( selectionState, certInfoPtr );\n\t\tif( cryptStatusError( status ))\n\t\t\treturn( status );\n\t\tENSURES( DATAPTR_ISSET( attributePtr ) );\n\n\t\t/* Get the attribute component data */\n\t\tstatus = getAttributeDataPtr( attributePtr, &dataPtr, &dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t certInfoLength, dataPtr, dataLength ) );\n\t\t}\n\tif( isDNComponent( certInfoType ) )\n\t\t{\n\t\tint count = 0;\n\t\t\n\t\t/* If this is the currently selected item in the DN, the caller may\n\t\t   be asking for the n-th occurrence rather than the initial one */\n\t\tif( certInfoPtr->currentSelection.dnComponent == certInfoType )\n\t\t\tcount = certInfoPtr->currentSelection.dnComponentCount;\n\n\t\t/* Find the requested DN component and return it to the caller */\n\t\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t   MUST_BE_PRESENT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES( certInfoPtr->currentSelection.dnPtr != NULL );\n\t\treturn( getDNComponentValue( *certInfoPtr->currentSelection.dnPtr,\n\t\t\t\t\t\t\t\t\t certInfoType, count, certInfo, \n\t\t\t\t\t\t\t\t\t certInfoMaxLength, certInfoLength ) );\n\t\t}\n\n\t/* If it's standard certificate or CMS attribute, return it */\n\tif( isValidExtension( certInfoType ) )\n\t\t{\n\t\treturn( getCertAttributeComponent( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t\t\t\t   certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t   certInfoLength ) );\n\t\t}\n\n\t/* If it's anything else, handle it specially */\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_FINGERPRINT_SHA1:\n\t\tcase CRYPT_CERTINFO_FINGERPRINT_SHA2:\n\t\tcase CRYPT_CERTINFO_FINGERPRINT_SHAng:\n\t\t\treturn( getCertHash( certInfoPtr, certInfoType, certInfo, \n\t\t\t\t\t\t\t\t certInfoMaxLength, certInfoLength ) );\n\n\t\tcase CRYPT_CERTINFO_SERIALNUMBER:\n\t\t\tswitch( certInfoPtr->type )\n\t\t\t\t{\n#ifdef USE_CERTREV\n\t\t\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t\t\t{\n\t\t\t\t\tconst CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\t\t\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\t\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\t\t\tif( revInfoPtr == NULL )\n\t\t\t\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->revocations );\n\t\t\t\t\tif( revInfoPtr != NULL )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tdata = revInfoPtr->id;\n\t\t\t\t\t\tdataLength = revInfoPtr->idLength;\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTREQ\n\t\t\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t\t\tdata = certInfoPtr->cCertReq->serialNumber;\n\t\t\t\t\tdataLength = certInfoPtr->cCertReq->serialNumberLength;\n\t\t\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n\t\t\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\t\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\t\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\t\t\tdata = certInfoPtr->cCertCert->serialNumber;\n\t\t\t\t\tdataLength = certInfoPtr->cCertCert->serialNumberLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, data, dataLength ) );\n\n\t\tcase CRYPT_CERTINFO_VALIDFROM:\n\t\tcase CRYPT_CERTINFO_THISUPDATE:\n\t\t\tif( certInfoPtr->startTime > MIN_CERT_TIME_VALUE )\n\t\t\t\t{\n\t\t\t\tdata = &certInfoPtr->startTime;\n\t\t\t\tdataLength = sizeof( time_t );\n\t\t\t\t}\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, data, dataLength ) );\n\n\t\tcase CRYPT_CERTINFO_VALIDTO:\n\t\tcase CRYPT_CERTINFO_NEXTUPDATE:\n\t\t\tif( certInfoPtr->endTime > MIN_CERT_TIME_VALUE )\n\t\t\t\t{\n\t\t\t\tdata = &certInfoPtr->endTime;\n\t\t\t\tdataLength = sizeof( time_t );\n\t\t\t\t}\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, data, dataLength ) );\n\n#ifdef USE_CERT_OBSOLETE \n\t\tcase CRYPT_CERTINFO_ISSUERUNIQUEID:\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->cCertCert->issuerUniqueID, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->cCertCert->issuerUniqueIDlength ) );\n\n\t\tcase CRYPT_CERTINFO_SUBJECTUNIQUEID:\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->cCertCert->subjectUniqueID, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->cCertCert->subjectUniqueIDlength ) );\n#endif /* USE_CERT_OBSOLETE */\n\n\t\tcase CRYPT_CERTINFO_REVOCATIONDATE:\n\t\t\tswitch( certInfoPtr->type )\n\t\t\t\t{\n#ifdef USE_CERTREV\n\t\t\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t\t\tdata = getRevocationTimePtr( certInfoPtr );\n\t\t\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL \n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\t\t\tdata = getValidityTimePtr( certInfoPtr );\n\t\t\t\t\tbreak;\n#endif /* USE_CERTVAL */\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( data != NULL )\n\t\t\t\tdataLength = sizeof( time_t );\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, data, dataLength ) );\n\n#ifdef USE_CERT_DNSTRING\n\t\tcase CRYPT_CERTINFO_DN:\n\t\t\t{\n\t\t\tSTREAM stream;\n\n\t\t\t/* Export the entire DN in string form */\n\t\t\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t   MUST_BE_PRESENT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tENSURES( certInfoPtr->currentSelection.dnPtr != NULL );\n\t\t\tsMemOpenOpt( &stream, certInfo, certInfoMaxLength );\n\t\t\tstatus = writeDNstring( &stream, \n\t\t\t\t\t\t\t\t\t*certInfoPtr->currentSelection.dnPtr );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t*certInfoLength = stell( &stream );\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n#endif /* USE_CERT_DNSTRING */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTINFO_PKIUSER_ID:\n\t\tcase CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD:\n\t\tcase CRYPT_CERTINFO_PKIUSER_REVPASSWORD:\n\t\t\treturn( getPkiUserInfo( certInfoPtr, certInfoType, certInfo, \n\t\t\t\t\t\t\t\t\tcertInfoMaxLength, certInfoLength ) );\n#endif /* USE_PKIUSER */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_IATTRIBUTE_CRLENTRY:\n\t\t\treturn( getCrlEntry( certInfoPtr, certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t certInfoLength ) );\n#endif /* USE_CERTREV */\n\n\t\tcase CRYPT_IATTRIBUTE_SUBJECT:\n\t\t\t/* Normally these attributes are only present for signed objects\n\t\t\t   (i.e. ones that are in the high state) but CRMF requests \n\t\t\t   acting as CMP revocation requests aren't signed so the kernel \n\t\t\t   ACLs are set to allow the attribute to be read in the low \n\t\t\t   state as well.  Since this only represents a programming \n\t\t\t   error rather than a real access violation we catch it here \n\t\t\t   with an assertion */\n\t\t\tassert( ( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\t\t\t\t  certInfoPtr->certificate == NULL ) || \\\n\t\t\t\t\tcertInfoPtr->certificate != NULL  );\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->subjectDNsize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_ISSUER:\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->issuerDNsize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER:\n\t\t\treturn( getIAndS( certInfoPtr, certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t  certInfoLength ) );\n\n\t\tcase CRYPT_IATTRIBUTE_HOLDERNAME:\n\t\t\treturn( getHolderName( certInfoPtr, certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t   certInfoLength ) );\n\n\t\tcase CRYPT_IATTRIBUTE_HOLDERURI:\n\t\t\treturn( getHolderURI( certInfoPtr, certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t  certInfoLength ) );\n\n\t\tcase CRYPT_IATTRIBUTE_SPKI:\n\t\t\t{\n\t\t\tBYTE *dataStartPtr = certInfo;\n\n\t\t\tstatus = attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t  certInfoLength, \n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->publicKeyInfo, \n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->publicKeyInfoSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( dataStartPtr != NULL && dataStartPtr[ 0 ] == MAKE_CTAG( 6 ) )\n\t\t\t\t{\n\t\t\t\t/* Fix up CRMF braindamage */\n\t\t\t\t*dataStartPtr = BER_SEQUENCE;\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\t\tcase CRYPT_IATTRIBUTE_RESPONDERURL:\n\t\t\t/* An RTCS/OCSP URL may be present if it was copied over from a \n\t\t\t   certificate that's being checked, however if there wasn't any \n\t\t\t   authorityInfoAccess information present then the URL won't \n\t\t\t   have been initialised.  Since this attribute isn't accessed \n\t\t\t   via the normal certificate attribute mechanisms we have to \n\t\t\t   explictly check for its non-presence */\n\t\t\tswitch( certInfoPtr->type )\n\t\t\t\t{\n#ifdef USE_CERTREV\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\t\t\tif( certInfoPtr->cCertRev->responderUrl == NULL )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\tcertInfoLength, \n\t\t\t\t\t\t\t\tcertInfoPtr->cCertRev->responderUrl, \n\t\t\t\t\t\t\t\tcertInfoPtr->cCertRev->responderUrlSize ) );\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL \n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\t\t\t\tif( certInfoPtr->cCertVal->responderUrl == NULL )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\tcertInfoLength, \n\t\t\t\t\t\t\t\tcertInfoPtr->cCertVal->responderUrl, \n\t\t\t\t\t\t\t\tcertInfoPtr->cCertVal->responderUrlSize ) );\n#endif /* USE_CERTVAL */\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_IATTRIBUTE_AUTHCERTID:\n\t\t\t/* An authorising certificate identifier will be present if\n\t\t\t   the request was handled by cryptlib but not if it came from\n\t\t\t   an external source so we have to make sure that there's \n\t\t\t   something actually present before we try to return it */\n\t\t\tif( isEmptyData( certInfoPtr->cCertReq->authCertID, 0 ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopyParams( certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t\t\t certInfoLength, \n\t\t\t\t\t\t\t\t\t\t certInfoPtr->cCertReq->authCertID, \n\t\t\t\t\t\t\t\t\t\t KEYID_SIZE ) );\n#endif /* USE_CERTREQ */\n\n\t\tcase CRYPT_IATTRIBUTE_ESSCERTID:\n\t\t\treturn( getESSCertID( certInfoPtr, certInfo, certInfoMaxLength, \n\t\t\t\t\t\t\t\t  certInfoLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/comp_pkiu.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSet PKI User Components\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_CERTIFICATES ) && defined( USE_PKIUSER )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKI User Attribute Management\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform any special-case adjustments on attributes that may be required \n   after they've been copied from the PKI user to the certificate request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int adjustPkiUserAttributes( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* The SCEP protocol requires that the SCEP challenge password be placed \n\t   in the PKCS #10 request instead of being included in the SCEP \n\t   metadata.  This shouldn't have been copied across to the certificate \n\t   request since the NOCOPY flag was set for the attribute, but to make \n\t   absolutely certain we try and delete it anyway.  Since this could in \n\t   theory be present in non-SCEP requests as well (the request-\n\t   processing code just knows about PKCS #10 requests as a whole, not \n\t   requests from a SCEP source vs. requests not from a SCEP source), we \n\t   make the delete unconditional */\n\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CHALLENGEPASSWORD, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = deleteCompleteAttribute( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CHALLENGEPASSWORD, \n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* The PKI user information contains an sKID that's used to uniquely \n\t   identify the user, this applies to the user information itself rather \n\t   than the certificate that'll be issued from it.  Since this will have \n\t   been copied over alongside the other attributes we need to explicitly \n\t   delete it before we continue */\n\tattributePtr = findAttributeField( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = deleteCompleteAttribute( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, \n\t\t\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Populate the certificate request with additional attributes from the PKI \n   user information.  The attributes that can be specified in requests are \n   severely limited (see the long comment for sanitiseCertAttributes() in \n   comp_cert.c) so the only ones that we really need to handle are the \n   altName and a special-case keyUsage check for CA key usages.\n   \n   This addition of extra attributes leads to the somewhat odd situation\n   where, if it's done for a completed request, the stored encoded form no\n   longer corresponds to the attributes present in the request.  This means\n   that if the request is exported it has its original form, but when it's\n   converted into a certificate it has the additional attributes added from\n   the PKI user information.  This seems to be the best (meaning least awful)\n   way to handle things, the request doesn't suddenly change its shape\n   halfway through processing but the sum of the attributes from the request\n   and the PKI user information are copied to the final certificate that's\n   created from it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyPkiUserAttributes( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t  const DATAPTR_ATTRIBUTE pkiUserAttributes )\n\t{\n\tDATAPTR_ATTRIBUTE requestAttrPtr, pkiUserAttrPtr;\n\tint value, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( DATAPTR_ISSET( pkiUserAttributes ) );\n\n\t/* If there are altNames present in both the PKI user data and the \n\t   request, make sure that they match */\n\trequestAttrPtr = findAttribute( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME, FALSE );\n\tpkiUserAttrPtr = findAttribute( pkiUserAttributes,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME, FALSE );\n\tif( DATAPTR_ISSET( requestAttrPtr ) && \\\n\t\tDATAPTR_ISSET( pkiUserAttrPtr ) )\n\t\t{\n\t\t/* Both the certificate request and the PKI user have altNames,\n\t\t   make sure that they're identical */\n\t\tif( !compareAttribute( requestAttrPtr, pkiUserAttrPtr ) )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* The two altNames are identical, delete the one in the request in \n\t\t   order to allow the one from the PKI user data to be copied across \n\t\t   when we call copyAttributes() */\n\t\tstatus = deleteAttribute( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t  requestAttrPtr,\n\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* There's one rather ugly special-case situation that we have to handle \n\t   which is when the user has submitted a PnP PKI request for a generic \n\t   signing certificate but their PKI user information indicates that \n\t   they're intended to be a CA user.  The processing flow for this is:\n\n\t\t\tRead request data from an external source into certificate \n\t\t\t\trequest object, creating a state=high object;\n\n\t\t\tAdd PKI user information to state=high request;\n\n\t   When augmenting the request with the PKI user information the \n\t   incoming request will contain a keyUsage of digitalSignature while \n\t   the PKI user information will contain a keyUsage of keyCertSign \n\t   and/or crlSign.  We can't fix this up at the PnP processing level \n\t   because the request object will be in the high state once it's\n\t   instantiated and no changes to the attributes can be made (the PKI \n\t   user information is a special case that can be added to an object in \n\t   the high state but which modifies attributes in it as if it were \n\t   still in the low state).\n\n\t   To avoid the attribute conflict, if we find this situation in the \n\t   request/pkiUser combination we delete the keyUsage in the request to \n\t   allow it to be replaced by the pkiUser keyUsage.  Hardcoding in this \n\t   special case isn't very elegant but it's the only way to make the PnP \n\t   PKI issue work without requiring that the user explicitly specify \n\t   that they want to be a CA in the request's keyUsage, which makes it \n\t   rather non-PnP and would also lead to slightly strange requests since\n\t   basicConstraints can't be specified in requests while the CA keyUsage\n\t   can */\n\tstatus = getAttributeFieldValue( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\tif( cryptStatusOK( status ) && value == CRYPT_KEYUSAGE_DIGITALSIGNATURE )\n\t\t{\n\t\tstatus = getAttributeFieldValue( pkiUserAttributes, \n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\t\tif( cryptStatusOK( status ) && ( value & KEYUSAGE_CA ) )\n\t\t\t{\n\t\t\t/* The certificate contains a digitalSignature keyUsage and the \n\t\t\t   PKI user information contains a CA usage, delete the \n\t\t\t   certificate's keyUsage to make way for the PKI user's CA \n\t\t\t   keyUsage */\n\t\t\tstatus = deleteCompleteAttribute( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t\t\t  certInfoPtr->currentSelection.dnPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Copy the attributes from the PKI user information into the \n\t   certificate request */\n\tstatus = copyAttributes( &certInfoPtr->attributes, pkiUserAttributes,\n\t\t\t\t\t\t\t &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Perform any special-case adjustments on attributes that may be \n\t   required after they've been copied from the PKI user to the \n\t   certificate request */\n\treturn( adjustPkiUserAttributes( certInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKI User DN Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Assemble the certificate DN from information in the request and the PKI \n   user data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int assemblePkiUserDN( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t  const DATAPTR_DN pkiUserSubjectName,\n\t\t\t\t\t\t\t  IN_BUFFER( commonNameLength ) const void *commonName, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int commonNameLength,\n\t\t\t\t\t\t\t  const BOOLEAN replaceCN )\n\t{\n\tSTREAM stream;\n\tDATAPTR_DN tempDN;\n\tvoid *tempDNdata;\n\tint tempDNsize DUMMY_INIT, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( commonName, commonNameLength ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( DATAPTR_ISSET( pkiUserSubjectName ) );\n\tREQUIRES( isShortIntegerRangeNZ( commonNameLength ) );\n\tREQUIRES( replaceCN == TRUE || replaceCN == FALSE );\n\n\t/* Copy the DN template, delete the original CN if necessary (required \n\t   if the template is from an RA, for which the user being authorised \n\t   has a different CN), append the user-supplied CN, and allocate room \n\t   for the encoded form */\n\tstatus = copyDN( &tempDN, pkiUserSubjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( replaceCN )\n\t\t{\n\t\t/* We're replacing the CN with a new one, delete the current one */\n\t\t( void ) deleteDNComponent( &tempDN, CRYPT_CERTINFO_COMMONNAME, \n\t\t\t\t\t\t\t\t\tNULL, 0 );\n\t\t}\n\tstatus = insertDNComponent( &tempDN, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\tcommonName, commonNameLength,\n\t\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = tempDNsize = sizeofDN( tempDN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeleteDN( &tempDN );\n\t\treturn( status );\n\t\t}\n\tREQUIRES( rangeCheck( tempDNsize, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( tempDNdata = clAlloc( \"assemblePkiUserDN\", tempDNsize ) ) == NULL )\n\t\t{\n\t\tdeleteDN( &tempDN );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\n\t/* Replace the existing DN with the new one and set up the encoded \n\t   form.  At this point we could already have an encoded DN present if \n\t   the request was read from its encoded form, with the subject DN \n\t   pointer pointing into the encoded request data (if the request was \n\t   created from scratch then there's no DN present).  We replace the \n\t   (possible) existing pointer into the certificate data with a pointer \n\t   to the updated encoded DN written to our newly-allocated block of \n\t   memory */\n\tdeleteDN( &certInfoPtr->subjectName );\n\tcertInfoPtr->subjectName = tempDN;\n\tsMemOpen( &stream, tempDNdata, tempDNsize );\n\tstatus = writeDN( &stream, tempDN, DEFAULT_TAG );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\tcertInfoPtr->subjectDNdata = certInfoPtr->subjectDNptr = tempDNdata;\n\tcertInfoPtr->subjectDNsize = tempDNsize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the DN in a certificate request, reconciling it with the DN \n   information from the PKI user data.  This is an extremely complex \n   operation, see the comments in the code below for more */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int processReqDN( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t const DATAPTR_DN pkiUserSubjectName,\n\t\t\t\t\t\t IN_BUFFER( pkiUserDNsize ) const void *pkiUserDNptr, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int pkiUserDNsize,\n\t\t\t\t\t\t const BOOLEAN requestFromRA )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE dnComponentType;\n\tDATAPTR_DN requestDNSubset, pkiUserDNSubset;\n\tconst BOOLEAN certNamePresent = \\\n\t\t\t\t\tDATAPTR_ISSET( certInfoPtr->subjectName ) ? TRUE : FALSE;\n\tconst BOOLEAN pkiUserNamePresent = \\\n\t\t\t\t\tDATAPTR_ISSET( pkiUserSubjectName ) ? TRUE : FALSE;\n\tBOOLEAN replaceCN = FALSE, dnContinues;\n\tint dummy, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( pkiUserDNptr, sizeof( pkiUserDNsize ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( DATAPTR_ISVALID( pkiUserSubjectName ) );\n\tREQUIRES( isShortIntegerRangeNZ( pkiUserDNsize ) );\n\tREQUIRES( requestFromRA == TRUE || requestFromRA == FALSE );\n\n\t/* Because a DN can be made up of elements from both the certificate \n\t   request and the PKI user information, it's possible that neither can\n\t   contain a DN, expecting it to be supplied by the other side.  \n\t   Although the lack of a DN would be caught anyway when the certificate\n\t   is signed, it's better to alert the caller at this early stage rather\n\t   than later on in the certification process.  First we check for an\n\t   overall missing DN and then for the more specific case of a missing \n\t   CN.\n\n\t   Note that both here and in all of the following checks we return an\n\t   error status of CRYPT_ERROR_INVALID rather than CRYPT_ERROR_NOTINITED\n\t   since this is a validity check of the certificate request against the\n\t   PKI user information and not a general object-ready-to-encode check */\n\tif( !certNamePresent && !pkiUserNamePresent )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( ( !certNamePresent || \\\n\t\t  cryptStatusError( \\\n\t\t\t\tgetDNComponentValue( certInfoPtr->subjectName, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_COMMONNAME, 0, NULL, 0, \n\t\t\t\t\t\t\t\t\t &dummy ) ) ) && \\\n\t\t( !pkiUserNamePresent || \\\n\t\t  cryptStatusError( \\\n\t\t\t\tgetDNComponentValue( pkiUserSubjectName, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_COMMONNAME, 0, NULL, 0, \n\t\t\t\t\t\t\t\t\t &dummy ) ) ) )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* If there's no DN present in the request then one has been supplied by \n\t   the CA in the PKI user information, copy over the DN and its encoded \n\t   form from the user information.  \n\t   \n\t   Note that this case also applies for when the PKI user is an RA and\n\t   they're obtaining their own certificate that's then used to authorise \n\t   further certificate issuance */\n\tif( !certNamePresent )\n\t\t{\n\t\tREQUIRES( pkiUserNamePresent && pkiUserDNptr != NULL );\n\n\t\tstatus = copyDN( &certInfoPtr->subjectName, pkiUserSubjectName );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tREQUIRES( rangeCheck( pkiUserDNsize, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( certInfoPtr->subjectDNdata = \\\n\t\t\t\tclAlloc( \"processReqDN\", pkiUserDNsize ) ) == NULL )\n\t\t\t{\n\t\t\tdeleteDN( &certInfoPtr->subjectName );\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tmemcpy( certInfoPtr->subjectDNdata, pkiUserDNptr, pkiUserDNsize );\n\t\tcertInfoPtr->subjectDNptr = certInfoPtr->subjectDNdata;\n\t\tcertInfoPtr->subjectDNsize = pkiUserDNsize;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's no PKI user DN with the potential to conflict with the one\n\t   in the request present, we're done */\n\tif( !pkiUserNamePresent )\n\t\treturn( CRYPT_OK );\n\n\t/* If there are full DNs present in both objects and they match then \n\t   there's nothing else to do */\n\tif( compareDN( certInfoPtr->subjectName, pkiUserSubjectName, \n\t\t\t\t   FALSE, NULL ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Now things get complicated because there are distinct request DN and \n\t   PKI user DNs present and we need to reconcile the two.  Typically the \n\t   CA will have provided a partial DN with the user providing the rest:\n\n\t\tpkiUser: A - B - C - D\n\t\trequest: A - B - C - D - E - F\n\n\t   in which case we could just allow the request DN (in theory we're \n\t   merging the two, but since the pkiUser DN is a proper subset of the \n\t   request DN it just acts as a filter).  The real problem though occurs \n\t   when we get a request like:\n\n\t\tpkiUser: A - B - C - D\n\t\trequest: X\n\n\t   where X can be any of:\n\n\t\t'D': Legal, this duplicates a single permitted element\n\t\t'E': Legal, this adds a new sub-element\n\t\t'D - E': Legal, this duplicates a legal element and adds a new sub-\n\t\t\telement\n\t\t'A - B - C - D#' where 'D#' doesn't match 'D', for example it's a CN \n\t\t\tthat differs from the pkiUser CN: Not legal since it violates a\n\t\t\tCA-imposed constraint.\n\t\t'A - B - C - D - E - F': Legal, this is the scenario given above \n\t\t\twhere one is a proper subset of the other.\n\t\t'D - A': This is somewhat dubious and probably not legal, for \n\t\t\texample if 'A' is a countryName.\n\t\t'D - A - B - C - D': This is almost certainly not legal because in a \n\t\t\thierarchy like this 'A' is probably a countryName so an attempt \n\t\t\tto merge the request DN at point 'D' in the pkiUser DN could \n\t\t\tlead to a malformed DN.\n\t\t'E - C - D - E': This may or may not be legal if the middle elements \n\t\t\tare things like O's and OU's, which can be mixed up arbitrarily.\n\n\t   Handling this really requires human intervention to decide what's \n\t   legal or not.  In the absence of an AI capability in the software\n\t   we restrict ourselves to allowing only two cases:\n\n\t\t1. If the PKI user contains a DN without a CN and the request\n\t\t   contains only a CN (typically used where the CA provides a\n\t\t   template for the user's DN and the user supplies only their\n\t\t   name), we merge the CA-provided DN-without-CN with the user-\n\t\t   provided CN.\n\n\t\t2. If the PKI user contains a DN without a CN and the request\n\t\t   contains a full DN (a variation of the above where the user\n\t\t   knows their full DN), we make sure that the rest of the DN\n\t\t   matches.\n\n\t   First we check that the user DN contains a CN, optionally preceded\n\t   by a prefix of the PKI user's DN, by passing them to compareDN(), \n\t   which checks whether the first DN is a proper subset of the second.  \n\t   Some sample DN configurations and their results are:\n\n\t\trequest = CN\t\t\t\tresult = FALSE, mismatchSubset = CN\n\t\tpkiUser = C - O - OU\n\n\t\trequest = ... X\t\t\t\tresult = FALSE, mismatchSubset = X\n\t\tpkiUser = C - O - OU\n\n\t\trequest = C - O - OU - CN\tresult = FALSE, mismatchSubset = CN\n\t\tpkiUser = C - O - OU\n\n\t\trequest = C - O - OU - CN1\tresult = FALSE, mismatchSubset = CN1\n\t\tpkiUser = C - O - OU - CN2\n\n\t\trequest = C - O - OU\t\tresult = TRUE, mismatchSubset = NULL\n\t\tpkiUser = C - O - OU - CN\n\n\t   If this is an RA user then things work slightly differently.  In \n\t   order to avoid an RA being able to approve the issuance of \n\t   certificates for any identity, we require that all portions of the DN \n\t   except the CN match the RA's DN, meaning that the request has to have \n\t   a full DN that matches (apart from the CN) or contains only a CN, \n\t   with the rest filled in from the RA's DN.\n\n\t   The set of DNs with a prefix-match-result of TRUE (in other words the\n\t   request contains a subset of the PKI user's DN) are trivially \n\t   invalid, so we can reject them immediately */\n\tif( compareDN( certInfoPtr->subjectName, pkiUserSubjectName, TRUE, \n\t\t\t\t   &requestDNSubset ) )\n\t\t{\n\t\t/* The issuer-constraint error is technically accurate if a little \n\t\t   unexpected at this point, since the PKIUser information has been \n\t\t   set as a constraint by the CA */\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* The request DN is a prefix (possibly an empty one) of the PKI user \n\t   DN, check that the mis-matching part is only a CN */\n\tstatus = getDNComponentInfo( requestDNSubset, &dnComponentType, \n\t\t\t\t\t\t\t\t &dnContinues );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* This is an even more problematic situation to report (since it's\n\t\t   a shouldn't-occur type error), the best that we can do is report\n\t\t   a generic issuer constraint */\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( dnComponentType != CRYPT_CERTINFO_COMMONNAME || dnContinues )\n\t\t{\n\t\t/* Check for the special case of there being no CN at all present in \n\t\t   the request DN, which lets us return a more specific error \n\t\t   indicator (this is a more specific case of the check performed\n\t\t   earlier for a CN in the request or the PKI user object) */\n\t\tstatus = getDNComponentValue( requestDNSubset, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME, 0, NULL, 0, \n\t\t\t\t\t\t\t\t\t  &dummy );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* The mismatching portion of the request DN isn't just a CN */\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* There's one special case that we have to handle where both DNs \n\t   consist of identical prefixes ending in CNs but the CNs differ, which \n\t   passes the above check.  We do this by reversing the order of the \n\t   match performed above, if what's left is also a CN then there was a \n\t   mismatch in the CNs */\n\tif( !compareDN( pkiUserSubjectName, certInfoPtr->subjectName, TRUE, \n\t\t\t\t\t&pkiUserDNSubset ) )\n\t\t{\n\t\tstatus = getDNComponentInfo( pkiUserDNSubset, &dnComponentType, \n\t\t\t\t\t\t\t\t\t &dnContinues );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* There's some sort of nonspecific error, treat it as a problem \n\t\t\t   with a missing/mismatched CN */\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\tif( dnComponentType == CRYPT_CERTINFO_COMMONNAME )\n\t\t\t{\n\t\t\t/* There is one situation in which a mismatched CN is valid and \n\t\t\t   that's where the PKI user is an RA, in which case the CN is\n\t\t\t   for the user being authorised by the RA rather than the RA \n\t\t\t   user themselves.  In this case we replace any possibly-\n\t\t\t   present RA CN with the one in the request */\n\t\t\tif( dnContinues || !requestFromRA )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\treplaceCN = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* If the request DN consists only of a CN, replace the request DN with \n\t   the merged DN prefix from the PKI user DN and the CN from the request \n\t   DN */\n\tif( DATAPTR_SAME( certInfoPtr->subjectName, requestDNSubset ) || \\\n\t\treplaceCN )\n\t\t{\n\t\tchar commonName[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint commonNameLength;\n\n\t\tstatus = getDNComponentValue( requestDNSubset, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME, 0, \n\t\t\t\t\t\t\t\t\t  commonName, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  &commonNameLength );\n\t\tif( cryptStatusOK( status ) )\n\t\treturn( assemblePkiUserDN( certInfoPtr, pkiUserSubjectName,\n\t\t\t\t\t\t\t\t   commonName, commonNameLength, \n\t\t\t\t\t\t\t\t   replaceCN ) );\n\t\t}\n\n\t/* The request DN contains a full DN including a CN that matches the \n\t   full PKI user DN and there's nothing to do beyond the checks that \n\t   we've already performed above */\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCopy PKI User Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set or modify data in a certificate request based on the PKI user \n   information.  This is rather more complicated than the standard copy\n   operations because we potentially have to merge information already\n   present in the request with information in the PKI user object, checking\n   for consistency/conflicts in the process */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint copyPkiUserToCertReq( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t  INOUT CERT_INFO *pkiUserInfoPtr )\n\t{\n\tBOOLEAN requestFromRA = FALSE;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( pkiUserInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT );\n\tREQUIRES( sanityCheckCert( pkiUserInfoPtr ) );\n\tREQUIRES( pkiUserInfoPtr->type == CRYPT_CERTTYPE_PKIUSER );\n\tREQUIRES( pkiUserInfoPtr->certificate != NULL );\n\n\t/* If the request came via an RA then this changes the DN constraint \n\t   handling.  Only CRMF requests support RA functionality so there's no \n\t   check for standard PKSC #10 requests */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\tBOOLEAN_INT value;\n\n\t\tstatus = getCertComponent( certInfoPtr, CRYPT_IATTRIBUTE_REQFROMRA, \n\t\t\t\t\t\t\t\t   &value );\n\t\tif( cryptStatusOK( status ) && value == TRUE )\n\t\t\trequestFromRA = TRUE;\n\t\t}\n\n\t/* Process the DN in the request and make sure that it's consistent with \n\t   the information for the PKI user */\n\tstatus = processReqDN( certInfoPtr, pkiUserInfoPtr->subjectName,\n\t\t\t\t\t\t   pkiUserInfoPtr->subjectDNptr, \n\t\t\t\t\t\t   pkiUserInfoPtr->subjectDNsize, requestFromRA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are no PKI user attributes present then we're done */\n\tif( DATAPTR_ISNULL( pkiUserInfoPtr->attributes ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Copy any additional attributes across */\n\treturn( copyPkiUserAttributes( certInfoPtr, \n\t\t\t\t\t\t\t\t   pkiUserInfoPtr->attributes ) );\n\t}\n#endif /* USE_CERTIFICATES && USE_PKIUSER */\n"
  },
  {
    "path": "deps/cl345/cert/comp_set.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSet Certificate Components\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSerial-Number Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set the serial number for a certificate.  In theory we could store this \n   as a static value in the configuration database but this has three\n   disadvantages: Updating the serial number updates the entire \n   configuration database (including things the user might not want\n   updated), if the configuration database update fails then the serial \n   number never changes, and the predictable serial number allows tracking \n   of the number of certificates that have been issued by the CA.  Because \n   of this we just use a 64-bit nonce if the user doesn't supply a value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSerialNumber( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t IN_BUFFER_OPT( serialNumberLength ) const void *serialNumber, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int serialNumberLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE *serialNumberPtr;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( serialNumber == NULL && serialNumberLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( serialNumber, serialNumberLength ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tREQUIRES( ( serialNumber == NULL && serialNumberLength == 0 ) || \\\n\t\t\t  ( serialNumber != NULL && \\\n\t\t\t\tserialNumberLength > 0 && \\\n\t\t\t\tserialNumberLength <= MAX_SERIALNO_SIZE ) );\n\n   \t/* Get a pointer to the location where we're going to store the new \n\t   serial number, either a user-supplied value or one that we've \n\t   generated ourselves.  However if a serial number has already been set \n\t   explicitly then we don't override it with an implicitly-set one */\n\tswitch( certInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\tif( certInfoPtr->cCertCert->serialNumber != NULL )\n\t\t\t\t{\n\t\t\t\tENSURES( serialNumber == NULL && serialNumberLength == 0 );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tserialNumberPtr = certInfoPtr->cCertCert->serialNumberBuffer;\n\t\t\tcertInfoPtr->cCertCert->serialNumber = serialNumberPtr;\n\t\t\tbreak;\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\tif( certInfoPtr->cCertReq->serialNumber != NULL )\n\t\t\t\t{\n\t\t\t\tENSURES( serialNumber == NULL && serialNumberLength == 0 );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tserialNumberPtr = certInfoPtr->cCertReq->serialNumberBuffer;\n\t\t\tcertInfoPtr->cCertReq->serialNumber = serialNumberPtr;\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* If we're using user-supplied serial number data, canonicalise it into\n\t   a form suitable for use as an INTEGER hole */\n\tif( serialNumber != NULL )\n\t\t{\n\t\tSTREAM stream;\n\t\tBYTE buffer[ 4 + MAX_SERIALNO_SIZE + 8 ];\n\t\tint bufPos;\n \n\t\tsMemOpen( &stream, buffer, 4 + MAX_SERIALNO_SIZE );\n\t\tstatus = writeInteger( &stream, serialNumber, serialNumberLength,\n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tbufPos = 2;\t\t/* Skip INTEGER tag + length at the start */\n\t\tlength -= 2;\n\n\t\t/* Now that we've canonicalised the serial number, check that its \n\t\t   size is still within bounds */\n\t\tif( length < 1 || length > MAX_SERIALNO_SIZE )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t/* If it's too long to fit into the certificate's internal serial-\n\t\t   number buffer, allocate storage for it dynamically */\n\t\tif( length > SERIALNO_BUFSIZE )\n\t\t\t{\n\t\t\tif( ( serialNumberPtr = clDynAlloc( \"setSerialNumber\", \n\t\t\t\t\t\t\t\t\t\t\t\tlength ) ) == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\n\t\t/* Copy across the canonicalised serial number value.  Since the \n\t\t   serial number data may now be held in dynamically-allocated \n\t\t   memory, we have to update the serial number pointer */\n\t\tmemcpy( serialNumberPtr, buffer + bufPos, length );\n#ifdef USE_CERTREV\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t{\n\t\t\tcertInfoPtr->cCertReq->serialNumber = serialNumberPtr;\n\t\t\tcertInfoPtr->cCertReq->serialNumberLength = length;\n\t\t\t}\n\t\telse\n#endif /* USE_CERTREV */\n\t\t\t{\n\t\t\tcertInfoPtr->cCertCert->serialNumber = serialNumberPtr;\n\t\t\tcertInfoPtr->cCertCert->serialNumberLength = length;\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Generate a random (but fixed-length) serial number, ensure that the \n\t   first byte of the value that we use is nonzero (to guarantee a DER \n\t   encoding), and clear the high bit to provide a constant-length ASN.1 \n\t   encoded value */\n\tstatic_assert( DEFAULT_SERIALNO_SIZE + 1 <= SERIALNO_BUFSIZE, \\\n\t\t\t\t   \"Buffer size\" );\n\tsetMessageData( &msgData, serialNumberPtr, DEFAULT_SERIALNO_SIZE + 1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tserialNumberPtr[ 0 ] &= 0x7F;\t/* Clear the sign bit */\n\tif( serialNumberPtr[ 0 ] == 0 )\n\t\t{\n\t\t/* The first byte is zero, see if we can use the extra byte of data \n\t\t   that we fetched as a nonzero byte.  If that's zero too, just set \n\t\t   it to 1 */\n\t\tserialNumberPtr[ 0 ] = \\\n\t\t\t\tintToByte( serialNumberPtr[ DEFAULT_SERIALNO_SIZE ] & 0x7F );\n\t\tif( serialNumberPtr[ 0 ] == 0 )\n\t\t\tserialNumberPtr[ 0 ] = 1;\n\t\t}\n\n\t/* Copy across the canonicalised serial number value */\n#ifdef USE_CERTREV\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tcertInfoPtr->cCertReq->serialNumberLength = DEFAULT_SERIALNO_SIZE;\n\t\t}\n\telse\n#endif /* USE_CERTREV */\n\t\t{\n\t\tcertInfoPtr->cCertCert->serialNumberLength = DEFAULT_SERIALNO_SIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Compare a serial number in canonical form to a generic serial number,\n   with special handling for leading-zero truncation.  This one can get a\n   bit tricky because for a long time Microsoft would fairly consistently \n   encode serial numbers incorrectly so we normalise the values to have no \n   leading zero, which is the lowest common denominator */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nBOOLEAN compareSerialNumber( IN_BUFFER( canonSerialNumberLength ) \\\n\t\t\t\t\t\t\t\tconst void *canonSerialNumber,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int canonSerialNumberLength,\n\t\t\t\t\t\t\t IN_BUFFER( serialNumberLength ) \\\n\t\t\t\t\t\t\t\tconst void *serialNumber,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int serialNumberLength )\n\t{\n\tconst BYTE *canonSerialNumberPtr = canonSerialNumber;\n\tconst BYTE *serialNumberPtr = serialNumber;\n\tint canonSerialLength = canonSerialNumberLength;\n\tint serialLength, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( canonSerialNumber, canonSerialNumberLength ) );\n\tassert( isReadPtrDynamic( serialNumber, serialNumberLength ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( canonSerialNumberLength ) );\n\tREQUIRES_B( isShortIntegerRangeNZ( serialNumberLength ) );\n\n\t/* Internal serial numbers are canonicalised so all we need to do is \n\t   strip a possible leading zero */\n\tif( canonSerialNumberPtr[ 0 ] == 0 )\n\t\t{\n\t\tcanonSerialNumberPtr++;\n\t\tcanonSerialLength--;\n\t\t}\n\tENSURES_B( canonSerialLength == 0 || canonSerialNumberPtr[ 0 ] != 0 );\n\n\t/* Serial numbers from external sources can be arbitarily strangely\n\t   encoded so we strip leading zeroes until we get to actual data */\n\tLOOP_LARGE( serialLength = serialNumberLength,\n\t\t\t\tserialLength > 0 && serialNumberPtr[ 0 ] == 0,\n\t\t\t\t( serialLength--, serialNumberPtr++ ) );\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Finally we've got them in a form where we can compare them */\n\tif( canonSerialLength != serialLength )\n\t\treturn( FALSE );\n\tif( canonSerialLength <= 0 )\n\t\t{\n\t\t/* It's an all-zeroes serialNumber, there's nothing to compare */\n\t\treturn( TRUE );\n\t\t}\n\treturn( memcmp( canonSerialNumberPtr, serialNumberPtr, \n\t\t\t\t\tserialLength ) ? FALSE : TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSet Miscellaneous Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set XYZZY certificate information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setXyzzyInfo( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\tCRYPT_ERRTYPE_TYPE dummy2;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tconst time_t currentTime = getApproxTime();\n\tint isXyzzyCert, keyUsage = CRYPT_KEYUSAGE_NONE, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* Make sure that we haven't already set up this certificate as a XYZZY\n\t   certificate */\n\tstatus = getCertComponent( certInfoPtr, CRYPT_CERTINFO_XYZZY, \n\t\t\t\t\t\t\t   &isXyzzyCert );\n\tif( cryptStatusOK( status ) && isXyzzyCert )\n\t\t{\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_XYZZY,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* Get the appropriate key usage types that are possible for this\n\t   certificate.  We only do this if there's a key present, if it hasn't \n\t   been set yet (in other words if the caller sets CRYPT_CERTINFO_XYZZY \n\t   before they set CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO) then this will\n\t   be done in the code that sets the public key */\n\tif( certInfoPtr->publicKeyAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = checkKeyUsage( certInfoPtr, CHECKKEY_FLAG_NONE, \n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT,\n\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_STANDARD,\n\t\t\t\t\t\t\t\t&dummy1, &dummy2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tkeyUsage = CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\tstatus = checkKeyUsage( certInfoPtr, CHECKKEY_FLAG_NONE, \n\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_DIGITALSIGNATURE,\n\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_STANDARD,\n\t\t\t\t\t\t\t\t&dummy1, &dummy2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tkeyUsage |= KEYUSAGE_SIGN | KEYUSAGE_CA;\n\t\tif( !( keyUsage & CRYPT_KEYUSAGE_DIGITALSIGNATURE ) )\n\t\t\t{\n\t\t\t/* We have to have at least a signing capability available in \n\t\t\t   order to create a self-signed certificate */\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* Clear any existing attribute values before trying to set new ones.  \n\t   We don't check the return values for these operations because we \n\t   could get a success or error status depending on whether a component \n\t   is present or not, and in any case any problem with deleting a \n\t   present component will be caught when we try and set the new value\n\t   further on */\n\tcertInfoPtr->startTime = certInfoPtr->endTime = 0;\n\t( void ) deleteCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE );\n\t( void ) deleteCertComponent( certInfoPtr, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTIFICATEPOLICIES );\n\n\t/* Give the certificate a 20-year expiry time, make it a self-signed CA \n\t   certificate with all key usage types enabled, and set the policy OID \n\t   to identify it as a XYZZY certificate */\n\tcertInfoPtr->startTime = currentTime;\n\tcertInfoPtr->endTime = certInfoPtr->startTime + ( 86400L * 365 * 20 );\n\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\tstatus = addCertComponent( certInfoPtr, CRYPT_CERTINFO_CA, TRUE );\n\tif( cryptStatusOK( status ) && keyUsage != CRYPT_KEYUSAGE_NONE )\n\t\t{\n\t\tstatus = addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\t\t   keyUsage );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = addCertComponentString( certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CERTPOLICYID,\n\t\t\t\t\t\t\t\t\t\t OID_CRYPTLIB_XYZZYCERT,\n\t\t\t\t\t\t\t\t\t\t sizeofOID( OID_CRYPTLIB_XYZZYCERT ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tattributePtr = findAttributeFieldEx( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CERTPOLICYID );\n\t\tENSURES( DATAPTR_ISSET( attributePtr ) );\n\t\tsetAttributeProperty( attributePtr, ATTRIBUTE_PROPERTY_LOCKED, 0 );\n\t\t}\n\treturn( status );\n\t}\n\n#ifdef USE_CERT_DNSTRING\n\n/* Convert a DN in string form into a certificate DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getEncodedDn( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( dnStringLength ) const void *dnString,\n\t\t\t\t\t\t IN_LENGTH_ATTRIBUTE const int dnStringLength )\n\t{\n\tSELECTION_STATE savedState;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( dnString, dnStringLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dnStringLength ) );\n\n\t/* If there's already a DN set then we can't do anything else.  Since \n\t   this potentially changes the DN selection state, we save the state \n\t   around the check */\n\tsaveSelectionState( savedState, certInfoPtr );\n\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE, MUST_BE_PRESENT );\n\tif( cryptStatusOK( status ) && \\\n\t\tDATAPTR_ISNULL_PTR( certInfoPtr->currentSelection.dnPtr ) )\n\t\t{\n\t\t/* There's a DN selected but it's empty (in other words it's been \n\t\t   marked for create-on-access but doesn't actually exist yet), \n\t\t   we're OK */\n\t\tstatus = CRYPT_ERROR;\n\t\t}\n\trestoreSelectionState( savedState, certInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* Read the entire DN from its string form into the selected DN */\n\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE, CREATE_IF_ABSENT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readDNstring( certInfoPtr->currentSelection.dnPtr,\n\t\t\t\t\t\t   dnString, dnStringLength );\n\tif( cryptStatusOK( status ) && \\\n\t\tcertInfoPtr->currentSelection.updateCursor )\n\t\t{\n\t\t/* If we couldn't update the cursor earlier on because the attribute\n\t\t   field in question hadn't been created yet, do it now.  Since this \n\t\t   is merely a side-effect of the DN-read operation we ignore the \n\t\t   return status */\n\t\t( void ) selectGeneralName( certInfoPtr,\n\t\t\t\t\t\t\t\t\tcertInfoPtr->currentSelection.generalName,\n\t\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\t\t}\n\treturn( status );\n\t}\n#endif /* USE_CERT_DNSTRING */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAdd a Component\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a certificate component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addCertComponent( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t  const int certInfo )\n\t{\n\tCRYPT_CERTIFICATE addedCert;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\n\t/* If we're adding data to a certificate, clear the error information */\n\tif( !isPseudoInformation( certInfoType ) )\n\t\tclearErrorInfo( certInfoPtr );\n\n\t/* If it's a GeneralName or DN selection component, add it.  These are \n\t   special-case attribute values so they have to come before the \n\t   attribute-handling code */\n\tif( isGeneralNameSelectionComponent( certInfoType ) )\n\t\t{\n\t\tstatus = selectGeneralName( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t   MUST_BE_PRESENT ) );\n\t\t}\n\n\t/* If it's standard certificate or CMS attribute, add it to the \n\t   certificate */\n\tif( isValidExtension( certInfoType ) )\n\t\t{\n\t\tint localCertInfoType = certInfoType;\n\n\t\t/* Revocation reason codes are actually a single range of values\n\t\t   spread across two different extensions so we adjust the\n\t\t   (internal) type based on the reason code value */\n\t\tif( certInfoType == CRYPT_CERTINFO_CRLREASON || \\\n\t\t\tcertInfoType == CRYPT_CERTINFO_CRLEXTREASON )\n\t\t\t{\n\t\t\tlocalCertInfoType = ( certInfo < CRYPT_CRLREASON_LAST ) ? \\\n\t\t\t\t\tCRYPT_CERTINFO_CRLREASON : CRYPT_CERTINFO_CRLEXTREASON;\n\t\t\t}\n\n\t\t/* If it's a CRL, RTCS, or OCSP per-entry attribute, add the\n\t\t   attribute to the currently selected entry unless it's a\n\t\t   revocation request, in which case it goes in with the main\n\t\t   attributes */\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\t\tif( isRevocationEntryComponent( localCertInfoType ) && \\\n\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t{\n\t\t\tswitch( certInfoPtr->type )\n\t\t\t\t{\n  #ifdef USE_CERTVAL\n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\t\t\t{\n\t\t\t\t\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\t\t\t\t\tVALIDITY_INFO *validityInfoPtr;\n\n\t\t\t\t\tif( DATAPTR_ISNULL( certValInfo->currentValidity ) )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\t\t\tENSURES( validityInfoPtr != NULL );\n\t\t\t\t\treturn( addAttributeField( &validityInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\tcertInfo, ATTR_FLAG_NONE, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorType ) );\n\t\t\t\t\t}\n  #endif /* USE_CERTVAL */\n  #ifdef USE_CERTREV\n\t\t\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t\t\t{\n\t\t\t\t\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\t\t\t\tREVOCATION_INFO *revInfoPtr;\n\n\t\t\t\t\tif( DATAPTR_ISNULL( certRevInfo->currentRevocation ) )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\t\t\tENSURES( revInfoPtr != NULL );\n\t\t\t\t\treturn( addAttributeField( &revInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\tcertInfo, ATTR_FLAG_NONE, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorType ) );\n\t\t\t\t\t}\n  #endif /* USE_CERTREV */\n\t\t\t\t}\n\n\t\t\tretIntError();\n\t\t\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n\t\treturn( addAttributeField( &certInfoPtr->attributes,\n\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE, certInfo, \n\t\t\t\t\t\tATTR_FLAG_NONE,  &certInfoPtr->errorLocus, \n\t\t\t\t\t\t&certInfoPtr->errorType ) );\n\t\t}\n\n\t/* If it's anything else, handle it specially */\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_SELFSIGNED:\n\t\t\tif( certInfo )\n\t\t\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\telse\n\t\t\t\tCLEAR_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_XYZZY:\n\t\t\treturn( setXyzzyInfo( certInfoPtr ) );\n\n\t\tcase CRYPT_CERTINFO_CURRENT_CERTIFICATE:\n\t\t\treturn( setCertificateCursor( certInfoPtr, certInfo ) );\n\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\treturn( setAttributeCursor( certInfoPtr, certInfoType, certInfo ) );\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_USAGE:\n\t\t\tcertInfoPtr->cCertCert->trustedUsage = certInfo;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_TRUSTED_IMPLICIT:\n\t\t\t{\n\t\t\tint value;\n\n\t\t\t/* This option is only valid for CA certificates */\n\t\t\tstatus = getAttributeFieldValue( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &value );\n\t\t\tif( cryptStatusError( status ) || !( value & KEYUSAGE_CA ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CA,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\treturn( krnlSendMessage( certInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t\t IMESSAGE_USER_TRUSTMGMT,\n\t\t\t\t\t\t\t\t\t &certInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t certInfo ? MESSAGE_TRUSTMGMT_ADD : \\\n\t\t\t\t\t\t\t\t\t\t\t\tMESSAGE_TRUSTMGMT_DELETE ) );\n\t\t\t}\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_SIGNATURELEVEL:\n\t\t\tcertInfoPtr->cCertRev->signatureLevel = certInfo;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREV */\n\n\t\tcase CRYPT_CERTINFO_VERSION:\n\t\t\tcertInfoPtr->version = certInfo;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO:\n\t\t\treturn( copyPublicKeyInfo( certInfoPtr, certInfo, NULL ) );\n\n\t\tcase CRYPT_CERTINFO_CERTIFICATE:\n\t\t\t/* If it's a certificate, copy across various components or\n\t\t\t   store the entire certificate where required */\n\t\t\tstatus = krnlSendMessage( certInfo, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t\t  &addedCert, OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* If it's a certificate chain then we're adding the complete \n\t\t\t   certificate, just store it and exit */\n\t\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t\t{\n\t\t\t\tCERT_CERT_INFO *certCertInfoPtr = certInfoPtr->cCertCert;\n\t\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\t\tif( certCertInfoPtr->chainEnd >= MAX_CHAINLENGTH - 1 )\n\t\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t\t\t/* Perform a simple check to make sure that it hasn't been\n\t\t\t\t   added already */\n\t\t\t\tLOOP_EXT( i = 0, \n\t\t\t\t\t\t  i < certCertInfoPtr->chainEnd && i < MAX_CHAINLENGTH,\n\t\t\t\t\t\t  i++, MAX_CHAINLENGTH + 1 )\n\t\t\t\t\t{\n\t\t\t\t\tif( cryptStatusOK( \\\n\t\t\t\t\t\tkrnlSendMessage( addedCert, IMESSAGE_COMPARE,\n\t\t\t\t\t\t\t\t\t\t &certCertInfoPtr->chain[ i ],\n\t\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_CERTOBJ ) ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tsetErrorInfo( certInfoPtr,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t\t\t/* Add the user certificate and increment its reference \n\t\t\t\t   count */\n\t\t\t\tkrnlSendNotifier( addedCert, IMESSAGE_INCREFCOUNT );\n\t\t\t\tcertCertInfoPtr->chain[ certCertInfoPtr->chainEnd++ ] = addedCert;\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\treturn( copyCertObject( certInfoPtr, addedCert, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTIFICATE, certInfo ) );\n\n\t\tcase CRYPT_CERTINFO_CACERTIFICATE:\n\t\t\t/* We can't add another CA certificate if there's already one \n\t\t\t   present, in theory this is valid but it's more likely to be \n\t\t\t   an implementation problem than an attempt to query multiple \n\t\t\t   CAs through a single responder */\n\t\t\tif( certInfoPtr->certHashSet )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CACERTIFICATE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\t/* Get the certificate handle and make sure that it really is a \n\t\t\t   CA certificate */\n\t\t\tstatus = krnlSendMessage( certInfo, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t\t  &addedCert, OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( !checkContextCapability( addedCert, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGCHECK_CA ) && \\\n\t\t\t\t!checkContextCapability( addedCert, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN_CA ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\treturn( copyCertObject( certInfoPtr, addedCert, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CACERTIFICATE, CRYPT_UNUSED ) );\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTINFO_CERTREQUEST:\n\t\t\t/* Make sure that we haven't already got a public key (either as\n\t\t\t   a context or encoded key data) or DN present */\n\t\t\tif( ( certInfoPtr->iPubkeyContext != CRYPT_ERROR || \\\n\t\t\t\t  certInfoPtr->publicKeyInfo != NULL ) || \\\n\t\t\t\tDATAPTR_ISSET( certInfoPtr->subjectName ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTREQUEST,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\treturn( copyCertObject( certInfoPtr, certInfo, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTREQUEST, CRYPT_UNUSED ) );\n#endif /* USE_CERTREQ */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTINFO_PKIUSER_RA:\n\t\t\t/* Make sure that this flag isn't already set */\n\t\t\tif( certInfoPtr->cCertUser->isRA )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CERTREQUEST,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\tcertInfoPtr->cCertUser->isRA = certInfo;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PKIUSER */\n\n\t\tcase CRYPT_IATTRIBUTE_CERTCOLLECTION:\n\t\t\treturn( copyCertChain( certInfoPtr, certInfo, TRUE ) );\n\n\t\tcase CRYPT_IATTRIBUTE_RTCSREQUEST:\n\t\tcase CRYPT_IATTRIBUTE_OCSPREQUEST:\n\t\tcase CRYPT_IATTRIBUTE_REVREQUEST:\n\t\tcase CRYPT_IATTRIBUTE_PKIUSERINFO:\n#ifdef USE_DBMS\t/* Only used by CA code */\n\t\tcase CRYPT_IATTRIBUTE_BLOCKEDATTRS:\n#endif /* USE_DBMS */\n\t\t\treturn( copyCertObject( certInfoPtr, certInfo, certInfoType, \n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED ) );\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_IATTRIBUTE_REQFROMRA:\n\t\t\tcertInfoPtr->cCertReq->requestFromRA = certInfo;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREQ */\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addCertComponentString( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\tIN_BUFFER( certInfoLength ) const void *certInfo, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int certInfoLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtrDynamic( certInfo, certInfoLength ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isAttribute( certInfoType ) || \\\n\t\t\t  isInternalAttribute( certInfoType ) );\n\tREQUIRES( isShortIntegerRangeNZ( certInfoLength ) );\n\n\t/* If we're adding data to a certificate, clear the error information */\n\tif( !isPseudoInformation( certInfoType ) )\n\t\tclearErrorInfo( certInfoPtr );\n\n\t/* If it's a GeneralName or DN component, add it.  These are special-\n\t   case attribute values so they have to come before the attribute-\n\t   handling code */\n\tif( isGeneralNameComponent( certInfoType ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE fieldID;\n\t\tSELECTION_INFO savedSelectionInfo DUMMY_INIT_STRUCT;\n\t\tBOOLEAN isImplicitSelect = FALSE, cursorInGeneralName = FALSE;\n\n\t\t/* GeneralName DN components have an awkward special-case processing\n\t\t   requirement based on the fact that we try and hide the need to\n\t\t   stuff a value like an email address or server name into an altName\n\t\t   extension in order to be able to store it.  This means that, while\n\t\t   adding a CN just adds a CN, adding an email address needs to do:\n\n\t\t\tcreate altName if required;\n\t\t\tselect altName;\n\t\t\tadd email address (to altName);\n\n\t\t   However, once the altName has been implicitly selected in this\n\t\t   manner, adding further DN components adds them to the (implicitly-\n\t\t   selected) DN in the altName rather than the subjectName.\n\n\t\t   Because of this, if the currently selected DN is the subjectName\n\t\t   then we have to reset the selection after we add the component to\n\t\t   ensure that subsequent DN values don't end up in the altName DN */\n\t\tif( isSubjectNameSelected( certInfoPtr ) || \\\n\t\t\tisIssuerNameSelected( certInfoPtr ) )\n\t\t\t{\n\t\t\tsavedSelectionInfo = certInfoPtr->currentSelection;\n\t\t\tisImplicitSelect = TRUE;\n\t\t\t}\n\n\t\t/* Another special-case situation can occur when the cursor is \n\t\t   pointing at the GeneralName and the addition of the new attribute\n\t\t   field changes the structure of the GeneralName.  In the worst \n\t\t   case a new GeneralName field may be added before the current\n\t\t   cursor position, so that after the add it points past the start \n\t\t   of the GeneralName.  To deal with this we have to remember to fix \n\t\t   up the cursor after the add if required */\n\t\tif( DATAPTR_ISSET( certInfoPtr->attributes ) && \\\n\t\t\tDATAPTR_SAME( certInfoPtr->attributes, \n\t\t\t\t\t\t  certInfoPtr->attributeCursor ) )\n\t\t\tcursorInGeneralName = TRUE;\n\n\t\tstatus = selectGeneralName( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\tCREATE_IF_ABSENT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( DATAPTR_ISSET( certInfoPtr->attributeCursor ) )\n\t\t\t{\n\t\t\tstatus = getAttributeIdInfo( certInfoPtr->attributeCursor, NULL, \n\t\t\t\t\t\t\t\t\t\t &fieldID, NULL );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\tfieldID = certInfoPtr->currentSelection.generalName;\n\t\tstatus = addAttributeFieldString( &certInfoPtr->attributes, \n\t\t\t\t\t\t\tfieldID, certInfoType, certInfo, certInfoLength, \n\t\t\t\t\t\t\tATTR_FLAG_NONE, &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( isImplicitSelect )\n\t\t\t{\n\t\t\t/* The GeneralName was implicitly selected (for example by the \n\t\t\t   addition of an email address, which switches the selection \n\t\t\t   from the subjectName to the altName), re-select the original\n\t\t\t   name */\n\t\t\tcertInfoPtr->currentSelection = savedSelectionInfo;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If we couldn't update the cursor earlier on because the\n\t\t\t   attribute field in question hadn't been created yet, do it\n\t\t\t   now.  Since this is merely a side-effect of this operation, \n\t\t\t   we ignore the return status */\n\t\t\tif( certInfoPtr->currentSelection.updateCursor )\n\t\t\t\t{\n\t\t\t\t( void ) selectGeneralName( certInfoPtr,\n\t\t\t\t\t\t\t\tcertInfoPtr->currentSelection.generalName,\n\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cursorInGeneralName && \\\n\t\t\t!DATAPTR_SAME( certInfoPtr->attributes, \n\t\t\t\t\t\t   certInfoPtr->attributeCursor ) )\n\t\t\t{\n\t\t\t/* The attribute cursor was pointing at the GeneralName, but the\n\t\t\t   addition of a new field has modified its structure, we need \n\t\t\t   to reset the cursor to point at the start of the updated\n\t\t\t   GeneralName.  This is somewhat complex because the \n\t\t\t   GeneralName is still selected, but the cursor now points past\n\t\t\t   the start of it, so an isGeneralNameSelected() check in\n\t\t\t   comp_curs.c will always pass.  To deal with this, we \n\t\t\t   explicitly clear the attribute cursor and then tell\n\t\t\t   selectGeneralName() to re-select the GeneralName, which sets\n\t\t\t   the cursor to the start of the GeneralName */\n\t\t\tDATAPTR_SET( certInfoPtr->attributeCursor, NULL );\n\t\t\tcertInfoPtr->currentSelection.generalName = fieldID;\n\t\t\tstatus = selectGeneralName( certInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\tMUST_BE_PRESENT );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( isDNComponent( certInfoType ) )\n\t\t{\n\t\t/* Add the string component to the DN */\n\t\tstatus = selectDN( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t   CREATE_IF_ABSENT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcertInfoPtr->errorLocus = certInfoType;\n\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = insertDNComponent( certInfoPtr->currentSelection.dnPtr,\n\t\t\t\t\t\t\t\t\tcertInfoType, certInfo, \n\t\t\t\t\t\t\t\t\tcertInfoLength, &certInfoPtr->errorType );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tcertInfoPtr->currentSelection.updateCursor )\n\t\t\t{\n\t\t\t/* If we couldn't update the cursor earlier on because the\n\t\t\t   attribute field in question hadn't been created yet, do it\n\t\t\t   now.  Since this is merely a side-effect of this operation, \n\t\t\t   we ignore the return status */\n\t\t\t( void ) selectGeneralName( certInfoPtr,\n\t\t\t\t\t\t\t\t\t\tcertInfoPtr->currentSelection.generalName,\n\t\t\t\t\t\t\t\t\t\tMAY_BE_ABSENT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_MEMORY )\n\t\t\tcertInfoPtr->errorLocus = certInfoType;\n\t\treturn( status );\n\t\t}\n\n\t/* If it's standard certificate or CMS attribute, add it to the \n\t   certificate */\n\tif( isValidExtension( certInfoType ) )\n\t\t{\n\t\tint localCertInfoType = certInfoType;\n\n\t\t/* If it's a CRL, RTCS, or OCSP per-entry attribute, add the\n\t\t   attribute to the currently selected entry unless it's a\n\t\t   revocation request, in which case it goes in with the main\n\t\t   attributes */\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\t\tif( isRevocationEntryComponent( localCertInfoType ) && \\\n\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t{\n\t\t\tswitch( certInfoPtr->type )\n\t\t\t\t{\n  #ifdef USE_CERTVAL\n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\t\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\t\t\t{\n\t\t\t\t\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\t\t\t\t\tVALIDITY_INFO *validityInfoPtr;\n\n\t\t\t\t\tif( DATAPTR_ISNULL( certValInfo->currentValidity ) )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\tvalidityInfoPtr = DATAPTR_GET( certValInfo->currentValidity );\n\t\t\t\t\tENSURES( validityInfoPtr != NULL );\n\t\t\t\t\treturn( addAttributeFieldString( &validityInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\tcertInfo, certInfoLength, ATTR_FLAG_NONE,\n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorType ) );\n\t\t\t\t\t}\n  #endif /* USE_CERTVAL */\n  #ifdef USE_CERTREV\n\t\t\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t\t\t{\n\t\t\t\t\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\t\t\t\t\tREVOCATION_INFO *revInfoPtr;\n\n\t\t\t\t\tif( DATAPTR_ISNULL( certRevInfo->currentRevocation ) )\n\t\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\t\t\t\tENSURES( revInfoPtr != NULL );\n\t\t\t\t\treturn( addAttributeFieldString( &revInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\tcertInfo, certInfoLength, ATTR_FLAG_NONE,\n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t&certInfoPtr->errorType ) );\n\t\t\t\t\t}\n  #endif /* USE_CERTREV */\n\t\t\t\t}\n\n\t\t\tretIntError();\n\t\t\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n\t\treturn( addAttributeFieldString( &certInfoPtr->attributes,\n\t\t\t\t\t\tlocalCertInfoType, CRYPT_ATTRIBUTE_NONE, certInfo, \n\t\t\t\t\t\tcertInfoLength, ATTR_FLAG_NONE, \n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType ) );\n\t\t}\n\n\t/* If it's anything else, handle it specially */\n\tswitch( certInfoType )\n\t\t{\n\t\tcase CRYPT_CERTINFO_SERIALNUMBER:\n\t\t\tENSURES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE );\n\t\t\tif( certInfoPtr->cCertCert->serialNumber != NULL )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\treturn( setSerialNumber( certInfoPtr, certInfo,\n\t\t\t\t\t\t\t\t\t certInfoLength ) );\n\n\t\tcase CRYPT_CERTINFO_VALIDFROM:\n\t\tcase CRYPT_CERTINFO_THISUPDATE:\n\t\t\t{\n\t\t\tconst time_t certTime = *( ( time_t * ) certInfo );\n\n\t\t\tif( certInfoPtr->startTime > 0 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\tif( certInfoPtr->endTime > 0 && \\\n\t\t\t\tcertTime >= certInfoPtr->endTime )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr,\n\t\t\t\t\t\t\t  ( certInfoType == CRYPT_CERTINFO_VALIDFROM ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_VALIDTO : CRYPT_CERTINFO_NEXTUPDATE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tcertInfoPtr->startTime = certTime;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_CERTINFO_VALIDTO:\n\t\tcase CRYPT_CERTINFO_NEXTUPDATE:\n\t\t\t{\n\t\t\tconst time_t certTime = *( ( time_t * ) certInfo );\n\n\t\t\tif( certInfoPtr->endTime > 0 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\tif( certInfoPtr->startTime > 0 && \\\n\t\t\t\tcertTime <= certInfoPtr->startTime )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr,\n\t\t\t\t\t\t\t  ( certInfoType == CRYPT_CERTINFO_VALIDTO ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_VALIDFROM : CRYPT_CERTINFO_THISUPDATE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tcertInfoPtr->endTime = certTime;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTINFO_REVOCATIONDATE:\n\t\t\t{\n\t\t\tconst time_t certTime = *( ( time_t * ) certInfo );\n\t\t\ttime_t *revocationTimePtr = getRevocationTimePtr( certInfoPtr );\n\n\t\t\tif( revocationTimePtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tif( *revocationTimePtr > 0 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( certInfoPtr, certInfoType,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\t*revocationTimePtr = certTime;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERT_DNSTRING\n\t\tcase CRYPT_CERTINFO_DN:\n\t\t\treturn( getEncodedDn( certInfoPtr, certInfo, certInfoLength ) );\n#endif /* USE_CERT_DNSTRING */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_IATTRIBUTE_CRLENTRY:\n\t\t\t{\n\t\t\tSTREAM stream;\n\n\t\t\tENSURES( certInfoPtr->type == CRYPT_CERTTYPE_CRL );\n\n\t\t\t/* The revocation information is being provided to us in pre-\n\t\t\t   encoded form from a certificate store, decode it so that we \n\t\t\t   can add it to the CRL */\n\t\t\tsMemConnect( &stream, certInfo, certInfoLength );\n\t\t\tstatus = readCRLentry( &stream,\n\t\t\t\t\t\t\t\t   &certInfoPtr->cCertRev->revocations, 0,\n\t\t\t\t\t\t\t\t   &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t   &certInfoPtr->errorType );\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_IATTRIBUTE_AUTHCERTID:\n\t\t\tENSURES( certInfoLength == KEYID_SIZE );\n\t\t\tmemcpy( certInfoPtr->cCertReq->authCertID, certInfo, \n\t\t\t\t\tKEYID_SIZE );\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_CERTREQ */\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/dn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate DN Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"dn.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/dn.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDN Information Tables\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A macro to make make declaring DN OIDs simpler */\n\n#define MKDNOID( value )\t\t\tMKOID( \"\\x06\\x03\" value )\n\n/* Type information for DN components.  If the OID doesn't correspond to a \n   valid cryptlib component (i.e. it's one of the 1,001 other odd things that \n   can be crammed into a DN) then we can't directly identify it with a type \n   but instead return a simple integer value in the information table.  This \n   works because the certificate component values don't start until x000 */\n\nstatic const DN_COMPONENT_INFO certInfoOIDs[] = {\n\t/* Useful components, identified by attribute */\n\t{ CRYPT_CERTINFO_COMMONNAME, MKDNOID( \"\\x55\\x04\\x03\" ), \n\t  \"cn\", 2, \"oid.2.5.4.3\", 11, CRYPT_MAX_TEXTSIZE, FALSE, TRUE },\n\t{ CRYPT_CERTINFO_COUNTRYNAME, MKDNOID( \"\\x55\\x04\\x06\" ), \n\t  \"c\", 1, \"oid.2.5.4.6\", 11, 2, FALSE, FALSE },\n\t{ CRYPT_CERTINFO_LOCALITYNAME, MKDNOID( \"\\x55\\x04\\x07\" ), \n\t  \"l\", 1, \"oid.2.5.4.7\", 11, 128, FALSE, TRUE },\n\t{ CRYPT_CERTINFO_STATEORPROVINCENAME, MKDNOID( \"\\x55\\x04\\x08\" ), \n\t  \"sp\", 2, \"oid.2.5.4.8\", 11, 128, FALSE, TRUE },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, MKDNOID( \"\\x55\\x04\\x0A\" ), \n\t  \"o\", 1, \"oid.2.5.4.10\", 12, CRYPT_MAX_TEXTSIZE, FALSE, TRUE },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, MKDNOID( \"\\x55\\x04\\x0B\" ), \n\t  \"ou\", 2, \"oid.2.5.4.11\", 12, CRYPT_MAX_TEXTSIZE, FALSE, TRUE },\n\n\t/* Non-useful components, identified by index value */\n\t{ 1, MKDNOID( \"\\x55\\x04\\x01\" ),\t\t/* aliasObjectName (2 5 4 1) */\n\t  \"oid.2.5.4.1\", 11, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 2, MKDNOID( \"\\x55\\x04\\x02\" ),\t\t/* knowledgeInformation (2 5 4 2) */\n\t  \"oid.2.5.4.2\", 11, NULL, 0, MAX_ATTRIBUTE_SIZE /*32768*/, FALSE, FALSE },\n\t{ 3, MKDNOID( \"\\x55\\x04\\x04\" ),\t\t/* surname (2 5 4 4) */\n\t  \"s\", 1, \"oid.2.5.4.4\", 11, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 4, MKDNOID( \"\\x55\\x04\\x05\" ),\t\t/* serialNumber (2 5 4 5) */\n\t  \"sn\", 2, \"oid.2.5.4.5\", 11, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 5, MKDNOID( \"\\x55\\x04\\x09\" ),\t\t/* streetAddress (2 5 4 9) */\n\t  \"st\", 2, \"oid.2.5.4.9\", 11, 128, FALSE, FALSE },\n\t{ 6, MKDNOID( \"\\x55\\x04\\x0C\" ),\t\t/* title (2 5 4 12) */\n\t  \"t\", 1, \"oid.2.5.4.12\", 12, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 7, MKDNOID( \"\\x55\\x04\\x0D\" ),\t\t/* description (2 5 4 13) */\n\t  \"d\", 1, \"oid.2.5.4.13\", 12, 1024, FALSE, FALSE },\n\t{ 8, MKDNOID( \"\\x55\\x04\\x0E\" ),\t\t/* searchGuide (2 5 4 14) */\n\t  \"oid.2.5.4.14\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 9, MKDNOID( \"\\x55\\x04\\x0F\" ),\t\t/* businessCategory (2 5 4 15) */\n\t  \"bc\", 2, \"oid.2.5.4.15\", 12, 128, FALSE, FALSE },\n\t{ 10, MKDNOID( \"\\x55\\x04\\x10\" ),\t/* postalAddress (2 5 4 16) */\n\t  \"oid.2.5.4.16\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 11, MKDNOID( \"\\x55\\x04\\x11\" ),\t/* postalCode (2 5 4 17) */\n\t  \"oid.2.5.4.17\", 12, NULL, 0, 40, FALSE, FALSE },\n\t{ 12, MKDNOID( \"\\x55\\x04\\x12\" ),\t/* postOfficeBox (2 5 4 18) */\n\t  \"oid.2.5.4.18\", 12, NULL, 0, 40, FALSE, FALSE },\n\t{ 13, MKDNOID( \"\\x55\\x04\\x13\" ),\t/* physicalDeliveryOfficeName (2 5 4 19) */\n\t  \"oid.2.5.4.19\", 12, NULL, 0, 128, FALSE, FALSE },\n\t{ 14, MKDNOID( \"\\x55\\x04\\x14\" ),\t/* telephoneNumber (2 5 4 20) */\n\t  \"oid.2.5.4.20\", 12, NULL, 0, 32, FALSE, FALSE },\n\t{ 15, MKDNOID( \"\\x55\\x04\\x15\" ),\t/* telexNumber (2 5 4 21) */\n\t  \"oid.2.5.4.21\", 12, NULL, 0, 14, FALSE, FALSE },\n\t{ 16, MKDNOID( \"\\x55\\x04\\x16\" ),\t/* teletexTerminalIdentifier (2 5 4 22) */\n\t  \"oid.2.5.4.22\", 12, NULL, 0, 24, FALSE, FALSE },\n\t{ 17, MKDNOID( \"\\x55\\x04\\x17\" ),\t/* facsimileTelephoneNumber (2 5 4 23) */\n\t  \"oid.2.5.4.23\", 12, NULL, 0, 32, FALSE, FALSE },\n\t{ 18, MKDNOID( \"\\x55\\x04\\x18\" ),\t/* x121Address (2 5 4 24) */\n\t  \"oid.2.5.4.24\", 12, NULL, 0, 15, FALSE, FALSE },\n\t{ 19, MKDNOID( \"\\x55\\x04\\x19\" ),\t/* internationalISDNNumber (2 5 4 25) */\n\t  \"isdn\", 4, \"oid.2.5.4.25\", 12, 16, FALSE, FALSE },\n\t{ 20, MKDNOID( \"\\x55\\x04\\x1A\" ),\t/* registeredAddress (2 5 4 26) */\n\t  \"oid.2.5.4.26\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 21, MKDNOID( \"\\x55\\x04\\x1B\" ),\t/* destinationIndicator (2 5 4 27) */\n\t  \"oid.2.5.4.27\", 12, NULL, 0, 128, FALSE, FALSE },\n\t{ 22, MKDNOID( \"\\x55\\x04\\x1C\" ),\t/* preferredDeliveryMethod (2 5 4 28) */\n\t  \"oid.2.5.4.28\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 23, MKDNOID( \"\\x55\\x04\\x1D\" ),\t/* presentationAddress (2 5 4 29) */\n\t  \"oid.2.5.4.29\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 24, MKDNOID( \"\\x55\\x04\\x1E\" ),\t/* supportedApplicationContext (2 5 4 30) */\n\t  \"oid.2.5.4.30\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 25, MKDNOID( \"\\x55\\x04\\x1F\" ),\t/* member (2 5 4 31) */\n\t  \"oid.2.5.4.31\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 26, MKDNOID( \"\\x55\\x04\\x20\" ),\t/* owner (2 5 4 32) */\n\t  \"oid.2.5.4.32\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 27, MKDNOID( \"\\x55\\x04\\x21\" ),\t/* roleOccupant (2 5 4 33) */\n\t  \"oid.2.5.4.33\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 28, MKDNOID( \"\\x55\\x04\\x22\" ),\t/* seeAlso (2 5 4 34) */\n\t  \"oid.2.5.4.34\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t  /* 0x23-0x28 are certificates/CRLs and some weird encrypted directory components */\n\t{ 29, MKDNOID( \"\\x55\\x04\\x29\" ),\t/* name (2 5 4 41) */\n\t  \"oid.2.5.4.41\", 12, NULL, 0, MAX_ATTRIBUTE_SIZE /*32768*/, FALSE, FALSE },\n\t{ 30, MKDNOID( \"\\x55\\x04\\x2A\" ),\t/* givenName (2 5 4 42) */\n\t  \"g\", 1, \"oid.2.5.4.42\", 12, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 31, MKDNOID( \"\\x55\\x04\\x2B\" ),\t/* initials (2 5 4 43) */\n\t  \"i\", 1, \"oid.2.5.4.43\", 12, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 32, MKDNOID( \"\\x55\\x04\\x2C\" ),\t/* generationQualifier (2 5 4 44) */\n\t  \"oid.2.5.4.44\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 33, MKDNOID( \"\\x55\\x04\\x2D\" ),\t/* uniqueIdentifier (2 5 4 45) */\n\t  \"oid.2.5.4.45\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 34, MKDNOID( \"\\x55\\x04\\x2E\" ),\t/* dnQualifier (2 5 4 46) */\n\t  \"oid.2.5.4.46\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t  /* 0x2F-0x30 are directory components */\n\t{ 35, MKDNOID( \"\\x55\\x04\\x31\" ),\t/* distinguishedName (2 5 4 49) */\n\t  \"oid.2.5.4.49\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 36, MKDNOID( \"\\x55\\x04\\x32\" ),\t/* uniqueMember (2 5 4 50) */\n\t  \"oid.2.5.4.50\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 37, MKDNOID( \"\\x55\\x04\\x33\" ),\t/* houseIdentifier (2 5 4 51) */\n\t  \"oid.2.5.4.51\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t  /* 0x34-0x3A are more certificates and weird encrypted directory components */\n\t{ 38, MKDNOID( \"\\x55\\x04\\x41\" ),\t/* pseudonym (2 5 4 65) */\n\t  \"oid.2.5.4.65\", 12, NULL, 0, 128, FALSE, FALSE },\n\t{ 39, MKDNOID( \"\\x55\\x04\\x42\" ),\t/* communicationsService (2 5 4 66) */\n\t  \"oid.2.5.4.66\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t{ 40, MKDNOID( \"\\x55\\x04\\x43\" ),\t/* communicationsNetwork (2 5 4 67) */\n\t  \"oid.2.5.4.67\", 12, NULL, 0, CRYPT_MAX_TEXTSIZE, FALSE, FALSE },\n\t  /* 0x44-0x49 are more PKI-related attributes */\n\t{ 41, MKOID( \"\\x06\\x0A\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x64\\x01\\x01\" ),\t/* userid (0 9 2342 19200300 100 1 1) */\n\t  \"uid\", 3, NULL, 0, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },\n\t{ 42, MKOID( \"\\x06\\x0A\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x64\\x01\\x03\" ),\t/* rfc822Mailbox (0 9 2342 19200300 100 1 3) */\n\t  \"oid.0.9.2342.19200300.100.1.3\", 29, NULL, 0, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },\n\t{ 43, MKOID( \"\\x06\\x0A\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x64\\x01\\x19\" ),\t/* domainComponent (0 9 2342 19200300 100 1 25) */\n\t  \"dc\", 2, \"oid.0.9.2342.19200300.100.1.25\", 30, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },\n\t{ 44, MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x01\" ),\t\t/* emailAddress (1 2 840 113549 1 9 1) */\n\t  \"email\", 5, \"oid.1.2.840.113549.1.9.1\", 24, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },\n\t{ 45, MKOID( \"\\x06\\x07\\x02\\x82\\x06\\x01\\x0A\\x07\\x14\" ),\t\t\t\t/* nameDistinguisher (0 2 262 1 10 7 20) */\n\t  \"oid.0.2.262.1.10.7.20\", 21, NULL, 0, CRYPT_MAX_TEXTSIZE, TRUE, FALSE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, NULL }, { CRYPT_ATTRIBUTE_NONE, NULL }\n\t};\n\n/* Check that a country code is valid */\n\n#define xA\t( 1 << 0 )\n#define xB\t( 1 << 1 )\n#define xC\t( 1 << 2 )\n#define xD\t( 1 << 3 )\n#define xE\t( 1 << 4 )\n#define xF\t( 1 << 5 )\n#define xG\t( 1 << 6 )\n#define xH\t( 1 << 7 )\n#define xI\t( 1 << 8 )\n#define xJ\t( 1 << 9 )\n#define xK\t( 1 << 10 )\n#define xL\t( 1 << 11 )\n#define xM\t( 1 << 12 )\n#define xN\t( 1 << 13 )\n#define xO\t( 1 << 14 )\n#define xP\t( 1 << 15 )\n#define xQ\t( 1 << 16 )\n#define xR\t( 1 << 17 )\n#define xS\t( 1 << 18 )\n#define xT\t( 1 << 19 )\n#define xU\t( 1 << 20 )\n#define xV\t( 1 << 21 )\n#define xW\t( 1 << 22 )\n#define xX\t( 1 << 23 )\n#define xY\t( 1 << 24 )\n#define xZ\t( 1 << 25 )\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkCountryCode( IN_BUFFER_C( 2 ) const BYTE *countryCode )\n\t{\n\tstatic const long countryCodes[] = {\t/* ISO 3166 code table */\n\t/*\t A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z */\n  /*A*/\t\t\t xD|xE|xF|xG|\txI|\t\t xL|xM|xN|xO|\txQ|xR|xS|xT|xU|\t  xW|\t   xZ,\n  /*B*/\txA|xB|\t xD|xE|xF|xG|xH|xI|xJ|\t\txM|xN|xO|\t   xR|xS|xT|   xV|xW|\txY|xZ,\n  /*C*/\txA|\t  xC|xD|   xF|xG|xH|xI|\t  xK|xL|xM|xN|xO|\t   xR|\t\txU|xV|\t xX|xY|xZ,\n  /*D*/\t\t\t\txE|\t\t\t   xJ|xK|\txM|\t  xO|\t\t\t\t\t\t\t   xZ,\n  /*E*/\t\t  xC|\txE|\t  xG|xH|\t\t\t\t\t\t   xR|xS|xT,\n  /*F*/\t\t\t\t\t\t\txI|xJ|xK|\txM|\t  xO|\t   xR,\n  /*G*/\txA|xB|\t xD|xE|xF|\t xH|xI|\t\t xL|xM|xN|\t xP|xQ|xR|xS|xT|xU|\t  xW|\txY,\n  /*H*/\t\t\t\t\t\t\t\t  xK|\txM|xN|\t\t   xR|\t xT|xU,\n  /*I*/\t\t\t xD|xE|\t\t\t\t\t xL|   xN|xO|\txQ|xR|xS|xT,\n  /*J*/\t\t\t\t\t\t\t\t\t\txM|\t  xO|xP,\n  /*K*/\t\t\t\txE|\t  xG|xH|xI|\t\t\txM|xN|\t xP|   xR|\t\t\t  xW|\txY|xZ,\n  /*L*/\txA|xB|xC|\t\t\t\txI|\t  xK|\t\t\t\t   xR|xS|xT|xU|xV|\t\txY,\n  /*M*/\txA|\t  xC|xD|\t  xG|xH|\t  xK|xL|xM|xN|xO|xP|xQ|xR|xS|xT|xU|xV|xW|xX|xY|xZ,\n  /*N*/\txA|\t  xC|\txE|xF|xG|\txI|\t\t xL|\t  xO|xP|   xR|\t\txU|\t\t\t   xZ,\n  /*O*/\t\t\t\t\t\t\t\t\t\txM,\n  /*P*/\txA|\t\t\txE|xF|xG|xH|\t  xK|xL|xM|xN|\t\t   xR|xS|xT|\t  xW|\txY,\n  /*Q*/\txA,\n  /*R*/\t\t\t\txE|\t\t\t\t\t\t\t  xO|\t\t\t\txU|\t  xW,\n  /*S*/\txA|xB|xC|xD|xE|\t  xG|xH|xI|xJ|xK|xL|xM|xN|xO|\t   xR|\t xT|   xV|\t\txY|xZ,\n  /*T*/\t\t  xC|xD|   xF|xG|xH|   xJ|xK|xL|xM|xN|xO|\t   xR|\t xT|   xV|xW|\t   xZ,\n  /*U*/\txA|\t\t\t\t  xG|\t\t\t\txM|\t\t\t\t  xS|\t\t\t\txY|xZ,\n  /*V*/\txA|\t  xC|\txE|\t  xG|\txI|\t\t\t   xN|\t\t\t\t\txU,\n  /*W*/\t\t\t\t   xF|\t\t\t\t\t\t\t\t\t  xS,\n  /*X*/\t0,\n  /*Y*/\t\t\t\txE|\t\t\t\t\t\t\t\t\t\t\t xT|xU,\n  /*Z*/\txA|\t\t\t\t\t\t\t\t\txM|\t\t\t\t\t\t\t  xW,\n\t\t0, 0\t/* Catch overflows */\n\t\t};\n\tconst int cc0 = countryCode[ 0 ] - 'A';\n\tconst int cc1 = countryCode[ 1 ] - 'A';\n\n\tassert( isReadPtr( countryCode, 2 ) );\n\n\t/* Check that the country code is present in the table of valid ISO 3166\n\t   codes.  Note the explicit declaration of the one-bit as '1L', this is\n\t   required because the shift amount can be greater than the word size on\n\t   16-bit systems */\n\tif( cc0 < 0 || cc0 > 25 || cc1 < 0 || cc1 > 25 )\n\t\treturn( FALSE );\n\treturn( ( countryCodes[ cc0 ] & ( 1L << cc1 ) ) ? TRUE : FALSE );\n\t}\n\n/* Determine the sort priority for DN components */\n\nCHECK_RETVAL_RANGE( 0, 10 ) \\\nstatic int dnSortOrder( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tstatic const MAP_TABLE dnSortOrderTbl[] = {\n\t\t{ CRYPT_CERTINFO_COUNTRYNAME, 0 },\n\t\t{ CRYPT_CERTINFO_STATEORPROVINCENAME, 1 },\n\t\t{ CRYPT_CERTINFO_LOCALITYNAME, 2 },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, 3 },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, 4 },\n\t\t{ CRYPT_CERTINFO_COMMONNAME, 5 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tint status, value;\n\n\tREQUIRES( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t  type <= CRYPT_CERTINFO_LAST_DN );\n\n\tstatus = mapValue( type, &value, dnSortOrderTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( dnSortOrderTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( value );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check a DN component */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckDNComponent( IN const DN_COMPONENT *dnComponent )\n\t{\n\tassert( isReadPtr( dnComponent, sizeof( DN_COMPONENT ) ) );\n\n\tREQUIRES_B( dnComponent != NULL );\n\n\t/* Check general DN component data */\n\tif( dnComponent->type < 1 || \\\n\t\t( dnComponent->type > 50 && \\\n\t\t  dnComponent->type < CRYPT_CERTINFO_FIRST_DN ) || \\\n\t\tdnComponent->type > CRYPT_CERTINFO_LAST_DN || \\\n\t\tdnComponent->typeInfo == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDNComponent: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !CHECK_FLAGS( dnComponent->flags, DN_FLAG_NONE, DN_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDNComponent: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( dnComponent->prev ) || \\\n\t\t!DATAPTR_ISVALID( dnComponent->next ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDNComponent: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\t\n\t/* Check encoding information */\n\tif( dnComponent->value != dnComponent->storage || \\\n\t\t!isShortIntegerRange( dnComponent->valueLength ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDNComponent: Value\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( dnComponent->asn1EncodedStringType < 0 || \\\n\t\tdnComponent->asn1EncodedStringType > 0xFF || \\\n\t\t!isShortIntegerRange( dnComponent->encodedRDNdataSize ) || \\\n\t\t!isShortIntegerRange( dnComponent->encodedAVAdataSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDNComponent: Encoding info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Find a DN component in a DN component list by type and by OID.  This also\n   takes a count parameter to return the n'th occurrence of a DN component.\n   Note that we use counted-access rather than the usual getFirst()/getNext()\n   enumeration mechanism because some of the accesses are coming from outside\n   cryptlib and may be non-atomic.  In other words there's no guarantee that\n   the caller won't perform a delete between getNext()'s, leaving a dangling\n   reference to trip up the next getNext() call */\n\nCHECK_RETVAL_PTR \\\nstatic DN_COMPONENT *findDNComponent( const DATAPTR_DN dnComponentList,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\t\t\t  IN_RANGE( 0, 100 ) const int count,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER_OPT( valueLength ) const void *value,\n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int valueLength )\n\t{\n\tDN_COMPONENT *listPtr;\n\tint matchCount = 0, LOOP_ITERATOR;\n\n\tassert( ( value == NULL && valueLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( value, valueLength ) );\n\t\t\t/* We may be doing the lookup purely by type */\n\n\tREQUIRES_N( DATAPTR_ISVALID( dnComponentList ) );\n\tREQUIRES_N( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t\ttype <= CRYPT_CERTINFO_LAST_DN );\n\tREQUIRES_N( count >= 0 && count <= 100 );\n\tREQUIRES_N( ( value == NULL && valueLength == 0 ) || \\\n\t\t\t\t( value != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( valueLength ) ) );\n\tREQUIRES_N( ( value == NULL && count >= 0 ) || \\\n\t\t\t\t( value != NULL && count == 0 ) );\n\n\t/* Find the position of this component in the list */\n\tLOOP_MED( listPtr = DATAPTR_GET( dnComponentList ), listPtr != NULL,\n\t\t\t  listPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tREQUIRES_N( sanityCheckDNComponent( listPtr ) );\n\n\t\t/* If it's of a different type then it can't be a match */\n\t\tif( listPtr->type != type )\n\t\t\tcontinue;\n\t\t\n\t\t/* If we're doing the lookup purely by type then we've found a \n\t\t   match */\n\t\tif( value == NULL )\n\t\t\t{\n\t\t\t/* If we're looking for the n-th match rather than the first\n\t\t\t   matching item, continue if we haven't reached the n-th item \n\t\t\t   yet */\n\t\t\tif( matchCount < count )\n\t\t\t\t{\n\t\t\t\tmatchCount++;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\treturn( ( DN_COMPONENT * ) listPtr );\n\t\t\t}\n\n\t\t/* Check for a match by value */\n\t\tif( listPtr->valueLength == valueLength && \\\n\t\t\t!memcmp( listPtr->value, value, valueLength ) ) \n\t\t\treturn( ( DN_COMPONENT * ) listPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic DN_COMPONENT *findDNComponentByOID( const DATAPTR_DN dnComponentList,\n\t\t\t\t\t\t\t\t\t\t   IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_OID const int oidLength )\n\t{\n\tDN_COMPONENT *listPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\n\tREQUIRES_N( DATAPTR_ISVALID( dnComponentList ) );\n\tREQUIRES_N( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \\\n\t\t\t\toidLength == sizeofOID( oid ) );\n\n\t/* Find the position of this component in the list */\n\tLOOP_MED( listPtr = DATAPTR_GET( dnComponentList ), listPtr != NULL, \n\t\t\t  listPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tconst DN_COMPONENT_INFO *dnComponentInfo;\n\n\t\tREQUIRES_N( sanityCheckDNComponent( listPtr ) );\n\n\t\tdnComponentInfo = listPtr->typeInfo;\n\t\tif( oidLength == sizeofOID( dnComponentInfo->oid ) && \\\n\t\t\t!memcmp( dnComponentInfo->oid, oid, oidLength ) )\n\t\t\treturn( listPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/* Find DN information by type, by OID, and by string label */\n\nCHECK_RETVAL_PTR \\\nstatic const DN_COMPONENT_INFO *findDNInfo( IN_INT const int type )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( ( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t\t  type <= CRYPT_CERTINFO_LAST_DN ) || \\\n\t\t\t\t( type > 0 && type < 50 ) );\n\n\t/* Find the type information for this component */\n\tLOOP_LARGE( i = 0, \n\t\t\t\tcertInfoOIDs[ i ].oid != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( certInfoOIDs[ i ].type == type )\n\t\t\treturn( &certInfoOIDs[ i ] );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ) );\n\n\tretIntError_Null();\n\t}\t\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst DN_COMPONENT_INFO *findDNInfoByOID( IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\n\tREQUIRES_N( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \\\n\t\t\t\toidLength == sizeofOID( oid ) );\n\n\tLOOP_LARGE( i = 0,\n\t\t\t\tcertInfoOIDs[ i ].oid != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst DN_COMPONENT_INFO *certInfoOID = &certInfoOIDs[ i ];\n\n\t\t/* Perform a quick check of the OID.  The majority of all DN OIDs\n\t\t   are of the form (2 5 4 n), encoded as 0x06 0x03 0x55 0x04 0xnn,\n\t\t   so we compare the byte at offset 4 for a quick-reject match \n\t\t   before we go for the full OID match */\n\t\tif( oidLength == sizeofOID( certInfoOID->oid ) && \\\n\t\t\tcertInfoOID->oid[ 4 ] == oid[ 4 ] && \\\n\t\t\t!memcmp( certInfoOID->oid, oid, oidLength ) )\n\t\t\treturn( certInfoOID );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ) );\n\n\treturn( NULL );\n\t}\n\n#ifdef USE_CERT_DNSTRING\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst DN_COMPONENT_INFO *findDNInfoByLabel( IN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int labelLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( label, labelLength ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( labelLength ) );\n\n\tLOOP_LARGE( i = 0,\n\t\t\t\tcertInfoOIDs[ i ].oid != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst DN_COMPONENT_INFO *certInfoOID = &certInfoOIDs[ i ];\n\n\t\tif( certInfoOID->nameLen == labelLength && \\\n\t\t\t!strCompare( certInfoOID->name, label, labelLength ) )\n\t\t\treturn( certInfoOID );\n\t\tif( certInfoOID->altName != NULL && \\\n\t\t\tcertInfoOID->altNameLen == labelLength && \\\n\t\t\t!strCompare( certInfoOID->altName, label, labelLength ) )\n\t\t\treturn( certInfoOID );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( certInfoOIDs, DN_COMPONENT_INFO ) );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CERT_DNSTRING */\n\n/* Find the appropriate location in a DN to insert a new component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nstatic int findDNInsertPoint( const DN_COMPONENT *listHeadPtr,\n\t\t\t\t\t\t\t  IN_INT const int type,\n\t\t\t\t\t\t\t  const BOOLEAN fromExternalSource,\n\t\t\t\t\t\t\t  OUT_PTR_COND DN_COMPONENT **insertPointPtrPtr,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\t\n\t{\n\tconst DN_COMPONENT *listPtr, *prevElement = NULL;\n\tint newValueSortOrder, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( listHeadPtr, sizeof( DN_COMPONENT ) ) );\n\tassert( isWritePtr( insertPointPtrPtr, sizeof( DN_COMPONENT * ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( ( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t\ttype <= CRYPT_CERTINFO_LAST_DN ) || \\\n\t\t\t  ( type > 0 && type < 50 ) );\n\tREQUIRES( fromExternalSource == TRUE || fromExternalSource == FALSE );\n\n\t/* Clear return values */\n\t*insertPointPtrPtr = NULL;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If it's being read from encoded certificate data just append it to \n\t   the end of the list */\n\tif( fromExternalSource )\n\t\t{\n\t\tLOOP_MED( ( prevElement = NULL, listPtr = listHeadPtr ), \n\t\t\t\t  listPtr != NULL,\n\t\t\t\t  ( prevElement = listPtr,\n\t\t\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) ) )\n\t\t\t{\n\t\t\tREQUIRES( sanityCheckDNComponent( listPtr ) );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t*insertPointPtrPtr = ( DN_COMPONENT * ) prevElement;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the sort order for the new value and make sure that it's valid */\n\tstatus = newValueSortOrder = dnSortOrder( type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Find the location to insert it */\t\t\t\n\tLOOP_MED( ( prevElement = NULL, listPtr = listHeadPtr ), \n\t\t\t  listPtr != NULL && \\\n\t\t\t\tnewValueSortOrder >= dnSortOrder( listPtr->type ),\n\t\t\t  ( prevElement = listPtr,\n\t\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) ) )\n\t\t{\n\t\tREQUIRES( sanityCheckDNComponent( listPtr ) );\n\n\t\t/* Make sure that this component isn't already present.  We only \n\t\t   allow a single DN component of any type to keep things simple for \n\t\t   the user and to avoid potential problems with implementations\n\t\t   that don't handle more than one instance of a given DN component\n\t\t   too well */\n\t\tif( listPtr->type == type )\n\t\t\t{\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*insertPointPtrPtr = ( DN_COMPONENT * ) prevElement;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd DN Components\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Insert a DN component into a list.  The type can be either a \n   CRYPT_CERTINFO_xxx value, indicating that it's a standard DN component,\n   or a small integer denoting a recognised but nonstandard DN component.  \n   In the latter case we don't try to sort the component into the correct \n   position */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 7 ) ) \\\nint insertDNstring( INOUT DATAPTR_DN *dnListHeadPtr, \n\t\t\t\t\tIN_INT const int type,\n\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\tIN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\tIN_RANGE( 1, 20 ) const int valueStringType,\n\t\t\t\t\tIN_FLAGS_Z( DN ) const int flags, \n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst DN_COMPONENT_INFO *dnComponentInfo = NULL;\n\tDATAPTR_ATTRIBUTE listHead = *dnListHeadPtr;\n\tDN_COMPONENT *newElement, *listHeadPtr, *insertPoint;\n\tBYTE countryCode[ 8 + 8 ];\n\n\tassert( isWritePtr( dnListHeadPtr, sizeof( DATAPTR_DN ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\tREQUIRES( ( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t\ttype <= CRYPT_CERTINFO_LAST_DN ) || \\\n\t\t\t  ( type > 0 && type < 50 ) );\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\tREQUIRES( valueStringType >= 1 && valueStringType <= 20 );\n\tREQUIRES( isFlagRangeZ( flags, DN ) );\n\n\t/* Clear return value */\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If the DN is locked against modification we can't make any further\n\t   updates */\n\tlistHeadPtr = DATAPTR_GET( listHead );\n\tif( listHeadPtr != NULL && \\\n\t\tTEST_FLAG( listHeadPtr->flags, DN_FLAG_LOCKED ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* Find the type information for this component */\n\tdnComponentInfo = findDNInfo( type );\n\tENSURES( dnComponentInfo != NULL );\n\n\t/* Make sure that the length is valid.  If it's being read from an\n\t   encoded form we allow abnormally-long lengths (although we still keep\n\t   them within a sensible limit) since this is better than failing to\n\t   read a certificate because it contains a broken DN.  In addition if a \n\t   widechar string is OK we allow a range up to the maximum byte count\n\t   defined by the widechar size */\n#ifdef USE_WIDECHARS\n\tif( valueLength > ( ( flags & DN_FLAG_NOCHECK ) ? \\\n\t\t\t\t\t\t\tMAX_ATTRIBUTE_SIZE : \\\n\t\t\t\t\t\t( dnComponentInfo->wcsOK ) ? \\\n\t\t\t\t\t\t\t( WCSIZE * dnComponentInfo->maxLength ) : \\\n\t\t\t\t\t\t\tdnComponentInfo->maxLength ) )\n#else\n\tif( valueLength > ( ( flags & DN_FLAG_NOCHECK ) ? \\\n\t\t\t\t\t\t\tMAX_ATTRIBUTE_SIZE : dnComponentInfo->maxLength ) )\n#endif /* USE_WIDECHARS */\n\t\t{\n\t\t*errorType = CRYPT_ERRTYPE_ATTR_SIZE;\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Find the correct place in the list to insert the new element */\n\tif( listHeadPtr != NULL )\n\t\t{\n\t\tint status;\n\n\t\tstatus = findDNInsertPoint( listHeadPtr, type, \n\t\t\t\t\t\t\t\t\t( flags & DN_FLAG_NOCHECK ) ? \\\n\t\t\t\t\t\t\t\t\t\tTRUE : FALSE,\n\t\t\t\t\t\t\t\t\t&insertPoint, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an empty list, insert the new element at the start */\n\t\tinsertPoint = NULL;\n\t\t}\n\n\t/* If it's a country code, force it to uppercase as per ISO 3166 */\n\tif( type == CRYPT_CERTINFO_COUNTRYNAME )\n\t\t{\n\t\tconst BYTE *dnStrPtr = value;\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* An ISO 3166 country code must be exactly two characters long, \n\t\t   however some implementations stuff things like abbreviated \n\t\t   country names into the \"country code\" (e.g. \"US\" -> \"USA\") so if \n\t\t   the DN is coming from an external source then we allow longer \n\t\t   values */\n\t\tif( flags & DN_FLAG_NOCHECK )\n\t\t\t{\n\t\t\tif( valueLength < 2 || valueLength > 8 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( valueLength != 2 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\n\t\t/* Note: When this code is run under BoundsChecker 6.x the toUpper() \n\t\t   conversion will produce garbage on any call after the first one \n\t\t   resulting in the following checks failing */\n\t\tLOOP_SMALL( i = 0, i < valueLength, i++ )\n\t\t\tcountryCode[ i ] = intToByte( toUpper( dnStrPtr[ i ] ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( flags & DN_FLAG_NOCHECK )\n\t\t\t{\n\t\t\t/* 'UK' isn't an ISO 3166 country code but may be found in some\n\t\t\t   certificates.  If we find this we quietly convert it to the\n\t\t\t   correct value */\n\t\t\tif( !memcmp( countryCode, \"UK\", 2 ) )\n\t\t\t\tmemcpy( countryCode, \"GB\", 2 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Make sure that the country code is valid */\n\t\t\tif( !checkCountryCode( countryCode ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* We've fixed up the coutry code information if required, make sure \n\t\t   that we add the fixed form rather than the original */\n\t\tvalue = countryCode;\n\t\t}\n\n\t/* Allocate memory for the new element and copy over the information */\n\tREQUIRES( rangeCheck( valueLength, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( newElement = ( DN_COMPONENT * ) \\\n\t\t\t\tclAlloc( \"insertDNstring\", sizeof( DN_COMPONENT ) + \\\n\t\t\t\t\t\t\t\t\t\t   valueLength ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tinitVarStruct( newElement, DN_COMPONENT, valueLength, value );\n\tnewElement->type = type;\n\tnewElement->typeInfo = dnComponentInfo;\n\tmemcpy( newElement->value, value, valueLength );\n\tnewElement->valueLength = valueLength;\n\tnewElement->valueStringType = valueStringType;\n\tINIT_FLAGS( newElement->flags, flags );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\n\tENSURES( sanityCheckDNComponent( newElement ) );\n\n\t/* Link it into the list */\n\tinsertDoubleListElement( dnListHeadPtr, insertPoint, newElement, \n\t\t\t\t\t\t\t DN_COMPONENT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint insertDNComponent( INOUT DATAPTR_DN *dnListHeadPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE componentType,\n\t\t\t\t\t   IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t   IN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint valueStringType, dummy1, dummy2, status;\n\n\tassert( isWritePtr( dnListHeadPtr, sizeof( DATAPTR_DN ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( componentType >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t  componentType <= CRYPT_CERTINFO_LAST_DN );\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\n\t/* The value is coming from an external source, make sure that it's\n\t   representable as a certificate string type.  All that we care\n\t   about here is the validity so we ignore the returned encoding\n\t   information */\n\tstatus = getAsn1StringInfo( value, valueLength, &valueStringType, \n\t\t\t\t\t\t\t\t&dummy1, &dummy2, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\treturn( insertDNstring( dnListHeadPtr, componentType, value, \n\t\t\t\t\t\t\tvalueLength, valueStringType, 0, errorType ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete DN Components\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete a DN component from a list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int deleteComponent( INOUT DATAPTR_DN *dnPtr, \n\t\t\t\t\t\t\tINOUT DN_COMPONENT *theElement )\n\t{\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\tassert( isWritePtr( theElement, sizeof( DN_COMPONENT ) ) );\n\n\tREQUIRES( sanityCheckDNComponent( theElement ) );\n\n\t/* Remove the item from the list */\n\tdeleteDoubleListElement( dnPtr, theElement, DN_COMPONENT );\n\n\t/* Clear all data in the list item and free the memory */\n\tendVarStruct( theElement, DN_COMPONENT );\n\tclFree( \"deleteComponent\", theElement );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteDNComponent( INOUT DATAPTR_DN *dnPtr, \n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t   IN_BUFFER_OPT( valueLength ) const void *value, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int valueLength )\n\t{\n\tDATAPTR_DN dn = *dnPtr;\n\tDN_COMPONENT *listHeadPtr, *itemToDelete;\n\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\tassert( ( value == NULL && valueLength == 0 ) ||\n\t\t\tisReadPtrDynamic( value, valueLength ) );\n\t\t\t/* We may be doing the delete purely by type */\n\n\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\tREQUIRES( type > CRYPT_CERTINFO_FIRST && type < CRYPT_CERTINFO_LAST );\n\tREQUIRES( ( value == NULL && valueLength == 0 ) || \\\n\t\t\t  ( value != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( valueLength ) ) );\n\n\t/* Trying to delete from an empty DN always fails */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tlistHeadPtr = DATAPTR_GET( dn );\n\tREQUIRES( listHeadPtr != NULL );\n\n\t/* If the DN is locked against modification then we can't make any \n\t   further updates */\n\tif( TEST_FLAG( listHeadPtr->flags, DN_FLAG_LOCKED ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Find the component in the list and delete it */\n\titemToDelete = findDNComponent( dn, type, 0, value, valueLength );\n\tif( itemToDelete == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\treturn( deleteComponent( dnPtr, itemToDelete ) );\n\t}\n\n/* Delete a DN */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteDN( INOUT_PTR DATAPTR_DN *dnPtr )\n\t{\n\tDATAPTR_DN dn = *dnPtr;\n\tDN_COMPONENT *dnComponentListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN *) ) );\n\n\tREQUIRES_V( DATAPTR_ISSET( dn ) );\n\n\t/* Destroy all DN items */\n\tdnComponentListPtr = DATAPTR_GET( dn );\n\tENSURES_V( dnComponentListPtr != NULL );\n\tENSURES_V( sanityCheckDNComponent( dnComponentListPtr ) );\n\tLOOP_MED_CHECK( dnComponentListPtr != NULL )\n\t\t{\n\t\tDATAPTR_DN itemToFree;\n\t\tDN_COMPONENT *itemToFreePtr;\n\t\tint status;\n\n\t\tDATAPTR_SET( itemToFree, dnComponentListPtr );\n\t\titemToFreePtr = dnComponentListPtr;\n\t\tREQUIRES_V( sanityCheckDNComponent( itemToFreePtr ) );\n\t\tREQUIRES_V( DATAPTR_ISVALID( dnComponentListPtr->next ) );\n\t\tdnComponentListPtr = DATAPTR_GET( dnComponentListPtr->next );\n\n\t\t/* Another gcc bug, this time in gcc 4.x for 64-bit architectures \n\t\t   (confirmed for x86-64 and ppc64) in which it removes an empty-\n\t\t   list check in deleteDoubleListElement() (in fact the emitted \n\t\t   code bears only a passing resemblance to the actual source code, \n\t\t   this appears to be a variant of the broken handling of the\n\t\t   nonnull attribute described in misc/analyse.h). The only possible \n\t\t   workaround seems to be to omit the call to deleteComponent() and \n\t\t   just delete the item directly */\n#if defined( __GNUC__ ) && ( __GNUC__ == 4 ) && 0\n\t\t\t/* The addition of the REQUIRES() preconditions to \n\t\t\t   deleteDoubleListElement() seem to have fixed the gcc problem,\n\t\t\t   either that or it was only present in some early 4.0.x versions */\n\t\tdeleteDoubleListElementSafe( dnComponentListPtrPtr, itemToFree, \n\t\t\t\t\t\t\t\t\t DN_COMPONENT );\n\t\tendVarStruct( itemToFree, DN_COMPONENT );\n\t\tclFree( \"deleteComponent\", itemToFree );\n#else\n\t\tstatus = deleteComponent( &itemToFree, itemToFreePtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn;\n#endif /* gcc 4.x on 64-bit architectures bug workaround */\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\t/* Mark the list as being empty */\n\tDATAPTR_SET_PTR( dnPtr, NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMiscellaneous DN Component Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get DN component information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getDNComponentInfo( IN const DATAPTR_DN dn,\n\t\t\t\t\t\tOUT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *type,\n\t\t\t\t\t\tOUT_BOOL BOOLEAN *dnContinues )\n\t{\n\tconst DN_COMPONENT *dnComponent;\n\n\tassert( isWritePtr( type, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( dnContinues, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( dn ) );\n\n\t/* Clear return values */\n\t*type = CRYPT_ATTRIBUTE_NONE;\n\t*dnContinues = FALSE;\n\n\tdnComponent = DATAPTR_GET( dn );\n\tREQUIRES( dnComponent != NULL );\n\tREQUIRES( sanityCheckDNComponent( dnComponent ) );\n\n\t/* Return the component information to the caller.  The dnContinues \n\t   value is a somewhat oddball piece of information that's used in \n\t   conjunction with compareDN() when checking subsets of DNs, for \n\t   example to see if a DN subset contains more than one element */\n\tif( dnComponent->type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\tdnComponent->type <= CRYPT_CERTINFO_LAST_DN )\n\t\t*type = dnComponent->type;\n\tREQUIRES( DATAPTR_ISVALID( dnComponent->next ) );\n\tif( DATAPTR_ISSET( dnComponent->next ) )\n\t\t*dnContinues = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the value of a DN component.  This also takes a count parameter to \n   return the n'th occurrence of a DN component, see the comment for\n   findDNComponent() for details */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 6 ) ) \\\nint getDNComponentValue( IN_DATAPTR_OPT const DATAPTR_DN dn,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t IN_RANGE( 0, 100 ) const int count,\n\t\t\t\t\t\t OUT_BUFFER_OPT( valueMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *valueLength ) void *value, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int valueMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( valueMaxLength ) \\\n\t\t\t\t\t\t\tint *valueLength )\n\t{\n\tconst DN_COMPONENT *dnComponent;\n\n\tassert( ( value == NULL && valueMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( value, valueMaxLength ) ) );\n\tassert( isWritePtr( valueLength, sizeof( int ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\tREQUIRES( type >= CRYPT_CERTINFO_FIRST_DN && \\\n\t\t\t  type <= CRYPT_CERTINFO_LAST_DN );\n\tREQUIRES( count >= 0 && count <= 100 );\n\tREQUIRES( ( value == NULL && valueMaxLength == 0 ) || \\\n\t\t\t  ( value != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( valueMaxLength ) ) );\n\n\t/* Clear return values */\n\t*valueLength = 0;\n\tif( value != NULL )\n\t\tmemset( value, 0, min( 16, valueMaxLength ) );\n\n\t/* Trying to get data from an empty DN always fails */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tdnComponent = findDNComponent( dn, type, count, NULL, 0 );\n\tif( dnComponent == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\treturn( attributeCopyParams( value, valueMaxLength, valueLength,\n\t\t\t\t\t\t\t\t dnComponent->value, \n\t\t\t\t\t\t\t\t dnComponent->valueLength ) );\n\t}\n\n/* Compare two DNs.  Since this is used for constraint comparisons as well\n   as just strict equality checks we provide a flag that, if set, returns\n   a match if the first DN is a proper substring of the second DN.  We\n   optionally return a pointer to the first mis-matching element in the \n   first DN in case the caller wants to perform further actions with it */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN compareDN( IN_DATAPTR_OPT const DATAPTR_DN dn1,\n\t\t\t\t   IN_DATAPTR_OPT const DATAPTR_DN dn2,\n\t\t\t\t   const BOOLEAN dn1substring,\n\t\t\t\t   OUT_DATAPTR_xCOND DATAPTR_DN *mismatchPointPtr )\n\t{\n\tDN_COMPONENT *dn1ptr, *dn2ptr;\n\tint LOOP_ITERATOR;\n\n\tassert( mismatchPointPtr == NULL || \\\n\t\t\tisWritePtr( mismatchPointPtr, sizeof( DATAPTR_DN * ) ) );\n\n\tREQUIRES_B( DATAPTR_ISVALID( dn1 ) && DATAPTR_ISVALID( dn2 ) );\n\tREQUIRES_B( dn1substring == TRUE || dn1substring == FALSE );\n\tREQUIRES_B( !( dn1substring == FALSE && mismatchPointPtr != NULL ) );\n\n\t/* Clear return value */\n\tif( mismatchPointPtr != NULL )\n\t\tDATAPTR_SET_PTR( mismatchPointPtr, NULL );\n\n\t/* Check each DN component for equality */\n\tLOOP_MED( ( dn1ptr = DATAPTR_GET( dn1 ), \\\n\t\t\t\tdn2ptr = DATAPTR_GET( dn2 ) ),\n\t\t\t  dn1ptr != NULL && dn2ptr != NULL,\n\t\t\t  ( dn1ptr = DATAPTR_GET( dn1ptr->next ), \\\n\t\t\t\tdn2ptr = DATAPTR_GET( dn2ptr->next ) ) )\n\t\t{\n\t\tREQUIRES_B( sanityCheckDNComponent( dn1ptr ) );\n\t\tREQUIRES_B( sanityCheckDNComponent( dn2ptr ) );\n\n\t\t/* If the RDN types differ then the DNs don't match */\n\t\tif( dn1ptr->type != dn2ptr->type )\n\t\t\t{\n\t\t\tif( mismatchPointPtr != NULL )\n\t\t\t\tDATAPTR_SET_PTR( mismatchPointPtr, dn1ptr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Compare the current RDNs.  In theory we should be using the\n\t\t   complex and arcane X.500 name comparison rules but no-one in \n\t\t   their right mind actually does this since they're almost \n\t\t   impossible to get right.  Since everyone else uses memcpy()/\n\t\t   memcmp() to handle DN components it's safe to use it here (sic \n\t\t   faciunt omnes).  This also avoids any security problems arising \n\t\t   from the complexity of the code necessary to implement the X.500 \n\t\t   matching rules */\n\t\tif( dn1ptr->valueLength != dn2ptr->valueLength || \\\n\t\t\tmemcmp( dn1ptr->value, dn2ptr->value, dn1ptr->valueLength ) ||\n\t\t\tGET_FLAG( dn1ptr->flags, DN_FLAGS_COMPARE_MASK ) != \\\n\t\t\t\tGET_FLAG( dn2ptr->flags, DN_FLAGS_COMPARE_MASK ) )\n\t\t\t{\n\t\t\tif( mismatchPointPtr != NULL )\n\t\t\t\tDATAPTR_SET_PTR( mismatchPointPtr, dn1ptr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* If we've reached the end of both DNs or we're looking for a substring\n\t   match (which means that the match ended when it reached the end of \n\t   the first DN, making it a proper substring of the second) then the \n\t   two match */\n\tif( dn1ptr == NULL && dn2ptr == NULL )\n\t\treturn( TRUE );\n\tif( dn1substring && dn1ptr == NULL )\n\t\treturn( TRUE );\n\n\t/* We've reached the end of the DN without finding a match */\n\tif( mismatchPointPtr != NULL )\n\t\tDATAPTR_SET_PTR( mismatchPointPtr, dn1ptr );\n\treturn( FALSE );\n\t}\n\n/* Copy a DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyDN( OUT_DATAPTR DATAPTR_DN *dnDestPtr, \n\t\t\tIN const DATAPTR_DN dnSrc )\n\t{\n\tDN_COMPONENT *srcCursor, *destCursor = NULL;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( dnDestPtr, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( dnSrc ) );\n\n\t/* Clear return value */\n\tDATAPTR_SET_PTR( dnDestPtr, NULL );\n\n\t/* Copy each element in the source DN */\n\tLOOP_MED( srcCursor = DATAPTR_GET( dnSrc ), \n\t\t\t  srcCursor != NULL, \n\t\t\t  srcCursor = DATAPTR_GET( srcCursor->next ) )\n\t\t{\n\t\tDN_COMPONENT *newElement;\n\n\t\tREQUIRES( sanityCheckDNComponent( srcCursor ) );\n\n\t\t/* Allocate memory for the new element and copy over the \n\t\t   information.  Since we're copying over the contents of an \n\t\t   existing DN_COMPONENT structure we have to zero the list links \n\t\t   after the copy */\n\t\tif( ( newElement = ( DN_COMPONENT * ) \\\n\t\t\t\tclAlloc( \"copyDN\", \\\n\t\t\t\t\t\t sizeofVarStruct( srcCursor, DN_COMPONENT ) ) ) == NULL )\n\t\t\t{\n\t\t\tdeleteDN( dnDestPtr );\n\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tcopyVarStruct( newElement, srcCursor, DN_COMPONENT, value );\n\t\tDATAPTR_SET( newElement->prev, NULL );\n\t\tDATAPTR_SET( newElement->next, NULL );\n\n\t\tENSURES( sanityCheckDNComponent( newElement ) );\n\n\t\t/* Link it into the list */\n\t\tinsertDoubleListElement( dnDestPtr, destCursor, newElement, \n\t\t\t\t\t\t\t\t DN_COMPONENT );\n\t\tdestCursor = newElement;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the validity and well-formedness of a DN.  The check for the bottom \n   of the DN (common name) and top (country) are made configurable, DNs that \n   act as filters (e.g. path constraints) may not have the lower DN parts \n   present and certificate requests submitted to CAs that set the country \n   themselves may not have the country present.\n\n   We also check that there's only one country present (the use of DN \n   strings allows more than one to be set).  In addition if an explicit \n   check for well-formedness is being done then we check for no more than \n   one CN and no more than one AVA per RDN because the behaviour of \n   different implementations when they encounter these is more or less \n   random */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nint checkDN( IN const DATAPTR_DN dn,\n\t\t\t IN_FLAGS( CHECKDN ) const int checkFlags,\n\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDN_COMPONENT *dnComponentListPtr;\n\tBOOLEAN seenCountry = FALSE, seenCommonName = FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\tREQUIRES( isFlagRange( checkFlags, CHECKDN ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Perform a special-case check for a null DN */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Make sure that certain critical components are present */\n\tLOOP_MED( dnComponentListPtr = DATAPTR_GET( dn ), \n\t\t\t  dnComponentListPtr != NULL,\n\t\t\t  dnComponentListPtr = DATAPTR_GET( dnComponentListPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckDNComponent( dnComponentListPtr ) );\n\n\t\tif( dnComponentListPtr->type == CRYPT_CERTINFO_COUNTRYNAME )\n\t\t\t{\n\t\t\tif( !checkCountryCode( dnComponentListPtr->value ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\t*errorLocus = CRYPT_CERTINFO_COUNTRYNAME;\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\tif( seenCountry )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\t*errorLocus = CRYPT_CERTINFO_COUNTRYNAME;\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\t}\n\t\t\tseenCountry = TRUE;\n\t\t\t}\n\t\tif( dnComponentListPtr->type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\t{\n\t\t\tif( ( checkFlags & CHECKDN_FLAG_WELLFORMED ) && seenCommonName )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\t*errorLocus = CRYPT_CERTINFO_COMMONNAME;\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\t}\n\t\t\tseenCommonName = TRUE;\n\t\t\t}\n\n\t\t/* Multi-AVA RDNs are handled more or less arbitrarily by \n\t\t   implementations, we don't allow them if the DN is supposed to\n\t\t   be well-formed */\n\t\tif( ( checkFlags & CHECKDN_FLAG_WELLFORMED ) && \\\n\t\t\tTEST_FLAG( dnComponentListPtr->flags, DN_FLAG_CONTINUED ) )\n\t\t\t{\n\t\t\tif( dnComponentListPtr->type >= CRYPT_CERTINFO_FIRST && \\\n\t\t\t\tdnComponentListPtr->type <= CRYPT_CERTINFO_LAST )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\t*errorLocus = dnComponentListPtr->type;\n\t\t\t\t}\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( ( ( checkFlags & CHECKDN_FLAG_COUNTRY ) && !seenCountry ) || \\\n\t\t( ( checkFlags & CHECKDN_FLAG_COMMONNAME ) && !seenCommonName ) )\n\t\t{\n\t\t*errorType = CRYPT_ERRTYPE_ATTR_ABSENT;\n\t\t*errorLocus = ( seenCountry ) ? CRYPT_CERTINFO_COMMONNAME : \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_COUNTRYNAME;\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Convert a DN component containing a PKCS #9 emailAddress or an RFC 1274\n   rfc822Mailbox into an rfc822Name */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint convertEmail( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t  INOUT DATAPTR_DN *dnPtr,\n\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE altNameType )\n\t{\n\tDATAPTR_DN dn = *dnPtr;\n\tDATAPTR certData, subjectDNData, issuerDNData, publicKeyData;\n\tDN_COMPONENT *emailComponent;\n\tSELECTION_STATE selectionState;\n\tint certDataSize, publicKeyDataSize, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( altNameType == CRYPT_CERTINFO_SUBJECTALTNAME || \\\n\t\t\t  altNameType == CRYPT_CERTINFO_ISSUERALTNAME );\n\n\t/* If there's no PKCS #9 email address present, try for an RFC 1274 one.\n\t   If that's not present either, exit */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\t{\n\t\t/* If there's an empty subject/issuer DN present, there's nothing to \n\t\t   do */\n\t\treturn( CRYPT_OK );\n\t\t}\n\temailComponent = findDNComponentByOID( dn,\n\t\t\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x01\" ), 11 );\n\tif( emailComponent == NULL )\n\t\t{\n\t\temailComponent = findDNComponentByOID( dn,\n\t\t\tMKOID( \"\\x06\\x09\\x09\\x92\\x26\\x89\\x93\\xF2\\x2C\\x01\\x03\" ), 11 );\n\t\t}\n\tif( emailComponent == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Try and add the email address component as an rfc822Name.  Since this\n\t   changes the current GeneralName selection we have to be careful about\n\t   saving and restoring the state.  In addition since we're changing the\n\t   internal state of an object which is technically in the high state we \n\t   have to temporarily disconnect all of the certificate data from the \n\t   certificate object to make it appear as a mutable object.  This is an \n\t   unfortunate consequence of the fact that what we're doing is a \n\t   behind-the-scenes switch to move an initialised certificate component \n\t   from where it is to where it really should be */\n\tsaveSelectionState( selectionState, certInfoPtr );\n\tDATAPTR_SET( certData, certInfoPtr->certificate );\n\tcertDataSize = certInfoPtr->certificateSize;\n\tDATAPTR_SET( subjectDNData, certInfoPtr->subjectDNptr );\n\tDATAPTR_SET( issuerDNData, certInfoPtr->issuerDNptr );\n\tDATAPTR_SET( publicKeyData, certInfoPtr->publicKeyInfo );\n\tpublicKeyDataSize = certInfoPtr->publicKeyInfoSize;\n\tcertInfoPtr->certificate = NULL;\n\tcertInfoPtr->certificateSize = 0;\n\tcertInfoPtr->subjectDNptr = certInfoPtr->issuerDNptr = NULL;\n\tcertInfoPtr->publicKeyInfo = NULL;\n\tcertInfoPtr->publicKeyInfoSize = 0;\n\tENSURES( sanityCheckCert( certInfoPtr ) );\n\tstatus = addCertComponent( certInfoPtr, CRYPT_ATTRIBUTE_CURRENT, \n\t\t\t\t\t\t\t   altNameType );\n\tassert( cryptStatusOK( status ) );\t/* Should never fail, warn in debug mode */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = addCertComponentString( certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_RFC822NAME,\n\t\t\t\t\t\t\t\t\t\t emailComponent->value,\n\t\t\t\t\t\t\t\t\t\t emailComponent->valueLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* It was successfully copied over, delete the copy in the DN */\n\t\t( void ) deleteComponent( dnPtr, emailComponent );\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's already present (which is somewhat odd since the presence\n\t\t   of an email address in the DN implies that the implementation\n\t\t   doesn't know about rfc822Name), we can't do anything about it */\n\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\tstatus = CRYPT_OK;\n\t\telse\n\t\t\t{\n\t\t\t/* Some certificates can contain garbage in the (supposed) email \n\t\t\t   address, normally the certificate would be rejected because \n\t\t\t   of this but if we're running in oblivious mode then we can \n\t\t\t   import it successfully but get an internal error code when we \n\t\t\t   try and perform this sideways add.  To catch this we check \n\t\t\t   for invalid email addresses here and ignore an error status \n\t\t\t   if we get one */\n\t\t\tif( cryptArgError( status ) )\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\tcertInfoPtr->certificate = DATAPTR_GET( certData );\n\tcertInfoPtr->certificateSize = certDataSize;\n\tcertInfoPtr->subjectDNptr = DATAPTR_GET( subjectDNData );\n\tcertInfoPtr->issuerDNptr = DATAPTR_GET( issuerDNData );\n\tcertInfoPtr->publicKeyInfo = DATAPTR_GET( publicKeyData );\n\tcertInfoPtr->publicKeyInfoSize = publicKeyDataSize;\n\tENSURES( sanityCheckCert( certInfoPtr ) );\n\trestoreSelectionState( selectionState, certInfoPtr );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/dn.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Certificate DN Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _DN_DEFINED\n\n#define _DN_DEFINED\n\n/* DN component information flags.  These are:\n\n\tFLAG_CONTINUED: Some implementations may place more than one AVA into \n\t\tan RDN, this flag indicates that the RDN continues in the next DN \n\t\tcomponent structure.  \n\n\tFLAG_LOCKED: If the RDN/DN was set by specifying the entire DN at once \n\t\tusing a free-format text DN string it's not a good idea to allow \n\t\trandom changes to it so this flag marks the components as locked.\n\n\tFLAG_NOCHECK: If we're reading data from an external source the DN can \n\t\tcontain all sorts of strange stuff so we use this flag to tell the \n\t\tDN component-handling code not to perform any validity checking on \n\t\tthe components as they're added */\n\n#define DN_FLAG_NONE\t\t0x00\t/* No DN flag */\n#define DN_FLAG_CONTINUED\t0x01\t/* RDN continues with another AVA */\n#define DN_FLAG_LOCKED\t\t0x02\t/* RDN can't be modified */\n#define DN_FLAG_NOCHECK\t\t0x08\t/* Don't check validity of components */\n#define DN_FLAG_MAX\t\t\t0x0F\t/* Maximum possible flag value */\n\n/* When comparing DN fields we only want to compare relevant data and not \n   incidental flags related to parsing or encoding actions.  The following\n   mask defines the attribute flags that we want to compare */\n\n#define DN_FLAGS_COMPARE_MASK\t( DN_FLAG_CONTINUED )\n\n/* The structure to hold a DN component */\n\ntypedef struct DC {\n\t/* DN component type and type information */\n\tint type;\t\t\t\t\t\t/* cryptlib component type, either a\n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_TYPE or an integer ID */\n\tconst void *typeInfo;\t\t\t/* Type information for this component, a\n\t\t\t\t\t\t\t\t\t   pointer to the DN_COMPONENT_INFO tbl */\n\tSAFE_FLAGS flags;\n\n\t/* DN component data */\n\tBUFFER_FIXED( valueLength ) \\\n\tvoid *value;\t\t\t\t\t/* DN component value, in varStruct */\n\tint valueLength;\t\t\t\t/* DN component value length */\n\tint valueStringType;\t\t\t/* DN component native string type, \n\t\t\t\t\t\t\t\t\t   encoded as a cookie used by dnstring.c */\n\n\t/* Encoding information: The ASN.1 encoded string type as a \n\t   BER_STRING_xyz, the overall size of the RDN data (without the tag and \n\t   length) if this is the first or only component of an RDN, and the size \n\t   of the AVA containing this component.  If it's the first component of\n\t   a multi-AVA RDN then the DN_FLAG_CONTINUED flag will be set in the \n\t   flags field */\n\tint asn1EncodedStringType, encodedRDNdataSize, encodedAVAdataSize;\n\n\t/* The next and previous list element in the linked list of DN\n\t   components */\n\tDATAPTR_DN prev, next;\n\n\t/* Variable-length storage for the DN data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} DN_COMPONENT;\n\n/* Type information for DN components */\n\ntypedef struct {\n\tconst int type;\t\t\t\t\t/* cryptlib attribute type, or index \n\t\t\t\t\t\t\t\t\t   value for non-cryptlib attributes */\n\tconst BYTE *oid;\t\t\t\t/* OID for this type */\n\tARRAY_FIXED( nameLen ) \\\n\tconst char *name;\t\t\t\t/* Name for this type */\n\tconst int nameLen;\n\tARRAY_FIXED( nameLen ) \\\n\tconst char *altName;\t\t\t/* Alt. name for this type */\n\tconst int altNameLen;\n\tconst int maxLength;\t\t\t/* Maximum allowed length for this type */\n\tconst BOOLEAN ia5OK;\t\t\t/* Whether IA5 is allowed for this comp.*/\n\tconst BOOLEAN wcsOK;\t\t\t/* Whether widechar is allowed for comp.*/\n\t} DN_COMPONENT_INFO;\n\n/* Prototypes for functions in dn.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckDNComponent( IN const DN_COMPONENT *dnComponent );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst DN_COMPONENT_INFO *findDNInfoByOID( IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength );\n#ifdef USE_CERT_DNSTRING\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst DN_COMPONENT_INFO *findDNInfoByLabel( IN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int labelLength );\n#endif /* USE_CERT_DNSTRING */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 7 ) ) \\\nint insertDNstring( INOUT DATAPTR_DN *dnComponentPtr, \n\t\t\t\t\tIN_INT const int type,\n\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\tIN_LENGTH_SHORT const int valueLength,\n\t\t\t\t\tIN_RANGE( 1, 20 ) const int valueStringType,\n\t\t\t\t\tIN_FLAGS_Z( DN ) const int flags, \n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType );\n\n/* Prototypes for functions in dnstring.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint copyToAsn1String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t  IN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen, \n\t\t\t\t\t  IN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t  IN_LENGTH_SHORT const int sourceLen,\n\t\t\t\t\t  IN_RANGE( 0, 20 ) const int stringType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nint copyFromAsn1String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen, \n\t\t\t\t\t\tOUT_RANGE( 0, 20 ) int *destStringType,\n\t\t\t\t\t\tIN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int sourceLen,\n\t\t\t\t\t\tIN_TAG_ENCODED const int stringTag );\n\n#endif /* _DN_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/dn_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate DN Read/Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"dn.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/dn.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tRead a DN\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Parse an AVA.  This determines the AVA type and leaves the stream pointer\n   at the start of the data value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readAVABitstring( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *length, \n\t\t\t\t\t\t\t OUT_TAG_ENCODED_Z int *stringTag )\n\t{\n\tlong streamPos;\n\tint bitStringLength, innerTag, innerLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( isWritePtr( stringTag, sizeof( int ) ) );\n\n\t/* Bitstrings are used for uniqueIdentifiers, however these usually \n\t   encapsulate something else:\n\n\t\tBIT STRING {\n\t\t\tIA5String 'xxxxx'\n\t\t\t}\n\n\t   so we try and dig one level deeper to find the encapsulated string if \n\t   there is one.  This gets a bit complicated because we have to \n\t   speculatively try and decode the inner content and if that fails \n\t   assume that it's raw bitstring data.  First we read the bitstring \n\t   wrapper and remember where the bitstring data starts */\n\tstatus = readBitStringHole( stream, &bitStringLength, 2, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamPos = stell( stream );\n\n\t/* Then we try and read any inner content */\n\tstatus = innerTag = peekTag( stream );\n\tif( !cryptStatusError( status ) )\n\t\tstatus = readGenericHole( stream, &innerLength, 1, innerTag );\n\tif( !cryptStatusError( status ) && \\\n\t\tbitStringLength == sizeofObject( innerLength ) )\n\t\t{\n\t\t/* There was inner content present, treat it as the actual type and \n\t\t   value of the bitstring.  This assumes that the inner content is\n\t\t   a string data type, which always seems to be the case (in any \n\t\t   event it's not certain what we should be returning to the user if\n\t\t   we find, for example, a SEQUENCE with further encapsulated \n\t\t   content at this point) */\n\t\t*stringTag = innerTag;\n\t\t*length = innerLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We couldn't identify any (obvious) inner content, it must be raw\n\t   bitstring data.  Unfortunately we have no idea what format this is\n\t   in, it could in fact really be raw binary data but never actually \n\t   seems to be this, it's usually ASCII text so we mark it as such and \n\t   let the string-read routines sort it out */\n\tsClearError( stream );\n\tsseek( stream, streamPos );\n\t*stringTag = BER_STRING_IA5;\n\t*length = bitStringLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int readAVA( INOUT STREAM *stream, \n\t\t\t\t\tOUT_INT_Z int *type, \n\t\t\t\t\tOUT_LENGTH_SHORT_Z int *length, \n\t\t\t\t\tOUT_TAG_ENCODED_Z int *stringTag )\n\t{\n\tconst DN_COMPONENT_INFO *dnComponentInfo;\n\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\tint oidLength, tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( type, sizeof( int ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( isWritePtr( stringTag, sizeof( int ) ) );\n\n\t/* Clear return values */\n\t*type = 0;\n\t*length = 0;\n\t*stringTag = 0;\n\n\t/* Read the start of the AVA and determine the type from the \n\t   AttributeType field.  If we find something that we don't recognise we \n\t   indicate it as a non-component type that can be read or written but \n\t   not directly accessed by the user (although it can still be accessed \n\t   using the cursor functions) */\n\treadSequence( stream, NULL );\n\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdnComponentInfo = findDNInfoByOID( oid, oidLength );\n\tif( dnComponentInfo == NULL )\n\t\t{\n\t\t/* If we don't recognise the component type at all, skip it */\n\t\tstatus = readUniversal( stream );\n\t\treturn( cryptStatusError( status ) ? status : OK_SPECIAL );\n\t\t}\n\t*type = dnComponentInfo->type;\n\n\t/* We've reached the data value, make sure that it's in order.  When we\n\t   read the wrapper around the string type with readGenericHole() we have \n\t   to allow a minimum length of zero instead of one because of broken \n\t   AVAs with zero-length strings */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == BER_BITSTRING )\n\t\treturn( readAVABitstring( stream, length, stringTag ) );\n\t*stringTag = tag;\n\treturn( readGenericHoleZ( stream, length, 0, tag ) );\n\t}\n\n/* Read an RDN/DN component */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRDNcomponent( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT DATAPTR_DN *dnPtr,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int rdnDataLeft )\n\t{\t\n\tCRYPT_ERRTYPE_TYPE dummy;\n\tBYTE stringBuffer[ MAX_ATTRIBUTE_SIZE + 8 ];\n\tvoid *value;\n\tconst int rdnStart = stell( stream );\n\tint type, valueLength, valueStringType, stringTag;\n\tint flags = DN_FLAG_NOCHECK, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( rdnDataLeft ) );\n\tREQUIRES( isShortIntegerRangeNZ( rdnStart ) );\n\n\t/* Read the type information for this AVA */\n\tstatus = readAVA( stream, &type, &valueLength, &stringTag );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If this is an unrecognised AVA, don't try and process it (the\n\t\t   content will already have been skipped in readAVA()) */\n\t\tif( status == OK_SPECIAL )\n\t\t\treturn( CRYPT_OK );\n\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that the string is a valid type for a DirectoryString.  We \n\t   don't allow Universal strings since no-one in their right mind uses\n\t   those.\n\t   \n\t   Alongside DirectoryString values we also allow IA5Strings, from the\n\t   practice of stuffing email addresses into DNs */\n\tif( stringTag != BER_STRING_PRINTABLE && stringTag != BER_STRING_T61 && \\\n\t\tstringTag != BER_STRING_BMP && stringTag != BER_STRING_UTF8 && \\\n\t\tstringTag != BER_STRING_IA5 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Skip broken AVAs with zero-length strings */\n\tif( valueLength <= 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* Record the string contents, avoiding moving it into a buffer */\n\tstatus = sMemGetDataBlock( stream, &value, valueLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, valueLength, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( value != NULL );\n\n\t/* If there's room for another AVA, mark this one as being continued.  The\n\t   +10 value is the minimum length for an AVA: SEQUENCE { OID, value } \n\t   (2-bytes SEQUENCE + 5 bytes OID + 2 bytes (tag + length) + 1 byte min-\n\t   length data) */\n\tif( rdnDataLeft >= ( stell( stream ) - rdnStart ) + 10 )\n\t\tflags |= DN_FLAG_CONTINUED;\n\n\t/* Convert the string into the local character set */\n\tstatus = copyFromAsn1String( stringBuffer, MAX_ATTRIBUTE_SIZE, \n\t\t\t\t\t\t\t\t &valueLength, &valueStringType, value, \n\t\t\t\t\t\t\t\t valueLength, stringTag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the DN component to the DN.  If we hit a non-memory related error\n\t   we turn it into a generic CRYPT_ERROR_BADDATA error since the other\n\t   codes are somewhat too specific for this case, something like \n\t   CRYPT_ERROR_INITED or an arg error isn't too useful for the caller */\n\tstatus = insertDNstring( dnPtr, type, stringBuffer, valueLength,\n\t\t\t\t\t\t\t valueStringType, flags, &dummy );\n\treturn( ( cryptStatusError( status ) && status != CRYPT_ERROR_MEMORY ) ? \\\n\t\t\tCRYPT_ERROR_BADDATA : status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readDNComponent( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT DATAPTR_DN *dnPtr )\n\t{\n\tint rdnLength, noComponents, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\n\t/* Read the start of the RDN */\n\tstatus = readSet( stream, &rdnLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read each RDN component */\n\tLOOP_MED( noComponents = 0, rdnLength > 0 && noComponents < 32,\n\t\t\t  noComponents++ )\n\t\t{\n\t\tconst int rdnStart = stell( stream );\n\n\t\tREQUIRES( isShortIntegerRangeNZ( rdnStart ) );\n\n\t\tstatus = readRDNcomponent( stream, dnPtr, rdnLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\trdnLength -= stell( stream ) - rdnStart;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( rdnLength < 0 || noComponents >= 32 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readDN( INOUT STREAM *stream, \n\t\t\tOUT_DATAPTR_COND DATAPTR_DN *dnPtr )\n\t{\n\tDATAPTR_DN dn;\n\tint length, noComponents, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\n\t/* Clear return value */\n\tDATAPTR_SET_PTR( dnPtr, NULL );\n\n\t/* Read the encoded DN into the local copy of the DN (in other words \n\t   into the dn, not the externally-visible dnPtr) */\n\tstatus = readSequenceZ( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\t/* Some buggy certificates include zero-length DNs, which we skip */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tDATAPTR_SET( dn, NULL );\n\tLOOP_MED( noComponents = 0, length > 0 && noComponents < 32,\n\t\t\t  noComponents++ )\n\t\t{\n\t\tconst int startPos = stell( stream );\n\n\t\tREQUIRES( isShortIntegerRangeNZ( startPos ) );\n\n\t\tstatus = readDNComponent( stream, &dn );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tlength -= stell( stream ) - startPos;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) || \\\n\t\tlength < 0 || noComponents >= 32 )\n\t\t{\n\t\t/* Delete the local copy of the DN read so far if necessary */\n\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\tdeleteDN( &dn );\n\t\treturn( cryptStatusError( status ) ? status : CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Copy the local copy of the DN back to the caller */\n\t*dnPtr = dn;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tWrite a DN\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform the pre-encoding processing for a DN.  Note that sizeofDN() takes\n   a slightly anomalous const parameter that isn't because the pre-encoding \n   process required to determine the DN's size modifies portions of the DN \n   component values related to the encoding process */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int preEncodeDN( INOUT DN_COMPONENT *dnComponentPtr, \n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *length )\n\t{\n\tint size = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dnComponentPtr, sizeof( DN_COMPONENT ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckDNComponent( dnComponentPtr ) );\n\tREQUIRES( DATAPTR_ISNULL( dnComponentPtr->prev ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Walk down the DN pre-encoding each AVA */\n\tLOOP_MED_CHECKINC( dnComponentPtr != NULL,\n\t\t\t\t\t   dnComponentPtr = DATAPTR_GET( dnComponentPtr->next ) )\n\t\t{\n\t\tDN_COMPONENT *rdnStartPtr = dnComponentPtr;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Calculate the size of every AVA in this RDN */\n\t\tLOOP_MED_CHECKINC_ALT( dnComponentPtr != NULL,\n\t\t\t\t\t\t\t   dnComponentPtr = DATAPTR_GET( dnComponentPtr->next ) )\n\t\t\t{\n\t\t\tconst DN_COMPONENT_INFO *dnComponentInfo;\n\t\t\tint dnStringLength, status;\n\n\t\t\tREQUIRES( sanityCheckDNComponent( dnComponentPtr ) );\n\n\t\t\tdnComponentInfo = dnComponentPtr->typeInfo;\n\t\t\tstatus = getAsn1StringInfo( dnComponentPtr->value, \n\t\t\t\t\t\t\t\t\t\tdnComponentPtr->valueLength,\n\t\t\t\t\t\t\t\t\t\t&dnComponentPtr->valueStringType, \n\t\t\t\t\t\t\t\t\t\t&dnComponentPtr->asn1EncodedStringType,\n\t\t\t\t\t\t\t\t\t\t&dnStringLength, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tdnComponentPtr->encodedAVAdataSize = \\\n\t\t\t\t\t\t\t\t\t\tsizeofOID( dnComponentInfo->oid ) + \\\n\t\t\t\t\t\t\t\t\t\tsizeofShortObject( dnStringLength );\n\t\t\tdnComponentPtr->encodedRDNdataSize = 0;\n\t\t\trdnStartPtr->encodedRDNdataSize += \\\n\t\t\t\t\t\tsizeofShortObject( dnComponentPtr->encodedAVAdataSize );\n\t\t\tif( !TEST_FLAG( dnComponentPtr->flags, DN_FLAG_CONTINUED ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\n\t\t/* Calculate the overall size of the RDN */\n\t\tsize += sizeofShortObject( rdnStartPtr->encodedRDNdataSize );\n\n\t\t/* If the inner loop terminated because it reached the end of the DN \n\t\t   then we need to explicitly exit the outer loop as well before it\n\t\t   tries to follow the 'next' link in the dnComponentPtr */\n\t\tif( dnComponentPtr == NULL )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*length = size;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_LENGTH \\\nint sizeofDN( IN_DATAPTR_OPT const DATAPTR_DN dn )\n\t{\n\tDN_COMPONENT *dnComponentList;\n\tint length, status;\n\n\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\n\t/* Null DNs produce a zero-length SEQUENCE */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( sizeofObject( 0 ) );\n\n\tdnComponentList = DATAPTR_GET( dn );\n\tENSURES( dnComponentList != NULL );\n\tREQUIRES( sanityCheckDNComponent( dnComponentList ) );\n\tstatus = preEncodeDN( dnComponentList, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sizeofObject( length ) );\n\t}\n\n/* Write a DN */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeDN( INOUT STREAM *stream, \n\t\t\t IN const DATAPTR_DN dn,\n\t\t\t IN_TAG const int tag )\n\t{\n\tDN_COMPONENT *dnComponentList, *dnComponentPtr;\n\tint size, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( DATAPTR_ISVALID( dn ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Special case for empty DNs */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( writeConstructed( stream, 0, tag ) );\n\n\tdnComponentList = DATAPTR_GET( dn );\n\tENSURES( dnComponentList != NULL );\n\tREQUIRES( sanityCheckDNComponent( dnComponentList ) );\n\tstatus = preEncodeDN( dnComponentList, &size );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the DN */\n\twriteConstructed( stream, size, tag );\n\tLOOP_MED( dnComponentPtr = dnComponentList, \n\t\t\t  dnComponentPtr != NULL,\n\t\t\t  dnComponentPtr = DATAPTR_GET( dnComponentPtr->next ) )\n\t\t{\n\t\tconst DN_COMPONENT_INFO *dnComponentInfo;\n\t\tBYTE dnString[ MAX_ATTRIBUTE_SIZE + 8 ];\n\t\tint dnStringLength;\n\n\t\tREQUIRES( sanityCheckDNComponent( dnComponentPtr ) );\n\n\t\t/* Write the RDN wrapper */\n\t\tdnComponentInfo = dnComponentPtr->typeInfo;\n\t\tif( dnComponentPtr->encodedRDNdataSize > 0 )\n\t\t\t{\n\t\t\t/* If it's the start of an RDN, write the RDN header */\n\t\t\twriteSet( stream, dnComponentPtr->encodedRDNdataSize );\n\t\t\t}\n\t\twriteSequence( stream, dnComponentPtr->encodedAVAdataSize );\n\t\tstatus = swrite( stream, dnComponentInfo->oid, \n\t\t\t\t\t\t sizeofOID( dnComponentInfo->oid ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Convert the string to an ASN.1-compatible format and write it\n\t\t   out */\n\t\tstatus = copyToAsn1String( dnString, MAX_ATTRIBUTE_SIZE, \n\t\t\t\t\t\t\t\t   &dnStringLength, dnComponentPtr->value,\n\t\t\t\t\t\t\t\t   dnComponentPtr->valueLength,\n\t\t\t\t\t\t\t\t   dnComponentPtr->valueStringType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( dnComponentPtr->asn1EncodedStringType == BER_STRING_IA5 && \\\n\t\t\t!dnComponentInfo->ia5OK )\n\t\t\t{\n\t\t\t/* If an IA5String isn't allowed in this instance, use a\n\t\t\t   T61String instead */\n\t\t\tdnComponentPtr->asn1EncodedStringType = BER_STRING_T61;\n\t\t\t}\n\t\tstatus = writeCharacterString( stream, dnString, dnStringLength,\n\t\t\t\t\t\t\t\t\t   dnComponentPtr->asn1EncodedStringType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/dn_rws.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate DN String Read/Write Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"dn.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/dn.h\"\n#endif /* Compiler-specific includes */\n\n/* The ability to specify free-form DNs means that users can create \n   arbitrarily garbled and broken DNs (the creation of weird nonstandard DNs \n   is pretty much the main reason why the DN-string capability exists).  \n   This includes DNs that can't be easily handled through normal cryptlib \n   facilities, for example ones where the CN component consists of illegal \n   characters or is in a form that isn't usable as a search key for \n   functions like cryptGetPublicKey().  Because of these problems this \n   functionality is disabled by default, if users want to use this oddball-\n   DN facility it's up to them to make sure that the resulting DN \n   information works with whatever environment they're intending to use it \n   in */\n\n#if defined( USE_CERTIFICATES ) && defined( USE_CERT_DNSTRING )\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with string-form DNs enabled.\" )\n#endif /* Warn about special features enabled */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead a String-form DN\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a string can be represented as a textual DN string */\n\nstatic BOOLEAN isTextString( IN_BUFFER( stringLength ) const BYTE *string, \n\t\t\t\t\t\t\t IN_LENGTH_ATTRIBUTE const int stringLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\tREQUIRES_B( stringLength > 0 && stringLength <= MAX_ATTRIBUTE_SIZE );\n\n\t/* Make sure that there are no control characters in the string.  We \n\t   allow high-bit-set characters in order to support latin-1 strings,\n\t   see also the comment at the start of this section about the general\n\t   caveat-emptor philosophy for this interface */\n\tLOOP_LARGE( i = 0, i < stringLength, i++ )\n\t\t{\n\t\tif( ( string[ i ] & 0x7F ) < ' ' )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Read a DN in string form */\n\ntypedef struct {\n\tBUFFER_FIXED( labelLen ) \\\n\tconst BYTE *label;\n\tBUFFER_FIXED( textLen ) \\\n\tconst BYTE *text;\n\tint labelLen, textLen;\t/* DN component label and value */\n\tBOOLEAN isContinued;\t/* Whether there are further AVAs in this RDN */\n\t} DN_STRING_INFO;\n\n#define MAX_DNSTRING_COMPONENTS 32\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN parseDNString( OUT_ARRAY( MAX_DNSTRING_COMPONENTS ) \\\n\t\t\t\t\t\t\t\t\tDN_STRING_INFO *dnStringInfo,\n\t\t\t\t\t\t\t  OUT_RANGE( 0, MAX_DNSTRING_COMPONENTS ) \\\n\t\t\t\t\t\t\t\t\tint *dnStringInfoIndex,\n\t\t\t\t\t\t\t  IN_BUFFER( stringLength ) const BYTE *string, \n\t\t\t\t\t\t\t  IN_LENGTH_ATTRIBUTE const int stringLength )\n\t{\n\tint stringPos, stringInfoIndex, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dnStringInfo, sizeof( DN_STRING_INFO ) * \\\n\t\t\t\t\t\t\t\t\t  MAX_DNSTRING_COMPONENTS ) );\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\tREQUIRES_B( stringLength > 0 && stringLength <= MAX_ATTRIBUTE_SIZE );\n\n\t/* Clear return values */\n\tmemset( dnStringInfo, 0,\n\t\t\tsizeof( DN_STRING_INFO ) * MAX_DNSTRING_COMPONENTS );\n\t*dnStringInfoIndex = 0;\n\n\t/* Make sure that the string is can be rendered as a text string */\n\tif( !isTextString( string, stringLength ) )\n\t\treturn( FALSE );\n\n\t/* Verify that a DN string is of the form:\n\n\t\tdnString ::= assignment '\\0' | assignment ',' assignment\n\t\tassignment ::= label '=' text */\n\tLOOP_EXT( ( stringPos = 0, stringInfoIndex = 0 ),\n\t\t\t  stringPos < stringLength && \\\n\t\t\t\tstringInfoIndex < MAX_DNSTRING_COMPONENTS, \n\t\t\t  stringInfoIndex++, MAX_DNSTRING_COMPONENTS + 1 )\n\t\t{\n\t\tDN_STRING_INFO *dnStringInfoPtr = &dnStringInfo[ stringInfoIndex ];\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Check for label '=' ... */\n\t\tLOOP_LARGE_ALT( i = stringPos, i < stringLength, i++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( string[ i ] );\n\n\t\t\tif( ch == '\\\\' || ch == '+' || ch == ',' )\n\t\t\t\t{\n\t\t\t\t/* The label component can't have special characters in it */\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( ch == '=' )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tif( i <= stringPos || i >= stringLength - 1 )\t/* -1 for '=' */\n\t\t\t{\n\t\t\t/* The label component is empty */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tENSURES_B( boundsCheckZ( stringPos, i - stringPos, stringLength ) );\n\t\tdnStringInfoPtr->label = string + stringPos;\n\t\tdnStringInfoPtr->labelLen = i - stringPos;\n\t\tstringPos = i + 1;\t\t/* Skip text + '=' */\n\n\t\t/* Check for ... text { EOT | ',' ... | '+' ... } */\n\t\tLOOP_LARGE_ALT( i = stringPos, \n\t\t\t\t\t\ti < stringLength && i < MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( string[ i ] );\n\n\t\t\t/* Check for invalid data */\n\t\t\tif( ch == '=' )\n\t\t\t\t{\n\t\t\t\t/* Spurious '=' */\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( ch == '\\\\' )\n\t\t\t\t{\n\t\t\t\tif( i >= stringLength - 1 )\n\t\t\t\t\t{\n\t\t\t\t\t/* Missing escaped character */\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\n\t\t\t\t/* It's an escaped character that isn't subject to the usual\n\t\t\t\t   checks, skip it and continue */\n\t\t\t\ti++;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* If this isn't a continuation symbol, continue */\n\t\t\tif( ch != ',' && ch != '+' )\n\t\t\t\tcontinue;\n\n\t\t\t/* We've reached a continuation symbol, make sure that there's \n\t\t\t   room for at least another 'x=y' after this point */\n\t\t\tif( i >= stringLength - 3 )\n\t\t\t\treturn( FALSE );\n\n\t\t\tbreak;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tENSURES_B( boundsCheck( stringPos, i - stringPos, stringLength ) );\n\t\tdnStringInfoPtr->text = string + stringPos;\n\t\tdnStringInfoPtr->textLen = i - stringPos;\n\t\tif( string[ i ] == ',' || string[ i ] == '+' )\n\t\t\t{\n\t\t\t/* Skip the final ',' or '+' and remember whether this is a \n\t\t\t   continued RDN */\n\t\t\tif( string[ i ] == '+' )\n\t\t\t\tdnStringInfoPtr->isContinued = TRUE;\n\t\t\ti++;\n\t\t\t}\n\t\tstringPos = i;\t\t\t/* Skip text + optional ','/'+' */\n\n\t\t/* Strip leading and trailing whitespace on the label and text */\n\t\tdnStringInfoPtr->labelLen = \\\n\t\t\t\tstrStripWhitespace( ( const char ** ) &dnStringInfoPtr->label,\n\t\t\t\t\t\t\t\t\tdnStringInfoPtr->label, \n\t\t\t\t\t\t\t\t\tdnStringInfoPtr->labelLen );\n\t\tdnStringInfoPtr->textLen = \\\n\t\t\t\tstrStripWhitespace( ( const char ** ) &dnStringInfoPtr->text,\n\t\t\t\t\t\t\t\t\tdnStringInfoPtr->text, \n\t\t\t\t\t\t\t\t\tdnStringInfoPtr->textLen );\n\t\tif( dnStringInfoPtr->labelLen < 1 || \\\n\t\t\tdnStringInfoPtr->labelLen > MAX_ATTRIBUTE_SIZE || \\\n\t\t\tdnStringInfoPtr->textLen < 1 || \\\n\t\t\tdnStringInfoPtr->textLen > MAX_ATTRIBUTE_SIZE )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( stringInfoIndex <= 0 || stringInfoIndex >= MAX_DNSTRING_COMPONENTS )\n\t\treturn( FALSE );\n\t*dnStringInfoIndex = stringInfoIndex;\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readDNstring( INOUT_PTR DATAPTR_DN *dnPtr,\n\t\t\t\t  IN_BUFFER( stringLength ) const BYTE *string, \n\t\t\t\t  IN_LENGTH_ATTRIBUTE const int stringLength )\n\t{\n\tDN_STRING_INFO dnStringInfo[ MAX_DNSTRING_COMPONENTS + 8 ];\n\tDATAPTR_DN dn;\n\tDN_COMPONENT *dnComponentList = NULL, *dnComponentListCursor;\n\tint stringInfoIndex, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dnPtr, sizeof( DATAPTR_DN ) ) );\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\tREQUIRES( stringLength > 0 && stringLength <= MAX_ATTRIBUTE_SIZE );\n\n\t/* Clear return value */\n\tDATAPTR_SET_PTR( dnPtr, NULL );\n\n\t/* We have to perform the text string to DN translation in two stages\n\t   thanks to the backwards encoding required by RFC 1779.  First we \n\t   parse it forwards to separate out the RDN components, then we move \n\t   through the parsed information backwards adding it to the RDN (with \n\t   special handling for multi-AVA RDNs as for writeDNstring()).  Overall \n\t   this isn't so bad because it means that we can perform a general \n\t   firewall check to make sure that the DN string is well-formed and \n\t   then leave the decoding as a separate pass */\n\tif( !parseDNString( dnStringInfo, &stringInfoIndex, string, \n\t\t\t\t\t\tstringLength ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* parseDNString() returns the number of entries parsed, since we're\n\t   using zero-based indexing we have to decrement the value returned to\n\t   provide the actual index into the dnStringInfo[] array */\n\tstringInfoIndex--;\n\n\tDATAPTR_SET( dn, NULL );\n\tLOOP_MED_CHECKINC( stringInfoIndex >= 0, stringInfoIndex-- )\n\t\t{\n\t\tconst DN_STRING_INFO *dnStringInfoPtr;\n\t\tBOOLEAN isContinued;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Find the start of the RDN */\n\t\tLOOP_MED_CHECKINC_ALT( stringInfoIndex > 0 && \\\n\t\t\t\t\t\t\t\tdnStringInfo[ stringInfoIndex - 1 ].isContinued,\n\t\t\t\t\t\t\t   stringInfoIndex-- );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tdnStringInfoPtr = &dnStringInfo[ stringInfoIndex ];\n\n\t\tLOOP_MED_INITCHECK_ALT( isContinued = TRUE, isContinued )\n\t\t\t{\n\t\t\tCRYPT_ERRTYPE_TYPE dummy;\n\t\t\tconst DN_COMPONENT_INFO *dnComponentInfo;\n\t\t\tBYTE textBuffer[ MAX_ATTRIBUTE_SIZE + 8 ];\n\t\t\tCRYPT_ATTRIBUTE_TYPE type;\n\t\t\tint i, textIndex = 0, valueStringType, dummy1, dummy2;\n\t\t\tint status, LOOP_ITERATOR_ALT2;\n\n\t\t\t/* Look up the DN component information */\n\t\t\tdnComponentInfo = findDNInfoByLabel( dnStringInfoPtr->label, \n\t\t\t\t\t\t\t\t\t\t\t\t dnStringInfoPtr->labelLen );\n\t\t\tif( dnComponentInfo == NULL )\n\t\t\t\t{\n\t\t\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\t\t\tdeleteDN( &dn );\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\ttype = dnComponentInfo->type;\n\n\t\t\t/* Convert the text to canonical form, removing any escapes for\n\t\t\t   special characters */\n\t\t\tLOOP_EXT_ALT2( i = 0, i < dnStringInfoPtr->textLen, i++,\n\t\t\t\t\t\t   MAX_ATTRIBUTE_SIZE )\n\t\t\t\t{\n\t\t\t\tint ch = byteToInt( dnStringInfoPtr->text[ i ] );\n\n\t\t\t\tif( ch == '\\\\' )\n\t\t\t\t\t{\n\t\t\t\t\t/* Skip '\\\\' */\n\t\t\t\t\ti++;\n\t\t\t\t\tif( i >= dnStringInfoPtr->textLen )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\t\t\t\t\tdeleteDN( &dn );\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t\t\t}\n\t\t\t\t\tch = byteToInt( dnStringInfoPtr->text[ i ] );\n\t\t\t\t\t}\n\t\t\t\ttextBuffer[ textIndex++ ] = intToByte( ch );\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT2 );\n\t\t\tENSURES( isShortIntegerRangeNZ( textIndex ) );\n\n\t\t\t/* The value is coming from an external source, make sure that \n\t\t\t   it's representable as a certificate string type.  All that \n\t\t\t   we care about here is the validity so we ignore the returned \n\t\t\t   encoding information */\n\t\t\tstatus = getAsn1StringInfo( textBuffer, textIndex, \n\t\t\t\t\t\t\t\t\t\t&valueStringType, &dummy1, &dummy2, \n\t\t\t\t\t\t\t\t\t\tFALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\t\t\tdeleteDN( &dn );\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\n\t\t\t/* Add the AVA to the DN */\n\t\t\tif( type == CRYPT_CERTINFO_COUNTRYNAME )\n\t\t\t\t{\n\t\t\t\t/* If it's a country code force it to uppercase as per ISO 3166 */\n\t\t\t\tif( textIndex != 2 )\n\t\t\t\t\t{\n\t\t\t\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\t\t\t\tdeleteDN( &dn );\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t\t}\n\t\t\t\ttextBuffer[ 0 ] = intToByte( toUpper( textBuffer[ 0 ] ) );\n\t\t\t\ttextBuffer[ 1 ] = intToByte( toUpper( textBuffer[ 1 ] ) );\n\t\t\t\t}\n\t\t\tstatus = insertDNstring( &dn, type, textBuffer, textIndex, \n\t\t\t\t\t\t\t\t\t valueStringType,\n\t\t\t\t\t\t\t\t\t ( dnStringInfoPtr->isContinued ) ? \\\n\t\t\t\t\t\t\t\t\t\tDN_FLAG_CONTINUED | DN_FLAG_NOCHECK :\n\t\t\t\t\t\t\t\t\t\tDN_FLAG_NOCHECK, &dummy );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( DATAPTR_ISSET( dn ) )\n\t\t\t\t\tdeleteDN( &dn );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\t/* Move on to the next AVA */\n\t\t\tisContinued = dnStringInfoPtr->isContinued;\n\t\t\tdnStringInfoPtr++;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We're done, lock the DN against further updates */\n\tLOOP_LARGE( dnComponentListCursor = dnComponentList,\n\t\t\t\tdnComponentListCursor != NULL,\n\t\t\t\tdnComponentListCursor = DATAPTR_GET( dnComponentListCursor->next ) )\n\t\t{\n\t\tSET_FLAG( dnComponentListCursor->flags, DN_FLAG_LOCKED );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Copy the local copy of the DN back to the caller */\n\t*dnPtr = dn;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite a String-form DN\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a DN in string form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeAVAString( INOUT STREAM *stream,\n\t\t\t\t\t\t   const DN_COMPONENT *dnComponentPtr )\n\t{\n\tconst DN_COMPONENT_INFO *componentInfoPtr = dnComponentPtr->typeInfo;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( dnComponentPtr, sizeof( DN_COMPONENT ) ) );\n\n\tREQUIRES( sanityCheckDNComponent( dnComponentPtr ) );\n\n\t/* Print the current AVA */\n\tswrite( stream, componentInfoPtr->name, componentInfoPtr->nameLen );\n\tstatus = sputc( stream, '=' );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_LARGE( i = 0, i < dnComponentPtr->valueLength, i++ )\n\t\t{\n\t\tconst int ch = byteToInt( ( ( BYTE * ) dnComponentPtr->value )[ i ] );\n\n\t\tif( ch == ',' || ch == '=' || ch == '+' || ch == ';' || \\\n\t\t\tch == '\\\\' || ch == '\"' )\n\t\t\tsputc( stream, '\\\\' );\n\t\tstatus = sputc( stream, ch );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeDNstring( INOUT STREAM *stream, \n\t\t\t\t   const DATAPTR_DN dn )\n\t{\n\tconst DN_COMPONENT *dnComponentListPtr, *prevElementPtr;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( DATAPTR_ISVALID( dn ) );\n\n\t/* Special case for empty DNs */\n\tif( DATAPTR_ISNULL( dn ) )\n\t\treturn( CRYPT_OK );\n\n\tdnComponentListPtr = DATAPTR_GET( dn );\n\tENSURES( dnComponentListPtr != NULL );\n\tREQUIRES( sanityCheckDNComponent( dnComponentListPtr ) );\n\n\t/* Find the end of the DN string.  We have to print the RDNs backwards\n\t   because of ISODE's JANET memorial backwards encoding.  This also \n\t   provides a convenient location to check that the DN data is actually\n\t   representable as a text string.\n\n\t   Some string types can't be represented as text strings which means \n\t   that we can't send them directly to the output.  The details of what \n\t   to do here are a bit complex, in theory we could send them out as \n\t   UTF-8 but few environments are going to expect this as a returned \n\t   type, particularly when the existing expectation is for oddball \n\t   characters in text strings to be latin-1.  The least ugly solution \n\t   seems to be to just return an indicator that this string can't be \n\t   represented */\n\tLOOP_MED( prevElementPtr = dnComponentListPtr,\n\t\t\t  dnComponentListPtr != NULL,\n\t\t\t  ( prevElementPtr = dnComponentListPtr,\n\t\t\t\tdnComponentListPtr = DATAPTR_GET( dnComponentListPtr->next ) ) )\n\t\t{\n\t\tREQUIRES( sanityCheckDNComponent( dnComponentListPtr ) );\n\n\t\t/* Make sure that the DN component is representable as a text \n\t\t   string.  Exactly what we should return if this check fails is a\n\t\t   bit uncertain since there's no error code that it really\n\t\t   corresponds to, CRYPT_ERROR_NOTAVAIL appears to be the least\n\t\t   inappropriate one to use.\n\t\t   \n\t\t   An alternative is to return a special-case string like \"(DN \n\t\t   can't be represented in string form)\" but this then looks (from \n\t\t   the return status) as if it was actually representable, requiring \n\t\t   special-case checks for valid-but-not-valid returned data, so the \n\t\t   error status is probably the best option */\n\t\tif( !isTextString( dnComponentListPtr->value, \n\t\t\t\t\t\t   dnComponentListPtr->valueLength ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tLOOP_MED_INITCHECK( dnComponentListPtr = prevElementPtr, \n\t\t\t\t\t\tdnComponentListPtr != NULL )\n\t\t{\n\t\tconst DN_COMPONENT *dnComponentCursor, *dnComponentPrev;\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Find the start of the RDN */\n\t\tLOOP_MED_ALT( dnComponentPrev = DATAPTR_GET( dnComponentListPtr->prev ),\n\t\t\t\t\t  dnComponentPrev != NULL && \\\n\t\t\t\t\t\t\tTEST_FLAG( dnComponentPrev->flags, DN_FLAG_CONTINUED ),\n\t\t\t\t\t  ( dnComponentListPtr = dnComponentPrev,\n\t\t\t\t\t\t\tdnComponentPrev = DATAPTR_GET( dnComponentPrev->prev ) ) );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tdnComponentCursor = dnComponentListPtr;\n\t\tdnComponentListPtr = dnComponentPrev;\n\n\t\t/* Print the current RDN.  The loop checks and controls are \n\t\t   sufficiently non-amenable to implementation as a standard loop \n\t\t   that we just use a dummy counter i that guarantees that the loop \n\t\t   is double-indexed */\n\t\tLOOP_MED_ALT( i = 0, i < 50, i++ )\n\t\t\t{\n\t\t\tstatus = writeAVAString( stream, dnComponentCursor );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* If this is the last AVA in the RDN, we're done */\n\t\t\tif( !TEST_FLAG( dnComponentCursor->flags, DN_FLAG_CONTINUED ) )\n\t\t\t\tbreak;\n\n\t\t\t/* There are more AVAs in this RDN, print a continuation \n\t\t\t   indicator and move on to the next AVA */\n\t\t\tstatus = swrite( stream, \" + \", 3 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tdnComponentCursor = DATAPTR_GET( dnComponentCursor->next );\n\t\t\tENSURES( dnComponentCursor != NULL );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( i < 50 );\n\n\t\t/* If there are more components to come print an RDN separator */\n\t\tif( dnComponentListPtr != NULL )\n\t\t\t{\n\t\t\tstatus = swrite( stream, \", \", 2 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES && USE_CERT_DNSTRING */\n\n"
  },
  {
    "path": "deps/cl345/cert/dn_string.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate String Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"misc_rw.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/misc_rw.h\"\n#endif /* Compiler-specific includes */\n\n/* The character set (or at least ASN.1 string type) for a string.  Although \n   IA5String and VisibleString/ISO646String are technically different the \n   only real difference is that IA5String allows the full range of control \n   characters, which isn't notably useful.  For this reason we treat both as \n   ISO646String.  Sometimes we can be fed Unicode strings that are just \n   bloated versions of another string type so we need to account for these \n   as well.\n\n   UTF-8 strings are a pain because they're only intermittently supported as \n   a native format.  For this reason we convert them to a more useful local\n   character set (ASCII, 8859-1, or Unicode as appropriate) when we read \n   them to make them usable.  Although their use was required after the \n   cutover date of December 2003, by unspoken unanimous consensus of \n   implementers everywhere implementations stuck with the existing DN \n   encoding to avoid breaking things.  Several years after the cutoff date \n   vendors slowly started introducing UTF-8 support to certificate-using\n   applications, although on an ad-hoc basis and sometimes only as a user-\n   configurable option so it's still too risky to rely on this being\n   supported */\n\ntypedef enum {\n\tSTRINGTYPE_NONE,\t\t\t\t\t/* No string type */\n\n\t/* 8-bit character types */\n\tSTRINGTYPE_PRINTABLE,\t\t\t\t/* PrintableString */\n\tSTRINGTYPE_IA5,\t\t\t\t\t\t/* IA5String */\n\tSTRINGTYPE_T61,\t\t\t\t\t\t/* T61 (8859-1) string */\n\n\t/* 8-bit types masquerading as Unicode */\n\tSTRINGTYPE_UNICODE_PRINTABLE,\t\t/* PrintableString as Unicode */\n\tSTRINGTYPE_UNICODE_IA5,\t\t\t\t/* IA5String as Unicode */\n\tSTRINGTYPE_UNICODE_T61,\t\t\t\t/* 8859-1 as Unicode */\n\n\t/* 8-bit native character string (e.g. eastern European latin-2 or \n\t   Windows CP 1251) that needs to be converted to Unicode (only valid \n\t   for strings originating from the local system) */\n\tSTRINGTYPE_TO_UNICODE,\t\t\t\t/* 8-bit string needing conversion */\n\n\t/* Unicode/UTF-8 */\n\tSTRINGTYPE_UNICODE,\t\t\t\t\t/* Unicode string */\n\tSTRINGTYPE_UTF8,\t\t\t\t\t/* UTF-8 string */\n\n\t/* Special-case error string types.  STRINGTYPE_ERROR_TRY_UNICODE tells\n\t   the caller to try converting from a system-native 8-bit character set\n\t   type to Unicode before reporting an error in case this is some \n\t   oddball 8-bit character set that the local system understands but that\n\t   isn't equivalent to any ASN.1 string type.  If the string type can be\n\t   converted to Unicode it's then reported as STRINGTYPE_TO_UNICODE */\n\tSTRINGTYPE_ERROR,\t\t\t\t\t/* Error occurred during processing */\n\tSTRINGTYPE_ERROR_TRY_UNICODE,\t\t/* Try converting to Unicode */\n\n\tSTRINGTYPE_LAST\t\t\t\t\t\t/* Last possible string type */\n\t} ASN1_STRINGTYPE;\n\n#define isErrorStringType( stringType ) \\\n\t\t( ( stringType ) == STRINGTYPE_ERROR_TRY_UNICODE || \\\n\t\t  ( stringType ) == STRINGTYPE_ERROR )\n\n/* Since wchar_t can be anything from 8 bits (Borland C++ under DOS) to 32 \n   bits (some RISC Unixen) we define a bmpchar_t for Unicode/BMPString \n   characters which is always 16 bits as required for BMPStrings, to match \n   the naming convention of wchar_t.  The conversion to and from a BMPString \n   and wchar_t may require narrowing or widening of characters and possibly \n   endianness conversion as well */\n\ntypedef unsigned short int bmpchar_t;\t/* Unicode/BMPString data type */\n#define UCSIZE\t2\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCharacter Set Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Because of the bizarre (and mostly useless) collection of ASN.1 character\n   types we need to be very careful about what we allow in a string.  The\n   following table is used to determine whether a character is valid within \n   a given string type.\n\n   Although IA5String and VisibleString/ISO646String are technically\n   different the only real difference is that IA5String allows the full \n   range of control characters, which isn't notably useful.  For this reason \n   we treat both as ISO646String */\n\n#define P\t1\t\t\t\t\t\t/* PrintableString */\n#define I\t2\t\t\t\t\t\t/* IA5String/VisibleString/ISO646String */\n#define PI\t( P | I )\t\t\t\t/* PrintableString and IA5String */\n\nstatic const int asn1CharFlags[] = {\n\t/* 00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F */\n\t\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\n\t/* 10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F */\n\t\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\n\t/*\t\t!\t\"\t#\t$\t%\t&\t'\t(\t)\t*\t+\t,\t-\t.\t/ */\n\t   PI,\tI,\tI,\tI,\tI,\tI,\tI, PI, PI, PI,\tI, PI, PI, PI, PI, PI,\n\t/*\t0\t1\t2\t3\t4\t5\t6\t7\t8\t9\t:\t;\t<\t=\t>\t? */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI, PI,\tI, PI,\n\t/*\t@\tA\tB\tC\tD\tE\tF\tG\tH\tI\tJ\tK\tL\tM\tN\tO */\n\t\tI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\n\t/*\tP\tQ\tR\tS\tT\tU\tV\tW\tX\tY\tZ\t[\t\\\t]\t^\t_ */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI,\tI,\tI,\tI,\n\t/*\t`\ta\tb\tc\td\te\tf\tg\th\ti\tj\tk\tl\tm\tn\to */\n\t\tI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\n\t/*\tp\tq\tr\ts\tt\tu\tv\tw\tx\ty\tz\t{\t|\t}\t~  DL */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI,\tI,\tI,\t0,\n\t\t0, 0\t/* Catch overflows */\n\t};\n\n#define nativeCharFlags\tasn1CharFlags\n\n/* Extract a widechar or bmpchar from an (arbitrarily-aligned) string.  Note\n   that if WCSIZE == sizeof( wchar_t ) is larger than 16 bits and we're fed \n   malformed data then the return value can become larger than what's \n   indicated in the CHECK_RETVAL_RANGE() statement, but the calling code \n   checks for this so it's mostly a slightly misleading static-analysis\n   annotation */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, 0xFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic wchar_t getNativeWidechar( IN_BUFFER_C( 2 ) const BYTE *string )\n\t{\n\twchar_t ch = 0;\n#ifdef DATA_LITTLEENDIAN\n\tint shiftAmt = 0;\n#endif /* DATA_LITTLEENDIAN */\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( string, 2 ) );\n\t\n\t/* Since we're reading wchar_t-sized values from a char-aligned source, \n\t   we have to assemble the data a byte at a time to handle systems where \n\t   non-char values can only be accessed on word-aligned boundaries */\n\tLOOP_SMALL( i = 0, i < WCSIZE, i++ )\n\t\t{\n#ifdef DATA_LITTLEENDIAN\n\t\tch |= string[ i ] << shiftAmt;\n\t\tshiftAmt += 8;\n#else\n\t\tch = ( ch << 8 ) | string[ i ];\n#endif /* DATA_LITTLEENDIAN */\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, 0 );\n\n\treturn( ch );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUTF-8 Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Parse one UTF-8 encoded character from a string, enforcing the UTF-8 \n   canonical-encoding rules:\n\n\t  00 -  7F = 0xxxxxxx, mask = 0x80\n\t 80 -  7FF = 110xxxxx 10xxxxxx, mask = 0xE0\n\t800 - FFFF = 1110xxxx 10xxxxxx 10xxxxxx, mask = 0xF0\n\n   Note that some of the checks applied below are redundant but due to the \n   powerful nature of UTF-8 string formatting attacks we apply them anyway \n   to make the different checking actions explicit and to reduce the chances \n   of a coding error that allows something dangerous to slip through */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic long getUTF8Char( INOUT STREAM *stream )\n\t{\n\tlong largeCh;\n\tint firstChar, secondChar, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Process the first character */\n\tstatus = firstChar = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( !( firstChar & 0x80 ) )\n\t\t{\n\t\t/* 1-byte character, straight ASCII */\n\t\treturn( firstChar & 0x7F );\n\t\t}\n\tif( ( firstChar & 0xC0 ) == 0x80 )\t\t/* 11xxxxxx -> 10xxxxxx */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Process the second character */\n\tstatus = secondChar = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( ( firstChar & 0xE0 ) == 0xC0 )\t\t/* 111xxxxx -> 110xxxxx */\n\t\t{\n\t\t/* 2-byte character in the range 0x80...0x7FF */\n\t\tif( ( secondChar & 0xC0 ) != 0x80 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tlargeCh = ( ( firstChar & 0x1F ) << 6 ) | \\\n\t\t\t\t\t( secondChar & 0x3F );\n\t\tif( largeCh < 0x80 || largeCh > 0x7FF )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\treturn( largeCh & 0x7FF );\n\t\t}\n\n\t/* Process any further characters */\n\tif( ( firstChar & 0xF0 ) == 0xE0 )\t\t/* 1111xxxx -> 1110xxxx */\n\t\t{\n\t\tint thirdChar;\n\t\t\n\t\tstatus = thirdChar = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* 3-byte character in the range 0x800...0xFFFF */\n\t\tif( ( secondChar & 0xC0 ) != 0x80 || \\\n\t\t\t( thirdChar & 0xC0 ) != 0x80 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tlargeCh = ( ( firstChar & 0x1F ) << 12 ) | \\\n\t\t\t\t  ( ( secondChar & 0x3F ) << 6 ) | \\\n\t\t\t\t\t( thirdChar & 0x3F );\n\t\tif( largeCh < 0x800 || largeCh > 0xFFFF )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\treturn( largeCh & 0xFFFF );\n\t\t}\n\n\t/* In theory we can also get 4- and 5-byte encodings but this is far \n\t   more likely to be invalid data than a genuine attempt to represent \n\t   something in Tsolyani */\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n\n#if 0\t/* Not currently used, see note at start */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int putUtf8Char( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_RANGE( 0, 0xFFFF ) const long largeCh )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( largeCh >= 0 && largeCh <= 0xFFFF );\n\n\tif( largeCh < 0x80 )\n\t\treturn( sputc( stream, ( BYTE ) largeCh ) );\n\tif( largeCh < 0x0800 )\n\t\t{\n\t\tsputc( stream, ( BYTE )( 0xC0 | ( ( largeCh >> 6 ) & 0x1F ) ) );\n\t\treturn( sputc( stream, ( BYTE )( 0x80 | ( largeCh & 0x3F ) ) ) );\n\t\t}\n\tsputc( stream, ( BYTE )( 0xE0 | ( ( largeCh >> 12 ) & 0x0F ) ) );\n\tsputc( stream, ( BYTE )( 0x80 | ( ( largeCh >> 6 ) & 0x3F ) ) );\n\treturn( sputc( stream, ( BYTE )( 0x80 | largeCh & 0x3F ) ) );\n\t}\n\n/* Determine the length of a string once it's encoded as UTF-8 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int utf8TargetStringLen( IN_BUFFER( stringLen ) const void *string, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *targetStringLength,\n\t\t\t\t\t\t\t\tconst BOOLEAN isWideChar )\n\t{\n\tSTREAM stream;\n\tint i, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\tassert( isWritePtr( targetStringLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( stringLen ) );\n\tREQUIRES( isWideChar == TRUE || isWideChar == FALSE );\n\n\t/* Clear return value */\n\t*targetStringLength = 0;\n\n\tsMemNullOpen( &stream );\n\tif( isWideChar )\n\t\t{\n\t\tconst wchar_t *wcStrPtr = ( wchar_t * ) string;\n\t\tconst int wcStrLen = stringLen / WCSIZE;\n\n\t\tREQUIRES( stringLen % WCSIZE == 0 );\n\n\t\tLOOP_LARGE( i = 0, i < wcStrLen, i++ )\n\t\t\t{\n\t\t\tstatus = putUtf8Char( &stream, wcStrPtr[ i ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\telse\n\t\t{\n\t\tconst BYTE *strPtr = string;\n\n\t\tLOOP_LARGE( i = 0, i < stringLen, i++ )\n\t\t\t{\n\t\t\tstatus = putUtf8Char( &stream, strPtr[ i ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*targetStringLength = stell( &stream );\n\tsMemClose( &stream );\n\n\treturn( status );\n\t}\n#endif /* 0 */\n\n/* Check that a UTF-8 string has a valid encoding */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkUtf8String( IN_BUFFER( stringLen ) const void *string, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int stringLen )\n\t{\n\tSTREAM stream;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( stringLen ) );\n\n\t/* Scan the string making sure that there are no malformed characters */\n\tsMemConnect( &stream, string, stringLen );\n\tLOOP_LARGE_CHECK( stell( &stream ) < stringLen )\n\t\t{\n\t\tconst long longStatus = getUTF8Char( &stream );\n\t\tif( cryptStatusError( longStatus ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Convert a UTF-8 string to ASCII, 8859-1, or Unicode, and vice versa */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int copyFromUtf8String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( destMaxLen ) \\\n\t\t\t\t\t\t\t\t\tint *destLen, \n\t\t\t\t\t\t\t   OUT_RANGE( 0, 20 ) int *destStringType,\n\t\t\t\t\t\t\t   IN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int sourceLen )\n\t{\n\tSTREAM stream;\n\tASN1_STRINGTYPE stringType = STRINGTYPE_PRINTABLE;\n\twchar_t *wcDestPtr = dest;\n\tBYTE *destPtr = dest;\n\tint noChars = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( isWritePtr( destStringType, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( source, sourceLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( destMaxLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( sourceLen ) );\n\n\t/* Clear return value */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\t*destStringType = STRINGTYPE_NONE;\n\n\t/* Scan the string to determine its length and the widest character type \n\t   in it.  We have to process the entire string even if we've already \n\t   identified it as containing the widest string type (Unicode) in order \n\t   to check for malformed characters.  In addition we can't combine this \n\t   with the copy loop that follows because until we get to the end we \n\t   don't know whether we're copying 8-bit or wide characters */\n\tsMemConnect( &stream, source, sourceLen );\n\tLOOP_LARGE_CHECK( stell( &stream ) < sourceLen )\n\t\t{\n\t\tconst long largeCh = getUTF8Char( &stream );\n\t\tif( cryptStatusError( largeCh ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( ( int ) largeCh );\n\t\t\t}\n\t\tnoChars++;\n\n\t\t/* If we've already identified the widest character type then \n\t\t   there's nothing more to do */\n\t\tif( stringType == STRINGTYPE_UNICODE )\n\t\t\tcontinue;\n\n\t\t/* If it's not an 8-bit value then it can only be Unicode */\n\t\tif( largeCh > 0xFF )\n\t\t\t{\n\t\t\tstringType = STRINGTYPE_UNICODE;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If it's not a PrintableString character mark it as T61 if it's \n\t\t   within range, otherwise it's Unicode */\n\t\tif( largeCh >= 128 )\n\t\t\t{\n\t\t\tstringType = ( asn1CharFlags[ largeCh & 0x7F ] & P ) ? \\\n\t\t\t\t\t\t STRINGTYPE_T61 : STRINGTYPE_UNICODE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\t/* Make sure that the translated string will fit into the destination \n\t   buffer */\n\t*destLen = noChars * ( ( stringType == STRINGTYPE_UNICODE ) ? \\\n\t\t\t\t\t\t   WCSIZE : 1 );\n\tif( *destLen < 0 || *destLen > destMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t*destStringType = stringType;\n\n\t/* Perform a second pass copying the string over */\n\tsMemConnect( &stream, source, sourceLen );\n\tLOOP_LARGE_CHECK( stell( &stream ) < sourceLen )\n\t\t{\n\t\tconst long largeCh = getUTF8Char( &stream );\n\n\t\tENSURES( !cryptStatusError( largeCh ) );\n\n\t\t/* Copy the result as a Unicode or ASCII/8859-1 character */\n\t\tif( stringType == STRINGTYPE_UNICODE )\n\t\t\t*wcDestPtr++ = ( wchar_t ) largeCh;\n\t\telse\n\t\t\t*destPtr++ = ( BYTE ) largeCh;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\t/* Currently unused, see note at start */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int copyToUtf8String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen,\n\t\t\t\t\t\t\t IN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int sourceLen,\n\t\t\t\t\t\t\t const BOOLEAN isWideChar )\n\t{\n\tSTREAM stream;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( source, sourceLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( destMaxLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( sourceLen ) );\n\tREQUIRES( isWideChar == TRUE || isWideChar == FALSE );\n\n\t/* Clear return value */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\n\tsMemOpen( &stream, dest, destMaxLen );\n\tif( isWideChar )\n\t\t{\n\t\tconst wchar_t *wcStrPtr = ( wchar_t * ) string;\n\t\tconst int wcStrLen = stringLen / WCSIZE;\n\n\t\tREQUIRES( stringLen % WCSIZE == 0 );\n\n\t\tLOOP_LARGE( i = 0, i < wcStrLen, i++ )\n\t\t\t{\n\t\t\tif( wcStrPtr[ i ] < 0 || wcStrPtr[ i ] > 0xFFFF )\n\t\t\t\t{\n\t\t\t\t/* Safety check for WCSIZE > 2 */\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tstatus = putUtf8Char( &stream, wcStrPtr[ i ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\telse\n\t\t{\n\t\tLOOP_LARGE( i = 0, i < strinLen, i++ )\n\t\t\t{\n\t\t\tstatus = putUtf8Char( &stream, string[ i ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*destLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tString-type Identification Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and guess whether a native string is a widechar string */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isNativeWidecharString( IN_BUFFER( stringLen ) const BYTE *string, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 2 ) const int stringLen )\n\t{\n\twchar_t wCh;\n#if WCHAR_MAX <= 0xFFFF\n\tint hiByte = 0, i, LOOP_ITERATOR;\n#endif /* 16-bit wchar_t */\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES_B( stringLen >= WCSIZE && stringLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES_B( !( stringLen % WCSIZE ) );\n\n\t/* Look at the first character in the string */\n\twCh = getNativeWidechar( string );\n\n\t/* If wchar_t is > 16 bits and the bits above 16 are set or all zero,\n\t   it's either definitely not Unicode or Unicode.  Note that some\n\t   compilers will complain of unreachable code here, unfortunately we\n\t   can't easily fix this since WCSIZE is usually an expression involving\n\t   sizeof() which can't be handled via the preprocessor so we have to\n\t   guard it with a preprocessor check */\n#if WCHAR_MAX > 0xFFFF\n\treturn( ( wCh > 0xFFFF ) ? FALSE : TRUE );\n#else\n\t/* wchar_t is 16 bits, make sure that we don't get false positives with \n\t   short strings.  Two-character strings are more likely to be ASCII \n\t   than a single widechar, and repeated alternate characters (e.g. \n\t   \"tanaka\") in an ASCII string appear to be widechars for the general-\n\t   purpose check below so we check for these in strings of 2-3 wide \n\t   characters before we perform the general-purpose check */\n\tif( stringLen <= ( WCSIZE * 3 ) && wCh > 0xFF )\n\t\t{\n\t\tif( stringLen == WCSIZE )\n\t\t\t{\n\t\t\tconst int ch1 = string[ 0 ];\n\t\t\tconst int ch2 = string[ 1 ];\n\n\t\t\t/* Check for a two-character ASCII string, usually a country \n\t\t\t   name */\n\t\t\tif( isValidTextChar( ch1 ) && isValidTextChar( ch2 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint hi1, hi2, hi3;\n\n\t\t\tENSURES_B( stringLen == ( WCSIZE * 2 ) || \\\n\t\t\t\t\t   stringLen == ( WCSIZE * 3 ) );\n\n\t\t\t/* Check for alternate characters being ASCII */\n\t\t\thi1 = hi3 = byteToInt( wCh >> 8 );\n\t\t\thi2 = byteToInt( getNativeWidechar( string + WCSIZE ) >> 8 );\n\t\t\tif( stringLen > WCSIZE * 2 )\n\t\t\t\thi3 = byteToInt( getNativeWidechar( string + ( WCSIZE * 2 ) ) >> 8 );\n\t\t\tif( isAlnum( hi1 ) && isAlnum( hi2 ) && isAlnum( hi3 ) && \\\n\t\t\t\thi1 == hi2 && hi2 == hi3 )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* wchar_t is 16 bits, check whether it's in the form { 00 xx }* or\n\t   { AA|00 xx }*, either ASCII-as-Unicode or Unicode.  The code used \n\t   below is safe because to get to this point the string has to be some \n\t   multiple of 2 bytes long.  Note that if someone passes in a 1-byte \n\t   string and mistakenly includes the terminator in the length it'll be \n\t   identified as a 16-bit widechar string but this doesn't really matter \n\t   since it'll get \"converted\" into a non-widechar string later */\n\tLOOP_LARGE( i = 0, i < stringLen, i += WCSIZE )\n\t\t{\n\t\twCh = getNativeWidechar( &string[ i ] );\n\t\tif( wCh > 0xFF )\n\t\t\t{\n\t\t\tconst int wChHi = byteToInt( wCh >> 8 );\n\n\t\t\tENSURES_B( wChHi );\n\n\t\t\t/* If we haven't already seen a high byte, remember it */\n\t\t\tif( hiByte == 0 )\n\t\t\t\thiByte = wChHi;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If the current high byte doesn't match the previous one,\n\t\t\t\t   it's probably 8-bit characters */\n\t\t\t\tif( wChHi != hiByte )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\t\t\t\t/* Probably 16-bit characters */\n#endif /* 32- vs 16-bit wchar_t */ \n\t}\n\n/* Try and figure out the true string type for an ASN.1-encoded or native \n   string.  This detects (or at least tries to detect) not only the basic \n   string type but also basic string types encoded as widechar strings and \n   widechar strings encoded as basic string types.\n\n   All of these functions work by checking for the most restrictive ASN.1\n   string subset that'll still contain the string, progressively widening\n   from PrintableString -> IA5String -> T61(8859-1)String -> \n   BMP(Unicode)String, reporting an error if even a Unicode string can't\n   contain the value.  Note that we continue processing the string even\n   when we've reached the least-constraining value (Unicode) because we\n   still need to check whether all of the characters in the string are\n   actually valid before we exit */\n\nCHECK_RETVAL_ENUM( STRINGTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ASN1_STRINGTYPE get8bitStringType( IN_BUFFER( stringLen ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst BYTE *string,\n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t\t\t\t\t\t  IN_TAG_ENCODED const int stringTag )\n\t{\n\tBOOLEAN isIA5 = FALSE, isT61 = FALSE;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( stringLen ), \\\n\t\t\t\t  STRINGTYPE_ERROR );\n\tREQUIRES_EXT( ( stringTag >= BER_STRING_UTF8 && \\\n\t\t\t\t\tstringTag < BER_STRING_BMP ), \n\t\t\t\t  STRINGTYPE_ERROR );\n\n\t/* Walk down the string checking each character */\n\tLOOP_LARGE( i = 0, i < stringLen, i++ )\n\t\t{\n\t\tconst BYTE ch = string[ i ];\n\n\t\t/* If the high bit is set then it's not an ASCII subset */\n\t\tif( ch >= 128 )\n\t\t\t{\n\t\t\tisT61 = TRUE;\n\t\t\tif( asn1CharFlags[ ch & 0x7F ] )\n\t\t\t\tcontinue;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Check whether it's a PrintableString */\n\t\t\tif( !( asn1CharFlags[ ch ] & P ) )\n\t\t\t\tisIA5 = TRUE;\n\n\t\t\t/* Check whether it's something peculiar */\n\t\t\tif( asn1CharFlags[ ch ] )\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* It's not 8859-1 either, check whether it's UTF-8 if this is \n\t\t   permitted.  We can safely do an early-out in this case because \n\t\t   checkUtf8String() checks the entire string */\n\t\tif( stringTag == BER_STRING_UTF8 && \\\n\t\t\tcryptStatusOK( checkUtf8String( string, stringLen ) ) )\n\t\t\treturn( STRINGTYPE_UTF8 );\n\n\t\t/* This may be some native 8-bit string type that can be converted \n\t\t   to Unicode, tell the caller to try this before reporting an \n\t\t   error */\n\t\treturn( STRINGTYPE_ERROR_TRY_UNICODE );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, STRINGTYPE_ERROR );\n\n\treturn( isT61 ? STRINGTYPE_T61 : \\\n\t\t\tisIA5 ? STRINGTYPE_IA5 : \\\n\t\t\t\t\tSTRINGTYPE_PRINTABLE );\n\t}\n\nCHECK_RETVAL_ENUM( STRINGTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ASN1_STRINGTYPE getAsn1StringType( IN_BUFFER( stringLen ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst BYTE *string, \n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int stringLen, \n\t\t\t\t\t\t\t\t\t\t  IN_TAG_ENCODED const int stringTag )\n\t{\n\tSTREAM stream;\n\tBOOLEAN isIA5 = FALSE, isT61 = FALSE, isUnicode = FALSE;\n\tint length, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( stringLen ), \\\n\t\t\t\t  STRINGTYPE_ERROR );\n\tREQUIRES_EXT( ( stringTag >= BER_STRING_UTF8 && \\\n\t\t\t\t\tstringTag <= BER_STRING_BMP ), \n\t\t\t\t  STRINGTYPE_ERROR );\n\n\t/* If it's not a Unicode string, determine the 8-bit string type */\n\tif( stringTag != BER_STRING_BMP )\n\t\t{\n\t\tconst ASN1_STRINGTYPE stringType = \\\n\t\t\t\t\t\tget8bitStringType( string, stringLen, stringTag );\n\n\t\treturn( isErrorStringType( stringType ) ? \\\n\t\t\t\tSTRINGTYPE_ERROR : stringType );\n\t\t}\n\n\t/* If it's not a multiple of bmpchar_t in size then it can't really be \n\t   Unicode either */\n\tif( stringLen % UCSIZE )\n\t\treturn( STRINGTYPE_ERROR );\n\n\t/* If the first character isn't a null then it's definitely a Unicode\n\t   string.  These strings are always big-endian, even coming from \n\t   Microsoft software, so we don't have to check for a null as the \n\t   second character */\n\tif( string[ 0 ] != '\\0' )\n\t\treturn( STRINGTYPE_UNICODE );\n\n\t/* Check whether it's an 8-bit string encoded as a BMPString */\n\tsMemConnect( &stream, string, stringLen );\n\tLOOP_LARGE( length = 0, length < stringLen, length += UCSIZE )\n\t\t{\n\t\tint ch;\n\t\t\n\t\tstatus = ch = readUint16( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( STRINGTYPE_ERROR );\n\t\t\t}\n\n\t\t/* If it's not an 8-bit value then it's a pure Unicode string */\n\t\tif( ch > 0xFF )\n\t\t\t{\n\t\t\tisUnicode = TRUE;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If the high bit is set then it's not an ASCII subset */\n\t\tif( ch >= 0x80 )\n\t\t\t{\n\t\t\tisT61 = TRUE;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check whether it's a PrintableString */\n\t\tif( !( asn1CharFlags[ ch ] & P ) )\n\t\t\tisIA5 = TRUE;\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, STRINGTYPE_ERROR );\n\tsMemDisconnect( &stream );\n\n\treturn( isUnicode ? STRINGTYPE_UNICODE : \\\n\t\t\tisT61 ? STRINGTYPE_UNICODE_T61 : \\\n\t\t\tisIA5 ? STRINGTYPE_UNICODE_IA5 : \\\n\t\t\t\t\tSTRINGTYPE_UNICODE_PRINTABLE );\n\t}\n\nCHECK_RETVAL_ENUM( STRINGTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ASN1_STRINGTYPE getNativeStringType( IN_BUFFER( stringLen ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst BYTE *string, \n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int stringLen )\n\t{\n\tBOOLEAN isIA5 = FALSE, isT61 = FALSE, isUnicode = FALSE;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( stringLen ), \\\n\t\t\t\t  STRINGTYPE_ERROR );\n\n\t/* If it's not a widechar string, handle it as a basic 8-bit string \n\t   type.  By default we pass in 8859-1 as the most permissible allowed \n\t   string type, making it UTF-8 is rather risky because we don't know \n\t   whether the environment really does support this natively or whether \n\t   we've been passed garbage, so we only enable it for Unix systems, \n\t   which are likely to be using UTF8 */\n\tif( stringLen < WCSIZE || ( stringLen % WCSIZE ) != 0 || \\\n\t\t!isNativeWidecharString( string, stringLen ) )\n\t\t{\n#if defined( __UNIX__ )\n\t\treturn( get8bitStringType( string, stringLen, BER_STRING_UTF8 ) );\n#else\n\t\treturn( get8bitStringType( string, stringLen, BER_STRING_T61 ) );\n#endif /* __UNIX__ */\n\t\t}\n\n\t/* It's a widechar string, although it may actually be something else \n\t   that's been bloated out into widechars so we check for this as well */\n\tLOOP_LARGE( i = 0, i < stringLen, i += WCSIZE )\n\t\t{\n\t\tconst wchar_t wCh = getNativeWidechar( &string[ i ] );\n\n\t\t/* Make sure that we've got a character from a Unicode (BMP) string.  \n\t\t   This check can be triggered if WCSIZE > 2 and the caller feeds us \n\t\t   a binary garbage string so that the resulting decoded widechar \n\t\t   value is larger than 16 bits */\n\t\tif( wCh < 0 || ( wCh & 0xFFFF8000L ) )\n\t\t\treturn( STRINGTYPE_ERROR );\n\n\t\t/* If the high bit is set then it's not an ASCII subset */\n\t\tif( wCh >= 0x80 )\n\t\t\t{\n\t\t\t/* If it's larger than 8 bits then it's definitely Unicode */\n\t\t\tif( wCh >= 0xFF )\n\t\t\t\t{\n\t\t\t\tisUnicode = TRUE;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* Check which (if any) 8-bit type it could be */\n\t\t\tisT61 = TRUE;\n\t\t\tif( nativeCharFlags[ wCh & 0x7F ] )\n\t\t\t\tcontinue;\n\n\t\t\t/* It's not 8859-1 either, or more specifically it's something \n\t\t\t   that ends up looking like a control character.  What to do at \n\t\t\t   this point is a bit uncertain but making it a generic Unicode \n\t\t\t   string which'll be handled via somewhat more robust \n\t\t\t   mechanisms than something presumed to be ASCII or close to it \n\t\t\t   is probably safer than storing it as a what's probably a \n\t\t\t   control character */\n\t\t\tisUnicode = TRUE;\n\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check whether it's a PrintableString */\n\t\tif( !( nativeCharFlags[ wCh ] & P ) )\n\t\t\tisIA5 = TRUE;\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, STRINGTYPE_ERROR );\n\n\treturn( isUnicode ? STRINGTYPE_UNICODE : \\\n\t\t\tisT61 ? STRINGTYPE_UNICODE_T61 : \\\n\t\t\tisIA5 ? STRINGTYPE_UNICODE_IA5 : \\\n\t\t\t\t\tSTRINGTYPE_UNICODE_PRINTABLE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tASN.1 String Conversion Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that a text string contains valid characters for its string type.\n   This is used in non-DN strings where we can't vary the string type based \n   on the characters being used */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkTextStringData( IN_BUFFER( stringLen ) const char *string, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t\t\t const BOOLEAN isPrintableString )\n\t{\n\tconst int charTypeMask = isPrintableString ? P : I;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( stringLen ) );\n\tREQUIRES( isPrintableString == TRUE || isPrintableString == FALSE );\n\n\tLOOP_LARGE( i = 0, i < stringLen, i++ )\n\t\t{\n\t\tconst int ch = byteToInt( string[ i ] );\n\n\t\tif( !isValidTextChar( ch ) )\n\t\t\treturn( FALSE );\n\t\tif( !( nativeCharFlags[ ch ] & charTypeMask ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Convert a character string from the format used in certificates into the \n   native format */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nint copyFromAsn1String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen, \n\t\t\t\t\t\tOUT_RANGE( 0, 20 ) int *destStringType,\n\t\t\t\t\t\tIN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int sourceLen,\n\t\t\t\t\t\tIN_TAG_ENCODED const int stringTag )\n\t{\n\tSTREAM stream;\n\tconst ASN1_STRINGTYPE stringType = \\\n\t\t\t\t\tgetAsn1StringType( source, sourceLen, stringTag );\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( isWritePtr( destStringType, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( source, sourceLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( destMaxLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( sourceLen ) );\n\tREQUIRES( stringTag >= BER_STRING_UTF8 && stringTag <= BER_STRING_BMP );\n\n\t/* Clear return values */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\t*destStringType = STRINGTYPE_NONE;\n\n\t/* Make sure that the string type can be determined */\n\tif( stringType <= STRINGTYPE_NONE || stringType >= STRINGTYPE_ERROR )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If it's a BMP or UTF-8 string convert it to the native format */\n\tif( stringType == STRINGTYPE_UNICODE )\n\t\t{\n\t\twchar_t *wcDestPtr = ( wchar_t * ) dest;\n\t\tconst int newLen = ( sourceLen / UCSIZE ) * WCSIZE;\n\n\t\tif( newLen <= 0 || newLen > destMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\n\t\tsMemConnect( &stream, source, sourceLen );\n\t\tLOOP_LARGE_CHECK( stell( &stream ) < sourceLen )\n\t\t\t{\n\t\t\tint wCh;\n\t\t\t\n\t\t\tstatus = wCh = readUint16( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t*wcDestPtr++ = ( wchar_t ) wCh;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tsMemDisconnect( &stream );\n\t\t*destLen = newLen;\n\t\t*destStringType = STRINGTYPE_UNICODE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( stringTag == BER_STRING_UTF8 )\n\t\t{\n\t\treturn( copyFromUtf8String( dest, destMaxLen, destLen, \n\t\t\t\t\t\t\t\t\tdestStringType, source, sourceLen ) );\n\t\t}\n\n\t/* If it's something masquerading as Unicode, convert it to the narrower \n\t   format */\n\tif( stringType == STRINGTYPE_UNICODE_PRINTABLE || \\\n\t\tstringType == STRINGTYPE_UNICODE_IA5 || \\\n\t\tstringType == STRINGTYPE_UNICODE_T61 )\n\t\t{\n\t\tBYTE *destPtr = dest;\n\t\tconst int newLen = sourceLen / UCSIZE;\n\n\t\tif( newLen <= 0 || newLen > destMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\tsMemConnect( &stream, source, sourceLen );\n\t\tLOOP_LARGE_CHECK( stell( &stream ) < sourceLen )\n\t\t\t{\n\t\t\tint wCh;\n\t\t\t\n\t\t\tstatus = wCh = readUint16( &stream );\n\t\t\tif( !cryptStatusError( status ) && ( wCh > 0xFF ) )\n\t\t\t\t{\n\t\t\t\t/* Should never happen because of the pre-scan that we've \n\t\t\t\t   done earlier */\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t*destPtr++ = intToByte( wCh );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tsMemDisconnect( &stream );\n\t\t*destLen = newLen;\n\t\t*destStringType = ( stringType == STRINGTYPE_UNICODE_PRINTABLE ) ? \\\n\t\t\t\t\t\t\tSTRINGTYPE_PRINTABLE : \\\n\t\t\t\t\t\t  ( stringType == STRINGTYPE_UNICODE_IA5 ) ? \\\n\t\t\t\t\t\t\tSTRINGTYPE_IA5 : STRINGTYPE_T61;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's an 8-bit character set, just copy it across */\n\tif( sourceLen <= 0 || sourceLen > destMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tREQUIRES( rangeCheck( sourceLen, 1, destMaxLen ) );\n\tmemcpy( dest, source, sourceLen );\n\t*destLen = sourceLen;\n\t*destStringType = stringType;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Convert a character string from the native format to the format used in \n   certificates.  The 'stringType' value doesn't have any meaning outside\n   this module, it's merely used as a cookie to pass back to other functions \n   here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nint getAsn1StringInfo( IN_BUFFER( stringLen ) const void *string, \n\t\t\t\t\t   IN_LENGTH_SHORT const int stringLen,\n\t\t\t\t\t   OUT_RANGE( 0, 20 ) int *stringType, \n\t\t\t\t\t   OUT_TAG_ENCODED_Z int *asn1StringType,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *asn1StringLen,\n\t\t\t\t\t   const BOOLEAN isNativeString )\n\t{\n\tconst ASN1_STRINGTYPE localStringType = \\\n\t\t\t\t\t\t\tgetNativeStringType( string, stringLen );\n\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\tassert( isWritePtr( stringType, sizeof( int ) ) );\n\tassert( isWritePtr( asn1StringType, sizeof( int ) ) );\n\tassert( isWritePtr( asn1StringLen, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( stringLen ) );\n\tREQUIRES( isNativeString == TRUE || isNativeString == FALSE );\n\n\t/* Clear return value */\n\t*asn1StringLen = 0;\n\t*asn1StringType = 0;\n\n\t/* Make sure that the string type can be determined */\n\tif( localStringType <= STRINGTYPE_NONE || \\\n\t\tlocalStringType >= STRINGTYPE_ERROR )\n\t\t{\n\t\tsize_t mbStringLen;\n\t\tint result;\n\n\t\t/* If it's not a native string or we're not being told to try re-\n\t\t   encoding as Unicode, report an error */\n\t\tif( !isNativeString || \\\n\t\t\tlocalStringType != STRINGTYPE_ERROR_TRY_UNICODE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\n\t\t/* This may be some oddball 8-bit local character type that can be \n\t\t   converted into Unicode, check whether this is the case */\n\t\tresult = mbstowcs_s( &mbStringLen, NULL, 0, string, stringLen );\n\t\tif( result != 0 || mbStringLen <= 0 || mbStringLen > stringLen )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* It's a valid native 8-bit character string, report it as \n\t\t   something that needs to be converted to Unicode */\n\t\t*stringType = STRINGTYPE_TO_UNICODE;\n\t\t*asn1StringLen = mbStringLen * UCSIZE;\n\t\t*asn1StringType = BER_STRING_BMP;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t*stringType = localStringType;\n\tswitch( localStringType )\n\t\t{\n\t\tcase STRINGTYPE_UNICODE:\n\t\t\t/* It's a native widechar string, the output is Unicode \n\t\t\t   (BMPString) */\n\t\t\t*asn1StringLen = ( stringLen / WCSIZE ) * UCSIZE;\n\t\t\t*asn1StringType = BER_STRING_BMP;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase STRINGTYPE_UNICODE_PRINTABLE:\n\t\tcase STRINGTYPE_UNICODE_IA5:\n\t\tcase STRINGTYPE_UNICODE_T61:\n\t\t\t/* It's an ASCII string masquerading as a native widechar \n\t\t\t   string, output is an 8-bit string type */\n\t\t\t*asn1StringLen = stringLen / WCSIZE;\n\t\t\t*asn1StringType = \\\n\t\t\t\t\t( localStringType == STRINGTYPE_UNICODE_PRINTABLE ) ? \\\n\t\t\t\t\t\tBER_STRING_PRINTABLE : \\\n\t\t\t\t\t( localStringType == STRINGTYPE_UNICODE_IA5 ) ? \\\n\t\t\t\t\t\tBER_STRING_IA5 : BER_STRING_T61;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase STRINGTYPE_UTF8:\n#if 0\n\t\t\t/* It's a native widechar string encoded as UTF-8, the output is \n\t\t\t   a variable-length UTF-8 string */\n\t\t\tstatus = utf8TargetStringLen( string, stringLen, asn1StringLen,\n\t\t\t\t\t\t( localStringType == STRINGTYPE_UNICODE || \\\n\t\t\t\t\t\t  localStringType == STRINGTYPE_UNICODE_PRINTABLE || \\\n\t\t\t\t\t\t  localStringType == STRINGTYPE_UNICODE_IA5 || \\\n\t\t\t\t\t\t  localStringType == STRINGTYPE_UNICODE_T61 ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n#else\n\t\t\t/* It's an already-encoded UTF8 string (getNativeStringType() \n\t\t\t   has already checked its validity) */\n\t\t\t*asn1StringLen = stringLen;\n#endif /* 0 */\n\t\t\t*asn1StringType = BER_STRING_UTF8;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If nothing specialised matches then the default string type is an \n\t   ASCII or T61/latin1 string */\n\t*asn1StringLen = stringLen;\n\t*asn1StringType = ( localStringType == STRINGTYPE_PRINTABLE ) ? \\\n\t\t\t\t\t\tBER_STRING_PRINTABLE : \\\n\t\t\t\t\t  ( localStringType == STRINGTYPE_IA5 ) ? \\\n\t\t\t\t\t\tBER_STRING_IA5 : BER_STRING_T61;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint copyToAsn1String( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t\t  IN_LENGTH_SHORT const int destMaxLen, \n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen, \n\t\t\t\t\t  IN_BUFFER( sourceLen ) const void *source, \n\t\t\t\t\t  IN_LENGTH_SHORT const int sourceLen,\n\t\t\t\t\t  IN_RANGE( 1, 20 ) const int stringType )\n\t{\n\tSTREAM stream;\n\tconst BYTE *srcPtr = source;\n\tconst BOOLEAN unicodeTarget = ( stringType == STRINGTYPE_UNICODE ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( source, sourceLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( destMaxLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( sourceLen ) );\n\tREQUIRES( isEnumRange( stringType, STRINGTYPE ) && \\\n\t\t\t  stringType != STRINGTYPE_ERROR );\n\n\t/* Clear return value */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\n\t/* If it's a non-widechar string then we can just copy it across \n\t   directly */\n\tif( stringType != STRINGTYPE_UNICODE && \\\n\t\tstringType != STRINGTYPE_UNICODE_PRINTABLE && \\\n\t\tstringType != STRINGTYPE_UNICODE_IA5 && \\\n\t\tstringType != STRINGTYPE_UNICODE_T61 && \\\n\t\tstringType != STRINGTYPE_TO_UNICODE )\n\t\t{\n\t\tif( sourceLen > destMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tREQUIRES( rangeCheck( sourceLen, 1, destMaxLen ) );\n\t\tmemcpy( dest, source, sourceLen );\n\t\t*destLen = sourceLen;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's some oddball native 8-bit string type, convert it to \n\t   Unicode */\n\tif( stringType == STRINGTYPE_TO_UNICODE )\n\t\t{\n\t\tmbstate_t mbState;\n\t\tint count = 0;\n\n\t\tmemset( &mbState, 0, sizeof( mbstate_t  ) );\n  \n\t\t/* Copy the characters across, converting to bmpchar_t as we go.\n\t\t   In commemoration of classic non-thread-safe functions like\n\t\t   strtok(), the C99 standards committee also made the standard \n\t\t   mbtowc() non-thread-safe by allowing it to be called with a \n\t\t   null second argument to initialise the internal shift state for \n\t\t   state-dependent encodings, we use mbrtowc() to deal with this */\n\t\tsMemOpen( &stream, dest, destMaxLen );\n\t\tLOOP_LARGE( ( status = CRYPT_OK, i = 0 ),\n\t\t\t\t\tcryptStatusOK( status ) && i < sourceLen,\n\t\t\t\t\ti += count )\n\t\t\t{\n\t\t\twchar_t wCh;\n\n\t\t\tcount = mbrtowc( &wCh, srcPtr + i, sourceLen - i, &mbState );\n\t\t\tif( count <= 0 )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\telse\n\t\t\t\tstatus = writeUint16( &stream, wCh );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*destLen = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( status );\n\t\t}\n\n\t/* It's a native widechar string, copy it across converting from wchar_t \n\t   to bmpchar_t/char as required */\n\tsMemOpen( &stream, dest, destMaxLen );\n\tLOOP_LARGE( ( status = CRYPT_OK, i = 0 ),\n\t\t\t\tcryptStatusOK( status ) && i < sourceLen,\n\t\t\t\ti += WCSIZE )\n\t\t{\n\t\tconst wchar_t wCh = getNativeWidechar( &srcPtr[ i ] );\n\t\tif( unicodeTarget )\n\t\t\tstatus = writeUint16( &stream, wCh );\n\t\telse\n\t\t\tstatus = sputc( &stream, intToByte( wCh ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) )\n\t\t*destLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Attribute Management Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/* Special ATTRIBUTE_LIST values to indicate that an attribute field is a \n   blob attribute, a default-value field, or a complete attribute, see the \n   long comment for findAttributeFieldEx() for a detailed description */\n\n#define ATTR_BLOB_ATTR\t\t{ ( CRYPT_ATTRIBUTE_TYPE ) 0, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) 0, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) 0 }\n#define ATTR_COMPLETE_ATTR\t{ ( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) 0, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) 0 }\n#define ATTR_DEFAULT_FIELD\t{ ( CRYPT_ATTRIBUTE_TYPE ) 0, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR, \\\n\t\t\t\t\t\t\t  ( CRYPT_ATTRIBUTE_TYPE ) 0 }\n\nstatic const ATTRIBUTE_LIST blobAttributeData = ATTR_BLOB_ATTR;\nstatic const ATTRIBUTE_LIST completeAttributeData = ATTR_COMPLETE_ATTR;\nstatic const ATTRIBUTE_LIST defaultFieldData = ATTR_DEFAULT_FIELD;\nstatic DATAPTR_ATTRIBUTE defaultFieldAttribute, completeAttribute;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check attribute data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckAttributePtr( IN const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\t/* There are three special ATTRIBUTE_LIST values that denote special-\n\t   case attribute types rather than normal attributes, so a sanity check\n\t   on them will always fail.  To deal with this we detect when we've \n\t   been passed these and don't perform any further checks */\n\tif( attributeListPtr == &blobAttributeData || \\\n\t\tattributeListPtr == &completeAttributeData || \\\n\t\tattributeListPtr == &defaultFieldData )\n\t\treturn( TRUE );\n\n\t/* If it's a blob-type attribute then none of the usual values are set.\n\t   We don't use isValidAttributeField(), used elsewhere to check for \n\t   blob-type attributes, for this check because that only checks the \n\t   attributeID, and we want a (fairly) definite match for a blob-type\n\t   attribute before we assume that it really is one */\n\tif( attributeListPtr->attributeID == CRYPT_ATTRIBUTE_NONE && \\\n\t\tattributeListPtr->fieldID == CRYPT_ATTRIBUTE_NONE && \\\n\t\tattributeListPtr->subFieldID == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\t/* Make sure that various fields are set/not set as required */\n\t\tif( attributeListPtr->oid == NULL || \\\n\t\t\tattributeListPtr->encodedSize != 0 || \\\n\t\t\tattributeListPtr->fieldType != 0 || \\\n\t\t\tTEST_FLAG( attributeListPtr->flags,\n\t\t\t\t\t   ~( ATTR_FLAG_IGNORED | ATTR_FLAG_CRITICAL ) ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckAttribute: Blob general information\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !DATAPTR_ISVALID( attributeListPtr->prev ) || \\\n\t\t\t!DATAPTR_ISVALID( attributeListPtr->next ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Blob prev/next links\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check general attribute data */\n\tif( !isValidExtension( attributeListPtr->attributeID ) || \\\n\t\t!isValidExtension( attributeListPtr->fieldID ) || \\\n\t\t( attributeListPtr->subFieldID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t  !isValidExtension( attributeListPtr->subFieldID ) && \\\n\t\t  !isGeneralNameComponent( attributeListPtr->subFieldID ) && \\\n\t\t  !isDNComponent( attributeListPtr->subFieldID ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttribute: Attribute/field/subfield ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isShortIntegerRange( attributeListPtr->encodedSize ) || \\\n\t\tattributeListPtr->fieldType < FIELDTYPE_LAST || \\\n\t\tattributeListPtr->fieldType > 0xFF || \\\n\t\t!CHECK_FLAGS( attributeListPtr->flags, ATTR_FLAG_NONE, \n\t\t\t\t\t  ATTR_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttribute: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( attributeListPtr->prev ) || \\\n\t\t!DATAPTR_ISVALID( attributeListPtr->next ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Prev/next links\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check encoding info */\n\tif( attributeListPtr->fifoEnd < 0 || \\\n\t\tattributeListPtr->fifoEnd > ENCODING_FIFO_SIZE - 1 || \\\n\t\tattributeListPtr->fifoPos < 0 || \\\n\t\tattributeListPtr->fifoPos > attributeListPtr->fifoEnd )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttribute: Encoding FIFO info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN sanityCheckAttribute( IN const DATAPTR_ATTRIBUTE attribute )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\t/* Check the basic data pointer */\n\tif( !DATAPTR_ISSET( attribute ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttribute: Pointer\" ));\n\t\treturn( FALSE );\n\t\t}\n\tattributeListPtr = DATAPTR_GET( attribute );\n\tENSURES_B( attributeListPtr != NULL );\n\n\treturn( sanityCheckAttributePtr( attributeListPtr ) );\n\t}\n\n/* Initialise constant-value attribute data, returned from getAttribute() \n   functions to denote special-case conditions such as the presence of a\n   default attribute value */\n\nvoid initAttributes( void )\n\t{\n\tDATAPTR_SET( defaultFieldAttribute, \n\t\t\t\t ( ATTRIBUTE_LIST * ) &defaultFieldData );\n\tDATAPTR_SET( completeAttribute, \n\t\t\t\t ( ATTRIBUTE_LIST * ) &completeAttributeData );\n\t}\n\n/* Callback function used to provide external access to attribute list-\n   internal fields */\n\nCHECK_RETVAL_PTR \\\nstatic const void *getAttrFunction( IN_OPT TYPECAST( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *attributePtr, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *groupID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *attributeID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *instanceID,\n\t\t\t\t\t\t\t\t\tIN_ENUM( ATTR ) const ATTR_TYPE attrGetType )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = attributePtr;\n\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( groupID == NULL || \\\n\t\t\tisWritePtr( groupID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( attributeID == NULL || \\\n\t\t\tisWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( instanceID == NULL || \\\n\t\t\tisWritePtr( instanceID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES_N( isEnumRange( attrGetType, ATTR ) );\n\n\t/* Clear return values */\n\tif( groupID != NULL )\n\t\t*groupID = CRYPT_ATTRIBUTE_NONE;\n\tif( attributeID != NULL )\n\t\t*attributeID = CRYPT_ATTRIBUTE_NONE;\n\tif( instanceID != NULL )\n\t\t*instanceID = CRYPT_ATTRIBUTE_NONE;\n\n\t/* Move to the next or previous attribute if required */\n\tif( attributeListPtr == NULL )\n\t\treturn( NULL );\n\tif( !isValidAttributeField( attributeListPtr ) )\n\t\t{\n\t\t/* It's a blob-type attribute, there's no concept of ordering by\n\t\t   field for these since they're opaque blobs so we can't move\n\t\t   to a previous/next field */\n\t\treturn( NULL );\n\t\t}\n\tif( attrGetType == ATTR_PREV )\n\t\t{\n\t\tREQUIRES_N( DATAPTR_ISVALID( attributeListPtr->prev ) );\n\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->prev );\n\t\t}\n\telse\n\t\t{\n\t\tif( attrGetType == ATTR_NEXT )\n\t\t\t{\n\t\t\tREQUIRES_N( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\t\t\t}\n\t\t}\n\tif( attributeListPtr == NULL || \\\n\t\t!isValidAttributeField( attributeListPtr ) )\n\t\treturn( NULL );\n\n\t/* Return ID information to the caller */\n\tif( groupID != NULL )\n\t\t*groupID = attributeListPtr->attributeID;\n\tif( attributeID != NULL )\n\t\t*attributeID = attributeListPtr->fieldID;\n\tif( instanceID != NULL )\n\t\t*instanceID = attributeListPtr->subFieldID;\n\treturn( attributeListPtr );\n\t}\n\n/* Print an attribute list, for debugging */\n\n#ifndef NDEBUG\n\nvoid printAttributeList( IN const DATAPTR_ATTRIBUTE attributeList )\n\t{\n\tATTRIBUTE_LIST *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_V( DATAPTR_ISVALID( attributeList ) );\n\n\tDEBUG_PRINT(( \"Attribute list starting at %lX:\\n\", \n\t\t\t\t  attributeList.dataPtr ));\n\tLOOP_LARGE( attributeListCursor = DATAPTR_GET( attributeList ), \n\t\t\t\tattributeListCursor != NULL,\n\t\t\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next ) )\n\t\t{\n\t\tDEBUG_PRINT(( \"This: %8lX Prev: %8lX Next: %8lX attrID = %4d fldID = %4d \"\n\t\t\t\t\t  \"subFldID = %4d.\\n\", attributeListCursor,\n\t\t\t\t\t  attributeListCursor->prev.dataPtr, \n\t\t\t\t\t  attributeListCursor->next.dataPtr, \n\t\t\t\t\t  attributeListCursor->attributeID, \n\t\t\t\t\t  attributeListCursor->fieldID,\n\t\t\t\t\t  attributeListCursor->subFieldID ));\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n#endif /* NDEBUG */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAttribute Type Mapping\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the attribute information for a given OID.  Note that this function\n   looks up whole attributes by OID but won't match an OID that's internal\n   to an attribute */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nconst ATTRIBUTE_INFO *oidToAttribute( IN_ENUM( ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tint attributeInfoSize, attributeInfoCount, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\t\n\tREQUIRES_N( attributeType == ATTRIBUTE_CERTIFICATE || \\\n\t\t\t\tattributeType == ATTRIBUTE_CMS );\n\tREQUIRES_N( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \\\n\t\t\t\toidLength == sizeofOID( oid ) );\n\n\tstatus = getAttributeInfo( attributeType, &attributeInfoPtr, \n\t\t\t\t\t\t\t   &attributeInfoSize );\n\tENSURES_N( cryptStatusOK( status ) );\n\tLOOP_LARGE( attributeInfoCount = 0,\n\t\t\t\t!isAttributeTableEnd( attributeInfoPtr ) && \\\n\t\t\t\t\tattributeInfoCount < attributeInfoSize,\n\t\t\t\t( attributeInfoPtr++, attributeInfoCount++ ) )\n\t\t{\n\t\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\t\t/* If it's an OID that's internal to an attribute, skip it */\n\t\tif( !isAttributeStart( attributeInfoPtr ) )\n\t\t\tcontinue;\n\n\t\t/* Guaranteed by the initialisation sanity-check */\n\t\tENSURES_N( attributeInfoPtr->oid != NULL );\n\n\t\t/* If the OID matches the current attribute, we're done */\n\t\tif( oidLength == sizeofOID( attributeInfoPtr->oid ) && \\\n\t\t\t!memcmp( attributeInfoPtr->oid, oid, oidLength ) )\n\t\t\treturn( attributeInfoPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( attributeInfoCount < attributeInfoSize );\n\n\t/* It's an unknown attribute */\n\treturn( NULL );\n\t}\n\n/* Get the attribute and attributeID for a field ID */\n\nCHECK_RETVAL_PTR \\\nconst ATTRIBUTE_INFO *fieldIDToAttribute( IN_ENUM( ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID, \n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *attributeID )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE lastAttributeID = CRYPT_ATTRIBUTE_NONE;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tint attributeInfoSize, attributeInfoCount, status, LOOP_ITERATOR;\n\n\tassert( attributeID == NULL || \\\n\t\t\tisWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES_N( attributeType == ATTRIBUTE_CERTIFICATE || \\\n\t\t\t\tattributeType == ATTRIBUTE_CMS );\n\tREQUIRES_N( isValidExtension( fieldID ) );\n\tREQUIRES_N( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t\t( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\t  subFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\n\t/* Clear return value */\n\tif( attributeID != NULL )\n\t\t*attributeID = CRYPT_ATTRIBUTE_NONE;\n\n\t/* Find the information on this attribute field */\n\tstatus = getAttributeInfo( attributeType, &attributeInfoPtr, \n\t\t\t\t\t\t\t   &attributeInfoSize );\n\tENSURES_N( cryptStatusOK( status ) );\n\tLOOP_LARGE( attributeInfoCount = 0, \n\t\t\t\t!isAttributeTableEnd( attributeInfoPtr ) && \\\n\t\t\t\t\tattributeInfoCount < attributeInfoSize,\n\t\t\t\t( attributeInfoPtr++, attributeInfoCount++ ) )\n\t\t{\n\t\tconst ATTRIBUTE_INFO *altEncodingTable;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\t\t/* If we're looking for an attribute ID and this is the start of a \n\t\t   complete attribute, remember it so that we can report it to the \n\t\t   caller */\n\t\tif( attributeID != NULL && isAttributeStart( attributeInfoPtr ) )\n\t\t\t{\n\t\t\t/* Usually the attribute ID is the fieldID for the first entry,\n\t\t\t   however in some cases the attributeID is the same as the\n\t\t\t   fieldID and isn't specified until later on.  For example when \n\t\t\t   the attribute consists of a SEQUENCE OF field the first\n\t\t\t   entry is the SEQUENCE and the fieldID isn't given until the\n\t\t\t   second entry.  This case is denoted by the fieldID being \n\t\t\t   FIELDID_FOLLOWS, if this happens then the next entry contains \n\t\t\t   the fieldID (this requirement has been verified by the \n\t\t\t   startup self-check in ext_def.c) */\n\t\t\tif( attributeInfoPtr->fieldID == FIELDID_FOLLOWS )\n\t\t\t\tattributeInfoPtr++;\n\t\t\tENSURES_N( isValidExtension( attributeInfoPtr->fieldID ) );\n\t\t\tlastAttributeID = attributeInfoPtr->fieldID;\n\t\t\t}\n\n\t\t/* If the field ID for this entry isn't the one that we want, \n\t\t   continue */\n\t\tif( attributeInfoPtr->fieldID != fieldID )\n\t\t\tcontinue;\n\n\t\t/* If we're not after a subfield match or there's no subfield \n\t\t   information present, we're done */\n\t\tif( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\tattributeInfoPtr->extraData == NULL )\n\t\t\t{\n\t\t\tif( attributeID != NULL )\n\t\t\t\t*attributeID = lastAttributeID;\n\t\t\treturn( attributeInfoPtr );\n\t\t\t}\n\n\t\t/* We're after a subfield match as well, try and match it.  \n\t\t   Unfortunately we can't use the attributeInfoSize bounds check \n\t\t   limit here because we don't know the size of the alternative \n\t\t   encoding table so we have to use a generic value (the terminating \n\t\t   condition has been verified by the startup self-check in \n\t\t   ext_def.c) */\n\t\tLOOP_MED_ALT( altEncodingTable = attributeInfoPtr->extraData, \n\t\t\t\t\t  !isAttributeTableEnd( altEncodingTable ), \n\t\t\t\t\t  altEncodingTable++ )\n\t\t\t{\n\t\t\tif( altEncodingTable->fieldID == subFieldID )\n\t\t\t\t{\n\t\t\t\tif( attributeID != NULL )\n\t\t\t\t\t*attributeID = lastAttributeID;\n\t\t\t\treturn( altEncodingTable );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK_ALT );\n\n\t\tretIntError_Null();\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( attributeInfoCount < attributeInfoSize );\n\n\t/* If the use of all attributes is enabled then we should never reach \n\t   this point, however since it's unlikely that we'll have every single \n\t   obscure, obsolete, and weird attribute enabled we simply return a not-\n\t   found error if we get to here */\n\treturn( NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\tInternal (ATTRIBUTE_LIST) Attribute Location/Cursor Movement Routines\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the start of an attribute from a field within the attribute */\n\nCHECK_RETVAL_PTR \\\nconst ATTRIBUTE_LIST *findAttributeStart( IN_OPT const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\treturn( attributeFindStart( attributeListPtr, getAttrFunction ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*  External (DATAPTR_ATTRIBUTE) Attribute Location/Cursor Movement Routines\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an attribute in a list of certificate attributes by field and \n   subfield ID.  This is an exact-match functions for which we need an\n   attribute with { fieldID, subFieldID } matching exactly.  It won't find,\n   for example, any match for CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT even\n   if one of the attribute fields such as CRYPT_CERTINFO_ISSUINGDIST_FULLNAME\n   is present */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeField( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID )\n\t{\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_D( isValidExtension( fieldID ) );\n\tREQUIRES_D( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t\t( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\t  subFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\tif( subFieldID == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\treturn( dataptrAttributeFind( attributePtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t  fieldID ) );\n\t\t}\n\treturn( dataptrAttributeFindEx( attributePtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, fieldID, \n\t\t\t\t\t\t\t\t\tsubFieldID ) );\n\t}\n\n/* Find an attribute in a list of certificate attributes by field ID, with\n   special handling for things that aren't direct matches.  These special \n   cases occur when:\n\n\tWe're searching via the overall attribute ID for a constructed attribute \n\t(e.g. CRYPT_CERTINFO_CA) for which only the individual fields (e.g. \n\tCRYPT_CERTINFO_BASICCONSTRAINTS) are present in the attribute list, in \n\twhich case we return a special-case value to indicate that this is a \n\tcomplete attribute and not just one attribute field.\n   \n\tWe're searching for a default-valued field that isn't explicitly present \n\tin the attribute list but for which the attribute that contains it is \n\tpresent, in which case we return a special-case value to indicate that \n\tthis is a default-value field */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeFieldEx( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tconst ATTRIBUTE_TYPE attributeType = \\\n\t\t\t\t\t\t\t( fieldID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_D( isValidExtension( fieldID ) );\n\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\t/* Find the position of this attribute component in the list */\n\tattributeCursor = dataptrAttributeFind( attributePtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t\t\tfieldID );\n\tif( DATAPTR_ISSET( attributeCursor ) )\n\t\treturn( attributeCursor );\n\n\t/* This particular attribute field isn't present in the list of \n\t   attributes, check whether the overall attribute that contains this \n\t   field is present.  First we map the field to the attribute that \n\t   contains it, so for example CRYPT_CERTINFO_AUTHORITYINFO_CRLS \n\t   would become CRYPT_CERTINFO_AUTHORITYINFOACCESS.  If we're already \n\t   searching by overall attribute ID (e.g. searching for \n\t   CRYPT_CERTINFO_AUTHORITYINFOACCESS, which wouldn't result in a match \n\t   because only the component fields of \n\t   CRYPT_CERTINFO_AUTHORITYINFOACCESS are present) then this step is a \n\t   no-op */\n\tattributeInfoPtr = fieldIDToAttribute( attributeType, fieldID, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE, &attributeID );\n\tif( attributeInfoPtr == NULL )\n\t\t{\n\t\t/* There's no attribute containing this field, exit */\n\t\treturn( DATAPTR_NULL );\n\t\t}\n\n\t/* We've now got the ID of the overall attribute that contains the \n\t   requested field, check whether any other part of the attribute that \n\t   contains the field is present in the list of attribute fields.  So \n\t   from the previous example of looking for the field \n\t   CRYPT_CERTINFO_AUTHORITYINFO_CRLS we'd get a match if e.g. \n\t   CRYPT_CERTINFO_AUTHORITYINFO_OCSP was present since they're both in \n\t   the same attribute CRYPT_CERTINFO_AUTHORITYINFOACCESS */\n\tattributeCursor = dataptrAttributeFindEx( attributePtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t\t\t  attributeID, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn( DATAPTR_NULL );\n\tattributeListPtr = DATAPTR_GET( attributeCursor );\n\tENSURES_D( attributeListPtr != NULL );\n\tif( !isValidAttributeField( attributeListPtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\t/* Some other part of the attribute containing the given field is \n\t   present in the attribute list:\n\n\t\tIf the attribute info indicates that this field is a default-value \n\t\tthen one we return an entry that denotes that this field is pseudo-\n\t\tpresent due to it having a default setting.  Note that this requires \n\t\tthat the field be a BOOLEAN DEFAULT FALSE, or at least a numeric \n\t\tvalue DEFAULT 0, since the returned 'defaultField' reads as having a \n\t\tnumeric value zero (this has been verified by the startup self-check \n\t\tin ext_def.c).\n\t\t\n\t\tIf the attribute info indicates that this is an ID for a complete \n\t\tattribute rather than an individual field within it we return an \n\t\tentry to indicate this */\n\tif( attributeInfoPtr->encodingFlags & FL_DEFAULT )\n\t\treturn( defaultFieldAttribute );\n\tif( isAttributeStart( attributeInfoPtr ) )\n\t\treturn( completeAttribute );\n\n\treturn( DATAPTR_NULL );\n\t}\n\n/* Find an attribute in a list of certificate attributes by object \n   identifier, used for blob-type attributes */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttributeByOID( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tATTRIBUTE_LIST *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\t\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_D( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \\\n\t\t\t\toidLength == sizeofOID( oid ) );\n\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\t/* Find the position of this component in the list */\n\tLOOP_LARGE( ( attributeCursor = attributePtr, \n\t\t\t\t  attributeListCursor = DATAPTR_GET( attributePtr ) ),\n\t\t\t\tattributeListCursor != NULL,\n\t\t\t\t( attributeCursor = attributeListCursor->next,\n\t\t\t\t  attributeListCursor = DATAPTR_GET( attributeListCursor->next ) ) )\n\t\t{\n\t\tREQUIRES_D( sanityCheckAttributePtr( attributeListCursor ) );\n\n\t\t/* If it's not a blob-type attribute, continue */\n\t\tif( !checkAttributeListProperty( attributeListCursor, \n\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t\tcontinue;\n\n\t\t/* If we've found the entry with the required OID, we're done */\n\t\tif( oidLength == sizeofOID( attributeListCursor->oid ) && \\\n\t\t\t!memcmp( attributeListCursor->oid, oid, oidLength ) )\n\t\t\treturn( attributeCursor );\n\t\t}\n\tENSURES_D( LOOP_BOUND_OK );\n\n\treturn( DATAPTR_NULL );\n\t}\n\n/* Find the next instance of an attribute field in an attribute.  This is \n   used to step through multiple instances of a field, for example where the\n   attribute is defined as containing a SEQUENCE OF <field> */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findNextFieldInstance( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr )\n\t{\n\tREQUIRES_D( DATAPTR_ISSET( attributePtr ) );\n\n\treturn( dataptrAttributeFindNextInstance( attributePtr, getAttrFunction ) );\n\t}\n\n/* Find a DN in an attribute, where the attribute will be a GeneralName */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findDnInAttribute( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tCRYPT_ATTRIBUTE_TYPE attributeID, fieldID;\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES_D( attributeListPtr != NULL );\n\n\t/* Remember the current GeneralName type so that we don't stray \n\t   outside it */\n\tattributeID = attributeListPtr->attributeID;\n\tfieldID = attributeListPtr->fieldID;\n\tREQUIRES_D( isGeneralNameSelectionComponent( fieldID ) );\n\n\t/* Search for a DN in the current GeneralName */\n\tLOOP_LARGE( attributeCursor = attributePtr,\n\t\t\t\tattributeListPtr != NULL && \\\n\t\t\t\t\tattributeListPtr->attributeID == attributeID && \\\n\t\t\t\t\tattributeListPtr->fieldID == fieldID,\n\t\t\t\t( attributeCursor = attributeListPtr->next,\n\t\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) ) )\n\t\t{\n\t\tREQUIRES_D( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t\tif( attributeListPtr->fieldType == FIELDTYPE_DN )\n\t\t\treturn( attributeCursor );\n\t\t}\n\tENSURES_D( LOOP_BOUND_OK );\n\n\treturn( DATAPTR_NULL );\n\t}\n\n/* Find an overall attribute in a list of attributes.  This is almost always\n   used as a check for the presence of an overall attribute so we provide a \n   separate function checkAttributeXXXPresent() to make this explicit */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE findAttribute( IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\t const BOOLEAN isFieldID )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE localAttributeID = attributeID;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_D( isValidExtension( attributeID ) );\n\tREQUIRES_D( isFieldID == TRUE || isFieldID == FALSE );\n\t\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\t/* If this is a (potential) fieldID rather than an attributeID, find the\n\t   attributeID for the attribute containing this field */\n\tif( isFieldID )\n\t\t{\n\t\tif( fieldIDToAttribute( ( attributeID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE, \n\t\t\t\t\t\t\t\tattributeID, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t&localAttributeID ) == NULL )\n\t\t\t{\n\t\t\t/* There's no attribute containing this field, exit */\n\t\t\treturn( DATAPTR_NULL );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Make sure that we're searching on an attribute ID rather than a \n\t\t   field ID */\n\t\tENSURES_D( \\\n\t\t\tfieldIDToAttribute( ( attributeID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE, \n\t\t\t\t\t\t\t\tattributeID, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t&localAttributeID ) == NULL || \\\n\t\t\tattributeID == localAttributeID );\n\t\t}\n\n\t/* Check whether this attribute is present in the list of attribute \n\t   fields */\n\treturn( dataptrAttributeFindEx( attributePtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\tlocalAttributeID, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE ) );\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributePresent( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\tREQUIRES_B( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_B( isValidExtension( fieldID ) );\n\n\tattributeCursor = findAttribute( attributePtr, fieldID, FALSE );\n\treturn( DATAPTR_ISSET( attributeCursor ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeFieldPresent( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\tREQUIRES_B( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_B( isValidExtension( fieldID ) );\n\n\tattributeCursor = findAttributeField( attributePtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE );\n\treturn( DATAPTR_ISSET( attributeCursor ) ? TRUE : FALSE );\n\t}\n\n/* Move the attribute cursor relative to the current cursor position.  The \n   reason for the apparently-reversed values in the IN_RANGE() annotation\n   are because the values are -ve, so last comes before first */\n\nCHECK_RETVAL_DATAPTR \\\nDATAPTR_ATTRIBUTE certMoveAttributeCursor( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE currentCursor,\n\t\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE certInfoType,\n\t\t\t\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int position )\n\t{\n\tREQUIRES_D( DATAPTR_ISVALID( currentCursor ) );\n\tREQUIRES_D( certInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t\tcertInfoType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t\tcertInfoType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\tREQUIRES_D( position <= CRYPT_CURSOR_FIRST && \\\n\t\t\t\tposition >= CRYPT_CURSOR_LAST );\n\n\treturn( dataptrAttributeMoveCursor( currentCursor, getAttrFunction,\n\t\t\t\t\t\t\t\t\t\tcertInfoType, position ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get/set information for an attribute */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkAttributeListProperty( IN const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES_B( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES_B( isEnumRange( property, ATTRIBUTE_PROPERTY ) );\n\n\tswitch( property )\n\t\t{\n\t\tcase ATTRIBUTE_PROPERTY_BLOBATTRIBUTE:\n\t\t\treturn( ( attributeListPtr->fieldID == blobAttributeData.fieldID && \\\n\t\t\t\t\t  attributeListPtr->attributeID == blobAttributeData.attributeID ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_COMPLETEATRIBUTE:\n\t\t\treturn( ( attributeListPtr->fieldID == completeAttributeData.fieldID && \\\n\t\t\t\t\t  attributeListPtr->attributeID == completeAttributeData.attributeID ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_CRITICAL:\n\t\t\treturn( TEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t   ATTR_FLAG_CRITICAL ) ? TRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_DEFAULTVALUE:\n\t\t\treturn( ( attributeListPtr->fieldID == defaultFieldData.fieldID && \\\n\t\t\t\t\t  attributeListPtr->attributeID == defaultFieldData.attributeID ) ? \\\n\t\t\t\t\t  TRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_DN:\n\t\t\treturn( ( attributeListPtr->fieldType == FIELDTYPE_DN ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_IGNORED:\n\t\t\treturn( TEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t   ATTR_FLAG_IGNORED ) ? TRUE : FALSE );\n\n\t\tcase ATTRIBUTE_PROPERTY_LOCKED:\n\t\t\treturn( TEST_FLAG( attributeListPtr->flags,\n\t\t\t\t\t\t\t   ATTR_FLAG_LOCKED ) ? TRUE : FALSE );\n\t\t\n\t\tcase ATTRIBUTE_PROPERTY_OID:\n\t\t\treturn( ( attributeListPtr->fieldType == BER_OBJECT_IDENTIFIER ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeProperty( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\tIN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES_B( DATAPTR_ISSET( attributePtr ) );\n\tREQUIRES_B( isEnumRange( property, ATTRIBUTE_PROPERTY ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tREQUIRES_B( attributeListPtr != NULL );\n\n\treturn( checkAttributeListProperty( attributeListPtr, property ) );\n\t}\n\nvoid setAttributeProperty( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   IN_ENUM( ATTRIBUTE_PROPERTY ) \\\n\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_TYPE property,\n\t\t\t\t\t\t   IN_INT_Z const int optValue )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES_V( DATAPTR_ISSET( attributePtr ) );\n\tREQUIRES_V( isEnumRange( property, ATTRIBUTE_PROPERTY ) );\n\tREQUIRES_V( optValue >= 0 );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tREQUIRES_V( attributeListPtr != NULL );\n\n\tswitch( property )\n\t\t{\n\t\tcase ATTRIBUTE_PROPERTY_CRITICAL:\n\t\t\tREQUIRES_V( optValue == 0 );\n\n\t\t\tSET_FLAG( attributeListPtr->flags, ATTR_FLAG_CRITICAL );\n\t\t\treturn;\n\n\t\tcase ATTRIBUTE_PROPERTY_VALUE:\n\t\t\tREQUIRES_V( optValue > 0 );\n\n\t\t\tattributeListPtr->intValue = optValue;\n\t\t\treturn;\n\n\t\tcase ATTRIBUTE_PROPERTY_LOCKED:\n\t\t\tREQUIRES_V( optValue == 0 );\n\n\t\t\tSET_FLAG( attributeListPtr->flags, ATTR_FLAG_LOCKED );\n\t\t\treturn;\n\t\t}\n\t\n\tretIntError_Void();\n\t}\n\n/* Get attribute ID information */\n\nCHECK_RETVAL \\\nint getAttributeIdInfo( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *attributeID,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *fieldID,\n\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *subFieldID )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tassert( attributeID == NULL || \\\n\t\t\tisWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( fieldID == NULL || \\\n\t\t\tisWritePtr( fieldID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( subFieldID == NULL || \\\n\t\t\tisWritePtr( subFieldID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tREQUIRES( attributeID != NULL || fieldID != NULL || subFieldID != NULL );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tREQUIRES( attributeListPtr != NULL );\n\n\t/* If this is a blob attribute then the ID values aren't present */\n\tif( checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Return ID information to the caller */\n\tif( attributeID != NULL )\n\t\t*attributeID = attributeListPtr->attributeID;\n\tif( fieldID != NULL )\n\t\t*fieldID = attributeListPtr->fieldID;\n\tif( subFieldID != NULL )\n\t\t*subFieldID = attributeListPtr->subFieldID;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Enumerate entries in an attribute list.  Note that these two functions \n   must be called atomically since they record pointers within the list, \n   which would leave a dangling reference if (say) a delete occurred between\n   getNext()'s */\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nCONST_RETURN DATAPTR_ATTRIBUTE getFirstAttribute( OUT ATTRIBUTE_ENUM_INFO *attrEnumInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t  IN_DATAPTR_OPT \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\t\t\t\t  IN_ENUM( ATTRIBUTE_ENUM ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_ENUM_TYPE enumType )\n\t{\n\tassert( isWritePtr( attrEnumInfo, sizeof( ATTRIBUTE_ENUM_INFO ) ) );\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES_D( isEnumRange( enumType, ATTRIBUTE_ENUM ) );\n\n\t/* Clear return value */\n\tmemset( attrEnumInfo, 0, sizeof( ATTRIBUTE_ENUM_INFO ) );\n\tattrEnumInfo->attributePtr = attributePtr;\n\tattrEnumInfo->enumType = enumType;\n\n\t/* Early-out check for empty attribute lists */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\tswitch( enumType )\n\t\t{\n\t\tcase ATTRIBUTE_ENUM_BLOB:\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE attributeCursor;\n\t\t\tconst ATTRIBUTE_LIST *attributeListPtr;\n\t\t\tint LOOP_ITERATOR;\n\n\t\t\t/* Blob attributes are a special case because they're preceded \n\t\t\t   in the attribute list by non-blob attributes so before we try \n\t\t\t   and enumerate blob attributes we have to skip any non-blob\n\t\t\t   ones that may be present */\n\t\t\tLOOP_LARGE( ( attributeCursor = attributePtr,\n\t\t\t\t\t\t  attributeListPtr = DATAPTR_GET( attributePtr ) ),\n\t\t\t\t\t\tattributeListPtr != NULL && \\\n\t\t\t\t\t\t\t!checkAttributeProperty( attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ),\n\t\t\t\t\t\t( attributeCursor = attributeListPtr->next,\n\t\t\t\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) ) )\n\t\t\t\t{\n\t\t\t\tREQUIRES_D( sanityCheckAttributePtr( attributeListPtr ) );\n\t\t\t\t}\n\t\t\tENSURES_D( LOOP_BOUND_OK );\n\t\t\tattrEnumInfo->attributePtr = attributeCursor;\n\n\t\t\t/* If there are no blob attributes, we're done */\n\t\t\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\t\t\treturn( DATAPTR_NULL );\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ATTRIBUTE_ENUM_NONBLOB:\n\t\t\t/* If there are no non-blob attributes, we're done */\n\t\t\tif( checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t\t\t{\n\t\t\t\tDATAPTR_SET( attrEnumInfo->attributePtr, NULL );\n\t\t\t\treturn( DATAPTR_NULL );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Dataptr();\n\t\t}\n\n\treturn( attrEnumInfo->attributePtr );\n\t}\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 1 ) ) \\\nCONST_RETURN DATAPTR_ATTRIBUTE getNextAttribute( INOUT ATTRIBUTE_ENUM_INFO *attrEnumInfo )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tassert( isWritePtr( attrEnumInfo, sizeof( ATTRIBUTE_ENUM_INFO ) ) );\n\n\tREQUIRES_D( DATAPTR_ISSET( attrEnumInfo->attributePtr ) );\n\n\t/* Move on to the next attribute in the list */\n\tattributeListPtr = DATAPTR_GET( attrEnumInfo->attributePtr );\n\tENSURES_D( attributeListPtr != NULL );\n\tattrEnumInfo->attributePtr = attributeListPtr->next;\n\tif( DATAPTR_ISNULL( attrEnumInfo->attributePtr ) )\n\t\treturn( DATAPTR_NULL );\n\n\tswitch( attrEnumInfo->enumType )\n\t\t{\n\t\tcase ATTRIBUTE_ENUM_BLOB:\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_ENUM_NONBLOB:\n\t\t\t/* If there are no more non-blob attributes, we're done */\n\t\t\tif( checkAttributeProperty( attrEnumInfo->attributePtr, \n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t\t\t{\n\t\t\t\tDATAPTR_SET( attrEnumInfo->attributePtr, NULL );\n\t\t\t\treturn( DATAPTR_NULL );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Dataptr();\n\t\t}\n\n\treturn( attrEnumInfo->attributePtr );\n\t}\n\n/* Get attribute data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataValue( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   OUT_INT_Z int *value )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( attributeListPtr->fieldType == BER_INTEGER || \\\n\t\t\t  attributeListPtr->fieldType == BER_ENUMERATED || \\\n\t\t\t  attributeListPtr->fieldType == BER_BITSTRING || \\\n\t\t\t  attributeListPtr->fieldType == BER_BOOLEAN || \\\n\t\t\t  attributeListPtr->fieldType == BER_NULL || \\\n\t\t\t  attributeListPtr->fieldType == FIELDTYPE_CHOICE || \\\n\t\t\t  attributeListPtr->fieldType == FIELDTYPE_IDENTIFIER );\n\n\t*value = attributeListPtr->intValue;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataTime( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t  OUT time_t *value )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( attributeListPtr->fieldType == BER_TIME_GENERALIZED || \\\n\t\t\t  attributeListPtr->fieldType == BER_TIME_UTC );\n\n\t*value = *( ( time_t * ) attributeListPtr->dataValue );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataDN( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\tOUT_DATAPTR_COND DATAPTR_DN *dnPtr )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( attributeListPtr->fieldType == FIELDTYPE_DN );\n\n\t*dnPtr = GET_DN_POINTER( attributeListPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getAttributeDataDNPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   OUT_PTR DATAPTR_DN **dnPtrPtr )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( attributeListPtr->fieldType == FIELDTYPE_DN );\n\n\t/* See the comment by the definition of SELECTION_INFO in cert.h for the\n\t   reason why we return the address of the pointer rather than the \n\t   pointer itself */\n\t*dnPtrPtr = ( DATAPTR_DN * ) &attributeListPtr->dnValue;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getAttributeDataPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t OUT_BUFFER_ALLOC( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *dataLength )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( attributeListPtr->fieldType == BER_OCTETSTRING || \\\n\t\t\t  attributeListPtr->fieldType == BER_OBJECT_IDENTIFIER || \\\n\t\t\t  attributeListPtr->fieldType == BER_TIME_GENERALIZED || \\\n\t\t\t  attributeListPtr->fieldType == BER_TIME_UTC || \\\n\t\t\t  isStringField( attributeListPtr->fieldType ) || \\\n\t\t\t  attributeListPtr->fieldType == FIELDTYPE_TEXTSTRING || \\\n\t\t\t  isBlobField( attributeListPtr->fieldType ) );\n\n\t*dataPtrPtr = attributeListPtr->dataValue;\n\t*dataLength = attributeListPtr->dataValueLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getBlobAttributeDataPtr( IN const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t OUT_BUFFER_ALLOC( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *dataLength )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\t/* This function is identical to getAttributeDataPtr() except for a \n\t   type-checking issue, it returns a pointer to a blob attribute's \n\t   data */\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\tREQUIRES( checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) );\n\n\t*dataPtrPtr = attributeListPtr->dataValue;\n\t*dataLength = attributeListPtr->dataValueLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* The pattern { findAttributeField(), getAttributeDataXXX() } where XXX ==\n   { Value, Time } is used frequently enough that we provide a standard \n   function for it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nint getAttributeFieldValue( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\tIN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\tOUT_INT_Z int *value )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\t/* Find the required attribute field and return its value */\n\tattributeCursor = findAttributeField( attributePtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t  subFieldID );\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\treturn( getAttributeDataValue( attributeCursor, value ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nint getAttributeFieldTime( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t   IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t   OUT time_t *value )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\t/* Find the required attribute field and return its value */\n\tattributeCursor = findAttributeField( attributePtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t  subFieldID );\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\treturn( getAttributeDataTime( attributeCursor, value ) );\n\t}\n\n/* Get the default value for an optional field of an attribute */\n\nCHECK_RETVAL \\\nint getDefaultFieldValue( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\n\tREQUIRES( isValidExtension( fieldID ) );\n\n\tattributeInfoPtr = \\\n\t\tfieldIDToAttribute( ( fieldID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE, fieldID, \n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, NULL );\n\tENSURES( attributeInfoPtr != NULL );\n\n\treturn( attributeInfoPtr->defaultValue );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Compare Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKIUSER\n\n/* Compare attribute fields */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN compareAttributeField( IN const ATTRIBUTE_LIST *attributeField1,\n\t\t\t\t\t\t\t\t\t  IN const ATTRIBUTE_LIST *attributeField2 )\n\t{\n\tassert( isReadPtr( attributeField1, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtr( attributeField2, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES_B( sanityCheckAttributePtr( attributeField1 ) );\n\tREQUIRES_B( sanityCheckAttributePtr( attributeField2 ) );\n\tREQUIRES_B( attributeField1->attributeID == attributeField2->attributeID );\n\n\t/* Compare attribute IDs */\n\tif( attributeField1->fieldID != attributeField2->fieldID || \\\n\t\tattributeField1->subFieldID != attributeField2->subFieldID )\n\t\treturn( FALSE );\n\n\t/* Compare the field type and any relevant attribute flags */\n\tif( attributeField1->fieldType != attributeField2->fieldType )\n\t\treturn( FALSE );\n\tif( GET_FLAGS( attributeField1->flags, ATTR_FLAGS_COMPARE_MASK ) != \\\n\t\t\tGET_FLAGS( attributeField2->flags, ATTR_FLAGS_COMPARE_MASK ) )\n\t\treturn( FALSE );\n\n\t/* Compare field data */\n\tif( attributeField1->fieldType == FIELDTYPE_DN )\n\t\t{\n\t\tconst DATAPTR_DN dn1 = GET_DN_POINTER( attributeField1 );\n\t\tconst DATAPTR_DN dn2 = GET_DN_POINTER( attributeField2 );\n\n\t\tREQUIRES_B( DATAPTR_ISVALID( dn1 ) );\n\t\tREQUIRES_B( DATAPTR_ISVALID( dn2 ) );\n\n\t\t/* DNs are structured data and need to be compared specially */\n\t\treturn( compareDN( dn1, dn2, FALSE, NULL ) );\n\t\t}\n\tif( attributeField1->fieldType == FIELDTYPE_CHOICE || \\\n\t\tattributeField1->fieldType == FIELDTYPE_IDENTIFIER )\n\t\t{\n\t\t/* Choice/identifier fields store the selection value in the \n\t\t   intValue */\n\t\treturn( ( attributeField1->intValue == attributeField2->intValue ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attributeField1->fieldType == BER_NULL )\n\t\t{\n\t\t/* A BER_NULL has no associated data and always compares as \n\t\t   true */\n\t\treturn( TRUE );\n\t\t}\n\tif( attributeField1->fieldType == BER_INTEGER || \\\n\t\tattributeField1->fieldType == BER_ENUMERATED || \\\n\t\tattributeField1->fieldType == BER_BITSTRING || \\\n\t\tattributeField1->fieldType == BER_BOOLEAN )\n\t\t{\n\t\treturn( ( attributeField1->intValue == attributeField2->intValue ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tREQUIRES_B( attributeField1->fieldType == BER_OCTETSTRING || \\\n\t\t\t\tattributeField1->fieldType == BER_OBJECT_IDENTIFIER || \\\n\t\t\t\tattributeField1->fieldType == BER_TIME_GENERALIZED || \\\n\t\t\t\tattributeField1->fieldType == BER_TIME_UTC || \\\n\t\t\t\tisStringField( attributeField1->fieldType ) || \\\n\t\t\t\tattributeField1->fieldType == FIELDTYPE_TEXTSTRING || \\\n\t\t\t\tisBlobField( attributeField1->fieldType ) );\n\tif( attributeField1->dataValueLength != \\\n\t\t\t\t\t\t\tattributeField2->dataValueLength )\n\t\treturn( FALSE );\n\tif( attributeField1->dataValueLength > 0 )\n\t\t{\n\t\tif( memcmp( attributeField1->dataValue, attributeField2->dataValue,\n\t\t\t\t\tattributeField1->dataValueLength ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Compare attributes */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN compareAttribute( IN_DATAPTR const DATAPTR_ATTRIBUTE attribute1,\n\t\t\t\t\t\t  IN_DATAPTR const DATAPTR_ATTRIBUTE attribute2 )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr1;\n\tconst ATTRIBUTE_LIST *attributeListPtr2;\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_B( DATAPTR_ISSET( attribute1 ) );\n\tREQUIRES_B( DATAPTR_ISSET( attribute2 ) );\n\tattributeListPtr1 = DATAPTR_GET( attribute1 );\n\tattributeListPtr2 = DATAPTR_GET( attribute2 );\n\tREQUIRES_B( attributeListPtr1 != NULL && attributeListPtr2 != NULL );\n\tREQUIRES_B( attributeListPtr1->attributeID == \\\n\t\t\t\t\t\t\t\t\t\tattributeListPtr2->attributeID );\n\tattributeID = attributeListPtr1->attributeID;\n\n\t/* Compare all of the fields in the attributes */\n\tLOOP_LARGE_CHECKINC( attributeListPtr1 != NULL && attributeListPtr2 != NULL && \\\n\t\t\t\t\t\t\tattributeListPtr1->attributeID == attributeID && \\\n\t\t\t\t\t\t\tattributeListPtr2->attributeID == attributeID,\n\t\t\t\t\t\t ( attributeListPtr1 = DATAPTR_GET( attributeListPtr1->next ), \\\n\t\t\t\t\t\t   attributeListPtr2 = DATAPTR_GET( attributeListPtr2->next ) ) )\n\t\t{\n\t\tif( !compareAttributeField( attributeListPtr1, attributeListPtr2 ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* If the first attribute list terminated, make sure that the attribute \n\t   doesn't continue in the second list */\n\tif( attributeListPtr1 == NULL )\n\t\t{\n\t\tif( attributeListPtr2 != NULL && \\\n\t\t\tattributeListPtr2->attributeID == attributeID )\n\t\t\treturn( FALSE );\n\n\t\t/* Both attribute lists terminated at the same point */\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If the second attribute list terminated, make sure that the attribute \n\t   doesn't continue in the first list */\n\tif( attributeListPtr2 == NULL )\n\t\t{\n\t\tif( attributeListPtr1->attributeID == attributeID )\n\t\t\treturn( FALSE );\n\n\t\t/* Both attribute lists terminated at the same point */\n\t\treturn( TRUE );\n\t\t}\n\n\t/* There are more attributes in the list, make sure that the current \n\t   attribute doesn't continue in either list */\n\tif( attributeListPtr1->attributeID == attributeID || \\\n\t\tattributeListPtr2->attributeID == attributeID )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_PKIUSER */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMiscellaneous Attribute Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Fix up certificate attributes, mapping from incorrect values to standards-\n   compliant ones */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fixAttributes( INOUT CERT_INFO *certInfoPtr )\n\t{\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tint complianceLevel;\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Try and locate email addresses wherever they might be stashed and move\n\t   them to the certificate altNames */\n\tstatus = convertEmail( certInfoPtr, &certInfoPtr->subjectName,\n\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = convertEmail( certInfoPtr, &certInfoPtr->issuerName,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUERALTNAME );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* If we're running at a compliance level of \n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL or above, don't try and compensate\n\t   for dubious attributes */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( complianceLevel >= CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )\n\t\treturn( CRYPT_OK );\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n#ifdef USE_CERT_OBSOLETE\n\t/* If the only key usage information present is the Netscape one, \n\t   convert it into the X.509 equivalent */\n\tif( !checkAttributePresent( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\tattributePtr = findAttributeField( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_NS_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t{\n\t\t\tint keyUsage;\n\n\t\t\tstatus = getKeyUsageFromExtKeyUsage( certInfoPtr, &keyUsage,\n\t\t\t\t\t\t\t\t\t\t\t\t &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = addAttributeField( &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, keyUsage, \n\t\t\t\t\t\t\t\t\t\t\tATTR_FLAG_NONE,  \n\t\t\t\t\t\t\t\t\t\t\t&certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_CERT_OBSOLETE */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_add.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Attribute Add/Delete Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the validity of an attribute field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 7 ) ) \\\nstatic int checkAttributeField( IN_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\tconst ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t\tIN_INT_Z const int value,\n\t\t\t\t\t\t\t\tIN_FLAGS( ATTR ) const int flags, \n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Clear return value */\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Make sure that a valid field has been specified and that this field\n\t   isn't already present as a non-default entry unless it's a field for\n\t   which multiple values are allowed */\n\tif( attributeInfoPtr == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\t\t/* If this attribute is already present and it's not multivalued, we \n\t\t   can't have any duplicate fields */\n\t\tattributeCursor = findAttributeField( attributePtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t  subFieldID );\n\t\tif( DATAPTR_ISSET( attributeCursor ) && \\\n\t\t\t!( ( attributeInfoPtr->encodingFlags & FL_MULTIVALUED ) || \\\n\t\t\t   ( flags & ATTR_FLAG_MULTIVALUED ) ) )\n\t\t\t{\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\t\t}\n\n\tswitch( attributeInfoPtr->fieldType )\n\t\t{\n\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\t/* It's an identifier, make sure that all parameters are correct */\n\t\t\tif( value != CRYPT_UNUSED )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t/* When creating a new certificate this is a special-case field \n\t\t\t   that's used as a placeholder to indicate that a DN structure \n\t\t\t   is being instantiated.  When reading an encoded certificate \n\t\t\t   this is the decoded DN structure */\n\t\t\tENSURES( value == CRYPT_UNUSED );\n\t\t\tbreak;\n\n\t\tcase BER_BOOLEAN:\n\t\t\t/* BOOLEAN data is accepted as zero/nonzero so it's always \n\t\t\t   valid */\n\t\t\tbreak;\n\n\t\tcase BER_INTEGER:\n\t\tcase BER_ENUMERATED:\n\t\tcase BER_BITSTRING:\n\t\tcase BER_NULL:\n\t\tcase FIELDTYPE_CHOICE:\n\t\t\t/* Check that the range is valid */\n\t\t\tif( value < attributeInfoPtr->lowRange || \\\n\t\t\t\tvalue > attributeInfoPtr->highRange )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 8, 9 ) ) \\\nstatic int checkAttributeFieldString( IN_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\tconst ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t\tIN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\tIN_LENGTH_ATTRIBUTE const int dataLength,\n\t\t\t\t\t\t\t\tIN_FLAGS( ATTR ) const int flags, \n\t\t\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *newDataLength, \n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tint status;\n\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( newDataLength, sizeof( int ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\tREQUIRES( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE );\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_BLOB_PAYLOAD | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Clear return value */\n\t*newDataLength = 0;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Make sure that a valid field has been specified and that this field\n\t   isn't already present as a non-default entry unless it's a field for\n\t   which multiple values are allowed */\n\tif( attributeInfoPtr == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\t\t/* If this attribute is already present and it's not multivalued, we \n\t\t   can't have any duplicate fields */\n\t\tattributeCursor = findAttributeField( attributePtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t  subFieldID );\n\t\tif( DATAPTR_ISSET( attributeCursor ) && \\\n\t\t\t!( ( attributeInfoPtr->encodingFlags & FL_MULTIVALUED ) || \\\n\t\t\t   ( flags & ATTR_FLAG_MULTIVALUED ) ) )\n\t\t\t{\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\t\t}\n\n\t/* If it's a blob field, don't do any type checking.  This is a special \n\t   case that differs from FIELDTYPE_BLOB_xxx in that it corresponds to \n\t   an ASN.1 value that's mis-encoded by one or more implementations, so \n\t   we have to accept absolutely anything at this point */\n\tif( flags & ATTR_FLAG_BLOB )\n\t\treturn( CRYPT_OK );\n\n\t/* If it's a DN_PTR there's no further type checking to be done either */\n\tif( attributeInfoPtr->fieldType == FIELDTYPE_DN )\n\t\treturn( CRYPT_OK );\n\n\t/* If we've been passed an OID it may be encoded as a text string so \n\t   before we can continue we have to determine whether any \n\t   transformations will be necessary */\n\tif( attributeInfoPtr->fieldType == BER_OBJECT_IDENTIFIER )\n\t\t{\n\t\tconst BYTE *oidPtr = data;\n\t\tBYTE binaryOID[ MAX_OID_SIZE + 8 ];\n\n\t\t/* If it's a BER/DER-encoded OID, make sure that it's valid ASN.1 */\n\t\tif( oidPtr[ 0 ] == BER_OBJECT_IDENTIFIER )\n\t\t\t{\n\t\t\tif( dataLength >= MIN_OID_SIZE && dataLength <= MAX_OID_SIZE && \\\n\t\t\t\tsizeofOID( oidPtr ) == dataLength )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint length;\n\n\t\t\t/* It's a text OID, check the syntax and make sure that the \n\t\t\t   length is valid */\n\t\t\tstatus = textToOID( data, dataLength, binaryOID, MAX_OID_SIZE, \n\t\t\t\t\t\t\t\t&length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* The binary form of the OID differs in length from the \n\t\t\t\t   string form, tell the caller that the data length will \n\t\t\t\t   change on encoding so that they can allocate an \n\t\t\t\t   appropriately-sized buffer for it before continuing */\n\t\t\t\t*newDataLength = length;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\n\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Make sure that the data size is valid */\n\tif( dataLength < attributeInfoPtr->lowRange || \\\n\t\tdataLength > attributeInfoPtr->highRange )\n\t\t{\n\t\t*errorType = CRYPT_ERRTYPE_ATTR_SIZE;\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* If we're not checking the payload in order to handle CAs who stuff \n\t   any old rubbish into the fields, exit now unless it's a blob field, \n\t   for which we need to find at least valid ASN.1 data */\n\tif( ( flags & ATTR_FLAG_BLOB_PAYLOAD ) && \\\n\t\t!isBlobField( attributeInfoPtr->fieldType ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Perform any special-case checking that may be required */\n\tswitch( attributeInfoPtr->fieldType )\n\t\t{\n\t\tcase FIELDTYPE_BLOB_ANY:\n\t\t\t{\n\t\t\t/* It's a blob field, make sure that it's a valid ASN.1 object */\n\t\t\tstatus = checkCertObjectEncoding( data, dataLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\t\t{\n\t\t\tconst int firstByte = byteToInt( ( ( BYTE * ) data )[ 0 ] );\n\t\t\tconst int requiredByte = \\\n\t\t\t\t\t( attributeInfoPtr->fieldType == FIELDTYPE_BLOB_BITSTRING ) ? \\\n\t\t\t\t\t  BER_BITSTRING : BER_SEQUENCE;\n\n\t\t\t/* Typed blobs have a bit more information available than just \n\t\t\t   \"it must be a valid ASN.1 object\" so we can check that it's \n\t\t\t   the correct type of object as well as the ASN.1 validity \n\t\t\t   check */\n\t\t\tif( firstByte != requiredByte )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tstatus = checkCertObjectEncoding( data, dataLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase BER_STRING_NUMERIC:\n\t\t\t{\n\t\t\tconst BYTE *dataPtr = data;\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\t/* Make sure that it's a numeric string */\n\t\t\tLOOP_EXT( i = 0, i < dataLength, i++, MAX_ATTRIBUTE_SIZE + 1 )\n\t\t\t\t{\n\t\t\t\tif( !isDigit( dataPtr[ i ] ) )\n\t\t\t\t\t{\n\t\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase BER_STRING_IA5:\n\t\tcase BER_STRING_ISO646:\n\t\tcase BER_STRING_PRINTABLE:\n\t\t\t/* Make sure that it's an ASCII string of the correct type */\n\t\t\tif( !checkTextStringData( data, dataLength, \n\t\t\t\t\t( attributeInfoPtr->fieldType == BER_STRING_PRINTABLE ) ? \\\n\t\t\t\t\tTRUE : FALSE ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t/* Finally, if there's a special-case validation function present, make\n\t   sure that the value is valid */\n\tif( attributeInfoPtr->extraData != NULL )\n\t\t{\n\t\tVALIDATION_FUNCTION validationFunction = \\\n\t\t\t\t\t( VALIDATION_FUNCTION ) attributeInfoPtr->extraData;\n\t\tATTRIBUTE_LIST checkAttribute;\n\n\t\t/* Since the validation function expects an ATTRIBUTE_LIST entry,\n\t\t   we have to create a dummy entry in order to check the raw\n\t\t   attribute components */\n\t\tmemset( &checkAttribute, 0, sizeof( ATTRIBUTE_LIST ) );\n\t\tcheckAttribute.attributeID = checkAttribute.fieldID = fieldID;\n\t\tcheckAttribute.subFieldID = subFieldID;\n\t\tcheckAttribute.dataValue = ( void * ) data;\n\t\tcheckAttribute.dataValueLength = dataLength;\n\t\tINIT_FLAGS( checkAttribute.flags, flags );\n\t\tcheckAttribute.fieldType = attributeInfoPtr->fieldType;\n\t\tDATAPTR_SET( checkAttribute.next, NULL );\n\t\tDATAPTR_SET( checkAttribute.prev, NULL );\n\t\tENSURES( sanityCheckAttributePtr( &checkAttribute ) );\n\t\t*errorType = validationFunction( &checkAttribute );\n\t\tif( *errorType != CRYPT_ERRTYPE_NONE )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the location in the attribute list at which to insert a new attribute \n   field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int findFieldInsertLocation( IN_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t\t\t\t\tOUT_PTR_COND ATTRIBUTE_LIST **insertPointPtrPtr,\n\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID )\n\t{\n\tconst ATTRIBUTE_LIST *insertPoint, *prevElement = NULL;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( insertPointPtrPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( ( subFieldID == CRYPT_ATTRIBUTE_NONE ) || \\\n\t\t\t  ( isValidExtension( fieldID ) ) );\n\n\t/* Clear return value */\n\t*insertPointPtrPtr = NULL;\n\n\t/* Find the location at which to insert this attribute field in a list \n\t   sorted in order of fieldID.  Normally we use a LOOP_MAX(), however \n\t   RPKI certificates, which are general-purpose certificates turned into \n\t   pseudo-attribute certificates with monstrous lists of capabilities, \n\t   can have much larger upper bounds.  To handle these we have to make a \n\t   special exception for the upper bound of the loop sanity check */\n#ifdef USE_RPKI\n\tLOOP_EXT_INITCHECK( insertPoint = DATAPTR_GET( attributePtr ), \n\t\t\t\t\t\tinsertPoint != NULL && \\\n\t\t\t\t\t\t\tinsertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\t\tinsertPoint->fieldID <= fieldID,\n\t\t\t\t\t\tFAILSAFE_ITERATIONS_LARGE * 10 )\n#else\n\tLOOP_LARGE_INITCHECK( insertPoint = DATAPTR_GET( attributePtr ), \n\t\t\t\t\t\t  insertPoint != NULL && \\\n\t\t\t\t\t\t\tinsertPoint->fieldID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\t\tinsertPoint->fieldID <= fieldID )\n#endif /* USE_RPKI */\n\t\t{\n\t\tconst ATTRIBUTE_LIST *insertPointNext = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( insertPoint->next );\n\n\t\tREQUIRES( sanityCheckAttributePtr( insertPoint ) );\n\t\tENSURES( insertPointNext == NULL || \\\n\t\t\t\t !isValidAttributeField( insertPointNext ) || \\\n\t\t\t\t insertPoint->attributeID <= insertPointNext->attributeID );\n\n\t\t/* If it's a composite field that can have multiple fields with the \n\t\t   same field ID (e.g. a GeneralName), exit if the overall field ID \n\t\t   is greater (which means that the component belongs to a different \n\t\t   field entirely) or if the field ID is the same and the subfield \n\t\t   ID is greater (which means that the component belongs to a \n\t\t   different subfield within the field) */\n\t\tif( subFieldID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\tinsertPoint->fieldID == fieldID && \\\n\t\t\tinsertPoint->subFieldID > subFieldID )\n\t\t\tbreak;\n\n\t\tprevElement = insertPoint;\n\t\tinsertPoint = insertPointNext;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*insertPointPtrPtr = ( ATTRIBUTE_LIST * ) prevElement;\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd Attribute Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a blob-type attribute to a list of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 6 ) ) \\\nint addAttribute( IN_ATTRIBUTE const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t  INOUT DATAPTR_ATTRIBUTE *listHeadPtr, \n\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t  IN_LENGTH_OID const int oidLength,\n\t\t\t\t  const BOOLEAN critical, \n\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t  IN_FLAGS_Z( ATTR ) const int flags )\n\t{\n\tDATAPTR_ATTRIBUTE listHead = *listHeadPtr;\n\tATTRIBUTE_LIST *newElement, *insertPoint = NULL;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( ATTRIBUTE_LIST * ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( ( flags & ( ATTR_FLAG_IGNORED | ATTR_FLAG_BLOB ) ) || \\\n\t\t\tcryptStatusOK( checkCertObjectEncoding( data, dataLength ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\tREQUIRES( attributeType == ATTRIBUTE_CERTIFICATE || \\\n\t\t\t  attributeType == ATTRIBUTE_CMS );\n\tREQUIRES( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE && \\\n\t\t\t  oidLength == sizeofOID( oid ) );\n\tREQUIRES( critical == TRUE || critical == FALSE );\n#ifdef USE_RPKI\n\tREQUIRES( data != NULL && isShortIntegerRangeNZ( dataLength ) );\n#else\n\tREQUIRES( data != NULL && \\\n\t\t\t  dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE );\n#endif /* USE_RPKI */\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_IGNORED | ATTR_FLAG_BLOB | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( flags == ATTR_FLAG_NONE || flags == ATTR_FLAG_BLOB || \\\n\t\t\t  flags == ( ATTR_FLAG_BLOB | ATTR_FLAG_IGNORED ) );\n\n\t/* If this attribute type is already handled as a non-blob attribute,\n\t   don't allow it to be added as a blob as well.  This avoids problems\n\t   with the same attribute being added twice, once as a blob and once as\n\t   a non-blob.  In addition it forces the caller to use the (recommended)\n\t   normal attribute handling mechanism, which allows for proper type\n\t   checking */\n\tif( !( flags & ATTR_FLAG_BLOB ) && \\\n\t\toidToAttribute( attributeType, oid, oidLength ) != NULL )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Find the correct place in the list to insert the new element */\n\tif( DATAPTR_ISSET( listHead ) )\n\t\t{\n\t\tATTRIBUTE_LIST *prevElement = NULL;\n\t\tint LOOP_ITERATOR;\n\n\t\tLOOP_LARGE( insertPoint = DATAPTR_GET( listHead ), \n\t\t\t\t\tinsertPoint != NULL, \n\t\t\t\t\tinsertPoint = DATAPTR_GET( insertPoint->next ) )\n\t\t\t{\n\t\t\tREQUIRES( sanityCheckAttributePtr( insertPoint ) );\n\n\t\t\t/* Make sure that this blob attribute isn't already present */\n\t\t\tif( checkAttributeListProperty( insertPoint, \n\t\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) && \\\n\t\t\t\toidLength == sizeofOID( insertPoint->oid ) && \\\n\t\t\t\t!memcmp( insertPoint->oid, oid, oidLength ) )\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\t\tprevElement = insertPoint;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tinsertPoint = prevElement;\n\t\t}\n\n\t/* Allocate memory for the new element and copy the information across.  \n\t   The data is stored in storage ... storage + dataLength, the OID in\n\t   storage + dataLength ... storage + dataLength + oidLength */\n\tREQUIRES( rangeCheck( dataLength, 1, MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( rangeCheck( oidLength, MIN_OID_SIZE, MAX_OID_SIZE ) );\n\tif( ( newElement = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t   clAlloc( \"addAttribute\", sizeof( ATTRIBUTE_LIST ) + \\\n\t\t\t\t\t\t\t\t\t\t\t\tdataLength + oidLength ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tinitVarStruct( newElement, ATTRIBUTE_LIST, dataLength + oidLength, dataValue );\n\tnewElement->oid = newElement->storage + dataLength;\n\tmemcpy( newElement->oid, oid, oidLength );\n\tINIT_FLAGS( newElement->flags,\n\t\t\t\t( flags & ATTR_FLAG_IGNORED ) | \\\n\t\t\t\t( critical ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE ) );\n\tmemcpy( newElement->dataValue, data, dataLength );\n\tnewElement->dataValueLength = dataLength;\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\tENSURES( sanityCheckAttributePtr( newElement ) );\n\tinsertDoubleListElement( listHeadPtr, insertPoint, newElement, \n\t\t\t\t\t\t\t ATTRIBUTE_LIST );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add an attribute field to a list of attributes at the appropriate \n   location */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6, 7 ) ) \\\nint addAttributeField( INOUT DATAPTR_ATTRIBUTE *listHeadPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t   IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t   const int value,\n\t\t\t\t\t   IN_FLAGS_Z( ATTR ) const int flags, \n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst ATTRIBUTE_TYPE attributeType = \\\n\t\t\t\t\t\t\t( fieldID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\tDATAPTR_ATTRIBUTE listHead = *listHeadPtr;\n\tATTRIBUTE_LIST *newElement, *insertPoint;\n\tint status;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\nassert( ( flags & ~( ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED | ATTR_FLAG_BLOB_PAYLOAD ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Check the field's validity */\n\tattributeInfoPtr = fieldIDToAttribute( attributeType, fieldID, subFieldID, \n\t\t\t\t\t\t\t\t\t\t   &attributeID );\n\tREQUIRES( attributeInfoPtr != NULL );\n\tstatus = checkAttributeField( listHead, attributeInfoPtr, fieldID, \n\t\t\t\t\t\t\t\t  subFieldID, value, flags, errorType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( *errorType != CRYPT_ERRTYPE_NONE )\n\t\t\t{\n\t\t\t/* If we encountered an error that sets the error type, record \n\t\t\t   the locus as well */\n\t\t\t*errorLocus = fieldID;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* Find the location at which to insert this attribute field */\n\tstatus = findFieldInsertLocation( listHead, &insertPoint, fieldID, \n\t\t\t\t\t\t\t\t\t  subFieldID );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Allocate memory for the new element and copy the information across */\n\tif( ( newElement = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t   clAlloc( \"addAttributeField\", \\\n\t\t\t\t\t\t\t\tsizeof( ATTRIBUTE_LIST ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( newElement, 0, sizeof( ATTRIBUTE_LIST ) );\n\tnewElement->attributeID = attributeID;\n\tnewElement->fieldID = fieldID;\n\tnewElement->subFieldID = subFieldID;\n\tINIT_FLAGS( newElement->flags, flags );\n\tnewElement->fieldType = attributeInfoPtr->fieldType;\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\tswitch( attributeInfoPtr->fieldType )\n\t\t{\n\t\tcase BER_BOOLEAN:\n\t\t\t/* Force it to the correct type if it's a boolean */\n\t\t\tnewElement->intValue = value ? TRUE : FALSE;\n\t\t\tbreak;\n\n\t\tcase BER_INTEGER:\n\t\tcase BER_ENUMERATED:\n\t\tcase BER_BITSTRING:\n\t\tcase BER_NULL:\n\t\t\tnewElement->intValue = value;\n\t\t\tbreak;\n\n\t\tcase FIELDTYPE_CHOICE:\n\t\t\t/* The value for a CHOICE is used to select an entry within a \n\t\t\t   subtype table rather than being encoded directly, see the\n\t\t\t   comments in checkAttributeEntry() for details */\n\t\t\tREQUIRES( value > 0 && value < 100 );\n\t\t\tnewElement->intValue = value;\n\t\t\tbreak;\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t/* This type is present in both addAttributeField() and \n\t\t\t   addAttributeFieldString(), when creating a new certificate \n\t\t\t   this is a placeholder to indicate that a DN structure is being \n\t\t\t   instantiated (value == CRYPT_UNUSED) and when reading an \n\t\t\t   encoded certificate this is the decoded DN structure \n\t\t\t   (data == DATAPTR_DN) */\n\t\t\tDATAPTR_SET( newElement->dnValue, NULL );\n\t\t\tENSURES( value == CRYPT_UNUSED );\n\t\t\tbreak;\n\n\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\t/* This is a placeholder entry with no explicit value */\n\t\t\tnewElement->intValue = CRYPT_UNUSED;\n\t\t\tbreak;\n\n\t\t}\n\tENSURES( sanityCheckAttributePtr( newElement ) );\n\tinsertDoubleListElement( listHeadPtr, insertPoint, newElement, \n\t\t\t\t\t\t\t ATTRIBUTE_LIST );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 7, 8 ) ) \\\nint addAttributeFieldString( INOUT DATAPTR_ATTRIBUTE *listHeadPtr,\n\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subFieldID,\n\t\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t IN_LENGTH_ATTRIBUTE const int dataLength,\n\t\t\t\t\t\t\t IN_FLAGS_Z( ATTR ) const int flags, \n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst ATTRIBUTE_TYPE attributeType = \\\n\t\t\t\t\t\t\t( fieldID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\tDATAPTR_ATTRIBUTE listHead = *listHeadPtr;\n\tATTRIBUTE_LIST *newElement, *insertPoint;\n\tint storageSize = 0, newDataLength, status;\n\n\tassert( isWritePtr( listHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( listHead ) );\n\tREQUIRES( isValidExtension( fieldID ) );\n\tREQUIRES( subFieldID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t  ( subFieldID >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\tsubFieldID <= CRYPT_CERTINFO_LAST_GENERALNAME ) );\n\tREQUIRES( dataLength > 0 && dataLength <= MAX_ATTRIBUTE_SIZE );\nassert( ( flags & ~( ATTR_FLAG_BLOB_PAYLOAD | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Check the field's validity */\n\tattributeInfoPtr = fieldIDToAttribute( attributeType, fieldID, subFieldID, \n\t\t\t\t\t\t\t\t\t\t   &attributeID );\n\tREQUIRES( attributeInfoPtr != NULL );\n\tstatus = checkAttributeFieldString( listHead, attributeInfoPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\tsubFieldID, data, dataLength, flags, \n\t\t\t\t\t\t\t\t\t\t&newDataLength, errorType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( *errorType != CRYPT_ERRTYPE_NONE )\n\t\t\t{\n\t\t\t/* If we encountered an error that sets the error type, record \n\t\t\t   the locus as well */\n\t\t\t*errorLocus = fieldID;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* Find the location at which to insert this attribute field */\n\tstatus = findFieldInsertLocation( listHead, &insertPoint, fieldID, \n\t\t\t\t\t\t\t\t\t  subFieldID );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Allocate memory for the new element and copy the information across */\n\tif( newDataLength != 0 )\n\t\t{\n\t\tREQUIRES( attributeInfoPtr->fieldType == BER_OBJECT_IDENTIFIER );\n\n\t\t/* The length has changed due to data en/decoding, use the \n\t\t   en/decoded length for the storage size */\n\t\tstorageSize = newDataLength;\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's not a DN pointer then we copy the data in as is */\n\t\tif( attributeInfoPtr->fieldType != FIELDTYPE_DN )\n\t\t\tstorageSize = dataLength;\n\t\t}\n\tREQUIRES( storageSize == 0 || \\\n\t\t\t  rangeCheck( storageSize, 1, MAX_ATTRIBUTE_SIZE ) );\n\tif( ( newElement = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t   clAlloc( \"addAttributeField\", sizeof( ATTRIBUTE_LIST ) + \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t storageSize ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tinitVarStruct( newElement, ATTRIBUTE_LIST, storageSize, dataValue );\n\tnewElement->attributeID = attributeID;\n\tnewElement->fieldID = fieldID;\n\tnewElement->subFieldID = subFieldID;\n\tINIT_FLAGS( newElement->flags, flags );\n\tnewElement->fieldType = attributeInfoPtr->fieldType;\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\tswitch( attributeInfoPtr->fieldType )\n\t\t{\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\t/* If it's a BER/DER-encoded OID copy it in as is, otherwise \n\t\t\t   convert it from the text form */\n\t\t\tif( ( ( BYTE * ) data )[ 0 ] == BER_OBJECT_IDENTIFIER )\n\t\t\t\t{\n\t\t\t\tmemcpy( newElement->dataValue, data, dataLength );\n\t\t\t\tnewElement->dataValueLength = dataLength;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = textToOID( data, dataLength, newElement->dataValue, \n\t\t\t\t\t\t\t\t\tstorageSize, \n\t\t\t\t\t\t\t\t\t&newElement->dataValueLength );\n\t\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t{\n\t\t\tDATAPTR_DN dn = *( ( DATAPTR_DN  * ) data );\n\n\t\t\tREQUIRES( DATAPTR_ISSET( dn ) );\n\n\t\t\t/* This type is present in both addAttributeField() and \n\t\t\t   addAttributeFieldString(), when creating a new certificate \n\t\t\t   this is a placeholder to indicate that a DN structure is being \n\t\t\t   instantiated (value == CRYPT_UNUSED) and when reading an \n\t\t\t   encoded certificate this is the decoded DN structure \n\t\t\t   (data == DATAPTR_DN *) */\n\t\t\tnewElement->dnValue = dn;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tmemcpy( newElement->dataValue, data, dataLength );\n\t\t\tnewElement->dataValueLength = dataLength;\n\t\t\tbreak;\n\t\t}\n\tENSURES( sanityCheckAttributePtr( newElement ) );\n\tinsertDoubleListElement( listHeadPtr, insertPoint, newElement, \n\t\t\t\t\t\t\t ATTRIBUTE_LIST );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete Attribute Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an attribute/attribute field from a list of attributes, updating\n   the list DN cursor at the same time.  This is a somewhat ugly kludge, \n   it's not really possible to do this cleanly since deleting attributes \n   affects the attribute and DN cursors as well */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteAttributeField( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t  INOUT_OPT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t  INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t\t  INOUT_OPT DATAPTR_DN *dnCursor )\n\t{\n\tconst DATAPTR_ATTRIBUTE cursor = ( cursorPtr == NULL ) ? \\\n\t\t\t\t\t\t\t\t\t DATAPTR_NULL : *cursorPtr;\n\tATTRIBUTE_LIST *listItemPtr;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( cursorPtr == NULL || \\\n\t\t\tisWritePtr( cursorPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( dnCursor == NULL || \\\n\t\t\tisReadPtr( dnCursor, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( cursor ) );\n\tREQUIRES( DATAPTR_ISSET( listItem ) );\n\n\tlistItemPtr = DATAPTR_GET( listItem );\n\tREQUIRES( listItemPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( listItemPtr ) );\n\n\t/* If we're about to delete the field that's pointed to by the attribute \n\t   cursor, advance the cursor to the next field.  If there's no next \n\t   field, move it to the previous field.  This behaviour is the most\n\t   logically consistent, it means that we can do things like deleting an\n\t   entire attribute list by repeatedly deleting a field */\n\tif( DATAPTR_ISSET( cursor ) && DATAPTR_SAME( cursor, listItem ) )\n\t\t{\n\t\tANALYSER_HINT( cursorPtr != NULL );\t/* From DATAPTR_ISSET( cursor ) */\n\n\t\tif( DATAPTR_ISSET( listItemPtr->next ) )\n\t\t\t*cursorPtr = listItemPtr->next;\n\t\telse\n\t\t\t*cursorPtr = listItemPtr->prev;\n\t\t}\n\n\t/* Remove the item from the list */\n\tdeleteDoubleListElement( attributePtr, listItemPtr, ATTRIBUTE_LIST );\n\n\t/* Clear all data in the item and free the memory */\n\tif( listItemPtr->fieldType == FIELDTYPE_DN )\n\t\t{\n\t\tconst DATAPTR_ATTRIBUTE dn = ( dnCursor == NULL ) ? \\\n\t\t\t\t\t\t\t\t\t DATAPTR_NULL : *dnCursor;\n\t\tDATAPTR_ATTRIBUTE listItemDN = GET_DN_POINTER( listItemPtr );\n\n\t\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\t\tREQUIRES( DATAPTR_ISVALID( listItemDN ) );\n\n\t\t/* If we've deleted the DN at the current cursor position, clear the\n\t\t   DN cursor */\n\t\tif( DATAPTR_ISSET( dn ) && DATAPTR_SAME( dn, listItemDN ) )\n\t\t\t{\n\t\t\tANALYSER_HINT( dnCursor != NULL );\t/* From DATAPTR_ISSET( dn ) */\n\n\t\t\tDATAPTR_SET_PTR( dnCursor, NULL );\n\t\t\t}\n\t\tdeleteDN( &listItemDN );\n\t\t}\n\tendVarStruct( listItemPtr, ATTRIBUTE_LIST );\n\tclFree( \"deleteAttributeField\", listItemPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteCompositeAttributeField( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t\t\t\t   INOUT DATAPTR_DN *dnCursor )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeID, fieldID;\n\tDATAPTR_ATTRIBUTE attribute = *attributePtr;\n\tconst DATAPTR_ATTRIBUTE cursor = ( cursorPtr == NULL ) ? \\\n\t\t\t\t\t\t\t\t\t DATAPTR_NULL : *cursorPtr;\n\tATTRIBUTE_LIST *listItemPtr, *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( cursorPtr == NULL || \\\n\t\t\tisWritePtr( cursorPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( dnCursor == NULL || \\\n\t\t\tisReadPtr( dnCursor, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attribute ) );\n\tREQUIRES( DATAPTR_ISVALID( cursor ) );\n\tREQUIRES( DATAPTR_ISSET( listItem ) );\n\n\tlistItemPtr = DATAPTR_GET( listItem );\n\tREQUIRES( listItemPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( listItemPtr ) );\n\tattributeID = listItemPtr->attributeID;\n\tfieldID = listItemPtr->fieldID;\n\n\t/* Delete an attribute field that contains one or more entries of a \n\t   subfield.  This is typically used with GeneralName fields, where the \n\t   fieldID for the GeneralName is further divided into DN, URI, email \n\t   address, and so on, subfields */\n\tLOOP_MED_INITCHECK( attributeListCursor = listItemPtr, \n\t\t\t\t\t\tattributeListCursor != NULL && \\\n\t\t\t\t\t\t\tattributeListCursor->attributeID == attributeID && \\\n\t\t\t\t\t\t\tattributeListCursor->fieldID == fieldID )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE itemToFree;\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\n\t\tDATAPTR_SET( itemToFree, attributeListCursor );\n\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next );\n\t\tstatus = deleteAttributeField( attributePtr, cursorPtr, itemToFree, \n\t\t\t\t\t\t\t\t\t   dnCursor );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteAttribute( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE listItem,\n\t\t\t\t\t INOUT DATAPTR_DN *dnCursor )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\tconst ATTRIBUTE_LIST *listItemPtr, *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( cursorPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( dnCursor, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( listItem ) );\n\n\t/* If it's a blob-type attribute, everything is contained in this one\n\t   list item so we only need to destroy that */\n\tif( checkAttributeProperty( listItem, ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\treturn( deleteAttributeField( attributePtr, cursorPtr, listItem, \n\t\t\t\t\t\t\t\t\t  NULL ) );\n\t\t}\n\n\t/* Complete attributes should be deleted with deleteCompleteAttribute() */\n\tassert( !checkAttributeProperty( listItem, \n\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_COMPLETEATRIBUTE ) );\n\n\t/* Find the start of the fields in this attribute */\n\tlistItemPtr = DATAPTR_GET( listItem );\n\tENSURES( listItemPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( listItemPtr ) );\n\tattributeListCursor = findAttributeStart( listItemPtr );\n\tENSURES( attributeListCursor != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\tattributeID = attributeListCursor->attributeID;\n\n\t/* It's an item with multiple fields, destroy each field separately */\n\tLOOP_LARGE_CHECK( attributeListCursor != NULL && \\\n\t\t\t\t\t  attributeListCursor->attributeID == attributeID )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE itemToFree;\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\n\t\tDATAPTR_SET( itemToFree, ( ATTRIBUTE_LIST * ) attributeListCursor );\n\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next );\n\t\tstatus = deleteAttributeField( attributePtr, cursorPtr, itemToFree, \n\t\t\t\t\t\t\t\t\t   dnCursor );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint deleteCompleteAttribute( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE *cursorPtr,\n\t\t\t\t\t\t\t const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t INOUT DATAPTR_DN *dnCursor )\n\t{\n\tDATAPTR_ATTRIBUTE attribute = *attributePtr, listItem;\n\tconst DATAPTR_ATTRIBUTE cursor = ( cursorPtr == NULL ) ? \\\n\t\t\t\t\t\t\t\t\t DATAPTR_NULL : *cursorPtr;\n\tATTRIBUTE_LIST *attributeListCursor, *attributeListCursorNext;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( cursorPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtr( dnCursor, sizeof( DATAPTR_DN ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( attribute ) );\n\tREQUIRES( DATAPTR_ISVALID( cursor ) );\n\tREQUIRES( isValidExtension( attributeID ) );\n\n\t/* We're deleting an entire (constructed) attribute that won't have an \n\t   entry in the list so we find the first field of the constructed \n\t   attribute that's present in the list and delete that */\n\tLOOP_LARGE( attributeListCursor = DATAPTR_GET( attribute ), \n\t\t\t\tattributeListCursor != NULL && \\\n\t\t\t\t\tattributeListCursor->attributeID != attributeID,\n\t\t\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( attributeListCursor != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\tattributeListCursorNext = DATAPTR_GET( attributeListCursor->next );\n\tENSURES( attributeListCursorNext == NULL || \\\n\t\t\t attributeListCursorNext->attributeID != \\\n\t\t\t\t\t\t\t\tattributeListCursor->attributeID );\n\tDATAPTR_SET( listItem, attributeListCursor );\n\treturn( deleteAttributeField( attributePtr, cursorPtr, listItem, \n\t\t\t\t\t\t\t\t  dnCursor ) );\n\t}\n\n/* Delete a complete set of attributes */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteAttributes( INOUT DATAPTR_ATTRIBUTE *attributePtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributeCursor = *attributePtr;\n\tATTRIBUTE_LIST *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES_V( DATAPTR_ISVALID( attributeCursor ) );\n\n\t/* If the list was empty, return now */\n\tif( DATAPTR_ISNULL( attributeCursor ) )\n\t\treturn;\n\n\t/* Destroy any remaining list items.  See the comment in \n\t   findFieldInsertLocation() for the RPKI loop bound */\n#ifdef USE_RPKI\n\tLOOP_EXT_INITCHECK( attributeListCursor = DATAPTR_GET( attributeCursor ),\n\t\t\t\t\t\tattributeListCursor != NULL, \n\t\t\t\t\t\tFAILSAFE_ITERATIONS_LARGE * 10 )\n#else\n\tLOOP_LARGE_INITCHECK( attributeListCursor = DATAPTR_GET( attributeCursor ),\n\t\t\t\t\t\t  attributeListCursor != NULL )\n#endif /* USE_RPKI */\n\t\t{\n\t\tDATAPTR_ATTRIBUTE itemToFree;\n\n\t\tREQUIRES_V( sanityCheckAttributePtr( attributeListCursor ) );\n\n\t\tDATAPTR_SET( itemToFree, ( ATTRIBUTE_LIST * ) attributeListCursor );\n\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next );\n\t\t( void ) deleteAttributeField( attributePtr, NULL, itemToFree, NULL );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( DATAPTR_ISNULL_PTR( attributePtr ) );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_chk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Attribute Checking Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2018\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/* Validate and preprocess a set of attributes and set up links to the \n   information in the attribute information table in preparation for \n   encoding the attribute.  This is a rather complex process that relies on \n   stepping through the list of attribute fields and the attribute \n   information table in sync and making sure that the list of fields is \n   consistent with the attribute information table.  In addition we set up \n   synchronisation points between the list and table that are used during \n   the encoding process.  For example assume that we have the following \n   attribute:\n\n\tattribute ::= SEQUENCE {\n\t\tfoo\t\tBOOLEAN DEFAULT TRUE,\n\t\tbar\t\tSEQUENCE OF OBJECT IDENTIFIER\n\t\t}\n\n   The attribute information table would encode this attribute as:\n\n\tt1:\tOID\tSEQUENCE\n\tt2:\t\tBOOLEAN\t\tOPTIONAL\n\tt3:\t\tSEQUENCE\n\tt4:\t\tOID\t\t\tEND\n\n   The first table entry t1 contains the OID and the SEQUENCE wrapper.  For \n   the purposes of comparison with the list this is a no-op and can be \n   skipped since it's only used for encoding purposes.  The next table entry \n   t2 contains the first attribute field, an optional boolean.  The next \n   table entry t3 contains another SEQUENCE wrapper that again is only used \n   for encoding and can be skipped for comparing with the list.  Finally, \n   the last table entry t4 contains the second attribute field, an OID, and \n   the end-of-attribute flag.\n\n   Assuming that the attribute list contains the following:\n\n\tBOOLEAN\tFALSE\t-> t1\n\tOID\t\txxx\t\t-> t3\n\n   The attribute validation process sets the synchronisation point for the \n   first attribute list entry to point to t1 and the second one to point to \n   t3.  When we encode the attribute we encode t1 (the OID, critical flag, \n   and SEQUENCE wrapper) and then since the field IDs won't match we step on \n   to t2 and use that to encode the boolean.  We then do the same for t3 \n   with the SEQUENCE and OID.\n\n   If the attribute list instead contained only:\n\n\tOID\t\txxx\t\t-> t1\n\n   then this time the attribute validation process sets the synchronisation \n   point to t1.  When encoding we encode t1 as before, step to t2, the field \n   IDs won't match but t2 is optional so we skip it, then encode t3 as for \n   t1 and finally encode the OID using t4.\n\n   At this point we also evaluate the encoded size of each attribute.  For\n   invidual fields we just store their encoded size.  For constructed \n   objects we stack the attribute list entry where the constructed object\n   starts and, until we reach the end of the constructed object, accumulate\n   the total size of the fields that make up the object.  When we reach the\n   end of the object we unstack the pointer to the attribute list and store\n   the total size in it.\n\n   To handle nested constructed objects we only update the size of the\n   topmost item on the stack.  When this is unstacked we add the size of \n   that entry plus the size of its tag and length information to the next\n   entry on the stack.\n\n   In addition to updating the size we also record the sequence of table\n   entries that are required to encode the constructed item.  A worst-case\n   sequence of entries would be:\n\n\tSEQUENCE {\n\t\tSEQUENCE OPTIONAL { ... }\t\t| Not encoded\n\t\tSEQUENCE {\n\t\t\tSEQUENCE OPTIONAL { ... }\t| Not encoded\n\t\t\tSEQUENCE {\n\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n   which contains an alternating sequence of encoded and non-encoded fields.\n   Because of this the validation check performs the complex task of\n   recording which table entries are used for the encoding by stacking and\n   unstacking them and discarding the ones that evaluate to a zero size\n   during the unstacking process */\n\n/* Define the following to print a trace of the certificate fields being \n   checked */\n\n#if !defined( NDEBUG ) && 0\n  #define TRACE_FIELDTYPE( attributeInfoPtr ) \\\n\t\t  { \\\n\t\t  if( ( attributeInfoPtr ) != NULL && \\\n\t\t\t  ( attributeInfoPtr )->description != NULL ) \\\n\t\t\t  DEBUG_PUTS(( ( attributeInfoPtr )->description )); \\\n\t\t  else \\\n\t\t\t  DEBUG_PUTS(( \"<Unrecognised attribute>\" )); \\\n\t\t  }\n  #define TRACE_DEBUG( message ) \\\n\t\t  DEBUG_PRINT( message )\n#else\n  #define TRACE_FIELDTYPE( attributeInfoPtr )\n  #define TRACE_DEBUG( message )\n#endif /* NDEBUG */\n\n/* State machine for checking a CHOICE.  When we get to the start of a\n   CHOICE we move from CHOICE_NONE to CHOICE_START.  Once we've checked one\n   of the CHOICE options we move to CHOICE_DONE.  If a further option is\n   found in the CHOICE_DONE state we record an error.  This is a somewhat\n   crude mechanism that works because the only CHOICE fields that can't be\n   handled by rewriting them as alternative representations are complete\n   attributes so that the CHOICE applies over the entire attribute.  If a\n   CHOICE is ever present as an attribute subfield then the checking would \n   be handled by recursively checking it as a subtyped field */\n\ntypedef enum { CHOICE_NONE, CHOICE_START, CHOICE_DONE, \n\t\t\t   CHOICE_LAST } CHOICE_STATE;\n\n/* The attribute parsing state stack.  Each entry in the stack contains the \n   list item that it applies to, the table entry which is used to encode the \n   stacked item, and the size of the item.  We don't bother making these\n   safe pointers because they've live only as long as standard stack-based\n   pointers */\n\n#define ATTRIBUTE_STACKSIZE\t\t10\n\ntypedef struct {\n\tATTRIBUTE_LIST *attributeListPtr;\t/* List entry that this applies to */\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\t/* Encoding point for sequence */\n\tint size;\t\t\t\t\t\t\t/* Size of sequence */\n\t} ATTRIBUTE_STACK;\n\n/* When we're performing a check of an attribute we need to pass a lot of \n   state information around, this is contained in the following \n   structure.  We don't bother making these safe pointers because they've \n   live only as long as standard stack-based pointers */\n\ntypedef struct {\n\t/* State information.  When we're encoding a subtyped field (using an\n\t   alternative encoding table) we need to remember the field ID of the\n\t   parent to both tell the encoding routines that we're using an\n\t   alternative encoding table and to remember the overall field ID so we\n\t   don't treat two adjacent field subfields as though they were part of\n\t   the same parent field.  If we're not currently encoding a subtyped\n\t   field, this field is set to CRYPT_ATTRIBUTE_NONE */\n\tATTRIBUTE_LIST *attributeListPtr;\t/* Position in attribute list */\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\t/* Position in attribute table */\n\tCRYPT_ATTRIBUTE_TYPE subtypeParent;\t/* Parent of subtype being processed */\n\tCHOICE_STATE choiceState;\t\t\t/* State of CHOICE processing */\n\n\t/* Encoding stack.  When we're encoding subfields the stack contains \n\t   items from both the subfield and the encapsulating field so we also\n\t   record a stack marker position that records how far we have to go \n\t   back when popping items after we've finished encoding a subfield */\n\tARRAY( ATTRIBUTE_STACKSIZE, stackPos ) \\\n\tATTRIBUTE_STACK stack[ ATTRIBUTE_STACKSIZE + 8 ];\n\tint stackPos;\t\t\t\t\t/* Encoding stack position */\n\tint stackMarkerPos;\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tint errorType;\t\t\t\t\t/* Error type */\n\t} ATTRIBUTE_CHECK_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the attribute check info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckAttributeCheckInfo( const ATTRIBUTE_CHECK_INFO *attributeCheckInfo )\n\t{\n\tassert( isReadPtr( attributeCheckInfo, sizeof( ATTRIBUTE_CHECK_INFO ) ) );\n\n\t/* Make sure that the state information is valid */\n\tif( attributeCheckInfo->attributeInfoPtr == NULL || \\\n\t\t( attributeCheckInfo->subtypeParent != CRYPT_ATTRIBUTE_NONE && \\\n\t\t  !isValidExtension( attributeCheckInfo->subtypeParent ) ) || \\\n\t\t( attributeCheckInfo->choiceState < CHOICE_NONE || \\\n\t\t  attributeCheckInfo->choiceState >= CHOICE_LAST ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttributeCheckInfo: State information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the stack is valid */\n\tif( attributeCheckInfo->stackPos < 0 || \\\n\t\tattributeCheckInfo->stackPos >= ATTRIBUTE_STACKSIZE || \\\n\t\tattributeCheckInfo->stackMarkerPos < 0 || \\\n\t\tattributeCheckInfo->stackMarkerPos > attributeCheckInfo->stackPos )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttributeCheckInfo: Stack information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the error information is valid */\n\tif( !isEnumRangeOpt( attributeCheckInfo->errorLocus, CRYPT_ATTRIBUTE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckAttributeCheckInfo: Error information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Stack Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Stack an item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int stackInfo( INOUT ATTRIBUTE_CHECK_INFO *attributeCheckInfo,\n\t\t\t\t\t  IN_OPT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t  const ATTRIBUTE_INFO *attributeInfoPtr )\n\t{\n\tATTRIBUTE_STACK *stack = attributeCheckInfo->stack;\n\n\tassert( isWritePtr( attributeCheckInfo, \\\n\t\t\t\t\t\tsizeof( ATTRIBUTE_CHECK_INFO ) ) );\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\tstack[ attributeCheckInfo->stackPos ].size = 0;\n\tstack[ attributeCheckInfo->stackPos ].attributeListPtr = attributeListPtr;\n\tstack[ attributeCheckInfo->stackPos++ ].attributeInfoPtr = attributeInfoPtr;\n\n\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Once we reach the end of the constructed item we need to unwind the stack\n   and update everything that we've gone past.  If it's an optional item (so \n   that nothing gets encoded) we don't do anything.  The count argument \n   specifies the level of unwinding to perform, this can be relative \n   (isRelative = TRUE, in which case we undo 'count' levels of nesting, which \n   may be more than 'count' stack positions if non-nested data was stacked) \n   or absolute (isRelative = FALSE, in which case we undo 'count' stack \n   positions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int updateStackedInfo( INOUT_ARRAY_C( ATTRIBUTE_STACKSIZE ) \\\n\t\t\t\t\t\t\t\tATTRIBUTE_STACK *stack, \n\t\t\t\t\t\t\t  IN_RANGE( 0, ATTRIBUTE_STACKSIZE - 1 ) \\\n\t\t\t\t\t\t\t\tconst int stackPos,\n\t\t\t\t\t\t\t  OUT_RANGE( 0, ATTRIBUTE_STACKSIZE - 1 ) \\\n\t\t\t\t\t\t\t\tint *newStackPosPtr,\n\t\t\t\t\t\t\t  IN_RANGE( 0, ATTRIBUTE_STACKSIZE - 1 ) int count, \n\t\t\t\t\t\t\t  const BOOLEAN isRelative )\n\t{\n\tint currentStackPos = stackPos, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stack, sizeof( ATTRIBUTE_STACK ) * \\\n\t\t\t\t\t\t\t   ATTRIBUTE_STACKSIZE ) );\n\tassert( isWritePtr( newStackPosPtr, sizeof( int ) ) );\n\n\tstatic_assert( ENCODING_FIFO_SIZE >= ATTRIBUTE_STACKSIZE, \\\n\t\t\t\t   \"Stack size\" );\n\n\tREQUIRES( stackPos >= 0 && stackPos < ATTRIBUTE_STACKSIZE );\n\tREQUIRES( count >= 0 && count <= stackPos );\n\tREQUIRES( isRelative == TRUE || isRelative == FALSE );\n\n\tLOOP_EXT_CHECKINC( count > 0, count--, ATTRIBUTE_STACKSIZE + 1 )\n\t\t{\n\t\tATTRIBUTE_LIST *attributeFifoPtr;\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tint size;\n\n\t\tENSURES( count > 0 && count <= currentStackPos );\n\n\t\t/* Unstack the current entry */\n\t\tcurrentStackPos--;\n\t\tENSURES( currentStackPos >= 0 && \\\n\t\t\t\t currentStackPos < ATTRIBUTE_STACKSIZE );\n\t\tattributeFifoPtr = stack[ currentStackPos ].attributeListPtr;\n\t\tattributeInfoPtr = stack[ currentStackPos ].attributeInfoPtr;\n\t\tsize = stack[ currentStackPos ].size;\n\t\tREQUIRES( attributeFifoPtr == NULL || \\\n\t\t\t\t  sanityCheckAttributePtr( attributeFifoPtr ) );\n\t\tENSURES( isIntegerRange( size ) );\n\n\t\tassert( attributeFifoPtr == NULL || \\\n\t\t\t\tisReadPtr( attributeFifoPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\t\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\t\t/* If there's nothing to encode, continue.  There are a few special \n\t\t   cases here where even if the sequence is of zero length we may \n\t\t   have to encode something.  Firstly, if there's a member with a \n\t\t   default value present (resulting in nothing being encoded) we \n\t\t   still have to encode a zero-length sequence.  In addition if all \n\t\t   of the members have non-encoding values (e.g. OIDs and fixed \n\t\t   attributes, none of which are specified by the user) then we have \n\t\t   to encode these even though there's no actual value associated \n\t\t   with them since their mere presence conveys the necessary \n\t\t   information.\n\n\t\t   In addition sometimes we can reach the end of the attribute list \n\t\t   but there are further actions defined in the encoding table (for \n\t\t   example cleanup actions in nested sequences).  In this case the \n\t\t   stacked attributeFifoPtr is NULL and the size is zero so we \n\t\t   perform an additional check to make sure that the pointer is \n\t\t   non-null */\n\t\tif( attributeFifoPtr == NULL )\n\t\t\t{\n\t\t\tENSURES( size == 0 );\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( size <= 0 && \\\n\t\t\t!( TEST_FLAG( attributeFifoPtr->flags, \n\t\t\t\t\t\t  ATTR_FLAG_DEFAULTVALUE ) || \\\n\t\t\t   ( attributeInfoPtr->encodingFlags & FL_NONENCODING ) ) )\n\t\t\tcontinue;\n\n\t\t/* Remember the size and table entry used to encode this stack \n\t\t   entry */\n\t\tattributeFifoPtr->sizeFifo[ attributeFifoPtr->fifoEnd ] = size;\n\t\tattributeFifoPtr->encodingFifo[ attributeFifoPtr->fifoEnd++ ] = \\\n\t\t\t\t\t\t\t\tstack[ currentStackPos ].attributeInfoPtr;\n\n\t\tENSURES( attributeFifoPtr->fifoEnd > 0 && \\\n\t\t\t\t attributeFifoPtr->fifoEnd < ENCODING_FIFO_SIZE );\n\n\t\t/* If there are no further items on the stack, continue */\n\t\tif( currentStackPos <= 0 )\n\t\t\tcontinue;\n\n\t\tENSURES( currentStackPos > 0 && \\\n\t\t\t\t currentStackPos < ATTRIBUTE_STACKSIZE );\n\n\t\t/* If it's a non-constructed field, add the length of the existing and\n\t\t   new fields */\n\t\tif( attributeInfoPtr->fieldType != BER_SEQUENCE && \\\n\t\t\tattributeInfoPtr->fieldType != BER_SET )\n\t\t\t{\n\t\t\tint newLength;\n\n\t\t\t/* Calculate the size of the encoded field data.  A sequence of\n\t\t\t   identifier fields has a final catch-all entry without an OID \n\t\t\t   which is only used for decoding, we should never see this \n\t\t\t   when encoding but we make the check explicit just in case */\n\t\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )\n\t\t\t\t{\n\t\t\t\tENSURES( attributeInfoPtr->oid != NULL );\n\t\t\t\tnewLength = sizeofOID( attributeInfoPtr->oid );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tnewLength = attributeInfoPtr->defaultValue;\n\n\t\t\t/* Add the new length to the existing data size.  Since this is a\n\t\t\t   non-constructed field it doesn't count as a reduction in the\n\t\t\t   nesting level so if we're unnesting by a relative amount we \n\t\t\t   adjust the nesting count to give a net change of zero for this\n\t\t\t   item */\n\t\t\tstack[ currentStackPos - 1 ].size += size + newLength;\n\t\t\tif( isRelative )\n\t\t\t\tcount++;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a constructed field, percolate the encapsulated content\n\t\t\t   size up the stack */\n\t\t\tstack[ currentStackPos - 1 ].size += sizeofShortObject( size );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t*newStackPosPtr = currentStackPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Field Type Checking\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some attributes contain a sequence of items of the attributeTypeAndValue \n   form (i.e. OID, ANY DEFINED BY OID).  To process these we check whether \n   the named value component in the attribute list is present in the current \n   attributeTypeAndValue definition.  If it isn't then the item is given a \n   zero length, which means that it's never encoded since the field is \n   marked as optional.  The following function checks whether a named value \n   component is present in the item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int checkComponentPresent( IN_RANGE( CRYPT_ATTRIBUTE_NONE + 1,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_LAST ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\t  INOUT ATTRIBUTE_INFO **attributeInfoPtrPtr )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr = *attributeInfoPtrPtr;\n\tint nestLevel = 0, noEntries, LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( isEnumRange( fieldID, CRYPT_ATTRIBUTE ) || \\\n\t\t\t  ( fieldID == CRYPT_IATTRIBUTE_LAST ) );\n\t\t\t  /* The latter is used when we've run out of values to match \n\t\t\t     and just want to skip to the end of the \n\t\t\t\t attributeTypeAndValue */\n\n\t/* Check each field that we find until we find the end of the\n\t   attributeTypeAndValue.  This is a bit of an awkward loop because\n\t   there's no direct loop structure, the loop control checks are\n\t   performed in the body of the loop.  Because of this we iterate on a\n\t   dummy variable noEntries in order to bound the loop.  In addition we \n\t   don't know how many attribute table entries are left so we have to \n\t   use the generic FAILSAFE_ITERATIONS_LARGE for the bounds check */\n\tLOOP_LARGE( noEntries = 0, noEntries < 500, noEntries++ )\n\t\t{\n\t\t/* Sanity check to make sure that we don't fall off the end of the \n\t\t   table */\n\t\tENSURES( !isAttributeTableEnd( attributeInfoPtr ) );\n\n\t\t/* Adjust the nesting level depending on whether we're entering or\n\t\t   leaving a sequence */\n\t\tif( attributeInfoPtr->fieldType == BER_SEQUENCE )\n\t\t\tnestLevel++;\n\t\tnestLevel -= decodeNestingLevel( attributeInfoPtr->encodingFlags );\n\n\t\t/* If the field is present in this attributeTypeAndValue, return */\n\t\tif( attributeInfoPtr->fieldID == fieldID )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If we're at the end of the attribute or the attributeTypeAndValue,\n\t\t   exit the loop before adjusting the attributeInfoPtr so that we're\n\t\t   still pointing at the end-of-attribute field */\n\t\tif( nestLevel <= 0 || \\\n\t\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\t\tbreak;\n\n\t\tattributeInfoPtr++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( noEntries < 500 );\n\n\t/* The field isn't present, update the pointer to the next\n\t   attributeTypeAndValue or the end of the attribute */\n\t*attributeInfoPtrPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr;\n\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAttribute Checking\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check an entry in the attribute table */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttribute( INOUT ATTRIBUTE_CHECK_INFO *attributeCheckInfo );\n\t\t\t\t\t\t   /* Forward declaration for function */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttributeEntry( INOUT ATTRIBUTE_CHECK_INFO *attributeCheckInfo,\n\t\t\t\t\t\t\t\tOUT BOOLEAN *skipStackUpdate )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr = attributeCheckInfo->attributeListPtr;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr = attributeCheckInfo->attributeInfoPtr;\n\tATTRIBUTE_STACK *stack = attributeCheckInfo->stack;\n\tCRYPT_ATTRIBUTE_TYPE fieldID;\n\n\tassert( isWritePtr( attributeCheckInfo, \\\n\t\t\t\t\t\tsizeof( ATTRIBUTE_CHECK_INFO ) ) );\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( stack, \\\n\t\t\t\t\t\tsizeof( ATTRIBUTE_STACK ) * ATTRIBUTE_STACKSIZE ) );\n\n\tREQUIRES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\tREQUIRES( attributeListPtr == NULL || \\\n\t\t\t  sanityCheckAttributePtr( attributeListPtr ) );\n\t\t\t  \n\t/* Clear return values */\n\t*skipStackUpdate = FALSE; \n\n\t/* Determine the fieldID for the current attribute field.  Once we get \n\t   to the end of an attribute list entry we may still run through this \n\t   function multiple times with attributeListPtr set to NULL but \n\t   attributeInfoPtr advancing on each step, see the comment in \n\t   updateStackedInfo() for details */\n\tif( attributeListPtr == NULL || \\\n\t\tattributeListPtr->fieldID == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\t/* If we've reached the end of the list of recognised attributes, \n\t\t   use a non-ID that doesn't match any table entry */\n\t\tfieldID = CRYPT_IATTRIBUTE_LAST;\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're encoding a subtyped field then the fieldID is the field \n\t\t   ID within the parent field, or the subFieldID.  However, for a \n\t\t   CHOICE type the value is a selection with a subtype table, for\n\t\t   example CRYPT_CONTENT_DATA within the contentTypeInfo, rather \n\t\t   than an attribute, so we have to use the attribute value as a\n\t\t   (pseudo-)fieldID to select the encoding table entry */\n\t\tif( attributeCheckInfo->subtypeParent == attributeListPtr->fieldID )\n\t\t\t{\n\t\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )\n\t\t\t\t{\n\t\t\t\tfieldID = attributeListPtr->intValue;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tfieldID = attributeListPtr->subFieldID;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a standard attribute field */\n\t\t\tfieldID = attributeListPtr->fieldID;\n\t\t\t}\n\t\t}\n\n\t/* If the field in the attribute list matches the one in the table,\n\t   process it and move on to the next one */\n\tif( attributeListPtr != NULL && attributeInfoPtr->fieldID == fieldID )\n\t\t{\n\t\tint size, status;\n\n\t\t/* If it's a subtyped or CHOICE field, check the components using\n\t\t   their own encoding table */\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED || \\\n\t\t\tattributeInfoPtr->fieldType == FIELDTYPE_CHOICE )\n\t\t\t{\n\t\t\tTRACE_DEBUG(( \"Switching to sub-field \" ));\n\t\t\tTRACE_FIELDTYPE( attributeCheckInfo->attributeInfoPtr );\n\n\t\t\t/* Switch to the new encoding table, record the fact that\n\t\t\t   we've done this, and set the new stack top to the level at\n\t\t\t   which we start encoding the subtype */\n\t\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )\n\t\t\t\t{\n\t\t\t\t/* Stack the value start position in the attribute list and\n\t\t\t\t   record the fact that we're processing a CHOICE */\n\t\t\t\tstatus = stackInfo( attributeCheckInfo, attributeListPtr,\n\t\t\t\t\t\t\t\t\tattributeInfoPtr );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tattributeCheckInfo->choiceState = CHOICE_START;\n\t\t\t\t}\n\t\t\tattributeCheckInfo->attributeInfoPtr = \\\n\t\t\t\t\t( const ATTRIBUTE_INFO * ) attributeInfoPtr->extraData;\n\t\t\tattributeCheckInfo->subtypeParent = attributeListPtr->fieldID;\n\t\t\tattributeCheckInfo->stackMarkerPos = attributeCheckInfo->stackPos;\n\t\t\tstatus = checkAttribute( attributeCheckInfo );\n\t\t\tattributeCheckInfo->attributeInfoPtr = attributeInfoPtr;\n\t\t\tattributeCheckInfo->subtypeParent = CRYPT_ATTRIBUTE_NONE;\n\t\t\tattributeCheckInfo->stackMarkerPos = 0;\n\t\t\tif( !( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) && \\\n\t\t\t\tattributeCheckInfo->attributeListPtr == attributeListPtr )\n\t\t\t\t{\n\t\t\t\t/* The subtyped field was non-optional but we failed to \n\t\t\t\t   match anything in it against the current attribute list \n\t\t\t\t   entry (meaning that the atributeListPtr in the check info\n\t\t\t\t   hasn't been advanced), there's a problem with the \n\t\t\t\t   encoding table.  This check is used to catch situations \n\t\t\t\t   where a subtyped field is used to encode a CHOICE for \n\t\t\t\t   which each CHOICE field is optional but at least one \n\t\t\t\t   component of the CHOICE must be present */\n\t\t\t\tretIntError();\n\t\t\t\t}\n\n\t\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If there's an extended validation function attached to this field,\n\t\t   call it */\n\t\tif( attributeInfoPtr->extraData != NULL )\n\t\t\t{\n\t\t\tVALIDATION_FUNCTION validationFunction = \\\n\t\t\t\t\t( VALIDATION_FUNCTION ) attributeInfoPtr->extraData;\n\n\t\t\tattributeCheckInfo->errorType = \\\n\t\t\t\t\t\t\t\t\tvalidationFunction( attributeListPtr );\n\t\t\tif( attributeCheckInfo->errorType != CRYPT_ERRTYPE_NONE )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* If this is an optional field and the value is the same as the\n\t\t   default value remember that it doesn't get encoded */\n\t\tif( ( attributeInfoPtr->encodingFlags & FL_DEFAULT ) && \\\n\t\t\t( attributeInfoPtr->defaultValue == attributeListPtr->intValue ) )\n\t\t\t{\n\t\t\tSET_FLAG( attributeListPtr->flags, ATTR_FLAG_DEFAULTVALUE );\n\t\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\t\tattributeCheckInfo->attributeListPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( attributeListPtr->next );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tTRACE_DEBUG(( \"Checking field \" ));\n\t\tTRACE_FIELDTYPE( attributeCheckInfo->attributeInfoPtr );\n\n\t\t/* Remember the encoded size of this field */\n\t\tattributeListPtr->attributeInfoPtr = attributeInfoPtr;\n\t\tstatus = size = sizeofAttributeField( attributeListPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tattributeListPtr->encodedSize = size;\n\t\tif( attributeCheckInfo->stackPos > 0 )\n\t\t\t{\n\t\t\tstack[ attributeCheckInfo->stackPos - 1 ].size += \\\n\t\t\t\t\t\t\t\t\t\tattributeListPtr->encodedSize;\n\t\t\t}\n\n\t\t/* If this is a CHOICE field update the choice state */\n\t\tif( attributeCheckInfo->choiceState != CHOICE_NONE )\n\t\t\t{\n\t\t\tif( attributeCheckInfo->choiceState == CHOICE_DONE )\n\t\t\t\t{\n\t\t\t\t/* If we've already processed one of the CHOICE options then \n\t\t\t\t   there can't be another one present */\n\t\t\t\tattributeCheckInfo->errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t}\n\t\t\tif( attributeCheckInfo->choiceState == CHOICE_START )\n\t\t\t\t{\n\t\t\t\t/* Remember that we've seen a CHOICE option */\n\t\t\t\tattributeCheckInfo->choiceState = CHOICE_DONE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Move on to the next attribute field */\n\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\tattributeCheckInfo->attributeListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( attributeListPtr->next );\n\n\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's an attributeTypeAndValue sequence, check whether it contains\n\t   the field that we want:\n\n\t\t\tt0:\tBER_SEQUENCE\tIDENTIFIER\n\t\t\tt1:\tOID\n\t\t  [ t2:\tparams\t\t\tNONENCODING ]\n\n\t   The initialisation sanity-check has already confirmed the validity of \n\t   the above format in the encoding table on startup */\n\tif( attributeInfoPtr->encodingFlags & FL_IDENTIFIER )\n\t\t{\n\t\tBOOLEAN endOfAttributeField = FALSE;\n\t\tint status;\n\n\t\tstatus = checkComponentPresent( fieldID, \n\t\t\t\t\t\t\t\t\t\t( ATTRIBUTE_INFO ** ) &attributeInfoPtr );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* Since we've jumped over several items we may be pointing at an\n\t\t\t   end-of-sequence flag for which no sequence start was stacked \n\t\t\t   so we skip the stack update step */\n\t\t\tattributeCheckInfo->attributeInfoPtr = attributeInfoPtr;\n\t\t\t*skipStackUpdate = TRUE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Stack the position of the sequence start and the following OID */\n\t\tstatus = stackInfo( attributeCheckInfo, attributeListPtr, \n\t\t\t\t\t\t\tattributeInfoPtr++ );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = stackInfo( attributeCheckInfo, attributeListPtr, \n\t\t\t\t\t\t\t\tattributeInfoPtr );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If the OID entry is marked as the end-of-sequence then there are \n\t\t   no parameters attached so we move on to the next entry */\n\t\tif( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK )\n\t\t\tendOfAttributeField = TRUE;\n\n\t\t/* Sometimes the OID is followed by a fixed-value blob field that\n\t\t   constitutes parameters for the OID, if this is present then we \n\t\t   stack it as well */\n\t\tif( attributeInfoPtr[ 1 ].encodingFlags & FL_NONENCODING )\n\t\t\t{\n\t\t\tattributeInfoPtr++;\n\t\t\tstatus = stackInfo( attributeCheckInfo, attributeListPtr, \n\t\t\t\t\t\t\t\tattributeInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* If the fields are fixed-value we always move on to the next\n\t\t\t   entry since there are no user-supplied parameters present */\n\t\t\tendOfAttributeField = TRUE;\n\t\t\t}\n\n\t\tattributeCheckInfo->attributeInfoPtr = attributeInfoPtr;\n\n\t\t/* If this is all that needs to be encoded move on to the next \n\t\t   attribute field */\n\t\tif( endOfAttributeField )\n\t\t\t{\n\t\t\tif( attributeListPtr == NULL )\n\t\t\t\tattributeCheckInfo->attributeListPtr = NULL;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\t\t\tattributeCheckInfo->attributeListPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( attributeListPtr->next );\n\t\t\t\t}\n\t\t\t}\n\n\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a SEQUENCE/SET or a non-encoding value then it's a no-op entry\n\t   used only for encoding purposes and can be skipped, however we need to\n\t   remember it for later encoding */\n\tif( attributeInfoPtr->fieldType == BER_SEQUENCE || \\\n\t\tattributeInfoPtr->fieldType == BER_SET || \\\n\t\tattributeInfoPtr->encodingFlags & FL_NONENCODING )\n\t\t{\n\t\tint status;\n\n\t\t/* Stack the sequence or value start position in the attribute list */\n\t\tstatus = stackInfo( attributeCheckInfo, attributeListPtr, \n\t\t\t\t\t\t\tattributeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a non-optional field and the attribute field doesn't match,\n\t   it's an error - attribute attributeID is missing field\n\t   attributeInfoPtr->fieldID (optional subfield\n\t   attributeInfoPtr->subFieldID) (set by the error handler in the calling\n\t   code) */\n\tif( !( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) )\n\t\t{\n\t\tattributeCheckInfo->errorType = CRYPT_ERRTYPE_ATTR_ABSENT;\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check an individual attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttribute( INOUT ATTRIBUTE_CHECK_INFO *attributeCheckInfo )\n\t{\n\tconst ATTRIBUTE_LIST *restartEntry = NULL;\n\tconst ATTRIBUTE_INFO *restartPoint = NULL;\n\tint restartStackPos = 0, noEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributeCheckInfo, \\\n\t\t\t\t\t\tsizeof( ATTRIBUTE_CHECK_INFO ) ) );\n\tassert( isReadPtr( attributeCheckInfo->attributeInfoPtr,\n\t\t\t\t\t   sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\tTRACE_DEBUG(( \"Checking attribute \" ));\n\tTRACE_FIELDTYPE( attributeCheckInfo->attributeInfoPtr );\n\n\t/* Step through the attribute comparing the fields that are present in\n\t   the attribute list with the fields that should be present according\n\t   to the table and set encoding synchronisation points as required.\n\t   \n\t   This loop has the same issue as the one discussed in the comment in \n\t   checkComponentPresent() */\n\tLOOP_LARGE( noEntries = 0, noEntries < 500, noEntries++ )\n\t\t{\n\t\tBOOLEAN skipStackUpdate;\n\t\tint typeInfoFlags;\n\n\t\t/* Sanity check to make sure that we don't fall off the end of the \n\t\t   encoding table */\n\t\tENSURES( !isAttributeTableEnd( attributeCheckInfo->attributeInfoPtr ) );\n\n\t\t/* Check whether this is a repeated instance of the same attribute\n\t\t   and if it is remember the encoding restart point.  We have to do\n\t\t   this before we check the attribute information because it usually\n\t\t   updates the information after the check */\n\t\tif( restartEntry == NULL && \\\n\t\t\tattributeCheckInfo->attributeListPtr != NULL )\n\t\t\t{\n\t\t\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\t\t\tattributeCheckInfo->attributeListPtr;\n\t\t\tconst ATTRIBUTE_LIST *attributeListNextPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( attributeListPtr->next );\n\n\t\t\tif( attributeListNextPtr != NULL && \\\n\t\t\t\t( attributeListPtr->fieldID == \\\n\t\t\t\t\t\t\tattributeListNextPtr->fieldID ) && \\\n\t\t\t\t( attributeListPtr->subFieldID == \\\n\t\t\t\t\t\t\tattributeListNextPtr->subFieldID ) )\n\t\t\t\t{\n\t\t\t\t/* Remember the restart point, the next (repeated) attribute \n\t\t\t\t   beyond the current one.  In other words if \n\t\t\t\t   attributeListPtr->fieldID == CRYPT_CERTINFO_IPADDRESS and\n\t\t\t\t   attributeListNextPtr->fieldID == CRYPT_CERTINFO_IPADDRESS \n\t\t\t\t   then we need to reset the attributeInfoPtr to its current\n\t\t\t\t   position once we've processed the first entry in order to \n\t\t\t\t   process the second entry */\n\t\t\t\trestartEntry = attributeListNextPtr;\n\t\t\t\trestartPoint = attributeCheckInfo->attributeInfoPtr;\n\t\t\t\trestartStackPos = attributeCheckInfo->stackPos + 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Check the current encoding table entry.  checkAttributeEntry() \n\t\t   may skip over several optional items and end up at an end-of-\n\t\t   SEQUENCE flag for which no SEQUENCE start was stacked, in which \n\t\t   case we don't perform the stack update */\n\t\tstatus = checkAttributeEntry( attributeCheckInfo, &skipStackUpdate );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tattributeCheckInfo->errorLocus = \\\n\t\t\t\t\t\t\tattributeCheckInfo->attributeInfoPtr->fieldID;\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( !skipStackUpdate )\n\t\t\t{\n\t\t\t/* If this is the end of a constructed item unstack it and\n\t\t\t   update the attribute list entry with the length information.\n\t\t\t   If it's a sequence with all fields optional (so that nothing\n\t\t\t   gets encoded) we don't do anything */\n\t\t\tstatus = updateStackedInfo( attributeCheckInfo->stack,\n\t\t\t\t\t\t\t\t\t\tattributeCheckInfo->stackPos,\n\t\t\t\t\t\t\t\t\t\t&attributeCheckInfo->stackPos,\n\t\t\t\tdecodeNestingLevel( attributeCheckInfo->attributeInfoPtr->encodingFlags ),\n\t\t\t\t\t\t\t\t\t\tTRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\t\t\t}\n\n\t\t/* If there's another instance of the same item, don't move on to\n\t\t   the next table entry.  We need to check whether we're still at \n\t\t   the restartable attribute because checkAttributeEntry() may have, \n\t\t   via a recursive call back to checkAttribute(), processed both the \n\t\t   initial attribute and the repeated instance(s) of the attribute */\n\t\tif( restartEntry != NULL && \\\n\t\t\trestartEntry == attributeCheckInfo->attributeListPtr )\n\t\t\t{\n\t\t\t/* Restart at the table entry for the previous instance of the \n\t\t\t   item and adjust the stack to match */\n\t\t\tattributeCheckInfo->attributeInfoPtr = restartPoint;\n\t\t\tif( attributeCheckInfo->stackPos > restartStackPos )\n\t\t\t\t{\n\t\t\t\tstatus = updateStackedInfo( attributeCheckInfo->stack,\n\t\t\t\t\t\t\t\t\t\t\tattributeCheckInfo->stackPos,\n\t\t\t\t\t\t\t\t\t\t\t&attributeCheckInfo->stackPos,\n\t\t\t\t\t\t\t\t\t\t\tattributeCheckInfo->stackPos - \\\n\t\t\t\t\t\t\t\t\t\t\t\trestartStackPos, TRUE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\t\t\t\t}\n\t\t\trestartEntry = NULL;\n\t\t\trestartPoint = NULL;\n\t\t\trestartStackPos = 0;\n\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Move on to the next table entry.  We have to check the\n\t\t   continuation flag before we move to the next table entry in order\n\t\t   to include processing of the last field in an attribute */\n\t\ttypeInfoFlags = attributeCheckInfo->attributeInfoPtr->typeInfoFlags;\n\t\tattributeCheckInfo->attributeInfoPtr++;\n\t\tif( typeInfoFlags & FL_ATTR_ATTREND )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( noEntries < 500 );\n\tattributeCheckInfo->choiceState = CHOICE_NONE;\n\t\n\t/* We've reached the end of the attribute, if there are still constructed\n\t   objects stacked, unstack them and update their length information.  If\n\t   it's a sequence with all fields optional (so that nothing gets\n\t   encoded) this won't do anything */\n\tstatus = updateStackedInfo( attributeCheckInfo->stack, \n\t\t\t\t\t\t\t\tattributeCheckInfo->stackPos,\n\t\t\t\t\t\t\t\t&attributeCheckInfo->stackPos,\n\t\t\t\t\t\t\t\tattributeCheckInfo->stackPos - \\\n\t\t\t\t\t\t\t\t\tattributeCheckInfo->stackMarkerPos, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckAttributeCheckInfo( attributeCheckInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the entire list of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4 ) ) \\\nint checkAttributes( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t IN const DATAPTR_ATTRIBUTE listHeadPtr,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tATTRIBUTE_CHECK_INFO attributeCheckInfo;\n\tconst ATTRIBUTE_INFO *attributeInfoStartPtr;\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint dummy, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( listHeadPtr ) );\n\tREQUIRES( attributeType == ATTRIBUTE_CERTIFICATE || \\\n\t\t\t  attributeType == ATTRIBUTE_CMS );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Get the attribute encoding information.  We can't use the size value\n\t   returned from this because of the nested-loop structure below which \n\t   only ever iterates through a subset of the encoding information so we\n\t   leave it as a dummy value */\n\tstatus = getAttributeInfo( attributeType, &attributeInfoStartPtr, \n\t\t\t\t\t\t\t   &dummy );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* If we've already done a validation pass some of the fields will\n\t   contain values that were previously set so before we begin we walk\n\t   down the list resetting the fields that are updated by this\n\t   function */\n\tLOOP_LARGE( attributeListPtr = DATAPTR_GET( listHeadPtr ), \n\t\t\t\tattributeListPtr != NULL && \\\n\t\t\t\t\tisValidAttributeField( attributeListPtr ),\n\t\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListNextPtr;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t\tattributeListNextPtr = DATAPTR_GET( attributeListPtr->next );\n\t\tif( attributeListNextPtr != NULL && \\\n\t\t\tisValidAttributeField( attributeListNextPtr ) && \\\n\t\t\tattributeListPtr->attributeID > \\\n\t\t\t\t\t\tattributeListNextPtr->attributeID )\n\t\t\t{\n\t\t\t/* Safety check in case of an invalid attribute list */\n\t\t\tretIntError();\n\t\t\t}\n\t\tattributeListPtr->attributeInfoPtr = NULL;\n\t\tattributeListPtr->encodedSize = attributeListPtr->fifoPos = \\\n\t\t\tattributeListPtr->fifoEnd = 0;\n\t\tCLEAR_FLAG( attributeListPtr->flags, ATTR_FLAG_DEFAULTVALUE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Set up the attribute-checking state information */\n\tmemset( &attributeCheckInfo, 0, sizeof( ATTRIBUTE_CHECK_INFO ) );\n\tattributeCheckInfo.attributeListPtr = DATAPTR_GET( listHeadPtr );\n\tattributeCheckInfo.attributeInfoPtr = attributeInfoStartPtr;\n\tENSURES( sanityCheckAttributeCheckInfo( &attributeCheckInfo ) );\n\n\t/* Walk down the list of known attributes checking each one for\n\t   consistency */\n\tLOOP_LARGE_CHECK( attributeCheckInfo.attributeListPtr != NULL && \\\n\t\t\t\t\t  attributeCheckInfo.attributeListPtr->fieldID != CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Find the start of this attribute in the attribute information \n\t\t   table and remember it as an encoding synchronisation point.  \n\t\t   Comparing the field ID with the attribute ID is usually valid \n\t\t   because the attribute information table always begins the series \n\t\t   of entries for an attribute with the attribute ID.  The one \n\t\t   exception is where the attribute ID is the same as the field ID \n\t\t   but they're separate entries in the table, in which case the \n\t\t   first entries will contain a FIELDID_FOLLOWS code to indicate \n\t\t   that the following field contains the attribute/fieldID */\n\t\tLOOP_LARGE_CHECKINC_ALT( !isAttributeTableEnd( attributeCheckInfo.attributeInfoPtr ),\n\t\t\t\t\t\t\t\t attributeCheckInfo.attributeInfoPtr++ )\n\t\t\t{\n\t\t\tif( attributeCheckInfo.attributeInfoPtr->fieldID == FIELDID_FOLLOWS )\n\t\t\t\t{\n\t\t\t\tif( attributeCheckInfo.attributeInfoPtr[ 1 ].fieldID == \\\n\t\t\t\t\t\tattributeCheckInfo.attributeListPtr->attributeID )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( attributeCheckInfo.attributeInfoPtr->fieldID == \\\n\t\t\t\t\t\tattributeCheckInfo.attributeListPtr->attributeID )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( !isAttributeTableEnd( attributeCheckInfo.attributeInfoPtr ) );\n\n\t\t/* Check this attribute */\n\t\tstatus = checkAttribute( &attributeCheckInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t*errorLocus = attributeCheckInfo.errorLocus;\n\t\t\t*errorType = attributeCheckInfo.errorType;\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_copy.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Attribute Copy Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n#endif /* Compiler-specific includes */\n\n/* When replicating attributes from one type of certificate object to \n   another (for example from an issuer certificate to a subject certificate \n   when issuing a new certificate) we may have to adjust the attribute \n   information based on the source and destination object roles.  The \n   following values denote the different copy types that we have to handle.  \n   Usually this is a direct copy, however if we're copying from subject to \n   issuer we have to adjust attribute IDs such as the altName \n   (subjectAltName -> issuerAltName), if we're copying from issuer to \n   subject we have to adjust path length-based contraints since the new \n   subject is one further down the chain than the issuer */\n\ntypedef enum {\n\tCOPY_NONE,\t\t\t\t/* No copy type */\n\tCOPY_DIRECT,\t\t\t/* Direct attribute copy */\n\tCOPY_SUBJECT_TO_ISSUER,\t/* Copy of subject attributes to issuer cert */\n\tCOPY_ISSUER_TO_SUBJECT,\t/* Copy of issuer attributes to subject cert */\n\tCOPY_LAST\t\t\t\t/* Last valid copy type */\n\t} COPY_TYPE;\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Make a copy of an attribute field, used for copying attributes from a \n   source attribute list to a new destination */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyAttributeField( OUT_PTR_COND ATTRIBUTE_LIST **newDestAttributeField,\n\t\t\t\t\t\t\t   IN const ATTRIBUTE_LIST *srcAttributeField )\n\t{\n\tATTRIBUTE_LIST *newElement;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( newDestAttributeField, sizeof( ATTRIBUTE_LIST * ) ) );\n\tassert( isReadPtr( srcAttributeField, sizeof( ATTRIBUTE_LIST ) ) );\n\n\t/* Allocate memory for the new element and copy the information across */\n\t*newDestAttributeField = NULL;\n\tif( ( newElement = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t   clAlloc( \"copyAttributeField\", \\\n\t\t\t\t\t\t\t\tsizeofVarStruct( srcAttributeField, \\\n\t\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_LIST ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tcopyVarStruct( newElement, srcAttributeField, ATTRIBUTE_LIST, dataValue );\n\tif( srcAttributeField->fieldType == FIELDTYPE_DN )\n\t\t{\n\t\tDATAPTR_DN dn = GET_DN_POINTER( newElement );\n\t\tDATAPTR_DN srcDN = GET_DN_POINTER( srcAttributeField );\n\n\t\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\t\tREQUIRES( DATAPTR_ISSET( srcDN ) );\n\n\t\t/* If the field contains a DN, copy that across as well */\n\t\tstatus = copyDN( &dn, srcDN );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tendVarStruct( newElement, ATTRIBUTE_LIST );\n\t\t\tclFree( \"copyAttributeField\", newElement );\n\t\t\treturn( status );\n\t\t\t}\n\t\tSET_DN_POINTER( newElement, dn );\n\t\t}\n\tif( checkAttributeListProperty( srcAttributeField, \n\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\t/* For blob-type attributes the OID is stored at the end of the\n\t\t   attribute data, so we have to update the pointer to this after\n\t\t   the copy */\n\t\tnewElement->oid = newElement->storage + \\\n\t\t\t\t\t\t  newElement->dataValueLength;\n\t\t}\n\tDATAPTR_SET( newElement->next, NULL );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tENSURES( sanityCheckAttributePtr( newElement ) );\n\t*newDestAttributeField = newElement;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy an attribute from one attribute list to another */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int fixAttributeInfo( INOUT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t IN_ENUM( COPY ) const COPY_TYPE copyType,\n\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t IN const BOOLEAN targetIsCA )\n\t{\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( isEnumRange( copyType, COPY ) );\n\tREQUIRES( isValidExtension( attributeID ) );\n\tREQUIRES( targetIsCA == FALSE || targetIsCA == TRUE );\n\n\t/* If we're copying from an issuer to a subject attribute list and the \n\t   field is an altName or keyIdentifier, change the field type from \n\t   issuer.subjectAltName to subject.issuerAltName or\n\t   issuer.subjectKeyIdentifier to subject.authorityKeyIdentifier */\n\tif( copyType == COPY_SUBJECT_TO_ISSUER )\n\t\t{\n\t\tif( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )\n\t\t\t{\n\t\t\tattributeListPtr->attributeID = \\\n\t\t\t\t\tattributeListPtr->fieldID = \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ISSUERALTNAME;\n\t\t\t}\n\t\tif( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )\n\t\t\t{\n\t\t\tattributeListPtr->attributeID = \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;\n\t\t\tattributeListPtr->fieldID = \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER;\n\t\t\t}\n\t\t}\n\n\t/* If we're copying from a subject to an issuer attribute list and it's \n\t   a path length-based constraint, adjust the constraint value by one \n\t   since we're now one further down the chain */\n\tif( copyType == COPY_ISSUER_TO_SUBJECT )\n\t\t{\n\t\tif( attributeListPtr->fieldID == \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PATHLENCONSTRAINT || \\\n\t\t\tattributeListPtr->fieldID == \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_REQUIREEXPLICITPOLICY || \\\n\t\t\tattributeListPtr->fieldID == \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_INHIBITPOLICYMAPPING )\n\t\t\t{\n\t\t\t/* If we're already at a path length of zero then we can't \n\t\t\t   reduce it any further */\n\t\t\tif( attributeListPtr->intValue <= 0 )\n\t\t\t\t{\n\t\t\t\t/* If the copy target is a CA then this is an error */\n\t\t\t\tif( targetIsCA )\n\t\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t\n\t\t\t\t/* The target is an EE, let the caller know that this \n\t\t\t\t   attribute shouldn't be copied */\n\t\t\t\treturn( OK_SPECIAL );\n\t\t\t\t}\n\n\t\t\tattributeListPtr->intValue--;\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyAttribute( INOUT_PTR DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\t\t  IN_ENUM( COPY ) const COPY_TYPE copyType )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeID, newAttributeID;\n\tDATAPTR_ATTRIBUTE destHead = *destHeadPtr, newAttributeHead;\n\tDATAPTR_ATTRIBUTE *newAttributeHeadPtr = &newAttributeHead;\n\tATTRIBUTE_LIST *srcListPtr, *insertPoint, *prevElement = NULL;\n\tATTRIBUTE_LIST *newAttributeListHead;\n\tATTRIBUTE_LIST *newAttributeListTail DUMMY_INIT_PTR;\n\tBOOLEAN targetIsCA = FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\t\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\tREQUIRES( isEnumRange( copyType, COPY ) );\n\n\tsrcListPtr = DATAPTR_GET( srcPtr );\n\tREQUIRES( srcListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( srcListPtr ) );\n\tattributeID = newAttributeID = srcListPtr->attributeID;\n\n\t/* If we're re-mapping the destination attribute ID (see the comment\n\t   further down) we have to insert it at a point corresponding to the \n\t   re-mapped ID, not the original ID, to maintain the list's sorted\n\t   property.  The CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER is only\n\t   copied at CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL or above so we'll never\n\t   see this attribute copied at lower compliance levels (this is \n\t   enforced in the caller) */\n\tif( copyType == COPY_SUBJECT_TO_ISSUER )\n\t\t{\n\t\tif( attributeID == CRYPT_CERTINFO_SUBJECTALTNAME )\n\t\t\tnewAttributeID = CRYPT_CERTINFO_ISSUERALTNAME;\n\t\tif( attributeID == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER )\n\t\t\tnewAttributeID = CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER;\n\t\t}\n\n\t/* If we're copying from a CA certificate, determine whether the copy\n\t   target is also a CA.  This affects the copying of length constraint\n\t   extensions */\n\tif( copyType == COPY_ISSUER_TO_SUBJECT )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\tattributePtr = findAttributeField( destHead, CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\ttargetIsCA = TRUE;\n\t\t}\n\n\t/* Find the location at which to insert this attribute (this assumes \n\t   that the fieldIDs are defined in sorted order) */\n\tLOOP_LARGE( insertPoint = DATAPTR_GET( destHead ), \n\t\t\t\tinsertPoint != NULL && \\\n\t\t\t\t\tinsertPoint->attributeID < newAttributeID && \\\n\t\t\t\t\tinsertPoint->fieldID != CRYPT_ATTRIBUTE_NONE,\n\t\t\t\tinsertPoint = DATAPTR_GET( insertPoint->next ) )\n\t\t{\n\t\tprevElement = insertPoint;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tinsertPoint = prevElement;\n\n\t/* Build a new attribute list containing the attribute fields */\n\tDATAPTR_SET_PTR( newAttributeHeadPtr, NULL );\n\tLOOP_LARGE_CHECKINC( srcListPtr != NULL && \\\n\t\t\t\t\t\t\tsrcListPtr->attributeID == attributeID,\n\t\t\t\t\t\t srcListPtr = DATAPTR_GET( srcListPtr->next ) )\n\t\t{\n\t\tATTRIBUTE_LIST *newAttributeField;\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckAttributePtr( srcListPtr ) );\n\n\t\t/* Copy the field across */\n\t\tstatus = copyAttributeField( &newAttributeField, srcListPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( DATAPTR_ISSET_PTR( newAttributeHeadPtr ) )\n\t\t\t\tdeleteAttributes( newAttributeHeadPtr );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Perform any attribute fixups due to issuer-to-subject/subject-to-\n\t\t   issuer copying */\n\t\tstatus = fixAttributeInfo( newAttributeField, copyType, attributeID, \n\t\t\t\t\t\t\t\t   targetIsCA );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE newAttribute;\n\n\t\t\tDATAPTR_SET( newAttribute, newAttributeField );\n\t\t\t( void ) deleteAttributeField( &newAttribute, NULL,\t\n\t\t\t\t\t\t\t\t\t\t   newAttribute, NULL );\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\t/* This attribute shouldn't be copied, contine with the next \n\t\t\t\t   one */\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\tif( DATAPTR_ISSET_PTR( newAttributeHeadPtr ) )\n\t\t\t\tdeleteAttributes( newAttributeHeadPtr );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Append the new field to the new attribute list */\n\t\tinsertDoubleListElement( newAttributeHeadPtr, newAttributeListTail, \n\t\t\t\t\t\t\t\t newAttributeField, ATTRIBUTE_LIST );\n\t\tnewAttributeListTail = newAttributeField;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( DATAPTR_ISSET_PTR( newAttributeHeadPtr ) );\n\tnewAttributeListHead = DATAPTR_GET_PTR( newAttributeHeadPtr );\n\tENSURES( newAttributeListHead != NULL );\n\n\t/* Link the new list into the existing list at the appropriate position */\n\tinsertDoubleListElements( destHeadPtr, insertPoint, \n\t\t\t\t\t\t\t  newAttributeListHead, \n\t\t\t\t\t\t\t  newAttributeListTail, ATTRIBUTE_LIST );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy a length constraint from an issuer CA certificate to a subject CA\n   certificate, decrementing the value by one */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int copyLengthConstraint( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t\t IN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID,\n\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus )\n\n\t{\n\tDATAPTR_ATTRIBUTE destHead = *destHeadPtr, srcAttribute;\n\tATTRIBUTE_LIST *srcListPtr, *destListPtr;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE  ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\t\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\tREQUIRES( fieldID == CRYPT_CERTINFO_PATHLENCONSTRAINT || \\\n\t\t\t  fieldID == CRYPT_CERTINFO_REQUIREEXPLICITPOLICY || \\\n\t\t\t  fieldID == CRYPT_CERTINFO_INHIBITPOLICYMAPPING );\n#else\n\tREQUIRES( fieldID == CRYPT_CERTINFO_PATHLENCONSTRAINT );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Clear return value */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\n\tsrcListPtr = DATAPTR_GET( srcPtr );\n\tREQUIRES( srcListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( srcListPtr ) );\n\n\t/* If there's nothing to copy, we're done */\n\tsrcAttribute = findAttributeField( srcPtr, fieldID, CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( srcAttribute ) )\n\t\treturn( CRYPT_OK );\n\tsrcListPtr = DATAPTR_GET( srcAttribute );\n\tENSURES( srcListPtr != NULL );\n\n\t/* There's a length constraint present, if the value is already at zero \n\t   then the next certificate must be an EE certificate rather than a\n\t   CA certificate */\n\tif( srcListPtr->intValue <= 0 )\n\t\t{\n\t\t*errorLocus = fieldID;\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* There's something to copy, if it's not already present in the \n\t   destination just copy it across */\n\tdestHead = findAttributeField( destHead, fieldID, \n\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( destHead ) )\n\t\t{\n\t\tCRYPT_ERRTYPE_TYPE dummy;\n\n\t\t/* Copy the field across and update the constraint value */\n\t\treturn( addAttributeField( destHeadPtr, fieldID, \n\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t   srcListPtr->intValue - 1,\n\t\t\t\t\t\t\t\t   GET_FLAGS( srcListPtr->flags, \n\t\t\t\t\t\t\t\t\t\t\t  ATTR_FLAG_MAX ), \n\t\t\t\t\t\t\t\t   errorLocus, &dummy ) );\n\t\t}\n\n\t/* The same constraint exists in source and destination, set the result\n\t   value to the lesser of the two, with the necessary decrement applied */\n\tdestListPtr = DATAPTR_GET( destHead );\n\tENSURES( destListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( destListPtr  ) );\n\tif( srcListPtr->intValue <= destListPtr->intValue )\n\t\tdestListPtr->intValue = srcListPtr->intValue - 1;\n\tENSURES( destListPtr->intValue >= 0 );\n\n\treturn( CRYPT_OK );\n\t}\t\t\t\t\t\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCopy a Complete Attribute List\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy a complete attribute list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint copyAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\tIN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst DATAPTR_ATTRIBUTE destHead = *destHeadPtr;\n\tconst ATTRIBUTE_LIST *srcListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE  ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\t/* Clear return values */\n\tDATAPTR_SET_PTR( destHeadPtr, NULL );\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\tsrcListPtr = DATAPTR_GET( srcPtr );\n\tREQUIRES( srcListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( srcListPtr ) );\n\n\t/* If there are destination attributes present make a first pass down \n\t   the list checking that the attribute to copy isn't already present in \n\t   the destination attributes, first for recognised attributes and then \n\t   for unrecognised ones.  We have to do this separately since once we \n\t   begin the copy process it's rather hard to undo it.  There are two \n\t   special cases that we could in theory allow:\n\n\t\t1. Some composite attributes could have non-overlapping fields in \n\t\t   the source and destination.\n\n\t\t2. Some attributes can have multiple instances of a field present.\n\n\t   This means that we could allow them to appear in both the source and \n\t   destination lists, however if this occurs it's more likely to be an \n\t   error than a desire to merge two disparate collections of fields or \n\t   attributes so we report them as (disallowed) duplicates */\n\tif( DATAPTR_ISSET( destHead ) )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListCursor;\n\n\t\t/* Check the non-blob attributes */\n\t\tLOOP_LARGE( attributeListCursor = DATAPTR_GET( srcPtr ), \n\t\t\t\t\tattributeListCursor != NULL && \\\n\t\t\t\t\t\t!checkAttributeListProperty( attributeListCursor,\n\t\t\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ),\n\t\t\t\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next ) )\n\t\t\t{\n\t\t\tATTRIBUTE_LIST *attributeListCursorNext;\n\t\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\t\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\t\t\tattributeListCursorNext = DATAPTR_GET( attributeListCursor->next );\n\t\t\tENSURES( attributeListCursorNext == NULL || \\\n\t\t\t\t\t !isValidAttributeField( attributeListCursorNext ) || \\\n\t\t\t\t\t attributeListCursor->attributeID <= \\\n\t\t\t\t\t\t\tattributeListCursorNext->attributeID );\n\t\t\tattributePtr = findAttributeField( destHead,\n\t\t\t\t\t\t\t\t\t\t\t   attributeListCursor->fieldID, \n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t\t{\n\t\t\t\t*errorLocus = attributeListCursor->fieldID;\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Check the blob attributes */\n\t\tLOOP_LARGE_CHECKINC( attributeListCursor != NULL,\n\t\t\t\t\t\t\t attributeListCursor = DATAPTR_GET( attributeListCursor->next ) )\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\t\tREQUIRES( sanityCheckAttributePtr( attributeListCursor ) );\n\t\t\tENSURES( checkAttributeListProperty( attributeListCursor,\n\t\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) );\n\t\t\tattributePtr = findAttributeByOID( destHead, attributeListCursor->oid,\n\t\t\t\t\t\t\t\t\t\t\t   sizeofOID( attributeListCursor->oid ) );\n\t\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t\t{\n\t\t\t\t/* We can't set the locus for blob-type attributes since \n\t\t\t\t   it's not a known attribute */\n\t\t\t\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Make a second pass copying everything across, first the non-blob \n\t   attributes */\n\tLOOP_LARGE_CHECK( srcListPtr != NULL && \\\n\t\t\t\t\t  !checkAttributeListProperty( srcListPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE attributeID = srcListPtr->attributeID;\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tint status, LOOP_ITERATOR_ALT;\n\n\t\t/* Get the attribute information for the attribute to be copied */\n\t\tif( srcListPtr->attributeInfoPtr != NULL )\n\t\t\tattributeInfoPtr = srcListPtr->attributeInfoPtr;\n\t\telse\n\t\t\t{\n\t\t\tattributeInfoPtr = \\\n\t\t\t\tfieldIDToAttribute( ( attributeID >= CRYPT_CERTINFO_FIRST_CMS ) ? \\\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tattributeID, CRYPT_ATTRIBUTE_NONE, NULL );\n\t\t\t}\n\t\tENSURES( attributeInfoPtr != NULL );\n\n\t\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\t\t/* Copy the complete attribute across unless it's one that we \n\t\t   explicitly don't propagate from source to destination */\n\t\tif( !( attributeInfoPtr->typeInfoFlags & FL_ATTR_NOCOPY ) )\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE srcAttribute;\n\n\t\t\tDATAPTR_SET( srcAttribute, ( ATTRIBUTE_LIST * ) srcListPtr );\n\t\t\tstatus = copyAttribute( destHeadPtr, srcAttribute, COPY_DIRECT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Move on to the next attribute.  Since each loop restarts the \n\t\t   bounds check value this unfortunately makes the combined bound\n\t\t   2*n rather than just n, but there's no easy way to access the\n\t\t   bounds variable from the outer loop */\n\t\tLOOP_LARGE_CHECKINC_ALT( srcListPtr != NULL && \\\n\t\t\t\t\t\t\t\t\tsrcListPtr->attributeID == attributeID,\n\t\t\t\t\t\t\t\t srcListPtr = DATAPTR_GET( srcListPtr->next ) );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If there are blob-type attributes left at the end of the list, copy\n\t   them across last */\n\tif( srcListPtr != NULL )\n\t\t{\n\t\tATTRIBUTE_LIST *insertPoint;\n\n\t\t/* Find the end of the destination list */\n\t\tLOOP_LARGE( insertPoint = DATAPTR_GET( destHead ), \n\t\t\t\t\tinsertPoint != NULL && DATAPTR_ISSET( insertPoint->next ),\n\t\t\t\t\tinsertPoint = DATAPTR_GET( insertPoint->next ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Copy all remaining attributes across */\n\t\tLOOP_LARGE_CHECKINC( srcListPtr != NULL,\n\t\t\t\t\t\t\t srcListPtr = DATAPTR_GET( srcListPtr->next ) )\n\t\t\t{\n\t\t\tATTRIBUTE_LIST *newAttribute;\n\t\t\tint status;\n\n\t\t\tstatus = copyAttributeField( &newAttribute, srcListPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tinsertDoubleListElement( destHeadPtr, insertPoint, \n\t\t\t\t\t\t\t\t\t newAttribute, ATTRIBUTE_LIST );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCopy Specific Attributes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy CA constraints from the issuer to the subject */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\nstatic int copyCAConstraints( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE destHead = *destHeadPtr, attributePtr;\n\tDATAPTR_ATTRIBUTE srcPermittedSubtrees, srcExcludedSubtrees;\n\tint status;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Check for the presence of permitted/excluded subtrees */\n\tsrcPermittedSubtrees = findAttributeField( srcPtr,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tsrcExcludedSubtrees = findAttributeField( srcPtr,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE );\n\n\t/* If we're copying permitted or excluded subtrees then they can't \n\t   already be present in the destination.  We check the two separately \n\t   rather than just checking for the overall presence of name \n\t   constraints since in theory it's possible to merge permitted and \n\t   excluded constraints, so that permitted constraints in the \n\t   destination don't clash with excluded constraints in the source (yet \n\t   another one of X.509's semantic holes) */\n\tif( DATAPTR_ISSET( srcPermittedSubtrees ) )\n\t\t{\n\t\tattributePtr = findAttributeField( destHead, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t{\n\t\t\t*errorLocus = CRYPT_CERTINFO_PERMITTEDSUBTREES;\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\t}\n\tif( DATAPTR_ISSET( srcExcludedSubtrees ) )\n\t\t{\n\t\tattributePtr = findAttributeField( destHead, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\t\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t\t{\n\t\t\t*errorLocus = CRYPT_CERTINFO_EXCLUDEDSUBTREES;\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\t}\n\n\t/* Copy the fields across */\n\tif( DATAPTR_ISSET( srcPermittedSubtrees ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, \n\t\t\t\t\t\t\t\tsrcPermittedSubtrees, \n\t\t\t\t\t\t\t\tCOPY_SUBJECT_TO_ISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( DATAPTR_ISSET( srcExcludedSubtrees ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, \n\t\t\t\t\t\t\t\tsrcExcludedSubtrees, \n\t\t\t\t\t\t\t\tCOPY_SUBJECT_TO_ISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* The path-length constraints are a bit easier to handle, if they're \n\t   already present then we just use the smaller of the two */\n\tstatus = copyLengthConstraint( destHeadPtr, srcPtr, \n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,\n\t\t\t\t\t\t\t\t   errorLocus );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = copyLengthConstraint( destHeadPtr, srcPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_INHIBITPOLICYMAPPING,\n\t\t\t\t\t\t\t\t\t   errorLocus );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/* Copy attributes that are propagated down certificate chains from an \n   issuer to a subject certificate, changing the field types from subject \n   to issuer and adjusting constraint values at the same time if required */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint copyIssuerAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr,\n\t\t\t\t\t\t  const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tDATAPTR_ATTRIBUTE destHead = *destHeadPtr, attributePtr;\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\tREQUIRES( isEnumRange( type, CRYPT_CERTTYPE ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* If the destination is a CA certificate and the source has constraint \n\t   extensions, copy them over to the destination.  The reason why we\n\t   copy the constraints even though they're already present in the\n\t   source is to ensure that they're still present in a certificate chain \n\t   even if the parent isn't available.  This can occur for example when \n\t   a chain-internal certificate is marked as implicitly trusted and the \n\t   chain is only available up to the implicitly-trusted certificate with \n\t   the contraint-imposing parent not present */\n\tattributePtr = findAttributeField( destHead, CRYPT_CERTINFO_CA, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tattributeListPtr = DATAPTR_GET( attributePtr );\n\t\tENSURES( attributeListPtr != NULL );\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\t\tif( attributeListPtr->intValue > 0 )\n\t\t\t{\n\t\t\t/* Copy any extended CA constraints across */\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t\tstatus = copyCAConstraints( destHeadPtr, srcPtr, \n\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t\t\t/* Finally, copy the CA basic constraints across */\n\t\t\tstatus = copyLengthConstraint( destHeadPtr, srcPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t\t\t\t\t\t\t\t\t\t   errorLocus );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ISSUERCONSTRAINT;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If it's an attribute certificate, that's all that we can copy */\n\tif( type == CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\treturn( CRYPT_OK );\n\n\t/* Copy the altName and keyIdentifier if these are present.  We don't\n\t   have to check for their presence in the destination certificate since \n\t   they're read-only fields and can't be added by the user.  The\n\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER becomes the \n\t   CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER when copied from the issuer to \n\t   the subject so we only copy it at a compliance level of \n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL or above, since it's not enforced \n\t   below that level */\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_SUBJECTALTNAME, \n\t\t\t\t\t\t\t\t  TRUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, attributePtr, \n\t\t\t\t\t\t\t\tCOPY_SUBJECT_TO_ISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, \n\t\t\t\t\t\t\t\t  TRUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, attributePtr, \n\t\t\t\t\t\t\t\tCOPY_SUBJECT_TO_ISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* Copy the authorityInfoAccess if it's present.  This one is a bit \n\t   tricky both because it's a multi-valued attribute and some values \n\t   may already be present in the destination certificate and because \n\t   it's not certain that the issuer certificate's AIA should be the same \n\t   as the subject certificate's AIA.  At the moment with monolithic CAs \n\t   (i.e. ones that control all the certificates down to the EE) this is \n\t   always the case and if it isn't then it's assumed that the CA will \n\t   set the EE's AIA to the appropriate value before trying to sign the \n\t   certificate.  Because of this we copy the issuer AIA if there's no \n\t   subject AIA present, otherwise we assume that the CA has set the \n\t   subject AIA to its own choice of value and don't try and copy \n\t   anything */\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_AUTHORITYINFOACCESS, \n\t\t\t\t\t\t\t\t  FALSE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tDATAPTR_ATTRIBUTE aiaAttribute;\n\n\t\taiaAttribute = findAttribute( destHead, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_AUTHORITYINFOACCESS, FALSE );\n\t\tif( DATAPTR_ISNULL( aiaAttribute ) )\n\t\t\t{\n\t\t\tstatus = copyAttribute( destHeadPtr, attributePtr, \n\t\t\t\t\t\t\t\t\tCOPY_SUBJECT_TO_ISSUER );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CERTREQ\n\n/* Copy attributes that are propagated from a CRMF certificate request \n   template to the issued certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyCRMFRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\t/* Copy the altName across, needed for the additional identification \n\t   that it provides */\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_SUBJECTALTNAME, \n\t\t\t\t\t\t\t\t  TRUE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, attributePtr, COPY_DIRECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREQ */\n\n#if defined( USE_CERTVAL ) || defined( USE_CERTREV )\n\n/* Copy attributes that are propagated from an RTCS or OCSP request to a \n   response.  Since only one attribute, the nonce, is copied across we can\n   use the same function for both operations */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRTCSRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr )\n\t{\n\tDATAPTR_ATTRIBUTE destHead = *destHeadPtr, attributePtr;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\t/* If the nonce attribute is already present in the destination, delete\n\t   it */\n\tattributePtr = findAttributeField( destHead, CRYPT_CERTINFO_OCSP_NONCE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\t( void ) deleteAttributeField( destHeadPtr, NULL, attributePtr, \n\t\t\t\t\t\t\t\t\t   NULL );\n\t\t}\n\n\t/* Copy the nonce attribute from the source to the destination.  We don't\n\t   copy anything else (i.e. we default to deny-all) to prevent the \n\t   requester from being able to insert arbitrary attributes into the \n\t   response */\n\tattributePtr = findAttributeField( srcPtr, CRYPT_CERTINFO_OCSP_NONCE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\treturn( copyAttribute( destHeadPtr, attributePtr, COPY_DIRECT ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTVAL || USE_CERTREV */\n\n#ifdef USE_CERTREV\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyOCSPRequestAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t   IN const DATAPTR_ATTRIBUTE srcPtr )\n\t{\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\treturn( copyRTCSRequestAttributes( destHeadPtr, srcPtr ) );\n\t}\n\n/* Copy attributes that are propagated from a revocation request to a CRL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint copyRevocationAttributes( INOUT DATAPTR_ATTRIBUTE *destHeadPtr,\n\t\t\t\t\t\t\t  IN const DATAPTR_ATTRIBUTE srcPtr )\n\t{\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tint status;\n\n\tassert( isWritePtr( destHeadPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( srcPtr ) );\n\n\t/* Copy the CRL reason and invalidity date attributes from the source to \n\t   the destination.  We don't copy anything else (i.e. we default to \n\t   deny-all) to prevent the requester from being able to insert arbitrary \n\t   attributes into the CRL */\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_CRLREASON, \n\t\t\t\t\t\t\t\t  FALSE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\t{\n\t\tstatus = copyAttribute( destHeadPtr, attributePtr, COPY_DIRECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tattributePtr = findAttribute( srcPtr, CRYPT_CERTINFO_INVALIDITYDATE, \n\t\t\t\t\t\t\t\t  FALSE );\n\tif( DATAPTR_ISSET( attributePtr ) )\n\t\treturn( copyAttribute( destHeadPtr, attributePtr, COPY_DIRECT ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTREV */\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_def.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Attribute Definitions\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/* The following certificate extensions are currently supported.  If\n   'Enforced' is set to 'Yes' then they're constraint extensions that are \n   enforced by the certificate checking code; if set to '-' then they're\n   informational extensions for which enforcement doesn't apply; if set to \n   'No' they need to be handled by the user (this only applies for \n   certificate policies for which the user has to decide whether a given \n   policy is acceptable or not).  The Yes/No in policyConstraints means \n   that everything except the policy mapping constraint is enforced \n   (because policyMappings itself isn't enforced).  The 'level' value \n   indicates the compliance level at which the extension is decoded and\n   enforced.  The 'conditions' value indicates any further conditions under\n   which the extension may be applied or skipped.  PKIX = 'Full' overrides\n   Conditions = 'Obscure', so that setting PKIX compliance to Full enables\n   handling of all PKIX/X.509 extensions no matter how obscure and strange\n   they are.\n\n\t\t\t\t\t\t\t\t\tEnforced\tLevel\t\tConditions\n\t\t\t\t\t\t\t\t\t--------\t-----\t\t----------\n\taaIssuingDistributionPoint\t\t   -\t\t Full\t\t   Rev\n\tadditionalInformation (SigG)\t   -\t\tPartial\t\t Obscure\n\tadmissions (SigG)\t\t\t\t   -\t\tPartial\t\t Obscure\n\tauthorityInfoAccess\t\t\t\t   -\t\t  -\t\t\t\t-\n\tauthorityKeyIdentifier\t\t\t   -\t\tPartial\t\t\t-\n\tautonomousSysIds (RPKI)\t\t\t   -\t\t  -\t\t\t\t-\n\tbasicConstraints\t\t\t\t  Yes\t\t  -\t\t\t\t-\n\tbiometricInfo (QualifiedCert)\t   -\t\t Full\t\t\t-\n\tcertCardRequired (SET)\t\t\t   -\t\tPartial\t\t Obsolete\n\tcertHash (SigG, OCSP)\t\t\t   -\t\tPartial\t\t Obscure, Rev\n\tcertificateIssuer\t\t\t\t   -\t\t Full\t\t   Rev\n\tcertificatePolicies\t\t\t\t  Yes\t\t  -\t\t\t\t-\n\tcertificateType (SET)\t\t\t   -\t\tPartial\t\t Obsolete\n\tchallengePassword (SCEP)\t\t   -\t\t  -\t\t\t   Req\n\tcRLDistributionPoints\t\t\t   -\t\t  -\t\t\t\t-\n\tcRLNumber\t\t\t\t\t\t   -\t\tPartial\t\t   Rev\n\tcRLReason\t\t\t\t\t\t   -\t\t  -\t\t\tRev | Req\n\tcRLExtReason\t\t\t\t\t   -\t\t  -\t\t\t   Rev\n\tcrlStreamIdentifier\t\t\t\t   -\t\t Full\t\t   Rev\n\tdateOfCertGen (SigG)\t\t\t   -\t\tPartial\t\t Obscure\n\tdeclarationOfMajority (SigG)\t   -\t\tPartial\t\t Obscure\n\tdeltaCRLIndicator\t\t\t\t   -\t\tPartial\t\t   Rev\n\tdeltaInfo\t\t\t\t\t\t   -\t\t Full\t\t   Rev\n\texpiredCertsOnCRL\t\t\t\t   -\t\t Full\t\t   Rev\n\textKeyUsage\t\t\t\t\t\t  Yes\t\t  -\t\t\t\t-\n\tfreshestCRL\t\t\t\t\t\t   -\t\t Full\t\t   Rev\n\thashedRootKey (SET)\t\t\t\t   -\t\tPartial\t\t Obsolete\n\tholdInstructionCode\t\t\t\t   -\t\tPartial\t\tRev | Req\n\tinhibitAnyPolicy\t\t\t\t  Yes\t\t Full\t\t\t-\n\tinvalidityDate\t\t\t\t\t   -\t\t  -\t\t\tRev | Req\n\tipAddrBlocks (RPKI)\t\t\t\t   -\t\t  -\t\t\t\t-\n\tissuerAltName\t\t\t\t\t   -\t\t  -\t\t\t\t-\n\tissuingDistributionPoint\t\t   -\t\tPartial\t\t   Rev\n\tkeyFeatures\t\t\t\t\t\t   -\t\t  -\t\t\t\t-\n\tkeyUsage\t\t\t\t\t\t  Yes\t\t  -\t\t\t\t-\n\tmonetaryLimit (SigG)\t\t\t   -\t\tPartial\t\t Obscure\n\tnameConstraints\t\t\t\t\t  Yes\t\t Full\t\t\t-\n\tnetscape-cert-type\t\t\t\t  Yes\t\t  -\t\t\t Obsolete\n\tnetscape-base-url\t\t\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-revocation-url\t\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-ca-revocation-url\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-cert-renewal-url\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-ca-policy-url\t\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-ssl-server-name\t\t   -\t\t  -\t\t\t Obsolete\n\tnetscape-comment\t\t\t\t   -\t\t  -\t\t\t Obsolete\n\tmerchantData (SET)\t\t\t\t   -\t\tPartial\t\t Obsolete\n\tocspAcceptableResponse (OCSP)\t   -\t\tPartial\t\t   Rev\n\tocspArchiveCutoff (OCSP)\t\t   -\t\tPartial\t\t   Rev\n\tocspNoCheck (OCSP)\t\t\t\t   -\t\tPartial\t\t   Rev\n\tocspNonce (OCSP)\t\t\t\t   -\t\t  -\t\t\t   Rev\n\torderedList\t\t\t\t\t\t   -\t\t Full\t\t   Rev\n\tpolicyConstraints\t\t\t\t Yes/No\t\t Full\t\t\t-\n\tpolicyMappings\t\t\t\t\t  No\t\t Full\t\t\t-\n\tprivateKeyUsagePeriod\t\t\t  Yes\t\tPartial\t\t\t-\n\tprocuration (SigG)\t\t\t\t   -\t\tPartial\t\t Obscure\n\tqcStatements (QualifiedCert)\t   -\t\t Full\t\t\t-\n\trestriction (SigG)\t\t\t\t   -\t\tPartial\t\t Obscure\n\trevokedGroups\t\t\t\t\t   -\t\t Full\t\t   Rev\n  [\tsigningCertificate\t\t\t\t   -\t\t  -\t\t\t   Rev ]\n\tstrongExtranet (Thawte)\t\t\t   -\t\tPartial\t\t Obsolete\n\tsubjectAltName\t\t\t\t\t   -\t\t  -\t\t\t\t-\n\tsubjectDirectoryAttributes\t\t   -\t\tPartial\t\t\t-\n\tsubjectInfoAccess\t\t\t\t   -\t\t  -\t\t\t\t-\n\tsubjectKeyIdentifier\t\t\t   -\t\t  -\t\t\t\t-\n\ttoBeRevoked\t\t\t\t\t\t   -\t\t Full\t\t   Rev\n\ttunneling (SET)\t\t\t\t\t   -\t\tPartial\t\t Obsolete\n\n   Of these extensions, only a very small number are permitted in certificate \n   requests for security reasons, see the code comment for \n   sanitiseCertAttributes() in comp_set.c before changing any of these \n   values.\n\n   Since some extensions fields are tagged the fields as encoded differ from\n   the fields as defined by the tagging, the following macro is used to turn\n   a small integer into a context-specific tag.  By default the tag is\n   implicit as per X.509v3, to make it an explicit tag we need to set the\n   FL_EXPLICIT flag for the field */\n\n#define CTAG( x )\t\t\t( x | BER_CONTEXT_SPECIFIC )\n\n/* Symbolic defines to make the encoded forms more legible */\n\n#define ENCODING( tag )\t\tBER_##tag, CRYPT_UNUSED\n#define ENCODING_SPECIAL( value ) \\\n\t\t\t\t\t\t\tFIELDTYPE_##value, CRYPT_UNUSED\n#define ENCODING_TAGGED( tag, outerTag ) \\\n\t\t\t\t\t\t\tBER_##tag, outerTag\n#define ENCODING_SPECIAL_TAGGED( tag, outerTag ) \\\n\t\t\t\t\t\t\tFIELDTYPE_##tag, outerTag\n#define RANGE( min, max )\tmin, max, 0, NULL\n#define RANGE_ATTRIBUTEBLOB\t1, MAX_ATTRIBUTE_SIZE, 0, NULL\n#define RANGE_BLOB\t\t\t16, MAX_ATTRIBUTE_SIZE, 0, NULL\n#define RANGE_BOOLEAN\t\tFALSE, TRUE, FALSE, NULL \n#define RANGE_NONE\t\t\t0, 0, 0, NULL\n#define RANGE_OID\t\t\tMIN_OID_SIZE, MAX_OID_SIZE, 0, NULL\n#define RANGE_TEXTSTRING\t1, CRYPT_MAX_TEXTSIZE, 0, NULL\n#define RANGE_TIME\t\t\tsizeof( time_t ), sizeof( time_t ), 0, NULL\n#define RANGE_UNUSED\t\tCRYPT_UNUSED, CRYPT_UNUSED, 0, NULL\n#define ENCODED_OBJECT( altEncodingTable ) \\\n\t\t\t\t\t\t\t0, 0, 0, ( void * ) altEncodingTable\n#define CHECK_DNS\t\t\tMIN_DNS_SIZE, MAX_DNS_SIZE, 0, ( void * ) checkDNS\n#define CHECK_HTTP\t\t\tMIN_URL_SIZE, MAX_URL_SIZE, 0, ( void * ) checkHTTP\n#define CHECK_RFC822\t\tMIN_RFC822_SIZE, MAX_RFC822_SIZE, 0, ( void * ) checkRFC822\n#define CHECK_URL\t\t\tMIN_URL_SIZE, MAX_URL_SIZE, 0, ( void * ) checkURL\n#define CHECK_X500\t\t\t0, 0, 0, ( void * ) checkDirectoryName\n\n/* Symbolic defines for attribute type information */\n\n#define ATTR_TYPEINFO( type, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type | \\\n\t\t\t\t\t\t\t  FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO2( type1, type2, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type1 | \\\n\t\t\t\t\t\t\t  FL_VALID_##type2 | FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO3( type1, type2, type3, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type1 | \\\n\t\t\t\t\t\t\t  FL_VALID_##type2 | FL_VALID_##type3 | \\\n\t\t\t\t\t\t\t  FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO_CRITICAL( type, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type | \\\n\t\t\t\t\t\t\t  FL_ATTR_CRITICAL | FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO2_CRITICAL( type1, type2, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type1 | \\\n\t\t\t\t\t\t\t  FL_VALID_##type2 | FL_ATTR_CRITICAL | \\\n\t\t\t\t\t\t\t  FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO3_CRITICAL( type1, type2, type3, level ) \\\n\t\t\t\t\t\t\t( FL_LEVEL_##level | FL_VALID_##type1 | \\\n\t\t\t\t\t\t\t  FL_VALID_##type2 | FL_VALID_##type3 | \\\n\t\t\t\t\t\t\t  FL_ATTR_CRITICAL | FL_ATTR_ATTRSTART )\n#define ATTR_TYPEINFO_CMS\t( FL_ATTR_ATTRSTART )\n\n/* Extended checking functions */\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRFC822( const ATTRIBUTE_LIST *attributeListPtr );\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDNS( const ATTRIBUTE_LIST *attributeListPtr );\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkURL( const ATTRIBUTE_LIST *attributeListPtr );\n#ifdef USE_CERT_OBSOLETE\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkHTTP( const ATTRIBUTE_LIST *attributeListPtr );\n#endif /* USE_CERT_OBSOLETE */\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDirectoryName( const ATTRIBUTE_LIST *attributeListPtr );\n\n/* Forward declarations for alternative encoding tables used by the main \n   tables.  These are declared in a somewhat peculiar manner because there's \n   no clean way in C to forward declare a static array.  Under VC++ with the \n   highest warning level enabled this produces a compiler warning, so we \n   turn the warning off for this module.  In addition there are the usual \n   problems that crop up with gcc */\n\n#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )\n  static const ATTRIBUTE_INFO generalNameInfo[];\n  static const ATTRIBUTE_INFO holdInstructionInfo[];\n  static const ATTRIBUTE_INFO contentTypeInfo[];\n#else\n  extern const ATTRIBUTE_INFO generalNameInfo[];\n  extern const ATTRIBUTE_INFO holdInstructionInfo[];\n  extern const ATTRIBUTE_INFO contentTypeInfo[];\n#endif /* gcc 4.x */\n\n#if defined( _MSC_VER )\n  #pragma warning( disable: 4211 )\n#endif /* VC++ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Extension Definitions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Certificate extensions are encoded using the following table */\n\nstatic const ATTRIBUTE_INFO extensionInfo[] = {\n#ifdef USE_CERTREQ\n\t/* challengePassword:\n\n\t\tOID = 1 2 840 113549 1 9 7\n\t\tDirectoryString.\n\n\t   This is here even though it's a CMS attribute because SCEP stuffs it \n\t   into PKCS #10 requests */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x07\" ), CRYPT_CERTINFO_CHALLENGEPASSWORD,\n\t  DESCRIPTION( \"challengePassword\" )\n\t  ENCODING_SPECIAL( TEXTSTRING ),\n\t  ATTR_TYPEINFO( CERTREQ, STANDARD ) | FL_ATTR_ATTREND | FL_ATTR_NOCOPY, \n\t  FL_SPECIALENCODING, RANGE_TEXTSTRING },\n#endif /* USE_CERTREQ */\n\n#if defined( USE_CERTREV )\n\t/* signingCertificate:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 12\n\t\tSEQUENCE {\n\t\t\tSEQUENCE OF ESSCertID {\n\t\t\t\tcertHash\t\tOCTET STRING SIZE(20)\n\t\t\t\t},\t\t\t\t\t\t\t-- SIZE(1)\n\t\t\tSEQUENCE OF { ... } OPTIONAL\t-- ABSENT\n\t\t\t} \n\n\t   This is here even though it's a CMS attribute because it's required \n\t   in order to make OCSP work (a second copy is present with the CMS\n\t   attributes, see the remainder of this comment below).  Since OCSP \n\t   breaks up the certificate identification information into bits and \n\t   pieces and hashes some while leaving others intact, there's no way to \n\t   map what arrives at the responder back into a certificate without an \n\t   ability to reverse the cryptographic hash function.  To work around \n\t   this we include an ESSCertID in the request that properly identifies \n\t   the certificate being queried.  Since it's a limited-use version that \n\t   only identifies the certificate we don't allow a full \n\t   signingCertificate extension but only a single ESSCertID.  \n\t   \n\t   Note that having this attribute here is somewhat odd in that type-\n\t   checking is done via the equivalent entry in the CMS attributes \n\t   because the fieldID identifies it as a CMS attribute but decoding is \n\t   done via this entry because the decoder loops through the certificate \n\t   attribute entries to find the decoding information.  For this reason \n\t   if OCSP use is enabled then both this entry and the one in the CMS \n\t   attributes must be enabled */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x0C\" ), CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE,\n\t  DESCRIPTION( \"signingCertificate\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( OCSPREQ /*Per-entry*/, STANDARD ), \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.certs\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID,\n\t  DESCRIPTION( \"signingCertificate.certs.essCertID\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  FL_ATTR_ATTREND, FL_SEQEND_2 /*FL_SEQEND*/, RANGE_BLOB },\n\n\t/* cRLExtReason:\n\n\t\tOID = 1 3 6 1 4 1 3029 3 1 4\n\t\tENUMERATED */\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x03\\x01\\x04\" ), CRYPT_CERTINFO_CRLEXTREASON,\n\t  DESCRIPTION( \"cRLExtReason\" )\n\t  ENCODING( ENUMERATED ),\n\t  ATTR_TYPEINFO2( REVREQ /*Per-entry*/, CRL, STANDARD ) | FL_ATTR_ATTREND, \n\t  0, RANGE( 0, CRYPT_CRLEXTREASON_LAST ) },\n#endif /* USE_CERTREV */\n\n\t/* keyFeatures:\n\n\t\tOID = 1 3 6 1 4 1 3029 3 1 5\n\t\tBITSTRING */\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x03\\x01\\x05\" ), CRYPT_CERTINFO_KEYFEATURES,\n\t  DESCRIPTION( \"keyFeatures\" )\n\t  ENCODING( BITSTRING ),\n\t  ATTR_TYPEINFO2( CERT, CERTREQ, STANDARD ) | FL_ATTR_ATTREND, \n\t  0, RANGE( 0, 7 ) },\n\n\t/* authorityInfoAccess:\n\n\t\tOID = 1 3 6 1 5 5 7 1 1\n\t\tSEQUENCE SIZE (1...MAX) OF {\n\t\t\tSEQUENCE {\n\t\t\t\taccessMethod\tOBJECT IDENTIFIER,\n\t\t\t\taccessLocation\tGeneralName\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x01\" ), CRYPT_CERTINFO_AUTHORITYINFOACCESS,\n\t  DESCRIPTION( \"authorityInfoAccess\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ), \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (rtcs)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x03\\x01\\x07\" ), 0,\n\t  DESCRIPTION( \"authorityInfoAccess.rtcs (1 3 6 1 4 1 3029 3 1 7)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITYINFO_RTCS,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription.accessLocation (rtcs)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (ocsp)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\" ), 0,\n\t  DESCRIPTION( \"authorityInfoAccess.ocsp (1 3 6 1 5 5 7 48 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITYINFO_OCSP,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription.accessLocation (ocsp)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (caIssuers)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x02\" ), 0,\n\t  DESCRIPTION( \"authorityInfoAccess.caIssuers (1 3 6 1 5 5 7 48 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription.accessLocation (caIssuers)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (httpCerts)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x06\" ), 0,\n\t  DESCRIPTION( \"authorityInfoAccess.httpCerts (1 3 6 1 5 5 7 48 6)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription.accessLocation (httpCerts)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (httpCRLs)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x07\" ), 0,\n\t  DESCRIPTION( \"authorityInfoAccess.httpCRLs (1 3 6 1 5 5 7 48 7)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITYINFO_CRLS,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription.accessLocation (httpCRLs)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.accessDescription (catchAll)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityInfoAccess.catchAll\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* Match anything and ignore it */\n\t  FL_ATTR_ATTREND, FL_NONENCODING | FL_SEQEND_2 /*FL_SEQEND*/, RANGE_NONE },\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* biometricInfo (QualifiedCert):\n\n\t\tOID = 1 3 6 1 5 5 7 1 2\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\ttypeOfData\t\tINTEGER,\n\t\t\t\thashAlgorithm\tOBJECT IDENTIFIER,\n\t\t\t\tdataHash\t\tOCTET STRING,\n\t\t\t\tsourceDataUri\tIA5String OPTIONAL\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x02\" ), CRYPT_CERTINFO_BIOMETRICINFO,\n\t  DESCRIPTION( \"biometricInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_FULL ), \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"biometricInfo.biometricData\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_BIOMETRICINFO_TYPE,\n\t  DESCRIPTION( \"biometricInfo.biometricData.typeOfData\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_MULTIVALUED, RANGE( 0, 1 ) },\n\t{ NULL, CRYPT_CERTINFO_BIOMETRICINFO_HASHALGO,\n\t  DESCRIPTION( \"biometricInfo.biometricData.hashAlgorithm\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_BIOMETRICINFO_HASH,\n\t  DESCRIPTION( \"biometricInfo.biometricData.dataHash\" )\n\t  ENCODING( OCTETSTRING ),\n\t  0, FL_MULTIVALUED, RANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) },\n\t{ NULL, CRYPT_CERTINFO_BIOMETRICINFO_URL,\n\t  DESCRIPTION( \"biometricInfo.biometricData.sourceDataUri\" )\n\t  ENCODING( STRING_IA5 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2 /*FL_SEQEND*/, CHECK_URL },\n\n\t/* qcStatements (QualifiedCert):\n\n\t\tOID = 1 3 6 1 5 5 7 1 3\n\t\tcritical = TRUE\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\tstatementID\t\tOBJECT IDENTIFIER,\n\t\t\t\tstatementInfo\tSEQUENCE {\n\t\t\t\t\tsemanticsIdentifier\tOBJECT IDENTIFIER OPTIONAL,\n\t\t\t\t\tnameRegistrationAuthorities SEQUENCE OF GeneralName\n\t\t\t\t}\n\t\t\t}\n\n\t\tThere are two versions of the statementID OID, one for RFC 3039 and\n\t\tthe other for RFC 3739 (which are actually identical except where\n\t\tthey're not).  To handle this we preferentially encode the RFC 3739\n\t\t(v2) OID but allow the v1 OID as a fallback by marking both as\n\t\toptional */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x03\" ), CRYPT_CERTINFO_QCSTATEMENT,\n\t  DESCRIPTION( \"qcStatements\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CRITICAL( CERT, PKIX_FULL ), \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"qcStatements.qcStatement (statementID)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x0B\\x02\" ), 0,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementID (1 3 6 1 5 5 7 11 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x0B\\x01\" ), 0,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementID (Backwards-compat.) (1 3 6 1 5 5 7 11 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementInfo (statementID)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementInfo.semanticsIdentifier (statementID)\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementInfo.nameRegistrationAuthorities (statementID)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY,\n\t  DESCRIPTION( \"qcStatements.qcStatement.statementInfo.nameRegistrationAuthorities.generalNames\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, /*FL_MULTIVALUED |*/ FL_SEQEND_3 /* Really _4*/, ENCODED_OBJECT( generalNameInfo ) },\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n#ifdef USE_RPKI\n\t/* ipAddrBlocks (RPKI):\n\n\t\tOID = 1 3 6 1 5 5 7 1 7\n\t\tcritical = TRUE\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\taddressFamily\tOCTET STRING (SIZE(2)),\n\t\t\t\taddressesOrRanges SEQUENCE OF {\n\t\t\t\t\tCHOICE {\n\t\t\t\t\taddressPrefix\n\t\t\t\t\t\t\t\tBITSTRING,\t\t-- Treated as blob, see below\n\t\t\t\t\taddressRange\tSEQUENCE {\n\t\t\t\t\t\tmin\t\tBITSTRING,\t\t-- Treated as blob, see below\n\t\t\t\t\t\tmax\t\tBITSTRING\t\t-- Treated as blob, see below\n\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} \n\n\t   The length range for the BIT STRING is 3 bytes (zero-length string \n\t   for all IP address blocks) up to 19 bytes (16-byte IPv6 address plus \n\t   3-byte BIT STRING header) */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x07\" ), CRYPT_CERTINFO_IPADDRESSBLOCKS,\n\t  DESCRIPTION( \"ipAddrBlocks\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ), \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressFamily\" )\n\t  ENCODING( OCTETSTRING ),\n\t  0, FL_MULTIVALUED, RANGE( 2, 2 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressesOrRanges\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressesOrRanges.addressPrefix\" )\n\t  ENCODING_SPECIAL( BLOB_BITSTRING ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, 3, 19 },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressesOrRanges.addressRange\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_IPADDRESSBLOCKS_MIN,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressesOrRanges.addressRange.min\" )\n\t  ENCODING_SPECIAL( BLOB_BITSTRING ),\n\t  0, FL_MULTIVALUED, 3, 19 },\n\t{ NULL, CRYPT_CERTINFO_IPADDRESSBLOCKS_MAX,\n\t  DESCRIPTION( \"ipAddrBlocks.ipAddressFamily.addressesOrRanges.addressRange.max\" )\n\t  ENCODING_SPECIAL( BLOB_BITSTRING ),\n\t  FL_ATTR_ATTREND, FL_SEQEND_4 | FL_MULTIVALUED, 3, 19 },\n\n\t/* autonomousSysIds (RPKI):\n\n\t\tOID = 1 3 6 1 5 5 7 1 8\n\t\tcritical = TRUE\n\t\tSEQUENCE { \n\t\t\t[ 0 ] EXPLICIT SEQUENCE OF {\n\t\t\t\tCHOICE {\n\t\t\t\tasId\t\t\tINTEGER,\n\t\t\t\tasRange SEQUENCE {\n\t\t\t\t\tmin\t\t\tINTEGER,\n\t\t\t\t\tmax\t\t\tINTEGER\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} \n\n\t\tThe AS ranges are a bit difficult to provide sensible restrictions\n\t\tfor, traditionally they were 16-bit numbers but then RFC 4893 \n\t\textended them to 32-bits, of which subranges up to about 400K have\n\t\tbeen allocated (with wierd huge gaps in between the small set of\n\t\tsubranges in use), see http://www.iana.org/assignments/as-numbers/ \n\t\tfor current assignments.  We set a limit of 500K to allow some \n\t\tsanity-checking while also allowing room for future expansion */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x08\" ), CRYPT_CERTINFO_AUTONOMOUSSYSIDS,\n\t  DESCRIPTION( \"autonomousSysIds\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ), \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"autonomousSysIds.asnum\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_SETOF | FL_EXPLICIT, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID,\n\t  DESCRIPTION( \"autonomousSysIds.asnum.asIdsOrRanges.asId\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, 1, 500000 },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"autonomousSysIds.asnum.asIdsOrRanges.asRange\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN,\n\t  DESCRIPTION( \"autonomousSysIds.asnum.asIdsOrRanges.asRange.min\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_MULTIVALUED, 1, 500000 },\n\t{ NULL, CRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX,\n\t  DESCRIPTION( \"autonomousSysIds.asnum.asIdsOrRanges.asRange.max\" )\n\t  ENCODING( INTEGER ),\n\t  FL_ATTR_ATTREND, FL_SEQEND_3 | FL_MULTIVALUED, 1, 500000 },\n#endif /* USE_RPKI */\n\n#ifdef USE_CERTREV\n\t/* ocspNonce:\n\n\t\tOID = 1 3 6 1 5 5 7 48 1 2\n\t\tnonce\t\tOCTET STRING\n\n\t   This value was apparently supposed to be an OCTET STRING (although it \n\t   may also have been a cargo-cult design version of TSP's INTEGER), \n\t   however while specifying a million pieces of unnecessary braindamage \n\t   OCSP forgot to actually define this anywhere in the spec.  Because of \n\t   this it's possible to get other stuff here as well, the worst-case \n\t   being OpenSSL 0.9.6/0.9.7a-c which just dumps a raw blob (not even \n\t   valid ASN.1 data) in here.  We can't do anything with this since we \n\t   need at least something DER-encoded to be able to read it.  OpenSSL \n\t   0.9.7d and later used an OCTET STRING.  The length is (somewhat\n\t   arbitrarily) set at 256 bits, corresponding to a SHA-256 hash, to \n\t   prevent it being (easily) used for chosen-prefix attacks.\n\t   \n\t   We set the en/decoding level to FL_LEVEL_OBLIVIOUS to make sure that \n\t   it's still encoded even in oblivious mode, if we don't do this then a \n\t   nonce in a request won't be returned in the response if the user is \n\t   running at a reduced compliance level */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x02\" ), CRYPT_CERTINFO_OCSP_NONCE,\n\t  DESCRIPTION( \"ocspNonce\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO2( OCSPREQ, OCSPRESP, OBLIVIOUS ) | FL_ATTR_ATTREND, \n\t  0, RANGE( 1, 32 ) },\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* ocspAcceptableResponses:\n\n\t\tOID = 1 3 6 1 5 5 7 48 1 4\n\t\tSEQUENCE {\n\t\t\toidInstance1 OPTIONAL,\n\t\t\toidInstance2 OPTIONAL,\n\t\t\t\t...\n\t\t\toidInstanceN OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x04\" ), CRYPT_CERTINFO_OCSP_RESPONSE,\n\t  DESCRIPTION( \"ocspAcceptableResponses\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( OCSPREQ, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x01\" ), CRYPT_CERTINFO_OCSP_RESPONSE_OCSP,\n\t  DESCRIPTION( \"ocspAcceptableResponses.ocsp (1 3 6 1 5 5 7 48 1 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE_NONE },\n\n\t/* ocspNoCheck:\n\n\t\tOID = 1 3 6 1 5 5 7 48 1 5\n\t\tcritical = FALSE\n\t\tNULL\n\n\t   ocspNoCheck is a certificate extension rather than an OCSP request \n\t   extension, it's used by the CA in yet another of OCSP's schizophrenic \n\t   trust models to indicate that an OCSP responder certificate shouldn't \n\t   be checked until it expires naturally.  The value is treated as a \n\t   pseudo-numeric value that must be CRYPT_UNUSED when written and is \n\t   explicitly set to CRYPT_UNUSED when read */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x05\" ), CRYPT_CERTINFO_OCSP_NOCHECK,\n\t  DESCRIPTION( \"ocspNoCheck\" )\n\t  ENCODING( NULL ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  FL_NONENCODING, RANGE_UNUSED },\n\n\t/* ocspArchiveCutoff:\n\n\t\tOID = 1 3 6 1 5 5 7 48 1 6\n\t\tarchiveCutoff\tGeneralizedTime */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x06\" ), CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF,\n\t  DESCRIPTION( \"ocspArchiveCutoff\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  ATTR_TYPEINFO( OCSPRESP, PKIX_PARTIAL ) | FL_ATTR_ATTREND, \n\t  0, RANGE_TIME },\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n#endif /* USE_CERTREV */\n\n\t/* subjectInfoAccess:\n\n\t\tOID = 1 3 6 1 5 5 7 1 11\n\t\tSEQUENCE SIZE (1...MAX) OF {\n\t\t\tSEQUENCE {\n\t\t\t\taccessMethod\tOBJECT IDENTIFIER,\n\t\t\t\taccessLocation\tGeneralName\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x01\\x0B\" ), CRYPT_CERTINFO_SUBJECTINFOACCESS,\n\t  DESCRIPTION( \"subjectInfoAccess\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ), \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (timeStamping)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x03\" ), 0,\n\t  DESCRIPTION( \"subjectInfoAccess.timeStamping (1 3 6 1 5 5 7 48 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription.accessLocation (timeStamping)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (caRepository)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x05\" ), 0,\n\t  DESCRIPTION( \"subjectInfoAccess.caRepository (1 3 6 1 5 5 7 48 5)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription.accessLocation (caRepository)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (signedObjectRepository)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x09\" ), 0,\n\t  DESCRIPTION( \"subjectInfoAccess.signedObjectRepository (1 3 6 1 5 5 7 48 9)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription.accessLocation (signedObjectRepository)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (rpkiManifest)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x0A\" ), 0,\n\t  DESCRIPTION( \"subjectInfoAccess.rpkiManifest (1 3 6 1 5 5 7 48 10)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription.accessLocation (rpkiManifest)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (signedObject)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x0B\" ), 0,\n\t  DESCRIPTION( \"subjectInfoAccess.signedObject (1 3 6 1 5 5 7 48 11)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription.accessLocation (signedObject)\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.accessDescription (catchAll)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectInfoAccess.catchAll\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* Match anything and ignore it */\n\t  FL_ATTR_ATTREND, FL_NONENCODING | FL_SEQEND_2 /*FL_SEQEND*/, RANGE_NONE },\n\n#if defined( USE_CERT_OBSCURE ) && defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\t/* dateOfCertGen (SigG)\n\n\t\tOID = 1 3 36 8 3 1\n\t\tdateOfCertGen\t\t\t\tGeneralizedTime */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x01\" ), CRYPT_CERTINFO_SIGG_DATEOFCERTGEN,\n\t  DESCRIPTION( \"dateOfCertGen\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND, \n\t  0, RANGE_TIME },\n\n\t/* procuration (SigG)\n\n\t\tOID = 1 3 36 8 3 2\n\t\tSEQUENCE OF {\n\t\t\tcountry\t\t\t  [ 1 ]\tEXPLICIT PrintableString SIZE(2) OPTIONAL,\n\t\t\ttypeOfSubstitution[ 2 ]\tEXPLICIT PrintableString OPTIONAL,\n\t\t\tsigningFor\t\t  [ 3 ]\tEXPLICIT GeneralName\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x02\" ), CRYPT_CERTINFO_SIGG_PROCURATION,\n\t  DESCRIPTION( \"procuration\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY,\n\t  DESCRIPTION( \"procuration.country\" )\n\t  ENCODING_TAGGED( STRING_PRINTABLE, 1 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_EXPLICIT, RANGE( 2, 2 ) },\n\t{ NULL, CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION,\n\t  DESCRIPTION( \"procuration.typeOfSubstitution\" )\n\t  ENCODING_TAGGED( STRING_PRINTABLE, 2 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_EXPLICIT, RANGE( 1, 128 ) },\n\t{ NULL, CRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR,\n\t  DESCRIPTION( \"procuration.signingFor.thirdPerson\" )\n\t  ENCODING_SPECIAL_TAGGED( SUBTYPED, 3 ),\n\t  FL_ATTR_ATTREND, FL_EXPLICIT | FL_SEQEND /*NONE*/, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* admissions (SigG)\n\n\t\tOID = 1 3 36 8 3 3\n\t\tSEQUENCE {\n\t\t\tauthority\t\t\tGeneralName OPTIONAL,\n\t\t\tcontent\t\t\t\tSEQUENCE OF {\n\t\t\t\tnamingAuthority\t[ 1 ] EXPLICIT SEQUENCE {\n\t\t\t\t\tnamingAuthID\t\tOBJECT IDENTIFIER OPTIONAL,\n\t\t\t\t\tnamingAuthURL\t\tIA5String OPTIONAL,\n\t\t\t\t\tnamingAuthText\t\tPrintableString OPTIONAL\n\t\t\t\t\t} OPTIONAL,\n\t\t\t\tprofessionInfo SEQUENCE OF {\n\t\t\t\t\tprofessionItems SEQUENCE OF {\n\t\t\t\t\t\tprofessionItem\tPrintableString\n\t\t\t\t\t\t},\n\t\t\t\t\tprofessionOIDs SEQUENCE OF {\n\t\t\t\t\t\tprofessionOID\tOBJECT IDENTIFIER\n\t\t\t\t\t\t} OPTIONAL,\n\t\t\t\t\tregistrationNumber\tPrintableString OPTIONAL\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} \n\n\t\tThis is a weird extension with several fields (admissionAuthority, namingAuthority)\n\t\tduplicated in two places and only a vague indication in the spec as to which one\n\t\tis used under which conditions, the above is an attempt to create a meaningful\n\t\tinterpretation of the definition */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x03\" ), CRYPT_CERTINFO_SIGG_ADMISSIONS,\n\t  DESCRIPTION( \"admissions\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY,\n\t  DESCRIPTION( \"admissions.authority\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"admissions.content\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"admissions.content.namingAuthority\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL | FL_EXPLICIT, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID,\n\t  DESCRIPTION( \"admissions.content.namingAuthority.namingAuthID\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL,\n\t  DESCRIPTION( \"admissions.content.namingAuthority.namingAuthURL\" )\n\t  ENCODING( STRING_IA5 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_TEXTSTRING },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT,\n\t  DESCRIPTION( \"admissions.content.namingAuthority.namingAuthText\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND, RANGE_TEXTSTRING },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"admissions.professionInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"admissions.professionInfo.professionItems\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM,\n\t  DESCRIPTION( \"admissions.professionInfo.professionItems.professionItem\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  0, FL_MULTIVALUED | FL_SEQEND, RANGE_TEXTSTRING },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"admissions.professionInfo.professionOIDs\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID,\n\t  DESCRIPTION( \"admissions.professionInfo.professionOIDs.professionOID\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER,\n\t  DESCRIPTION( \"admissions.professionInfo.professionItems.registrationNumber\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_3, RANGE_TEXTSTRING },\n\n\t/* monetaryLimit (SigG)\n\n\t\tOID = 1 3 36 8 3 4\n\t\tSEQUENCE {\n\t\t\tcurrency\t\t\tPrintableString SIZE(3),\n\t\t\tamount\t\t\t\tINTEGER,\n\t\t\texponent\t\t\tINTEGER\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x04\" ), CRYPT_CERTINFO_SIGG_MONETARYLIMIT,\n\t  DESCRIPTION( \"monetaryLimit\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY,\n\t  DESCRIPTION( \"monetaryLimit.currency\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  0, 0, RANGE( 3, 3 ) },\n\t{ NULL, CRYPT_CERTINFO_SIGG_MONETARY_AMOUNT,\n\t  DESCRIPTION( \"monetaryLimit.amount\" )\n\t  ENCODING( INTEGER ),\n\t  0, 0, RANGE( 1, 255 ) },\t/* That's what the spec says */\n\t{ NULL, CRYPT_CERTINFO_SIGG_MONETARY_EXPONENT,\n\t  DESCRIPTION( \"monetaryLimit.exponent\" )\n\t  ENCODING( INTEGER ),\n\t  FL_ATTR_ATTREND, FL_SEQEND /*NONE*/, RANGE( 0, 255 ) },\n\n\t/* declarationOfMajority (SigG)\n\n\t\tOID = 1 3 36 8 3 5\n\t\tCHOICE {\n\t\t\tfullAgeAtCountry [ 1 ] SEQUENCE {\n\t\t\t\tfullAge\t\t\tDEFAULT TRUE,\n\t\t\t\tcountry\t\t\tPrintableString (SIZE(2))\n\t\t\t\t},\n\t\t\tdateOfBirth\t  [ 2 ]\tGeneralizedTime\n\t\t\t} \n\n\t\tThis is a rather problematic extension because it uses a CHOICE at \n\t\tthe top level so there's no easy way to work with it because, \n\t\tdepending on whether the fullAgeAtCountry or dateOfBirth is used, \n\t\tthe extension has a different name.  To deal with this we rely on\n\t\tthe fact that in privacy-conscious Europe where this is unlikely\n\t\tto be used (as opposed to everywhere else, where it definitely\n\t\twon't be used) it's unlikely that people will want personally\n\t\tidentifiable information like birth dates in certificates and so\n\t\twhat'll be used in practice is the fullAgeAtCountry.\n\n\t\tThe fullAgeAtCountry has an additional complication in that in \n\t\ttheory there's a fullAge field that precedes the country field but\n\t\tsince it's declared as DEFAULT TRUE and a declaration of majority\n\t\tcan't be false it can never occur in any (sane) implementation.\n\n\t\tThe resulting extension is therefore:\n\n\t\tdeclarationOfMajority [ 1 ] EXPLICIT SEQUENCE {\n\t\t\t\tcountry\t\t\tPrintableString (SIZE(2))\n\t\t\t\t} */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x05\" ), CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY,\n\t  DESCRIPTION( \"declarationOfMajority\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  FL_EXPLICIT, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY,\n\t  DESCRIPTION( \"declarationOfMajority.fullAgeAtCountry.country\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  FL_ATTR_ATTREND, FL_SEQEND, RANGE( 2, 2 ) },\n\n\t/* restriction (SigG)\n\n\t\tOID = 1 3 36 8 3 8\n\t\trestriction\t\t\t\tPrintableString */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x08\" ), CRYPT_CERTINFO_SIGG_RESTRICTION,\n\t  DESCRIPTION( \"restriction\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 1, 128 ) },\n\n#ifdef USE_CERTREV\n\t/* certHash  (SigG, OCSP)\n\n\t\tOID = 1 3 36 8 3 13\n\t\tSEQUENCE {\n\t\t\thashAlgo\tAlgorithmIdentifier,\n\t\t\tcertHash\tOCTET STRING\n\t\t\t} */\n\t{ NULL, CRYPT_CERTINFO_SIGG_CERTHASH,\n\t  DESCRIPTION( \"certhash\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE_BLOB },\n#endif /* USE_CERTREV */\n\n\t/* additionalInformation (SigG)\n\n\t\tOID = 1 3 36 8 3 15\n\t\tadditionalInformation\tPrintableString */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x03\\x0F\" ), CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION,\n\t  DESCRIPTION( \"additionalInformation\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 1, 128 ) },\n#endif /* USE_CERT_OBSCURE && USE_CERTLEVEL_PKIX_PARTIAL */\n\n#ifdef USE_CERT_OBSOLETE\n\t/* strongExtranet:\n\n\t\tOID = 1 3 101 1 4 1\n\t\tSEQUENCE {\n\t\t\tversion\t\t\t\tINTEGER (0),\n\t\t\tSEQUENCE OF {\n\t\t\t\tSEQUENCE {\n\t\t\t\t\tzone\t\tINTEGER,\n\t\t\t\t\tid\t\t\tOCTET STRING (SIZE(1..64))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x65\\x01\\x04\\x01\" ), CRYPT_CERTINFO_STRONGEXTRANET,\n\t  DESCRIPTION( \"strongExtranet\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"strongExtranet.version\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* INTEGER 0 */\n\t  0, FL_NONENCODING, 0, 0, 3, \"\\x02\\x01\\x00\" },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"strongExtranet.sxNetIDList\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"strongExtranet.sxNetIDList.sxNetID\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_STRONGEXTRANET_ZONE,\n\t  DESCRIPTION( \"strongExtranet.sxNetIDList.sxNetID.zone\" )\n\t  ENCODING( INTEGER ),\n\t  0, 0, RANGE( 0, MAX_INTLENGTH ) },\n\t{ NULL, CRYPT_CERTINFO_STRONGEXTRANET_ID,\n\t  DESCRIPTION( \"strongExtranet.sxNetIDList.sxnetID.id\" )\n\t  ENCODING( OCTETSTRING ),\n\t  FL_ATTR_ATTREND, FL_SEQEND_3 /*FL_SEQEND_2*/, RANGE( 1, 64 ) },\n#endif /* USE_CERT_OBSOLETE */\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* subjectDirectoryAttributes:\n\n\t\tOID = 2 5 29 9\n\t\tSEQUENCE SIZE (1..MAX) OF {\n\t\t\tSEQUENCE {\n\t\t\t\ttype\t\t\tOBJECT IDENTIFIER,\n\t\t\t\tvalues\t\t\tSET OF ANY\t\t\t-- SIZE (1)\n\t\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x09\" ), CRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES,\n\t  DESCRIPTION( \"subjectDirectoryAttributes\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectDirectoryAttributes.attribute\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTDIR_TYPE,\n\t  DESCRIPTION( \"subjectDirectoryAttributes.attribute.type\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"subjectDirectoryAttributes.attribute.values\" )\n\t  ENCODING( SET ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTDIR_VALUES,\n\t  DESCRIPTION( \"subjectDirectoryAttributes.attribute.values.value\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\n\t  FL_ATTR_ATTREND, FL_MULTIVALUED | FL_SEQEND_2 /*SEQEND*/, RANGE_ATTRIBUTEBLOB },\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* subjectKeyIdentifier:\n\n\t\tOID = 2 5 29 14\n\t\tOCTET STRING\n\n\t   In theory this should only be processed at level \n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL but the sKID is a universal \n\t   identifier that's often used in place of the DN to identify a\n\t   certificate so unlike the authorityKeyIdentifier we process it even \n\t   in standard mode */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x0E\" ), CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t  DESCRIPTION( \"subjectKeyIdentifier\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 1, 64 ) },\n\n\t/* keyUsage:\n\n\t\tOID = 2 5 29 15\n\t\tcritical = TRUE\n\t\tBITSTRING */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x0F\" ), CRYPT_CERTINFO_KEYUSAGE,\n\t  DESCRIPTION( \"keyUsage\" )\n\t  ENCODING( BITSTRING ),\n\t  ATTR_TYPEINFO2_CRITICAL( CERTREQ, CERT, REDUCED ) | FL_ATTR_ATTREND,\n\t  0, 0, CRYPT_KEYUSAGE_LAST, 0, NULL },\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* privateKeyUsagePeriod:\n\n\t\tOID = 2 5 29 16\n\t\tSEQUENCE {\n\t\t\tnotBefore\t  [ 0 ]\tGeneralizedTime OPTIONAL,\n\t\t\tnotAfter\t  [ 1 ]\tGeneralizedTime OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x10\" ), CRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD,\n\t  DESCRIPTION( \"privateKeyUsagePeriod\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE,\n\t  DESCRIPTION( \"privateKeyUsagePeriod.notBefore\" )\n\t  ENCODING_TAGGED( TIME_GENERALIZED, 0 ),\n\t  0, FL_OPTIONAL, RANGE_TIME },\n\t{ NULL, CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER,\n\t  DESCRIPTION( \"privateKeyUsagePeriod.notAfter\" )\n\t  ENCODING_TAGGED( TIME_GENERALIZED, 1 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE_TIME },\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* subjectAltName:\n\n\t\tOID = 2 5 29 17\n\t\tSEQUENCE OF GeneralName\n\t\n\t   The handling of the SEQUENCE OF GeneralName for this attribute and \n\t   others where the construct is used is somewhat peculiar in that it's\n\t   not given as FL_MULTIVALUED, see the comment in the generalNameInfo\n\t   table for details */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x11\" ), FIELDID_FOLLOWS,\n\t  DESCRIPTION( \"subjectAltName\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERTREQ, CERT, STANDARD ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTALTNAME,\n\t  DESCRIPTION( \"subjectAltName.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, /*FL_MULTIVALUED |*/ FL_SEQEND /*NONE*/, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* issuerAltName:\n\n\t\tOID = 2 5 29 18\n\t\tSEQUENCE OF GeneralName\n\t\n\t   The handling of the SEQUENCE OF GeneralName for this attribute and \n\t   others where the construct is used is somewhat peculiar in that it's\n\t   not given as FL_MULTIVALUED, see the comment in the generalNameInfo\n\t   table for details */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x12\" ), FIELDID_FOLLOWS,\n\t  DESCRIPTION( \"issuerAltName\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERT, CRL, STANDARD ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_ISSUERALTNAME,\n\t  DESCRIPTION( \"issuerAltName.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, /*FL_MULTIVALUED |*/ FL_SEQEND /*NONE*/, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* basicConstraints:\n\n\t\tOID = 2 5 29 19\n\t\tcritical = TRUE\n\t\tSEQUENCE {\n\t\t\tcA\t\t\t\t\tBOOLEAN DEFAULT FALSE,\n\t\t\tpathLenConstraint\tINTEGER (0..64) OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x13\" ), CRYPT_CERTINFO_BASICCONSTRAINTS,\n\t  DESCRIPTION( \"basicConstraints\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2_CRITICAL( CERT, ATTRCERT, REDUCED ),\n\t  FL_EMPTYOK, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CA,\n\t  DESCRIPTION( \"basicConstraints.cA\" )\n\t  ENCODING( BOOLEAN ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t  DESCRIPTION( \"basicConstraints.pathLenConstraint\" )\n\t  ENCODING( INTEGER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE( 0, 64 ) },\n\n#if defined( USE_CERTREV ) && defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\t/* cRLNumber:\n\n\t\tOID = 2 5 29 20\n\t\tINTEGER */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x14\" ), CRYPT_CERTINFO_CRLNUMBER,\n\t  DESCRIPTION( \"cRLNumber\" )\n\t  ENCODING( INTEGER ),\n\t  ATTR_TYPEINFO( CRL, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, MAX_INTLENGTH ) },\n#endif /* USE_CERTREV && USE_CERTLEVEL_PKIX_PARTIAL */\n\n#if defined( USE_CERTREV ) || defined( USE_CERTREQ )\n\t/* cRLReason:\n\n\t\tOID = 2 5 29 21\n\t\tENUMERATED */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x15\" ), CRYPT_CERTINFO_CRLREASON,\n\t  DESCRIPTION( \"cRLReason\" )\n\t  ENCODING( ENUMERATED ),\n\t  ATTR_TYPEINFO2( CRL, REVREQ /*Per-entry*/, REDUCED ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, CRYPT_CRLREASON_LAST ) },\n#endif /* USE_CERTREV || USE_CERTREQ */\n\n#if ( defined( USE_CERTREV ) || defined( USE_CERTREQ ) ) && \\\n\tdefined( USE_CERTLEVEL_PKIX_FULL )\n\t/* holdInstructionCode:\n\n\t\tOID = 2 5 29 23\n\t\tOBJECT IDENTIFIER */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x17\" ), CRYPT_CERTINFO_HOLDINSTRUCTIONCODE,\n\t  DESCRIPTION( \"holdInstructionCode\" )\n\t  ENCODING_SPECIAL( CHOICE ),\n\t  ATTR_TYPEINFO2( CRL, REVREQ /*Per-entry*/, PKIX_FULL ) | FL_ATTR_ATTREND,\n\t  0, CRYPT_HOLDINSTRUCTION_NONE, CRYPT_HOLDINSTRUCTION_LAST, 0, ( void * ) holdInstructionInfo },\n#endif /* ( USE_CERTREV || USE_CERTREQ ) && USE_CERTLEVEL_PKIX_FULL */\n\n#if defined( USE_CERTREV ) || defined( USE_CERTREQ )\n\t/* invalidityDate:\n\n\t\tOID = 2 5 29 24\n\t\tGeneralizedTime */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x18\" ), CRYPT_CERTINFO_INVALIDITYDATE,\n\t  DESCRIPTION( \"invalidityDate\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  ATTR_TYPEINFO2( CRL, REVREQ /*Per-entry*/, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, RANGE_TIME },\n#endif /* USE_CERTREV || USE_CERTREQ */\n\n#if defined( USE_CERTREV ) && defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\t/* deltaCRLIndicator:\n\n\t\tOID = 2 5 29 27\n\t\tcritical = TRUE\n\t\tINTEGER */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x1B\" ), CRYPT_CERTINFO_DELTACRLINDICATOR,\n\t  DESCRIPTION( \"deltaCRLIndicator\" )\n\t  ENCODING( INTEGER ),\n\t  ATTR_TYPEINFO_CRITICAL( CRL, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, MAX_INTLENGTH ) },\n\n\t/* issuingDistributionPoint:\n\n\t\tOID = 2 5 29 28\n\t\tcritical = TRUE\n\t\tSEQUENCE {\n\t\t\tdistributionPoint [ 0 ]\t{\n\t\t\t\tfullName\t  [ 0 ]\t{\t\t\t\t-- CHOICE { ... }\n\t\t\t\t\tSEQUENCE OF GeneralName\t\t\t-- GeneralNames\n\t\t\t\t\t}\n\t\t\t\t} OPTIONAL,\n\t\t\tonlyContainsUserCerts\n\t\t\t\t\t\t\t  [ 1 ]\tBOOLEAN DEFAULT FALSE,\n\t\t\tonlyContainsCACerts\n\t\t\t\t\t\t\t  [ 2 ]\tBOOLEAN DEFAULT FALSE,\n\t\t\tonlySomeReasons\t  [ 3 ]\tBITSTRING OPTIONAL,\n\t\t\tindirectCRL\t\t  [ 4 ]\tBOOLEAN DEFAULT FALSE\n\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x1C\" ), CRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT,\n\t  DESCRIPTION( \"issuingDistributionPoint\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CRITICAL( CRL, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"issuingDistributionPoint.distributionPoint\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"issuingDistributionPoint.distributionPoint.fullName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"issuingDistributionPoint.distributionPoint.fullName.generalNames\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_ISSUINGDIST_FULLNAME,\n\t  DESCRIPTION( \"issuingDistributionPoint.distributionPoint.fullName.generalNames.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND_3, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY,\n\t  DESCRIPTION( \"issuingDistributionPoint.onlyContainsUserCerts\" )\n\t  ENCODING_TAGGED( BOOLEAN, 1 ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY,\n\t  DESCRIPTION( \"issuingDistributionPoint.onlyContainsCACerts\" )\n\t  ENCODING_TAGGED( BOOLEAN, 2 ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY,\n\t  DESCRIPTION( \"issuingDistributionPoint.onlySomeReasons\" )\n\t  ENCODING_TAGGED( BITSTRING, 3 ),\n\t  0, FL_OPTIONAL, RANGE( 0, CRYPT_CRLREASONFLAG_LAST ) },\n\t{ NULL, CRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL,\n\t  DESCRIPTION( \"issuingDistributionPoint.indirectCRL\" )\n\t  ENCODING_TAGGED( BOOLEAN, 4 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_DEFAULT | FL_SEQEND /*NONE*/, RANGE_BOOLEAN },\n#endif /* USER_CERTREV && USE_CERTLEVEL_PKIX_PARTIAL */\n\n#if defined( USE_CERTREV ) && defined( USE_CERTLEVEL_PKIX_FULL )\n\t/* certificateIssuer:\n\n\t\tOID = 2 5 29 29\n\t\tcritical = TRUE\n\t\tcertificateIssuer SEQUENCE OF GeneralName */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x1D\" ), FIELDID_FOLLOWS,\n\t  DESCRIPTION( \"certificateIssuer\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CRITICAL( CRL, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CERTIFICATEISSUER,\n\t  DESCRIPTION( \"certificateIssuer.generalNames\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, /*FL_MULTIVALUED | */ FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n#endif /* USE_CERTREV && USE_CERTLEVEL_PKIX_FULL */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* nameConstraints\n\n\t\tOID = 2 5 29 30\n\t\tcritical = TRUE\n\t\tSEQUENCE {\n\t\t\tpermittedSubtrees [ 0 ]\tSEQUENCE OF {\n\t\t\t\tSEQUENCE { GeneralName }\n\t\t\t\t} OPTIONAL,\n\t\t\texcludedSubtrees  [ 1 ]\tSEQUENCE OF {\n\t\t\t\tSEQUENCE { GeneralName }\n\t\t\t\t} OPTIONAL,\n\t\t\t}\n\n\t\tRFC 3280 extended this by adding two additional fields after the\n\t\tGeneralName (probably from X.509v4) but mitigated it by requiring\n\t\tthat they never be used so we leave the definition as is */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x1E\" ), CRYPT_CERTINFO_NAMECONSTRAINTS,\n\t  DESCRIPTION( \"nameConstraints\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERT, ATTRCERT, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"nameConstraints.permittedSubtrees\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"nameConstraints.permittedSubtrees.sequenceOf\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t  DESCRIPTION( \"nameConstraints.permittedSubtrees.sequenceOf.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"nameConstraints.excludedSubtrees\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"nameConstraints.excludedSubtrees.sequenceOf\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t  DESCRIPTION( \"nameConstraints.excludedSubtrees.sequenceOf.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2 /*or _3*/, ENCODED_OBJECT( generalNameInfo ) },\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* cRLDistributionPoints:\n\n\t\tOID = 2 5 29 31\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\tdistributionPoint\n\t\t\t\t\t\t\t  [ 0 ]\t{\t\t\t\t-- CHOICE { ... }\n\t\t\t\t\tfullName  [ 0 ]\tSEQUENCE OF GeneralName\n\t\t\t\t\t} OPTIONAL,\n\t\t\t\treasons\t\t  [ 1 ]\tBIT STRING OPTIONAL,\n\t\t\t\tcRLIssuer\t  [ 2 ]\tSEQUENCE OF GeneralName OPTIONAL\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x1F\" ), CRYPT_CERTINFO_CRLDISTRIBUTIONPOINT,\n\t  DESCRIPTION( \"cRLDistributionPoints\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERT, ATTRCERT, STANDARD ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.distPoint\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.distPoint.fullName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CRLDIST_FULLNAME,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.distPoint.fullName.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND_2, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_CRLDIST_REASONS,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.reasons\" )\n\t  ENCODING_TAGGED( BITSTRING, 1 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE( 0, CRYPT_CRLREASONFLAG_LAST ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.cRLIssuer\" )\n\t  ENCODING_TAGGED( SEQUENCE, 2 ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CRLDIST_CRLISSUER,\n\t  DESCRIPTION( \"cRLDistributionPoints.distPoint.cRLIssuer.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND_2 /*or _3*/, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* certificatePolicies:\n\n\t\tOID = 2 5 29 32\n\t\tSEQUENCE SIZE (1..64) OF {\n\t\t\tSEQUENCE {\n\t\t\t\tpolicyIdentifier\tOBJECT IDENTIFIER,\n\t\t\t\tpolicyQualifiers\tSEQUENCE SIZE (1..64) OF {\n\t\t\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\t\tpolicyQualifierId\n\t\t\t\t\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\t\t\tqualifier\t\tANY DEFINED BY policyQualifierID\n\t\t\t\t\t\t} OPTIONAL\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\tCPSuri ::= IA5String\t\t\t\t\t\t-- OID = cps\n\n\t\tUserNotice ::= SEQUENCE {\t\t\t\t\t-- OID = unotice\n\t\t\tnoticeRef\t\tSEQUENCE {\n\t\t\t\torganization\tDisplayText,\n\t\t\t\tnoticeNumbers\tSEQUENCE OF INTEGER\t-- SIZE (1)\n\t\t\t\t} OPTIONAL,\n\t\t\texplicitText\tDisplayText OPTIONAL\n\t\t\t}\n\n\t   Note that although this extension is decoded at\n\t   CRYPT_COMPLIANCELEVEL_STANDARD policy constraints are only enforced\n\t   at CRYPT_COMPLIANCELEVEL_PKIX_FULL due to the totally bizarre\n\t   requirements that some of them have (see comments in chk_*.c for more\n\t   on this) */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x20\" ), CRYPT_CERTINFO_CERTIFICATEPOLICIES,\n\t  DESCRIPTION( \"certPolicies\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CERTPOLICYID,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyIdentifier\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQualifiers\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x02\\x01\" ), 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.cps (1 3 6 1 5 5 7 2 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CERTPOLICY_CPSURI,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQuals.qualifier.cPSuri\" )\n\t  ENCODING( STRING_IA5 ),\n\t  0, FL_MULTIVALUED | FL_SEQEND /*FL_SEQEND_2*/, CHECK_URL },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x02\\x02\" ), 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.unotice (1 3 6 1 5 5 7 2 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice.noticeRef\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice.noticeRef.organization\" )\n\t  ENCODING_SPECIAL( TEXTSTRING ),\n\t  0, FL_MULTIVALUED, RANGE( 1, 200 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice.noticeRef.noticeNumbers\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice.noticeRef.noticeNumbers\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_MULTIVALUED | FL_SEQEND_2, RANGE( 1, 1000 ) },\n\t{ NULL, CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT,\n\t  DESCRIPTION( \"certPolicies.policyInfo.policyQual.userNotice.explicitText\" )\n\t  ENCODING_SPECIAL( TEXTSTRING ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_3 /*FL_SEQEND, or _4 (CPS) or _5 or _7 (uNotice), */, RANGE( 1, 200 ) },\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* policyMappings:\n\n\t\tOID = 2 5 29 33\n\t\tSEQUENCE SIZE (1..MAX) OF {\n\t\t\tSEQUENCE {\n\t\t\t\tissuerDomainPolicy\tOBJECT IDENTIFIER,\n\t\t\t\tsubjectDomainPolicy\tOBJECT IDENTIFIER\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x21\" ), CRYPT_CERTINFO_POLICYMAPPINGS,\n\t  DESCRIPTION( \"policyMappings\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_FULL ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"policyMappings.sequenceOf\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_ISSUERDOMAINPOLICY,\n\t  DESCRIPTION( \"policyMappings.sequenceOf.issuerDomainPolicy\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_SUBJECTDOMAINPOLICY,\n\t  DESCRIPTION( \"policyMappings.sequenceOf.subjectDomainPolicy\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_MULTIVALUED | FL_SEQEND_2 /*FL_SEQEND_3*/, RANGE_OID },\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* authorityKeyIdentifier:\n\n\t\tOID = 2 5 29 35\n\t\tSEQUENCE {\n\t\t\tkeyIdentifier [ 0 ]\tOCTET STRING OPTIONAL,\n\t\t\tauthorityCertIssuer\t\t\t\t\t\t-- Neither or both\n\t\t\t\t\t\t  [ 1 ] SEQUENCE OF GeneralName OPTIONAL\n\t\t\tauthorityCertSerialNumber\t\t\t\t-- of these must\n\t\t\t\t\t\t  [ 2 ] INTEGER OPTIONAL\t-- be present\n\t\t\t}\n\n\t   Although the serialNumber should be an INTEGER it's really an INTEGER \n\t   equivalent of an OCTET STRING hole so we call it an OCTET STRING to \n\t   make sure that it gets handled appropriately */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x23\" ), CRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER,\n\t  DESCRIPTION( \"authorityKeyIdentifier\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERT, CRL, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER,\n\t  DESCRIPTION( \"authorityKeyIdentifier.keyIdentifier\" )\n\t  ENCODING_TAGGED( OCTETSTRING, 0 ),\n\t  0, FL_OPTIONAL, RANGE( 1, 64 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"authorityKeyIdentifier.authorityCertIssuer\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITY_CERTISSUER,\n\t  DESCRIPTION( \"authorityKeyIdentifier.authorityCertIssuer.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER,\n\t  DESCRIPTION( \"authorityKeyIdentifier.authorityCertSerialNumber\" )\n\t  ENCODING_TAGGED( OCTETSTRING, 2 ),\t/* Actually an INTEGER hole */\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE( 1, 64 ) },\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* policyConstraints:\n\n\t\tOID = 2 5 29 36\n\t\tSEQUENCE {\n\t\t\trequireExplicitPolicy [ 0 ]\tINTEGER OPTIONAL,\n\t\t\tinhibitPolicyMapping  [ 1 ]\tINTEGER OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x24\" ), CRYPT_CERTINFO_POLICYCONSTRAINTS,\n\t  DESCRIPTION( \"policyConstraints\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_REQUIREEXPLICITPOLICY,\n\t  DESCRIPTION( \"policyConstraints.requireExplicitPolicy\" )\n\t  ENCODING_TAGGED( INTEGER, 0 ),\n\t  0, FL_OPTIONAL, RANGE( 0, 64 ) },\n\t{ NULL, CRYPT_CERTINFO_INHIBITPOLICYMAPPING,\n\t  DESCRIPTION( \"policyConstraints.inhibitPolicyMapping\" )\n\t  ENCODING_TAGGED( INTEGER, 1 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE( 0, 64 ) },\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* extKeyUsage:\n\n\t\tOID = 2 5 29 37\n\t\tSEQUENCE {\n\t\t\toidInstance1 OPTIONAL,\n\t\t\toidInstance2 OPTIONAL,\n\t\t\t\t...\n\t\t\toidInstanceN OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x25\" ), CRYPT_CERTINFO_EXTKEYUSAGE,\n\t  DESCRIPTION( \"extKeyUsage\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERTREQ, CERT, STANDARD ),\n\t  0, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x15\" ), CRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,\n\t  DESCRIPTION( \"extKeyUsage.individualCodeSigning (1 3 6 1 4 1 311 2 1 21)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x16\" ), CRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,\n\t  DESCRIPTION( \"extKeyUsage.commercialCodeSigning (1 3 6 1 4 1 311 2 1 22)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x0A\\x03\\x01\" ), CRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,\n\t  DESCRIPTION( \"extKeyUsage.certTrustListSigning (1 3 6 1 4 1 311 10 3 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x0A\\x03\\x02\" ), CRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING,\n\t  DESCRIPTION( \"extKeyUsage.timeStampSigning (1 3 6 1 4 1 311 10 3 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x0A\\x03\\x03\" ), CRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO,\n\t  DESCRIPTION( \"extKeyUsage.serverGatedCrypto (1 3 6 1 4 1 311 10 3 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x0A\\x03\\x04\" ), CRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM,\n\t  DESCRIPTION( \"extKeyUsage.encrypedFileSystem (1 3 6 1 4 1 311 10 3 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x01\" ), CRYPT_CERTINFO_EXTKEY_SERVERAUTH,\n\t  DESCRIPTION( \"extKeyUsage.serverAuth (1 3 6 1 5 5 7 3 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x02\" ), CRYPT_CERTINFO_EXTKEY_CLIENTAUTH,\n\t  DESCRIPTION( \"extKeyUsage.clientAuth (1 3 6 1 5 5 7 3 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x03\" ), CRYPT_CERTINFO_EXTKEY_CODESIGNING,\n\t  DESCRIPTION( \"extKeyUsage.codeSigning (1 3 6 1 5 5 7 3 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x04\" ), CRYPT_CERTINFO_EXTKEY_EMAILPROTECTION,\n\t  DESCRIPTION( \"extKeyUsage.emailProtection (1 3 6 1 5 5 7 3 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x05\" ), CRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM,\n\t  DESCRIPTION( \"extKeyUsage.ipsecEndSystem (1 3 6 1 5 5 7 3 5)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x06\" ), CRYPT_CERTINFO_EXTKEY_IPSECTUNNEL,\n\t  DESCRIPTION( \"extKeyUsage.ipsecTunnel (1 3 6 1 5 5 7 3 6)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x07\" ), CRYPT_CERTINFO_EXTKEY_IPSECUSER,\n\t  DESCRIPTION( \"extKeyUsage.ipsecUser (1 3 6 1 5 5 7 3 7)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x08\" ), CRYPT_CERTINFO_EXTKEY_TIMESTAMPING,\n\t  DESCRIPTION( \"extKeyUsage.timeStamping (1 3 6 1 5 5 7 3 8)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x03\\x09\" ), CRYPT_CERTINFO_EXTKEY_OCSPSIGNING,\n\t  DESCRIPTION( \"extKeyUsage.ocspSigning (1 3 6 1 5 5 7 3 9)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x05\\x2B\\x24\\x08\\x02\\x01\" ), CRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE,\n\t  DESCRIPTION( \"extKeyUsage.directoryService (1 3 36 8 2 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x04\\x55\\x1D\\x25\\x00\" ), CRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE,\n\t  DESCRIPTION( \"extKeyUsage.anyExtendedKeyUsage(2 5 29 37 0)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x04\\x01\" ), CRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO,\n\t  DESCRIPTION( \"extKeyUsage.serverGatedCrypto (2 16 840 1 113730 4 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x08\\x01\" ), CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,\n\t  DESCRIPTION( \"extKeyUsage.serverGatedCryptoCA (2 16 840 1 113733 1 8 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"extKeyUsage.catchAll\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* Match anything and ignore it */\n\t  FL_ATTR_ATTREND, FL_NONENCODING | FL_SEQEND /*NONE*/, RANGE_NONE },\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n#ifdef USE_REV\n\t/* crlStreamIdentifier:\n\n\t\tOID = 2 5 29 40\n\t\tINTEGER */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x28\" ), CRYPT_CERTINFO_CRLSTREAMIDENTIFIER,\n\t  DESCRIPTION( \"crlStreamIdentifier\" )\n\t  ENCODING( INTEGER ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, 64 ) },\n#endif /* USE_REV */\n\n\t/* statusReferrals:\n\n\t\tOID = 2 5 29 46\n\t\tcritical = TRUE\n\t\tSEQUENCE OF {\n\t\t\tcRLReferral [ 0 ] EXPLICIT SEQUENCE {\n\t\t\t\tissuer\t\t\t\t\t  [ 0 ]\tGeneralName OPTIONAL,\n\t\t\t\tlocation\t\t\t\t  [ 1 ]\tGeneralName OPTIONAL,\n\t\t\t\tdeltaRefInfo [ 2 ] SEQUENCE {\n\t\t\t\t\tdeltaLocation\t\t\t\tGeneralName,\n\t\t\t\t\tlastDelta\t\t\t\t\tGeneralizedTime OPTIONAL\n\t\t\t\t\t} OPTIONAL,\n\t\t\t\tcRLScope SEQUENCE OF {\n\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\tauthorityName\t  [ 0 ]\tGeneralName OPTIONAL,\n\t\t\t\t\t\tdistributionPoint [ 1 ][ 0 ] EXPLICIT GeneralName OPTIONAL,\n\t\t\t\t\t\tonlyContains\t  [ 2 ]\tBIT STRING OPTIONAL,\t-- 3 bits\n\t\t\t\t\t\tonlySomeReasons   [ 4 ]\tBIT STRING OPTIONAL, -- 9 bits\n\t\t\t\t\t\tserialNumberRange [ 5 ] SEQUENCE {\n\t\t\t\t\t\t\tstartingNumber[ 0 ]\tINTEGER OPTIONAL,\n\t\t\t\t\t\t\tendingNumber  [ 1 ]\tINTEGER OPTIONAL\n\t\t\t\t\t\t\t} OPTIONAL,\n\t\t\t\t\t\tsubjectKeyIdRange [ 6 ] SEQUENCE {\n\t\t\t\t\t\t\tstartingKeyId [ 0 ]\tINTEGER OPTIONAL,\n\t\t\t\t\t\t\tendingKeyId\t  [ 1 ]\tINTEGER OPTIONAL\n\t\t\t\t\t\t\t} OPTIONAL,\n\t\t\t\t\t\tnameSubtrees\t  [ 7 ] SEQUENCE OF GeneralName OPTIONAL,\n\t\t\t\t\t\tbaseRevocationInfo [ 9 ] SEQUENCE {\n\t\t\t\t\t\t\tcRLStatusIndicator [ 0 ] INTEGER OPTIONAL,\n\t\t\t\t\t\t\tcRLNumber\t\t   [ 1 ] INTEGER,\n\t\t\t\t\t\t\tbaseThisUpdate\t   [ 2 ] GeneralizedTime\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tlastUpdate [ 3 ] GeneralizedTime OPTIONAL,\n\t\t\t\tlastChangedCRL [ 4 ] GeneralizedTime OPTIONAL\n\t\t\t\t}\n\t\t\t}\n\n\t\tTo think that someone actually did this on purpose!\n\n\t\tThis is a crazy extension that, in effect, says that the CRL that \n\t\tyou're holding in your hands isn't really a CRL at all but a pointer\n\t\tto locations where actual CRL information may be found, assuming that\n\t\tthe processing application knows about this bizarre interpretation.\n\t\tSince the likelihood of this happening is essentially zero (there are \n\t\tno known implementations of this at present), we don't use it */\n\n\t/* freshestCRL:\n\n\t\tOID = 2 5 29 46\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\tdistributionPoint\n\t\t\t\t\t\t\t  [ 0 ]\t{\t\t\t\t-- CHOICE { ... }\n\t\t\t\t\tfullName  [ 0 ]\tSEQUENCE OF GeneralName\n\t\t\t\t\t} OPTIONAL,\n\t\t\t\treasons\t\t  [ 1 ]\tBIT STRING OPTIONAL,\n\t\t\t\tcRLIssuer\t  [ 2 ]\tSEQUENCE OF GeneralName OPTIONAL\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x2E\" ), CRYPT_CERTINFO_FRESHESTCRL,\n\t  DESCRIPTION( \"freshestCRL\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO2( CERT, ATTRCERT, PKIX_FULL ),\n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.distributionPoint\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.distributionPoint.fullName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_FRESHESTCRL_FULLNAME,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.distributionPoint.fullName.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND_2, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_FRESHESTCRL_REASONS,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.reasons\" )\n\t  ENCODING_TAGGED( BITSTRING, 1 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE( 0, CRYPT_CRLREASONFLAG_LAST ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.cRLIssuer\" )\n\t  ENCODING_TAGGED( SEQUENCE, 2 ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_FRESHESTCRL_CRLISSUER,\n\t  DESCRIPTION( \"freshestCRL.distributionPoint.cRLIssuer.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | /*FL_MULTIVALUED |*/ FL_SEQEND_2 /*or _3*/, ENCODED_OBJECT( generalNameInfo ) },\n\n#ifdef USE_REV\n\t/* orderedList:\n\n\t\tOID = 2 5 29 47\n\t\tENUMERATED */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x2F\" ), CRYPT_CERTINFO_ORDEREDLIST,\n\t  DESCRIPTION( \"orderedList\" )\n\t  ENCODING( ENUMERATED ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, 1 ) },\n\n\t/* baseUpdateTime:\n\n\t\tOID = 2 5 29 51\n\t\tGeneralizedTime */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x33\" ), CRYPT_CERTINFO_BASEUPDATETIME,\n\t  DESCRIPTION( \"baseUpdateTime\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ),\n\t  FL_ATTR_ATTREND, RANGE_TIME },\n\n\t/* deltaInfo:\n\n\t\tOID = 2 5 29 53\n\t\tSEQUENCE {\n\t\t\tdeltaLocation\t\tGeneralName,\n\t\t\tnextDelta\t\t\tGeneralizedTime OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x35\" ), CRYPT_CERTINFO_DELTAINFO,\n\t  DESCRIPTION( \"deltaInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_DELTAINFO_LOCATION,\n\t  DESCRIPTION( \"deltaInfo.deltaLocation\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, 0, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_DELTAINFO_NEXTDELTA,\n\t  DESCRIPTION( \"deltaInfo.nextDelta\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  FL_ATTR_ATTREND, FL_SEQEND, RANGE_TIME },\n#endif /* USE_REV */\n\n\t/* inhibitAnyPolicy:\n\n\t\tOID = 2 5 29 54\n\t\tINTEGER */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x36\" ), CRYPT_CERTINFO_INHIBITANYPOLICY,\n\t  DESCRIPTION( \"inhibitAnyPolicy\" )\n\t  ENCODING( INTEGER ),\n\t  ATTR_TYPEINFO( CERT, PKIX_FULL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, 64 ) },\n\n#ifdef USE_REV\n\t/* toBeRevoked:\n\n\t\tOID = 2 5 29 58\n\t\tSEQUENCE OF SEQUENCE {\n\t\t\tcertificateIssuer [ 0 ]\tGeneralName OPTIONAL,\n\t\t\treasonInfo\t\t  [ 1 ] SEQUENCE {\n\t\t\t\treasonCode\t\t\tENUMERATED\n\t\t\t\t} OPTIONAL,\n\t\t\trevocationTime\t\t\tGeneralizedTime,\n\t\t\tcertificateGroup  [ 0 ]\tEXPLICIT SEQUENCE OF {\n\t\t\t\tcertificateSerialNumber \n\t\t\t\t\t\t\t\t\tINTEGER\n\t\t\t\t}\n\t\t\t} \n\n\t   Although the certificateSerialNumber should be an INTEGER it's really \n\t   an INTEGER equivalent of an OCTET STRING hole so we call it an OCTET \n\t   STRING to make sure that it gets handled appropriately */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x3A\" ), CRYPT_CERTINFO_TOBEREVOKED,\n\t  DESCRIPTION( \"toBeRevoked\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"toBeRevoked.group\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_MULTIVALUED, RANGE_NONE }\n\t{ NULL, CRYPT_CERTINFO_TOBEREVOKED_CERTISSUER,\n\t  DESCRIPTION( \"toBeRevoked.group.certificateIssuer\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"toBeRevoked.group.reasonInfo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_NONE }\n\t{ NULL, CRYPT_CERTINFO_TOBEREVOKED_REASONCODE,\n\t  DESCRIPTION( \"toBeRevoked.group.reasonInfo.reasonCode\" )\n\t  ENCODING( ENUMERATED ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND, RANGE( 0, CRYPT_CRLREASON_LAST ) },\n\t{ 0, CRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME,\n\t  DESCRIPTION( \"toBeRevoked.group.revocationTime\" )\n\t  ENCODING( TIME_UTC ),\n\t  0, FL_MULTIVALUED, RANGE_TIME },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"toBeRevoked.group.certificateGroup\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_EXPLICIT, RANGE_NONE }\n\t{ NULL, CRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER,\n\t  DESCRIPTION( \"toBeRevoked.group.certificateGroup.certificateSerialNumber\" )\n\t  ENCODING_TAGGED( OCTETSTRING, BER_INTEGER ),\t/* Actually an INTEGER hole */\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_3, RANGE( 1, 64 ) },\n\n\t/* revokedGroups:\n\n\t\tOID = 2 5 29 59\n\t\tSEQUENCE {\n\t\t\tcertificateIssuer [ 0 ]\tGeneralName OPTIONAL,\n\t\t\treasonInfo\t\t  [ 1 ] SEQUENCE {\n\t\t\t\treasonCode\t\t\tENUMERATED\n\t\t\t\t} OPTIONAL,\n\t\t\tinvalidityDate\t  [ 2 ]\tGeneralizedTime OPTIONAL,\n\t\t\trevokedCertificateGroup [ 3 ] EXPLICIT SEQUENCE {\n\t\t\t\tstartingNumber[ 0 ]\tINTEGER,\n\t\t\t\tendingNumber  [ 1 ] INTEGER\n\t\t\t\t}\n\t\t\t} \n\n\t   Although the revokedCertificateGroup serial numbers should INTEGERs \n\t   they're really the INTEGER equivalent of OCTET STRING holes so we \n\t   call them OCTET STRINGs to make sure that they get handled \n\t   appropriately */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x3B\" ), CRYPT_CERTINFO_REVOKEDGROUPS,\n\t  DESCRIPTION( \"revokedGroups\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER,\n\t  DESCRIPTION( \"revokedGroups.certificateIssuer\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"revokedGroups.reasonInfo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL, RANGE_NONE }\n\t{ NULL, CRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE,\n\t  DESCRIPTION( \"revokedGroups.reasonCode\" )\n\t  ENCODING( ENUMERATED ),\n\t  0, FL_OPTIONAL | FL_SEQEND, RANGE( 0, CRYPT_CRLREASON_LAST ) },\n\t{ 0, CRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE,\n\t  DESCRIPTION( \"revokedGroups.revocationTime\" )\n\t  ENCODING_TAGGED( TIME_GENERALIZED, 2 ),\n\t  0, FL_OPTIONAL, RANGE_TIME },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"revokedGroups.revokedCertificateGroup\" )\n\t  ENCODING_TAGGED( SEQUENCE, 3 ),\n\t  0, FL_EXPLICIT, RANGE_NONE }\n\t{ NULL, CRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER,\n\t  DESCRIPTION( \"revokedGroups.revokedCertificateGroup.startingNumber\" )\n\t  ENCODING_TAGGED( OCTETSTRING, BER_INTEGER ),\t/* Actually an INTEGER hole */\n\t  0, 0, RANGE( 1, 64 ) },\n\t{ NULL, CRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER,\n\t  DESCRIPTION( \"revokedGroups.revokedCertificateGroup.endingNumber\" )\n\t  ENCODING_TAGGED( OCTETSTRING, BER_INTEGER ),\t/* Actually an INTEGER hole */\n\t  FL_ATTR_ATTREND, FL_SEQEND_2, RANGE( 1, 64 ) },\n\n\t/* expiredCertsOnCRL:\n\n\t\tOID = 2 5 29 60\n\t\tGeneralizedTime */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x3C\" ), CRYPT_CERTINFO_EXPIREDCERTSONCRL,\n\t  DESCRIPTION( \"expiredCertsOnCRL\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  ATTR_TYPEINFO( CRL, PKIX_FULL ),\n\t  FL_ATTR_ATTREND, RANGE_TIME },\n\n\t/* aaIssuingDistributionPoint:\n\n\t\tOID = 2 5 29 63\n\t\tcritical = TRUE\n\t\tSEQUENCE {\n\t\t\tdistributionPoint [ 0 ]\t{\n\t\t\t\tfullName\t  [ 0 ]\tEXPLICIT GeneralName\t-- CHOICE ...\n\t\t\t\t} OPTIONAL,\n\t\t\tonlySomeReasons\t  [ 1 ]\tBITSTRING OPTIONAL,\n\t\t\tindirectCRL\t\t  [ 2 ]\tBOOLEAN DEFAULT FALSE\n\t\t\tcontainsUserAttributeCerts\n\t\t\t\t\t\t\t  [ 3 ]\tBOOLEAN DEFAULT TRUE,\n\t\t\tcontainsAACerts\t  [ 4 ]\tBOOLEAN DEFAULT TRUE,\n\t\t\tcontainsSOAPublicKeyCerts\t  \n\t\t\t\t\t\t\t  [ 5 ]\tBOOLEAN DEFAULT TRUE\n\t\t} */\n\t{ MKOID( \"\\x06\\x03\\x55\\x1D\\x3F\" ), CRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CRITICAL( CRL, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.distributionPoint\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.distributionPoint.fullName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_FULLNAME,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.distributionPoint.fullName.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND_3, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.onlySomeReasons\" )\n\t  ENCODING_TAGGED( BITSTRING, 1 ),\n\t  0, FL_OPTIONAL, RANGE( 0, CRYPT_CRLREASONFLAG_LAST ) },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.indirectCRL\" )\n\t  ENCODING_TAGGED( BOOLEAN, 2 ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.containsUserAttributeCerts\" )\n\t  ENCODING_TAGGED( BOOLEAN, 3 ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_AACERTS,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.containsAACerts\" )\n\t  ENCODING_TAGGED( BOOLEAN, 4 ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, RANGE_BOOLEAN },\n\t{ NULL, CRYPT_CERTINFO_AAISSUINGDIST_SOACERTS,\n\t  DESCRIPTION( \"aaIssuingDistributionPoint.containsSOAPublicKeyCerts\" )\n\t  ENCODING_TAGGED( BOOLEAN, 5 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_DEFAULT | FL_SEQEND /*NONE*/, RANGE_BOOLEAN },\n#endif /* USE_REV */\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n#ifdef USE_CERT_OBSOLETE\n\t/* netscape-cert-type:\n\n\t\tOID = 2 16 840 1 113730 1 1\n\t\tBITSTRING */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x01\" ), CRYPT_CERTINFO_NS_CERTTYPE,\n\t  DESCRIPTION( \"netscape-cert-type\" )\n\t  ENCODING( BITSTRING ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, CRYPT_NS_CERTTYPE_LAST ) },\n\n\t/* netscape-base-url:\n\n\t\tOID = 2 16 840 1 113730 1 2\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x02\" ), CRYPT_CERTINFO_NS_BASEURL,\n\t  DESCRIPTION( \"netscape-base-url\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_HTTP },\n\n\t/* netscape-revocation-url:\n\n\t\tOID = 2 16 840 1 113730 1 3\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x03\" ), CRYPT_CERTINFO_NS_REVOCATIONURL,\n\t  DESCRIPTION( \"netscape-revocation-url\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_HTTP },\n\n\t/* netscape-ca-revocation-url:\n\n\t\tOID = 2 16 840 1 113730 1 3\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x04\" ), CRYPT_CERTINFO_NS_CAREVOCATIONURL,\n\t  DESCRIPTION( \"netscape-ca-revocation-url\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_HTTP },\n\n\t/* netscape-ca-revocation-url:\n\n\t\tOID = 2 16 840 1 113730 11 7\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x07\" ), CRYPT_CERTINFO_NS_CERTRENEWALURL,\n\t  DESCRIPTION( \"netscape-ca-revocation-url\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_HTTP },\n\n\t/* netscape-ca-policy-url:\n\n\t\tOID = 2 16 840 1 113730 1 8\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x08\" ), CRYPT_CERTINFO_NS_CAPOLICYURL,\n\t  DESCRIPTION( \"netscape-ca-policy-url\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_HTTP },\n\n\t/* netscape-ssl-server-name:\n\n\t\tOID = 2 16 840 1 113730 1 12\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x0C\" ), CRYPT_CERTINFO_NS_SSLSERVERNAME,\n\t  DESCRIPTION( \"netscape-ssl-server-name\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, CHECK_DNS },\n\n\t/* netscape-comment:\n\n\t\tOID = 2 16 840 1 113730 1 13\n\t\tIA5String */\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x01\\x0D\" ), CRYPT_CERTINFO_NS_COMMENT,\n\t  DESCRIPTION( \"netscape-comment\" )\n\t  ENCODING( STRING_IA5 ),\n\t  ATTR_TYPEINFO( CERT, STANDARD ) | FL_ATTR_ATTREND,\n\t  0, RANGE_ATTRIBUTEBLOB },\n#endif /* USE_CERT_OBSOLETE */\n\n#ifdef USE_CERT_OBSOLETE\n\t/* hashedRootKey (SET):\n\n\t\tOID = 2 23 42 7 0\n\t\tcritical = TRUE\n\t\tSEQUENCE {\n\t\t\trootKeyThumbprint\tDigestedData\t\t-- PKCS #7-type wrapper\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x04\\x67\\x2A\\x07\\x00\" ), CRYPT_CERTINFO_SET_HASHEDROOTKEY,\n\t  DESCRIPTION( \"hashedRootKey\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CRITICAL( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"hashedRootKey.rootKeyThumbprint\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\t\t/* PKCS #7-type wrapper */\n\t  0, FL_NONENCODING, 0, 0, 25,\n\t  \"\\x30\\x2D\\x02\\x01\\x00\\x30\\x09\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1A\\x05\\x00\\x30\\x07\\x06\\x05\\x67\\x2A\\x03\\x00\\x00\" },\n\t{ NULL, CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT,\n\t  DESCRIPTION( \"hashedRootKey.rootKeyThumbprint.hashData\" )\n\t  ENCODING( OCTETSTRING ),\n\t  FL_ATTR_ATTREND, FL_SEQEND /*NONE*/, RANGE( 20, 20 ) },\n\n\t/* certificateType (SET):\n\n\t\tOID = 2 23 42 7 1\n\t\tcritical = TRUE\n\t\tBIT STRING */\n\t{ MKOID( \"\\x06\\x04\\x67\\x2A\\x07\\x01\" ), CRYPT_CERTINFO_SET_CERTIFICATETYPE,\n\t  DESCRIPTION( \"certificateType\" )\n\t  ENCODING( BITSTRING ),\n\t  ATTR_TYPEINFO_CRITICAL( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE( 0, CRYPT_SET_CERTTYPE_LAST ) },\n\n\t/* merchantData (SET):\n\n\t\tOID = 2 23 42 7 2\n\t\tSEQUENCE {\n\t\t\tmerID\t\t\t\tSETString SIZE(1..30),\n\t\t\tmerAcquirerBIN\t\tNumericString SIZE(6),\n\t\t\tmerNameSeq\t\t\tSEQUENCE OF MerNames,\n\t\t\tmerCountry\t\t\tINTEGER (1..999),\n\t\t\tmerAuthFlag\t\t\tBOOLEAN DEFAULT TRUE\n\t\t\t}\n\n\t\tMerNames ::= SEQUENCE {\n\t\t\tlanguage\t  [ 0 ] VisibleString SIZE(1..35),\n\t\t\tname\t\t  [ 1 ]\tEXPLICIT SETString SIZE(1..50),\n\t\t\tcity\t\t  [ 2 ]\tEXPLICIT SETString SIZE(1..50),\n\t\t\tstateProvince [ 3 ] EXPLICIT SETString SIZE(1..50) OPTIONAL,\n\t\t\tpostalCode\t  [ 4 ] EXPLICIT SETString SIZE(1..14) OPTIONAL,\n\t\t\tcountryName\t  [ 5 ]\tEXPLICIT SETString SIZE(1..50)\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x04\\x67\\x2A\\x07\\x02\" ), CRYPT_CERTINFO_SET_MERCHANTDATA,\n\t  DESCRIPTION( \"merchantData\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SET_MERID,\n\t  DESCRIPTION( \"merchantData.merID\" )\n\t  ENCODING( STRING_ISO646 ),\n\t  0, 0, RANGE( 1, 30 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERACQUIRERBIN,\n\t  DESCRIPTION( \"merchantData.merAcquirerBIN\" )\n\t  ENCODING( STRING_NUMERIC ),\n\t  0, 0, RANGE( 6, 6 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"merchantData.merNameSeq\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTLANGUAGE,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.language\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 0 ),\n\t  0, FL_MULTIVALUED, RANGE( 1, 35 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTNAME,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.name\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 1 ),\n\t  0, FL_MULTIVALUED | FL_EXPLICIT, RANGE( 1, 50 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTCITY,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.city\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 2 ),\n\t  0, FL_MULTIVALUED | FL_EXPLICIT, RANGE( 1, 50 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.stateProvince\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 3 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_EXPLICIT, RANGE( 1, 50 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.postalCode\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 4 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_EXPLICIT, RANGE( 1, 50 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME,\n\t  DESCRIPTION( \"merchantData.merNameSeq.merNames.countryName\" )\n\t  ENCODING_TAGGED( STRING_ISO646, 5 ),\n\t  0, FL_MULTIVALUED | FL_EXPLICIT | FL_SEQEND_2, RANGE( 1, 50 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERCOUNTRY,\n\t  DESCRIPTION( \"merchantData.merCountry\" )\n\t  ENCODING( INTEGER ),\n\t  0, 0, RANGE( 1, 999 ) },\n\t{ NULL, CRYPT_CERTINFO_SET_MERAUTHFLAG,\n\t  DESCRIPTION( \"merchantData.merAuthFlag\" )\n\t  ENCODING( BOOLEAN ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_DEFAULT | FL_SEQEND /*NONE*/, RANGE_BOOLEAN },\n\n\t/* certCardRequired (SET):\n\n\t\tOID = 2 23 42 7 3\n\t\tBOOLEAN */\n\t{ MKOID( \"\\x06\\x04\\x67\\x2A\\x07\\x03\" ), CRYPT_CERTINFO_SET_CERTCARDREQUIRED,\n\t  DESCRIPTION( \"certCardRequired\" )\n\t  ENCODING( BOOLEAN ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ) | FL_ATTR_ATTREND,\n\t  0, RANGE_BOOLEAN },\n\n\t/* tunneling (SET):\n\n\t\tOID = 2 23 42 7 4\n\t\tSEQUENCE {\n\t\t\ttunneling \t\tDEFAULT TRUE,\n\t\t\ttunnelAlgIDs\tSEQUENCE OF OBJECT IDENTIFIER\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x04\\x67\\x2A\\x07\\x04\" ), CRYPT_CERTINFO_SET_TUNNELING,\n\t  DESCRIPTION( \"tunneling\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO( CERT, PKIX_PARTIAL ),\n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SET_TUNNELINGFLAG,\n\t  DESCRIPTION( \"tunneling.tunneling\" )\n\t  ENCODING( BOOLEAN ),\n\t  0, FL_OPTIONAL | FL_DEFAULT, FALSE, TRUE, TRUE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"tunneling.tunnelingAlgIDs\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_SET_TUNNELINGALGID,\n\t  DESCRIPTION( \"tunneling.tunnelingAlgIDs.tunnelingAlgID\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_MULTIVALUED | FL_SEQEND, RANGE_OID },\n#endif /* USE_CERT_OBSOLETE */\n\n\t{ NULL, CRYPT_IATTRIBUTE_LAST }, { NULL, CRYPT_IATTRIBUTE_LAST }\n\t};\n\n#if ( defined( USE_CERTREV ) || defined( USE_CERTREQ ) ) && \\\n\tdefined( USE_CERTLEVEL_PKIX_FULL )\n\n/* Subtable for encoding the holdInstructionCode */\n\nSTATIC_DATA const ATTRIBUTE_INFO holdInstructionInfo[] = {\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x02\\x01\" ), CRYPT_HOLDINSTRUCTION_NONE,\n\t  DESCRIPTION( \"holdInstructionCode.holdinstruction-none (1 2 840 10040 2 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTRSTART, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x02\\x02\" ), CRYPT_HOLDINSTRUCTION_CALLISSUER,\n\t  DESCRIPTION( \"holdInstructionCode.holdinstruction-callissuer (1 2 840 10040 2 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x02\\x03\" ), CRYPT_HOLDINSTRUCTION_REJECT,\n\t  DESCRIPTION( \"holdInstructionCode.holdinstruction-reject (1 2 840 10040 2 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x02\\x04\" ), CRYPT_HOLDINSTRUCTION_PICKUPTOKEN,\n\t  DESCRIPTION( \"holdInstructionCode.holdinstruction-pickupToken (1 2 840 10040 2 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL, RANGE_NONE },\n\n\t{ NULL, CRYPT_IATTRIBUTE_LAST }, { NULL, CRYPT_IATTRIBUTE_LAST }\n\t};\n#endif /* ( USE_CERTREV || USE_CERTREQ ) && USE_CERTLEVEL_PKIX_FULL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGeneralName Definition\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encoding and decoding of GeneralNames is performed with the following\n   subtable:\n\n\totherName\t\t  [ 0 ]\tSEQUENCE {\n\t\ttype-id\t\t\t\tOBJECT IDENTIFIER,\n\t\tvalue\t\t  [ 0 ]\tEXPLICIT ANY DEFINED BY type-id\n\t\t} OPTIONAL,\n\trfc822Name\t\t  [ 1 ]\tIA5String OPTIONAL,\n\tdNSName\t\t\t  [ 2 ]\tIA5String OPTIONAL,\n\tx400Address\t\t  [ 3 ] ITU-BrainDamage OPTIONAL\n\tdirectoryName\t  [ 4 ]\tEXPLICIT Name OPTIONAL,\n\tediPartyName \t  [ 5 ]\tSEQUENCE {\n\t\tnameAssigner  [ 0 ]\tEXPLICIT DirectoryString OPTIONAL,\n\t\tpartyName\t  [ 1 ]\tEXPLICIT DirectoryString\n\t\t} OPTIONAL,\n\tuniformResourceIdentifier\n\t\t\t\t\t  [ 6 ]\tIA5String OPTIONAL,\n\tiPAddress\t\t  [ 7 ]\tOCTET STRING OPTIONAL,\n\tregisteredID\t  [ 8 ]\tOBJECT IDENTIFIER OPTIONAL\n\n\tITU-Braindamge ::= SEQUENCE {\n\t\tbuilt-in-standard-attributes\t\tSEQUENCE {\n\t\t\tcountry-name  [ APPLICATION 1 ]\tCHOICE {\n\t\t\t\tx121-dcc-code\t\t\t\tNumericString,\n\t\t\t\tiso-3166-alpha2-code\t\tPrintableString\n\t\t\t\t},\n\t\t\tadministration-domain-name\n\t\t\t\t\t\t  [ APPLICATION 2 ]\tCHOICE {\n\t\t\t\tnumeric\t\t\t\t\t\tNumericString,\n\t\t\t\tprintable\t\t\t\t\tPrintableString\n\t\t\t\t},\n\t\t\tnetwork-address\t\t\t  [ 0 ]\tNumericString OPTIONAL,\n\t\t\tterminal-identifier\t\t  [ 1 ]\tPrintableString OPTIONAL,\n\t\t\tprivate-domain-name\t\t  [ 2 ]\tCHOICE {\n\t\t\t\tnumeric\t\t\t\t\t\tNumericString,\n\t\t\t\tprintable\t\t\t\t\tPrintableString\n\t\t\t\t} OPTIONAL,\n\t\t\torganization-name\t\t  [ 3 ]\tPrintableString OPTIONAL,\n\t\t\tnumeric-use-identifier\t  [ 4 ]\tNumericString OPTIONAL,\n\t\t\tpersonal-name\t\t\t  [ 5 ]\tSET {\n\t\t\t\tsurname\t\t\t\t  [ 0 ]\tPrintableString,\n\t\t\t\tgiven-name\t\t\t  [ 1 ]\tPrintableString,\n\t\t\t\tinitials\t\t\t  [ 2 ]\tPrintableString,\n\t\t\t\tgeneration-qualifier  [ 3 ]\tPrintableString\n\t\t\t\t} OPTIONAL,\n\t\t\torganizational-unit-name  [ 6 ]\tPrintableString OPTIONAL,\n\t\t\t}\n\t\tbuilt-in-domain-defined-attributes\tSEQUENCE OF {\n\t\t\ttype\t\t\t\t\t\t\tPrintableString SIZE(1..64),\n\t\t\tvalue\t\t\t\t\t\t\tPrintableString SIZE(1..64)\n\t\t\t} OPTIONAL\n\t\textensionAttributes\t\t\t\t\tSET OF SEQUENCE {\n\t\t\textension-attribute-type  [ 0 ]\tINTEGER,\n\t\t\textension-attribute-value [ 1 ]\tANY DEFINED BY extension-attribute-type\n\t\t\t} OPTIONAL\n\t\t}\n\n   Needless to say X.400 addresses aren't supported (for readers who've\n   never seen one before you now know why they've been so enormously\n   successful).\n\n   Note the special-case encoding of the DirectoryName and EDIPartyName.\n   This is required because (for the DirectoryName) a Name is actually a\n   CHOICE { RDNSequence } and if the tagging were implicit then there'd be\n   no way to tell which of the CHOICE options was being used:\n\n\tdirectoryName\t  [ 4 ]\tName OPTIONAL\n\n   becomes:\n\n\tdirectoryName\t  [ 4 ]\tCHOICE { RDNSequence } OPTIONAL\n\n   which, if implicit tagging is used, would replace the RDNSequence tag with\n   the [4] tag, making it impossible to determine which of the Name choices\n   was used (actually there's only one possibility and it's unlikely that\n   there'll ever be more but that's what the encoding rules require - X.208,\n   section 26.7c).\n\n   The same applies to the EDIPartyName, this is a DirectoryString which is\n   a CHOICE of several possible string types.  The end result is that:\n\n\t[ 0 ] DirectoryString\n\n   ends up looking like:\n\n\t[ 0 ] CHOICE { PrintableString | T61String | UTF8String | BMPString }\n\n   In addition to the above complications, newer versions of the PKIX core \n   RFC allow the use of 8- and 32-byte CIDR forms for 4- and 16-byte IP \n   addresses in some instances when they're being used as constraints.  We \n   can add support for this if anyone ever asks for it.\n   \n   Finally, each field, or at least each field which is likely to be used, \n   is marked with FL_MULTIVALUED.  This is because every location in a \n   common attribute that uses a GeneralName has it as a SEQUENCE OF, so that \n   multiple GeneralName entries can be present.  This makes sense if you \n   look at the way in which a GeneralName is defined, a CHOICE hiding the \n   actual item, so that it's (almost) always wrapped in a SEQUENCE OF to \n   make it useful.  So what's multivalued isn't the SEQUENCE OF part but \n   each individual entry of the CHOICE within it.  This also helps with the \n   checking since the attribute-add code checks whether, for example,\n   CRYPT_CERTINFO_RFC822NAME is FL_MULTIVALUED and not whether the SEQUENCE \n   OF [0] SEQUENCE SEQUENCE [4] SEQUENCE OF GeneralName is FL_MULTIVALUED */\n\nSTATIC_DATA const ATTRIBUTE_INFO generalNameInfo[] = {\n\t/* otherName */\n\t{ NULL, FIELDID_FOLLOWS,\n\t  DESCRIPTION( \"generalName.otherName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  FL_ATTR_ATTRSTART, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_OTHERNAME_TYPEID,\n\t  DESCRIPTION( \"generalName.otherName.type-id\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_OTHERNAME_VALUE,\n\t  DESCRIPTION( \"generalName.otherName.value\" )\n\t  ENCODING_SPECIAL_TAGGED( BLOB_ANY, 0 ),\n\t  0, FL_OPTIONAL | FL_EXPLICIT | FL_SEQEND, RANGE( 3, MAX_ATTRIBUTE_SIZE ) },\n\t\n\t/* rfc822Name */\n\t{ NULL, CRYPT_CERTINFO_RFC822NAME,\n\t  DESCRIPTION( \"generalName.rfc822Name\" )\n\t  ENCODING_TAGGED( STRING_IA5, 1 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, CHECK_RFC822 },\n\t\n\t/* dNSName */\n\t{ NULL, CRYPT_CERTINFO_DNSNAME,\n\t  DESCRIPTION( \"generalName.dNSName\" )\n\t  ENCODING_TAGGED( STRING_IA5, 2 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, CHECK_DNS },\n\t\n\t/* directoryName */\n\t{ NULL, CRYPT_CERTINFO_DIRECTORYNAME,\n\t  DESCRIPTION( \"generalName.directoryName\" )\n\t  ENCODING_SPECIAL_TAGGED( DN, 4 ),\n\t  0, FL_OPTIONAL | FL_EXPLICIT, CHECK_X500 },\n\n\t/* ediPartyName */\n\t{ NULL, 0,\n\t  DESCRIPTION( \"generalName.ediPartyName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 5 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"generalName.ediPartyName.nameAssigner\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_TEXTSTRING },\n\t  /* See note above on why the extra SEQUENCE is present */\n\t{ NULL, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER,\n\t  DESCRIPTION( \"generalName.ediPartyName.nameAssigner.directoryName\" )\n\t  ENCODING_SPECIAL( TEXTSTRING ),\n\t  0, FL_OPTIONAL | FL_SEQEND, RANGE_TEXTSTRING },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"generalName.ediPartyName.partyName\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL, RANGE_TEXTSTRING },\n\t{ NULL, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME,\n\t  DESCRIPTION( \"generalName.ediPartyName.partyName.directoryName\" )\n\t  ENCODING_SPECIAL( TEXTSTRING ),\n\t  0, FL_OPTIONAL | FL_SEQEND_2, RANGE_TEXTSTRING },\n\t\n\t/* uniformResourceIdentifier */\n\t{ NULL, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t  DESCRIPTION( \"generalName.uniformResourceIdentifier\" )\n\t  ENCODING_TAGGED( STRING_IA5, 6 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, CHECK_URL },\n\t\n\t/* iPAddress */\n\t{ NULL, CRYPT_CERTINFO_IPADDRESS,\n\t  DESCRIPTION( \"generalName.iPAddress\" )\n\t  ENCODING_TAGGED( OCTETSTRING, 7 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE( 4, 16 ) },\n\n\t/* registeredID */\n\t{ NULL, CRYPT_CERTINFO_REGISTEREDID,\n\t  DESCRIPTION( \"generalName.registeredID\" )\n\t  ENCODING_TAGGED( OBJECT_IDENTIFIER, 8 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL, RANGE_OID },\n\n\t{ NULL, CRYPT_IATTRIBUTE_LAST }, { NULL, CRYPT_IATTRIBUTE_LAST }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMS Attribute Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMS attributes are encoded using the following table */\n\nstatic const ATTRIBUTE_INFO cmsAttributeInfo[] = {\n\t/* contentType:\n\n\t\tOID = 1 2 840 113549 1 9 3\n\t\tOBJECT IDENTIFIER */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x03\" ), CRYPT_CERTINFO_CMS_CONTENTTYPE,\n\t  DESCRIPTION( \"contentType\" )\n\t  ENCODING_SPECIAL( CHOICE ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, CRYPT_CONTENT_DATA, CRYPT_CONTENT_LAST, 0, ( void * ) contentTypeInfo },\n\n\t/* messageDigest:\n\n\t\tOID = 1 2 840 113549 1 9 4\n\t\tOCTET STRING */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x04\" ), CRYPT_CERTINFO_CMS_MESSAGEDIGEST,\n\t  DESCRIPTION( \"messageDigest\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) },\n\n\t/* signingTime:\n\n\t\tOID = 1 2 840 113549 1 9 5\n\t\tCHOICE {\n\t\t\tutcTime\t\t\tUTCTime,\t\t\t\t-- Up to 2049\n\t\t\tgeneralizedTime\tGeneralizedTime\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x05\" ), CRYPT_CERTINFO_CMS_SIGNINGTIME,\n\t  DESCRIPTION( \"signingTime\" )\n\t  ENCODING( TIME_UTC ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE_TIME },\n\n#ifdef USE_CMSATTR_OBSCURE\n\t/* counterSignature:\n\n\t\tOID = 1 2 840 113549 1 9 6\n\t\tCHOICE {\n\t\t\tutcTime\t\t\tUTCTime,\t\t\t\t-- Up to 2049\n\t\t\tgeneralizedTime\tGeneralizedTime\n\t\t\t}\n\n\t   This field isn't an authenticated attribute so it isn't used */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x06\" ), CRYPT_CERTINFO_CMS_COUNTERSIGNATURE,\n\t  DESCRIPTION( \"counterSignature\" )\n\t  ENCODING( NULL ),\t\t/* Dummy value */\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE_NONE },\n\n  \t/* signingDescription:\n\n\t\tOID = 1 2 840 113549 1 9 13\n\t\tUTF8String */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x0D\" ), CRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION,\n\t  DESCRIPTION( \"signingDescription\" )\n\t  ENCODING( STRING_UTF8 ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE_ATTRIBUTEBLOB },\n#endif /* USE_CMSATTR_OBSCURE */\n\n\t/* sMIMECapabilities:\n\n\t\tOID = 1 2 840 113549 1 9 15\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\tcapabilityID\tOBJECT IDENTIFIER,\n\t\t\t\tparameters\t\tANY DEFINED BY capabilityID\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x0F\" ), CRYPT_CERTINFO_CMS_SMIMECAPABILITIES,\n\t  DESCRIPTION( \"sMIMECapabilities\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (des-EDE3-CBC)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x07\" ), CRYPT_CERTINFO_CMS_SMIMECAP_3DES,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.des-EDE3-CBC\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (aes128-CBC)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x02\" ), CRYPT_CERTINFO_CMS_SMIMECAP_AES,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.aes128-CBC\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (cast5CBC)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF6\\x7D\\x07\\x42\\x0A\" ), CRYPT_CERTINFO_CMS_SMIMECAP_CAST128,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.cast5CBC\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.cast5CBC.parameter\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* 128-bit key */\n\t  0, FL_NONENCODING | FL_SEQEND, 0, 0, 4, \"\\x02\\x02\\x00\\x80\" },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (sha-ng)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"Unknown\" ), CRYPT_CERTINFO_CMS_SMIMECAP_SHAng,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.sha-ng\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (sha2-256)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x01\" ), CRYPT_CERTINFO_CMS_SMIMECAP_SHA2,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.sha2-256\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (sha1)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1A\" ), CRYPT_CERTINFO_CMS_SMIMECAP_SHA1,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.sha1\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (hmac-sha-ng)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"Unknown\" ), CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.hmac-sha-ng\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (hmac-sha2-256)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x09\" ), CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.hmac-sha2-256\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (hmac-sha1)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x08\\x01\\x02\" ), CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.hmac-sha1\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (authEnc256)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x10\" ), CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.authEnc256\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (authEnc128)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x0F\" ), CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.authEnc128\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (rsaWithSHAng)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"Unknown\" ), CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.rsaWithSHAng\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (rsaWithSHA2-256)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0B\" ), CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.rsaWithSHA2-256\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (rsaWithSHA1)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x05\" ), CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.rsaWithSHA1\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (dsaWithSHA1)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x04\\x03\" ), CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.dsaWithSHA1\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (ecdsaWithSHA-ng)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"Unknown\" ), CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.ecdsaWithSHA-ng\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (ecdsaWithSHA2-256)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x03\\x02\" ), CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.ecdsaWithSHA2-256\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (ecdsaWithSHA1)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x01\" ), CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.ecdsaWithSHA1\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (preferSignedData)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x0F\\x01\" ), CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.preferSignedData\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (canNotDecryptAny)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x0F\\x02\" ), CRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.canNotDecryptAny\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (preferBinaryInside)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x0B\\x01\" ), CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.preferBinaryInside\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_NONENCODING | FL_SEQEND, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability (catchAll)\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"sMIMECapabilities.capability.catchAll\" )\n\t  ENCODING_SPECIAL( BLOB_ANY ),\t/* Match anything and ignore it */\n\t  FL_ATTR_ATTREND, FL_NONENCODING | FL_SEQEND_2 /*FL_SEQEND*/, RANGE_NONE },\n\n#ifdef USE_CMSATTR_OBSCURE\n\t/* receiptRequest:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 1\n\t\tSEQUENCE {\n\t\t\tcontentIdentifier\tOCTET STRING,\n\t\t\treceiptsFrom  [ 0 ]\tINTEGER (0..1),\n\t\t\treceiptsTo\t\t\tSEQUENCE {\n\t\t\t\tSEQUENCE OF GeneralName\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x01\" ), CRYPT_CERTINFO_CMS_RECEIPTREQUEST,\n\t  DESCRIPTION( \"receiptRequest\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER,\n\t  DESCRIPTION( \"receiptRequest.contentIdentifier\" )\n\t  ENCODING( OCTETSTRING ),\n\t  0, 0, RANGE( 16, 64 ) },\n\t{ NULL, CRYPT_CERTINFO_CMS_RECEIPT_FROM,\n\t  DESCRIPTION( \"receiptRequest.receiptsFrom\" )\n\t  ENCODING_TAGGED( INTEGER, 0 ),\n\t  0, 0, RANGE( 0, 1 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"receiptRequest.receiptsTo\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"receiptRequest.receiptsTo.generalNames\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_RECEIPT_TO,\n\t  DESCRIPTION( \"receiptRequest.receiptsTo.generalNames.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, FL_MULTIVALUED | FL_SEQEND_3 /*FL_SEQEND_2*/, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* essSecurityLabel:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 2\n\t\tSET {\n\t\t\tpolicyIdentifier\tOBJECT IDENTIFIER,\n\t\t\tclassification\t\tINTEGER (0..5+6..255) OPTIONAL,\n\t\t\tprivacyMark\t\t\tPrintableString OPTIONAL,\n\t\t\tcategories\t\t\tSET OF {\n\t\t\t\tSEQUENCE {\n\t\t\t\t\ttype  [ 0 ]\tOBJECT IDENTIFIER,\n\t\t\t\t\tvalue [ 1 ]\tANY DEFINED BY type\n\t\t\t\t\t}\n\t\t\t\t} OPTIONAL\n\t\t\t}\n\n\t\tBecause this is a SET we don't order the fields in the sequence\n\t\tgiven in the above ASN.1 but in the order of encoded size to follow\n\t\tthe DER SET encoding rules */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x02\" ), CRYPT_CERTINFO_CMS_SECURITYLABEL,\n\t  DESCRIPTION( \"essSecurityLabel\" )\n\t  ENCODING( SET ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SECLABEL_POLICY,\n\t  DESCRIPTION( \"essSecurityLabel.securityPolicyIdentifier\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, 0, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION,\n\t  DESCRIPTION( \"essSecurityLabel.securityClassification\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_OPTIONAL, RANGE( CRYPT_CLASSIFICATION_UNMARKED, CRYPT_CLASSIFICATION_LAST ) },\n\t{ NULL, CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK,\n\t  DESCRIPTION( \"essSecurityLabel.privacyMark\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  0, FL_OPTIONAL, RANGE( 1, 64 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"essSecurityLabel.securityCategories\" )\n\t  ENCODING( SET ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"essSecurityLabel.securityCategories.securityCategory\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE,\n\t  DESCRIPTION( \"essSecurityLabel.securityCategories.securityCategory.type\" )\n\t  ENCODING_TAGGED( OBJECT_IDENTIFIER, 0 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE,\n\t  DESCRIPTION( \"essSecurityLabel.securityCategories.securityCategory.value\" )\n\t  ENCODING_SPECIAL_TAGGED( BLOB_ANY, 1 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND /*FL_SEQEND_2, or _3*/, RANGE_ATTRIBUTEBLOB },\n\n\t/* mlExpansionHistory:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 3\n\t\tSEQUENCE OF {\n\t\t\tSEQUENCE {\n\t\t\t\tentityIdentifier IssuerAndSerialNumber,\t-- Treated as blob\n\t\t\t\texpansionTime\tGeneralizedTime,\n\t\t\t\tmlReceiptPolicy\tCHOICE {\n\t\t\t\t\tnone\t\t  [ 0 ]\tNULL,\n\t\t\t\t\tinsteadOf\t  [ 1 ]\tSEQUENCE OF {\n\t\t\t\t\t\tSEQUENCE OF GeneralName\t\t-- GeneralNames\n\t\t\t\t\t\t}\n\t\t\t\t\tinAdditionTo  [ 2 ]\tSEQUENCE OF {\n\t\t\t\t\t\tSEQUENCE OF GeneralName\t\t-- GeneralNames\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x03\" ), CRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY,\n\t  DESCRIPTION( \"mlExpansionHistory\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mailListIdentifier.issuerAndSerialNumber\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  0, FL_MULTIVALUED, RANGE_ATTRIBUTEBLOB },\n\t{ NULL, CRYPT_CERTINFO_CMS_MLEXP_TIME,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.expansionTime\" )\n\t  ENCODING( TIME_GENERALIZED ),\n\t  0, FL_MULTIVALUED, RANGE_TIME },\n\t{ NULL, CRYPT_CERTINFO_CMS_MLEXP_NONE,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.none\" )\n\t  ENCODING_TAGGED( NULL, 0 ),\n\t  0, FL_MULTIVALUED, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.insteadOf\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.insteadOf.generalNames\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_MLEXP_INSTEADOF,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.insteadOf.generalNames.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  0, FL_OPTIONAL | FL_SEQEND_2 | FL_MULTIVALUED, ENCODED_OBJECT( generalNameInfo ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.inAdditionTo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 2 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.inAdditionTo.generalNames\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO,\n\t  DESCRIPTION( \"mlExpansionHistory.mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName\" )\n\t  ENCODING_SPECIAL( SUBTYPED ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND_2 /*FL_SEQEND_3, or _4*/ | FL_MULTIVALUED, ENCODED_OBJECT( generalNameInfo ) },\n\n\t/* contentHints:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 4\n\t\tSEQUENCE {\n\t\t\tcontentDescription\tUTF8String,\n\t\t\tcontentType\t\t\tOBJECT IDENTIFIER\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x04\" ), CRYPT_CERTINFO_CMS_CONTENTHINTS,\n\t  DESCRIPTION( \"contentHints\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION,\n\t  DESCRIPTION( \"contentHints.contentDescription\" )\n\t  ENCODING( STRING_UTF8 ),\n\t  0, FL_OPTIONAL, RANGE_TEXTSTRING },\n\t{ NULL, CRYPT_CERTINFO_CMS_CONTENTHINT_TYPE,\n\t  DESCRIPTION( \"contentHints.contentType\" )\n\t  ENCODING_SPECIAL( CHOICE ),\n\t  FL_ATTR_ATTREND, FL_SEQEND /*NONE*/, CRYPT_CONTENT_DATA, CRYPT_CONTENT_LAST, 0, ( void * ) contentTypeInfo },\n\n\t/* equivalentLabels:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 9\n\t\tSEQUENCE OF {\n\t\t\tSET {\n\t\t\t\tpolicyIdentifier OBJECT IDENTIFIER,\n\t\t\t\tclassification\tINTEGER (0..5) OPTIONAL,\n\t\t\t\tprivacyMark\t\tPrintableString OPTIONAL,\n\t\t\t\tcategories\t\tSET OF {\n\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\ttype  [ 0 ]\tOBJECT IDENTIFIER,\n\t\t\t\t\t\tvalue [ 1 ]\tANY DEFINED BY type\n\t\t\t\t\t\t}\n\t\t\t\t\t} OPTIONAL\n\t\t\t\t}\n\t\t\t}\n\n\t\tBecause this is a SET we don't order the fields in the sequence\n\t\tgiven in the above ASN.1 but in the order of encoded size to follow\n\t\tthe DER SET encoding rules */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x09\" ), CRYPT_CERTINFO_CMS_EQUIVALENTLABEL,\n\t  DESCRIPTION( \"equivalentLabels\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"equivalentLabels.set\" )\n\t  ENCODING( SET ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION,\n\t  DESCRIPTION( \"equivalentLabels.set.securityClassification\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, CRYPT_CLASSIFICATION_UNMARKED, CRYPT_CLASSIFICATION_LAST, 0, NULL },\n\t{ NULL, CRYPT_CERTINFO_CMS_EQVLABEL_POLICY,\n\t  DESCRIPTION( \"equivalentLabels.set.securityPolicyIdentifier\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK,\n\t  DESCRIPTION( \"equivalentLabels.set.privacyMark\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_TEXTSTRING },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"equivalentLabels.set.securityCategories\" )\n\t  ENCODING( SET ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"equivalentLabels.set.securityCategories.securityCategory\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE,\n\t  DESCRIPTION( \"equivalentLabels.set.securityCategories.securityCategory.type\" )\n\t  ENCODING_TAGGED( OBJECT_IDENTIFIER, 0 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE,\n\t  DESCRIPTION( \"equivalentLabels.set.securityCategories.securityCategory.value\" )\n\t  ENCODING_SPECIAL_TAGGED( BLOB_ANY, 1 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2 /*or _4*/, RANGE_ATTRIBUTEBLOB },\n#endif /* USE_CMSATTR_OBSCURE */\n\n#if defined( USE_CMSATTR_OBSCURE ) || defined( USE_CERTREV ) || defined( USE_TSP )\n\t/* signingCertificate:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 12\n\t\tSEQUENCE {\n\t\t\tSEQUENCE OF ESSCertID {\n\t\t\t\tcertHash\t\tOCTET STRING SIZE(20)\n\t\t\t\t},\n\t\t\tSEQUENCE OF {\n\t\t\t\tSEQUENCE {\n\t\t\t\t\tpolicyIdentifier\tOBJECT IDENTIFIER\n\t\t\t\t\t}\n\t\t\t\t} OPTIONAL\n\t\t\t}\n\n\t   See the long comment in the certificate attributes for why this \n\t   attribute has to be enabled if USE_CERTREV is defined */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x0C\" ), CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE,\n\t  DESCRIPTION( \"signingCertificate\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.certs\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID,\n\t  DESCRIPTION( \"signingCertificate.certs.essCertID\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  0, FL_MULTIVALUED | FL_SEQEND, RANGE_BLOB },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.policies\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.policies.policyInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES,\n\t  DESCRIPTION( \"signingCertificate.policies.policyInfo.policyIdentifier\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND /*or _3*/, RANGE_OID },\n#endif /* USE_CMSATTR_OBSCURE || USE_CERTREV || USE_TSP */\n\n\t/* signingCertificateV2:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 47\n\t\tSEQUENCE {\n\t\t\tSEQUENCE OF ESSCertIDv2 {\n\t\t\t\t\thashAlgorithm\t\tAlgorithmIdentifier DEFAULT {SHA-256},\n\t\t\t\t\tcertHash\t\t\tOCTET STRING\n\t\t\t\t\t},\n\t\t\tSEQUENCE OF {\n\t\t\t\tSEQUENCE {\n\t\t\t\t\tpolicyIdentifier\tOBJECT IDENTIFIER\n\t\t\t\t\t}\n\t\t\t\t} OPTIONAL\n\t\t\t} \n\n\t   This attribute is used to prevent certificate-substitution attacks on\n\t   signatures by uniquely identifying the entire signing certificate \n\t   rather than just including a reference to its issuer and serial \n\t   number.  In standard PKIX/CMS form this attribute, a single hash \n\t   value, is complicated by being a SEQUENCE OF, with a further SEQUENCE \n\t   OF policies attached, with no indication of what they're supposed to \n\t   do (or at least the text says \"the certificates after the first one \n\t   limit the set of authorization certificates that are used during \n\t   signature validation\", whatever that's supposed to mean) */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x2F\" ), CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2,\n\t  DESCRIPTION( \"signingCertificate\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.certs\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_SETOF, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2,\n\t  DESCRIPTION( \"signingCertificate.certs.essCertID\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  0, FL_MULTIVALUED | FL_SEQEND, RANGE_BLOB },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.policies\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signingCertificate.policies.policyInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES,\n\t  DESCRIPTION( \"signingCertificate.policies.policyInfo.policyIdentifier\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND /*or _3*/, RANGE_OID },\n\n#ifdef USE_CMSATTR_OBSCURE\n\t/* signaturePolicyID:\n\n\t\tOID = 1 2 840 113549 1 9 16 2 15\n\t\tSEQUENCE {\n\t\t\tsigPolicyID\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\tsigPolicyHash\t\t\t\tOtherHashAlgAndValue,\n\t\t\tsigPolicyQualifiers\t\t\tSEQUENCE OF {\n\t\t\t\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\tsigPolicyQualifierID\tOBJECT IDENTIFIER,\n\t\t\t\tsigPolicyQualifier\t\tANY DEFINED BY sigPolicyQualifierID\n\t\t\t\t\t}\n\t\t\t\t} OPTIONAL\n\t\t\t}\n\n\t\tCPSuri ::= IA5String\t\t\t\t\t\t-- OID = cps\n\n\t\tUserNotice ::= SEQUENCE {\t\t\t\t\t-- OID = unotice\n\t\t\tnoticeRef\t\tSEQUENCE {\n\t\t\t\torganization\tUTF8String,\n\t\t\t\tnoticeNumbers\tSEQUENCE OF INTEGER\t-- SIZE (1)\n\t\t\t\t} OPTIONAL,\n\t\t\texplicitText\tUTF8String OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x0F\" ), CRYPT_CERTINFO_CMS_SIGNATUREPOLICYID,\n\t  DESCRIPTION( \"signaturePolicyID\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICYID,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyID\" )\n\t  ENCODING( OBJECT_IDENTIFIER ),\n\t  0, 0, RANGE_OID },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICYHASH,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyHash\" )\n\t  ENCODING_SPECIAL( BLOB_SEQUENCE ),\n\t  0, 0, RANGE_BLOB },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_SETOF, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x05\\x01\" ), 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.cps (1 2 840 113549 1 9 16 5 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.cPSuri\" )\n\t  ENCODING( STRING_IA5 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2, CHECK_URL },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_IDENTIFIER, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x05\\x02\" ), 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.unotice (1 2 840 113549 1 9 16 5 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization\" )\n\t  ENCODING( STRING_UTF8 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE( 1, 200 ) },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION,\t/* Backwards-compat.handling for VisibleString */\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization\" )\n\t  ENCODING( STRING_ISO646 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED, RANGE( 1, 200 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers\" )\n\t  ENCODING( SEQUENCE ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers\" )\n\t  ENCODING( INTEGER ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND_2, RANGE( 1, 1000 ) },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT,\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText\" )\n\t  ENCODING( STRING_UTF8 ),\n\t  0, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND, RANGE( 1, 200 ) },\n\t{ NULL, CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT,\t/* Backwards-compat.handling for VisibleString */\n\t  DESCRIPTION( \"signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText\" )\n\t  ENCODING( STRING_ISO646 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_MULTIVALUED | FL_SEQEND /* or ... _5 */, RANGE( 1, 200 ) },\n\n\t/* signatureTypeIdentifier:\n\n\t\tOID = 1 2 840 113549 1 9 16 9\n\t\tSEQUENCE {\n\t\t\toidInstance1 OPTIONAL,\n\t\t\toidInstance2 OPTIONAL,\n\t\t\t\t...\n\t\t\toidInstanceN OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x09\" ), CRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER,\n\t  DESCRIPTION( \"signatureTypeIdentifier\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x09\\x01\" ), CRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG,\n\t  DESCRIPTION( \"signatureTypeIdentifier.originatorSig (1 2 840 113549 1 9 16 9 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x09\\x02\" ), CRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG,\n\t  DESCRIPTION( \"signatureTypeIdentifier.domainSig (1 2 840 113549 1 9 16 9 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x09\\x03\" ), CRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES,\n\t  DESCRIPTION( \"signatureTypeIdentifier.additionalAttributesSig (1 2 840 113549 1 9 16 9 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x09\\x04\" ), CRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG,\n\t  DESCRIPTION( \"signatureTypeIdentifier.reviewSig (1 2 840 113549 1 9 16 9 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE_NONE },\n#endif /* USE_CMSATTR_OBSCURE */\n\n\t/* randomNonce:\n\n\t\tOID = 1 2 840 113549 1 9 25 3\n\t\tOCTET STRING */\n\t{ MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x19\\x03\" ), CRYPT_CERTINFO_CMS_NONCE,\n\t  DESCRIPTION( \"randomNonce\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 4, CRYPT_MAX_HASHSIZE ) },\n\n#ifdef USE_SCEP\n\t/* SCEP attributes:\n\n\t\tmessageType:\n\t\t\tOID = 2 16 840 1 113733 1 9 2\n\t\t\tPrintableString\n\t\tpkiStatus\n\t\t\tOID = 2 16 840 1 113733 1 9 3\n\t\t\tPrintableString\n\t\tfailInfo\n\t\t\tOID = 2 16 840 1 113733 1 9 4\n\t\t\tPrintableString\n\t\tsenderNonce\n\t\t\tOID = 2 16 840 1 113733 1 9 5\n\t\t\tOCTET STRING\n\t\trecipientNonce\n\t\t\tOID = 2 16 840 1 113733 1 9 6\n\t\t\tOCTET STRING\n\t\ttransID\n\t\t\tOID = 2 16 840 1 113733 1 9 7\n\t\t\tPrintableString */\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x02\" ), CRYPT_CERTINFO_SCEP_MESSAGETYPE,\n\t  DESCRIPTION( \"messageType\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 1, 2 ) },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x03\" ), CRYPT_CERTINFO_SCEP_PKISTATUS,\n\t  DESCRIPTION( \"pkiStatus\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 1, 1 ) },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x04\" ), CRYPT_CERTINFO_SCEP_FAILINFO,\n\t  DESCRIPTION( \"failInfo\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 1, 1 ) },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x05\" ), CRYPT_CERTINFO_SCEP_SENDERNONCE,\n\t  DESCRIPTION( \"senderNonce\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 16, 16 ) },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x06\" ), CRYPT_CERTINFO_SCEP_RECIPIENTNONCE,\n\t  DESCRIPTION( \"recipientNonce\" )\n\t  ENCODING( OCTETSTRING ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 16, 16 ) },\n\t{ MKOID( \"\\x06\\x0A\\x60\\x86\\x48\\x01\\x86\\xF8\\x45\\x01\\x09\\x07\" ), CRYPT_CERTINFO_SCEP_TRANSACTIONID,\n\t  DESCRIPTION( \"transID\" )\n\t  ENCODING( STRING_PRINTABLE ),\n\t  ATTR_TYPEINFO_CMS | FL_ATTR_ATTREND, \n\t  0, RANGE( 2, CRYPT_MAX_TEXTSIZE ) },\n#endif /* USE_SCEP */\n\n#ifdef USE_CMSATTR_OBSCURE\n\t/* spcAgencyInfo:\n\n\t\tOID = 1 3 6 1 4 1 311 2 1 10\n\t\tSEQUENCE {\n\t\t\t[ 0 ] {\n\t\t\t\t??? (= [ 0 ] IA5String )\n\t\t\t\t}\n\t\t\t}\n\n\t   The format for this attribute is unknown but it seems to be an\n\t   unnecessarily nested URL which is probably an IA5String */\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x0A\" ), CRYPT_CERTINFO_CMS_SPCAGENCYINFO,\n\t  DESCRIPTION( \"spcAgencyInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"spcAgencyInfo.vendorInfo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, 0, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SPCAGENCYURL,\n\t  DESCRIPTION( \"spcAgencyInfo..vendorInfo.url\" )\n\t  ENCODING_TAGGED( STRING_IA5, 0 ),\n\t  FL_ATTR_ATTREND, FL_SEQEND /*NONE*/, CHECK_HTTP },\n\n\t/* spcStatementType:\n\n\t\tOID = 1 3 6 1 4 1 311 2 1 11\n\t\tSEQUENCE {\n\t\t\toidInstance1 OPTIONAL,\n\t\t\toidInstance2 OPTIONAL,\n\t\t\t\t...\n\t\t\toidInstanceN OPTIONAL\n\t\t\t} */\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x0B\" ), CRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE,\n\t  DESCRIPTION( \"spcStatementType\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  FL_SETOF, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x15\" ), CRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING,\n\t  DESCRIPTION( \"spcStatementType.individualCodeSigning (1 3 6 1 4 1 311 2 1 21)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x16\" ), CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING,\n\t  DESCRIPTION( \"spcStatementType.commercialCodeSigning (1 3 6 1 4 1 311 2 1 22)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND /*NONE*/, RANGE_NONE },\n\n\t/* spcOpusInfo:\n\n\t\tOID = 1 3 6 1 4 1 311 2 1 12\n\t\tSEQUENCE {\n\t\t\t[ 0 ] {\n\t\t\t\t??? (= [ 0 ] BMPString )\n\t\t\t\t}\n\t\t\t[ 1 ] {\n\t\t\t\t??? (= [ 0 ] IA5String )\n\t\t\t\t}\n\t\t\t}\n\n\t   The format for this attribute is unknown but it seems to be either an\n\t   empty sequence or some nested set of tagged fields that eventually\n\t   end up as text strings */\n\t{ MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x0C\" ), CRYPT_CERTINFO_CMS_SPCOPUSINFO,\n\t  DESCRIPTION( \"spcOpusInfo\" )\n\t  ENCODING( SEQUENCE ),\n\t  ATTR_TYPEINFO_CMS, \n\t  0, RANGE_NONE },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"spcOpusInfo.programInfo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 0 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME,\n\t  DESCRIPTION( \"spcOpusInfo.programInfo.name\" )\n\t  ENCODING_TAGGED( STRING_BMP, 0 ),\n\t  0, FL_OPTIONAL | FL_SEQEND, RANGE( 2, 128 ) },\n\t{ NULL, 0,\n\t  DESCRIPTION( \"spcOpusInfo.vendorInfo\" )\n\t  ENCODING_TAGGED( SEQUENCE, 1 ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL,\n\t  DESCRIPTION( \"spcOpusInfo.vendorInfo.url\" )\n\t  ENCODING_TAGGED( STRING_IA5, 0 ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL | FL_SEQEND, CHECK_HTTP },\n#endif /* USE_CMSATTR_OBSCURE */\n\n\t{ NULL, CRYPT_IATTRIBUTE_LAST }, { NULL, CRYPT_IATTRIBUTE_LAST }\n\t};\n\n/* Subtable for encoding the contentType.  Since the fieldID that we're \n   using for this subtable is a CRYPT_CONTENT_TYPE rather than the \n   CRYPT_ATTRIBUTE_TYPE that's used for the standard encoding tables, we \n   define a macro to convert to the appropriate type */\n\n#define MK_FIELDID( value )\t\t( CRYPT_ATTRIBUTE_TYPE ) ( value )\n\nSTATIC_DATA const ATTRIBUTE_INFO contentTypeInfo[] = {\n\t{ OID_CMS_DATA, MK_FIELDID( CRYPT_CONTENT_DATA ),\n\t  DESCRIPTION( \"contentType.data (1 2 840 113549 1 7 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTRSTART, FL_OPTIONAL, RANGE_NONE },\n\t{ OID_CMS_SIGNEDDATA, MK_FIELDID( CRYPT_CONTENT_SIGNEDDATA ),\n\t  DESCRIPTION( \"contentType.signedData (1 2 840 113549 1 7 2)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ OID_CMS_ENVELOPEDDATA, MK_FIELDID( CRYPT_CONTENT_ENVELOPEDDATA ),\n\t  DESCRIPTION( \"contentType.envelopedData (1 2 840 113549 1 7 3)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#ifdef USE_CMSATTR_OBSCURE\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x04\" ), MK_FIELDID( CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA ),\n\t  DESCRIPTION( \"contentType.signedAndEnvelopedData (1 2 840 113549 1 7 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#endif /* USE_CMSATTR_OBSCURE */\n\t{ OID_CMS_DIGESTEDDATA, MK_FIELDID( CRYPT_CONTENT_DIGESTEDDATA ),\n\t  DESCRIPTION( \"contentType.digestedData (1 2 840 113549 1 7 5)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ OID_CMS_ENCRYPTEDDATA, MK_FIELDID( CRYPT_CONTENT_ENCRYPTEDDATA ),\n\t  DESCRIPTION( \"contentType.encryptedData (1 2 840 113549 1 7 6)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#ifdef USE_COMPRESSION\n\t{ OID_CMS_COMPRESSEDDATA, MK_FIELDID( CRYPT_CONTENT_COMPRESSEDDATA ),\n\t  DESCRIPTION( \"contentType.compressedData (1 2 840 113549 1 9 16 1 9)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#endif /* USE_COMPRESSION */\n#ifdef USE_TSP\n\t{ OID_CMS_TSTOKEN, MK_FIELDID( CRYPT_CONTENT_TSTINFO ),\n\t  DESCRIPTION( \"contentType.tstInfo (1 2 840 113549 1 9 16 1 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#endif /* USE_TSP */\n#ifdef USE_CMSATTR_OBSCURE\n\t{ OID_MS_SPCINDIRECTDATACONTEXT, MK_FIELDID( CRYPT_CONTENT_SPCINDIRECTDATACONTEXT ),\n\t  DESCRIPTION( \"contentType.spcIndirectDataContext (1 3 6 1 4 1 311 2 1 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#endif /* USE_CMSATTR_OBSCURE */\n#ifdef USE_CERTVAL\n\t{ OID_CRYPTLIB_RTCSREQ, MK_FIELDID( CRYPT_CONTENT_RTCSREQUEST ),\n\t  DESCRIPTION( \"contentType.rtcsRequest (1 3 6 1 4 1 3029 4 1 4)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ OID_CRYPTLIB_RTCSRESP, MK_FIELDID( CRYPT_CONTENT_RTCSRESPONSE ),\n\t  DESCRIPTION( \"contentType.rtcsResponse (1 3 6 1 4 1 3029 4 1 5)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n\t{ OID_CRYPTLIB_RTCSRESP_EXT, MK_FIELDID( CRYPT_CONTENT_RTCSRESPONSE_EXT ),\n\t  DESCRIPTION( \"contentType.rtcsResponseExt (1 3 6 1 4 1 3029 4 1 6)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  0, FL_OPTIONAL, RANGE_NONE },\n#endif /* USE_CERTVAL */\n\t{ MKOID( \"\\x06\\x06\\x67\\x81\\x08\\x01\\x01\\x01\" ), MK_FIELDID( CRYPT_CONTENT_MRTD ),\n\t  DESCRIPTION( \"contentType.mRTD (2 23 136 1 1 1)\" )\n\t  ENCODING_SPECIAL( IDENTIFIER ),\n\t  FL_ATTR_ATTREND, FL_OPTIONAL, RANGE_NONE },\n\t{ NULL, CRYPT_IATTRIBUTE_LAST }, { NULL, CRYPT_IATTRIBUTE_LAST }\n\t};\n\n/* Select the appropriate attribute information table for encoding/type \n   checking */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getAttributeInfo( IN_ENUM( ATTRIBUTE ) const ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t  OUT const ATTRIBUTE_INFO **attributeInfoPtrPtr,\n\t\t\t\t\t  OUT_INT_Z int *noAttributeEntries )\n\t{\n\tassert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isWritePtr( noAttributeEntries, sizeof( int ) ) );\n\n\tREQUIRES( attributeType == ATTRIBUTE_CERTIFICATE || \\\n\t\t\t  attributeType == ATTRIBUTE_CMS );\n\t\n\tif( attributeType == ATTRIBUTE_CMS )\n\t\t{\n\t\t*attributeInfoPtrPtr = cmsAttributeInfo;\n\t\t*noAttributeEntries = FAILSAFE_ARRAYSIZE( cmsAttributeInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO );\n\t\t}\n\telse\n\t\t{\n\t\t*attributeInfoPtrPtr = extensionInfo;\n\t\t*noAttributeEntries = FAILSAFE_ARRAYSIZE( extensionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the validity of the encoding information for an individual \n   extension */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkExtension( IN_ARRAY( noAttributeInfoEntries ) \\\n\t\t\t\t\t\t\t\tconst ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int noAttributeInfoEntries,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE CRYPT_ATTRIBUTE_TYPE firstAttributeID,\n\t\t\t\t\t\t\t   const BOOLEAN isStandardAttribute, \n\t\t\t\t\t\t\t   const BOOLEAN isSubTable )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE prevFieldID = CRYPT_ATTRIBUTE_NONE;\n\tBOOLEAN seenFirstField = FALSE;\n\tint nestingLevel = 0, attributeEntryCount, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( attributeInfoPtr, \\\n\t\t\t\t\t\t\t  noAttributeInfoEntries * sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( noAttributeInfoEntries ) );\n\tREQUIRES_B( ( !isSubTable && \\\n\t\t\t\t  firstAttributeID >= CRYPT_CERTINFO_FIRST && \\\n\t\t\t\t  firstAttributeID < CRYPT_CERTINFO_LAST ) || \\\n\t\t\t\t( isSubTable && \\\n\t\t\t\t  firstAttributeID >= 0 && firstAttributeID < 50 ) );\n\t\t\t\t/* Subtables are indexed by small integer values \n\t\t\t\t   (CRYPT_CONTENT_TYPE, CRYPT_HOLDINSTRUCTION_TYPE) rather\n\t\t\t\t   than CRYPT_ATTRIBUTE_TYPE so the values are outside the\n\t\t\t\t   usual CRYPT_CERTINFO_xxx range */\n\tREQUIRES_B( isStandardAttribute == TRUE || isStandardAttribute == FALSE );\n\tREQUIRES_B( isSubTable == TRUE || isSubTable == FALSE );\n\n\t/* The first entry must be marked as the attribute start and must have an\n\t   associated OID */\n\tif( !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTRSTART ) )\n\t\treturn( FALSE );\n\tif( isStandardAttribute && attributeInfoPtr->oid == NULL )\n\t\treturn( FALSE );\n\n\t/* The overall attribute can't have a lower attribute ID than any \n\t   preceding attribute */\n\tif( attributeInfoPtr->fieldID == FIELDID_FOLLOWS )\n\t\t{\n\t\tif( attributeInfoPtr[ 1 ].fieldID < firstAttributeID )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( attributeInfoPtr->fieldID < firstAttributeID )\n\t\t\treturn( FALSE );\n\t\t}\n\n\tLOOP_LARGE( attributeEntryCount = 0,\n\t\t\t\t!isAttributeTableEnd( attributeInfoPtr ) && \\\n\t\t\t\t\tattributeEntryCount < noAttributeInfoEntries,\n\t\t\t\t( attributeInfoPtr++, attributeEntryCount++ ) )\n\t\t{\n\t\tconst int nestingLevelDelta = \\\n\t\t\t\t\tdecodeNestingLevel( attributeInfoPtr->encodingFlags );\n\n\t\t/* Make sure that various ranges are valid */\n\t\tif( nestingLevelDelta < 0 || nestingLevelDelta > 5 )\n\t\t\treturn( FALSE );\n\t\tif( decodeComplianceLevel( attributeInfoPtr->typeInfoFlags ) < \\\n\t\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_OBLIVIOUS || \\\n\t\t\tdecodeComplianceLevel( attributeInfoPtr->typeInfoFlags ) >= \\\n\t\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_LAST )\n\t\t\treturn( FALSE );\n\n\t\t/* Make sure that the fieldIDs (if present for this entry) are \n\t\t   sorted.  We can't require that they be monotone increasing \n\t\t   because handling of some extensions may have been disabled \n\t\t   through the use of configuration options */\n\t\tif( attributeInfoPtr->fieldID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\tattributeInfoPtr->fieldID != FIELDID_FOLLOWS && \\\n\t\t\tattributeInfoPtr->fieldID <= prevFieldID )\n\t\t\t{\n\t\t\t/* There are a few special-case situations in which the fields\n\t\t\t   don't appear sorted:\n\n\t\t\t\tequivalentLabels is for some unknown reason it's defined as \n\t\t\t\ta SET rather than a SEQUENCE, so the fields are given in \n\t\t\t\ttheir encoding order rather than their sorting order.  This \n\t\t\t\tmeans in practice that the two fields \n\t\t\t\tCRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION and\n\t\t\t\tCRYPT_CERTINFO_CMS_EQVLABEL_POLICY are reversed.\n\n\t\t\t\tsignaturePolicyID has changed over time to use a different\n\t\t\t\tencoding form for its text strings, which is handled in a\n\t\t\t\ttransparent manner by having the \n\t\t\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION and \n\t\t\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT entries present \n\t\t\t\ttwice, first with the current (preferred) format and then \n\t\t\t\tagain with the legacy one */\n\t\t\tif( !( ( prevFieldID == CRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION && \\\n\t\t\t\t\t attributeInfoPtr->fieldID == CRYPT_CERTINFO_CMS_EQVLABEL_POLICY ) || \\\n\t\t\t\t   ( prevFieldID == CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION && \\\n\t\t\t\t     attributeInfoPtr->fieldID == CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION ) || \\\n\t\t\t\t   ( prevFieldID == CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT && \\\n\t\t\t\t\t attributeInfoPtr->fieldID == CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT ) ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( attributeInfoPtr->fieldID > CRYPT_ATTRIBUTE_NONE && \\\n\t\t\tattributeInfoPtr->fieldID < CRYPT_ATTRIBUTE_LAST )\n\t\t\t{\n\t\t\t/* This may be a field code or unused, so we only update it if\n\t\t\t   it's an attribute value */\n\t\t\tprevFieldID = attributeInfoPtr->fieldID;\n\t\t\t}\n\n\t\t/* Make sure that the field entries are consistent with the field \n\t\t   type */\n\t\tif( attributeInfoPtr->fieldType < FIELDTYPE_LAST || \\\n\t\t\tattributeInfoPtr->fieldType >= MAX_TAG )\n\t\t\treturn( FALSE ); \n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE && \\\n\t\t\tattributeInfoPtr->extraData == NULL )\n\t\t\t{\n\t\t\t/* CHOICE must have a CHOICE encoding table */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_DN && \\\n\t\t\tattributeInfoPtr->extraData == NULL )\n\t\t\t{\n\t\t\t/* DN must have a DN entry checking function */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( ( attributeInfoPtr->fieldType == FIELDTYPE_DN || \\\n\t\t\t  attributeInfoPtr->fieldType == FIELDTYPE_BLOB_ANY ) && \\\n\t\t\t  ( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) && \\\n\t\t\t  !( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) )\n\t\t\t{\n\t\t\t/* A FIELDTYPE_BLOB_ANY or FIELDTYPE_DN can't be optional fields \n\t\t\t   (unless they're explicitly tagged) because with no type \n\t\t\t   information for them available there's no way to check \n\t\t\t   whether we've encountered them or not */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )\n\t\t\t{\n\t\t\t/* Subtyped field must have a subtype encoding table, currently \n\t\t\t   this can only be the GeneralName table */\n\t\t\tif( attributeInfoPtr->extraData != generalNameInfo )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Make sure that the field really is a GeneralName */\n\t\t\tif( !isGeneralNameSelectionComponent( attributeInfoPtr->fieldID ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( attributeInfoPtr->fieldType == FIELDID_FOLLOWS )\n\t\t\t{\n\t\t\tconst ATTRIBUTE_INFO *nextAttributeInfoPtr = attributeInfoPtr + 1;\n\n\t\t\t/* FIELDID_FOLLOWS entry must be at the start of the attribute \n\t\t\t   and must followed by the one that contains the actual field \n\t\t\t   ID */\n\t\t\tif( !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTRSTART ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( !isValidExtension( nextAttributeInfoPtr->fieldID ) )\n\t\t\t\treturn( FALSE ); \n\t\t\t}\n\n\t\t/* We shouldn't be finding another attribute-start flag in the \n\t\t   middle of the current attribute */\n\t\tif( seenFirstField && \\\n\t\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTRSTART ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Make sure that identifier fields are set up correctly */\n\t\tif( attributeInfoPtr->encodingFlags & FL_IDENTIFIER )\n\t\t\t{\n\t\t\t/* Each identifier field must be followed by the OID that \n\t\t\t   identifies it (required in ext_chk.c and ext_rd.c) unless\n\t\t\t   it's the final catch-all blob entry */\n\t\t\tif( attributeInfoPtr[ 1 ].fieldType == FIELDTYPE_BLOB_ANY )\n\t\t\t\t{\n\t\t\t\tif( attributeInfoPtr[ 1 ].oid != NULL )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( attributeInfoPtr[ 1 ].oid == NULL )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* If there's optional parameters following the OID then they \n\t\t\t   have to be part of the current extension (required in \n\t\t\t   ext_chk.c) */\n\t\t\tif( ( attributeInfoPtr[ 1 ].encodingFlags & FL_NONENCODING ) && \\\n\t\t\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Make sure that fields with default values are booleans.  This \n\t\t   isn't technically required (ext.c simply uses the value stored in \n\t\t   the 'defaultValue' field) but currently all default-value fields \n\t\t   are booleans so we add it as a safety check */\n\t\tif( ( attributeInfoPtr->encodingFlags & FL_DEFAULT ) && \\\n\t\t\tattributeInfoPtr->fieldType != BER_BOOLEAN )\n\t\t\treturn( FALSE );\n\t\tif( !isIntegerRange( attributeInfoPtr->defaultValue ) )\n\t\t\treturn( FALSE );\n\n\t\t/* At the moment only complete-attribute SET/SEQUENCEs can be marked\n\t\t   with FL_EMPTYOK, see the comment in certattr.h for details */\n\t\tif( ( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) && \\\n\t\t\tattributeInfoPtr->fieldID != CRYPT_CERTINFO_BASICCONSTRAINTS )\n\t\t\treturn( FALSE );\n\n\t\t/* If it's a CHOICE field then it must be associated with an \n\t\t   encoding subtable for which each entry has the type\n\t\t   FIELDTYPE_IDENTIFIER.  The presence of the subtable has already\n\t\t   been checked in the general field-entry checks above */\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )\n\t\t\t{\n\t\t\tconst ATTRIBUTE_INFO *subTableInfoPtr;\n\t\t\tint LOOP_ITERATOR_ALT;\n\n\t\t\tLOOP_MED_ALT( subTableInfoPtr = attributeInfoPtr->extraData, \n\t\t\t\t\t\t  !isAttributeTableEnd( subTableInfoPtr ),\n\t\t\t\t\t\t  subTableInfoPtr++ )\n\t\t\t\t{\n\t\t\t\tif( subTableInfoPtr->fieldType != FIELDTYPE_IDENTIFIER )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\t\t}\n\n\t\t/* If it's a sequence/set, increment the nesting level; if it's an \n\t\t   end-of-constructed-item marker, decrement it by the appropriate \n\t\t   amount */\n\t\tif( attributeInfoPtr->fieldType == BER_SEQUENCE || \\\n\t\t\tattributeInfoPtr->fieldType == BER_SET )\n\t\t\tnestingLevel++;\n\t\tnestingLevel -= nestingLevelDelta;\n\n\t\t/* Make sure that the encoding information is valid */\n\t\tif( !( attributeInfoPtr->fieldEncodedType == CRYPT_UNUSED || \\\n\t\t\t   ( attributeInfoPtr->fieldEncodedType >= 0 && \\\n\t\t\t\t attributeInfoPtr->fieldEncodedType < MAX_TAG_VALUE ) ) )\n\t\t\treturn( FALSE );\n\n\t\t/* If it's explicitly tagged make sure that it's a constructed tag \n\t\t   in the correct range */\n\t\tif( attributeInfoPtr->encodingFlags & FL_EXPLICIT )\n\t\t\t{\n\t\t\tif( ( attributeInfoPtr->fieldEncodedType < 0 ) || \\\n\t\t\t\t( attributeInfoPtr->fieldEncodedType >= MAX_TAG ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Check any remaining miscellaneous conditions */\n\t\tif( attributeInfoPtr->encodingFlags & FL_SPECIALENCODING )\n\t\t\t{\n\t\t\t/* This flag is only valid for certificate requests, and the \n\t\t\t   attribute that it applies to can only have a single field */\n\t\t\tif( ( attributeInfoPtr->typeInfoFlags & \\\n\t\t\t\t\t\t\t\tFL_VALID_MASK ) != FL_VALID_CERTREQ || \\\n\t\t\t\t!( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* If we've reached the end of the extension, we're done */\n\t\tif( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND )\n\t\t\tbreak;\n\n\t\t/* Remember that we've seen the first field, from now on we \n\t\t   shouldn't be seeing any start-of-attribute fields */\n\t\tseenFirstField = TRUE;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( attributeEntryCount < noAttributeInfoEntries );\n\n\t/* The last entry must be marked as the attribute end */\n\tif( !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that the nesting is correct.  Unfortunately this isn't a \n\t   very good check because we can exit with a nesting level between zero \n\t   and four, see the long comment in cert/certattr.h on the complexities \n\t   of deeply nested SEQUENCEs with optional components */\n\tif( nestingLevel < 0 || nestingLevel > 4 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/* Check the validity of each extension in an encoding table */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkExtensionTable( IN_ARRAY( noAttributeInfoEntries ) \\\n\t\t\t\t\t\t\t\t\t\tconst ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int noAttributeInfoEntries,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isStandardAttribute, \n\t\t\t\t\t\t\t\t\tconst BOOLEAN isSubTable )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE baseAttributeID;\n\tint index, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( attributeInfoPtr, \\\n\t\t\t\t\t\t\t  noAttributeInfoEntries * sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( noAttributeInfoEntries ) );\n\tREQUIRES( isStandardAttribute == TRUE || isStandardAttribute == FALSE );\n\tREQUIRES( isSubTable == TRUE || isSubTable == FALSE );\n\n\tbaseAttributeID = ( attributeInfoPtr->fieldID == FIELDID_FOLLOWS ) ? \\\n\t\t\t\t\t  attributeInfoPtr[ 1 ].fieldID : attributeInfoPtr->fieldID;\n\tLOOP_LARGE( index = 0,\n\t\t\t\t!isAttributeTableEnd( attributeInfoPtr ) && \\\n\t\t\t\t\tindex < noAttributeInfoEntries,\n\t\t\t\t( attributeInfoPtr++, index++ ) )\n\t\t{\n\t\tint noAdditionalEntries, LOOP_ITERATOR_ALT;\n\n\t\tif( !checkExtension( attributeInfoPtr, \\\n\t\t\t\t\t\t\t\tnoAttributeInfoEntries - index,\n\t\t\t\t\t\t\t baseAttributeID, isStandardAttribute, \n\t\t\t\t\t\t\t isSubTable ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Extension '%s' definition consistency check failed\",\n\t\t\t\t\t\t ( attributeInfoPtr->description != NULL ) ? \\\n\t\t\t\t\t\t\tattributeInfoPtr->description : \"<Unknown>\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Remember the base attribute ID, which all subsequent IDs have to\n\t\t   be equal to or higher.  The only exception to this is the ID for\n\t\t   the ESSCertID attribute, which also applies to certificates and \n\t\t   so appears in a out-of-place location in the certificate \n\t\t   extensions */ \n\t\tif( attributeInfoPtr->fieldID != CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE && \\\n\t\t\tattributeInfoPtr->fieldID != CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID )\n\t\t\t{\n\t\t\tbaseAttributeID = ( attributeInfoPtr->fieldID == FIELDID_FOLLOWS ) ? \\\n\t\t\t\t\t\t\t\tattributeInfoPtr[ 1 ].fieldID + 1 : \\\n\t\t\t\t\t\t\t\tattributeInfoPtr->fieldID + 1;\n\t\t\t}\n\n\t\t/* Skip the remainder of this attribute */\n\t\tLOOP_MED_ALT( noAdditionalEntries = 0,\n\t\t\t\t\t  !isAttributeTableEnd( attributeInfoPtr ) && \\\n\t\t\t\t\t\t\t!( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) && \\\n\t\t\t\t\t\t\tnoAdditionalEntries < noAttributeInfoEntries,\n\t\t\t\t\t  ( attributeInfoPtr++, noAdditionalEntries++ ) );\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tENSURES_B( noAdditionalEntries < noAttributeInfoEntries );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Sanity-check the validity of the encoding tables */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN sanityCheckExtensionTables( void )\n\t{\n\tstatic const MAP_TABLE checkNestingTbl[] = {\n\t\t{ FL_SEQEND, 1 },\n\t\t{ FL_SEQEND_2, 2 },\n\t\t{ FL_SEQEND_3, 3 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tstatic const MAP_TABLE checkComplianceTbl[] = {\n\t\t{ FL_LEVEL_OBLIVIOUS, CRYPT_COMPLIANCELEVEL_OBLIVIOUS },\n\t\t{ FL_LEVEL_REDUCED, CRYPT_COMPLIANCELEVEL_REDUCED },\n\t\t{ FL_LEVEL_STANDARD, CRYPT_COMPLIANCELEVEL_STANDARD },\n\t\t{ FL_LEVEL_PKIX_PARTIAL, CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL },\n\t\t{ FL_LEVEL_PKIX_FULL, CRYPT_COMPLIANCELEVEL_PKIX_FULL },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\t/* Sanity checks on various encoded attribute information flags.  These \n\t   evaluate to constant expressions at compile-time, which both (at \n\t   least somewhat) defeats the point of the check and can also lead to\n\t   compiler warnings with some compilers due to the expressions being\n\t   constant, so we evaluate them from a table in order to ensure that \n\t   they're actually evaluated and to get rid of compiler warnings */\n\tLOOP_SMALL( i = 0, \n\t\t\t\tcheckNestingTbl[ i ].source != CRYPT_ERROR && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( checkNestingTbl, \\\n\t\t\t\t\t\t\t\t\t\t\tsizeof( MAP_TABLE ) ), i++ )\n\t\t{\n\t\tENSURES_B( decodeNestingLevel( checkNestingTbl[ i ].source ) == \\\n\t\t\t\t   checkNestingTbl[ i ].destination );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < FAILSAFE_ARRAYSIZE( checkNestingTbl, \\\n\t\t\t\t\t\t\t\t\t   sizeof( MAP_TABLE ) ) );\n\tLOOP_SMALL( i = 0,\n\t\t\t\tcheckComplianceTbl[ i ].source != CRYPT_ERROR && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( checkComplianceTbl, \\\n\t\t\t\t\t\t\t\t\t\t\tsizeof( MAP_TABLE ) ), i++ )\n\t\t{\n\t\tENSURES_B( decodeComplianceLevel( checkComplianceTbl[ i ].source ) == \\\n\t\t\t\t   checkComplianceTbl[ i ].destination );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < FAILSAFE_ARRAYSIZE( checkComplianceTbl, \\\n\t\t\t\t\t\t\t\t\t   sizeof( MAP_TABLE ) ) );\n\n\t/* Check each encoding table */\n\tif( !checkExtensionTable( extensionInfo, \n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( extensionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO ), \n\t\t\t\t\t\t\t  TRUE, FALSE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Certificate extension definition consistency check failed\" ));\n\t\tretIntError_Boolean();\n\t\t}\n\tif( !checkExtensionTable( cmsAttributeInfo,\n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( cmsAttributeInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO ), \n\t\t\t\t\t\t\t  TRUE, FALSE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"CMS attribute definition consistency check failed\" ));\n\t\tretIntError_Boolean();\n\t\t}\n\tif( !checkExtensionTable( generalNameInfo,\n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( generalNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO ), \n\t\t\t\t\t\t\t  FALSE, FALSE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"GeneralName definition consistency check failed\" ));\n\t\tretIntError_Boolean();\n\t\t}\n#if ( defined( USE_CERTREV ) || defined( USE_CERTREQ ) ) && \\\n\tdefined( USE_CERTLEVEL_PKIX_FULL )\n\tif( !checkExtensionTable( holdInstructionInfo,\n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( holdInstructionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO ), \n\t\t\t\t\t\t\t  TRUE, TRUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"HoldInstructionInfo definition consistency check failed\" ));\n\t\tretIntError_Boolean();\n\t\t}\n#endif /* ( USE_CERTREV || USE_CERTREQ ) && USE_CERTLEVEL_PKIX_FULL */\n\tif( !checkExtensionTable( contentTypeInfo,\n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( contentTypeInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ATTRIBUTE_INFO ), \n\t\t\t\t\t\t\t  TRUE, TRUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"ContentTypeInfo definition consistency check failed\" ));\n\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tExtended Validity Checking Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine whether a variety of URIs are valid and return a \n   CRYPT_ERRTYPE_TYPE describing the type of error if there's a problem.  \n   The PKIX RFC refers to a pile of complex parsing rules for various URI \n   forms, since cryptlib is neither a resolver nor an MTA nor a web browser \n   it leaves it up to the calling application to decide whether a particular \n   form is acceptable to it or not.  We do however perform a few basic \n   checks to weed out obviously-incorrect forms here.\n   \n   In theory we could use sNetParseUrl() for this but the code won't be\n   included if cryptlib is built without networking support, and in any case \n   we also need to perform processing for URLs that aren't network URLs */\n\ntypedef enum {\n\tURL_NONE,\t\t\t\t/* No URL */\n\tURL_RFC822,\t\t\t\t/* Email address */\n\tURL_DNS,\t\t\t\t/* FQDN */\n\tURL_HTTP,\t\t\t\t/* HTTP URL */\n\tURL_ANY,\t\t\t\t/* Generic URL */\n\tURL_LAST\t\t\t\t/* Last possible URL type */\n\t} URL_CHECK_TYPE;\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkURLString( IN_BUFFER( urlLength ) const char *url, \n\t\t\t\t\t\t   IN_LENGTH_DNS const int urlLength,\n\t\t\t\t\t\t   IN_ENUM( URL ) const URL_CHECK_TYPE urlType )\n\t{\n\tconst char *schema = NULL;\n\tint schemaLength = 0, length = urlLength, offset, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( url, urlLength ) );\n\n\tREQUIRES_EXT( urlLength >= MIN_RFC822_SIZE && urlLength < MAX_URL_SIZE,\n\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\t  /* MIN_RFC822_SIZE is the shortest value allow, \n\t\t\t\t     MAX_URL_SIZE is the largest */\n\tREQUIRES_EXT( isEnumRange( urlType, URL ),\n\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\n\t/* Make a first pass over the URL checking that it follows the RFC 1738 \n\t   rules for valid characters.  Because of the use of wildcards in \n\t   certificates we can't check for '*' at this point but have to make a\n\t   second pass after we've performed URL-specific processing */\n\tLOOP_EXT( i = 0, i < urlLength, i++, MAX_URL_SIZE + 1 )\n\t\t{\n\t\tconst int ch = byteToInt( url[ i ] );\n\n\t\tif( !isValidTextChar( ch ) || \\\n\t\t\tch == ' ' || ch == '<' || ch == '>' || ch == '\"' || \\\n\t\t\tch == '{' || ch == '}' || ch == '|' || ch == '\\\\' || \\\n\t\t\tch == '^' || ch == '[' || ch == ']' || ch == '`' )\n\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Check for a schema separator.  This gets a bit complicated because\n\t   some URLs use \"://\" (HTTP, FTP, LDAP) and others just use \":\" (SMTP, \n\t   SIP), so we have to check for both.  We can't check for a possibly-\n\t   malformed \":/\" because this could be something like \n\t   \"file:/dir/filename\", which is valid.  The pattern that we check for\n\t   is '(2...8 chars) \":\" [\"//\" ] (3...n chars)' */\n\tif( ( offset = strFindStr( url, urlLength, \"://\", 3 ) ) >= 0 )\n\t\t{\n\t\t/* Extract the URI schema */\n\t\tif( offset < 2 || offset > 8 || offset >= urlLength - 3 )\n\t\t\treturn( CRYPT_ERRTYPE_ATTR_SIZE );\n\t\toffset += 3;\t/* Adjust for \"://\" */\n\t\t}\n\telse\n\t\t{\n\t\tif( ( offset = strFindCh( url, urlLength, ':' ) ) >= 0 )\n\t\t\t{\n\t\t\t/* Extract the URI schema */\n\t\t\tif( offset < 2 || offset > 8 || offset >= urlLength - 3 )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_SIZE );\n\t\t\toffset++;\t/* Adjust for \":\" */\n\t\t\t}\n\t\t}\n\tif( offset > 0 )\n\t\t{\n\t\tschema = url;\n\t\tschemaLength = offset;\n\t\turl += offset;\n\t\tlength = urlLength - offset;\n\t\t}\n\tENSURES_EXT( boundsCheckZ( schemaLength, length, urlLength ),\n\t\t\t\t CRYPT_ERRTYPE_ATTR_VALUE );\n\n\t/* Make sure that the start of the URL looks valid.  Note that this \n\t   simply checks for obvious mistakes (e.g. setting an IP address for a \n\t   DNS name), not for every possible way of disguising one kind of URL \n\t   as another.\n\n\t   The lengths have already been checked by the kernel but we check them \n\t   again here to be sure */\n\tswitch( urlType )\n\t\t{\n\t\tcase URL_DNS:\n\t\t\tif( urlLength < MIN_DNS_SIZE || urlLength > MAX_DNS_SIZE )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_SIZE );\n\t\t\tif( schema != NULL )\n\t\t\t\t{\n\t\t\t\t/* It's a URL, not a DNS name */\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\t}\n\t\t\tif( ( isDigit( url[ 0 ] && isDigit( url[ 1 ] ) ) ) || \\\n\t\t\t\t( url[ 0 ] == '[' && \\\n\t\t\t\t  ( url[ 1 ] == ':' || isDigit( url[ 1 ] ) ) ) )\n\t\t\t\t{\n\t\t\t\t/* It's an IPv4 or IPv6 address, not a DNS name */\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\t}\n\t\t\tif( !strCompare( url, \"*.\", 2 ) )\n\t\t\t\t{\n\t\t\t\turl += 2;\t/* Skip wildcard */\n\t\t\t\tlength -= 2;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase URL_RFC822:\n\t\t\tif( urlLength < MIN_RFC822_SIZE || urlLength > MAX_RFC822_SIZE )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_SIZE );\n\t\t\tif( schema != NULL )\n\t\t\t\t{\n\t\t\t\t/* Catch erroneous use of URL */\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\t}\n\t\t\tif( !strCompare( url, \"*@\", 2 ) )\n\t\t\t\t{\n\t\t\t\turl += 2;\t/* Skip wildcard */\n\t\t\t\tlength -= 2;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase URL_HTTP:\n\t\t\tif( urlLength < MIN_URL_SIZE || urlLength > MAX_URL_SIZE )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_SIZE );\n\t\t\tif( schema == NULL || \\\n\t\t\t\t( strCompare( schema, \"http://\", 7 ) && \\\n\t\t\t\t  strCompare( schema, \"https://\", 8 ) ) )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\tif( !strCompare( url, \"*.\", 2 ) )\n\t\t\t\t{\n\t\t\t\turl += 2;\t/* Skip wildcard */\n\t\t\t\tlength -= 2;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase URL_ANY:\n\t\t\tif( schema == NULL || length < 3 || length > MAX_URL_SIZE )\n\t\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make a second pass over the URL checking for any remaining invalid \n\t   characters.  Since we've stripped any permitted wildcards earlier on,\n\t   the wildcard is now an invalid character */\n\tLOOP_EXT( i = 0, i < length, i++, MAX_URL_SIZE + 1 )\n\t\t{\n\t\tconst int ch = byteToInt( url[ i ] );\n\n\t\tif( ch == '*' )\n\t\t\treturn( CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_ERRTYPE_NONE );\n\t}\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRFC822( const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\treturn( checkURLString( attributeListPtr->dataValue,\n\t\t\t\t\t\t\tattributeListPtr->dataValueLength, URL_RFC822 ) );\n\t}\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDNS( const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\treturn( checkURLString( attributeListPtr->dataValue,\n\t\t\t\t\t\t\tattributeListPtr->dataValueLength, URL_DNS ) );\n\t}\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkURL( const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\treturn( checkURLString( attributeListPtr->dataValue,\n\t\t\t\t\t\t\tattributeListPtr->dataValueLength, URL_ANY ) );\n\t}\n\n#ifdef USE_CERT_OBSOLETE\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkHTTP( const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\treturn( checkURLString( attributeListPtr->dataValue,\n\t\t\t\t\t\t\tattributeListPtr->dataValueLength, URL_HTTP ) );\n\t}\n#endif /* USE_CERT_OBSOLETE */\n\n/* Determine whether a DN (either a complete DN or a DN subtree) is valid.\n   Most attribute fields require a full DN but some fields (which act as\n   filters) are allowed a partial DN */\n\nCHECK_RETVAL_ENUM( CRYPT_ERRTYPE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDirectoryName( const ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE dummy;\n\tCRYPT_ERRTYPE_TYPE errorType;\n\tDATAPTR_DN dn = GET_DN_POINTER( attributeListPtr );\n\tint status;\n\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tif( attributeListPtr->fieldID == CRYPT_CERTINFO_EXCLUDEDSUBTREES || \\\n\t\tattributeListPtr->fieldID == CRYPT_CERTINFO_PERMITTEDSUBTREES )\n\t\t{\n\t\tstatus = checkDN( dn, CHECKDN_FLAG_COUNTRY, &dummy, &errorType );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = checkDN( dn, CHECKDN_FLAG_COUNTRY | CHECKDN_FLAG_COMMONNAME,\n\t\t\t\t\t\t  &dummy, &errorType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( errorType );\n\n\treturn( CRYPT_ERRTYPE_NONE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since many of the attributes can be disabled to save space and reduce \n   complexity, we may need to check that an attribute that we want to use is\n   actually available, for example if we're about to create it as part of an\n   internal operation for which we don't want to present an unexpected error\n   status to the caller.  The following function checks whether an attribute\n   is enabled for use */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAttributeAvailable( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE fieldID )\n\t{\n\tREQUIRES_B( isValidExtension( fieldID ) );\n\n\tif( fieldID <= CRYPT_CERTINFO_LAST_EXTENSION )\n\t\t{\n\t\treturn( fieldIDToAttribute( ATTRIBUTE_CERTIFICATE, fieldID, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, NULL ) != NULL ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\treturn( fieldIDToAttribute( ATTRIBUTE_CMS, fieldID, \n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, NULL ) != NULL ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/* Get the encoded tag value for a field */\n\nCHECK_RETVAL_RANGE( MAKE_CTAG_PRIMITIVE( 0 ), MAX_TAG ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getFieldEncodedTag( const ATTRIBUTE_INFO *attributeInfoPtr )\n\t{\n\tint tag;\n\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( attributeInfoPtr->fieldEncodedType == CRYPT_UNUSED || \\\n\t\t\t  ( attributeInfoPtr->fieldEncodedType >= 0 && \\\n\t\t\t\tattributeInfoPtr->fieldEncodedType < MAX_TAG_VALUE ) );\n\n\t/* If it's a non-tagged field, we're done */\n\tif( attributeInfoPtr->fieldEncodedType == CRYPT_UNUSED )\n\t\treturn( OK_SPECIAL );\n\n\t/* It's a tagged field, the actual tag is stored as the encoded-type \n\t   value.  If it's explicitly tagged or an implictly tagged SET/SEQUENCE \n\t   then it's constructed, otherwise it's primitive */\n\tif( ( attributeInfoPtr->fieldType == BER_SEQUENCE ||\n\t\t  attributeInfoPtr->fieldType == BER_SET ||\n\t\t  attributeInfoPtr->fieldType == FIELDTYPE_DN ||\n\t\t  ( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) ) )\n\t\t{\n\t\ttag = MAKE_CTAG( attributeInfoPtr->fieldEncodedType );\n\t\t}\n\telse\n\t\ttag = MAKE_CTAG_PRIMITIVE( attributeInfoPtr->fieldEncodedType );\n\n\tENSURES( ( tag >= MAKE_CTAG_PRIMITIVE( 0 ) ) && \\\n\t\t\t ( tag <= MAX_TAG ) );\n\n\treturn( tag );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Attribute Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* Define the following to print a trace of the certificate fields being \n   parsed, useful for debugging broken certificates */\n\n#if !defined( NDEBUG ) && 0\n  #if defined( _MSC_VER )\n\t/* Temporarily disable the conditional expression is constant warning, \n\t   which occurs because 'stackPos' may be hardcoded to 0 */\n\t#pragma warning( disable: 4127 )\n  #endif /* VC++ */\n  #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos ) \\\n\t\t  { \\\n\t\t  int i; \\\n\t\t  \\\n\t\t  DEBUG_PRINT(( \"%4d:\", stell( stream ) )); \\\n\t\t  for( i = 0; i < stackPos; i++ ) \\\n\t\t\t  DEBUG_PRINT(( \"  \" )); \\\n\t\t  if( ( attributeInfoPtr ) != NULL && \\\n\t\t\t  ( attributeInfoPtr )->description != NULL ) \\\n\t\t\t  { \\\n\t\t\t  DEBUG_PUTS(( ( attributeInfoPtr )->description )); \\\n\t\t\t  } \\\n\t\t  else \\\n\t\t\t  { \\\n\t\t\t  DEBUG_PUTS(( \"<Unknown field>\" )); \\\n\t\t\t  } \\\n\t\t  }\n  #define TRACE_DEBUG( message ) \\\n\t\t  DEBUG_PRINT( message ); \\\n\t\t  DEBUG_PUTS(( \"\" ));\n#else\n  #define TRACE_FIELDTYPE( attributeInfoPtr, stackPos )\n  #define TRACE_DEBUG( message )\n#endif /* NDEBUG */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the tag for a field from the attribute field definition */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getFieldTag( INOUT STREAM *stream, \n\t\t\t\t\t\tIN const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\tOUT int *tag )\n\t{\n\tint status, value;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( tag, sizeof( int ) ) );\n\n\t/* Clear return value.  This is actually a bit difficult to do because \n\t   the output can have both positive values (tags) and negative values \n\t   (field codes), setting the output to -1000 is invalid for both \n\t   types */\n\t*tag = -1000;\n\n\t/* Check whether the field is tagged */\n\tstatus = value = getFieldEncodedTag( attributeInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there's no tagging (i.e. the tag is the same as the field \n\t\t   type) we'll get an OK_SPECIAL return value, this isn't an \n\t\t   error */\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a tagged field, return the encoded form */\n\t\t*tag = value;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( status == OK_SPECIAL );\n\n\t/* It's a non-tagged field, the tag is the same as the field type */\n\tvalue = attributeInfoPtr->fieldType;\n\tif( value == FIELDTYPE_TEXTSTRING )\n\t\t{\n\t\tstatic const int allowedStringTypes[] = {\n\t\t\tBER_STRING_BMP, BER_STRING_IA5, BER_STRING_ISO646, \n\t\t\tBER_STRING_PRINTABLE, BER_STRING_T61, BER_STRING_UTF8,\n\t\t\tCRYPT_ERROR, CRYPT_ERROR \n\t\t\t};\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* This is a variable-tag field that can have one of a number of \n\t\t   tags.  To handle this we peek ahead into the stream to see if an \n\t\t   acceptable tag is present and if not set the value to a non-\n\t\t   matching tag value */\n\t\tstatus = value = peekTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tLOOP_SMALL( i = 0,\n\t\t\t\t\tallowedStringTypes[ i ] != value && \\\n\t\t\t\t\t\tallowedStringTypes[ i ] != CRYPT_ERROR && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( allowedStringTypes, int ),\n\t\t\t\t\ti++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( allowedStringTypes, int ) );\n\t\tif( allowedStringTypes[ i ] == CRYPT_ERROR )\n\t\t\t{\n\t\t\t/* We've reached the end of the list of allowed types without \n\t\t\t   finding a match, change the tag value from what we've read \n\t\t\t   from the stream to make sure that it results in a non-match \n\t\t\t   when the caller uses it */\n\t\t\tvalue = BER_ID_RESERVED;\n\t\t\t}\n\t\t}\n\tif( value == FIELDTYPE_BLOB_BITSTRING || \\\n\t\tvalue == FIELDTYPE_BLOB_SEQUENCE )\n\t\t{\n\t\t/* This is a typed blob that's read as a blob but still has a type\n\t\t   for type-checking purposes */\n\t\tvalue = ( value == FIELDTYPE_BLOB_BITSTRING ) ? \\\n\t\t\t\tBER_BITSTRING : BER_SEQUENCE;\n\t\t}\n\n\tENSURES( ( ( value == FIELDTYPE_BLOB_ANY || value == FIELDTYPE_DN ) && \\\n\t\t\t   !( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) ) || \\\n\t\t\t ( value >= BER_ID_RESERVED && value <= MAX_TAG ) );\n\t\t\t /* A FIELDTYPE_BLOB_ANY or FIELDTYPE_DN can't be optional \n\t\t\t    fields because with no type information for them available \n\t\t\t\tthere's no way to check whether we've encountered them or \n\t\t\t\tnot, has been verified during the startup check.  \n\t\t\t\tBER_ID_RESERVED is used to indicate that an invalid tag was \n\t\t\t\tread so it's valid at this point */\n\t*tag = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an explicit tag that wraps the actual item that we're after */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readExplicitTag( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN const ATTRIBUTE_INFO *attributeInfoPtr, \n\t\t\t\t\t\t\tOUT_TAG_Z int *tag )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( tag, sizeof( int ) ) );\n\n\tREQUIRES( attributeInfoPtr->encodingFlags & FL_EXPLICIT );\n\tREQUIRES( attributeInfoPtr->fieldEncodedType >= 0 && \\\n\t\t\t  attributeInfoPtr->fieldEncodedType < MAX_TAG );\n\n\t/* Clear return value */\n\t*tag = 0;\n\n\t/* Read the explicit wrapper */\n\tstatus = readConstructed( stream, NULL, \n\t\t\t\t\t\t\t  attributeInfoPtr->fieldEncodedType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've processed the explicit wrappper, we're now on the actual tag */\n\t*tag = attributeInfoPtr->fieldType;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the end of an item (either primitive or constructed) in the attribute\n   table.  Sometimes we may have already entered a constructed object (for\n   example when an attribute has a version number so we don't know until we've\n   started processing it that we can't do anything with it), if this is the\n   case then the depth parameter indicates how many nesting levels we have to \n   undo */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findItemEnd( IN const ATTRIBUTE_INFO **attributeInfoPtrPtr,\n\t\t\t\t\t\tIN_RANGE( 0, 2 ) const int depth )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tint currentDepth = depth, LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( depth >= 0 && depth <= 2 );\n\n\t/* Skip to the end of the (potentially) constructed item by recording the\n\t   nesting level and continuing until either it reaches zero or we reach\n\t   the end of the item */\n\tLOOP_MED( attributeInfoPtr = *attributeInfoPtrPtr, \n\t\t\t  !( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ),\n\t\t\t  attributeInfoPtr++ )\n\t\t{\n\t\t/* If it's a SEQUENCE/SET, increment the depth; if it's an end-of-\n\t\t   constructed-item marker, decrement it by the appropriate amount */\n\t\tif( attributeInfoPtr->fieldType == BER_SEQUENCE || \\\n\t\t\tattributeInfoPtr->fieldType == BER_SET )\n\t\t\tcurrentDepth++;\n\t\tcurrentDepth -= decodeNestingLevel( attributeInfoPtr->encodingFlags );\n\t\tif( currentDepth <= 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We return the next-to-last entry by stopping when we find the \n\t   FL_ATTR_ATTREND flag since we're going to move on to the next entry \n\t   once we return */\n\t*attributeInfoPtrPtr = attributeInfoPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSET/SEQUENCE Management Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* When we're processing SETs/SEQUENCEs (generically referred to as a SET\n   OF) we need to maintain a stack of state information to handle a nested \n   SET OF.  The following code implements the state stack, with the zero-th\n   entry being a dummy entry and the first user-set entry being at position\n   1 */\n\n#define SETOF_STATE_STACKSIZE\t16\n\n#define SETOF_FLAG_NONE\t\t\t0x00\t/* No flag value */\n#define SETOF_FLAG_SUBTYPED\t\t0x01\t/* SET ends on a subtyped value */\n#define SETOF_FLAG_RESTARTPOINT\t0x02\t/* SET OF rather than SET */\n#define SETOF_FLAG_ISEMPTY\t\t0x04\t/* Cleared if SET OF contains at least one entry */\n#define SETOF_FLAG_MAX\t\t\t0x07\t/* Maximum possible flag value */\n\ntypedef struct {\n\t/* SET OF state information */\n\tconst ATTRIBUTE_INFO *infoStart;\t/* Start of SET OF attribute information */\n\tint startPos, endPos;\t/* Start and end position of SET OF */\n\tint flags;\t\t\t\t/* SET OF flags */\n\n\t/* Subtype information */\n\tCRYPT_ATTRIBUTE_TYPE subtypeParent;\t/* Parent type if this is subtyped */\n\tint inheritedAttrFlags;\t/* Attribute flags inherited from parent if subtyped */\n\t} SETOF_STATE_INFO;\n\ntypedef struct {\n\tARRAY( SETOF_STATE_STACKSIZE, stackPos ) \\\n\tSETOF_STATE_INFO stateInfo[ SETOF_STATE_STACKSIZE + 8 ];\n\tint stackPos;\t\t\t/* Current position in stack */\n\t} SETOF_STACK;\n\nstatic const SETOF_STATE_INFO stackPos0Data = {\n\tNULL, 0, MAX_INTLENGTH_SHORT, SETOF_FLAG_NONE, \n\tCRYPT_ATTRIBUTE_NONE, SETOF_FLAG_NONE\n\t};\nstatic const SETOF_STATE_INFO stackPosEmptyData = {\n\tNULL, 0, 0, SETOF_FLAG_NONE, \n\tCRYPT_ATTRIBUTE_NONE, SETOF_FLAG_NONE\n\t};\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckSetofStack( IN const SETOF_STACK *setofStack )\n\t{\n\tconst SETOF_STATE_INFO *setofInfoPtr;\n\n\tassert( isReadPtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\t/* Check general stack info */\n\tif( setofStack->stackPos < 0 || \\\n\t\tsetofStack->stackPos >= SETOF_STATE_STACKSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSetofStack: Stack position\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check the special-case zero'th stack position */\n\tsetofInfoPtr = &setofStack->stateInfo[ 0 ];\n\tif( memcmp( setofInfoPtr, &stackPos0Data, sizeof( SETOF_STATE_INFO ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSetofStack: First stack entry\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE ); \n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckSetofStateInfo( IN const SETOF_STATE_INFO *setofInfoPtr )\n\t{\n\tassert( isReadPtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );\n\n\t/* Check for the zero'th entry, which has special properties */\n\tif( setofInfoPtr->startPos == 0 && \\\n\t\tsetofInfoPtr->endPos == MAX_INTLENGTH_SHORT )\n\t\t{\n\t\tif( memcmp( setofInfoPtr, &stackPos0Data, \n\t\t\t\t\tsizeof( SETOF_STATE_INFO ) ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSetofStack: First stack entry\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check for an empty stack entry, which we can encounter when we've \n\t   just pushed an item onto the stack and are setting up the next \n\t   entry */\n\tif( setofInfoPtr->startPos == 0 && setofInfoPtr->endPos == 0 )\n\t\t{\n\t\tif( memcmp( setofInfoPtr, &stackPosEmptyData, \n\t\t\t\t\tsizeof( SETOF_STATE_INFO ) ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSetofStack: Empty stack entry\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check general state info */\n\tif( !isShortIntegerRangeNZ( setofInfoPtr->startPos ) || \\\n\t\t!isShortIntegerRangeNZ( setofInfoPtr->endPos ) || \\\n\t\tsetofInfoPtr->startPos >= setofInfoPtr->endPos || \\\n\t\t!isFlagRangeZ( setofInfoPtr->flags, SETOF ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSetofStateInfo: State information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check subtyping info */\n\tif( setofInfoPtr->subtypeParent == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tif( setofInfoPtr->inheritedAttrFlags != ATTR_FLAG_NONE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSetofStateInfo: Spurious subtype information\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isAttribute( setofInfoPtr->subtypeParent ) || \\\n\t\t\t!isFlagRangeZ( setofInfoPtr->inheritedAttrFlags, ATTR ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSetofStateInfo: Subtype information\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void setofStackInit( OUT SETOF_STACK *setofStack )\n\t{\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\tmemset( setofStack, 0, sizeof( SETOF_STACK ) );\n\n\t/* Set up the dummy entry at position zero.  This has an (effectively) \n\t   infinite length to ensure that the encapsulation check for subsequent \n\t   entries always succeeds */\n\tmemcpy( &setofStack->stateInfo[ 0 ], &stackPos0Data, \n\t\t\tsizeof( SETOF_STATE_INFO ) ); \n\n\tENSURES_V( sanityCheckSetofStack( setofStack ) );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN setofStackPush( INOUT SETOF_STACK *setofStack )\n\t{\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\tREQUIRES_B( sanityCheckSetofStack( setofStack ) );\n\n\t/* Make sure that there's space left on the stack.  The < 0 check has \n\t   already been performed by the sanity check, but we add it to the \n\t   comparison here to make it consistent */\n\tif( setofStack->stackPos < 0 || \\\n\t\tsetofStack->stackPos >= SETOF_STATE_STACKSIZE - 1 )\n\t\treturn( FALSE );\n\n\t/* Increment the stack pointer */\n\tsetofStack->stackPos++;\n\tENSURES_B( setofStack->stackPos >= 1 && \\\n\t\t\t   setofStack->stackPos < SETOF_STATE_STACKSIZE );\n\n\t/* Initialise the new entry */\n\tmemset( &setofStack->stateInfo[ setofStack->stackPos ], 0, \n\t\t\tsizeof( SETOF_STATE_INFO ) );\n\n\tENSURES_B( sanityCheckSetofStack( setofStack ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN setofStackPop( INOUT SETOF_STACK *setofStack )\n\t{\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\tREQUIRES_B( sanityCheckSetofStack( setofStack ) );\n\n\t/* Decrement the stack pointer.  Note that the precondition is explicitly\n\t   checked for since it can occur normally as a result of a corrupted\n\t   certificate while the postcondition can only occur as an internal \n\t   error */\n\tif( setofStack->stackPos <= 0 || \\\n\t\tsetofStack->stackPos >= SETOF_STATE_STACKSIZE )\n\t\treturn( FALSE );\n\tsetofStack->stackPos--;\n\tENSURES_B( setofStack->stackPos >= 0 && \\\n\t\t\t   setofStack->stackPos < SETOF_STATE_STACKSIZE - 1 );\n\n\tENSURES_B( sanityCheckSetofStack( setofStack ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN setofStackIsEmpty( INOUT SETOF_STACK *setofStack )\n\t{\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\tREQUIRES_B( sanityCheckSetofStack( setofStack ) );\n\n\treturn( ( setofStack->stackPos <= 0 ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic SETOF_STATE_INFO *setofTOS( const SETOF_STACK *setofStack )\n\t{\n\tconst SETOF_STATE_INFO *setofInfoPtr;\n\n\tassert( isReadPtr( setofStack, sizeof( SETOF_STACK ) ) );\n\n\tREQUIRES_N( sanityCheckSetofStack( setofStack ) );\n\n\tsetofInfoPtr = &setofStack->stateInfo[ setofStack->stackPos ];\n\tENSURES_N( sanityCheckSetofStateInfo( setofInfoPtr ) );\n\n\treturn( ( SETOF_STATE_INFO * ) setofInfoPtr );\n\t}\n\n/* Set full/emptiness handling: Check whether the current set is empty, and \n   mark the current set as non-empty */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN setIsEmpty( SETOF_STATE_INFO *setofInfoPtr )\n\t{\n\tassert( isWritePtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckSetofStateInfo( setofInfoPtr ) );\n\n\treturn( ( setofInfoPtr->flags & SETOF_FLAG_ISEMPTY ) ? TRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void setSetNonempty( SETOF_STATE_INFO *setofInfoPtr )\n\t{\n\tassert( isWritePtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSetofStateInfo( setofInfoPtr ) );\n\n\tsetofInfoPtr->flags &= ~SETOF_FLAG_ISEMPTY;\n\t}\n\n/* Process the start of a SET/SET OF/SEQUENCE/SEQUENCE OF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int beginSetof( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT SETOF_STACK *setofStack,\n\t\t\t\t\t   IN const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t   IN_LENGTH const int dataEndPos )\n\t{\n\tSETOF_STATE_INFO *setofInfoPtr, *parentSetofInfoPtr;\n\tint setofLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSetofStack( setofStack ) );\n\tREQUIRES( isIntegerRangeNZ( dataEndPos ) );\n\n\t/* Determine the length and start position of the SET OF items.  If the\n\t   tag is an explicit tag then we don't have to process it since it's\n\t   already been handled by the caller */\n\tif( attributeInfoPtr->fieldEncodedType >= 0 && \\\n\t\t!( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) )\n\t\t{\n\t\tstatus = readConstructed( stream, &setofLength,\n\t\t\t\t\t\t\t\t  attributeInfoPtr->fieldEncodedType );\n\t\t}\n\telse\n\t\t{\n\t\tif( attributeInfoPtr->fieldType == BER_SET )\n\t\t\tstatus = readSet( stream, &setofLength );\n\t\telse\n\t\t\tstatus = readSequenceZ( stream, &setofLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Sanity-check the wrapper length information to make sure that it \n\t   makes sense */\n\tif( !isShortIntegerRange( setofLength ) || \\\n\t\tstell( stream ) + setofLength > dataEndPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* When processing a SEQUENCE with default values for the elements the \n\t   result may be a zero-length object, in which case we don't take any \n\t   action.  Other too-short objects are an error */\n\tif( setofLength <= 2 )\n\t\t{\n\t\tif( setofLength == 0 && \\\n\t\t\t( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Remember assorted information such as where the SET/SEQUENCE ends.  \n\t   In addition if this is a SET OF/SEQUENCE OF, remember this as a \n\t   restart point for when we're parsing the next item in the \n\t   SET/SEQUENCE OF */\n\tparentSetofInfoPtr = setofTOS( setofStack );\n\tENSURES( parentSetofInfoPtr != NULL );\n\tif( !setofStackPush( setofStack ) )\n\t\t{\n\t\t/* Stack overflow, there's a problem with the certificate */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tsetofInfoPtr = setofTOS( setofStack );\n\tENSURES( setofInfoPtr != NULL );\n\tsetofInfoPtr->infoStart = attributeInfoPtr;\n\tif( attributeInfoPtr->encodingFlags & FL_SETOF )\n\t\tsetofInfoPtr->flags |= SETOF_FLAG_RESTARTPOINT;\n\tif( !( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) )\n\t\tsetofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;\n\tsetofInfoPtr->subtypeParent = parentSetofInfoPtr->subtypeParent;\n\tsetofInfoPtr->inheritedAttrFlags = parentSetofInfoPtr->inheritedAttrFlags;\n\tsetofInfoPtr->startPos = stell( stream );\n\tsetofInfoPtr->endPos = setofInfoPtr->startPos + setofLength;\n\tENSURES( sanityCheckSetofStateInfo( setofInfoPtr ) );\n\n\t/* Check that the current SET OF is contained within its parent */\n\tif( setofInfoPtr->startPos < parentSetofInfoPtr->startPos || \\\n\t\tsetofInfoPtr->endPos > parentSetofInfoPtr->endPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether we've reached the end of a SET/SEQUENCE.  Returns OK_SPECIAL\n   if the end has been reached */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int checkSetofEnd( const STREAM *stream, \n\t\t\t\t\t\t  INOUT SETOF_STACK *setofStack,\n\t\t\t\t\t\t  const ATTRIBUTE_INFO **attributeInfoPtrPtr )\n\t{\n\tconst ATTRIBUTE_INFO *oldAttributeInfoPtr = *attributeInfoPtrPtr;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr = *attributeInfoPtrPtr;\n\tconst SETOF_STATE_INFO *setofInfoPtr;\n\tconst int currentPos = stell( stream );\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( setofStack, sizeof( SETOF_STACK ) ) );\n\tassert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSetofStack( setofStack ) );\n\t\n\tsetofInfoPtr = setofTOS( setofStack );\n\tENSURES( setofInfoPtr != NULL );\n\tREQUIRES( isShortIntegerRangeNZ( currentPos ) );\n\n\t/* If we're still within the SET/SEQUENCE, we're done */\n\tif( currentPos < setofInfoPtr->endPos )\n\t\treturn( CRYPT_OK );\n\n\t/* If we've read past the end of the SET/SEQUENCE then there's a problem\n\t   with the data.  Usually this will be caught by the encoding-validity\n\t   check, but if it's been disabled due to an oblivious-mode read then\n\t   we can end up catching the problem here */\n\tif( currentPos > setofInfoPtr->endPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* We've reached the end of one or more layers of SET/SEQUENCE, keep \n\t   popping SET/SEQUENCE state information until we can continue */\n\tLOOP_EXT_CHECK( !setofStackIsEmpty( setofStack ) && \\\n\t\t\t\t\tcurrentPos >= setofInfoPtr->endPos, \n\t\t\t\t\tSETOF_STATE_STACKSIZE )\n\t\t{\n\t\tconst int flags = setofInfoPtr->flags;\n\n\t\t/* Pop one level of parse state.  Alongside the standard stack-\n\t\t   underflow check we also check whether the stack is empty after \n\t\t   the pop.  This condition should never occur because for any\n\t\t   (non-primitive) attribute data inside the { OID, OCTET STRING }\n\t\t   wrapper the encapsulation will always be a SEQUENCE (or perhaps \n\t\t   SET):\n\n\t\t\tOID attributeType,\n\t\t\tOCTET STRING encapsulates {\n\t\t\t\tSEQUENCE {\n\t\t\t\t\t... ,\n\t\t\t\t\t... ,\n\t\t\t\t\t...\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t   which means that it can never be popped until the end of the \n\t\t   attribute is reached.  Since we exit before this, emptying the\n\t\t   stack indicates that there's spurious data at the end of the\n\t\t   attribute */\n\t\tif( !setofStackPop( setofStack ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tif( setofStackIsEmpty( setofStack ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tsetofInfoPtr = setofTOS( setofStack );\n\t\tENSURES( setofInfoPtr != NULL );\n\t\tattributeInfoPtr = setofInfoPtr->infoStart;\n\n\t\t/* If it's a pure SET/SEQUENCE (not a SET OF/SEQUENCE OF) and there \n\t\t   are no more elements present, go to the end of the SET/SEQUENCE \n\t\t   information in the decoding table */\n\t\tif( !( flags & SETOF_FLAG_RESTARTPOINT ) && \\\n\t\t\tcurrentPos >= setofInfoPtr->endPos )\n\t\t\t{\n\t\t\tint status;\n\n\t\t\tstatus = findItemEnd( &attributeInfoPtr, 0 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t*attributeInfoPtrPtr = attributeInfoPtr;\n\treturn( ( attributeInfoPtr != oldAttributeInfoPtr ) ? \\\n\t\t\tOK_SPECIAL : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tIdentified Item Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Given a pointer to a set of SEQUENCE { type, value } entries, return a\n   pointer to the { value } entry appropriate for the data in the stream.  \n   If the entry contains user data in the { value } portion then the \n   returned pointer points to this, if it contains a fixed value or isn't \n   present at all then the returned pointer points to the { type } portion */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic const ATTRIBUTE_INFO *findIdentifiedItem( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\tIN const ATTRIBUTE_INFO *attributeInfoPtr )\n\t{\n\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\tint oidLength, sequenceLength, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES_N( attributeInfoPtr->encodingFlags & FL_IDENTIFIER );\n\n\t/* Skip the header and read the OID */\n\treadSequence( stream, &sequenceLength );\n\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\tif( cryptStatusError( status ) )\n\t\treturn( NULL );\n\tsequenceLength -= oidLength;\n\tif( !isShortIntegerRange( sequenceLength ) )\n\t\treturn( NULL );\n\n\t/* Walk down the list of entries trying to match the read OID to an \n\t   allowed value.  Unfortunately we can't use the attributeInfoSize \n\t   bounds check limit here because we don't know how far through the \n\t   attribute table we already are, so we have to use a generic large \n\t   value */\n\tLOOP_LARGE_CHECK( attributeInfoPtr->encodingFlags & FL_IDENTIFIER )\n\t\t{\n\t\tconst BYTE *oidPtr;\n\n\t\t/* Skip the SEQUENCE and OID.  The fact that an OID follows the\n\t\t   entry with the FL_IDENTIFIER field in the encoding table unless \n\t\t   it's the final catch-all blob entry has been verified during the \n\t\t   startup check */\n\t\tattributeInfoPtr++;\n\t\toidPtr = attributeInfoPtr->oid;\n\n\t\t/* If this is a non-encoded blob field then we've hit a don't-care \n\t\t   value (usually the last in a series of type-and-value pairs) \n\t\t   which ensures that { type }s added after the encoding table was \n\t\t   defined don't get processed as errors, skip the field and \n\t\t   continue */\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_BLOB_ANY && \\\n\t\t\t( attributeInfoPtr->encodingFlags & FL_NONENCODING ) )\n\t\t\t{\n\t\t\t/* If there's a { value } attached to the type, skip it */\n\t\t\tif( sequenceLength > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = sSkip( stream, sequenceLength, \n\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( NULL );\n\t\t\t\t}\n\t\t\treturn( attributeInfoPtr );\n\t\t\t}\n\t\tENSURES_N( oidPtr != NULL );\n\n\t\t/* Skip to the payload data unless this is a field like a version \n\t\t   number which isn't used to encode user-supplied information */\n\t\tif( !( attributeInfoPtr->encodingFlags & FL_NONENCODING ) )\n\t\t\tattributeInfoPtr++;\n\n\t\t/* If the OID matches, return a pointer to the value entry */\n\t\tif( oidLength == sizeofOID( oidPtr ) && \\\n\t\t\t!memcmp( oidPtr, oid, sizeofOID( oidPtr ) ) )\n\t\t\t{\n\t\t\t/* If this is a fixed field and there's a value attached, skip\n\t\t\t   it */\n\t\t\tif( ( attributeInfoPtr->encodingFlags & FL_NONENCODING ) && \\\n\t\t\t\tsequenceLength > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = sSkip( stream, sequenceLength, \n\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( NULL );\n\t\t\t\t}\n\n\t\t\treturn( attributeInfoPtr );\n\t\t\t}\n\n\t\t/* The OID doesn't match, skip the { value } entry and continue.  We \n\t\t   set the current nesting depth parameter to 1 since we've already\n\t\t   entered the SEQUENCE above */\n\t\tstatus = findItemEnd( &attributeInfoPtr, 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( NULL );\n\t\tattributeInfoPtr++;\t\t/* Move to start of next item */\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\t/* We've reached the end of the set of entries without matching the OID \n\t   (including a possible catch-all value at the end), this is an error */\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5, 6, 7 ) ) \\\nstatic int processIdentifiedItem( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\t\t\t\t  IN_FLAGS( ATTR ) const int flags, \n\t\t\t\t\t\t\t\t  IN const SETOF_STACK *setofStack,\n\t\t\t\t\t\t\t\t  IN const ATTRIBUTE_INFO **attributeInfoPtrPtr,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst SETOF_STATE_INFO *setofInfoPtr;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtr( setofStack, sizeof( SETOF_STACK ) ) );\n\tassert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\nassert( ( flags & ~( ATTR_FLAG_CRITICAL ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\tsetofInfoPtr = setofTOS( setofStack );\n\tENSURES( setofInfoPtr != NULL );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Search for the identified item from the start of the set of items.  \n\t   The 0-th value is the SET OF/SEQUENCE OF so we start the search at \n\t   the next entry, which is the first FL_IDENTIFIER */\n\tENSURES( setofInfoPtr->infoStart->encodingFlags & FL_SETOF );\n\tattributeInfoPtr = findIdentifiedItem( stream, \n\t\t\t\t\t\t\t\t\t\t   setofInfoPtr->infoStart + 1 );\n\tif( attributeInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*attributeInfoPtrPtr = attributeInfoPtr;\n\n\t/* If it's a subtyped field, tell the caller to restart the decoding\n\t   using the new attribute information.  This is typically used where\n\t   the { type, value } combinations that we're processing are\n\t   { OID, GeneralName }, so the process consists of locating the entry \n\t   that corresponds to the OID and then continuing the decoding with\n\t   the the subtyped attribute information entry that points to the\n\t   GeneralName decoding table */\n\tif( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )\n\t\treturn( OK_SPECIAL );\n\n\t/* If it's not a special-case, non-encoding field, we're done */\n\tif( !( attributeInfoPtr->encodingFlags & FL_NONENCODING ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If the { type, value } pair has a fixed value then the information \n\t   being conveyed is its presence, not its contents, so we add an \n\t   attribute corresponding to its ID and continue.  The addition of the \n\t   attribute is a bit tricky, some of the fixed type-and-value pairs can \n\t   have multiple entries denoting things like { algorithm, weak key }, \n\t   { algorithm, average key }, { algorithm, strong key }, however all \n\t   that we're interested in is the strong key so we ignore the value and \n\t   only use the type (in his ordo est ordinem non servare).  Since the \n\t   same type can be present multiple times (with different { value }s) \n\t   we ignore data duplicate errors and continue.  If we're processing a \n\t   blob field type then we've ended up at a generic catch-any value and \n\t   can't do much with it */\n\tif( attributeInfoPtr->fieldType != FIELDTYPE_BLOB_ANY )\n\t\t{\n\t\tint status;\n\n\t\t/* Add the field type, discarding warnings about duplicates */\n\t\tTRACE_FIELDTYPE( attributeInfoPtr, 0 );\n\t\tstatus = addAttributeField( attributePtrPtr, attributeInfoPtr->fieldID, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tflags, errorLocus, errorType );\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_INITED )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Reset the attribute information position in preparation for \n\t   processing the next value and tell the caller to continue using the \n\t   reset attribute information */\n\t*attributeInfoPtrPtr = setofInfoPtr->infoStart + 1;\n\treturn( OK_SPECIAL );\n\t}\n\n/* Read a sequence of identifier fields of the form { oid, value OPTIONAL }.\n   This is used to read both SEQUENCE OF (via FIELDTYPE_IDENTIFIER) and \n   CHOICE (via FIELDTYPE_CHOICE), with SEQUENCE OF allowing multiple entries \n   and CHOICE allowing only a single entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \\\nstatic int readIdentifierFields( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\t\t\t\t IN const ATTRIBUTE_INFO **attributeInfoPtrPtr, \n\t\t\t\t\t\t\t\t IN_FLAGS( ATTR ) const int flags,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE_OPT const CRYPT_ATTRIBUTE_TYPE fieldID, \n\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tconst BOOLEAN isChoice = ( fieldID != CRYPT_ATTRIBUTE_NONE ) ? \\\n\t\t\t\t\t\t\t TRUE : FALSE;\n\tint count = 0, tag, noIdentifierFields;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isReadPtr( *attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\nassert( ( flags == ATTR_FLAG_NONE ) || ( flags == ATTR_FLAG_CRITICAL ) );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\tREQUIRES( ( fieldID == CRYPT_ATTRIBUTE_NONE ) || \\\n\t\t\t  isValidExtension( fieldID ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\tLOOP_MED( noIdentifierFields = 0,\n\t\t\t  checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\t\ttag == BER_OBJECT_IDENTIFIER && noIdentifierFields < 32,\n\t\t\t  noIdentifierFields++ )\n\t\t{\n\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\t\tBOOLEAN addField = TRUE;\n\t\tint oidLength, LOOP_ITERATOR_ALT;\n\n\t\t/* The fact that the FIELDTYPE_IDENTIFIER field is present and \n\t\t   associated with an OID in the encoding table has been verified \n\t\t   during the startup check */\n\t\tattributeInfoPtr = *attributeInfoPtrPtr;\n\t\tENSURES( attributeInfoPtr != NULL && \\\n\t\t\t\t attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER && \\\n\t\t\t\t attributeInfoPtr->oid != NULL );\n\n\t\t/* Read the OID and walk down the list of possible OIDs up to the end\n\t\t   of the group of alternatives trying to match it to an allowed\n\t\t   value */\n\t\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tLOOP_MED_CHECK_ALT( oidLength != sizeofOID( attributeInfoPtr->oid ) || \\\n\t\t\t\t\t\t\tmemcmp( attributeInfoPtr->oid, oid, oidLength ) )\n\t\t\t{\n\t\t\t/* If we've reached the end of the list and the OID wasn't\n\t\t\t   matched, exit */\n\t\t\tif( ( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) || \\\n\t\t\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t\tattributeInfoPtr++;\n\n\t\t\t/* If this is a blob field then we've hit a don't-care value \n\t\t\t   which ensures that { type }s added after the encoding table \n\t\t\t   was defined don't get processed as errors, skip the field and \n\t\t\t   continue */\n\t\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_BLOB_ANY )\n\t\t\t\t{\n\t\t\t\taddField = FALSE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* The fact that the FIELDTYPE_IDENTIFIER field is present and \n\t\t\t   associated with an OID in the encoding table has been verified \n\t\t\t   during the startup check */\n\t\t\tENSURES( attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER && \\\n\t\t\t\t\t attributeInfoPtr->oid != NULL );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tTRACE_FIELDTYPE( attributeInfoPtr, 0 );\n\t\tif( addField == TRUE )\n\t\t\t{\n\t\t\t/* The OID matches, add this field as an identifier field.  This\n\t\t\t   will catch duplicate OIDs since we can't add the same \n\t\t\t   identifier field twice */\n\t\t\tif( isChoice == TRUE )\n\t\t\t\t{\n\t\t\t\t/* If there's a field value present then this is a CHOICE of\n\t\t\t\t   attributes whose value is the field value so we add it with\n\t\t\t\t   this value */\n\t\t\t\tstatus = addAttributeField( attributePtrPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->fieldID,  \n\t\t\t\t\t\t\t\t\t\t\tflags, errorLocus, errorType );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* It's a standard field */\n\t\t\t\tstatus = addAttributeField( attributePtrPtr, \n\t\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->fieldID, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED, flags, \n\t\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tcount++;\n\n\t\t/* If there's more than one OID present in a CHOICE, it's an error */\n\t\tif( isChoice == TRUE && count > 1 )\n\t\t\t{\n\t\t\t*errorLocus = attributeInfoPtr->fieldID,\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noIdentifierFields >= 32 )\n\t\t{\n\t\t/* If we've found this many identifier fields then there's something \n\t\t   wrong */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* If we haven't seen any fields, this is an error */\n\tif( count <= 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* We've processed the non-data field(s), move on to the next field.\n\t   We move to the last valid non-data field rather than the start of the\n\t   field following it since the caller needs to be able to check whether\n\t   there are more fields to follow using the current field's flags.\n\t   Unfortunately we can't use the attributeInfoSize bounds check limit \n\t   here because we don't know how far through the attribute table we \n\t   already are, so we have to use a generic value */\n\tLOOP_MED( attributeInfoPtr = *attributeInfoPtrPtr, \n\t\t\t  !( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) && \\\n\t\t\t\t\t!( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ),\n\t\t\t  attributeInfoPtr++ );\n\tENSURES( LOOP_BOUND_OK );\n\t*attributeInfoPtrPtr = attributeInfoPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute/Attribute Field Read Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generic error-handler that sets extended error codes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int fieldErrorReturn( OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType, \n\t\t\t\t\t\t\t IN const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t IN_ERROR const int status )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE fieldID = attributeInfoPtr->fieldID;\n\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* For some attributes the field ID is in the following entry, so we \n\t   skip to this if required */\n\tif( fieldID == FIELDID_FOLLOWS )\n\t\t{\n\t\tfieldID = attributeInfoPtr[ 1 ].fieldID;\n\n\t\t/* Verified during the startup check */\n\t\tENSURES( fieldID > CRYPT_CERTINFO_FIRST && \\\n\t\t\t\t fieldID < CRYPT_CERTINFO_LAST );\n\t\t}\n\telse\n\t\t{\n\t\t/* Since some fields are internal-use only (e.g. meaningless blob \n\t\t   data, version numbers, and other paraphernalia) we only set the \n\t\t   locus if it has a meaningful value */\n\t\tif( fieldID <= CRYPT_CERTINFO_FIRST || \\\n\t\t\tfieldID >= CRYPT_CERTINFO_LAST )\n\t\t\tfieldID = CRYPT_ATTRIBUTE_NONE;\n\t\t}\n\t*errorLocus = fieldID;\n\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\n\treturn( status );\n\t}\n\n/* Switch from the main encoding table to a subtype encoding table */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic ATTRIBUTE_INFO *switchToSubtype( IN const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t\tINOUT SETOF_STATE_INFO *setofInfoPtr )\n\t{\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isReadPtr( attributeInfoPtr->extraData, \n\t\t\t\t\t   sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( setofInfoPtr, sizeof( SETOF_STATE_INFO ) ) );\n\n\t/* This has already been verified during the startup check */\n\tREQUIRES_N( attributeInfoPtr != NULL && \\\n\t\t\t\tattributeInfoPtr->extraData != NULL );\n\n\t/* Record the subtype parent information */\n\tsetofInfoPtr->subtypeParent = attributeInfoPtr->fieldID;\n\tsetofInfoPtr->inheritedAttrFlags = \\\n\t\t\t\t\t( attributeInfoPtr->encodingFlags & FL_MULTIVALUED ) ? \\\n\t\t\t\t\t  ATTR_FLAG_MULTIVALUED : ATTR_FLAG_NONE;\n\n\t/* If the subtype is being used to process a list of { ... OPTIONAL, \n\t   ... OPTIONAL } and at least one entry must be present, remember \n\t   that we haven't seen any entries yet */\n\tif( !( attributeInfoPtr->encodingFlags & FL_EMPTYOK ) )\n\t\tsetofInfoPtr->flags |= SETOF_FLAG_ISEMPTY;\n\n\t/* If the subtype ends once the current SET/SEQUENCE ends, remember this \n\t   so that we return to the main type when appropriate */\n\tif( ( attributeInfoPtr->encodingFlags & FL_SEQEND_MASK ) || \\\n\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) )\n\t\tsetofInfoPtr->flags |= SETOF_FLAG_SUBTYPED;\n\n\t/* Switch to the subtype encoding table */\n\treturn( ( ATTRIBUTE_INFO * ) attributeInfoPtr->extraData );\n\t}\n\n/* Read the contents of an attribute field.  This uses the readXXXData() \n   variants of the read functions because the field that we're reading may \n   be tagged so we process the tag at a higher level and only read the \n   contents here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \\\nstatic int readAttributeField( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\t\t\t   IN const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE_OPT \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE subtypeParent, \n\t\t\t\t\t\t\t   IN_FLAGS( ATTR ) const int flags, \n\t\t\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE fieldID, subFieldID;\n\tconst int fieldType = attributeInfoPtr->fieldType;\n\tint length, status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( ( subtypeParent == CRYPT_ATTRIBUTE_NONE ) || \\\n\t\t\t  ( subtypeParent > CRYPT_CERTINFO_FIRST && \\\n\t\t\t\tsubtypeParent < CRYPT_CERTINFO_LAST ) );\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_CRITICAL | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Set up the field identifiers depending on whether it's a normal field\n\t   or a subfield of a parent field */\n\tif( subtypeParent == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tfieldID = attributeInfoPtr->fieldID;\n\t\tsubFieldID = CRYPT_ATTRIBUTE_NONE;\n\t\t}\n\telse\n\t\t{\n\t\tfieldID = subtypeParent;\n\t\tsubFieldID = attributeInfoPtr->fieldID;\n\t\t}\n\n\t/* Read the field as appropriate */\n\tswitch( fieldType )\n\t\t{\n\t\tcase BER_INTEGER:\n\t\tcase BER_ENUMERATED:\n\t\tcase BER_BITSTRING:\n\t\tcase BER_BOOLEAN:\n\t\tcase BER_NULL:\n\t\t\t{\n\t\t\tint value DUMMY_INIT;\n\n\t\t\t/* Read the data as appropriate */\n\t\t\tswitch( fieldType )\n\t\t\t\t{\n\t\t\t\tcase BER_BITSTRING:\n\t\t\t\t\tstatus = readBitStringData( stream, &value );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BER_BOOLEAN:\n\t\t\t\t\t{\n\t\t\t\t\tBOOLEAN boolean;\n\n\t\t\t\t\tstatus = readBooleanData( stream, &boolean );\n\t\t\t\t\tvalue = boolean ? 1 : 0;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\tcase BER_ENUMERATED:\n\t\t\t\t\tstatus = readEnumeratedData( stream, &value );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase BER_INTEGER:\n\t\t\t\t\t{\n\t\t\t\t\tlong longValue;\n\n\t\t\t\t\tstatus = readShortIntegerData( stream, &longValue );\n\t\t\t\t\tif( cryptStatusOK( status ) && !isIntegerRange( longValue ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tvalue = ( int ) longValue;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\tcase BER_NULL:\n\t\t\t\t\t/* NULL values have no associated data so we explicitly \n\t\t\t\t\t   set the value to CRYPT_UNUSED to ensure that this is \n\t\t\t\t\t   returned on any attempt to read the attribute data */\n\t\t\t\t\tvalue = CRYPT_UNUSED;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\n\t\t\t/* Add the data for this attribute field */\n\t\t\treturn( addAttributeField( attributePtrPtr, fieldID, subFieldID, \n\t\t\t\t\t\t\t\t\t   value, flags, errorLocus, errorType ) );\n\t\t\t}\n\n\t\tcase BER_TIME_GENERALIZED:\n\t\tcase BER_TIME_UTC:\n\t\t\t{\n\t\t\ttime_t timeVal;\n\n\t\t\tif( fieldType == BER_TIME_GENERALIZED )\n\t\t\t\tstatus = readGeneralizedTimeData( stream, &timeVal );\n\t\t\telse\n\t\t\t\tstatus = readUTCTimeData( stream, &timeVal );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\n\t\t\t/* Add the data for this attribute field */\n\t\t\treturn( addAttributeFieldString( attributePtrPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t subFieldID, &timeVal, \n\t\t\t\t\t\t\t\t\t\t\t sizeof( time_t ), flags, \n\t\t\t\t\t\t\t\t\t\t\t errorLocus, errorType ) );\n\t\t\t}\n\n\t\tcase BER_STRING_BMP:\n\t\tcase BER_STRING_IA5:\n\t\tcase BER_STRING_ISO646:\n\t\tcase BER_STRING_NUMERIC:\n\t\tcase BER_STRING_PRINTABLE:\n\t\tcase BER_STRING_T61:\n\t\tcase BER_STRING_UTF8:\n\t\tcase BER_OCTETSTRING:\n\t\tcase FIELDTYPE_BLOB_ANY:\n\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\tcase FIELDTYPE_TEXTSTRING:\n\t\t\t{\n\t\t\t/* If it's a string type or a blob read it in as a blob (the \n\t\t\t   only difference being that for a true blob we read the tag + \n\t\t\t   length as well) */\n\t\t\tBYTE buffer[ 256 + 8 ];\n\n\t\t\t/* Read in the string to a maximum length of 256 bytes */\n\t\t\tif( isBlobField( fieldType ) )\n\t\t\t\t{\n\t\t\t\tint tag;\n\t\t\t\t\n\t\t\t\t/* Reading in blob fields is somewhat difficult since these\n\t\t\t\t   are typically used to read SET/SEQUENCE OF kitchen-sink\n\t\t\t\t   values and so won't have a consistent tag that we can pass\n\t\t\t\t   to readRawObject().  To get around this we peek ahead into\n\t\t\t\t   the stream to get the tag and then pass that down to \n\t\t\t\t   readRawObject().  Note that this requires that the blob \n\t\t\t\t   have an internal structure (with its own { tag, length }\n\t\t\t\t   data) since the caller has already stripped off the \n\t\t\t\t   encapsulating tag and length */\n\t\t\t\tstatus = tag = peekTag( stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t\t}\n\t\t\t\tstatus = readRawObject( stream, buffer, 256, &length, tag );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = readOctetStringData( stream, buffer, &length, \\\n\t\t\t\t\t\t\t\t\t\t\t  1, 256 );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\n\t\t\t/* There are enough broken certificates out there with \n\t\t\t   enormously long disclaimers in the certificate policy \n\t\t\t   explicit text field that we have to specifically check for \n\t\t\t   them here and truncate the text at a valid length in order to \n\t\t\t   get it past the attribute validity checking code */\n\t\t\tif( fieldID == CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT && \\\n\t\t\t\tlength > 200 )\n\t\t\t\tlength = 200;\n\n\t\t\t/* Add the data for this attribute field, setting the payload-\n\t\t\t   blob flag to disable type-checking of the payload data so \n\t\t\t   that users can cram any old rubbish into the strings */\n\t\t\treturn( addAttributeFieldString( attributePtrPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t subFieldID, buffer, length, \n\t\t\t\t\t\t\t\t\t\t\t flags | ATTR_FLAG_BLOB_PAYLOAD,\n\t\t\t\t\t\t\t\t\t\t\t errorLocus, errorType ) );\n\t\t\t}\n\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\t{\n\t\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\n\t\t\t/* If it's an OID then we need to reassemble the entire OID \n\t\t\t   since this is the form expected by addAttributeFieldString() */\n\t\t\toid[ 0 ] = BER_OBJECT_IDENTIFIER;\t/* Add skipped tag */\n\t\t\tstatus = readEncodedOID( stream, oid + 1, MAX_OID_SIZE - 1, \n\t\t\t\t\t\t\t\t\t &length, NO_TAG );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\t\t\treturn( addAttributeFieldString( attributePtrPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t subFieldID, oid, length + 1, \n\t\t\t\t\t\t\t\t\t\t\t flags, errorLocus, errorType ) );\n\t\t\t}\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t{\n\t\t\tDATAPTR_DN dn;\n\n\t\t\t/* Read the DN */\n\t\t\tstatus = readDN( stream, &dn );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\n\t\t\t/* Some buggy certificates can include zero-length DNs, which we \n\t\t\t   skip */\n\t\t\tif( DATAPTR_ISNULL( dn ) )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* We're being asked to instantiate the field containing the DN,\n\t\t\t   create the attribute field and fill in the DN value.  Since \n\t\t\t   the value that we're passing in is actually a DN_PTR rather \n\t\t\t   than a standard string value we set the size field to the \n\t\t\t   pseudo-length of a DN_PTR_STORAGE value to keep the static/\n\t\t\t   runtime code checks happy */\n\t\t\tstatus = addAttributeFieldString( attributePtrPtr, fieldID, \n\t\t\t\t\t\t\t\t\t\t\t  subFieldID, &dn, \n\t\t\t\t\t\t\t\t\t\t\t  sizeof( DATAPTR_DN ), flags, \n\t\t\t\t\t\t\t\t\t\t\t  errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tdeleteDN( &dn );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Read an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6, 7 ) ) \\\nstatic int readAttribute( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\t\t  IN const ATTRIBUTE_INFO *attributeInfoPtr, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int attributeLength, \n\t\t\t\t\t\t  const BOOLEAN criticalFlag, \n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t  OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tSETOF_STACK setofStack;\n\tSETOF_STATE_INFO *setofInfoPtr;\n\tconst int endPos = stell( stream ) + attributeLength;\n#ifdef USE_RPKI\n\tCRYPT_ATTRIBUTE_TYPE fieldID = attributeInfoPtr->fieldID;\n\tint maxAttributeFields;\n#else\n\tconst int maxAttributeFields = min( 5 + ( attributeLength / 3 ), 256 );\n#endif /* USE_RPKI */\n\tBOOLEAN attributeContinues = TRUE;\n\tint flags = criticalFlag ? ATTR_FLAG_CRITICAL : ATTR_FLAG_NONE;\n\tint attributeFieldsProcessed, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\t\n\tREQUIRES( isShortIntegerRange( attributeLength ) );\n\tREQUIRES( criticalFlag == TRUE || criticalFlag == FALSE );\n\tREQUIRES( isIntegerRangeNZ( endPos ) );\n\n\t/* Clear return values */\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Set an upper limit for how many attribute fields we should be seeing \n\t   before we report a problem.  We have to apply special-case handling\n\t   for a few problem attributes that get used as general-purpose list\n\t   fields with arbitrary numbers of entries that exceed normal sanity-\n\t   check limits.\n\n\t   altNames used by CDNs to contain one of every site the CDN supports \n\t   or one of every domain the parent company owns may also get very\n\t   large.  This causes additional problems with the failsafe loop bound \n\t   because the altName contains large numbers of non-present fields so \n\t   attributeFieldsProcessed is never incremented even though we go \n\t   through the loop, resulting in large numbers of passes through the \n\t   loop until the failsafe check is triggered.  Google at one point had \n\t   certificates that required the limit to be raised from min( ..., 256 ) \n\t   to min( ..., 512 ) and the use of LOOP_MAX(), but these certificates \n\t   have now expired and been redone in a more sane manner */\n#ifdef USE_RPKI\n\tif( fieldID == FIELDID_FOLLOWS )\n\t\tfieldID = attributeInfoPtr[ 1 ].fieldID; \n\tif( fieldID == CRYPT_CERTINFO_AUTONOMOUSSYSIDS || \\\n\t\tfieldID == CRYPT_CERTINFO_IPADDRESSBLOCKS )\n\t\t{\n\t\t/* CRYPT_CERTINFO_IPADDRESSBLOCKS and \n\t\t   CRYPT_CERTINFO_AUTONOMOUSSYSIDS are an end-run around the \n\t\t   nonexistence of attribute certificates that turn standard \n\t\t   certificates into arbitrary-length capability lists, with each\n\t\t   entry being as small as three bytes.  To deal with this we have\n\t\t   to apply a special scaling factor to the upper-bound check */\n\t\tmaxAttributeFields = 5 + ( attributeLength / 3 );\n\t\t}\n#endif /* USE_RPKI */\n\n\t/* Initialise the SET OF state stack */\n\tsetofStackInit( &setofStack );\n\tsetofInfoPtr = setofTOS( &setofStack );\n\tENSURES( setofInfoPtr != NULL );\n\n\t/* Process each field in the attribute.  This is a simple (well, \n\t   conceptually simple but practically complex since it has to deal with \n\t   the product of PKI standards committees) FSM driven by the encoding \n\t   table and the data that we encounter.  The various states and \n\t   associated actions are indicated by the comment tags */\n\tLOOP_LARGE( attributeFieldsProcessed = 0,\n\t\t\t\t( attributeContinues || !setofStackIsEmpty( &setofStack ) ) && \\\n\t\t\t\t\tstell( stream ) < endPos && \\\n\t\t\t\t\tattributeFieldsProcessed < maxAttributeFields,\n\t\t\t\tattributeFieldsProcessed++ )\n\t\t{\n\t\tint tag, peekedTag, value;\n\n\t\t/* Inside a SET/SET OF/SEQUENCE/SEQUENCE OF: Check for the end of the\n\t\t   item/collection of items.  This must be the first action taken\n\t\t   since reaching the end of a SET/SEQUENCE pre-empts all other\n\t\t   parsing actions */\n\t\tif( !setofStackIsEmpty( &setofStack ) )\n\t\t\t{\n\t\t\t/* If we've reached the end of the collection of items, exit */\n\t\t\tstatus = checkSetofEnd( stream, &setofStack, &attributeInfoPtr );\n\t\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\tsetofInfoPtr = setofTOS( &setofStack );\n\t\t\tENSURES( setofInfoPtr != NULL );\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\tgoto continueDecoding;\n\n\t\t\t/* If we're looking for a new item, find the table entry that it\n\t\t\t   corresponds to.  This takes a pointer to the start of a set of\n\t\t\t   SEQUENCE { type, value } entries and returns a pointer to the\n\t\t\t   appropriate value entry.\n\n\t\t\t   The test for the start of a new item is a bit complex since we\n\t\t\t   could be at the end of the previous item (i.e. on the next item\n\t\t\t   flagged as an identifier) or at the end of the attribute (i.e.\n\t\t\t   on the start of the next attribute) */\n\t\t\tif( ( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTRSTART ) || \\\n\t\t\t\t( attributeInfoPtr->encodingFlags & FL_IDENTIFIER ) )\n\t\t\t\t{\n\t\t\t\tstatus = processIdentifiedItem( stream, attributePtrPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tflags, &setofStack, \n\t\t\t\t\t\t\t\t\t\t\t\t&attributeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/* We've switched to a new encoding table, continue\n\t\t\t\t\t\t   from there */\n\t\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Subtyped field: Switch to the new encoding table */\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_SUBTYPED )\n\t\t\t{\n\t\t\tattributeInfoPtr = switchToSubtype( attributeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tsetofInfoPtr );\n\t\t\tENSURES( attributeInfoPtr != NULL );\n\t\t\t}\n\n\t\t/* CHOICE (of object identifiers): Read a single OID from a\n\t\t   selection defined in a subtable.\n\t\t   Identifier field: Read a sequence of one or more { oid, value }\n\t\t   fields and continue */\n\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE || \\\n\t\t\tattributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER )\n\t\t\t{\n\t\t\tif( attributeInfoPtr->fieldType == FIELDTYPE_CHOICE )\n\t\t\t\t{\n\t\t\t\tconst ATTRIBUTE_INFO *extraDataPtr = \\\n\t\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->extraData;\n\t\t\t\t\t\t/* Needed because ->extraData is read-only */\n\n\t\t\t\t/* This has already been verified during the startup check */\n\t\t\t\tENSURES( extraDataPtr != NULL );\n\t\t\t\t\n\t\t\t\tstatus = readIdentifierFields( stream, attributePtrPtr,\n\t\t\t\t\t\t\t&extraDataPtr, flags, attributeInfoPtr->fieldID,\n\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = readIdentifierFields( stream, attributePtrPtr,\n\t\t\t\t\t\t\t&attributeInfoPtr, flags, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType,\n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\tif( !setofStackIsEmpty( &setofStack ) )\n\t\t\t\tsetSetNonempty( setofInfoPtr );\t/* We've seen a set entry */\n\t\t\tgoto continueDecoding;\n\t\t\t}\n\n\t\t/* Non-encoding field: Skip it and continue */\n\t\tif( attributeInfoPtr->encodingFlags & FL_NONENCODING )\n\t\t\t{\n\t\t\t/* Read the data and continue.  We don't check its value or set\n\t\t\t   specific error information for the reasons given under the SET \n\t\t\t   OF handling code above (value check) and optional field code \n\t\t\t   below (error locus set) */\n\t\t\tTRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );\n\t\t\tstatus = readUniversal( stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( !setofStackIsEmpty( &setofStack ) )\n\t\t\t\tsetSetNonempty( setofInfoPtr );\t/* We've seen a set entry */\n\t\t\tgoto continueDecoding;\n\t\t\t}\n\n\t\t/* Get the tag for the field */\n\t\tstatus = getFieldTag( stream, attributeInfoPtr, &tag );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Optional field: Check whether it's present and if it isn't, move\n\t\t   on to the next field */\n\t\tif( ( attributeInfoPtr->encodingFlags & FL_OPTIONAL ) && \\\n\t\t\tcheckStatusPeekTag( stream, status, peekedTag ) && \\\n\t\t\tpeekedTag != tag )\n\t\t\t{\n\t\t\t/* If it's a field with a default value, add that value.  This\n\t\t\t   isn't needed for cryptlib's own use since it knows the default\n\t\t\t   values for fields but can cause confusion for the caller if \n\t\t\t   all fields in an attribute have default values because the\n\t\t\t   attribute will appear to disappear when it's read in as no\n\t\t\t   fields are ever added */\n\t\t\tif( attributeInfoPtr->encodingFlags & FL_DEFAULT )\n\t\t\t\t{\n\t\t\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\t\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\n\t\t\t\tstatus = addAttributeField( attributePtrPtr,\n\t\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->fieldID, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->defaultValue, \n\t\t\t\t\t\t\t\t\t\t\tflags, &dummy1, &dummy2 );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* This is a field contributed from internal data so we\n\t\t\t\t\t   don't get an error locus or value for it since this \n\t\t\t\t\t   would only confuse the caller */\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* Skip to the end of the item and continue */\n\t\t\tstatus = findItemEnd( &attributeInfoPtr, 0 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t\n\t\t\t/* Since this was a (non-present) optional attribute it \n\t\t\t   shouldn't be counted in the total when we continue decoding,\n\t\t\t   so we adjust the fields-processed value to account for this */\n\t\t\tif( attributeFieldsProcessed > 0 )\n\t\t\t\tattributeFieldsProcessed--;\n\n\t\t\tgoto continueDecoding;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t\t/* Print a trace of what we're processing.  Everything before this\n\t\t   point does its own special-case tracing if required so we don't\n\t\t   trace before we get here to avoid displaying duplicate/\n\t\t   misleading information */\n\t\tTRACE_FIELDTYPE( attributeInfoPtr, setofStack.stackPos );\n\n\t\t/* Explicitly tagged field: Read the explicit wrapper and make sure\n\t\t   that it matches what we're expecting (the read is done here, the\n\t\t   match is done further down) */\n\t\tif( attributeInfoPtr->encodingFlags & FL_EXPLICIT )\n\t\t\t{\n\t\t\tREQUIRES( tag == MAKE_CTAG( attributeInfoPtr->fieldEncodedType ) );\n\t\t\t\t\t  /* Always constructed */\n\n\t\t\tstatus = readExplicitTag( stream, attributeInfoPtr, &tag );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Blob field or DN: We don't try and interpret blobs in any way, \n\t\t   and DNs are a composite structure read as a complete unit by the \n\t\t   lower-level code */\n\t\tif( isBlobField( attributeInfoPtr->fieldType ) || \\\n\t\t\tattributeInfoPtr->fieldType == FIELDTYPE_DN )\n\t\t\t{\n\t\t\tstatus = readAttributeField( stream, attributePtrPtr,\n\t\t\t\t\t\t\t\t\t\t attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t setofInfoPtr->subtypeParent,\n\t\t\t\t\t\t\t\t\t\t flags | setofInfoPtr->inheritedAttrFlags,\n\t\t\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Adding complex attributes such as DNs can return detailed\n\t\t\t\t   error codes that report the exact parameter that was wrong,\n\t\t\t\t   we don't need this much detail so we convert a parameter\n\t\t\t\t   error into a more general bad data status */\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType,\n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  cryptArgError( status ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ERROR_BADDATA : status ) );\n\t\t\t\t}\n\t\t\tif( !setofStackIsEmpty( &setofStack ) )\n\t\t\t\tsetSetNonempty( setofInfoPtr );\t/* We've seen a set entry */\n\t\t\tgoto continueDecoding;\n\t\t\t}\n\n\t\t/* Standard field: Read the tag for the field and make sure that it\n\t\t   matches what we're expecting */\n\t\tstatus = value = peekTag( stream );\n\t\tif( cryptStatusError( status ) || value != tag )\n\t\t\t{\n\t\t\treturn( fieldErrorReturn( errorLocus, errorType,\n\t\t\t\t\t\t\t\t\t  attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\tif( !setofStackIsEmpty( &setofStack ) )\n\t\t\tsetSetNonempty( setofInfoPtr );\t\t/* We've seen a set entry */\n\n\t\t/* SET/SET OF/SEQUENCE/SEQUENCE OF start: Record its end position,\n\t\t   stack the current processing state, and continue */\n\t\tif( attributeInfoPtr->fieldType == BER_SEQUENCE || \\\n\t\t\tattributeInfoPtr->fieldType == BER_SET )\n\t\t\t{\n\t\t\tstatus = beginSetof( stream, &setofStack, attributeInfoPtr,\n\t\t\t\t\t\t\t\t endPos );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( fieldErrorReturn( errorLocus, errorType, \n\t\t\t\t\t\t\t\t\t\t  attributeInfoPtr, status ) );\n\t\t\t\t}\n\t\t\tsetofInfoPtr = setofTOS( &setofStack );\n\t\t\tENSURES( setofInfoPtr != NULL );\n\t\t\tgoto continueDecoding;\n\t\t\t}\n\t\tENSURES( !( attributeInfoPtr->encodingFlags & FL_SETOF ) );\n\n\t\t/* We've checked the tag, skip it.  We do this at this level rather\n\t\t   than in readAttributeField() because it doesn't know about \n\t\t   context-specific tagging requirements */\n\t\tstatus = readTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Standard field, read the field data */\n\t\tstatus = readAttributeField( stream, attributePtrPtr,\n\t\t\t\t\t\t\t\t\t attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t setofInfoPtr->subtypeParent,\n\t\t\t\t\t\t\t\t\t flags | setofInfoPtr->inheritedAttrFlags,\n\t\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Adding invalid attribute data can return detailed error codes\n\t\t\t   that report the exact parameter that was wrong, we don't\n\t\t\t   need this much detail so we convert a parameter error into a\n\t\t\t   more general bad data status */\n\t\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t\t\t}\n\n\t\t/* Move on to the next field */\ncontinueDecoding:\n\t\tattributeContinues = \\\n\t\t\t\t\t( attributeInfoPtr->typeInfoFlags & FL_ATTR_ATTREND ) ? \\\n\t\t\t\t\tFALSE : TRUE;\n\t\tattributeInfoPtr++;\n\n\t\t/* If this is the end of the attribute encoding information but we're\n\t\t   inside a SET OF/SEQUENCE OF and there's more attribute data \n\t\t   present, go back to the restart point and try again */\n\t\tif( !attributeContinues && !setofStackIsEmpty( &setofStack ) && \\\n\t\t\tstell( stream ) < setofInfoPtr->endPos )\n\t\t\t{\n\t\t\t/* If we require at least one entry in the SET OF/SEQUENCE OF \n\t\t\t   but we haven't found one, this is an error */\n\t\t\tif( setIsEmpty( setofInfoPtr ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tENSURES( setofInfoPtr->infoStart != NULL );\n\n\t\t\t/* If this isn't a SET OF/SEQUENCE OF and we haven't seen an \n\t\t\t   element, we've run into an error */\n\t\t\tif( !( setofInfoPtr->infoStart->encodingFlags & FL_SETOF ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t\t/* If we haven't made any progress in processing the SET OF/\n\t\t\t   SEQUENCE OF then further iterations through the loop won't\n\t\t\t   make any difference, there's a bug in the decoder */\n\t\t\tENSURES( stell( stream ) > setofInfoPtr->startPos );\n\n\t\t\t/* Retry from the restart point */\n\t\t\tattributeInfoPtr = setofInfoPtr->infoStart + 1;\n\t\t\tENSURES( ( setofInfoPtr->flags & SETOF_FLAG_RESTARTPOINT ) || \\\n\t\t\t\t\t attributeInfoPtr->fieldType == FIELDTYPE_IDENTIFIER );\n\t\t\tattributeContinues = TRUE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we got stuck in a loop trying to decode an attribute, complain and \n\t   exit.  At this point we could have encountered either a certificate-\n\t   parsing error or a CRYPT_ERROR_INTERNAL internal error, since we \n\t   can't tell without human intervention we treat it as a certificate \n\t   error rather than throwing a retIntError() exception */\n\tif( attributeFieldsProcessed >= maxAttributeFields )\n\t\t{\n\t\tDEBUG_DIAG(( \"Processed more than %d fields in attribute, decoder \"\n\t\t\t\t\t \"may be stuck\", maxAttributeFields ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Handle the special case of (a) the encoded data ending but fields with\n\t   default values being present or (b) the encoded data continuing but no \n\t   more decoding information being present */\n\tif( attributeContinues )\n\t\t{\n\t\t/* If there are default fields to follow, add the default value, see\n\t\t   the comment on the handling of default fields above for more \n\t\t   details.  For now we only add the first field since the only \n\t\t   attributes where this case can occur have a single default value \n\t\t   as the next possible entry, burrowing down further causes \n\t\t   complications due to default values present in optional sequences.  \n\t\t   As usual we don't set any specific error information for the \n\t\t   default fields */\n\t\tif( attributeInfoPtr->encodingFlags & FL_DEFAULT )\n\t\t\t{\n\t\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\n\t\t\tstatus = addAttributeField( attributePtrPtr,\n\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->fieldID, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t\tattributeInfoPtr->defaultValue, \n\t\t\t\t\t\t\t\t\t\tflags, &dummy1, &dummy2 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tint noAdditionalEntries;\n\t\t\n\t\t/* Some attributes have a SEQUENCE OF fields of no great use (e.g.\n\t\t   Microsoft's extensive crlDistributionPoints lists providing\n\t\t   redundant pointers to the same inaccessible site-internal\n\t\t   servers, although these are already handled above), if there's\n\t\t   any extraneous data left then we just skip it */\n\t\tLOOP_SMALL( noAdditionalEntries = 0, \n\t\t\t\t\tcryptStatusOK( status ) && stell( stream ) < endPos && \\\n\t\t\t\t\t\tnoAdditionalEntries < 5,\n\t\t\t\t\tnoAdditionalEntries++ )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Skipping extraneous data at end of attribute\" ));\n\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( noAdditionalEntries > 5 )\n\t\t\t{\n\t\t\t/* There's a suspiciously large amount of extra data, treat it \n\t\t\t   as an error */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Collection Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the certificate object-specific wrapper for a set of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readAttributeWrapper( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t OUT_LENGTH_Z int *lengthPtr, \n\t\t\t\t\t\t\t\t IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int attributeLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( lengthPtr, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRangeOpt( type, CRYPT_CERTTYPE ) );\n\t\t\t  /* Single CRL entries have the special-case type \n\t\t\t     CRYPT_CERTTYPE_NONE */\n\tREQUIRES( isShortIntegerRange( attributeLength ) );\n\n\t/* Clear return value */\n\t*lengthPtr = 0;\n\n\t/* Read the appropriate wrapper for the certificate object type and \n\t   determine how far we can read.  CRLs and OCSP requests/responses have \n\t   two attribute types that have different tagging, per-entry attributes \n\t   and entire-CRL/request attributes.  To differentiate between the two \n\t   we read per-entry attributes with a type of CRYPT_CERTTYPE_NONE */\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\t\treadConstructed( stream, NULL, CTAG_CE_EXTENSIONS );\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\treadConstructed( stream, NULL, CTAG_CL_EXTENSIONS );\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\tcase CRYPT_CERTTYPE_NONE:\n\t\t\t/* Any outer wrapper for per-entry CRL/OCSP attributes has\n\t\t\t   already been read by the caller so there's only the inner\n\t\t\t   SEQUENCE left to read */\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_CMS_ATTRIBUTES:\n\t\t\treturn( readConstructed( stream, lengthPtr,\n\t\t\t\t\t\t\t\t\t CTAG_SI_AUTHENTICATEDATTRIBUTES ) );\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t/* CRMF/CMP attributes don't contain any wrapper so there's\n\t\t\t   nothing to read */\n\t\t\t*lengthPtr = attributeLength;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\t\treturn( readSet( stream, lengthPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\treturn( readConstructed( stream, lengthPtr, CTAG_RP_EXTENSIONS ) );\n\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\treadConstructed( stream, NULL, CTAG_OR_EXTENSIONS );\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\treadConstructed( stream, NULL, CTAG_OP_EXTENSIONS );\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n#ifdef USE_CERTREQ \n\n/* Read a PKCS #10 certificate request wrapper for a set of attributes.  \n   This isn't as simple as it should be because there are two approaches to \n   adding attributes to a request, the PKCS #10 approach which puts them all \n   inside a PKCS #9 extensionRequest attribute and the SET approach which \n   lists them all individually (CRMF is a separate case handled by \n   readAttributeWrapper() above).  Complicating this even further is the \n   SCEP approach, which puts attributes intended to be put into the final \n   certificate inside a PKCS #9 extensionRequest but other attributes used \n   for certificate issuance control, for example a challengePassword, \n   individually as SET does.  So the result can be something like:\n\n\t[0] SEQUENCE {\n\t\tSEQUENCE { challengePassword ... }\n\t\tSEQUENCE { extensionRequest \n\t\t\tSEQUENCE basicConstraints \n\t\t\tSEQUENCE keyUsage \n\t\t\t}\n\t\t}\n\n   In addition Microsoft invented their own incompatible version of the PKCS \n   #9 extensionRequest which is exactly the same as the PKCS #9 one but with \n   a MS OID, however they also invented other values to add containing God \n   knows what sort of data (long Unicode strings describing the Windows \n   module that created it (as if you'd need that to know where it came \n   from), the scripts from \"Gilligan's Island\", every \"Brady Bunch\" episode \n   ever made, dust from under somebody's bed from the 1930s, etc).\n   \n   Because of these problems, the code does the following:\n\n\t- If it's a standalone attribute, it processes it.\n\t- If it's a PKCS #9 extensionRequest, it reads the wrapper and returns.\n\t- If it's unknown garbage, it skips it.\n   \n   This leads to two follow-on issues.  Firstly, since all attributes may be \n   either skipped or processed at this stage we include provisions for \n   bailing out if we exhaust the available attributes.  Secondly, as soon as \n   we encounter a PKCS #9 extensionRequest we exit back to readAttributes() \n   for handling the individual attributes within the extensionRequest.  This \n   means that in order to handle any additional attributes present after the \n   ones encapsulated in the PKCS #9 extensionRequest we have to make a \n   second call to here after the main attribute-processing loop in \n   readAttributes() has finished reading the encapsulated attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 6 ) ) \\\nstatic int readCertReqWrapper( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *lengthPtr, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int attributeLength,\n\t\t\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst int endPos = stell( stream ) + attributeLength;\n\tint attributesProcessed, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( lengthPtr, sizeof( int ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( attributeLength ) );\n\tREQUIRES( endPos > 0 && endPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*lengthPtr = 0;\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\t/* Make sure that the length that we've been given makes sense */\n\tif( attributeLength < MIN_ATTRIBUTE_SIZE || \\\n\t\tattributeLength >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\tLOOP_MED( attributesProcessed = 0, attributesProcessed < 16, \n\t\t\t  attributesProcessed++ )\n\t\t{\n#if defined( USE_CERT_OBSOLETE ) || defined( USE_SCEP )\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n#endif /* USE_CERT_OBSOLETE || USE_SCEP */\n\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\t\tint oidLength;\n\n\t\t/* If we've run out of attributes, exit */\n\t\tif( stell( stream ) >= endPos )\n\t\t\treturn( OK_SPECIAL );\n\n\t\t/* Read the wrapper SEQUENCE and OID */\n\t\treadSequence( stream, NULL );\n\t\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n#if defined( USE_CERT_OBSOLETE ) || defined( USE_SCEP )\n\t\t/* Check for a known attribute, which can happen with SET and SCEP \n\t\t   certificate requests.  If it's a known attribute, process it */\n\t\tattributeInfoPtr = oidToAttribute( ATTRIBUTE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t\t   oid, oidLength );\n\t\tif( attributeInfoPtr != NULL )\n\t\t\t{\n\t\t\tint length;\n\n\t\t\tstatus = readSet( stream, &length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = readAttribute( stream, attributePtrPtr,\n\t\t\t\t\t\t\t\t\t\tattributeInfoPtr, length, FALSE, \n\t\t\t\t\t\t\t\t\t\terrorLocus, errorType );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\tcontinue;\n\t\t\t}\n#endif /* USE_CERT_OBSOLETE || USE_SCEP */\n\n\t\t/* It's not a known attribute, check whether it's a CRMF or MS \n\t\t   wrapper attribute */\n\t\tif( ( oidLength == sizeofOID( OID_PKCS9_EXTREQ ) && \\\n\t\t\t  !memcmp( oid, OID_PKCS9_EXTREQ, oidLength ) ) || \\\n\t\t\t( oidLength == sizeofOID( OID_MS_EXTREQ ) && \\\n\t\t\t  !memcmp( oid, OID_MS_EXTREQ, oidLength ) ) )\n\t\t\t{\n\t\t\t/* Skip the wrapper to reveal the encapsulated attributes */\n\t\t\treadSet( stream, NULL );\n\t\t\treturn( readSequence( stream, lengthPtr ) );\n\t\t\t}\n\n\t\t/* It's unknown MS garbage, skip it */\n\t\tstatus = readUniversal( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* As with the check in readAttribute() above, getting to this point \n\t   could be either a certificate-parsing error or a CRYPT_ERROR_INTERNAL \n\t   internal error, since we can't tell without human intervention we \n\t   treat it as a certificate error rather than throwing a retIntError() \n\t   exception */\n\tDEBUG_DIAG(( \"Unknown certificate request wrapper type encountered\" ));\n\tassert_nofuzz( DEBUG_WARN );\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n#endif /* USE_CERTREQ */\n\n/* Read a set of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 6 ) ) \\\nint readAttributes( INOUT STREAM *stream, \n\t\t\t\t\tINOUT DATAPTR_ATTRIBUTE *attributePtrPtr,\n\t\t\t\t\tIN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type, \n\t\t\t\t\tIN_LENGTH_Z const int attributeLength,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *errorLocus,\n\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ERRTYPE ) \\\n\t\t\t\t\t\tCRYPT_ERRTYPE_TYPE *errorType )\n\t{\n\tconst ATTRIBUTE_TYPE attributeType = ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES || \\\n\t\t\t\t\t\t\t\t\t\t   type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\t\t\t\t\t\t\t\t   type == CRYPT_CERTTYPE_RTCS_RESPONSE ) ? \\\n\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE;\n\tconst BOOLEAN wrapperTagSet = ( attributeType == ATTRIBUTE_CMS ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n#ifdef USE_CERTREQ \n\tconst int attributeEndPos = stell( stream ) + attributeLength;\n#endif /* USE_CERTREQ */\n\tint length, endPos, complianceLevel, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributePtrPtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\tassert( isWritePtr( errorLocus, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( isWritePtr( errorType, sizeof( CRYPT_ERRTYPE_TYPE ) ) );\n\n\tREQUIRES( isEnumRangeOpt( type, CRYPT_CERTTYPE ) );\n\t\t\t  /* Single CRL entries have the special-case type \n\t\t\t     CRYPT_CERTTYPE_NONE */\n\tREQUIRES( ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\t\t\tattributeLength == 0 ) || \\\n\t\t\t  ( type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\t\t\tisIntegerRangeNZ( attributeLength ) ) );\n\t\t\t  /* CMS attributes are pure attribute data with no \n\t\t\t     encapsulation to indicate the length so the length is \n\t\t\t\t implicitly \"everything that's present\".\n\t\t\t\t See the comment below for why we check for MAX_INTLENGTH\n\t\t\t\t rather than MAX_INTLENGTH_SHORT */\n\n\t/* Clear return values */\n\tDATAPTR_SET_PTR( attributePtrPtr, NULL );\n\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t*errorType = CRYPT_ERRTYPE_NONE;\n\n\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel,\n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we've been given an excessively long length, don't try and go any \n\t   further.  Generally the higher-level code will have enforced this\n\t   check by way of the length being passed to us being what's left of\n\t   the data in the certificate object, but if the length has come from\n\t   a read of any level of wrapper around the attributes then this \n\t   implicit enforcement won't have taken place so we perform an explicit \n\t   check here.  This means that from now on we can guarantee that the \n\t   length is no greater than MAX_INTLENGTH_SHORT rather than the more \n\t   generic MAX_INTLENGTH that's checked for in the precondition check\n\t   above */\n\tif( ( type != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\t  attributeLength < MIN_ATTRIBUTE_SIZE ) || \\\n\t\tattributeLength >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the wrapper for the certificate object's attributes and \n\t   determine how far we can read */\n#ifdef USE_CERTREQ \n\tif( type == CRYPT_CERTTYPE_CERTREQUEST )\n\t\t{\n\t\tstatus = readCertReqWrapper( stream, attributePtrPtr, \n\t\t\t\t\t\t\t\t\t &length, attributeLength, errorLocus, \n\t\t\t\t\t\t\t\t\t errorType );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* We processed all attributes that were present as part of the\n\t\t\t   wrapper read (see the explanation in readCertReqWrapper() for\n\t\t\t   details), we're done */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\telse\n#endif /* USE_CERTREQ */\n\t\tstatus = readAttributeWrapper( stream, &length, type, attributeLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_ATTRIBUTE_SIZE || length >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the collection of attributes */\n\tTRACE_DEBUG(( \"\\nReading attributes for certificate object starting at \"\n\t\t\t\t  \"offset %d.\", stell( stream ) ));\n\tLOOP_LARGE_CHECK( stell( stream ) < endPos )\n\t\t{\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\t\tBOOLEAN criticalFlag = FALSE, ignoreAttribute = FALSE;\n\t\tvoid *attributeDataPtr;\n\t\tint tag, oidLength, attributeDataLength;\n\n\t\t/* Read the outer wrapper and determine the attribute type based on\n\t\t   the OID */\n\t\treadSequence( stream, NULL );\n\t\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tTRACE_DEBUG(( \"Couldn't read attribute OID, status %s.\", \n\t\t\t\t\t\t  getStatusName( status ) ));\n\t\t\treturn( status );\n\t\t\t}\n\t\tattributeInfoPtr = oidToAttribute( attributeType, oid, oidLength );\n\t\tif( attributeInfoPtr != NULL && \\\n\t\t\tcomplianceLevel < decodeComplianceLevel( attributeInfoPtr->typeInfoFlags ) )\n\t\t\t{\n\t\t\t/* If we're running at a lower compliance level than that\n\t\t\t   required for the attribute, ignore it by treating it as a\n\t\t\t   blob-type attribute */\n\t\t\tTRACE_DEBUG(( \"Reading %s (%d) as a blob.\", \n\t\t\t\t\t\t  attributeInfoPtr->description, \n\t\t\t\t\t\t  attributeInfoPtr->fieldID ));\n\t\t\tattributeInfoPtr = NULL;\n\t\t\tignoreAttribute = TRUE;\n\t\t\t}\n\n\t\t/* Read the optional critical flag if it's a certificate object.  If \n\t\t   the attribute is marked critical and we don't recognise it then \n\t\t   we don't reject it at this point because that'd make it \n\t\t   impossible to examine the contents of the certificate or display \n\t\t   it to the user.  Instead we reject the certificate when we try \n\t\t   and check it with cryptCheckCert()/checkCertValidity() */\n\t\tif( attributeType != ATTRIBUTE_CMS && \\\n\t\t\tcheckStatusPeekTag( stream, status, tag ) && \\\n\t\t\ttag == BER_BOOLEAN )\n\t\t\t{\n\t\t\tstatus = readBoolean( stream, &criticalFlag );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t*errorLocus = ( attributeInfoPtr != NULL ) ? \\\n\t\t\t\t\t\t\t  attributeInfoPtr->fieldID : CRYPT_ATTRIBUTE_NONE;\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t\t/* Read the wrapper around the attribute payload.  We allow a length \n\t\t   down to zero since it could be an attribute with all-default \n\t\t   fields */\n\t\tif( wrapperTagSet )\n\t\t\tstatus = readSet( stream, &attributeDataLength );\n\t\telse\n\t\t\t{\n\t\t\tstatus = readOctetStringHole( stream, &attributeDataLength, 2,\n\t\t\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t}\n#ifdef USE_RPKI\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!isShortIntegerRange( attributeDataLength ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n#else\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( attributeDataLength < 0 || \\\n\t\t\t  attributeDataLength >= MAX_ATTRIBUTE_SIZE ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n#endif /* USE_RPKI */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t*errorLocus = ( attributeInfoPtr != NULL ) ? \\\n\t\t\t\t\t\t  attributeInfoPtr->fieldID : CRYPT_ATTRIBUTE_NONE;\n\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_VALUE;\n\t\t\tTRACE_DEBUG(( \"Couldn't read attribute payload wrapper for %s, \"\n\t\t\t\t\t\t  \"status %s.\", \n\t\t\t\t\t\t  ( attributeInfoPtr != NULL && \\\n\t\t\t\t\t\t    attributeInfoPtr->description != NULL ) ? \\\n\t\t\t\t\t\t\tattributeInfoPtr->description : \\\n\t\t\t\t\t\t\t\"(unrecognised blob attribute)\", \n\t\t\t\t\t\t\tgetStatusName( status ) ));\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If it's a known attribute, parse the payload */\n\t\tif( attributeInfoPtr != NULL )\n\t\t\t{\n\t\t\tstatus = readAttribute( stream, attributePtrPtr,\n\t\t\t\t\t\t\t\t\tattributeInfoPtr, attributeDataLength,\n\t\t\t\t\t\t\t\t\tcriticalFlag, errorLocus, errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tTRACE_DEBUG(( \"Error %s reading %s attribute.\", \n\t\t\t\t\t\t\t  getStatusName( status ),\n\t\t\t\t\t\t\t  ( attributeInfoPtr->description != NULL ) ? \\\n\t\t\t\t\t\t\t\tattributeInfoPtr->description : \\\n\t\t\t\t\t\t\t\t\"(unrecognised blob attribute)\" ));\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If it's a zero-length unrecognised attribute, don't add anything.\n\t\t   A zero length indicates that the attribute contains all default\n\t\t   values, however since we don't recognise the attribute we can't\n\t\t   fill these in so the attribute is in effect not present */\n\t\tif( attributeDataLength <= 0 )\n\t\t\tcontinue;\n\n\t\t/* It's an unrecognised or ignored attribute type, add the raw data\n\t\t   to the list of attributes */\n\t\tstatus = sMemGetDataBlock( stream, &attributeDataPtr, \n\t\t\t\t\t\t\t\t   attributeDataLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tANALYSER_HINT( attributeDataPtr != NULL );\n\t\t\tstatus = addAttribute( attributeType, attributePtrPtr, \n\t\t\t\t\t\t\t\t   oid, oidLength, criticalFlag, \n\t\t\t\t\t\t\t\t   attributeDataPtr, attributeDataLength, \n\t\t\t\t\t\t\t\t   ignoreAttribute ? \\\n\t\t\t\t\t\t\t\t\t\tATTR_FLAG_BLOB | ATTR_FLAG_IGNORED : \\\n\t\t\t\t\t\t\t\t\t\tATTR_FLAG_BLOB );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\t\t{\n\t\t\t\t/* If there's a duplicate attribute present, set error\n\t\t\t\t   information for it and flag it as a bad data error.  We\n\t\t\t\t   can't set an error locus since it's an unknown blob */\n\t\t\t\t*errorLocus = CRYPT_ATTRIBUTE_NONE;\n\t\t\t\t*errorType = CRYPT_ERRTYPE_ATTR_PRESENT;\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\tTRACE_DEBUG(( \"Error %s adding unrecognised blob attribute data.\", \n\t\t\t\t\t\t  getStatusName( status ) ));\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Skip the attribute data */\n\t\tsSkip( stream, attributeDataLength, MAX_INTLENGTH_SHORT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tTRACE_DEBUG(( \"Finished reading attributes for certificate object ending at \"\n\t\t\t\t  \"offset %d.\\n\", stell( stream ) ));\n\n\t/* Certificate requests can contain unencapsulated attributes as well as\n\t   attributes encapsulated inside PKCS #9 extensionRequests.  \n\t   readCertReqWrapper() processes any unencapsulated attributes that \n\t   precede a PKCS #9 extensionRequest (if present) and the attribute-\n\t   read loop above reads the encapsulated attributes.  If there are \n\t   further unencapsulated attributes present following the PKCS #9 \n\t   extensionRequest-encapsulated ones then we read them now */\n#ifdef USE_CERTREQ \n\tif( type == CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\tstell( stream ) < attributeEndPos )\n\t\t{\n\t\tstatus = readCertReqWrapper( stream, attributePtrPtr, &length, \n\t\t\t\t\t\t\t\t\t attributeEndPos - stell( stream ), \n\t\t\t\t\t\t\t\t\t errorLocus, errorType );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t{\n\t\t\t/* If all remaining attributes were processed by \n\t\t\t   readCertReqWrapper() then it returns OK_SPECIAL, this is used \n\t\t\t   to indicate that there are no PKCS #9 extensionRequest-\n\t\t\t   encapsulated attributes present.  Since this condition is\n\t\t\t   always met at this point because we're calling it after\n\t\t\t   processing encapsulated attributes, we have to filter it\n\t\t\t   out */\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTREQ */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/ext_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Attribute Write Routines\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"certattr.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/certattr.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the encoding information needed to encode an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getAttributeEncodingInfo( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\t OUT_PTR_COND \\\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_INFO **attributeInfoPtrPtr,\n\t\t\t\t\t\t\t\t\t OUT_INT_Z int *attributeDataSize )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tconst int fifoEndPos = attributeListPtr->fifoEnd - 1;\n\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isWritePtr( attributeInfoPtrPtr, sizeof( ATTRIBUTE_INFO * ) ) );\n\tassert( isWritePtr( attributeDataSize, sizeof( int ) ) );\n\n\tREQUIRES( fifoEndPos >= -1 && fifoEndPos < ENCODING_FIFO_SIZE - 1 );\n\n\t/* Clear return value */\n\t*attributeInfoPtrPtr = NULL;\n\n\t/* If it's a constructed attribute then the encoding information for\n\t   the outermost wrapper will be recorded in the encoding FIFO, \n\t   otherwise it's present directly */\n\tif( fifoEndPos >= 0 )\n\t\tattributeInfoPtr = attributeListPtr->encodingFifo[ fifoEndPos ];\n\telse\n\t\tattributeInfoPtr = attributeListPtr->attributeInfoPtr;\n\tENSURES( attributeInfoPtr != NULL );\n\n\t/* Determine the size of the attribute payload */\n\tif( fifoEndPos >= 0 && attributeInfoPtr->fieldType != FIELDTYPE_CHOICE )\n\t\t{\n\t\tconst int attributePayloadSize = \\\n\t\t\t\t\t\tattributeListPtr->sizeFifo[ fifoEndPos ];\n\n\t\tREQUIRES( isShortIntegerRange( attributePayloadSize ) );\n\t\t*attributeDataSize = sizeofShortObject( attributePayloadSize );\n\t\t}\n\telse\n\t\t*attributeDataSize = attributeListPtr->encodedSize;\n\t*attributeInfoPtrPtr = ( ATTRIBUTE_INFO * ) attributeInfoPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CMSATTR\n\n/* When we write the attributes as a SET OF Attribute (as CMS does) we have \n   to sort them by encoded value.  This is an incredible nuisance since it \n   requires that each value be encoded and stored in encoded form and then \n   the encoded forms sorted and emitted in that order.  To avoid this hassle \n   we keep a record of the current lowest encoded form and then find the \n   next one by encoding enough information (the SEQUENCE and OID, CMS \n   attributes don't have critical flags) on the fly to distinguish them.  \n   This is actually less overhead than storing the encoded form for sorting \n   because there are only a small total number of attributes (usually 3-5,\n   of which the main two are signingTime and messageDigest) and we don't \n   have to malloc() storage for each one and manage the stored form if we do \n   things on the fly */\n\n#define ATTR_ENCODED_SIZE\t( 16 + MAX_OID_SIZE )\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic ATTRIBUTE_LIST *getNextEncodedAttribute( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tINOUT_BUFFER_FIXED( prevEncodedFormLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tBYTE *prevEncodedForm,\n\t\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_FIXED( ATTR_ENCODED_SIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int prevEncodedFormLength )\n\t{\n\tconst ATTRIBUTE_LIST *currentAttributeListPtr = NULL;\n\tSTREAM stream;\n\tBYTE currentEncodedForm[ ATTR_ENCODED_SIZE + 8 ];\n\tBYTE buffer[ ATTR_ENCODED_SIZE + 8 ];\n\tint status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isWritePtrDynamic( prevEncodedForm, prevEncodedFormLength ) );\n\n\tREQUIRES_N( prevEncodedFormLength == ATTR_ENCODED_SIZE );\n\n\t/* Give the current encoded form the maximum possible value */\n\tmemset( currentEncodedForm, 0xFF, ATTR_ENCODED_SIZE );\n\n\tsMemOpen( &stream, buffer, ATTR_ENCODED_SIZE );\n\n\t/* Write the known attributes until we reach either the end of the list\n\t   or the first blob-type attribute */\n\tLOOP_LARGE_CHECK( attributeListPtr != NULL && \\\n\t\t\t\t\t  !checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tint attributeDataSize, LOOP_ITERATOR_ALT;\n\n\t\tREQUIRES_N( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t\t/* Get the encoding information for the attribute */\n\t\tstatus = getAttributeEncodingInfo( attributeListPtr, \n\t\t\t\t\t\t\t\t( ATTRIBUTE_INFO ** ) &attributeInfoPtr, \n\t\t\t\t\t\t\t\t&attributeDataSize );\n\t\tENSURES_N( cryptStatusOK( status ) );\n\t\tattributeID = attributeListPtr->attributeID;\n\n\t\t/* Reset the stream data */\n\t\tsseek( &stream, 0 );\n\t\tmemset( buffer, 0, ATTR_ENCODED_SIZE );\n\n\t\t/* Write the header and OID */\n\t\twriteSequence( &stream, sizeofOID( attributeInfoPtr->oid ) + \\\n\t\t\t\t\t\t\t\tsizeofShortObject( attributeDataSize ) );\n\t\tstatus = swrite( &stream, attributeInfoPtr->oid,\n\t\t\t\t\t\t sizeofOID( attributeInfoPtr->oid ) );\n\t\tENSURES_N( cryptStatusOK( status ) );\n\n\t\t/* Check to see whether this is larger than the previous value but \n\t\t   smaller than any other one that we've seen.  If it is, remember \n\t\t   it.  A full-length memcmp() is safe here because no encoded form \n\t\t   can be a prefix of another form so we always exit before we get \n\t\t   into the leftover data from previous encodings */\n\t\tif( memcmp( prevEncodedForm, buffer, ATTR_ENCODED_SIZE ) < 0 && \\\n\t\t\tmemcmp( buffer, currentEncodedForm, ATTR_ENCODED_SIZE ) < 0 )\n\t\t\t{\n\t\t\tmemcpy( currentEncodedForm, buffer, ATTR_ENCODED_SIZE );\n\t\t\tcurrentAttributeListPtr = attributeListPtr;\n\t\t\t}\n\n\t\t/* Move on to the next attribute */\n\t\tLOOP_LARGE_CHECKINC_ALT( attributeListPtr != NULL && \\\n\t\t\t\t\t\t\t\t attributeListPtr->attributeID == attributeID,\n\t\t\t\t\t\t\t\t attributeListPtr = DATAPTR_GET( attributeListPtr->next ) );\n\t\tENSURES_N( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\t/* Write the blob-type attributes */\n\tLOOP_LARGE_CHECKINC( attributeListPtr != NULL, \n\t\t\t\t\t\t attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tENSURES_N( sanityCheckAttributePtr( attributeListPtr ) );\n\t\tENSURES_N( checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) );\n\n\t\t/* Write the header and OID */\n\t\tsseek( &stream, 0 );\n\t\twriteSequence( &stream, \n\t\t\t\t\t   sizeofOID( attributeListPtr->oid ) + \\\n\t\t\t\t\t   sizeofShortObject( attributeListPtr->dataValueLength ) );\n\t\tstatus = swrite( &stream, attributeListPtr->oid,\n\t\t\t\t\t\t sizeofOID( attributeListPtr->oid ) );\n\t\tENSURES_N( cryptStatusOK( status ) );\n\n\t\t/* Check to see whether this is larger than the previous value but\n\t\t   smaller than any other one that we've seen.  If it is, remember \n\t\t   it */\n\t\tif( memcmp( prevEncodedForm, buffer, ATTR_ENCODED_SIZE ) < 0 && \\\n\t\t\tmemcmp( buffer, currentEncodedForm, ATTR_ENCODED_SIZE ) < 0 )\n\t\t\t{\n\t\t\tmemcpy( currentEncodedForm, buffer, ATTR_ENCODED_SIZE );\n\t\t\tcurrentAttributeListPtr = attributeListPtr;\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\tsMemDisconnect( &stream );\n\n\t/* Remember the encoded form of the attribute and return a pointer to\n\t   it */\n\tmemcpy( prevEncodedForm, currentEncodedForm, ATTR_ENCODED_SIZE );\n\treturn( ( ATTRIBUTE_LIST * ) currentAttributeListPtr );\n\t}\n#endif /* USE_CMSATTR */\n\n/* Determine the size of a set of attributes and validate and preprocess the\n   attribute information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int calculateAttributeSizes( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN hasSpecialEncoding,\n\t\t\t\t\t\t\t\t\tOUT_LENGTH_Z int *attributeSize,\n\t\t\t\t\t\t\t\t\tOUT_LENGTH_Z int *encapsAttributeSize )\n\t{\n\tBOOLEAN_INT signUnrecognised;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isWritePtr( attributeSize, sizeof( int ) ) );\n\tassert( isWritePtr( encapsAttributeSize, sizeof( int ) ) );\n\n\tREQUIRES( hasSpecialEncoding == TRUE || hasSpecialEncoding == FALSE );\n\n\t/* Clear return values */\n\t*attributeSize = *encapsAttributeSize = 0;\n\n\t/* Determine the size of the recognised attributes */\n\tLOOP_LARGE_CHECK( attributeListPtr != NULL && \\\n\t\t\t\t\t  !checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tint attributeDataSize, LOOP_ITERATOR_ALT;\n\n\t\tENSURES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t\t/* Get the encoding information for the attribute */\n\t\tstatus = getAttributeEncodingInfo( attributeListPtr, \n\t\t\t\t\t\t\t\t( ATTRIBUTE_INFO ** ) &attributeInfoPtr, \n\t\t\t\t\t\t\t\t&attributeDataSize );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tattributeID = attributeListPtr->attributeID;\n\t\tattributeDataSize = sizeofShortObject( attributeDataSize );\n\n\t\t/* Determine the attribute data size */\n\t\tattributeDataSize += sizeofOID( attributeInfoPtr->oid );\n\t\tif( ( attributeInfoPtr->typeInfoFlags & FL_ATTR_CRITICAL ) || \\\n\t\t\tTEST_FLAG( attributeListPtr->flags, ATTR_FLAG_CRITICAL ) )\n\t\t\tattributeDataSize += sizeofBoolean();\n\t\tattributeDataSize = sizeofShortObject( attributeDataSize );\n\n\t\t/* Some certificate objects (and specifically PKCS #10 requests) \n\t\t   have two classes of extensions, ones that apply to the request \n\t\t   itself and ones that apply to the certificate that the request \n\t\t   will be turned into, which are themselves encapsulated inside \n\t\t   their own extension type.  To deal with this we record sizes for \n\t\t   encapsulated and non-encapsulated extensions */\n\t\tif( hasSpecialEncoding )\n\t\t\t{\n\t\t\tif( attributeInfoPtr->encodingFlags & FL_SPECIALENCODING )\n\t\t\t\t*attributeSize += attributeDataSize;\n\t\t\telse\n\t\t\t\t*encapsAttributeSize += attributeDataSize;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a standard extension */\n\t\t\t*attributeSize += attributeDataSize;\n\t\t\t}\n\n\t\t/* Skip everything else in the current attribute */\n\t\tLOOP_LARGE_CHECKINC_ALT( attributeListPtr != NULL && \\\n\t\t\t\t\t\t\t\t attributeListPtr->attributeID == attributeID,\n\t\t\t\t\t\t\t\t attributeListPtr = DATAPTR_GET( attributeListPtr->next ) );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we're not going to be signing the blob-type attributes, return */\n\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &signUnrecognised, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES );\n\tif( cryptStatusError( status ) || !signUnrecognised )\n\t\treturn( CRYPT_OK );\n\n\t/* Determine the size of the blob-type attributes.  This has the same \n\t   problem as the recognised attributes, but this time even more so, \n\t   since the attribute isn't recognised we don't know whether it should\n\t   apply to the request or to the certificate that the request will be\n\t   turned into.  Based on a user survey it seems that in the rare cases\n\t   when custom attributes are used in requests, they're intended to\n\t   apply to the certificate that the request will be turned into, so we\n\t   include them in the encapsulated attributes */\n\tLOOP_LARGE_CHECKINC( attributeListPtr != NULL, \n\t\t\t\t\t\t attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tint attributeDataSize;\n\n\t\tENSURES( sanityCheckAttributePtr( attributeListPtr ) );\n\t\tENSURES( checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) );\n\n\t\tattributeDataSize = \\\n\t\t\t\t\tsizeofShortObject( sizeofOID( attributeListPtr->oid ) + \\\n\t\t\t\t\tsizeofShortObject( attributeListPtr->dataValueLength ) );\n\t\tif( TEST_FLAG( attributeListPtr->flags, ATTR_FLAG_CRITICAL ) )\n\t\t\tattributeDataSize += sizeofBoolean();\n\t\tif( hasSpecialEncoding )\n\t\t\t*encapsAttributeSize += attributeDataSize;\n\t\telse\n\t\t\t*attributeSize += attributeDataSize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAttributes( IN_DATAPTR_OPT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE type )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tconst BOOLEAN hasSpecialEncoding = \\\n\t\t\t\t\t( type == CRYPT_CERTTYPE_CERTREQUEST ) ? TRUE : FALSE;\n\tint attributeSize, encapsAttributeSize, status;\n\n\tREQUIRES( DATAPTR_ISVALID( attributePtr ) );\n\tREQUIRES( isEnumRangeOpt( type, CRYPT_CERTTYPE ) );\n\t\t\t  /* Single CRL, OCSP, and RTCS entries have the special-case \n\t\t\t     type CRYPT_CERTTYPE_NONE */\n\n\t/* If there are no attributes, return now */\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\treturn( 0 );\n\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tREQUIRES( attributeListPtr != NULL ); \n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t/* Calculate the size of the attributes */\n\tstatus = calculateAttributeSizes( attributeListPtr, hasSpecialEncoding,\n\t\t\t\t\t\t\t\t\t  &attributeSize, &encapsAttributeSize );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* If it's a PKCS #10 request, add any extra size from the encapsulated\n\t   certificate attributes */\n\tif( hasSpecialEncoding && encapsAttributeSize > 0 )\n\t\t{\n\t\tattributeSize += sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofOID( OID_PKCS9_EXTREQ ) + \\\n\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( encapsAttributeSize ) ) );\n\t\t}\n\t\n\treturn( attributeSize );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAttribute/Attribute Field Write Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate the size of an attribute field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int calculateSpecialFieldSize( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\t  const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *payloadSize, \n\t\t\t\t\t\t\t\t\t  const int fieldType )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtr( payloadSize, sizeof( int ) ) );\n\n\tREQUIRES( isBlobField( fieldType ) || \\\n\t\t\t  ( fieldType == FIELDTYPE_IDENTIFIER ) || \\\n\t\t\t  ( fieldType > 0 && fieldType < MAX_TAG ) );\n\n\t/* Determine the size of the data payload */\n\t*payloadSize = attributeListPtr->sizeFifo[ attributeListPtr->fifoPos ];\n\tENSURES( isShortIntegerRange( *payloadSize ) );\n\n\t/* It's a special-case field, the data size is taken from somewhere \n\t   other than the user-supplied data */\n\tswitch( fieldType )\n\t\t{\n\t\tcase FIELDTYPE_BLOB_ANY:\n\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\t\t/* Fixed-value blob (as opposed to user-supplied one) */\n\t\t\treturn( attributeInfoPtr->defaultValue );\n\n\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\treturn( sizeofOID( attributeInfoPtr->oid ) );\n\n\t\tcase BER_SEQUENCE:\n\t\tcase BER_SET:\n\t\t\treturn( sizeofShortObject( *payloadSize ) );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int calculateFieldSize( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t   const ATTRIBUTE_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t   const int fieldType )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtr( attributeInfoPtr, sizeof( ATTRIBUTE_INFO ) ) );\n\n\tREQUIRES( fieldType >= FIELDTYPE_LAST && fieldType < MAX_TAG );\n\t\t\t  /* The default handler at the end can include fields up to \n\t\t\t     FIELDTYPE_LAST */\n\n\tswitch( fieldType )\n\t\t{\n\t\tcase FIELDTYPE_BLOB_ANY:\n\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\treturn( attributeListPtr->dataValueLength );\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t{\n\t\t\tconst DATAPTR_DN dn = GET_DN_POINTER( attributeListPtr );\n\n\t\t\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\n\t\t\treturn( sizeofDN( dn ) );\n\t\t\t}\n\n\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\treturn( sizeofOID( attributeInfoPtr->oid ) );\n\n\t\tcase BER_BITSTRING:\n\t\t\treturn( sizeofBitString( attributeListPtr->intValue ) );\n\n\t\tcase BER_BOOLEAN:\n\t\t\treturn( sizeofBoolean() );\n\n\t\tcase BER_ENUMERATED:\n\t\t\treturn( sizeofEnumerated( attributeListPtr->intValue ) );\n\n\t\tcase BER_INTEGER:\n\t\t\treturn( sizeofShortInteger( attributeListPtr->intValue ) );\n\n\t\tcase BER_NULL:\n\t\t\t/* This is stored as a pseudo-numeric value CRYPT_UNUSED so we \n\t\t\t   can't fall through to the default handler */\n\t\t\treturn( sizeofNull() );\n\n\t\tcase BER_OCTETSTRING:\n\t\t\treturn( sizeofShortObject( attributeListPtr->dataValueLength ) );\n\n\t\tcase BER_TIME_GENERALIZED:\n\t\t\treturn( sizeofGeneralizedTime() );\n\n\t\tcase BER_TIME_UTC:\n\t\t\treturn( sizeofUTCTime() );\n\t\t}\n\n\treturn( sizeofShortObject( attributeListPtr->dataValueLength ) );\n\t}\n\n/* Determine the encoded size of an attribute field */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofAttributeField( INOUT ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tBOOLEAN isSpecial;\n\tint fieldType, size, status;\n\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t/* Get the encoding information for this attribute field */\n\tisSpecial = ( attributeListPtr->fifoPos > 0 ) ? TRUE : FALSE;\n\tif( isSpecial )\n\t\t{\n#if 0\t/* 18/12/17 Never reached in any test code */\n\t\tassert( DEBUG_WARN );\n\t\tattributeListPtr->fifoPos--;\t/* Move down to the next entry */\n\t\t\t\t\t\t\t\t\t\t// Should we be modifying this?\n\t\tattributeInfoPtr = attributeListPtr->encodingFifo[ attributeListPtr->fifoPos ];\n#endif /* 0 */\n\t\tretIntError();\n\t\t}\n\telse\n\t\tattributeInfoPtr = attributeListPtr->attributeInfoPtr;\n\tENSURES( attributeInfoPtr != NULL );\n\tfieldType = attributeInfoPtr->fieldType;\n\n\t/* If this is just a marker for a series of CHOICE alternatives, return\n\t   without doing anything */\n\tif( fieldType == FIELDTYPE_CHOICE )\n\t\t{\n#if 0\t/* 18/12/17 Never reached in any test code */\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n#endif /* 0 */\n\t\tretIntError();\n\t\t}\n\n\t/* Calculate the size of the encoded data */\n#if 0\t/* 18/12/17 Never reached due to isSpecial exit above */\n\tif( isSpecial )\n\t\t{\n\t\tint dummy;\n\n\t\tstatus = size = \\\n\t\t\tcalculateSpecialFieldSize( attributeListPtr, attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t   &dummy, fieldType );\n\t\t}\n\telse\n#endif /* 0 */\n\t\t{\n\t\tstatus = size = \\\n\t\t\tcalculateFieldSize( attributeListPtr, attributeInfoPtr, \n\t\t\t\t\t\t\t\tfieldType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( ( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) ? \\\n\t\t\tsizeofShortObject( size ) : size );\n\t}\n\n/* Write an attribute field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeAttributeField( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\tIN_RANGE( 0, 4 ) const int complianceLevel )\n\t{\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tconst BOOLEAN isSpecial = ( attributeListPtr->fifoPos > 0 ) ? TRUE : FALSE;\n\tconst void *dataPtr = attributeListPtr->dataValue;\n\tint fieldType, tag, size, payloadSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Get the encoding information for this attribute field */\n\tif( isSpecial )\n\t\t{\n\t\tREQUIRES( attributeListPtr->fifoPos > 0 && \\\n\t\t\t\t  attributeListPtr->fifoPos < ENCODING_FIFO_SIZE );\n\t\tattributeListPtr->fifoPos--;\t/* Move down to the next entry */\n\t\tattributeInfoPtr = attributeListPtr->encodingFifo[ attributeListPtr->fifoPos ];\n\t\t}\n\telse\n\t\tattributeInfoPtr = attributeListPtr->attributeInfoPtr;\n\tENSURES( attributeInfoPtr != NULL );\n\tfieldType = attributeInfoPtr->fieldType;\n\n\t/* If this is just a marker for a series of CHOICE alternatives, return\n\t   without doing anything */\n\tif( fieldType == FIELDTYPE_CHOICE )\n\t\treturn( CRYPT_OK );\n\n\t/* Calculate the size of the encoded data */\n\tif( isSpecial )\n\t\t{\n\t\tstatus = size = \\\n\t\t\tcalculateSpecialFieldSize( attributeListPtr, attributeInfoPtr,\n\t\t\t\t\t\t\t\t\t   &payloadSize, fieldType );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = size = \\\n\t\t\tcalculateFieldSize( attributeListPtr, attributeInfoPtr, \n\t\t\t\t\t\t\t\tfieldType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the field is explicitly tagged, add another layer of wrapping */\n\tif( attributeInfoPtr->encodingFlags & FL_EXPLICIT )\n\t\t{\n\t\tstatus = writeConstructed( stream, size, \n\t\t\t\t\t\t\t\t   attributeInfoPtr->fieldEncodedType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If the encoded field type differs from the actual field type (because\n\t   of implicit tagging) and we're not specifically using explicit\n\t   tagging and it's not a DN in a GeneralName (which is a tagged IMPLICIT\n\t   SEQUENCE overridden to make it EXPLICIT because of the tagged CHOICE\n\t   encoding rules) set the tag to the encoded field type rather than the\n\t   actual field type */\n\tif( attributeInfoPtr->fieldEncodedType >= 0 && \\\n\t\t!( attributeInfoPtr->encodingFlags & FL_EXPLICIT ) && \\\n\t\tattributeInfoPtr->fieldType != FIELDTYPE_DN )\n\t\ttag = attributeInfoPtr->fieldEncodedType;\n\telse\n\t\ttag = DEFAULT_TAG;\n\n\t/* Write the data as appropriate */\n\tif( isSpecial )\n\t\t{\n\t\t/* If it's a special-case field, the data is taken from somewhere\n\t\t   other than the user-supplied data */\n\t\tswitch( fieldType )\n\t\t\t{\n\t\t\tcase FIELDTYPE_BLOB_ANY:\n\t\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\t\t\t/* Fixed-value blob (as opposed to user-supplied one) */\n\t\t\t\treturn( swrite( stream, attributeInfoPtr->extraData, size ) );\n\n\t\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\t\treturn( swrite( stream, attributeInfoPtr->oid, size ) );\n\n\t\t\tcase BER_SEQUENCE:\n\t\t\tcase BER_SET:\n\t\t\t\tif( tag != DEFAULT_TAG )\n\t\t\t\t\treturn( writeConstructed( stream, payloadSize, tag ) );\n\t\t\t\treturn( ( fieldType == BER_SET ) ? \\\n\t\t\t\t\t\twriteSet( stream, payloadSize ) : \\\n\t\t\t\t\t\twriteSequence( stream, payloadSize ) );\n\t\t\t}\n\t\t\n\t\tretIntError();\n\t\t}\n\n\t/* It's a standard object, take the data from the user-supplied data */\n\tswitch( fieldType )\n\t\t{\n\t\tcase FIELDTYPE_BLOB_ANY:\n\t\tcase FIELDTYPE_BLOB_BITSTRING:\n\t\tcase FIELDTYPE_BLOB_SEQUENCE:\n\t\t\tif( tag != DEFAULT_TAG )\n\t\t\t\t{\n\t\t\t\t/* This gets a bit messy because the blob is stored in \n\t\t\t\t   encoded form in the attribute, to write it as a tagged \n\t\t\t\t   value we have to write a different first byte */\n\t\t\t\tsputc( stream, getFieldEncodedTag( attributeInfoPtr ) );\n\t\t\t\treturn( swrite( stream, ( ( BYTE * ) dataPtr ) + 1,\n\t\t\t\t\t\t\t\tattributeListPtr->dataValueLength - 1 ) );\n\t\t\t\t}\n\t\t\treturn( swrite( stream, dataPtr, \n\t\t\t\t\tattributeListPtr->dataValueLength ) );\n\n\t\tcase FIELDTYPE_DN:\n\t\t\t{\n\t\t\tconst DATAPTR_DN dn = GET_DN_POINTER( attributeListPtr );\n\n\t\t\tREQUIRES( DATAPTR_ISVALID( dn ) );\n\n\t\t\treturn( writeDN( stream, dn, tag ) );\n\t\t\t}\n\n\t\tcase FIELDTYPE_IDENTIFIER:\n\t\t\tENSURES( tag == DEFAULT_TAG );\n\t\t\treturn( swrite( stream, attributeInfoPtr->oid, size ) );\n\n\t\tcase FIELDTYPE_TEXTSTRING:\n\t\t\tif( tag == DEFAULT_TAG )\n\t\t\t\t{\n\t\t\t\tint newStringLen, dummy;\n\n\t\t\t\tstatus = getAsn1StringInfo( dataPtr, \n\t\t\t\t\t\t\t\tattributeListPtr->dataValueLength, \n\t\t\t\t\t\t\t\t&dummy, &tag, &newStringLen, FALSE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\n\t\t\t\t/* If the only way to encode the string is to convert it \n\t\t\t\t   into a wider encoding type then we can't safely emit \n\t\t\t\t   it */\n\t\t\t\tif( newStringLen != attributeListPtr->dataValueLength )\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\treturn( writeCharacterString( stream, dataPtr, \n\t\t\t\t\t\t\t\t\t\t  attributeListPtr->dataValueLength, \n\t\t\t\t\t\t\t\t\t\t  tag ) );\n\n\t\tcase BER_BITSTRING:\n\t\t\tREQUIRES( isIntegerRange( attributeListPtr->intValue ) );\n\t\t\treturn( writeBitString( stream, ( int ) \\\n\t\t\t\t\t\t\t\t\tattributeListPtr->intValue, tag ) );\n\n\t\tcase BER_BOOLEAN:\n\t\t\tREQUIRES( isIntegerRange( attributeListPtr->intValue ) );\n\t\t\treturn( writeBoolean( stream, attributeListPtr->intValue ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE, tag ) );\n\n\t\tcase BER_ENUMERATED:\n\t\t\tREQUIRES( isIntegerRange( attributeListPtr->intValue ) );\n\t\t\treturn( writeEnumerated( stream, ( int ) \\\n\t\t\t\t\t\t\t\t\t attributeListPtr->intValue, tag ) );\n\n\t\tcase BER_INTEGER:\n\t\t\tREQUIRES( isIntegerRange( attributeListPtr->intValue ) );\n\t\t\treturn( writeShortInteger( stream, attributeListPtr->intValue, \n\t\t\t\t\t\t\t\t\t   tag ) );\n\n\t\tcase BER_NULL:\n\t\t\treturn( writeNull( stream, tag ) );\n\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\tif( tag != DEFAULT_TAG )\n\t\t\t\t{\n\t\t\t\t/* This gets a bit messy because the OID is stored in \n\t\t\t\t   encoded form in the attribute, to write it as a tagged \n\t\t\t\t   value we have to write a different first byte */\n\t\t\t\tsputc( stream, getFieldEncodedTag( attributeInfoPtr ) );\n\t\t\t\treturn( swrite( stream, ( ( BYTE * ) dataPtr ) + 1,\n\t\t\t\t\t\t\t\tattributeListPtr->dataValueLength - 1 ) );\n\t\t\t\t}\n\t\t\treturn( swrite( stream, dataPtr, \n\t\t\t\t\t\t\tattributeListPtr->dataValueLength ) );\n\n\t\tcase BER_OCTETSTRING:\n\t\t\treturn( writeOctetString( stream, dataPtr, \n\t\t\t\t\t\t\t\t\t  attributeListPtr->dataValueLength, \n\t\t\t\t\t\t\t\t\t  tag ) );\n\n\t\tcase BER_STRING_BMP:\n\t\tcase BER_STRING_IA5:\n\t\tcase BER_STRING_ISO646:\n\t\tcase BER_STRING_NUMERIC:\n\t\tcase BER_STRING_PRINTABLE:\n\t\tcase BER_STRING_UTF8:\n\t\t\treturn( writeCharacterString( stream, dataPtr, \n\t\t\t\t\t\t\t\t\t\t  attributeListPtr->dataValueLength,\n\t\t\t\t\t\t\t\t\t\t  ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tfieldType : \\\n\t\t\t\t\t\t\t\t\t\t\tMAKE_CTAG_PRIMITIVE( tag ) ) );\n\n\t\tcase BER_TIME_GENERALIZED:\n\t\t\treturn( writeGeneralizedTime( stream, *( time_t * ) dataPtr, \n\t\t\t\t\t\t\t\t\t\t  tag ) );\n\n\t\tcase BER_TIME_UTC:\n\t\t\treturn( writeUTCTime( stream, *( time_t * ) dataPtr, tag ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Write an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeAttribute( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT ATTRIBUTE_LIST **attributeListPtrPtr,\n\t\t\t\t\t\t   const BOOLEAN wrapperTagSet, \n\t\t\t\t\t\t   IN_RANGE( 0, 4 ) const int complianceLevel )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\tATTRIBUTE_LIST *attributeListPtr = *attributeListPtrPtr;\n\tBOOLEAN isCritical = FALSE;\n\tint attributeDataSize, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributeListPtrPtr, sizeof( ATTRIBUTE_LIST * ) ) );\n\tassert( isReadPtr( *attributeListPtrPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( wrapperTagSet == TRUE || wrapperTagSet == FALSE );\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Get the encoding information for the attribute */\n\tstatus = getAttributeEncodingInfo( attributeListPtr, \n\t\t\t\t\t\t\t\t( ATTRIBUTE_INFO ** ) &attributeInfoPtr, \n\t\t\t\t\t\t\t\t&attributeDataSize );\n\tENSURES( cryptStatusOK( status ) );\n\tattributeID = attributeListPtr->attributeID;\n\tif( ( attributeInfoPtr->typeInfoFlags & FL_ATTR_CRITICAL ) || \\\n\t\tTEST_FLAG( attributeListPtr->flags, ATTR_FLAG_CRITICAL ) )\n\t\tisCritical = TRUE;\n\n\t/* Write the outer SEQUENCE, OID, critical flag (if it's set) and \n\t   appropriate wrapper for the attribute payload */\n\twriteSequence( stream, \n\t\t\t\t   sizeofOID( attributeInfoPtr->oid ) + \\\n\t\t\t\t   ( isCritical ? sizeofBoolean() : 0 ) + \\\n\t\t\t\t   sizeofShortObject( attributeDataSize ) );\n\tswrite( stream, attributeInfoPtr->oid,\n\t\t\tsizeofOID( attributeInfoPtr->oid ) );\n\tif( isCritical )\n\t\twriteBoolean( stream, TRUE, DEFAULT_TAG );\n\tif( wrapperTagSet )\n\t\tstatus = writeSet( stream, attributeDataSize );\n\telse\n\t\tstatus = writeOctetStringHole( stream, attributeDataSize, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the current attribute */\n\tLOOP_MED_CHECKINC( attributeListPtr != NULL && \\\n\t\t\t\t\t   attributeListPtr->attributeID == attributeID,\n\t\t\t\t\t   attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t\t/* Write any encapsulating SEQUENCEs if necessary, followed by the \n\t\t   field itself.  In some rare instances we may have a zero-length \n\t\t   SEQUENCE (if all the member(s) of the sequence have default \n\t\t   values) so we only try to write the member if there's encoding \n\t\t   information for it present.  \n\t\t   \n\t\t   Note that this loop doesn't update the FIFO position since this \n\t\t   is updated by the call to writeAttributeField() */\n\t\tLOOP_EXT_INITCHECK_ALT( attributeListPtr->fifoPos = \\\n\t\t\t\t\t\t\t\t\tattributeListPtr->fifoEnd, \n\t\t\t\t\t\t\t   cryptStatusOK( status ) && \\\n\t\t\t\t\t\t\t\t\tattributeListPtr->fifoPos > 0, \n\t\t\t\t\t\t\t   ENCODING_FIFO_SIZE + 1 )\n\t\t\t{\n\t\t\tstatus = writeAttributeField( stream, \n\t\t\t\t\t\t\t\t\t( ATTRIBUTE_LIST * ) attributeListPtr,\n\t\t\t\t\t\t\t\t\tcomplianceLevel );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tattributeListPtr->attributeInfoPtr != NULL )\n\t\t\t{\n\t\t\tstatus = writeAttributeField( stream, \n\t\t\t\t\t\t\t\t\t( ATTRIBUTE_LIST * ) attributeListPtr,\n\t\t\t\t\t\t\t\t\tcomplianceLevel );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t*attributeListPtrPtr = attributeListPtr;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeBlobAttribute( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t   const BOOLEAN wrapperTagSet )\n\t{\n\tconst BOOLEAN isCritical = TEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t\t\t\t  ATTR_FLAG_CRITICAL ) ? TRUE : FALSE;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( wrapperTagSet == TRUE || wrapperTagSet == FALSE );\n\n\t/* Write the header, OID, critical flag (if present), and payload \n\t   wrapped up as appropriate */\n\twriteSequence( stream, \n\t\t\tsizeofOID( attributeListPtr->oid ) + \\\n\t\t\t( isCritical ? sizeofBoolean() : 0 ) + \\\n\t\t\tsizeofShortObject( attributeListPtr->dataValueLength ) );\n\tswrite( stream, attributeListPtr->oid,\n\t\t\tsizeofOID( attributeListPtr->oid ) );\n\tif( isCritical )\n\t\twriteBoolean( stream, TRUE, DEFAULT_TAG );\n\tif( wrapperTagSet )\n\t\twriteSet( stream, attributeListPtr->dataValueLength );\n\telse\n\t\t{\n\t\twriteOctetStringHole( stream, \n\t\t\t\t\t\t\t  attributeListPtr->dataValueLength, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t}\n\tstatus = swrite( stream, attributeListPtr->dataValue,\n\t\t\t\t\t attributeListPtr->dataValueLength );\n\treturn( status );\n\t}\n\n#ifdef USE_CMSATTR\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCmsAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   IN const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t\t   IN_LENGTH const int attributeSize,\n\t\t\t\t\t\t\t   IN_RANGE( 0, 4 ) const int complianceLevel )\n\t{\n\tATTRIBUTE_LIST *currentAttributePtr;\n\tBYTE currentEncodedForm[ ATTR_ENCODED_SIZE + 8 ];\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES || \\\n\t\t\t  type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\t  type == CRYPT_CERTTYPE_RTCS_RESPONSE );\n\tREQUIRES( isIntegerRangeNZ( attributeSize ) );\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Write the wrapper, depending on the object type */\n\tif( type == CRYPT_CERTTYPE_RTCS_REQUEST )\n\t\tstatus = writeSet( stream, attributeSize );\n\telse\n\t\t{\n\t\tstatus = writeConstructed( stream, attributeSize, \n\t\t\t\t\t\t\t\t  ( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \\\n\t\t\t\t\t\t\t\t\tCTAG_SI_AUTHENTICATEDATTRIBUTES : \\\n\t\t\t\t\t\t\t\t\tCTAG_RP_EXTENSIONS );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the attributes in sorted form */\n\tmemset( currentEncodedForm, 0, ATTR_ENCODED_SIZE );\t/* Set lowest encoded form */\n\tLOOP_LARGE( currentAttributePtr = \\\n\t\t\t\t\tgetNextEncodedAttribute( attributeListPtr, \n\t\t\t\t\t\t\t\t\t\t\t currentEncodedForm, \n\t\t\t\t\t\t\t\t\t\t\t ATTR_ENCODED_SIZE ),\n\t\t\t\tcurrentAttributePtr != NULL && cryptStatusOK( status ),\n\t\t\t\tcurrentAttributePtr = \\\n\t\t\t\t\tgetNextEncodedAttribute( attributeListPtr, \n\t\t\t\t\t\t\t\t\t\t\t currentEncodedForm,\n\t\t\t\t\t\t\t\t\t\t\t ATTR_ENCODED_SIZE ) )\n\t\t{\n\t\tREQUIRES( sanityCheckAttributePtr( currentAttributePtr ) );\n\n\t\tif( checkAttributeListProperty( currentAttributePtr,\n\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t\t{\n\t\t\tstatus = writeBlobAttribute( stream, currentAttributePtr, TRUE );\n\t\t\tcurrentAttributePtr = DATAPTR_GET( currentAttributePtr->next );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = writeAttribute( stream, &currentAttributePtr, TRUE, \n\t\t\t\t\t\t\t\t\t complianceLevel );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMSATTR */\n\n#ifdef USE_CERTREQ\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCertReqAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t   IN_RANGE( 0, 4 ) const int complianceLevel )\n\t{\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Write any standalone attributes that aren't encapsulated in an\n\t   extensionRequest.  We stop when we reach the blob-type attributes\n\t   because, since they're blobs, we don't know whether they're \n\t   standalone or extensionRequest-encapsulated ones */\n\tLOOP_LARGE_CHECK( cryptStatusOK( status ) && \\\n\t\t\t\t\t  attributeListPtr != NULL && \\\n\t\t\t\t\t  !checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\t\tDATAPTR_ATTRIBUTE attributePtr;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\t\tattributeInfoPtr = attributeListPtr->attributeInfoPtr;\n\n\t\t/* If this is an attribute that's not encapsulated inside an \n\t\t   extensionRequest (denoted by it having the FL_SPECIALENCODING\n\t\t   flag set), write it now.  We have to check for attributeInfoPtr \n\t\t   not being NULL because in the case of an attribute that contains \n\t\t   all-default values (for example the default basicConstraints with \n\t\t   cA = DEFAULT FALSE and pathLenConstraint absent) there won't be \n\t\t   any encoding information present since the entire attribute is \n\t\t   empty */\n\t\tif( attributeInfoPtr != NULL && \\\n\t\t\t( attributeInfoPtr->encodingFlags & FL_SPECIALENCODING ) )\n\t\t\t{\n\t\t\t/* Since this is a CMS attribute we write it with a SET wrapper \n\t\t\t   tag rather than an OCTET STRING wrapper tag, indicated by \n\t\t\t   setting the wrapperTagSet flag to TRUE */\n\t\t\tstatus = writeAttribute( stream, \n\t\t\t\t\t\t\t\t\t ( ATTRIBUTE_LIST ** ) &attributeListPtr, \n\t\t\t\t\t\t\t\t\t TRUE, complianceLevel );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Move on to the next attribute */\n\t\tDATAPTR_SET( attributePtr, ( ATTRIBUTE_LIST * ) attributeListPtr );\n\t\tattributePtr = certMoveAttributeCursor( attributePtr, \n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, \n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\tattributeListPtr = DATAPTR_GET( attributePtr );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCertReqWrapper( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tIN const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\tIN_RANGE( 0, 4 ) const int complianceLevel )\n\t{\n\tint encapsAttributeSize, nonEncapsAttributeSize, totalAttributeSize = 0;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( complianceLevel >= CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\t\t  complianceLevel < CRYPT_COMPLIANCELEVEL_LAST );\n\n\t/* Certificate request attributes can be written in two groups, standard\n\t   attributes that apply to the request itself and attributes that \n\t   should be placed in the certificate that's created from the request,\n\t   encapsulated inside an extensionRequest attribute.  First we \n\t   determine which portion of the attributes will be encoded as is and\n\t   which will be encapsulated inside an extensionRequest */\n\tstatus = calculateAttributeSizes( attributeListPtr, TRUE,\n\t\t\t\t\t\t\t\t\t  &nonEncapsAttributeSize, \n\t\t\t\t\t\t\t\t\t  &encapsAttributeSize );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Determine the overall size of the attributes */\n\tif( encapsAttributeSize > 0 )\n\t\t{\n\t\ttotalAttributeSize += \\\n\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\tsizeofOID( OID_PKCS9_EXTREQ ) + \\\n\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofShortObject( encapsAttributeSize ) ) );\n\t\t}\n\tif( nonEncapsAttributeSize > 0 )\n\t\ttotalAttributeSize += nonEncapsAttributeSize;\n\n\t/* Write the overall wrapper for the attributes */\n\tstatus = writeConstructed( stream, totalAttributeSize, \n\t\t\t\t\t\t\t   CTAG_CR_ATTRIBUTES );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are non-encapsulated attributes present, write them first */\n\tif( nonEncapsAttributeSize > 0 ) \n\t\t{\n\t\tstatus = writeCertReqAttributes( stream, attributeListPtr, \n\t\t\t\t\t\t\t\t\t\t complianceLevel );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( encapsAttributeSize <= 0 )\n\t\t\t{\n\t\t\t/* There's nothing left to write as an encapsulated attribute, \n\t\t\t   we're done */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\t/* Write the wrapper for the remaining attributes, encapsulated inside \n\t   a PKCS #9 extensionRequest attribute */\n\twriteSequence( stream, sizeofOID( OID_PKCS9_EXTREQ ) + \\\n\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofShortObject( encapsAttributeSize ) ) );\n\tswrite( stream, OID_PKCS9_EXTREQ, sizeofOID( OID_PKCS9_EXTREQ ) );\n\twriteSet( stream, sizeofShortObject( encapsAttributeSize ) );\n\treturn( writeSequence( stream, encapsAttributeSize ) );\n\t}\n#endif /* USE_CERTREQ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Collection Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a set of attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAttributes( INOUT STREAM *stream, \n\t\t\t\t\t INOUT const DATAPTR_ATTRIBUTE attributePtr,\n\t\t\t\t\t IN_ENUM_OPT( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t IN_LENGTH const int attributeSize )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\tBOOLEAN_INT signUnrecognised DUMMY_INIT;\n\tint complianceLevel, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( attributePtr ) );\n\tREQUIRES( isEnumRangeOpt( type, CRYPT_CERTTYPE ) );\n\t\t\t  /* Single CRL, OCSP, and RTCS entries have the special-case \n\t\t\t     type CRYPT_CERTTYPE_NONE */\n\tREQUIRES( isIntegerRangeNZ( attributeSize ) );\n\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\n\t/* Some attributes have odd encoding/handling requirements that can \n\t   cause problems for other software so we only enforce peculiarities \n\t   required by some standards at higher compliance levels.  In addition \n\t   we only sign unrecognised attributes if we're explicitly asked to do \n\t   so by the user */\n\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel,\n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &signUnrecognised,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* CMS attributes work somewhat differently from normal attributes in \n\t   that, since they're encoded as a SET OF Attribute, they have to be \n\t   sorted according to their encoded form before being written.  For \n\t   this reason we don't write them sorted by OID as with the other \n\t   attributes but keep writing the next-lowest attribute until they've \n\t   all been written */\n#ifdef USE_CMSATTR\n\tif( type == CRYPT_CERTTYPE_CMS_ATTRIBUTES || \\\n\t\ttype == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\ttype == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t{\n\t\treturn( writeCmsAttributes( stream, attributeListPtr, type, \n\t\t\t\t\t\t\t\t\tattributeSize, complianceLevel ) );\n\t\t}\n#endif /* USE_CMSATTR */\n\n\t/* Write the appropriate wrapper for the extensions.  CRLs and OCSP \n\t   requests/responses have two extension types that have different \n\t   tagging, per-entry extensions and entire-CRL/request extensions.  To \n\t   differentiate between the two we write per-entry extensions with a \n\t   type of CRYPT_CERTTYPE_NONE.\n\n\t   Certificate requests also have two classes of extensions, the first\n\t   class is extensions that are meant to go into the certificare that's\n\t   created from the request (for example keyUsage, basicConstrains,\n\t   altNames) which are encapsulated inside a PKCS #9 extensionRequest \n\t   extension, and the second class is extensions that are written as\n\t   is.  To deal with this we write the as-is extensions first as part\n\t   of the wrapper write (there usually aren't any of these), and then we \n\t   write the extensions that go inside the PKCS #9 extensionRequest \n\t   (which is usually all of them) */\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\twriteConstructed( stream, sizeofShortObject( attributeSize ),\n\t\t\t\t\t\t\t  ( type == CRYPT_CERTTYPE_CERTIFICATE ) ? \\\n\t\t\t\t\t\t\t  CTAG_CE_EXTENSIONS : CTAG_CL_EXTENSIONS );\n\t\t\tstatus = writeSequence( stream, attributeSize );\n\t\t\tbreak;\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\t\tstatus = writeCertReqWrapper( stream, attributeListPtr, \n\t\t\t\t\t\t\t\t\t\t  complianceLevel );\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t/* No wrapper, extensions are written directly */\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\tcase CRYPT_CERTTYPE_NONE:\n\t\t\tstatus = writeSequence( stream, attributeSize );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\t\twriteConstructed( stream, sizeofShortObject( attributeSize ), \n\t\t\t\t\t\t\t  CTAG_OR_EXTENSIONS );\n\t\t\tstatus = writeSequence( stream, attributeSize );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\twriteConstructed( stream, sizeofShortObject( attributeSize ), \n\t\t\t\t\t\t\t  CTAG_OP_EXTENSIONS );\n\t\t\tstatus = writeSequence( stream, attributeSize );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the known attributes until we reach either the end of the list\n\t   or the first blob-type attribute */\n\tLOOP_LARGE_CHECK( cryptStatusOK( status ) && \\\n\t\t\t\t\t  attributeListPtr != NULL && \\\n\t\t\t\t\t  !checkAttributeListProperty( attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_PROPERTY_BLOBATTRIBUTE ) )\n\t\t{\n\t\tconst ATTRIBUTE_INFO *attributeInfoPtr;\n\n\t\tREQUIRES( sanityCheckAttributePtr( attributeListPtr ) );\n\t\tattributeInfoPtr = attributeListPtr->attributeInfoPtr;\n\n\t\t/* If this attribute requires special-case encoding (which in \n\t\t   practice means that it's a PKCS #10 non-encapsulated attribute) \n\t\t   then we don't write it at this point since it's already been \n\t\t   written as part of the certificate-object wrapper write */\n\t\tif( attributeInfoPtr != NULL && \\\n\t\t\t( attributeInfoPtr->encodingFlags & FL_SPECIALENCODING ) )\n\t\t\t{\n\t\t\tDATAPTR_ATTRIBUTE attributeCursor;\n\n\t\t\tDATAPTR_SET( attributeCursor, attributeListPtr );\n\t\t\tattributeCursor = certMoveAttributeCursor( attributeCursor, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeCursor );\n\t\t\tENSURES( attributeListPtr == NULL || \\\n\t\t\t\t\t sanityCheckAttributePtr( attributeListPtr ) );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tstatus = writeAttribute( stream, &attributeListPtr, FALSE, \n\t\t\t\t\t\t\t\t complianceLevel );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) || !signUnrecognised  )\n\t\treturn( status );\n\n\t/* Write the blob-type attributes */\n\tLOOP_LARGE_CHECKINC( attributeListPtr != NULL && cryptStatusOK( status ),\n\t\t\t\t\t\t attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tstatus = writeBlobAttribute( stream, attributeListPtr, FALSE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/imp_chk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Import Format-check Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* Oddball OIDs that may be used to wrap certificates */\n\n#define OID_X509_USERCERTIFICATE\tMKOID( \"\\x06\\x03\\x55\\x04\\x24\" )\n\n/* If fed an unknown object from the external source we can (with some \n   difficulty) determine its type at runtime (although it's hardly LL(1)) \n   and import it as appropriate.  If fed an object by a cryptlib-internal \n   function, the exact type will always be known.\n   \n   If the data starts with a [0] it's CMS attributes.  If it starts with a \n   sequence followed by an OID it's a certificate chain/sequence or (rarely) \n   a certificate wrapped up in some weird packaging.  If it starts with a \n   sequence followed by an integer (version = 3) it's a PKCS #12 mess.  \n   Otherwise it follows the general pattern SEQUENCE { tbsSomething, \n   signature }, and it's at this point that distinguishing the different \n   types gets tricky, with the following top-level formats being possible:\n\n\tCert:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t[0] EXPLICIT ... OPTIONAL,\n\t\t\t\t\t\t\tINTEGER,\n\t\t\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tAttribute cert:\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\tINTEGER,\n\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[1]\tName,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t}\n\n\tCRL:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\tINTEGER OPTIONAL,\n\t\t\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\tINTEGER,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\tINTEGER,\n\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[0] ... [9]\t\t-- cert request should have \n\t\t\t\t\t\t\t\t\t\t\t\t-- [6] SubjectPublicKeyInfo\n\n\tCRMF rev.req:\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t[0] ... [9]\t\t\t-- Should have [1] INTEGER \n\t\t\t\t\t\t\t\t\t\t\t\t-- (= serialNo)\n\n\tOCSP request:\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t[0] EXPLICIT ... OPTIONAL,\n\t\t\t\t\t\t\t[1]\tEXPLICIT ... OPTIONAL,\n\t\t\t\t\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- For certID, abandoned v2 also\n\t\t\t\t\t\t\t\t\t\t\t\t-- allowed [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs.\n\t\n\tOCSP resp:\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t[0] EXPLICIT ... OPTIONAL,\n\t\t\t\t\t\t\t[1] | [2] ...,\t\t-- responderID = CHOICE [1] | [2]\n\t\t\t\t\t\t\tGeneralizedTime\n\n\tRTCS request:\tSEQUENCE { SEQUENCE { \n\t\t\t\t\t\t\tSEQUENCE { \n\t\t\t\t\t\t\t\tOCTET STRING\t-- certHash\n\n\tRTCS resp:\t\tSEQUENCE { SEQUENCE \n\t\t\t\t\t\t\tOCTET STRING\t\t-- certHash\n\n\tPKI user:\t\tSEQUENCE { SEQUENCE {\t\t-- Name\n\t\t\t\t\t\t\tSET ... | empty \t-- RDN or zero-length DN\n\n   The first step is to strip out the SEQUENCE { SEQUENCE, which is shared \n   by all objects.  In addition we can remove the [0] ... OPTIONAL and\n   [1] ... OPTIONAL, which isn't useful in distinguishing anything.  Since \n   the standard OCSP response can also have [2] in place of the [1] and \n   leaving it in isn't notably useful we strip this as well.  Note that PKI \n   user information can be left in one of two states depending on whether \n   there's a DN present.  Rather than parse down into the rest of the PKI \n   user object (the next element is an AlgorithmID that clashes with a \n   certificate and CRL) we use the presence of a zero-length sequence to \n   identify a PKI user object with an absent DN.  This leaves the following:\n\n\tCert:\t\t\t\t\tINTEGER,\n\t\t\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tAttribute cert:\t\t\tINTEGER,\n\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[1]\tName,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t}\n\n\tCRL:\t\t\t\t\tINTEGER OPTIONAL,\n\t\t\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\t\t\tINTEGER,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\t\t\tINTEGER,\n\t\t\t\t\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[0] | [1] |\t-\t-- Implicitly tagged\n\t\t\t\t\t\t\t\t[3] ... [9]\t\t-- [2] stripped\n\n\tCRMF rev.req:\t\t\t[0] | [1] | -\t\t-- Implicitly tagged\n\t\t\t\t\t\t\t[3] ... [9]\t\t\t-- [2] stripped\n\n\tOCSP request:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\t\n\tOCSP resp:\t\t\t\tGeneralizedTime\n\n\tRTCS request:\t\t\tSEQUENCE { \n\t\t\t\t\t\t\t\tOCTET STRING\t-- certHash\n\n\tRTCS resp:\t\t\t\tOCTET STRING\t\t-- certHash\n\n\tPKI user:\t\t\t\tSET ...\t\t\t\t-- RDN\n\n   Next we have the INTEGER, which also isn't notably useful.  Stripping this\n   leaves:\n\n\tCert:\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tAttribute cert:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[1]\tName,\t\t-- Constructed tag\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t}\n\n\tCRL:\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[0] | [1] | -\t-- Primitive tag\n\t\t\t\t\t\t\t\t[3] ... [9]\t\t-- [2] stripped\n\n\tCRMF rev.req:\t\t\t[0] | [1] |\t-\t\t-- Primitive tag\n\t\t\t\t\t\t\t[3] ... [9]\t\t\t-- [2] stripped\n\n\tOCSP request:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\t\n\tOCSP resp:\t\t\t\tGeneralizedTime\n\n\tRTCS request:\t\t\tSEQUENCE { \n\t\t\t\t\t\t\t\tOCTET STRING\t-- certHash\n\n\tRTCS resp:\t\t\t\tOCTET STRING\t\t-- certHash\n\n\tPKI user:\t\t\t\tSET ...\t\t\t\t-- RDN\n\n   We can now immediately identify the attribute certificate by the [1] ...\n   constructed tag, a CRMF revocation request by the not-stripped [0] or [1] \n   primitive tags (implicitly tagged INTEGER) or [3]...[9] ..., an OCSP \n   response by the GeneralizedTime, an RTCS response by the OCTET STRING, \n   and the alternative PKI user variant by the SET ..., leaving:\n\n\tCert:\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCRL:\t\t\t\t\tAlgorithmID,\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[3] ... [9]\n\n\tOCSP request:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\n\tRTCS request:\t\t\tSEQUENCE { \n\t\t\t\t\t\t\t\tOCTET STRING\t-- certHash\n\n\n   Expanding the complex types for certificate, CRL, and certificate \n   request, we get:\n\n\tCert:\t\t\t\t\tSEQUENCE {\t\t\t-- AlgorithmID\n\t\t\t\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCRL:\t\t\t\t\tSEQUENCE {\t\t\t-- AlgorithmID\n\t\t\t\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\t\t\tSEQUENCE {\t\t\t-- Name\n\t\t\t\t\t\t\t\tSET {\n\t\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\t[3] ... [9]\n\n\tOCSP request:\t\t\tSEQUENCE { SEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\n\tRTCS request:\t\t\tSEQUENCE { \n\t\t\t\t\t\t\t\tOCTET STRING\t-- certHash\n\n   Stripping the first SEQUENCE { we get:\n\n\tCert:\t\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- Validity\n\t\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCRL:\t\t\t\t\t\tOBJECT IDENTIFIER,\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tName,\n\t\t\t\t\t\t\tUTCTime | GeneralizedTime\n\n\tCert request:\t\t\t\tSET {\n\t\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\tSEQUENCE {\t\t\t-- SubjectPublicKeyInfo\n\t\t\t\t\t\t\t\tAlgorithmID\n\n\tCRMF request:\t\t\t[3] ... [9]\n\n\tOCSP request:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\n\tRTCS request:\t\t\tOCTET STRING\t-- certHash\n\n   which allows us to distinguish certificates and CRLs (the two are \n   themselves distinguished by what follows the second Name), certificate  \n   requests, and RTCS requests.  What's left now are the tricky ones, the \n   other request and response types:\n\n\tCRMF request:\t\t\t[3] ... [9]\n\n\tOCSP request:\t\t\tSEQUENCE {\n\t\t\t\t\t\t\t\tSEQUENCE ...\t-- [0] | [1] | [2] | [3]\n\t\t\t\t\t\t\t\t\t\t\t\t-- for other IDs\n\n   which can themselves be distinguished by the remaining data.\n\n   Note that in practice we don't try and auto-recognise all of these \n   because some of them should never be fed to us by a user, for example a\n   CRMF revocation request and PKIUser object is only valid in the context \n   of a CMP transaction and RTCS and OCSP objects are only valid in the \n   contxt of RTCS or OCSP transactions, however we make an exception for \n   CRMF certification requests and OCSP responses because they're used in \n   the self-test */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFormat Check Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the PKCS #7/CMS wrapper that can surround a certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processCertWrapper( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *objectOffset, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *objectLength, \n\t\t\t\t\t\t\t   IN_DATALENGTH_Z const int objectStartPos )\n\t{\n\tstatic const CMS_CONTENT_INFO oidInfoSignedData = { 1, 3 };\n\tstatic const OID_INFO signedDataOIDinfo[] = {\n\t\t{ OID_CMS_SIGNEDDATA, CRYPT_OK, &oidInfoSignedData },\n\t\t{ NULL, 0 }, { NULL, 0 }\n\t\t};\n\tstatic const OID_INFO dataOIDinfo[] = {\n\t\t{ OID_CMS_DATA, CRYPT_OK, NULL },\n\t\t{ NULL, 0 }, { NULL, 0 }\n\t\t};\n\tlong length;\n\tint setLength, localLength, offset DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( objectOffset, sizeof( int ) ) );\n\tassert( isWritePtr( objectLength, sizeof( int ) ) );\n\n\tREQUIRES( objectStartPos >= 0 && objectStartPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*objectOffset = *objectLength = 0;\n\n\t/* Read the SignedData wrapper */\n\tsseek( stream, objectStartPos );\n\tstatus = readCMSheader( stream, signedDataOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( signedDataOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\tNULL, &length, READCMS_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SET OF DigestAlgorithmIdentifier, empty for a pure \n\t   certificate chain (so we use readSetZ()), nonempty for signed data or \n\t   buggy certificate chains */\n\tstatus = readSetZ( stream, &setLength );\n\tif( cryptStatusOK( status ) && setLength > 0 )\n\t\tstatus = sSkip( stream, setLength, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the ContentInfo information */\n\tstatus = readCMSheader( stream, dataOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\tNULL, &length, READCMS_FLAG_INNERHEADER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we've been fed signed data (i.e. the ContentInfo has the content \n\t   field present), skip the content to get to the certificate chain */\n\tif( length > 0 )\n\t\t{\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* If we have an indefinite length then there could be up to three \n\t\t   EOCs present (one for each of the SEQUENCE, [0], and OCTET \n\t\t   STRING), which we have to skip.  In theory there could be content\n\t\t   present as well but at that point we're going to be replicating\n\t\t   large chunks of the de-enveloping code so we only try and process\n\t\t   zero-length content, created by some buggy browser's cert-export\n\t\t   code (possibly Firefox)  */\n\t\tif( length == CRYPT_UNUSED )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\tLOOP_SMALL( i = 0, i < 3, i++ )\n\t\t\t\t{\n\t\t\t\tstatus = checkEOC( stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tif( !status )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\t}\n\n\t/* We've reached the inner content encapsulation, find out how long the \n\t   content (i.e. the chain of certificates) is */\n\tstatus = getStreamObjectLength( stream, &localLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\toffset = stell( stream );\n\t\tstatus = readConstructedI( stream, NULL, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Adjust for the [0] { ... } wrapper that contains the list of \n\t   certificate, returning a pointer to the collection of certificates\n\t   without any encapsulation */\n\tlocalLength -= stell( stream ) - offset;\n\tif( localLength < MIN_CERTSIZE || localLength >= MAX_INTLENGTH )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*objectOffset = stell( stream );\n\t*objectLength = localLength;\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Determine the object type and how long the total object is.  Note that \n   this code recognises all possible format types, even ones that have\n   been disabled, so that we can return a more useful CRYPT_ERROR_NOTAVAIL\n   rather than the generic CRYPT_ERROR_BADDATA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint getCertObjectInfo( INOUT STREAM *stream,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *objectOffset, \n\t\t\t\t\t   OUT_DATALENGTH_Z int *objectLength, \n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_TYPE *objectType,\n\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE formatHint )\n\t{\n\tstatic const MAP_TABLE minLengthMapTable[] = {\n\t\t\t\t{ CRYPT_CERTTYPE_NONE, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_CERTTYPE_CERTIFICATE, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_CERTTYPE_CERTCHAIN, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_ICERTTYPE_CMS_CERTSET, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_ICERTTYPE_SSL_CERTCHAIN, MIN_CERTSIZE },\n\t\t\t\t{ CRYPT_CERTTYPE_CRL, 64 },\n\t\t\t\t{ CRYPT_CERTTYPE_OCSP_RESPONSE, 64 },\n\t\t\t\t{ CRYPT_CERTTYPE_REQUEST_CERT, 64 },\n\t\t\t\t{ CRYPT_CERTTYPE_RTCS_REQUEST, 32 },\n\t\t\t\t{ CRYPT_CERTTYPE_RTCS_RESPONSE, 32 },\n\t\t\t\t{ CRYPT_CERTTYPE_OCSP_REQUEST, 32 },\n\t\t\t\t{ CRYPT_CERTTYPE_CERTREQUEST, 32 },\n\t\t\t\t{ CRYPT_CERTTYPE_PKIUSER, 32 },\n\t\t\t\t{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, 16 },\n\t\t\t\t{ CRYPT_CERTTYPE_REQUEST_REVOCATION, 16 },\n\t\t\t\t{ CRYPT_ICERTTYPE_REVINFO, 16 },\n\t\t\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t\t\t};\n\tBOOLEAN isContextTagged = FALSE, isLongData = FALSE;\n\tint tag, minLength, length, offset, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( objectOffset, sizeof( int ) ) );\n\tassert( isWritePtr( objectLength, sizeof( int ) ) );\n\tassert( isWritePtr( objectType, sizeof( CRYPT_CERTTYPE_TYPE ) ) );\n\n\tREQUIRES( isEnumRangeOpt( formatHint, CRYPT_CERTTYPE ) );\n\n\t/* Clear return values */\n\t*objectOffset = *objectLength = 0;\n\t*objectType = CRYPT_CERTTYPE_NONE;\n\n\t/* Figure out how much data we need to have for a minimum-length \n\t   object */\n\tstatus = mapValue( formatHint, &minLength, minLengthMapTable,\n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( minLengthMapTable, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* If it's an SSL certificate chain then there's no recognisable \n\t   tagging, however the caller will have told us what it is */\n\tif( formatHint == CRYPT_ICERTTYPE_SSL_CERTCHAIN )\n\t\t{\n\t\t*objectLength = sMemDataLeft( stream );\n\t\t*objectType = CRYPT_ICERTTYPE_SSL_CERTCHAIN;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Check whether we need to process the object wrapper using context-\n\t   specific tagging rather than the usual SEQUENCE */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == MAKE_CTAG( 0 ) || \\\n\t\tformatHint == CRYPT_ICERTTYPE_CMS_CERTSET )\n\t\tisContextTagged = TRUE;\n\n\t/* Get the object's length */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n#if INT_MAX > 32767\n\t\tlong longLength;\n\n\t\tif( status != CRYPT_ERROR_OVERFLOW )\n\t\t\treturn( status );\n\n\t\t/* CRLs can grow without bounds as more and more certificates are \n\t\t   accumulated, to handle these we have to fall back to an \n\t\t   unconstrained length read if a standard constrained length read \n\t\t   fails.  We also remember the fact that it's an exceptionally long \n\t\t   object and only allow this length if we (eventually) detect that \n\t\t   it's associated with a CRL, for anything else we return later \n\t\t   with a CRYPT_ERROR_OVERFLOW */\n\t\tsClearError( stream );\n\t\tsseek( stream, 0 );\n\t\tstatus = getLongStreamObjectLength( stream, &longLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !isIntegerRange( longLength ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tlength = ( int ) longLength;\n\t\tisLongData = TRUE;\n#else\n\t\t/* Mega-CRLs are too much for 16-bit systems */\n\t\treturn( status );\n#endif /* 16- vs. 32/64-bit systems */\n\t\t}\n\tif( length < minLength || length > MAX_INTLENGTH )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*objectLength = length;\n\toffset = stell( stream );\n\n\t/* Check that the start of the object is in order */\n\tif( isLongData )\n\t\tstatus = readLongSequence( stream, NULL );\n\telse\n\t\t{\n\t\tstatus = readConstructedI( stream, NULL, \n\t\t\t\t\t\t\t\t   isContextTagged ? 0 : DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the caller has specified that the data is in a fixed format, don't \n\t   try and recognise any other format.  This prevents security holes of \n\t   the type common in Windows software where data purportedly of type A \n\t   is auto-recognised as harmful type B and processed as such after being\n\t   passed as type A by security-checking code */\n\tif( formatHint != CRYPT_CERTTYPE_NONE )\n\t\t{\n\t\tswitch( formatHint )\n\t\t\t{\n\t\t\tcase CRYPT_ICERTTYPE_REVINFO:\n\t\t\t\t/* Single CRL entry, treated as standard CRL with portions \n\t\t\t\t   missing */\n\t\t\t\t*objectType = CRYPT_CERTTYPE_CRL;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\t\t/* If it's a certificate chain then we have to read past the\n\t\t\t\t   PKCS #7/CMS wrapper to find the chain */\n\t\t\t\tstatus = processCertWrapper( stream, objectOffset, \n\t\t\t\t\t\t\t\t\t\t\t objectLength, offset );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tSTDC_FALLTHROUGH;\n\n\t\t\tdefault:\n\t\t\t\t*objectType = formatHint;\n\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t}\n\n\t/* First we check for the easy ones, CMS attributes, which begin with a \n\t   [0] IMPLICIT SET */\n\tif( isContextTagged )\n\t\t{\n\t\t*objectType = CRYPT_CERTTYPE_CMS_ATTRIBUTES;\n\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t}\n\n\t/* See what's next */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a PKCS #7 certificate chain there'll be an object identifier \n\t   present, check the wrapper */\n\tif( tag == BER_OBJECT_IDENTIFIER )\n\t\t{\n\t\tstatus = processCertWrapper( stream, objectOffset, objectLength,\n\t\t\t\t\t\t\t\t\t offset );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*objectType = CRYPT_CERTTYPE_CERTCHAIN;\n\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t}\n\n\t/* If it's a PKCS #12 mess there'll be a version number, 3, present */\n\tif( tag == BER_INTEGER )\n\t\t{\n\t\tlong value;\n\n\t\t/* Strip off the amazing number of layers of bloat that PKCS #12 \n\t\t   lards a certificate with.  There are any number of different\n\t\t   interpretations of how to store certificates in a PKCS #12 file, \n\t\t   the following is the one that (eventually) ends up in a \n\t\t   certificate that we can read */\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value != 3 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\treadSequence( stream, NULL );\n\t\treadFixedOID( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );\n\t\treadConstructed( stream, NULL, 0 );\n\t\treadOctetStringHole( stream, NULL, 8, DEFAULT_TAG );\n\t\treadSequence( stream, NULL );\n\t\treadSequence( stream, NULL );\n\t\treadFixedOID( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );\n\t\treadConstructed( stream, NULL, 0 );\n\t\treadOctetStringHole( stream, NULL, 8, DEFAULT_TAG );\n\t\treadSequence( stream, NULL );\n\t\treadSequence( stream, NULL );\n\t\treadFixedOID( stream, \n\t\t\t\t\t  MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x0A\\x01\\x03\" ),\n\t\t\t\t\t  13 );\n\t\treadConstructed( stream, NULL, 0 );\n\t\treadSequence( stream, NULL );\n\t\treadFixedOID( stream, \n\t\t\t\t\t  MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x16\\x01\" ),\n\t\t\t\t\t  12 );\n\t\treadConstructed( stream, NULL, 0 );\n\t\tstatus = readOctetStringHole( stream, &length, 8, DEFAULT_TAG );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\toffset = stell( stream );\t/* Certificate start */\n\t\treadSequence( stream, NULL );\n\t\tstatus = readSequence( stream, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* We've finally reached the certificate, record its offset and \n\t\t   length */\n\t\t*objectOffset = offset;\n\t\t*objectLength = length;\n\t\t*objectType = CRYPT_CERTTYPE_CERTIFICATE;\n\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t}\n\n\t/* Read the inner sequence */\n\tif( isLongData )\n\t\t{\n\t\tlong longLength;\n\n\t\tstatus = readLongSequence( stream, &longLength );\n\t\tif( cryptStatusOK( status ) && longLength == CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* If it's an (invalid) indefinite-length encoding then we can't \n\t\t\t   do anything with it */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\telse\n\t\tstatus = readSequence( stream, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip optional tagged fields and the INTEGER value */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\tstatus = readUniversal( stream );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\tstatus = readUniversal( stream );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 2 ) )\n\t\tstatus = readUniversal( stream );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_INTEGER )\n\t\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we've hit a GeneralizedTime it's an OCSP response, if we've hit \n\t   a SET it's PKI user information, and if we've hit a [0] or [1] \n\t   primitive tag (implicitly tagged INTEGER) or [3]...[9] it's a CRMF \n\t   revocation request */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_TIME_GENERALIZED )\n\t\t{\n\t\t*objectType = CRYPT_CERTTYPE_OCSP_RESPONSE;\n\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* Read the next SEQUENCE.  If it's followed by an OID it's the \n\t   AlgorithmIdentifier in a certificate or CRL, if it's followed by a \n\t   SET it's the Name in a certificate request, if it's followed by a\n\t   [1] constructed tag it's an attribute certificate, and if it's \n\t   followed by a tag in the range [0]...[9] it's a horror from CRMF */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_OBJECT_IDENTIFIER )\n\t\t{\n\t\t/* Skip the AlgorithmIdentifier data and the following Name.  For a\n\t\t   certificate we now have a SEQUENCE (from the Validity), for a CRL \n\t\t   a UTCTime or GeneralizedTime */\n\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\treadUniversal( stream );\n\t\tstatus = tag = readTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( tag == BER_SEQUENCE )\n\t\t\t{\n\t\t\t*objectType = CRYPT_CERTTYPE_CERTIFICATE;\n\t\t\treturn( isLongData ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t\t}\n\t\tif( tag == BER_TIME_UTC || tag == BER_TIME_GENERALIZED )\n\t\t\t{\n\t\t\t*objectType = CRYPT_CERTTYPE_CRL;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\tif( isLongData )\n\t\t{\n\t\t/* Beyond this point we shouldn't be seeing long-length objects */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tif( tag == MAKE_CTAG( 1 ) )\n\t\t{\n\t\t*objectType = CRYPT_CERTTYPE_ATTRIBUTE_CERT;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( tag == MAKE_CTAG_PRIMITIVE( 0 ) || \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( 1 ) || \\\n\t\t( tag >= MAKE_CTAG( 2 ) && tag <= MAKE_CTAG( 9 ) ) )\n\t\t{\n\t\t*objectType = CRYPT_CERTTYPE_REQUEST_CERT;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( tag == BER_SET )\n\t\t{\n\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\treadSequence( stream, NULL );\n\t\tstatus = tag = readTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( tag == BER_OBJECT_IDENTIFIER )\n\t\t\t{\n\t\t\t*objectType = CRYPT_CERTTYPE_ATTRIBUTE_CERT;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( tag == BER_SEQUENCE )\n\t\t\t{\n\t\t\t*objectType = CRYPT_CERTTYPE_CERTREQUEST;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* It's nothing identifiable */\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/imp_exp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Import/Export Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tbase64/PEM/SMIME Processing Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_BASE64\n\n/* Decode a base64/PEM/SMIME-encoded certificate into a temporary buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int decodeCertificate( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\t\t\t\t  IN_DATALENGTH const int certObjectLength,\n\t\t\t\t\t\t\t  OUT_PTR_COND void **newObject, \n\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *newObjectLength )\n\t{\n\tvoid *decodedObjectPtr;\n\tint decodedLength, status;\n\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\tassert( isWritePtr( newObject, sizeof( void * ) ) );\n\tassert( isWritePtr( newObjectLength, sizeof( int ) ) );\n\n\tREQUIRES( certObjectLength >= MIN_CERTSIZE && \\\n\t\t\t  certObjectLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*newObject = NULL;\n\t*newObjectLength = 0;\n\n\t/* Allocate a temporary buffer to decode the certificate object data \n\t   into */\n\tstatus = base64decodeLen( certObject, certObjectLength, \n\t\t\t\t\t\t\t  &decodedLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( decodedLength < MIN_CERTSIZE || \\\n\t\tdecodedLength >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\tREQUIRES( rangeCheck( decodedLength, 1, MAX_BUFFER_SIZE ) );\n\tif( ( decodedObjectPtr = clAlloc( \"decodeCertificate\", \\\n\t\t\t\t\t\t\t\t\t  decodedLength + 8 ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t/* Decode the base64/PEM/SMIME-encoded certificate data into the \n\t   temporary buffer */\n\tstatus = base64decode( decodedObjectPtr, decodedLength, &decodedLength,\n\t\t\t\t\t\t   certObject, certObjectLength, \n\t\t\t\t\t\t   CRYPT_CERTFORMAT_TEXT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Make sure that the decoded data length is still valid.  We don't \n\t\t   allow long lengths here because we shouldn't be getting things \n\t\t   like mega-CRLs as email messages */\n\t\tif( decodedLength < MIN_CERTSIZE || \\\n\t\t\tdecodedLength >= MAX_INTLENGTH_SHORT )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"decodeCertificate\", decodedObjectPtr );\n\t\treturn( status );\n\t\t}\n\t*newObject = decodedObjectPtr;\n\t*newObjectLength = decodedLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Detect the encoded form of certificate data, either raw binary, raw\n   binary with a MIME header, or some form of text encoding.  Autodetection \n   in the presence of EBCDIC gets a bit more complicated because the text\n   content can potentially be either EBCDIC or ASCII so we have to add an\n   extra layer of checking for EBCDIC */\n\n#ifdef EBCDIC_CHARS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int checkTextEncoding( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\t\t\t\t  IN_DATALENGTH const int certObjectLength,\n\t\t\t\t\t\t\t  OUT_PTR void **newObject, \n\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *newObjectLength )\n\t{\n\tCRYPT_CERTFORMAT_TYPE format;\n\tvoid *asciiObject = NULL;\n\tint offset, status;\n\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\tassert( isWritePtr( newObject, sizeof( void * ) ) );\n\tassert( isWritePtr( newObjectLength, sizeof( int ) ) );\n\n\tREQUIRES( certObjectLength >= MIN_CERTSIZE && \\\n\t\t\t  certObjectLength < MAX_BUFFER_SIZE );\n\n\t/* Initialise the return values to the default settings, the identity\n\t   transformation */\n\t*newObject = ( void * ) certObject;\n\t*newObjectLength = certObjectLength;\n\n\t/* Check for a header that identifies some form of encoded object */\n\tstatus = base64checkHeader( certObject, certObjectLength, &format, \n\t\t\t\t\t\t\t\t&offset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tint status;\n\n\t\t/* If we get a decoding error (i.e. it's not either an unencoded \n\t\t   object or some form of ASCII encoded object) try again assuming\n\t\t   that the source is EBCDIC */\n\t\tREQUIRES( rangeCheck( certObjectLength, 1, MAX_BUFFER_SIZE ) );\n\t\tif( ( asciiObject = clAlloc( \"checkTextEncoding\",\n\t\t\t\t\t\t\t\t\t certObjectLength + 8 ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tstatus = ebcdicToAscii( asciiObject, certObject, certObjectLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertObject = asciiObject;\n\t\tstatus = base64checkHeader( certObject, certObjectLength, &format, \n\t\t\t\t\t\t\t\t\t&offset );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( format != CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && \\\n\t\t\t  format != CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) )\n\t\t\t{\n\t\t\tclFree( \"checkTextEncoding\", asciiObject );\n\t\t\tasciiObject = NULL;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If it's not encoded in any way, we're done */\n\tif( format == CRYPT_CERTFORMAT_NONE )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the length after (potentially) skipping the header is \n\t   still valid, since this will now be different from the length that \n\t   was validated by the kernel */\n\tif( certObjectLength - offset < MIN_CERTSIZE || \\\n\t\tcertObjectLength - offset >= MAX_INTLENGTH )\n\t\t{\n\t\tif( asciiObject != NULL )\n\t\t\tclFree( \"checkTextEncoding\", asciiObject );\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\tif( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE || \\\n\t\tformat == CRYPT_CERTFORMAT_TEXT_CERTIFICATE )\n\t\t{\n\t\tstatus = decodeCertificate( ( const char * ) certObject + offset, \n\t\t\t\t\t\t\t\t\tcertObjectLength - offset, newObject,\n\t\t\t\t\t\t\t\t\tnewObjectLength );\n\t\tif( asciiObject != NULL )\n\t\t\tclFree( \"checkTextEncoding\", asciiObject );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Let the caller know that they have to free the temporary decoding\n\t\t   buffer before they exit.  This is somewhat ugly but necessary for\n\t\t   the EBCDIC case because of the extra level of conversion that's \n\t\t   required before we can base64-decode it */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* If it's binary-encoded MIME data then we don't need to decode it but \n\t   still need to skip the MIME header */\n\tif( format == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\tformat == CRYPT_CERTFORMAT_CERTCHAIN )\n\t\t{\n\t\tENSURES( isIntegerRangeNZ( offset ) );\n\n\t\t*newObject = ( BYTE * ) certObject + offset;\n\t\t*newObjectLength = certObjectLength - offset;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int checkTextEncoding( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\t\t\t\t  IN_DATALENGTH const int certObjectLength,\n\t\t\t\t\t\t\t  OUT_PTR void **objectData, \n\t\t\t\t\t\t\t  OUT_DATALENGTH int *objectDataLength )\n\t{\n\tCRYPT_CERTFORMAT_TYPE format;\n\tint offset, status;\n\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\tassert( isWritePtr( objectData, sizeof( void * ) ) );\n\tassert( isWritePtr( objectDataLength, sizeof( int ) ) );\n\n\tREQUIRES( certObjectLength >= MIN_CERTSIZE && \\\n\t\t\t  certObjectLength < MAX_BUFFER_SIZE );\n\n\t/* Initialise the return values to the default settings, the identity\n\t   transformation */\n\t*objectData = ( void * ) certObject;\n\t*objectDataLength = certObjectLength;\n\n\t/* Check for a header that identifies some form of encoded object */\n\tstatus = base64checkHeader( certObject, certObjectLength, &format, \n\t\t\t\t\t\t\t\t&offset );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's not encoded in any way, we're done */\n\tif( format == CRYPT_CERTFORMAT_NONE )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the length after (potentially) skipping the header is \n\t   still valid, since this will now be different from the length that \n\t   was validated by the kernel */\n\tif( certObjectLength - offset < MIN_CERTSIZE || \\\n\t\tcertObjectLength - offset >= MAX_INTLENGTH )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t/* Remember the position of the payload, which may be either binary \n\t   (with a MIME header) or base64-encoded (with or without a header) */\n\t*objectData = ( BYTE * ) certObject + offset;\n\t*objectDataLength = certObjectLength - offset;\n\tENSURES( boundsCheckZ( offset, *objectDataLength, certObjectLength ) );\n\n\t/* It's base64-encoded let the caller know that it needs decoding */\n\treturn( ( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE || \\\n\t\t\t  format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE ) ? \\\n\t\t\tOK_SPECIAL : CRYPT_OK );\n\t}\n#endif /* EBCDIC_CHARS */\n#endif /* USE_BASE64 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tImport a Certificate\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import a certificate object.  If the import type is set to create a data-\n   only certificate then its publicKeyInfo pointer is set to the start of \n   the encoded public key to allow it to be decoded later */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint importCert( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\tIN_DATALENGTH const int certObjectLength,\n\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *certificate,\n\t\t\t\tIN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\tIN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\tIN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options,\n\t\t\t\tIN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE formatHint )\n\t{\n\tCERT_INFO *certInfoPtr;\n\tCRYPT_CERTTYPE_TYPE type, baseType;\n\tSTREAM stream;\n\tREADCERT_FUNCTION readCertFunction;\n\tBOOLEAN isDecodedObject = FALSE;\n\tvoid *certObjectPtr = ( void * ) certObject, *certBuffer;\n\tint objectLength = certObjectLength, length, offset = 0;\n\tint complianceLevel, initStatus = CRYPT_OK, status;\n\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\tassert( isWritePtr( certificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t  keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t( keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t  isReadPtrDynamic( keyID, keyIDlength ) ) );\n\n\tREQUIRES( certObjectLength >= 16 && \\\n\t\t\t  certObjectLength < MAX_BUFFER_SIZE );\n\t\t\t  /* May be CMS attribute (short) or a mega-CRL (long ) */\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t  ( isEnumRange( keyIDtype, CRYPT_KEYID ) && \\\n\t\t\t\tkeyID != NULL && \\\n\t\t\t\tkeyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\tkeyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\tREQUIRES( ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\toptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\toptions == KEYMGMT_FLAG_NONE ) || \\\n\t\t\t  ( keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\toptions != KEYMGMT_FLAG_NONE ) );\n\tREQUIRES( isEnumRangeOpt( formatHint, CRYPT_CERTTYPE ) );\n\n\t/* Clear return value */\n\t*certificate = CRYPT_ERROR;\n\n\t/* Determine how much checking we need to perform */\n\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's not a pre-specified or special-case format, check whether \n\t   it's some form of encoded certificate object and decode it if \n\t   required */\n#ifdef USE_BASE64\n\tif( formatHint == CRYPT_CERTTYPE_NONE )\n\t\t{\n\t\tstatus = checkTextEncoding( certObject, certObjectLength,\n\t\t\t\t\t\t\t\t\t&certObjectPtr, &objectLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n#ifndef EBCDIC_CHARS\n\t\t\tstatus = decodeCertificate( certObjectPtr, objectLength, \n\t\t\t\t\t\t\t\t\t\t&certObjectPtr, &objectLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n#endif /* EBCDIC_CHARS */\n\n\t\t\t/* The certificate object has been decoded into a temporary \n\t\t\t   buffer, remember that we have to free it before we exit */\n\t\t\tisDecodedObject = TRUE;\n\t\t\t}\t\t\n\t\t}\n#endif /* USE_BASE64 */\n\n\t/* Check the object's encoding unless we're running in oblivious mode \n\t   (qui omnes insidias timet in nullas incidit - Syrus).  In addition we \n\t   can't perform the check for SSL certificate chains because there's \n\t   SSL length data between each certificate, so it has to be performed \n\t   later when each certificate in the chain is read */\n#ifndef CONFIG_FUZZ\n\tif( complianceLevel > CRYPT_COMPLIANCELEVEL_OBLIVIOUS && \\\n\t\tformatHint != CRYPT_ICERTTYPE_SSL_CERTCHAIN )\n\t\t{\n\t\tstatus = checkCertObjectEncodingLength( certObjectPtr, objectLength, \n\t\t\t\t\t\t\t\t\t\t\t\t&objectLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( isDecodedObject )\n\t\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* CONFIG_FUZZ */\n\n\t/* Determine the object's type and length */\n\tsMemConnect( &stream, certObjectPtr, objectLength );\n\tstatus = getCertObjectInfo( &stream, &offset, &length, &type, \n\t\t\t\t\t\t\t\tformatHint );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( isDecodedObject )\n\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* If we're fuzzing the base64 decoding then we can exit now.  We exit \n\t   with an error code since we haven't actually created a certificate at \n\t   this point */\n#ifdef CONFIG_FUZZ\n\tif( isDecodedObject )\n\t\t{\n\t\tclFree( \"importCert\", certObjectPtr );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n#endif /* CONFIG_FUZZ */\n\n\t/* Some of the certificate types have multiple formats that are mapped \n\t   to a single base type, for example the various ways of representing\n\t   a certificate chain that all end up as a CRYPT_CERTTYPE_CERTCHAIN.\n\t   Before we continue we have to sort out what input type will end up as\n\t   which base type */\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_ICERTTYPE_CMS_CERTSET:\n\t\tcase CRYPT_ICERTTYPE_SSL_CERTCHAIN:\n\t\t\tbaseType = CRYPT_CERTTYPE_CERTCHAIN;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbaseType = type;\n\t\t\tbreak;\n\t\t}\n\n\t/* If it's a certificate chain then this is handled specially since we \n\t   need to import a plurality of certificates at once */\n\tif( baseType == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\t/* Read the certificate chain into a collection of internal \n\t\t   certificate objects.  This returns a handle to the leaf \n\t\t   certificate in the chain with the remaining certificates being \n\t\t   accessible within it via the certificate cursor functions.  \n\t\t   Because the different chain types are used only to distinguish \n\t\t   the chain wrapper type on import, the final object type which is \n\t\t   created is always a CRYPT_CERTTYPE_CERTCHAIN no matter what the \n\t\t   import format was */\n\t\tENSURES( boundsCheckZ( offset, length, objectLength ) );\n\t\tsMemConnect( &stream, ( BYTE * ) certObjectPtr + offset, length );\n\t\tstatus = readCertChain( &stream, certificate, iCryptOwner, type, \n\t\t\t\t\t\t\t\tkeyIDtype, keyID, keyIDlength, options );\n\t\tsMemDisconnect( &stream );\n\t\tif( isDecodedObject )\n\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( keyIDtype == CRYPT_KEYID_NONE && keyID == NULL && \\\n\t\t\t keyIDlength == 0 );\n\n\t/* Select the function to use to read the certificate object */\n\treadCertFunction = getCertReadFunction( baseType );\n\tif( readCertFunction == NULL )\n\t\t{\n\t\t/* In theory this should be an internal error if there's no decode \n\t\t   function corresponding to an identified certificate object type\n\t\t   present, however with the ability to selectively disable some\n\t\t   capabilities it may just correspond to a disabled capability so\n\t\t   we return a not-available error instead */\n\t\tif( isDecodedObject )\n\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\t\n\t/* Allocate a buffer to store a copy of the object so that we can \n\t   preserve the original for when it's needed again later, and try and \n\t   create the certificate object.  All of the objects (including the CMS \n\t   attributes, which in theory aren't needed for anything further) need \n\t   to be kept around in their encoded form, which is often incorrect and \n\t   therefore can't be reconstructed from the decoded information.  The \n\t   readXXX() functions also record pointers to the various required \n\t   encoded fields such as DNs and key data so that they can be recovered \n\t   later in their (possibly incorrect) form, and these pointers need to \n\t   be to a persistent copy of the encoded object.  In addition the \n\t   certificate objects need to be kept around anyway for signature \n\t   checks and possible re-export */\n\tREQUIRES( rangeCheck( length, 1, MAX_BUFFER_SIZE ) );\n\tif( ( certBuffer = clAlloc( \"importCert\", length ) ) == NULL )\n\t\t{\n\t\tif( isDecodedObject )\n\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\n\t/* Create the certificate object */\n\tstatus = createCertificateInfo( &certInfoPtr, iCryptOwner, \n\t\t\t\t\t\t( options & KEYMGMT_FLAG_CERT_AS_CERTCHAIN ) ? \\\n\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTCHAIN : baseType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( isDecodedObject )\n\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\tclFree( \"importCert\", certBuffer );\n\t\treturn( status );\n\t\t}\n\t*certificate = certInfoPtr->objectHandle;\n\n\t/* If we're doing a deferred read of the public key components (they'll\n\t   be decoded later when we know whether we need them) set the data-only\n\t   flag to ensure that we don't try to decode them */\n\tif( options & KEYMGMT_FLAG_DATAONLY_CERT )\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_DATAONLY );\n\n\t/* If we're reading a single entry from a CRL, indicate that the \n\t   resulting object is a standalone single CRL entry rather than a proper\n\t   CRL */\n\tif( formatHint == CRYPT_ICERTTYPE_REVINFO )\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_CRLENTRY );\n\n\t/* Copy in the certificate object for later use */\n\tREQUIRES( boundsCheckZ( offset, length, objectLength ) );\n\tmemcpy( certBuffer, ( BYTE * ) certObjectPtr + offset, length );\n\tcertInfoPtr->certificate = certBuffer;\n\tcertInfoPtr->certificateSize = length;\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Parse the data into the certificate object.  Note that we have to use \n\t   the copy in the certBuffer rather than the original since the \n\t   readXXX() functions will record pointers to various required encoded \n\t   fields */\n\tsMemConnect( &stream, certBuffer, length );\n\tif( baseType != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\tbaseType != CRYPT_CERTTYPE_RTCS_REQUEST && \\\n\t\tbaseType != CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t{\n\t\t/* Skip the outer wrapper */\n\t\tstatus = readLongSequence( &stream, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( isDecodedObject )\n\t\t\t\tclFree( \"importCert\", certObjectPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tstatus = readCertFunction( &stream, certInfoPtr );\n\tif( cryptStatusOK( status ) && \\\n\t\t( baseType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t  baseType == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t  baseType == CRYPT_CERTTYPE_CRL || \\\n\t\t  baseType == CRYPT_CERTTYPE_CERTREQUEST ) )\n\t\t{\n\t\tCRYPT_ALGO_TYPE dummyAlgo, hashAlgo;\n\t\tint dummyParam;\n\n\t\t/* If it's one of the standard certificate object types, check that\n\t\t   the signature information is present and valid.  This will be\n\t\t   checked explicitly anyway when the object's signature is checked,\n\t\t   but we perform at least a basic sanity check here to make sure \n\t\t   that the information is actually present since the check might\n\t\t   otherwise be skipped if the user doesn't perform an explicit\n\t\t   signature check.\n\t\t   \n\t\t   Since this is only a sanity/presence-check, we don't perform any \n\t\t   algorithm or signature-data validation (apart from the hash \n\t\t   algorithm check, see the comment below) but just verify that the \n\t\t   information is present and seems approximately valid, using the \n\t\t   code that's used in readX509Signature() in mechs/sign_rw.c.  Any \n\t\t   in-depth validation is deferred for the full signature check \n\t\t   because at this point we don't know whether the presence of (say) \n\t\t   an RSA or a DSA or an ECDSA signature is correct, or whether the \n\t\t   signature key size is appropriate, without having the signing key \n\t\t   present.\n\n\t\t   For the other object types like CMP/OCSP/RTCS requests and \n\t\t   responses we don't perform the check for the dual reasons that \n\t\t   the signatures are optional for many of the object types and that \n\t\t   if they are present they have gratuitously nonstandard formats, \n\t\t   or in some cases aren't signatures at all but things like MAC \n\t\t   values.  Since these can only be verified in the context of the\n\t\t   protocol with which they're used, we defer the checking to the\n\t\t   protocol-specific code */\n\t\tstatus = readAlgoIDex( &stream, &dummyAlgo, &hashAlgo, \n\t\t\t\t\t\t\t   &dummyParam, ALGOID_CLASS_PKCSIG );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tbaseType != CRYPT_CERTTYPE_CERTREQUEST )\n\t\t\t{\n\t\t\tconst CRYPT_ALGO_TYPE *sigHashAlgoPtr = \n#ifdef USE_CERTREV\n\t\t\t\t( baseType == CRYPT_CERTTYPE_CRL ) ? \\\n\t\t\t\t&certInfoPtr->cCertRev->hashAlgo : \n#endif /* USE_CERTREV */\n\t\t\t\t&certInfoPtr->cCertCert->hashAlgo;\n\n\t\t\t/* Make sure that the hash algorithm that's indicated inside the\n\t\t\t   signed data matches what's specified in the unauthenticed \n\t\t\t   signature metadata.  See the comment in cert.h for why we do\n\t\t\t   this.  We report a mismatch as a signature-check failure, \n\t\t\t   since it's an indication of someone messing with the \n\t\t\t   signature */\n\t\t\tif( *sigHashAlgoPtr != hashAlgo )\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\t\t\t\t\t\t\t\t\t\t   \n\t\t\tstatus = readBitStringHole( &stream, NULL, 18 + 18, \n\t\t\t\t\t\t\t\t\t\tDEFAULT_TAG ); /* Min.DLP size.size */\n\t\t\t}\n\t\t}\t\t\t\t\t\t\t\t\t\t\n\tsMemDisconnect( &stream );\n\tif( isDecodedObject )\n\t\tclFree( \"importCert\", certObjectPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The import failed, make sure that the object gets destroyed when \n\t\t   we notify the kernel that the setup process is complete.  We also\n\t\t   have to explicitly destroy the attached context since at this\n\t\t   point it hasn't been associated with the certificate yet so it\n\t\t   won't be automatically destroyed by the kernel when the \n\t\t   certificate is destroyed */\n\t\tkrnlSendNotifier( *certificate, IMESSAGE_DESTROY );\n\t\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tcertInfoPtr->iPubkeyContext = CRYPT_ERROR;\n\t\t\t}\n\t\tinitStatus = status;\n\t\t}\n\n\t/* We've finished setting up the object-type-specific information, tell \n\t   the kernel that the object is ready for use */\n\tstatus = krnlSendMessage( *certificate, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\t{\n\t\t*certificate = CRYPT_ERROR;\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\t\t}\n\n\t/* If this is a type of object that has a public key associated with it, \n\t   notify the kernel that the given context is attached to the \n\t   certificate.  Note that we can only do this at this point because the \n\t   certificate object can't receive general messages until its status is \n\t   set to OK.  In addition since this is an internal object used only by \n\t   the certificate we tell the kernel not to increment its reference \n\t   count when it attaches it to the certificate object.  Finally, we're \n\t   ready to go so we mark the object as initialised (we can't do this \n\t   before the initialisation is complete because the kernel won't \n\t   forward the message to a not-ready-for-use object)*/\n\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( *certificate, IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t\t  &certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\treturn( krnlSendMessage( *certificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tImport a Certificate\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export a certificate object.  This just writes the internal encoded \n   object data to an external buffer.  For certificate/certificate chain \n   export the possibilities are as follows:\n\n\tCert\t\t\t\tExport Type\n\tType  |\t\tCert\t\t\t\tChain\n\t------+--------------------+---------------\n\tCert  | Cert\t\t\t   | Cert as chain\n\t\t  |\t\t\t\t\t   |\n\tChain | Currently selected | Chain\n\t\t  | cert in chain\t   |\t\t\t\t\t*/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint exportCert( OUT_BUFFER_OPT( certObjectMaxLength, *certObjectLength ) \\\n\t\t\t\t\tvoid *certObject, \n\t\t\t\tIN_DATALENGTH_Z const int certObjectMaxLength, \n\t\t\t\tOUT_DATALENGTH_Z int *certObjectLength,\n\t\t\t\tIN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType,\n\t\t\t\tIN const CERT_INFO *certInfoPtr )\n\t{\n\tconst CRYPT_CERTFORMAT_TYPE baseFormatType = \\\n\t\t( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \\\n\t\t  certFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE ) ? \\\n\t\t\tCRYPT_CERTFORMAT_CERTIFICATE : \\\n\t\t( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \\\n\t\t  certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN ) ? \\\n\t\t\tCRYPT_CERTFORMAT_CERTCHAIN : \\\n\t\t\tcertFormatType;\n\tSTREAM stream;\n#ifdef USE_BASE64\n\tvoid *buffer;\n#endif /* USE_BASE64 */\n\tint length, encodedLength, status = CRYPT_ARGERROR_VALUE;\n\n\tassert( ( certObject == NULL && certObjectMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( certObject, certObjectMaxLength ) );\n\tassert( isWritePtr( certObjectLength, sizeof( int ) ) );\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( ( certObject == NULL && certObjectMaxLength == 0 ) || \\\n\t\t\t  ( certObject != NULL && \\\n\t\t\t\tcertObjectMaxLength >= MIN_CERTSIZE && \\\n\t\t\t\tcertObjectMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isEnumRange( certFormatType, CRYPT_CERTFORMAT ) );\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* If it's an internal format, write it and exit */\n\tif( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \\\n\t\tcertFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \\\n\t\tcertFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN )\n\t\t{\n\t\tstatus = length = \\\n\t\t\t\t\tsizeofCertCollection( certInfoPtr, certFormatType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES( length >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\t length < MAX_INTLENGTH );\n\t\t*certObjectLength = length;\n\t\tif( certObject == NULL )\n\t\t\treturn( CRYPT_OK );\n\t\tif( length > certObjectMaxLength )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tsMemOpen( &stream, certObject, length );\n\t\tstatus = writeCertCollection( &stream, certInfoPtr,\n\t\t\t\t\t\t\t\t\t  certFormatType );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the output object will be */\n\tlength = encodedLength = certInfoPtr->certificateSize;\n\t\t\t\t/* Placed here to get rid of not-inited warnings */\n\tif( baseFormatType == CRYPT_CERTFORMAT_CERTCHAIN )\n\t\t{\n\t\tSTREAM nullStream;\n\n\t\tENSURES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t\t certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t\tsMemNullOpen( &nullStream );\n\t\tstatus = writeCertChain( &nullStream, certInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlength = encodedLength = stell( &nullStream );\n\t\tsMemClose( &nullStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( baseFormatType != certFormatType )\n\t\t{\n#ifdef USE_BASE64 \n\t\t/* If we're exporting a certificate or certificate chain then the \n\t\t   final format will be affected by the format specifier as per \n\t\t   the table in the comment at the start of this function, so for \n\t\t   these two types the final format is defined by the format \n\t\t   specifier, not by the underlying object type */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t{\n\t\t\tstatus = base64encodeLen( length, &encodedLength, \n\t\t\t\t( baseFormatType == CRYPT_CERTFORMAT_CERTCHAIN ) ? \\\n\t\t\t\tCRYPT_CERTTYPE_CERTCHAIN : CRYPT_CERTTYPE_CERTIFICATE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = base64encodeLen( length, &encodedLength, \n\t\t\t\t\t\t\t\t\t  certInfoPtr->type );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#else\n\t\t/* If text-encoding isn't enabled then an attempt to use it is an \n\t\t   error */\n\t\treturn( CRYPT_ARGERROR_VALUE );\n#endif /* USE_BASE64 */\n\t\t}\n\n\t/* Set up the length information.  RTCS messages can be very short so we \n\t   have to use a limit below MIN_CRYPT_OBJECTSIZE */\n\tENSURES( encodedLength >= 32 && encodedLength < MAX_INTLENGTH );\n\t*certObjectLength = encodedLength;\n\tif( certObject == NULL )\n\t\treturn( CRYPT_OK );\n\tif( encodedLength > certObjectMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tif( !isWritePtrDynamic( certObject, encodedLength ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* If it's a simple format, write either the DER-encoded object data or \n\t   its base64 / S/MIME-encoded form directly to the output */\n\tif( certFormatType == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\tcertFormatType == CRYPT_ICERTFORMAT_DATA )\n\t\t{\n\t\tENSURES( length == encodedLength );\n\n\t\tREQUIRES( rangeCheck( length, 1, certObjectMaxLength ) );\n\t\tmemcpy( certObject, certInfoPtr->certificate, length );\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef USE_BASE64\n\tif( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \\\n\t\tcertFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE )\n\t\t{\n\t\treturn( base64encode( certObject, certObjectMaxLength, \n\t\t\t\t\t\t\t  certObjectLength, certInfoPtr->certificate,\n\t\t\t\t\t\t\t  certInfoPtr->certificateSize, \n\t\t\t\t\t\t\t  certInfoPtr->type ) );\n\t\t}\n#endif /* USE_BASE64 */\n\n\t/* It's a straight certificate chain, write it directly to the output */\n\tif( certFormatType == CRYPT_CERTFORMAT_CERTCHAIN )\n\t\t{\n\t\tsMemOpen( &stream, certObject, length );\n\t\tstatus = writeCertChain( &stream, certInfoPtr );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* It's a base64 / S/MIME-encoded certificate chain, write it to a \n\t   temporary buffer and then encode it to the output */\n#ifdef USE_BASE64\n\tENSURES( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \\\n\t\t\t certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN );\n\tREQUIRES( rangeCheck( length, 1, MAX_BUFFER_SIZE ) );\n\tif( ( buffer = clAlloc( \"exportCert\", length ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tsMemOpen( &stream, buffer, length );\n\tstatus = writeCertChain( &stream, certInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = base64encode( certObject, certObjectMaxLength, \n\t\t\t\t\t\t\t   certObjectLength, buffer, length, \n\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTCHAIN );\n\t\t}\n\tsMemClose( &stream );\n\tclFree( \"exportCert\", buffer );\n#endif /* USE_BASE64 */\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/read.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n#if defined( __MVS__ )\n  /* MVS control section (CSECT) names default to the file name and can't\n\t match any symbol name either in the file or in another file or library \n\t (e.g. write.c vs. write()).  Because of this we have to explicitly \n\t name the csect's so that they don't conflict with external symbol\n\t names */\n  #pragma csect( CODE, \"readC\" )\n  #pragma csect( STATIC, \"readS\" )\n  #pragma csect( TEST, \"readT\" )\n#endif /* __MVS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead Certificate Components\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return from a certificate information read after encountering an error, \n   setting the extended error information if the error was caused by invalid \n   data.  Although this isn't actually returned to the caller because the \n   certificate object isn't created, it allows more precise error diagnosis \n   for other routines */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int certErrorReturn( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t\t\tIN_ERROR const int status )\n\t{\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( errorLocus > CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t  errorLocus < CRYPT_IATTRIBUTE_LAST );\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Catch any attempts to set the error locus to internal attributes */\n\tif( errorLocus > CRYPT_ATTRIBUTE_LAST )\n\t\t{\n\t\tDEBUG_DIAG(( \"Caught attempt to set invalid error locus\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\n\tif( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_UNDERFLOW )\n\t\tsetErrorInfo( certInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_VALUE );\n\treturn( status );\n\t}\n\n/* Read version information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readVersion( INOUT STREAM *stream, \n\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\tIN_TAG const int tag,\n\t\t\t\t\t\tIN_RANGE( 1, 5 ) const int maxVersion )\n\t{\n\tlong version;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES( maxVersion >= 1 && maxVersion <= 5 );\n\n\t/* Versions can be represented in one of three ways:\n\n\t\t1. version\t\t  INTEGER\n\t\t2. version\t\t  INTEGER DEFAULT (1)\n\t\t3. version\t[tag] INTEGER DEFAULT (1)\n\n\t   To handle this we check for the required tags for versions with \n\t   DEFAULT values and exit if they're not found, setting the version to \n\t   1 first */\n\tcertInfoPtr->version = X509_V1;\n\tif( tag != DEFAULT_TAG )\n\t\t{\n\t\tint peekedTag;\n\n\t\tstatus = peekedTag = peekTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( tag == BER_INTEGER )\n\t\t\t{\n\t\t\t/* INTEGER DEFAULT (1), if we don't find this we're done */\n\t\t\tif( peekedTag != BER_INTEGER )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* [tag] INTEGER DEFAULT (1), if we don't find this we're done */\n\t\t\tif( peekedTag != MAKE_CTAG( tag ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tstatus = readConstructed( stream, NULL, tag );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* We've definitely got a version number present, process it.  Since the\n\t   version number is zero-based, we have to adjust the range check and \n\t   value we store by one to compensate for this */\n\tstatus = readShortInteger( stream, &version );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( version < 0 || version > maxVersion - 1 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tENSURES( isIntegerRange( version + 1 ) );\n\tcertInfoPtr->version = ( int ) version + 1;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a certificate serial number */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSerialNumber( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t IN_TAG const int tag )\n\t{\n\tBYTE integer[ MAX_SERIALNO_SIZE + 8 ];\n\tint integerLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Read the integer component of the serial number */\n\tstatus = readIntegerTag( stream, integer, MAX_SERIALNO_SIZE, \n\t\t\t\t\t\t\t &integerLength, tag );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Some certificates may have a serial number of zero, which is turned \n\t   into a zero-length integer by the ASN.1 read code since it truncates \n\t   leading zeroes that are added due to ASN.1 encoding requirements.  If \n\t   we get a zero-length integer we turn it into a single zero byte */\n\tif( integerLength <= 0 )\n\t\t{\n\t\tinteger[ 0 ] = 0;\n\t\tintegerLength = 1;\n\t\t}\n\n\t/* Copy the data across for the caller */\n\tstatus = setSerialNumber( certInfoPtr, integer, integerLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read DN information and remember the encoded DN data so that we can copy \n   it (complete with any encoding errors) to the issuer DN field of \n   anything that we sign */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSubjectDN( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tconst int startPos = stell( stream );\n\tBOOLEAN isNullDN = FALSE;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Full PKIX allows null DNs, which would otherwise fail all sorts \n\t\t   of sanity checks.  To identify a null DN, we need to retry the\n\t\t   read for a zero-length SEQUENCE, and if we find that, treat it as\n\t\t   a null DN */\n\t\tsClearError( stream );\n\t\tstatus = sseek( stream, startPos );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readSequenceExt( stream, &length, LENGTH_CHECK_ZERO );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( length == 0 )\n\t\t\t\t{\n\t\t\t\t/* It's an empty sequence, this is a null DN */\n\t\t\t\tlength = sizeofObject( length );\n\t\t\t\tisNullDN = TRUE;\n\t\t\t\tstatus = sseek( stream, startPos );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertInfoPtr->subjectDNsize = length;\n\t\tstatus = sMemGetDataBlock( stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t   length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( isNullDN )\n\t\t\tstatus = readUniversal( stream );\n\t\telse\n\t\t\tstatus = readDN( stream, &certInfoPtr->subjectName );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSubjectDN( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertInfoPtr->subjectDNsize = length;\n\t\tstatus = sMemGetDataBlock( stream, &certInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t   length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readDN( stream, &certInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readIssuerDN( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertInfoPtr->issuerDNsize = length;\n\t\tstatus = sMemGetDataBlock( stream, &certInfoPtr->issuerDNptr, \n\t\t\t\t\t\t\t\t   length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readDN( stream, &certInfoPtr->issuerName );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Read public-key information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKeyInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Record a reference to the public-key data */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertInfoPtr->publicKeyInfoSize = length;\n\t\tstatus = sMemGetDataBlock( stream, &certInfoPtr->publicKeyInfo, \n\t\t\t\t\t\t\t\t   length );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Import or read (for a data-only certificate) the public key \n\t   information */\n\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_DATAONLY ) )\n\t\t{\n\t\tint parameterLength DUMMY_INIT;\n\n\t\t/* We're doing deferred handling of the public key, skip it for now.\n\t\t   Because of weird tagging in things like CRMF objects we have to\n\t\t   read the information as a generic hole rather than a normal\n\t\t   SEQUENCE.\n\t\t   \n\t\t   Unlike a standard read via iCryptReadSubjectPublicKey() this\n\t\t   doesn't catch the use of too-short key parameters because we'd\n\t\t   have to duplicate most of the code that \n\t\t   iCryptReadSubjectPublicKey() calls in order to read the key\n\t\t   components, however data-only certificates are only created for \n\t\t   use in conjunction with encryption contexts so the context create \n\t\t   will catch the use of too-short parameters */\n\t\tstatus = readGenericHole( stream, NULL, 4, DEFAULT_TAG );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readAlgoIDparam( stream, &certInfoPtr->publicKeyAlgo, \n\t\t\t\t\t\t\t\t\t  &parameterLength, ALGOID_CLASS_PKC );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( parameterLength > 0 )\n\t\t\t\tsSkip( stream, parameterLength, MAX_INTLENGTH_SHORT );\n\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = iCryptReadSubjectPublicKey( stream,\n\t\t\t\t\t\t\t\t\t\t&certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\tSYSTEM_OBJECT_HANDLE, FALSE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( certInfoPtr->iPubkeyContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->publicKeyAlgo,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead Certificate Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read validity information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readValidityTime( INOUT STREAM *stream, \n\t\t\t\t\t\t\t time_t *timePtr )\n\t{\n\tint status, tag;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( timePtr, sizeof( time_t ) ) );\n\n\t/* Clear return value */\n\t*timePtr = 0;\n\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == BER_TIME_UTC )\n\t\treturn( readUTCTime( stream, timePtr ) );\n\tif( tag == BER_TIME_GENERALIZED )\n\t\treturn( readGeneralizedTime( stream, timePtr ) );\n\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readValidity( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tstatus = readSequence( stream, NULL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readValidityTime( stream, &certInfoPtr->startTime );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\tstatus = readValidityTime( stream, &certInfoPtr->endTime );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VALIDTO,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CERT_OBSOLETE \n\n/* Read a uniqueID */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readUniqueID( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( type == CRYPT_CERTINFO_ISSUERUNIQUEID || \\\n\t\t\t  type == CRYPT_CERTINFO_SUBJECTUNIQUEID );\n\n\t/* Read the length of the unique ID, allocate room for it, and read it\n\t   into the certificate */\n\tstatus = readBitStringHole( stream, &length, 1, \n\t\t\t\t\t\t\t\t( type == CRYPT_CERTINFO_ISSUERUNIQUEID ) ? \\\n\t\t\t\t\t\t\t\t\tCTAG_CE_ISSUERUNIQUEID : \\\n\t\t\t\t\t\t\t\t\tCTAG_CE_SUBJECTUNIQUEID );\n\tif( cryptStatusOK( status ) && ( length < 1 || length > 1024 ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *bufPtr;\n\n\t\tif( ( bufPtr = clDynAlloc( \"readUniqueID\", length ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tif( type == CRYPT_CERTINFO_SUBJECTUNIQUEID )\n\t\t\t{\n\t\t\tcertInfoPtr->cCertCert->subjectUniqueID = bufPtr;\n\t\t\tcertInfoPtr->cCertCert->subjectUniqueIDlength = length;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tcertInfoPtr->cCertCert->issuerUniqueID = bufPtr;\n\t\t\tcertInfoPtr->cCertCert->issuerUniqueIDlength = length;\n\t\t\t}\n\t\tstatus = sread( stream, bufPtr, length );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( certErrorReturn( certInfoPtr, type, status ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n  #define readUniqueID( stream, certInfoPtr, type )\treadUniversal( stream );\n#endif /* USE_CERT_OBSOLETE */\n\n/* Read certificate information:\n\n\tCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t  [ 0 ]\tEXPLICIT INTEGER DEFAULT(0),\n\t\tserialNumber\t\t\tINTEGER,\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tissuer\t\t\t\t\tName\n\t\tvalidity\t\t\t\tValidity,\n\t\tsubject\t\t\t\t\tName,\n\t\tsubjectPublicKeyInfo\tSubjectPublicKeyInfo,\n\t\textensions\t\t  [ 3 ]\tExtensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCertInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint length, endPos, tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the outer SEQUENCE and version number if it's present */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, CTAG_CE_VERSION, 3 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Read the serial number and signature algorithm information.  The\n\t   algorithm information was included to avert a somewhat obscure attack\n\t   where it's possible to substitute the hash algorithm specified for \n\t   the signature with a broken one, however this isn't possible because \n\t   of the way that the signature data is encoded in PKCS #1 sigs \n\t   (although it's still possible for some of the ISO signature types) or \n\t   because the (EC)DSA sigs have a different size for each hash \n\t   algorithm (SHA-1, SHA-256, SHA-384, SHA-512) so technically there's \n\t   no need to record it, however we record it because CMP uses the hash \n\t   algorithm in the certificate as an implicit indicator of the hash \n\t   algorithm that it uses for CMP messages (!!) and also just because \n\t   it's good practice to do so in case some future hash algorithm of\n\t   the same size as an existing (EC)DSA one but that's breakable turns\n\t   up */\n\tstatus = readSerialNumber( stream, certInfoPtr, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tCRYPT_ALGO_TYPE dummyAlgo;\n\t\tint dummyInt;\n\n\t\tstatus = readAlgoIDex( stream, &dummyAlgo, \n\t\t\t\t\t\t\t   &certInfoPtr->cCertCert->hashAlgo,\n\t\t\t\t\t\t\t   &dummyInt, ALGOID_CLASS_PKCSIG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the issuer name, validity information, and subject name */\n\tstatus = readIssuerDN( stream, certInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readValidity( stream, certInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readSubjectDN( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check to see whether it's a self-signed certificate */\n\tif( certInfoPtr->issuerDNsize == certInfoPtr->subjectDNsize && \\\n\t\t!memcmp( certInfoPtr->issuerDNptr, certInfoPtr->subjectDNptr,\n\t\t\t\t certInfoPtr->subjectDNsize ) )\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\n\t/* Read the public key information */\n\tstatus = readPublicKeyInfo( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the issuer and subject unique IDs if there are any present */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( CTAG_CE_ISSUERUNIQUEID ) )\n\t\t{\n\t\tstatus = readUniqueID( stream, certInfoPtr,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUERUNIQUEID );\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( CTAG_CE_SUBJECTUNIQUEID ) )\n\t\t{\n\t\tstatus = readUniqueID( stream, certInfoPtr,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTUNIQUEID );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the extensions if there are any present.  In theory we're only \n\t   supposed to accept extensions if the certificate is marked as v3\n\t   (RFC 3280 section 4.1.2.8) however this requirement doesn't serve any \n\t   useful function in that while we always mark certificates with \n\t   extensions as v3 when we create them, there's no problem introduced\n\t   by accepting extensions for any certificate version */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n\n#ifdef USE_ATTRCERT\n\n/* Read attribute certificate information.  There are two variants of this, \n   v1 attribute certificates that were pretty much never used (the fact \n   that no-one had bothered to define any attributes to be used with them\n   didn't help here) and v2 attribute certificates that are also almost\n   never used but are newer and shinier.  We read v2 certificates.  \n   \n   The original v1 attribute certificate format was:\n\n\tAttributeCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER DEFAULT(0),\n\t\towner\t\t\t  [ 1 ]\tName,\n\t\tissuer\t\t\t\t\tName,\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tserialNumber\t\t\tINTEGER,\n\t\tvalidity\t\t\t\tValidity,\n\t\tattributes\t\t\t\tSEQUENCE OF Attribute,\n\t\textensions\t\t\t\tExtensions OPTIONAL\n\t\t} \n\n   In v2 this was bloated up to:\n\n\tAttributeCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER (1),\n\t\tholder\t\t\t\t\tSEQUENCE {\n\t\t\tentityNames\t  [ 1 ]\tSEQUENCE OF {\n\t\t\t\tentityName[ 4 ]\tEXPLICIT Name\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\tissuer\t\t\t  [ 0 ]\tSEQUENCE {\n\t\t\tissuerNames\t\t\tSEQUENCE OF {\n\t\t\t\tissuerName[ 4 ]\tEXPLICIT Name\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tserialNumber\t\t\tINTEGER,\n\t\tvalidity\t\t\t\tSEQUENCE {\n\t\t\tnotBefore\t\t\tGeneralizedTime,\n\t\t\tnotAfter\t\t\tGeneralizedTime\n\t\t\t\t\t\t\t\t},\n\t\tattributes\t\t\t\tSEQUENCE OF Attribute,\n\t\textensions\t\t\t\tExtensions OPTIONAL\n\t\t} \n\n   because obviously the failure of attribute certificates in the market was \n   because they weren't complex enough the first time round */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readAttributeCertInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE dummyAlgo;\n\tint tag, length, endPos, innerEndPos, dummyInt, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the outer SEQUENCE and version number */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, BER_INTEGER, 2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Read the owner and issuer names */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tinnerEndPos = stell( stream ) + length;\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_AC_HOLDER_BASECERTIFICATEID ) )\n\t\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( checkStatusLimitsPeekTag( stream, status, tag, innerEndPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_AC_HOLDER_ENTITYNAME ) )\n\t\t{\n\t\treadConstructed( stream, NULL, CTAG_AC_HOLDER_ENTITYNAME );\n\t\tstatus = readConstructed( stream, NULL, 4 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readSubjectDN( stream, certInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( checkStatusLimitsPeekTag( stream, status, tag, innerEndPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_AC_HOLDER_OBJECTDIGESTINFO ) )\n\t\t{\n\t\t/* This is a complicated structure that in effect encodes a generic \n\t\t   hole reference to \"other\", for now we just skip it until we can\n\t\t   find an example of something that actually uses it */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readConstructed( stream, &length, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tinnerEndPos = stell( stream ) + length;\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_SEQUENCE )\n\t\t{\n\t\treadSequence( stream, NULL );\n\t\tstatus = readConstructed( stream, NULL, 4 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readIssuerDN( stream, certInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( checkStatusLimitsPeekTag( stream, status, tag, innerEndPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_AC_ISSUER_BASECERTIFICATEID ) )\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( checkStatusLimitsPeekTag( stream, status, tag, innerEndPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_AC_ISSUER_OBJECTDIGESTINFO ) )\n\t\t{\n\t\t/* See the comment for the owner objectDigectInfo above */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the signature algorithm information and remember the hash\n\t   algorithm.  See the comment in readCertInfo() for why we do this */\n\tstatus = readAlgoIDex( stream, &dummyAlgo, \n\t\t\t\t\t\t   &certInfoPtr->cCertCert->hashAlgo,\n\t\t\t\t\t\t   &dummyInt, ALGOID_CLASS_PKCSIG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the serial number and validity information */\n\tstatus = readSerialNumber( stream, certInfoPtr, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readValidity( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip the attributes for now since these aren't really defined yet */\n\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the issuer unique ID if there's one present */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_BITSTRING )\n\t\t{\n\t\tstatus = readUniqueID( stream, certInfoPtr,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUERUNIQUEID );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are no extensions present, we're done */\n\tif( stell( stream ) >= endPos )\n\t\treturn( CRYPT_OK );\n\n\t/* Read the extensions */\n\treturn( readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_ATTRIBUTE_CERT, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType ) );\n\t}\n#endif /* USE_ATTRCERT */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead CRL Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Read CRL information:\n\n\tCRLInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER DEFAULT(0),\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tissuer\t\t\t\t\tName,\n\t\tthisUpdate\t\t\t\tUTCTime,\n\t\tnextUpdate\t\t\t\tUTCTime OPTIONAL,\n\t\trevokedCertificates\t\tSEQUENCE OF RevokedCerts,\n\t\textensions\t\t  [ 0 ]\tExtensions OPTIONAL\n\t\t}\n\n   We read various lengths as long values since CRLs can get quite large */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCRLInfo( INOUT STREAM *stream, \n\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE dummyAlgo;\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tlong length, endPos;\n\tint tag, dummyInt, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* If it's a standalone CRL entry, read the single entry and return */\n\tif( TEST_FLAG( certInfoPtr->flags, CERT_FLAG_CRLENTRY ) )\n\t\t{\n\t\treturn( readCRLentry( stream, &certRevInfo->revocations, 1,\n\t\t\t\t\t\t\t  &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t  &certInfoPtr->errorType ) );\n\t\t}\n\n\t/* Read the outer SEQUENCE and version number if it's present */\n\tstatus = readLongSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length == CRYPT_UNUSED )\n\t\t{\n\t\t/* If it's an (invalid) indefinite-length encoding \n\t\t   (readLongSequence() also accepts those) then we can't do anything \n\t\t   with it */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, BER_INTEGER, 2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Read the signature algorithm information and remember the hash\n\t   algorithm.  See the comment in readCertInfo() for why we do this */\n\tstatus = readAlgoIDex( stream, &dummyAlgo, \n\t\t\t\t\t\t   &certInfoPtr->cCertRev->hashAlgo,\n\t\t\t\t\t\t   &dummyInt, ALGOID_CLASS_PKCSIG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the issuer name, update time, and optional next update time */\n\tstatus = readIssuerDN( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readUTCTime( stream, &certInfoPtr->startTime );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_THISUPDATE,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_TIME_UTC )\n\t\t{\n\t\tstatus = readUTCTime( stream, &certInfoPtr->endTime );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_NEXTUPDATE,\n\t\t\t\t\t\t\t\t\t status ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* Read the SEQUENCE OF revoked certificates and make the currently \n\t   selected one the start of the list.  Since the set of revoked\n\t   certificates may be empty, we need to check for the presence of the\n\t   SEQUENCE tag before we try and read it */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_SEQUENCE )\n\t\t{\n\t\tstatus = readCRLentries( stream, &certRevInfo->revocations,\n\t\t\t\t\t\t\t\t &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertRevInfo->currentRevocation = certRevInfo->revocations;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* Read the extensions if there are any present.  In theory we're only \n\t   supposed to accept extensions if the CRL is marked as v2 (RFC 3280\n\t   section 5.1.2.7), but see the comment in readCertInfo() for why we\n\t   read them unconditionally */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_CRL, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Certificate Request Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREQ\n\n/* Read validity information.  Despite being a post-Y2K standard, CRMF still\n   allows the non-Y2K UTCTime format to be used for dates so we have to \n   accomodate both date types.  In addition both values are optional so we\n   only try and read them if we see their tags */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCrmfValidity( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tstatus = readConstructed( stream, NULL, CTAG_CF_VALIDITY );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\treadConstructed( stream, NULL, 0 );\n\t\tstatus = readValidityTime( stream, &certInfoPtr->startTime );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t status ) );\n\t\t\t}\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\t{\n\t\treadConstructed( stream, NULL, 1 );\n\t\tstatus = readValidityTime( stream, &certInfoPtr->endTime );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VALIDTO,\n\t\t\t\t\t\t\t\t\t status ) );\n\t\t\t}\n\t\t}\n\treturn( cryptStatusError( status ) ? status : CRYPT_OK );\n\t}\t\t/* checkStatusPeekTag() can return tag as status */\n\n/* CRMF requests can include a large amount of unnecessary junk that no-one \n   (including the RFC authors, when asked) can explain and the semantics of \n   which are at best undefined (version) and at worst dangerous \n   (serialNumber).  The best way to deal with them on the off chance that \n   the client has specified them is to skip the unneeded information until \n   we get to something that we can use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int skipCrmfJunk( INOUT STREAM *stream,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int endPos,\n\t\t\t\t\t\t IN_TAG_ENCODED const int terminatorTag,\n\t\t\t\t\t\t IN_TAG_ENCODED const int optTerminatorTag1,\n\t\t\t\t\t\t IN_TAG_ENCODED const int optTerminatorTag2 )\n\t{\n\tint fieldsProcessed, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isIntegerRangeNZ( endPos ) );\n\t\t\t  /* See the comment below for why we check for MAX_INTLENGTH\n\t\t\t\t rather than MAX_INTLENGTH_SHORT */\n\tREQUIRES( terminatorTag > 0 && terminatorTag <= MAX_TAG );\n\tREQUIRES( ( optTerminatorTag1 == NO_TAG ) || \\\n\t\t\t  ( optTerminatorTag1 > 0 && optTerminatorTag1 <= MAX_TAG ) );\n\tREQUIRES( ( optTerminatorTag2 == NO_TAG ) || \\\n\t\t\t  ( optTerminatorTag2 > 0 && optTerminatorTag2 <= MAX_TAG ) );\n\n\t/* If we've been given an end position that doesn't make sense, don't \n\t   try and go any further.  This saves having to perform the check in\n\t   every higher-level function that calls us.  From now on we can \n\t   guarantee that the length is no greater than MAX_INTLENGTH_SHORT \n\t   rather than the more generic MAX_INTLENGTH that's checked for in the \n\t   precondition check above */\n\tif( !isShortIntegerRangeNZ( endPos ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Skip any junk until we get to a field that we're interested in */\n\tLOOP_SMALL( fieldsProcessed = 0,\n\t\t\t\tstell( stream ) < endPos - MIN_ATTRIBUTE_SIZE && \\\n\t\t\t\t\tfieldsProcessed < 8, \n\t\t\t\tfieldsProcessed++ )\n\t\t{\n\t\tint tag, status;\n\n\t\t/* Check whether we've reached any of the requested terminator \n\t\t   tags */\n\t\tstatus = tag = peekTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( tag == terminatorTag )\n\t\t\tbreak;\n\t\tif( optTerminatorTag1 != NO_TAG && tag == optTerminatorTag1 )\n\t\t\tbreak;\n\t\tif( optTerminatorTag2 != NO_TAG && tag == optTerminatorTag2 )\n\t\t\tbreak;\n\n\t\t/* Skip this item */\n\t\tstatus = readUniversal( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( fieldsProcessed >= 8 )\n\t\t{\n\t\t/* We should have hit something useful by this point */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read certificate request information:\n\n\tCertificationRequestInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER (0),\n\t\tsubject\t\t\t\t\tName,\n\t\tsubjectPublicKeyInfo\tSubjectPublicKeyInfo,\n\t\tattributes\t\t  [ 0 ]\tSET OF Attribute\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCertRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr )\n\t{\n\tlong endPos;\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Skip the outer SEQUENCE and read the version number */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, DEFAULT_TAG, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Read the subject name and public key information */\n\tstatus = readSubjectDN( stream, certInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readPublicKeyInfo( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the attributes.  Since these can be zero-length due to an error\n\t   in the ASN.1 which makes them mandatory, we use readConstructedZ() \n\t   rather than readConstructed() to allow this */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CR_ATTRIBUTES ) )\n\t\t{\n\t\tstatus = readConstructedZ( stream, &length, CTAG_CR_ATTRIBUTES );\n\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t{\n\t\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTREQUEST, length,\n\t\t\t\t\t\t\t\t\t &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Certification requests are always self-signed */\n\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n\n/* Read CRMF certificate request information:\n\n\tCertReq ::= SEQUENCE {\n\t\tcertReqID\t\t\t\tINTEGER (0),\n\t\tcertTemplate\t\t\tSEQUENCE {\n\t\t\tvalidity\t  [ 4 ]\tSEQUENCE {\n\t\t\t\tvalidFrom [ 0 ]\tEXPLICIT GeneralizedTime OPTIONAL,\n\t\t\t\tvalidTo\t  [ 1 ] EXPLICIT GeneralizedTime OPTIONAL\n\t\t\t\t} OPTIONAL,\n\t\t\tsubject\t\t  [ 5 ]\tEXPLICIT Name OPTIONAL,\n\t\t\tpublicKey\t  [ 6 ]\tSubjectPublicKeyInfo,\n\t\t\textensions\t  [ 9 ]\tSET OF Attribute OPTIONAL\n\t\t\t}\n\t\t} \n\n   We enforce the requirement that the request must contain at least a \n   subject DN and a public key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCrmfRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr )\n\t{\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Skip the outer SEQUENCE, request ID, and inner SEQUENCE */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\treadUniversal( stream );\n\tstatus = readSequence( stream, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip any junk before the Validity, SubjectName, or\n\t   SubjectPublicKeyInfo */\n\tstatus = skipCrmfJunk( stream, endPos, \n\t\t\t\t\t\t   MAKE_CTAG( CTAG_CF_VALIDITY ),\n\t\t\t\t\t\t   MAKE_CTAG( CTAG_CF_SUBJECT ), \n\t\t\t\t\t\t   MAKE_CTAG( CTAG_CF_PUBLICKEY ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there's validity data present, read it */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CF_VALIDITY ) )\n\t\t{\n\t\tstatus = readCrmfValidity( stream, certInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there's a subject name present, read it */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CF_SUBJECT ) )\n\t\t{\n\t\tstatus = readConstructed( stream, NULL, CTAG_CF_SUBJECT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readSubjectDN( stream, certInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the public key information.  CRMF uses yet more nonstandard \n\t   tagging for the public key, in theory we'd have to read it with the \n\t   CTAG_CF_PUBLICKEY tag instead of the default SEQUENCE, however the \n\t   public-key-read code reads the SPKI encapsulation as a generic hole \n\t   to handle this so there's no need for any special handling */\n\tif( peekTag( stream ) != MAKE_CTAG( CTAG_CF_PUBLICKEY ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, \n\t\t\t\t\t\t\t\t CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tstatus = readPublicKeyInfo( stream, certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, status ) );\n\t\t}\n\n\t/* Read the attributes */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )\n\t\t{\n\t\tstatus = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );\n\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t{\n\t\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT, length,\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Fix up any problems in attributes */\n\tstatus = fixAttributes( certInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* The request may contain additional data that doesn't apply to the\n\t   request itself but to the management of the request by CMP (which \n\t   means that it should actually be part of the management protocol and \n\t   not the request data but CMP muddles things up quite thoroughly, \n\t   including encoding CMP protocol data inside fields in the issuer \n\t   certificate(!!)).  Because we can't do anything with this \n\t   information, we just skip it if it's present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readUniversal( stream );\t/* Skip request management information */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* CRMF requests are usually self-signed, however if they've been\n\t   generated with an encryption-only key then the place of the signature\n\t   is taken by one of a number of magic values which indicate that no\n\t   signature is present and that something else needs to be done to\n\t   verify that the sender has the private key */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttag = EXTRACT_CTAG( tag );\n\tif( tag == CTAG_CF_POP_SIGNATURE )\n\t\t{\n\t\t/* It's a signature, the request is self-signed */\n\t\tSET_FLAG( certInfoPtr->flags, CERT_FLAG_SELFSIGNED );\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's neither a signature nor an indication that private-key \n\t\t   POP will be performed by returning the certificate in encrypted \n\t\t   form then we can't do anything with it */\n\t\tif( tag != CTAG_CF_POP_ENCRKEY )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\treturn( readConstructed( stream, NULL, EXTRACT_CTAG( tag ) ) );\n\t}\n\n/* Read CRMF revocation request information:\n\n\tRevDetails ::= SEQUENCE {\n\t\tcertTemplate\t\t\tSEQUENCE {\n\t\t\tserialNumber  [ 1 ]\tINTEGER,\n\t\t\tissuer\t\t  [ 3 ]\tEXPLICIT Name,\n\t\t\t},\n\t\tcrlEntryDetails\t\t\tSET OF Attribute\n\t\t}\n\n   We enforce the requirement that the request must contain at least an \n   issuer DN and a serial number */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRevRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT CERT_INFO *certInfoPtr )\n\t{\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Find out how much certificate template is present */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Skip any junk before the serial number and read the serial number */\n\tstatus = skipCrmfJunk( stream, endPos, \n\t\t\t\t\t\t   MAKE_CTAG_PRIMITIVE( CTAG_CF_SERIALNUMBER ), \n\t\t\t\t\t\t   NO_TAG, NO_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readSerialNumber( stream, certInfoPtr,\n\t\t\t\t\t\t\t\t   CTAG_CF_SERIALNUMBER );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip any further junk before the issuer name and read the issuer \n\t   name.  We don't actually care about the contents of the DN but we \n\t   have to decode it anyway in case the caller wants to view it */\n\tstatus = skipCrmfJunk( stream, endPos, MAKE_CTAG( CTAG_CF_ISSUER ),\n\t\t\t\t\t\t   NO_TAG, NO_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readConstructed( stream, NULL, CTAG_CF_ISSUER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readIssuerDN( stream, certInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip any additional junk that may be present in the template, \n\t   stopping if we get to the request attributes */\n\tstatus = skipCrmfJunk( stream, endPos, MAKE_CTAG( CTAG_CF_EXTENSIONS ),\n\t\t\t\t\t\t   NO_TAG, NO_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the attributes */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CF_EXTENSIONS ) )\n\t\t{\n\t\tstatus = readConstructed( stream, &length, CTAG_CF_EXTENSIONS );\n\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t{\n\t\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_REQUEST_REVOCATION,\n\t\t\t\t\t\t\t\t\t length, &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n#endif /* USE_CERTREQ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Validity-checking Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTVAL\n\n/* Read an RTCS request:\n\n\tRTCSRequests ::= SEQUENCE {\n\t\tSEQUENCE OF \n\t\t\tSEQUENCE {\n\t\t\t\tcertHash\tOCTET STRING SIZE(20)\n\t\t\t\t},\n\t\tattributes\t\tAttributes OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRtcsRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\tint length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the outer wrapper */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the request information and make the currently selected one the \n\t   start of the list */\n\tstatus = readRTCSRequestEntries( stream, &certValInfo->validityInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcertValInfo->currentValidity = certValInfo->validityInfo;\n\n\t/* Read the extensions if there are any present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_RTCS_REQUEST, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n\n/* Read an RTCS response:\n\n\tRTCSResponses ::= SEQUENCE OF \n\t\tSEQUENCE {\n\t\t\tcertHash\tOCTET STRING SIZE(20),\n\t\t\tstatus\t\tBOOLEAN\n\t\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRtcsResponseInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the SEQUENCE OF validity information and make the currently \n\t   selected one the start of the list */\n\tstatus = readRTCSResponseEntries( stream, &certValInfo->validityInfo,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcertValInfo->currentValidity = certValInfo->validityInfo;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Revocation-checking Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Read an OCSP request:\n\n\tOCSPRequest ::= SEQUENCE {\t\t\t\t-- Write, v1\n\t\tversion\t\t[0]\tEXPLICIT INTEGER DEFAULT(0),\n\t\treqName\t\t[1]\tEXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,\n\t\treqList\t\t\tSEQUENCE OF SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- certID\n\t\t\thashAlgo\tAlgorithmIdentifier,\n\t\t\tiNameHash\tOCTET STRING,\n\t\t\tiKeyHash\tOCTET STRING,\n\t\t\tserialNo\tINTEGER\n\t\t\t} }\n\t\t}\n\n\tOCSPRequest ::= SEQUENCE {\t\t\t\t-- Write, v2\n\t\tversion\t\t[0]\tEXPLICIT INTEGER (1),\n\t\treqName\t\t[1]\tEXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,\n\t\treqList\t\t\tSEQUENCE OF SEQUENCE {\n\t\t\tcertID\t[2]\tEXPLICIT OCTET STRING\t-- Certificate hash\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readOcspRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the wrapper and version information */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, CTAG_OR_VERSION, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Skip the optional requestor name */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_OR_DUMMY ) )\n\t\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SEQUENCE OF revocation information and make the currently \n\t   selected one the start of the list */\n\tstatus = readOcspRequestEntries( stream, &certRevInfo->revocations,\n\t\t\t\t\t\t\t\t\t &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcertRevInfo->currentRevocation = certRevInfo->revocations;\n\n\t/* Read the extensions if there are any present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_OCSP_REQUEST, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Fix up any problems in attributes */\n\treturn( fixAttributes( certInfoPtr ) );\n\t}\n\n/* Read an OCSP response:\n\n\tOCSPResponse ::= SEQUENCE {\n\t\tversion\t\t[0]\tEXPLICIT INTEGER DEFAULT (0),\n\t\trespID\t\t[1]\tEXPLICIT Name,\n\t\tproducedAt\t\tGeneralizedTime,\n\t\tresponses\t\tSEQUENCE OF Response\n\t\texts\t\t[1]\tEXPLICIT Extensions OPTIONAL,\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readOcspResponseInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CERT_INFO *certInfoPtr )\n\t{\n\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\n\t/* Read the wrapper and version information */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readVersion( stream, certInfoPtr, CTAG_OP_VERSION, 2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,\n\t\t\t\t\t\t\t\t status ) );\n\t\t}\n\n\t/* Read the responder ID and produced-at time value */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\t{\n\t\t/* It's a DN, read it as the issuer name in case the caller is\n\t\t   interested in it */\n\t\tstatus = readConstructed( stream, NULL, 1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readIssuerDN( stream, certInfoPtr );\n\t\t}\n\telse\n\t\t{\n\t\t/* We can't do much with a key hash, in any case all current\n\t\t   responders use the issuer DN to identify the responder so\n\t\t   this shouldn't be much of a problem */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readGeneralizedTime( stream, &certInfoPtr->startTime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the SEQUENCE OF revocation information and make the currently \n\t   selected one the start of the list */\n\tstatus = readOcspResponseEntries( stream, &certRevInfo->revocations,\n\t\t\t\t\t\t\t\t\t  &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t\t\t  &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcertRevInfo->currentRevocation = certRevInfo->revocations;\n\n\t/* Read the extensions if there are any present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readAttributes( stream, &certInfoPtr->attributes,\n\t\t\t\t\t\tCRYPT_CERTTYPE_OCSP_RESPONSE, endPos - stell( stream ),\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\t\t}\n\n\t/* In theory some OCSP responses can be sort of self-signed via attached\n\t   certificates but there are so many incompatible ways to delegate \n\t   trust and signing authority mentioned in the RFC (one for each vendor\n\t   that contributed and an additional catchall in case any option got \n\t   missed) without any indication of which one implementors will follow \n\t   that we require the user to supply the signature check certificate \n\t   rather than assuming that some particular trust delegation mechanism \n\t   will happen to be in place */\n/*\tcertInfoPtr->flags |= CERT_FLAG_SELFSIGNED; */\n\n\treturn( status );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead CMS Attribute Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CMSATTR\n\n/* Read CMS attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCmsAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CERT_INFO *attributeInfoPtr )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributeInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( attributeInfoPtr ) );\n\n\t/* CMS attributes are straight attribute objects so we just pass the call\n\t   through.  In addition since there's no encapsulation we specify a\n\t   special-case length of 0 to mean \"whatever's there\" */\n\treturn( readAttributes( stream, &attributeInfoPtr->attributes,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_CMS_ATTRIBUTES, 0,\n\t\t\t\t\t\t\t&attributeInfoPtr->errorLocus,\n\t\t\t\t\t\t\t&attributeInfoPtr->errorType ) );\n\t}\n#endif /* USE_CMSATTR */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKI User Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKIUSER\n\n/* Read PKI user information:\n\n\tuserData ::= SEQUENCE {\n\t\tname\t\t\t\tName,\t\t\t-- Name for CMP\n\t\tencAlgo\t\t\t\tAlgorithmIdentifier,-- Algo to encrypt passwords\n\t\tencPW\t\t\t\tOCTET STRING,\t-- Encrypted passwords\n\t\tcertAttributes\t\tAttributes\t\t-- Certificate attributes\n\t\tuserAttributes\t\tSEQUENCE {\t\t-- PKI user attributes\n\t\t\tisRA\t\t\tBOOLEAN OPTIONAL -- Whether user is an RA\n\t\t\t} OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPkiUserInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT CERT_INFO *userInfoPtr )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tCERT_PKIUSER_INFO *certUserInfo = userInfoPtr->cCertUser;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tDATAPTR_ATTRIBUTE attributeCursor;\n\tMESSAGE_DATA msgData;\n\tQUERY_INFO queryInfo;\n\tSTREAM userInfoStream;\n\tATTRIBUTE_ENUM_INFO attrEnumInfo;\n\tBYTE userInfo[ 128 + 8 ];\n\tint userInfoSize DUMMY_INIT, length;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( userInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( userInfoPtr ) );\n\n\t/* Read the user name, encryption algorithm information, and the start \n\t   of the encrypted data */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tuserInfoPtr->subjectDNsize = length;\n\t\tstatus = sMemGetDataBlock( stream, &userInfoPtr->subjectDNptr, \n\t\t\t\t\t\t\t\t   length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readDN( stream, &userInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readContextAlgoID( stream, NULL, &queryInfo, DEFAULT_TAG,\n\t\t\t\t\t\t\t\tALGOID_CLASS_CRYPT );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readOctetString( stream, userInfo, &userInfoSize, 8, 128 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( userInfoSize != PKIUSER_ENCR_AUTHENTICATOR_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Clone the CA data storage key for our own use, load the IV from the \n\t   encryption information, and use the cloned context to decrypt the \n\t   user information.  We need to do this to prevent problems if multiple \n\t   threads try to simultaneously decrypt with the CA data storage key.  \n\t   See the comment in write.c for the use of the fixed interop key \n\t   rather than actually using a clone of the CA data storage key as the \n\t   comment would imply */\n\tswitch( queryInfo.cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_AES:\n\t\t\tsetMessageData( &msgData, \"interop interop \", 16 );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_3DES:\n\t\t\tsetMessageData( &msgData, \"interop interop interop \", 24 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tsetMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, queryInfo.iv, queryInfo.ivLength );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t  userInfo, userInfoSize );\n\t\t}\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the user information.  If we get a bad data error at this point \n\t   we report it as a wrong decryption key rather than bad data since \n\t   it's more likely to be the former */\n\tsMemConnect( &userInfoStream, userInfo, userInfoSize );\n\treadSequence( &userInfoStream, NULL );\n\treadOctetString( &userInfoStream, certUserInfo->pkiIssuePW, &length,\n\t\t\t\t\t PKIUSER_AUTHENTICATOR_SIZE, PKIUSER_AUTHENTICATOR_SIZE );\n\tstatus = readOctetString( &userInfoStream, certUserInfo->pkiRevPW,\n\t\t\t\t\t\t\t  &length, PKIUSER_AUTHENTICATOR_SIZE, \n\t\t\t\t\t\t\t  PKIUSER_AUTHENTICATOR_SIZE );\n\tsMemDisconnect( &userInfoStream );\n\tzeroise( userInfo, userInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t/* Read any attributes */\n\tstatus = readAttributes( stream, &userInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_PKIUSER, sMemDataLeft( stream ),\n\t\t\t\t\t\t\t &userInfoPtr->errorLocus,\n\t\t\t\t\t\t\t &userInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sMemDataLeft( stream ) > 3 )\n\t\t{\n\t\tint tag;\n\n\t\tstatus = readSequence( stream, NULL );\n\t\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\ttag == BER_BOOLEAN )\n\t\t\tstatus = readBoolean( stream, &certUserInfo->isRA );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* As used by cryptlib the PKI user information is applied as a template \n\t   to certificates to modify their contents before issue.  This is done \n\t   by merging the user information with the certificate before it's \n\t   issued.  Since there can be overlapping or conflicting attributes in \n\t   the two objects, the ones in the PKI user information are marked as \n\t   locked to ensure that they override any conflicting attributes that \n\t   may be present in the certificate */\n\tLOOP_MAX( attributeCursor = getFirstAttribute( &attrEnumInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t   userInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t\t\t   ATTRIBUTE_ENUM_NONBLOB ), \n\t\t\t  DATAPTR_ISSET( attributeCursor ),\n\t\t\t  attributeCursor = getNextAttribute( &attrEnumInfo ) )\n\t\t{\n\t\tsetAttributeProperty( attributeCursor, \n\t\t\t\t\t\t\t  ATTRIBUTE_PROPERTY_LOCKED, 0 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKIUSER */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Function Access Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst CRYPT_CERTTYPE_TYPE type;\n\tconst READCERT_FUNCTION function;\n\t} CERTREAD_INFO;\nstatic const CERTREAD_INFO certReadTable[] = {\n\t{ CRYPT_CERTTYPE_CERTIFICATE, readCertInfo },\n#ifdef USE_ATTRCERT\n\t{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, readAttributeCertInfo },\n#endif /* USE_ATTRCERT */\n#ifdef USE_CERTREV\n\t{ CRYPT_CERTTYPE_CRL, readCRLInfo },\n#endif /* USE_CERTREV */\n#ifdef USE_CERTREQ\n\t{ CRYPT_CERTTYPE_CERTREQUEST, readCertRequestInfo },\n\t{ CRYPT_CERTTYPE_REQUEST_CERT, readCrmfRequestInfo },\n\t{ CRYPT_CERTTYPE_REQUEST_REVOCATION, readRevRequestInfo },\n#endif /* USE_CERTREQ */\n#ifdef USE_CERTVAL\n\t{ CRYPT_CERTTYPE_RTCS_REQUEST, readRtcsRequestInfo },\n\t{ CRYPT_CERTTYPE_RTCS_RESPONSE, readRtcsResponseInfo },\n#endif /* USE_CERTVAL */\n#ifdef USE_CERTREV\n\t{ CRYPT_CERTTYPE_OCSP_REQUEST, readOcspRequestInfo },\n\t{ CRYPT_CERTTYPE_OCSP_RESPONSE, readOcspResponseInfo },\n#endif /* USE_CERTREV */\n#ifdef USE_CMSATTR\n\t{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, readCmsAttributes },\n#endif /* USE_CMSATTR */\n#ifdef USE_PKIUSER\n\t{ CRYPT_CERTTYPE_PKIUSER, readPkiUserInfo },\n#endif /* USE_PKIUSER */\n\t{ CRYPT_CERTTYPE_NONE, NULL }, { CRYPT_CERTTYPE_NONE, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nREADCERT_FUNCTION getCertReadFunction( IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( certType, CRYPT_CERTTYPE ) );\n\n\tLOOP_MED( i = 0,\n\t\t\t  certReadTable[ i ].type != CRYPT_CERTTYPE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( certReadTable, CERTREAD_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( certReadTable[ i ].type == certType )\n\t\t\treturn( certReadTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( certReadTable, CERTREAD_INFO ) );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/trustmgr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Certificate Trust Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following code is actually part of the user rather than certificate\n   routines but it pertains to certificates so we include it here.  Trust\n   information mutex handling is done in the user object so there are no \n   mutexes required here.\n\n   The interpretation of what represents a \"trusted certificate\" is somewhat \n   complex and open-ended, it's not clear whether what's being trusted is \n   the key in the certificate, the certificate, or the owner of the \n   certificate (corresponding to subjectKeyIdentifier, issuerAndSerialNumber/\n   certHash, or subject DN).  The generally accepted form is to trust the \n   subject so we check for this in the certificate.  The modification for \n   trusting the key is fairly simple to make if required.\n   \n   Since the trust data sits in memory for extended periods of time, we're\n   especially careful to defend against memory corruption issues */\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"trustmgr_int.h\"\n  #include \"trustmgr.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"cert/trustmgr_int.h\"\n  #include \"cert/trustmgr.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check trust information */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckTrustInfo( const TRUST_INFO *trustInfo )\n\t{\n\tassert( isReadPtr( trustInfo, sizeof( TRUST_INFO ) ) );\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( trustInfo->certObject ) || \\\n\t\t!DATAPTR_ISVALID( trustInfo->next ) || \\\n\t\t!DATAPTR_ISVALID( trustInfo->prev ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckTrustInfo: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check certificate data */\n\tif( trustInfo->iCryptCert != CRYPT_ERROR && \\\n\t\t!isHandleRangeValid( trustInfo->iCryptCert ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckTrustInfo: Certificate object\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( DATAPTR_ISSET( trustInfo->certObject ) )\n\t\t{\n\t\tconst void *certObjectPtr;\n\n\t\tcertObjectPtr = DATAPTR_GET( trustInfo->certObject );\n\t\tENSURES( certObjectPtr != NULL );\n\n\t\tif( trustInfo->certObjectLength < MIN_CERTSIZE || \\\n\t\t\ttrustInfo->certObjectLength >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckTrustInfo: Certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( checksumData( certObjectPtr, \\\n\t\t\t\t\t\t  trustInfo->certObjectLength ) != trustInfo->certChecksum )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckTrustInfo: Certificate data corruption\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !DATAPTR_ISNULL( trustInfo->certObject ) || \\\n\t\t\ttrustInfo->certObjectLength != 0 || \\\n\t\t\ttrustInfo->certChecksum != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckTrustInfo: Spurious certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Get a pointer to the trust information from a generic DATAPTR after \n   checking that it's valid */\n\nCHECK_RETVAL_PTR \\\nstatic DATAPTR *getCheckTrustInfo( IN const DATAPTR trustInfo )\n\t{\n\tTRUST_INFO_CONTAINER *trustInfoContainer;\n\n\t/* Get a pointer to the trust information */\n\ttrustInfoContainer = DATAPTR_GET( trustInfo );\n\tENSURES_N( trustInfoContainer != NULL );\n\n\t/* Make sure that it's valid */\n\tif( checksumData( trustInfoContainer->trustInfo, \n\t\t\t\t\t  sizeof( DATAPTR ) * TRUSTINFO_SIZE ) != \\\n\t\ttrustInfoContainer->trustInfoChecksum )\n\t\treturn( NULL );\n\n\treturn( trustInfoContainer->trustInfo );\n\t}\n\n/* Update the checksum on the trust information */\n\nstatic void updateTrustInfoChecksum( IN const DATAPTR trustInfo )\n\t{\n\tTRUST_INFO_CONTAINER *trustInfoContainer;\n\n\t/* Get a pointer to the trust information index.  We can't use \n\t   getCheckTrustInfo() because we've changed it so the checksum won't\n\t   validate */\n\ttrustInfoContainer = DATAPTR_GET( trustInfo );\n\tENSURES_V( trustInfoContainer != NULL );\n\n\t/* Update the trust information checksum */\n\ttrustInfoContainer->trustInfoChecksum = \\\n\t\t\t\t\tchecksumData( trustInfoContainer->trustInfo, \n\t\t\t\t\t\t\t\t  sizeof( DATAPTR ) * TRUSTINFO_SIZE );\n\t}\n\n/* Extract ID fields from an encoded certificate.  Since this isn't a\n   certificate object we have to parse the encoded data to locate the fields\n   that we're interested in */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int getCertIdInfo( IN_BUFFER( certObjectLength ) const void *certObject, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\tconst int certObjectLength,\n\t\t\t\t\t\t  OUT_PTR_COND void **subjectDNptrPtr,\n\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *subjectDNsizePtr )\n\t{\n\tSTREAM stream;\n\tvoid *subjectDNptr DUMMY_INIT_PTR;\n\tint subjectDNsize DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( certObject, certObjectLength ) );\n\tassert( isWritePtr( subjectDNptrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( subjectDNsizePtr, sizeof( int ) ) );\n\n\tREQUIRES( certObjectLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  certObjectLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*subjectDNptrPtr = NULL;\n\t*subjectDNsizePtr = 0;\n\n\t/* Parse the certificate to locate the start of the encoded subject DN \n\t   and certificate extensions (if present) */\n\tsMemConnect( &stream, certObject, certObjectLength );\n\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\treadSequence( &stream, NULL );\t\t\t/* Inner wrapper */\n\tif( peekTag( &stream ) == MAKE_CTAG( 0 ) )\n\t\treadUniversal( &stream );\t\t\t/* Version */\n\treadUniversal( &stream );\t\t\t\t/* Serial number */\n\treadUniversal( &stream );\t\t\t\t/* Signature algo */\n\treadUniversal( &stream );\t\t\t\t/* Issuer DN */\n\tstatus = readUniversal( &stream );\t\t/* Validity */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getStreamObjectLength( &stream, &subjectDNsize );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( subjectDNsize ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( &stream, &subjectDNptr, subjectDNsize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\t*subjectDNptrPtr = subjectDNptr;\n\t*subjectDNsizePtr = subjectDNsize;\n\tstatus = sSkip( &stream, subjectDNsize, MAX_INTLENGTH_SHORT );/* Subject DN */\n#if 0\t/* sKID lookup isn't used at present.  Also this code should use the \n\t\t   parsing mechanism from dbx_rd.c to provide better checking */\n\tconst BYTE *extensionPtr;\n\tint extensionSize = 0;\n\tstatus = readUniversal( &stream );\t\t/* Public key */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 3 ) )\n\t\t{\n\t\tstatus = readConstructed( &stream, &extensionSize, 3 );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!isShortIntegerRangeNZ( extensionSize ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\textensionPtr = sMemBufPtr( &stream );\n\t\t\tsSkip( &stream, extensionSize, MAX_INTLENGTH_SHORT );\n\t\t\t}\n\t\t}\n\tif( !cryptStatusError( status ) )\t\t/* Signature */\n\t\tstatus = readUniversal( &stream );\n#endif /* 0 */\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n#if 0\t/* sKID lookup isn't used at present.  Also this code should use the \n\t\t   parsing mechanism from dbx_rd.c to provide better checking */\n\t/* Look for the subjectKeyID in the extensions.  It's easier to do a \n\t   pattern match than to try and parse the extensions */\n\tsubjectKeyIDptr = NULL;\n\tsubjectKeyIDsize = 0;\n\tLOOP_LARGE( i = 0, i < extensionSize - 64, i++ )\n\t\t{\n\t\t/* Look for the OID.  This potentially skips two bytes at a time, \n\t\t   but this is safe since the preceding bytes can never contain \n\t\t   either of these two values (they're 0x30, len) */\n\t\tif( extensionPtr[ i++ ] != BER_OBJECT_IDENTIFIER || \\\n\t\t\textensionPtr[ i++ ] != 3 )\n\t\t\tcontinue;\n\t\tif( memcmp( extensionPtr + i, \"\\x55\\x1D\\x0E\", 3 ) )\n\t\t\tcontinue;\n\t\ti += 3;\n\n\t\t/* We've found the OID (with 1.1e-12 error probability), skip the \n\t\t   critical flag if necessary */\n\t\tif( extensionPtr[ i ] == BER_BOOLEAN )\n\t\t\ti += 3;\n\n\t\t/* Check for the OCTET STRING and a reasonable length */\n\t\tif( extensionPtr[ i++ ] != BER_OCTETSTRING || \\\n\t\t\textensionPtr[ i ] & 0x80 )\n\t\t\tcontinue;\n\n\t\t/* Extract the key ID */\n\t\tif( i + extensionPtr[ i ] <= extensionSize )\n\t\t\t{\n\t\t\tsubjectKeyIDsize = extensionPtr[ i++ ];\n\t\t\tsubjectKeyIDptr = extensionPtr + i;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n#endif /* 0 */\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRetrieve Trusted Certificate Information\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the trust information entry for a given certificate.  This isn't \n   used within this module but is called from cryptusr.c */\n\nCHECK_RETVAL_PTR \\\nvoid *findTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t  const BOOLEAN getIssuerEntry )\n\t{\n\tconst DATAPTR *trustInfoIndex;\n\tconst TRUST_INFO *trustInfoCursor;\n\tDYNBUF nameDB;\n\tBYTE sHash[ HASH_DATA_SIZE + 8 ];\n\tBOOLEAN nameHashed = FALSE;\n\tint sCheck, trustInfoEntry, status, LOOP_ITERATOR;\n\n\tREQUIRES_N( DATAPTR_ISSET( trustInfo ) );\n\tREQUIRES_N( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES_N( getIssuerEntry == TRUE || getIssuerEntry == FALSE );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES_N( trustInfoIndex != NULL );\n\n\t/* If we're trying to get a trusted issuer certificate and we're already \n\t   at a self-signed (CA root) certificate, don't return it.  This check \n\t   is necessary because self-signed certificates have issuer name == \n\t   subject name so once we get to a self-signed certificate's subject DN \n\t   an attempt to fetch its issuer would just repeatedly fetch the same \n\t   certificate */\n\tif( getIssuerEntry )\n\t\t{\n\t\tBOOLEAN_INT selfSigned;\n\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &selfSigned, CRYPT_CERTINFO_SELFSIGNED );\n\t\tif( cryptStatusError( status ) || selfSigned == TRUE )\n\t\t\treturn( NULL );\n\t\t}\n\n\t/* Set up the information needed to find the trusted certificate */\n\tstatus = dynCreate( &nameDB, iCryptCert, getIssuerEntry ? \\\n\t\t\t\t\t\tCRYPT_IATTRIBUTE_ISSUER : CRYPT_IATTRIBUTE_SUBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( NULL );\n\tsCheck = checksumData( dynData( nameDB ), dynLength( nameDB ) );\n\ttrustInfoEntry = sCheck & ( TRUSTINFO_SIZE - 1 );\n\tENSURES_N( trustInfoEntry >= 0 && trustInfoEntry < TRUSTINFO_SIZE );\n\n\t/* Check to see whether something with the requested DN is present */\n\tLOOP_MED( trustInfoCursor = DATAPTR_GET( trustInfoIndex[ trustInfoEntry ] ), \n\t\t\t  trustInfoCursor != NULL,\n\t\t\t  trustInfoCursor = DATAPTR_GET( trustInfoCursor->next ) )\n\t\t{\n\t\tREQUIRES_N( sanityCheckTrustInfo( trustInfoCursor ) );\n\n\t\t/* Perform a quick check using a checksum of the name to weed out\n\t\t   most entries */\n\t\tif( trustInfoCursor->sCheck == sCheck )\n\t\t\t{\n\t\t\tif( !nameHashed )\n\t\t\t\t{\n\t\t\t\thashData( sHash, HASH_DATA_SIZE, dynData( nameDB ), \n\t\t\t\t\t\t  dynLength( nameDB ) );\n\t\t\t\tnameHashed = TRUE;\n\t\t\t\t}\n\t\t\tif( !memcmp( trustInfoCursor->sHash, sHash, HASH_DATA_SIZE ) )\n\t\t\t\t{\n\t\t\t\tdynDestroy( &nameDB );\n\t\t\t\treturn( ( TRUST_INFO * ) trustInfoCursor );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tdynDestroy( &nameDB );\n\n\treturn( NULL );\n\t}\n\n/* Retrieve trusted certificates */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getTrustedCert( INOUT TYPECAST( TRUST_INFO * ) void *trustInfoPtr,\n\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate )\n\t{\n\tTRUST_INFO *trustInfo = trustInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( trustInfoPtr, sizeof( TRUST_INFO ) ) );\n\n\tREQUIRES( sanityCheckTrustInfo( trustInfo ) );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* If the certificate hasn't already been instantiated yet, do so now */\n\tif( trustInfo->iCryptCert == CRYPT_ERROR )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\t\tvoid *certObjectPtr;\n\n\t\tcertObjectPtr = DATAPTR_GET( trustInfo->certObject );\n\t\tENSURES( certObjectPtr != NULL );\n\n\t\t/* Instantiate the certificate */\n\t\tsetMessageCreateObjectIndirectInfo( &createInfo, certObjectPtr,\n\t\t\t\t\t\t\t\t\t\t\ttrustInfo->certObjectLength,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we couldn't instantiate the certificate and it's due to a\n\t\t\t   problem with the certificate rather than circumstances beyond\n\t\t\t   our control, warn about the issue since a (supposedly) known-\n\t\t\t   good certificate shouldn't cause problems on import */\n\t\t\tif( status != CRYPT_ERROR_MEMORY )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Couldn't instantiate trusted certificate\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* The certificate was successfully instantiated, free its stored \n\t\t   encoded form */\n\t\tzeroise( certObjectPtr, trustInfo->certObjectLength );\n\t\tclFree( \"getTrustedCert\", certObjectPtr );\n\t\tDATAPTR_SET( trustInfo->certObject, NULL );\n\t\ttrustInfo->certObjectLength = 0;\n\t\ttrustInfo->certChecksum = 0;\n\t\ttrustInfo->iCryptCert = createInfo.cryptHandle;\n\t\t}\n\n\t/* Return the trusted certificate */\n\t*iCertificate = trustInfo->iCryptCert;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN trustedCertsPresent( IN const DATAPTR trustInfo )\n\t{\n\tconst DATAPTR *trustInfoIndex;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISSET( trustInfo ) );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES_B( trustInfoIndex != NULL );\n\n\tLOOP_EXT( i = 0, i < TRUSTINFO_SIZE, i++, TRUSTINFO_SIZE + 1 )\n\t\t{\n\t\tif( DATAPTR_ISSET( trustInfoIndex[ i ] ) )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\nCHECK_RETVAL \\\nint enumTrustedCerts( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCtl,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_KEYSET iCryptKeyset )\n\t{\n\tconst DATAPTR *trustInfoIndex;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES( DATAPTR_ISSET( trustInfo ) );\n\tREQUIRES( ( iCryptCtl == CRYPT_UNUSED && \\\n\t\t\t\tisHandleRangeValid( iCryptKeyset ) ) || \\\n\t\t\t  ( isHandleRangeValid( iCryptCtl ) && \\\n\t\t\t\tiCryptKeyset == CRYPT_UNUSED ) );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES_B( trustInfoIndex != NULL );\n\n\t/* Send each trusted certificate to the given object, either a \n\t   certificate trust list or a keyset */\n\tLOOP_EXT( i = 0, i < TRUSTINFO_SIZE, i++, TRUSTINFO_SIZE + 1 )\n\t\t{\n\t\tTRUST_INFO *trustInfoCursor;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tLOOP_MED_ALT( trustInfoCursor = DATAPTR_GET( trustInfoIndex[ i ] ), \n\t\t\t\t\t  trustInfoCursor != NULL,\n\t\t\t\t\t  trustInfoCursor = DATAPTR_GET( trustInfoCursor->next ) )\t\n\t\t\t{\n\t\t\tCRYPT_CERTIFICATE iCryptCert;\n\t\t\tint status;\n\n\t\t\tREQUIRES( sanityCheckTrustInfo( trustInfoCursor ) );\n\n\t\t\tstatus = getTrustedCert( trustInfoCursor, &iCryptCert );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( iCryptCtl != CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\t/* We're sending trusted certificates to a certificate trust \n\t\t\t\t   list */\n\t\t\t\tstatus = krnlSendMessage( iCryptCtl, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCryptCert,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTCOLLECTION );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\n\t\t\t\t/* We're sending trusted certificates to a keyset */\n\t\t\t\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\t\t\t\tsetkeyInfo.cryptHandle = iCryptCert;\n\t\t\t\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_SETKEY, \n\t\t\t\t\t\t\t\t\t\t  &setkeyInfo, \n\t\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAdd/Update Trusted Certificate Information\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add and delete a trust entry */\n\nCHECK_RETVAL \\\nstatic int addEntry( IN const DATAPTR trustInfo, \n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert, \n\t\t\t\t\t IN_BUFFER_OPT( certObjectLength ) const void *certObject, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int certObjectLength )\n\t{\n\tDATAPTR *trustInfoIndex;\n\tTRUST_INFO *newElement, *trustInfoCursor, *trustInfoLast;\n\tBYTE sHash[ HASH_DATA_SIZE + 8 ];\n\tBOOLEAN recreateCert = FALSE;\n\tint sCheck, trustInfoEntry, status, LOOP_ITERATOR;\n\n\tassert( ( certObject == NULL && certObjectLength == 0 && \\\n\t\t\t  isHandleRangeValid( iCryptCert ) ) || \\\n\t\t\t( isReadPtrDynamic( certObject, certObjectLength ) && \\\n\t\t\t  iCryptCert == CRYPT_UNUSED ) );\n\n\tREQUIRES( ( certObject == NULL && certObjectLength == 0 && \\\n\t\t\t\tisHandleRangeValid( iCryptCert ) ) || \\\n\t\t\t  ( certObject != NULL && \\\n\t\t\t    certObjectLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tcertObjectLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tiCryptCert == CRYPT_UNUSED ) );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES( trustInfoIndex != NULL );\n\n\t/* If we're adding a certificate, check whether it has a context \n\t   attached and if it does, whether it's a public-key context.  If \n\t   there's no context attached (it's a data-only certificate) or the \n\t   attached context is a private-key context (which we don't want to \n\t   leave hanging around in memory, or which could be in a removable \n\t   crypto device) we don't try and use the certificate but instead add \n\t   the certificate data and then later re-instantiate a new certificate \n\t   with attached public-key context if required */\n\tif( certObject == NULL )\n\t\t{\n\t\tCRYPT_CONTEXT iCryptContext;\n\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t\t  &iCryptContext, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* There's no context associated with this certificate, we'll \n\t\t\t   have to recreate it later */\n\t\t\trecreateCert = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( checkContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_PRIVATE ) )\n\t\t\t\t{\n\t\t\t\t/* The context associated with the certificate is a private-\n\t\t\t\t   key context, recreate it later as a public-key context */\n\t\t\t\trecreateCert = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Get the ID information for the certificate */\n\tif( certObject == NULL )\n\t\t{\n\t\tDYNBUF subjectDB;\n\n\t\t/* Generate the checksum and hash of the certificate object's \n\t\t   subject name and key ID */\n\t\tstatus = dynCreate( &subjectDB, iCryptCert, \n\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_SUBJECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsCheck = checksumData( dynData( subjectDB ), \n\t\t\t\t\t\t\t   dynLength( subjectDB ) );\n\t\thashData( sHash, HASH_DATA_SIZE, dynData( subjectDB ), \n\t\t\t\t  dynLength( subjectDB ) );\n#if 0\t/* sKID lookup isn't used at present */\n\t\tDYNBUF subjectKeyDB;\n\t\tstatus = dynCreate( &subjectKeyDB, iCryptCert, \n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tkCheck = checksumData( dynData( subjectKeyDB ), \n\t\t\t\t\t\t\t\t   dynLength( subjectKeyDB ) );\n\t\t\thashData( kHash, HASH_DATA_SIZE, dynData( subjectKeyDB ), \n\t\t\t\t\t  dynLength( subjectKeyDB ) );\n\t\t\tdynDestroy( &subjectKeyDB );\n\t\t\t}\n#endif /* 0 */\n\t\tdynDestroy( &subjectDB );\n\t\t}\n\telse\n\t\t{\n\t\tvoid *subjectDNptr;\n\t\tint subjectDNsize;\n\n\t\t/* Get the ID information from the encoded certificate */\n\t\tstatus = getCertIdInfo( certObject, certObjectLength, \n\t\t\t\t\t\t\t\t&subjectDNptr, &subjectDNsize );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tANALYSER_HINT( subjectDNptr != NULL );\n\n\t\t/* Generate the checksum and hash of the encoded certificate's \n\t\t   subject name and key ID */\n\t\tsCheck = checksumData( subjectDNptr, subjectDNsize );\n\t\thashData( sHash, HASH_DATA_SIZE, subjectDNptr, subjectDNsize );\n#if 0\t/* sKID lookup isn't used at present */\n\t\tkCheck = checksumData( subjectKeyIDptr, subjectKeyIDsize );\n\t\thashData( kHash, HASH_DATA_SIZE, subjectKeyIDptr, subjectKeyIDsize );\n#endif /* 0 */\n\t\t}\n\n\t/* Find the insertion point and make sure that this entry isn't already \n\t   present */\n\ttrustInfoEntry = sCheck & ( TRUSTINFO_SIZE - 1 );\n\tENSURES( trustInfoEntry >= 0 && trustInfoEntry < TRUSTINFO_SIZE );\n\tLOOP_MED( trustInfoCursor = trustInfoLast = \\\n\t\t\t\t\tDATAPTR_GET( trustInfoIndex[ trustInfoEntry ] ), \n\t\t\t  trustInfoCursor != NULL,\n\t\t\t  trustInfoCursor = DATAPTR_GET( trustInfoCursor->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckTrustInfo( trustInfoCursor ) );\n\n\t\t/* Perform a quick check using a checksum of the name to weed out\n\t\t   most entries */\n\t\tif( trustInfoCursor->sCheck == sCheck && \\\n\t\t\t!memcmp( trustInfoCursor->sHash, sHash, HASH_DATA_SIZE ) )\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\ttrustInfoLast = trustInfoCursor;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\ttrustInfoCursor = trustInfoLast;\n\n\t/* Allocate memory for the new element and copy the information across */\n\tif( ( newElement  = ( TRUST_INFO * ) \\\n\t\t\t\tclAlloc( \"addEntry\", sizeof( TRUST_INFO ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( newElement, 0, sizeof( TRUST_INFO ) );\n\tnewElement->sCheck = sCheck;\n\tmemcpy( newElement->sHash, sHash, HASH_DATA_SIZE );\n\tDATAPTR_SET( newElement->certObject, NULL );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tDATAPTR_SET( newElement->next, NULL );\n\tif( certObject != NULL || recreateCert )\n\t\t{\n\t\tDYNBUF certDB;\n\t\tvoid *objectPtr;\n\t\tint objectLength = certObjectLength;\n\n\t\t/* If we're using the data from an existing certificate object we \n\t\t   need to extract the encoded data */\n\t\tif( recreateCert )\n\t\t\t{\n\t\t\t/* Get the encoded certificate */\n\t\t\tstatus = dynCreateCert( &certDB, iCryptCert, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tclFree( \"addEntry\", newElement );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tcertObject = dynData( certDB );\n\t\t\tobjectLength = dynLength( certDB );\n\t\t\t}\n\n\t\t/* Remember the trusted certificate data for later use */\n\t\tREQUIRES( rangeCheck( objectLength, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( objectPtr = clAlloc( \"addEntry\", objectLength ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"addEntry\", newElement );\n\t\t\tif( recreateCert )\n\t\t\t\tdynDestroy( &certDB );\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tmemcpy( objectPtr, certObject, objectLength );\n\t\tDATAPTR_SET( newElement->certObject, objectPtr );\n\t\tnewElement->certObjectLength = objectLength;\n\t\tnewElement->certChecksum = checksumData( objectPtr, objectLength );\n\t\tnewElement->iCryptCert = CRYPT_ERROR;\n\n\t\t/* Clean up */\n\t\tif( recreateCert )\n\t\t\tdynDestroy( &certDB );\n\t\t}\n\telse\n\t\t{\n\t\t/* The trusted key exists as a standard certificate with a public-\n\t\t   key context attached, remember it for later */\n\t\tkrnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );\n\t\tnewElement->iCryptCert = iCryptCert;\n\t\t}\n\tENSURES( sanityCheckTrustInfo( newElement ) );\n\n\t/* Add the new entry to the list */\n\tinsertDoubleListElement( &trustInfoIndex[ trustInfoEntry ], \n\t\t\t\t\t\t\t trustInfoCursor, newElement, TRUST_INFO );\n\tupdateTrustInfoChecksum( trustInfo );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint addTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t   IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t   IN_BUFFER_OPT( certObjectLength ) const void *certObject, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int certObjectLength,\n\t\t\t\t   const BOOLEAN addSingleCert )\n\t{\n\tBOOLEAN itemAdded = FALSE;\n\tint status;\n\n\tassert( ( certObject == NULL && certObjectLength == 0 && \\\n\t\t\t  isHandleRangeValid( iCryptCert ) ) || \\\n\t\t\t( isReadPtrDynamic( certObject, certObjectLength ) && \\\n\t\t\t  iCryptCert == CRYPT_UNUSED ) );\n\n\tREQUIRES( DATAPTR_ISSET( trustInfo ) );\n\tREQUIRES( ( certObject == NULL && certObjectLength == 0 && \\\n\t\t\t\tisHandleRangeValid( iCryptCert ) ) || \\\n\t\t\t  ( certObject != NULL && \\\n\t\t\t    certObjectLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tcertObjectLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tiCryptCert == CRYPT_UNUSED ) );\n\tREQUIRES( addSingleCert == TRUE || addSingleCert == FALSE );\n\n\t/* If we're adding encoded certificate data then we can add it \n\t   directly */\n\tif( certObject != NULL )\n\t\t{\n\t\treturn( addEntry( trustInfo, CRYPT_UNUSED, certObject, \n\t\t\t\t\t\t  certObjectLength ) );\n\t\t}\n\n\t/* Add the certificate/each certificate in the trust list */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( addSingleCert )\n\t\t{\n\t\tstatus = addEntry( trustInfo, iCryptCert, NULL, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\titemAdded = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tint loopStatus, LOOP_ITERATOR;\n\n\t\t/* It's a trust list, move to the start of the list and add each\n\t\t   certificate in it */\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\treturn( status );\n\t\t\t}\n\t\tLOOP_MED( loopStatus = CRYPT_OK, cryptStatusOK( loopStatus ),\n\t\t\t\t  loopStatus = krnlSendMessage( iCryptCert, \n\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t\t{\n\t\t\t/* An item being added may already be present, however we can't \n\t\t\t   fail immediately because what's being added may be a chain \n\t\t\t   containing further certificates so we keep track of whether \n\t\t\t   we've successfully added at least one item and clear data \n\t\t\t   duplicate errors */\n\t\t\tstatus = addEntry( trustInfo, iCryptCert, NULL, 0 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t\t\tbreak;\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\titemAdded = TRUE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !itemAdded )\n\t\t{\n\t\t/* We reached the end of the certificate chain without finding \n\t\t   anything that we could add, return a data duplicate error */\n\t\treturn( CRYPT_ERROR_DUPLICATE ); \n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deleteTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN TYPECAST( TRUST_INFO * ) void *entryToDeletePtr )\n\t{\n\tDATAPTR *trustInfoIndex;\n\tTRUST_INFO *entryToDelete = ( TRUST_INFO * ) entryToDeletePtr;\n\tint trustInfoEntry;\n\n\tassert( isWritePtr( entryToDeletePtr, sizeof( TRUST_INFO ) ) );\n\n\tREQUIRES( DATAPTR_ISSET( trustInfo ) );\n\tREQUIRES( sanityCheckTrustInfo( entryToDelete ) );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES( trustInfoIndex != NULL );\n\n\ttrustInfoEntry = entryToDelete->sCheck & ( TRUSTINFO_SIZE - 1 );\n\tREQUIRES( trustInfoEntry >= 0 && trustInfoEntry < TRUSTINFO_SIZE );\n\n\t/* Free the trust information entry contents */\n\tif( entryToDelete->iCryptCert != CRYPT_ERROR )\n\t\tkrnlSendNotifier( entryToDelete->iCryptCert, IMESSAGE_DECREFCOUNT );\n\tif( DATAPTR_ISSET( entryToDelete->certObject ) )\n\t\t{\n\t\tvoid *certObjectPtr = DATAPTR_GET( entryToDelete->certObject );\n\n\t\tENSURES( certObjectPtr != NULL );\n\t\tzeroise( certObjectPtr, entryToDelete->certObjectLength );\n\t\tclFree( \"deleteTrustEntry\", certObjectPtr );\n\t\t}\n\n\t/* Remove the trust entry from the list */\n\tdeleteDoubleListElement( &trustInfoIndex[ trustInfoEntry ], entryToDelete, \n\t\t\t\t\t\t\t TRUST_INFO );\n\tupdateTrustInfoChecksum( trustInfo );\n\n\t/* Clear all data in the trust entry and free the memory */\n\tmemset( entryToDelete, 0, sizeof( TRUST_INFO ) );\n\tclFree( \"deleteTrustEntry\", entryToDelete );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tInit/Shut down Trusted Certificate Information\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and shut down the trust information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initTrustInfo( OUT_DATAPTR DATAPTR *trustInfoPtr )\n\t{\n\tTRUST_INFO_CONTAINER *trustInfoContainer;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( trustInfoPtr, sizeof( DATAPTR ) ) );\n\n\t/* Clear return value */\n\tDATAPTR_SET_PTR( trustInfoPtr, NULL );\n\n\t/* Initialise the trust information table */\n\ttrustInfoContainer = getTrustMgrStorage();\n\tmemset( trustInfoContainer, 0, sizeof( TRUST_INFO_CONTAINER ) );\n\tLOOP_EXT( i = 0, i < TRUSTINFO_SIZE, i++, TRUSTINFO_SIZE + 1 )\n\t\t{\n\t\tDATAPTR_SET( trustInfoContainer->trustInfo[ i ], NULL );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDATAPTR_SET_PTR( trustInfoPtr, trustInfoContainer );\n\tupdateTrustInfoChecksum( *trustInfoPtr );\n\n\tENSURES( getCheckTrustInfo( *trustInfoPtr ) != NULL );\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid endTrustInfo( IN const DATAPTR trustInfo )\n\t{\n\tDATAPTR *trustInfoIndex;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_V( DATAPTR_ISSET( trustInfo ) );\n\n\t/* Check that the trust information is valid and get a pointer to the\n\t   trust information index */\n\ttrustInfoIndex = getCheckTrustInfo( trustInfo );\n\tENSURES_V( trustInfoIndex != NULL );\n\n\t/* Destroy the chain of items at each table position */\n\tLOOP_EXT( i = 0, i < TRUSTINFO_SIZE, i++, TRUSTINFO_SIZE + 1 )\n\t\t{\n\t\tTRUST_INFO *trustInfoCursor;\n\n\t\t/* Destroy any items in the list */\n\t\tLOOP_MED_INITCHECK( trustInfoCursor = DATAPTR_GET( trustInfoIndex[ i ] ), \n\t\t\t\t\t\t\ttrustInfoCursor != NULL )\n\t\t\t{\n\t\t\tTRUST_INFO *itemToFree = trustInfoCursor;\n\n\t\t\ttrustInfoCursor = DATAPTR_GET( trustInfoCursor->next );\n\t\t\tdeleteTrustEntry( trustInfo, itemToFree );\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK );\n\n\t\t/* Clear the list head */\n\t\tDATAPTR_SET( trustInfoIndex[ i ], NULL );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\tupdateTrustInfoChecksum( trustInfo );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/trustmgr.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Trust Manger Interface \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _TRUSTMGR_DEFINED\n\n#define _TRUSTMGR_DEFINED\n\n/* Prototypes for certificate trust management functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initTrustInfo( OUT_DATAPTR DATAPTR *trustInfoPtr );\nvoid endTrustInfo( IN const DATAPTR trustInfo );\nCHECK_RETVAL \\\nint addTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t   IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t   IN_BUFFER_OPT( certObjectLength ) const void *certObject, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int certObjectLength,\n\t\t\t\t   const BOOLEAN addSingleCert );\nRETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deleteTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN void *entryToDeletePtr );\nCHECK_RETVAL_PTR \\\nvoid *findTrustEntry( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t  const BOOLEAN getIssuerEntry );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getTrustedCert( INOUT void *trustInfoPtr,\n\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate );\nCHECK_RETVAL_BOOL \\\nBOOLEAN trustedCertsPresent( IN const DATAPTR trustInfo );\nCHECK_RETVAL \\\nint enumTrustedCerts( IN const DATAPTR trustInfo, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCtl,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_KEYSET iCryptKeyset );\n\n/* If certificates aren't available, we have to no-op out the cert trust\n   manager functions */\n\n#ifndef USE_CERTIFICATES\n\n#define initTrustInfo( trustInfoPtrPtr )\tCRYPT_OK\n#define endTrustInfo( trustInfoPtr )\n#define addTrustEntry( trustInfoPtr, iCryptCert, certObject, \\\n\t\t\t\t\t   certObjectLength, addSingleCert ) \\\n\t\tCRYPT_ERROR_NOTAVAIL\n#define deleteTrustEntry( trustInfoPtr, entryToDelete )\n#define findTrustEntry( trustInfoPtr, cryptCert, getIssuerEntry ) \\\n\t\tNULL\n#define getTrustedCert( trustInfoPtr )\t\tCRYPT_ERROR_NOTFOUND\n#define enumTrustedCerts( trustInfoPtr, iCryptCtl, iCryptKeyset ) \\\n\t\tCRYPT_ERROR_NOTFOUND\n\n#endif /* USE_CERTIFICATES */\n\n#endif /* _TRUSTMGR_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/trustmgr_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tCertificate Trust Manger Internal Interface \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _TRUSTMGR_INT_DEFINED\n\n#define _TRUSTMGR_INT_DEFINED\n\n/* The size of the table of trust information.  This must be a power of 2 */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define TRUSTINFO_SIZE\t\t16\n#else\n  #define TRUSTINFO_SIZE\t\t256\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* Trusted certificate information */\n\ntypedef struct TI {\n\t/* Identification information, the checksum and hash of the \n\t   certificate's subjectName and subjectKeyIdentifier */\n\tint sCheck;\n\tBYTE sHash[ HASH_DATA_SIZE + 4 ];\n#if 0\t/* sKID lookup isn't used at present */\n\tint kCheck;\n\tBYTE kHash[ HASH_DATA_SIZE + 4 ];\n#endif /* 0 */\n\n\t/* The trusted certificate.  When we read trusted certificates from a \n\t   configuration file the certificate is stored in the encoded form to \n\t   save creating a pile of certificate objects that'll never be used.  \n\t   When it's needed the certificate is created on the fly from the \n\t   encoded form.  Conversely, when we get the trust information directly \n\t   from the user the certificate object already exists and the encoded \n\t   form isn't used */\n\tDATAPTR certObject;\n\tint certObjectLength;\n\tint certChecksum;\n\tCRYPT_CERTIFICATE iCryptCert;\n\n\t/* Pointer to the next entry */\n\tDATAPTR next, prev;\t\t\t/* Next trustInfo record in the chain */\n\t} TRUST_INFO;\n\n/* The data structure that stores the trust management information */\n\ntypedef struct {\n\t/* Array of pointers to certificate trust information */\n\tDATAPTR trustInfo[ TRUSTINFO_SIZE ];\t\n\n\t/* Checksum for the trust information array */\n\tint trustInfoChecksum;\n\t} TRUST_INFO_CONTAINER;\n\n/* Trust manager access function */\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getTrustMgrStorage( void );\n\n#endif /* _TRUSTMGR_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cert/write.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Write Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* The X.509 version numbers */\n\nenum { X509VERSION_1, X509VERSION_2, X509VERSION_3 };\nenum { X509ACVERSION_1, X509ACVERSION_2 }; \n\n#ifdef USE_CERTIFICATES\n\n#if defined( __MVS__ )\n  /* MVS control section (CSECT) names default to the file name and can't\n\t match any symbol name either in the file or in another file or library \n\t (e.g. write.c vs. write()).  Because of this we have to explicitly \n\t name the csect's so that they don't conflict with external symbol\n\t names */\n  #pragma csect( CODE, \"writeC\" )\n  #pragma csect( STATIC, \"writeS\" )\n  #pragma csect( TEST, \"writeT\" )\n#endif /* __MVS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n\n/* Set/refresh a nonce in an RTCS/OCSP request (difficile est tenere quae \n   acceperis nisi exerceas) */\n\nstatic int setNonce( INOUT DATAPTR_ATTRIBUTE *attributePtr,\n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE nonceType )\n\t{\n\tDATAPTR_ATTRIBUTE attribute;\n\tMESSAGE_DATA msgData;\n\tvoid *noncePtr;\n\tint nonceLength, status;\n\n\tassert( isWritePtr( attributePtr, sizeof( DATAPTR_ATTRIBUTE ) ) );\n\n\tREQUIRES( nonceType == CRYPT_CERTINFO_CMS_NONCE || \\\n\t\t\t  nonceType == CRYPT_CERTINFO_OCSP_NONCE );\n\n\t/* To ensure freshness we always use a new nonce when we write an RTCS \n\t   or OCSP request */\n\tattribute = findAttributeField( *attributePtr, nonceType,\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attribute ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\t\tBYTE nonce[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t/* There's no nonce present, add a new one */\n\t\tsetMessageData( &msgData, nonce, 16 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( addAttributeFieldString( attributePtr, nonceType, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, nonce, 16, 0, \n\t\t\t\t\t\t\t\t\t\t &dummy1, &dummy2 ) );\n\t\t}\n\n\t/* There's an existing nonce present, refresh it */\n\tstatus = getAttributeDataPtr( attribute, &noncePtr, &nonceLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( nonceLength == 16 );\n\tsetMessageData( &msgData, noncePtr, 16 );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE ) );\n\t}\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite Certificate Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write certificate information:\n\n\tCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t  [ 0 ]\tEXPLICIT INTEGER DEFAULT(0),\n\t\tserialNumber\t\t\tINTEGER,\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tissuer\t\t\t\t\tName\n\t\tvalidity\t\t\t\tValidity,\n\t\tsubject\t\t\t\t\tName,\n\t\tsubjectPublicKeyInfo\tSubjectPublicKeyInfo,\n\t\textensions\t\t  [ 3 ]\tExtensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeCertInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tconst CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;\n\tint algoIdInfoSize, length, extensionSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( iIssuerCryptContext ) );\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tBOOLEAN_INT isXyzzyCert;\n\t\tint dnCheckFlag = PRE_CHECK_DN;\n\n\t\t/* If it's a XYZZY certificate then a complete DN isn't required */\n\t\tstatus = getCertComponent( subjectCertInfoPtr, CRYPT_CERTINFO_XYZZY, \n\t\t\t\t\t\t\t\t   &isXyzzyCert );\n\t\tif( cryptStatusOK( status ) && isXyzzyCert == TRUE )\n\t\t\tdnCheckFlag = PRE_CHECK_DN_PARTIAL;\n\n\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t   PRE_SET_STANDARDATTR | PRE_SET_ISSUERATTR | \\\n\t\t\t\t\t\t\t\t\t   PRE_SET_ISSUERDN | PRE_SET_VALIDITYPERIOD );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_SPKI | dnCheckFlag | \\\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERDN | PRE_CHECK_SERIALNO | \\\n\t\t\t\t\t\t\t( TEST_FLAG( subjectCertInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CERT_FLAG_SELFSIGNED ) ? \\\n\t\t\t\t\t\t\t\t\t  0 : PRE_CHECK_NONSELFSIGNED_DN ),\n\t\t\t\t\t\t\t( issuerCertInfoPtr->subjectDNptr != NULL ) ? \\\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_DN_IN_ISSUERCERT : \\\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how the issuer name will be encoded */\n\tstatus = length = ( issuerCertInfoPtr->subjectDNptr != NULL ) ? \\\n\t\t\t\t\t\tissuerCertInfoPtr->subjectDNsize : \\\n\t\t\t\t\t\tsizeofDN( subjectCertInfoPtr->issuerName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsubjectCertInfoPtr->issuerDNsize = length;\n\tstatus = length = sizeofDN( subjectCertInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsubjectCertInfoPtr->subjectDNsize = length;\n\n\t/* Determine the size of the certificate information */\n\tstatus = algoIdInfoSize = \\\n\t\t\t\tsizeofContextAlgoID( iIssuerCryptContext, \n\t\t\t\t\t\t\t\t\t certCertInfo->hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = sizeofInteger( certCertInfo->serialNumber,\n\t\t\t\t\t\t\tcertCertInfo->serialNumberLength ) + \\\n\t\t\t algoIdInfoSize + \\\n\t\t\t subjectCertInfoPtr->issuerDNsize + \\\n\t\t\t sizeofObject( sizeofUTCTime() * 2 ) + \\\n\t\t\t subjectCertInfoPtr->subjectDNsize + \\\n\t\t\t subjectCertInfoPtr->publicKeyInfoSize;\n\tif( extensionSize > 0 )\n\t\t{\n\t\tlength += sizeofObject( sizeofShortInteger( X509VERSION_3 ) ) + \\\n\t\t\t\t  sizeofObject( sizeofObject( extensionSize ) );\n\t\t}\n\n\t/* Write the outer SEQUENCE wrapper */\n\tstatus = writeSequence( stream, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are extensions present, mark this as a v3 certificate */\n\tif( extensionSize > 0 )\n\t\t{\n\t\twriteConstructed( stream, sizeofShortInteger( X509VERSION_3 ),\n\t\t\t\t\t\t  CTAG_CE_VERSION );\n\t\tstatus = writeShortInteger( stream, X509VERSION_3, DEFAULT_TAG );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the serial number and signature algorithm identifier */\n\twriteInteger( stream, certCertInfo->serialNumber,\n\t\t\t\t  certCertInfo->serialNumberLength, DEFAULT_TAG );\n\tstatus = writeContextAlgoIDex( stream, iIssuerCryptContext,\n\t\t\t\t\t\t\t\t   certCertInfo->hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the issuer name, validity period, subject name, and public key\n\t   information */\n\tif( issuerCertInfoPtr->subjectDNptr != NULL )\n\t\t{\n\t\tstatus = swrite( stream, issuerCertInfoPtr->subjectDNptr,\n\t\t\t\t\t\t issuerCertInfoPtr->subjectDNsize );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeDN( stream, subjectCertInfoPtr->issuerName, \n\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteSequence( stream, sizeofUTCTime() * 2 );\n\twriteUTCTime( stream, subjectCertInfoPtr->startTime, DEFAULT_TAG );\n\twriteUTCTime( stream, subjectCertInfoPtr->endTime, DEFAULT_TAG );\n\tstatus = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = swrite( stream, subjectCertInfoPtr->publicKeyInfo,\n\t\t\t\t\t\t subjectCertInfoPtr->publicKeyInfoSize );\n\t\t}\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the extensions */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE, extensionSize ) );\n\t}\n\n#ifdef USE_ATTRCERT\n\n/* Write attribute certificate information.  There are two variants of this, \n   v1 attributes certificates that were pretty much never used (the fact \n   that no-one had bothered to define any attributes to be used with them\n   didn't help here) and v2 attribute certificates that are also almost\n   never used but are newer, we write v2 certificates.  The original v1\n   attribute certificate format was:\n\n\tAttributeCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER DEFAULT(0),\n\t\towner\t\t\t  [ 1 ]\tName,\n\t\tissuer\t\t\t\t\tName,\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tserialNumber\t\t\tINTEGER,\n\t\tvalidity\t\t\t\tValidity,\n\t\tattributes\t\t\t\tSEQUENCE OF Attribute,\n\t\textensions\t\t\t\tExtensions OPTIONAL\n\t\t} \n\n   In v2 this changed to:\n\n\tAttributeCertificateInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER (1),\n\t\tholder\t\t\t\t\tSEQUENCE {\n\t\t\tentityNames\t  [ 1 ]\tSEQUENCE OF {\n\t\t\t\tentityName[ 4 ]\tEXPLICIT Name\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\tissuer\t\t\t  [ 0 ]\tSEQUENCE {\n\t\t\tissuerNames\t\t\tSEQUENCE OF {\n\t\t\t\tissuerName[ 4 ]\tEXPLICIT Name\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tserialNumber\t\t\tINTEGER,\n\t\tvalidity\t\t\t\tSEQUENCE {\n\t\t\tnotBefore\t\t\tGeneralizedTime,\n\t\t\tnotAfter\t\t\tGeneralizedTime\n\t\t\t\t\t\t\t\t},\n\t\tattributes\t\t\t\tSEQUENCE OF Attribute,\n\t\textensions\t\t\t\tExtensions OPTIONAL\n\t\t} \n\n   In order to write the issuer and owner/holder DN as GeneralName we encode\n   it using the DN choice of a GeneralName with explicit tag 4, see the \n   comments on GeneralName encoding in ext_def.c for an explanation of the\n   tagging */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeAttributeCertInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t   IN const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tconst CERT_CERT_INFO *certCertInfo = subjectCertInfoPtr->cCertCert;\n\tint algoIdInfoSize, length, extensionSize;\n\tint issuerNameSize, holderNameSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( iIssuerCryptContext ) );\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t   PRE_SET_ISSUERDN | PRE_SET_ISSUERATTR | \\\n\t\t\t\t\t\t\t\t\t   PRE_SET_VALIDITYPERIOD );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\t\t  PRE_CHECK_DN | PRE_CHECK_ISSUERDN | \\\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_SERIALNO | \\\n\t\t\t\t\t\t\t( TEST_FLAG( subjectCertInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CERT_FLAG_SELFSIGNED ) ? \\\n\t\t\t\t\t\t\t\t\t  0 : PRE_CHECK_NONSELFSIGNED_DN ),\n\t\t\t\t\t\t\t( issuerCertInfoPtr->subjectDNptr != NULL ) ? \\\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_DN_IN_ISSUERCERT : \\\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how the issuer name will be encoded */\n\tstatus = length = ( issuerCertInfoPtr->subjectDNptr != NULL ) ? \\\n\t\t\t\t\t\tissuerCertInfoPtr->subjectDNsize : \\\n\t\t\t\t\t\tsizeofDN( subjectCertInfoPtr->issuerName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n \tissuerNameSize = length;\n\tstatus = length = sizeofDN( subjectCertInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tholderNameSize = length;\n\n\t/* Determine the size of the certificate information */\n\tstatus = algoIdInfoSize = \\\n\t\t\t\t\tsizeofContextAlgoID( iIssuerCryptContext, \n\t\t\t\t\t\t\t\t\t\t certCertInfo->hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_ATTRIBUTE_CERT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = sizeofShortInteger( X509ACVERSION_2 ) + \\\n\t\t\t sizeofObject( sizeofObject( sizeofObject( holderNameSize ) ) ) + \\\n\t\t\t sizeofObject( sizeofObject( sizeofObject( issuerNameSize ) ) ) + \\\n\t\t\t algoIdInfoSize + \\\n\t\t\t sizeofInteger( certCertInfo->serialNumber,\n\t\t\t\t\t\t\tcertCertInfo->serialNumberLength ) + \\\n\t\t\t sizeofObject( sizeofGeneralizedTime() * 2 ) + \\\n\t\t\t sizeofObject( 0 );\n\tif( extensionSize > 0 )\n\t\tlength += sizeofShortObject( extensionSize );\n\n\t/* Write the outer SEQUENCE wrapper and version */\n\twriteSequence( stream, length );\n\tstatus = writeShortInteger( stream, X509ACVERSION_2, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the owner and issuer name */\n\twriteSequence( stream, sizeofObject( sizeofObject( holderNameSize ) ) );\n\twriteConstructed( stream, sizeofObject( holderNameSize ), \n\t\t\t\t\t  CTAG_AC_HOLDER_ENTITYNAME );\n\twriteConstructed( stream, holderNameSize, 4 );\n\tstatus = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\twriteConstructed( stream, \n\t\t\t\t\t\t  sizeofObject( sizeofObject( issuerNameSize ) ), 0 );\n\t\twriteSequence( stream, sizeofObject( issuerNameSize ) );\n\t\twriteConstructed( stream, issuerNameSize, 4 );\n\t\tif( issuerCertInfoPtr->subjectDNptr != NULL )\n\t\t\t{\n\t\t\tstatus = swrite( stream, issuerCertInfoPtr->subjectDNptr,\n\t\t\t\t\t\t\t issuerCertInfoPtr->subjectDNsize );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = writeDN( stream, subjectCertInfoPtr->issuerName, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the signature algorithm identifier, serial number and validity\n\t   period */\n\twriteContextAlgoIDex( stream, iIssuerCryptContext, \n\t\t\t\t\t\t  certCertInfo->hashAlgo );\n\twriteInteger( stream, certCertInfo->serialNumber,\n\t\t\t\t  certCertInfo->serialNumberLength, DEFAULT_TAG );\n\twriteSequence( stream, sizeofGeneralizedTime() * 2 );\n\twriteGeneralizedTime( stream, subjectCertInfoPtr->startTime, \n\t\t\t\t\t\t  DEFAULT_TAG );\n\tstatus = writeGeneralizedTime( stream, subjectCertInfoPtr->endTime, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\tstatus = writeSequence( stream, 0 );\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the extensions */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_ATTRIBUTE_CERT, extensionSize ) );\n\t}\n#endif /* USE_ATTRCERT */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite CRL Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Write CRL information:\n\n\tCRLInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER DEFAULT(0),\n\t\tsignature\t\t\t\tAlgorithmIdentifier,\n\t\tissuer\t\t\t\t\tName,\n\t\tthisUpdate\t\t\t\tUTCTime,\n\t\tnextUpdate\t\t\t\tUTCTime OPTIONAL,\n\t\trevokedCertificates\t\tSEQUENCE OF RevokedCerts,\n\t\textensions\t\t  [ 0 ]\tExtensions OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCRLInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tconst CERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;\n\tconst BOOLEAN isCrlEntry = ( issuerCertInfoPtr == NULL ) ? TRUE : FALSE;\n\tBOOLEAN isV2CRL;\n\tint length, algoIdInfoSize, extensionSize, revocationInfoLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( issuerCertInfoPtr == NULL && \\\n\t\t\t  iIssuerCryptContext == CRYPT_UNUSED ) || \\\n\t\t\t( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) && \\\n\t\t\t  isHandleRangeValid( iIssuerCryptContext ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( ( issuerCertInfoPtr == NULL && \\\n\t\t\t\tiIssuerCryptContext == CRYPT_UNUSED ) || \\\n\t\t\t  ( issuerCertInfoPtr != NULL && \\\n\t\t\t\tisHandleRangeValid( iIssuerCryptContext ) ) );\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tif( isCrlEntry )\n\t\t\t{\n\t\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, NULL,\n\t\t\t\t\t\t\t\t\t\t   PRE_SET_REVINFO );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   PRE_SET_ISSUERDN | \\\n\t\t\t\t\t\t\t\t\t\t   PRE_SET_ISSUERATTR | \\\n\t\t\t\t\t\t\t\t\t\t   PRE_SET_REVINFO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = preCheckCertificate( subjectCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERCERTDN | \\\n\t\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERDN,\n\t\t\t\t\t\t\t\t\t\t  PRE_FLAG_DN_IN_ISSUERCERT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Process CRL entries and version information */\n\tsubjectCertInfoPtr->version = \\\n\t\t\t\t( DATAPTR_ISSET( subjectCertInfoPtr->attributes ) ) ? 2 : 1;\n\tstatus = revocationInfoLength = \\\n\t\t\t\tsizeofCRLentries( certRevInfo->revocations, &isV2CRL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isV2CRL )\n\t\t{\n\t\t/* The CRL can be forced to v2 even if it would otherwise by v1 by \n\t\t   the presence of certain information in the CRL entries */\n\t\tsubjectCertInfoPtr->version = 2;\n\t\t}\n\n\t/* If we're being asked to write a single CRL entry, we don't try and go\n\t   any further since the remaining CRL fields (and issuer information) \n\t   may not be set up */\n\tif( isCrlEntry )\n\t\t{\n\t\tconst REVOCATION_INFO *revInfoPtr;\n\n\t\trevInfoPtr = DATAPTR_GET( certRevInfo->currentRevocation );\n\t\tENSURES_B( revInfoPtr != NULL );\n\t\treturn( writeCRLentry( stream, revInfoPtr ) );\n\t\t}\n\n\t/* Determine how big the encoded CRL will be */\n\tstatus = algoIdInfoSize = \\\n\t\t\t\t\tsizeofContextAlgoID( iIssuerCryptContext, \n\t\t\t\t\t\t\t\t\t\t certRevInfo->hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CRL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = algoIdInfoSize + \\\n\t\t\t issuerCertInfoPtr->subjectDNsize + \\\n\t\t\t sizeofUTCTime() + \\\n\t\t\t ( ( subjectCertInfoPtr->endTime > MIN_TIME_VALUE ) ? \\\n\t\t\t\tsizeofUTCTime() : 0 ) + \\\n\t\t\t sizeofObject( revocationInfoLength );\n\tif( extensionSize > 0 )\n\t\t{\n\t\tlength += sizeofShortInteger( X509VERSION_2 ) + \\\n\t\t\t \t  sizeofObject( sizeofObject( extensionSize ) );\n\t\t}\n\n\t/* Write the outer SEQUENCE wrapper */\n\tstatus = writeSequence( stream, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are extensions present, mark this as a v2 CRL */\n\tif( extensionSize > 0 )\n\t\t{\n\t\tstatus = writeShortInteger( stream, X509VERSION_2, DEFAULT_TAG );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the signature algorithm identifier, issuer name, and CRL time */\n\tstatus = writeContextAlgoIDex( stream, iIssuerCryptContext,\n\t\t\t\t\t\t\t\t   certRevInfo->hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswrite( stream, issuerCertInfoPtr->subjectDNptr,\n\t\t\tissuerCertInfoPtr->subjectDNsize );\n\tstatus = writeUTCTime( stream, subjectCertInfoPtr->startTime, \n\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( subjectCertInfoPtr->endTime > MIN_TIME_VALUE )\n\t\t{\n\t\tstatus = writeUTCTime( stream, subjectCertInfoPtr->endTime, \n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the SEQUENCE OF revoked certificates wrapper and the revoked\n\t   certificate information */\n\tstatus = writeSequence( stream, revocationInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeCRLentries( stream, certRevInfo->revocations );\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the extensions */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CRL, extensionSize ) );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Certificate Request Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREQ\n\n/* Write certificate request information:\n\n\tCertificationRequestInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER (0),\n\t\tsubject\t\t\t\t\tName,\n\t\tsubjectPublicKeyInfo\tSubjectPublicKeyInfo,\n\t\tattributes\t\t  [ 0 ]\tSET OF Attribute\n\t\t}\n\n   If extensions are present they are encoded as:\n\n\tSEQUENCE {\t\t\t\t\t\t\t-- Attribute from X.501\n\t\tOBJECT IDENTIFIER {pkcs-9 14},\t--   type\n\t\tSET OF {\t\t\t\t\t\t--   values\n\t\t\tSEQUENCE OF {\t\t\t\t-- ExtensionReq from CMMF draft\n\t\t\t\t<X.509v3 extensions>\n\t\t\t\t}\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCertRequestInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tint length, extensionSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */\n\n\t/* Make sure that everything is in order */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, NULL, \n\t\t\t\t\t\t\t\t\t  PRE_CHECK_SPKI | PRE_CHECK_DN_PARTIAL,\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded certificate request will be */\n\tstatus = length = sizeofDN( subjectCertInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsubjectCertInfoPtr->subjectDNsize = length;\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTREQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = sizeofShortInteger( 0 ) + \\\n\t\t\t subjectCertInfoPtr->subjectDNsize + \\\n\t\t\t subjectCertInfoPtr->publicKeyInfoSize;\n\tlength += sizeofShortObject( \\\n\t\t\t\t\t\t( extensionSize > 0 ) ? extensionSize : 0 );\n\n\t/* Write the header, version number, DN, and public key information */\n\twriteSequence( stream, length );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\tstatus = writeDN( stream, subjectCertInfoPtr->subjectName, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = swrite( stream, subjectCertInfoPtr->publicKeyInfo,\n\t\t\t\t\t\t subjectCertInfoPtr->publicKeyInfoSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the attributes.  If there are no attributes we still have to \n\t   write an (erroneous) zero-length field */\n\tif( extensionSize <= 0 )\n\t\treturn( writeConstructed( stream, 0, CTAG_CR_ATTRIBUTES ) );\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTREQUEST, extensionSize ) );\n\t}\n\n/* Write CRMF certificate request information:\n\n\tCertReq ::= SEQUENCE {\n\t\tcertReqID\t\t\t\tINTEGER (0),\n\t\tcertTemplate\t\t\tSEQUENCE {\n\t\t\tvalidity\t  [ 4 ]\tSEQUENCE {\n\t\t\t\tvalidFrom [ 0 ]\tEXPLICIT GeneralizedTime OPTIONAL,\n\t\t\t\tvalidTo\t  [ 1 ] EXPLICIT GeneralizedTime OPTIONAL\n\t\t\t\t} OPTIONAL,\n\t\t\tsubject\t\t  [ 5 ]\tEXPLICIT Name OPTIONAL,\n\t\t\tpublicKey\t  [ 6 ]\tSubjectPublicKeyInfo,\n\t\t\textensions\t  [ 9 ]\tSET OF Attribute OPTIONAL\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCrmfRequestInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tint payloadLength, extensionSize, subjectDNsize = 0, timeSize = 0;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */\n\n\t/* Make sure that everything is in order */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, NULL, \n\t\t\t\t\t\t\t\t\t  PRE_CHECK_SPKI | \\\n\t\t\t\t\t( ( DATAPTR_ISSET( subjectCertInfoPtr->subjectName ) ) ? \\\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_DN_PARTIAL : 0 ),\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded certificate request will be */\n\tpayloadLength = subjectCertInfoPtr->publicKeyInfoSize;\n\tif( DATAPTR_ISSET( subjectCertInfoPtr->subjectName ) )\n\t\t{\n\t\tstatus = subjectDNsize = sizeofDN( subjectCertInfoPtr->subjectName );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsubjectCertInfoPtr->subjectDNsize = subjectDNsize;\n\t\tpayloadLength += sizeofObject( subjectDNsize );\n\t\t}\n\tif( subjectCertInfoPtr->startTime > MIN_TIME_VALUE )\n\t\ttimeSize = sizeofObject( sizeofGeneralizedTime() );\n\tif( subjectCertInfoPtr->endTime > MIN_TIME_VALUE )\n\t\ttimeSize += sizeofObject( sizeofGeneralizedTime() );\n\tif( timeSize > 0 ) \n\t\tpayloadLength += sizeofObject( timeSize );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_CERT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( extensionSize > 0 )\n\t\tpayloadLength += sizeofObject( extensionSize );\n\n\t/* Write the header, request ID, inner header, DN, and public key */\n\twriteSequence( stream, sizeofShortInteger( 0 ) + \\\n\t\t\t\t   sizeofObject( payloadLength ) );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\twriteSequence( stream, payloadLength );\n\tif( timeSize > 0 )\n\t\t{\n\t\twriteConstructed( stream, timeSize, CTAG_CF_VALIDITY );\n\t\tif( subjectCertInfoPtr->startTime > MIN_TIME_VALUE )\n\t\t\t{\n\t\t\twriteConstructed( stream, sizeofGeneralizedTime(), 0 );\n\t\t\twriteGeneralizedTime( stream, subjectCertInfoPtr->startTime,\n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t}\n\t\tif( subjectCertInfoPtr->endTime > MIN_TIME_VALUE )\n\t\t\t{\n\t\t\twriteConstructed( stream, sizeofGeneralizedTime(), 1 );\n\t\t\twriteGeneralizedTime( stream, subjectCertInfoPtr->endTime,\n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t}\n\t\t}\n\tif( subjectDNsize > 0 )\n\t\t{\n\t\tstatus = writeConstructed( stream, subjectCertInfoPtr->subjectDNsize,\n\t\t\t\t\t\t\t\t   CTAG_CF_SUBJECT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = writeDN( stream, subjectCertInfoPtr->subjectName,\n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsputc( stream, MAKE_CTAG( CTAG_CF_PUBLICKEY ) );\n\t\t   \t/* Convert the SPKI SEQUENCE tag to the CRMF alternative */\n\tstatus = swrite( stream, \n\t\t\t\t\t ( BYTE * ) subjectCertInfoPtr->publicKeyInfo + 1,\n\t\t\t\t\t subjectCertInfoPtr->publicKeyInfoSize - 1 );\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\tstatus = writeConstructed( stream, extensionSize, CTAG_CF_EXTENSIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_CERT, \n\t\t\t\t\t\t\t\t  extensionSize );\n\t\t}\n\treturn( status );\n\t}\n\n/* Write CRMF revocation request information:\n\n\tRevDetails ::= SEQUENCE {\n\t\tcertTemplate\t\t\tSEQUENCE {\n\t\t\tserialNumber  [ 1 ]\tINTEGER,\n\t\t\tissuer\t\t  [ 3 ]\tEXPLICIT Name,\n\t\t\t},\n\t\tcrlEntryDetails\t\t\tSET OF Attribute\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRevRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tint payloadLength, extensionSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED );\n\n\t/* Make sure that everything is in order */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, NULL, \n\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERDN | PRE_CHECK_SERIALNO,\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded certificate request will be */\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpayloadLength = sizeofInteger( subjectCertInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t\t   subjectCertInfoPtr->cCertCert->serialNumberLength ) + \\\n\t\t\t\t\tsizeofObject( subjectCertInfoPtr->issuerDNsize );\n\tif( extensionSize > 0 )\n\t\tpayloadLength += sizeofObject( extensionSize );\n\n\t/* Write the header, inner header, serial number and issuer DN */\n\twriteSequence( stream, sizeofObject( payloadLength ) );\n\twriteSequence( stream, payloadLength );\n\twriteInteger( stream, subjectCertInfoPtr->cCertCert->serialNumber,\n\t\t\t\t  subjectCertInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t  CTAG_CF_SERIALNUMBER );\n\twriteConstructed( stream, subjectCertInfoPtr->issuerDNsize,\n\t\t\t\t\t  CTAG_CF_ISSUER );\n\tstatus = swrite( stream, subjectCertInfoPtr->issuerDNptr,\n\t\t\t\t\t subjectCertInfoPtr->issuerDNsize );\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\tstatus = writeConstructed( stream, extensionSize, CTAG_CF_EXTENSIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION, \n\t\t\t\t\t\t\t\t  extensionSize );\n\t\t}\n\treturn( status );\n\t}\n#endif /* USE_CERTREQ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Validity-checking Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTVAL\n\n/* Write an RTCS request:\n\n\tRTCSRequests ::= SEQUENCE {\n\t\tSEQUENCE OF SEQUENCE {\n\t\t\tcertHash\tOCTET STRING SIZE(20)\n\t\t\t},\n\t\tattributes\t\tAttributes OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRtcsRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t STDC_UNUSED \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tCERT_VAL_INFO *certValInfo = subjectCertInfoPtr->cCertVal;\n\tint length, extensionSize, requestInfoLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED );\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\t/* Generate a fresh nonce for the request */\n\t\tstatus = setNonce( &subjectCertInfoPtr->attributes, \n\t\t\t\t\t\t   CRYPT_CERTINFO_CMS_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Perform the pre-encoding checks */\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, NULL, \n\t\t\t\t\t\t\t\t\t  PRE_CHECK_VALENTRIES, PRE_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded RTCS request will be */\n\tstatus = requestInfoLength = \\\n\t\t\t\t\tsizeofRtcsRequestEntries( certValInfo->validityInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_RTCS_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = sizeofObject( requestInfoLength ) + \\\n\t\t\t ( ( extensionSize > 0 ) ? sizeofObject( extensionSize ) : 0 );\n\n\t/* Write the outer SEQUENCE wrapper */\n\twriteSequence( stream, length );\n\n\t/* Write the SEQUENCE OF request wrapper and the request information */\n\tstatus = writeSequence( stream, requestInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeRtcsRequestEntries( stream, \n\t\t\t\t\t\t\t\t\t\t  certValInfo->validityInfo );\n\t\t}\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_RTCS_REQUEST, extensionSize ) );\n\t}\n\n/* Write an RTCS response:\n\n\tRTCSResponse ::= SEQUENCE OF SEQUENCE {\n\t\tcertHash\tOCTET STRING SIZE(20),\n\t\tRESPONSEINFO\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRtcsResponseInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t  INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t  STDC_UNUSED \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tCERT_VAL_INFO *certValInfo = subjectCertInfoPtr->cCertVal;\n\tconst BOOLEAN isExtendedResponse = \\\n\t\t( certValInfo->responseType == RTCSRESPONSE_TYPE_EXTENDED ) ? \\\n\t\t  TRUE : FALSE;\n\tint extensionSize, validityInfoLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED );\n\n\t/* RTCS can legitimately return an empty response if there's a problem\n\t   with the responder so we don't require that any responses be present\n\t   as for CRLs/OCSP */\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, NULL,\n\t\t\t\t\t\t\t\t\t   PRE_SET_VALINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded RTCS response will be */\n\tstatus = validityInfoLength = \\\n\t\t\t\t\tsizeofRtcsResponseEntries( certValInfo->validityInfo,\n\t\t\t\t\t\t\t\t\t\t\t   isExtendedResponse );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_RTCS_RESPONSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the SEQUENCE OF status information wrapper and the certificate \n\t   status information */\n\tstatus = writeSequence( stream, validityInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeRtcsResponseEntries( stream, \n\t\t\t\t\t\t\t\t\t\t   certValInfo->validityInfo,\n\t\t\t\t\t\t\t\t\t\t   isExtendedResponse );\n\t\t}\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_RTCS_RESPONSE, extensionSize ) );\n\t}\n#endif /* USE_CERTVAL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Revocation-checking Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTREV\n\n/* Write an OCSP request:\n\n\tOCSPRequest ::= SEQUENCE {\t\t\t\t-- Write, v1\n\t\treqName\t\t[1]\tEXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,\n\t\treqList\t\t\tSEQUENCE OF SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- certID\n\t\t\thashAlgo\tAlgorithmIdentifier,\n\t\t\tiNameHash\tOCTET STRING,\n\t\t\tiKeyHash\tOCTET STRING,\n\t\t\tserialNo\tINTEGER\n\t\t\t} }\n\t\t}\n\n\tOCSPRequest ::= SEQUENCE {\t\t\t\t-- Write, v2 (not used)\n\t\tversion\t\t[0]\tEXPLICIT INTEGER (1),\n\t\treqName\t\t[1]\tEXPLICIT [4] EXPLICIT DirectoryName OPTIONAL,\n\t\treqList\t\t\tSEQUENCE OF SEQUENCE {\n\t\t\tcertID\t[2]\tEXPLICIT OCTET STRING\t-- Certificate hash\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeOcspRequestInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t IN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tCERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;\n\tint length, extensionSize, revocationInfoLength = 0;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( issuerCertInfoPtr == NULL || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\t/* Generate a fresh nonce for the request */\n\t\tstatus = setNonce( &subjectCertInfoPtr->attributes, \n\t\t\t\t\t\t   CRYPT_CERTINFO_OCSP_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Perform the pre-encoding checks */\n\t\tstatus = preEncodeCertificate( subjectCertInfoPtr, issuerCertInfoPtr, \n\t\t\t\t\t\t\t\t\t   PRE_SET_REVINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( issuerCertInfoPtr != NULL )\n\t\t\t{\n\t\t\t/* It's a signed request, there has to be an issuer DN present */\n\t\t\tstatus = preCheckCertificate( subjectCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  issuerCertInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERDN | \\\n\t\t\t\t\t\t\t\t\t\t  PRE_CHECK_REVENTRIES,\n\t\t\t\t\t\t\t\t\t\t  PRE_FLAG_DN_IN_ISSUERCERT );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = preCheckCertificate( subjectCertInfoPtr, NULL,\n\t\t\t\t\t\t\t\t\t\t  PRE_CHECK_REVENTRIES, \n\t\t\t\t\t\t\t\t\t\t  PRE_FLAG_NONE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded OCSP request will be */\n\tstatus = revocationInfoLength = \\\n\t\t\t\t\tsizeofOcspRequestEntries( certRevInfo->revocations );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_OCSP_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = ( ( subjectCertInfoPtr->version == 2 ) ? \\\n\t\t\t\t sizeofObject( sizeofShortInteger( CTAG_OR_VERSION ) ) : 0 ) + \\\n\t\t\t ( ( issuerCertInfoPtr != NULL ) ? \\\n\t\t\t\t sizeofObject( sizeofObject( issuerCertInfoPtr->subjectDNsize ) ) : 0 ) + \\\n\t\t\t sizeofObject( revocationInfoLength );\n\tif( extensionSize > 0 )\n\t\tlength += sizeofObject( sizeofObject( extensionSize ) );\n\n\t/* Write the outer SEQUENCE wrapper */\n\twriteSequence( stream, length );\n\n\t/* If we're using v2 identifiers, mark this as a v2 request */\n\tif( subjectCertInfoPtr->version == 2 )\n\t\t{\n\t\twriteConstructed( stream, sizeofShortInteger( 1 ), CTAG_OR_VERSION );\n\t\tstatus = writeShortInteger( stream, 1, DEFAULT_TAG );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If we're signing the request, write the issuer DN as a GeneralName */\n\tif( issuerCertInfoPtr != NULL )\n\t\t{\n\t\twriteConstructed( stream,\n\t\t\t\t\t\t  sizeofObject( issuerCertInfoPtr->subjectDNsize ), 1 );\n\t\twriteConstructed( stream, issuerCertInfoPtr->subjectDNsize, 4 );\n\t\tstatus = swrite( stream, issuerCertInfoPtr->subjectDNptr,\n\t\t\t\t\t\t issuerCertInfoPtr->subjectDNsize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the SEQUENCE OF revocation information wrapper and the\n\t   revocation information */\n\tstatus = writeSequence( stream, revocationInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeOcspRequestEntries( stream, certRevInfo->revocations );\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_OCSP_REQUEST, extensionSize ) );\n\t}\n\n/* Write an OCSP response:\n\n\tOCSPResponse ::= SEQUENCE {\n\t\tversion\t\t[0]\tEXPLICIT INTEGER (1),\n\t\trespID\t\t[1]\tEXPLICIT Name,\n\t\tproducedAt\t\tGeneralizedTime,\n\t\tresponses\t\tSEQUENCE OF Response\n\t\texts\t\t[1]\tEXPLICIT Extensions OPTIONAL,\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeOcspResponseInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t  INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t\t\t  IN const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t  IN_HANDLE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tCERT_REV_INFO *certRevInfo = subjectCertInfoPtr->cCertRev;\n\tint length, extensionSize, revocationInfoLength = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( isReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iIssuerCryptContext ) );/* Not used here */\n\n\t/* Perform any necessary pre-encoding steps */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = preCheckCertificate( subjectCertInfoPtr, issuerCertInfoPtr,\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_ISSUERDN | \\\n\t\t\t\t\t\t\t\t\t  PRE_CHECK_REVENTRIES,\n\t\t\t\t\t\t\t\t\t  PRE_FLAG_DN_IN_ISSUERCERT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine how big the encoded OCSP response will be */\n\tstatus = revocationInfoLength = \\\n\t\t\t\t\tsizeofOcspResponseEntries( certRevInfo->revocations );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = extensionSize = \\\n\t\t\t\t\tsizeofAttributes( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = sizeofObject( sizeofShortInteger( CTAG_OP_VERSION ) ) + \\\n\t\t\t sizeofObject( issuerCertInfoPtr->subjectDNsize ) + \\\n\t\t\t sizeofGeneralizedTime() + \\\n\t\t\t sizeofObject( revocationInfoLength );\n\tif( extensionSize > 0 )\n\t\tlength += sizeofObject( sizeofObject( extensionSize ) );\n\n\t/* Write the outer SEQUENCE wrapper, version, and issuer DN and \n\t   producedAt time */\n\twriteSequence( stream, length );\n\twriteConstructed( stream, sizeofShortInteger( 1 ), CTAG_OP_VERSION );\n\twriteShortInteger( stream, 1, DEFAULT_TAG );\n\twriteConstructed( stream, issuerCertInfoPtr->subjectDNsize, 1 );\n\tswrite( stream, issuerCertInfoPtr->subjectDNptr,\n\t\t\tissuerCertInfoPtr->subjectDNsize );\n\tstatus = writeGeneralizedTime( stream, subjectCertInfoPtr->startTime,\n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the SEQUENCE OF revocation information wrapper and the\n\t   revocation information */\n\tstatus = writeSequence( stream, revocationInfoLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeOcspResponseEntries( stream, certRevInfo->revocations,\n\t\t\t\t\t\t\t\t\t\t   subjectCertInfoPtr->startTime );\n\t\t}\n\tif( cryptStatusError( status ) || extensionSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\treturn( writeAttributes( stream, subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_OCSP_RESPONSE, extensionSize ) );\n\t}\n#endif /* USE_CERTREV */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite CMS Attribute Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CMSATTR\n\n/* Write CMS attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCmsAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT CERT_INFO *attributeInfoPtr,\n\t\t\t\t\t\t\t   STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t   STDC_UNUSED const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tint attributeSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( attributeInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( attributeInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED );\n\tREQUIRES( DATAPTR_ISSET( attributeInfoPtr->attributes ) );\n\n\t/* Make sure that there's a hash and content type present */\n\tif( !checkAttributePresent( attributeInfoPtr->attributes,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_MESSAGEDIGEST ) )\n\t\t{\n\t\tsetErrorInfo( attributeInfoPtr, CRYPT_CERTINFO_CMS_MESSAGEDIGEST,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\tif( !checkAttributePresent( attributeInfoPtr->attributes,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_CONTENTTYPE ) )\n\t\t{\n\t\tsetErrorInfo( attributeInfoPtr, CRYPT_CERTINFO_CMS_CONTENTTYPE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* Check that the attributes are in order and determine how big the whole\n\t   mess will be */\n\tstatus = checkAttributes( ATTRIBUTE_CMS, attributeInfoPtr->attributes,\n\t\t\t\t\t\t\t  &attributeInfoPtr->errorLocus,\n\t\t\t\t\t\t\t  &attributeInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = attributeSize = \\\n\t\t\t\t\tsizeofAttributes( attributeInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tif( cryptStatusError( status ) || attributeSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the attributes */\n\treturn( writeAttributes( stream, attributeInfoPtr->attributes,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CMS_ATTRIBUTES, attributeSize ) );\n\t}\n#endif /* USE_CMSATTR */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite PKI User Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKIUSER\n\n/* Write PKI user information:\n\n\tuserData ::= SEQUENCE {\n\t\tname\t\t\t\tName,\t\t\t-- Name for CMP\n\t\tencAlgo\t\t\t\tAlgorithmIdentifier,-- Algo to encrypt passwords\n\t\tencPW\t\t\t\tOCTET STRING,\t-- Encrypted passwords\n\t\tcertAttributes\t\tAttributes\t\t-- Certificate attributes\n\t\tuserAttributes\t\tSEQUENCE {\t\t-- PKI user attributes\n\t\t\tisRA\t\t\tBOOLEAN OPTIONAL -- Whether user is an RA\n\t\t\t} OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5, 7 ) ) \\\nstatic int createPkiUserInfo( INOUT CERT_PKIUSER_INFO *certUserInfo,\n\t\t\t\t\t\t\t  OUT_BUFFER( maxUserInfoSize, *userInfoSize ) \\\n\t\t\t\t\t\t\t\t\tBYTE *userInfo, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 64 ) \\\n\t\t\t\t\t\t\t\t\tconst int maxUserInfoSize, \n\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxUserInfoSize ) \\\n\t\t\t\t\t\t\t\t\tint *userInfoSize, \n\t\t\t\t\t\t\t  OUT_BUFFER( maxCryptAlgoIDSize, *cryptAlgoIDSize ) \\\n\t\t\t\t\t\t\t\t\tBYTE *cryptAlgoID, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\tconst int maxCryptAlgoIDSize, \n\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxCryptAlgoIDSize ) \\\n\t\t\t\t\t\t\t\t\tint *cryptAlgoIDSize )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE encryptedDataBuffer[ 16 + 8 ];\n\tint userInfoBufPos DUMMY_INIT, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( certUserInfo, sizeof( CERT_PKIUSER_INFO ) ) );\n\tassert( isWritePtrDynamic( userInfo, maxUserInfoSize ) );\n\tassert( isWritePtr( userInfoSize, sizeof( int ) ) );\n\tassert( isWritePtrDynamic( cryptAlgoID, maxCryptAlgoIDSize ) );\n\tassert( isWritePtr( cryptAlgoIDSize, sizeof( int ) ) );\n\n\tREQUIRES( maxUserInfoSize >= 64 && \\\n\t\t\t  maxUserInfoSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( maxCryptAlgoIDSize >= 16 && \\\n\t\t\t  maxCryptAlgoIDSize < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( userInfo, 0, maxUserInfoSize );\n\tmemset( cryptAlgoID, 0, maxCryptAlgoIDSize );\n\t*userInfoSize = *cryptAlgoIDSize = 0;\n\n\t/* Create a stream-cipher encryption context and use it to generate the \n\t   user passwords.  These aren't encryption keys but just authenticators \n\t   used for MACing so we don't go to the usual extremes to protect \n\t   them */\n\tsetMessageCreateObjectInfo( &createInfo, DEFAULT_CRYPT_ALGO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\tstatus = krnlSendNotifier( iCryptContext, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendNotifier( iCryptContext, IMESSAGE_CTX_GENIV );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Create the PKI user authenticators */\n\tstatic_assert( PKIUSER_AUTHENTICATOR_SIZE <= 16, \n\t\t\t\t   \"pkiUser authenticator size\" );\n\tmemset( encryptedDataBuffer, 0, 16 );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t  encryptedDataBuffer, 16 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmemcpy( certUserInfo->pkiIssuePW, encryptedDataBuffer, \n\t\t\t\tPKIUSER_AUTHENTICATOR_SIZE );\n\t\tmemset( encryptedDataBuffer, 0, 16 );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  encryptedDataBuffer, 16 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmemcpy( certUserInfo->pkiRevPW, encryptedDataBuffer, \n\t\t\t\tPKIUSER_AUTHENTICATOR_SIZE );\n\t\t}\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Encode the user information so that it can be encrypted */\n\tsMemOpen( &stream, userInfo, maxUserInfoSize );\n\twriteSequence( &stream, 2 * sizeofObject( PKIUSER_AUTHENTICATOR_SIZE ) );\n\twriteOctetString( &stream, certUserInfo->pkiIssuePW,\n\t\t\t\t\t  PKIUSER_AUTHENTICATOR_SIZE, DEFAULT_TAG );\n\tstatus = writeOctetString( &stream, certUserInfo->pkiRevPW,\n\t\t\t\t\t\t\t   PKIUSER_AUTHENTICATOR_SIZE, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tuserInfoBufPos = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Encrypt (or at least mask) the user information.  For forwards \n\t   compatibility (and because the format requires the use of some form \n\t   of encryption when encoding the data) we encrypt the user data, once \n\t   user roles are fully implemented this can use the data storage key \n\t   associated with the CA user to perform the encryption instead of a \n\t   fixed interop key.  This isn't a security issue because the CA \n\t   database is assumed to be secure (or at least the CA is in serious \n\t   trouble if its database isn't secured), we encrypt because it's \n\t   pretty much free and because it doesn't hurt either way.  Most CA \n\t   guidelines merely require that the CA protect its user database via \n\t   standard (physical/ACL) security measures so this is no less secure \n\t   than what's required by various CA guidelines.\n\n\t   When we do this for real we probably need an extra level of \n\t   indirection to go from the CA secret to the database decryption key \n\t   so that we can change the encryption algorithm and so that we don't \n\t   have to directly apply the CA's data storage key to the user \n\t   database */\n\tsetMessageCreateObjectInfo( &createInfo, DEFAULT_CRYPT_ALGO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n#ifdef DEFAULT_ALGO_AES\n\tsetMessageData( &msgData, \"interop interop \", 16 );\n#else\n\tsetMessageData( &msgData, \"interop interop interop \", 24 );\n#endif /* AES vs. 3DES key size */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add PKCS #5 padding to the end of the user information and encrypt \n\t   it */\n\tREQUIRES( userInfoBufPos + 2 == PKIUSER_ENCR_AUTHENTICATOR_SIZE );\n\tLOOP_SMALL( i = 0, i < 2, i++ )\n\t\tuserInfo[ userInfoBufPos++ ] = 2;\n\tENSURES( LOOP_BOUND_OK );\n\tstatus = krnlSendNotifier( iCryptContext, IMESSAGE_CTX_GENIV );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT, \n\t\t\t\t\t\t\t\t  userInfo, userInfoBufPos );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsMemOpen( &stream, cryptAlgoID, maxCryptAlgoIDSize );\n\t\tstatus = writeCryptContextAlgoID( &stream, iCryptContext );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*cryptAlgoIDSize = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\t}\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*userInfoSize = userInfoBufPos;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writePkiUserInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT CERT_INFO *userInfoPtr,\n\t\t\t\t\t\t\t STDC_UNUSED const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t\t STDC_UNUSED const CRYPT_CONTEXT iIssuerCryptContext )\n\t{\n\tCERT_PKIUSER_INFO *certUserInfo = userInfoPtr->cCertUser;\n\tBYTE userInfo[ 128 + 8 ], cryptAlgoID[ 128 + 8 ];\n\tint certAttributeSize, userAttributeSize = 0, userInfoSize;\n\tint cryptAlgoIDSize, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( userInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( userInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL );\n\tREQUIRES( iIssuerCryptContext == CRYPT_UNUSED );\n\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE dummy1;\n\t\tCRYPT_ERRTYPE_TYPE dummy2;\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE keyID[ 16 + 8 ];\n\t\tint keyIDlength DUMMY_INIT;\n\n\t\t/* Generate the key identifier.  Once it's in user-encoded form the\n\t\t   full identifier can't quite fit so we adjust the size to the\n\t\t   maximum amount that we can encode by creating the encoded form \n\t\t   (which trims the input to fit) and then decoding it again.  This \n\t\t   is necessary because it's also used to locate the user information \n\t\t   in a key store, if we used the un-adjusted form for the key ID then \n\t\t   we couldn't locate the stored user information using the adjusted \n\t\t   form */\n\t\tsetMessageData( &msgData, keyID, 16 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tchar encodedKeyID[ 32 + 8 ];\n\t\t\tint encKeyIdSize;\n\n\t\t\tstatus = encodePKIUserValue( encodedKeyID, 32, &encKeyIdSize,\n\t\t\t\t\t\t\t\t\t\t keyID, 16, 3 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = decodePKIUserValue( keyID, 16, &keyIDlength,\n\t\t\t\t\t\t\t\t\t\t\t encodedKeyID, encKeyIdSize );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = addAttributeFieldString( &userInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE, keyID, \n\t\t\t\t\t\t\t\t\t\t  keyIDlength, 0, &dummy1, &dummy2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = checkAttributes( ATTRIBUTE_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t  userInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  &userInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t  &userInfoPtr->errorType );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* We can't generate the user information yet since we're doing the \n\t\t   pre-encoding pass and writing to a null stream so we leave it for \n\t\t   the actual encoding pass and only provide a size estimate for \n\t\t   now */\n\t\tuserInfoSize = PKIUSER_ENCR_AUTHENTICATOR_SIZE;\n\n\t\t/* Since we can't use the CA's data storage key yet we set the \n\t\t   algorithm ID size to the size of the information for the fixed \n\t\t   AES or 3DES key */\n#ifdef DEFAULT_ALGO_AES\n\t\tcryptAlgoIDSize = 31;\n#else\n\t\tcryptAlgoIDSize = 22;\n#endif /* AES vs. 3DES algoID size */\n\t\t}\n\telse\n\t\t{\n\t\tstatus = createPkiUserInfo( certUserInfo, userInfo, 128, \n\t\t\t\t\t\t\t\t\t&userInfoSize, cryptAlgoID, 128, \n\t\t\t\t\t\t\t\t\t&cryptAlgoIDSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Determine the size of the user information */\n\tstatus = length = sizeofDN( userInfoPtr->subjectName );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tuserInfoPtr->subjectDNsize = length;\n\tstatus = certAttributeSize = \\\n\t\t\t\t\tsizeofAttributes( userInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( isShortIntegerRangeNZ( certAttributeSize ) );\n\tif( certUserInfo->isRA )\n\t\tuserAttributeSize += sizeofBoolean();\n\n\t/* Write the user DN, encrypted user information, and any supplementary \n\t   information */\n\tstatus = writeDN( stream, userInfoPtr->subjectName, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswrite( stream, cryptAlgoID, cryptAlgoIDSize );\n\tstatus = writeOctetString( stream, userInfo, userInfoSize, \n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAttributes( stream, userInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER, \n\t\t\t\t\t\t\t\t  certAttributeSize );\n\t\t}\n\tif( cryptStatusOK( status ) && userAttributeSize > 0 )\n\t\t{\n\t\tstatus = writeSequence( stream, userAttributeSize );\n\t\tif( certUserInfo->isRA )\n\t\t\tstatus = writeBoolean( stream, TRUE, DEFAULT_TAG );\n\t\t}\n\treturn( status );\n\t}\n#endif /* USE_PKIUSER */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Function Access Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst CRYPT_CERTTYPE_TYPE type;\n\tconst WRITECERT_FUNCTION function;\n\t} CERTWRITE_INFO;\nstatic const CERTWRITE_INFO certWriteTable[] = {\n\t{ CRYPT_CERTTYPE_CERTIFICATE, writeCertInfo },\n\t{ CRYPT_CERTTYPE_CERTCHAIN, writeCertInfo },\n#ifdef USE_ATTRCERT\n\t{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, writeAttributeCertInfo },\n#endif /* USE_ATTRCERT */\n#ifdef USE_CERTREV\n\t{ CRYPT_CERTTYPE_CRL, writeCRLInfo },\n#endif /* USE_CERTREV */\n#ifdef USE_CERTREQ\n\t{ CRYPT_CERTTYPE_CERTREQUEST, writeCertRequestInfo },\n\t{ CRYPT_CERTTYPE_REQUEST_CERT, writeCrmfRequestInfo },\n\t{ CRYPT_CERTTYPE_REQUEST_REVOCATION, writeRevRequestInfo },\n#endif /* USE_CERTREQ */\n#ifdef USE_CERTVAL\n\t{ CRYPT_CERTTYPE_RTCS_REQUEST, writeRtcsRequestInfo },\n\t{ CRYPT_CERTTYPE_RTCS_RESPONSE, writeRtcsResponseInfo },\n#endif /* USE_CERTVAL */\n#ifdef USE_CERTREV\n\t{ CRYPT_CERTTYPE_OCSP_REQUEST, writeOcspRequestInfo },\n\t{ CRYPT_CERTTYPE_OCSP_RESPONSE, writeOcspResponseInfo },\n#endif /* USE_CERTREV */\n#ifdef USE_CMSATTR\n\t{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, writeCmsAttributes },\n#endif /* USE_CMSATTR */\n#ifdef USE_PKIUSER\n\t{ CRYPT_CERTTYPE_PKIUSER, writePkiUserInfo },\n#endif /* USE_PKIUSER */\n\t{ CRYPT_CERTTYPE_NONE, NULL }, { CRYPT_CERTTYPE_NONE, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nWRITECERT_FUNCTION getCertWriteFunction( IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( certType, CRYPT_CERTTYPE ) );\n\n\tLOOP_MED( i = 0, \n\t\t\t  certWriteTable[ i ].type != CRYPT_CERTTYPE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( certWriteTable, CERTWRITE_INFO ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( certWriteTable[ i ].type == certType )\n\t\t\treturn( certWriteTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( certWriteTable, CERTWRITE_INFO ) );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cert/write_pre.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Write Preparation Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"cert.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* Before we encode a certificate object we have to perform various final \n   setup actions and check that the object is ready for encoding.  The setup \n   operations and checks for the different object types are:\n\n\t\t\t\t|  Cert\t|  Attr\t|  P10\t|Cr.Req\t|Rv.Req\t\n\t------------+-------+-------+-------+-------+-------+\n\tSTDATTR\t\t|\tX[1]|\t\t|\t\t|\t\t|\t\t| Setup \n\tISSUERATTR\t|\tX\t|\tX\t|\t\t|\t\t|\t\t| action\n\tISSUERDN\t|\tX\t|\tX\t|\t\t|\t\t|\t\t|\n\tVALPERIOD\t|\tX\t|\tX\t|\t\t|\t\t|\t\t|\n\tVALINFO\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tREVINFO\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\t------------+-------+-------+-------+-------+-------+\n\tSPKI\t\t|\tX\t|\t\t|\tX\t|\tX\t|\t\t| Check\n\tDN\t\t\t|\tX\t|\tX\t|\t\t|\t\t|\t\t|\n\tDN_PART\t\t|\t\t|\t\t|\tX\t|\tX\t|\t\t|\n\tISSUERDN\t|\tX\t|\tX\t|\t\t|\t\t|\tX\t|\n\tISSUERCRTDN\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tNON_SELFSD\t|\tX\t|\tX\t|\t\t|\t\t|\t\t|\n\tSERIALNO\t|\tX\t|\tX\t|\t\t|\t\t|\tX\t|\n\tREVENTRIES\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\t------------+-------+-------+-------+-------+-------+\n\n\t\t\t\t|RTCS Rq|RTCS Rs|OCSP Rq|OCSP Rs|  CRL\t|CRLentr|\n\t------------+-------+-------+-------+-------+-------+-------+\n\tSTDATTR\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t| Setup \n\tISSUERATTR\t|\t\t|\t\t|\t\t|\t\t|\tX\t|\t\t| action\n\tISSUERDN\t|\t\t|\t\t|\t\t|\t\t|\tX\t|\t\t|\n\tVALPERIOD\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tVALINFO\t\t|\tX\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tREVINFO\t\t|\t\t|\t\t|\tX\t|\t\t|\tX\t|\tX\t|\n\t------------+-------+-------+-------+-------+-------+-------+\n\tSPKI\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t| Check\n\tDN\t\t\t|\t\t|\t\t|\t\t|\tX\t|\t\t|\t\t|\n\tDN_PART\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tISSUERDN\t|\t\t|\t\t|\t\t|\t\t|\tX\t|\t\t|\n\tISSUERCRTDN\t|\t\t|\t\t|\t\t|\t\t|\tX\t|\t\t|\n\tNON_SELFSD\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tSERIALNO\t|\t\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tVALENTRIES\t|\tX\t|\t\t|\t\t|\t\t|\t\t|\t\t|\n\tREVENTRIES\t|\t\t|\t\t|\tX\t|\tX\t|\t\t|\t\t|\n\t------------+-------+-------+-------+-------+-------+-------+ \n\n   We have to be careful here to avoid race conditions when some of the \n   checks depend on setup actions having been performed first but some of\n   the setup actions require that checks be performed first.  The noted\n   exceptions are:\n\n\t[1] Requires that the SPKI check be performed first since STDATTR\n\t\tevaluates keyUsage from the SPKI */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add standard X.509v3 extensions to a certificate if they're not already \n   present.  This function simply adds the required extensions, it doesn't \n   check for consistency with existing extensions which is done later by \n   checkAttributes() and checkCert() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addStandardExtensions( INOUT CERT_INFO *certInfoPtr )\n\t{\n\tBOOLEAN isCA = FALSE;\n\tint keyUsage, extKeyUsage, value, status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* Get the implicit keyUsage flags (based on any extended key usage \n\t   extensions present) and explicit key usage flags, which we use to \n\t   extend the basic keyUsage flags if required */\n\tstatus = getKeyUsageFromExtKeyUsage( certInfoPtr, &extKeyUsage,\n\t\t\t\t\t\t&certInfoPtr->errorLocus, &certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = getAttributeFieldValue( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_NONE, &keyUsage );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\n\t\t/* There's no keyUsage attribute present, mark the value as being \n\t\t   not set so that we explicitly set it later */\n\t\tkeyUsage = CRYPT_ERROR;\n\t\t}\n\n\t/* If there's an explicit key usage present, make sure that it's\n\t   consistent with the implicit key usage flags derived from the \n\t   extended key usage.  We mask out the nonRepudiation bit for reasons \n\t   given in chk_cert.c.\n\n\t   This check is also performed by checkCert(), however we need to\n\t   explicitly perform it here as well since we need to add a key usage \n\t   to match the extKeyUsage before calling checkCert() if one wasn't\n\t   explicitly set or checkCert() will reject the certificate because of \n\t   the inconsistent keyUsage */\n\tif( keyUsage > 0 )\n\t\t{\n\t\tconst int effectiveKeyUsage = \\\n\t\t\t\t\t\textKeyUsage & ~CRYPT_KEYUSAGE_NONREPUDIATION;\n\n\t\tif( ( keyUsage & effectiveKeyUsage ) != effectiveKeyUsage )\n\t\t\t{\n\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* Check whether this is a CA certificate.  If there's no \n\t   basicConstraints attribute present, add one and make it a non-CA \n\t   certificate */\n\tstatus = getAttributeFieldValue( certInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t &value );\n\tif( cryptStatusOK( status ) )\n\t\tisCA = ( value > 0 ) ? TRUE : FALSE;\n\telse\n\t\t{\n\t\tstatus = addCertComponent( certInfoPtr, CRYPT_CERTINFO_CA, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's no explicit keyUsage information present add it based on\n\t   various implicit information.  We also add key feature information\n\t   which is used to help automate key management, for example to inhibit\n\t   speculative reads of keys held in removable tokens, which can result\n\t   in spurious insert-token dialogs being presented to the user outside\n\t   the control of cryptlib if the token isn't present */\n\tif( keyUsage <= 0 )\n\t\t{\n\t\t/* If there's no implicit key usage present and it's not a CA (for \n\t\t   which we don't want to set things like encryption flags for the\n\t\t   CA certificate), set the key usage flags based on the \n\t\t   capabilities of the associated context.  Because no-one can \n\t\t   figure out what the nonRepudiation flag signifies we don't set \n\t\t   this, if the user wants it they have to specify it explicitly.  \n\t\t   Similarly we don't try and set the keyAgreement encipher/decipher-\n\t\t   only flags, which were tacked on as variants of keyAgreement long \n\t\t   after the basic keyAgreement flag was defined */\n\t\tif( extKeyUsage <= 0 && !isCA )\n\t\t\t{\n\t\t\tkeyUsage = 0;\t/* Reset key usage */\n\t\t\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\t/* There's a context present, check its capabilities.  \n\t\t\t\t   Checking via a kernel call has the advantage that it \n\t\t\t\t   takes into account any ACLs that may exist for the key */\n\t\t\t\tif( checkContextCapability( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_SIGCHECK ) )\n\t\t\t\t\tkeyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE;\n\t\t\t\tif( checkContextCapability( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\t\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\t\t\tif( checkContextCapability( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_KA_EXPORT ) || \\\n\t\t\t\t\tcheckContextCapability( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_KA_IMPORT ) )\n\t\t\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* There's no context present (the key is present as encoded\n\t\t\t\t   data), assume we can do whatever the algorithm allows */\n\t\t\t\tif( isSigAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\t\t\tkeyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE;\n\t\t\t\tif( isCryptAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\t\t\tif( isKeyxAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\t\t\tkeyUsage |= CRYPT_KEYUSAGE_KEYAGREEMENT;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* There's an extended key usage set but no basic keyUsage, make \n\t\t\t   the keyUsage consistent with the usage flags derived from the \n\t\t\t   extended usage */\n\t\t\tkeyUsage = extKeyUsage;\n\n\t\t\t/* If it's a CA key, make sure that it's a signing key and\n\t\t\t   enable its use for certification-related purposes*/\n\t\t\tif( isCA )\n\t\t\t\t{\n\t\t\t\tBOOLEAN usageOK = FALSE;\n\n\t\t\t\tif( certInfoPtr->iPubkeyContext != CRYPT_ERROR )\n\t\t\t\t\t{\n\t\t\t\t\tif( checkContextCapability( certInfoPtr->iPubkeyContext, \n\t\t\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_SIGCHECK ) )\n\t\t\t\t\t\tusageOK = TRUE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( isSigAlgo( certInfoPtr->publicKeyAlgo ) )\n\t\t\t\t\t\tusageOK = TRUE;\n\t\t\t\t\t}\n\t\t\t\tif( !usageOK )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_CA,\n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t\t\t}\n\t\t\t\tkeyUsage |= KEYUSAGE_CA;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( keyUsage > CRYPT_KEYUSAGE_NONE && \\\n\t\t\t\t keyUsage < CRYPT_KEYUSAGE_LAST );\n\t\tstatus = addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t\t\t   keyUsage );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( certInfoPtr->publicKeyFeatures > 0 )\n\t\t{\n\t\t/* This is a bitstring so we only add it if there are feature flags\n\t\t   present to avoid writing zero-length values */\n\t\tstatus = addCertComponent( certInfoPtr, CRYPT_CERTINFO_KEYFEATURES,\n\t\t\t\t\t\t\t\t   certInfoPtr->publicKeyFeatures );\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_INITED )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Add the subjectKeyIdentifier */\n\treturn( addCertComponentString( certInfoPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t\t\t\t\t\t\t\t\tcertInfoPtr->publicKeyID, KEYID_SIZE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPre-encode Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether an empty DN is permitted in a certificate.  This is a PKIX \n   peculiarity that causes severe problems for virtually all certificate-\n   using protocols so we only allow it at a compliance level of \n   CRYPT_COMPLIANCELEVEL_PKIX_FULL */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkEmptyDnOK( INOUT CERT_INFO *subjectCertInfoPtr )\n\t{\n\tDATAPTR_ATTRIBUTE attribute;\n\tBOOLEAN_INT isCA;\n\tint complianceLevel, status;\n\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\t/* PKIX allows empty subject DNs if a subject altName is present, \n\t   however creating certificates like this breaks pretty much every \n\t   certificate-using protocol so we only allow it at the highest \n\t   compliance level */\n\tstatus = krnlSendMessage( subjectCertInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel,\n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) || \\\n\t\tcomplianceLevel < CRYPT_COMPLIANCELEVEL_PKIX_FULL )\n\t\treturn( FALSE );\n\t   \n\t/* We also have to be very careful to ensure that the empty subject \n\t   DN can't end up becoming an empty issuer DN, which can occur if it's \n\t   a self-signed certificate */\n\tif( TEST_FLAG( subjectCertInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t{\n\t\t/* We can't have an empty issuer (== subject) DN */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* In addition if it's a CA certificate then the subject DN can't be \n\t   empty, for obvious reasons */\n\tstatus = getAttributeFieldValue( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_CA, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t\t\t\t\t &isCA );\n\tif( cryptStatusOK( status ) && isCA )\n\t\t{\n\t\t/* It's a CA certificate, the subject DN can't be empty */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Finally, if there's no subject DN present then there has to be an \n\t   altName present to take its place */\n\tattribute = findAttributeField( subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME,\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE );\n\tif( DATAPTR_ISNULL( attribute ) )\n\t\t{\n\t\t/* Either a subject DN or subject altName must be present */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* There's a subject altName present but no subject DN, mark the altName \n\t   as critical */\n\tsetAttributeProperty( attribute, ATTRIBUTE_PROPERTY_CRITICAL, 0 );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n/* Perform any final setup actions that add default and issuer-contributed \n   attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint preEncodeCertificate( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t  IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t  IN_FLAGS( PRE_SET ) const int actions )\n\t{\n\tint status;\n\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( issuerCertInfoPtr == NULL ) || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( actions >= PRE_SET_NONE && \\\n\t\t\t  actions <= PRE_SET_FLAG_MAX );\n\tREQUIRES( ( ( actions & ( PRE_SET_ISSUERATTR | PRE_SET_ISSUERDN | \\\n\t\t\t\t\t\t\t  PRE_SET_VALIDITYPERIOD ) ) && \\\n\t\t\t\tissuerCertInfoPtr != NULL ) || \\\n\t\t\t  !( actions & ( PRE_SET_ISSUERATTR | PRE_SET_ISSUERDN | \\\n\t\t\t\t\t\t\t PRE_SET_VALIDITYPERIOD ) ) );\n\n\t/* If it's a >= v3 certificate, add the standard X.509v3 extensions if \n\t   these aren't already present */\n\tif( actions & PRE_SET_STANDARDATTR )\n\t\t{\n\t\t/* Setting the standard attributes requires the presence of a public\n\t\t   key to get keyUsage information from, so we have to check this\n\t\t   before we can add any attributes.  This would normally be checked \n\t\t   as part of the range of checking performed in \n\t\t   preCheckCertificate(), but that isn't called until the pre-\n\t\t   encoding functions here have been performed */\n\t\tif( subjectCertInfoPtr->publicKeyInfo == NULL )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, \n\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\n\t\t/* Attributes are only allowed with version 3 certificates */\n\t\tif( subjectCertInfoPtr->version >= X509_V3 )\n\t\t\t{\n\t\t\tstatus = addStandardExtensions( subjectCertInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Copy any required extensions from the issuer to the subject \n\t   certificate if necessary */\n\tif( actions & PRE_SET_ISSUERATTR )\n\t\t{\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\n\t\tif( !TEST_FLAG( subjectCertInfoPtr->flags, CERT_FLAG_SELFSIGNED ) )\n\t\t\t{\n\t\t\tstatus = copyIssuerAttributes( &subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t   issuerCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t\t\t   subjectCertInfoPtr->type,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Copy the issuer DN if this isn't already present */\n\tif( actions & PRE_SET_ISSUERDN )\n\t\t{\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\n\t\tif( DATAPTR_ISNULL( subjectCertInfoPtr->issuerName ) )\n\t\t\t{\n\t\t\tstatus = copyDN( &subjectCertInfoPtr->issuerName,\n\t\t\t\t\t\t\t issuerCertInfoPtr->subjectName );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Constrain the subject validity period to be within the issuer \n\t   validity period */\n\tif( actions & PRE_SET_VALIDITYPERIOD )\n\t\t{\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\n\t\tif( subjectCertInfoPtr->startTime < issuerCertInfoPtr->startTime )\n\t\t\tsubjectCertInfoPtr->startTime = issuerCertInfoPtr->startTime;\n\t\tif( subjectCertInfoPtr->endTime > issuerCertInfoPtr->endTime )\n\t\t\tsubjectCertInfoPtr->endTime = issuerCertInfoPtr->endTime;\n\t\t}\n\n#ifdef USE_CERTVAL\n\t/* If it's an RTCS response, prepare the certificate status list entries \n\t   prior to encoding them */\n\tif( actions & PRE_SET_VALINFO )\n\t\t{\n\t\tCERT_VAL_INFO *valInfo = subjectCertInfoPtr->cCertVal;\n\t\tVALIDITY_INFO *validityErrorEntry = NULL;\n\n\t\tstatus = prepareValidityEntries( valInfo->validityInfo,\n\t\t\t\t\t\t\t\t\t\t &validityErrorEntry,\n\t\t\t\t\t\t\t\t\t\t &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t\t &subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* There was an error, select the entry that caused the \n\t\t\t   problem */\n\t\t\tDATAPTR_SET( valInfo->currentValidity, validityErrorEntry );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CERTREV\n\t/* If it's a CRL or OCSP response, prepare the revocation list entries \n\t   prior to encoding them */\n\tif( actions & PRE_SET_REVINFO )\n\t\t{\n\t\tCERT_REV_INFO *revInfo = subjectCertInfoPtr->cCertRev;\n\t\tREVOCATION_INFO *revocationErrorEntry = NULL;\n\t\tconst BOOLEAN isCrlEntry = \\\n\t\t\t\t\t\t( ( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CRL ) && \\\n\t\t\t\t\t\t  !( actions & PRE_SET_ISSUERDN ) ) ? TRUE : FALSE;\n\n\t\tstatus = prepareRevocationEntries( revInfo->revocations,\n\t\t\t\t\t\t\t\t\t\t   revInfo->revocationTime,\n\t\t\t\t\t\t\t\t\t\t   &revocationErrorEntry, isCrlEntry,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t\t\t   &subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If there was an error and we're processing an entire \n\t\t\t   revocation list, select the entry that caused the problem */\n\t\t\tif( !isCrlEntry )\n\t\t\t\t{\n\t\t\t\tDATAPTR_SET( revInfo->currentRevocation, revocationErrorEntry );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTREV */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check that a certificate object is reading for encoding */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint preCheckCertificate( INOUT CERT_INFO *subjectCertInfoPtr,\n\t\t\t\t\t\t IN_OPT const CERT_INFO *issuerCertInfoPtr,\n\t\t\t\t\t\t IN_FLAGS( PRE_CHECK ) const int actions, \n\t\t\t\t\t\t IN_FLAGS_Z( PRE ) const int flags )\n\t{\n\tint status;\n\n\tassert( isWritePtr( subjectCertInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( issuerCertInfoPtr == NULL ) || \\\n\t\t\tisReadPtr( issuerCertInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( subjectCertInfoPtr ) );\n\tREQUIRES( issuerCertInfoPtr == NULL || \\\n\t\t\t  sanityCheckCert( issuerCertInfoPtr ) );\n\tREQUIRES( actions >= PRE_CHECK_NONE && \\\n\t\t\t  actions <= PRE_CHECK_FLAG_MAX );\n\tREQUIRES( flags == PRE_FLAG_NONE || \\\n\t\t\t  flags == PRE_FLAG_DN_IN_ISSUERCERT );\n\tREQUIRES( ( ( actions & ( PRE_CHECK_ISSUERCERTDN | \\\n\t\t\t\t\t\t\t  PRE_CHECK_NONSELFSIGNED_DN ) ) && \\\n\t\t\t\tissuerCertInfoPtr != NULL ) || \\\n\t\t\t  !( actions & ( PRE_CHECK_ISSUERCERTDN | \\\n\t\t\t\t\t\t\t PRE_CHECK_NONSELFSIGNED_DN ) ) );\n\t\t\t  /* We can't impose a complete set of preconditions on the\n\t\t\t     issuer certificate because some issuer attributes like the \n\t\t\t\t issuer DN may already be present in the subject \n\t\t\t\t certificate */\n\n\t/* Make sure that there's public-key information present */\n\tif( actions & PRE_CHECK_SPKI )\n\t\t{\n\t\tif( subjectCertInfoPtr->publicKeyInfo == NULL )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, \n\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that there's a full DN present */\n\tif( actions & PRE_CHECK_DN )\n\t\t{\n\t\tstatus = checkDN( subjectCertInfoPtr->subjectName, \n\t\t\t\t\t\t  CHECKDN_FLAG_COUNTRY | CHECKDN_FLAG_COMMONNAME,\n\t\t\t\t\t\t  &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t  &subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t\t/* In some very special cases an empty DN is permitted so we\n\t\t\t   only return an error if this really isn't allowed */\n\t\t\tif( status != CRYPT_ERROR_NOTINITED || \\\n\t\t\t\t!checkEmptyDnOK( subjectCertInfoPtr ) )\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that there's at least a partial DN present (some CA's will \n\t   fill the upper portion of the DN themselves so at a minimum all that \n\t   we really need is a CommonName) */\n\tif( actions & PRE_CHECK_DN_PARTIAL )\n\t\t{\n\t\tstatus = checkDN( subjectCertInfoPtr->subjectName, \n\t\t\t\t\t\t  CHECKDN_FLAG_COMMONNAME,\n\t\t\t\t\t\t  &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t  &subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Make sure that there's an issuer DN present */\n\tif( actions & PRE_CHECK_ISSUERDN )\n\t\t{\n\t\tif( flags & PRE_FLAG_DN_IN_ISSUERCERT )\n\t\t\t{\n\t\t\tif( issuerCertInfoPtr == NULL || \\\n\t\t\t\tissuerCertInfoPtr->subjectDNptr == NULL || \\\n\t\t\t\tissuerCertInfoPtr->subjectDNsize < 1 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The issuer DN can be present either in pre-encoded form (if\n\t\t\t   it was copied from an issuer certificate) or as a full DN (if \n\t\t\t   it's a self-signed certificate), so we check for the presence \n\t\t\t   of either */\n\t\t\tif( DATAPTR_ISNULL( subjectCertInfoPtr->issuerName ) && \n\t\t\t\t( subjectCertInfoPtr->issuerDNptr == NULL || \\\n\t\t\t\t  subjectCertInfoPtr->issuerDNsize < 1 ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If it's a CRL, compare the revoked certificate issuer DN and signer \n\t   DN to make sure that we're not trying to revoke someone else's \n\t   certificates, and prepare the revocation entries */\n\tif( actions & PRE_CHECK_ISSUERCERTDN )\n\t\t{\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\n\t\tif( !compareDN( subjectCertInfoPtr->issuerName,\n\t\t\t\t\t\tissuerCertInfoPtr->subjectName, FALSE, NULL ) )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_ISSUERNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* If we're creating a non-self-signed certificate, check whether the \n\t   subject's DN is the same as the issuer's DN.  If this is the case \n\t   then the resulting object would appear to be self-signed so we \n\t   disallow it */\n\tif( actions & PRE_CHECK_NONSELFSIGNED_DN )\n\t\t{\n\t\tANALYSER_HINT( issuerCertInfoPtr != NULL );\n\n\t\tif( compareDN( issuerCertInfoPtr->subjectName,\n\t\t\t\t\t   subjectCertInfoPtr->subjectName, FALSE, NULL ) )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ISSUERCONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* Check that the serial number is present */\n\tif( actions & PRE_CHECK_SERIALNO )\n\t\t{\n#ifdef USE_CERTREQ\n\t\tif( subjectCertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t{\n\t\t\tif( subjectCertInfoPtr->cCertReq->serialNumberLength <= 0 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n#endif /* USE_CERTREQ */\n\t\t\t{\n\t\t\tif( subjectCertInfoPtr->cCertCert->serialNumberLength <= 0 )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_SERIALNUMBER,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Check that the validity/revocation information is present */\n#ifdef USE_CERTVAL\n\tif( actions & PRE_CHECK_VALENTRIES )\n\t\t{\n\t\tconst CERT_VAL_INFO *valInfo = subjectCertInfoPtr->cCertVal;\n\n\t\tif( DATAPTR_ISNULL( valInfo->validityInfo ) )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTVAL */\n#ifdef USE_CERTREV\n\tif( actions & PRE_CHECK_REVENTRIES )\n\t\t{\n\t\tconst CERT_REV_INFO *revInfo = subjectCertInfoPtr->cCertRev;\n\n\t\tif( DATAPTR_ISNULL( revInfo->revocations ) )\n\t\t\t{\n\t\t\tsetErrorInfo( subjectCertInfoPtr, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTREV */\n\n\t/* Now that we've set up the attributes, perform the remainder of the\n\t   checks.  Because RTCS is a CMS standard rather than PKIX the RTCS\n\t   attributes are CMS rather than certificate attributes */\n\tif( DATAPTR_ISSET( subjectCertInfoPtr->attributes ) )\n\t\t{\n\t\tstatus = checkAttributes( ( subjectCertInfoPtr->type == \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_RTCS_REQUEST ) ? \\\n\t\t\t\t\t\t\t\t  ATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE,\n\t\t\t\t\t\t\t\t  subjectCertInfoPtr->attributes,\n\t\t\t\t\t\t\t\t  &subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t\t\t  &subjectCertInfoPtr->errorType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = checkCert( subjectCertInfoPtr, issuerCertInfoPtr, FALSE,\n\t\t\t\t\t\t&subjectCertInfoPtr->errorLocus,\n\t\t\t\t\t\t&subjectCertInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a certificate or certificate chain remember that it's been \n\t   checked at full compliance level (or at least as full as we're\n\t   configured for).  This short-circuits the need to perform excessive \n\t   levels of checking if the caller wants to re-check it after it's \n\t   been signed */\n\tif( subjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tsubjectCertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tsubjectCertInfoPtr->cCertCert->maxCheckLevel = \\\n\t\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_PKIX_FULL;\n\t\t}\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/context/context.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Encryption Context Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CRYPTCTX_DEFINED\n\n#define _CRYPTCTX_DEFINED\n\n/* Various include files needed by contexts.  Since the bignum and stream\n   headers are only needed by PKC contexts, we only apply them in modules \n   that use PKC contexts */\n\n#ifdef PKC_CONTEXT\n  #ifndef _STREAM_DEFINED\n\t#if defined( INC_ALL )\n\t  #include \"stream.h\"\n\t#else\n\t  #include \"io/stream.h\"\n\t#endif /* Compiler-specific includes */\n  #endif /* _STREAM_DEFINED */\n  #ifndef HEADER_BN_H\n\t#if defined( INC_ALL )\n\t  #include \"bn.h\"\n\t#else\n\t  #include \"bn/bn.h\"\n\t#endif /* Compiler-specific includes */\n  #endif /* HEADER_BN_H */\n  #if ( defined( USE_ECDH ) || defined( USE_ECDSA ) ) && !defined( HEADER_EC_H )\n\t#if defined( INC_ALL )\n\t  #include \"ec_lcl.h\"\n\t#else\n\t  #include \"bn/ec_lcl.h\"\n\t#endif /* Compiler-specific includes */\n  #endif /* ( USE_ECDH || USE_ECDSA ) && HEADER_EC_H */\n#endif /* Extra eaders needed only for PKC contexts */\n#ifndef _CRYPTCAP_DEFINED\n  #if defined( INC_ALL )\n\t#include \"capabil.h\"\n  #else\n\t#include \"device/capabil.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _CRYPTCAP_DEFINED */\n#ifdef HAS_DEVCRYPTO\n  #include <fcntl.h>\n  #include <crypto/cryptodev.h>\n  #include <sys/ioctl.h>\n#endif /* HAS_DEVCRYPTO */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Types and Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Context information flags.  Most of these flags are context-type-specific,\n   and are only used with some context types:\n\n\tFLAG_DUMMY: The context is a dummy context with actions handled through \n\t\t\tan external crypto device.  When a device context is created, it \n\t\t\tusually isn't instantiated at the device level until the key \n\t\t\t(and possibly other parameters) are available because most \n\t\t\tdevices use an atomic created-initialised-context operation \n\t\t\trather than allowing incremental parameter setting like cryptlib\n\t\t\tdoes.  To handle this, we first create a dummy context and then\n\t\t\tfill in the details on demand.\n\n\tFLAG_DUMMY_INITED: The dummy context has been initialised.  Since the \n\t\t\tcontext isn't instantiated until required, this flag is needed \n\t\t\tto keep track of whether any cached parameters retained from the \n\t\t\tdummy state need to be set when the context is used.\n\n\tFLAG_HASH_INITED: The hash parameters have been inited.\n\tFLAG_HASH_DONE: The hash operation is complete, no further hashing can \n\t\t\tbe done \n\n\tFLAG_ISPUBLICKEY: The key is a public or private key.\n\tFLAG_ISPRIVATEKEY:\n\n\tFLAG_IV_SET: The IV has been set.\n\tFLAG_KEY_SET: The key has been initialised.\n\n\tFLAG_PERSISTENT: The context is backed by a keyset or crypto device.\n\n\tFLAG_SIDECHANNELPROTECTION: The context has side-channel protection\n\t\t\t(additional checking for crypto operations, blinding, and so\n\t\t\ton) enabled.\n\n\tFLAG_STATICCONTEXT: The context data has been instantiated via\n\t\t\tstaticInitContext() for internal use and doesn't correspond to \n\t\t\tan actual cryptlib object */\n\n#define CONTEXT_FLAG_NONE\t\t\t0x0000\t/* No context flag */\n#define CONTEXT_FLAG_KEY_SET\t\t0x0001\t/* Key has been set */\n#define CONTEXT_FLAG_IV_SET\t\t\t0x0002\t/* IV has been set */\n#define CONTEXT_FLAG_ISPUBLICKEY\t0x0004\t/* Key is a public key */\n#define CONTEXT_FLAG_ISPRIVATEKEY\t0x0008\t/* Key is a private key */\n#define CONTEXT_FLAG_DUMMY\t\t\t0x0010\t/* Context actions handled externally */\n#define CONTEXT_FLAG_DUMMY_INITED\t0x0020\t/* Dummy context is inited */\n#define CONTEXT_FLAG_HWCRYPTO\t\t0x0040\t/* Context uses built-in crypto HW */\n#define CONTEXT_FLAG_PERSISTENT\t\t0x0080\t/* Context is backed by dev.or keyset */\n#define CONTEXT_FLAG_SIDECHANNELPROTECTION \\\n\t\t\t\t\t\t\t\t\t0x0100\t/* Enabled side-channel prot.in ops */\n#define CONTEXT_FLAG_HASH_INITED\t0x0200\t/* Hash parameters have been inited */\n#define CONTEXT_FLAG_HASH_DONE\t\t0x0400\t/* Hash operation is complete */\n#define CONTEXT_FLAG_STATICCONTEXT\t0x0800\t/* Static context */\n#define CONTEXT_FLAG_MAX\t\t\t0x0FFF\t/* Maximum possible flag value */\n\n/* PKC info information flags.  These are:\n\n\tFLAG_DUMMY: As for CONTEXT_FLAG_DUMMY, this is required to identify a \n\t\t\tdummy context when only the PKC_INFO is available.\n\n\tFLAG_PGPKEYID_SET: The PGP keyID has been set (this is only valid for \n\t\t\tRSA keys, and may not be enabled if we're not using PGP).\n\tFLAG_OPENPGPKEYID_SET: The OpenPGP keyID has been set (this may not be \n\t\t\tenabled if we're not using PGP) */\n\n#define PKCINFO_FLAG_NONE\t\t\t0x0000\t/* No PKC info flag */\n#define PKCINFO_FLAG_DUMMY\t\t\t0x0001\t/* Context actions handled externally */\n#define PKCINFO_FLAG_PGPKEYID_SET\t0x0002\t/* PGP keyID is set */\n#define PKCINFO_FLAG_OPENPGPKEYID_SET 0x0004 /* OpenPGP keyID is set */\n#define PKCINFO_FLAG_MAX\t\t\t0x0007\t/* Maximum possible flag value */\n\n/* DLP PKCs require a random value k that's then reduced mod p or q, however\n   if we make sizeof( k ) == sizeof( p ) then this introduced a bias into k\n   that eventually leaks the private key (see \"The Insecurity of the Digital \n   Signature Algorithm with Partially Known Nonces\" by Phong Nguyen and Igor \n   Shparlinski, or more recently Serge Vaudenay's \"Evaluation Report on DSA\").  \n   To get around this we generate a k that's somewhat larger than required, \n   the following defines the size in bytes of this overflow factor */\n\n#define DLP_OVERFLOW_SIZE\t\t\tbitsToBytes( 64 )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Data Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The internal fields in a context that hold data for a conventional,\n   public-key, hash, or MAC algorithm.  CONTEXT_CONV and CONTEXT_MAC\n   should be allocated in pagelocked memory since they contain the sensitive\n   userKey data */\n\ntypedef enum { \n\tCONTEXT_NONE,\t\t\t\t\t/* No context type */\n\tCONTEXT_CONV,\t\t\t\t\t/* Conventional encryption context */\n\tCONTEXT_PKC,\t\t\t\t\t/* PKC context */\n\tCONTEXT_HASH,\t\t\t\t\t/* Hash context */\n\tCONTEXT_MAC,\t\t\t\t\t/* MAC context */\n\tCONTEXT_GENERIC,\t\t\t\t/* Generic-secret context */\n\tCONTEXT_LAST\t\t\t\t\t/* Last valid context type */\n\t} CONTEXT_TYPE;\n\n#define needsSecureMemory( contextType ) \\\n\t\t( contextType == CONTEXT_CONV || contextType == CONTEXT_MAC || \\\n\t\t  contextType == CONTEXT_GENERIC )\n\ntypedef struct {\n\t/* General algorithm information */\n\tCRYPT_MODE_TYPE mode;\t\t\t/* Encryption mode being used */\n\n\t/* User keying information.  The user key is the unprocessed key as\n\t   entered by the user (rather than the key in the form used by the\n\t   algorithm), the IV is the initial IV (the version that's updated on\n\t   each block is stored in currentIV below).  We keep a copy of the\n\t   unprocessed key because we usually need to wrap it up in a KEK\n\t   at some point after it's loaded */\n\tBUFFER( CRYPT_MAX_KEYSIZE, userKeyLength ) \\\n\tBYTE userKey[ CRYPT_MAX_KEYSIZE + 8 ];\t/* User encryption key */\n\tBUFFER( CRYPT_MAX_IVSIZE, ivLength ) \\\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];/* Initial IV */\n\tint userKeyLength, ivLength;\n\n\t/* Conventional encryption keying information.  The key is the processed\n\t   encryption key stored in whatever form is required by the algorithm,\n\t   usually the key-scheduled user key.  The size and checksum values are\n\t   used to integrity-check the key data for side-channel attack purposes.  \n\t   The IV is the current per-block working IV, distinct from the IV above\n\t   which is the initial IV loaded for the overall data.  The ivCount is \n\t   the number of bytes of IV that have been used, and is used when a \n\t   block cipher is used as a stream cipher */\n\tvoid *key;\t\t\t\t\t\t/* Internal working key */\n\tint keyDataSize, keyDataChecksum;\t/* Data size and checksum */\n\tBUFFER( CRYPT_MAX_IVSIZE, ivLength ) \\\n\tBYTE currentIV[ CRYPT_MAX_IVSIZE + 8 ];\t/* Internal working IV */\n\tint ivCount;\t\t\t\t\t/* Internal IV count for chaining modes */\n\n\t/* Information required when a key suitable for use by this algorithm\n\t   is derived from a longer user key */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltLength ) \\\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];/* Salt */\n\tint saltLength;\n\tint keySetupIterations;\t\t\t/* Number of times setup was iterated */\n\tCRYPT_ALGO_TYPE keySetupAlgorithm; /* Algorithm used for key setup */\n\tint keySetupAlgoParam;\t\t\t/* Optional algorithm parameter */\n\t} CONV_INFO;\n\n#ifdef PKC_CONTEXT\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *PKC_CALCULATEKEYID_FUNCTION )( INOUT struct CI *contextInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *PKC_READKEY_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT struct CI *contextInfoPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t  const BOOLEAN checkRead );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\n\t\tint ( *PKC_WRITEKEY_FUNCTION )( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   const struct CI *contextInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t   IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 4 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\n\t\tint ( *PKC_ENCODEDLVALUES_FUNCTION )( OUT_BUFFER( bufMaxSize, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t *bufSize ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 20 + 20 ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int bufMaxSize, \n\t\t\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxSize ) \\\n\t\t\t\t\t\t\t\t\t\t\tint *bufSize, \n\t\t\t\t\t\t\t\t\t\t IN const BIGNUM *value1, \n\t\t\t\t\t\t\t\t\t\t IN const BIGNUM *value2, \n\t\t\t\t\t\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\n\t\tint ( *PKC_DECODEDLVALUES_FUNCTION )( IN_BUFFER( bufSize ) const BYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) const int bufSize, \n\t\t\t\t\t\t\t\t\t\t INOUT BIGNUM *value1, \n\t\t\t\t\t\t\t\t\t\t INOUT BIGNUM *value2, \n\t\t\t\t\t\t\t\t\t\t const BIGNUM *maxRange,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType );\n\ntypedef struct {\n\t/* General information on the key: The nominal key size in bits, the key\n\t   IDs, and key-related metadata.  Since the OpenPGP key ID can't be\n\t   calculated directly like the other IDs, we have to keep track of\n\t   whether it's been set or not with a flag (set in the CONTEXT_INFO \n\t   flags) */\n\tint keySizeBits;\t\t\t\t/* Nominal key size in bits */\n\tSAFE_FLAGS flags;\t\t\t\t/* PKC information flags */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE keyID[ KEYID_SIZE + 8 ];\t/* Key ID for this key */\n#ifdef USE_PGP\n\tBUFFER_FIXED( PGP_KEYID_SIZE ) \\\n\tBYTE pgp2KeyID[ PGP_KEYID_SIZE + 8 ];/* PGP 2 key ID for this key */\n\tBUFFER_FIXED( PGP_KEYID_SIZE ) \\\n\tBYTE openPgpKeyID[ PGP_KEYID_SIZE + 8 ];/* OpenPGP key ID for this key */\n\ttime_t pgpCreationTime;\t\t\t/* Key creation time (for OpenPGP ID) */\n#endif /* USE_PGP */\n\n\t/* Public-key encryption keying information.  Since each algorithm has\n\t   its own unique parameters, the bignums are given generic names here.\n\t   The algorithm-specific code refers to them by their actual names,\n\t   which are implemented as symbolic defines of the form\n\t   <algo>Param_<param_name>, e.g.rsaParam_e */\n\tBIGNUM param1;\t\t\t\t\t/* PKC key components */\n\tBIGNUM param2;\n\tBIGNUM param3;\n\tBIGNUM param4;\n\tBIGNUM param5;\n\tBIGNUM param6;\n\tBIGNUM param7;\n\tBIGNUM param8;\n\tBN_MONT_CTX montCTX1;\t\t\t/* Precomputed Montgomery values */\n\tBN_MONT_CTX montCTX2;\n\tBN_MONT_CTX montCTX3;\n#if defined( USE_ECDH ) || defined( USE_ECDSA ) \n\tCRYPT_ECCCURVE_TYPE curveType;\t/* Additional info.needed for ECC ctxs.*/\n\tBOOLEAN isECC;\n\tEC_GROUP *ecCTX;\n\tEC_POINT *ecPoint;\n#endif /* USE_ECDH || USE_ECDSA */\n\tint checksum;\t\t\t\t\t/* Checksum for key data */\n\n\t/* Temporary workspace values used to avoid having to allocate and\n\t   deallocate them on each PKC operation, and to keep better control\n\t   over the data in them.  DLP operations that require extensive\n\t   temporary vars also reuse the last three general-purpose bignums\n\t   above, since they're not used for keying material */\n\tBIGNUM tmp1, tmp2, tmp3;\n#if defined( USE_ECDH ) || defined( USE_ECDSA ) \n\tEC_POINT *tmpPoint;\n#endif /* USE_ECDH || USE_ECDSA */\n\tBN_CTX bnCTX;\n\t#define CONTEXT_FLAG_PBO 0x08\n\n\t/* If we're using side-channel protection, we also need to store values\n\t   used to perform extra operations that eliminate timing channels */\n\tBIGNUM blind1, blind2;\n\n\t/* Domain parameters used by DLP and ECDLP algorithms */\n\tconst void *domainParams;\n\n\t/* If the context is tied to a device the keying info won't be available,\n\t   however we generally need the public key information for use in cert\n\t   requests and whatnot so we save a copy as SubjectPublicKeyInfo when\n\t   the key is loaded/generated */\n\tBUFFER_OPT_FIXED( publicKeyInfoSize ) \\\n\tvoid *publicKeyInfo;\t\t\t/* X.509 SubjectPublicKeyInfo */\n\tint publicKeyInfoSize;\t\t\t/* Key info size */\n\n\t/* Pointers to functions to public-key context access methods.  The\n\t   functions to read and write public and private keys are kept distinct\n\t   to enforce red/black separation */\n\tFNPTR calculateKeyIDFunction, readPublicKeyFunction;\n\tFNPTR readPrivateKeyFunction, writePublicKeyFunction; \n\tFNPTR writePrivateKeyFunction, encodeDLValuesFunction;\n\tFNPTR decodeDLValuesFunction;\n\t} PKC_INFO;\n#endif /* PKC_CONTEXT */\n\ntypedef struct {\n\t/* The current state of the hashing and the result from the last\n\t   completed hash operation */\n\tvoid *hashInfo;\t\t\t\t\t/* Current hash state */\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];/* Last hash result */\n\t} HASH_INFO;\n\ntypedef struct {\n\t/* User keying information.  The user key is the unprocessed key as\n\t   entered by the user rather than the key in the form used by the\n\t   algorithm.  We keep a copy of the unprocessed key because we usually \n\t   need to wrap it up in a KEK at some point after it's loaded */\n\tBUFFER( CRYPT_MAX_KEYSIZE, userKeyLength ) \\\n\tBYTE userKey[ CRYPT_MAX_KEYSIZE + 8 ];\t/* User MAC key */\n\tint userKeyLength;\n\n\t/* The current state of the MAC'ing and the result from the last\n\t   completed MAC operation */\n\tvoid *macInfo;\t\t\t\t\t/* Current MAC state */\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE mac[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Last MAC result */\n\n\t/* Information required when a key suitable for use by this algorithm\n\t   is derived from a longer user key */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltLength ) \\\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];/* Salt */\n\tint saltLength;\n\tint keySetupIterations;\t\t\t/* Number of times setup was iterated */\n\tCRYPT_ALGO_TYPE keySetupAlgorithm; /* Algorithm used for key setup */\n\tint keySetupAlgoParam;\t\t\t/* Optional algorithm parameter */\n\t} MAC_INFO;\n\ntypedef struct {\n\t/* Generic-secret information */\n\tBUFFER( CRYPT_MAX_KEYSIZE, genericSecretLength ) \\\n\tBYTE genericSecret[ CRYPT_MAX_KEYSIZE + 8 ];\n\tint genericSecretLength;\n\n\t/* Parameter information for the optional KDF and the encryption and MAC \n\t   contexts that are derived from the generic-secret context */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, kdfParamSize ) \\\n\tBYTE kdfParams[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint kdfParamSize;\n\tBUFFER( CRYPT_MAX_TEXTSIZE, encAlgoParamSize ) \\\n\tBYTE encAlgoParams[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint encAlgoParamSize;\n\tBUFFER( CRYPT_MAX_TEXTSIZE, macAlgoParamSize ) \\\n\tBYTE macAlgoParams[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint macAlgoParamSize;\n\t} GENERIC_INFO;\n\n/* Defines to make access to the union fields less messy */\n\n#define ctxConv\t\tkeyingInfo.convInfo\n#define ctxPKC\t\tkeyingInfo.pkcInfo\n#define ctxHash\t\tkeyingInfo.hashInfo\n#define ctxMAC\t\tkeyingInfo.macInfo\n#define ctxGeneric\tkeyingInfo.genericInfo\n\n/* An encryption context */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CTX_LOADKEY_FUNCTION )( INOUT struct CI *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   IN_BUFFER_OPT( keyLength ) const void *key, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int keyLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CTX_GENERATEKEY_FUNCTION )( INOUT struct CI *contextInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *CTX_ENCRYPT_FUNCTION )( INOUT struct CI *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_Z int length );\n\ntypedef struct CI {\n\t/* Control and status information */\n\tCONTEXT_TYPE type;\t\t\t\t/* The context type */\n\tDATAPTR capabilityInfo;\t\t\t/* Encryption capability info */\n\tSAFE_FLAGS flags;\t\t\t\t/* Context information flags */\n\n\t/* Context type-specific information */\n\tunion {\n\t\tCONV_INFO *convInfo;\n#ifdef PKC_CONTEXT\n\t\tPKC_INFO *pkcInfo;\n#endif /* PKC_CONTEXT */\n\t\tHASH_INFO *hashInfo;\n\t\tMAC_INFO *macInfo;\n\t\tGENERIC_INFO *genericInfo;\n\t\t} keyingInfo;\n\n#ifdef USE_DEVICES\n\t/* If implemented using a crypto device, the object information is\n\t   usually stored inside the device.  The following value contains the\n\t   reference to the crypto object inside the device.  In addition some\n\t   objects (specifically, DH) that aren't really public- or private-key\n\t   objects but a mixture of both require a second handle to the other \n\t   part of the object in the device */\n\tlong deviceObject, altDeviceObject;\n\n  #ifdef USE_HARDWARE\n\t/* When data used to instantiate a context is stored in a device we may\n\t   need a unique ID value to locate the data, the following value \n\t   contains this storage ID */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE deviceStorageID[ KEYID_SIZE + 8 ];\n\tBOOLEAN deviceStorageIDset;\n  #endif /* USE_HARDWARE */\n#endif /* USE_DEVICES */\n#ifdef HAS_DEVCRYPTO\n\t/* If we're using the /dev/crypto interface then we need to keep track of \n\t   the crypto device handle and session ID within the device */\n\tint cryptoFD;\n\tuint32_t sessionID;\n#endif /* HAS_DEVCRYPTO */\n\n\t/* The label for this object, typically used to identify stored keys */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, labelSize ) \\\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];/* Text string identifying key */\n\tint labelSize;\n\n\t/* Pointers to context access methods.  These are somewhat higher-level\n\t   than the capability info methods and apply to entire classes of\n\t   context rather than at a per-algorithm level */\n\tFNPTR loadKeyFunction, generateKeyFunction;\n\tFNPTR encryptFunction, decryptFunction;\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the\n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\t} CONTEXT_INFO;\n\n#ifdef PKC_CONTEXT \n\n/* Symbolic defines for the various PKC components for different PKC\n   algorithms.  All of the DLP algorithms actually use the same parameters,\n   so we define generic DLP names for them */\n\n#define dlpParam_p\t\t\tparam1\n#define dlpParam_g\t\t\tparam2\n#define dlpParam_q\t\t\tparam3\n#define dlpParam_y\t\t\tparam4\n#define dlpParam_x\t\t\tparam5\n#define dlpTmp1\t\t\t\tparam6\n#define dlpTmp2\t\t\t\tparam7\n#define dlpTmp3\t\t\t\tparam8\t\t/* More temp.values for DLP PKCs */\n#define dhParam_yPrime\t\tparam8\t\t/* Special value for DH */\n#define dlpParam_mont_p\t\tmontCTX1\n\n#define rsaParam_n\t\t\tparam1\n#define rsaParam_e\t\t\tparam2\n#define rsaParam_d\t\t\tparam3\t\t/* Required for PGP, PKCS #12 */\n#define rsaParam_p\t\t\tparam4\n#define rsaParam_q\t\t\tparam5\n#define rsaParam_u\t\t\tparam6\n#define rsaParam_exponent1\tparam7\n#define rsaParam_exponent2\tparam8\n#define rsaParam_blind_k\tblind1\n#define rsaParam_blind_kInv\tblind2\n#define rsaParam_mont_n\t\tmontCTX1\n#define rsaParam_mont_p\t\tmontCTX2\n#define rsaParam_mont_q\t\tmontCTX3\n\n/* p, a, b, gx, gy, n and h are stored as ECC_DOMAINPARAMS.  In addition \n   since this frees up so many parameter bignums, we can use two of them as\n   extra temporaries */\n#define eccParam_qx\t\t\tparam1\n#define eccParam_qy\t\t\tparam2\n#define eccParam_d\t\t\tparam3\n#define eccParam_tmp4\t\tparam4\n#define eccParam_tmp5\t\tparam5\n\n/* Minimum and maximum permitted lengths for various PKC components.  These\n   can be loaded in various ways (read from ASN.1 data, read from \n   PGP/SSH/SSL data, loaded by the user, and so on) so we define permitted\n   length values in a central location for use in the different read \n   routines.\n   \n   For the PKC sub-components we allow a bit of leeway (one byte's worth) \n   in order to deal with situations where one component is a few bits short \n   and the other a few bits long (with the total still fitting into the\n   MIN_PKCSIZE limit), otherwise we'll occasionally get valid values \n   rejected for being a few bits shy of the MIN_PKCSIZE / 2 limit */\n\n#define RSAPARAM_MIN_N\t\tMIN_PKCSIZE\n#define RSAPARAM_MAX_N\t\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_E\t\t1\n#define RSAPARAM_MAX_E\t\t4\n#define RSAPARAM_MIN_D\t\tMIN_PKCSIZE\n#define RSAPARAM_MAX_D\t\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_P\t\t( MIN_PKCSIZE / 2 ) - 1\n#define RSAPARAM_MAX_P\t\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_Q\t\t( MIN_PKCSIZE / 2 ) - 1\n#define RSAPARAM_MAX_Q\t\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_U\t\t( MIN_PKCSIZE / 2 ) - 1\n#define RSAPARAM_MAX_U\t\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_EXP1\t( MIN_PKCSIZE / 2 ) - 1\n#define RSAPARAM_MAX_EXP1\tCRYPT_MAX_PKCSIZE\n#define RSAPARAM_MIN_EXP2\t( MIN_PKCSIZE / 2 ) - 1\n#define RSAPARAM_MAX_EXP2\tCRYPT_MAX_PKCSIZE\n\n#define DLPPARAM_MIN_P\t\tMIN_PKCSIZE\n#define DLPPARAM_MAX_P\t\tCRYPT_MAX_PKCSIZE\n#define DLPPARAM_MIN_G\t\t1\n#define DLPPARAM_MAX_G\t\tCRYPT_MAX_PKCSIZE\n#define DLPPARAM_MIN_Q\t\tbitsToBytes( 128 )\n#define DLPPARAM_MAX_Q\t\tCRYPT_MAX_PKCSIZE\n#define DLPPARAM_MIN_Y\t\tMIN_PKCSIZE - 1\n#define DLPPARAM_MAX_Y\t\tCRYPT_MAX_PKCSIZE\n#define DLPPARAM_MIN_X\t\tbitsToBytes( 128 )\n#define DLPPARAM_MAX_X\t\tCRYPT_MAX_PKCSIZE\n\n#define DLPPARAM_MIN_SIG_R\tDLPPARAM_MIN_Q\t/* For DSA sigs */\n#define DLPPARAM_MIN_SIG_S\tDLPPARAM_MIN_Q\t/* For DSA sigs */\n\n#define ECCPARAM_MIN_P\t\tMIN_PKCSIZE_ECC\n#define ECCPARAM_MAX_P\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_A\t\tMIN_PKCSIZE_ECC / 2\n#define ECCPARAM_MAX_A\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_B\t\tMIN_PKCSIZE_ECC / 2\n#define ECCPARAM_MAX_B\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_GX\t\t1\n#define ECCPARAM_MAX_GX\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_GY\t\t1\n#define ECCPARAM_MAX_GY\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_N\t\tMIN_PKCSIZE_ECC\n#define ECCPARAM_MAX_N\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_H\t\tMIN_PKCSIZE_ECC\n#define ECCPARAM_MAX_H\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_QX\t\tMIN_PKCSIZE_ECC / 2\n#define ECCPARAM_MAX_QX\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_QY\t\tMIN_PKCSIZE_ECC / 2\n#define ECCPARAM_MAX_QY\t\tCRYPT_MAX_PKCSIZE_ECC\n#define ECCPARAM_MIN_D\t\tMIN_PKCSIZE_ECC / 2\n#define ECCPARAM_MAX_D\t\tCRYPT_MAX_PKCSIZE_ECC\n\n#define ECCPARAM_MIN_SIG_R\tECCPARAM_MIN_QX\t/* For ECDSA sigs */\n#define ECCPARAM_MIN_SIG_S\tECCPARAM_MIN_QX\t/* For ECDSA sigs */\n\n/* Because there's no really clean way to throw an exception in C and the\n   bnlib routines don't carry around state information like cryptlib objects\n   do, we need to perform an error check for most of the routines we call.\n   To make this slightly less ugly we define the following macro that\n   performs the check for us by updating a variable called `bnStatus' with\n   the result of a bnlib call, which returns 1 for OK and 0 for error.\n   Annoyingly, this interface isn't quite consistent and some calls return\n   pointers rather than integer values, so we define a second macro that\n   checks for pointer values rather than integers */\n\n#define CK( expr )\t\t\t{ if( bnStatus ) bnStatus &= expr; }\n#define CKPTR( expr )\t\t{ if( bnStatus ) bnStatus &= ( ( expr ) == NULL ? 0 : 1 ); }\n#define BN_STATUS\t\t\t1\n#define bnStatusOK( value )\tvalue\n#define bnStatusError( value ) ( !value )\n#define getBnStatus( value ) ( value ? CRYPT_OK : CRYPT_ERROR_FAILED )\n#define getBnStatusBool( value ) ( value ? TRUE : FALSE )\n\n/* Storage for fixed domain parameters for DH and ECC */\n\ntypedef struct {\n\tconst BIGNUM p, q, g;\n\tconst BN_ULONG p_checksum, q_checksum, g_checksum;\n\t} DH_DOMAINPARAMS;\n\ntypedef struct {\n\tconst BIGNUM p, a, b, gx, gy, n, h;\n\tconst BN_ULONG p_checksum, a_checksum, b_checksum;\n\tconst BN_ULONG gx_checksum, gy_checksum, n_checksum, h_checksum;\n\t} ECC_DOMAINPARAMS;\n\n#endif /* PKC_CONTEXT */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInternal API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* When we're using static context storage, the subtype-specific data needs \n   to be aligned to particular memory boundaries to deal with the \n   requirements of underlying hardware implementations.  To do this we \n   provide macros to declare a wrapper struct that contains the key storage\n   and extra space for alignment, and a second macro to get an aligned \n   pointer into that space.  These are used as follows:\n\n\ttypedef BYTE KEY_DATA[ KEY_DATA_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\n\ttypedef BYTE HASH_STATE[ HASH_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( HASH_STATE_STORAGE, HASH_STATE );\n\tHASH_STATE_STORAGE hashStateStorage;\n\tHASH_STATE *hashStatePtr = ALIGN_STRUCT( &hashStateStorage, HASH_STATE, 8 );\n\n\ttypedef BYTE MAC_STATE[ MAC_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( MAC_STATE_STORAGE, MAC_STATE );\n\tMAC_STATE_STORAGE macStateStorage;\n\tMAC_STATE *macStatePtr = ALIGN_STRUCT( &macStateStorage, MAC_STATE, 8 ); */\n\n#define DECLARE_ALIGN_STRUCT( name, innerStruct ) \\\n\t\ttypedef struct { \\\n\t\t\tinnerStruct storage; \\\n\t\t\tBYTE padding[ 16 ]; \\\n\t\t\t} name\n\n#define ALIGN_STRUCT( outerStruct, innerStruct, alignValue ) \\\n\t\t( innerStruct * ) roundUp( ( uintptr_t ) ( outerStruct ), ( alignValue ) )\n\n/* Determine whether a context needs to have a key loaded */\n\n#define needsKey( contextInfoPtr ) \\\n\t\t!TEST_FLAG( ( contextInfoPtr )->flags, CONTEXT_FLAG_KEY_SET )\n\n/* Miscellaneous context functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckContext( const CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint processActionMessage( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t  INOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int dataLength );\n\n/* Low-level capability checking and context-creation functions used when\n   creating a context in a device */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCapability( const CAPABILITY_INFO *capabilityInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint createContextFromCapability( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t\t\t const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( CREATEOBJECT ) const int objectFlags );\n\n/* Statically init/destroy a context for the self-check, and perform various\n   types of self-check */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint staticInitContext( OUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( CONTEXT ) const CONTEXT_TYPE type, \n\t\t\t\t\t   const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t   OUT_BUFFER_FIXED( contextDataSize ) void *contextData, \n\t\t\t\t\t   IN_LENGTH_MIN( 32 ) const int contextDataSize,\n\t\t\t\t\t   IN_OPT const void *keyData );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid staticDestroyContext( INOUT CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 6 ) ) \\\nint testCipher( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t\tIN const void *keyDataStorage, \n\t\t\t\tIN_BUFFER( keySize ) const void *key, \n\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keySize, \n\t\t\t\tIN const void *plaintext,\n\t\t\t\tIN const void *ciphertext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nint testHash( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t  IN_LENGTH_HASH_Z const int hashSize,\n\t\t\t  IN const void *hashDataStorage,\n\t\t\t  IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t  IN_LENGTH_SHORT_Z const int dataLength, \n\t\t\t  IN const void *hashValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 7 ) ) \\\nint testMAC( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t IN const void *macDataStorage,\n\t\t\t IN_BUFFER( keySize ) const void *key, \n\t\t\t IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keySize, \n\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int dataLength,\n\t\t\t IN const void *hashValue );\n\n/* Context attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getContextAttributeS( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t  INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t IN_INT_Z const int value, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setContextAttributeS( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t  IN_LENGTH const int dataLength,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\n\n/* General key load/generation routines */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyHandling( INOUT CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint setEncodedKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyType, \n\t\t\t\t   IN_BUFFER( keyDataLen ) const void *keyData, \n\t\t\t\t   IN_LENGTH_SHORT const int keyDataLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setKeyComponents( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  IN_BUFFER( keyDataLen ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int keyDataLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completeKeyLoad( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t const BOOLEAN isPGPkey );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint deriveKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t   IN_BUFFER( keyValueLen ) const void *keyValue, \n\t\t\t   IN_LENGTH_SHORT const int keyValueLen );\n\n/* PKC key-generation and related routines */\n\n#ifdef PKC_CONTEXT\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint loadDHparams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t  IN_LENGTH_PKC const int requestedKeySize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkFixedDHparams( const INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\tOUT const DH_DOMAINPARAMS **domainParamsPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckDLPkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t const BOOLEAN isPKCS3 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateDLPkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) const int keyBits );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckRSAkey( INOUT CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateRSAkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) const int keyBits );\n#if defined( USE_ECDSA ) || defined( USE_ECDH )\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint loadECCparams( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t   IN_ENUM( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE curveType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckECCkey( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t const BOOLEAN isECDH );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateECCkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\tconst int keyBits );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getECCFieldSize( IN_ENUM( CRYPT_ECCCURVE ) const CRYPT_ECCCURVE_TYPE fieldID,\n\t\t\t\t\t OUT_INT_Z int *fieldSize, const BOOLEAN isBits );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getECCFieldID( IN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC ) \\\n\t\t\t\t\t\tconst int fieldSize,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ECCCURVE ) \n\t\t\t\t\t\tCRYPT_ECCCURVE_TYPE *fieldID );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN isPointOnCurve( const BIGNUM *x, const BIGNUM *y, \n\t\t\t\t\t\tconst BIGNUM *a, const BIGNUM *b, \n\t\t\t\t\t\tINOUT PKC_INFO *pkcInfo );\n#endif /* USE_ECDSA || USE_ECDH */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBignum( const BIGNUM *bignum );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBNCTX( const BN_CTX *bnCTX );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBNMontCTX( const BN_MONT_CTX *bnMontCTX );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateBignum( OUT BIGNUM *bn, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t\tIN_BYTE const int high, IN_BYTE const int low );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateBignumEx( OUT BIGNUM *bn, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t\t  IN_BYTE const int high, IN_BYTE const int low,\n\t\t\t\t\t  IN_BUFFER_OPT( seedLength ) const void *seed,\n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int seedLength,\n\t\t\t\t\t  IN_OPT const void *getRandomInfoPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckPKCInfo( const PKC_INFO *pkcInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid clearTempBignums( INOUT PKC_INFO *pkcInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initContextBignums( INOUT PKC_INFO *pkcInfo, const BOOLEAN isECC );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endContextBignums( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\tIN const BOOLEAN isDummyContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checksumContextData( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t const BOOLEAN isPrivateKey );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checksumDomainParameters( const void *domainParams, \n\t\t\t\t\t\t\t\t  const BOOLEAN isECC );\n#if defined( DEBUG_DIAGNOSTIC_ENABLE ) && !defined( NDEBUG )\nvoid printBignumChecksum( const BIGNUM *bignum );\nvoid printBignum( const BIGNUM *bignum, const char *label );\n#endif /* DEBUG_DIAGNOSTIC_ENABLE && Debug */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\nCHECK_RETVAL_BOOL \\\nBOOLEAN bnmathSelfTest( void );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n#endif /* PKC_CONTEXT */\n\n/* Hardware crypto assist functions */\n\n#ifdef HAS_DEVCRYPTO\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoInit( INOUT CONTEXT_INFO *contextInfoPtr );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoEnd( INOUT CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoCloneState( INOUT CONTEXT_INFO *contextInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hwCryptoHash( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t  IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t  IN_LENGTH_Z int noBytes );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hwCryptoCrypt( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t   IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t   IN_LENGTH_Z int noBytes,\n\t\t\t\t   const BOOLEAN doEncrypt );\n#else\n  #define hwCryptoEnd( contextInfoPtr )\t\tCRYPT_ERROR\n#endif /* HAS_DEVCRYPTO */\n\n/* Key read/write routines */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyID( INOUT CONTEXT_INFO *contextInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPrivKeyRead( INOUT CONTEXT_INFO *contextInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPubKeyRead( INOUT CONTEXT_INFO *contextInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyWrite( INOUT CONTEXT_INFO *contextInfoPtr );\n\n/* Internal functions shared across a small number of modules, declared via \n   a header to allow type checking (attributeToFormatType() from keyload.c, \n   hash functions from ctx_XXX.c accessed via the universal interface in \n   ctx_misc.c) */\n\nCHECK_RETVAL \\\nint attributeToFormatType( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t   OUT_ENUM_OPT( KEYFORMAT ) KEYFORMAT_TYPE *keyformat );\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid md5HashBuffer( INOUT_OPT HASHINFO hashInfo, \n\t\t\t\t\tOUT_BUFFER_OPT_C( outBufMaxLength, 16 ) BYTE *outBuffer, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\tIN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\tIN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid shaHashBuffer( INOUT_OPT HASHINFO hashInfo, \n\t\t\t\t\tOUT_BUFFER_OPT_C( outBufMaxLength, 20 ) BYTE *outBuffer, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\tIN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\tIN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sha2HashBuffer( INOUT_OPT HASHINFO hashInfo, \n\t\t\t\t\t OUT_BUFFER_OPT_C( outBufMaxLength, 32 ) BYTE *outBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\t IN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\t IN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sha2_ExtHashBuffer( INOUT_OPT HASHINFO hashInfo, \n\t\t\t\t\t\t OUT_BUFFER_OPT_C( outBufMaxLength, 64 ) BYTE *outBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\t\t IN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\t\t IN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState );\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid md5HashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 16 ) BYTE *outBuffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int outBufMaxLength,\n\t\t\t\t\t\t  IN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int inLength );\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid shaHashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 20 ) BYTE *outBuffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 20 ) const int outBufMaxLength,\n\t\t\t\t\t\t  IN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int inLength );\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid sha2HashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 32 ) BYTE *outBuffer, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int outBufMaxLength,\n\t\t\t\t\t\t   IN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int inLength );\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid sha2_ExtHashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 64 ) BYTE *outBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 64 ) const int outBufMaxLength,\n\t\t\t\t\t\t\t   IN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int inLength );\n\n#endif /* _CRYPTCTX_DEFINED */\n"
  },
  {
    "path": "deps/cl345/context/ctx_3des.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Triple DES Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1994-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"des.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/des.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_3DES\n\n/* The DES block size */\n\n#define DES_BLOCKSIZE\t8\n\n#if defined( INC_ALL )\n  #include \"testdes.h\"\n#else\n  #include \"crypt/testdes.h\"\n#endif /* Compiler-specific includes */\n\n/* A structure to hold the keyscheduled DES keys */\n\ntypedef struct {\n\tKey_schedule desKey1;\t\t\t/* The first DES key */\n\tKey_schedule desKey2;\t\t\t/* The second DES key */\n\tKey_schedule desKey3;\t\t\t/* The third DES key */\n\t} DES3_KEY;\n\n/* The size of the keyscheduled DES and 3DES keys */\n\n#define DES_KEYSIZE\t\tsizeof( Key_schedule )\n#define DES3_KEYSIZE\tsizeof( DES3_KEY )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t3DES Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the DES implementation against the test vectors given in NBS Special\n   Publication 800-20, 1999 (which are actually the same as 500-20, 1980,\n   since they require that K1 = K2 = K3, but we do it anyway so we can claim\n   compliance) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int testLoop( const DES_TEST *testDES, \n\t\t\t\t\t IN_RANGE( 1, 100 ) int iterations )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = get3DESCapability();\n\ttypedef BYTE KEY_DATA[ DES3_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( testDES, iterations * sizeof( DES_TEST ) ) );\n\n\tREQUIRES( iterations > 0 && iterations <= 100 );\n\n\tmemset( keyDataPtr, 0, DES3_KEYSIZE );\t/* Keep static analysers happy */\n\tLOOP_LARGE( i = 0, i < iterations, i++ )\n\t\t{\n\t\tBYTE desKeyData[ ( DES_BLOCKSIZE * 3 ) + 8 ];\n\n\t\tmemcpy( desKeyData, testDES[ i ].key, DES_BLOCKSIZE );\n\t\tmemcpy( desKeyData + DES_BLOCKSIZE, testDES[ i ].key, \n\t\t\t\tDES_BLOCKSIZE );\n\t\tmemcpy( desKeyData + ( DES_BLOCKSIZE * 2 ), testDES[ i ].key, \n\t\t\t\tDES_BLOCKSIZE );\n\n\t\t/* The self-test uses weak keys, which means they'll be rejected by \n\t\t   the key-load function if it checks for these.  For the OpenSSL\n\t\t   DES implementation we can kludge around this by temporarily \n\t\t   clearing the global des_check_key value, but for other \n\t\t   implementations some alternative workaround will be necessary */\n\t\tdes_check_key = FALSE;\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, desKeyData, \n\t\t\t\t\t\t\t DES_BLOCKSIZE * 3, testDES[ i ].plaintext,\n\t\t\t\t\t\t\t testDES[ i ].ciphertext );\n\t\tdes_check_key = TRUE;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\t/* Check the 3DES test vectors.  Note that we don't perform the RS test, \n\t   since it's valid only for single DES */\n\tif( ( testLoop( testIP, sizeof( testIP ) / sizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testVP, sizeof( testVP ) / sizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testKP, sizeof( testKP ) / sizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testDP, sizeof( testDP ) / sizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testSB, sizeof( testSB ) / sizeof( DES_TEST ) ) != CRYPT_OK ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = DES3_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t3DES En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\tint blockCount = noBytes / DES_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Encrypt a block of data */\n\t\tdes_ecb3_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2,\n\t\t\t\t\t\t  des3Key->desKey3, DES_ENCRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += DES_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\tint blockCount = noBytes / DES_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Decrypt a block of data */\n\t\tdes_ecb3_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2,\n\t\t\t\t\t\t  des3Key->desKey3, DES_DECRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += DES_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CBC mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If we're using crypto hardware, use that */\n#ifdef HAS_DEVCRYPTO\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\treturn( hwCryptoCrypt( contextInfoPtr, buffer, noBytes, TRUE ) );\n#endif /* HAS_DEVCRYPTO */\n\n\tdes_ede3_cbc_encrypt( buffer, buffer, noBytes,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2, des3Key->desKey3,\n\t\t\t\t\t\t  ( C_Block * ) convInfo->currentIV, DES_ENCRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If we're using crypto hardware, use that */\n#ifdef HAS_DEVCRYPTO\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\treturn( hwCryptoCrypt( contextInfoPtr, buffer, noBytes, FALSE ) );\n#endif /* HAS_DEVCRYPTO */\n\n\tdes_ede3_cbc_encrypt( buffer, buffer, noBytes,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2, des3Key->desKey3,\n\t\t\t\t\t\t  ( C_Block * ) convInfo->currentIV, DES_DECRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CFB mode */\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = DES_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Encrypt the data */\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tdes_ecb3_encrypt( ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t  ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2,\n\t\t\t\t\t\t  des3Key->desKey3, DES_ENCRYPT );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, buffer, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % DES_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Decrypt data in CFB mode.  Note that the transformation can be made\n   faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp\n   all in one loop */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\tBYTE temp[ DES_BLOCKSIZE + 8 ];\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = DES_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Decrypt the data */\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, DES_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, bytesToUse );\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, temp, \n\t\t\t\tbytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tdes_ecb3_encrypt( ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t  ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t  des3Key->desKey1, des3Key->desKey2,\n\t\t\t\t\t\t  des3Key->desKey3, DES_ENCRYPT );\n\n\t\t/* Save the ciphertext */\n\t\tREQUIRES( rangeCheck( ivCount, 1, DES_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, ivCount );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, temp, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % DES_BLOCKSIZE );\n\n\t/* Clear the temporary buffer */\n\tzeroise( temp, DES_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t3DES Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key schedule two/three DES keys */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tDES3_KEY *des3Key = ( DES3_KEY * ) convInfo->key;\n\tBOOLEAN useEDE = FALSE;\n#ifdef HAS_DEVCRYPTO\n\tconst int hwCryptInfo = getSysVar( SYSVAR_HWCRYPT );\n#endif /* HAS_DEVCRYPTO */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= DES_BLOCKSIZE * 3 );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* If there's crypto hardware available, try and use that */\n#ifdef HAS_DEVCRYPTO\n\tif( !cryptStatusError( hwCryptInfo ) && \\\n\t\t( hwCryptInfo & HWCRYPT_FLAG_CRYPTDEV_3DES ) && \\\n\t\tconvInfo->mode == CRYPT_MODE_CBC )\n\t\t{\n\t\tint status;\n\n\t\tstatus = hwCryptoInit( contextInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* HAS_DEVCRYPTO */\n\n\t/* Check the key size.  This gets a bit complicated because although we\n\t   follow X9.52 and default to three-key triple DES, we'll often be\n\t   passed a 128 (112)-bit key which was common in older designs.  If this\n\t   happens we take the 112-bit key and repeat the first 56 bits to create\n\t   a 168-bit key.  X9.52 says that if the caller wants EDE behaviour they\n\t   have to set it up themselves using a full 168-bit key, but this will\n\t   cause problems for people using the high-level functions which don't\n\t   allow this level of control, so if we're passed a 112-bit key we just\n\t   expand it out to 168 bits to get two-key EDE */\n\tif( keyLength <= bitsToBytes( 64 * 2 ) )\n\t\tuseEDE = TRUE;\t/* Only 112 bits of key, force EDE mode */\n\n\t/* Call the libdes key schedule code.  Returns with -1 if the key parity\n\t   is wrong (which never occurs since we force the correct parity) or -2\n\t   if a weak key is used.  In theory this could leave us open to timing\n\t   attacks (a memcmp() implemented as a bytewise operation will exit on \n\t   the first mis-matching byte), but in practice the trip through the\n\t   kernel adds enough skew to make the one or two clock cycle difference\n\t   undetectable */\n\tdes_set_odd_parity( ( C_Block * ) convInfo->userKey );\n\tif( des_key_sched( ( des_cblock * ) convInfo->userKey, des3Key->desKey1 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tdes_set_odd_parity( ( C_Block * ) \\\n\t\t\t\t\t\t( ( BYTE * ) convInfo->userKey + bitsToBytes( 64 ) ) );\n\tif( des_key_sched( ( des_cblock * ) \\\n\t\t\t\t\t   ( ( BYTE * ) convInfo->userKey + bitsToBytes( 64 ) ),\n\t\t\t\t\t   des3Key->desKey2 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( useEDE )\n\t\t{\n\t\t/* Rather than performing another key schedule, we just copy the first\n\t\t   scheduled key into the third one */\n\t\tmemcpy( des3Key->desKey3, des3Key->desKey1, DES_KEYSIZE );\n\t\t}\n\telse\n\t\t{\n\t\tdes_set_odd_parity( ( C_Block * ) \\\n\t\t\t\t\t\t\t( ( BYTE * ) convInfo->userKey + bitsToBytes( 128 ) ) );\n\t\tif( des_key_sched( ( des_cblock * ) \\\n\t\t\t\t\t\t   ( ( BYTE * ) convInfo->userKey + bitsToBytes( 128 ) ),\n\t\t\t\t\t\t   des3Key->desKey3 ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\t/* We give the default key size as 192 bits instead of 128 to make sure \n\t   that anyone using a key of the default size ends up with three-key \n\t   3DES rather than two-key 3DES */\n\tCRYPT_ALGO_3DES, bitsToBytes( 64 ), \"3DES\", 4,\n\tbitsToBytes( 128 ), bitsToBytes( 192 ), bitsToBytes( 192 ),\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB\n#endif /* USE_CFB */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *get3DESCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n#endif /* USE_3DES */\n"
  },
  {
    "path": "deps/cl345/context/ctx_aes.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib AES Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2000-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"aes.h\"\n  #include \"aesopt.h\"\n  #include \"gcm.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/aes.h\"\n  #include \"crypt/aesopt.h\"\n  #include \"crypt/gcm.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_AES\n\n/* The AES code separates encryption and decryption to make it easier to\n   do encrypt-only or decrypt-only apps, however since we don't know\n   what the user will choose to do we have to do both key schedules (this\n   is a relatively minor overhead compared to en/decryption, so it's not a \n   big problem).\n\n   When building with VC++, the asm code used is aescrypt2.asm, built with\n   'yasm -Xvc -D ASMV2 -f win32 aescrypt2.asm', which provides the best\n   performance by using asm for the en/decrypt functions and C for the\n   key schedule */\n\n/* The size of an AES key and block and a keyscheduled AES key */\n\n#define AES_KEYSIZE\t\t32\n#define AES_BLOCKSIZE\t16\n#define AES_EXPANDED_KEYSIZE sizeof( AES_CTX )\n\n/* The size of the equivalent AES-GCM keying information */\n\n#define AES_GCM_CTX\t\tgcm_ctx\n#define AES_GCM_EXPANDED_KEYSIZE\tsizeof( AES_GCM_CTX )\n\n/* The scheduled AES key and key schedule control and function return \n   codes */\n\n#define AES_EKEY\taes_encrypt_ctx\n#define AES_DKEY\taes_decrypt_ctx\n#define AES_2KEY\tAES_CTX\n\n/* AES-GCM can make use of various sizes of lookup tables for the GF-\n   multiplication, by default 4K tables are used (the best tradeoff between\n   speed and memory), in case the default is changed in the future we warn\n   the user that this will consume quite a bit of memory */\n\n#if defined( TABLES_8K ) || defined( TABLES_64K )\n  #error AES-GCM is configured to use unusually large GF-mult tables, is this deliberate?\n#endif /* Unusually large GF-mult table sizes */\n\n/* The following macros are from the AES implementation, and aren't cryptlib\n   code.\n\n   Assign memory for AES contexts in 'UNIT_SIZE' blocks of bytes with two \n   such blocks in cryptlib's AES context (one encryption and one decryption). \n   The cryptlib key schedule is then two AES contexts plus an extra UNIT_SIZE \n   block to allow for alignment adjustment by up to 'UNIT_SIZE' - 1 bytes to \n   align each of the internal AES contexts on UNIT_SIZE boundaries */\n\n#define UNIT_SIZE\t16\n\n/* The size of the AES context rounded up (if necessary) to a multiple of 16 \n   bytes */\n\n#define BYTE_SIZE( x )\t( UNIT_SIZE * ( ( sizeof( x ) + UNIT_SIZE - 1 ) / UNIT_SIZE ) )\n\n/* The size of the cryptlib AES context plus UNIT_SIZE bytes for possible upward \n   alignment to a UNIT_SIZE byte boundary */\n\n#define KS_SIZE\t\t( BYTE_SIZE( AES_EKEY ) + BYTE_SIZE( AES_DKEY ) + UNIT_SIZE )\n\n/* The base address for the cryptlib AES context */\n\n#define KS_BASE(x)\t( ( unsigned char * )( ( ( AES_CTX * ) x )->ksch ) )\n\n/* The AES encrypt/decrypt data within the AES context data */\n\n#define EKEY( x )\t( ( AES_EKEY * ) ALIGN_CEIL( KS_BASE( x ), UNIT_SIZE ) )\n#define DKEY( x )\t( ( AES_DKEY * ) ALIGN_CEIL( KS_BASE( x ) + BYTE_SIZE( AES_EKEY ), UNIT_SIZE ) )\n\n/* A type to hold the cryptlib AES context */\n\ntypedef unsigned long _unit;\ntypedef struct {\t\n\t_unit ksch[ ( KS_SIZE + sizeof( _unit ) - 1 ) / sizeof( _unit ) ];\n\t} AES_CTX;\n\n#define\tENC_KEY( x )\t\tEKEY( ( x )->key )\n#define\tDEC_KEY( x )\t\tDKEY( ( x )->key )\n#define GCM_KEY( x )\t\t( x )->key \n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAES Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* AES FIPS test vectors */\n\n/* The data structure for the ( key, plaintext, ciphertext ) triplets */\n\ntypedef struct {\n\tconst int keySize;\n\tconst BYTE key[ AES_KEYSIZE + 8 ];\n\tconst BYTE plaintext[ AES_BLOCKSIZE + 8 ];\n\tconst BYTE ciphertext[ AES_BLOCKSIZE + 8 ];\n\t} AES_TEST;\n\nstatic const AES_TEST testAES[] = {\n\t{ 16,\n\t  { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \n\t\t0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F },\n\t  { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, \n\t\t0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },\n\t  { 0x69, 0xC4, 0xE0, 0xD8, 0x6A, 0x7B, 0x04, 0x30, \n\t\t0xD8, 0xCD, 0xB7, 0x80, 0x70, 0xB4, 0xC5, 0x5A } },\n\t{ 24,\n\t  { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \n\t\t0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \n\t\t0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },\n\t  { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, \n\t\t0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },\n\t  { 0xDD, 0xA9, 0x7C, 0xA4, 0x86, 0x4C, 0xDF, 0xE0, \n\t\t0x6E, 0xAF, 0x70, 0xA0, 0xEC, 0x0D, 0x71, 0x91 } },\n\t{ 32,\n\t  { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \n\t\t0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \n\t\t0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \n\t\t0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },\n\t  { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, \n\t\t0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF },\n\t  { 0x8E, 0xA2, 0xB7, 0xCA, 0x51, 0x67, 0x45, 0xBF, \n\t\t0xEA, 0xFC, 0x49, 0x90, 0x4B, 0x49, 0x60, 0x89 } }\n\t};\n\n#if 0\n\n/* Test the AES code against the test vectors from the AES FIPS */\n\nstatic void printVector( const char *description, const BYTE *data,\n\t\t\t\t\t\t const int length )\n\t{\n\tint i;\n\n\tprintf( \"%s = \", description );\n\tfor( i = 0; i < length; i++ )\n\t\tprintf( \"%02x\", data[ i ] );\n\tputchar( '\\n' );\n\t}\n\nstatic int updateKey( BYTE *key, const int keySize,\n\t\t\t\t\t  CONTEXT_INFO *contextInfo, \n\t\t\t\t\t  const CAPABILITY_INFO *capabilityInfo,\n\t\t\t\t\t  const BYTE *newKey1, const BYTE *newKey2 )\n\t{\n\tBYTE keyData[ AES_KEYSIZE + 8 ];\n\tint i;\n\n\tswitch( keySize )\n\t\t{\n\t\tcase 16:\n\t\t\tmemcpy( keyData, newKey2, keySize );\n\t\t\tbreak;\n\n\t\tcase 24:\n\t\t\tmemcpy( keyData, newKey1 + 8, keySize );\n\t\t\tmemcpy( keyData + 8, newKey2, AES_BLOCKSIZE );\n\n\t\tcase 32:\n\t\t\tmemcpy( keyData, newKey1, AES_BLOCKSIZE );\n\t\t\tmemcpy( keyData + 16, newKey2, AES_BLOCKSIZE );\n\t\t}\n\n\tfor( i = 0; i < keySize; i++ )\n\t\tkey[ i ] ^= keyData[ i ];\n\treturn( capabilityInfo->initKeyFunction( contextInfo, key, \n\t\t\t\t\t\t\t\t\t\t\t keySize ) );\n\t}\n\nstatic int mct( CONTEXT_INFO *contextInfo, \n\t\t\t    const CAPABILITY_INFO *capabilityInfo,\n\t\t\t\tconst BYTE *initialKey, const int keySize,\n\t\t\t\tconst BYTE *initialIV, const BYTE *initialPT )\n\t{\n\tBYTE key[ AES_KEYSIZE + 8 ], iv[ AES_KEYSIZE + 8 ];\n\tBYTE temp[ AES_BLOCKSIZE + 8 ];\n\tint i;\n\n\tmemcpy( key, initialKey, keySize );\n\tif( iv != NULL )\n\t\tmemcpy( iv, initialIV, AES_BLOCKSIZE );\n\tmemcpy( temp, initialPT, AES_BLOCKSIZE );\n\tfor( i = 0; i < 100; i++ )\n\t\t{\n\t\tBYTE prevTemp[ AES_BLOCKSIZE + 8 ];\n\t\tint j, status;\n\n\t\tstatus = capabilityInfo->initKeyFunction( contextInfo, key, \n\t\t\t\t\t\t\t\t\t\t\t\t  keySize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprintVector( \"Key\", key, keySize );\n\t\tif( iv != NULL )\n\t\t\tprintVector( \"IV\", iv, AES_BLOCKSIZE );\n\t\tprintVector( \"Plaintext\", temp, AES_BLOCKSIZE );\n\t\tif( iv != NULL )\n\t\t\tmemcpy( contextInfo->ctxConv->currentIV, iv, AES_BLOCKSIZE );\n\t\tfor( j = 0; j < 1000; j++ )\n\t\t\t{\n/*\t\t\tmemcpy( prevTemp, temp, AES_BLOCKSIZE ); */\n\t\t\tif( iv != NULL && j == 0 )\n\t\t\t\t{\n\t\t\t\tstatus = capabilityInfo->encryptCBCFunction( contextInfo, temp, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t AES_BLOCKSIZE );\n\t\t\t\tmemcpy( prevTemp, temp, AES_BLOCKSIZE );\n\t\t\t\tmemcpy( temp, iv, AES_BLOCKSIZE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = capabilityInfo->encryptFunction( contextInfo, temp, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  AES_BLOCKSIZE );\n\t\t\t\tif( iv != NULL )\n\t\t\t\t\t{\n\t\t\t\t\tBYTE tmpTemp[ AES_BLOCKSIZE + 8 ];\n\n\t\t\t\t\tmemcpy( tmpTemp, temp, AES_BLOCKSIZE );\n\t\t\t\t\tmemcpy( temp, prevTemp, AES_BLOCKSIZE );\n\t\t\t\t\tmemcpy( prevTemp, tmpTemp, AES_BLOCKSIZE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tprintVector( \"Ciphertext\", temp, AES_BLOCKSIZE );\n\t\tputchar( '\\n' );\n\t\tstatus = updateKey( key, keySize, contextInfo, capabilityInfo, \n\t\t\t\t\t\t\tprevTemp, temp );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t\n\treturn( CRYPT_OK );\n\t}\n#endif\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n#if 0\n\t/* ECB */\n\tstatic const BYTE mctECBKey[] = \\\n\t\t{ 0x8D, 0x2E, 0x60, 0x36, 0x5F, 0x17, 0xC7, 0xDF, 0x10, 0x40, 0xD7, 0x50, 0x1B, 0x4A, 0x7B, 0x5A };\n\tstatic const BYTE mctECBPT[] = \\\n\t\t{ 0x59, 0xB5, 0x08, 0x8E, 0x6D, 0xAD, 0xC3, 0xAD, 0x5F, 0x27, 0xA4, 0x60, 0x87, 0x2D, 0x59, 0x29 };\n\t/* CBC */\n\tstatic const BYTE mctCBCKey[] = \\\n\t\t{ 0x9D, 0xC2, 0xC8, 0x4A, 0x37, 0x85, 0x0C, 0x11, 0x69, 0x98, 0x18, 0x60, 0x5F, 0x47, 0x95, 0x8C };\n\tstatic const BYTE mctCBCIV[] = \\\n\t\t{ 0x25, 0x69, 0x53, 0xB2, 0xFE, 0xAB, 0x2A, 0x04, 0xAE, 0x01, 0x80, 0xD8, 0x33, 0x5B, 0xBE, 0xD6 };\n\tstatic const BYTE mctCBCPT[] = \\\n\t\t{ 0x2E, 0x58, 0x66, 0x92, 0xE6, 0x47, 0xF5, 0x02, 0x8E, 0xC6, 0xFA, 0x47, 0xA5, 0x5A, 0x2A, 0xAB };\n\t/* CFB-128 */\n\tstatic const BYTE mctCFBKey[] = \\\n\t\t{ 0x71, 0x15, 0x11, 0x93, 0x1A, 0x15, 0x62, 0xEA, 0x73, 0x29, 0x0A, 0x8B, 0x0A, 0x37, 0xA3, 0xB4 };\n\tstatic const BYTE mctCFBIV[] = \\\n\t\t{ 0x9D, 0xCE, 0x23, 0xFD, 0x2D, 0xF5, 0x36, 0x0F, 0x79, 0x9C, 0xF1, 0x79, 0x84, 0xE4, 0x7C, 0x8D };\n\tstatic const BYTE mctCFBPT[] = \\\n\t\t{ 0xF0, 0x66, 0xBE, 0x4B, 0xD6, 0x71, 0xEB, 0xC1, 0xC4, 0xCF, 0x3C, 0x00, 0x8E, 0xF2, 0xCF, 0x18 };\n#endif /* 0 */\n\tconst CAPABILITY_INFO *capabilityInfo = getAESCapability();\n\ttypedef BYTE KEY_DATA[ AES_EXPANDED_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 );\n\tint i, status, LOOP_ITERATOR;\n\n\t/* The AES code requires 16-byte alignment for data structures, before \n\t   we try anything else we make sure that the compiler voodoo required\n\t   to handle this has worked */\n\tif( aes_test_alignment_detection( 16 ) != EXIT_SUCCESS  )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\tmemset( keyDataPtr, 0, AES_EXPANDED_KEYSIZE );\t/* Keep static analysers happy */\n\tLOOP_SMALL( i = 0, i < sizeof( testAES ) / sizeof( AES_TEST ), i++ )\n\t\t{\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, testAES[ i ].key, \n\t\t\t\t\t\t\t testAES[ i ].keySize, testAES[ i ].plaintext,\n\t\t\t\t\t\t\t testAES[ i ].ciphertext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n#if 0\t/* OK */\n\tstaticInitContext( &contextInfo, CONTEXT_CONV, capabilityInfo,\n\t\t\t\t\t   &contextData, sizeof( CONV_INFO ), keyData );\n\tstatus = mct( &contextInfo, capabilityInfo, mctECBKey, 16, \n\t\t\t\t  NULL, mctECBPT );\n\tstaticDestroyContext( &contextInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n#endif\n#if 0\t/* OK */\n\tstaticInitContext( &contextInfo, CONTEXT_CONV, capabilityInfo,\n\t\t\t\t\t   &contextData, sizeof( CONV_INFO ), keyData );\n\tstatus = mct( &contextInfo, capabilityInfo, mctCBCKey, 16, \n\t\t\t\t  mctCBCIV, mctCBCPT );\n\tstaticDestroyContext( &contextInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n#endif\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tstatic_assert( AES_EXPANDED_KEYSIZE >= KS_SIZE, \"AES context storage\" );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( ( type == CAPABILITY_INFO_STATESIZE || \\\n\t\t\t\t  type == CAPABILITY_INFO_STATEALIGNTYPE ) && \\\n\t\t\t\tcontextInfoPtr == NULL ) || \\\n\t\t\t  ( type == CAPABILITY_INFO_ICV && \\\n\t\t\t\tcontextInfoPtr != NULL ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tswitch( type )\n\t\t{\n\t\tcase CAPABILITY_INFO_STATESIZE:\n\t\t\t{\n\t\t\tint *valuePtr = ( int * ) data;\n\t\t\n#ifdef USE_GCM\n\t\t\t*valuePtr = max( AES_EXPANDED_KEYSIZE, AES_GCM_EXPANDED_KEYSIZE );\n#else\n\t\t\t*valuePtr = AES_EXPANDED_KEYSIZE;\n#endif /* USE_GCM */\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CAPABILITY_INFO_STATEALIGNTYPE:\n\t\t\t{\n\t\t\tint *valuePtr = ( int * ) data;\n\n\t\t\t/* The AES code requires alignment to 128-bit boundaries */\n\t\t\t*valuePtr = UNIT_SIZE;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#ifdef USE_GCM\n\t\tcase CAPABILITY_INFO_ICV:\n\t\t\t{\n\t\t\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\t\t\tREQUIRES( convInfo->mode == CRYPT_MODE_GCM );\n\n\t\t\t/* We're about to modify the keying data, make sure that it's \n\t\t\t   still valid before we start */\n\t\t\tif( checksumData( convInfo->key, \\\n\t\t\t\t\t\t\t  convInfo->keyDataSize ) != convInfo->keyDataChecksum )\n\t\t\t\tretIntError();\n\n\t\t\tif( gcm_compute_tag( data, length, \n\t\t\t\t\t\t\t\t GCM_KEY( convInfo ) ) != RETURN_GOOD )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\t\t\t\t\t\t\t\t\t   \n\n\t\t\t/* This process updates internal state which changes the key \n\t\t\t   data checksum, so we have to update the checksum before we \n\t\t\t   return to the caller */\n\t\t\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_GCM */\n\n\t\tdefault:\n\t\t\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAES En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB/CBC/CFB modes.  These are just basic wrappers\n   for the AES code, which either calls down to the C/asm AES routines or\n   uses hardware assist to perform the operation directly */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\treturn( ( aes_ecb_encrypt( buffer, buffer, noBytes, \n\t\t\t\t\t\t\t   ENC_KEY( convInfo ) ) == EXIT_SUCCESS ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_FAILED );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\treturn( ( aes_ecb_decrypt( buffer, buffer, noBytes, \n\t\t\t\t\t\t\t   DEC_KEY( convInfo ) ) == EXIT_SUCCESS ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_FAILED );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If we're using crypto hardware, use that */\n#ifdef HAS_DEVCRYPTO\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\treturn( hwCryptoCrypt( contextInfoPtr, buffer, noBytes, TRUE ) );\n#endif /* HAS_DEVCRYPTO */\n\n\treturn( ( aes_cbc_encrypt( buffer, buffer, noBytes, convInfo->currentIV,\n\t\t\t\t\t\t\t   ENC_KEY( convInfo ) ) == EXIT_SUCCESS ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_FAILED );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If we're using crypto hardware, use that */\n#ifdef HAS_DEVCRYPTO\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\treturn( hwCryptoCrypt( contextInfoPtr, buffer, noBytes, FALSE ) );\n#endif /* HAS_DEVCRYPTO */\n\n\treturn( ( aes_cbc_decrypt( buffer, buffer, noBytes, convInfo->currentIV,\n\t\t\t\t\t\t\t   DEC_KEY( convInfo ) ) == EXIT_SUCCESS ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_FAILED );\n\t}\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tstatus = aes_cfb_encrypt( buffer, buffer, noBytes, convInfo->currentIV,\n\t\t\t\t\t\t\t  ENC_KEY( convInfo ) );\n\tif( status != EXIT_SUCCESS )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* The CFB encryption process updates an internal IV count which \n\t   changes the key data checksum, so we have to update the checksum \n\t   before we return to the caller */\n\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tstatus = aes_cfb_decrypt( buffer, buffer, noBytes, convInfo->currentIV,\n\t\t\t\t\t\t\t  ENC_KEY( convInfo ) );\n\tif( status != EXIT_SUCCESS )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* The CFB decryption process updates an internal IV count which \n\t   changes the key data checksum, so we have to update the checksum \n\t   before we return to the caller */\n\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n#ifdef USE_GCM\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptGCM( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tstatus = gcm_encrypt( buffer, noBytes, GCM_KEY( convInfo ) );\n\tif( status != EXIT_SUCCESS )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* The GCM decryption process updates an internal IV count which \n\t   changes the key data checksum, so we have to update the checksum \n\t   before we return to the caller */\n\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptGCM( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tstatus = gcm_decrypt( buffer, noBytes, GCM_KEY( convInfo ) );\n\tif( status != EXIT_SUCCESS )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* The GCM decryption process updates an internal IV count which \n\t   changes the key data checksum, so we have to update the checksum \n\t   before we return to the caller */\n\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_GCM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAES Key Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise crypto parameters such as the IV and encryption mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initParams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,\n\t\t\t\t\t   IN_OPT const void *data, \n\t\t\t\t\t   IN_INT const int dataLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\tREQUIRES( isEnumRange( paramType, KEYPARAM ) );\n\n\t/* Normally we implement the IV handling ourselves, however the AES code \n\t   implements these modes natively and maintains its own CFB and GCM \n\t   state, so when we get an IV load/reload we have to explicitly reset \n\t   the internal state before passing the load down to the global\n\t   parameter-handling function */\n\tif( paramType == KEYPARAM_IV && \\\n\t\t( convInfo->mode == CRYPT_MODE_CFB || \\\n\t\t  convInfo->mode == CRYPT_MODE_GCM ) )\n\t\t{\n\t\t/* We're about to modify the keying data, make sure that it's still\n\t\t   valid before we start */\n\t\tif( checksumData( convInfo->key, \\\n\t\t\t\t\t\t  convInfo->keyDataSize ) != convInfo->keyDataChecksum )\n\t\t\tretIntError();\n\n#ifdef USE_GCM\n  #ifdef USE_CFB\n\t\tif( convInfo->mode == CRYPT_MODE_CFB )\n\t\t\taes_mode_reset( ENC_KEY( convInfo ) );\n\t\telse\n  #endif /* USE_CFB */\n\t\t\t{\n\t\t\t/* Update the GCM state with the IV */\n\t\t\tif( gcm_init_message( data, dataLength, \n\t\t\t\t\t\t\t\t  GCM_KEY( convInfo ) ) != RETURN_GOOD )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n#else\n\t\taes_mode_reset( ENC_KEY( convInfo ) );\n#endif /* USE_GCM */\n\n\t\t/* This process updates internal state which changes the key data \n\t\t   checksum, so we have to update the checksum before we return to \n\t\t   the caller */\n\t\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\n\t\t/* Fall through to load the IV into the context data */\n\t\t}\n\n\t/* Handling of crypto parameters is normally done by a global generic\n\t   function, however for AES-GCM we have to provide special handling\n\t   for AAD data */\n#ifdef USE_GCM\n\tif( paramType == KEYPARAM_AAD )\n\t\t{\n\t\tREQUIRES( convInfo->mode == CRYPT_MODE_GCM );\n\n\t\t/* We're about to modify the keying data, make sure that it's still\n\t\t   valid before we start */\n\t\tif( checksumData( convInfo->key, \\\n\t\t\t\t\t\t  convInfo->keyDataSize ) != convInfo->keyDataChecksum )\n\t\t\tretIntError();\n\n\t\t/* Update the GCM state with the AAD */\n\t\tif( gcm_auth_header( data, dataLength, \n\t\t\t\t\t\t\t GCM_KEY( convInfo ) ) != RETURN_GOOD ) \n\t\t\treturn( CRYPT_ERROR_FAILED );\n\n\t\t/* This process updates internal state which changes the key data \n\t\t   checksum, so we have to update the checksum before we return to \n\t\t   the caller */\n\t\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_GCM */\n\n\t/* Pass the call on down to the global parameter-handling function */\t\n\treturn( initGenericParams( contextInfoPtr, paramType, data, \n\t\t\t\t\t\t\t   dataLength ) );\n\t}\n\n/* Key schedule an AES key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n#ifdef HAS_DEVCRYPTO\n\tconst int hwCryptInfo = getSysVar( SYSVAR_HWCRYPT );\n#endif /* HAS_DEVCRYPTO */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= AES_KEYSIZE );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* If there's crypto hardware available, try and use that */\n#ifdef HAS_DEVCRYPTO\n\tif( !cryptStatusError( hwCryptInfo ) && \\\n\t\t( hwCryptInfo & HWCRYPT_FLAG_CRYPTDEV_AES ) && \\\n\t\tconvInfo->mode == CRYPT_MODE_CBC )\n\t\t{\n\t\tint status;\n\n\t\tstatus = hwCryptoInit( contextInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* HAS_DEVCRYPTO */\n\n\t/* Call the AES key schedule code */\n#ifdef USE_GCM\n\tif( convInfo->mode == CRYPT_MODE_GCM )\n\t\t{\n\t\tif( gcm_init_and_key( convInfo->userKey, keyLength, \n\t\t\t\t\t\t\t  GCM_KEY( convInfo ) ) != RETURN_GOOD ) \n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\telse\n#endif /* USE_GCM */\n\t\t{\n\t\tif( aes_encrypt_key( convInfo->userKey, keyLength, \n\t\t\t\t\t\t\t ENC_KEY( convInfo ) ) != EXIT_SUCCESS )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\tif( aes_decrypt_key( convInfo->userKey, keyLength, \n\t\t\t\t\t\t\t DEC_KEY( convInfo ) ) != EXIT_SUCCESS )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_AES, bitsToBytes( 128 ), \"AES\", 3,\n\tbitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ),\n\tselfTest, getInfo, NULL, initParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB \n#endif /* USE_CFB */\n#ifdef USE_GCM\n  #ifndef USE_CFB\n\t, NULL, NULL\n  #endif /* USE_CFB */\n\t, encryptGCM, decryptGCM\n#endif /* USE_GCM */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getAESCapability( void )\n\t{\n\t/* If we're not using compiler-generated tables, we have to manually\n\t   initialise the tables before we can use AES (this is only required\n\t   for old/broken compilers that aren't tough enough for the\n\t   preprocessor-based table calculations) */\n#ifndef STATIC_TABLES\n\tgen_tabs();\n#endif /* FIXED_TABLES */\n\n\treturn( &capabilityInfo );\n\t}\n#endif /* USE_AES */\n"
  },
  {
    "path": "deps/cl345/context/ctx_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Encryption Context Attribute Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"context.h\"\n  #include \"asn1.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( contextInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorInited( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( contextInfoPtr, errorLocus, \n\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_PRESENT, CRYPT_ERROR_INITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotInited( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( contextInfoPtr, errorLocus, \n\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_ABSENT, CRYPT_ERROR_NOTINITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( contextInfoPtr, errorLocus, \n\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_ABSENT, CRYPT_ERROR_NOTFOUND ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\tint value;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Clear return value */\n\t*valuePtr = 0;\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_ERRORTYPE:\n\t\t\t*valuePtr = contextInfoPtr->errorType;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORLOCUS:\n\t\t\t*valuePtr = contextInfoPtr->errorLocus;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_MISC_SIDECHANNELPROTECTION:\n\t\t\t*valuePtr = TEST_FLAG( contextInfoPtr->flags,\n\t\t\t\t\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) ? \\\n\t\t\t\t\t\t1 : 0;\n\t\t\t\t\t\t/* This is actually a protection level rather than a \n\t\t\t\t\t\t   boolean value, although internally it's stored as\n\t\t\t\t\t\t   a boolean flag */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_ALGO:\n\t\t\t*valuePtr = capabilityInfoPtr->cryptAlgo;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_MODE:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\t*valuePtr = contextInfoPtr->ctxConv->mode;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYSIZE:\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_CONV:\n\t\t\t\t\tvalue = contextInfoPtr->ctxConv->userKeyLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_PKC:\n\t\t\t\t\tvalue = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tvalue = contextInfoPtr->ctxMAC->userKeyLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_GENERIC:\n\t\t\t\t\tvalue = contextInfoPtr->ctxGeneric->genericSecretLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( value <= 0 )\n\t\t\t\t{\n\t\t\t\t/* If a key hasn't been loaded yet then we return the \n\t\t\t\t   default key size */\n\t\t\t\tvalue = capabilityInfoPtr->keySize;\n\t\t\t\t}\n\t\t\t*valuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_BLOCKSIZE:\n#ifdef USE_CFB\n\t\t\tif( contextType == CONTEXT_CONV && \\\n\t\t\t\tcontextInfoPtr->ctxConv->mode == CRYPT_MODE_CFB )\n\t\t\t\t*valuePtr = 1;\t/* Block cipher in stream mode */\n\t\t\telse\n#endif /* USE_CFB */\n\t\t\t\t*valuePtr = capabilityInfoPtr->blockSize;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_IVSIZE:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tif( !needsIV( contextInfoPtr->ctxConv->mode ) || \\\n\t\t\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t*valuePtr = capabilityInfoPtr->blockSize;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYING_ALGO:\n\t\tcase CRYPT_OPTION_KEYING_ALGO:\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_CONV:\n\t\t\t\t\tvalue = contextInfoPtr->ctxConv->keySetupAlgorithm;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tvalue = contextInfoPtr->ctxMAC->keySetupAlgorithm;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( value <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_ALGO ) );\n\t\t\t\t}\n\t\t\t*valuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYING_ITERATIONS:\n\t\tcase CRYPT_OPTION_KEYING_ITERATIONS:\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_CONV:\n\t\t\t\t\tvalue = contextInfoPtr->ctxConv->keySetupIterations;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tvalue = contextInfoPtr->ctxMAC->keySetupIterations;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( value <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_ITERATIONS ) );\n\t\t\t\t}\n\t\t\t*valuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_PERSISTENT:\n\t\t\t*valuePtr = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t   CONTEXT_FLAG_PERSISTENT ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_KEYFEATURES:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\t*valuePtr = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t   CONTEXT_FLAG_PBO ) ? 1 : 0;\n#ifdef USE_DEVICES\n\t\t\t*valuePtr |= isHandleRangeValid( contextInfoPtr->deviceObject ) ? 2 : 0;\n#endif /* USE_DEVICES */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_DEVICEOBJECT:\n#ifdef USE_DEVICES\n\t\t\tif( isHandleRangeValid( contextInfoPtr->deviceObject ) )\n\t\t\t\t{\n\t\t\t\t*valuePtr = contextInfoPtr->deviceObject;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n#endif /* USE_DEVICES */\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getContextAttributeS( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t  INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_CTXINFO_NAME_ALGO:\n\t\t\treturn( attributeCopy( msgData, capabilityInfoPtr->algoName,\n\t\t\t\t\t\t\t\t   capabilityInfoPtr->algoNameLen ) );\n\n\t\tcase CRYPT_CTXINFO_NAME_MODE:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tswitch( contextInfoPtr->ctxConv->mode )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_MODE_ECB:\n\t\t\t\t\treturn( attributeCopy( msgData, \"ECB\", 3 ) );\n\t\t\t\tcase CRYPT_MODE_CBC:\n\t\t\t\t\treturn( attributeCopy( msgData, \"CBC\", 3 ) );\n#ifdef USE_CFB\n\t\t\t\tcase CRYPT_MODE_CFB:\n\t\t\t\t\treturn( attributeCopy( msgData, \"CFB\", 3 ) );\n#endif /* USE_CFB */\n\t\t\t\tcase CRYPT_MODE_GCM:\n\t\t\t\t\treturn( attributeCopy( msgData, \"GCM\", 3 ) );\n\t\t\t\t}\n\t\t\tretIntError();\n\n\t\tcase CRYPT_CTXINFO_KEYING_SALT:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tif( contextType == CONTEXT_CONV )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv->saltLength <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t\t}\n\t\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxConv->salt,\n\t\t\t\t\t\t\t\t\t   contextInfoPtr->ctxConv->saltLength ) );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->ctxMAC->saltLength <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t}\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxMAC->salt,\n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxMAC->saltLength ) );\n\n\t\tcase CRYPT_CTXINFO_IV:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tif( !needsIV( contextInfoPtr->ctxConv->mode ) || \\\n\t\t\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_IV_SET ) )\n\t\t\t\treturn( exitErrorNotInited( contextInfoPtr, CRYPT_CTXINFO_IV ) );\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxConv->iv,\n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxConv->ivLength ) );\n\n\t\tcase CRYPT_CTXINFO_HASHVALUE:\n\t\t\tREQUIRES( contextType == CONTEXT_HASH || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_HASH_INITED ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_HASH_DONE ) )\n\t\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t\treturn( attributeCopy( msgData, ( contextType == CONTEXT_HASH ) ? \\\n\t\t\t\t\t\t\t\t\t\tcontextInfoPtr->ctxHash->hash : \\\n\t\t\t\t\t\t\t\t\t\tcontextInfoPtr->ctxMAC->mac,\n\t\t\t\t\t\t\t\t   capabilityInfoPtr->blockSize ) );\n\n\t\tcase CRYPT_CTXINFO_LABEL:\n\t\t\tif( contextInfoPtr->labelSize <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_LABEL ) );\n\t\t\t\t}\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->label,\n\t\t\t\t\t\t\t\t   contextInfoPtr->labelSize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_KEYID:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\t\t\tREQUIRES( !isEmptyData( contextInfoPtr->ctxPKC->keyID, 0 ) );\n\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxPKC->keyID,\n\t\t\t\t\t\t\t\t   KEYID_SIZE ) );\n\n#ifdef USE_PGP\n\t\tcase CRYPT_IATTRIBUTE_KEYID_PGP2:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\tif( !TEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t\t\tPKCINFO_FLAG_PGPKEYID_SET ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxPKC->pgp2KeyID,\n\t\t\t\t\t\t\t\t   PGP_KEYID_SIZE ) );\n\n\t\tcase CRYPT_IATTRIBUTE_KEYID_OPENPGP:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\tif( !TEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t\t\tPKCINFO_FLAG_OPENPGPKEYID_SET ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxPKC->openPgpKeyID,\n\t\t\t\t\t\t\t\t   PGP_KEYID_SIZE ) );\n#endif /* USE_PGP */\n\n\t\tcase CRYPT_IATTRIBUTE_KEY_SPKI:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL:\n\t\t\t/* CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL is used to read from dummy\n\t\t\t   contexts used as placeholders for external crypto hardware\n\t\t\t   functionality, these aren't necessarily in the high state as\n\t\t\t   required by a CRYPT_IATTRIBUTE_KEY_SPKI read when they're\n\t\t\t   accessed because the hardware may not be ready yet but we \n\t\t\t   can still fetch the stored public-key data from them */\n\t\t\tREQUIRES( contextType == CONTEXT_PKC && \\\n\t\t\t\t\t  !needsKey( contextInfoPtr ) );\n\n\t\t\tif( contextInfoPtr->ctxPKC->publicKeyInfo != NULL )\n\t\t\t\t{\n\t\t\t\t/* If the data is available in pre-encoded form, copy it\n\t\t\t\t   out */\n\t\t\t\treturn( attributeCopy( msgData, contextInfoPtr->ctxPKC->publicKeyInfo,\n\t\t\t\t\t\t\t\t\t   contextInfoPtr->ctxPKC->publicKeyInfoSize ) );\n\t\t\t\t}\n\t\t\tENSURES( attribute == CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase CRYPT_IATTRIBUTE_KEY_PGP:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSH:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSL:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSL_EXT:\n\t\t\t{\n\t\t\tconst PKC_WRITEKEY_FUNCTION writePublicKeyFunction = \\\n\t\t\t\t( PKC_WRITEKEY_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->writePublicKeyFunction );\n\t\t\tSTREAM stream;\n\t\t\tKEYFORMAT_TYPE formatType;\n\n\t\t\tREQUIRES( contextType == CONTEXT_PKC && \\\n\t\t\t\t\t  !needsKey( contextInfoPtr ) );\n\t\t\tREQUIRES( writePublicKeyFunction != NULL );\n\n\t\t\t/* Write the appropriately-formatted key data from the context */\n\t\t\tstatus = attributeToFormatType( attribute, &formatType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsMemOpenOpt( &stream, msgData->data, msgData->length );\n\t\t\tstatus = writePublicKeyFunction( &stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t formatType,  \"public_key\", 10 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tmsgData->length = stell( &stream );\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\n#ifdef USE_PGP\n\t\tcase CRYPT_IATTRIBUTE_PGPVALIDITY:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\t*( ( time_t * ) msgData->data ) = \\\n\t\t\t\t\t\t\t\t\tcontextInfoPtr->ctxPKC->pgpCreationTime;\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PGP */\n\n\t\tcase CRYPT_IATTRIBUTE_DEVICESTORAGEID:\n#ifdef USE_HARDWARE\n\t\t\tif( contextInfoPtr->deviceStorageIDset )\n\t\t\t\t{\n\t\t\t\treturn( attributeCopy( msgData, contextInfoPtr->deviceStorageID, \n\t\t\t\t\t\t\t\t\t   KEYID_SIZE ) );\n\t\t\t\t}\n#endif /* USE_HARDWARE */\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\tcase CRYPT_IATTRIBUTE_KDFPARAMS:\n\t\t\tREQUIRES( contextType == CONTEXT_GENERIC );\n\n\t\t\tif( contextInfoPtr->ctxGeneric->kdfParamSize <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopy( msgData, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->kdfParams, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->kdfParamSize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_ENCPARAMS:\n\t\t\tREQUIRES( contextType == CONTEXT_GENERIC );\n\n\t\t\tif( contextInfoPtr->ctxGeneric->encAlgoParamSize <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopy( msgData, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->encAlgoParams, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->encAlgoParamSize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_MACPARAMS:\n\t\t\tREQUIRES( contextType == CONTEXT_GENERIC );\n\n\t\t\tif( contextInfoPtr->ctxGeneric->macAlgoParamSize <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( attributeCopy( msgData, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->macAlgoParams, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxGeneric->macAlgoParamSize ) );\n\n\t\tcase CRYPT_IATTRIBUTE_ICV:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_GCM )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\treturn( capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_ICV, \n\t\t\t\t\t\t\t\t\t\t\tcontextInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t\t\t\tmsgData->length ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t IN_INT_Z const int value, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\tint *valuePtr;\n#if defined( USE_DH ) || defined( USE_ECDH ) || defined( USE_ECDSA ) \n\tint status;\n#endif /* USE_DH || USE_ECDH || USE_ECDSA */ \n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( value ) || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\t\t\t  /* Some PKCS #11 device handles are most likely disguised\n\t\t\t\t pointers so we have to allow for outrageous values for\n\t\t\t\t these */\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_MISC_SIDECHANNELPROTECTION:\n\t\t\tif( value > 0 )\n\t\t\t\t{\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t  CONTEXT_FLAG_SIDECHANNELPROTECTION );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tCLEAR_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_SIDECHANNELPROTECTION );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_MODE:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\t/* If the mode for the context isn't set to the initial default \n\t\t\t   value, it's already been explicitly set and we can't change \n\t\t\t   it again.  This isn't quite as straightforward as it seems\n\t\t\t   because the definition of \"initial default mode\" is a bit\n\t\t\t   vague, for stream ciphers it's CTR, for block ciphers it's\n\t\t\t   usually CBC unless we're working with specific hardware \n\t\t\t   crypto that only supports one mode and that mode isn't CBC.\n\t\t\t   For now this only seems to be ECB so we add a special-case\n\t\t\t   check for ECB-only operation */\n\t\t\tif( isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t\t{\n\t\t\t\t/* It's a stream cipher, the only possible mode is an\n\t\t\t\t   implicit CTR so any attempt to change it isn't valid */\n\t\t\t\treturn( exitErrorInited( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_MODE ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n#if 1\t\t\t/* So far no devices without CBC support have been \n\t\t\t\t   encountered, so we always assume a default of CBC */\n\t\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_CBC )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorInited( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_MODE ) );\n\t\t\t\t\t}\n#else\n\t\t\t\tif( capabilityInfoPtr->encryptCBCFunction != NULL )\n\t\t\t\t\t{\n\t\t\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_CBC )\n\t\t\t\t\t\t{\n\t\t\t\t\t\treturn( exitErrorInited( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_MODE ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t/* This algorithm isn't available in CBC mode, the \n\t\t\t\t\t   default will be ECB */\n\t\t\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_ECB )\n\t\t\t\t\t\t{\n\t\t\t\t\t\treturn( exitErrorInited( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_MODE ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\n\t\t\t/* Set the en/decryption mode */\n\t\t\treturn( capabilityInfoPtr->initParamsFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tKEYPARAM_MODE, NULL, value ) );\n\n\t\tcase CRYPT_CTXINFO_KEYSIZE:\n\t\t\t/* Make sure that the requested size is within range */\n\t\t\tif( value < capabilityInfoPtr->minKeySize || \\\n\t\t\t\tvalue > capabilityInfoPtr->maxKeySize )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Get the location to store the key size and make sure that \n\t\t\t   it's not already set */\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_CONV:\n\t\t\t\t\tvaluePtr = &contextInfoPtr->ctxConv->userKeyLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_PKC:\n\t\t\t\t\tvaluePtr = &contextInfoPtr->ctxPKC->keySizeBits;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tvaluePtr = &contextInfoPtr->ctxMAC->userKeyLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_GENERIC:\n\t\t\t\t\tvaluePtr = &contextInfoPtr->ctxGeneric->genericSecretLength;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( *valuePtr != 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYSIZE ) );\n\t\t\t\t}\n\n\t\t\t/* Trim the user-supplied value to the correct shape, taking\n\t\t\t   into account various issues such as limitations with the\n\t\t\t   underlying crypto code/hardware and interop problems with \n\t\t\t   algorithms that allow excessively long keys.  In virtute sunt \n\t\t\t   multi ascensus.\n\n\t\t\t   If it's a PKC key then there's nothing further to do, since \n\t\t\t   the range check above is all that we need.  ECC keys are a \n\t\t\t   bit complicated because if we're using fixed curve parameters \n\t\t\t   (which in practice we always do) there are only a small \n\t\t\t   number of quantised key sizes that we can use, but since some \n\t\t\t   of those correspond to very odd bit sizes like 521 bits that \n\t\t\t   can't be specified as an integral byte count what we do in \n\t\t\t   the ECC code is use the nearest fixed curve parameters equal \n\t\t\t   to or above the given value, avoiding the need for the caller \n\t\t\t   to play guessing games as to which byte-count value \n\t\t\t   corresponds to which curve.\n\t\t\t   \n\t\t\t   For conventional/MAC keys we need to limit the maximum \n\t\t\t   working key length to a sane size since the other side may \n\t\t\t   not be able to handle stupidly large keys */\n\t\t\tif( contextType == CONTEXT_PKC )\n\t\t\t\t*valuePtr = bytesToBits( value );\n\t\t\telse\n\t\t\t\t*valuePtr = min( value, MAX_WORKING_KEYSIZE );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_BLOCKSIZE:\n\t\t\tREQUIRES( contextType == CONTEXT_HASH || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\t/* Some hash (and corresponding MAC) algorithms have variable-\n\t\t\t   length outputs, in which case the blocksize is user-\n\t\t\t   definable */\n\t\t\tif( capabilityInfoPtr->initParamsFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\treturn( capabilityInfoPtr->initParamsFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\tKEYPARAM_BLOCKSIZE, NULL, value ) );\n\n\t\tcase CRYPT_CTXINFO_KEYING_ALGO:\n\t\tcase CRYPT_OPTION_KEYING_ALGO:\n\t\t\t{\n\t\t\tCRYPT_ALGO_TYPE *algoValuePtr;\n\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\t/* The kernel only allows (potentially) valid values to be set,\n\t\t\t   but these may be disabled at the algorithm level so we have \n\t\t\t   to perform an additional check here */\n\t\t\tif( !algoAvailable( value ) )\n\t\t\t\t{\n\t\t\t\treturn( exitError( contextInfoPtr, attribute,\n\t\t\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, \n\t\t\t\t\t\t\t\t   CRYPT_ERROR_NOTAVAIL ) );\n\t\t\t\t}\n\n\t\t\talgoValuePtr = ( contextType == CONTEXT_CONV ) ? \\\n\t\t\t\t\t\t   &contextInfoPtr->ctxConv->keySetupAlgorithm : \\\n\t\t\t\t\t\t   &contextInfoPtr->ctxMAC->keySetupAlgorithm;\n\t\t\tif( *algoValuePtr != CRYPT_ALGO_NONE )\n\t\t\t\treturn( exitErrorInited( contextInfoPtr, attribute ) );\n\t\t\t*algoValuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_CTXINFO_KEYING_ITERATIONS:\n\t\tcase CRYPT_OPTION_KEYING_ITERATIONS:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tvaluePtr = ( contextType == CONTEXT_CONV ) ? \\\n\t\t\t\t\t   &contextInfoPtr->ctxConv->keySetupIterations : \\\n\t\t\t\t\t   &contextInfoPtr->ctxMAC->keySetupIterations;\n\t\t\tif( *valuePtr )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) );\n\t\t\t\t}\n\t\t\t*valuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_KEYING_ALGO_PARAM:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tvaluePtr = ( contextType == CONTEXT_CONV ) ? \\\n\t\t\t\t\t   &contextInfoPtr->ctxConv->keySetupAlgoParam : \\\n\t\t\t\t\t   &contextInfoPtr->ctxMAC->keySetupAlgoParam;\n\t\t\tif( *valuePtr )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_KEYING_ALGO_PARAM ) );\n\t\t\t\t}\n\t\t\t*valuePtr = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_PERSISTENT:\n\t\t\t/* The is-object-persistent attribute functions as follows:\n\n\t\t\t\t\t | Software\t| Hardware\n\t\t\t\t-----+----------+-------------------\n\t\t\t\tPKC\t | R/O (1)\t| R/O (2)\n\t\t\t\t-----+----------+-------------------\n\t\t\t\tConv | R/O (1)\t| R/W low state (3)\n\t\t\t\t\t |\t\t\t| R/O high state\n\n\t\t\t   (1) = Set if stored to or read from a keyset.\n\t\t\t   (2) = Always set.  Private-key objects are automatically\n\t\t\t\t\t created as persistent objects, public-key objects\n\t\t\t\t\t are (transparently) created as software objects since\n\t\t\t\t\t the operation is much faster on the host system than\n\t\t\t\t\t by going via the device.\n\t\t\t   (3) = Can be set in the low state, if set then the object\n\t\t\t\t\t is created as a persistent object in the device.\n\n\t\t\t   Most of these checks are enforced by the kernel, the one \n\t\t\t   thing that the ACL language can't specify is the requirement \n\t\t\t   that a persistent conventional-encryption object be tied to\n\t\t\t   a device, which we do explicitly here */\n\t\t\tif( ( value != 0 ) && \\\n\t\t\t\t!TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\t\t/* Set or clear the persistent flag as required */\n\t\t\tif( value != 0 )\n\t\t\t\t{\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t  CONTEXT_FLAG_PERSISTENT );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tCLEAR_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_PERSISTENT );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_KEYSIZE:\n\t\t\t/* If it's a private key context or a persistent context we need \n\t\t\t   to have a key label set before we can continue */\n\t\t\tif( ( ( contextInfoPtr->type == CONTEXT_PKC ) || \\\n\t\t\t\t  TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ) && \\\n\t\t\t\tcontextInfoPtr->labelSize <= 0 )\n\t\t\t\tretIntError();\n\n\t\t\t/* If the key is held outside the context (e.g. in a device) we\n\t\t\t   may need to manually supply the key-related information \n\t\t\t   needed by the context if it can't be obtained through other\n\t\t\t   means such as when the SubjectPublicKeyInfo is set */\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_CONV:\n\t\t\t\t\tcontextInfoPtr->ctxConv->userKeyLength = value;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_PKC:\n\t\t\t\t\tcontextInfoPtr->ctxPKC->keySizeBits = bytesToBits( value );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tcontextInfoPtr->ctxMAC->userKeyLength = value;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_GENERIC:\n\t\t\t\t\tcontextInfoPtr->ctxGeneric->genericSecretLength = value;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_DH\n\t\tcase CRYPT_IATTRIBUTE_KEY_DLPPARAM:\n\t\t\tstatus = loadDHparams( contextInfoPtr, value );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = completeKeyLoad( contextInfoPtr, FALSE );\n\t\t\treturn( status );\n#endif /* USE_DH */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA ) \n\t\tcase CRYPT_IATTRIBUTE_KEY_ECCPARAM:\n\t\t\tstatus = loadECCparams( contextInfoPtr, value );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = completeKeyLoad( contextInfoPtr, FALSE );\n\t\t\treturn( status );\n#endif /* USE_ECDH || USE_ECDSA */\n\n\t\tcase CRYPT_IATTRIBUTE_DEVICEOBJECT:\n#ifdef USE_DEVICES\n\t\t\t/* Setting the device object means that the crypto functionality \n\t\t\t   for the context is enabled, which means that it's effectively \n\t\t\t   in the key-loaded state, however for standard key-loaded\n\t\t\t   operations to be possible certain other preconditions need to \n\t\t\t   be met, which we check for here */\n\t\t\tREQUIRES( ( contextType == CONTEXT_CONV && \\\n\t\t\t\t\t\tcontextInfoPtr->ctxConv->userKeyLength > 0 ) || \\\n\t\t\t\t\t  ( contextType == CONTEXT_PKC && \\\n\t\t\t\t\t\tcontextInfoPtr->ctxPKC->keySizeBits > 0 && \\\n\t\t\t\t\t\tcontextInfoPtr->ctxPKC->publicKeyInfo != NULL ) || \\\n\t\t\t\t\t  ( contextType == CONTEXT_MAC && \\\n\t\t\t\t\t\tcontextInfoPtr->ctxMAC->userKeyLength > 0 ) || \\\n\t\t\t\t\t  ( contextType == CONTEXT_GENERIC && \\\n\t\t\t\t\t\tcontextInfoPtr->ctxGeneric->genericSecretLength > 0 ) || \\\n\t\t\t\t\t  ( contextType == CONTEXT_HASH ) );\n\n\t\t\t/* Remember the reference to the associated crypto functionality\n\t\t\t   in the device */\n\t\t\tcontextInfoPtr->deviceObject = value;\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n#endif /* USE_DEVICES */\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setContextAttributeS( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t  IN_LENGTH const int dataLength,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( dataLength ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_CTXINFO_KEYING_SALT:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\t\t\tREQUIRES( dataLength > 0 && dataLength <= CRYPT_MAX_HASHSIZE );\n\n\t\t\tif( contextType == CONTEXT_CONV )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv->saltLength > 0 )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t\t}\n\t\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_HASHSIZE ) );\n\t\t\t\tmemcpy( contextInfoPtr->ctxConv->salt, data, dataLength );\n\t\t\t\tcontextInfoPtr->ctxConv->saltLength = dataLength;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->ctxMAC->saltLength > 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t}\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_HASHSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxMAC->salt, data, dataLength );\n\t\t\tcontextInfoPtr->ctxMAC->saltLength = dataLength;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYING_VALUE:\n\t\t\treturn( deriveKey( contextInfoPtr, data, dataLength ) );\n\n\t\tcase CRYPT_CTXINFO_KEY:\n\t\t\t{\n\t\t\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC || \\\n\t\t\t\t\t  contextType == CONTEXT_GENERIC );\n\t\t\tREQUIRES( needsKey( contextInfoPtr ) );\n\t\t\tREQUIRES( loadKeyFunction != NULL );\n\n\t\t\t/* If it's a persistent context we need to have a key label set \n\t\t\t   before we can continue */\n\t\t\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t   CONTEXT_FLAG_PERSISTENT ) && \\\n\t\t\t\tcontextInfoPtr->labelSize <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_LABEL ) );\n\t\t\t\t}\n\n\t\t\t/* The kernel performs a general check on the size of this\n\t\t\t   attribute but doesn't know about context subtype-specific\n\t\t\t   limits so we perform a context-specific check here */\n\t\t\tif( dataLength < capabilityInfoPtr->minKeySize || \\\n\t\t\t\tdataLength > capabilityInfoPtr->maxKeySize )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Load the key into the context */\n\t\t\tstatus = loadKeyFunction( contextInfoPtr, data, dataLength );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n\t\t\treturn( status );\n\t\t\t}\n\n#ifndef USE_FIPS140\n\t\tcase CRYPT_CTXINFO_KEY_COMPONENTS:\n\t\t\treturn( setKeyComponents( contextInfoPtr, data, dataLength ) );\n#endif /* !USE_FIPS140 */\n\n\t\tcase CRYPT_CTXINFO_IV:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\t/* If it's a mode that doesn't use an IV then the load IV \n\t\t\t   operation is meaningless */\n\t\t\tif( !needsIV( contextInfoPtr->ctxConv->mode ) || \\\n\t\t\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t\t/* Make sure that the data size is valid.  GCM is handled \n\t\t\t   specially because the default IV size is somewhat smaller \n\t\t\t   than the cipher block size */\n\t\t\tif( contextInfoPtr->ctxConv->mode == CRYPT_MODE_GCM )\n\t\t\t\t{\n\t\t\t\tif( dataLength < 8 || \\\n\t\t\t\t\tdataLength > capabilityInfoPtr->blockSize )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( dataLength != capabilityInfoPtr->blockSize )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\n\t\t\t/* Load the IV */\n\t\t\treturn( capabilityInfoPtr->initParamsFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\tKEYPARAM_IV, data, dataLength ) );\n\n\t\tcase CRYPT_CTXINFO_LABEL:\n\t\t\t{\n\t\t\tCRYPT_HANDLE iCryptHandle;\n\n\t\t\tif( contextInfoPtr->labelSize > 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_LABEL ) );\n\t\t\t\t}\n\n\t\t\t/* Check any device object that the context is associated with \n\t\t\t   to ensure that nothing with that label already exists in the\n\t\t\t   device.  For keysets the check for duplicates is performed \n\t\t\t   when the context is explicitly added to the keyset but with \n\t\t\t   devices the context will be implicitly created within the \n\t\t\t   device at some future point (at context creation, on key \n\t\t\t   load/generation, or at some other point) that depends on the \n\t\t\t   device.  Because of this we perform a preemptive check for \n\t\t\t   duplicates to avoid a potentially confusing error condition \n\t\t\t   at some indeterminate point in the future.  \n\t\t\t   \n\t\t\t   Since objects are typed, we have to check for the three \n\t\t\t   possible { label, type } combinations.  In theory we could \n\t\t\t   require that labels are only unique per object type but this \n\t\t\t   can lead to problems with underlying devices or keysets that \n\t\t\t   only support a check by label and not by { label, type } \n\t\t\t   combination.  In addition we can't send the message to the \n\t\t\t   context because the kernel won't forward this message type \n\t\t\t   (sending a get-key message to a context doesn't make sense) \n\t\t\t   so we have to explicitly get the dependent device and then \n\t\t\t   send the get-key directly to it */\n\t\t\tstatus = krnlSendMessage( contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETDEPENDENT, &iCryptHandle, \n\t\t\t\t\t\t\t\t\t  OBJECT_TYPE_DEVICE );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t( iCryptHandle != SYSTEM_OBJECT_HANDLE ) )\n\t\t\t\t{\n\t\t\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\n\t\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_NAME, \n\t\t\t\t\t\t\t\t\t   data, dataLength, NULL, 0, \n\t\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\t\t\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_SECRETKEY );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t\t\t\t\t  &getkeyInfo,\n\t\t\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t\t\t\t\t  &getkeyInfo,\n\t\t\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY );\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* We've found something with this label already \n\t\t\t\t\t   present, we can't use it again */\n\t\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\t\t}\n\n\t\t\t\t/* Make sure that the error status wasn't due to a problem \n\t\t\t\t   with the getkeyInfo.  We can get a CRYPT_ARGERROR_OBJECT \n\t\t\t\t   if the target doesn't support a particular operation, so\n\t\t\t\t   this error is allowed */\n\t\t\t\tassert( ( status == CRYPT_ARGERROR_OBJECT ) || \\\n\t\t\t\t\t\t!cryptArgError( status ) );\n\t\t\t\t}\n\t\t\t\n\t\t\tSTDC_FALLTHROUGH;\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_EXISTINGLABEL:\n\t\t\tREQUIRES( dataLength > 0 && dataLength <= CRYPT_MAX_TEXTSIZE );\n\n\t\t\t/* The difference between CRYPT_CTXINFO_LABEL and \n\t\t\t   CRYPT_IATTRIBUTE_EXISTINGLABEL is that the latter is used to \n\t\t\t   set a label for a context that's being instantiated from a \n\t\t\t   persistent object in a device.  We can't perform the \n\t\t\t   duplicate-label check in this case because we'll always get a \n\t\t\t   match for the device object's label */\n\t\t\tif( contextInfoPtr->labelSize > 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_LABEL ) );\n\t\t\t\t}\n\n\t\t\t/* Set the label */\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->label, data, dataLength );\n\t\t\tcontextInfoPtr->labelSize = dataLength;\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_PGP\n\t\tcase CRYPT_IATTRIBUTE_KEYID_OPENPGP:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\t\t\tREQUIRES( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA || \\\n\t\t\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL || \\\n\t\t\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\t\t\tREQUIRES( dataLength == PGP_KEYID_SIZE );\n\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, PGP_KEYID_SIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxPKC->openPgpKeyID, data, dataLength );\n\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t  PKCINFO_FLAG_OPENPGPKEYID_SET );\n\n\t\t\t/* If it's a non-PGP 2.x key type, set the PGP 2.x keyID to the \n\t\t\t   OpenPGP keyID.  This is necessary because non-PGP 2.x keys can\n\t\t\t   be used with PGP 2.x message formats which would imply the use \n\t\t\t   of a PGP 2.x keyID except that it's not defined for this key \n\t\t\t   type */\n\t\t\tif( capabilityInfoPtr->cryptAlgo != CRYPT_ALGO_RSA )\n\t\t\t\t{\n\t\t\t\tmemcpy( contextInfoPtr->ctxPKC->pgp2KeyID, \n\t\t\t\t\t\tcontextInfoPtr->ctxPKC->openPgpKeyID, PGP_KEYID_SIZE );\n\t\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t\t  PKCINFO_FLAG_PGPKEYID_SET );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PGP */\n\n\t\tcase CRYPT_IATTRIBUTE_KEY_SPKI:\n\t\tcase CRYPT_IATTRIBUTE_KEY_PGP:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSH:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSL:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SSL_EXT:\n\t\tcase CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL:\n\t\tcase CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\treturn( setEncodedKey( contextInfoPtr, attribute, data, \n\t\t\t\t\t\t\t\t   dataLength ) );\n\n#ifdef USE_PGP\n\t\tcase CRYPT_IATTRIBUTE_PGPVALIDITY:\n\t\t\tREQUIRES( contextType == CONTEXT_PKC );\n\n\t\t\tcontextInfoPtr->ctxPKC->pgpCreationTime = *( ( time_t * ) data );\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_PGP */\n\n\t\tcase CRYPT_IATTRIBUTE_DEVICESTORAGEID:\n#ifdef USE_HARDWARE\n\t\t\tREQUIRES( dataLength > 0 && dataLength <= KEYID_SIZE );\n\t\t\tmemset( contextInfoPtr->deviceStorageID, 0, KEYID_SIZE );\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, KEYID_SIZE ) );\n\t\t\tmemcpy( contextInfoPtr->deviceStorageID, data, dataLength );\n\t\t\tcontextInfoPtr->deviceStorageIDset = TRUE;\n#endif /* USE_HARDWARE */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_KDFPARAMS:\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxGeneric->kdfParams, data, \n\t\t\t\t\tdataLength );\n\t\t\tcontextInfoPtr->ctxGeneric->kdfParamSize = dataLength;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_ENCPARAMS:\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxGeneric->encAlgoParams, data, \n\t\t\t\t\tdataLength );\n\t\t\tcontextInfoPtr->ctxGeneric->encAlgoParamSize = dataLength;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_MACPARAMS:\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxGeneric->macAlgoParams, data, \n\t\t\t\t\tdataLength );\n\t\t\tcontextInfoPtr->ctxGeneric->macAlgoParamSize = dataLength;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_AAD:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_GCM )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t\t/* Process the AAD */\n\t\t\treturn( capabilityInfoPtr->initParamsFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tKEYPARAM_AAD , data, dataLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete Attributes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteContextAttribute( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_CTXINFO_KEYING_ALGO:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tif( contextType == CONTEXT_CONV )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv->keySetupAlgorithm == CRYPT_ALGO_NONE )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_ALGO ) );\n\t\t\t\t\t}\n\t\t\t\tcontextInfoPtr->ctxConv->keySetupAlgorithm = CRYPT_ALGO_NONE;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->ctxMAC->keySetupAlgorithm == CRYPT_ALGO_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_ALGO ) );\n\t\t\t\t}\n\t\t\tcontextInfoPtr->ctxMAC->keySetupAlgorithm = CRYPT_ALGO_NONE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYING_ITERATIONS:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tif( contextType == CONTEXT_CONV )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv->keySetupIterations == 0 )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_ITERATIONS ) );\n\t\t\t\t\t}\n\t\t\t\tcontextInfoPtr->ctxConv->keySetupIterations = 0;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->ctxMAC->keySetupIterations == 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_ITERATIONS ) );\n\t\t\t\t}\n\t\t\tcontextInfoPtr->ctxMAC->keySetupIterations = 0;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_KEYING_SALT:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV || \\\n\t\t\t\t\t  contextType == CONTEXT_MAC );\n\n\t\t\tif( contextType == CONTEXT_CONV )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv->saltLength == 0 )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t\t}\n\t\t\t\tzeroise( contextInfoPtr->ctxConv->salt, CRYPT_MAX_HASHSIZE );\n\t\t\t\tcontextInfoPtr->ctxConv->saltLength = 0;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->ctxMAC->saltLength == 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEYING_SALT ) );\n\t\t\t\t}\n\t\t\tzeroise( contextInfoPtr->ctxMAC->salt, CRYPT_MAX_HASHSIZE );\n\t\t\tcontextInfoPtr->ctxMAC->saltLength = 0;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_IV:\n\t\t\tREQUIRES( contextType == CONTEXT_CONV );\n\n\t\t\tif( !needsIV( contextInfoPtr->ctxConv->mode ) || \\\n\t\t\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_IV ) );\n\t\t\tcontextInfoPtr->ctxConv->ivLength = \\\n\t\t\t\t\tcontextInfoPtr->ctxConv->ivCount = 0;\n\t\t\tCLEAR_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_IV_SET );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_LABEL:\n\t\t\tif( contextInfoPtr->labelSize <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_LABEL ) );\n\t\t\t\t}\n\t\t\tzeroise( contextInfoPtr->label, contextInfoPtr->labelSize );\n\t\t\tcontextInfoPtr->labelSize = 0;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CTXINFO_HASHVALUE:\n\t\t\tswitch( contextType )\n\t\t\t\t{\n\t\t\t\tcase CONTEXT_HASH:\n\t\t\t\t\tzeroise( contextInfoPtr->ctxHash->hash, CRYPT_MAX_HASHSIZE );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CONTEXT_MAC:\n\t\t\t\t\tzeroise( contextInfoPtr->ctxMAC->mac, CRYPT_MAX_HASHSIZE );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tCLEAR_FLAGS( contextInfoPtr->flags, \n\t\t\t\t\t\t CONTEXT_FLAG_HASH_INITED | CONTEXT_FLAG_HASH_DONE );\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_bn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Bignum Support Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKC\n\n/* The vast numbers of iterated and/or recursive calls to bignum code means \n   that any diagnostic print routines produce an enormous increase in \n   runtime.  To deal with this we define a conditional value that can be used \n   to control printing of output.  In addition where possible the diagnostic \n   code itself tries to minimise the conditions under which it produces \n   output */\n\n#if !defined( NDEBUG ) && defined( USE_ERRMSGS )\nstatic const BOOLEAN diagOutput = FALSE;\n#endif /* Debug build with USE_ERRMSGS */\n\n/* If we're not using dynamically-allocated bignums then we need to convert \n   the bn_expand() macros that are used throughout the bignum code into \n   no-ops.  The following value represents a non-null location that can be\n   used in the bn_expand() macros */\n\n#ifndef BN_ALLOC\nint nonNullAddress;\n#endif /* BN_ALLOC */\n\n/* If we're debugging the bignum allocation code then the clBnAlloc() macro\n   points to the following function */\n\n#ifdef USE_BN_DEBUG_MALLOC\n\nvoid *clBnAllocFn( const char *fileName, const char *fnName,\n\t\t\t\t   const int lineNo, size_t size )\n\t{\n\tprintf( \"BNDEBUG: %s:%s:%d %lu bytes.\\n\", fileName, fnName, \n\t\t\tlineNo, size );\n\treturn( malloc( size ) );\n\t}\n#endif /* USE_BN_DEBUG_MALLOC */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Make sure that a bignum/BN_CTX's metadata is valid */\n\nCHECK_RETVAL_LENGTH_SHORT_NOERROR STDC_NONNULL_ARG( ( 1 ) ) \\\nint getBNMaxSize( const BIGNUM *bignum )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\treturn( ( bignum->flags & BN_FLG_ALLOC_EXT ) ? BIGNUM_ALLOC_WORDS_EXT : \\\n\t\t\t( bignum->flags & BN_FLG_ALLOC_EXT2 ) ? BIGNUM_ALLOC_WORDS_EXT2 : \\\n\t\t\tBIGNUM_ALLOC_WORDS );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBignum( const BIGNUM *bignum )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tif( bignum->top < 0 || bignum->top > getBNMaxSize( bignum ) )\n\t\treturn( FALSE );\n\tif( bignum->neg != TRUE && bignum->neg != FALSE )\n\t\treturn( FALSE );\n\tif( bignum->flags < BN_FLG_NONE || bignum->flags > BN_FLG_MAX )\n\t\treturn( FALSE );\n#ifndef NDEBUG\n\tif( !( bignum->flags & BN_FLG_SCRATCH ) )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_LARGE( i = bignum->top, i < getBNMaxSize( bignum ), i++ )\n\t\t\tassert( bignum->d[ i ] == 0 );\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\t}\n#endif /* Debug mode */\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBNCTX( const BN_CTX *bnCTX )\n\t{\n\tassert( isReadPtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tif( bnCTX->bnArrayMax < 0 || bnCTX->bnArrayMax > BN_CTX_ARRAY_SIZE )\n\t\treturn( FALSE );\n\tif( bnCTX->stackPos < 0 || bnCTX->stackPos >= BN_CTX_ARRAY_SIZE )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckBNMontCTX( const BN_MONT_CTX *bnMontCTX )\n\t{\n\tassert( isReadPtr( bnMontCTX, sizeof( bnMontCTX ) ) );\n\n\tif( !sanityCheckBignum( &bnMontCTX->R ) || \\\n\t\t!sanityCheckBignum( &bnMontCTX->N ) )\n\t\treturn( FALSE );\n\tif( bnMontCTX->flags != 0 && bnMontCTX->flags != BN_FLG_MALLOCED )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Miscellaneous Bignum Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Allocate/initialise/clear/free bignums.  The original OpenSSL bignum code \n   allocates storage on-demand, which results in both lots of kludgery to \n   deal with array bounds and buffer sizes moving around, and huge numbers \n   of memory-allocation/reallocation calls as bignum data sizes creep slowly \n   upwards until some sort of steady state is reached, whereupon the bignum \n   is destroyed and a new one allocated and the whole cycle begins anew.\n\n   To avoid all of this memory-thrashing we use a fixed-size memory block \n   for each bignum, which is unfortunately somewhat wasteful but saves a \n   lot of memory allocation/reallocation and accompanying heap fragmentation \n   (see also the BN_CTX code comments further down).\n\n   A useful side-effect of the elimination of dynamic memory allocation is \n   that the large number of null pointer dereferences on allocation failure \n   in the OpenSSL bignum code are never triggered because there's always \n   memory allocated for the bignum */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_clear( INOUT BIGNUM *bignum )\n\t{\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_V( sanityCheckBignum( bignum ) );\n\n\tif( !( bignum->flags & BN_FLG_STATIC_DATA ) )\n\t\t{\n\t\tDEBUG_PRINT_COND( diagOutput && bignum->top > 64, \\\n\t\t\t\t\t\t  ( \"BN max.size = %d words.\\n\", bignum->top ) );\n\t\tzeroise( bignum->d, bnWordsToBytes( getBNMaxSize( bignum ) ) );\n\t\tbignum->top = bignum->neg = 0;\n\t\tbignum->flags &= ~( BN_FLG_CONSTTIME | BN_FLG_SCRATCH );\n\t\t}\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_init( OUT BIGNUM *bignum )\n\t{\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tmemset( bignum, 0, sizeof( BIGNUM ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void BN_init_ext( INOUT void *bignumExtPtr, \n\t\t\t\t\t\t const BOOLEAN isExt2Bignum )\n\t{\n\tassert( isWritePtr( bignumExtPtr, sizeof( BIGNUM_EXT ) ) );\n\n\tREQUIRES_V( isExt2Bignum == TRUE || isExt2Bignum == FALSE );\n\n\tif( isExt2Bignum )\n\t\t{\n\t\tBIGNUM_EXT2 *bignum = bignumExtPtr;\n\n\t\tmemset( bignum, 0, sizeof( BIGNUM_EXT2 ) );\n\t\tbignum->flags = BN_FLG_ALLOC_EXT2;\n\t\t}\n\telse\n\t\t{\n\t\tBIGNUM_EXT *bignum = bignumExtPtr;\n\n\t\tmemset( bignum, 0, sizeof( BIGNUM_EXT ) );\n\t\tbignum->flags = BN_FLG_ALLOC_EXT;\n\t\t}\n\t}\n\nCHECK_RETVAL_PTR \\\nBIGNUM *BN_new( void )\n\t{\n\tBIGNUM *bignum;\n\n\tbignum = clAlloc( \"BN_new\", sizeof( BIGNUM ) );\n\tif( bignum == NULL )\n\t\treturn( NULL );\n\tBN_init( bignum );\n\tbignum->flags = BN_FLG_MALLOCED;\n\n\treturn( bignum );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_free( INOUT BIGNUM *bignum )\n\t{\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tBN_clear( bignum );\n\tif( bignum->flags & BN_FLG_MALLOCED )\n\t\tclFree( \"BN_free\", bignum );\n\t}\n\n/* Duplicate, swap bignums */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_dup( const BIGNUM *bignum )\n\t{\n\tBIGNUM *newBignum;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tnewBignum = BN_new();\n\tif( newBignum == NULL ) \n\t\treturn( NULL );\n\tif( BN_copy( newBignum, bignum ) == NULL )\n\t\t{\n\t\tBN_free( newBignum );\n\n\t\treturn( NULL );\n\t\t}\n\n\treturn( newBignum );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBIGNUM *BN_copy( INOUT BIGNUM *destBignum, const BIGNUM *srcBignum )\n\t{\n\tassert( isWritePtr( destBignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( srcBignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_N( destBignum != srcBignum );\n\tREQUIRES_N( sanityCheckBignum( destBignum ) );\n\tREQUIRES_N( sanityCheckBignum( srcBignum ) );\n\tREQUIRES_N( getBNMaxSize( destBignum ) >= srcBignum->top );\n\n\t/* Clear out the destination bignum, a general sanitation measure in \n\t   case there's un-cleared data left in it from previous operations */\n\tBN_clear( destBignum );\n\n\t/* Copy most of the bignum fields.  We don't copy the maximum-size field\n\t   or anything but a subset of the flags field since these may differ \n\t   for the two bignums (the flags field will be things like \n\t   BN_FLG_MALLOCED, BN_FLG_STATIC_DATA, and BN_FLG_ALLOC_EXT) */\n\tmemcpy( destBignum->d, srcBignum->d, bnWordsToBytes( srcBignum->top ) );\n\tdestBignum->flags |= srcBignum->flags & BN_FLG_COPY_MASK;\n\tdestBignum->top = srcBignum->top;\n\tdestBignum->neg = srcBignum->neg;\n\n\treturn( destBignum );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid BN_swap( INOUT BIGNUM *bignum1, INOUT BIGNUM *bignum2 )\n\t{\n\tBIGNUM tmp;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( bignum1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bignum2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_V( bignum1 != bignum2 );\n\tREQUIRES_V( !( bignum1->flags & BN_FLG_STATIC_DATA ) );\n\tREQUIRES_V( !( bignum1->flags & BN_FLG_STATIC_DATA ) );\n\n\tBN_init( &tmp );\n\tCKPTR( BN_copy( &tmp, bignum1 ) );\n\tCKPTR( BN_copy( bignum1, bignum2 ) );\n\tCKPTR( BN_copy( bignum2, &tmp ) );\n\tBN_clear( &tmp );\n\n\tENSURES_V( bnStatusOK( bnStatus ) );\n\t}\n\n/* Get a bignum with the value 1 */\n\nCHECK_RETVAL_PTR \\\nconst BIGNUM *BN_value_one( void )\n\t{\n\tstatic const BIGNUM bignum = { 1, FALSE, BN_FLG_STATIC_DATA, \n\t\t\t\t\t\t\t\t   { 1, 0, 0, 0 } };\n\n\t/* Catch problems arising from changes to bignum struct layout */\n\tassert( bignum.top == 1 );\n\tassert( bignum.neg == FALSE );\n\tassert( bignum.flags == BN_FLG_STATIC_DATA );\n\tassert( bignum.d[ 0 ] == 1 && bignum.d[ 1 ] == 0 && bignum.d[ 2 ] == 0 );\n\n\treturn( &bignum );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Manipulate Bignum Values/Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get/set a bignum as a word value */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nBN_ULONG BN_get_word( const BIGNUM *bignum )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_EXT( sanityCheckBignum( bignum ), BN_NAN );\n\n\t/* If the result won't fit in a word, return a NaN indicator */\n\tif( bignum->top > 1 )\n\t\treturn( BN_NAN );\n\n\t/* Bignums with the value zero have a length of zero so we don't try and\n\t   read a data value from them */\n\tif( bignum->top < 1 )\n\t\treturn( 0 );\n\n\treturn( bignum->d[ 0 ] );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_set_word( INOUT BIGNUM *bignum, const BN_ULONG word )\n\t{\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\tREQUIRES_B( !( bignum->flags & BN_FLG_STATIC_DATA ) );\n\n\tBN_clear( bignum );\n\tbignum->d[ 0 ] = word;\n\tbignum->top = word ? 1 : 0;\n\n\treturn( TRUE );\n\t}\n\n/* Count the number of bits used in a word and in a bignum.  The former is \n   the classic log2 problem for which there are about a million clever hacks \n   (including stuffing them into IEEE-754 64-bit floats and fiddling with \n   the bit-representation of those) but they're all endianness/word-size/\n   whatever-dependent and since this is never called in time-critical code \n   we just use a straight loop, which works everywhere */\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint BN_num_bits_word( const BN_ULONG word )\n\t{\n\tBN_ULONG value = word;\n\tint i, LOOP_ITERATOR;\n\n\tLOOP_LARGE( i = 0, i < 128 && value > 0, i++ )\n\t\tvalue >>= 1;\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < 128 );\n\n\treturn( i );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint BN_num_bits( const BIGNUM *bignum )\n\t{\n\tconst int lastWordIndex = bignum->top - 1;\n\tint bits, status;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\n\t/* Bignums with value zero are special-cased since they have a length of\n\t   zero */\n\tif( bignum->top <= 0 )\n\t\treturn( 0 );\n\n\tstatus = bits = BN_num_bits_word( bignum->d[ lastWordIndex ] );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( ( lastWordIndex * BN_BITS2 ) + bits );\n\t}\n\n/* Bit-manipulation operations */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_set_bit( INOUT BIGNUM *bignum, \n\t\t\t\t\tIN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tint bitNo )\n\t{\n\tconst int wordIndex = bitNo / BN_BITS2;\n\tconst int bitIndex = bitNo % BN_BITS2;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\tREQUIRES_B( !( bignum->flags & BN_FLG_STATIC_DATA ) );\n\tREQUIRES_B( bitNo >= 0 && \\\n\t\t\t\tbitNo < bnWordsToBits( getBNMaxSize( bignum ) ) );\n\n\t/* If we're extending the bignum, clear the words up to where we insert \n\t   the bit.\n\t   \n\t   Note that the use of the unified BIGNUM type to also represent a \n\t   BIGNUM_EXT/BIGNUM_EXT2 can result in false-positive warnings from \n\t   bounds-checking applications that apply the d[] array size from a \n\t   BIGNUM to the much larger array in a BIGNUM_EXT/BIGNUM_EXT2 */\n\tif( bignum->top < wordIndex + 1 )\n\t\t{\n\t\tconst int iterationBound = getBNMaxSize( bignum );\n\t\tint index, LOOP_ITERATOR;\n\n\t\tREQUIRES_B( wordIndex < getBNMaxSize( bignum ) );\n\t\tLOOP_EXT( index = bignum->top, index < wordIndex + 1, index++, \n\t\t\t\t  iterationBound )\n\t\t\t{\n\t\t\tbignum->d[ index ] = 0;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tbignum->top = wordIndex + 1;\n\t\t}\n\n\t/* Set the appropriate bit location */\n\tbignum->d[ wordIndex ] |= ( BN_ULONG ) 1 << bitIndex;\n\n\tENSURES_B( sanityCheckBignum( bignum ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_is_bit_set( const BIGNUM *bignum, /* See comment */ int bitNo )\n\t{\n\tconst int wordIndex = bitNo / BN_BITS2;\n\tconst int bitIndex = bitNo % BN_BITS2;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\tREQUIRES_B( bitNo < bnWordsToBits( getBNMaxSize( bignum ) ) );\n\t\t\t\t/* See comment below */\n\n\t/* The OpenSSL bignum code occasionally calls this with negative values \n\t   for the bit to check (e.g. the Montgomery modexp code, which contains \n\t   a comment that explicitly says it'll be calling this function with \n\t   negative bit values) so we have to special-case this condition */\n\tif( bitNo < 0 )\n\t\treturn( 0 );\n\n\t/* Bits off the end of the bignum are always zero */\n\tif( wordIndex >= bignum->top )\n\t\treturn( 0 );\n\n\treturn( ( bignum->d[ wordIndex ] & ( ( BN_ULONG ) 1 << bitIndex ) ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_high_bit( const BIGNUM *bignum )\n\t{\n\tint noBytes = BN_num_bytes( bignum ) - 1;\n\tBN_ULONG highWord;\n\tint highByte;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\n\t/* Bignums with value zero are special-cased since they have a length of\n\t   zero */\n\tif( noBytes < 0 )\n\t\treturn( 0 );\n\n\t/* Extract the topmost nonzero byte in the bignum */\n\thighWord = bignum->d[ noBytes / BN_BYTES ];\n\thighByte = ( int ) ( highWord >> ( ( noBytes % BN_BYTES ) * 8 ) );\n\n\treturn( ( highByte & 0x80 ) ? 1 : 0 );\n\t}\n\n/* Set the sign flag on a bignum.  This is almost universally ignored by the\n   OpenSSL code, which manipulates the sign value directly */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_set_negative( INOUT BIGNUM *bignum, const int value )\n\t{\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\tif( BN_is_zero( bignum ) )\n\t\treturn;\n\tbignum->neg = value ? TRUE : FALSE;\n\t}\n\n/* A bignum operation may have reduced the magnitude of the bignum value,\n   in which case bignum->top will be left pointing to the head of a long\n   string of zeroes.  The following function normalises the representation,\n   leaving bignum->top pointing to the first nonzero entry */\n\nRETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_normalise( INOUT BIGNUM *bignum )\n\t{\n\tconst int iterationBound = getBNMaxSize( bignum );\n\tint LOOP_ITERATOR;\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\n\t/* If it's a zero-magnitude bignum then there's nothing to do */\n\tif( BN_is_zero( bignum ) )\n\t\treturn( TRUE );\n\n\t/* Note that the use of the unified BIGNUM type to also represent a \n\t   BIGNUM_EXT/BIGNUM_EXT2 can result in false-positive warnings from \n\t   bounds-checking applications that apply the d[] array size from a \n\t   BIGNUM to the much larger array in a BIGNUM_EXT/BIGNUM_EXT2 */\n\tLOOP_EXT_CHECKINC( bignum->top > 0, bignum->top--, iterationBound )\n\t\t{\n\t\tif( bignum->d[ bignum->top - 1 ] != 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\tENSURES_B( sanityCheckBignum( bignum ) );\n\n\treturn( TRUE );\n\t}\n\n/* When we're working with a bignum's internal data, we may end up reducing \n   its magnitude, typically via an operation like BN_op( out, in1, in2 ) \n   where 'out' contained a previous value larger than 'in1 op in2'.  In\n   order to deal with this we need to clear any leftover data that wasn't\n   replaced by the operation being performed */\n\nRETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_clear_top( INOUT BIGNUM *bignum, \n\t\t\t\t\t  IN_RANGE( 0, BIGNUM_ALLOC_WORDS_EXT2 ) const int oldTop )\n\t{\n\tconst int iterationBound = getBNMaxSize( bignum );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\t/* We can't call sanityCheckBignum() at this point because there's\n\t   potentially leftover data beyond bignum->top, which is the whole\n\t   reason why this function is being called in the first place */\n\tREQUIRES_B( oldTop >= 0 && oldTop <= getBNMaxSize( bignum ) );\n\n\t/* If we've overwritten any previous contents, we're done */\n\tif( oldTop <= bignum->top )\n\t\treturn( TRUE );\n\n\t/* Clear any previous bignum data content */\n\tLOOP_EXT( i = bignum->top, i < oldTop, i++, iterationBound )\n\t\t{\n\t\tbignum->d[ i ] = 0;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\tENSURES_B( sanityCheckBignum( bignum ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBN_CTX Support Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The BN_CTX code up until about 2000 (or cryptlib 3.21) used to be just an \n   array of BN_CTX_NUM = 32 BIGNUMs.  After that it was replaced by an \n   awkward pool/stack combination that makes something relatively \n   straighforward quite complex.  What's needed is a way of stacking and\n   unstacking blocks of BN_CTX_get()s in nested functions:\n\n\tBN_foo()\n\t\tBN_CTX_start();\n\t\tfoo_a = BN_CTX_get();\n\t\tfoo_b = BN_CTX_get();\n\t\tfoo_c = BN_CTX_get();\n\t\tBN_bar()\n\t\t\tBN_CTX_start();\n\t\t\tbar_a = BN_CTX_get();\n\t\t\tbar_b = BN_CTX_get();\n\t\t\tBN_CTX_end();\n\t\tBN_CTX_end();\n\n   where the first BN_CTX_end() frees up the BNs grabbed in BN_bar() and the\n   second frees up the ones grabbed in BN_foo().  This is why we have the\n   stack alongside the bignum array, every time we increase the nesting depth\n   by calling BN_CTX_start() we remember the stack position that we need to \n   unwind to when BN_CTX_end() is called.\n\n   All of the complex stack/pool manipulations in the original code, \n   possibly meant to \"optimise\" the strategy of allocating a single fixed-\n   size block of values, actually have a negative effect on memory use \n   because the bookkeeping overhead of dozens of tiny little allocations is \n   more than just allocating the fixed-size block.  Since we can measure the \n   deepest that the allocation ever goes we just use a fixed-size array of \n   bignums set to BN_CTX_ARRAY_SIZE.\n   \n   The init and end functions just set up and clear a BN_CTX */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_init( OUT BN_CTX *bnCTX )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tmemset( bnCTX, 0, sizeof( BN_CTX ) );\n\tLOOP_MED( i = 0, i < BN_CTX_ARRAY_SIZE, i++ )\n\t\tBN_init( &bnCTX->bnArray[ i ] );\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( i == BN_CTX_ARRAY_SIZE );\n\tLOOP_MED( i = 0, i < BN_CTX_EXTARRAY_SIZE, i++ )\n\t\tBN_init_ext( &bnCTX->bnExtArray[ i ], FALSE );\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( i == BN_CTX_EXTARRAY_SIZE );\n\tLOOP_MED( i = 0, i < BN_CTX_EXT2ARRAY_SIZE, i++ )\n\t\tBN_init_ext( &bnCTX->bnExt2Array[ i ], TRUE );\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( i == BN_CTX_EXT2ARRAY_SIZE );\n\tENSURES_V( sanityCheckBNCTX( bnCTX ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_final( INOUT BN_CTX *bnCTX )\n\t{\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_V( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Clear the overall BN_CTX */\n\tzeroise( bnCTX, sizeof( BN_CTX ) );\n\n\t/* The various bignums were cleared when the BN_CTX was zeroised, we now \n\t   have to reset them to their initial state so that they can be \n\t   reused */\n\tBN_CTX_init( bnCTX );\n\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MUL1 freed.\\nEXT_MUL2 freed.\\n\" ));\n\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MONT freed.\\n\" ));\n\t}\n\n/* The start and badly-named end functions (it should be finish()) remember \n   the current stack position and unwind to the last stack position */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_start( INOUT BN_CTX *bnCTX )\n\t{\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_V( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Advance one stack frame */\n\tbnCTX->stackPos++;\n\tbnCTX->stack[ bnCTX->stackPos ] = bnCTX->stack[ bnCTX->stackPos - 1 ];\n\n\tENSURES_V( sanityCheckBNCTX( bnCTX ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_end( INOUT BN_CTX *bnCTX )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_V( sanityCheckBNCTX( bnCTX ) );\n\tREQUIRES_V( bnCTX->stack[ bnCTX->stackPos - 1 ] <= \\\n\t\t\t\t\t\tbnCTX->stack[ bnCTX->stackPos ] );\n\n\t/* Only enable the following when required, the bignum code performs\n\t   a huge number of stackings and un-stackings for which the following\n\t   produces an enormous increase in runtime */\n#if 0\t\n\tDEBUG_PRINT(( \"bnCTX unstacking from %d to %d.\\n\", \n\t\t\t\t  bnCTX->stack[ bnCTX->stackPos - 1 ],\n\t\t\t\t  bnCTX->stack[ bnCTX->stackPos ] ));\n#endif /* 0 */\n\n\t/* Clear each bignum in the current stack frame.  We perform the sanity \n\t   check as an assert() rather than an ENSURES_V() because we want to \n\t   catch programming errors resulting in random garbage being left in\n\t   bignums but don't want to abort the BN_CTX cleanup in release code \n\t   due to a random bit flip */\n\tLOOP_EXT( i = bnCTX->stack[ bnCTX->stackPos - 1 ],\n\t\t\t  i < bnCTX->stack[ bnCTX->stackPos ], i++, BN_CTX_ARRAY_SIZE )\n\t\t{\n\t\tassert( sanityCheckBignum( &bnCTX->bnArray[ i ] ) );\n\t\tBN_clear( &bnCTX->bnArray[ i ] );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\t/* Unwind the stack by one frame */\n\tbnCTX->stack[ bnCTX->stackPos ] = 0;\n\tbnCTX->stackPos--;\n\n\tENSURES_V( sanityCheckBNCTX( bnCTX ) );\n\t}\n\n/* Peel another bignum off the BN_CTX array */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_CTX_get( INOUT BN_CTX *bnCTX )\n\t{\n\tBIGNUM *bignum;\n\tconst int arrayIndex = bnCTX->stack[ bnCTX->stackPos ] + 1;\n\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tif( bnCTX->bnArrayMax >= BN_CTX_ARRAY_SIZE )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\tDEBUG_PRINT(( \"bnCTX array size overflow.\\n\" ));\n\n\t\treturn( NULL );\n\t\t}\n\n\tREQUIRES_N( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Get the element at the previous top-of-stack */\n\tbignum = &bnCTX->bnArray[ arrayIndex - 1 ];\n\tENSURES_N( sanityCheckBignum( bignum ) && BN_is_zero( bignum ) );\n\n\t/* Advance the top-of-stack element by one, and increase the last-used \n\t   postion if it exceeds the existing one */\n\tbnCTX->stack[ bnCTX->stackPos ] = arrayIndex;\n\tif( arrayIndex > bnCTX->bnArrayMax )\n\t\tbnCTX->bnArrayMax = arrayIndex;\n\n\tENSURES_N( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Return the new element at the top of the stack */\n\treturn( bignum );\n\t}\n\n/* The bignum multiplication code requires a few temporary values that grow \n   to an enormous size, rather than resizing every bignum that we use to \n   deal with this we return fixed extra-size bignums when this is explicitly \n   required */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nBIGNUM *BN_CTX_get_ext( INOUT BN_CTX *bnCTX, \n\t\t\t\t\t\tIN_ENUM( BIGNUM_EXT ) const BIGNUM_EXT_TYPE bnExtType )\n\t{\n\tBIGNUM *bignum = NULL;\n\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_N( isEnumRange( bnExtType, BIGNUM_EXT ) );\n\n\tswitch( bnExtType )\n\t\t{\n\t\tcase BIGNUM_EXT_MONT:\n\t\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MONT acquired.\\n\" ));\n\t\t\tbignum = ( BIGNUM * ) &bnCTX->bnExtArray[ 0 ];\n\t\t\tbreak;\n\n\t\tcase BIGNUM_EXT_MUL1:\n\t\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MUL1 acquired.\\n\" ));\n\t\t\tbignum = ( BIGNUM * ) &bnCTX->bnExt2Array[ 0 ];\n\t\t\tbreak;\n\n\t\tcase BIGNUM_EXT_MUL2:\n\t\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MUL2 acquired.\\n\" ));\n\t\t\tbignum = ( BIGNUM * ) &bnCTX->bnExt2Array[ 1 ];\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( bignum != NULL );\n\tENSURES_N( sanityCheckBignum( bignum ) );\n\t\t\t   /* We can't also check that BN_is_zero( bignum ) because we \n\t\t\t      may be getting it for the purpose of clearing it, from \n\t\t\t\t  BN_CTX_end_ext() */\n\n\treturn( bignum );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_end_ext( INOUT BN_CTX *bnCTX, \n\t\t\t\t\t IN_ENUM( BIGNUM_EXT ) const BIGNUM_EXT_TYPE bnExtType )\n\t{\n\tBIGNUM *bignum;\n\n\t/* Perform the standard context cleanup */\n\tBN_CTX_end( bnCTX );\n\n\tENSURES_V( bnExtType == BIGNUM_EXT_MUL1 || \\\n\t\t\t   bnExtType == BIGNUM_EXT_MONT );\n\n\t/* Clear the extended-size bignums */\n\tif( bnExtType == BIGNUM_EXT_MUL1 )\n\t\t{\n\t\tbignum = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\tENSURES_V( bignum != NULL );\n\t\tBN_clear( bignum );\n\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MUL1 cleared.\\n\" ));\n\t\tbignum = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MUL2 );\n\t\tENSURES_V( bignum != NULL );\n\t\tBN_clear( bignum );\n\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MUL2 cleared.\\n\" ));\n\t\t}\n\telse\n\t\t{\n\t\tbignum = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MONT );\n\t\tENSURES_V( bignum != NULL );\n\t\tBN_clear( bignum );\n\t\tDEBUG_PRINT_COND( diagOutput, ( \"EXT_MONT cleared.\\n\" ));\n\t\t}\n\t}\n\n/* Dynamically allocate a BN_CTX, only needed by the ECC code */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL_PTR \\\nBN_CTX *BN_CTX_new( void )\n\t{\n\tBN_CTX *bnCTX;\n\n\tbnCTX = clAlloc( \"BN_CTX_new\", sizeof( BN_CTX ) );\n\tif( bnCTX == NULL )\n\t\treturn( NULL );\n\tBN_CTX_init( bnCTX );\n\tENSURES_N( sanityCheckBNCTX( bnCTX ) );\n\n\treturn( bnCTX );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_CTX_free( INOUT BN_CTX *bnCTX )\n\t{\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_V( sanityCheckBNCTX( bnCTX ) );\n\n\tBN_CTX_final( bnCTX );\n\tclFree( \"BN_CTX_free\", bnCTX );\n\t}\n#endif /* ECDH || ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBN_MONT_CTX Support Routines \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise/clear a BN_MONT_CTX */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_MONT_CTX_init( OUT BN_MONT_CTX *bnMontCTX )\n\t{\n\tassert( isWritePtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\n\tmemset( bnMontCTX, 0, sizeof( BN_MONT_CTX ) );\n\tBN_init( &bnMontCTX->R );\n\tBN_init( &bnMontCTX->N );\n\n\tENSURES_V( sanityCheckBNMontCTX( bnMontCTX ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_MONT_CTX_free( INOUT BN_MONT_CTX *bnMontCTX )\n\t{\n\tassert( isWritePtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\n\t/* We perform the sanity check as an assert() rather than an ENSURES_V() \n\t   because we want to catch programming errors resulting in random \n\t   garbage being left in bignums but don't want to abort the BN_MONT_CTX \n\t   cleanup in release code due to a random bit flip */\n\tassert( sanityCheckBNMontCTX( bnMontCTX ) );\n\n\tBN_clear( &bnMontCTX->R );\n\tBN_clear( &bnMontCTX->N );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( bnMontCTX->flags & BN_FLG_MALLOCED )\n\t\tclFree( \"BN_MONT_CTX_free\", bnMontCTX );\n#endif /* ECDH || ECDSA */\n\t}\n\n/* Set parameters for a Montgomery context.  This computes the constant R \n   used to convert a bignum into the Montgomery form aR mod N and records\n   R and N */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_MONT_CTX_set( INOUT BN_MONT_CTX *bnMontCTX, const BIGNUM *mod, \n\t\t\t\t\t\t INOUT BN_CTX *bnCTX )\n\t{\n\tBIGNUM *R, *modWord;\n\tconst int Nbits = roundUp( BN_num_bits( mod ), BN_BITS2 );\n\tconst int flags = bnMontCTX->flags;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\tassert( isReadPtr( mod, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( mod ) && !BN_is_zero( mod ) && \\\n\t\t\t\t!BN_is_negative( mod ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\tREQUIRES_B( BN_cmp( &bnMontCTX->N, mod ) );\t/* Ensure not already set */\n\n\t/* Clear the Montgomery context entries and record the modulus.  We need\n\t   to preserve the flags around the init since this records details such\n\t   as whether the context is dynamically allocated */\n\tBN_MONT_CTX_init( bnMontCTX );\n\tbnMontCTX->flags = flags;\n\tCKPTR( BN_copy( &bnMontCTX->N, mod ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\tBN_CTX_start( bnCTX );\n\n\t/* Get the temporaries that we'll be working with.  We borrow the \n\t   modWord bignum from the bnMontCTX since we won't be setting it until \n\t   right at the end */\n\tR = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MONT );\n\tif( R == NULL )\n\t\t{\n\t\tBN_CTX_end( bnCTX );\n\t\treturn( FALSE );\n\t\t}\n\tmodWord = &bnMontCTX->R;\n\n\t/* Set up the auxiliary modulus R as a value one larger than a bignum \n\t   word and modWord as a bignum containing the low word of the modulus \n\t   (this fulfils the requirement that R > N, or in this case \n\t   R > modWord).  \n\t   \n\t   modWord can't be zero, or more generally even otherwise the modulus \n\t   would be composite, we make the check explicit otherwise the \n\t   following modular inverse operation won't work */\n\tCK( BN_zero( R ) );\n\tCK( BN_set_bit( R, BN_BITS2 ) );\n\tCK( BN_set_word( modWord, mod->d[ 0 ] ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tBN_CTX_end( bnCTX );\n\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( BN_is_odd( modWord ) );\n\tif( BN_is_one( modWord ) )\n\t\t{\n\t\t/* When modWord is 1, the modular inverse is zero, so instead we \n\t\t   have to explicitly set R to all one bits */\n\t\tCK( BN_set_word( R, BN_MASK2 ) );\n\t\t}\n\telse\n\t\t{\n\t\t/* R = R^-1 mod modWord, shifted left one word (i.e. multiplied by \n\t\t   the initial R value) to make word-based divides easier */\n\t\tCKPTR( BN_mod_inverse( R, R, modWord, bnCTX ) );\n\t\tENSURES_B( !BN_is_zero( R ) );\n\t\tCK( BN_lshift( R, R, BN_BITS2 ) );\n\t\tCK( BN_sub_word( R, 1 ) );\n\t\tCK( BN_div( R, NULL, R, modWord, bnCTX ) );\n\t\t}\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tBN_CTX_end( bnCTX );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Record the least significant word of R */\n\tbnMontCTX->n0 = R->d[ 0 ];\n\n\t/* Set up the value R used for conversion to aR mod N form.  This \n\t   temporarily expands the value to an extremely large size so it's done \n\t   via an extended bignum */\n\tCK( BN_zero( R ) );\n\tCK( BN_set_bit( R, Nbits * 2 ) );\n\tCK( BN_mod( &bnMontCTX->R, R, &bnMontCTX->N, bnCTX ) );\n\n\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MONT );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\tENSURES_B( sanityCheckBNMontCTX( bnMontCTX ) );\n\n\treturn( TRUE );\n\t}\n\n/* Convert values to/from Montgomery form.  Note that BN_from_montgomery()\n   modifies its input value as part of the conversion process, this is done\n   because it saves allocating a temporary bignum only to throw it away \n   again as soon as the conversion is complete, and is safe because the only\n   values passed to it are themselves temporaries output from other\n   calculations */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_to_montgomery( INOUT BIGNUM *ret, const BIGNUM *a,\n\t\t\t\t\t\t  const BN_MONT_CTX *bnMontCTX,\n\t\t\t\t\t\t  INOUT BN_CTX *bnCTX )\n\t{\n\tassert( isWritePtr( ret, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\t/* This is just a wrapper for BN_mod_mul_montgomery() */\n\treturn( BN_mod_mul_montgomery( ret, a, &bnMontCTX->R, bnMontCTX, \n\t\t\t\t\t\t\t\t   bnCTX ) );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_from_montgomery( INOUT BIGNUM *ret, INOUT BIGNUM *aTmp,\n\t\t\t\t\t\t\tconst BN_MONT_CTX *bnMontCTX,\n\t\t\t\t\t\t\tINOUT BN_CTX *bnCTX )\n\t{\n\tconst BIGNUM *N = &bnMontCTX->N;\n\tBIGNUM *aTmpExt = NULL;\n\tBN_ULONG *aData, carry = 0;\n\tconst int oldTop = ret->top, nLen = N->top;\n\tconst int iterationBound = getBNMaxSize( N );\n\tint bnStatus = BN_STATUS, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( ret, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( aTmp, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( aTmp ) && !BN_is_zero( aTmp ) && \\\n\t\t\t\t!BN_is_negative( aTmp ) );\n\tREQUIRES_B( ret != aTmp );\n\tREQUIRES_B( sanityCheckBNMontCTX( bnMontCTX ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\n\t/* If the values get very large then we need to use an extended bignum \n\t   as a temporary */\n\tif( nLen * 2 > getBNMaxSize( aTmp ) )\n\t\t{\n\t\tBN_CTX_start( bnCTX );\n\t\taTmpExt = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MONT );\n\t\tif( aTmpExt == NULL || BN_copy( aTmpExt, aTmp ) == NULL )\n\t\t\t{\n\t\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MONT );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\taTmp = aTmpExt;\n\t\t}\n\tBN_set_flags( aTmp, BN_FLG_SCRATCH );\n\taData = aTmp->d;\n\n\t/* Perform the same operation that's used in BN_sqr() (see the long \n\t   comment there for an explanation of what's going on), but in modified \n\t   form to make it constant-time */\n\tLOOP_EXT( i = 0, i < nLen, i++, iterationBound )\n\t\t{\n\t\tconst BN_ULONG aDataVal = aData[ nLen + i ];\n\t\tBN_ULONG tmp;\n\n\t\ttmp = bn_mul_add_words( aData + i, N->d, nLen, \n\t\t\t\t\t\t\t\taData[ i ] * bnMontCTX->n0 ) + carry + aDataVal;\n\t\taData[ nLen + i ] = tmp;\n\n\t\t/* Compute the carry for the next round.  The convoluted logic \n\t\t   expression is required in order to perform the operation in a\n\t\t   branch-free manner if possible (depending on what the compiler \n\t\t   does for code generation */\n\t\tcarry = ( carry | ( tmp != aDataVal ) ) & ( tmp <= aDataVal );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tret->top = nLen;\n\n\t/* Perform the final transformation using a constant-time operation in \n\t   which, if there's a borrow due to the subtraction, we copy out the \n\t   computed result, otherwise we perform a dummy copy of the same data \n\t   into an unused memory location */\n\tif( bn_sub_words( ret->d, aData + nLen, N->d, nLen ) - carry != 0 )\n\t\t{\n\t\t/* There was a borrow, perform the actual copy */\n\t\tmemcpy( ret->d, aData + nLen, bnWordsToBytes( nLen ) );\n\t\t}\n\telse\n\t\t{\n\t\t/* Perform a dummy copy that takes the same time as the real one */\n\t\tmemcpy( aData, aData + nLen, bnWordsToBytes( nLen ) );\n\t\t}\n\tCK( BN_clear_top( ret, oldTop ) );\n\tCK( BN_normalise( ret ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\tBN_clear( aTmp );\n\tif( aTmpExt != NULL )\n\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MONT );\n\n\tENSURES_B( sanityCheckBignum( ret ) );\n\n\treturn( TRUE );\n\t}\n\n/* Dynamically allocate a BN_MONT_CTX, only needed by the ECC code */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL_PTR \\\nBN_MONT_CTX *BN_MONT_CTX_new( void )\n\t{\n\tBN_MONT_CTX *bnMontCTX;\n\n\tbnMontCTX = clAlloc( \"BN_MONT_CTX_new\", sizeof( BN_MONT_CTX ) );\n\tif( bnMontCTX == NULL )\n\t\treturn( NULL );\n\tBN_MONT_CTX_init( bnMontCTX );\n\tbnMontCTX->flags = BN_FLG_MALLOCED;\n\tENSURES_N( sanityCheckBNMontCTX( bnMontCTX ) );\n\n\treturn( bnMontCTX );\n\t}\n#else\n\nCHECK_RETVAL_PTR \\\nBN_MONT_CTX *BN_MONT_CTX_new( void )\n\t{\n\tassert( DEBUG_WARN );\n\treturn( NULL );\n\t}\n#endif /* ECDH || ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBN_RECP_CTX Support Routines \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise/clear a BN_RECP_CTX */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_RECP_CTX_init( OUT BN_RECP_CTX *bnRecpCTX )\n\t{\n\tassert( isWritePtr( bnRecpCTX, sizeof( BN_RECP_CTX ) ) );\n\n\tmemset( bnRecpCTX, 0, sizeof( BN_RECP_CTX ) );\n\n\tBN_init( &bnRecpCTX->N );\n\tBN_init( &bnRecpCTX->Nr );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid BN_RECP_CTX_free( INOUT BN_RECP_CTX *bnRecpCTX )\n\t{\n\tassert( isWritePtr( bnRecpCTX, sizeof( BN_RECP_CTX ) ) );\n\n\t/* We perform the sanity check as an assert() rather than an ENSURES_V() \n\t   because we want to catch programming errors resulting in random \n\t   garbage being left in bignums but don't want to abort the BN_CTX \n\t   cleanup in release code  due to a random bit flip */\n\tassert( sanityCheckBignum( &bnRecpCTX->N ) );\n\tassert( sanityCheckBignum( &bnRecpCTX->Nr ) );\n\n\tBN_clear( &bnRecpCTX->N );\n\tBN_clear( &bnRecpCTX->Nr );\n\t}\n\n/* Initialise a BN_RECP_CTX.  The BN_CTX isn't used for anything, we keep it\n   just to preserve the original function signature */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_RECP_CTX_set( INOUT BN_RECP_CTX *bnRecpCTX, const BIGNUM *d, \n\t\t\t\t\t\t STDC_UNUSED const BN_CTX *bnCTX )\n\t{\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( bnRecpCTX, sizeof( BN_RECP_CTX ) ) );\n\tassert( isReadPtr( d, sizeof( BIGNUM ) ) );\n\n\tUNUSED_ARG( bnCTX );\n\n\t/* Clear context fields.  This should already have been done through an \n\t   earlier call to BN_RECP_CTX_init(), but given that this is OpenSSL, \n\t   we're extra conservative */\n\tBN_RECP_CTX_init( bnRecpCTX );\n\n\t/* N = bignum, Nr = 0 */\n\tCKPTR( BN_copy( &bnRecpCTX->N, d ) );\n\tCK( BN_zero( &bnRecpCTX->Nr ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\t/* Initialise metadata fields */\n\tbnRecpCTX->num_bits = BN_num_bits( d );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntBN( void )\n\t{\n\tif( !bnmathSelfTest() )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bnmath.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Bignum Maths Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"bn_lcl.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"bn/bn_lcl.h\"\t/* For macros used in BN_div() */\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd/Subtract Bignums\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add and subtract two bignums, r = a + b, r = a - b */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_uadd( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b )\n\t{\n\tBN_ULONG carry;\n\tconst int oldTop = r->top;\n\tint length = max( a->top, b->top );\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) );\n\n\t/* Add the two values, propagating the carry if required */\n\tcarry = bn_add_words( r->d, a->d, b->d, length );\n\tif( carry )\n\t\tr->d[ length++ ] = 1;\n\tr->top = length;\n\tBN_set_negative( r, FALSE );\n\tBN_clear_top( r, oldTop );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/* Subtract two bignums, r = a - b */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_usub( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b )\n\t{\n\tBN_ULONG carry;\n\tconst int oldTop = r->top;\n\tint length = max( a->top, b->top ), bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) );\n\tREQUIRES_B( BN_cmp( a, b ) >= 0 );\n\n\t/* Subtract the two values.  The carry should be zero since a >= b */\n\tcarry = bn_sub_words( r->d, a->d, b->d, length );\n\tENSURES_B( !carry );\n\tr->top = length;\n\tBN_set_negative( r, FALSE );\n\tBN_clear_top( r, oldTop );\n\n\t/* The subtraction may have reduced the size of the resulting value so \n\t   we have to normalise it before we return */\n\tCK( BN_normalise( r ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/* Signed versions of the above: r = a + b, r = a - b.  These are just \n   wrappers around BN_uadd()/BN_usub() that deal with sign bits as\n   appropriate */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_add( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b )\n\t{\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\n\t/* a can be negative via the BN_mod_inverse() used in Montgomery \n\t   ops */\n\tREQUIRES_B( sanityCheckBignum( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_negative( b ) );\n\n\t/* If a is negative then -a + b becomes b - a.  We can't pass this down \n\t   to BN_sub() because that expects positive numbers so we have to \n\t   handle the special case here, but in any case it's straightforward\n\t   because abs( a ) <= b so the result is always a positive number */\n\tif( BN_is_negative( a ) ) \n\t\t{\n\t\tREQUIRES_B( BN_ucmp( a, b ) <= 0 ); \n\n\t\tif( !BN_usub( r, b, a ) )\n\t\t\treturn( FALSE );\n\t\tBN_set_negative( r, FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* It's a straight add */\n\treturn( BN_uadd( r, a, b ) );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_sub( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b )\n\t{\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_negative( b ) );\n\n\t/* If a < b then the result is the difference as a negative number */\n\tif( BN_ucmp( a, b ) < 0 ) \n\t\t{\n\t\tif( !BN_usub( r, b, a ) )\n\t\t\treturn( FALSE );\n\t\tBN_set_negative( r, TRUE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* It's a straight subtract */\n\treturn( BN_usub( r, a, b ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tShift Bignums\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Shift a bignum left or right */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_lshift( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t   IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tconst int shiftAmount )\n\t{\n\tconst int wordShiftAmount = shiftAmount / BN_BITS2;\n\tconst int bitShiftAmount = shiftAmount % BN_BITS2;\n\tconst int bitShiftRemainder = BN_BITS2 - bitShiftAmount;\n\tconst BN_ULONG *aData = a->d;\n\tconst int oldTop = r->top;\n\tconst int iterationBound = getBNMaxSize( a );\n\tBN_ULONG *rData = r->d;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) );\n\tREQUIRES_B( shiftAmount > 0 && \\\n\t\t\t\tshiftAmount < bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES_B( a->top + wordShiftAmount < getBNMaxSize( r ) );\n\n\t/* Copy across the sign bit.  a can be negative via the BN_mod_inverse() \n\t   used in Montgomery ops */\n\tBN_set_negative( r, BN_is_negative( a ) );\n\n\t/* If we're shifting a word at a time then it's just a straight copy \n\t   operation */\n\tif( bitShiftAmount == 0 )\n\t\t{\n\t\t/* Move the words up, starting from the MSB and moving down to the \n\t\t   LSB */\n\t\tLOOP_EXT( i = a->top - 1, i >= 0, i--, iterationBound )\n\t\t\t{\n\t\t\trData[ wordShiftAmount + i ] = aData[ i ];\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* Set the new top based on what we've shifted up */\n\t\tr->top = a->top + wordShiftAmount;\n\t\t}\n\telse\n\t\t{\n\t\tBN_ULONG left, right = 0;\n\n\t\t/* Shift everything up by taking two words and extracting out the \n\t\t   single word of shifted data that we need */\n\t\tLOOP_EXT( i = a->top - 1, i >= 0, i--, iterationBound ) \n\t\t\t{\n\t\t\tleft = aData[ i ];\n\t\t\trData[ wordShiftAmount + i + 1 ] = \\\n\t\t\t\t( right << bitShiftAmount ) | ( left >> bitShiftRemainder );\n\t\t\tright = left;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\trData[ wordShiftAmount ] = right << bitShiftAmount;\n\n\t\t/* Set the new top based on what we've shifted up */\n\t\tr->top = a->top + wordShiftAmount;\n\t\tif( rData[ r->top ] != 0 )\n\t\t\t{\n\t\t\t/* We shifted bits off the end of the last word, extend the \n\t\t\t   length by one word */\n\t\t\tr->top++;\n\t\t\tENSURES( r->top <= getBNMaxSize( r ) );\n\t\t\t}\n\t\t}\n\tBN_clear_top( r, oldTop );\n\n\t/* Clear the space that we've shifted up from.  This can become an issue \n\t   when r == a */\n\tLOOP_EXT( i = 0, i < wordShiftAmount, i++, iterationBound )\n\t\t{ \n\t\trData[ i ] = 0;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_rshift( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t   IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\tconst int shiftAmount )\n\t{\n\tconst int wordShiftAmount = shiftAmount / BN_BITS2;\n\tconst int bitShiftAmount = shiftAmount % BN_BITS2;\n\tconst int bitShiftRemainder = BN_BITS2 - bitShiftAmount;\n\tconst int wordsToShift = a->top - wordShiftAmount;\n\tconst BN_ULONG *aData = a->d;\n\tconst int oldTop = r->top;\n\tconst int iterationBound = getBNMaxSize( a );\n\tBN_ULONG *rData = r->d;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_negative( a ) );\n\tREQUIRES_B( shiftAmount > 0 && \\\n\t\t\t\tshiftAmount < bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES_B( wordShiftAmount < a->top || BN_is_zero( a ) );\n\tREQUIRES_B( wordShiftAmount + wordsToShift < getBNMaxSize( r ) );\n\n\t/* a can be zero when we're being called from routines like \n\t   BN_mod_inverse() that iterate until a certain value is reached */\n\tif( BN_is_zero( a ) )\n\t\t{\n\t\tint bnStatus = BN_STATUS;\n\n\t\tCK( BN_zero( r ) );\n\t\tENSURES_B( bnStatusOK( bnStatus ) );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Clear the sign bit.  We know that it's not set since a can't be \n\t   negative, so we just clear it unconditionally */ \n\tBN_set_negative( r, FALSE );\n\n\t/* If we're shifting a word at a time then it's just a straight copy \n\t   operation */\n\tif( bitShiftAmount == 0 ) \n\t\t{\n\t\t/* Move the words down, starting from the LSB and moving down to the \n\t\t   MSB */\n\t\tLOOP_EXT( i = 0, i < wordsToShift, i++, iterationBound )\n\t\t\t{\n\t\t\trData[ i ] = aData[ wordShiftAmount + i ];\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* Set the new top based on what we've shifted down */\n\t\tr->top = wordsToShift;\n\t\t} \n\telse\n\t\t{\n\t\tBN_ULONG left, right;\n\n\t\t/* Shift everything down by taking two words and extracting out the \n\t\t   single word of shifted data that we need.  Since we're taking two \n\t\t   words at a time (i.e. reading ahead by one word), we only iterate\n\t\t   to wordsToShift - 1 */\n\t\tleft = aData[ wordShiftAmount ];\n\t\tLOOP_EXT( i = 0, i < wordsToShift - 1, i++, iterationBound ) \n\t\t\t{\n\t\t\tright = aData[ wordShiftAmount + i + 1 ];\n\t\t\trData[ i ] = ( left >> bitShiftAmount ) | ( right << bitShiftRemainder );\n\t\t\tleft = right;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* Set the new top based on what we've shifted down */\n\t\tr->top = wordsToShift - 1;\n\n\t\t/* Add in any remaining bits if required */\n\t\tleft >>= bitShiftAmount;\n\t\tif( left > 0 )\n\t\t\trData[ r->top++ ] = left;\n\t\t}\n\tBN_clear_top( r, oldTop );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPerform Word Ops on Bignums\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add and subtract words to/from a bignum */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_add_word( INOUT BIGNUM *a, const BN_ULONG w )\n\t{\n\tBN_ULONG *aData = a->d, word = w;\n\tconst int iterationBound = getBNMaxSize( a );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( word > 0 );\n\n\t/* Do an add with carry.  We can't use the bn_xxx_words() form because\n\t   it adds the words of two bignums, not a word to a bignum */\n\tLOOP_EXT( i = 0, i < a->top, i++, iterationBound )\n\t\t{\n\t\taData[ i ] += word;\n\n\t\t/* If there wasn't an overflow then we're done, otherwise continue \n\t\t   with carry */\n\t\tif( word <= aData[ i ] )\n\t\t\tbreak;\n\t\tword = 1;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* If we've overflowed onto a new word, increase the length of the \n\t   bignum.  The logic here is as follows, if we got as far as a->top\n\t   without exiting the loop (so i >= a->top) then we're propagating a\n\t   carry (a->top is at least 1 since a is non-zero so we've passed at \n\t   least once through the loop, setting word = 1), so we know that the \n\t   top word has the value 1 */\n\tif( i >= a->top )\n\t\taData[ a->top++ ] = 1;\n\n\tENSURES_B( sanityCheckBignum( a ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_sub_word( INOUT BIGNUM *a, const BN_ULONG w )\n\t{\n\tBN_ULONG *aData = a->d, word = w;\n\tconst int iterationBound = getBNMaxSize( a );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( word > 0 );\n\tREQUIRES_B( a->top > 1 || aData[ 0 ] >= w );\n\t\t\t\t/* Result shouldn't go negative */\n\n\t/* The bignum is larger than the value that we're subtracting, do a \n\t   simple subtract with carry.  At this point we again run into the\n\t   bizarro non-orthogonality of the bn_xxx_words() routines where they\n\t   sometimes act on { bignum, word }, sometimes on { bignum, bignum },\n\t   and sometimes on { hiWord, loWord, word }.  In this case it's\n\t   { bignum, bignum } so we have to synthesise the { bignum, word }\n\t   form outselves */\n\tLOOP_EXT( i = 0, i < a->top, i++, iterationBound )\n\t\t{\n\t\t/* If we can satisfy the subtract from the current bignum word then\n\t\t   we're done */\n\t\tif( aData[ i ] >= word )\n\t\t\t{\n\t\t\taData[ i ] -= word;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Subtract the word with carry */\n\t\taData[ i ] -= word;\n\t\tword = 1;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* If we've cleared the top word, decrease the overall bignum length */\n\tif( aData[ a->top - 1 ] == 0 )\n\t\ta->top--;\n\n\tENSURES_B( sanityCheckBignum( a ) );\n\n\treturn( TRUE );\n\t}\n\n/* Multiply and divide (more accurately, perform a modulo operation) words \n   to/from a bignum */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN BN_mul_word( INOUT BIGNUM *a, const BN_ULONG w )\n\t{\n\tBN_ULONG *aData = a->d, word;\n\n\tassert( isWritePtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( w > 0 );\n\n\t/* For once we've got a bn_xxx_words() form that's actually useful, so \n\t   we just call down to that */\n\tword = bn_mul_words( aData, aData, a->top, w );\n\tif( word > 0 )\n\t\taData[ a->top++ ] = word;\n\n\tENSURES_B( sanityCheckBignum( a ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN BN_mod_word( OUT BN_ULONG *r, const BIGNUM *a, const BN_ULONG w )\n\t{\n\tconst BN_ULONG *aData = a->d;\n\tBN_ULONG value = 0;\n\tconst int iterationBound = getBNMaxSize( a );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BN_ULONG ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( w > 0 );\n\n\t/* Clear return value */\n\t*r = 0;\n\n\t/* Now we run into yet another member of the non-orthogonal OpenSSL zoo,\n\t   this time a function that divides hi:lo by a word, so\n\t   result = bn_div_words( hi, lo, word ).  To work with this, we walk\n\t   down the bignum a double-word at a time, propagating the result as\n\t   we go */\n\tLOOP_EXT( i = a->top - 1, i >= 0, i--, iterationBound )\n\t\t{\n\t\tBN_ULONG tmp;\n\n\t\ttmp = bn_div_words( value, aData[ i ], w );\n\t\tvalue = aData[ i ] - ( tmp * w );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t*r = value;\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSquare Bignums\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Square an array of BN_ULONGs */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic BOOLEAN bn_square( INOUT BN_ULONG *r, const BN_ULONG *a, \n\t\t\t\t\t\t  IN_RANGE( 0, BIGNUM_ALLOC_WORDS ) const int length, \n\t\t\t\t\t\t  INOUT BN_ULONG *tmp )\n\t{\n\tBN_ULONG carry;\n\tconst int max = length * 2;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( r, sizeof( BN_ULONG ) * length ) );\n\tassert( isReadPtrDynamic( a, sizeof( BN_ULONG ) * length ) );\n\tassert( isReadPtrDynamic( tmp, sizeof( BN_ULONG ) * ( length * 2 ) ) );\n\n\tREQUIRES_B( length > 0 && length <= BIGNUM_ALLOC_WORDS );\n\n\t/* Walk up the bignum multiplying out the words in it.  For the least-\n\t   significant word it's a straight multiply, for subsequent words it's\n\t   a multiply-accumulate.  To see what's going on here it's helpful to \n\t   consider each round in turn:\n\n\t\tr[ length ]\t\t=\t mul( r + 1, a + 1, length - 1, a[ 0 ] );\n\t\tr[ length + 1 ] = mulacc( r + 3, a + 2, length - 2, a[ 1 ] );\n\t\tr[ length + 2 ] = mulacc( r + 5, a + 3, length - 3, a[ 2 ] );\n\t\tr[ length + 3 ] = mulacc( r + 7, a + 4, length - 4, a[ 3 ] );\n\n\t   Since we're doubling the value, the low word becomes zero, and we also\n\t   set the high word to zero to handle possible carries in the \n\t   bn_add_words() that follows */\n\tr[ 0 ] = r[ max - 1 ] = 0;\n\tif( length > 1 )\n\t\t{\n\t\tr[ length ] = bn_mul_words( &r[ 1 ], &a[ 1 ], length - 1, a[ 0 ] );\n\t\tLOOP_EXT( i = 1, i < length - 1, i++, BIGNUM_ALLOC_WORDS )\n\t\t\t{\n\t\t\tr[ length + i ] = bn_mul_add_words( &r[ ( i * 2 ) + 1 ], \n\t\t\t\t\t\t\t\t\t\t\t\t&a[ i + 1 ], length - ( i + 1 ), \n\t\t\t\t\t\t\t\t\t\t\t\ta[ i ] );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\t}\n\tcarry = bn_add_words( r, r, r, max );\n\tENSURES_B( carry == 0 );\n\tbn_sqr_words( tmp, a, length );\n\tcarry = bn_add_words( r, r, tmp, max );\n\tENSURES_B( carry == 0 );\n\n\treturn( TRUE );\n\t}\n\n/* Square a bignum: r = a * a */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN BN_sqr( INOUT BIGNUM *r, const BIGNUM *a, INOUT BN_CTX *bnCTX )\n\t{\n\tBIGNUM *rTmp = r, *tmp;\n\tconst int length = a->top;\n\tint oldTop, bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\tREQUIRES_B( length > 0 && length < BIGNUM_ALLOC_WORDS );\n\tREQUIRES_B( 2 * a->top <= getBNMaxSize( r ) );\n\n\tBN_CTX_start( bnCTX );\n\tif( a == r )\n\t\t{\n\t\t/* If the input is the same as the output, we need to use\n\t\t   a temporary value to compute the result into */\n\t\trTmp = BN_CTX_get( bnCTX );\n\t\tif( rTmp == NULL )\n\t\t\t{\n\t\t\tBN_CTX_end( bnCTX );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\toldTop = rTmp->top;\n\n\t/* Call the internal bn_square() function with a temporary as scratch \n\t   space */\n\ttmp = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\tENSURES_B( tmp != NULL );\n\tBN_set_flags( tmp, BN_FLG_SCRATCH );\n\tCK( bn_square( rTmp->d, a->d, length, tmp->d ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\treturn( bnStatus );\n\t\t}\n\n\t/* Squaring a value typically doubles its size, however if the top word\n\t   of the original value has the high half clear then the result is one \n\t   word shorter */\n\trTmp->top = 2 * length;\n\tif( ( a->d[ length - 1 ] & BN_MASK2h ) == 0 )\n\t\trTmp->top--;\n\tBN_clear_top( rTmp, oldTop );\n\tif( rTmp != r )\n\t\t{\n\t\t/* Since the input was the same as the output we need to copy the \n\t\t   temporary back to the output */\n\t\tCKPTR( BN_copy( r, rTmp ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\t{\n\t\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\t\treturn( bnStatus );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPerform Division Ops on Bignums\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Use the top two words of the numerator and divisor to calculate a \n   multiplier s.t. | numerator - divisor * multiplier | < divisor.  This \n   performs a variety of system-specific operations chosen based on what the \n   hardware is capable of and what's most efficient, to make things easier \n   we borrow some of the core macros from OpenSSL, since they've already \n   sorted out which option needs to be used where.\n   \n   numeratorData points at the MSW of the numerator, since the bignum data \n   is in little-endian format subsequent words are at negative offsets to\n   this.  We know the there are always at least 3 words present due to the\n   normalisation and padding process in BN_div() */\n\n#ifdef BN_LLONG\t\t\t\t\t\t/* BN_ULONG 32-bit, BN_ULLONG 64-bit */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN calculateMultiplier( OUT BN_ULONG *multiplier, \n\t\t\t\t\t\t\t\t\tconst BN_ULONG *numeratorData,\n\t\t\t\t\t\t\t\t\tconst BN_ULONG divisorMSW, \n\t\t\t\t\t\t\t\t\tconst BN_ULONG divisorMSWnext ) \n\t{\n\tconst BN_ULONG numeratorMSW = numeratorData[ 0 ];\n\tconst BN_ULONG numeratorMSWnext = numeratorData[ -1 ];\n\tconst BN_ULONG numeratorMSWnext2 = numeratorData[ -2 ];\n\tBN_ULLONG tempWord;\n\tBN_ULONG mult, multRemainder;\n\n\tassert( isWritePtr( multiplier, sizeof( BN_ULONG ) ) );\n\tassert( isReadPtr( numeratorData, sizeof( BN_ULONG ) * 3 ) );\n\n\t/* Clear return value */\n\t*multiplier = 0;\n\n\t/* If the numerator is larger than the divisor then the multiplier is \n\t   all one bits */\n\tif( numeratorMSW >= divisorMSW )\n\t\t{\n\t\t*multiplier = BN_MASK2;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Calculate the initial estimate for the multiplier */\n  #ifdef BN_DIV2W\n\t/* Double-word divide available (most modern compilers), use this if \n\t   possible */\n\tmult = ( BN_ULONG ) \\\n\t\t( ( ( ( ( BN_ULLONG ) numeratorMSW ) << BN_BITS2 ) | numeratorMSWnext ) / divisorMSW );\n  #else\n\tmult = bn_div_words( numeratorMSW, numeratorMSWnext, divisorMSW );\n  #endif /* BN_DIV2W */\n\tmultRemainder = ( numeratorMSWnext - divisorMSW * mult ) & BN_MASK2;\n\ttempWord = ( BN_ULLONG ) divisorMSWnext * mult;\n\n\t/* Refine the estimate.  This operation isn't branch-free, but since \n\t   it's just a few low-complexity instructions it shouldn't be subject \n\t   to any timing issues, particularly compared to the variable-time\n\t   divide that we've just performed.\n\n\t   For the remainder add-overflow-check, we could use \n\t   __builtin_uaddl_overflow() (gcc/clang) or ULongAdd() (Windows), \n\t   however clang generates the same code regardless of whether the \n\t   intrinsic or the portable overflow-check is used and gcc actually \n\t   generates *worse* code for the intrinsic (as well as worse code than \n\t   clang in both cases), so we just stick with the portable version */\n\tif( ( ( ( ( BN_ULLONG ) multRemainder ) << BN_BITS2 ) | numeratorMSWnext2 ) < tempWord )\n\t\t{\n\t\tmult--;\n\t\tmultRemainder += divisorMSW;\n\t\tif( multRemainder >= divisorMSW )\t/* No overflow yet */\n\t\t\t{\n\t\t\ttempWord -= divisorMSWnext;\n\t\t\tif( ( ( ( ( BN_ULLONG ) multRemainder ) << BN_BITS2 ) | numeratorMSWnext2 ) < tempWord )\n\t\t\t\t{\n\t\t\t\tmult--;\n\n\t\t\t\tENSURES( multRemainder + divisorMSW < divisorMSW );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t*multiplier = mult;\n\n\treturn( TRUE );\n\t}\n#else\t\t\t\t\t\t\t\t/* BN_ULONG 64-bit */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN calculateMultiplier( OUT BN_ULONG *multiplier, \n\t\t\t\t\t\t\t\t\tconst BN_ULONG *numeratorData,\n\t\t\t\t\t\t\t\t\tconst BN_ULONG divisorMSW, \n\t\t\t\t\t\t\t\t\tconst BN_ULONG divisorMSWnext ) \n\t{\n\tconst BN_ULONG numeratorMSW = numeratorData[ 0 ];\n\tconst BN_ULONG numeratorMSWnext = numeratorData[ -1 ];\n\tconst BN_ULONG numeratorMSWnext2 = numeratorData[ -2 ];\n\tBN_ULONG mult, multRemainder, tempWordLow, tempWordHigh;\n\n\tassert( isWritePtr( multiplier, sizeof( BN_ULONG ) ) );\n\tassert( isReadPtr( numeratorData, sizeof( BN_ULONG ) * 2 ) );\n\n\t/* Clear return value */\n\t*multiplier = 0;\n\n\t/* If the numerator is larger than the divisor then the multiplier is \n\t   all one bits */\n\tif( numeratorMSW >= divisorMSW )\n\t\t{\n\t\t*multiplier = BN_MASK2;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Calculate the initial estimate for the multiplier */\n\tmult = bn_div_words( numeratorMSW, numeratorMSWnext, divisorMSW );\n\tmultRemainder = ( numeratorMSWnext - divisorMSW * mult ) & BN_MASK2;\n  #if defined( BN_UMULT_LOHI )\n\t/* Compiler-based 128-bit multiply available */\n\tBN_UMULT_LOHI( tempWordLow, tempWordHigh, divisorMSWnext, mult );\n  #elif defined( BN_UMULT_HIGH )\n\t/* Inline asm 64 x 64 -> 64:64 multiply available */\n\ttempWordLow = divisorMSWnext * mult;\n\ttempWordHigh = BN_UMULT_HIGH( divisorMSWnext, mult );\n  #else\n\t{\n\tBN_ULONG multiplierLow, multiplierHigh;\n\n\t/* The method of last resort when no double-word multiply is \n\t   available, break the values up into words and multiply and \n\t   add everything in pieces */\n\ttempWordLow = LBITS( divisorMSWnext );\n\ttempWordHigh = HBITS( divisorMSWnext );\n\tmultiplierLow = LBITS( mult );\n\tmultiplierHigh = HBITS( mult );\n\tmul64( tempWordLow, tempWordHigh, multiplierLow, multiplierHigh );\n\t}\n  #endif /* BN_UMULT_xxx options */\n\n\t/* Perform the same fixup as in the BN_LLONG case, but expressed in \n\t   terms of high:low pairs since we can't store the value in a single \n\t   word */\n\tif( ( multRemainder < tempWordHigh ) || \\\n\t\t( multRemainder == tempWordHigh && numeratorMSWnext2 < tempWordLow ) )\n\t\t{\n\t\tmult--;\n\t\tmultRemainder += divisorMSW;\n\t\tif( multRemainder >= divisorMSW )\t/* No overflow yet */\n\t\t\t{\n\t\t\tif( tempWordLow < divisorMSWnext )\n\t\t\t\ttempWordHigh--;\n\t\t\ttempWordLow -= divisorMSWnext;\n\t\t\tif( ( multRemainder < tempWordHigh ) || \\\n\t\t\t\t( multRemainder == tempWordHigh && numeratorMSWnext2 < tempWordLow ) )\n\t\t\t\t{\n\t\t\t\tmult--;\n\n\t\t\t\tENSURES( multRemainder + divisorMSW < divisorMSW );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t*multiplier = mult;\n\n\treturn( TRUE );\n\t}\n#endif /* !BN_LLONG */\n\n/* Calculate quotient = numerator / divisor, remainder = numerator % divisor.  \n   Either the quotient or the remainder may be NULL, so that the function can \n   be used to calculate both BN_div() and BN_mod().\n\n   There's no explicitly constant-time form of this function since it's not \n   clear whether this is either an issue or actually feasible.  The reason \n   why it's probably not an issue is that it's only used (in the BN_mod() \n   form) in three places where online queries can be made via secure \n   sessions, in the RSA code which is blinded so it doesn't matter, in the \n   (EC)DSA code to reduce k where it doesn't matter, and in the (EC)DSA code \n   to create the signature, where it's working with the output created from \n   the random k and again doesn't really matter (in addition there's the \n   dithering timing-protection on private-key ops in the secure session code).\n   \n   The reason why it's not clear whether it's actually feasible is that the \n   division instruction can vary in time by dozens of cycles, so even a \n   single divide can have more timing-related difference than any extra \n   branches and similar code differences.  Even if we took a measure like\n   zero-padding values to make them a constant length, the fact that we're\n   operating on long strings of zeroes will still produce significant, and\n   measureable, timing differences */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 3, 4, 5 ) ) \\\nBOOLEAN BN_div( INOUT_OPT BIGNUM *quotient, INOUT_OPT BIGNUM *remainder, \n\t\t\t\tconst BIGNUM *numerator, const BIGNUM *divisor,\n\t\t\t\tINOUT BN_CTX *bnCTX )\n\t{\n\tBIGNUM *normalisedNumerator, *normalisedDivisor, *result, *temp;\n\tBN_ULONG *numeratorData, *numeratorDataCurrent, *resultData;\n\tBN_ULONG divisorMSW, divisorMSWnext;\n\tconst BOOLEAN isNegative = BN_is_negative( numerator );\n\tconst int iterationBound = getBNMaxSize( numerator );\n\tconst int oldQuotientSize = ( quotient != NULL ) ? quotient->top : 0;\n\tint numeratorWordCount, divisorWordCount, wordsToProcess;\n\tint normalisationShiftAmt, i, bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( quotient == NULL || isWritePtr( quotient, sizeof( BIGNUM ) ) );\n\tassert( remainder == NULL || isWritePtr( remainder, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( numerator, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( divisor, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\t/* Numerator can be negative via the BN_mod_inverse() used in Montgomery \n\t   ops */\n\tREQUIRES_B( quotient == NULL || sanityCheckBignum( quotient ) );\n\tREQUIRES_B( remainder == NULL || sanityCheckBignum( remainder ) );\n\tREQUIRES_B( quotient != NULL || remainder != NULL );\n\tREQUIRES_B( sanityCheckBignum( numerator ) );\n\tREQUIRES_B( sanityCheckBignum( divisor ) && !BN_is_zero( divisor ) && \\\n\t\t\t\t!BN_is_negative( divisor ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Check for the simplest case of divisor > numerator, resulting in \n\t   either quotient = zero, remainder = numerator, or quotient = one,\n\t   remainder = zero */\n\tif( BN_ucmp( divisor, numerator ) >= 0 ) \n\t\t{\n\t\tif( BN_ucmp( divisor, numerator ) == 0 )\n\t\t\t{\n\t\t\tif( quotient != NULL )\n\t\t\t\tCK( BN_one( quotient ) );\n\t\t\tif( remainder != NULL )\n\t\t\t\tCK( BN_zero( remainder ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( quotient != NULL )\n\t\t\t\tCK( BN_zero( quotient ) );\n\t\t\tif( remainder != NULL && remainder != numerator )\n\t\t\t\tCKPTR( BN_copy( remainder, numerator ) );\n\t\t\t}\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\tBN_CTX_start( bnCTX );\n\tnormalisedNumerator = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\tnormalisedDivisor = BN_CTX_get( bnCTX );\n\tif( quotient != NULL )\n\t\tresult = quotient;\n\telse\n\t\t{\n\t\t/* The caller doesn't want the quotient returned (in other words \n\t\t   we're being called as BN_mod()), compute it to a temporary \n\t\t   value */\n\t\tresult = BN_CTX_get( bnCTX );\n\t\t}\n\ttemp = BN_CTX_get( bnCTX );\n\tif( normalisedNumerator == NULL || normalisedDivisor == NULL || \\\n\t\tresult == NULL || temp == NULL )\n\t\t{\n\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\treturn( FALSE );\n\t\t}\n\tBN_set_flags( temp, BN_FLG_SCRATCH );\n\n\t/* Normalise the numerator and divisor */\n\tnormalisationShiftAmt = BN_BITS2 - ( BN_num_bits( divisor ) % BN_BITS2 );\n\tCK( BN_lshift( normalisedDivisor, divisor, normalisationShiftAmt ) );\n\tnormalisationShiftAmt += BN_BITS2;\n\tCK( BN_lshift( normalisedNumerator, numerator, normalisationShiftAmt ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\treturn( FALSE );\n\t\t}\n\tBN_set_negative( normalisedDivisor, FALSE );\n\tBN_set_negative( normalisedNumerator, FALSE );\n\n\t/* calculateMultiplier() requires three words of numerator data, we have\n\t   at least two present due to the normalisation process above but if we \n\t   need a third we pad the numerator data with a leading zero word.  \n\t   Note that this denormalises the result, so we have to BN_normalise() \n\t   the value at the end of this function */\n\tif( normalisedNumerator->top < 3 ) \n\t\tnormalisedNumerator->d[ normalisedNumerator->top++ ] = 0;\n\n\t/* Now that we've finished fiddling the numerator and divisor, remember \n\t   various values related to them.  We know that numeratorWordCount is \n\t   at least 3 (required by calculateMultiplier()) and wordsToProcess is \n\t   at least 1 due to the normalisation/padding step above, these are \n\t   required in the operations below */\n\tdivisorWordCount = normalisedDivisor->top;\n\tnumeratorWordCount = normalisedNumerator->top;\n\twordsToProcess = numeratorWordCount - divisorWordCount;\n\tnumeratorData = &normalisedNumerator->d[ numeratorWordCount - 1 ];\n\tnumeratorDataCurrent = &normalisedNumerator->d[ wordsToProcess ];\n\tdivisorMSW = normalisedDivisor->d[ divisorWordCount - 1 ];\n\tif( divisorWordCount > 1 )\n\t\tdivisorMSWnext = normalisedDivisor->d[ divisorWordCount - 2 ];\n\telse\n\t\tdivisorMSWnext = 0;\n\tENSURES_B( numeratorWordCount >= 3 && \\\n\t\t\t   numeratorWordCount <= BIGNUM_ALLOC_WORDS_EXT );\n\tENSURES_B( wordsToProcess >= 1 && \\\n\t\t\t   wordsToProcess <= BIGNUM_ALLOC_WORDS );\n\n\t/* Similarly, remember values relating to the result */\n\tresult->top = wordsToProcess;\n\tresultData = &result->d[ wordsToProcess - 1 ];\n\n\t/* Evaluate the MSW.  Note that what's being modified here is the \n\t   local copy of the normalised numerator, not the actual numerator \n\t   passed in by the caller */\n\tif( BN_ucmp_words( numeratorDataCurrent, divisorWordCount, \n\t\t\t\t\t   normalisedDivisor ) >= 0 )\n\t\t{\t\n\t\tbn_sub_words( numeratorDataCurrent, numeratorDataCurrent, \n\t\t\t\t\t  normalisedDivisor->d, divisorWordCount );\n\t\t*resultData-- = 1;\n\t\t} \n\telse\n\t\t{\n\t\tresult->top--;\n\t\tresultData--;\n\t\t}\n\n\t/* Iterate through evey word of numerator/divisor performing a divide \n\t   step on each one */\n\tLOOP_EXT( i = 0, i < wordsToProcess - 1, ( i++, numeratorData-- ), \n\t\t\t  iterationBound ) \n\t\t{\n\t\tBN_ULONG multiplier DUMMY_INIT, word;\n\n\t\t/* Calculate the multiplier (see the comment for \n\t\t   calculateMultiplier()), multiply it by the divisor and fix up the \n\t\t   result.  This is required because we've only used the top two \n\t\t   words of the numerator and divisor when we calculated the \n\t\t   multipler, requiring fixups for edge cases at this point */\n\t\tCK( calculateMultiplier( &multiplier, numeratorData, \n\t\t\t\t\t\t\t\t divisorMSW, divisorMSWnext ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\t{\n\t\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tword = bn_mul_words( temp->d, normalisedDivisor->d, \n\t\t\t\t\t\t\t divisorWordCount, multiplier );\n\t\ttemp->d[ divisorWordCount ] = word;\n\t\tnumeratorDataCurrent--;\n\t\tif( bn_sub_words( numeratorDataCurrent, numeratorDataCurrent, \n\t\t\t\t\t\t  temp->d, divisorWordCount + 1 ) ) \n\t\t\t{\n\t\t\tmultiplier--;\n\t\t\tif( bn_add_words( numeratorDataCurrent, numeratorDataCurrent, \n\t\t\t\t\t\t\t  normalisedDivisor->d, divisorWordCount ) )\n\t\t\t\t{\n\t\t\t\t( *numeratorData )++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Store the current result and move on to the next word */\n\t\t*resultData-- = multiplier;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Clean up the quotient and remainder, which includes restoring the \n\t   remainder from its earlier normalised form */\n\tif( quotient != NULL )\n\t\t{\n\t\tCK( BN_clear_top( quotient, oldQuotientSize ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\t{\n\t\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tBN_set_negative( quotient, isNegative );\n\t\t}\n\tif( remainder != NULL ) \n\t\t{\n\t\t/* Re-normalise the numerator because of the possible padding added\n\t\t   earlier, then restore it from its shifted (normalised) form */\n\t\tCK( BN_normalise( normalisedNumerator ) );\n\t\tCK( BN_rshift( remainder, normalisedNumerator, \n\t\t\t\t\t   normalisationShiftAmt ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\t{\n\t\t\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tBN_set_negative( remainder, isNegative );\n\t\t}\n\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MUL1 );\n\n\tENSURES_B( quotient == NULL || sanityCheckBignum( quotient ) );\n\tENSURES_B( remainder == NULL || sanityCheckBignum( remainder ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPerform Modulus Ops on Bignums\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* BN_mod() variant that always returns a positive result (nn = non-\n   negative) in the range { 0...abs( d ) - 1 }.  m can be negative via the \n   BN_mod_inverse() used in Montgomery ops */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_nnmod( INOUT BIGNUM *r, const BIGNUM *m, const BIGNUM *d, \n\t\t\t\t  INOUT BN_CTX *bnCTX )\n\t{\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( d, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) );\n\tREQUIRES_B( sanityCheckBignum( d ) && !BN_is_zero( d ) && \\\n\t\t\t\t!BN_is_negative( d ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\n\t/* Perform the mod operation and, if the result is negative, add d to \n\t   make it positive again */\n\tCK( BN_mod( r, m, d, bnCTX ) );\n\tif( bnStatusOK( bnStatus) && BN_is_negative( r ) )\n\t\tCK( BN_add( r, r, d ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( bnStatus );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* BN_mod_add/sub that assume that a and b are positive and less than m, \n   which avoids the need for an expensive mod operation */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_add_quick( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\t\t  const BIGNUM *m )\n\t{\n\tint bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_zero( b ) && \\\n\t\t\t\t!BN_is_negative( b ) );\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) && \\\n\t\t\t\t!BN_is_negative( m ) );\n\tREQUIRES_B( BN_ucmp( a, m ) < 0 &&  BN_ucmp( b, m ) < 0 );\n\n\t/* Quick form of mod that subtracts m if the value ends up greater \n\t   than m.  In some extremely rare cases (r large, m small) we have to \n\t   subtract m twice to get r within range */\n\tCK( BN_uadd( r, a, b ) );\n\tLOOP_SMALL_CHECK( bnStatusOK( bnStatus ) && BN_ucmp( r, m ) >= 0 )\n\t\t{\n\t\t/* r is bigger than m, get it back within range */\n\t\tCK( BN_usub( r, r, m ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( bnStatus );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_sub_quick( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\t\t  const BIGNUM *m )\n\t{\n\tint bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_zero( b ) && \\\n\t\t\t\t!BN_is_negative( b ) );\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) && \\\n\t\t\t\t!BN_is_negative( m ) );\n\tREQUIRES_B( BN_ucmp( a, m ) < 0 &&  BN_ucmp( b, m ) < 0 );\n\n\t/* Quick form of mod that adds m if the value ends up negative.  We \n\t   have to use BN_sub() rather than BN_usub() since b can be larger\n\t   than a so that r goes negative */\n\tCK( BN_sub( r, a, b ) );\n\tLOOP_SMALL_CHECK( bnStatusOK( bnStatus ) && BN_is_negative( r ) )\n\t\t{\n\t\t/* r is negative, get it back within range.  Note that we have to use \n\t\t   BN_add() rather than BN_uadd() since r is negative */\n\t\tCK( BN_add( r, r, m ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( bnStatus );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/* BN_mod_lshift() that assumes that a is positive and less than m, avoiding\n   an expensive modulus operation */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nBOOLEAN BN_mod_lshift_quick( BIGNUM *r, const BIGNUM *a,\n\t\t\t\t\t\t\t IN_RANGE( 0, bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\t\t\tconst int shiftAmount,\n\t\t\t\t\t\t\t const BIGNUM *m )\n\t{\n\tint shiftCount, bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( shiftAmount > 0 && \\\n\t\t\t\tshiftAmount < bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) && \\\n\t\t\t\t!BN_is_negative( m ) );\n\tREQUIRES_B( BN_cmp( a, m ) < 0 );\n\n\t/* Initialise the output value if it's not the same as the input */\n\tif( r != a )\n\t\t{\n\t\tCKPTR( BN_copy( r, a ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Convert a shift-and-mod into a series of far less expensive shift-and-\n\t   subtracts.  We do this by ensuring that the shifts are capped so that\n\t   r can only grow to the same size as m, in which case the reduction \n\t   step is just a subtract */\n\tLOOP_EXT_INITCHECK( shiftCount = shiftAmount, shiftCount > 0, \n\t\t\t\t\t\tbytesToBits( CRYPT_MAX_PKCSIZE ) )\n\t\t{\n\t\tint shift;\n\n\t\t/* Set a shift amount that ensures that we can still do a reduction\n\t\t   with a simple subtract.  The first time through this shifts\n\t\t   sufficient bits that r grows to the same size as m, after which\n\t\t   it typically shifts one bit at a time, so the total number of\n\t\t   iterations is 1 + ( sizeof_bits( m ) - sizeof_bits( a ) ) */\n\t\tshift = BN_num_bits( m ) - BN_num_bits( r );\n\t\tENSURES_B( shift >= 0 && shift < bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\t\tif( shift > shiftCount )\n\t\t\tshift = shiftCount;\n\t\telse\n\t\t\t{\n\t\t\t/* If the bignums are the same size, make sure that we shift by\n\t\t\t   at least one bit */\n\t\t\tif( shift == 0 )\n\t\t\t\tshift = 1;\n\t\t\t}\n\n\t\t/* Perform the shift and reduction */\n\t\tCK( BN_lshift( r, r, shift ) );\n\t\tif( bnStatusOK( bnStatus) && BN_cmp( r, m ) >= 0 )\n\t\t\tCK( BN_sub( r, r, m ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( bnStatus );\n\t\tshiftCount -= shift;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/* Generic modmult without special tricks like Montgomery maths */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN BN_mod_mul( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\tconst BIGNUM *m, INOUT BN_CTX *ctx )\n\t{\n\tBIGNUM *tmp;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( ctx, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_zero( b ) && \\\n\t\t\t\t!BN_is_negative( b ) );\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) && \\\n\t\t\t\t!BN_is_negative( m ) );\n\tREQUIRES_B( sanityCheckBNCTX( ctx ) );\n\n\t/* If a and b are the same then we can use a more efficient squaring op \n\t   rather than a multiply */\n\tif( !BN_cmp( a, b ) )\n\t\treturn( BN_mod_sqr( r, a, m, ctx ) );\n\n    BN_CTX_start( ctx );\n    tmp = BN_CTX_get( ctx );\n\tif( tmp == NULL )\n\t\t{\n\t\tBN_CTX_end( ctx );\n\t\treturn( FALSE );\n\t\t}\n\tCK( BN_mul( tmp, a, b, ctx ) );\n\tCK( BN_mod( r, tmp, m, ctx ) );\n\tBN_CTX_end( ctx );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( bnStatus );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/* Mod square */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nBOOLEAN BN_mod_sqr( INOUT BIGNUM *r, const BIGNUM *a, const BIGNUM *m, \n\t\t\t\t\tINOUT BN_CTX *ctx )\n\t{\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( m, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( ctx, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( m ) && !BN_is_zero( m ) && \\\n\t\t\t\t!BN_is_negative( m ) );\n\tREQUIRES_B( sanityCheckBNCTX( ctx ) );\n\n\t/* Since we know that r can't be negative after the squaring (which it \n\t   couldn't be in any case since a is positive), we can just call \n\t   BN_mod() directly */\n    CK( BN_sqr( r, a, ctx ) );\n\tCK( BN_mod( r, r, m, ctx ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( bnStatus );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPerform Montgomery Ops on Bignums\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Montgomery modmult */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN BN_mod_mul_montgomery( INOUT BIGNUM *r, const BIGNUM *a, \n\t\t\t\t\t\t\t   const BIGNUM *b, const BN_MONT_CTX *bnMontCTX, \n\t\t\t\t\t\t\t   INOUT BN_CTX *bnCTX )\n\t{\n\tBIGNUM *tmp;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isReadPtr( r, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( bnMontCTX, sizeof( BN_MONT_CTX ) ) );\n\tassert( isWritePtr( bnCTX, sizeof( BN_CTX ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( a ) && !BN_is_zero( a ) && \\\n\t\t\t\t!BN_is_negative( a ) );\n\tREQUIRES_B( sanityCheckBignum( b ) && !BN_is_zero( b ) && \\\n\t\t\t\t!BN_is_negative( b ) );\n\tREQUIRES_B( sanityCheckBNMontCTX( bnMontCTX ) );\n\tREQUIRES_B( sanityCheckBNCTX( bnCTX ) );\n\tREQUIRES_B( BN_cmp( a, &bnMontCTX->N ) <= 0 );\n\tREQUIRES_B( BN_cmp( b, &bnMontCTX->N ) <= 0 );\n\n\tBN_CTX_start( bnCTX );\n\n\t/* Since we're dealing with oversize values that temporarily get very \n\t   large, we have to use an extended bignum */\n\ttmp = BN_CTX_get_ext( bnCTX, BIGNUM_EXT_MONT );\n\tif( tmp == NULL )\n\t\t{\n\t\tBN_CTX_end( bnCTX );\n\t\treturn( FALSE );\n\t\t}\n\tBN_set_flags( tmp, BN_FLG_SCRATCH );\n\n\t/* Perform the multiply and convert the result back from the Montgomery \n\t   form */\n\tCK( BN_mul( tmp, a, b, bnCTX ) );\n\tCK( BN_from_montgomery( r, tmp, bnMontCTX, bnCTX ) )\n\n\tBN_CTX_end_ext( bnCTX, BIGNUM_EXT_MONT );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\tENSURES_B( sanityCheckBignum( r ) );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCompare Bignums\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Compare two bignums */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint BN_cmp_word( const BIGNUM *bignum, const BN_ULONG word )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\t/* If the bignum is negative then the (unsigned) word is always\n\t   larger.  This can occur via the usual mechanism of the \n\t   BN_mod_inverse() used in Montgomery ops */\n\tif( BN_is_negative( bignum ) )\n\t\treturn( -1 );\n\n\t/* If the bignum is longer than one word then the word being compared is \n\t   smaller */\n\tif( bignum->top > 1 )\n\t\treturn( 1 );\n\n\t/* If the bignum is zero then the word is either equal or larger */\n\tif( bignum->top <= 0 )\n\t\treturn( ( word == 0 ) ? 0 : -1 );\n\n\tif( bignum->d[ 0 ] != word )\n\t\treturn( ( bignum->d[ 0 ] > word ) ? 1 : -1 );\n\t\n\t/* They're identical */\n\treturn( 0 );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint BN_ucmp( const BIGNUM *bignum1, const BIGNUM *bignum2 )\n\t{\n\tconst int bignum1top = bignum1->top;\n\n\tassert( isReadPtr( bignum1, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( bignum2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( bignum1top >= 0 && bignum1top < getBNMaxSize( bignum1 ) );\n\t\t\t\t/* There's not really any error return value that we can use \n\t\t\t\t   here, the best that we can do is return zero on error */\n\n\t/* If we're comparing a bignum to itself (which can happen in functions\n\t   that take bignums as parameters in multiple locations) then we don't \n\t   need to explicitly compare the contents */\n\tif( bignum1 == bignum2 )\n\t\treturn( 0 );\n\n\treturn( BN_ucmp_words( bignum1->d, bignum1top, bignum2 ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint BN_ucmp_words( const BN_ULONG *bignumData1, \n\t\t\t\t   IN_RANGE( 0, BIGNUM_ALLOC_WORDS ) const int bignum1Length, \n\t\t\t\t   const BIGNUM *bignum2 )\n\t{\n\tassert( bignum1Length == 0 || \\\n\t\t\tisReadPtrDynamic( bignumData1, bignum1Length ) );\n\tassert( isReadPtr( bignum2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( bignum1Length >= 0 && bignum1Length <= BIGNUM_ALLOC_WORDS );\n\t\t\t\t/* There's not really any error return value that we can use \n\t\t\t\t   here, the best that we can do is return zero on error */\n\n\t/* If the magnitude differs then we don't need to look at the values */\n\tif( bignum1Length != bignum2->top )\n\t\treturn( ( bignum1Length > bignum2->top ) ? 1 : -1 );\n\n\treturn( bn_cmp_words( bignumData1, bignum2->d, bignum1Length ) );\n\t}\n\n/* Internal function that compares the words of two bignums */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint bn_cmp_words( const BN_ULONG *bignumData1, const BN_ULONG *bignumData2, \n\t\t\t\t  IN_RANGE( 0, BIGNUM_ALLOC_WORDS ) const int length )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( length == 0 || isReadPtrDynamic( bignumData1, length ) );\n\tassert( length == 0 || isReadPtrDynamic( bignumData2, length ) );\n\n\tREQUIRES_B( length >= 0 && length <= BIGNUM_ALLOC_WORDS );\n\t\t\t\t/* There's not really any error return value that we can use \n\t\t\t\t   here, the best that we can do is return zero on error */\n\n\t/* Walk down the bignum until we find a difference */\n\tLOOP_EXT( i = length - 1, i >= 0, i--, BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tif( bignumData1[ i ] != bignumData2[ i ] )\n\t\t\treturn( ( bignumData1[ i ] > bignumData2[ i ] ) ? 1 : -1 );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* They're identical */\n\treturn( 0 );\n\t}\n\n/* An oddball compare function used in BN_mul() via the bn_mul_recursive() \n   routine.  This compares two lots of bignum data of different lengths.\n   Instead of doing the sensible thing and passing in { a, aLen } and\n   { b, bLen }, we get passed { a, b, min( aLen, bLen ), aLen - bLen },\n   where the last value can be negative if a < b, and have to figure things\n   out from there */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint bn_cmp_part_words( const BN_ULONG *a, const BN_ULONG *b, \n\t\t\t\t\t   IN_RANGE( 0, BIGNUM_ALLOC_WORDS_EXT ) const int cl, \n\t\t\t\t\t   IN_RANGE( -BIGNUM_ALLOC_WORDS_EXT, \\\n\t\t\t\t\t\t\t\t BIGNUM_ALLOC_WORDS_EXT ) const int dl )\n\t{\n\tconst BN_ULONG *data = ( dl < 0 ) ? b : a;\n\tconst int max = ( dl < 0 ) ? -dl + cl : dl + cl;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_B( cl >= 0 && cl < BIGNUM_ALLOC_WORDS_EXT );\n\tREQUIRES_B( dl > -BIGNUM_ALLOC_WORDS_EXT && \\\n\t\t\t\tdl < BIGNUM_ALLOC_WORDS_EXT );\n\tREQUIRES_B( max >= 0 && max < BIGNUM_ALLOC_WORDS_EXT );\n\t\t\t\t/* There's not really any error return value that we can use \n\t\t\t\t   here, the best that we can do is return zero on error */\n\n\t/* Compare the overflow portions of length dl.  If any of the overflow\n\t   portion is nonzero then a or b is larger, depending on whether dl is\n\t   positive or negative */\n\tLOOP_EXT( i = cl, i < max, i++, BIGNUM_ALLOC_WORDS_EXT )\n\t\t{\n\t\tif( data[ i ] != 0 )\n\t\t\treturn( ( dl < 0 ) ? -1 : 1 );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Compare the common-length portions */\n\treturn( bn_cmp_words( a, b, cl ) );\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bnpkc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKC_INFO Bignum Support Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Make sure that the metadata for bignums in a PKC_INFO is valid */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckPKCInfo( const PKC_INFO *pkcInfo )\n\t{\n\tassert( isReadPtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\t/* Check the PKC info metadata */\n\tif( !CHECK_FLAGS( pkcInfo->flags, PKCINFO_FLAG_NONE, \n\t\t\t\t\t  PKCINFO_FLAG_MAX ) )\n\t\treturn( FALSE );\n\tif( pkcInfo->keySizeBits < 0 || \\\n\t\tpkcInfo->keySizeBits > bytesToBits( CRYPT_MAX_PKCSIZE ) )\n\t\treturn( FALSE );\n\tif( pkcInfo->publicKeyInfo == NULL )\n\t\t{\n\t\tif( pkcInfo->publicKeyInfoSize != 0 )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( pkcInfo->publicKeyInfoSize < MIN_CRYPT_OBJECTSIZE || \\\n\t\t\tpkcInfo->publicKeyInfoSize >= MAX_INTLENGTH_SHORT )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's a dummy context with the keys held in hardware, we're done.\n\t   In theory we could check for BN_is_zero() for each of the bignums, \n\t   but that only looks at the metadata to see if the bignum has a length\n\t   of zero, and it's not clear what this would achieve */\n\tif( TEST_FLAG( pkcInfo->flags, PKCINFO_FLAG_DUMMY ) )\n\t\treturn( TRUE );\n\n\t/* Check the PKC info bignums */\n\tif( !sanityCheckBignum( &pkcInfo->param1 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param2 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param3 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param4 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param5 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param6 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param7 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->param8 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->blind1 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->blind2 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->tmp1 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->tmp2 ) || \\\n\t\t!sanityCheckBignum( &pkcInfo->tmp3 ) )\n\t\treturn( FALSE );\n\tif( !sanityCheckBNCTX( &pkcInfo->bnCTX ) )\n\t\treturn( FALSE );\n\tif( !sanityCheckBNMontCTX( &pkcInfo->montCTX1 ) || \\\n\t\t!sanityCheckBNMontCTX( &pkcInfo->montCTX2 ) || \\\n\t\t!sanityCheckBNMontCTX( &pkcInfo->montCTX3 ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tBignum Init/Shutdown Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Clear temporary bignum values used during PKC operations */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid clearTempBignums( INOUT PKC_INFO *pkcInfo )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tBN_clear( &pkcInfo->tmp1 ); BN_clear( &pkcInfo->tmp2 );\n\tBN_clear( &pkcInfo->tmp3 );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( pkcInfo->isECC )\n\t\t{\n\t\tBN_clear( &pkcInfo->eccParam_tmp4 ); \n\t\tBN_clear( &pkcInfo->eccParam_tmp5 );\n\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\tBN_CTX_final( &pkcInfo->bnCTX );\n\t}\n\n/* Initialse and free the bignum information in a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initContextBignums( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\tconst BOOLEAN isECC )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( isECC == TRUE || isECC == FALSE );\n\n\t/* Initialise the overall PKC information */\n\tmemset( pkcInfo, 0, sizeof( PKC_INFO ) );\n\tINIT_FLAGS( pkcInfo->flags, PKCINFO_FLAG_NONE );\n\n\t/* Initialise the bignum information */\n\tBN_init( &pkcInfo->param1 ); BN_init( &pkcInfo->param2 );\n\tBN_init( &pkcInfo->param3 ); BN_init( &pkcInfo->param4 );\n\tBN_init( &pkcInfo->param5 ); BN_init( &pkcInfo->param6 );\n\tBN_init( &pkcInfo->param7 ); BN_init( &pkcInfo->param8 );\n\tBN_init( &pkcInfo->blind1 ); BN_init( &pkcInfo->blind2 );\n\tBN_init( &pkcInfo->tmp1 ); BN_init( &pkcInfo->tmp2 );\n\tBN_init( &pkcInfo->tmp3 );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isECC )\n\t\t{\n\t\tpkcInfo->isECC = TRUE;\n\t\tpkcInfo->ecCTX = EC_GROUP_new( EC_GFp_simple_method() );\n\t\tpkcInfo->ecPoint = EC_POINT_new( pkcInfo->ecCTX );\n\t\tpkcInfo->tmpPoint = EC_POINT_new( pkcInfo->ecCTX );\n\t\tif( pkcInfo->ecCTX == NULL || pkcInfo->ecPoint == NULL || \\\n\t\t\tpkcInfo->tmpPoint == NULL )\n\t\t\t{\n\t\t\tif( pkcInfo->tmpPoint != NULL )\n\t\t\t\tEC_POINT_free( pkcInfo->tmpPoint );\n\t\t\tif( pkcInfo->ecPoint != NULL )\n\t\t\t\tEC_POINT_free( pkcInfo->ecPoint );\n\t\t\tif( pkcInfo->ecCTX != NULL )\n\t\t\t\tEC_GROUP_free( pkcInfo->ecCTX );\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\tBN_CTX_init( &pkcInfo->bnCTX );\n\tBN_MONT_CTX_init( &pkcInfo->montCTX1 );\n\tBN_MONT_CTX_init( &pkcInfo->montCTX2 );\n\tBN_MONT_CTX_init( &pkcInfo->montCTX3 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endContextBignums( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\tIN const BOOLEAN isDummyContext )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( sanityCheckPKCInfo( pkcInfo ) );\n\t\t\t/* We don't make this an ENSURES since that would prevent \n\t\t\t   clearing the data.  Since the cleanup is just a series of \n\t\t\t   memset()s of fixed-sized data it doesn't matter if a field \n\t\t\t   is in an inconsistent state */\n\n\tREQUIRES_V( isDummyContext == TRUE || isDummyContext == FALSE );\n\n\tif( !isDummyContext )\n\t\t{\n\t\tBN_clear( &pkcInfo->param1 ); BN_clear( &pkcInfo->param2 );\n\t\tBN_clear( &pkcInfo->param3 ); BN_clear( &pkcInfo->param4 );\n\t\tBN_clear( &pkcInfo->param5 ); BN_clear( &pkcInfo->param6 );\n\t\tBN_clear( &pkcInfo->param7 ); BN_clear( &pkcInfo->param8 );\n\t\tBN_clear( &pkcInfo->blind1 ); BN_clear( &pkcInfo->blind2 );\n\t\tBN_clear( &pkcInfo->tmp1 ); BN_clear( &pkcInfo->tmp2 );\n\t\tBN_clear( &pkcInfo->tmp3 );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t\tif( pkcInfo->isECC )\n\t\t\t{\n\t\t\tEC_POINT_free( pkcInfo->tmpPoint );\n\t\t\tEC_POINT_free( pkcInfo->ecPoint );\n\t\t\tEC_GROUP_free( pkcInfo->ecCTX );\n\t\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\t\tBN_CTX_final( &pkcInfo->bnCTX );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t\tif( !pkcInfo->isECC )\n#endif /* USE_ECDH || USE_ECDSA */\n\t\t\t{\n\t\t\tBN_MONT_CTX_free( &pkcInfo->montCTX1 );\n\t\t\tBN_MONT_CTX_free( &pkcInfo->montCTX2 );\n\t\t\tBN_MONT_CTX_free( &pkcInfo->montCTX3 );\n\t\t\t}\n\t\t}\n\tif( pkcInfo->publicKeyInfo != NULL )\n\t\tclFree( \"freeContextBignums\", pkcInfo->publicKeyInfo );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBignum Checksum Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Checksum a bignum's metadata and its data payload.  We can't use the \n   standard checksumData() here both because we need to keep a running total \n   of the existing checksum value and because we don't want to truncate the \n   checksum value to 16 bits at the end of each calculation because it's fed \n   to the next round of checksumming */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checksumBignumData( IN_BUFFER( length ) const void *data, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t   IN const int initialSum )\n\t{\n\tconst unsigned char *dataPtr = data;\n\tint sum1 = 0, sum2 = initialSum, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, length ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( length ), 0 );\n\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\t{\n\t\tsum1 += dataPtr[ i ];\n\t\tsum2 += sum1;\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, 0 );\n\treturn( sum2 );\n\t}\n\n#define BN_checksum( bignum, checksum ) \\\n\t*( checksum ) = checksumBignumData( bignum, sizeof( BIGNUM ), *( checksum ) )\n#define BN_checksum_montgomery( montCTX, checksum ) \\\n\t*( checksum ) = checksumBignumData( montCTX, sizeof( BN_MONT_CTX ), *( checksum ) )\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* Checksum the ECC structure metadata and their data payloads */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void BN_checksum_ec_group( IN const EC_GROUP *group, \n\t\t\t\t\t\t\t\t  INOUT int *checksum )\n\t{\n\tint value = *checksum;\n\n\tassert( isReadPtr( group, sizeof( EC_GROUP ) ) );\n\tassert( isWritePtr( checksum, sizeof( int ) ) );\n\n\t/* Checksum the EC_GROUP metadata */\n\tvalue = checksumBignumData( group, sizeof( EC_GROUP ), value );\n\n\t/* EC_GROUPs have an incredibly complex inner stucture (see \n\t   bn/ec_lcl.h), the following checksums the common data without getting \n\t   into the lists of method-specific data values */\n\tBN_checksum( &group->order, &value );\n\tBN_checksum( &group->cofactor, &value );\n\tBN_checksum( &group->field, &value );\n\tBN_checksum( &group->a, &value );\n\tBN_checksum( &group->b, &value );\n\t\n\t*checksum = value;\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void BN_checksum_ec_point( IN const EC_POINT *point, \n\t\t\t\t\t\t\t\t  INOUT int *checksum )\n\t{\n\tint value = *checksum;\n\n\tassert( isReadPtr( point, sizeof( EC_POINT ) ) );\n\tassert( isWritePtr( checksum, sizeof( int ) ) );\n\n\t/* Checksum the EC_POINT metadata */\n\tvalue = checksumBignumData( point, sizeof( EC_POINT ), value );\n\n\t/* Checksum the EC_POINT data */\n\tBN_checksum( &point->X, &value );\n\tBN_checksum( &point->Y, &value );\n\tBN_checksum( &point->Z, &value );\n\n\t*checksum = value;\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/* Calculate a bignum checksum */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int bignumChecksum( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t   const BOOLEAN isPrivateKey,\n\t\t\t\t\t\t   OUT int *checksum )\n\t{\n\tint value = 0;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( checksum, sizeof( int ) ) );\n\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\t/* Clear return value */\n\t*checksum = 0;\n\n\t/* Calculate the key data checksum */\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tBN_checksum( &pkcInfo->eccParam_qx, &value );\n\t\tBN_checksum( &pkcInfo->eccParam_qy, &value );\n\t\tif( isPrivateKey )\n\t\t\tBN_checksum( &pkcInfo->eccParam_d, &value );\n\t\tBN_checksum_ec_group( pkcInfo->ecCTX, &value );\n\t\tBN_checksum_ec_point( pkcInfo->ecPoint, &value );\n\t\t}\n\telse\n#endif /* USE_ECDH || USE_ECDSA */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\tBN_checksum( &pkcInfo->dlpParam_p, &value );\n\t\tBN_checksum( &pkcInfo->dlpParam_g, &value );\n\t\tBN_checksum( &pkcInfo->dlpParam_q, &value );\n\t\tBN_checksum( &pkcInfo->dlpParam_y, &value );\n\t\tif( cryptAlgo == CRYPT_ALGO_DH )\n\t\t\tBN_checksum( &pkcInfo->dhParam_yPrime, &value );\n\t\tif( isPrivateKey )\n\t\t\tBN_checksum( &pkcInfo->dlpParam_x, &value );\n\t\tBN_checksum_montgomery( &pkcInfo->dlpParam_mont_p, &value );\n\t\t}\n\telse\n\t\t{\n\t\t/* Note that we don't checksum the (optional) blinding values \n\t\t   rsaParam_blind_k and rsaParam_blind_kInv, since these are updated\n\t\t   on every RSA operation so the checksum would change every time \n\t\t   they're used.  Since these are random values, a fault will only\n\t\t   make them even more random */\n\t\tBN_checksum( &pkcInfo->rsaParam_n, &value );\n\t\tBN_checksum( &pkcInfo->rsaParam_e, &value );\n\t\tBN_checksum_montgomery( &pkcInfo->rsaParam_mont_n, &value );\n\t\tif( isPrivateKey )\n\t\t\t{\n\t\t\tBN_checksum( &pkcInfo->rsaParam_d, &value );\n\t\t\tBN_checksum( &pkcInfo->rsaParam_p, &value );\n\t\t\tBN_checksum( &pkcInfo->rsaParam_q, &value );\n\t\t\tBN_checksum( &pkcInfo->rsaParam_u, &value );\n\t\t\tBN_checksum( &pkcInfo->rsaParam_exponent1, &value );\n\t\t\tBN_checksum( &pkcInfo->rsaParam_exponent2, &value );\n\t\t\tBN_checksum_montgomery( &pkcInfo->rsaParam_mont_p, &value );\n\t\t\tBN_checksum_montgomery( &pkcInfo->rsaParam_mont_q, &value );\n\t\t\t}\n\t\t}\n\t*checksum = value;\n\n\treturn( CRYPT_OK ); \n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checksumContextData( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t const BOOLEAN isPrivateKey )\n\t{\n\tint checksum, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\t/* Set or update the data checksum */\n\tstatus = bignumChecksum( pkcInfo, cryptAlgo, isPrivateKey, &checksum );\n\tENSURES( cryptStatusOK( status ) );\n\tif( pkcInfo->checksum == 0L )\n\t\tpkcInfo->checksum = checksum;\n\telse\n\t\t{\n\t\tif( pkcInfo->checksum != checksum )\n\t\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Check static domain parameters if required */\n\tif( pkcInfo->domainParams != NULL )\n\t\t{\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t\tif( !checksumDomainParameters( pkcInfo->domainParams, pkcInfo->isECC ) )\n\t\t\treturn( CRYPT_ERROR );\n#else\n\t\tif( !checksumDomainParameters( pkcInfo->domainParams, FALSE ) )\n\t\t\treturn( CRYPT_ERROR );\n#endif /* USE_ECDH || USE_ECDSA */\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Checksum a static bignum, which is one where the bignum image is stored\n   in read-only memory.  This is used for things like DLP and ECDLP domain\n   parameters, for which there's no need to parse and process them into \n   dynamically-allocated RAM space.\n\n   We can't use the standard Fletcher checksum for this because it performs\n   poorly on data with long strings of repeated bits, particularly all-zero\n   and all-one words, which occur in both the DLP and ECDLP domain \n   parameters.  What we need is a function with good avalanche, of which\n   MurmurHash seems to be the best tradeoff between effectiveness in\n   defeating bit flips and the like and speed.\n\n   The principal alternative is CityHash (and its follow-on FarmHash), but \n   that's incredibly complex (FarmHash is 12K LOC, do have a cow), and in \n   any case CityHash only exists as 64- and 128-bit variants, there's no \n   32-bit version of the hash.\n\n   The following code is based on the MurmurHash3 implementation by Austin \n   Appleby, who placed it in the public domain.  It's built around a core\n   that takes the input word and pre-mixes it using multiplies by two \n   constants and a rotate (thus the Murmur name, multiply-and-rotate), xors \n   the result into the hash value, and them mixes the hash using a rotate \n   and multiply-accumulate:\n\n\tk *= c1;\n\tk = rotl( k, r1 );\n\tk *= c2;\n\n\th ^= k;\n\n\th = rotl( h, r1 );\n\th = h * m1 + n1; */\n\n#ifdef _MSC_VER\n  #define ROTL32( x, r )\t_rotl( x, r )\n  #define ROTL64( x, r )\t_rotl64( x, r )\n#else\n  /* Most compilers have rotate-recognisers, this is the form that will \n     produce a native rotate instruction */\n  #define ROTL32( x, r )\t( ( ( x ) << ( r ) ) | ( ( x ) >> ( 32 - ( r ) ) ) )\n  #define ROTL64( x, r )\t( ( ( x ) << ( r ) ) | ( ( x ) >> ( 64 - ( r ) ) ) )\n#endif /* _MSC_VER */\n\n#if BN_BITS2 == 64\n\n#define CONST_1\t\t0x87C37B91114253D5ULL\n#define CONST_2\t\t0x4CF5AD432745937FULL\n\nstatic BN_ULONG fmix64( BN_ULONG k )\n\t{\n\t/* The constants were generated by Austin Appleby using a simulated-\n\t   annealing algorithm, and will avalanche all bits of 'h' to within \n\t   a 0.25% bias */ \n\tk ^= k >> 33;\n\tk *= 0xFF51AFD7ED558CCDULL;\n\tk ^= k >> 33;\n\tk *= 0xC4CEB9FE1A85EC53ULL;\n\tk ^= k >> 33;\n\n\treturn( k );\n\t}\n\nstatic BN_ULONG MurmurHash3( const BN_ULONG *data, const int len, BN_ULONG seed )\n\t{\n\tBN_ULONG h1 = seed, h2 = seed;\n\tconst int nblocks = ( len + 1 ) / 2;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( data, len * sizeof( BN_ULONG ) ) );\n\n\tENSURES_B( len > 0 && len <= BIGNUM_ALLOC_WORDS_EXT2 );\n\n\t/* Process each input word, two words at a time */\n\tLOOP_EXT( i = 0, i < nblocks, i += 2, BIGNUM_ALLOC_WORDS_EXT2 )\n\t\t{\n\t\tBN_ULONG k1 = data[ i ];\n\t\tBN_ULONG k2 = data[ i + 1 ];\n\n\t\tk1 *= CONST_1; \n\t\tk1 = ROTL64( k1, 31 ); \n\t\tk1 *= CONST_2; \n\t\th1 ^= k1;\n\n\t\th1 = ROTL64( h1, 27 ); \n\t\th1 += h2; \n\t\th1 = ( h1 * 5 ) + 0x52DCE729;\n\n\t\tk2 *= CONST_2; \n\t\tk2 = ROTL64( k2, 33 ); \n\t\tk2 *= CONST_1; \n\t\th2 ^= k2;\n\n\t\th2 = ROTL64( h2, 31 ); \n\t\th2 += h1; \n\t\th2 = ( h2 * 5 ) + 0x38495AB5;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Finalisation and avalanche */\n\th1 ^= len; \n\th2 ^= len;\n\th1 += h2;\n\th2 += h1;\n\th1 = fmix64( h1 );\n\th2 = fmix64( h2 );\n\th1 += h2;\n/*\th2 += h1; Not used for 64-bit result */\n\n\treturn( h1 );\n\t}\n#else\n\n#define CONST_1\t\t0xCC9E2D51UL\n#define CONST_2\t\t0x1B873593UL\n\nstatic BN_ULONG MurmurHash3( const BN_ULONG *data, const int len, BN_ULONG seed )\n\t{\n\tBN_ULONG h1 = seed;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( data, len * sizeof( BN_ULONG ) ) );\n\n\tENSURES_B( len > 0 && len <= BIGNUM_ALLOC_WORDS_EXT2 );\n\n\t/* Process each input word */\n\tLOOP_EXT( i = 0, i < len, i++, BIGNUM_ALLOC_WORDS_EXT2 )\n\t\t{\n\t\tBN_ULONG k1 = data[ i ];\n\n\t\tk1 *= CONST_1;\n\t\tk1 = ROTL32( k1, 15 );\n\t\tk1 *= CONST_2;\n    \n\t\th1 ^= k1;\n\t\th1 = ROTL32( h1,13 ); \n\t\th1 = ( h1 * 5 ) + 0xE6546B64UL;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Finalisation and avalanche using the fmix32() version of the 64-bit \n\t   fmix64(), see the comment on that for how it works */\n\th1 ^= len;\n\th1 ^= h1 >> 16;\n\th1 *= 0x85EBCA6BUL;\n\th1 ^= h1 >> 13;\n\th1 *= 0xC2B2AE35UL;\n\th1 ^= h1 >> 16;\n\n\treturn( h1 );\n\t} \n#endif /* 64- vs 32-bit */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checksumStaticBignum( const BIGNUM *bignum,\n\t\t\t\t\t\t\t\t\t const BN_ULONG checksum )\n\t{\n\tBN_ULONG hash;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\t/* Make sure that the metadata fields are valid.  These have fixed \n\t   values so we just check that they contain the values that they're\n\t   supposed to */\n\tif( bignum->neg != FALSE || \\\n\t\tbignum->flags != BN_FLG_STATIC_DATA )\n\t\treturn( FALSE );\n\tif( bignum->top <= 0 || bignum->top > BIGNUM_ALLOC_WORDS )\n\t\treturn( FALSE );\n\n\t/* Check that the data matches the checksum */\n\thash = MurmurHash3( bignum->d, bignum->top, 0 );\n\tif( hash != checksum )\n\t\treturn( FALSE );\n\n\t/* Finally, make sure that the rest of the bignum data is all zeroes */\n\tLOOP_EXT( i = bignum->top, i < BIGNUM_ALLOC_WORDS, i++,\n\t\t\t  BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tif( bignum->d[ i ] != 0 )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Print a bignum checksum, used when hardcoding constant values like DLP \n   and ECDLP domain parameters from their bignum representations */\n\n#if defined( DEBUG_DIAGNOSTIC_ENABLE ) && !defined( NDEBUG )\n\nvoid printBignumChecksum( const BIGNUM *bignum )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n#if BN_BITS2 == 64\n\tDEBUG_PRINT(( \"0x%016llXULL, \", \n\t\t\t\t  MurmurHash3( bignum->d, bignum->top, 0 ) ));\n#else\n\tDEBUG_PRINT(( \"0x%08X, \", \n\t\t\t\t  MurmurHash3( bignum->d, bignum->top, 0 ) ));\n#endif /* 64- vs 32-bit */\n\t}\n#endif /* DEBUG_DIAGNOSTIC_ENABLE && Debug */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checksumECCParameters( const ECC_DOMAINPARAMS *domainParams )\n\t{\n\tassert( isReadPtr( domainParams, sizeof( DH_DOMAINPARAMS ) ) );\n\n\tif( !checksumStaticBignum( &domainParams->p, domainParams->p_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->a, domainParams->a_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->b, domainParams->b_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->gx, domainParams->gx_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->gy, domainParams->gy_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->n, domainParams->n_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->h, domainParams->h_checksum ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checksumDHParameters( const DH_DOMAINPARAMS *domainParams )\n\t{\n\tassert( isReadPtr( domainParams, sizeof( DH_DOMAINPARAMS ) ) );\n\n\tif( !checksumStaticBignum( &domainParams->p, domainParams->p_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->q, domainParams->q_checksum ) || \\\n\t\t!checksumStaticBignum( &domainParams->g, domainParams->g_checksum ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checksumDomainParameters( const void *domainParams, \n\t\t\t\t\t\t\t\t  const BOOLEAN isECC )\n\t{\n\tREQUIRES( isECC == TRUE || isECC == FALSE );\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\treturn( isECC ? checksumECCParameters( domainParams ) : \\\n\t\t\t\t\tchecksumDHParameters( domainParams ) );\n#else\n\treturn( checksumDHParameters( domainParams ) );\n#endif /* USE_ECDH || USE_ECDSA */\n\t}\n#else\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tNon-Bignum Stubs \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid clearTempBignums( INOUT PKC_INFO *pkcInfo )\n\t{\n\t}\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initContextBignums( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\tconst BOOLEAN isECC )\n\t{\n\t}\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid freeContextBignums( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t IN_FLAGS( CONTEXT ) const int contextFlags )\n\t{\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bnprime.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib SSHv2/SSL/TLS DH Public Parameters\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* Define the following to convert from the fixed-format DH and ECC domain\n   parameters to pre-encoded the bignum format.  This will also require\n   changing loadDHparams() to load each of 1536, 2048 and 3072 bit keys,\n   and changing loadECCparams() to load each of CRYPT_ECCCURVE_P256, \n   CRYPT_ECCCURVE_BRAINPOOL_P256, CRYPT_ECCCURVE_P384, \n   CRYPT_ECCCURVE_BRAINPOOL_P384, CRYPT_ECCCURVE_P521 and \n   CRYPT_ECCCURVE_BRAINPOOL_P512 */\n\n/* #define CREATE_BIGNUM_VALUES */\n\n#if defined( USE_SSH ) || defined( USE_SSL )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDH Domain Parameters\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Predefined DH values from RFC 2409 and RFC 3526.  These have been \n   independently verified by Henrick Hellstrm <henrick@streamsec.se> to \n   check that:\n\n\ta: The numbers match the numbers in the RFCs.\n\tb: The numbers are safe primes (using both Miller-Rabin tests and Lucas \n\t   tests on q = (p-1)/2, and then the Pocklington Criterion on p).\n\tc: The small constant k is indeed the least positive integer such that \n\t   the number is a safe prime.\n\n   Safely converting these to pre-encoded bignum values is a multi-stage\n   process, first we encode the original values as SSL-format values, which\n   is the closest format to the original spec and one for which we can\n   use SHA-1 hashes to verify the primes.\n   \n   Then we read them into a bignum and print the result.  This finally \n   allows us to use the values as pre-generated bignums.  To enable the\n   code for this process, define the following value */\n\n#ifdef CREATE_BIGNUM_VALUES\n\n#ifdef USE_DH1024\n\n/* 1024-bit DH parameters from RFC 2409 */\n\nstatic const BYTE dh1024SSL[] = {\n\t0x00, 0x80,\t\t/* p */\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n\t\t0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,\n\t\t0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n\t\t0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,\n\t\t0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n\t\t0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,\n\t\t0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n\t\t0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,\n\t\t0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n\t\t0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,\n\t\t0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n\t\t0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,\n\t\t0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n\t\t0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x01,\t\t/* g */\n\t\t0x02\n\t};\n#endif /* USE_DH1024 */\n\n/* 1536-, 2048- and 3072-bit parameters from RFC 3526.  There is also a \n   4096-bit value given in the RFC, but using that, and the even larger\n   values of 6144 and 8192 bits, is just silly.  See also the comment on \n   defences against clients that request stupid key sizes in processDHE() \n   in ssh2_svr.c */\n\nstatic const BYTE dh1536SSL[] = {\n\t0x00, 0xC0,\t\t/* p */\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n\t\t0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,\n\t\t0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n\t\t0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,\n\t\t0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n\t\t0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,\n\t\t0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n\t\t0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,\n\t\t0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n\t\t0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,\n\t\t0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n\t\t0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,\n\t\t0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n\t\t0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,\n\t\t0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,\n\t\t0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,\n\t\t0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,\n\t\t0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,\n\t\t0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,\n\t\t0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,\n\t\t0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,\n\t\t0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x01,\t\t/* g */\n\t\t0x02\n\t};\n\nstatic const BYTE dh2048SSL[] = {\n\t0x01, 0x00,\t\t/* p */\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n\t\t0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,\n\t\t0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n\t\t0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,\n\t\t0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n\t\t0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,\n\t\t0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n\t\t0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,\n\t\t0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n\t\t0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,\n\t\t0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n\t\t0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,\n\t\t0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n\t\t0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,\n\t\t0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,\n\t\t0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,\n\t\t0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,\n\t\t0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,\n\t\t0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,\n\t\t0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,\n\t\t0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,\n\t\t0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,\n\t\t0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,\n\t\t0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,\n\t\t0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,\n\t\t0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,\n\t\t0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,\n\t\t0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,\n\t\t0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,\n\t\t0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x01,\t\t/* g */\n\t\t0x02\n\t};\n\nstatic const BYTE dh3072SSL[] = {\n\t0x01, 0x80,\t\t/* p */\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n\t\t0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,\n\t\t0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n\t\t0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,\n\t\t0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n\t\t0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,\n\t\t0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n\t\t0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,\n\t\t0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n\t\t0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,\n\t\t0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n\t\t0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,\n\t\t0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n\t\t0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,\n\t\t0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,\n\t\t0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,\n\t\t0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,\n\t\t0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,\n\t\t0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,\n\t\t0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,\n\t\t0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,\n\t\t0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,\n\t\t0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,\n\t\t0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,\n\t\t0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,\n\t\t0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,\n\t\t0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,\n\t\t0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,\n\t\t0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,\n\t\t0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,\n\t\t0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,\n\t\t0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,\n\t\t0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,\n\t\t0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,\n\t\t0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,\n\t\t0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,\n\t\t0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,\n\t\t0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,\n\t\t0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,\n\t\t0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,\n\t\t0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,\n\t\t0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,\n\t\t0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,\n\t\t0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,\n\t\t0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,\n\t\t0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,\n\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t0x00, 0x01,\t\t/* g */\n\t\t0x02\n\t};\n\n/* Checksum values for the DH data */\n\n#ifdef USE_DH1024\nstatic int dh1024checksum;\n#endif /* USE_DH1024 */\n\nstatic int dh1536checksum, dh2048checksum, dh3072checksum;\n\n/* Check that the stored DH key data is valid */\n\nCHECK_RETVAL \\\nstatic int checkDHdata( void )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hashValue[ 20 + 8 ];\n\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\n\t/* Generate/check the SHA-1 values for the primes.  This doesn't cover \n\t   all of the data, but is needed to bootstrap the full check because \n\t   only the hashes of the primes have been published */\n#if 0\n\thashFunctionAtomic( hashValue, 20, dh1024SSL + 2, sizeof( dh1024SSL ) - 5 );\n\thashFunctionAtomic( hashValue, 20, dh1536SSL + 2, sizeof( dh1536SSL ) - 5 );\n\thashFunctionAtomic( hashValue, 20, dh2048SSL + 2, sizeof( dh2048SSL ) - 5 );\n\thashFunctionAtomic( hashValue, 20, dh3072SSL + 2, sizeof( dh3072SSL ) - 5 );\n#endif /* 0 */\n\n\t/* Check the SHA-1 values for the DH data */\n#ifndef CONFIG_FUZZ\n  #ifdef USE_DH1024\n\thashFunctionAtomic( hashValue, 20, dh1024SSL, sizeof( dh1024SSL ) );\n\tif( memcmp( hashValue, \\\n\t\t\t\t\"\\x46\\xF4\\x47\\xC3\\x69\\x00\\x6F\\x22\\x91\\x0E\\x24\\xF5\\x73\\x68\\xE6\\xF7\", 16 ) )\n\t\tretIntError();\n  #endif /* USE_DH1024 */\n\thashFunctionAtomic( hashValue, 20, dh1536SSL, sizeof( dh1536SSL ) );\n\tif( memcmp( hashValue, \\\n\t\t\t\t\"\\xA3\\xEC\\x2F\\x85\\xC7\\xD3\\x74\\xD2\\x56\\x53\\x22\\xED\\x53\\x87\\x6F\\xDC\", 16 ) )\n\t\tretIntError();\n\thashFunctionAtomic( hashValue, 20, dh2048SSL, sizeof( dh2048SSL ) );\n\tif( memcmp( hashValue, \\\n\t\t\t\t\"\\x0E\\x8E\\x49\\x9F\\xD9\\x18\\x02\\xCB\\x5D\\x42\\x03\\xA5\\xE1\\x67\\x51\\xDB\", 16 ) )\n\t\tretIntError();\n\thashFunctionAtomic( hashValue, 20, dh3072SSL, sizeof( dh3072SSL ) );\n\tif( memcmp( hashValue, \\\n\t\t\t\t\"\\x8F\\x4A\\x19\\xEF\\x85\\x1D\\x91\\xEA\\x18\\xE8\\xB8\\xB9\\x9F\\xF0\\xFD\\xF8\", 16 ) )\n\t\tretIntError();\n#endif /* !CONFIG_FUZZ */\n\n\t/* Now that we've verified that the DH data is valid, calculate a \n\t   checksum for each value to allow it to be quickly checked before it's\n\t   loaded into a context */\n#ifdef USE_DH1024\n\tdh1024checksum = checksumData( dh1024SSL, sizeof( dh1024SSL ) );\n#endif /* USE_DH1024 */\n\tdh1536checksum = checksumData( dh1536SSL, sizeof( dh1536SSL ) );\n\tdh2048checksum = checksumData( dh2048SSL, sizeof( dh2048SSL ) );\n\tdh3072checksum = checksumData( dh3072SSL, sizeof( dh3072SSL ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nstatic int loadDHparamsFixed( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int keySize )\n\t{\n\tMESSAGE_DATA msgData;\n\tconst void *keyData;\n\tint keyDataLength, keyDataChecksum;\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( keySize >= MIN_PKCSIZE && keySize <= CRYPT_MAX_PKCSIZE );\n\n\tswitch( keySize )\n\t\t{\n#ifdef USE_DH1024\n\t\tcase bitsToBytes( 1024 ):\n\t\t\tkeyData = dh1024SSL;\n\t\t\tkeyDataLength = sizeof( dh1024SSL );\n\t\t\tkeyDataChecksum = dh1024checksum;\n\t\t\tbreak;\n#endif /* USE_DH1024 */\n\n\t\tcase bitsToBytes( 1536 ):\n\t\t\tkeyData = dh1536SSL;\n\t\t\tkeyDataLength = sizeof( dh1536SSL );\n\t\t\tkeyDataChecksum = dh1536checksum;\n\t\t\tbreak;\n\n\t\tcase bitsToBytes( 2048 ):\n\t\t\tkeyData = dh2048SSL;\n\t\t\tkeyDataLength = sizeof( dh2048SSL );\n\t\t\tkeyDataChecksum = dh2048checksum;\n\t\t\tbreak;\n\n\t\tcase bitsToBytes( 3072 ):\n\t\tdefault:\t\t\t/* Hier ist der mast zu ende */\n\t\t\tkeyData = dh3072SSL;\n\t\t\tkeyDataLength = sizeof( dh3072SSL );\n\t\t\tkeyDataChecksum = dh3072checksum;\n\t\t\tbreak;\n\t\t}\n\n\t/* Make sure that the key data hasn't been corrupted */\n\tif( keyDataChecksum != checksumData( keyData, keyDataLength ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Fixed DH value for %d-bit key has been corrupted\",\n\t\t\t\t\t bytesToBits( keySize ) ));\n\t\tretIntError();\n\t\t}\n\n\t/* Load the fixed DH key into the context */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength );\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KEY_SSL ) );\n\t}\n#endif /* CREATE_BIGNUM_VALUES */\n\n/* DH values as pre-encoded bignums, allowing them to be used directly.  \n   Note that this includes the somewhat unsound 1024-bit values, we never \n   offer these ourselves but still provide built-in values to deal with \n   other implementations that use them */\n\n#if BN_BITS2 == 64\n\nstatic const DH_DOMAINPARAMS dh1024params = {\t/* See note above */\n\t/* p */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA,{\n\t0xFFFFFFFFFFFFFFFFULL, 0x49286651ECE65381ULL,\n\t0xAE9F24117C4B1FE6ULL, 0xEE386BFB5A899FA5ULL,\n\t0x0BFF5CB6F406B7EDULL, 0xF44C42E9A637ED6BULL,\n\t0xE485B576625E7EC6ULL, 0x4FE1356D6D51C245ULL,\n\t0x302B0A6DF25F1437ULL, 0xEF9519B3CD3A431BULL,\n\t0x514A08798E3404DDULL, 0x020BBEA63B139B22ULL,\n\t0x29024E088A67CC74ULL, 0xC4C6628B80DC1CD1ULL,\n\t0xC90FDAA22168C234ULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* q */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA,{\n\t0xFFFFFFFFFFFFFFFFULL, 0x24943328F67329C0ULL,\n\t0xD74F9208BE258FF3ULL, 0xF71C35FDAD44CFD2ULL,\n\t0x85FFAE5B7A035BF6ULL, 0x7A262174D31BF6B5ULL,\n\t0xF242DABB312F3F63ULL, 0xA7F09AB6B6A8E122ULL,\n\t0x98158536F92F8A1BULL, 0xF7CA8CD9E69D218DULL,\n\t0x28A5043CC71A026EULL, 0x0105DF531D89CD91ULL,\n\t0x948127044533E63AULL, 0x62633145C06E0E68ULL,\n\t0xE487ED5110B4611AULL, 0x7FFFFFFFFFFFFFFFULL } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA,{\n\t0x0000000000000002ULL } },\n\t/* Checksums */\n\t0x3E2F059DBCCFD195ULL, 0x5503C71D5F777AE8ULL, 0x28C47BE7F867ED54ULL\n\t};\n\nstatic const DH_DOMAINPARAMS dh1536params = {\n\t/* p */\n\t{ 24, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0xF1746C08CA237327ULL,\n\t0x670C354E4ABC9804ULL, 0x9ED529077096966DULL,\n\t0x1C62F356208552BBULL, 0x83655D23DCA3AD96ULL,\n\t0x69163FA8FD24CF5FULL, 0x98DA48361C55D39AULL,\n\t0xC2007CB8A163BF05ULL, 0x49286651ECE45B3DULL,\n\t0xAE9F24117C4B1FE6ULL, 0xEE386BFB5A899FA5ULL,\n\t0x0BFF5CB6F406B7EDULL, 0xF44C42E9A637ED6BULL,\n\t0xE485B576625E7EC6ULL, 0x4FE1356D6D51C245ULL,\n\t0x302B0A6DF25F1437ULL, 0xEF9519B3CD3A431BULL,\n\t0x514A08798E3404DDULL, 0x020BBEA63B139B22ULL,\n\t0x29024E088A67CC74ULL, 0xC4C6628B80DC1CD1ULL,\n\t0xC90FDAA22168C234ULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* q */\n\t{ 24, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0x78BA36046511B993ULL,\n\t0xB3861AA7255E4C02ULL, 0xCF6A9483B84B4B36ULL,\n\t0x0E3179AB1042A95DULL, 0xC1B2AE91EE51D6CBULL,\n\t0x348B1FD47E9267AFULL, 0xCC6D241B0E2AE9CDULL,\n\t0xE1003E5C50B1DF82ULL, 0x24943328F6722D9EULL,\n\t0xD74F9208BE258FF3ULL, 0xF71C35FDAD44CFD2ULL,\n\t0x85FFAE5B7A035BF6ULL, 0x7A262174D31BF6B5ULL,\n\t0xF242DABB312F3F63ULL, 0xA7F09AB6B6A8E122ULL,\n\t0x98158536F92F8A1BULL, 0xF7CA8CD9E69D218DULL,\n\t0x28A5043CC71A026EULL, 0x0105DF531D89CD91ULL,\n\t0x948127044533E63AULL, 0x62633145C06E0E68ULL,\n\t0xE487ED5110B4611AULL, 0x7FFFFFFFFFFFFFFFULL } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000002ULL } },\n\t/* Checksums */\n\t0x9472AA5034F03DC6ULL, 0x7E4E90EF890616AFULL, 0x28C47BE7F867ED54ULL\n\t};\n\nstatic const DH_DOMAINPARAMS dh2048params = {\n\t/* p */\n\t{ 32, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0x15728E5A8AACAA68ULL,\n\t0x15D2261898FA0510ULL, 0x3995497CEA956AE5ULL,\n\t0xDE2BCBF695581718ULL, 0xB5C55DF06F4C52C9ULL,\n\t0x9B2783A2EC07A28FULL, 0xE39E772C180E8603ULL,\n\t0x32905E462E36CE3BULL, 0xF1746C08CA18217CULL,\n\t0x670C354E4ABC9804ULL, 0x9ED529077096966DULL,\n\t0x1C62F356208552BBULL, 0x83655D23DCA3AD96ULL,\n\t0x69163FA8FD24CF5FULL, 0x98DA48361C55D39AULL,\n\t0xC2007CB8A163BF05ULL, 0x49286651ECE45B3DULL,\n\t0xAE9F24117C4B1FE6ULL, 0xEE386BFB5A899FA5ULL,\n\t0x0BFF5CB6F406B7EDULL, 0xF44C42E9A637ED6BULL,\n\t0xE485B576625E7EC6ULL, 0x4FE1356D6D51C245ULL,\n\t0x302B0A6DF25F1437ULL, 0xEF9519B3CD3A431BULL,\n\t0x514A08798E3404DDULL, 0x020BBEA63B139B22ULL,\n\t0x29024E088A67CC74ULL, 0xC4C6628B80DC1CD1ULL,\n\t0xC90FDAA22168C234ULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* q */\n\t{ 32, FALSE, BN_FLG_STATIC_DATA, {\n\t0x7FFFFFFFFFFFFFFFULL, 0x0AB9472D45565534ULL,\n\t0x8AE9130C4C7D0288ULL, 0x1CCAA4BE754AB572ULL,\n\t0xEF15E5FB4AAC0B8CULL, 0xDAE2AEF837A62964ULL,\n\t0xCD93C1D17603D147ULL, 0xF1CF3B960C074301ULL,\n\t0x19482F23171B671DULL, 0x78BA3604650C10BEULL,\n\t0xB3861AA7255E4C02ULL, 0xCF6A9483B84B4B36ULL,\n\t0x0E3179AB1042A95DULL, 0xC1B2AE91EE51D6CBULL,\n\t0x348B1FD47E9267AFULL, 0xCC6D241B0E2AE9CDULL,\n\t0xE1003E5C50B1DF82ULL, 0x24943328F6722D9EULL,\n\t0xD74F9208BE258FF3ULL, 0xF71C35FDAD44CFD2ULL,\n\t0x85FFAE5B7A035BF6ULL, 0x7A262174D31BF6B5ULL,\n\t0xF242DABB312F3F63ULL, 0xA7F09AB6B6A8E122ULL,\n\t0x98158536F92F8A1BULL, 0xF7CA8CD9E69D218DULL,\n\t0x28A5043CC71A026EULL, 0x0105DF531D89CD91ULL,\n\t0x948127044533E63AULL, 0x62633145C06E0E68ULL,\n\t0xE487ED5110B4611AULL, 0x7FFFFFFFFFFFFFFFULL } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000002ULL } },\n\t/* Checksums */\n\t0x405BD3182D6B262CULL, 0x22EEE58D97A843AFULL, 0x28C47BE7F867ED54ULL\n\t};\n\n#if CRYPT_MAX_PKCSIZE >= bitsToBytes( 3072 )\n\nstatic const DH_DOMAINPARAMS dh3072params = {\n\t/* p */\n\t{ 48, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0x4B82D120A93AD2CAULL,\n\t0x43DB5BFCE0FD108EULL, 0x08E24FA074E5AB31ULL,\n\t0x770988C0BAD946E2ULL, 0xBBE117577A615D6CULL,\n\t0x521F2B18177B200CULL, 0xD87602733EC86A64ULL,\n\t0xF12FFA06D98A0864ULL, 0xCEE3D2261AD2EE6BULL,\n\t0x1E8C94E04A25619DULL, 0xABF5AE8CDB0933D7ULL,\n\t0xB3970F85A6E1E4C7ULL, 0x8AEA71575D060C7DULL,\n\t0xECFB850458DBEF0AULL, 0xA85521ABDF1CBA64ULL,\n\t0xAD33170D04507A33ULL, 0x15728E5A8AAAC42DULL,\n\t0x15D2261898FA0510ULL, 0x3995497CEA956AE5ULL,\n\t0xDE2BCBF695581718ULL, 0xB5C55DF06F4C52C9ULL,\n\t0x9B2783A2EC07A28FULL, 0xE39E772C180E8603ULL,\n\t0x32905E462E36CE3BULL, 0xF1746C08CA18217CULL,\n\t0x670C354E4ABC9804ULL, 0x9ED529077096966DULL,\n\t0x1C62F356208552BBULL, 0x83655D23DCA3AD96ULL,\n\t0x69163FA8FD24CF5FULL, 0x98DA48361C55D39AULL,\n\t0xC2007CB8A163BF05ULL, 0x49286651ECE45B3DULL,\n\t0xAE9F24117C4B1FE6ULL, 0xEE386BFB5A899FA5ULL,\n\t0x0BFF5CB6F406B7EDULL, 0xF44C42E9A637ED6BULL,\n\t0xE485B576625E7EC6ULL, 0x4FE1356D6D51C245ULL,\n\t0x302B0A6DF25F1437ULL, 0xEF9519B3CD3A431BULL,\n\t0x514A08798E3404DDULL, 0x020BBEA63B139B22ULL,\n\t0x29024E088A67CC74ULL, 0xC4C6628B80DC1CD1ULL,\n\t0xC90FDAA22168C234ULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* q */\n\t{ 48, FALSE, BN_FLG_STATIC_DATA, {\n\t0x7FFFFFFFFFFFFFFFULL, 0x25C16890549D6965ULL,\n\t0xA1EDADFE707E8847ULL, 0x047127D03A72D598ULL,\n\t0x3B84C4605D6CA371ULL, 0x5DF08BABBD30AEB6ULL,\n\t0x290F958C0BBD9006ULL, 0x6C3B01399F643532ULL,\n\t0xF897FD036CC50432ULL, 0xE771E9130D697735ULL,\n\t0x8F464A702512B0CEULL, 0xD5FAD7466D8499EBULL,\n\t0xD9CB87C2D370F263ULL, 0x457538ABAE83063EULL,\n\t0x767DC2822C6DF785ULL, 0xD42A90D5EF8E5D32ULL,\n\t0xD6998B8682283D19ULL, 0x0AB9472D45556216ULL,\n\t0x8AE9130C4C7D0288ULL, 0x1CCAA4BE754AB572ULL,\n\t0xEF15E5FB4AAC0B8CULL, 0xDAE2AEF837A62964ULL,\n\t0xCD93C1D17603D147ULL, 0xF1CF3B960C074301ULL,\n\t0x19482F23171B671DULL, 0x78BA3604650C10BEULL,\n\t0xB3861AA7255E4C02ULL, 0xCF6A9483B84B4B36ULL,\n\t0x0E3179AB1042A95DULL, 0xC1B2AE91EE51D6CBULL,\n\t0x348B1FD47E9267AFULL, 0xCC6D241B0E2AE9CDULL,\n\t0xE1003E5C50B1DF82ULL, 0x24943328F6722D9EULL,\n\t0xD74F9208BE258FF3ULL, 0xF71C35FDAD44CFD2ULL,\n\t0x85FFAE5B7A035BF6ULL, 0x7A262174D31BF6B5ULL,\n\t0xF242DABB312F3F63ULL, 0xA7F09AB6B6A8E122ULL,\n\t0x98158536F92F8A1BULL, 0xF7CA8CD9E69D218DULL,\n\t0x28A5043CC71A026EULL, 0x0105DF531D89CD91ULL,\n\t0x948127044533E63AULL, 0x62633145C06E0E68ULL,\n\t0xE487ED5110B4611AULL, 0x7FFFFFFFFFFFFFFFULL } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000002ULL } },\n\t/* Checksums */\n\t0x576642F5C4CD8D96ULL, 0x22F5A1C20DEE267BULL, 0x28C47BE7F867ED54ULL\n\t};\n#endif /* 3072-bit bignums */\n\n#else\n\nstatic const DH_DOMAINPARAMS dh1024params = {\t/* See note above */\n\t/* p */\n\t{ 32, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xECE65381, 0x49286651, \n\t0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB, \n\t0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9, \n\t0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D, \n\t0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3, \n\t0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6, \n\t0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B, \n\t0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* q */\n\t{ 32, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xF67329C0, 0x24943328, \n\t0xBE258FF3, 0xD74F9208, 0xAD44CFD2, 0xF71C35FD, \n\t0x7A035BF6, 0x85FFAE5B, 0xD31BF6B5, 0x7A262174, \n\t0x312F3F63, 0xF242DABB, 0xB6A8E122, 0xA7F09AB6, \n\t0xF92F8A1B, 0x98158536, 0xE69D218D, 0xF7CA8CD9, \n\t0xC71A026E, 0x28A5043C, 0x1D89CD91, 0x0105DF53, \n\t0x4533E63A, 0x94812704, 0xC06E0E68, 0x62633145, \n\t0x10B4611A, 0xE487ED51, 0xFFFFFFFF, 0x7FFFFFFF } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000002 } },\n\t/* Checksums */\n\t0x8CE0F339, 0xA165CE72, 0x847050E5\n\t};\n\nstatic const DH_DOMAINPARAMS dh1536params = { \n\t/* p */\n\t{ 48, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xCA237327, 0xF1746C08,\n\t0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907, \n\t0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23, \n\t0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,\n\t0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651, \n\t0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB, \n\t0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9,\n\t0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D, \n\t0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3, \n\t0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,\n\t0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B, \n\t0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* q */\n\t{ 48, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0x6511B993, 0x78BA3604, \n\t0x255E4C02, 0xB3861AA7, 0xB84B4B36, 0xCF6A9483, \n\t0x1042A95D, 0x0E3179AB, 0xEE51D6CB, 0xC1B2AE91, \n\t0x7E9267AF, 0x348B1FD4, 0x0E2AE9CD, 0xCC6D241B, \n\t0x50B1DF82, 0xE1003E5C, 0xF6722D9E, 0x24943328, \n\t0xBE258FF3, 0xD74F9208, 0xAD44CFD2, 0xF71C35FD, \n\t0x7A035BF6, 0x85FFAE5B, 0xD31BF6B5, 0x7A262174, \n\t0x312F3F63, 0xF242DABB, 0xB6A8E122, 0xA7F09AB6, \n\t0xF92F8A1B, 0x98158536, 0xE69D218D, 0xF7CA8CD9, \n\t0xC71A026E, 0x28A5043C, 0x1D89CD91, 0x0105DF53, \n\t0x4533E63A, 0x94812704, 0xC06E0E68, 0x62633145, \n\t0x10B4611A, 0xE487ED51, 0xFFFFFFFF, 0x7FFFFFFF } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000002 } },\n\t/* Checksums */\n\t0x7A168323, 0x6A1B6597, 0x847050E5\n\t};\n\nstatic const DH_DOMAINPARAMS dh2048params = { \n\t/* p */\n\t{ 64, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0x8AACAA68, 0x15728E5A,\n\t0x98FA0510, 0x15D22618, 0xEA956AE5, 0x3995497C,\n\t0x95581718, 0xDE2BCBF6, 0x6F4C52C9, 0xB5C55DF0,\n\t0xEC07A28F, 0x9B2783A2, 0x180E8603, 0xE39E772C,\n\t0x2E36CE3B, 0x32905E46, 0xCA18217C, 0xF1746C08,\n\t0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907,\n\t0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23,\n\t0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,\n\t0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651,\n\t0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB,\n\t0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9,\n\t0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D,\n\t0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3,\n\t0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,\n\t0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B,\n\t0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* q */\n\t{ 64, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0x7FFFFFFF, 0x45565534, 0x0AB9472D, \n\t0x4C7D0288, 0x8AE9130C, 0x754AB572, 0x1CCAA4BE, \n\t0x4AAC0B8C, 0xEF15E5FB, 0x37A62964, 0xDAE2AEF8, \n\t0x7603D147, 0xCD93C1D1, 0x0C074301, 0xF1CF3B96, \n\t0x171B671D, 0x19482F23, 0x650C10BE, 0x78BA3604, \n\t0x255E4C02, 0xB3861AA7, 0xB84B4B36, 0xCF6A9483, \n\t0x1042A95D, 0x0E3179AB, 0xEE51D6CB, 0xC1B2AE91, \n\t0x7E9267AF, 0x348B1FD4, 0x0E2AE9CD, 0xCC6D241B, \n\t0x50B1DF82, 0xE1003E5C, 0xF6722D9E, 0x24943328, \n\t0xBE258FF3, 0xD74F9208, 0xAD44CFD2, 0xF71C35FD, \n\t0x7A035BF6, 0x85FFAE5B, 0xD31BF6B5, 0x7A262174, \n\t0x312F3F63, 0xF242DABB, 0xB6A8E122, 0xA7F09AB6, \n\t0xF92F8A1B, 0x98158536, 0xE69D218D, 0xF7CA8CD9, \n\t0xC71A026E, 0x28A5043C, 0x1D89CD91, 0x0105DF53, \n\t0x4533E63A, 0x94812704, 0xC06E0E68, 0x62633145, \n\t0x10B4611A, 0xE487ED51, 0xFFFFFFFF, 0x7FFFFFFF } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000002 } },\n\t/* Checksums */\n\t0x82C18653, 0xF0162B14, 0x847050E5 \n\t};\n\n#if CRYPT_MAX_PKCSIZE >= bitsToBytes( 3072 )\n\nstatic const DH_DOMAINPARAMS dh3072params = { \n\t/* p */\n\t{ 96, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xA93AD2CA, 0x4B82D120,\n\t0xE0FD108E, 0x43DB5BFC, 0x74E5AB31, 0x08E24FA0,\n\t0xBAD946E2, 0x770988C0, 0x7A615D6C, 0xBBE11757,\n\t0x177B200C, 0x521F2B18, 0x3EC86A64, 0xD8760273,\n\t0xD98A0864, 0xF12FFA06, 0x1AD2EE6B, 0xCEE3D226,\n\t0x4A25619D, 0x1E8C94E0, 0xDB0933D7, 0xABF5AE8C,\n\t0xA6E1E4C7, 0xB3970F85, 0x5D060C7D, 0x8AEA7157,\n\t0x58DBEF0A, 0xECFB8504, 0xDF1CBA64, 0xA85521AB,\n\t0x04507A33, 0xAD33170D, 0x8AAAC42D, 0x15728E5A,\n\t0x98FA0510, 0x15D22618, 0xEA956AE5, 0x3995497C,\n\t0x95581718, 0xDE2BCBF6, 0x6F4C52C9, 0xB5C55DF0,\n\t0xEC07A28F, 0x9B2783A2, 0x180E8603, 0xE39E772C,\n\t0x2E36CE3B, 0x32905E46, 0xCA18217C, 0xF1746C08,\n\t0x4ABC9804, 0x670C354E, 0x7096966D, 0x9ED52907,\n\t0x208552BB, 0x1C62F356, 0xDCA3AD96, 0x83655D23,\n\t0xFD24CF5F, 0x69163FA8, 0x1C55D39A, 0x98DA4836,\n\t0xA163BF05, 0xC2007CB8, 0xECE45B3D, 0x49286651,\n\t0x7C4B1FE6, 0xAE9F2411, 0x5A899FA5, 0xEE386BFB,\n\t0xF406B7ED, 0x0BFF5CB6, 0xA637ED6B, 0xF44C42E9,\n\t0x625E7EC6, 0xE485B576, 0x6D51C245, 0x4FE1356D,\n\t0xF25F1437, 0x302B0A6D, 0xCD3A431B, 0xEF9519B3,\n\t0x8E3404DD, 0x514A0879, 0x3B139B22, 0x020BBEA6,\n\t0x8A67CC74, 0x29024E08, 0x80DC1CD1, 0xC4C6628B,\n\t0x2168C234, 0xC90FDAA2, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* q */\n\t{ 96, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0x7FFFFFFF, 0x549D6965, 0x25C16890, \n\t0x707E8847, 0xA1EDADFE, 0x3A72D598, 0x047127D0, \n\t0x5D6CA371, 0x3B84C460, 0xBD30AEB6, 0x5DF08BAB, \n\t0x0BBD9006, 0x290F958C, 0x9F643532, 0x6C3B0139, \n\t0x6CC50432, 0xF897FD03, 0x0D697735, 0xE771E913, \n\t0x2512B0CE, 0x8F464A70, 0x6D8499EB, 0xD5FAD746, \n\t0xD370F263, 0xD9CB87C2, 0xAE83063E, 0x457538AB, \n\t0x2C6DF785, 0x767DC282, 0xEF8E5D32, 0xD42A90D5, \n\t0x82283D19, 0xD6998B86, 0x45556216, 0x0AB9472D, \n\t0x4C7D0288, 0x8AE9130C, 0x754AB572, 0x1CCAA4BE, \n\t0x4AAC0B8C, 0xEF15E5FB, 0x37A62964, 0xDAE2AEF8, \n\t0x7603D147, 0xCD93C1D1, 0x0C074301, 0xF1CF3B96, \n\t0x171B671D, 0x19482F23, 0x650C10BE, 0x78BA3604, \n\t0x255E4C02, 0xB3861AA7, 0xB84B4B36, 0xCF6A9483, \n\t0x1042A95D, 0x0E3179AB, 0xEE51D6CB, 0xC1B2AE91, \n\t0x7E9267AF, 0x348B1FD4, 0x0E2AE9CD, 0xCC6D241B, \n\t0x50B1DF82, 0xE1003E5C, 0xF6722D9E, 0x24943328, \n\t0xBE258FF3, 0xD74F9208, 0xAD44CFD2, 0xF71C35FD, \n\t0x7A035BF6, 0x85FFAE5B, 0xD31BF6B5, 0x7A262174, \n\t0x312F3F63, 0xF242DABB, 0xB6A8E122, 0xA7F09AB6, \n\t0xF92F8A1B, 0x98158536, 0xE69D218D, 0xF7CA8CD9, \n\t0xC71A026E, 0x28A5043C, 0x1D89CD91, 0x0105DF53, \n\t0x4533E63A, 0x94812704, 0xC06E0E68, 0x62633145, \n\t0x10B4611A, 0xE487ED51, 0xFFFFFFFF, 0x7FFFFFFF } },\n\t/* g */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000002 } },\n\t/* Checksums */\n\t0xFB7DF2C8, 0x1D70CEE7, 0x847050E5\n\t};\n#endif /* 3072-bit bignums */\n\n#endif /* 64- vs 32-bit */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDH Access Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load a fixed DH key of the appropriate size */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint loadDHparams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t  IN_LENGTH_PKC const int requestedKeySize )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst DH_DOMAINPARAMS *domainParams;\n#ifdef CREATE_BIGNUM_VALUES\n\tint status;\n#endif /* CREATE_BIGNUM_VALUES */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( requestedKeySize >= MIN_PKCSIZE && \\\n\t\t\t  requestedKeySize <= CRYPT_MAX_PKCSIZE );\n\n\t/* Convert the fixed-format bignums to encoded BIGNUMs */\n#ifdef CREATE_BIGNUM_VALUES\n\tcheckDHdata();\n\tstatus = loadDHparamsFixed( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\tbitsToBytes( 1024 ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( pkcInfo->domainParams != NULL )\n\t\t{\n\t\t/* If we're loading known domain parameters in order to calculate q \n\t\t   from { p, g } or to calculate the parameter checksum, the values\n\t\t   won't be stored in the dlpParam values but as constant \n\t\t   domainParams data */\n\t\tdomainParams = pkcInfo->domainParams;\n\t\tBN_copy( &pkcInfo->dlpParam_q, &domainParams->p );\n\t\t}\n\telse\n\t\tBN_copy( &pkcInfo->dlpParam_q, &pkcInfo->dlpParam_p );\n\tBN_sub_word( &pkcInfo->dlpParam_q, 1 );\n\tBN_rshift( &pkcInfo->dlpParam_q, &pkcInfo->dlpParam_q, 1 );\t/* q = (p-1)/2 */\n\tprintBignum( &pkcInfo->dlpParam_p, \"p\" );\n\tprintBignum( &pkcInfo->dlpParam_q, \"q\" );\n\tprintBignum( &pkcInfo->dlpParam_g, \"g\" );\n\tDEBUG_PRINT(( \"\\t/* Checksums */\\n\\t\" ));\n\tprintBignumChecksum( &pkcInfo->dlpParam_p );\n\tprintBignumChecksum( &pkcInfo->dlpParam_q );\n\tprintBignumChecksum( &pkcInfo->dlpParam_g );\n\tDEBUG_PRINT(( \"\\n\" ));\n#endif /* CREATE_BIGNUM_VALUES */\n\n\t/* Get the built-in DH key value that corresponds best to the client's \n\t   requested key size.  We allow for a bit of slop to avoid having \n\t   something like a 2049-bit requested key size lead to the use of a \n\t   3072-bit key value.\n\n\t   In theory for protocols that support the use of arbitrary DH \n\t   parameters we should probably generate a new DH key each time:\n\n\t\tstatus = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &requestedKeySize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( iDHContext, IMESSAGE_CTX_GENKEY, \n\t\t\t\t\t\t\t\t\t  NULL, FALSE );\n\n\t   however because the handshake is set up so that the client (rather \n\t   than the server) chooses the key size we can't actually perform the \n\t   generation until we're in the middle of the handshake.  This means \n\t   that the server will grind to a halt during each handshake as it \n\t   generates a new key of whatever size takes the client's fancy (it \n\t   also leads to a nice potential DoS attack on the server).  To avoid \n\t   this problem we use fixed keys of various common sizes.\n\t   \n\t   As late as 2014 Java still can't handle DH keys over 1024 bits (it \n\t   only allows keys ranging from 512-1024 bits):\n\n\t\tjava.security.InvalidAlgorithmParameterException: Prime size must be \n\t\tmultiple of 64, and can only range from 512 to 1024 (inclusive)\n\n\t   so if you need to talk to a system built in Java you need to first\n\t   enable the use of unsound 1024-bit keys using USE_DH1024 and then \n\t   hardcode the key size to 1024 bits, the largest size that Java will \n\t   allow */\n#ifdef USE_DH1024\n\tif( requestedKeySize <= 128 + 8 )\n\t\tdomainParams = &dh1024params;\n\telse\n#endif /* USE_DH1024 */\n\tif( requestedKeySize <= 192 + 8 )\n\t\tdomainParams = &dh1536params;\n\telse\n#if CRYPT_MAX_PKCSIZE >= bitsToBytes( 3072 )\n\tif( requestedKeySize <= 256 + 8 )\n\t\tdomainParams = &dh2048params;\n\telse\n\t\tdomainParams = &dh3072params;\n#else\n\t\tdomainParams = &dh2048params;\n#endif /* 3072-bit bignums */\n\n\t/* Make sure that the domain parameters are in order */\n\tif( !checksumDomainParameters( domainParams, FALSE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Fixed DH value for requested %d-bit key has been \"\n\t\t\t\t\t \"corrupted\", requestedKeySize ));\n\t\tretIntError();\n\t\t}\n\n\tpkcInfo->domainParams = domainParams;\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkFixedDHparams( const INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\tOUT const DH_DOMAINPARAMS **domainParamsPtr )\n\t{\n\tconst BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;\n\n\tassert( isReadPtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isReadPtr( domainParamsPtr, sizeof( DH_DOMAINPARAMS * ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Clear return value */\n\t*domainParamsPtr = NULL;\n\n\t/* Compare the { p, g } value that we've been given against our known\n\t   { p, g } values.  We check for the values in order of likelihood */\n\tif( !BN_cmp( &dh2048params.p, p ) && !BN_cmp( &dh2048params.g, g ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Using built-in DH value for requested 2048-bit key\" ));\n\t\t*domainParamsPtr = &dh2048params;\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tif( !BN_cmp( &dh1536params.p, p ) && !BN_cmp( &dh1536params.g, g ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Using built-in DH value for requested 1536-bit key\" ));\n\t\t*domainParamsPtr = &dh1536params;\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tif( !BN_cmp( &dh1024params.p, p ) && !BN_cmp( &dh1024params.g, g ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Using built-in DH value for requested 1024-bit key\" ));\n\t\t*domainParamsPtr = &dh1024params;\n\t\treturn( OK_SPECIAL );\n\t\t}\n#if CRYPT_MAX_PKCSIZE >= bitsToBytes( 3072 )\n\tif( !BN_cmp( &dh3072params.p, p ) && !BN_cmp( &dh3072params.g, g ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Using built-in DH value for requested 3072-bit key\" ));\n\t\t*domainParamsPtr = &dh3072params;\n\t\treturn( OK_SPECIAL );\n\t\t}\n#endif /* 3072-bit bignums */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH || USE_SSL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tECC Domain Parameters\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* We always use pre-generated parameters both because it's unlikely that \n   anyone will ever decide to generate nonstandard parameters when standard \n   ones are available (or at least no sane person would, no doubt every \n   little standards committee wanting to make their mark will feel the need \n   to have their own personal incompatible parameters).  In addition using \n   externally-generated parameters can (as for DSA) lead to problems with \n   maliciously-generated values (see \"CM-Curves with good Cryptography \n   Properties\", Neal Koblitz, Proceedings of Crypto'91, p.279), and finally \n   (also like DSA) it can lead to problems with parameter-substitution \n   attacks (see \"Digital Signature Schemes with Domain Parameters\", Serge \n   Vaudenay, Proceedings of ACISP'04, p.188) */\n\n#ifdef CREATE_BIGNUM_VALUES\n\ntypedef struct {\n\tCRYPT_ECCCURVE_TYPE paramType;\n\tconst int curveSizeBits;\n\tconst BYTE *p, *a, *b, *gx, *gy, *n, *h;\n\tconst BYTE *hashValue;\n\t} ECC_DOMAIN_PARAMS;\n\nstatic const ECC_DOMAIN_PARAMS domainParamTbl[] = {\n\t/* NIST P-256, X9.62 p256r1, SECG p256r1 */\n\t{ CRYPT_ECCCURVE_P256, 256,\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x01\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ),\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x01\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFC\" ),\n\t  MKDATA( \"\\x5A\\xC6\\x35\\xD8\\xAA\\x3A\\x93\\xE7\" \\\n\t\t\t  \"\\xB3\\xEB\\xBD\\x55\\x76\\x98\\x86\\xBC\" \\\n\t\t\t  \"\\x65\\x1D\\x06\\xB0\\xCC\\x53\\xB0\\xF6\" \\\n\t\t\t  \"\\x3B\\xCE\\x3C\\x3E\\x27\\xD2\\x60\\x4B\" ),\n\t  MKDATA( \"\\x6B\\x17\\xD1\\xF2\\xE1\\x2C\\x42\\x47\" \\\n\t\t\t  \"\\xF8\\xBC\\xE6\\xE5\\x63\\xA4\\x40\\xF2\" \\\n\t\t\t  \"\\x77\\x03\\x7D\\x81\\x2D\\xEB\\x33\\xA0\" \\\n\t\t\t  \"\\xF4\\xA1\\x39\\x45\\xD8\\x98\\xC2\\x96\" ),\n\t  MKDATA( \"\\x4F\\xE3\\x42\\xE2\\xFE\\x1A\\x7F\\x9B\" \\\n\t\t\t  \"\\x8E\\xE7\\xEB\\x4A\\x7C\\x0F\\x9E\\x16\" \\\n\t\t\t  \"\\x2B\\xCE\\x33\\x57\\x6B\\x31\\x5E\\xCE\" \\\n\t\t\t  \"\\xCB\\xB6\\x40\\x68\\x37\\xBF\\x51\\xF5\" ),\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xBC\\xE6\\xFA\\xAD\\xA7\\x17\\x9E\\x84\" \\\n\t\t\t  \"\\xF3\\xB9\\xCA\\xC2\\xFC\\x63\\x25\\x51\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\x40\\x31\\x2F\\x8C\\x04\\xBB\\x5E\\x5C\" \\\n\t\t\t  \"\\x0F\\x12\\x32\\x75\\x91\\xE8\\x71\\x65\" ) },\n\n\t/* Brainpool p256r1 */\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P256, 256,\n\t  MKDATA( \"\\xA9\\xFB\\x57\\xDB\\xA1\\xEE\\xA9\\xBC\" \\\n\t\t\t  \"\\x3E\\x66\\x0A\\x90\\x9D\\x83\\x8D\\x72\" \\\n\t\t\t  \"\\x6E\\x3B\\xF6\\x23\\xD5\\x26\\x20\\x28\" \\\n\t\t\t  \"\\x20\\x13\\x48\\x1D\\x1F\\x6E\\x53\\x77\" ),\n\t  MKDATA( \"\\x7D\\x5A\\x09\\x75\\xFC\\x2C\\x30\\x57\" \\\n\t\t\t  \"\\xEE\\xF6\\x75\\x30\\x41\\x7A\\xFF\\xE7\" \\\n\t\t\t  \"\\xFB\\x80\\x55\\xC1\\x26\\xDC\\x5C\\x6C\" \\\n\t\t\t  \"\\xE9\\x4A\\x4B\\x44\\xF3\\x30\\xB5\\xD9\" ),\n\t  MKDATA( \"\\x26\\xDC\\x5C\\x6C\\xE9\\x4A\\x4B\\x44\" \\\n\t\t\t  \"\\xF3\\x30\\xB5\\xD9\\xBB\\xD7\\x7C\\xBF\" \\\n\t\t\t  \"\\x95\\x84\\x16\\x29\\x5C\\xF7\\xE1\\xCE\" \\\n\t\t\t  \"\\x6B\\xCC\\xDC\\x18\\xFF\\x8C\\x07\\xB6\" ),\n\t  MKDATA( \"\\x8B\\xD2\\xAE\\xB9\\xCB\\x7E\\x57\\xCB\" \\\n\t\t\t  \"\\x2C\\x4B\\x48\\x2F\\xFC\\x81\\xB7\\xAF\" \\\n\t\t\t  \"\\xB9\\xDE\\x27\\xE1\\xE3\\xBD\\x23\\xC2\" \\\n\t\t\t  \"\\x3A\\x44\\x53\\xBD\\x9A\\xCE\\x32\\x62\" ),\n\t  MKDATA( \"\\x54\\x7E\\xF8\\x35\\xC3\\xDA\\xC4\\xFD\" \\\n\t\t\t  \"\\x97\\xF8\\x46\\x1A\\x14\\x61\\x1D\\xC9\" \\\n\t\t\t  \"\\xC2\\x77\\x45\\x13\\x2D\\xED\\x8E\\x54\" \\\n\t\t\t  \"\\x5C\\x1D\\x54\\xC7\\x2F\\x04\\x69\\x97\" ),\n\t  MKDATA( \"\\xA9\\xFB\\x57\\xDB\\xA1\\xEE\\xA9\\xBC\" \\\n\t\t\t  \"\\x3E\\x66\\x0A\\x90\\x9D\\x83\\x8D\\x71\" \\\n\t\t\t  \"\\x8C\\x39\\x7A\\xA3\\xB5\\x61\\xA6\\xF7\" \\\n\t\t\t  \"\\x90\\x1E\\x0E\\x82\\x97\\x48\\x56\\xA7\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\x3F\\xBF\\x15\\xA2\\x89\\x27\\x68\\x83\" \\\n\t\t\t  \"\\x67\\xAC\\x82\\x26\\x48\\xFA\\x44\\x8E\" ) },\n\n\t/* NIST P-384, SECG p384r1 */\n\t{ CRYPT_ECCCURVE_P384, 384,\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ),\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\" \\\n\t\t\t  \"\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFC\" ),\n\t  MKDATA( \"\\xB3\\x31\\x2F\\xA7\\xE2\\x3E\\xE7\\xE4\" \\\n\t\t\t  \"\\x98\\x8E\\x05\\x6B\\xE3\\xF8\\x2D\\x19\" \\\n\t\t\t  \"\\x18\\x1D\\x9C\\x6E\\xFE\\x81\\x41\\x12\" \\\n\t\t\t  \"\\x03\\x14\\x08\\x8F\\x50\\x13\\x87\\x5A\" \\\n\t\t\t  \"\\xC6\\x56\\x39\\x8D\\x8A\\x2E\\xD1\\x9D\" \\\n\t\t\t  \"\\x2A\\x85\\xC8\\xED\\xD3\\xEC\\x2A\\xEF\" ),\n\t  MKDATA( \"\\xAA\\x87\\xCA\\x22\\xBE\\x8B\\x05\\x37\" \\\n\t\t\t  \"\\x8E\\xB1\\xC7\\x1E\\xF3\\x20\\xAD\\x74\" \\\n\t\t\t  \"\\x6E\\x1D\\x3B\\x62\\x8B\\xA7\\x9B\\x98\" \\\n\t\t\t  \"\\x59\\xF7\\x41\\xE0\\x82\\x54\\x2A\\x38\" \\\n\t\t\t  \"\\x55\\x02\\xF2\\x5D\\xBF\\x55\\x29\\x6C\" \\\n\t\t\t  \"\\x3A\\x54\\x5E\\x38\\x72\\x76\\x0A\\xB7\" ),\n\t  MKDATA( \"\\x36\\x17\\xDE\\x4A\\x96\\x26\\x2C\\x6F\" \\\n\t\t\t  \"\\x5D\\x9E\\x98\\xBF\\x92\\x92\\xDC\\x29\" \\\n\t\t\t  \"\\xF8\\xF4\\x1D\\xBD\\x28\\x9A\\x14\\x7C\" \\\n\t\t\t  \"\\xE9\\xDA\\x31\\x13\\xB5\\xF0\\xB8\\xC0\" \\\n\t\t\t  \"\\x0A\\x60\\xB1\\xCE\\x1D\\x7E\\x81\\x9D\" \\\n\t\t\t  \"\\x7A\\x43\\x1D\\x7C\\x90\\xEA\\x0E\\x5F\" ),\n\t  MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xC7\\x63\\x4D\\x81\\xF4\\x37\\x2D\\xDF\" \\\n\t\t\t \"\\x58\\x1A\\x0D\\xB2\\x48\\xB0\\xA7\\x7A\" \\\n\t\t\t \"\\xEC\\xEC\\x19\\x6A\\xCC\\xC5\\x29\\x73\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\xC2\\xDF\\x12\\x1E\\x86\\x76\\xF9\\x5A\" \\\n\t\t\t  \"\\x6C\\xD9\\xA9\\x3C\\x18\\xA3\\xA8\\x79\" ) },\n\n\t/* Brainpool p384r1 */\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P384, 384,\n\t  MKDATA( \"\\x8C\\xB9\\x1E\\x82\\xA3\\x38\\x6D\\x28\" \\\n\t\t\t  \"\\x0F\\x5D\\x6F\\x7E\\x50\\xE6\\x41\\xDF\" \\\n\t\t\t  \"\\x15\\x2F\\x71\\x09\\xED\\x54\\x56\\xB4\" \\\n\t\t\t  \"\\x12\\xB1\\xDA\\x19\\x7F\\xB7\\x11\\x23\" \\\n\t\t\t  \"\\xAC\\xD3\\xA7\\x29\\x90\\x1D\\x1A\\x71\" \\\n\t\t\t  \"\\x87\\x47\\x00\\x13\\x31\\x07\\xEC\\x53\" ),\n\t  MKDATA( \"\\x7B\\xC3\\x82\\xC6\\x3D\\x8C\\x15\\x0C\" \\\n\t\t\t  \"\\x3C\\x72\\x08\\x0A\\xCE\\x05\\xAF\\xA0\" \\\n\t\t\t  \"\\xC2\\xBE\\xA2\\x8E\\x4F\\xB2\\x27\\x87\" \\\n\t\t\t  \"\\x13\\x91\\x65\\xEF\\xBA\\x91\\xF9\\x0F\" \\\n\t\t\t  \"\\x8A\\xA5\\x81\\x4A\\x50\\x3A\\xD4\\xEB\" \\\n\t\t\t  \"\\x04\\xA8\\xC7\\xDD\\x22\\xCE\\x28\\x26\" ),\n\t  MKDATA( \"\\x04\\xA8\\xC7\\xDD\\x22\\xCE\\x28\\x26\" \\\n\t\t\t  \"\\x8B\\x39\\xB5\\x54\\x16\\xF0\\x44\\x7C\" \\\n\t\t\t  \"\\x2F\\xB7\\x7D\\xE1\\x07\\xDC\\xD2\\xA6\" \\\n\t\t\t  \"\\x2E\\x88\\x0E\\xA5\\x3E\\xEB\\x62\\xD5\" \\\n\t\t\t  \"\\x7C\\xB4\\x39\\x02\\x95\\xDB\\xC9\\x94\" \\\n\t\t\t  \"\\x3A\\xB7\\x86\\x96\\xFA\\x50\\x4C\\x11\" ),\n\t  MKDATA( \"\\x1D\\x1C\\x64\\xF0\\x68\\xCF\\x45\\xFF\" \\\n\t\t\t  \"\\xA2\\xA6\\x3A\\x81\\xB7\\xC1\\x3F\\x6B\" \\\n\t\t\t  \"\\x88\\x47\\xA3\\xE7\\x7E\\xF1\\x4F\\xE3\" \\\n\t\t\t  \"\\xDB\\x7F\\xCA\\xFE\\x0C\\xBD\\x10\\xE8\" \\\n\t\t\t  \"\\xE8\\x26\\xE0\\x34\\x36\\xD6\\x46\\xAA\" \\\n\t\t\t  \"\\xEF\\x87\\xB2\\xE2\\x47\\xD4\\xAF\\x1E\" ),\n\t  MKDATA( \"\\x8A\\xBE\\x1D\\x75\\x20\\xF9\\xC2\\xA4\" \\\n\t\t\t  \"\\x5C\\xB1\\xEB\\x8E\\x95\\xCF\\xD5\\x52\" \\\n\t\t\t  \"\\x62\\xB7\\x0B\\x29\\xFE\\xEC\\x58\\x64\" \\\n\t\t\t  \"\\xE1\\x9C\\x05\\x4F\\xF9\\x91\\x29\\x28\" \\\n\t\t\t  \"\\x0E\\x46\\x46\\x21\\x77\\x91\\x81\\x11\" \\\n\t\t\t  \"\\x42\\x82\\x03\\x41\\x26\\x3C\\x53\\x15\" ),\n\t  MKDATA( \"\\x8C\\xB9\\x1E\\x82\\xA3\\x38\\x6D\\x28\" \\\n\t\t\t  \"\\x0F\\x5D\\x6F\\x7E\\x50\\xE6\\x41\\xDF\" \\\n\t\t\t  \"\\x15\\x2F\\x71\\x09\\xED\\x54\\x56\\xB3\" \\\n\t\t\t  \"\\x1F\\x16\\x6E\\x6C\\xAC\\x04\\x25\\xA7\" \\\n\t\t\t  \"\\xCF\\x3A\\xB6\\xAF\\x6B\\x7F\\xC3\\x10\" \\\n\t\t\t  \"\\x3B\\x88\\x32\\x02\\xE9\\x04\\x65\\x65\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\x04\\xDE\\xA5\\xE1\\x39\\x3B\\xE0\\xB5\" \\\n\t\t\t  \"\\x6F\\x2C\\x0B\\xC7\\xAF\\x9E\\xF9\\x07\" ) },\n\n\t/* NIST P-521, SECG p521r1 */\n\t{ CRYPT_ECCCURVE_P521, 521,\n\t  MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\" ),\n\t  MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFC\" ),\n\t  MKDATA( \"\\x00\\x51\\x95\\x3E\\xB9\\x61\\x8E\\x1C\" \\\n\t\t\t  \"\\x9A\\x1F\\x92\\x9A\\x21\\xA0\\xB6\\x85\" \\\n\t\t\t  \"\\x40\\xEE\\xA2\\xDA\\x72\\x5B\\x99\\xB3\" \\\n\t\t\t  \"\\x15\\xF3\\xB8\\xB4\\x89\\x91\\x8E\\xF1\" \\\n\t\t\t  \"\\x09\\xE1\\x56\\x19\\x39\\x51\\xEC\\x7E\" \\\n\t\t\t  \"\\x93\\x7B\\x16\\x52\\xC0\\xBD\\x3B\\xB1\" \\\n\t\t\t  \"\\xBF\\x07\\x35\\x73\\xDF\\x88\\x3D\\x2C\" \\\n\t\t\t  \"\\x34\\xF1\\xEF\\x45\\x1F\\xD4\\x6B\\x50\" \\\n\t\t\t  \"\\x3F\\x00\" ),\n\t  MKDATA( \"\\x00\\xC6\\x85\\x8E\\x06\\xB7\\x04\\x04\" \\\n\t\t\t  \"\\xE9\\xCD\\x9E\\x3E\\xCB\\x66\\x23\\x95\" \\\n\t\t\t  \"\\xB4\\x42\\x9C\\x64\\x81\\x39\\x05\\x3F\" \\\n\t\t\t  \"\\xB5\\x21\\xF8\\x28\\xAF\\x60\\x6B\\x4D\" \\\n\t\t\t  \"\\x3D\\xBA\\xA1\\x4B\\x5E\\x77\\xEF\\xE7\" \\\n\t\t\t  \"\\x59\\x28\\xFE\\x1D\\xC1\\x27\\xA2\\xFF\" \\\n\t\t\t  \"\\xA8\\xDE\\x33\\x48\\xB3\\xC1\\x85\\x6A\" \\\n\t\t\t  \"\\x42\\x9B\\xF9\\x7E\\x7E\\x31\\xC2\\xE5\" \\\n\t\t\t  \"\\xBD\\x66\" ),\n\t  MKDATA( \"\\x01\\x18\\x39\\x29\\x6A\\x78\\x9A\\x3B\" \\\n\t\t\t  \"\\xC0\\x04\\x5C\\x8A\\x5F\\xB4\\x2C\\x7D\" \\\n\t\t\t  \"\\x1B\\xD9\\x98\\xF5\\x44\\x49\\x57\\x9B\" \\\n\t\t\t  \"\\x44\\x68\\x17\\xAF\\xBD\\x17\\x27\\x3E\" \\\n\t\t\t  \"\\x66\\x2C\\x97\\xEE\\x72\\x99\\x5E\\xF4\" \\\n\t\t\t  \"\\x26\\x40\\xC5\\x50\\xB9\\x01\\x3F\\xAD\" \\\n\t\t\t  \"\\x07\\x61\\x35\\x3C\\x70\\x86\\xA2\\x72\" \\\n\t\t\t  \"\\xC2\\x40\\x88\\xBE\\x94\\x76\\x9F\\xD1\" \\\n\t\t\t  \"\\x66\\x50\" ),\n\t  MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" \\\n\t\t\t  \"\\xFF\\xFA\\x51\\x86\\x87\\x83\\xBF\\x2F\" \\\n\t\t\t  \"\\x96\\x6B\\x7F\\xCC\\x01\\x48\\xF7\\x09\" \\\n\t\t\t  \"\\xA5\\xD0\\x3B\\xB5\\xC9\\xB8\\x89\\x9C\" \\\n\t\t\t  \"\\x47\\xAE\\xBB\\x6F\\xB7\\x1E\\x91\\x38\" \\\n\t\t\t  \"\\x64\\x09\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\xC4\\x0E\\xC4\\xCC\\x78\\x19\\x0A\\xA6\" \\\n\t\t\t  \"\\x8C\\x7E\\xA0\\xB1\\x14\\xA4\\xBC\\x23\" ) },\n\n\t/* Brainpool p512r1 */\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P512, 512,\n\t  MKDATA( \"\\xAA\\xDD\\x9D\\xB8\\xDB\\xE9\\xC4\\x8B\" \\\n\t\t\t  \"\\x3F\\xD4\\xE6\\xAE\\x33\\xC9\\xFC\\x07\" \\\n\t\t\t  \"\\xCB\\x30\\x8D\\xB3\\xB3\\xC9\\xD2\\x0E\" \\\n\t\t\t  \"\\xD6\\x63\\x9C\\xCA\\x70\\x33\\x08\\x71\" \\\n\t\t\t  \"\\x7D\\x4D\\x9B\\x00\\x9B\\xC6\\x68\\x42\" \\\n\t\t\t  \"\\xAE\\xCD\\xA1\\x2A\\xE6\\xA3\\x80\\xE6\" \\\n\t\t\t  \"\\x28\\x81\\xFF\\x2F\\x2D\\x82\\xC6\\x85\" \\\n\t\t\t  \"\\x28\\xAA\\x60\\x56\\x58\\x3A\\x48\\xF3\" ),\n\t  MKDATA( \"\\x78\\x30\\xA3\\x31\\x8B\\x60\\x3B\\x89\" \\\n\t\t\t  \"\\xE2\\x32\\x71\\x45\\xAC\\x23\\x4C\\xC5\" \\\n\t\t\t  \"\\x94\\xCB\\xDD\\x8D\\x3D\\xF9\\x16\\x10\" \\\n\t\t\t  \"\\xA8\\x34\\x41\\xCA\\xEA\\x98\\x63\\xBC\" \\\n\t\t\t  \"\\x2D\\xED\\x5D\\x5A\\xA8\\x25\\x3A\\xA1\" \\\n\t\t\t  \"\\x0A\\x2E\\xF1\\xC9\\x8B\\x9A\\xC8\\xB5\" \\\n\t\t\t  \"\\x7F\\x11\\x17\\xA7\\x2B\\xF2\\xC7\\xB9\" \\\n\t\t\t  \"\\xE7\\xC1\\xAC\\x4D\\x77\\xFC\\x94\\xCA\" ),\n\t  MKDATA( \"\\x3D\\xF9\\x16\\x10\\xA8\\x34\\x41\\xCA\" \\\n\t\t\t  \"\\xEA\\x98\\x63\\xBC\\x2D\\xED\\x5D\\x5A\" \\\n\t\t\t  \"\\xA8\\x25\\x3A\\xA1\\x0A\\x2E\\xF1\\xC9\" \\\n\t\t\t  \"\\x8B\\x9A\\xC8\\xB5\\x7F\\x11\\x17\\xA7\" \\\n\t\t\t  \"\\x2B\\xF2\\xC7\\xB9\\xE7\\xC1\\xAC\\x4D\" \\\n\t\t\t  \"\\x77\\xFC\\x94\\xCA\\xDC\\x08\\x3E\\x67\" \\\n\t\t\t  \"\\x98\\x40\\x50\\xB7\\x5E\\xBA\\xE5\\xDD\" \\\n\t\t\t  \"\\x28\\x09\\xBD\\x63\\x80\\x16\\xF7\\x23\" ),\n\t  MKDATA( \"\\x81\\xAE\\xE4\\xBD\\xD8\\x2E\\xD9\\x64\" \\\n\t\t\t  \"\\x5A\\x21\\x32\\x2E\\x9C\\x4C\\x6A\\x93\" \\\n\t\t\t  \"\\x85\\xED\\x9F\\x70\\xB5\\xD9\\x16\\xC1\" \\\n\t\t\t  \"\\xB4\\x3B\\x62\\xEE\\xF4\\xD0\\x09\\x8E\" \\\n\t\t\t  \"\\xFF\\x3B\\x1F\\x78\\xE2\\xD0\\xD4\\x8D\" \\\n\t\t\t  \"\\x50\\xD1\\x68\\x7B\\x93\\xB9\\x7D\\x5F\" \\\n\t\t\t  \"\\x7C\\x6D\\x50\\x47\\x40\\x6A\\x5E\\x68\" \\\n\t\t\t  \"\\x8B\\x35\\x22\\x09\\xBC\\xB9\\xF8\\x22\" ),\n\t  MKDATA( \"\\x7D\\xDE\\x38\\x5D\\x56\\x63\\x32\\xEC\" \\\n\t\t\t  \"\\xC0\\xEA\\xBF\\xA9\\xCF\\x78\\x22\\xFD\" \\\n\t\t\t  \"\\xF2\\x09\\xF7\\x00\\x24\\xA5\\x7B\\x1A\" \\\n\t\t\t  \"\\xA0\\x00\\xC5\\x5B\\x88\\x1F\\x81\\x11\" \\\n\t\t\t  \"\\xB2\\xDC\\xDE\\x49\\x4A\\x5F\\x48\\x5E\" \\\n\t\t\t  \"\\x5B\\xCA\\x4B\\xD8\\x8A\\x27\\x63\\xAE\" \\\n\t\t\t  \"\\xD1\\xCA\\x2B\\x2F\\xA8\\xF0\\x54\\x06\" \\\n\t\t\t  \"\\x78\\xCD\\x1E\\x0F\\x3A\\xD8\\x08\\x92\" ),\n\t  MKDATA( \"\\xAA\\xDD\\x9D\\xB8\\xDB\\xE9\\xC4\\x8B\" \\\n\t\t\t  \"\\x3F\\xD4\\xE6\\xAE\\x33\\xC9\\xFC\\x07\" \\\n\t\t\t  \"\\xCB\\x30\\x8D\\xB3\\xB3\\xC9\\xD2\\x0E\" \\\n\t\t\t  \"\\xD6\\x63\\x9C\\xCA\\x70\\x33\\x08\\x70\" \\\n\t\t\t  \"\\x55\\x3E\\x5C\\x41\\x4C\\xA9\\x26\\x19\" \\\n\t\t\t  \"\\x41\\x86\\x61\\x19\\x7F\\xAC\\x10\\x47\" \\\n\t\t\t  \"\\x1D\\xB1\\xD3\\x81\\x08\\x5D\\xDA\\xDD\" \\\n\t\t\t  \"\\xB5\\x87\\x96\\x82\\x9C\\xA9\\x00\\x69\" ),\n\t  MKDATA( \"\\x01\" ),\n\t  MKDATA( \"\\x2C\\x2A\\xE4\\xF6\\x05\\xB6\\xAF\\xB5\"\n\t\t\t  \"\\x78\\xC5\\x90\\x1E\\x45\\x9F\\x4B\\x5C\" ) },\n\n\t/* End-of-list marker */\n\t{ CRYPT_ECCCURVE_NONE, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },\n\t\t{ CRYPT_ECCCURVE_NONE, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }\n\t};\n\n/* Checksum values for the ECC data */\n\nstatic BOOLEAN eccChecksumsSet = FALSE;\nstatic int eccChecksums[ 8 + 8 ];\n\n/* Check that the DH key data is valid */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN hashECCparams( const ECC_DOMAIN_PARAMS *eccParams,\n\t\t\t\t\t\t\t  IN_BUFFER( 20 ) const void *hashValue )\n\t{\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst int curveSize = bitsToBytes( eccParams->curveSizeBits );\n\tint hashSize;\n\n\tassert( isReadPtr( eccParams, sizeof( ECC_DOMAIN_PARAMS ) ) );\n\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, &hashSize );\n\thashFunction( hashInfo, NULL, 0, eccParams->p, curveSize, HASH_STATE_START );\n\thashFunction( hashInfo, NULL, 0, eccParams->a, curveSize, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, NULL, 0, eccParams->b, curveSize, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, NULL, 0, eccParams->gx, curveSize, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, NULL, 0, eccParams->gy, curveSize, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, NULL, 0, eccParams->n, curveSize, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, hash, CRYPT_MAX_HASHSIZE, eccParams->h, 1, HASH_STATE_END );\n\n\treturn( !memcmp( hash, hashValue, 16 ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL \\\nstatic int initCheckECCdata( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Check the SHA-1 values for the ECC data and set up the corresponding\n\t   checksums for the overall ECC parameters */\n\tLOOP_MED( i = 0, domainParamTbl[ i ].paramType != CRYPT_ECCCURVE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ), \n\t\t\t  i++ )\n\t\t{\n\t\tconst ECC_DOMAIN_PARAMS *eccParams = &domainParamTbl[ i ];\n\n\t\tif( !isEnumRange( eccParams->paramType, CRYPT_ECCCURVE ) || \\\n\t\t\teccParams->curveSizeBits < 192 || \\\n\t\t\teccParams->curveSizeBits > 521 )\n\t\t\tretIntError();\n\t\tif( !hashECCparams( eccParams, eccParams->hashValue ) )\n\t\t\tretIntError();\n\t\teccChecksums[ i ] = checksumData( eccParams, \n\t\t\t\t\t\t\t\t\t\t  sizeof( ECC_DOMAIN_PARAMS ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ) );\n\teccChecksumsSet = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise the bignums for the domain parameter values { p, a, b, gx, gy, \n   n }.  Note that although the cofactor h is given for the standard named \n   curves it's not used for any ECC operations so we don't bother allocating \n   a bignum to it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint loadECCparamsFixed( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\tIN_ENUM( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE curveType )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst ECC_DOMAIN_PARAMS *eccParams = NULL;\n\tBIGNUM bignums[ 7 ];\n\tint curveSize, checksum DUMMY_INIT, i, LOOP_ITERATOR;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isEnumRange( curveType, CRYPT_ECCCURVE ) );\n\n\t/* Set up the ECC parameter checksums if required */\n\tif( !eccChecksumsSet )\n\t\t{\n\t\tstatus = initCheckECCdata();\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\teccChecksumsSet = TRUE;\n\t\t}\n\n\t/* Find the parameter info for this curve */\n\tLOOP_MED( i = 0, domainParamTbl[ i ].paramType != CRYPT_ECCCURVE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( domainParamTbl[ i ].paramType == curveType )\n\t\t\t{\n\t\t\teccParams = &domainParamTbl[ i ];\n\t\t\tchecksum = eccChecksums[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( domainParamTbl, ECC_DOMAIN_PARAMS ) );\n\tENSURES( eccParams != NULL );\n\tif( checksum != checksumData( eccParams, sizeof( ECC_DOMAIN_PARAMS ) ) )\n\t\tretIntError();\n\n\t/* For the named curve the key size is defined by exective fiat based\n\t   on the curve type rather than being taken from the public-key value \n\t   (which in this case is the magnitude of the point Q on the curve), so \n\t   we set it explicitly based on the curve type */\n\tpkcInfo->curveType = curveType;\n\tpkcInfo->keySizeBits = eccParams->curveSizeBits;\n\tcurveSize = bitsToBytes( eccParams->curveSizeBits );\n\n\t/* Load the parameters into the context bignums */\n\tLOOP_MED( i = 0, i < 7, i++ )\n\t\tBN_init( &bignums[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\tCKPTR( BN_bin2bn( eccParams->p, curveSize, &bignums[ 0 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->a, curveSize, &bignums[ 1 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->b, curveSize, &bignums[ 2 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->gx, curveSize, &bignums[ 3 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->gy, curveSize, &bignums[ 4 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->n, curveSize, &bignums[ 5 ] ) );\n\tCKPTR( BN_bin2bn( eccParams->h, 1, &bignums[ 6 ] ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tprintBignum( &bignums[ 0 ], \"p\" );\n\tprintBignum( &bignums[ 1 ], \"a\" );\n\tprintBignum( &bignums[ 2 ], \"b\" );\n\tprintBignum( &bignums[ 3 ], \"gx\" );\n\tprintBignum( &bignums[ 4 ], \"gy\" );\n\tprintBignum( &bignums[ 5 ], \"n\" );\n\tprintBignum( &bignums[ 6 ], \"h\" );\n\tDEBUG_PRINT(( \"\\t/* Checksums */\\n\\t\" ));\n\tprintBignumChecksum( &bignums[ 0 ] );\n\tprintBignumChecksum( &bignums[ 1 ] );\n#if BN_BITS2 == 64\n\tDEBUG_PRINT( ( \"\\n\\t\" ) );\n#endif /* 64- vs 32-bit */\n\tprintBignumChecksum( &bignums[ 2 ] );\n\tprintBignumChecksum( &bignums[ 3 ] );\n\tDEBUG_PRINT(( \"\\n\\t\" ));\n\tprintBignumChecksum( &bignums[ 4 ] );\n\tprintBignumChecksum( &bignums[ 5 ] );\n#if BN_BITS2 == 64\n\tDEBUG_PRINT( ( \"\\n\\t\" ) );\n#endif /* 64- vs 32-bit */\n\tprintBignumChecksum( &bignums[ 6 ] );\n\tDEBUG_PRINT(( \"\\n\" ));\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CREATE_BIGNUM_VALUES */\n\n/* ECC values as pre-encoded bignums, allowing them to be used directly */\n\n#if BN_BITS2 == 64\n\n/* NIST P-256, X9.62 p256r1, SECG p256r1, CRYPT_ECCCURVE_P256 */\n\nstatic const ECC_DOMAINPARAMS p256params = {\n\t/* p */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL,\n\t0x0000000000000000ULL, 0xFFFFFFFF00000001ULL } },\n\t/* a */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFCULL, 0x00000000FFFFFFFFULL,\n\t0x0000000000000000ULL, 0xFFFFFFFF00000001ULL } },\n\t/* b */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3BCE3C3E27D2604BULL, 0x651D06B0CC53B0F6ULL,\n\t0xB3EBBD55769886BCULL, 0x5AC635D8AA3A93E7ULL } },\n\t/* gx */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xF4A13945D898C296ULL, 0x77037D812DEB33A0ULL,\n\t0xF8BCE6E563A440F2ULL, 0x6B17D1F2E12C4247ULL } },\n\t/* gy */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xCBB6406837BF51F5ULL, 0x2BCE33576B315ECEULL,\n\t0x8EE7EB4A7C0F9E16ULL, 0x4FE342E2FE1A7F9BULL } },\n\t/* n */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xF3B9CAC2FC632551ULL, 0xBCE6FAADA7179E84ULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFF00000000ULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0xA72822FA39201D4CULL, 0x77FB7550AD79DEE0ULL, \n\t0x4E550413B3F54BB8ULL, 0xE5D81ACCD382A875ULL,\n\t0xA2C6307087289DE6ULL, 0xBB9E6DDEC3E0E95AULL, \n\t0x26402E6EE1F4833EULL\n\t};\n\n/* Brainpool p256r1, CRYPT_ECCCURVE_BRAINPOOL_P256 */\n\nstatic const ECC_DOMAINPARAMS brainpool256params = {\n\t/* p */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x2013481D1F6E5377ULL, 0x6E3BF623D5262028ULL,\n\t0x3E660A909D838D72ULL, 0xA9FB57DBA1EEA9BCULL } },\n\t/* a */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0xE94A4B44F330B5D9ULL, 0xFB8055C126DC5C6CULL,\n\t0xEEF67530417AFFE7ULL, 0x7D5A0975FC2C3057ULL } },\n\t/* b */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x6BCCDC18FF8C07B6ULL, 0x958416295CF7E1CEULL,\n\t0xF330B5D9BBD77CBFULL, 0x26DC5C6CE94A4B44ULL } },\n\t/* gx */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3A4453BD9ACE3262ULL, 0xB9DE27E1E3BD23C2ULL,\n\t0x2C4B482FFC81B7AFULL, 0x8BD2AEB9CB7E57CBULL } },\n\t/* gy */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x5C1D54C72F046997ULL, 0xC27745132DED8E54ULL,\n\t0x97F8461A14611DC9ULL, 0x547EF835C3DAC4FDULL } },\n\t/* n */\n\t{ 4, FALSE, BN_FLG_STATIC_DATA, {\n\t0x901E0E82974856A7ULL, 0x8C397AA3B561A6F7ULL,\n\t0x3E660A909D838D71ULL, 0xA9FB57DBA1EEA9BCULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0x8C58020DDBF6A665ULL, 0x50890F90EEF60A86ULL, \n\t0xEA0C456931CC1EEFULL, 0x70E10A10445E70FAULL,\n\t0xAD55C5C5D51EC478ULL, 0x2AB6E0C318795E4FULL, \n\t0x26402E6EE1F4833EULL\n\t};\n\n/* NIST P-384, SECG p384r1, CRYPT_ECCCURVE_P384 */\n\nstatic const ECC_DOMAINPARAMS p384params = {\n\t/* p */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000000FFFFFFFFULL, 0xFFFFFFFF00000000ULL,\n\t0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* a */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000000FFFFFFFCULL, 0xFFFFFFFF00000000ULL,\n\t0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* b */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x2A85C8EDD3EC2AEFULL, 0xC656398D8A2ED19DULL,\n\t0x0314088F5013875AULL, 0x181D9C6EFE814112ULL,\n\t0x988E056BE3F82D19ULL, 0xB3312FA7E23EE7E4ULL } },\n\t/* gx */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3A545E3872760AB7ULL, 0x5502F25DBF55296CULL,\n\t0x59F741E082542A38ULL, 0x6E1D3B628BA79B98ULL,\n\t0x8EB1C71EF320AD74ULL, 0xAA87CA22BE8B0537ULL } },\n\t/* gy */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x7A431D7C90EA0E5FULL, 0x0A60B1CE1D7E819DULL,\n\t0xE9DA3113B5F0B8C0ULL, 0xF8F41DBD289A147CULL,\n\t0x5D9E98BF9292DC29ULL, 0x3617DE4A96262C6FULL } },\n\t/* n */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0xECEC196ACCC52973ULL, 0x581A0DB248B0A77AULL,\n\t0xC7634D81F4372DDFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0x9A9A47599E9FA193ULL, 0x8A54B4DE8DBA0429ULL,\n\t0xFB1CEA2E3FFD90F0ULL, 0x14A04AC2065B13E6ULL,\n\t0xBC63FBAFCEB8C35DULL, 0xA679E5A399BA581CULL,\n\t0x26402E6EE1F4833EULL \n\t};\n\n/* Brainpool p384r1, CRYPT_ECCCURVE_BRAINPOOL_P384 */\n\nstatic const ECC_DOMAINPARAMS brainpool384params = {\n\t/* p */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x874700133107EC53ULL, 0xACD3A729901D1A71ULL,\n\t0x12B1DA197FB71123ULL, 0x152F7109ED5456B4ULL,\n\t0x0F5D6F7E50E641DFULL, 0x8CB91E82A3386D28ULL } },\n\t/* a */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x04A8C7DD22CE2826ULL, 0x8AA5814A503AD4EBULL,\n\t0x139165EFBA91F90FULL, 0xC2BEA28E4FB22787ULL,\n\t0x3C72080ACE05AFA0ULL, 0x7BC382C63D8C150CULL } },\n\t/* b */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3AB78696FA504C11ULL, 0x7CB4390295DBC994ULL,\n\t0x2E880EA53EEB62D5ULL, 0x2FB77DE107DCD2A6ULL,\n\t0x8B39B55416F0447CULL, 0x04A8C7DD22CE2826ULL } },\n\t/* gx */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0xEF87B2E247D4AF1EULL, 0xE826E03436D646AAULL,\n\t0xDB7FCAFE0CBD10E8ULL, 0x8847A3E77EF14FE3ULL,\n\t0xA2A63A81B7C13F6BULL, 0x1D1C64F068CF45FFULL } },\n\t/* gy */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x42820341263C5315ULL, 0x0E46462177918111ULL,\n\t0xE19C054FF9912928ULL, 0x62B70B29FEEC5864ULL,\n\t0x5CB1EB8E95CFD552ULL, 0x8ABE1D7520F9C2A4ULL } },\n\t/* n */\n\t{ 6, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3B883202E9046565ULL, 0xCF3AB6AF6B7FC310ULL,\n\t0x1F166E6CAC0425A7ULL, 0x152F7109ED5456B3ULL,\n\t0x0F5D6F7E50E641DFULL, 0x8CB91E82A3386D28ULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0x6A9E0847ABC8E154ULL, 0x61C83241A722DD92ULL,\n\t0xD325B1754DE15E11ULL, 0x350A61B48CD1B7F9ULL,\n\t0xFAB31A42AC6B58C9ULL, 0xE36D9145DA891AF4ULL,\n\t0x26402E6EE1F4833EULL\n\t};\n\n/* NIST P-521, SECG p521r1, CRYPT_ECCCURVE_P521 */\n\nstatic const ECC_DOMAINPARAMS p521params = {\n\t/* p */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0x00000000000001FFULL } },\n\t/* a */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFFFFFFFFFCULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0x00000000000001FFULL } },\n\t/* b */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0xEF451FD46B503F00ULL, 0x3573DF883D2C34F1ULL,\n\t0x1652C0BD3BB1BF07ULL, 0x56193951EC7E937BULL,\n\t0xB8B489918EF109E1ULL, 0xA2DA725B99B315F3ULL,\n\t0x929A21A0B68540EEULL, 0x953EB9618E1C9A1FULL,\n\t0x0000000000000051ULL } },\n\t/* gx */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0xF97E7E31C2E5BD66ULL, 0x3348B3C1856A429BULL,\n\t0xFE1DC127A2FFA8DEULL, 0xA14B5E77EFE75928ULL,\n\t0xF828AF606B4D3DBAULL, 0x9C648139053FB521ULL,\n\t0x9E3ECB662395B442ULL, 0x858E06B70404E9CDULL,\n\t0x00000000000000C6ULL } },\n\t/* gy */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0x88BE94769FD16650ULL, 0x353C7086A272C240ULL,\n\t0xC550B9013FAD0761ULL, 0x97EE72995EF42640ULL,\n\t0x17AFBD17273E662CULL, 0x98F54449579B4468ULL,\n\t0x5C8A5FB42C7D1BD9ULL, 0x39296A789A3BC004ULL,\n\t0x0000000000000118ULL } },\n\t/* n */\n\t{ 9, FALSE, BN_FLG_STATIC_DATA, {\n\t0xBB6FB71E91386409ULL, 0x3BB5C9B8899C47AEULL,\n\t0x7FCC0148F709A5D0ULL, 0x51868783BF2F966BULL,\n\t0xFFFFFFFFFFFFFFFAULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,\n\t0x00000000000001FFULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0xDA99C55253FF5436ULL, 0x2847E17D2F34D05BULL,\n\t0x11D14F0DFE0C6BF1ULL, 0x5F95A0E0F9B321C8ULL,\n\t0x2EEA29DDC3441128ULL, 0x2595D584A94B217DULL,\n\t0x26402E6EE1F4833EULL\n\t};\n\n/* Brainpool p512r1, CRYPT_ECCCURVE_BRAINPOOL_P512 */\n\nstatic const ECC_DOMAINPARAMS brainpool512params = {\n\t/* p */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x28AA6056583A48F3ULL, 0x2881FF2F2D82C685ULL,\n\t0xAECDA12AE6A380E6ULL, 0x7D4D9B009BC66842ULL,\n\t0xD6639CCA70330871ULL, 0xCB308DB3B3C9D20EULL,\n\t0x3FD4E6AE33C9FC07ULL, 0xAADD9DB8DBE9C48BULL } },\n\t/* a */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xE7C1AC4D77FC94CAULL, 0x7F1117A72BF2C7B9ULL,\n\t0x0A2EF1C98B9AC8B5ULL, 0x2DED5D5AA8253AA1ULL,\n\t0xA83441CAEA9863BCULL, 0x94CBDD8D3DF91610ULL,\n\t0xE2327145AC234CC5ULL, 0x7830A3318B603B89ULL } },\n\t/* b */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x2809BD638016F723ULL, 0x984050B75EBAE5DDULL,\n\t0x77FC94CADC083E67ULL, 0x2BF2C7B9E7C1AC4DULL,\n\t0x8B9AC8B57F1117A7ULL, 0xA8253AA10A2EF1C9ULL,\n\t0xEA9863BC2DED5D5AULL, 0x3DF91610A83441CAULL } },\n\t/* gx */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x8B352209BCB9F822ULL, 0x7C6D5047406A5E68ULL,\n\t0x50D1687B93B97D5FULL, 0xFF3B1F78E2D0D48DULL,\n\t0xB43B62EEF4D0098EULL, 0x85ED9F70B5D916C1ULL,\n\t0x5A21322E9C4C6A93ULL, 0x81AEE4BDD82ED964ULL } },\n\t/* gy */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x78CD1E0F3AD80892ULL, 0xD1CA2B2FA8F05406ULL,\n\t0x5BCA4BD88A2763AEULL, 0xB2DCDE494A5F485EULL,\n\t0xA000C55B881F8111ULL, 0xF209F70024A57B1AULL,\n\t0xC0EABFA9CF7822FDULL, 0x7DDE385D566332ECULL } },\n\t/* n */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xB58796829CA90069ULL, 0x1DB1D381085DDADDULL,\n\t0x418661197FAC1047ULL, 0x553E5C414CA92619ULL,\n\t0xD6639CCA70330870ULL, 0xCB308DB3B3C9D20EULL,\n\t0x3FD4E6AE33C9FC07ULL, 0xAADD9DB8DBE9C48BULL } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x0000000000000001ULL } },\n\t/* Checksums */\n\t0xC1DA14200D9335A0ULL, 0x0576ECE4ABA7F09BULL,\n\t0x4319F6256D8AAFCFULL, 0x1042D928E89F3778ULL,\n\t0x0A26038C333433C3ULL, 0x1B30D8586B566AFDULL,\n\t0x26402E6EE1F4833EULL\n\t};\n\n#else\n\n/* NIST P-256, X9.62 p256r1, SECG p256r1, CRYPT_ECCCURVE_P256 */\n\nstatic const ECC_DOMAINPARAMS p256params = { \n\t/* p */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, \n\t0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF } },\n\t/* a */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, \n\t0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF } },\n\t/* b */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x27D2604B, 0x3BCE3C3E, 0xCC53B0F6, 0x651D06B0, \n\t0x769886BC, 0xB3EBBD55, 0xAA3A93E7, 0x5AC635D8 } },\n\t/* gx */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xD898C296, 0xF4A13945, 0x2DEB33A0, 0x77037D81, \n\t0x63A440F2, 0xF8BCE6E5, 0xE12C4247, 0x6B17D1F2 } },\n\t/* gy */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x37BF51F5, 0xCBB64068, 0x6B315ECE, 0x2BCE3357, \n\t0x7C0F9E16, 0x8EE7EB4A, 0xFE1A7F9B, 0x4FE342E2 } },\n\t/* n */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFC632551, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0xF3897EFA, 0xA860F782, 0x3994862C, 0x1E8D2321, \n\t0x15B99322, 0x4943FE0A, 0x75E7E997 \n\t};\n\n/* Brainpool p256r1, CRYPT_ECCCURVE_BRAINPOOL_P256 */\n\nstatic const ECC_DOMAINPARAMS brainpool256params = { \n\t/* p */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x1F6E5377, 0x2013481D, 0xD5262028, 0x6E3BF623, \n\t0x9D838D72, 0x3E660A90, 0xA1EEA9BC, 0xA9FB57DB } },\n\t/* a */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xF330B5D9, 0xE94A4B44, 0x26DC5C6C, 0xFB8055C1, \n\t0x417AFFE7, 0xEEF67530, 0xFC2C3057, 0x7D5A0975 } },\n\t/* b */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFF8C07B6, 0x6BCCDC18, 0x5CF7E1CE, 0x95841629, \n\t0xBBD77CBF, 0xF330B5D9, 0xE94A4B44, 0x26DC5C6C } },\n\t/* gx */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x9ACE3262, 0x3A4453BD, 0xE3BD23C2, 0xB9DE27E1, \n\t0xFC81B7AF, 0x2C4B482F, 0xCB7E57CB, 0x8BD2AEB9 } },\n\t/* gy */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x2F046997, 0x5C1D54C7, 0x2DED8E54, 0xC2774513, \n\t0x14611DC9, 0x97F8461A, 0xC3DAC4FD, 0x547EF835 } },\n\t/* n */\n\t{ 8, FALSE, BN_FLG_STATIC_DATA, {\n\t0x974856A7, 0x901E0E82, 0xB561A6F7, 0x8C397AA3, \n\t0x9D838D71, 0x3E660A90, 0xA1EEA9BC, 0xA9FB57DB } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0x3498DCF4, 0x3BCBEBC2, 0x69495E03, 0x2AD8069D, \n\t0x11DAF3CF, 0xCA928D15, 0x75E7E997\n\t};\n\n/* NIST P-384, SECG p384r1, CRYPT_ECCCURVE_P384 */\n\nstatic const ECC_DOMAINPARAMS p384params = { \n\t/* p */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, \n\t0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* a */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFC, 0x00000000, 0x00000000, 0xFFFFFFFF, \n\t0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* b */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xD3EC2AEF, 0x2A85C8ED, 0x8A2ED19D, 0xC656398D, \n\t0x5013875A, 0x0314088F, 0xFE814112, 0x181D9C6E, \n\t0xE3F82D19, 0x988E056B, 0xE23EE7E4, 0xB3312FA7 } },\n\t/* gx */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x72760AB7, 0x3A545E38, 0xBF55296C, 0x5502F25D, \n\t0x82542A38, 0x59F741E0, 0x8BA79B98, 0x6E1D3B62, \n\t0xF320AD74, 0x8EB1C71E, 0xBE8B0537, 0xAA87CA22 } },\n\t/* gy */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x90EA0E5F, 0x7A431D7C, 0x1D7E819D, 0x0A60B1CE, \n\t0xB5F0B8C0, 0xE9DA3113, 0x289A147C, 0xF8F41DBD, \n\t0x9292DC29, 0x5D9E98BF, 0x96262C6F, 0x3617DE4A } },\n\t/* n */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xCCC52973, 0xECEC196A, 0x48B0A77A, 0x581A0DB2, \n\t0xF4372DDF, 0xC7634D81, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0x7D715AAC, 0x1FC7CA5A, 0x114D671D, 0x9173FBBF, \n\t0x26E973C0, 0x8D05F26F, 0x75E7E997 \n\t};\n\n/* Brainpool p384r1, CRYPT_ECCCURVE_BRAINPOOL_P384 */\n\nstatic const ECC_DOMAINPARAMS brainpool384params = { \n\t/* p */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3107EC53, 0x87470013, 0x901D1A71, 0xACD3A729, \n\t0x7FB71123, 0x12B1DA19, 0xED5456B4, 0x152F7109, \n\t0x50E641DF, 0x0F5D6F7E, 0xA3386D28, 0x8CB91E82 } },\n\t/* a */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x22CE2826, 0x04A8C7DD, 0x503AD4EB, 0x8AA5814A, \n\t0xBA91F90F, 0x139165EF, 0x4FB22787, 0xC2BEA28E, \n\t0xCE05AFA0, 0x3C72080A, 0x3D8C150C, 0x7BC382C6 } },\n\t/* b */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFA504C11, 0x3AB78696, 0x95DBC994, 0x7CB43902, \n\t0x3EEB62D5, 0x2E880EA5, 0x07DCD2A6, 0x2FB77DE1, \n\t0x16F0447C, 0x8B39B554, 0x22CE2826, 0x04A8C7DD } },\n\t/* gx */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x47D4AF1E, 0xEF87B2E2, 0x36D646AA, 0xE826E034, \n\t0x0CBD10E8, 0xDB7FCAFE, 0x7EF14FE3, 0x8847A3E7, \n\t0xB7C13F6B, 0xA2A63A81, 0x68CF45FF, 0x1D1C64F0 } },\n\t/* gy */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0x263C5315, 0x42820341, 0x77918111, 0x0E464621, \n\t0xF9912928, 0xE19C054F, 0xFEEC5864, 0x62B70B29, \n\t0x95CFD552, 0x5CB1EB8E, 0x20F9C2A4, 0x8ABE1D75 } },\n\t/* n */\n\t{ 12, FALSE, BN_FLG_STATIC_DATA, {\n\t0xE9046565, 0x3B883202, 0x6B7FC310, 0xCF3AB6AF, \n\t0xAC0425A7, 0x1F166E6C, 0xED5456B3, 0x152F7109, \n\t0x50E641DF, 0x0F5D6F7E, 0xA3386D28, 0x8CB91E82 } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0xA104D6F2, 0x0154CB82, 0xF8B07960, 0xACC086CC, \n\t0x7F4924D6, 0x0B03676F, 0x75E7E997 \n\t};\n\n/* NIST P-521, SECG p521r1, CRYPT_ECCCURVE_P521 */\n\nstatic const ECC_DOMAINPARAMS p521params = { \n\t/* p */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0x000001FF } },\n\t/* a */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0x000001FF } },\n\t/* b */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0x6B503F00, 0xEF451FD4, 0x3D2C34F1, 0x3573DF88, \n\t0x3BB1BF07, 0x1652C0BD, 0xEC7E937B, 0x56193951, \n\t0x8EF109E1, 0xB8B48991, 0x99B315F3, 0xA2DA725B, \n\t0xB68540EE, 0x929A21A0, 0x8E1C9A1F, 0x953EB961, \n\t0x00000051 } },\n\t/* gx */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0xC2E5BD66, 0xF97E7E31, 0x856A429B, 0x3348B3C1, \n\t0xA2FFA8DE, 0xFE1DC127, 0xEFE75928, 0xA14B5E77, \n\t0x6B4D3DBA, 0xF828AF60, 0x053FB521, 0x9C648139, \n\t0x2395B442, 0x9E3ECB66, 0x0404E9CD, 0x858E06B7, \n\t0x000000C6 } },\n\t/* gy */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0x9FD16650, 0x88BE9476, 0xA272C240, 0x353C7086, \n\t0x3FAD0761, 0xC550B901, 0x5EF42640, 0x97EE7299, \n\t0x273E662C, 0x17AFBD17, 0x579B4468, 0x98F54449, \n\t0x2C7D1BD9, 0x5C8A5FB4, 0x9A3BC004, 0x39296A78, \n\t0x00000118 } },\n\t/* n */\n\t{ 17, FALSE, BN_FLG_STATIC_DATA, {\n\t0x91386409, 0xBB6FB71E, 0x899C47AE, 0x3BB5C9B8, \n\t0xF709A5D0, 0x7FCC0148, 0xBF2F966B, 0x51868783, \n\t0xFFFFFFFA, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \n\t0x000001FF } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0xF0CB48FC, 0xC89C4882, 0xB1A12B3C, 0x22B097CC, \n\t0xEE2FFB2E, 0xA2E7127F, 0x75E7E997 \n\t};\n\n/* Brainpool p512r1, CRYPT_ECCCURVE_BRAINPOOL_P512 */\n\nstatic const ECC_DOMAINPARAMS brainpool512params = { \n\t/* p */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0x583A48F3, 0x28AA6056, 0x2D82C685, 0x2881FF2F, \n\t0xE6A380E6, 0xAECDA12A, 0x9BC66842, 0x7D4D9B00, \n\t0x70330871, 0xD6639CCA, 0xB3C9D20E, 0xCB308DB3, \n\t0x33C9FC07, 0x3FD4E6AE, 0xDBE9C48B, 0xAADD9DB8 } },\n\t/* a */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0x77FC94CA, 0xE7C1AC4D, 0x2BF2C7B9, 0x7F1117A7, \n\t0x8B9AC8B5, 0x0A2EF1C9, 0xA8253AA1, 0x2DED5D5A, \n\t0xEA9863BC, 0xA83441CA, 0x3DF91610, 0x94CBDD8D, \n\t0xAC234CC5, 0xE2327145, 0x8B603B89, 0x7830A331 } },\n\t/* b */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0x8016F723, 0x2809BD63, 0x5EBAE5DD, 0x984050B7, \n\t0xDC083E67, 0x77FC94CA, 0xE7C1AC4D, 0x2BF2C7B9, \n\t0x7F1117A7, 0x8B9AC8B5, 0x0A2EF1C9, 0xA8253AA1, \n\t0x2DED5D5A, 0xEA9863BC, 0xA83441CA, 0x3DF91610 } },\n\t/* gx */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0xBCB9F822, 0x8B352209, 0x406A5E68, 0x7C6D5047, \n\t0x93B97D5F, 0x50D1687B, 0xE2D0D48D, 0xFF3B1F78, \n\t0xF4D0098E, 0xB43B62EE, 0xB5D916C1, 0x85ED9F70, \n\t0x9C4C6A93, 0x5A21322E, 0xD82ED964, 0x81AEE4BD } },\n\t/* gy */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0x3AD80892, 0x78CD1E0F, 0xA8F05406, 0xD1CA2B2F, \n\t0x8A2763AE, 0x5BCA4BD8, 0x4A5F485E, 0xB2DCDE49, \n\t0x881F8111, 0xA000C55B, 0x24A57B1A, 0xF209F700, \n\t0xCF7822FD, 0xC0EABFA9, 0x566332EC, 0x7DDE385D } },\n\t/* n */\n\t{ 16, FALSE, BN_FLG_STATIC_DATA, {\n\t0x9CA90069, 0xB5879682, 0x085DDADD, 0x1DB1D381, \n\t0x7FAC1047, 0x41866119, 0x4CA92619, 0x553E5C41, \n\t0x70330870, 0xD6639CCA, 0xB3C9D20E, 0xCB308DB3, \n\t0x33C9FC07, 0x3FD4E6AE, 0xDBE9C48B, 0xAADD9DB8 } },\n\t/* h */\n\t{ 1, FALSE, BN_FLG_STATIC_DATA, {\n\t0x00000001 } },\n\t/* Checksums */\n\t0x8A2C6186, 0x8FBBE214, 0x60D7593D, 0x02F580D8, \n\t0xD6823856, 0xBD31D0D9, 0x75E7E997 \n\t};\n#endif /* 64- vs 32-bit */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tECC Access Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the bignums for the domain parameter values { p, a, b, gx, gy, \n   n }.  Note that although the cofactor h is given for the standard named \n   curves it's not used for any ECC operations, so we could quite easily \n   omit it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint loadECCparams( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t   IN_ENUM( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE curveType )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst ECC_DOMAINPARAMS *domainParams;\n\tint curveSizeBits, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isEnumRange( curveType, CRYPT_ECCCURVE ) );\n\n\t/* Convert the fixed-format bignums to encoded BIGNUMs */\n#ifdef CREATE_BIGNUM_VALUES\n\tstatus = loadECCparamsFixed( contextInfoPtr, CRYPT_ECCCURVE_P256 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#endif /* CREATE_BIGNUM_VALUES */\n\n\t/* Get the requested domain parameters */\n\tswitch( curveType )\n\t\t{\n\t\tcase CRYPT_ECCCURVE_P256:\n\t\t\tdomainParams = &p256params;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_BRAINPOOL_P256:\n\t\t\tdomainParams = &brainpool256params;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_P384:\n\t\t\tdomainParams = &p384params;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_BRAINPOOL_P384:\n\t\t\tdomainParams = &brainpool384params;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_P521:\n\t\t\tdomainParams = &p521params;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_BRAINPOOL_P512:\n\t\t\tdomainParams = &brainpool512params;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* For the named curve the key size is defined by exective fiat based\n\t   on the curve type rather than being taken from the public-key value \n\t   (which in this case is the magnitude of the point Q on the curve), so \n\t   we set it explicitly based on the curve type */\n\tstatus = getECCFieldSize( curveType, &curveSizeBits, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpkcInfo->curveType = curveType;\n\tpkcInfo->keySizeBits = curveSizeBits;\n\n\t/* Make sure that the domain parameters are in order */\n\tif( !checksumDomainParameters( domainParams, TRUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"ECC domain parameters for curve ID %d key has been \"\n\t\t\t\t\t \"corrupted\", curveType ));\n\t\tretIntError();\n\t\t}\n\n\tpkcInfo->domainParams = domainParams;\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bnrw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Bignum Import/Export Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Dump a bignum as a C structure, used for hardcoding constant values like\n   DLP and ECDLP domain parameters from their bignum representations */\n\n#if defined( DEBUG_DIAGNOSTIC_ENABLE ) && !defined( NDEBUG )\n\n#if BN_BITS2 == 64\n  #define BNULONG_FORMAT\t\"0x%016llXULL\"\n  #define BNULONG_PER_LINE\t2\n#else\n  #define BNULONG_FORMAT\t\"0x%08X\"\n  #define BNULONG_PER_LINE\t4\n#endif /* 64- vs 32-bit */\n\nvoid printBignum( const BIGNUM *bignum, const char *label )\n\t{\n\tconst BN_ULONG *data = bignum->d;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( label, 2 ) );\n\n\tDEBUG_PRINT(( \"\\t/* %s */\\n\\t\", label ));\n\tDEBUG_PRINT(( \"{ BIGNUM_ALLOC_WORDS, %d, FALSE, BN_FLG_STATIC_DATA, {\\n\\t\", \n\t\t\t\t  bignum->top ));\n\tLOOP_EXT( i = 0, i < bignum->top, i++, BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tDEBUG_PRINT(( BNULONG_FORMAT, data[ i ] ));\n\t\tif( i < bignum->top - 1 )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \", \" ));\n\t\t\tif( i > 0 && !( ( i + 1 ) & ( BNULONG_PER_LINE - 1 ) ) )\n\t\t\t\tDEBUG_PRINT(( \"\\n\\t\" ));\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tDEBUG_PRINT(( \" } },\\n\" ));\n\t}\n#endif /* DEBUG_DIAGNOSTIC_ENABLE && Debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tBignum Import Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that an imported bignum value is valid */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkBignum( const BIGNUM *bignum,\n\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\tIN_OPT const BIGNUM *maxRange,\n\t\t\t\t\t\tIN_ENUM_OPT( KEYSIZE_CHECK_SPECIAL ) \\\n\t\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tint bignumLengthBits, status;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( minLength > 0 && minLength <= maxLength && \\\n\t\t\t  maxLength <= CRYPT_MAX_PKCSIZE + \\\n\t\t\t\t\t\t   ( ( checkType == KEYSIZE_CHECK_SPECIAL ) ? \\\n\t\t\t\t\t\t\t   DLP_OVERFLOW_SIZE : 0 ) );\n\tREQUIRES( maxRange == NULL || sanityCheckBignum( maxRange ) );\n\tREQUIRES( checkType >= KEYSIZE_CHECK_NONE && \\\n\t\t\t  checkType < KEYSIZE_CHECK_SPECIAL_LAST );\n\n\t/* The following should never happen because BN_bin2bn() works with \n\t   unsigned values but we perform the check anyway just in case someone \n\t   messes with the underlying bignum code */\n\tENSURES( !( BN_is_negative( bignum ) ) )\n\n\t/* A zero- or one-valued bignum on the other hand is an error because we \n\t   should never find zero or one in a PKC-related value.  This check is \n\t   somewhat redundant with the one that follows, we place it here to \n\t   make it explicit and because the cost is near zero */\n\tif( BN_cmp_word( bignum, 1 ) <= 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Check that the bignum value falls within the allowed length range.  \n\t   Before we do the general length check we perform a more specific \n\t   check for the case where the length is below the minimum allowed but \n\t   still looks at least vaguely valid, in which case we report it as a \n\t   too-short key rather than a bad data error.\n\t   \n\t   Note that we check the length in bits rather than bytes since the \n\t   latter is rounded up, so a length that passes the check based on\n\t   its rounded-up byte-length value can then fail a later check based \n\t   on its actual length in bits */\n\tstatus = bignumLengthBits = BN_num_bits( bignum );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( checkType )\n\t\t{\n\t\tcase KEYSIZE_CHECK_NONE:\n\t\t\t/* No specific weak-key check for this value */\n\t\t\tbreak;\n\n\t\tcase KEYSIZE_CHECK_PKC:\n\t\t\tif( isShortPKCKey( bitsToBytes( bignumLengthBits ) ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\tbreak;\n\n\t\tcase KEYSIZE_CHECK_ECC:\n\t\t\tif( isShortECCKey( bitsToBytes( bignumLengthBits ) ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\tbreak;\n\n\t\tcase KEYSIZE_CHECK_SPECIAL:\n\t\t\t/* This changes the upper bound of the check rather than the \n\t\t\t   lower bound so there's no special check required */\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Check that the value is within range.  We have to be a bit careful\n\t   here when doing a bit-length based comparison because the minimum\n\t   length that can be specified as a byte is 8 bits, so if minLength == 1\n\t   then we allow any bit-length >= 2 bits, used for DH g values */\n\tif( minLength == 1 )\n\t\t{\n\t\tif( bignumLengthBits < 2 || \\\n\t\t\tbignumLengthBits > bytesToBits( maxLength ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\telse\n\t\t{\n\t\tif( bignumLengthBits < bytesToBits( minLength ) || \\\n\t\t\tbignumLengthBits > bytesToBits( maxLength ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Finally, if the caller has supplied a maximum-range bignum value, \n\t   make sure that the value that we've read is less than this */\n\tif( maxRange != NULL && BN_cmp( bignum, maxRange ) >= 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Import a bignum from a buffer.  This is a low-level internal routine also\n   used by the OpenSSL bignum code, the non-cryptlib-style API is for \n   compatibility purposes */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nBIGNUM *BN_bin2bn( IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t   IN_LENGTH_PKC_Z const int length, \n\t\t\t\t   OUT BIGNUM *bignum )\n\t{\n\tint byteCount, wordIndex, index = 0, bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( length == 0 || isReadPtrDynamic( buffer, length ) );\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_N( length >= 0 && length <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_N( sanityCheckBignum( bignum ) );\n\n\t/* Clear return value */\n\tBN_clear( bignum );\n\n\t/* Bignums with value zero are special-cased since they have a length of\n\t   zero */\n\tif( length <= 0 )\n\t\treturn( bignum );\n\n\t/* Walk down the bignum a word at a time adding the data bytes */\n\tbignum->top = ( ( length - 1 ) / BN_BYTES ) + 1;\n\tLOOP_EXT( ( byteCount = length, wordIndex = bignum->top - 1 ), \n\t\t\t  byteCount > 0 && wordIndex >= 0, wordIndex--, \n\t\t\t  BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tBN_ULONG value = 0;\n\t\tint noBytes = ( ( byteCount - 1 ) % BN_BYTES ) + 1;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tbyteCount -= noBytes;\n\t\tLOOP_EXT_CHECKINC_ALT( noBytes > 0, noBytes--, BN_BYTES + 1 )\n\t\t\t{\n\t\t\tvalue = ( value << 8 ) | buffer[ index++ ];\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK_ALT );\n\t\tbignum->d[ wordIndex ] = value;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( wordIndex == -1 && byteCount == 0 );\n\n\t/* Now that we've imported the raw data value, convert it to \n\t   normalised form */\n\tCK( BN_normalise( bignum ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( NULL );\n\n\tENSURES_N( sanityCheckBignum( bignum ) );\n\n\treturn( bignum );\n\t}\n\n/* Convert a byte string to a BIGNUM value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint importBignum( INOUT TYPECAST( BIGNUM * ) void *bignumPtr, \n\t\t\t\t  IN_BUFFER( length ) const void *buffer, \n\t\t\t\t  IN_LENGTH_SHORT const int length,\n\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t  IN_RANGE( 1, CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE ) \\\n\t\t\t\t\t\tconst int maxLength,\n\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRangePtr,\n\t\t\t\t  IN_ENUM_OPT( KEYSIZE_CHECK_SPECIAL ) \\\n\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tBIGNUM *bignum = ( BIGNUM * ) bignumPtr;\n\tBIGNUM *maxRange = ( BIGNUM * ) maxRangePtr;\n\tint status;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( isShortIntegerRange( length ) );\n\tREQUIRES( minLength > 0 && minLength <= maxLength && \\\n\t\t\t  maxLength <= CRYPT_MAX_PKCSIZE + \\\n\t\t\t\t\t\t   ( ( checkType == KEYSIZE_CHECK_SPECIAL ) ? \\\n\t\t\t\t\t\t\t   DLP_OVERFLOW_SIZE : 0 ) );\n\tREQUIRES( maxRange == NULL || sanityCheckBignum( maxRange ) );\n\tREQUIRES( checkType >= KEYSIZE_CHECK_NONE && \\\n\t\t\t  checkType < KEYSIZE_CHECK_SPECIAL_LAST );\n\n\t/* Make sure that we've been given valid input.  This should already \n\t   have been checked by the caller using far more specific checks than \n\t   the very generic values that we use here, but we perform the check \n\t   anyway just to be sure */\n\tif( length < 1 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( checkType == KEYSIZE_CHECK_SPECIAL )\n\t\t{\n\t\tif( length > CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\telse\n\t\t{\n\t\tif( length > CRYPT_MAX_PKCSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Convert the byte string into a bignum.  Since the only thing that \n\t   this does is format a string of bytes as a BN_ULONGs, the only\n\t   failure that can occur is a CRYPT_ERROR_INTERNAL */\n\tif( BN_bin2bn( buffer, length, bignum ) == NULL )\n\t\t{\n\t\tBN_clear( bignum );\n\t\treturn( CRYPT_ERROR_INTERNAL );\n\t\t}\n\n\t/* Check the value that we've just imported */\n\tstatus = checkBignum( bignum, minLength, maxLength, maxRange, \n\t\t\t\t\t\t  checkType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tBN_clear( bignum );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckBignum( bignum ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Verify that a bignum value corresponds to encoded bignum data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN verifyBignumImport( TYPECAST( const BIGNUM * ) const void *bignumPtr, \n\t\t\t\t\t\t\tIN_BUFFER( length ) const void *buffer, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int length )\n\t{\n\tconst BIGNUM *bignum = ( BIGNUM * ) bignumPtr;\n\tconst BYTE *bufPtr = buffer;\n\tint byteCount, wordIndex, index = 0, LOOP_ITERATOR;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES_B( sanityCheckBignum( bignum ) );\n\tREQUIRES_B( isShortIntegerRange( length ) );\n\n\t/* Walk down the bignum a word at a time verifying that the data bytes \n\t   correspond to the bignum words.  We can't check bignum->top since the\n\t   bignum is normalised on import, so it may not correspond exactly to \n\t   the data length in bytes */\n\tLOOP_EXT( ( byteCount = length, wordIndex = bignum->top - 1 ), \n\t\t\t  byteCount > 0 && wordIndex >= 0, wordIndex--, \n\t\t\t  BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tBN_ULONG value = 0;\n\t\tint noBytes = ( ( byteCount - 1 ) % BN_BYTES ) + 1;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tbyteCount -= noBytes;\n\t\tLOOP_EXT_CHECKINC_ALT( noBytes > 0, noBytes--, BN_BYTES + 1 )\n\t\t\t{\n\t\t\tvalue = ( value << 8 ) | bufPtr[ index++ ];\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tif( bignum->d[ wordIndex ] != value )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Bignum data memory corruption detected at word %d\", \n\t\t\t\t\t\t wordIndex ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( wordIndex == -1 && byteCount == 0 );\n\n\tENSURES_B( sanityCheckBignum( bignum ) );\n\n\treturn( TRUE );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* Convert a byte string to an ECC point */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint importECCPoint( INOUT TYPECAST( BIGNUM * ) void *bignumPtr1, \n\t\t\t\t\tINOUT TYPECAST( BIGNUM * ) void *bignumPtr2, \n\t\t\t\t    IN_BUFFER( length ) const void *buffer, \n\t\t\t\t    IN_LENGTH_SHORT const int length,\n\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\tIN_LENGTH_PKC const int maxLength, \n\t\t\t\t\tIN_LENGTH_PKC const int fieldSize,\n\t\t\t\t\tIN_OPT const void *maxRangePtr,\n\t\t\t\t\tIN_ENUM( KEYSIZE_CHECK ) \\\n\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tconst BYTE *eccPointData = buffer;\n\tBIGNUM *bignum1 = ( BIGNUM * ) bignumPtr1;\n\tBIGNUM *bignum2 = ( BIGNUM * ) bignumPtr2;\n\tBIGNUM *maxRange = ( BIGNUM * ) maxRangePtr;\n\tint status;\n\n\tassert( isWritePtr( bignum1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( bignum2, sizeof( BIGNUM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum1 ) );\n\tREQUIRES( sanityCheckBignum( bignum2 ) );\n\tREQUIRES( minLength > 0 && minLength <= maxLength && \\\n\t\t\t  maxLength <= CRYPT_MAX_PKCSIZE_ECC );\n\tREQUIRES( fieldSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t  fieldSize <= CRYPT_MAX_PKCSIZE_ECC );\n\tREQUIRES( maxRange == NULL || sanityCheckBignum( maxRange ) );\n\tREQUIRES( isEnumRangeOpt( checkType, KEYSIZE_CHECK ) );\n\n\t/* Make sure that we've been given valid input.  This should already \n\t   have been checked by the caller using far more specific checks than \n\t   the very generic values that we use here, but we perform the check \n\t   anyway just to be sure */\n\tif( length < MIN_PKCSIZE_ECCPOINT_THRESHOLD || \\\n\t\tlength > MAX_PKCSIZE_ECCPOINT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Decode the ECC point data.  At this point we run into another \n\t   artefact of the chronic indecisiveness of the ECC standards authors, \n\t   because of the large variety of ways in which ECC data can be encoded \n\t   there's no single way of representing a point.  The only encoding \n\t   that's actually of any practical use is the straight (x, y) \n\t   coordinate form with no special-case encoding or other tricks, \n\t   denoted by an 0x04 byte at the start of the data:\n\n\t\t+---+---------------+---------------+\n\t\t|ID\t|\t\tqx\t\t|\t\tqy\t\t|\n\t\t+---+---------------+---------------+\n\t\t\t|<- fldSize --> |<- fldSize --> |\n\n\t   There's also a hybrid form that combines the patent encumbrance of \n\t   point compression with the size of the uncompressed form that we \n\t   could in theory allow for, but it's unlikely that anyone's going to\n\t   be crazy enough to use this */\n\tif( length != 1 + ( fieldSize * 2 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( eccPointData[ 0 ] != 0x04 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\teccPointData++;\t\t/* Skip format type byte */\n\tstatus = importBignum( bignum1, eccPointData, fieldSize,\n\t\t\t\t\t\t   minLength, maxLength, maxRange, checkType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importBignum( bignum2, eccPointData + fieldSize, fieldSize, \n\t\t\t\t\t\t   minLength, maxLength, maxRange, checkType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tBN_clear( bignum1 );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckBignum( bignum1 ) );\n\tENSURES( sanityCheckBignum( bignum2 ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tBignum Export Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export a bignum to a buffer.  This is a low-level internal routine also\n   used by the OpenSSL bignum code, the non-cryptlib-style API is for \n   compatibility purposes */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint BN_bn2bin( const BIGNUM *bignum, BYTE *buffer )\n\t{\n\tconst int length = BN_num_bytes( bignum );\n\tint byteCount, wordIndex, index = 0, LOOP_ITERATOR;\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( length >= 0 && length <= CRYPT_MAX_PKCSIZE );\n\n\t/* Walk down the bignum a word at a time extracting the data bytes */\n\tLOOP_EXT( ( byteCount = length, wordIndex = bignum->top - 1 ),\n\t\t\t  byteCount > 0 && wordIndex >= 0, wordIndex--, \n\t\t\t  BIGNUM_ALLOC_WORDS )\n\t\t{\n\t\tconst BN_ULONG value = bignum->d[ wordIndex ];\n\t\tint noBytes = ( ( byteCount - 1 ) % BN_BYTES ) + 1;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tbyteCount -= noBytes;\n\t\tLOOP_EXT_CHECKINC_ALT( noBytes > 0, noBytes--, BN_BYTES + 1 )\n\t\t\t{\n\t\t\tconst int shiftAmount = ( noBytes - 1 ) * 8;\n\n\t\t\tbuffer[ index++ ] = intToByte( value >> shiftAmount );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( wordIndex == -1 && byteCount == 0 );\n\n\treturn( length );\n\t}\n\n/* Convert a BIGNUM value to a byte string */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint exportBignum( OUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) int *dataLength,\n\t\t\t\t  IN TYPECAST( BIGNUM * ) const void *bignumPtr )\n\t{\n\tBIGNUM *bignum = ( BIGNUM * ) bignumPtr;\n\tint length, result;\n\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* Make sure that the result will fit into the output buffer */\n\tlength = BN_num_bytes( bignum );\n\tENSURES( length > 0 && length <= CRYPT_MAX_PKCSIZE );\n\tif( length > dataMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Export the bignum into the output buffer */\n\tresult = BN_bn2bin( bignum, data );\n\tENSURES( result == length );\n\t*dataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* Convert an ECC point to a byte string */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4, 5 ) ) \\\nint exportECCPoint( OUT_BUFFER_OPT( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_PKC_Z( dataMaxLength ) int *dataLength,\n\t\t\t\t\tIN TYPECAST( BIGNUM * ) const void *bignumPtr1, \n\t\t\t\t\tIN TYPECAST( BIGNUM * ) const void *bignumPtr2,\n\t\t\t\t\tIN_LENGTH_PKC const int fieldSize )\n\t{\n\tBIGNUM *bignum1 = ( BIGNUM * ) bignumPtr1;\n\tBIGNUM *bignum2 = ( BIGNUM * ) bignumPtr2;\n\tBYTE *bufPtr = data;\n\tint length, result;\n\n\tassert( data == NULL || isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\tassert( isReadPtr( bignum1, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( bignum2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataMaxLength >= 16 && \\\n\t\t\t\tdataMaxLength < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( sanityCheckBignum( bignum1 ) );\n\tREQUIRES( sanityCheckBignum( bignum2 ) );\n\tREQUIRES( fieldSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t  fieldSize <= CRYPT_MAX_PKCSIZE_ECC );\n\n\t/* Clear return values */\n\tif( data != NULL )\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* If it's just an encoding-length check then there's nothing to do */\n\tif( data == NULL )\n\t\t{\n\t\t*dataLength = 1 + ( fieldSize * 2 );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Encode the ECC point data, which consists of the Q coordinates \n\t   stuffed into a byte string with an encoding-specifier byte 0x04 at \n\t   the start:\n\n\t\t+---+---------------+---------------+\n\t\t|ID\t|\t\tqx\t\t|\t\tqy\t\t|\n\t\t+---+---------------+---------------+\n\t\t\t|<-- fldSize -> |<- fldSize --> | */\n\tif( dataMaxLength < 1 + ( fieldSize * 2 ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t*bufPtr++ = 0x04;\n\tmemset( bufPtr, 0, fieldSize * 2 );\n\tlength = BN_num_bytes( bignum1 );\n\tENSURES( length > 0 && length <= fieldSize );\n\tresult = BN_bn2bin( bignum1, bufPtr + ( fieldSize - length ) );\n\tENSURES( result == length );\n\tbufPtr += fieldSize;\n\tlength = BN_num_bytes( bignum2 );\n\tENSURES( length > 0 && length <= fieldSize );\n\tresult = BN_bn2bin( bignum2, bufPtr + ( fieldSize - length ) );\n\tENSURES( result == length );\n\t*dataLength = 1 + ( fieldSize * 2 );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bnsieve.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Prime Sieve\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2012-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"keygen.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"context/keygen.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTable of Primes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* First 2000 primes, generated using PARI/GP with:\n\n\tfor( n = 1, 2000, print( prime( n ) ) )\n\n   but that could just as easily have been done using one of a million Sieve \n   of Eratosthenes programs */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define NO_PRIMES\t\t100\n#else\n  #define NO_PRIMES\t\t2000\n#endif /* CONFIG_CONSERVE_MEMORY */\n\nstatic const int primeTbl[ NO_PRIMES + 2 ] = {\n\t\t2,\t   3,\t  5,\t 7,\t   11,\t  13,\t 17,\t19,\t   23,\t  29,\n\t   31,    37,    41,    43,    47,    53,    59,    61,    67,    71,\n\t   73,    79,    83,    89,    97,   101,   103,   107,   109,   113,\n\t  127,   131,   137,   139,   149,   151,   157,   163,   167,   173,\n\t  179,   181,   191,   193,   197,   199,   211,   223,   227,   229,\n\t  233,   239,   241,   251,   257,   263,   269,   271,   277,   281,\n\t  283,   293,   307,   311,   313,   317,   331,   337,   347,   349,\n\t  353,   359,   367,   373,   379,   383,   389,   397,   401,   409,\n\t  419,   421,   431,   433,   439,   443,   449,   457,   461,   463,\n\t  467,   479,   487,   491,   499,   503,   509,   521,   523,   541,\n#if NO_PRIMES > 100\n\t  547,   557,   563,   569,   571,   577,   587,   593,   599,   601,\n\t  607,   613,   617,   619,   631,   641,   643,   647,   653,   659,\n\t  661,   673,   677,   683,   691,   701,   709,   719,   727,   733,\n\t  739,   743,   751,   757,   761,   769,   773,   787,   797,   809,\n\t  811,   821,   823,   827,   829,   839,   853,   857,   859,   863,\n\t  877,   881,   883,   887,   907,   911,   919,   929,   937,   941,\n\t  947,   953,   967,   971,   977,   983,   991,   997,  1009,  1013,\n\t 1019,  1021,  1031,  1033,  1039,  1049,  1051,  1061,  1063,  1069,\n\t 1087,  1091,  1093,  1097,  1103,  1109,  1117,  1123,  1129,  1151,\n\t 1153,  1163,  1171,  1181,  1187,  1193,  1201,  1213,  1217,  1223,\n\t 1229,  1231,  1237,  1249,  1259,  1277,  1279,  1283,  1289,  1291,\n\t 1297,  1301,  1303,  1307,  1319,  1321,  1327,  1361,  1367,  1373,\n\t 1381,  1399,  1409,  1423,  1427,  1429,  1433,  1439,  1447,  1451,\n\t 1453,  1459,  1471,  1481,  1483,  1487,  1489,  1493,  1499,  1511,\n\t 1523,  1531,  1543,  1549,  1553,  1559,  1567,  1571,  1579,  1583,\n\t 1597,  1601,  1607,  1609,  1613,  1619,  1621,  1627,  1637,  1657,\n\t 1663,  1667,  1669,  1693,  1697,  1699,  1709,  1721,  1723,  1733,\n\t 1741,  1747,  1753,  1759,  1777,  1783,  1787,  1789,  1801,  1811,\n\t 1823,  1831,  1847,  1861,  1867,  1871,  1873,  1877,  1879,  1889,\n\t 1901,  1907,  1913,  1931,  1933,  1949,  1951,  1973,  1979,  1987,\n\t 1993,  1997,  1999,  2003,  2011,  2017,  2027,  2029,  2039,  2053,\n\t 2063,  2069,  2081,  2083,  2087,  2089,  2099,  2111,  2113,  2129,\n\t 2131,  2137,  2141,  2143,  2153,  2161,  2179,  2203,  2207,  2213,\n\t 2221,  2237,  2239,  2243,  2251,  2267,  2269,  2273,  2281,  2287,\n\t 2293,  2297,  2309,  2311,  2333,  2339,  2341,  2347,  2351,  2357,\n\t 2371,  2377,  2381,  2383,  2389,  2393,  2399,  2411,  2417,  2423,\n\t 2437,  2441,  2447,  2459,  2467,  2473,  2477,  2503,  2521,  2531,\n\t 2539,  2543,  2549,  2551,  2557,  2579,  2591,  2593,  2609,  2617,\n\t 2621,  2633,  2647,  2657,  2659,  2663,  2671,  2677,  2683,  2687,\n\t 2689,  2693,  2699,  2707,  2711,  2713,  2719,  2729,  2731,  2741,\n\t 2749,  2753,  2767,  2777,  2789,  2791,  2797,  2801,  2803,  2819,\n\t 2833,  2837,  2843,  2851,  2857,  2861,  2879,  2887,  2897,  2903,\n\t 2909,  2917,  2927,  2939,  2953,  2957,  2963,  2969,  2971,  2999,\n\t 3001,  3011,  3019,  3023,  3037,  3041,  3049,  3061,  3067,  3079,\n\t 3083,  3089,  3109,  3119,  3121,  3137,  3163,  3167,  3169,  3181,\n\t 3187,  3191,  3203,  3209,  3217,  3221,  3229,  3251,  3253,  3257,\n\t 3259,  3271,  3299,  3301,  3307,  3313,  3319,  3323,  3329,  3331,\n\t 3343,  3347,  3359,  3361,  3371,  3373,  3389,  3391,  3407,  3413,\n\t 3433,  3449,  3457,  3461,  3463,  3467,  3469,  3491,  3499,  3511,\n\t 3517,  3527,  3529,  3533,  3539,  3541,  3547,  3557,  3559,  3571,\n\t 3581,  3583,  3593,  3607,  3613,  3617,  3623,  3631,  3637,  3643,\n\t 3659,  3671,  3673,  3677,  3691,  3697,  3701,  3709,  3719,  3727,\n\t 3733,  3739,  3761,  3767,  3769,  3779,  3793,  3797,  3803,  3821,\n\t 3823,  3833,  3847,  3851,  3853,  3863,  3877,  3881,  3889,  3907,\n\t 3911,  3917,  3919,  3923,  3929,  3931,  3943,  3947,  3967,  3989,\n\t 4001,  4003,  4007,  4013,  4019,  4021,  4027,  4049,  4051,  4057,\n\t 4073,  4079,  4091,  4093,  4099,  4111,  4127,  4129,  4133,  4139,\n\t 4153,  4157,  4159,  4177,  4201,  4211,  4217,  4219,  4229,  4231,\n\t 4241,  4243,  4253,  4259,  4261,  4271,  4273,  4283,  4289,  4297,\n\t 4327,  4337,  4339,  4349,  4357,  4363,  4373,  4391,  4397,  4409,\n\t 4421,  4423,  4441,  4447,  4451,  4457,  4463,  4481,  4483,  4493,\n\t 4507,  4513,  4517,  4519,  4523,  4547,  4549,  4561,  4567,  4583,\n\t 4591,  4597,  4603,  4621,  4637,  4639,  4643,  4649,  4651,  4657,\n\t 4663,  4673,  4679,  4691,  4703,  4721,  4723,  4729,  4733,  4751,\n\t 4759,  4783,  4787,  4789,  4793,  4799,  4801,  4813,  4817,  4831,\n\t 4861,  4871,  4877,  4889,  4903,  4909,  4919,  4931,  4933,  4937,\n\t 4943,  4951,  4957,  4967,  4969,  4973,  4987,  4993,  4999,  5003,\n\t 5009,  5011,  5021,  5023,  5039,  5051,  5059,  5077,  5081,  5087,\n\t 5099,  5101,  5107,  5113,  5119,  5147,  5153,  5167,  5171,  5179,\n\t 5189,  5197,  5209,  5227,  5231,  5233,  5237,  5261,  5273,  5279,\n\t 5281,  5297,  5303,  5309,  5323,  5333,  5347,  5351,  5381,  5387,\n\t 5393,  5399,  5407,  5413,  5417,  5419,  5431,  5437,  5441,  5443,\n\t 5449,  5471,  5477,  5479,  5483,  5501,  5503,  5507,  5519,  5521,\n\t 5527,  5531,  5557,  5563,  5569,  5573,  5581,  5591,  5623,  5639,\n\t 5641,  5647,  5651,  5653,  5657,  5659,  5669,  5683,  5689,  5693,\n\t 5701,  5711,  5717,  5737,  5741,  5743,  5749,  5779,  5783,  5791,\n\t 5801,  5807,  5813,  5821,  5827,  5839,  5843,  5849,  5851,  5857,\n\t 5861,  5867,  5869,  5879,  5881,  5897,  5903,  5923,  5927,  5939,\n\t 5953,  5981,  5987,  6007,  6011,  6029,  6037,  6043,  6047,  6053,\n\t 6067,  6073,  6079,  6089,  6091,  6101,  6113,  6121,  6131,  6133,\n\t 6143,  6151,  6163,  6173,  6197,  6199,  6203,  6211,  6217,  6221,\n\t 6229,  6247,  6257,  6263,  6269,  6271,  6277,  6287,  6299,  6301,\n\t 6311,  6317,  6323,  6329,  6337,  6343,  6353,  6359,  6361,  6367,\n\t 6373,  6379,  6389,  6397,  6421,  6427,  6449,  6451,  6469,  6473,\n\t 6481,  6491,  6521,  6529,  6547,  6551,  6553,  6563,  6569,  6571,\n\t 6577,  6581,  6599,  6607,  6619,  6637,  6653,  6659,  6661,  6673,\n\t 6679,  6689,  6691,  6701,  6703,  6709,  6719,  6733,  6737,  6761,\n\t 6763,  6779,  6781,  6791,  6793,  6803,  6823,  6827,  6829,  6833,\n\t 6841,  6857,  6863,  6869,  6871,  6883,  6899,  6907,  6911,  6917,\n\t 6947,  6949,  6959,  6961,  6967,  6971,  6977,  6983,  6991,  6997,\n\t 7001,  7013,  7019,  7027,  7039,  7043,  7057,  7069,  7079,  7103,\n\t 7109,  7121,  7127,  7129,  7151,  7159,  7177,  7187,  7193,  7207,\n\t 7211,  7213,  7219,  7229,  7237,  7243,  7247,  7253,  7283,  7297,\n\t 7307,  7309,  7321,  7331,  7333,  7349,  7351,  7369,  7393,  7411,\n\t 7417,  7433,  7451,  7457,  7459,  7477,  7481,  7487,  7489,  7499,\n\t 7507,  7517,  7523,  7529,  7537,  7541,  7547,  7549,  7559,  7561,\n\t 7573,  7577,  7583,  7589,  7591,  7603,  7607,  7621,  7639,  7643,\n\t 7649,  7669,  7673,  7681,  7687,  7691,  7699,  7703,  7717,  7723,\n\t 7727,  7741,  7753,  7757,  7759,  7789,  7793,  7817,  7823,  7829,\n\t 7841,  7853,  7867,  7873,  7877,  7879,  7883,  7901,  7907,  7919,\n\t 7927,  7933,  7937,  7949,  7951,  7963,  7993,  8009,  8011,  8017,\n\t 8039,  8053,  8059,  8069,  8081,  8087,  8089,  8093,  8101,  8111,\n\t 8117,  8123,  8147,  8161,  8167,  8171,  8179,  8191,  8209,  8219,\n\t 8221,  8231,  8233,  8237,  8243,  8263,  8269,  8273,  8287,  8291,\n\t 8293,  8297,  8311,  8317,  8329,  8353,  8363,  8369,  8377,  8387,\n\t 8389,  8419,  8423,  8429,  8431,  8443,  8447,  8461,  8467,  8501,\n\t 8513,  8521,  8527,  8537,  8539,  8543,  8563,  8573,  8581,  8597,\n\t 8599,  8609,  8623,  8627,  8629,  8641,  8647,  8663,  8669,  8677,\n\t 8681,  8689,  8693,  8699,  8707,  8713,  8719,  8731,  8737,  8741,\n\t 8747,  8753,  8761,  8779,  8783,  8803,  8807,  8819,  8821,  8831,\n\t 8837,  8839,  8849,  8861,  8863,  8867,  8887,  8893,  8923,  8929,\n\t 8933,  8941,  8951,  8963,  8969,  8971,  8999,  9001,  9007,  9011,\n\t 9013,  9029,  9041,  9043,  9049,  9059,  9067,  9091,  9103,  9109,\n\t 9127,  9133,  9137,  9151,  9157,  9161,  9173,  9181,  9187,  9199,\n\t 9203,  9209,  9221,  9227,  9239,  9241,  9257,  9277,  9281,  9283,\n\t 9293,  9311,  9319,  9323,  9337,  9341,  9343,  9349,  9371,  9377,\n\t 9391,  9397,  9403,  9413,  9419,  9421,  9431,  9433,  9437,  9439,\n\t 9461,  9463,  9467,  9473,  9479,  9491,  9497,  9511,  9521,  9533,\n\t 9539,  9547,  9551,  9587,  9601,  9613,  9619,  9623,  9629,  9631,\n\t 9643,  9649,  9661,  9677,  9679,  9689,  9697,  9719,  9721,  9733,\n\t 9739,  9743,  9749,  9767,  9769,  9781,  9787,  9791,  9803,  9811,\n\t 9817,  9829,  9833,  9839,  9851,  9857,  9859,  9871,  9883,  9887,\n\t 9901,  9907,  9923,  9929,  9931,  9941,  9949,  9967,  9973, 10007,\n\t10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,\n\t10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177,\n\t10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,\n\t10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343,\n\t10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,\n\t10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567,\n\t10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657,\n\t10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739,\n\t10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,\n\t10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949,\n\t10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059,\n\t11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,\n\t11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,\n\t11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329,\n\t11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443,\n\t11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527,\n\t11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,\n\t11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777,\n\t11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833,\n\t11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933,\n\t11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,\n\t12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109,\n\t12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211,\n\t12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289,\n\t12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,\n\t12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487,\n\t12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553,\n\t12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641,\n\t12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,\n\t12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,\n\t12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923,\n\t12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007,\n\t13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,\n\t13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187,\n\t13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309,\n\t13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411,\n\t13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,\n\t13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619,\n\t13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,\n\t13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781,\n\t13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,\n\t13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967,\n\t13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081,\n\t14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197,\n\t14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,\n\t14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419,\n\t14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519,\n\t14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,\n\t14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,\n\t14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767,\n\t14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851,\n\t14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947,\n\t14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,\n\t15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149,\n\t15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259,\n\t15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319,\n\t15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,\n\t15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497,\n\t15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607,\n\t15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679,\n\t15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,\n\t15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881,\n\t15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971,\n\t15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069,\n\t16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,\n\t16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,\n\t16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381,\n\t16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481,\n\t16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,\n\t16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691,\n\t16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811,\n\t16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903,\n\t16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,\n\t17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093,\n\t17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,\n\t17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317,\n\t17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,\n#endif /* NO_PRIMES > 100 */\n\t0, 0\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFast Prime Sieve\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The number of primes in the sieve (and their values) that result in a\n   given number of candidates remaining from 40,000.  Even the first 100\n   primes weed out 91% of all the candidates, and after 500 you're only\n   removing a handful for each 100 extra primes.\n\n\t Number\t\t   Prime\tCandidates left\n\t\t\t\t  Values\tfrom 40,000\n\t--------\t---------\t---------------\n\t  0- 99\t\t   0- 541\t\t3564\n\t100-199\t\t 541-1223\t\t3175\n\t200-299\t\t1223-1987\t\t2969\n\t300-399\t\t1987-2741\t\t2845\n\t400-499\t\t2741-3571\t\t2755\n\t500-599\t\t3571-4409\t\t2688\n\t600-699\t\t4409-5279\t\t2629\n\t700-799\t\t5279-6133\t\t2593\n\t800-899\t\t6133-6997\t\t2555\n\t900-999\t\t6997-7919\t\t2521\n\n  There is in fact an even faster prime tester due to Dan Piponi that uses\n  C++ templates as a universal computer and performs the primality test at\n  compile time, however this requires the use of a fairly advanced C++\n  compiler and isn't amenable to generating different primes */\n\n/* When we're doing a sieve of a singleton candidate we don't run through\n   the whole range of sieve values since we run into the law of diminishing\n   returns after a certain point.  The following value sieves with every\n   prime under 1000 */\n\n#if NO_PRIMES < ( 21 * 8 )\n  #define FAST_SIEVE_PRIMES\t\tNO_PRIMES\n#else\n  #define FAST_SIEVE_PRIMES\t\t( 21 * 8 )\n#endif /* Small prime table */\n\n/* Set up the sieve array for the number.  Every position that contains\n   a zero is non-divisible by all of the small primes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint initSieve( IN_ARRAY( sieveSize ) BOOLEAN *sieveArray, \n\t\t\t   IN_LENGTH_FIXED( SIEVE_SIZE ) const int sieveSize,\n\t\t\t   const BIGNUM *candidate )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( sieveArray, sieveSize * sizeof( BOOLEAN ) ) );\n\tassert( isReadPtr( candidate, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sieveSize == SIEVE_SIZE );\n\n\tmemset( sieveArray, 0, sieveSize * sizeof( BOOLEAN ) );\n\n\t/* Walk down the list of primes marking the appropriate position in the\n\t   array as divisible by the prime.  We start at index 1 because the\n\t   candidate will never be divisible by 2 (== primeTbl[ 0 ]) */\n\tLOOP_MAX( i = 1, i < NO_PRIMES, i++ )\n\t\t{\n\t\tunsigned int step = primeTbl[ i ];\n\t\tBN_ULONG sieveIndex DUMMY_INIT;\n\t\tint bnStatus = BN_STATUS, LOOP_ITERATOR_ALT;\n\n\t\t/* Determine the correct start index for this value */\n\t\tCK( BN_mod_word( &sieveIndex, candidate, step ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tif( sieveIndex & 1 )\n\t\t\tsieveIndex = ( step - sieveIndex ) / 2;\n\t\telse\n\t\t\t{\n\t\t\tif( sieveIndex > 0 )\n\t\t\t\tsieveIndex = ( ( step * 2 ) - sieveIndex ) / 2;\n\t\t\t}\n\n\t\t/* If the start index falls outside the sieve, don't go any \n\t\t   further */\n\t\tif( sieveIndex >= sieveSize )\n\t\t\tcontinue;\n\n\t\t/* Mark each multiple of the divisor as being divisible.\n\t\t\n\t\t   Note that many compilers will complain about the comparison for \n\t\t   sieveIndex >= 0 being redundant because a BN_ULONG is unsigned, \n\t\t   we leave it in anyway to be safe */\n\t\tLOOP_MAX_CHECKINC_ALT( sieveIndex >= 0 && sieveIndex < sieveSize,\n\t\t\t\t\t\t\t   sieveIndex += step ) \n\t\t\t{\n\t\t\tsieveArray[ sieveIndex ] = TRUE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* An LFSR to step through each entry in the sieve array, avoiding a linear \n   search.  This isn't a true pseudorandom selection since all that it's \n   really doing is going through the numbers in a linear order with a \n   different starting point, but it's good enough as a randomiser.  In any\n   case even a straight linear search isn't so bad, there's a slightly\n   higher chance of selecting a prime that's preceded by a larger gap of\n   non-primes, but in practice this slight bias isn't observable */\n\n#define LFSR_POLYNOMIAL\t\t0x1053\n#define LFSR_MASK\t\t\t0x1000\n\nCHECK_RETVAL_RANGE( 0, SIEVE_SIZE ) \\\nint nextSievePosition( IN_INT_SHORT int value )\n\t{\n\tstatic_assert( LFSR_MASK == SIEVE_SIZE, \"LFSR size\" );\n\t\n\tREQUIRES( value > 0 && value < SIEVE_SIZE );\n\n\t/* Get the next value: Multiply by x and reduce by the polynomial */\n\tvalue <<= 1;\n\tif( value & LFSR_MASK )\n\t\tvalue ^= LFSR_POLYNOMIAL;\n\n\tENSURES( value > 0 && value < SIEVE_SIZE );\n\n\treturn( value );\n\t}\n\n/* Get the n-th prime table entry, used in primeProbable() for the\n   Miller-Rabin test */\n\nCHECK_RETVAL_RANGE( 0, SIEVE_SIZE ) \\\nint getSieveEntry( IN_RANGE( 0, SIEVE_SIZE - 1 ) int position )\n\t{\n\tREQUIRES_EXT( position >= 0 && position < SIEVE_SIZE, 2 ); \n\n\treturn( primeTbl[ position ] );\n\t}\n\n/* A one-off sieve check for when we're testing a singleton rather than\n   running over a range of values */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN primeSieve( const BIGNUM *candidate )\n\t{\n\tconst int candidateLen = BN_num_bytes( candidate );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( candidate, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_B( sanityCheckBignum( candidate ) );\n\tREQUIRES_B( candidateLen > 0 && candidateLen <= CRYPT_MAX_PKCSIZE );\n\n\t/* If we're checking a small value then we can use a direct machine\n\t   instruction for the check, this is both faster and avoids false \n\t   positives when the value being checked is small enough to be \n\t   present in the sieve */\n\tif( candidateLen < sizeof( BN_ULONG ) )\n\t\t{\n\t\tconst BN_ULONG candidateWord = BN_get_word( candidate );\n\n\t\tENSURES_B( candidateWord != BN_NAN );\n\t\tLOOP_MAX( i = 1, i < FAST_SIEVE_PRIMES && \\\n\t\t\t\t\t\t primeTbl[ i ] < candidateWord, i++ )\n\t\t\t{\n\t\t\tif( candidateWord % primeTbl[ i ] == 0 )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\treturn( TRUE );\n\t\t}\n\n\tLOOP_MAX( i = 0, i < FAST_SIEVE_PRIMES, i++ )\n\t\t{\n\t\tBN_ULONG result DUMMY_INIT;\n\t\tint bnStatus = BN_STATUS;\n\n\t\tCK( BN_mod_word( &result, candidate, primeTbl[ i ] ) );\n\t\tif( bnStatusError( bnStatus ) || result == 0 )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/ctx_bntest.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Bignum Test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* Work around a code optimizer bug in the IBM xlc compiler which causes the \n   compare operations in selfTestBignumFields() to be evaluated incorrectly, \n   resulting in a self-test failure.  Luckily IBM provides per-function\n   optimisation control to \"help debug errors that occur only under \n   optimization\" (i.e. work around compiler bugs) so we just turn it off for\n   the one function where it causes a problem */\n\n#if defined( __xlc__ ) && defined( __OPTIMIZE__ )\n  #pragma option_override( selfTestBignumFields, \"opt( level, 0 )\" ) \n#endif /* IBM xlc optimizer bug */\n\n#if defined( USE_PKC ) && !defined( CONFIG_CONSERVE_MEMORY_EXTRA )\n\n/* Test operation types */\n\ntypedef enum {\n\tBN_OP_NONE,\t\t\t\t/* No operation type */\n\tBN_OP_CMP, BN_OP_CMPPART,\n\tBN_OP_ADD, BN_OP_SUB, \n\tBN_OP_LSHIFT, BN_OP_RSHIFT,\n\tBN_OP_ADDWORD, BN_OP_SUBWORD,\n\tBN_OP_MULWORD, BN_OP_MODWORD,\n\tBN_OP_SQR, \n\tBN_OP_DIV, BN_OP_MONTMODMULT,\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tBN_OP_MODADD, BN_OP_MODSUB,\n\tBN_OP_MODMUL, BN_OP_MODSHIFT,\n#endif /* USE_ECDH || USE_ECDSA */\n\tBN_OP_LAST\t\t\t\t/* Last possible operation type */\n\t} BN_OP_TYPE;\n\n/* Some of the tests require negative values, in which case we encode a sign\n   bit in the length field */\n\n#define BN_VAL_NEGATIVE\t\t0x800000\n#define MK_NEGATIVE( val )\t( ( val ) | 0x800000 )\n\n/* The structure used to hold the self-test values */\n\ntypedef struct {\n\tconst int aLen; const BYTE *a;\n\tconst int bLen; const BYTE *b; unsigned int bWord;\n\tconst int resultLen; const BYTE *result;\n\tconst int modLen; const BYTE *mod;\n\t} SELFTEST_VALUE;\n\n/* Macro to shorten the amount of text required to represent array sizes */\n\n#define FS_SIZE( selfTestArray )\tFAILSAFE_ARRAYSIZE( selfTestArray, SELFTEST_VALUE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test values, a op b -> result.  Notes: We can't use values of 0 or 1 since\n   these are never valid and are automatically rejected by importBignum(),\n   and the code assumes a 32-bit architecture for checking of carry/borrow\n   propagation functionality (it'll still work on 64-bit but won't hit as\n   many corner cases) */\n\nstatic const SELFTEST_VALUE cmpSelftestValues[] = {\n\t{ 1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x02\" ), 0, 0, NULL },\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x02\" ), 0, 1, NULL },\n\t{ 1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x03\" ), 0, -1, NULL },\n\t{ 5, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0, 1, NULL },\n\t{ 9, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0, 1, NULL },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), \n\t  5, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\" ), 0, -1, NULL },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), \n\t  9, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ), 0, -1, NULL },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE addsubSelftestValues[] = {\n\t/* a, b, result */\n\t{ 1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x03\" ), 0,\n\t  1, MKDATA( \"\\x05\" ) },\n\t{ MK_NEGATIVE( 1 ), MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x05\" ), 0,\n\t  1, MKDATA( \"\\x02\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 1, MKDATA( \"\\x02\" ), 0,\n\t  5, MKDATA( \"\\x01\\x00\\x00\\x00\\x01\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  5, MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFE\" ) },\n\t{ 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), \n\t  1, MKDATA( \"\\x02\" ), 0,\n\t  9, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\" ) },\n\t{ 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), \n\t  8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  9, MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\" ) },\n\t{ 12, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  1, MKDATA( \"\\x02\" ), 0,\n\t  12, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x57\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x01\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\" ), \n\t  8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t{ 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x01\" ), \n\t  12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t{ 16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x56\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x54\" ) },\n\t{ 16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x00\\x00\\x00\\x00\\x55\\x55\\x55\\x55\" ), \n\t  8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x56\\x00\\x00\\x00\\x00\\x55\\x55\\x55\\x54\" ) },\n\t{ 16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x00\\x00\\x00\\x00\\x55\\x55\\x55\\x55\" ), \n\t  12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  16, MKDATA( \"\\x55\\x55\\x55\\x56\\x55\\x55\\x55\\x54\\x00\\x00\\x00\\x01\\x55\\x55\\x55\\x54\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE shiftSelftestValues[] = {\n\t/* a, shiftAmt, result */\n\t{ 1, MKDATA( \"\\x02\" ), 1, NULL, 0,\n\t  1, MKDATA( \"\\x04\" ) },\n\t{ 4, MKDATA( \"\\x80\\x00\\x00\\x01\" ), 1, NULL, 0,\n\t  5, MKDATA( \"\\x01\\x00\\x00\\x00\\x02\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 1, NULL, 0,\n\t  5, MKDATA( \"\\x01\\xFF\\xFF\\xFF\\xFE\" ) },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 1, NULL, 0,\n\t  8, MKDATA( \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\" ) },\n\t{ 10, MKDATA( \"\\x01\\x23\\x45\\x67\\x89\\xAB\\xCD\\xEF\\xE2\\xD3\" ), 1, NULL, 0,\n\t  10, MKDATA( \"\\x02\\x46\\x8A\\xCF\\x13\\x57\\x9B\\xDF\\xC5\\xA6\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 16, NULL, 0,\n\t  14, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\\x00\\x00\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 32, NULL, 0,\n\t  16, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\" ) },\n\t{ 8, MKDATA( \"\\x01\\x23\\x45\\x67\\x89\\xAB\\xCD\\xEF\" ), 93, NULL, 0,\n\t  19, MKDATA( \"\\x24\\x68\\xAC\\xF1\\x35\\x79\\xBD\\xE0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE addsubWordsSelftestValues[] = {\n\t/* a, bWord, result */\n\t{ 1, MKDATA( \"\\x02\" ), 0, NULL, 3,\n\t  1, MKDATA( \"\\x05\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 2,\n\t  5, MKDATA( \"\\x01\\x00\\x00\\x00\\x01\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFD\" ), 0, NULL, 2,\n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ) },\n\t{ 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 2,\n\t  9, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE muldivWordsSelftestValues[] = {\n\t/* a, bWord, result */\n\t{ 1, MKDATA( \"\\x02\" ), 0, NULL, 3,\n\t  1, MKDATA( \"\\x06\" ) },\n\t{ 2, MKDATA( \"\\x45\\x67\" ), 0, NULL, 0x89AB,\n\t  4, MKDATA( \"\\x25\\x52\\x7A\\xCD\" ) },\n\t{ 4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0, NULL, 0x9ABCDEF1,\n\t  8, MKDATA( \"\\x0B\\x00\\xEA\\x4E\\x36\\x61\\x76\\xF8\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), 0, NULL, 0xAA55AA55,\n\t  12, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8E\\xDC\\xC7\\x10\\x05\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE modWordsSelftestValues[] = {\n\t/* a, bWord, result */\n\t{ 1, MKDATA( \"\\x06\" ), 0, NULL, 3, 0, NULL },\n\t{ 1, MKDATA( \"\\x05\" ), 0, NULL, 3, 2, NULL },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 7, 3, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 14, 5, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 15, 5, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 16, 5, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 17, 0, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 18, 17, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 19, 18, NULL },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 20, 5, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 29, 27, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 177545, 111310, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 0xFFFE, 51, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 0xFFFF, 0, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 0xFFFFFFFE, 5, NULL },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 0xFFFFFFFF, 0, NULL },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE sqrSelftestValues[] = {\n\t/* a, result */\n\t{ 1, MKDATA( \"\\x02\" ), 0, NULL, 0,\n\t  1, MKDATA( \"\\x04\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0, NULL, 0, \n\t  8, MKDATA( \"\\xFF\\xFF\\xFF\\xFE\\x00\\x00\\x00\\x01\" ) },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0, \n\t  16, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 12, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0, \n\t  24, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC6\\xE3\\x8E\\x38\\xE3\"\n\t\t  \"\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 20, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\"\n\t\t  \"\\x55\\x55\\x55\\x55\" ), 0, NULL, 0,\n\t  40, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\"\n\t\t  \"\\x71\\xC7\\x1C\\x71\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\"\n\t\t  \"\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 24, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\"\n\t\t  \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0,\n\t  48, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\"\n\t\t  \"\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC6\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\"\n\t\t  \"\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 28, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\"\n\t\t  \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0,\n\t  56, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\"\n\t\t  \"\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x38\\xE3\\x8E\\x38\"\n\t\t  \"\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\"\n\t\t  \"\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0,\n\t  32, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\"\n\t\t  \"\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t{ 32, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\"\n\t\t  \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), 0, NULL, 0,\n\t  64, MKDATA( \"\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\"\n\t\t  \"\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\\xC7\\x1C\\x71\"\n\t\t  \"\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\"\n\t\t  \"\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x38\\xE3\\x8E\\x39\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE divSelftestValues[] = {\n\t/* a, b, result, remainder */\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x02\" ), 0,\t/* Test normalisation */\n\t  1, MKDATA( \"\\x01\" ), 1, MKDATA( \"\\x01\" ) },\n\t{ 1, MKDATA( \"\\x08\" ), 1, MKDATA( \"\\x03\" ), 0,\n\t  1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x02\" ) },\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x08\" ), 0,\n\t  1, MKDATA( \"\\x00\" ), 1, MKDATA( \"\\x03\" ) },\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x03\" ), 0,\n\t  1, MKDATA( \"\\x01\" ), 1, MKDATA( \"\\x00\" ) },\n\t{ 4, MKDATA( \"\\x55\\x55\\x55\\x55\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0,\n\t  1, MKDATA( \"\\x04\" ), \n\t  4, MKDATA( \"\\x0C\\x83\\xFB\\x75\" ) },\n\t{ 8, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0,\n\t  5, MKDATA( \"\\x04\\xB0\\x00\\x00\\x27\" ), \n\t  4, MKDATA( \"\\x0F\\x5C\\x29\\x0D\" ) },\n\t{ 12, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0,\n\t  9, MKDATA( \"\\x04\\xB0\\x00\\x00\\x27\\xD8\\x00\\x01\\x52\" ), \n\t  4, MKDATA( \"\\x0C\\x3B\\x2A\\xE5\" ) },\n\t{ 16, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0,\n\t  13, MKDATA( \"\\x04\\xB0\\x00\\x00\\x27\\xD8\\x00\\x01\\x52\\xAC\\x00\\x0B\\x3E\" ), \n\t  4, MKDATA( \"\\x0C\\xF1\\x3C\\x45\" ) },\n\t{ 20, MKDATA( \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 0,\n\t  17, MKDATA( \"\\x04\\xB0\\x00\\x00\\x27\\xD8\\x00\\x01\\x52\\xAC\\x00\\x0B\\x3E\\xB6\\x00\\x5F\\x95\" ), \n\t  3, MKDATA( \"\\xC8\\x79\\x7D\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8F\" ), 0,\n\t  1, MKDATA( \"\\x01\" ), \n\t  8, MKDATA( \"\\x06\\x17\\x7d\\x8f\\x01\\x23\\x45\\x62\" ) },\n\t{ 8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8F\" ),\n\t  8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), 0,\n\t  1, MKDATA( \"\\x00\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8F\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  4, MKDATA( \"\\x56\\x78\\x9A\\xBC\" ), 0,\n\t  4, MKDATA( \"\\x35\\xE5\\x0D\\x79\" ), \n\t  4, MKDATA( \"\\x45\\xB4\\x30\\x15\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0, \n\t  5, MKDATA( \"\\x01\\x80\\xBF\\xA0\\x2E\" ), \n\t  8, MKDATA( \"\\x44\\xBB\\x44\\xBD\\x44\\xBB\\x44\\xB9\" ) },\n\t{ 20, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0, \n\t  13, MKDATA( \"\\x01\\x80\\xBF\\xA0\\x2E\\x67\\x4C\\x59\\xD6\\x17\\xF4\\x05\\xFA\" ), \n\t  5, MKDATA( \"\\x02\\xFF\\xFF\\xFF\\xFD\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE montModMulSelftestValues[] = {\n\t/* a, b, result, modulus */\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x04\" ), 0,\n\t  1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x05\" ) },\n\t{ 1, MKDATA( \"\\x07\" ), 1, MKDATA( \"\\x07\" ), 0,\n\t  1, MKDATA( \"\\x04\" ), 1, MKDATA( \"\\x09\" ) },\n\t{ 4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 4, MKDATA( \"\\x55\\x55\\x55\\x55\" ), 0,\n\t  4, MKDATA( \"\\x6E\\x6E\\x6E\\x6E\" ), 4, MKDATA( \"\\x9A\\xBC\\xDE\\xF1\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8F\" ), 0,\n\t  8, MKDATA( \"\\x67\\x63\\xD1\\x34\\xCA\\x6D\\x53\\x9F\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  4, MKDATA( \"\\x56\\x78\\x9A\\xBC\" ), 0,\n\t  8, MKDATA( \"\\x02\\x34\\x6B\\x2A\\x61\\x50\\x18\\x42\" ), \n\t  8, MKDATA( \"\\x12\\x34\\x56\\x79\\x00\\x00\\x00\\x01\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0, \n\t  13, MKDATA( \"\\x04\\x12\\x96\\xEF\\xDF\\x20\\x8F\\x5F\\xFC\\x0B\\xFE\\x08\\x53\" ), \n\t  13, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\\x23\\x45\\x67\\x89\\xAB\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nstatic const SELFTEST_VALUE modAddSelftestValues[] = {\n\t/* a, b, result, modulus */\n\t{ 1, \"\\x03\", 1, \"\\x04\", 0,\n\t  1, \"\\x02\", 1, \"\\x05\" },\n\t{ 4, \"\\xFF\\xFF\\xFF\\xFE\", 1, \"\\x03\", 0,\n\t  1, \"\\x02\", 4, \"\\xFF\\xFF\\xFF\\xFF\" },\n\t{ 8, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\", 8, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\", 0,\n\t  8, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFD\", 8, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" },\n\t{ 12, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x03\", 4, \"\\xFF\\xFF\\xFF\\xFF\", 0,\n\t  1, \"\\x02\", 13, \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" },\n\t{ 12, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x04\", 4, \"\\xFF\\xFF\\xFF\\xFF\", 0,\n\t  1, \"\\x03\", 13, \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" },\n\t{ 12, \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x05\", 4, \"\\xFF\\xFF\\xFF\\xFF\", 0,\n\t  1, \"\\x04\", 13, \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE modSubSelftestValues[] = {\n\t/* a, b, result, modulus */\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x04\" ), 0,\n\t  1, MKDATA( \"\\x04\" ), 1, MKDATA( \"\\x05\" ) },\n\t{ 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFE\" ), 1, MKDATA( \"\\x03\" ), 0,\n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFB\" ), 4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ) },\n\t{ 1, MKDATA( \"\\x02\" ), 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\" ), 0,\n\t  1, MKDATA( \"\\x03\" ), 8, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x03\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\\x00\\x00\\x00\\x04\" ), \n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x04\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\\x00\\x00\\x00\\x05\" ), \n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t{ 12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x05\" ), \n\t  4, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\" ), 0,\n\t  12, MKDATA( \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFE\\x00\\x00\\x00\\x06\" ), \n\t  13, MKDATA( \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE modMulSelftestValues[] = {\n\t/* a, b, result, modulus */\n\t{ 1, MKDATA( \"\\x03\" ), 1, MKDATA( \"\\x04\" ), 0,\n\t  1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x05\" ) },\n\t{ 1, MKDATA( \"\\x07\" ), 1, MKDATA( \"\\x07\" ), 0,\n\t  1, MKDATA( \"\\x04\" ), 1, MKDATA( \"\\x05\" ) },\n\t{ 4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 4, MKDATA( \"\\x9A\\xBC\\xDE\\xF1\" ), 0,\n\t  4, MKDATA( \"\\x41\\x62\\x61\\x46\" ), 4, MKDATA( \"\\x55\\x55\\x55\\x55\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0,\n\t  8, MKDATA( \"\\x02\\xBF\\xCF\\x99\\x0F\\xFA\\x44\\x09\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8E\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0,\n\t  8, MKDATA( \"\\x01\\x1D\\x9A\\xC1\\xA9\\x93\\xDC\\xB2\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x8F\" ) },\n\t{ 8, MKDATA( \"\\x12\\x34\\x56\\x78\\x9A\\xBC\\xDE\\xF1\" ), \n\t  8, MKDATA( \"\\xAA\\x55\\xAA\\x55\\xAA\\x55\\xAA\\x55\" ), 0,\n\t  8, MKDATA( \"\\x0B\\x98\\x3E\\xD3\\xDC\\xC7\\x0F\\x15\" ), \n\t  8, MKDATA( \"\\x0C\\x1C\\xD8\\xE9\\x99\\x99\\x99\\x90\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n\nstatic const SELFTEST_VALUE modShiftSelftestValues[] = {\n\t/* a, b, result, modulus */\n\t{ 1, MKDATA( \"\\x02\" ), 2, NULL, 0,\n\t  1, MKDATA( \"\\x02\" ), 1, MKDATA( \"\\x03\" ) },\n\t{ 4, MKDATA( \"\\x12\\x34\\x56\\x78\" ), 27, NULL, 0,\n\t  4, MKDATA( \"\\x19\\x38\\xFB\\x5B\" ), \n\t  4, MKDATA( \"\\xAA\\x55\\xAA\\x55\" ) },\n\t{ 2, MKDATA( \"\\xAA\\x55\" ), 27, NULL, 0,\n\t  4, MKDATA( \"\\x06\\x6F\\xAD\\xD0\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x78\" ) },\n\t{ 2, MKDATA( \"\\xAA\\x55\" ), 27, NULL, 0,\n\t  4, MKDATA( \"\\x06\\x6F\\x62\\xF6\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x79\" ) },\n\t{ 2, MKDATA( \"\\xAA\\x55\" ), 27, NULL, 0,\n\t  4, MKDATA( \"\\x06\\x6F\\x18\\x1C\" ), \n\t  4, MKDATA( \"\\x12\\x34\\x56\\x7A\" ) },\n\t\t{ 0, NULL, 0, NULL, 0, 0, NULL }, { 0, NULL, 0, NULL, 0, 0, NULL }\n\t};\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that the compiler doesn't do strange things to the overlaid\n   BIGNUM/BIGNUM_EXT/BIGNUM_EXT2 fields */\n\n#define TEST_TOP_CONST\t\t0x12345678U\n#define TEST_NEG_CONST\t\t0x9ABCDEF0U\n#define TEST_FLAGS_CONST\t0x1F2E3D4CU\n#define TEST_D0_CONST\t\t0x5B6A7980U\n#define TEST_D1_CONST\t\t0x19283746U\n#define TEST_D2_CONST\t\t0x5F6E7D4CU\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN selfTestBignumFields( void )\n\t{\n\tBIGNUM bignum;\n\tBIGNUM_EXT *bignumExt = ( BIGNUM_EXT * ) &bignum;\n\tBIGNUM_EXT2 *bignumExt2 = ( BIGNUM_EXT2 * ) &bignum;\n\n\t/* At this point we haven't checked any of the higher-level bignum ops \n\t   so we have to manipulate the fields directly.  These are fundamental \n\t   tests that indicate serious problems if they fail, so we provide \n\t   additional diagnostics in cases that might occur */\n\tmemset( &bignum, 0, sizeof( BIGNUM ) );\n\tbignum.top = TEST_TOP_CONST;\n\tbignum.neg = TEST_NEG_CONST;\n\tbignum.flags = TEST_FLAGS_CONST;\n\tbignum.d[ 0 ] = TEST_D0_CONST;\n\tbignum.d[ 1 ] = TEST_D1_CONST;\n\tbignum.d[ 2 ] = TEST_D2_CONST;\n\tif( bignumExt->top != TEST_TOP_CONST || \\\n\t\tbignumExt->neg != TEST_NEG_CONST || \\\n\t\tbignumExt->flags != TEST_FLAGS_CONST || \\\n\t\tbignumExt->d[ 0 ] != TEST_D0_CONST || \\\n\t\tbignumExt->d[ 1 ] != TEST_D1_CONST || \\\n\t\tbignumExt->d[ 2 ] != TEST_D2_CONST )\n\t\t{\n\t\tDEBUG_DIAG(( \"Check of BIGNUM/BIGNUM_EXT overlay failed\" ));\n\t\tDEBUG_DIAG(( \"BN->top = %lX, BN->neg = %lX, BN->flags = %lX, \"\n\t\t\t\t\t \"BN->d[0] = %lX, BN->d[1] = %lX, BN->d[2] = %lX\", \n\t\t\t\t\t bignumExt->top, bignumExt->neg, bignumExt->flags, \n\t\t\t\t\t bignumExt->d[ 0 ], bignumExt->d[ 1 ], \n\t\t\t\t\t bignumExt->d[ 2 ] ));\n\t\treturn( FALSE );\n\t\t}\n\tif( bignumExt2->top != TEST_TOP_CONST || \\\n\t\tbignumExt2->neg != TEST_NEG_CONST || \\\n\t\tbignumExt2->flags != TEST_FLAGS_CONST || \\\n\t\tbignumExt2->d[ 0 ] != TEST_D0_CONST || \\\n\t\tbignumExt2->d[ 1 ] != TEST_D1_CONST || \\\n\t\tbignumExt2->d[ 2 ] != TEST_D2_CONST )\n\t\t{\n\t\tDEBUG_DIAG(( \"Check of BIGNUM/BIGNUM_EXT2 overlay failed\" ));\n\t\tDEBUG_DIAG(( \"BN->top = %lX, BN->neg = %lX, BN->flags = %lX, \"\n\t\t\t\t\t \"BN->d[0] = %lX, BN->d[1] = %lX, BN->d[2] = %lX\", \n\t\t\t\t\t bignumExt2->top, bignumExt2->neg, bignumExt2->flags, \n\t\t\t\t\t bignumExt2->d[ 0 ], bignumExt2->d[ 1 ], \n\t\t\t\t\t bignumExt2->d[ 2 ] ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* If the application that uses us is linked against anything containing \n   OpenSSL code then, depending on the link order, the bignum function calls\n   may end up referencing the OpenSSL version of the functions rather than \n   our ones.  To try and detect this we initialise a bignum with BN_one()\n   (= BN_set_word()), check that the fields are OK, and if they're not check\n   whehter they look like an OpenSSL-style bignum */ \n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN selfTestBignumLinkage( void )\n\t{\n\ttypedef struct {\n\t\tBN_ULONG *d;\n\t\tint top, dmax, neg, flags;\n\t\t} BIGNUM_ALT;\n\tBIGNUM bignum;\n\tBIGNUM_ALT *bignumAlt = ( BIGNUM_ALT * ) &bignum;\n\n\t/* Set the bignum to zero.  If we're being used with our own bignum \n\t   code, the fields should be set correctly */\n\tBN_init( &bignum );\n\t( void ) BN_one( &bignum );\n\tif( bignum.top == 1 && bignum.neg == 0 && bignum.flags == 0 && \\\n\t\tbignum.d[ 0 ] == 1 && bignum.d[ 1 ] == 0 )\n\t\t{\n\t\tBN_clear( &bignum );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check for the fields being set by the OpenSSL functions */\n\tif( bignumAlt->top == 1 && bignumAlt->neg == 0 && bignumAlt->flags == 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"BN code appears to be using OpenSSL, not cryptlib, \"\n\t\t\t\t\t \"library\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\tDEBUG_DIAG(( \"BN init sanity check failed\" ));\n\treturn( FALSE );\n\t}\n\n/* Test general bignum ops.  Apart from acting as a standard self-test these \n   also test the underlying building blocks used in the higher-level \n   routines whose self-tests follow */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN selfTestGeneralOps1( void )\n\t{\n\tBIGNUM a;\n#ifdef BN_LLONG\n\tconst BN_ULONG bnWord1 = ( BN_ULONG  ) ~0, bnWord2 = ( BN_ULONG  ) ~0;\n\tBN_ULLONG bnWordL;\n#endif /* BN_LLONG */\n\n\t/* If we're using double-sized long words to handle overflow from\n\t   standard long words, make sure that things are set up correctly */\n#ifdef BN_LLONG\n\tbnWordL = ( BN_ULLONG ) bnWord1 + bnWord2;\n\tbnWordL >>= BN_BITS2;\n\tif( bnWordL != 1 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Test of overflow handling from\\n  BN_ULONG via \"\n\t\t\t\t\t \"BN_ULLONG failed\" ));\n\t\tDEBUG_DIAG(( \"sizeof( BN_LONG ) = %d,\\n  sizeof( BN_ULLONG ) = %d, \"\n\t\t\t\t\t \"BN_BITS2 = %d\", sizeof( BN_ULONG ), sizeof( BN_ULLONG ),\n\t\t\t\t\t BN_BITS2 ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* BN_LLONG */\n\n\t/* Simple tests that don't need the support of higher-level routines \n\t   like importBignum().  These are fundamental tests that indicate \n\t   serious problems if they fail, so we provide additional diagnostics \n\t   in cases that might occur */\n\tBN_init( &a );\n\tif( !BN_zero( &a ) )\n\t\treturn( FALSE );\n\tif( !BN_is_zero( &a ) || BN_is_one( &a ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Check of BN set to zero failed\" ));\n\t\tDEBUG_DIAG(( \"BN.top = %d, BN.neg = %d, BN.flags = %0X, \"\n\t\t\t\t\t \"BN.d[0] = %0X, BN.d[1] = %0X, BN.d[2] = %0X\", \n\t\t\t\t\t a.top, a.neg, a.flags, a.d[ 0 ], a.d[ 1 ], a.d[ 2 ] ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) )\n\t\treturn( FALSE );\t/* Identical to the above macros */\n\tif( BN_is_odd( &a ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Odd/even check of BN set to zero failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( BN_get_word( &a ) != 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Read of BN set to zero failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !BN_one( &a ) )\n\t\treturn( FALSE );\n\tif( BN_is_zero( &a ) || !BN_is_one( &a ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Check of BN set to one failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( BN_is_word( &a, 0 ) || !BN_is_word( &a, 1 ) )\n\t\treturn( FALSE );\t/* Identical to the above macros */\n\tif( !BN_is_odd( &a ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Odd/even check of BN set to one failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( BN_num_bytes( &a ) != 1 )\n\t\treturn( FALSE );\n\tif( BN_get_word( &a ) != 1 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Read of BN set to one failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tBN_clear( &a );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN selfTestGeneralOps2( void )\n\t{\n\tBIGNUM a;\n\tint status;\n\n\t/* More complex tests that need higher-level routines like importBignum(),\n\t   run after the tests of components of importBignum() have concluded */\n\tBN_init( &a );\n#if BN_BITS2 == 64\n\tstatus = importBignum( &a, \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 9, \n\t\t\t\t\t\t   1, 128, NULL, KEYSIZE_CHECK_NONE );\n#else\n\tstatus = importBignum( &a, \"\\x01\\x00\\x00\\x00\\x00\", 5, 1, 128, NULL, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n#endif /* 64- vs 32-bit */\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( BN_is_zero( &a ) || BN_is_one( &a ) )\n\t\treturn( FALSE );\n\tif( BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) )\n\t\treturn( FALSE );\n\tif( BN_is_odd( &a ) )\n\t\treturn( FALSE );\n\tif( BN_get_word( &a ) != BN_NAN )\n\t\treturn( FALSE );\n\tif( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 1 )\n\t\treturn( FALSE );\n\tif( BN_num_bits( &a ) != BN_BITS2 + 1 )\n\t\treturn( FALSE );\n\tif( !BN_is_bit_set( &a, BN_BITS2 ) )\n\t\treturn( FALSE );\n\tif( BN_is_bit_set( &a, 17 ) || !BN_set_bit( &a, 17 ) || \\\n\t\t!BN_is_bit_set( &a, 17 ) )\n\t\treturn( FALSE );\n#if BN_BITS2 == 64\n\tstatus = importBignum( &a, \"\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\", 9, \n\t\t\t\t\t\t   1, 128, NULL, KEYSIZE_CHECK_NONE );\n#else\n\tstatus = importBignum( &a,\t\"\\x01\\x00\\x00\\x00\\x01\", 5, 1, 128, NULL,\n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n#endif /* 64- vs 32-bit */\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( BN_is_zero( &a ) || BN_is_one( &a ) )\n\t\treturn( FALSE );\n\tif( BN_is_word( &a, 0 ) || BN_is_word( &a, 1 ) )\n\t\treturn( FALSE );\n\tif( !BN_is_odd( &a ) )\n\t\treturn( FALSE );\n\tif( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 1 )\n\t\treturn( FALSE );\n\tif( BN_get_word( &a ) != BN_NAN )\n\t\treturn( FALSE );\n\tif( BN_num_bits( &a ) != BN_BITS2 + 1 )\n\t\treturn( FALSE );\n\tif( !BN_is_bit_set( &a, BN_BITS2 ) )\n\t\treturn( FALSE );\n\tif( BN_is_bit_set( &a, BN_BITS2 + 27 ) || \\\n\t\t!BN_set_bit( &a, BN_BITS2 + 27 ) || \\\n\t\t!BN_is_bit_set( &a, BN_BITS2 + 27 ) )\n\t\treturn( FALSE );\n\t/* Setting a bit off the end of a bignum extends its size, which is why\n\t   the following value doesn't match the one from a few lines earlier */\n\tif( BN_num_bytes( &a ) != ( BN_BITS2 / 8 ) + 4 )\n\t\treturn( FALSE );\n\t/* The bit index for indexing bits is zero-based (since 1 == 1 << 0) but\n\t   for counting bits is one-based, which is why the following comparison\n\t   looks wrong.  Yet another one of OpenSSL's many booby-traps */\n\tif( BN_num_bits( &a ) != BN_BITS2 + 28 )\n\t\treturn( FALSE );\n\tBN_clear( &a );\n\n\treturn( TRUE );\n\t}\n\n/* Make sure that the selected operation gives the required result */\n\n#if defined( DEBUG_DIAGNOSTIC_ENABLE ) && !defined( NDEBUG )\n\nstatic void reportBignumValues( const char *opDescription,\n\t\t\t\t\t\t\t\tconst char *failType,\n\t\t\t\t\t\t\t\tconst BIGNUM *a, const BIGNUM *b,\n\t\t\t\t\t\t\t\tconst BIGNUM *result, \n\t\t\t\t\t\t\t\tconst BIGNUM *expectedResult )\n\t{\n\tDEBUG_DIAG(( \"Operation 'a %s b -> result'\\n  failed (%s), bignum \"\n\t\t\t\t \"values follow\", opDescription, failType ));\n\tprintBignum( a, \"a\" );\n\tprintBignum( b, \"b\" );\n\tprintBignum( expectedResult, \"Expected result\" );\n\tprintBignum( result, \"Actual result\" );\n\t}\n#else\n\n#define reportBignumValues( opDescription, faileType, a, b, result, expectedResult )\n\n#endif /* DEBUG_DIAGNOSTIC_ENABLE !NDEBUG */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN selfTestOp( const SELFTEST_VALUE *selftestValue,\n\t\t\t\t\t\t   IN_ENUM( BN_OP ) const BN_OP_TYPE op,\n\t\t\t\t\t\t   const char *opDescription )\n\t{\n\tBN_CTX bnCTX;\n\tBN_MONT_CTX bnMontCTX;\n\tBIGNUM a, b, mod, result, expectedResult;\n\tBN_ULONG bWord DUMMY_INIT;\n\tconst BOOLEAN isCompareOp = ( op == BN_OP_CMP || op == BN_OP_CMPPART ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE;\n\tconst BOOLEAN isDivOp = ( op == BN_OP_DIV ) ? TRUE : FALSE;\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tconst BOOLEAN isModOp = ( ( op >= BN_OP_MODADD && op <= BN_OP_MODSHIFT ) || \\\n\t\t\t\t\t\t\t  ( op == BN_OP_MONTMODMULT ) ) ? TRUE : FALSE;\n#else\n\tconst BOOLEAN isModOp = ( op == BN_OP_MONTMODMULT ) ? TRUE : FALSE;\n#endif /* USE_ECDH || USE_ECDSA */\n\tBOOLEAN aNeg, expectedResultNeg DUMMY_INIT;\n\tint aLen, expectedResultLen, bValue DUMMY_INIT;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isReadPtr( selftestValue, sizeof( SELFTEST_VALUE ) ) );\n\n\tREQUIRES_B( isEnumRange( op, BN_OP ) );\n\n\t/* The BN_OP_MODWORD is sufficently specialised that we have to handle \n\t   it specially */\n\tif( op == BN_OP_MODWORD )\n\t\t{\n\t\tBN_ULONG word DUMMY_INIT;\n\n\t\tBN_init( &a );\n\n\t\tstatus = importBignum( &a, selftestValue->a, selftestValue->aLen, \n\t\t\t\t\t\t\t   1, 128, NULL, KEYSIZE_CHECK_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tCK( BN_mod_word( &word, &a, selftestValue->bWord ) );\n\t\tif( bnStatusError( bnStatus) || word != selftestValue->resultLen )\n\t\t\treturn( FALSE );\n\n\t\tBN_clear( &a );\n\n\t\treturn( TRUE );\n\t\t}\n\n\tBN_CTX_init( &bnCTX );\n\tBN_MONT_CTX_init( &bnMontCTX );\n\tBN_init( &a );\n\tBN_init( &b );\n\tBN_init( &mod );\n\tBN_init( &result );\n#if BN_BITS2 == 64\n\tstatus = importBignum( &result,\t\t/* Pollute result value */\n\t\t\t\t\t\t   \"\\x55\\x55\\x55\\x55\\x55\\x55\\x55\\x55\" \\\n\t\t\t\t\t\t   \"\\x44\\x44\\x44\\x44\\x44\\x44\\x44\\x44\\x33\\x33\\x33\\x33\" \\\n\t\t\t\t\t\t   \"\\x33\\x33\\x33\\x33\\x22\\x22\\x22\\x22\\x22\\x22\\x22\\x22\" \\\n\t\t\t\t\t\t   \"\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\", \n\t\t\t\t\t\t   40, 1, 128, NULL, KEYSIZE_CHECK_NONE );\n#else\n\tstatus = importBignum( &result,\t\t/* Pollute result value */\n\t\t\t\t\t\t   \"\\xAA\\xAA\\xAA\\xAA\\x99\\x99\\x99\\x99\" \\\n\t\t\t\t\t\t   \"\\x88\\x88\\x88\\x88\\x77\\x77\\x77\\x77\\x66\\x66\\x66\\x66\" \\\n\t\t\t\t\t\t   \"\\x55\\x55\\x55\\x55\\x44\\x44\\x44\\x44\\x33\\x33\\x33\\x33\" \\\n\t\t\t\t\t\t   \"\\x22\\x22\\x22\\x22\\x11\\x11\\x11\\x11\", 40, 1, 128,\n\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n#endif /* 64- vs 32-bit */\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tBN_init( &expectedResult );\n\n\t/* Some of the quantities may have flags indicating that they're meant \n\t   to be treated as negative values, so we have to extract the actual \n\t   value and the negative flag from the overall value */\n\taLen = selftestValue->aLen & ~BN_VAL_NEGATIVE;\n\taNeg = ( selftestValue->aLen & BN_VAL_NEGATIVE ) ? TRUE : FALSE;\n\texpectedResultLen = selftestValue->resultLen & ~BN_VAL_NEGATIVE;\n\texpectedResultNeg = ( selftestValue->resultLen & BN_VAL_NEGATIVE ) ? \\\n\t\t\t\t\t\tTRUE : FALSE;\n\n\t/* Set up the test data */\n\tstatus = importBignum( &a, selftestValue->a, aLen, 1, 128, NULL, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( selftestValue->b != NULL )\n\t\t\t{\n\t\t\tstatus = importBignum( &b, selftestValue->b, selftestValue->bLen, \n\t\t\t\t\t\t\t\t   1, 128, NULL, KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( selftestValue->bLen != 0 )\n\t\t\t\tbValue = selftestValue->bLen;\n\t\t\telse\n\t\t\t\tbWord = selftestValue->bWord;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && !isCompareOp )\n\t\t{\n\t\t/* Some of the div/mod operations produce a result of zero or one, \n\t\t   which we can't import via importBignum() but can obtain by\n\t\t   special-casing the import via BN_set_word() */\n\t\tif( expectedResultLen == 1 )\n\t\t\t{\n\t\t\tCK( BN_set_word( &expectedResult, selftestValue->result[ 0 ] ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = importBignum( &expectedResult, selftestValue->result, \n\t\t\t\t\t\t\t\t   expectedResultLen, 1, 128, NULL, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && isModOp )\n\t\t{\n\t\tstatus = importBignum( &mod, selftestValue->mod, \n\t\t\t\t\t\t\t   selftestValue->modLen, 1, 128, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( aNeg )\n\t\tBN_set_negative( &a, TRUE );\n\n\t/* Perform the requested operation on the values */\n\tswitch( op )\n\t\t{\n\t\tcase BN_OP_CMP:\n\t\t\t/* This is a compare op so bnStatus is the compare result, not \n\t\t\t   an error code */\n\t\t\tbnStatus = BN_cmp( &a, &b );\n\t\t\tbreak;\n\n\t\tcase BN_OP_CMPPART:\n\t\t\t/* As before */\n\t\t\tbnStatus = bn_cmp_part_words( a.d, b.d, min( a.top, b.top ),\n\t\t\t\t\t\t\t\t\t\t  a.top - b.top );\n\t\t\tbreak;\n\n\t\tcase BN_OP_ADD:\n\t\t\tCK( BN_add( &result, &a, &b ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_SUB:\n\t\t\tBN_swap( &expectedResult, &a );\n\t\t\tCK( BN_sub( &result, &a, &b ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_LSHIFT:\n\t\t\tCK( BN_lshift( &result, &a, bValue ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_RSHIFT:\n\t\t\tBN_swap( &expectedResult, &a );\n\t\t\tCK( BN_rshift( &result, &a, bValue ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_ADDWORD:\n\t\t\tCKPTR( BN_copy( &result, &a ) );\n\t\t\tCK( BN_add_word( &result, bWord ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_SUBWORD:\n\t\t\tCKPTR( BN_copy( &result, &expectedResult ) );\n\t\t\tCKPTR( BN_copy( &expectedResult, &a ) );\n\t\t\tCK( BN_sub_word( &result, bWord ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_MULWORD:\n\t\t\tCKPTR( BN_copy( &result, &a ) );\n\t\t\tCK( BN_mul_word( &result, bWord ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_SQR:\n\t\t\tCK( BN_sqr( &result, &a, &bnCTX ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_DIV:\n\t\t\tCK( BN_div( &result, &mod, &a, &b, &bnCTX ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_MONTMODMULT:\n\t\t\tCK( BN_MONT_CTX_set( &bnMontCTX, &mod, &bnCTX ) );\n\t\t\tCK( BN_to_montgomery( &a, &a, &bnMontCTX, &bnCTX ) );\n\t\t\tCK( BN_mod_mul_montgomery( &result, &a, &b, &bnMontCTX, &bnCTX ) );\n\t\t\tbreak;\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t\tcase BN_OP_MODADD:\n\t\t\tCK( BN_mod_add_quick( &result, &a, &b, &mod ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_MODSUB:\n\t\t\tCK( BN_mod_sub_quick( &result, &a, &b, &mod ) );\n\t\t\tbreak;\n\n\t\tcase BN_OP_MODMUL:\n\t\t\tCK( BN_mod_mul( &result, &a, &b, &mod, &bnCTX ) );\n\t\t\tbreak;\n\t\t\n\t\tcase BN_OP_MODSHIFT:\n\t\t\tCK( BN_mod_lshift_quick( &result, &a, bValue, &mod ) );\n\t\t\tbreak;\n#endif /* USE_ECDH || USE_ECDSA */\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\tif( isCompareOp )\n\t\t{\n\t\t/* The compare operations return their result as the return status \n\t\t   so there's no result value to check.  In addition they return\n\t\t   { -1, 0, 1 } so we can't use the processed expectedResultLen \n\t\t   value */\n\t\tif( bnStatus != selftestValue->resultLen )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that we got what we were expecting */\n\tif( BN_cmp( &result, &expectedResult ) )\n\t\t{\n\t\treportBignumValues( opDescription, \"BN_cmp()\", &a, &b, \n\t\t\t\t\t\t\t&result, &expectedResult );\n\t\treturn( FALSE );\n\t\t}\n\tif( expectedResultNeg && !BN_is_negative( &result ) )\n\t\t{\n\t\treportBignumValues( opDescription, \"negative check\", &a, &b, \n\t\t\t\t\t\t\t&result, &expectedResult );\n\t\treturn( FALSE );\n\t\t}\n\tif( isDivOp )\n\t\t{\n\t\tBIGNUM expectedRemainder;\n\n\t\tBN_init( &expectedRemainder );\n\n\t\tif( selftestValue->modLen == 1 )\n\t\t\t{\n\t\t\tCK( BN_set_word( &expectedRemainder, selftestValue->mod[ 0 ] ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = importBignum( &expectedRemainder, selftestValue->mod, \n\t\t\t\t\t\t\t\t   selftestValue->modLen, 1, 128, NULL, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( BN_cmp( &mod, &expectedRemainder ) )\n\t\t\t{\n\t\t\treportBignumValues( opDescription, \"BN_cmp()\", &a, &b, \n\t\t\t\t\t\t\t\t&mod, &expectedRemainder );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tBN_clear( &expectedRemainder );\n\t\t}\n\tBN_clear( &expectedResult );\n\tBN_clear( &result );\n\tBN_clear( &mod );\n\tBN_clear( &b );\n\tBN_clear( &a );\n\tBN_MONT_CTX_free( &bnMontCTX );\n\tBN_CTX_final( &bnCTX );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN selfTestOps( const SELFTEST_VALUE *selftestValueArray,\n\t\t\t\t\t\t\tIN_RANGE( 1, 50 ) const int selftestValueArraySize,\n\t\t\t\t\t\t\tIN_ENUM( BN_OP ) const BN_OP_TYPE op,\n\t\t\t\t\t\t\tconst char *opDescription )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( selftestValueArray, \n\t\t\t\t\t\t\t  selftestValueArraySize * sizeof( SELFTEST_VALUE ) ) );\n\n\tREQUIRES_B( selftestValueArraySize >= 1 && selftestValueArraySize < 50 );\n\tREQUIRES_B( isEnumRange( op, BN_OP ) );\n\n\tLOOP_LARGE( i = 0, selftestValueArray[ i ].a != NULL && \\\n\t\t\t\t\t   i < selftestValueArraySize, i++ )\n\t\t{\n\t\tif( !selfTestOp( &selftestValueArray[ i ], op, opDescription ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Failed %s test #%d\", opDescription, i ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < selftestValueArraySize );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN bnmathSelfTest( void )\n\t{\n\tif( !selfTestBignumFields() )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed bignum fields test\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !selfTestBignumLinkage() )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed bignum linkage test\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !selfTestGeneralOps1() )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed general operations test phase 1\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !selfTestOps( cmpSelftestValues, FS_SIZE( cmpSelftestValues ),\n\t\t\t\t\t  BN_OP_CMP, \"BN_OP_CMP\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( cmpSelftestValues, FS_SIZE( cmpSelftestValues ),\n\t\t\t\t\t  BN_OP_CMPPART, \"BN_OP_CMPPART\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestGeneralOps2() )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed general operations test phase 1\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !selfTestOps( addsubSelftestValues, FS_SIZE( addsubSelftestValues ),\n\t\t\t\t\t  BN_OP_ADD, \"BN_OP_ADD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( addsubSelftestValues, FS_SIZE( addsubSelftestValues ),\n\t\t\t\t\t  BN_OP_SUB, \"BN_OP_SUB\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( shiftSelftestValues, FS_SIZE( shiftSelftestValues ),\n\t\t\t\t\t  BN_OP_LSHIFT, \"BN_OP_LSHIFT\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( shiftSelftestValues, FS_SIZE( shiftSelftestValues ),\n\t\t\t\t\t  BN_OP_RSHIFT, \"BN_OP_RSHIFT\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( addsubWordsSelftestValues, FS_SIZE( addsubWordsSelftestValues ),\n\t\t\t\t\t  BN_OP_ADDWORD, \"BN_OP_ADDWORD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( addsubWordsSelftestValues, FS_SIZE( addsubWordsSelftestValues ),\n\t\t\t\t\t  BN_OP_SUBWORD, \"BN_OP_SUBWORD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( muldivWordsSelftestValues, FS_SIZE( muldivWordsSelftestValues ),\n\t\t\t\t\t  BN_OP_MULWORD, \"BN_OP_MULWORD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( modWordsSelftestValues, FS_SIZE( modWordsSelftestValues ),\n\t\t\t\t\t  BN_OP_MODWORD, \"BN_OP_MODWORD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( sqrSelftestValues, FS_SIZE( sqrSelftestValues ),\n\t\t\t\t\t  BN_OP_SQR, \"BN_OP_SQR\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( divSelftestValues, FS_SIZE( divSelftestValues ),\n\t\t\t\t\t  BN_OP_DIV, \"BN_OP_DIV\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( montModMulSelftestValues, FS_SIZE( montModMulSelftestValues ),\n\t\t\t\t\t  BN_OP_MONTMODMULT, \"BN_OP_MONTMODMULT\" ) )\n\t\treturn( FALSE );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( !selfTestOps( modAddSelftestValues, FS_SIZE( modAddSelftestValues ),\n\t\t\t\t\t  BN_OP_MODADD, \"BN_OP_MODADD\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( modSubSelftestValues, FS_SIZE( modSubSelftestValues ),\n\t\t\t\t\t  BN_OP_MODSUB, \"BN_OP_MODSUB\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( modMulSelftestValues, FS_SIZE( modMulSelftestValues ),\n\t\t\t\t\t  BN_OP_MODMUL, \"BN_OP_MODMUL\" ) )\n\t\treturn( FALSE );\n\tif( !selfTestOps( modShiftSelftestValues, FS_SIZE( modShiftSelftestValues ),\n\t\t\t\t\t  BN_OP_MODSHIFT, \"BN_OP_MODSHIFT\" ) )\n\t\treturn( FALSE );\n#endif /* USE_ECDH || USE_ECDSA */\n\n\treturn( TRUE );\n\t}\n#endif /* USE_PKC && !CONFIG_CONSERVE_MEMORY_EXTRA */\n"
  },
  {
    "path": "deps/cl345/context/ctx_cast.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib CAST-128 Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"cast.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/cast.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CAST\n\n/* Defines to map from EAY to native naming */\n\n#define CAST_BLOCKSIZE\t\t\tCAST_BLOCK\n\n/* The size of the keyscheduled CAST key */\n\n#define CAST_EXPANDED_KEYSIZE\tsizeof( CAST_KEY )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCAST Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* CAST test vectors from CAST specification */\n\nstatic const struct CAST_TEST {\n\tBYTE key[ CAST_KEY_LENGTH + 8 ];\n\tBYTE plaintext[ CAST_BLOCKSIZE + 8 ];\n\tBYTE ciphertext[ CAST_BLOCKSIZE + 8 ];\n\t} testCAST[] = {\n\t{ { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,\n\t\t0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A },\n\t  { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },\n\t  { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 } }\n\t};\n\n/* Test the CAST code against the CAST test vectors */\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getCASTCapability();\n\ttypedef BYTE KEY_DATA[ CAST_EXPANDED_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\tint i, status, LOOP_ITERATOR;\n\n\tmemset( keyDataPtr, 0, CAST_EXPANDED_KEYSIZE );\t/* Keep static analysers happy */\n\tLOOP_SMALL( i = 0, i < sizeof( testCAST ) / sizeof( struct CAST_TEST ), i++ )\n\t\t{\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, testCAST[ i ].key, \n\t\t\t\t\t\t\t CAST_KEY_LENGTH, testCAST[ i ].plaintext,\n\t\t\t\t\t\t\t testCAST[ i ].ciphertext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = CAST_EXPANDED_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCAST En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint blockCount = noBytes / CAST_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Encrypt a block of data */\n\t\tCAST_ecb_encrypt( buffer, buffer, convInfo->key, CAST_ENCRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += CAST_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint blockCount = noBytes / CAST_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Decrypt a block of data */\n\t\tCAST_ecb_encrypt( buffer, buffer, convInfo->key, CAST_DECRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += CAST_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CBC mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tCAST_cbc_encrypt( buffer, buffer, noBytes, convInfo->key,\n\t\t\t\t\t  convInfo->currentIV, CAST_ENCRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tCAST_cbc_encrypt( buffer, buffer, noBytes, convInfo->key,\n\t\t\t\t\t  convInfo->currentIV, CAST_DECRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CFB mode */\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = CAST_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Encrypt the data */\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > CAST_BLOCKSIZE ) ? CAST_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tCAST_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,\n\t\t\t\t\t\t  convInfo->key, CAST_ENCRYPT );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, buffer, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % CAST_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Decrypt data in CFB mode.  Note that the transformation can be made\n   faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp\n   all in one loop */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tBYTE temp[ CAST_BLOCKSIZE + 8 ];\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = CAST_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Decrypt the data */\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CAST_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, bytesToUse );\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, temp, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > CAST_BLOCKSIZE ) ? CAST_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tCAST_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,\n\t\t\t\t\t\t  convInfo->key, CAST_ENCRYPT );\n\n\t\t/* Save the ciphertext */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CAST_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, ivCount );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, temp, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % CAST_BLOCKSIZE );\n\n\t/* Clear the temporary buffer */\n\tzeroise( temp, CAST_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCAST Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key schedule an CAST key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CAST_KEY_LENGTH );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\tCAST_set_key( convInfo->key, CAST_KEY_LENGTH, ( BYTE * ) key );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_CAST, bitsToBytes( 64 ), \"CAST-128\", 8,\n\tMIN_KEYSIZE, bitsToBytes( 128 ), bitsToBytes( 128 ),\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB\n#endif /* USE_CFB */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getCASTCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_CAST */\n"
  },
  {
    "path": "deps/cl345/context/ctx_des.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib DES Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"des.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/des.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DES\n\n/* The DES block size */\n\n#define DES_BLOCKSIZE\t\t\t8\n\n#if defined( INC_ALL )\n  #include \"testdes.h\"\n#else\n  #include \"crypt/testdes.h\"\n#endif /* Compiler-specific includes */\n\n/* The scheduled DES key and size of the keyscheduled DES key */\n\n#define DES_KEY\t\t\t\t\tKey_schedule\n#define DES_KEYSIZE\t\t\t\tsizeof( Key_schedule )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDES Self-test Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the DES implementation against the test vectors given in NBS Special\n   Publication 500-20, 1980 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int testLoop( const DES_TEST *testDES, int iterations )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getDESCapability();\n\ttypedef BYTE KEY_DATA[ DES_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 8 ); \n\tint i, status, LOOP_ITERATOR;\n\n\tLOOP_LARGE( i = 0, i < iterations, i++ )\n\t\t{\n\t\t/* The self-test uses weak keys, which means they'll be rejected by \n\t\t   the key-load function if it checks for these.  For the OpenSSL\n\t\t   DES implementation we can kludge around this by temporarily \n\t\t   clearing the global des_check_key value, but for other \n\t\t   implementations some alternative workaround will be necessary */\n\t\tdes_check_key = FALSE;\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, testDES[ i ].key, \n\t\t\t\t\t\t\t DES_BLOCKSIZE, testDES[ i ].plaintext,\n\t\t\t\t\t\t\t testDES[ i ].ciphertext );\n\t\tdes_check_key = TRUE;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\t/* Check the DES test vectors.  Note that we don't explicitly test\n\t   the RS values, however these are tested implicitly since they're\n\t   just the decrypt side of the KP tests */\n\tif( ( testLoop( testIP, sizeof( testIP ) / \\\n\t\t\t\t\t\t\tsizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testVP, sizeof( testVP ) / \\\n\t\t\t\t\t\t\tsizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testKP, sizeof( testKP ) / \\\n\t\t\t\t\t\t\tsizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testDP, sizeof( testDP ) / \\\n\t\t\t\t\t\t\tsizeof( DES_TEST ) ) != CRYPT_OK ) || \\\n\t\t( testLoop( testSB, sizeof( testSB ) / \\\n\t\t\t\t\t\t\tsizeof( DES_TEST ) ) != CRYPT_OK ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = DES_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDES En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint blockCount = noBytes / DES_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Encrypt a block of data */\n\t\tdes_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, \n\t\t\t\t\t\t *( DES_KEY * ) convInfo->key, DES_ENCRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += DES_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint blockCount = noBytes / DES_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Decrypt a block of data */\n\t\tdes_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer, \n\t\t\t\t\t\t *( DES_KEY * ) convInfo->key, DES_DECRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += DES_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CBC mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tdes_ncbc_encrypt( buffer, buffer, noBytes, *( DES_KEY * ) convInfo->key,\n\t\t\t\t\t  ( C_Block * ) convInfo->currentIV, DES_ENCRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tdes_ncbc_encrypt( buffer, buffer, noBytes, *( DES_KEY * ) convInfo->key,\n\t\t\t\t\t  ( C_Block * ) convInfo->currentIV, DES_DECRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CFB mode */\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = DES_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Encrypt the data */\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tdes_ecb_encrypt( ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t *( DES_KEY * ) convInfo->key, DES_ENCRYPT );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_MED( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, buffer, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % DES_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tBYTE temp[ DES_BLOCKSIZE + 8 ];\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = DES_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Decrypt the data */\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, DES_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, bytesToUse );\n\t\tLOOP_MED( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, temp, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tdes_ecb_encrypt( ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t ( C_Block * ) convInfo->currentIV,\n\t\t\t\t\t\t *( DES_KEY * ) convInfo->key, DES_ENCRYPT );\n\n\t\t/* Save the ciphertext */\n\t\tREQUIRES( rangeCheck( ivCount, 1, DES_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, ivCount );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_MED( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, temp, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % DES_BLOCKSIZE );\n\n\t/* Clear the temporary buffer */\n\tzeroise( temp, DES_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDES Key Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key schedule a DES key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= DES_BLOCKSIZE );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* Call the libdes key schedule code.  Returns with -1 if the key parity\n\t   is wrong (which never occurs since we force the correct parity) or -2\n\t   if a weak key is used.  In theory this could leave us open to timing\n\t   attacks (a memcmp() implemented as a bytewise operation will exit on \n\t   the first mis-matching byte), but in practice the trip through the\n\t   kernel adds enough skew to make the one or two clock cycle difference\n\t   undetectable */\n\tdes_set_odd_parity( ( C_Block * ) convInfo->userKey );\n\tif( des_key_sched( ( C_Block * ) convInfo->userKey, \n\t\t\t\t\t   *( DES_KEY * ) convInfo->key ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_DES, bitsToBytes( 64 ), \"DES\", 3,\n\tMIN_KEYSIZE, bitsToBytes( 64 ), bitsToBytes( 64 ),\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB\n#endif /* USE_CFB */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDESCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n#endif /* USE_DES */\n"
  },
  {
    "path": "deps/cl345/context/ctx_dh.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Diffie-Hellman Key Exchange Routines\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* The DH key exchange process is somewhat complex because there are two\n   phases involved for both sides, an \"export\" and an \"import\" phase, and\n   they have to be performed in the correct order.  The sequence of\n   operations is:\n\n\tA.load:\t\tset p, g from fixed or external values\n\t\t\t\tx(A) = rand, x s.t. 0 < x < q-1\n\n\tA.export\ty(A) = g^x(A) mod p\t\terror if y != 0 at start\n\t\t\t\toutput = y(A)\n\n\tB.load\t\tread p, g / set p, g from external values\n\t\t\t\tx(B) = rand, x s.t. 0 < x < q-1\n\n\tB.import\ty(A) = input\n\t\t\t\tz = y(A)^x(B) mod p\n\n\tB.export\ty(B) = g^x(B) mod p\t\terror if y != 0 at start\n\t\t\t\toutput = y(B)\n\n\tA.import\ty(B) = input\n\t\t\t\tz = y(B)^x(A) mod p\n\n   Note that we have to set x when we load p and g because otherwise we'd\n   have to set x(A) on export and x(B) on import, which is tricky since the\n   DH code doesn't know whether it's working with A or B */\n\n#ifdef USE_DH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCONTEXT_INFO checkContextInfo;\n\tPKC_INFO *sourcePkcInfo = contextInfoPtr->ctxPKC;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tKEYAGREE_PARAMS keyAgreeParams1, keyAgreeParams2;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\n\t/* The DH pairwise check is a bit more complex than the one for the\n\t   other algorithms because there's no matched public/private key pair,\n\t   so we have to load a second DH key to use for key agreement with\n\t   the first one */\n\tstatus = staticInitContext( &checkContextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetDHCapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tCKPTR( BN_copy( &pkcInfo->dlpParam_p, &sourcePkcInfo->dlpParam_p ) );\n\tCKPTR( BN_copy( &pkcInfo->dlpParam_g, &sourcePkcInfo->dlpParam_g ) );\n\tCKPTR( BN_copy( &pkcInfo->dlpParam_q, &sourcePkcInfo->dlpParam_q ) );\n\tCKPTR( BN_copy( &pkcInfo->dlpParam_y, &sourcePkcInfo->dlpParam_y ) );\n\tCKPTR( BN_copy( &pkcInfo->dlpParam_x, &sourcePkcInfo->dlpParam_x ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tstaticDestroyContext( &checkContextInfo );\n\t\treturn( getBnStatusBool( bnStatus ) );\n\t\t}\n\n\t/* Perform the pairwise test using the check key */\n\tcapabilityInfoPtr = DATAPTR_GET( checkContextInfo.capabilityInfo );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\tmemset( &keyAgreeParams1, 0, sizeof( KEYAGREE_PARAMS ) );\n\tmemset( &keyAgreeParams2, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = capabilityInfoPtr->initKeyFunction( &checkContextInfo, NULL, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->encryptFunction( contextInfoPtr,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->encryptFunction( &checkContextInfo,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( contextInfoPtr,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( &checkContextInfo,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusError( status ) || \\\n\t\tkeyAgreeParams1.wrappedKeyLen != keyAgreeParams2.wrappedKeyLen || \\\n\t\tmemcmp( keyAgreeParams1.wrappedKey, keyAgreeParams2.wrappedKey, \n\t\t\t\tkeyAgreeParams1.wrappedKeyLen ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\n\t/* Clean up */\n\tstaticDestroyContext( &checkContextInfo );\n\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the Diffie-Hellman implementation using a sample key.  Because a lot \n   of the high-level encryption routines don't exist yet, we cheat a bit and \n   set up a dummy encryption context with just enough information for the \n   following code to work */\n\ntypedef struct {\n\tconst int pLen; const BYTE p[ 128 ];\n\tconst int qLen; const BYTE q[ 20 ];\n\tconst int gLen; const BYTE g[ 128 ];\n\tconst int xLen; const BYTE x[ 20 ];\n\tconst int yLen; const BYTE y[ 128 ];\n\t} DLP_KEY;\n\nstatic const DLP_KEY dlpTestKey = {\n\t/* p */\n\t128,\n\t{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE, \n\t  0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27, \n\t  0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3, \n\t  0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10, \n\t  0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88, \n\t  0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36, \n\t  0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30, \n\t  0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE, \n\t  0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71, \n\t  0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F, \n\t  0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F, \n\t  0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB, \n\t  0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D, \n\t  0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09, \n\t  0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F, \n\t  0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 }, \n\n\t/* q */\n\t20,\n\t{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79, \n\t  0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90, \n\t  0x97, 0x13, 0x26, 0x1D }, \n\n\t/* g */\n\t128,\n\t{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42, \n\t  0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31, \n\t  0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11, \n\t  0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79, \n\t  0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37, \n\t  0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4, \n\t  0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88, \n\t  0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F, \n\t  0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9, \n\t  0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8, \n\t  0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12, \n\t  0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78, \n\t  0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2, \n\t  0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16, \n\t  0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE, \n\t  0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B }, \n\n\t/* x */\n\t20,\n\t{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71, \n\t  0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4, \n\t  0xF2, 0xAB, 0x54, 0xA1 }, \n\n\t/* y */\n\t128,\n\t{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA, \n\t  0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D, \n\t  0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E, \n\t  0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51, \n\t  0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5, \n\t  0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8, \n\t  0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59, \n\t  0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90, \n\t  0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C, \n\t  0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52, \n\t  0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD, \n\t  0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92, \n\t  0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC, \n\t  0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A, \n\t  0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50, \n\t  0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetDHCapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\tstatus = importBignum( &pkcInfo->dlpParam_p, dlpTestKey.p, \n\t\t\t\t\t\t   dlpTestKey.pLen, DLPPARAM_MIN_P, \n\t\t\t\t\t\t   DLPPARAM_MAX_P, NULL, KEYSIZE_CHECK_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_g, dlpTestKey.g, \n\t\t\t\t\t\t\t   dlpTestKey.gLen, DLPPARAM_MIN_G, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_G, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_q, dlpTestKey.q, \n\t\t\t\t\t\t\t   dlpTestKey.qLen, DLPPARAM_MIN_Q, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_y, dlpTestKey.y, \n\t\t\t\t\t\t\t   dlpTestKey.yLen, DLPPARAM_MIN_Y, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_x, dlpTestKey.x, \n\t\t\t\t\t\t\t   dlpTestKey.xLen, DLPPARAM_MIN_X, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_X, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\tretIntError();\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Perform the test key exchange on a block of data */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusOK( status ) && \\\n\t\t!pairwiseConsistencyTest( &contextInfo ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( status );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDiffie-Hellman Key Exchange Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform phase 1 of Diffie-Hellman (\"export\").  We have to append the\n   distinguisher 'Fn' to the name since some systems already have 'encrypt'\n   and 'decrypt' in their standard headers */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );\n\tREQUIRES( !BN_is_zero( &pkcInfo->dlpParam_y ) );\n\n\t/* y is generated either at keygen time for static DH or as a side-effect\n\t   of the implicit generation of the x value for ephemeral DH, so all we\n\t   have to do is copy it to the output */\n\tstatus = exportBignum( keyAgreeParams->publicValue, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\t\t   &keyAgreeParams->publicValueLen, \n\t\t\t\t\t\t   &pkcInfo->dlpParam_y );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform phase 2 of Diffie-Hellman (\"import\") */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )\n\t{\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &pkcInfo->dlpParam_p;\n\tBIGNUM *z = &pkcInfo->tmp1;\n\tint offset, bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\tassert( isReadPtrDynamic( keyAgreeParams->publicValue, \n\t\t\t\t\t\t\t  keyAgreeParams->publicValueLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );\n\tREQUIRES( keyAgreeParams->publicValueLen >= MIN_PKCSIZE && \\\n\t\t\t  keyAgreeParams->publicValueLen < MAX_INTLENGTH_SHORT );\n\n\t/* The other party's y value will be stored with the key agreement info\n\t   rather than having been read in when we read the DH public key so we\n\t   need to import it now.\n\t   \n\t   Since reading and storing the other party's value changes the context \n\t   data, we need to force a recalculation of the data checksum after the \n\t   import.  We don't need to perform the check beforehand since it's \n\t   just been done by the caller */\n\tstatus = importBignum( &pkcInfo->dhParam_yPrime,\n\t\t\t\t\t\t   keyAgreeParams->publicValue, \n\t\t\t\t\t\t   keyAgreeParams->publicValueLen,\n\t\t\t\t\t\t   DLPPARAM_MIN_Y, DLPPARAM_MAX_Y, p, \n\t\t\t\t\t\t   KEYSIZE_CHECK_PKC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpkcInfo->checksum = 0L;\n\tstatus = checksumContextData( contextInfoPtr->ctxPKC, CRYPT_ALGO_DH, \n\t\t\t\t\t\t\t\t  TRUE );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Export z = y^x mod p.  We need to use separate y and z values because\n\t   the bignum code can't handle modexp with the first two parameters the\n\t   same */\n\tCK( BN_mod_exp_mont( z, &pkcInfo->dhParam_yPrime, &pkcInfo->dlpParam_x,\n\t\t\t\t\t\t p, &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\toffset = bitsToBytes( pkcInfo->keySizeBits ) - BN_num_bytes( z );\n\tENSURES( offset >= 0 && offset <= bitsToBytes( pkcInfo->keySizeBits ) );\n\tif( offset > 16 )\n\t\t{\n\t\t/* If the resulting value has more than 128 bits of leading zeroes\n\t\t   then there's something wrong */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tstatus = exportBignum( keyAgreeParams->wrappedKey, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t   &keyAgreeParams->wrappedKeyLen, z );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the result looks random.  This is done to defend \n\t   against (most) small-subgroup confinement attacks */\n\tif( !checkEntropy( keyAgreeParams->wrappedKey, \n\t\t\t\t\t   keyAgreeParams->wrappedKeyLen ) )\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the\n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tconst CRYPT_PKCINFO_DLP *dhKey = ( CRYPT_PKCINFO_DLP * ) key;\n\t\tint status;\n\n\t\tif( dhKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n\t\tstatus = importBignum( &pkcInfo->dlpParam_p, dhKey->p, \n\t\t\t\t\t\t\t   bitsToBytes( dhKey->pLen ),\n\t\t\t\t\t\t\t   DLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_PKC );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_g, dhKey->g, \n\t\t\t\t\t\t\t\t   bitsToBytes( dhKey->gLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_q, dhKey->q, \n\t\t\t\t\t\t\t\t   bitsToBytes( dhKey->qLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_y, dhKey->y, \n\t\t\t\t\t\t\t\t   bitsToBytes( dhKey->yLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !dhKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_x, dhKey->x, \n\t\t\t\t\t\t\t\t   bitsToBytes( dhKey->xLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_X, DLPPARAM_MAX_X,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup.  DH keys may follow PKCS #3 \n\t   rather than X9.42 which means that we can't do extended checking \n\t   using q, so if q is zero we denote it as a PKCS #3 key.  This is \n\t   only permitted for DH keys and PGP Elgamal keys, other key types will \n\t   fail the check if q = 0 */\n\treturn( initCheckDLPkey( contextInfoPtr, \n\t\t\t\t\t\t\t BN_is_zero( &pkcInfo->dlpParam_q ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\tstatus = generateDLPkey( contextInfoPtr, keySizeBits );\n\tif( cryptStatusOK( status ) && \\\n\t\t!pairwiseConsistencyTest( contextInfoPtr ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated DH key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_DH, bitsToBytes( 0 ), \"Diffie-Hellman\", 14,\n\tMIN_PKCSIZE, bitsToBytes( 1536 ), CRYPT_MAX_PKCSIZE,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, \n\tencryptFn, decryptFn\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDHCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_DH */\n"
  },
  {
    "path": "deps/cl345/context/ctx_dsa.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib DSA Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DSA\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPredefined DSA p, q, and g Parameters\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* We never use shared DSA parameters because they allow forgery of\n   signatures on certificates.  This works as follows: Suppose that the\n   certificate contains a copy of the certificate signer's DSA parameters,\n   and the verifier of the certificate has a copy of the signer's public key\n   but not the signer's DSA parameters (which are shared with other keys).\n   If the verifier uses the DSA parameters from the certificate along with\n   the signer's public key to verify the signature on the certificate, then\n   an attacker can create bogus certificates by choosing a random u and\n   finding its inverse v modulo q (uv is congruent to 1 modulo q).  Then\n   take the certificate signer's public key g^x and compute g' = (g^x)^u.\n   Then g'^v = g^x.  Using the DSA parameters p, q, g', the signer's public\n   key corresponds to the private key v, which the attacker knows.  The\n   attacker can then create a bogus certificate, put parameters (p, q, g')\n   in it, and sign it with the DSA private key v to create an apparently\n   valid certificate.  This works with the DSA OID that makes p, q, and g\n   unauthenticated public parameters and y the public key, but not the one\n   that makes p, q, g, and y the public key */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Technically, post-FIPS 186-2 DSA can be used with any hash function, \n   including ones with a block size larger than the subgroup order (although \n   in practice the hash function always seems to be matched to the subgroup \n   size).  To handle the possibility of a mismatched size we use the \n   following custom conversion function, which applies the conversion rules \n   for transforming the hash value into an integer from FIPS 186-3, \"the \n   leftmost min( N, outlen ) bits of Hash( M )\" where N = sizeof( q ).  \n   Mathematically, this is equivalent to first converting the value to a \n   bignum and then right-shifting it by hlen - nlen bits, where hlen is the \n   hash length in bits (a more generic way to view the required conversion is \n   'while( BN_num_bits( hash ) > BN_num_bits( n ) { BN_rshift( hash, 1 ); }') */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int hashToBignum( INOUT BIGNUM *bignum, \n\t\t\t\t\t\t IN_BUFFER( hashLength ) const void *hash, \n\t\t\t\t\t\t IN_LENGTH_HASH const int hashLength, \n\t\t\t\t\t\t const BIGNUM *q )\n\t{\n\tconst int hLen = bytesToBits( hashLength );\n\tconst int qLen = BN_num_bits( q );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtrDynamic( hash, hashLength ) );\n\tassert( isReadPtr( q, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( hashLength >= max( 20, MIN_HASHSIZE ) && \\\n\t\t\t  hashLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( qLen >= bytesToBits( 20 ) && \\\n\t\t\t  qLen <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Convert the hash value into a bignum.  We have to be careful when\n\t   we specify the bounds because, with increasingly smaller \n\t   probabilities, the leading bytes of the hash value may be zero.\n\t   The check used here gives one in 4 billion chance of a false\n\t   positive */\n\tstatus = importBignum( bignum, hash, hashLength, \n\t\t\t\t\t\t   hashLength - 3, hashLength + 1, NULL, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Shift out any extra bits */\n\tif( hLen > qLen )\n\t\t{\n\t\tCK( BN_rshift( bignum, bignum, hLen - qLen ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\tENSURES( sanityCheckBignum( bignum ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since we're doing the self-test using the FIPS 186 values we use the \n   following fixed k and hash values rather than a randomly-generated \n   value */\n\nstatic const BYTE shaM[] = {\n\t0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A,\n\t0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C,\n\t0x9C, 0xD0, 0xD8, 0x9D\n\t};\n\nstatic const BYTE kVal[] = {\n\t0x35, 0x8D, 0xAD, 0x57, 0x14, 0x62, 0x71, 0x0F,\n\t0x50, 0xE2, 0x54, 0xCF, 0x1A, 0x37, 0x6B, 0x2B,\n\t0xDE, 0xAA, 0xDF, 0xBF\n\t};\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ 128 + 8 ];\n\tint sigSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\n\t/* Generate a signature with the private key */\n\tsetDLPParams( &dlpParams, shaM, 20, buffer, 128 );\n\tdlpParams.inLen2 = -999;\n\tstatus = capabilityInfoPtr->signFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Verify the signature with the public key */\n\tsigSize = dlpParams.outLen;\n\tsetDLPParams( &dlpParams, shaM, 20, NULL, 0 );\n\tdlpParams.inParam2 = buffer;\n\tdlpParams.inLen2 = sigSize;\n\tstatus = capabilityInfoPtr->sigCheckFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the DSA implementation using the sample key and hash from FIPS 186\n   (we actually use a generated 1024-bit key because the FIPS 186 key at\n   512 bits is too short to load).  Because a lot of the high-level \n   encryption routines don't exist yet, we cheat a bit and set up a dummy \n   encryption context with just enough information for the following code to \n   work */\n\ntypedef struct {\n\tconst int pLen; const BYTE p[ 128 ];\n\tconst int qLen; const BYTE q[ 20 ];\n\tconst int gLen; const BYTE g[ 128 ];\n\tconst int xLen; const BYTE x[ 20 ];\n\tconst int yLen; const BYTE y[ 128 ];\n\t} DLP_KEY;\n\n#if 0\t/* FIPS 186 test key is too small to be loaded */\n\nstatic const DLP_PRIVKEY dlpTestKey = {\n\t/* p */\n\t64,\n\t{ 0x8D, 0xF2, 0xA4, 0x94, 0x49, 0x22, 0x76, 0xAA,\n\t  0x3D, 0x25, 0x75, 0x9B, 0xB0, 0x68, 0x69, 0xCB,\n\t  0xEA, 0xC0, 0xD8, 0x3A, 0xFB, 0x8D, 0x0C, 0xF7,\n\t  0xCB, 0xB8, 0x32, 0x4F, 0x0D, 0x78, 0x82, 0xE5,\n\t  0xD0, 0x76, 0x2F, 0xC5, 0xB7, 0x21, 0x0E, 0xAF,\n\t  0xC2, 0xE9, 0xAD, 0xAC, 0x32, 0xAB, 0x7A, 0xAC,\n\t  0x49, 0x69, 0x3D, 0xFB, 0xF8, 0x37, 0x24, 0xC2,\n\t  0xEC, 0x07, 0x36, 0xEE, 0x31, 0xC8, 0x02, 0x91 },\n\t/* q */\n\t20,\n\t{ 0xC7, 0x73, 0x21, 0x8C, 0x73, 0x7E, 0xC8, 0xEE,\n\t  0x99, 0x3B, 0x4F, 0x2D, 0xED, 0x30, 0xF4, 0x8E,\n\t  0xDA, 0xCE, 0x91, 0x5F },\n\t/* g */\n\t64,\n\t{ 0x62, 0x6D, 0x02, 0x78, 0x39, 0xEA, 0x0A, 0x13,\n\t  0x41, 0x31, 0x63, 0xA5, 0x5B, 0x4C, 0xB5, 0x00,\n\t  0x29, 0x9D, 0x55, 0x22, 0x95, 0x6C, 0xEF, 0xCB,\n\t  0x3B, 0xFF, 0x10, 0xF3, 0x99, 0xCE, 0x2C, 0x2E,\n\t  0x71, 0xCB, 0x9D, 0xE5, 0xFA, 0x24, 0xBA, 0xBF,\n\t  0x58, 0xE5, 0xB7, 0x95, 0x21, 0x92, 0x5C, 0x9C,\n\t  0xC4, 0x2E, 0x9F, 0x6F, 0x46, 0x4B, 0x08, 0x8C,\n\t  0xC5, 0x72, 0xAF, 0x53, 0xE6, 0xD7, 0x88, 0x02 },\n\t/* x */\n\t20,\n\t{ 0x20, 0x70, 0xB3, 0x22, 0x3D, 0xBA, 0x37, 0x2F,\n\t  0xDE, 0x1C, 0x0F, 0xFC, 0x7B, 0x2E, 0x3B, 0x49,\n\t  0x8B, 0x26, 0x06, 0x14 },\n\t/* y */\n\t64,\n\t{ 0x19, 0x13, 0x18, 0x71, 0xD7, 0x5B, 0x16, 0x12,\n\t  0xA8, 0x19, 0xF2, 0x9D, 0x78, 0xD1, 0xB0, 0xD7,\n\t  0x34, 0x6F, 0x7A, 0xA7, 0x7B, 0xB6, 0x2A, 0x85,\n\t  0x9B, 0xFD, 0x6C, 0x56, 0x75, 0xDA, 0x9D, 0x21,\n\t  0x2D, 0x3A, 0x36, 0xEF, 0x16, 0x72, 0xEF, 0x66,\n\t  0x0B, 0x8C, 0x7C, 0x25, 0x5C, 0xC0, 0xEC, 0x74,\n\t  0x85, 0x8F, 0xBA, 0x33, 0xF4, 0x4C, 0x06, 0x69,\n\t  0x96, 0x30, 0xA7, 0x6B, 0x03, 0x0E, 0xE3, 0x33 }\n\t};\n#endif /* 0 */\n\nstatic const DLP_KEY dlpTestKey = {\n\t/* p */\n\t128,\n\t{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE, \n\t  0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27, \n\t  0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3, \n\t  0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10, \n\t  0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88, \n\t  0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36, \n\t  0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30, \n\t  0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE, \n\t  0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71, \n\t  0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F, \n\t  0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F, \n\t  0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB, \n\t  0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D, \n\t  0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09, \n\t  0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F, \n\t  0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 }, \n\n\t/* q */\n\t20,\n\t{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79, \n\t  0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90, \n\t  0x97, 0x13, 0x26, 0x1D }, \n\n\t/* g */\n\t128,\n\t{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42, \n\t  0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31, \n\t  0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11, \n\t  0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79, \n\t  0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37, \n\t  0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4, \n\t  0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88, \n\t  0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F, \n\t  0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9, \n\t  0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8, \n\t  0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12, \n\t  0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78, \n\t  0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2, \n\t  0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16, \n\t  0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE, \n\t  0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B }, \n\n\t/* x */\n\t20,\n\t{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71, \n\t  0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4, \n\t  0xF2, 0xAB, 0x54, 0xA1 }, \n\n\t/* y */\n\t128,\n\t{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA, \n\t  0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D, \n\t  0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E, \n\t  0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51, \n\t  0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5, \n\t  0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8, \n\t  0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59, \n\t  0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90, \n\t  0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C, \n\t  0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52, \n\t  0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD, \n\t  0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92, \n\t  0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC, \n\t  0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A, \n\t  0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50, \n\t  0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetDSACapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importBignum( &pkcInfo->dlpParam_p, dlpTestKey.p, \n\t\t\t\t\t\t   dlpTestKey.pLen, DLPPARAM_MIN_P, \n\t\t\t\t\t\t   DLPPARAM_MAX_P, NULL, KEYSIZE_CHECK_PKC );\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_q, dlpTestKey.q, \n\t\t\t\t\t\t\t   dlpTestKey.qLen, DLPPARAM_MIN_Q, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_g, dlpTestKey.g, \n\t\t\t\t\t\t\t   dlpTestKey.gLen, DLPPARAM_MIN_G, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_G, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_y, dlpTestKey.y, \n\t\t\t\t\t\t\t   dlpTestKey.yLen, DLPPARAM_MIN_Y, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_x, dlpTestKey.x, \n\t\t\t\t\t\t\t   dlpTestKey.xLen, DLPPARAM_MIN_X, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_X, &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) ) \n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\tretIntError();\n\t\t}\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Perform the test sign/sig.check of the FIPS 186 test values */\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\t!pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Try it again with side-channel protection enabled */\n\tSET_FLAG( contextInfo.flags, CONTEXT_FLAG_SIDECHANNELPROTECTION );\n\tif( !pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* The checking for memory faults is performed at the \n\t   MESSAGE_CTX_ENCRYPT level, so it won't be detected when we call the\n\t   function directly via an internal code pointer */\n#if 0\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ 128 + 8 ];\n\n\t/* Finally, make sure that the memory fault-detection is working */\n\tpkcInfo->dlpParam_g.d[ 8 ] ^= 0x0011;\n\tsetDLPParams( &dlpParams, shaM, 20, buffer, 128 );\n\tdlpParams.inLen2 = -999;\n\tstatus = capabilityInfoPtr->signFunction( &contextInfo,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fault-detection couldn't detect a bit-flip, there's a \n\t\t   problem */\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#else\n\t/* Emulation of what the above code would do */\n\tpkcInfo->dlpParam_g.d[ 8 ] ^= 0x0011;\n\tstatus = checksumContextData( pkcInfo, CRYPT_ALGO_DSA, TRUE );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#endif /* 0 */\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate/Check a Signature\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since DSA signature generation produces two values and the cryptEncrypt()\n   model only provides for passing a byte string in and out (or, more\n   specifically, the internal bignum data can't be exported to the outside\n   world) we need to encode the resulting data into a flat format.  This is\n   done by encoding the output as an X9.31 Dss-Sig record:\n\n\tDss-Sig ::= SEQUENCE {\n\t\tr\tINTEGER,\n\t\ts\tINTEGER\n\t\t} */\n\n/* Sign a single block of data  */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sign( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_ENCODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->encodeDLValuesFunction );\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;\n\tBIGNUM *g = &pkcInfo->dlpParam_g, *x = &pkcInfo->dlpParam_x;\n\tBIGNUM *hash = &pkcInfo->tmp1, *k = &pkcInfo->tmp2, *kInv = &pkcInfo->tmp3;\n\tBIGNUM *r = &pkcInfo->dlpTmp1, *s = &pkcInfo->dlpTmp2;\n\tconst int qLen = BN_num_bytes( q );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( dlpParams->inParam1, dlpParams->inLen1 ) );\n\tassert( isWritePtrDynamic( dlpParams->outParam, dlpParams->outLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( dlpParams->inLen1 >= max( 20, MIN_HASHSIZE ) && \\\n\t\t\t  dlpParams->inLen1 <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( dlpParams->inParam2 == NULL && \\\n\t\t\t  ( dlpParams->inLen2 == 0 || dlpParams->inLen2 == -999 ) );\n\tREQUIRES( dlpParams->outLen >= ( 2 + dlpParams->inLen1 ) * 2 && \\\n\t\t\t  dlpParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( encodeDLValuesFunction != NULL );\n\tREQUIRES( qLen >= DLPPARAM_MIN_Q && qLen <= DLPPARAM_MAX_Q )\n\n\t/* Generate the secret random value k.  During the initial self-test\n\t   the random data pool may not exist yet, and may in fact never exist in\n\t   a satisfactory condition if there isn't enough randomness present in\n\t   the system to generate cryptographically strong random numbers.  To\n\t   bypass this problem, if the caller passes in a second length parameter\n\t   of -999 we know that it's an internal self-test call and use a fixed\n\t   bit pattern for k that avoids having to call generateBignum() (this\n\t   also means that we can use the FIPS 186 self-test value for k).  This \n\t   is a somewhat ugly use of 'magic numbers', but it's safe because this\n\t   function can only be called internally, so all we need to trap is\n\t   accidental use of the parameter which is normally unused.\n\t   \n\t   Since the size of k, in bits, is less than 160 (20 bytes), we give\n\t   the minimum length as 19 bytes rather than 20 */\n\tif( dlpParams->inLen2 == -999 )\n\t\t{\n\t\tstatus = importBignum( k, ( BYTE * ) kVal, 20, 19, 20, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\telse\n\t\t{\n\t\t/* Generate the random value k.  FIPS 186 requires (Appendix 3)\n\t\t   that this be done with:\n\n\t\t\tk = G(t,KKEY) mod q\n\n\t\t   where G(t,c) produces a 160-bit output, however this produces a\n\t\t   slight bias in k that that allows the private key x to be \n\t\t   recovered once sufficient signatures have been generated.  The \n\t\t   difficulty of recovering x depends on the number of signatures \n\t\t   generated, the number of bits leaked, the how recent the attack \n\t\t   is (they get better over time).  The best reference for this is \n\t\t   probably \"The Insecurity of the Digital Signature Algorithm with \n\t\t   Partially Known Nonces\" by Phong Nguyen and Igor Shparlinski or \n\t\t   more recently Serge Vaudenay's \"Evaluation Report on DSA\"), but \n\t\t   as a rule of thumb even three or four known bits and a handful of \n\t\t   signatures is enough to allow recovery of x.  Because of this we \n\t\t   start with a value which is DLP_OVERFLOW_SIZE bytes larger than q \n\t\t   and then do the reduction, eliminating the bias, which was also\n\t\t   required by later versions of FIPS 186.\n\t\t   \n\t\t   We also add (meaning \"mix in\" rather than strictly \n\t\t   \"arithmetically add\") the message hash to k to curtail problems \n\t\t   in the incredibly unlikely situation that the RNG value repeats */\n\t\tREQUIRES( qLen >= 20 && qLen <= CRYPT_MAX_PKCSIZE );\n\t\tstatus = generateBignumEx( k, bytesToBits( qLen ) + \\\n\t\t\t\t\t\t\t\t\t  bytesToBits( DLP_OVERFLOW_SIZE ), 0x80, \n\t\t\t\t\t\t\t\t   0, dlpParams->inParam1, dlpParams->inLen1,\n\t\t\t\t\t\t\t\t   NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\t/* Use constant-time modexp() to protect the secret random value \n\t\t   from timing channels.  We could also use blinding, but neither of\n\t\t   these measures are actually terribly useful because we're using a \n\t\t   random exponent each time so the timing information isn't of much\n\t\t   use to an attacker */\n\t\tBN_set_flags( k, BN_FLG_CONSTTIME );\n\t\t}\n\tCK( BN_mod( k, k, q, \t\t\t\t/* Reduce k to the correct range */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Make sure that the result isn't zero (or more generally less than 64\n\t   bits).  Admittedly the chances of this are infinitesimally small \n\t   (2^-160 or less for a value of zero, 2^-96 for 64 bits) but someone's \n\t   bound to complain if we don't check */\n\tENSURES( BN_num_bytes( k ) > 8 );\n\n\t/* Convert the hash value to an integer in the proper range */\n\tstatus = hashToBignum( hash, dlpParams->inParam1, dlpParams->inLen1, q );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* r = ( g ^ k mod p ) mod q */\n\tCK( BN_mod_exp_mont( r, g, k, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\tCK( BN_mod( r, r, q, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* s = k^-1 * ( hash + x * r ) mod q */\n\tCKPTR( BN_mod_inverse( kInv, k, q,\t/* temp = k^-1 mod q */\n\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\tCK( BN_mod_mul( s, x, r, q,\t\t\t/* s = ( x * r ) mod q */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_add( s, s, hash ) );\t\t\t/* s = s + hash */\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( s, q ) > 0 )\t\t\t/* if s > q */\n\t\t{\n\t\tCK( BN_sub( s, s, q ) );\t\t/*   s = s - q (fast mod) */\n\t\t}\n\telse\n\t\t{\n\t\t/* Perform a dummy subtract on a value around the same size as s \n\t\t   (it's one bit shorter) to balance out the timing */\n\t\t( void ) BN_sub( k, k, q );\n\t\t}\n\tCK( BN_mod_mul( s, s, kInv, q,\t\t/* s = k^-1 * ( hash + x * r ) mod q */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Check that neither r = 0 or s = 0.  See the earlier comment where k \n\t   is  checked for the real necessity of this check */\n\tENSURES( !BN_is_zero( r ) && !BN_is_zero( s ) );\n\n\t/* More generally, and usefully, check that the values aren't \n\t   suspiciously small.  Since qLen is typically only 20 bytes anyway we\n\t   can't use the standard 128-bits-of-zeroes check since we only have\n\t   160 bits to work with in the first place, so we use 80 bits as the\n\t   best tradeoff between FPs and allowing bogus values through */\n\tif( BN_num_bytes( r ) < qLen - 10 || BN_num_bytes( s ) < qLen - 10 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Encode the result as a DL data block */\n\tstatus = encodeDLValuesFunction( dlpParams->outParam, dlpParams->outLen, \n\t\t\t\t\t\t\t\t\t &dlpParams->outLen, r, s, \n\t\t\t\t\t\t\t\t\t dlpParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Signature check a single block of data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sigCheck( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t\t IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_DECODEDLVALUES_FUNCTION decodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_DECODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->decodeDLValuesFunction );\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;\n\tBIGNUM *g = &pkcInfo->dlpParam_g, *y = &pkcInfo->dlpParam_y;\n\tBIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp2;\n\tBIGNUM *u1 = &pkcInfo->tmp3, *u2 = &pkcInfo->dlpTmp1;\t/* Doubles as w */\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( dlpParams->inParam1, dlpParams->inLen1 ) );\n\tassert( isReadPtrDynamic( dlpParams->inParam2, dlpParams->inLen2 ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( ( dlpParams->formatType == CRYPT_FORMAT_CRYPTLIB && \\\n\t\t\t\t( dlpParams->inLen2 >= 42 && dlpParams->inLen2 <= 128 ) ) || \\\n\t\t\t  ( dlpParams->formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\t( dlpParams->inLen2 >= 42 && dlpParams->inLen2 <= 128 ) ) || \\\n\t\t\t  ( dlpParams->formatType == CRYPT_IFORMAT_SSH && \\\n\t\t\t\tdlpParams->inLen2 == 40 ) );\n\tREQUIRES( dlpParams->inLen1 >= max( 20, MIN_HASHSIZE ) && \\\n\t\t\t  dlpParams->inLen1 <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( dlpParams->outParam == NULL && dlpParams->outLen == 0 );\n\tREQUIRES( decodeDLValuesFunction != NULL );\n\n\t/* Decode the values from a DL data block and make sure that r and s are\n\t   valid, i.e. r, s = [1...q-1] */\n\tstatus = decodeDLValuesFunction( dlpParams->inParam2, dlpParams->inLen2, \n\t\t\t\t\t\t\t\t\t r, s, q, dlpParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Convert the hash value to an integer in the proper range */\n\tstatus = hashToBignum( u1, dlpParams->inParam1, dlpParams->inLen1, q );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* w = s^-1 mod q */\n\tCKPTR( BN_mod_inverse( u2, s, q,\t/* w = s^-1 mod q */\n\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* u1 = ( hash * w ) mod q */\n\tCK( BN_mod_mul( u1, u1, u2, q,\t\t/* u1 = ( hash * w ) mod q */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* u2 = ( r * w ) mod q */\n\tCK( BN_mod_mul( u2, r, u2, q,\t\t/* u2 = ( r * w ) mod q */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* v = ( ( ( g^u1 ) * ( y^u2 ) ) mod p ) mod q */\n\tCK( BN_mod_exp2_mont( u2, g, u1, y, u2, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t  &pkcInfo->dlpParam_mont_p ) );\n\tCK( BN_mod( s, u2, q, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* If r == s then the signature is good */\n\tif( BN_cmp( r, s ) )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the\n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\t\tconst CRYPT_PKCINFO_DLP *dsaKey = ( CRYPT_PKCINFO_DLP * ) key;\n\t\tint status;\n\n\t\tif( dsaKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n\t\tstatus = importBignum( &pkcInfo->dlpParam_p, dsaKey->p, \n\t\t\t\t\t\t\t   bitsToBytes( dsaKey->pLen ),\n\t\t\t\t\t\t\t   DLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_PKC );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_q, dsaKey->q, \n\t\t\t\t\t\t\t\t   bitsToBytes( dsaKey->qLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Q, DLPPARAM_MAX_Q, \n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_g, dsaKey->g, \n\t\t\t\t\t\t\t\t   bitsToBytes( dsaKey->gLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_y, dsaKey->y, \n\t\t\t\t\t\t\t\t   bitsToBytes( dsaKey->yLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !dsaKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_x, dsaKey->x, \n\t\t\t\t\t\t\t\t   bitsToBytes( dsaKey->xLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_X, DLPPARAM_MAX_X,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup */\n\treturn( initCheckDLPkey( contextInfoPtr, FALSE ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\tstatus = generateDLPkey( contextInfoPtr, ( keySizeBits / 64 ) * 64 );\n\tif( cryptStatusOK( status ) && \\\n\t\t!pairwiseConsistencyTest( contextInfoPtr ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated DSA key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_DSA, bitsToBytes( 0 ), \"DSA\", 3,\n\tMIN_PKCSIZE, bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey,\n\tNULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \n\tsign, sigCheck\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDSACapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_DSA */\n"
  },
  {
    "path": "deps/cl345/context/ctx_ecdh.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib ECDH Key Exchange Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2006-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* The ECDH key exchange process is somewhat complex because there are two \n   phases involved for both sides, an \"export\" and an \"import\" phase, and \n   they have to be performed in the correct order.  The sequence of \n   operations is:\n\n\tA.load:\t\tset p, g from fixed or external values\n\t\t\t\tx(A) = rand, x s.t. 0 < x < q-1\n\n\tA.export\ty(A) = g^x(A) mod p\t\terror if y != 0 at start\n\t\t\t\toutput = y(A)\n\n\tB.load\t\tread p, g / set p, g from external values\n\t\t\t\tx(B) = rand, x s.t. 0 < x < q-1\n\n\tB.import\ty(A) = input\n\t\t\t\tz = y(A)^x(B) mod p\n\n\tB.export\ty(B) = g^x(B) mod p\t\terror if y != 0 at start\n\t\t\t\toutput = y(B)\n\n\tA.import\ty(B) = input\n\t\t\t\tz = y(B)^x(A) mod p\n\n   Note that we have to set x when we load p and g because otherwise we'd \n   have to set x(A) on export and x(B) on import, which is tricky since the \n   ECDH code doesn't know whether it's working with A or B */\n\n#ifdef USE_ECDH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCONTEXT_INFO checkContextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tPKC_INFO *sourcePkcInfo = contextInfoPtr->ctxPKC;\n\tKEYAGREE_PARAMS keyAgreeParams1, keyAgreeParams2;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\n\t/* The ECDH pairwise check is a bit more complex than the one for the \n\t   other algorithms because there's no matched public/private key pair, \n\t   so we have to load a second ECDH key to use for key agreement with \n\t   the first one */\n\tstatus = staticInitContext( &checkContextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetECDHCapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tpkcInfo->curveType = CRYPT_ECCCURVE_P256;\n\tCKPTR( BN_copy( &pkcInfo->eccParam_qx, &sourcePkcInfo->eccParam_qx ) );\n\tCKPTR( BN_copy( &pkcInfo->eccParam_qy, &sourcePkcInfo->eccParam_qy ) );\n\tCKPTR( BN_copy( &pkcInfo->eccParam_d, &sourcePkcInfo->eccParam_d ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tstaticDestroyContext( &checkContextInfo );\n\t\treturn( getBnStatusBool( bnStatus ) );\n\t\t}\n\n\t/* Perform the pairwise test using the check key */\n\tcapabilityInfoPtr = DATAPTR_GET( checkContextInfo.capabilityInfo );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\tmemset( &keyAgreeParams1, 0, sizeof( KEYAGREE_PARAMS ) );\n\tmemset( &keyAgreeParams2, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = capabilityInfoPtr->initKeyFunction( &checkContextInfo, NULL, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->encryptFunction( contextInfoPtr,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->encryptFunction( &checkContextInfo,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( contextInfoPtr,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( &checkContextInfo,\n\t\t\t\t\t( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusError( status ) || \\\n\t\tkeyAgreeParams1.wrappedKeyLen != keyAgreeParams2.wrappedKeyLen || \\\n\t\tmemcmp( keyAgreeParams1.wrappedKey, keyAgreeParams2.wrappedKey, \n\t\t\t\tkeyAgreeParams1.wrappedKeyLen ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\n\t/* Clean up */\n\tstaticDestroyContext( &checkContextInfo );\n\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the ECDH implementation (re-)using the test key for the ECDSA test, \n   which comes from from X9.62-2005 section L.4.2.  Because a lot of the \n   high-level encryption routines don't exist yet, we cheat a bit and \n   set up a dummy encryption context with just enough information for the \n   following code to work */\n\ntypedef struct {\n\tconst int qxLen; const BYTE qx[ 32 ];\n\tconst int qyLen; const BYTE qy[ 32 ];\n\tconst int dLen; const BYTE d[ 32 ];\n\t} ECC_KEY;\n\nstatic const ECC_KEY ecdhTestKey = {\n\t/* qx */\n\t32,\n\t{ 0x59, 0x63, 0x75, 0xE6, 0xCE, 0x57, 0xE0, 0xF2, \n\t  0x02, 0x94, 0xFC, 0x46, 0xBD, 0xFC, 0xFD, 0x19, \n\t  0xA3, 0x9F, 0x81, 0x61, 0xB5, 0x86, 0x95, 0xB3, \n\t  0xEC, 0x5B, 0x3D, 0x16, 0x42, 0x7C, 0x27, 0x4D },\n\t32,\n\t/* qy */\n\t{ 0x42, 0x75, 0x4D, 0xFD, 0x25, 0xC5, 0x6F, 0x93, \n\t  0x9A, 0x79, 0xF2, 0xB2, 0x04, 0x87, 0x6B, 0x3A, \n\t  0x3A, 0xB1, 0xCE, 0xB2, 0xE4, 0xFF, 0x57, 0x1A, \n\t  0xBF, 0x4F, 0xBF, 0x36, 0x32, 0x6C, 0x8B, 0x27 },\n\t32,\n\t/* d */\n\t{ 0x2C, 0xA1, 0x41, 0x1A, 0x41, 0xB1, 0x7B, 0x24,\n\t  0xCC, 0x8C, 0x3B, 0x08, 0x9C, 0xFD, 0x03, 0x3F,\n\t  0x19, 0x20, 0x20, 0x2A, 0x6C, 0x0D, 0xE8, 0xAB,\n\t  0xB9, 0x7D, 0xF1, 0x49, 0x8D, 0x50, 0xD2, 0xC8 }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetECDHCapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\tpkcInfo->curveType = CRYPT_ECCCURVE_P256;\n\tstatus = importBignum( &pkcInfo->eccParam_qx, ecdhTestKey.qx, \n\t\t\t\t\t\t   ecdhTestKey.qxLen, ECCPARAM_MIN_QX, \n\t\t\t\t\t\t   ECCPARAM_MAX_QX, NULL, KEYSIZE_CHECK_ECC );\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->eccParam_qy, ecdhTestKey.qy, \n\t\t\t\t\t\t\t   ecdhTestKey.qyLen, ECCPARAM_MIN_QY, \n\t\t\t\t\t\t\t   ECCPARAM_MAX_QY, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->eccParam_d, ecdhTestKey.d, \n\t\t\t\t\t\t\t   ecdhTestKey.dLen, ECCPARAM_MIN_D, \n\t\t\t\t\t\t\t   ECCPARAM_MAX_D, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) ) \n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\tretIntError();\n\t\t}\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Perform the test key exchange on a block of data */\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo,  NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\t!pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tECDH Key Exchange Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform phase 1 of ECDH (\"export\").  We have to append the distinguisher \n   'Fn' to the name since some systems already have 'encrypt' and 'decrypt' \n   in their standard headers */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( pkcInfo->domainParams != NULL );\n\tREQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );\n\tREQUIRES( !BN_is_zero( &pkcInfo->eccParam_qx ) && \\\n\t\t\t  !BN_is_zero( &pkcInfo->eccParam_qy ) );\n\n\t/* Q is generated either at keygen time for static ECDH or as a side-\n\t   effect of the implicit generation of the d value for ephemeral ECDH, \n\t   so all we have to do is encode it in X9.62 point form to the output */\n\tstatus = exportECCPoint( keyAgreeParams->publicValue, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\t\t\t &keyAgreeParams->publicValueLen, \n\t\t\t\t\t\t\t &pkcInfo->eccParam_qx, &pkcInfo->eccParam_qy,\n\t\t\t\t\t\t\t bitsToBytes( pkcInfo->keySizeBits ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform phase 2 of ECDH (\"import\") */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( KEYAGREE_PARAMS ) ) int noBytes )\n\t{\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *q = pkcInfo->tmpPoint;\n\tBIGNUM *x = &pkcInfo->tmp1, *y = &pkcInfo->tmp2;\n\tconst int keySize = bitsToBytes( pkcInfo->keySizeBits );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\tassert( isReadPtrDynamic( keyAgreeParams->publicValue, \n\t\t\t\t\t\t\t  keyAgreeParams->publicValueLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( pkcInfo->domainParams != NULL );\n\tREQUIRES( noBytes == sizeof( KEYAGREE_PARAMS ) );\n\tREQUIRES( keyAgreeParams->publicValueLen >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t  keyAgreeParams->publicValueLen < MAX_INTLENGTH_SHORT );\n\n\t/* The other party's Q value will be stored with the key agreement info \n\t   in X9.62 point form rather than having been read in when we read the \n\t   ECDH public key so we need to import it now.\n\t   \n\t   Since reading and storing the other party's value changes the context \n\t   data, we need to force a recalculation of the data checksum after the \n\t   import.  We don't need to perform the check beforehand since it's \n\t   just been done by the caller */\n\tstatus = importECCPoint( &pkcInfo->eccParam_qx, &pkcInfo->eccParam_qy,\n\t\t\t\t\t\t\t keyAgreeParams->publicValue,\n\t\t\t\t\t\t\t keyAgreeParams->publicValueLen,\n\t\t\t\t\t\t\t MIN_PKCSIZE_ECC_THRESHOLD, \n\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE_ECC, keySize,\n\t\t\t\t\t\t\t &domainParams->p, KEYSIZE_CHECK_ECC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpkcInfo->checksum = 0L;\n\tstatus = checksumContextData( contextInfoPtr->ctxPKC, CRYPT_ALGO_ECDH, \n\t\t\t\t\t\t\t\t  TRUE );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Make sure that the Q value is valid */\n\tif( !isPointOnCurve( &pkcInfo->eccParam_qx, &pkcInfo->eccParam_qy, \n\t\t\t\t\t\t &domainParams->a, &domainParams->b, pkcInfo ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Fill in point structure with coordinates from Q */\n\tCK( EC_POINT_set_affine_coordinates_GFp( ecCTX, q,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->eccParam_qx,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->eccParam_qy,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Multiply Q by private key d. */\n\tCK( EC_POINT_mul( ecCTX, q, NULL, q, &pkcInfo->eccParam_d,\n\t\t\t\t\t  &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Extract affine coordinates. */\n\tCK( EC_POINT_get_affine_coordinates_GFp( ecCTX, q, x, y, \n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* If the resulting values have more than 128 bits of leading zeroes \n\t   then there's something wrong */\n\tif( BN_num_bytes( x ) < keySize  - 16 || \\\n\t\tBN_num_bytes( y ) < keySize  - 16 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Encode the point.  This gets rather ugly because the only two \n\t   protocols that use ECDH, TLS and SSH, both use only the x coordinate\n\t   rather than the complete point value.  In the interests of \n\t   consistency we return the full point, so it's up to the users of the\n\t   ECDH capability to extract any sub-components that they need.  This\n\t   isn't so hard to do because of the use of the fixed-length\n\t   uncompressed format */\n\tstatus = exportECCPoint( keyAgreeParams->wrappedKey, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t &keyAgreeParams->wrappedKeyLen, x, y,\n\t\t\t\t\t\t\t bitsToBytes( pkcInfo->keySizeBits ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the result looks random.  This is done to defend \n\t   against (most) small-subgroup confinement attacks, although the size\n\t   check above does a pretty good job of that too */\n\tif( !checkEntropy( keyAgreeParams->wrappedKey, \n\t\t\t\t\t   keyAgreeParams->wrappedKeyLen ) )\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the \n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\t\tconst CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) key;\n\t\tint status;\n\n\t\tif( eccKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n#if 0\t/* We don't allow explicit ECC parameters since all curves are \n\t\t   predefined */\n\t\tif( eccKey->curveType == CRYPT_ECCCURVE_NONE )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_p, eccKey->p, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->pLen ), \n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_P, ECCPARAM_MAX_P, \n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_ECC );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_a, eccKey->a, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->aLen ), \n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_A, ECCPARAM_MAX_A, \n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_b, eccKey->b, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->bLen ), \n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_B, ECCPARAM_MAX_B, \n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_gx, eccKey->gx, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->gxLen ), \n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_GX, ECCPARAM_MAX_GX, \n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_gy, eccKey->gy, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->gyLen ), \n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_GY, ECCPARAM_MAX_GY, \n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_n, eccKey->n, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->nLen ), \n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_N, ECCPARAM_MAX_N, \n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n#endif /* 0 */\n\t\t\t{\n\t\t\tif( !isEnumRange( eccKey->curveType, CRYPT_ECCCURVE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tpkcInfo->curveType = eccKey->curveType;\n\t\t\t}\n\t\tstatus = importBignum( &pkcInfo->eccParam_qx, eccKey->qx, \n\t\t\t\t\t\t\t   bitsToBytes( eccKey->qxLen ), \n\t\t\t\t\t\t\t   ECCPARAM_MIN_QX, ECCPARAM_MAX_QX, \n\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_qy, eccKey->qy, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->qyLen ), \n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_QY, ECCPARAM_MAX_QY, \n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !eccKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_d, eccKey->d, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->dLen ), \n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_D, ECCPARAM_MAX_D, \n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup */\n\treturn( initCheckECCkey( contextInfoPtr, TRUE ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\n\tstatus = generateECCkey( contextInfoPtr, keySizeBits );\n\tif( cryptStatusOK( status ) &&\n#ifndef USE_FIPS140\n\t\tTEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&\n#endif /* USE_FIPS140 */\n\t\t!pairwiseConsistencyTest( contextInfoPtr ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated ECDH key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_ECDH, bitsToBytes( 0 ), \"ECDH\", 4,\n\tMIN_PKCSIZE_ECC, bitsToBytes( 256 ), CRYPT_MAX_PKCSIZE_ECC,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, \n\tencryptFn, decryptFn\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getECDHCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_ECDH */\n"
  },
  {
    "path": "deps/cl345/context/ctx_ecdsa.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib ECDSA Encryption Routines\t\t\t\t\t*\n*\t\t\tCopyright Matthias Bruestle and Peter Gutmann 2006-2014\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ECDSA\n\n/* ECDSA has the same problem with parameters that DSA does (see the comment\n   in the DSA code for details), see \"Digital Signature Schemes with Domain \n   Parameters\", Serge Vaudenay, ACISP'04, p.188.\n\n   In addition, ECDSA signatures have an interesting, or perhaps annoying,\n   property that they're trivially malleable.  With ECDSA a signature (r, s) \n   is still valid when it's given as (r, N-s), so there are two distinct \n   encoded forms that will both verify as a signature.  It's not clear that \n   this is a vulnerability in any protocol used by cryptlib, although it's \n   quite possible to design one where it causes problems.  For example \n   PKIX's braindamaged preference for blacklist-based \"validation\" means \n   that the blacklist can be bypassed by encoding the ECDSA signature into \n   its alternate form, so the signature is still valid but the item that \n   contains it is no longer on the blacklist.\n\n   We could check for and reject signatures that aren't in a particular \n   form, but this will just end up rejecting signatures created by some \n   library that happens to generate them one way or the other.  In addition \n   we could make sure that our signatures are always in a particular form, \n   but again it's not clear which one is the most appropriate one.  The \n   X9.62 test vectors are created using the > N/2 form, while some might \n   regard the < N/2 form as the more correct one.  A particularly amusing \n   trick would be to leak the private key by using the (r, s) form as a \n   subliminal channel.\n\n   To enable both generation of the < N/2 form and checking for the < N/2 \n   form, uncomment the following */\n\n/* #define CHECK_ECDSA_MALLEABILITY */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Technically, ECDSA can be used with any hash function, including ones \n   with a block size larger than the subgroup order (although in practice\n   the hash function always seems to be matched to the subgroup size).  To\n   handle the possibility of a mismatched size we use the following custom \n   conversion function, which applies the conversion rules for transforming \n   the hash value into an integer from X9.62.  For a group order n, of size \n   nlen (where 2 ^ (nlen-1) <= n < 2 ^ nlen), X9.62 mandates that the hash \n   value is first truncated to its leftmost nlen bits if nlen is smaller \n   than the hash value bit length before conversion to a bignum.  \n   Mathematically, this is equivalent to first converting the value to a \n   bignum and then right-shifting it by hlen - nlen bits, where hlen is the \n   hash length in bits (a more generic way to view the required conversion \n   is 'while( BN_num_bits( hash ) > BN_num_bits( n ) \n   { BN_rshift( hash, 1 ); }').  Finally, we reduce the value modulo n, \n   which is a simple matter of a compare-and-subtract */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int hashToBignum( INOUT BIGNUM *bignum, \n\t\t\t\t\t\t IN_BUFFER( hashLength ) const void *hash, \n\t\t\t\t\t\t IN_LENGTH_HASH const int hashLength, \n\t\t\t\t\t\t const BIGNUM *n )\n\t{\n\tconst int hLen = bytesToBits( hashLength );\n\tconst int nLen = BN_num_bits( n );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( isReadPtrDynamic( hash, hashLength ) );\n\tassert( isReadPtr( n, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( hashLength >= max( 20, MIN_HASHSIZE ) && \\\n\t\t\t  hashLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( nLen >= 20 && nLen <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\n\t/* Convert the hash value into a bignum.  We have to be careful when\n\t   we specify the bounds because, with increasingly smaller \n\t   probabilities, the leading bytes of the hash value may be zero.\n\t   The check used here gives one in 4 billion chance of a false\n\t   positive */\n\tstatus = importBignum( bignum, hash, hashLength, \n\t\t\t\t\t\t   hashLength - 3, hashLength + 1, NULL, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Shift out any extra bits */\n\tif( hLen > nLen )\n\t\t{\n\t\tCK( BN_rshift( bignum, bignum, hLen - nLen ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Make sure that the value really is smaller than the group order */\n\tif( BN_cmp( bignum, n ) >= 0 )\n\t\t{\n\t\tCK( BN_sub( bignum, bignum, n ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\tENSURES( sanityCheckBignum( bignum ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The SHA-256 hash of the string \"Example of ECDSA with ansip256r1 and \n   SHA-256\".  Note that X9.62-2005 contains both the message text and its \n   hash value, but the text (as given in X9.62) is wrong since it uses \n   'ansix9p256r1' instead of 'ansip256r1'.  The text above matches the given \n   hash value, and the rest of the test vector */\n\nstatic const BYTE shaM[] = {\n\t0x1B, 0xD4, 0xED, 0x43, 0x0B, 0x0F, 0x38, 0x4B,\n\t0x4E, 0x8D, 0x45, 0x8E, 0xFF, 0x1A, 0x8A, 0x55,\n\t0x32, 0x86, 0xD7, 0xAC, 0x21, 0xCB, 0x2F, 0x68,\n\t0x06, 0x17, 0x2E, 0xF5, 0xF9, 0x4A, 0x06, 0xAD\n\t};\n\n/* For the self-test we use the following fixed k data rather than a \n   randomly-generated value.  The corresponding signature value for the \n   fixed k with P256 should be:\n\n\tr = D73CD3722BAE6CC0B39065BB4003D8ECE1EF2F7A8A55BFD677234B0B3B902650\n\ts = D9C88297FEFED8441E08DDA69554A6452B8A0BD4A0EA1DDB750499F0C2298C2F */\n\nstatic const BYTE kVal[] = {\n\t0xA0, 0x64, 0x0D, 0x49, 0x57, 0xF2, 0x7D, 0x09,\n\t0x1A, 0xB1, 0xAE, 0xBC, 0x69, 0x94, 0x9D, 0x96,\n\t0xE5, 0xAC, 0x2B, 0xB2, 0x83, 0xED, 0x52, 0x84,\n\t0xA5, 0x67, 0x47, 0x58, 0xB1, 0x2F, 0x08, 0xDF\n\t};\n\n#define ECDSA_TESTVECTOR_SIZE\t32\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ 8 + ( 2 * CRYPT_MAX_PKCSIZE_ECC ) + 8 ];\n\tint sigSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\n\t/* Generate a signature with the private key */\n\tsetDLPParams( &dlpParams, shaM, 32, buffer, \n\t\t\t\t  8 + ( 2 * CRYPT_MAX_PKCSIZE_ECC ) );\n\tdlpParams.inLen2 = -999;\n\tstatus = capabilityInfoPtr->signFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Verify the signature with the public key */\n\tsigSize = dlpParams.outLen;\n\tsetDLPParams( &dlpParams, shaM, 32, NULL, 0 );\n\tdlpParams.inParam2 = buffer;\n\tdlpParams.inLen2 = sigSize;\n\tstatus = capabilityInfoPtr->sigCheckFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the ECDSA implementation using the test vectors from ANSI\n   X9.62-2005, in this case from section L.4.2, which uses P-256.  Note that\n   the test vector contains the Q point in compressed format only.  Qy can \n   be computed from the private key d or by using point decompression, which \n   was done manually here: Qy is one of the square roots of Qx^3-3*Qx+b (the \n   compressed format contains the LSB of Qy, here 1, which allows us to \n   unambiguously choose the square root).\n\n   Because a lot of the high-level encryption routines don't exist yet, we \n   cheat a bit and set up a dummy encryption context with just enough \n   information for the following code to work */\n\ntypedef struct {\n\tconst int qxLen; const BYTE qx[ 32 ];\n\tconst int qyLen; const BYTE qy[ 32 ];\n\tconst int dLen; const BYTE d[ 32 ];\n\t} ECC_KEY;\n\nstatic const ECC_KEY ecdsaTestKey = {\n\t/* qx */\n\t32,\n\t{ 0x59, 0x63, 0x75, 0xE6, 0xCE, 0x57, 0xE0, 0xF2,\n\t  0x02, 0x94, 0xFC, 0x46, 0xBD, 0xFC, 0xFD, 0x19,\n\t  0xA3, 0x9F, 0x81, 0x61, 0xB5, 0x86, 0x95, 0xB3,\n\t  0xEC, 0x5B, 0x3D, 0x16, 0x42, 0x7C, 0x27, 0x4D },\n\t32,\n\t/* qy */\n\t{ 0x42, 0x75, 0x4D, 0xFD, 0x25, 0xC5, 0x6F, 0x93,\n\t  0x9A, 0x79, 0xF2, 0xB2, 0x04, 0x87, 0x6B, 0x3A,\n\t  0x3A, 0xB1, 0xCE, 0xB2, 0xE4, 0xFF, 0x57, 0x1A,\n\t  0xBF, 0x4F, 0xBF, 0x36, 0x32, 0x6C, 0x8B, 0x27 },\n\t32,\n\t/* d */\n\t{ 0x2C, 0xA1, 0x41, 0x1A, 0x41, 0xB1, 0x7B, 0x24,\n\t  0xCC, 0x8C, 0x3B, 0x08, 0x9C, 0xFD, 0x03, 0x3F,\n\t  0x19, 0x20, 0x20, 0x2A, 0x6C, 0x0D, 0xE8, 0xAB,\n\t  0xB9, 0x7D, 0xF1, 0x49, 0x8D, 0x50, 0xD2, 0xC8 }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetECDSACapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\tpkcInfo->curveType = CRYPT_ECCCURVE_P256;\n\tstatus = importBignum( &pkcInfo->eccParam_qx, ecdsaTestKey.qx, \n\t\t\t\t\t\t   ecdsaTestKey.qxLen, ECCPARAM_MIN_QX, \n\t\t\t\t\t\t   ECCPARAM_MAX_QX, NULL, KEYSIZE_CHECK_ECC );\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->eccParam_qy, ecdsaTestKey.qy, \n\t\t\t\t\t\t\t   ecdsaTestKey.qyLen, ECCPARAM_MIN_QY, \n\t\t\t\t\t\t\t   ECCPARAM_MAX_QY, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) ) \n\t\t{\n\t\tstatus = importBignum( &pkcInfo->eccParam_d, ecdsaTestKey.d, \n\t\t\t\t\t\t\t   ecdsaTestKey.dLen, ECCPARAM_MIN_D, \n\t\t\t\t\t\t\t   ECCPARAM_MAX_D, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) ) \n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\tretIntError();\n\t\t}\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Perform the test sign/sig.check of the X9.62 test values */\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\t!pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Try it again with side-channel protection enabled */\n\tSET_FLAG( contextInfo.flags, CONTEXT_FLAG_SIDECHANNELPROTECTION );\n\tif( !pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* The checking for memory faults is performed at the \n\t   MESSAGE_CTX_ENCRYPT level, so it won't be detected when we call the\n\t   function directly via an internal code pointer */\n#if 0\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ 8 + ( 2 * CRYPT_MAX_PKCSIZE_ECC ) + 8 ];\n\n\t/* Finally, make sure that the memory fault-detection is working */\n\tpkcInfo->eccParam_qx.d[ 1 ] ^= 0x1001;\n\tsetDLPParams( &dlpParams, shaM, 32, buffer, \n\t\t\t\t  8 + ( 2 * CRYPT_MAX_PKCSIZE_ECC ) );\n\tdlpParams.inLen2 = -999;\n\tstatus = capabilityInfoPtr->signFunction( &contextInfo,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fault-detection couldn't detect a bit-flip, there's a \n\t\t   problem */\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#else\n\t/* Emulation of what the above code would do */\n\tpkcInfo->eccParam_qx.d[ 1 ] ^= 0x1001;\n\tstatus = checksumContextData( pkcInfo, CRYPT_ALGO_ECDSA, TRUE );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#endif /* 0 */\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate/Check a Signature\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since ECDSA signature generation produces two values and the \n   cryptEncrypt() model only provides for passing a byte string in and out \n   (or, more specifically, the internal bignum data can't be exported to the \n   outside world) we need to encode the resulting data into a flat format.  \n   This is done by encoding the output as an X9.31 Dss-Sig record, which is\n   also used for ECDSA:\n\n\tDss-Sig ::= SEQUENCE {\n\t\tr\tINTEGER,\n\t\ts\tINTEGER\n\t\t} */\n\n/* Sign a single block of data.  There's a possibility of fault attacks \n   against ECDSA as detailed by a variety of authors, \"Differential Fault \n   Attacks on Elliptic Curve Cryptosystems\", Ingrid Biehl, Bernd Meyer and \n   Volker Mueller, Proceedings of Crypto 2000, Springer-Verlag LNCS No.1880, \n   August 2000, p.131, \"Validation of Elliptic Curve Public Keys\", Adrian \n   Antipa, Daniel Brown, Alfred Menezes, Ren Struik and Scott Vanstone, \n   Proceedings of the Public Key Cryptography Conference (PKC'03), Springer-\n   Verlag LNCS No.2567, January 2003, p.211, \"Elliptic Curve Cryptosystems \n   in the Presence of Permanent and Transient Faults\", Mathieu Ciet and Marc \n   Joye, Designs, Codes and Cryptography, Vol.36, No.1 (2005), p.33, \"Error \n   Detection and Fault Tolerance in ECSM Using Input Randomisation\", Agustin \n   Dominguez-Oviedo and M. Anwar Hasan, IEEE Transactions on Dependable and \n   Secure Computing, Vol.6, No.6, p.175, and \"Bit-flip Faults on Elliptic \n   Curve Base Fields, Revisited\", Taechan Kim and Mehdi Tibouchi, \n   Proceedings of the Applied Cryptography and Network Security Conference \n   (ACNS'14), Springer-Verlag LNCS No.8479, p.163, and no doubt many more in\n   the future.\n   \n   In some cases this can be defended against by point validation, i.e. \n   through the use of isPointOnCurve() in kg_ecc.c, but a much simpler \n   solution is just to verify the private-key operation with the matching \n   public-key operation after we perform it.  This operation is handled at a \n   higher level (to accomodate algorithms like RSA for which the private-key \n   operation could be a sign or a decrypt and we only need to check the \n   sign), performing a signature verify after each signature generation at \n   the crypto mechanism level */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sign( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *eccParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_ENCODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->encodeDLValuesFunction );\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *n = &domainParams->n;\n\tBIGNUM *hash = &pkcInfo->tmp1, *x = &pkcInfo->tmp2;\n\tBIGNUM *k = &pkcInfo->tmp3, *r = &pkcInfo->eccParam_tmp4;\n\tBIGNUM *s = &pkcInfo->eccParam_tmp5;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *kg = pkcInfo->tmpPoint;\n\tconst int nLen = BN_num_bytes( n );\n\tint bnStatus = BN_STATUS, status = CRYPT_OK;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( eccParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( eccParams->inParam1, eccParams->inLen1 ) );\n\tassert( isWritePtrDynamic( eccParams->outParam, eccParams->outLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( pkcInfo->domainParams != NULL );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( eccParams->inParam2 == NULL && \\\n\t\t\t  ( eccParams->inLen2 == 0 || eccParams->inLen2 == -999 ) );\n\tREQUIRES( eccParams->outLen >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  eccParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( encodeDLValuesFunction != NULL );\n\tREQUIRES( nLen >= ECCPARAM_MIN_N && nLen <= ECCPARAM_MAX_N );\n\n\t/* Generate the secret random value k.  During the initial self-test the \n\t   random data pool may not exist yet, and may in fact never exist in a \n\t   satisfactory condition if there isn't enough randomness present in \n\t   the system to generate cryptographically strong random numbers.  To \n\t   bypass this problem, if the caller passes in a second length \n\t   parameter of -999 we know that it's an internal self-test call and \n\t   use a fixed bit pattern for k that avoids having to call \n\t   generateBignum() (this also means that we can use the fixed self-test \n\t   value for k).  This is a somewhat ugly use of 'magic numbers' but \n\t   it's safe because this function can only be called internally so all \n\t   that we need to trap is accidental use of the parameter which is \n\t   normally unused */\n\tif( eccParams->inLen2 == -999 )\n\t\t{\n\t\tstatus = importBignum( k, ( BYTE * ) kVal, ECDSA_TESTVECTOR_SIZE, \n\t\t\t\t\t\t\t   ECDSA_TESTVECTOR_SIZE - 1, \n\t\t\t\t\t\t\t   ECDSA_TESTVECTOR_SIZE, NULL,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\telse\n\t\t{\n\n\t\t/* Generate the random value k from [1...n-1], i.e. a random value \n\t\t   mod n.  Using a random value of the same length as r would \n\t\t   produce a slight bias in k that leaks a small amount of the \n\t\t   private key in each signature.  Because of this we start with a \n\t\t   value which is DLP_OVERFLOW_SIZE larger than r and then do the \n\t\t   reduction, eliminating the bias.\n\n\t\t   We also add (meaning \"mix in\" rather than strictly \n\t\t   \"arithmetically add\") the message hash to k to curtail problems \n\t\t   in the incredibly unlikely situation that the RNG value repeats */\n\t\tstatus = generateBignumEx( k, bytesToBits( nLen ) + \\\n\t\t\t\t\t\t\t\t\t  bytesToBits( DLP_OVERFLOW_SIZE ), 0x80, \n\t\t\t\t\t\t\t\t   0, eccParams->inParam1, eccParams->inLen1,\n\t\t\t\t\t\t\t\t   NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\t/* Use constant-time modexp() to protect the secret random value \n\t\t   from timing channels.  We could also use blinding, but neither of\n\t\t   these measures are actually terribly useful because we're using a \n\t\t   random exponent each time so the timing information isn't of much\n\t\t   use to an attacker */\n\t\tBN_set_flags( k, BN_FLG_CONSTTIME );\n\t\t}\n\tCK( BN_mod( k, k, n, \t\t\t\t/* Reduce k to the correct range */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Make sure that the result isn't zero (or more generally less than 64\n\t   bits).  Admittedly the chances of this are infinitesimally small \n\t   (2^-256, the size of the smallest curve, or less for a value of zero, \n\t   2^-128 for 64 bits) but someone's bound to complain if we don't \n\t   check */\n\tENSURES( BN_num_bytes( k ) > 8 );\n\n\t/* Convert the hash value to an integer in the proper range */\n\tstatus = hashToBignum( hash, eccParams->inParam1, eccParams->inLen1, n );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Compute the point kG.  EC_POINT_mul() extracts the generator G from \n\t   the curve definition (and see the long comment in sigCheck() about \n\t   the peculiarities of this function) */\n\tCK( EC_POINT_mul( ecCTX, kg, k, NULL, NULL, &pkcInfo->bnCTX ) );\t\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* r = kG.x mod G.r (s is a dummy) */\n\tCK( EC_POINT_get_affine_coordinates_GFp( ecCTX, kg, x, s, \n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tCK( BN_mod( r, x, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* k = ( k^-1 ) mod n */\n\tCKPTR( BN_mod_inverse( k, k, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* s = k^-1 * ( d * r + e ) mod n */\n\tCK( BN_mod_mul( s, &pkcInfo->eccParam_d, r, n, &pkcInfo->bnCTX ) );\n\tCK( BN_mod_add( s, s, hash, n, &pkcInfo->bnCTX ) );\n\tCK( BN_mod_mul( s, s, k, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Optional code to ensure that the signature is always in < N/2 form, \n\t   see the comment about ECDSA malleability further up */\n#ifdef CHECK_ECDSA_MALLEABILITY\n\tCKPTR( BN_copy( x, n ) );\n\tCK( BN_rshift( x, x, 1 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( s, x ) > 0 )\n\t\t{\n\t\tCK( BN_sub( s, n, s ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n#endif /* CHECK_ECDSA_MALLEABILITY */\n\n\t/* Check that neither r = 0 or s = 0.  See the earlier comment where k \n\t   is checked for the real necessity of this check */\n\tENSURES( !BN_is_zero( r ) && !BN_is_zero( s ) );\n\n\t/* More generally, and usefully, check that the values aren't \n\t   suspiciously small */\n\tif( BN_num_bytes( r ) < nLen - 16 || BN_num_bytes( s ) < nLen - 16 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Encode the result as a DL data block */\n\tstatus = encodeDLValuesFunction( eccParams->outParam, eccParams->outLen, \n\t\t\t\t\t\t\t\t\t &eccParams->outLen, r, s, \n\t\t\t\t\t\t\t\t\t eccParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Signature check a single block of data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sigCheck( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t\t IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *eccParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_DECODEDLVALUES_FUNCTION decodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_DECODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->decodeDLValuesFunction );\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *n = &domainParams->n;\n\tBIGNUM *qx = &pkcInfo->eccParam_qx, *qy = &pkcInfo->eccParam_qy;\n\tBIGNUM *u1 = &pkcInfo->tmp1, *u2 = &pkcInfo->tmp2;\n\tBIGNUM *r = &pkcInfo->tmp3, *s = &pkcInfo->eccParam_tmp4;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *u1gu2q = pkcInfo->tmpPoint, *u2q DUMMY_INIT_PTR;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( eccParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( eccParams->inParam1, eccParams->inLen1 ) );\n\tassert( isReadPtrDynamic( eccParams->inParam2, eccParams->inLen2 ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( pkcInfo->domainParams != NULL );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( eccParams->outParam == NULL && eccParams->outLen == 0 );\n\tREQUIRES( decodeDLValuesFunction != NULL );\n\n\t/* Decode the values from a DL data block and make sure that r and s are\n\t   valid, i.e. r, s = [1...n-1] */\n\tstatus = decodeDLValuesFunction( eccParams->inParam2, eccParams->inLen2, \n\t\t\t\t\t\t\t\t\t r, s, n, eccParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Optional code to check that the signature is always in < N/2 form, \n\t   see the comment about ECDSA malleability further up */\n#ifdef CHECK_ECDSA_MALLEABILITY\n\tCKPTR( BN_copy( u1, n ) );\n\tCK( BN_rshift( u1, u1, 1 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( s, u1 ) > 0 )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n#endif /* CHECK_ECDSA_MALLEABILITY */\n\n\t/* Convert the hash value to an integer in the proper range. */\n\tstatus = hashToBignum( u1, eccParams->inParam1, eccParams->inLen1, n );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've got all the data that we need, allocate the EC points working \n\t   variable */\n\tCKPTR( u2q = EC_POINT_new( ecCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* w = s^-1 mod G.r */\n\tCKPTR( BN_mod_inverse( u2, s, n, &pkcInfo->bnCTX ) );\n\n\t/* u1 = ( hash * w ) mod G.r */\n\tCK( BN_mod_mul( u1, u1, u2, n, &pkcInfo->bnCTX ) );\n\n\t/* u2 = ( r * w ) mod G.r */\n\tCK( BN_mod_mul( u2, r, u2, n, &pkcInfo->bnCTX ) );\n\n\t/* R = u1*G + u2*Q.  EC_POINT_mul() is a somewhat weird function that \n\t   supports faster ECDSA signature verification by allowing two point \n\t   multiplications to be done in a single call to EC_POINT_mul().  The \n\t   implementation of the multiplication process uses window-based \n\t   optimizations (also known as \"Shamir's trick\", according to the \n\t   \"Guide to Elliptic Curve Cryptography\") which computes nG + mQ faster \n\t   than if both point multiplications were done separately */\n\tCK( EC_POINT_set_affine_coordinates_GFp( ecCTX, u2q, qx, qy, \n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tCK( EC_POINT_mul( ecCTX, u1gu2q, u1, u2q, u2, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tEC_POINT_free( u2q );\n\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Convert point (x1, y1) to an integer r':\n\n\t\tr' = p((x1, y1)) mod n\n\t\t   = x1 mod n */\n\tCK( EC_POINT_get_affine_coordinates_GFp( ecCTX, u1gu2q, u1, u2, \n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tCK( BN_mod( u1, u1, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tEC_POINT_free( u2q );\n\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Clean up */\n\tEC_POINT_free( u2q );\n\n\t/* If r == r' then the signature is good */\n\tif( BN_cmp( r, u1 ) )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_ECC ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the\n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\t\tconst CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) key;\n\t\tint status;\n\n\t\tif( eccKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n#if 0\t/* We don't allow explicit ECC parameters since all curves are \n\t\t   predefined */\n\t\tif( eccKey->curveType == CRYPT_ECCCURVE_NONE )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_p, eccKey->p, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->pLen ),\n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_P, ECCPARAM_MAX_P,\n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_ECC );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_a, eccKey->a, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->aLen ),\n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_A, ECCPARAM_MAX_A,\n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_b, eccKey->b, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->bLen ),\n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_B, ECCPARAM_MAX_B,\n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_gx, eccKey->gx, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->gxLen ),\n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_GX, ECCPARAM_MAX_GX,\n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_gy, eccKey->gy, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->gyLen ),\n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_GY, ECCPARAM_MAX_GY,\n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->eccParam_n, eccKey->n, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->nLen ),\n\t\t\t\t\t\t\t\t\t   ECCPARAM_MIN_N, ECCPARAM_MAX_N,\n\t\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n#endif /* 0 */\n\t\t\t{\n\t\t\tif( !isEnumRange( eccKey->curveType, CRYPT_ECCCURVE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tpkcInfo->curveType = eccKey->curveType;\n\t\t\t}\n\t\tstatus = importBignum( &pkcInfo->eccParam_qx, eccKey->qx, \n\t\t\t\t\t\t\t   bitsToBytes( eccKey->qxLen ),\n\t\t\t\t\t\t\t   ECCPARAM_MIN_QX, ECCPARAM_MAX_QX,\n\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_qy, eccKey->qy, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->qyLen ),\n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_QY, ECCPARAM_MAX_QY,\n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !eccKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->eccParam_d, eccKey->d, \n\t\t\t\t\t\t\t\t   bitsToBytes( eccKey->dLen ),\n\t\t\t\t\t\t\t\t   ECCPARAM_MIN_D, ECCPARAM_MAX_D,\n\t\t\t\t\t\t\t\t   NULL, KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup */\n\treturn( initCheckECCkey( contextInfoPtr, FALSE ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\n\tstatus = generateECCkey( contextInfoPtr, keySizeBits );\n\tif( cryptStatusOK( status ) &&\n#ifndef USE_FIPS140\n\t\tTEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&\n#endif /* USE_FIPS140 */\n\t\t!pairwiseConsistencyTest( contextInfoPtr ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated ECDSA key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_ECDSA, bitsToBytes( 0 ), \"ECDSA\", 5,\n\tMIN_PKCSIZE_ECC, bitsToBytes( 256 ), CRYPT_MAX_PKCSIZE_ECC,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey,\n\tNULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, \n\tsign, sigCheck\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getECDSACapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n#endif /* USE_ECDSA */\n"
  },
  {
    "path": "deps/cl345/context/ctx_elg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Elgamal Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ELGAMAL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're doing a self-test we use the following fixed k (for the\n   signature) and kRandom (for the encryption) data rather than a randomly-\n   generated value.  The k value is the 160-bit DSA one from FIPS 186, which \n   seems as good as any */\n\n#if 0\t/* Only needed for Elgamal signing */\n\nstatic const BYTE kVal[] = {\n\t0x35, 0x8D, 0xAD, 0x57, 0x14, 0x62, 0x71, 0x0F,\n\t0x50, 0xE2, 0x54, 0xCF, 0x1A, 0x37, 0x6B, 0x2B,\n\t0xDE, 0xAA, 0xDF, 0xBF\n\t};\n#endif /* 0 */\n\nstatic const BYTE kRandomVal[] = {\n\t0x2A, 0x7C, 0x01, 0xFD, 0x62, 0xF7, 0x43, 0x13,\n\t0x36, 0xFE, 0xE8, 0xF1, 0x68, 0xB2, 0xA2, 0x2F,\n\t0x76, 0x50, 0xA1, 0x2C, 0x3E, 0x64, 0x8E, 0xFE,\n\t0x04, 0x58, 0x7F, 0xDE, 0xC2, 0x34, 0xE5, 0x79,\n\t0xE9, 0x45, 0xB0, 0xDD, 0x5E, 0x56, 0xD7, 0x82,\n\t0xEF, 0x93, 0xEF, 0x5F, 0xD0, 0x71, 0x8B, 0xA1,\n\t0x3E, 0xA0, 0x55, 0x6A, 0xB9, 0x6E, 0x72, 0xFE,\n\t0x17, 0x03, 0x95, 0x50, 0xB7, 0xA1, 0x11, 0xBA,\n\t};\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isGeneratedKey )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 32 + 8 ];\n\tint encrSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_B( isGeneratedKey == TRUE || isGeneratedKey == FALSE );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\n\t/* Encrypt with the public key.  We  */\n\tmemset( buffer, 0, CRYPT_MAX_PKCSIZE );\n\tmemcpy( buffer + 1, \"abcde\", 5 );\n\tsetDLPParams( &dlpParams, buffer,\n\t\t\t\t  bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ),\n\t\t\t\t  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );\n\tif( !isGeneratedKey )\n\t\t{\n\t\t/* Force the use of a fixed k value for the encryption test to\n\t\t   avoid having to go via the RNG */\n\t\tdlpParams.inLen2 = -999;\n\t\t}\n\tstatus = capabilityInfoPtr->encryptFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Decrypt with the private key */\n\tencrSize = dlpParams.outLen;\n\tsetDLPParams( &dlpParams, buffer, encrSize,\n\t\t\t\t  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );\n\tstatus = capabilityInfoPtr->decryptFunction( contextInfoPtr,\n\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\treturn( !memcmp( buffer + 1, \"abcde\", 5 ) );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the Elgamal implementation using a sample key.  Because a lot of the \n   high-level encryption routines don't exist yet, we cheat a bit and set up \n   a dummy encryption context with just enough information for the following \n   code to work */\n\ntypedef struct {\n\tconst int pLen; const BYTE p[ 128 ];\n\tconst int qLen; const BYTE q[ 20 ];\n\tconst int gLen; const BYTE g[ 128 ];\n\tconst int xLen; const BYTE x[ 20 ];\n\tconst int yLen; const BYTE y[ 128 ];\n\t} DLP_KEY;\n\nstatic const DLP_KEY dlpTestKey = {\n\t/* p */\n\t128,\n\t{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE, \n\t  0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27, \n\t  0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3, \n\t  0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10, \n\t  0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88, \n\t  0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36, \n\t  0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30, \n\t  0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE, \n\t  0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71, \n\t  0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F, \n\t  0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F, \n\t  0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB, \n\t  0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D, \n\t  0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09, \n\t  0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F, \n\t  0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 }, \n\n\t/* q */\n\t20,\n\t{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79, \n\t  0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90, \n\t  0x97, 0x13, 0x26, 0x1D }, \n\n\t/* g */\n\t128,\n\t{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42, \n\t  0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31, \n\t  0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11, \n\t  0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79, \n\t  0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37, \n\t  0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4, \n\t  0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88, \n\t  0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F, \n\t  0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9, \n\t  0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8, \n\t  0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12, \n\t  0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78, \n\t  0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2, \n\t  0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16, \n\t  0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE, \n\t  0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B }, \n\n\t/* x */\n\t20,\n\t{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71, \n\t  0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4, \n\t  0xF2, 0xAB, 0x54, 0xA1 }, \n\n\t/* y */\n\t128,\n\t{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA, \n\t  0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D, \n\t  0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E, \n\t  0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51, \n\t  0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5, \n\t  0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8, \n\t  0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59, \n\t  0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90, \n\t  0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C, \n\t  0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52, \n\t  0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD, \n\t  0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92, \n\t  0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC, \n\t  0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A, \n\t  0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50, \n\t  0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetElgamalCapability(), &contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importBignum( &pkcInfo->dlpParam_p, dlpTestKey.p, \n\t\t\t\t\t\t   dlpTestKey.pLen, DLPPARAM_MIN_P, \n\t\t\t\t\t\t   DLPPARAM_MAX_P, NULL, KEYSIZE_CHECK_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_g, dlpTestKey.g, \n\t\t\t\t\t\t\t   dlpTestKey.gLen, DLPPARAM_MIN_G, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_G, &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_q, dlpTestKey.q, \n\t\t\t\t\t\t\t   dlpTestKey.qLen, DLPPARAM_MIN_Q, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_y, dlpTestKey.y, \n\t\t\t\t\t\t\t   dlpTestKey.yLen, DLPPARAM_MIN_Y, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->dlpParam_x, dlpTestKey.x, \n\t\t\t\t\t\t\t   dlpTestKey.xLen, DLPPARAM_MIN_X, \n\t\t\t\t\t\t\t   DLPPARAM_MAX_X, &pkcInfo->dlpParam_p,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\tretIntError();\n\t\t}\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Perform a test a sig generation/check and test en/decryption */\n#if 0\t/* See comment in sig.code */\n\tmemset( buffer, '*', 20 );\n\tstatus = capabilityInfoPtr->signFunction( &contextInfoPtr, buffer, -1 );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tmemmove( buffer + 20, buffer, status );\n\t\tmemset( buffer, '*', 20 );\n\t\tstatus = capabilityInfoPtr->sigCheckFunction( &contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  buffer, 20 + status );\n\t\t}\n\tif( status != CRYPT_OK )\n\t\tstatus = CRYPT_ERROR_FAILED;\n#endif /* 0 */\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\t!pairwiseConsistencyTest( &contextInfo, FALSE ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* The checking for memory faults is performed at the \n\t   MESSAGE_CTX_ENCRYPT level, so it won't be detected when we call the\n\t   function directly via an internal code pointer */\n#if 0\n\tDLP_PARAMS dlpParams;\n\tBYTE buffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 32 + 8 ];\n\n\t/* Finally, make sure that the memory fault-detection is working */\n\tpkcInfo->dlpParam_p.d[ 8 ] ^= 0x0011;\n\tmemset( buffer, 0, CRYPT_MAX_PKCSIZE );\n\tmemcpy( buffer + 1, \"abcde\", 5 );\n\tsetDLPParams( &dlpParams, buffer,\n\t\t\t\t  bitsToBytes( contextInfo.ctxPKC->keySizeBits ),\n\t\t\t\t  buffer, ( CRYPT_MAX_PKCSIZE * 2 ) + 32 );\n\tstatus = capabilityInfoPtr->encryptFunction( &contextInfo,\n\t\t\t\t\t\t\t( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fault-detection couldn't detect a bit-flip, there's a \n\t\t   problem */\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#else\n\t/* Emulation of what the above code would do */\n\tpkcInfo->dlpParam_p.d[ 8 ] ^= 0x0011;\n\tstatus = checksumContextData( pkcInfo, CRYPT_ALGO_ELGAMAL, TRUE );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#endif /* 0 */\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate/Check a Signature\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Elgamal signatures have potential security problems (although this isn't\n   an issue when they're used in a PKCS #1 manner, OTOH nothing apart from\n   cryptlib uses them like this) while the equivalent DSA signatures don't\n   (or at least have less than Elgamal).  In addition since nothing uses\n   them anyway this code, we don't support Elgamal signing */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEncrypt/Decrypt a Data Block\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt a single block of data.  We have to append the distinguisher 'Fn'\n   to the name since some systems already have 'encrypt' and 'decrypt' in\n   their standard headers */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_ENCODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->encodeDLValuesFunction );\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;\n\tBIGNUM *y = &pkcInfo->dlpParam_y;\n\tBIGNUM *tmp = &pkcInfo->tmp1, *k = &pkcInfo->tmp2;\n\tBIGNUM *r = &pkcInfo->tmp3, *s = &pkcInfo->dlpTmp1;\n\tBIGNUM *phi_p = &pkcInfo->dlpTmp2;\n\tconst int length = bitsToBytes( pkcInfo->keySizeBits );\n\tint i, bnStatus = BN_STATUS, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( dlpParams->inParam1, dlpParams->inLen1 ) );\n\tassert( isWritePtrDynamic( dlpParams->outParam, dlpParams->outLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( dlpParams->inLen1 == length );\n\tREQUIRES( dlpParams->inParam2 == NULL && \\\n\t\t\t  ( dlpParams->inLen2 == 0 || dlpParams->inLen2 == -999 ) );\n\tREQUIRES( dlpParams->outLen >= ( 2 + length ) * 2 && \\\n\t\t\t  dlpParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( encodeDLValuesFunction != NULL );\n\n\t/* Make sure that we're not being fed suspiciously short data \n\t   quantities.  importBignum() performs a more rigorous check, but we\n\t   use this as a lint filter before performing the relatively expensive\n\t   random bignum generation and preprocessing */\n\tLOOP_LARGE( i = 0, i < length, i++ )\n\t\t{\n\t\tif( ( ( BYTE * ) dlpParams->inParam1 ) [ i ] != 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( length - i < MIN_PKCSIZE - 8 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Generate the secret random value k.  During the initial self-test\n\t   the random data pool may not exist yet, and may in fact never exist in\n\t   a satisfactory condition if there isn't enough randomness present in\n\t   the system to generate cryptographically strong random numbers.  To\n\t   bypass this problem, if the caller passes in a second length parameter\n\t   of -999, we know that it's an internal self-test call and use a fixed\n\t   bit pattern for k that avoids having to call generateBignum().  This\n\t   is a somewhat ugly use of 'magic numbers', but it's safe because this\n\t   function can only be called internally, so all we need to trap is\n\t   accidental use of the parameter which is normally unused */\n\tif( dlpParams->inLen2 == -999 )\n\t\t{\n\t\tstatus = importBignum( k, ( BYTE * ) kRandomVal, length, \n\t\t\t\t\t\t\t   length - 1, length, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\telse\n\t\t{\n\t\t/* Generate the random value k, with the same 32-bit adjustment used\n\t\t   in the DSA code to avoid bias in the output (the only real\n\t\t   difference is that we eventually reduce it mode phi(p) rather than\n\t\t   mod q).\n\n\t\t   We also add (meaning \"mix in\" rather than strictly \n\t\t   \"arithmetically add\") the data being encrypted to curtail \n\t\t   problems in the incredibly unlikely situation that the RNG value \n\t\t   repeats */\n\t\tstatus = generateBignumEx( k, \n\t\t\t\t\t\t\t\t   bytesToBits( length + DLP_OVERFLOW_SIZE ), \n\t\t\t\t\t\t\t\t   0x80, 0, dlpParams->inParam1, \n\t\t\t\t\t\t\t\t   dlpParams->inLen1, NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate phi( p ) and use it to get k, k < p-1 and k relatively prime\n\t   to p-1.  Since (p-1)/2 is prime, the initial choice for k will be\n\t   divisible by (p-1)/2 with probability 2/(p-1), so we'll do at most two\n\t   gcd operations with very high probability.  A k of (p-3)/2 will be\n\t   chosen with probability 3/(p-1), and all other numbers from 1 to p-1\n\t   will be chosen with probability 2/(p-1), giving a nearly uniform\n\t   distribution of exponents */\n\tCKPTR( BN_copy( phi_p, p ) );\n\tCK( BN_sub_word( phi_p, 1 ) );\t\t/* phi( p ) = p - 1 */\n\tCK( BN_mod( k, k, phi_p,\t\t\t/* Reduce k to the correct range */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_gcd( s, k, phi_p, &pkcInfo->bnCTX ) );\n\tLOOP_SMALL_CHECK( bnStatusOK( bnStatus ) && !BN_is_one( s ) )\n\t\t{\n\t\tCK( BN_sub_word( k, 1 ) );\n\t\tCK( BN_gcd( s, k, phi_p, &pkcInfo->bnCTX ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Move the input data into a bignum */\n\tstatus = importBignum( tmp, ( BYTE * ) dlpParams->inParam1, length,\n\t\t\t\t\t\t   MIN_PKCSIZE - 8, CRYPT_MAX_PKCSIZE, p, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* s = ( y^k * M ) mod p */\n\tCK( BN_mod_exp_mont( r, y, k, p,\t/* y' = y^k mod p */\n\t\t\t\t\t\t &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );\n\tCK( BN_mod_mul( s, r, tmp, p,\t\t/* s = y'M mod p */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* r = g^k mod p */\n\tCK( BN_mod_exp_mont( r, g, k, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Encode the result as a DL data block */\n\tstatus = encodeDLValuesFunction( dlpParams->outParam, dlpParams->outLen, \n\t\t\t\t\t\t\t\t\t &dlpParams->outLen, r, s, \n\t\t\t\t\t\t\t\t\t dlpParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Decrypt a single block of data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tconst PKC_DECODEDLVALUES_FUNCTION decodeDLValuesFunction = \\\n\t\t\t\t\t( PKC_DECODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( pkcInfo->decodeDLValuesFunction );\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *x = &pkcInfo->dlpParam_x;\n\tBIGNUM *r = &pkcInfo->tmp1, *s = &pkcInfo->tmp2, *tmp = &pkcInfo->tmp3;\n\tconst int length = bitsToBytes( pkcInfo->keySizeBits );\n\tint offset, dummy, bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( dlpParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( dlpParams->inParam1, dlpParams->inLen1 ) );\n\tassert( isWritePtrDynamic( dlpParams->outParam, dlpParams->outLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( dlpParams->inLen1 >= ( 2 + ( length - 2 ) ) * 2 && \\\n\t\t\t  dlpParams->inLen1 < MAX_INTLENGTH_SHORT );\n\tREQUIRES( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );\n\tREQUIRES( dlpParams->outLen >= length && \\\n\t\t\t  dlpParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( decodeDLValuesFunction != NULL );\n\n\t/* Decode the values from a DL data block and make sure that r and s are\n\t   valid, i.e. r, s = [1...p-1] */\n\tstatus = decodeDLValuesFunction( dlpParams->inParam1, dlpParams->inLen1, \n\t\t\t\t\t\t\t\t\t r, s, p, dlpParams->formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* M = ( s / ( r^x ) ) mod p */\n\tCK( BN_mod_exp_mont( r, r, x, p,\t\t/* r' = r^x */\n\t\t\t\t\t\t &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );\n\tCKPTR( BN_mod_inverse( tmp, r, p,\t\t/* r'' = r'^-1 */\n\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\tCK( BN_mod_mul( s, s, tmp, p,\t\t\t/* s = s * r'^-1 mod p */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Copy the result to the output.  Since the bignum code performs\n\t   leading-zero truncation, we have to adjust where we copy the\n\t   result to in the buffer to take into account extra zero bytes\n\t   that aren't extracted from the bignum.  In addition we can't use\n\t   the length returned from exportBignum() because this is the length \n\t   of the zero-truncated result, not the full length */\n\toffset = length - BN_num_bytes( s );\n\tENSURES( offset >= 0 && offset <= length );\n\tif( offset > 0 )\n\t\t{\n\t\t/* If the resulting value has more than 128 bits of leading zeroes\n\t\t   then there's something wrong */\n\t\tif( offset > 16 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tmemset( dlpParams->outParam, 0, offset );\n\t\t}\n\tdlpParams->outLen = length;\n\tstatus = exportBignum( dlpParams->outParam + offset, \n\t\t\t\t\t\t   dlpParams->outLen - offset, &dummy, s );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the\n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tconst CRYPT_PKCINFO_DLP *egKey = ( CRYPT_PKCINFO_DLP * ) key;\n\t\tint status;\n\n\t\t/* Load the key components into the bignums */\n\t\tif( egKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n\t\tstatus = importBignum( &pkcInfo->dlpParam_p, egKey->p, \n\t\t\t\t\t\t\t   bitsToBytes( egKey->pLen ),\n\t\t\t\t\t\t\t   DLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_PKC );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_g, egKey->g, \n\t\t\t\t\t\t\t\t   bitsToBytes( egKey->gLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_q, egKey->q, \n\t\t\t\t\t\t\t\t   bitsToBytes( egKey->qLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_y, egKey->y, \n\t\t\t\t\t\t\t\t   bitsToBytes( egKey->yLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !egKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->dlpParam_x, egKey->x, \n\t\t\t\t\t\t\t\t   bitsToBytes( egKey->xLen ),\n\t\t\t\t\t\t\t\t   DLPPARAM_MIN_X, DLPPARAM_MAX_X,\n\t\t\t\t\t\t\t\t   &pkcInfo->dlpParam_p, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup.  PGP Elgamal keys don't follow \n\t   X9.42 and are effectively PKCS #3 keys so if the key is being \n\t   instantiated from PGP key data and doesn't have a q parameter we mark \n\t   it as a PKCS #3 key to ensure that it doesn't fail the validity check \n\t   for q != 0 */\n\tif( key == NULL && \\\n\t\tTEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t   PKCINFO_FLAG_OPENPGPKEYID_SET ) && \\\n\t\tBN_is_zero( &pkcInfo->dlpParam_q ) )\n\t\t{\n\t\t/* It's a PGP Elgamal key, treat it as a PKCS #3 key for checking\n\t\t   purposes */\n\t\treturn( initCheckDLPkey( contextInfoPtr, TRUE ) );\n\t\t}\n\treturn( initCheckDLPkey( contextInfoPtr, FALSE ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\tstatus = generateDLPkey( contextInfoPtr, keySizeBits );\n\tif( cryptStatusOK( status ) &&\n#ifndef USE_FIPS140\n\t\tTEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&\n#endif /* USE_FIPS140 */\n\t\t!pairwiseConsistencyTest( contextInfoPtr, TRUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated Elgamal key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_ELGAMAL, bitsToBytes( 0 ), \"Elgamal\", 7,\n\tMIN_PKCSIZE, bitsToBytes( 1536 ), CRYPT_MAX_PKCSIZE,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, \n\tencryptFn, decryptFn\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getElgamalCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_ELGAMAL */\n"
  },
  {
    "path": "deps/cl345/context/ctx_encr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Encryption Context Action Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* \"Modern cryptography is nothing more than a mathematical framework for\n\tdebating the implications of various paranoid delusions\"\n\t\t\t\t\t\t\t\t\t\t\t\t- Don Alvarez */\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"context.h\"\n#else\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* The number of bytes of data that we check to make sure that the \n   encryption operation succeeded.  See the comment in encryptData() before \n   changing this */\n\n#define ENCRYPT_CHECKSIZE\t16\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a validity check on keying/state information in a context, used \n   to defend against side-channel attacks */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkContextStateData( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_B( contextInfoPtr->type == CONTEXT_CONV || \\\n\t\t\t\tcontextInfoPtr->type == CONTEXT_PKC )\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES_B( capabilityInfoPtr != NULL );\n\n\t/* If it's a context with the keying information held externally then we \n\t   can't check it */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\treturn( TRUE );\n\n\t/* Make sure that the keying information hasn't been corrupted */\n\tif( contextInfoPtr->type == CONTEXT_PKC )\n\t\t{\n\t\tstatus = checksumContextData( contextInfoPtr->ctxPKC, \n\t\t\t\t\tcapabilityInfoPtr->cryptAlgo, \n\t\t\t\t\tTEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t   CONTEXT_FLAG_ISPUBLICKEY ) ? FALSE : TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tconst CONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\t\tif( checksumData( convInfo->key, \\\n\t\t\t\t\t\t  convInfo->keyDataSize ) != convInfo->keyDataChecksum )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"%s key memory corruption detected for object %d\", \n\t\t\t\t\t capabilityInfoPtr->algoName, \n\t\t\t\t\t contextInfoPtr->objectHandle ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Recover from an en/decryption failure.  This replaces the data being en/\n   decrypted/signed/verified with appropriate values to ensure that no \n   plaintext or other sensitive information is leaked even if the caller\n   ignores the return code */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void sanitiseFailedData( INOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t\t\tIN_LENGTH_Z const int dataLength,\n\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tvoid *dataPtr = data;\n\tint length = dataLength, status;\n\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES_V( isIntegerRange( dataLength ) );\n\tREQUIRES_V( message >= MESSAGE_CTX_ENCRYPT && message <= MESSAGE_CTX_HASH );\n\tREQUIRES_V( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\t/* If it's a PKC algorithm then the input may be structured data, so we \n\t   have to extract the reference to the actual data being processed from\n\t   it.  This gets a bit complicated because, depending on the point at \n\t   which the operation failed, the output-length may have been cleared \n\t   (alongside the output data).  To deal with this we use the maximum\n\t   length possible for keyex, and either the full output length (if it's\n\t   available) or at least the minimum permitted length for a DLP/ECDLP \n\t   operation (2 * SHA-1 size) if it's not */\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( isKeyxAlgo( cryptAlgo ) )\n\t\t\t{\n\t\t\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) data;\n\n\t\t\tdataPtr = ( message == MESSAGE_CTX_ENCRYPT ) ? \\\n\t\t\t\t\t  keyAgreeParams->publicValue : keyAgreeParams->wrappedKey;\n\t\t\tlength = CRYPT_MAX_PKCSIZE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( isDlpAlgo( cryptAlgo ) || isEccAlgo( cryptAlgo ) )\n\t\t\t\t{\n\t\t\t\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) data;\n\n\t\t\t\tdataPtr = dlpParams->outParam;\n\t\t\t\tlength = max( dlpParams->outLen, 20 + 20 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If it's a failed en/decrypt then we replace the data with random \n\t   noise.  On encrypt this means that the plaintext is replaced with \n\t   non-decryptable garbage that looks encrypted.  On decrypt this means \n\t   that the plaintext is also replaced with garbage, for decryption of \n\t   data this doesn't really matter but for decryption of keying material \n\t   it means that we continue with junk keys that don't reveal anything \n\t   to an attacker */\n\tif( message == MESSAGE_CTX_ENCRYPT || message == MESSAGE_CTX_DECRYPT )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, dataPtr, length );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The attempt to fill with random garbage failed, fall back to\n\t\t\t   fixed, but non-zero, data */\n\t\t\tmemset( dataPtr, '*', length );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a failed sign/signature verify, clear the output to ensure\n\t\t   that nothing is leaked */\n\t\tmemset( dataPtr, 0, length );\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEncrypt Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt a block of data using a conventional cipher */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptDataConv( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\tINOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t\tIN_LENGTH_Z const int dataLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCTX_ENCRYPT_FUNCTION encryptFunction;\n\tconst int savedDataLength = min( dataLength, ENCRYPT_CHECKSIZE );\n\tBYTE savedData[ ENCRYPT_CHECKSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\tREQUIRES( !needsKey( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( dataLength ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( isStreamCipher( capabilityInfoPtr->cryptAlgo ) || \\\n\t\t\t  !needsIV( contextInfoPtr->ctxConv->mode ) ||\n\t\t\t  TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_IV_SET ) );\n\n\t/* Get function pointers for the context */\n\tencryptFunction = ( CTX_ENCRYPT_FUNCTION ) \\\n\t\t\t\t\t  FNPTR_GET( contextInfoPtr->encryptFunction );\n\tREQUIRES( encryptFunction != NULL );\n\n\t/* Save a copy of the plaintext, and encrypt it */\n\tREQUIRES( rangeCheck( savedDataLength, 1, ENCRYPT_CHECKSIZE ) );\n\tmemcpy( savedData, data, savedDataLength );\n\tstatus = encryptFunction( contextInfoPtr, data, dataLength );\n\tif( cryptStatusError( status ) || savedDataLength <= 8 )\n\t\t{\n\t\tzeroise( savedData, savedDataLength );\n\t\treturn( status );\n\t\t}\n\n\t/* Check for a catastrophic failure of the encryption.  A check of\n\t   a single block unfortunately isn't completely foolproof for 64-bit\n\t   blocksize ciphers in CBC mode because of the way the IV is applied to \n\t   the input.  For the CBC encryption operation:\n\t\t\t\t\t\n\t\tout = enc( in ^ IV )\n\t\t\t\t\t\t\n\t   if out == IV the operation turns into a no-op.  Consider the simple \n\t   case where IV == in, so IV ^ in == 0.  Then out = enc( 0 ) == IV, \n\t   with the input appearing again at the output.  In fact for a 64-bit \n\t   block cipher this can occur during normal operation once every 2^32 \n\t   blocks.  Although the chances of this happening are fairly low (the \n\t   collision would have to occur on the first encrypted block in a \n\t   message since that's the one that we check), we check the first two \n\t   blocks if we're using a 64-bit block cipher in CBC mode in order to \n\t   reduce false positives */\n\tif( !memcmp( savedData, data, savedDataLength ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\n\tzeroise( savedData, savedDataLength );\n\treturn( status );\n\t}\n\n/* Encrypt a block of data using a PKC */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptDataPKC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t   INOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t   IN_LENGTH_PKC const int dataLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCTX_ENCRYPT_FUNCTION encryptFunction;\n\tBYTE savedData[ ENCRYPT_CHECKSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES( !needsKey( contextInfoPtr ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Get function pointers for the context */\n\tencryptFunction = ( CTX_ENCRYPT_FUNCTION ) \\\n\t\t\t\t\t  FNPTR_GET( contextInfoPtr->encryptFunction );\n\tREQUIRES( encryptFunction != NULL );\n\n\t/* Key agreement algorithms are treated as a special case since they \n\t   don't actually encrypt the data */\n\tif( isKeyxAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tREQUIRES( dataLength == sizeof( KEYAGREE_PARAMS ) );\n\n\t\treturn( encryptFunction( contextInfoPtr, data, dataLength ) );\n\t\t}\n\n\t/* DLP algorithms have composite parameters and are handled differently \n\t   from standard algorithms */\n\tif( isDlpAlgo( capabilityInfoPtr->cryptAlgo ) || \\\n\t\tisEccAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) data;\n\n\t\tREQUIRES( dataLength == sizeof( DLP_PARAMS ) );\n\n\t\t/* Save a copy of the plaintext, and encrypt it */\n\t\tmemcpy( savedData, dlpParams->inParam1, ENCRYPT_CHECKSIZE );\n\t\tstatus = encryptFunction( contextInfoPtr, data, dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( savedData, ENCRYPT_CHECKSIZE );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Check for a catastrophic failure of the encryption */\n\t\tif( !memcmp( savedData, dlpParams->outParam, \n\t\t\t\t\t ENCRYPT_CHECKSIZE ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\n\t\tzeroise( savedData, ENCRYPT_CHECKSIZE );\n\n\t\treturn( status );\n\t\t}\n\n\tREQUIRES( dataLength >= MIN_PKCSIZE && \\\n\t\t\t  dataLength <= CRYPT_MAX_PKCSIZE );\n\n\t/* Save a copy of the plaintext, and encrypt it */\n\tmemcpy( savedData, data, ENCRYPT_CHECKSIZE );\n\tstatus = encryptFunction( contextInfoPtr, data, dataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( savedData, ENCRYPT_CHECKSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Check for a catastrophic failure of the encryption */\n\tif( !memcmp( savedData, data, ENCRYPT_CHECKSIZE ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\n\tzeroise( savedData, ENCRYPT_CHECKSIZE );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEncryption Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process an action message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint processActionMessage( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t  INOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int dataLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( message == MESSAGE_CTX_HASH && \\\n\t\t\t  ( dataLength == 0 || \\\n\t\t\t    isReadPtrDynamic( data, dataLength ) ) ) || \\\n\t\t\tisWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( message >= MESSAGE_CTX_ENCRYPT && message <= MESSAGE_CTX_HASH );\n\tREQUIRES( isIntegerRange( dataLength ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( message )\n\t\t{\n\t\tcase MESSAGE_CTX_ENCRYPT:\n\t\t\tif( !checkContextStateData( contextInfoPtr ) )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\tif( contextInfoPtr->type == CONTEXT_PKC )\n\t\t\t\tstatus = encryptDataPKC( contextInfoPtr, data, dataLength );\n\t\t\telse\n\t\t\t\tstatus = encryptDataConv( contextInfoPtr, data, dataLength );\n\t\t\tif( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t\t!TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t!checkContextStateData( contextInfoPtr ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t\tsanitiseFailedData( data, dataLength, message, \n\t\t\t\t\t\t\t\t\tcapabilityInfoPtr->cryptAlgo );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CTX_DECRYPT:\n\t\t\t{\n\t\t\tconst CTX_ENCRYPT_FUNCTION decryptFunction = \\\n\t\t\t\t\t\t( CTX_ENCRYPT_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->decryptFunction );\n\n\t\t\tREQUIRES( decryptFunction != NULL );\n\n\t\t\tif( !checkContextStateData( contextInfoPtr ) )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\tstatus = decryptFunction( contextInfoPtr, data, dataLength );\n\t\t\tif( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t\t!TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t!checkContextStateData( contextInfoPtr ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t\tsanitiseFailedData( data, dataLength, message, \n\t\t\t\t\t\t\t\t\tcapabilityInfoPtr->cryptAlgo );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase MESSAGE_CTX_SIGN:\n\t\t\tif( !checkContextStateData( contextInfoPtr ) )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\tstatus = capabilityInfoPtr->signFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  data, dataLength );\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t!checkContextStateData( contextInfoPtr ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tsanitiseFailedData( data, dataLength, message, \n\t\t\t\t\t\t\t\t\tcapabilityInfoPtr->cryptAlgo );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CTX_SIGCHECK:\n\t\t\tif( !checkContextStateData( contextInfoPtr ) )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\tstatus = capabilityInfoPtr->sigCheckFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  data, dataLength );\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t!checkContextStateData( contextInfoPtr ) )\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\tif( cryptStatusError( status ) && !isDataError( status ) )\n\t\t\t\t{\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tsanitiseFailedData( data, dataLength, message, \n\t\t\t\t\t\t\t\t\tcapabilityInfoPtr->cryptAlgo );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CTX_HASH:\n\t\t\t{\n\t\t\t/* We don't check the state for these since there's not much \n\t\t\t   that can be done in terms of an attack, we'll just produce a\n\t\t\t   random hash/MAC value that can't be verified */\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_HASH || \\\n\t\t\t\t\t  contextInfoPtr->type == CONTEXT_MAC );\n\n\t\t\t/* If we've already completed the hashing/MACing then we can't \n\t\t\t   continue */\n\t\t\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_DONE ) )\n\t\t\t\treturn( CRYPT_ERROR_COMPLETE );\n\n\t\t\tstatus = capabilityInfoPtr->encryptFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t data, dataLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( dataLength > 0 )\n\t\t\t\t{\n\t\t\t\t/* Usually the MAC initialisation happens when we load the \n\t\t\t\t   key, but if we've deleted the MAC value to process \n\t\t\t\t   another piece of data it'll happen on-demand so we have \n\t\t\t\t   to set the flag here */\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Usually a hash of zero bytes is used to wrap up an\n\t\t\t\t   ongoing hash operation, however it can also be the only \n\t\t\t\t   operation if a zero-byte string is being hashed.  To \n\t\t\t\t   handle this we have to set the inited flag as well as the \n\t\t\t\t   done flag */\n\t\t\t\tSET_FLAG( contextInfoPtr->flags,\n\t\t\t\t\t\t  CONTEXT_FLAG_HASH_DONE | CONTEXT_FLAG_HASH_INITED );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_generic.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Generic-Secret Object Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* This is a special-case context type that implements no actual \n   functionality but instead serves as a generic-secret container for use \n   with crypto mechanisms that employ intermediate cryptovariables, for \n   example ones that derive encryption keys, MAC keys, and IVs from a master\n   secret value */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since this is a pure data-storage object, this is the only routine that\n   does anything */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\tconst int keyLength )\n\t{\n\tGENERIC_INFO *genericInfo = contextInfoPtr->ctxGeneric;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );\n\n\t/* Copy the key to internal storage */\n\tif( genericInfo->genericSecret != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( genericInfo->genericSecret, key, keyLength );\n\t\tgenericInfo->genericSecretLength = keyLength;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_IALGO_GENERIC_SECRET, 0, \"Generic Secret\", 14,\n\tbitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ),\n\tselfTest, getDefaultInfo, NULL, initGenericParams, initKey, NULL,\n\tNULL, NULL, NULL, NULL, NULL, NULL, \n\tNULL, NULL\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getGenericSecretCapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_hsha.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib HMAC-SHA Hash Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"sha.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/sha.h\"\n#endif /* Compiler-specific includes */\n\n/* A structure to hold the initial and current MAC state info.  Rather than\n   redoing the key processing each time when we're calculating multiple MACs\n   with the same key, we just copy the initial state into the current state */\n\ntypedef struct {\n\tSHA_CTX macState, initialMacState;\n\t} SHA1_MAC_STATE;\n\n#define SHA1_MAC_STATE_SIZE\t\tsizeof( SHA1_MAC_STATE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHMAC-SHA Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the HMAC-SHA output against the test vectors given in RFC ???? */\n\nstatic const struct {\n\tconst char *key;\t\t\t\t\t\t/* HMAC key */\n\tconst int keyLength;\t\t\t\t\t/* Length of key */\n\tconst char *data;\t\t\t\t\t\t/* Data to hash */\n\tconst int length;\t\t\t\t\t\t/* Length of data */\n\tconst BYTE digest[ SHA_DIGEST_LENGTH ];\t/* Digest of data */\n\t} hmacValues[] = {\n\t{ \"\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\"\n\t  \"\\x0B\\x0B\\x0B\\x0B\", 20,\n\t  \"Hi There\", 8,\n\t  { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,\n\t\t0xE2, 0x8B, 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E,\n\t\t0xF1, 0x46, 0xBE, 0x00 } },\n\t{ \"Jefe\", 4,\n\t\t\"what do ya want for nothing?\", 28,\n\t  { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2,\n\t\t0xD2, 0x74, 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C,\n\t\t0x25, 0x9A, 0x7C, 0x79 } },\n\t{ \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\", 20,\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\", 50,\n\t  { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD,\n\t\t0x91, 0xA3, 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F,\n\t\t0x63, 0xF1, 0x75, 0xD3 } },\n\t{ \"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F\\x10\"\n\t  \"\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\", 25,\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\", 50,\n\t  { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6,\n\t\t0xBC, 0x84, 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C,\n\t\t0x2D, 0x72, 0x35, 0xDA } },\n#if 0\t/* Should be truncated to 96 bits - we don't do truncation */\n\t{ \"\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\"\n\t  \"\\x0C\\x0C\\x0C\\x0C\", 20,\n\t  \"Test With Truncation\", 20,\n\t  { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F,\n\t\t0xE7, 0xF2, 0x7B, 0xE1, 0xD5, 0x8B, 0xB9, 0x32,\n\t\t0x4A, 0x9A, 0x5A, 0x04 } },\n#endif /* 0 */\n\t{ \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\", 80,\n\t  \"Test Using Larger Than Block-Size Key - Hash Key First\", 54,\n\t  { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E,\n\t\t0x95, 0x70, 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55,\n\t\t0xED, 0x40, 0x21, 0x12 } },\n\t{ \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\", 80,\n\t  \"Test Using Larger Than Block-Size Key and Larger Than One \"\n\t  \"Block-Size Data\", 73,\n\t  { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78,\n\t\t0x6D, 0x6B, 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08,\n\t\t0xBB, 0xFF, 0x1A, 0x91 } },\n\t{ \"\", 0, NULL, 0, { 0 } }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getHmacSHA1Capability();\n\ttypedef BYTE MAC_STATE[ SHA1_MAC_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( MAC_STATE_STORAGE, MAC_STATE );\n\tMAC_STATE_STORAGE macStateStorage;\n\tMAC_STATE *macStatePtr = ALIGN_STRUCT( &macStateStorage, MAC_STATE, 8 ); \n\tint i, status, LOOP_ITERATOR;\n\n\t/* Test HMAC-SHA against the test vectors given in RFC ???? */\n\tmemset( macStatePtr, 0, SHA1_MAC_STATE_SIZE );\t/* Keep static analysers happy */\n\tLOOP_MED( i = 0, hmacValues[ i ].data != NULL, i++ )\n\t\t{\n\t\tstatus = testMAC( capabilityInfo, macStatePtr, hmacValues[ i ].key, \n\t\t\t\t\t\t  hmacValues[ i ].keyLength, hmacValues[ i ].data, \n\t\t\t\t\t\t  hmacValues[ i ].length, hmacValues[ i ].digest );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = SHA1_MAC_STATE_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHMAC-SHA Hash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash data using HMAC-SHA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hash( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int noBytes )\n\t{\n\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\tSHA_CTX *shaInfo = &( ( SHA1_MAC_STATE * ) macInfo->macInfo )->macState;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( noBytes == 0 || isReadPtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( noBytes ) );\n\n\t/* If the hash state was reset to allow another round of MAC'ing, copy\n\t   the initial MAC state over into the current MAC state */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\t{\n\t\tSHA1_MAC_STATE *macState = macInfo->macInfo;\n\n\t\tmemcpy( &macState->macState, &macState->initialMacState,\n\t\t\t\tsizeof( SHA_CTX ) );\n\t\t}\n\n\tif( noBytes > 0 )\n\t\tSHA1_Update( shaInfo, buffer, noBytes );\n\telse\n\t\t{\n\t\tBYTE hashBuffer[ SHA_CBLOCK + 8 ];\n\t\tBYTE digestBuffer[ SHA_DIGEST_LENGTH + 8 ];\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Complete the inner hash and extract the digest */\n\t\tSHA1_Final( digestBuffer, shaInfo );\n\n\t\t/* Perform the of the outer hash using the zero-padded key XOR'd\n\t\t   with the opad value followed by the digest from the inner hash */\n\t\tmemset( hashBuffer, HMAC_OPAD, SHA_CBLOCK );\n\t\tREQUIRES( rangeCheck( macInfo->userKeyLength, 1, SHA_CBLOCK ) );\n\t\tmemcpy( hashBuffer, macInfo->userKey,\n\t\t\t\tmacInfo->userKeyLength );\n\t\tLOOP_LARGE( i = 0, i < macInfo->userKeyLength, i++ )\n\t\t\thashBuffer[ i ] ^= HMAC_OPAD;\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tSHA1_Init( shaInfo );\n\t\tSHA1_Update( shaInfo, hashBuffer, SHA_CBLOCK );\n\t\tmemset( hashBuffer, 0, SHA_CBLOCK );\n\t\tSHA1_Update( shaInfo, digestBuffer, SHA_DIGEST_LENGTH );\n\t\tmemset( digestBuffer, 0, SHA_DIGEST_LENGTH );\n\t\tSHA1_Final( macInfo->mac, shaInfo );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHMAC-SHA Key Management Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up an HMAC-SHA key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\tSHA_CTX *shaInfo = &( ( SHA1_MAC_STATE * ) macInfo->macInfo )->macState;\n\tBYTE hashBuffer[ SHA_CBLOCK + 8 ];\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= 4 && keyLength < MAX_INTLENGTH_SHORT );\n\t\t\t  /* The self-test uses very short keys */\n\n\tSHA1_Init( shaInfo );\n\n\t/* If the key size is larger than tha SHA data size, reduce it to the\n\t   SHA hash size before processing it (yuck.  You're required to do this\n\t   though) */\n\tif( keyLength > SHA_CBLOCK )\n\t\t{\n\t\t/* Hash the user key down to the hash size (SHA1_Init() has already\n\t\t   been called when the context was created) and use the hashed form\n\t\t   of the key */\n\t\tSHA1_Update( shaInfo, ( void * ) key, keyLength );\n\t\tSHA1_Final( macInfo->userKey, shaInfo );\n\t\tmacInfo->userKeyLength = SHA_DIGEST_LENGTH;\n\n\t\t/* Reset the SHA state */\n\t\tSHA1_Init( shaInfo );\n\t\t}\n\telse\n\t\t{\n\t\t/* Copy the key to internal storage.  The memset() is unnecessary \n\t\t   but used to produce more or less constant timing across \n\t\t   different key sizes */\n\t\tif( macInfo->userKey != key )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\t\tmemcpy( macInfo->userKey, key, keyLength );\n\t\t\tmemset( macInfo->userKey + keyLength, 0,\n\t\t\t\t\tCRYPT_MAX_KEYSIZE - keyLength );\n\t\t\t}\n\t\tmacInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* Perform the start of the inner hash using the zero-padded key XOR'd\n\t   with the ipad value.  We do this in a manner that tries to minimise \n\t   timing information that may reveal the length of the password, given \n\t   the amount of other stuff that's going on it's highly unlikely that \n\t   this will ever ben an issue but we do it just in case */\n\tREQUIRES( rangeCheck( macInfo->userKeyLength, 1, SHA_CBLOCK ) );\n\tmemcpy( hashBuffer, macInfo->userKey,\n\t\t\tmacInfo->userKeyLength );\n\tif( macInfo->userKeyLength < SHA_CBLOCK )\n\t\t{\n\t\tmemset( hashBuffer + macInfo->userKeyLength, 0, \n\t\t\t\tSHA_CBLOCK - macInfo->userKeyLength );\n\t\t}\n\tLOOP_LARGE( i = 0, i < SHA_CBLOCK, i++ )\n\t\thashBuffer[ i ] ^= HMAC_IPAD;\n\tENSURES( LOOP_BOUND_OK );\n\tSHA1_Update( shaInfo, hashBuffer, SHA_CBLOCK );\n\tmemset( hashBuffer, 0, SHA_CBLOCK );\n\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED );\n\n\t/* Save a copy of the initial state in case it's needed later */\n\tmemcpy( &( ( SHA1_MAC_STATE * ) macInfo->macInfo )->initialMacState, shaInfo,\n\t\t\tsizeof( SHA_CTX ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_HMAC_SHA1, bitsToBytes( 160 ), \"HMAC-SHA\", 8,\n\tbitsToBytes( 64 ), bitsToBytes( 160 ), CRYPT_MAX_KEYSIZE,\n\tselfTest, getInfo, NULL, NULL, initKey, NULL, hash, hash\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getHmacSHA1Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_hsha2.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib HMAC-SHA2 Hash Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2004-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"sha2.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/sha2.h\"\n#endif /* Compiler-specific includes */\n\n/* A structure to hold the initial and current MAC state info.  Rather than\n   redoing the key processing each time when we're calculating multiple MACs\n   with the same key, we just copy the initial state into the current state */\n\ntypedef struct {\n\tsha2_ctx macState, initialMacState;\n\t} SHA2_MAC_STATE;\n\n#define SHA2_MAC_STATE_SIZE\t\tsizeof( SHA2_MAC_STATE )\n\n#ifndef SHA384_DIGEST_SIZE\n  /* These may not be defined on non 64-bit systems */\n  #define SHA384_DIGEST_SIZE\t\t\t48\n  #define SHA512_DIGEST_SIZE\t\t\t64\n  #define sha2_begin( size, ctx )\t\tsha256_begin( ( ctx )->uu->ctx256 )\n  #define sha2_hash( data, len, ctx )\tsha256_hash( data, len, ( ctx )->uu->ctx256 )\n  #define sha2_end( hash, ctx )\t\t\tsha256_end( hash, ( ctx )->uu->ctx256 )\n#endif /* SHA384_DIGEST_SIZE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHMAC-SHA2 Self-test Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the HMAC-SHA2 output against the test vectors given in RFC 4231 */\n\nstatic const struct {\n\tconst char *key;\t\t\t\t\t\t/* HMAC key */\n\tconst int keyLength;\t\t\t\t\t/* Length of key */\n\tconst char *data;\t\t\t\t\t\t/* Data to hash */\n\tconst int length;\t\t\t\t\t\t/* Length of data */\n\tconst BYTE digest[ SHA256_DIGEST_SIZE ];\t/* Digest of data */\n\t} hmacValues[] = {\n\t{ \"\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\\x0B\"\n\t  \"\\x0B\\x0B\\x0B\\x0B\", 20,\n\t  \"Hi There\", 8,\n\t  { 0xB0, 0x34, 0x4C, 0x61, 0xD8, 0xDB, 0x38, 0x53,\n\t    0x5C, 0xA8, 0xAF, 0xCE, 0xAF, 0x0B, 0xF1, 0x2B,\n\t\t0x88, 0x1D, 0xC2, 0x00, 0xC9, 0x83, 0x3D, 0xA7,\n\t\t0x26, 0xE9, 0x37, 0x6C, 0x2E, 0x32, 0xCF, 0xF7 } },\n\t{ \"Jefe\", 4,\n\t\t\"what do ya want for nothing?\", 28,\n\t  { 0x5B, 0xDC, 0xC1, 0x46, 0xBF, 0x60, 0x75, 0x4E,\n\t    0x6A, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xC7,\n\t\t0x5A, 0x00, 0x3F, 0x08, 0x9D, 0x27, 0x39, 0x83,\n\t\t0x9D, 0xEC, 0x58, 0xB9, 0x64, 0xEC, 0x38, 0x43 } },\n\t{ \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\", 20,\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\"\n\t  \"\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\\xDD\", 50,\n\t  { 0x77, 0x3E, 0xA9, 0x1E, 0x36, 0x80, 0x0E, 0x46,\n\t    0x85, 0x4D, 0xB8, 0xEB, 0xD0, 0x91, 0x81, 0xA7,\n\t\t0x29, 0x59, 0x09, 0x8B, 0x3E, 0xF8, 0xC1, 0x22,\n\t\t0xD9, 0x63, 0x55, 0x14, 0xCE, 0xD5, 0x65, 0xFE } },\n\t{ \"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F\\x10\"\n\t  \"\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\", 25,\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\"\n\t  \"\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\\xCD\", 50,\n\t  { 0x82, 0x55, 0x8A, 0x38, 0x9A, 0x44, 0x3C, 0x0E,\n\t    0xA4, 0xCC, 0x81, 0x98, 0x99, 0xF2, 0x08, 0x3A,\n\t\t0x85, 0xF0, 0xFA, 0xA3, 0xE5, 0x78, 0xF8, 0x07,\n\t\t0x7A, 0x2E, 0x3F, 0xF4, 0x67, 0x29, 0x66, 0x5B } },\n#if 0\t/* Should be truncated to 128 bits - we don't do truncation */\n\t{ \"\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\\x0C\"\n\t  \"\\x0C\\x0C\\x0C\\x0C\", 20,\n\t  \"Test With Truncation\", 20,\n\t  { 0xA3, 0xB6, 0x16, 0x74, 0x73, 0x10, 0x0E, 0xE0,\n\t    0x6E, 0x0C, 0x79, 0x6C, 0x29, 0x55, 0x55, 0x2B } },\n#endif /* 0 */\n\t{ \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\\xAA\"\n\t  \"\\xAA\", 131,\n\t  \"Test Using Larger Than Block-Size Key - Hash Key First\", 54,\n\t  { 0x60, 0xE4, 0x31, 0x59, 0x1E, 0xE0, 0xB6, 0x7F,\n\t    0x0D, 0x8A, 0x26, 0xAA, 0xCB, 0xF5, 0xB7, 0x7F,\n\t\t0x8E, 0x0B, 0xC6, 0x21, 0x37, 0x28, 0xC5, 0x14,\n\t\t0x05, 0x46, 0x04, 0x0F, 0x0E, 0xE3, 0x7F, 0x54 } },\n\n\t{ \"\", 0, NULL, 0, { 0 } }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getHmacSHA2Capability();\n\ttypedef BYTE MAC_STATE[ SHA2_MAC_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( MAC_STATE_STORAGE, MAC_STATE );\n\tMAC_STATE_STORAGE macStateStorage;\n\tMAC_STATE *macStatePtr = ALIGN_STRUCT( &macStateStorage, MAC_STATE, 8 ); \n\tint i, status, LOOP_ITERATOR;\n\n\t/* Test HMAC-SHA2 against the test vectors given in RFC 4231 */\n\tmemset( macStatePtr, 0, SHA2_MAC_STATE_SIZE );\t/* Keep static analysers happy */\n\tLOOP_MED( i = 0, hmacValues[ i ].data != NULL, i++ )\n\t\t{\n\t\tstatus = testMAC( capabilityInfo, macStatePtr, hmacValues[ i ].key, \n\t\t\t\t\t\t  hmacValues[ i ].keyLength, hmacValues[ i ].data, \n\t\t\t\t\t\t  hmacValues[ i ].length, hmacValues[ i ].digest );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = SHA2_MAC_STATE_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHMAC-SHA2 Hash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash data using HMAC-SHA2 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hash( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int noBytes )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\tsha2_ctx *shaInfo = &( ( SHA2_MAC_STATE * ) macInfo->macInfo )->macState;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( noBytes == 0 || isReadPtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( noBytes ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If the hash state was reset to allow another round of MAC'ing, copy\n\t   the initial MAC state over into the current MAC state */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\t{\n\t\tSHA2_MAC_STATE *macState = macInfo->macInfo;\n\n\t\tmemcpy( &macState->macState, &macState->initialMacState,\n\t\t\t\tsizeof( sha2_ctx ) );\n\t\t}\n\n\tif( noBytes > 0 )\n\t\tsha2_hash( buffer, noBytes, shaInfo );\n\telse\n\t\t{\n\t\tconst int digestSize = capabilityInfoPtr->blockSize;\n\t\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tBYTE digestBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Complete the inner hash and extract the digest */\n\t\tsha2_end( digestBuffer, shaInfo );\n\n\t\t/* Perform the of the outer hash using the zero-padded key XOR'd\n\t\t   with the opad value followed by the digest from the inner hash */\n\t\tmemset( hashBuffer, HMAC_OPAD, SHA256_BLOCK_SIZE );\n\t\tREQUIRES( rangeCheck( macInfo->userKeyLength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( hashBuffer, macInfo->userKey,\n\t\t\t\tmacInfo->userKeyLength );\n\t\tLOOP_LARGE( i = 0, i < macInfo->userKeyLength, i++ )\n\t\t\thashBuffer[ i ] ^= HMAC_OPAD;\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tsha2_begin( digestSize, shaInfo );\n\t\tsha2_hash( hashBuffer, SHA256_BLOCK_SIZE, shaInfo );\n\t\tmemset( hashBuffer, 0, SHA256_BLOCK_SIZE );\n\t\tsha2_hash( digestBuffer, digestSize, shaInfo );\n\t\tmemset( digestBuffer, 0, digestSize );\n\t\tsha2_end( macInfo->mac, shaInfo );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tHMAC-SHA2 Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up an HMAC-SHA2 key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\tsha2_ctx *shaInfo = &( ( SHA2_MAC_STATE * ) macInfo->macInfo )->macState;\n\tBYTE hashBuffer[ SHA256_BLOCK_SIZE + 8 ];\n\tint digestSize, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= 4 && keyLength < MAX_INTLENGTH_SHORT );\n\t\t\t  /* The self-test uses very short keys */\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tdigestSize = capabilityInfoPtr->blockSize;\n\tsha2_begin( digestSize, shaInfo );\n\n\t/* If the key size is larger than tha SHA2 data size, reduce it to the\n\t   SHA2 hash size before processing it (yuck.  You're required to do this\n\t   though) */\n\tif( keyLength > SHA256_BLOCK_SIZE )\n\t\t{\n\t\t/* Hash the user key down to the hash size (sha2_begin() has already\n\t\t   been called when the context was created) and use the hashed form\n\t\t   of the key */\n\t\tsha2_hash( ( void * ) key, keyLength, shaInfo );\n\t\tsha2_end( macInfo->userKey, shaInfo );\n\t\tmacInfo->userKeyLength = digestSize;\n\n\t\t/* Reset the SHA2 state */\n\t\tsha2_begin( digestSize, shaInfo );\n\t\t}\n\telse\n\t\t{\n\t\t/* Copy the key to internal storage.  The memset() is unnecessary \n\t\t   but used to produce more or less constant timing across \n\t\t   different key sizes */\n\t\tif( macInfo->userKey != key )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\t\tmemcpy( macInfo->userKey, key, keyLength );\n\t\t\tmemset( macInfo->userKey + keyLength, 0, \n\t\t\t\t\tCRYPT_MAX_KEYSIZE - keyLength );\n\t\t\t}\n\t\tmacInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* Perform the start of the inner hash using the zero-padded key XOR'd\n\t   with the ipad value.  We do this in a manner that tries to minimise \n\t   timing information that may reveal the length of the password, given \n\t   the amount of other stuff that's going on it's highly unlikely that \n\t   this will ever ben an issue but we do it just in case */\n\tREQUIRES( rangeCheck( macInfo->userKeyLength, 1, SHA256_BLOCK_SIZE ) );\n\tmemcpy( hashBuffer, macInfo->userKey,\n\t\t\tmacInfo->userKeyLength );\n\tif( macInfo->userKeyLength < SHA256_BLOCK_SIZE )\n\t\t{\n\t\tmemset( hashBuffer + macInfo->userKeyLength, 0, \n\t\t\t\tSHA256_BLOCK_SIZE - macInfo->userKeyLength );\n\t\t}\n\tLOOP_LARGE( i = 0, i < SHA256_BLOCK_SIZE, i++ )\n\t\thashBuffer[ i ] ^= HMAC_IPAD;\n\tENSURES( LOOP_BOUND_OK );\n\tsha2_hash( hashBuffer, SHA256_BLOCK_SIZE, shaInfo );\n\tmemset( hashBuffer, 0, SHA256_BLOCK_SIZE );\n\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED );\n\n\t/* Save a copy of the initial state in case it's needed later */\n\tmemcpy( &( ( SHA2_MAC_STATE * ) macInfo->macInfo )->initialMacState, shaInfo,\n\t\t\tsizeof( sha2_ctx ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise algorithm parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initParams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,\n\t\t\t\t\t   IN_OPT const void *data, \n\t\t\t\t\t   IN_INT const int dataLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( contextInfoPtr->type == CONTEXT_MAC );\n\tREQUIRES( isEnumRange( paramType, KEYPARAM ) );\n\n\t/* SHA-2 has a variable-length output, selectable by setting the \n\t   blocksize attribute */\n\tif( paramType == KEYPARAM_BLOCKSIZE )\n\t\t{\n#ifdef USE_SHA2_EXT\n  #ifdef CONFIG_SUITEB\n\t\tstatic const CAPABILITY_INFO capabilityInfo = {\n\t\t\t\tCRYPT_ALGO_SHA2, bitsToBytes( 384 ), \"HMAC-SHA384\", 11,\n\t\t\t\tbitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE,\n\t\t\t\tselfTest, getInfo, NULL, NULL, initKey, NULL, hash, hash\n\t\t\t\t};\n  #else\n\t\tstatic const CAPABILITY_INFO capabilityInfo = {\n\t\t\t\tCRYPT_ALGO_SHA2, bitsToBytes( 512 ), \"HMAC-SHA512\", 11,\n\t\t\t\tbitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE,\n\t\t\t\tselfTest, getInfo, NULL, NULL, initKey, NULL, hash, hash\n\t\t\t\t};\n  #endif /* CONFIG_SUITEB */\n#endif /* USE_SHA2_EXT */\n\n\t\t/* The default SHA-2 variant is SHA-256, so an attempt to set this \n\t\t   size is a no-op */\n\t\tif( dataLength == SHA256_DIGEST_SIZE )\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_SHA2_EXT\n\t\t/* Switch to the appropriate variant of SHA-2.  Note that the \n\t\t   initParamsFunction pointer for this version is NULL rather than\n\t\t   pointing to this function, so once the output size has been set \n\t\t   it can't be changed again */\n  #ifdef CONFIG_SUITEB\n\t\tif( dataLength != SHA384_DIGEST_SIZE )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tDATAPTR_SET( contextInfoPtr->capabilityInfo, \n\t\t\t\t\t ( void * ) &capabilityInfo );\n  #else\n\t\tif( dataLength != SHA512_DIGEST_SIZE )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tDATAPTR_SET( contextInfoPtr->capabilityInfo, \n\t\t\t\t\t ( void * ) &capabilityInfo );\n  #endif /* CONFIG_SUITEB */\n\n\t\treturn( CRYPT_OK );\n#else\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n#endif /* USE_SHA2_EXT */\n\t\t}\n\n\t/* Pass the call on down to the global parameter-handling function */\t\n\treturn( initGenericParams( contextInfoPtr, paramType, data, \n\t\t\t\t\t\t\t   dataLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_HMAC_SHA2, bitsToBytes( 256 ), \"HMAC-SHA2\", 9,\n\tbitsToBytes( 64 ), bitsToBytes( 256 ), CRYPT_MAX_KEYSIZE,\n\tselfTest, getInfo, NULL, initParams, initKey, NULL, hash, hash\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getHmacSHA2Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_idea.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib IDEA Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"idea.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/idea.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_IDEA\n\n/* Defines to map from EAY to native naming */\n\n#define IDEA_BLOCKSIZE\t\t\t\tIDEA_BLOCK\n\n/* A structure to hold the two expanded IDEA keys */\n\ntypedef struct {\n\tIDEA_KEY_SCHEDULE eKey, dKey;\n\t} IDEA_KEY;\n\n/* The size of the expanded IDEA keys */\n\n#define IDEA_EXPANDED_KEYSIZE\t\tsizeof( IDEA_KEY )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tIDEA Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* IDEA test vectors, from the ETH reference implementation */\n\n/* The data structure for the ( key, plaintext, ciphertext ) triplets */\n\ntypedef struct {\n\tconst BYTE key[ IDEA_KEY_LENGTH ];\n\tconst BYTE plaintext[ IDEA_BLOCKSIZE ];\n\tconst BYTE ciphertext[ IDEA_BLOCKSIZE ];\n\t} IDEA_TEST;\n\nstatic const IDEA_TEST testIdea[] = {\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 },\n\t  { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },\n\t  { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF },\n\t  { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 },\n\t  { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E },\n\t  { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 },\n\t  { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } },\n\t{ { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,\n\t\t0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 },\n\t  { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 },\n\t  { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } },\n\t{ { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14,\n\t\t0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 },\n\t  { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },\n\t  { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } },\n\t{ { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3,\n\t\t0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 },\n\t  { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },\n\t  { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } },\n\t{ { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90,\n\t\t0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 },\n\t  { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA },\n\t  { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } },\n\t{ { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A,\n\t\t0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 },\n\t  { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 },\n\t  { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } }\n\t};\n\n/* Test the IDEA code against the test vectors from the ETH reference\n   implementation */\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getIDEACapability();\n\ttypedef BYTE KEY_DATA[ IDEA_EXPANDED_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\tint i, status, LOOP_ITERATOR;\n\n\tmemset( keyDataPtr, 0, IDEA_EXPANDED_KEYSIZE );\t/* Keep static analysers happy */\n\tLOOP_MED( i = 0, i < sizeof( testIdea ) / sizeof( IDEA_TEST ), i++ )\n\t\t{\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, testIdea[ i ].key, \n\t\t\t\t\t\t\t 16, testIdea[ i ].plaintext, \n\t\t\t\t\t\t\t testIdea[ i ].ciphertext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = IDEA_EXPANDED_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tIDEA En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tIDEA_KEY *ideaKey = ( IDEA_KEY * ) convInfo->key;\n\tint blockCount = noBytes / IDEA_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Encrypt a block of data */\n\t\tidea_ecb_encrypt( buffer, buffer, &ideaKey->eKey );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += IDEA_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tIDEA_KEY *ideaKey = ( IDEA_KEY * ) convInfo->key;\n\tint blockCount = noBytes / IDEA_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Decrypt a block of data */\n\t\tidea_ecb_encrypt( buffer, buffer, &ideaKey->dKey );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += IDEA_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CBC mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tidea_cbc_encrypt( buffer, buffer, noBytes,\n\t\t\t\t\t  &( ( IDEA_KEY * ) convInfo->key )->eKey,\n\t\t\t\t\t  convInfo->currentIV, IDEA_ENCRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\tidea_cbc_encrypt( buffer, buffer, noBytes,\n\t\t\t\t\t  &( ( IDEA_KEY * ) convInfo->key )->dKey,\n\t\t\t\t\t  convInfo->currentIV, IDEA_DECRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CFB mode */\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tIDEA_KEY *ideaKey = ( IDEA_KEY * ) convInfo->key;\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = IDEA_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Encrypt the data */\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( boundsCheck( ivCount, bytesToUse, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tidea_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,\n\t\t\t\t\t\t  &ideaKey->eKey );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, buffer, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Decrypt data in CFB mode.  Note that the transformation can be made\n   faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp\n   all in one loop */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tIDEA_KEY *ideaKey = ( IDEA_KEY * ) convInfo->key;\n\tBYTE temp[ IDEA_BLOCKSIZE + 8 ];\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = IDEA_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Decrypt the data */\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, IDEA_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, bytesToUse );\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( boundsCheck( ivCount, bytesToUse, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, temp, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tidea_ecb_encrypt( convInfo->currentIV, convInfo->currentIV,\n\t\t\t\t\t\t  &ideaKey->eKey );\n\n\t\t/* Save the ciphertext */\n\t\tREQUIRES( rangeCheck( ivCount, 1, IDEA_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, ivCount );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, temp, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );\n\n\t/* Clear the temporary buffer */\n\tzeroise( temp, IDEA_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tIDEA Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key schedule an IDEA key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tIDEA_KEY *ideaKey = ( IDEA_KEY * ) convInfo->key;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= IDEA_KEY_LENGTH );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\t/* Generate the expanded IDEA encryption and decryption keys */\n\tidea_set_encrypt_key( key, &ideaKey->eKey );\n\tidea_set_decrypt_key( &ideaKey->eKey, &ideaKey->dKey );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_IDEA, bitsToBytes( 64 ), \"IDEA\", 4,\n\tMIN_KEYSIZE, bitsToBytes( 128 ), bitsToBytes( 128 ),\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB\n#endif /* USE_CFB */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getIDEACapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_IDEA */\n"
  },
  {
    "path": "deps/cl345/context/ctx_md5.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib MD5 Hash Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"md5.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/md5.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_MD5\n\n#define HASH_STATE_SIZE\t\tsizeof( MD5_CTX )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMD5 Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the MD5 output against the test vectors given in RFC 1321.  Since\n   hashing an empty string is a valid operation, we have to provide an \n   explicit isValid flag to tell the code when to stop */\n\nstatic const struct {\n\tconst char *data;\t\t\t\t\t\t/* Data to hash */\n\tconst int length;\t\t\t\t\t\t/* Length of data */\n\tconst BOOLEAN isValid;\t\t\t\t\t/* Whether entry is valid */\n\tconst BYTE digest[ MD5_DIGEST_LENGTH ];\t/* Digest of data */\n\t} digestValues[] = {\n\t{ NULL, 0, TRUE,\n\t  { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,\n\t\t0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E } },\n\t{ \"a\", 1, TRUE,\n\t  { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,\n\t\t0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 } },\n\t{ \"abc\", 3, TRUE,\n\t  { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,\n\t\t0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 } },\n\t{ \"message digest\", 14, TRUE,\n\t  { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,\n\t\t0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 } },\n\t{ \"abcdefghijklmnopqrstuvwxyz\", 26, TRUE,\n\t  { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,\n\t\t0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B } },\n\t{ \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\", 62, TRUE,\n\t  { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,\n\t\t0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F } },\n\t{ \"12345678901234567890123456789012345678901234567890123456789012345678901234567890\", 80, TRUE,\n\t  { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,\n\t\t0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } },\n\t{ NULL, 0, FALSE, { 0 } }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getMD5Capability();\n\ttypedef BYTE HASH_STATE[ HASH_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( HASH_STATE_STORAGE, HASH_STATE );\n\tHASH_STATE_STORAGE hashStateStorage;\n\tHASH_STATE *hashStatePtr = ALIGN_STRUCT( &hashStateStorage, HASH_STATE, 8 );\n\tint i, status, LOOP_ITERATOR;\n\n\t/* Test MD5 against the test vectors given in RFC 1320 */\n\tmemset( hashStatePtr, 0, HASH_STATE_SIZE );\t/* Keep static analysers happy */\n\tLOOP_MED( i = 0, digestValues[ i ].isValid, i++ )\n\t\t{\n\t\tstatus = testHash( capabilityInfo, 0, hashStatePtr, digestValues[ i ].data, \n\t\t\t\t\t\t   digestValues[ i ].length, digestValues[ i ].digest );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = HASH_STATE_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMD5 Hash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash data using MD5 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hash( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int noBytes )\n\t{\n\tMD5_CTX *md5Info = ( MD5_CTX * ) contextInfoPtr->ctxHash->hashInfo;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( noBytes == 0 || isReadPtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( noBytes ) );\n\n\t/* If the hash state was reset to allow another round of hashing,\n\t   reinitialise things */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\tMD5_Init( md5Info );\n\n\tif( noBytes > 0 )\n\t\t{\n\t\tMD5_Update( md5Info, buffer, noBytes );\n\t\t}\n\telse\n\t\t{\n\t\tMD5_Final( contextInfoPtr->ctxHash->hash, md5Info );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Internal API: Hash a single block of memory without the overhead of\n   creating an encryption context */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid md5HashBuffer( INOUT_OPT HASHINFO hashInfo,\n\t\t\t\t\tOUT_BUFFER_OPT_C( outBufMaxLength, 16 ) BYTE *outBuffer,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\tIN_BUFFER_OPT( inLength ) const void *inBuffer,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\tIN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState )\n\t{\n\tMD5_CTX *md5Info = ( MD5_CTX * ) hashInfo;\n\n\tassert( isWritePtr( hashInfo, sizeof( HASHINFO ) ) );\n\tassert( ( hashState != HASH_STATE_END && \\\n\t\t\t  outBuffer == NULL && outBufMaxLength == 0 ) || \\\n\t\t\t( hashState == HASH_STATE_END && \\\n\t\t\t  isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\t  outBufMaxLength >= 16 ) );\n\tassert( inBuffer == NULL || isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( ( hashState == HASH_STATE_END && outBufMaxLength < 16 ) || \\\n\t\t( hashState != HASH_STATE_END && inLength <= 0 ) )\n\t\tretIntError_Void();\n\n\tswitch( hashState )\n\t\t{\n\t\tcase HASH_STATE_START:\n\t\t\tMD5_Init( md5Info );\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase HASH_STATE_CONTINUE:\n\t\t\tMD5_Update( md5Info, ( BYTE * ) inBuffer, inLength );\n\t\t\tbreak;\n\n\t\tcase HASH_STATE_END:\n\t\t\tif( inBuffer != NULL )\n\t\t\t\tMD5_Update( md5Info, ( BYTE * ) inBuffer, inLength );\n\t\t\tMD5_Final( outBuffer, md5Info );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid md5HashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 16 ) BYTE *outBuffer,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int outBufMaxLength,\n\t\t\t\t\t\t  IN_BUFFER( inLength ) const void *inBuffer,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int inLength )\n\t{\n\tMD5_CTX md5Info;\n\n\tassert( isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\toutBufMaxLength >= 16 );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( outBufMaxLength < 16 || inLength <= 0 )\n\t\tretIntError_Void();\n\n\tMD5_Init( &md5Info );\n\tMD5_Update( &md5Info, ( BYTE * ) inBuffer, inLength );\n\tMD5_Final( outBuffer, &md5Info );\n\tzeroise( &md5Info, sizeof( MD5_CTX ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_MD5, bitsToBytes( 128 ), \"MD5\", 3,\n\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\tselfTest, getInfo, NULL, NULL, NULL, NULL, hash, hash\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getMD5Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_MD5 */\n"
  },
  {
    "path": "deps/cl345/context/ctx_misc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Context Support Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #ifdef USE_MD5\n\t#include \"md5.h\"\n  #endif /* USE_MD5 */\n  #include \"sha.h\"\n  #include \"sha2.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #ifdef USE_MD5\n\t#include \"crypt/md5.h\"\n  #endif /* USE_MD5 */\n  #include \"crypt/sha.h\"\n  #include \"crypt/sha2.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that a capability info record is consistent */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckFunctionality( const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ALGO CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tconst BOOLEAN isCrypt = \\\n\t\t( capabilityInfoPtr->encryptCBCFunction != NULL || \\\n\t\t  capabilityInfoPtr->decryptCBCFunction != NULL || \\\n\t\t  capabilityInfoPtr->encryptCFBFunction != NULL || \\\n\t\t  capabilityInfoPtr->decryptCFBFunction != NULL || \\\n\t\t  capabilityInfoPtr->encryptGCMFunction != NULL || \\\n\t\t  capabilityInfoPtr->decryptGCMFunction != NULL ) ? TRUE : FALSE;\n\tconst BOOLEAN isSig = \\\n\t\t( capabilityInfoPtr->signFunction != NULL || \\\n\t\t  capabilityInfoPtr->sigCheckFunction != NULL ) ? TRUE : FALSE;\n\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\t/* Generic-secret algorithms are non-capabilities used to to store\n\t   keying data, but that can't perform any operations themselves */\n\tif( isSpecialAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( capabilityInfoPtr->encryptFunction != NULL || \\\n\t\t\tcapabilityInfoPtr->decryptFunction != NULL || \\\n\t\t\tisCrypt || isSig )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Generic secret\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* We need at least one mechanism pair to be able to do anything useful \n\t   with the capability */\n\tif( ( capabilityInfoPtr->encryptFunction == NULL || \\\n\t\t  capabilityInfoPtr->decryptFunction == NULL ) && \\\n\t\t( capabilityInfoPtr->encryptCBCFunction == NULL || \\\n\t\t  capabilityInfoPtr->decryptCBCFunction == NULL ) && \\\n\t\t( capabilityInfoPtr->encryptCFBFunction == NULL || \\\n\t\t  capabilityInfoPtr->decryptCFBFunction == NULL ) && \\\n\t\t( capabilityInfoPtr->encryptGCMFunction == NULL || \\\n\t\t  capabilityInfoPtr->decryptGCMFunction == NULL ) && \\\n\t\t( capabilityInfoPtr->signFunction == NULL || \\\n\t\t  capabilityInfoPtr->sigCheckFunction == NULL ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: General capabilities\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform algorithm class-specific checks */\n\tif( isConvAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( isSig )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Spurious conv capability\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( isStreamCipher( cryptAlgo ) )\n\t\t\t{\n\t\t\tif( capabilityInfoPtr->encryptFunction == NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptFunction == NULL )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Missing CFB\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->encryptCBCFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptCBCFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->encryptCFBFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptCFBFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->encryptGCMFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptGCMFunction != NULL )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Spurious stream capability\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( capabilityInfoPtr->encryptFunction == NULL && \\\n\t\t\t\tcapabilityInfoPtr->decryptFunction == NULL && \\\n\t\t\t\t!isCrypt )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Missing crypt capability\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tif( ( capabilityInfoPtr->encryptCBCFunction != NULL && \\\n\t\t\t  capabilityInfoPtr->decryptCBCFunction == NULL ) || \\\n\t\t\t( capabilityInfoPtr->encryptCBCFunction == NULL && \\\n\t\t\t  capabilityInfoPtr->decryptCBCFunction != NULL ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Inconsistent CBC\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( ( capabilityInfoPtr->encryptCFBFunction != NULL && \\\n\t\t\t  capabilityInfoPtr->decryptCFBFunction == NULL ) || \\\n\t\t\t( capabilityInfoPtr->encryptCFBFunction == NULL && \\\n\t\t\t  capabilityInfoPtr->decryptCFBFunction != NULL ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Inconsistent CFB\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( ( capabilityInfoPtr->encryptGCMFunction != NULL && \\\n\t\t\t  capabilityInfoPtr->decryptGCMFunction == NULL ) || \\\n\t\t\t( capabilityInfoPtr->encryptGCMFunction == NULL && \\\n\t\t\t  capabilityInfoPtr->decryptGCMFunction != NULL ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Inconsistent GCM\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t\n\t\treturn( TRUE );\n\t\t}\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( capabilityInfoPtr->encryptFunction == NULL && \\\n\t\t\tcapabilityInfoPtr->decryptFunction == NULL && \\\n\t\t\tcapabilityInfoPtr->signFunction == NULL && \\\n\t\t\tcapabilityInfoPtr->sigCheckFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Missing PKC capability\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( isCrypt )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Spurious PKC capability\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\tif( isHashAlgo( cryptAlgo ) || isMacAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( capabilityInfoPtr->encryptFunction == NULL || \\\n\t\t\tcapabilityInfoPtr->decryptFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Missing hash/MAC capability\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( isCrypt || isSig )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckFunctionality: Spurious hash/MAC capability\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckCapability( const CAPABILITY_INFO *capabilityInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\t/* Check the algorithm and mode parameters.  We check for an algorithm\n\t   name one shorter than the maximum because as returned to an external\n\t   caller it's an ASCIZ string so we need to allow room for the\n\t   terminator */\n\tif( !isEnumRange( cryptAlgo, CRYPT_ALGO ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( capabilityInfoPtr->algoName == NULL || \\\n\t\tcapabilityInfoPtr->algoNameLen < 3 || \\\n\t\tcapabilityInfoPtr->algoNameLen > CRYPT_MAX_TEXTSIZE - 1 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Algorithm name\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the minimum functions are present.  We don't check for\n\t   the presence of the keygen function since the symmetric capabilities\n\t   use the generic keygen and the hash capabilities don't do keygen at \n\t   all */\n#ifdef CONFIG_NO_SELFTEST\n\tif( capabilityInfoPtr->selfTestFunction != NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Suprious self-test function\" ));\n\t\treturn( FALSE );\n\t\t}\n#else\n\tif( capabilityInfoPtr->selfTestFunction == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Self-test function\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* CONFIG_NO_SELFTEST */\n\tif( capabilityInfoPtr->getInfoFunction == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Get-info function\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !sanityCheckFunctionality( capabilityInfoPtr, cryptAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Functionality\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the algorithm/mode-specific parameters are\n\t   consistent */\n\tif( capabilityInfoPtr->minKeySize > capabilityInfoPtr->keySize || \\\n\t\tcapabilityInfoPtr->maxKeySize < capabilityInfoPtr->keySize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCapability: Key size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( isConvAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( ( capabilityInfoPtr->blockSize < bitsToBytes( 8 ) || \\\n        \t  capabilityInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) || \\\n\t\t\t( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \\\n\t\t\t  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Conv. block size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Conv. key wrap size\" ));\n\t\t\treturn( FALSE );\t/* Requirement for key wrap */\n\t\t\t}\n\t\tif( capabilityInfoPtr->initParamsFunction == NULL || \\\n\t\t\tcapabilityInfoPtr->initKeyFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Conv. init functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !isStreamCipher( cryptAlgo ) && \\\n\t\t\t capabilityInfoPtr->blockSize < bitsToBytes( 64 ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Conv. minimum block size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check any remaining algorithm types */\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tconst int minKeySize = isEccAlgo( cryptAlgo ) ? \\\n\t\t\t\t\t\t\t   MIN_PKCSIZE_ECC : MIN_PKCSIZE;\n\n\t\tif( capabilityInfoPtr->blockSize != 0 || \\\n\t\t\t( capabilityInfoPtr->minKeySize < minKeySize || \\\n\t\t\t  capabilityInfoPtr->maxKeySize > CRYPT_MAX_PKCSIZE ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: PKC key size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( capabilityInfoPtr->initKeyFunction == NULL || \\\n\t\t\tcapabilityInfoPtr->generateKeyFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: PKC Init/generate function\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\tif( isHashAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( ( capabilityInfoPtr->blockSize < MIN_HASHSIZE || \\\n\t\t\t  capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t( capabilityInfoPtr->minKeySize != 0 || \\\n\t\t\t  capabilityInfoPtr->keySize != 0 || \\\n\t\t\t  capabilityInfoPtr->maxKeySize != 0 ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Hash block size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\tif( isMacAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( ( capabilityInfoPtr->blockSize < MIN_HASHSIZE || \\\n\t\t\t  capabilityInfoPtr->blockSize > CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t( capabilityInfoPtr->minKeySize < MIN_KEYSIZE || \\\n\t\t\t  capabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: MAC key size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( capabilityInfoPtr->keySize > MAX_WORKING_KEYSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: MAC key wrap size\" ));\n\t\t\treturn( FALSE );\t/* Requirement for key wrap */\n\t\t\t}\n\t\tif( capabilityInfoPtr->initKeyFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: MAC init function\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\tif( isSpecialAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( capabilityInfoPtr->blockSize != 0 || \\\n\t\t\tcapabilityInfoPtr->minKeySize < bitsToBytes( 128 ) || \\\n\t\t\tcapabilityInfoPtr->maxKeySize > CRYPT_MAX_KEYSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Generic key size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( capabilityInfoPtr->initKeyFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckCapability: Generic init function\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\n/* Get information from a capability record */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid getCapabilityInfo( OUT CRYPT_QUERY_INFO *cryptQueryInfo,\n\t\t\t\t\t\tconst CAPABILITY_INFO *capabilityInfoPtr )\n\t{\n\tassert( isWritePtr( cryptQueryInfo, sizeof( CRYPT_QUERY_INFO ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tmemset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );\n\tREQUIRES_V( rangeCheck( capabilityInfoPtr->algoNameLen, 1, \n\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( cryptQueryInfo->algoName, capabilityInfoPtr->algoName,\n\t\t\tcapabilityInfoPtr->algoNameLen );\n\tcryptQueryInfo->algoName[ capabilityInfoPtr->algoNameLen ] = '\\0';\n\tcryptQueryInfo->blockSize = capabilityInfoPtr->blockSize;\n\tcryptQueryInfo->minKeySize = capabilityInfoPtr->minKeySize;\n\tcryptQueryInfo->keySize = capabilityInfoPtr->keySize;\n\tcryptQueryInfo->maxKeySize = capabilityInfoPtr->maxKeySize;\n\t}\n\n/* Find the capability record for a given encryption algorithm */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst CAPABILITY_INFO *findCapabilityInfo(\n\t\t\t\t\t\tconst CAPABILITY_INFO_LIST *capabilityInfoList,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tconst CAPABILITY_INFO_LIST *capabilityInfoListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( capabilityInfoList, sizeof( CAPABILITY_INFO_LIST ) ) );\n\n\t/* Find the capability corresponding to the requested algorithm/mode */\n\tLOOP_MED( capabilityInfoListPtr = capabilityInfoList, \n\t\t\t  capabilityInfoListPtr != NULL,\n\t\t\t  capabilityInfoListPtr = DATAPTR_GET( capabilityInfoListPtr->next ) )\n\t\t{\n\t\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( capabilityInfoListPtr->info );\n\n\t\tREQUIRES_N( capabilityInfoPtr != NULL );\n\t\tREQUIRES_N( sanityCheckCapability( capabilityInfoPtr ) );\n\n\t\tif( capabilityInfoPtr->cryptAlgo == cryptAlgo )\n\t\t\treturn( capabilityInfoPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tShared Context Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Default handler to get object subtype-specific information.  This \n   fallback function is called if the object-specific primary get-info \n   handler doesn't want to handle the query */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getDefaultInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( contextInfoPtr == NULL || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\n\tswitch( type )\n\t\t{\n\t\tcase CAPABILITY_INFO_STATESIZE:\n\t\t\t{\n\t\t\tint *valuePtr = ( int * ) data;\n\n\t\t\t/* If we're falling through to a default handler for this then \n\t\t\t   it's because the context has no state information */\n\t\t\t*valuePtr = 0;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CAPABILITY_INFO_STATEALIGNTYPE:\n\t\t\t{\n\t\t\tint *valuePtr = ( int * ) data;\n\n\t\t\t/* Default alignment for the algorithm-specific state data is\n\t\t\t   64 bits */\n\t\t\t*valuePtr = 8;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCrypto Hardware Interface Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise/shut down the crypto hardware interface for a context.  This \n   is used for conventional and hash/MAC algorithms where there's no \n   explicit device, or at least for which it's not worth the overhead of \n   doing everything via a device */\n\n#ifdef HAS_DEVCRYPTO\n\n#include <errno.h>\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int getHWAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\tuint32_t *hwAlgoID )\n\t{\n\tstatic const MAP_TABLE hwCryptInfo[] = {\n\t\t{ CRYPT_ALGO_3DES, CRYPTO_3DES_CBC },\n\t\t{ CRYPT_ALGO_AES, CRYPTO_AES_CBC },\n\t\t{ CRYPT_ALGO_SHA1, CRYPTO_SHA1 },\n\t\t{ CRYPT_ALGO_SHA2, CRYPTO_SHA2_256 },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR },\n\t\t\t{ CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\n\tassert( isWritePtr( hwAlgoID, sizeof( uint32_t ) ) );\n\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\t/* Map the cryptlib algorithm ID to the /dev/crypto equivalent value */\n\treturn( mapValue( cryptAlgo, hwAlgoID, hwCryptInfo, \n\t\t\t\t\t  FAILSAFE_ARRAYSIZE( hwCryptInfo, MAP_TABLE ) ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoInit( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tstruct session_op session;\n\tint hwAlgoID, cryptoFD, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\t\n\t/* Map the cryptlib algorithm ID to the /dev/crypto equivalent value */\n\tstatus = getHWAlgoID( capabilityInfoPtr->cryptAlgo, &hwAlgoID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Open the crypto device and set up a session to it */\n\tcryptoFD = open( \"/dev/crypto\", O_RDWR, 0 );\n\tif( cryptoFD < 0 )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tfcntl( cryptoFD, F_SETFD, FD_CLOEXEC );\n\tmemset( &session, 0, sizeof( struct session_op ) );\n\tif( isConvAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\t\tsession.cipher = hwAlgoID;\n\t\tsession.key = convInfo->userKey;\n\t\tsession.keylen = convInfo->userKeyLength;\n\t\t}\n\telse\n\t\tsession.mac = hwAlgoID;\n\tif( ioctl( cryptoFD, CIOCGSESSION, &session ) )\n\t\t{\n\t\tclose( cryptoFD );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* Remember the hardware interface details */\n\tcontextInfoPtr->cryptoFD = cryptoFD;\n\tcontextInfoPtr->sessionID = session.ses;\n\tSET_FLAGS( contextInfoPtr->flags, \n\t\t\t   CONTEXT_FLAG_DUMMY | CONTEXT_FLAG_DUMMY_INITED | \\\n\t\t\t   CONTEXT_FLAG_HWCRYPTO );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoEnd( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) );\n\n\t/* Shut down the crypto session and close the device handle */\n\tif( contextInfoPtr->cryptoFD > 0 )\n\t\t{\n\t\t( void ) ioctl( contextInfoPtr->cryptoFD, CIOCFSESSION, \n\t\t\t\t\t\t&contextInfoPtr->sessionID );\n\t\tclose( contextInfoPtr->cryptoFD );\n\t\t}\n\tcontextInfoPtr->cryptoFD = 0;\n\tcontextInfoPtr->sessionID = 0;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Clone the hardware crypto state, used as part of a context-clone \n   operation */\n\n#ifdef CIOCCPHASH\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoCloneState( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tstruct session_op session;\n\tconst uint32_t oldSessionID = contextInfoPtr->sessionID;\n\tconst int oldCryptoFD = contextInfoPtr->cryptoFD;\n\tint cryptoFD, hwAlgoID, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* Since we're referencing the original context's crypto FD and session\n\t   ID, we clear them before continuing to make sure that if any of the\n\t   following operations fail the original context's crypto session won't\n\t   be cleaned up */\n\tcontextInfoPtr->cryptoFD = 0;\n\tcontextInfoPtr->sessionID = 0;\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* /dev/crypto currently doesn't support copying state from a \n\t   conventional-encryption session, only a hash session.  To deal with\n\t   this we change the context back from a hardware crypto one which\n\t   can't be cloned to a software one, which can.  \n\t   \n\t   This particular situation virtually never occurs since it's only \n\t   triggered when cloning a user-supplied raw session-key object in an \n\t   envelope (pgp_env.c and res_env.c), and those are essentially never \n\t   used.  In any case given the slowdown created by using hardware \n\t   crypto, this probably isn't such a bad thing... */\n\tif( isConvAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\t\tCLEAR_FLAGS( contextInfoPtr->flags, \n\t\t\t\t\t CONTEXT_FLAG_DUMMY | CONTEXT_FLAG_DUMMY_INITED | \\\n\t\t\t\t\t CONTEXT_FLAG_HWCRYPTO );\n\t\treturn( capabilityInfoPtr->initKeyFunction( contextInfoPtr, \n\t\t\t\t\t\tconvInfo->userKey, convInfo->userKeyLength ) );\n\t\t}\n\n\t/* Map the cryptlib algorithm ID to the /dev/crypto equivalent value */\n\tstatus = getHWAlgoID( capabilityInfoPtr->cryptAlgo, &hwAlgoID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create a second session and copy the state from the first one into \n\t   it.  We have to dup() the crypto FD and initialise a second session\n\t   on it rather than creating a fresh FD and session via hwCryptoInit() \n\t   because session IDs aren't valid across FDs */\n\tcryptoFD = dup( oldCryptoFD );\n\tif( cryptoFD < 0 )\n\t\treturn( CRYPT_ERROR_FAILED );\n\tmemset( &session, 0, sizeof( struct session_op ) );\n\tif( isConvAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\t\tsession.cipher = hwAlgoID;\n\t\tsession.key = convInfo->userKey;\n\t\tsession.keylen = convInfo->userKeyLength;\n\t\tDEBUG_DIAG(( \"Trying to clone context for conventional algo %d, this \"\n\t\t\t\t\t \"will fail with the current version of /dev/crypto\", \n\t\t\t\t\t capabilityInfoPtr->cryptAlgo ));\n\t\t}\n\telse\n\t\tsession.mac = hwAlgoID;\n\tstatus = ioctl( cryptoFD, CIOCGSESSION, &session );\n\tif( status == 0 )\n\t\t{\n\t\tstruct cphash_op copyInfo;\n\n\t\tmemset( &copyInfo, 0, sizeof( struct cphash_op ) );\n\t\tcopyInfo.src_ses = oldSessionID;\n\t\tcopyInfo.dst_ses = session.ses;\n\t\tstatus = ioctl( cryptoFD, CIOCCPHASH, &copyInfo );\n\t\t}\n\tif( status != 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"CIOCCPHASH ioctl failed, errno = %d\", errno ));\n\t\tclose( cryptoFD );\n\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tcontextInfoPtr->cryptoFD = cryptoFD;\n\tcontextInfoPtr->sessionID = session.ses;\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint hwCryptoCloneState( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* CIOCCPHASH */\n\n/* Push data through the hardware cryptologic */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hwCryptoHash( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t  IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t  IN_LENGTH_Z int noBytes )\n\t{\n\tstruct crypt_op cryptOpInfo;\n\tint cryptoFlags = COP_FLAG_NONE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) );\n\n\t/* Set up the processing flags as required */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\tcryptoFlags |= COP_FLAG_RESET | COP_FLAG_UPDATE;\n\tif( noBytes > 0 )\n\t\tcryptoFlags |= COP_FLAG_UPDATE;\n\telse\n\t\tcryptoFlags |= COP_FLAG_FINAL;\n\n\t/* Set up the crypto info and send it to the cryptologic */\t\n\tmemset( &cryptOpInfo, 0, sizeof( struct crypt_op ) );\n\tcryptOpInfo.ses = contextInfoPtr->sessionID;\n\tcryptOpInfo.op = COP_ENCRYPT;\n\tcryptOpInfo.flags = cryptoFlags;\n\tcryptOpInfo.src = buffer;\n\tcryptOpInfo.len = noBytes;\n\tif( noBytes == 0 )\n\t\tcryptOpInfo.mac = contextInfoPtr->ctxHash->hash;\n\tif( ioctl( contextInfoPtr->cryptoFD, CIOCCRYPT, &cryptOpInfo ) ) \n\t\t{\n\t\tDEBUG_DIAG(( \"CIOCCRYPT hash ioctl failed, errno = %d\", errno ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hwCryptoCrypt( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t   IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t   IN_LENGTH_Z int noBytes,\n\t\t\t\t   const BOOLEAN doEncrypt )\n\t{\n\tstruct crypt_op cryptOpInfo;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) );\n\n\t/* Set up the crypto info and send it to the cryptologic */\t\n\tmemset( &cryptOpInfo, 0, sizeof( struct crypt_op ) );\n\tcryptOpInfo.ses = contextInfoPtr->sessionID;\n\tcryptOpInfo.op = doEncrypt ? COP_ENCRYPT : COP_DECRYPT;\n\tcryptOpInfo.flags = COP_FLAG_WRITE_IV;\n\tcryptOpInfo.src = cryptOpInfo.dst = buffer;\n\tcryptOpInfo.len = noBytes;\n\tcryptOpInfo.iv = contextInfoPtr->ctxConv->currentIV;\n\tif( ioctl( contextInfoPtr->cryptoFD, CIOCCRYPT, &cryptOpInfo ) ) \n\t\t{\n\t\tDEBUG_DIAG(( \"CIOCCRYPT crypt ioctl failed, errno = %d\", errno ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* HAS_DEVCRYPTO */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSelf-test Support Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Statically initialise a context for the internal self-test and a few \n   other internal-only functions such as when generating keyIDs for raw \n   encoded key data where no context is available */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint staticInitContext( OUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( CONTEXT ) const CONTEXT_TYPE type, \n\t\t\t\t\t   const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t   OUT_BUFFER_FIXED( contextDataSize ) void *contextData, \n\t\t\t\t\t   IN_LENGTH_MIN( 32 ) const int contextDataSize,\n\t\t\t\t\t   IN_OPT const void *keyData )\n\t{\n\tint status;\n\t\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isReadPtrDynamic( contextData, contextDataSize ) );\n\n\tREQUIRES( isEnumRange( type, CONTEXT ) );\n\tREQUIRES( contextDataSize >= 32 && \\\n\t\t\t  ( ( type != CONTEXT_PKC && \\\n\t\t\t\t  contextDataSize < MAX_INTLENGTH_SHORT ) || \\\n\t\t\t\t( type == CONTEXT_PKC && \\\n\t\t\t\t  contextDataSize < MAX_INTLENGTH ) ) );\n\n\tmemset( contextInfoPtr, 0, sizeof( CONTEXT_INFO ) );\n\tmemset( contextData, 0, contextDataSize );\n\tcontextInfoPtr->type = type;\n\tDATAPTR_SET( contextInfoPtr->capabilityInfo, ( void * ) capabilityInfoPtr );\n\tINIT_FLAGS( contextInfoPtr->flags, CONTEXT_FLAG_STATICCONTEXT );\n\tswitch( type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\tREQUIRES( keyData == ptr_align( keyData, 8 ) || \\\n\t\t\t\t\t  keyData == ptr_align( keyData, 16 ) );\n\t\t\tcontextInfoPtr->ctxConv = ( CONV_INFO * ) contextData;\n\t\t\tcontextInfoPtr->ctxConv->key = ( void * ) keyData;\n\t\t\tbreak;\n\n\t\tcase CONTEXT_HASH:\n\t\t\tcontextInfoPtr->ctxHash = ( HASH_INFO * ) contextData;\n\t\t\tcontextInfoPtr->ctxHash->hashInfo = ( void * ) keyData;\n\t\t\tbreak;\n\n\t\tcase CONTEXT_MAC:\n\t\t\tcontextInfoPtr->ctxMAC = ( MAC_INFO * ) contextData;\n\t\t\tcontextInfoPtr->ctxMAC->macInfo = ( void * ) keyData;\n\t\t\tbreak;\n\n\t\tcase CONTEXT_PKC:\n\t\t\t{\n\t\t\tPKC_INFO *pkcInfo = contextData;\n\n\t\t\t/* PKC context initialisation is a bit more complex because we\n\t\t\t   have to set up all of the bignum values as well.  Since static\n\t\t\t   contexts are only used for self-test operations we set the \n\t\t\t   side-channel protection level to zero */\n\t\t\tcontextInfoPtr->ctxPKC = pkcInfo;\n\t\t\tmemset( pkcInfo, 0, sizeof( PKC_INFO ) );\n\t\t\tINIT_FLAGS( pkcInfo->flags, PKCINFO_FLAG_NONE );\n\t\t\tstatus = initContextBignums( pkcInfo, \n\t\t\t\t\t\t\tisEccAlgo( capabilityInfoPtr->cryptAlgo ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tinitKeyID( contextInfoPtr );\n\t\t\tinitPubKeyRead( contextInfoPtr );\n\t\t\tinitPrivKeyRead( contextInfoPtr );\n\t\t\tinitKeyWrite( contextInfoPtr );\t\t/* For calcKeyID() */\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid staticDestroyContext( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tENSURES_V( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t  CONTEXT_FLAG_STATICCONTEXT ) );\n\n\t/* If this is a context that's implemented via built-in crypto hardware, \n\t   perform any required cleanup */\n#ifdef HAS_DEVCRYPTO\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\thwCryptoEnd( contextInfoPtr );\n#endif /* HAS_DEVCRYPTO */\n\n\tif( contextInfoPtr->type == CONTEXT_PKC )\n\t\t{\n\t\tendContextBignums( contextInfoPtr->ctxPKC, \n\t\t\t\t\t\t   GET_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_DUMMY ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t}\n\tmemset( contextInfoPtr, 0, sizeof( CONTEXT_INFO ) );\n\t}\n\n/* Perform a self-test of a cipher, encrypting and decrypting one block of \n   data and comparing it to a fixed test value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 6 ) ) \\\nint testCipher( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t\tIN const void *keyDataStorage, \n\t\t\t\tIN_BUFFER( keySize ) const void *key, \n\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keySize, \n\t\t\t\tIN const void *plaintext,\n\t\t\t\tIN const void *ciphertext )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tCONV_INFO contextData;\n\tBYTE temp[ CRYPT_MAX_IVSIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtr( capabilityInfo, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isReadPtr( keyDataStorage, 16 ) );\n\tassert( isReadPtrDynamic( key, keySize ) );\n\tassert( isReadPtrDynamic( plaintext, capabilityInfo->blockSize ) );\n\tassert( isReadPtrDynamic( ciphertext, capabilityInfo->blockSize ) );\n\n\tREQUIRES( capabilityInfo->encryptFunction != NULL && \\\n\t\t\t  capabilityInfo->decryptFunction != NULL );\n\tREQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE );\n\n\tREQUIRES( rangeCheck( capabilityInfo->blockSize, 1, \n\t\t\t\t\t\t  CRYPT_MAX_IVSIZE ) );\n\tmemcpy( temp, plaintext, capabilityInfo->blockSize );\n\n\tstatus = staticInitContext( &contextInfo, CONTEXT_CONV, capabilityInfo,\n\t\t\t\t\t\t\t\t&contextData, sizeof( CONV_INFO ), \n\t\t\t\t\t\t\t\tkeyDataStorage );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = capabilityInfo->initKeyFunction( &contextInfo, key, keySize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, temp, \n\t\t\t\t\t\t\t\t\t\t\t\t  capabilityInfo->blockSize );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( ciphertext, temp, capabilityInfo->blockSize ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfo->decryptFunction( &contextInfo, temp, \n\t\t\t\t\t\t\t\t\t\t\t\t  capabilityInfo->blockSize );\n\t\t}\n\tstaticDestroyContext( &contextInfo );\n\tif( cryptStatusError( status ) || \\\n\t\tmemcmp( plaintext, temp, capabilityInfo->blockSize ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a self-test of a hash or MAC */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nint testHash( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t  IN_LENGTH_HASH_Z const int hashSize,\n\t\t\t  IN const void *hashDataStorage,\n\t\t\t  IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t  IN_LENGTH_SHORT_Z const int dataLength, \n\t\t\t  IN const void *hashValue )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tHASH_INFO contextData;\n\tint status;\n\n\tassert( isReadPtr( capabilityInfo, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isReadPtr( hashDataStorage, 16 ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\tassert( isReadPtrDynamic( hashValue, capabilityInfo->blockSize ) );\n\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( dataLength ) ) );\n\tREQUIRES( hashSize == 0 || \\\n\t\t\t  ( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE ) );\n\n\tstatus = staticInitContext( &contextInfo, CONTEXT_HASH, capabilityInfo,\n\t\t\t\t\t\t\t\t&contextData, sizeof( HASH_INFO ), \n\t\t\t\t\t\t\t\thashDataStorage );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hashSize != 0 )\n\t\t{\n\t\tstatus = capabilityInfo->initParamsFunction( &contextInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t\t KEYPARAM_BLOCKSIZE, NULL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t hashSize );\n\t\t}\n\tif( cryptStatusOK( status ) && data != NULL )\n\t\t{\n\t\t/* Some of the test vector sets start out with empty strings so we \n\t\t   only call the hash function if we've actually been fed data to \n\t\t   hash */\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t  ( void * ) data, \n\t\t\t\t\t\t\t\t\t\t\t\t  dataLength );\n\t\tSET_FLAG( contextInfo.flags, CONTEXT_FLAG_HASH_INITED );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t  MKDATA( \"\" ), 0 );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( contextInfo.ctxHash->hash, hashValue, \n\t\t\t\tcapabilityInfo->blockSize ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 7 ) ) \\\nint testMAC( IN const CAPABILITY_INFO *capabilityInfo, \n\t\t\t IN const void *macDataStorage,\n\t\t\t IN_BUFFER( keySize ) const void *key, \n\t\t\t IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keySize, \n\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int dataLength,\n\t\t\t IN const void *hashValue )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tMAC_INFO contextData;\n\tint status;\n\n\tassert( isReadPtr( capabilityInfo, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isReadPtr( macDataStorage, 16 ) );\n\tassert( isReadPtrDynamic( key, keySize ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isReadPtrDynamic( hashValue, capabilityInfo->blockSize ) );\n\n\tREQUIRES( keySize >= 4 && keySize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( dataLength >= 8 && dataLength < MAX_INTLENGTH_SHORT );\n\n\tstatus = staticInitContext( &contextInfo, CONTEXT_MAC, capabilityInfo,\n\t\t\t\t\t\t\t\t&contextData, sizeof( MAC_INFO ), \n\t\t\t\t\t\t\t\tmacDataStorage );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = capabilityInfo->initKeyFunction( &contextInfo, key, keySize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t  ( void * ) data, \n\t\t\t\t\t\t\t\t\t\t\t\t  dataLength );\n\t\tSET_FLAG( contextInfo.flags, CONTEXT_FLAG_HASH_INITED );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t  MKDATA( \"\" ), 0 );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( contextInfo.ctxMAC->mac, hashValue, \n\t\t\t\tcapabilityInfo->blockSize ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHash External Access Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine the parameters for a particular hash algorithm */\n\ntypedef struct HI {\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\n\tconst int hashSize;\n\tconst HASH_FUNCTION function;\n\t} HASHFUNCTION_INFO;\n\ntypedef struct HAI {\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\n\tconst int hashSize;\n\tconst HASH_FUNCTION_ATOMIC function;\n\t} HASHFUNCTION_ATOMIC_INFO;\n\nSTDC_NONNULL_ARG( ( 3 ) ) \\\nvoid getHashParameters( IN_ALGO const CRYPT_ALGO_TYPE hashAlgorithm,\n\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParam,\n\t\t\t\t\t\tOUT_PTR HASH_FUNCTION *hashFunction, \n\t\t\t\t\t\tOUT_OPT_LENGTH_SHORT_Z int *hashOutputSize )\n\t{\n\tstatic const HASHFUNCTION_INFO hashFunctions[] = {\n#ifdef USE_MD5\n\t\t{ CRYPT_ALGO_MD5, MD5_DIGEST_LENGTH, md5HashBuffer },\n#endif /* USE_MD5 */\n\t\t{ CRYPT_ALGO_SHA1, SHA_DIGEST_LENGTH, shaHashBuffer },\n\t\t{ CRYPT_ALGO_SHA2, SHA256_DIGEST_SIZE, sha2HashBuffer },\n  #ifdef USE_SHA2_EXT\n\t\t/* The extended SHA2 variants are only available on systems with 64-\n\t\t   bit data type support */\n\t#if defined( CONFIG_SUITEB )\n\t\t{ CRYPT_ALGO_SHA2, SHA384_DIGEST_SIZE, sha2_ExtHashBuffer },\n\t#else\n\t\t{ CRYPT_ALGO_SHA2, SHA512_DIGEST_SIZE, sha2_ExtHashBuffer },\n\t#endif /* Suite B vs. generic use */\n  #endif /* USE_SHA2_EXT */\n\t\t{ CRYPT_ALGO_NONE, SHA_DIGEST_LENGTH, shaHashBuffer },\n\t\t\t{ CRYPT_ALGO_NONE, SHA_DIGEST_LENGTH, shaHashBuffer }\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\tassert( isHashAlgo( hashAlgorithm ) );\n\tassert( isShortIntegerRange( hashParam ) );\n\t\t\t/* We don't use REQUIRES() for this for the reason given in the\n\t\t\t   comments below */\n\tassert( isWritePtr( hashFunction, sizeof( HASH_FUNCTION ) ) );\n\tassert( ( hashOutputSize == NULL ) || \\\n\t\t\tisWritePtr( hashOutputSize, sizeof( int ) ) );\n\n\t/* Fast-path for SHA-1, which is almost always the one that we're being \n\t   asked for */\n\tif( hashAlgorithm == CRYPT_ALGO_SHA1 )\n\t\t{\n\t\t*hashFunction = shaHashBuffer;\n\t\tif( hashOutputSize != NULL )\n\t\t\t*hashOutputSize = SHA_DIGEST_LENGTH;\n\t\treturn;\n\t\t}\n\n\t/* Clear return value */\n\tif( hashOutputSize != NULL )\n\t\t*hashOutputSize = 0;\n\n\t/* Find the information for the requested hash algorithm */\n\tLOOP_SMALL( i = 0, hashFunctions[ i ].cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( hashFunctions, HASHFUNCTION_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\t/* If this isn't the algorithm that we're looking for, continue */\n\t\tif( hashFunctions[ i ].cryptAlgo != hashAlgorithm )\n\t\t\tcontinue;\n\n\t\t/* If we're looking for a specific hash-size match and this isn't\n\t\t   it, continue */\n\t\tif( hashParam != 0 && hashFunctions[ i ].hashSize != hashParam )\n\t\t\tcontinue;\n\n\t\t/* We've found what we're after */\n\t\tbreak;\n\t\t}\n\tif( !LOOP_BOUND_OK || \\\n\t\ti >= FAILSAFE_ARRAYSIZE( hashFunctions, HASHFUNCTION_INFO ) || \\\n\t\thashFunctions[ i ].cryptAlgo == CRYPT_ALGO_NONE )\n\t\t{\n\t\t/* Make sure that we always get some sort of hash function rather \n\t\t   than just dying.  This code always works because the internal \n\t\t   self-test has confirmed the availability and functioning of SHA-1 \n\t\t   on startup */\n\t\t*hashFunction = shaHashBuffer;\n\t\tif( hashOutputSize != NULL )\n\t\t\t*hashOutputSize = SHA_DIGEST_LENGTH;\n\t\tretIntError_Void();\n\t\t}\n\n\t*hashFunction = hashFunctions[ i ].function;\n\tif( hashOutputSize != NULL )\n\t\t*hashOutputSize = hashFunctions[ i ].hashSize;\n\t}\n\nSTDC_NONNULL_ARG( ( 3 ) ) \\\nvoid getHashAtomicParameters( IN_ALGO const CRYPT_ALGO_TYPE hashAlgorithm,\n\t\t\t\t\t\t\t  IN_INT_SHORT_Z const int hashParam,\n\t\t\t\t\t\t\t  OUT_PTR HASH_FUNCTION_ATOMIC *hashFunctionAtomic, \n\t\t\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *hashOutputSize )\n\t{\n\tstatic const HASHFUNCTION_ATOMIC_INFO hashFunctions[] = {\n#ifdef USE_MD5\n\t\t{ CRYPT_ALGO_MD5, MD5_DIGEST_LENGTH, md5HashBufferAtomic },\n#endif /* USE_MD5 */\n\t\t{ CRYPT_ALGO_SHA1, SHA_DIGEST_LENGTH, shaHashBufferAtomic },\n\t\t{ CRYPT_ALGO_SHA2, SHA256_DIGEST_SIZE, sha2HashBufferAtomic },\n  #ifdef USE_SHA2_EXT\n\t\t/* The extended SHA2 variants are only available on systems with 64-\n\t\t   bit data type support */\n\t#if defined( CONFIG_SUITEB )\n\t\t{ CRYPT_ALGO_SHA2, SHA384_DIGEST_SIZE, sha2_ExtHashBufferAtomic },\n\t#else\n\t\t{ CRYPT_ALGO_SHA2, SHA512_DIGEST_SIZE, sha2_ExtHashBufferAtomic },\n\t#endif /* Suite B vs. generic use */\n  #endif /* USE_SHA2_EXT */\n\t\t{ CRYPT_ALGO_NONE, SHA_DIGEST_LENGTH, shaHashBufferAtomic },\n\t\t\t{ CRYPT_ALGO_NONE, SHA_DIGEST_LENGTH, shaHashBufferAtomic }\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\tassert( isHashAlgo( hashAlgorithm ) );\n\tassert( isShortIntegerRange( hashParam ) );\n\t\t\t/* We don't use REQUIRES() for this for the reason given in the\n\t\t\t   comments below */\n\tassert( isWritePtr( hashFunctionAtomic, sizeof( HASH_FUNCTION_ATOMIC ) ) );\n\tassert( ( hashOutputSize == NULL ) || \\\n\t\t\tisWritePtr( hashOutputSize, sizeof( int ) ) );\n\n\t/* Fast-path for SHA-1, which is almost always the one that we're being \n\t   asked for */\n\tif( hashAlgorithm == CRYPT_ALGO_SHA1 )\n\t\t{\n\t\t*hashFunctionAtomic = shaHashBufferAtomic;\n\t\tif( hashOutputSize != NULL )\n\t\t\t*hashOutputSize = SHA_DIGEST_LENGTH;\n\t\treturn;\n\t\t}\n\n\t/* Clear return value */\n\tif( hashOutputSize != NULL )\n\t\t*hashOutputSize = 0;\n\n\t/* Find the information for the requested hash algorithm */\n\tLOOP_SMALL( i = 0, hashFunctions[ i ].cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( hashFunctions, HASHFUNCTION_ATOMIC_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\t/* If this isn't the algorithm that we're looking for, continue */\n\t\tif( hashFunctions[ i ].cryptAlgo != hashAlgorithm )\n\t\t\tcontinue;\n\n\t\t/* If we're looking for a specific hash-size match and this isn't\n\t\t   it, continue */\n\t\tif( hashParam != 0 && hashFunctions[ i ].hashSize != hashParam )\n\t\t\tcontinue;\n\n\t\t/* We've found what we're after */\n\t\tbreak;\n\t\t}\n\tif( !LOOP_BOUND_OK || \\\n\t\ti >= FAILSAFE_ARRAYSIZE( hashFunctions, HASHFUNCTION_ATOMIC_INFO ) || \\\n\t\thashFunctions[ i ].cryptAlgo == CRYPT_ALGO_NONE )\n\t\t{\n\t\t/* Make sure that we always get some sort of hash function rather \n\t\t   than just dying.  This code always works because the internal \n\t\t   self-test has confirmed the availability and functioning of SHA-1 \n\t\t   on startup */\n\t\t*hashFunctionAtomic = shaHashBufferAtomic;\n\t\tif( hashOutputSize != NULL )\n\t\t\t*hashOutputSize = SHA_DIGEST_LENGTH;\n\t\tretIntError_Void();\n\t\t}\n\n\t*hashFunctionAtomic = hashFunctions[ i ].function;\n\tif( hashOutputSize != NULL )\n\t\t*hashOutputSize = hashFunctions[ i ].hashSize;\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_rc2.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib RC2 Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"rc2.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/rc2.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC2\n\n/* Defines to map from EAY to native naming */\n\n#define RC2_BLOCKSIZE\t\t\t\tRC2_BLOCK\n#define RC2_EXPANDED_KEYSIZE\t\tsizeof( RC2_KEY )\n\n/* The RC2 key schedule provides a mechanism for reducing the effective key\n   size for export-control purposes, typically used to create 40-bit\n   espionage-enabled keys.  BSAFE always sets the bitcount to the actual\n   key size (so for example for a 128-bit key it first expands it up to 1024\n   bits and then folds it back down again to 128 bits).  Because this scheme\n   was copied by early S/MIME implementations (which were just BSAFE\n   wrappers), it's become a part of CMS/SMIME so we use it here even though\n   other sources do it differently */\n\n#define effectiveKeysizeBits( keySize )\t\tbytesToBits( keySize )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRC2 Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* RC2 test vectors from RFC 2268 */\n\nstatic const struct RC2_TEST {\n\tconst BYTE key[ 16 ];\n\tconst BYTE plaintext[ 8 ];\n\tconst BYTE ciphertext[ 8 ];\n\t} testRC2[] = {\n\t{ { 0x88, 0xBC, 0xA9, 0x0E, 0x90, 0x87, 0x5A, 0x7F,\n\t\t0x0F, 0x79, 0xC3, 0x84, 0x62, 0x7B, 0xAF, 0xB2 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x22, 0x69, 0x55, 0x2A, 0xB0, 0xF8, 0x5C, 0xA6 } }\n\t};\n\n/* Test the RC2 code against the RC2 test vectors */\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getRC2Capability();\n\ttypedef BYTE KEY_DATA[ RC2_EXPANDED_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\tint i, status, LOOP_ITERATOR;\n\n\tmemset( keyDataPtr, 0, RC2_EXPANDED_KEYSIZE );\t/* Keep static analysers happy */\n\tLOOP_SMALL( i = 0, i < sizeof( testRC2 ) / sizeof( struct RC2_TEST ), i++ )\n\t\t{\n\t\tstatus = testCipher( capabilityInfo, keyDataPtr, testRC2[ i ].key, \n\t\t\t\t\t\t\t 16, testRC2[ i ].plaintext, \n\t\t\t\t\t\t\t testRC2[ i ].ciphertext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = RC2_EXPANDED_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRC2 En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data in ECB mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\tint blockCount = noBytes / RC2_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Encrypt a block of data */\n\t\tRC2_ecb_encrypt( buffer, buffer, rc2Key, RC2_ENCRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += RC2_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\tint blockCount = noBytes / RC2_BLOCKSIZE;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\twhile( blockCount-- > 0 )\n\t\t{\n\t\t/* Decrypt a block of data */\n\t\tRC2_ecb_encrypt( buffer, buffer, rc2Key, RC2_DECRYPT );\n\n\t\t/* Move on to next block of data */\n\t\tbuffer += RC2_BLOCKSIZE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CBC mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* Encrypt the buffer of data */\n\tRC2_cbc_encrypt( buffer, buffer, noBytes, ( RC2_KEY * ) convInfo->key,\n\t\t\t\t\t convInfo->currentIV, RC2_ENCRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* Decrypt the buffer of data */\n\tRC2_cbc_encrypt( buffer, buffer, noBytes, ( RC2_KEY * ) convInfo->key,\n\t\t\t\t\t convInfo->currentIV, RC2_DECRYPT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt/decrypt data in CFB mode */\n\n#ifdef USE_CFB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = RC2_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Encrypt the data */\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( boundsCheck( ivCount, bytesToUse, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > RC2_BLOCKSIZE ) ? RC2_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tRC2_ecb_encrypt( convInfo->currentIV, convInfo->currentIV, rc2Key,\n\t\t\t\t\t\t RC2_ENCRYPT );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, buffer, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % RC2_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Decrypt data in CFB mode.  Note that the transformation can be made\n   faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp\n   all in one loop */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptCFB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t   IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\tBYTE temp[ RC2_BLOCKSIZE + 8 ];\n\tint i, ivCount = convInfo->ivCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* If there's any encrypted material left in the IV, use it now */\n\tif( ivCount > 0 )\n\t\t{\n\t\tint bytesToUse;\n\n\t\t/* Find out how much material left in the encrypted IV we can use */\n\t\tbytesToUse = RC2_BLOCKSIZE - ivCount;\n\t\tif( noBytes < bytesToUse )\n\t\t\tbytesToUse = noBytes;\n\n\t\t/* Decrypt the data */\n\t\tREQUIRES( rangeCheck( bytesToUse, 1, RC2_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, bytesToUse );\n\t\tLOOP_SMALL( i = 0, i < bytesToUse, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i + ivCount ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tREQUIRES( boundsCheck( ivCount, bytesToUse, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV + ivCount, temp, bytesToUse );\n\n\t\t/* Adjust the byte count and buffer position */\n\t\tnoBytes -= bytesToUse;\n\t\tbuffer += bytesToUse;\n\t\tivCount += bytesToUse;\n\t\t}\n\n\twhile( noBytes > 0 )\n\t\t{\n\t\tivCount = ( noBytes > RC2_BLOCKSIZE ) ? RC2_BLOCKSIZE : noBytes;\n\n\t\t/* Encrypt the IV */\n\t\tRC2_ecb_encrypt( convInfo->currentIV, convInfo->currentIV, rc2Key,\n\t\t\t\t\t\t RC2_ENCRYPT );\n\n\t\t/* Save the ciphertext */\n\t\tREQUIRES( rangeCheck( ivCount, 1, RC2_BLOCKSIZE ) );\n\t\tmemcpy( temp, buffer, ivCount );\n\n\t\t/* XOR the buffer contents with the encrypted IV */\n\t\tLOOP_SMALL( i = 0, i < ivCount, i++ )\n\t\t\tbuffer[ i ] ^= convInfo->currentIV[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Shift the ciphertext into the IV */\n\t\tREQUIRES( rangeCheck( ivCount, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( convInfo->currentIV, temp, ivCount );\n\n\t\t/* Move on to next block of data */\n\t\tnoBytes -= ivCount;\n\t\tbuffer += ivCount;\n\t\t}\n\n\t/* Remember how much of the IV is still available for use */\n\tconvInfo->ivCount = ( ivCount % RC2_BLOCKSIZE );\n\n\t/* Clear the temporary buffer */\n\tzeroise( temp, RC2_BLOCKSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRC2 Key Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if 0\n\nstatic int keyCrack( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\tBYTE data[ 32 ], key[ 32 ];\n#if 0\t/* Test data, key = \"\\x13\\x25\\x0c\\x1a\\x60\" */\n\tstatic const BYTE *plaintext = \"\\x11\\x1C\\xDB\\x36\\xDC\\x6E\\x19\\xF5\";\n\tstatic const BYTE *ciphertext = \"\\x9C\\x4E\\x66\\x8A\\xC7\\x6B\\x97\\xF5\";\n#else\t/* Actual data */\n\tstatic const BYTE *plaintext = \"\\x69\\xAB\\x54\\x23\\x2D\\x86\\x92\\x61\";\n\tstatic const BYTE *ciphertext = \"\\x34\\xAA\\xF1\\x83\\xBD\\x9C\\xC0\\x15\";\n#endif /* 0 */\n\tint i;\n\n\t/* Test file: IV =  17 17 F1 B0 94 E8 EE F8\t\tencData + 0\n\t\t\t\t  PT =\t06 0B 2A 86 48 86 F7 0D\n\t\t\t\t\t\t-----------------------\n\t\t\t\t  XOR:\t11 1C DB 36 DC 6E 19 F5 \n\n\t   So encr. above = CT block 2.\n\t\t\t\t\t  =\t9C 4E 66 8A C7 6B 97 F5\t\tencData + 8\n\n\t   Actual:    IV =  6F A0 7E A5 65 00 65 6C\t\tencData + 0\n\t\t\t\t  PT =\t06 0B 2A 86 48 86 F7 0D\n\t\t\t\t\t\t-----------------------\n\t\t\t\t  XOR:\t69 AB 54 23 2D 86 92 61 \n\n\t   So encr. above = CT block 2.\n\t\t\t\t\t  =\t34 AA F1 83 BD 9C C0 15\t\tencData + 8 */\n\n\tmemset( key, 0, 5 );\n//\tmemcpy( key, \"\\x13\\x25\\x0c\\x1a\\x60\", 5 );\n\tfor( i = 0; i < 256; i++ )\n\t\t{\n\t\tint keyIndex;\n\n\t\tprintf( \"Trying keys %02X xx.\\n\", i );\n\t\tfflush( stdout );\n\t\twhile( key[ 0 ] == i )\n\t\t\t{\n\t\t\tRC2_set_key( rc2Key, 5, key, effectiveKeysizeBits( 5 ) );\n\t\t\tRC2_ecb_encrypt( plaintext, data, rc2Key, RC2_ENCRYPT );\n\t\t\tif( data[ 0 ] == ciphertext[ 0 ] && \\\n\t\t\t\t!memcmp( data, ciphertext, 8 ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Found at %02X %02X %02X %02X %02X.\\n\",\n\t\t\t\t\t\tkey[ 0 ], key[ 1 ], key[ 2 ], key[ 3 ], key[ 4 ] );\n\t\t\t\tfflush( stdout );\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tfor( keyIndex = 4; keyIndex >= 0; keyIndex-- )\n\t\t\t\t{\n\t\t\t\tkey[ keyIndex ]++;\n\t\t\t\tif( key[ keyIndex ] > 0 )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( keyIndex == 1 )\n\t\t\t\t{\n\t\t\t\tprintf( \"Trying keys %02X %02X %02X %02X %02X.\\n\", \n\t\t\t\t\t\tkey[ 0 ], key[ 1 ], key[ 2 ], key[ 3 ], key[ 4 ] );\n\t\t\t\tfflush( stdout );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/* Key schedule an RC2 key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tRC2_KEY *rc2Key = ( RC2_KEY * ) convInfo->key;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength < MAX_INTLENGTH_SHORT );\n\n#if 0\nif( !memcmp( key, \"crackcrackcrack\", 15 ) )\n\tkeyCrack( contextInfoPtr );\n#endif /* 1 */\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n#ifdef USE_PKCS12\n\t/* The only time that RC2 is ever likely to be used is as RC2-40 (since \n\t   it's disabled by default and is only enabled when PKCS #12 is \n\t   enabled), which is still universally used by Windows and possibly a \n\t   number of other implementations as well.  To allow the use of keys \n\t   this short, the caller gives them an oddball length and prefixes them \n\t   with two copies of the string \"PKCS#12\", if we find this then we \n\t   shorten the keys back down to 40 bits */\n\tif( convInfo->userKeyLength == 14 + bitsToBytes( 40 ) && \\\n\t\t!memcmp( convInfo->userKey, \"PKCS#12PKCS#12\", 14 ) )\n\t\t{\n\t\tmemmove( convInfo->userKey, convInfo->userKey + 14, \n\t\t\t\t bitsToBytes( 40 ) );\n\t\tconvInfo->userKeyLength = bitsToBytes( 40 );\n\n\t\tRC2_set_key( rc2Key, convInfo->userKeyLength, convInfo->userKey, \n\t\t\t\t\t effectiveKeysizeBits( convInfo->userKeyLength ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_PKCS12 */\n\n\tRC2_set_key( rc2Key, keyLength, key, effectiveKeysizeBits( keyLength ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_RC2, bitsToBytes( 64 ), \"RC2\", 3,\n\tMIN_KEYSIZE, bitsToBytes( 128 ), bitsToBytes( 1024 ),\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptECB, decryptECB, encryptCBC, decryptCBC\n#ifdef USE_CFB\n\t, encryptCFB, decryptCFB\n#endif /* USE_CFB */\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRC2Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_RC2 */\n"
  },
  {
    "path": "deps/cl345/context/ctx_rc4.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib RC4 Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1994-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"rc4.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/rc4.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC4\n\n/* The size of the expanded RC4 keys */\n\n#define RC4_EXPANDED_KEYSIZE\tsizeof( RC4_KEY )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRC4 Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* RC4 test vectors from the BSAFE implementation */\n\nstatic const BYTE testRC4key1[] =\n\t{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };\nstatic const BYTE testRC4plaintext1[] =\n\t{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };\nstatic const BYTE testRC4ciphertext1[] =\n\t{ 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 };\n\nstatic const BYTE testRC4key2[] =\n\t{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };\nstatic const BYTE testRC4plaintext2[] =\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\nstatic const BYTE testRC4ciphertext2[] =\n\t{ 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 };\n\nstatic const BYTE testRC4key3[] =\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\nstatic const BYTE testRC4plaintext3[] =\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\nstatic const BYTE testRC4ciphertext3[] =\n\t{ 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A };\n\nstatic const BYTE testRC4key4[] =\n\t{ 0xEF, 0x01, 0x23, 0x45 };\nstatic const BYTE testRC4plaintext4[] =\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\nstatic const BYTE testRC4ciphertext4[] =\n\t{ 0xD6, 0xA1, 0x41, 0xA7, 0xEC, 0x3C, 0x38, 0xDF, 0xBD, 0x61 };\n\nstatic const BYTE testRC4key5[] =\n\t{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };\nstatic const BYTE testRC4plaintext5[] =\n\t{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\n\t  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };\nstatic const BYTE testRC4ciphertext5[] =\n\t{ 0x75, 0x95, 0xC3, 0xE6, 0x11, 0x4A, 0x09, 0x78,\n\t  0x0C, 0x4A, 0xD4, 0x52, 0x33, 0x8E, 0x1F, 0xFD,\n\t  0x9A, 0x1B, 0xE9, 0x49, 0x8F, 0x81, 0x3D, 0x76,\n\t  0x53, 0x34, 0x49, 0xB6, 0x77, 0x8D, 0xCA, 0xD8,\n\t  0xC7, 0x8A, 0x8D, 0x2B, 0xA9, 0xAC, 0x66, 0x08,\n\t  0x5D, 0x0E, 0x53, 0xD5, 0x9C, 0x26, 0xC2, 0xD1,\n\t  0xC4, 0x90, 0xC1, 0xEB, 0xBE, 0x0C, 0xE6, 0x6D,\n\t  0x1B, 0x6B, 0x1B, 0x13, 0xB6, 0xB9, 0x19, 0xB8,\n\t  0x47, 0xC2, 0x5A, 0x91, 0x44, 0x7A, 0x95, 0xE7,\n\t  0x5E, 0x4E, 0xF1, 0x67, 0x79, 0xCD, 0xE8, 0xBF,\n\t  0x0A, 0x95, 0x85, 0x0E, 0x32, 0xAF, 0x96, 0x89,\n\t  0x44, 0x4F, 0xD3, 0x77, 0x10, 0x8F, 0x98, 0xFD,\n\t  0xCB, 0xD4, 0xE7, 0x26, 0x56, 0x75, 0x00, 0x99,\n\t  0x0B, 0xCC, 0x7E, 0x0C, 0xA3, 0xC4, 0xAA, 0xA3,\n\t  0x04, 0xA3, 0x87, 0xD2, 0x0F, 0x3B, 0x8F, 0xBB,\n\t  0xCD, 0x42, 0xA1, 0xBD, 0x31, 0x1D, 0x7A, 0x43,\n\t  0x03, 0xDD, 0xA5, 0xAB, 0x07, 0x88, 0x96, 0xAE,\n\t  0x80, 0xC1, 0x8B, 0x0A, 0xF6, 0x6D, 0xFF, 0x31,\n\t  0x96, 0x16, 0xEB, 0x78, 0x4E, 0x49, 0x5A, 0xD2,\n\t  0xCE, 0x90, 0xD7, 0xF7, 0x72, 0xA8, 0x17, 0x47,\n\t  0xB6, 0x5F, 0x62, 0x09, 0x3B, 0x1E, 0x0D, 0xB9,\n\t  0xE5, 0xBA, 0x53, 0x2F, 0xAF, 0xEC, 0x47, 0x50,\n\t  0x83, 0x23, 0xE6, 0x71, 0x32, 0x7D, 0xF9, 0x44,\n\t  0x44, 0x32, 0xCB, 0x73, 0x67, 0xCE, 0xC8, 0x2F,\n\t  0x5D, 0x44, 0xC0, 0xD0, 0x0B, 0x67, 0xD6, 0x50,\n\t  0xA0, 0x75, 0xCD, 0x4B, 0x70, 0xDE, 0xDD, 0x77,\n\t  0xEB, 0x9B, 0x10, 0x23, 0x1B, 0x6B, 0x5B, 0x74,\n\t  0x13, 0x47, 0x39, 0x6D, 0x62, 0x89, 0x74, 0x21,\n\t  0xD4, 0x3D, 0xF9, 0xB4, 0x2E, 0x44, 0x6E, 0x35,\n\t  0x8E, 0x9C, 0x11, 0xA9, 0xB2, 0x18, 0x4E, 0xCB,\n\t  0xEF, 0x0C, 0xD8, 0xE7, 0xA8, 0x77, 0xEF, 0x96,\n\t  0x8F, 0x13, 0x90, 0xEC, 0x9B, 0x3D, 0x35, 0xA5,\n\t  0x58, 0x5C, 0xB0, 0x09, 0x29, 0x0E, 0x2F, 0xCD,\n\t  0xE7, 0xB5, 0xEC, 0x66, 0xD9, 0x08, 0x4B, 0xE4,\n\t  0x40, 0x55, 0xA6, 0x19, 0xD9, 0xDD, 0x7F, 0xC3,\n\t  0x16, 0x6F, 0x94, 0x87, 0xF7, 0xCB, 0x27, 0x29,\n\t  0x12, 0x42, 0x64, 0x45, 0x99, 0x85, 0x14, 0xC1,\n\t  0x5D, 0x53, 0xA1, 0x8C, 0x86, 0x4C, 0xE3, 0xA2,\n\t  0xB7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 0x52,\n\t  0x0E, 0xAC, 0xF2, 0xE3, 0x06, 0x6E, 0x23, 0x0C,\n\t  0x91, 0xBE, 0xE4, 0xDD, 0x53, 0x04, 0xF5, 0xFD,\n\t  0x04, 0x05, 0xB3, 0x5B, 0xD9, 0x9C, 0x73, 0x13,\n\t  0x5D, 0x3D, 0x9B, 0xC3, 0x35, 0xEE, 0x04, 0x9E,\n\t  0xF6, 0x9B, 0x38, 0x67, 0xBF, 0x2D, 0x7B, 0xD1,\n\t  0xEA, 0xA5, 0x95, 0xD8, 0xBF, 0xC0, 0x06, 0x6F,\n\t  0xF8, 0xD3, 0x15, 0x09, 0xEB, 0x0C, 0x6C, 0xAA,\n\t  0x00, 0x6C, 0x80, 0x7A, 0x62, 0x3E, 0xF8, 0x4C,\n\t  0x3D, 0x33, 0xC1, 0x95, 0xD2, 0x3E, 0xE3, 0x20,\n\t  0xC4, 0x0D, 0xE0, 0x55, 0x81, 0x57, 0xC8, 0x22,\n\t  0xD4, 0xB8, 0xC5, 0x69, 0xD8, 0x49, 0xAE, 0xD5,\n\t  0x9D, 0x4E, 0x0F, 0xD7, 0xF3, 0x79, 0x58, 0x6B,\n\t  0x4B, 0x7F, 0xF6, 0x84, 0xED, 0x6A, 0x18, 0x9F,\n\t  0x74, 0x86, 0xD4, 0x9B, 0x9C, 0x4B, 0xAD, 0x9B,\n\t  0xA2, 0x4B, 0x96, 0xAB, 0xF9, 0x24, 0x37, 0x2C,\n\t  0x8A, 0x8F, 0xFF, 0xB1, 0x0D, 0x55, 0x35, 0x49,\n\t  0x00, 0xA7, 0x7A, 0x3D, 0xB5, 0xF2, 0x05, 0xE1,\n\t  0xB9, 0x9F, 0xCD, 0x86, 0x60, 0x86, 0x3A, 0x15,\n\t  0x9A, 0xD4, 0xAB, 0xE4, 0x0F, 0xA4, 0x89, 0x34,\n\t  0x16, 0x3D, 0xDD, 0xE5, 0x42, 0xA6, 0x58, 0x55,\n\t  0x40, 0xFD, 0x68, 0x3C, 0xBF, 0xD8, 0xC0, 0x0F,\n\t  0x12, 0x12, 0x9A, 0x28, 0x4D, 0xEA, 0xCC, 0x4C,\n\t  0xDE, 0xFE, 0x58, 0xBE, 0x71, 0x37, 0x54, 0x1C,\n\t  0x04, 0x71, 0x26, 0xC8, 0xD4, 0x9E, 0x27, 0x55,\n\t  0xAB, 0x18, 0x1A, 0xB7, 0xE9, 0x40, 0xB0, 0xC0 };\n\n/* Test vector from the State/Commerce Department */\n\nstatic const BYTE testRC4key6[] =\n\t{ 0x61, 0x8A, 0x63, 0xD2, 0xFB };\nstatic const BYTE testRC4plaintext6[] =\n\t{ 0xDC, 0xEE, 0x4C, 0xF9, 0x2C };\nstatic const BYTE testRC4ciphertext6[] =\n\t{ 0xF1, 0x38, 0x29, 0xC9, 0xDE };\n\n/* Test the RC4 code against the test vectors from the BSAFE implementation */\n\nCHECK_RETVAL \\\nstatic int rc4Test( IN_BUFFER( keySize ) const BYTE *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keySize,\n\t\t\t\t\tIN_BUFFER( length ) const BYTE *plaintext, \n\t\t\t\t\tIN_BUFFER( length ) const BYTE *ciphertext,\n\t\t\t\t\tIN_LENGTH_SHORT const int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getRC4Capability();\n\tCONTEXT_INFO contextInfo;\n\tCONV_INFO contextData;\n\ttypedef BYTE KEY_DATA[ RC4_EXPANDED_KEYSIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( KEY_DATA_STORAGE, KEY_DATA );\n\tKEY_DATA_STORAGE keyDataStorage;\n\tKEY_DATA *keyDataPtr = ALIGN_STRUCT( &keyDataStorage, KEY_DATA, 16 ); \n\tBYTE temp[ 512 + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( key, keySize ) );\n\tassert( isReadPtrDynamic( plaintext, length ) );\n\tassert( isReadPtrDynamic( ciphertext, length ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( keySize ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\tstaticInitContext( &contextInfo, CONTEXT_CONV, capabilityInfo,\n\t\t\t\t\t   &contextData, sizeof( CONV_INFO ), keyDataPtr );\n\tREQUIRES( rangeCheck( length, 1, 512 ) );\n\tmemcpy( temp, plaintext, length );\n\tstatus = capabilityInfo->initKeyFunction( &contextInfo, key, keySize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Since RC4 changes its keying state on every en/decrypt, the \n\t\t   encryption function re-checksums the key data after the state has\n\t\t   been updated.  Normally the checksumming is handled by higher-\n\t\t   level code but since we're calling directly into internal \n\t\t   functions we have to do it explicitly here */\n\t\tcontextData.keyDataSize = RC4_EXPANDED_KEYSIZE;\n\t\tcontextData.keyDataChecksum = checksumData( contextData.key, \n\t\t\t\t\t\t\t\t\t\t\t\t\tcontextData.keyDataSize );\n\t\tstatus = capabilityInfo->encryptFunction( &contextInfo, temp,\n\t\t\t\t\t\t\t\t\t\t\t\t  length );\n\t\t}\n\tstaticDestroyContext( &contextInfo );\n\tif( cryptStatusError( status ) || \\\n\t\tmemcmp( ciphertext, temp, length ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\t/* We can't use the standard testCipher() for this test because of the \n\t   variable-length plaintext/ciphertext messages (rather than just a \n\t   single block for a block cipher) so we have to perform the tests \n\t   manually */\n\tif( rc4Test( testRC4key1, sizeof( testRC4key1 ), testRC4plaintext1,\n\t\t\t\t testRC4ciphertext1, sizeof( testRC4plaintext1 ) ) != CRYPT_OK || \\\n\t\trc4Test( testRC4key2, sizeof( testRC4key2 ), testRC4plaintext2,\n\t\t\t\t testRC4ciphertext2, sizeof( testRC4plaintext2 ) ) != CRYPT_OK || \\\n\t\trc4Test( testRC4key3, sizeof( testRC4key3 ), testRC4plaintext3,\n\t\t\t\t testRC4ciphertext3, sizeof( testRC4plaintext3 ) ) != CRYPT_OK ||\n#if 0\t/* 32-bit key, will fail the key length check */\n\t\trc4Test( testRC4key4, sizeof( testRC4key4 ), testRC4plaintext4,\n\t\t\t\t testRC4ciphertext4, sizeof( testRC4plaintext4 ) ) != CRYPT_OK ||\n#endif /* 0 */\n\t\trc4Test( testRC4key5, sizeof( testRC4key5 ), testRC4plaintext5,\n\t\t\t\t testRC4ciphertext5, sizeof( testRC4plaintext5 ) ) != CRYPT_OK\n#if 0\t/* 40-bit key, will fail the key length check */\n\t\t|| \\\n\t\trc4Test( testRC4key6, sizeof( testRC4key6 ), testRC4plaintext6,\n\t\t\t\t testRC4ciphertext6, sizeof( testRC4plaintext6 ) ) != CRYPT_OK \n#endif /* 0 */\n\t\t)\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = RC4_EXPANDED_KEYSIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRC4 En/Decryption Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data.  Since RC4 is a stream cipher, encryption and\n   decryption are the same operation.  We have to append the distinguisher\n   'Fn' to the name since some systems already have 'encrypt' and 'decrypt'\n   in their standard headers  */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH int noBytes )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( noBytes ) );\n\n\t/* We're about to modify the keying data, make sure that it's still \n\t   valid before we start */\n\tif( checksumData( convInfo->key, \\\n\t\t\t\t\t  convInfo->keyDataSize ) != convInfo->keyDataChecksum )\n\t\tretIntError();\n\n\tRC4( ( RC4_KEY * ) convInfo->key, noBytes, buffer, buffer );\n\n\t/* This en/decryption process updates changes the key data, so we have \n\t   to update the checksum before we return to the caller */\n\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRC4 Key Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create an expanded RC4 key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength < MAX_INTLENGTH_SHORT );\n\n\t/* Copy the key to internal storage */\n\tif( convInfo->userKey != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( convInfo->userKey, key, keyLength );\n\t\tconvInfo->userKeyLength = keyLength;\n\t\t}\n\n\tRC4_set_key( ( RC4_KEY * ) convInfo->key, keyLength, ( BYTE * ) key );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_RC4, bitsToBytes( 8 ), \"RC4\", 3,\n\tMIN_KEYSIZE, bitsToBytes( 128 ), 256,\n\tselfTest, getInfo, NULL, initGenericParams, initKey, NULL,\n\tencryptFn, encryptFn, NULL, NULL, NULL, NULL \n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRC4Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n\n#endif /* USE_RC4 */\n"
  },
  {
    "path": "deps/cl345/context/ctx_rsa.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib RSA Encryption Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* I suppose if we all used pure RSA, the Illuminati would blackmail God into\n   putting a trapdoor into the laws of mathematics.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t-- Lyle Seaman */\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAlgorithm Self-test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a pairwise consistency test on a public/private key pair */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = getRSACapability();\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckContext( contextInfoPtr ) );\n\n\t/* Encrypt with the public key */\n\tmemset( buffer, 0, CRYPT_MAX_PKCSIZE );\n\tmemcpy( buffer + 1, \"abcde\", 5 );\n\tstatus = capabilityInfoPtr->encryptFunction( contextInfoPtr, buffer,\n\t\t\t\t\t\t bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Decrypt with the private key */\n\tstatus = capabilityInfoPtr->decryptFunction( contextInfoPtr, buffer,\n\t\t\t\t\t\t bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that we're recovered the original, including correct\n\t   handling of leading zeroes */\n\treturn( !memcmp( buffer, \"\\x00\" \"abcde\" \"\\x00\\x00\\x00\\x00\", 10 ) );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the RSA implementation using a sample key.  Because a lot of the\n   high-level encryption routines don't exist yet, we cheat a bit and set\n   up a dummy encryption context with just enough information for the\n   following code to work */\n\ntypedef struct {\n\tconst int nLen; const BYTE n[ 128 ];\n\tconst int eLen; const BYTE e[ 3 ];\n\tconst int dLen; const BYTE d[ 128 ];\n\tconst int pLen; const BYTE p[ 64 ];\n\tconst int qLen; const BYTE q[ 64 ];\n\tconst int uLen; const BYTE u[ 64 ];\n\tconst int e1Len; const BYTE e1[ 64 ];\n\tconst int e2Len; const BYTE e2[ 64 ];\n\t} RSA_KEY;\n\nstatic const RSA_KEY rsaTestKey = {\n\t/* n */\n\t128,\n\t{ 0x9C, 0x4D, 0x98, 0x18, 0x67, 0xF9, 0x45, 0xBC,\n\t  0xB6, 0x75, 0x53, 0x5D, 0x2C, 0xFA, 0x55, 0xE4,\n\t  0x51, 0x54, 0x9F, 0x0C, 0x16, 0xB1, 0xAF, 0x89,\n\t  0xF6, 0xF3, 0xE7, 0x78, 0xB1, 0x2B, 0x07, 0xFB,\n\t  0xDC, 0xDE, 0x64, 0x23, 0x34, 0x87, 0xDA, 0x0B,\n\t  0xE5, 0xB3, 0x17, 0x16, 0xA4, 0xE3, 0x7F, 0x23,\n\t  0xDF, 0x96, 0x16, 0x28, 0xA6, 0xD2, 0xF0, 0x0A,\n\t  0x59, 0xEE, 0x06, 0xB3, 0x76, 0x6C, 0x64, 0x19,\n\t  0xD9, 0x76, 0x41, 0x25, 0x66, 0xD1, 0x93, 0x51,\n\t  0x52, 0x06, 0x6B, 0x71, 0x50, 0x0E, 0xAB, 0x30,\n\t  0xA5, 0xC8, 0x41, 0xFC, 0x30, 0xBC, 0x32, 0xD7,\n\t  0x4B, 0x22, 0xF2, 0x45, 0x4C, 0x94, 0x68, 0xF1,\n\t  0x92, 0x8A, 0x4C, 0xF9, 0xD4, 0x5E, 0x87, 0x92,\n\t  0xA8, 0x54, 0x93, 0x92, 0x94, 0x48, 0xA4, 0xA3,\n\t  0xEE, 0x19, 0x7F, 0x6E, 0xD3, 0x14, 0xB1, 0x48,\n\t  0xCE, 0x93, 0xD1, 0xEA, 0x4C, 0xE1, 0x9D, 0xEF },\n\n\t/* e */\n\t3,\n\t{ 0x01, 0x00, 0x01 },\n\n\t/* d */\n\t128,\n\t{ 0x37, 0xE2, 0x66, 0x67, 0x13, 0x85, 0xC4, 0xB1,\n\t  0x5C, 0x6B, 0x46, 0x8B, 0x21, 0xF1, 0xBF, 0x94,\n\t  0x0A, 0xA0, 0x3E, 0xDD, 0x8B, 0x9F, 0xAC, 0x2B,\n\t  0x9F, 0xE8, 0x44, 0xF2, 0x9A, 0x25, 0xD0, 0x8C,\n\t  0xF4, 0xC3, 0x6E, 0xFA, 0x47, 0x65, 0xEB, 0x48,\n\t  0x25, 0xB0, 0x8A, 0xA8, 0xC5, 0xFB, 0xB1, 0x11,\n\t  0x9A, 0x77, 0x87, 0x24, 0xB1, 0xC0, 0xE9, 0xA2,\n\t  0x49, 0xD5, 0x19, 0x00, 0x41, 0x6F, 0x2F, 0xBA,\n\t  0x9F, 0x28, 0x47, 0xF9, 0xB8, 0xBA, 0xFF, 0xF4,\n\t  0x8B, 0x20, 0xC9, 0xC9, 0x39, 0xAB, 0x52, 0x0E,\n\t  0x8A, 0x5A, 0xAF, 0xB3, 0xA3, 0x93, 0x4D, 0xBB,\n\t  0xFE, 0x62, 0x9B, 0x02, 0xCC, 0xA7, 0xB4, 0xAE,\n\t  0x86, 0x65, 0x88, 0x19, 0xD7, 0x44, 0xA7, 0xE4,\n\t  0x18, 0xB6, 0xCE, 0x01, 0xCD, 0xDF, 0x36, 0x81,\n\t  0xD5, 0xE1, 0x62, 0xF8, 0xD0, 0x27, 0xF1, 0x86,\n\t  0xA8, 0x58, 0xA7, 0xEB, 0x39, 0x79, 0x56, 0x41 },\n\n\t/* p */\n\t64,\n\t{ 0xCF, 0xDA, 0xF9, 0x99, 0x6F, 0x05, 0x95, 0x84,\n\t  0x09, 0x90, 0xB3, 0xAB, 0x39, 0xB7, 0xDD, 0x1D,\n\t  0x7B, 0xFC, 0xFD, 0x10, 0x35, 0xA0, 0x18, 0x1D,\n\t  0x9A, 0x11, 0x30, 0x90, 0xD4, 0x3B, 0xF0, 0x5A,\n\t  0xC1, 0xA6, 0xF4, 0x53, 0xD0, 0x94, 0xA0, 0xED,\n\t  0xE0, 0xE4, 0xE0, 0x8E, 0x44, 0x18, 0x42, 0x42,\n\t  0xE1, 0x2C, 0x0D, 0xF7, 0x30, 0xE2, 0xB8, 0x09,\n\t  0x73, 0x50, 0x28, 0xF6, 0x55, 0x85, 0x57, 0x03 },\n\n\t/* q */\n\t64,\n\t{ 0xC0, 0x81, 0xC4, 0x82, 0x6E, 0xF6, 0x1C, 0x92,\n\t  0x83, 0xEC, 0x17, 0xFB, 0x30, 0x98, 0xED, 0x6E,\n\t  0x89, 0x92, 0xB2, 0xA1, 0x21, 0x0D, 0xC1, 0x95,\n\t  0x49, 0x99, 0xD3, 0x79, 0xD3, 0xBD, 0x94, 0x93,\n\t  0xB9, 0x28, 0x68, 0xFF, 0xDE, 0xEB, 0xE8, 0xD2,\n\t  0x0B, 0xED, 0x7C, 0x08, 0xD0, 0xD5, 0x59, 0xE3,\n\t  0xC1, 0x76, 0xEA, 0xC1, 0xCD, 0xB6, 0x8B, 0x39,\n\t  0x4E, 0x29, 0x59, 0x5F, 0xFA, 0xCE, 0x83, 0xA5 },\n\n\t/* u */\n\t64,\n\t{ 0x4B, 0x87, 0x97, 0x1F, 0x27, 0xED, 0xAA, 0xAF,\n\t  0x42, 0xF4, 0x57, 0x82, 0x3F, 0xEC, 0x80, 0xED,\n\t  0x1E, 0x91, 0xF8, 0xB4, 0x33, 0xDA, 0xEF, 0xC3,\n\t  0x03, 0x53, 0x0F, 0xCE, 0xB9, 0x5F, 0xE4, 0x29,\n\t  0xCC, 0xEE, 0x6A, 0x5E, 0x11, 0x0E, 0xFA, 0x66,\n\t  0x85, 0xDC, 0xFC, 0x48, 0x31, 0x0C, 0x00, 0x97,\n\t  0xC6, 0x0A, 0xF2, 0x34, 0x60, 0x6B, 0xF7, 0x68,\n\t  0x09, 0x4E, 0xCF, 0xB1, 0x9E, 0x33, 0x9A, 0x41 },\n\n\t/* exponent1 */\n\t64,\n\t{ 0x6B, 0x2A, 0x0D, 0xF8, 0x22, 0x7A, 0x71, 0x8C,\n\t  0xE2, 0xD5, 0x9D, 0x1C, 0x91, 0xA4, 0x8F, 0x37,\n\t  0x0D, 0x5E, 0xF1, 0x26, 0x73, 0x4F, 0x78, 0x3F,\n\t  0x82, 0xD8, 0x8B, 0xFE, 0x8F, 0xBD, 0xDB, 0x7D,\n\t  0x1F, 0x4C, 0xB1, 0xB9, 0xA8, 0xD7, 0x88, 0x65,\n\t  0x3C, 0xC7, 0x24, 0x53, 0x95, 0x1E, 0x20, 0xC3,\n\t  0x94, 0x8E, 0x7F, 0x20, 0xCC, 0x2E, 0x88, 0x0E,\n\t  0x2F, 0x4A, 0xCB, 0xE3, 0xBD, 0x52, 0x02, 0xFB },\n\n\t/* exponent2 */\n\t64,\n\t{ 0x10, 0x27, 0xD3, 0xD2, 0x0E, 0x75, 0xE1, 0x17,\n\t  0xFA, 0xB2, 0x49, 0xA0, 0xEF, 0x07, 0x26, 0x85,\n\t  0xEC, 0x4D, 0xBF, 0x67, 0xFE, 0x5A, 0x25, 0x30,\n\t  0xDE, 0x28, 0x66, 0xB3, 0x06, 0xAE, 0x16, 0x55,\n\t  0xFF, 0x68, 0x00, 0xC7, 0xD8, 0x71, 0x7B, 0xEC,\n\t  0x84, 0xCB, 0xBD, 0x69, 0x0F, 0xFD, 0x97, 0xB9,\n\t  0xA1, 0x76, 0xD5, 0x64, 0xC6, 0x5A, 0xD7, 0x7C,\n\t  0x4B, 0xAE, 0xF4, 0xAD, 0x35, 0x63, 0x37, 0x71 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initContext( OUT CONTEXT_INFO *contextInfo,\n\t\t\t\t\t\tOUT PKC_INFO *pkcInfo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfo, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\t/* Clear return values */\n\tmemset( contextInfo, 0, sizeof( CONTEXT_INFO ) );\n\tmemset( pkcInfo, 0, sizeof( PKC_INFO ) );\n\n\tstatus = staticInitContext( contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetRSACapability(), pkcInfo, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importBignum( &pkcInfo->rsaParam_n, rsaTestKey.n, \n\t\t\t\t\t\t   rsaTestKey.nLen, RSAPARAM_MIN_N, \n\t\t\t\t\t\t   RSAPARAM_MAX_N, NULL, KEYSIZE_CHECK_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_e, rsaTestKey.e, \n\t\t\t\t\t\t\t   rsaTestKey.eLen, RSAPARAM_MIN_E, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_E, &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_d, rsaTestKey.d, \n\t\t\t\t\t\t\t   rsaTestKey.dLen, RSAPARAM_MIN_D, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_D, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_p, rsaTestKey.p, \n\t\t\t\t\t\t\t   rsaTestKey.pLen, RSAPARAM_MIN_P, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_P, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_q, rsaTestKey.q, \n\t\t\t\t\t\t\t   rsaTestKey.qLen, RSAPARAM_MIN_Q, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_Q, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_u, rsaTestKey.u, \n\t\t\t\t\t\t\t   rsaTestKey.uLen, RSAPARAM_MIN_U, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_U, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_exponent1, rsaTestKey.e1, \n\t\t\t\t\t\t\t   rsaTestKey.e1Len, RSAPARAM_MIN_EXP1, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_EXP1, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importBignum( &pkcInfo->rsaParam_exponent2, rsaTestKey.e2, \n\t\t\t\t\t\t\t   rsaTestKey.e2Len, RSAPARAM_MIN_EXP2, \n\t\t\t\t\t\t\t   RSAPARAM_MAX_EXP2, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tBYTE buffer[ 128 + 8 ];\n\tint status;\n\n\t/* Initialise the key components */\n\tstatus = initContext( &contextInfo, pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Perform the test en/decryption of a block of data */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfo.capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\t!pairwiseConsistencyTest( &contextInfo ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tstaticDestroyContext( &contextInfo );\n\n\t/* Try it again with side-channel protection/blinding enabled.  Note \n\t   that this uses the randomness subsystem, which can significantly slow \n\t   down the self-test if it's being performed before the polling has \n\t   completed.\n\t   \n\t   Since we're still using the same key but changing the way that it's\n\t   used, we have to call initKeyFunction() on the existing data, which\n\t   isn't normally done.  Because the re-init with blinding changed the\n\t   bignum state, we reset the checksums to force them to be re-\n\t   calculated */\n\tmemcpy( buffer, \"abcde\", 5 );\n\tmemset( buffer + 5, 0, rsaTestKey.nLen - 5 );\n\tstatus = initContext( &contextInfo, pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( contextInfo.flags, CONTEXT_FLAG_SIDECHANNELPROTECTION );\n\tstatus = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->encryptFunction( &contextInfo,\n\t\t\t\t\t\t\t\t\t\t\tbuffer, rsaTestKey.nLen );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( &contextInfo,\n\t\t\t\t\t\t\t\t\t\t\tbuffer, rsaTestKey.nLen );\n\t\t}\n\tif( cryptStatusError( status ) || memcmp( buffer, \"abcde\", 5 ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* And one last time to ensure that the blinding value update works */\n\tmemcpy( buffer, \"fghij\", 5 );\n\tmemset( buffer + 5, 0, rsaTestKey.nLen - 5 );\n\tstatus = capabilityInfoPtr->encryptFunction( &contextInfo,\n\t\t\t\t\t\t\t\t\t\t\tbuffer, rsaTestKey.nLen );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->decryptFunction( &contextInfo,\n\t\t\t\t\t\t\t\t\t\t\tbuffer, rsaTestKey.nLen );\n\t\t}\n\tif( cryptStatusError( status ) || memcmp( buffer, \"fghij\", 5 ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* The checking for memory faults is performed at the \n\t   MESSAGE_CTX_ENCRYPT level, so it won't be detected when we call the\n\t   function directly via an internal code pointer */\n#if 0\n\t/* Finally, make sure that the memory fault-detection is working */\n\tpkcInfo->rsaParam_n.d[ 8 ] ^= 0x0100;\n\tstatus = capabilityInfoPtr->encryptFunction( &contextInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t buffer, rsaTestKey.nLen );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fault-detection couldn't detect a bit-flip, there's a \n\t\t   problem */\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#else\n\t/* Emulation of what the above code would do */\n\tpkcInfo->rsaParam_n.d[ 8 ] ^= 0x0100;\n\tstatus = checksumContextData( pkcInfo, CRYPT_ALGO_RSA, TRUE );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( &contextInfo );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#endif /* 0 */\n\n\t/* Clean up */\n\tstaticDestroyContext( &contextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEncrypt/Decrypt a Data Block\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/signature check a single block of data.  We have to append the\n   distinguisher 'Fn' to the name since some systems already have 'encrypt'\n   and 'decrypt' in their standard headers */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_SHORT int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tBIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;\n\tBIGNUM *data = &pkcInfo->tmp1;\n\tconst int length = bitsToBytes( pkcInfo->keySizeBits );\n\tint offset, dummy, bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == length );\n\tREQUIRES( isShortIntegerRangeNZ( noBytes ) );\n\n\t/* Move the data from the buffer into a bignum */\n\tstatus = importBignum( data, buffer, length, \n\t\t\t\t\t\t   MIN_PKCSIZE - 8, CRYPT_MAX_PKCSIZE, n, \n\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Perform the modexp and move the result back into the buffer.  Since \n\t   this function takes a fixed-length input and produces a fixed-length\n\t   result but the bignum code performs leading-zero truncation, we have \n\t   to adjust where we copy the result to in the buffer to take into \n\t   account extra zero bytes that aren't extracted from the bignum */\n\tCK( BN_mod_exp_mont( data, data, e, n, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->rsaParam_mont_n ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\toffset = length - BN_num_bytes( data );\n\tENSURES( offset >= 0 && offset <= length );\n\tif( offset > 0 )\n\t\t{\n\t\t/* If the resulting value has more than 128 bits of leading zeroes\n\t\t   then there's something wrong */\n\t\tif( offset > 16 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tmemset( buffer, 0, offset );\n\t\t}\n\tstatus = exportBignum( buffer + offset, noBytes - offset, &dummy, data );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Use the Chinese Remainder Theorem shortcut for RSA decryption/signature\n   generation.  n isn't needed because of this.\n\n   There are two types of side-channel attack protection that we employ for\n   prvate-key operations, the first being standard blinding included in the\n   code below.  The second type applies to CRT-based RSA implementations and\n   is based on the fact that if a fault occurs during the computation of p2\n   or q2 (to give, say, p2') then applying the CRT will yield a faulty\n   signature M'.  An attacker can then compute q from\n   gcd( M' ** e - ( C mod n ), n ), and the same for q2' and p.  The chances\n   of this actually occurring are... unlikely, given that it requires a\n   singleton failure inside the CPU (with data running over ECC-protected\n   buses) at the exact moment of CRT computation (the original threat model\n   assumed a fault-injection attack on a smart card), however we can still\n   provide protection against the problem for people who consider it a\n   genuine threat.\n\n   The problem was originally pointed out by Marc Joye, Arjen Lenstra, and\n   Jean-Jacques Quisquater in \"Chinese Remaindering Based Cryptosystems in\n   the Presence of Faults\", Journal of Cryptology, Vol.12, No.4 (Autumn\n   1999), p.241, based on an earlier result \"On the importance of checking\n   cryptographic protocols for faults\", Dan Boneh, Richard DeMillo, and\n   Richard Lipton, Proceedings of EuroCrypt'97, Springer-Verlag LNCS \n   Vol.1233, May 1997, p.37.  Adi Shamir presented one possible solution to \n   the problem in the conference's rump session in \"How to check modular \n   exponentiation\", which performs a parallel computation of the potentially \n   fault-affected portions of the CRT operation in blinded form and then \n   checks that the two outputs are consistent.  This has three drawbacks: \n   It's slow, Shamir patented it (US Patent 5,991,415), and if one CRT is \n   faulty there's no guarantee that the parallel CRT won't be faulty as \n   well.  Better solutions were suggested by Sung-Ming Yen, Seungjoo Kim, \n   Seongan Lim, and Sangjae Moon in \"RSA Speedup with Residue Number System \n   Immune against Hardware Fault Cryptanalysis\", Proceedings of the \n   Information Security and Cryptology Conference (ICISC'01), Springer-\n   Verlag LNCS Vol.2288, December 2001, p.397.  These have less overhead \n   than Shamir's approach and are also less patented, but like Shamir's \n   approach they involve messing around with the CRT computation.  A further \n   update to this given by Sung-Ming Yen, Sangjae Kim, and Jae-Cheol Ha in \n   \"Hardware Fault Attack on RSA with CRT Revisited\", Proceedings of the \n   Information Security and Cryptology Conference (ICISC'02), Springer-\n   Verlag LNCS Vol.2587, November 2002, p.374, which updated the earlier \n   work and also found flaws in Shamir's solution.  Numerous further updates\n   and ideas followed, for example \"RSA with CRT: A New Cost-Effective \n   Solution to Thwart Fault Attacks\", David Vigilant, Proceedings of the\n   Workshop on Cryptographic Hardware and Embedded Systems (CHES'08), \n   Springer-Verlag LNCS No.5154, August 2008, p.130, \"Fault Attacks and \n   Countermeasures on Vigilant's RSA-CRT Algorithm\", Jean-Sbastien Coron, \n   Christophe Giraud, Nicolas Morin, Gilles Piret and David Vigilant, \n   Proceedings of the Workshop on Fault Diagnosis and Tolerance in \n   Cryptography (FDTC'10), August 2010, p.89, and \"Formal Analysis of \n   CRT-RSA Vigilant's Countermeasure Against the BellCoRe Attack\", Pablo \n   Rauzy and Sylvain Guilley, Proceedings of the Program Protection and \n   Reverse Engineering Workshop (PPREW'14), January 2014, Article No.2.  \n   More updates, with comprehensive surveys of existing approaches, are\n   \"The Fault Attack Jungle - A Classification Model to Guide You\", \n   Proceedings of the Workshop on Fault Diagnosis and Tolerance in \n   Cryptography (FDTC'11), p.3 and \"Countermeasures Against High-Order \n   Fault-Injection Attacks on CRT-RSA\" by Pablo Rauzy and Sylvain Guilley, \n   Proceedings of the Workshop on Fault Diagnosis and Tolerance in \n   Cryptography (FDTC'14), currently unpublished but the paper is available \n   as https://eprint.iacr.org/2014/559.\n\n   A much simpler solution is just to verify the CRT-based private-key\n   operation with the matching public-key operation after we perform it.\n   Since this is only required for signatures (the output of a decrypt is\n   (a) never visible to an attacker and (b) verified via the PKCS #1\n   padding), we perform this operation at a higher level, performing a\n   signature verify after each signature generation at the crypto mechanism\n   level */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int decryptFn( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_SHORT int noBytes )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tBIGNUM *p = &pkcInfo->rsaParam_p, *q = &pkcInfo->rsaParam_q;\n\tBIGNUM *u = &pkcInfo->rsaParam_u, *e1 = &pkcInfo->rsaParam_exponent1;\n\tBIGNUM *e2 = &pkcInfo->rsaParam_exponent2;\n\tBIGNUM *data = &pkcInfo->tmp1, *p2 = &pkcInfo->tmp2, *q2 = &pkcInfo->tmp3;\n\tBOOLEAN dummyAdd = TRUE;\n\tconst int length = bitsToBytes( pkcInfo->keySizeBits );\n\tint offset, dummy, bnStatus = BN_STATUS, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( noBytes == length );\n\tREQUIRES( isShortIntegerRangeNZ( noBytes ) );\n\n\t/* Move the data from the buffer into a bignum.  We need to make an \n\t   unfortunate exception to the valid-length check for SSL's weird \n\t   signatures, which sign a raw concatenated MD5 and SHA-1 hash with a \n\t   total length of 36 bytes */\n\tstatus = importBignum( data, buffer, length, 36, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t   &pkcInfo->rsaParam_n, KEYSIZE_CHECK_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( BN_num_bytes( data ) != 36 && \\\n\t\tBN_num_bytes( data ) < MIN_PKCSIZE - 8 )\n\t\t{\n\t\t/* If it's not the weird SSL signature and it's outside the valid \n\t\t   length range, reject it */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* If we're blinding the RSA operation, set:\n\n\t\tdata = ( ( rand^e ) * data ) mod n (where k = rand^e) \n\t\n\t   In theory we could use BN_mod_mul_montgomery() for this and the later\n\t   un-blinding and k update, but that would require converting data to\n\t   its Montgomery form (as well as k/kInv, but we could keep that in\n\t   the Montgomery form all the time).  It's not clear how much benefit\n\t   would be gained by this, since it requires two Montgomery-form \n\t   conversions for each RSA operation */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tBIGNUM *k = &pkcInfo->rsaParam_blind_k;\n\n\t\tCK( BN_mod_mul( data, data, k, &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t&pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Rather than decrypting by computing a modexp with full mod n\n\t   precision, compute a shorter modexp with mod p and mod q precision:\n\n\t\tp2 = ( ( C mod p ) ** exponent1 ) mod p\n\t\tq2 = ( ( C mod q ) ** exponent2 ) mod q */\n\tREQUIRES( BN_cmp( p, q ) > 0 );\t\t/* Precondition for CRT shortcut */\n\tCK( BN_mod( p2, data, p,\t\t\t/* p2 = C mod p  */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_mod_exp_mont( p2, p2, e1, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->rsaParam_mont_p ) );\n\tCK( BN_mod( q2, data, q,\t\t\t/* q2 = C mod q  */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_mod_exp_mont( q2, q2, e2, q, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->rsaParam_mont_q ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* p2 = p2 - q2; if p2 < 0 then p2 = p2 + p.  In some extremely rare\n\t   cases (q2 large, p2 small) we have to add p twice to get p2\n\t   positive */\n\tCK( BN_sub( p2, p2, q2 ) );\n\tLOOP_SMALL_CHECK( bnStatusOK( bnStatus ) && BN_is_negative( p2 ) )\n\t\t{\n\t\tCK( BN_add( p2, p2, p ) );\n\t\tdummyAdd = FALSE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* M = ( ( ( p2 * u ) mod p ) * q ) + q2 */\n\tCK( BN_mod_mul( data, p2, u, p,\t\t/* data = ( p2 * u ) mod p */\n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_mul( p2, data, q,\t\t\t/* p2 = data * q (bn can't reuse data) */\n\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( BN_add( data, p2, q2 ) );\t\t/* data = p2 + q2 */\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* If we didn't adjust p above, perform a dummy add operation that takes\n\t   roughly the same time as the p-adjust would have.  The second add of p\n\t   is virtually nonexistent so we don't bother performing a second \n\t   compensating add */\n\tif( dummyAdd )\n\t\t( void ) BN_add( q2, q2, p );\n\n\t/* If we're blinding the RSA operation, set\n\n\t\tdata = ( ( data^e ) / rand ) mod n\n\t\t\t = ( rand^-1 * data ) mod n */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tBIGNUM *n = &pkcInfo->rsaParam_n;\n\t\tBIGNUM *k = &pkcInfo->rsaParam_blind_k;\n\t\tBIGNUM *kInv = &pkcInfo->rsaParam_blind_kInv;\n\n\t\tCK( BN_mod_mul( data, data, kInv, n, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\n\t\t/* Update the blinding values in such a way that we get new random\n\t\t   (that is, unpredictable to an outsider) numbers of the correct\n\t\t   form without having to do a full modexp as we would if starting\n\t\t   with new random data:\n\n\t\t\tk = ( k^2 ) mod n \n\t\t\n\t\t   In theory we could replace the random blinding value periodically\n\t\t   in order to avoid an attacker being able to build up stats on it \n\t\t   and the values derived from it, but it seems unlikely that they \n\t\t   can do much with this and leads to problems of its own since the\n\t\t   process of calculating the new blinding value is itself \n\t\t   susceptible to side-channel attacks */\n\t\tCK( BN_mod_mul( k, k, k, n, &pkcInfo->bnCTX ) );\n\t\tCK( BN_mod_mul( kInv, kInv, kInv, n, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Perform the modexp and move the result back into the buffer.  Since \n\t   this function takes a fixed-length input and produces a fixed-length\n\t   result but the bignum code performs leading-zero truncation, we have \n\t   to adjust where we copy the result to in the buffer to take into \n\t   account extra zero bytes that aren't extracted from the bignum */\n\toffset = length - BN_num_bytes( data );\n\tENSURES( offset >= 0 && offset <= length );\n\tif( offset > 0 )\n\t\t{\n\t\t/* If the resulting value has more than 128 bits of leading zeroes\n\t\t   then there's something wrong */\n\t\tif( offset > 16 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tmemset( buffer, 0, offset );\n\t\t}\n\tstatus = exportBignum( buffer + offset, noBytes - offset, &dummy, data );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tLoad Key Components\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load key components into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( keyLength ) const void *key,\n\t\t\t\t\tIN_LENGTH_SHORT_OPT const int keyLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( key, keyLength ) && \\\n\t\t\t  keyLength == sizeof( CRYPT_PKCINFO_RSA ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && keyLength == sizeof( CRYPT_PKCINFO_RSA ) ) );\n\n#ifndef USE_FIPS140\n\t/* Load the key component from the external representation into the\n\t   internal bignums unless we're doing an internal load */\n\tif( key != NULL )\n\t\t{\n\t\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\t\tconst CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;\n\t\tint status;\n\n\t\tif( rsaKey->isPublicKey )\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\telse\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPRIVATEKEY );\n\t\tstatus = importBignum( &pkcInfo->rsaParam_n, rsaKey->n, \n\t\t\t\t\t\t\t   bitsToBytes( rsaKey->nLen ), \n\t\t\t\t\t\t\t   RSAPARAM_MIN_N, RSAPARAM_MAX_N, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_PKC );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->rsaParam_e, rsaKey->e, \n\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->eLen ),\n\t\t\t\t\t\t\t\t   RSAPARAM_MIN_E, RSAPARAM_MAX_E,\n\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !rsaKey->isPublicKey )\n\t\t\t{\n\t\t\tstatus = importBignum( &pkcInfo->rsaParam_d, rsaKey->d, \n\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->dLen ),\n\t\t\t\t\t\t\t\t   RSAPARAM_MIN_D, RSAPARAM_MAX_D,\n\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->rsaParam_p, rsaKey->p, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->pLen ),\n\t\t\t\t\t\t\t\t\t   RSAPARAM_MIN_P, RSAPARAM_MAX_P,\n\t\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->rsaParam_q, rsaKey->q, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->qLen ),\n\t\t\t\t\t\t\t\t\t   RSAPARAM_MIN_Q, RSAPARAM_MAX_Q,\n\t\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) && rsaKey->uLen > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->rsaParam_u, rsaKey->u, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->uLen ),\n\t\t\t\t\t\t\t\t\t   RSAPARAM_MIN_U, RSAPARAM_MAX_U,\n\t\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) && rsaKey->e1Len > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->rsaParam_exponent1, rsaKey->e1, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->e1Len ),\n\t\t\t\t\t\t\t\t\t   RSAPARAM_MIN_EXP1, RSAPARAM_MAX_EXP1,\n\t\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) && rsaKey->e2Len > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = importBignum( &pkcInfo->rsaParam_exponent2, rsaKey->e2, \n\t\t\t\t\t\t\t\t\t   bitsToBytes( rsaKey->e2Len ),\n\t\t\t\t\t\t\t\t\t   RSAPARAM_MIN_EXP2, RSAPARAM_MAX_EXP2,\n\t\t\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n, \n\t\t\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t\t\t}\n\t\t\t}\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PBO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\t}\n#endif /* USE_FIPS140 */\n\n\t/* Complete the key checking and setup */\n\treturn( initCheckRSAkey( contextInfoPtr ) );\n\t}\n\n/* Generate a key into an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\tstatus = generateRSAkey( contextInfoPtr, keySizeBits );\n\tif( cryptStatusOK( status ) &&\n#ifndef USE_FIPS140\n\t\tTEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) &&\n#endif /* USE_FIPS140 */\n\t\t!pairwiseConsistencyTest( contextInfoPtr ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Consistency check of freshly-generated RSA key \"\n\t\t\t\t\t \"failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_FAILED : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_RSA, bitsToBytes( 0 ), \"RSA\", 3,\n\tMIN_PKCSIZE, bitsToBytes( 1536 ), CRYPT_MAX_PKCSIZE,\n\tselfTest, getDefaultInfo, NULL, NULL, initKey, generateKey, \n\tencryptFn, decryptFn, NULL, NULL, NULL, NULL, NULL, NULL, \n\tdecryptFn, encryptFn\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRSACapability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_sha.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib SHA Hash Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"sha.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/sha.h\"\n#endif /* Compiler-specific includes */\n\n#define HASH_STATE_SIZE\t\tsizeof( SHA_CTX )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSHA Self-test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the SHA output against the test vectors given in FIPS 180-1.  Since\n   hashing an empty string is a valid operation, we have to provide an \n   explicit isValid flag to tell the code when to stop.  We skip the third \n   test since this can take several seconds to execute on slower processors, \n   which leads to an unacceptable delay */\n\nstatic const struct {\n\tconst char *data;\t\t\t\t\t\t/* Data to hash */\n\tconst int length;\t\t\t\t\t\t/* Length of data */\n\tconst BOOLEAN isValid;\t\t\t\t\t/* Whether entry is valid */\n\tconst BYTE digest[ SHA_DIGEST_LENGTH ];\t/* Digest of data */\n\t} digestValues[] = {\n\t{ NULL, 0, TRUE,\n\t  { 0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D, \n\t\t0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90, \n\t\t0xAF, 0xD8, 0x07, 0x09 } },\n\t{ \"abc\", 3, TRUE,\n\t  { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A,\n\t\t0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C,\n\t\t0x9C, 0xD0, 0xD8, 0x9D } },\n\t{ \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\", 56, TRUE,\n\t  { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,\n\t\t0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,\n\t\t0xE5, 0x46, 0x70, 0xF1 } },\n/*\t{ \"aaaaa...\", 1000000L, TRUE,\n\t  { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4,\n\t\t0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31,\n\t\t0x65, 0x34, 0x01, 0x6F } }, */\n\t{ NULL, 0, FALSE, { 0 } }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getSHA1Capability();\n\ttypedef BYTE HASH_STATE[ HASH_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( HASH_STATE_STORAGE, HASH_STATE );\n\tHASH_STATE_STORAGE hashStateStorage;\n\tHASH_STATE *hashStatePtr = ALIGN_STRUCT( &hashStateStorage, HASH_STATE, 8 ); \n\tint i, status, LOOP_ITERATOR;\n\n\t/* Test SHA-1 against values given in FIPS 180-1 */\n\tmemset( hashStatePtr, 0, HASH_STATE_SIZE );\t/* Keep static analysers happy */\n\tLOOP_SMALL( i = 0, digestValues[ i ].isValid, i++ )\n\t\t{\n\t\tstatus = testHash( capabilityInfo, 0, hashStatePtr, digestValues[ i ].data, \n\t\t\t\t\t\t   digestValues[ i ].length, digestValues[ i ].digest );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = HASH_STATE_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSHA Hash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash data using SHA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hash( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int noBytes )\n\t{\n\tSHA_CTX *shaInfo = ( SHA_CTX * ) contextInfoPtr->ctxHash->hashInfo;\n#ifdef HAS_DEVCRYPTO\n\tconst int hwCryptInfo = getSysVar( SYSVAR_HWCRYPT );\n#endif /* HAS_DEVCRYPTO */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( noBytes == 0 || isReadPtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( noBytes ) );\n\n\t/* If there's crypto hardware available, try and use that */\n#ifdef HAS_DEVCRYPTO\n\tif( !cryptStatusError( hwCryptInfo ) && \\\n\t\t( hwCryptInfo & HWCRYPT_FLAG_CRYPTDEV_SHA1 ) )\n\t\t{\n\t\tint status = CRYPT_OK;\n\n\t\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\tstatus = hwCryptoInit( contextInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( hwCryptoHash( contextInfoPtr, buffer, noBytes ) );\n\t\t}\n#endif /* HAS_DEVCRYPTO */\n\n\t/* If the hash state was reset to allow another round of hashing,\n\t   reinitialise things */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\tSHA1_Init( shaInfo );\n\n\tif( noBytes > 0 )\n\t\t{\n\t\tSHA1_Update( shaInfo, buffer, noBytes );\n\t\t}\n\telse\n\t\tSHA1_Final( contextInfoPtr->ctxHash->hash, shaInfo );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Internal API: Hash a single block of memory without the overhead of\n   creating an encryption context.  This always uses SHA1 */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid shaHashBuffer( INOUT_OPT HASHINFO hashInfo,\n\t\t\t\t\tOUT_BUFFER_OPT_C( outBufMaxLength, 20 ) BYTE *outBuffer,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\tIN_BUFFER_OPT( inLength ) const void *inBuffer,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\tIN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState )\n\t{\n\tSHA_CTX *shaInfo = ( SHA_CTX * ) hashInfo;\n\n\tassert( isWritePtr( hashInfo, sizeof( HASHINFO ) ) );\n\tassert( ( hashState != HASH_STATE_END && \\\n\t\t\t  outBuffer == NULL && outBufMaxLength == 0 ) || \\\n\t\t\t( hashState == HASH_STATE_END && \\\n\t\t\t  isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\t  outBufMaxLength >= 20 ) );\n\tassert( inBuffer == NULL || isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( ( hashState == HASH_STATE_END && outBufMaxLength < 20 ) || \\\n\t\t( hashState != HASH_STATE_END && inLength <= 0 ) )\n\t\tretIntError_Void();\n\n\tswitch( hashState )\n\t\t{\n\t\tcase HASH_STATE_START:\n\t\t\tSHA1_Init( shaInfo );\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase HASH_STATE_CONTINUE:\n\t\t\tSHA1_Update( shaInfo, ( BYTE * ) inBuffer, inLength );\n\t\t\tbreak;\n\n\t\tcase HASH_STATE_END:\n\t\t\tif( inBuffer != NULL )\n\t\t\t\tSHA1_Update( shaInfo, ( BYTE * ) inBuffer, inLength );\n\t\t\tSHA1_Final( outBuffer, shaInfo );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid shaHashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 20 ) BYTE *outBuffer,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 20 ) const int outBufMaxLength,\n\t\t\t\t\t\t  IN_BUFFER( inLength ) const void *inBuffer,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int inLength )\n\t{\n\tSHA_CTX shaInfo;\n\n\tassert( isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\toutBufMaxLength >= 20 );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( outBufMaxLength < 20 || inLength <= 0 )\n\t\tretIntError_Void();\n\n\tSHA1_Init( &shaInfo );\n\tSHA1_Update( &shaInfo, ( BYTE * ) inBuffer, inLength );\n\tSHA1_Final( outBuffer, &shaInfo );\n\tzeroise( &shaInfo, sizeof( SHA_CTX ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_SHA1, bitsToBytes( 160 ), \"SHA-1\", 5,\n\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\tselfTest, getInfo, NULL, NULL, NULL, NULL, hash, hash\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getSHA1Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/ctx_sha2.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib SHA2 Hash Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"sha2.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"crypt/sha2.h\"\n#endif /* Compiler-specific includes */\n\n#define HASH_STATE_SIZE\t\tsizeof( sha2_ctx )\n\n#if defined( USE_SHA2_EXT ) && !defined( SHA512_DIGEST_SIZE )\n  #error SHA2-384/512 can only be used on a system with 64-bit data type support\n#endif /* Extended SHA-2 variants on system without 64-bit data type */\n\n#ifndef SHA384_DIGEST_SIZE\n  /* These may not be defined on non 64-bit systems */\n  #define SHA384_DIGEST_SIZE\t\t\t48\n  #define SHA512_DIGEST_SIZE\t\t\t64\n  #define sha2_begin( size, ctx )\t\tsha256_begin( ( ctx )->uu->ctx256 )\n  #define sha2_hash( data, len, ctx )\tsha256_hash( data, len, ( ctx )->uu->ctx256 )\n  #define sha2_end( hash, ctx )\t\t\tsha256_end( hash, ( ctx )->uu->ctx256 )\n#endif /* SHA384_DIGEST_SIZE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSHA2 Self-test Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test the SHA output against the test vectors given in FIPS 180-2.  Since\n   hashing an empty string is a valid operation, we have to provide an \n   explicit isValid flag to tell the code when to stop.  We skip the third \n   test since this can take several seconds to execute on slower processors, \n   which leads to an unacceptable delay */\n\nstatic const struct {\n\tconst char *data;\t\t\t\t\t\t/* Data to hash */\n\tconst int length;\t\t\t\t\t\t/* Length of data */\n\tconst BOOLEAN isValid;\t\t\t\t\t/* Whether entry is valid */\n\tconst BYTE dig256[ SHA256_DIGEST_SIZE ];/* Digest of data */\n\tconst BYTE dig384[ SHA384_DIGEST_SIZE ];/* Digest of data */\n\tconst BYTE dig512[ SHA512_DIGEST_SIZE ];/* Digest of data */\n\t} digestValues[] = {\n\t{ NULL, 0, TRUE,\n\t  { 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, \n\t\t0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, \n\t\t0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, \n\t\t0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55 },\n\t  { 0x38, 0xB0, 0x60, 0xA7, 0x51, 0xAC, 0x96, 0x38, \n\t\t0x4C, 0xD9, 0x32, 0x7E, 0xB1, 0xB1, 0xE3, 0x6A, \n\t\t0x21, 0xFD, 0xB7, 0x11, 0x14, 0xBE, 0x07, 0x43, \n\t\t0x4C, 0x0C, 0xC7, 0xBF, 0x63, 0xF6, 0xE1, 0xDA, \n\t\t0x27, 0x4E, 0xDE, 0xBF, 0xE7, 0x6F, 0x65, 0xFB, \n\t\t0xD5, 0x1A, 0xD2, 0xF1, 0x48, 0x98, 0xB9, 0x5B },\n\t  { 0xCF, 0x83, 0xE1, 0x35, 0x7E, 0xEF, 0xB8, 0xBD, \n\t\t0xF1, 0x54, 0x28, 0x50, 0xD6, 0x6D, 0x80, 0x07, \n\t\t0xD6, 0x20, 0xE4, 0x05, 0x0B, 0x57, 0x15, 0xDC, \n\t\t0x83, 0xF4, 0xA9, 0x21, 0xD3, 0x6C, 0xE9, 0xCE, \n\t\t0x47, 0xD0, 0xD1, 0x3C, 0x5D, 0x85, 0xF2, 0xB0, \n\t\t0xFF, 0x83, 0x18, 0xD2, 0x87, 0x7E, 0xEC, 0x2F, \n\t\t0x63, 0xB9, 0x31, 0xBD, 0x47, 0x41, 0x7A, 0x81, \n\t\t0xA5, 0x38, 0x32, 0x7A, 0xF9, 0x27, 0xDA, 0x3E } \n\t  },\n\t{ \"abc\", 3, TRUE,\n\t  { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,\n\t    0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,\n\t\t0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,\n\t\t0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },\n\t  {\t0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,\n\t\t0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,\n\t\t0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,\n\t\t0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,\n\t\t0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,\n\t\t0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 },\n\t  {\t0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,\n\t\t0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,\n\t\t0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,\n\t\t0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,\n\t\t0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,\n\t\t0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,\n\t\t0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,\n\t\t0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }\n\t\t},\n\t{ \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\", 56, TRUE,\n\t  {\t0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,\n\t    0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,\n\t\t0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,\n\t\t0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },\n\t  { 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39,\n\t\t0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39,\n\t\t0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab,\n\t\t0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6,\n\t\t0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f,\n\t\t0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b },\n\t  {\t0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a,\n\t\t0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16,\n\t\t0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8,\n\t\t0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35,\n\t\t0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9,\n\t\t0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0,\n\t\t0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03,\n\t\t0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45 }\n\t\t},\n#if 0\n\t{ \"aaaaa...\", 1000000L, TRUE,\n\t  {\t0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,\n\t    0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,\n\t\t0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,\n\t\t0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 },\n\t  {\t0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb,\n\t\t0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c,\n\t\t0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52,\n\t\t0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b,\n\t\t0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb,\n\t\t0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85 },\n\t  {\t0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,\n\t\t0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,\n\t\t0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,\n\t\t0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,\n\t\t0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,\n\t\t0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,\n\t\t0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,\n\t\t0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b } }\n#endif\n\t{ NULL, 0, FALSE, { 0 }, { 0 }, { 0 } },\n\t\t{ NULL, 0, FALSE, { 0 }, { 0 }, { 0 } }\n\t};\n\nCHECK_RETVAL \\\nstatic int selfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo = getSHA2Capability();\n\ttypedef BYTE HASH_STATE[ HASH_STATE_SIZE + 8 ];\n\tDECLARE_ALIGN_STRUCT( HASH_STATE_STORAGE, HASH_STATE );\n\tHASH_STATE_STORAGE hashStateStorage;\n\tHASH_STATE *hashStatePtr = ALIGN_STRUCT( &hashStateStorage, HASH_STATE, 8 );\n\tint i, status, LOOP_ITERATOR;\n\n\t/* SHA-2 requires the largest amount of context state so we check to\n\t   make sure that the HASHINFO is large enough.  Unfortunately the\n\t   terminology is a bit confusing here, HASHINFO is an opaque memory\n\t   block used to contain the low-level hash algorithm state, HASH_INFO\n\t   is the high-level hash info held inside a CONTEXT_INFO */\n\tassert( sizeof( HASHINFO ) >= HASH_STATE_SIZE );\n\n\tmemset( hashStatePtr, 0, HASH_STATE_SIZE );\t/* Keep static analysers happy */\n\tLOOP_SMALL( i = 0, digestValues[ i ].isValid, i++ )\n\t\t{\n\t\tstatus = testHash( capabilityInfo, SHA256_DIGEST_SIZE, hashStatePtr, \n\t\t\t\t\t\t   digestValues[ i ].data, digestValues[ i ].length, \n\t\t\t\t\t\t   digestValues[ i ].dig256 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#ifdef USE_SHA2_EXT\n\t\tstatus = testHash( capabilityInfo, SHA384_DIGEST_SIZE, hashStatePtr, \n\t\t\t\t\t\t   digestValues[ i ].data, digestValues[ i ].length, \n\t\t\t\t\t\t   digestValues[ i ].dig384 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = testHash( capabilityInfo, SHA512_DIGEST_SIZE, hashStatePtr, \n\t\t\t\t\t\t   digestValues[ i ].data, digestValues[ i ].length, \n\t\t\t\t\t\t   digestValues[ i ].dig512 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#endif /* USE_SHA2_EXT */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\t#define selfTest\tNULL\n#endif /* !CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tControl Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return context subtype-specific information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length )\n\t{\n\tassert( contextInfoPtr == NULL || \\\n\t\t\tisWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \\\n\t\t\t( length > 0 && isWritePtrDynamic( data, length ) ) );\n\n\tREQUIRES( isEnumRange( type, CAPABILITY_INFO ) );\n\tREQUIRES( ( contextInfoPtr == NULL ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = HASH_STATE_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSHA Hash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash data using SHA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hash( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t IN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int noBytes )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tsha2_ctx *shaInfo = ( sha2_ctx * ) contextInfoPtr->ctxHash->hashInfo;\n#ifdef HAS_DEVCRYPTO\n\tconst int hwCryptInfo = getSysVar( SYSVAR_HWCRYPT );\n#endif /* HAS_DEVCRYPTO */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( noBytes == 0 || isReadPtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isIntegerRange( noBytes ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If there's crypto hardware available, try and use that */\n#ifdef HAS_DEVCRYPTO\n\tif( !cryptStatusError( hwCryptInfo ) && \\\n\t\t( hwCryptInfo & HWCRYPT_FLAG_CRYPTDEV_SHA2 ) && \\\n\t\tcapabilityInfoPtr->blockSize == bitsToBytes( 256 ) )\n\t\t{\n\t\tint status = CRYPT_OK;\n\n\t\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t\tstatus = hwCryptoInit( contextInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( hwCryptoHash( contextInfoPtr, buffer, noBytes ) );\n\t\t}\n#endif /* HAS_DEVCRYPTO */\n\n\t/* If the hash state was reset to allow another round of hashing,\n\t   reinitialise things */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\tsha2_begin( capabilityInfoPtr->blockSize, shaInfo );\n\n\tif( noBytes > 0 )\n\t\t{\n\t\tsha2_hash( buffer, noBytes, shaInfo );\n\t\t}\n\telse\n\t\t{\n\t\tsha2_end( contextInfoPtr->ctxHash->hash, shaInfo );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Internal API: Hash a single block of memory without the overhead of\n   creating an encryption context.*/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sha2HashBuffer( INOUT_OPT HASHINFO hashInfo,\n\t\t\t\t\t OUT_BUFFER_OPT_C( outBufMaxLength, 32 ) BYTE *outBuffer,\n\t\t\t\t\t IN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\t IN_BUFFER_OPT( inLength ) const void *inBuffer,\n\t\t\t\t\t IN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\t IN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState )\n\t{\n\tsha2_ctx *shaInfo = ( sha2_ctx * ) hashInfo;\n\t\n\tassert( sizeof( HASHINFO ) >= HASH_STATE_SIZE );\n\tassert( isWritePtr( hashInfo, sizeof( HASHINFO ) ) );\n\tassert( ( hashState != HASH_STATE_END && \\\n\t\t\t  outBuffer == NULL && outBufMaxLength == 0 ) || \\\n\t\t\t( hashState == HASH_STATE_END && \\\n\t\t\t  isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\t  outBufMaxLength >= 32 ) );\n\tassert( inBuffer == NULL || isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( ( hashState == HASH_STATE_END && outBufMaxLength < 32 ) || \\\n\t\t( hashState != HASH_STATE_END && inLength <= 0 ) )\n\t\tretIntError_Void();\n\n\tswitch( hashState )\n\t\t{\n\t\tcase HASH_STATE_START:\n\t\t\tsha2_begin( SHA256_DIGEST_SIZE, shaInfo );\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase HASH_STATE_CONTINUE:\n\t\t\tsha2_hash( ( BYTE * ) inBuffer, inLength, shaInfo );\n\t\t\tbreak;\n\n\t\tcase HASH_STATE_END:\n\t\t\tif( inBuffer != NULL )\n\t\t\t\tsha2_hash( ( BYTE * ) inBuffer, inLength, shaInfo );\n\t\t\tsha2_end( outBuffer, shaInfo );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid sha2HashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 32 ) BYTE *outBuffer,\n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int outBufMaxLength,\n\t\t\t\t\t\t   IN_BUFFER( inLength ) const void *inBuffer,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int inLength )\n\t{\n\tsha2_ctx shaInfo;\n\n\tassert( isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\toutBufMaxLength >= 32 );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( outBufMaxLength < 32 || inLength <= 0 )\n\t\tretIntError_Void();\n\n\tsha2_begin( SHA256_DIGEST_SIZE, &shaInfo );\n\tsha2_hash( ( BYTE * ) inBuffer, inLength, &shaInfo );\n\tsha2_end( outBuffer, &shaInfo );\n\tzeroise( &shaInfo, sizeof( sha2_ctx ) );\n\t}\n\n#ifdef USE_SHA2_EXT\n\n#if defined( CONFIG_SUITEB )\n  #define SHA2EXT_DIGEST_SIZE\tSHA384_DIGEST_SIZE\n#else\n  #define SHA2EXT_DIGEST_SIZE\tSHA512_DIGEST_SIZE\n#endif /* Suite B vs. generic use */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sha2_ExtHashBuffer( INOUT_OPT HASHINFO hashInfo, \n\t\t\t\t\t\t OUT_BUFFER_OPT_C( outBufMaxLength, 64 ) BYTE *outBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int outBufMaxLength,\n\t\t\t\t\t\t IN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int inLength,\n\t\t\t\t\t\t IN_ENUM( HASH_STATE ) const HASH_STATE_TYPE hashState )\n\t{\n\tsha2_ctx *shaInfo = ( sha2_ctx * ) hashInfo;\n\n\tassert( sizeof( HASHINFO ) >= HASH_STATE_SIZE );\n\tassert( isWritePtr( hashInfo, sizeof( HASHINFO ) ) );\n\tassert( ( hashState != HASH_STATE_END && \\\n\t\t\t  outBuffer == NULL && outBufMaxLength == 0 ) || \\\n\t\t\t( hashState == HASH_STATE_END && \\\n\t\t\t  isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\t  outBufMaxLength >= SHA2EXT_DIGEST_SIZE ) );\n\tassert( inBuffer == NULL || isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( ( hashState == HASH_STATE_END && \\\n\t\t  outBufMaxLength < SHA2EXT_DIGEST_SIZE ) || \\\n\t\t( hashState != HASH_STATE_END && inLength <= 0 ) )\n\t\tretIntError_Void();\n\n\tswitch( hashState )\n\t\t{\n\t\tcase HASH_STATE_START:\n\t\t\tif( sha2_begin( SHA2EXT_DIGEST_SIZE, shaInfo ) != EXIT_SUCCESS )\n\t\t\t\tretIntError_Void()\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase HASH_STATE_CONTINUE:\n\t\t\tsha2_hash( ( BYTE * ) inBuffer, inLength, shaInfo );\n\t\t\tbreak;\n\n\t\tcase HASH_STATE_END:\n\t\t\tif( inBuffer != NULL )\n\t\t\t\tsha2_hash( ( BYTE * ) inBuffer, inLength, shaInfo );\n\t\t\tsha2_end( outBuffer, shaInfo );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid sha2_ExtHashBufferAtomic( OUT_BUFFER_C( outBufMaxLength, 64 ) BYTE *outBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 64 ) const int outBufMaxLength,\n\t\t\t\t\t\t\t   IN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int inLength )\n\t{\n\tsha2_ctx shaInfo;\n\n\tassert( isWritePtrDynamic( outBuffer, outBufMaxLength ) && \\\n\t\t\toutBufMaxLength >= 64 );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\n\tif( outBufMaxLength < 64 || inLength <= 0 )\n\t\tretIntError_Void();\n\n\tif( sha2_begin( SHA2EXT_DIGEST_SIZE, &shaInfo ) != EXIT_SUCCESS )\n\t\t{\n\t\tmemset( outBuffer, 0, outBufMaxLength );\n\t\tretIntError_Void();\n\t\t}\n\tsha2_hash( ( BYTE * ) inBuffer, inLength, &shaInfo );\n\tsha2_end( outBuffer, &shaInfo );\n\tzeroise( &shaInfo, sizeof( sha2_ctx ) );\n\t}\n#endif /* USE_SHA2_EXT */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSHA2 Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise algorithm parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initParams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,\n\t\t\t\t\t   IN_OPT const void *data, \n\t\t\t\t\t   IN_INT const int dataLength )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( contextInfoPtr->type == CONTEXT_HASH );\n\tREQUIRES( isEnumRange( paramType, KEYPARAM ) );\n\n\t/* SHA-2 has a variable-length output, selectable by setting the \n\t   blocksize attribute */\n\tif( paramType == KEYPARAM_BLOCKSIZE )\n\t\t{\n#ifdef USE_SHA2_EXT\n\t\tstatic const CAPABILITY_INFO capabilityInfoSHA384 = {\n\t\t\t\tCRYPT_ALGO_SHA2, bitsToBytes( 384 ), \"SHA-384\", 7,\n\t\t\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\t\t\t\tselfTest, getInfo, NULL, NULL, NULL, NULL, hash, hash\n\t\t\t\t};\n\t\tstatic const CAPABILITY_INFO capabilityInfoSHA512 = {\n\t\t\t\tCRYPT_ALGO_SHA2, bitsToBytes( 512 ), \"SHA-512\", 7,\n\t\t\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\t\t\t\tselfTest, getInfo, NULL, NULL, NULL, NULL, hash, hash\n\t\t\t\t};\n#endif /* USE_SHA2_EXT */\n\n#ifdef USE_SHA2_EXT\n\t\t/* Switch to the appropriate variant of SHA-2.  Note that the \n\t\t   initParamsFunction pointer for this version is NULL rather than\n\t\t   pointing to this function, so once the output size has been set \n\t\t   it can't be changed again */\n\t\tswitch( dataLength )\n\t\t\t{\n\t\t\tcase SHA256_DIGEST_SIZE:\n\t\t\t\t/* The default SHA-2 variant is SHA-256, so an attempt to \n\t\t\t\t   set this size is a no-op */\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\tcase SHA384_DIGEST_SIZE:\n\t\t\t\tDATAPTR_SET( contextInfoPtr->capabilityInfo, \n\t\t\t\t\t\t\t ( void * ) &capabilityInfoSHA384 );\n\t\t\t\tbreak;\n\n\t\t\tcase SHA512_DIGEST_SIZE:\n\t\t\t\tDATAPTR_SET( contextInfoPtr->capabilityInfo, \n\t\t\t\t\t\t\t ( void * ) &capabilityInfoSHA512 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n#else\n\t\t/* The default SHA-2 variant is SHA-256, so an attempt to set this \n\t\t   size is a no-op */\n\t\treturn( ( dataLength == SHA256_DIGEST_SIZE ) ? \\\n\t\t\t\tCRYPT_OK : CRYPT_ARGERROR_NUM1 );\n#endif /* USE_SHA2_EXT */\n\t\t}\n\n\t/* Pass the call on down to the global parameter-handling function */\t\n\treturn( initGenericParams( contextInfoPtr, paramType, data, \n\t\t\t\t\t\t\t   dataLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCapability Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CAPABILITY_INFO capabilityInfo = {\n\tCRYPT_ALGO_SHA2, bitsToBytes( 256 ), \"SHA-2\", 5,\n\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\tselfTest, getInfo, NULL, initParams, NULL, NULL, hash, hash\n\t};\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getSHA2Capability( void )\n\t{\n\treturn( &capabilityInfo );\n\t}\n"
  },
  {
    "path": "deps/cl345/context/key_id.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPublic-key ID Generation Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"context.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_INT_ASN1 ) && defined( USE_PKC )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate a keyID from an encoded SubjectPublicKeyInfo record */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int calculateFlatKeyID( IN_BUFFER( keyInfoSize ) const void *keyInfo,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) const int keyInfoSize,\n\t\t\t\t\t\t\t   OUT_BUFFER_FIXED( keyIdMaxLen ) BYTE *keyID,\n\t\t\t\t\t\t\t   IN_LENGTH_FIXED( KEYID_SIZE ) const int keyIdMaxLen )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\n\tassert( isReadPtrDynamic( keyInfo, keyInfoSize ) );\n\tassert( isWritePtrDynamic( keyID, keyIdMaxLen ) );\n\n\tREQUIRES( keyInfoSize >= 16 && keyInfoSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( keyIdMaxLen == KEYID_SIZE );\n\n\t/* Hash the key info to get the key ID */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\thashFunctionAtomic( keyID, keyIdMaxLen, keyInfo, keyInfoSize );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tKeyID-from-Encoded-Data Calculation Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_DEVICES\n\n/* Instantiate static context data from raw encoded public-key data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int initStaticContext( OUT CONTEXT_INFO *staticContextInfo,\n\t\t\t\t\t\t\t  OUT PKC_INFO *contextData,\n\t\t\t\t\t\t\t  const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t  IN_BUFFER( publicKeyDataLength ) \\\n\t\t\t\t\t\t\t  const void *publicKeyData,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t  const int publicKeyDataLength )\n\t{\n\tPKC_READKEY_FUNCTION readPublicKeyFunction;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( staticContextInfo, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( contextData, sizeof( PKC_INFO ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isReadPtrDynamic( publicKeyData, publicKeyDataLength ) );\n\n\tREQUIRES( ( isEccAlgo( capabilityInfoPtr->cryptAlgo ) && \\\n\t\t\t\tpublicKeyDataLength >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t\tpublicKeyDataLength < MAX_INTLENGTH_SHORT ) || \\\n\t\t\t  ( !isEccAlgo( capabilityInfoPtr->cryptAlgo ) && \\\n\t\t\t\tpublicKeyDataLength >= MIN_PKCSIZE && \\\n\t\t\t\tpublicKeyDataLength < MAX_INTLENGTH_SHORT ) );\n\n\t/* Clear return values */\n\tmemset( staticContextInfo, 0, sizeof( CONTEXT_INFO ) );\n\tmemset( contextData, 0, sizeof( PKC_INFO ) );\n\n\t/* Initialise a static context to read the key data into */\n\tstatus = staticInitContext( staticContextInfo, CONTEXT_PKC,\n\t\t\t\t\t\t\t\tcapabilityInfoPtr, contextData,\n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treadPublicKeyFunction = ( PKC_READKEY_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( contextData->readPublicKeyFunction );\n\tENSURES( readPublicKeyFunction != NULL );\n\n\t/* Read the key data into the static context and calculate the keyIDs.\n\t   We can do this now that the data is in a native context rather than\n\t   being present only in raw encoded form */\n\tsMemConnect( &stream, publicKeyData, publicKeyDataLength );\n\tstatus = readPublicKeyFunction( &stream, staticContextInfo,\n\t\t\t\t\t\t\t\t\tKEYFORMAT_CERT, 0 );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tSET_FLAG( staticContextInfo->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\tstatus = capabilityInfoPtr->initKeyFunction( staticContextInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t\t NULL, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( staticContextInfo );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Calculate a keyID when the only key data present is a raw encoded\n   SubjectPublicKeyInfo record.  This is a bit more complicated than the \n   standard keyID calculation because while the hash-of-SPKI form is rather\n   easier to calculate, the other oddball forms aren't since they first \n   require breaking down the SPKI into its components and then re-encoding \n   them in the various ways that we need to calculate the other forms of \n   keyID */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int calculateKeyIDFromEncoded( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCONTEXT_INFO staticContextInfo;\\\n\tPKC_INFO staticContextData, *publicKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = NULL;\n\tconst BOOLEAN isPgpAlgo = \\\n\t\t( cryptAlgo == CRYPT_ALGO_RSA || cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t  cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\n\t/* Calculate the keyID for the pre-encoded key data */\n\tstatus = calculateFlatKeyID( publicKey->publicKeyInfo, \n\t\t\t\t\t\t\t\t publicKey->publicKeyInfoSize, \n\t\t\t\t\t\t\t\t publicKey->keyID, KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* At this point we're (technically) done, however a few special-case\n\t   situations require further processing.  These are explained in the\n\t   code blocks that handle them below */\n\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\tCONTEXT_FLAG_DUMMY ) && !isPgpAlgo )\n\t\treturn( CRYPT_OK );\n\n\t/* If the keys are held externally (e.g. in a crypto device) then \n\t   there's no way to tell what the nominal keysize for the context \n\t   should be.  In order to determine this we have to parse the key\n\t   data in order to extract the specific component that defines the\n\t   key's nominal length.\n\n\t   PGP keyIDs present a similar problem because we would in theory \n\t   need to decode the flattened key data and then re-encode it in the \n\t   format needed to generate the PGP IDs. \n\t   \n\t   While it would be possible to do this with a lot of customised \n\t   duplication of code from other parts of key_rd.c and from key_wr.c \n\t   it's easier to just create a static public-key context from the \n\t   encoded key data and let the standard key-read code take care of it.  \n\t   On the downside, it requires creation of a static (if not a full) \n\t   public-key context just for this purpose */\n\tswitch( cryptAlgo )\n\t\t{\n#ifdef USE_DH\n\t\tcase CRYPT_ALGO_DH:\n\t\t\tcapabilityInfoPtr = getDHCapability();\n\t\t\tbreak;\n#endif /* USE_DH */\n\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tcapabilityInfoPtr = getRSACapability();\n\t\t\tbreak;\n\n#ifdef USE_DSA\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tcapabilityInfoPtr = getDSACapability();\n\t\t\tbreak;\n#endif /* USE_DSA */\n\n#ifdef USE_ELGAMAL\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tcapabilityInfoPtr = getElgamalCapability();\n\t\t\tbreak;\n#endif /* USE_ELGAMAL */\n\n#ifdef USE_ECDSA\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tcapabilityInfoPtr = getECDSACapability();\n\t\t\tbreak;\n#endif /* USE_ECDSA */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tENSURES( capabilityInfoPtr != NULL );\n\tstatus = initStaticContext( &staticContextInfo, &staticContextData, \n\t\t\t\t\t\t\t\tcapabilityInfoPtr, publicKey->publicKeyInfo, \n\t\t\t\t\t\t\t\tpublicKey->publicKeyInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a non-native context, explicitly set the key size.  For \n\t   native contexts this is done by the init-key function but for non-\n\t   native contexts this function is never called since there are no key \n\t   components present to initialise.  Because of this we have to \n\t   explicitly copy the key size information from the static native \n\t   context that we've created */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\tcontextInfoPtr->ctxPKC->keySizeBits = staticContextData.keySizeBits;\n\n\t/* If it's a PGP algorithm, copy across any relevant PGP keyIDs */\n\tif( isPgpAlgo )\n\t\t{\n\t\tif( TEST_FLAG( staticContextData.flags, \n\t\t\t\t\t   PKCINFO_FLAG_PGPKEYID_SET ) )\n\t\t\t{\n\t\t\tmemcpy( publicKey->pgp2KeyID, staticContextData.pgp2KeyID, \n\t\t\t\t\tPGP_KEYID_SIZE );\n\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t  PKCINFO_FLAG_PGPKEYID_SET );\n\t\t\t}\n\t\tif( TEST_FLAG( staticContextData.flags, \n\t\t\t\t\t   PKCINFO_FLAG_OPENPGPKEYID_SET ) )\n\t\t\t{\n\t\t\tmemcpy( publicKey->openPgpKeyID, staticContextData.openPgpKeyID, \n\t\t\t\t\tPGP_KEYID_SIZE );\n\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t  PKCINFO_FLAG_OPENPGPKEYID_SET );\n\t\t\t}\n\t\t}\n\tstaticDestroyContext( &staticContextInfo );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DEVICES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyID Calculation Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a PGP keyID */\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int calculateOpenPGPKeyID( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tPKC_INFO *publicKey = contextInfoPtr->ctxPKC;\n\tconst PKC_WRITEKEY_FUNCTION writePublicKeyFunction = \\\n\t\t\t\t\t\t( PKC_WRITEKEY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( publicKey->writePublicKeyFunction );\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tSTREAM stream;\n\tBYTE buffer[ ( CRYPT_MAX_PKCSIZE * 4 ) + 50 + 8 ];\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ], packetHeader[ 64 + 8 ];\n\tint hashSize, length, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( writePublicKeyFunction != NULL );\n\n\t/* Generate an OpenPGP key ID.  Note that the creation date isn't \n\t   necessarily present if the key came from a non-PGP source, in which \n\t   case the date will have a value of zero.  This leads to problems \n\t   because PGP hashes the creation date into the key ID, which means\n\t   that mixing keys from PGP and non-PGP sources leads to them being\n\t   identified with different IDs even though they're the same key.\n\n\t   There's no easy fix for this, the best that we can do is leave the \n\t   date as an all-zero value, which at least produces a constant ID:\n\n\t\tbyte\t\tctb = 0x99\n\t\tbyte[2]\t\tlength\n\t\t-- Key data --\n\t\tbyte\t\tversion = 4\n\t\tbyte[4]\t\tkey generation time \n\t\tbyte\t\talgorithm\n\t\tbyte[]\t\tkey data */\n\tsMemOpen( &stream, buffer, ( CRYPT_MAX_PKCSIZE * 4 ) + 50 );\n\tstatus = writePublicKeyFunction( &stream, contextInfoPtr, KEYFORMAT_PGP, \n\t\t\t\t\t\t\t\t\t \"public_key\", 10 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\tlength = stell( &stream );\n\tpacketHeader[ 0 ] = 0x99;\n\tpacketHeader[ 1 ] = intToByte( ( length >> 8 ) & 0xFF );\n\tpacketHeader[ 2 ] = intToByte( length & 0xFF );\n\n\t/* Hash the data needed to generate the OpenPGP keyID */\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, &hashSize );\n\thashFunction( hashInfo, NULL, 0, packetHeader, 1 + 2, \n\t\t\t\t  HASH_STATE_START );\n\thashFunction( hashInfo, hash, CRYPT_MAX_HASHSIZE, buffer, length, \n\t\t\t\t  HASH_STATE_END );\n\tmemcpy( publicKey->openPgpKeyID, hash + hashSize - PGP_KEYID_SIZE, \n\t\t\tPGP_KEYID_SIZE );\n\tsMemClose( &stream );\n\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t  PKCINFO_FLAG_OPENPGPKEYID_SET );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP || USE_PGPKEYS */\n\n/* Generate a keyID for a PKCS #3 key, which differs slightly from the \n   FIPS 186/X9.42 standard format in that there's no q value present, so we\n   have to write a dummy zero value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writePKCS3Key( INOUT STREAM *stream, \n\t\t\t\t\t\t  const PKC_INFO *dlpKey,\n\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tconst DH_DOMAINPARAMS *domainParams = dlpKey->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &dlpKey->dlpParam_p;\n\tconst BIGNUM *g = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->g : &dlpKey->dlpParam_g;\n\tconst int parameterSize = sizeofShortObject( \\\n\t\t\t\t\t\t\t\t\t\t\tsizeofBignum( p ) + \\\n\t\t\t\t\t\t\t\t\t\t\t3 +\t\t/* INTEGER value 0 */\n\t\t\t\t\t\t\t\t\t\t\tsizeofBignum( g ) );\n\tconst int componentSize = sizeofBignum( &dlpKey->dlpParam_y );\n\tint totalSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( dlpKey, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( dlpKey ) );\n\tREQUIRES( isDlpAlgo( cryptAlgo ) );\n\n\t/* Implement a cut-down version of writeDlpSubjectPublicKey(), writing a \n\t   zero value for q */\n\ttotalSize = sizeofAlgoIDparam( cryptAlgo, parameterSize ) + \\\n\t\t\t\tsizeofShortObject( componentSize + 1 );\n\twriteSequence( stream, totalSize );\n\twriteAlgoIDparam( stream, cryptAlgo, parameterSize );\n\twriteBignum( stream, p );\n\tswrite( stream, \"\\x02\\x01\\x00\", 3 );\t/* Integer value 0 */\n\twriteBignum( stream, g );\n\twriteBitStringHole( stream, componentSize, DEFAULT_TAG );\n\treturn( writeBignum( stream, &dlpKey->dlpParam_y ) );\n\t}\n\n/* Generate an X.509 key ID, which is the SHA-1 hash of the \n   SubjectPublicKeyInfo.  There are about half a dozen incompatible ways of \n   generating X.509 keyIdentifiers, the following is conformant with the \n   PKIX specification (\"use whatever you like as long as it's unique\") but \n   differs slightly from one common method that hashes the SubjectPublicKey \n   without the BIT STRING encapsulation.  The problem with that method is \n   that some DLP-based algorithms use a single integer as the \n   SubjectPublicKey, leading to potential key ID clashes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int calculateKeyID( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *publicKey = contextInfoPtr->ctxPKC;\n\tconst PKC_WRITEKEY_FUNCTION writePublicKeyFunction = \\\n\t\t\t\t\t\t( PKC_WRITEKEY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( publicKey->writePublicKeyFunction );\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tSTREAM stream;\n\tBYTE buffer[ ( CRYPT_MAX_PKCSIZE * 4 ) + 50 + 8 ];\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES( writePublicKeyFunction != NULL );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\t/* If the public key info is present in pre-encoded form, calculate the\n\t   key ID directly from that */\n\tif( publicKey->publicKeyInfo != NULL )\n\t\t{\n#ifdef USE_DEVICES\n\t\treturn( calculateKeyIDFromEncoded( contextInfoPtr, cryptAlgo ) );\n#else\n\t\tretIntError();\n#endif /* USE_DEVICES */\n\t\t}\n\n\t/* Write the public key fields to a buffer and hash them to get the key\n\t   ID */\n\tsMemOpen( &stream, buffer, ( CRYPT_MAX_PKCSIZE * 4 ) + 50 );\n\tif( isDlpAlgo( cryptAlgo ) && BN_is_zero( &publicKey->dlpParam_q ) )\n\t\t{\n\t\t/* OpenPGP Elgamal keys and SSL/SSH DH keys don't have a q \n\t\t   parameter, which makes it impossible to write them in the X.509 \n\t\t   format.  If this situation occurs we write them in a cut-down\n\t\t   version of the format, which is OK because the X.509 keyIDs are \n\t\t   explicit and not implicitly generated from the key data like \n\t\t   OpenPGP one */\n\t\tstatus = writePKCS3Key( &stream, publicKey, cryptAlgo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writePublicKeyFunction( &stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t KEYFORMAT_CERT, \"public_key\", 10 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = calculateFlatKeyID( buffer, stell( &stream ), \n\t\t\t\t\t\t\t\t\t publicKey->keyID, KEYID_SIZE );\n\t\t}\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t/* If it's an RSA key, we need to calculate the PGP 2 key ID alongside \n\t   the cryptlib one */\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\tconst PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\t\tint length;\n\n\t\tstatus = exportBignum( buffer, CRYPT_MAX_PKCSIZE, &length,\n\t\t\t\t\t\t\t   &pkcInfo->rsaParam_n );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( length > PGP_KEYID_SIZE )\n\t\t\t{\n\t\t\tmemcpy( publicKey->pgp2KeyID, \n\t\t\t\t\tbuffer + length - PGP_KEYID_SIZE, PGP_KEYID_SIZE );\n\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t  PKCINFO_FLAG_PGPKEYID_SET );\n\t\t\t}\n\t\t}\n\n\t/* If the OpenPGP ID is already set by having the key loaded from a PGP\n\t   keyset, we're done */\n\tif( TEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t   PKCINFO_FLAG_OPENPGPKEYID_SET ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If it's a non-PGP algorithm then we can't do anything with it */\n\tif( cryptAlgo != CRYPT_ALGO_RSA && cryptAlgo != CRYPT_ALGO_DSA && \\\n\t\tcryptAlgo != CRYPT_ALGO_ELGAMAL )\n\t\treturn( CRYPT_OK );\n\n\t/* Finally, set the OpenPGP key ID */\n\tstatus = calculateOpenPGPKeyID( contextInfoPtr, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#endif /* USE_PGP || USE_PGPKEYS */\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyID( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( pkcInfo->calculateKeyIDFunction, calculateKeyID );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int calculateKeyIDDummy( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *publicKey = contextInfoPtr->ctxPKC;\n\tMESSAGE_DATA msgData;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\n\t/* If we're not using ASN.1 then we can't calculate keyIDs, but then no \n\t   code that requires keyIDs is actually enabled so we just set a dummy\n\t   value for the ID */\n\tsetMessageData( &msgData, publicKey->keyID, KEYID_SIZE );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyID( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( pkcInfo->calculateKeyIDFunction, calculateKeyIDDummy );\n\t}\n#endif /* USE_INT_ASN1 && USE_PKC */\n\n"
  },
  {
    "path": "deps/cl345/context/key_rdpri.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPrivate Key Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"context.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_KEYSETS ) && defined( USE_PKC )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKCS #15 Private Keys\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Read private key components.  These functions assume that the public\n   portions of the context have already been set up */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRsaPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tREAD_BIGNUM_FUNCTION readBignumFunction = checkRead ? \\\n\t\t\t\t\t\t\t\t\tcheckBignumRead : readBignumTag;\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\t/* Read the header */\n\tstatus = readSequence( stream, NULL );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\t/* Erroneously written in older code */\n\t\tstatus = readConstructed( stream, NULL, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the key components */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( 0 ) )\n\t\t{\n\t\t/* The public components may already have been read when we read a\n\t\t   corresponding public key or certificate so we only read them if\n\t\t   they're not already present */\n\t\tif( BN_is_zero( &rsaKey->rsaParam_n ) && \\\n\t\t\tBN_is_zero( &rsaKey->rsaParam_e ) )\n\t\t\t{\n\t\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_n, \n\t\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_N, RSAPARAM_MAX_N, \n\t\t\t\t\t\t\t\t\t\t NULL, 0 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_e, \n\t\t\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_E, RSAPARAM_MAX_E, \n\t\t\t\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The key components are already present, skip them */\n\t\t\tREQUIRES( !BN_is_zero( &rsaKey->rsaParam_n ) && \\\n\t\t\t\t\t  !BN_is_zero( &rsaKey->rsaParam_e ) );\n\t\t\treadUniversal( stream );\n\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( 2 ) )\n\t\t{\n\t\t/* d isn't used so we skip it */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_p, \n\t\t\t\t\t\t\t\t RSAPARAM_MIN_P, RSAPARAM_MAX_P, \n\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 3 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_q, \n\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_Q, RSAPARAM_MAX_Q, \n\t\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 4 );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( 5 ) )\n\t\t{\n\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_exponent1, \n\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_EXP1, RSAPARAM_MAX_EXP1, \n\t\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 5 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_exponent2, \n\t\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_EXP2, RSAPARAM_MAX_EXP2, \n\t\t\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 6 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readBignumFunction( stream, &rsaKey->rsaParam_u, \n\t\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_U, RSAPARAM_MAX_U, \n\t\t\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n, 7 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readDlpPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tPKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst DH_DOMAINPARAMS *domainParams = dlpKey->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &dlpKey->dlpParam_p;\n\tREAD_BIGNUM_FUNCTION readBignumFunction = checkRead ? \\\n\t\t\t\t\t\t\t\t\tcheckBignumRead : readBignumTag;\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\t/* Read the key components */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == BER_SEQUENCE )\n\t\t{\n\t\t/* Erroneously written in older code */\n\t\tstatus = readSequence( stream, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readBignumFunction( stream, &dlpKey->dlpParam_x,\n\t\t\t\t\t\t\t\t\t\t DLPPARAM_MIN_X, DLPPARAM_MAX_X, \n\t\t\t\t\t\t\t\t\t\t p, 0 );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tstatus = readBignumFunction( stream, &dlpKey->dlpParam_x,\n\t\t\t\t\t\t\t\t DLPPARAM_MIN_X, DLPPARAM_MAX_X, p,\n\t\t\t\t\t\t\t\t DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dlpKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readEccPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREAD_BIGNUM_FUNCTION readBignumFunction = checkRead ? \\\n\t\t\t\t\t\t\t\t\tcheckBignumRead : readBignumTag;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\t/* Read the key components.  Note that we can't use the ECC p value for\n\t   a range check because it hasn't been set yet, all that we have at \n\t   this point is a curve ID */\n\tstatus = readBignumFunction( stream, &eccKey->eccParam_d,\n\t\t\t\t\t\t\t\t ECCPARAM_MIN_D, ECCPARAM_MAX_D, NULL,\n\t\t\t\t\t\t\t\t DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKCS #12 Private Keys\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read private key components.  These functions assume that the public\n   portions of the context have already been set up */\n\n#if defined( USE_PKCS12 ) && defined( USE_INT_ASN1 )\n\n#define OID_X509_KEYUSAGE\tMKOID( \"\\x06\\x03\\x55\\x1D\\x0F\" )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRsaPrivateKeyOld( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int startPos = stell( stream );\n\tint length, endPos, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\n\t/* Skip the PKCS #8 wrapper.  When we read the OCTET STRING \n\t   encapsulation we use MIN_PKCSIZE_THRESHOLD rather than MIN_PKCSIZE\n\t   so that a too-short key will get to readBignumChecked(), which\n\t   returns an appropriate error code */\n\treadSequence( stream, &length );\t\t\t/* Outer wrapper */\n\tstatus = readShortInteger( stream, NULL );\t/* Version */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAlgoID( stream, &cryptAlgo, ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_RSA )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = readOctetStringHole( stream, NULL, \n\t\t\t\t\t\t\t\t  ( 2 * MIN_PKCSIZE_THRESHOLD ) + \\\n\t\t\t\t\t\t\t\t\t( 5 * ( MIN_PKCSIZE_THRESHOLD / 2 ) ), \n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\t\t\t/* OCTET STRING encaps.*/\n\t\treturn( status );\n\n\t/* Read the header */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the RSA key components, skipping n and e if we've already got \n\t   them via the associated public key/certificate */\n\tif( BN_is_zero( &rsaKey->rsaParam_n ) )\n\t\t{\n\t\tstatus = readBignumChecked( stream, &rsaKey->rsaParam_n,\n\t\t\t\t\t\t\t\t\tRSAPARAM_MIN_N, RSAPARAM_MAX_N, \n\t\t\t\t\t\t\t\t\tNULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readBignum( stream, &rsaKey->rsaParam_e,\n\t\t\t\t\t\t\t\t RSAPARAM_MIN_E, RSAPARAM_MAX_E,\n\t\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\t\t}\n\telse\n\t\t{\n\t\treadUniversal( stream );\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* d isn't used so we skip it */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_p,\n\t\t\t\t\t\t\t RSAPARAM_MIN_P, RSAPARAM_MAX_P,\n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_q,\n\t\t\t\t\t\t\t RSAPARAM_MIN_Q, RSAPARAM_MAX_Q,\n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_exponent1,\n\t\t\t\t\t\t\t RSAPARAM_MIN_EXP1, RSAPARAM_MAX_EXP1,\n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_exponent2,\n\t\t\t\t\t\t\t RSAPARAM_MIN_EXP2, RSAPARAM_MAX_EXP2,\n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_u,\n\t\t\t\t\t\t\t RSAPARAM_MIN_U, RSAPARAM_MAX_U,\n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check whether there are any attributes present */\n\tif( stell( stream ) >= startPos + length )\n\t\treturn( CRYPT_OK );\n\n\t/* Read the attribute wrapper */\n\tstatus = readConstructed( stream, &length, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the collection of attributes.  Unlike any other key-storage \n\t   format, PKCS #8 stores the key usage information as an X.509 \n\t   attribute alongside the encrypted private key data so we have to\n\t   process whatever attributes may be present in order to find the\n\t   keyUsage (if there is any) in order to set the object action \n\t   permissions */\n\tLOOP_MED_CHECK( stell( stream ) < endPos )\n\t\t{\n\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\t\tint oidLength, actionFlags, value;\n\n\t\t/* Read the attribute.  Since there's only one attribute type that \n\t\t   we can use, we hardcode the read in here rather than performing a \n\t\t   general-purpose attribute read */\n\t\treadSequence( stream, NULL );\n\t\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If it's not a key-usage attribute, we can't do much with it */\n\t\tif( oidLength != sizeofOID( OID_X509_KEYUSAGE ) || \\\n\t\t\tmemcmp( oid, OID_X509_KEYUSAGE, oidLength ) )\n\t\t\t{\n\t\t\tstatus = readUniversal( stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Read the keyUsage attribute and convert it into cryptlib action \n\t\t   permissions */\n\t\treadSet( stream, NULL );\n\t\tstatus = readBitString( stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tactionFlags = ACTION_PERM_NONE;\n\t\tif( value & ( KEYUSAGE_SIGN | KEYUSAGE_CA ) )\n\t\t\t{\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL );\n\t\t\t}\n\t\tif( value & KEYUSAGE_CRYPT )\n\t\t\t{\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL );\n\t\t\t}\n#if 0\t/* 11/6/13 Windows sets these flags to what are effectively\n\t\t\t\t   gibberish values (dataEncipherment for a signing key,\n\t\t\t\t   digitalSignature for an encryption key) so in order\n\t\t\t\t   to be able to use the key we have to ignore the keyUsage \n\t\t\t\t   settings, in the same way that every other application \n\t\t\t\t   seems to */\n\t\tif( actionFlags == ACTION_PERM_NONE )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\tstatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &actionFlags, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#else\n\t\tassert( actionFlags != ACTION_PERM_NONE );\t/* Warn in debug mode */\n#endif /* 0 */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readDsaPrivateKeyOld( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;\n\tPKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA );\n\n\t/* Skip the PKCS #8 wrapper */\n\treadSequence( stream, NULL );\t\t\t\t/* Outer wrapper */\n\tstatus = readShortInteger( stream, NULL );\t/* Version */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAlgoIDparam( stream, &cryptAlgo, &dummy, \n\t\t\t\t\t\t\t\t  ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_DSA )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the DSA parameters if we haven't already got them via the\n\t   associated public key/certificate */\n\tif( BN_is_zero( &dlpKey->dlpParam_p ) )\n\t\t{\n\t\treadSequence( stream, NULL );\t/* Parameter wrapper */\n\t\tstatus = readBignumChecked( stream, &dlpKey->dlpParam_p,\n\t\t\t\t\t\t\t\t\tDLPPARAM_MIN_P, DLPPARAM_MAX_P, \n\t\t\t\t\t\t\t\t\tNULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readBignumChecked( stream, &dlpKey->dlpParam_q,\n\t\t\t\t\t\t\t\t\t\tDLPPARAM_MIN_Q, DLPPARAM_MAX_Q, \n\t\t\t\t\t\t\t\t\t\tNULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readBignumChecked( stream, &dlpKey->dlpParam_g,\n\t\t\t\t\t\t\t\t\t\tDLPPARAM_MIN_G, DLPPARAM_MAX_G, \n\t\t\t\t\t\t\t\t\t\tNULL );\n\t\t}\n\telse\n\t\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the DSA private key component */\n\tstatus = readOctetStringHole( stream, NULL, 20, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\t/* OCTET STRING encapsulation */\n\t\tstatus = readBignum( stream, &dlpKey->dlpParam_x,\n\t\t\t\t\t\t\t DLPPARAM_MIN_X, DLPPARAM_MAX_X,\n\t\t\t\t\t\t\t &dlpKey->dlpParam_p );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dlpKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n#define OID_ECPUBLICKEY\t\tMKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x02\\x01\" )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readEccPrivateKeyOld( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tlong value;\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\n\t/* Read the ECC key components.  These were never standardised in any \n\t   PKCS standard, nor in the PKCS #12 RFC.  RFC 5915 \"Elliptic Curve \n\t   Private Key Structure\" specifies the format for PKCS #8 as:\n\n\t\tECPrivateKey ::= SEQUENCE {\n\t\t\tversion\t\t\tINTEGER (1),\n\t\t\tprivateKey\t\tOCTET STRING,\n\t\t\tparameters\t[0]\tECParameters {{ NamedCurve }} OPTIONAL,\n\t\t\tpublicKey\t[1]\tBIT STRING OPTIONAL\n\t\t\t}\n\n\t   but this isn't what's present in the encoded form created by OpenSSL.\n\t   Instead it's:\n\n\t\tECSomething ::= SEQUENCE {\n\t\t\tversion\t\t\tINTEGER (0),\n\t\t\tparameters\t\tSEQUENCE {\n\t\t\t\ttype\t\tOBJECT IDENTIFIER ecPublicKey,\n\t\t\t\tnamedCurve\tOBJECT IDENTIFIER\n\t\t\t\t}\n\t\t\tsomething\t\tOCTET STRING {\n\t\t\t\tkey\t\t\tECPrivateKey\t\t-- As above\n\t\t\t\t}\n\t\t\t}\n\n\t   so we have to tunnel into this in order to find the PKCS #8-like\n\t   data that we're actually interested in.\n\n\t   Note that we can't use the ECC p value for a range check because it \n\t   hasn't been set yet, all that we have at this point is a curve ID */\n\treadSequence( stream, NULL );\t\t/* Outer wrapper */\n\tstatus = readShortInteger( stream, &value );/* Version */\n\tif( cryptStatusError( status ) || value != 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = readAlgoIDparam( stream, &cryptAlgo, &length, \n\t\t\t\t\t\t\t  ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_ECDSA )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\treadUniversal( stream );\t\t\t/* Named curve */\n\treadOctetStringHole( stream, NULL, MIN_PKCSIZE_ECC_THRESHOLD, \n\t\t\t\t\t\t DEFAULT_TAG );\t\t/* OCTET STRING hole wrapper */\n\treadSequence( stream, NULL );\t\t\t\t/* ECPrivateKey wrapper */\n\tstatus = readShortInteger( stream, &value );\t/* Version */\n\tif( cryptStatusError( status ) || value != 1 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* We've finalled made it down to the private key value.  At this point \n\t   we can't use readBignumTag() directly because it's designed to read \n\t   either standard INTEGERs (via DEFAULT_TAG) or context-specific tagged \n\t   items, so passing in a BER_OCTETSTRING will be interpreted as \n\t   [4] IMPLICIT INTEGER rather than an OCTET STRING-tagged integer.  To \n\t   get around this we read the tag separately and tell readBignumTag() \n\t   to skip the tag read */\n\ttag = readTag( stream );\n\tif( cryptStatusError( tag ) || tag != BER_OCTETSTRING )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = readBignumTag( stream, &eccKey->eccParam_d,\n\t\t\t\t\t\t\tECCPARAM_MIN_D, ECCPARAM_MAX_D, NULL,\n\t\t\t\t\t\t\tNO_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_PKCS12 && USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PGP Private Keys\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PGP \n\n/* Read PGP private key components.  This function assumes that the public\n   portion of the context has already been set up */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpRsaPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\n\t/* Read the PGP private key information.  Note that we have to read the \n\t   d value here because we need it to calculate e1 and e2 */\n\tstatus = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_d, \n\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MIN_D ), \n\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MAX_D ), \n\t\t\t\t\t\t\t\t\t   &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_p, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MIN_P ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MAX_P ),\n\t\t\t\t\t\t\t\t\t\t   &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_q, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MIN_Q ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MAX_Q ),\n\t\t\t\t\t\t\t\t\t\t   &rsaKey->rsaParam_n );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_u, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MIN_U ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MAX_U ),\n\t\t\t\t\t\t\t\t\t\t   &rsaKey->rsaParam_n );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpDlpPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\n\t/* Read the PGP private key information */\n\tstatus = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_x, \n\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MIN_X ), \n\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MAX_X ),\n\t\t\t\t\t\t\t\t\t   &dlpKey->dlpParam_p );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dlpKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPrivate-Key Read Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Umbrella private-key read functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPrivateKeyRsaFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_PRIVATE:\n\t\t\treturn( readRsaPrivateKey( stream, contextInfoPtr, checkRead ) );\n#endif /* USE_INT_ASN1 */\n\n#if defined( USE_PKCS12 ) && defined( USE_INT_ASN1 )\n\t\tcase KEYFORMAT_PRIVATE_OLD:\n\t\t\treturn( readRsaPrivateKeyOld( stream, contextInfoPtr ) );\n#endif /* USE_PKCS12 && USE_INT_ASN1 */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\treturn( readPgpRsaPrivateKey( stream, contextInfoPtr ) );\n#endif /* USE_PGP */\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPrivateKeyDlpFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_PRIVATE:\n\t\t\treturn( readDlpPrivateKey( stream, contextInfoPtr, checkRead ) );\n#endif /* USE_INT_ASN1 */\n\n#if defined( USE_PKCS12 ) && defined( USE_INT_ASN1 )\n\t\tcase KEYFORMAT_PRIVATE_OLD:\n\t\t\treturn( readDsaPrivateKeyOld( stream, contextInfoPtr ) );\n#endif /* USE_PKCS12 && USE_INT_ASN1 */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\treturn( readPgpDlpPrivateKey( stream, contextInfoPtr ) );\n#endif /* USE_PGP */\n\t\t}\n\n\tretIntError();\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPrivateKeyEccFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_PRIVATE:\n\t\t\treturn( readEccPrivateKey( stream, contextInfoPtr, checkRead ) );\n#endif /* USE_INT_ASN1 */\n\n#if defined( USE_PKCS12 ) && defined( USE_INT_ASN1 )\n\t\tcase KEYFORMAT_PRIVATE_OLD:\n\t\t\treturn( readEccPrivateKeyOld( stream, contextInfoPtr ) );\n#endif /* USE_PKCS12 && USE_INT_ASN1 */\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPrivKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES_V( capabilityInfoPtr != NULL );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\t/* Set the access method pointers */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->readPrivateKeyFunction, readPrivateKeyDlpFunction );\n\t\treturn;\n\t\t}\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->readPrivateKeyFunction, readPrivateKeyEccFunction );\n\t\treturn;\n\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\tFNPTR_SET( pkcInfo->readPrivateKeyFunction, readPrivateKeyRsaFunction );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPrivKeyNullFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN checkRead )\n\t{\n\tUNUSED_ARG( stream );\n\tUNUSED_ARG( contextInfoPtr );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPrivKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( pkcInfo->readPrivateKeyFunction, readPrivKeyNullFunction );\n\t}\n#endif /* USE_KEYSETS && USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/key_rdpub.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPublic Key Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"context.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/* The DLP algorithms split the key components over the information in the\n   AlgorithmIdentifier and the actual public/private key components, with the\n   (p, q, g) set classed as domain parameters and included in the\n   AlgorithmIdentifier and y being the actual key.\n\n\tparams = SEQ {\n\t\tp INTEGER,\n\t\tq INTEGER,\t\t\t\t-- q for DSA\n\t\tg INTEGER,\t\t\t\t-- g for DSA\n\t\tj INTEGER OPTIONAL,\t\t-- X9.42 only\n\t\tvalidationParams [...]\t-- X9.42 only\n\t\t}\n\n\tkey = y INTEGER\t\t\t\t-- g^x mod p\n\n   For peculiar historical reasons (copying errors and the use of obsolete\n   drafts as reference material) the X9.42 interpretation used in PKIX \n   reverses the second two parameters from FIPS 186 (so it uses p, g, q \n   instead of p, q, g), so when we read/write the parameter information we \n   have to switch the order in which we read the values if the algorithm \n   isn't DSA */\n\n#define hasReversedParams( cryptAlgo ) \\\n\t\t( ( cryptAlgo ) == CRYPT_ALGO_DH || \\\n\t\t  ( cryptAlgo ) == CRYPT_ALGO_ELGAMAL )\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead X.509 Public Keys\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Read X.509 SubjectPublicKeyInfo public keys:\n\n\tSubjectPublicKeyInfo  ::=  SEQUENCE  {\n\t\talgorithm\t\t\tAlgorithmIdentifier,\n\t\tsubjectPublicKey\tBIT STRING  \n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readRsaSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the SubjectPublicKeyInfo header field and parameter data if\n\t   there's any present.  We read the outer wrapper in generic form since\n\t   it may be context-specific-tagged if it's coming from a keyset (RSA\n\t   public keys is the one place where PKCS #15 keys differ from X.509\n\t   ones) or something odd from CRMF */\n\tstatus = readGenericHole( stream, NULL, 8 + MIN_PKCSIZE_THRESHOLD + \\\n\t\t\t\t\t\t\t\t\t\t\tRSAPARAM_MIN_E, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAlgoID( stream, &cryptAlgo, ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( cryptAlgo != CRYPT_ALGO_RSA )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Set the maximum permitted actions.  More restrictive permissions may \n\t   be set by higher-level code if required and in particular if the key \n\t   is a pure public key rather than merely the public portions of a \n\t   private key then the actions will be restricted at that point to \n\t   encrypt and signature-check only */\n\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL ) | \\\n\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );\n\n\t/* Read the BIT STRING encapsulation and the public key fields */\n\treadBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );\n\treadSequence( stream, NULL );\n\tstatus = readBignumChecked( stream, &rsaKey->rsaParam_n, \n\t\t\t\t\t\t\t\tRSAPARAM_MIN_N, RSAPARAM_MAX_N, NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignum( stream, &rsaKey->rsaParam_e,\n\t\t\t\t\t\t\t RSAPARAM_MIN_E, RSAPARAM_MAX_E, \n\t\t\t\t\t\t\t &rsaKey->rsaParam_n );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readDlpSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;\n\tint extraLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the SubjectPublicKeyInfo header field and make sure that the DLP \n\t   parameter data is present */\n\tstatus = readGenericHole( stream, NULL, \n\t\t\t\t\t\t\t  8 + MIN_PKCSIZE_THRESHOLD + DLPPARAM_MIN_G + \\\n\t\t\t\t\t\t\t  DLPPARAM_MIN_Q + MIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAlgoIDparam( stream, &cryptAlgo, &extraLength, \n\t\t\t\t\t\t\t\t  ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( extraLength < MIN_PKCSIZE_THRESHOLD + DLPPARAM_MIN_G + \\\n\t\t\t\t\t  DLPPARAM_MIN_Q || \\\n\t\textraLength > MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( capabilityInfoPtr->cryptAlgo != cryptAlgo )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the header and key parameters */\n\treadSequence( stream, NULL );\n\tstatus = readBignumChecked( stream, &dlpKey->dlpParam_p, \n\t\t\t\t\t\t\t\tDLPPARAM_MIN_P, DLPPARAM_MAX_P, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hasReversedParams( cryptAlgo ) )\n\t\t{\n\t\tstatus = readBignum( stream, &dlpKey->dlpParam_g, DLPPARAM_MIN_G, \n\t\t\t\t\t\t\t DLPPARAM_MAX_G, &dlpKey->dlpParam_p );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readBignum( stream, &dlpKey->dlpParam_q, DLPPARAM_MIN_Q, \n\t\t\t\t\t\t\t\t DLPPARAM_MAX_Q, &dlpKey->dlpParam_p );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readBignum( stream, &dlpKey->dlpParam_q, DLPPARAM_MIN_Q, \n\t\t\t\t\t\t\t DLPPARAM_MAX_Q, &dlpKey->dlpParam_p );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readBignum( stream, &dlpKey->dlpParam_g, DLPPARAM_MIN_G, \n\t\t\t\t\t\t\t\t DLPPARAM_MAX_G, &dlpKey->dlpParam_p );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the maximum permitted actions.  Because of the special-case data \n\t   formatting requirements for DLP algorithms we make the usage \n\t   internal-only.  If the key is a pure public key rather than merely \n\t   the public portions of a private key then the actions will be \n\t   restricted by higher-level code to encrypt/signature-check only */\n\tif( cryptAlgo == CRYPT_ALGO_DSA )\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\telse\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\n\t/* Read the BIT STRING encapsulation and the public key fields */\n\treadBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );\n\tstatus = readBignumChecked( stream, &dlpKey->dlpParam_y,\n\t\t\t\t\t\t\t\tDLPPARAM_MIN_Y, DLPPARAM_MAX_Y,\n\t\t\t\t\t\t\t\t&dlpKey->dlpParam_p );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dlpKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readEccSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo DUMMY_INIT;\n\tCRYPT_ECCCURVE_TYPE curveType;\n\tBYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];\n\tint fieldSize DUMMY_INIT;\n\tint length, extraLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the SubjectPublicKeyInfo header field and make sure that the ECC \n\t   parameter data is present.  Because of the more or less arbitrary \n\t   manner in which these parameters can be represented we have to be \n\t   fairly open-ended in terms of the data size limits that we use, and \n\t   in particular for named curves the lower bound is the size of a \n\t   single OID that defines the curve */\n\tstatus = readGenericHole( stream, NULL, \n\t\t\t\t\t\t\t  8 + MIN_OID_SIZE + \\\n\t\t\t\t\t\t\t  MIN_PKCSIZE_ECCPOINT_THRESHOLD, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDparam( stream, &cryptAlgo, &extraLength, \n\t\t\t\t\t\t\t\t  ALGOID_CLASS_PKC );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( extraLength < MIN_OID_SIZE || extraLength > MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( capabilityInfoPtr->cryptAlgo != cryptAlgo )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Now things get messy, since the ECC standards authors carefully \n\t   sidestepped having to make a decision about anything and instead\n\t   just created an open framework into which it's possible to drop\n\t   almost anything.  To keep things sane we require the use of named\n\t   curves (which most people seem to use) over a prime field */\n\tstatus = readECCOID( stream, &curveType );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getECCFieldSize( curveType, &fieldSize, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\teccKey->curveType = curveType;\n\n\t/* Set the maximum permitted actions.  Because of the special-case data \n\t   formatting requirements for ECC algorithms (which are a part of the \n\t   DLP algorithm family) we make the usage internal-only.  If the key is \n\t   a pure public key rather than merely the public portions of a private \n\t   key then the actions will be restricted by higher-level code to \n\t   encrypt/signature-check only */\n\tif( cryptAlgo == CRYPT_ALGO_ECDSA )\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\telse\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\n\t/* Read the BIT STRING encapsulation and the public key fields.  Instead \n\t   of encoding the necessary information as an obvious OID + SEQUENCE \n\t   combination for the parameters it's all stuffed into an ad-hoc BIT \n\t   STRING that we have to pick apart manually.  Note that we can't use \n\t   the ECC p value for a range check because it hasn't been set yet, all \n\t   that we have at this point is a curve ID */\n\tstatus = readBitStringHole( stream, &length, \n\t\t\t\t\t\t\t\tMIN_PKCSIZE_ECCPOINT_THRESHOLD, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_PKCSIZE_ECCPOINT_THRESHOLD || \\\n\t\tlength > MAX_PKCSIZE_ECCPOINT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sread( stream, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importECCPoint( &eccKey->eccParam_qx, &eccKey->eccParam_qy,\n\t\t\t\t\t\t\t buffer, length, MIN_PKCSIZE_ECC_THRESHOLD, \n\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE_ECC, fieldSize, NULL, \n\t\t\t\t\t\t\t KEYSIZE_CHECK_ECC );\n\tzeroise( buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead SSH Public Keys\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSH\n\n/* Read SSHv2 public keys:\n\n   RSA/DSA:\n\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\tmpint\te\t\t\tp\n\t\tmpint\tn\t\t\tq\n\t\tmpint\t\t\t\tg\n\t\tmpint\t\t\t\ty\n\n   ECDSA:\n\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ecdsa-sha2-*\"\n\t\tstring\t\"*\"\t\t\t\t-- The \"*\" portion from the above field\n\t\tstring\tQ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readSshRsaPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tchar buffer[ 16 + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the wrapper and make sure that it's OK */\n\treadUint32( stream );\n\tstatus = readString32( stream, buffer, 7, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != 7 || memcmp( buffer, \"ssh-rsa\", 7 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Set the maximum permitted actions.  SSH keys are only used internally\n\t   so we restrict the usage to internal-only */\n\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\n\t/* Read the SSH public key information */\n\tstatus = readBignumInteger32( stream, &rsaKey->rsaParam_e, \n\t\t\t\t\t\t\t\t  RSAPARAM_MIN_E, RSAPARAM_MAX_E, \n\t\t\t\t\t\t\t\t  NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger32Checked( stream, &rsaKey->rsaParam_n,\n\t\t\t\t\t\t\t\t\t\t\t RSAPARAM_MIN_N, RSAPARAM_MAX_N );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readSshDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *dsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tchar buffer[ 16 + 8 ];\n\tBOOLEAN isDH;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA ) );\n\n\tisDH = ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? TRUE : FALSE;\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the wrapper and make sure that it's OK.  SSHv2 uses PKCS #3 \n\t   rather than X9.42-style DH keys so we have to treat this algorithm \n\t   type specially */\n\treadUint32( stream );\n\tif( isDH )\n\t\t{\n\t\tstatus = readString32( stream, buffer, 6, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( length != 6 || memcmp( buffer, \"ssh-dh\", 6 ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Set the maximum permitted actions.  SSH keys are only used \n\t\t   internally so we restrict the usage to internal-only.  Since DH \n\t\t   keys can be both public and private keys we allow both usage \n\t\t   types even though technically it's a public key */\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\n\t\t/* Read the SSH public key information */\n\t\tstatus = readBignumInteger32Checked( stream, &dsaKey->dlpParam_p,\n\t\t\t\t\t\t\t\t\t\t\t DLPPARAM_MIN_P, DLPPARAM_MAX_P );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readBignumInteger32( stream, &dsaKey->dlpParam_g,\n\t\t\t\t\t\t\t\t\t\t  DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t\t\t  &dsaKey->dlpParam_p );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* It's a standard DLP key, read the wrapper and make sure that it's \n\t   OK */\n\tstatus = readString32( stream, buffer, 7, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != 7 || memcmp( buffer, \"ssh-dss\", 7 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Set the maximum permitted actions.  SSH keys are only used internally\n\t   so we restrict the usage to internal-only */\n\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\n\t/* Read the SSH public key information */\n\tstatus = readBignumInteger32Checked( stream, &dsaKey->dlpParam_p,\n\t\t\t\t\t\t\t\t\t\t DLPPARAM_MIN_P, DLPPARAM_MAX_P );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger32( stream, &dsaKey->dlpParam_q,\n\t\t\t\t\t\t\t\t\t  DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,\n\t\t\t\t\t\t\t\t\t  &dsaKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger32( stream, &dsaKey->dlpParam_g,\n\t\t\t\t\t\t\t\t\t  DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t\t  &dsaKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusOK( status ) && !isDH )\n\t\t{\n\t\tstatus = readBignumInteger32( stream, &dsaKey->dlpParam_y,\n\t\t\t\t\t\t\t\t\t  DLPPARAM_MIN_Y, DLPPARAM_MAX_Y,\n\t\t\t\t\t\t\t\t\t  &dsaKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readSshEccPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tBYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];\n\tBOOLEAN isECDH;\n\tint length, fieldSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\n\tisECDH = ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH ) ? TRUE : FALSE;\n\n\t/* No need to clear return value as usual since it's set in the \n\t   following line of code, and clearing it leads to compiler warnings\n\t   about unused assignments */\n\n\t/* Set the maximum permitted actions.  SSH keys are only used \n\t   internally so we restrict the usage to internal-only.  Since ECDH \n\t   keys can be both public and private keys we allow both usage \n\t   types even though technically it's a public key */\n\tif( isECDH )\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\telse\n\t\t{\n\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\n\t/* Read the wrapper and make sure that it's OK.  The key parameter\n\t   information is repeated twice, so for the overall wrapper we only\n\t   check for the ECDH/ECDSA algorithm indication and get the parameter\n\t   information from the second version, which contains only the\n\t   parameter string */\n\treadUint32( stream );\n\tstatus = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < 18 )\t\t/* \"ecdh-sha2-nistXXXX\" */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( isECDH )\n\t\t{\n\t\tif( memcmp( buffer, \"ecdh-sha2-\", 10 ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\telse\n\t\t{\n\t\tif( memcmp( buffer, \"ecdsa-sha2-\", 11 ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Read and process the parameter information.  At this point we know \n\t   that we've got valid ECC key data, so if we find anything unexpected \n\t   we report it as an unavailable ECC field size rather than bad data */\n\tstatus = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != 8 )\t\t/* \"nistXXXX\" */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( !memcmp( buffer, \"nistp256\", 8 ) )\n\t\teccKey->curveType = CRYPT_ECCCURVE_P256;\n\telse\n\t\t{\n\t\tif( !memcmp( buffer, \"nistp384\", 8 ) )\n\t\t\teccKey->curveType = CRYPT_ECCCURVE_P384;\n\t\telse\n\t\t\t{\n\t\t\tif( !memcmp( buffer, \"nistp521\", 8 ) )\n\t\t\t\teccKey->curveType = CRYPT_ECCCURVE_P521;\n\t\t\telse\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\t}\n\tstatus = getECCFieldSize( eccKey->curveType, &fieldSize, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the ECC public key.  See the comments in \n\t   readEccSubjectPublicKey() for why the checks are done the way they \n\t   are */\n\tstatus = readString32( stream, buffer, MAX_PKCSIZE_ECCPOINT, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_PKCSIZE_ECCPOINT_THRESHOLD || \\\n\t\tlength > MAX_PKCSIZE_ECCPOINT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = importECCPoint( &eccKey->eccParam_qx, &eccKey->eccParam_qy,\n\t\t\t\t\t\t\t buffer, length, MIN_PKCSIZE_ECC_THRESHOLD, \n\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE_ECC, fieldSize, NULL, \n\t\t\t\t\t\t\t KEYSIZE_CHECK_ECC );\n\tzeroise( buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_SSH */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead SSL Public Keys\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSL\n\n/* Read SSL public keys:\n\n\tDH:\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t  [\tuint16\t\tdh_qLen\n\t\tbyte[]\t\tdh_q\t\t-- For TLS-ext format ]\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t  [\tuint16\t\tdh_YsLen ]\n\t  [\tbyte[]\t\tdh_Ys\t ]\n\n\tECDH:\n\t\tbyte\t\tcurveType\n\t\tuint16\t\tnamedCurve\n\t  [\tuint8\t\tecPointLen\t-- NB uint8 not uint16 ]\n\t  [\tbyte[]\t\tecPoint ]\n\n   The DH y value is nominally attached to the DH p and g values but isn't \n   processed at this level since this is a pure PKCS #3 DH key and not a \n   generic DLP key.  The same holds for the ECDH Q value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readSslDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags,\n\t\t\t\t\t\t\t\tconst BOOLEAN readExtKey )\n\t{\n\tPKC_INFO *dhKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH );\n\tREQUIRES( readExtKey == TRUE || readExtKey == FALSE );\n\n\t/* No need to clear return value as usual since it's set in the \n\t   following line of code, and clearing it leads to compiler warnings\n\t   about unused assignments */\n\n\t/* Set the maximum permitted actions.  SSL keys are only used \n\t   internally so we restrict the usage to internal-only.  Since DH \n\t   keys can be both public and private keys we allow both usage \n\t   types even though technically it's a public key */\n\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\n\t/* Read the SSL public key information */\n\tstatus = readBignumInteger16UChecked( stream, &dhKey->dlpParam_p,\n\t\t\t\t\t\t\t\t\t\t  DLPPARAM_MIN_P, DLPPARAM_MAX_P );\n\tif( cryptStatusOK( status ) && readExtKey )\n\t\t{\n\t\tstatus = readBignumInteger16U( stream, &dhKey->dlpParam_q, \n\t\t\t\t\t\t\t\t\t   DLPPARAM_MIN_Q, DLPPARAM_MAX_Q,\n\t\t\t\t\t\t\t\t\t   &dhKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger16U( stream, &dhKey->dlpParam_g, \n\t\t\t\t\t\t\t\t\t   DLPPARAM_MIN_G, DLPPARAM_MAX_G,\n\t\t\t\t\t\t\t\t\t   &dhKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dhKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH )\n\nstatic const MAP_TABLE sslCurveInfo[] = {\n\t{ /* TLS_CURVE_SECP256R1 */ 23, CRYPT_ECCCURVE_P256 },\n\t{ /* TLS_CURVE_SECP384R1 */ 24, CRYPT_ECCCURVE_P384 },\n\t{ /* TLS_CURVE_SECP521R1 */ 25, CRYPT_ECCCURVE_P521 },\n\t{ /* TLS_CURVE_BRAINPOOLP256R1 */ 26, CRYPT_ECCCURVE_BRAINPOOL_P256 },\n\t{ /* TLS_CURVE_BRAINPOOLP384R1 */ 27, CRYPT_ECCCURVE_BRAINPOOL_P384 },\n\t{ /* TLS_CURVE_BRAINPOOLP512R1 */ 28, CRYPT_ECCCURVE_BRAINPOOL_P512 },\n\t{ CRYPT_ERROR, 0 }, \n\t\t{ CRYPT_ERROR, 0 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getEccSslInfoTbl( OUT const MAP_TABLE **sslInfoTblPtr,\n\t\t\t\t\t\t\t OUT_INT_Z int *noSslInfoTblEntries )\n\t{\n\tassert( isReadPtr( sslInfoTblPtr, sizeof( MAP_TABLE * ) ) );\n\tassert( isWritePtr( noSslInfoTblEntries, sizeof( int ) ) );\n\n\t*sslInfoTblPtr = sslCurveInfo;\n\t*noSslInfoTblEntries = FAILSAFE_ARRAYSIZE( sslCurveInfo, MAP_TABLE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readSslEccPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst MAP_TABLE *sslCurveInfoPtr;\n\tint value, curveID, sslCurveInfoNoEntries, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Set the maximum permitted actions.  SSL keys are only used \n\t   internally so we restrict the usage to internal-only.  Since ECDH \n\t   keys can be both public and private keys we allow both usage \n\t   types even though technically it's a public key */\n\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\n\t/* Read the SSL public key information */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != 0x03 )\t\t/* NamedCurve */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = value = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value < 19 || value > 28 )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Look up the curve ID based on the SSL NamedCurve ID */\n\tstatus = getEccSslInfoTbl( &sslCurveInfoPtr, &sslCurveInfoNoEntries );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = mapValue( value, &curveID, sslCurveInfoPtr, \n\t\t\t\t\t   sslCurveInfoNoEntries );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\teccKey->curveType = curveID;\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH */\n#endif /* USE_SSL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead PGP Public Keys\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PGP \n\n/* Read PGP public keys:\n\n\tbyte\t\tversion\n\tuint32\t\tcreationTime\n\t[ uint16\tvalidity - version 2 or 3 only ]\n\tbyte\t\tRSA\t\tDSA\t\tElgamal\t\tECDH/ECDSA\n\tmpi\t\t\tn\t\tp\t\tp\t\t\tqx/qy\n\tmpi\t\t\te\t\tq\t\tg\n\tmpi\t\t\t\t\tg\t\ty\n\tmpi\t\t\t\t\ty */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT time_t *pgpCreationTime,\n\t\t\t\t\t\t  const BOOLEAN openPgpOnly )\n\t{\n\tint version, value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pgpCreationTime, sizeof( time_t ) ) );\n\n\tREQUIRES( openPgpOnly == TRUE || openPgpOnly == FALSE );\n\n\t/* Clear return value */\n\t*pgpCreationTime = 0;\n\n\t/* Read the PGP version info */\n\tstatus = version = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( openPgpOnly )\n\t\t{\n\t\tif( version != PGP_VERSION_OPENPGP )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\telse\n\t\t{\n\t\tif( version != PGP_VERSION_2 && version != PGP_VERSION_3 && \\\n\t\t\tversion != PGP_VERSION_OPENPGP )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Read the creation time.  In theory we should do this with\n\t   readUint32Time(), however some keys coming from non-PGP sources can\n\t   have a creation time of zero which would result in the value being\n\t   rejected by the time read.  Because of this we have to read the value\n\t   as a standard 32-bit int and the perform the range check that's \n\t   otherwise performed by readUint32Time(), with an exception for a time\n\t   value of 0 */\n\tstatus = value = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != 0 )\n\t\t{\n\t\tif( value < MIN_STORED_TIME_VALUE || \\\n\t\t\tvalue >= MAX_TIME_VALUE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\t*pgpCreationTime = ( time_t ) value;\n\n\t/* Skip the validity time if it's present */\n\tif( version == PGP_VERSION_2 || version == PGP_VERSION_3 )\n\t\treturn( sSkip( stream, 2, 2 ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPgpRsaPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the header info */\n\tstatus = readPgpHeader( stream, &rsaKey->pgpCreationTime, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the maximum permitted actions.  If there are no restrictions we\n\t   allow external usage, if the keys are encryption-only or signature-\n\t   only we make the usage internal-only because of RSA's signature/\n\t   encryption duality.  If the key is a pure public key rather than \n\t   merely the public portions of a private key then the actions will be \n\t   restricted by higher-level code to encrypt/signature-check only */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( value )\n\t\t{\n\t\tcase PGP_ALGO_RSA:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL );\n\t\t\tbreak;\n\n\t\tcase PGP_ALGO_RSA_ENCRYPT:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tcase PGP_ALGO_RSA_SIGN:\n\t\t\t*actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Read the PGP public key information */\n\tstatus = readBignumInteger16UbitsChecked( stream, &rsaKey->rsaParam_n, \n\t\t\t\t\t\t\t\t\t\t\t  bytesToBits( RSAPARAM_MIN_N ), \n\t\t\t\t\t\t\t\t\t\t\t  bytesToBits( RSAPARAM_MAX_N ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger16Ubits( stream, &rsaKey->rsaParam_e, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MIN_E ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( RSAPARAM_MAX_E ),\n\t\t\t\t\t\t\t\t\t\t   &rsaKey->rsaParam_n );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( rsaKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPgpDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tPKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the header info */\n\tstatus = readPgpHeader( stream, &dlpKey->pgpCreationTime, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the maximum permitted actions.  Because of the special-case data \n\t   formatting requirements for DLP algorithms we make the usage \n\t   internal-only.  If the key is a pure public key rather than merely \n\t   the public portions of a private key then the actions will be \n\t   restricted by higher-level code to encrypt/signature-check only  */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( value )\n\t\t{\n\t\tcase PGP_ALGO_DSA:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\t\t\n\t\tcase PGP_ALGO_ELGAMAL:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Read the PGP public key information */\n\tstatus = readBignumInteger16UbitsChecked( stream, &dlpKey->dlpParam_p, \n\t\t\t\t\t\t\t\t\t\t\t  bytesToBits( DLPPARAM_MIN_P ), \n\t\t\t\t\t\t\t\t\t\t\t  bytesToBits( DLPPARAM_MAX_P ) );\n\tif( cryptStatusOK( status ) && value == PGP_ALGO_DSA )\n\t\t{\n\t\tstatus = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_q, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MIN_Q ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MAX_Q ),\n\t\t\t\t\t\t\t\t\t\t   &dlpKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_g, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MIN_G ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MAX_G ),\n\t\t\t\t\t\t\t\t\t\t   &dlpKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger16Ubits( stream, &dlpKey->dlpParam_y, \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MIN_Y ), \n\t\t\t\t\t\t\t\t\t\t   bytesToBits( DLPPARAM_MAX_Y ),\n\t\t\t\t\t\t\t\t\t\t   &dlpKey->dlpParam_p );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckPKCInfo( dlpKey ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPgpEccPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *actionFlags )\n\t{\n\tCRYPT_ECCCURVE_TYPE curveType;\n\tPKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tSTREAM oidStream;\n\tBYTE oidBuffer[ 2 + MAX_OID_SIZE + 8 ];\n\tint value, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( actionFlags, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH ) );\n\n\t/* Clear return value */\n\t*actionFlags = ACTION_PERM_NONE;\n\n\t/* Read the header info */\n\tstatus = readPgpHeader( stream, &eccKey->pgpCreationTime, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the maximum permitted actions.  Because of the special-case data \n\t   formatting requirements for ECC algorithms (which are a part of the \n\t   DLP algorithm family) we make the usage internal-only.  If the key is \n\t   a pure public key rather than merely the public portions of a private \n\t   key then the actions will be restricted by higher-level code to \n\t   encrypt/signature-check only */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( value )\n\t\t{\n\t\tcase PGP_ALGO_ECDH:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tcase PGP_ALGO_ECDSA:\n\t\t\t*actionFlags = MK_ACTION_PERM( MESSAGE_CTX_SIGN, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, \\\n\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Read the ECC OID, preceded by a length byte.  For no known reason \n\t   (probably a coding error that was made part of the spec), the PGP\n\t   format omits the first two bytes of the OID, so we have to read the\n\t   value into an intermediate buffer and recreate the full OID from \n\t   it */\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_OID_SIZE || length >= MAX_OID_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\toidBuffer[ 0 ] = 0x06;\t\t/* OID tag */\n\toidBuffer[ 1 ] = intToByte( length );\n\tstatus = sread( stream, oidBuffer + 2, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &oidStream, oidBuffer, 2 + length );\n\tstatus = readECCOID( &oidStream, &curveType );\n\tsMemDisconnect( &oidStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\teccKey->curveType = curveType;\n\n\tENSURES( sanityCheckPKCInfo( eccKey ) );\n\n\t/* We don't do PGP ECC yet since there's barely any use of it to test\n\t   against */\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPublic-Key Read Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Umbrella public-key read functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completePubkeyRead( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t   IN_FLAGS( ACTION_PERM ) const int actionFlags )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isFlagRange( actionFlags, ACTION_PERM ) );\n\n\t/* If it's statically-initialised context data used in the self-test \n\t   then there's no corresponding cryptlib object and we're done */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_STATICCONTEXT ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Set the action permissions for the context */\n\treturn( krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t ( MESSAGE_CAST ) &actionFlags, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ACTIONPERMS ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKeyRsaFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t STDC_UNUSED const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint actionFlags, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\tstatus = readRsaSubjectPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\tstatus = readSshRsaPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\tstatus = readPgpRsaPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( completePubkeyRead( contextInfoPtr, actionFlags ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKeyDlpFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t STDC_UNUSED const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint actionFlags, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\tstatus = readDlpSubjectPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\tstatus = readSshDlpPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n#ifdef USE_SSL\n\t\tcase KEYFORMAT_SSL:\n\t\tcase KEYFORMAT_SSL_EXT:\n\t\t\tstatus = readSslDlpPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t&actionFlags,\n\t\t\t\t\t\t\t\t\t( formatType == KEYFORMAT_SSL_EXT ) ? \\\n\t\t\t\t\t\t\t\t\t  TRUE : FALSE );\n\t\t\tbreak;\n#endif /* USE_SSL */\n\t\t\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\tstatus = readPgpDlpPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( completePubkeyRead( contextInfoPtr, actionFlags ) );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKeyEccFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t STDC_UNUSED const BOOLEAN checkRead )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint actionFlags, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH ) );\n\tREQUIRES( formatType == KEYFORMAT_CERT || formatType == KEYFORMAT_SSL || \\\n\t\t\t  formatType == KEYFORMAT_SSL_EXT || formatType == KEYFORMAT_SSH || \\\n\t\t\t  formatType == KEYFORMAT_PGP );\n\tREQUIRES( checkRead == TRUE || checkRead == FALSE );\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\tstatus = readEccSubjectPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_INT_ASN1 */\n\n\t\t/* TLS only uses ECDH (the ECDSA key data is conveyed in a \n\t\t   certificate) so we only enable the TLS format if ECDH is defined \n\t\t   rather than ECDH or ECDSA */\n#if defined( USE_SSL ) && defined( USE_ECDH )\n\t\tcase KEYFORMAT_SSL:\n\t\tcase KEYFORMAT_SSL_EXT:\n\t\t\tstatus = readSslEccPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_SSL && USE_ECDH */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\tstatus = readSshEccPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\tstatus = readPgpEccPublicKey( stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &actionFlags );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( completePubkeyRead( contextInfoPtr, actionFlags ) );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead DL Values\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike the simpler RSA PKC, DL-based PKCs produce a pair of values that\n   need to be encoded as structured data.  The following two functions \n   decode the encoded forms from various formats.  SSH assumes that DLP \n   values are two fixed-size blocks of 20 bytes so we can't use the normal \n   read/write routines to handle these values */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int decodeDLValuesFunction( IN_BUFFER( bufSize ) const BYTE *buffer, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int bufSize, \n\t\t\t\t\t\t\t\t   INOUT BIGNUM *value1, \n\t\t\t\t\t\t\t\t   INOUT BIGNUM *value2, \n\t\t\t\t\t\t\t\t   const BIGNUM *maxRange,\n\t\t\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtrDynamic( buffer, bufSize ) );\n\tassert( isWritePtr( value1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( value2, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( bufSize >= 32 && bufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\n\t/* Clear return values */\n\tBN_clear( value1 );\n\tBN_clear( value2 );\n\n\tsMemConnect( &stream, buffer, bufSize );\n\n\t/* Read the DL components from the buffer and make sure that they're \n\t   valid, i.e. that they're in the range [1...maxRange - 1] (the lower\n\t   bound is actually DLPPARAM_MIN_SIG_x and not 1, which is > 100 bits).  \n\t   Although nominally intended for DLP algorithms the DLPPARAM_MIN_SIG_x \n\t   values also work for ECC ones since they're also in the DLP family */\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\treadSequence( &stream, NULL );\n\t\t\tstatus = readBignum( &stream, value1, DLPPARAM_MIN_SIG_R,\n\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE, maxRange );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tstatus = readBignum( &stream, value2, DLPPARAM_MIN_SIG_S,\n\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE, maxRange );\n\t\t\tbreak;\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\tstatus = readBignumInteger16Ubits( &stream, value1, \n\t\t\t\t\t\t\t\t\t\t\t   DLPPARAM_MIN_SIG_R,\n\t\t\t\t\t\t\t\t\t\t\t   bytesToBits( CRYPT_MAX_PKCSIZE ),\n\t\t\t\t\t\t\t\t\t\t\t   maxRange );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tstatus = readBignumInteger16Ubits( &stream, value2, \n\t\t\t\t\t\t\t\t\t\t\t   DLPPARAM_MIN_SIG_S,\n\t\t\t\t\t\t\t\t\t\t\t   bytesToBits( CRYPT_MAX_PKCSIZE ),\n\t\t\t\t\t\t\t\t\t\t\t   maxRange );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\t\n#ifdef USE_SSH\n\t\tcase CRYPT_IFORMAT_SSH:\n\t\t\tstatus = importBignum( value1, buffer, 20, DLPPARAM_MIN_SIG_R, \n\t\t\t\t\t\t\t\t   20, maxRange, KEYSIZE_CHECK_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tstatus = importBignum( value2, buffer + 20, 20, DLPPARAM_MIN_SIG_S, \n\t\t\t\t\t\t\t\t   20, maxRange, KEYSIZE_CHECK_NONE );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Clean up */\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckBignum( value1 ) );\n\tENSURES( sanityCheckBignum( value2 ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int decodeECDLValuesFunction( IN_BUFFER( bufSize ) const BYTE *buffer, \n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) const int bufSize, \n\t\t\t\t\t\t\t\t\t INOUT BIGNUM *value1, \n\t\t\t\t\t\t\t\t\t INOUT BIGNUM *value2, \n\t\t\t\t\t\t\t\t\t const BIGNUM *maxRange,\n\t\t\t\t\t\t\t\t\t IN_ENUM( CRYPT_FORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtrDynamic( buffer, bufSize ) );\n\tassert( isWritePtr( value1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( value2, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( bufSize >= 32 && bufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\n\t/* Clear return values */\n\tBN_clear( value1 );\n\tBN_clear( value2 );\n\n\t/* In most cases the DLP and ECDLP formats are identical and we can just\n\t   pass the call on to the DLP form, however SSH uses totally different \n\t   signature formats depending on whether the signature is DSA or ECDSA, \n\t   so we handle the SSH format explicitly here */\n\tif( formatType != CRYPT_IFORMAT_SSH )\n\t\t{\n\t\treturn( decodeDLValuesFunction( buffer, bufSize, value1, value2, \n\t\t\t\t\t\t\t\t\t\tmaxRange, formatType ) );\n\t\t}\n\tsMemConnect( &stream, buffer, bufSize );\n\tstatus = readBignumInteger32( &stream, value1, ECCPARAM_MIN_SIG_R,\n\t\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE_ECC, maxRange );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBignumInteger32( &stream, value2, ECCPARAM_MIN_SIG_S,\n\t\t\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE_ECC, maxRange );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckBignum( value1 ) );\n\tENSURES( sanityCheckBignum( value2 ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPubKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES_V( capabilityInfoPtr != NULL );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\t/* Set the access method pointers */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyDlpFunction );\n\t\tFNPTR_SET( pkcInfo->decodeDLValuesFunction, decodeDLValuesFunction );\n\t\treturn;\n\t\t}\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyEccFunction );\n\t\tFNPTR_SET( pkcInfo->decodeDLValuesFunction, decodeECDLValuesFunction );\n\t\treturn;\n\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\tFNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyRsaFunction );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKeyNullFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT )  \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPubKeyRead( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\n\tFNPTR_SET( pkcInfo->readPublicKeyFunction, readPublicKeyNullFunction );\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/key_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPublic/Private Key Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"context.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/* Although there is a fair amount of commonality between public and private-\n   key functions, we keep them distinct to enforce red/black separation.\n\n   The DLP algorithms split the key components over the information in the\n   AlgorithmIdentifier and the actual public/private key components, with the\n   (p, q, g) set classed as domain parameters and included in the\n   AlgorithmIdentifier and y being the actual key.\n\n\tparams = SEQ {\n\t\tp INTEGER,\n\t\tq INTEGER,\t\t\t\t-- q for DSA\n\t\tg INTEGER,\t\t\t\t-- g for DSA\n\t\tj INTEGER OPTIONAL,\t\t-- X9.42 only\n\t\tvalidationParams [...]\t-- X9.42 only\n\t\t}\n\n\tkey = y INTEGER\t\t\t\t-- g^x mod p\n\n   For peculiar historical reasons (copying errors and the use of obsolete\n   drafts as reference material) the X9.42 interpretation used in PKIX \n   reverses the second two parameters from FIPS 186 (so it uses p, g, q \n   instead of p, q, g), so when we read/write the parameter information we \n   have to switch the order in which we read the values if the algorithm \n   isn't DSA */\n\n#define hasReversedParams( cryptAlgo ) \\\n\t\t( ( cryptAlgo ) == CRYPT_ALGO_DH || \\\n\t\t  ( cryptAlgo ) == CRYPT_ALGO_ELGAMAL )\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_SSH )\n\n/* Write a bignum as a fixed-length value, needed by SSH */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeFixedBignum( INOUT STREAM *stream, const BIGNUM *bignum,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 20 ) const int fixedSize )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint bnLength, noZeroes, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( fixedSize >= 20 && fixedSize <= CRYPT_MAX_PKCSIZE );\n\n\t/* Extract the bignum data and get its length */\n\tstatus = exportBignum( buffer, CRYPT_MAX_PKCSIZE, &bnLength, bignum );\n\tENSURES( cryptStatusOK( status ) );\n\tnoZeroes = fixedSize - bnLength;\n\tREQUIRES( noZeroes >= 0 && noZeroes < fixedSize );\n\n\t/* Write the leading zeroes followed by the bignum value */\n\tLOOP_LARGE( i = 0, i < noZeroes, i++ )\n\t\tsputc( stream, 0 );\n\tENSURES( LOOP_BOUND_OK );\n\tstatus = swrite( stream, buffer, bnLength );\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\t\n\treturn( status );\n\t}\n#endif /* USE_SSH */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Public Keys\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Write X.509 SubjectPublicKeyInfo public keys */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRsaSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int length = sizeofBignum( &rsaKey->rsaParam_n ) + \\\n\t\t\t\t\t   sizeofBignum( &rsaKey->rsaParam_e );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( sanityCheckPKCInfo( rsaKey ) );\n\n\t/* Write the SubjectPublicKeyInfo header field (the +1 is for the \n\t   bitstring) */\n\twriteSequence( stream, sizeofAlgoID( CRYPT_ALGO_RSA ) + \\\n\t\t\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( length ) + 1 ) );\n\twriteAlgoID( stream, CRYPT_ALGO_RSA );\n\n\t/* Write the BIT STRING wrapper and the PKC information */\n\twriteBitStringHole( stream, sizeofShortObject( length ), \n\t\t\t\t\t\tDEFAULT_TAG );\n\twriteSequence( stream, length );\n\twriteBignum( stream, &rsaKey->rsaParam_n );\n\treturn( writeBignum( stream, &rsaKey->rsaParam_e ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeDlpSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int parameterSize = sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofBignum( &dlpKey->dlpParam_p ) + \\\n\t\t\t\t\t\t\t\tsizeofBignum( &dlpKey->dlpParam_q ) + \\\n\t\t\t\t\t\t\t\tsizeofBignum( &dlpKey->dlpParam_g ) );\n\tconst int componentSize = sizeofBignum( &dlpKey->dlpParam_y );\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint totalSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( sanityCheckPKCInfo( dlpKey ) );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\t/* If it's an Elgamal key created by PGP or a DH key from SSL/SSH then \n\t   the q parameter isn't present so we can't write the key in this format */\n\tif( BN_is_zero( &dlpKey->dlpParam_q ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Can't write Elgamal key due to missing q parameter\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* Determine the size of the AlgorithmIdentifier and the BIT STRING-\n\t   encapsulated public-key data (the +1 is for the bitstring) */\n\ttotalSize = sizeofAlgoIDparam( cryptAlgo, parameterSize ) + \\\n\t\t\t\tsizeofShortObject( componentSize + 1 );\n\n\t/* Write the SubjectPublicKeyInfo header field */\n\twriteSequence( stream, totalSize );\n\twriteAlgoIDparam( stream, cryptAlgo, parameterSize );\n\n\t/* Write the parameter data */\n\twriteSequence( stream, sizeofBignum( &dlpKey->dlpParam_p ) + \\\n\t\t\t\t\t\t   sizeofBignum( &dlpKey->dlpParam_q ) + \\\n\t\t\t\t\t\t   sizeofBignum( &dlpKey->dlpParam_g ) );\n\twriteBignum( stream, &dlpKey->dlpParam_p );\n\tif( hasReversedParams( cryptAlgo ) )\n\t\t{\n\t\twriteBignum( stream, &dlpKey->dlpParam_g );\n\t\twriteBignum( stream, &dlpKey->dlpParam_q );\n\t\t}\n\telse\n\t\t{\n\t\twriteBignum( stream, &dlpKey->dlpParam_q );\n\t\twriteBignum( stream, &dlpKey->dlpParam_g );\n\t\t}\n\n\t/* Write the BIT STRING wrapper and the PKC information */\n\twriteBitStringHole( stream, componentSize, DEFAULT_TAG );\n\treturn( writeBignum( stream, &dlpKey->dlpParam_y ) );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeEccSubjectPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tBYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];\n\tint fieldSize DUMMY_INIT, oidSize DUMMY_INIT, encodedPointSize, totalSize;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH ) );\n\tREQUIRES( sanityCheckPKCInfo( eccKey ) );\n\n\t/* Get the information that we'll need to encode the key.  Note that \n\t   this assumes that we'll be using a known (named) curve rather than\n\t   arbitrary curve parameters, which has been enforced by the higher-\n\t   level code */\n\tstatus = getECCFieldSize( eccKey->curveType, &fieldSize, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = oidSize = sizeofECCOID( eccKey->curveType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get the encoded point data */\n\tstatus = exportECCPoint( buffer, MAX_PKCSIZE_ECCPOINT, &encodedPointSize, \n\t\t\t\t\t\t\t &eccKey->eccParam_qx, &eccKey->eccParam_qy, \n\t\t\t\t\t\t\t fieldSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine the size of the AlgorithmIdentifier and the BIT STRING-\n\t   encapsulated public-key data (the final +1 is for the bitstring),\n\t   ECC algorithms are a bit strange because there's no specific type of \n\t   \"ECDSA key\" or \"ECDH key\" or whatever, just a generic \"ECC key\", so \n\t   if we're given an ECDH key we write it as a generic ECC key, denoted \n\t   using the generic identifier CRYPT_ALGO_ECDSA */\n\tstatus = totalSize = sizeofAlgoIDparam( CRYPT_ALGO_ECDSA, oidSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalSize += sizeofShortObject( encodedPointSize + 1 );\n\n\t/* Write the SubjectPublicKeyInfo header field */\n\twriteSequence( stream, totalSize );\n\twriteAlgoIDparam( stream, CRYPT_ALGO_ECDSA, oidSize );\n\twriteECCOID( stream, eccKey->curveType );\n\n\t/* Write the BIT STRING wrapper and the PKC information */\n\twriteBitStringHole( stream, encodedPointSize, DEFAULT_TAG );\n\tstatus = swrite( stream, buffer, encodedPointSize );\n\tzeroise( buffer, MAX_PKCSIZE_ECCPOINT );\n\treturn( status );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_SSH\n\n/* Write SSHv2 public keys:\n\n   RSA/DSA:\n\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\tmpint\te\t\t\tp\n\t\tmpint\tn\t\t\tq\n\t\tmpint\t\t\t\tg\n\t\tmpint\t\t\t\ty\n\n   ECDSA:\n\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ecdsa-sha2-*\"\n\t\tstring\t\"*\"\t\t\t\t-- The \"*\" portion from the above field\n\t\tstring\tQ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSshRsaPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( sanityCheckPKCInfo( rsaKey ) );\n\n\twriteUint32( stream, sizeofString32( 7 ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &rsaKey->rsaParam_e ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &rsaKey->rsaParam_n ) );\n\twriteString32( stream, \"ssh-rsa\", 7 );\n\twriteBignumInteger32( stream, &rsaKey->rsaParam_e );\n\treturn( writeBignumInteger32( stream, &rsaKey->rsaParam_n ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSshDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA ) );\n\tREQUIRES( sanityCheckPKCInfo( dlpKey ) );\n\n\t/* SSHv2 uses PKCS #3 rather than X9.42-style DH keys so we have to \n\t   treat this algorithm type specially */\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH )\n\t\t{\n\t\tconst DH_DOMAINPARAMS *domainParams = dlpKey->domainParams;\n\t\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t\t  &domainParams->p : &dlpKey->dlpParam_p;\n\t\tconst BIGNUM *g = ( domainParams != NULL ) ? \\\n\t\t\t\t\t\t  &domainParams->g : &dlpKey->dlpParam_g;\n\n\t\twriteUint32( stream, sizeofString32( 6 ) + \\\n\t\t\t\t\t\t\t sizeofBignumInteger32( p ) + \\\n\t\t\t\t\t\t\t sizeofBignumInteger32( g ) );\n\t\twriteString32( stream, \"ssh-dh\", 6 );\n\t\twriteBignumInteger32( stream, p );\n\t\treturn( writeBignumInteger32( stream, g ) );\n\t\t}\n\n\twriteUint32( stream, sizeofString32( 7 ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &dlpKey->dlpParam_p ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &dlpKey->dlpParam_q ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &dlpKey->dlpParam_g ) + \\\n\t\t\t\t\t\t sizeofBignumInteger32( &dlpKey->dlpParam_y ) );\n\twriteString32( stream, \"ssh-dss\", 7 );\n\twriteBignumInteger32( stream, &dlpKey->dlpParam_p );\n\twriteBignumInteger32( stream, &dlpKey->dlpParam_q );\n\twriteBignumInteger32( stream, &dlpKey->dlpParam_g );\n\treturn( writeBignumInteger32( stream, &dlpKey->dlpParam_y ) );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSshEccPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst char *algoName, *paramName;\n\tBYTE buffer[ MAX_PKCSIZE_ECCPOINT + 8 ];\n\tint fieldSize, encodedPointSize DUMMY_INIT;\n\tint algoNameLen, paramNameLen, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\tREQUIRES( sanityCheckPKCInfo( eccKey ) );\n\n\t/* Get the string form of the curve parameters */\n\tswitch( eccKey->curveType )\n\t\t{\n\t\tcase CRYPT_ECCCURVE_P256:\n\t\t\talgoName = \"ecdsa-sha2-nistp256\";\n\t\t\talgoNameLen = 19;\n\t\t\tparamName = \"nistp256\";\n\t\t\tparamNameLen = 8;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_P384:\n\t\t\talgoName = \"ecdsa-sha2-nistp384\";\n\t\t\talgoNameLen = 19;\n\t\t\tparamName = \"nistp384\";\n\t\t\tparamNameLen = 8;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ECCCURVE_P521:\n\t\t\talgoName = \"ecdsa-sha2-nistp521\";\n\t\t\talgoNameLen = 19;\n\t\t\tparamName = \"nistp521\";\n\t\t\tparamNameLen = 8;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Get the information that we'll need to encode the key and the encoded\n\t   point data.  Note that this assumes that we'll be using a known \n\t   (named) curve rather than arbitrary curve parameters, which has been \n\t   enforced by the higher-level code */\n\tstatus = getECCFieldSize( eccKey->curveType, &fieldSize, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = exportECCPoint( buffer, MAX_PKCSIZE_ECCPOINT, \n\t\t\t\t\t\t\t\t &encodedPointSize, &eccKey->eccParam_qx, \n\t\t\t\t\t\t\t\t &eccKey->eccParam_qy, fieldSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the PKC information */\n\twriteUint32( stream, sizeofString32( algoNameLen ) + \\\n\t\t\t\t\t\t sizeofString32( paramNameLen ) + \\\n\t\t\t\t\t\t sizeofString32( encodedPointSize ) );\n\twriteString32( stream, algoName, algoNameLen );\n\twriteString32( stream, paramName, paramNameLen );\n\tstatus = writeString32( stream, buffer, encodedPointSize );\n\tzeroise( buffer, MAX_PKCSIZE_ECCPOINT );\n\treturn( status );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n#endif /* USE_SSH */\n\n#ifdef USE_SSL\n\n/* Write SSL public keys:\n\n\tDH:\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t  [\tuint16\t\tdh_qLen\n\t\tbyte[]\t\tdh_q\t\t-- For TLS-ext format ]\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t  [\tuint16\t\tdh_YsLen ]\n\t  [\tbyte[]\t\tdh_Ys\t ]\n\n\tECDH:\n\t\tbyte\t\tcurveType\n\t\tuint16\t\tnamedCurve\n\t  [\tuint8\t\tecPointLen\t-- NB uint8 not uint16 ]\n\t  [\tbyte[]\t\tecPoint ]\n\n   The DH y value is nominally attached to the DH p and g values but isn't \n   processed at this level since this is a pure PKCS #3 DH key and not a \n   generic DLP key.  The same holds for the ECDH Q value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSslDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t const BOOLEAN writeExtKey )\n\t{\n\tconst PKC_INFO *dhKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH );\n\tREQUIRES( sanityCheckPKCInfo( dhKey ) );\n\tREQUIRES( writeExtKey == TRUE || writeExtKey == FALSE );\n\n\tif( dhKey->domainParams != NULL )\n\t\t{\n\t\tconst DH_DOMAINPARAMS *domainParams = dhKey->domainParams;\n\n\t\twriteBignumInteger16U( stream, &domainParams->p );\n\t\tif( writeExtKey )\n\t\t\twriteBignumInteger16U( stream, &domainParams->q ); \n\t\treturn( writeBignumInteger16U( stream, &domainParams->g ) );\n\t\t}\n\twriteBignumInteger16U( stream, &dhKey->dlpParam_p );\n\tif( writeExtKey )\n\t\twriteBignumInteger16U( stream, &dhKey->dlpParam_q );\n\treturn( writeBignumInteger16U( stream, &dhKey->dlpParam_g ) );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nstatic const MAP_TABLE sslCurveInfo[] = {\n\t{ CRYPT_ECCCURVE_P256, 23 },\n\t{ CRYPT_ECCCURVE_P384, 24 },\n\t{ CRYPT_ECCCURVE_P521, 25 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P256, 26 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P384, 26 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P512, 27 },\n\t{ CRYPT_ERROR, 0 }, \n\t\t{ CRYPT_ERROR, 0 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getEccSslInfoTbl( OUT const MAP_TABLE **sslInfoTblPtr,\n\t\t\t\t\t\t\t OUT_INT_Z int *noSslInfoTblEntries )\n\t{\n\tassert( isReadPtr( sslInfoTblPtr, sizeof( MAP_TABLE * ) ) );\n\tassert( isWritePtr( noSslInfoTblEntries, sizeof( int ) ) );\n\n\t*sslInfoTblPtr = sslCurveInfo;\n\t*noSslInfoTblEntries = FAILSAFE_ARRAYSIZE( sslCurveInfo, MAP_TABLE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSslEccPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst MAP_TABLE *sslCurveInfoPtr;\n\tint curveID, sslCurveInfoNoEntries, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH );\n\tREQUIRES( sanityCheckPKCInfo( eccKey ) );\n\n\t/* Look up the SSL NamedCurve ID based on the curve ID */\n\tstatus = getEccSslInfoTbl( &sslCurveInfoPtr, &sslCurveInfoNoEntries );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = mapValue( eccKey->curveType, &curveID, sslCurveInfoPtr, \n\t\t\t\t\t   sslCurveInfoNoEntries );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tsputc( stream, 0x03 );\t/* NamedCurve */\n\treturn( writeUint16( stream, curveID ) );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n#endif /* USE_SSL */\n\n#ifdef USE_PGP\n\n/* Write PGP public keys:\n\n\tbyte\t\tversion\n\tuint32\t\tcreationTime\n\tbyte\t\tRSA\t\tDSA\t\tElgamal\n\tmpi\t\t\tn\t\tp\t\tp\n\tmpi\t\t\te\t\tq\t\tg\n\tmpi\t\t\t\t\tg\t\ty\n\tmpi\t\t\t\t\ty */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writePgpKeyHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  const PKC_INFO *pkcInfo,\n\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tint pgpAlgo, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( pkcInfo->pgpCreationTime == 0 || \\\n\t\t\t  pkcInfo->pgpCreationTime > MIN_TIME_VALUE );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\n\tsputc( stream, PGP_VERSION_OPENPGP );\n\tif( pkcInfo->pgpCreationTime == 0 )\n\t\t{\n\t\t/* The creation time may be zero for a key coming from a non-PGP \n\t\t   source */\n\t\twriteUint32( stream, 0 );\n\t\t}\n\telse\n\t\twriteUint32Time( stream, pkcInfo->pgpCreationTime );\n\tstatus = cryptlibToPgpAlgo( cryptAlgo, &pgpAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sputc( stream, pgpAlgo ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writePgpRsaPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( sanityCheckPKCInfo( rsaKey ) );\n\n\tstatus = writePgpKeyHeader( stream, rsaKey, CRYPT_ALGO_RSA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteBignumInteger16Ubits( stream, &rsaKey->rsaParam_n );\n\treturn( writeBignumInteger16Ubits( stream, &rsaKey->rsaParam_e ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writePgpDlpPublicKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( sanityCheckPKCInfo( dlpKey ) );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\tstatus = writePgpKeyHeader( stream, dlpKey, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteBignumInteger16Ubits( stream, &dlpKey->dlpParam_p );\n\tif( cryptAlgo == CRYPT_ALGO_DSA )\n\t\twriteBignumInteger16Ubits( stream, &dlpKey->dlpParam_q );\n\twriteBignumInteger16Ubits( stream, &dlpKey->dlpParam_g );\n\treturn( writeBignumInteger16Ubits( stream, &dlpKey->dlpParam_y ) );\n\t}\n#endif /* USE_PGP */\n\n/* Umbrella public-key write functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePublicKeyRsaFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_FIXED( 10 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 10 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 10 || memcmp( accessKey, \"public_key\", 10 ) )\n\t\tretIntError();\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\treturn( writeRsaSubjectPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\treturn( writeSshRsaPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_SSH */\n\n#ifdef USE_SSH1\n\t\tcase KEYFORMAT_SSH1:\n\t\t\treturn( writeSsh1RsaPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_SSH1 */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\treturn( writePgpRsaPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_PGP */\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePublicKeyDlpFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_FIXED( 10 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 10 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 10 || memcmp( accessKey, \"public_key\", 10 ) )\n\t\tretIntError();\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\treturn( writeDlpSubjectPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\treturn( writeSshDlpPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_SSH */\n\n#ifdef USE_SSL\n\t\tcase KEYFORMAT_SSL:\n\t\tcase KEYFORMAT_SSL_EXT:\n\t\t\treturn( writeSslDlpPublicKey( stream, contextInfoPtr,\n\t\t\t\t\t\t\t\t\t( formatType == KEYFORMAT_SSL_EXT ) ? \\\n\t\t\t\t\t\t\t\t\t  TRUE : FALSE ) );\n#endif /* USE_SSL */\n\n#ifdef USE_PGP\n\t\tcase KEYFORMAT_PGP:\n\t\t\treturn( writePgpDlpPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_PGP */\n\t\t}\n\n\tretIntError();\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePublicKeyEccFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t  const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_FIXED( 10 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDH ) );\n\tREQUIRES( formatType == KEYFORMAT_CERT || formatType == KEYFORMAT_SSL || \\\n\t\t\t  formatType == KEYFORMAT_SSL_EXT || formatType == KEYFORMAT_SSH );\n\tREQUIRES( accessKeyLen == 10 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 10 || memcmp( accessKey, \"public_key\", 10 ) )\n\t\tretIntError();\n\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase KEYFORMAT_CERT:\n\t\t\treturn( writeEccSubjectPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_INT_ASN1 */\n\n\n#ifdef USE_SSL\n\t\tcase KEYFORMAT_SSL:\n\t\tcase KEYFORMAT_SSL_EXT:\n\t\t\treturn( writeSslEccPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_SSL */\n\n#ifdef USE_SSH\n\t\tcase KEYFORMAT_SSH:\n\t\t\treturn( writeSshEccPublicKey( stream, contextInfoPtr ) );\n#endif /* USE_SSH */\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Private Keys\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Write private keys */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRsaPrivateKey( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint length = sizeofBignum( &rsaKey->rsaParam_p ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_q );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( sanityCheckPKCInfo( rsaKey ) );\n\n\t/* Add the length of any optional components that may be present */\n\tif( !BN_is_zero( &rsaKey->rsaParam_exponent1 ) )\n\t\t{\n\t\tlength += sizeofBignum( &rsaKey->rsaParam_exponent1 ) + \\\n\t\t\t\t  sizeofBignum( &rsaKey->rsaParam_exponent2 ) + \\\n\t\t\t\t  sizeofBignum( &rsaKey->rsaParam_u );\n\t\t}\n\n\t/* Write the the PKC fields */\n\twriteSequence( stream, length );\n\twriteBignumTag( stream, &rsaKey->rsaParam_p, 3 );\n\tif( BN_is_zero( &rsaKey->rsaParam_exponent1 ) )\n\t\treturn( writeBignumTag( stream, &rsaKey->rsaParam_q, 4 ) );\n\twriteBignumTag( stream, &rsaKey->rsaParam_q, 4 );\n\twriteBignumTag( stream, &rsaKey->rsaParam_exponent1, 5 );\n\twriteBignumTag( stream, &rsaKey->rsaParam_exponent2, 6 );\n\treturn( writeBignumTag( stream, &rsaKey->rsaParam_u, 7 ) );\n\t}\n\n#ifdef USE_PKCS12\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRsaPrivateKeyOld( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst PKC_INFO *rsaKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst BIGNUM *d = &rsaKey->rsaParam_d;\n\tBOOLEAN calculatedPrivateExponent = FALSE;\n\tint length = sizeofShortInteger( 0 ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_n ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_e ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_p ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_q ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_exponent1 ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_exponent2 ) + \\\n\t\t\t\t sizeofBignum( &rsaKey->rsaParam_u );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( sanityCheckPKCInfo( rsaKey ) );\n\n\t/* The older format is somewhat restricted in terms of what can be\n\t   written since all components must be present, even the ones that are\n\t   never used (if d isn't present we calculate it on the fly, see \n\t   below).  If anything is missing we can't write the key since nothing \n\t   would be able to read it */\n\tif( BN_is_zero( &rsaKey->rsaParam_n ) || \\\n\t\tBN_is_zero( &rsaKey->rsaParam_p ) || \\\n\t\tBN_is_zero( &rsaKey->rsaParam_exponent1 ) )\n\t\t{\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* If the private-key d value isn't present, calculate it from p and q.\n\t   This is the most common missing value since it's not needed for the\n\t   CRT so we calculate a temporary value for this if it's not present.\n\n\t   This is somewhat ugly in that we're both messing with a const \n\t   parameter and performing complex bignum ops as part of what should\n\t   only be a straight data write, but there's no easy way around this \n\t   unless we create and manage our own bignum data values here */\n\tif( BN_is_zero( d ) )\n\t\t{\n\t\tBIGNUM *tmp = ( BIGNUM * ) &rsaKey->tmp1;\n\t\tint bnStatus = BN_STATUS;\n\n\t\t/* Use the extended Euclidean algorithm to calculate d from p and q:\n\n\t\t\tphi( n ) = (p - 1) * (q - 1) \n\t\t\t\t\t = n - p - q + 1\n\t\t\td = e^-1 % phi( n ) */\n\t\tCKPTR( BN_copy( tmp, &rsaKey->rsaParam_n ) );\n\t\tCK( BN_sub( tmp, tmp, &rsaKey->rsaParam_p ) );\n\t\tCK( BN_sub( tmp, tmp, &rsaKey->rsaParam_q ) );\n\t\tCK( BN_add_word( tmp, 1 ) );\n\t\tCKPTR( BN_mod_inverse( tmp, &rsaKey->rsaParam_e, tmp, \n\t\t\t\t\t\t\t   ( BN_CTX * ) &rsaKey->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\td = tmp;\n\t\tcalculatedPrivateExponent = TRUE;\n\t\t}\n\tlength += sizeofBignum( d );\n\n\t/* Write the the PKC fields */\n\twriteSequence( stream, sizeofShortInteger( 0 ) + \\\n\t\t\t\t\t\t   sizeofAlgoID( CRYPT_ALGO_RSA ) + \\\n\t\t\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( length ) ) );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\twriteAlgoID( stream, CRYPT_ALGO_RSA );\n\twriteOctetStringHole( stream, sizeofShortObject( length ), \n\t\t\t\t\t\t  DEFAULT_TAG );\n\twriteSequence( stream, length );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\twriteBignum( stream, &rsaKey->rsaParam_n );\n\twriteBignum( stream, &rsaKey->rsaParam_e );\n\twriteBignum( stream, d );\n\twriteBignum( stream, &rsaKey->rsaParam_p );\n\twriteBignum( stream, &rsaKey->rsaParam_q );\n\twriteBignum( stream, &rsaKey->rsaParam_exponent1 );\n\twriteBignum( stream, &rsaKey->rsaParam_exponent2 );\n\tstatus = writeBignum( stream, &rsaKey->rsaParam_u );\n\tif( calculatedPrivateExponent )\n\t\tBN_clear( ( BIGNUM * ) d );\n\n\treturn( status );\n\t}\n#endif /* USE_PKCS12 */\n\n/* Umbrella private-key write functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePrivateKeyRsaFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t   IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_FIXED( 11 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RSA );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 11 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 11 || memcmp( accessKey, \"private_key\", 11 ) || \\\n\t\t( formatType != KEYFORMAT_PRIVATE && \\\n\t\t  formatType != KEYFORMAT_PRIVATE_OLD ) )\n\t\tretIntError();\n\n\tswitch( formatType )\n\t\t{\n\t\tcase KEYFORMAT_PRIVATE:\n\t\t\treturn( writeRsaPrivateKey( stream, contextInfoPtr ) );\n\n#ifdef USE_PKCS12\n\t\tcase KEYFORMAT_PRIVATE_OLD:\n\t\t\treturn( writeRsaPrivateKeyOld( stream, contextInfoPtr ) );\n#endif /* USE_PKCS12 */\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePrivateKeyDlpFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t   IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_FIXED( 11 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst PKC_INFO *dlpKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t\tcapabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ELGAMAL ) );\n\tREQUIRES( sanityCheckPKCInfo( dlpKey ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 11 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 11 || memcmp( accessKey, \"private_key\", 11 ) || \\\n\t\tformatType != KEYFORMAT_PRIVATE )\n\t\tretIntError();\n\n\t/* When we're generating a DH key ID only p, q, and g are initialised so \n\t   we write a special-case zero y value.  This is a somewhat ugly side-\n\t   effect of the odd way in which DH \"public keys\" work */\n\tif( BN_is_zero( &dlpKey->dlpParam_y ) )\n\t\treturn( writeShortInteger( stream, 0, DEFAULT_TAG ) );\n\n\t/* Write the key components */\n\treturn( writeBignum( stream, &dlpKey->dlpParam_x ) );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePrivateKeyEccFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t   IN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_FIXED( 11 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tconst PKC_INFO *eccKey = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_ECDSA );\n\tREQUIRES( sanityCheckPKCInfo( eccKey ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 11 );\n\n\t/* Make sure that we really intended to call this function */\n\tif( accessKeyLen != 11 || memcmp( accessKey, \"private_key\", 11 ) || \\\n\t\tformatType != KEYFORMAT_PRIVATE )\n\t\tretIntError();\n\n\t/* Write the key components */\n\treturn( writeBignum( stream, &eccKey->eccParam_d ) );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite Flat Public Key Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* If the keys are stored in a crypto device rather than being held in the\n   context all that we'll have available are the public components in flat \n   format.  The following code writes flat-format public components in the \n   X.509 SubjectPublicKeyInfo format.  The parameters are:\n\n\tAlgo\tComp1\tComp2\tComp3\tComp4\n\t----\t-----\t-----\t-----\t-----\n\tRSA\t\t  n\t\t  e\t\t  -\t\t  -\n\tDLP\t\t  p\t\t  q\t\t  g\t\t  y \n\tECDLP\t  point\t  -\t\t  -\t\t  - */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 6 ) ) \\\nint writeFlatPublicKey( OUT_BUFFER_OPT( bufMaxSize, *bufSize ) void *buffer, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int bufMaxSize, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( bufMaxSize ) int *bufSize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t\tIN_RANGE( 0, 100 ) const int intParam,\n\t\t\t\t\t\tIN_BUFFER( component1Length ) const void *component1, \n\t\t\t\t\t\tIN_LENGTH_PKC const int component1Length,\n\t\t\t\t\t\tIN_BUFFER( component2Length ) const void *component2, \n\t\t\t\t\t\tIN_LENGTH_PKC const int component2Length,\n\t\t\t\t\t\tIN_BUFFER_OPT( component3Length ) const void *component3, \n\t\t\t\t\t\tIN_LENGTH_PKC_Z const int component3Length,\n\t\t\t\t\t\tIN_BUFFER_OPT( component4Length ) const void *component4, \n\t\t\t\t\t\tIN_LENGTH_PKC_Z const int component4Length )\n\t{\n\tSTREAM stream;\n\tconst int comp1Size = sizeofInteger( component1, component1Length );\n\tconst int comp2Size = ( component2 == NULL ) ? 0 : \\\n\t\t\t\t\t\t  sizeofInteger( component2, component2Length );\n\tconst int comp3Size = ( component3 == NULL ) ? 0 : \\\n\t\t\t\t\t\t  sizeofInteger( component3, component3Length );\n\tint parameterSize, componentSize, totalSize, status;\n\n\tassert( ( buffer == NULL && bufMaxSize == 0 ) || \\\n\t\t\tisWritePtrDynamic( buffer, bufMaxSize ) );\n\tassert( isWritePtr( bufSize, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( component1, component1Length ) );\n\tassert( component2 == NULL || \\\n\t\t\tisReadPtrDynamic( component2, component2Length ) );\n\tassert( component3 == NULL || \\\n\t\t\tisReadPtrDynamic( component3, component3Length ) );\n\tassert( component4 == NULL || \\\n\t\t\tisReadPtrDynamic( component4, component4Length ) );\n\n\tREQUIRES( ( buffer == NULL && bufMaxSize == 0 ) || \\\n\t\t\t  ( buffer != NULL && \\\n\t\t\t    bufMaxSize > 64 && bufMaxSize < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( ( isEccAlgo( cryptAlgo ) && \\\n\t\t\t\tintParam > CRYPT_ECCCURVE_NONE && \\\n\t\t\t\tintParam < CRYPT_ECCCURVE_LAST ) || \\\n\t\t\t  ( !isEccAlgo( cryptAlgo ) && intParam == 0 ) );\n\tREQUIRES( ( isEccAlgo( cryptAlgo ) && \\\n\t\t\t\tcomponent1Length >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t\tcomponent1Length <= MAX_PKCSIZE_ECCPOINT ) || \\\n\t\t\t  ( !isEccAlgo( cryptAlgo ) && \\\n\t\t\t\tcomponent1Length >= MIN_PKCSIZE && \\\n\t\t\t\tcomponent1Length <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( component1 != NULL && \\\n\t\t\t  component1Length >= 1 && component1Length <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( ( isEccAlgo( cryptAlgo ) && component2 == NULL && \\\n\t\t\t\tcomponent2Length == 0 ) || \\\n\t\t\t  ( !isEccAlgo( cryptAlgo ) && component2 != NULL && \\\n\t\t\t\tcomponent2Length >= 1 && component2Length <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( ( component3 == NULL && component3Length == 0 ) || \\\n\t\t\t  ( component3 != NULL && \\\n\t\t\t\tcomponent3Length >= 1 && component3Length <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( ( component4 == NULL && component4Length == 0 ) || \\\n\t\t\t  ( component4 != NULL && \\\n\t\t\t\tcomponent4Length >= 1 && component4Length <= CRYPT_MAX_PKCSIZE ) );\n\n\t/* Clear return values */\n\tif( buffer != NULL )\n\t\tmemset( buffer, 0, min( 16, bufMaxSize ) );\n\t*bufSize = 0;\n\n\t/* Calculate the size of the algorithm parameters and the public key \n\t   components */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_DH:\n\t\tcase CRYPT_ALGO_DSA:\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tREQUIRES( component3 != NULL && component4 != NULL );\n\n\t\t\tparameterSize = sizeofShortObject( comp1Size + comp2Size + \\\n\t\t\t\t\t\t\t\t\t\t\t\t  comp3Size );\n\t\t\tcomponentSize = sizeofInteger( component4, component4Length );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tREQUIRES( component3 == NULL && component4 == NULL );\n\n\t\t\tparameterSize = 0;\n\t\t\tcomponentSize = sizeofShortObject( comp1Size + comp2Size );\n\t\t\tbreak;\n\n#if defined( USE_ECDSA )\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tREQUIRES( component2 == NULL && component3 == NULL && \\\n\t\t\t\t\t  component4 == NULL );\n\n\t\t\tparameterSize = sizeofECCOID( intParam );\n\t\t\tENSURES( !cryptStatusError( parameterSize ) );\n\t\t\tcomponentSize = component1Length;\n\t\t\t\t\t\t\t/* ECDSA doesn't use INTEGER wrapping */\n\t\t\tbreak;\n#endif /* USE_ECDSA */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Determine the size of the AlgorithmIdentifier and the BIT STRING-\n\t   encapsulated public-key data (the +1 is for the bitstring) */\n\tstatus = totalSize = sizeofAlgoIDparam( cryptAlgo, parameterSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalSize += sizeofShortObject( componentSize + 1 );\n\tif( buffer == NULL )\n\t\t{\n\t\t/* It's a size-check call, return the overall size */\n\t\t*bufSize = sizeofShortObject( totalSize );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tsMemOpen( &stream, buffer, bufMaxSize );\n\n\t/* Write the SubjectPublicKeyInfo header field */\n\twriteSequence( &stream, totalSize );\n\twriteAlgoIDparam( &stream, cryptAlgo, parameterSize );\n\n\t/* Write the parameter data if necessary */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\twriteSequence( &stream, comp1Size + comp2Size + comp3Size );\n\t\twriteInteger( &stream, component1, component1Length, DEFAULT_TAG );\n\t\tif( hasReversedParams( cryptAlgo ) )\n\t\t\t{\n\t\t\twriteInteger( &stream, component3, component3Length, DEFAULT_TAG );\n\t\t\twriteInteger( &stream, component2, component2Length, DEFAULT_TAG );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\twriteInteger( &stream, component2, component2Length, DEFAULT_TAG );\n\t\t\twriteInteger( &stream, component3, component3Length, DEFAULT_TAG );\n\t\t\t}\n\t\t}\n#if defined( USE_ECDSA )\n\telse\n\t\t{\n\t\tif( isEccAlgo( cryptAlgo ) )\n\t\t\twriteECCOID( &stream, intParam );\n\t\t}\n#endif /* USE_ECDSA */\n\n\t/* Write the BIT STRING wrapper and the PKC information */\n\twriteBitStringHole( &stream, componentSize, DEFAULT_TAG );\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\twriteSequence( &stream, comp1Size + comp2Size );\n\t\twriteInteger( &stream, component1, component1Length, DEFAULT_TAG );\n\t\tstatus = writeInteger( &stream, component2, component2Length, \n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\telse\n\t\t{\n\t\tif( isEccAlgo( cryptAlgo ) )\n\t\t\tstatus = swrite( &stream, component1, component1Length );\n\t\telse\n\t\t\tstatus = writeInteger( &stream, component4, component4Length, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*bufSize = stell( &stream );\n\n\t/* Clean up */\n\tsMemDisconnect( &stream );\n\treturn( status );\n\t}\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite DL Values\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike the simpler RSA PKC, DL-based PKCs produce a pair of values that\n   need to be encoded as structured data.  The following two functions \n   perform this en/decoding.  SSH assumes that DLP values are two fixed-size\n   blocks of 20 bytes so we can't use the normal read/write routines to \n   handle these values */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int encodeDLValuesFunction( OUT_BUFFER( bufMaxSize, \\\n\t\t\t\t\t\t\t\t\t\t\t   *bufSize ) BYTE *buffer, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 20 + 20 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int bufMaxSize, \n\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( bufMaxSize ) \\\n\t\t\t\t\t\t\t\t\t\tint *bufSize, \n\t\t\t\t\t\t\t\t   const BIGNUM *value1, \n\t\t\t\t\t\t\t\t   const BIGNUM *value2, \n\t\t\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tSTREAM stream;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtrDynamic( buffer, bufMaxSize ) );\n\tassert( isWritePtr( bufSize, sizeof( int ) ) );\n\tassert( isReadPtr( value1, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( value2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( bufMaxSize >= 40 && bufMaxSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckBignum( value1 ) );\n\tREQUIRES( sanityCheckBignum( value2 ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bufMaxSize ) );\n\t*bufSize = 0;\n\n\tsMemOpen( &stream, buffer, bufMaxSize );\n\n\t/* Write the DL components to the buffer */\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_ASN1\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\twriteSequence( &stream, sizeofBignum( value1 ) + \\\n\t\t\t\t\t\t\t\t\tsizeofBignum( value2 ) );\n\t\t\twriteBignum( &stream, value1 );\n\t\t\tstatus = writeBignum( &stream, value2 );\n\t\t\tbreak;\n#endif /* USE_INT_ASN1 */\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\twriteBignumInteger16Ubits( &stream, value1 );\n\t\t\tstatus = writeBignumInteger16Ubits( &stream, value2 );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n#ifdef USE_SSH\n\t\tcase CRYPT_IFORMAT_SSH:\n\t\t\t/* SSH uses an awkward and horribly inflexible fixed format with \n\t\t\t   each of the nominally 160-bit DLP values at fixed positions \n\t\t\t   in a 2 x 20-byte buffer, so we have to write the bignums as\n\t\t\t   fixed-size value */\n\t\t\tstatus = writeFixedBignum( &stream, value1, 20 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = writeFixedBignum( &stream, value2, 20 );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*bufSize = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int encodeECDLValuesFunction( OUT_BUFFER( bufMaxSize, \\\n\t\t\t\t\t\t\t\t\t\t\t\t *bufSize ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 20 + 20 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int bufMaxSize, \n\t\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxSize ) \\\n\t\t\t\t\t\t\t\t\t\tint *bufSize, \n\t\t\t\t\t\t\t\t\t const BIGNUM *value1, \n\t\t\t\t\t\t\t\t\t const BIGNUM *value2, \n\t\t\t\t\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tSTREAM stream;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtrDynamic( buffer, bufMaxSize ) );\n\tassert( isWritePtr( bufSize, sizeof( int ) ) );\n\tassert( isReadPtr( value1, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( value2, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( bufMaxSize >= 40 && bufMaxSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckBignum( value1 ) );\n\tREQUIRES( sanityCheckBignum( value2 ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bufMaxSize ) );\n\t*bufSize = 0;\n\n\t/* In most cases the DLP and ECDLP formats are identical and we can just\n\t   pass the call on to the DLP form, however SSH uses totally different \n\t   signature formats depending on whether the signature is DSA or ECDSA, \n\t   so we handle the SSH format explicitly here */\n\tif( formatType != CRYPT_IFORMAT_SSH )\n\t\t{\n\t\treturn( encodeDLValuesFunction( buffer, bufMaxSize, bufSize, \n\t\t\t\t\t\t\t\t\t\tvalue1, value2, formatType ) );\n\t\t}\n\tsMemOpen( &stream, buffer, bufMaxSize );\n\twriteBignumInteger32( &stream, value1 );\n\tstatus = writeBignumInteger32( &stream, value2 );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*bufSize = length;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef USE_INT_ASN1\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writePrivateKeyNullFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\tconst CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\tIN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER( accessKeyLen ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst char *accessKey, \n\t\t\t\t\t\t\t\t\t\tIN_LENGTH_FIXED( 11 ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int accessKeyLen )\n\t{\n\tUNUSED_ARG( stream );\n\tUNUSED_ARG( contextInfoPtr );\n\tUNUSED_ARG( accessKey );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* USE_INT_ASN1 */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyWrite( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES_V( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES_V( capabilityInfoPtr != NULL );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\n\t/* Set the access method pointers */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->writePublicKeyFunction, writePublicKeyDlpFunction );\n#ifdef USE_INT_ASN1\n\t\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyDlpFunction );\n#else\n\t\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyNullFunction );\n#endif /* USE_INT_ASN1 */\n\t\tFNPTR_SET( pkcInfo->encodeDLValuesFunction, encodeDLValuesFunction );\n\n\t\treturn;\n\t\t}\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tFNPTR_SET( pkcInfo->writePublicKeyFunction, writePublicKeyEccFunction );\n#ifdef USE_INT_ASN1\n\t\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyEccFunction );\n#else\n\t\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyNullFunction );\n#endif /* USE_INT_ASN1 */\n\t\tFNPTR_SET( pkcInfo->encodeDLValuesFunction, encodeECDLValuesFunction );\n\n\t\treturn;\n\t\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\tFNPTR_SET( pkcInfo->writePublicKeyFunction, writePublicKeyRsaFunction );\n#ifdef USE_INT_ASN1\n\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyRsaFunction );\n#else\n\tFNPTR_SET( pkcInfo->writePrivateKeyFunction, writePrivateKeyNullFunction );\n#endif /* USE_INT_ASN1 */\n\t}\n#else\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyWrite( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/keygen.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKC Keygen Header File \t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1997-2015\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _KEYGEN_DEFINED\n\n#define _KEYGEN_DEFINED\n\n/* The number of iterations of Miller-Rabin for an error probbility of\n   (1/2)^80, from HAC */\n\n#define getNoPrimeChecks( noBits ) \\\n\t( ( noBits < 150 ) ? 18 : ( noBits < 200 ) ? 15 : \\\n\t  ( noBits < 250 ) ? 12 : ( noBits < 300 ) ? 9 : \\\n\t  ( noBits < 350 ) ? 8 : ( noBits < 400 ) ? 7 : \\\n\t  ( noBits < 500 ) ? 6 : ( noBits < 600 ) ? 5 : \\\n\t  ( noBits < 800 ) ? 4 : ( noBits < 1250 ) ? 3 : 2 )\n\n/* The size of the prime sieve array, 1 memory page (on most CPUs) = 4K \n   candidate values.  When changing this value the LFSR parameters need to \n   be adjusted to match */\n\n#define SIEVE_SIZE\t\t\t\t4096\n\n/* Random-data access function, used to allow deterministic prime generation \n   when generating DLP parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\ntypedef int ( *GETRANDOMDATA_FUNCTION )( INOUT_OPT void *randomState,\n\t\t\t\t\t\t\t\t\t\t OUT_BUFFER_FIXED( noBytes ) void *buffer, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int noBytes  );\ntypedef struct { \n\tFNPTR getRandomFunction;\n\tvoid *getRandomState;\n\t} GET_RANDOM_INFO;\n\n/* Prototypes for functions in ctx_bsieve.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint initSieve( IN_ARRAY( sieveSize ) BOOLEAN *sieveArray, \n\t\t\t   IN_LENGTH_FIXED( SIEVE_SIZE ) const int sieveSize,\n\t\t\t   const BIGNUM *candidate );\nCHECK_RETVAL_RANGE( 0, SIEVE_SIZE ) \\\nint nextSievePosition( IN_INT_SHORT int value );\nCHECK_RETVAL_RANGE( 0, SIEVE_SIZE ) \\\nint getSieveEntry( IN_RANGE( 0, SIEVE_SIZE - 1 ) int position );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN primeSieve( const BIGNUM *candidate );\n\n/* Prototypes for functions in kg_prime.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint primeProbable( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t   INOUT BIGNUM *n, \n\t\t\t\t   IN_RANGE( 1, 100 ) const int noChecks,\n\t\t\t\t   OUT BOOLEAN *isPrime );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint primeProbableFermat( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t const BIGNUM *n,\n\t\t\t\t\t\t INOUT BN_MONT_CTX *montCTX_n,\n\t\t\t\t\t\t OUT BOOLEAN *isPrime );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generatePrime( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t   INOUT BIGNUM *candidate, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t   IN_OPT const GET_RANDOM_INFO *getRandomInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generatePrimeRSA( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t  INOUT BIGNUM *candidate, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( bytesToBits( MIN_PKCSIZE ) / 2 ) \\\n\t\t\t\t\t\t\tconst int noBits, \n\t\t\t\t\t  IN_INT const long exponent );\n\n#endif /* _KEYGEN_DEFINED */\n\n"
  },
  {
    "path": "deps/cl345/context/keyload.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Key Load Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n#endif /* Compiler-specific includes */\n\n/* The default size of the salt for PKCS #5v2 key derivation, needed when we\n   set the CRYPT_CTXINFO_KEYING_VALUE */\n\n#define PKCS5_SALT_SIZE\t\t8\t/* 64 bits */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert a key attribute type into a key format type */\n\nCHECK_RETVAL \\\nint attributeToFormatType( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t   OUT_ENUM_OPT( KEYFORMAT ) KEYFORMAT_TYPE *keyformat )\n\t{\n\tstatic const MAP_TABLE attributeMapTbl[] = {\n\t\t{ CRYPT_IATTRIBUTE_KEY_SSH, KEYFORMAT_SSH },\n\t\t{ CRYPT_IATTRIBUTE_KEY_SSL, KEYFORMAT_SSL },\n\t\t{ CRYPT_IATTRIBUTE_KEY_SSL_EXT, KEYFORMAT_SSL_EXT },\n\t\t{ CRYPT_IATTRIBUTE_KEY_PGP, KEYFORMAT_PGP },\n\t\t{ CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL, KEYFORMAT_PGP },\n\t\t{ CRYPT_IATTRIBUTE_KEY_SPKI, KEYFORMAT_CERT },\n\t\t{ CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL, KEYFORMAT_CERT },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tint value, status;\n\n\tassert( isWritePtr( keyformat, sizeof( KEYFORMAT_TYPE ) ) );\n\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Clear return value */\n\t*keyformat = KEYFORMAT_NONE;\n\n\tstatus = mapValue( attribute, &value, attributeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( attributeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\t*keyformat = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tKey Parameter Handling Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise crypto parameters such as the IV and encryption mode, shared \n   by most capabilities.  This is never called directly, but is accessed\n   through function pointers in the capability lists */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initGenericParams( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,\n\t\t\t\t\t   IN_OPT const void *data, \n\t\t\t\t\t   IN_INT const int dataLength )\n\t{\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\tREQUIRES( isEnumRange( paramType, KEYPARAM ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Set the en/decryption mode if required */\n\tswitch( paramType )\n\t\t{\n\t\tcase KEYPARAM_MODE:\n\t\t\tREQUIRES( data == NULL );\n\t\t\tREQUIRES( isEnumRange( dataLength, CRYPT_MODE ) );\n\n\t\t\tswitch( dataLength )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_MODE_ECB:\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->encryptFunction );\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction, \n\t\t\t\t\t\t\t   capabilityInfoPtr->decryptFunction );\n\t\t\t\t\tbreak;\n\t\t\t\tcase CRYPT_MODE_CBC:\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->encryptCBCFunction );\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->decryptCBCFunction );\n\t\t\t\t\tbreak;\n#ifdef USE_CFB\n\t\t\t\tcase CRYPT_MODE_CFB:\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->encryptCFBFunction );\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->decryptCFBFunction );\n\t\t\t\t\tbreak;\n#endif /* USE_CFB */\n\t\t\t\tcase CRYPT_MODE_GCM:\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->encryptGCMFunction );\n\t\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t\t\t   capabilityInfoPtr->decryptGCMFunction );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tENSURES( ( FNPTR_ISNULL( contextInfoPtr->encryptFunction ) && \\\n\t\t\t\t\t   FNPTR_ISNULL( contextInfoPtr->decryptFunction ) ) || \\\n\t\t\t\t\t ( FNPTR_ISSET( contextInfoPtr->encryptFunction ) && \\\n\t\t\t\t\t   FNPTR_ISSET( contextInfoPtr->decryptFunction ) ) );\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->encryptFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->decryptFunction ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( contextInfoPtr, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t\t}\n\t\t\tconvInfo->mode = dataLength;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase KEYPARAM_IV:\n\t\t\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\t\t\tREQUIRES( data != NULL && \\\n\t\t\t\t\t  dataLength >= 8 && dataLength <= CRYPT_MAX_IVSIZE );\n\n\t\t\t/* Load an IV of the required length */\n\t\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_IVSIZE ) );\n\t\t\tmemcpy( convInfo->iv, data, dataLength );\n\t\t\tconvInfo->ivLength = dataLength;\n\t\t\tconvInfo->ivCount = 0;\n\t\t\tmemcpy( convInfo->currentIV, convInfo->iv, dataLength );\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_IV_SET );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\tretIntError();\n\t}\n\n/* Check that user-supplied supplied PKC parameters make sense (algorithm-\n   parameter-specific validity checks are performed at a lower level).  \n   Although the checks are somewhat specific to particular PKC algorithm \n   classes we have to do them at this point in order to avoid duplicating \n   them in every plug-in PKC module, and because strictly speaking it's the \n   job of the higher-level code to ensure that the lower-level routines get \n   fed at least approximately valid input */\n\n#ifndef USE_FIPS140 \n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int checkPKCparams( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t\t   const void *keyInfo )\n\t{\n\tconst CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) keyInfo;\n\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( keyInfo != NULL );\n\n\t/* The ECC check is somewhat different to the others because ECC key\n\t   sizes work in different ways so we have to special-case this one */\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tconst CRYPT_PKCINFO_ECC *eccKey = ( CRYPT_PKCINFO_ECC * ) keyInfo;\n\n\t\tassert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_ECC ) ) );\n\n\t\t/* Check the general info and make sure that all required values are\n\t\t   initialised */\n\t\tif( ( eccKey->isPublicKey != TRUE_ALT && \\\n\t\t\t  eccKey->isPublicKey != FALSE ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n#if 0\t/* For now we always require the use of named curves, which means \n\t\t   that the domain parameters can't be explicitly set */\n\t\tif( eccKey->curveType != CRYPT_ECCCURVE_NONE )\n\t\t\t{\n\t\t\tif( eccKey->pLen <= 0 || eccKey->aLen <= 0 || eccKey->bLen <= 0 || \\\n\t\t\t\teccKey->gxLen <= 0 || eccKey->gyLen <= 0 || eccKey->nLen <= 0 || \\\n\t\t\t\teccKey->qxLen <= 0 || eccKey->qyLen <= 0 || eccKey->dLen < 0 )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\t\telse\n#endif /* 0 */\n\t\t\t{\n\t\t\tif( eccKey->pLen != 0 || eccKey->aLen != 0 || eccKey->bLen != 0 || \\\n\t\t\t\teccKey->gxLen != 0 || eccKey->gyLen != 0 || eccKey->nLen != 0 || \\\n\t\t\t\teccKey->hLen != 0 || eccKey->qxLen <= 0 || eccKey->qyLen <= 0 || \\\n\t\t\t\teccKey->dLen < 0 )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( !isEnumRange( eccKey->curveType, CRYPT_ECCCURVE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\n\t\t/* Check the parameters and public components */\n\t\tif( isShortECCKey( eccKey->pLen ) )\n\t\t\t{\n\t\t\t/* Special-case handling for insecure-sized public keys */\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n#if 0\t/* Already checked above */\n\t\tif( eccKey->curveType != CRYPT_ECCCURVE_NONE )\n\t\t\t{\n\t\t\tif( eccKey->pLen < bytesToBits( ECCPARAM_MIN_P ) || \\\n\t\t\t\teccKey->pLen > bytesToBits( ECCPARAM_MAX_P ) || \\\n\t\t\t\teccKey->aLen < bytesToBits( ECCPARAM_MIN_A ) || \\\n\t\t\t\teccKey->aLen > bytesToBits( ECCPARAM_MAX_A ) || \\\n\t\t\t\teccKey->bLen < bytesToBits( ECCPARAM_MIN_B ) || \\\n\t\t\t\teccKey->bLen > bytesToBits( ECCPARAM_MAX_B ) || \\\n\t\t\t\teccKey->gxLen < bytesToBits( ECCPARAM_MIN_GX ) || \\\n\t\t\t\teccKey->gxLen > bytesToBits( ECCPARAM_MAX_GX ) || \\\n\t\t\t\teccKey->gyLen < bytesToBits( ECCPARAM_MIN_GY ) || \\\n\t\t\t\teccKey->gyLen > bytesToBits( ECCPARAM_MAX_GY ) || \\\n\t\t\t\teccKey->nLen < bytesToBits( ECCPARAM_MIN_N ) || \\\n\t\t\t\teccKey->nLen > bytesToBits( ECCPARAM_MAX_N ) || \\\n\t\t\t\teccKey->hLen < 1 || \\\n\t\t\t\teccKey->hLen > bytesToBits( ECCPARAM_MAX_N ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n#endif /* 0 */\n\t\tif( eccKey->qxLen < bytesToBits( ECCPARAM_MIN_QX ) || \\\n\t\t\teccKey->qxLen > bytesToBits( ECCPARAM_MAX_QX ) || \\\n\t\t\teccKey->qyLen < bytesToBits( ECCPARAM_MIN_QY ) || \\\n\t\t\teccKey->qyLen > bytesToBits( ECCPARAM_MAX_QY ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 ); \n\t\tif( eccKey->isPublicKey )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Check the private components */\n\t\tif( eccKey->dLen < bytesToBits( ECCPARAM_MIN_D ) || \\\n\t\t\teccKey->dLen > bytesToBits( ECCPARAM_MAX_D ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* For the non-ECC algorithms the DLP check is simpler than the RSA one \n\t   because there are less odd parameter combinations possible so we get \n\t   this one out of the way first.  Note that we don't get PKCS #3 DH \n\t   keys at this level so we always require that q be present */\n\tif( isDlpAlgo( cryptAlgo ) )\n\t\t{\n\t\tconst CRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) keyInfo;\n\n\t\tassert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n\t\t/* Check the general info and make sure that all required values are\n\t\t   initialised */\n\t\tif( ( dlpKey->isPublicKey != TRUE_ALT && \\\n\t\t\t  dlpKey->isPublicKey != FALSE ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( dlpKey->pLen <= 0 || dlpKey->qLen <= 0 || dlpKey->gLen <= 0 || \\\n\t\t\tdlpKey->yLen < 0 || dlpKey->xLen < 0 )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\t/* Check the public components */\n\t\tif( isShortPKCKey( dlpKey->pLen ) )\n\t\t\t{\n\t\t\t/* Special-case handling for insecure-sized public keys */\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n\t\tif( dlpKey->pLen < bytesToBits( DLPPARAM_MIN_P ) || \\\n\t\t\tdlpKey->pLen > bytesToBits( DLPPARAM_MAX_P ) || \\\n\t\t\tdlpKey->qLen < bytesToBits( DLPPARAM_MIN_Q ) || \\\n\t\t\tdlpKey->qLen > bytesToBits( DLPPARAM_MAX_Q ) || \\\n\t\t\tdlpKey->gLen < bytesToBits( DLPPARAM_MIN_G ) || \\\n\t\t\tdlpKey->gLen > bytesToBits( DLPPARAM_MAX_G ) || \\\n\t\t\tdlpKey->yLen < bytesToBits( 0 ) || \\\n\t\t\tdlpKey->yLen > bytesToBits( DLPPARAM_MAX_Y ) )\n\t\t\t/* y may be 0 if only x and the public parameters are available */\n\t\t\t{\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\t\tif( !( dlpKey->p[ bitsToBytes( dlpKey->pLen ) - 1 ] & 0x01 ) || \\\n\t\t\t!( dlpKey->q[ bitsToBytes( dlpKey->qLen ) - 1 ] & 0x01 ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\t/* Quick non-prime check */\n\t\tif( dlpKey->isPublicKey )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Check the private components */\n\t\tif( dlpKey->xLen < bytesToBits( DLPPARAM_MIN_X ) || \\\n\t\t\tdlpKey->xLen > bytesToBits( DLPPARAM_MAX_X ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tassert( isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) );\n\n\t/* Check the general info and make sure that all required values are\n\t   initialised */\n\tif( rsaKey->isPublicKey != TRUE_ALT && rsaKey->isPublicKey != FALSE )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( rsaKey->nLen <= 0 || rsaKey->eLen <= 0 || \\\n\t\trsaKey->dLen < 0 || rsaKey->pLen < 0 || rsaKey->qLen < 0 || \\\n\t\trsaKey->uLen < 0 || rsaKey->e1Len < 0 || rsaKey->e2Len < 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Check the public components */\n\tif( isShortPKCKey( rsaKey->nLen ) )\n\t\t{\n\t\t/* Special-case handling for insecure-sized public keys */\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t}\n\tif( rsaKey->nLen < bytesToBits( RSAPARAM_MIN_N ) || \\\n\t\trsaKey->nLen > bytesToBits( RSAPARAM_MAX_N ) || \\\n\t\trsaKey->eLen < bytesToBits( RSAPARAM_MIN_E ) || \\\n\t\trsaKey->eLen > bytesToBits( RSAPARAM_MAX_E ) || \\\n\t\trsaKey->eLen > rsaKey->nLen )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !( rsaKey->n[ bitsToBytes( rsaKey->nLen ) - 1 ] & 0x01 ) || \\\n\t\t!( rsaKey->e[ bitsToBytes( rsaKey->eLen ) - 1 ] & 0x01 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\t/* Quick non-prime check */\n\tif( rsaKey->isPublicKey )\n\t\treturn( CRYPT_OK );\n\n\t/* Check the private components.  This can get somewhat complex, possible\n\t   combinations are:\n\n\t\td, p, q\n\t\td, p, q, u\n\t\td, p, q, e1, e2, u\n\t\t   p, q, e1, e2, u\n\n\t   The reason for some of the odder combinations is that some \n\t   implementations don't use all of the values (for example d isn't \n\t   needed at all for the CRT shortcut) or recreate them when the key is \n\t   loaded.  If only d, p, and q are present we recreate e1 and e2 from \n\t   them, we also create u if necessary */\n\tif( rsaKey->pLen < bytesToBits( RSAPARAM_MIN_P ) || \\\n\t\trsaKey->pLen > bytesToBits( RSAPARAM_MAX_P ) || \\\n\t\trsaKey->pLen >= rsaKey->nLen || \\\n\t\trsaKey->qLen < bytesToBits( RSAPARAM_MIN_Q ) || \\\n\t\trsaKey->qLen > bytesToBits( RSAPARAM_MAX_Q ) || \\\n\t\trsaKey->qLen >= rsaKey->nLen )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !( rsaKey->p[ bitsToBytes( rsaKey->pLen ) - 1 ] & 0x01 ) || \\\n\t\t!( rsaKey->q[ bitsToBytes( rsaKey->qLen ) - 1 ] & 0x01 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\t/* Quick non-prime check */\n\tif( rsaKey->dLen <= 0 && rsaKey->e1Len <= 0 )\n\t\t{\n\t\t/* Must have either d or e1 et al */\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\tif( rsaKey->dLen > 0 && \\\n\t\t( rsaKey->dLen < bytesToBits( RSAPARAM_MIN_D ) || \\\n\t\t  rsaKey->dLen > bytesToBits( RSAPARAM_MAX_D ) ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( rsaKey->e1Len > 0 && \\\n\t\t( rsaKey->e1Len < bytesToBits( RSAPARAM_MIN_EXP1 ) || \\\n\t\t  rsaKey->e1Len > bytesToBits( RSAPARAM_MAX_EXP1 ) || \\\n\t\t  rsaKey->e2Len < bytesToBits( RSAPARAM_MIN_EXP2 ) || \\\n\t\t  rsaKey->e2Len > bytesToBits( RSAPARAM_MAX_EXP2 ) ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( rsaKey->uLen > 0 && \\\n\t\t( rsaKey->uLen < bytesToBits( RSAPARAM_MIN_U ) || \\\n\t\t  rsaKey->uLen > bytesToBits( RSAPARAM_MAX_U ) ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\treturn( CRYPT_OK );\n\t}\n#endif /* !USE_FIPS140 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Load Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load a key into a CONTEXT_INFO structure.  These functions are called by \n   the various higher-level functions that move a key into a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int loadKeyConvFunction( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t\t\tIN_LENGTH_KEY const int keyLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tint keyDataSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If we don't need an IV, record it as being set */\n\tif( !needsIV( convInfo->mode ) || \\\n\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_IV_SET );\n\n\t/* Perform the key setup */\n\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATESIZE, \n\t\t\t\t\t\t\t\t\t\t\t\t NULL, &keyDataSize, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, \n\t\t\t\t\t\t\t\t\t\t\t\t\t keyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Checksum the keying information for side-channel attack protection\n\t   purposes */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t{\n\t\tconvInfo->keyDataSize = keyDataSize;\n\t\tconvInfo->keyDataChecksum = checksumData( convInfo->key, \n\t\t\t\t\t\t\t\t\t\t\t\t  convInfo->keyDataSize );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int loadKeyPKCFunction( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t   IN_BUFFER_OPT( keyLength ) const void *key, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int keyLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( key == NULL ) || isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES( ( key == NULL && keyLength == 0 ) || \\\n\t\t\t  ( key != NULL && \\\n\t\t\t    keyLength > 16 && keyLength < MAX_INTLENGTH_SHORT ) );\n\t\t\t  /* The key data for this function may be NULL if the values\n\t\t\t     have been read from encoded X.509/SSH/SSL/PGP data straight\n\t\t\t\t into the context bignums */\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n#ifndef USE_FIPS140 \n\t/* Make sure that the parameters make sense */\n\tif( key != NULL )\n\t\t{\n\t\tstatus = checkPKCparams( capabilityInfoPtr->cryptAlgo, key );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tSET_FLAG( contextInfoPtr->flags, 0x08 );\n\t\t\t\t  /* Tell lib_kg to check params too */\n\t\t}\n#endif /* !USE_FIPS140 */\n\n\t/* Load the keying information.  The checksumming of the key data is \n\t   performed by the key-init code since for the DLP algorithms it can \n\t   get complicated in the presence of (EC)DH contexts that aren't quite\n\t   public or private keys */\n\tstatus = capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, \n\t\t\t\t\t\t\t\t\t\t\t\t keyLength );\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int loadKeyMacFunction( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t\t   IN_LENGTH_KEY const int keyLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_MAC );\n\tREQUIRES( keyLength >= MIN_KEYSIZE && keyLength <= CRYPT_MAX_KEYSIZE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\treturn( capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, keyLength ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int loadKeyGenericFunction( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t\t\t   IN_LENGTH_KEY const int keyLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_GENERIC );\n\tREQUIRES( keyLength >= bitsToBytes( 128 ) && \\\n\t\t\t  keyLength <= CRYPT_MAX_KEYSIZE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\treturn( capabilityInfoPtr->initKeyFunction( contextInfoPtr, key, keyLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Component Load Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load an encoded X.509/SSH/SSL/PGP key into a context.  This is used for \n   two purposes, to load public key components into native contexts and to \n   save encoded X.509 public-key data for use in certificates associated \n   with non-native contexts held in a device.  The latter is required \n   because there's no key data stored with the context itself that we can \n   use to create the SubjectPublicKeyInfo, however it's necessary to have \n   SubjectPublicKeyInfo available for certificate requests/certificates.  \n\n   Normally this is sufficient because cryptlib always generates native \n   contexts for public keys/certificates and for private keys the data is \n   generated in the device with the encoded public components attached to \n   the context as described above.  However for DH keys this gets a bit more \n   complex because although the private key is generated in the device, in \n   the case of the DH responder this is only the DH x value, with the \n   parameters (p and g) being supplied externally by the initiator.  This \n   means that it's necessary to decode at least some of the public key data \n   in order to create the y value after the x value has been generated in \n   the device.  The only situation where this functionality is currently \n   needed is for the SSHv2 code, which at the moment always uses native DH \n   contexts.  For this reason we leave off resolving this issue until it's \n   actually required */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint setEncodedKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyType, \n\t\t\t\t   IN_BUFFER( keyDataLen ) const void *keyData, \n\t\t\t\t   IN_LENGTH_SHORT const int keyDataLen )\n\t{\n\tconst PKC_CALCULATEKEYID_FUNCTION calculateKeyIDFunction = \\\n\t\t\t\t( PKC_CALCULATEKEYID_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->calculateKeyIDFunction );\n\tconst PKC_READKEY_FUNCTION readPublicKeyFunction = \\\n\t\t\t\t\t( PKC_READKEY_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->readPublicKeyFunction );\n\tSTREAM stream;\n\tKEYFORMAT_TYPE formatType;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES( needsKey( contextInfoPtr ) || \\\n\t\t\t  TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) );\n\tREQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_PGP || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_SSH || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_SSL || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_SSL_EXT || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \\\n\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL );\n\tREQUIRES( keyDataLen >= 2 && keyDataLen < MAX_INTLENGTH_SHORT );\n\t\t\t  /* Can be very short in the case of ECC curve IDs */\n\tREQUIRES( calculateKeyIDFunction != NULL );\n\tREQUIRES( readPublicKeyFunction != NULL );\n\n\t/* If the keys are held externally (e.g. in a crypto device), copy the \n\t   SubjectPublicKeyInfo data in and set up any other information that we \n\t   may need from it.  This information is used when loading a context \n\t   from a key contained in a device, for which the actual key components \n\t   aren't directly available in the context but may be needed in the \n\t   future for things like certificate requests and certificates */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\t{\n\t\tREQUIRES( keyType == CRYPT_IATTRIBUTE_KEY_SPKI || \\\n\t\t\t\t  keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\n\t\tREQUIRES( rangeCheck( keyDataLen, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( contextInfoPtr->ctxPKC->publicKeyInfo = \\\n\t\t\t\t\tclAlloc( \"setEncodedKey\", keyDataLen ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tmemcpy( contextInfoPtr->ctxPKC->publicKeyInfo, keyData, keyDataLen );\n\t\tcontextInfoPtr->ctxPKC->publicKeyInfoSize = keyDataLen;\n\t\treturn( calculateKeyIDFunction( contextInfoPtr ) );\n\t\t}\n\n\t/* Read the appropriately-formatted key data into the context, applying \n\t   a lowest-common-denominator set of usage flags to the loaded key */\n\tstatus = attributeToFormatType( keyType, &formatType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, keyData, keyDataLen );\n\tstatus = readPublicKeyFunction( &stream, contextInfoPtr, formatType, 0 );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a partial load of the initial public portions of a private \n\t   key with further key component operations to follow, there's nothing \n\t   more to do at this point and we're done */\n\tif( keyType == CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL || \\\n\t\tkeyType == CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL )\n\t\treturn( calculateKeyIDFunction( contextInfoPtr ) );\n\n\t/* Complete the key load using the internally-stored key components */\n\treturn( completeKeyLoad( contextInfoPtr, \n\t\t\t\t( keyType == CRYPT_IATTRIBUTE_KEY_PGP ) ? TRUE : FALSE ) );\n\t}\n\n/* Complete the load process for a key that was loaded with setEncodedKey() \n   or by setting DLP/ECDLP domain parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completeKeyLoad( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t const BOOLEAN isPGPkey )\n\t{\n\tstatic const int actionFlags = \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );\n\tstatic const int actionFlagsDH = ACTION_PERM_NONE_EXTERNAL_ALL;\n\tstatic const int actionFlagsPGP = \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst PKC_CALCULATEKEYID_FUNCTION calculateKeyIDFunction = \\\n\t\t\t\t( PKC_CALCULATEKEYID_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->calculateKeyIDFunction );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isPGPkey == TRUE || isPGPkey == FALSE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( calculateKeyIDFunction != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* Perform an internal load that uses the key component values that \n\t   we've just read into the context */\n\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\tstatus = loadKeyFunction( contextInfoPtr, NULL, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Map the status to a more appropriate code if necessary */\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t\t}\n\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n\n\t/* Restrict the key usage to public-key-only actions if necessary.  For \n\t   PGP key loads (which, apart from the restrictions specified with the \n\t   stored key data aren't constrained by the presence of ACLs in the \n\t   form of certificates) we allow external usage, for DH (whose keys can be \n\t   both public and private keys even though technically it's a public \n\t   key) we allow both encryption and decryption usage, and for public \n\t   keys read from certificates we  allow internal usage only */\n\tstatus = krnlSendMessage( contextInfoPtr->objectHandle,\n\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\tisPGPkey ? ( MESSAGE_CAST ) &actionFlagsPGP : \\\n\t\t\t\t\t\t( isKeyxAlgo( capabilityInfoPtr->cryptAlgo ) ) ? \\\n\t\t\t\t\t\t\t( MESSAGE_CAST ) &actionFlagsDH : \\\n\t\t\t\t\t\t\t( MESSAGE_CAST ) &actionFlags,\n\t\t\t\t\t\tCRYPT_IATTRIBUTE_ACTIONPERMS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( calculateKeyIDFunction( contextInfoPtr ) );\n\t}\n\n/* Load the components of a composite PKC key into a context */\n\n#ifndef USE_FIPS140\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setKeyComponents( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  IN_BUFFER( keyDataLen ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int keyDataLen )\n\t{\n\tstatic const int actionFlags = \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst PKC_CALCULATEKEYID_FUNCTION calculateKeyIDFunction = \\\n\t\t\t\t( PKC_CALCULATEKEYID_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->calculateKeyIDFunction );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tBOOLEAN isPublicKey;\n\tint externalBoolean, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t  needsKey( contextInfoPtr ) );\n\tREQUIRES( keyDataLen == sizeof( CRYPT_PKCINFO_RSA ) || \\\n\t\t\t  keyDataLen == sizeof( CRYPT_PKCINFO_DLP ) || \\\n\t\t\t  keyDataLen == sizeof( CRYPT_PKCINFO_ECC ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( calculateKeyIDFunction != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* If it's a private key we need to have a key label set before we can \n\t   continue.  The checking for this is a bit complex because at this\n\t   point all that the context knows is that it's a generic PKC context,\n\t   but it won't know whether it's a public- or private-key context until\n\t   the key is actually loaded.  To determine what it'll become we look\n\t   into the key data to see what's being loaded.\n\t   \n\t   In addition to this the key data probably came from an external \n\t   source (internal loads only come from marshalled data), so we have\n\t   to convert the boolean representation from the external to the \n\t   internal form */\n\tif( isEccAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\texternalBoolean = ( ( CRYPT_PKCINFO_ECC * ) keyData )->isPublicKey;\n\telse\n\t\t{\n\t\tif( isDlpAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t\texternalBoolean = ( ( CRYPT_PKCINFO_DLP * ) keyData )->isPublicKey;\n\t\telse\n\t\t\texternalBoolean = ( ( CRYPT_PKCINFO_RSA * ) keyData )->isPublicKey;\n\t\t}\n\tisPublicKey = externalBoolean ? TRUE : FALSE;\n\tif( !isPublicKey && contextInfoPtr->labelSize <= 0 )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* If it's a dummy object with keys held externally (e.g. in a crypto \n\t   device) we need a key label set in order to access the object at a \n\t   later date */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) && \\\n\t\tcontextInfoPtr->labelSize <= 0 )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Load the key components into the context */\n\tstatus = loadKeyFunction( contextInfoPtr, keyData, keyDataLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( contextInfoPtr->flags, \n\t\t\t  CONTEXT_FLAG_KEY_SET | CONTEXT_FLAG_PBO );\n\n\t/* Restrict the key usage to public-key-only actions if it's a public \n\t   key.  DH keys act as both public and private keys so we don't \n\t   restrict their usage */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY ) && \\\n\t\t( capabilityInfoPtr->cryptAlgo != CRYPT_ALGO_DH ) )\n\t\t{\n\t\tstatus = krnlSendMessage( contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &actionFlags,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( calculateKeyIDFunction( contextInfoPtr ) );\n\t}\n#endif /* !USE_FIPS140 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Generation Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a key into a CONTEXT_INFO structure */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKeyConvFunction( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\tMESSAGE_DATA msgData;\n\tint keyLength = convInfo->userKeyLength, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* If there's no key size specified, use the default length */\n\tif( keyLength <= 0 )\n\t\tkeyLength = capabilityInfoPtr->keySize;\n\n\t/* If the context is implemented in a crypto device it may have the\n\t   capability to generate the key itself so if there's a keygen function\n\t   present we call this to generate the key directly into the context\n\t   rather than generating it ourselves and loading it in.  Note that to\n\t   export this key we'll need to use an exporting context which is also\n\t   located in the device, since we can't access it externally */\n\tif( capabilityInfoPtr->generateKeyFunction != NULL )\n\t\t{\n\t\treturn( capabilityInfoPtr->generateKeyFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tbytesToBits( keyLength ) ) );\n\t\t}\n\n\t/* Generate a random session key into the context.  We load the random \n\t   data directly into the pagelocked encryption context and pass that in \n\t   as the key buffer, loadKey() won't copy the data if src == dest */\n\tsetMessageData( &msgData, convInfo->userKey, keyLength );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tconvInfo->userKeyLength = keyLength;\n\treturn( loadKeyFunction( contextInfoPtr, convInfo->userKey, \n\t\t\t\t\t\t\t convInfo->userKeyLength ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKeyPKCFunction( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst PKC_CALCULATEKEYID_FUNCTION calculateKeyIDFunction = \\\n\t\t\t\t( PKC_CALCULATEKEYID_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->calculateKeyIDFunction );\n\tint keyLength = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( calculateKeyIDFunction != NULL );\n\n\t/* Writing a key in PGP format requires that it have a creation time \n\t   associated with it, however keys from non-PGP sources don't have \n\t   this.  In theory if we wanted to write out the key in PGP format \n\t   then we'd have to set one in order to have something to write out.  \n\t   However, the creation time is hashed into the OpenPGP key ID when the \n\t   ID is generated, which means that moving a key via a non-PGP format \n\t   changes its key ID.  \n\n\t   Fortunately the standard never actually explains what the creation \n\t   time field is for, so it probably doesn't matter what we set it to.\n       Because of this we leave it at its default value of zero */\n#if defined( USE_PGP ) && 0\n\tcontextInfoPtr->ctxPKC->pgpCreationTime = getApproxTime();\n#endif /* USE_PGP */\n\n\t/* If there's no key size specified, use the default length.  In theory \n\t   we could also read the CRYPT_OPTION_PKC_KEYSIZE at this point, \n\t   however this only applies to the algorithm selected by \n\t   CRYPT_OPTION_PKC_ALGO, or perhaps the algorithm class of \n\t   CRYPT_OPTION_PKC_ALGO (for example { RSA, DSA, DH } vs. { ECDSA, \n\t   ECDH }), however this then creates a confusing gotcha where all \n\t   algorithms except CRYPT_OPTION_PKC_ALGO use the default key size if \n\t   none is explicitly specified using CRYPT_CTXINFO_KEYSIZE while\n\t   CRYPT_OPTION_PKC_ALGO takes its key size from \n\t   CRYPT_OPTION_PKC_KEYSIZE.  A quick user poll indicated that no-one \n\t   specifically wanted this behaviour, so we don't use \n\t   CRYPT_OPTION_PKC_KEYSIZE */\n\tif( keyLength <= 0 )\n\t\tkeyLength = capabilityInfoPtr->keySize;\n\n\t/* Generate the key into the context */\n\tstatus = capabilityInfoPtr->generateKeyFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tbytesToBits( keyLength ) );\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY ) )\n\t\tclearTempBignums( contextInfoPtr->ctxPKC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( calculateKeyIDFunction( contextInfoPtr ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKeyMacFunction( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\tMESSAGE_DATA msgData;\n\tint keyLength = macInfo->userKeyLength, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_MAC );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* If there's no key size specified, use the default length */\n\tif( keyLength <= 0 )\n\t\tkeyLength = capabilityInfoPtr->keySize;\n\n\t/* If the context is implemented in a crypto device it may have the\n\t   capability to generate the key itself so if there's a keygen function\n\t   present we call this to generate the key directly into the context\n\t   rather than generating it ourselves and loading it in.  Note that to\n\t   export this key we'll need to use an exporting context which is also\n\t   located in the device, since we can't access it externally */\n\tif( capabilityInfoPtr->generateKeyFunction != NULL )\n\t\t{\n\t\treturn( capabilityInfoPtr->generateKeyFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tbytesToBits( keyLength ) ) );\n\t\t}\n\n\t/* Generate a random session key into the context.  We load the random \n\t   data directly into the pagelocked encryption context and pass that in \n\t   as the key buffer, loadKey() won't copy the data if src == dest */\n\tsetMessageData( &msgData, macInfo->userKey, keyLength );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmacInfo->userKeyLength = keyLength;\n\treturn( loadKeyFunction( contextInfoPtr, macInfo->userKey, \n\t\t\t\t\t\t\t macInfo->userKeyLength ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKeyGenericFunction( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tGENERIC_INFO *genericInfo = contextInfoPtr->ctxGeneric;\n\tMESSAGE_DATA msgData;\n\tint keyLength = genericInfo->genericSecretLength, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_GENERIC );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* If there's no key size specified, use the default length */\n\tif( keyLength <= 0 )\n\t\tkeyLength = capabilityInfoPtr->keySize;\n\n\t/* If the context is implemented in a crypto device it may have the\n\t   capability to generate the key itself so if there's a keygen function\n\t   present we call this to generate the key directly into the context\n\t   rather than generating it ourselves and loading it in.  Note that to\n\t   export this key we'll need to use an exporting context which is also\n\t   located in the device, since we can't access it externally */\n\tif( capabilityInfoPtr->generateKeyFunction != NULL )\n\t\t{\n\t\treturn( capabilityInfoPtr->generateKeyFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tbytesToBits( keyLength ) ) );\n\t\t}\n\n\t/* Generate a random session key into the context.  We load the random \n\t   data directly into the pagelocked encryption context and pass that in \n\t   as the key buffer, loadKey() won't copy the data if src == dest */\n\tsetMessageData( &msgData, genericInfo->genericSecret, keyLength );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tgenericInfo->genericSecretLength = keyLength;\n\treturn( loadKeyFunction( contextInfoPtr, genericInfo->genericSecret, \n\t\t\t\t\t\t\t genericInfo->genericSecretLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Derivation Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Derive a key into a context from a user-supplied keying value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint deriveKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t   IN_BUFFER( keyValueLen ) const void *keyValue, \n\t\t\t   IN_LENGTH_SHORT const int keyValueLen )\n\t{\n\tstatic const MAP_TABLE mapTbl[] = {\n\t\t{ CRYPT_ALGO_SHA1, CRYPT_ALGO_HMAC_SHA1 },\n\t\t{ CRYPT_ALGO_SHA2, CRYPT_ALGO_HMAC_SHA2 },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst CTX_LOADKEY_FUNCTION loadKeyFunction = \\\n\t\t\t\t\t\t( CTX_LOADKEY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tint hmacAlgo = ( contextInfoPtr->type == CONTEXT_CONV ) ? \\\n\t\t\t\t\t contextInfoPtr->ctxConv->keySetupAlgorithm : \\\n\t\t\t\t\t contextInfoPtr->ctxMAC->keySetupAlgorithm;\n\tint value DUMMY_INIT, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( keyValue, keyValueLen ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV || \\\n\t\t\t  contextInfoPtr->type == CONTEXT_MAC );\n\tREQUIRES( needsKey( contextInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyValueLen ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\tREQUIRES( loadKeyFunction != NULL );\n\n\t/* If it's a persistent context we need to have a key label set before \n\t   we can continue */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) && \\\n\t\tcontextInfoPtr->labelSize <= 0 )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Set up various derivation parameters if they're not already set */\n\tif( hmacAlgo == CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = krnlSendMessage( contextInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &hmacAlgo, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_HASH );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = mapValue( hmacAlgo, &value, mapTbl, \n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( mapTbl, MAP_TABLE ) );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thmacAlgo = value;\n\t\t}\n\tif( contextInfoPtr->type == CONTEXT_CONV )\n\t\t{\n\t\tCONV_INFO *convInfo = contextInfoPtr->ctxConv;\n\t\tint keySize;\n\n\t\tkeySize = ( convInfo->userKeyLength > 0 ) ? \\\n\t\t\t\t  convInfo->userKeyLength : capabilityInfoPtr->keySize;\n\t\tif( convInfo->saltLength <= 0 )\n\t\t\t{\n\t\t\tMESSAGE_DATA nonceMsgData;\n\n\t\t\tsetMessageData( &nonceMsgData, convInfo->salt, PKCS5_SALT_SIZE );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &nonceMsgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tconvInfo->saltLength = PKCS5_SALT_SIZE;\n\t\t\t}\n\t\tconvInfo->keySetupAlgorithm = hmacAlgo;\n\t\tsetMechanismDeriveInfo( &mechanismInfo, convInfo->userKey, keySize,\n\t\t\t\t\t\t\t\tkeyValue, keyValueLen, \n\t\t\t\t\t\t\t\tconvInfo->keySetupAlgorithm, \n\t\t\t\t\t\t\t\tconvInfo->salt, convInfo->saltLength, \n\t\t\t\t\t\t\t\tconvInfo->keySetupIterations );\n\t\tif( mechanismInfo.iterations <= 0 )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( contextInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  &mechanismInfo.iterations, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYING_ITERATIONS );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tconvInfo->keySetupIterations = mechanismInfo.iterations;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tMAC_INFO *macInfo = contextInfoPtr->ctxMAC;\n\t\tint keySize;\n\n\t\tkeySize = ( macInfo->userKeyLength > 0 ) ? \\\n\t\t\t\t  macInfo->userKeyLength : capabilityInfoPtr->keySize;\n\t\tif( macInfo->saltLength <= 0 )\n\t\t\t{\n\t\t\tMESSAGE_DATA nonceMsgData;\n\n\t\t\tsetMessageData( &nonceMsgData, macInfo->salt, PKCS5_SALT_SIZE );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &nonceMsgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tmacInfo->saltLength = PKCS5_SALT_SIZE;\n\t\t\t}\n\t\tmacInfo->keySetupAlgorithm = hmacAlgo;\n\t\tsetMechanismDeriveInfo( &mechanismInfo, macInfo->userKey, keySize,\n\t\t\t\t\t\t\t\tkeyValue, keyValueLen, \n\t\t\t\t\t\t\t\tmacInfo->keySetupAlgorithm, \n\t\t\t\t\t\t\t\tmacInfo->salt, macInfo->saltLength,\n\t\t\t\t\t\t\t\tmacInfo->keySetupIterations );\n\t\tif( mechanismInfo.iterations <= 0 )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( contextInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  &mechanismInfo.iterations, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYING_ITERATIONS );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tmacInfo->keySetupIterations = mechanismInfo.iterations;\n\t\t\t}\n\t\t}\n\n\t/* Turn the user key into an encryption context key and load the key \n\t   into the context */\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, \n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( contextInfoPtr->type == CONTEXT_CONV )\n\t\t\tcontextInfoPtr->ctxConv->userKeyLength = mechanismInfo.dataOutLength;\n\t\telse\n\t\t\tcontextInfoPtr->ctxMAC->userKeyLength = mechanismInfo.dataOutLength;\n\t\tstatus = loadKeyFunction( contextInfoPtr, mechanismInfo.dataOut,\n\t\t\t\t\t\t\t\t  mechanismInfo.dataOutLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n\tzeroise( &mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initKeyHandling( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckContext( contextInfoPtr ) );\n\n\t/* Set the access method pointers */\n\tswitch( contextInfoPtr->type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\tFNPTR_SET( contextInfoPtr->loadKeyFunction, loadKeyConvFunction );\n\t\t\tFNPTR_SET( contextInfoPtr->generateKeyFunction, generateKeyConvFunction );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_PKC:\n\t\t\tFNPTR_SET( contextInfoPtr->loadKeyFunction, loadKeyPKCFunction );\n\t\t\tFNPTR_SET( contextInfoPtr->generateKeyFunction, generateKeyPKCFunction );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_MAC:\n\t\t\tFNPTR_SET( contextInfoPtr->loadKeyFunction, loadKeyMacFunction );\n\t\t\tFNPTR_SET( contextInfoPtr->generateKeyFunction, generateKeyMacFunction );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\tFNPTR_SET( contextInfoPtr->loadKeyFunction, loadKeyGenericFunction );\n\t\t\tFNPTR_SET( contextInfoPtr->generateKeyFunction, generateKeyGenericFunction );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n"
  },
  {
    "path": "deps/cl345/context/kg_dlp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib DLP Key Generation/Checking Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"keygen.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"context/keygen.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enable various side-channel protection mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int enableSidechannelProtection( INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( isDlpAlgo( cryptAlgo ) );\n\n\t/* Use constant-time modexp() to protect the private key from timing \n\t   channels */\n\tBN_set_flags( &pkcInfo->dlpParam_x, BN_FLG_CONSTTIME );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDetermine Discrete Log Exponent Bits\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following function (provided by Colin Plumb) is used to calculate the\n   appropriate size exponent for a given prime size which is required to\n   provide equivalent security from small-exponent attacks.  Note that it's\n   not clear which paper Colin is referring to here, the obvious candidate\n   would be \"On Diffie-Hellman Key Agreement with Short Exponents\" from\n   EuroCrypt'96 but it's not present in there and in any case the paper is\n   by van Oorschot and Wiener.  This leaves a tech report, possibly from\n   Bell-Northern Research.  A more recent reference is the ENISA \n   \"Algorithms, key size and parameters report\", which (Table 3.1) draws on\n   a number of different sources to produce more or less the same figures.\n\n   This is based on a paper by Michael Wiener on\t| The function defined\n   the difficulty of the two attacks, which has\t\t| below (not part of the\n   the following table:\t\t\t\t\t\t\t\t| original paper)\n\t\t\t\t\t\t\t\t\t\t\t\t\t| produces the following\n\t Table 1: Subgroup Sizes to Match Field Sizes\t| results:\n\t\t\t\t\t\t\t\t\t\t\t\t\t|\n\tSize of p\tCost of each attack\t\tSize of q\t|\tOutput\tError\n\t (bits)\t\t(instructions or\t\t(bits)\t\t|\t\t\t(+ is safe)\n\t\t\t\t modular multiplies)\t\t\t\t|\n\t\t\t\t\t\t\t\t\t\t\t\t\t|\n\t   512\t\t\t9 x 10^17\t\t\t119\t\t\t|\t137\t\t+18\n\t   768\t\t\t6 x 10^21\t\t\t145\t\t\t|\t153\t\t+8\n\t  1024\t\t\t7 x 10^24\t\t\t165\t\t\t|\t169\t\t+4\n\t  1280\t\t\t3 x 10^27\t\t\t183\t\t\t|\t184\t\t+1\n\t  1536\t\t\t7 x 10^29\t\t\t198\t\t\t|\t198\t\t+0\n\t  1792\t\t\t9 x 10^31\t\t\t212\t\t\t|\t212\t\t+0\n\t  2048\t\t\t8 x 10^33\t\t\t225\t\t\t|\t225\t\t+0\n\t  2304\t\t\t5 x 10^35\t\t\t237\t\t\t|\t237\t\t+0\n\t  2560\t\t\t3 x 10^37\t\t\t249\t\t\t|\t249\t\t+0\n\t  2816\t\t\t1 x 10^39\t\t\t259\t\t\t|\t260\t\t+1\n\t  3072\t\t\t3 x 10^40\t\t\t269\t\t\t|\t270\t\t+1\n\t  3328\t\t\t8 x 10^41\t\t\t279\t\t\t|\t280\t\t+1\n\t  3584\t\t\t2 x 10^43\t\t\t288\t\t\t|\t289\t\t+1\n\t  3840\t\t\t4 x 10^44\t\t\t296\t\t\t|\t297\t\t+1\n\t  4096\t\t\t7 x 10^45\t\t\t305\t\t\t|\t305\t\t+0\n\t  4352\t\t\t1 x 10^47\t\t\t313\t\t\t|\t313\t\t+0\n\t  4608\t\t\t2 x 10^48\t\t\t320\t\t\t|\t321\t\t+1\n\t  4864\t\t\t2 x 10^49\t\t\t328\t\t\t|\t329\t\t+1\n\t  5120\t\t\t3 x 10^50\t\t\t335\t\t\t|\t337\t\t+2\n\n   This function fits a curve to this, which overestimates the size of the\n   exponent required, but by a very small amount in the important 1000-4000\n   bit range.  It is a quadratic curve up to 3840 bits, and a linear curve\n   past that.  They are designed to be C(1) (have the same value and the same\n   slope) at the point where they meet */\n\n#define AN\t\t1L\t\t/* a = -AN/AD/65536, the quadratic coefficient */\n#define AD\t\t3L\n#define M\t\t8L\t\t/* Slope = M/256, i.e. 1/32 where linear starts */\n#define TX\t\t3840L\t/* X value at the slope point, where linear starts */\n#define TY\t\t297L\t/* Y value at the slope point, where linear starts */\n\n/* For a slope of M at the point (TX,TY) we only have one degree of freedom\n   left in a quadratic curve so use the coefficient of x^2, namely a, as \n   that free parameter.\n\n   y = -AN/AD*((x-TX)/256)^2 + M*(x-TX)/256 + TY\n\t = -AN*(x-TX)*(x-TX)/AD/256/256 + M*x/256 - M*TX/256 + TY\n\t = -AN*x*x/AD/256/256 + 2*AN*x*TX/AD/256/256 - AN*TX*TX/AD/256/256 \\\n\t\t+ M*x/256 - M*TX/256 + TY\n\t = -AN*(x/256)^2/AD + 2*AN*(TX/256)*(x/256)/AD + M*(x/256) \\\n\t\t- AN*(TX/256)^2/AD - M*(TX/256) + TY\n\t = (AN*(2*TX/256 - x/256) + M*AD)*x/256/AD - (AN*(TX/256)/AD + M)*TX/256 \\\n\t\t+ TY\n\t = (AN*(2*TX/256 - x/256) + M*AD)*x/256/AD \\\n\t\t- (AN*(TX/256) + M*AD)*TX/256/AD + TY\n\t =  ((M*AD + AN*(2*TX/256 - x/256))*x - (AN*(TX/256)+M*AD)*TX)/256/AD + TY\n\t =  ((M*AD + AN*(2*TX - x)/256)*x - (AN*(TX/256)+M*AD)*TX)/256/AD + TY\n\t =  ((M*AD + AN*(2*TX - x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD + TY\n\t =  (((256*M*AD+2*AN*TX-AN*x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD + TY\n\n   Since this is for the range 0...TX, in order to avoid having any\n   intermediate results less than 0, we need one final rearrangement, and a\n   compiler can easily take the constant-folding from there...\n\n\t =  TY + (((256*M*AD+2*AN*TX-AN*x)/256)*x - (M*AD + AN*TX/256)*TX)/256/AD\n\t =  TY - ((M*AD + AN*TX/256)*TX - ((256*M*AD+2*AN*TX-AN*x)/256)*x)/256/AD */\n\nCHECK_RETVAL_RANGE( 160, 1000 ) \\\nstatic int getDLPexpSize( IN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\tconst int primeBits )\n\t{\n\tlong value;\t/* Necessary to avoid problems with 16-bit compilers */\n\n\tREQUIRES( primeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  primeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* If it's over TX bits, it's linear */\n\tif( primeBits > TX )\n\t\tvalue = M * primeBits / 256 - M * TX / 256 + TY;\n\telse\n\t\t{\n\t\t/* It's quadratic */\n\t\tvalue = TY - ( ( M * AD + AN * TX / 256 ) * TX - \\\n\t\t\t\t\t   ( ( 256 * M * AD + AN * 2 * TX - AN * primeBits ) / 256 ) * \\\n\t\t\t\t\t   primeBits ) / ( AD * 256 );\n\t\t}\n\tENSURES( value >= 160 && value < 1000 );\n\n\t/* At this point we run into a problem with SSH, it hardcodes the \n\t   exponent size at 160 bits no matter what the prime size is so that\n\t   there's no increase in security when the key size is increased.  \n\t   Because this function generates an exponent whose size matches the \n\t   security level of the key, it can't be used to generate DSA keys for \n\t   use with SSH.  In order to provide at least basic keys usable with\n\t   SSH and also for backwards compatiblity with older (non-SSH) \n\t   implementations that hardcode DSA key parameters at { 1024, 160 } we \n\t   always return a fixed exponent size of 160 bits if the key size is \n\t   around 1024 bits */\n\tif( primeBits <= 1028 )\n\t\treturn( 160 );\n\n\tENSURES( isIntegerRange( value ) );\n\treturn( ( int ) value );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t  \t\t\t\t\tGenerate DL Primes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\tOriginal findGeneratorForPQ() and generateDLPPublicValues() are \t\t*\n*\t  copyright Kevin J. Bluck 1998, provided for use in cryptlib.\t\t\t*\n*\t\t  findGeneratorForPQ() has been completely rewritten, \t\t\t\t*\n*\t\t\tgenerateDLPPublicValues() is heavily modified.\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* DLP-based PKCs have various requirements for the generated parameters.\n   For the generator g it can generate either the entire group (meaning\n   g^x mod p can take any value between 1 and p-1) or the subgroup q, an\n   appropriately-sized prime.  Ideally we'd choose g = 2 (standard for PKCS \n   #3 DH), however to safely use g = 2 we need a safe prime p = 2q + 1 so \n   the order of any g in the range 2 ... p-2 is either q or 2q.  If we don't \n   use a safe prime then the order of g = 2 can't really be determined \n   without first factoring p-1, in other words there's no easy way to force \n   g to a particular value.\n\n\tDSA: p, q, and g of preset lengths (currently p isn't fixed at exactly\n\t\tn * 64 bits because of the way the Lim-Lee algorithm works, it's\n\t\tpossible to get this by iterating the multiplication step until the\n\t\tresult is exactly n * 64 bits but this doesn't seem worth the\n\t\teffort), x = 1...q-1.\n\tPKCS #3 DH: No g (it's fixed at 2) or q.  Requires safe primes, see the\n\t\tcomment for X9.42 values.\n\tX9.42 DH: p, q, and g as for DSA but without the 160-bit SHA1-enforced\n\t\tupper limit on q in original versions of the DSA specification so \n\t\tthat p can go above 1024 bits.  Newer versions of the spec \n\t\teventually allowed larger p and q values in conjunction with post-\n\t\tSHA1 hash algorithms.  Note that the way g is generated leads to \n\t\textraordinarily inefficient g values relative to PKCS #3's g = 2, \n\t\thowever to safely use g = 2 we'd need a safe prime.  x = 2...q-2.  \n\tElgamal: As X9.42 DH.\n\n   Traditionally for PKCS #3 DH g is fixed at 2 which is safe even when it's \n   not a primitive root since it still covers half of the space of possible \n   residues, however this requires the use of a safe prime so we always \n   generate a FIPS 186-style g value */\n\n/* The minimum safe exponent size for a given-size prime */\n\n#define MIN_EXPONENT_SIZE_BITS\t160\n\n/* The maximum number of factors required to generate a prime using the Lim-\n   Lee algorithm, which evaluates to 25 for a 4 kbit max.prime size */\n\n#define MAX_NO_FACTORS\t\t\t( ( bytesToBits( CRYPT_MAX_PKCSIZE ) / \\\n\t\t\t\t\t\t\t\t\tMIN_EXPONENT_SIZE_BITS ) + 1 )\n\n/* The maximum number of small primes required to generate a prime using the\n   Lim-Lee algorithm.  There's no fixed bound on this value, but in the worst\n   case we start with \n   ~ CRYPT_MAX_PKCSIZE_bits / getDLPexpSize( CRYPT_MAX_PKCSIZE_bits ) primes \n   = ~ 13 values, and add one more prime on each retry.  Typically we need \n   10-15 for keys in the most commonly-used range 1024-2048 bits.  In order \n   to simplify the handling of values we allow for 64 primes, which has a \n   vanishingly small probability of failing and also provides a safe upper \n   bound for the number of retries (there's something wrong with the \n   algorithm if it requires anywhere near this many retries) */\n\n#define MAX_NO_PRIMES\t\t\t64\n\n/* Select a generator g for the prime moduli p and q.  g will be chosen to \n   be of prime order q, where q divides (p - 1), i.e. g generates the \n   subgroup of order q in the multiplicative group of GF(p) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findGeneratorForPQ( INOUT PKC_INFO *pkcInfo )\n\t{\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;\n\tBIGNUM *g = &pkcInfo->dlpParam_g;\n\tBIGNUM *j = &pkcInfo->tmp1;\n\tBN_ULONG gCounter;\n\tint bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* j = (p - 1) / q */\n\tCKPTR( BN_copy( j, p ) );\n\tCK( BN_sub_word( j, 1 ) );\n\tCK( BN_div( j, NULL, j, q, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Starting gCounter at 3, set g = (gCounter ^ j) mod p until g != 1.\n\t   Although FIPS 196/X9.30/X9.42 merely require that 1 < g < p - 1, if \n\t   we use small integers it makes this operation much faster */\n\tLOOP_MED( gCounter = 3, gCounter < FAILSAFE_ITERATIONS_MED, gCounter++ )\n\t\t{\n\t\tCK( BN_mod_exp_mont_word( g, gCounter, j, p, &pkcInfo->bnCTX, \n\t\t\t\t\t\t\t\t  &pkcInfo->dlpParam_mont_p ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tif( BN_cmp_word( g, 1 ) > 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Generate prime numbers for DLP-based PKC's using the Lim-Lee algorithm:\n\n\tp = 2 * q * ( prime[1] * ... prime[n] ) + 1 \n\n   This function allows the generation of reproducible (NUMS) prime values \n   if getRandomInfo is provided as a randomness source instead of the \n   default built-in source */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateDLPPublicValues( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int pBits,\n\t\t\t\t\t\t\t\t\tIN_OPT const GET_RANDOM_INFO *getRandomInfo )\n\t{\n\tconst int safeExpSizeBits = getDLPexpSize( pBits );\n\tconst int noChecks = getNoPrimeChecks( pBits );\n\tBIGNUM llPrimes[ MAX_NO_PRIMES + 8 ], llProducts[ MAX_NO_FACTORS + 8 ];\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;\n\tBOOLEAN primeFound;\n\tint indices[ MAX_NO_FACTORS + 8 ];\n\tint nPrimes, nFactors, factorBits, i, LOOP_ITERATOR;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( getDLPexpSize( 1024 ) == MIN_EXPONENT_SIZE_BITS );\n\t\t\t/* 1024-bit keys have special handling for pre-FIPS 186-3\n\t\t\t   compatibility */\n\tassert( getDLPexpSize( 1030 ) == 168 );\n\t\t\t/* First size over MIN_EXPONENT_SIZE_BITS */\n\tassert( getRandomInfo == NULL || \\\n\t\t\tisReadPtr( getRandomInfo, sizeof( GET_RANDOM_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( pBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  pBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( safeExpSizeBits >= MIN_EXPONENT_SIZE_BITS && \\\n\t\t\t  safeExpSizeBits < 512 );\n\n\tENSURES( getDLPexpSize( 1024 ) == MIN_EXPONENT_SIZE_BITS );\n\t\t\t /* 1024-bit keys have special handling for pre-FIPS 186-3 \n\t\t\t\tcompatibility */\n\tENSURES( getDLPexpSize( 1536 ) == 198 );\n\tENSURES( getDLPexpSize( 2048 ) == 225 );\n\tENSURES( getDLPexpSize( 3072 ) == 270 );\n\tENSURES( getDLPexpSize( 4096 ) == 305 );\n\n\t/* Determine how many factors we need and the size in bits of the \n\t   factors.  For the range checks below, the minimum value for\n\t   factorBits is 860, the minimum value for nFactors is 5 when\n\t   MIN_PKCSIZE is 1024 */\n\tfactorBits = ( pBits - safeExpSizeBits ) - 1;\n\tENSURES( factorBits >= bytesToBits( MIN_PKCSIZE ) - \\\n\t\t\t\t\t\t\t( MIN_EXPONENT_SIZE_BITS + 1 ) && \\\n\t\t\t factorBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tnFactors = nPrimes = ( factorBits / safeExpSizeBits ) + 1;\n\tENSURES( nFactors >= ( bytesToBits( MIN_PKCSIZE ) - MIN_EXPONENT_SIZE_BITS ) / \\\n\t\t\t\t\t\t\tMIN_EXPONENT_SIZE_BITS && \\\n\t\t\t nFactors <= MAX_NO_FACTORS );\n\tENSURES( nPrimes > ( bytesToBits( MIN_PKCSIZE ) - MIN_EXPONENT_SIZE_BITS ) / \\\n\t\t\t\t\t\t\tMIN_EXPONENT_SIZE_BITS && \\\n\t\t\t nPrimes <= MAX_NO_PRIMES );\n\tfactorBits /= nFactors;\n\n\t/* Generate a random prime q and multiply it by 2 to form the base for \n\t   the other factors */\n\tstatus = generatePrime( pkcInfo, q, safeExpSizeBits, getRandomInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCK( BN_lshift1( q, q ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Set up the permutation control arrays and generate the first nFactors \n\t   factors */\n\tLOOP_LARGE( i = 0, i < MAX_NO_FACTORS, i++ )\n\t\tBN_init( &llProducts[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\tLOOP_LARGE( i = 0, i < MAX_NO_PRIMES, i++ )\n\t\tBN_init( &llPrimes[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\tLOOP_LARGE( i = 0, i < nFactors, i++ )\n\t\t{\n\t\tstatus = generatePrime( pkcInfo, &llPrimes[ i ], factorBits, \n\t\t\t\t\t\t\t\tgetRandomInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\tgoto cleanup;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tLOOP_LARGE_INITCHECK( primeFound = FALSE, !primeFound )\n\t\t{\n\t\tint indexMoved, LOOP_ITERATOR_ALT;\n\n\t\t/* Initialize the indices for the permutation.  We try the first \n\t\t   nFactors factors first since any new primes will be added at the \n\t\t   end.  Since initially nFactors == nPrimes, this is just the\n\t\t   identity mapping { 0, 1, 2, 3, 4, ... } until we start adding\n\t\t   more primes if we run out of permutations to test */\n\t\tindices[ nFactors - 1 ] = nPrimes - 1;\n\t\tLOOP_LARGE_ALT( i = nFactors - 2, i >= 0, i-- )\n\t\t\t{\n\t\t\tindices[ i ] = indices[ i + 1 ] - 1;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tCK( BN_mul( &llProducts[ nFactors - 1 ], q, &llPrimes[ nPrimes - 1 ], \n\t\t\t\t\t&pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\t{\n\t\t\tstatus = getBnStatus( bnStatus );\n\t\t\tgoto cleanup;\n\t\t\t}\n\t\tindexMoved = nFactors - 2;\n\n\t\t/* Test all possible new prime permutations until a prime is found or \n\t\t   we run out of permutations */\n\t\tLOOP_MAX_CHECK_ALT( indices[ nFactors - 1 ] > 0 )\n\t\t\t{\n\t\t\tint LOOP_ITERATOR_ALT2;\n\n\t\t\t/* Assemble a new candidate prime 2 * q * primes + 1 from the \n\t\t\t   currently indexed random primes */\n\t\t\tLOOP_LARGE_ALT2( i = indexMoved, \n\t\t\t\t\t\t\t bnStatusOK( bnStatus ) && i >= 0, i-- )\n\t\t\t\t{\n\t\t\t\tCK( BN_mul( &llProducts[ i ], &llProducts[ i + 1 ],\n\t\t\t\t\t\t\t&llPrimes[ indices[ i ] ], &pkcInfo->bnCTX ) );\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT2 );\n\t\t\tCKPTR( BN_copy( p, &llProducts[ 0 ] ) );\n\t\t\tCK( BN_add_word( p, 1 ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\t{\n\t\t\t\tstatus = getBnStatus( bnStatus );\n\t\t\t\tgoto cleanup;\n\t\t\t\t}\n\n\t\t\t/* If the candidate has a good chance of being prime, try a\n\t\t\t   probabilistic test and exit if it succeeds */\n\t\t\tif( primeSieve( p ) )\n\t\t\t\t{\n\t\t\t\tstatus = primeProbable( pkcInfo, p, noChecks, &primeFound );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tgoto cleanup;\n\t\t\t\tif( primeFound )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Find the lowest index which is not already at the lowest \n\t\t\t   possible point and move it down one */\n\t\t\tLOOP_LARGE_ALT2( i = 0, i < nFactors, i++ )\n\t\t\t\t{\n\t\t\t\tif( indices[ i ] > i )\n\t\t\t\t\t{\n\t\t\t\t\tindices[ i ]--;\n\t\t\t\t\tindexMoved = i;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT2 );\n\n\t\t\t/* If we moved down the highest index then we've exhausted all \n\t\t\t   of the permutations so we have to start over with another \n\t\t\t   prime */\n\t\t\tif( ( indexMoved >= nFactors - 1 ) || ( i >= nFactors ) )\n\t\t\t\tbreak;\n\n\t\t\t/* We haven't changed the highest index, take all of the indices \n\t\t\t   below the one that we moved down and move them up so that \n\t\t\t   they're packed up as high as they'll go */\n\t\t\tLOOP_LARGE_ALT2( i = indexMoved - 1, i >= 0, i-- )\n\t\t\t\t{\n\t\t\t\tindices[ i ] = indices[ i + 1 ] - 1;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT2 );\n\t\t\t} \n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\n\t\t/* If we haven't found a prime yet, add a new prime to the pool and\n\t\t   try again */\n\t\tif( !primeFound )\n\t\t\t{\n\t\t\tif( nPrimes >= MAX_NO_PRIMES )\n\t\t\t\t{\n\t\t\t\t/* We've run through an extraordinary number of primes, \n\t\t\t\t   something is wrong */\n\t\t\t\tDEBUG_DIAG(( \"Iterated through %d primes trying to \"\n\t\t\t\t\t\t\t \"generate DLP key\", MAX_NO_PRIMES ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\tgoto cleanup;\n\t\t\t\t}\n\t\t\tstatus = generatePrime( pkcInfo, &llPrimes[ nPrimes++ ], \n\t\t\t\t\t\t\t\t\tfactorBits, getRandomInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tgoto cleanup;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Recover the original value of q by dividing by 2 */\n\tCK( BN_rshift1( q, q ) );\n\tif( bnStatusError( bnStatus ) )\n\t\t{\n\t\tstatus = getBnStatus( bnStatus );\n\t\tgoto cleanup;\n\t\t}\n\n\t/* In theory now that we've got p we need to evaluate its Montgomery \n\t   form, however this has already been done as a side-effect of the\n\t   primality checking in primeProbable(), so all we do here is verify \n\t   that it's indeed set */\n\tENSURES( !BN_cmp( &pkcInfo->dlpParam_mont_p.N, p ) );\n\n\t/* Find a generator suitable for p and q */\n\tstatus = findGeneratorForPQ( pkcInfo );\n\ncleanup:\n\n\t/* Free the local storage */\n\tLOOP_LARGE( i = 0, i < MAX_NO_PRIMES, i++ )\n\t\tBN_clear_free( &llPrimes[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\tLOOP_LARGE( i = 0, i < MAX_NO_FACTORS, i++ )\n\t\tBN_clear_free( &llProducts[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( status );\n\t}\n\n/* Generate the DLP private value x and public value y */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateDLPPrivateValue( INOUT PKC_INFO *pkcInfo )\n\t{\n\tBIGNUM *x = &pkcInfo->dlpParam_x, *q = &pkcInfo->dlpParam_q; \n\tconst int qBits = BN_num_bits( q );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( ( qBits == 0 ) || \\\n\t\t\t  ( qBits >= MIN_EXPONENT_SIZE_BITS && \\\n\t\t\t\tqBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ) );\n\n\t/* If it's a PKCS #3 DH key then there won't be a q value present so we \n\t   have to estimate the appropriate x size in the same way that we \n\t   estimated the q size when we generated the public key components */\n\tif( qBits == 0 )\n\t\t{\n\t\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\t\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t\t  &domainParams->p : &pkcInfo->dlpParam_p;\n\t\tconst int pLen = BN_num_bits( p );\n\n\t\tREQUIRES( pLen >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t\t  pLen <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\t\treturn( generateBignum( x, getDLPexpSize( pLen ), 0xC0, 0 ) );\n\t\t}\n\n\t/* Generate the DLP private value x s.t. 2 <= x <= q-2 (this is the \n\t   lowest common denominator of FIPS 186's 1...q-1 and X9.42's 2...q-2). \n\t   Because the mod q-2 is expensive we do a quick check to make sure \n\t   that it's really necessary before evaluating it */\n\tstatus = generateBignum( x, qBits, 0xC0, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCK( BN_sub_word( q, 2 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( x, q ) > 0 )\n\t\t{\n\t\tint xLen;\n\n\t\t/* Trim x down to size.  Actually we get the upper bound as q - 3, \n\t\t   but over a MIN_EXPONENT_SIZE_BITS (minimum) number range this \n\t\t   doesn't matter */\n\t\tCK( BN_mod( x, x, q, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\n\t\t/* If the value that we ended up with is too small, just generate a \n\t\t   new value one bit shorter, which guarantees that it'll fit the \n\t\t   criteria (the target is a suitably large random value, not the \n\t\t   closest possible fit within the range) */\n\t\txLen = BN_num_bits( x );\n\t\tREQUIRES( xLen > 0 && xLen <= qBits );\n\t\tif( xLen < qBits - 5 )\n\t\t\tstatus = generateBignum( x, qBits - 1, 0xC0, 0 );\n\t\t}\n\tCK( BN_add_word( q, 2 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateDLPPublicValue( INOUT PKC_INFO *pkcInfo )\n\t{\n\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &pkcInfo->dlpParam_p;\n\tconst BIGNUM *g = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->g : &pkcInfo->dlpParam_g;\n\tBIGNUM *x = &pkcInfo->dlpParam_x, *y = &pkcInfo->dlpParam_y; \n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\tCK( BN_mod_exp_mont( y, g, x, p, &pkcInfo->bnCTX, \n\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck a DLP Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform validity checks on the public key.  This function is only called \n   for nonstandard, custom domain parameters that don't match the known-good\n   built-in values.  \n   \n   We have to make the PKC_INFO data non-const because the bignum code wants \n   to modify some of the values as it's working with them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDLPDomainParameters( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t\t\t const BOOLEAN isPKCS3, \n\t\t\t\t\t\t\t\t\t const BOOLEAN isFullyInitialised )\n\t{\n\tBIGNUM *p = &pkcInfo->dlpParam_p, *q = &pkcInfo->dlpParam_q;\n\tBIGNUM *g = &pkcInfo->dlpParam_g, *tmp = &pkcInfo->tmp1;\n\tconst int gBits = BN_num_bits( g );\n\tBOOLEAN isPrime;\n\tint length, bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( isPKCS3 == TRUE || isPKCS3 == FALSE );\n\tREQUIRES( isFullyInitialised == TRUE || isFullyInitialised == FALSE );\n\tREQUIRES( gBits > 0 && gBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Verify that pLen >= DLPPARAM_MIN_P, pLen <= DLPPARAM_MAX_P */\n\tlength = BN_num_bytes( p );\n\tif( isShortPKCKey( length ) )\n\t\t{\n\t\t/* Special-case handling for insecure-sized public keys */\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t}\n\tif( length < DLPPARAM_MIN_P || length > DLPPARAM_MAX_P )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n#ifndef CONFIG_FUZZ\n\t/* Verify that p is not (obviously) composite.  Note that we can't \n\t   use primeProbable() because this updates the Montgomery CTX data, \n\t   it's OK to use it early in the keygen process before everything is \n\t   set up but not after the pkcInfo is fully initialised so we use\n\t   primeProbableFermat() instead */\n\tif( !primeSieve( p ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( isFullyInitialised )\n\t\t{\n\t\tstatus = primeProbableFermat( pkcInfo, p, &pkcInfo->dlpParam_mont_p, \n\t\t\t\t\t\t\t\t\t  &isPrime );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !isPrime )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n#else\n\t/* If we're fuzzing we skip the relatively expensive non-prime check, \n\t   but we still have to at least ensure that the value won't trigger\n\t   an exception in subsequent code */\n\tif( !BN_is_odd( p ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n#endif /* CONFIG_FUZZ */\n\n\t/* Verify that gLen >= DLPPARAM_MIN_G, gLen <= DLPPARAM_MAX_G */\n\tlength = BN_num_bytes( g );\n\tif( length < DLPPARAM_MIN_G || length > DLPPARAM_MAX_G )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that g < 256 if it's straight PKCS #3 DH.  This isn't strictly \n\t   necessary but use of g in DH typically sets g = 2, the only reason for \n\t   setting it to a larger value is either stupidity or a deliberate DoS, \n\t   neither of which we want to encourage.  FIPS 186/X9.42 use a g \n\t   parameter the same size as p so we can't limit the size as for \n\t   PKCS #3 */\n\tif( isPKCS3 && gBits > 8 )\n\t\t{\n\t\tassert_nofuzz( DEBUG_WARN );\t/* Warn in debug build */\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Verify that 2 <= g <= p - 2 */\n\tif( gBits < 2 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tCKPTR( BN_copy( tmp, p ) );\n\tCK( BN_sub_word( tmp, 2 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1  );\n\tif( BN_cmp( g, tmp ) > 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* If it's a PKCS #3 key then the only public values are p and g and \n\t   we're done */\n\tif( isPKCS3 )\n\t\t{\n\t\t/* There is a further check that we can perform on p, but it's \n\t\t   rather problematic because it only works for safe primes of the \n\t\t   form p = 2q + 1, and even then the checks depend on your \n\t\t   religious inclinations, you've got the choice of either choosing \n\t\t   a value where the generated DH secret is limited to half the \n\t\t   possible values, or one where you leak a bit of the secret \n\t\t   exponent.  \n\t\t   \n\t\t   For example for g=2, if p is congruent to 11 mod 24 then g is a \n\t\t   quadratic nonresidue and the DH secret covers all possible values \n\t\t   but you leak the LSB of the secret exponent, but if p is \n\t\t   congruent to 11 mod 23 then g is a quadratic residue and the DH \n\t\t   secret only covers half the possible values, but you don't leak \n\t\t   any bits of the exponent (for OpenSSH's g=5, the values are 3 and \n\t\t   7).\n\n\t\t   Once you go to more general values of g, or FIPS 186 primes which\n\t\t   should be easily verifiable but aren't because the PKCS #3 form\n\t\t   discards the q value that you need for the verification, there \n\t\t   isn't really any checking that can be done.  The result is an ugly\n\t\t   yes-biased test that can say \"definitely safe\" but only \"possibly\n\t\t   unsafe\" (unless we're willing to deal with lots of false \n\t\t   positives).\n\n\t\t   Because of this we only complain about problems in debug mode, if we\n\t\t   enabled the rejection of unverifiable primes in release code we'd \n\t\t   Get Letters... */\n#ifndef NDEBUG\n\t\t{\n\t\tBN_ULONG modWord DUMMY_INIT;\n\n\t\tswitch( BN_get_word( g ) )\n\t\t\t{\n\t\t\tcase 2:\n\t\t\t\t/* Oakley primes, congruent to 11 mod 24 = leaks LSB, \n\t\t\t\t   congruent to 23 mod 24 = only covers half the possible \n\t\t\t\t   values */\n\t\t\t\tCK( BN_mod_word( &modWord, p, 24 ) );\n\t\t\t\tassert( !bnStatusError( bnStatus ) );\n\t\t\t\tassert_nofuzz( modWord == 11 || modWord == 23 );\n\t\t\t\tbreak;\n\n\t\t\tcase 5:\n\t\t\t\t/* Used by OpenSSH for no known reason */\n\t\t\t\tCK( BN_mod_word( &modWord, p, 10 ) );\n\t\t\t\tassert( !bnStatusError( bnStatus ) );\n\t\t\t\tassert_nofuzz( modWord == 3 || modWord == 7 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t}\n\t\t}\n\n\t/* Now we could do a full test for a safe prime, so both p and p' are \n\t   primes, but this is very slow and given the inability to reject \n\t   values that don't check out, it's not certain what would be gained\n\t   by it */\n#endif /* !NDEBUG */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Verify that qLen >= DLPPARAM_MIN_Q, qLen <= DLPPARAM_MAX_Q */\n\tlength = BN_num_bytes( q );\n\tif( length < DLPPARAM_MIN_Q || length > DLPPARAM_MAX_Q )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that q is not (obviously) composite.  Note that we can't \n\t   use primeProbable() because this updates the Montgomery CTX data, \n\t   it's OK to use it early in the keygen process before everything is \n\t   set up but not after the pkcInfo is fully initialised so we use\n\t   primeProbableFermat() instead */\n\tif( !primeSieve( q ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tassert( BN_is_zero( &( pkcInfo->montCTX2.N ) ) );\n\tCK( BN_MONT_CTX_set( &pkcInfo->montCTX2, q, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tstatus = primeProbableFermat( pkcInfo, q, &pkcInfo->montCTX2, &isPrime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isPrime )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that g is a generator of order q, i.e. that g^q mod p == 1.  \n\t   This check requires initialisation of values that may not have been \n\t   performed yet at this point, in which case the check is performed \n\t   inline in the main initCheckDLPkey() code below */\n\tif( !isFullyInitialised )\n\t\treturn( CRYPT_OK );\n\tCK( BN_mod_exp_mont( tmp, g, q, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !BN_is_one( tmp ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDLPPublicKey( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t  const BOOLEAN isPKCS3 )\n\t{\n\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &pkcInfo->dlpParam_p;\n\tBIGNUM *y = &pkcInfo->dlpParam_y, *tmp = &pkcInfo->tmp1;\n\tint bnStatus = BN_STATUS, length;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( isPKCS3 == TRUE || isPKCS3 == FALSE );\n\n\t/* Verify that yLen >= DLPPARAM_MIN_Y, yLen <= DLPPARAM_MAX_Y */\n\tlength = BN_num_bytes( y );\n\tif( length < DLPPARAM_MIN_Y || length > DLPPARAM_MAX_Y )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that y < p */\n\tif( BN_cmp( y, p ) >= 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that y has the correct order in the subgroup, i.e. that\n\t   y ^ q mod p == 1 */\n\tif( !isPKCS3 )\n\t\t{\n\t\tCK( BN_mod_exp_mont( tmp, y, &pkcInfo->dlpParam_q, p,\n\t\t\t\t\t\t\t &pkcInfo->bnCTX, &pkcInfo->dlpParam_mont_p ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( !BN_is_one( tmp ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform validity checks on the private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDLPPrivateKey( INOUT PKC_INFO *pkcInfo )\n\t{\n\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->p : &pkcInfo->dlpParam_p;\n\tconst BIGNUM *g = ( domainParams != NULL ) ? \\\n\t\t\t\t\t  &domainParams->g : &pkcInfo->dlpParam_g;\n\tBIGNUM *x = &pkcInfo->dlpParam_x, *y = &pkcInfo->dlpParam_y;\n\tBIGNUM *tmp = &pkcInfo->tmp1;\n\tint bnStatus = BN_STATUS, length;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Verify that xLen >= DLPPARAM_MIN_X, xLen <= DLPPARAM_MAX_X */\n\tlength = BN_num_bytes( x );\n\tif( length < DLPPARAM_MIN_X || length > DLPPARAM_MAX_X )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that g^x mod p == y */\n#ifndef CONFIG_FUZZ\n\tCK( BN_mod_exp_mont( tmp, g, x, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( BN_cmp( tmp, y ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n#endif /* CONFIG_FUZZ */\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGenerate/Initialise a DLP Key\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate and check a generic DLP key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateDLPkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) const int keyBits )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tBIGNUM *p = &pkcInfo->dlpParam_p;\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keyBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Generate the domain parameters */\n\tpkcInfo->keySizeBits = keyBits;\n\tstatus = generateDLPPublicValues( pkcInfo, keyBits, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the private key */\n\tstatus = generateDLPPrivateValue( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Since the keygen is randomised it may occur that the final size of \n\t   the public value that determines its nominal size is slightly smaller \n\t   than the requested nominal size.  To handle this we recalculate the \n\t   effective key size after we've finished generating the public value\n\t   that determines its nominal size */\n\tpkcInfo->keySizeBits = BN_num_bits( p );\n\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Calculate y */\n\tstatus = generateDLPPublicValue( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo, \n\t\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr->cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're\n\t   setting the checksum at this point there's no need to check the \n\t   return value */\n\t( void ) checksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  TRUE );\n\n\t/* Make sure that the generated values are valid */\n\tstatus = checkDLPDomainParameters( pkcInfo, FALSE, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkDLPPublicKey( pkcInfo, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkDLPPrivateKey( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that what we generated is still valid */\n\tif( cryptStatusError( \\\n\t\t\tchecksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t TRUE ) ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Generated DLP key memory corruption detected\" ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and check a DLP key.  If the isDH flag is set then it's a DH \n   key and we generate the x value (and by extension the y value) if it's\n   not present.  If the isPKCS3 flag is set then it's a PKCS #3 key rather\n   than FIPS 186/X9.42, without a q value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckDLPkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t const BOOLEAN isPKCS3 )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst DH_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst BIGNUM *p = &pkcInfo->dlpParam_p, *g = &pkcInfo->dlpParam_g;\n\tBIGNUM *x = &pkcInfo->dlpParam_x, *y = &pkcInfo->dlpParam_y;\n\tBIGNUM *tmp = &pkcInfo->tmp1;\n\tconst BOOLEAN isPrivateKey = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t\tCONTEXT_FLAG_ISPUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t FALSE : TRUE;\n\tBOOLEAN isDH, generatedX = FALSE;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isPKCS3 == TRUE || isPKCS3 == FALSE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tisDH = ( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_DH ) ? TRUE : FALSE;\n\n\t/* Make sure that the necessary key parameters have been initialised.  \n\t   Since PKCS #3 doesn't use the q parameter we only require it for \n\t   algorithms that specifically use FIPS 186 values.  DH keys are a bit\n\t   more complicated because they function as both public and private\n\t   keys so we don't require an x parameter if it's a DH key */\n\tif( domainParams == NULL )\n\t\t{ \n\t\tif( BN_is_zero( p ) || BN_is_zero( g ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( !isPKCS3 && BN_is_zero( &pkcInfo->dlpParam_q ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\tif( isPrivateKey && !isDH && BN_is_zero( x ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* If we're loading user-supplied parameters, check whether they match \n\t   any of the fixed domain parameters, and switch to those if they do */\n#if defined( USE_SSH ) || defined( USE_SSL )\n\tif( domainParams == NULL )\n\t\t{\n\t\tstatus = checkFixedDHparams( pkcInfo, &domainParams );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\n\t\t\t/* The user-supplied parameters match a set of fixed domain\n\t\t\t   parameters, use those directly */\n\t\t\tpkcInfo->domainParams = domainParams;\n\t\t\tBN_clear( &pkcInfo->dlpParam_p );\n\t\t\tBN_clear( &pkcInfo->dlpParam_q );\n\t\t\tBN_clear( &pkcInfo->dlpParam_g );\n\t\t\t}\n\t\t}\n#endif /* USE_SSH || USE_SSL */\n\tif( domainParams != NULL )\n\t\t{\n\t\t/* We're using fixed, known-good parameters */\n\t\tp = &domainParams->p; \n\t\tg = &domainParams->g;\n\t\t}\n\telse\n\t\t{\n\t\t/* We're using non-fixed domain parameters, make sure that they're \n\t\t   valid */\n\t\tstatus = checkDLPDomainParameters( pkcInfo, isPKCS3, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Evaluate the Montgomery form of p, needed for further operations */\n\tCK( BN_MONT_CTX_set( &pkcInfo->dlpParam_mont_p, p, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tpkcInfo->keySizeBits = BN_num_bits( p );\n\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Additional verification that would normally be performed in \n\t   checkDLPDomainParameters() but that requires initialisation of values \n\t   that haven't been set up yet when checkDLPDomainParameters() is \n\t   called */\n\tif( domainParams == NULL )\n\t\t{\n\t\tBOOLEAN isPrime;\n\n\t\t/* Verify that p is (probably) prime */\n\t\tstatus = primeProbableFermat( pkcInfo, p, &pkcInfo->dlpParam_mont_p, \n\t\t\t\t\t\t\t\t\t  &isPrime );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !isPrime )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\t/* Additional verification that we can perform for non-PKCS #3 (i.e. \n\t\t   FIPS 186) keys, verify that g is a generator of order q */\n\t\tif( !isPKCS3 )\n\t\t\t{\n\t\t\tCK( BN_mod_exp_mont( tmp, g, &pkcInfo->dlpParam_q, p, &pkcInfo->bnCTX,\n\t\t\t\t\t\t\t\t &pkcInfo->dlpParam_mont_p ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( !BN_is_one( tmp ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\t\t}\n\n\t/* If it's a DH key and there's no x value present, generate one now.  \n\t   This is needed because all DH keys are effectively private keys.  We \n\t   also update the context flags to reflect this change in status */\n\tif( isDH && BN_is_zero( x ) )\n\t\t{\n\t\tstatus = generateDLPPrivateValue( pkcInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCLEAR_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\tgeneratedX = TRUE;\n\t\t}\n\n\t/* Some sources (specifically PKCS #11) don't make y available for\n\t   private keys so if the caller is trying to load a private key with a\n\t   zero y value we calculate it for them.  First, we check to make sure\n\t   that we have x available to calculate y */\n\tif( BN_is_zero( y ) && BN_is_zero( x ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Calculate y if required.  This is a bit odd because if we've \n\t   generated a new x value it'll cause any existing y value to be \n\t   overwritten by a new one based on the newly-generated x value.  This \n\t   means that if we load a DH key from a certificate containing an \n\t   existing y value then this process will overwrite the value with a \n\t   new one, so that the context associated with the certificate will \n\t   contain a y value that differs from the one in the certificate.  This \n\t   is unfortunate, but again because of the DH key duality we need to \n\t   have both an x and a y value present otherwise the key is useless and \n\t   in order to get an x value we have to recreate the y value.  In any \n\t   case the use of DH in certificates is nonexistent, so it's not a \n\t   condition that we're likely to encounter.\n\n\t   This process (and DLP public-key ops in general) can be trapdoored as\n\t   follows to leak the x value over two consecutive exchanges (due to \n\t   Adam Young and Moti Yung, \"Kleptography: Using Cryptography Against \n\t   Cryptography\" and \"The Prevalence of Kleptographic Attacks on \n\t   Discrete-Log Based Cryptosystems\").  In the following, x and y are \n\t   the public and private values and xA and yA are the attacker's public \n\t   and private values (in this particular example x, y are used as DH \n\t   values and xA and yA as Elgamal values):\n\n\t\ty1 = g^x1 mod p, saving x1.\n\t\tz = g^x1 * yA^-(a * x1 - b) mod p, where a, b are constants.\n\t\tx2 = hash( z ).\n\t\ty2 = g^x2 mod p.\n\n\t   The attacker intercepts the two DH values and computes:\n\n\t\tr = y1^a * g^b mod p.\n\t\tz = y1 / r^xA mod p.\n\t\tif y2 == g^hash( z ) mod p then x1 is hash( z ).\n\t\tz = z / g^W, where W is a fixed odd integer.\n\t\tif y2 == g^hash( z ) mod p then x1 is hash( z ).\n\n\t   This is why it's a good idea to use public code for this sort of \n\t   thing... */\n\tif( BN_is_zero( y ) || generatedX )\n\t\t{\n\t\tstatus = generateDLPPublicValue( pkcInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Make sure that the public key is valid */\n\tstatus = checkDLPPublicKey( pkcInfo, isPKCS3 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the private key is valid */\n\tif( isPrivateKey || generatedX )\n\t\t{\n\t\tstatus = checkDLPPrivateKey( pkcInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo, \n\t\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr->cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're\n\t   setting the checksum at this point there's no need to check the \n\t   return value.  Note that this isn't the TOCTOU issue that it appears \n\t   to be because the bignum values are read by the calling code from \n\t   their stored form a second time and compared to the values that we're \n\t   checksumming here */\n\t( void ) checksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  ( isPrivateKey || generatedX ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DH || USE_DSA || USE_ELGAMAL */\n"
  },
  {
    "path": "deps/cl345/context/kg_ecc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib ECC Key Generation/Checking Routines\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 2006-2015\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"keygen.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"context/keygen.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enable various side-channel protection mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int enableSidechannelProtection( INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( isEccAlgo( cryptAlgo ) );\n\n\t/* Use constant-time modexp() to protect the private key from timing \n\t   channels.\n\n\t   (There really isn't much around in the way of side-channel protection \n\t   for the ECC computations, for every operation we use a new random \n\t   secret value as the point multiplier so there doesn't seem to be much \n\t   scope for timing attacks.  In the absence of anything better to do, \n\t   we set the constant-time modexp() flag just for warm fuzzies) */\n\tBN_set_flags( &pkcInfo->eccParam_d, BN_FLG_CONSTTIME );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tECC Information Access Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the nominal size of an ECC field based on an CRYPT_ECCCURVE_TYPE */\n\nstatic const MAP_TABLE fieldSizeMapTbl[] = {\n\t{ CRYPT_ECCCURVE_P256, 256 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P256, 256 },\n\t{ CRYPT_ECCCURVE_P384, 384 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P384, 384 },\n\t{ CRYPT_ECCCURVE_P521, 521 },\n\t{ CRYPT_ECCCURVE_BRAINPOOL_P512, 512 },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getECCFieldSize( IN_ENUM( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE fieldID,\n\t\t\t\t\t OUT_INT_Z int *fieldSize,\n\t\t\t\t\t const BOOLEAN isBits )\n\t{\n\tint value, status;\n\n\tassert( isWritePtr( fieldSize, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( fieldID, CRYPT_ECCCURVE ) );\n\tREQUIRES( isBits == TRUE || isBits == FALSE );\n\n\t/* Clear return value */\n\t*fieldSize = 0;\n\n\t/* Find the nominal field size for the given fieldID */\n\tstatus = mapValue( fieldID, &value, fieldSizeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( fieldSizeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\t*fieldSize = isBits ? value : bitsToBytes( value );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a CRYPT_ECCCURVE_TYPE based on a nominal ECC field size */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getECCFieldID( IN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC ) \\\n\t\t\t\t\t\tconst int fieldSize,\n\t\t\t\t   OUT_ENUM_OPT( CRYPT_ECCCURVE ) \n\t\t\t\t\t\tCRYPT_ECCCURVE_TYPE *fieldID )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( fieldID, sizeof( CRYPT_ECCCURVE_TYPE ) ) );\n\n\tREQUIRES( fieldSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t  fieldSize <= CRYPT_MAX_PKCSIZE_ECC );\n\n\t/* Clear return value */\n\t*fieldID = CRYPT_ECCCURVE_NONE;\n\n\t/* Find the fieldID for the given nominal field size.  We use a map \n\t   table because it's convenient but we can't use mapValue() because\n\t   we need a >= comparison rather then == */\n\tLOOP_MED( i = 0, fieldSizeMapTbl[ i ].source != CRYPT_ERROR && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( fieldSizeMapTbl, MAP_TABLE ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( bitsToBytes( fieldSizeMapTbl[ i ].destination ) >= fieldSize )\n\t\t\t{\n\t\t\t*fieldID = fieldSizeMapTbl[ i ].source;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( fieldSizeMapTbl, MAP_TABLE ) );\n\n\t/* Because of rounding issues in parameter bounds checking, combined \n\t   with the odd-length sizes chosen for some of the standard curves,\n\t   we can end up with a situation where the requested curve size is a \n\t   few bits over even the largest field size.  If we run into this \n\t   situation then we use the largest field size */\n\tif( fieldSize >= bitsToBytes( 521 ) )\n\t\t{\n\t\t*fieldID = CRYPT_ECCCURVE_P521;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGenerate an ECC Key\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate the ECC private value d and public value Q */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateECCPrivateValue( INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int keyBits )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tBIGNUM *d = &pkcInfo->eccParam_d, *p_2 = &pkcInfo->tmp1;\n\tint dLen, bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( keyBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  keyBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\n\t/* Generate the ECC private value d s.t. 2 <= d <= p-2.  Because the mod \n\t   p-2 is expensive we do a quick check to make sure that it's really \n\t   necessary before calling it */\n\tstatus = generateBignum( d, keyBits, 0xC0, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCKPTR( BN_copy( p_2, &domainParams->p ) );\n\tCK( BN_sub_word( p_2, 2 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( d, p_2 ) <= 0 )\n\t\t{\n\t\t/* We've got d within range, we're done */\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Trim d down to size.  Actually we get the upper bound as p-3, but \n\t   over a 256-bit (minimum) number range this doesn't matter */\n\tCK( BN_mod( d, d, p_2, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* If the value that we ended up with is too small, just generate a new \n\t   value one bit shorter, which guarantees that it'll fit the criteria \n\t   (the target is a suitably large random value, not the closest \n\t   possible fit within the range) */\n\tdLen = BN_num_bits( d );\n\tREQUIRES( dLen > 0 && dLen <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\tif( dLen < keyBits - 5 )\n\t\t{\n\t\tstatus = generateBignum( d, keyBits - 1, 0xC0, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateECCPublicValue( INOUT PKC_INFO *pkcInfo )\n\t{\n\tBIGNUM *d = &pkcInfo->eccParam_d;\n\tBIGNUM *qx = &pkcInfo->eccParam_qx, *qy = &pkcInfo->eccParam_qy;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *q = pkcInfo->tmpPoint;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Calculate the public-key value Q = d * G */\n\tCK( EC_POINT_mul( ecCTX, q, d, NULL, NULL, &pkcInfo->bnCTX ) );\n\tCK( EC_POINT_get_affine_coordinates_GFp( ecCTX, q, qx, qy,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck an ECC Key\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform validity checks on the public key.  In the tradition of these\n   documents, FIPS 186 and the X9.62 standard that it's derived from \n   occasionally use different names for the parameters, the following \n   mapping can be used to go from one to the other:\n\n\tFIPS 186\tX9.62/SECG\t\tDescription\n\t--------\t----------\t\t-----------\n\t\tp\t\t\tp\t\t\tFinite field Fp\n\t  a, b\t\t  a, b\t\t\tElliptic curve y^2 == x^3 + ax + b\n\t xg, yg\t\t xg, yg\t\t\tBase point G on the curve\n\t\tn\t\t\tn\t\t\tPrime n of order G\n\t\th\t\t\th\t\t\tCofactor\n\t--------\t---------\t\t-----------\n\t wx, wy\t\t xq, yq\t\t\tPublic key Q\n\t\td\t\t\td\t\t\tPrivate key\n\n   We have to make the PKC_INFO data non-const because the bignum code wants \n   to modify some of the values as it's working with them */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN checkComponentLength( const BIGNUM *component,\n\t\t\t\t\t\t\t\t\t const BIGNUM *p,\n\t\t\t\t\t\t\t\t\t const BOOLEAN lowerBoundZero )\n\t{\n\tint length;\n\n\tassert( isReadPtr( component, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( p, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( lowerBoundZero == TRUE || lowerBoundZero == FALSE );\n\n\t/* Make sure that the component is in the range 0...p - 1 (optionally\n\t   MIN_PKCSIZE_ECC if lowerBoundZero is false) */\n\tlength = BN_num_bytes( component );\n\tif( length < ( lowerBoundZero ? 0 : MIN_PKCSIZE_ECC ) || \\\n\t\tlength > CRYPT_MAX_PKCSIZE_ECC )\n\t\treturn( FALSE );\n\tif( BN_cmp( component, p ) >= 0 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/* Check that y^2 = x^3 + a*x + b is in the field GF(p) */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nBOOLEAN isPointOnCurve( const BIGNUM *x, const BIGNUM *y, \n\t\t\t\t\t\tconst BIGNUM *a, const BIGNUM *b, \n\t\t\t\t\t\tINOUT PKC_INFO *pkcInfo )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = &domainParams->p;\n\tBIGNUM *tmp1 = &pkcInfo->tmp1, *tmp2 = &pkcInfo->tmp2;\n\tBN_CTX *ctx = &pkcInfo->bnCTX;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isReadPtr( x, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( y, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( b, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( p, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckBignum( x ) );\n\tREQUIRES( sanityCheckBignum( y ) );\n\tREQUIRES( sanityCheckBignum( a ) );\n\tREQUIRES( sanityCheckBignum( b ) );\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\tCK( BN_mod_mul( tmp1, y, y, p, ctx ) );\n\tCK( BN_mod_mul( tmp2, x, x, p, ctx ) );\n\tCK( BN_mod_add( tmp2, tmp2, a, p, ctx ) );\n\tCK( BN_mod_mul( tmp2, tmp2, x, p, ctx ) );\n\tCK( BN_mod_add( tmp2, tmp2, b, p, ctx ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( FALSE );\n\tif( BN_cmp( tmp1, tmp2 ) != 0 )\n\t\treturn( FALSE );\n\t\n\treturn( TRUE );\n\t}\n\n/* Check the ECC domain parameters.  X9.62 specifies curves in the field \n   GF(q) of size q, where q is either a prime integer or equal to 2^m (with \n   m prime).  The following checks only handle curves where q is a prime \n   integer (the de facto universal standard), referred to as 'p' in the \n   following code */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkECCDomainParameters( INOUT PKC_INFO *pkcInfo,\n\t\t\t\t\t\t\t\t\t const BOOLEAN isFullyInitialised )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = &domainParams->p;\n\tconst BIGNUM *a = &domainParams->a, *b = &domainParams->b;\n\tconst BIGNUM *n = &domainParams->n, *h = &domainParams->h;\n\tconst BIGNUM *gx = &domainParams->gx, *gy = &domainParams->gy;\n\tBIGNUM *tmp1 = &pkcInfo->tmp1, *tmp2 = &pkcInfo->tmp2;\n\tBIGNUM *tmp3_h = &pkcInfo->tmp3;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *vp = pkcInfo->tmpPoint;\n\tconst BOOLEAN isStandardCurve = \\\n\t\t\t( pkcInfo->curveType != CRYPT_ECCCURVE_NONE ) ? TRUE : FALSE;\n\tBOOLEAN isPrime;\n\tint length, i, pLen, tmp3hBits, nBits, LOOP_ITERATOR;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( isFullyInitialised == TRUE || isFullyInitialised == FALSE );\n\n\t/* Verify that the domain parameter sizes are valid:\n\n\t\tpLen >= MIN_PKCSIZE_ECC, pLen <= CRYPT_MAX_PKCSIZE_ECC\n\t\ta, b >= 0, a, b <= p - 1\n\t\tgx, gy >= 0, gx, gy <= p - 1\n\t\tnLen >= MIN_PKCSIZE_ECC, nLen <= CRYPT_MAX_PKCSIZE_ECC\n\t\thLen >= 1, hLen <= CRYPT_MAX_PKCSIZE_ECC (if present) */\n\tlength = BN_num_bytes( p );\n\tif( length < MIN_PKCSIZE_ECC || length > CRYPT_MAX_PKCSIZE_ECC )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !checkComponentLength( a, p, TRUE ) || \\\n\t\t!checkComponentLength( b, p, TRUE ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !checkComponentLength( gx, p, TRUE ) || \\\n\t\t!checkComponentLength( gy, p, TRUE ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tlength = BN_num_bytes( n );\n\tif( length < MIN_PKCSIZE_ECC || length > CRYPT_MAX_PKCSIZE_ECC )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !BN_is_zero( h ) )\n\t\t{\n\t\tlength = BN_num_bytes( h );\n\t\tif( length < 1 || length > CRYPT_MAX_PKCSIZE_ECC )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Whether the domain parameters need to be validated each time that \n\t   they're loaded is left unclear in the specifications.  In fact \n\t   whether they, or the public key data, needs to be validated at all, \n\t   is left unspecified.  FIPS 186-3 is entirely silent on the matter and \n\t   X9.62 defers to an annex that contains two whole sentences that \n\t   merely say that it's someone else's problem.  In the absence of any \n\t   guidance we only validate domain parameters if they're supplied \n\t   externally.  Since the hardcoded internal values are checksummed,\n\t   there's not much need to perform additional validation on them.\n\t   \n\t   To activate domain validation on known curves, comment out the check\n\t   below */\n\tif( isStandardCurve )\n\t\treturn( CRYPT_OK );\n\n\t/* Verify that p is not (obviously) composite.  ECC doesn't use \n\t   Montgomery forms at this level so we have to set the necessary \n\t   context up explicitly just for the primality check */\n\tif( !primeSieve( p ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tCK( BN_MONT_CTX_set( &pkcInfo->montCTX1, p, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tstatus = primeProbableFermat( pkcInfo, p, &pkcInfo->montCTX1, &isPrime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isPrime )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that a, b and gx, gy are integers in the range 0...p - 1.  \n\t   This has already been done in the range checks performed earlier */\n\n\t/* Verify that (4a^3 + 27b^2) is not congruent to zero (mod p) */\n\tCK( BN_sqr( tmp1, a, &pkcInfo->bnCTX ) );\n\tCK( BN_mul( tmp1, tmp1, a, &pkcInfo->bnCTX ) );\n\tCK( BN_mul_word( tmp1, 4 ) );\n\tCK( BN_sqr( tmp2, b, &pkcInfo->bnCTX ) );\n\tCK( BN_mul_word( tmp2, 27 ) );\n\tCK( BN_add( tmp1, tmp1, tmp2 ) );\n\tCK( BN_mod( tmp1, tmp1, p, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_is_zero( tmp1 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that gy^2 is congruent to gx^3 + a*gx + b (mod p) */\n\tif( !isPointOnCurve( gx, gy, a, b, pkcInfo ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that:\n\n\t\tn is not (obviously) composite.\n\n\t\tn > 2^160 and n > 2^( 2s-1 ), where s is the \"security level\"\n\n\t\tThe second test is about ensuring that the subgroup order is large \n\t\tenough to make the ECDLP infeasible.  X9.62 measures infeasibility \n\t\tby the security level, and the test on 2^160 means that X9.62 \n\t\tconsiders that there is no worthwhile security below level 80.5.  \n\t\tThe security level has already been implicitly checked via the \n\t\tMIN_PKCSIZE_ECC constant, and n has already been tested above */\n\tif( !primeSieve( n ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tCK( BN_MONT_CTX_set( &pkcInfo->montCTX1, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tstatus = primeProbableFermat( pkcInfo, n, &pkcInfo->montCTX1, &isPrime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isPrime )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that n * G is the point at infinity.  This runs into a nasty \n\t   catch-22 where we have to initialise at least some of the ECC \n\t   parameter information in order to perform the check, but we can't \n\t   (safely) use the parameters before we've checked them.  To get around\n\t   this, if the values haven't been fully set up yet then we perform the \n\t   check inline in the initCheckECCKey() code */\n\tif( isFullyInitialised )\n\t\t{\n\t\tCK( EC_POINT_mul( ecCTX, vp, n, NULL, NULL, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tif( !EC_POINT_is_at_infinity( ecCTX, vp ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Compute the cofactor h.  The domain parameters may include h, but we \n\t   still want to compute it and check that we get the same value.  The \n\t   cofactor will be needed for verification of the \"anomalous condition\".\n\n\t   The curve size is #E = q + 1 - t, where t is the trace of Frobenius.  \n\t   Hasse's theorem guarantees that |t| <= 2*sqrt( q ).  Since we work \n\t   over a subgroup of size n, we know that n divides #E.  The cofactor h \n\t   is the integer such that #E = n * h.\n\n\t   In the X9.62 world, h is much smaller than n.  It follows that h can \n\t   be recomputed accurately from q and n, since there's only one integer \n\t   value for h that puts t in the proper range.  The formula given in \n\t   X9.62 is:\n\n\t\t\th = floor( ( sqrt( q ) + 1 )^2 / n )\n\n\t   which expands to:\n\n\t\t\th = floor( ( q + 1 + 2*sqrt( q ) ) / n )\n\n\t   which can be seen to map to the proper cofactor.  To check this we \n\t   compute a value which is one more than the maximum possible curve \n\t   order and divide by n.  If we then verify that h is small enough \n\t   (which is a requirement of X9.62) then we know that we've found the \n\t   proper cofactor.\n\n\t   The X9.62 formula is cumbersome because it requires a square root, \n\t   and we have to keep track of fractional bits as well.  The expanded \n\t   formula requires less fractional bits, but it still needs a square \n\t   root.  To avoid having to deal with this we can take advantage of the \n\t   fact that the conditions on the \"security level\" (n >= 2^160, \n\t   n >= 2^( 2s - 1 ) and h <= 2^( s / 8 ) for an integer s) imply that \n\t   n >= h^15.  A consequence of this is that n*h <= n^( 1 + 1/15 ).  \n\t   n * h is the curve order, which is close to q and lower than 2 * q.\n\n\t   Now, let qlen = log2( q ) (the size of q in bits, so that \n\t   2^( qlen-1 ) <= q < 2^qlen).  We then compute:\n\n\t      z = q + 2^( floor( qlen / 2 ) + 3 )\n\n\t   which is easily obtained by shifting one bit and performing an \n\t   addition.  It's then easily seen that z > #E.  Since we work in a \n\t   field of sufficiently large size (according to X9.62, qlen >= 160, \n\t   but we may accept slightly smaller values of q, but no less than \n\t   qlen = 128), we can show that n is much larger than\n\t   2^( floor( qlen / 2 ) + 4 ) (the size of n is at least 15/16ths of \n\t   that of q).  This implies that z - n is much smaller than the minimal \n\t   possible size of E.\n\n\t   We conclude that h = floor( z / n ), which is then the formula that \n\t   we apply.  We also check that h is no larger than 1/14th of n (using \n\t   14 instead of 15 avoids rounding issues since the size in bits of h \n\t   is not exactly equal to log2( h ), but it's still good enough for the \n\t   analysis above).\n\n\t   For the standard named curves in GF( p ) (the P-* NIST curves), h = 1\n\t   and is implicitly present */\n\tpLen = BN_num_bits( p );\n\tREQUIRES( pLen >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  pLen <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\tCK( BN_one( tmp1 ) );\n\tCK( BN_lshift( tmp1, tmp1, ( pLen >> 1 ) + 3 ) );\n\tCK( BN_add( tmp1, tmp1, p ) );\n\tCK( BN_div( tmp3_h, NULL, tmp1, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\ttmp3hBits = BN_num_bits( tmp3_h );\n\tnBits = BN_num_bits( n );\n\tREQUIRES( tmp3hBits > 0 && \\\n\t\t\t  tmp3hBits < bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\tREQUIRES( nBits > 0 && \\\n\t\t\t  nBits < bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\tif( tmp3hBits * 14 > nBits )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( isStandardCurve )\n\t\t{\n\t\t/* This code is executed only if the early exit for known curves \n\t\t   above has been deactivated */\n\t\tif ( !BN_is_one( tmp3_h ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( !BN_is_zero( h ) && BN_cmp( h, tmp3_h ) != 0 )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\th = tmp3_h;\n\n\t/* Verify that the MOV condition holds.  We use a MOV threshold B = 100\n\t   as per X9.62:2005 ('98 used B = 20).\n\t   \n\t   Mathematically, we want to make sure that the embedding degree of the \n\t   curve (for the subgroup that we're interested in) is greater than 100.  \n\t   The embedding degree is the lowest integer k such that r divides q^k-1 \n\t   (using the X9.62 notations where q is the field size, here held in \n\t   the local variable p, while r is the subgroup order size, which the \n\t   code below calls n).  The embedding degree always exists, except if \n\t   the curve is anomalous, i.e. the size of the curve is equal to the \n\t   field size.  Anomalous curves are a bad thing to have, so they're\n\t   checked for later on.\n\n\t   The Weil and Tate pairings allow the conversion of the ECDLP problem\n\t   into the \"plain\" DLP problem in GF( q^k ), the field extension of \n\t   GF( q ) of degree k, for which subexponential algorithms are known.  \n\t   For example if a curve is defined over a field GF(q) such that the \n\t   size of q is 256 bits and n also has a size close to 256 bits then we \n\t   expect the ECDLP to have a cost of about O( 2^128 ), i.e. it's very \n\t   much infeasible.  However if that curve happens to have an extension \n\t   degree k = 2 then a Weil or Tate pairing transforms the ECLDP into \n\t   the DLP in GF( q^2 ), a field of size 512 bits, for which the DLP is \n\t   technologically feasible.\n\n\t   For a random curve, k should be a large integer of the same size as \n\t   n, thus making q^k astronomically high.  For our purposes we want to \n\t   make sure that k isn't very small.  X9.62 checks that k > 100, which \n\t   is good enough, since if if k = 101 then the 256-bit ECDLP is \n\t   transformed into the 25856-bit DLP, which is awfully big and totally \n\t   infeasible as far as we know.\n\n\t   Computing the value of k is feasible if you can factor r - 1, but \n\t   this is expensive.  The X9.62 test computes q, q^2, q^3... q^100 \n\t   modulo n and checks that none of these equal one */\n\tCK( BN_one( tmp1 ) );\n\tCK( BN_mod( tmp2, p, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tLOOP_LARGE( i = 0, i < 100, i++ )\n\t\t{\n\t\tCK( BN_mod_mul( tmp1, tmp1, tmp2, n, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tif( BN_is_one( tmp1 ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Verify that the anomalous condition holds.  An \"anomalous curve\" is a \n\t   curve E defined over a field of size q such that #E = q, i.e. the \n\t   curve size is equal to the field size.  ECDLP on an anomalous curve \n\t   can be computed very efficiently, hence we want to avoid anomalous \n\t   curves.\n\n\t   The curve order is r * h, where h is the cofactor, which we computed \n\t   (and checked) above */\n\tCK( BN_mul( tmp1, n, h, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( tmp1, p ) == 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkECCPublicKey( INOUT PKC_INFO *pkcInfo )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = &domainParams->p, *n = &domainParams->n;\n\tBIGNUM *qx = &pkcInfo->eccParam_qx, *qy = &pkcInfo->eccParam_qy;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *q = pkcInfo->tmpPoint;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Verify that the public key parameter sizes are valid:\n\n\t\tqx, qy >= MIN_PKCSIZE_ECC, qx, qy <= p - 1 */\n\tif( !checkComponentLength( qx, p, FALSE ) || \\\n\t\t!checkComponentLength( qy, p, FALSE ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that Q is not the point at infinity */\n\tCK( EC_POINT_set_affine_coordinates_GFp( ecCTX, q, qx, qy,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( EC_POINT_is_at_infinity( ecCTX, q ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that qx, qy are elements in the field Fq, i.e. in the range\n\t   0...p - 1.  This has already been done in the range checks performed\n\t   earlier */\n\n\t/* Verify that Q is a point on the curve */\n\tif( !isPointOnCurve( qx, qy, &domainParams->a, &domainParams->b, \n\t\t\t\t\t\t pkcInfo ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that n * Q is the point at infinity */\n\tCK( EC_POINT_mul( ecCTX, q, NULL, q, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( !EC_POINT_is_at_infinity( ecCTX, q ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform validity checks on the private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkECCPrivateKey( INOUT PKC_INFO *pkcInfo )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tconst BIGNUM *p = &domainParams->p;\n\tBIGNUM *d = &pkcInfo->eccParam_d;\n\tBIGNUM *tmp1 = &pkcInfo->tmp1, *tmp2 = &pkcInfo->tmp2;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *q = pkcInfo->tmpPoint;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t/* Verify that the private key parameter sizes are valid:\n\n\t\td >= MIN_PKCSIZE_ECC, d <= p - 1 */\n\tif( !checkComponentLength( d, p, FALSE ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that Q = d * G */\n\tCK( EC_POINT_mul( ecCTX, q, d, NULL, NULL, &pkcInfo->bnCTX ) );\n\tCK( EC_POINT_get_affine_coordinates_GFp( ecCTX, q, tmp1, tmp2,\n\t\t\t\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_cmp( tmp1, &pkcInfo->eccParam_qx ) != 0 || \\\n\t\tBN_cmp( tmp2, &pkcInfo->eccParam_qy ) != 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGenerate/Initialise an ECC Key\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the mass of variables required by the ECC operations */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initECCVariables( INOUT PKC_INFO *pkcInfo )\n\t{\n\tconst ECC_DOMAINPARAMS *domainParams = pkcInfo->domainParams;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tEC_POINT *ecPoint = pkcInfo->ecPoint;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\n\tCK( EC_GROUP_set_curve_GFp( ecCTX, &domainParams->p, &domainParams->a, \n\t\t\t\t\t\t\t\t&domainParams->b, &pkcInfo->bnCTX ) );\n\tCK( EC_POINT_set_affine_coordinates_GFp( ecCTX, ecPoint, \n\t\t\t\t\t\t\t\t&domainParams->gx, &domainParams->gy, \n\t\t\t\t\t\t\t\t&pkcInfo->bnCTX ) );\n\tCK( EC_GROUP_set_generator( ecCTX, ecPoint, &domainParams->n, \n\t\t\t\t\t\t\t\t&domainParams->h ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Generate and check a generic ECC key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateECCkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\tconst int keyBits )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCRYPT_ECCCURVE_TYPE fieldID;\n\tint keySizeBits, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  keyBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Find the fieldID matching the requested key size.  This gets a bit\n\t   complicated because with fixed-parameter curves the key size is taken \n\t   to indicate the closest matching curve size (if we didn't do this and\n\t   required that the caller specify exact sizes to match the predefined\n\t   curves then they'd end up having to play guessing games to match\n\t   byte-valued key sizes to oddball curve sizes like P521).  To handle\n\t   this we first map the key size to the matching curve, and then \n\t   retrieve the actual key size in bits from the ECC parameter data */\n\tstatus = getECCFieldID( bitsToBytes( keyBits ), &fieldID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = loadECCparams( contextInfoPtr, fieldID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tkeySizeBits = pkcInfo->keySizeBits;\n\n\t/* Initialise the mass of variables required by the ECC operations */\n\tstatus = initECCVariables( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the private key */\n\tstatus = generateECCPrivateValue( pkcInfo, keySizeBits );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate the public-key value Q = d * G */\n\tstatus = generateECCPublicValue( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo,\n\t\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr->cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're\n\t   setting the checksum at this point there's no need to check the \n\t   return value */\n\t( void ) checksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  TRUE );\n\n\t/* Make sure that the generated values are valid */\n\tstatus = checkECCDomainParameters( pkcInfo, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkECCPublicKey( pkcInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkECCPrivateKey( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that what we generated is still valid */\n\tif( cryptStatusError( \\\n\t\t\tchecksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t TRUE ) ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Generated DLP key memory corruption detected\" ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and check an ECC key.  If the isECDH flag is set then it's an \n   ECDH key and we generate the d value (and by extension the Q value) if \n   it's not present */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckECCkey( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t const BOOLEAN isECDH )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst ECC_DOMAINPARAMS *domainParams;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst BIGNUM *p;\n\tEC_GROUP *ecCTX = pkcInfo->ecCTX;\n\tconst BOOLEAN isPrivateKey = TEST_FLAG( contextInfoPtr->flags,\n\t\t\t\t\t\t\t\t\t\t\tCONTEXT_FLAG_ISPUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t FALSE : TRUE;\n\tBOOLEAN generatedD = FALSE;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isECDH == TRUE || isECDH == FALSE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If we're loading a named curve then the public-key parameters may not \n\t   have been set yet, in which case we have to set them before we can\n\t   continue */\n\tif( pkcInfo->domainParams == NULL )\n\t\t{\n\t\tstatus = loadECCparams( contextInfoPtr, pkcInfo->curveType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tdomainParams = pkcInfo->domainParams;\n\tENSURES( domainParams != NULL );\n\tp = &domainParams->p;\n\n\t/* Make sure that the necessary key parameters have been initialised */\n\tif( !isECDH )\n\t\t{\n\t\tif( BN_is_zero( &pkcInfo->eccParam_qx ) || \\\n\t\t\tBN_is_zero( &pkcInfo->eccParam_qy ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( isPrivateKey && BN_is_zero( &pkcInfo->eccParam_d ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Make sure that the domain parameters are valid */\n\tstatus = checkECCDomainParameters( pkcInfo, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Initialise the mass of variables required by the ECC operations */\n\tstatus = initECCVariables( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Additional verification for ECC domain parameters, verify that \n\t   n * G is the point at infinity.  We have to do this at this point \n\t   rather than in checkECCDomainParameters() because it requires \n\t   initialisation of values that haven't been set up yet when \n\t   checkECCDomainParameters() is called */\n\tCK( EC_POINT_mul( ecCTX, pkcInfo->tmpPoint, &domainParams->n, \n\t\t\t\t\t  NULL, NULL, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( !EC_POINT_is_at_infinity( ecCTX, pkcInfo->tmpPoint ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* If it's an ECDH key and there's no d value present, generate one \n\t   now.  This is needed because all ECDH keys are effectively private \n\t   keys.  We also update the context flags to reflect this change in \n\t   status */\n\tif( isECDH && BN_is_zero( &pkcInfo->eccParam_d ) )\n\t\t{\n\t\tstatus = generateECCPrivateValue( pkcInfo, pkcInfo->keySizeBits );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCLEAR_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\tgeneratedD = TRUE;\n\t\t}\n\n\t/* Some sources (specifically PKCS #11) don't make Q available for\n\t   private keys so if the caller is trying to load a private key with a\n\t   zero Q value we calculate it for them.  First, we check to make sure\n\t   that we have d available to calculate Q */\n\tif( BN_is_zero( &pkcInfo->eccParam_qx ) && \\\n\t\tBN_is_zero( &pkcInfo->eccParam_d ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Calculate Q if required.  This is a bit odd because if we've \n\t   generated a new d value it'll cause any existing Q value to be \n\t   overwritten by a new one based on the newly-generated Q value.  This \n\t   means that if we load an ECDH key from a certificate containing an \n\t   existing Q value then this process will overwrite the value with a \n\t   new one, so that the context associated with the certificate will \n\t   contain a Q value that differs from the one in the certificate.  This \n\t   is unfortunate, but again because of the ECDH key duality we need to \n\t   have both a d and a Q value present otherwise the key is useless and \n\t   in order to get a d value we have to recreate the Q value */\n\tif( BN_is_zero( &pkcInfo->eccParam_qx ) || generatedD )\n\t\t{\n\t\tstatus = generateECCPublicValue( pkcInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Make sure that the public key is valid */\n\tstatus = checkECCPublicKey( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the private key is valid */\n\tif( isPrivateKey || generatedD )\n\t\t{\n\t\tstatus = checkECCPrivateKey( pkcInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* ECCs are somewhat weird in that the nominal key size is defined by\n\t   executive fiat based on the curve type.  For named curves this is \n\t   fairly simple but for curves loaded as raw parameters we have to\n\t   recover the nominal value from the ECC p parameter */\n\tif( pkcInfo->keySizeBits <= 0 )\n\t\t{\n\t\tpkcInfo->keySizeBits = BN_num_bits( p );\n\t\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\t\t}\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo, \n\t\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr->cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're \n\t   setting the checksum at this point there's no need to check the \n\t   return value.  Note that this isn't the TOCTOU issue that it appears \n\t   to be because the bignum values are read by the calling code from \n\t   their stored form a second time and compared to the values that we're \n\t   checksumming here */\n\t( void ) checksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo,\n\t\t\t\t\t\t\t\t  ( isPrivateKey || generatedD ) ? \\\n\t\t\t\t\t\t\t\t    TRUE : FALSE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n"
  },
  {
    "path": "deps/cl345/context/kg_prime.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Prime Generation/Checking Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The Usenet Oracle has pondered your question deeply.\n   Your question was:\n\n   > O Oracle Most Wise,\n   >\n   > What is the largest prime number?\n\n   And in response, thus spake the Oracle:\n\n   } This is a question which has stumped some of the best minds in\n   } mathematics, but I will explain it so that even you can understand it.\n   } The first prime is 2, and the binary representation of 2 is 10.\n   } Consider the following series:\n   }\n   }\tPrime\tDecimal Representation\tRepresentation in its own base\n   }\t1st\t\t2\t\t\t\t\t\t10\n   }\t2nd\t\t3\t\t\t\t\t\t10\n   }\t3rd\t\t5\t\t\t\t\t\t10\n   }\t4th\t\t7\t\t\t\t\t\t10\n   }\t5th\t\t11\t\t\t\t\t\t10\n   }\t6th\t\t13\t\t\t\t\t\t10\n   }\t7th\t\t17\t\t\t\t\t\t10\n   }\n   } From this demonstration you can see that there is only one prime, and\n   } it is ten. Therefore, the largest prime is ten.\n\t\t\t\t\t\t\t\t\t\t\t\t\t-- The Usenet Oracle */\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"keygen.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"context/keygen.h\"\n#endif /* Compiler-specific includes */\n\n/* Enable the following to cross-check the Miller-Rabin test using an \n   alternative form of the Miller-Rabin test that merges the test loop and \n   the modexp at the start.  Note that this displays diagnostic timing \n   output and expects to use Pentium performance counters for timing so it's \n   only (optionally) enabled for Win32 debug */\n\n#if defined( __WIN32__ ) && !defined( NDEBUG ) && 0\n  #define CHECK_PRIMETEST\n#endif /* Win32 debug */\n\n#ifdef USE_PKC\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* BN_cmp() is a bit of a tricky function because there's no way to signal\n   an error from it.  This means that when performing a compare for \n   primality-testing purposes an error return looks like a valid compare \n   result.  To deal with this, we implement a fail-open version of BN_cmp() \n   that validates its parameters as BN_cmp() would and returns a compare-\n   failed status, specifically a less-than result, if there's a problem.  \n   Since the primality-checking functions treat a compare-equal (status == \n   0) as success, this means that we can never erroneously report a non-\n   prime as prime due to an error occurring */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int BN_cmp_checked( const BIGNUM *bignum1, const BIGNUM *bignum2 )\n\t{\n\tif( !sanityCheckBignum( bignum1 ) || !sanityCheckBignum( bignum2 ) )\n\t\treturn( -1 );\n\treturn( BN_cmp( bignum1, bignum2 ) );\n\t}\n\n/* Get random data, used for seeding bignums for prime generation.  This is\n   just a wrapper for krnlSendMessage() that can be overridden by a user-\n   defined function if required, for example for deterministic DLP parameter\n   generation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int getRandomData( INOUT_OPT void *dummy, \n\t\t\t\t\t\t  OUT_BUFFER_FIXED( noBytes ) void *buffer, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int noBytes )\n\t{\n\tMESSAGE_DATA msgData;\n\n\tassert( isWritePtrDynamic( buffer, noBytes ) );\n\n\tREQUIRES( dummy == NULL );\n\tREQUIRES( noBytes > 0 && noBytes <= CRYPT_MAX_PKCSIZE );\n\t\n\tsetMessageData( &msgData, buffer, noBytes );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_RANDOM ) );\n\t}\n\n#ifdef CHECK_PRIMETEST\n\n/* Witness function, modified from original BN code as found at a UFO crash \n   site.  This looks nothing like a standard Miller-Rabin test because it \n   merges the modexp that usually needs to be performed as the first \n   portion of the test process and the remainder of the checking.  Destroys \n   param6 + 7 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5, 6, 7 ) ) \\\nstatic int witnessOld( INOUT PKC_INFO *pkcInfo, INOUT BIGNUM *a, \n\t\t\t\t\t   INOUT BIGNUM *n1, INOUT BIGNUM *mont_n1, \n\t\t\t\t\t   INOUT BIGNUM *mont_1, INOUT BN_MONT_CTX *montCTX_n )\n\t{\n\tBIGNUM *y = &pkcInfo->param6;\n\tBIGNUM *yPrime = &pkcInfo->param7;\t\t/* Safe to destroy */\n\tBN_CTX *ctx = &pkcInfo->bnCTX;\n\tBIGNUM *mont_a = &ctx->bn[ ctx->tos++ ];\n\tconst int k = BN_num_bits( n1 );\n\tint i, bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( a, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( n, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( n1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( mont_n1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( mont_1, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( montCTX_n, sizeof( BN_MONT_CTX ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( a ) );\n\tREQUIRES( sanityCheckBignum( n1 ) );\n\tREQUIRES( sanityCheckBignum( mont_n1 ) );\n\tREQUIRES( sanityCheckBignum( mont_1 ) );\n\tREQUIRES( sanityCheckBNMontCTX( montCTX_n ) );\n\tREQUIRES( k > 0 && k <= bytesToBits( CRYPT_MAX_PKCSIZE );\n\n\t/* All values are manipulated in their Montgomery form so before we \n\t   begin we have to convert a to this form as well */\n\tif( !BN_to_montgomery( mont_a, a, montCTX_n, &pkcInfo->bnCTX ) )\n\t\t{\n\t\tctx->tos--;\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\tCKPTR( BN_copy( y, mont_1 ) );\n\tfor ( i = k - 1; i >= 0; i-- )\n\t\t{\n\t\t/* Perform the y^2 mod n check.  yPrime = y^2 mod n, if yPrime == 1\n\t\t   it's composite (this condition is virtually never met) */\n\t\tCK( BN_mod_mul_montgomery( yPrime, y, y, montCTX_n, \n\t\t\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) || \\\n\t\t\t( !BN_cmp( yPrime, mont_1 ) && \\\n\t\t\t  BN_cmp( y, mont_1 ) && BN_cmp( y, mont_n1 ) ) )\n\t\t\t{\n\t\t\tctx->tos--;\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* Perform another step of the modexp */\n\t\tif( BN_is_bit_set( n1, i ) )\n\t\t\t{\n\t\t\tCK( BN_mod_mul_montgomery( y, yPrime, mont_a, montCTX_n, \n\t\t\t\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\t{\n\t\t\t\tctx->tos--;\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tBIGNUM *tmp;\n\n\t\t\t/* Input and output to modmult can't be the same, so we have to\n\t\t\t   swap the pointers */\n\t\t\ttmp = y; y = yPrime; yPrime = tmp;\n\t\t\t}\n\t\t}\n\tctx->tos--;\n\n\t/* Finally we have y = a^u mod n.  If y == 1 (mod n) it's prime,\n\t   otherwise it's composite */\n\treturn( BN_cmp( y, mont_1 ) ? TRUE : FALSE );\n\t}\n\n/* Perform noChecks iterations of the Miller-Rabin probabilistic primality \n   test.  Destroys param8, tmp1-3, mont1 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int primeProbableOld( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t INOUT BIGNUM *candidate, \n\t\t\t\t\t\t\t IN_RANGE( 1, 100 ) const int noChecks )\n\t{\n\tBIGNUM *check = &pkcInfo->tmp1;\n\tBIGNUM *candidate_1 = &pkcInfo->tmp2;\n\tBIGNUM *mont_candidate_1 = &pkcInfo->tmp3;\n\tBIGNUM *mont_1 = &pkcInfo->param8;\t\t/* Safe to destroy */\n\tBN_MONT_CTX *montCTX_candidate = &pkcInfo->montCTX1;\n\tint i, bnStatus = BN_STATUS, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( candidate, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( noChecks >= 1 && noChecks <= 100 );\n\n\t/* Set up various values */\n\tCK( BN_MONT_CTX_set( montCTX_candidate, candidate, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tCK( BN_to_montgomery( mont_1, BN_value_one(), montCTX_candidate, \n\t\t\t\t\t\t  &pkcInfo->bnCTX ) );\n\tCKPTR( BN_copy( candidate_1, candidate ) );\n\tCK( BN_sub_word( candidate_1, 1 ) );\n\tCK( BN_to_montgomery( mont_candidate_1, candidate_1, montCTX_candidate, \n\t\t\t\t\t\t  &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Perform n iterations of Miller-Rabin */\n\tLOOP_LARGE( i = 0, i < noChecks, i++ )\n\t\t{\n\t\t/* Instead of using a bignum for the Miller-Rabin check we use a\n\t\t   series of small primes.  The reason for this is that if bases a1\n\t\t   and a2 are strong liars for n then their product a1*a2 is also \n\t\t   very likely to be a strong liar so using a composite base \n\t\t   doesn't give us any great advantage.  In addition an initial test \n\t\t   with a=2 is beneficial since most composite numbers will fail \n\t\t   Miller-Rabin with a=2, and exponentiation with base 2 is faster \n\t\t   than general-purpose exponentiation.  Finally, using small values \n\t\t   instead of random bignums is both significantly more efficient \n\t\t   and much easier on the RNG.   In theory in order to use the first \n\t\t   noChecks small primes as the base instead of using random bignum \n\t\t   bases we would have to assume that the extended Riemann \n\t\t   hypothesis holds (without this, which allows us to use values \n\t\t   1 < check < 2 * log( candidate )^2, we'd have to pick random \n\t\t   check values as required for Monte Carlo algorithms), however the \n\t\t   requirement for random bases assumes that the candidates could be \n\t\t   chosen maliciously to be pseudoprime to any reasonable list of \n\t\t   bases, thus requiring random bases to evade the problem.  \n\t\t   Obviously we're not going to do this so one base is as good as \n\t\t   another, and small primes work well (even a single Fermat test \n\t\t   has a failure probability of around 10e-44 for 512-bit primes if \n\t\t   you're not trying to cook the primes, this is why Fermat works as \n\t\t   a verification of the Miller-Rabin test in generatePrime()) */\n\t\tBN_set_word( check, primeTbl[ i ] );\n\t\tstatus = witnessOld( pkcInfo, check, candidate, candidate_1, \n\t\t\t\t\t\t\t mont_candidate_1, mont_1, montCTX_candidate );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( status )\n\t\t\treturn( FALSE );\t/* It's not a prime */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* It's prime */\n\treturn( TRUE );\n\t}\n#endif /* CHECK_PRIMETEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGenerate a Prime Number\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Non-primality witness-of-compositeness function:\n\n\tx(0) = a^u mod n\n\tif x(0) = 1 || x(0) = n - 1 \n\t\treturn \"probably-prime\"\n\n\tfor i = 1 to k\n\t\tx(i) = x(i-1)^2 mod n\n\t\tif x(i) = n - 1\n\t\t\treturn \"probably-prime\"\n\t\tif x(i) = 1\n\t\t\treturn \"composite\";\n\treturn \"composite\"\n\n   Since it's a yes-biased Monte Carlo algorithm this witness function can\n   only answer \"probably-prime\" so we reduce the uncertainty by iterating\n   for the Miller-Rabin test.  Destroys a.\n   \n   Note that this returns an error status or a boolean TRUE/FALSE so we give\n   the return value as CHECK_RETVAL_RANGE( FALSE, TRUE ) rather than\n   CHECK_RETVAL_BOOL */\n\nCHECK_RETVAL_RANGE( FALSE, TRUE ) STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5, 7 ) ) \\\nstatic int witness( INOUT PKC_INFO *pkcInfo, INOUT BIGNUM *a, \n\t\t\t\t\tconst BIGNUM *n, const BIGNUM *n_1, const BIGNUM *u, \n\t\t\t\t\tIN_LENGTH_PKC const int k, \n\t\t\t\t\tINOUT BN_MONT_CTX *montCTX_n )\n\t{\n\tint i, bnStatus = BN_STATUS, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( a, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( n, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( n_1, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( u, sizeof( BIGNUM ) ) );\n\tassert( isReadPtr( montCTX_n, sizeof( BN_MONT_CTX ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( a ) );\n\tREQUIRES( sanityCheckBignum( n ) );\n\tREQUIRES( sanityCheckBignum( n_1 ) );\n\tREQUIRES( sanityCheckBignum( u ) );\n\tREQUIRES( sanityCheckBNMontCTX( montCTX_n ) );\n\tREQUIRES( k >= 1 && k <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* x(0) = a^u mod n.  If x(0) == 1 || x(0) == n - 1 it's probably\n\t   prime */\n\tCK( BN_mod_exp_mont( a, a, u, n, &pkcInfo->bnCTX, montCTX_n ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( BN_is_one( a ) || !BN_cmp_checked( a, n_1 ) )\n\t\treturn( FALSE );\t\t/* Probably prime */\n\n\tLOOP_LARGE( i = 1, i < k, i++ )\n\t\t{\n\t\t/* x(i) = x(i-1)^2 mod n */\n\t\tCK( BN_mod_mul( a, a, a, n, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tif( !BN_cmp_checked( a, n_1 ) )\n\t\t\treturn( FALSE );\t/* Probably prime */\n\t\tif( BN_is_one( a ) )\n\t\t\t{\n\t\t\t/* At this point we could perform an additional test:\n\n\t\t\t\tg = gcd( x(i-1)-1, n )\n\n\t\t\t  If g > 1 then the candidate is composite with factor g, if not \n\t\t\t  then it's composite but not a power of a prime, i.e. there are \n\t\t\t  no x, y >= 2 s.t. x^y == n.  This can be used when checking \n\t\t\t  the RSA modulus for validity, however it requires an \n\t\t\t  additional temporary bignum that we don't really have.  In \n\t\t\t  theory we could overload pkcInfo->blind1, which isn't used\n\t\t\t  yet when primeProbable() is called, but this is asking for\n\t\t\t  trouble if any code path ever sets blind1 before \n\t\t\t  primeProbable() is called.  In any case it's uncertain whether\n\t\t\t  all of this is worth the effort... */\n\t\t\treturn( TRUE );\t\t/* Composite */\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckBignum( a ) );\n\n\treturn( TRUE );\n\t}\n\n/* Perform noChecks iterations of the Miller-Rabin probabilistic primality \n   test (n = candidate prime, a = randomly-chosen check value):\n\n\tevaluate u s.t. n - 1 = 2^k * u, u odd\n\n\tfor i = 1 to noChecks\n\t\tif witness( a, n, n-1, u, k )\n\t\t\treturn \"composite\"\n\n\treturn \"prime\"\n\n  Destroys tmp1-3, mont1 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint primeProbable( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t   INOUT BIGNUM *n, \n\t\t\t\t   IN_RANGE( 1, 100 ) const int noChecks,\n\t\t\t\t   OUT BOOLEAN *isPrime )\n\t{\n\tBIGNUM *a = &pkcInfo->tmp1, *n_1 = &pkcInfo->tmp2, *u = &pkcInfo->tmp3;\n\tint i, k, bnStatus = BN_STATUS, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( n, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( isPrime, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( n ) );\n\tREQUIRES( noChecks >= 1 && noChecks <= 100 );\n\n\t/* Clear return value */\n\t*isPrime = FALSE;\n\n\t/* Set up various values */\n\tCK( BN_MONT_CTX_set( &pkcInfo->montCTX1, n, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Evaluate u as n - 1 = 2^k * u.  Obviously the less one bits in the \n\t   LSBs of n the more efficient this test becomes, however with a \n\t   randomly-chosen n value we get an exponentially-decreasing chance \n\t   of losing any bits after the first one, which will always be zero \n\t   since n starts out being odd */\n\tCKPTR( BN_copy( n_1, n ) );\n\tCK( BN_sub_word( n_1, 1 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tLOOP_LARGE( k = 1, !BN_is_bit_set( n_1, k ), k++ )\n\t\t/* No loop body */ ;\n\tENSURES( LOOP_BOUND_OK );\n\tCK( BN_rshift( u, n_1, k ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Perform n iterations of Miller-Rabin */\n\tLOOP_LARGE( i = 0, i < noChecks, i++ )\n\t\t{\n\t\t/* Instead of using a bignum for the Miller-Rabin check we use a\n\t\t   series of small primes.  The reason for this is that if bases a1\n\t\t   and a2 are strong liars for n then their product a1 * a2 is also \n\t\t   very likely to be a strong liar so using a composite base \n\t\t   doesn't give us any great advantage.  In addition an initial test \n\t\t   with a = 2 is beneficial since most composite numbers will fail \n\t\t   Miller-Rabin with a = 2, and exponentiation with base 2 is faster \n\t\t   than general-purpose exponentiation.  Finally, using small values \n\t\t   instead of random bignums is both significantly more efficient \n\t\t   and much easier on the RNG.\n\t\t   \n\t\t   In theory in order to use the first noChecks small primes as the \n\t\t   base instead of using random bignum bases we would have to assume \n\t\t   that the extended Riemann hypothesis holds (without this, which \n\t\t   allows us to use values 1 < check < 2 * log( candidate )^2, we'd \n\t\t   have to pick random check values as required for Monte Carlo \n\t\t   algorithms), however the requirement for random bases assumes that \n\t\t   the candidates could be chosen maliciously to be pseudoprime to \n\t\t   any reasonable list of bases, thus requiring random bases to \n\t\t   evade the problem.  \n\n\t\t   Obviously we're not going to do this so one base is as good as \n\t\t   another, and small primes work well (even a single Fermat test \n\t\t   has a failure probability of around 10e-44 for 512-bit primes if \n\t\t   you're not trying to cook the primes, this is why Fermat works as \n\t\t   a verification of the Miller-Rabin test in generatePrime()).\n\t\t   \n\t\t   There is one situation in which we could run into problems with\n\t\t   maliciously-chosen candidates and that's if the values are used \n\t\t   in SRP, see Bleichenbacher's \"Breaking a Cryptographic Protocol \n\t\t   with Pseudoprimes\", PKC'05.  We don't do SRP or similar PAKEs, if\n\t\t   we ever do then the primality test will have to be strengthened */\n\t\tCK( BN_set_word( a, getSieveEntry( i ) ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\tstatus = witness( pkcInfo, a, n, n_1, u, k, &pkcInfo->montCTX1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( status )\n\t\t\t{\n\t\t\t*isPrime = FALSE;\n\t\t\treturn( CRYPT_OK );\t/* It's not a prime */\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckBignum( n ) );\n\n\t/* It's prime */\n\t*isPrime = TRUE;\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a Fermat primality test to the base 2 as a quick screening \n   alternative to a full M-R test */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint primeProbableFermat( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t const BIGNUM *n,\n\t\t\t\t\t\t INOUT BN_MONT_CTX *montCTX_n,\n\t\t\t\t\t\t OUT BOOLEAN *isPrime )\n\t{\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isReadPtr( n, sizeof( BIGNUM ) ) );\n\tassert( isWritePtr( montCTX_n, sizeof( BN_MONT_CTX ) ) );\n\tassert( isWritePtr( isPrime, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( n ) );\n\tREQUIRES( !BN_is_zero( &montCTX_n->N ) );\n\n\t/* Clear return value */\n\t*isPrime = FALSE;\n\n\t/* Perform a Fermat test to the base 2 (Fermat = a^p-1 mod p == 1 -> \n\t   a^p mod p == a, for all a).  This isn't as reliable as Miller-Rabin \n\t   but can use the fast BN_mod_exp_mont_word() to perform a (somewhat)\n\t   quicker screening check */\n\tCK( BN_mod_exp_mont_word( &pkcInfo->tmp1, 2, n, n, &pkcInfo->bnCTX, \n\t\t\t\t\t\t\t  montCTX_n ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( !BN_is_word( &pkcInfo->tmp1, 2 ) )\n\t\t{\n\t\t*isPrime = FALSE;\n\t\treturn( CRYPT_OK );\t/* It's not a prime */\n\t\t}\n\n\t/* It's prime */\n\t*isPrime = TRUE;\n\treturn( CRYPT_OK );\n\t}\n\n/* Generate a prime.  This isn't of any special form, e.g. a strong prime,\n   since it's only relevant for Pollard's p - 1 algorithm and with smaller\n   prime sizes that we're working with, algorithms like NFS aren't affected.\n   In addition if the strong primes are generated according to the one \n   standard that actually requires them, X9.31, then there's a significant\n   loss of entropy, around 20 bits, due to the low density of \"strong\" \n   primes, i.e. a great many possible primes get discarded in favour of the \n   \"strong\" one, see \"The Million-Key Question: Investigating the Origins of \n   RSA Public Keys\" by Svenda et al.\n\n   If the exponent is present this will also verify that \n   gcd( (p - 1)(q - 1), exponent ) = 1, which is required for RSA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int generatePrimeEx( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\tINOUT BIGNUM *candidate, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t\t\t\tIN_INT_OPT const long exponent,\n\t\t\t\t\t\t\tIN_OPT const GET_RANDOM_INFO *getRandomInfo )\n\t{\n\tconst GETRANDOMDATA_FUNCTION getRandomFunction = \\\n\t\t\t( getRandomInfo != NULL ) ? \\\n\t\t\t\t( GETRANDOMDATA_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( getRandomInfo->getRandomFunction ) : getRandomData;\n\tvoid *getRandomState = ( getRandomInfo != NULL ) ? \\\n\t\t\tgetRandomInfo->getRandomState : NULL;\n\tconst int noChecks = getNoPrimeChecks( noBits );\n\tBOOLEAN *sieveArray, primeFound = FALSE;\n\tint oldOffset = 0, bnStatus = BN_STATUS, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( candidate, sizeof( BIGNUM ) ) );\n\tassert( getRandomInfo == NULL || \\\n\t\t\tisReadPtr( getRandomInfo, sizeof( GET_RANDOM_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( candidate ) );\n\tREQUIRES( ( exponent == CRYPT_UNUSED && \\\n\t\t\t\tnoBits >= 120 && noBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ) || \\\n\t\t\t  ( exponent != CRYPT_UNUSED && \\\n\t\t\t\tnoBits >= bytesToBits( MIN_PKCSIZE ) / 2 && \\\n\t\t\t\tnoBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) ) );\n\t\t\t  /* The value of 120 doesn't correspond to any key size but is \n\t\t\t     the minimal value for a prime that we'd generate using the \n\t\t\t\t Lim-Lee algorithm */\n\tREQUIRES( exponent == CRYPT_UNUSED || \\\n\t\t\t  ( exponent >= 17 && exponent < INT_MAX - 1000 && \\\n\t\t\t  getRandomInfo == NULL ) );\n\tREQUIRES( getRandomFunction != NULL );\n\n\t/* Start with a cryptographically strong odd random number (\"There is a \n\t   divinity in odd numbers\", William Shakespeare, \"Merry Wives of \n\t   Windsor\").  We set the two high bits so that (when generating RSA \n\t   keys) pq will end up exactly 2n bits long */\n\tstatus = generateBignumEx( candidate, noBits, 0xC0, 0x1, NULL, 0, \n\t\t\t\t\t\t\t   getRandomInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Allocate the array */\n\tif( ( sieveArray = clAlloc( \"generatePrime\", \\\n\t\t\t\t\t\t\t\tSIEVE_SIZE * sizeof( BOOLEAN ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\n\tLOOP_LARGE_CHECK( !primeFound && !cryptStatusError( status ) )\n\t\t{\n\t\tint offset, startPoint, LOOP_ITERATOR_ALT;\n\n\t\t/* Set up the sieve array for the number and pick a random starting\n\t\t   point */\n\t\tstatus = initSieve( sieveArray, SIEVE_SIZE, candidate );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getRandomFunction( getRandomState, &startPoint, \n\t\t\t\t\t\t\t\t\t\tsizeof( int ) );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tstartPoint &= SIEVE_SIZE - 1;\n\t\tif( startPoint <= 0 )\n\t\t\tstartPoint = 1;\t\t/* Avoid getting stuck on zero */\n\n\t\t/* Perform a random-probing search for a prime (poli, poli, di \n\t\t   umbuendo).  \"On generation of probably primes by incremental\n\t\t   search\" by Jrgen Brandt and Ivan Damgrd, Proceedings of\n\t\t   Crypto'92, (LNCS Vol.740), p.358, shows that for an n-bit\n\t\t   number we'll find a prime after O( n ) steps by incrementing\n\t\t   the start value by 2 each time */\n\t\tLOOP_EXT_ALT( offset = nextSievePosition( startPoint ), \n\t\t\t\t\t  offset != startPoint, \n\t\t\t\t\t  offset = nextSievePosition( offset ), SIEVE_SIZE + 1 )\n\t\t\t{\n#ifdef CHECK_PRIMETEST\n\t\t\tLARGE_INTEGER tStart, tStop;\n\t\t\tBOOLEAN passedFermat, passedOldPrimeTest;\n\t\t\tint oldTicks, newTicks, ratio;\n#endif /* CHECK_PRIMETEST */\n\t\t\tBN_ULONG remainder DUMMY_INIT;\n\n\t\t\tENSURES( offset > 0 && offset < SIEVE_SIZE );\n\t\t\tENSURES( offset != oldOffset );\n\n\t\t\t/* If this candidate is divisible by anything, continue */\n\t\t\tif( sieveArray[ offset ] != 0 )\n\t\t\t\tcontinue;\n\n\t\t\t/* Adjust the candidate by the number of nonprimes that we've\n\t\t\t   skipped */\n\t\t\tif( offset > oldOffset )\n\t\t\t\t{\n\t\t\t\tCK( BN_add_word( candidate, ( offset - oldOffset ) * 2 ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tCK( BN_sub_word( candidate, ( oldOffset - offset ) * 2 ) );\n\t\t\t\t}\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\t{\n\t\t\t\tstatus = getBnStatus( bnStatus );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\toldOffset = offset;\n\n#if defined( CHECK_PRIMETEST )\n\t\t\t/* Perform a Fermat test to the base 2 */\n\t\t\tCK( BN_MONT_CTX_set( &pkcInfo->montCTX1, candidate, \n\t\t\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\t\t\tpassedFermat = primeProbableFermat( pkcInfo, candidate,\n\t\t\t\t\t\t\t\t\t\t\t\t&pkcInfo->montCTX1 );\n\n\t\t\t/* Perform the older probabilistic test */\n\t\t\tQueryPerformanceCounter( &tStart );\n\t\t\tstatus = primeProbableOld( pkcInfo, candidate, noChecks );\n\t\t\tQueryPerformanceCounter( &tStop );\n\t\t\tassert( tStart.HighPart == tStop.HighPart );\n\t\t\toldTicks = tStop.LowPart - tStart.LowPart;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tpassedOldPrimeTest = status;\n\n\t\t\t/* Perform the probabilistic test */\n\t\t\tQueryPerformanceCounter( &tStart );\n\t\t\tstatus = primeProbable( pkcInfo, candidate, noChecks );\n\t\t\tQueryPerformanceCounter( &tStop );\n\t\t\tassert( tStart.HighPart == tStop.HighPart );\n\t\t\tnewTicks = tStop.LowPart - tStart.LowPart;\n\t\t\tratio = ( oldTicks * 100 ) / newTicks;\n\t\t\tprintf( \"%4d bits, old MR = %6d ticks, new MR = %6d ticks, \"\n\t\t\t\t\t\"ratio = %d.%d\\n\", noBits, oldTicks, newTicks, \n\t\t\t\t\tratio / 100, ratio % 100 );\n\t\t\tif( status != passedFermat || status != passedOldPrimeTest )\n\t\t\t\t{\n\t\t\t\tprintf( \"Fermat reports %d, old Miller-Rabin reports %d, \"\n\t\t\t\t\t\t\"new Miller-Rabin reports %d.\\n\", \n\t\t\t\t\t\tpassedFermat, passedOldPrimeTest, status );\n\t\t\t\tgetchar();\n\t\t\t\t}\n#else\n\t\t\tstatus = primeProbable( pkcInfo, candidate, noChecks, \n\t\t\t\t\t\t\t\t\t&primeFound );\n#endif /* CHECK_PRIMETEST */\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tif( !primeFound )\n\t\t\t\tcontinue;\n\n\t\t\t/* If it's not for RSA use then we've found our candidate */\n\t\t\tif( exponent == CRYPT_UNUSED )\n\t\t\t\tbreak;\n\n\t\t\t/* It's for use with RSA, check the RSA condition that\n\t\t\t   gcd( p - 1, exp ) == 1.  Since exp is a small prime we can do\n\t\t\t   this efficiently by checking that ( p - 1 ) mod exp != 0 */\n\t\t\tCK( BN_sub_word( candidate, 1 ) );\n\t\t\tif( !bnStatusError( bnStatus ) )\n\t\t\t\tCK( BN_mod_word( &remainder, candidate, exponent ) );\n\t\t\tCK( BN_add_word( candidate, 1 ) );\n\t\t\tif( bnStatusError( bnStatus ) )\n\t\t\t\t{\n\t\t\t\tstatus = getBnStatus( bnStatus );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( remainder > 0 )\n\t\t\t\t{\n\t\t\t\tprimeFound = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's a prime, but not the right sort of prime */\n\t\t\tprimeFound = FALSE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( cryptStatusError( status ) || primeFound );\n\n\t/* Clean up */\n\tzeroise( sieveArray, SIEVE_SIZE * sizeof( BOOLEAN ) );\n\tclFree( \"generatePrime\", sieveArray );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckBignum( candidate ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generatePrime( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t   INOUT BIGNUM *candidate, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t   IN_OPT const GET_RANDOM_INFO *getRandomInfo )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( candidate, sizeof( BIGNUM ) ) );\n\tassert( getRandomInfo == NULL || \\\n\t\t\tisReadPtr( getRandomInfo, sizeof( GET_RANDOM_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( candidate ) );\n\tREQUIRES( noBits >= 120 && noBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\t\t\t  /* The value of 120 doesn't correspond to any key size but is \n\t\t\t     the minimal value for a prime that we'd generate using the \n\t\t\t\t Lim-Lee algorithm */\n\n\treturn( generatePrimeEx( pkcInfo, candidate, noBits, CRYPT_UNUSED, \n\t\t\t\t\t\t\t getRandomInfo ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generatePrimeRSA( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t  INOUT BIGNUM *candidate, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( bytesToBits( MIN_PKCSIZE ) / 2 ) \\\n\t\t\t\t\t\t\tconst int noBits, \n\t\t\t\t\t  IN_INT const long exponent )\n\t{\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\tassert( isWritePtr( candidate, sizeof( BIGNUM ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( sanityCheckBignum( candidate ) );\n\tREQUIRES( noBits >= bytesToBits( MIN_PKCSIZE ) / 2 && \\\n\t\t\t  noBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( exponent >= 17 && exponent < INT_MAX - 1000 );\n\n\treturn( generatePrimeEx( pkcInfo, candidate, noBits, exponent, NULL ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGenerate a Random Bignum\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a bignum of a specified length with the given high and low 8 \n   bits.  'high' is merged into the high 8 bits of the number (set it to 0x80\n   to ensure that the number is exactly 'bits' bits long, i.e. 2^(bits-1) <=\n   bn < 2^bits), 'low' is merged into the low 8 bits (set it to 1 to ensure\n   that the number is odd).  In almost all cases used in cryptlib, 'high' is\n   set to 0xC0 and low is set to 0x01.\n\n   The parameters also allow for two additional inputs, the first a fixed-\n   length seed for DSA/ECDSA deterministic signatures to deal with potential \n   RNG issues, the second a user-definable randomness function for \n   verifiable generation of DLP parameters.\n\n   We don't need to pagelock the bignum buffer that we're using because it's \n   being accessed continuously while there's data in it so there's little \n   chance that it'll be swapped unless the system is already thrashing */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateBignumEx( OUT BIGNUM *bignum, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t\t  IN_BYTE const int high, IN_BYTE const int low,\n\t\t\t\t\t  IN_BUFFER_OPT( seedLength ) const void *seed,\n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int seedLength,\n\t\t\t\t\t  IN_OPT const void *getRandomInfoPtr )\n\t{\n\tconst GET_RANDOM_INFO *getRandomInfo = getRandomInfoPtr;\n\tconst GETRANDOMDATA_FUNCTION getRandomFunction = \\\n\t\t\t( getRandomInfo != NULL ) ? \\\n\t\t\t\t( GETRANDOMDATA_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( getRandomInfo->getRandomFunction ) : getRandomData;\n\tvoid *getRandomState = ( getRandomInfo != NULL ) ? \\\n\t\t\tgetRandomInfo->getRandomState : NULL;\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE + 8 ];\n\tconst int noBytes = bitsToBytes( noBits );\n\tint bnStatus, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( seed == NULL || isReadPtrDynamic( seed, seedLength ) );\n\tassert( getRandomInfoPtr == NULL || \\\n\t\t\tisReadPtr( getRandomInfoPtr, sizeof( GET_RANDOM_INFO ) ) );\n\n\tREQUIRES( sanityCheckBignum( bignum ) );\n\tREQUIRES( noBits >= 120 && \\\n\t\t\t  noBits <= bytesToBits( CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE ) );\n\t\t\t  /* The value of 120 doesn't correspond to any key size but is \n\t\t\t     the minimal value for a prime that we'd generate using the \n\t\t\t\t Lim-Lee algorithm.  The extra DLP_OVERFLOW_SIZE bits added \n\t\t\t\t to CRYPT_MAX_PKCSIZE are for DLP algorithms where we reduce \n\t\t\t\t the bignum mod p or q and use a few extra bits to avoid the \n\t\t\t\t resulting value being biased, see the DLP code for \n\t\t\t\t details */\n\tREQUIRES( high > 0 && high <= 0xFF );\n\tREQUIRES( low >= 0 && low <= 0xFF );\n\t\t\t  /* The lower bound may be zero if we're generating e.g. a \n\t\t\t     blinding value or some similar non-key-data value */\n\tREQUIRES( ( seed == NULL && seedLength == 0 ) || \\\n\t\t\t  ( seed != NULL && isShortIntegerRangeNZ( seedLength ) ) );\n\tREQUIRES( getRandomFunction != NULL );\n\tREQUIRES( noBytes >= bitsToBytes( 120 ) && \\\n\t\t\t  noBytes <= CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE );\n\t\t\t  /* See comment above */\n\n\t/* Clear the return value */\n\tbnStatus = BN_zero( bignum );\n\tENSURES( bnStatusOK( bnStatus ) );\n\n\t/* Load the random data into the bignum buffer */\n\tstatus = getRandomFunction( getRandomState, buffer, noBytes );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( buffer, noBytes );\n\t\treturn( status );\n\t\t}\n\n\t/* Mix in the seed value if there's one present.  This is used for \n\t   DLP/ECDLP operations where the (phenomenally low) likelihood of the \n\t   RNG producing repeated values would lead to a loss of the private\n\t   key */\n\tif( seed != NULL )\n\t\t{\n\t\tconst BYTE *seedPtr = seed;\n\t\tconst int length = min( noBytes, seedLength );\n\t\tint i;\n\n\t\tLOOP_LARGE( i = 0, i < length, i++ )\n\t\t\tbuffer[ i ] ^= seedPtr[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Merge in the specified low bits, mask off any excess high bits, and\n\t   merge in the specified high bits.  This is a bit more complex than\n\t   just masking in the byte values because the bignum may not be a\n\t   multiple of 8 bytes long */\n\tbuffer[ noBytes - 1 ] |= low;\n\tbuffer[ 0 ] &= 0xFF >> ( -noBits & 7 );\n\tbuffer[ 0 ] |= high >> ( -noBits & 7 );\n\tif( noBits & 7 )\n\t\tbuffer[ 1 ] |= ( high << ( noBits & 7 ) ) & 0xFF;\n\n\t/* Turn the contents of the buffer into a bignum */\n\tif( noBytes > CRYPT_MAX_PKCSIZE )\n\t\t{\n\t\t/* We've created an oversize bignum for use in a DLP algorithm (see \n\t\t   the comment above about DLP_OVERFLOW_SIZE), the upper bound is \n\t\t   somewhat larger than CRYPT_MAX_PKCSIZE */\n\t\tstatus = importBignum( bignum, buffer, noBytes, max( noBytes - 8, 1 ),\n\t\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE + DLP_OVERFLOW_SIZE, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_SPECIAL );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = importBignum( bignum, buffer, noBytes, max( noBytes - 8, 1 ),\n\t\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE, NULL, KEYSIZE_CHECK_NONE );\n\t\t}\n\tzeroise( buffer, noBytes );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckBignum( bignum ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateBignum( OUT BIGNUM *bignum, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 120 ) const int noBits, \n\t\t\t\t\tIN_BYTE const int high, IN_BYTE const int low )\n\t{\n\treturn( generateBignumEx( bignum, noBits, high, low, NULL, 0, NULL ) );\n\t}\n\n#if 0\n\n/* Composite value that passes the primeProbable() test as described in \n   \"Prime and Prejudice: Primality Testing Under Adversarial Conditions\",\n   Martin Albrecht, Jake Massimo, Kenny Paterson and Juraj Somorovsky.\n\n   This is an expected result, see the long comment in primeProbable().\n   \n   The 2315-bit value is generated as follows:\n\n\tn = p1 x p2 x p3\n\n\tp1 = 2^576 x 0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9\n\t\t+ 2^384 x 0xb99c408f131cef3855b4b0aea6b17a4469ed5a7ec8b2be62\n\t\t+ 2^192 x 0x66c3a9eae83a6769e175cb2598256da977b9e191b9b847a7\n\t\t+ 2^0 x 0xe2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56eff3\n\n\tpi = ki ( p1 - 1 ) + 1\n\n\t( k2,k3 ) = ( 641, 677 ) \n\n   So p1 =\n\t( 2^576 * 0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9 ) + \n\t( 2^384 * 0xb99c408f131cef3855b4b0aea6b17a4469ed5a7ec8b2be62 ) + \n\t( 2^192 * 0x66c3a9eae83a6769e175cb2598256da977b9e191b9b847a7 ) + \n\t( 2^0 * 0xe2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56eff3 )\n\n\t0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9b99c408f131cef385\\\n\t5b4b0aea6b17a4469ed5a7ec8b2be6266c3a9eae83a6769e175cb2598256da977b9\\\n\te191b9b847a7e2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56eff3\n\n   p2 = \n\t( 641 * ( p1 - 1 ) ) + 1\n\t( 641 * ( 0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9b99c408\\\n\tf131cef3855b4b0aea6b17a4469ed5a7ec8b2be6266c3a9eae83a6769e175cb2598\\\n\t256da977b9e191b9b847a7e2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56e\\\n\tff3 - 1 ) ) + 1\n\n\t0x5bb502e8c673c9ed84b0f91e2b7da02f674d4939a199d611f9c03da63edb72fc0\\\n\te996e654f6263254d3b4f9774878eb4634fec752f7a3cf01d87f1a921f5b79554c8\\\n\t6dcde2066b6b5ee9019171302da964dcf456d9a5ad4830cbafb1f515aeccf3\n\n   p3 = \n\t( 677 * ( p1 - 1 ) ) + 1\n\t( 677 * ( 0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9b99c408\\\n\tf131cef3855b4b0aea6b17a4469ed5a7ec8b2be6266c3a9eae83a6769e175cb2598\\\n\t256da977b9e191b9b847a7e2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56e\\\n\tff3 - 1 ) ) + 1\n\n\t0x60db8876d8c95e4125e73e3906652164c95c02a78057caedd7da36ba5d8b849ff\\\n\taa6d73dded35856ec20b05148c0b17a39c3705a3822737b013c823a6b5afb01299e\\\n\t91866024557eface2798cfcea40b91aaa96682d3532b7f04a7973591e88afb\n\n   n = p1 x p2 x p3\n\t0x24a027808260908b96d740bef8355ded63f6edb7f70de9a9b99c408f131cef385\\\n\t5b4b0aea6b17a4469ed5a7ec8b2be6266c3a9eae83a6769e175cb2598256da977b9\\\n\te191b9b847a7e2cf4750d9bc2d64ccd3406f5db662c22c3fc65e3c56eff3 * \n\t0x5bb502e8c673c9ed84b0f91e2b7da02f674d4939a199d611f9c03da63edb72fc0\\\n\te996e654f6263254d3b4f9774878eb4634fec752f7a3cf01d87f1a921f5b79554c8\\\n\t6dcde2066b6b5ee9019171302da964dcf456d9a5ad4830cbafb1f515aeccf3 * \n\t0x60db8876d8c95e4125e73e3906652164c95c02a78057caedd7da36ba5d8b849ff\\\n\taa6d73dded35856ec20b05148c0b17a39c3705a3822737b013c823a6b5afb01299e\\\n\t91866024557eface2798cfcea40b91aaa96682d3532b7f04a7973591e88afb\n\n\t4f6cfc0001b66240de95fba380575ed10b55a7e00f7bfb5f4d9a54156e73858737a\\\n\t3c9a290e99a7e9b96358b78c4bb5e944ed98f69ad414dbbc21725c0825facbe07bf\\\n\t2019512a8cf00183d9c185ec2f97ec1cec8b3d0de6d08f9069d809664ee8fde15c3\\\n\tcb10ffafe6891e1fed987b577dc7c13355c8b9828f578d7164af90b388665ee6a74\\\n\t597b2318a871d5887d832876d390a99d683fea506d8f84fbd8391ed2ae990e66078\\\n\td0fe3d67d1f369b67fdc402eee9a75985d34d1b8f5fc9f818f16d6cf4c863d710d1\\\n\tb86fed5b5b50b367b04783634a997e17afc59db0af2d64fcec265b02c3cf2d7896d\\\n\tee97dbaaa55f41e28d9e7daeb8b820565c7d51690bbf84f6abc727ddc2e8f5115fe\\\n\t4d69995008c7b805c4509f04b2c98c2819355f5bcb3 */\n\nstatic const BYTE compositePrime[] = {\n\t0x04, 0xF6, 0xCF, 0xC0, 0x00, 0x1B, 0x66, 0x24,\n\t0x0D, 0xE9, 0x5F, 0xBA, 0x38, 0x05, 0x75, 0xED,\n\t0x10, 0xB5, 0x5A, 0x7E, 0x00, 0xF7, 0xBF, 0xB5,\n\t0xF4, 0xD9, 0xA5, 0x41, 0x56, 0xE7, 0x38, 0x58,\n\t0x73, 0x7A, 0x3C, 0x9A, 0x29, 0x0E, 0x99, 0xA7,\n\t0xE9, 0xB9, 0x63, 0x58, 0xB7, 0x8C, 0x4B, 0xB5,\n\t0xE9, 0x44, 0xED, 0x98, 0xF6, 0x9A, 0xD4, 0x14,\n\t0xDB, 0xBC, 0x21, 0x72, 0x5C, 0x08, 0x25, 0xFA,\n\t0xCB, 0xE0, 0x7B, 0xF2, 0x01, 0x95, 0x12, 0xA8,\n\t0xCF, 0x00, 0x18, 0x3D, 0x9C, 0x18, 0x5E, 0xC2,\n\t0xF9, 0x7E, 0xC1, 0xCE, 0xC8, 0xB3, 0xD0, 0xDE,\n\t0x6D, 0x08, 0xF9, 0x06, 0x9D, 0x80, 0x96, 0x64,\n\t0xEE, 0x8F, 0xDE, 0x15, 0xC3, 0xCB, 0x10, 0xFF,\n\t0xAF, 0xE6, 0x89, 0x1E, 0x1F, 0xED, 0x98, 0x7B,\n\t0x57, 0x7D, 0xC7, 0xC1, 0x33, 0x55, 0xC8, 0xB9,\n\t0x82, 0x8F, 0x57, 0x8D, 0x71, 0x64, 0xAF, 0x90,\n\t0xB3, 0x88, 0x66, 0x5E, 0xE6, 0xA7, 0x45, 0x97,\n\t0xB2, 0x31, 0x8A, 0x87, 0x1D, 0x58, 0x87, 0xD8,\n\t0x32, 0x87, 0x6D, 0x39, 0x0A, 0x99, 0xD6, 0x83,\n\t0xFE, 0xA5, 0x06, 0xD8, 0xF8, 0x4F, 0xBD, 0x83,\n\t0x91, 0xED, 0x2A, 0xE9, 0x90, 0xE6, 0x60, 0x78,\n\t0xD0, 0xFE, 0x3D, 0x67, 0xD1, 0xF3, 0x69, 0xB6,\n\t0x7F, 0xDC, 0x40, 0x2E, 0xEE, 0x9A, 0x75, 0x98,\n\t0x5D, 0x34, 0xD1, 0xB8, 0xF5, 0xFC, 0x9F, 0x81,\n\t0x8F, 0x16, 0xD6, 0xCF, 0x4C, 0x86, 0x3D, 0x71,\n\t0x0D, 0x1B, 0x86, 0xFE, 0xD5, 0xB5, 0xB5, 0x0B,\n\t0x36, 0x7B, 0x04, 0x78, 0x36, 0x34, 0xA9, 0x97,\n\t0xE1, 0x7A, 0xFC, 0x59, 0xDB, 0x0A, 0xF2, 0xD6,\n\t0x4F, 0xCE, 0xC2, 0x65, 0xB0, 0x2C, 0x3C, 0xF2,\n\t0xD7, 0x89, 0x6D, 0xEE, 0x97, 0xDB, 0xAA, 0xA5,\n\t0x5F, 0x41, 0xE2, 0x8D, 0x9E, 0x7D, 0xAE, 0xB8,\n\t0xB8, 0x20, 0x56, 0x5C, 0x7D, 0x51, 0x69, 0x0B,\n\t0xBF, 0x84, 0xF6, 0xAB, 0xC7, 0x27, 0xDD, 0xC2,\n\t0xE8, 0xF5, 0x11, 0x5F, 0xE4, 0xD6, 0x99, 0x95,\n\t0x00, 0x8C, 0x7B, 0x80, 0x5C, 0x45, 0x09, 0xF0,\n\t0x4B, 0x2C, 0x98, 0xC2, 0x81, 0x93, 0x55, 0xF5,\n\t0xBC, 0xB3 \n\t};\n\nvoid checkCompositePrime( void )\n\t{\n\tCONTEXT_INFO contextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tBOOLEAN primeFound;\n\tconst int noChecks = getNoPrimeChecks( bytesToBits( 290 ) );\n\tint status;\n\n\tmemset( &contextInfo, 0, sizeof( CONTEXT_INFO ) );\n\tmemset( pkcInfo, 0, sizeof( PKC_INFO ) );\n\n\tstatus = staticInitContext( &contextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tgetRSACapability(), pkcInfo, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tstatus = importBignum( &pkcInfo->rsaParam_n, compositePrime, \n\t\t\t\t\t\t   290, 289, 290, NULL, KEYSIZE_CHECK_PKC );\n\tstatus = primeSieve( &pkcInfo->rsaParam_n );\n\tstatus = primeProbable( pkcInfo, &pkcInfo->rsaParam_n, noChecks, \n\t\t\t\t\t\t\t&primeFound );\n\t}\n#endif /* 0 */\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/context/kg_rsa.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib RSA Key Generation/Checking Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"keygen.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"context/keygen.h\"\n#endif /* Compiler-specific includes */\n\n/* We use F4 as the default public exponent e unless the user chooses to\n   override this with some other value:\n\n\tFn = 2^(2^n) + 1, n = 0...4.\n\n\tF0 = 3, F1 = 5, F2 = 17, F3 = 257, F4 = 65537.\n   \n   The older (X.509v1) recommended value of 3 is insecure for general use \n   and more recent work indicates that values like 17 (used by PGP) are also \n   insecure against the Hastad attack.  We could work around this by using \n   41 or 257 as the exponent, however current best practice favours F4 \n   unless you're doing banking standards, in which case you set e=2 (EMV) \n   and use raw, unpadded RSA (HBCI) to make it easier for students to break \n   your banking security as a homework exercise.\n\n   Since some systems may be using 16-bit bignum component values we use an\n   exponent of 257 for these cases to ensure that it fits in a single\n   component value */\n\n#ifndef RSA_PUBLIC_EXPONENT\n  #ifdef SIXTEEN_BIT\n\t#define RSA_PUBLIC_EXPONENT\t\t257\n  #else\n\t#define RSA_PUBLIC_EXPONENT\t\t65537L\n  #endif /* 16-bit bignum components */\n#endif /* RSA_PUBLIC_EXPONENT */\n\n/* The minimum allowed public exponent.  In theory this could go as low as 3\n   (and in fact a GoDaddy root cert for \"Go Daddy Class 2 Certification \n   Authority\" from 2004 still uses this value), however there are all manner \n   of obscure corner cases that have to be checked if this exponent is used \n   and in general the necessary checking presents a more or less intractable \n   problem.  \n   \n   To avoid this minefield we require a minimum exponent of at 17, the next \n   generally-used value above 3.  However even this is only used by PGP 2.x, \n   the next minimum is 33 (a weird value used by OpenSSH until mid-2010, see \n   the comment further down), 41 (another weird value used by GPG until \n   mid-2006), and then 257 or (in practice) F4 / 65537 by everything else */\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n  #define MIN_PUBLIC_EXPONENT\t\t17\n#elif defined( USE_SSH )\n  #define MIN_PUBLIC_EXPONENT\t\t33\n#else\n  #define MIN_PUBLIC_EXPONENT\t\t257\n#endif /* Smallest exponents used by various crypto protocols */\n#if ( MIN_PUBLIC_EXPONENT <= 0xFF && RSAPARAM_MIN_E > 1 ) || \\\n\t( MIN_PUBLIC_EXPONENT <= 0xFFFF && RSAPARAM_MIN_E > 2 )\n  #error RSAPARAM_MIN_E is too large for MIN_PUBLIC_EXPONENT\n#endif /* MIN_PUBLIC_EXPONENT size > RSAPARAM_MIN_E value */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enable various side-channel protection mechanisms */\n\n#if defined( __WINCE__ ) && defined( ARMV4 ) && defined( NDEBUG )\n  #pragma optimize( \"g\", off )\n#endif /* eVC++ 4.0 ARMv4 optimiser bug */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int enableSidechannelProtection( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isPrivateKey )\n\t{\n\tBIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;\n\tBIGNUM *k = &pkcInfo->rsaParam_blind_k;\n\tBIGNUM *kInv = &pkcInfo->rsaParam_blind_kInv;\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint noBytes = bitsToBytes( pkcInfo->keySizeBits );\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\t/* Generate a random bignum for blinding.  Since this merely has to be \n\t   unpredictable to an outsider but not cryptographically strong, and to \n\t   avoid having more crypto RNG output than necessary sitting around in \n\t   memory, we get it from the nonce PRNG rather than the crypto one.  In\n\t   addition we don't have to perform a range check on import to see if \n\t   it's larger than 'n' since we're about to reduce it mod n in the next \n\t   step, and doing so would give false positives */\n\tsetMessageData( &msgData, buffer, noBytes );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tbuffer[ 0 ] &= 0xFF >> ( -pkcInfo->keySizeBits & 7 );\n\t\tstatus = importBignum( k, buffer, noBytes, MIN_PKCSIZE - 8, \n\t\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE, NULL, \n\t\t\t\t\t\t\t   KEYSIZE_CHECK_NONE );\n\t\t}\n\tzeroise( buffer, noBytes );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the blinding and unblinding values */\n\tCK( BN_mod( k, k, n, &pkcInfo->bnCTX ) );\t/* k = rand() mod n */\n\tCKPTR( BN_mod_inverse( kInv, k, n, &pkcInfo->bnCTX ) );\n\t\t\t\t\t\t\t\t\t\t\t\t/* kInv = k^-1 mod n */\n\tCK( BN_mod_exp_mont( k, k, e, n, &pkcInfo->bnCTX,\n\t\t\t\t\t\t &pkcInfo->rsaParam_mont_n ) );\n\t\t\t\t\t\t\t\t\t\t\t\t/* k = k^e mod n */\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Use constant-time modexp() to protect the private key from timing \n\t   channels if required */\n\tif( isPrivateKey )\n\t\t{\n\t\tBN_set_flags( &pkcInfo->rsaParam_exponent1, BN_FLG_CONSTTIME );\n\t\tBN_set_flags( &pkcInfo->rsaParam_exponent2, BN_FLG_CONSTTIME );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( __WINCE__ ) && defined( ARMV4 ) && defined( NDEBUG )\n  #pragma optimize( \"g\", on )\n#endif /* eVC++ 4.0 ARMv4 optimiser bug */\n\n/* Adjust p and q if necessary to ensure that the CRT decrypt works */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int fixCRTvalues( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t const BOOLEAN fixPKCSvalues )\n\t{\n\tBIGNUM *p = &pkcInfo->rsaParam_p, *q = &pkcInfo->rsaParam_q;\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( fixPKCSvalues == TRUE || fixPKCSvalues == FALSE );\n\n\t/* Make sure that p > q, which is required for the CRT decrypt */\n\tif( BN_cmp( p, q ) > 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* Swap the values p and q and, if necessary, the PKCS parameters e1\n\t   and e2 that depend on them (e1 = d mod (p - 1) and\n\t   e2 = d mod (q - 1)), and recompute u = qInv mod p */\n\tBN_swap( p, q );\n\tif( fixPKCSvalues )\n\t\t{\n\t\tBN_swap( &pkcInfo->rsaParam_exponent1, \n\t\t\t\t &pkcInfo->rsaParam_exponent2 );\n\t\tCKPTR( BN_mod_inverse( &pkcInfo->rsaParam_u, q, p,\n\t\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\tENSURES( BN_cmp( p, q ) > 0 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Evaluate the Montgomery forms for public and private components */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getRSAMontgomery( INOUT PKC_INFO *pkcInfo, \n\t\t\t\t\t\t\t const BOOLEAN isPrivateKey )\n\t{\n\tint bnStatus = BN_STATUS;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\t/* Evaluate the public value */\n\tCK( BN_MONT_CTX_set( &pkcInfo->rsaParam_mont_n, &pkcInfo->rsaParam_n,\n\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\tif( !isPrivateKey )\n\t\treturn( CRYPT_OK );\n\n\t/* Evaluate the private values */\n\tCK( BN_MONT_CTX_set( &pkcInfo->rsaParam_mont_p, &pkcInfo->rsaParam_p,\n\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tCK( BN_MONT_CTX_set( &pkcInfo->rsaParam_mont_q, &pkcInfo->rsaParam_q,\n\t\t\t\t\t\t &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck an RSA Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform validity checks on the public key.  We have to make the PKC_INFO\n   data non-const because the bignum code wants to modify some of the values\n   as it's working with them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRSAPublicKeyComponents( INOUT PKC_INFO *pkcInfo )\n\t{\n\tBIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;\n\tconst BN_ULONG eWord = BN_get_word( e );\n\tconst int eLen = BN_num_bits( e );\n\tint length;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( eLen > 0 && eLen <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Verify that nLen >= RSAPARAM_MIN_N (= MIN_PKCSIZE), \n\t   nLen <= RSAPARAM_MAX_N (= CRYPT_MAX_PKCSIZE) */\n\tlength = BN_num_bytes( n );\n\tif( isShortPKCKey( length ) )\n\t\t{\n\t\t/* Special-case handling for insecure-sized public keys */\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t}\n\tif( length < RSAPARAM_MIN_N || length > RSAPARAM_MAX_N )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that n is not (obviously) composite */\n\tif( !primeSieve( n ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that e >= MIN_PUBLIC_EXPONENT, eLen <= RSAPARAM_MAX_E \n\t   (= 32 bits).  The latter check is to preclude DoS attacks due to \n\t   ridiculously large e values.  BN_get_word() works even on 16-bit \n\t   systems because it returns BN_MASK2 (== UINT_MAX) if the value \n\t   can't be represented in a machine word */\n\tif( eWord < MIN_PUBLIC_EXPONENT || bitsToBytes( eLen ) > RSAPARAM_MAX_E )\n\t\t{\n\t\tDEBUG_DIAG(( \"Encountered insecure/peculiar RSA key exponent %d\", \n\t\t\t\t\t eWord ));\n\t\tassert_nofuzz( DEBUG_WARN );\t/* Warn in debug build */\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Perform a second check to make sure that e will fit into a signed \n\t   integer.  This isn't strictly required since a BN_ULONG is unsigned \n\t   but it's unlikely that anyone would consciously use a full 32-bit e\n\t   value (well, except for the German RegTP, who do all sorts of other\n\t   bizarre things as well) so we weed out any attempts to use one here */\n\tif( eLen >= bytesToBits( sizeof( int ) ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that e is a small prime.  The easiest way to do this would be\n\t   to compare it to a set of standard values but there'll always be some\n\t   wierdo implementation that uses a nonstandard value and that would\n\t   therefore fail the test so we perform a quick check that just tries\n\t   dividing by all primes below 1000.  In addition since in almost all\n\t   cases e will be one of a standard set of values we don't bother with \n\t   the trial division unless it's an unusual value.  This test isn't\n\t   perfect but it'll catch obvious non-primes */\n\tif( eWord != 17 && eWord != 257 && eWord != 65537L && !primeSieve( e ) )\n\t\t{\n\t\t/* OpenSSH versions up to 5.4 (released in 2010) hardcoded e = 35, \n\t\t   which is both a suboptimal exponent (it's less efficient that a \n\t\t   safer value like 257 or F4) and non-prime.  The reason for this \n\t\t   was that the original SSH used an e relatively prime to \n\t\t   (p-1)(q-1), choosing odd (in both senses of the word) \n\t\t   numbers > 31.  33 or 35 probably ended up being chosen frequently \n\t\t   so it was hardcoded into OpenSSH for cargo-cult reasons, finally \n\t\t   being fixed after more than a decade to use F4.  In order to use \n\t\t   pre-5.4 OpenSSH keys that use this odd value we make a special-\n\t\t   case exception for SSH use */\n#ifdef USE_SSH\n\t\tif( eWord == 33 || eWord == 35 )\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_SSH */\n\n\t\tDEBUG_DIAG(( \"Encountered insecure/peculiar RSA key exponent %d\", \n\t\t\t\t\t eWord ));\n\t\tassert_nofuzz( DEBUG_WARN );\t/* Warn in debug build */\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform validity checks on the private key.  We have to make the PKC_INFO\n   data non-const because the bignum code wants to modify some of the values\n   as it's working with them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRSAPrivateKeyComponents( INOUT PKC_INFO *pkcInfo )\n\t{\n\tBIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;\n\tBIGNUM *d = &pkcInfo->rsaParam_d, *p = &pkcInfo->rsaParam_p;\n\tBIGNUM *q = &pkcInfo->rsaParam_q;\n\tBIGNUM *p1 = &pkcInfo->tmp1, *q1 = &pkcInfo->tmp2, *tmp = &pkcInfo->tmp3;\n\tconst BN_ULONG eWord = BN_get_word( e );\n\tBN_ULONG word DUMMY_INIT;\n\tBOOLEAN isPrime;\n\tint bnStatus = BN_STATUS, status;\n\n\tassert( isWritePtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\tREQUIRES( sanityCheckPKCInfo( pkcInfo ) );\n\tREQUIRES( eWord > 0 && eWord < INT_MAX );\n\t\t\t  /* Already checked in checkRSAPublicKeyComponents() */\n\n\t/* Verify that p, q aren't (obviously) composite.  Note that we can't \n\t   use primeProbable() because this updates the Montgomery CTX data, \n\t   it's OK to use it early in the keygen process before everything is \n\t   set up but not after the pkcInfo is fully initialised so we use\n\t   primeProbableFermat() instead */\n\tif( !primeSieve( p ) || !primeSieve( q ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tstatus = primeProbableFermat( pkcInfo, p, &pkcInfo->rsaParam_mont_p, \n\t\t\t\t\t\t\t\t  &isPrime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isPrime )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tstatus = primeProbableFermat( pkcInfo, q, &pkcInfo->rsaParam_mont_q,\n\t\t\t\t\t\t\t\t  &isPrime );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isPrime )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that |p-q| > 128 bits.  We know that p >= q because this is a\n\t   precondition for the CRT decrypt to work.  FIPS 186-3 requires only \n\t   100 bits, this check is slightly more conservative but in any case \n\t   both values are somewhat arbitrary and are merely meant to delimit \n\t   \"not too close\".  \n\t   \n\t   There's a second more obscure check that we could in theory perform \n\t   to make sure that p and q don't have the least significant nLen / 4 \n\t   bits the same (which would still lead to |p-q| > 128), this would \n\t   make the Boneh/Durfee attack marginally less improbable (result by \n\t   Zhao and Qi).  Since the chance of them having 256 LSB bits the same \n\t   is vanishingly small and the Boneh/Dufree attack requires special \n\t   properties for d (see the comment in generateRSAkey()) we don't \n\t   bother with this check */\n\tENSURES( BN_cmp( p, q ) >= 0 );\n\tCKPTR( BN_copy( tmp, p ) );\n\tCK( BN_sub( tmp, tmp, q ) );\n\tif( bnStatusError( bnStatus ) || \\\n\t\tBN_num_bits( tmp ) < 128 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Calculate p - 1, q - 1 */\n\tCKPTR( BN_copy( p1, p ) );\n\tCK( BN_sub_word( p1, 1 ) );\n\tCKPTR( BN_copy( q1, q ) );\n\tCK( BN_sub_word( q1, 1 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that n = p * q */\n\tCK( BN_mul( tmp, p, q, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) || BN_cmp( n, tmp ) != 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that:\n\n\t\tp, q < d\n\t\t( d * e ) mod p-1 == 1 \n\t\t( d * e ) mod q-1 == 1\n\t\n\t   Some implementations don't store d since it's not needed when the CRT\n\t   shortcut is used so we can only perform this check if d is present */\n\tif( !BN_is_zero( d ) )\n\t\t{\n\t\tif( BN_cmp( p, d ) >= 0 || BN_cmp( q, d ) >= 0 )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tCK( BN_mod_mul( tmp, d, e, p1, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) || !BN_is_one( tmp ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tCK( BN_mod_mul( tmp, d, e, q1, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) || !BN_is_one( tmp ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n#ifdef USE_FIPS140\n\t/* Verify that sizeof( d ) > sizeof( p ) / 2, a weird requirement set by \n\t   FIPS 186-3.  This is one of those things where the probability of the\n\t   check going wrong in some way outweighs the probability of the \n\t   situation actually occurring by about two dozen orders of magnitude \n\t   so we only do this when we have to.  The fact that this parameter is\n\t   never even used makes the check even less meaningful.\n\t   \n\t   (This check possibly has something to do with defending against \n\t   Wiener's continued-fraction attack, which requires d < n^(1/4) in\n\t   order to succeed, later extended into the range d < n^(0.29) by\n\t   Boneh and Durfee/Bloemer and May and d < 1/2 n^(1/2) by Maitra and \n\t   Sarkar) */\n\tif( !BN_is_zero( d ) && BN_num_bits( d ) <= pkcInfo->keySizeBits )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n#endif /* USE_FIPS140 */\n\n\t/* Verify that ( q * u ) mod p == 1 */\n\tCK( BN_mod_mul( tmp, q, &pkcInfo->rsaParam_u, p, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) || !BN_is_one( tmp ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that e1 < p, e2 < q */\n\tif( BN_cmp( &pkcInfo->rsaParam_exponent1, p ) >= 0 || \\\n\t\tBN_cmp( &pkcInfo->rsaParam_exponent2, q ) >= 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Verify that u < p, where u was calculated as q^-1 mod p */\n\tif( BN_cmp( &pkcInfo->rsaParam_u, p ) >= 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* A very small number of systems/compilers can't handle 32 * 32 -> 64\n\t   ops which means that we have to use 16-bit bignum components.  For \n\t   the common case where e = F4 the value won't fit into a 16-bit bignum\n\t   component so we have to use the full BN_mod() form of the checks that \n\t   are carried out further on */\n#ifdef SIXTEEN_BIT\n\tCK( BN_mod( tmp, p1, e, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) || BN_is_zero( tmp ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tCK( BN_mod( tmp, q1, e, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) || BN_is_zero( tmp ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\treturn( CRYPT_OK );\n#endif /* Systems without 32 * 32 -> 64 ops */\n\n\t/* Verify that gcd( ( p - 1 )( q - 1), e ) == 1\n\t\n\t   Since e is a small prime we can do this much more efficiently by \n\t   checking that:\n\n\t\t( p - 1 ) mod e != 0\n\t\t( q - 1 ) mod e != 0 */\n\tCK( BN_mod_word( &word, p1, eWord ) );\n\tif( bnStatusError( bnStatus ) || word == 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tCK( BN_mod_word( &word, q1, eWord ) );\n\tif( bnStatusError( bnStatus ) || word == 0 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInitialise/Check an RSA Key\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate an RSA key pair into an encryption context.  For FIPS 140 \n   purposes the keygen method used here complies with FIPS 186-3 Appendix \n   B.3, \"IFC Key Pair Generation\", specifically method B.3.3, \"Generation of \n   Random Primes that are Probably Prime\".  Note that FIPS 186-3 provides a\n   range of key-generation methods and allows implementations to select one\n   that's appropriate, this implementation provides the one in B.3.3, with\n   the exception that it allows keys in the range MIN_PKC_SIZE ... \n   CRYPT_MAX_PKCSIZE to be generated.  FIPS 186-3 is rather confusing in\n   that it discusses conditions and requirements for generating pairs from\n   512 ... 3072 bits and then gives different lengths and restrictions on\n   lengths depending on which portion of text you consult.  Because of this\n   confusion, and the fact that telling users that they can't generate the\n   key that they want because of some obscure document that they've never\n   even heard of will cause friction, we leave it as a policy decision to\n   define the appropriate key size to use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint generateRSAkey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_PKCSIZE * 8 ) const int keyBits )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tBIGNUM *d = &pkcInfo->rsaParam_d, *p = &pkcInfo->rsaParam_p;\n\tBIGNUM *q = &pkcInfo->rsaParam_q;\n\tBIGNUM *tmp = &pkcInfo->tmp1;\n\tint pBits, qBits, bnStatus, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( keyBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keyBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Determine how many bits to give to each of p and q */\n\tpBits = ( keyBits + 1 ) / 2;\n\tqBits = keyBits - pBits;\n\tpkcInfo->keySizeBits = pBits + qBits;\n\n\t/* Generate the primes p and q and set them up so that the CRT decrypt\n\t   will work.  FIPS 186-3 requires that they be in the range \n\t   sqr(2) * 2^(keyBits-1) ... 2^keyBits (so that pq will be exactly \n\t   keyBits long), but this is guaranteed by the way that generatePrime()\n\t   selects its prime values so we don't have to check explicitly for it\n\t   here */\n\tbnStatus = BN_set_word( &pkcInfo->rsaParam_e, RSA_PUBLIC_EXPONENT );\n\tENSURES( bnStatusOK( bnStatus ) );\n\tstatus = generatePrimeRSA( pkcInfo, p, pBits, RSA_PUBLIC_EXPONENT );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = generatePrimeRSA( pkcInfo, q, qBits, RSA_PUBLIC_EXPONENT );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = fixCRTvalues( pkcInfo, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Compute d = eInv mod (p - 1)(q - 1) */\n\tCK( BN_sub_word( p, 1 ) );\n\tCK( BN_sub_word( q, 1 ) );\n\tCK( BN_mul( tmp, p, q, &pkcInfo->bnCTX ) );\n\tCKPTR( BN_mod_inverse( d, &pkcInfo->rsaParam_e, tmp, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n#ifdef USE_FIPS140\n\t/* Check that sizeof( d ) > sizeof( p ) / 2, a weird requirement set by \n\t   FIPS 186-3.  This is one of those things where the probability of the\n\t   check going wrong in some way outweighs the probability of the \n\t   situation actually occurring by about two dozen orders of magnitude \n\t   so we only do this when we have to.  The fact that this parameter is\n\t   never even used makes the check even less meaningful.\n\t   \n\t   (This check possibly has something to do with defending against \n\t   Wiener's continued-fraction attack, which requires d < n^(1/4) in\n\t   order to succeed, later extended into the range d < n^(0.29) by\n\t   Boneh and Durfee/Bloemer and May and d < 1/2 n^(1/2) by Maitra and \n\t   Sarkar) */\n\tif( BN_num_bits( d ) <= pkcInfo->keySizeBits / 2 )\n\t\treturn( CRYPT_ERROR_FAILED );\n#endif /* USE_FIPS140 */\n\n\t/* Compute e1 = d mod (p - 1), e2 = d mod (q - 1) */\n\tCK( BN_mod( &pkcInfo->rsaParam_exponent1, d,\n\t\t\t\tp, &pkcInfo->bnCTX ) );\n\tCK( BN_mod( &pkcInfo->rsaParam_exponent2, d, q, &pkcInfo->bnCTX ) );\n\tCK( BN_add_word( p, 1 ) );\n\tCK( BN_add_word( q, 1 ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Compute n = pq, u = qInv mod p */\n\tCK( BN_mul( &pkcInfo->rsaParam_n, p, q, &pkcInfo->bnCTX ) );\n\tCKPTR( BN_mod_inverse( &pkcInfo->rsaParam_u, q, p, &pkcInfo->bnCTX ) );\n\tif( bnStatusError( bnStatus ) )\n\t\treturn( getBnStatus( bnStatus ) );\n\n\t/* Since the keygen is randomised it may occur that the final size of \n\t   the public value that determines its nominal size is slightly smaller \n\t   than the requested nominal size.  To handle this we recalculate the \n\t   effective key size after we've finished generating the public value\n\t   that determines its nominal size */\n\tpkcInfo->keySizeBits = BN_num_bits( &pkcInfo->rsaParam_n );\n\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Evaluate the Montgomery forms */\n\tstatus = getRSAMontgomery( pkcInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're\n\t   setting the checksum at this point there's no need to check the \n\t   return value */\n\t( void ) checksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  TRUE );\n\n\t/* Make sure that the generated values are valid */\n\tstatus = checkRSAPublicKeyComponents( pkcInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkRSAPrivateKeyComponents( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that what we generated is still valid */\n\tif( cryptStatusError( \\\n\t\t\tchecksumContextData( pkcInfo, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t TRUE ) ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Generated DLP key memory corruption detected\" ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and check an RSA key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initCheckRSAkey( INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\tBIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;\n\tBIGNUM *d = &pkcInfo->rsaParam_d, *p = &pkcInfo->rsaParam_p;\n\tBIGNUM *q = &pkcInfo->rsaParam_q;\n\tconst BOOLEAN isPrivateKey = TEST_FLAG( contextInfoPtr->flags,\n\t\t\t\t\t\t\t\t\t\t\tCONTEXT_FLAG_ISPUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t FALSE : TRUE;\n\tint bnStatus = BN_STATUS, status = CRYPT_OK;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\n\t/* Make sure that the necessary key parameters have been initialised */\n\tif( BN_is_zero( n ) || BN_is_zero( e ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( isPrivateKey )\n\t\t{\n\t\tif( BN_is_zero( p ) || BN_is_zero( q ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( BN_is_zero( d ) && \\\n\t\t\t( BN_is_zero( &pkcInfo->rsaParam_exponent1 ) || \\\n\t\t\t  BN_is_zero( &pkcInfo->rsaParam_exponent2 ) ) )\n\t\t\t{\n\t\t\t/* Either d or e1+e2 must be present, d isn't needed if we have \n\t\t\t   e1+e2 and e1+e2 can be reconstructed from d */\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that the public key parameters are valid */\n\tstatus = checkRSAPublicKeyComponents( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a public key, we're done */\n\tif( !isPrivateKey )\n\t\t{\n\t\t/* Precompute the Montgomery forms of required values */\n\t\tstatus = getRSAMontgomery( pkcInfo, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpkcInfo->keySizeBits = BN_num_bits( &pkcInfo->rsaParam_n );\n\t\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t\t/* Enable side-channel protection if required */\n\t\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t\t{\n\t\t\tstatus = enableSidechannelProtection( pkcInfo, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Checksum the bignums to try and detect fault attacks.  Since \n\t\t   we're setting the checksum at this point there's no need to check \n\t\t   the return value.  Note that this isn't the TOCTOU issue that it \n\t\t   appears to be because the bignum values are read by the calling \n\t\t   code from their stored form a second time and compared to the \n\t\t   values that we're checksumming here */\n\t\t( void ) checksumContextData( pkcInfo, CRYPT_ALGO_RSA, FALSE );\n\n\t\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're not using PKCS keys that have exponent1 = d mod ( p - 1 )\n\t   and exponent2 = d mod ( q - 1 ) precalculated, evaluate them now\n\t   (this only ever occurs for PGP keys).  If there's no u precalculated, \n\t   evaluate it now (this should never occur with any normal source of\n\t   keys) */\n\tif( BN_is_zero( &pkcInfo->rsaParam_exponent1 ) )\n\t\t{\n\t\tBIGNUM *exponent1 = &pkcInfo->rsaParam_exponent1;\n\t\tBIGNUM *exponent2 = &pkcInfo->rsaParam_exponent2;\n\n\t\tREQUIRES( !BN_is_zero( d ) );\n\n\t\t/* exponent1 = d mod ( p - 1 ) ) */\n\t\tCKPTR( BN_copy( exponent1, p ) );\n\t\tCK( BN_sub_word( exponent1, 1 ) );\n\t\tCK( BN_mod( exponent1, d, exponent1, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\n\t\t/* exponent2 = d mod ( q - 1 ) ) */\n\t\tCKPTR( BN_copy( exponent2, q ) );\n\t\tCK( BN_sub_word( exponent2, 1 ) );\n\t\tCK( BN_mod( exponent2, d, exponent2, &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\tif( BN_is_zero( &pkcInfo->rsaParam_u ) )\n\t\t{\n\t\tCKPTR( BN_mod_inverse( &pkcInfo->rsaParam_u, q, p,\n\t\t\t\t\t\t\t   &pkcInfo->bnCTX ) );\n\t\tif( bnStatusError( bnStatus ) )\n\t\t\treturn( getBnStatus( bnStatus ) );\n\t\t}\n\n\t/* Make sure that p and q are set up correctly for the CRT decryption */\n\tstatus = fixCRTvalues( pkcInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Precompute the Montgomery forms of required values */\n\tstatus = getRSAMontgomery( pkcInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpkcInfo->keySizeBits = BN_num_bits( &pkcInfo->rsaParam_n );\n\tENSURES( pkcInfo->keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t pkcInfo->keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* We've got the remaining components set up, perform further validity \n\t   checks on the private key */\n\tstatus = checkRSAPrivateKeyComponents( pkcInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Enable side-channel protection if required */\n\tif( TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t   CONTEXT_FLAG_SIDECHANNELPROTECTION ) )\n\t\t{\n\t\tstatus = enableSidechannelProtection( pkcInfo, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Checksum the bignums to try and detect fault attacks.  Since we're\n\t   setting the checksum at this point there's no need to check the \n\t   return value.  Note that this isn't the TOCTOU issue that it appears \n\t   to be because the bignum values are read by the calling code from \n\t   their stored form a second time and compared to the values that we're \n\t   checksumming here */\n\t( void ) checksumContextData( pkcInfo, CRYPT_ALGO_RSA, TRUE );\n\n\tENSURES( sanityCheckPKCInfo( pkcInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/crypt/aes.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n This file contains the definitions required to use AES in C. See aesopt.h\n for optimisation details.\n*/\n\n#ifndef _AES_H\n#define _AES_H\n\n#include <stdlib.h>\n\n/*  This include is used to find 8 & 32 bit unsigned integer types  */\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"brg_types.h\"\n#else\n  #include \"crypt/brg_types.h\"\n#endif /* Compiler-specific includes */\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#define AES_128     /* if a fast 128 bit key scheduler is needed    */\n#ifndef CONFIG_CONSERVE_MEMORY\t/* pcg */\n#define AES_192     /* if a fast 192 bit key scheduler is needed    */\n#endif /* CONFIG_CONSERVE_MEMORY */\n#define AES_256     /* if a fast 256 bit key scheduler is needed    */\n#define AES_VAR     /* if variable key size scheduler is needed     */\n#define AES_MODES   /* if support is needed for modes               */\n\n/* The following must also be set in assembler files if being used  */\n\n#define AES_ENCRYPT /* if support for encryption is needed          */\n#define AES_DECRYPT /* if support for decryption is needed          */\n\n#define AES_BLOCK_SIZE  16  /* the AES block size in bytes          */\n#define N_COLS           4  /* the number of columns in the state   */\n\n/* The key schedule length is 11, 13 or 15 16-byte blocks for 128,  */\n/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes  */\n/* or 44, 52 or 60 32-bit words.                                    */\n\n#if defined( AES_VAR ) || defined( AES_256 )\n#define KS_LENGTH       60\n#elif defined( AES_192 )\n#define KS_LENGTH       52\n#else\n#define KS_LENGTH       44\n#endif\n\n#define AES_RETURN INT_RETURN\n\n/* the character array 'inf' in the following structures is used    */\n/* to hold AES context information. This AES code uses cx->inf.b[0] */\n/* to hold the number of rounds multiplied by 16. The other three   */\n/* elements can be used by code that implements additional modes    */\n\ntypedef union\n{   uint32_t l;\n    uint8_t b[4];\n} aes_inf;\n\n#ifdef _MSC_VER\n#  pragma warning( disable : 4324 )\n#endif\n\n#if defined(_MSC_VER) && defined(_WIN64)\n#define ALIGNED_(x) __declspec(align(x))\n#elif defined(__GNUC__) && defined(__x86_64__)\n#define ALIGNED_(x) __attribute__ ((aligned(x)))\n#else\n#define ALIGNED_(x)\n#endif\n\ntypedef struct ALIGNED_(16)\n{   uint32_t ks[KS_LENGTH];\n    aes_inf inf;\n} aes_encrypt_ctx;\n\ntypedef struct ALIGNED_(16)\n{   uint32_t ks[KS_LENGTH];\n    aes_inf inf;\n} aes_decrypt_ctx;\n\n#ifdef _MSC_VER\n#  pragma warning( default : 4324 )\n#endif\n\n/* This routine must be called before first use if non-static       */\n/* tables are being used                                            */\n\nAES_RETURN aes_init(void);\n\n/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */\n/* those in the range 128 <= key_len <= 256 are given in bits       */\n\n#if defined( AES_ENCRYPT )\n\n#if defined( AES_128 ) || defined( AES_VAR)\nAES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_192 ) || defined( AES_VAR)\nAES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_256 ) || defined( AES_VAR)\nAES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_VAR )\nAES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]);\n#endif\n\nAES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);\n\n#endif\n\n#if defined( AES_DECRYPT )\n\n#if defined( AES_128 ) || defined( AES_VAR)\nAES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_192 ) || defined( AES_VAR)\nAES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_256 ) || defined( AES_VAR)\nAES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);\n#endif\n\n#if defined( AES_VAR )\nAES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]);\n#endif\n\nAES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);\n\n#endif\n\n#if defined( AES_MODES )\n\n/* Multiple calls to the following subroutines for multiple block   */\n/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */\n/* long messages incrementally provided that the context AND the iv */\n/* are preserved between all such calls.  For the ECB and CBC modes */\n/* each individual call within a series of incremental calls must   */\n/* process only full blocks (i.e. len must be a multiple of 16) but */\n/* the CFB, OFB and CTR mode calls can handle multiple incremental  */\n/* calls of any length.  Each mode is reset when a new AES key is   */\n/* set but ECB needs no reset and CBC can be reset without setting  */\n/* a new key by setting a new IV value.  To reset CFB, OFB and CTR  */\n/* without setting the key, aes_mode_reset() must be called and the */\n/* IV must be set.  NOTE: All these calls update the IV on exit so  */\n/* this has to be reset if a new operation with the same IV as the  */\n/* previous one is required (or decryption follows encryption with  */\n/* the same IV array).                                              */\n\nAES_RETURN aes_test_alignment_detection(unsigned int n);\n\nAES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, const aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, const aes_decrypt_ctx cx[1]);\n\nAES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, const aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, const aes_decrypt_ctx cx[1]);\n\nAES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);\n\n#define aes_ofb_encrypt aes_ofb_crypt\n#define aes_ofb_decrypt aes_ofb_crypt\n\nAES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx cx[1]);\n\ntypedef void cbuf_inc(unsigned char *cbuf);\n\n#define aes_ctr_encrypt aes_ctr_crypt\n#define aes_ctr_decrypt aes_ctr_crypt\n\nAES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,\n            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]);\n\n#endif\n\n#if 0\n#  define ADD_AESNI_MODE_CALLS\n#endif\n\n#if 0 && defined( ADD_AESNI_MODE_CALLS )\n#  define USE_AES_CONTEXT\n#endif\n\n#ifdef ADD_AESNI_MODE_CALLS\n#  ifdef USE_AES_CONTEXT\n\nAES_RETURN aes_CBC_encrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    const aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_CBC_decrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    const aes_decrypt_ctx cx[1]);\n\nAES_RETURN AES_CTR_encrypt(const unsigned char *in,\n    unsigned char *out,\n    const unsigned char ivec[8],\n    const unsigned char nonce[4],\n    unsigned long length,\n    const aes_encrypt_ctx cx[1]);\n\n#  else\n\nvoid aes_CBC_encrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    unsigned char *key,\n    int number_of_rounds);\n\nvoid aes_CBC_decrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    unsigned char *key,\n    int number_of_rounds);\n\nvoid AES_CTR_encrypt(const unsigned char *in,\n    unsigned char *out,\n    const unsigned char ivec[8],\n    const unsigned char nonce[4],\n    unsigned long length,\n    const unsigned char *key,\n    int number_of_rounds);\n\n#  endif\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aes_amd64.asm",
    "content": "; ---------------------------------------------------------------------------\n; Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n;\n; The redistribution and use of this software (with or without changes)\n; is allowed without the payment of fees or royalties provided that:\n;\n;   source code distributions include the above copyright notice, this\n;   list of conditions and the following disclaimer;\n;\n;   binary distributions include the above copyright notice, this list\n;   of conditions and the following disclaimer in their documentation.\n;\n; This software is provided 'as is' with no explicit or implied warranties\n; in respect of its operation, including, but not limited to, correctness\n; and fitness for purpose.\n; ---------------------------------------------------------------------------\n; Issue Date: 20/12/2007\n;\n; I am grateful to Dag Arne Osvik for many discussions of the techniques that\n; can be used to optimise AES assembler code on AMD64/EM64T architectures.\n; Some of the techniques used in this implementation are the result of\n; suggestions made by him for which I am most grateful.\n\n; An AES implementation for AMD64 processors using the YASM assembler.  This\n; implemetation provides only encryption, decryption and hence requires key\n; scheduling support in C. It uses 8k bytes of tables but its encryption and\n; decryption performance is very close to that obtained using large tables.\n; It can use either Windows or Gnu/Linux calling conventions, which are as\n; follows:\n;               windows  gnu/linux\n;\n;   in_blk          rcx     rdi\n;   out_blk         rdx     rsi\n;   context (cx)     r8     rdx\n;\n;   preserved       rsi      -    + rbx, rbp, rsp, r12, r13, r14 & r15\n;   registers       rdi      -      on both\n;\n;   destroyed        -      rsi   + rax, rcx, rdx, r8, r9, r10 & r11\n;   registers        -      rdi     on both\n;\n; The default convention is that for windows, the gnu/linux convention being\n; used if __GNUC__ is defined.\n;\n; To build for cryptlib (pcg):\n;\n;\tyasm -Xvc -f win64 -D _SEH_ -o aescryptx64.obj aes_amd64.asm\n;\n; Define _SEH_ to include support for Win64 structured exception handling\n; (this requires YASM version 0.6 or later).\n;\n; This code provides the standard AES block size (128 bits, 16 bytes) and the\n; three standard AES key sizes (128, 192 and 256 bits). It has the same call\n; interface as my C implementation.  It uses the Microsoft C AMD64 calling\n; conventions in which the three parameters are placed in  rcx, rdx and r8\n; respectively.  The rbx, rsi, rdi, rbp and r12..r15 registers are preserved.\n;\n;     AES_RETURN aes_encrypt(const unsigned char in_blk[],\n;                   unsigned char out_blk[], const aes_encrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt(const unsigned char in_blk[],\n;                   unsigned char out_blk[], const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],\n;                                            const aes_encrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],\n;                                            const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_encrypt_key(const unsigned char key[],\n;                           unsigned int len, const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt_key(const unsigned char key[],\n;                           unsigned int len, const aes_decrypt_ctx cx[1]);\n;\n; where <NNN> is 128, 192 or 256.  In the last two calls the length can be in\n; either bits or bytes.\n\n;----------------------------------------------------------------------------\n; Comment in/out the following lines to obtain the desired subroutines. These\n; selections MUST match those in the C header files aes.h and aesopt.h\n\n%define USE_INTEL_AES_IF_PRESENT\n%define AES_128                 ; define if AES with 128 bit keys is needed\n%define AES_192                 ; define if AES with 192 bit keys is needed\n%define AES_256                 ; define if AES with 256 bit keys is needed\n%define AES_VAR                 ; define if a variable key size is needed\n%define ENCRYPTION              ; define if encryption is needed\n%define DECRYPTION              ; define if decryption is needed\n;----------------------------------------------------------------------------\n\n%ifdef USE_INTEL_AES_IF_PRESENT\n%define aes_ni(x) aes_ %+ x %+ _i\n%undef  AES_REV_DKS\n%else\n%define aes_ni(x) aes_ %+ x\n%define AES_REV_DKS\n%endif\n\n%define LAST_ROUND_TABLES       ; define for the faster version using extra tables\n\n; The encryption key schedule has the following in memory layout where N is the\n; number of rounds (10, 12 or 14):\n;\n; lo: | input key (round 0)  |  ; each round is four 32-bit words\n;     | encryption round 1   |\n;     | encryption round 2   |\n;     ....\n;     | encryption round N-1 |\n; hi: | encryption round N   |\n;\n; The decryption key schedule is normally set up so that it has the same\n; layout as above by actually reversing the order of the encryption key\n; schedule in memory (this happens when AES_REV_DKS is set):\n;\n; lo: | decryption round 0   | =              | encryption round N   |\n;     | decryption round 1   | = INV_MIX_COL[ | encryption round N-1 | ]\n;     | decryption round 2   | = INV_MIX_COL[ | encryption round N-2 | ]\n;     ....                       ....\n;     | decryption round N-1 | = INV_MIX_COL[ | encryption round 1   | ]\n; hi: | decryption round N   | =              | input key (round 0)  |\n;\n; with rounds except the first and last modified using inv_mix_column()\n; But if AES_REV_DKS is NOT set the order of keys is left as it is for\n; encryption so that it has to be accessed in reverse when used for\n; decryption (although the inverse mix column modifications are done)\n;\n; lo: | decryption round 0   | =              | input key (round 0)  |\n;     | decryption round 1   | = INV_MIX_COL[ | encryption round 1   | ]\n;     | decryption round 2   | = INV_MIX_COL[ | encryption round 2   | ]\n;     ....                       ....\n;     | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ]\n; hi: | decryption round N   | =              | encryption round N   |\n;\n; This layout is faster when the assembler key scheduling is used (not\n; used here).\n;\n; The DLL interface must use the _stdcall convention in which the number\n; of bytes of parameter space is added after an @ to the rouutine's name.\n; We must also remove our parameters from the stack before return (see\n; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version.\n\n; %define DLL_EXPORT\n\n; End of user defines\n\n%ifdef AES_VAR\n%ifndef AES_128\n%define AES_128\n%endif\n%ifndef AES_192\n%define AES_192\n%endif\n%ifndef AES_256\n%define AES_256\n%endif\n%endif\n\n%ifdef AES_VAR\n%define KS_LENGTH       60\n%elifdef AES_256\n%define KS_LENGTH       60\n%elifdef AES_192\n%define KS_LENGTH       52\n%else\n%define KS_LENGTH       44\n%endif\n\n%define     r0  rax\n%define     r1  rdx\n%define     r2  rcx\n%define     r3  rbx\n%define     r4  rsi\n%define     r5  rdi\n%define     r6  rbp\n%define     r7  rsp\n\n%define     raxd    eax\n%define     rdxd    edx\n%define     rcxd    ecx\n%define     rbxd    ebx\n%define     rsid    esi\n%define     rdid    edi\n%define     rbpd    ebp\n%define     rspd    esp\n\n%define     raxb    al\n%define     rdxb    dl\n%define     rcxb    cl\n%define     rbxb    bl\n%define     rsib    sil\n%define     rdib    dil\n%define     rbpb    bpl\n%define     rspb    spl\n\n%define     r0h ah\n%define     r1h dh\n%define     r2h ch\n%define     r3h bh\n\n%define     r0d eax\n%define     r1d edx\n%define     r2d ecx\n%define     r3d ebx\n\n; finite field multiplies by {02}, {04} and {08}\n\n%define f2(x)   ((x<<1)^(((x>>7)&1)*0x11b))\n%define f4(x)   ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))\n%define f8(x)   ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))\n\n; finite field multiplies required in table generation\n\n%define f3(x)   (f2(x) ^ x)\n%define f9(x)   (f8(x) ^ x)\n%define fb(x)   (f8(x) ^ f2(x) ^ x)\n%define fd(x)   (f8(x) ^ f4(x) ^ x)\n%define fe(x)   (f8(x) ^ f4(x) ^ f2(x))\n\n; macro for expanding S-box data\n\n%macro enc_vals 1\n    db  %1(0x63),%1(0x7c),%1(0x77),%1(0x7b),%1(0xf2),%1(0x6b),%1(0x6f),%1(0xc5)\n    db  %1(0x30),%1(0x01),%1(0x67),%1(0x2b),%1(0xfe),%1(0xd7),%1(0xab),%1(0x76)\n    db  %1(0xca),%1(0x82),%1(0xc9),%1(0x7d),%1(0xfa),%1(0x59),%1(0x47),%1(0xf0)\n    db  %1(0xad),%1(0xd4),%1(0xa2),%1(0xaf),%1(0x9c),%1(0xa4),%1(0x72),%1(0xc0)\n    db  %1(0xb7),%1(0xfd),%1(0x93),%1(0x26),%1(0x36),%1(0x3f),%1(0xf7),%1(0xcc)\n    db  %1(0x34),%1(0xa5),%1(0xe5),%1(0xf1),%1(0x71),%1(0xd8),%1(0x31),%1(0x15)\n    db  %1(0x04),%1(0xc7),%1(0x23),%1(0xc3),%1(0x18),%1(0x96),%1(0x05),%1(0x9a)\n    db  %1(0x07),%1(0x12),%1(0x80),%1(0xe2),%1(0xeb),%1(0x27),%1(0xb2),%1(0x75)\n    db  %1(0x09),%1(0x83),%1(0x2c),%1(0x1a),%1(0x1b),%1(0x6e),%1(0x5a),%1(0xa0)\n    db  %1(0x52),%1(0x3b),%1(0xd6),%1(0xb3),%1(0x29),%1(0xe3),%1(0x2f),%1(0x84)\n    db  %1(0x53),%1(0xd1),%1(0x00),%1(0xed),%1(0x20),%1(0xfc),%1(0xb1),%1(0x5b)\n    db  %1(0x6a),%1(0xcb),%1(0xbe),%1(0x39),%1(0x4a),%1(0x4c),%1(0x58),%1(0xcf)\n    db  %1(0xd0),%1(0xef),%1(0xaa),%1(0xfb),%1(0x43),%1(0x4d),%1(0x33),%1(0x85)\n    db  %1(0x45),%1(0xf9),%1(0x02),%1(0x7f),%1(0x50),%1(0x3c),%1(0x9f),%1(0xa8)\n    db  %1(0x51),%1(0xa3),%1(0x40),%1(0x8f),%1(0x92),%1(0x9d),%1(0x38),%1(0xf5)\n    db  %1(0xbc),%1(0xb6),%1(0xda),%1(0x21),%1(0x10),%1(0xff),%1(0xf3),%1(0xd2)\n    db  %1(0xcd),%1(0x0c),%1(0x13),%1(0xec),%1(0x5f),%1(0x97),%1(0x44),%1(0x17)\n    db  %1(0xc4),%1(0xa7),%1(0x7e),%1(0x3d),%1(0x64),%1(0x5d),%1(0x19),%1(0x73)\n    db  %1(0x60),%1(0x81),%1(0x4f),%1(0xdc),%1(0x22),%1(0x2a),%1(0x90),%1(0x88)\n    db  %1(0x46),%1(0xee),%1(0xb8),%1(0x14),%1(0xde),%1(0x5e),%1(0x0b),%1(0xdb)\n    db  %1(0xe0),%1(0x32),%1(0x3a),%1(0x0a),%1(0x49),%1(0x06),%1(0x24),%1(0x5c)\n    db  %1(0xc2),%1(0xd3),%1(0xac),%1(0x62),%1(0x91),%1(0x95),%1(0xe4),%1(0x79)\n    db  %1(0xe7),%1(0xc8),%1(0x37),%1(0x6d),%1(0x8d),%1(0xd5),%1(0x4e),%1(0xa9)\n    db  %1(0x6c),%1(0x56),%1(0xf4),%1(0xea),%1(0x65),%1(0x7a),%1(0xae),%1(0x08)\n    db  %1(0xba),%1(0x78),%1(0x25),%1(0x2e),%1(0x1c),%1(0xa6),%1(0xb4),%1(0xc6)\n    db  %1(0xe8),%1(0xdd),%1(0x74),%1(0x1f),%1(0x4b),%1(0xbd),%1(0x8b),%1(0x8a)\n    db  %1(0x70),%1(0x3e),%1(0xb5),%1(0x66),%1(0x48),%1(0x03),%1(0xf6),%1(0x0e)\n    db  %1(0x61),%1(0x35),%1(0x57),%1(0xb9),%1(0x86),%1(0xc1),%1(0x1d),%1(0x9e)\n    db  %1(0xe1),%1(0xf8),%1(0x98),%1(0x11),%1(0x69),%1(0xd9),%1(0x8e),%1(0x94)\n    db  %1(0x9b),%1(0x1e),%1(0x87),%1(0xe9),%1(0xce),%1(0x55),%1(0x28),%1(0xdf)\n    db  %1(0x8c),%1(0xa1),%1(0x89),%1(0x0d),%1(0xbf),%1(0xe6),%1(0x42),%1(0x68)\n    db  %1(0x41),%1(0x99),%1(0x2d),%1(0x0f),%1(0xb0),%1(0x54),%1(0xbb),%1(0x16)\n%endmacro\n\n%macro dec_vals 1\n    db  %1(0x52),%1(0x09),%1(0x6a),%1(0xd5),%1(0x30),%1(0x36),%1(0xa5),%1(0x38)\n    db  %1(0xbf),%1(0x40),%1(0xa3),%1(0x9e),%1(0x81),%1(0xf3),%1(0xd7),%1(0xfb)\n    db  %1(0x7c),%1(0xe3),%1(0x39),%1(0x82),%1(0x9b),%1(0x2f),%1(0xff),%1(0x87)\n    db  %1(0x34),%1(0x8e),%1(0x43),%1(0x44),%1(0xc4),%1(0xde),%1(0xe9),%1(0xcb)\n    db  %1(0x54),%1(0x7b),%1(0x94),%1(0x32),%1(0xa6),%1(0xc2),%1(0x23),%1(0x3d)\n    db  %1(0xee),%1(0x4c),%1(0x95),%1(0x0b),%1(0x42),%1(0xfa),%1(0xc3),%1(0x4e)\n    db  %1(0x08),%1(0x2e),%1(0xa1),%1(0x66),%1(0x28),%1(0xd9),%1(0x24),%1(0xb2)\n    db  %1(0x76),%1(0x5b),%1(0xa2),%1(0x49),%1(0x6d),%1(0x8b),%1(0xd1),%1(0x25)\n    db  %1(0x72),%1(0xf8),%1(0xf6),%1(0x64),%1(0x86),%1(0x68),%1(0x98),%1(0x16)\n    db  %1(0xd4),%1(0xa4),%1(0x5c),%1(0xcc),%1(0x5d),%1(0x65),%1(0xb6),%1(0x92)\n    db  %1(0x6c),%1(0x70),%1(0x48),%1(0x50),%1(0xfd),%1(0xed),%1(0xb9),%1(0xda)\n    db  %1(0x5e),%1(0x15),%1(0x46),%1(0x57),%1(0xa7),%1(0x8d),%1(0x9d),%1(0x84)\n    db  %1(0x90),%1(0xd8),%1(0xab),%1(0x00),%1(0x8c),%1(0xbc),%1(0xd3),%1(0x0a)\n    db  %1(0xf7),%1(0xe4),%1(0x58),%1(0x05),%1(0xb8),%1(0xb3),%1(0x45),%1(0x06)\n    db  %1(0xd0),%1(0x2c),%1(0x1e),%1(0x8f),%1(0xca),%1(0x3f),%1(0x0f),%1(0x02)\n    db  %1(0xc1),%1(0xaf),%1(0xbd),%1(0x03),%1(0x01),%1(0x13),%1(0x8a),%1(0x6b)\n    db  %1(0x3a),%1(0x91),%1(0x11),%1(0x41),%1(0x4f),%1(0x67),%1(0xdc),%1(0xea)\n    db  %1(0x97),%1(0xf2),%1(0xcf),%1(0xce),%1(0xf0),%1(0xb4),%1(0xe6),%1(0x73)\n    db  %1(0x96),%1(0xac),%1(0x74),%1(0x22),%1(0xe7),%1(0xad),%1(0x35),%1(0x85)\n    db  %1(0xe2),%1(0xf9),%1(0x37),%1(0xe8),%1(0x1c),%1(0x75),%1(0xdf),%1(0x6e)\n    db  %1(0x47),%1(0xf1),%1(0x1a),%1(0x71),%1(0x1d),%1(0x29),%1(0xc5),%1(0x89)\n    db  %1(0x6f),%1(0xb7),%1(0x62),%1(0x0e),%1(0xaa),%1(0x18),%1(0xbe),%1(0x1b)\n    db  %1(0xfc),%1(0x56),%1(0x3e),%1(0x4b),%1(0xc6),%1(0xd2),%1(0x79),%1(0x20)\n    db  %1(0x9a),%1(0xdb),%1(0xc0),%1(0xfe),%1(0x78),%1(0xcd),%1(0x5a),%1(0xf4)\n    db  %1(0x1f),%1(0xdd),%1(0xa8),%1(0x33),%1(0x88),%1(0x07),%1(0xc7),%1(0x31)\n    db  %1(0xb1),%1(0x12),%1(0x10),%1(0x59),%1(0x27),%1(0x80),%1(0xec),%1(0x5f)\n    db  %1(0x60),%1(0x51),%1(0x7f),%1(0xa9),%1(0x19),%1(0xb5),%1(0x4a),%1(0x0d)\n    db  %1(0x2d),%1(0xe5),%1(0x7a),%1(0x9f),%1(0x93),%1(0xc9),%1(0x9c),%1(0xef)\n    db  %1(0xa0),%1(0xe0),%1(0x3b),%1(0x4d),%1(0xae),%1(0x2a),%1(0xf5),%1(0xb0)\n    db  %1(0xc8),%1(0xeb),%1(0xbb),%1(0x3c),%1(0x83),%1(0x53),%1(0x99),%1(0x61)\n    db  %1(0x17),%1(0x2b),%1(0x04),%1(0x7e),%1(0xba),%1(0x77),%1(0xd6),%1(0x26)\n    db  %1(0xe1),%1(0x69),%1(0x14),%1(0x63),%1(0x55),%1(0x21),%1(0x0c),%1(0x7d)\n%endmacro\n\n%define u8(x)   f2(x), x, x, f3(x), f2(x), x, x, f3(x)\n%define v8(x)   fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x\n%define w8(x)   x, 0, 0, 0, x, 0, 0, 0\n\n%define tptr    rbp     ; table pointer\n%define kptr    r8      ; key schedule pointer\n%define fofs    128     ; adjust offset in key schedule to keep |disp| < 128\n%define fk_ref(x,y) [kptr-16*x+fofs+4*y]\n%ifdef  AES_REV_DKS\n%define rofs    128\n%define ik_ref(x,y) [kptr-16*x+rofs+4*y]\n%else\n%define rofs    -128\n%define ik_ref(x,y) [kptr+16*x+rofs+4*y]\n%endif\n\n%define tab_0(x)   [tptr+8*x]\n%define tab_1(x)   [tptr+8*x+3]\n%define tab_2(x)   [tptr+8*x+2]\n%define tab_3(x)   [tptr+8*x+1]\n%define tab_f(x)   byte [tptr+8*x+1]\n%define tab_i(x)   byte [tptr+8*x+7]\n%define t_ref(x,r) tab_ %+ x(r)\n\n%macro ff_rnd 5                 ; normal forward round\n    mov     %1d, fk_ref(%5,0)\n    mov     %2d, fk_ref(%5,1)\n    mov     %3d, fk_ref(%5,2)\n    mov     %4d, fk_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    shr     eax, 16\n    xor     %1d, t_ref(0,rsi)\n    xor     %4d, t_ref(1,rdi)\n    movzx   esi, al\n    movzx   edi, ah\n    xor     %3d, t_ref(2,rsi)\n    xor     %2d, t_ref(3,rdi)\n\n    movzx   esi, bl\n    movzx   edi, bh\n    shr     ebx, 16\n    xor     %2d, t_ref(0,rsi)\n    xor     %1d, t_ref(1,rdi)\n    movzx   esi, bl\n    movzx   edi, bh\n    xor     %4d, t_ref(2,rsi)\n    xor     %3d, t_ref(3,rdi)\n\n    movzx   esi, cl\n    movzx   edi, ch\n    shr     ecx, 16\n    xor     %3d, t_ref(0,rsi)\n    xor     %2d, t_ref(1,rdi)\n    movzx   esi, cl\n    movzx   edi, ch\n    xor     %1d, t_ref(2,rsi)\n    xor     %4d, t_ref(3,rdi)\n\n    movzx   esi, dl\n    movzx   edi, dh\n    shr     edx, 16\n    xor     %4d, t_ref(0,rsi)\n    xor     %3d, t_ref(1,rdi)\n    movzx   esi, dl\n    movzx   edi, dh\n    xor     %2d, t_ref(2,rsi)\n    xor     %1d, t_ref(3,rdi)\n\n    mov     eax,%1d\n    mov     ebx,%2d\n    mov     ecx,%3d\n    mov     edx,%4d\n%endmacro\n\n%ifdef LAST_ROUND_TABLES\n\n%macro fl_rnd 5                 ; last forward round\n    add     tptr, 2048\n    mov     %1d, fk_ref(%5,0)\n    mov     %2d, fk_ref(%5,1)\n    mov     %3d, fk_ref(%5,2)\n    mov     %4d, fk_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    shr     eax, 16\n    xor     %1d, t_ref(0,rsi)\n    xor     %4d, t_ref(1,rdi)\n    movzx   esi, al\n    movzx   edi, ah\n    xor     %3d, t_ref(2,rsi)\n    xor     %2d, t_ref(3,rdi)\n\n    movzx   esi, bl\n    movzx   edi, bh\n    shr     ebx, 16\n    xor     %2d, t_ref(0,rsi)\n    xor     %1d, t_ref(1,rdi)\n    movzx   esi, bl\n    movzx   edi, bh\n    xor     %4d, t_ref(2,rsi)\n    xor     %3d, t_ref(3,rdi)\n\n    movzx   esi, cl\n    movzx   edi, ch\n    shr     ecx, 16\n    xor     %3d, t_ref(0,rsi)\n    xor     %2d, t_ref(1,rdi)\n    movzx   esi, cl\n    movzx   edi, ch\n    xor     %1d, t_ref(2,rsi)\n    xor     %4d, t_ref(3,rdi)\n\n    movzx   esi, dl\n    movzx   edi, dh\n    shr     edx, 16\n    xor     %4d, t_ref(0,rsi)\n    xor     %3d, t_ref(1,rdi)\n    movzx   esi, dl\n    movzx   edi, dh\n    xor     %2d, t_ref(2,rsi)\n    xor     %1d, t_ref(3,rdi)\n%endmacro\n\n%else\n\n%macro fl_rnd 5                 ; last forward round\n    mov     %1d, fk_ref(%5,0)\n    mov     %2d, fk_ref(%5,1)\n    mov     %3d, fk_ref(%5,2)\n    mov     %4d, fk_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    shr     eax, 16\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    xor     %1d, esi\n    rol     edi, 8\n    xor     %4d, edi\n    movzx   esi, al\n    movzx   edi, ah\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %3d, esi\n    xor     %2d, edi\n\n    movzx   esi, bl\n    movzx   edi, bh\n    shr     ebx, 16\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    xor     %2d, esi\n    rol     edi, 8\n    xor     %1d, edi\n    movzx   esi, bl\n    movzx   edi, bh\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %4d, esi\n    xor     %3d, edi\n\n    movzx   esi, cl\n    movzx   edi, ch\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    shr     ecx, 16\n    xor     %3d, esi\n    rol     edi, 8\n    xor     %2d, edi\n    movzx   esi, cl\n    movzx   edi, ch\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %1d, esi\n    xor     %4d, edi\n\n    movzx   esi, dl\n    movzx   edi, dh\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    shr     edx, 16\n    xor     %4d, esi\n    rol     edi, 8\n    xor     %3d, edi\n    movzx   esi, dl\n    movzx   edi, dh\n    movzx   esi, t_ref(f,rsi)\n    movzx   edi, t_ref(f,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %2d, esi\n    xor     %1d, edi\n%endmacro\n\n%endif\n\n%macro ii_rnd 5                 ; normal inverse round\n    mov     %1d, ik_ref(%5,0)\n    mov     %2d, ik_ref(%5,1)\n    mov     %3d, ik_ref(%5,2)\n    mov     %4d, ik_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    shr     eax, 16\n    xor     %1d, t_ref(0,rsi)\n    xor     %2d, t_ref(1,rdi)\n    movzx   esi, al\n    movzx   edi, ah\n    xor     %3d, t_ref(2,rsi)\n    xor     %4d, t_ref(3,rdi)\n\n    movzx   esi, bl\n    movzx   edi, bh\n    shr     ebx, 16\n    xor     %2d, t_ref(0,rsi)\n    xor     %3d, t_ref(1,rdi)\n    movzx   esi, bl\n    movzx   edi, bh\n    xor     %4d, t_ref(2,rsi)\n    xor     %1d, t_ref(3,rdi)\n\n    movzx   esi, cl\n    movzx   edi, ch\n    shr     ecx, 16\n    xor     %3d, t_ref(0,rsi)\n    xor     %4d, t_ref(1,rdi)\n    movzx   esi, cl\n    movzx   edi, ch\n    xor     %1d, t_ref(2,rsi)\n    xor     %2d, t_ref(3,rdi)\n\n    movzx   esi, dl\n    movzx   edi, dh\n    shr     edx, 16\n    xor     %4d, t_ref(0,rsi)\n    xor     %1d, t_ref(1,rdi)\n    movzx   esi, dl\n    movzx   edi, dh\n    xor     %2d, t_ref(2,rsi)\n    xor     %3d, t_ref(3,rdi)\n\n    mov     eax,%1d\n    mov     ebx,%2d\n    mov     ecx,%3d\n    mov     edx,%4d\n%endmacro\n\n%ifdef LAST_ROUND_TABLES\n\n%macro il_rnd 5                 ; last inverse round\n    add     tptr, 2048\n    mov     %1d, ik_ref(%5,0)\n    mov     %2d, ik_ref(%5,1)\n    mov     %3d, ik_ref(%5,2)\n    mov     %4d, ik_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    shr     eax, 16\n    xor     %1d, t_ref(0,rsi)\n    xor     %2d, t_ref(1,rdi)\n    movzx   esi, al\n    movzx   edi, ah\n    xor     %3d, t_ref(2,rsi)\n    xor     %4d, t_ref(3,rdi)\n\n    movzx   esi, bl\n    movzx   edi, bh\n    shr     ebx, 16\n    xor     %2d, t_ref(0,rsi)\n    xor     %3d, t_ref(1,rdi)\n    movzx   esi, bl\n    movzx   edi, bh\n    xor     %4d, t_ref(2,rsi)\n    xor     %1d, t_ref(3,rdi)\n\n    movzx   esi, cl\n    movzx   edi, ch\n    shr     ecx, 16\n    xor     %3d, t_ref(0,rsi)\n    xor     %4d, t_ref(1,rdi)\n    movzx   esi, cl\n    movzx   edi, ch\n    xor     %1d, t_ref(2,rsi)\n    xor     %2d, t_ref(3,rdi)\n\n    movzx   esi, dl\n    movzx   edi, dh\n    shr     edx, 16\n    xor     %4d, t_ref(0,rsi)\n    xor     %1d, t_ref(1,rdi)\n    movzx   esi, dl\n    movzx   edi, dh\n    xor     %2d, t_ref(2,rsi)\n    xor     %3d, t_ref(3,rdi)\n%endmacro\n\n%else\n\n%macro il_rnd 5                 ; last inverse round\n    mov     %1d, ik_ref(%5,0)\n    mov     %2d, ik_ref(%5,1)\n    mov     %3d, ik_ref(%5,2)\n    mov     %4d, ik_ref(%5,3)\n\n    movzx   esi, al\n    movzx   edi, ah\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    shr     eax, 16\n    xor     %1d, esi\n    rol     edi, 8\n    xor     %2d, edi\n    movzx   esi, al\n    movzx   edi, ah\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %3d, esi\n    xor     %4d, edi\n\n    movzx   esi, bl\n    movzx   edi, bh\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    shr     ebx, 16\n    xor     %2d, esi\n    rol     edi, 8\n    xor     %3d, edi\n    movzx   esi, bl\n    movzx   edi, bh\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %4d, esi\n    xor     %1d, edi\n\n    movzx   esi, cl\n    movzx   edi, ch\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    shr     ecx, 16\n    xor     %3d, esi\n    rol     edi, 8\n    xor     %4d, edi\n    movzx   esi, cl\n    movzx   edi, ch\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %1d, esi\n    xor     %2d, edi\n\n    movzx   esi, dl\n    movzx   edi, dh\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    shr     edx, 16\n    xor     %4d, esi\n    rol     edi, 8\n    xor     %1d, edi\n    movzx   esi, dl\n    movzx   edi, dh\n    movzx   esi, t_ref(i,rsi)\n    movzx   edi, t_ref(i,rdi)\n    rol     esi, 16\n    rol     edi, 24\n    xor     %2d, esi\n    xor     %3d, edi\n%endmacro\n\n%endif\n\n%ifdef ENCRYPTION\n\n    global  aes_ni(encrypt)\n%ifdef DLL_EXPORT\n    export  aes_ni(encrypt)\n%endif\n\n    section .data align=64\n    align   64\nenc_tab:\n    enc_vals u8\n%ifdef LAST_ROUND_TABLES\n    enc_vals w8\n%endif\n\n    section .text align=16\n    align   16\n\n%ifdef _SEH_\nproc_frame aes_ni(encrypt)\n    alloc_stack\t7*8\t\t\t; 7 to align stack to 16 bytes\n    save_reg\trsi,4*8\n    save_reg\trdi,5*8\n    save_reg\trbx,1*8\n    save_reg\trbp,2*8\n    save_reg\tr12,3*8\nend_prologue\n    mov     rdi, rcx        ; input pointer\n    mov     [rsp+0*8], rdx  ; output pointer\n%else\n    aes_ni(encrypt):\n    %ifdef __GNUC__\n        sub     rsp, 4*8        ; gnu/linux binary interface\n        mov     [rsp+0*8], rsi  ; output pointer\n        mov     r8, rdx         ; context\n    %else\n        sub     rsp, 6*8        ; windows binary interface\n        mov     [rsp+4*8], rsi\n        mov     [rsp+5*8], rdi\n        mov     rdi, rcx        ; input pointer\n        mov     [rsp+0*8], rdx  ; output pointer\n    %endif\n        mov     [rsp+1*8], rbx  ; input pointer in rdi\n        mov     [rsp+2*8], rbp  ; output pointer in [rsp]\n        mov     [rsp+3*8], r12  ; context in r8\n%endif\n\n    movzx   esi, byte [kptr+4*KS_LENGTH]\n    lea     tptr, [rel enc_tab]\n    sub     kptr, fofs\n\n    mov     eax, [rdi+0*4]\n    mov     ebx, [rdi+1*4]\n    mov     ecx, [rdi+2*4]\n    mov     edx, [rdi+3*4]\n\n    xor     eax, [kptr+fofs]\n    xor     ebx, [kptr+fofs+4]\n    xor     ecx, [kptr+fofs+8]\n    xor     edx, [kptr+fofs+12]\n\n    lea     kptr,[kptr+rsi]\n    cmp     esi, 10*16\n    je      .3\n    cmp     esi, 12*16\n    je      .2\n    cmp     esi, 14*16\n    je      .1\n    mov     rax, -1\n    jmp     .4\n\n.1: ff_rnd  r9, r10, r11, r12, 13\n    ff_rnd  r9, r10, r11, r12, 12\n.2: ff_rnd  r9, r10, r11, r12, 11\n    ff_rnd  r9, r10, r11, r12, 10\n.3: ff_rnd  r9, r10, r11, r12, 9\n    ff_rnd  r9, r10, r11, r12, 8\n    ff_rnd  r9, r10, r11, r12, 7\n    ff_rnd  r9, r10, r11, r12, 6\n    ff_rnd  r9, r10, r11, r12, 5\n    ff_rnd  r9, r10, r11, r12, 4\n    ff_rnd  r9, r10, r11, r12, 3\n    ff_rnd  r9, r10, r11, r12, 2\n    ff_rnd  r9, r10, r11, r12, 1\n    fl_rnd  r9, r10, r11, r12, 0\n\n    mov     rbx, [rsp]\n    mov     [rbx], r9d\n    mov     [rbx+4], r10d\n    mov     [rbx+8], r11d\n    mov     [rbx+12], r12d\n    xor     rax, rax\n.4:\n    mov     rbx, [rsp+1*8]\n    mov     rbp, [rsp+2*8]\n    mov     r12, [rsp+3*8]\n%ifdef __GNUC__\n    add     rsp, 4*8\n    ret\n%else\n    mov     rsi, [rsp+4*8]\n    mov     rdi, [rsp+5*8]\n    %ifdef _SEH_\n        add     rsp, 7*8\n        ret\n    endproc_frame\n    %else\n        add     rsp, 6*8\n        ret\n    %endif\n%endif\n\n%endif\n\n%ifdef DECRYPTION\n\n    global  aes_ni(decrypt)\n%ifdef DLL_EXPORT\n    export  aes_ni(decrypt)\n%endif\n\n    section .data\n    align   64\ndec_tab:\n    dec_vals v8\n%ifdef LAST_ROUND_TABLES\n    dec_vals w8\n%endif\n\n    section .text\n    align   16\n\n%ifdef _SEH_\nproc_frame aes_ni(decrypt)\n    alloc_stack\t7*8\t\t\t; 7 to align stack to 16 bytes\n    save_reg\trsi,4*8\n    save_reg\trdi,5*8\n    save_reg\trbx,1*8\n    save_reg\trbp,2*8\n    save_reg\tr12,3*8\nend_prologue\n    mov     rdi, rcx        ; input pointer\n    mov     [rsp+0*8], rdx  ; output pointer\n%else\n    aes_ni(decrypt):\n    %ifdef __GNUC__\n        sub     rsp, 4*8        ; gnu/linux binary interface\n        mov     [rsp+0*8], rsi  ; output pointer\n        mov     r8, rdx         ; context\n    %else\n        sub     rsp, 6*8        ; windows binary interface\n        mov     [rsp+4*8], rsi\n        mov     [rsp+5*8], rdi\n        mov     rdi, rcx        ; input pointer\n        mov     [rsp+0*8], rdx  ; output pointer\n    %endif\n        mov     [rsp+1*8], rbx  ; input pointer in rdi\n        mov     [rsp+2*8], rbp  ; output pointer in [rsp]\n        mov     [rsp+3*8], r12  ; context in r8\n%endif\n\n    movzx   esi, byte[kptr+4*KS_LENGTH]\n    lea     tptr, [rel dec_tab]\n    sub     kptr, rofs\n\n    mov     eax, [rdi+0*4]\n    mov     ebx, [rdi+1*4]\n    mov     ecx, [rdi+2*4]\n    mov     edx, [rdi+3*4]\n\n%ifdef      AES_REV_DKS\n    mov     rdi, kptr\n    lea     kptr,[kptr+rsi]\n%else\n    lea     rdi,[kptr+rsi]\n%endif\n\n    xor     eax, [rdi+rofs]\n    xor     ebx, [rdi+rofs+4]\n    xor     ecx, [rdi+rofs+8]\n    xor     edx, [rdi+rofs+12]\n\n    cmp     esi, 10*16\n    je      .3\n    cmp     esi, 12*16\n    je      .2\n    cmp     esi, 14*16\n    je      .1\n    mov     rax, -1\n    jmp     .4\n\n.1: ii_rnd  r9, r10, r11, r12, 13\n    ii_rnd  r9, r10, r11, r12, 12\n.2: ii_rnd  r9, r10, r11, r12, 11\n    ii_rnd  r9, r10, r11, r12, 10\n.3: ii_rnd  r9, r10, r11, r12, 9\n    ii_rnd  r9, r10, r11, r12, 8\n    ii_rnd  r9, r10, r11, r12, 7\n    ii_rnd  r9, r10, r11, r12, 6\n    ii_rnd  r9, r10, r11, r12, 5\n    ii_rnd  r9, r10, r11, r12, 4\n    ii_rnd  r9, r10, r11, r12, 3\n    ii_rnd  r9, r10, r11, r12, 2\n    ii_rnd  r9, r10, r11, r12, 1\n    il_rnd  r9, r10, r11, r12, 0\n\n    mov     rbx, [rsp]\n    mov     [rbx], r9d\n    mov     [rbx+4], r10d\n    mov     [rbx+8], r11d\n    mov     [rbx+12], r12d\n    xor     rax, rax\n.4: mov     rbx, [rsp+1*8]\n    mov     rbp, [rsp+2*8]\n    mov     r12, [rsp+3*8]\n%ifdef __GNUC__\n    add     rsp, 4*8\n    ret\n%else\n    mov     rsi, [rsp+4*8]\n    mov     rdi, [rsp+5*8]\n    %ifdef _SEH_\n        add     rsp, 7*8\n        ret\n    endproc_frame\n    %else\n        add     rsp, 6*8\n        ret\n    %endif\n%endif\n\n%endif\n\n    end\n"
  },
  {
    "path": "deps/cl345/crypt/aes_modes.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n These subroutines implement multiple block AES modes for ECB, CBC, CFB,\n OFB and CTR encryption,  The code provides support for the VIA Advanced\n Cryptography Engine (ACE).\n\n NOTE: In the following subroutines, the AES contexts (ctx) must be\n 16 byte aligned if VIA ACE is being used\n*/\n\n#include <string.h>\n#include <assert.h>\n#if 0\t\t\t\t\t\t/* pcg */\n#include <stdint.h>\n#endif /* 0 */\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"aesopt.h\"\n#else\n  #include \"crypt/aesopt.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( AES_MODES )\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 800 )\n#pragma intrinsic(memcpy)\n#endif\n\n#define BFR_BLOCKS      8\n\n/* These values are used to detect long word alignment in order to */\n/* speed up some buffer operations. This facility may not work on  */\n/* some machines so this define can be commented out if necessary  */\n\n#define FAST_BUFFER_OPERATIONS\n\n#define lp32(x)         ((uint32_t*)(x))\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n#include \"crypt/aes_via_ace.h\"\t/* pcg */\n\n#pragma pack(16)\n\naligned_array(unsigned long,    enc_gen_table, 12, 16) =    NEH_ENC_GEN_DATA;\naligned_array(unsigned long,   enc_load_table, 12, 16) =   NEH_ENC_LOAD_DATA;\naligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;\naligned_array(unsigned long,    dec_gen_table, 12, 16) =    NEH_DEC_GEN_DATA;\naligned_array(unsigned long,   dec_load_table, 12, 16) =   NEH_DEC_LOAD_DATA;\naligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;\n\n/* NOTE: These control word macros must only be used after  */\n/* a key has been set up because they depend on key size    */\n/* See the VIA ACE documentation for key type information   */\n/* and aes_via_ace.h for non-default NEH_KEY_TYPE values    */\n\n#ifndef NEH_KEY_TYPE\n#  define NEH_KEY_TYPE NEH_HYBRID\n#endif\n\n#if NEH_KEY_TYPE == NEH_LOAD\n#define kd_adr(c)   ((uint8_t*)(c)->ks)\n#elif NEH_KEY_TYPE == NEH_GENERATE\n#define kd_adr(c)   ((uint8_t*)(c)->ks + (c)->inf.b[0])\n#elif NEH_KEY_TYPE == NEH_HYBRID\n#define kd_adr(c)   ((uint8_t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))\n#else\n#error no key type defined for VIA ACE \n#endif\n\n#else\n\n#define aligned_array(type, name, no, stride) type name[no]\n#define aligned_auto(type, name, no, stride)  type name[no]\n\n#endif\n\n#if defined( _MSC_VER ) && _MSC_VER > 1200\n\n#define via_cwd(cwd, ty, dir, len) \\\n    unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))\n\n#else\n\n#define via_cwd(cwd, ty, dir, len)              \\\n    aligned_auto(unsigned long, cwd, 4, 16);    \\\n    cwd[1] = cwd[2] = cwd[3] = 0;               \\\n    cwd[0] = neh_##dir##_##ty##_key(len)\n\n#endif\n\n/* test the code for detecting and setting pointer alignment */\n\nAES_RETURN aes_test_alignment_detection(unsigned int n)\t/* 4 <= n <= 16 */\n{\tuint8_t\tp[16];\n    uint32_t i, count_eq = 0, count_neq = 0;\n\n    if(n < 4 || n > 16)\n        return EXIT_FAILURE;\n\n    for(i = 0; i < n; ++i)\n    {\n        uint8_t *qf = ALIGN_FLOOR(p + i, n),\n                *qh =  ALIGN_CEIL(p + i, n);\n        \n        if(qh == qf)\n            ++count_eq;\n        else if(qh == qf + n)\n            ++count_neq;\n        else\n            return EXIT_FAILURE;\n    }\n    return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);\n}\n\nAES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1])\n{\n    ctx->inf.b[2] = 0;\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, const aes_encrypt_ctx ctx[1])\n{   int nb = len >> 4;\n\n    if(len & (AES_BLOCK_SIZE - 1))\n        return EXIT_FAILURE;\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n    if(ctx->inf.b[1] == 0xff)\n    {   uint8_t *ksp = (uint8_t*)(ctx->ks);\n        via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);\n\n        if(ALIGN_OFFSET( ctx, 16 ))\n            return EXIT_FAILURE;\n\n        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))\n        {\n            via_ecb_op5(ksp, cwd, ibuf, obuf, nb);\n        }\n        else\n        {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n            uint8_t *ip, *op;\n\n            while(nb)\n            {\n                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);\n\n                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                if(ip != ibuf)\n                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                via_ecb_op5(ksp, cwd, ip, op, m);\n\n                if(op != obuf)\n                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                ibuf += m * AES_BLOCK_SIZE;\n                obuf += m * AES_BLOCK_SIZE;\n                nb -= m;\n            }\n        }\n\n        return EXIT_SUCCESS;\n    }\n\n#endif\n\n#if !defined( ASSUME_VIA_ACE_PRESENT )\n    while(nb--)\n    {\n        if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n        ibuf += AES_BLOCK_SIZE;\n        obuf += AES_BLOCK_SIZE;\n    }\n#endif\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, const aes_decrypt_ctx ctx[1])\n{   int nb = len >> 4;\n\n    if(len & (AES_BLOCK_SIZE - 1))\n        return EXIT_FAILURE;\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n    if(ctx->inf.b[1] == 0xff)\n    {   uint8_t *ksp = kd_adr(ctx);\n        via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);\n\n        if(ALIGN_OFFSET( ctx, 16 ))\n            return EXIT_FAILURE;\n\n        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))\n        {\n            via_ecb_op5(ksp, cwd, ibuf, obuf, nb);\n        }\n        else\n        {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n            uint8_t *ip, *op;\n\n            while(nb)\n            {\n                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);\n\n                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                if(ip != ibuf)\n                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                via_ecb_op5(ksp, cwd, ip, op, m);\n\n                if(op != obuf)\n                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                ibuf += m * AES_BLOCK_SIZE;\n                obuf += m * AES_BLOCK_SIZE;\n                nb -= m;\n            }\n        }\n\n        return EXIT_SUCCESS;\n    }\n\n#endif\n\n#if !defined( ASSUME_VIA_ACE_PRESENT )\n    while(nb--)\n    {\n        if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n        ibuf += AES_BLOCK_SIZE;\n        obuf += AES_BLOCK_SIZE;\n    }\n#endif\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, const aes_encrypt_ctx ctx[1])\n{   int nb = len >> 4;\n\n    if(len & (AES_BLOCK_SIZE - 1))\n        return EXIT_FAILURE;\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n    if(ctx->inf.b[1] == 0xff)\n    {   uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;\n        aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);\n        via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);\n\n        if(ALIGN_OFFSET( ctx, 16 ))\n            return EXIT_FAILURE;\n\n        if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */\n        {\n            ivp = liv;\n            memcpy(liv, iv, AES_BLOCK_SIZE);\n        }\n\n        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))\n        {\n            via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);\n        }\n        else\n        {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n            uint8_t *ip, *op;\n\n            while(nb)\n            {\n                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);\n\n                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                if(ip != ibuf)\n                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);\n\n                if(op != obuf)\n                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                ibuf += m * AES_BLOCK_SIZE;\n                obuf += m * AES_BLOCK_SIZE;\n                nb -= m;\n            }\n        }\n\n        if(iv != ivp)\n            memcpy(iv, ivp, AES_BLOCK_SIZE);\n\n        return EXIT_SUCCESS;\n    }\n\n#endif\n\n#if !defined( ASSUME_VIA_ACE_PRESENT )\n# ifdef FAST_BUFFER_OPERATIONS\n    if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))\n        while(nb--)\n        {\n            lp32(iv)[0] ^= lp32(ibuf)[0];\n            lp32(iv)[1] ^= lp32(ibuf)[1];\n            lp32(iv)[2] ^= lp32(ibuf)[2];\n            lp32(iv)[3] ^= lp32(ibuf)[3];\n            if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                return EXIT_FAILURE;\n            memcpy(obuf, iv, AES_BLOCK_SIZE);\n            ibuf += AES_BLOCK_SIZE;\n            obuf += AES_BLOCK_SIZE;\n        }\n    else\n# endif\n        while(nb--)\n        {\n            iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1];\n            iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3];\n            iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5];\n            iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7];\n            iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9];\n            iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11];\n            iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13];\n            iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15];\n            if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                return EXIT_FAILURE;\n            memcpy(obuf, iv, AES_BLOCK_SIZE);\n            ibuf += AES_BLOCK_SIZE;\n            obuf += AES_BLOCK_SIZE;\n        }\n#endif\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, const aes_decrypt_ctx ctx[1])\n{   unsigned char tmp[AES_BLOCK_SIZE];\n    int nb = len >> 4;\n\n    if(len & (AES_BLOCK_SIZE - 1))\n        return EXIT_FAILURE;\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n    if(ctx->inf.b[1] == 0xff)\n    {   uint8_t *ksp = kd_adr(ctx), *ivp = iv;\n        aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);\n        via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);\n\n        if(ALIGN_OFFSET( ctx, 16 ))\n            return EXIT_FAILURE;\n\n        if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */\n        {\n            ivp = liv;\n            memcpy(liv, iv, AES_BLOCK_SIZE);\n        }\n\n        if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))\n        {\n            via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);\n        }\n        else\n        {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n            uint8_t *ip, *op;\n\n            while(nb)\n            {\n                int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);\n\n                ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                if(ip != ibuf)\n                    memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                via_cbc_op6(ksp, cwd, ip, op, m, ivp);\n\n                if(op != obuf)\n                    memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                ibuf += m * AES_BLOCK_SIZE;\n                obuf += m * AES_BLOCK_SIZE;\n                nb -= m;\n            }\n        }\n\n        if(iv != ivp)\n            memcpy(iv, ivp, AES_BLOCK_SIZE);\n\n        return EXIT_SUCCESS;\n    }\n#endif\n\n#if !defined( ASSUME_VIA_ACE_PRESENT )\n# ifdef FAST_BUFFER_OPERATIONS\n    if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))\n        while(nb--)\n        {\n            memcpy(tmp, ibuf, AES_BLOCK_SIZE);\n            if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)\n                return EXIT_FAILURE;\n            lp32(obuf)[0] ^= lp32(iv)[0];\n            lp32(obuf)[1] ^= lp32(iv)[1];\n            lp32(obuf)[2] ^= lp32(iv)[2];\n            lp32(obuf)[3] ^= lp32(iv)[3];\n            memcpy(iv, tmp, AES_BLOCK_SIZE);\n            ibuf += AES_BLOCK_SIZE;\n            obuf += AES_BLOCK_SIZE;\n        }\n    else\n# endif\n        while(nb--)\n        {\n            memcpy(tmp, ibuf, AES_BLOCK_SIZE);\n            if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)\n                return EXIT_FAILURE;\n            obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1];\n            obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3];\n            obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5];\n            obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7];\n            obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9];\n            obuf[10] ^= iv[10]; obuf[11] ^= iv[11];\n            obuf[12] ^= iv[12]; obuf[13] ^= iv[13];\n            obuf[14] ^= iv[14]; obuf[15] ^= iv[15];\n            memcpy(iv, tmp, AES_BLOCK_SIZE);\n            ibuf += AES_BLOCK_SIZE;\n            obuf += AES_BLOCK_SIZE;\n        }\n#endif\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])\n{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;\n\n    if(b_pos)           /* complete any partial block   */\n    {\n        while(b_pos < AES_BLOCK_SIZE && cnt < len)\n        {\n            *obuf++ = (iv[b_pos++] ^= *ibuf++);\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    if((nb = (len - cnt) >> 4) != 0)    /* process whole blocks */\n    {\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n        if(ctx->inf.b[1] == 0xff)\n        {   int m;\n            uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;\n            aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);\n            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);\n\n            if(ALIGN_OFFSET( ctx, 16 ))\n                return EXIT_FAILURE;\n\n            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */\n            {\n                ivp = liv;\n                memcpy(liv, iv, AES_BLOCK_SIZE);\n            }\n\n            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))\n            {\n                via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);\n                ibuf += nb * AES_BLOCK_SIZE;\n                obuf += nb * AES_BLOCK_SIZE;\n                cnt  += nb * AES_BLOCK_SIZE;\n            }\n            else    /* input, output or both are unaligned  */\n            {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n                uint8_t *ip, *op;\n\n                while(nb)\n                {\n                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;\n\n                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                    if(ip != ibuf)\n                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                    via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);\n\n                    if(op != obuf)\n                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                    ibuf += m * AES_BLOCK_SIZE;\n                    obuf += m * AES_BLOCK_SIZE;\n                    cnt  += m * AES_BLOCK_SIZE;\n                }\n            }\n\n            if(ivp != iv)\n                memcpy(iv, ivp, AES_BLOCK_SIZE);\n        }\n#else\n# ifdef FAST_BUFFER_OPERATIONS\n        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];\n                lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];\n                lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];\n                lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n        else\n# endif\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];\n                obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];\n                obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];\n                obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];\n                obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];\n                obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];\n                obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];\n                obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n#endif\n    }\n\n    while(cnt < len)\n    {\n        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n\n        while(cnt < len && b_pos < AES_BLOCK_SIZE)\n        {\n            *obuf++ = (iv[b_pos++] ^= *ibuf++);\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    ctx->inf.b[2] = (uint8_t)b_pos;\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])\n{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;\n\n    if(b_pos)           /* complete any partial block   */\n    {   uint8_t t;\n\n        while(b_pos < AES_BLOCK_SIZE && cnt < len)\n        {\n            t = *ibuf++;\n            *obuf++ = t ^ iv[b_pos];\n            iv[b_pos++] = t;\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    if((nb = (len - cnt) >> 4) != 0)    /* process whole blocks */\n    {\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n        if(ctx->inf.b[1] == 0xff)\n        {   int m;\n            uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;\n            aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);\n            via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);\n\n            if(ALIGN_OFFSET( ctx, 16 ))\n                return EXIT_FAILURE;\n\n            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */\n            {\n                ivp = liv;\n                memcpy(liv, iv, AES_BLOCK_SIZE);\n            }\n\n            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))\n            {\n                via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);\n                ibuf += nb * AES_BLOCK_SIZE;\n                obuf += nb * AES_BLOCK_SIZE;\n                cnt  += nb * AES_BLOCK_SIZE;\n            }\n            else    /* input, output or both are unaligned  */\n            {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n                uint8_t *ip, *op;\n\n                while(nb)\n                {\n                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;\n\n                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                    if(ip != ibuf)  /* input buffer is not aligned */\n                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                    via_cfb_op6(ksp, cwd, ip, op, m, ivp);\n\n                    if(op != obuf)  /* output buffer is not aligned */\n                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                    ibuf += m * AES_BLOCK_SIZE;\n                    obuf += m * AES_BLOCK_SIZE;\n                    cnt  += m * AES_BLOCK_SIZE;\n                }\n            }\n\n            if(ivp != iv)\n                memcpy(iv, ivp, AES_BLOCK_SIZE);\n        }\n#else\n# ifdef FAST_BUFFER_OPERATIONS\n        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {   uint32_t t;\n\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;\n                t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;\n                t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;\n                t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n        else\n# endif\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {   uint8_t t;\n\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;\n                t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;\n                t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;\n                t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;\n                t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;\n                t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;\n                t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;\n                t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;\n                t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;\n                t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;\n                t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;\n                t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;\n                t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;\n                t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;\n                t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;\n                t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n#endif\n    }\n\n    while(cnt < len)\n    {   uint8_t t;\n\n        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n\n        while(cnt < len && b_pos < AES_BLOCK_SIZE)\n        {\n            t = *ibuf++;\n            *obuf++ = t ^ iv[b_pos];\n            iv[b_pos++] = t;\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    ctx->inf.b[2] = (uint8_t)b_pos;\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,\n                    int len, unsigned char *iv, aes_encrypt_ctx ctx[1])\n{   int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;\n\n    if(b_pos)           /* complete any partial block   */\n    {\n        while(b_pos < AES_BLOCK_SIZE && cnt < len)\n        {\n            *obuf++ = iv[b_pos++] ^ *ibuf++;\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    if((nb = (len - cnt) >> 4) != 0)   /* process whole blocks */\n    {\n#if defined( USE_VIA_ACE_IF_PRESENT )\n\n        if(ctx->inf.b[1] == 0xff)\n        {   int m;\n            uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;\n            aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);\n            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);\n\n            if(ALIGN_OFFSET( ctx, 16 ))\n                return EXIT_FAILURE;\n\n            if(ALIGN_OFFSET( iv, 16 ))   /* ensure an aligned iv */\n            {\n                ivp = liv;\n                memcpy(liv, iv, AES_BLOCK_SIZE);\n            }\n\n            if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))\n            {\n                via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);\n                ibuf += nb * AES_BLOCK_SIZE;\n                obuf += nb * AES_BLOCK_SIZE;\n                cnt  += nb * AES_BLOCK_SIZE;\n            }\n            else    /* input, output or both are unaligned  */\n        {   aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);\n            uint8_t *ip, *op;\n\n                while(nb)\n                {\n                    m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;\n\n                    ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);\n                    op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);\n\n                    if(ip != ibuf)\n                        memcpy(buf, ibuf, m * AES_BLOCK_SIZE);\n\n                    via_ofb_op6(ksp, cwd, ip, op, m, ivp);\n\n                    if(op != obuf)\n                        memcpy(obuf, buf, m * AES_BLOCK_SIZE);\n\n                    ibuf += m * AES_BLOCK_SIZE;\n                    obuf += m * AES_BLOCK_SIZE;\n                    cnt  += m * AES_BLOCK_SIZE;\n                }\n            }\n\n            if(ivp != iv)\n                memcpy(iv, ivp, AES_BLOCK_SIZE);\n        }\n#else\n# ifdef FAST_BUFFER_OPERATIONS\n        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];\n                lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];\n                lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];\n                lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n        else\n# endif\n            while(cnt + AES_BLOCK_SIZE <= len)\n            {\n                assert(b_pos == 0);\n                if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n                    return EXIT_FAILURE;\n                obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];\n                obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];\n                obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];\n                obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];\n                obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];\n                obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];\n                obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];\n                obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n                cnt  += AES_BLOCK_SIZE;\n            }\n#endif\n    }\n\n    while(cnt < len)\n    {\n        if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n\n        while(cnt < len && b_pos < AES_BLOCK_SIZE)\n        {\n            *obuf++ = iv[b_pos++] ^ *ibuf++;\n            cnt++;\n        }\n\n        b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);\n    }\n\n    ctx->inf.b[2] = (uint8_t)b_pos;\n    return EXIT_SUCCESS;\n}\n\n#define BFR_LENGTH  (BFR_BLOCKS * AES_BLOCK_SIZE)\n\nAES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,\n            int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])\n{   unsigned char   *ip;\n    int             i, blen, b_pos = (int)(ctx->inf.b[2]);\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n    aligned_auto(uint8_t, buf, BFR_LENGTH, 16);\n    if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))\n        return EXIT_FAILURE;\n#else\n    uint8_t buf[BFR_LENGTH];\n#endif\n\n    if(b_pos)\n    {\n        memcpy(buf, cbuf, AES_BLOCK_SIZE);\n        if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n\n        while(b_pos < AES_BLOCK_SIZE && len)\n        {\n            *obuf++ = *ibuf++ ^ buf[b_pos++];\n            --len;\n        }\n\n        if(len)\n            ctr_inc(cbuf), b_pos = 0;\n    }\n\n    while(len)\n    {\n        blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;\n\n        for(i = 0, ip = buf; i < (blen >> 4); ++i)\n        {\n            memcpy(ip, cbuf, AES_BLOCK_SIZE);\n            ctr_inc(cbuf);\n            ip += AES_BLOCK_SIZE;\n        }\n\n        if(blen & (AES_BLOCK_SIZE - 1))\n            memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;\n\n#if defined( USE_VIA_ACE_IF_PRESENT )\n        if(ctx->inf.b[1] == 0xff)\n        {\n            via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);\n            via_ecb_op5((ctx->ks), cwd, buf, buf, i);\n        }\n        else\n#endif\n        if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)\n            return EXIT_FAILURE;\n\n        i = 0; ip = buf;\n# ifdef FAST_BUFFER_OPERATIONS\n        if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))\n            while(i + AES_BLOCK_SIZE <= blen)\n            {\n                lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];\n                lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];\n                lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];\n                lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];\n                i += AES_BLOCK_SIZE;\n                ip += AES_BLOCK_SIZE;\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n            }\n        else\n#endif\n            while(i + AES_BLOCK_SIZE <= blen)\n            {\n                obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1];\n                obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3];\n                obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5];\n                obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7];\n                obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9];\n                obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11];\n                obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13];\n                obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15];\n                i += AES_BLOCK_SIZE;\n                ip += AES_BLOCK_SIZE;\n                ibuf += AES_BLOCK_SIZE;\n                obuf += AES_BLOCK_SIZE;\n            }\n\n        while(i++ < blen)\n            *obuf++ = *ibuf++ ^ ip[b_pos++];\n    }\n\n    ctx->inf.b[2] = (uint8_t)b_pos;\n    return EXIT_SUCCESS;\n}\n\n#if defined(__cplusplus)\n}\n#endif\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aes_ni.c",
    "content": "/*\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 09/09/2014\n*/\n\n/* Oh, what sad times are these when passing code can say Ni at will to old \n   CPUs - pcg */\n\n#include \"aes_ni.h\"\n\n#if defined( USE_INTEL_AES_IF_PRESENT )\n\n#if defined(_MSC_VER)\n\n#include <intrin.h>\n#pragma intrinsic(__cpuid)\n#define INLINE  __inline\n\nINLINE int has_aes_ni( void )\t/* pcg */\n{\n\tstatic int test = -1;\n\tif(test < 0)\n\t{\n        int cpu_info[4];\n        __cpuid(cpu_info, 1);\n\t\ttest = cpu_info[2] & 0x02000000;\n\t}\n\treturn test;\n}\n\n#elif defined( __GNUC__ )\n\n#include <cpuid.h>\n#pragma GCC target (\"ssse3\")\n#pragma GCC target (\"sse4.1\")\n#pragma GCC target (\"aes\")\n#include <x86intrin.h>\n#define INLINE  static __inline\n\nINLINE int has_aes_ni( void )\t/* pcg */\n{\n    static int test = -1;\n    if(test < 0)\n    {\n        unsigned int a, b, c, d;\n        if(!__get_cpuid(1, &a, &b, &c, &d))\n            test = 0;\n        else\n            test = (c & 0x2000000);\n    }\n    return test;\n}\n\n#else\n#error AES New Instructions require Microsoft, Intel, GNU C, or CLANG\n#endif\n\nINLINE __m128i aes_128_assist(__m128i t1, __m128i t2)\n{\n\t__m128i t3;\n\tt2 = _mm_shuffle_epi32(t2, 0xff);\n\tt3 = _mm_slli_si128(t1, 0x4);\n\tt1 = _mm_xor_si128(t1, t3);\n\tt3 = _mm_slli_si128(t3, 0x4);\n\tt1 = _mm_xor_si128(t1, t3);\n\tt3 = _mm_slli_si128(t3, 0x4);\n\tt1 = _mm_xor_si128(t1, t3);\n\tt1 = _mm_xor_si128(t1, t2);\n\treturn t1;\n}\n\nAES_RETURN aes_ni(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{\n\t__m128i t1, t2;\n\t__m128i *ks = (__m128i*)cx->ks;\n\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(encrypt_key128)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tt1 = _mm_loadu_si128((__m128i*)key);\n\n\tks[0] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x1);\n\tt1 = aes_128_assist(t1, t2);\n\tks[1] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x2);\n\tt1 = aes_128_assist(t1, t2);\n\tks[2] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x4);\n\tt1 = aes_128_assist(t1, t2);\n\tks[3] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x8);\n\tt1 = aes_128_assist(t1, t2);\n\tks[4] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x10);\n\tt1 = aes_128_assist(t1, t2);\n\tks[5] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x20);\n\tt1 = aes_128_assist(t1, t2);\n\tks[6] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x40);\n\tt1 = aes_128_assist(t1, t2);\n\tks[7] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x80);\n\tt1 = aes_128_assist(t1, t2);\n\tks[8] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x1b);\n\tt1 = aes_128_assist(t1, t2);\n\tks[9] = t1;\n\n\tt2 = _mm_aeskeygenassist_si128(t1, 0x36);\n\tt1 = aes_128_assist(t1, t2);\n\tks[10] = t1;\n\n\tcx->inf.l = 0;\n\tcx->inf.b[0] = 10 * 16;\n\treturn EXIT_SUCCESS;\n}\n\nINLINE void aes_192_assist(__m128i* t1, __m128i * t2, __m128i * t3)\n{\n\t__m128i t4;\n\t*t2 = _mm_shuffle_epi32(*t2, 0x55);\n\tt4 = _mm_slli_si128(*t1, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\t*t1 = _mm_xor_si128(*t1, *t2);\n\t*t2 = _mm_shuffle_epi32(*t1, 0xff);\n\tt4 = _mm_slli_si128(*t3, 0x4);\n\t*t3 = _mm_xor_si128(*t3, t4);\n\t*t3 = _mm_xor_si128(*t3, *t2);\n}\n\nAES_RETURN aes_ni(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{\n\t__m128i t1, t2, t3;\n\t__m128i *ks = (__m128i*)cx->ks;\n\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(encrypt_key192)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tt1 = _mm_loadu_si128((__m128i*)key);\n\tt3 = _mm_loadu_si128((__m128i*)(key + 16));\n\n\tks[0] = t1;\n\tks[1] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x1);\n\taes_192_assist(&t1, &t2, &t3);\n\n\tks[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[1]), _mm_castsi128_pd(t1), 0));\n\tks[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x2);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[3] = t1;\n\tks[4] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x4);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[4]), _mm_castsi128_pd(t1), 0));\n\tks[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x8);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[6] = t1;\n\tks[7] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x10);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[7]), _mm_castsi128_pd(t1), 0));\n\tks[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x20);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[9] = t1;\n\tks[10] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x40);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[10]), _mm_castsi128_pd(t1), 0));\n\tks[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x80);\n\taes_192_assist(&t1, &t2, &t3);\n\tks[12] = t1;\n\n\tcx->inf.l = 0;\n\tcx->inf.b[0] = 12 * 16;\n\treturn EXIT_SUCCESS;\n}\n\nINLINE void aes_256_assist1(__m128i* t1, __m128i * t2)\n{\n\t__m128i t4;\n\t*t2 = _mm_shuffle_epi32(*t2, 0xff);\n\tt4 = _mm_slli_si128(*t1, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t1 = _mm_xor_si128(*t1, t4);\n\t*t1 = _mm_xor_si128(*t1, *t2);\n}\n\nINLINE void aes_256_assist2(__m128i* t1, __m128i * t3)\n{\n\t__m128i t2, t4;\n\tt4 = _mm_aeskeygenassist_si128(*t1, 0x0);\n\tt2 = _mm_shuffle_epi32(t4, 0xaa);\n\tt4 = _mm_slli_si128(*t3, 0x4);\n\t*t3 = _mm_xor_si128(*t3, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t3 = _mm_xor_si128(*t3, t4);\n\tt4 = _mm_slli_si128(t4, 0x4);\n\t*t3 = _mm_xor_si128(*t3, t4);\n\t*t3 = _mm_xor_si128(*t3, t2);\n}\n\nAES_RETURN aes_ni(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{\n\t__m128i t1, t2, t3;\n\t__m128i *ks = (__m128i*)cx->ks;\n\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(encrypt_key256)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tt1 = _mm_loadu_si128((__m128i*)key);\n\tt3 = _mm_loadu_si128((__m128i*)(key + 16));\n\n\tks[0] = t1;\n\tks[1] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x01);\n\taes_256_assist1(&t1, &t2);\n\tks[2] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[3] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x02);\n\taes_256_assist1(&t1, &t2);\n\tks[4] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[5] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x04);\n\taes_256_assist1(&t1, &t2);\n\tks[6] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[7] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x08);\n\taes_256_assist1(&t1, &t2);\n\tks[8] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[9] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x10);\n\taes_256_assist1(&t1, &t2);\n\tks[10] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[11] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x20);\n\taes_256_assist1(&t1, &t2);\n\tks[12] = t1;\n\taes_256_assist2(&t1, &t3);\n\tks[13] = t3;\n\n\tt2 = _mm_aeskeygenassist_si128(t3, 0x40);\n\taes_256_assist1(&t1, &t2);\n\tks[14] = t1;\n\n\tcx->inf.l = 0;\n\tcx->inf.b[0] = 14 * 16;\n\treturn EXIT_SUCCESS;\n}\n\nINLINE void enc_to_dec(aes_decrypt_ctx cx[1])\n{\n\t__m128i *ks = (__m128i*)cx->ks;\n\tint j;\n\n\tfor( j = 1 ; j < (cx->inf.b[0] >> 4) ; ++j )\n\t\tks[j] = _mm_aesimc_si128(ks[j]);\n}\n\nAES_RETURN aes_ni(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(decrypt_key128)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tif(aes_ni(encrypt_key128)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)\n\t{\n\t\tenc_to_dec(cx);\n\t\treturn EXIT_SUCCESS;\n\t}\n\telse\n\t\treturn EXIT_FAILURE;\n\n}\n\nAES_RETURN aes_ni(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(decrypt_key192)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tif(aes_ni(encrypt_key192)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)\n\t{\n\t\tenc_to_dec(cx);\n\t\treturn EXIT_SUCCESS;\n\t}\n\telse\n\t\treturn EXIT_FAILURE;\n}\n\nAES_RETURN aes_ni(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(decrypt_key256)(key, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tif(aes_ni(encrypt_key256)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)\n\t{\n\t\tenc_to_dec(cx);\n\t\treturn EXIT_SUCCESS;\n\t}\n\telse\n\t\treturn EXIT_FAILURE;\n}\n\nAES_RETURN aes_ni(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])\n{\n\t__m128i *key = (__m128i*)cx->ks, t;\n\n\tif(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)\n\t\treturn EXIT_FAILURE;\n\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(encrypt)(in, out, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tt = _mm_xor_si128(_mm_loadu_si128((__m128i*)in), *(__m128i*)key);\n\n\tswitch(cx->inf.b[0])\n\t{\n\tcase 14 * 16:\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\tcase 12 * 16:\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\tcase 10 * 16:\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenc_si128(t, *(__m128i*)++key);\n\t\tt = _mm_aesenclast_si128(t, *(__m128i*)++key);\n\t}\n\n\t_mm_storeu_si128(&((__m128i*)out)[0], t);\n\treturn EXIT_SUCCESS;\n}\n\nAES_RETURN aes_ni(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])\n{\n\t__m128i *key = (__m128i*)cx->ks + (cx->inf.b[0] >> 4), t;\n\n\tif(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)\n\t\treturn EXIT_FAILURE;\n\n\tif(!has_aes_ni())\n\t{\n\t\treturn aes_xi(decrypt)(in, out, cx);\n\t}\n\n\tassert( ALIGN_OFFSET( cx, 16 ) == 0 );\t/* pcg */\n\n\tt = _mm_xor_si128(_mm_loadu_si128((__m128i*)in), *(__m128i*)key);\n\n\tswitch(cx->inf.b[0])\n\t{\n\tcase 14 * 16:\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\tcase 12 * 16:\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\tcase 10 * 16:\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdec_si128(t, *(__m128i*)--key);\n\t\tt = _mm_aesdeclast_si128(t, *(__m128i*)--key);\n\t}\n\n\t_mm_storeu_si128((__m128i*)out, t);\n\treturn EXIT_SUCCESS;\n}\n\n#ifdef ADD_AESNI_MODE_CALLS\n#ifdef USE_AES_CONTEXT\n\nAES_RETURN aes_CBC_encrypt(const unsigned char *in,\n\tunsigned char *out,\n\tunsigned char ivec[16],\n\tunsigned long length,\n    const aes_encrypt_ctx cx[1])\n{\n\t__m128i feedback, data, *key = (__m128i*)cx->ks;\n\tint number_of_rounds = cx->inf.b[0] >> 4, j;\n    unsigned long i;\n    \n    if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)\n        return EXIT_FAILURE;\n\n    if(!has_aes_ni())\n    {\n        return aes_cbc_encrypt(in, out, length, ivec, cx);\n    }\n\n    if(length % 16)\n\t\tlength = length / 16 + 1;\n\telse length /= 16;\n\tfeedback = _mm_loadu_si128((__m128i*)ivec);\n\tfor(i = 0; i < length; i++)\n\t{\n\t\tdata = _mm_loadu_si128(&((__m128i*)in)[i]);\n\t\tfeedback = _mm_xor_si128(data, feedback);\n\t\tfeedback = _mm_xor_si128(feedback, ((__m128i*)key)[0]);\n\t\tfor(j = 1; j <number_of_rounds; j++)\n\t\t\tfeedback = _mm_aesenc_si128(feedback, ((__m128i*)key)[j]);\n\t\tfeedback = _mm_aesenclast_si128(feedback, ((__m128i*)key)[j]);\n\t\t_mm_storeu_si128(&((__m128i*)out)[i], feedback);\n\t}\n    return EXIT_SUCCESS;\n}\n\nAES_RETURN aes_CBC_decrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    const aes_decrypt_ctx cx[1])\n{\n    __m128i data, feedback, last_in, *key = (__m128i*)cx->ks;\n    int number_of_rounds = cx->inf.b[0] >> 4, j;\n    unsigned long i;\n\n    if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)\n        return EXIT_FAILURE;\n\n    if(!has_aes_ni())\n    {\n        return aes_cbc_decrypt(in, out, length, ivec, cx);\n    }\n\n    if(length % 16)\n        length = length / 16 + 1;\n    else length /= 16;\n    feedback = _mm_loadu_si128((__m128i*)ivec);\n    for(i = 0; i < length; i++)\n    {\n        last_in = _mm_loadu_si128(&((__m128i*)in)[i]);\n        data = _mm_xor_si128(last_in, ((__m128i*)key)[number_of_rounds]);\n        for(j = number_of_rounds - 1; j > 0; j--)\n        {\n            data = _mm_aesdec_si128(data, ((__m128i*)key)[j]);\n        }\n        data = _mm_aesdeclast_si128(data, ((__m128i*)key)[0]);\n        data = _mm_xor_si128(data, feedback);\n        _mm_storeu_si128(&((__m128i*)out)[i], data);\n        feedback = last_in;\n    }\n    return EXIT_SUCCESS;\n}\n\nstatic void ctr_inc(unsigned char *ctr_blk)\n{\n    uint32_t c;\n\n    c = *(uint32_t*)(ctr_blk + 8);\n    c++;\n    *(uint32_t*)(ctr_blk + 8) = c;\n\n    if(!c)\n        *(uint32_t*)(ctr_blk + 12) = *(uint32_t*)(ctr_blk + 12) + 1;\n}\n\nAES_RETURN AES_CTR_encrypt(const unsigned char *in,\n    unsigned char *out,\n    const unsigned char ivec[8],\n    const unsigned char nonce[4],\n    unsigned long length,\n    const aes_encrypt_ctx cx[1])\n{\n    __m128i ctr_block = { 0 }, *key = (__m128i*)cx->ks, tmp, ONE, BSWAP_EPI64;\n    int number_of_rounds = cx->inf.b[0] >> 4, j;\n    unsigned long i;\n\n    if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)\n        return EXIT_FAILURE;\n\n    if(!has_aes_ni())\n    {\n        unsigned char ctr_blk[16];\n        *(uint64_t*)ctr_blk = *(uint64_t*)ivec;\n        *(uint32_t*)(ctr_blk + 8) = *(uint32_t*)nonce;\n        return aes_ctr_crypt(in, out, length, (unsigned char*)ctr_blk, ctr_inc, cx);\n    }\n\n    if(length % 16)\n        length = length / 16 + 1;\n    else length /= 16;\n    ONE = _mm_set_epi32(0, 1, 0, 0);\n    BSWAP_EPI64 = _mm_setr_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);\n#ifdef _MSC_VER\n    ctr_block = _mm_insert_epi64(ctr_block, *(long long*)ivec, 1);\n#else\n    ctr_block = _mm_set_epi64(*(__m64*)ivec, *(__m64*)&ctr_block);\n#endif\n    ctr_block = _mm_insert_epi32(ctr_block, *(long*)nonce, 1);\n    ctr_block = _mm_srli_si128(ctr_block, 4);\n    ctr_block = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);\n    ctr_block = _mm_add_epi64(ctr_block, ONE);\n    for(i = 0; i < length; i++)\n    {\n        tmp = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);\n        ctr_block = _mm_add_epi64(ctr_block, ONE);\n        tmp = _mm_xor_si128(tmp, ((__m128i*)key)[0]);\n        for(j = 1; j <number_of_rounds; j++)\n        {\n            tmp = _mm_aesenc_si128(tmp, ((__m128i*)key)[j]);\n        };\n        tmp = _mm_aesenclast_si128(tmp, ((__m128i*)key)[j]);\n        tmp = _mm_xor_si128(tmp, _mm_loadu_si128(&((__m128i*)in)[i]));\n        _mm_storeu_si128(&((__m128i*)out)[i], tmp);\n    }\n    return EXIT_SUCCESS;\n}\n\n#else\n\nvoid aes_CBC_encrypt(const unsigned char *in,\n    unsigned char *out,\n    unsigned char ivec[16],\n    unsigned long length,\n    unsigned char *key,\n    int number_of_rounds)\n{\n    __m128i feedback, data;\n    unsigned long i;\n    int j;\n    if(length % 16)\n        length = length / 16 + 1;\n    else length /= 16;\n    feedback = _mm_loadu_si128((__m128i*)ivec);\n    for(i = 0; i < length; i++)\n    {\n        data = _mm_loadu_si128(&((__m128i*)in)[i]);\n        feedback = _mm_xor_si128(data, feedback);\n        feedback = _mm_xor_si128(feedback, ((__m128i*)key)[0]);\n        for(j = 1; j <number_of_rounds; j++)\n            feedback = _mm_aesenc_si128(feedback, ((__m128i*)key)[j]);\n        feedback = _mm_aesenclast_si128(feedback, ((__m128i*)key)[j]);\n        _mm_storeu_si128(&((__m128i*)out)[i], feedback);\n    }\n}\n\nvoid aes_CBC_decrypt(const unsigned char *in,\n\tunsigned char *out,\n\tunsigned char ivec[16],\n\tunsigned long length,\n\tunsigned char *key,\n\tint number_of_rounds)\n{\n\t__m128i data, feedback, last_in;\n\tunsigned long i;\n\tint j;\n\tif(length % 16)\n\t\tlength = length / 16 + 1;\n\telse length /= 16;\n\tfeedback = _mm_loadu_si128((__m128i*)ivec);\n\tfor(i = 0; i < length; i++)\n\t{\n\t\tlast_in = _mm_loadu_si128(&((__m128i*)in)[i]);\n\t\tdata = _mm_xor_si128(last_in, ((__m128i*)key)[0]);\n\t\tfor(j = 1; j <number_of_rounds; j++)\n\t\t{\n\t\t\tdata = _mm_aesdec_si128(data, ((__m128i*)key)[j]);\n\t\t}\n\t\tdata = _mm_aesdeclast_si128(data, ((__m128i*)key)[j]);\n\t\tdata = _mm_xor_si128(data, feedback);\n\t\t_mm_storeu_si128(&((__m128i*)out)[i], data);\n\t\tfeedback = last_in;\n\t}\n}\n\nvoid AES_CTR_encrypt(const unsigned char *in,\n\tunsigned char *out,\n\tconst unsigned char ivec[8],\n\tconst unsigned char nonce[4],\n\tunsigned long length,\n\tconst unsigned char *key,\n\tint number_of_rounds)\n{\n\t__m128i ctr_block = { 0 }, tmp, ONE, BSWAP_EPI64;\n\tunsigned long i;\n\tint j;\n\tif(length % 16)\n\t\tlength = length / 16 + 1;\n\telse length /= 16;\n\tONE = _mm_set_epi32(0, 1, 0, 0);\n\tBSWAP_EPI64 = _mm_setr_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);\n#ifdef _MSC_VER\n\tctr_block = _mm_insert_epi64(ctr_block, *(long long*)ivec, 1);\n#else\n\tctr_block = _mm_set_epi64(*(__m64*)ivec, *(__m64*)&ctr_block);\n#endif\n\tctr_block = _mm_insert_epi32(ctr_block, *(long*)nonce, 1);\n\tctr_block = _mm_srli_si128(ctr_block, 4);\n\tctr_block = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);\n\tctr_block = _mm_add_epi64(ctr_block, ONE);\n\tfor(i = 0; i < length; i++)\n\t{\n\t\ttmp = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);\n\t\tctr_block = _mm_add_epi64(ctr_block, ONE);\n\t\ttmp = _mm_xor_si128(tmp, ((__m128i*)key)[0]);\n\t\tfor(j = 1; j <number_of_rounds; j++)\n\t\t{\n\t\t\ttmp = _mm_aesenc_si128(tmp, ((__m128i*)key)[j]);\n\t\t};\n\t\ttmp = _mm_aesenclast_si128(tmp, ((__m128i*)key)[j]);\n\t\ttmp = _mm_xor_si128(tmp, _mm_loadu_si128(&((__m128i*)in)[i]));\n\t\t_mm_storeu_si128(&((__m128i*)out)[i], tmp);\n\t}\n}\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aes_ni.h",
    "content": "/*\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 13/11/2013\n*/\n\n#ifndef AES_NI_H\n#define AES_NI_H\n\n#define USE_AES_CONTEXT\n\n#include \"aesopt.h\"\n\n#if defined( USE_INTEL_AES_IF_PRESENT )\n\n/* map names in C code to make them internal ('name' -> 'aes_name_i') */\n#define aes_xi(x) aes_ ## x ## _i\n\n/* map names here to provide the external API ('name' -> 'aes_name') */\n#define aes_ni(x) aes_ ## x\n\nAES_RETURN aes_ni(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]);\nAES_RETURN aes_ni(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]);\nAES_RETURN aes_ni(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_ni(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]);\nAES_RETURN aes_ni(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]);\nAES_RETURN aes_ni(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]);\n\nAES_RETURN aes_ni(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);\nAES_RETURN aes_ni(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);\n\nAES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]);\nAES_RETURN aes_xi(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]);\nAES_RETURN aes_xi(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]);\n\nAES_RETURN aes_xi(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]);\nAES_RETURN aes_xi(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]);\nAES_RETURN aes_xi(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]);\n\nAES_RETURN aes_xi(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);\nAES_RETURN aes_xi(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aes_via_ace.h",
    "content": "/*\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n*/\n\n#ifndef AES_VIA_ACE_H\n#define AES_VIA_ACE_H\n\n#if defined( _MSC_VER )\n#  define INLINE  __inline\n#elif defined( __GNUC__ )\n#  define INLINE  static inline\n#else\n#  error VIA ACE requires Microsoft or GNU C\n#endif\n\n#define NEH_GENERATE    1\n#define NEH_LOAD        2\n#define NEH_HYBRID      3\n\n#define MAX_READ_ATTEMPTS   1000\n\n/* VIA Nehemiah RNG and ACE Feature Mask Values */\n\n#define NEH_CPU_IS_VIA      0x00000001\n#define NEH_CPU_READ        0x00000010\n#define NEH_CPU_MASK        0x00000011\n\n#define NEH_RNG_PRESENT     0x00000004\n#define NEH_RNG_ENABLED     0x00000008\n#define NEH_ACE_PRESENT     0x00000040\n#define NEH_ACE_ENABLED     0x00000080\n#define NEH_RNG_FLAGS       (NEH_RNG_PRESENT | NEH_RNG_ENABLED)\n#define NEH_ACE_FLAGS       (NEH_ACE_PRESENT | NEH_ACE_ENABLED)\n#define NEH_FLAGS_MASK      (NEH_RNG_FLAGS | NEH_ACE_FLAGS)\n\n/* VIA Nehemiah Advanced Cryptography Engine (ACE) Control Word Values  */\n\n#define NEH_GEN_KEY     0x00000000      /* generate key schedule        */\n#define NEH_LOAD_KEY    0x00000080      /* load schedule from memory    */\n#define NEH_ENCRYPT     0x00000000      /* encryption                   */\n#define NEH_DECRYPT     0x00000200      /* decryption                   */\n#define NEH_KEY128      0x00000000+0x0a /* 128 bit key                  */\n#define NEH_KEY192      0x00000400+0x0c /* 192 bit key                  */\n#define NEH_KEY256      0x00000800+0x0e /* 256 bit key                  */\n\n#define NEH_ENC_GEN     (NEH_ENCRYPT | NEH_GEN_KEY)\n#define NEH_DEC_GEN     (NEH_DECRYPT | NEH_GEN_KEY)\n#define NEH_ENC_LOAD    (NEH_ENCRYPT | NEH_LOAD_KEY)\n#define NEH_DEC_LOAD    (NEH_DECRYPT | NEH_LOAD_KEY)\n\n#define NEH_ENC_GEN_DATA {\\\n    NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\\\n    NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\\\n    NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 }\n\n#define NEH_ENC_LOAD_DATA {\\\n    NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\\\n    NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\\\n    NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }\n\n#define NEH_ENC_HYBRID_DATA {\\\n    NEH_ENC_GEN  | NEH_KEY128, 0, 0, 0,\\\n    NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\\\n    NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }\n\n#define NEH_DEC_GEN_DATA {\\\n    NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\\\n    NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\\\n    NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 }\n\n#define NEH_DEC_LOAD_DATA {\\\n    NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\\\n    NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\\\n    NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }\n\n#define NEH_DEC_HYBRID_DATA {\\\n    NEH_DEC_GEN  | NEH_KEY128, 0, 0, 0,\\\n    NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\\\n    NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }\n\n#define neh_enc_gen_key(x)  ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :      \\\n     (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256))\n\n#define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) :     \\\n     (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))\n\n#define neh_enc_hybrid_key(x)   ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :  \\\n     (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))\n\n#define neh_dec_gen_key(x)  ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :      \\\n     (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256))\n\n#define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) :     \\\n     (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))\n\n#define neh_dec_hybrid_key(x)   ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :  \\\n     (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 1200 )\n#define aligned_auto(type, name, no, stride)  __declspec(align(stride)) type name[no]\n#else\n#define aligned_auto(type, name, no, stride)                \\\n    unsigned char _##name[no * sizeof(type) + stride];      \\\n    type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride))\n#endif\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 1200 )\n#define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no]\n#elif defined( __GNUC__ )\n#define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride)))\n#else\n#define aligned_array(type, name, no, stride) type name[no]\n#endif\n\n/* VIA ACE codeword     */\n\nstatic unsigned char via_flags = 0;\n\n#if defined ( _MSC_VER ) && ( _MSC_VER > 800 )\n\n#define NEH_REKEY   __asm pushfd __asm popfd\n#define NEH_AES     __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7\n#define NEH_ECB     NEH_AES __asm _emit 0xc8\n#define NEH_CBC     NEH_AES __asm _emit 0xd0\n#define NEH_CFB     NEH_AES __asm _emit 0xe0\n#define NEH_OFB     NEH_AES __asm _emit 0xe8\n#define NEH_RNG     __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0\n\nINLINE int has_cpuid(void)\n{   char ret_value;\n    __asm\n    {   pushfd                  /* save EFLAGS register     */\n        mov     eax,[esp]       /* copy it to eax           */\n        mov     edx,0x00200000  /* CPUID bit position       */\n        xor     eax,edx         /* toggle the CPUID bit     */\n        push    eax             /* attempt to set EFLAGS to */\n        popfd                   /*     the new value        */\n        pushfd                  /* get the new EFLAGS value */\n        pop     eax             /*     into eax             */\n        xor     eax,[esp]       /* xor with original value  */\n        and     eax,edx         /* has CPUID bit changed?   */\n        setne   al              /* set to 1 if we have been */\n        mov     ret_value,al    /*     able to change it    */\n        popfd                   /* restore original EFLAGS  */\n    }\n    return (int)ret_value;\n}\n\nINLINE int is_via_cpu(void)\n{   char ret_value;\n    __asm\n    {   push    ebx\n        xor     eax,eax         /* use CPUID to get vendor  */\n        cpuid                   /* identity string          */\n        xor     eax,eax         /* is it \"CentaurHauls\" ?   */\n        sub     ebx,0x746e6543  /* 'Cent'                   */\n        or      eax,ebx\n        sub     edx,0x48727561  /* 'aurH'                   */\n        or      eax,edx\n        sub     ecx,0x736c7561  /* 'auls'                   */\n        or      eax,ecx\n        sete    al              /* set to 1 if it is VIA ID */\n        mov     dl,NEH_CPU_READ /* mark CPU type as read    */\n        or      dl,al           /* & store result in flags  */\n        mov     [via_flags],dl  /* set VIA detected flag    */\n        mov     ret_value,al    /*     able to change it    */\n        pop     ebx\n    }\n    return (int)ret_value;\n}\n\nINLINE int read_via_flags(void)\n{   char ret_value = 0;\n    __asm\n    {   mov     eax,0xC0000000  /* Centaur extended CPUID   */\n        cpuid\n        mov     edx,0xc0000001  /* >= 0xc0000001 if support */\n        cmp     eax,edx         /* for VIA extended feature */\n        jnae    no_rng          /*     flags is available   */\n        mov     eax,edx         /* read Centaur extended    */\n        cpuid                   /*     feature flags        */\n        mov     eax,NEH_FLAGS_MASK  /* mask out and save    */\n        and     eax,edx         /*  the RNG and ACE flags   */\n        or      [via_flags],al  /* present & enabled flags  */\n        mov     ret_value,al    /*     able to change it    */\nno_rng:\n    }\n    return (int)ret_value;\n}\n\nINLINE unsigned int via_rng_in(void *buf)\n{   char ret_value = 0x1f;\n    __asm\n    {   push    edi\n        mov     edi,buf         /* input buffer address     */\n        xor     edx,edx         /* try to fetch 8 bytes     */\n        NEH_RNG                 /* do RNG read operation    */\n        and     ret_value,al    /* count of bytes returned  */\n        pop     edi\n    }\n    return (int)ret_value;\n}\n\nINLINE void via_ecb_op5(\n            const void *k, const void *c, const void *s, void *d, int l)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        NEH_ECB\n        pop     ebx\n    }\n}\n\nINLINE void via_cbc_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        mov     eax, (v)\n        NEH_CBC\n        pop     ebx\n    }\n}\n\nINLINE void via_cbc_op7(\n        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        mov     eax, (v)\n        NEH_CBC\n        mov     esi, eax\n        mov     edi, (w)\n        movsd\n        movsd\n        movsd\n        movsd\n        pop     ebx\n    }\n}\n\nINLINE void via_cfb_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        mov     eax, (v)\n        NEH_CFB\n        pop     ebx\n    }\n}\n\nINLINE void via_cfb_op7(\n        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        mov     eax, (v)\n        NEH_CFB\n        mov     esi, eax\n        mov     edi, (w)\n        movsd\n        movsd\n        movsd\n        movsd\n        pop     ebx\n    }\n}\n\nINLINE void via_ofb_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{   __asm\n    {   push    ebx\n        NEH_REKEY\n        mov     ebx, (k)\n        mov     edx, (c)\n        mov     esi, (s)\n        mov     edi, (d)\n        mov     ecx, (l)\n        mov     eax, (v)\n        NEH_OFB\n        pop     ebx\n    }\n}\n\n#elif defined( __GNUC__ )\n\n#define NEH_REKEY   asm(\"pushfl\\n popfl\\n\\t\")\n#define NEH_ECB     asm(\".byte 0xf3, 0x0f, 0xa7, 0xc8\\n\\t\")\n#define NEH_CBC     asm(\".byte 0xf3, 0x0f, 0xa7, 0xd0\\n\\t\")\n#define NEH_CFB     asm(\".byte 0xf3, 0x0f, 0xa7, 0xe0\\n\\t\")\n#define NEH_OFB     asm(\".byte 0xf3, 0x0f, 0xa7, 0xe8\\n\\t\")\n#define NEH_RNG     asm(\".byte 0x0f, 0xa7, 0xc0\\n\\t\");\n\nINLINE int has_cpuid(void)\n{   int val;\n    asm(\"pushfl\\n\\t\");\n    asm(\"movl  0(%esp),%eax\\n\\t\");\n    asm(\"xor   $0x00200000,%eax\\n\\t\");\n    asm(\"pushl %eax\\n\\t\");\n    asm(\"popfl\\n\\t\");\n    asm(\"pushfl\\n\\t\");\n    asm(\"popl  %eax\\n\\t\");\n    asm(\"xorl  0(%esp),%edx\\n\\t\");\n    asm(\"andl  $0x00200000,%eax\\n\\t\");\n    asm(\"movl  %%eax,%0\\n\\t\" : \"=m\" (val));\n    asm(\"popfl\\n\\t\");\n    return val ? 1 : 0;\n}\n\nINLINE int is_via_cpu(void)\n{   int val;\n    asm(\"pushl %eax\\n\\t\");\n    asm(\"pushl %ebx\\n\\t\");\n    asm(\"pushl %ecx\\n\\t\");\n    asm(\"pushl %edx\\n\\t\");\n    asm(\"xorl %eax,%eax\\n\\t\");\n    asm(\"cpuid\\n\\t\");\n    asm(\"xorl %eax,%eax\\n\\t\");\n    asm(\"subl $0x746e6543,%ebx\\n\\t\");\n    asm(\"orl  %ebx,%eax\\n\\t\");\n    asm(\"subl $0x48727561,%edx\\n\\t\");\n    asm(\"orl  %edx,%eax\\n\\t\");\n    asm(\"subl $0x736c7561,%ecx\\n\\t\");\n    asm(\"orl  %ecx,%eax\\n\\t\");\n    asm(\"movl %%eax,%0\\n\\t\" : \"=m\" (val));\n    asm(\"popl %edx\\n\\t\");\n    asm(\"popl %ecx\\n\\t\");\n    asm(\"popl %ebx\\n\\t\");\n    asm(\"popl %eax\\n\\t\");\n    val = (val ? 0 : 1);\n    via_flags = (val | NEH_CPU_READ);\n    return val;\n}\n\nINLINE int read_via_flags(void)\n{   unsigned char   val;\n    asm(\"movl $0xc0000000,%eax\\n\\t\");\n    asm(\"cpuid\\n\\t\");\n    asm(\"movl $0xc0000001,%edx\\n\\t\");\n    asm(\"cmpl %edx,%eax\\n\\t\");\n    asm(\"setae %al\\n\\t\");\n    asm(\"movb %%al,%0\\n\\t\" : \"=m\" (val));\n    if(!val) return 0;\n    asm(\"movl $0xc0000001,%eax\\n\\t\");\n    asm(\"cpuid\\n\\t\");\n    asm(\"movb %%dl,%0\\n\\t\" : \"=m\" (val));\n    val &= NEH_FLAGS_MASK;\n    via_flags |= val;\n    return (int) val;\n}\n\nINLINE int via_rng_in(void *buf)\n{   int val;\n    asm(\"pushl %edi\\n\\t\");\n    asm(\"movl %0,%%edi\\n\\t\" : : \"m\" (buf));\n    asm(\"xorl %edx,%edx\\n\\t\");\n    NEH_RNG\n    asm(\"andl $0x0000001f,%eax\\n\\t\");\n    asm(\"movl %%eax,%0\\n\\t\" : \"=m\" (val));\n    asm(\"popl %edi\\n\\t\");\n    return val;\n}\n\nINLINE volatile  void via_ecb_op5(\n            const void *k, const void *c, const void *s, void *d, int l)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    NEH_ECB;\n    asm(\"popl %ebx\\n\\t\");\n}\n\nINLINE volatile  void via_cbc_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    asm(\"movl %0, %%eax\\n\\t\" : : \"m\" (v));\n    NEH_CBC;\n    asm(\"popl %ebx\\n\\t\");\n}\n\nINLINE volatile  void via_cbc_op7(\n        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    asm(\"movl %0, %%eax\\n\\t\" : : \"m\" (v));\n    NEH_CBC;\n    asm(\"movl %eax,%esi\\n\\t\");\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (w));\n    asm(\"movsl; movsl; movsl; movsl\\n\\t\");\n    asm(\"popl %ebx\\n\\t\");\n}\n\nINLINE volatile  void via_cfb_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    asm(\"movl %0, %%eax\\n\\t\" : : \"m\" (v));\n    NEH_CFB;\n    asm(\"popl %ebx\\n\\t\");\n}\n\nINLINE volatile  void via_cfb_op7(\n        const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    asm(\"movl %0, %%eax\\n\\t\" : : \"m\" (v));\n    NEH_CFB;\n    asm(\"movl %eax,%esi\\n\\t\");\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (w));\n    asm(\"movsl; movsl; movsl; movsl\\n\\t\");\n    asm(\"popl %ebx\\n\\t\");\n}\n\nINLINE volatile  void via_ofb_op6(\n            const void *k, const void *c, const void *s, void *d, int l, void *v)\n{\n    asm(\"pushl %ebx\\n\\t\");\n    NEH_REKEY;\n    asm(\"movl %0, %%ebx\\n\\t\" : : \"m\" (k));\n    asm(\"movl %0, %%edx\\n\\t\" : : \"m\" (c));\n    asm(\"movl %0, %%esi\\n\\t\" : : \"m\" (s));\n    asm(\"movl %0, %%edi\\n\\t\" : : \"m\" (d));\n    asm(\"movl %0, %%ecx\\n\\t\" : : \"m\" (l));\n    asm(\"movl %0, %%eax\\n\\t\" : : \"m\" (v));\n    NEH_OFB;\n    asm(\"popl %ebx\\n\\t\");\n}\n\n#else\n#error VIA ACE is not available with this compiler\n#endif\n\nINLINE int via_ace_test(void)\n{\n    return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_ACE_FLAGS) == NEH_ACE_FLAGS);\n}\n\n#define VIA_ACE_AVAILABLE   (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS)         \\\n    || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test())\n\nINLINE int via_rng_test(void)\n{\n    return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_RNG_FLAGS) == NEH_RNG_FLAGS);\n}\n\n#define VIA_RNG_AVAILABLE   (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS)         \\\n    || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test())\n\nINLINE int read_via_rng(void *buf, int count)\n{   int nbr, max_reads, lcnt = count;\n    unsigned char *p, *q;\n    aligned_auto(unsigned char, bp, 64, 16);\n\n    if(!VIA_RNG_AVAILABLE)\n        return 0;\n\n    do\n    {\n        max_reads = MAX_READ_ATTEMPTS;\n        do\n            nbr = via_rng_in(bp);\n        while\n            (nbr == 0 && --max_reads);\n\n        lcnt -= nbr;\n        p = (unsigned char*)buf; q = bp;\n        while(nbr--)\n            *p++ = *q++;\n    }\n    while\n        (lcnt && max_reads);\n\n    return count - lcnt;\n}\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aes_x86_v2.asm",
    "content": "\n; ---------------------------------------------------------------------------\n; Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n;\n; The redistribution and use of this software (with or without changes)\n; is allowed without the payment of fees or royalties provided that:\n;\n;   source code distributions include the above copyright notice, this\n;   list of conditions and the following disclaimer;\n;\n;   binary distributions include the above copyright notice, this list\n;   of conditions and the following disclaimer in their documentation.\n;\n; This software is provided 'as is' with no explicit or implied warranties\n; in respect of its operation, including, but not limited to, correctness\n; and fitness for purpose.\n; ---------------------------------------------------------------------------\n; Issue Date: 20/11/2013\n;\n; This code requires either ASM_X86_V2 or ASM_X86_V2C to be set in aesopt.h\n; and the same define to be set here as well. If AES_V2C is set this file\n; requires the C files aeskey.c and aestab.c for support.\n\n; An AES implementation for x86 processors using the YASM (or NASM) assembler.\n; This is a full assembler implementation covering encryption, decryption and\n; key scheduling. It uses 2k bytes of tables but its encryption and decryption\n; performance is very close to that obtained using large tables.  Key schedule\n; expansion is slower for both encryption and decryption but this is likely to\n; be offset by the much smaller load that this version places on the processor\n; cache. I acknowledge the contribution made by Daniel Bernstein to aspects of\n; the design of the AES round function used here.\n;\n; This code provides the standard AES block size (128 bits, 16 bytes) and the\n; three standard AES key sizes (128, 192 and 256 bits). It has the same call\n; interface as my C implementation. The ebx, esi, edi and ebp registers are\n; preserved across calls but eax, ecx and edx and the artihmetic status flags\n; are not.  Although this is a full assembler implementation, it can be used\n; in conjunction with my C code which provides faster key scheduling using\n; large tables. In this case aeskey.c should be compiled with ASM_X86_V2C\n; defined.  It is also important that the defines below match those used in the\n; C code.  This code uses the VC++ register saving conentions; if it is used\n; with another compiler, conventions for using and saving registers may need\n; to be checked (and calling conventions).  The YASM command line for the VC++\n; custom build step is:\n;\n;    yasm -Xvc -f win32 -D <Z> -o \"$(TargetDir)\\$(InputName).obj\" \"$(InputPath)\"\n;\n; For the cryptlib build this is (pcg):\n;\n;\tyasm -Xvc -f win32 -D ASM_X86_V2C -o aescryptx86.obj aes_x86_v2.asm\n;\n; where <Z> is ASM_X86_V2 or ASM_X86_V2C.  The calling intefaces are:\n;\n;     AES_RETURN aes_encrypt(const unsigned char in_blk[],\n;                   unsigned char out_blk[], const aes_encrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt(const unsigned char in_blk[],\n;                   unsigned char out_blk[], const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_encrypt_key<NNN>(const unsigned char key[],\n;                                            const aes_encrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt_key<NNN>(const unsigned char key[],\n;                                            const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_encrypt_key(const unsigned char key[],\n;                           unsigned int len, const aes_decrypt_ctx cx[1]);\n;\n;     AES_RETURN aes_decrypt_key(const unsigned char key[],\n;                           unsigned int len, const aes_decrypt_ctx cx[1]);\n;\n; where <NNN> is 128, 102 or 256.  In the last two calls the length can be in\n; either bits or bytes.\n\n; The DLL interface must use the _stdcall convention in which the number\n; of bytes of parameter space is added after an @ to the sutine's name.\n; We must also remove our parameters from the stack before return (see\n; the do_exit macro). Define DLL_EXPORT for the Dynamic Link Library version.\n\n;%define DLL_EXPORT\n\n; Comment in/out the following lines to obtain the desired subroutines. These\n; selections MUST match those in the C header file aes.h\n\n; The size of the code can be reduced by using functions for the encryption\n; and decryption rounds in place of macro expansion\n\n%define REDUCE_CODE_SIZE\n\n%define AES_128                 ; define if AES with 128 bit keys is needed\n%define AES_192                 ; define if AES with 192 bit keys is needed\n%define AES_256                 ; define if AES with 256 bit keys is needed\n%define AES_VAR                 ; define if a variable key size is needed\n%define ENCRYPTION              ; define if encryption is needed\n%define DECRYPTION              ; define if decryption is needed\n%define AES_REV_DKS             ; define if key decryption schedule is reversed\n\n%ifndef ASM_X86_V2C\n%define ENCRYPTION_KEY_SCHEDULE ; define if encryption key expansion is needed\n%define DECRYPTION_KEY_SCHEDULE ; define if decryption key expansion is needed\n%endif\n\n; The encryption key schedule has the following in memory layout where N is the\n; number of rounds (10, 12 or 14):\n;\n; lo: | input key (round 0)  |  ; each round is four 32-bit words\n;     | encryption round 1   |\n;     | encryption round 2   |\n;     ....\n;     | encryption round N-1 |\n; hi: | encryption round N   |\n;\n; The decryption key schedule is normally set up so that it has the same\n; layout as above by actually reversing the order of the encryption key\n; schedule in memory (this happens when AES_REV_DKS is set):\n;\n; lo: | decryption round 0   | =              | encryption round N   |\n;     | decryption round 1   | = INV_MIX_COL[ | encryption round N-1 | ]\n;     | decryption round 2   | = INV_MIX_COL[ | encryption round N-2 | ]\n;     ....                       ....\n;     | decryption round N-1 | = INV_MIX_COL[ | encryption round 1   | ]\n; hi: | decryption round N   | =              | input key (round 0)  |\n;\n; with rounds except the first and last modified using inv_mix_column()\n; But if AES_REV_DKS is NOT set the order of keys is left as it is for\n; encryption so that it has to be accessed in reverse when used for\n; decryption (although the inverse mix column modifications are done)\n;\n; lo: | decryption round 0   | =              | input key (round 0)  |\n;     | decryption round 1   | = INV_MIX_COL[ | encryption round 1   | ]\n;     | decryption round 2   | = INV_MIX_COL[ | encryption round 2   | ]\n;     ....                       ....\n;     | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ]\n; hi: | decryption round N   | =              | encryption round N   |\n;\n; This layout is faster when the assembler key scheduling provided here\n; is used.\n;\n; End of user defines\n\n    section .text align=32\n    \n%ifdef AES_VAR\n%ifndef AES_128\n%define AES_128\n%endif\n%ifndef AES_192\n%define AES_192\n%endif\n%ifndef AES_256\n%define AES_256\n%endif\n%endif\n\n%ifdef AES_VAR\n%define KS_LENGTH       60\n%elifdef AES_256\n%define KS_LENGTH       60\n%elifdef AES_192\n%define KS_LENGTH       52\n%else\n%define KS_LENGTH       44\n%endif\n\n%ifdef  REDUCE_CODE_SIZE\n    %macro mf_call 1\n        call %1\n    %endmacro\n%else\n    %macro mf_call 1\n        %1\n    %endmacro\n%endif\n\n; the DLL has to implement the _stdcall calling interface on return\n; In this case we have to take our parameters (3 4-byte pointers)\n; off the stack\n\n%define parms 12\n\n%macro  do_name 1-2 parms\n%ifndef DLL_EXPORT\n    global  %1\n%1:\n%else\n    global  %1@%2\n    export  %1@%2\n%1@%2:\n%endif\n%endmacro\n\n%macro  do_call 1-2 parms\n%ifndef DLL_EXPORT\n    call    %1\n    add     esp,%2\n%else\n    call    %1@%2\n%endif\n%endmacro\n\n%macro  do_exit  0-1 parms\n%ifdef DLL_EXPORT\n    ret %1\n%else\n    ret\n%endif\n%endmacro\n\n%ifndef ASM_X86_V2C\n    do_name _aes_init,0\n    do_exit 0\n%endif\n\n; finite field multiplies by {02}, {04} and {08}\n\n%define f2(x)   ((x<<1)^(((x>>7)&1)*0x11b))\n%define f4(x)   ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))\n%define f8(x)   ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))\n\n; finite field multiplies required in table generation\n\n%define f3(x)   (f2(x) ^ x)\n%define f9(x)   (f8(x) ^ x)\n%define fb(x)   (f8(x) ^ f2(x) ^ x)\n%define fd(x)   (f8(x) ^ f4(x) ^ x)\n%define fe(x)   (f8(x) ^ f4(x) ^ f2(x))\n\n%define etab_0(x)   [enc_tab+4+8*x]\n%define etab_1(x)   [enc_tab+3+8*x]\n%define etab_2(x)   [enc_tab+2+8*x]\n%define etab_3(x)   [enc_tab+1+8*x]\n%define etab_b(x)   byte [enc_tab+1+8*x] ; used with movzx for 0x000000xx\n%define etab_w(x)   word [enc_tab+8*x]   ; used with movzx for 0x0000xx00\n\n%define btab_0(x)   [enc_tab+6+8*x]\n%define btab_1(x)   [enc_tab+5+8*x]\n%define btab_2(x)   [enc_tab+4+8*x]\n%define btab_3(x)   [enc_tab+3+8*x]\n\n; ROUND FUNCTION.  Build column[2] on ESI and column[3] on EDI that have the\n; round keys pre-loaded. Build column[0] in EBP and column[1] in EBX.\n;\n; Input:\n;\n;   EAX     column[0]\n;   EBX     column[1]\n;   ECX     column[2]\n;   EDX     column[3]\n;   ESI     column key[round][2]\n;   EDI     column key[round][3]\n;   EBP     scratch\n;\n; Output:\n;\n;   EBP     column[0]   unkeyed\n;   EBX     column[1]   unkeyed\n;   ESI     column[2]   keyed\n;   EDI     column[3]   keyed\n;   EAX     scratch\n;   ECX     scratch\n;   EDX     scratch\n\n%macro rnd_fun 2\n\n    rol     ebx,16\n    %1      esi, cl, 0, ebp\n    %1      esi, dh, 1, ebp\n    %1      esi, bh, 3, ebp\n    %1      edi, dl, 0, ebp\n    %1      edi, ah, 1, ebp\n    %1      edi, bl, 2, ebp\n    %2      ebp, al, 0, ebp\n    shr     ebx,16\n    and     eax,0xffff0000\n    or      eax,ebx\n    shr     edx,16\n    %1      ebp, ah, 1, ebx\n    %1      ebp, dh, 3, ebx\n    %2      ebx, dl, 2, ebx\n    %1      ebx, ch, 1, edx\n    %1      ebx, al, 0, edx\n    shr     eax,16\n    shr     ecx,16\n    %1      ebp, cl, 2, edx\n    %1      edi, ch, 3, edx\n    %1      esi, al, 2, edx\n    %1      ebx, ah, 3, edx\n\n%endmacro\n\n;   Basic MOV and XOR Operations for normal rounds\n\n%macro  nr_xor  4\n    movzx   %4,%2\n    xor     %1,etab_%3(%4)\n%endmacro\n\n%macro  nr_mov  4\n    movzx   %4,%2\n    mov     %1,etab_%3(%4)\n%endmacro\n\n;   Basic MOV and XOR Operations for last round\n\n%if 1\n\n    %macro  lr_xor  4\n        movzx   %4,%2\n        movzx   %4,etab_b(%4)\n    %if %3 != 0\n        shl     %4,8*%3\n    %endif\n        xor     %1,%4\n    %endmacro\n\n    %macro  lr_mov  4\n        movzx   %4,%2\n        movzx   %1,etab_b(%4)\n    %if %3 != 0\n        shl     %1,8*%3\n    %endif\n    %endmacro\n\n%else       ; less effective but worth leaving as an option\n\n    %macro  lr_xor  4\n        movzx   %4,%2\n        mov     %4,btab_%3(%4)\n        and     %4,0x000000ff << 8 * %3\n        xor     %1,%4\n    %endmacro\n\n    %macro  lr_mov  4\n        movzx   %4,%2\n        mov     %1,btab_%3(%4)\n        and     %1,0x000000ff << 8 * %3\n    %endmacro\n\n%endif\n\n;   Apply S-Box to the 4 bytes in a 32-bit word and rotate byte positions\n\n%ifdef REDUCE_CODE_SIZE\n\n    global _ls_sub\n_ls_sub:                        ; ls_sub(t,n) = ls_box(t,n)\n    mov     ecx,[esp+8]\n    mov     eax,[esp+4]\n    shl     ecx,3\n    rol     eax,cl\n    xor     edx,edx\nl3s_col:\n    movzx   ecx,al              ; in      eax\n    movzx   ecx, etab_b(ecx)    ; out     eax\n    xor     edx,ecx             ; scratch ecx,edx\n    movzx   ecx,ah\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,8\n    xor     edx,ecx\n    shr     eax,16\n    movzx   ecx,al\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,16\n    xor     edx,ecx\n    movzx   ecx,ah\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,24\n    xor     edx,ecx\n    mov     eax,edx\n    ret\n\n%else\n\n%macro l3s_col 0\n\n    movzx   ecx,al              ; in      eax\n    movzx   ecx, etab_b(ecx)    ; out     eax\n    xor     edx,ecx             ; scratch ecx,edx\n    movzx   ecx,ah\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,8\n    xor     edx,ecx\n    shr     eax,16\n    movzx   ecx,al\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,16\n    xor     edx,ecx\n    movzx   ecx,ah\n    movzx   ecx, etab_b(ecx)\n    shl     ecx,24\n    xor     edx,ecx\n    mov     eax,edx\n\n%endmacro\n\n%endif\n    \n; offsets to parameters\n\nin_blk  equ     4   ; input byte array address parameter\nout_blk equ     8   ; output byte array address parameter\nctx     equ    12   ; AES context structure\nstk_spc equ    16   ; stack space\n\n%ifdef  ENCRYPTION\n\n%define ENCRYPTION_TABLE\n\n%macro _enc_round 0\n\n    add     ebp,16\n    mov     esi,[ebp+8]\n    mov     edi,[ebp+12]\n    push    ebp\n    rnd_fun nr_xor, nr_mov\n    mov     eax,ebp\n    pop     ebp\n    mov     ecx,esi\n    mov     edx,edi\n    xor     eax,[ebp]\n    xor     ebx,[ebp+4]\n\n%endmacro\n\n%ifdef REDUCE_CODE_SIZE\n\nenc_round:\n    _enc_round\n\tret\n\n%else\n\n%macro enc_round 0\n    _enc_round\n%endmacro\n\n%endif\n\n%macro enc_last_round 0\n\n    add     ebp,16\n    mov     esi,[ebp+8]\n    mov     edi,[ebp+12]\n    push    ebp\n    rnd_fun lr_xor, lr_mov\n    mov     eax,ebp\n    pop     ebp\n    xor     eax,[ebp]\n    xor     ebx,[ebp+4]\n\n%endmacro\n\n;   AES Encryption Subroutine\n\n    do_name _aes_encrypt,12\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n\n;   load the input block\n\n    mov     esi,[esp+in_blk+stk_spc] ; input pointer\n    mov     eax,[esi   ]\n    mov     ebx,[esi+ 4]\n    mov     ecx,[esi+ 8]\n    mov     edx,[esi+12]\n\n;   and xor in first key block\n\n    mov     ebp,[esp+ctx+stk_spc]    ; key pointer\n    movzx   edi,byte [ebp+4*KS_LENGTH]\n    xor     eax,[ebp   ]\n    xor     ebx,[ebp+ 4]\n    xor     ecx,[ebp+ 8]\n    xor     edx,[ebp+12]\n\n;   determine the number of rounds\n\n    cmp     edi,10*16\n    je      .3\n    cmp     edi,12*16\n    je      .2\n    cmp     edi,14*16\n    je      .1\n    mov     eax,-1\n    jmp     .5\n\n;   do the encryption rounds\n\n.1: mf_call enc_round\n    mf_call enc_round\n.2: mf_call enc_round\n    mf_call enc_round\n.3: mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    mf_call enc_round\n    enc_last_round\n\n;   output the block\n\n    mov     edx,[esp+out_blk+stk_spc]\n    mov     [edx   ],eax\n    mov     [edx+ 4],ebx\n    mov     [edx+ 8],esi\n    mov     [edx+12],edi\n    xor     eax,eax\n\n.5: pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    do_exit 12\n\n%endif\n\n%macro f_key 2\n\n    push    ecx\n    push    edx\n    mov     edx,esi\n    ror     eax,8\n    mf_call l3s_col\n    mov     esi,eax\n    pop     edx\n    pop     ecx\n    xor     esi,rc_val\n\n    mov     [ebp+%1*%2],esi\n    xor     edi,esi\n    mov     [ebp+%1*%2+4],edi\n    xor     ecx,edi\n    mov     [ebp+%1*%2+8],ecx\n    xor     edx,ecx\n    mov     [ebp+%1*%2+12],edx\n    mov     eax,edx\n\n%if %2 == 24\n\n%if %1 < 7\n    xor     eax,[ebp+%1*%2+16-%2]\n    mov     [ebp+%1*%2+16],eax\n    xor     eax,[ebp+%1*%2+20-%2]\n    mov     [ebp+%1*%2+20],eax\n%endif\n\n%elif %2 == 32\n\n%if %1 < 6\n    push    ecx\n    push    edx\n    mov     edx,[ebp+%1*%2+16-%2]\n    mf_call l3s_col\n    pop     edx\n    pop     ecx\n    mov     [ebp+%1*%2+16],eax\n    xor     eax,[ebp+%1*%2+20-%2]\n    mov     [ebp+%1*%2+20],eax\n    xor     eax,[ebp+%1*%2+24-%2]\n    mov     [ebp+%1*%2+24],eax\n    xor     eax,[ebp+%1*%2+28-%2]\n    mov     [ebp+%1*%2+28],eax\n%endif\n\n%endif\n\n%assign rc_val f2(rc_val)\n\n%endmacro\n\n%ifdef ENCRYPTION_KEY_SCHEDULE\n\n%ifdef  AES_128\n\n%ifndef ENCRYPTION_TABLE\n%define ENCRYPTION_TABLE\n%endif\n\n%assign rc_val  1\n\n    align   32\n    do_name _aes_encrypt_key128,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n\n    mov     ebp,[esp+24]\n    mov     [ebp+4*KS_LENGTH],dword 10*16\n    mov     ebx,[esp+20]\n\n    mov     esi,[ebx]\n    mov     [ebp],esi\n    mov     edi,[ebx+4]\n    mov     [ebp+4],edi\n    mov     ecx,[ebx+8]\n    mov     [ebp+8],ecx\n    mov     edx,[ebx+12]\n    mov     [ebp+12],edx\n    add     ebp,16\n    mov     eax,edx\n\n    f_key   0,16        ; 11 * 4 = 44 unsigned longs\n    f_key   1,16        ; 4 + 4 * 10 generated = 44\n    f_key   2,16\n    f_key   3,16\n    f_key   4,16\n    f_key   5,16\n    f_key   6,16\n    f_key   7,16\n    f_key   8,16\n    f_key   9,16\n\n    pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    xor     eax,eax\n    do_exit  8\n\n%endif\n\n%ifdef  AES_192\n\n%ifndef ENCRYPTION_TABLE\n%define ENCRYPTION_TABLE\n%endif\n\n%assign rc_val  1\n\n    align   32\n    do_name _aes_encrypt_key192,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n\n    mov     ebp,[esp+24]\n    mov     [ebp+4*KS_LENGTH],dword 12 * 16\n    mov     ebx,[esp+20]\n\n    mov     esi,[ebx]\n    mov     [ebp],esi\n    mov     edi,[ebx+4]\n    mov     [ebp+4],edi\n    mov     ecx,[ebx+8]\n    mov     [ebp+8],ecx\n    mov     edx,[ebx+12]\n    mov     [ebp+12],edx\n    mov     eax,[ebx+16]\n    mov     [ebp+16],eax\n    mov     eax,[ebx+20]\n    mov     [ebp+20],eax\n    add     ebp,24\n\n    f_key   0,24        ; 13 * 4 = 52 unsigned longs\n    f_key   1,24        ; 6 + 6 * 8 generated = 54\n    f_key   2,24\n    f_key   3,24\n    f_key   4,24\n    f_key   5,24\n    f_key   6,24\n    f_key   7,24\n\n    pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    xor     eax,eax\n    do_exit  8\n\n%endif\n\n%ifdef  AES_256\n\n%ifndef ENCRYPTION_TABLE\n%define ENCRYPTION_TABLE\n%endif\n\n%assign rc_val  1\n\n    align   32\n    do_name _aes_encrypt_key256,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n\n    mov     ebp,[esp+24]\n    mov     [ebp+4*KS_LENGTH],dword 14 * 16\n    mov     ebx,[esp+20]\n\n    mov     esi,[ebx]\n    mov     [ebp],esi\n    mov     edi,[ebx+4]\n    mov     [ebp+4],edi\n    mov     ecx,[ebx+8]\n    mov     [ebp+8],ecx\n    mov     edx,[ebx+12]\n    mov     [ebp+12],edx\n    mov     eax,[ebx+16]\n    mov     [ebp+16],eax\n    mov     eax,[ebx+20]\n    mov     [ebp+20],eax\n    mov     eax,[ebx+24]\n    mov     [ebp+24],eax\n    mov     eax,[ebx+28]\n    mov     [ebp+28],eax\n    add     ebp,32\n\n    f_key   0,32        ; 15 * 4 = 60 unsigned longs\n    f_key   1,32        ; 8 + 8 * 7 generated = 64\n    f_key   2,32\n    f_key   3,32\n    f_key   4,32\n    f_key   5,32\n    f_key   6,32\n\n    pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    xor     eax,eax\n    do_exit  8\n\n%endif\n\n%ifdef  AES_VAR\n\n%ifndef ENCRYPTION_TABLE\n%define ENCRYPTION_TABLE\n%endif\n\n    align   32\n    do_name _aes_encrypt_key,12\n\n    mov     ecx,[esp+4]\n    mov     eax,[esp+8]\n    mov     edx,[esp+12]\n    push    edx\n    push    ecx\n\n    cmp     eax,16\n    je      .1\n    cmp     eax,128\n    je      .1\n\n    cmp     eax,24\n    je      .2\n    cmp     eax,192\n    je      .2\n\n    cmp     eax,32\n    je      .3\n    cmp     eax,256\n    je      .3\n    mov     eax,-1\n    add     esp,8\n    do_exit 12\n\n.1: do_call _aes_encrypt_key128,8\n    do_exit 12\n.2: do_call _aes_encrypt_key192,8\n    do_exit 12\n.3: do_call _aes_encrypt_key256,8\n    do_exit 12\n\n%endif\n\n%endif\n\n%ifdef  DECRYPTION\n\n%define DECRYPTION_TABLE\n\n%define dtab_0(x)   [dec_tab+  8*x]\n%define dtab_1(x)   [dec_tab+3+8*x]\n%define dtab_2(x)   [dec_tab+2+8*x]\n%define dtab_3(x)   [dec_tab+1+8*x]\n%define dtab_x(x)   byte [dec_tab+7+8*x]\n\n%macro irn_fun 2\n\n    rol     eax,16\n    %1      esi, cl, 0, ebp\n    %1      esi, bh, 1, ebp\n    %1      esi, al, 2, ebp\n    %1      edi, dl, 0, ebp\n    %1      edi, ch, 1, ebp\n    %1      edi, ah, 3, ebp\n    %2      ebp, bl, 0, ebp\n    shr     eax,16\n    and     ebx,0xffff0000\n    or      ebx,eax\n    shr     ecx,16\n    %1      ebp, bh, 1, eax\n    %1      ebp, ch, 3, eax\n    %2      eax, cl, 2, ecx\n    %1      eax, bl, 0, ecx\n    %1      eax, dh, 1, ecx\n    shr     ebx,16\n    shr     edx,16\n    %1      esi, dh, 3, ecx\n    %1      ebp, dl, 2, ecx\n    %1      eax, bh, 3, ecx\n    %1      edi, bl, 2, ecx\n\n%endmacro\n\n; Basic MOV and XOR Operations for normal rounds\n\n%macro  ni_xor  4\n    movzx   %4,%2\n    xor     %1,dtab_%3(%4)\n%endmacro\n\n%macro  ni_mov  4\n    movzx   %4,%2\n    mov     %1,dtab_%3(%4)\n%endmacro\n\n; Basic MOV and XOR Operations for last round\n\n%macro  li_xor  4\n    movzx   %4,%2\n    movzx   %4,dtab_x(%4)\n%if %3 != 0\n    shl     %4,8*%3\n%endif\n    xor     %1,%4\n%endmacro\n\n%macro  li_mov  4\n    movzx   %4,%2\n    movzx   %1,dtab_x(%4)\n%if %3 != 0\n    shl     %1,8*%3\n%endif\n%endmacro\n\n%macro _dec_round 0\n\n%ifdef AES_REV_DKS\n    add     ebp,16\n%else\n    sub     ebp,16\n%endif\n    mov     esi,[ebp+8]\n    mov     edi,[ebp+12]\n    push    ebp\n    irn_fun ni_xor, ni_mov\n    mov     ebx,ebp\n    pop     ebp\n    mov     ecx,esi\n    mov     edx,edi\n    xor     eax,[ebp]\n    xor     ebx,[ebp+4]\n\n%endmacro\n\n%ifdef REDUCE_CODE_SIZE\n\n    section .text align=32\ndec_round:\n\t_dec_round\n\tret\n\n%else\n\n%macro dec_round 0\n\t_dec_round\n%endmacro\n\n%endif\n\n%macro dec_last_round 0\n\n%ifdef AES_REV_DKS\n    add     ebp,16\n%else\n    sub     ebp,16\n%endif\n    mov     esi,[ebp+8]\n    mov     edi,[ebp+12]\n    push    ebp\n    irn_fun li_xor, li_mov\n    mov     ebx,ebp\n    pop     ebp\n    xor     eax,[ebp]\n    xor     ebx,[ebp+4]\n\n%endmacro\n\n; AES Decryption Subroutine\n\n    do_name _aes_decrypt,12\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n\n;   load the input block\n\n    mov     esi,[esp+in_blk+stk_spc] ; input pointer\n    mov     eax,[esi   ]\n    mov     ebx,[esi+ 4]\n    mov     ecx,[esi+ 8]\n    mov     edx,[esi+12]\n    lea     esi,[esi+16]\n\n;   xor in the first round key\n\n    mov     ebp,[esp+ctx+stk_spc]    ; key pointer\n    movzx   edi,byte[ebp+4*KS_LENGTH]\n%ifndef  AES_REV_DKS        ; if decryption key schedule is not reversed\n    lea     ebp,[ebp+edi]   ; we have to access it from the top down\n%endif\n    xor     eax,[ebp   ]    ; key schedule\n    xor     ebx,[ebp+ 4]\n    xor     ecx,[ebp+ 8]\n    xor     edx,[ebp+12]\n\n;   determine the number of rounds\n\n    cmp     edi,10*16\n    je      .3\n    cmp     edi,12*16\n    je      .2\n    cmp     edi,14*16\n    je      .1\n    mov     eax,-1\n    jmp     .5\n\n;   perform the decryption rounds\n\n.1: mf_call dec_round\n    mf_call dec_round\n.2: mf_call dec_round\n    mf_call dec_round\n.3: mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    mf_call dec_round\n    dec_last_round\n\n;   output the block\n\n    mov     ebp,[esp+out_blk+stk_spc]\n    mov     [ebp   ],eax\n    mov     [ebp+ 4],ebx\n    mov     [ebp+ 8],esi\n    mov     [ebp+12],edi\n    xor     eax,eax\n\n.5: pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    do_exit 12\n\n%endif\n\n%ifdef REDUCE_CODE_SIZE\n\n    global _im_sub\n_im_sub:\n    mov     edx,[esp+4]\ninv_mix_col:\n    movzx   ecx,dl          ; input  eax, edx\n    movzx   ecx,etab_b(ecx) ; output eax\n    mov     eax,dtab_0(ecx) ; used   ecx\n    movzx   ecx,dh\n    shr     edx,16\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_1(ecx)\n    movzx   ecx,dl\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_2(ecx)\n    movzx   ecx,dh\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_3(ecx)\n    ret\n\n%else\n\n%macro  inv_mix_col 0   \n\n    movzx   ecx,dl          ; input  eax, edx\n    movzx   ecx,etab_b(ecx) ; output eax\n    mov     eax,dtab_0(ecx) ; used   ecx\n    movzx   ecx,dh\n    shr     edx,16\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_1(ecx)\n    movzx   ecx,dl\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_2(ecx)\n    movzx   ecx,dh\n    movzx   ecx,etab_b(ecx)\n    xor     eax,dtab_3(ecx)\n\n%endmacro\n\n%endif\n\n%ifdef DECRYPTION_KEY_SCHEDULE\n\n%ifdef AES_128\n\n%ifndef DECRYPTION_TABLE\n%define DECRYPTION_TABLE\n%endif\n\n    align   32\n    do_name _aes_decrypt_key128,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n    \n    mov     eax,[esp+24]    ; context\n    mov     edx,[esp+20]    ; key\n    push    eax\n    push    edx\n    do_call _aes_encrypt_key128,8   ; generate expanded encryption key\n    mov     eax,10*16\n    mov     esi,[esp+24]    ; pointer to first round key\n    lea     edi,[esi+eax]   ; pointer to last round key\n    add     esi,32\n                            ; the inverse mix column transformation\n    mov     edx,[esi-16]    ; needs to be applied to all round keys\n    mf_call inv_mix_col     ; except first and last. Hence start by\n    mov     [esi-16],eax    ; transforming the four sub-keys in the\n    mov     edx,[esi-12]    ; second round key\n    mf_call inv_mix_col\n    mov     [esi-12],eax    ; transformations for subsequent rounds\n    mov     edx,[esi-8]     ; can then be made more efficient by\n    mf_call inv_mix_col     ; noting that for three of the four sub-keys\n    mov     [esi-8],eax     ; in the encryption round key ek[r]:\n    mov     edx,[esi-4]     ;\n    mf_call inv_mix_col     ;   ek[r][n] = ek[r][n-1] ^ ek[r-1][n]\n    mov     [esi-4],eax     ;\n                            ; where n is 1..3. Hence the corresponding\n.0: mov     edx,[esi]       ; subkeys in the decryption round key dk[r]\n    mf_call inv_mix_col     ; also obey since inv_mix_col is linear in\n    mov     [esi],eax       ; GF(256):\n    xor     eax,[esi-12]    ;\n    mov     [esi+4],eax     ;   dk[r][n] = dk[r][n-1] ^ dk[r-1][n]\n    xor     eax,[esi-8]     ;\n    mov     [esi+8],eax     ; So we only need one inverse mix column\n    xor     eax,[esi-4]     ; operation (n = 0) for each four word cycle\n    mov     [esi+12],eax    ; in the expanded key.\n    add     esi,16\n    cmp     edi,esi\n    jg      .0\n    jmp     dec_end\n\n%endif\n\n%ifdef AES_192\n\n%ifndef DECRYPTION_TABLE\n%define DECRYPTION_TABLE\n%endif\n\n    align   32\n    do_name _aes_decrypt_key192,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n    \n    mov     eax,[esp+24]    ; context\n    mov     edx,[esp+20]    ; key\n    push    eax\n    push    edx\n    do_call _aes_encrypt_key192,8   ; generate expanded encryption key\n    mov     eax,12*16\n    mov     esi,[esp+24]    ; first round key\n    lea     edi,[esi+eax]   ; last round key\n    add     esi,48          ; the first 6 words are the key, of\n                            ; which the top 2 words are part of\n    mov     edx,[esi-32]    ; the second round key and hence\n    mf_call inv_mix_col     ; need to be modified. After this we\n    mov     [esi-32],eax    ; need to do a further six values prior\n    mov     edx,[esi-28]    ; to using a more efficient technique\n    mf_call inv_mix_col     ; based on:\n    mov     [esi-28],eax    ;\n                            ; dk[r][n] = dk[r][n-1] ^ dk[r-1][n]\n    mov     edx,[esi-24]    ;\n    mf_call inv_mix_col     ; for n = 1 .. 5 where the key expansion\n    mov     [esi-24],eax    ; cycle is now 6 words long\n    mov     edx,[esi-20]\n    mf_call inv_mix_col\n    mov     [esi-20],eax\n    mov     edx,[esi-16]\n    mf_call inv_mix_col\n    mov     [esi-16],eax\n    mov     edx,[esi-12]\n    mf_call inv_mix_col\n    mov     [esi-12],eax\n    mov     edx,[esi-8]\n    mf_call inv_mix_col\n    mov     [esi-8],eax\n    mov     edx,[esi-4]\n    mf_call inv_mix_col\n    mov     [esi-4],eax\n\n.0: mov     edx,[esi]       ; the expanded key is 13 * 4 = 44 32-bit words\n    mf_call inv_mix_col     ; of which 11 * 4 = 44 have to be modified\n    mov     [esi],eax       ; using inv_mix_col.  We have already done 8\n    xor     eax,[esi-20]    ; of these so 36 are left - hence we need\n    mov     [esi+4],eax     ; exactly 6 loops of six here\n    xor     eax,[esi-16]\n    mov     [esi+8],eax\n    xor     eax,[esi-12]\n    mov     [esi+12],eax\n    xor     eax,[esi-8]\n    mov     [esi+16],eax\n    xor     eax,[esi-4]\n    mov     [esi+20],eax\n    add     esi,24\n    cmp     edi,esi\n    jg      .0\n    jmp     dec_end\n\n%endif\n\n%ifdef AES_256\n\n%ifndef DECRYPTION_TABLE\n%define DECRYPTION_TABLE\n%endif\n\n    align   32\n    do_name _aes_decrypt_key256,8\n    push    ebp\n    push    ebx\n    push    esi\n    push    edi\n    \n    mov     eax,[esp+24]\n    mov     edx,[esp+20]\n    push    eax\n    push    edx\n    do_call _aes_encrypt_key256,8   ; generate expanded encryption key\n    mov     eax,14*16\n    mov     esi,[esp+24]\n    lea     edi,[esi+eax]\n    add     esi,64\n\n    mov     edx,[esi-48]    ; the primary key is 8 words, of which\n    mf_call inv_mix_col     ; the top four require modification\n    mov     [esi-48],eax\n    mov     edx,[esi-44]\n    mf_call inv_mix_col\n    mov     [esi-44],eax\n    mov     edx,[esi-40]\n    mf_call inv_mix_col\n    mov     [esi-40],eax\n    mov     edx,[esi-36]\n    mf_call inv_mix_col\n    mov     [esi-36],eax\n\n    mov     edx,[esi-32]    ; the encryption key expansion cycle is\n    mf_call inv_mix_col     ; now eight words long so we need to\n    mov     [esi-32],eax    ; start by doing one complete block\n    mov     edx,[esi-28]\n    mf_call inv_mix_col\n    mov     [esi-28],eax\n    mov     edx,[esi-24]\n    mf_call inv_mix_col\n    mov     [esi-24],eax\n    mov     edx,[esi-20]\n    mf_call inv_mix_col\n    mov     [esi-20],eax\n    mov     edx,[esi-16]\n    mf_call inv_mix_col\n    mov     [esi-16],eax\n    mov     edx,[esi-12]\n    mf_call inv_mix_col\n    mov     [esi-12],eax\n    mov     edx,[esi-8]\n    mf_call inv_mix_col\n    mov     [esi-8],eax\n    mov     edx,[esi-4]\n    mf_call inv_mix_col\n    mov     [esi-4],eax\n\n.0: mov     edx,[esi]       ; we can now speed up the remaining\n    mf_call inv_mix_col     ; rounds by using the technique\n    mov     [esi],eax       ; outlined earlier.  But note that\n    xor     eax,[esi-28]    ; there is one extra inverse mix\n    mov     [esi+4],eax     ; column operation as the 256 bit\n    xor     eax,[esi-24]    ; key has an extra non-linear step\n    mov     [esi+8],eax     ; for the midway element.\n    xor     eax,[esi-20]\n    mov     [esi+12],eax    ; the expanded key is 15 * 4 = 60\n    mov     edx,[esi+16]    ; 32-bit words of which 52 need to\n    mf_call inv_mix_col     ; be modified.  We have already done\n    mov     [esi+16],eax    ; 12 so 40 are left - which means\n    xor     eax,[esi-12]    ; that we need exactly 5 loops of 8\n    mov     [esi+20],eax\n    xor     eax,[esi-8]\n    mov     [esi+24],eax\n    xor     eax,[esi-4]\n    mov     [esi+28],eax\n    add     esi,32\n    cmp     edi,esi\n    jg      .0\n\n%endif\n\ndec_end:\n\n%ifdef AES_REV_DKS\n\n    mov     esi,[esp+24]    ; this reverses the order of the\n.1: mov     eax,[esi]       ; round keys if required\n    mov     ebx,[esi+4]\n    mov     ebp,[edi]\n    mov     edx,[edi+4]\n    mov     [esi],ebp\n    mov     [esi+4],edx\n    mov     [edi],eax\n    mov     [edi+4],ebx\n\n    mov     eax,[esi+8]\n    mov     ebx,[esi+12]\n    mov     ebp,[edi+8]\n    mov     edx,[edi+12]\n    mov     [esi+8],ebp\n    mov     [esi+12],edx\n    mov     [edi+8],eax\n    mov     [edi+12],ebx\n\n    add     esi,16\n    sub     edi,16\n    cmp     edi,esi\n    jg      .1\n\n%endif\n\n    pop     edi\n    pop     esi\n    pop     ebx\n    pop     ebp\n    xor     eax,eax\n    do_exit  8\n\n%ifdef AES_VAR\n\n    align   32\n    do_name _aes_decrypt_key,12\n\n    mov     ecx,[esp+4]\n    mov     eax,[esp+8]\n    mov     edx,[esp+12]\n    push    edx\n    push    ecx\n\n    cmp     eax,16\n    je      .1\n    cmp     eax,128\n    je      .1\n\n    cmp     eax,24\n    je      .2\n    cmp     eax,192\n    je      .2\n\n    cmp     eax,32\n    je      .3\n    cmp     eax,256\n    je      .3\n    mov     eax,-1\n    add     esp,8\n    do_exit 12\n\n.1: do_call _aes_decrypt_key128,8\n    do_exit 12\n.2: do_call _aes_decrypt_key192,8\n    do_exit 12\n.3: do_call _aes_decrypt_key256,8\n    do_exit 12\n\n%endif\n\n%endif\n\n    section .data align=32\n\n%ifdef ENCRYPTION_TABLE\n\n; S-box data - 256 entries\n\n%define u8(x)   0, x, x, f3(x), f2(x), x, x, f3(x)\n\nenc_tab:\n    db  u8(0x63),u8(0x7c),u8(0x77),u8(0x7b),u8(0xf2),u8(0x6b),u8(0x6f),u8(0xc5)\n    db  u8(0x30),u8(0x01),u8(0x67),u8(0x2b),u8(0xfe),u8(0xd7),u8(0xab),u8(0x76)\n    db  u8(0xca),u8(0x82),u8(0xc9),u8(0x7d),u8(0xfa),u8(0x59),u8(0x47),u8(0xf0)\n    db  u8(0xad),u8(0xd4),u8(0xa2),u8(0xaf),u8(0x9c),u8(0xa4),u8(0x72),u8(0xc0)\n    db  u8(0xb7),u8(0xfd),u8(0x93),u8(0x26),u8(0x36),u8(0x3f),u8(0xf7),u8(0xcc)\n    db  u8(0x34),u8(0xa5),u8(0xe5),u8(0xf1),u8(0x71),u8(0xd8),u8(0x31),u8(0x15)\n    db  u8(0x04),u8(0xc7),u8(0x23),u8(0xc3),u8(0x18),u8(0x96),u8(0x05),u8(0x9a)\n    db  u8(0x07),u8(0x12),u8(0x80),u8(0xe2),u8(0xeb),u8(0x27),u8(0xb2),u8(0x75)\n    db  u8(0x09),u8(0x83),u8(0x2c),u8(0x1a),u8(0x1b),u8(0x6e),u8(0x5a),u8(0xa0)\n    db  u8(0x52),u8(0x3b),u8(0xd6),u8(0xb3),u8(0x29),u8(0xe3),u8(0x2f),u8(0x84)\n    db  u8(0x53),u8(0xd1),u8(0x00),u8(0xed),u8(0x20),u8(0xfc),u8(0xb1),u8(0x5b)\n    db  u8(0x6a),u8(0xcb),u8(0xbe),u8(0x39),u8(0x4a),u8(0x4c),u8(0x58),u8(0xcf)\n    db  u8(0xd0),u8(0xef),u8(0xaa),u8(0xfb),u8(0x43),u8(0x4d),u8(0x33),u8(0x85)\n    db  u8(0x45),u8(0xf9),u8(0x02),u8(0x7f),u8(0x50),u8(0x3c),u8(0x9f),u8(0xa8)\n    db  u8(0x51),u8(0xa3),u8(0x40),u8(0x8f),u8(0x92),u8(0x9d),u8(0x38),u8(0xf5)\n    db  u8(0xbc),u8(0xb6),u8(0xda),u8(0x21),u8(0x10),u8(0xff),u8(0xf3),u8(0xd2)\n    db  u8(0xcd),u8(0x0c),u8(0x13),u8(0xec),u8(0x5f),u8(0x97),u8(0x44),u8(0x17)\n    db  u8(0xc4),u8(0xa7),u8(0x7e),u8(0x3d),u8(0x64),u8(0x5d),u8(0x19),u8(0x73)\n    db  u8(0x60),u8(0x81),u8(0x4f),u8(0xdc),u8(0x22),u8(0x2a),u8(0x90),u8(0x88)\n    db  u8(0x46),u8(0xee),u8(0xb8),u8(0x14),u8(0xde),u8(0x5e),u8(0x0b),u8(0xdb)\n    db  u8(0xe0),u8(0x32),u8(0x3a),u8(0x0a),u8(0x49),u8(0x06),u8(0x24),u8(0x5c)\n    db  u8(0xc2),u8(0xd3),u8(0xac),u8(0x62),u8(0x91),u8(0x95),u8(0xe4),u8(0x79)\n    db  u8(0xe7),u8(0xc8),u8(0x37),u8(0x6d),u8(0x8d),u8(0xd5),u8(0x4e),u8(0xa9)\n    db  u8(0x6c),u8(0x56),u8(0xf4),u8(0xea),u8(0x65),u8(0x7a),u8(0xae),u8(0x08)\n    db  u8(0xba),u8(0x78),u8(0x25),u8(0x2e),u8(0x1c),u8(0xa6),u8(0xb4),u8(0xc6)\n    db  u8(0xe8),u8(0xdd),u8(0x74),u8(0x1f),u8(0x4b),u8(0xbd),u8(0x8b),u8(0x8a)\n    db  u8(0x70),u8(0x3e),u8(0xb5),u8(0x66),u8(0x48),u8(0x03),u8(0xf6),u8(0x0e)\n    db  u8(0x61),u8(0x35),u8(0x57),u8(0xb9),u8(0x86),u8(0xc1),u8(0x1d),u8(0x9e)\n    db  u8(0xe1),u8(0xf8),u8(0x98),u8(0x11),u8(0x69),u8(0xd9),u8(0x8e),u8(0x94)\n    db  u8(0x9b),u8(0x1e),u8(0x87),u8(0xe9),u8(0xce),u8(0x55),u8(0x28),u8(0xdf)\n    db  u8(0x8c),u8(0xa1),u8(0x89),u8(0x0d),u8(0xbf),u8(0xe6),u8(0x42),u8(0x68)\n    db  u8(0x41),u8(0x99),u8(0x2d),u8(0x0f),u8(0xb0),u8(0x54),u8(0xbb),u8(0x16)\n\n%endif\n\n%ifdef DECRYPTION_TABLE\n\n; Inverse S-box data - 256 entries\n\n%define v8(x)   fe(x), f9(x), fd(x), fb(x), fe(x), f9(x), fd(x), x\n\ndec_tab:\n    db  v8(0x52),v8(0x09),v8(0x6a),v8(0xd5),v8(0x30),v8(0x36),v8(0xa5),v8(0x38)\n    db  v8(0xbf),v8(0x40),v8(0xa3),v8(0x9e),v8(0x81),v8(0xf3),v8(0xd7),v8(0xfb)\n    db  v8(0x7c),v8(0xe3),v8(0x39),v8(0x82),v8(0x9b),v8(0x2f),v8(0xff),v8(0x87)\n    db  v8(0x34),v8(0x8e),v8(0x43),v8(0x44),v8(0xc4),v8(0xde),v8(0xe9),v8(0xcb)\n    db  v8(0x54),v8(0x7b),v8(0x94),v8(0x32),v8(0xa6),v8(0xc2),v8(0x23),v8(0x3d)\n    db  v8(0xee),v8(0x4c),v8(0x95),v8(0x0b),v8(0x42),v8(0xfa),v8(0xc3),v8(0x4e)\n    db  v8(0x08),v8(0x2e),v8(0xa1),v8(0x66),v8(0x28),v8(0xd9),v8(0x24),v8(0xb2)\n    db  v8(0x76),v8(0x5b),v8(0xa2),v8(0x49),v8(0x6d),v8(0x8b),v8(0xd1),v8(0x25)\n    db  v8(0x72),v8(0xf8),v8(0xf6),v8(0x64),v8(0x86),v8(0x68),v8(0x98),v8(0x16)\n    db  v8(0xd4),v8(0xa4),v8(0x5c),v8(0xcc),v8(0x5d),v8(0x65),v8(0xb6),v8(0x92)\n    db  v8(0x6c),v8(0x70),v8(0x48),v8(0x50),v8(0xfd),v8(0xed),v8(0xb9),v8(0xda)\n    db  v8(0x5e),v8(0x15),v8(0x46),v8(0x57),v8(0xa7),v8(0x8d),v8(0x9d),v8(0x84)\n    db  v8(0x90),v8(0xd8),v8(0xab),v8(0x00),v8(0x8c),v8(0xbc),v8(0xd3),v8(0x0a)\n    db  v8(0xf7),v8(0xe4),v8(0x58),v8(0x05),v8(0xb8),v8(0xb3),v8(0x45),v8(0x06)\n    db  v8(0xd0),v8(0x2c),v8(0x1e),v8(0x8f),v8(0xca),v8(0x3f),v8(0x0f),v8(0x02)\n    db  v8(0xc1),v8(0xaf),v8(0xbd),v8(0x03),v8(0x01),v8(0x13),v8(0x8a),v8(0x6b)\n    db  v8(0x3a),v8(0x91),v8(0x11),v8(0x41),v8(0x4f),v8(0x67),v8(0xdc),v8(0xea)\n    db  v8(0x97),v8(0xf2),v8(0xcf),v8(0xce),v8(0xf0),v8(0xb4),v8(0xe6),v8(0x73)\n    db  v8(0x96),v8(0xac),v8(0x74),v8(0x22),v8(0xe7),v8(0xad),v8(0x35),v8(0x85)\n    db  v8(0xe2),v8(0xf9),v8(0x37),v8(0xe8),v8(0x1c),v8(0x75),v8(0xdf),v8(0x6e)\n    db  v8(0x47),v8(0xf1),v8(0x1a),v8(0x71),v8(0x1d),v8(0x29),v8(0xc5),v8(0x89)\n    db  v8(0x6f),v8(0xb7),v8(0x62),v8(0x0e),v8(0xaa),v8(0x18),v8(0xbe),v8(0x1b)\n    db  v8(0xfc),v8(0x56),v8(0x3e),v8(0x4b),v8(0xc6),v8(0xd2),v8(0x79),v8(0x20)\n    db  v8(0x9a),v8(0xdb),v8(0xc0),v8(0xfe),v8(0x78),v8(0xcd),v8(0x5a),v8(0xf4)\n    db  v8(0x1f),v8(0xdd),v8(0xa8),v8(0x33),v8(0x88),v8(0x07),v8(0xc7),v8(0x31)\n    db  v8(0xb1),v8(0x12),v8(0x10),v8(0x59),v8(0x27),v8(0x80),v8(0xec),v8(0x5f)\n    db  v8(0x60),v8(0x51),v8(0x7f),v8(0xa9),v8(0x19),v8(0xb5),v8(0x4a),v8(0x0d)\n    db  v8(0x2d),v8(0xe5),v8(0x7a),v8(0x9f),v8(0x93),v8(0xc9),v8(0x9c),v8(0xef)\n    db  v8(0xa0),v8(0xe0),v8(0x3b),v8(0x4d),v8(0xae),v8(0x2a),v8(0xf5),v8(0xb0)\n    db  v8(0xc8),v8(0xeb),v8(0xbb),v8(0x3c),v8(0x83),v8(0x53),v8(0x99),v8(0x61)\n    db  v8(0x17),v8(0x2b),v8(0x04),v8(0x7e),v8(0xba),v8(0x77),v8(0xd6),v8(0x26)\n    db  v8(0xe1),v8(0x69),v8(0x14),v8(0x63),v8(0x55),v8(0x21),v8(0x0c),v8(0x7d)\n\n%endif\n\n    end\n"
  },
  {
    "path": "deps/cl345/crypt/aescrypt.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n*/\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"aesopt.h\"\n  #include \"aestab.h\"\n#else\n  #include \"crypt/aesopt.h\"\n  #include \"crypt/aestab.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_INTEL_AES_IF_PRESENT )\n  #if defined( INC_ALL )\t/* pcg */\n\t#include \"aes_ni.h\"\n  #else\n\t#include \"crypt/aes_ni.h\"\n  #endif /* Compiler-specific includes */\n#else\n/* map names here to provide the external API ('name' -> 'aes_name') */\n#  define aes_xi(x) aes_ ## x\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])\n#define so(y,x,c)   word_out(y, c, s(x,c))\n\n#if defined(ARRAYS)\n#define locals(y,x)     x[4],y[4]\n#else\n#define locals(y,x)     x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3\n#endif\n\n#define l_copy(y, x)    s(y,0) = s(x,0); s(y,1) = s(x,1); \\\n                        s(y,2) = s(x,2); s(y,3) = s(x,3);\n#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)\n#define state_out(y,x)  so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)\n#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)\n\n#if ( FUNCS_IN_C & ENCRYPTION_IN_C )\n\n/* Visual C++ .Net v7.1 provides the fastest encryption code when using\n   Pentium optimiation with small code but this is poor for decryption\n   so we need to control this with the following VC++ pragmas\n*/\n\n#if defined( _MSC_VER ) && !defined( _WIN64 )\n#pragma optimize( \"s\", on )\n#endif\n\n/* Given the column (c) of the output state variable, the following\n   macros give the input state variables which are needed in its\n   computation for each row (r) of the state. All the alternative\n   macros give the same end values but expand into different ways\n   of calculating these values.  In particular the complex macro\n   used for dynamically variable block sizes is designed to expand\n   to a compile time constant whenever possible but will expand to\n   conditional clauses on some branches (I am grateful to Frank\n   Yellin for this construction)\n*/\n\n#define fwd_var(x,r,c)\\\n ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\\\n : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\\\n : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\\\n :          ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))\n\n#if defined(FT4_SET)\n#undef  dec_fmvars\n#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))\n#elif defined(FT1_SET)\n#undef  dec_fmvars\n#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))\n#else\n#define fwd_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))\n#endif\n\n#if defined(FL4_SET)\n#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))\n#elif defined(FL1_SET)\n#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))\n#else\n#define fwd_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))\n#endif\n\nAES_RETURN aes_xi(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])\n{   uint32_t         locals(b0, b1);\n    const uint32_t   *kp;\n#if defined( dec_fmvars )\n    dec_fmvars; /* declare variables for fwd_mcol() if needed */\n#endif\n\n\tif(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)\n\t\treturn EXIT_FAILURE;\n\n\tkp = cx->ks;\n    state_in(b0, in, kp);\n\n#if (ENC_UNROLL == FULL)\n\n    switch(cx->inf.b[0])\n    {\n    case 14 * 16:\n        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\n        kp += 2 * N_COLS;\n    case 12 * 16:\n        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\n        kp += 2 * N_COLS;\n    case 10 * 16:\n        round(fwd_rnd,  b1, b0, kp + 1 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 2 * N_COLS);\n        round(fwd_rnd,  b1, b0, kp + 3 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 4 * N_COLS);\n        round(fwd_rnd,  b1, b0, kp + 5 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 6 * N_COLS);\n        round(fwd_rnd,  b1, b0, kp + 7 * N_COLS);\n        round(fwd_rnd,  b0, b1, kp + 8 * N_COLS);\n        round(fwd_rnd,  b1, b0, kp + 9 * N_COLS);\n        round(fwd_lrnd, b0, b1, kp +10 * N_COLS);\n    }\n\n#else\n\n#if (ENC_UNROLL == PARTIAL)\n    {   uint32_t    rnd;\n        for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)\n        {\n            kp += N_COLS;\n            round(fwd_rnd, b1, b0, kp);\n            kp += N_COLS;\n            round(fwd_rnd, b0, b1, kp);\n        }\n        kp += N_COLS;\n        round(fwd_rnd,  b1, b0, kp);\n#else\n    {   uint32_t    rnd;\n        for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)\n        {\n            kp += N_COLS;\n            round(fwd_rnd, b1, b0, kp);\n            l_copy(b0, b1);\n        }\n#endif\n        kp += N_COLS;\n        round(fwd_lrnd, b0, b1, kp);\n    }\n#endif\n\n    state_out(out, b0);\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if ( FUNCS_IN_C & DECRYPTION_IN_C)\n\n/* Visual C++ .Net v7.1 provides the fastest encryption code when using\n   Pentium optimiation with small code but this is poor for decryption\n   so we need to control this with the following VC++ pragmas\n*/\n\n#if defined( _MSC_VER ) && !defined( _WIN64 )\n#pragma optimize( \"t\", on )\n#endif\n\n/* Given the column (c) of the output state variable, the following\n   macros give the input state variables which are needed in its\n   computation for each row (r) of the state. All the alternative\n   macros give the same end values but expand into different ways\n   of calculating these values.  In particular the complex macro\n   used for dynamically variable block sizes is designed to expand\n   to a compile time constant whenever possible but will expand to\n   conditional clauses on some branches (I am grateful to Frank\n   Yellin for this construction)\n*/\n\n#define inv_var(x,r,c)\\\n ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\\\n : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\\\n : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\\\n :          ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))\n\n#if defined(IT4_SET)\n#undef  dec_imvars\n#define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))\n#elif defined(IT1_SET)\n#undef  dec_imvars\n#define inv_rnd(y,x,k,c)    (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))\n#else\n#define inv_rnd(y,x,k,c)    (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))\n#endif\n\n#if defined(IL4_SET)\n#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))\n#elif defined(IL1_SET)\n#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))\n#else\n#define inv_lrnd(y,x,k,c)   (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))\n#endif\n\n/* This code can work with the decryption key schedule in the   */\n/* order that is used for encrytpion (where the 1st decryption  */\n/* round key is at the high end ot the schedule) or with a key  */\n/* schedule that has been reversed to put the 1st decryption    */\n/* round key at the low end of the schedule in memory (when     */\n/* AES_REV_DKS is defined)                                      */\n\n#ifdef AES_REV_DKS\n#define key_ofs     0\n#define rnd_key(n)  (kp + n * N_COLS)\n#else\n#define key_ofs     1\n#define rnd_key(n)  (kp - n * N_COLS)\n#endif\n\nAES_RETURN aes_xi(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])\n{   uint32_t        locals(b0, b1);\n#if defined( dec_imvars )\n    dec_imvars; /* declare variables for inv_mcol() if needed */\n#endif\n    const uint32_t *kp;\n\n\tif(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)\n\t\treturn EXIT_FAILURE;\n\n    kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0);\n    state_in(b0, in, kp);\n\n#if (DEC_UNROLL == FULL)\n\n    kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2));\n    switch(cx->inf.b[0])\n    {\n    case 14 * 16:\n        round(inv_rnd,  b1, b0, rnd_key(-13));\n        round(inv_rnd,  b0, b1, rnd_key(-12));\n    case 12 * 16:\n        round(inv_rnd,  b1, b0, rnd_key(-11));\n        round(inv_rnd,  b0, b1, rnd_key(-10));\n    case 10 * 16:\n        round(inv_rnd,  b1, b0, rnd_key(-9));\n        round(inv_rnd,  b0, b1, rnd_key(-8));\n        round(inv_rnd,  b1, b0, rnd_key(-7));\n        round(inv_rnd,  b0, b1, rnd_key(-6));\n        round(inv_rnd,  b1, b0, rnd_key(-5));\n        round(inv_rnd,  b0, b1, rnd_key(-4));\n        round(inv_rnd,  b1, b0, rnd_key(-3));\n        round(inv_rnd,  b0, b1, rnd_key(-2));\n        round(inv_rnd,  b1, b0, rnd_key(-1));\n        round(inv_lrnd, b0, b1, rnd_key( 0));\n    }\n\n#else\n\n#if (DEC_UNROLL == PARTIAL)\n    {   uint32_t    rnd;\n        for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd)\n        {\n            kp = rnd_key(1);\n            round(inv_rnd, b1, b0, kp);\n            kp = rnd_key(1);\n            round(inv_rnd, b0, b1, kp);\n        }\n        kp = rnd_key(1);\n        round(inv_rnd, b1, b0, kp);\n#else\n    {   uint32_t    rnd;\n        for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd)\n        {\n            kp = rnd_key(1);\n            round(inv_rnd, b1, b0, kp);\n            l_copy(b0, b1);\n        }\n#endif\n        kp = rnd_key(1);\n        round(inv_lrnd, b0, b1, kp);\n        }\n#endif\n\n    state_out(out, b0);\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aeskey.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n*/\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"aesopt.h\"\n  #include \"aestab.h\"\n#else\n  #include \"crypt/aesopt.h\"\n  #include \"crypt/aestab.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_INTEL_AES_IF_PRESENT )\n  #if defined( INC_ALL )\t/* pcg */\n\t#include \"aes_ni.h\"\n  #else\n\t#include \"crypt/aes_ni.h\"\n  #endif /* Compiler-specific includes */\n#else\n/* map names here to provide the external API ('name' -> 'aes_name') */\n#  define aes_xi(x) aes_ ## x\n#endif\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n  #if defined( INC_ALL )\t/* pcg */\n\t#include \"aes_via_ace.h\"\n  #else\n\t#include \"crypt/aes_via_ace.h\"\n  #endif /* Compiler-specific includes */\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n/* Initialise the key schedule from the user supplied key. The key\n   length can be specified in bytes, with legal values of 16, 24\n   and 32, or in bits, with legal values of 128, 192 and 256. These\n   values correspond with Nk values of 4, 6 and 8 respectively.\n\n   The following macros implement a single cycle in the key\n   schedule generation process. The number of cycles needed\n   for each cx->n_col and nk value is:\n\n    nk =             4  5  6  7  8\n    ------------------------------\n    cx->n_col = 4   10  9  8  7  7\n    cx->n_col = 5   14 11 10  9  9\n    cx->n_col = 6   19 15 12 11 11\n    cx->n_col = 7   21 19 16 13 14\n    cx->n_col = 8   29 23 19 17 14\n*/\n\n#if defined( REDUCE_CODE_SIZE )\n#  define ls_box ls_sub\n   uint32_t ls_sub(const uint32_t t, const uint32_t n);\n#  define inv_mcol im_sub\n   uint32_t im_sub(const uint32_t x);\n#  ifdef ENC_KS_UNROLL\n#    undef ENC_KS_UNROLL\n#  endif\n#  ifdef DEC_KS_UNROLL\n#    undef DEC_KS_UNROLL\n#  endif\n#endif\n\n#if (FUNCS_IN_C & ENC_KEYING_IN_C)\n\n#if defined(AES_128) || defined( AES_VAR )\n\n#define ke4(k,i) \\\n{   k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \\\n    k[4*(i)+5] = ss[1] ^= ss[0]; \\\n    k[4*(i)+6] = ss[2] ^= ss[1]; \\\n    k[4*(i)+7] = ss[3] ^= ss[2]; \\\n}\n\nAES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{   uint32_t    ss[4];\n\n    cx->ks[0] = ss[0] = word_in(key, 0);\n    cx->ks[1] = ss[1] = word_in(key, 1);\n    cx->ks[2] = ss[2] = word_in(key, 2);\n    cx->ks[3] = ss[3] = word_in(key, 3);\n\n#ifdef ENC_KS_UNROLL\n    ke4(cx->ks, 0);  ke4(cx->ks, 1);\n    ke4(cx->ks, 2);  ke4(cx->ks, 3);\n    ke4(cx->ks, 4);  ke4(cx->ks, 5);\n    ke4(cx->ks, 6);  ke4(cx->ks, 7);\n    ke4(cx->ks, 8);\n#else\n    {   uint32_t i;\n        for(i = 0; i < 9; ++i)\n            ke4(cx->ks, i);\n    }\n#endif\n    ke4(cx->ks, 9);\n    cx->inf.l = 0;\n    cx->inf.b[0] = 10 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if defined(AES_192) || defined( AES_VAR )\n\n#define kef6(k,i) \\\n{   k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \\\n    k[6*(i)+ 7] = ss[1] ^= ss[0]; \\\n    k[6*(i)+ 8] = ss[2] ^= ss[1]; \\\n    k[6*(i)+ 9] = ss[3] ^= ss[2]; \\\n}\n\n#define ke6(k,i) \\\n{   kef6(k,i); \\\n    k[6*(i)+10] = ss[4] ^= ss[3]; \\\n    k[6*(i)+11] = ss[5] ^= ss[4]; \\\n}\n\nAES_RETURN aes_xi(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{   uint32_t    ss[6];\n\n\tcx->ks[0] = ss[0] = word_in(key, 0);\n    cx->ks[1] = ss[1] = word_in(key, 1);\n    cx->ks[2] = ss[2] = word_in(key, 2);\n    cx->ks[3] = ss[3] = word_in(key, 3);\n    cx->ks[4] = ss[4] = word_in(key, 4);\n    cx->ks[5] = ss[5] = word_in(key, 5);\n\n#ifdef ENC_KS_UNROLL\n    ke6(cx->ks, 0);  ke6(cx->ks, 1);\n    ke6(cx->ks, 2);  ke6(cx->ks, 3);\n    ke6(cx->ks, 4);  ke6(cx->ks, 5);\n    ke6(cx->ks, 6);\n#else\n    {   uint32_t i;\n        for(i = 0; i < 7; ++i)\n            ke6(cx->ks, i);\n    }\n#endif\n    kef6(cx->ks, 7);\n    cx->inf.l = 0;\n    cx->inf.b[0] = 12 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if defined(AES_256) || defined( AES_VAR )\n\n#define kef8(k,i) \\\n{   k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \\\n    k[8*(i)+ 9] = ss[1] ^= ss[0]; \\\n    k[8*(i)+10] = ss[2] ^= ss[1]; \\\n    k[8*(i)+11] = ss[3] ^= ss[2]; \\\n}\n\n#define ke8(k,i) \\\n{   kef8(k,i); \\\n    k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \\\n    k[8*(i)+13] = ss[5] ^= ss[4]; \\\n    k[8*(i)+14] = ss[6] ^= ss[5]; \\\n    k[8*(i)+15] = ss[7] ^= ss[6]; \\\n}\n\nAES_RETURN aes_xi(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1])\n{   uint32_t    ss[8];\n\n    cx->ks[0] = ss[0] = word_in(key, 0);\n    cx->ks[1] = ss[1] = word_in(key, 1);\n    cx->ks[2] = ss[2] = word_in(key, 2);\n    cx->ks[3] = ss[3] = word_in(key, 3);\n    cx->ks[4] = ss[4] = word_in(key, 4);\n    cx->ks[5] = ss[5] = word_in(key, 5);\n    cx->ks[6] = ss[6] = word_in(key, 6);\n    cx->ks[7] = ss[7] = word_in(key, 7);\n\n#ifdef ENC_KS_UNROLL\n    ke8(cx->ks, 0); ke8(cx->ks, 1);\n    ke8(cx->ks, 2); ke8(cx->ks, 3);\n    ke8(cx->ks, 4); ke8(cx->ks, 5);\n#else\n    {   uint32_t i;\n        for(i = 0; i < 6; ++i)\n            ke8(cx->ks,  i);\n    }\n#endif\n    kef8(cx->ks, 6);\n    cx->inf.l = 0;\n    cx->inf.b[0] = 14 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#endif\n\n#if (FUNCS_IN_C & DEC_KEYING_IN_C)\n\n/* this is used to store the decryption round keys  */\n/* in forward or reverse order                      */\n\n#ifdef AES_REV_DKS\n#define v(n,i)  ((n) - (i) + 2 * ((i) & 3))\n#else\n#define v(n,i)  (i)\n#endif\n\n#if DEC_ROUND == NO_TABLES\n#define ff(x)   (x)\n#else\n#define ff(x)   inv_mcol(x)\n#if defined( dec_imvars )\n#define d_vars  dec_imvars\n#endif\n#endif\n\n#if defined(AES_128) || defined( AES_VAR )\n\n#define k4e(k,i) \\\n{   k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \\\n    k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \\\n    k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \\\n    k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \\\n}\n\n#if 1\n\n#define kdf4(k,i) \\\n{   ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \\\n    ss[1] = ss[1] ^ ss[3]; \\\n    ss[2] = ss[2] ^ ss[3]; \\\n    ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \\\n    ss[i % 4] ^= ss[4]; \\\n    ss[4] ^= k[v(40,(4*(i)))];   k[v(40,(4*(i))+4)] = ff(ss[4]); \\\n    ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \\\n    ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \\\n    ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \\\n}\n\n#define kd4(k,i) \\\n{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \\\n    ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \\\n    k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \\\n    k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \\\n    k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \\\n    k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \\\n}\n\n#define kdl4(k,i) \\\n{   ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \\\n    k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \\\n    k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \\\n    k[v(40,(4*(i))+6)] = ss[0]; \\\n    k[v(40,(4*(i))+7)] = ss[1]; \\\n}\n\n#else\n\n#define kdf4(k,i) \\\n{   ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \\\n    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \\\n    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \\\n    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \\\n}\n\n#define kd4(k,i) \\\n{   ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \\\n    ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \\\n    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \\\n    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \\\n    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \\\n}\n\n#define kdl4(k,i) \\\n{   ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \\\n    ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \\\n    ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \\\n    ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \\\n}\n\n#endif\n\nAES_RETURN aes_xi(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{   uint32_t    ss[5];\n#if defined( d_vars )\n        d_vars;\n#endif\n\n\tcx->ks[v(40,(0))] = ss[0] = word_in(key, 0);\n    cx->ks[v(40,(1))] = ss[1] = word_in(key, 1);\n    cx->ks[v(40,(2))] = ss[2] = word_in(key, 2);\n    cx->ks[v(40,(3))] = ss[3] = word_in(key, 3);\n\n#ifdef DEC_KS_UNROLL\n     kdf4(cx->ks, 0); kd4(cx->ks, 1);\n     kd4(cx->ks, 2);  kd4(cx->ks, 3);\n     kd4(cx->ks, 4);  kd4(cx->ks, 5);\n     kd4(cx->ks, 6);  kd4(cx->ks, 7);\n     kd4(cx->ks, 8);  kdl4(cx->ks, 9);\n#else\n    {   uint32_t i;\n        for(i = 0; i < 10; ++i)\n            k4e(cx->ks, i);\n#if !(DEC_ROUND == NO_TABLES)\n        for(i = N_COLS; i < 10 * N_COLS; ++i)\n            cx->ks[i] = inv_mcol(cx->ks[i]);\n#endif\n    }\n#endif\n    cx->inf.l = 0;\n    cx->inf.b[0] = 10 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if defined(AES_192) || defined( AES_VAR )\n\n#define k6ef(k,i) \\\n{   k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \\\n    k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \\\n    k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \\\n    k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \\\n}\n\n#define k6e(k,i) \\\n{   k6ef(k,i); \\\n    k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \\\n    k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \\\n}\n\n#define kdf6(k,i) \\\n{   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \\\n    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \\\n    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \\\n    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \\\n    ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \\\n    ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \\\n}\n\n#define kd6(k,i) \\\n{   ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \\\n    ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \\\n    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \\\n    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \\\n    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \\\n    ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \\\n    ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \\\n}\n\n#define kdl6(k,i) \\\n{   ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \\\n    ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \\\n    ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \\\n    ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \\\n}\n\nAES_RETURN aes_xi(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{   uint32_t    ss[7];\n#if defined( d_vars )\n        d_vars;\n#endif\n\n    cx->ks[v(48,(0))] = ss[0] = word_in(key, 0);\n    cx->ks[v(48,(1))] = ss[1] = word_in(key, 1);\n    cx->ks[v(48,(2))] = ss[2] = word_in(key, 2);\n    cx->ks[v(48,(3))] = ss[3] = word_in(key, 3);\n\n#ifdef DEC_KS_UNROLL\n    /* split original code into two lines to avoid possible ambiguity (Ralf Senderek) \n\t   (Additional annotation to find changes - pcg) */\n    ss[4] = word_in(key, 4);\n    cx->ks[v(48,(4))] = ff(ss[4]);\n    ss[5] = word_in(key, 5);\n    cx->ks[v(48,(5))] = ff(ss[5]);\n    kdf6(cx->ks, 0); kd6(cx->ks, 1);\n    kd6(cx->ks, 2);  kd6(cx->ks, 3);\n    kd6(cx->ks, 4);  kd6(cx->ks, 5);\n    kd6(cx->ks, 6);  kdl6(cx->ks, 7);\n#else\n    cx->ks[v(48,(4))] = ss[4] = word_in(key, 4);\n    cx->ks[v(48,(5))] = ss[5] = word_in(key, 5);\n    {   uint32_t i;\n\n        for(i = 0; i < 7; ++i)\n            k6e(cx->ks, i);\n        k6ef(cx->ks, 7);\n#if !(DEC_ROUND == NO_TABLES)\n        for(i = N_COLS; i < 12 * N_COLS; ++i)\n            cx->ks[i] = inv_mcol(cx->ks[i]);\n#endif\n    }\n#endif\n    cx->inf.l = 0;\n    cx->inf.b[0] = 12 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#if defined(AES_256) || defined( AES_VAR )\n\n#define k8ef(k,i) \\\n{   k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \\\n    k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \\\n    k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \\\n    k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \\\n}\n\n#define k8e(k,i) \\\n{   k8ef(k,i); \\\n    k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \\\n    k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \\\n    k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \\\n    k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \\\n}\n\n#define kdf8(k,i) \\\n{   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \\\n    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \\\n    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \\\n    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \\\n    ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \\\n    ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \\\n    ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \\\n    ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \\\n}\n\n#define kd8(k,i) \\\n{   ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \\\n    ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \\\n    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \\\n    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \\\n    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \\\n    ss[8] = ls_box(ss[3],0); \\\n    ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \\\n    ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \\\n    ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \\\n    ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \\\n}\n\n#define kdl8(k,i) \\\n{   ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \\\n    ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \\\n    ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \\\n    ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \\\n}\n\nAES_RETURN aes_xi(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1])\n{   uint32_t    ss[9];\n#if defined( d_vars )\n        d_vars;\n#endif\n\n    cx->ks[v(56,(0))] = ss[0] = word_in(key, 0);\n    cx->ks[v(56,(1))] = ss[1] = word_in(key, 1);\n    cx->ks[v(56,(2))] = ss[2] = word_in(key, 2);\n    cx->ks[v(56,(3))] = ss[3] = word_in(key, 3);\n\n#ifdef DEC_KS_UNROLL\n    /* split original code into two lines to avoid possible ambiguity (Ralf Senderek) \n\t   (Additional annotation to find changes - pcg) */\n    ss[4] = word_in(key, 4);\n    cx->ks[v(56,(4))] = ff(ss[4]);\n    ss[5] = word_in(key, 5);\n    cx->ks[v(56,(5))] = ff(ss[5]);\n    ss[6] = word_in(key, 6);\n    cx->ks[v(56,(6))] = ff(ss[6]);\n    ss[7] = word_in(key, 7);\n    cx->ks[v(56,(7))] = ff(ss[7]);\n    kdf8(cx->ks, 0); kd8(cx->ks, 1);\n    kd8(cx->ks, 2);  kd8(cx->ks, 3);\n    kd8(cx->ks, 4);  kd8(cx->ks, 5);\n    kdl8(cx->ks, 6);\n#else\n    cx->ks[v(56,(4))] = ss[4] = word_in(key, 4);\n    cx->ks[v(56,(5))] = ss[5] = word_in(key, 5);\n    cx->ks[v(56,(6))] = ss[6] = word_in(key, 6);\n    cx->ks[v(56,(7))] = ss[7] = word_in(key, 7);\n    {   uint32_t i;\n\n        for(i = 0; i < 6; ++i)\n            k8e(cx->ks,  i);\n        k8ef(cx->ks,  6);\n#if !(DEC_ROUND == NO_TABLES)\n        for(i = N_COLS; i < 14 * N_COLS; ++i)\n            cx->ks[i] = inv_mcol(cx->ks[i]);\n#endif\n    }\n#endif\n    cx->inf.l = 0;\n    cx->inf.b[0] = 14 * 16;\n\n#ifdef USE_VIA_ACE_IF_PRESENT\n    if(VIA_ACE_AVAILABLE)\n        cx->inf.b[1] = 0xff;\n#endif\n    return EXIT_SUCCESS;\n}\n\n#endif\n\n#endif\n\n#if defined( AES_VAR )\n\nAES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1])\n{\n\tswitch(key_len)\n\t{\n\tcase 16: case 128: return aes_encrypt_key128(key, cx);\n\tcase 24: case 192: return aes_encrypt_key192(key, cx);\n\tcase 32: case 256: return aes_encrypt_key256(key, cx);\n\tdefault: return EXIT_FAILURE;\n\t}\n}\n\nAES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1])\n{\n\tswitch(key_len)\n\t{\n\tcase 16: case 128: return aes_decrypt_key128(key, cx);\n\tcase 24: case 192: return aes_decrypt_key192(key, cx);\n\tcase 32: case 256: return aes_decrypt_key256(key, cx);\n\tdefault: return EXIT_FAILURE;\n\t}\n}\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aesopt.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n This file contains the compilation options for AES (Rijndael) and code\n that is common across encryption, key scheduling and table generation.\n\n OPERATION\n\n These source code files implement the AES algorithm Rijndael designed by\n Joan Daemen and Vincent Rijmen. This version is designed for the standard\n block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24\n and 32 bytes).\n\n This version is designed for flexibility and speed using operations on\n 32-bit words rather than operations on bytes.  It can be compiled with\n either big or little endian internal byte order but is faster when the\n native byte order for the processor is used.\n\n THE CIPHER INTERFACE\n\n The cipher interface is implemented as an array of bytes in which lower\n AES bit sequence indexes map to higher numeric significance within bytes.\n\n  uint8_t                 (an unsigned  8-bit type)\n  uint32_t                (an unsigned 32-bit type)\n  struct aes_encrypt_ctx  (structure for the cipher encryption context)\n  struct aes_decrypt_ctx  (structure for the cipher decryption context)\n  AES_RETURN                the function return type\n\n  C subroutine calls:\n\n  AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]);\n  AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]);\n  AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]);\n  AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out,\n                                                  const aes_encrypt_ctx cx[1]);\n\n  AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]);\n  AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]);\n  AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]);\n  AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out,\n                                                  const aes_decrypt_ctx cx[1]);\n\n IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that\n you call aes_init() before AES is used so that the tables are initialised.\n\n C++ aes class subroutines:\n\n     Class AESencrypt  for encryption\n\n      Construtors:\n          AESencrypt(void)\n          AESencrypt(const unsigned char *key) - 128 bit key\n      Members:\n          AES_RETURN key128(const unsigned char *key)\n          AES_RETURN key192(const unsigned char *key)\n          AES_RETURN key256(const unsigned char *key)\n          AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const\n\n      Class AESdecrypt  for encryption\n      Construtors:\n          AESdecrypt(void)\n          AESdecrypt(const unsigned char *key) - 128 bit key\n      Members:\n          AES_RETURN key128(const unsigned char *key)\n          AES_RETURN key192(const unsigned char *key)\n          AES_RETURN key256(const unsigned char *key)\n          AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const\n*/\n\n#if !defined( _AESOPT_H )\n#define _AESOPT_H\n\n/* Cryptlib options: Enable use of asm encryption with C key schedule (the\n   fastest combination) and use Intel NI and VIA ACE if possible, but for\n   VIA ACE not under WinCE, both because it's possible that we could be \n   running on an oddball embedded x86 that doesn't understand the necessary \n   opcodes, and because eVC++ doesn't understand some of the extensions \n   used in the ACE-support code - pcg */\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 1500 ) && \\\n\tdefined( _M_X64 )\n  #define USE_INTEL_AES_IF_PRESENT\n#endif /* VC++ on x64 under Win64 - pcg */\n#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) && \\\n\tdefined( _M_IX86 ) && \\\n\t!( defined( _WIN32_WCE ) || defined( NO_ASM ) )\n  #ifndef USE_VIA_ACE_IF_PRESENT\n\t#define USE_VIA_ACE_IF_PRESENT\n  #endif\n#endif /* VC++ on x86 under Win32 - pcg */\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 800 ) && \\\n\t!( defined( _WIN32_WCE ) || defined( NO_ASM ) )\n  /* The apparently redundant guards are necessary in case users manually\n     define the values to enable various asm options */\n  #if defined( _M_X64 )\n\t#ifndef ASM_AMD64_C\n\t  #define ASM_AMD64_C\n\t#endif /* ASM_AMD64_C */\n  #elif defined( _M_IX86 )\n\t#ifndef ASM_X86_V2C\n\t  #define ASM_X86_V2C\n\t#endif /* ASM_X86_V2C */\n  #else\n\t#define NO_ASM\n  #endif /* Different x86 architectures */\n#endif /* VC++ on x86 under Win32 - pcg */\n\n#if defined( INC_ALL )\n  #include \"aes.h\"\n#else\n  #include \"crypt/aes.h\"\n#endif /* Compiler-specific includes - pcg */\n\n/*  PLATFORM SPECIFIC INCLUDES */\n\n#if defined( INC_ALL )\n  #include \"brg_endian.h\"\n#else\n  #include \"crypt/brg_endian.h\"\n#endif /* Compiler-specific includes - pcg */\n\n#ifdef __VxWorks__\n  /* vxWorksCommon.h defines NONE (\"for times when NULL won't do\") so we \n\t undefine it so that the AES code can define it below */\n  #undef NONE\n#endif /* __VxWorks__ - pcg */\n\n/*  CONFIGURATION - THE USE OF DEFINES\n\n    Later in this section there are a number of defines that control the\n    operation of the code.  In each section, the purpose of each define is\n    explained so that the relevant form can be included or excluded by\n    setting either 1's or 0's respectively on the branches of the related\n    #if clauses.  The following local defines should not be changed.\n*/\n\n#define ENCRYPTION_IN_C     1\n#define DECRYPTION_IN_C     2\n#define ENC_KEYING_IN_C     4\n#define DEC_KEYING_IN_C     8\n\n#define NO_TABLES           0\n#define ONE_TABLE           1\n#define FOUR_TABLES         4\n#define NONE                0\n#define PARTIAL             1\n#define FULL                2\n\n/*  --- START OF USER CONFIGURED OPTIONS --- */\n\n/*  1. BYTE ORDER WITHIN 32 BIT WORDS\n\n    The fundamental data processing units in Rijndael are 8-bit bytes. The\n    input, output and key input are all enumerated arrays of bytes in which\n    bytes are numbered starting at zero and increasing to one less than the\n    number of bytes in the array in question. This enumeration is only used\n    for naming bytes and does not imply any adjacency or order relationship\n    from one byte to another. When these inputs and outputs are considered\n    as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to\n    byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte.\n    In this implementation bits are numbered from 0 to 7 starting at the\n    numerically least significant end of each byte (bit n represents 2^n).\n\n    However, Rijndael can be implemented more efficiently using 32-bit\n    words by packing bytes into words so that bytes 4*n to 4*n+3 are placed\n    into word[n]. While in principle these bytes can be assembled into words\n    in any positions, this implementation only supports the two formats in\n    which bytes in adjacent positions within words also have adjacent byte\n    numbers. This order is called big-endian if the lowest numbered bytes\n    in words have the highest numeric significance and little-endian if the\n    opposite applies.\n\n    This code can work in either order irrespective of the order used by the\n    machine on which it runs. Normally the internal byte order will be set\n    to the order of the processor on which the code is to be run but this\n    define can be used to reverse this in special situations\n\n    WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set.\n    This define will hence be redefined later (in section 4) if necessary\n*/\n\n#if 1\n#  define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER\n#elif 0\n#  define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN\n#elif 0\n#  define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN\n#else\n#  error The algorithm byte order is not defined\n#endif\n\n/*  2. Intel AES AND VIA ACE SUPPORT */\n\n#if defined( __GNUC__ ) && defined( __i386__ ) \\\n || defined( _WIN32 ) && defined( _M_IX86 ) && !(defined( _WIN64 ) \\\n || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 ))\n#  define VIA_ACE_POSSIBLE\n#endif\n\n/* AES is supported out of the box by Windows x64 compilers, but by gcc only \n   if the stars are right, we have to feature-test for SSE 2, SSE 3, and AES \n   to enable it - pcg */\n\n#if defined( _WIN64 ) && defined( _MSC_VER ) && \\\n\t!defined( INTEL_AES_POSSIBLE )\n  #define INTEL_AES_POSSIBLE\n#elif defined( __GNUC__ ) && defined( __x86_64__ ) && \\\n\t  defined( __SSE2__ ) && defined( __SSE3__ ) && \\\n\t  defined( __AES__ ) && \\\n\t  !defined( INTEL_AES_POSSIBLE )\n  #define INTEL_AES_POSSIBLE\n#endif /* Compiler-specific AES instruction support */\n\n/*  Define this option if support for the Intel AESNI is required\n    If USE_INTEL_AES_IF_PRESENT is defined then AESNI will be used\n    if it is detected (both present and enabled).\n\n\tAESNI uses a decryption key schedule with the first decryption\n\tround key at the high end of the key scedule with the following\n\tround keys at lower positions in memory.  So AES_REV_DKS must NOT\n\tbe defined when AESNI will be used.  ALthough it is unlikely that\n\tassembler code will be used with an AESNI build, if it is then\n\tAES_REV_DKS must NOT be defined when the assembler files are\n\tbuilt\n*/\n\n#if 1 && defined( INTEL_AES_POSSIBLE ) && !defined( USE_INTEL_AES_IF_PRESENT )\n#  define USE_INTEL_AES_IF_PRESENT\n#endif\n\n/*  Define this option if support for the VIA ACE is required. This uses\n    inline assembler instructions and is only implemented for the Microsoft,\n    Intel and GCC compilers.  If VIA ACE is known to be present, then defining\n    ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption\n    code.  If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if\n    it is detected (both present and enabled) but the normal AES code will\n    also be present.\n\n    When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte\n    aligned; other input/output buffers do not need to be 16 byte aligned\n    but there are very large performance gains if this can be arranged.\n    VIA ACE also requires the decryption key schedule to be in reverse\n    order (which later checks below ensure).\n\n\tAES_REV_DKS must be set for assembler code used with a VIA ACE build\n*/\n\n#if 1 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT )\n#  define USE_VIA_ACE_IF_PRESENT\n#endif\n\n#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT )\n#  define ASSUME_VIA_ACE_PRESENT\n#  endif\n\n/*  3. ASSEMBLER SUPPORT\n\n    This define (which can be on the command line) enables the use of the\n    assembler code routines for encryption, decryption and key scheduling\n    as follows:\n\n    ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for\n                encryption and decryption and but with key scheduling in C\n    ASM_X86_V2  uses assembler (aes_x86_v2.asm) with compressed tables for\n                encryption, decryption and key scheduling\n    ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for\n                encryption and decryption and but with key scheduling in C\n    ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for\n                encryption and decryption and but with key scheduling in C\n\n    Change one 'if 0' below to 'if 1' to select the version or define\n    as a compilation option.\n*/\n\n#if 0 && !defined( ASM_X86_V1C )\n#  define ASM_X86_V1C\n#elif 0 && !defined( ASM_X86_V2  )\n#  define ASM_X86_V2\n#elif 0 && !defined( ASM_X86_V2C )\n#  define ASM_X86_V2C\n#elif 0 && !defined( ASM_AMD64_C )\n#  define ASM_AMD64_C\n#endif\n\n#if defined( __i386 ) || defined( _M_IX86 )\n#  define A32_\n#elif defined( __x86_64__ ) || defined( _M_X64 )\n#  define A64_\n#endif\n\n#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \\\n       && !defined( A32_ )  || defined( ASM_AMD64_C ) && !defined( A64_ )\n#  error Assembler code is only available for x86 and AMD64 systems\n#endif\n\n/*  4. FAST INPUT/OUTPUT OPERATIONS.\n\n    On some machines it is possible to improve speed by transferring the\n    bytes in the input and output arrays to and from the internal 32-bit\n    variables by addressing these arrays as if they are arrays of 32-bit\n    words.  On some machines this will always be possible but there may\n    be a large performance penalty if the byte arrays are not aligned on\n    the normal word boundaries. On other machines this technique will\n    lead to memory access errors when such 32-bit word accesses are not\n    properly aligned. The option SAFE_IO avoids such problems but will\n    often be slower on those machines that support misaligned access\n    (especially so if care is taken to align the input  and output byte\n    arrays on 32-bit word boundaries). If SAFE_IO is not defined it is\n    assumed that access to byte arrays as if they are arrays of 32-bit\n    words will not cause problems when such accesses are misaligned.\n*/\n#if 1 && !defined( _MSC_VER )\n#  define SAFE_IO\n#endif\n\n/*  5. LOOP UNROLLING\n\n    The code for encryption and decrytpion cycles through a number of rounds\n    that can be implemented either in a loop or by expanding the code into a\n    long sequence of instructions, the latter producing a larger program but\n    one that will often be much faster. The latter is called loop unrolling.\n    There are also potential speed advantages in expanding two iterations in\n    a loop with half the number of iterations, which is called partial loop\n    unrolling.  The following options allow partial or full loop unrolling\n    to be set independently for encryption and decryption\n*/\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define ENC_UNROLL  FULL\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define ENC_UNROLL  PARTIAL\n#else\n#  define ENC_UNROLL  NONE\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define DEC_UNROLL  FULL\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define DEC_UNROLL  PARTIAL\n#else\n#  define DEC_UNROLL  NONE\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define ENC_KS_UNROLL\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define DEC_KS_UNROLL\n#endif\n\n/*  6. FAST FINITE FIELD OPERATIONS\n\n    If this section is included, tables are used to provide faster finite\n    field arithmetic (this has no effect if STATIC_TABLES is defined).\n*/\n#if 1\n#  define FF_TABLES\n#endif\n\n/*  7. INTERNAL STATE VARIABLE FORMAT\n\n    The internal state of Rijndael is stored in a number of local 32-bit\n    word varaibles which can be defined either as an array or as individual\n    names variables. Include this section if you want to store these local\n    varaibles in arrays. Otherwise individual local variables will be used.\n*/\n#if 1\n#  define ARRAYS\n#endif\n\n/*  8. FIXED OR DYNAMIC TABLES\n\n    When this section is included the tables used by the code are compiled\n    statically into the binary file.  Otherwise the subroutine aes_init()\n    must be called to compute them before the code is first used.\n*/\n#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 ))\n#  define STATIC_TABLES\n#endif\n\n/*  9. MASKING OR CASTING FROM LONGER VALUES TO BYTES\n\n    In some systems it is better to mask longer values to extract bytes\n    rather than using a cast. This option allows this choice.\n*/\n#if 0\n#  define to_byte(x)  ((uint8_t)(x))\n#else\n#  define to_byte(x)  ((x) & 0xff)\n#endif\n\n/*  10. TABLE ALIGNMENT\n\n    On some sytsems speed will be improved by aligning the AES large lookup\n    tables on particular boundaries. This define should be set to a power of\n    two giving the desired alignment. It can be left undefined if alignment\n    is not needed.  This option is specific to the Microsft VC++ compiler -\n    it seems to sometimes cause trouble for the VC++ version 6 compiler.\n*/\n\n#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 )\n#  define TABLE_ALIGN 32\n#endif\n\n/*  11.  REDUCE CODE AND TABLE SIZE\n\n    This replaces some expanded macros with function calls if AES_ASM_V2 or\n    AES_ASM_V2C are defined\n*/\n\n#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))\n#  define REDUCE_CODE_SIZE\n#endif\n\n/*  12. TABLE OPTIONS\n\n    This cipher proceeds by repeating in a number of cycles known as 'rounds'\n    which are implemented by a round function which can optionally be speeded\n    up using tables.  The basic tables are each 256 32-bit words, with either\n    one or four tables being required for each round function depending on\n    how much speed is required. The encryption and decryption round functions\n    are different and the last encryption and decrytpion round functions are\n    different again making four different round functions in all.\n\n    This means that:\n      1. Normal encryption and decryption rounds can each use either 0, 1\n         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.\n      2. The last encryption and decryption rounds can also use either 0, 1\n         or 4 tables and table spaces of 0, 1024 or 4096 bytes each.\n\n    Include or exclude the appropriate definitions below to set the number\n    of tables used by this implementation.\n*/\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define ENC_ROUND   FOUR_TABLES\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define ENC_ROUND   ONE_TABLE\n#else\n#  define ENC_ROUND   NO_TABLES\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define LAST_ENC_ROUND  FOUR_TABLES\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define LAST_ENC_ROUND  ONE_TABLE\n#else\n#  define LAST_ENC_ROUND  NO_TABLES\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define DEC_ROUND   FOUR_TABLES\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define DEC_ROUND   ONE_TABLE\n#else\n#  define DEC_ROUND   NO_TABLES\n#endif\n\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define LAST_DEC_ROUND  FOUR_TABLES\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define LAST_DEC_ROUND  ONE_TABLE\n#else\n#  define LAST_DEC_ROUND  NO_TABLES\n#endif\n\n/*  The decryption key schedule can be speeded up with tables in the same\n    way that the round functions can.  Include or exclude the following\n    defines to set this requirement.\n*/\n#if !defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define KEY_SCHED   FOUR_TABLES\n#elif defined( CONFIG_CONSERVE_MEMORY )\t\t/* pcg */\n#  define KEY_SCHED   ONE_TABLE\n#else\n#  define KEY_SCHED   NO_TABLES\n#endif\n\n/*  ---- END OF USER CONFIGURED OPTIONS ---- */\n\n/* VIA ACE support is only available for VC++ and GCC */\n\n#if !defined( _MSC_VER ) && !defined( __GNUC__ )\n#  if defined( ASSUME_VIA_ACE_PRESENT )\n#    undef ASSUME_VIA_ACE_PRESENT\n#  endif\n#  if defined( USE_VIA_ACE_IF_PRESENT )\n#    undef USE_VIA_ACE_IF_PRESENT\n#  endif\n#endif\n\n#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT )\n#  define USE_VIA_ACE_IF_PRESENT\n#endif\n\n#if defined( __APPLE__ ) && TARGET_OS_SIMULATOR\n  /* The iPhone simmulator, even though it's simulating an ARM platform, \n     actually builds x86 (ARMv7) or x86 (ARM64) binaries.  In addition the\n\t simulator isn't very complete, and crashes with an EXC_BAD_ACCESS when \n\t we do the CPUID check for the Via ACE, so we disable it */\n  #undef ASSUME_VIA_ACE_PRESENT\n  #undef USE_VIA_ACE_IF_PRESENT\n#endif /* iPhone simulator - pcg */\n\n#if defined(__BEOS__)\n  /* The BeOS compiler (and ancient version of gcc) cannot generate code \n     that reliably determines if a VIA CPU is available */\n  #undef USE_VIA_ACE_IF_PRESENT\n#endif /* BeOS gcc - pcg */\n\n/* define to reverse decryption key schedule    */\n#if 1 || defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS )\n#  define AES_REV_DKS\n#endif\n\n/* Intel AESNI uses a decryption key schedule in the encryption order */\n#if defined( USE_INTEL_AES_IF_PRESENT ) && defined ( AES_REV_DKS )\n#  undef AES_REV_DKS\n#endif\n\n/* Assembler support requires the use of platform byte order */\n\n#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \\\n    && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER)\n#  undef  ALGORITHM_BYTE_ORDER\n#  define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER\n#endif\n\n/* In this implementation the columns of the state array are each held in\n   32-bit words. The state array can be held in various ways: in an array\n   of words, in a number of individual word variables or in a number of\n   processor registers. The following define maps a variable name x and\n   a column number c to the way the state array variable is to be held.\n   The first define below maps the state into an array x[c] whereas the\n   second form maps the state into a number of individual variables x0,\n   x1, etc.  Another form could map individual state colums to machine\n   register names.\n*/\n\n#if defined( ARRAYS )\n#  define s(x,c) x[c]\n#else\n#  define s(x,c) x##c\n#endif\n\n/*  This implementation provides subroutines for encryption, decryption\n    and for setting the three key lengths (separately) for encryption\n    and decryption. Since not all functions are needed, masks are set\n    up here to determine which will be implemented in C\n*/\n\n#if !defined( AES_ENCRYPT )\n#  define EFUNCS_IN_C   0\n#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \\\n    || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )\n#  define EFUNCS_IN_C   ENC_KEYING_IN_C\n#elif !defined( ASM_X86_V2 )\n#  define EFUNCS_IN_C   ( ENCRYPTION_IN_C | ENC_KEYING_IN_C )\n#else\n#  define EFUNCS_IN_C   0\n#endif\n\n#if !defined( AES_DECRYPT )\n#  define DFUNCS_IN_C   0\n#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \\\n    || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C )\n#  define DFUNCS_IN_C   DEC_KEYING_IN_C\n#elif !defined( ASM_X86_V2 )\n#  define DFUNCS_IN_C   ( DECRYPTION_IN_C | DEC_KEYING_IN_C )\n#else\n#  define DFUNCS_IN_C   0\n#endif\n\n#define FUNCS_IN_C  ( EFUNCS_IN_C | DFUNCS_IN_C )\n\n/* END OF CONFIGURATION OPTIONS */\n\n#define RC_LENGTH   (5 * (AES_BLOCK_SIZE / 4 - 2))\n\n/* Disable or report errors on some combinations of options */\n\n#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES\n#  undef  LAST_ENC_ROUND\n#  define LAST_ENC_ROUND  NO_TABLES\n#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES\n#  undef  LAST_ENC_ROUND\n#  define LAST_ENC_ROUND  ONE_TABLE\n#endif\n\n#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE\n#  undef  ENC_UNROLL\n#  define ENC_UNROLL  NONE\n#endif\n\n#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES\n#  undef  LAST_DEC_ROUND\n#  define LAST_DEC_ROUND  NO_TABLES\n#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES\n#  undef  LAST_DEC_ROUND\n#  define LAST_DEC_ROUND  ONE_TABLE\n#endif\n\n#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE\n#  undef  DEC_UNROLL\n#  define DEC_UNROLL  NONE\n#endif\n\n#if defined( bswap32 )\n#  define aes_sw32    bswap32\n#elif defined( bswap_32 )\n#  define aes_sw32    bswap_32\n#else\n#  define brot(x,n)   (((uint32_t)(x) <<  n) | ((uint32_t)(x) >> (32 - n)))\n#  define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00))\n#endif\n\n/*  upr(x,n):  rotates bytes within words by n positions, moving bytes to\n               higher index positions with wrap around into low positions\n    ups(x,n):  moves bytes by n positions to higher index positions in\n               words but without wrap around\n    bval(x,n): extracts a byte from a word\n\n    WARNING:   The definitions given here are intended only for use with\n               unsigned variables and with shift counts that are compile\n               time constants\n*/\n\n#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN )\n#  define upr(x,n)      (((uint32_t)(x) << (8 * (n))) | ((uint32_t)(x) >> (32 - 8 * (n))))\n#  define ups(x,n)      ((uint32_t) (x) << (8 * (n)))\n#  define bval(x,n)     to_byte((x) >> (8 * (n)))\n#  define bytes2word(b0, b1, b2, b3)  \\\n        (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))\n#endif\n\n#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN )\n#  define upr(x,n)      (((uint32_t)(x) >> (8 * (n))) | ((uint32_t)(x) << (32 - 8 * (n))))\n#  define ups(x,n)      ((uint32_t) (x) >> (8 * (n)))\n#  define bval(x,n)     to_byte((x) >> (24 - 8 * (n)))\n#  define bytes2word(b0, b1, b2, b3)  \\\n        (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3))\n#endif\n\n#if defined( SAFE_IO )\n#  define word_in(x,c)    bytes2word(((const uint8_t*)(x)+4*c)[0], ((const uint8_t*)(x)+4*c)[1], \\\n                                   ((const uint8_t*)(x)+4*c)[2], ((const uint8_t*)(x)+4*c)[3])\n#  define word_out(x,c,v) { ((uint8_t*)(x)+4*c)[0] = bval(v,0); ((uint8_t*)(x)+4*c)[1] = bval(v,1); \\\n                          ((uint8_t*)(x)+4*c)[2] = bval(v,2); ((uint8_t*)(x)+4*c)[3] = bval(v,3); }\n#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER )\n#  define word_in(x,c)    (*((uint32_t*)(x)+(c)))\n#  define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v))\n#else\n#  define word_in(x,c)    aes_sw32(*((uint32_t*)(x)+(c)))\n#  define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = aes_sw32(v))\n#endif\n\n/* the finite field modular polynomial and elements */\n\n#define WPOLY   0x011b\n#define BPOLY     0x1b\n\n/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */\n\n#define gf_c1  0x80808080\n#define gf_c2  0x7f7f7f7f\n#define gf_mulx(x)  ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY))\n\n/* The following defines provide alternative definitions of gf_mulx that might\n   give improved performance if a fast 32-bit multiply is not available. Note\n   that a temporary variable u needs to be defined where gf_mulx is used.\n\n#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6))\n#define gf_c4  (0x01010101 * BPOLY)\n#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4)\n*/\n\n/* Work out which tables are needed for the different options   */\n\n#if defined( ASM_X86_V1C )\n#  if defined( ENC_ROUND )\n#    undef  ENC_ROUND\n#  endif\n#  define ENC_ROUND   FOUR_TABLES\n#  if defined( LAST_ENC_ROUND )\n#    undef  LAST_ENC_ROUND\n#  endif\n#  define LAST_ENC_ROUND  FOUR_TABLES\n#  if defined( DEC_ROUND )\n#    undef  DEC_ROUND\n#  endif\n#  define DEC_ROUND   FOUR_TABLES\n#  if defined( LAST_DEC_ROUND )\n#    undef  LAST_DEC_ROUND\n#  endif\n#  define LAST_DEC_ROUND  FOUR_TABLES\n#  if defined( KEY_SCHED )\n#    undef  KEY_SCHED\n#    define KEY_SCHED   FOUR_TABLES\n#  endif\n#endif\n\n#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C )\n#  if ENC_ROUND == ONE_TABLE\n#    define FT1_SET\n#  elif ENC_ROUND == FOUR_TABLES\n#    define FT4_SET\n#  else\n#    define SBX_SET\n#  endif\n#  if LAST_ENC_ROUND == ONE_TABLE\n#    define FL1_SET\n#  elif LAST_ENC_ROUND == FOUR_TABLES\n#    define FL4_SET\n#  elif !defined( SBX_SET )\n#    define SBX_SET\n#  endif\n#endif\n\n#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C )\n#  if DEC_ROUND == ONE_TABLE\n#    define IT1_SET\n#  elif DEC_ROUND == FOUR_TABLES\n#    define IT4_SET\n#  else\n#    define ISB_SET\n#  endif\n#  if LAST_DEC_ROUND == ONE_TABLE\n#    define IL1_SET\n#  elif LAST_DEC_ROUND == FOUR_TABLES\n#    define IL4_SET\n#  elif !defined(ISB_SET)\n#    define ISB_SET\n#  endif\n#endif\n\n#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )))\n#  if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C))\n#    if KEY_SCHED == ONE_TABLE\n#      if !defined( FL1_SET )  && !defined( FL4_SET )\n#        define LS1_SET\n#      endif\n#    elif KEY_SCHED == FOUR_TABLES\n#      if !defined( FL4_SET )\n#        define LS4_SET\n#      endif\n#    elif !defined( SBX_SET )\n#      define SBX_SET\n#    endif\n#  endif\n#  if (FUNCS_IN_C & DEC_KEYING_IN_C)\n#    if KEY_SCHED == ONE_TABLE\n#      define IM1_SET\n#    elif KEY_SCHED == FOUR_TABLES\n#      define IM4_SET\n#    elif !defined( SBX_SET )\n#      define SBX_SET\n#    endif\n#  endif\n#endif\n\n/* generic definitions of Rijndael macros that use tables    */\n\n#define no_table(x,box,vf,rf,c) bytes2word( \\\n    box[bval(vf(x,0,c),rf(0,c))], \\\n    box[bval(vf(x,1,c),rf(1,c))], \\\n    box[bval(vf(x,2,c),rf(2,c))], \\\n    box[bval(vf(x,3,c),rf(3,c))])\n\n#define one_table(x,op,tab,vf,rf,c) \\\n (     tab[bval(vf(x,0,c),rf(0,c))] \\\n  ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \\\n  ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \\\n  ^ op(tab[bval(vf(x,3,c),rf(3,c))],3))\n\n#define four_tables(x,tab,vf,rf,c) \\\n (  tab[0][bval(vf(x,0,c),rf(0,c))] \\\n  ^ tab[1][bval(vf(x,1,c),rf(1,c))] \\\n  ^ tab[2][bval(vf(x,2,c),rf(2,c))] \\\n  ^ tab[3][bval(vf(x,3,c),rf(3,c))])\n\n#define vf1(x,r,c)  (x)\n#define rf1(r,c)    (r)\n#define rf2(r,c)    ((8+r-c)&3)\n\n/* perform forward and inverse column mix operation on four bytes in long word x in */\n/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros.  */\n\n#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )))\n\n#if defined( FM4_SET )      /* not currently used */\n#  define fwd_mcol(x)       four_tables(x,t_use(f,m),vf1,rf1,0)\n#elif defined( FM1_SET )    /* not currently used */\n#  define fwd_mcol(x)       one_table(x,upr,t_use(f,m),vf1,rf1,0)\n#else\n#  define dec_fmvars        uint32_t g2\n#  define fwd_mcol(x)       (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1))\n#endif\n\n#if defined( IM4_SET )\n#  define inv_mcol(x)       four_tables(x,t_use(i,m),vf1,rf1,0)\n#elif defined( IM1_SET )\n#  define inv_mcol(x)       one_table(x,upr,t_use(i,m),vf1,rf1,0)\n#else\n#  define dec_imvars        uint32_t g2, g4, g9\n#  define inv_mcol(x)       (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \\\n                            (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1))\n#endif\n\n#if defined( FL4_SET )\n#  define ls_box(x,c)       four_tables(x,t_use(f,l),vf1,rf2,c)\n#elif defined( LS4_SET )\n#  define ls_box(x,c)       four_tables(x,t_use(l,s),vf1,rf2,c)\n#elif defined( FL1_SET )\n#  define ls_box(x,c)       one_table(x,upr,t_use(f,l),vf1,rf2,c)\n#elif defined( LS1_SET )\n#  define ls_box(x,c)       one_table(x,upr,t_use(l,s),vf1,rf2,c)\n#else\n#  define ls_box(x,c)       no_table(x,t_use(s,box),vf1,rf2,c)\n#endif\n\n#endif\n\n#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET )\n#  define ISB_SET\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/aestab.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n*/\n\n#define DO_TABLES\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"aes.h\"\n  #include \"aesopt.h\"\n#else\n  #include \"crypt/aes.h\"\n  #include \"crypt/aesopt.h\"\n#endif /* Compiler-specific includes */\n\n#if defined(STATIC_TABLES)\n\n#define sb_data(w) {\\\n    w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\\\n    w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\\\n    w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\\\n    w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\\\n    w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\\\n    w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\\\n    w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\\\n    w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\\\n    w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\\\n    w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\\\n    w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\\\n    w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\\\n    w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\\\n    w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\\\n    w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\\\n    w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\\\n    w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\\\n    w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\\\n    w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\\\n    w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\\\n    w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\\\n    w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\\\n    w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\\\n    w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\\\n    w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\\\n    w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\\\n    w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\\\n    w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\\\n    w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\\\n    w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\\\n    w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\\\n    w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }\n\n#define isb_data(w) {\\\n    w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\\\n    w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\\\n    w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\\\n    w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\\\n    w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\\\n    w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\\\n    w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\\\n    w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\\\n    w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\\\n    w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\\\n    w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\\\n    w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\\\n    w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\\\n    w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\\\n    w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\\\n    w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\\\n    w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\\\n    w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\\\n    w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\\\n    w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\\\n    w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\\\n    w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\\\n    w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\\\n    w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\\\n    w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\\\n    w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\\\n    w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\\\n    w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\\\n    w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\\\n    w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\\\n    w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\\\n    w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }\n\n#define mm_data(w) {\\\n    w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\\\n    w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\\\n    w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\\\n    w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\\\n    w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\\\n    w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\\\n    w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\\\n    w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\\\n    w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\\\n    w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\\\n    w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\\\n    w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\\\n    w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\\\n    w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\\\n    w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\\\n    w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\\\n    w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\\\n    w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\\\n    w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\\\n    w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\\\n    w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\\\n    w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\\\n    w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\\\n    w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\\\n    w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\\\n    w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\\\n    w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\\\n    w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\\\n    w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\\\n    w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\\\n    w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\\\n    w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }\n\n#define rc_data(w) {\\\n    w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\\\n    w(0x1b), w(0x36) }\n\n#define h0(x)   (x)\n\n#define w0(p)   bytes2word(p, 0, 0, 0)\n#define w1(p)   bytes2word(0, p, 0, 0)\n#define w2(p)   bytes2word(0, 0, p, 0)\n#define w3(p)   bytes2word(0, 0, 0, p)\n\n#define u0(p)   bytes2word(f2(p), p, p, f3(p))\n#define u1(p)   bytes2word(f3(p), f2(p), p, p)\n#define u2(p)   bytes2word(p, f3(p), f2(p), p)\n#define u3(p)   bytes2word(p, p, f3(p), f2(p))\n\n#define v0(p)   bytes2word(fe(p), f9(p), fd(p), fb(p))\n#define v1(p)   bytes2word(fb(p), fe(p), f9(p), fd(p))\n#define v2(p)   bytes2word(fd(p), fb(p), fe(p), f9(p))\n#define v3(p)   bytes2word(f9(p), fd(p), fb(p), fe(p))\n\n#endif\n\n#if defined(STATIC_TABLES) || !defined(FF_TABLES)\n\n#define f2(x)   ((x<<1) ^ (((x>>7) & 1) * WPOLY))\n#define f4(x)   ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))\n#define f8(x)   ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \\\n                        ^ (((x>>5) & 4) * WPOLY))\n#define f3(x)   (f2(x) ^ x)\n#define f9(x)   (f8(x) ^ x)\n#define fb(x)   (f8(x) ^ f2(x) ^ x)\n#define fd(x)   (f8(x) ^ f4(x) ^ x)\n#define fe(x)   (f8(x) ^ f4(x) ^ f2(x))\n\n#else\n\n#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)\n#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)\n#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)\n#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)\n#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)\n#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)\n\n#endif\n\n#include \"aestab.h\"\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#if defined(STATIC_TABLES)\n\n/* implemented in case of wrong call for fixed tables */\n\nAES_RETURN aes_init(void)\n{\n    return EXIT_SUCCESS;\n}\n\n#else   /*  Generate the tables for the dynamic table option */\n\n#if defined(FF_TABLES)\n\n#define gf_inv(x)   ((x) ? pow[ 255 - log[x]] : 0)\n\n#else\n\n/*  It will generally be sensible to use tables to compute finite\n    field multiplies and inverses but where memory is scarse this\n    code might sometimes be better. But it only has effect during\n    initialisation so its pretty unimportant in overall terms.\n*/\n\n/*  return 2 ^ (n - 1) where n is the bit number of the highest bit\n    set in x with x in the range 1 < x < 0x00000200.   This form is\n    used so that locals within fi can be bytes rather than words\n*/\n\nstatic uint8_t hibit(const uint32_t x)\n{   uint8_t r = (uint8_t)((x >> 1) | (x >> 2));\n\n    r |= (r >> 2);\n    r |= (r >> 4);\n    return (r + 1) >> 1;\n}\n\n/* return the inverse of the finite field element x */\n\nstatic uint8_t gf_inv(const uint8_t x)\n{   uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;\n\n    if(x < 2)\n        return x;\n\n    for( ; ; )\n    {\n        if(n1)\n            while(n2 >= n1)             /* divide polynomial p2 by p1    */\n            {\n                n2 /= n1;               /* shift smaller polynomial left */\n                p2 ^= (p1 * n2) & 0xff; /* and remove from larger one    */\n                v2 ^= v1 * n2;          /* shift accumulated value and   */\n                n2 = hibit(p2);         /* add into result               */\n            }\n        else\n            return v1;\n\n        if(n2)                          /* repeat with values swapped    */\n            while(n1 >= n2)\n            {\n                n1 /= n2;\n                p1 ^= p2 * n1;\n                v1 ^= v2 * n1;\n                n1 = hibit(p1);\n            }\n        else\n            return v2;\n    }\n}\n\n#endif\n\n/* The forward and inverse affine transformations used in the S-box */\nuint8_t fwd_affine(const uint8_t x)\n{   uint32_t w = x;\n    w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);\n    return 0x63 ^ ((w ^ (w >> 8)) & 0xff);\n}\n\nuint8_t inv_affine(const uint8_t x)\n{   uint32_t w = x;\n    w = (w << 1) ^ (w << 3) ^ (w << 6);\n    return 0x05 ^ ((w ^ (w >> 8)) & 0xff);\n}\n\nstatic int init = 0;\n\nAES_RETURN aes_init(void)\n{   uint32_t  i, w;\n\n#if defined(FF_TABLES)\n\n    uint8_t  pow[512], log[256];\n\n    if(init)\n        return EXIT_SUCCESS;\n    /*  log and power tables for GF(2^8) finite field with\n        WPOLY as modular polynomial - the simplest primitive\n        root is 0x03, used here to generate the tables\n    */\n\n    i = 0; w = 1;\n    do\n    {\n        pow[i] = (uint8_t)w;\n        pow[i + 255] = (uint8_t)w;\n        log[w] = (uint8_t)i++;\n        w ^=  (w << 1) ^ (w & 0x80 ? WPOLY : 0);\n    }\n    while (w != 1);\n\n#else\n    if(init)\n        return EXIT_SUCCESS;\n#endif\n\n    for(i = 0, w = 1; i < RC_LENGTH; ++i)\n    {\n        t_set(r,c)[i] = bytes2word(w, 0, 0, 0);\n        w = f2(w);\n    }\n\n    for(i = 0; i < 256; ++i)\n    {   uint8_t    b;\n\n        b = fwd_affine(gf_inv((uint8_t)i));\n        w = bytes2word(f2(b), b, b, f3(b));\n\n#if defined( SBX_SET )\n        t_set(s,box)[i] = b;\n#endif\n\n#if defined( FT1_SET )                 /* tables for a normal encryption round */\n        t_set(f,n)[i] = w;\n#endif\n#if defined( FT4_SET )\n        t_set(f,n)[0][i] = w;\n        t_set(f,n)[1][i] = upr(w,1);\n        t_set(f,n)[2][i] = upr(w,2);\n        t_set(f,n)[3][i] = upr(w,3);\n#endif\n        w = bytes2word(b, 0, 0, 0);\n\n#if defined( FL1_SET )            /* tables for last encryption round (may also   */\n        t_set(f,l)[i] = w;        /* be used in the key schedule)                 */\n#endif\n#if defined( FL4_SET )\n        t_set(f,l)[0][i] = w;\n        t_set(f,l)[1][i] = upr(w,1);\n        t_set(f,l)[2][i] = upr(w,2);\n        t_set(f,l)[3][i] = upr(w,3);\n#endif\n\n#if defined( LS1_SET )\t\t\t/* table for key schedule if t_set(f,l) above is*/\n        t_set(l,s)[i] = w;      /* not of the required form                     */\n#endif\n#if defined( LS4_SET )\n        t_set(l,s)[0][i] = w;\n        t_set(l,s)[1][i] = upr(w,1);\n        t_set(l,s)[2][i] = upr(w,2);\n        t_set(l,s)[3][i] = upr(w,3);\n#endif\n\n        b = gf_inv(inv_affine((uint8_t)i));\n        w = bytes2word(fe(b), f9(b), fd(b), fb(b));\n\n#if defined( IM1_SET )\t\t\t/* tables for the inverse mix column operation  */\n        t_set(i,m)[b] = w;\n#endif\n#if defined( IM4_SET )\n        t_set(i,m)[0][b] = w;\n        t_set(i,m)[1][b] = upr(w,1);\n        t_set(i,m)[2][b] = upr(w,2);\n        t_set(i,m)[3][b] = upr(w,3);\n#endif\n\n#if defined( ISB_SET )\n        t_set(i,box)[i] = b;\n#endif\n#if defined( IT1_SET )\t\t\t/* tables for a normal decryption round */\n        t_set(i,n)[i] = w;\n#endif\n#if defined( IT4_SET )\n        t_set(i,n)[0][i] = w;\n        t_set(i,n)[1][i] = upr(w,1);\n        t_set(i,n)[2][i] = upr(w,2);\n        t_set(i,n)[3][i] = upr(w,3);\n#endif\n        w = bytes2word(b, 0, 0, 0);\n#if defined( IL1_SET )\t\t\t/* tables for last decryption round */\n        t_set(i,l)[i] = w;\n#endif\n#if defined( IL4_SET )\n        t_set(i,l)[0][i] = w;\n        t_set(i,l)[1][i] = upr(w,1);\n        t_set(i,l)[2][i] = upr(w,2);\n        t_set(i,l)[3][i] = upr(w,3);\n#endif\n    }\n    init = 1;\n    return EXIT_SUCCESS;\n}\n\n/* \n   Automatic code initialisation (suggested by by Henrik S. Gaßmann)\n   based on code provided by Joe Lowe and placed in the public domain at:\n   http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc\n*/\n\n#ifdef _MSC_VER\n\n#pragma section(\".CRT$XCU\", read)\n\n__declspec(allocate(\".CRT$XCU\")) void (__cdecl *aes_startup)(void) = aes_init;\n\n#elif defined(__GNUC__)\n\nstatic void aes_startup(void) __attribute__((constructor));\n\nstatic void aes_startup(void)\n{\n    aes_init();\n}\n\n#else\n\n#pragma message( \"dynamic tables must be initialised manually on your system\" )\n\n#endif\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n"
  },
  {
    "path": "deps/cl345/crypt/aestab.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n This file contains the code for declaring the tables needed to implement\n AES. The file aesopt.h is assumed to be included before this header file.\n If there are no global variables, the definitions here can be used to put\n the AES tables in a structure so that a pointer can then be added to the\n AES context to pass them to the AES routines that need them.   If this\n facility is used, the calling program has to ensure that this pointer is\n managed appropriately.  In particular, the value of the t_dec(in,it) item\n in the table structure must be set to zero in order to ensure that the\n tables are initialised. In practice the three code sequences in aeskey.c\n that control the calls to aes_init() and the aes_init() routine itself will\n have to be changed for a specific implementation. If global variables are\n available it will generally be preferable to use them with the precomputed\n STATIC_TABLES option that uses static global tables.\n\n The following defines can be used to control the way the tables\n are defined, initialised and used in embedded environments that\n require special features for these purposes\n\n    the 't_dec' construction is used to declare fixed table arrays\n    the 't_set' construction is used to set fixed table values\n    the 't_use' construction is used to access fixed table values\n\n    256 byte tables:\n\n        t_xxx(s,box)    => forward S box\n        t_xxx(i,box)    => inverse S box\n\n    256 32-bit word OR 4 x 256 32-bit word tables:\n\n        t_xxx(f,n)      => forward normal round\n        t_xxx(f,l)      => forward last round\n        t_xxx(i,n)      => inverse normal round\n        t_xxx(i,l)      => inverse last round\n        t_xxx(l,s)      => key schedule table\n        t_xxx(i,m)      => key schedule table\n\n    Other variables and tables:\n\n        t_xxx(r,c)      => the rcon table\n*/\n\n#if !defined( _AESTAB_H )\n#define _AESTAB_H\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#define t_dec(m,n) t_##m##n\n#define t_set(m,n) t_##m##n\n#define t_use(m,n) t_##m##n\n\n#if defined(STATIC_TABLES)\n#  if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ ))\n/*   make tables far data to avoid using too much DGROUP space (PG) */\n#    define CONST const far\n#  else\n#    define CONST const\n#  endif\n#else\n#  define CONST\n#endif\n\n#if defined(DO_TABLES)\n#  define EXTERN\n#else\n#  define EXTERN extern\n#endif\n\n#if defined(_MSC_VER) && defined(TABLE_ALIGN)\n#define ALIGN __declspec(align(TABLE_ALIGN))\n#else\n#define ALIGN\n#endif\n\n#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 )\n#  define XP_DIR __cdecl\n#else\n#  define XP_DIR\n#endif\n\n#if defined(DO_TABLES) && defined(STATIC_TABLES)\n#define d_1(t,n,b,e)       EXTERN ALIGN CONST XP_DIR t n[256]    =   b(e)\n#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) }\nEXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH] = rc_data(w0);\n#else\n#define d_1(t,n,b,e)       EXTERN ALIGN CONST XP_DIR t n[256]\n#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256]\nEXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH];\n#endif\n\n#if defined( SBX_SET )\n    d_1(uint8_t, t_dec(s,box), sb_data, h0);\n#endif\n#if defined( ISB_SET )\n    d_1(uint8_t, t_dec(i,box), isb_data, h0);\n#endif\n\n#if defined( FT1_SET )\n    d_1(uint32_t, t_dec(f,n), sb_data, u0);\n#endif\n#if defined( FT4_SET )\n    d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);\n#endif\n\n#if defined( FL1_SET )\n    d_1(uint32_t, t_dec(f,l), sb_data, w0);\n#endif\n#if defined( FL4_SET )\n    d_4(uint32_t, t_dec(f,l), sb_data, w0, w1, w2, w3);\n#endif\n\n#if defined( IT1_SET )\n    d_1(uint32_t, t_dec(i,n), isb_data, v0);\n#endif\n#if defined( IT4_SET )\n    d_4(uint32_t, t_dec(i,n), isb_data, v0, v1, v2, v3);\n#endif\n\n#if defined( IL1_SET )\n    d_1(uint32_t, t_dec(i,l), isb_data, w0);\n#endif\n#if defined( IL4_SET )\n    d_4(uint32_t, t_dec(i,l), isb_data, w0, w1, w2, w3);\n#endif\n\n#if defined( LS1_SET )\n#if defined( FL1_SET )\n#undef  LS1_SET\n#else\n    d_1(uint32_t, t_dec(l,s), sb_data, w0);\n#endif\n#endif\n\n#if defined( LS4_SET )\n#if defined( FL4_SET )\n#undef  LS4_SET\n#else\n    d_4(uint32_t, t_dec(l,s), sb_data, w0, w1, w2, w3);\n#endif\n#endif\n\n#if defined( IM1_SET )\n    d_1(uint32_t, t_dec(i,m), mm_data, v0);\n#endif\n#if defined( IM4_SET )\n    d_4(uint32_t, t_dec(i,m), mm_data, v0, v1, v2, v3);\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/brg_endian.h",
    "content": "/* Replacement for the original brg_endian.h, used because cryptlib contains \n   its own endianness-management mechanisms that replace the ones in that \n   file */\n\n#ifndef _BRG_ENDIAN_H\n#define _BRG_ENDIAN_H\n\n#include \"crypt.h\"\n\n#define IS_BIG_ENDIAN\t\t4321\n#define IS_LITTLE_ENDIAN\t1234\n\n#ifdef DATA_LITTLEENDIAN\n  #define PLATFORM_BYTE_ORDER\tIS_LITTLE_ENDIAN\n#else\n  #define PLATFORM_BYTE_ORDER\tIS_BIG_ENDIAN\n#endif\n\n#endif /* _BRG_ENDIAN_H */\n"
  },
  {
    "path": "deps/cl345/crypt/brg_types.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n The unsigned integer types defined here are of the form uint_<nn>t where\n <nn> is the length of the type; for example, the unsigned 32-bit type is\n 'uint32_t'.  These are NOT the same as the 'C99 integer types' that are\n defined in the inttypes.h and stdint.h headers since attempts to use these\n types have shown that support for them is still highly variable.  However,\n since the latter are of the form uint<nn>_t, a regular expression search\n and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\\1_t')\n can be used to convert the types used here to the C99 standard types.\n*/\n\n#ifndef _BRG_TYPES_H\n#define _BRG_TYPES_H\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#include <limits.h>\n#if 0\t/* pcg */\n#include <stdint.h>\n#endif /* 0 */\n\n#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )\n  #include <stddef.h>\n  #define ptrint_t\t\tintptr_t\n#elif defined( __ECOS__ )\n  #define intptr_t unsigned int\n  #define ptrint_t intptr_t\n#elif ( defined( __GNUC__ ) && ( __GNUC__ >= 3 ) ) || \\\n\t  defined( __clang__ )\n  #if defined( __VxWorks__ )\n\t /* Wind River's toolchain doesn't include stdint.h */\n\t#define ptrint_t int\n  #else\n\t#include <stdint.h>\n\t#define ptrint_t\tintptr_t\n\t#define HAS_STDINT\n  #endif /* VxWorks vs. everything else */\n#elif defined ( __HAIKU__ )\n  #include <stdint.h>\n  #define ptrint_t\t\tint\n  #define HAS_STDINT\n#else\n  #define ptrint_t\t\tint\n#endif /* System-specific stdint.h usage */\n\n/* The stdint types may have been included via another path, so we check for\n   other signs that they're present */\n#if defined( __int8_t_defined ) \n  #define HAS_STDINT\n#endif /* stdint.h probably present */\n\n#ifndef HAS_STDINT\n  typedef unsigned char uint8_t;\t\t\t/* pcg */\n  typedef unsigned short uint16_t;\t\t\t/* GCM - pcg */\n#endif /* uint8_t already defined - pcg */\n\n#ifndef BRG_UI32\n#  define BRG_UI32\n#  if UINT_MAX == 4294967295u\n#    define li_32(h) 0x##h##u\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned int uint32_t;\t\t/* AES - pcg */\n#    endif /* HAS_STDINT */\n#  elif ULONG_MAX == 4294967295u\n#    define li_32(h) 0x##h##ul\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned long uint32_t;\t\t/* AES - pcg */\n#    endif /* HAS_STDINT */\n#  elif defined( _CRAY )\n  /* USE_AES is undefined on Crays, however we define a dummy data type\n     to get the code to compile - pcg */\n/*#error Crays don't support 32-bit data types, this code won't compile on a Cray*/\n\ttypedef   unsigned int     uint32_t;\n#  else\n#    error Please define uint32_t as a 32-bit unsigned integer type in brg_types.h\n#  endif\n#endif\n\n#ifndef BRG_UI64\n#  if defined( __BORLANDC__ ) && !defined( __MSDOS__ )\n#    define BRG_UI64\n#    define li_64(h) 0x##h##ui64\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned __int64 uint64_t;\t/* AES-GCM - pcg */\n#    endif /* HAS_STDINT */\n#  elif defined( _MSC_VER ) && ( _MSC_VER < 1300 )    /* 1300 == VC++ 7.0 */\n#    define BRG_UI64\n#    define li_64(h) 0x##h##ui64\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned __int64 uint64_t;\t\t/* AES-GCM - pcg */\n#    endif /* HAS_STDINT */\n#  elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful\n#    define BRG_UI64\n#    define li_64(h) 0x##h##ull\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned long long uint64_t;\t/* AES-GCM - pcg */\n#    endif /* HAS_STDINT */\n#  elif defined( __MVS__ )\n#    define BRG_UI64\n#    define li_64(h) 0x##h##ull\n#    ifndef HAS_STDINT\n\t\ttypedef unsigned long long uint64_t;\t/* AES-GCM - pcg */\n#    endif /* HAS_STDINT */\n#  elif defined( UINT_MAX ) && UINT_MAX > 4294967295u\n#    if UINT_MAX == 18446744073709551615u\n#      define BRG_UI64\n#      define li_64(h) 0x##h##u\n#      ifndef HAS_STDINT\n\t\ttypedef unsigned int uint64_t;\t\t/* AES-GCM - pcg */\n#      endif /* HAS_STDINT */\n#    endif\n#  elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u\n#    if ULONG_MAX == 18446744073709551615ul\n#      define BRG_UI64\n#      define li_64(h) 0x##h##ul\n\t#ifndef _UINT64_T\t/* Apple define their own version - pcg */\n\t   typedef unsigned long uint64_t;\t\t/* AES-GCM - pcg */\n\t#endif /* !_UINT64_T */\n#    endif\n#  elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u\n#    if ULLONG_MAX == 18446744073709551615ull\n#      define BRG_UI64\n#      define li_64(h) 0x##h##ull\n#      ifndef HAS_STDINT\n\t\ttypedef unsigned long long uint64_t;/* AES-GCM - pcg */\n#      endif /* HAS_STDINT */\n#    endif\n#  elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u\n#    if ULONG_LONG_MAX == 18446744073709551615ull\n#      define BRG_UI64\n#      define li_64(h) 0x##h##ull\n#      ifndef HAS_STDINT\n\t\ttypedef unsigned long long uint64_t;\t/* AES-GCM - pcg */\n#      endif /* HAS_STDINT */\n#    endif\n#  endif\n#endif\n\n#if !defined( BRG_UI64 )\n#  if defined( NEED_UINT_64T )\n#    error Please define uint64_t as an unsigned 64 bit type in brg_types.h\n#  endif\n#endif\n\n#ifndef RETURN_VALUES\n#  define RETURN_VALUES\n#  if defined( DLL_EXPORT )\n#    if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )\n#      define VOID_RETURN    __declspec( dllexport ) void __stdcall\n#      define INT_RETURN     __declspec( dllexport ) int  __stdcall\n#    elif defined( __GNUC__ )\n#      define VOID_RETURN    __declspec( __dllexport__ ) void\n#      define INT_RETURN     __declspec( __dllexport__ ) int\n#    else\n#      error Use of the DLL is only available on the Microsoft, Intel and GCC compilers\n#    endif\n#  elif defined( DLL_IMPORT )\n#    if defined( _MSC_VER ) || defined ( __INTEL_COMPILER )\n#      define VOID_RETURN    __declspec( dllimport ) void __stdcall\n#      define INT_RETURN     __declspec( dllimport ) int  __stdcall\n#    elif defined( __GNUC__ )\n#      define VOID_RETURN    __declspec( __dllimport__ ) void\n#      define INT_RETURN     __declspec( __dllimport__ ) int\n#    else\n#      error Use of the DLL is only available on the Microsoft, Intel and GCC compilers\n#    endif\n#  elif defined( __WATCOMC__ )\n#    define VOID_RETURN  void __cdecl\n#    define INT_RETURN   int  __cdecl\n#  else\n#    define VOID_RETURN  void\n#    define INT_RETURN   int\n#  endif\n#endif\n\n/*\tThese defines are used to detect and set the memory alignment of pointers.\n    Note that offsets are in bytes.\n\n    ALIGN_OFFSET(x,n)\t\t\treturn the positive or zero offset of \n                                the memory addressed by the pointer 'x' \n                                from an address that is aligned on an \n                                'n' byte boundary ('n' is a power of 2)\n\n    ALIGN_FLOOR(x,n)\t\t\treturn a pointer that points to memory\n                                that is aligned on an 'n' byte boundary \n                                and is not higher than the memory address\n                                pointed to by 'x' ('n' is a power of 2)\n\n    ALIGN_CEIL(x,n)\t\t\t\treturn a pointer that points to memory\n                                that is aligned on an 'n' byte boundary \n                                and is not lower than the memory address\n                                pointed to by 'x' ('n' is a power of 2)\n*/\n\n#define ALIGN_OFFSET(x,n)\t(((ptrint_t)(x)) & ((n) - 1))\n#define ALIGN_FLOOR(x,n)\t((uint8_t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1)))\n#define ALIGN_CEIL(x,n)\t\t((uint8_t*)(x) + (-((ptrint_t)(x)) & ((n) - 1)))\n\n/*  These defines are used to declare buffers in a way that allows\n    faster operations on longer variables to be used.  In all these\n    defines 'size' must be a power of 2 and >= 8. NOTE that the \n    buffer size is in bytes but the type length is in bits\n\n    UNIT_TYPEDEF(x,size)        declares a variable 'x' of length \n                                'size' bits\n\n    BUFR_TYPEDEF(x,size,bsize)  declares a buffer 'x' of length 'bsize' \n                                bytes defined as an array of variables\n                                each of 'size' bits (bsize must be a \n                                multiple of size / 8)\n\n    UNIT_CAST(x,size)           casts a variable to a type of \n                                length 'size' bits\n\n    UPTR_CAST(x,size)           casts a pointer to a pointer to a \n                                varaiable of length 'size' bits\n*/\n\n#define UI_TYPE(size)               uint##size##_t\n#define UNIT_TYPEDEF(x,size)        typedef UI_TYPE(size) x\n#define BUFR_TYPEDEF(x,size,bsize)  typedef UI_TYPE(size) x[bsize / (size >> 3)]\n#define UNIT_CAST(x,size)           ((UI_TYPE(size) )(x))  \n#define UPTR_CAST(x,size)           ((UI_TYPE(size)*)(x))\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/cast.h",
    "content": "/* crypto/cast/cast.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_CAST_H\n#define HEADER_CAST_H\n\n#ifndef _OSCONFIG_DEFINED\t\t/* pcg */\n  #if defined( INC_ALL )\n\t#include \"osconfig.h\"\n  #else\n\t#include \"crypt/osconfig.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _OSCONFIG_DEFINED */\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef NO_CAST\n#error CAST is disabled.\n#endif\n\n#define CAST_ENCRYPT\t1\n#define CAST_DECRYPT\t0\n\n#define CAST_LONG unsigned long\n\n#define CAST_BLOCK\t8\n#define CAST_KEY_LENGTH\t16\n\ntypedef struct cast_key_st\n\t{\n\tCAST_LONG data[32];\n\tint short_key;\t/* Use reduced rounds for short key */\n\t} CAST_KEY;\n\n \nvoid CAST_set_key(CAST_KEY *key, int len, const unsigned char *data);\nvoid ASM_EXPORT CAST_ecb_encrypt(const unsigned char *in,unsigned char *out,CAST_KEY *key,\n\t\t      int enc);\t\t\t\t\t\t\t\t\t\t\t/* pcg */\nvoid ASM_EXPORT CAST_encrypt(CAST_LONG *data,CAST_KEY *key);\t/* pcg */\nvoid ASM_EXPORT CAST_decrypt(CAST_LONG *data,CAST_KEY *key);\t/* pcg */\nvoid ASM_EXPORT CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t\t      CAST_KEY *ks, unsigned char *iv, int enc);\t\t/* pcg */\nvoid ASM_EXPORT CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,\n\t\t\tlong length, CAST_KEY *schedule, unsigned char *ivec,\n\t\t\tint *num, int enc);\t\t\t\t\t\t\t\t\t/* pcg */\nvoid ASM_EXPORT CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, \n\t\t\tlong length, CAST_KEY *schedule, unsigned char *ivec,\n\t\t\tint *num);\t\t\t\t\t\t\t\t\t\t\t/* pcg */\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/castecb.c",
    "content": "/* crypto/cast/c_ecb.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"cast.h\"\n  #include \"castlcl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/cast.h\"\n  #include \"crypt/castlcl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CAST\n\nvoid CAST_ecb_encrypt(const unsigned char *in, unsigned char *out,\n\t\t      CAST_KEY *ks, int enc)\n\t{\n\tCAST_LONG l,d[2];\n\n\tn2l(in,l); d[0]=l;\n\tn2l(in,l); d[1]=l;\n\tif (enc)\n\t\tCAST_encrypt(d,ks);\n\telse\n\t\tCAST_decrypt(d,ks);\n\tl=d[0]; l2n(l,out);\n\tl=d[1]; l2n(l,out);\n\tl=d[0]=d[1]=0;\n\t}\n#endif /* USE_CAST */\n"
  },
  {
    "path": "deps/cl345/crypt/castenc.c",
    "content": "/* crypto/cast/c_enc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"cast.h\"\n  #include \"castlcl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/cast.h\"\n  #include \"crypt/castlcl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CAST\n\nvoid CAST_encrypt(CAST_LONG *data, CAST_KEY *key)\n\t{\n\tregister CAST_LONG l,r,*k,t;\n\n\tk= &(key->data[0]);\n\tl=data[0];\n\tr=data[1];\n\n\tE_CAST( 0,k,l,r,+,^,-);\n\tE_CAST( 1,k,r,l,^,-,+);\n\tE_CAST( 2,k,l,r,-,+,^);\n\tE_CAST( 3,k,r,l,+,^,-);\n\tE_CAST( 4,k,l,r,^,-,+);\n\tE_CAST( 5,k,r,l,-,+,^);\n\tE_CAST( 6,k,l,r,+,^,-);\n\tE_CAST( 7,k,r,l,^,-,+);\n\tE_CAST( 8,k,l,r,-,+,^);\n\tE_CAST( 9,k,r,l,+,^,-);\n\tE_CAST(10,k,l,r,^,-,+);\n\tE_CAST(11,k,r,l,-,+,^);\n\tif(!key->short_key)\n\t    {\n\t    E_CAST(12,k,l,r,+,^,-);\n\t    E_CAST(13,k,r,l,^,-,+);\n\t    E_CAST(14,k,l,r,-,+,^);\n\t    E_CAST(15,k,r,l,+,^,-);\n\t    }\n\n\tdata[1]=l&0xffffffffL;\n\tdata[0]=r&0xffffffffL;\n\t}\n\nvoid CAST_decrypt(CAST_LONG *data, CAST_KEY *key)\n\t{\n\tregister CAST_LONG l,r,*k,t;\n\n\tk= &(key->data[0]);\n\tl=data[0];\n\tr=data[1];\n\n\tif(!key->short_key)\n\t    {\n\t    E_CAST(15,k,l,r,+,^,-);\n\t    E_CAST(14,k,r,l,-,+,^);\n\t    E_CAST(13,k,l,r,^,-,+);\n\t    E_CAST(12,k,r,l,+,^,-);\n\t    }\n\tE_CAST(11,k,l,r,-,+,^);\n\tE_CAST(10,k,r,l,^,-,+);\n\tE_CAST( 9,k,l,r,+,^,-);\n\tE_CAST( 8,k,r,l,-,+,^);\n\tE_CAST( 7,k,l,r,^,-,+);\n\tE_CAST( 6,k,r,l,+,^,-);\n\tE_CAST( 5,k,l,r,-,+,^);\n\tE_CAST( 4,k,r,l,^,-,+);\n\tE_CAST( 3,k,l,r,+,^,-);\n\tE_CAST( 2,k,r,l,-,+,^);\n\tE_CAST( 1,k,l,r,^,-,+);\n\tE_CAST( 0,k,r,l,+,^,-);\n\n\tdata[1]=l&0xffffffffL;\n\tdata[0]=r&0xffffffffL;\n\t}\n\nvoid CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t     CAST_KEY *ks, unsigned char *iv, int enc)\n\t{\n\tregister CAST_LONG tin0,tin1;\n\tregister CAST_LONG tout0,tout1,xor0,xor1;\n\tregister long l=length;\n\tCAST_LONG tin[2];\n\n\tif (enc)\n\t\t{\n\t\tn2l(iv,tout0);\n\t\tn2l(iv,tout1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tn2l(in,tin0);\n\t\t\tn2l(in,tin1);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tCAST_encrypt(tin,ks);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\t\t\tl2n(tout0,out);\n\t\t\tl2n(tout1,out);\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tn2ln(in,tin0,tin1,l+8);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tCAST_encrypt(tin,ks);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\t\t\tl2n(tout0,out);\n\t\t\tl2n(tout1,out);\n\t\t\t}\n\t\tl2n(tout0,iv);\n\t\tl2n(tout1,iv);\n\t\t}\n\telse\n\t\t{\n\t\tn2l(iv,xor0);\n\t\tn2l(iv,xor1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tn2l(in,tin0);\n\t\t\tn2l(in,tin1);\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tCAST_decrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2n(tout0,out);\n\t\t\tl2n(tout1,out);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tn2l(in,tin0);\n\t\t\tn2l(in,tin1);\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tCAST_decrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2nn(tout0,tout1,out,l+8);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tl2n(xor0,iv);\n\t\tl2n(xor1,iv);\n\t\t}\n\ttin0=tin1=tout0=tout1=xor0=xor1=0;\n\ttin[0]=tin[1]=0;\n\t}\n#endif /* USE_CAST */\n"
  },
  {
    "path": "deps/cl345/crypt/castlcl.h",
    "content": "/* crypto/cast/cast_lcl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifdef WIN32\n#include <stdlib.h>\n#endif\n\n#undef c2l\n#define c2l(c,l)\t(l =((unsigned long)(*((c)++)))    , \\\n\t\t\t l|=((unsigned long)(*((c)++)))<< 8L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<16L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<24L)\n\n/* NOTE - c is not incremented as per c2l */\n#undef c2ln\n#define c2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))<<24L; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<<16L; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<< 8L; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))));     \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))<<24L; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<<16L; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<< 8L; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))));     \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef l2c\n#define l2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24L)&0xff))\n\n/* NOTE - c is not incremented as per l2c */\n#undef l2cn\n#define l2cn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per n2l */\n#define n2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per l2n */\n#define l2nn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef n2l\n#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \\\n                         l|=((unsigned long)(*((c)++)))<<16L, \\\n                         l|=((unsigned long)(*((c)++)))<< 8L, \\\n                         l|=((unsigned long)(*((c)++))))\n\n#undef l2n\n#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)     )&0xff))\n\n#if defined(WIN32) && defined(_MSC_VER)\n#define ROTL(a,n)     (_lrotl(a,n))\n#else\n#define ROTL(a,n)     ((((a)<<(n))&0xffffffffL)|((a)>>(32-(n))))\n#endif\n\n#define C_M    0x3fc\n#define C_0    22L\n#define C_1    14L\n#define C_2     6L\n#define C_3     2L /* left shift */\n\n/* The rotate has an extra 16 added to it to help the x86 asm */\n#if defined(CAST_PTR)\n#define E_CAST(n,key,L,R,OP1,OP2,OP3) \\\n\t{ \\\n\tint i; \\\n\tt=(key[n*2] OP1 R)&0xffffffffL; \\\n\ti=key[n*2+1]; \\\n\tt=ROTL(t,i); \\\n\tL^= (((((*(CAST_LONG *)((unsigned char *) \\\n\t\t\tCAST_S_table0+((t>>C_2)&C_M)) OP2 \\\n\t\t*(CAST_LONG *)((unsigned char *) \\\n\t\t\tCAST_S_table1+((t<<C_3)&C_M)))&0xffffffffL) OP3 \\\n\t\t*(CAST_LONG *)((unsigned char *) \\\n\t\t\tCAST_S_table2+((t>>C_0)&C_M)))&0xffffffffL) OP1 \\\n\t\t*(CAST_LONG *)((unsigned char *) \\\n\t\t\tCAST_S_table3+((t>>C_1)&C_M)))&0xffffffffL; \\\n\t}\n#elif defined(CAST_PTR2)\n#define E_CAST(n,key,L,R,OP1,OP2,OP3) \\\n\t{ \\\n\tint i; \\\n\tCAST_LONG u,v,w; \\\n\tw=(key[n*2] OP1 R)&0xffffffffL; \\\n\ti=key[n*2+1]; \\\n\tw=ROTL(w,i); \\\n\tu=w>>C_2; \\\n\tv=w<<C_3; \\\n\tu&=C_M; \\\n\tv&=C_M; \\\n\tt= *(CAST_LONG *)((unsigned char *)CAST_S_table0+u); \\\n\tu=w>>C_0; \\\n\tt=(t OP2 *(CAST_LONG *)((unsigned char *)CAST_S_table1+v))&0xffffffffL;\\\n\tv=w>>C_1; \\\n\tu&=C_M; \\\n\tv&=C_M; \\\n\tt=(t OP3 *(CAST_LONG *)((unsigned char *)CAST_S_table2+u)&0xffffffffL);\\\n\tt=(t OP1 *(CAST_LONG *)((unsigned char *)CAST_S_table3+v)&0xffffffffL);\\\n\tL^=(t&0xffffffff); \\\n\t}\n#else\n#define E_CAST(n,key,L,R,OP1,OP2,OP3) \\\n\t{ \\\n\tCAST_LONG a,b,c,d; \\\n\tt=(key[n*2] OP1 R)&0xffffffff; \\\n\tt=ROTL(t,(key[n*2+1])); \\\n\ta=CAST_S_table0[(t>> 8)&0xff]; \\\n\tb=CAST_S_table1[(t    )&0xff]; \\\n\tc=CAST_S_table2[(t>>24)&0xff]; \\\n\td=CAST_S_table3[(t>>16)&0xff]; \\\n\tL^=(((((a OP2 b)&0xffffffffL) OP3 c)&0xffffffffL) OP1 d)&0xffffffffL; \\\n\t}\n#endif\n\nextern const CAST_LONG ASM_EXPORT CAST_S_table0[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table1[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table2[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table3[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table4[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table5[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table6[256];\t/* pcg */\nextern const CAST_LONG ASM_EXPORT CAST_S_table7[256];\t/* pcg */\n"
  },
  {
    "path": "deps/cl345/crypt/castsbox.h",
    "content": "/* crypto/cast/cast_s.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\nconst CAST_LONG ASM_EXPORT CAST_S_table0[256]={\t\t/* pcg */\n\t0x30fb40d4,0x9fa0ff0b,0x6beccd2f,0x3f258c7a,\n\t0x1e213f2f,0x9c004dd3,0x6003e540,0xcf9fc949,\n\t0xbfd4af27,0x88bbbdb5,0xe2034090,0x98d09675,\n\t0x6e63a0e0,0x15c361d2,0xc2e7661d,0x22d4ff8e,\n\t0x28683b6f,0xc07fd059,0xff2379c8,0x775f50e2,\n\t0x43c340d3,0xdf2f8656,0x887ca41a,0xa2d2bd2d,\n\t0xa1c9e0d6,0x346c4819,0x61b76d87,0x22540f2f,\n\t0x2abe32e1,0xaa54166b,0x22568e3a,0xa2d341d0,\n\t0x66db40c8,0xa784392f,0x004dff2f,0x2db9d2de,\n\t0x97943fac,0x4a97c1d8,0x527644b7,0xb5f437a7,\n\t0xb82cbaef,0xd751d159,0x6ff7f0ed,0x5a097a1f,\n\t0x827b68d0,0x90ecf52e,0x22b0c054,0xbc8e5935,\n\t0x4b6d2f7f,0x50bb64a2,0xd2664910,0xbee5812d,\n\t0xb7332290,0xe93b159f,0xb48ee411,0x4bff345d,\n\t0xfd45c240,0xad31973f,0xc4f6d02e,0x55fc8165,\n\t0xd5b1caad,0xa1ac2dae,0xa2d4b76d,0xc19b0c50,\n\t0x882240f2,0x0c6e4f38,0xa4e4bfd7,0x4f5ba272,\n\t0x564c1d2f,0xc59c5319,0xb949e354,0xb04669fe,\n\t0xb1b6ab8a,0xc71358dd,0x6385c545,0x110f935d,\n\t0x57538ad5,0x6a390493,0xe63d37e0,0x2a54f6b3,\n\t0x3a787d5f,0x6276a0b5,0x19a6fcdf,0x7a42206a,\n\t0x29f9d4d5,0xf61b1891,0xbb72275e,0xaa508167,\n\t0x38901091,0xc6b505eb,0x84c7cb8c,0x2ad75a0f,\n\t0x874a1427,0xa2d1936b,0x2ad286af,0xaa56d291,\n\t0xd7894360,0x425c750d,0x93b39e26,0x187184c9,\n\t0x6c00b32d,0x73e2bb14,0xa0bebc3c,0x54623779,\n\t0x64459eab,0x3f328b82,0x7718cf82,0x59a2cea6,\n\t0x04ee002e,0x89fe78e6,0x3fab0950,0x325ff6c2,\n\t0x81383f05,0x6963c5c8,0x76cb5ad6,0xd49974c9,\n\t0xca180dcf,0x380782d5,0xc7fa5cf6,0x8ac31511,\n\t0x35e79e13,0x47da91d0,0xf40f9086,0xa7e2419e,\n\t0x31366241,0x051ef495,0xaa573b04,0x4a805d8d,\n\t0x548300d0,0x00322a3c,0xbf64cddf,0xba57a68e,\n\t0x75c6372b,0x50afd341,0xa7c13275,0x915a0bf5,\n\t0x6b54bfab,0x2b0b1426,0xab4cc9d7,0x449ccd82,\n\t0xf7fbf265,0xab85c5f3,0x1b55db94,0xaad4e324,\n\t0xcfa4bd3f,0x2deaa3e2,0x9e204d02,0xc8bd25ac,\n\t0xeadf55b3,0xd5bd9e98,0xe31231b2,0x2ad5ad6c,\n\t0x954329de,0xadbe4528,0xd8710f69,0xaa51c90f,\n\t0xaa786bf6,0x22513f1e,0xaa51a79b,0x2ad344cc,\n\t0x7b5a41f0,0xd37cfbad,0x1b069505,0x41ece491,\n\t0xb4c332e6,0x032268d4,0xc9600acc,0xce387e6d,\n\t0xbf6bb16c,0x6a70fb78,0x0d03d9c9,0xd4df39de,\n\t0xe01063da,0x4736f464,0x5ad328d8,0xb347cc96,\n\t0x75bb0fc3,0x98511bfb,0x4ffbcc35,0xb58bcf6a,\n\t0xe11f0abc,0xbfc5fe4a,0xa70aec10,0xac39570a,\n\t0x3f04442f,0x6188b153,0xe0397a2e,0x5727cb79,\n\t0x9ceb418f,0x1cacd68d,0x2ad37c96,0x0175cb9d,\n\t0xc69dff09,0xc75b65f0,0xd9db40d8,0xec0e7779,\n\t0x4744ead4,0xb11c3274,0xdd24cb9e,0x7e1c54bd,\n\t0xf01144f9,0xd2240eb1,0x9675b3fd,0xa3ac3755,\n\t0xd47c27af,0x51c85f4d,0x56907596,0xa5bb15e6,\n\t0x580304f0,0xca042cf1,0x011a37ea,0x8dbfaadb,\n\t0x35ba3e4a,0x3526ffa0,0xc37b4d09,0xbc306ed9,\n\t0x98a52666,0x5648f725,0xff5e569d,0x0ced63d0,\n\t0x7c63b2cf,0x700b45e1,0xd5ea50f1,0x85a92872,\n\t0xaf1fbda7,0xd4234870,0xa7870bf3,0x2d3b4d79,\n\t0x42e04198,0x0cd0ede7,0x26470db8,0xf881814c,\n\t0x474d6ad7,0x7c0c5e5c,0xd1231959,0x381b7298,\n\t0xf5d2f4db,0xab838653,0x6e2f1e23,0x83719c9e,\n\t0xbd91e046,0x9a56456e,0xdc39200c,0x20c8c571,\n\t0x962bda1c,0xe1e696ff,0xb141ab08,0x7cca89b9,\n\t0x1a69e783,0x02cc4843,0xa2f7c579,0x429ef47d,\n\t0x427b169c,0x5ac9f049,0xdd8f0f00,0x5c8165bf,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table1[256]={\t\t/* pcg */\n\t0x1f201094,0xef0ba75b,0x69e3cf7e,0x393f4380,\n\t0xfe61cf7a,0xeec5207a,0x55889c94,0x72fc0651,\n\t0xada7ef79,0x4e1d7235,0xd55a63ce,0xde0436ba,\n\t0x99c430ef,0x5f0c0794,0x18dcdb7d,0xa1d6eff3,\n\t0xa0b52f7b,0x59e83605,0xee15b094,0xe9ffd909,\n\t0xdc440086,0xef944459,0xba83ccb3,0xe0c3cdfb,\n\t0xd1da4181,0x3b092ab1,0xf997f1c1,0xa5e6cf7b,\n\t0x01420ddb,0xe4e7ef5b,0x25a1ff41,0xe180f806,\n\t0x1fc41080,0x179bee7a,0xd37ac6a9,0xfe5830a4,\n\t0x98de8b7f,0x77e83f4e,0x79929269,0x24fa9f7b,\n\t0xe113c85b,0xacc40083,0xd7503525,0xf7ea615f,\n\t0x62143154,0x0d554b63,0x5d681121,0xc866c359,\n\t0x3d63cf73,0xcee234c0,0xd4d87e87,0x5c672b21,\n\t0x071f6181,0x39f7627f,0x361e3084,0xe4eb573b,\n\t0x602f64a4,0xd63acd9c,0x1bbc4635,0x9e81032d,\n\t0x2701f50c,0x99847ab4,0xa0e3df79,0xba6cf38c,\n\t0x10843094,0x2537a95e,0xf46f6ffe,0xa1ff3b1f,\n\t0x208cfb6a,0x8f458c74,0xd9e0a227,0x4ec73a34,\n\t0xfc884f69,0x3e4de8df,0xef0e0088,0x3559648d,\n\t0x8a45388c,0x1d804366,0x721d9bfd,0xa58684bb,\n\t0xe8256333,0x844e8212,0x128d8098,0xfed33fb4,\n\t0xce280ae1,0x27e19ba5,0xd5a6c252,0xe49754bd,\n\t0xc5d655dd,0xeb667064,0x77840b4d,0xa1b6a801,\n\t0x84db26a9,0xe0b56714,0x21f043b7,0xe5d05860,\n\t0x54f03084,0x066ff472,0xa31aa153,0xdadc4755,\n\t0xb5625dbf,0x68561be6,0x83ca6b94,0x2d6ed23b,\n\t0xeccf01db,0xa6d3d0ba,0xb6803d5c,0xaf77a709,\n\t0x33b4a34c,0x397bc8d6,0x5ee22b95,0x5f0e5304,\n\t0x81ed6f61,0x20e74364,0xb45e1378,0xde18639b,\n\t0x881ca122,0xb96726d1,0x8049a7e8,0x22b7da7b,\n\t0x5e552d25,0x5272d237,0x79d2951c,0xc60d894c,\n\t0x488cb402,0x1ba4fe5b,0xa4b09f6b,0x1ca815cf,\n\t0xa20c3005,0x8871df63,0xb9de2fcb,0x0cc6c9e9,\n\t0x0beeff53,0xe3214517,0xb4542835,0x9f63293c,\n\t0xee41e729,0x6e1d2d7c,0x50045286,0x1e6685f3,\n\t0xf33401c6,0x30a22c95,0x31a70850,0x60930f13,\n\t0x73f98417,0xa1269859,0xec645c44,0x52c877a9,\n\t0xcdff33a6,0xa02b1741,0x7cbad9a2,0x2180036f,\n\t0x50d99c08,0xcb3f4861,0xc26bd765,0x64a3f6ab,\n\t0x80342676,0x25a75e7b,0xe4e6d1fc,0x20c710e6,\n\t0xcdf0b680,0x17844d3b,0x31eef84d,0x7e0824e4,\n\t0x2ccb49eb,0x846a3bae,0x8ff77888,0xee5d60f6,\n\t0x7af75673,0x2fdd5cdb,0xa11631c1,0x30f66f43,\n\t0xb3faec54,0x157fd7fa,0xef8579cc,0xd152de58,\n\t0xdb2ffd5e,0x8f32ce19,0x306af97a,0x02f03ef8,\n\t0x99319ad5,0xc242fa0f,0xa7e3ebb0,0xc68e4906,\n\t0xb8da230c,0x80823028,0xdcdef3c8,0xd35fb171,\n\t0x088a1bc8,0xbec0c560,0x61a3c9e8,0xbca8f54d,\n\t0xc72feffa,0x22822e99,0x82c570b4,0xd8d94e89,\n\t0x8b1c34bc,0x301e16e6,0x273be979,0xb0ffeaa6,\n\t0x61d9b8c6,0x00b24869,0xb7ffce3f,0x08dc283b,\n\t0x43daf65a,0xf7e19798,0x7619b72f,0x8f1c9ba4,\n\t0xdc8637a0,0x16a7d3b1,0x9fc393b7,0xa7136eeb,\n\t0xc6bcc63e,0x1a513742,0xef6828bc,0x520365d6,\n\t0x2d6a77ab,0x3527ed4b,0x821fd216,0x095c6e2e,\n\t0xdb92f2fb,0x5eea29cb,0x145892f5,0x91584f7f,\n\t0x5483697b,0x2667a8cc,0x85196048,0x8c4bacea,\n\t0x833860d4,0x0d23e0f9,0x6c387e8a,0x0ae6d249,\n\t0xb284600c,0xd835731d,0xdcb1c647,0xac4c56ea,\n\t0x3ebd81b3,0x230eabb0,0x6438bc87,0xf0b5b1fa,\n\t0x8f5ea2b3,0xfc184642,0x0a036b7a,0x4fb089bd,\n\t0x649da589,0xa345415e,0x5c038323,0x3e5d3bb9,\n\t0x43d79572,0x7e6dd07c,0x06dfdf1e,0x6c6cc4ef,\n\t0x7160a539,0x73bfbe70,0x83877605,0x4523ecf1,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table2[256]={\t\t/* pcg */\n\t0x8defc240,0x25fa5d9f,0xeb903dbf,0xe810c907,\n\t0x47607fff,0x369fe44b,0x8c1fc644,0xaececa90,\n\t0xbeb1f9bf,0xeefbcaea,0xe8cf1950,0x51df07ae,\n\t0x920e8806,0xf0ad0548,0xe13c8d83,0x927010d5,\n\t0x11107d9f,0x07647db9,0xb2e3e4d4,0x3d4f285e,\n\t0xb9afa820,0xfade82e0,0xa067268b,0x8272792e,\n\t0x553fb2c0,0x489ae22b,0xd4ef9794,0x125e3fbc,\n\t0x21fffcee,0x825b1bfd,0x9255c5ed,0x1257a240,\n\t0x4e1a8302,0xbae07fff,0x528246e7,0x8e57140e,\n\t0x3373f7bf,0x8c9f8188,0xa6fc4ee8,0xc982b5a5,\n\t0xa8c01db7,0x579fc264,0x67094f31,0xf2bd3f5f,\n\t0x40fff7c1,0x1fb78dfc,0x8e6bd2c1,0x437be59b,\n\t0x99b03dbf,0xb5dbc64b,0x638dc0e6,0x55819d99,\n\t0xa197c81c,0x4a012d6e,0xc5884a28,0xccc36f71,\n\t0xb843c213,0x6c0743f1,0x8309893c,0x0feddd5f,\n\t0x2f7fe850,0xd7c07f7e,0x02507fbf,0x5afb9a04,\n\t0xa747d2d0,0x1651192e,0xaf70bf3e,0x58c31380,\n\t0x5f98302e,0x727cc3c4,0x0a0fb402,0x0f7fef82,\n\t0x8c96fdad,0x5d2c2aae,0x8ee99a49,0x50da88b8,\n\t0x8427f4a0,0x1eac5790,0x796fb449,0x8252dc15,\n\t0xefbd7d9b,0xa672597d,0xada840d8,0x45f54504,\n\t0xfa5d7403,0xe83ec305,0x4f91751a,0x925669c2,\n\t0x23efe941,0xa903f12e,0x60270df2,0x0276e4b6,\n\t0x94fd6574,0x927985b2,0x8276dbcb,0x02778176,\n\t0xf8af918d,0x4e48f79e,0x8f616ddf,0xe29d840e,\n\t0x842f7d83,0x340ce5c8,0x96bbb682,0x93b4b148,\n\t0xef303cab,0x984faf28,0x779faf9b,0x92dc560d,\n\t0x224d1e20,0x8437aa88,0x7d29dc96,0x2756d3dc,\n\t0x8b907cee,0xb51fd240,0xe7c07ce3,0xe566b4a1,\n\t0xc3e9615e,0x3cf8209d,0x6094d1e3,0xcd9ca341,\n\t0x5c76460e,0x00ea983b,0xd4d67881,0xfd47572c,\n\t0xf76cedd9,0xbda8229c,0x127dadaa,0x438a074e,\n\t0x1f97c090,0x081bdb8a,0x93a07ebe,0xb938ca15,\n\t0x97b03cff,0x3dc2c0f8,0x8d1ab2ec,0x64380e51,\n\t0x68cc7bfb,0xd90f2788,0x12490181,0x5de5ffd4,\n\t0xdd7ef86a,0x76a2e214,0xb9a40368,0x925d958f,\n\t0x4b39fffa,0xba39aee9,0xa4ffd30b,0xfaf7933b,\n\t0x6d498623,0x193cbcfa,0x27627545,0x825cf47a,\n\t0x61bd8ba0,0xd11e42d1,0xcead04f4,0x127ea392,\n\t0x10428db7,0x8272a972,0x9270c4a8,0x127de50b,\n\t0x285ba1c8,0x3c62f44f,0x35c0eaa5,0xe805d231,\n\t0x428929fb,0xb4fcdf82,0x4fb66a53,0x0e7dc15b,\n\t0x1f081fab,0x108618ae,0xfcfd086d,0xf9ff2889,\n\t0x694bcc11,0x236a5cae,0x12deca4d,0x2c3f8cc5,\n\t0xd2d02dfe,0xf8ef5896,0xe4cf52da,0x95155b67,\n\t0x494a488c,0xb9b6a80c,0x5c8f82bc,0x89d36b45,\n\t0x3a609437,0xec00c9a9,0x44715253,0x0a874b49,\n\t0xd773bc40,0x7c34671c,0x02717ef6,0x4feb5536,\n\t0xa2d02fff,0xd2bf60c4,0xd43f03c0,0x50b4ef6d,\n\t0x07478cd1,0x006e1888,0xa2e53f55,0xb9e6d4bc,\n\t0xa2048016,0x97573833,0xd7207d67,0xde0f8f3d,\n\t0x72f87b33,0xabcc4f33,0x7688c55d,0x7b00a6b0,\n\t0x947b0001,0x570075d2,0xf9bb88f8,0x8942019e,\n\t0x4264a5ff,0x856302e0,0x72dbd92b,0xee971b69,\n\t0x6ea22fde,0x5f08ae2b,0xaf7a616d,0xe5c98767,\n\t0xcf1febd2,0x61efc8c2,0xf1ac2571,0xcc8239c2,\n\t0x67214cb8,0xb1e583d1,0xb7dc3e62,0x7f10bdce,\n\t0xf90a5c38,0x0ff0443d,0x606e6dc6,0x60543a49,\n\t0x5727c148,0x2be98a1d,0x8ab41738,0x20e1be24,\n\t0xaf96da0f,0x68458425,0x99833be5,0x600d457d,\n\t0x282f9350,0x8334b362,0xd91d1120,0x2b6d8da0,\n\t0x642b1e31,0x9c305a00,0x52bce688,0x1b03588a,\n\t0xf7baefd5,0x4142ed9c,0xa4315c11,0x83323ec5,\n\t0xdfef4636,0xa133c501,0xe9d3531c,0xee353783,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table3[256]={\t\t/* pcg */\n\t0x9db30420,0x1fb6e9de,0xa7be7bef,0xd273a298,\n\t0x4a4f7bdb,0x64ad8c57,0x85510443,0xfa020ed1,\n\t0x7e287aff,0xe60fb663,0x095f35a1,0x79ebf120,\n\t0xfd059d43,0x6497b7b1,0xf3641f63,0x241e4adf,\n\t0x28147f5f,0x4fa2b8cd,0xc9430040,0x0cc32220,\n\t0xfdd30b30,0xc0a5374f,0x1d2d00d9,0x24147b15,\n\t0xee4d111a,0x0fca5167,0x71ff904c,0x2d195ffe,\n\t0x1a05645f,0x0c13fefe,0x081b08ca,0x05170121,\n\t0x80530100,0xe83e5efe,0xac9af4f8,0x7fe72701,\n\t0xd2b8ee5f,0x06df4261,0xbb9e9b8a,0x7293ea25,\n\t0xce84ffdf,0xf5718801,0x3dd64b04,0xa26f263b,\n\t0x7ed48400,0x547eebe6,0x446d4ca0,0x6cf3d6f5,\n\t0x2649abdf,0xaea0c7f5,0x36338cc1,0x503f7e93,\n\t0xd3772061,0x11b638e1,0x72500e03,0xf80eb2bb,\n\t0xabe0502e,0xec8d77de,0x57971e81,0xe14f6746,\n\t0xc9335400,0x6920318f,0x081dbb99,0xffc304a5,\n\t0x4d351805,0x7f3d5ce3,0xa6c866c6,0x5d5bcca9,\n\t0xdaec6fea,0x9f926f91,0x9f46222f,0x3991467d,\n\t0xa5bf6d8e,0x1143c44f,0x43958302,0xd0214eeb,\n\t0x022083b8,0x3fb6180c,0x18f8931e,0x281658e6,\n\t0x26486e3e,0x8bd78a70,0x7477e4c1,0xb506e07c,\n\t0xf32d0a25,0x79098b02,0xe4eabb81,0x28123b23,\n\t0x69dead38,0x1574ca16,0xdf871b62,0x211c40b7,\n\t0xa51a9ef9,0x0014377b,0x041e8ac8,0x09114003,\n\t0xbd59e4d2,0xe3d156d5,0x4fe876d5,0x2f91a340,\n\t0x557be8de,0x00eae4a7,0x0ce5c2ec,0x4db4bba6,\n\t0xe756bdff,0xdd3369ac,0xec17b035,0x06572327,\n\t0x99afc8b0,0x56c8c391,0x6b65811c,0x5e146119,\n\t0x6e85cb75,0xbe07c002,0xc2325577,0x893ff4ec,\n\t0x5bbfc92d,0xd0ec3b25,0xb7801ab7,0x8d6d3b24,\n\t0x20c763ef,0xc366a5fc,0x9c382880,0x0ace3205,\n\t0xaac9548a,0xeca1d7c7,0x041afa32,0x1d16625a,\n\t0x6701902c,0x9b757a54,0x31d477f7,0x9126b031,\n\t0x36cc6fdb,0xc70b8b46,0xd9e66a48,0x56e55a79,\n\t0x026a4ceb,0x52437eff,0x2f8f76b4,0x0df980a5,\n\t0x8674cde3,0xedda04eb,0x17a9be04,0x2c18f4df,\n\t0xb7747f9d,0xab2af7b4,0xefc34d20,0x2e096b7c,\n\t0x1741a254,0xe5b6a035,0x213d42f6,0x2c1c7c26,\n\t0x61c2f50f,0x6552daf9,0xd2c231f8,0x25130f69,\n\t0xd8167fa2,0x0418f2c8,0x001a96a6,0x0d1526ab,\n\t0x63315c21,0x5e0a72ec,0x49bafefd,0x187908d9,\n\t0x8d0dbd86,0x311170a7,0x3e9b640c,0xcc3e10d7,\n\t0xd5cad3b6,0x0caec388,0xf73001e1,0x6c728aff,\n\t0x71eae2a1,0x1f9af36e,0xcfcbd12f,0xc1de8417,\n\t0xac07be6b,0xcb44a1d8,0x8b9b0f56,0x013988c3,\n\t0xb1c52fca,0xb4be31cd,0xd8782806,0x12a3a4e2,\n\t0x6f7de532,0x58fd7eb6,0xd01ee900,0x24adffc2,\n\t0xf4990fc5,0x9711aac5,0x001d7b95,0x82e5e7d2,\n\t0x109873f6,0x00613096,0xc32d9521,0xada121ff,\n\t0x29908415,0x7fbb977f,0xaf9eb3db,0x29c9ed2a,\n\t0x5ce2a465,0xa730f32c,0xd0aa3fe8,0x8a5cc091,\n\t0xd49e2ce7,0x0ce454a9,0xd60acd86,0x015f1919,\n\t0x77079103,0xdea03af6,0x78a8565e,0xdee356df,\n\t0x21f05cbe,0x8b75e387,0xb3c50651,0xb8a5c3ef,\n\t0xd8eeb6d2,0xe523be77,0xc2154529,0x2f69efdf,\n\t0xafe67afb,0xf470c4b2,0xf3e0eb5b,0xd6cc9876,\n\t0x39e4460c,0x1fda8538,0x1987832f,0xca007367,\n\t0xa99144f8,0x296b299e,0x492fc295,0x9266beab,\n\t0xb5676e69,0x9bd3ddda,0xdf7e052f,0xdb25701c,\n\t0x1b5e51ee,0xf65324e6,0x6afce36c,0x0316cc04,\n\t0x8644213e,0xb7dc59d0,0x7965291f,0xccd6fd43,\n\t0x41823979,0x932bcdf6,0xb657c34d,0x4edfd282,\n\t0x7ae5290c,0x3cb9536b,0x851e20fe,0x9833557e,\n\t0x13ecf0b0,0xd3ffb372,0x3f85c5c1,0x0aef7ed2,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table4[256]={\t\t/* pcg */\n\t0x7ec90c04,0x2c6e74b9,0x9b0e66df,0xa6337911,\n\t0xb86a7fff,0x1dd358f5,0x44dd9d44,0x1731167f,\n\t0x08fbf1fa,0xe7f511cc,0xd2051b00,0x735aba00,\n\t0x2ab722d8,0x386381cb,0xacf6243a,0x69befd7a,\n\t0xe6a2e77f,0xf0c720cd,0xc4494816,0xccf5c180,\n\t0x38851640,0x15b0a848,0xe68b18cb,0x4caadeff,\n\t0x5f480a01,0x0412b2aa,0x259814fc,0x41d0efe2,\n\t0x4e40b48d,0x248eb6fb,0x8dba1cfe,0x41a99b02,\n\t0x1a550a04,0xba8f65cb,0x7251f4e7,0x95a51725,\n\t0xc106ecd7,0x97a5980a,0xc539b9aa,0x4d79fe6a,\n\t0xf2f3f763,0x68af8040,0xed0c9e56,0x11b4958b,\n\t0xe1eb5a88,0x8709e6b0,0xd7e07156,0x4e29fea7,\n\t0x6366e52d,0x02d1c000,0xc4ac8e05,0x9377f571,\n\t0x0c05372a,0x578535f2,0x2261be02,0xd642a0c9,\n\t0xdf13a280,0x74b55bd2,0x682199c0,0xd421e5ec,\n\t0x53fb3ce8,0xc8adedb3,0x28a87fc9,0x3d959981,\n\t0x5c1ff900,0xfe38d399,0x0c4eff0b,0x062407ea,\n\t0xaa2f4fb1,0x4fb96976,0x90c79505,0xb0a8a774,\n\t0xef55a1ff,0xe59ca2c2,0xa6b62d27,0xe66a4263,\n\t0xdf65001f,0x0ec50966,0xdfdd55bc,0x29de0655,\n\t0x911e739a,0x17af8975,0x32c7911c,0x89f89468,\n\t0x0d01e980,0x524755f4,0x03b63cc9,0x0cc844b2,\n\t0xbcf3f0aa,0x87ac36e9,0xe53a7426,0x01b3d82b,\n\t0x1a9e7449,0x64ee2d7e,0xcddbb1da,0x01c94910,\n\t0xb868bf80,0x0d26f3fd,0x9342ede7,0x04a5c284,\n\t0x636737b6,0x50f5b616,0xf24766e3,0x8eca36c1,\n\t0x136e05db,0xfef18391,0xfb887a37,0xd6e7f7d4,\n\t0xc7fb7dc9,0x3063fcdf,0xb6f589de,0xec2941da,\n\t0x26e46695,0xb7566419,0xf654efc5,0xd08d58b7,\n\t0x48925401,0xc1bacb7f,0xe5ff550f,0xb6083049,\n\t0x5bb5d0e8,0x87d72e5a,0xab6a6ee1,0x223a66ce,\n\t0xc62bf3cd,0x9e0885f9,0x68cb3e47,0x086c010f,\n\t0xa21de820,0xd18b69de,0xf3f65777,0xfa02c3f6,\n\t0x407edac3,0xcbb3d550,0x1793084d,0xb0d70eba,\n\t0x0ab378d5,0xd951fb0c,0xded7da56,0x4124bbe4,\n\t0x94ca0b56,0x0f5755d1,0xe0e1e56e,0x6184b5be,\n\t0x580a249f,0x94f74bc0,0xe327888e,0x9f7b5561,\n\t0xc3dc0280,0x05687715,0x646c6bd7,0x44904db3,\n\t0x66b4f0a3,0xc0f1648a,0x697ed5af,0x49e92ff6,\n\t0x309e374f,0x2cb6356a,0x85808573,0x4991f840,\n\t0x76f0ae02,0x083be84d,0x28421c9a,0x44489406,\n\t0x736e4cb8,0xc1092910,0x8bc95fc6,0x7d869cf4,\n\t0x134f616f,0x2e77118d,0xb31b2be1,0xaa90b472,\n\t0x3ca5d717,0x7d161bba,0x9cad9010,0xaf462ba2,\n\t0x9fe459d2,0x45d34559,0xd9f2da13,0xdbc65487,\n\t0xf3e4f94e,0x176d486f,0x097c13ea,0x631da5c7,\n\t0x445f7382,0x175683f4,0xcdc66a97,0x70be0288,\n\t0xb3cdcf72,0x6e5dd2f3,0x20936079,0x459b80a5,\n\t0xbe60e2db,0xa9c23101,0xeba5315c,0x224e42f2,\n\t0x1c5c1572,0xf6721b2c,0x1ad2fff3,0x8c25404e,\n\t0x324ed72f,0x4067b7fd,0x0523138e,0x5ca3bc78,\n\t0xdc0fd66e,0x75922283,0x784d6b17,0x58ebb16e,\n\t0x44094f85,0x3f481d87,0xfcfeae7b,0x77b5ff76,\n\t0x8c2302bf,0xaaf47556,0x5f46b02a,0x2b092801,\n\t0x3d38f5f7,0x0ca81f36,0x52af4a8a,0x66d5e7c0,\n\t0xdf3b0874,0x95055110,0x1b5ad7a8,0xf61ed5ad,\n\t0x6cf6e479,0x20758184,0xd0cefa65,0x88f7be58,\n\t0x4a046826,0x0ff6f8f3,0xa09c7f70,0x5346aba0,\n\t0x5ce96c28,0xe176eda3,0x6bac307f,0x376829d2,\n\t0x85360fa9,0x17e3fe2a,0x24b79767,0xf5a96b20,\n\t0xd6cd2595,0x68ff1ebf,0x7555442c,0xf19f06be,\n\t0xf9e0659a,0xeeb9491d,0x34010718,0xbb30cab8,\n\t0xe822fe15,0x88570983,0x750e6249,0xda627e55,\n\t0x5e76ffa8,0xb1534546,0x6d47de08,0xefe9e7d4,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table5[256]={\t\t/* pcg */\n\t0xf6fa8f9d,0x2cac6ce1,0x4ca34867,0xe2337f7c,\n\t0x95db08e7,0x016843b4,0xeced5cbc,0x325553ac,\n\t0xbf9f0960,0xdfa1e2ed,0x83f0579d,0x63ed86b9,\n\t0x1ab6a6b8,0xde5ebe39,0xf38ff732,0x8989b138,\n\t0x33f14961,0xc01937bd,0xf506c6da,0xe4625e7e,\n\t0xa308ea99,0x4e23e33c,0x79cbd7cc,0x48a14367,\n\t0xa3149619,0xfec94bd5,0xa114174a,0xeaa01866,\n\t0xa084db2d,0x09a8486f,0xa888614a,0x2900af98,\n\t0x01665991,0xe1992863,0xc8f30c60,0x2e78ef3c,\n\t0xd0d51932,0xcf0fec14,0xf7ca07d2,0xd0a82072,\n\t0xfd41197e,0x9305a6b0,0xe86be3da,0x74bed3cd,\n\t0x372da53c,0x4c7f4448,0xdab5d440,0x6dba0ec3,\n\t0x083919a7,0x9fbaeed9,0x49dbcfb0,0x4e670c53,\n\t0x5c3d9c01,0x64bdb941,0x2c0e636a,0xba7dd9cd,\n\t0xea6f7388,0xe70bc762,0x35f29adb,0x5c4cdd8d,\n\t0xf0d48d8c,0xb88153e2,0x08a19866,0x1ae2eac8,\n\t0x284caf89,0xaa928223,0x9334be53,0x3b3a21bf,\n\t0x16434be3,0x9aea3906,0xefe8c36e,0xf890cdd9,\n\t0x80226dae,0xc340a4a3,0xdf7e9c09,0xa694a807,\n\t0x5b7c5ecc,0x221db3a6,0x9a69a02f,0x68818a54,\n\t0xceb2296f,0x53c0843a,0xfe893655,0x25bfe68a,\n\t0xb4628abc,0xcf222ebf,0x25ac6f48,0xa9a99387,\n\t0x53bddb65,0xe76ffbe7,0xe967fd78,0x0ba93563,\n\t0x8e342bc1,0xe8a11be9,0x4980740d,0xc8087dfc,\n\t0x8de4bf99,0xa11101a0,0x7fd37975,0xda5a26c0,\n\t0xe81f994f,0x9528cd89,0xfd339fed,0xb87834bf,\n\t0x5f04456d,0x22258698,0xc9c4c83b,0x2dc156be,\n\t0x4f628daa,0x57f55ec5,0xe2220abe,0xd2916ebf,\n\t0x4ec75b95,0x24f2c3c0,0x42d15d99,0xcd0d7fa0,\n\t0x7b6e27ff,0xa8dc8af0,0x7345c106,0xf41e232f,\n\t0x35162386,0xe6ea8926,0x3333b094,0x157ec6f2,\n\t0x372b74af,0x692573e4,0xe9a9d848,0xf3160289,\n\t0x3a62ef1d,0xa787e238,0xf3a5f676,0x74364853,\n\t0x20951063,0x4576698d,0xb6fad407,0x592af950,\n\t0x36f73523,0x4cfb6e87,0x7da4cec0,0x6c152daa,\n\t0xcb0396a8,0xc50dfe5d,0xfcd707ab,0x0921c42f,\n\t0x89dff0bb,0x5fe2be78,0x448f4f33,0x754613c9,\n\t0x2b05d08d,0x48b9d585,0xdc049441,0xc8098f9b,\n\t0x7dede786,0xc39a3373,0x42410005,0x6a091751,\n\t0x0ef3c8a6,0x890072d6,0x28207682,0xa9a9f7be,\n\t0xbf32679d,0xd45b5b75,0xb353fd00,0xcbb0e358,\n\t0x830f220a,0x1f8fb214,0xd372cf08,0xcc3c4a13,\n\t0x8cf63166,0x061c87be,0x88c98f88,0x6062e397,\n\t0x47cf8e7a,0xb6c85283,0x3cc2acfb,0x3fc06976,\n\t0x4e8f0252,0x64d8314d,0xda3870e3,0x1e665459,\n\t0xc10908f0,0x513021a5,0x6c5b68b7,0x822f8aa0,\n\t0x3007cd3e,0x74719eef,0xdc872681,0x073340d4,\n\t0x7e432fd9,0x0c5ec241,0x8809286c,0xf592d891,\n\t0x08a930f6,0x957ef305,0xb7fbffbd,0xc266e96f,\n\t0x6fe4ac98,0xb173ecc0,0xbc60b42a,0x953498da,\n\t0xfba1ae12,0x2d4bd736,0x0f25faab,0xa4f3fceb,\n\t0xe2969123,0x257f0c3d,0x9348af49,0x361400bc,\n\t0xe8816f4a,0x3814f200,0xa3f94043,0x9c7a54c2,\n\t0xbc704f57,0xda41e7f9,0xc25ad33a,0x54f4a084,\n\t0xb17f5505,0x59357cbe,0xedbd15c8,0x7f97c5ab,\n\t0xba5ac7b5,0xb6f6deaf,0x3a479c3a,0x5302da25,\n\t0x653d7e6a,0x54268d49,0x51a477ea,0x5017d55b,\n\t0xd7d25d88,0x44136c76,0x0404a8c8,0xb8e5a121,\n\t0xb81a928a,0x60ed5869,0x97c55b96,0xeaec991b,\n\t0x29935913,0x01fdb7f1,0x088e8dfa,0x9ab6f6f5,\n\t0x3b4cbf9f,0x4a5de3ab,0xe6051d35,0xa0e1d855,\n\t0xd36b4cf1,0xf544edeb,0xb0e93524,0xbebb8fbd,\n\t0xa2d762cf,0x49c92f54,0x38b5f331,0x7128a454,\n\t0x48392905,0xa65b1db8,0x851c97bd,0xd675cf2f,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table6[256]={\t\t/* pcg */\n\t0x85e04019,0x332bf567,0x662dbfff,0xcfc65693,\n\t0x2a8d7f6f,0xab9bc912,0xde6008a1,0x2028da1f,\n\t0x0227bce7,0x4d642916,0x18fac300,0x50f18b82,\n\t0x2cb2cb11,0xb232e75c,0x4b3695f2,0xb28707de,\n\t0xa05fbcf6,0xcd4181e9,0xe150210c,0xe24ef1bd,\n\t0xb168c381,0xfde4e789,0x5c79b0d8,0x1e8bfd43,\n\t0x4d495001,0x38be4341,0x913cee1d,0x92a79c3f,\n\t0x089766be,0xbaeeadf4,0x1286becf,0xb6eacb19,\n\t0x2660c200,0x7565bde4,0x64241f7a,0x8248dca9,\n\t0xc3b3ad66,0x28136086,0x0bd8dfa8,0x356d1cf2,\n\t0x107789be,0xb3b2e9ce,0x0502aa8f,0x0bc0351e,\n\t0x166bf52a,0xeb12ff82,0xe3486911,0xd34d7516,\n\t0x4e7b3aff,0x5f43671b,0x9cf6e037,0x4981ac83,\n\t0x334266ce,0x8c9341b7,0xd0d854c0,0xcb3a6c88,\n\t0x47bc2829,0x4725ba37,0xa66ad22b,0x7ad61f1e,\n\t0x0c5cbafa,0x4437f107,0xb6e79962,0x42d2d816,\n\t0x0a961288,0xe1a5c06e,0x13749e67,0x72fc081a,\n\t0xb1d139f7,0xf9583745,0xcf19df58,0xbec3f756,\n\t0xc06eba30,0x07211b24,0x45c28829,0xc95e317f,\n\t0xbc8ec511,0x38bc46e9,0xc6e6fa14,0xbae8584a,\n\t0xad4ebc46,0x468f508b,0x7829435f,0xf124183b,\n\t0x821dba9f,0xaff60ff4,0xea2c4e6d,0x16e39264,\n\t0x92544a8b,0x009b4fc3,0xaba68ced,0x9ac96f78,\n\t0x06a5b79a,0xb2856e6e,0x1aec3ca9,0xbe838688,\n\t0x0e0804e9,0x55f1be56,0xe7e5363b,0xb3a1f25d,\n\t0xf7debb85,0x61fe033c,0x16746233,0x3c034c28,\n\t0xda6d0c74,0x79aac56c,0x3ce4e1ad,0x51f0c802,\n\t0x98f8f35a,0x1626a49f,0xeed82b29,0x1d382fe3,\n\t0x0c4fb99a,0xbb325778,0x3ec6d97b,0x6e77a6a9,\n\t0xcb658b5c,0xd45230c7,0x2bd1408b,0x60c03eb7,\n\t0xb9068d78,0xa33754f4,0xf430c87d,0xc8a71302,\n\t0xb96d8c32,0xebd4e7be,0xbe8b9d2d,0x7979fb06,\n\t0xe7225308,0x8b75cf77,0x11ef8da4,0xe083c858,\n\t0x8d6b786f,0x5a6317a6,0xfa5cf7a0,0x5dda0033,\n\t0xf28ebfb0,0xf5b9c310,0xa0eac280,0x08b9767a,\n\t0xa3d9d2b0,0x79d34217,0x021a718d,0x9ac6336a,\n\t0x2711fd60,0x438050e3,0x069908a8,0x3d7fedc4,\n\t0x826d2bef,0x4eeb8476,0x488dcf25,0x36c9d566,\n\t0x28e74e41,0xc2610aca,0x3d49a9cf,0xbae3b9df,\n\t0xb65f8de6,0x92aeaf64,0x3ac7d5e6,0x9ea80509,\n\t0xf22b017d,0xa4173f70,0xdd1e16c3,0x15e0d7f9,\n\t0x50b1b887,0x2b9f4fd5,0x625aba82,0x6a017962,\n\t0x2ec01b9c,0x15488aa9,0xd716e740,0x40055a2c,\n\t0x93d29a22,0xe32dbf9a,0x058745b9,0x3453dc1e,\n\t0xd699296e,0x496cff6f,0x1c9f4986,0xdfe2ed07,\n\t0xb87242d1,0x19de7eae,0x053e561a,0x15ad6f8c,\n\t0x66626c1c,0x7154c24c,0xea082b2a,0x93eb2939,\n\t0x17dcb0f0,0x58d4f2ae,0x9ea294fb,0x52cf564c,\n\t0x9883fe66,0x2ec40581,0x763953c3,0x01d6692e,\n\t0xd3a0c108,0xa1e7160e,0xe4f2dfa6,0x693ed285,\n\t0x74904698,0x4c2b0edd,0x4f757656,0x5d393378,\n\t0xa132234f,0x3d321c5d,0xc3f5e194,0x4b269301,\n\t0xc79f022f,0x3c997e7e,0x5e4f9504,0x3ffafbbd,\n\t0x76f7ad0e,0x296693f4,0x3d1fce6f,0xc61e45be,\n\t0xd3b5ab34,0xf72bf9b7,0x1b0434c0,0x4e72b567,\n\t0x5592a33d,0xb5229301,0xcfd2a87f,0x60aeb767,\n\t0x1814386b,0x30bcc33d,0x38a0c07d,0xfd1606f2,\n\t0xc363519b,0x589dd390,0x5479f8e6,0x1cb8d647,\n\t0x97fd61a9,0xea7759f4,0x2d57539d,0x569a58cf,\n\t0xe84e63ad,0x462e1b78,0x6580f87e,0xf3817914,\n\t0x91da55f4,0x40a230f3,0xd1988f35,0xb6e318d2,\n\t0x3ffa50bc,0x3d40f021,0xc3c0bdae,0x4958c24c,\n\t0x518f36b2,0x84b1d370,0x0fedce83,0x878ddada,\n\t0xf2a279c7,0x94e01be8,0x90716f4b,0x954b8aa3,\n\t};\nconst CAST_LONG ASM_EXPORT CAST_S_table7[256]={\t\t/* pcg */\n\t0xe216300d,0xbbddfffc,0xa7ebdabd,0x35648095,\n\t0x7789f8b7,0xe6c1121b,0x0e241600,0x052ce8b5,\n\t0x11a9cfb0,0xe5952f11,0xece7990a,0x9386d174,\n\t0x2a42931c,0x76e38111,0xb12def3a,0x37ddddfc,\n\t0xde9adeb1,0x0a0cc32c,0xbe197029,0x84a00940,\n\t0xbb243a0f,0xb4d137cf,0xb44e79f0,0x049eedfd,\n\t0x0b15a15d,0x480d3168,0x8bbbde5a,0x669ded42,\n\t0xc7ece831,0x3f8f95e7,0x72df191b,0x7580330d,\n\t0x94074251,0x5c7dcdfa,0xabbe6d63,0xaa402164,\n\t0xb301d40a,0x02e7d1ca,0x53571dae,0x7a3182a2,\n\t0x12a8ddec,0xfdaa335d,0x176f43e8,0x71fb46d4,\n\t0x38129022,0xce949ad4,0xb84769ad,0x965bd862,\n\t0x82f3d055,0x66fb9767,0x15b80b4e,0x1d5b47a0,\n\t0x4cfde06f,0xc28ec4b8,0x57e8726e,0x647a78fc,\n\t0x99865d44,0x608bd593,0x6c200e03,0x39dc5ff6,\n\t0x5d0b00a3,0xae63aff2,0x7e8bd632,0x70108c0c,\n\t0xbbd35049,0x2998df04,0x980cf42a,0x9b6df491,\n\t0x9e7edd53,0x06918548,0x58cb7e07,0x3b74ef2e,\n\t0x522fffb1,0xd24708cc,0x1c7e27cd,0xa4eb215b,\n\t0x3cf1d2e2,0x19b47a38,0x424f7618,0x35856039,\n\t0x9d17dee7,0x27eb35e6,0xc9aff67b,0x36baf5b8,\n\t0x09c467cd,0xc18910b1,0xe11dbf7b,0x06cd1af8,\n\t0x7170c608,0x2d5e3354,0xd4de495a,0x64c6d006,\n\t0xbcc0c62c,0x3dd00db3,0x708f8f34,0x77d51b42,\n\t0x264f620f,0x24b8d2bf,0x15c1b79e,0x46a52564,\n\t0xf8d7e54e,0x3e378160,0x7895cda5,0x859c15a5,\n\t0xe6459788,0xc37bc75f,0xdb07ba0c,0x0676a3ab,\n\t0x7f229b1e,0x31842e7b,0x24259fd7,0xf8bef472,\n\t0x835ffcb8,0x6df4c1f2,0x96f5b195,0xfd0af0fc,\n\t0xb0fe134c,0xe2506d3d,0x4f9b12ea,0xf215f225,\n\t0xa223736f,0x9fb4c428,0x25d04979,0x34c713f8,\n\t0xc4618187,0xea7a6e98,0x7cd16efc,0x1436876c,\n\t0xf1544107,0xbedeee14,0x56e9af27,0xa04aa441,\n\t0x3cf7c899,0x92ecbae6,0xdd67016d,0x151682eb,\n\t0xa842eedf,0xfdba60b4,0xf1907b75,0x20e3030f,\n\t0x24d8c29e,0xe139673b,0xefa63fb8,0x71873054,\n\t0xb6f2cf3b,0x9f326442,0xcb15a4cc,0xb01a4504,\n\t0xf1e47d8d,0x844a1be5,0xbae7dfdc,0x42cbda70,\n\t0xcd7dae0a,0x57e85b7a,0xd53f5af6,0x20cf4d8c,\n\t0xcea4d428,0x79d130a4,0x3486ebfb,0x33d3cddc,\n\t0x77853b53,0x37effcb5,0xc5068778,0xe580b3e6,\n\t0x4e68b8f4,0xc5c8b37e,0x0d809ea2,0x398feb7c,\n\t0x132a4f94,0x43b7950e,0x2fee7d1c,0x223613bd,\n\t0xdd06caa2,0x37df932b,0xc4248289,0xacf3ebc3,\n\t0x5715f6b7,0xef3478dd,0xf267616f,0xc148cbe4,\n\t0x9052815e,0x5e410fab,0xb48a2465,0x2eda7fa4,\n\t0xe87b40e4,0xe98ea084,0x5889e9e1,0xefd390fc,\n\t0xdd07d35b,0xdb485694,0x38d7e5b2,0x57720101,\n\t0x730edebc,0x5b643113,0x94917e4f,0x503c2fba,\n\t0x646f1282,0x7523d24a,0xe0779695,0xf9c17a8f,\n\t0x7a5b2121,0xd187b896,0x29263a4d,0xba510cdf,\n\t0x81f47c9f,0xad1163ed,0xea7b5965,0x1a00726e,\n\t0x11403092,0x00da6d77,0x4a0cdd61,0xad1f4603,\n\t0x605bdfb0,0x9eedc364,0x22ebe6a8,0xcee7d28a,\n\t0xa0e736a0,0x5564a6b9,0x10853209,0xc7eb8f37,\n\t0x2de705ca,0x8951570f,0xdf09822b,0xbd691a6c,\n\t0xaa12e4f2,0x87451c0f,0xe0f6a27a,0x3ada4819,\n\t0x4cf1764f,0x0d771c2b,0x67cdb156,0x350d8384,\n\t0x5938fa0f,0x42399ef3,0x36997b07,0x0e84093d,\n\t0x4aa93e61,0x8360d87b,0x1fa98b0c,0x1149382c,\n\t0xe97625a5,0x0614d1b7,0x0e25244b,0x0c768347,\n\t0x589e8d82,0x0d2059d1,0xa466bb1e,0xf8da0a82,\n\t0x04f19130,0xba6e4ec0,0x99265164,0x1ee7230d,\n\t0x50b2ad80,0xeaee6801,0x8db2a283,0xea8bf59e,\n\t};\n"
  },
  {
    "path": "deps/cl345/crypt/castskey.c",
    "content": "/* crypto/cast/c_skey.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"cast.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/cast.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CAST\n\n/* castsbox.h declates an enormous static const lookup table, so we need to \n   include it after we've checked whether we want to build the BF code or\n   not - pcg */\n\n#if defined( INC_ALL )\n  #include \"castsbox.h\"\n#else\n  #include \"crypt/castsbox.h\"\n#endif /* Compiler-specific includes */\n\n#define CAST_exp(l,A,a,n) \\\n\tA[n/4]=l; \\\n\ta[n+3]=(l    )&0xff; \\\n\ta[n+2]=(l>> 8)&0xff; \\\n\ta[n+1]=(l>>16)&0xff; \\\n\ta[n+0]=(l>>24)&0xff;\n\n#define S4 CAST_S_table4\n#define S5 CAST_S_table5\n#define S6 CAST_S_table6\n#define S7 CAST_S_table7\n\nvoid CAST_set_key(CAST_KEY *key, int len, const unsigned char *data)\n\t{\n\tCAST_LONG x[16];\n\tCAST_LONG z[16];\n\tCAST_LONG k[32];\n\tCAST_LONG X[4],Z[4];\n\tCAST_LONG l,*K;\n\tint i;\n\n\tfor (i=0; i<16; i++) x[i]=0;\n\tif (len > 16) len=16;\n\tfor (i=0; i<len; i++)\n\t\tx[i]=data[i];\n\tif(len <= 10)\n\t    key->short_key=1;\n\telse\n\t    key->short_key=0;\n\n\tK= &k[0];\n\tX[0]=((x[ 0]<<24)|(x[ 1]<<16)|(x[ 2]<<8)|x[ 3])&0xffffffffL;\n\tX[1]=((x[ 4]<<24)|(x[ 5]<<16)|(x[ 6]<<8)|x[ 7])&0xffffffffL;\n\tX[2]=((x[ 8]<<24)|(x[ 9]<<16)|(x[10]<<8)|x[11])&0xffffffffL;\n\tX[3]=((x[12]<<24)|(x[13]<<16)|(x[14]<<8)|x[15])&0xffffffffL;\n\n\tfor (;;)\n\t\t{\n\tl=X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];\n\tCAST_exp(l,Z,z, 0);\n\tl=X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];\n\tCAST_exp(l,Z,z, 4);\n\tl=X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];\n\tCAST_exp(l,Z,z, 8);\n\tl=X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];\n\tCAST_exp(l,Z,z,12);\n\n\tK[ 0]= S4[z[ 8]]^S5[z[ 9]]^S6[z[ 7]]^S7[z[ 6]]^S4[z[ 2]];\n\tK[ 1]= S4[z[10]]^S5[z[11]]^S6[z[ 5]]^S7[z[ 4]]^S5[z[ 6]];\n\tK[ 2]= S4[z[12]]^S5[z[13]]^S6[z[ 3]]^S7[z[ 2]]^S6[z[ 9]];\n\tK[ 3]= S4[z[14]]^S5[z[15]]^S6[z[ 1]]^S7[z[ 0]]^S7[z[12]];\n\n\tl=Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];\n\tCAST_exp(l,X,x, 0);\n\tl=Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];\n\tCAST_exp(l,X,x, 4);\n\tl=Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];\n\tCAST_exp(l,X,x, 8);\n\tl=Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];\n\tCAST_exp(l,X,x,12);\n\n\tK[ 4]= S4[x[ 3]]^S5[x[ 2]]^S6[x[12]]^S7[x[13]]^S4[x[ 8]];\n\tK[ 5]= S4[x[ 1]]^S5[x[ 0]]^S6[x[14]]^S7[x[15]]^S5[x[13]];\n\tK[ 6]= S4[x[ 7]]^S5[x[ 6]]^S6[x[ 8]]^S7[x[ 9]]^S6[x[ 3]];\n\tK[ 7]= S4[x[ 5]]^S5[x[ 4]]^S6[x[10]]^S7[x[11]]^S7[x[ 7]];\n\n\tl=X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];\n\tCAST_exp(l,Z,z, 0);\n\tl=X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];\n\tCAST_exp(l,Z,z, 4);\n\tl=X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];\n\tCAST_exp(l,Z,z, 8);\n\tl=X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];\n\tCAST_exp(l,Z,z,12);\n\n\tK[ 8]= S4[z[ 3]]^S5[z[ 2]]^S6[z[12]]^S7[z[13]]^S4[z[ 9]];\n\tK[ 9]= S4[z[ 1]]^S5[z[ 0]]^S6[z[14]]^S7[z[15]]^S5[z[12]];\n\tK[10]= S4[z[ 7]]^S5[z[ 6]]^S6[z[ 8]]^S7[z[ 9]]^S6[z[ 2]];\n\tK[11]= S4[z[ 5]]^S5[z[ 4]]^S6[z[10]]^S7[z[11]]^S7[z[ 6]];\n\n\tl=Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];\n\tCAST_exp(l,X,x, 0);\n\tl=Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];\n\tCAST_exp(l,X,x, 4);\n\tl=Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];\n\tCAST_exp(l,X,x, 8);\n\tl=Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];\n\tCAST_exp(l,X,x,12);\n\n\tK[12]= S4[x[ 8]]^S5[x[ 9]]^S6[x[ 7]]^S7[x[ 6]]^S4[x[ 3]];\n\tK[13]= S4[x[10]]^S5[x[11]]^S6[x[ 5]]^S7[x[ 4]]^S5[x[ 7]];\n\tK[14]= S4[x[12]]^S5[x[13]]^S6[x[ 3]]^S7[x[ 2]]^S6[x[ 8]];\n\tK[15]= S4[x[14]]^S5[x[15]]^S6[x[ 1]]^S7[x[ 0]]^S7[x[13]];\n\tif (K != k)  break;\n\tK+=16;\n\t\t}\n\n\tfor (i=0; i<16; i++)\n\t\t{\n\t\tkey->data[i*2]=k[i];\n\t\tkey->data[i*2+1]=((k[i+16])+16)&0x1f;\n\t\t}\n\t}\n#endif /* USE_CAST */\n"
  },
  {
    "path": "deps/cl345/crypt/d-win32.asm",
    "content": "\t; Don't even think of reading this code\n\t; It was automatically generated by des-586.pl\n\t; Which is a perl program used to generate the x86 assember for\n\t; any of elf, a.out, BSDI, Win32, gaswin (for GNU as on Win32) or Solaris\n\t; eric <eay@cryptsoft.com>\n\t; \nsegment .text\nextern\t_des_SPtrans\nglobal\t_des_encrypt1\n_des_encrypt1:\n\tpush\tesi\n\tpush\tedi\n\t; \n\t; Load the 2 words\n\tmov\tesi,\t\t[12+esp]\n\txor\tecx,\t\tecx\n\tpush\tebx\n\tpush\tebp\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[28+esp]\n\tmov\tedi,\t\t[4+esi]\n\t; \n\t; IP\n\trol\teax,\t\t4\n\tmov\tesi,\t\teax\n\txor\teax,\t\tedi\n\tand\teax,\t\t0f0f0f0f0h\n\txor\tesi,\t\teax\n\txor\tedi,\t\teax\n\t; \n\trol\tedi,\t\t20\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0fff0000fh\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\teax,\t\t14\n\tmov\tedi,\t\teax\n\txor\teax,\t\tesi\n\tand\teax,\t\t033333333h\n\txor\tedi,\t\teax\n\txor\tesi,\t\teax\n\t; \n\trol\tesi,\t\t22\n\tmov\teax,\t\tesi\n\txor\tesi,\t\tedi\n\tand\tesi,\t\t003fc03fch\n\txor\teax,\t\tesi\n\txor\tedi,\t\tesi\n\t; \n\trol\teax,\t\t9\n\tmov\tesi,\t\teax\n\txor\teax,\t\tedi\n\tand\teax,\t\t0aaaaaaaah\n\txor\tesi,\t\teax\n\txor\tedi,\t\teax\n\t; \n\trol\tedi,\t\t1\n\tmov\tebp,\t\t[24+esp]\n\tcmp\tebx,\t\t0\n\tje NEAR\t$L000start_decrypt\n\t; \n\t; Round 0\n\tmov\teax,\t\t[ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[4+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 1\n\tmov\teax,\t\t[8+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[12+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 2\n\tmov\teax,\t\t[16+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[20+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 3\n\tmov\teax,\t\t[24+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[28+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 4\n\tmov\teax,\t\t[32+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[36+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 5\n\tmov\teax,\t\t[40+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[44+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 6\n\tmov\teax,\t\t[48+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[52+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 7\n\tmov\teax,\t\t[56+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[60+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 8\n\tmov\teax,\t\t[64+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[68+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 9\n\tmov\teax,\t\t[72+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[76+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 10\n\tmov\teax,\t\t[80+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[84+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 11\n\tmov\teax,\t\t[88+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[92+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 12\n\tmov\teax,\t\t[96+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[100+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 13\n\tmov\teax,\t\t[104+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[108+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 14\n\tmov\teax,\t\t[112+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[116+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 15\n\tmov\teax,\t\t[120+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[124+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\tjmp\t$L001end\n$L000start_decrypt:\n\t; \n\t; Round 15\n\tmov\teax,\t\t[120+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[124+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 14\n\tmov\teax,\t\t[112+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[116+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 13\n\tmov\teax,\t\t[104+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[108+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 12\n\tmov\teax,\t\t[96+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[100+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 11\n\tmov\teax,\t\t[88+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[92+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 10\n\tmov\teax,\t\t[80+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[84+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 9\n\tmov\teax,\t\t[72+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[76+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 8\n\tmov\teax,\t\t[64+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[68+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 7\n\tmov\teax,\t\t[56+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[60+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 6\n\tmov\teax,\t\t[48+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[52+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 5\n\tmov\teax,\t\t[40+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[44+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 4\n\tmov\teax,\t\t[32+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[36+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 3\n\tmov\teax,\t\t[24+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[28+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 2\n\tmov\teax,\t\t[16+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[20+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 1\n\tmov\teax,\t\t[8+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[12+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 0\n\tmov\teax,\t\t[ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[4+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n$L001end:\n\t; \n\t; FP\n\tmov\tedx,\t\t[20+esp]\n\tror\tesi,\t\t1\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0aaaaaaaah\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\teax,\t\t23\n\tmov\tedi,\t\teax\n\txor\teax,\t\tesi\n\tand\teax,\t\t003fc03fch\n\txor\tedi,\t\teax\n\txor\tesi,\t\teax\n\t; \n\trol\tedi,\t\t10\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t033333333h\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\tesi,\t\t18\n\tmov\tedi,\t\tesi\n\txor\tesi,\t\teax\n\tand\tesi,\t\t0fff0000fh\n\txor\tedi,\t\tesi\n\txor\teax,\t\tesi\n\t; \n\trol\tedi,\t\t12\n\tmov\tesi,\t\tedi\n\txor\tedi,\t\teax\n\tand\tedi,\t\t0f0f0f0f0h\n\txor\tesi,\t\tedi\n\txor\teax,\t\tedi\n\t; \n\tror\teax,\t\t4\n\tmov\t[edx],\t\teax\n\tmov\t[4+edx],\tesi\n\tpop\tebp\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\nglobal\t_des_encrypt2\n_des_encrypt2:\n\tpush\tesi\n\tpush\tedi\n\t; \n\t; Load the 2 words\n\tmov\teax,\t\t[12+esp]\n\txor\tecx,\t\tecx\n\tpush\tebx\n\tpush\tebp\n\tmov\tesi,\t\t[eax]\n\tmov\tebx,\t\t[28+esp]\n\trol\tesi,\t\t3\n\tmov\tedi,\t\t[4+eax]\n\trol\tedi,\t\t3\n\tmov\tebp,\t\t[24+esp]\n\tcmp\tebx,\t\t0\n\tje NEAR\t$L002start_decrypt\n\t; \n\t; Round 0\n\tmov\teax,\t\t[ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[4+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 1\n\tmov\teax,\t\t[8+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[12+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 2\n\tmov\teax,\t\t[16+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[20+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 3\n\tmov\teax,\t\t[24+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[28+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 4\n\tmov\teax,\t\t[32+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[36+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 5\n\tmov\teax,\t\t[40+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[44+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 6\n\tmov\teax,\t\t[48+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[52+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 7\n\tmov\teax,\t\t[56+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[60+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 8\n\tmov\teax,\t\t[64+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[68+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 9\n\tmov\teax,\t\t[72+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[76+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 10\n\tmov\teax,\t\t[80+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[84+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 11\n\tmov\teax,\t\t[88+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[92+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 12\n\tmov\teax,\t\t[96+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[100+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 13\n\tmov\teax,\t\t[104+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[108+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 14\n\tmov\teax,\t\t[112+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[116+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 15\n\tmov\teax,\t\t[120+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[124+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\tjmp\t$L003end\n$L002start_decrypt:\n\t; \n\t; Round 15\n\tmov\teax,\t\t[120+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[124+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 14\n\tmov\teax,\t\t[112+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[116+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 13\n\tmov\teax,\t\t[104+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[108+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 12\n\tmov\teax,\t\t[96+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[100+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 11\n\tmov\teax,\t\t[88+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[92+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 10\n\tmov\teax,\t\t[80+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[84+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 9\n\tmov\teax,\t\t[72+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[76+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 8\n\tmov\teax,\t\t[64+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[68+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 7\n\tmov\teax,\t\t[56+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[60+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 6\n\tmov\teax,\t\t[48+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[52+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 5\n\tmov\teax,\t\t[40+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[44+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 4\n\tmov\teax,\t\t[32+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[36+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 3\n\tmov\teax,\t\t[24+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[28+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 2\n\tmov\teax,\t\t[16+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[20+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n\t; \n\t; Round 1\n\tmov\teax,\t\t[8+ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[12+ebp]\n\txor\teax,\t\tesi\n\txor\tedx,\t\tesi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tedi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tedi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tedi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tedi,\t\tebx\n\t; \n\t; Round 0\n\tmov\teax,\t\t[ebp]\n\txor\tebx,\t\tebx\n\tmov\tedx,\t\t[4+ebp]\n\txor\teax,\t\tedi\n\txor\tedx,\t\tedi\n\tand\teax,\t\t0fcfcfcfch\n\tand\tedx,\t\t0cfcfcfcfh\n\tmov\tbl,\t\tal\n\tmov\tcl,\t\tah\n\tror\tedx,\t\t4\n\tmov\tebp,\t\t[_des_SPtrans+ebx]\n\tmov\tbl,\t\tdl\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[_des_SPtrans+0200h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tcl,\t\tdh\n\tshr\teax,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0100h+ebx]\n\txor\tesi,\t\tebp\n\tmov\tbl,\t\tah\n\tshr\tedx,\t\t16\n\tmov\tebp,\t\t[_des_SPtrans+0300h+ecx]\n\txor\tesi,\t\tebp\n\tmov\tebp,\t\t[24+esp]\n\tmov\tcl,\t\tdh\n\tand\teax,\t\t0ffh\n\tand\tedx,\t\t0ffh\n\tmov\tebx,\t\t[_des_SPtrans+0600h+ebx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0700h+ecx]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0400h+eax]\n\txor\tesi,\t\tebx\n\tmov\tebx,\t\t[_des_SPtrans+0500h+edx]\n\txor\tesi,\t\tebx\n$L003end:\n\t; \n\t; Fixup\n\tror\tedi,\t\t3\n\tmov\teax,\t\t[20+esp]\n\tror\tesi,\t\t3\n\tmov\t[eax],\t\tedi\n\tmov\t[4+eax],\tesi\n\tpop\tebp\n\tpop\tebx\n\tpop\tedi\n\tpop\tesi\n\tret\nglobal\t_des_encrypt3\n_des_encrypt3:\n\tpush\tebx\n\tmov\tebx,\t\t[8+esp]\n\tpush\tebp\n\tpush\tesi\n\tpush\tedi\n\t; \n\t; Load the data words\n\tmov\tedi,\t\t[ebx]\n\tmov\tesi,\t\t[4+ebx]\n\tsub\tesp,\t\t12\n\t; \n\t; IP\n\trol\tedi,\t\t4\n\tmov\tedx,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0f0f0f0f0h\n\txor\tedx,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\tesi,\t\t20\n\tmov\tedi,\t\tesi\n\txor\tesi,\t\tedx\n\tand\tesi,\t\t0fff0000fh\n\txor\tedi,\t\tesi\n\txor\tedx,\t\tesi\n\t; \n\trol\tedi,\t\t14\n\tmov\tesi,\t\tedi\n\txor\tedi,\t\tedx\n\tand\tedi,\t\t033333333h\n\txor\tesi,\t\tedi\n\txor\tedx,\t\tedi\n\t; \n\trol\tedx,\t\t22\n\tmov\tedi,\t\tedx\n\txor\tedx,\t\tesi\n\tand\tedx,\t\t003fc03fch\n\txor\tedi,\t\tedx\n\txor\tesi,\t\tedx\n\t; \n\trol\tedi,\t\t9\n\tmov\tedx,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0aaaaaaaah\n\txor\tedx,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\tror\tedx,\t\t3\n\tror\tesi,\t\t2\n\tmov\t[4+ebx],\tesi\n\tmov\teax,\t\t[36+esp]\n\tmov\t[ebx],\t\tedx\n\tmov\tedi,\t\t[40+esp]\n\tmov\tesi,\t\t[44+esp]\n\tmov\t[8+esp],\tDWORD 1\n\tmov\t[4+esp],\teax\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tmov\t[8+esp],\tDWORD 0\n\tmov\t[4+esp],\tedi\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tmov\t[8+esp],\tDWORD 1\n\tmov\t[4+esp],\tesi\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tadd\tesp,\t\t12\n\tmov\tedi,\t\t[ebx]\n\tmov\tesi,\t\t[4+ebx]\n\t; \n\t; FP\n\trol\tesi,\t\t2\n\trol\tedi,\t\t3\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0aaaaaaaah\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\teax,\t\t23\n\tmov\tedi,\t\teax\n\txor\teax,\t\tesi\n\tand\teax,\t\t003fc03fch\n\txor\tedi,\t\teax\n\txor\tesi,\t\teax\n\t; \n\trol\tedi,\t\t10\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t033333333h\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\tesi,\t\t18\n\tmov\tedi,\t\tesi\n\txor\tesi,\t\teax\n\tand\tesi,\t\t0fff0000fh\n\txor\tedi,\t\tesi\n\txor\teax,\t\tesi\n\t; \n\trol\tedi,\t\t12\n\tmov\tesi,\t\tedi\n\txor\tedi,\t\teax\n\tand\tedi,\t\t0f0f0f0f0h\n\txor\tesi,\t\tedi\n\txor\teax,\t\tedi\n\t; \n\tror\teax,\t\t4\n\tmov\t[ebx],\t\teax\n\tmov\t[4+ebx],\tesi\n\tpop\tedi\n\tpop\tesi\n\tpop\tebp\n\tpop\tebx\n\tret\nglobal\t_des_decrypt3\n_des_decrypt3:\n\tpush\tebx\n\tmov\tebx,\t\t[8+esp]\n\tpush\tebp\n\tpush\tesi\n\tpush\tedi\n\t; \n\t; Load the data words\n\tmov\tedi,\t\t[ebx]\n\tmov\tesi,\t\t[4+ebx]\n\tsub\tesp,\t\t12\n\t; \n\t; IP\n\trol\tedi,\t\t4\n\tmov\tedx,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0f0f0f0f0h\n\txor\tedx,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\tesi,\t\t20\n\tmov\tedi,\t\tesi\n\txor\tesi,\t\tedx\n\tand\tesi,\t\t0fff0000fh\n\txor\tedi,\t\tesi\n\txor\tedx,\t\tesi\n\t; \n\trol\tedi,\t\t14\n\tmov\tesi,\t\tedi\n\txor\tedi,\t\tedx\n\tand\tedi,\t\t033333333h\n\txor\tesi,\t\tedi\n\txor\tedx,\t\tedi\n\t; \n\trol\tedx,\t\t22\n\tmov\tedi,\t\tedx\n\txor\tedx,\t\tesi\n\tand\tedx,\t\t003fc03fch\n\txor\tedi,\t\tedx\n\txor\tesi,\t\tedx\n\t; \n\trol\tedi,\t\t9\n\tmov\tedx,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0aaaaaaaah\n\txor\tedx,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\tror\tedx,\t\t3\n\tror\tesi,\t\t2\n\tmov\t[4+ebx],\tesi\n\tmov\tesi,\t\t[36+esp]\n\tmov\t[ebx],\t\tedx\n\tmov\tedi,\t\t[40+esp]\n\tmov\teax,\t\t[44+esp]\n\tmov\t[8+esp],\tDWORD 0\n\tmov\t[4+esp],\teax\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tmov\t[8+esp],\tDWORD 1\n\tmov\t[4+esp],\tedi\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tmov\t[8+esp],\tDWORD 0\n\tmov\t[4+esp],\tesi\n\tmov\t[esp],\t\tebx\n\tcall\t_des_encrypt2\n\tadd\tesp,\t\t12\n\tmov\tedi,\t\t[ebx]\n\tmov\tesi,\t\t[4+ebx]\n\t; \n\t; FP\n\trol\tesi,\t\t2\n\trol\tedi,\t\t3\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t0aaaaaaaah\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\teax,\t\t23\n\tmov\tedi,\t\teax\n\txor\teax,\t\tesi\n\tand\teax,\t\t003fc03fch\n\txor\tedi,\t\teax\n\txor\tesi,\t\teax\n\t; \n\trol\tedi,\t\t10\n\tmov\teax,\t\tedi\n\txor\tedi,\t\tesi\n\tand\tedi,\t\t033333333h\n\txor\teax,\t\tedi\n\txor\tesi,\t\tedi\n\t; \n\trol\tesi,\t\t18\n\tmov\tedi,\t\tesi\n\txor\tesi,\t\teax\n\tand\tesi,\t\t0fff0000fh\n\txor\tedi,\t\tesi\n\txor\teax,\t\tesi\n\t; \n\trol\tedi,\t\t12\n\tmov\tesi,\t\tedi\n\txor\tedi,\t\teax\n\tand\tedi,\t\t0f0f0f0f0h\n\txor\tesi,\t\tedi\n\txor\teax,\t\tedi\n\t; \n\tror\teax,\t\t4\n\tmov\t[ebx],\t\teax\n\tmov\t[4+ebx],\tesi\n\tpop\tedi\n\tpop\tesi\n\tpop\tebp\n\tpop\tebx\n\tret\nglobal\t_des_ncbc_encrypt\n_des_ncbc_encrypt:\n\t; \n\tpush\tebp\n\tpush\tebx\n\tpush\tesi\n\tpush\tedi\n\tmov\tebp,\t\t[28+esp]\n\t; getting iv ptr from parameter 4\n\tmov\tebx,\t\t[36+esp]\n\tmov\tesi,\t\t[ebx]\n\tmov\tedi,\t\t[4+ebx]\n\tpush\tedi\n\tpush\tesi\n\tpush\tedi\n\tpush\tesi\n\tmov\tebx,\t\tesp\n\tmov\tesi,\t\t[36+esp]\n\tmov\tedi,\t\t[40+esp]\n\t; getting encrypt flag from parameter 5\n\tmov\tecx,\t\t[56+esp]\n\t; get and push parameter 5\n\tpush\tecx\n\t; get and push parameter 3\n\tmov\teax,\t\t[52+esp]\n\tpush\teax\n\tpush\tebx\n\tcmp\tecx,\t\t0\n\tjz NEAR\t$L004decrypt\n\tand\tebp,\t\t4294967288\n\tmov\teax,\t\t[12+esp]\n\tmov\tebx,\t\t[16+esp]\n\tjz NEAR\t$L005encrypt_finish\nL006encrypt_loop:\n\tmov\tecx,\t\t[esi]\n\tmov\tedx,\t\t[4+esi]\n\txor\teax,\t\tecx\n\txor\tebx,\t\tedx\n\tmov\t[12+esp],\teax\n\tmov\t[16+esp],\tebx\n\tcall\t_des_encrypt1\n\tmov\teax,\t\t[12+esp]\n\tmov\tebx,\t\t[16+esp]\n\tmov\t[edi],\t\teax\n\tmov\t[4+edi],\tebx\n\tadd\tesi,\t\t8\n\tadd\tedi,\t\t8\n\tsub\tebp,\t\t8\n\tjnz NEAR\tL006encrypt_loop\n$L005encrypt_finish:\n\tmov\tebp,\t\t[56+esp]\n\tand\tebp,\t\t7\n\tjz NEAR\t$L007finish\n\txor\tecx,\t\tecx\n\txor\tedx,\t\tedx\n\tmov\tebp,\t\t[$L008cbc_enc_jmp_table+ebp*4]\n\tjmp\t ebp\nL009ej7:\n\tmov\tdh,\t\t[6+esi]\n\tshl\tedx,\t\t8\nL010ej6:\n\tmov\tdh,\t\t[5+esi]\nL011ej5:\n\tmov\tdl,\t\t[4+esi]\nL012ej4:\n\tmov\tecx,\t\t[esi]\n\tjmp\t$L013ejend\nL014ej3:\n\tmov\tch,\t\t[2+esi]\n\tshl\tecx,\t\t8\nL015ej2:\n\tmov\tch,\t\t[1+esi]\nL016ej1:\n\tmov\tcl,\t\t[esi]\n$L013ejend:\n\txor\teax,\t\tecx\n\txor\tebx,\t\tedx\n\tmov\t[12+esp],\teax\n\tmov\t[16+esp],\tebx\n\tcall\t_des_encrypt1\n\tmov\teax,\t\t[12+esp]\n\tmov\tebx,\t\t[16+esp]\n\tmov\t[edi],\t\teax\n\tmov\t[4+edi],\tebx\n\tjmp\t$L007finish\n$L004decrypt:\n\tand\tebp,\t\t4294967288\n\tmov\teax,\t\t[20+esp]\n\tmov\tebx,\t\t[24+esp]\n\tjz NEAR\t$L017decrypt_finish\nL018decrypt_loop:\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[12+esp],\teax\n\tmov\t[16+esp],\tebx\n\tcall\t_des_encrypt1\n\tmov\teax,\t\t[12+esp]\n\tmov\tebx,\t\t[16+esp]\n\tmov\tecx,\t\t[20+esp]\n\tmov\tedx,\t\t[24+esp]\n\txor\tecx,\t\teax\n\txor\tedx,\t\tebx\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[edi],\t\tecx\n\tmov\t[4+edi],\tedx\n\tmov\t[20+esp],\teax\n\tmov\t[24+esp],\tebx\n\tadd\tesi,\t\t8\n\tadd\tedi,\t\t8\n\tsub\tebp,\t\t8\n\tjnz NEAR\tL018decrypt_loop\n$L017decrypt_finish:\n\tmov\tebp,\t\t[56+esp]\n\tand\tebp,\t\t7\n\tjz NEAR\t$L007finish\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[12+esp],\teax\n\tmov\t[16+esp],\tebx\n\tcall\t_des_encrypt1\n\tmov\teax,\t\t[12+esp]\n\tmov\tebx,\t\t[16+esp]\n\tmov\tecx,\t\t[20+esp]\n\tmov\tedx,\t\t[24+esp]\n\txor\tecx,\t\teax\n\txor\tedx,\t\tebx\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\nL019dj7:\n\tror\tedx,\t\t16\n\tmov\t[6+edi],\tdl\n\tshr\tedx,\t\t16\nL020dj6:\n\tmov\t[5+edi],\tdh\nL021dj5:\n\tmov\t[4+edi],\tdl\nL022dj4:\n\tmov\t[edi],\t\tecx\n\tjmp\t$L023djend\nL024dj3:\n\tror\tecx,\t\t16\n\tmov\t[2+edi],\tcl\n\tshl\tecx,\t\t16\nL025dj2:\n\tmov\t[1+esi],\tch\nL026dj1:\n\tmov\t[esi],\t\tcl\n$L023djend:\n\tjmp\t$L007finish\n$L007finish:\n\tmov\tecx,\t\t[64+esp]\n\tadd\tesp,\t\t28\n\tmov\t[ecx],\t\teax\n\tmov\t[4+ecx],\tebx\n\tpop\tedi\n\tpop\tesi\n\tpop\tebx\n\tpop\tebp\n\tret\n$L008cbc_enc_jmp_table:\n\tDD\t0\n\tDD\tL016ej1\n\tDD\tL015ej2\n\tDD\tL014ej3\n\tDD\tL012ej4\n\tDD\tL011ej5\n\tDD\tL010ej6\n\tDD\tL009ej7\nL027cbc_dec_jmp_table:\n\tDD\t0\n\tDD\tL026dj1\n\tDD\tL025dj2\n\tDD\tL024dj3\n\tDD\tL022dj4\n\tDD\tL021dj5\n\tDD\tL020dj6\n\tDD\tL019dj7\nglobal\t_des_ede3_cbc_encrypt\n_des_ede3_cbc_encrypt:\n\t; \n\tpush\tebp\n\tpush\tebx\n\tpush\tesi\n\tpush\tedi\n\tmov\tebp,\t\t[28+esp]\n\t; getting iv ptr from parameter 6\n\tmov\tebx,\t\t[44+esp]\n\tmov\tesi,\t\t[ebx]\n\tmov\tedi,\t\t[4+ebx]\n\tpush\tedi\n\tpush\tesi\n\tpush\tedi\n\tpush\tesi\n\tmov\tebx,\t\tesp\n\tmov\tesi,\t\t[36+esp]\n\tmov\tedi,\t\t[40+esp]\n\t; getting encrypt flag from parameter 7\n\tmov\tecx,\t\t[64+esp]\n\t; get and push parameter 5\n\tmov\teax,\t\t[56+esp]\n\tpush\teax\n\t; get and push parameter 4\n\tmov\teax,\t\t[56+esp]\n\tpush\teax\n\t; get and push parameter 3\n\tmov\teax,\t\t[56+esp]\n\tpush\teax\n\tpush\tebx\n\tcmp\tecx,\t\t0\n\tjz NEAR\t$L028decrypt\n\tand\tebp,\t\t4294967288\n\tmov\teax,\t\t[16+esp]\n\tmov\tebx,\t\t[20+esp]\n\tjz NEAR\t$L029encrypt_finish\nL030encrypt_loop:\n\tmov\tecx,\t\t[esi]\n\tmov\tedx,\t\t[4+esi]\n\txor\teax,\t\tecx\n\txor\tebx,\t\tedx\n\tmov\t[16+esp],\teax\n\tmov\t[20+esp],\tebx\n\tcall\t_des_encrypt3\n\tmov\teax,\t\t[16+esp]\n\tmov\tebx,\t\t[20+esp]\n\tmov\t[edi],\t\teax\n\tmov\t[4+edi],\tebx\n\tadd\tesi,\t\t8\n\tadd\tedi,\t\t8\n\tsub\tebp,\t\t8\n\tjnz NEAR\tL030encrypt_loop\n$L029encrypt_finish:\n\tmov\tebp,\t\t[60+esp]\n\tand\tebp,\t\t7\n\tjz NEAR\t$L031finish\n\txor\tecx,\t\tecx\n\txor\tedx,\t\tedx\n\tmov\tebp,\t\t[$L032cbc_enc_jmp_table+ebp*4]\n\tjmp\t ebp\nL033ej7:\n\tmov\tdh,\t\t[6+esi]\n\tshl\tedx,\t\t8\nL034ej6:\n\tmov\tdh,\t\t[5+esi]\nL035ej5:\n\tmov\tdl,\t\t[4+esi]\nL036ej4:\n\tmov\tecx,\t\t[esi]\n\tjmp\t$L037ejend\nL038ej3:\n\tmov\tch,\t\t[2+esi]\n\tshl\tecx,\t\t8\nL039ej2:\n\tmov\tch,\t\t[1+esi]\nL040ej1:\n\tmov\tcl,\t\t[esi]\n$L037ejend:\n\txor\teax,\t\tecx\n\txor\tebx,\t\tedx\n\tmov\t[16+esp],\teax\n\tmov\t[20+esp],\tebx\n\tcall\t_des_encrypt3\n\tmov\teax,\t\t[16+esp]\n\tmov\tebx,\t\t[20+esp]\n\tmov\t[edi],\t\teax\n\tmov\t[4+edi],\tebx\n\tjmp\t$L031finish\n$L028decrypt:\n\tand\tebp,\t\t4294967288\n\tmov\teax,\t\t[24+esp]\n\tmov\tebx,\t\t[28+esp]\n\tjz NEAR\t$L041decrypt_finish\nL042decrypt_loop:\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[16+esp],\teax\n\tmov\t[20+esp],\tebx\n\tcall\t_des_decrypt3\n\tmov\teax,\t\t[16+esp]\n\tmov\tebx,\t\t[20+esp]\n\tmov\tecx,\t\t[24+esp]\n\tmov\tedx,\t\t[28+esp]\n\txor\tecx,\t\teax\n\txor\tedx,\t\tebx\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[edi],\t\tecx\n\tmov\t[4+edi],\tedx\n\tmov\t[24+esp],\teax\n\tmov\t[28+esp],\tebx\n\tadd\tesi,\t\t8\n\tadd\tedi,\t\t8\n\tsub\tebp,\t\t8\n\tjnz NEAR\tL042decrypt_loop\n$L041decrypt_finish:\n\tmov\tebp,\t\t[60+esp]\n\tand\tebp,\t\t7\n\tjz NEAR\t$L031finish\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\n\tmov\t[16+esp],\teax\n\tmov\t[20+esp],\tebx\n\tcall\t_des_decrypt3\n\tmov\teax,\t\t[16+esp]\n\tmov\tebx,\t\t[20+esp]\n\tmov\tecx,\t\t[24+esp]\n\tmov\tedx,\t\t[28+esp]\n\txor\tecx,\t\teax\n\txor\tedx,\t\tebx\n\tmov\teax,\t\t[esi]\n\tmov\tebx,\t\t[4+esi]\nL043dj7:\n\tror\tedx,\t\t16\n\tmov\t[6+edi],\tdl\n\tshr\tedx,\t\t16\nL044dj6:\n\tmov\t[5+edi],\tdh\nL045dj5:\n\tmov\t[4+edi],\tdl\nL046dj4:\n\tmov\t[edi],\t\tecx\n\tjmp\t$L047djend\nL048dj3:\n\tror\tecx,\t\t16\n\tmov\t[2+edi],\tcl\n\tshl\tecx,\t\t16\nL049dj2:\n\tmov\t[1+esi],\tch\nL050dj1:\n\tmov\t[esi],\t\tcl\n$L047djend:\n\tjmp\t$L031finish\n$L031finish:\n\tmov\tecx,\t\t[76+esp]\n\tadd\tesp,\t\t32\n\tmov\t[ecx],\t\teax\n\tmov\t[4+ecx],\tebx\n\tpop\tedi\n\tpop\tesi\n\tpop\tebx\n\tpop\tebp\n\tret\n$L032cbc_enc_jmp_table:\n\tDD\t0\n\tDD\tL040ej1\n\tDD\tL039ej2\n\tDD\tL038ej3\n\tDD\tL036ej4\n\tDD\tL035ej5\n\tDD\tL034ej6\n\tDD\tL033ej7\nL051cbc_dec_jmp_table:\n\tDD\t0\n\tDD\tL050dj1\n\tDD\tL049dj2\n\tDD\tL048dj3\n\tDD\tL046dj4\n\tDD\tL045dj5\n\tDD\tL044dj6\n\tDD\tL043dj7\n"
  },
  {
    "path": "deps/cl345/crypt/des.h",
    "content": "/* crypto/des/des.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_DES_H\n#define HEADER_DES_H\n\n#ifndef _OSCONFIG_DEFINED\t\t/* pcg */\n  #if defined( INC_ALL )\n\t#include \"osconfig.h\"\n  #else\n\t#include \"crypt/osconfig.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _OSCONFIG_DEFINED */\n\n#ifdef DES_INT\t/* pcg */\n  #define DES_LONG\tunsigned int\n#else\n  #define DES_LONG\tunsigned long\n#endif /* Alpha */\n\n#ifdef NO_DES\n#error DES is disabled.\n#endif\n\n#ifdef _KERBEROS_DES_H\n#error <openssl/des.h> replaces <kerberos/des.h>.\n#endif\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\ntypedef unsigned char des_cblock[8];\ntypedef /* const */ unsigned char const_des_cblock[8];\n/* With \"const\", gcc 2.8.1 on Solaris thinks that des_cblock *\n * and const_des_cblock * are incompatible pointer types. */\n\ntypedef struct des_ks_struct\n\t{\n\tunion\t{\n\t\tdes_cblock cblock;\n\t\t/* make sure things are correct size on machines with\n\t\t * 8 byte longs */\n\t\tDES_LONG deslong[2];\n\t\t} ks;\n\tint weak_key;\n\t} des_key_schedule[16];\n\n#define DES_KEY_SZ \t(sizeof(des_cblock))\n#define DES_SCHEDULE_SZ (sizeof(des_key_schedule))\n\n#define DES_ENCRYPT\t1\n#define DES_DECRYPT\t0\n\n#define DES_CBC_MODE\t0\n#define DES_PCBC_MODE\t1\n\n#define des_ecb2_encrypt(i,o,k1,k2,e) \\\n\tdes_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e))\n\n#define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \\\n\tdes_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e))\n\n#define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \\\n\tdes_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e))\n\n#define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \\\n\tdes_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n))\n\nextern int des_check_key;\t/* defaults to false */\nextern int des_rw_mode;\t\t/* defaults to DES_PCBC_MODE */\nextern int des_set_weak_key_flag; /* set the weak key flag */\n\nconst char *des_options(void);\nvoid des_ecb3_encrypt(const_des_cblock *input, des_cblock *output,\n\t\t      des_key_schedule ks1,des_key_schedule ks2,\n\t\t      des_key_schedule ks3, int enc);\nDES_LONG des_cbc_cksum(const unsigned char *input,des_cblock *output,\n\t\t       long length,des_key_schedule schedule,\n\t\t       const_des_cblock *ivec);\n/* des_cbc_encrypt does not update the IV!  Use des_ncbc_encrypt instead. */\nvoid des_cbc_encrypt(const unsigned char *input,unsigned char *output,\n\t\t     long length,des_key_schedule schedule,des_cblock *ivec,\n\t\t     int enc);\nvoid ASM_EXPORT des_ncbc_encrypt(const unsigned char *input,unsigned char *output,\n\t\t      long length,des_key_schedule schedule,des_cblock *ivec,\n\t\t      int enc);\t\t\t\t\t\t\t\t\t\t/* pcg */\nvoid des_xcbc_encrypt(const unsigned char *input,unsigned char *output,\n\t\t      long length,des_key_schedule schedule,des_cblock *ivec,\n\t\t      const_des_cblock *inw,const_des_cblock *outw,int enc);\nvoid des_cfb_encrypt(const unsigned char *in,unsigned char *out,int numbits,\n\t\t     long length,des_key_schedule schedule,des_cblock *ivec,\n\t\t     int enc);\nvoid des_ecb_encrypt(const_des_cblock *input,des_cblock *output,\n\t\t     des_key_schedule ks,int enc);\n\n/* \tThis is the DES encryption function that gets called by just about\n\tevery other DES routine in the library.  You should not use this\n\tfunction except to implement 'modes' of DES.  I say this because the\n\tfunctions that call this routine do the conversion from 'char *' to\n\tlong, and this needs to be done to make sure 'non-aligned' memory\n\taccess do not occur.  The characters are loaded 'little endian'.\n\tData is a pointer to 2 unsigned long's and ks is the\n\tdes_key_schedule to use.  enc, is non zero specifies encryption,\n\tzero if decryption. */\nvoid ASM_EXPORT des_encrypt1(DES_LONG *data,des_key_schedule ks, int enc);\t/* pcg */\n\n/* \tThis functions is the same as des_encrypt1() except that the DES\n\tinitial permutation (IP) and final permutation (FP) have been left\n\tout.  As for des_encrypt1(), you should not use this function.\n\tIt is used by the routines in the library that implement triple DES.\n\tIP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same\n\tas des_encrypt1() des_encrypt1() des_encrypt1() except faster :-). */\nvoid des_encrypt2(DES_LONG *data,des_key_schedule ks, int enc);\n\nvoid ASM_EXPORT des_encrypt3(DES_LONG *data, des_key_schedule ks1,\t\t\t/* pcg */\n\tdes_key_schedule ks2, des_key_schedule ks3);\nvoid ASM_EXPORT des_decrypt3(DES_LONG *data, des_key_schedule ks1,\t\t\t/* pcg */\n\tdes_key_schedule ks2, des_key_schedule ks3);\nvoid des_ede3_cbc_encrypt(const unsigned char *input,unsigned char *output,\n\t\t\t  long length,\n\t\t\t  des_key_schedule ks1,des_key_schedule ks2,\n\t\t\t  des_key_schedule ks3,des_cblock *ivec,int enc);\t\t\t\t/* pcg */\nvoid des_ede3_cbcm_encrypt(const unsigned char *in,unsigned char *out,\n\t\t\t   long length,\n\t\t\t   des_key_schedule ks1,des_key_schedule ks2,\n\t\t\t   des_key_schedule ks3,\n\t\t\t   des_cblock *ivec1,des_cblock *ivec2,\n\t\t\t   int enc);\nvoid des_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out,\n\t\t\t    long length,des_key_schedule ks1,\n\t\t\t    des_key_schedule ks2,des_key_schedule ks3,\n\t\t\t    des_cblock *ivec,int *num,int enc);\nvoid des_ede3_ofb64_encrypt(const unsigned char *in,unsigned char *out,\n\t\t\t    long length,des_key_schedule ks1,\n\t\t\t    des_key_schedule ks2,des_key_schedule ks3,\n\t\t\t    des_cblock *ivec,int *num);\n\nvoid des_xwhite_in2out(const_des_cblock *des_key,const_des_cblock *in_white,\n\t\t       des_cblock *out_white);\n\nint des_enc_read(int fd,void *buf,int len,des_key_schedule sched,\n\t\t des_cblock *iv);\nint des_enc_write(int fd,const void *buf,int len,des_key_schedule sched,\n\t\t  des_cblock *iv);\nchar *des_fcrypt(const char *buf,const char *salt, char *ret);\nchar *des_crypt(const char *buf,const char *salt);\n#if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT)\nchar *crypt(const char *buf,const char *salt);\n#endif\nvoid des_ofb_encrypt(const unsigned char *in,unsigned char *out,int numbits,\n\t\t     long length,des_key_schedule schedule,des_cblock *ivec);\nvoid des_pcbc_encrypt(const unsigned char *input,unsigned char *output,\n\t\t      long length,des_key_schedule schedule,des_cblock *ivec,\n\t\t      int enc);\nDES_LONG des_quad_cksum(const unsigned char *input,des_cblock output[],\n\t\t\tlong length,int out_count,des_cblock *seed);\nvoid des_random_seed(des_cblock *key);\nint des_random_key(des_cblock *ret);\nint des_read_password(des_cblock *key,const char *prompt,int verify);\nint des_read_2passwords(des_cblock *key1,des_cblock *key2,\n\t\t\tconst char *prompt,int verify);\nint des_read_pw_string(char *buf,int length,const char *prompt,int verify);\nvoid des_set_odd_parity(des_cblock *key);\nint des_check_key_parity(const_des_cblock *key);\nint des_is_weak_key(const_des_cblock *key);\n/* des_set_key (= set_key = des_key_sched = key_sched) calls\n * des_set_key_checked if global variable des_check_key is set,\n * des_set_key_unchecked otherwise. */\nint des_set_key(const_des_cblock *key,des_key_schedule schedule);\nint des_key_sched(const_des_cblock *key,des_key_schedule schedule);\nint des_set_key_checked(const_des_cblock *key,des_key_schedule schedule);\nvoid des_set_key_unchecked(const_des_cblock *key,des_key_schedule schedule);\nvoid des_string_to_key(const char *str,des_cblock *key);\nvoid des_string_to_2keys(const char *str,des_cblock *key1,des_cblock *key2);\nvoid des_cfb64_encrypt(const unsigned char *in,unsigned char *out,long length,\n\t\t       des_key_schedule schedule,des_cblock *ivec,int *num,\n\t\t       int enc);\nvoid des_ofb64_encrypt(const unsigned char *in,unsigned char *out,long length,\n\t\t       des_key_schedule schedule,des_cblock *ivec,int *num);\nint des_read_pw(char *buf,char *buff,int size,const char *prompt,int verify);\n\n/* The following definitions provide compatibility with the MIT Kerberos\n * library. The des_key_schedule structure is not binary compatible. */\n\n#define _KERBEROS_DES_H\n\n#define KRBDES_ENCRYPT DES_ENCRYPT\n#define KRBDES_DECRYPT DES_DECRYPT\n\n#ifdef KERBEROS\n#  define ENCRYPT DES_ENCRYPT\n#  define DECRYPT DES_DECRYPT\n#endif\n\n#ifndef NCOMPAT\n#  define C_Block des_cblock\n#  define Key_schedule des_key_schedule\n#  define KEY_SZ DES_KEY_SZ\n#  define string_to_key des_string_to_key\n#  define read_pw_string des_read_pw_string\n#  define random_key des_random_key\n#  define pcbc_encrypt des_pcbc_encrypt\n#  define set_key des_set_key\n#  define key_sched des_key_sched\n#  define ecb_encrypt des_ecb_encrypt\n#  define cbc_encrypt des_cbc_encrypt\n#  define ncbc_encrypt des_ncbc_encrypt\n#  define xcbc_encrypt des_xcbc_encrypt\n#  define cbc_cksum des_cbc_cksum\n#  define quad_cksum des_quad_cksum\n#  define check_parity des_check_key_parity\n#endif\n\ntypedef des_key_schedule bit_64;\n#define des_fixup_key_parity des_set_odd_parity\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/descbc.c",
    "content": "/* crypto/des/ncbc_enc.c */\n/*\n * #included by:\n *    cbc_enc.c  (des_cbc_encrypt)\n *    des_enc.c  (des_ncbc_encrypt)\n */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n  #include \"deslocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n  #include \"crypt/deslocl.h\"\n#endif /* Compiler-specific includes */\n\n#ifndef USE_ASM\t/* Needed for complex asm-replacement or C code */\n\n#ifdef CBC_ENC_C__DONT_UPDATE_IV\nvoid des_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t     des_key_schedule schedule, des_cblock *ivec, int enc)\n#else\nvoid des_ncbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t     des_key_schedule schedule, des_cblock *ivec, int enc)\n#endif\n\t{\n\tregister DES_LONG tin0,tin1;\n\tregister DES_LONG tout0,tout1,xor0,xor1;\n\tregister long l=length;\n\tDES_LONG tin[2];\n\tunsigned char *iv;\n\n\tiv = &(*ivec)[0];\n\n\tif (enc)\n\t\t{\n\t\tc2l(iv,tout0);\n\t\tc2l(iv,tout1);\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0);\n\t\t\tc2l(in,tin1);\n\t\t\ttin0^=tout0; tin[0]=tin0;\n\t\t\ttin1^=tout1; tin[1]=tin1;\n\t\t\tdes_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT);\n\t\t\ttout0=tin[0]; l2c(tout0,out);\n\t\t\ttout1=tin[1]; l2c(tout1,out);\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2ln(in,tin0,tin1,l+8);\n\t\t\ttin0^=tout0; tin[0]=tin0;\n\t\t\ttin1^=tout1; tin[1]=tin1;\n\t\t\tdes_encrypt1((DES_LONG *)tin,schedule,DES_ENCRYPT);\n\t\t\ttout0=tin[0]; l2c(tout0,out);\n\t\t\ttout1=tin[1]; l2c(tout1,out);\n\t\t\t}\n#ifndef CBC_ENC_C__DONT_UPDATE_IV\n\t\tiv = &(*ivec)[0];\n\t\tl2c(tout0,iv);\n\t\tl2c(tout1,iv);\n#endif\n\t\t}\n\telse\n\t\t{\n\t\tc2l(iv,xor0);\n\t\tc2l(iv,xor1);\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0); tin[0]=tin0;\n\t\t\tc2l(in,tin1); tin[1]=tin1;\n\t\t\tdes_encrypt1((DES_LONG *)tin,schedule,DES_DECRYPT);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2c(tout0,out);\n\t\t\tl2c(tout1,out);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2l(in,tin0); tin[0]=tin0;\n\t\t\tc2l(in,tin1); tin[1]=tin1;\n\t\t\tdes_encrypt1((DES_LONG *)tin,schedule,DES_DECRYPT);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2cn(tout0,tout1,out,l+8);\n#ifndef CBC_ENC_C__DONT_UPDATE_IV\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n#endif\n\t\t\t}\n#ifndef CBC_ENC_C__DONT_UPDATE_IV\n\t\tiv = &(*ivec)[0];\n\t\tl2c(xor0,iv);\n\t\tl2c(xor1,iv);\n#endif\n\t\t}\n\ttin0=tin1=tout0=tout1=xor0=xor1=0;\n\ttin[0]=tin[1]=0;\n\t}\n#endif /* USE_ASM */\n"
  },
  {
    "path": "deps/cl345/crypt/desecb.c",
    "content": "/* crypto/des/ecb_enc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n  #include \"deslocl.h\"\n  #include \"spr.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n  #include \"crypt/deslocl.h\"\n  #include \"crypt/spr.h\"\n#endif /* Compiler-specific includes */\n\n#if 0\t/* pcg */\n\nconst char *des_options(void)\n\t{\n\tstatic int init=1;\n\tstatic char buf[32];\n\n\tif (init)\n\t\t{\n\t\tconst char *ptr,*unroll,*risc,*size;\n\n#ifdef DES_PTR\n\t\tptr=\"ptr\";\n#else\n\t\tptr=\"idx\";\n#endif\n#if defined(DES_RISC1) || defined(DES_RISC2)\n#ifdef DES_RISC1\n\t\trisc=\"risc1\";\n#endif\n#ifdef DES_RISC2\n\t\trisc=\"risc2\";\n#endif\n#else\n\t\trisc=\"cisc\";\n#endif\n#ifdef DES_UNROLL\n\t\tunroll=\"16\";\n#else\n\t\tunroll=\"4\";\n#endif\n\t\tif (sizeof(DES_LONG) != sizeof(long))\n\t\t\tsize=\"int\";\n\t\telse\n\t\t\tsize=\"long\";\n\t\tsprintf(buf,\"des(%s,%s,%s,%s)\",ptr,risc,unroll,size);\n\t\tinit=0;\n\t\t}\n\treturn(buf);\n\t}\n#endif /* 0 */\n\nvoid des_ecb_encrypt(const_des_cblock *input, des_cblock *output,\n\t     des_key_schedule ks,\n\t     int enc)\n\t{\n\tregister DES_LONG l;\n\tDES_LONG ll[2];\n\tconst unsigned char *in = &(*input)[0];\n\tunsigned char *out = &(*output)[0];\n\n\tc2l(in,l); ll[0]=l;\n\tc2l(in,l); ll[1]=l;\n\tdes_encrypt1(ll,ks,enc);\n\tl=ll[0]; l2c(l,out);\n\tl=ll[1]; l2c(l,out);\n\tl=ll[0]=ll[1]=0;\n\t}\n\n"
  },
  {
    "path": "deps/cl345/crypt/desecb3.c",
    "content": "/* crypto/des/ecb3_enc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n  #include \"deslocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n  #include \"crypt/deslocl.h\"\n#endif /* Compiler-specific includes */\n\nvoid des_ecb3_encrypt(const_des_cblock *input, des_cblock *output,\n\t     des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3,\n\t     int enc)\n\t{\n\tregister DES_LONG l0,l1;\n\tDES_LONG ll[2];\n\tconst unsigned char *in = &(*input)[0];\n\tunsigned char *out = &(*output)[0];\n\n\tc2l(in,l0);\n\tc2l(in,l1);\n\tll[0]=l0;\n\tll[1]=l1;\n\tif (enc)\n\t\tdes_encrypt3(ll,ks1,ks2,ks3);\n\telse\n\t\tdes_decrypt3(ll,ks1,ks2,ks3);\n\tl0=ll[0];\n\tl1=ll[1];\n\tl2c(l0,out);\n\tl2c(l1,out);\n\t}\n"
  },
  {
    "path": "deps/cl345/crypt/desenc.c",
    "content": "/* crypto/des/des_enc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#define CHECK_ENDIANNESS\t/* One-off sanity check for osconfig.h */\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n  #include \"deslocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n  #include \"crypt/deslocl.h\"\n#endif /* Compiler-specific includes */\n\n#ifndef USE_ASM\n\n/* OpenSSL includes some sort of Configure-based versioning mechanism which\n   includes an attribution notice in the code, since cryptlib doesn't use\n   Configure (or the OpenSSL config) we hardcode in the following which \n   should have the same effect */\n\nstatic const char *version1=\"This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)\";\nstatic const char *version2=\"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)\";\n\nvoid des_encrypt1(DES_LONG *data, des_key_schedule ks, int enc)\n\t{\n\tregister DES_LONG l,r,t,u;\n#ifdef DES_PTR\n\tregister const unsigned char *des_SP=(const unsigned char *)des_SPtrans;\n#endif\n#ifndef DES_UNROLL\n\tregister int i;\n#endif\n\tregister DES_LONG *s;\n\n\tr=data[0];\n\tl=data[1];\n\n\tIP(r,l);\n\t/* Things have been modified so that the initial rotate is\n\t * done outside the loop.  This required the\n\t * des_SPtrans values in sp.h to be rotated 1 bit to the right.\n\t * One perl script later and things have a 5% speed up on a sparc2.\n\t * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>\n\t * for pointing this out. */\n\t/* clear the top bits on machines with 8byte longs */\n\t/* shift left by 2 */\n\tr=ROTATE(r,29)&0xffffffffL;\n\tl=ROTATE(l,29)&0xffffffffL;\n\n\ts=ks->ks.deslong;\n\t/* I don't know if it is worth the effort of loop unrolling the\n\t * inner loop */\n\tif (enc)\n\t\t{\n#ifdef DES_UNROLL\n\t\tD_ENCRYPT(l,r, 0); /*  1 */\n\t\tD_ENCRYPT(r,l, 2); /*  2 */\n\t\tD_ENCRYPT(l,r, 4); /*  3 */\n\t\tD_ENCRYPT(r,l, 6); /*  4 */\n\t\tD_ENCRYPT(l,r, 8); /*  5 */\n\t\tD_ENCRYPT(r,l,10); /*  6 */\n\t\tD_ENCRYPT(l,r,12); /*  7 */\n\t\tD_ENCRYPT(r,l,14); /*  8 */\n\t\tD_ENCRYPT(l,r,16); /*  9 */\n\t\tD_ENCRYPT(r,l,18); /*  10 */\n\t\tD_ENCRYPT(l,r,20); /*  11 */\n\t\tD_ENCRYPT(r,l,22); /*  12 */\n\t\tD_ENCRYPT(l,r,24); /*  13 */\n\t\tD_ENCRYPT(r,l,26); /*  14 */\n\t\tD_ENCRYPT(l,r,28); /*  15 */\n\t\tD_ENCRYPT(r,l,30); /*  16 */\n#else\n\t\tfor (i=0; i<32; i+=8)\n\t\t\t{\n\t\t\tD_ENCRYPT(l,r,i+0); /*  1 */\n\t\t\tD_ENCRYPT(r,l,i+2); /*  2 */\n\t\t\tD_ENCRYPT(l,r,i+4); /*  3 */\n\t\t\tD_ENCRYPT(r,l,i+6); /*  4 */\n\t\t\t}\n#endif\n\t\t}\n\telse\n\t\t{\n#ifdef DES_UNROLL\n\t\tD_ENCRYPT(l,r,30); /* 16 */\n\t\tD_ENCRYPT(r,l,28); /* 15 */\n\t\tD_ENCRYPT(l,r,26); /* 14 */\n\t\tD_ENCRYPT(r,l,24); /* 13 */\n\t\tD_ENCRYPT(l,r,22); /* 12 */\n\t\tD_ENCRYPT(r,l,20); /* 11 */\n\t\tD_ENCRYPT(l,r,18); /* 10 */\n\t\tD_ENCRYPT(r,l,16); /*  9 */\n\t\tD_ENCRYPT(l,r,14); /*  8 */\n\t\tD_ENCRYPT(r,l,12); /*  7 */\n\t\tD_ENCRYPT(l,r,10); /*  6 */\n\t\tD_ENCRYPT(r,l, 8); /*  5 */\n\t\tD_ENCRYPT(l,r, 6); /*  4 */\n\t\tD_ENCRYPT(r,l, 4); /*  3 */\n\t\tD_ENCRYPT(l,r, 2); /*  2 */\n\t\tD_ENCRYPT(r,l, 0); /*  1 */\n#else\n\t\tfor (i=30; i>0; i-=8)\n\t\t\t{\n\t\t\tD_ENCRYPT(l,r,i-0); /* 16 */\n\t\t\tD_ENCRYPT(r,l,i-2); /* 15 */\n\t\t\tD_ENCRYPT(l,r,i-4); /* 14 */\n\t\t\tD_ENCRYPT(r,l,i-6); /* 13 */\n\t\t\t}\n#endif\n\t\t}\n\n\t/* rotate and clear the top bits on machines with 8byte longs */\n\tl=ROTATE(l,3)&0xffffffffL;\n\tr=ROTATE(r,3)&0xffffffffL;\n\n\tFP(r,l);\n\tdata[0]=l;\n\tdata[1]=r;\n\tl=r=t=u=0;\n\t}\n\nvoid des_encrypt2(DES_LONG *data, des_key_schedule ks, int enc)\n\t{\n\tregister DES_LONG l,r,t,u;\n#ifdef DES_PTR\n\tregister const unsigned char *des_SP=(const unsigned char *)des_SPtrans;\n#endif\n#ifndef DES_UNROLL\n\tregister int i;\n#endif\n\tregister DES_LONG *s;\n\n\tr=data[0];\n\tl=data[1];\n\n\t/* Things have been modified so that the initial rotate is\n\t * done outside the loop.  This required the\n\t * des_SPtrans values in sp.h to be rotated 1 bit to the right.\n\t * One perl script later and things have a 5% speed up on a sparc2.\n\t * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>\n\t * for pointing this out. */\n\t/* clear the top bits on machines with 8byte longs */\n\tr=ROTATE(r,29)&0xffffffffL;\n\tl=ROTATE(l,29)&0xffffffffL;\n\n\ts=ks->ks.deslong;\n\t/* I don't know if it is worth the effort of loop unrolling the\n\t * inner loop */\n\tif (enc)\n\t\t{\n#ifdef DES_UNROLL\n\t\tD_ENCRYPT(l,r, 0); /*  1 */\n\t\tD_ENCRYPT(r,l, 2); /*  2 */\n\t\tD_ENCRYPT(l,r, 4); /*  3 */\n\t\tD_ENCRYPT(r,l, 6); /*  4 */\n\t\tD_ENCRYPT(l,r, 8); /*  5 */\n\t\tD_ENCRYPT(r,l,10); /*  6 */\n\t\tD_ENCRYPT(l,r,12); /*  7 */\n\t\tD_ENCRYPT(r,l,14); /*  8 */\n\t\tD_ENCRYPT(l,r,16); /*  9 */\n\t\tD_ENCRYPT(r,l,18); /*  10 */\n\t\tD_ENCRYPT(l,r,20); /*  11 */\n\t\tD_ENCRYPT(r,l,22); /*  12 */\n\t\tD_ENCRYPT(l,r,24); /*  13 */\n\t\tD_ENCRYPT(r,l,26); /*  14 */\n\t\tD_ENCRYPT(l,r,28); /*  15 */\n\t\tD_ENCRYPT(r,l,30); /*  16 */\n#else\n\t\tfor (i=0; i<32; i+=8)\n\t\t\t{\n\t\t\tD_ENCRYPT(l,r,i+0); /*  1 */\n\t\t\tD_ENCRYPT(r,l,i+2); /*  2 */\n\t\t\tD_ENCRYPT(l,r,i+4); /*  3 */\n\t\t\tD_ENCRYPT(r,l,i+6); /*  4 */\n\t\t\t}\n#endif\n\t\t}\n\telse\n\t\t{\n#ifdef DES_UNROLL\n\t\tD_ENCRYPT(l,r,30); /* 16 */\n\t\tD_ENCRYPT(r,l,28); /* 15 */\n\t\tD_ENCRYPT(l,r,26); /* 14 */\n\t\tD_ENCRYPT(r,l,24); /* 13 */\n\t\tD_ENCRYPT(l,r,22); /* 12 */\n\t\tD_ENCRYPT(r,l,20); /* 11 */\n\t\tD_ENCRYPT(l,r,18); /* 10 */\n\t\tD_ENCRYPT(r,l,16); /*  9 */\n\t\tD_ENCRYPT(l,r,14); /*  8 */\n\t\tD_ENCRYPT(r,l,12); /*  7 */\n\t\tD_ENCRYPT(l,r,10); /*  6 */\n\t\tD_ENCRYPT(r,l, 8); /*  5 */\n\t\tD_ENCRYPT(l,r, 6); /*  4 */\n\t\tD_ENCRYPT(r,l, 4); /*  3 */\n\t\tD_ENCRYPT(l,r, 2); /*  2 */\n\t\tD_ENCRYPT(r,l, 0); /*  1 */\n#else\n\t\tfor (i=30; i>0; i-=8)\n\t\t\t{\n\t\t\tD_ENCRYPT(l,r,i-0); /* 16 */\n\t\t\tD_ENCRYPT(r,l,i-2); /* 15 */\n\t\t\tD_ENCRYPT(l,r,i-4); /* 14 */\n\t\t\tD_ENCRYPT(r,l,i-6); /* 13 */\n\t\t\t}\n#endif\n\t\t}\n\t/* rotate and clear the top bits on machines with 8byte longs */\n\tdata[0]=ROTATE(l,3)&0xffffffffL;\n\tdata[1]=ROTATE(r,3)&0xffffffffL;\n\tl=r=t=u=0;\n\t}\n\nvoid des_encrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2,\n\t     des_key_schedule ks3)\n\t{\n\tregister DES_LONG l,r;\n\n\tl=data[0];\n\tr=data[1];\n\tIP(l,r);\n\tdata[0]=l;\n\tdata[1]=r;\n\tdes_encrypt2((DES_LONG *)data,ks1,DES_ENCRYPT);\n\tdes_encrypt2((DES_LONG *)data,ks2,DES_DECRYPT);\n\tdes_encrypt2((DES_LONG *)data,ks3,DES_ENCRYPT);\n\tl=data[0];\n\tr=data[1];\n\tFP(r,l);\n\tdata[0]=l;\n\tdata[1]=r;\n\t}\n\nvoid des_decrypt3(DES_LONG *data, des_key_schedule ks1, des_key_schedule ks2,\n\t     des_key_schedule ks3)\n\t{\n\tregister DES_LONG l,r;\n\n\tl=data[0];\n\tr=data[1];\n\tIP(l,r);\n\tdata[0]=l;\n\tdata[1]=r;\n\tdes_encrypt2((DES_LONG *)data,ks3,DES_DECRYPT);\n\tdes_encrypt2((DES_LONG *)data,ks2,DES_ENCRYPT);\n\tdes_encrypt2((DES_LONG *)data,ks1,DES_DECRYPT);\n\tl=data[0];\n\tr=data[1];\n\tFP(r,l);\n\tdata[0]=l;\n\tdata[1]=r;\n\t}\n\n#ifndef DES_DEFAULT_OPTIONS\n\n#undef CBC_ENC_C__DONT_UPDATE_IV\n\nvoid des_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,\n\t     long length, des_key_schedule ks1, des_key_schedule ks2,\n\t     des_key_schedule ks3, des_cblock *ivec, int enc)\n\t{\n\tregister DES_LONG tin0,tin1;\n\tregister DES_LONG tout0,tout1,xor0,xor1;\n\tregister const unsigned char *in;\n\tunsigned char *out;\n\tregister long l=length;\n\tDES_LONG tin[2];\n\tunsigned char *iv;\n\n\tin=input;\n\tout=output;\n\tiv = &(*ivec)[0];\n\n\tif (enc)\n\t\t{\n\t\tc2l(iv,tout0);\n\t\tc2l(iv,tout1);\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0);\n\t\t\tc2l(in,tin1);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tdes_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\n\t\t\tl2c(tout0,out);\n\t\t\tl2c(tout1,out);\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2ln(in,tin0,tin1,l+8);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tdes_encrypt3((DES_LONG *)tin,ks1,ks2,ks3);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\n\t\t\tl2c(tout0,out);\n\t\t\tl2c(tout1,out);\n\t\t\t}\n\t\tiv = &(*ivec)[0];\n\t\tl2c(tout0,iv);\n\t\tl2c(tout1,iv);\n\t\t}\n\telse\n\t\t{\n\t\tregister DES_LONG t0,t1;\n\n\t\tc2l(iv,xor0);\n\t\tc2l(iv,xor1);\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0);\n\t\t\tc2l(in,tin1);\n\n\t\t\tt0=tin0;\n\t\t\tt1=tin1;\n\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tdes_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\n\t\t\ttout0^=xor0;\n\t\t\ttout1^=xor1;\n\t\t\tl2c(tout0,out);\n\t\t\tl2c(tout1,out);\n\t\t\txor0=t0;\n\t\t\txor1=t1;\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2l(in,tin0);\n\t\t\tc2l(in,tin1);\n\n\t\t\tt0=tin0;\n\t\t\tt1=tin1;\n\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tdes_decrypt3((DES_LONG *)tin,ks1,ks2,ks3);\n\t\t\ttout0=tin[0];\n\t\t\ttout1=tin[1];\n\n\t\t\ttout0^=xor0;\n\t\t\ttout1^=xor1;\n\t\t\tl2cn(tout0,tout1,out,l+8);\n\t\t\txor0=t0;\n\t\t\txor1=t1;\n\t\t\t}\n\n\t\tiv = &(*ivec)[0];\n\t\tl2c(xor0,iv);\n\t\tl2c(xor1,iv);\n\t\t}\n\ttin0=tin1=tout0=tout1=xor0=xor1=0;\n\ttin[0]=tin[1]=0;\n\t}\n\n#endif /* DES_DEFAULT_OPTIONS */\n\n#endif /* USE_ASM */\n"
  },
  {
    "path": "deps/cl345/crypt/deslocl.h",
    "content": "/* crypto/des/des_locl.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_DES_LOCL_H\n#define HEADER_DES_LOCL_H\n\n#if defined(WIN32) || defined(WIN16)\n#ifndef MSDOS\n#define MSDOS\n#endif\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n#endif /* Compiler-specific includes */\n\n#if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS)\n#include <string.h>\n#endif\n\n#define ITERATIONS 16\n#define HALF_ITERATIONS 8\n\n/* used in des_read and des_write */\n#define MAXWRITE\t(1024*16)\n#ifdef BSIZE\n  /* If it's already defined, undefine it completely so that it can be\n   * resolved by the user.  This macro is redefined on HP-UX 10.20 using\n   * gcc 2.95.2.   Fortunately, BSIZE is not used in the DES code. */\n  #undef BSIZE\n#else\n  #define BSIZE\t\t(MAXWRITE+4)\n#endif\n\n#define c2l(c,l)\t(l =((DES_LONG)(*((c)++)))    , \\\n\t\t\t l|=((DES_LONG)(*((c)++)))<< 8L, \\\n\t\t\t l|=((DES_LONG)(*((c)++)))<<16L, \\\n\t\t\t l|=((DES_LONG)(*((c)++)))<<24L)\n\n/* NOTE - c is not incremented as per c2l */\n#define c2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((DES_LONG)(*(--(c))))<<24L; \\\n\t\t\tcase 7: l2|=((DES_LONG)(*(--(c))))<<16L; \\\n\t\t\tcase 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \\\n\t\t\tcase 5: l2|=((DES_LONG)(*(--(c))));     \\\n\t\t\tcase 4: l1 =((DES_LONG)(*(--(c))))<<24L; \\\n\t\t\tcase 3: l1|=((DES_LONG)(*(--(c))))<<16L; \\\n\t\t\tcase 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \\\n\t\t\tcase 1: l1|=((DES_LONG)(*(--(c))));     \\\n\t\t\t\t} \\\n\t\t\t}\n\n#define l2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24L)&0xff))\n\n/* replacements for htonl and ntohl since I have no idea what to do\n * when faced with machines with 8 byte longs. */\n#define HDRSIZE 4\n\n#define n2l(c,l)\t(l =((DES_LONG)(*((c)++)))<<24L, \\\n\t\t\t l|=((DES_LONG)(*((c)++)))<<16L, \\\n\t\t\t l|=((DES_LONG)(*((c)++)))<< 8L, \\\n\t\t\t l|=((DES_LONG)(*((c)++))))\n\n#define l2n(l,c)\t(*((c)++)=(unsigned char)(((l)>>24L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)     )&0xff))\n\n/* NOTE - c is not incremented as per l2c */\n#define l2cn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n#if defined(WIN32) && defined(_MSC_VER)\n#define\tROTATE(a,n)\t(_lrotr(a,n))\n#else\n#define\tROTATE(a,n)\t(((a)>>(n))+((a)<<(32-(n))))\n#endif\n\n/* Don't worry about the LOAD_DATA() stuff, that is used by\n * fcrypt() to add it's little bit to the front */\n\n#ifdef DES_FCRYPT\n\n#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \\\n\t{ DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); }\n\n#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \\\n\tt=R^(R>>16L); \\\n\tu=t&E0; t&=E1; \\\n\ttmp=(u<<16); u^=R^s[S  ]; u^=tmp; \\\n\ttmp=(t<<16); t^=R^s[S+1]; t^=tmp\n#else\n#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g)\n#define LOAD_DATA(R,S,u,t,E0,E1,tmp) \\\n\tu=R^s[S  ]; \\\n\tt=R^s[S+1]\n#endif\n\n/* The changes to this macro may help or hinder, depending on the\n * compiler and the architecture.  gcc2 always seems to do well :-).\n * Inspired by Dana How <how@isl.stanford.edu>\n * DO NOT use the alternative version on machines with 8 byte longs.\n * It does not seem to work on the Alpha, even when DES_LONG is 4\n * bytes, probably an issue of accessing non-word aligned objects :-( */\n#ifdef DES_PTR\n\n/* It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there\n * is no reason to not xor all the sub items together.  This potentially\n * saves a register since things can be xored directly into L */\n\n#if defined(DES_RISC1) || defined(DES_RISC2)\n#ifdef DES_RISC1\n#define D_ENCRYPT(LL,R,S) { \\\n\tunsigned int u1,u2,u3; \\\n\tLOAD_DATA(R,S,u,t,E0,E1,u1); \\\n\tu2=(int)u>>8L; \\\n\tu1=(int)u&0xfc; \\\n\tu2&=0xfc; \\\n\tt=ROTATE(t,4); \\\n\tu>>=16L; \\\n\tLL^= *(const DES_LONG *)(des_SP      +u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x200+u2); \\\n\tu3=(int)(u>>8L); \\\n\tu1=(int)u&0xfc; \\\n\tu3&=0xfc; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x400+u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x600+u3); \\\n\tu2=(int)t>>8L; \\\n\tu1=(int)t&0xfc; \\\n\tu2&=0xfc; \\\n\tt>>=16L; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x100+u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x300+u2); \\\n\tu3=(int)t>>8L; \\\n\tu1=(int)t&0xfc; \\\n\tu3&=0xfc; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x500+u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x700+u3); }\n#endif\n#ifdef DES_RISC2\n#define D_ENCRYPT(LL,R,S) { \\\n\tunsigned int u1,u2,s1,s2; \\\n\tLOAD_DATA(R,S,u,t,E0,E1,u1); \\\n\tu2=(int)u>>8L; \\\n\tu1=(int)u&0xfc; \\\n\tu2&=0xfc; \\\n\tt=ROTATE(t,4); \\\n\tLL^= *(const DES_LONG *)(des_SP      +u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x200+u2); \\\n\ts1=(int)(u>>16L); \\\n\ts2=(int)(u>>24L); \\\n\ts1&=0xfc; \\\n\ts2&=0xfc; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x400+s1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x600+s2); \\\n\tu2=(int)t>>8L; \\\n\tu1=(int)t&0xfc; \\\n\tu2&=0xfc; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x100+u1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x300+u2); \\\n\ts1=(int)(t>>16L); \\\n\ts2=(int)(t>>24L); \\\n\ts1&=0xfc; \\\n\ts2&=0xfc; \\\n\tLL^= *(const DES_LONG *)(des_SP+0x500+s1); \\\n\tLL^= *(const DES_LONG *)(des_SP+0x700+s2); }\n#endif\n#else\n#define D_ENCRYPT(LL,R,S) { \\\n\tLOAD_DATA_tmp(R,S,u,t,E0,E1); \\\n\tt=ROTATE(t,4); \\\n\tLL^= \\\n\t*(const DES_LONG *)(des_SP      +((u     )&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x200+((u>> 8L)&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x400+((u>>16L)&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x600+((u>>24L)&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x100+((t     )&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x300+((t>> 8L)&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x500+((t>>16L)&0xfc))^ \\\n\t*(const DES_LONG *)(des_SP+0x700+((t>>24L)&0xfc)); }\n#endif\n\n#else /* original version */\n\n#if defined(DES_RISC1) || defined(DES_RISC2)\n#ifdef DES_RISC1\n#define D_ENCRYPT(LL,R,S) {\\\n\tunsigned int u1,u2,u3; \\\n\tLOAD_DATA(R,S,u,t,E0,E1,u1); \\\n\tu>>=2L; \\\n\tt=ROTATE(t,6); \\\n\tu2=(int)u>>8L; \\\n\tu1=(int)u&0x3f; \\\n\tu2&=0x3f; \\\n\tu>>=16L; \\\n\tLL^=des_SPtrans[0][u1]; \\\n\tLL^=des_SPtrans[2][u2]; \\\n\tu3=(int)u>>8L; \\\n\tu1=(int)u&0x3f; \\\n\tu3&=0x3f; \\\n\tLL^=des_SPtrans[4][u1]; \\\n\tLL^=des_SPtrans[6][u3]; \\\n\tu2=(int)t>>8L; \\\n\tu1=(int)t&0x3f; \\\n\tu2&=0x3f; \\\n\tt>>=16L; \\\n\tLL^=des_SPtrans[1][u1]; \\\n\tLL^=des_SPtrans[3][u2]; \\\n\tu3=(int)t>>8L; \\\n\tu1=(int)t&0x3f; \\\n\tu3&=0x3f; \\\n\tLL^=des_SPtrans[5][u1]; \\\n\tLL^=des_SPtrans[7][u3]; }\n#endif\n#ifdef DES_RISC2\n#define D_ENCRYPT(LL,R,S) {\\\n\tunsigned int u1,u2,s1,s2; \\\n\tLOAD_DATA(R,S,u,t,E0,E1,u1); \\\n\tu>>=2L; \\\n\tt=ROTATE(t,6); \\\n\tu2=(int)u>>8L; \\\n\tu1=(int)u&0x3f; \\\n\tu2&=0x3f; \\\n\tLL^=des_SPtrans[0][u1]; \\\n\tLL^=des_SPtrans[2][u2]; \\\n\ts1=(int)u>>16L; \\\n\ts2=(int)u>>24L; \\\n\ts1&=0x3f; \\\n\ts2&=0x3f; \\\n\tLL^=des_SPtrans[4][s1]; \\\n\tLL^=des_SPtrans[6][s2]; \\\n\tu2=(int)t>>8L; \\\n\tu1=(int)t&0x3f; \\\n\tu2&=0x3f; \\\n\tLL^=des_SPtrans[1][u1]; \\\n\tLL^=des_SPtrans[3][u2]; \\\n\ts1=(int)t>>16; \\\n\ts2=(int)t>>24L; \\\n\ts1&=0x3f; \\\n\ts2&=0x3f; \\\n\tLL^=des_SPtrans[5][s1]; \\\n\tLL^=des_SPtrans[7][s2]; }\n#endif\n\n#else\n\n#define D_ENCRYPT(LL,R,S) {\\\n\tLOAD_DATA_tmp(R,S,u,t,E0,E1); \\\n\tt=ROTATE(t,4); \\\n\tLL^=\\\n\t\tdes_SPtrans[0][(u>> 2L)&0x3f]^ \\\n\t\tdes_SPtrans[2][(u>>10L)&0x3f]^ \\\n\t\tdes_SPtrans[4][(u>>18L)&0x3f]^ \\\n\t\tdes_SPtrans[6][(u>>26L)&0x3f]^ \\\n\t\tdes_SPtrans[1][(t>> 2L)&0x3f]^ \\\n\t\tdes_SPtrans[3][(t>>10L)&0x3f]^ \\\n\t\tdes_SPtrans[5][(t>>18L)&0x3f]^ \\\n\t\tdes_SPtrans[7][(t>>26L)&0x3f]; }\n#endif\n#endif\n\n\t/* IP and FP\n\t * The problem is more of a geometric problem that random bit fiddling.\n\t 0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6\n\t 8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4\n\t16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2\n\t24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0\n\n\t32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7\n\t40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5\n\t48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3\n\t56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1\n\n\tThe output has been subject to swaps of the form\n\t0 1 -> 3 1 but the odd and even bits have been put into\n\t2 3    2 0\n\tdifferent words.  The main trick is to remember that\n\tt=((l>>size)^r)&(mask);\n\tr^=t;\n\tl^=(t<<size);\n\tcan be used to swap and move bits between words.\n\n\tSo l =  0  1  2  3  r = 16 17 18 19\n\t        4  5  6  7      20 21 22 23\n\t        8  9 10 11      24 25 26 27\n\t       12 13 14 15      28 29 30 31\n\tbecomes (for size == 2 and mask == 0x3333)\n\t   t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19\n\t\t 6^20  7^21 -- --        4  5 20 21       6  7 22 23\n\t\t10^24 11^25 -- --        8  9 24 25      10 11 24 25\n\t\t14^28 15^29 -- --       12 13 28 29      14 15 28 29\n\n\tThanks for hints from Richard Outerbridge - he told me IP&FP\n\tcould be done in 15 xor, 10 shifts and 5 ands.\n\tWhen I finally started to think of the problem in 2D\n\tI first got ~42 operations without xors.  When I remembered\n\thow to use xors :-) I got it to its final state.\n\t*/\n#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\\\n\t(b)^=(t),\\\n\t(a)^=((t)<<(n)))\n\n#define IP(l,r) \\\n\t{ \\\n\tregister DES_LONG tt; \\\n\tPERM_OP(r,l,tt, 4,0x0f0f0f0fL); \\\n\tPERM_OP(l,r,tt,16,0x0000ffffL); \\\n\tPERM_OP(r,l,tt, 2,0x33333333L); \\\n\tPERM_OP(l,r,tt, 8,0x00ff00ffL); \\\n\tPERM_OP(r,l,tt, 1,0x55555555L); \\\n\t}\n\n#define FP(l,r) \\\n\t{ \\\n\tregister DES_LONG tt; \\\n\tPERM_OP(l,r,tt, 1,0x55555555L); \\\n\tPERM_OP(r,l,tt, 8,0x00ff00ffL); \\\n\tPERM_OP(l,r,tt, 2,0x33333333L); \\\n\tPERM_OP(r,l,tt,16,0x0000ffffL); \\\n\tPERM_OP(l,r,tt, 4,0x0f0f0f0fL); \\\n\t}\n\nOPENSSL_EXTERN const DES_LONG ASM_EXPORT des_SPtrans[8][64];\t/* pcg */\n\nvoid fcrypt_body(DES_LONG *out,des_key_schedule ks,\n\tDES_LONG Eswap0, DES_LONG Eswap1);\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/desskey.c",
    "content": "/* crypto/des/set_key.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n/* set_key.c v 1.4 eay 24/9/91\n * 1.4 Speed up by 400% :-)\n * 1.3 added register declarations.\n * 1.2 unrolled make_key_sched a bit more\n * 1.1 added norm_expand_bits\n * 1.0 First working version\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"des.h\"\n  #include \"deslocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/des.h\"\n  #include \"crypt/deslocl.h\"\n#endif /* Compiler-specific includes */\n\nOPENSSL_GLOBAL int des_check_key=1;\n\nstatic const unsigned char odd_parity[256]={\n  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,\n 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,\n 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,\n 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,\n 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,\n 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,\n 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,\n112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,\n128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,\n145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,\n161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,\n176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,\n193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,\n208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,\n224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,\n241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254};\n\nvoid des_set_odd_parity(des_cblock *key)\n\t{\n\tunsigned char *keyPtr = *key;\t/* Work around XMK compiler bug - pcg */\n\tint i;\n\n\tfor (i=0; i<DES_KEY_SZ; i++)\n\t\tkeyPtr[i]=odd_parity[keyPtr[i]];\n\t}\n\nint des_check_key_parity(const_des_cblock *key)\n\t{\n\tint i;\n\n\tfor (i=0; i<DES_KEY_SZ; i++)\n\t\t{\n\t\tif ((*key)[i] != odd_parity[(*key)[i]])\n\t\t\treturn(0);\n\t\t}\n\treturn(1);\n\t}\n\n/* Weak and semi week keys as take from\n * %A D.W. Davies\n * %A W.L. Price\n * %T Security for Computer Networks\n * %I John Wiley & Sons\n * %D 1984\n * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference\n * (and actual cblock values).\n */\n#define NUM_WEAK_KEY\t16\nstatic des_cblock weak_keys[NUM_WEAK_KEY]={\n\t/* weak keys */\n\t{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},\n\t{0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE},\n\t{0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},\n\t{0xE0,0xE0,0xE0,0xE0,0xF1,0xF1,0xF1,0xF1},\n\t/* semi-weak keys */\n\t{0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE},\n\t{0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01},\n\t{0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1},\n\t{0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E},\n\t{0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1},\n\t{0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01},\n\t{0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE},\n\t{0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E},\n\t{0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E},\n\t{0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01},\n\t{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},\n\t{0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1}};\n\nint des_is_weak_key(const_des_cblock *key)\n\t{\n\tint i;\n\n\tfor (i=0; i<NUM_WEAK_KEY; i++)\n\t\t/* Added == 0 to comparison, I obviously don't run\n\t\t * this section very often :-(, thanks to\n\t\t * engineering@MorningStar.Com for the fix\n\t\t * eay 93/06/29\n\t\t * Another problem, I was comparing only the first 4\n\t\t * bytes, 97/03/18 */\n\t\tif (memcmp(weak_keys[i],key,sizeof(des_cblock)) == 0) return(1);\n\treturn(0);\n\t}\n\n/* NOW DEFINED IN des_local.h\n * See ecb_encrypt.c for a pseudo description of these macros.\n * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\\\n * \t(b)^=(t),\\\n * \t(a)=((a)^((t)<<(n))))\n */\n\n#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\\\n\t(a)=(a)^(t)^(t>>(16-(n))))\n\nstatic const DES_LONG des_skb[8][64]={\n\t{\n\t/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\n\t0x00000000L,0x00000010L,0x20000000L,0x20000010L,\n\t0x00010000L,0x00010010L,0x20010000L,0x20010010L,\n\t0x00000800L,0x00000810L,0x20000800L,0x20000810L,\n\t0x00010800L,0x00010810L,0x20010800L,0x20010810L,\n\t0x00000020L,0x00000030L,0x20000020L,0x20000030L,\n\t0x00010020L,0x00010030L,0x20010020L,0x20010030L,\n\t0x00000820L,0x00000830L,0x20000820L,0x20000830L,\n\t0x00010820L,0x00010830L,0x20010820L,0x20010830L,\n\t0x00080000L,0x00080010L,0x20080000L,0x20080010L,\n\t0x00090000L,0x00090010L,0x20090000L,0x20090010L,\n\t0x00080800L,0x00080810L,0x20080800L,0x20080810L,\n\t0x00090800L,0x00090810L,0x20090800L,0x20090810L,\n\t0x00080020L,0x00080030L,0x20080020L,0x20080030L,\n\t0x00090020L,0x00090030L,0x20090020L,0x20090030L,\n\t0x00080820L,0x00080830L,0x20080820L,0x20080830L,\n\t0x00090820L,0x00090830L,0x20090820L,0x20090830L,\n\t},{\n\t/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */\n\t0x00000000L,0x02000000L,0x00002000L,0x02002000L,\n\t0x00200000L,0x02200000L,0x00202000L,0x02202000L,\n\t0x00000004L,0x02000004L,0x00002004L,0x02002004L,\n\t0x00200004L,0x02200004L,0x00202004L,0x02202004L,\n\t0x00000400L,0x02000400L,0x00002400L,0x02002400L,\n\t0x00200400L,0x02200400L,0x00202400L,0x02202400L,\n\t0x00000404L,0x02000404L,0x00002404L,0x02002404L,\n\t0x00200404L,0x02200404L,0x00202404L,0x02202404L,\n\t0x10000000L,0x12000000L,0x10002000L,0x12002000L,\n\t0x10200000L,0x12200000L,0x10202000L,0x12202000L,\n\t0x10000004L,0x12000004L,0x10002004L,0x12002004L,\n\t0x10200004L,0x12200004L,0x10202004L,0x12202004L,\n\t0x10000400L,0x12000400L,0x10002400L,0x12002400L,\n\t0x10200400L,0x12200400L,0x10202400L,0x12202400L,\n\t0x10000404L,0x12000404L,0x10002404L,0x12002404L,\n\t0x10200404L,0x12200404L,0x10202404L,0x12202404L,\n\t},{\n\t/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */\n\t0x00000000L,0x00000001L,0x00040000L,0x00040001L,\n\t0x01000000L,0x01000001L,0x01040000L,0x01040001L,\n\t0x00000002L,0x00000003L,0x00040002L,0x00040003L,\n\t0x01000002L,0x01000003L,0x01040002L,0x01040003L,\n\t0x00000200L,0x00000201L,0x00040200L,0x00040201L,\n\t0x01000200L,0x01000201L,0x01040200L,0x01040201L,\n\t0x00000202L,0x00000203L,0x00040202L,0x00040203L,\n\t0x01000202L,0x01000203L,0x01040202L,0x01040203L,\n\t0x08000000L,0x08000001L,0x08040000L,0x08040001L,\n\t0x09000000L,0x09000001L,0x09040000L,0x09040001L,\n\t0x08000002L,0x08000003L,0x08040002L,0x08040003L,\n\t0x09000002L,0x09000003L,0x09040002L,0x09040003L,\n\t0x08000200L,0x08000201L,0x08040200L,0x08040201L,\n\t0x09000200L,0x09000201L,0x09040200L,0x09040201L,\n\t0x08000202L,0x08000203L,0x08040202L,0x08040203L,\n\t0x09000202L,0x09000203L,0x09040202L,0x09040203L,\n\t},{\n\t/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */\n\t0x00000000L,0x00100000L,0x00000100L,0x00100100L,\n\t0x00000008L,0x00100008L,0x00000108L,0x00100108L,\n\t0x00001000L,0x00101000L,0x00001100L,0x00101100L,\n\t0x00001008L,0x00101008L,0x00001108L,0x00101108L,\n\t0x04000000L,0x04100000L,0x04000100L,0x04100100L,\n\t0x04000008L,0x04100008L,0x04000108L,0x04100108L,\n\t0x04001000L,0x04101000L,0x04001100L,0x04101100L,\n\t0x04001008L,0x04101008L,0x04001108L,0x04101108L,\n\t0x00020000L,0x00120000L,0x00020100L,0x00120100L,\n\t0x00020008L,0x00120008L,0x00020108L,0x00120108L,\n\t0x00021000L,0x00121000L,0x00021100L,0x00121100L,\n\t0x00021008L,0x00121008L,0x00021108L,0x00121108L,\n\t0x04020000L,0x04120000L,0x04020100L,0x04120100L,\n\t0x04020008L,0x04120008L,0x04020108L,0x04120108L,\n\t0x04021000L,0x04121000L,0x04021100L,0x04121100L,\n\t0x04021008L,0x04121008L,0x04021108L,0x04121108L,\n\t},{\n\t/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */\n\t0x00000000L,0x10000000L,0x00010000L,0x10010000L,\n\t0x00000004L,0x10000004L,0x00010004L,0x10010004L,\n\t0x20000000L,0x30000000L,0x20010000L,0x30010000L,\n\t0x20000004L,0x30000004L,0x20010004L,0x30010004L,\n\t0x00100000L,0x10100000L,0x00110000L,0x10110000L,\n\t0x00100004L,0x10100004L,0x00110004L,0x10110004L,\n\t0x20100000L,0x30100000L,0x20110000L,0x30110000L,\n\t0x20100004L,0x30100004L,0x20110004L,0x30110004L,\n\t0x00001000L,0x10001000L,0x00011000L,0x10011000L,\n\t0x00001004L,0x10001004L,0x00011004L,0x10011004L,\n\t0x20001000L,0x30001000L,0x20011000L,0x30011000L,\n\t0x20001004L,0x30001004L,0x20011004L,0x30011004L,\n\t0x00101000L,0x10101000L,0x00111000L,0x10111000L,\n\t0x00101004L,0x10101004L,0x00111004L,0x10111004L,\n\t0x20101000L,0x30101000L,0x20111000L,0x30111000L,\n\t0x20101004L,0x30101004L,0x20111004L,0x30111004L,\n\t},{\n\t/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */\n\t0x00000000L,0x08000000L,0x00000008L,0x08000008L,\n\t0x00000400L,0x08000400L,0x00000408L,0x08000408L,\n\t0x00020000L,0x08020000L,0x00020008L,0x08020008L,\n\t0x00020400L,0x08020400L,0x00020408L,0x08020408L,\n\t0x00000001L,0x08000001L,0x00000009L,0x08000009L,\n\t0x00000401L,0x08000401L,0x00000409L,0x08000409L,\n\t0x00020001L,0x08020001L,0x00020009L,0x08020009L,\n\t0x00020401L,0x08020401L,0x00020409L,0x08020409L,\n\t0x02000000L,0x0A000000L,0x02000008L,0x0A000008L,\n\t0x02000400L,0x0A000400L,0x02000408L,0x0A000408L,\n\t0x02020000L,0x0A020000L,0x02020008L,0x0A020008L,\n\t0x02020400L,0x0A020400L,0x02020408L,0x0A020408L,\n\t0x02000001L,0x0A000001L,0x02000009L,0x0A000009L,\n\t0x02000401L,0x0A000401L,0x02000409L,0x0A000409L,\n\t0x02020001L,0x0A020001L,0x02020009L,0x0A020009L,\n\t0x02020401L,0x0A020401L,0x02020409L,0x0A020409L,\n\t},{\n\t/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */\n\t0x00000000L,0x00000100L,0x00080000L,0x00080100L,\n\t0x01000000L,0x01000100L,0x01080000L,0x01080100L,\n\t0x00000010L,0x00000110L,0x00080010L,0x00080110L,\n\t0x01000010L,0x01000110L,0x01080010L,0x01080110L,\n\t0x00200000L,0x00200100L,0x00280000L,0x00280100L,\n\t0x01200000L,0x01200100L,0x01280000L,0x01280100L,\n\t0x00200010L,0x00200110L,0x00280010L,0x00280110L,\n\t0x01200010L,0x01200110L,0x01280010L,0x01280110L,\n\t0x00000200L,0x00000300L,0x00080200L,0x00080300L,\n\t0x01000200L,0x01000300L,0x01080200L,0x01080300L,\n\t0x00000210L,0x00000310L,0x00080210L,0x00080310L,\n\t0x01000210L,0x01000310L,0x01080210L,0x01080310L,\n\t0x00200200L,0x00200300L,0x00280200L,0x00280300L,\n\t0x01200200L,0x01200300L,0x01280200L,0x01280300L,\n\t0x00200210L,0x00200310L,0x00280210L,0x00280310L,\n\t0x01200210L,0x01200310L,0x01280210L,0x01280310L,\n\t},{\n\t/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */\n\t0x00000000L,0x04000000L,0x00040000L,0x04040000L,\n\t0x00000002L,0x04000002L,0x00040002L,0x04040002L,\n\t0x00002000L,0x04002000L,0x00042000L,0x04042000L,\n\t0x00002002L,0x04002002L,0x00042002L,0x04042002L,\n\t0x00000020L,0x04000020L,0x00040020L,0x04040020L,\n\t0x00000022L,0x04000022L,0x00040022L,0x04040022L,\n\t0x00002020L,0x04002020L,0x00042020L,0x04042020L,\n\t0x00002022L,0x04002022L,0x00042022L,0x04042022L,\n\t0x00000800L,0x04000800L,0x00040800L,0x04040800L,\n\t0x00000802L,0x04000802L,0x00040802L,0x04040802L,\n\t0x00002800L,0x04002800L,0x00042800L,0x04042800L,\n\t0x00002802L,0x04002802L,0x00042802L,0x04042802L,\n\t0x00000820L,0x04000820L,0x00040820L,0x04040820L,\n\t0x00000822L,0x04000822L,0x00040822L,0x04040822L,\n\t0x00002820L,0x04002820L,0x00042820L,0x04042820L,\n\t0x00002822L,0x04002822L,0x00042822L,0x04042822L,\n\t}};\n\nint des_set_key(const_des_cblock *key, des_key_schedule schedule)\n\t{\n\tif (des_check_key)\n\t\t{\n\t\treturn des_set_key_checked(key, schedule);\n\t\t}\n\telse\n\t\t{\n\t\tdes_set_key_unchecked(key, schedule);\n\t\treturn 0;\n\t\t}\n\t}\n\n/* return 0 if key parity is odd (correct),\n * return -1 if key parity error,\n * return -2 if illegal weak key.\n */\nint des_set_key_checked(const_des_cblock *key, des_key_schedule schedule)\n\t{\n\tif (!des_check_key_parity(key))\n\t\treturn(-1);\n\tif (des_is_weak_key(key))\n\t\treturn(-2);\n\tdes_set_key_unchecked(key, schedule);\n\treturn 0;\n\t}\n\nvoid des_set_key_unchecked(const_des_cblock *key, des_key_schedule schedule)\n\t{\n\tstatic int shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};\n\tregister DES_LONG c,d,t,s,t2;\n\tregister const unsigned char *in;\n\tregister DES_LONG *k;\n\tregister int i;\n\n\tk = &schedule->ks.deslong[0];\n\tin = &(*key)[0];\n\n\tc2l(in,c);\n\tc2l(in,d);\n\n\t/* do PC1 in 47 simple operations :-)\n\t * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)\n\t * for the inspiration. :-) */\n\tPERM_OP (d,c,t,4,0x0f0f0f0fL);\n\tHPERM_OP(c,t,-2,0xcccc0000L);\n\tHPERM_OP(d,t,-2,0xcccc0000L);\n\tPERM_OP (d,c,t,1,0x55555555L);\n\tPERM_OP (c,d,t,8,0x00ff00ffL);\n\tPERM_OP (d,c,t,1,0x55555555L);\n\td=\t(((d&0x000000ffL)<<16L)| (d&0x0000ff00L)     |\n\t\t ((d&0x00ff0000L)>>16L)|((c&0xf0000000L)>>4L));\n\tc&=0x0fffffffL;\n\n\tfor (i=0; i<ITERATIONS; i++)\n\t\t{\n\t\tif (shifts2[i])\n\t\t\t{ c=((c>>2L)|(c<<26L)); d=((d>>2L)|(d<<26L)); }\n\t\telse\n\t\t\t{ c=((c>>1L)|(c<<27L)); d=((d>>1L)|(d<<27L)); }\n\t\tc&=0x0fffffffL;\n\t\td&=0x0fffffffL;\n\t\t/* could be a few less shifts but I am to lazy at this\n\t\t * point in time to investigate */\n\t\ts=\tdes_skb[0][ (c    )&0x3f                ]|\n\t\t\tdes_skb[1][((c>> 6L)&0x03)|((c>> 7L)&0x3c)]|\n\t\t\tdes_skb[2][((c>>13L)&0x0f)|((c>>14L)&0x30)]|\n\t\t\tdes_skb[3][((c>>20L)&0x01)|((c>>21L)&0x06) |\n\t\t\t\t\t\t  ((c>>22L)&0x38)];\n\t\tt=\tdes_skb[4][ (d    )&0x3f                ]|\n\t\t\tdes_skb[5][((d>> 7L)&0x03)|((d>> 8L)&0x3c)]|\n\t\t\tdes_skb[6][ (d>>15L)&0x3f                ]|\n\t\t\tdes_skb[7][((d>>21L)&0x0f)|((d>>22L)&0x30)];\n\n\t\t/* table contained 0213 4657 */\n\t\tt2=((t<<16L)|(s&0x0000ffffL))&0xffffffffL;\n\t\t*(k++)=ROTATE(t2,30)&0xffffffffL;\n\n\t\tt2=((s>>16L)|(t&0xffff0000L));\n\t\t*(k++)=ROTATE(t2,26)&0xffffffffL;\n\t\t}\n\t}\n\nint des_key_sched(const_des_cblock *key, des_key_schedule schedule)\n\t{\n\treturn(des_set_key(key,schedule));\n\t}\n\n#undef des_fixup_key_parity\nvoid des_fixup_key_parity(des_cblock *key)\n\t{\n\tdes_set_odd_parity(key);\n\t}\n"
  },
  {
    "path": "deps/cl345/crypt/gcm.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 30/03/2011\n\n My thanks to:\n\n   Colin Sinclair for finding an error and suggesting a number of\n   improvements to this code. \n \n   John Viega and David McGrew for their support in the development \n   of this code and to David for testing it on a big-endIAN system.\n\n   Mark Rodenkirch and Jason Papadopoulos for their help in finding\n   a bug in the fast buffer operations on big endian systems.\n*/\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"gcm.h\"\n  #include \"mode_hdr.h\"\n#else\n  #include \"crypt/gcm.h\"\n  #include \"crypt/mode_hdr.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_GCM\n\n/*  This GCM implementation needs a Galois Field multiplier for GF(2^128).\n    which operates on field elements using a polynomial field representation\n    x^127 + x^126 + ... + x^2 + x + 1 using the bits in a bit sequence that\n    will be numbered by the power of x that they represent. GCM uses the\n    polynomial x^128 + x^7 + x^2 + x + 1 as its basis for representation.\n\n    The obvious way of representing this in a computer system is to map GF\n    'x' to the binary integer '2' - but this was way too obvious for any\n    cryptographer to adopt!\n\n    Here bytes are numbered in memory order and  bits within bytes according\n    to their integer numeric significance. The term 'little endian' is then\n    used to describe mappings in which numeric (power of 2) or field (power\n    of x) significance increase with increasing bit or byte numbers with\n    'big endian' being used to describe the inverse situation.\n\n    GCM uses little endian byte ordering and big endian bit ordering, a\n    representation that will be described as LB. Hence the low end of the\n    field polynomial is in byte[0], which has the value 0xe1 rather than\n    0x87 in the more obvious mappings.\n\n    The related field multipler can use this mapping but if you want to\n    use an alternative (e.g hardware) multiplier that uses a different\n    polynomial field representation, you can do so by changing the form\n    used for the field elements when this alternative multiplier is used.\n\n    If GF_REPRESENTATION is defined as one of:\n\n        REVERSE_BITS                      // change to LL\n        REVERSE_BYTES | REVERSE_BITS      // change to BL\n        REVERSE_NONE                      // no change\n        REVERSE_BYTES                     // change to BB\n\n    then an appropriate change of representation will occur before and\n    after calls to your revised field multiplier. To use this you need\n    to add gf_convert.c to your application.  \n*/\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#if 1\n#  undef GF_REPRESENTATION\n#elif 0\n#  define GF_REPRESENTATION REVERSE_BITS\n#elif 0\n#  define GF_REPRESENTATION REVERSE_BYTES | REVERSE_BITS\n#elif 0\n#  define GF_REPRESENTATION REVERSE_NONE\n#elif 0\n#  define GF_REPRESENTATION REVERSE_BITS\n#endif\n\n#define BLOCK_SIZE      GCM_BLOCK_SIZE      /* block length                 */\n#define BLK_ADR_MASK    (BLOCK_SIZE - 1)    /* mask for 'in block' address  */\n#define CTR_POS         12\n\n#define inc_ctr(x)  \\\n    {   int i = BLOCK_SIZE; while(i-- > CTR_POS && !++(UI8_PTR(x)[i])) ; }\n\nret_type gcm_init_and_key(                  /* initialise mode and set key  */\n            const unsigned char key[],      /* the key value                */\n            unsigned long key_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{\n    memset(ctx->ghash_h, 0, sizeof(ctx->ghash_h));\n\n    /* set the AES key                          */\n    aes_encrypt_key(key, key_len, ctx->aes);\n\n    /* compute E(0) (for the hash function)     */\n    aes_encrypt(UI8_PTR(ctx->ghash_h), UI8_PTR(ctx->ghash_h), ctx->aes);\n\n#if defined( GF_REPRESENTATION )\n    convert_representation(ctx->ghash_h, ctx->ghash_h, GF_REPRESENTATION);\n#endif\n\n#if defined( TABLES_64K )\n    init_64k_table(ctx->ghash_h, ctx->gf_t64k);\n#elif defined( TABLES_8K )\n    init_8k_table(ctx->ghash_h, ctx->gf_t8k);\n#elif defined( TABLES_4K )\n    init_4k_table(ctx->ghash_h, ctx->gf_t4k);\n#elif defined( TABLES_256 )\n    init_256_table(ctx->ghash_h, ctx->gf_t256);\n#endif\n#if defined(  GF_REPRESENTATION )\n    convert_representation(ctx->ghash_h, ctx->ghash_h, GF_REPRESENTATION);\n#endif\n    return RETURN_GOOD;\n}\n\nvoid gf_mul_hh(gf_t a, gcm_ctx ctx[1])\n{\n#if defined( GF_REPRESENTATION ) || !defined( NO_TABLES )\n    gf_t    scr;\n#endif\n#if defined(  GF_REPRESENTATION )\n    convert_representation(a, a, GF_REPRESENTATION);\n#endif\n\n#if defined( TABLES_64K )\n    gf_mul_64k(a, ctx->gf_t64k, scr);\n#elif defined( TABLES_8K )\n    gf_mul_8k(a, ctx->gf_t8k, scr);\n#elif defined( TABLES_4K )\n    gf_mul_4k(a, ctx->gf_t4k, scr);\n#elif defined( TABLES_256 )\n    gf_mul_256(a, ctx->gf_t256, scr);\n#else\n# if defined( GF_REPRESENTATION )\n    convert_representation(scr, ctx->ghash_h, GF_REPRESENTATION);\n    gf_mul(a, scr);\n# else\n    gf_mul(a, ctx->ghash_h);\n# endif\n#endif\n\n#if defined(  GF_REPRESENTATION )\n    convert_representation(a, a, GF_REPRESENTATION);\n#endif\n}\n\nret_type gcm_init_message(                  /* initialise a new message     */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint32_t i, n_pos = 0;\n    uint8_t *p;\n\n    memset(ctx->ctr_val, 0, BLOCK_SIZE);\n    if(iv_len == CTR_POS)\n    {\n        memcpy(ctx->ctr_val, iv, CTR_POS); UI8_PTR(ctx->ctr_val)[15] = 0x01;\n    }\n    else\n    {   n_pos = iv_len;\n        while(n_pos >= BLOCK_SIZE)\n        {\n            xor_block_aligned(ctx->ctr_val, ctx->ctr_val, iv);\n            n_pos -= BLOCK_SIZE;\n            iv += BLOCK_SIZE;\n            gf_mul_hh((void*)ctx->ctr_val, ctx);\n        }\n\n        if(n_pos)\n        {\n            p = UI8_PTR(ctx->ctr_val);\n            while(n_pos-- > 0)\n                *p++ ^= *iv++;\n            gf_mul_hh((void*)ctx->ctr_val, ctx);\n        }\n        n_pos = (iv_len << 3);\n        for(i = BLOCK_SIZE - 1; n_pos; --i, n_pos >>= 8)\n            UI8_PTR(ctx->ctr_val)[i] ^= (unsigned char)n_pos;\n        gf_mul_hh((void*)ctx->ctr_val, ctx);\n    }\n\n    ctx->y0_val = *UI32_PTR(UI8_PTR(ctx->ctr_val) + CTR_POS);\n    memset(ctx->hdr_ghv, 0, BLOCK_SIZE);\n    memset(ctx->txt_ghv, 0, BLOCK_SIZE);\n    ctx->hdr_cnt = 0;\n    ctx->txt_ccnt = ctx->txt_acnt = 0;\n    return RETURN_GOOD;\n}\n\nret_type gcm_auth_header(                   /* authenticate the header      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint32_t cnt = 0, b_pos = (uint32_t)ctx->hdr_cnt & BLK_ADR_MASK;\n\n    if(!hdr_len)\n        return RETURN_GOOD;\n\n    if(ctx->hdr_cnt && b_pos == 0)\n        gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n\n    if(!((hdr - (UI8_PTR(ctx->hdr_ghv) + b_pos)) & BUF_ADRMASK))\n    {\n\t\twhile(cnt < hdr_len && (b_pos & BUF_ADRMASK))\n\t\t    UI8_PTR(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];\n\n\t\twhile(cnt + BUF_INC <= hdr_len && b_pos <= BLOCK_SIZE - BUF_INC)\n        {\n            *UNIT_PTR(UI8_PTR(ctx->hdr_ghv) + b_pos) ^= *UNIT_PTR(hdr + cnt);\n            cnt += BUF_INC; b_pos += BUF_INC;\n        }\n\n        while(cnt + BLOCK_SIZE <= hdr_len)\n        {\n            gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n            xor_block_aligned(ctx->hdr_ghv, ctx->hdr_ghv, hdr + cnt);\n            cnt += BLOCK_SIZE;\n        }\n    }\n    else\n    {\n        while(cnt < hdr_len && b_pos < BLOCK_SIZE)\n            UI8_PTR(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];\n\n        while(cnt + BLOCK_SIZE <= hdr_len)\n        {\n            gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n            xor_block(ctx->hdr_ghv, ctx->hdr_ghv, hdr + cnt);\n            cnt += BLOCK_SIZE;\n        }\n    }\n\n    while(cnt < hdr_len)\n    {\n        if(b_pos == BLOCK_SIZE)\n        {\n            gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n            b_pos = 0;\n        }\n        UI8_PTR(ctx->hdr_ghv)[b_pos++] ^= hdr[cnt++];\n    }\n\n    ctx->hdr_cnt += cnt;\n    return RETURN_GOOD;\n}\n\nret_type gcm_auth_data(                     /* authenticate ciphertext data */\n            const unsigned char data[],     /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint32_t cnt = 0, b_pos = (uint32_t)ctx->txt_acnt & BLK_ADR_MASK;\n\n    if(!data_len)\n        return RETURN_GOOD;\n\n    if(ctx->txt_acnt && b_pos == 0)\n        gf_mul_hh((void*)ctx->txt_ghv, ctx);\n\n    if(!((data - (UI8_PTR(ctx->txt_ghv) + b_pos)) & BUF_ADRMASK))\n    {\n\t    while(cnt < data_len && (b_pos & BUF_ADRMASK))\n\t\t    UI8_PTR(ctx->txt_ghv)[b_pos++] ^= data[cnt++];\n\n        while(cnt + BUF_INC <= data_len && b_pos <= BLOCK_SIZE - BUF_INC)\n        {\n            *UNIT_PTR(UI8_PTR(ctx->txt_ghv) + b_pos) ^= *UNIT_PTR(data + cnt);\n            cnt += BUF_INC; b_pos += BUF_INC;\n        }\n\n        while(cnt + BLOCK_SIZE <= data_len)\n        {\n            gf_mul_hh((void*)ctx->txt_ghv, ctx);\n            xor_block_aligned(ctx->txt_ghv, ctx->txt_ghv, data + cnt);\n            cnt += BLOCK_SIZE;\n        }\n    }\n    else\n    {\n        while(cnt < data_len && b_pos < BLOCK_SIZE)\n            UI8_PTR(ctx->txt_ghv)[b_pos++] ^= data[cnt++];\n\n        while(cnt + BLOCK_SIZE <= data_len)\n        {\n            gf_mul_hh((void*)ctx->txt_ghv, ctx);\n            xor_block(ctx->txt_ghv, ctx->txt_ghv, data + cnt);\n            cnt += BLOCK_SIZE;\n        }\n    }\n\n    while(cnt < data_len)\n    {\n        if(b_pos == BLOCK_SIZE)\n        {\n            gf_mul_hh((void*)ctx->txt_ghv, ctx);\n            b_pos = 0;\n        }\n        UI8_PTR(ctx->txt_ghv)[b_pos++] ^= data[cnt++];\n    }\n\n    ctx->txt_acnt += cnt;\n    return RETURN_GOOD;\n}\n\nret_type gcm_crypt_data(                    /* encrypt or decrypt data      */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint32_t cnt = 0, b_pos = (uint32_t)ctx->txt_ccnt & BLK_ADR_MASK;\n\n    if(!data_len)\n        return RETURN_GOOD;\n\n    if(!((data - (UI8_PTR(ctx->enc_ctr) + b_pos)) & BUF_ADRMASK))\n    {\n        if(b_pos)\n        {\n\t        while(cnt < data_len && (b_pos & BUF_ADRMASK))\n\t\t        data[cnt++] ^= UI8_PTR(ctx->enc_ctr)[b_pos++];\n\n            while(cnt + BUF_INC <= data_len && b_pos <= BLOCK_SIZE - BUF_INC)\n            {\n                *UNIT_PTR(data + cnt) ^= *UNIT_PTR(UI8_PTR(ctx->enc_ctr) + b_pos);\n                cnt += BUF_INC; b_pos += BUF_INC;\n            }\n        }\n\n        while(cnt + BLOCK_SIZE <= data_len)\n        {\n            inc_ctr(ctx->ctr_val);\n            aes_encrypt(UI8_PTR(ctx->ctr_val), UI8_PTR(ctx->enc_ctr), ctx->aes);\n            xor_block_aligned(data + cnt, data + cnt, ctx->enc_ctr);\n            cnt += BLOCK_SIZE;\n        }\n    }\n    else\n    {\n        if(b_pos)\n            while(cnt < data_len && b_pos < BLOCK_SIZE)\n                data[cnt++] ^= UI8_PTR(ctx->enc_ctr)[b_pos++];\n\n        while(cnt + BLOCK_SIZE <= data_len)\n        {\n            inc_ctr(ctx->ctr_val);\n            aes_encrypt(UI8_PTR(ctx->ctr_val), UI8_PTR(ctx->enc_ctr), ctx->aes);\n            xor_block(data + cnt, data + cnt, ctx->enc_ctr);\n            cnt += BLOCK_SIZE;\n        }\n    }\n\n    while(cnt < data_len)\n    {\n        if(b_pos == BLOCK_SIZE || !b_pos)\n        {\n            inc_ctr(ctx->ctr_val);\n            aes_encrypt(UI8_PTR(ctx->ctr_val), UI8_PTR(ctx->enc_ctr), ctx->aes);\n            b_pos = 0;\n        }\n        data[cnt++] ^= UI8_PTR(ctx->enc_ctr)[b_pos++];\n    }\n\n    ctx->txt_ccnt += cnt;\n    return RETURN_GOOD;\n}\n\nret_type gcm_compute_tag(                   /* compute authentication tag   */\n            unsigned char tag[],            /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint32_t i, ln;\n    gf_t tbuf;\n\n    if(ctx->txt_acnt != ctx->txt_ccnt && ctx->txt_ccnt > 0)\n        return RETURN_ERROR;\n\n    gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n    gf_mul_hh((void*)ctx->txt_ghv, ctx);\n\n    if(ctx->hdr_cnt)\n    {\n        ln = (uint32_t)((ctx->txt_acnt + BLOCK_SIZE - 1) / BLOCK_SIZE);\n        if(ln)\n        {\n#if 1       /* alternative versions of the exponentiation operation */\n            memcpy(tbuf, ctx->ghash_h, BLOCK_SIZE);\n#       if defined(  GF_REPRESENTATION )\n            convert_representation(tbuf, tbuf, GF_REPRESENTATION);\n            convert_representation(ctx->hdr_ghv, ctx->hdr_ghv, GF_REPRESENTATION);\n#       endif\n            for( ; ; )\n            {\n                if(ln & 1)\n                {\n                    gf_mul((void*)ctx->hdr_ghv, tbuf);\n                }\n                if(!(ln >>= 1))\n                    break;\n                gf_mul(tbuf, tbuf);\n            }\n#else       /* this one seems slower on x86 and x86_64 :-( */\n            i = ln | ln >> 1; i |= i >> 2; i |= i >> 4;\n            i |= i >> 8; i |= i >> 16; i &= ~(i >> 1);\n            memset(tbuf, 0, BLOCK_SIZE);\n            UI8_PTR(tbuf)[0] = 0x80;\n            while(i)\n            {\n#           if defined(  GF_REPRESENTATION )\n                convert_representation(tbuf, tbuf, GF_REPRESENTATION);\n#           endif\n                gf_mul(tbuf, tbuf);\n#           if defined(  GF_REPRESENTATION )\n                convert_representation(tbuf, tbuf, GF_REPRESENTATION);\n#           endif\n                if(i & ln)\n                    gf_mul_hh(tbuf, ctx);\n                i >>= 1;\n            }\n#           if defined(  GF_REPRESENTATION )\n            convert_representation(tbuf, tbuf, GF_REPRESENTATION);\n            convert_representation(ctx->hdr_ghv, ctx->hdr_ghv, GF_REPRESENTATION);\n#           endif\n            gf_mul((void*)ctx->hdr_ghv, tbuf);\n#endif\n#if         defined(  GF_REPRESENTATION )\n            convert_representation(ctx->hdr_ghv, ctx->hdr_ghv, GF_REPRESENTATION);\n#           endif\n        }\n    }\n\n    i = BLOCK_SIZE; \n#ifdef BRG_UI64\n    {   uint64_t tm = ((uint64_t)ctx->txt_acnt) << 3;\n        while(i-- > 0)\n        {\n            UI8_PTR(ctx->hdr_ghv)[i] ^= UI8_PTR(ctx->txt_ghv)[i] ^ (unsigned char)tm;\n            tm = (i == 8 ? (((uint64_t)ctx->hdr_cnt) << 3) : tm >> 8);\n        }\n    }\n#else   \n    {   uint32_t tm = ctx->txt_acnt << 3;\n\n        while(i-- > 0)\n        {\n            UI8_PTR(ctx->hdr_ghv)[i] ^= UI8_PTR(ctx->txt_ghv)[i] ^ (unsigned char)tm;\n            if(i & 3)\n                tm >>= 8;\n            else if(i == 4)\n                tm = ctx->txt_acnt >> 29;\n            else if(i == 8)\n                tm = ctx->hdr_cnt << 3;\n            else\n                tm = ctx->hdr_cnt >> 29;\n        }\n    }\n#endif\n\n    gf_mul_hh((void*)ctx->hdr_ghv, ctx);\n\n    memcpy(ctx->enc_ctr, ctx->ctr_val, BLOCK_SIZE);\n    *UI32_PTR(UI8_PTR(ctx->enc_ctr) + CTR_POS) = ctx->y0_val;\n    aes_encrypt(UI8_PTR(ctx->enc_ctr), UI8_PTR(ctx->enc_ctr), ctx->aes);\n    for(i = 0; i < (unsigned int)tag_len; ++i)\n        tag[i] = (unsigned char)(UI8_PTR(ctx->hdr_ghv)[i] ^ UI8_PTR(ctx->enc_ctr)[i]);\n\n    return (ctx->txt_ccnt == ctx->txt_acnt ? RETURN_GOOD : RETURN_WARN);\n}\n\nret_type gcm_end(                           /* clean up and end operation   */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{\n    memset(ctx, 0, sizeof(gcm_ctx));\n    return RETURN_GOOD;\n}\n\nret_type gcm_encrypt(                       /* encrypt & authenticate data  */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{\n\n    gcm_crypt_data(data, data_len, ctx);\n    gcm_auth_data(data, data_len, ctx);\n    return RETURN_GOOD;\n}\n\nret_type gcm_decrypt(                       /* authenticate & decrypt data  */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{\n    gcm_auth_data(data, data_len, ctx);\n    gcm_crypt_data(data, data_len, ctx);\n    return RETURN_GOOD;\n}\n\nret_type gcm_encrypt_message(               /* encrypt an entire message    */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            unsigned char msg[],            /* the message buffer           */\n            unsigned long msg_len,          /* and its length in bytes      */\n            unsigned char tag[],            /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{\n    gcm_init_message(iv, iv_len, ctx);\n    gcm_auth_header(hdr, hdr_len, ctx);\n    gcm_encrypt(msg, msg_len, ctx);\n    return gcm_compute_tag(tag, tag_len, ctx) ? RETURN_ERROR : RETURN_GOOD;\n}\n\nret_type gcm_decrypt_message(               /* decrypt an entire message    */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            unsigned char msg[],            /* the message buffer           */\n            unsigned long msg_len,          /* and its length in bytes      */\n            const unsigned char tag[],      /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1])                 /* the mode context             */\n{   uint8_t local_tag[BLOCK_SIZE];\n    ret_type rr;\n\n    gcm_init_message(iv, iv_len, ctx);\n    gcm_auth_header(hdr, hdr_len, ctx);\n    gcm_decrypt(msg, msg_len, ctx);\n    rr = gcm_compute_tag(local_tag, tag_len, ctx);\n    return (rr != RETURN_GOOD || memcmp(tag, local_tag, tag_len)) ? RETURN_ERROR : RETURN_GOOD;\n}\n\n#if defined(__cplusplus)\n}\n#endif\n#endif /* USE_GCM */\n"
  },
  {
    "path": "deps/cl345/crypt/gcm.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 11/01/2011\n\n I am grateful for the work done by Mark Rodenkirch and Jason Papadopoulos\n in helping to remove a bug in the operation of this code on big endian\n systems when fast buffer operations are enabled.\n ---------------------------------------------------------------------------\n*/\n\n#ifndef _GCM_H\n#define _GCM_H\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"aes.h\"\n  #include \"gf128mul.h\"\n#else\n  #include \"crypt/aes.h\"\n  #include \"crypt/gf128mul.h\"\n#endif /* Compiler-specific includes */\n\n/*  USER DEFINABLE OPTIONS (Further options need to be set in gf128mul.h) */\n\n/*  UNIT_BITS sets the size of variables used to process 16 byte buffers\n    when the buffer alignment allows this.  When buffers are processed\n    in bytes, 16 individual operations are invoolved.  But if, say, such \n    a buffer is divided into 4 32 bit variables, it can then be processed\n    in 4 operations, making the code typically much faster. In general\n    it will pay to use the longest natively supported size, which will\n    probably be 32 or 64 bits in 32 and 64 bit systems respectively.\n*/\n\n#if defined( UNIT_BITS )\n# undef UNIT_BITS\n#endif\n\n#if !defined( UNIT_BITS )\n#  if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN\n#    if 0\n#      define UNIT_BITS   8\n#    elif 0\n#      define UNIT_BITS  32\n#    elif 1\n#      define UNIT_BITS  64\n#    endif\n#  elif defined( _WIN64 )\n#    define UNIT_BITS 64\n#  else\n#    define UNIT_BITS 32\n#  endif\n#endif\n\n#if UNIT_BITS == 64 && !defined( NEED_UINT_64T )\n#  define NEED_UINT_64T\n#endif\n\n/* END OF USER DEFINABLE OPTIONS */\n\n/*  After encryption or decryption operations the return value of\n    'compute tag' will be one of the values RETURN_GOOD, RETURN_WARN\n    or RETURN_ERROR, the latter indicating an error. A return value\n    RETURN_GOOD indicates that both encryption and authentication\n    have taken place and resulted in the returned tag value. If\n    the returned value is RETURN_WARN, the tag value is the result\n    of authentication alone without encryption (CCM) or decryption\n    (GCM and EAX).\n*/\n#ifndef RETURN_GOOD\n# define RETURN_WARN      1\n# define RETURN_GOOD      0\n# define RETURN_ERROR    -1\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#ifndef RET_TYPE_DEFINED\n  typedef int  ret_type;\n#endif\nUNIT_TYPEDEF(gcm_unit_t, UNIT_BITS);\nBUFR_TYPEDEF(gcm_buf_t, UNIT_BITS, AES_BLOCK_SIZE);\n\n#define GCM_BLOCK_SIZE  AES_BLOCK_SIZE\n\n/* The GCM-AES  context  */\n\ntypedef struct\n{\n#if defined( TABLES_64K )\n    gf_t64k_a       gf_t64k;\n#endif\n#if defined( TABLES_8K )\n    gf_t8k_a        gf_t8k;\n#endif\n#if defined( TABLES_4K )\n    gf_t4k_a        gf_t4k;\n#endif\n#if defined( TABLES_256 )\n    gf_t256_a       gf_t256;\n#endif\n    gcm_buf_t       ctr_val;                /* CTR counter value            */\n    gcm_buf_t       enc_ctr;                /* encrypted CTR block          */\n    gcm_buf_t       hdr_ghv;                /* ghash buffer (header)        */\n    gcm_buf_t       txt_ghv;                /* ghash buffer (ciphertext)    */\n    gf_t            ghash_h;                /* ghash H value                */\n    aes_encrypt_ctx aes[1];                 /* AES encryption context       */\n    uint32_t        y0_val;                 /* initial counter value        */\n    uint32_t        hdr_cnt;                /* header bytes so far          */\n    uint32_t        txt_ccnt;               /* text bytes so far (encrypt)  */\n    uint32_t        txt_acnt;               /* text bytes so far (auth)     */\n} gcm_ctx;\n\n/* The following calls handle mode initialisation, keying and completion    */\n\nret_type gcm_init_and_key(                  /* initialise mode and set key  */\n            const unsigned char key[],      /* the key value                */\n            unsigned long key_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_end(                           /* clean up and end operation   */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\n/* The following calls handle complete messages in memory as one operation  */\n\nret_type gcm_encrypt_message(               /* encrypt an entire message    */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            unsigned char msg[],            /* the message buffer           */\n            unsigned long msg_len,          /* and its length in bytes      */\n            unsigned char tag[],            /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\n                                /* RETURN_GOOD is returned if the input tag */\n                                /* matches that for the decrypted message   */\nret_type gcm_decrypt_message(               /* decrypt an entire message    */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            unsigned char msg[],            /* the message buffer           */\n            unsigned long msg_len,          /* and its length in bytes      */\n            const unsigned char tag[],      /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\n/* The following calls handle messages in a sequence of operations followed */\n/* by tag computation after the sequence has been completed. In these calls */\n/* the user is responsible for verfiying the computed tag on decryption     */\n\nret_type gcm_init_message(                  /* initialise a new message     */\n            const unsigned char iv[],       /* the initialisation vector    */\n            unsigned long iv_len,           /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_auth_header(                   /* authenticate the header      */\n            const unsigned char hdr[],      /* the header buffer            */\n            unsigned long hdr_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_encrypt(                       /* encrypt & authenticate data  */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_decrypt(                       /* authenticate & decrypt data  */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_compute_tag(                   /* compute authentication tag   */\n            unsigned char tag[],            /* the buffer for the tag       */\n            unsigned long tag_len,          /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\n/*  The use of the following calls should be avoided if possible because \n    their use requires a very good understanding of the way this encryption \n    mode works and the way in which this code implements it in order to use \n    them correctly.\n\n    The gcm_auth_data routine is used to authenticate encrypted message data.\n    In message encryption gcm_crypt_data must be called before gcm_auth_data\n    is called since it is encrypted data that is authenticated.  In message\n    decryption authentication must occur before decryption and data can be\n    authenticated without being decrypted if necessary.\n\n    If these calls are used it is up to the user to ensure that these routines\n    are called in the correct order and that the correct data is passed to \n    them.\n\n    When gcm_compute_tag is called it is assumed that an error in use has\n    occurred if both encryption (or decryption) and authentication have taken\n    place but the total lengths of the message data respectively authenticated\n    and encrypted are not the same. If authentication has taken place but \n    there has been no corresponding encryption or decryption operations (none\n    at all) only a warning is issued. This should be treated as an error if it \n    occurs during encryption but it is only signalled as a warning as it might \n    be intentional when decryption operations are involved (this avoids having\n    different compute tag functions for encryption and decryption). Decryption\n    operations can be undertaken freely after authetication but if the tag is\n    computed after such operations an error will be signalled if the lengths\n    of the data authenticated and decrypted don't match.\n*/\n\nret_type gcm_auth_data(                     /* authenticate ciphertext data */\n            const unsigned char data[],     /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\nret_type gcm_crypt_data(                    /* encrypt or decrypt data      */\n            unsigned char data[],           /* the data buffer              */\n            unsigned long data_len,         /* and its length in bytes      */\n            gcm_ctx ctx[1]);                /* the mode context             */\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/gf128mul.c",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 20/12/2007\n\n This file provides fast multiplication in GF(128) as required by several\n cryptographic authentication modes (see gfmul128.h).\n*/\n\n/*  Speed critical loops can be unrolled to gain speed but consume more memory */\n#if 1\n#  define UNROLL_LOOPS\n#endif\n\n/* The order of these includes matters */\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"mode_hdr.h\"\n  #include \"gf128mul.h\"\n#else\n  #include \"crypt/mode_hdr.h\"\n  #include \"crypt/gf128mul.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_GCM\n\n/* We can only include gf_mul_lo.h at this point since it includes code \n   for various functions - pcg */\n\n#if defined( INC_ALL )\n  #include \"gf_mul_lo.h\"\n#else\n  #include \"crypt/gf_mul_lo.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( GF_MODE_LL )\n#  define mode   _ll\n#elif defined( GF_MODE_BL )\n#  define mode   _bl\n#elif defined( GF_MODE_LB )\n#  define mode   _lb\n#elif defined( GF_MODE_BB )\n#  define mode   _bb\n#else\n#  error mode is not defined\n#endif\n\n#if defined( GF_MODE_LL) || defined( GF_MODE_LB )\n#  define GF_INDEX(i)  (i)\n#else\n#  define GF_INDEX(i)  (15 - (i))\n#endif\n\n/* A slow field multiplier */\n\nvoid gf_mul(gf_t a, const gf_t b)\n{   gf_t p[8];\n    uint8_t *q, ch;\n    int i;\n\n    copy_block_aligned(p[0], a);\n    for(i = 0; i < 7; ++i)\n        gf_mulx1(mode)(p[i + 1], p[i]);\n\n    q = (uint8_t*)(a == b ? p[0] : b);\n    memset(a, 0, GF_BYTE_LEN);\n    for(i = 15 ;  ; )\n    {\n        ch = q[GF_INDEX(i)];\n        if(ch & X_0)\n            xor_block_aligned(a, a, p[0]);\n        if(ch & X_1)\n            xor_block_aligned(a, a, p[1]);\n        if(ch & X_2)\n            xor_block_aligned(a, a, p[2]);\n        if(ch & X_3)\n            xor_block_aligned(a, a, p[3]);\n        if(ch & X_4)\n            xor_block_aligned(a, a, p[4]);\n        if(ch & X_5)\n            xor_block_aligned(a, a, p[5]);\n        if(ch & X_6)\n            xor_block_aligned(a, a, p[6]);\n        if(ch & X_7)\n            xor_block_aligned(a, a, p[7]);\n        if(!i--)\n            break;\n        gf_mulx8(mode)(a);\n    }\n}\n\n#if defined( TABLES_64K )\n\n/*  This version uses 64k bytes of table space on the stack.\n    An input variable field value in a[] has to be multiplied\n    by a key value in g[] that changes far less frequently.\n\n    To do this a[] is split up into 16 smaller field values,\n    each one byte in length. For the 256 values of each of\n    these smaller values, we can precompute the result of\n    mulltiplying g by this field value. We can then combine\n    these values to provide the full multiply. So for each\n    of 16 bytes we have a table of 256 field values each of\n    16 bytes - 64k bytes in total.\n*/\n\nvoid init_64k_table(const gf_t g, gf_t64k_t t)\n{   int i = 0, j, k;\n\n    /*\n    depending on the representation we have to process bits\n    within bytes high to low (0xe1 style ) or low to high\n    (0x87 style).  We start by producing the powers x ,x^2\n    .. x^7 and put them in t[0][1], t[0][2] .. t[128] or in\n    t[128], t[64] .. t[1] depending on the bit order in use.\n    */\n\n    /* clear the element for the zero field element */\n    memset(t[0][0], 0, GF_BYTE_LEN);\n\n#if defined( GF_MODE_LL ) || defined( GF_MODE_BL )\n\n    /* g -> t[0][1], generate t[0][2] ...           */\n    memcpy(t[0][1], g, GF_BYTE_LEN);\n    for(j = 1; j <= 64; j <<= 1)\n        gf_mulx1(mode)(t[0][j + j], t[0][j]);\n#else\n\n    /* g -> t[0][128], generate t[0][64] ...        */\n    memcpy(t[0][128], g, GF_BYTE_LEN);\n    for(j = 64; j >= 1; j >>= 1)\n        gf_mulx1(mode)(t[0][j], t[0][j + j]);\n#endif\n\n    for( ; ; )\n    {\n        /*  if { n } stands for the field value represented by\n            the integer n, we can express higher multiplies in\n            the table as follows:\n\n                1. g * { 3} = g * {2} ^ g * {1}\n\n                2. g * { 5} = g * {4} ^ g * {1}\n                   g * { 6} = g * {4} ^ g * {2}\n                   g * { 7} = g * {4} ^ g * {3}\n\n                3. g * { 9} = g * {8} ^ g * {1}\n                   g * {10} = g * {8} ^ g * {2}\n                   ....\n\n           and so on.  This is what the following loops do.\n        */\n        for(j = 2; j < 256; j += j)\n            for(k = 1; k < j; ++k)\n                xor_block_aligned(t[i][j + k], t[i][j], t[i][k]);\n\n        if(++i == GF_BYTE_LEN)  /* all 16 byte positions done */\n            return;\n\n        /*  We now move to the next byte up and set up its eight\n            starting values by multiplying the values in the\n            lower table by x^8\n        */\n        memset(t[i][0], 0, GF_BYTE_LEN);\n        for(j = 128; j > 0; j >>= 1)\n        {\n            memcpy(t[i][j], t[i - 1][j], GF_BYTE_LEN);\n            gf_mulx8(mode)(t[i][j]);\n        }\n    }\n}\n\n#define xor_64k(i,ap,t,r) xor_block_aligned(r, r, t[i][ap[GF_INDEX(i)]])\n\n#if defined( UNROLL_LOOPS )\n\nvoid gf_mul_64k(gf_t a, const  gf_t64k_t t, gf_t r)\n{   uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    xor_64k(15, ap, t, r); xor_64k(14, ap, t, r);\n    xor_64k(13, ap, t, r); xor_64k(12, ap, t, r);\n    xor_64k(11, ap, t, r); xor_64k(10, ap, t, r);\n    xor_64k( 9, ap, t, r); xor_64k( 8, ap, t, r);\n    xor_64k( 7, ap, t, r); xor_64k( 6, ap, t, r);\n    xor_64k( 5, ap, t, r); xor_64k( 4, ap, t, r);\n    xor_64k( 3, ap, t, r); xor_64k( 2, ap, t, r);\n    xor_64k( 1, ap, t, r); xor_64k( 0, ap, t, r);\n    copy_block_aligned(a, r);\n}\n\n#else\n\nvoid gf_mul_64k(gf_t a, const  gf_t64k_t t, gf_t r)\n{   int i;\n    uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    for(i = 15; i >= 0; --i)\n    {\n        xor_64k(i,ap,t,r);\n    }\n    copy_block_aligned(a, r);\n}\n\n#endif\n\n#endif\n\n#if defined( TABLES_8K )\n\n/*  This version uses 8k bytes of table space on the stack.\n    An input field value in a[] has to be multiplied by a\n    key value in g[]. To do this a[] is split up into 32\n    smaller field values each 4-bits in length. For the\n    16 values of each of these smaller field values we can\n    precompute the result of mulltiplying g[] by the field\n    value in question. So for each of 32 nibbles we have a\n    table of 16 field values, each of 16 bytes - 8k bytes\n    in total.\n*/\nvoid init_8k_table(const gf_t g, gf_t8k_t t)\n{   int i = 0, j, k;\n\n    /*  do the low 4-bit nibble first - t[0][16] - and note\n        that the unit multiplier sits at 0x01 - t[0][1] in\n        the table. Then multiplies by x go at 2, 4, 8\n    */\n    /* set the table elements for a zero multiplier */\n    memset(t[0][0], 0, GF_BYTE_LEN);\n    memset(t[1][0], 0, GF_BYTE_LEN);\n\n#if defined( GF_MODE_LL ) || defined( GF_MODE_BL )\n\n    /* t[0][1] = g, compute t[0][2], t[0][4], t[0][8]   */\n    memcpy(t[0][1], g, GF_BYTE_LEN);\n    for(j = 1; j <= 4; j <<= 1)\n        gf_mulx1(mode)(t[0][j + j], t[0][j]);\n    /* t[1][1] = t[0][1] * x^4 = t[0][8] * x            */\n    gf_mulx1(mode)(t[1][1], t[0][8]);\n    for(j = 1; j <= 4; j <<= 1)\n        gf_mulx1(mode)(t[1][j + j], t[1][j]);\n#else\n\n    /* g -> t[0][8], compute t[0][4], t[0][2], t[0][1]  */\n    memcpy(t[1][8], g, GF_BYTE_LEN);\n    for(j = 4; j >= 1; j >>= 1)\n        gf_mulx1(mode)(t[1][j], t[1][j + j]);\n    /* t[1][1] = t[0][1] * x^4 = t[0][8] * x            */\n    gf_mulx1(mode)(t[0][8], t[1][1]);\n    for(j = 4; j >= 1; j >>= 1)\n        gf_mulx1(mode)(t[0][j], t[0][j + j]);\n#endif\n\n    for( ; ; )\n    {\n        for(j = 2; j < 16; j += j)\n            for(k = 1; k < j; ++k)\n                xor_block_aligned(t[i][j + k], t[i][j], t[i][k]);\n\n        if(++i == 2 * GF_BYTE_LEN)\n            return;\n\n        if(i > 1)\n        {\n            memset(t[i][0], 0, GF_BYTE_LEN);\n            for(j = 8; j > 0; j >>= 1)\n            {\n                memcpy(t[i][j], t[i - 2][j], GF_BYTE_LEN);\n                gf_mulx8(mode)(t[i][j]);\n            }\n        }\n\n    }\n}\n\n#define xor_8k(i,ap,t,r)   \\\n    xor_block_aligned(r, r, t[i + i][ap[GF_INDEX(i)] & 15]); \\\n    xor_block_aligned(r, r, t[i + i + 1][ap[GF_INDEX(i)] >> 4])\n\n#if defined( UNROLL_LOOPS )\n\nvoid gf_mul_8k(gf_t a, const gf_t8k_t t, gf_t r)\n{   uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    xor_8k(15, ap, t, r); xor_8k(14, ap, t, r);\n    xor_8k(13, ap, t, r); xor_8k(12, ap, t, r);\n    xor_8k(11, ap, t, r); xor_8k(10, ap, t, r);\n    xor_8k( 9, ap, t, r); xor_8k( 8, ap, t, r);\n    xor_8k( 7, ap, t, r); xor_8k( 6, ap, t, r);\n    xor_8k( 5, ap, t, r); xor_8k( 4, ap, t, r);\n    xor_8k( 3, ap, t, r); xor_8k( 2, ap, t, r);\n    xor_8k( 1, ap, t, r); xor_8k( 0, ap, t, r);\n    copy_block_aligned(a, r);\n}\n\n#else\n\nvoid gf_mul_8k(gf_t a, const gf_t8k_t t, gf_t r)\n{   int i;\n    uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    for(i = 15; i >= 0; --i)\n    {\n        xor_8k(i,ap,t,r);\n    }\n    memcpy(a, r, GF_BYTE_LEN);\n}\n\n#endif\n\n#endif\n\n#if defined( TABLES_4K )\n\n/*  This version uses 4k bytes of table space on the stack.\n    A 16 byte buffer has to be multiplied by a 16 byte key\n    value in GF(128).  If we consider a GF(128) value in a\n    single byte, we can construct a table of the 256 16\n    byte values that result from multiplying g by the 256\n    values of this byte.  This requires 4096 bytes.\n\n    If we take the highest byte in the buffer and use this\n    table to multiply it by g, we then have to multiply it\n    by x^120 to get the final value. For the next highest\n    byte the result has to be multiplied by x^112 and so on.\n\n    But we can do this by accumulating the result in an\n    accumulator starting with the result for the top byte.\n    We repeatedly multiply the accumulator value by x^8 and\n    then add in (i.e. xor) the 16 bytes of the next lower\n    byte in the buffer, stopping when we reach the lowest\n    byte. This requires a 4096 byte table.\n*/\n\nvoid init_4k_table(const gf_t g, gf_t4k_t t)\n{   int j, k;\n\n    memset(t[0], 0, GF_BYTE_LEN);\n\n#if defined( GF_MODE_LL ) || defined( GF_MODE_BL )\n\n    memcpy(t[1], g, GF_BYTE_LEN);\n    for(j = 1; j <= 64; j <<= 1)\n        gf_mulx1(mode)(t[j + j], t[j]);\n#else\n\n    memcpy(t[128], g, GF_BYTE_LEN);\n    for(j = 64; j >= 1; j >>= 1)\n        gf_mulx1(mode)(t[j], t[j + j]);\n#endif\n\n    for(j = 2; j < 256; j += j)\n        for(k = 1; k < j; ++k)\n            xor_block_aligned(t[j + k], t[j], t[k]);\n}\n\n#define xor_4k(i,ap,t,r) gf_mulx8(mode)(r); xor_block_aligned(r, r, t[ap[GF_INDEX(i)]])\n\n#if defined( UNROLL_LOOPS )\n\nvoid gf_mul_4k(gf_t a, const gf_t4k_t t, gf_t r)\n{   uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    xor_4k(15, ap, t, r); xor_4k(14, ap, t, r);\n    xor_4k(13, ap, t, r); xor_4k(12, ap, t, r);\n    xor_4k(11, ap, t, r); xor_4k(10, ap, t, r);\n    xor_4k( 9, ap, t, r); xor_4k( 8, ap, t, r);\n    xor_4k( 7, ap, t, r); xor_4k( 6, ap, t, r);\n    xor_4k( 5, ap, t, r); xor_4k( 4, ap, t, r);\n    xor_4k( 3, ap, t, r); xor_4k( 2, ap, t, r);\n    xor_4k( 1, ap, t, r); xor_4k( 0, ap, t, r);\n    copy_block_aligned(a, r);\n}\n\n#else\n\nvoid gf_mul_4k(gf_t a, const gf_t4k_t t, gf_t r)\n{   int i = 15;\n    uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    for(i = 15; i >=0; --i)\n    {\n        xor_4k(i, ap, t, r);\n    }\n    copy_block_aligned(a, r);\n}\n\n#endif\n\n#endif\n\n#if defined( TABLES_256 )\n\n/*  This version uses 256 bytes of table space on the stack.\n    A 16 byte buffer has to be multiplied by a 16 byte key\n    value in GF(128).  If we consider a GF(128) value in a\n    single 4-bit nibble, we can construct a table of the 16\n    16 byte  values that result from the 16 values of this\n    byte.  This requires 256 bytes. If we take the highest\n    4-bit nibble in the buffer and use this table to get the\n    result, we then have to multiply by x^124 to get the\n    final value. For the next highest byte the result has to\n    be multiplied by x^120 and so on. But we can do this by\n    accumulating the result in an accumulator starting with\n    the result for the top nibble.  We repeatedly multiply\n    the accumulator value by x^4 and then add in (i.e. xor)\n    the 16 bytes of the next lower nibble in the buffer,\n    stopping when we reach the lowest nibble. This uses a\n    256 byte table.\n*/\n\nvoid init_256_table(const gf_t g, gf_t256_t t)\n{   int j, k;\n\n    memset(t[0], 0, GF_BYTE_LEN);\n\n#if defined( GF_MODE_LL ) || defined( GF_MODE_BL )\n\n    memcpy(t[1], g, GF_BYTE_LEN);\n    for(j = 1; j <= 4; j <<= 1)\n        gf_mulx1(mode)(t[j + j], t[j]);\n#else\n\n    memcpy(t[8], g, GF_BYTE_LEN);\n    for(j = 4; j >= 1; j >>= 1)\n        gf_mulx1(mode)(t[j], t[j + j]);\n#endif\n\n    for(j = 2; j < 16; j += j)\n        for(k = 1; k < j; ++k)\n            xor_block_aligned(t[j + k], t[j], t[k]);\n}\n\n#define x_lo(i,ap,t,r) gf_mulx4(mode)(r); xor_block_aligned(r, r, t[ap[GF_INDEX(i)] & 0x0f])\n#define x_hi(i,ap,t,r) gf_mulx4(mode)(r); xor_block_aligned(r, r, t[ap[GF_INDEX(i)] >> 4])\n\n#if defined( GF_MODE_LL ) || defined( GF_MODE_BL )\n#define xor_256(a,b,c,d)    x_hi(a,b,c,d);  x_lo(a,b,c,d)\n#else\n#define xor_256(a,b,c,d)    x_lo(a,b,c,d);  x_hi(a,b,c,d)\n#endif\n\n#if defined( UNROLL_LOOPS )\n\nvoid gf_mul_256(gf_t a, const gf_t256_t t, gf_t r)\n{   uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    xor_256(15, ap, t, r); xor_256(14, ap, t, r);\n    xor_256(13, ap, t, r); xor_256(12, ap, t, r);\n    xor_256(11, ap, t, r); xor_256(10, ap, t, r);\n    xor_256( 9, ap, t, r); xor_256( 8, ap, t, r);\n    xor_256( 7, ap, t, r); xor_256( 6, ap, t, r);\n    xor_256( 5, ap, t, r); xor_256( 4, ap, t, r);\n    xor_256( 3, ap, t, r); xor_256( 2, ap, t, r);\n    xor_256( 1, ap, t, r); xor_256( 0, ap, t, r);\n    copy_block_aligned(a, r);\n}\n\n#else\n\nvoid gf_mul_256(gf_t a, const gf_t256_t t, gf_t r)\n{   int i;\n    uint8_t *ap = (uint8_t*)a;\n    memset(r, 0, GF_BYTE_LEN);\n    for(i = 15; i >= 0; --i)\n    {\n        xor_256(i, ap, t, r);\n    }\n    copy_block_aligned(a, r);\n}\n\n#endif\n\n#endif\n#endif /* USE_GCM */\n"
  },
  {
    "path": "deps/cl345/crypt/gf128mul.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 11/01/2011\n\n I am grateful for the work done by Mark Rodenkirch and Jason Papadopoulos\n in helping to remove a bug in the operation of this code on big endian\n systems when fast buffer operations are enabled.\n ---------------------------------------------------------------------------\n\n An implementation of field multiplication in the Galois Field GF(2^128)\n\n A polynomial representation is used for the field with the coefficients\n held in bit sequences in which the bit numbers are the powers of x that\n a bit represents. The field polynomial used is (x^128+x^7+x^2+x+1).\n \n The obvious way of representing field elements in a computer system is \n to map 'x' in the field to the binary integer '2'. But this was way too\n obvious for cryptographers!\n \n Here bytes are numbered in their memory order and bits within bytes are\n numbered according to their integer numeric significance (that is as is \n now normal with bit 0 representing unity). The term 'little endian' \n will then used to describe mappings where numeric (power of 2) or field \n (power of x) significance increases with increasing bit or byte numbers \n with 'big endian' being used to describe the inverse situation.  \n\n The GF bit sequence can then be mapped onto 8-bit bytes in computer \n memory in one of four simple ways:\n\n     A mapping in which x maps to the integer 2 in little endian \n     form for both bytes and bits within bytes:\n     \n         LL: bit for x^n ==> bit for 2^(n % 8) in byte[n / 8]\n\n     A mapping in which x maps to the integer 2 in big endian form \n     for both bytes and bits within bytes:\n\n         BL: bit for x^n ==> bit for 2^(n % 8) in byte[15 - n / 8]\n \n     A little endian mapping for bytes but with the bits within \n     bytes in reverse order (big endian bytes):\n\n         LB: bit for x^n ==> bit for 2^(7 - n % 8) in byte[n / 8]\n\n     A big endian mapping for bytes but with the bits within \n     bytes in reverse order (big endian bytes):\n\n         BB: bit for x^n ==> bit for 2^(7 - n % 8) in byte[15 - n / 8]\n\n 128-bit field elements are represented by 16 byte buffers but for\n processing efficiency reasons it is often desirable to process arrays \n of bytes using longer types such as, for example, unsigned long values. \n The type used for representing these buffers will be called a 'gf_unit' \n and the buffer itself will be referred to as a 'gf_t' type.\n\n THe field multiplier is based on the assumption that one of the two\n field elements involved in multiplication will change only relatively\n infrequently, making it worthwhile to precompute tables to speed up\n multiplication by this value. \n*/\n\n#ifndef _GF128MUL_H\n#define _GF128MUL_H\n\n#include <stdlib.h>\n#include <string.h>\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"brg_endian.h\"\n#else\n  #include \"crypt/brg_endian.h\"\n#endif /* Compiler-specific includes */\n\n/* USER DEFINABLE OPTIONS */\n/*  UNIT_BITS sets the size of variables used to process 16 byte buffers\n    when the buffer alignment allows this.  When buffers are processed\n    in bytes, 16 individual operations are invoolved.  But if, say, such \n    a buffer is divided into 4 32 bit variables, it can then be processed \n    in 4 operations, making the code typically much faster. In general\n    it will pay to use the longest natively supported size, which will\n    probably be 32 or 64 bits in 32 and 64 bit systems respectively.\n*/\n\n#if defined( UNIT_BITS )\n# undef UNIT_BITS\n#endif\n\n#if !defined( UNIT_BITS )\n#  if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN\n#    if 0\n#      define UNIT_BITS   8\n#    elif 0\n#      define UNIT_BITS  32\n#    elif 1\n#      define UNIT_BITS  64\n#    endif\n#  elif defined( _WIN64 )\n#    define UNIT_BITS 64\n#  else\n#    define UNIT_BITS 32\n#  endif\n#endif\n\n#if UNIT_BITS == 64 && !defined( NEED_UINT_64T )\n#  define NEED_UINT_64T\n#endif\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"brg_types.h\"\n#else\n  #include \"crypt/brg_types.h\"\n#endif /* Compiler-specific includes */\n\n/* Choose the Galois Field representation to use (see above) */\n#if 0\n#  define GF_MODE_LL\n#elif 0\n#  define GF_MODE_BL\n#elif 1\n#  define GF_MODE_LB    /* the representation used by GCM */\n#elif 0\n#  define GF_MODE_BB\n#else\n#  error mode is not defined\n#endif\n\n/*  Table sizes for GF(128) Multiply.  Normally larger tables give \n    higher speed but cache loading might change this. Normally only \n    one table size (or none at all) will be specified here\n*/\n#if 0\n#  define TABLES_64K\n#endif\n#if 0\n#  define TABLES_8K\n#endif\n#if 1\n#  define TABLES_4K\n#endif\n#if 0\n#  define TABLES_256\n#endif\n\n/* END OF USER DEFINABLE OPTIONS */\n\n#if !(defined( TABLES_64K ) || defined( TABLES_8K ) \\\n    || defined( TABLES_4K ) || defined( TABLES_256 ))\n#  define NO_TABLES\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#define GF_BYTE_LEN 16\n#define GF_UNIT_LEN (GF_BYTE_LEN / (UNIT_BITS >> 3))\n\nUNIT_TYPEDEF(gf_unit_t, UNIT_BITS);\nBUFR_TYPEDEF(gf_t, UNIT_BITS, GF_BYTE_LEN);\n\n/*  Code for conversion between the four different galois field representations \n    is optionally available using gf_convert.c\n*/\n\ntypedef enum { REVERSE_NONE = 0, REVERSE_BITS = 1, REVERSE_BYTES = 2 } transform;\n\nvoid convert_representation(gf_t dest, const gf_t source, transform rev);\n\nvoid gf_mul(gf_t a, const gf_t b);      /* slow field multiply  */  \n\n/* types and calls for 64k table driven field multiplier        */\n\ntypedef gf_t    gf_t64k_a[16][256]; \ntypedef gf_t    (*gf_t64k_t)[256];\n\nvoid init_64k_table(const gf_t g, gf_t64k_t t);\nvoid gf_mul_64k(gf_t a, const gf_t64k_t t, void *r);\n\n/* types and calls for 8k table driven field multiplier        */\n\ntypedef gf_t    gf_t8k_a[32][16];\ntypedef gf_t    (*gf_t8k_t)[16];\n\nvoid init_8k_table(const gf_t g, gf_t8k_t t);\nvoid gf_mul_8k(gf_t a, const gf_t8k_t t, gf_t r);\n\n/* types and calls for 8k table driven field multiplier        */\n\ntypedef gf_t    gf_t4k_a[256];\ntypedef gf_t    (*gf_t4k_t);\n\nvoid init_4k_table(const gf_t g, gf_t4k_t t);\nvoid gf_mul_4k(gf_t a, const gf_t4k_t t, gf_t r);\n\n/* types and calls for 8k table driven field multiplier        */\n\ntypedef gf_t    gf_t256_a[16];\ntypedef gf_t    (*gf_t256_t);\n\nvoid init_256_table(const gf_t g, gf_t256_t t);\nvoid gf_mul_256(gf_t a, const gf_t256_t t, gf_t r);\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/gf_mul_lo.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2010, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 18/02/2014\n\n This file provides the low level primitives needed for Galois Field \n operations in GF(2^128) for the four most likely field representations.\n*/\n\n#ifndef _GF_MUL_LO_H\n#define _GF_MUL_LO_H\n\n#if defined( USE_INLINING )\n#  if defined( _MSC_VER )\n#    define gf_decl __inline\n#  elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )\n#    define gf_decl static inline\n#  else\n#    define gf_decl static\n#  endif\n#endif\n\n#if 0   /* used for testing only: t1(UNIT_BITS), t2(UNIT_BITS)  */\n#  define _t1(n) bswap ## n ## _block(x, x)\n#  define  t1(n) _t1(n)\n#  define _t2(n) bswap ## n ## _block(x, x); bswap ## n ## _block(r, r) \n#  define  t2(n) _t2(n)\n#endif\n\n#define gf_m(n,x)    gf_mulx ## n ## x\n#define gf_mulx1(x)  gf_m(1,x)\n#define gf_mulx4(x)  gf_m(4,x)\n#define gf_mulx8(x)  gf_m(8,x)\n\n#define MASK(x) ((x) * (UNIT_CAST(-1,UNIT_BITS) / 0xff))\n\n#define DATA_256(q) {\\\n    q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\\\n    q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\\\n    q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\\\n    q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\\\n    q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\\\n    q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\\\n    q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\\\n    q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\\\n    q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\\\n    q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\\\n    q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\\\n    q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\\\n    q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\\\n    q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\\\n    q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\\\n    q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\\\n    q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\\\n    q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\\\n    q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\\\n    q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\\\n    q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\\\n    q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\\\n    q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\\\n    q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\\\n    q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\\\n    q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\\\n    q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\\\n    q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\\\n    q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\\\n    q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\\\n    q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\\\n    q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) }\n\n/*  Within the 16 bytes of the field element the top and bottom field bits\n    are within bytes as follows (bit numbers in bytes 0 from ls up) for\n    each of the four field representations supported (see gf128mul.txt):\n\n    GF_BIT   127 126 125 124 123 122 121 120     .....  7 6 5 4 3 2 1 0\n                                                  0x87  1 0 0 0 0 1 1 1\n    BL x[ 0]   7   6   5   4   3   2   1   0     x[15]  7 6 5 4 3 2 1 0\n    LL x[15]   7   6   5   4   3   2   1   0     x[ 0]  7 6 5 4 3 2 1 0\n\n    GF_BIT   120 121 122 123 124 125 126 127     .....  0 1 2 3 4 5 6 7\n                                                  0xc1  1 1 1 0 0 0 0 1\n    BB x[ 0]   7   6   5   4   3   2   1   0     x[15]  7 6 5 4 3 2 1 0\n    LB x[15]   7   6   5   4   3   2   1   0     x[ 0]  7 6 5 4 3 2 1 0\n\n    When the field element is multiplied by x^n, the high bits overflow\n    and are used to form an overflow byte. For the BL and LL modes this\n    byte has the lowest overflow bit in bit 0 whereas for the BB and LB\n    modes this bit is in biit 7.  So we have for this byte:\n\n    bit (bit n = 2^n)    7   6   5   4   3   2   1   0\n    BL and LL          x^7 x^6 x^5 x^4 x^3 x^2 x^1 x^0  \n    BB and LB          x^0 x^1 x^2 x^3 x^4 x^5 x^6 x^7  \n    \n    This byte then has to be multiplied by the low bits of the field\n    polynomial, which produces a value of 16 bits to be xored into the \n    left shifted field value. For the BL and LL modes bit 0 gives the\n    word value 0x0087, bit 1 gives 0x010e (0x87 left shifted 1), 0x021c\n    (0x87 left shifted 2), ... For the BB and LB modes, bit 7 gives the\n    value 0x00e1, bit 6 gives 0x8070, bit 5 gives 0x4038, ... Each bit\n    in the overflow byte is expanded in this way and is xored into the\n    overall result, so eaach of the 256 byte values will produce a\n    corresponding word value that is computed by the gf_uint16_xor(i)\n    macros below.\n\n    These word values have to be xored into the low 16 bits of the \n    field value. If the byte endianess of the mode matches that of\n    the architecture xoring the word value will be correct. But if\n    the mode has the opposite endianess, the word value has to be\n    xored in byte reversed order. This is done by the ord() macro.\n*/\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN \\\n      && (defined( GF_MODE_LB ) || defined( GF_MODE_LL )) || \\\n    PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN \\\n      && (defined( GF_MODE_BB ) || defined( GF_MODE_BL ))\n#  define ord(hi, lo)   0x##hi##lo\n#else \n#  define ord(hi, lo)   0x##lo##hi\n#endif\n\n#if defined( GF_MODE_BL ) || defined( GF_MODE_LL )\n\n/* field and numeric bit significance correspond */\n\n#define gf_uint16_xor(i) ( \\\n    (i & 0x01 ? ord(00,87) : 0) ^ (i & 0x02 ? ord(01,0e) : 0) ^ \\\n    (i & 0x04 ? ord(02,1c) : 0) ^ (i & 0x08 ? ord(04,38) : 0) ^ \\\n    (i & 0x10 ? ord(08,70) : 0) ^ (i & 0x20 ? ord(10,e0) : 0) ^ \\\n    (i & 0x40 ? ord(21,c0) : 0) ^ (i & 0x80 ? ord(43,80) : 0) )\n\nenum x_bit \n{ \n    X_0 = 0x01, X_1 = 0x02, X_2 = 0x04, X_3 = 0x08, \n    X_4 = 0x10, X_5 = 0x20, X_6 = 0x40, X_7 = 0x80\n};\n\n#elif defined( GF_MODE_BB ) || defined( GF_MODE_LB )\n\n/* field and numeric bit significance are in reverse */\n\n#define gf_uint16_xor(i) ( \\\n    (i & 0x80 ? ord(00,e1) : 0) ^ (i & 0x40 ? ord(80,70) : 0) ^ \\\n    (i & 0x20 ? ord(40,38) : 0) ^ (i & 0x10 ? ord(20,1c) : 0) ^ \\\n    (i & 0x08 ? ord(10,0e) : 0) ^ (i & 0x04 ? ord(08,07) : 0) ^ \\\n    (i & 0x02 ? ord(84,03) : 0) ^ (i & 0x01 ? ord(c2,01) : 0) )\n\nenum x_bit \n{ \n    X_0 = 0x80, X_1 = 0x40, X_2 = 0x20, X_3 = 0x10, \n    X_4 = 0x08, X_5 = 0x04, X_6 = 0x02, X_7 = 0x01\n};\n\n#else\n#error Galois Field representation has not been set\n#endif\n\nconst uint16_t gf_tab[256] = DATA_256(gf_uint16_xor);\n\n/* LL Mode Galois Field operations \n\n  x[0]     x[1]     x[2]     x[3]     x[4]     x[5]     x[6]    x[7]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n10000111 ........ ........ ........ ........ ........ ........ ........\n07....00 15....08 23....16 31....24 39....32 47....40 55....48 63....56\n  x[8]    x[9]   x[10]   x[11]   x[12]   x[13]   x[14]  x[15]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n........ ........ ........ ........ ........ ........ ........ M.......\n71....64 79....72 87....80 95....88 103...96 111..104 119..112 127..120\n*/\n\n#if UNIT_BITS == 64\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_ll(n,r,x)   r[n] = (x[n] << 1) | (n ? x[n-1] >> 63 : 0)\n#define f4_ll(n,r,x)   r[n] = (x[n] << 4) | (n ? x[n-1] >> 60 : 0)\n#define f8_ll(n,r,x)   r[n] = (x[n] << 8) | (n ? x[n-1] >> 56 : 0)\n#else\n#define f1_ll(n,r,x)   r[n] = ((x[n] << 1) & ~MASK(0x01)) | (((x[n] >> 15) \\\n                            | (n ? x[n-1] << 49 : 0)) & MASK(0x01))\n#define f4_ll(n,r,x)   r[n] = ((x[n] << 4) & ~MASK(0x0f)) | (((x[n] >> 12) \\\n                            | (n ? x[n-1] << 52 : 0)) & MASK(0x0f))\n#define f8_ll(n,r,x)   r[n] = (x[n] >> 8) | (n ? x[n-1] << 56 : 0)\n#endif\n\ngf_decl void gf_mulx1_ll(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[1] >> 63) & 0x01];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[1] >> 7) & 0x01])) << 48;\n#endif\n    rep2_d2(f1_ll, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx4_ll(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[1] >> 60) & 0x0f];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[1] >> 4) & 0x0f])) << 48;\n#endif\n    rep2_d2(f4_ll, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx8_ll(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[UNIT_PTR(x)[1] >> 56];\n#else\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[1] & 0xff])) << 48;\n#endif\n    rep2_d2(f8_ll, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\n#elif UNIT_BITS == 32\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_ll(n,r,x)   r[n] = (x[n] << 1) | (n ? x[n-1] >> 31 : 0)\n#define f4_ll(n,r,x)   r[n] = (x[n] << 4) | (n ? x[n-1] >> 28 : 0)\n#define f8_ll(n,r,x)   r[n] = (x[n] << 8) | (n ? x[n-1] >> 24 : 0)\n#else\n#define f1_ll(n,r,x)   r[n] = ((x[n] << 1) & ~MASK(0x01)) | (((x[n] >> 15) \\\n                            | (n ? x[n-1] << 17 : 0)) & MASK(0x01))\n#define f4_ll(n,r,x)   r[n] = ((x[n] << 4) & ~MASK(0x0f)) | (((x[n] >> 12) \\\n                            | (n ? x[n-1] << 20 : 0)) & MASK(0x0f))\n#define f8_ll(n,r,x)   r[n] = (x[n] >> 8) | (n ? x[n-1] << 24 : 0)\n#endif\n\ngf_decl void gf_mulx1_ll(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[3] >> 31) & 0x01];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[3] >> 7) & 0x01])) << 16;\n#endif\n    rep2_d4(f1_ll, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx4_ll(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[3] >> 28) & 0x0f];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[3] >> 4) & 0x0f])) << 16;\n#endif\n    rep2_d4(f4_ll, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx8_ll(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[UNIT_PTR(x)[3] >> 24];\n#else\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[3] & 0xff])) << 16;\n#endif\n    rep2_d4(f8_ll, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\n#else\n\n#define f1_ll(n,r,x)   r[n] = (x[n] << 1) | (n ? x[n-1] >> 7 : 0)\n#define f4_ll(n,r,x)   r[n] = (x[n] << 4) | (n ? x[n-1] >> 4 : 0)\n\ngf_decl void gf_mulx1_ll(gf_t r, const gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[15] >> 7) & 0x01];\n    rep2_d16(f1_ll, UNIT_PTR(r), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(r)[0] ^= _tt & 0xff;\n#else\n    UNIT_PTR(r)[0] ^= _tt >> 8;\n#endif\n}\n\ngf_decl void gf_mulx4_ll(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[15] >> 4) & 0x0f];\n    rep2_d16(f4_ll, UNIT_PTR(x), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[1] ^= _tt >> 8;\n    UNIT_PTR(x)[0] ^= _tt & 0xff;\n#else\n    UNIT_PTR(x)[1] ^= _tt & 0xff;\n    UNIT_PTR(x)[0] =  _tt >> 8;\n#endif\n}\n\ngf_decl void gf_mulx8_ll(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[UNIT_PTR(x)[15]];\n    memmove(UNIT_PTR(x) + 1, UNIT_PTR(x), 15);\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[1] ^= _tt >> 8;\n    UNIT_PTR(x)[0] =  _tt & 0xff;\n#else\n    UNIT_PTR(x)[1] ^= _tt & 0xff;\n    UNIT_PTR(x)[0] =  _tt >> 8;\n#endif\n}\n\n#endif\n\n/* BL Mode Galois Field operations \n\n  x[0]     x[1]     x[2]     x[3]     x[4]     x[5]     x[6]     x[7]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\nM....... ........ ........ ........ ........ ........ ........ ........\n127..120 119..112 111..104 103...96 95....88 87....80 79....72 71....64\n  x[8]     x[9]    x[10]    x[11]    x[12]    x[13]    x[14]    x[15]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n........ ........ ........ ........ ........ ........ ........ 10000111\n63....56 55....48 47....40 39....32 31....24 23....16 15....08 07....00\n*/\n\n#if UNIT_BITS == 64\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_bl(n,r,x)   r[n] = ((x[n] << 1) & ~MASK(0x01)) | (((x[n] >> 15) \\\n                            | (!n ? x[n+1] << 49 : 0)) & MASK(0x01))\n#define f4_bl(n,r,x)   r[n] = ((x[n] << 4) & ~MASK(0x0f)) | (((x[n] >> 12) \\\n                            | (!n ? x[n+1] << 52 : 0)) & MASK(0x0f))\n#define f8_bl(n,r,x)   r[n] = (x[n] >> 8) | (!n ? x[n+1] << 56 : 0)\n#else\n#define f1_bl(n,r,x)   r[n] = (x[n] << 1) | (!n ? x[n+1] >> 63 : 0)\n#define f4_bl(n,r,x)   r[n] = (x[n] << 4) | (!n ? x[n+1] >> 60 : 0)\n#define f8_bl(n,r,x)   r[n] = (x[n] << 8) | (!n ? x[n+1] >> 56 : 0)\n#endif\n\ngf_decl void gf_mulx1_bl(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] >> 7) & 0x01])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 63) & 0x01];\n#endif\n    rep2_u2(f1_bl, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[1] ^= _tt;\n}\n\ngf_decl void gf_mulx4_bl(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] >> 4) & 0x0f])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 60) & 0x0f];\n#endif\n    rep2_u2(f4_bl, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[1] ^= _tt;\n}\n\ngf_decl void gf_mulx8_bl(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[0] & 0xff])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 56) & 0xff];\n#endif\n    rep2_u2(f8_bl, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[1] ^= _tt;\n}\n\n#elif UNIT_BITS == 32\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_bl(n,r,x)   r[n] = ((x[n] << 1) & ~MASK(0x01)) | (((x[n] >> 15) \\\n                            | (n < 3 ? x[n+1] << 17 : 0)) & MASK(0x01))\n#define f4_bl(n,r,x)   r[n] = ((x[n] << 4) & ~MASK(0x0f)) | (((x[n] >> 12) \\\n                            | (n < 3 ? x[n+1] << 20 : 0)) & MASK(0x0f))\n#define f8_bl(n,r,x)   r[n] = (x[n] >> 8) | (n < 3 ? x[n+1] << 24 : 0)\n#else\n#define f1_bl(n,r,x)   r[n] = (x[n] << 1) | (n < 3 ? x[n+1] >> 31 : 0)\n#define f4_bl(n,r,x)   r[n] = (x[n] << 4) | (n < 3 ? x[n+1] >> 28 : 0)\n#define f8_bl(n,r,x)   r[n] = (x[n] << 8) | (n < 3 ? x[n+1] >> 24 : 0)\n#endif\n\ngf_decl void gf_mulx1_bl(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] >> 7) & 0x01])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 31) & 0x01];\n#endif\n    rep2_u4(f1_bl, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[3] ^= _tt;\n}\n\ngf_decl void gf_mulx4_bl(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] >> 4) & 0x0f])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 28) & 0x0f];\n#endif\n    rep2_u4(f4_bl, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[3] ^= _tt;\n}\n\ngf_decl void gf_mulx8_bl(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[0] & 0xff])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 24) & 0xff];\n#endif\n    rep2_u4(f8_bl, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[3] ^= _tt;\n}\n\n#else\n\n#define f1_bl(n,r,x)   r[n] = (x[n] << 1) | (n < 15 ? x[n+1] >> 7 : 0)\n#define f4_bl(n,r,x)   r[n] = (x[n] << 4) | (n < 15 ? x[n+1] >> 4 : 0)\n\ngf_decl void gf_mulx1_bl(gf_t r, const gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[0] >> 7) & 0x01];\n    rep2_u16(f1_bl, UNIT_PTR(r), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(r)[15] ^= _tt >> 8;\n#else\n    UNIT_PTR(r)[15] ^= _tt & 0xff;\n#endif\n}\n\ngf_decl void gf_mulx4_bl(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[0] >> 4) & 0x0f];\n    rep2_u16(f4_bl, UNIT_PTR(x), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[14] ^= _tt & 0xff;\n    UNIT_PTR(x)[15] ^= _tt >> 8;\n#else\n    UNIT_PTR(x)[14] ^= _tt >> 8;\n    UNIT_PTR(x)[15] = _tt & 0xff;\n#endif\n}\n\ngf_decl void gf_mulx8_bl(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[UNIT_PTR(x)[0]];\n    memmove(UNIT_PTR(x), UNIT_PTR(x) + 1, 15);\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[14] ^= _tt & 0xff;\n    UNIT_PTR(x)[15]  = _tt >> 8;\n#else\n    UNIT_PTR(x)[14] ^= _tt >> 8;\n    UNIT_PTR(x)[15]  = _tt & 0xff;\n#endif\n}\n\n#endif\n\n/* LB Mode Galois Field operations \n\n   x[0]    x[1]     x[2]     x[3]     x[4]     x[5]     x[6]     x[7]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n11100001 ........ ........ ........ ........ ........ ........ ........\n00....07 08....15 16....23 24....31 32....39 40....47 48....55 56....63\n   x[8]    x[9]    x[10]    x[11]    x[12]    x[13]    x[14]    x[15]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n........ ........ ........ ........ ........ ........ ........ .......M\n64....71 72....79 80....87 88....95 96...103 104..111 112..119 120..127\n*/\n\n#if UNIT_BITS == 64\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_lb(n,r,x)   r[n] = ((x[n] >> 1) & ~MASK(0x80)) | (((x[n] << 15) \\\n                            | (n ? x[n-1] >> 49 : 0)) & MASK(0x80))\n#define f4_lb(n,r,x)   r[n] = ((x[n] >> 4) & ~MASK(0xf0)) | (((x[n] << 12) \\\n                            | (n ? x[n-1] >> 52 : 0)) & MASK(0xf0))\n#define f8_lb(n,r,x)   r[n] = (x[n] << 8) | (n ? x[n-1] >> 56 : 0)\n#else\n#define f1_lb(n,r,x)   r[n] = (x[n] >> 1) | (n ? x[n-1] << 63 : 0)\n#define f4_lb(n,r,x)   r[n] = (x[n] >> 4) | (n ? x[n-1] << 60 : 0)\n#define f8_lb(n,r,x)   x[n] = (x[n] >> 8) | (n ? x[n-1] << 56 : 0)\n#endif\n\ngf_decl void gf_mulx1_lb(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[1] >> 49) & MASK(0x80)];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[1] << 7) & 0xff])) << 48;\n#endif\n    rep2_d2(f1_lb, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx4_lb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[1] >> 52) & MASK(0xf0)];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[1] << 4) & 0xff])) << 48;\n#endif\n    rep2_d2(f4_lb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx8_lb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[UNIT_PTR(x)[1] >> 56];\n#else\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[1] & 0xff])) << 48;\n#endif\n    rep2_d2(f8_lb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\n#elif UNIT_BITS == 32\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_lb(n,r,x)   r[n] = ((x[n] >> 1) & ~MASK(0x80)) | (((x[n] << 15) \\\n                            | (n ? x[n-1] >> 17 : 0)) & MASK(0x80))\n#define f4_lb(n,r,x)   r[n] = ((x[n] >> 4) & ~MASK(0xf0)) | (((x[n] << 12) \\\n                            | (n ? x[n-1] >> 20 : 0)) & MASK(0xf0))\n#define f8_lb(n,r,x)   r[n] = (x[n] << 8) | (n ? x[n-1] >> 24 : 0)\n#else\n#define f1_lb(n,r,x)   r[n] = (x[n] >> 1) | (n ? x[n-1] << 31 : 0)\n#define f4_lb(n,r,x)   r[n] = (x[n] >> 4) | (n ? x[n-1] << 28 : 0)\n#define f8_lb(n,r,x)   r[n] = (x[n] >> 8) | (n ? x[n-1] << 24 : 0)\n#endif\n\ngf_decl void gf_mulx1_lb(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[3] >> 17) & MASK(0x80)];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[3] << 7) & 0xff])) << 16;\n#endif\n    rep2_d4(f1_lb, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx4_lb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[(UNIT_PTR(x)[3] >> 20) & MASK(0xf0)];\n#else\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[3] << 4) & 0xff])) << 16;\n#endif\n    rep2_d4(f4_lb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\ngf_decl void gf_mulx8_lb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = gf_tab[UNIT_PTR(x)[3] >> 24];\n#else\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[3] & 0xff])) << 16;\n#endif\n    rep2_d4(f8_lb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[0] ^= _tt;\n}\n\n#else\n\n#define f1_lb(n,r,x)   r[n] = (x[n] >> 1) | (n ? x[n-1] << 7 : 0)\n#define f4_lb(n,r,x)   r[n] = (x[n] >> 4) | (n ? x[n-1] << 4 : 0)\n\ngf_decl void gf_mulx1_lb(gf_t r, const gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[15] << 7) & 0x80];\n    rep2_d16(f1_lb, UNIT_PTR(r), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(r)[0] ^= _tt;\n#else\n    UNIT_PTR(r)[0] ^= _tt >> 8;\n#endif\n}\n\ngf_decl void gf_mulx4_lb(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[15] << 4) & 0xf0];\n    rep2_d16(f4_lb, UNIT_PTR(x), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[1] ^= _tt >> 8;\n    UNIT_PTR(x)[0] ^= _tt & 0xff;\n#else\n    UNIT_PTR(x)[1] ^= _tt & 0xff;\n    UNIT_PTR(x)[0] ^= _tt >> 8;\n#endif\n}\n\ngf_decl void gf_mulx8_lb(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[UNIT_PTR(x)[15]];\n    memmove(UNIT_PTR(x) + 1, UNIT_PTR(x), 15);\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[1] ^= _tt >> 8;\n    UNIT_PTR(x)[0] = _tt & 0xff;\n#else\n    UNIT_PTR(x)[1] ^= _tt & 0xff;\n    UNIT_PTR(x)[0] = _tt >> 8;\n#endif\n}\n\n#endif\n\n/* BB Mode Galois Field operations \n\n  x[0]     x[1]     x[2]     x[3]     x[4]     x[5]     x[6]     x[7]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n.......M ........ ........ ........ ........ ........ ........ ........\n120..127 112..119 104..111 96...103 88....95 80....87 72....79 64....71\n  x[8]     x[9]     x[10]    x[11]    x[12]    x[13]    x[14]   x[15]\nms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls ms    ls\n........ ........ ........ ........ ........ ........ ........ 11100001\n56....63 48....55 40....47 32....39 24....31 16....23 08....15 00....07\n*/\n\n#if UNIT_BITS == 64\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_bb(n,r,x)   r[n] = (x[n] >> 1) | (!n ? x[n+1] << 63 : 0)\n#define f4_bb(n,r,x)   r[n] = (x[n] >> 4) | (!n ? x[n+1] << 60 : 0)\n#define f8_bb(n,r,x)   r[n] = (x[n] >> 8) | (!n ? x[n+1] << 56 : 0)\n#else\n#define f1_bb(n,r,x)   r[n] = ((x[n] >> 1) & ~MASK(0x80)) | (((x[n] << 15) \\\n                            | (!n ? x[n+1] >> 49 : 0)) & MASK(0x80))\n#define f4_bb(n,r,x)   r[n] = ((x[n] >> 4) & ~MASK(0xf0)) | (((x[n] << 12) \\\n                            | (!n ? x[n+1] >> 52 : 0)) & MASK(0xf0))\n#define f8_bb(n,r,x)   r[n] = (x[n] << 8) | (!n ? x[n+1] >> 56 : 0)\n#endif\n\ngf_decl void gf_mulx1_bb(gf_t r, const gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = (( gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] << 7) & 0x80])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 49) & 0x80];\n#endif\n    rep2_u2(f1_bb, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[1] ^= _tt;\n}\n\ngf_decl void gf_mulx4_bb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] << 4) & 0xf0])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 52) & 0xf0];\n#endif\n    rep2_u2(f4_bb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[1] ^= _tt;\n}\n\ngf_decl void gf_mulx8_bb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[0] & 0xff])) << 48;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 56) & 0xff];\n#endif\n    rep2_u2(f8_bb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[1] ^= _tt;\n}\n\n#elif UNIT_BITS == 32\n\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n#define f1_bb(n,r,x)   r[n] = (x[n] >> 1) | (n < 3 ? x[n+1] << 31 : 0)\n#define f4_bb(n,r,x)   r[n] = (x[n] >> 4) | (n < 3 ? x[n+1] << 28 : 0)\n#define f8_bb(n,r,x)   r[n] = (x[n] >> 8) | (n < 3 ? x[n+1] << 24 : 0)\n#else\n#define f1_bb(n,r,x)   r[n] = ((x[n] >> 1) & ~MASK(0x80)) | (((x[n] << 15) \\\n                            | (n < 3 ? x[n+1] >> 17 : 0)) & MASK(0x80))\n#define f4_bb(n,r,x)   r[n] = ((x[n] >> 4) & ~MASK(0xf0)) | (((x[n] << 12) \\\n                            | (n < 3 ? x[n+1] >> 20 : 0)) & MASK(0xf0))\n#define f8_bb(n,r,x)   r[n] = (x[n] << 8) | (n < 3 ? x[n+1] >> 24 : 0)\n#endif\n\ngf_decl void gf_mulx1_bb(gf_t r, const gf_t x)\n{   gf_unit_t _tt; \n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] << 7) & 0x80])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 17) & 0x80];\n#endif\n    rep2_u4(f1_bb, UNIT_PTR(r), UNIT_PTR(x));\n    UNIT_PTR(r)[3] ^= _tt;\n}\n\ngf_decl void gf_mulx4_bb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[(UNIT_PTR(x)[0] << 4) & 0xf0])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 20) & 0xf0];\n#endif\n    rep2_u4(f4_bb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[3] ^= _tt;\n}\n\ngf_decl void gf_mulx8_bb(gf_t x)\n{   gf_unit_t _tt;\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    _tt = ((gf_unit_t)(gf_tab[UNIT_PTR(x)[0] & 0xff])) << 16;\n#else\n    _tt = gf_tab[(UNIT_PTR(x)[0] >> 24) & 0xff];\n#endif\n    rep2_u4(f8_bb, UNIT_PTR(x), UNIT_PTR(x));\n    UNIT_PTR(x)[3] ^= _tt;\n}\n\n#else\n\n#define f1_bb(n,r,x)   r[n] = (x[n] >> 1) | (n < 15 ? x[n+1] << 7 : 0)\n#define f4_bb(n,r,x)   r[n] = (x[n] >> 4) | (n < 15 ? x[n+1] << 4 : 0)\n\ngf_decl void gf_mulx1_bb(gf_t r, const gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[0] << 7) & 0x80];\n    rep2_u16(f1_bb, UNIT_PTR(r), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(r)[15] ^= _tt >> 8;\n#else\n    UNIT_PTR(r)[15] ^= _tt;\n#endif\n}\n\ngf_decl void gf_mulx4_bb(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[(UNIT_PTR(x)[0] << 4) & 0xf0];\n    rep2_u16(f4_bb, UNIT_PTR(x), UNIT_PTR(x));\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[14] ^= _tt & 0xff;\n    UNIT_PTR(x)[15] ^= _tt >> 8;\n#else\n    UNIT_PTR(x)[14] ^= _tt >> 8;\n    UNIT_PTR(x)[15] ^= _tt & 0xff;\n#endif\n}\n\ngf_decl void gf_mulx8_bb(gf_t x)\n{   uint16_t _tt;\n\t_tt = gf_tab[UNIT_PTR(x)[0]];\n    memmove(UNIT_PTR(x), UNIT_PTR(x) + 1, 15);\n#if PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN\n    UNIT_PTR(x)[14] ^= _tt & 0xff;\n    UNIT_PTR(x)[15] = _tt >> 8;\n#else\n    UNIT_PTR(x)[14] ^= _tt >> 8;\n    UNIT_PTR(x)[15] = _tt & 0xff;\n#endif\n}\n\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/icbc.c",
    "content": "/* crypto/idea/i_cbc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"idea.h\"\n  #include \"idealocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/idea.h\"\n  #include \"crypt/idealocl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_IDEA\n\nvoid idea_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t     IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int encrypt)\n\t{\n\tregister unsigned long tin0,tin1;\n\tregister unsigned long tout0,tout1,xor0,xor1;\n\tregister long l=length;\n\tunsigned long tin[2];\n\n\tif (encrypt)\n\t\t{\n\t\tn2l(iv,tout0);\n\t\tn2l(iv,tout1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tn2l(in,tin0);\n\t\t\tn2l(in,tin1);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tidea_encrypt(tin,ks);\n\t\t\ttout0=tin[0]; l2n(tout0,out);\n\t\t\ttout1=tin[1]; l2n(tout1,out);\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tn2ln(in,tin0,tin1,l+8);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tidea_encrypt(tin,ks);\n\t\t\ttout0=tin[0]; l2n(tout0,out);\n\t\t\ttout1=tin[1]; l2n(tout1,out);\n\t\t\t}\n\t\tl2n(tout0,iv);\n\t\tl2n(tout1,iv);\n\t\t}\n\telse\n\t\t{\n\t\tn2l(iv,xor0);\n\t\tn2l(iv,xor1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tn2l(in,tin0); tin[0]=tin0;\n\t\t\tn2l(in,tin1); tin[1]=tin1;\n\t\t\tidea_encrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2n(tout0,out);\n\t\t\tl2n(tout1,out);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tn2l(in,tin0); tin[0]=tin0;\n\t\t\tn2l(in,tin1); tin[1]=tin1;\n\t\t\tidea_encrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2nn(tout0,tout1,out,l+8);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tl2n(xor0,iv);\n\t\tl2n(xor1,iv);\n\t\t}\n\ttin0=tin1=tout0=tout1=xor0=xor1=0;\n\ttin[0]=tin[1]=0;\n\t}\n\nvoid idea_encrypt(unsigned long *d, IDEA_KEY_SCHEDULE *key)\n\t{\n\tregister IDEA_INT *p;\n\tregister unsigned long x1,x2,x3,x4,t0,t1,ul;\n\n\tx2=d[0];\n\tx1=(x2>>16);\n\tx4=d[1];\n\tx3=(x4>>16);\n\n\tp= &(key->data[0][0]);\n\n\tE_IDEA(0);\n\tE_IDEA(1);\n\tE_IDEA(2);\n\tE_IDEA(3);\n\tE_IDEA(4);\n\tE_IDEA(5);\n\tE_IDEA(6);\n\tE_IDEA(7);\n\n\tx1&=0xffff;\n\tidea_mul(x1,x1,*p,ul); p++;\n\n\tt0= x3+ *(p++);\n\tt1= x2+ *(p++);\n\n\tx4&=0xffff;\n\tidea_mul(x4,x4,*p,ul);\n\n\td[0]=(t0&0xffff)|((x1&0xffff)<<16);\n\td[1]=(x4&0xffff)|((t1&0xffff)<<16);\n\t}\n#endif /* USE_IDEA */\n"
  },
  {
    "path": "deps/cl345/crypt/idea.h",
    "content": "/* crypto/idea/idea.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_IDEA_H\n#define HEADER_IDEA_H\n\n#define IDEA_ENCRYPT\t1\n#define IDEA_DECRYPT\t0\n\n#define IDEA_BLOCK\t8\n#define IDEA_KEY_LENGTH\t16\n#define IDEA_INT unsigned int\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct idea_key_st\n\t{\n\tIDEA_INT data[9][6];\n\t} IDEA_KEY_SCHEDULE;\n\nconst char *idea_options(void);\nvoid idea_ecb_encrypt(const unsigned char *in, unsigned char *out,\n\tIDEA_KEY_SCHEDULE *ks);\nvoid idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks);\nvoid idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk);\nvoid idea_cbc_encrypt(const unsigned char *in, unsigned char *out,\n\tlong length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,int enc);\nvoid idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,\n\tlong length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv,\n\tint *num,int enc);\nvoid idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,\n\tlong length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num);\nvoid idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks);\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/idealocl.h",
    "content": "/* crypto/idea/idea_lcl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n/* The new form of this macro (check if the a*b == 0) was suggested by \n * Colin Plumb <colin@nyx10.cs.du.edu> */\n/* Removal of the inner if from from Wei Dai 24/4/96 */\n#define idea_mul(r,a,b,ul) \\\nul=(unsigned long)a*b; \\\nif (ul != 0) \\\n\t{ \\\n\tr=(ul&0xffff)-(ul>>16); \\\n\tr-=((r)>>16); \\\n\t} \\\nelse \\\n\tr=(-(int)a-b+1); /* assuming a or b is 0 and in range */ \n\n/* Removed spurious trailing '\\' in previous line and non-used macro \n   here - pcg */\n\n/*  7/12/95 - Many thanks to Rhys Weatherley <rweather@us.oracle.com>\n * for pointing out that I was assuming little endian\n * byte order for all quantities what idea\n * actually used bigendian.  No where in the spec does it mention\n * this, it is all in terms of 16 bit numbers and even the example\n * does not use byte streams for the input example :-(.\n * If you byte swap each pair of input, keys and iv, the functions\n * would produce the output as the old version :-(.\n */\n\n/* NOTE - c is not incremented as per n2l */\n#define n2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per l2n */\n#define l2nn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef n2l\n#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \\\n                         l|=((unsigned long)(*((c)++)))<<16L, \\\n                         l|=((unsigned long)(*((c)++)))<< 8L, \\\n                         l|=((unsigned long)(*((c)++))))\n\n#undef l2n\n#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)     )&0xff))\n\n#undef s2n\n#define s2n(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff))\n\n#undef n2s\n#define n2s(c,l)\t(l =((IDEA_INT)(*((c)++)))<< 8L, \\\n\t\t\t l|=((IDEA_INT)(*((c)++)))      )\n\n#ifdef undef\n/* NOTE - c is not incremented as per c2l */\n#define c2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))<<24; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))));     \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))<<24; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))));     \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per l2c */\n#define l2cn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)    )&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)    )&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef c2s\n#define c2s(c,l)\t(l =((unsigned long)(*((c)++)))    , \\\n\t\t\t l|=((unsigned long)(*((c)++)))<< 8L)\n\n#undef s2c\n#define s2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff))\n\n#undef c2l\n#define c2l(c,l)\t(l =((unsigned long)(*((c)++)))     , \\\n\t\t\t l|=((unsigned long)(*((c)++)))<< 8L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<16L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<24L)\n\n#undef l2c\n#define l2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24L)&0xff))\n#endif\n\n#define E_IDEA(num) \\\n\tx1&=0xffff; \\\n\tidea_mul(x1,x1,*p,ul); p++; \\\n\tx2+= *(p++); \\\n\tx3+= *(p++); \\\n\tx4&=0xffff; \\\n\tidea_mul(x4,x4,*p,ul); p++; \\\n\tt0=(x1^x3)&0xffff; \\\n\tidea_mul(t0,t0,*p,ul); p++; \\\n\tt1=(t0+(x2^x4))&0xffff; \\\n\tidea_mul(t1,t1,*p,ul); p++; \\\n\tt0+=t1; \\\n\tx1^=t1; \\\n\tx4^=t0; \\\n\tul=x2^t0; /* do the swap to x3 */ \\\n\tx2=x3^t1; \\\n\tx3=ul;\n\n"
  },
  {
    "path": "deps/cl345/crypt/iecb.c",
    "content": "/* crypto/idea/i_ecb.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"idea.h\"\n  #include \"idealocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/idea.h\"\n  #include \"crypt/idealocl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_IDEA\n\n#if 0\t/* pcg */\n\nconst char *idea_options(void)\n\t{\n\tif (sizeof(short) != sizeof(IDEA_INT))\n\t\treturn(\"idea(int)\");\n\telse\n\t\treturn(\"idea(short)\");\n\t}\n#endif /* 0 */\n\nvoid idea_ecb_encrypt(const unsigned char *in, unsigned char *out,\n\t     IDEA_KEY_SCHEDULE *ks)\n\t{\n\tunsigned long l0,l1,d[2];\n\n\tn2l(in,l0); d[0]=l0;\n\tn2l(in,l1); d[1]=l1;\n\tidea_encrypt(d,ks);\n\tl0=d[0]; l2n(l0,out);\n\tl1=d[1]; l2n(l1,out);\n\tl0=l1=d[0]=d[1]=0;\n\t}\n#endif /* USE_IDEA */\n"
  },
  {
    "path": "deps/cl345/crypt/iskey.c",
    "content": "/* crypto/idea/i_skey.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"idea.h\"\n  #include \"idealocl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/idea.h\"\n  #include \"crypt/idealocl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_IDEA\n\nstatic IDEA_INT inverse(unsigned int xin);\nvoid idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)\n\t{\n\tint i;\n\tregister IDEA_INT *kt,*kf,r0,r1,r2;\n\n\tkt= &(ks->data[0][0]);\n\tn2s(key,kt[0]); n2s(key,kt[1]); n2s(key,kt[2]); n2s(key,kt[3]);\n\tn2s(key,kt[4]); n2s(key,kt[5]); n2s(key,kt[6]); n2s(key,kt[7]);\n\n\tkf=kt;\n\tkt+=8;\n\tfor (i=0; i<6; i++)\n\t\t{\n\t\tr2= kf[1];\n\t\tr1= kf[2];\n\t\t*(kt++)= ((r2<<9) | (r1>>7))&0xffff;\n\t\tr0= kf[3];\n\t\t*(kt++)= ((r1<<9) | (r0>>7))&0xffff;\n\t\tr1= kf[4];\n\t\t*(kt++)= ((r0<<9) | (r1>>7))&0xffff;\n\t\tr0= kf[5];\n\t\t*(kt++)= ((r1<<9) | (r0>>7))&0xffff;\n\t\tr1= kf[6];\n\t\t*(kt++)= ((r0<<9) | (r1>>7))&0xffff;\n\t\tr0= kf[7];\n\t\t*(kt++)= ((r1<<9) | (r0>>7))&0xffff;\n\t\tr1= kf[0];\n\t\tif (i >= 5) break;\n\t\t*(kt++)= ((r0<<9) | (r1>>7))&0xffff;\n\t\t*(kt++)= ((r1<<9) | (r2>>7))&0xffff;\n\t\tkf+=8;\n\t\t}\n\t}\n\nvoid idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)\n\t{\n\tint r;\n\tregister IDEA_INT *fp,*tp,t;\n\n\ttp= &(dk->data[0][0]);\n\tfp= &(ek->data[8][0]);\n\tfor (r=0; r<9; r++)\n\t\t{\n\t\t*(tp++)=inverse(fp[0]);\n\t\t*(tp++)=((int)(0x10000L-fp[2])&0xffff);\n\t\t*(tp++)=((int)(0x10000L-fp[1])&0xffff);\n\t\t*(tp++)=inverse(fp[3]);\n\t\tif (r == 8) break;\n\t\tfp-=6;\n\t\t*(tp++)=fp[4];\n\t\t*(tp++)=fp[5];\n\t\t}\n\n\ttp= &(dk->data[0][0]);\n\tt=tp[1];\n\ttp[1]=tp[2];\n\ttp[2]=t;\n\n\tt=tp[49];\n\ttp[49]=tp[50];\n\ttp[50]=t;\n\t}\n\n/* taken directly from the 'paper' I'll have a look at it later */\nstatic IDEA_INT inverse(unsigned int xin)\n\t{\n\tlong n1,n2,q,r,b1,b2,t;\n\n\tif (xin == 0)\n\t\tb2=0;\n\telse\n\t\t{\n\t\tn1=0x10001;\n\t\tn2=xin;\n\t\tb2=1;\n\t\tb1=0;\n\n\t\tdo\t{\n\t\t\tr=(n1%n2);\n\t\t\tq=(n1-r)/n2;\n\t\t\tif (r == 0)\n\t\t\t\t{ if (b2 < 0) b2=0x10001+b2; }\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tn1=n2;\n\t\t\t\tn2=r;\n\t\t\t\tt=b2;\n\t\t\t\tb2=b1-q*b2;\n\t\t\t\tb1=t;\n\t\t\t\t}\n\t\t\t} while (r != 0);\n\t\t}\n\treturn((IDEA_INT)b2);\n\t}\n#endif /* USE_IDEA */\n"
  },
  {
    "path": "deps/cl345/crypt/md32com.h",
    "content": "/* crypto/md32_common.h */\n/* ====================================================================\n * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in\n *    the documentation and/or other materials provided with the\n *    distribution.\n *\n * 3. All advertising materials mentioning features or use of this\n *    software must display the following acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)\"\n *\n * 4. The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to\n *    endorse or promote products derived from this software without\n *    prior written permission. For written permission, please contact\n *    licensing@OpenSSL.org.\n *\n * 5. Products derived from this software may not be called \"OpenSSL\"\n *    nor may \"OpenSSL\" appear in their names without prior written\n *    permission of the OpenSSL Project.\n *\n * 6. Redistributions of any form whatsoever must retain the following\n *    acknowledgment:\n *    \"This product includes software developed by the OpenSSL Project\n *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)\"\n *\n * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY\n * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR\n * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n * ====================================================================\n *\n * This product includes cryptographic software written by Eric Young\n * (eay@cryptsoft.com).  This product includes software written by Tim\n * Hudson (tjh@cryptsoft.com).\n *\n */\n\n/*\n * This is a generic 32 bit \"collector\" for message digest algorithms.\n * Whenever needed it collects input character stream into chunks of\n * 32 bit values and invokes a block function that performs actual hash\n * calculations.\n *\n * Porting guide.\n *\n * Obligatory macros:\n *\n * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN\n *\tthis macro defines byte order of input stream.\n * HASH_CBLOCK\n *\tsize of a unit chunk HASH_BLOCK operates on.\n * HASH_LONG\n *\thas to be at lest 32 bit wide, if it's wider, then\n *\tHASH_LONG_LOG2 *has to* be defined along\n * HASH_CTX\n *\tcontext structure that at least contains following\n *\tmembers:\n *\t\ttypedef struct {\n *\t\t\t...\n *\t\t\tHASH_LONG\tNl,Nh;\n *\t\t\tHASH_LONG\tdata[HASH_LBLOCK];\n *\t\t\tint\t\tnum;\n *\t\t\t...\n *\t\t\t} HASH_CTX;\n * HASH_UPDATE\n *\tname of \"Update\" function, implemented here.\n * HASH_TRANSFORM\n *\tname of \"Transform\" function, implemented here.\n * HASH_FINAL\n *\tname of \"Final\" function, implemented here.\n * HASH_BLOCK_HOST_ORDER\n *\tname of \"block\" function treating *aligned* input message\n *\tin host byte order, implemented externally.\n * HASH_BLOCK_DATA_ORDER\n *\tname of \"block\" function treating *unaligned* input message\n *\tin original (data) byte order, implemented externally (it\n *\tactually is optional if data and host are of the same\n *\t\"endianess\").\n * HASH_MAKE_STRING\n *\tmacro convering context variables to an ASCII hash string.\n *\n * Optional macros:\n *\n * B_ENDIAN or L_ENDIAN\n *\tdefines host byte-order.\n * HASH_LONG_LOG2\n *\tdefaults to 2 if not states otherwise.\n * HASH_LBLOCK\n *\tassumed to be HASH_CBLOCK/4 if not stated otherwise.\n * HASH_BLOCK_DATA_ORDER_ALIGNED\n *\talternative \"block\" function capable of treating\n *\taligned input message in original (data) order,\n *\timplemented externally.\n *\n * MD5 example:\n *\n *\t#define DATA_ORDER_IS_LITTLE_ENDIAN\n *\n *\t#define HASH_LONG\t\tMD5_LONG\n *\t#define HASH_LONG_LOG2\t\tMD5_LONG_LOG2\n *\t#define HASH_CTX\t\tMD5_CTX\n *\t#define HASH_CBLOCK\t\tMD5_CBLOCK\n *\t#define HASH_LBLOCK\t\tMD5_LBLOCK\n *\t#define HASH_UPDATE\t\tMD5_Update\n *\t#define HASH_TRANSFORM\t\tMD5_Transform\n *\t#define HASH_FINAL\t\tMD5_Final\n *\t#define HASH_BLOCK_HOST_ORDER\tmd5_block_host_order\n *\t#define HASH_BLOCK_DATA_ORDER\tmd5_block_data_order\n *\n *\t\t\t\t\t<appro@fy.chalmers.se>\n */\n\n#if defined( _MSC_VER )\n  #pragma warning( disable: 4311 )\t/* Warning about ugly 32-bit align ptr.cast - pcg */\n#endif /* VC++ */\n\n#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)\n#error \"DATA_ORDER must be defined!\"\n#endif\n\n#ifndef HASH_CBLOCK\n#error \"HASH_CBLOCK must be defined!\"\n#endif\n#ifndef HASH_LONG\n#error \"HASH_LONG must be defined!\"\n#endif\n#ifndef HASH_CTX\n#error \"HASH_CTX must be defined!\"\n#endif\n\n#ifndef HASH_UPDATE\n#error \"HASH_UPDATE must be defined!\"\n#endif\n#ifndef HASH_TRANSFORM\n#error \"HASH_TRANSFORM must be defined!\"\n#endif\n#ifndef HASH_FINAL\n#error \"HASH_FINAL must be defined!\"\n#endif\n\n#ifndef HASH_BLOCK_HOST_ORDER\n#error \"HASH_BLOCK_HOST_ORDER must be defined!\"\n#endif\n\n#if 0\n/*\n * Moved below as it's required only if HASH_BLOCK_DATA_ORDER_ALIGNED\n * isn't defined.\n */\n#ifndef HASH_BLOCK_DATA_ORDER\n#error \"HASH_BLOCK_DATA_ORDER must be defined!\"\n#endif\n#endif\n\n#ifndef HASH_LBLOCK\n#define HASH_LBLOCK\t(HASH_CBLOCK/4)\n#endif\n\n#ifndef HASH_LONG_LOG2\n#define HASH_LONG_LOG2\t2\n#endif\n\n/*\n * Engage compiler specific rotate intrinsic function if available.\n */\n#undef ROTATE\n#ifndef PEDANTIC\n# if defined(_MSC_VER) || defined( __BORLANDC__ )\n#  define ROTATE(a,n)\t_lrotl(a,n)\n# elif defined(__MWERKS__)\n#  if defined(__POWERPC__)\n#   define ROTATE(a,n)\t__rlwinm(a,n,0,31)\n#  elif defined(__MC68K__)\n    /* Motorola specific tweak. <appro@fy.chalmers.se> */\n#   define ROTATE(a,n)\t( n<24 ? __rol(a,n) : __ror(a,32-n) )\n#  else\n#   define ROTATE(a,n)\t__rol(a,n)\n#  endif\n# elif defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)\n  /*\n   * Some GNU C inline assembler templates. Note that these are\n   * rotates by *constant* number of bits! But that's exactly\n   * what we need here...\n   *\n   * \t\t\t\t\t<appro@fy.chalmers.se>\n   */\n#  if defined(__i386) || defined(__i386__)\n#   define ROTATE(a,n)\t({ register unsigned int ret;\t\\\n\t\t\t\tasm (\t\t\t\\\n\t\t\t\t\"roll %1,%0\"\t\t\\\n\t\t\t\t: \"=r\"(ret)\t\t\\\n\t\t\t\t: \"I\"(n), \"0\"(a)\t\\\n\t\t\t\t: \"cc\");\t\t\\\n\t\t\t   ret;\t\t\t\t\\\n\t\t\t})\n#  elif defined(__powerpc) || defined(__ppc)\n#   define ROTATE(a,n)\t({ register unsigned int ret;\t\\\n\t\t\t\tasm (\t\t\t\\\n\t\t\t\t\"rlwinm %0,%1,%2,0,31\"\t\\\n\t\t\t\t: \"=r\"(ret)\t\t\\\n\t\t\t\t: \"r\"(a), \"I\"(n));\t\\\n\t\t\t   ret;\t\t\t\t\\\n\t\t\t})\n#  endif\n# endif\n\n/*\n * Engage compiler specific \"fetch in reverse byte order\"\n * intrinsic function if available.\n */\n# if defined(__GNUC__) && __GNUC__>=2 && !defined(NO_ASM) && !defined(NO_INLINE_ASM)\n  /* some GNU C inline assembler templates by <appro@fy.chalmers.se> */\n#  if (defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)\n#   define BE_FETCH32(a)\t({ register unsigned int l=(a);\\\n\t\t\t\tasm (\t\t\t\\\n\t\t\t\t\"bswapl %0\"\t\t\\\n\t\t\t\t: \"=r\"(l) : \"0\"(l));\t\\\n\t\t\t  l;\t\t\t\t\\\n\t\t\t})\n#  elif defined(__powerpc)\n#   define LE_FETCH32(a)\t({ register unsigned int l;\t\\\n\t\t\t\tasm (\t\t\t\\\n\t\t\t\t\"lwbrx %0,0,%1\"\t\t\\\n\t\t\t\t: \"=r\"(l)\t\t\\\n\t\t\t\t: \"r\"(a));\t\t\\\n\t\t\t   l;\t\t\t\t\\\n\t\t\t})\n\n#  elif defined(__sparc) && defined(ULTRASPARC)\n#  define LE_FETCH32(a)\t({ register unsigned int l;\t\t\\\n\t\t\t\tasm (\t\t\t\t\\\n\t\t\t\t\"lda [%1]#ASI_PRIMARY_LITTLE,%0\"\\\n\t\t\t\t: \"=r\"(l)\t\t\t\\\n\t\t\t\t: \"r\"(a));\t\t\t\\\n\t\t\t   l;\t\t\t\t\t\\\n\t\t\t})\n#  endif\n# endif\n#endif /* PEDANTIC */\n\n#if HASH_LONG_LOG2==2\t/* Engage only if sizeof(HASH_LONG)== 4 */\n/* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */\n#ifdef ROTATE\n/* 5 instructions with rotate instruction, else 9 */\n#define REVERSE_FETCH32(a,l)\t(\t\t\t\t\t\\\n\t\tl=*(const HASH_LONG *)(a),\t\t\t\t\\\n\t\t((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))\t\\\n\t\t\t\t)\n#else\n/* 6 instructions with rotate instruction, else 8 */\n#define REVERSE_FETCH32(a,l)\t(\t\t\t\t\\\n\t\tl=*(const HASH_LONG *)(a),\t\t\t\\\n\t\tl=(((l>>8)&0x00FF00FF)|((l&0x00FF00FF)<<8)),\t\\\n\t\tROTATE(l,16)\t\t\t\t\t\\\n\t\t\t\t)\n/*\n * Originally the middle line started with l=(((l&0xFF00FF00)>>8)|...\n * It's rewritten as above for two reasons:\n *\t- RISCs aren't good at long constants and have to explicitely\n *\t  compose 'em with several (well, usually 2) instructions in a\n *\t  register before performing the actual operation and (as you\n *\t  already realized:-) having same constant should inspire the\n *\t  compiler to permanently allocate the only register for it;\n *\t- most modern CPUs have two ALUs, but usually only one has\n *\t  circuitry for shifts:-( this minor tweak inspires compiler\n *\t  to schedule shift instructions in a better way...\n *\n *\t\t\t\t<appro@fy.chalmers.se>\n */\n#endif\n#endif\n\n#ifndef ROTATE\n#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))\n#endif\n\n/*\n * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED\n * and HASH_BLOCK_HOST_ORDER ought to be the same if input data\n * and host are of the same \"endianess\". It's possible to mask\n * this with blank #define HASH_BLOCK_DATA_ORDER though...\n *\n *\t\t\t\t<appro@fy.chalmers.se>\n */\n#if defined(B_ENDIAN)\n#  if defined(DATA_ORDER_IS_BIG_ENDIAN)\n#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2\n#      define HASH_BLOCK_DATA_ORDER_ALIGNED\tHASH_BLOCK_HOST_ORDER\n#    endif\n#  elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)\n#    ifndef HOST_FETCH32\n#      ifdef LE_FETCH32\n#        define HOST_FETCH32(p,l)\tLE_FETCH32(p)\n#      elif defined(REVERSE_FETCH32)\n#        define HOST_FETCH32(p,l)\tREVERSE_FETCH32(p,l)\n#      endif\n#    endif\n#  endif\n#elif defined(L_ENDIAN)\n#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)\n#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2\n#      define HASH_BLOCK_DATA_ORDER_ALIGNED\tHASH_BLOCK_HOST_ORDER\n#    endif\n#  elif defined(DATA_ORDER_IS_BIG_ENDIAN)\n#    ifndef HOST_FETCH32\n#      ifdef BE_FETCH32\n#        define HOST_FETCH32(p,l)\tBE_FETCH32(p)\n#      elif defined(REVERSE_FETCH32)\n#        define HOST_FETCH32(p,l)\tREVERSE_FETCH32(p,l)\n#      endif\n#    endif\n#  endif\n#endif\n\n#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)\n#ifndef HASH_BLOCK_DATA_ORDER\n#error \"HASH_BLOCK_DATA_ORDER must be defined!\"\n#endif\n#endif\n\n#if defined(DATA_ORDER_IS_BIG_ENDIAN)\n\n#define HOST_c2l(c,l)\t(l =(((unsigned long)(*((c)++)))<<24),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))<<16),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))<< 8),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))    ),\t\t\\\n\t\t\t l)\n#define HOST_p_c2l(c,l,n)\t{\t\t\t\t\t\\\n\t\t\tswitch (n) {\t\t\t\t\t\\\n\t\t\tcase 0: l =((unsigned long)(*((c)++)))<<24;\t\\\n\t\t\tcase 1: l|=((unsigned long)(*((c)++)))<<16;\t\\\n\t\t\tcase 2: l|=((unsigned long)(*((c)++)))<< 8;\t\\\n\t\t\tcase 3: l|=((unsigned long)(*((c)++)));\t\t\\\n\t\t\t\t} }\n#define HOST_p_c2l_p(c,l,sc,len) {\t\t\t\t\t\\\n\t\t\tswitch (sc) {\t\t\t\t\t\\\n\t\t\tcase 0: l =((unsigned long)(*((c)++)))<<24;\t\\\n\t\t\t\tif (--len == 0) break;\t\t\t\\\n\t\t\tcase 1: l|=((unsigned long)(*((c)++)))<<16;\t\\\n\t\t\t\tif (--len == 0) break;\t\t\t\\\n\t\t\tcase 2: l|=((unsigned long)(*((c)++)))<< 8;\t\\\n\t\t\t\t} }\n/* NOTE the pointer is not incremented at the end of this */\n#define HOST_c2l_p(c,l,n)\t{\t\t\t\t\t\\\n\t\t\tl=0; (c)+=n;\t\t\t\t\t\\\n\t\t\tswitch (n) {\t\t\t\t\t\\\n\t\t\tcase 3: l =((unsigned long)(*(--(c))))<< 8;\t\\\n\t\t\tcase 2: l|=((unsigned long)(*(--(c))))<<16;\t\\\n\t\t\tcase 1: l|=((unsigned long)(*(--(c))))<<24;\t\\\n\t\t\t\t} }\n#define HOST_l2c(l,c)\t(*((c)++)=(unsigned char)(((l)>>24)&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16)&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8)&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)    )&0xff),\t\\\n\t\t\t l)\n\n#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)\n\n#define HOST_c2l(c,l)\t(l =(((unsigned long)(*((c)++)))    ),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))<< 8),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))<<16),\t\t\\\n\t\t\t l|=(((unsigned long)(*((c)++)))<<24),\t\t\\\n\t\t\t l)\n#define HOST_p_c2l(c,l,n)\t{\t\t\t\t\t\\\n\t\t\tswitch (n) {\t\t\t\t\t\\\n\t\t\tcase 0: l =((unsigned long)(*((c)++)));\t\t\\\n\t\t\tcase 1: l|=((unsigned long)(*((c)++)))<< 8;\t\\\n\t\t\tcase 2: l|=((unsigned long)(*((c)++)))<<16;\t\\\n\t\t\tcase 3: l|=((unsigned long)(*((c)++)))<<24;\t\\\n\t\t\t\t} }\n#define HOST_p_c2l_p(c,l,sc,len) {\t\t\t\t\t\\\n\t\t\tswitch (sc) {\t\t\t\t\t\\\n\t\t\tcase 0: l =((unsigned long)(*((c)++)));\t\t\\\n\t\t\t\tif (--len == 0) break;\t\t\t\\\n\t\t\tcase 1: l|=((unsigned long)(*((c)++)))<< 8;\t\\\n\t\t\t\tif (--len == 0) break;\t\t\t\\\n\t\t\tcase 2: l|=((unsigned long)(*((c)++)))<<16;\t\\\n\t\t\t\t} }\n/* NOTE the pointer is not incremented at the end of this */\n#define HOST_c2l_p(c,l,n)\t{\t\t\t\t\t\\\n\t\t\tl=0; (c)+=n;\t\t\t\t\t\\\n\t\t\tswitch (n) {\t\t\t\t\t\\\n\t\t\tcase 3: l =((unsigned long)(*(--(c))))<<16;\t\\\n\t\t\tcase 2: l|=((unsigned long)(*(--(c))))<< 8;\t\\\n\t\t\tcase 1: l|=((unsigned long)(*(--(c))));\t\t\\\n\t\t\t\t} }\n#define HOST_l2c(l,c)\t(*((c)++)=(unsigned char)(((l)    )&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8)&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16)&0xff),\t\\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24)&0xff),\t\\\n\t\t\t l)\n\n#endif\n\n/*\n * Time for some action:-)\n */\n\nvoid HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)\n\t{\n\tconst unsigned char *data=data_;\n\tregister HASH_LONG * p;\n\tregister unsigned long l;\n\tint sw,sc,ew,ec;\n\n\tif (len==0) return;\n\n\tl=(c->Nl+(len<<3))&0xffffffffL;\n\t/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to\n\t * Wei Dai <weidai@eskimo.com> for pointing it out. */\n\tif (l < c->Nl) /* overflow */\n\t\tc->Nh++;\n\tc->Nh+=(len>>29);\n\tc->Nl=l;\n\n\tif (c->num != 0)\n\t\t{\n\t\tp=c->data;\n\t\tsw=c->num>>2;\n\t\tsc=c->num&0x03;\n\n\t\tif ((c->num+len) >= HASH_CBLOCK)\n\t\t\t{\n\t\t\tl=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;\n\t\t\tfor (; sw<HASH_LBLOCK; sw++)\n\t\t\t\t{\n\t\t\t\tHOST_c2l(data,l); p[sw]=l;\n\t\t\t\t}\n\t\t\tHASH_BLOCK_HOST_ORDER (c,p,1);\n\t\t\tlen-=(HASH_CBLOCK-c->num);\n\t\t\tc->num=0;\n\t\t\t/* drop through and do the rest */\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tc->num+=len;\n\t\t\tif ((sc+len) < 4) /* ugly, add char's to a word */\n\t\t\t\t{\n\t\t\t\tl=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tew=(c->num>>2);\n\t\t\t\tec=(c->num&0x03);\n\t\t\t\tl=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;\n\t\t\t\tfor (; sw < ew; sw++)\n\t\t\t\t\t{\n\t\t\t\t\tHOST_c2l(data,l); p[sw]=l;\n\t\t\t\t\t}\n\t\t\t\tif (ec)\n\t\t\t\t\t{\n\t\t\t\t\tHOST_c2l_p(data,l,ec); p[sw]=l;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\tsw=len/HASH_CBLOCK;\n\tif (sw > 0)\n\t\t{\n#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)\n\t\t/*\n\t\t * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined\n\t\t * only if sizeof(HASH_LONG)==4.\n\t\t *\n\t\t * Masking is needed to suppress warnings from VS in 64-bit \n\t\t * mode - pcg\n\t\t */\n\t#if defined( _WIN32 ) && defined( _M_X64 )\n\t\tif ((((__int64)data)%4) == 0)\n\t#else\n\t\tif ((((unsigned long)data)%4) == 0)\n\t#endif /* Win64 vs. standard */\n\t\t\t{\n\t\t\t/* data is properly aligned so that we can cast it: */\n\t\t\tHASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,sw);\n\t\t\tsw*=HASH_CBLOCK;\n\t\t\tdata+=sw;\n\t\t\tlen-=sw;\n\t\t\t}\n\t\telse\n#if !defined(HASH_BLOCK_DATA_ORDER)\n\t\t\twhile (sw--)\n\t\t\t\t{\n\t\t\t\tmemcpy (p=c->data,data,HASH_CBLOCK);\n\t\t\t\tHASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);\n\t\t\t\tdata+=HASH_CBLOCK;\n\t\t\t\tlen-=HASH_CBLOCK;\n\t\t\t\t}\n#endif\n#endif\n#if defined(HASH_BLOCK_DATA_ORDER)\n\t\t\t{\n\t\t\tHASH_BLOCK_DATA_ORDER(c,data,sw);\n\t\t\tsw*=HASH_CBLOCK;\n\t\t\tdata+=sw;\n\t\t\tlen-=sw;\n\t\t\t}\n#endif\n\t\t}\n\n\tif (len!=0)\n\t\t{\n\t\tp = c->data;\n\t\tc->num = len;\n\t\tew=len>>2;\t/* words to copy */\n\t\tec=len&0x03;\n\t\tfor (; ew; ew--,p++)\n\t\t\t{\n\t\t\tHOST_c2l(data,l); *p=l;\n\t\t\t}\n\t\tHOST_c2l_p(data,l,ec);\n\t\t*p=l;\n\t\t}\n\t}\n\n\nvoid HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)\n\t{\n#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)\n\tif ((((unsigned long)data)%4) == 0)\n\t\t/* data is properly aligned so that we can cast it: */\n\t\tHASH_BLOCK_DATA_ORDER_ALIGNED (c,(HASH_LONG *)data,1);\n\telse\n#if !defined(HASH_BLOCK_DATA_ORDER)\n\t\t{\n\t\tmemcpy (c->data,data,HASH_CBLOCK);\n\t\tHASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);\n\t\t}\n#endif\n#endif\n#if defined(HASH_BLOCK_DATA_ORDER)\n\tHASH_BLOCK_DATA_ORDER (c,data,1);\n#endif\n\t}\n\n\nvoid HASH_FINAL (unsigned char *md, HASH_CTX *c)\n\t{\n\tregister HASH_LONG *p;\n\tregister unsigned long l;\n\tregister int i,j;\n\tstatic const unsigned char end[4]={0x80,0x00,0x00,0x00};\n\tconst unsigned char *cp=end;\n\n\t/* c->num should definitly have room for at least one more byte. */\n\tp=c->data;\n\ti=c->num>>2;\n\tj=c->num&0x03;\n\n#if 0\n\t/* purify often complains about the following line as an\n\t * Uninitialized Memory Read.  While this can be true, the\n\t * following p_c2l macro will reset l when that case is true.\n\t * This is because j&0x03 contains the number of 'valid' bytes\n\t * already in p[i].  If and only if j&0x03 == 0, the UMR will\n\t * occur but this is also the only time p_c2l will do\n\t * l= *(cp++) instead of l|= *(cp++)\n\t * Many thanks to Alex Tang <altitude@cic.net> for pickup this\n\t * 'potential bug' */\n#ifdef PURIFY\n\tif (j==0) p[i]=0; /* Yeah, but that's not the way to fix it:-) */\n#endif\n\tl=p[i];\n#else\n\tl = (j==0) ? 0 : p[i];\n#endif\n\tHOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */\n\n\tif (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */\n\t\t{\n\t\tif (i<HASH_LBLOCK) p[i]=0;\n\t\tHASH_BLOCK_HOST_ORDER (c,p,1);\n\t\ti=0;\n\t\t}\n\tfor (; i<(HASH_LBLOCK-2); i++)\n\t\tp[i]=0;\n\n#if   defined(DATA_ORDER_IS_BIG_ENDIAN)\n\tp[HASH_LBLOCK-2]=c->Nh;\n\tp[HASH_LBLOCK-1]=c->Nl;\n#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)\n\tp[HASH_LBLOCK-2]=c->Nl;\n\tp[HASH_LBLOCK-1]=c->Nh;\n#endif\n\tHASH_BLOCK_HOST_ORDER (c,p,1);\n\n#ifndef HASH_MAKE_STRING\n#error \"HASH_MAKE_STRING must be defined!\"\n#else\n\tHASH_MAKE_STRING(c,md);\n#endif\n\n\tc->num=0;\n\t/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack\n\t * but I'm not worried :-)\n\tmemset((void *)c,0,sizeof(HASH_CTX));\n\t */\n\t}\n"
  },
  {
    "path": "deps/cl345/crypt/md5.h",
    "content": "/* crypto/md5/md5.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_MD5_H\n#define HEADER_MD5_H\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef NO_MD5\n#error MD5 is disabled.\n#endif\n\n/*\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then !\n * ! MD5_LONG_LOG2 has to be defined along.\t\t\t   !\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n */\n\n#if defined(WIN16) || defined(__LP32__)\n#define MD5_LONG unsigned long\n#elif defined(_CRAY) || defined(__ILP64__)\n#define MD5_LONG unsigned long\n#define MD5_LONG_LOG2 3\n/*\n * _CRAY note. I could declare short, but I have no idea what impact\n * does it have on performance on none-T3E machines. I could declare\n * int, but at least on C90 sizeof(int) can be chosen at compile time.\n * So I've chosen long...\n *\t\t\t\t\t<appro@fy.chalmers.se>\n */\n#else\n#define MD5_LONG unsigned int\n#endif\n\n#define MD5_CBLOCK\t64\n#define MD5_LBLOCK\t(MD5_CBLOCK/4)\n#define MD5_DIGEST_LENGTH 16\n\ntypedef struct MD5state_st\n\t{\n\tMD5_LONG A,B,C,D;\n\tMD5_LONG Nl,Nh;\n\tMD5_LONG data[MD5_LBLOCK];\n\tlong num;\n\t} MD5_CTX;\n\nvoid MD5_Init(MD5_CTX *c);\nvoid MD5_Update(MD5_CTX *c, const void *data, unsigned long len);\nvoid MD5_Final(unsigned char *md, MD5_CTX *c);\nunsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md);\nvoid MD5_Transform(MD5_CTX *c, const unsigned char *b);\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/md5dgst.c",
    "content": "/* crypto/md5/md5_dgst.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n#else\n  #include \"crypt/osconfig.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_MD5\n\n/* We can only include md5locl.h at this point since it creates code for \n   various functions via complicated nesting of includes and macro \n   manipulation */\n\n#if defined( INC_ALL )\n  #include \"md5locl.h\"\n#else\n  #include \"crypt/md5locl.h\"\n#endif /* Compiler-specific includes */\n\n/* Implemented from RFC1321 The MD5 Message-Digest Algorithm\n */\n\n#define INIT_DATA_A (unsigned long)0x67452301L\n#define INIT_DATA_B (unsigned long)0xefcdab89L\n#define INIT_DATA_C (unsigned long)0x98badcfeL\n#define INIT_DATA_D (unsigned long)0x10325476L\n\nvoid MD5_Init(MD5_CTX *c)\n\t{\n\tc->A=INIT_DATA_A;\n\tc->B=INIT_DATA_B;\n\tc->C=INIT_DATA_C;\n\tc->D=INIT_DATA_D;\n\tc->Nl=0;\n\tc->Nh=0;\n\tc->num=0;\n\t}\n\n#ifndef md5_block_host_order\nvoid md5_block_host_order (MD5_CTX *c, const void *data, int num)\n\t{\n\tconst MD5_LONG *X=data;\n\tregister unsigned long A,B,C,D;\n\t/*\n\t * In case you wonder why A-D are declared as long and not\n\t * as MD5_LONG. Doing so results in slight performance\n\t * boost on LP64 architectures. The catch is we don't\n\t * really care if 32 MSBs of a 64-bit register get polluted\n\t * with eventual overflows as we *save* only 32 LSBs in\n\t * *either* case. Now declaring 'em long excuses the compiler\n\t * from keeping 32 MSBs zeroed resulting in 13% performance\n\t * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.\n\t * Well, to be honest it should say that this *prevents*\n\t * performance degradation.\n\t *\n\t *\t\t\t\t<appro@fy.chalmers.se>\n\t */\n\n\tA=c->A;\n\tB=c->B;\n\tC=c->C;\n\tD=c->D;\n\n\tfor (;num--;X+=HASH_LBLOCK)\n\t\t{\n\t/* Round 0 */\n\tR0(A,B,C,D,X[ 0], 7,0xd76aa478L);\n\tR0(D,A,B,C,X[ 1],12,0xe8c7b756L);\n\tR0(C,D,A,B,X[ 2],17,0x242070dbL);\n\tR0(B,C,D,A,X[ 3],22,0xc1bdceeeL);\n\tR0(A,B,C,D,X[ 4], 7,0xf57c0fafL);\n\tR0(D,A,B,C,X[ 5],12,0x4787c62aL);\n\tR0(C,D,A,B,X[ 6],17,0xa8304613L);\n\tR0(B,C,D,A,X[ 7],22,0xfd469501L);\n\tR0(A,B,C,D,X[ 8], 7,0x698098d8L);\n\tR0(D,A,B,C,X[ 9],12,0x8b44f7afL);\n\tR0(C,D,A,B,X[10],17,0xffff5bb1L);\n\tR0(B,C,D,A,X[11],22,0x895cd7beL);\n\tR0(A,B,C,D,X[12], 7,0x6b901122L);\n\tR0(D,A,B,C,X[13],12,0xfd987193L);\n\tR0(C,D,A,B,X[14],17,0xa679438eL);\n\tR0(B,C,D,A,X[15],22,0x49b40821L);\n\t/* Round 1 */\n\tR1(A,B,C,D,X[ 1], 5,0xf61e2562L);\n\tR1(D,A,B,C,X[ 6], 9,0xc040b340L);\n\tR1(C,D,A,B,X[11],14,0x265e5a51L);\n\tR1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);\n\tR1(A,B,C,D,X[ 5], 5,0xd62f105dL);\n\tR1(D,A,B,C,X[10], 9,0x02441453L);\n\tR1(C,D,A,B,X[15],14,0xd8a1e681L);\n\tR1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);\n\tR1(A,B,C,D,X[ 9], 5,0x21e1cde6L);\n\tR1(D,A,B,C,X[14], 9,0xc33707d6L);\n\tR1(C,D,A,B,X[ 3],14,0xf4d50d87L);\n\tR1(B,C,D,A,X[ 8],20,0x455a14edL);\n\tR1(A,B,C,D,X[13], 5,0xa9e3e905L);\n\tR1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);\n\tR1(C,D,A,B,X[ 7],14,0x676f02d9L);\n\tR1(B,C,D,A,X[12],20,0x8d2a4c8aL);\n\t/* Round 2 */\n\tR2(A,B,C,D,X[ 5], 4,0xfffa3942L);\n\tR2(D,A,B,C,X[ 8],11,0x8771f681L);\n\tR2(C,D,A,B,X[11],16,0x6d9d6122L);\n\tR2(B,C,D,A,X[14],23,0xfde5380cL);\n\tR2(A,B,C,D,X[ 1], 4,0xa4beea44L);\n\tR2(D,A,B,C,X[ 4],11,0x4bdecfa9L);\n\tR2(C,D,A,B,X[ 7],16,0xf6bb4b60L);\n\tR2(B,C,D,A,X[10],23,0xbebfbc70L);\n\tR2(A,B,C,D,X[13], 4,0x289b7ec6L);\n\tR2(D,A,B,C,X[ 0],11,0xeaa127faL);\n\tR2(C,D,A,B,X[ 3],16,0xd4ef3085L);\n\tR2(B,C,D,A,X[ 6],23,0x04881d05L);\n\tR2(A,B,C,D,X[ 9], 4,0xd9d4d039L);\n\tR2(D,A,B,C,X[12],11,0xe6db99e5L);\n\tR2(C,D,A,B,X[15],16,0x1fa27cf8L);\n\tR2(B,C,D,A,X[ 2],23,0xc4ac5665L);\n\t/* Round 3 */\n\tR3(A,B,C,D,X[ 0], 6,0xf4292244L);\n\tR3(D,A,B,C,X[ 7],10,0x432aff97L);\n\tR3(C,D,A,B,X[14],15,0xab9423a7L);\n\tR3(B,C,D,A,X[ 5],21,0xfc93a039L);\n\tR3(A,B,C,D,X[12], 6,0x655b59c3L);\n\tR3(D,A,B,C,X[ 3],10,0x8f0ccc92L);\n\tR3(C,D,A,B,X[10],15,0xffeff47dL);\n\tR3(B,C,D,A,X[ 1],21,0x85845dd1L);\n\tR3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);\n\tR3(D,A,B,C,X[15],10,0xfe2ce6e0L);\n\tR3(C,D,A,B,X[ 6],15,0xa3014314L);\n\tR3(B,C,D,A,X[13],21,0x4e0811a1L);\n\tR3(A,B,C,D,X[ 4], 6,0xf7537e82L);\n\tR3(D,A,B,C,X[11],10,0xbd3af235L);\n\tR3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);\n\tR3(B,C,D,A,X[ 9],21,0xeb86d391L);\n\n\tA = c->A += A;\n\tB = c->B += B;\n\tC = c->C += C;\n\tD = c->D += D;\n\t\t}\n\t}\n#endif\n\n#ifndef md5_block_data_order\n#ifdef X\n#undef X\n#endif\nvoid md5_block_data_order (MD5_CTX *c, const void *data_, int num)\n\t{\n\tconst unsigned char *data=data_;\n\tregister unsigned long A,B,C,D,l;\n\t/*\n\t * In case you wonder why A-D are declared as long and not\n\t * as MD5_LONG. Doing so results in slight performance\n\t * boost on LP64 architectures. The catch is we don't\n\t * really care if 32 MSBs of a 64-bit register get polluted\n\t * with eventual overflows as we *save* only 32 LSBs in\n\t * *either* case. Now declaring 'em long excuses the compiler\n\t * from keeping 32 MSBs zeroed resulting in 13% performance\n\t * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.\n\t * Well, to be honest it should say that this *prevents*\n\t * performance degradation.\n\t *\n\t *\t\t\t\t<appro@fy.chalmers.se>\n\t */\n#ifndef MD32_XARRAY\n\t/* See comment in crypto/sha/sha_locl.h for details. */\n\tunsigned long\tXX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,\n\t\t\tXX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;\n# define X(i)\tXX##i\n#else\n\tMD5_LONG XX[MD5_LBLOCK];\n# define X(i)\tXX[i]\n#endif\n\n\tA=c->A;\n\tB=c->B;\n\tC=c->C;\n\tD=c->D;\n\n\tfor (;num--;)\n\t\t{\n\tHOST_c2l(data,l); X( 0)=l;\t\tHOST_c2l(data,l); X( 1)=l;\n\t/* Round 0 */\n\tR0(A,B,C,D,X( 0), 7,0xd76aa478L);\tHOST_c2l(data,l); X( 2)=l;\n\tR0(D,A,B,C,X( 1),12,0xe8c7b756L);\tHOST_c2l(data,l); X( 3)=l;\n\tR0(C,D,A,B,X( 2),17,0x242070dbL);\tHOST_c2l(data,l); X( 4)=l;\n\tR0(B,C,D,A,X( 3),22,0xc1bdceeeL);\tHOST_c2l(data,l); X( 5)=l;\n\tR0(A,B,C,D,X( 4), 7,0xf57c0fafL);\tHOST_c2l(data,l); X( 6)=l;\n\tR0(D,A,B,C,X( 5),12,0x4787c62aL);\tHOST_c2l(data,l); X( 7)=l;\n\tR0(C,D,A,B,X( 6),17,0xa8304613L);\tHOST_c2l(data,l); X( 8)=l;\n\tR0(B,C,D,A,X( 7),22,0xfd469501L);\tHOST_c2l(data,l); X( 9)=l;\n\tR0(A,B,C,D,X( 8), 7,0x698098d8L);\tHOST_c2l(data,l); X(10)=l;\n\tR0(D,A,B,C,X( 9),12,0x8b44f7afL);\tHOST_c2l(data,l); X(11)=l;\n\tR0(C,D,A,B,X(10),17,0xffff5bb1L);\tHOST_c2l(data,l); X(12)=l;\n\tR0(B,C,D,A,X(11),22,0x895cd7beL);\tHOST_c2l(data,l); X(13)=l;\n\tR0(A,B,C,D,X(12), 7,0x6b901122L);\tHOST_c2l(data,l); X(14)=l;\n\tR0(D,A,B,C,X(13),12,0xfd987193L);\tHOST_c2l(data,l); X(15)=l;\n\tR0(C,D,A,B,X(14),17,0xa679438eL);\n\tR0(B,C,D,A,X(15),22,0x49b40821L);\n\t/* Round 1 */\n\tR1(A,B,C,D,X( 1), 5,0xf61e2562L);\n\tR1(D,A,B,C,X( 6), 9,0xc040b340L);\n\tR1(C,D,A,B,X(11),14,0x265e5a51L);\n\tR1(B,C,D,A,X( 0),20,0xe9b6c7aaL);\n\tR1(A,B,C,D,X( 5), 5,0xd62f105dL);\n\tR1(D,A,B,C,X(10), 9,0x02441453L);\n\tR1(C,D,A,B,X(15),14,0xd8a1e681L);\n\tR1(B,C,D,A,X( 4),20,0xe7d3fbc8L);\n\tR1(A,B,C,D,X( 9), 5,0x21e1cde6L);\n\tR1(D,A,B,C,X(14), 9,0xc33707d6L);\n\tR1(C,D,A,B,X( 3),14,0xf4d50d87L);\n\tR1(B,C,D,A,X( 8),20,0x455a14edL);\n\tR1(A,B,C,D,X(13), 5,0xa9e3e905L);\n\tR1(D,A,B,C,X( 2), 9,0xfcefa3f8L);\n\tR1(C,D,A,B,X( 7),14,0x676f02d9L);\n\tR1(B,C,D,A,X(12),20,0x8d2a4c8aL);\n\t/* Round 2 */\n\tR2(A,B,C,D,X( 5), 4,0xfffa3942L);\n\tR2(D,A,B,C,X( 8),11,0x8771f681L);\n\tR2(C,D,A,B,X(11),16,0x6d9d6122L);\n\tR2(B,C,D,A,X(14),23,0xfde5380cL);\n\tR2(A,B,C,D,X( 1), 4,0xa4beea44L);\n\tR2(D,A,B,C,X( 4),11,0x4bdecfa9L);\n\tR2(C,D,A,B,X( 7),16,0xf6bb4b60L);\n\tR2(B,C,D,A,X(10),23,0xbebfbc70L);\n\tR2(A,B,C,D,X(13), 4,0x289b7ec6L);\n\tR2(D,A,B,C,X( 0),11,0xeaa127faL);\n\tR2(C,D,A,B,X( 3),16,0xd4ef3085L);\n\tR2(B,C,D,A,X( 6),23,0x04881d05L);\n\tR2(A,B,C,D,X( 9), 4,0xd9d4d039L);\n\tR2(D,A,B,C,X(12),11,0xe6db99e5L);\n\tR2(C,D,A,B,X(15),16,0x1fa27cf8L);\n\tR2(B,C,D,A,X( 2),23,0xc4ac5665L);\n\t/* Round 3 */\n\tR3(A,B,C,D,X( 0), 6,0xf4292244L);\n\tR3(D,A,B,C,X( 7),10,0x432aff97L);\n\tR3(C,D,A,B,X(14),15,0xab9423a7L);\n\tR3(B,C,D,A,X( 5),21,0xfc93a039L);\n\tR3(A,B,C,D,X(12), 6,0x655b59c3L);\n\tR3(D,A,B,C,X( 3),10,0x8f0ccc92L);\n\tR3(C,D,A,B,X(10),15,0xffeff47dL);\n\tR3(B,C,D,A,X( 1),21,0x85845dd1L);\n\tR3(A,B,C,D,X( 8), 6,0x6fa87e4fL);\n\tR3(D,A,B,C,X(15),10,0xfe2ce6e0L);\n\tR3(C,D,A,B,X( 6),15,0xa3014314L);\n\tR3(B,C,D,A,X(13),21,0x4e0811a1L);\n\tR3(A,B,C,D,X( 4), 6,0xf7537e82L);\n\tR3(D,A,B,C,X(11),10,0xbd3af235L);\n\tR3(C,D,A,B,X( 2),15,0x2ad7d2bbL);\n\tR3(B,C,D,A,X( 9),21,0xeb86d391L);\n\n\tA = c->A += A;\n\tB = c->B += B;\n\tC = c->C += C;\n\tD = c->D += D;\n\t\t}\n\t}\n#endif\n\n#ifdef undef\nint printit(unsigned long *l)\n\t{\n\tint i,ii;\n\n\tfor (i=0; i<2; i++)\n\t\t{\n\t\tfor (ii=0; ii<8; ii++)\n\t\t\t{\n\t\t\tfprintf(stderr,\"%08lx \",l[i*8+ii]);\n\t\t\t}\n\t\tfprintf(stderr,\"\\n\");\n\t\t}\n\t}\n#endif\n#endif /* USE_MD5 */\n"
  },
  {
    "path": "deps/cl345/crypt/md5locl.h",
    "content": "/* crypto/md5/md5_locl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include <stdlib.h>\n#include <string.h>\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"md5.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/md5.h\"\n#endif /* Compiler-specific includes */\n\n#ifndef MD5_LONG_LOG2\n#define MD5_LONG_LOG2 2 /* default to 32 bits */\n#endif\n\n#ifdef MD5_ASM\n# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)\n#  define md5_block_host_order md5_block_asm_host_order\n# elif defined(__sparc) && defined(ULTRASPARC)\n   void md5_block_asm_data_order_aligned (MD5_CTX *c, const MD5_LONG *p,int num);\n#  define HASH_BLOCK_DATA_ORDER_ALIGNED md5_block_asm_data_order_aligned\n# endif\n#endif\n\nvoid md5_block_host_order (MD5_CTX *c, const void *p,int num);\nvoid md5_block_data_order (MD5_CTX *c, const void *p,int num);\n\n#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)\n/*\n * *_block_host_order is expected to handle aligned data while\n * *_block_data_order - unaligned. As algorithm and host (x86)\n * are in this case of the same \"endianness\" these two are\n * otherwise indistinguishable. But normally you don't want to\n * call the same function because unaligned access in places\n * where alignment is expected is usually a \"Bad Thing\". Indeed,\n * on RISCs you get punished with BUS ERROR signal or *severe*\n * performance degradation. Intel CPUs are in turn perfectly\n * capable of loading unaligned data without such drastic side\n * effect. Yes, they say it's slower than aligned load, but no\n * exception is generated and therefore performance degradation\n * is *incomparable* with RISCs. What we should weight here is\n * costs of unaligned access against costs of aligning data.\n * According to my measurements allowing unaligned access results\n * in ~9% performance improvement on Pentium II operating at\n * 266MHz. I won't be surprised if the difference will be higher\n * on faster systems:-)\n *\n *\t\t\t\t<appro@fy.chalmers.se>\n */\n#define md5_block_data_order md5_block_host_order\n#endif\n\n#define DATA_ORDER_IS_LITTLE_ENDIAN\n\n#define HASH_LONG\t\tMD5_LONG\n#define HASH_LONG_LOG2\t\tMD5_LONG_LOG2\n#define HASH_CTX\t\tMD5_CTX\n#define HASH_CBLOCK\t\tMD5_CBLOCK\n#define HASH_LBLOCK\t\tMD5_LBLOCK\n#define HASH_UPDATE\t\tMD5_Update\n#define HASH_TRANSFORM\t\tMD5_Transform\n#define HASH_FINAL\t\tMD5_Final\n#define\tHASH_MAKE_STRING(c,s)\t{\t\\\n\tunsigned long ll;\t\t\\\n\tll=(c)->A; HOST_l2c(ll,(s));\t\\\n\tll=(c)->B; HOST_l2c(ll,(s));\t\\\n\tll=(c)->C; HOST_l2c(ll,(s));\t\\\n\tll=(c)->D; HOST_l2c(ll,(s));\t\\\n\t} \t/* Removed dummy while(0) - pcg */\n#define HASH_BLOCK_HOST_ORDER\tmd5_block_host_order\n#if !defined(L_ENDIAN) || defined(md5_block_data_order)\n#define\tHASH_BLOCK_DATA_ORDER\tmd5_block_data_order\n/*\n * Little-endians (Intel and Alpha) feel better without this.\n * It looks like memcpy does better job than generic\n * md5_block_data_order on copying-n-aligning input data.\n * But frankly speaking I didn't expect such result on Alpha.\n * On the other hand I've got this with egcs-1.0.2 and if\n * program is compiled with another (better?) compiler it\n * might turn out other way around.\n *\n *\t\t\t\t<appro@fy.chalmers.se>\n */\n#endif\n\n#if defined( INC_ALL )\n  #include \"md32com.h\"\n#else\n  #include \"crypt/md32com.h\"\n#endif /* Compiler-specific includes */\n\n/*\n#define\tF(x,y,z)\t(((x) & (y))  |  ((~(x)) & (z)))\n#define\tG(x,y,z)\t(((x) & (z))  |  ((y) & (~(z))))\n*/\n\n/* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be\n * simplified to the code below.  Wei attributes these optimizations\n * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.\n */\n#define\tF(b,c,d)\t((((c) ^ (d)) & (b)) ^ (d))\n#define\tG(b,c,d)\t((((b) ^ (c)) & (d)) ^ (c))\n#define\tH(b,c,d)\t((b) ^ (c) ^ (d))\n#define\tI(b,c,d)\t(((~(d)) | (b)) ^ (c))\n\n#define R0(a,b,c,d,k,s,t) { \\\n\ta+=((k)+(t)+F((b),(c),(d))); \\\n\ta=ROTATE(a,s); \\\n\ta+=b; };\\\n\n#define R1(a,b,c,d,k,s,t) { \\\n\ta+=((k)+(t)+G((b),(c),(d))); \\\n\ta=ROTATE(a,s); \\\n\ta+=b; };\n\n#define R2(a,b,c,d,k,s,t) { \\\n\ta+=((k)+(t)+H((b),(c),(d))); \\\n\ta=ROTATE(a,s); \\\n\ta+=b; };\n\n#define R3(a,b,c,d,k,s,t) { \\\n\ta+=((k)+(t)+I((b),(c),(d))); \\\n\ta=ROTATE(a,s); \\\n\ta+=b; };\n"
  },
  {
    "path": "deps/cl345/crypt/mode_hdr.h",
    "content": "/*\n---------------------------------------------------------------------------\nCopyright (c) 1998-2014, Brian Gladman, Worcester, UK. All rights reserved.\n\nThe redistribution and use of this software (with or without changes)\nis allowed without the payment of fees or royalties provided that:\n\n  source code distributions include the above copyright notice, this\n  list of conditions and the following disclaimer;\n\n  binary distributions include the above copyright notice, this list\n  of conditions and the following disclaimer in their documentation.\n\nThis software is provided 'as is' with no explicit or implied warranties\nin respect of its operation, including, but not limited to, correctness\nand fitness for purpose.\n---------------------------------------------------------------------------\nIssue Date: 18/02/2014\n\nThis header file is an INTERNAL file which supports mode implementation\n*/\n\n#ifndef _MODE_HDR_H\n#define _MODE_HDR_H\n\n#include <string.h>\n#include <limits.h>\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"brg_endian.h\"\n#else\n  #include \"crypt/brg_endian.h\"\n#endif /* Compiler-specific includes */\n\n/*  This define sets the units in which buffers are processed.  This code\n    can provide significant speed gains if buffers can be processed in\n    32 or 64 bit chunks rather than in bytes.  This define sets the units\n    in which buffers will be accessed if possible\n*/\n#if !defined( UNIT_BITS )\n#  if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN\n#    if 0\n#      define UNIT_BITS  32\n#    elif 1\n#      define UNIT_BITS  64\n#    endif\n#  elif defined( _WIN64 )\n#    define UNIT_BITS 64\n#  else\n#    define UNIT_BITS 32\n#  endif\n#endif\n\n#if UNIT_BITS == 64 && !defined( NEED_UINT_64T )\n#  define NEED_UINT_64T\n#endif\n\n#if defined( INC_ALL )\t\t/* pcg */\n  #include \"brg_types.h\"\n#else\n  #include \"crypt/brg_types.h\"\n#endif /* Compiler-specific includes */\n\n/*  Use of inlines is preferred but code blocks can also be expanded inline\n    using 'defines'.  But the latter approach will typically generate a LOT\n    of code and is not recommended. \n*/\n#if 1 && !defined( USE_INLINING )\n#  define USE_INLINING\n#endif\n\n#if defined( _MSC_VER )\n#  if _MSC_VER >= 1400\n#    include <stdlib.h>\n#    include <intrin.h>\n#    pragma intrinsic(memset)\n#    pragma intrinsic(memcpy)\n#    define rotl32        _rotl\n#    define rotr32        _rotr\n#    define rotl64        _rotl64\n#    define rotr64        _rotl64\n#    define bswap_16(x)   _byteswap_ushort(x)\n#    define bswap_32(x)   _byteswap_ulong(x)\n#    define bswap_64(x)   _byteswap_uint64(x)\n#  else\n#    define rotl32 _lrotl\n#    define rotr32 _lrotr\n#  endif\n#endif\n\n#if defined( USE_INLINING )\n#  if defined( _MSC_VER )\n#    define mh_decl __inline\n#  elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )\n#    define mh_decl static inline\n#  else\n#    define mh_decl static\n#  endif\n#endif\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#define  UI8_PTR(x)     UPTR_CAST(x,  8)\n#define UI16_PTR(x)     UPTR_CAST(x, 16)\n#define UI32_PTR(x)     UPTR_CAST(x, 32)\n#define UI64_PTR(x)     UPTR_CAST(x, 64)\n#define UNIT_PTR(x)     UPTR_CAST(x, UNIT_BITS)\n\n#define  UI8_VAL(x)     UNIT_CAST(x,  8)\n#define UI16_VAL(x)     UNIT_CAST(x, 16)\n#define UI32_VAL(x)     UNIT_CAST(x, 32)\n#define UI64_VAL(x)     UNIT_CAST(x, 64)\n#define UNIT_VAL(x)     UNIT_CAST(x, UNIT_BITS)\n\n#define BUF_INC          (UNIT_BITS >> 3)\n#define BUF_ADRMASK     ((UNIT_BITS >> 3) - 1)\n\n#define rep2_u2(f,r,x)    f( 0,r,x); f( 1,r,x) \n#define rep2_u4(f,r,x)    f( 0,r,x); f( 1,r,x); f( 2,r,x); f( 3,r,x) \n#define rep2_u16(f,r,x)   f( 0,r,x); f( 1,r,x); f( 2,r,x); f( 3,r,x); \\\n                          f( 4,r,x); f( 5,r,x); f( 6,r,x); f( 7,r,x); \\\n                          f( 8,r,x); f( 9,r,x); f(10,r,x); f(11,r,x); \\\n                          f(12,r,x); f(13,r,x); f(14,r,x); f(15,r,x)\n\n#define rep2_d2(f,r,x)    f( 1,r,x); f( 0,r,x) \n#define rep2_d4(f,r,x)    f( 3,r,x); f( 2,r,x); f( 1,r,x); f( 0,r,x) \n#define rep2_d16(f,r,x)   f(15,r,x); f(14,r,x); f(13,r,x); f(12,r,x); \\\n                          f(11,r,x); f(10,r,x); f( 9,r,x); f( 8,r,x); \\\n                          f( 7,r,x); f( 6,r,x); f( 5,r,x); f( 4,r,x); \\\n                          f( 3,r,x); f( 2,r,x); f( 1,r,x); f( 0,r,x)\n\n#define rep3_u2(f,r,x,y,c)  f( 0,r,x,y,c); f( 1,r,x,y,c) \n#define rep3_u4(f,r,x,y,c)  f( 0,r,x,y,c); f( 1,r,x,y,c); f( 2,r,x,y,c); f( 3,r,x,y,c) \n#define rep3_u16(f,r,x,y,c) f( 0,r,x,y,c); f( 1,r,x,y,c); f( 2,r,x,y,c); f( 3,r,x,y,c); \\\n                            f( 4,r,x,y,c); f( 5,r,x,y,c); f( 6,r,x,y,c); f( 7,r,x,y,c); \\\n                            f( 8,r,x,y,c); f( 9,r,x,y,c); f(10,r,x,y,c); f(11,r,x,y,c); \\\n                            f(12,r,x,y,c); f(13,r,x,y,c); f(14,r,x,y,c); f(15,r,x,y,c)\n\n#define rep3_d2(f,r,x,y,c)  f( 1,r,x,y,c); f( 0,r,x,y,c) \n#define rep3_d4(f,r,x,y,c)  f( 3,r,x,y,c); f( 2,r,x,y,c); f( 1,r,x,y,c); f( 0,r,x,y,c) \n#define rep3_d16(f,r,x,y,c) f(15,r,x,y,c); f(14,r,x,y,c); f(13,r,x,y,c); f(12,r,x,y,c); \\\n                            f(11,r,x,y,c); f(10,r,x,y,c); f( 9,r,x,y,c); f( 8,r,x,y,c); \\\n                            f( 7,r,x,y,c); f( 6,r,x,y,c); f( 5,r,x,y,c); f( 4,r,x,y,c); \\\n                            f( 3,r,x,y,c); f( 2,r,x,y,c); f( 1,r,x,y,c); f( 0,r,x,y,c)\n\n/* function pointers might be used for fast XOR operations */\n\ntypedef void (*xor_function)(void* r, const void* p, const void* q);\n\n/* left and right rotates on 32 and 64 bit variables */\n\n#if !defined( rotl32 )  /* NOTE: 0 <= n <= 32 ASSUMED */\nmh_decl uint32_t rotl32(uint32_t x, int n)\n{\n    return (((x) << n) | ((x) >> (32 - n)));\n}\n#endif\n\n#if !defined( rotr32 )  /* NOTE: 0 <= n <= 32 ASSUMED */\nmh_decl uint32_t rotr32(uint32_t x, int n)\n{\n    return (((x) >> n) | ((x) << (32 - n)));\n}\n#endif\n\n#if ( UNIT_BITS == 64 ) && !defined( rotl64 )  /* NOTE: 0 <= n <= 64 ASSUMED */\nmh_decl uint64_t rotl64(uint64_t x, int n)\n{\n    return (((x) << n) | ((x) >> (64 - n)));\n}\n#endif\n\n#if ( UNIT_BITS == 64 ) && !defined( rotr64 )  /* NOTE: 0 <= n <= 64 ASSUMED */\nmh_decl uint64_t rotr64(uint64_t x, int n)\n{\n    return (((x) >> n) | ((x) << (64 - n)));\n}\n#endif\n\n/* byte order inversions for 16, 32 and 64 bit variables */\n\n#if !defined(bswap_16)\nmh_decl uint16_t bswap_16(uint16_t x)\n{\n    return (uint16_t)((x >> 8) | (x << 8));\n}\n#endif\n\n#if !defined(bswap_32)\nmh_decl uint32_t bswap_32(uint32_t x)\n{\n    return ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00));\n}\n#endif\n\n#if ( UNIT_BITS == 64 ) && !defined(bswap_64)\nmh_decl uint64_t bswap_64(uint64_t x)\n{   \n    return bswap_32((uint32_t)(x >> 32)) | ((uint64_t)bswap_32((uint32_t)x) << 32);\n}\n#endif\n\n/* support for fast aligned buffer move, xor and byte swap operations - \n   source and destination buffers for move and xor operations must not \n   overlap, those for byte order revesal must either not overlap or\n   must be identical\n*/\n#define f_copy(n,p,q)     p[n] = q[n]\n#define f_xor(n,r,p,q,c)  r[n] = c(p[n] ^ q[n])\n\nmh_decl void copy_block(void* p, const void* q)\n{\n    memcpy(p, q, 16);\n}\n\nmh_decl void copy_block_aligned(void *p, const void *q)\n{\n#if UNIT_BITS == 8\n    memcpy(p, q, 16);\n#elif UNIT_BITS == 32\n    rep2_u4(f_copy,UNIT_PTR(p),UNIT_PTR(q));\n#else\n    rep2_u2(f_copy,UNIT_PTR(p),UNIT_PTR(q));\n#endif\n}\n\nmh_decl void xor_block(void *r, const void* p, const void* q)\n{\n    rep3_u16(f_xor, UI8_PTR(r), UI8_PTR(p), UI8_PTR(q), UI8_VAL);\n}\n\nmh_decl void xor_block_aligned(void *r, const void *p, const void *q)\n{\n#if UNIT_BITS == 8\n    rep3_u16(f_xor, UNIT_PTR(r), UNIT_PTR(p), UNIT_PTR(q), UNIT_VAL);\n#elif UNIT_BITS == 32\n    rep3_u4(f_xor, UNIT_PTR(r), UNIT_PTR(p), UNIT_PTR(q), UNIT_VAL);\n#else\n    rep3_u2(f_xor, UNIT_PTR(r), UNIT_PTR(p), UNIT_PTR(q), UNIT_VAL);\n#endif\n}\n\n/* byte swap within 32-bit words in a 16 byte block; don't move 32-bit words */\nmh_decl void bswap32_block(void *d, const void* s)\n{\n#if UNIT_BITS == 8\n    uint8_t t;\n    t = UNIT_PTR(s)[ 0]; UNIT_PTR(d)[ 0] = UNIT_PTR(s)[ 3]; UNIT_PTR(d)[ 3] = t;\n    t = UNIT_PTR(s)[ 1]; UNIT_PTR(d)[ 1] = UNIT_PTR(s)[ 2]; UNIT_PTR(d)[ 2] = t;\n    t = UNIT_PTR(s)[ 4]; UNIT_PTR(d)[ 4] = UNIT_PTR(s)[ 7]; UNIT_PTR(d)[ 7] = t;\n    t = UNIT_PTR(s)[ 5]; UNIT_PTR(d)[ 5] = UNIT_PTR(s)[ 6]; UNIT_PTR(d) [6] = t;\n    t = UNIT_PTR(s)[ 8]; UNIT_PTR(d)[ 8] = UNIT_PTR(s)[11]; UNIT_PTR(d)[12] = t;\n    t = UNIT_PTR(s)[ 9]; UNIT_PTR(d)[ 9] = UNIT_PTR(s)[10]; UNIT_PTR(d)[10] = t;\n    t = UNIT_PTR(s)[12]; UNIT_PTR(d)[12] = UNIT_PTR(s)[15]; UNIT_PTR(d)[15] = t;\n    t = UNIT_PTR(s)[13]; UNIT_PTR(d)[ 3] = UNIT_PTR(s)[14]; UNIT_PTR(d)[14] = t;\n#elif UNIT_BITS == 32\n    UNIT_PTR(d)[0] = bswap_32(UNIT_PTR(s)[0]); UNIT_PTR(d)[1] = bswap_32(UNIT_PTR(s)[1]);\n    UNIT_PTR(d)[2] = bswap_32(UNIT_PTR(s)[2]); UNIT_PTR(d)[3] = bswap_32(UNIT_PTR(s)[3]);\n#else\n    UI32_PTR(d)[0] = bswap_32(UI32_PTR(s)[0]); UI32_PTR(d)[1] = bswap_32(UI32_PTR(s)[1]);\n    UI32_PTR(d)[2] = bswap_32(UI32_PTR(s)[2]); UI32_PTR(d)[3] = bswap_32(UI32_PTR(s)[3]);\n#endif\n}\n\n/* byte swap within 64-bit words in a 16 byte block; don't move 64-bit words */\nmh_decl void bswap64_block(void *d, const void* s)\n{\n#if UNIT_BITS == 8\n    uint8_t t;\n    t = UNIT_PTR(s)[ 0]; UNIT_PTR(d)[ 0] = UNIT_PTR(s)[ 7]; UNIT_PTR(d)[ 7] = t;\n    t = UNIT_PTR(s)[ 1]; UNIT_PTR(d)[ 1] = UNIT_PTR(s)[ 6]; UNIT_PTR(d)[ 6] = t;\n    t = UNIT_PTR(s)[ 2]; UNIT_PTR(d)[ 2] = UNIT_PTR(s)[ 5]; UNIT_PTR(d)[ 5] = t;\n    t = UNIT_PTR(s)[ 3]; UNIT_PTR(d)[ 3] = UNIT_PTR(s)[ 3]; UNIT_PTR(d) [3] = t;\n    t = UNIT_PTR(s)[ 8]; UNIT_PTR(d)[ 8] = UNIT_PTR(s)[15]; UNIT_PTR(d)[15] = t;\n    t = UNIT_PTR(s)[ 9]; UNIT_PTR(d)[ 9] = UNIT_PTR(s)[14]; UNIT_PTR(d)[14] = t;\n    t = UNIT_PTR(s)[10]; UNIT_PTR(d)[10] = UNIT_PTR(s)[13]; UNIT_PTR(d)[13] = t;\n    t = UNIT_PTR(s)[11]; UNIT_PTR(d)[11] = UNIT_PTR(s)[12]; UNIT_PTR(d)[12] = t;\n#elif UNIT_BITS == 32\n    uint32_t t;\n    t = bswap_32(UNIT_PTR(s)[0]); UNIT_PTR(d)[0] = bswap_32(UNIT_PTR(s)[1]); UNIT_PTR(d)[1] = t;\n    t = bswap_32(UNIT_PTR(s)[2]); UNIT_PTR(d)[2] = bswap_32(UNIT_PTR(s)[2]); UNIT_PTR(d)[3] = t;\n#else\n    UNIT_PTR(d)[0] = bswap_64(UNIT_PTR(s)[0]);  UNIT_PTR(d)[1] = bswap_64(UNIT_PTR(s)[1]); \n#endif\n}\n\nmh_decl void bswap128_block(void *d, const void* s)\n{\n#if UNIT_BITS == 8\n    uint8_t t;\n    t = UNIT_PTR(s)[0]; UNIT_PTR(d)[0] = UNIT_PTR(s)[15]; UNIT_PTR(d)[15] = t;\n    t = UNIT_PTR(s)[1]; UNIT_PTR(d)[1] = UNIT_PTR(s)[14]; UNIT_PTR(d)[14] = t;\n    t = UNIT_PTR(s)[2]; UNIT_PTR(d)[2] = UNIT_PTR(s)[13]; UNIT_PTR(d)[13] = t;\n    t = UNIT_PTR(s)[3]; UNIT_PTR(d)[3] = UNIT_PTR(s)[12]; UNIT_PTR(d)[12] = t;\n    t = UNIT_PTR(s)[4]; UNIT_PTR(d)[4] = UNIT_PTR(s)[11]; UNIT_PTR(d)[11] = t;\n    t = UNIT_PTR(s)[5]; UNIT_PTR(d)[5] = UNIT_PTR(s)[10]; UNIT_PTR(d)[10] = t;\n    t = UNIT_PTR(s)[6]; UNIT_PTR(d)[6] = UNIT_PTR(s)[ 9]; UNIT_PTR(d)[ 9] = t;\n    t = UNIT_PTR(s)[7]; UNIT_PTR(d)[7] = UNIT_PTR(s)[ 8]; UNIT_PTR(d)[ 8] = t;\n#elif UNIT_BITS == 32\n    uint32_t t;\n    t = bswap_32(UNIT_PTR(s)[0]); UNIT_PTR(d)[0] = bswap_32(UNIT_PTR(s)[3]); UNIT_PTR(d)[3] = t;\n    t = bswap_32(UNIT_PTR(s)[1]); UNIT_PTR(d)[1] = bswap_32(UNIT_PTR(s)[2]); UNIT_PTR(d)[2] = t;\n#else\n    uint64_t t;\n    t = bswap_64(UNIT_PTR(s)[0]); UNIT_PTR(d)[0] = bswap_64(UNIT_PTR(s)[1]); UNIT_PTR(d)[1] = t;\n#endif\n}\n\n/* platform byte order to big or little endian order for 16, 32 and 64 bit variables */\n\n#if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN\n\n#  define uint16_t_to_le(x) (x) = bswap_16((x))\n#  define uint32_t_to_le(x) (x) = bswap_32((x))\n#  define uint64_t_to_le(x) (x) = bswap_64((x))\n#  define uint16_t_to_be(x)\n#  define uint32_t_to_be(x)\n#  define uint64_t_to_be(x)\n\n#else\n\n#  define uint16_t_to_le(x)\n#  define uint32_t_to_le(x)\n#  define uint64_t_to_le(x)\n#  define uint16_t_to_be(x) (x) = bswap_16((x))\n#  define uint32_t_to_be(x) (x) = bswap_32((x))\n#  define uint64_t_to_be(x) (x) = bswap_64((x))\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/osconfig.h",
    "content": "#ifndef _OSCONFIG_DEFINED\n#define _OSCONFIG_DEFINED\n\n/* Pull in cryptlib-wide configuration options */\n\n#include \"crypt.h\"\n\n/* OpenSSL-specific defines */\n\n#define OPENSSL_EXTERN\textern\n#define OPENSSL_GLOBAL\n#if defined( _WINDOWS ) && !defined( WINDOWS )\t/* Windows */\n  #define WINDOWS\t\t\t\t/* Old format */\n  #define OPENSSL_SYS_WINDOWS\t/* New fomat */\n#endif /* OpenSSL Windows not defined */\n#if defined( _WIN32 )\t\t\t/* Win32 and WinCE */\n  #ifndef WIN32\n\t#define WIN32\t\t\t\t/* Old format OpenSSL Win32 identifier */\n  #endif /* WIN32 */\n  #define OPENSSL_SYS_WIN32\t\t/* New format OpenSSL Win32 identifier */\n  /* Note that the following asm defines are duplicated in misc/os_spec.h, \n\t because the OpenSSL headers are non-orthogonal to the cryptlib ones. \n\t Any changes made here need to be reflected in os_spec.h */\n  #if !( defined( _WIN32_WCE ) || defined( _M_X64 ) || \\\n\t\t defined( __BORLANDC__ ) || defined( NO_ASM ) )\n\t#define USE_ASM\t\t\t\t/* Always enabled for x86 Win32 */\n  #endif /* WinCE || x86-64 || Borland compilers */\n#endif /* OpenSSL Win32 not defined */\n#include <stdlib.h>\t\t\t/* For malloc() */\n#include <string.h>\t\t\t/* For memset() */\n#if defined( USE_ASM ) && defined( __WATCOMC__ )\n  #define ASM_EXPORT\t__cdecl\n#else\n  #define ASM_EXPORT\n#endif /* System-specific interface to ASM files */\n\n/* General defines.  An older generic config from the original OpenSSL \n   version can be found at \n   http://lists.alioth.debian.org/pipermail/pkg-openssl-changes/2005-October/000012.html \n   (which is just the OpenSSL Configure file, posted to the web), the \n   current one is at \n   https://github.com/openssl/openssl/blob/master/Configurations/10-main.conf.\n\n   Alongside all of the portability defines we also define a string \n   SYSTEM_NAME that's used for debugging purposes */\n\n#include <limits.h>\n#if ULONG_MAX > 0xFFFFFFFFUL\n  #define SIXTY_FOUR_BIT\n#else\n  #define THIRTY_TWO_BIT\n#endif /* Machine word size */\n\n/* Aches */\n#ifdef _AIX\n  #define SYSTEM_NAME\t\t\"AIX on PowerPC\"\n  #define B_ENDIAN\n  #define BN_LLONG\n  #define RC4_CHAR\n#endif /* AIX */\n\n/* Alpha */\n#if defined( __osf__ ) || defined( __alpha__ )\n  #define SYSTEM_NAME\t\"DEC Alpha\"\n  #define L_ENDIAN\n  #undef SIXTY_FOUR_BIT\n  #define SIXTY_FOUR_BIT_LONG\n  #define DES_INT\n  #define DES_UNROLL\n  #define DES_RISC1\n#endif /* Alpha */\n\n/* BeOS */\n#ifdef __BEOS__\n  #if defined( __i386__ )\n\t#define SYSTEM_NAME\t\t\"BeOS x86\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #elif defined( __ppc__ )\n\t#define SYSTEM_NAME\t\t\"BeOS PowerPC\"\n\t#define B_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_CHAR\n  #else\n\t#error Need to define CPU type for non-x86/non-PPC BeOS\n  #endif /* BeoS variants */\n#endif /* BeOS */\n\n/* The BSDs and Linux.  For low-level code-generation purposes these are \n   identical, even if they differ at a higher level */\n#if defined( __FreeBSD__ ) || defined( __bsdi__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __linux__ )\n  #if defined( __x86_64__ ) || defined( __amd64__ )\n\t/* 64-bit x86 has both 'long' and 'long long' as 64 bits.  In addition\n\t   we use DES_INT since int's are 64-bit.  We have to check for the\n\t   64-bit x86 variants before the generic ones because they're a\n\t   variation on the generics (e.g. AMD64 defines both __athlon__ and\n\t   __x86_64__, so if we checked for __athlon__ first we'd identify it\n\t   as a generic rather than 64-bit build) */\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux x64\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD x64\"\n\t#endif /* BSD vs. Linux */\n\t#define L_ENDIAN\n\t#undef SIXTY_FOUR_BIT\n\t#define SIXTY_FOUR_BIT_LONG\n\t#define DES_INT\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #elif defined( __i386__ )\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux x86\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD x86\"\n\t#endif /* BSD vs. Linux */\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #elif defined( __aarch64__ ) || defined( __arm64 )\n\t/* We check for Arm64 before generic Arm for the same reasons as\n\t   x64 vs. x86 */\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux Arm64\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD Arm64\"\n\t#endif /* BSD vs. Linux */\n\t#ifdef DATA_BIGENDIAN\n\t  #define B_ENDIAN\n\t#else\n\t  #define L_ENDIAN\n\t#endif\t/* Usually little-endian but may be big-endian */\n\t#undef SIXTY_FOUR_BIT\n\t#define SIXTY_FOUR_BIT_LONG\n\t#define RC4_CHAR\n  #elif defined( __arm ) || defined( __arm__ )\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux Arm\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD Arm\"\n\t#endif /* BSD vs. Linux */\n\t#ifdef DATA_BIGENDIAN\n\t  #define B_ENDIAN\n\t#else\n\t  #define L_ENDIAN\n\t#endif\t/* Usually little-endian but may be big-endian */\n\t#define BN_LLONG\n\t#define DES_RISC1\n  #elif defined( __mips__ )\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux MIPS\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD MIPS\"\n\t#endif /* BSD vs. Linux */\n\t#ifdef DATA_BIGENDIAN\n\t  #define B_ENDIAN\n\t#else\n\t  #define L_ENDIAN\n\t#endif\t/* Usually little-endian but may be big-endian */\n\t#ifndef SIXTY_FOUR_BIT\t/* No built-in define for 64 bit */\n\t  #define BN_LLONG\n\t#endif /* SIXTY_FOUR_BIT */\n\t#define DES_RISC2\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n\t#define RC4_CHAR\n  #elif defined( _ARCH_PPC ) || defined( _ARCH_PPC64 ) || \\\n\t\tdefined( __ppc ) || defined( __ppc__ ) || \\\n\t\tdefined( __powerpc ) || defined( __powerpc__ ) || \\\n\t\tdefined( __powerpc64__ )\n\t#ifdef DATA_LITTLEENDIAN\n\t  #define L_ENDIAN\n\t#else\n\t  #define B_ENDIAN\n\t#endif\t/* Usually big-endian but may be little-endian */\n\t#if defined( _ARCH_PPC64 ) || defined( __powerpc64__ )\n\t  /* int = 32 bits, long/long long = 64 bits */\n\t  #ifdef __linux__\n\t\t#define SYSTEM_NAME\t\"Linux PowerPC 64\"\n\t  #else\n\t\t#define SYSTEM_NAME\t\"BSD PowerPC 64\"\n\t  #endif /* BSD vs. Linux */\n\t  #undef SIXTY_FOUR_BIT\n\t  #define SIXTY_FOUR_BIT_LONG\n\t#else\n\t  #ifdef __linux__\n\t\t#define SYSTEM_NAME\t\"Linux PowerPC\"\n\t  #else\n\t\t#define SYSTEM_NAME\t\"BSD PowerPC\"\n\t  #endif /* BSD vs. Linux */\n\t  #define BN_LLONG\n\t#endif /* PPC 64-bit */\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_CHAR\n  #elif defined( __hppa__ )\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux HPPA\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD HPPA\"\n\t#endif /* BSD vs. Linux */\n\t#define B_ENDIAN\n\t#ifndef SIXTY_FOUR_BIT\t/* No built-in define for 64 bit */\n\t  #define BN_LLONG\n\t#endif /* SIXTY_FOUR_BIT */\n\t#define BN_DIV2W\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define DES_RISC1\n\t#define MD32_XARRAY\n  #elif defined( __sparc__ )\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux Sparc\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD Sparc\"\n\t#endif /* BSD vs. Linux */\n\t#define B_ENDIAN\n\t#ifdef SIXTY_FOUR_BIT\n\t  /* Sparc64 is a bit of a pain, the best multiply op is 32 x 32 -> 64,\n\t\t and there's no 64-bit add with carry/subtract with borrow, so we're\n\t\t better off using 32-bit ops even on a 64-bit architecture */\n\t  #undef SIXTY_FOUR_BIT\t\n\t  #define THIRTY_TWO_BIT\n\t#endif /* SIXTY_FOUR_BIT */\n\t#define BN_LLONG\n\t#define BN_DIV2W\n\t#define DES_UNROLL\n\t#define RC4_CHAR\n  #elif defined( __sh__ )\n\t/* Super-H has defines for subtypes, __sh1__ to __sh3__ and then \n\t   __SH3__ to __SH5__, but we treat them all as the same general \n\t   architecture.\n\t   \n\t   There isn't any official config for Super-H (specifically SH4), the \n\t   following is the config for MIPS which seems to work OK (the only\n\t   one that really matters is BN_LLONG which is generic for any 32-bit\n\t   CPU, Blowfish and RC4 are disabled by default and 3DES isn't used\n\t   much any more) */\n\t#ifdef __linux__\n\t  #define SYSTEM_NAME\t\"Linux SuperH\"\n\t#else\n\t  #define SYSTEM_NAME\t\"BSD SuperH\"\n\t#endif /* BSD vs. Linux */\n\t#ifdef DATA_BIGENDIAN\n\t  #define B_ENDIAN\n\t#else\n\t  #define L_ENDIAN\n\t#endif\t/* Usually little-endian but may be big-endian */\n\t#define BN_LLONG\n\t#define DES_RISC2\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n\t#define RC4_CHAR\n  #else\n\t#error Need to define CPU type for non-x86/Arm/MIPS/PA-Risc/PPC/Sparc Linux\n  #endif /* *BSD/Linux variants */\n#endif /* *BSD/Linux */\n#if defined( __LINUX__ ) && defined( __WATCOMC__ )\n  #define SYSTEM_NAME\t\t\"Linux x86 Watcom C\"\n  #define L_ENDIAN\n  #define BN_LLONG\n  #define RC4_INDEX\n#endif /* Linux */\n\n/* Cray Unicos */\n#ifdef _CRAY\n  /* Crays are big-endian, but if B_ENDIAN is defined the code implicitly\n     assumes 32-bit ints whereas Crays have 64-bit ints and longs.  However,\n     the non-B/L_ENDIAN code happens to work, so we don't define either */\n  #define SYSTEM_NAME\t\t\"Cray\"\n  #undef SIXTY_FOUR_BIT\n  #define SIXTY_FOUR_BIT_LONG\n  #define DES_INT\n#endif /* Cray Unicos */\n\n/* DGUX */\n#ifdef __dgux\n  #define SYSTEM_NAME\t\t\"DGUX\"\n  #define L_ENDIAN\n  #define RC4_INDEX\n  #define DES_UNROLL\n#endif /* DGUX */\n\n/* DOS */\n#if defined( MSDOS ) || defined( __MSDOS__ )\n  #if defined(__WATCOMC__)\n\t/* 32-bit DOS */\n\t#define SYSTEM_NAME\t\t\"32-bit DOS\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define RC4_INDEX\n  #else\n\t/* 16-bit DOS */\n\t#define SYSTEM_NAME\t\t\"16-bit DOS\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_UNROLL\n\t#define DES_PTR\n\t#define RC4_INDEX\n\t#undef THIRTY_TWO_BIT\n\t#define SIXTEEN_BIT\n  #endif /* 16- vs.32-bit DOS */\n#endif /* DOS */\n\n/* Irix */\n#ifdef __sgi\n\n  #define SYSTEM_NAME\t\t\"IRIX MIPS\"\n\n  /* Irix 5.x and lower */\n  #if ( OSVERSION <= 5 )\n\t#define B_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC2\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n\t#define RC4_CHAR\n\n  /* Irix 6.x and higher */\n  #else\n\t#define B_ENDIAN\n\t#define RC4_INDEX\n\t#define RC4_CHAR\n\t#define DES_UNROLL\n\t#define DES_RISC2\n\t#define DES_PTR\n\t/* Pure 64-bit should also define SIXTY_FOUR_BIT_LONG */\n  #endif /* Irix versions */\n#endif /* Irix */\n\n/* Mac */\n#if defined( __MWERKS__ ) || defined( SYMANTEC_C ) || defined( __MRC__ )\n  #define SYSTEM_NAME\t\t\"Macintosh\"\n  #define B_ENDIAN\n  #define BN_LLONG\n  #define DES_UNROLL\n  #define RC4_CHAR\n#endif /* Mac */\n\n/* Mac OS X / iOS */\n#if defined( __APPLE__ ) && !defined( __MAC__ )\n  #include <TargetConditionals.h>\n  #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR || TARGET_OS_WATCH\n\t#define L_ENDIAN\n\t#if defined( __aarch64__ ) || defined( __arm64 )\n\t  #define SYSTEM_NAME\t\"iOS Arm64\"\n\t  #undef SIXTY_FOUR_BIT\n\t  #define SIXTY_FOUR_BIT_LONG\n\t  #define RC4_CHAR\n\t#elif defined( __x86_64__ )\n\t  #define SYSTEM_NAME \"iOS x64\"\n\t  #define L_ENDIAN\n\t  #define DES_INT\n\t  #define DES_RISC1\n\t  #define DES_UNROLL\n\t  #undef SIXTY_FOUR_BIT\n\t  #define SIXTY_FOUR_BIT_LONG\t\n\t#else\n\t  #define SYSTEM_NAME\t\"iOS Arm\"\n\t  #define BN_LLONG\n\t  #define DES_RISC1\n\t#endif /* 64- vs. 32-bit ARM */\n  #elif defined( __ppc__ )\n\t#define SYSTEM_NAME\t\t\"OS X PowerPC\"\n\t#define B_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_CHAR\n  #elif defined( __x86_64__ )\n\t/* See the comment for the BSDs and Linux above */\n\t#define SYSTEM_NAME\t\t\"OS X x64\"\n\t#define L_ENDIAN\n\t#define DES_INT\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#undef SIXTY_FOUR_BIT\n\t#define SIXTY_FOUR_BIT_LONG\n  #else\n\t#define SYSTEM_NAME\t\t\"OS X x86\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #endif /* Mac OS variants */\n#endif /* Mac OS X / iOS */\n\n/* MSDOS */\n#ifdef __MSDOS__\n  #define SYSTEM_NAME\t\t\"DOS 16-bit\"\n  #define L_ENDIAN\n  #define BN_LLONG\n  #define DES_UNROLL\n  #define DES_PTR\n  #define RC4_INDEX\n  #undef THIRTY_TWO_BIT\n  #define SIXTEEN_BIT\n#endif /* __MSDOS__ */\n\n/* MVS */\n#ifdef __MVS__\n  #define SYSTEM_NAME\t\t\"MVS\"\n  #define B_ENDIAN\n  #define BN_LLONG\n#endif /* MVS */\n\n/* NCR MP-RAS */\n#ifdef __UNIX_SV__\n  #define SYSTEM_NAME\t\t\"NCR MP-RAS\"\n  #define L_ENDIAN\n  #define BN_LLONG\n  #define DES_PTR\n  #define DES_RISC1\n  #define DES_UNROLL\n  #define RC4_INDEX\n#endif /* UNIX_SV */\n\n/* Nucleus */\n#if defined( __Nucleus__ )\n  #define SYSTEM_NAME\t\t\"Nucleus\"\n  #ifdef DATA_BIGENDIAN\n\t#define B_ENDIAN\n  #else\n\t#define L_ENDIAN\n  #endif /* Big vs.little-endian */\n  #define BN_LLONG\n  #define DES_RISC1\n#endif /* __Nucleus__ */\n\n/* Palm OS: ARM */\n#if defined( __PALMSOURCE__ )\n  #if defined( __arm ) || defined( __arm__ )\n\t#define SYSTEM_NAME\t\t\"PalmOS Arm\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC1\n  #else\n\t#error Need to define architecture-specific values for crypto code\n  #endif /* Palm OS variants */\n#endif /* Palm OS */\n\n/* PHUX */\n#ifdef __hpux\n\n  #define SYSTEM_NAME\t\t\"HPUX HPPA\"\n\n  /* PHUX 9.x (some versions report it as 09 so we also check for 0) */\n  #if ( OSVERSION == 0 || OSVERSION == 9 )\n\t#define B_ENDIAN\n\t#define BN_DIV2W\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define DES_RISC1\n\t#define MD32_XARRAY\n\n  /* PHUX 10.x, 11.x */\n  #else\n\t#define B_ENDIAN\n\t#ifndef SIXTY_FOUR_BIT\t/* No built-in define for 64 bit */\n\t  #define BN_LLONG\n\t#endif /* SIXTY_FOUR_BIT */\n\t#define BN_DIV2W\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define DES_RISC1\n\t#define MD32_XARRAY\n\t/* Pure 64-bit should also define SIXTY_FOUR_BIT_LONG RC4_INDEX\n\t   RC4_CHAR DES_INT */\n  #endif /* PHUX versions */\n#endif /* PHUX */\n\n/* QNX */\n#ifdef __QNX__\n  #define SYSTEM_NAME\t\t\"QNX x86\"\n  #define L_ENDIAN\n  #define BN_LLONG\n  #define DES_PTR\n  #define DES_RISC1\n  #define DES_UNROLL\n  #define RC4_INDEX\n  #if OSVERSION <= 4\n\t/* The Watcom compiler can't handle 64-bit ints even though the hardware\n\t   can, so we have to build it as 16-bit code with 16x16 -> 32 multiplies\n\t   rather than 32x32 -> 64 */\n\t#undef THIRTY_TWO_BIT\n\t#define SIXTEEN_BIT\n  #endif /* QNX 4.x */\n#endif /* QNX */\n\n/* SCO/UnixWare */\n#ifdef __SCO_VERSION__\n\n  #define SYSTEM_NAME\t\t\"SCO x86\"\n\n  /* SCO gcc */\n  #if defined( __GNUC__ )\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n\n  /* SCO cc */\n  #else\n    #define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #endif /* SCO\tgcc/cc */\n#endif /* SCO */\n\n/* Solaris */\n#if defined( sun ) || defined( __sun )\n\n  /* Solaris Sparc */\n  #if defined( sparc ) || defined( __sparc )\n\t#define B_ENDIAN\n\n\t/* Solaris Sparc gcc */\n\t#if defined( __GNUC__ )\n\t  #if defined( __sparc64 ) || defined( __arch64__ )\n\t\t#define SYSTEM_NAME\t\"Solaris Sparc64 gcc\"\n\t\t#define DES_INT \n\t\t#define DES_PTR \n\t\t#define DES_RISC1 \n\t\t#define DES_UNROLL \n\t\t#define RC4_CHAR\n\t\t#ifdef SIXTY_FOUR_BIT\n\t\t  /* Sparc64 is a bit of a pain, the best multiply op is \n\t\t     32 x 32 -> 64, and there's no 64-bit add with carry/subtract \n\t\t\t with borrow, so we're better off using 32-bit ops even on a \n\t\t\t 64-bit architecture */\n\t\t  #undef SIXTY_FOUR_BIT\t\n\t\t  #define THIRTY_TWO_BIT\n\t\t#endif /* SIXTY_FOUR_BIT */\n\t\t#define BN_LLONG\n\t  #else\n\t    /* No obvious test for 32-bit Sparc */\n\t\t#define SYSTEM_NAME\t\"Solaris Sparc gcc\"\n\t\t#define BN_DIV2W\n\t\t#define BN_LLONG\n\t\t#define DES_UNROLL\n\t\t#define RC4_CHAR\n\t  #endif /* 64- vs 32-bit */\n\n\t/* Solaris Sparc Sun C */\n\t#elif defined( __SUNPRO_C )\n\t  #if defined( __sparc64 ) || defined( __arch64__ )\n\t\t#define SYSTEM_NAME\t\"Solaris Sparc64 SunPro\"\n\t\t#define DES_INT \n\t\t#define DES_PTR \n\t\t#define DES_RISC1\n\t\t#define DES_UNROLL \n\t\t#define RC4_CHAR \n\t\t#ifdef SIXTY_FOUR_BIT\n\t\t  /* Sparc64 is a bit of a pain, the best multiply op is \n\t\t     32 x 32 -> 64, and there's no 64-bit add with carry/subtract \n\t\t\t with borrow, so we're better off using 32-bit ops even on a \n\t\t\t 64-bit architecture */\n\t\t  #undef SIXTY_FOUR_BIT\t\n\t\t  #define THIRTY_TWO_BIT\n\t\t#endif /* SIXTY_FOUR_BIT */\n\t\t#define BN_LLONG\n\t  #else\n\t    /* No obvious test for 32-bit Sparc */\n\t\t#define SYSTEM_NAME\t\"Solaris Sparc SunPro\"\n\t\t#define BN_DIV2W\n\t\t#define BN_LLONG\n\t\t#define DES_PTR\n\t\t#define DES_RISC1\n\t\t#define DES_UNROLL\n\t\t#define RC4_CHAR\n\t  #endif /* 64- vs 32-bit */\n\n\t#else\n\t  #error Unknown Sun architecture (neither x86/x64 nor Sparc) encountered\n\t#endif /* Solaris Sparc */\n\n  /* Solaris x86 */\n  #else\n\t#define L_ENDIAN\n\n\t/* Solaris x86 gcc */\n\t#if defined( __GNUC__ )\n\t  #if defined( __x86_64__ )\n\t\t#define SYSTEM_NAME\t\"Solaris x64 gcc\"\n\t\t#define DES_INT \n\t\t#define DES_UNROLL\n\t\t#undef SIXTY_FOUR_BIT\n\t\t#define SIXTY_FOUR_BIT_LONG \n\t  #elif defined( __i386__ )\n\t\t#define SYSTEM_NAME\t\"Solaris x86 gcc\"\n\t\t#define BN_LLONG\n\t\t#define DES_PTR\n\t\t#define DES_RISC1\n\t\t#define DES_UNROLL\n\t\t#define RC4_INDEX\n\t  #else\n\t\t#error Unknown Sun x86 architecture (neither 32- nor 64-bit) encountered\n\t  #endif /* 32- vs 64-bit */\n\n\t/* Solaris x86 Sun C */\n\t#elif defined( __SUNPRO_C )\n\t  #if defined( __x86_64__ ) || defined( __x86_64 )\n\t\t#define SYSTEM_NAME\t\"Solaris x64 SunPro\"\n\t\t#define DES_INT\n\t\t#define DES_UNROLL\n\t\t#undef SIXTY_FOUR_BIT\n\t\t#define SIXTY_FOUR_BIT_LONG \n\t  #elif defined( __i386__ ) || defined( __i386 ) \n\t\t#define SYSTEM_NAME\t\"Solaris x86 SunPro\"\n\t\t#define BN_LLONG\n\t\t#define DES_PTR\n\t\t#define DES_UNROLL\n\t\t#define RC4_CHAR\n\t  #else\n\t\t#error Unknown Sun x86 architecture (neither 32- nor 64-bit) encountered\n\t  #endif /* 32- vs 64-bit */\n\n\t#else\n\t  #error Unknown Sun architecture (neither x86/x64 nor Sparc) encountered\n\t#endif /* Solaris x86 */\n  #endif /* Solaris Sparc vs x86 */\n#endif /* Slowaris */\n\n/* Symbian OS: Usually ARM, but we may be running under the x86 emulator */\n#if defined( __SYMBIAN32__ )\n  #if defined( __MARM__ )\n\t#define SYSTEM_NAME\t\t\"Symbian Arm\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC1\n  #elif defined( __EMU_SYMBIAN_OS__ )\n\t#define SYSTEM_NAME\t\t\"Symbian Arm emulator\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #else\n\t#error Need to define architecture-specific values for crypto code\n  #endif /* Symbian OS variants */\n#endif /* Symbian OS */\n\n/* Tandem NSK/OSS */\n#ifdef __TANDEM\n  #define SYSTEM_NAME\t\t\"Tandem NSK\"\n  #define B_ENDIAN\n  #define DES_RISC2\n  #define DES_PTR\n  #define DES_UNROLL\n  #define RC4_INDEX\n  #define RC4_CHAR\n#endif /* Tandem */\n\n/* Ultrix */\n#ifdef __ultrix__\n  #define SYSTEM_NAME\t\t\"Ultrix\"\n  #define L_ENDIAN\n  #define DES_PTR\n  #define DES_RISC2\n  #define DES_UNROLL\n#endif /* Ultrix */\n\n/* VM/CMS */\n#ifdef __VMCMS__\n  #define SYSTEM_NAME\t\t\"VM/CMS\"\n  #define B_ENDIAN\n#endif /* VM/CMS */\n\n/* Windows */\n#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) )\n  #define L_ENDIAN\n\n  /* VC++ */\n  #if defined( _MSC_VER )\n\n\t/* VS 64-bit */\n\t#if defined( _M_X64 )\n\t  /* Win64's ULONG_MAX (via limits.h) is 32 bits so the system isn't\n\t     detected as a 64-bit one, to fix this we manually override the\n\t     detected machine word size here */\n\t  #define SYSTEM_NAME\t\"Win64 Visual Studio\"\n\t  #undef THIRTY_TWO_BIT\n\t  #define SIXTY_FOUR_BIT \n\t  #define DES_INT \n\n\t/* VC++ 32-bit */\n\t#elif ( _MSC_VER >= 1000 )\n\t  #define SYSTEM_NAME\t\"Win32 Visual Studio\"\n\t  #define BN_LLONG\n\t  #define RC4_INDEX\n\n\t/* VC++ 16-bit */\n\t#else\n\t  #define SYSTEM_NAME\t\"Win16 Visual Studio\"\n\t  #define BN_LLONG\n\t  #define DES_UNROLL\n\t  #define DES_PTR\n\t  #define RC4_INDEX\n\t  #undef THIRTY_TWO_BIT\n\t  #define SIXTEEN_BIT\n\t#endif /* VC++ 32 vs 16-bit */\n\n  /* BC++ */\n  #elif defined( __BORLANDC__ )\n    #define SYSTEM_NAME\t\t\"Win32 Borland C\"\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define RC4_INDEX\n\n  /* gcc */\n  #else\n    #define SYSTEM_NAME\t\t\"Win32 gcc\"\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #endif /* Assorted Windows compilers */\n#endif /* Windows */\n#ifdef __CYGWIN__\n  #define SYSTEM_NAME\t\t\"cygwin x86\"\n  #define L_ENDIAN\n  #define BN_LLONG\n  #define DES_PTR\n  #define DES_RISC1\n  #define DES_UNROLL\n  #define RC4_INDEX\n#endif /* gcc native under Cygwin (i.e. not a Cygwin-hosted\n\t\t  cross-development toolchain */\n\n/* Embeded OSes get a bit complicated because they're usually cross-\n   compiled, first we try for OS-specific options, then we try for the most \n   obvious generic options like the GNU toolchain, and finally if we can't \n   find anything we bail out with an error message */\n\n#if defined( USE_EMBEDDED_OS )\n\n  /* Xilinx XMK */\n  #if defined ( _XMK ) || defined( __XMK__ )\n\t#if defined( __mb__ )\n\t  #define SYSTEM_NAME\t\"Xilinx MicroBlaze\"\n\t  #define B_ENDIAN\n\t  /* Not sure what other options the MicroBlaze build should enable... */\n\t#elif defined( __ppc__ ) || defined( __powerpc ) || defined( __powerpc__ )\n\t  #define SYSTEM_NAME\t\"Xilinx PowerPC\"\n\t  #ifdef DATA_LITTLEENDIAN\n\t\t#define L_ENDIAN\n\t  #else\n\t\t#define B_ENDIAN\n\t  #endif\t/* Usually big-endian but may be little-endian */\n\t  #define BN_LLONG\n\t  #define DES_RISC1\n\t  #define DES_UNROLL\n\t  #define RC4_CHAR\n\t#else\n\t  #error Need to define CPU type for non-MicroBlaze/non-PPC XMK.\n\t#endif /* XMK target variants */\n\n  /* Generic gcc */\n  #elif defined( __i386__ )\n\t#define SYSTEM_NAME\t\t\"Embedded x86 gcc\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_PTR\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_INDEX\n  #elif defined( __ppc__ ) || defined( __powerpc ) || defined( __powerpc__ )\n\t#define SYSTEM_NAME\t\t\"Embedded PowerPC gcc\"\n\t#ifdef DATA_LITTLEENDIAN\n\t  #define L_ENDIAN\n\t#else\n\t  #define B_ENDIAN\n\t#endif\t/* Usually big-endian but may be little-endian */\n\t#define BN_LLONG\n\t#define DES_RISC1\n\t#define DES_UNROLL\n\t#define RC4_CHAR\n  #elif defined( __arm ) || defined( __arm__ )\n\t#define SYSTEM_NAME\t\t\"Embedded Arm gcc\"\n\t#define L_ENDIAN\n\t#define BN_LLONG\n\t#define DES_RISC1\n\n  /* IAR and TI ARM compilers */\n  #elif defined( __IAR_SYSTEMS_ICC__ ) || defined( __TI_ARM__ )\n\t#define SYSTEM_NAME\t\t\"Embedded Arm IAR/TI\"\n\t#ifdef DATA_LITTLEENDIAN\n\t  #define L_ENDIAN\n\t#else\n\t  #define B_ENDIAN\n\t#endif\n\t#define BN_LLONG\n\t#define DES_RISC1\n\n  /* Generic 68K */\n  #elif defined( __m68k__  )\n\t/* This one is CISC-y enough that any of the (mostly) RISC-specific\n\t   optimisations won't have much effect, so the generic code is as good\n\t   as any */\n\t#define SYSTEM_NAME\t\t\"Embedded 68K\"\n\t#define B_ENDIAN\n\n  /* VC++ test build */\n  #elif defined( _MSC_VER )\n\n\t/* VS 64-bit */\n\t#if defined( _M_X64 )\n\t  /* Win64's ULONG_MAX (via limits.h) is 32 bits so the system isn't\n\t     detected as a 64-bit one, to fix this we manually override the\n\t     detected machine word size here */\n\t  #undef SYSTEM_NAME\n\t  #define SYSTEM_NAME\t\"Embedded Win64 emulated cross-compile\"\n\t  #undef THIRTY_TWO_BIT\n\t  #define SIXTY_FOUR_BIT \n\t  #define DES_INT \n\n\t/* VC++ 32-bit */\n\t#elif ( _MSC_VER >= 1000 )\n\t  #undef SYSTEM_NAME\n\t  #define SYSTEM_NAME\t\"Embedded Win32 emulated cross-compile\"\n\t  #define BN_LLONG\n\t  #define RC4_INDEX\n\n\t#endif /* VC++ 32 vs 16-bit */\n\n  /* We need the developer's help to sort it out */\n  #else\n\t#error Need to configure the crypto build options for your toolchain.\n  #endif /* Embedded OS variants */\n#endif /* Embedded OSes */\n\n/* Make sure that we weren't missed out.  See the comment in the Cray \n   section for the exception for Crays */\n\n#if !defined( _CRAY ) && !defined( L_ENDIAN ) && !defined( B_ENDIAN )\n  #error You need to add system-specific configuration settings to osconfig.h.\n#endif /* Endianness not defined */\n#if defined( L_ENDIAN ) && defined( B_ENDIAN )\n  #error Incorrect endianness detection in osconfig.h, both L_ENDIAN and B_ENDIAN are defined.\n#endif /* Endianness defined erratically */\n#if defined( CHECK_ENDIANNESS ) && !defined( OSX_UNIVERSAL_BINARY )\n  /* One-off check in des_enc.c, however for OS X universal (fat) binaries\n\t we're effectively cross-compiling for multiple targets so we don't\n\t perform the check, which would yield false positives */\n  #if defined( DATA_LITTLEENDIAN ) && defined( DATA_BIGENDIAN )\n\t#error Incorrect endianness detection in crypt.h, \n\t#error both DATA_LITTLEENDIAN and DATA_BIGENDIAN are defined.\n  #endif /* Global endianness defined erratically */\n  #if ( defined( L_ENDIAN ) && !defined( DATA_LITTLEENDIAN ) )\n\t#error You need to synchronise the endianness configuration settings \n\t#error in osconfig.h and crypt.h.  The cryptlib config is set to \n\t#error DATA_BIGENDIAN but osconfig.h has detected L_ENDIAN.\n  #endif /* L_ENDIAN && !DATA_LITTLEENDIAN */\n  #if ( defined( B_ENDIAN ) && !defined( DATA_BIGENDIAN ) )\n\t#error You need to synchronise the endianness configuration settings \n\t#error in osconfig.h and crypt.h.  The cryptlib config is set to \n\t#error DATA_LITTLEENDIAN but osconfig.h has detected B_ENDIAN.\n  #endif /* B_ENDIAN && !DATA_BIGENDIAN */\n#endif /* One-off check */\n\n#endif /* _OSCONFIG_DEFINED */\n"
  },
  {
    "path": "deps/cl345/crypt/rc2.h",
    "content": "/* crypto/rc2/rc2.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_RC2_H\n#define HEADER_RC2_H\n\n#ifdef NO_RC2\n#error RC2 is disabled.\n#endif\n\n#define RC2_ENCRYPT\t1\n#define RC2_DECRYPT\t0\n\n#define RC2_BLOCK\t8\n#define RC2_KEY_LENGTH\t16\n#define RC2_INT unsigned int\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct rc2_key_st\n\t{\n\tRC2_INT data[64];\n\t} RC2_KEY;\n\n\nvoid RC2_set_key(RC2_KEY *key, int len, const unsigned char *data,int bits);\nvoid RC2_ecb_encrypt(const unsigned char *in,unsigned char *out,RC2_KEY *key,\n\t\t     int enc);\nvoid RC2_encrypt(unsigned long *data,RC2_KEY *key);\nvoid RC2_decrypt(unsigned long *data,RC2_KEY *key);\nvoid RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\tRC2_KEY *ks, unsigned char *iv, int enc);\nvoid RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,\n\t\t       long length, RC2_KEY *schedule, unsigned char *ivec,\n\t\t       int *num, int enc);\nvoid RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,\n\t\t       long length, RC2_KEY *schedule, unsigned char *ivec,\n\t\t       int *num);\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/rc2cbc.c",
    "content": "/* crypto/rc2/rc2_cbc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"rc2.h\"\n  #include \"rc2locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/rc2.h\"\n  #include \"crypt/rc2locl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC2\n\nvoid RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,\n\t     RC2_KEY *ks, unsigned char *iv, int encrypt)\n\t{\n\tregister unsigned long tin0,tin1;\n\tregister unsigned long tout0,tout1,xor0,xor1;\n\tregister long l=length;\n\tunsigned long tin[2];\n\n\tif (encrypt)\n\t\t{\n\t\tc2l(iv,tout0);\n\t\tc2l(iv,tout1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0);\n\t\t\tc2l(in,tin1);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tRC2_encrypt(tin,ks);\n\t\t\ttout0=tin[0]; l2c(tout0,out);\n\t\t\ttout1=tin[1]; l2c(tout1,out);\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2ln(in,tin0,tin1,l+8);\n\t\t\ttin0^=tout0;\n\t\t\ttin1^=tout1;\n\t\t\ttin[0]=tin0;\n\t\t\ttin[1]=tin1;\n\t\t\tRC2_encrypt(tin,ks);\n\t\t\ttout0=tin[0]; l2c(tout0,out);\n\t\t\ttout1=tin[1]; l2c(tout1,out);\n\t\t\t}\n\t\tl2c(tout0,iv);\n\t\tl2c(tout1,iv);\n\t\t}\n\telse\n\t\t{\n\t\tc2l(iv,xor0);\n\t\tc2l(iv,xor1);\n\t\tiv-=8;\n\t\tfor (l-=8; l>=0; l-=8)\n\t\t\t{\n\t\t\tc2l(in,tin0); tin[0]=tin0;\n\t\t\tc2l(in,tin1); tin[1]=tin1;\n\t\t\tRC2_decrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2c(tout0,out);\n\t\t\tl2c(tout1,out);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tif (l != -8)\n\t\t\t{\n\t\t\tc2l(in,tin0); tin[0]=tin0;\n\t\t\tc2l(in,tin1); tin[1]=tin1;\n\t\t\tRC2_decrypt(tin,ks);\n\t\t\ttout0=tin[0]^xor0;\n\t\t\ttout1=tin[1]^xor1;\n\t\t\tl2cn(tout0,tout1,out,l+8);\n\t\t\txor0=tin0;\n\t\t\txor1=tin1;\n\t\t\t}\n\t\tl2c(xor0,iv);\n\t\tl2c(xor1,iv);\n\t\t}\n\ttin0=tin1=tout0=tout1=xor0=xor1=0;\n\ttin[0]=tin[1]=0;\n\t}\n\nvoid RC2_encrypt(unsigned long *d, RC2_KEY *key)\n\t{\n\tint i,n;\n\tregister RC2_INT *p0,*p1;\n\tregister RC2_INT x0,x1,x2,x3,t;\n\tunsigned long l;\n\n\tl=d[0];\n\tx0=(RC2_INT)l&0xffff;\n\tx1=(RC2_INT)(l>>16L);\n\tl=d[1];\n\tx2=(RC2_INT)l&0xffff;\n\tx3=(RC2_INT)(l>>16L);\n\n\tn=3;\n\ti=5;\n\n\tp0=p1= &(key->data[0]);\n\tfor (;;)\n\t\t{\n\t\tt=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff;\n\t\tx0=(t<<1)|(t>>15);\n\t\tt=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff;\n\t\tx1=(t<<2)|(t>>14);\n\t\tt=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff;\n\t\tx2=(t<<3)|(t>>13);\n\t\tt=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff;\n\t\tx3=(t<<5)|(t>>11);\n\n\t\tif (--i == 0)\n\t\t\t{\n\t\t\tif (--n == 0) break;\n\t\t\ti=(n == 2)?6:5;\n\n\t\t\tx0+=p1[x3&0x3f];\n\t\t\tx1+=p1[x0&0x3f];\n\t\t\tx2+=p1[x1&0x3f];\n\t\t\tx3+=p1[x2&0x3f];\n\t\t\t}\n\t\t}\n\n\td[0]=(unsigned long)(x0&0xffff)|((unsigned long)(x1&0xffff)<<16L);\n\td[1]=(unsigned long)(x2&0xffff)|((unsigned long)(x3&0xffff)<<16L);\n\t}\n\nvoid RC2_decrypt(unsigned long *d, RC2_KEY *key)\n\t{\n\tint i,n;\n\tregister RC2_INT *p0,*p1;\n\tregister RC2_INT x0,x1,x2,x3,t;\n\tunsigned long l;\n\n\tl=d[0];\n\tx0=(RC2_INT)l&0xffff;\n\tx1=(RC2_INT)(l>>16L);\n\tl=d[1];\n\tx2=(RC2_INT)l&0xffff;\n\tx3=(RC2_INT)(l>>16L);\n\n\tn=3;\n\ti=5;\n\n\tp0= &(key->data[63]);\n\tp1= &(key->data[0]);\n\tfor (;;)\n\t\t{\n\t\tt=((x3<<11)|(x3>>5))&0xffff;\n\t\tx3=(t-(x0& ~x2)-(x1&x2)- *(p0--))&0xffff;\n\t\tt=((x2<<13)|(x2>>3))&0xffff;\n\t\tx2=(t-(x3& ~x1)-(x0&x1)- *(p0--))&0xffff;\n\t\tt=((x1<<14)|(x1>>2))&0xffff;\n\t\tx1=(t-(x2& ~x0)-(x3&x0)- *(p0--))&0xffff;\n\t\tt=((x0<<15)|(x0>>1))&0xffff;\n\t\tx0=(t-(x1& ~x3)-(x2&x3)- *(p0--))&0xffff;\n\n\t\tif (--i == 0)\n\t\t\t{\n\t\t\tif (--n == 0) break;\n\t\t\ti=(n == 2)?6:5;\n\n\t\t\tx3=(x3-p1[x2&0x3f])&0xffff;\n\t\t\tx2=(x2-p1[x1&0x3f])&0xffff;\n\t\t\tx1=(x1-p1[x0&0x3f])&0xffff;\n\t\t\tx0=(x0-p1[x3&0x3f])&0xffff;\n\t\t\t}\n\t\t}\n\n\td[0]=(unsigned long)(x0&0xffff)|((unsigned long)(x1&0xffff)<<16L);\n\td[1]=(unsigned long)(x2&0xffff)|((unsigned long)(x3&0xffff)<<16L);\n\t}\n#endif /* USE_RC2 */\n"
  },
  {
    "path": "deps/cl345/crypt/rc2ecb.c",
    "content": "/* crypto/rc2/rc2_ecb.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"rc2.h\"\n  #include \"rc2locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/rc2.h\"\n  #include \"crypt/rc2locl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC2\n\n/* RC2 as implemented frm a posting from\n * Newsgroups: sci.crypt\n * Sender: pgut01@cs.auckland.ac.nz (Peter Gutmann)\n * Subject: Specification for Ron Rivests Cipher No.2\n * Message-ID: <4fk39f$f70@net.auckland.ac.nz>\n * Date: 11 Feb 1996 06:45:03 GMT\n */\n\nvoid RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, RC2_KEY *ks,\n\t\t     int encrypt)\n\t{\n\tunsigned long l,d[2];\n\n\tc2l(in,l); d[0]=l;\n\tc2l(in,l); d[1]=l;\n\tif (encrypt)\n\t\tRC2_encrypt(d,ks);\n\telse\n\t\tRC2_decrypt(d,ks);\n\tl=d[0]; l2c(l,out);\n\tl=d[1]; l2c(l,out);\n\tl=d[0]=d[1]=0;\n\t}\n#endif /* USE_RC2 */\n"
  },
  {
    "path": "deps/cl345/crypt/rc2locl.h",
    "content": "/* crypto/rc2/rc2_locl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#undef c2l\n#define c2l(c,l)\t(l =((unsigned long)(*((c)++)))    , \\\n\t\t\t l|=((unsigned long)(*((c)++)))<< 8L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<16L, \\\n\t\t\t l|=((unsigned long)(*((c)++)))<<24L)\n\n/* NOTE - c is not incremented as per c2l */\n#undef c2ln\n#define c2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))<<24L; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<<16L; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<< 8L; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))));     \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))<<24L; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<<16L; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<< 8L; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))));     \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef l2c\n#define l2c(l,c)\t(*((c)++)=(unsigned char)(((l)     )&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n\t\t\t *((c)++)=(unsigned char)(((l)>>24L)&0xff))\n\n/* NOTE - c is not incremented as per l2c */\n#undef l2cn\n#define l2cn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per n2l */\n#define n2ln(c,l1,l2,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tl1=l2=0; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: l2 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 7: l2|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 6: l2|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 5: l2|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\tcase 4: l1 =((unsigned long)(*(--(c))))    ; \\\n\t\t\tcase 3: l1|=((unsigned long)(*(--(c))))<< 8; \\\n\t\t\tcase 2: l1|=((unsigned long)(*(--(c))))<<16; \\\n\t\t\tcase 1: l1|=((unsigned long)(*(--(c))))<<24; \\\n\t\t\t\t} \\\n\t\t\t}\n\n/* NOTE - c is not incremented as per l2n */\n#define l2nn(l1,l2,c,n)\t{ \\\n\t\t\tc+=n; \\\n\t\t\tswitch (n) { \\\n\t\t\tcase 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \\\n\t\t\tcase 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \\\n\t\t\tcase 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \\\n\t\t\tcase 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \\\n\t\t\tcase 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \\\n\t\t\tcase 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \\\n\t\t\tcase 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \\\n\t\t\tcase 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \\\n\t\t\t\t} \\\n\t\t\t}\n\n#undef n2l\n#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \\\n                         l|=((unsigned long)(*((c)++)))<<16L, \\\n                         l|=((unsigned long)(*((c)++)))<< 8L, \\\n                         l|=((unsigned long)(*((c)++))))\n\n#undef l2n\n#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \\\n                         *((c)++)=(unsigned char)(((l)     )&0xff))\n\n#define C_RC2(n) \\\n\tt=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff; \\\n\tx0=(t<<1)|(t>>15); \\\n\tt=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff; \\\n\tx1=(t<<2)|(t>>14); \\\n\tt=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff; \\\n\tx2=(t<<3)|(t>>13); \\\n\tt=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff; \\\n\tx3=(t<<5)|(t>>11);\n\n"
  },
  {
    "path": "deps/cl345/crypt/rc2skey.c",
    "content": "/* crypto/rc2/rc2_skey.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"rc2.h\"\n  #include \"rc2locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/rc2.h\"\n  #include \"crypt/rc2locl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC2\n\nstatic unsigned char key_table[256]={\n\t0xd9,0x78,0xf9,0xc4,0x19,0xdd,0xb5,0xed,0x28,0xe9,0xfd,0x79,\n\t0x4a,0xa0,0xd8,0x9d,0xc6,0x7e,0x37,0x83,0x2b,0x76,0x53,0x8e,\n\t0x62,0x4c,0x64,0x88,0x44,0x8b,0xfb,0xa2,0x17,0x9a,0x59,0xf5,\n\t0x87,0xb3,0x4f,0x13,0x61,0x45,0x6d,0x8d,0x09,0x81,0x7d,0x32,\n\t0xbd,0x8f,0x40,0xeb,0x86,0xb7,0x7b,0x0b,0xf0,0x95,0x21,0x22,\n\t0x5c,0x6b,0x4e,0x82,0x54,0xd6,0x65,0x93,0xce,0x60,0xb2,0x1c,\n\t0x73,0x56,0xc0,0x14,0xa7,0x8c,0xf1,0xdc,0x12,0x75,0xca,0x1f,\n\t0x3b,0xbe,0xe4,0xd1,0x42,0x3d,0xd4,0x30,0xa3,0x3c,0xb6,0x26,\n\t0x6f,0xbf,0x0e,0xda,0x46,0x69,0x07,0x57,0x27,0xf2,0x1d,0x9b,\n\t0xbc,0x94,0x43,0x03,0xf8,0x11,0xc7,0xf6,0x90,0xef,0x3e,0xe7,\n\t0x06,0xc3,0xd5,0x2f,0xc8,0x66,0x1e,0xd7,0x08,0xe8,0xea,0xde,\n\t0x80,0x52,0xee,0xf7,0x84,0xaa,0x72,0xac,0x35,0x4d,0x6a,0x2a,\n\t0x96,0x1a,0xd2,0x71,0x5a,0x15,0x49,0x74,0x4b,0x9f,0xd0,0x5e,\n\t0x04,0x18,0xa4,0xec,0xc2,0xe0,0x41,0x6e,0x0f,0x51,0xcb,0xcc,\n\t0x24,0x91,0xaf,0x50,0xa1,0xf4,0x70,0x39,0x99,0x7c,0x3a,0x85,\n\t0x23,0xb8,0xb4,0x7a,0xfc,0x02,0x36,0x5b,0x25,0x55,0x97,0x31,\n\t0x2d,0x5d,0xfa,0x98,0xe3,0x8a,0x92,0xae,0x05,0xdf,0x29,0x10,\n\t0x67,0x6c,0xba,0xc9,0xd3,0x00,0xe6,0xcf,0xe1,0x9e,0xa8,0x2c,\n\t0x63,0x16,0x01,0x3f,0x58,0xe2,0x89,0xa9,0x0d,0x38,0x34,0x1b,\n\t0xab,0x33,0xff,0xb0,0xbb,0x48,0x0c,0x5f,0xb9,0xb1,0xcd,0x2e,\n\t0xc5,0xf3,0xdb,0x47,0xe5,0xa5,0x9c,0x77,0x0a,0xa6,0x20,0x68,\n\t0xfe,0x7f,0xc1,0xad,\n\t};\n\n/* It has come to my attention that there are 2 versions of the RC2\n * key schedule.  One which is normal, and anther which has a hook to\n * use a reduced key length.\n * BSAFE uses the 'retarded' version.  What I previously shipped is\n * the same as specifying 1024 for the 'bits' parameter.  Bsafe uses\n * a version where the bits parameter is the same as len*8 */\n\n#if defined( _WIN32_WCE ) && defined( ARMV4 ) && defined( NDEBUG )\n  #pragma optimize( \"g\", off )\n#endif /* pcg - eVC++ 4.0 ARMv4 optimiser bug */\n\nvoid RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)\n\t{\n\tint i,j;\n\tunsigned char *k;\n\tRC2_INT *ki;\n\tunsigned int c,d;\n\n\tk= (unsigned char *)&(key->data[0]);\n\t*k=0; /* for if there is a zero length key */\n\n\tif (len > 128) len=128;\n\tif (bits <= 0) bits=1024;\n\tif (bits > 1024) bits=1024;\n\n\tfor (i=0; i<len; i++)\n\t\tk[i]=data[i];\n\n\t/* expand table */\n\td=k[len-1];\n\tj=0;\n\tfor (i=len; i < 128; i++,j++)\n\t\t{\n\t\td=key_table[(k[j]+d)&0xff];\n\t\tk[i]=(unsigned char)d;\n\t\t}\n\n\t/* hmm.... key reduction to 'bits' bits */\n\n\tj=(bits+7)>>3;\n\ti=128-j;\n\tc= (0xff>>(-bits & 0x07));\n\n\td=key_table[k[i]&c];\n\tk[i]=(unsigned char)d;\n\twhile (i--)\n\t\t{\n\t\td=key_table[k[i+j]^d];\n\t\tk[i]=(unsigned char)d;\n\t\t}\n\n\t/* copy from bytes into RC2_INT's */\n\tki= &(key->data[63]);\n\tfor (i=127; i>=0; i-=2)\n\t\t*(ki--)=((k[i]<<8)|k[i-1])&0xffff;\n\t}\n\n#if defined( _WIN32_WCE ) && defined( ARMV4 ) && defined( NDEBUG )\n  #pragma optimize( \"g\", on )\n#endif /* pcg - eVC++ 4.0 ARMv4 optimiser bug */\n#endif /* USE_RC2 */\n"
  },
  {
    "path": "deps/cl345/crypt/rc4.h",
    "content": "/* crypto/rc4/rc4.h */\n/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_RC4_H\n#define HEADER_RC4_H\n\n#ifndef _OSCONFIG_DEFINED\t\t/* pcg */\n  #if defined( INC_ALL )\n\t#include \"osconfig.h\"\n  #else\n\t#include \"crypt/osconfig.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _OSCONFIG_DEFINED */\n\n#ifdef NO_RC4\n#error RC4 is disabled.\n#endif\n\n#ifdef RC4_CHAR\n  #define RC4_INT unsigned char\n#else\n  #define RC4_INT unsigned int\n#endif /* RC4_INT char vs int */\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\ntypedef struct rc4_key_st\n\t{\n\tRC4_INT x,y;\n\tRC4_INT data[256];\n\t} RC4_KEY;\n\n\nconst char *RC4_options(void);\nvoid RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);\nvoid ASM_EXPORT RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,\n\t\tunsigned char *outdata);\t\t\t\t\t\t\t\t/* pcg */\n\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/rc4enc.c",
    "content": "/* crypto/rc4/rc4_enc.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"rc4.h\"\n  #include \"rc4locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/rc4.h\"\n  #include \"crypt/rc4locl.h\"\n#endif /* Compiler-specific includes */\n\n/* RC4 as implemented from a posting from\n * Newsgroups: sci.crypt\n * From: sterndark@netcom.com (David Sterndark)\n * Subject: RC4 Algorithm revealed.\n * Message-ID: <sternCvKL4B.Hyy@netcom.com>\n * Date: Wed, 14 Sep 1994 06:35:31 GMT\n */\n\nvoid RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata,\n\t     unsigned char *outdata)\n\t{\n        register RC4_INT *d;\n        register RC4_INT x,y,tx,ty;\n\tint i;\n\n        x=key->x;\n        y=key->y;\n        d=key->data;\n\n#if defined(RC4_CHUNK)\n\t/*\n\t * The original reason for implementing this(*) was the fact that\n\t * pre-21164a Alpha CPUs don't have byte load/store instructions\n\t * and e.g. a byte store has to be done with 64-bit load, shift,\n\t * and, or and finally 64-bit store. Peaking data and operating\n\t * at natural word size made it possible to reduce amount of\n\t * instructions as well as to perform early read-ahead without\n\t * suffering from RAW (read-after-write) hazard. This resulted\n\t * in ~40%(**) performance improvement on 21064 box with gcc.\n\t * But it's not only Alpha users who win here:-) Thanks to the\n\t * early-n-wide read-ahead this implementation also exhibits\n\t * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending\n\t * on sizeof(RC4_INT)).\n\t *\n\t * (*)\t\"this\" means code which recognizes the case when input\n\t *\tand output pointers appear to be aligned at natural CPU\n\t *\tword boundary\n\t * (**)\ti.e. according to 'apps/openssl speed rc4' benchmark,\n\t *\tcrypto/rc4/rc4speed.c exhibits almost 70% speed-up...\n\t *\n\t * Cavets.\n\t *\n\t * - RC4_CHUNK=\"unsigned long long\" should be a #1 choice for\n\t *   UltraSPARC. Unfortunately gcc generates very slow code\n\t *   (2.5-3 times slower than one generated by Sun's WorkShop\n\t *   C) and therefore gcc (at least 2.95 and earlier) should\n\t *   always be told that RC4_CHUNK=\"unsigned long\".\n\t *\n\t *\t\t\t\t\t<appro@fy.chalmers.se>\n\t */\n\n# define RC4_STEP\t( \\\n\t\t\tx=(x+1) &0xff,\t\\\n\t\t\ttx=d[x],\t\\\n\t\t\ty=(tx+y)&0xff,\t\\\n\t\t\tty=d[y],\t\\\n\t\t\td[y]=tx,\t\\\n\t\t\td[x]=ty,\t\\\n\t\t\t(RC4_CHUNK)d[(tx+ty)&0xff]\\\n\t\t\t)\n\n\tif ( ( ((unsigned long)indata  & (sizeof(RC4_CHUNK)-1)) |\n\t       ((unsigned long)outdata & (sizeof(RC4_CHUNK)-1)) ) == 0 )\n\t\t{\n\t\tRC4_CHUNK ichunk,otp;\n\t\tconst union { long one; char little; } is_endian = {1};\n\n\t\t/*\n\t\t * I reckon we can afford to implement both endian\n\t\t * cases and to decide which way to take at run-time\n\t\t * because the machine code appears to be very compact\n\t\t * and redundant 1-2KB is perfectly tolerable (i.e.\n\t\t * in case the compiler fails to eliminate it:-). By\n\t\t * suggestion from Terrel Larson <terr@terralogic.net>\n\t\t * who also stands for the is_endian union:-)\n\t\t *\n\t\t * Special notes.\n\t\t *\n\t\t * - is_endian is declared automatic as doing otherwise\n\t\t *   (declaring static) prevents gcc from eliminating\n\t\t *   the redundant code;\n\t\t * - compilers (those I've tried) don't seem to have\n\t\t *   problems eliminating either the operators guarded\n\t\t *   by \"if (sizeof(RC4_CHUNK)==8)\" or the condition\n\t\t *   expressions themselves so I've got 'em to replace\n\t\t *   corresponding #ifdefs from the previous version;\n\t\t * - I chose to let the redundant switch cases when\n\t\t *   sizeof(RC4_CHUNK)!=8 be (were also #ifdefed\n\t\t *   before);\n\t\t * - in case you wonder \"&(sizeof(RC4_CHUNK)*8-1)\" in\n\t\t *   [LB]ESHFT guards against \"shift is out of range\"\n\t\t *   warnings when sizeof(RC4_CHUNK)!=8\n\t\t *\n\t\t *\t\t\t<appro@fy.chalmers.se>\n\t\t */\n\t\tif (!is_endian.little)\n\t\t\t{\t/* BIG-ENDIAN CASE */\n# define BESHFT(c)\t(((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1))\n\t\t\tfor (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK))\n\t\t\t\t{\n\t\t\t\tichunk  = *(RC4_CHUNK *)indata;\n\t\t\t\totp  = RC4_STEP<<BESHFT(0);\n\t\t\t\totp |= RC4_STEP<<BESHFT(1);\n\t\t\t\totp |= RC4_STEP<<BESHFT(2);\n\t\t\t\totp |= RC4_STEP<<BESHFT(3);\n\t\t\t\tif (sizeof(RC4_CHUNK)==8)\n\t\t\t\t\t{\n\t\t\t\t\totp |= RC4_STEP<<BESHFT(4);\n\t\t\t\t\totp |= RC4_STEP<<BESHFT(5);\n\t\t\t\t\totp |= RC4_STEP<<BESHFT(6);\n\t\t\t\t\totp |= RC4_STEP<<BESHFT(7);\n\t\t\t\t\t}\n\t\t\t\t*(RC4_CHUNK *)outdata = otp^ichunk;\n\t\t\t\tindata  += sizeof(RC4_CHUNK);\n\t\t\t\toutdata += sizeof(RC4_CHUNK);\n\t\t\t\t}\n\t\t\tif (len)\n\t\t\t\t{\n\t\t\t\tRC4_CHUNK mask=(RC4_CHUNK)-1, ochunk;\n\n\t\t\t\tichunk = *(RC4_CHUNK *)indata;\n\t\t\t\tochunk = *(RC4_CHUNK *)outdata;\n\t\t\t\totp = 0;\n\t\t\t\ti = BESHFT(0);\n\t\t\t\tmask <<= (sizeof(RC4_CHUNK)-len)<<3;\n\t\t\t\tswitch (len&(sizeof(RC4_CHUNK)-1))\n\t\t\t\t\t{\n\t\t\t\t\tcase 7:\totp  = RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 6:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 5:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 4:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 3:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 2:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 1:\totp |= RC4_STEP<<i, i-=8;\n\t\t\t\t\tcase 0: ; /*\n\t\t\t\t\t\t   * it's never the case,\n\t\t\t\t\t\t   * but it has to be here\n\t\t\t\t\t\t   * for ultrix?\n\t\t\t\t\t\t   */\n\t\t\t\t\t}\n\t\t\t\tochunk &= ~mask;\n\t\t\t\tochunk |= (otp^ichunk) & mask;\n\t\t\t\t*(RC4_CHUNK *)outdata = ochunk;\n\t\t\t\t}\n\t\t\tkey->x=x;\n\t\t\tkey->y=y;\n\t\t\treturn;\n\t\t\t}\n\t\telse\n\t\t\t{\t/* LITTLE-ENDIAN CASE */\n# define LESHFT(c)\t(((c)*8)&(sizeof(RC4_CHUNK)*8-1))\n\t\t\tfor (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK))\n\t\t\t\t{\n\t\t\t\tichunk  = *(RC4_CHUNK *)indata;\n\t\t\t\totp  = RC4_STEP;\n\t\t\t\totp |= RC4_STEP<<8;\n\t\t\t\totp |= RC4_STEP<<16;\n\t\t\t\totp |= RC4_STEP<<24;\n\t\t\t\tif (sizeof(RC4_CHUNK)==8)\n\t\t\t\t\t{\n\t\t\t\t\totp |= RC4_STEP<<LESHFT(4);\n\t\t\t\t\totp |= RC4_STEP<<LESHFT(5);\n\t\t\t\t\totp |= RC4_STEP<<LESHFT(6);\n\t\t\t\t\totp |= RC4_STEP<<LESHFT(7);\n\t\t\t\t\t}\n\t\t\t\t*(RC4_CHUNK *)outdata = otp^ichunk;\n\t\t\t\tindata  += sizeof(RC4_CHUNK);\n\t\t\t\toutdata += sizeof(RC4_CHUNK);\n\t\t\t\t}\n\t\t\tif (len)\n\t\t\t\t{\n\t\t\t\tRC4_CHUNK mask=(RC4_CHUNK)-1, ochunk;\n\n\t\t\t\tichunk = *(RC4_CHUNK *)indata;\n\t\t\t\tochunk = *(RC4_CHUNK *)outdata;\n\t\t\t\totp = 0;\n\t\t\t\ti   = 0;\n\t\t\t\tmask >>= (sizeof(RC4_CHUNK)-len)<<3;\n\t\t\t\tswitch (len&(sizeof(RC4_CHUNK)-1))\n\t\t\t\t\t{\n\t\t\t\t\tcase 7:\totp  = RC4_STEP,    i+=8;\n\t\t\t\t\tcase 6:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 5:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 4:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 3:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 2:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 1:\totp |= RC4_STEP<<i, i+=8;\n\t\t\t\t\tcase 0: ; /*\n\t\t\t\t\t\t   * it's never the case,\n\t\t\t\t\t\t   * but it has to be here\n\t\t\t\t\t\t   * for ultrix?\n\t\t\t\t\t\t   */\n\t\t\t\t\t}\n\t\t\t\tochunk &= ~mask;\n\t\t\t\tochunk |= (otp^ichunk) & mask;\n\t\t\t\t*(RC4_CHUNK *)outdata = ochunk;\n\t\t\t\t}\n\t\t\tkey->x=x;\n\t\t\tkey->y=y;\n\t\t\treturn;\n\t\t\t}\n\t\t}\n#endif\n#define LOOP(in,out) \\\n\t\tx=((x+1)&0xff); \\\n\t\ttx=d[x]; \\\n\t\ty=(tx+y)&0xff; \\\n\t\td[x]=ty=d[y]; \\\n\t\td[y]=tx; \\\n\t\t(out) = d[(tx+ty)&0xff]^ (in);\n\n#ifndef RC4_INDEX\n#define RC4_LOOP(a,b,i)\tLOOP(*((a)++),*((b)++))\n#else\n#define RC4_LOOP(a,b,i)\tLOOP(a[i],b[i])\n#endif\n\n\ti=(int)(len>>3L);\n\tif (i)\n\t\t{\n\t\tfor (;;)\n\t\t\t{\n\t\t\tRC4_LOOP(indata,outdata,0);\n\t\t\tRC4_LOOP(indata,outdata,1);\n\t\t\tRC4_LOOP(indata,outdata,2);\n\t\t\tRC4_LOOP(indata,outdata,3);\n\t\t\tRC4_LOOP(indata,outdata,4);\n\t\t\tRC4_LOOP(indata,outdata,5);\n\t\t\tRC4_LOOP(indata,outdata,6);\n\t\t\tRC4_LOOP(indata,outdata,7);\n#ifdef RC4_INDEX\n\t\t\tindata+=8;\n\t\t\toutdata+=8;\n#endif\n\t\t\tif (--i == 0) break;\n\t\t\t}\n\t\t}\n\ti=(int)len&0x07;\n\tif (i)\n\t\t{\n\t\tfor (;;)\n\t\t\t{\n\t\t\tRC4_LOOP(indata,outdata,0); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,1); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,2); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,3); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,4); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,5); if (--i == 0) break;\n\t\t\tRC4_LOOP(indata,outdata,6); if (--i == 0) break;\n\t\t\t}\n\t\t}\n\tkey->x=x;\n\tkey->y=y;\n\t}\n"
  },
  {
    "path": "deps/cl345/crypt/rc4locl.h",
    "content": "#ifndef HEADER_RC4_LOCL_H\n#define HEADER_RC4_LOCL_H\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/rc4skey.c",
    "content": "/* crypto/rc4/rc4_skey.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"rc4.h\"\n  #include \"rc4locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/rc4.h\"\n  #include \"crypt/rc4locl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RC4\n\nconst char *RC4_options(void)\n\t{\n#ifdef RC4_INDEX\n\tif (sizeof(RC4_INT) == 1)\n\t\treturn(\"rc4(idx,char)\");\n\telse\n\t\treturn(\"rc4(idx,int)\");\n#else\n\tif (sizeof(RC4_INT) == 1)\n\t\treturn(\"rc4(ptr,char)\");\n\telse\n\t\treturn(\"rc4(ptr,int)\");\n#endif\n\t}\n\n/* RC4 as implemented from a posting from\n * Newsgroups: sci.crypt\n * From: sterndark@netcom.com (David Sterndark)\n * Subject: RC4 Algorithm revealed.\n * Message-ID: <sternCvKL4B.Hyy@netcom.com>\n * Date: Wed, 14 Sep 1994 06:35:31 GMT\n */\n\nvoid RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)\n\t{\n        register RC4_INT tmp;\n        register int id1,id2;\n        register RC4_INT *d;\n        unsigned int i;\n\n        d= &(key->data[0]);\n\tfor (i=0; i<256; i++)\n\t\td[i]=i;\n        key->x = 0;\n        key->y = 0;\n        id1=id2=0;\n\n#define SK_LOOP(n) { \\\n\t\ttmp=d[(n)]; \\\n\t\tid2 = (data[id1] + tmp + id2) & 0xff; \\\n\t\tif (++id1 == len) id1=0; \\\n\t\td[(n)]=d[id2]; \\\n\t\td[id2]=tmp; }\n\n\tfor (i=0; i < 256; i+=4)\n\t\t{\n\t\tSK_LOOP(i+0);\n\t\tSK_LOOP(i+1);\n\t\tSK_LOOP(i+2);\n\t\tSK_LOOP(i+3);\n\t\t}\n\t}\n#endif /* USE_RC4 */\n"
  },
  {
    "path": "deps/cl345/crypt/sha.h",
    "content": "/* crypto/sha/sha.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef HEADER_SHA_H\n#define HEADER_SHA_H\n\n#ifdef  __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(NO_SHA) || (defined(NO_SHA0) && defined(NO_SHA1))\n#error SHA is disabled.\n#endif\n\n/*\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !\n * ! SHA_LONG_LOG2 has to be defined along.                        !\n * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n */\n\n#if defined(WIN16) || defined(__LP32__)\n#define SHA_LONG unsigned long\n#elif defined(_CRAY) || defined(__ILP64__)\n#define SHA_LONG unsigned long\n#define SHA_LONG_LOG2 3\n#else\n#define SHA_LONG unsigned int\n#endif\n\n#define SHA_LBLOCK\t16\n#define SHA_CBLOCK\t(SHA_LBLOCK*4)\t/* SHA treats input data as a\n\t\t\t\t\t * contiguous array of 32 bit\n\t\t\t\t\t * wide big-endian values. */\n#define SHA_LAST_BLOCK  (SHA_CBLOCK-8)\n#define SHA_DIGEST_LENGTH 20\n\ntypedef struct SHAstate_st\n\t{\n\tSHA_LONG h0,h1,h2,h3,h4;\n\tSHA_LONG Nl,Nh;\n\tSHA_LONG data[SHA_LBLOCK];\n\tlong num;\n\t} SHA_CTX;\n\n#ifndef NO_SHA0\nvoid SHA_Init(SHA_CTX *c);\nvoid SHA_Update(SHA_CTX *c, const void *data, unsigned long len);\nvoid SHA_Final(unsigned char *md, SHA_CTX *c);\nunsigned char *SHA(const unsigned char *d, unsigned long n,unsigned char *md);\nvoid SHA_Transform(SHA_CTX *c, const unsigned char *data);\n#endif\n#ifndef NO_SHA1\nvoid SHA1_Init(SHA_CTX *c);\nvoid SHA1_Update(SHA_CTX *c, const void *data, unsigned long len);\nvoid SHA1_Final(unsigned char *md, SHA_CTX *c);\nunsigned char *SHA1(const unsigned char *d, unsigned long n,unsigned char *md);\nvoid SHA1_Transform(SHA_CTX *c, const unsigned char *data);\n#endif\n#ifdef  __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/sha1dgst.c",
    "content": "/* crypto/sha/sha1dgst.c */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#if !defined(NO_SHA1) && !defined(NO_SHA)\n\n#undef  SHA_0\n#define SHA_1\n\n/* The implementation is in ../md32_common.h */\n\n#if defined( INC_ALL )\n  #include \"osconfig.h\"\n  #include \"sha1locl.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/sha1locl.h\"\n#endif /* Compiler-specific includes */\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/sha1locl.h",
    "content": "/* crypto/sha/sha_locl.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n *\n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n *\n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from\n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n *\n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#if defined( INC_ALL )\n  #include \"crypt/osconfig.h\"\n  #include \"sha.h\"\n#else\n  #include \"crypt/osconfig.h\"\n  #include \"crypt/sha.h\"\n#endif /* Compiler-specific includes */\n\n#ifndef SHA_LONG_LOG2\n#define SHA_LONG_LOG2\t2\t/* default to 32 bits */\n#endif\n\n#define DATA_ORDER_IS_BIG_ENDIAN\n\n#define HASH_LONG               SHA_LONG\n#define HASH_LONG_LOG2          SHA_LONG_LOG2\n#define HASH_CTX                SHA_CTX\n#define HASH_CBLOCK             SHA_CBLOCK\n#define HASH_LBLOCK             SHA_LBLOCK\n#define HASH_MAKE_STRING(c,s)   do {\t\\\n\tunsigned long ll;\t\t\\\n\tll=(c)->h0; HOST_l2c(ll,(s));\t\\\n\tll=(c)->h1; HOST_l2c(ll,(s));\t\\\n\tll=(c)->h2; HOST_l2c(ll,(s));\t\\\n\tll=(c)->h3; HOST_l2c(ll,(s));\t\\\n\tll=(c)->h4; HOST_l2c(ll,(s));\t\\\n\t} while (0)\n\n#if defined(SHA_0)\n\n# define HASH_UPDATE             \tSHA_Update\n# define HASH_TRANSFORM          \tSHA_Transform\n# define HASH_FINAL              \tSHA_Final\n# define HASH_INIT\t\t\tSHA_Init\n# define HASH_BLOCK_HOST_ORDER   \tsha_block_host_order\n# define HASH_BLOCK_DATA_ORDER   \tsha_block_data_order\n# define Xupdate(a,ix,ia,ib,ic,id)\t(ix=(a)=(ia^ib^ic^id))\n\n  void sha_block_host_order (SHA_CTX *c, const void *p,int num);\n  void sha_block_data_order (SHA_CTX *c, const void *p,int num);\n\n#elif defined(SHA_1)\n\n# define HASH_UPDATE             \tSHA1_Update\n# define HASH_TRANSFORM          \tSHA1_Transform\n# define HASH_FINAL              \tSHA1_Final\n# define HASH_INIT\t\t\tSHA1_Init\n# define HASH_BLOCK_HOST_ORDER   \tsha1_block_host_order\n# define HASH_BLOCK_DATA_ORDER   \tsha1_block_data_order\n# if defined(__MWERKS__) && defined(__MC68K__)\n   /* Metrowerks for Motorola fails otherwise:-( <appro@fy.chalmers.se> */\n#  define Xupdate(a,ix,ia,ib,ic,id)\tdo { (a)=(ia^ib^ic^id);\t\t\\\n\t\t\t\t\t     ix=(a)=ROTATE((a),1);\t\\\n\t\t\t\t\t} while (0)\n# else\n#  define Xupdate(a,ix,ia,ib,ic,id)\t( (a)=(ia^ib^ic^id),\t\\\n\t\t\t\t\t  ix=(a)=ROTATE((a),1)\t\\\n\t\t\t\t\t)\n# endif\n\n# ifdef SHA1_ASM\n#  if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)\n#   define sha1_block_host_order\t\tsha1_block_asm_host_order\n#   define DONT_IMPLEMENT_BLOCK_HOST_ORDER\n#   define sha1_block_data_order\t\tsha1_block_asm_data_order\n#   define DONT_IMPLEMENT_BLOCK_DATA_ORDER\n#   define HASH_BLOCK_DATA_ORDER_ALIGNED\tsha1_block_asm_data_order\n#  endif\n# endif\n  void sha1_block_host_order (SHA_CTX *c, const void *p,int num);\n  void sha1_block_data_order (SHA_CTX *c, const void *p,int num);\n\n#else\n# error \"Either SHA_0 or SHA_1 must be defined.\"\n#endif\n\n#if defined( INC_ALL )\n  #include \"md32com.h\"\n#else\n  #include \"crypt/md32com.h\"\n#endif /* Compiler-specific includes */\n\n#define INIT_DATA_h0 0x67452301UL\n#define INIT_DATA_h1 0xefcdab89UL\n#define INIT_DATA_h2 0x98badcfeUL\n#define INIT_DATA_h3 0x10325476UL\n#define INIT_DATA_h4 0xc3d2e1f0UL\n\nvoid HASH_INIT (SHA_CTX *c)\n\t{\n\tc->h0=INIT_DATA_h0;\n\tc->h1=INIT_DATA_h1;\n\tc->h2=INIT_DATA_h2;\n\tc->h3=INIT_DATA_h3;\n\tc->h4=INIT_DATA_h4;\n\tc->Nl=0;\n\tc->Nh=0;\n\tc->num=0;\n\t}\n\n#define K_00_19\t0x5a827999UL\n#define K_20_39 0x6ed9eba1UL\n#define K_40_59 0x8f1bbcdcUL\n#define K_60_79 0xca62c1d6UL\n\n/* As  pointed out by Wei Dai <weidai@eskimo.com>, F() below can be\n * simplified to the code in F_00_19.  Wei attributes these optimisations\n * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.\n * #define F(x,y,z) (((x) & (y))  |  ((~(x)) & (z)))\n * I've just become aware of another tweak to be made, again from Wei Dai,\n * in F_40_59, (x&a)|(y&a) -> (x|y)&a\n */\n#define\tF_00_19(b,c,d)\t((((c) ^ (d)) & (b)) ^ (d))\n#define\tF_20_39(b,c,d)\t((b) ^ (c) ^ (d))\n#define F_40_59(b,c,d)\t(((b) & (c)) | (((b)|(c)) & (d)))\n#define\tF_60_79(b,c,d)\tF_20_39(b,c,d)\n\n#define BODY_00_15(i,a,b,c,d,e,f,xi) \\\n\t(f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \\\n\tXupdate(f,xi,xa,xb,xc,xd); \\\n\t(f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \\\n\tXupdate(f,xi,xa,xb,xc,xd); \\\n\t(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \\\n\tXupdate(f,xa,xa,xb,xc,xd); \\\n\t(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \\\n\tXupdate(f,xa,xa,xb,xc,xd); \\\n\t(f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \\\n\tXupdate(f,xa,xa,xb,xc,xd); \\\n\t(f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \\\n\t(b)=ROTATE((b),30);\n\n#ifdef X\n#undef X\n#endif\n#ifndef MD32_XARRAY\n  /*\n   * Originally X was an array. As it's automatic it's natural\n   * to expect RISC compiler to accomodate at least part of it in\n   * the register bank, isn't it? Unfortunately not all compilers\n   * \"find\" this expectation reasonable:-( On order to make such\n   * compilers generate better code I replace X[] with a bunch of\n   * X0, X1, etc. See the function body below...\n   *\t\t\t\t\t<appro@fy.chalmers.se>\n   */\n# define X(i)\tXX##i\n#else\n  /*\n   * However! Some compilers (most notably HP C) get overwhelmed by\n   * that many local variables so that we have to have the way to\n   * fall down to the original behavior.\n   */\n# define X(i)\tXX[i]\n#endif\n\n#ifndef DONT_IMPLEMENT_BLOCK_HOST_ORDER\nvoid HASH_BLOCK_HOST_ORDER (SHA_CTX *c, const void *d, int num)\n\t{\n\tconst SHA_LONG *W=d;\n\tregister unsigned long A,B,C,D,E,T;\n#ifndef MD32_XARRAY\n\tunsigned long\tXX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,\n\t\t\tXX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;\n#else\n\tSHA_LONG\tXX[16];\n#endif\n\n\tA=c->h0;\n\tB=c->h1;\n\tC=c->h2;\n\tD=c->h3;\n\tE=c->h4;\n\n\tfor (;;)\n\t\t{\n\tBODY_00_15( 0,A,B,C,D,E,T,W[ 0]);\n\tBODY_00_15( 1,T,A,B,C,D,E,W[ 1]);\n\tBODY_00_15( 2,E,T,A,B,C,D,W[ 2]);\n\tBODY_00_15( 3,D,E,T,A,B,C,W[ 3]);\n\tBODY_00_15( 4,C,D,E,T,A,B,W[ 4]);\n\tBODY_00_15( 5,B,C,D,E,T,A,W[ 5]);\n\tBODY_00_15( 6,A,B,C,D,E,T,W[ 6]);\n\tBODY_00_15( 7,T,A,B,C,D,E,W[ 7]);\n\tBODY_00_15( 8,E,T,A,B,C,D,W[ 8]);\n\tBODY_00_15( 9,D,E,T,A,B,C,W[ 9]);\n\tBODY_00_15(10,C,D,E,T,A,B,W[10]);\n\tBODY_00_15(11,B,C,D,E,T,A,W[11]);\n\tBODY_00_15(12,A,B,C,D,E,T,W[12]);\n\tBODY_00_15(13,T,A,B,C,D,E,W[13]);\n\tBODY_00_15(14,E,T,A,B,C,D,W[14]);\n\tBODY_00_15(15,D,E,T,A,B,C,W[15]);\n\n\tBODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]);\n\tBODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]);\n\tBODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]);\n\tBODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0));\n\n\tBODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1));\n\tBODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2));\n\tBODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3));\n\tBODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4));\n\tBODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5));\n\tBODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6));\n\tBODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7));\n\tBODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8));\n\tBODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9));\n\tBODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10));\n\tBODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11));\n\tBODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12));\n\n\tBODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));\n\tBODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));\n\tBODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));\n\tBODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));\n\tBODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));\n\tBODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));\n\tBODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));\n\tBODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));\n\n\tBODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));\n\tBODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));\n\tBODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));\n\tBODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));\n\tBODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));\n\tBODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));\n\tBODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));\n\tBODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));\n\tBODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));\n\tBODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));\n\tBODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));\n\tBODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));\n\tBODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));\n\tBODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));\n\tBODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));\n\tBODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));\n\tBODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));\n\tBODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));\n\tBODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));\n\tBODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));\n\n\tBODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));\n\tBODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));\n\tBODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));\n\tBODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));\n\tBODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));\n\tBODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));\n\tBODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));\n\tBODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));\n\tBODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));\n\tBODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));\n\tBODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));\n\tBODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));\n\tBODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));\n\tBODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));\n\tBODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));\n\tBODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));\n\tBODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));\n\tBODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));\n\tBODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));\n\tBODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));\n\n\tc->h0=(c->h0+E)&0xffffffffL;\n\tc->h1=(c->h1+T)&0xffffffffL;\n\tc->h2=(c->h2+A)&0xffffffffL;\n\tc->h3=(c->h3+B)&0xffffffffL;\n\tc->h4=(c->h4+C)&0xffffffffL;\n\n\tif (--num <= 0) break;\n\n\tA=c->h0;\n\tB=c->h1;\n\tC=c->h2;\n\tD=c->h3;\n\tE=c->h4;\n\n\tW+=SHA_LBLOCK;\n\t\t}\n\t}\n#endif\n\n#ifndef DONT_IMPLEMENT_BLOCK_DATA_ORDER\nvoid HASH_BLOCK_DATA_ORDER (SHA_CTX *c, const void *p, int num)\n\t{\n\tconst unsigned char *data=p;\n\tregister unsigned long A,B,C,D,E,T,l;\n#ifndef MD32_XARRAY\n\tunsigned long\tXX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,\n\t\t\tXX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;\n#else\n\tSHA_LONG\tXX[16];\n#endif\n\n\tA=c->h0;\n\tB=c->h1;\n\tC=c->h2;\n\tD=c->h3;\n\tE=c->h4;\n\n\tfor (;;)\n\t\t{\n\n\tHOST_c2l(data,l); X( 0)=l;\t\tHOST_c2l(data,l); X( 1)=l;\n\tBODY_00_15( 0,A,B,C,D,E,T,X( 0));\tHOST_c2l(data,l); X( 2)=l;\n\tBODY_00_15( 1,T,A,B,C,D,E,X( 1));\tHOST_c2l(data,l); X( 3)=l;\n\tBODY_00_15( 2,E,T,A,B,C,D,X( 2));\tHOST_c2l(data,l); X( 4)=l;\n\tBODY_00_15( 3,D,E,T,A,B,C,X( 3));\tHOST_c2l(data,l); X( 5)=l;\n\tBODY_00_15( 4,C,D,E,T,A,B,X( 4));\tHOST_c2l(data,l); X( 6)=l;\n\tBODY_00_15( 5,B,C,D,E,T,A,X( 5));\tHOST_c2l(data,l); X( 7)=l;\n\tBODY_00_15( 6,A,B,C,D,E,T,X( 6));\tHOST_c2l(data,l); X( 8)=l;\n\tBODY_00_15( 7,T,A,B,C,D,E,X( 7));\tHOST_c2l(data,l); X( 9)=l;\n\tBODY_00_15( 8,E,T,A,B,C,D,X( 8));\tHOST_c2l(data,l); X(10)=l;\n\tBODY_00_15( 9,D,E,T,A,B,C,X( 9));\tHOST_c2l(data,l); X(11)=l;\n\tBODY_00_15(10,C,D,E,T,A,B,X(10));\tHOST_c2l(data,l); X(12)=l;\n\tBODY_00_15(11,B,C,D,E,T,A,X(11));\tHOST_c2l(data,l); X(13)=l;\n\tBODY_00_15(12,A,B,C,D,E,T,X(12));\tHOST_c2l(data,l); X(14)=l;\n\tBODY_00_15(13,T,A,B,C,D,E,X(13));\tHOST_c2l(data,l); X(15)=l;\n\tBODY_00_15(14,E,T,A,B,C,D,X(14));\n\tBODY_00_15(15,D,E,T,A,B,C,X(15));\n\n\tBODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13));\n\tBODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14));\n\tBODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15));\n\tBODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0));\n\n\tBODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1));\n\tBODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2));\n\tBODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3));\n\tBODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4));\n\tBODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5));\n\tBODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6));\n\tBODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7));\n\tBODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8));\n\tBODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9));\n\tBODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10));\n\tBODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11));\n\tBODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12));\n\n\tBODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));\n\tBODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));\n\tBODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));\n\tBODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));\n\tBODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));\n\tBODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));\n\tBODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));\n\tBODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));\n\n\tBODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));\n\tBODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));\n\tBODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));\n\tBODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));\n\tBODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));\n\tBODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));\n\tBODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));\n\tBODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));\n\tBODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));\n\tBODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));\n\tBODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));\n\tBODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));\n\tBODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));\n\tBODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));\n\tBODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));\n\tBODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));\n\tBODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));\n\tBODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));\n\tBODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));\n\tBODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));\n\n\tBODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));\n\tBODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));\n\tBODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));\n\tBODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));\n\tBODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));\n\tBODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));\n\tBODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));\n\tBODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));\n\tBODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));\n\tBODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));\n\tBODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));\n\tBODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));\n\tBODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));\n\tBODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));\n\tBODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));\n\tBODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));\n\tBODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));\n\tBODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));\n\tBODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));\n\tBODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));\n\n\tc->h0=(c->h0+E)&0xffffffffL;\n\tc->h1=(c->h1+T)&0xffffffffL;\n\tc->h2=(c->h2+A)&0xffffffffL;\n\tc->h3=(c->h3+B)&0xffffffffL;\n\tc->h4=(c->h4+C)&0xffffffffL;\n\n\tif (--num <= 0) break;\n\n\tA=c->h0;\n\tB=c->h1;\n\tC=c->h2;\n\tD=c->h3;\n\tE=c->h4;\n\n\t\t}\n\t}\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/sha2.c",
    "content": "/*\n ---------------------------------------------------------------------------\n Copyright (c) 2002, Dr Brian Gladman, Worcester, UK.   All rights reserved.\n\n LICENSE TERMS\n\n The free distribution and use of this software in both source and binary\n form is allowed (with or without changes) provided that:\n\n   1. distributions of this source code include the above copyright\n      notice, this list of conditions and the following disclaimer;\n\n   2. distributions in binary form include the above copyright\n      notice, this list of conditions and the following disclaimer\n      in the documentation and/or other associated materials;\n\n   3. the copyright holder's name is not used to endorse products\n      built using this software without specific written permission.\n\n ALTERNATIVELY, provided that this notice is retained in full, this product\n may be distributed under the terms of the GNU General Public License (GPL),\n in which case the provisions of the GPL apply INSTEAD OF those given above.\n\n DISCLAIMER\n\n This software is provided 'as is' with no explicit or implied warranties\n in respect of its properties, including, but not limited to, correctness\n and/or fitness for purpose.\n ---------------------------------------------------------------------------\n Issue Date: 01/08/2005\n\n This is a byte oriented version of SHA2 that operates on arrays of bytes\n stored in memory. This code implements sha256, sha384 and sha512 but the\n latter two functions rely on efficient 64-bit integer operations that\n may not be very efficient on 32-bit machines\n\n The sha256 functions use a type 'sha256_ctx' to hold details of the\n current hash state and uses the following three calls:\n\n       void sha256_begin(sha256_ctx ctx[1])\n       void sha256_hash(const unsigned char data[],\n                            unsigned long len, sha256_ctx ctx[1])\n       void sha_end1(unsigned char hval[], sha256_ctx ctx[1])\n\n The first subroutine initialises a hash computation by setting up the\n context in the sha256_ctx context. The second subroutine hashes 8-bit\n bytes from array data[] into the hash state withinh sha256_ctx context,\n the number of bytes to be hashed being given by the the unsigned long\n integer len.  The third subroutine completes the hash calculation and\n places the resulting digest value in the array of 8-bit bytes hval[].\n\n The sha384 and sha512 functions are similar and use the interfaces:\n\n       void sha384_begin(sha384_ctx ctx[1]);\n       void sha384_hash(const unsigned char data[],\n                            unsigned long len, sha384_ctx ctx[1]);\n       void sha384_end(unsigned char hval[], sha384_ctx ctx[1]);\n\n       void sha512_begin(sha512_ctx ctx[1]);\n       void sha512_hash(const unsigned char data[],\n                            unsigned long len, sha512_ctx ctx[1]);\n       void sha512_end(unsigned char hval[], sha512_ctx ctx[1]);\n\n In addition there is a function sha2 that can be used to call all these\n functions using a call with a hash length parameter as follows:\n\n       int sha2_begin(unsigned long len, sha2_ctx ctx[1]);\n       void sha2_hash(const unsigned char data[],\n                            unsigned long len, sha2_ctx ctx[1]);\n       void sha2_end(unsigned char hval[], sha2_ctx ctx[1]);\n\n My thanks to Erik Andersen <andersen@codepoet.org> for testing this code\n on big-endian systems and for his assistance with corrections\n*/\n\n#if 0\n#define UNROLL_SHA2     /* for SHA2 loop unroll     */\n#endif\n\n#include <string.h>     /* for memcpy() etc.        */\n\n#if defined( INC_ALL )\n  #include \"sha2.h\"\n  #include \"brg_endian.h\"\n#else\n  #include \"crypt/sha2.h\"\n  #include \"crypt/brg_endian.h\"\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 800 )\n#pragma intrinsic(memcpy)\n#endif\n\n#if 0 && defined(_MSC_VER)\n#define rotl32 _lrotl\n#define rotr32 _lrotr\n#else\n#define rotl32(x,n)   (((x) << n) | ((x) >> (32 - n)))\n#define rotr32(x,n)   (((x) >> n) | ((x) << (32 - n)))\n#endif\n\n#if !defined(bswap_32)\n#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))\n#endif\n\n#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)\n#define SWAP_BYTES\n#else\n#undef  SWAP_BYTES\n#endif\n\n#if 0\n\n#define ch(x,y,z)       (((x) & (y)) ^ (~(x) & (z)))\n#define maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))\n\n#else   /* Thanks to Rich Schroeppel and Colin Plumb for the following      */\n\n#define ch(x,y,z)       ((z) ^ ((x) & ((y) ^ (z))))\n#define maj(x,y,z)      (((x) & (y)) | ((z) & ((x) ^ (y))))\n\n#endif\n\n/* round transforms for SHA256 and SHA512 compression functions */\n\n#define vf(n,i) v[(n - i) & 7]\n\n#define hf(i) (p[i & 15] += \\\n    g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15]))\n\n#define v_cycle(i,j)                                \\\n    vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j]        \\\n    + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i));   \\\n    vf(3,i) += vf(7,i);                             \\\n    vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))\n\n#if defined(SHA_224) || defined(SHA_256)\n\n#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)\n\n#if defined(SWAP_BYTES)\n#define bsw_32(p,n) \\\n    { int _i = (n); while(_i--) ((uint32_t*)p)[_i] = bswap_32(((uint32_t*)p)[_i]); }\n#else\n#define bsw_32(p,n)\n#endif\n\n#define s_0(x)  (rotr32((x),  2) ^ rotr32((x), 13) ^ rotr32((x), 22))\n#define s_1(x)  (rotr32((x),  6) ^ rotr32((x), 11) ^ rotr32((x), 25))\n#define g_0(x)  (rotr32((x),  7) ^ rotr32((x), 18) ^ ((x) >>  3))\n#define g_1(x)  (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))\n#define k_0     k256\n\n/* rotated SHA256 round definition. Rather than swapping variables as in    */\n/* FIPS-180, different variables are 'rotated' on each round, returning     */\n/* to their starting positions every eight rounds                           */\n\n#define q(n)  v##n\n\n#define one_cycle(a,b,c,d,e,f,g,h,k,w)  \\\n    q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \\\n    q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c))\n\n/* SHA256 mixing data   */\n\nconst uint32_t k256[64] =\n{   0x428a2f98ul, 0x71374491ul, 0xb5c0fbcful, 0xe9b5dba5ul,\n    0x3956c25bul, 0x59f111f1ul, 0x923f82a4ul, 0xab1c5ed5ul,\n    0xd807aa98ul, 0x12835b01ul, 0x243185beul, 0x550c7dc3ul,\n    0x72be5d74ul, 0x80deb1feul, 0x9bdc06a7ul, 0xc19bf174ul,\n    0xe49b69c1ul, 0xefbe4786ul, 0x0fc19dc6ul, 0x240ca1ccul,\n    0x2de92c6ful, 0x4a7484aaul, 0x5cb0a9dcul, 0x76f988daul,\n    0x983e5152ul, 0xa831c66dul, 0xb00327c8ul, 0xbf597fc7ul,\n    0xc6e00bf3ul, 0xd5a79147ul, 0x06ca6351ul, 0x14292967ul,\n    0x27b70a85ul, 0x2e1b2138ul, 0x4d2c6dfcul, 0x53380d13ul,\n    0x650a7354ul, 0x766a0abbul, 0x81c2c92eul, 0x92722c85ul,\n    0xa2bfe8a1ul, 0xa81a664bul, 0xc24b8b70ul, 0xc76c51a3ul,\n    0xd192e819ul, 0xd6990624ul, 0xf40e3585ul, 0x106aa070ul,\n    0x19a4c116ul, 0x1e376c08ul, 0x2748774cul, 0x34b0bcb5ul,\n    0x391c0cb3ul, 0x4ed8aa4aul, 0x5b9cca4ful, 0x682e6ff3ul,\n    0x748f82eeul, 0x78a5636ful, 0x84c87814ul, 0x8cc70208ul,\n    0x90befffaul, 0xa4506cebul, 0xbef9a3f7ul, 0xc67178f2ul,\n};\n\n/* Compile 64 bytes of hash data into SHA256 digest value   */\n/* NOTE: this routine assumes that the byte order in the    */\n/* ctx->wbuf[] at this point is such that low address bytes */\n/* in the ORIGINAL byte stream will go into the high end of */\n/* words on BOTH big and little endian systems              */\n\nVOID_RETURN sha256_compile(sha256_ctx ctx[1])\n{\n#if !defined(UNROLL_SHA2)\n\n    uint32_t j, *p = ctx->wbuf, v[8];\n\n    memcpy(v, ctx->hash, 8 * sizeof(uint32_t));\n\n    for(j = 0; j < 64; j += 16)\n    {\n        v_cycle( 0, j); v_cycle( 1, j);\n        v_cycle( 2, j); v_cycle( 3, j);\n        v_cycle( 4, j); v_cycle( 5, j);\n        v_cycle( 6, j); v_cycle( 7, j);\n        v_cycle( 8, j); v_cycle( 9, j);\n        v_cycle(10, j); v_cycle(11, j);\n        v_cycle(12, j); v_cycle(13, j);\n        v_cycle(14, j); v_cycle(15, j);\n    }\n\n    ctx->hash[0] += v[0]; ctx->hash[1] += v[1];\n    ctx->hash[2] += v[2]; ctx->hash[3] += v[3];\n    ctx->hash[4] += v[4]; ctx->hash[5] += v[5];\n    ctx->hash[6] += v[6]; ctx->hash[7] += v[7];\n\n#else\n\n    uint32_t *p = ctx->wbuf,v0,v1,v2,v3,v4,v5,v6,v7;\n\n    v0 = ctx->hash[0]; v1 = ctx->hash[1];\n    v2 = ctx->hash[2]; v3 = ctx->hash[3];\n    v4 = ctx->hash[4]; v5 = ctx->hash[5];\n    v6 = ctx->hash[6]; v7 = ctx->hash[7];\n\n    one_cycle(0,1,2,3,4,5,6,7,k256[ 0],p[ 0]);\n    one_cycle(7,0,1,2,3,4,5,6,k256[ 1],p[ 1]);\n    one_cycle(6,7,0,1,2,3,4,5,k256[ 2],p[ 2]);\n    one_cycle(5,6,7,0,1,2,3,4,k256[ 3],p[ 3]);\n    one_cycle(4,5,6,7,0,1,2,3,k256[ 4],p[ 4]);\n    one_cycle(3,4,5,6,7,0,1,2,k256[ 5],p[ 5]);\n    one_cycle(2,3,4,5,6,7,0,1,k256[ 6],p[ 6]);\n    one_cycle(1,2,3,4,5,6,7,0,k256[ 7],p[ 7]);\n    one_cycle(0,1,2,3,4,5,6,7,k256[ 8],p[ 8]);\n    one_cycle(7,0,1,2,3,4,5,6,k256[ 9],p[ 9]);\n    one_cycle(6,7,0,1,2,3,4,5,k256[10],p[10]);\n    one_cycle(5,6,7,0,1,2,3,4,k256[11],p[11]);\n    one_cycle(4,5,6,7,0,1,2,3,k256[12],p[12]);\n    one_cycle(3,4,5,6,7,0,1,2,k256[13],p[13]);\n    one_cycle(2,3,4,5,6,7,0,1,k256[14],p[14]);\n    one_cycle(1,2,3,4,5,6,7,0,k256[15],p[15]);\n\n    one_cycle(0,1,2,3,4,5,6,7,k256[16],hf( 0));\n    one_cycle(7,0,1,2,3,4,5,6,k256[17],hf( 1));\n    one_cycle(6,7,0,1,2,3,4,5,k256[18],hf( 2));\n    one_cycle(5,6,7,0,1,2,3,4,k256[19],hf( 3));\n    one_cycle(4,5,6,7,0,1,2,3,k256[20],hf( 4));\n    one_cycle(3,4,5,6,7,0,1,2,k256[21],hf( 5));\n    one_cycle(2,3,4,5,6,7,0,1,k256[22],hf( 6));\n    one_cycle(1,2,3,4,5,6,7,0,k256[23],hf( 7));\n    one_cycle(0,1,2,3,4,5,6,7,k256[24],hf( 8));\n    one_cycle(7,0,1,2,3,4,5,6,k256[25],hf( 9));\n    one_cycle(6,7,0,1,2,3,4,5,k256[26],hf(10));\n    one_cycle(5,6,7,0,1,2,3,4,k256[27],hf(11));\n    one_cycle(4,5,6,7,0,1,2,3,k256[28],hf(12));\n    one_cycle(3,4,5,6,7,0,1,2,k256[29],hf(13));\n    one_cycle(2,3,4,5,6,7,0,1,k256[30],hf(14));\n    one_cycle(1,2,3,4,5,6,7,0,k256[31],hf(15));\n\n    one_cycle(0,1,2,3,4,5,6,7,k256[32],hf( 0));\n    one_cycle(7,0,1,2,3,4,5,6,k256[33],hf( 1));\n    one_cycle(6,7,0,1,2,3,4,5,k256[34],hf( 2));\n    one_cycle(5,6,7,0,1,2,3,4,k256[35],hf( 3));\n    one_cycle(4,5,6,7,0,1,2,3,k256[36],hf( 4));\n    one_cycle(3,4,5,6,7,0,1,2,k256[37],hf( 5));\n    one_cycle(2,3,4,5,6,7,0,1,k256[38],hf( 6));\n    one_cycle(1,2,3,4,5,6,7,0,k256[39],hf( 7));\n    one_cycle(0,1,2,3,4,5,6,7,k256[40],hf( 8));\n    one_cycle(7,0,1,2,3,4,5,6,k256[41],hf( 9));\n    one_cycle(6,7,0,1,2,3,4,5,k256[42],hf(10));\n    one_cycle(5,6,7,0,1,2,3,4,k256[43],hf(11));\n    one_cycle(4,5,6,7,0,1,2,3,k256[44],hf(12));\n    one_cycle(3,4,5,6,7,0,1,2,k256[45],hf(13));\n    one_cycle(2,3,4,5,6,7,0,1,k256[46],hf(14));\n    one_cycle(1,2,3,4,5,6,7,0,k256[47],hf(15));\n\n    one_cycle(0,1,2,3,4,5,6,7,k256[48],hf( 0));\n    one_cycle(7,0,1,2,3,4,5,6,k256[49],hf( 1));\n    one_cycle(6,7,0,1,2,3,4,5,k256[50],hf( 2));\n    one_cycle(5,6,7,0,1,2,3,4,k256[51],hf( 3));\n    one_cycle(4,5,6,7,0,1,2,3,k256[52],hf( 4));\n    one_cycle(3,4,5,6,7,0,1,2,k256[53],hf( 5));\n    one_cycle(2,3,4,5,6,7,0,1,k256[54],hf( 6));\n    one_cycle(1,2,3,4,5,6,7,0,k256[55],hf( 7));\n    one_cycle(0,1,2,3,4,5,6,7,k256[56],hf( 8));\n    one_cycle(7,0,1,2,3,4,5,6,k256[57],hf( 9));\n    one_cycle(6,7,0,1,2,3,4,5,k256[58],hf(10));\n    one_cycle(5,6,7,0,1,2,3,4,k256[59],hf(11));\n    one_cycle(4,5,6,7,0,1,2,3,k256[60],hf(12));\n    one_cycle(3,4,5,6,7,0,1,2,k256[61],hf(13));\n    one_cycle(2,3,4,5,6,7,0,1,k256[62],hf(14));\n    one_cycle(1,2,3,4,5,6,7,0,k256[63],hf(15));\n\n    ctx->hash[0] += v0; ctx->hash[1] += v1;\n    ctx->hash[2] += v2; ctx->hash[3] += v3;\n    ctx->hash[4] += v4; ctx->hash[5] += v5;\n    ctx->hash[6] += v6; ctx->hash[7] += v7;\n#endif\n}\n\n/* SHA256 hash data in an array of bytes into hash buffer   */\n/* and call the hash_compile function as required.          */\n\nVOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1])\n{   uint32_t pos = (uint32_t)(ctx->count[0] & SHA256_MASK),\n             space = SHA256_BLOCK_SIZE - pos;\n    const unsigned char *sp = data;\n\n    if((ctx->count[0] += len) < len)\n        ++(ctx->count[1]);\n\n    while(len >= space)     /* tranfer whole blocks while possible  */\n    {\n        memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);\n        sp += space; len -= space; space = SHA256_BLOCK_SIZE; pos = 0;\n        bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2)\n        sha256_compile(ctx);\n    }\n\n    memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);\n}\n\n/* SHA256 Final padding and digest calculation  */\n\nstatic void sha_end1(unsigned char hval[], sha256_ctx ctx[1], const unsigned int hlen)\n{   uint32_t    i = (uint32_t)(ctx->count[0] & SHA256_MASK);\n\n    /* put bytes in the buffer in an order in which references to   */\n    /* 32-bit words will put bytes with lower addresses into the    */\n    /* top of 32 bit words on BOTH big and little endian machines   */\n    bsw_32(ctx->wbuf, (i + 3) >> 2)\n\n    /* we now need to mask valid bytes and add the padding which is */\n    /* a single 1 bit and as many zero bits as necessary. Note that */\n    /* we can always add the first padding byte here because the    */\n    /* buffer always has at least one empty slot                    */\n    ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);\n    ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);\n\n    /* we need 9 or more empty positions, one for the padding byte  */\n    /* (above) and eight for the length count.  If there is not     */\n    /* enough space pad and empty the buffer                        */\n    if(i > SHA256_BLOCK_SIZE - 9)\n    {\n        if(i < 60) ctx->wbuf[15] = 0;\n        sha256_compile(ctx);\n        i = 0;\n    }\n    else    /* compute a word index for the empty buffer positions  */\n        i = (i >> 2) + 1;\n\n    while(i < 14) /* and zero pad all but last two positions        */\n        ctx->wbuf[i++] = 0;\n\n    /* the following 32-bit length fields are assembled in the      */\n    /* wrong byte order on little endian machines but this is       */\n    /* corrected later since they are only ever used as 32-bit      */\n    /* word values.                                                 */\n    ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);\n    ctx->wbuf[15] = ctx->count[0] << 3;\n    sha256_compile(ctx);\n\n    /* extract the hash value as bytes in case the hash buffer is   */\n    /* mislaigned for 32-bit words                                  */\n    for(i = 0; i < hlen; ++i)\n\t\thval[i] = (uint8_t)((ctx->hash[i >> 2] >> (8 * (~i & 3))) & 0xff);\n}\n\n#endif\n\n#if defined(SHA_224)\n\nconst uint32_t i224[8] =\n{\n    0xc1059ed8ul, 0x367cd507ul, 0x3070dd17ul, 0xf70e5939ul,\n    0xffc00b31ul, 0x68581511ul, 0x64f98fa7ul, 0xbefa4fa4ul\n};\n\nVOID_RETURN sha224_begin(sha224_ctx ctx[1])\n{\n    ctx->count[0] = ctx->count[1] = 0;\n    memcpy(ctx->hash, i224, 8 * sizeof(uint32_t));\n}\n\nVOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1])\n{\n    sha_end1(hval, ctx, SHA224_DIGEST_SIZE);\n}\n\nVOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len)\n{   sha224_ctx  cx[1];\n\n    sha224_begin(cx);\n    sha224_hash(data, len, cx);\n    sha_end1(hval, cx, SHA224_DIGEST_SIZE);\n}\n\n#endif\n\n#if defined(SHA_256)\n\nconst uint32_t i256[8] =\n{\n    0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul,\n    0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul\n};\n\nVOID_RETURN sha256_begin(sha256_ctx ctx[1])\n{\n    ctx->count[0] = ctx->count[1] = 0;\n    memcpy(ctx->hash, i256, 8 * sizeof(uint32_t));\n}\n\nVOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1])\n{\n    sha_end1(hval, ctx, SHA256_DIGEST_SIZE);\n}\n\nVOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len)\n{   sha256_ctx  cx[1];\n\n    sha256_begin(cx);\n    sha256_hash(data, len, cx);\n    sha_end1(hval, cx, SHA256_DIGEST_SIZE);\n}\n\n#endif\n\n#if defined(SHA_384) || defined(SHA_512)\n\n#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)\n\n#define rotr64(x,n)   (((x) >> n) | ((x) << (64 - n)))\n\n#if !defined(bswap_64)\n#define bswap_64(x) (((uint64_t)(bswap_32((uint32_t)(x)))) << 32 | bswap_32((uint32_t)((x) >> 32)))\n#endif\n\n#if defined(SWAP_BYTES)\n#define bsw_64(p,n) \\\n    { int _i = (n); while(_i--) ((uint64_t*)p)[_i] = bswap_64(((uint64_t*)p)[_i]); }\n#else\n#define bsw_64(p,n)\n#endif\n\n/* SHA512 mixing function definitions   */\n\n#ifdef   s_0\n# undef  s_0\n# undef  s_1\n# undef  g_0\n# undef  g_1\n# undef  k_0\n#endif\n\n#define s_0(x)  (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))\n#define s_1(x)  (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))\n#define g_0(x)  (rotr64((x),  1) ^ rotr64((x),  8) ^ ((x) >>  7))\n#define g_1(x)  (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >>  6))\n#define k_0     k512\n\n/* SHA384/SHA512 mixing data    */\n\nconst uint64_t  k512[80] =\n{\n    li_64(428a2f98d728ae22), li_64(7137449123ef65cd),\n    li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc),\n    li_64(3956c25bf348b538), li_64(59f111f1b605d019),\n    li_64(923f82a4af194f9b), li_64(ab1c5ed5da6d8118),\n    li_64(d807aa98a3030242), li_64(12835b0145706fbe),\n    li_64(243185be4ee4b28c), li_64(550c7dc3d5ffb4e2),\n    li_64(72be5d74f27b896f), li_64(80deb1fe3b1696b1),\n    li_64(9bdc06a725c71235), li_64(c19bf174cf692694),\n    li_64(e49b69c19ef14ad2), li_64(efbe4786384f25e3),\n    li_64(0fc19dc68b8cd5b5), li_64(240ca1cc77ac9c65),\n    li_64(2de92c6f592b0275), li_64(4a7484aa6ea6e483),\n    li_64(5cb0a9dcbd41fbd4), li_64(76f988da831153b5),\n    li_64(983e5152ee66dfab), li_64(a831c66d2db43210),\n    li_64(b00327c898fb213f), li_64(bf597fc7beef0ee4),\n    li_64(c6e00bf33da88fc2), li_64(d5a79147930aa725),\n    li_64(06ca6351e003826f), li_64(142929670a0e6e70),\n    li_64(27b70a8546d22ffc), li_64(2e1b21385c26c926),\n    li_64(4d2c6dfc5ac42aed), li_64(53380d139d95b3df),\n    li_64(650a73548baf63de), li_64(766a0abb3c77b2a8),\n    li_64(81c2c92e47edaee6), li_64(92722c851482353b),\n    li_64(a2bfe8a14cf10364), li_64(a81a664bbc423001),\n    li_64(c24b8b70d0f89791), li_64(c76c51a30654be30),\n    li_64(d192e819d6ef5218), li_64(d69906245565a910),\n    li_64(f40e35855771202a), li_64(106aa07032bbd1b8),\n    li_64(19a4c116b8d2d0c8), li_64(1e376c085141ab53),\n    li_64(2748774cdf8eeb99), li_64(34b0bcb5e19b48a8),\n    li_64(391c0cb3c5c95a63), li_64(4ed8aa4ae3418acb),\n    li_64(5b9cca4f7763e373), li_64(682e6ff3d6b2b8a3),\n    li_64(748f82ee5defb2fc), li_64(78a5636f43172f60),\n    li_64(84c87814a1f0ab72), li_64(8cc702081a6439ec),\n    li_64(90befffa23631e28), li_64(a4506cebde82bde9),\n    li_64(bef9a3f7b2c67915), li_64(c67178f2e372532b),\n    li_64(ca273eceea26619c), li_64(d186b8c721c0c207),\n    li_64(eada7dd6cde0eb1e), li_64(f57d4f7fee6ed178),\n    li_64(06f067aa72176fba), li_64(0a637dc5a2c898a6),\n    li_64(113f9804bef90dae), li_64(1b710b35131c471b),\n    li_64(28db77f523047d84), li_64(32caab7b40c72493),\n    li_64(3c9ebe0a15c9bebc), li_64(431d67c49c100d4c),\n    li_64(4cc5d4becb3e42b6), li_64(597f299cfc657e2a),\n    li_64(5fcb6fab3ad6faec), li_64(6c44198c4a475817)\n};\n\n/* Compile 128 bytes of hash data into SHA384/512 digest    */\n/* NOTE: this routine assumes that the byte order in the    */\n/* ctx->wbuf[] at this point is such that low address bytes */\n/* in the ORIGINAL byte stream will go into the high end of */\n/* words on BOTH big and little endian systems              */\n\nVOID_RETURN sha512_compile(sha512_ctx ctx[1])\n{   uint64_t    v[8], *p = ctx->wbuf;\n    uint32_t    j;\n\n    memcpy(v, ctx->hash, 8 * sizeof(uint64_t));\n\n    for(j = 0; j < 80; j += 16)\n    {\n        v_cycle( 0, j); v_cycle( 1, j);\n        v_cycle( 2, j); v_cycle( 3, j);\n        v_cycle( 4, j); v_cycle( 5, j);\n        v_cycle( 6, j); v_cycle( 7, j);\n        v_cycle( 8, j); v_cycle( 9, j);\n        v_cycle(10, j); v_cycle(11, j);\n        v_cycle(12, j); v_cycle(13, j);\n        v_cycle(14, j); v_cycle(15, j);\n    }\n\n    ctx->hash[0] += v[0]; ctx->hash[1] += v[1];\n    ctx->hash[2] += v[2]; ctx->hash[3] += v[3];\n    ctx->hash[4] += v[4]; ctx->hash[5] += v[5];\n    ctx->hash[6] += v[6]; ctx->hash[7] += v[7];\n}\n\n/* Compile 128 bytes of hash data into SHA256 digest value  */\n/* NOTE: this routine assumes that the byte order in the    */\n/* ctx->wbuf[] at this point is in such an order that low   */\n/* address bytes in the ORIGINAL byte stream placed in this */\n/* buffer will now go to the high end of words on BOTH big  */\n/* and little endian systems                                */\n\nVOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1])\n{   uint32_t pos = (uint32_t)(ctx->count[0] & SHA512_MASK),\n             space = SHA512_BLOCK_SIZE - pos;\n    const unsigned char *sp = data;\n\n    if((ctx->count[0] += len) < len)\n        ++(ctx->count[1]);\n\n    while(len >= space)     /* tranfer whole blocks while possible  */\n    {\n        memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);\n        sp += space; len -= space; space = SHA512_BLOCK_SIZE; pos = 0;\n        bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3);\n        sha512_compile(ctx);\n    }\n\n    memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);\n}\n\n/* SHA384/512 Final padding and digest calculation  */\n\nstatic void sha_end2(unsigned char hval[], sha512_ctx ctx[1], const unsigned int hlen)\n{   uint32_t    i = (uint32_t)(ctx->count[0] & SHA512_MASK);\n\n    /* put bytes in the buffer in an order in which references to   */\n    /* 32-bit words will put bytes with lower addresses into the    */\n    /* top of 32 bit words on BOTH big and little endian machines   */\n    bsw_64(ctx->wbuf, (i + 7) >> 3);\n\n    /* we now need to mask valid bytes and add the padding which is */\n    /* a single 1 bit and as many zero bits as necessary. Note that */\n    /* we can always add the first padding byte here because the    */\n    /* buffer always has at least one empty slot                    */\n    ctx->wbuf[i >> 3] &= li_64(ffffffffffffff00) << 8 * (~i & 7);\n    ctx->wbuf[i >> 3] |= li_64(0000000000000080) << 8 * (~i & 7);\n\n    /* we need 17 or more empty byte positions, one for the padding */\n    /* byte (above) and sixteen for the length count.  If there is  */\n    /* not enough space pad and empty the buffer                    */\n    if(i > SHA512_BLOCK_SIZE - 17)\n    {\n        if(i < 120) ctx->wbuf[15] = 0;\n        sha512_compile(ctx);\n        i = 0;\n    }\n    else\n        i = (i >> 3) + 1;\n\n    while(i < 14)\n        ctx->wbuf[i++] = 0;\n\n    /* the following 64-bit length fields are assembled in the      */\n    /* wrong byte order on little endian machines but this is       */\n    /* corrected later since they are only ever used as 64-bit      */\n    /* word values.                                                 */\n    ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61);\n    ctx->wbuf[15] = ctx->count[0] << 3;\n    sha512_compile(ctx);\n\n    /* extract the hash value as bytes in case the hash buffer is   */\n    /* misaligned for 32-bit words                                  */\n    for(i = 0; i < hlen; ++i)\n\t\thval[i] = (uint8_t)((ctx->hash[i >> 3] >> (8 * (~i & 7))) & 0xff);\t/* pcg */\n}\n\n#endif\n\n#if defined(SHA_384)\n\n/* SHA384 initialisation data   */\n\nconst uint64_t  i384[80] =\n{\n    li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507),\n    li_64(9159015a3070dd17), li_64(152fecd8f70e5939),\n    li_64(67332667ffc00b31), li_64(8eb44a8768581511),\n    li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4)\n};\n\nVOID_RETURN sha384_begin(sha384_ctx ctx[1])\n{\n    ctx->count[0] = ctx->count[1] = 0;\n    memcpy(ctx->hash, i384, 8 * sizeof(uint64_t));\n}\n\nVOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1])\n{\n    sha_end2(hval, ctx, SHA384_DIGEST_SIZE);\n}\n\nVOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len)\n{   sha384_ctx  cx[1];\n\n    sha384_begin(cx);\n    sha384_hash(data, len, cx);\n    sha_end2(hval, cx, SHA384_DIGEST_SIZE);\n}\n\n#endif\n\n#if defined(SHA_512)\n\n/* SHA512 initialisation data   */\n\nconst uint64_t  i512[80] =\n{\n    li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b),\n    li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1),\n    li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f),\n    li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179)\n};\n\nVOID_RETURN sha512_begin(sha512_ctx ctx[1])\n{\n    ctx->count[0] = ctx->count[1] = 0;\n    memcpy(ctx->hash, i512, 8 * sizeof(uint64_t));\n}\n\nVOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1])\n{\n    sha_end2(hval, ctx, SHA512_DIGEST_SIZE);\n}\n\nVOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len)\n{   sha512_ctx  cx[1];\n\n    sha512_begin(cx);\n    sha512_hash(data, len, cx);\n    sha_end2(hval, cx, SHA512_DIGEST_SIZE);\n}\n\n#endif\n\n#if defined(SHA_2)\n\n#define CTX_224(x)  ((x)->uu->ctx256)\n#define CTX_256(x)  ((x)->uu->ctx256)\n#define CTX_384(x)  ((x)->uu->ctx512)\n#define CTX_512(x)  ((x)->uu->ctx512)\n\n/* SHA2 initialisation */\n\nINT_RETURN sha2_begin(unsigned long len, sha2_ctx ctx[1])\n{\n    switch(len)\n    {\n#if defined(SHA_224)\n        case 224:\n        case  28:   CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;\n                    memcpy(CTX_256(ctx)->hash, i224, 32);\n                    ctx->sha2_len = 28; return EXIT_SUCCESS;\n#endif\n#if defined(SHA_256)\n        case 256:\n        case  32:   CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;\n                    memcpy(CTX_256(ctx)->hash, i256, 32);\n                    ctx->sha2_len = 32; return EXIT_SUCCESS;\n#endif\n#if defined(SHA_384)\n        case 384:\n        case  48:   CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0;\n                    memcpy(CTX_384(ctx)->hash, i384, 64);\n                    ctx->sha2_len = 48; return EXIT_SUCCESS;\n#endif\n#if defined(SHA_512)\n        case 512:\n        case  64:   CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0;\n                    memcpy(CTX_512(ctx)->hash, i512, 64);\n                    ctx->sha2_len = 64; return EXIT_SUCCESS;\n#endif\n        default:    return EXIT_FAILURE;\n    }\n}\n\nVOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1])\n{\n    switch(ctx->sha2_len)\n    {\n#if defined(SHA_224)\n        case 28: sha224_hash(data, len, CTX_224(ctx)); return;\n#endif\n#if defined(SHA_256)\n        case 32: sha256_hash(data, len, CTX_256(ctx)); return;\n#endif\n#if defined(SHA_384)\n        case 48: sha384_hash(data, len, CTX_384(ctx)); return;\n#endif\n#if defined(SHA_512)\n        case 64: sha512_hash(data, len, CTX_512(ctx)); return;\n#endif\n    }\n}\n\nVOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1])\n{\n    switch(ctx->sha2_len)\n    {\n#if defined(SHA_224)\n        case 28: sha_end1(hval, CTX_224(ctx), SHA224_DIGEST_SIZE); return;\n#endif\n#if defined(SHA_256)\n        case 32: sha_end1(hval, CTX_256(ctx), SHA256_DIGEST_SIZE); return;\n#endif\n#if defined(SHA_384)\n        case 48: sha_end2(hval, CTX_384(ctx), SHA384_DIGEST_SIZE); return;\n#endif\n#if defined(SHA_512)\n        case 64: sha_end2(hval, CTX_512(ctx), SHA512_DIGEST_SIZE); return;\n#endif\n    }\n}\n\n#if 0\t/* Can't be enabled because MVS doesn't allow a function name to have\n\t\t   the same name as a module name, this is safe to comment out since we\n\t\t   never use it - pcg */\n\nINT_RETURN sha2(unsigned char hval[], unsigned long size,\n                                const unsigned char data[], unsigned long len)\n{   sha2_ctx    cx[1];\n\n    if(sha2_begin(size, cx) == EXIT_SUCCESS)\n    {\n        sha2_hash(data, len, cx); sha2_end(hval, cx); return EXIT_SUCCESS;\n    }\n    else\n        return EXIT_FAILURE;\n}\n#endif /* 0 */\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n"
  },
  {
    "path": "deps/cl345/crypt/sha2.h",
    "content": "/*\n ---------------------------------------------------------------------------\n Copyright (c) 2002, Dr Brian Gladman, Worcester, UK.   All rights reserved.\n\n LICENSE TERMS\n\n The free distribution and use of this software in both source and binary\n form is allowed (with or without changes) provided that:\n\n   1. distributions of this source code include the above copyright\n      notice, this list of conditions and the following disclaimer;\n\n   2. distributions in binary form include the above copyright\n      notice, this list of conditions and the following disclaimer\n      in the documentation and/or other associated materials;\n\n   3. the copyright holder's name is not used to endorse products\n      built using this software without specific written permission.\n\n ALTERNATIVELY, provided that this notice is retained in full, this product\n may be distributed under the terms of the GNU General Public License (GPL),\n in which case the provisions of the GPL apply INSTEAD OF those given above.\n\n DISCLAIMER\n\n This software is provided 'as is' with no explicit or implied warranties\n in respect of its properties, including, but not limited to, correctness\n and/or fitness for purpose.\n ---------------------------------------------------------------------------\n Issue Date: 01/08/2005\n*/\n\n#ifndef _SHA2_H\n#define _SHA2_H\n\n#include <stdlib.h>\n\n#include \"crypt.h\"\t/* For USE_SHA2_EXT define via config.h */\n#ifdef USE_SHA2_EXT\t/* pcg */\n  #define SHA_64BIT\n#endif /* USE_SHA2_EXT */\n\n/* define the hash functions that you need  */\n#define SHA_2   /* for dynamic hash length  */\n#define SHA_224\n#define SHA_256\n#ifdef SHA_64BIT\n#  define SHA_384\n#  define SHA_512\n#  define NEED_UINT_64T\n#endif\n\n#if defined( INC_ALL )\n  #include \"brg_types.h\"\n#else\n  #include \"crypt/brg_types.h\"\n#endif\n\n#if defined(__cplusplus)\nextern \"C\"\n{\n#endif\n\n/* Note that the following function prototypes are the same */\n/* for both the bit and byte oriented implementations.  But */\n/* the length fields are in bytes or bits as is appropriate */\n/* for the version used.  Bit sequences are arrays of bytes */\n/* in which bit sequence indexes increase from the most to  */\n/* the least significant end of each byte                   */\n\n#define SHA224_DIGEST_SIZE  28\n#define SHA224_BLOCK_SIZE   64\n#define SHA256_DIGEST_SIZE  32\n#define SHA256_BLOCK_SIZE   64\n\n/* type to hold the SHA256 (and SHA224) context */\n\ntypedef struct\n{   uint32_t count[2];\n    uint32_t hash[8];\n    uint32_t wbuf[16];\n} sha256_ctx;\n\ntypedef sha256_ctx  sha224_ctx;\n\nVOID_RETURN sha256_compile(sha256_ctx ctx[1]);\n\nVOID_RETURN sha224_begin(sha224_ctx ctx[1]);\n#define sha224_hash sha256_hash\nVOID_RETURN sha224_end(unsigned char hval[], sha224_ctx ctx[1]);\nVOID_RETURN sha224(unsigned char hval[], const unsigned char data[], unsigned long len);\n\nVOID_RETURN sha256_begin(sha256_ctx ctx[1]);\nVOID_RETURN sha256_hash(const unsigned char data[], unsigned long len, sha256_ctx ctx[1]);\nVOID_RETURN sha256_end(unsigned char hval[], sha256_ctx ctx[1]);\nVOID_RETURN sha256(unsigned char hval[], const unsigned char data[], unsigned long len);\n\n#ifndef SHA_64BIT\n\ntypedef struct\n{   union\n    { sha256_ctx  ctx256[1];\n    } uu[1];\n    uint32_t    sha2_len;\n} sha2_ctx;\n\n#define SHA2_MAX_DIGEST_SIZE    SHA256_DIGEST_SIZE\n\n#else\n\n#define SHA384_DIGEST_SIZE  48\n#define SHA384_BLOCK_SIZE  128\n#define SHA512_DIGEST_SIZE  64\n#define SHA512_BLOCK_SIZE  128\n#define SHA2_MAX_DIGEST_SIZE    SHA512_DIGEST_SIZE\n\n/* type to hold the SHA384 (and SHA512) context */\n\ntypedef struct\n{   uint64_t count[2];\n    uint64_t hash[8];\n    uint64_t wbuf[16];\n} sha512_ctx;\n\ntypedef sha512_ctx  sha384_ctx;\n\ntypedef struct\n{   union\n    { sha256_ctx  ctx256[1];\n      sha512_ctx  ctx512[1];\n    } uu[1];\n    uint32_t    sha2_len;\n} sha2_ctx;\n\nVOID_RETURN sha512_compile(sha512_ctx ctx[1]);\n\nVOID_RETURN sha384_begin(sha384_ctx ctx[1]);\n#define sha384_hash sha512_hash\nVOID_RETURN sha384_end(unsigned char hval[], sha384_ctx ctx[1]);\nVOID_RETURN sha384(unsigned char hval[], const unsigned char data[], unsigned long len);\n\nVOID_RETURN sha512_begin(sha512_ctx ctx[1]);\nVOID_RETURN sha512_hash(const unsigned char data[], unsigned long len, sha512_ctx ctx[1]);\nVOID_RETURN sha512_end(unsigned char hval[], sha512_ctx ctx[1]);\nVOID_RETURN sha512(unsigned char hval[], const unsigned char data[], unsigned long len);\n\nINT_RETURN  sha2_begin(unsigned long size, sha2_ctx ctx[1]);\nVOID_RETURN sha2_hash(const unsigned char data[], unsigned long len, sha2_ctx ctx[1]);\nVOID_RETURN sha2_end(unsigned char hval[], sha2_ctx ctx[1]);\nINT_RETURN  sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);\n\n#endif\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/crypt/spr.h",
    "content": "/* crypto/des/spr.h */\n/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)\n * All rights reserved.\n *\n * This package is an SSL implementation written\n * by Eric Young (eay@cryptsoft.com).\n * The implementation was written so as to conform with Netscapes SSL.\n * \n * This library is free for commercial and non-commercial use as long as\n * the following conditions are aheared to.  The following conditions\n * apply to all code found in this distribution, be it the RC4, RSA,\n * lhash, DES, etc., code; not just the SSL code.  The SSL documentation\n * included with this distribution is covered by the same copyright terms\n * except that the holder is Tim Hudson (tjh@cryptsoft.com).\n * \n * Copyright remains Eric Young's, and as such any Copyright notices in\n * the code are not to be removed.\n * If this package is used in a product, Eric Young should be given attribution\n * as the author of the parts of the library used.\n * This can be in the form of a textual message at program startup or\n * in documentation (online or textual) provided with the package.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. All advertising materials mentioning features or use of this software\n *    must display the following acknowledgement:\n *    \"This product includes cryptographic software written by\n *     Eric Young (eay@cryptsoft.com)\"\n *    The word 'cryptographic' can be left out if the rouines from the library\n *    being used are not cryptographic related :-).\n * 4. If you include any Windows specific code (or a derivative thereof) from \n *    the apps directory (application code) you must include an acknowledgement:\n *    \"This product includes software written by Tim Hudson (tjh@cryptsoft.com)\"\n * \n * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n * \n * The licence and distribution terms for any publically available version or\n * derivative of this code cannot be changed.  i.e. this code cannot simply be\n * copied and put under another distribution licence\n * [including the GNU Public Licence.]\n */\n\n#ifndef _OSCONFIG_DEFINED\t\t/* pcg */\n  #if defined( INC_ALL )\n\t#include \"osconfig.h\"\n  #else\n\t#include \"crypt/osconfig.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _OSCONFIG_DEFINED */\n\nOPENSSL_GLOBAL const DES_LONG ASM_EXPORT des_SPtrans[8][64]={\t/* pcg */\n{\n/* nibble 0 */\n0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,\n0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,\n0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,\n0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,\n0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,\n0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,\n0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,\n0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,\n0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,\n0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,\n0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,\n0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,\n0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,\n0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,\n0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,\n0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L,\n},{\n/* nibble 1 */\n0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,\n0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,\n0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,\n0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,\n0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,\n0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,\n0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,\n0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,\n0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,\n0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,\n0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,\n0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,\n0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,\n0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,\n0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,\n0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L,\n},{\n/* nibble 2 */\n0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,\n0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,\n0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,\n0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,\n0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,\n0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,\n0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,\n0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,\n0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,\n0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,\n0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,\n0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,\n0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,\n0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,\n0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,\n0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L,\n},{\n/* nibble 3 */\n0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,\n0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,\n0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,\n0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,\n0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,\n0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,\n0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,\n0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,\n0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,\n0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,\n0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,\n0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,\n0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,\n0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,\n0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,\n0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L,\n},{\n/* nibble 4 */\n0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,\n0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,\n0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,\n0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,\n0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,\n0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,\n0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,\n0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,\n0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,\n0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,\n0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,\n0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,\n0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,\n0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,\n0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,\n0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L,\n},{\n/* nibble 5 */\n0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,\n0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,\n0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,\n0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,\n0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,\n0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,\n0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,\n0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,\n0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,\n0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,\n0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,\n0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,\n0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,\n0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,\n0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,\n0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,\n},{\n/* nibble 6 */\n0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,\n0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,\n0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,\n0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,\n0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,\n0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,\n0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,\n0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,\n0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,\n0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,\n0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,\n0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,\n0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,\n0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,\n0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,\n0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,\n},{\n/* nibble 7 */\n0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,\n0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,\n0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,\n0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,\n0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,\n0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,\n0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,\n0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,\n0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,\n0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,\n0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,\n0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,\n0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,\n0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,\n0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,\n0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,\n}};\n"
  },
  {
    "path": "deps/cl345/crypt/testdes.h",
    "content": "/* DES test vectors, derived from \"Validating the Correctness of Hardware\n   Implementations of the NBS Data Encryption Standard\", NBS Special\n   Publication 500-20, 1980, reprinted in NIST Pub.800-17 and also re-used\n   for 3DES in NIST Pub.800-20 by setting k1 = k2 = k3 so the 3DES tests\n   degenerate into single DES tests */\n\ntypedef struct {\n\tconst BYTE key[ DES_BLOCKSIZE ];\n\tconst BYTE plaintext[ DES_BLOCKSIZE ];\n\tconst BYTE ciphertext[ DES_BLOCKSIZE ];\n\t} DES_TEST;\n\n/* Initial Permutation and Expansion test: Encrypt */\n\nstatic const DES_TEST testIP[ 64 ] = {\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 },\n\t  { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 },\n\t  { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA },\n\t  { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F },\n\t  { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 },\n\t  { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF },\n\t  { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F },\n\t  { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 },\n\t  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A },\n\t  { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x42, 0x42, 0x50, 0xB3, 0x7C, 0x3D, 0xD9, 0x51 },\n\t  { 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xB8, 0x06, 0x1B, 0x7E, 0xCD, 0x9A, 0x21, 0xE5 },\n\t  { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xF1, 0x5D, 0x0F, 0x28, 0x6B, 0x65, 0xBD, 0x28 },\n\t  { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xAD, 0xD0, 0xCC, 0x8D, 0x6E, 0x5D, 0xEB, 0xA1 },  \n\t  { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE6, 0xD5, 0xF8, 0x27, 0x52, 0xAD, 0x63, 0xD1 },  \n\t  { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xEC, 0xBF, 0xE3, 0xBD, 0x3F, 0x59, 0x1A, 0x5E },\n\t  { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xF3, 0x56, 0x83, 0x43, 0x79, 0xD1, 0x65, 0xCD },  \n\t  { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x2B, 0x9F, 0x98, 0x2F, 0x20, 0x03, 0x7F, 0xA9 },\n\t  { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x88, 0x9D, 0xE0, 0x68, 0xA1, 0x6F, 0x0B, 0xE6 },  \n\t  { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE1, 0x9E, 0x27, 0x5D, 0x84, 0x6A, 0x12, 0x98 },  \n\t  { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x32, 0x9A, 0x8E, 0xD5, 0x23, 0xD7, 0x1A, 0xEC },\n\t  { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xE7, 0xFC, 0xE2, 0x25, 0x57, 0xD2, 0x3C, 0x97 },  \n\t  { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x12, 0xA9, 0xF5, 0x81, 0x7F, 0xF2, 0xD6, 0x5D },  \n\t  { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xA4, 0x84, 0xC3, 0xAD, 0x38, 0xDC, 0x9C, 0x19 },\n\t  { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xFB, 0xE0, 0x0A, 0x8A, 0x1E, 0xF8, 0xAD, 0x72 },  \n\t  { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x75, 0x0D, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63 },  \n\t  { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x64, 0xFE, 0xED, 0x9C, 0x72, 0x4C, 0x2F, 0xAF },  \n\t  { 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xF0, 0x2B, 0x26, 0x3B, 0x32, 0x8E, 0x2B, 0x60 },  \n\t  { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x9D, 0x64, 0x55, 0x5A, 0x9A, 0x10, 0xB8, 0x52 },\n\t  { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xD1, 0x06, 0xFF, 0x0B, 0xED, 0x52, 0x55, 0xD7 },\n\t  { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE1, 0x65, 0x2C, 0x6B, 0x13, 0x8C, 0x64, 0xA5 },  \n\t  { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE4, 0x28, 0x58, 0x11, 0x86, 0xEC, 0x8F, 0x46 },  \n\t  { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xAE, 0xB5, 0xF5, 0xED, 0xE2, 0x2D, 0x1A, 0x36 },\n\t  { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE9, 0x43, 0xD7, 0x56, 0x8A, 0xEC, 0x0C, 0x5C },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xDF, 0x98, 0xC8, 0x27, 0x6F, 0x54, 0xB0, 0x4B },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xB1, 0x60, 0xE4, 0x68, 0x0F, 0x6C, 0x69, 0x6F },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xFA, 0x07, 0x52, 0xB0, 0x7D, 0x9C, 0x4A, 0xB8 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xCA, 0x3A, 0x2B, 0x03, 0x6D, 0xBC, 0x85, 0x02 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x5E, 0x09, 0x05, 0x51, 0x7B, 0xB5, 0x9B, 0xCF },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x81, 0x4E, 0xEB, 0x3B, 0x91, 0xD9, 0x07, 0x26 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x4D, 0x49, 0xDB, 0x15, 0x32, 0x91, 0x9C, 0x9F },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x25, 0xEB, 0x5F, 0xC3, 0xF8, 0xCF, 0x06, 0x21 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xAB, 0x6A, 0x20, 0xC0, 0x62, 0x0D, 0x1C, 0x6F },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x79, 0xE9, 0x0D, 0xBC, 0x98, 0xF9, 0x2C, 0xCA },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x86, 0x6E, 0xCE, 0xDD, 0x80, 0x72, 0xBB, 0x0E },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x8B, 0x54, 0x53, 0x6F, 0x2F, 0x3E, 0x64, 0xA8 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xEA, 0x51, 0xD3, 0x97, 0x55, 0x95, 0xB8, 0x6B },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xCA, 0xFF, 0xC6, 0xAC, 0x45, 0x42, 0xDE, 0x31 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x8D, 0xD4, 0x5A, 0x2D, 0xDF, 0x90, 0x79, 0x6C },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x10, 0x29, 0xD5, 0x5E, 0x88, 0x0E, 0xC2, 0xD0 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x5D, 0x86, 0xCB, 0x23, 0x63, 0x9D, 0xBE, 0xA9 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x1D, 0x1C, 0xA8, 0x53, 0xAE, 0x7C, 0x0C, 0x5F },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xCE, 0x33, 0x23, 0x29, 0x24, 0x8F, 0x32, 0x28 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x84, 0x05, 0xD1, 0xAB, 0xE2, 0x4F, 0xB9, 0x42 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE6, 0x43, 0xD7, 0x80, 0x90, 0xCA, 0x42, 0x07 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x48, 0x22, 0x1B, 0x99, 0x37, 0x74, 0x8A, 0x23 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xDD, 0x7C, 0x0B, 0xBD, 0x61, 0xFA, 0xFD, 0x54 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x2F, 0xBC, 0x29, 0x1A, 0x57, 0x0D, 0xB5, 0xC4 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xE0, 0x7C, 0x30, 0xD7, 0xE4, 0xE2, 0x6E, 0x12 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x09, 0x53, 0xE2, 0x25, 0x8E, 0x8E, 0x90, 0xA1 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x5B, 0x71, 0x1B, 0xC4, 0xCE, 0xEB, 0xF2, 0xEE },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xCC, 0x08, 0x3F, 0x1E, 0x6D, 0x9E, 0x85, 0xF6 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xD2, 0xFD, 0x88, 0x67, 0xD5, 0x0D, 0x2D, 0xFE },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x06, 0xE7, 0xEA, 0x22, 0xCE, 0x92, 0x70, 0x8F },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x16, 0x6B, 0x40, 0xB4, 0x4A, 0xBA, 0x4B, 0xD6 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }\n\t};\n\n/* Inverse Permutation and Expansion test: Encrypt */\n\nstatic const DES_TEST testVP[ 64 ] = {\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x42, 0x42, 0x50, 0xB3, 0x7C, 0x3D, 0xD9, 0x51 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xB8, 0x06, 0x1B, 0x7E, 0xCD, 0x9A, 0x21, 0xE5 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xF1, 0x5D, 0x0F, 0x28, 0x6B, 0x65, 0xBD, 0x28 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAD, 0xD0, 0xCC, 0x8D, 0x6E, 0x5D, 0xEB, 0xA1 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE6, 0xD5, 0xF8, 0x27, 0x52, 0xAD, 0x63, 0xD1 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xEC, 0xBF, 0xE3, 0xBD, 0x3F, 0x59, 0x1A, 0x5E } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xF3, 0x56, 0x83, 0x43, 0x79, 0xD1, 0x65, 0xCD } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x2B, 0x9F, 0x98, 0x2F, 0x20, 0x03, 0x7F, 0xA9 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x88, 0x9D, 0xE0, 0x68, 0xA1, 0x6F, 0x0B, 0xE6 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE1, 0x9E, 0x27, 0x5D, 0x84, 0x6A, 0x12, 0x98 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x32, 0x9A, 0x8E, 0xD5, 0x23, 0xD7, 0x1A, 0xEC } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE7, 0xFC, 0xE2, 0x25, 0x57, 0xD2, 0x3C, 0x97 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x12, 0xA9, 0xF5, 0x81, 0x7F, 0xF2, 0xD6, 0x5D } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xA4, 0x84, 0xC3, 0xAD, 0x38, 0xDC, 0x9C, 0x19 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xFB, 0xE0, 0x0A, 0x8A, 0x1E, 0xF8, 0xAD, 0x72 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x75, 0x0D, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x64, 0xFE, 0xED, 0x9C, 0x72, 0x4C, 0x2F, 0xAF } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xF0, 0x2B, 0x26, 0x3B, 0x32, 0x8E, 0x2B, 0x60 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x9D, 0x64, 0x55, 0x5A, 0x9A, 0x10, 0xB8, 0x52 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD1, 0x06, 0xFF, 0x0B, 0xED, 0x52, 0x55, 0xD7 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE1, 0x65, 0x2C, 0x6B, 0x13, 0x8C, 0x64, 0xA5 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE4, 0x28, 0x58, 0x11, 0x86, 0xEC, 0x8F, 0x46 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAE, 0xB5, 0xF5, 0xED, 0xE2, 0x2D, 0x1A, 0x36 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },  \n\t  { 0xE9, 0x43, 0xD7, 0x56, 0x8A, 0xEC, 0x0C, 0x5C } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 },  \n\t  { 0xDF, 0x98, 0xC8, 0x27, 0x6F, 0x54, 0xB0, 0x4B } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 },  \n\t  { 0xB1, 0x60, 0xE4, 0x68, 0x0F, 0x6C, 0x69, 0x6F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 },  \n\t  { 0xFA, 0x07, 0x52, 0xB0, 0x7D, 0x9C, 0x4A, 0xB8 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 },  \n\t  { 0xCA, 0x3A, 0x2B, 0x03, 0x6D, 0xBC, 0x85, 0x02 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 },  \n\t  { 0x5E, 0x09, 0x05, 0x51, 0x7B, 0xB5, 0x9B, 0xCF } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },  \n\t  { 0x81, 0x4E, 0xEB, 0x3B, 0x91, 0xD9, 0x07, 0x26 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 },\n\t  { 0x4D, 0x49, 0xDB, 0x15, 0x32, 0x91, 0x9C, 0x9F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 },  \n\t  { 0x25, 0xEB, 0x5F, 0xC3, 0xF8, 0xCF, 0x06, 0x21 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00 },  \n\t  { 0xAB, 0x6A, 0x20, 0xC0, 0x62, 0x0D, 0x1C, 0x6F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 },  \n\t  { 0x79, 0xE9, 0x0D, 0xBC, 0x98, 0xF9, 0x2C, 0xCA } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00 },  \n\t  { 0x86, 0x6E, 0xCE, 0xDD, 0x80, 0x72, 0xBB, 0x0E } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00 },\n\t  { 0x8B, 0x54, 0x53, 0x6F, 0x2F, 0x3E, 0x64, 0xA8 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 },  \n\t  { 0xEA, 0x51, 0xD3, 0x97, 0x55, 0x95, 0xB8, 0x6B } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 },  \n\t  { 0xCA, 0xFF, 0xC6, 0xAC, 0x45, 0x42, 0xDE, 0x31 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 },  \n\t  { 0x8D, 0xD4, 0x5A, 0x2D, 0xDF, 0x90, 0x79, 0x6C } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 },  \n\t  { 0x10, 0x29, 0xD5, 0x5E, 0x88, 0x0E, 0xC2, 0xD0 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00 },  \n\t  { 0x5D, 0x86, 0xCB, 0x23, 0x63, 0x9D, 0xBE, 0xA9 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00 },  \n\t  { 0x1D, 0x1C, 0xA8, 0x53, 0xAE, 0x7C, 0x0C, 0x5F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 },  \n\t  { 0xCE, 0x33, 0x23, 0x29, 0x24, 0x8F, 0x32, 0x28 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 },  \n\t  { 0x84, 0x05, 0xD1, 0xAB, 0xE2, 0x4F, 0xB9, 0x42 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00 },  \n\t  { 0xE6, 0x43, 0xD7, 0x80, 0x90, 0xCA, 0x42, 0x07 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 },  \n\t  { 0x48, 0x22, 0x1B, 0x99, 0x37, 0x74, 0x8A, 0x23 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },  \n\t  { 0xDD, 0x7C, 0x0B, 0xBD, 0x61, 0xFA, 0xFD, 0x54 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },\n\t  { 0x2F, 0xBC, 0x29, 0x1A, 0x57, 0x0D, 0xB5, 0xC4 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 },  \n\t  { 0xE0, 0x7C, 0x30, 0xD7, 0xE4, 0xE2, 0x6E, 0x12 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 },  \n\t  { 0x09, 0x53, 0xE2, 0x25, 0x8E, 0x8E, 0x90, 0xA1 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 },  \n\t  { 0x5B, 0x71, 0x1B, 0xC4, 0xCE, 0xEB, 0xF2, 0xEE } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 },  \n\t  { 0xCC, 0x08, 0x3F, 0x1E, 0x6D, 0x9E, 0x85, 0xF6 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 },\n\t  { 0xD2, 0xFD, 0x88, 0x67, 0xD5, 0x0D, 0x2D, 0xFE } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },  \n\t  { 0x06, 0xE7, 0xEA, 0x22, 0xCE, 0x92, 0x70, 0x8F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },  \n\t  { 0x16, 0x6B, 0x40, 0xB4, 0x4A, 0xBA, 0x4B, 0xD6 } }\n\t}; \n\n/* Key Permutation tests: Encrypt */\n\nstatic const DES_TEST testKP[ 56 ] = {\n\t{ { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } },\n\t{ { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } },\n\t{ { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } },\n\t{ { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } },\n\t{ { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } },\n\t{ { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } },\n\t{ { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } },\n\t{ { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } },\n\t{ { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } },\n\t{ { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } },\n\t{ { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } },\n\t{ { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } },\n\t{ { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } },\n\t{ { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } },\n\t{ { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } },\n\t{ { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } },\n\t{ { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } },\n\t{ { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } },\n\t{ { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } },\n\t{ { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } },\n\t{ { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } },\n\t{ { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } },\n\t{ { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } },\n\t{ { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } },\n\t{ { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } },\n\t{ { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } },\n\t{ { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } },\n\t{ { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } }\n\t};\n\n/* Test of right-shifts in Decryption: Decrypt */\n\nstatic const DES_TEST testRS[ 56 ] = {\n\t{ { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 },  \n\t  { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 },\n\t  { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 },\n\t  { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 },  \n\t  { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 },  \n\t  { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 },  \n\t  { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 },  \n\t  { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 },  \n\t  { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 },  \n\t  { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 },  \n\t  { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 },  \n\t  { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 },  \n\t  { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 },  \n\t  { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 },  \n\t  { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 },  \n\t  { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 },  \n\t  { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 },  \n\t  { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 },  \n\t  { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 },\n\t  { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 },\n\t  { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 },  \n\t  { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 },  \n\t  { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 },  \n\t  { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 },  \n\t  { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 },  \n\t  { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 },  \n\t  { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 },  \n\t  { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 },  \n\t  { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 },  \n\t  { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\n\t{ { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 },  \n\t  { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }\n\t}; \n\n/* Data Permutation test: Encrypt */\n\nstatic const DES_TEST testDP[ 32 ] = {\n\t{ { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x88, 0xD5, 0x5E, 0x54, 0xF5, 0x4C, 0x97, 0xB4 } },\n\t{ { 0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x0C, 0x0C, 0xC0, 0x0C, 0x83, 0xEA, 0x48, 0xFD } },\n\t{ { 0x10, 0x07, 0x10, 0x34, 0xC8, 0x98, 0x01, 0x20 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x83, 0xBC, 0x8E, 0xF3, 0xA6, 0x57, 0x01, 0x83 } },\n\t{ { 0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xDF, 0x72, 0x5D, 0xCA, 0xD9, 0x4E, 0xA2, 0xE9 } },\n\t{ { 0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE6, 0x52, 0xB5, 0x3B, 0x55, 0x0B, 0xE8, 0xB0 } },\n\t{ { 0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xAF, 0x52, 0x71, 0x20, 0xC4, 0x85, 0xCB, 0xB0 } },\n\t{ { 0x51, 0x07, 0xB0, 0x15, 0x19, 0x58, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x0F, 0x04, 0xCE, 0x39, 0x3D, 0xB9, 0x26, 0xD5 } },\n\t{ { 0x10, 0x07, 0xB0, 0x15, 0x19, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xC9, 0xF0, 0x0F, 0xFC, 0x74, 0x07, 0x90, 0x67 } },\n\t{ { 0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x7C, 0xFD, 0x82, 0xA5, 0x93, 0x25, 0x2B, 0x4E } },\n\t{ { 0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xCB, 0x49, 0xA2, 0xF9, 0xE9, 0x13, 0x63, 0xE3 } },\n\t{ { 0x10, 0x07, 0x91, 0x15, 0xB9, 0x08, 0x01, 0x40 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x00, 0xB5, 0x88, 0xBE, 0x70, 0xD2, 0x3F, 0x56 } },\n\t{ { 0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x40, 0x6A, 0x9A, 0x6A, 0xB4, 0x33, 0x99, 0xAE } },\n\t{ { 0x10, 0x07, 0xD0, 0x15, 0x89, 0x98, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x6C, 0xB7, 0x73, 0x61, 0x1D, 0xCA, 0x9A, 0xDA } },\n\t{ { 0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x67, 0xFD, 0x21, 0xC1, 0x7D, 0xBB, 0x5D, 0x70 } },\n\t{ { 0x91, 0x07, 0xD0, 0x15, 0x89, 0x19, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x95, 0x92, 0xCB, 0x41, 0x10, 0x43, 0x07, 0x87 } },\n\t{ { 0x10, 0x07, 0xD0, 0x15, 0x98, 0x98, 0x01, 0x20 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xA6, 0xB7, 0xFF, 0x68, 0xA3, 0x18, 0xDD, 0xD3 } },\n\t{ { 0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x4D, 0x10, 0x21, 0x96, 0xC9, 0x14, 0xCA, 0x16 } },\n\t{ { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x2D, 0xFA, 0x9F, 0x45, 0x73, 0x59, 0x49, 0x65 } },\n\t{ { 0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xB4, 0x66, 0x04, 0x81, 0x6C, 0x0E, 0x07, 0x74 } },\n\t{ { 0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x6E, 0x7E, 0x62, 0x21, 0xA4, 0xF3, 0x4E, 0x87 } },\n\t{ { 0x19, 0x07, 0x92, 0x10, 0x98, 0x1A, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAA, 0x85, 0xE7, 0x46, 0x43, 0x23, 0x31, 0x99 } },\n\t{ { 0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x2E, 0x5A, 0x19, 0xDB, 0x4D, 0x19, 0x62, 0xD6 } },\n\t{ { 0x10, 0x07, 0x91, 0x19, 0x98, 0x1A, 0x08, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0x23, 0xA8, 0x66, 0xA8, 0x09, 0xD3, 0x08, 0x94 } },\n\t{ { 0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xD8, 0x12, 0xD9, 0x61, 0xF0, 0x17, 0xD3, 0x20 } },\n\t{ { 0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0B },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x05, 0x56, 0x05, 0x81, 0x6E, 0x58, 0x60, 0x8F } },\n\t{ { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },\n\t  { 0xAB, 0xD8, 0x8E, 0x8B, 0x1B, 0x77, 0x16, 0xF1 } },\n\t{ { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x53, 0x7A, 0xC9, 0x5B, 0xE6, 0x9D, 0xA1, 0xE1 } },\n\t{ { 0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xAE, 0xD0, 0xF6, 0xAE, 0x3C, 0x25, 0xCD, 0xD8 } },\n\t{ { 0x10, 0x02, 0x91, 0x14, 0x98, 0x10, 0x01, 0x04 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xB3, 0xE3, 0x5A, 0x5E, 0xE5, 0x3E, 0x7B, 0x8D } },\n\t{ { 0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x61, 0xC7, 0x9C, 0x71, 0x92, 0x1A, 0x2E, 0xF8 } },\n\t{ { 0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01 },  \n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0xE2, 0xF5, 0x72, 0x8F, 0x09, 0x95, 0x01, 0x3C } },\n\t{ { 0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01 },\n\t  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },  \n\t  { 0x1A, 0xEA, 0xC3, 0x9A, 0x61, 0xF0, 0xA4, 0x64 } }\n\t}; \n\n/* S-Box test: Encrypt */\n\nstatic const DES_TEST testSB[ 19 ] = {\n\t{ { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },\n\t  { 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42 },\n\t  { 0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B } },\n\t{ { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E },\n\t  { 0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA },\n\t  { 0x7A, 0x38, 0x9D, 0x10, 0x35, 0x4B, 0xD2, 0x71 } },\n\t{ { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 },  \n\t  { 0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72 },\n\t  { 0x86, 0x8E, 0xBB, 0x51, 0xCA, 0xB4, 0x59, 0x9A } },\n\t{ { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E },  \n\t  { 0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A },  \n\t  { 0x71, 0x78, 0x87, 0x6E, 0x01, 0xF1, 0x9B, 0x2A } },\n\t{ { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 },  \n\t  { 0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2 },  \n\t  { 0xAF, 0x37, 0xFB, 0x42, 0x1F, 0x8C, 0x40, 0x95 } },\n\t{ { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE },  \n\t  { 0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A },\n\t  { 0x86, 0xA5, 0x60, 0xF1, 0x0E, 0xC6, 0xD8, 0x5B } },\n\t{ { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 },\n\t  { 0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2 },  \n\t  { 0x0C, 0xD3, 0xDA, 0x02, 0x00, 0x21, 0xDC, 0x09 } },\n\t{ { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE },\n\t  { 0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A },  \n\t  { 0xEA, 0x67, 0x6B, 0x2C, 0xB7, 0xDB, 0x2B, 0x7A } },\n\t{ { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 },\n\t  { 0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02 },  \n\t  { 0xDF, 0xD6, 0x4A, 0x81, 0x5C, 0xAF, 0x1A, 0x0F } },\n\t{ { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F },  \n\t  { 0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A },  \n\t  { 0x5C, 0x51, 0x3C, 0x9C, 0x48, 0x86, 0xC0, 0x88 } },\n\t{ { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 },  \n\t  { 0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32 },  \n\t  { 0x0A, 0x2A, 0xEE, 0xAE, 0x3F, 0xF4, 0xAB, 0x77 } },\n\t{ { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E },\n\t  { 0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA },  \n\t  { 0xEF, 0x1B, 0xF0, 0x3E, 0x5D, 0xFA, 0x57, 0x5A } },\n\t{ { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 },  \n\t  { 0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62 },  \n\t  { 0x88, 0xBF, 0x0D, 0xB6, 0xD7, 0x0D, 0xEE, 0x56 } },\n\t{ { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 },  \n\t  { 0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2 },  \n\t  { 0xA1, 0xF9, 0x91, 0x55, 0x41, 0x02, 0x0B, 0x56 } },\n\t{ { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F },  \n\t  { 0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA },  \n\t  { 0x6F, 0xBF, 0x1C, 0xAF, 0xCF, 0xFD, 0x05, 0x56 } },\n\t{ { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 },  \n\t  { 0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92 },  \n\t  { 0x2F, 0x22, 0xE4, 0x9B, 0xAB, 0x7C, 0xA1, 0xAC } },\n\t{ { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF },\n\t  { 0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A },\n\t  { 0x5A, 0x6B, 0x61, 0x2C, 0xC2, 0x6C, 0xCE, 0x4A } },\n\t{ { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 },\n\t  { 0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2 },\n\t  { 0x5F, 0x4C, 0x03, 0x8E, 0xD1, 0x2B, 0x2E, 0x41 } },\n\t{ { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF },\n\t  { 0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A },\n\t  { 0x63, 0xFA, 0xC0, 0xD0, 0x34, 0xD9, 0xF7, 0x93 } }\n\t};\n"
  },
  {
    "path": "deps/cl345/crypt.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Internal General Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CRYPT_DEFINED\n\n#define _CRYPT_DEFINED\n\n/* Various compilers handle includes in subdirectories differently.  Most\n   will work with paths from a root directory.  Non-OS X Macintoshes don't\n   recognise '/'s as path delimiters, but work around it by scanning all\n   subdirectories and treating the files as if they were in the same\n   directory (INC_ALL).  Microsoft C, in a braindamaged exception to all\n   other compilers, treats the subdirectory as the root, unless explicitly\n   told to use the project-file directory by setting Project | Settings |\n   C/C++ | Preprocessor | Additional include directories to '.\\'.  The\n   Tandem NSK (Guardian) filesystem doesn't have subdirectories, and the C\n   compiler zaps '.'s, truncates filenames to 7 characters, and appends a\n   'h' to the name (so that asn1misc.h becomes asn1mish).  This\n   unfortunately requires a bit of renaming for header files.  Tandem OSS\n   (Unix services) on the other hand is just like Unix, so we explicitly\n   distinguish between the two */\n\n#if defined( SYMANTEC_C ) && !defined( INC_ALL )\n  #error You need to predefine INC_ALL in your project file\n#endif /* Checks for various compiler/OS-dependant include paths */\n\n/* If we're on a compiler that supports it, set a flag to only include \n   header files once.  Note that on IBM systems this is supported by\n   xlc (__xlc__) but not c89 (__IBMC__) */\n\n#if defined( __CC_ARM ) || defined( __clang__ ) || \\\n\t( defined( __GNUC__ ) && __GNUC__ >= 4 ) || defined( __HP_cc ) || \\\n\tdefined( __IAR_SYSTEMS_ICC__ ) || defined( __INTEL_COMPILER ) || \\\n\tdefined( _MSC_VER ) || \\\n\t( defined( __SUNPRO_C ) && ( __SUNPRO_C >= 0x5140 ) ) || \\\n\tdefined( __xlc__ ) \n  #pragma once\n#endif /* Compilers that support pragma once */\n\n/* Enable optional newer Posix features if they're available.  This is a \n   majorly problematic define to use because although it gives us access to\n   newer capabilities that may not be present by default, compiler vendors\n   really, really want to use it to show off how clever they are as rules\n   lawyers, so that _POSIX_C_SOURCE gives them free reign to abort the \n   compile if you don't navigate the maze of often compiler-specific options\n   and defines needed to comply with the requirements of fifteen different\n   standards documents, as interpreted by the compiler vendor.  For example\n   SunPro C's sys/feature_tests.h performs a complex series of checks to \n   enforce rules such as \"if you define this but don't define that and also \n   define the other and it's the second Tuesday of the month, stop with a \n   #error rather than continuing\".  In theory we can get past the SunPro \n   checks by defining the Sun-specific _STDC_C99 and _XPG6, but this still \n   produces internal errors in headers due to various things being enabled \n   or not enabled by various defines.\n\n   As a result, we use a whitelist approach and only define _POSIX_C_SOURCE \n   if there's a reasonable chance of the compile being able to continue.  \n   For IBM compilers this means restricting ourselves to Posix 2001, for gcc\n   we can at least use Posix 2008, but then defining it has the braindamaged \n   effect of disabling the use of all BSD-specific defines and data types, \n   which the networking headers are riddled with.  In order to deal with \n   this additionally define _BSD_SOURCE to re-enable all the defines and \n   types that _POSIX_C_SOURCE takes away.  However, in a further bit of\n   braindamage, glibc went from _BSD_SOURCE in 2.19 to _DEFAULT_SOURCE in\n   2.20, and the headers complain if they see _BSD_SOURCE defined.  Since\n   there's no way to tell whether glibc wants to see _BSD_SOURCE or\n   _DEFAULT_SOURCE, we take advantage of the fact that defining \n   _DEFAULT_SOURCE takes precedence over _BSD_SOURCE, so the warnings go\n   away.\n   \n   The value that we can define for _POSIX_C_SOURCE also varies from OS to\n   OS, in theory n-1 is a subset of n but some OSes will only accept n while\n   others want to see n-1 */\n\n#ifndef _POSIX_C_SOURCE \n  #if defined( __xlc__ ) || defined( __IBMC__ )\n\t#define _POSIX_C_SOURCE\t\t\t200112L\t\t/* Posix 2001 */\n  #elif defined( __GNUC__ )\n\t#define _POSIX_C_SOURCE\t\t\t200809L\t\t/* Posix 2008 */\n\t#define _DEFAULT_SOURCE\t\t\t1\t\t\t/* See note above */\n\t#define _BSD_SOURCE\t\t\t\t1\t\t\t/* Undo breakage */\n  #endif /* Compiler-specific _POSIX_C_SOURCE usage */\n#endif /* _POSIX_C_SOURCE  */\n\n/* Enable use of the TR 24731 safe stdlib extensions if they're available */\n\n#if !defined( __STDC_WANT_LIB_EXT1__ )\n  #define __STDC_WANT_LIB_EXT1__\t1\n#endif /* TR 24731 safe stdlib extensions */\n\n/* If we're building under Win32, don't haul in the huge amount of cruft\n   that windows.h brings with it.  We need to define these values before\n   we include cryptlib.h since this is where windows.h is included */\n\n#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \\\n\t  defined( __WIN32__ ) ) && !defined( _SCCTK )\n  #define NOATOM\t\t\t/* Atom Manager routines */\n  #define NOMCX\t\t\t\t/* Modem Configuration Extensions */\n/*#define NOCLIPBOARD\t\t// Clipboard routines, needed for randomness polling */\n  #define NOCOLOR\t\t\t/* Screen colors */\n  #define NOCOMM\t\t\t/* COMM driver routines */\n  #define NOCTLMGR\t\t\t/* Control and Dialog routines */\n  #define NODEFERWINDOWPOS\t/* DeferWindowPos routines */\n  #define NODRAWTEXT\t\t/* DrawText() and DT_* */\n  #define NOGDI\t\t\t\t/* All GDI defines and routines */\n  #define NOGDICAPMASKS\t\t/* CC_*, LC_*, PC_*, CP_*, TC_*, RC_ */\n  #define NOHELP\t\t\t/* Help engine interface */\n  #define NOICONS\t\t\t/* IDI_* */\n  #define NOKANJI\t\t\t/* Kanji support stuff */\n  #define NOKEYSTATES\t\t/* MK_* */\n  #define NOMB\t\t\t\t/* MB_* and MessageBox() */\n  #define NOMCX\t\t\t\t/* Modem Configuration Extensions */\n  #define NOMEMMGR\t\t\t/* GMEM_*, LMEM_*, GHND, LHND, etc */\n  #define NOMENUS\t\t\t/* MF_* */\n  #define NOMETAFILE\t\t/* typedef METAFILEPICT */\n  #if defined( _MSC_VER ) && ( _MSC_VER > 800 )\n\t#define NOMSG\t\t\t/* typedef MSG and associated routines */\n  #endif /* !Win16 */\n  #define NONLS\t\t\t\t/* NLS routines */\n  #define NOPROFILER\t\t/* Profiler interface */\n  #define NORASTEROPS\t\t/* Binary and Tertiary raster ops */\n  #define NOSCROLL\t\t\t/* SB_* and scrolling routines */\n  #define NOSERVICE\t\t\t/* All Service Controller routines, SERVICE_* */\n  #define NOSHOWWINDOW\t\t/* SW_* */\n  #define NOSOUND\t\t\t/* Sound driver routines */\n  #define NOSYSCOMMANDS\t\t/* SC_* */\n  #define NOSYSMETRICS\t\t/* SM_* */\n  #define NOTEXTMETRIC\t\t/* typedef TEXTMETRIC and associated routines */\n  #define NOVIRTUALKEYCODES\t/* VK_* */\n  #define NOWH\t\t\t\t/* SetWindowsHook and WH_* */\n  #define NOWINMESSAGES\t\t/* WM_*, EM_*, LB_*, CB_* */\n  #define NOWINOFFSETS\t\t/* GWL_*, GCL_*, associated routines */\n  #define NOWINSTYLES\t\t/* WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* */\n  #define OEMRESOURCE\t\t/* OEM Resource values */\n#endif /* Win32 */\n\n/* The Palm OS SDK compiler tries to make enums as small as possible (8-bit\n   unsigned chars if it can, otherwise 16-bit unsigned shorts, otherwise\n   ints) for backwards-compatibility with the old 68K-based Palm interface,\n   which causes severe problems for code that assumes that enum == int\n   (this occurs in a number of places where an integer parameter is used to\n   pass a generic value to/from a function).  CodeWarrior allows this enum\n   behaviour to be turned off, but pacc doesn't.\n\n   Similarly, the MSDOS-derived (!!) Watcom C compiler used with older\n   versions of QNX 4.x uses 16-bit enums (DOS 16-bit ints) if possible, and\n   again there's no way to disable this behaviour (there is with newer\n   versions, the pragma to fix the problem is used further down).\n\n   To fix this, we take advantage of the fact that every typedef'd enum has\n   a _LAST member as the last entry and override it to include an additional\n   value that forces the enum range into the 32-bit int range */\n\n#if ( defined( __PALMSOURCE__ ) && defined( _PACC_VER ) ) || \\\n\t( defined( __QNX__ ) && ( OSVERSION <= 4 ) )\n  #define NEED_ENUMFIX\t\t\t/* Remember to undo defines later */\n\n  /* cryptlib.h */\n  #define CRYPT_ALGO_LAST\t\tCRYPT_ALGO_LAST, CRYPT_ALGO_ENUM = -50000\n  #define CRYPT_MODE_LAST\t\tCRYPT_MODE_LAST, CRYPT_MODE_ENUM = -50000\n  #define CRYPT_KEYSET_LAST\t\tCRYPT_KEYSET_LAST, CRYPT_KEYSET_ENUM = -50000\n  #define CRYPT_DEVICE_LAST\t\tCRYPT_DEVICE_LAST, CRYPT_DEVICE_ENUM = -50000\n  #define CRYPT_CERTTYPE_LAST\tCRYPT_CERTTYPE_LAST, CRYPT_CERTTYPE_ENUM = -50000\n  #define CRYPT_FORMAT_LAST\t\tCRYPT_FORMAT_LAST, CRYPT_FORMAT_ENUM = -50000\n  #define CRYPT_SESSION_LAST\tCRYPT_SESSION_LAST, CRYPT_SESSION_ENUM = -50000\n  #define CRYPT_USER_LAST\t\tCRYPT_USER_LAST, CRYPT_USER_ENUM = -50000\n  #define CRYPT_IATTRIBUTE_LAST\tCRYPT_IATTRIBUTE_LAST, CRYPT_IATTRIBUTE_ENUM = -50000\n  #define CRYPT_CRLEXTREASON_LAST\tCRYPT_CRLEXTREASON_LAST, CRYPT_CRLEXTREASON_ENUM = -50000\n  #define CRYPT_CONTENT_LAST\tCRYPT_CONTENT_LAST, CRYPT_CONTENT_ENUM = -50000\n  #define CRYPT_SIGNATURELEVEL_LAST\tCRYPT_SIGNATURELEVEL_LAST, CRYPT_SIGNATURELEVEL_ENUM = -50000\n  #define CRYPT_CERTFORMAT_LAST\tCRYPT_CERTFORMAT_LAST\n  #define CRYPT_REQUESTTYPE_LAST\tCRYPT_REQUESTTYPE_LAST, CRYPT_REQUESTTYPE_ENUM = -50000\n  #define CRYPT_KEYID_LAST\t\tCRYPT_KEYID_LAST, CRYPT_KEYID_ENUM = -50000\n  #define CRYPT_OBJECT_LAST\t\tCRYPT_OBJECT_LAST, CRYPT_OBJECT_ENUM = -50000\n  #define CRYPT_ERRTYPE_LAST\tCRYPT_ERRTYPE_LAST, CRYPT_ERRTYPE_ENUM = -50000\n  #define CRYPT_CERTACTION_LAST\tCRYPT_CERTACTION_LAST, CRYPT_CERTACTION_ENUM = -50000\n  #define CRYPT_KEYOPT_LAST\t\tCRYPT_KEYOPT_LAST, CRYPT_KEYOPT_ENUM = -50000\n  /* crypt.h */\n  #define KEYFORMAT_LAST\t\tKEYFORMAT_LAST, KEYFORMAT_ENUM = -50000\n  #define CERTFORMAT_LAST\t\tCERTFORMAT_LAST, CERTFORMAT_ENUM = -50000\n  #define MANAGEMENT_ACTION_LAST\tMANAGEMENT_ACTION_LAST, MANAGEMENT_ACTION_ENUM = -50000\n  #define HASH_LAST\t\t\t\tHASH_LAST, HASH_ENUM = -50000\n  #define ATTR_LAST\t\t\t\tATTR_LAST, ATTR_ENUM = -50000\n  /* cryptkrn.h */\n  #define MESSAGE_COMPARE_LAST\tMESSAGE_COMPARE_LAST, MESSAGE_COMPARE_ENUM = -50000\n  #define MESSAGE_CHECK_LAST\tMESSAGE_CHECK_LAST, MESSAGE_CHECK_ENUM = -50000\n  #define MESSAGE_CHANGENOTIFY_LAST\tMESSAGE_CHANGENOTIFY_LAST, MESSAGE_CHANGENOTIFY_ENUM = -50000\n  #define MECHANISM_LAST\t\tMECHANISM_LAST, MECHANISM_ENUM = -50000\n  #define KEYMGMT_ITEM_LAST\t\tKEYMGMT_ITEM_LAST, KEYMGMT_ITEM_ENUM = -50000\n  #define SEMAPHORE_LAST\t\tSEMAPHORE_LAST, SEMAPHORE_ENUM = -50000\n  #define MUTEX_LAST\t\t\tMUTEX_LAST, MUTEX_ENUM = -50000\n  /* cert/cert.h */\n  #define RTCSRESPONSE_TYPE_LAST\tRTCSRESPONSE_TYPE_LAST, RTCSRESPONSE_TYPE_ENUM = -50000\n  #define ATTRIBUTE_LAST\t\tATTRIBUTE_LAST, ATTRIBUTE_ENUM = -50000\n  #define POLICY_LAST\t\t\tPOLICY_LAST, POLICY_ENUM = -50000\n  #define SELECTION_OPTION_LAST\tSELECTION_OPTION_LAST, SELECTION_OPTION_ENUM = -50000\n  /* context/context.h */\n  #define CONTEXT_LAST\t\t\tCONTEXT_LAST, CONTEXT_ENUM = -50000\n  /* device/capabil.h */\n  #define CAPABILITY_INFO_LAST\tCAPABILITY_INFO_LAST, CAPABILITY_INFO_ENUM = -50000\n  /* enc_dec/asn1.h */\n  #define BER_ID_LAST\t\t\tBER_ID_LAST, BER_ID_ENUM = -50000\n  /* envelope/envelope.h */\n  #define ACTION_LAST\t\t\tACTION_LAST, ACTION_ENUM = -50000\n  #define ACTION_RESULT_LAST\tACTION_RESULT_LAST, ACTION_RESULT_ENUM = -50000\n  #define STATE_LAST\t\t\tSTATE_LAST, STATE_ENUM = -50000\n  #define ENVSTATE_LAST\t\t\tENVSTATE_LAST, ENVSTATE_ENUM = -50000\n  #define DEENVSTATE_LAST\t\tDEENVSTATE_LAST, DEENVSTATE_ENUM = -50000\n  #define PGP_DEENVSTATE_LAST\tPGP_DEENVSTATE_LAST, PGP_DEENVSTATE_ENUM = -50000\n  #define SEGHDRSTATE_LAST\t\tSEGHDRSTATE_LAST, SEGHDRSTATE_ENUM = -50000\n  /* kernel/acl.h */\n  #define RANGEVAL_LAST\t\t\tRANGEVAL_LAST, RANGEVAL_ENUM = -50000\n  #define ATTRIBUTE_VALUE_LAST\tATTRIBUTE_VALUE_LAST, ATTRIBUTE_VALUE_ENUM = -50000\n  #define PARAM_VALUE_LAST\t\tPARAM_VALUE_LAST, PARAM_VALUE_ENUM = -50000\n  /* kernel/kernel.h */\n  #define SEMAPHORE_STATE_LAST\tSEMAPHORE_STATE_LAST, SEMAPHORE_STATE_ENUM = -50000\n  /* keyset/dbms.h */\n  #define CERTADD_LAST\t\t\tCERTADD_LAST, CERTADD_ENUM = -50000\n  /* keyset/keyset.h */\n  #define KEYSET_SUBTYPE_LAST\tKEYSET_SUBTYPE_LAST, KEYSET_SUBTYPE_ENUM = -50000\n  #define DBMS_QUERY_LAST\t\tDBMS_QUERY_LAST, DBMS_QUERY_ENUM = -50000\n  #define DBMS_UPDATE_LAST\t\tDBMS_UPDATE_LAST, DBMS_UPDATE_ENUM = -50000\n  #define DBMS_CACHEDQUERY_LAST\tDBMS_CACHEDQUERY_LAST, DBMS_CACHEDQUERY_ENUM = -50000\n  /* keyset/pkcs15.h */\n  #define PKCS15_SUBTYPE_LAST\tPKCS15_SUBTYPE_LAST, PKCS15_SUBTYPE_ENUM = -50000\n//  #define PKCS15_OBJECT_LAST\tPKCS15_OBJECT_LAST, PKCS15_OBJECT_ENUM = -50000\n  #define PKCS15_KEYID_LAST\t\tPKCS15_KEYID_LAST, PKCS15_KEYID_ENUM = -50000\n  /* misc/pgp.h */\n  #define PGP_ALGOCLASS_LAST\tPGP_ALGOCLASS_LAST, PGP_ALGOCLASS_ENUM = -50000\n  /* misc/rpc.h */\n  #define COMMAND_LAST\t\t\tCOMMAND_LAST, COMMAND_ENUM = -50000\n  #define DBX_COMMAND_LAST\t\tDBX_COMMAND_LAST, DBX_COMMAND_ENUM = -50000\n  /* io/stream.h */\n  #define STREAM_TYPE_LAST\t\tSTREAM_TYPE_LAST, STREAM_TYPE_ENUM = -50000\n  #define BUILDPATH_LAST\t\tBUILDPATH_LAST, BUILDPATH_ENUM = -50000\n  #define STREAM_IOCTL_LAST\t\tSTREAM_IOCTL_LAST, STREAM_IOCTL_ENUM = -50000\n  #define STREAM_PROTOCOL_LAST\tSTREAM_PROTOCOL_LAST, STREAM_PROTOCOL_ENUM = -50000\n  #define URL_TYPE_LAST\t\t\tURL_TYPE_LAST, URL_TYPE_ENUM = -50000\n  #define NET_OPTION_LAST\t\tNET_OPTION_LAST, NET_OPTION_ENUM = -50000\n  /* session/cmp.h */\n  #define CMPBODY_LAST\t\t\tCMPBODY_LAST, CMPBODY_ENUM = -50000\n  /* session/session.h */\n  #define READINFO_LAST\t\t\tREADINFO_LAST, READINFO_ENUM = -50000\n  /* session/ssh.h */\n  #define CHANNEL_LAST\t\t\tCHANNEL_LAST, CHANNEL_ENUM = -50000\n  #define MAC_LAST\t\t\t\tMAC_LAST, MAC_ENUM = -50000\n  #define SSH_ATRIBUTE_LAST\t\tSSH_ATRIBUTE_LAST, SSH_ATRIBUTE_ENUM = -50000\n  /* session/ssl.h */\n  #define SSL_LAST\t\t\t\tSSL_LAST, SSL_ENUM = -50000\n  #define TLS_EXT_LAST\t\t\tTLS_EXT_LAST, TLS_EXT_ENUM = -50000\n#endif /* Palm SDK compiler enum fix */\n\n/* Global headers used in almost every module.  Before includng these, we \n   set the magic define that enables safe(r) C library functions, which for\n   some unfathomable reason are disabled by default, like disabling the\n   seatbelts in a car */\n\n#ifndef __STDC_WANT_LIB_EXT1__\n  #define __STDC_WANT_LIB_EXT1__\t1\n#endif /* __STDC_WANT_LIB_EXT1__ */\n#if !defined( NDEBUG) && ( defined( __MVS__ ) || defined( __VMCMS__ ) )\n  /* IBM mainframe debug builds need extra functions for diagnostics \n\t support */\n  #define _OPEN_SYS_ITOA_EXT\n#endif /* IBM big iron debug build */\n#if defined( __APPLE__ ) \n  /* Apple headers rely on a pile of BSD-isms that don't get defined unless \n     _DARWIN_C_SOURCE is defined */\n  #define _DARWIN_C_SOURCE\n#endif /* Apple */\n\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n\n/* If the global cryptlib header hasn't been included yet, include it now */\n\n#ifndef _CRYPTLIB_DEFINED\n  #include \"cryptlib.h\"\n#endif /* _CRYPTLIB_DEFINED */\n\n/* Since some of the _LAST types are used in the code, we have to undefine\n   them again if they've been used in the enum-fix kludge */\n\n#ifdef NEED_ENUMFIX\n  #undef CRYPT_ALGO_LAST\n  #undef CRYPT_MODE_LAST\n  #undef CRYPT_KEYSET_LAST\n  #undef CRYPT_DEVICE_LAST\n  #undef CRYPT_CERTTYPE_LAST\n  #undef CRYPT_FORMAT_LAST\n  #undef CRYPT_SESSION_LAST\n  #undef CRYPT_USER_LAST\n  #undef CRYPT_IATTRIBUTE_LAST\n  #undef CRYPT_CRLEXTREASON_LAST\n  #undef CRYPT_CONTENT_LAST\n  #undef CRYPT_SIGNATURELEVEL_LAST\n  #undef CRYPT_CERTFORMAT_LAST\n  #undef CRYPT_REQUESTTYPE_LAST\n  #undef CRYPT_KEYID_LAST\n  #undef CRYPT_OBJECT_LAST\n  #undef CRYPT_ERRTYPE_LAST\n  #undef CRYPT_CERTACTION_LAST\n  #undef CRYPT_KEYOPT_LAST\n#endif /* NEED_ENUMFIX */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSystem- and Compiler-Specific Defines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the system and compiler-specific defines and values.  This \n   detects the system config and is used by config.h */\n\n#if defined( INC_ALL )\n  #include \"os_detect.h\"\n#else\n  #include \"misc/os_detect.h\"\n#endif /* Compiler-specific includes */\n\n/* Pull in the source code analysis header */\n\n#if defined( INC_ALL )\n  #include \"analyse.h\"\n#else\n  #include \"misc/analyse.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tConfig Options\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the cryptlib initialisation options file, which contains the\n   various USE_xxx defines that enable different cryptlib features */\n\n#if defined( INC_ALL )\n  #include \"config.h\"\n#else\n  #include \"misc/config.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSystem- and Compiler-Specific Interface\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the system and compiler-specific interface definitions.  This \n   uses the output from config.h to enable/disable system-specific \n   interfaces and options */\n\n#if defined( INC_ALL )\n  #include \"os_spec.h\"\n#else\n  #include \"misc/os_spec.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tData Size and Crypto-related Constants\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the data-size and crypt-related constants */\n\n#if defined( INC_ALL )\n  #include \"consts.h\"\n#else\n  #include \"misc/consts.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the cryptlib kernel interface defines */\n\n#include \"cryptkrn.h\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPortability Defines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write values as 32-bit big-endian data in cases where we're not \n   dealing with a stream.  Used to sample data from the crypto RNG to detect \n   stuck-at faults and in the debug version of clAlloc() */\n\n#define mgetLong( memPtr ) \\\n\t\t( ( ( unsigned long ) memPtr[ 0 ] << 24 ) | \\\n\t\t  ( ( unsigned long ) memPtr[ 1 ] << 16 ) | \\\n\t\t  ( ( unsigned long ) memPtr[ 2 ] << 8 ) | \\\n\t\t    ( unsigned long ) memPtr[ 3 ] ); \\\n\t\tmemPtr += 4\n\n#define mputLong( memPtr, data ) \\\n\t\tmemPtr[ 0 ] = ( BYTE ) ( ( ( data ) >> 24 ) & 0xFF ); \\\n\t\tmemPtr[ 1 ] = ( BYTE ) ( ( ( data ) >> 16 ) & 0xFF ); \\\n\t\tmemPtr[ 2 ] = ( BYTE ) ( ( ( data ) >> 8 ) & 0xFF ); \\\n\t\tmemPtr[ 3 ] = ( BYTE ) ( ( data ) & 0xFF ); \\\n\t\tmemPtr += 4\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Information on exported key/signature data.  This is an extended version\n   of the data returned by the externally-visible cryptQueryObject() routine */\n\n#define AUTHENCPARAM_MAX_SIZE\t128\n\ntypedef struct {\n\t/* Object format and status information */\n\tCRYPT_FORMAT_TYPE formatType;\t/* Object format type */\n\tCRYPT_OBJECT_TYPE type;\t\t\t/* Object type */\n\tlong size;\t\t\t\t\t\t/* Object size */\n\tVALUE( 0, 10 ) \\\n\tint version;\t\t\t\t\t/* Object format version */\n\n\t/* The encryption algorithm and mode */\n\tCRYPT_ALGO_TYPE cryptAlgo;\t\t/* The encryption algorithm */\n\tCRYPT_MODE_TYPE cryptMode;\t\t/* The encryption mode */\n\tint cryptAlgoParam;\t\t\t\t/* Optional algorithm parameter */\n\tint cryptAlgoEncoding;\t\t\t/* Optional encoding ALGOID_ENCODING_xxx */\n\n\t/* The key ID for public key objects */\n\tBUFFER( CRYPT_MAX_HASHSIZE, keyIDlength ) \\\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];/* PKC key ID */\n\tVALUE( 0, CRYPT_MAX_HASHSIZE ) \\\n\tint keyIDlength;\n\n\t/* The IV for conventionally encrypted data */\n\tBUFFER( CRYPT_MAX_IVSIZE, ivLength ) \\\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];/* IV */\n\tVALUE( 0, CRYPT_MAX_IVSIZE ) \\\n\tint ivLength;\n\n\t/* The key derivation algorithm and iteration count for conventionally\n\t   encrypted keys */\n\tCRYPT_ALGO_TYPE keySetupAlgo;\t/* Key setup algorithm */\n\tint keySetupAlgoParam;\t\t\t/* Optional parameter for key setup algo */\n\tint keySetupIterations;\t\t\t/* Key setup iteration count */\n\tint keySize;\t\t\t\t\t/* Key size (if not implicit) */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltLength ) \\\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];/* Key setup salt */\n\tVALUE( 0, CRYPT_MAX_HASHSIZE ) \\\n\tint saltLength;\n\n\t/* The hash algorithm for signatures */\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t/* Hash algorithm */\n\tint hashAlgoParam;\t\t\t\t/* Optional algorithm parameter */\n\n\t/* The encoded parameter data for authenticated encryption, and the\n\t   optional KDF and encryption and MAC algorithm parameter data within \n\t   that */\n\tBUFFER( AUTHENCPARAM_MAX_SIZE, authEncParamLength ) \\\n\tBYTE authEncParamData[ AUTHENCPARAM_MAX_SIZE + 8 ];\n\tVALUE( 0, AUTHENCPARAM_MAX_SIZE ) \\\n\tint authEncParamLength;\t\t\t/* AuthEnc parameter data */\n\tint kdfParamStart, kdfParamLength;\t/* Position of opt.KDF params */\n\tint encParamStart, encParamLength;\t/* Position of enc.parameters */\n\tint macParamStart, macParamLength;\t/* Position of MAC parameters */\n\n\t/* The start and length of the payload data, either the encrypted key or\n\t   the signature data */\n\tint dataStart, dataLength;\n\n\t/* The start and length of the issuerAndSerialNumber, authenticated \n\t   attributes, and unauthenticated attributes for CMS objects */\n\tint iAndSStart, iAndSLength;\n\tint attributeStart, attributeLength;\n\tint unauthAttributeStart, unauthAttributeLength;\n\t} QUERY_INFO;\n\n/* DLP algorithms require composite parameters when en/decrypting and\n   signing/sig checking, so we can't just pass in a single buffer full of\n   data as we can with RSA.  In addition the data length changes, for\n   example for a DSA sig we pass in a 20-byte hash and get back a ~50-byte\n   sig, for sig.checking we pass in a 20-byte hash and ~50-byte sig and get\n   back nothing.  Because of this we have to use the following structure to\n   pass data to the DLP-based PKCs */\n\ntypedef struct {\n\tBUFFER_FIXED( inLen1 ) \\\n\tconst BYTE *inParam1;\n\tBUFFER_OPT_FIXED( inLen2 ) \\\n\tconst BYTE *inParam2;\t\t\t\t/* Input parameters */\n\tBUFFER_FIXED( outLen ) \\\n\tBYTE *outParam;\t\t\t\t\t\t/* Output parameter */\n\tint inLen1, inLen2, outLen;\t\t\t/* Parameter lengths */\n\tCRYPT_FORMAT_TYPE formatType;\t\t/* Paramter format type */\n\t} DLP_PARAMS;\n\n#define setDLPParams( dlpDataPtr, dataIn, dataInLen, dataOut, dataOutLen ) \\\n\t{ \\\n\tmemset( ( dlpDataPtr ), 0, sizeof( DLP_PARAMS ) ); \\\n\t( dlpDataPtr )->formatType = CRYPT_FORMAT_CRYPTLIB; \\\n\t( dlpDataPtr )->inParam1 = ( dataIn ); \\\n\t( dlpDataPtr )->inLen1 = ( dataInLen ); \\\n\t( dlpDataPtr )->outParam = ( dataOut ); \\\n\t( dlpDataPtr )->outLen = ( dataOutLen ); \\\n\t}\n\n/* When calling key agreement functions we have to pass a mass of cruft\n   around instead of the usual flat data (even more than the generic DLP\n   parameter information) for which we use the following structure.  The\n   public value is the public key value used for the agreement process,\n   typically y = g^x mod p for DH-like mechanisms.  The ukm is the user\n   keying material, typically something which is mixed into the DH process\n   to make the new key unique.  The wrapped key is the output (originator)/\n   input(recipient) to the keyagreement process.  The session key context\n   contains a context into which the derived key is loaded.  Typical\n   examples of use are:\n\n\tPKCS #3: publicValue = y\n\tS/MIME: publicValue = y, ukm = 512-bit nonce, wrappedKey = g^x mod p\n\tSSH, SSL: publicValue = y, wrappedKey = x */\n\ntypedef struct {\n\tBUFFER( CRYPT_MAX_PKCSIZE, publicValueLen ) \\\n\tBYTE publicValue[ CRYPT_MAX_PKCSIZE + 8 ];\n\tVALUE( 0, CRYPT_MAX_PKCSIZE ) \\\n\tint publicValueLen;\t\t\t\t/* Public key value */\n\tBUFFER( CRYPT_MAX_PKCSIZE, wrappedKeyLen ) \\\n\tBYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];\n\tVALUE( 0, CRYPT_MAX_PKCSIZE ) \\\n\tint wrappedKeyLen;\t\t\t\t/* Wrapped key */\n\t} KEYAGREE_PARAMS;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUseful General Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Reasonably reliable way to get rid of unused argument warnings in a\n   compiler-independant manner */\n\n#define UNUSED_ARG( arg )\t( ( arg ) = ( arg ) )\n\n/* Although min() and max() aren't in the ANSI standard, most compilers have\n   them in one form or another, but just enough don't that we need to define \n   them ourselves in some cases */\n\n#if !defined( min )\n  #ifdef MIN\n\t#define min\t\t\tMIN\n\t#define max\t\t\tMAX\n  #else\n\t#define min( a, b )\t( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )\n\t#define max( a, b )\t( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )\n  #endif /* Various min/max macros */\n#endif /* !min/max */\n\n/* Macros to convert to and from the bit counts used for some encryption\n   parameters */\n\n#define bitsToBytes( bits )\t\t\t( ( ( bits ) + 7 ) >> 3 )\n#define bytesToBits( bytes )\t\t( ( bytes ) << 3 )\n\n/* When initialising a static block of bytes, it's useful to be able to \n   specify it as a character string, however this runs into problems with\n   the fact that the default char type is signed.  To get around this the\n   following macro declares a byte string as a set of unsigned bytes */\n\n#define MKDATA( x )\t\t\t\t\t( ( BYTE * ) ( x ) )\n\n/* Macro to round a value up to the nearest multiple of a second value,\n   with the second value being a power of 2 */\n\n#define roundUp( size, roundSize ) \\\n\t( ( ( size ) + ( ( roundSize ) - 1 ) ) & ~( ( roundSize ) - 1 ) )\n\n/* A macro to clear sensitive data from memory.  This is somewhat easier to\n   use than calling memset with the second parameter set to 0 all the time,\n   and makes it obvious where sensitive data is being erased.  In addition\n   some systems, recognising the problem of compilers removing what they see\n   as dead stores, have distinct memory zeroisation support, so if available \n   we use that */\n\n#if defined( _MSC_VER ) && VC_GE_2005( _MSC_VER )\n  /* This is just a mapping to RtlSecureZeroMemory() (via WinBase.h) which \n     is implemented as inline code implementing a loop on a pointer declared \n\t volatile, but unlike the corresponding RtlZeroMemory() there's a \n\t contract that this will always zeroise memory even in the face of \n\t compiler changes that would otherwise optimise away the access */\n  #define zeroise( memory, size )\tSecureZeroMemory( memory, size )\n#elif defined( __STDC_LIB_EXT1__ )\n  /* C11 defines a function memset_s() that guarantees that it won't be\n\t optimised away, although this is quite well obfuscated in the spec,\n\t \"the memory indicated by [the memset parameters] may be accessible in \n\t the future and therefore must contain the values indicated by [the\n\t value to set]\", hopefully the implementers will know that this equates\n\t to \"the memset_s() call can't be optimised away\" */\n  #define zeroise( memory, size )\tmemset_s( memory, size, 0, size )\n#elif defined( __OpenBSD__ )\n  /* The OpenBSD folks defined their own won't-be-optimised-away bzero()\n\t function */\n  #define zeroise( memory, size )\texplicit_bzero( memory, size )\n#else\n  #define zeroise( memory, size )\tmemset( memory, 0, size )\n#endif /* Systems with distinct zeroise functions */\n\n/* A macro to check that a value is a possibly valid handle.  This doesn't\n   check that the handle refers to a valid object, merely that the value is\n   in the range for valid handles.  The full function isValidHandle() used\n   in the kernel does check that the handle refers to a valid object, being\n   more than just a range check */\n\n#define isHandleRangeValid( handle ) \\\n\t\t( ( handle ) > NO_SYSTEM_OBJECTS - 1 && ( handle ) < MAX_NO_OBJECTS )\n\n/* A macro to check whether an encryption mode needs an IV or not */\n\n#define needsIV( mode )\t( ( mode ) == CRYPT_MODE_CBC || \\\n\t\t\t\t\t\t  ( mode ) == CRYPT_MODE_CFB || \\\n\t\t\t\t\t\t  ( mode ) == CRYPT_MODE_GCM )\n\n/* A macro to check whether an algorithm is a pure stream cipher (that is,\n   a real stream cipher rather than just a block cipher run in a stream\n   mode) */\n\n#define isStreamCipher( algorithm )\t\t( ( algorithm ) == CRYPT_ALGO_RC4 )\n\n/* Non-stream ciphers consist of { algorithm, mode } pairs, however pure\n   stream ciphers don't have any explicit mode, so we define a pseudo-mode\n   that can be used as a placeholder.  Using CRYPT_MODE_ECB, which is \n   IV-less, conveniently means that we pass any needsIV() checks */\n\n#define CRYPT_PSEUDOMODE_RC4\t\t\tCRYPT_MODE_ECB\n\n/* A macro to check whether an algorithm is regarded as being (relatively)\n   insecure or not.  This is used by some of the higher-level internal\n   routines that normally use the default algorithm set in the configuration\n   database if nothing else is explicitly specified, but that specifically\n   check for the weaker algorithms and use something stronger instead if a\n   weak algorithm is specified.  This is done both for luser-proofing and to\n   avoid possible problems from a trojan patching the configuration\n   database */\n\n#define isWeakCryptAlgo( algorithm )\t( ( algorithm ) == CRYPT_ALGO_DES || \\\n\t\t\t\t\t\t\t\t\t\t  ( algorithm ) == CRYPT_ALGO_RC2 || \\\n\t\t\t\t\t\t\t\t\t\t  ( algorithm ) == CRYPT_ALGO_RC4 )\n#define isWeakHashAlgo( algorithm )\t\t( ( algorithm ) == CRYPT_ALGO_MD5 )\n#define isWeakMacAlgo( algorithm )\t\t( 0 )\n\t\t\t\t\t\t\t\t\t\t/* None left with HMAC-MD5 deprecated */\n\n/* Macros to check for membership in overall algorithm classes */\n\n#define isConvAlgo( algorithm ) \\\n\t\t( ( algorithm ) >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t  ( algorithm ) <= CRYPT_ALGO_LAST_CONVENTIONAL )\n#define isPkcAlgo( algorithm ) \\\n\t\t( ( algorithm ) >= CRYPT_ALGO_FIRST_PKC && \\\n\t\t  ( algorithm ) <= CRYPT_ALGO_LAST_PKC )\n#define isHashAlgo( algorithm ) \\\n\t\t( ( algorithm ) >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t  ( algorithm ) <= CRYPT_ALGO_LAST_HASH )\n#define isHashMacExtAlgo( algorithm ) \\\n\t\t( ( algorithm ) == CRYPT_ALGO_SHA2 || \\\n\t\t  ( algorithm ) == CRYPT_ALGO_SHAng || \\\n\t\t  ( algorithm ) == CRYPT_ALGO_HMAC_SHA2 || \\\n\t\t  ( algorithm ) == CRYPT_ALGO_HMAC_SHAng )\n#define isMacAlgo( algorithm ) \\\n\t\t( ( algorithm ) >= CRYPT_ALGO_FIRST_MAC && \\\n\t\t  ( algorithm ) <= CRYPT_ALGO_LAST_MAC )\n#define isSpecialAlgo( algorithm ) \\\n\t\t( ( algorithm ) == CRYPT_IALGO_GENERIC_SECRET )\n\n/* Macros to check whether a PKC algorithm is useful for a certain purpose \n   or requires special-case handling.  Note that isDlpAlgo() doesn't include \n   the ECC algorithms, which are also based on the DLP (although in this \n   case the ECDLP and not the standard DLP).  This is a bit ugly but it's \n   used in various places to distinguish DLP-based PKCs from non-DLP-based\n   PKCs, while ECDLP-based-PKCs are in a separate class.  This means that\n   when checking for the extended class { DLP | ECDLP } it's necessary to\n   explicitly include isEccAlgo() alongside isDlpAlgo() */\n\n#define isSigAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_RSA || ( algorithm ) == CRYPT_ALGO_DSA || \\\n\t  ( algorithm ) == CRYPT_ALGO_ECDSA )\n#define isCryptAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_RSA || ( algorithm ) == CRYPT_ALGO_ELGAMAL )\n#define isKeyxAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_DH || ( algorithm ) == CRYPT_ALGO_ECDH )\n#define isDlpAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_DSA || ( algorithm ) == CRYPT_ALGO_ELGAMAL || \\\n\t  ( algorithm ) == CRYPT_ALGO_DH )\n#define isEccAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_ECDSA || ( algorithm ) == CRYPT_ALGO_ECDH )\n\n/* Macros to check whether an algorithm has additional parameters that need \n   to be handled explicitly */\n\n#define isParameterisedConvAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_AES )\n#define isParameterisedHashAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_SHA2 || ( algorithm ) == CRYPT_ALGO_SHAng )\n#define isParameterisedMacAlgo( algorithm ) \\\n\t( ( algorithm ) == CRYPT_ALGO_HMAC_SHA2 || \\\n\t  ( algorithm ) == CRYPT_ALGO_HMAC_SHAng )\n\n/* A macro to check whether an error status is related to a data-formatting\n   problem or some other problem.  This is used to provide extended string-\n   format error information, if it's a data error then the message being\n   processed was (probably) invalid, if it's not a data error then it may be\n   due to an invalid decryption key being used or something similar that's\n   unrelated to the message itself.\n   \n   The exact definition of what constitutes a \"data error\" is a bit vague \n   but since it's only used to control what additional error information is\n   returned a certain level of fuzziness is permitted */\n\n#define isDataError( status ) \\\n\t\t( ( status ) == CRYPT_ERROR_OVERFLOW || \\\n\t\t  ( status ) == CRYPT_ERROR_UNDERFLOW || \\\n\t\t  ( status ) == CRYPT_ERROR_BADDATA || \\\n\t\t  ( status ) == CRYPT_ERROR_SIGNATURE || \\\n\t\t  ( status ) == CRYPT_ERROR_NOTAVAIL || \\\n\t\t  ( status ) == CRYPT_ERROR_INCOMPLETE || \\\n\t\t  ( status ) == CRYPT_ERROR_COMPLETE || \\\n\t\t  ( status ) == CRYPT_ERROR_INVALID )\n\n/* A macro to check whether a public key is too short to be secure.  This\n   is a bit more complex than just a range check because any length below \n   about 512 bits is probably a bad data error, while lengths from about\n   512 bits to MIN_PKCSIZE (for standard PKCs) or 120 bits to \n   MIN_PKCSIZE_ECC are too-short key errors */\n\n#define isShortPKCKey( keySize ) \\\n\t\t( ( keySize ) >= MIN_PKCSIZE_THRESHOLD && \\\n\t\t  ( keySize ) < MIN_PKCSIZE )\n#define isShortECCKey( keySize ) \\\n\t\t( ( keySize ) >= MIN_PKCSIZE_ECC_THRESHOLD && \\\n\t\t  ( keySize ) < MIN_PKCSIZE_ECC )\n\n/* To avoid problems with signs, for example due to (signed) characters\n   being potentially converted to large signed integer values we perform a\n   safe conversion by going via an intermediate unsigned value, which in\n   the case of char -> int results in 0xFF turning into 0x000000FF rather\n   than 0xFFFFFFFF.\n   \n   For Visual Studio we explicitly mask some values to avoid runtime traps \n   in debug builds */\n\n#define byteToInt( x )\t\t\t\t( ( unsigned char ) ( x ) )\n#define intToLong( x )\t\t\t\t( ( unsigned int ) ( x ) )\n\n#define sizeToInt( x )\t\t\t\t( ( unsigned int ) ( x ) )\n#if defined( _MSC_VER ) && VC_GE_2010( _MSC_VER )\n  #define intToByte( x )\t\t\t( ( unsigned char ) ( ( x ) & 0xFF ) )\n#else\n  #define intToByte( x )\t\t\t( ( unsigned char ) ( x ) )\n#endif /* VS 2010 or newer */\n\n/* Clear/set object error information */\n\n#define clearErrorInfo( objectInfoPtr ) \\\n\t{ \\\n\t( objectInfoPtr )->errorLocus = CRYPT_ATTRIBUTE_NONE; \\\n\t( objectInfoPtr )->errorType = CRYPT_OK; \\\n\t}\n\n#define setErrorInfo( objectInfoPtr, locus, type ) \\\n\t{ \\\n\t( objectInfoPtr )->errorLocus = locus; \\\n\t( objectInfoPtr )->errorType = type; \\\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInternal API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the internal API function definitions and prototypes */\n\n#if defined( INC_ALL )\n  #include \"safety.h\"\t\t/* Must be before int_api.h for safe pointers */\n  #include \"int_api.h\"\n  #include \"list.h\"\n#else\n  #include \"misc/safety.h\"\t/* Must be before int_api.h for safe pointers */\n  #include \"misc/int_api.h\"\n  #include \"misc/list.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDebugging Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the debugging function definitions and prototypes */\n\n#if defined( INC_ALL )\n  #include \"debug.h\"\n  #include \"fault.h\"\n#else\n  #include \"misc/debug.h\"\n  #include \"misc/fault.h\"\n#endif /* Compiler-specific includes */\n\n#endif /* _CRYPT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/crypt32.def",
    "content": "; Definition file for the 32/64-bit cryptlib DLL.  Although the cryptlib \n; header file already provides all the information contained in this file, \n; the use of a redundant .DEF file is necessary because many non-C \n; development environments require the use of the Pascal calling convention \n; for Windows DLL's, however when this is used (via __stdcall) in VC++ it \n; mangles the function names, which means that other environments can't even \n; see the entry points, let alone call them.\n;\n; To avoid this, it's necessary to include this .DEF file to tell VC++ not to\n; mangle the exported names.  It'll still try to mangle them, but when the\n; linker sees the mangled names and the unmangled versions in this file, it\n; quietly forgets the mangled versions and uses these ones instead.\n;\n; An alternative way to fix this is to use a series of pragmas like:\n;\n;\t#pragma comment( linker, \"/export:cryptInit=_cryptInit:0\" )\n;\n; in one of the source modules, but this is even uglier than the .DEF hack.\n\nLIBRARY\t\tCL32\nEXPORTS\t\tcryptAddCertExtension\n\t\t\tcryptAddPrivateKey\n\t\t\tcryptAddPublicKey\n\t\t\tcryptAddRandom\n\t\t\tcryptCAAddItem\n\t\t\tcryptCACertManagement\n\t\t\tcryptCADeleteItem\n\t\t\tcryptCAGetItem\n\t\t\tcryptCheckCert\n\t\t\tcryptCheckSignature\n\t\t\tcryptCheckSignatureEx\n\t\t\tcryptCreateCert\n\t\t\tcryptCreateContext\n\t\t\tcryptCreateEnvelope\n\t\t\tcryptCreateSession\n\t\t\tcryptCreateSignature\n\t\t\tcryptCreateSignatureEx\n\t\t\tcryptDecrypt\n\t\t\tcryptDeleteAttribute\n\t\t\tcryptDeleteCertExtension\n\t\t\tcryptDeleteKey\n\t\t\tcryptDestroyCert\n\t\t\tcryptDestroyContext\n\t\t\tcryptDestroyEnvelope\n\t\t\tcryptDestroyObject\n\t\t\tcryptDestroySession\n\t\t\tcryptDeviceClose\n\t\t\tcryptDeviceCreateContext\n\t\t\tcryptDeviceOpen\n\t\t\tcryptDeviceQueryCapability\n\t\t\tcryptEncrypt\n\t\t\tcryptEnd\n\t\t\tcryptExportCert\n\t\t\tcryptExportKey\n\t\t\tcryptExportKeyEx\n\t\t\tcryptFlushData\n\t\t\tcryptGenerateKey\n\t\t\tcryptGetAttribute\n\t\t\tcryptGetAttributeString\n\t\t\tcryptGetCertExtension\n\t\t\tcryptGetKey\n\t\t\tcryptGetPrivateKey\n\t\t\tcryptGetPublicKey\n\t\t\tcryptImportCert\n\t\t\tcryptImportKey\n\t\t\tcryptImportKeyEx\n\t\t\tcryptInit\n\t\t\tcryptKeysetClose\n\t\t\tcryptKeysetOpen\n\t\t\tcryptLogin\n\t\t\tcryptLogout\n\t\t\tcryptPopData\n\t\t\tcryptPushData\n\t\t\tcryptQueryCapability\n\t\t\tcryptQueryObject\n\t\t\tcryptSetAttribute\n\t\t\tcryptSetAttributeString\n\t\t\tcryptSignCert\n"
  },
  {
    "path": "deps/cl345/crypt32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"Crypt32\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\n\nCFG=Crypt32 - Win32 Fuzz\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"crypt32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"crypt32.mak\" CFG=\"Crypt32 - Win32 Fuzz\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"Crypt32 - Win32 Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"Crypt32 - Win32 Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"Crypt32 - Win32 Purify\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"Crypt32 - Win32 Crosscompile\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"Crypt32 - Win32 Fuzz\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"Crypt32 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \".\\Release\"\n# PROP BASE Intermediate_Dir \".\\Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\release32_vc6\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"Release/\"\n# ADD F90 /I \"Release/\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /YX /c\n# ADD CPP /nologo /MD /W3 /O2 /I \".\\\\\" /D \"NDEBUG\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE MTL /nologo /D \"NDEBUG\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib netapi32.lib ws2_32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \".\\Debug\"\n# PROP BASE Intermediate_Dir \".\\Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\debug32_vc6\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"Debug/\"\n# ADD F90 /I \"Debug/\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /YX /c\n# ADD CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /D \"CONFIG_FAULTS\" /D \"CONFIG_DIRECT_API\" /Fr /FD /c\n# SUBTRACT CPP /YX /Yc /Yu\n# ADD BASE MTL /nologo /D \"_DEBUG\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT MTL /mktyplib203\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib netapi32.lib ws2_32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n# SUBTRACT LINK32 /map\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Purify\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Crypt32___Win32_Purify\"\n# PROP BASE Intermediate_Dir \"Crypt32___Win32_Purify\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\debug32_purify\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"Debug/\"\n# ADD F90 /I \"Debug/\"\n# ADD BASE CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /D \"NO_ASM\" /FD /c\n# SUBTRACT BASE CPP /Fr /YX\n# ADD CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /D \"NO_ASM\" /FD /c\n# SUBTRACT CPP /Fr /YX\n# ADD BASE MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT BASE MTL /mktyplib203\n# ADD MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT MTL /mktyplib203\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries/cl32.dll\"\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Crosscompile\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Crypt32___Win32_Crosscompile\"\n# PROP BASE Intermediate_Dir \"Crypt32___Win32_Crosscompile\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binaries_crosscompile\"\n# PROP Intermediate_Dir \"binaries_crosscompile\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"Debug/\"\n# ADD F90 /I \"Debug/\"\n# ADD BASE CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /D \"NO_ASM\" /FD /c\n# SUBTRACT BASE CPP /Fr /YX\n# ADD CPP /nologo /MD /W4 /Gm /Zi /Od /I \"./\" /I \"./embedded/mgos\" /I \"./embedded\" /D \"CROSSCOMPILE\" /D \"CONFIG_RANDSEED\" /FD /c\n# SUBTRACT CPP /Fr /YX\n# ADD BASE MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT BASE MTL /mktyplib203\n# ADD MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT MTL /mktyplib203\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Fuzz\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Crypt32___Win32_Fuzz\"\n# PROP BASE Intermediate_Dir \"Crypt32___Win32_Fuzz\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\binaries32_fuzz\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"Debug/\"\n# ADD F90 /I \"Debug/\"\n# ADD BASE CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /FD /c\n# SUBTRACT BASE CPP /Fr /YX /Yc /Yu\n# ADD CPP /nologo /MD /W4 /Gm /Zi /Od /I \".\\\\\" /D \"CONFIG_FUZZ\" /FD /c\n# SUBTRACT CPP /Fr /YX /Yc /Yu\n# ADD BASE MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT BASE MTL /mktyplib203\n# ADD MTL /nologo /D \"_DEBUG\" /win32\n# SUBTRACT MTL /mktyplib203\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib netapi32.lib /nologo /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib netapi32.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:\".\\binaries32_vc6/cl32.dll\"\n# SUBTRACT LINK32 /profile\n\n!ENDIF \n\n# Begin Target\n\n# Name \"Crypt32 - Win32 Release\"\n# Name \"Crypt32 - Win32 Debug\"\n# Name \"Crypt32 - Win32 Purify\"\n# Name \"Crypt32 - Win32 Crosscompile\"\n# Name \"Crypt32 - Win32 Fuzz\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90\"\n# Begin Group \"Bignum library\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\bn\\bn_asm.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_exp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_exp2.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_gcd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_mul.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_recp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\ec_lib.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\ec_mult.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\ecp_mont.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\ecp_smpl.c\n# End Source File\n# End Group\n# Begin Group \"Certificates\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\cert\\certrev.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certschk.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certsign.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certval.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chain.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_cert.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_chn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_san.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_use.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_cert.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_curs.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_del.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_get.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_gets.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_pkiu.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_set.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn_rw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn_rws.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn_string.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_add.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_chk.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_copy.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_def.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\imp_chk.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\imp_exp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\read.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\trustmgr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\write.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\write_pre.c\n# End Source File\n# End Group\n# Begin Group \"Contexts\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\context\\ctx_3des.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_aes.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bnmath.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bnpkc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bnprime.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bnrw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bnsieve.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bntest.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_cast.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_des.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_dh.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_dsa.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_ecdh.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_ecdsa.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_elg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_encr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_generic.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hsha.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hsha2.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_idea.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_md5.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_misc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rc2.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rc4.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rsa.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_sha.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_sha2.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_id.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_rdpri.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_rdpub.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\keyload.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_dlp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_ecc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_prime.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_rsa.c\n# End Source File\n# End Group\n# Begin Group \"Crypt/Hash algorithms\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\crypt\\aes_modes.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aescrypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aeskey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aestab.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castecb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castenc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castskey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\descbc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desecb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desecb3.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desenc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desskey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\gcm.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\gf128mul.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\icbc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\iecb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\iskey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\md5dgst.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2cbc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2ecb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2skey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc4enc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc4skey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\sha1dgst.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\sha2.c\n# End Source File\n# Begin Source File\n\nSOURCE=\".\\crypt\\d-win32.obj\"\n\n!IF  \"$(CFG)\" == \"Crypt32 - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Purify\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Crosscompile\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Fuzz\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aescryptx86.obj\n# End Source File\n# End Group\n# Begin Group \"Devices\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\device\\dev_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hardware.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hw_dummy.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\ms_capi.c\n\n!IF  \"$(CFG)\" == \"Crypt32 - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Purify\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Crosscompile\"\n\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Fuzz\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_init.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_pkc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\system.c\n# End Source File\n# End Group\n# Begin Group \"Encode/Decode\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_algid.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_chk.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_ext.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\base64.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\base64_id.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\misc_rw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\pgp_rw.c\n# End Source File\n# End Group\n# Begin Group \"Envelopes\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_denv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_env.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_envpre.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\decode.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\encode.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\env_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\pgp_denv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\pgp_env.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_actn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_denv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_env.c\n# End Source File\n# End Group\n# Begin Group \"I/O\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\io\\dns.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\dns_srv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\file.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_parse.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\memory.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_proxy.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_trans.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_url.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp_conn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp_err.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp_rw.c\n# End Source File\n# End Group\n# Begin Group \"Kernel\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\kernel\\attr_acl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\certm_acl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\init.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\int_msg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\key_acl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\mech_acl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\msg_acl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\obj_acc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\objects.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\sec_mem.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\selftest.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\semaphore.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\sendmsg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\storage.c\n# End Source File\n# End Group\n# Begin Group \"Keysets\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\http_keys.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\key_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ldap.c\n\n!IF  \"$(CFG)\" == \"Crypt32 - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Purify\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Crosscompile\"\n\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Fuzz\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_rdo.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_wr.c\n# End Source File\n# End Group\n# Begin Group \"Keysets - DBMS\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_add.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_clean.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_issue.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_misc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_rev.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbms.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_misc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\odbc.c\n# End Source File\n# End Group\n# Begin Group \"Keysets - PKCS15\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_add.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_adpb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_adpr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_atrd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_atwr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_get.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_getp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_set.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_wr.c\n# End Source File\n# End Group\n# Begin Group \"Mechanisms\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex_int.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex_rw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_cwrap.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_drv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_int.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_pkwrap.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_privk.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_sig.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\obj_qry.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_cms.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_int.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_pgp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_rw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_x509.c\n# End Source File\n# End Group\n# Begin Group \"Misc\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\crypt32.def\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt32.rc\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_api.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_debug.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_env.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_err.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_mem.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_string.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_time.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bindings\\java_jni.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\os_spec.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\pgp_misc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\rand_x917.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\random.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_cfg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_rw.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\win32.c\n\n!IF  \"$(CFG)\" == \"Crypt32 - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Purify\"\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Crosscompile\"\n\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"Crypt32 - Win32 Fuzz\"\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Sessions\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\scorebrd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_attr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_iattr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_ws.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\session.c\n# End Source File\n# End Group\n# Begin Group \"Sessions - SSH\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\ssh.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_authc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_auths.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_chn.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_cli.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msgc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msgs.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_svr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_wr.c\n# End Source File\n# End Group\n# Begin Group \"Sessions - SSL\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\ssl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_cli.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_ext.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_hs.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_hsc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_kmgmt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_suites.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_svr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_wr.c\n# End Source File\n# End Group\n# Begin Group \"Sessions - PKI\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\certstore.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_cli.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_err.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_rd.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_rdmsg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_svr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_wr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_wrmsg.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ocsp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\pnppki.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\rtcs.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep_cli.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep_svr.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\tsp.c\n# End Source File\n# End Group\n# Begin Group \"Zlib\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\zlib\\adler32.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\deflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inffast.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inftrees.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\trees.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\zutil.c\n# End Source File\n# End Group\n# Begin Source File\n\nSOURCE=.\\cryptapi.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptcrt.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptctx.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptdev.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptenv.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptkey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptlib.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptses.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptusr.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl;fi;fd\"\n# Begin Group \"Certificates - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\cert\\cert.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certattr.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certfn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\trustmgr.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\trustmgr_int.h\n# End Source File\n# End Group\n# Begin Group \"Devices - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\device\\capabil.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\device.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hardware.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_api.h\n# End Source File\n# End Group\n# Begin Group \"Encode/Decode - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_ext.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_oids.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\misc_rw.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\pgp_rw.h\n# End Source File\n# End Group\n# Begin Group \"I/O - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\io\\eap.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\file.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream_int.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp_int.h\n# End Source File\n# End Group\n# Begin Group \"Kernel - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\kernel\\acl.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\acl_perm.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptkrn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\kernel.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\thread.h\n# End Source File\n# End Group\n# Begin Group \"Keysets - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\dbms.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\keyset.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp_key.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15.h\n# End Source File\n# End Group\n# Begin Group \"Misc - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\misc\\analyse.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\config.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\debug.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\fault.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_api.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\list.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\os_detect.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\os_spec.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\random.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\random_int.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\safety.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_int.h\n# End Source File\n# End Group\n# Begin Group \"Sessions - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\certstore.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scorebrd.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scorebrd_int.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\session.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\websockets.h\n# End Source File\n# End Group\n# Begin Source File\n\nSOURCE=.\\context\\context.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\envelope.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\pgp.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe\"\n# Begin Source File\n\nSOURCE=.\\crypt32.ico\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/cl345/crypt32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"Crypt32\"=.\\crypt32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/cl345/crypt32.rc",
    "content": "/* cryptlib resource file.  We provide a slightly different version depending\n   on whether it's a debug or release build because some Windows lusers\n   complained about the fact that the code indicated a version of \"beta n\".\n   Shipping them exactly the same code renamed to \"SPn\" fixed the problem.\n\n   Unlike the C compiler, the resource compiler doesn't define platform-\n   specific macros, so it's necessary to do this manually via Properties |\n   Resources | General | Preprocessor Definitions */\n\n#ifdef APSTUDIO_INVOKED\n  #error This file should not be edited using the resource editor (ApStudio)\n#endif /* Resource editor fiddling with the file */\n\n#ifdef _WIN32_WCE\n  #include <winbase.h>\n#else\n  #include <winver.h>\n#endif /* Win32 vs. WinCE */\n#include \"misc/config.h\"\n\n/* If we're building with nonstandard options, mark it as a private build */\n\n#if defined( USE_CERT_DNSTRING ) || defined( USE_CRYPTOAPI ) || \\\n\tdefined( USE_DNSSRV ) || defined( USE_GCM ) || defined( USE_LDAP ) || \\\n\tdefined( USE_OAEP ) || defined( USE_PKCS12 ) || \\\n\tdefined( USE_SSH_EXTENDED ) || defined( USE_DES ) || \\\n\tdefined( USE_RC2 ) || defined( USE_RC4 )\n  #define PRIVATE_BUILD\n#endif /* Nonstandard config.options */\n\n/* cryptlib version information, needed at various places in the resources */\n\n#define VERSION\t\t3,4,5\n#define VERSION_STR\t\"3.4.5\\0\"\n\n/* The version information resource */\n\nVS_VERSION_INFO\t\tVERSIONINFO\nFILEVERSION\t\t\tVERSION\nPRODUCTVERSION\t\tVERSION\nFILEFLAGSMASK\t\tVS_FFI_FILEFLAGSMASK\n#if defined( _DEBUG )\n  FILEFLAGS\t\t\tVS_FF_DEBUG | VS_FF_PRIVATEBUILD | VS_FF_PRERELEASE\n#elif defined( PRIVATE_BUILD )\n  FILEFLAGS\t\t\tVS_FF_PRIVATEBUILD\n#else\n  FILEFLAGS\t\t\t0\n#endif /* _DEBUG */\n#ifdef _WIN32_WCE\n  #if UNDER_CE >= 400\n\tFILEOS\t\t\tVOS_WINDOWSCE\n  #else\n\tFILEOS\t\t\tVOS_NT_WINDOWS32\n  #endif /* Older vs. newer eVC++ versions */\n#else\n  FILEOS\t\t\tVOS_NT\n#endif /* Win32 vs. WinCE */\nFILETYPE\t\t\tVFT_DLL\nFILESUBTYPE\t\t\t0\t\t\t\t\t; Not needed for DLLs\nBEGIN\n  BLOCK \"VarFileInfo\"\n  BEGIN\n\tVALUE \"Translation\", 0x0409, 1252\t; US English, Windoze charset\n  END\n\n  BLOCK \"StringFileInfo\"\n  BEGIN\n\tBLOCK \"040904E4\"\t\t\t\t\t; US English, Windoze charset data\n\tBEGIN\n#if defined( _WIN32_WCE )\n\t  VALUE \"FileDescription\", \"cryptlib security toolkit for Windows CE\\0\"\n#elif defined( _WIN64 )\n\t  VALUE \"FileDescription\", \"cryptlib security toolkit (64 bit)\\0\"\n#else\n\t  VALUE \"FileDescription\", \"cryptlib security toolkit (32 bit)\\0\"\n#endif /* Win32 vs. WinCE */\n\t  VALUE \"ProductName\", \"cryptlib security toolkit\\0\"\n\t  VALUE \"CompanyName\", \"Peter Gutmann\\0\"\n\t  VALUE \"LegalCopyright\", \"Copyright \\251 1994 - 2019 Peter Gutmann, Eric Young, OpenSSL\\0\"\n\t  VALUE \"FileVersion\", VERSION_STR\n\t  VALUE \"ProductVersion\", VERSION_STR\n#if defined( _DEBUG )\n\t  VALUE \"PrivateBuild\", \"Debug/test build, not for production use!\\0\" ; Needed for VS_FF_PRIVATEBUILD\n#elif defined( PRIVATE_BUILD )\n\t  VALUE \"PrivateBuild\", \"Nonstandard build, not an official release\\0\" ; Needed for VS_FF_PRIVATEBUILD\n#endif /* _DEBUG */\n\tEND\n  END\nEND\n"
  },
  {
    "path": "deps/cl345/crypt32.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25420.1\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"crypt32\", \"crypt32.vcxproj\", \"{D0793AB4-C236-4105-AD9E-7E8B1716037B}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{F402D836-41AD-4B47-B8ED-DB857083E46F}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Win32 = Debug|Win32\n\t\tDebug|x64 = Debug|x64\n\t\tRelease|Win32 = Release|Win32\n\t\tRelease|x64 = Release|x64\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Debug|x64.Build.0 = Debug|x64\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Release|Win32.Build.0 = Release|Win32\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Release|x64.ActiveCfg = Release|x64\n\t\t{D0793AB4-C236-4105-AD9E-7E8B1716037B}.Release|x64.Build.0 = Release|x64\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/cl345/crypt32.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <!-- vv- Added to fix .NET bug - pcg -->\n  <!--\n  <PropertyGroup>\n    <TrackFileAccess>false</TrackFileAccess>\n  </PropertyGroup>\n-->\n  <!-- ^^- Added to fix .NET bug - pcg -->\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{D0793AB4-C236-4105-AD9E-7E8B1716037B}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>crypt32</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v142</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v142</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v142</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v142</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>.\\binaries32_vs10\\</OutDir>\n    <IntDir>.\\debug32_vs10\\</IntDir>\n    <TargetName>cl32</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>.\\binaries64_vs10\\</OutDir>\n    <IntDir>.\\debug64_vs10\\</IntDir>\n    <TargetName>cl64</TargetName>\n    <CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>.\\binaries32_vs10\\</OutDir>\n    <IntDir>.\\release32_vs10\\</IntDir>\n    <TargetName>cl32</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n    <OutDir>.\\binaries64_vs10\\</OutDir>\n    <IntDir>.\\release64_vs10\\</IntDir>\n    <TargetName>cl64</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level4</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CRYPT32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ExceptionHandling>false</ExceptionHandling>\n      <SmallerTypeCheck>false</SmallerTypeCheck>\n      <AdditionalIncludeDirectories>.\\</AdditionalIncludeDirectories>\n      <ControlFlowGuard>false</ControlFlowGuard>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;netapi32.lib;dnsapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\n      <ManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</ManifestFile>\n      <ModuleDefinitionFile>.\\crypt32.def</ModuleDefinitionFile>\n      <Profile>false</Profile>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level4</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CRYPT32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ExceptionHandling>false</ExceptionHandling>\n      <SmallerTypeCheck>false</SmallerTypeCheck>\n      <AdditionalIncludeDirectories>.\\</AdditionalIncludeDirectories>\n      <ControlFlowGuard>false</ControlFlowGuard>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;netapi32.lib;dnsapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\n      <ManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</ManifestFile>\n      <ModuleDefinitionFile>\n      </ModuleDefinitionFile>\n      <Profile>false</Profile>\n    </Link>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_WIN64</PreprocessorDefinitions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level4</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CRYPT32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>.\\</AdditionalIncludeDirectories>\n      <StringPooling>true</StringPooling>\n      <ExceptionHandling>false</ExceptionHandling>\n      <ControlFlowGuard>Guard</ControlFlowGuard>\n      <WholeProgramOptimization>true</WholeProgramOptimization>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;netapi32.lib;dnsapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\n      <ManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</ManifestFile>\n      <ModuleDefinitionFile>.\\crypt32.def</ModuleDefinitionFile>\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level4</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CRYPT32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>.\\</AdditionalIncludeDirectories>\n      <ExceptionHandling>false</ExceptionHandling>\n      <StringPooling>true</StringPooling>\n      <ControlFlowGuard>Guard</ControlFlowGuard>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;netapi32.lib;dnsapi.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>\n      <ManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</ManifestFile>\n      <ModuleDefinitionFile>\n      </ModuleDefinitionFile>\n      <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>\n    </Link>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_WIN64</PreprocessorDefinitions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <Object Include=\"crypt\\aescryptx64.obj\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </Object>\n    <Object Include=\"crypt\\aescryptx86.obj\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\n    </Object>\n    <Object Include=\"crypt\\d-win32.obj\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\n    </Object>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"crypt32.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"crypt32.def\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">true</ExcludedFromBuild>\n    </None>\n    <None Include=\"crypt32.ico\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"bindings\\java_jni.c\" />\n    <ClCompile Include=\"bn\\bn_asm.c\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">false</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">false</ExcludedFromBuild>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_exp.c\" />\n    <ClCompile Include=\"bn\\bn_exp2.c\" />\n    <ClCompile Include=\"bn\\bn_gcd.c\" />\n    <ClCompile Include=\"bn\\bn_mul.c\" />\n    <ClCompile Include=\"bn\\bn_recp.c\" />\n    <ClCompile Include=\"bn\\ecp_mont.c\" />\n    <ClCompile Include=\"bn\\ecp_smpl.c\" />\n    <ClCompile Include=\"bn\\ec_lib.c\" />\n    <ClCompile Include=\"bn\\ec_mult.c\" />\n    <ClCompile Include=\"cert\\certrev.c\" />\n    <ClCompile Include=\"cert\\certschk.c\" />\n    <ClCompile Include=\"cert\\certsign.c\" />\n    <ClCompile Include=\"cert\\certval.c\" />\n    <ClCompile Include=\"cert\\chain.c\" />\n    <ClCompile Include=\"cert\\chk_cert.c\" />\n    <ClCompile Include=\"cert\\chk_chn.c\" />\n    <ClCompile Include=\"cert\\chk_san.c\" />\n    <ClCompile Include=\"cert\\chk_use.c\" />\n    <ClCompile Include=\"cert\\comp_cert.c\" />\n    <ClCompile Include=\"cert\\comp_curs.c\" />\n    <ClCompile Include=\"cert\\comp_del.c\" />\n    <ClCompile Include=\"cert\\comp_get.c\" />\n    <ClCompile Include=\"cert\\comp_gets.c\" />\n    <ClCompile Include=\"cert\\comp_pkiu.c\" />\n    <ClCompile Include=\"cert\\comp_set.c\" />\n    <ClCompile Include=\"cert\\dn.c\" />\n    <ClCompile Include=\"cert\\dn_rw.c\" />\n    <ClCompile Include=\"cert\\dn_rws.c\" />\n    <ClCompile Include=\"cert\\dn_string.c\" />\n    <ClCompile Include=\"cert\\ext.c\" />\n    <ClCompile Include=\"cert\\ext_add.c\" />\n    <ClCompile Include=\"cert\\ext_chk.c\" />\n    <ClCompile Include=\"cert\\ext_copy.c\" />\n    <ClCompile Include=\"cert\\ext_def.c\" />\n    <ClCompile Include=\"cert\\ext_rd.c\" />\n    <ClCompile Include=\"cert\\ext_wr.c\" />\n    <ClCompile Include=\"cert\\imp_chk.c\" />\n    <ClCompile Include=\"cert\\imp_exp.c\" />\n    <ClCompile Include=\"cert\\read.c\" />\n    <ClCompile Include=\"cert\\trustmgr.c\" />\n    <ClCompile Include=\"cert\\write.c\" />\n    <ClCompile Include=\"cert\\write_pre.c\" />\n    <ClCompile Include=\"context\\ctx_3des.c\" />\n    <ClCompile Include=\"context\\ctx_aes.c\" />\n    <ClCompile Include=\"context\\ctx_attr.c\" />\n    <ClCompile Include=\"context\\ctx_bn.c\" />\n    <ClCompile Include=\"context\\ctx_bnmath.c\" />\n    <ClCompile Include=\"context\\ctx_bnpkc.c\" />\n    <ClCompile Include=\"context\\ctx_bnprime.c\" />\n    <ClCompile Include=\"context\\ctx_bnrw.c\" />\n    <ClCompile Include=\"context\\ctx_bnsieve.c\" />\n    <ClCompile Include=\"context\\ctx_bntest.c\" />\n    <ClCompile Include=\"context\\ctx_cast.c\" />\n    <ClCompile Include=\"context\\ctx_des.c\" />\n    <ClCompile Include=\"context\\ctx_dh.c\" />\n    <ClCompile Include=\"context\\ctx_dsa.c\" />\n    <ClCompile Include=\"context\\ctx_ecdh.c\" />\n    <ClCompile Include=\"context\\ctx_ecdsa.c\" />\n    <ClCompile Include=\"context\\ctx_elg.c\" />\n    <ClCompile Include=\"context\\ctx_encr.c\" />\n    <ClCompile Include=\"context\\ctx_generic.c\" />\n    <ClCompile Include=\"context\\ctx_hsha.c\" />\n    <ClCompile Include=\"context\\ctx_hsha2.c\" />\n    <ClCompile Include=\"context\\ctx_idea.c\" />\n    <ClCompile Include=\"context\\ctx_md5.c\" />\n    <ClCompile Include=\"context\\ctx_misc.c\" />\n    <ClCompile Include=\"context\\ctx_rc2.c\" />\n    <ClCompile Include=\"context\\ctx_rc4.c\" />\n    <ClCompile Include=\"context\\ctx_rsa.c\" />\n    <ClCompile Include=\"context\\ctx_sha.c\" />\n    <ClCompile Include=\"context\\ctx_sha2.c\" />\n    <ClCompile Include=\"context\\keyload.c\" />\n    <ClCompile Include=\"context\\key_id.c\" />\n    <ClCompile Include=\"context\\key_rdpri.c\" />\n    <ClCompile Include=\"context\\key_rdpub.c\" />\n    <ClCompile Include=\"context\\key_wr.c\" />\n    <ClCompile Include=\"context\\kg_dlp.c\" />\n    <ClCompile Include=\"context\\kg_ecc.c\" />\n    <ClCompile Include=\"context\\kg_prime.c\" />\n    <ClCompile Include=\"context\\kg_rsa.c\" />\n    <ClCompile Include=\"cryptapi.c\" />\n    <ClCompile Include=\"cryptcrt.c\" />\n    <ClCompile Include=\"cryptctx.c\" />\n    <ClCompile Include=\"cryptdev.c\" />\n    <ClCompile Include=\"cryptenv.c\" />\n    <ClCompile Include=\"cryptkey.c\" />\n    <ClCompile Include=\"cryptlib.c\" />\n    <ClCompile Include=\"cryptses.c\" />\n    <ClCompile Include=\"cryptusr.c\" />\n    <ClCompile Include=\"crypt\\aescrypt.c\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aeskey.c\" />\n    <ClCompile Include=\"crypt\\aestab.c\" />\n    <ClCompile Include=\"crypt\\aes_modes.c\" />\n    <ClCompile Include=\"crypt\\aes_ni.c\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\castecb.c\" />\n    <ClCompile Include=\"crypt\\castenc.c\" />\n    <ClCompile Include=\"crypt\\castskey.c\" />\n    <ClCompile Include=\"crypt\\descbc.c\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desecb.c\" />\n    <ClCompile Include=\"crypt\\desecb3.c\" />\n    <ClCompile Include=\"crypt\\desenc.c\">\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desskey.c\" />\n    <ClCompile Include=\"crypt\\gcm.c\" />\n    <ClCompile Include=\"crypt\\gf128mul.c\" />\n    <ClCompile Include=\"crypt\\icbc.c\" />\n    <ClCompile Include=\"crypt\\iecb.c\" />\n    <ClCompile Include=\"crypt\\iskey.c\" />\n    <ClCompile Include=\"crypt\\md5dgst.c\" />\n    <ClCompile Include=\"crypt\\rc2cbc.c\" />\n    <ClCompile Include=\"crypt\\rc2ecb.c\" />\n    <ClCompile Include=\"crypt\\rc2skey.c\" />\n    <ClCompile Include=\"crypt\\rc4enc.c\" />\n    <ClCompile Include=\"crypt\\rc4skey.c\" />\n    <ClCompile Include=\"crypt\\sha1dgst.c\" />\n    <ClCompile Include=\"crypt\\sha2.c\" />\n    <ClCompile Include=\"device\\dev_attr.c\" />\n    <ClCompile Include=\"device\\hardware.c\" />\n    <ClCompile Include=\"device\\hw_dummy.c\" />\n    <ClCompile Include=\"device\\ms_capi.c\" />\n    <ClCompile Include=\"device\\pkcs11.c\" />\n    <ClCompile Include=\"device\\pkcs11_init.c\" />\n    <ClCompile Include=\"device\\pkcs11_pkc.c\" />\n    <ClCompile Include=\"device\\pkcs11_rd.c\" />\n    <ClCompile Include=\"device\\pkcs11_wr.c\" />\n    <ClCompile Include=\"device\\system.c\" />\n    <ClCompile Include=\"enc_dec\\asn1_algid.c\" />\n    <ClCompile Include=\"enc_dec\\asn1_chk.c\" />\n    <ClCompile Include=\"enc_dec\\asn1_ext.c\" />\n    <ClCompile Include=\"enc_dec\\asn1_rd.c\" />\n    <ClCompile Include=\"enc_dec\\asn1_wr.c\" />\n    <ClCompile Include=\"enc_dec\\base64.c\" />\n    <ClCompile Include=\"enc_dec\\base64_id.c\" />\n    <ClCompile Include=\"enc_dec\\misc_rw.c\" />\n    <ClCompile Include=\"enc_dec\\pgp_rw.c\" />\n    <ClCompile Include=\"envelope\\cms_denv.c\" />\n    <ClCompile Include=\"envelope\\cms_env.c\" />\n    <ClCompile Include=\"envelope\\cms_envpre.c\" />\n    <ClCompile Include=\"envelope\\decode.c\" />\n    <ClCompile Include=\"envelope\\encode.c\" />\n    <ClCompile Include=\"envelope\\env_attr.c\" />\n    <ClCompile Include=\"envelope\\pgp_denv.c\" />\n    <ClCompile Include=\"envelope\\pgp_env.c\" />\n    <ClCompile Include=\"envelope\\res_actn.c\" />\n    <ClCompile Include=\"envelope\\res_denv.c\" />\n    <ClCompile Include=\"envelope\\res_env.c\" />\n    <ClCompile Include=\"io\\dns.c\" />\n    <ClCompile Include=\"io\\dns_srv.c\" />\n    <ClCompile Include=\"io\\file.c\" />\n    <ClCompile Include=\"io\\http.c\" />\n    <ClCompile Include=\"io\\http_parse.c\" />\n    <ClCompile Include=\"io\\http_rd.c\" />\n    <ClCompile Include=\"io\\http_wr.c\" />\n    <ClCompile Include=\"io\\memory.c\" />\n    <ClCompile Include=\"io\\net.c\" />\n    <ClCompile Include=\"io\\net_proxy.c\" />\n    <ClCompile Include=\"io\\net_trans.c\" />\n    <ClCompile Include=\"io\\net_url.c\" />\n    <ClCompile Include=\"io\\stream.c\" />\n    <ClCompile Include=\"io\\tcp.c\" />\n    <ClCompile Include=\"io\\tcp_conn.c\" />\n    <ClCompile Include=\"io\\tcp_err.c\" />\n    <ClCompile Include=\"io\\tcp_rw.c\" />\n    <ClCompile Include=\"kernel\\attr_acl.c\" />\n    <ClCompile Include=\"kernel\\certm_acl.c\" />\n    <ClCompile Include=\"kernel\\init.c\" />\n    <ClCompile Include=\"kernel\\int_msg.c\" />\n    <ClCompile Include=\"kernel\\key_acl.c\" />\n    <ClCompile Include=\"kernel\\mech_acl.c\" />\n    <ClCompile Include=\"kernel\\msg_acl.c\" />\n    <ClCompile Include=\"kernel\\objects.c\" />\n    <ClCompile Include=\"kernel\\obj_acc.c\" />\n    <ClCompile Include=\"kernel\\sec_mem.c\" />\n    <ClCompile Include=\"kernel\\selftest.c\" />\n    <ClCompile Include=\"kernel\\semaphore.c\" />\n    <ClCompile Include=\"kernel\\sendmsg.c\" />\n    <ClCompile Include=\"kernel\\storage.c\" />\n    <ClCompile Include=\"keyset\\ca_add.c\" />\n    <ClCompile Include=\"keyset\\ca_clean.c\" />\n    <ClCompile Include=\"keyset\\ca_issue.c\" />\n    <ClCompile Include=\"keyset\\ca_misc.c\" />\n    <ClCompile Include=\"keyset\\ca_rev.c\" />\n    <ClCompile Include=\"keyset\\dbms.c\" />\n    <ClCompile Include=\"keyset\\dbx_misc.c\" />\n    <ClCompile Include=\"keyset\\dbx_rd.c\" />\n    <ClCompile Include=\"keyset\\dbx_wr.c\" />\n    <ClCompile Include=\"keyset\\http_keys.c\" />\n    <ClCompile Include=\"keyset\\key_attr.c\" />\n    <ClCompile Include=\"keyset\\ldap.c\" />\n    <ClCompile Include=\"keyset\\odbc.c\" />\n    <ClCompile Include=\"keyset\\pgp.c\" />\n    <ClCompile Include=\"keyset\\pgp_rd.c\" />\n    <ClCompile Include=\"keyset\\pgp_wr.c\" />\n    <ClCompile Include=\"keyset\\pkcs12.c\" />\n    <ClCompile Include=\"keyset\\pkcs12_rd.c\" />\n    <ClCompile Include=\"keyset\\pkcs12_rdo.c\" />\n    <ClCompile Include=\"keyset\\pkcs12_wr.c\" />\n    <ClCompile Include=\"keyset\\pkcs15.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_add.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_adpb.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_adpr.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_atrd.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_atwr.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_get.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_getp.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_rd.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_set.c\" />\n    <ClCompile Include=\"keyset\\pkcs15_wr.c\" />\n    <ClCompile Include=\"mechs\\keyex.c\" />\n    <ClCompile Include=\"mechs\\keyex_int.c\" />\n    <ClCompile Include=\"mechs\\keyex_rw.c\" />\n    <ClCompile Include=\"mechs\\mech_cwrap.c\" />\n    <ClCompile Include=\"mechs\\mech_drv.c\" />\n    <ClCompile Include=\"mechs\\mech_int.c\" />\n    <ClCompile Include=\"mechs\\mech_pkwrap.c\" />\n    <ClCompile Include=\"mechs\\mech_privk.c\" />\n    <ClCompile Include=\"mechs\\mech_sig.c\" />\n    <ClCompile Include=\"mechs\\obj_qry.c\" />\n    <ClCompile Include=\"mechs\\sign.c\" />\n    <ClCompile Include=\"mechs\\sign_cms.c\" />\n    <ClCompile Include=\"mechs\\sign_int.c\" />\n    <ClCompile Include=\"mechs\\sign_pgp.c\" />\n    <ClCompile Include=\"mechs\\sign_rw.c\" />\n    <ClCompile Include=\"mechs\\sign_x509.c\" />\n    <ClCompile Include=\"misc\\int_api.c\" />\n    <ClCompile Include=\"misc\\int_attr.c\" />\n    <ClCompile Include=\"misc\\int_debug.c\" />\n    <ClCompile Include=\"misc\\int_env.c\" />\n    <ClCompile Include=\"misc\\int_err.c\" />\n    <ClCompile Include=\"misc\\int_mem.c\" />\n    <ClCompile Include=\"misc\\int_string.c\" />\n    <ClCompile Include=\"misc\\int_time.c\" />\n    <ClCompile Include=\"misc\\os_spec.c\" />\n    <ClCompile Include=\"misc\\pgp_misc.c\" />\n    <ClCompile Include=\"misc\\user.c\" />\n    <ClCompile Include=\"misc\\user_attr.c\" />\n    <ClCompile Include=\"misc\\user_cfg.c\" />\n    <ClCompile Include=\"misc\\user_rw.c\" />\n    <ClCompile Include=\"random\\random.c\" />\n    <ClCompile Include=\"random\\rand_x917.c\" />\n    <ClCompile Include=\"random\\win32.c\" />\n    <ClCompile Include=\"session\\certstore.c\" />\n    <ClCompile Include=\"session\\cmp.c\" />\n    <ClCompile Include=\"session\\cmp_cli.c\" />\n    <ClCompile Include=\"session\\cmp_crypt.c\" />\n    <ClCompile Include=\"session\\cmp_err.c\" />\n    <ClCompile Include=\"session\\cmp_rd.c\" />\n    <ClCompile Include=\"session\\cmp_rdmsg.c\" />\n    <ClCompile Include=\"session\\cmp_svr.c\" />\n    <ClCompile Include=\"session\\cmp_wr.c\" />\n    <ClCompile Include=\"session\\cmp_wrmsg.c\" />\n    <ClCompile Include=\"session\\ocsp.c\" />\n    <ClCompile Include=\"session\\pnppki.c\" />\n    <ClCompile Include=\"session\\rtcs.c\" />\n    <ClCompile Include=\"session\\scep.c\" />\n    <ClCompile Include=\"session\\scep_cli.c\" />\n    <ClCompile Include=\"session\\scep_svr.c\" />\n    <ClCompile Include=\"session\\scorebrd.c\" />\n    <ClCompile Include=\"session\\session.c\" />\n    <ClCompile Include=\"session\\sess_attr.c\" />\n    <ClCompile Include=\"session\\sess_iattr.c\" />\n    <ClCompile Include=\"session\\sess_rd.c\" />\n    <ClCompile Include=\"session\\sess_wr.c\" />\n    <ClCompile Include=\"session\\sess_ws.c\" />\n    <ClCompile Include=\"session\\ssh.c\" />\n    <ClCompile Include=\"session\\ssh2.c\" />\n    <ClCompile Include=\"session\\ssh2_authc.c\" />\n    <ClCompile Include=\"session\\ssh2_auths.c\" />\n    <ClCompile Include=\"session\\ssh2_chn.c\" />\n    <ClCompile Include=\"session\\ssh2_cli.c\" />\n    <ClCompile Include=\"session\\ssh2_crypt.c\" />\n    <ClCompile Include=\"session\\ssh2_msg.c\" />\n    <ClCompile Include=\"session\\ssh2_msgc.c\" />\n    <ClCompile Include=\"session\\ssh2_msgs.c\" />\n    <ClCompile Include=\"session\\ssh2_rd.c\" />\n    <ClCompile Include=\"session\\ssh2_svr.c\" />\n    <ClCompile Include=\"session\\ssh2_wr.c\" />\n    <ClCompile Include=\"session\\ssl.c\" />\n    <ClCompile Include=\"session\\ssl_cli.c\" />\n    <ClCompile Include=\"session\\ssl_crypt.c\" />\n    <ClCompile Include=\"session\\ssl_ext.c\" />\n    <ClCompile Include=\"session\\ssl_hs.c\" />\n    <ClCompile Include=\"session\\ssl_hsc.c\" />\n    <ClCompile Include=\"session\\ssl_kmgmt.c\" />\n    <ClCompile Include=\"session\\ssl_rd.c\" />\n    <ClCompile Include=\"session\\ssl_suites.c\" />\n    <ClCompile Include=\"session\\ssl_svr.c\" />\n    <ClCompile Include=\"session\\ssl_wr.c\" />\n    <ClCompile Include=\"session\\tsp.c\" />\n    <ClCompile Include=\"zlib\\adler32.c\" />\n    <ClCompile Include=\"zlib\\deflate.c\" />\n    <ClCompile Include=\"zlib\\inffast.c\" />\n    <ClCompile Include=\"zlib\\inflate.c\" />\n    <ClCompile Include=\"zlib\\inftrees.c\" />\n    <ClCompile Include=\"zlib\\trees.c\" />\n    <ClCompile Include=\"zlib\\zutil.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"cert\\cert.h\" />\n    <ClInclude Include=\"cert\\certattr.h\" />\n    <ClInclude Include=\"cert\\certfn.h\" />\n    <ClInclude Include=\"cert\\dn.h\" />\n    <ClInclude Include=\"cert\\trustmgr.h\" />\n    <ClInclude Include=\"context\\context.h\" />\n    <ClInclude Include=\"crypt.h\" />\n    <ClInclude Include=\"cryptkrn.h\" />\n    <ClInclude Include=\"cryptlib.h\" />\n    <ClInclude Include=\"device\\capabil.h\" />\n    <ClInclude Include=\"device\\device.h\" />\n    <ClInclude Include=\"device\\hardware.h\" />\n    <ClInclude Include=\"device\\pkcs11.h\" />\n    <ClInclude Include=\"device\\pkcs11f.h\" />\n    <ClInclude Include=\"device\\pkcs11t.h\" />\n    <ClInclude Include=\"device\\pkcs11_api.h\" />\n    <ClInclude Include=\"enc_dec\\asn1.h\" />\n    <ClInclude Include=\"enc_dec\\asn1_ext.h\" />\n    <ClInclude Include=\"enc_dec\\asn1_oids.h\" />\n    <ClInclude Include=\"enc_dec\\misc_rw.h\" />\n    <ClInclude Include=\"enc_dec\\pgp_rw.h\" />\n    <ClInclude Include=\"envelope\\envelope.h\" />\n    <ClInclude Include=\"io\\file.h\" />\n    <ClInclude Include=\"io\\http.h\" />\n    <ClInclude Include=\"io\\stream.h\" />\n    <ClInclude Include=\"io\\stream_int.h\" />\n    <ClInclude Include=\"io\\tcp.h\" />\n    <ClInclude Include=\"io\\tcp_int.h\" />\n    <ClInclude Include=\"kernel\\acl.h\" />\n    <ClInclude Include=\"kernel\\acl_perm.h\" />\n    <ClInclude Include=\"kernel\\kernel.h\" />\n    <ClInclude Include=\"kernel\\thread.h\" />\n    <ClInclude Include=\"keyset\\dbms.h\" />\n    <ClInclude Include=\"keyset\\keyset.h\" />\n    <ClInclude Include=\"keyset\\pgp_key.h\" />\n    <ClInclude Include=\"keyset\\pkcs12.h\" />\n    <ClInclude Include=\"keyset\\pkcs15.h\" />\n    <ClInclude Include=\"mechs\\mech.h\" />\n    <ClInclude Include=\"misc\\analyse.h\" />\n    <ClInclude Include=\"misc\\config.h\" />\n    <ClInclude Include=\"misc\\consts.h\" />\n    <ClInclude Include=\"misc\\debug.h\" />\n    <ClInclude Include=\"misc\\fault.h\" />\n    <ClInclude Include=\"misc\\int_api.h\" />\n    <ClInclude Include=\"misc\\os_spec.h\" />\n    <ClInclude Include=\"misc\\pgp.h\" />\n    <ClInclude Include=\"misc\\user.h\" />\n    <ClInclude Include=\"random\\random.h\" />\n    <ClInclude Include=\"random\\random_int.h\" />\n    <ClInclude Include=\"session\\certstore.h\" />\n    <ClInclude Include=\"session\\cmp.h\" />\n    <ClInclude Include=\"session\\eap.h\" />\n    <ClInclude Include=\"session\\scep.h\" />\n    <ClInclude Include=\"session\\scorebrd.h\" />\n    <ClInclude Include=\"session\\session.h\" />\n    <ClInclude Include=\"session\\ssh.h\" />\n    <ClInclude Include=\"session\\ssl.h\" />\n    <ClInclude Include=\"session\\websockets.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/cl345/crypt32.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n    <Filter Include=\"Source Files\\Bignum Library\">\n      <UniqueIdentifier>{13465a66-c28a-45f0-8439-427cd0bbc0e7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Certificates\">\n      <UniqueIdentifier>{24e2440e-9c91-42a9-add7-e0dfd5902884}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Contexts\">\n      <UniqueIdentifier>{ccc22b85-8080-4b85-abe9-cd405fbd7479}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Crypt/Hash Algorithms\">\n      <UniqueIdentifier>{f889013c-64a7-4569-b207-851f6a51bd81}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Devices\">\n      <UniqueIdentifier>{e929d6fa-6e4f-43ae-af0a-2c41d74820bb}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Encode/Decode\">\n      <UniqueIdentifier>{fc76204f-7030-447f-b73c-00e336ac5daf}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Envelopes\">\n      <UniqueIdentifier>{369eeec8-9848-4fc2-9a34-024c86279867}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\I/O\">\n      <UniqueIdentifier>{7656dab1-156b-4da1-8276-95703e6c3a67}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Kernel\">\n      <UniqueIdentifier>{c8dec72b-b631-4914-99cc-69d25a9262a1}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Keysets\">\n      <UniqueIdentifier>{c2c4c634-a719-449c-ae01-dddb8776dcc1}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Keysets - DBMS\">\n      <UniqueIdentifier>{cf9cfd67-6d3a-455f-ace1-3b34d42e79a2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Keysets - PKCS15\">\n      <UniqueIdentifier>{39666509-4396-4286-9c3b-cfdd4fda3af6}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Mechanisms\">\n      <UniqueIdentifier>{d5a2eb35-b4b7-4ab2-badb-c1b0827ae89f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Misc\">\n      <UniqueIdentifier>{24bb79a5-5b36-4b2a-aa79-7ead83b6a19e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Sessions\">\n      <UniqueIdentifier>{631da61f-8f6f-42b9-b889-1e50c6bb84af}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Sessions - PKI\">\n      <UniqueIdentifier>{c325b029-c829-48a7-8369-ad810721b159}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Sessions - SSH\">\n      <UniqueIdentifier>{80fbf6fe-52bf-4946-aede-f1c6d407ff37}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Sessions - SSL\">\n      <UniqueIdentifier>{009e0c4b-be2a-4215-ab2e-38d2db4eba71}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\Zlib\">\n      <UniqueIdentifier>{3b78ee8b-c8c5-4165-a192-f3e6ef1d1754}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Certificates - Headers\">\n      <UniqueIdentifier>{0a815ca7-f5ff-4bc6-91f6-7eb503141a16}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Devices - Headers\">\n      <UniqueIdentifier>{bf6e9b4a-32e2-429f-924c-fde6bf2764e7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Encode/Decode - Headers\">\n      <UniqueIdentifier>{ee1a35f1-f5f9-4c36-8a59-5ad99abfd101}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\I/O - Headers\">\n      <UniqueIdentifier>{304d484b-6c3b-438b-bc55-0ac26dfd8581}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Kernel - Headers\">\n      <UniqueIdentifier>{846545be-3645-4890-98bd-e198bea48d5a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Keysets - Headers\">\n      <UniqueIdentifier>{f4d9a946-dfc4-4bfa-a38e-e5f5ab0b4768}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Sessions - Headers\">\n      <UniqueIdentifier>{90481694-686f-46ba-b5b3-e1b52bfd25d0}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\Misc - Headers\">\n      <UniqueIdentifier>{574a8302-ef28-4be2-ae36-d2bd12cef02a}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <Object Include=\"crypt\\d-win32.obj\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </Object>\n    <Object Include=\"crypt\\aescryptx86.obj\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </Object>\n    <Object Include=\"crypt\\aescryptx64.obj\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </Object>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"crypt32.rc\">\n      <Filter>Resource Files</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"crypt32.ico\">\n      <Filter>Resource Files</Filter>\n    </None>\n    <None Include=\"crypt32.def\">\n      <Filter>Source Files\\Misc</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"bn\\ecp_smpl.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_asm.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_exp2.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_exp.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_gcd.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_mul.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\bn_recp.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\ec_lib.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\ec_mult.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bn\\ecp_mont.c\">\n      <Filter>Source Files\\Bignum Library</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\write_pre.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\certrev.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\certschk.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\certsign.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\certval.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\chain.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\chk_cert.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\chk_chn.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\chk_use.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_cert.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_curs.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_del.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_get.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_gets.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_set.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\dn.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\dn_rw.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_add.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_chk.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_copy.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_def.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_rd.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\ext_wr.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\imp_chk.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\imp_exp.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\read.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\trustmgr.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\write.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_3des.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_aes.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_attr.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_des.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_dh.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_dsa.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_ecdh.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_ecdsa.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_elg.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_generic.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_hsha2.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_hsha.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_idea.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_md5.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_misc.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_rc2.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_rc4.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_rsa.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_sha2.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_sha.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\key_id.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\key_wr.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\keyload.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\kg_dlp.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\kg_ecc.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\kg_prime.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\kg_rsa.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aes_modes.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aescrypt.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aeskey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aestab.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\descbc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desecb3.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desecb.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desenc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\desskey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\gcm.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\gf128mul.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\icbc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\iecb.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\iskey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\md5dgst.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\rc2cbc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\rc2ecb.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\rc2skey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\rc4skey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\sha1dgst.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\sha2.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\dev_attr.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\hardware.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\hw_dummy.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\ms_capi.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\pkcs11.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\pkcs11_init.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\pkcs11_pkc.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\pkcs11_rd.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\pkcs11_wr.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"device\\system.c\">\n      <Filter>Source Files\\Devices</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\asn1_algid.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\asn1_chk.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\asn1_ext.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\asn1_rd.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\asn1_wr.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\base64.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\base64_id.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\misc_rw.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"enc_dec\\pgp_rw.c\">\n      <Filter>Source Files\\Encode/Decode</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\cms_denv.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\cms_env.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\cms_envpre.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\decode.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\encode.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\env_attr.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\pgp_denv.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\pgp_env.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\res_actn.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\res_denv.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"envelope\\res_env.c\">\n      <Filter>Source Files\\Envelopes</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\tcp.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\dns.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\dns_srv.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\file.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\http_parse.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\http_rd.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\http_wr.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\memory.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\net.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\net_proxy.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\net_trans.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\net_url.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\stream.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\attr_acl.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\certm_acl.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\init.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\int_msg.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\key_acl.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\mech_acl.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\msg_acl.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\obj_acc.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\objects.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\sec_mem.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\semaphore.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\sendmsg.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs12_wr.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\key_attr.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ldap.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pgp.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pgp_rd.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs12.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs12_rd.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs12_rdo.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\odbc.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ca_add.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ca_clean.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ca_issue.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ca_misc.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\ca_rev.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\dbms.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\dbx_misc.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\dbx_rd.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\dbx_wr.c\">\n      <Filter>Source Files\\Keysets - DBMS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_wr.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_add.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_adpb.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_adpr.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_atrd.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_atwr.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_get.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_getp.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_rd.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pkcs15_set.c\">\n      <Filter>Source Files\\Keysets - PKCS15</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\keyex.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\keyex_int.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\keyex_rw.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_cwrap.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_drv.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_int.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_pkwrap.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_privk.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\mech_sig.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\obj_qry.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign_cms.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign_int.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign_pgp.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign_rw.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"mechs\\sign_x509.c\">\n      <Filter>Source Files\\Mechanisms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_api.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_attr.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_debug.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_env.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_err.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_mem.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_string.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\int_time.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\os_spec.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\pgp_misc.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\user.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\user_attr.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\user_cfg.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"misc\\user_rw.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"bindings\\java_jni.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"random\\win32.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"random\\rand_x917.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"random\\random.c\">\n      <Filter>Source Files\\Misc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\session.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\scorebrd.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\sess_attr.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\sess_iattr.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\tsp.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\certstore.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_cli.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_err.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_rd.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_rdmsg.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_svr.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_wr.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_wrmsg.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ocsp.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\pnppki.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\rtcs.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\scep.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\scep_cli.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\scep_svr.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_authc.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_auths.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_chn.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_cli.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_msg.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_msgc.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_msgs.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_rd.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_svr.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_wr.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_wr.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_cli.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_ext.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_hs.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_hsc.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_kmgmt.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_rd.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_suites.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_svr.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\zutil.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\adler32.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\deflate.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\inffast.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\inflate.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\inftrees.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"zlib\\trees.c\">\n      <Filter>Source Files\\Zlib</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptusr.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptapi.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptcrt.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptctx.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptdev.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptenv.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptkey.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptlib.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cryptses.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_cast.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\castecb.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\castenc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\castskey.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\selftest.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\key_rdpri.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\key_rdpub.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bn.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\comp_pkiu.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\aes_ni.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\pgp_wr.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bnmath.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bnpkc.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bnprime.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bnrw.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bntest.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_bnsieve.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\tcp_conn.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\tcp_err.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"kernel\\storage.c\">\n      <Filter>Source Files\\Kernel</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\dn_rws.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\dn_string.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"cert\\chk_san.c\">\n      <Filter>Source Files\\Certificates</Filter>\n    </ClCompile>\n    <ClCompile Include=\"context\\ctx_encr.c\">\n      <Filter>Source Files\\Contexts</Filter>\n    </ClCompile>\n    <ClCompile Include=\"crypt\\rc4enc.c\">\n      <Filter>Source Files\\Crypt/Hash Algorithms</Filter>\n    </ClCompile>\n    <ClCompile Include=\"keyset\\http_keys.c\">\n      <Filter>Source Files\\Keysets</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\sess_rd.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\sess_wr.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\http.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"io\\tcp_rw.c\">\n      <Filter>Source Files\\I/O</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\sess_ws.c\">\n      <Filter>Source Files\\Sessions</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\cmp_crypt.c\">\n      <Filter>Source Files\\Sessions - PKI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssh2_crypt.c\">\n      <Filter>Source Files\\Sessions - SSH</Filter>\n    </ClCompile>\n    <ClCompile Include=\"session\\ssl_crypt.c\">\n      <Filter>Source Files\\Sessions - SSL</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"cert\\trustmgr.h\">\n      <Filter>Header Files\\Certificates - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cert\\cert.h\">\n      <Filter>Header Files\\Certificates - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cert\\certattr.h\">\n      <Filter>Header Files\\Certificates - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cert\\certfn.h\">\n      <Filter>Header Files\\Certificates - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cert\\dn.h\">\n      <Filter>Header Files\\Certificates - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\capabil.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\device.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\hardware.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\pkcs11.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\pkcs11_api.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\pkcs11f.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"device\\pkcs11t.h\">\n      <Filter>Header Files\\Devices - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"enc_dec\\pgp_rw.h\">\n      <Filter>Header Files\\Encode/Decode - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"enc_dec\\asn1.h\">\n      <Filter>Header Files\\Encode/Decode - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"enc_dec\\asn1_ext.h\">\n      <Filter>Header Files\\Encode/Decode - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"enc_dec\\asn1_oids.h\">\n      <Filter>Header Files\\Encode/Decode - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"enc_dec\\misc_rw.h\">\n      <Filter>Header Files\\Encode/Decode - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\file.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\http.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\stream.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\stream_int.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\tcp.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"kernel\\acl.h\">\n      <Filter>Header Files\\Kernel - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"kernel\\acl_perm.h\">\n      <Filter>Header Files\\Kernel - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"kernel\\kernel.h\">\n      <Filter>Header Files\\Kernel - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"kernel\\thread.h\">\n      <Filter>Header Files\\Kernel - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"keyset\\pkcs15.h\">\n      <Filter>Header Files\\Keysets - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"keyset\\dbms.h\">\n      <Filter>Header Files\\Keysets - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"keyset\\keyset.h\">\n      <Filter>Header Files\\Keysets - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"keyset\\pgp_key.h\">\n      <Filter>Header Files\\Keysets - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"keyset\\pkcs12.h\">\n      <Filter>Header Files\\Keysets - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\certstore.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\cmp.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\scep.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\scorebrd.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\session.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\ssh.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\ssl.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\pgp.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\user.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"context\\context.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cryptlib.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"crypt.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"envelope\\envelope.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"mechs\\mech.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"cryptkrn.h\">\n      <Filter>Header Files\\Kernel - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\analyse.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\config.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\consts.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\debug.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\int_api.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\os_spec.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"misc\\fault.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"random\\random.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"random\\random_int.h\">\n      <Filter>Header Files\\Misc - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"io\\tcp_int.h\">\n      <Filter>Header Files\\I/O - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\eap.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"session\\websockets.h\">\n      <Filter>Header Files\\Sessions - Headers</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "deps/cl345/crypt32ce.vcp",
    "content": "# Microsoft eMbedded Visual Tools Project File - Name=\"crypt32ce\" - Package Owner=<4>\n# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (WCE MIPSIV) Dynamic-Link Library\" 0x9602\n# TARGTYPE \"Win32 (WCE SH3) Dynamic-Link Library\" 0x8102\n# TARGTYPE \"Win32 (WCE x86) Dynamic-Link Library\" 0x8302\n# TARGTYPE \"Win32 (WCE emulator) Dynamic-Link Library\" 0xa602\n# TARGTYPE \"Win32 (WCE ARMV4) Dynamic-Link Library\" 0xa302\n\nCFG=crypt32ce - Win32 (WCE SH3) Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"crypt32ce.vcn\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"crypt32ce.vcn\" CFG=\"crypt32ce - Win32 (WCE SH3) Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"crypt32ce - Win32 (WCE SH3) Release\" (based on \"Win32 (WCE SH3) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE SH3) Debug\" (based on \"Win32 (WCE SH3) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE MIPSIV) Release\" (based on \"Win32 (WCE MIPSIV) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE MIPSIV) Debug\" (based on \"Win32 (WCE MIPSIV) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE emulator) Release\" (based on \"Win32 (WCE emulator) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE emulator) Debug\" (based on \"Win32 (WCE emulator) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE ARMV4) Release\" (based on \"Win32 (WCE ARMV4) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE ARMV4) Debug\" (based on \"Win32 (WCE ARMV4) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE x86) Release\" (based on \"Win32 (WCE x86) Dynamic-Link Library\")\n!MESSAGE \"crypt32ce - Win32 (WCE x86) Debug\" (based on \"Win32 (WCE x86) Dynamic-Link Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n# PROP ATL_Project 2\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"SH3Rel\"\n# PROP BASE Intermediate_Dir \"SH3Rel\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"releasece_sh3\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /D \"CRYPT32CE_EXPORTS\" /YX /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /I \".\\\\\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D \"NDEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"SH3Dbg\"\n# PROP BASE Intermediate_Dir \"SH3Dbg\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"debugce_sh3\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /M$(CECrtMTDebug) /c\n# SUBTRACT CPP /YX\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"MIPSIVRel\"\n# PROP BASE Intermediate_Dir \"MIPSIVRel\"\n# PROP BASE CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"releasece_mips\"\n# PROP CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /D \"CRYPT32CE_EXPORTS\" /YX /QMmips4 /QMn32 /QMFPE /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /I \".\\\\\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D \"NDEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /QMmips4 /QMn32 /QMFPE /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"MIPSIVDbg\"\n# PROP BASE Intermediate_Dir \"MIPSIVDbg\"\n# PROP BASE CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"debugce_mips\"\n# PROP CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /QMmips4 /QMn32 /QMFPE /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /QMmips4 /QMn32 /QMFPE /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"emulatorRel\"\n# PROP BASE Intermediate_Dir \"emulatorRel\"\n# PROP BASE CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"releasece_em\"\n# PROP CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /O2 /c\n# ADD CPP /nologo /W3 /I \".\\\\\" /D \"_i386_\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /O2 /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"emulatorDbg\"\n# PROP BASE Intermediate_Dir \"emulatorDbg\"\n# PROP BASE CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"debugce_em\"\n# PROP CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"_i386_\" /D \"_X86_\" /D \"x86\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"ARMV4Rel\"\n# PROP BASE Intermediate_Dir \"ARMV4Rel\"\n# PROP BASE CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"releasece_arm4\"\n# PROP CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /D \"CRYPT32CE_EXPORTS\" /YX /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /I \".\\\\\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D \"NDEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"ARMV4Dbg\"\n# PROP BASE Intermediate_Dir \"ARMV4Dbg\"\n# PROP BASE CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"debugce_arm4\"\n# PROP CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 coredll.lib /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"$(CENoDefaultLib)\" /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"X86Rel\"\n# PROP BASE Intermediate_Dir \"X86Rel\"\n# PROP BASE CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"releasece_x86\"\n# PROP CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /O2 /c\n# ADD CPP /nologo /W3 /I \".\\\\\" /D \"_i386_\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /O2 /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"X86Dbg\"\n# PROP BASE Intermediate_Dir \"X86Dbg\"\n# PROP BASE CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"debugce_x86\"\n# PROP CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"_i386_\" /D \"_X86_\" /D \"x86\" /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"CRYPT32CE_EXPORTS\" /YX /Gs8192 /GF /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00100000\" /stack:0x10000,0x1000 /entry:\"_DllMainCRTStartup\" /dll /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /out:\"binariesce/cl32ce.dll\" /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ENDIF \n\n# Begin Target\n\n# Name \"crypt32ce - Win32 (WCE SH3) Release\"\n# Name \"crypt32ce - Win32 (WCE SH3) Debug\"\n# Name \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n# Name \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n# Name \"crypt32ce - Win32 (WCE emulator) Release\"\n# Name \"crypt32ce - Win32 (WCE emulator) Debug\"\n# Name \"crypt32ce - Win32 (WCE ARMV4) Release\"\n# Name \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n# Name \"crypt32ce - Win32 (WCE x86) Release\"\n# Name \"crypt32ce - Win32 (WCE x86) Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Group \"Bignum library\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\bn\\bn_add.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_AD=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_asm.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_AS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_AS=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_ctx.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_CT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_CT=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_div.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_DI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_DI=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_exp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_EX=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_EX=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_exp2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_EXP=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_EXP=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_gcd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_GC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_GC=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_lib.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_LI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_LI=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_mod.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_MO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MO=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_mont.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_MON=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MON=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_mul.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_MU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_MU=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_recp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_RE=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_RE=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_shift.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_SH=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_sqr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_SQ=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_SQ=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bn\\bn_word.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\bn\\bn\\bn.h\"\\\n\t\".\\bn\\bn\\bn_lcl.h\"\\\n\t\".\\bn\\bnlcl.h\"\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BN_WO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_lcl.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BN_WO=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Certificates\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\cert\\certrev.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CERTR=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certschk.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CERTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certsign.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTSI=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CERTSI=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certval.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTV=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CERTV=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chain.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\cert\\misc\\misc_rw.h\"\\\n\t\".\\cert\\misc_rw.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CHAIN=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CHAIN=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\misc_rw.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_cert.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CHK_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CHK_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_chn.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CHK_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CHK_CH=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\chk_use.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CHK_U=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CHK_U=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_cert.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_curs.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_del.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_get.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_G=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_gets.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_GE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_pkiu.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\cert\\dn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\comp_set.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_COMP_S=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_COMP_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DN_C3a=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\cert\\dn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DN_C3a=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DN_RW=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\cert\\dn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DN_RW=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dnstring.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DNSTR=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DNSTR=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\misc_rw.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_add.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_A=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_chk.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_CH=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_CH=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_copy.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_CO=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_CO=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_def.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_D=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_R=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\ext_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\cert\\certattr.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_EXT_W=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certattr.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_EXT_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\imp_chk.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_IMP_C=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_IMP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\imp_exp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_IMP_E=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_IMP_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\read.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_READ_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_READ_=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\trustmgr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TRUST=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_TRUST=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\write.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_WRITE=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_WRITE=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\write_pre.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\io\\stream.h\"\\\n\t\".\\cert\\misc\\asn1.h\"\\\n\t\".\\cert\\misc\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\cert\\cert\\cert.h\"\\\n\t\".\\cert\\misc\\asn1_rw.h\"\\\n\t\".\\cert\\misc\\asn1s_rw.h\"\\\n\t\".\\cert\\misc\\stream.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_WRITE_=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_WRITE_=\\\n\t\".\\analyse.h\"\\\n\t\".\\cert\\asn1.h\"\\\n\t\".\\cert\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Contexts\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\context\\ctx_3des.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\des.h\"\\\n\t\".\\context\\crypt\\testdes.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_3=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_3=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_aes.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\crypt\\gcm.h\"\\\n\t\".\\crypt\\gf128mul.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\aesopt.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\gcm.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\aes.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\aes.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_AT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_bf.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\blowfish.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_B=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_B=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\blowfish.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_cast.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\cast.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_des.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_D=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\des.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\testdes.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_dh.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_DH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_DH=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_dsa.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_DS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_DS=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_ecdh.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_E=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_ecdsa.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_EC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_EC=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_elg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_EL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_EL=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_generic.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_G=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hmd5.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_H=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_H=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hrmd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_HR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_HR=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hsha.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_HS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_HS=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_hsha2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_HSH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_HSH=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\sha2.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_idea.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\idea.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_I=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\idea.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_md5.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\md5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_M=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_misc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_MI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_MI=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\md5.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\context\\sha2.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rc2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\rc2.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rc4.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc4.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_RC=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_RC=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\rc4.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rc5.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\rc5.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_RC5=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_RC5=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\rc5.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_ripe.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\ripemd.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_RI=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_RI=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\ripemd.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_rsa.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_RS=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_sha.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_S=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\ctx_sha2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\libs.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\crypt\\sha2.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\context\\sha.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CTX_SH=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CTX_SH=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\sha2.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_id.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEY_I=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEY_I=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEY_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEY_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\key_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\envelope\\pgp.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\context\\misc\\asn1.h\"\\\n\t\".\\context\\misc\\asn1_ext.h\"\\\n\t\".\\context\\misc\\misc_rw.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEY_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEY_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\asn1.h\"\\\n\t\".\\context\\asn1_ext.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\context\\misc_rw.h\"\\\n\t\".\\context\\pgp.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\keyload.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYLO=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEYLO=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_dlp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KG_DL=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KG_DL=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_prime.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\bn\\bn_prime.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KG_PR=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\bn_prime.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KG_PR=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn_prime.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\kg_rsa.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\context\\context.h\"\\\n\t\".\\context\\context\\keygen.h\"\\\n\t\".\\context\\crypt.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KG_RS=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\context\\keygen.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KG_RS=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Crypt/Hash algorithms\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\crypt\\aes_modes.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\via_ace.h\"\\\n\t\".\\crypt\\via_ace.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_AES_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aes_via_ace.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AES_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aescrypt.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aes_edef.h\"\\\n\t\".\\crypt\\crypt\\aes_tdef.h\"\\\n\t\".\\crypt\\crypt\\aescpp.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\crypt\\aestab.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_AESCR=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESCR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aeskey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_AESKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aes_via_ace.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESKE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\aestab.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\aes.h\"\\\n\t\".\\crypt\\crypt\\aesopt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_AESTA=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\aes.h\"\\\n\t\".\\crypt\\aesopt.h\"\\\n\t\".\\crypt\\aestab.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_AESTA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\bfecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BFECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFECB=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\bfenc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BFENC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFENC=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\bfskey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BFSKE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\bflocl.h\"\\\n\t\".\\crypt\\bfpi.h\"\\\n\t\".\\crypt\\blowfish.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BFSKE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CASTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castenc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CASTEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\castskey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CASTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\cast.h\"\\\n\t\".\\crypt\\castlcl.h\"\\\n\t\".\\crypt\\castsbox.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CASTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\descbc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DESCB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESCB=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\spr.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DESEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\spr.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESEC=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desecb3.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DESECB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESECB=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desenc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DESEN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESEN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\desskey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\des.h\"\\\n\t\".\\crypt\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DESSK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\deslocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DESSK=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\icbc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ICBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ICBC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\iecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_IECB_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_IECB_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\iskey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\idea.h\"\\\n\t\".\\crypt\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ISKEY=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\idea.h\"\\\n\t\".\\crypt\\idealocl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ISKEY=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\md5dgst.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\md5.h\"\\\n\t\".\\crypt\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MD5DG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\md5locl.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MD5DG=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2cbc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC2CB=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2CB=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2ecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC2EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2EC=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc2skey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc2.h\"\\\n\t\".\\crypt\\crypt\\rc2locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC2SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc2.h\"\\\n\t\".\\crypt\\rc2locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC2SK=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc4enc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC4EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC4EN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc4skey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc4.h\"\\\n\t\".\\crypt\\crypt\\rc4locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC4SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc4.h\"\\\n\t\".\\crypt\\rc4locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC4SK=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc5ecb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC5EC=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5EC=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc5enc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC5EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5EN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rc5skey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\rc5.h\"\\\n\t\".\\crypt\\crypt\\rc5locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RC5SK=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\rc5.h\"\\\n\t\".\\crypt\\rc5locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RC5SK=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\rmddgst.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RMDDG=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\rmdconst.h\"\\\n\t\".\\crypt\\rmdlocl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RMDDG=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\sha1dgst.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\md32com.h\"\\\n\t\".\\crypt\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\crypt\\sha.h\"\\\n\t\".\\crypt\\crypt\\sha1locl.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SHA1D=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md32com.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha1locl.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SHA1D=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt\\sha2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\crypt\\crypt\\sha2.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SHA2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\brg_endian.h\"\\\n\t\".\\crypt\\brg_types.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SHA2_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Devices\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\device\\dev_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\asn1_ext.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1.h\"\\\n\t\".\\device\\misc\\asn1_ext.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DEV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DEV_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hardware.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\asn1_ext.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1.h\"\\\n\t\".\\device\\misc\\asn1_ext.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HARDW=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\hardware.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_HARDW=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\dev_mech.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hw_dummy.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\asn1_ext.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1.h\"\\\n\t\".\\device\\misc\\asn1_ext.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\asn1s_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\device\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HW_DU=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\hardware.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_HW_DU=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\ms_capi.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\asn1_ext.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1.h\"\\\n\t\".\\device\\misc\\asn1_ext.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MS_CA=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MS_CA=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\asn1_ext.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\dev_mech.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\asn1_rw.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\context\\context.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\device\\pkcs11.h\"\\\n\t\".\\device\\device\\pkcs11f.h\"\\\n\t\".\\device\\device\\pkcs11t.h\"\\\n\t\".\\device\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS1=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS1=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\device\\dev_mech.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_init.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS11=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS11=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_pkc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS11_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS11_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS11_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS11_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS11_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\device\\pkcs11.h\"\\\n\t\".\\device\\pkcs11_api.h\"\\\n\t\".\\device\\pkcs11f.h\"\\\n\t\".\\device\\pkcs11t.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS11_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\asn1.h\"\\\n\t\".\\device\\context.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\system.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\libs.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\device\\context\\libs.h\"\\\n\t\".\\device\\crypt.h\"\\\n\t\".\\device\\device\\capabil.h\"\\\n\t\".\\device\\device\\device.h\"\\\n\t\".\\device\\libs.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SYSTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\random\\random.h\"\\\n\t\nNODEP_CPP_SYSTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device\\dev_mech.h\"\\\n\t\".\\device\\random.h\"\\\n\t\".\\device\\vendalgo.c\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Encode/Decode\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_algid.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ASN1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\asn1_oids.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ASN1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_chk.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ASN1_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ASN1_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_ext.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ASN1_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ASN1_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ASN1_R=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ASN1_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ASN1_W=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ASN1_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\base64.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BASE6=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_BASE6=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\base64_id.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_BASE64=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_BASE64=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\misc_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MISC_=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MISC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\bn.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\pgp_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Envelopes\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_denv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMS_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMS_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_env.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMS_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMS_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\cms_envpre.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\asn1s_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\asn1s_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMS_EN=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMS_EN=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\decode.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DECOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DECOD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp_rw.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\encode.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ENCOD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ENCOD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\env_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1_rw.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\misc\\asn1_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ENV_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ENV_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\pgp_denv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\objinfo.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\objinfo.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\envelope\\pgp_rw.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\pgp_env.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\misc_rw.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\misc_rw.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\envelope\\pgp_rw.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_actn.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RES_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_RES_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_denv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RES_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_RES_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\res_env.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope\\envelope.h\"\\\n\t\".\\envelope\\envelope\\pgp.h\"\\\n\t\".\\envelope\\misc\\asn1.h\"\\\n\t\".\\envelope\\misc\\asn1_ext.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\envelope\\zlib\\zlib.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RES_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_RES_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope\\asn1.h\"\\\n\t\".\\envelope\\asn1_ext.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"IO\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\io\\dns.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DNS_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DNS_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\"r:\\temp\\trsocket.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\dns_srv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DNS_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_DNS_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\"r:\\temp\\trsocket.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\file.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\file.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_FILE_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\file.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_FILE_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_parse.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HTTP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\misc\\misc_rw.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HTTP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\http.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HTTP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\http.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\memory.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MEMOR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MEMOR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_NET_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_proxy.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_NET_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_P=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_trans.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_NET_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_T=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\net_url.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_NET_U=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_NET_U=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_STREA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_STREA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\io\\io\\stream.h\"\\\n\t\".\\io\\io\\tcp.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TCP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\io\\stream_int.h\"\\\n\t\".\\io\\tcp.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_TCP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\"r:\\temp\\trsocket.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Kernel\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\kernel\\attr_acl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ATTR_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_ATTR_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\certm_acl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTM=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\init.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\crypt\\des.h\"\\\n\t\".\\kernel\\crypt\\testdes.h\"\\\n\t\".\\kernel\\des.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\kernel\\testdes.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INIT_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INIT_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\capabil.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\int_msg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\key_acl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEY_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\mech_acl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\msg_acl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MSG_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MSG_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\obj_acc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\io\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\bn\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\device\\capabil.h\"\\\n\t\".\\context\\misc\\stream.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\context\\context.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_OBJ_A=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_OBJ_A=\\\n\t\"..\\..\\Intel\\VTune\\tcheck\\Include\\libittnotify.h\"\\\n\t\".\\analyse.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\context.h\"\\\n\t\".\\kernel\\mech_int.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\objects.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_OBJEC=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OBJEC=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\sec_mem.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\selftest.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SEC_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEC_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\semaphore.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SEMAP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SEMAP=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\sendmsg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\itron_itron.h\"\\\n\t\".\\docs\\itron_kernel.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\cryptini.h\"\\\n\t\".\\docs\\ecos_basetype.h\"\\\n\t\".\\docs\\ecos_cyg_type.h\"\\\n\t\".\\docs\\ecos_kapi.h\"\\\n\t\".\\docs\\ecos_kapidata.h\"\\\n\t\".\\docs\\itron_tool_defs.h\"\\\n\t\".\\docs\\kernel\\itron.h\"\\\n\t\".\\kernel\\crypt.h\"\\\n\t\".\\kernel\\kernel\\acl.h\"\\\n\t\".\\kernel\\kernel\\kernel.h\"\\\n\t\".\\kernel\\kernel\\thread.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SENDM=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\kernel\\acl.h\"\\\n\t\".\\kernel\\acl_perm.h\"\\\n\t\".\\kernel\\kernel.h\"\\\n\t\".\\kernel\\thread.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SENDM=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Keysets\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\http.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HTTP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_HTTP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\key_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEY_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEY_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ldap.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\lber.h\"\\\n\t\".\\keyset\\keyset\\ldap.h\"\\\n\t\".\\keyset\\lber.h\"\\\n\t\".\\keyset\\ldap.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\macsock.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\os2sock.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_LDAP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_LDAP_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\odbc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keysets\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ODBC_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\dbx_rpc.c\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_ODBC_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\envelope\\pgp.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\misc_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pgp_key.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\misc_rw.h\"\\\n\t\".\\keyset\\pgp.h\"\\\n\t\".\\keyset\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS12=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs12.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS12=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS12_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs12.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS12_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_rdo.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS12_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs12.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS12_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS12_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs12.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS12_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Keysets - DBMS\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_add.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CA_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CA_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_issue.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CA_IS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CA_IS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_misc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CA_MI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CA_MI=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\ca_rev.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CA_RE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CA_RE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbms.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DBMS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DBMS_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_misc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DBX_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DBX_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DBX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DBX_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\dbx_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\rpc.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DBX_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\dbms.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_DBX_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Keysets - PKCS15\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_add.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_adpb.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_adpr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_AD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_AD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_atrd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_AT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_atwr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_ATW=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_ATW=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_get.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_G=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_G=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_getp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_GE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_GE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\objinfo.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\objinfo.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_set.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\io\\stream.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\misc\\asn1.h\"\\\n\t\".\\keyset\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\keyset\\asn1_rw.h\"\\\n\t\".\\keyset\\asn1s_rw.h\"\\\n\t\".\\keyset\\crypt.h\"\\\n\t\".\\keyset\\keyset\\keyset.h\"\\\n\t\".\\keyset\\keyset\\pkcs15.h\"\\\n\t\".\\keyset\\libpq-fe.h\"\\\n\t\".\\keyset\\misc\\asn1_rw.h\"\\\n\t\".\\keyset\\misc\\asn1s_rw.h\"\\\n\t\".\\keyset\\misc\\stream.h\"\\\n\t\".\\keyset\\ociapr.h\"\\\n\t\".\\keyset\\ocidfn.h\"\\\n\t\".\\keyset\\oratypes.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PKCS15_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\keyset\\pkcs15.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PKCS15_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset\\asn1.h\"\\\n\t\".\\keyset\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Mechanisms\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYEX=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEYEX=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex_int.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYEX_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEYEX_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\keyex_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYEX_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_KEYEX_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_cwrap.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_drv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MECH_D=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_int.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_I=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_pkwrap.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MECH_P=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_privk.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_PR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MECH_PR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\mech_sig.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_MECH_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\dev_mech.h\"\\\n\t\".\\mechs\\mech_int.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_MECH_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\obj_qry.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_OBJ_Q=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_OBJ_Q=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\crypt.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_cms.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_int.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_I=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_pgp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_P=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_P=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\io\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\misc\\stream.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\envelope\\pgp.h\"\\\n\t\".\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\mechs\\mechanism.h\"\\\n\t\".\\mechs\\misc\\asn1.h\"\\\n\t\".\\mechs\\misc\\asn1_ext.h\"\\\n\t\".\\mechs\\misc\\misc_rw.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\mechs\\pgp_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\mechs\\sign_x509.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SIGN_X=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\mechs\\mech.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SIGN_X=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\mechs\\asn1.h\"\\\n\t\".\\mechs\\asn1_ext.h\"\\\n\t\".\\mechs\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Misc\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\misc\\int_api.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\md5.h\"\\\n\t\".\\crypt\\ripemd.h\"\\\n\t\".\\crypt\\sha.h\"\\\n\t\".\\crypt\\sha2.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\crypt\\md5.h\"\\\n\t\".\\misc\\crypt\\ripemd.h\"\\\n\t\".\\misc\\crypt\\sha.h\"\\\n\t\".\\misc\\crypt\\sha2.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\md5.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\ripemd.h\"\\\n\t\".\\misc\\sha.h\"\\\n\t\".\\misc\\sha2.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_INT_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_AT=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_AT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_debug.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_D=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_D=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_env.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_INT_E=\\\n\t\".\\misc\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_err.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ER=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_ER=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_mem.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_ME=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_ME=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_string.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_S=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_time.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_INT_T=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INT_T=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\bindings\\java_jni.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\cryptini.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_JAVA_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_JAVA_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\os_spec.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_OS_SP=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_OS_SP=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\pgp_misc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PGP_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PGP_M=\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\rand_x917.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\misc\\stream.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RAND_=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\random\\random.h\"\\\n\t\".\\random\\random_int.h\"\\\n\t\nNODEP_CPP_RAND_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\random\\capabil.h\"\\\n\t\".\\random\\des.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\random.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\misc\\stream.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\".\\random\\crypt\\des.h\"\\\n\t\".\\random\\crypt\\testdes.h\"\\\n\t\".\\random\\des.h\"\\\n\t\".\\random\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RANDO=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\random\\random.h\"\\\n\t\".\\random\\random_int.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_RANDO=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\random\\des.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_USER_=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_USER_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_USER_=\\\n\t\".\\misc\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_USER_A=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_USER_A=\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_cfg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_USER_C=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_C=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_USER_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\".\\misc\\user_int.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\user_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_USER_R=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\".\\misc\\user_int.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_USER_R=\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\trustmgr.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\random\\wince.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\random\\crypt.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\random\\random.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Sessions\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\certstore.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTST=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CERTST=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_cli.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_CL=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_cry.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_CR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_err.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_rdmsg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_RD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_RD=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_svr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp_wrmsg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CMP_WR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CMP_WR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ocsp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_OCSP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_OCSP_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\pnppki.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\cmp.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_PNPPK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\cmp.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_PNPPK=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\rtcs.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_RTCS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_RTCS_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SCEP_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SCEP_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep_cli.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SCEP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SCEP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep_svr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SCEP_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\certstore.h\"\\\n\t\".\\session\\scep.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SCEP_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scorebrd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SCORE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SCORE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_attr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SESS_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SESS_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_iattr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SESS_I=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SESS_I=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\sess_rw.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SESS_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SESS_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\session.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SESSI=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SESSI=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\tsp.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1.h\"\\\n\t\".\\session\\misc\\asn1_ext.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\objinfo.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\asn1_rw.h\"\\\n\t\".\\session\\asn1s_rw.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\asn1_rw.h\"\\\n\t\".\\session\\misc\\asn1s_rw.h\"\\\n\t\".\\session\\misc\\objinfo.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\objinfo.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TSP_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_TSP_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\asn1.h\"\\\n\t\".\\session\\asn1_ext.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"SSH\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\ssh.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh1.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH1_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH1_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_authc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_A=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_A=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_auths.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_AU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_AU=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_chn.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_cli.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_CL=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_cry.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\".\\session\\ssh_dhkeys.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_CR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\ssh_keys.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msg.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_M=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_M=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msgc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_MS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_MS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_msgs.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_MSG=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_MSG=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_svr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh2_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssh.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH2_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssh.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSH2_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"SSL/TLS\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\ssl.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_C=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_cli.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_CL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_CL=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_cry.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_CR=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_CR=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_ext.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_E=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_E=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_hs.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_H=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_H=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_hsc.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_HS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_HS=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_kmgmt.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_K=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_K=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_rd.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_R=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_R=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_suites.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_S=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_S=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_svr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\stream.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_SV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_SV=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl_wr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\io\\crypt.h\"\\\n\t\".\\misc\\io\\stream.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\session\\crypt.h\"\\\n\t\".\\session\\misc\\misc_rw.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\".\\session\\session\\session.h\"\\\n\t\".\\session\\session\\ssl.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_W=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t\".\\session\\ssl.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_SSL_W=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\session\\misc_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Zlib\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\zlib\\adler32.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_ADLER=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ADLER=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\deflate.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\misc\\config.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\zlib\\crypt.h\"\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DEFLA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_DEFLA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inffast.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inflate.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inflate.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INFFA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infcodes.h\"\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\infutil.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INFFA=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inflate.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFFA=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inflate.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inflate.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\zlib\\inffast.h\"\\\n\t\".\\zlib\\zlib\\inflate.h\"\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\".\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\infblock.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\".\\zlib\\inffast.h\"\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inflate.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\inftrees.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inffixed.h\"\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_INFTR=\\\n\t\".\\zlib\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_INFTR=\\\n\t\".\\zlib\\inftrees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\trees.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_TREES=\\\n\t\".\\zlib\\zlib\\deflate.h\"\\\n\t\".\\zlib\\zlib\\trees.h\"\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TREES=\\\n\t\".\\zlib\\deflate.h\"\\\n\t\".\\zlib\\trees.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\zlib\\zutil.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\nNODEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zlib\\zutil.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ZUTIL=\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\".\\zlib\\zutil.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Source File\n\nSOURCE=.\\cryptapi.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\docs\\cryptapi_ext.c\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\rpc.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptcrt.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTC=\\\n\t\".\\cert\\cert.h\"\\\n\t\".\\cert\\certfn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPTC=\\\n\t\".\\analyse.h\"\\\n\t\".\\asn1.h\"\\\n\t\".\\cert.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptctx.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\context.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\capabil.h\"\\\n\t\".\\misc\\context.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTCT=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\bn\\ec.h\"\\\n\t\".\\bn\\ec_lcl.h\"\\\n\t\".\\context\\context.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPTCT=\\\n\t\".\\analyse.h\"\\\n\t\".\\asn1.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\context.h\"\\\n\t\".\\context\\bn.h\"\\\n\t\".\\context\\capabil.h\"\\\n\t\".\\context\\ec_lcl.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptdev.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\device.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\device.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\device.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTD=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\device\\capabil.h\"\\\n\t\".\\device\\device.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTD=\\\n\t\".\\analyse.h\"\\\n\t\".\\capabil.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\device.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptenv.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTE=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\envelope\\envelope.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\zlib\\zconf.h\"\\\n\t\".\\zlib\\zlib.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPTE=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\envelope.h\"\\\n\t\".\\envelope\\zlib.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptkey.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\envelope\\pgp.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc_rw.h\"\\\n\t\".\\pgp.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTK=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\enc_dec\\asn1_ext.h\"\\\n\t\".\\enc_dec\\misc_rw.h\"\\\n\t\".\\enc_dec\\pgp_rw.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\keyset\\keyset.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPTK=\\\n\t\".\\analyse.h\"\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\enc_dec\\pgp.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\keyset.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\pgp_rw.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptlib.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\des.h\"\\\n\t\".\\crypt\\testdes.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\des.h\"\\\n\t\".\\testdes.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTL=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptses.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\session\\session.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTS=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\enc_dec\\asn1.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\session\\scorebrd.h\"\\\n\t\".\\session\\session.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\t\nNODEP_CPP_CRYPTS=\\\n\t\".\\analyse.h\"\\\n\t\".\\asn1.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\scorebrd.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptusr.c\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1.h\"\\\n\t\".\\asn1_ext.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\asn1.h\"\\\n\t\".\\misc\\asn1_ext.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\tream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\asn1_rw.h\"\\\n\t\".\\asn1s_rw.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\cryptos.h\"\\\n\t\".\\misc\\asn1_rw.h\"\\\n\t\".\\misc\\asn1s_rw.h\"\\\n\t\".\\misc\\ber.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CRYPTU=\\\n\t\".\\cert\\trustmgr.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\analyse.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\debug.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\user.h\"\\\n\t\nNODEP_CPP_CRYPTU=\\\n\t\".\\analyse.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\debug.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\trustmgr.h\"\\\n\t\".\\user.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Group \"Certificates - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\cert\\cert.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certattr.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\certfn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\dn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cert\\trustmgr.h\n# End Source File\n# End Group\n# Begin Group \"Devices - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\device\\capabil.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\device.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\hardware.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11_api.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11f.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\device\\pkcs11t.h\n# End Source File\n# End Group\n# Begin Group \"Encode/Decode - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\misc\\asn1.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\asn1_ext.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\asn1_oids.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec/misc_rw.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\enc_dec\\pgp_rw.h\n# End Source File\n# End Group\n# Begin Group \"I/O - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\io\\file.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\http.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\stream_int.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\io\\tcp.h\n# End Source File\n# End Group\n# Begin Group \"Kernel - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\kernel\\acl.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\acl_perm.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptkrn.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\kernel.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\kernel\\thread.h\n# End Source File\n# End Group\n# Begin Group \"Keysets - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\keyset\\dbms.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\keyset.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pgp_key.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs12.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\keyset\\pkcs15.h\n# End Source File\n# End Group\n# Begin Group \"Sessions - Headers\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=.\\session\\certstore.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\cmp.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\scep.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\session.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssh_dhkeys.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\session\\ssl.h\n# End Source File\n# End Group\n# Begin Source File\n\nSOURCE=.\\misc\\config.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\context\\context.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\cryptlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\envelope.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\int_api.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\misc\\os_spec.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\envelope\\pgp.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n# Begin Source File\n\nSOURCE=.\\crypt32.rc\n\n!IF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE SH3) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE MIPSIV) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE emulator) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE ARMV4) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"crypt32ce - Win32 (WCE x86) Debug\"\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/cl345/crypt32ce.vcw",
    "content": "Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"crypt32ce\"=.\\crypt32ce.vcp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/cl345/cryptapi.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib External API Interface\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* NSA motto: In God we trust... all others we monitor.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t-- Stanley Miller */\n#include \"crypt.h\"\n#if defined( INC_ALL )\n  #include \"rpc.h\"\n#else\n  #include \"misc/rpc.h\"\n#endif /* Compiler-specific includes */\n\n/* Handlers for the various commands */\n\n#ifdef USE_CERTIFICATES\n\nstatic int cmdCertCheck( COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == COMMAND_CERTCHECK );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( !isHandleRangeValid( cmd->arg[ 1 ] ) && \\\n\t\t( cmd->arg[ 1 ] != CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_SIGCHECK, NULL,\n\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t}\n\n#ifdef USE_KEYSETS\n\nstatic int cmdCertMgmt( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_CERTMGMT_INFO certMgmtInfo;\n\tint status;\n\n\tassert( cmd->type == COMMAND_CERTMGMT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE || \\\n\t\t\tcmd->flags == COMMAND_FLAG_RET_NONE );\n\tassert( cmd->noArgs == 4 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] < CRYPT_CERTACTION_FIRST_USER || \\\n\t\tcmd->arg[ 1 ] > CRYPT_CERTACTION_LAST_USER )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\tif( !isHandleRangeValid( cmd->arg[ 2 ] ) && \\\n\t\t!( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\t\t cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \\\n\t\t   cmd->arg[ 2 ] == CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( !isHandleRangeValid( cmd->arg[ 3 ] ) && \\\n\t\t!( ( cmd->arg[ 1 ] == CRYPT_CERTACTION_ISSUE_CRL || \\\n\t\t\t cmd->arg[ 1 ] == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\t\t cmd->arg[ 1 ] == CRYPT_CERTACTION_CLEANUP ) && \\\n\t\t   cmd->arg[ 3 ] == CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\n\tsetMessageCertMgmtInfo( &certMgmtInfo, cmd->arg[ 2 ], cmd->arg[ 3 ] );\n\tif( cmd->flags == COMMAND_FLAG_RET_NONE )\n\t\t{\n\t\t/* If we aren't interested in the return value, set the crypt handle \n\t\t   to CRYPT_UNUSED to indicate that there's no need to return the \n\t\t   created certificate object */\n\t\tcertMgmtInfo.cryptCert = CRYPT_UNUSED;\n\t\t}\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_CERTMGMT,\n\t\t\t\t\t\t\t  &certMgmtInfo, cmd->arg[ 1 ] );\n\tif( cryptStatusOK( status ) && cmd->flags != COMMAND_FLAG_RET_NONE )\n\t\tcmd->arg[ 0 ] = certMgmtInfo.cryptCert;\n\treturn( status );\n\t}\n#endif /* USE_KEYSETS */\n\nstatic int cmdCertSign( COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == COMMAND_CERTSIGN );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( !isHandleRangeValid( cmd->arg[ 1 ] ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_SIGN, NULL,\n\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t}\n#endif /* USE_CERTIFICATES */\n\nstatic int cmdCreateObject( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBOOLEAN bindToOwner = FALSE, hasStrArg = FALSE;\n\tint owner DUMMY_INIT, status;\n\n\tassert( cmd->type == COMMAND_CREATEOBJECT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs >= 2 && cmd->noArgs <= 4 );\n\tassert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 2 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) && \\\n\t\tcmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] <= OBJECT_TYPE_NONE || \\\n\t\tcmd->arg[ 1 ] >= OBJECT_TYPE_LAST )\n\t\treturn( CRYPT_ERROR_FAILED );\t/* Internal error */\n\tswitch( cmd->arg[ 1 ] )\n\t\t{\n\t\tcase OBJECT_TYPE_CONTEXT:\n\t\t\tassert( cmd->noArgs == 3 );\n\t\t\tassert( cmd->noStrArgs == 0 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_ALGO_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_CERTIFICATE:\n\t\t\tassert( cmd->noArgs == 3 );\n\t\t\tassert( cmd->noStrArgs == 0 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_CERTTYPE_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_CERTTYPE_LAST_EXTERNAL )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_DEVICE:\n\t\t\tassert( cmd->noArgs == 3 );\n\t\t\tassert( cmd->noStrArgs == 1 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_DEVICE_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_DEVICE_LAST )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( cmd->arg[ 2 ] == CRYPT_DEVICE_PKCS11 || \\\n\t\t\t\tcmd->arg[ 2 ] == CRYPT_DEVICE_CRYPTOAPI )\n\t\t\t\t{\n\t\t\t\tif( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\t\t\t\tcmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\thasStrArg = TRUE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_KEYSET:\n\t\t\tassert( cmd->noArgs == 4 );\n\t\t\tassert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_KEYSET_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_KEYSET_LAST )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\t\t\tcmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( cmd->arg[ 3 ] < CRYPT_KEYOPT_NONE || \\\n\t\t\t\tcmd->arg[ 3 ] >= CRYPT_KEYOPT_LAST_EXTERNAL )\n\t\t\t\t{\n\t\t\t\t/* CRYPT_KEYOPT_NONE is a valid setting for this parameter */\n\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t\t}\n\t\t\thasStrArg = TRUE;\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_ENVELOPE:\n\t\t\tassert( cmd->noArgs == 3 );\n\t\t\tassert( cmd->noStrArgs == 0 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_FORMAT_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_FORMAT_LAST_EXTERNAL )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_SESSION:\n\t\t\tassert( cmd->noArgs == 3 );\n\t\t\tassert( cmd->noStrArgs == 0 );\n\t\t\tif( cmd->arg[ 2 ] <= CRYPT_SESSION_NONE || \\\n\t\t\t\tcmd->arg[ 2 ] >= CRYPT_SESSION_LAST )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_USER:\n\t\t\tassert( cmd->noArgs == 2 );\n\t\t\tassert( cmd->noStrArgs == 2 );\n\t\t\tif( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\t\t\tcmd->strArgLen[ 0 ] >= CRYPT_MAX_TEXTSIZE )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( cmd->strArgLen[ 1 ] < MIN_NAME_LENGTH || \\\n\t\t\t\tcmd->strArgLen[ 1 ] >= CRYPT_MAX_TEXTSIZE )\n\t\t\t\treturn( CRYPT_ARGERROR_STR2 );\n\t\t\thasStrArg = TRUE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* If we're creating the object via a device, we should set the new \n\t   object owner to the device owner */\n\tif( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tbindToOwner = TRUE;\n\t\towner = cmd->arg[ 0 ];\n\t\t}\n\n\t/* Create the object via the device.  Since we're usually doing this via \n\t   the system object which is invisible to the user, we have to use an \n\t   internal message for this one case */\n\tsetMessageCreateObjectInfo( &createInfo, cmd->arg[ 2 ] );\n\tif( cmd->noArgs == 4 )\n\t\tcreateInfo.arg2 = cmd->arg[ 3 ];\n\tif( hasStrArg )\n\t\t{\n\t\tcreateInfo.strArg1 = cmd->strArg[ 0 ];\n\t\tcreateInfo.strArgLen1 = cmd->strArgLen[ 0 ];\n\t\tif( cmd->noStrArgs > 1 )\n\t\t\t{\n\t\t\tcreateInfo.strArg2 = cmd->strArg[ 1 ];\n\t\t\tcreateInfo.strArgLen2 = cmd->strArgLen[ 1 ];\n\t\t\t}\n\t\t}\n\tif( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  cmd->arg[ 1 ] );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, cmd->arg[ 1 ] );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the device used to create the object is bound to a thread, bind \n\t   the created object to the thread as well.  If this fails, we don't \n\t   return the object to the caller since it would be returned in a \n\t   potentially unbound state */\n\tif( bindToOwner )\n\t\t{\n\t\tint ownerID;\n\n\t\tstatus = krnlSendMessage( owner, IMESSAGE_GETATTRIBUTE, &ownerID,\n\t\t\t\t\t\t\t\t  CRYPT_PROPERTY_OWNER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &ownerID,\n\t\t\t\t\t\t\t\t\t  CRYPT_PROPERTY_OWNER );\n\t\t\t}\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make the newly-created object externally visible if necessary.  This\n\t   is only required when we're creating the object via the system\n\t   handle, which requires an internal message that leaves the object\n\t   internal */\n\tif( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );\n\t\t}\n\tcmd->arg[ 0 ] = createInfo.cryptHandle;\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CERTIFICATES \n\nstatic int cmdCreateObjectIndirect( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( cmd->type == COMMAND_CREATEOBJECT_INDIRECT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tif( cmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )\n\t\treturn( CRYPT_ERROR_FAILED );\t/* Internal error */\n\tif( cmd->arg[ 1 ] != OBJECT_TYPE_CERTIFICATE )\n\t\treturn( CRYPT_ERROR_FAILED );\t/* Internal error */\n\tif( cmd->strArgLen[ 0 ] < MIN_CERTSIZE || \\\n\t\tcmd->strArgLen[ 0 ] >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Create the object via the device.  Since we're usually doing this via \n\t   the system object which is invisible to the user, we have to use an \n\t   internal message for this one case */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, cmd->strArg[ 0 ],\n\t\t\t\t\t\t\t\t\t\tcmd->strArgLen[ 0 ],\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_NONE );\n\tif( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ],\n\t\t\t\t\t\t\t\t  MESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make the newly-created object externally visible */\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );\n\tcmd->arg[ 0 ] = createInfo.cryptHandle;\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n\nstatic int cmdDecrypt( COMMAND_INFO *cmd )\n\t{\n\tint algorithm, mode = CRYPT_MODE_NONE, status;\t/* int vs.enum */\n\n\tassert( cmd->type == COMMAND_DECRYPT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( algorithm <= CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tif( algorithm <= CRYPT_ALGO_LAST_PKC )\n\t\t\t{\n\t\t\tint blockSize;\n\n\t\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_KEYSIZE );\n\t\t\tif( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )\n\t\t\t\tstatus = CRYPT_ARGERROR_NUM1;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We shouldn't be invoking decrypt on a hash or MAC object */\n\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\t}\n\t\t}\n\tif( cmd->strArgLen[ 0 ] <= 0 )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( mode == CRYPT_MODE_ECB || mode == CRYPT_MODE_CBC )\n\t\t{\n\t\tint blockSize;\n\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )\n\t\t\tstatus = CRYPT_ARGERROR_NUM1;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Make sure that the IV has been set */\n\tif( needsIV( mode ) && !isStreamCipher( algorithm ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : \"\",\n\t\t\t\t\t\t\t  cmd->strArgLen[ 0 ] );\n\treturn( status );\n\t}\n\nstatic int cmdDeleteAttribute( COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == COMMAND_DELETEATTRIBUTE );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) && \\\n\t\tcmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_OPTION_LAST )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Delete the attribute.  Since we're usually doing this via the default\n\t   user object which is invisible to the user, we have to use an internal\n\t   message for this one case */\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\treturn( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t\t}\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t}\n\n#ifdef USE_KEYSETS\n\nstatic int cmdDeleteKey( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_KEYMGMT_INFO deletekeyInfo;\n\tint itemType = KEYMGMT_ITEM_PUBLICKEY;\n\n\tassert( cmd->type == COMMAND_DELETEKEY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] <= CRYPT_KEYID_NONE || \\\n\t\tcmd->arg[ 1 ] >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( cmd->arg[ 2 ] )\n\t\t{\n\t\t/* It's a special-case object being fetched from a CA store */\n\t\tif( cmd->arg[ 2 ] == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\titemType = KEYMGMT_ITEM_REQUEST;\n\t\telse\n\t\t\t{\n\t\t\tif( cmd->arg[ 2 ] == CRYPT_CERTTYPE_PKIUSER )\n\t\t\t\titemType = KEYMGMT_ITEM_PKIUSER;\n\t\t\telse\n\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t}\n\t\t}\n\tif( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\tcmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Delete the key from the keyset.  Unless the user has explicitly\n\t   specified a CA item to delete, we set the item type to delete to\n\t   public-key since private-key keysets will interpret this correctly\n\t   to mean they should also delete the associated private key */\n\tsetMessageKeymgmtInfo( &deletekeyInfo, cmd->arg[ 1 ], cmd->strArg[ 0 ],\n\t\t\t\t\t\t   cmd->strArgLen[ 0 ], NULL, 0, KEYMGMT_FLAG_NONE );\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_DELETEKEY,\n\t\t\t\t\t\t\t &deletekeyInfo, itemType ) );\n\t}\n#endif /* USE_KEYSETS */\n\nstatic int cmdDestroyObject( COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == COMMAND_DESTROYOBJECT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* Decrement the object's reference count, which may or may not actually\n\t   destroy it (the kernel marks it as internal so it appears destroyed\n\t   to the caller) */\n\treturn( krnlSendNotifier( cmd->arg[ 0 ], MESSAGE_DECREFCOUNT ) );\n\t}\n\nstatic int cmdEncrypt( COMMAND_INFO *cmd )\n\t{\n\tint algorithm, mode = CRYPT_MODE_NONE, status;\t/* int vs.enum */\n\n\tassert( cmd->type == COMMAND_ENCRYPT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( algorithm <= CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tif( algorithm <= CRYPT_ALGO_LAST_PKC )\n\t\t\t{\n\t\t\tint blockSize;\n\n\t\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_KEYSIZE );\n\t\t\tif( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] != blockSize )\n\t\t\t\tstatus = CRYPT_ARGERROR_NUM1;\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tif( isHashAlgo( algorithm ) || isMacAlgo( algorithm ) )\n\t\t{\n\t\t/* For hash and MAC operations a length of zero is valid since this\n\t\t   is an indication to wrap up the hash operation */\n\t\tif( cmd->strArgLen[ 0 ] < 0 )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( cmd->strArgLen[ 0 ] <= 0 )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tif( mode == CRYPT_MODE_ECB || mode == CRYPT_MODE_CBC )\n\t\t{\n\t\tint blockSize;\n\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusOK( status ) && cmd->strArgLen[ 0 ] % blockSize )\n\t\t\tstatus = CRYPT_ARGERROR_NUM1;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's no IV set, generate one ourselves */\n\tif( needsIV( mode ) && !isStreamCipher( algorithm ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status == CRYPT_ERROR_NOTINITED )\n\t\t\t\tkrnlSendNotifier( cmd->arg[ 0 ], MESSAGE_CTX_GENIV );\n\t\t\telse\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\tstatus = krnlSendMessage( cmd->arg[ 0 ],\n\t\t\t\t\t\t\t  ( isHashAlgo( algorithm ) || \\\n\t\t\t\t\t\t\t\tisMacAlgo( algorithm ) ) ? \\\n\t\t\t\t\t\t\t\tMESSAGE_CTX_HASH : MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t  cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : \"\",\n\t\t\t\t\t\t\t  cmd->strArgLen[ 0 ] );\n\tif( isHashAlgo( algorithm ) || isMacAlgo( algorithm ) )\n\t\t{\n\t\t/* There's no data to return since the hashing doesn't change it */\n\t\tcmd->strArgLen[ 0 ] = 0;\n\t\t}\n\treturn( status );\n\t}\n\n#ifdef USE_CERTIFICATES\n\nstatic int cmdExportObject( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( cmd->type == COMMAND_EXPORTOBJECT );\n\tassert( cmd->flags == COMMAND_FLAG_NONE || \\\n\t\t\tcmd->flags == COMMAND_FLAG_RET_LENGTH );\n\tassert( cmd->noArgs == 2 );\n\tassert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \\\n\t\t\t( cmd->flags == COMMAND_FLAG_RET_LENGTH && cmd->noStrArgs == 0 ) );\n\tassert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \\\n\t\t\tcmd->strArg[ 0 ] != NULL );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] <= CRYPT_CERTFORMAT_NONE || \\\n\t\tcmd->arg[ 1 ] >= CRYPT_CERTFORMAT_LAST_EXTERNAL )\n\t\t{\n\t\t/* At the moment the only object that we can export is a certificate, \n\t\t   so we make sure that the format type is valid for this */\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Export the certificate */\n\tif( cmd->flags == COMMAND_FLAG_RET_LENGTH )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_EXPORT,\n\t\t\t\t\t\t\t\t  &msgData, cmd->arg[ 1 ] );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tcmd->arg[ 0 ] = msgData.length;\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_CRT_EXPORT,\n\t\t\t\t\t\t\t\t  &msgData, cmd->arg[ 1 ] );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tcmd->strArgLen[ 0 ] = msgData.length;\n\t\t}\n\n\t/* If we try and export using a disallowed format (e.g. a\n\t   CRYPT_CERTFORMAT_CERTCHAIN from a certificate request) we'll get an \n\t   argument value error that we need to convert into something more \n\t   sensible.  The error type to report is somewhat debatable since \n\t   either the format type or the object can be regarded as being wrong, \n\t   for example when exporting a certificate request as a certificate \n\t   chain the format is wrong but when exporting a data-only object as \n\t   anything the object is wrong.  To handle this, we report an argument \n\t   value error as a numeric parameter error for cases where the format \n\t   is incorrect for the object type, and a permission error for cases \n\t   where the object can't be exported externally */\n\tif( status == CRYPT_ARGERROR_VALUE )\n\t\t{\n\t\tint type;\n\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE, &type,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\tstatus = ( type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t\t   type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t\t   type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t\t   type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t\t   type == CRYPT_CERTTYPE_CRL ) ? \\\n\t\t\t\t CRYPT_ARGERROR_NUM1 : CRYPT_ERROR_PERMISSION;\n\t\t}\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n\n#if defined( USE_ENVELOPES ) || defined( USE_SESSIONS )\n\nstatic int cmdFlushData( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( cmd->type == COMMAND_FLUSHDATA );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* Send the flush data command to the object */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t  &msgData, 0 );\n\treturn( status );\n\t}\n#endif /* USE_ENVELOPES || USE_SESSIONS */\n\nstatic int cmdGenKey( COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == COMMAND_GENKEY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\treturn( krnlSendNotifier( cmd->arg[ 0 ], MESSAGE_CTX_GENKEY ) );\n\t}\n\nstatic int cmdGetAttribute( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( cmd->type == COMMAND_GETATTRIBUTE );\n\tassert( cmd->flags == COMMAND_FLAG_NONE || \\\n\t\t\tcmd->flags == COMMAND_FLAG_RET_LENGTH );\n\tassert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );\n\tassert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \\\n\t\t\t( ( cmd->noArgs == 2 || cmd->flags == COMMAND_FLAG_RET_LENGTH ) && \\\n\t\t\t\tcmd->noStrArgs == 0 ) );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) && \\\n\t\tcmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_OPTION_LAST )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\telse\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\n\t/* Get the attribute data from the object.  If it's a config option,\n\t   we're usually doing this via the default user object which is\n\t   invisible to the user, so we have to use an internal message for this\n\t   one case.\n\n\t   This is further complicated by the fact that the kernel checks that\n\t   the destination memory is writable and either returns an error (for\n\t   an external message) or throws an exception (for the internal message\n\t   required to access the user object) if it isn't.  Since the external\n\t   API doesn't allow the specification of the returned data length, it\n\t   uses a worst-case estimate which may be much larger than the actual\n\t   buffer size, which the kernel will refuse to write to.  To handle\n\t   this we first read the actual length and then ask for only that much\n\t   data, which the caller should have made available for the output */\n\tif( cmd->noArgs == 2 )\n\t\t{\n\t\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t\t{\n\t\t\treturn( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE, &cmd->arg[ 0 ],\n\t\t\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t\t\t}\n\t\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t &cmd->arg[ 0 ], cmd->arg[ 1 ] ) );\n\t\t}\n\tsetMessageData( &msgData, NULL, 0 );\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  cmd->arg[ 1 ] );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, cmd->arg[ 1 ] );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( cmd->flags == COMMAND_FLAG_RET_LENGTH )\n\t\t{\n\t\tcmd->arg[ 0 ] = msgData.length;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tmsgData.data = cmd->strArg[ 0 ];\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  cmd->arg[ 1 ] );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, cmd->arg[ 1 ] );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tcmd->strArgLen[ 0 ] = msgData.length;\n\treturn( status );\n\t}\n\n#ifdef USE_KEYSETS\n\nstatic int cmdGetKey( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint messageType = ( cmd->arg[ 2 ] == CRYPT_KEYID_NONE ) ? \\\n\t\t\t\tMESSAGE_KEY_GETNEXTCERT : MESSAGE_KEY_GETKEY;\n\tint owner, status;\n\n\tassert( cmd->type == COMMAND_GETKEY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 3 );\n\tassert( cmd->noStrArgs >= 1 && cmd->noStrArgs <= 2 );\n\n\t/* Perform basic server-side error checking.  Because of keyset queries\n\t   we have to accept CRYPT_KEYID_NONE as well as obviously valid key\n\t   IDs.  In addition if we find a missing ID we pass the request in as\n\t   a keyset query (this is matched to an implicit GetFirstCert performed\n\t   by setting the query attribute, this isn't really possible using the\n\t   external API) */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] <= KEYMGMT_ITEM_NONE || \\\n\t\tcmd->arg[ 1 ] >= KEYMGMT_ITEM_REVOCATIONINFO )\n\t\t{\n\t\t/* Item can only be a public key, private key, secret key, CA \n\t\t   request, or CA PKI user info */\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tif( cmd->arg[ 2 ] < CRYPT_KEYID_NONE || \\\n\t\tcmd->arg[ 2 ] >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tif( cmd->arg[ 2 ] == CRYPT_KEYID_NONE )\n\t\t{\n\t\tif( cmd->arg[ 1 ] != KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t{\n\t\t\t/* If we're doing a keyset query, it has to be for a \n\t\t\t   certificate */\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\tif( cmd->strArgLen[ 0 ] )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\t\tcmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Read the key from the keyset */\n\tsetMessageKeymgmtInfo( &getkeyInfo, cmd->arg[ 2 ],\n\t\t\t\t\t\t   cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL,\n\t\t\t\t\t\t\tcmd->strArgLen[ 0 ],\n\t\t\t\t\t\t   cmd->strArgLen[ 1 ] ? cmd->strArg[ 1 ] : NULL,\n\t\t\t\t\t\t\tcmd->strArgLen[ 1 ], KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], messageType, &getkeyInfo,\n\t\t\t\t\t\t\t  cmd->arg[ 1 ] );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the keyset is bound to a thread, bind the key read from it to the\n\t   thread as well.  If this fails, we don't return the imported key to\n\t   the caller since it would be returned in a potentially unbound state */\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_GETATTRIBUTE, &owner,\n\t\t\t\t\t\t\t  CRYPT_PROPERTY_OWNER );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( getkeyInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &owner,\n\t\t\t\t\t\t\t\t  CRYPT_PROPERTY_OWNER );\n\t\t}\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\tcmd->arg[ 0 ] = getkeyInfo.cryptHandle;\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_KEYSETS */\n\n#if defined( USE_ENVELOPES ) || defined( USE_SESSIONS )\n\nstatic int cmdPopData( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( cmd->type == COMMAND_POPDATA );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] < 1 )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Get the data from the object.  We always copy out the byte count value\n\t   because it's valid even if an error occurs */\n\tsetMessageData( &msgData, cmd->strArg[ 0 ], cmd->arg[ 1 ] );\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_POPDATA,\n\t\t\t\t\t\t\t  &msgData, 0 );\n\tcmd->strArgLen[ 0 ] = msgData.length;\n\treturn( status );\n\t}\n\nstatic int cmdPushData( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( cmd->type == COMMAND_PUSHDATA );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs == 1 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->strArgLen[ 0 ] < 0 )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Send the data to the object.  We always copy out the byte count value\n\t   because it's valid even if an error occurs */\n\tsetMessageData( &msgData, cmd->strArgLen[ 0 ] ? cmd->strArg[ 0 ] : NULL,\n\t\t\t\t\tcmd->strArgLen[ 0 ] );\n\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_ENV_PUSHDATA, &msgData,\n\t\t\t\t\t\t\t  0 );\n\tcmd->arg[ 0 ] = msgData.length;\n\treturn( status );\n\t}\n#endif /* USE_ENVELOPES || USE_SESSIONS */\n\nstatic int cmdQueryCapability( COMMAND_INFO *cmd )\n\t{\n\tCRYPT_QUERY_INFO queryInfo;\n\tint status;\n\n\tassert( cmd->type == COMMAND_QUERYCAPABILITY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE || \\\n\t\t\tcmd->flags == COMMAND_FLAG_RET_LENGTH );\n\tassert( cmd->noArgs == 2 );\n\tassert( ( cmd->flags == COMMAND_FLAG_NONE && cmd->noStrArgs == 1 ) || \\\n\t\t\t( cmd->flags == COMMAND_FLAG_RET_LENGTH && cmd->noStrArgs == 0 ) );\n\tassert( cmd->flags == COMMAND_FLAG_RET_LENGTH || \\\n\t\t\tcmd->strArg[ 0 ] != NULL );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) && \\\n\t\tcmd->arg[ 0 ] != SYSTEM_OBJECT_HANDLE )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 1 ] < CRYPT_ALGO_NONE || \\\n\t\tcmd->arg[ 1 ] >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Query the device for information on the given algorithm and mode.\n\t   Since we're usually doing this via the system object which is\n\t   invisible to the user, we have to use an internal message for this\n\t   one case */\n\tif( cmd->arg[ 0 ] == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,\n\t\t\t\t\t\t\t\t  cmd->arg[ 1 ] );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmd->arg[ 0 ], MESSAGE_DEV_QUERYCAPABILITY,\n\t\t\t\t\t\t\t\t  &queryInfo, cmd->arg[ 1 ] );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Return either the length or the full capability into on what the\n\t\t   caller has asked for */\n\t\tif( cmd->flags == COMMAND_FLAG_RET_LENGTH )\n\t\t\tcmd->arg[ 0 ] = sizeof( CRYPT_QUERY_INFO );\n\t\telse\n\t\t\t{\n\t\t\tmemcpy( cmd->strArg[ 0 ], &queryInfo,\n\t\t\t\t\tsizeof( CRYPT_QUERY_INFO ) );\n\t\t\tcmd->strArgLen[ 0 ] = sizeof( CRYPT_QUERY_INFO );\n\t\t\t}\n\t\t}\n\n\treturn( status );\n\t}\n\n#ifdef USE_RPCAPI\n\nstatic int cmdServerQuery( COMMAND_INFO *cmd )\n\t{\n\tint value;\n\n\tassert( cmd->type == COMMAND_SERVERQUERY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 0 );\n\tassert( cmd->noStrArgs == 0 );\n\n\t/* Return information about the server */\n\tkrnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t &value, CRYPT_OPTION_INFO_MAJORVERSION );\n\tkrnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t &value, CRYPT_OPTION_INFO_MINORVERSION );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_RPCAPI */\n\nstatic int cmdSetAttribute( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_DATA msgData;\n\n\tassert( cmd->type == COMMAND_SETATTRIBUTE );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( ( cmd->noArgs == 3 && cmd->noStrArgs == 0 ) ||\n\t\t\t( cmd->noArgs == 2 && cmd->noStrArgs == 1 ) );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) && \\\n\t\tcmd->arg[ 0 ] != DEFAULTUSER_OBJECT_HANDLE )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_OPTION_FIRST || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_OPTION_LAST )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\telse\n\t\t{\n\t\tif( cmd->arg[ 1 ] <= CRYPT_ATTRIBUTE_NONE || \\\n\t\t\tcmd->arg[ 1 ] >= CRYPT_ATTRIBUTE_LAST )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\tif( cmd->noStrArgs == 1 )\n\t\t{\n\t\tif( cmd->arg[ 1 ] == CRYPT_CTXINFO_KEY_COMPONENTS )\n\t\t\t{\n\t\t\t/* Public key components constitute a special case since the\n\t\t\t   composite structures used are quite large */\n\t\t\tif( cmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_RSA ) && \\\n\t\t\t\tcmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_DLP ) && \\\n\t\t\t\tcmd->strArgLen[ 0 ] != sizeof( CRYPT_PKCINFO_ECC ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( cmd->strArgLen[ 0 ] < 1 || \\\n\t\t\t\tcmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t}\n\t\t}\n\n\t/* Send the attribute data to the object, mapping the return code to the\n\t   correct value if necessary.  If it's a config option, we're usually\n\t   doing this via the default user object which is invisible to the user,\n\t   so we have to use an internal message for this one case */\n\tif( cmd->noStrArgs == 0 )\n\t\t{\n\t\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t\t{\n\t\t\treturn( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t ( MESSAGE_CAST ) &cmd->arg[ 2 ],\n\t\t\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t\t\t}\n\t\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t ( MESSAGE_CAST ) &cmd->arg[ 2 ], cmd->arg[ 1 ] ) );\n\t\t}\n\tsetMessageData( &msgData, cmd->strArg[ 0 ], cmd->strArgLen[ 0 ] );\n\tif( cmd->arg[ 0 ] == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\treturn( krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t cmd->arg[ 1 ] ) );\n\t\t}\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, cmd->arg[ 1 ] ) );\n\t}\n\n#ifdef USE_KEYSETS\n\nstatic int cmdSetKey( COMMAND_INFO *cmd )\n\t{\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tint itemType = ( cmd->noStrArgs == 1 ) ? \\\n\t\t\t\t   KEYMGMT_ITEM_PRIVATEKEY : KEYMGMT_ITEM_PUBLICKEY;\n\n\tassert( cmd->type == COMMAND_SETKEY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs >= 2 && cmd->noArgs <= 3 );\n\tassert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 1 );\n\n\t/* Perform basic server-side error checking */\n\tif( !isHandleRangeValid( cmd->arg[ 0 ] ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( !isHandleRangeValid( cmd->arg[ 1 ] ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( cmd->noStrArgs == 1 && \\\n\t\t( cmd->strArgLen[ 0 ] < MIN_NAME_LENGTH || \\\n\t\t  cmd->strArgLen[ 0 ] >= MAX_ATTRIBUTE_SIZE ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( cmd->arg[ 2 ] )\n\t\t{\n\t\tint value;\n\n\t\t/* It's a certificate management item request being added to a CA \n\t\t   store, usually this is a request but it may also be PKI user \n\t\t   info */\n\t\titemType = KEYMGMT_ITEM_REQUEST;\n\t\tif( cryptStatusOK( krnlSendMessage( cmd->arg[ 1 ],\n\t\t\t\t\t\t\t\t\tMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTTYPE ) ) && \\\n\t\t\tvalue == CRYPT_CERTTYPE_PKIUSER )\n\t\t\t{\n\t\t\titemType = KEYMGMT_ITEM_PKIUSER;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tint value;\n\n\t\t/* If we're adding a CRL, add it as revocation information rather\n\t\t   than as a generic public-key object */\n\t\tif( itemType != KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t\tcryptStatusOK( krnlSendMessage( cmd->arg[ 1 ],\n\t\t\t\t\t\t\t\t\tMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTTYPE ) ) && \\\n\t\t\tvalue == CRYPT_CERTTYPE_CRL )\n\t\t\t{\n\t\t\titemType = KEYMGMT_ITEM_REVOCATIONINFO;\n\t\t\t}\n\t\t}\n\n\t/* Add the key */\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t   ( cmd->noStrArgs == 1 ) ? cmd->strArg[ 0 ] : NULL,\n\t\t\t\t\t\t   cmd->strArgLen[ 0 ], KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = cmd->arg[ 1 ];\n\treturn( krnlSendMessage( cmd->arg[ 0 ], MESSAGE_KEY_SETKEY,\n\t\t\t\t\t\t\t &setkeyInfo, itemType ) );\n\t}\n#endif /* USE_KEYSETS */\n\n#ifdef USE_RPCAPI\n\n/* Process a command from the client and send it to the appropriate handler */\n\nstatic const COMMAND_HANDLER commandHandlers[] = {\n\tNULL, NULL, cmdServerQuery, cmdCreateObject, cmdCreateObjectIndirect,\n\tcmdExportObject, cmdDestroyObject, cmdQueryCapability, cmdGenKey,\n\tcmdEncrypt, cmdDecrypt, cmdGetAttribute, cmdSetAttribute,\n\tcmdDeleteAttribute, cmdGetKey, cmdSetKey, cmdDeleteKey, cmdPushData,\n\tcmdPopData, cmdFlushData, cmdCertSign, cmdCertCheck, cmdCertMgmt };\n\nstatic void processCommand( BYTE *buffer )\n\t{\n\tCOMMAND_INFO cmd = { 0 };\n\tBYTE header[ COMMAND_FIXED_DATA_SIZE ], *bufPtr;\n\tlong totalLength;\n\tint i, status, LOOP_ITERATOR;\n\n\t/* Read the client's message header */\n\tmemcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );\n\n\t/* Process the fixed message header and make sure it's valid */\n\tgetMessageType( header, cmd.type, cmd.flags, cmd.noArgs, cmd.noStrArgs );\n\ttotalLength = getMessageLength( header + COMMAND_WORDSIZE );\n\tif( !checkCommandInfo( &cmd, totalLength ) || \\\n\t\tcmd.type == COMMAND_RESULT )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\n\t\t/* Return an invalid result message */\n\t\tputMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );\n\t\tputMessageLength( buffer + COMMAND_WORDSIZE, 0 );\n\t\treturn;\n\t\t}\n\n\t/* Read the rest of the clients message */\n\tbufPtr = buffer + COMMAND_FIXED_DATA_SIZE;\n\tLOOP_SMALL( i = 0, i < cmd.noArgs, i++ )\n\t\t{\n\t\tcmd.arg[ i ] = getMessageWord( bufPtr );\n\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tLOOP_SMALL( i = 0, i < cmd.noStrArgs, i++ )\n\t\t{\n\t\tcmd.strArgLen[ i ] = getMessageWord( bufPtr );\n\t\tcmd.strArg[ i ] = bufPtr + COMMAND_WORDSIZE;\n\t\tbufPtr += COMMAND_WORDSIZE + cmd.strArgLen[ i ];\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( !checkCommandConsistency( &cmd, totalLength ) )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\n\t\t/* Return an invalid result message */\n\t\tputMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );\n\t\tputMessageLength( buffer + COMMAND_WORDSIZE, 0 );\n\t\treturn;\n\t\t}\n\n\t/* If it's a command that returns a string value, obtain the returned\n\t   data in the buffer.  Normally we limit the size to the maximum\n\t   attribute size, however encoded objects and data popped from\n\t   envelopes/sessions can be larger than this so we use the entire buffer\n\t   minus a safety margin */\n\tif( cmd.type == COMMAND_POPDATA || \\\n\t\t( cmd.flags != COMMAND_FLAG_RET_LENGTH && \\\n\t\t  ( cmd.type == COMMAND_EXPORTOBJECT || \\\n\t\t\tcmd.type == COMMAND_QUERYCAPABILITY || \\\n\t\t\t( cmd.type == COMMAND_GETATTRIBUTE && \\\n\t\t\t  cmd.noArgs == 3 ) ) ) )\n\t\t{\n\t\tcmd.noStrArgs = 1;\n\t\tcmd.strArg[ 0 ] = bufPtr;\n\t\tif( cmd.type == COMMAND_EXPORTOBJECT || cmd.type == COMMAND_POPDATA )\n\t\t\t{\n\t\t\tcmd.strArgLen[ 0 ] = RPC_IO_BUFSIZE - 16 - ( bufPtr - buffer );\n\t\t\tassert( cmd.type != COMMAND_POPDATA || \\\n\t\t\t\t\tcmd.strArgLen[ 0 ] >= MAX_FRAGMENT_SIZE );\n\t\t\t}\n\t\telse\n\t\t\tcmd.strArgLen[ 0 ] = MAX_ATTRIBUTE_SIZE;\n\t\t}\n\n\t/* Process the command and copy any return information back to the\n\t   caller */\n\tstatus = commandHandlers[ cmd.type ]( NULL, &cmd );\n\tbufPtr = buffer;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The push data command is a special case since an error can occur\n\t\t   after some data has been processed, so we still need to copy back\n\t\t   a result even if we get an error status */\n\t\tif( cmd.type == COMMAND_PUSHDATA )\n\t\t\t{\n\t\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 2, 0 );\n\t\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE * 2 );\n\t\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, status );\n\t\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* The command failed, return a simple status value */\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, status );\n\t\treturn;\n\t\t}\n\tif( cmd.type == COMMAND_CREATEOBJECT || \\\n\t\tcmd.type == COMMAND_CREATEOBJECT_INDIRECT || \\\n\t\tcmd.type == COMMAND_GETKEY || \\\n\t\tcmd.type == COMMAND_PUSHDATA || \\\n\t\t( ( cmd.type == COMMAND_EXPORTOBJECT || \\\n\t\t\tcmd.type == COMMAND_QUERYCAPABILITY ) && \\\n\t\t  cmd.flags == COMMAND_FLAG_RET_LENGTH ) || \\\n\t\t( cmd.type == COMMAND_GETATTRIBUTE && \\\n\t\t  ( cmd.noArgs == 2 || cmd.flags == COMMAND_FLAG_RET_LENGTH ) ) || \\\n\t\t( cmd.type == COMMAND_CERTMGMT && cmd.flags != COMMAND_FLAG_RET_NONE ) )\n\t\t{\n\t\t/* Return object handle or numeric value or string length */\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 2, 0 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE * 2 );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );\n\t\treturn;\n\t\t}\n\tif( cmd.type == COMMAND_ENCRYPT || \\\n\t\tcmd.type == COMMAND_DECRYPT || \\\n\t\tcmd.type == COMMAND_POPDATA || \\\n\t\tcmd.type == COMMAND_EXPORTOBJECT || \\\n\t\tcmd.type == COMMAND_QUERYCAPABILITY || \\\n\t\tcmd.type == COMMAND_GETATTRIBUTE )\n\t\t{\n\t\tconst long dataLength = cmd.strArgLen[ 0 ];\n\n\t\t/* Return capability info or attribute data and length */\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 1 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE,\n\t\t\t\t\t\t  ( COMMAND_WORDSIZE * 2 ) + cmd.strArgLen[ 0 ] );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, dataLength );\n\t\tif( dataLength )\n\t\t\t{\n\t\t\tmemmove( bufPtr + COMMAND_WORD3_OFFSET, cmd.strArg[ 0 ],\n\t\t\t\t\t dataLength );\n\t\t\t}\n\t\treturn;\n\t\t}\n\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );\n\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE );\n\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t}\n\n/* Dummy forwarding procedure to take the place of the comms channel between\n   client and server */\n\nstatic void serverTransact( void *clientBuffer )\n\t{\n#ifdef CONFIG_CONSERVE_MEMORY\n\tstatic BYTE *serverBuffer = NULL;\n#else\n\tBYTE serverBuffer[ RPC_IO_BUFSIZE ];\n#endif /* Memory-starved systems */\n\tint length;\n\n\t/* On memory-starved systems (typically older ones limited to a maximum\n\t   of 64K of stack) we have to malloc() this on demand.  Since there's\n\t   no threading this is OK since there won't be any race conditions.\n\t   Note that there's no way to free this, but it'll be automatically\n\t   freed when the OS reclaims the application heap */\n#ifdef CONFIG_CONSERVE_MEMORY\n\tif( serverBuffer == NULL && \\\n\t\t( serverBuffer = clAlloc( \"serverTransact\", \\\n\t\t\t\t\t\t\t\t  RPC_IO_BUFSIZE ) ) == NULL )\n\t\t{\n\t\tmemset( clientBuffer, 0, 16 );\n\t\treturn;\n\t\t}\n#endif /* Memory-starved systems */\n\n\t/* Copy the command to the server buffer, process it, and copy the result\n\t   back to the client buffer to emulate the client <-> server\n\t   transmission */\n\tlength = getMessageLength( ( BYTE * ) clientBuffer + COMMAND_WORDSIZE );\n\tmemcpy( serverBuffer, clientBuffer, length + COMMAND_FIXED_DATA_SIZE );\n\tprocessCommand( serverBuffer );\n\tlength = getMessageLength( ( BYTE * ) serverBuffer + COMMAND_WORDSIZE );\n\tmemcpy( clientBuffer, serverBuffer, length + COMMAND_FIXED_DATA_SIZE );\n\t}\n\n/* Dispatch a command to the server */\n\nstatic int dispatchCommand( COMMAND_INFO *cmd )\n\t{\n\tCOMMAND_INFO sentCmd = *cmd;\n\tBYTE buffer[ RPC_IO_BUFSIZE ], *bufPtr = buffer;\n\tBYTE header[ COMMAND_FIXED_DATA_SIZE ];\n\tBYTE *payloadStartPtr, *payloadPtr;\n\tconst BOOLEAN isPushPop = \\\n\t\t( cmd->type == COMMAND_PUSHDATA || cmd->type == COMMAND_POPDATA ) ? \\\n\t\tTRUE : FALSE;\n\tconst BOOLEAN isDataCommand = \\\n\t\t( cmd->type == COMMAND_ENCRYPT || cmd->type == COMMAND_DECRYPT || \\\n\t\t  isPushPop ) ? TRUE : FALSE;\n\tconst long payloadLength = ( cmd->noArgs * COMMAND_WORDSIZE ) + \\\n\t\t\t\t\t\t\t   ( cmd->noStrArgs * COMMAND_WORDSIZE ) + \\\n\t\t\t\t\t\t\t   cmd->strArgLen[ 0 ] + cmd->strArgLen[ 1 ];\n\tlong dataLength = ( cmd->type == COMMAND_POPDATA ) ? \\\n\t\t\t\t\t  cmd->arg[ 1 ] : cmd->strArgLen[ 0 ], resultLength;\n\tint i, LOOP_ITERATOR;\n\n\tassert( checkCommandInfo( cmd, 0 ) );\n\n\t/* Clear the return value */\n\tmemset( cmd, 0, sizeof( COMMAND_INFO ) );\n\n\t/* Make sure the data will fit into the buffer */\n\tif( !isDataCommand && \\\n\t\t( COMMAND_FIXED_DATA_SIZE + payloadLength ) > RPC_IO_BUFSIZE )\n\t\t{\n\t\tlong maxLength = dataLength;\n\t\tint maxPos = 0;\n\n\t\t/* Find the longest arg (the one that contributes most to the\n\t\t   problem) and report it as an error.  We report the problem\n\t\t   as being with the numeric rather than the string arg since\n\t\t   string args with implicit lengths (e.g.text strings) have\n\t\t   their length check in the API function, and all other string\n\t\t   args are given as (data, length) pairs  */\n\t\tLOOP_SMALL( i = 0, i < sentCmd.noStrArgs, i++ )\n\t\t\t{\n\t\t\tif( sentCmd.strArgLen[ i ] > maxLength )\n\t\t\t\t{\n\t\t\t\tmaxLength = sentCmd.strArgLen[ i ];\n\t\t\t\tmaxPos = i;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\treturn( CRYPT_ARGERROR_NUM1 - maxPos );\n\t\t}\n\n\t/* If it's a short-datasize command, process it and return immediately */\n\tif( !isDataCommand || ( dataLength < MAX_FRAGMENT_SIZE ) )\n\t\t{\n\t\t/* Write the header and message fields to the buffer */\n\t\tputMessageType( bufPtr, sentCmd.type, sentCmd.flags,\n\t\t\t\t\t\tsentCmd.noArgs, sentCmd.noStrArgs );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, payloadLength );\n\t\tbufPtr += COMMAND_FIXED_DATA_SIZE;\n\t\tLOOP_SMALL( i = 0, i < sentCmd.noArgs, i++ )\n\t\t\t{\n\t\t\tputMessageWord( bufPtr, sentCmd.arg[ i ] );\n\t\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tLOOP_SMALL( i = 0, i < sentCmd.noStrArgs, i++ )\n\t\t\t{\n\t\t\tconst int argLength = sentCmd.strArgLen[ i ];\n\n\t\t\tputMessageWord( bufPtr, argLength );\n\t\t\tif( argLength > 0 )\n\t\t\t\t{\n\t\t\t\tmemcpy( bufPtr + COMMAND_WORDSIZE, sentCmd.strArg[ i ],\n\t\t\t\t\t\targLength );\n\t\t\t\t}\n\t\t\tbufPtr += COMMAND_WORDSIZE + argLength;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Send the command to the server and read the servers message header */\n\t\tserverTransact( buffer );\n\t\tmemcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );\n\n\t\t/* Process the fixed message header and make sure that it's valid */\n\t\tgetMessageType( header, cmd->type, cmd->flags,\n\t\t\t\t\t\tcmd->noArgs, cmd->noStrArgs );\n\t\tresultLength = getMessageLength( header + COMMAND_WORDSIZE );\n\t\tif( !checkCommandInfo( cmd, resultLength ) || \\\n\t\t\tcmd->type != COMMAND_RESULT )\n\t\t\t{\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR );\n\t\t\t}\n\n\t\t/* Read the rest of the server's message */\n\t\tbufPtr = buffer + COMMAND_FIXED_DATA_SIZE;\n\t\tLOOP_SMALL( i = 0, i < cmd->noArgs, i++ )\n\t\t\t{\n\t\t\tcmd->arg[ i ] = getMessageWord( bufPtr );\n\t\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tLOOP_SMALL( i = 0, i < cmd->noStrArgs, i++ )\n\t\t\t{\n\t\t\tcmd->strArgLen[ i ] = getMessageWord( bufPtr );\n\t\t\tcmd->strArg[ i ] = bufPtr + COMMAND_WORDSIZE;\n\t\t\tbufPtr += COMMAND_WORDSIZE + cmd->strArgLen[ i ];\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* The first value returned is the status code, if it's nonzero return\n\t\t   it to the caller, otherwise move the other values down */\n\t\tif( cryptStatusError( cmd->arg[ 0 ] ) )\n\t\t\t{\n\t\t\t/* The push data command is a special case since it returns a\n\t\t\t   bytes copied value even if an error occurs */\n\t\t\tif( sentCmd.type == COMMAND_PUSHDATA )\n\t\t\t\t{\n\t\t\t\tconst int status = cmd->arg[ 0 ];\n\n\t\t\t\tcmd->arg[ 0 ] = cmd->arg[ 1 ];\n\t\t\t\tcmd->arg[ 1 ] = 0;\n\t\t\t\tcmd->noArgs--;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\treturn( cmd->arg[ 0 ] );\n\t\t\t}\n\t\tassert( cryptStatusOK( cmd->arg[ 0 ] ) );\n\t\tLOOP_SMALL( i = 1, i < cmd->noArgs, i++ )\n\t\t\tcmd->arg[ i - 1 ] = cmd->arg[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tcmd->arg[ i ] = 0;\n\t\tcmd->noArgs--;\n\n\t\t/* Copy any string arg data back to the caller */\n\t\tif( cmd->noStrArgs && cmd->strArgLen[ 0 ] )\n\t\t\t{\n\t\t\tmemcpy( sentCmd.strArg[ 0 ], cmd->strArg[ 0 ],\n\t\t\t\t\tcmd->strArgLen[ 0 ] );\n\t\t\tcmd->strArg[ 0 ] = sentCmd.strArg[ 0 ];\n\t\t\tif( cmd->type == COMMAND_PUSHDATA )\n\t\t\t\t{\n\t\t\t\t/* A data push returns the actual number of copied bytes\n\t\t\t\t   (which may be less than the requested number of bytes) as\n\t\t\t\t   arg 0 */\n\t\t\t\tcmd->arg[ 0 ] = cmd->strArgLen[ 0 ];\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Remember where the variable-length payload starts in the buffer and\n\t   where it's to be copied to */\n\tpayloadStartPtr = buffer + COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE;\n\tpayloadPtr = sentCmd.strArg[ 0 ];\n\n\t/* It's a long-datasize command, handle fragmentation */\n\tdo\n\t\t{\n\t\tCOMMAND_INFO cmdResult = { 0 };\n\t\tconst int fragmentLength = min( dataLength, MAX_FRAGMENT_SIZE );\n\t\tint status;\n\n\t\t/* Write the fixed and variable-length message fields to the buffer */\n\t\tputMessageType( buffer, sentCmd.type, 0, sentCmd.noArgs,\n\t\t\t\t\t\tsentCmd.noStrArgs );\n\t\tif( sentCmd.type == COMMAND_POPDATA )\n\t\t\t{\n\t\t\tputMessageLength( buffer + COMMAND_WORDSIZE,\n\t\t\t\t\t\t\t  ( COMMAND_WORDSIZE * 2 ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tputMessageLength( buffer + COMMAND_WORDSIZE,\n\t\t\t\t\t\t\t  ( COMMAND_WORDSIZE * 2 ) + fragmentLength );\n\t\t\t}\n\t\tputMessageWord( buffer + COMMAND_FIXED_DATA_SIZE,\n\t\t\t\t\t\tsentCmd.arg[ 0 ] );\n\t\tputMessageWord( payloadStartPtr, fragmentLength );\n\t\tif( sentCmd.type != COMMAND_POPDATA )\n\t\t\t{\n\t\t\tmemcpy( payloadStartPtr + COMMAND_WORDSIZE, payloadPtr,\n\t\t\t\t\tfragmentLength );\n\t\t\t}\n\n\t\t/* Process as much data as we can and read the server's message\n\t\t   header */\n\t\tserverTransact( buffer );\n\t\tmemcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );\n\n\t\t/* Process the fixed message header and make sure it's valid */\n\t\tgetMessageType( header, cmdResult.type, cmdResult.flags,\n\t\t\t\t\t\tcmdResult.noArgs, cmdResult.noStrArgs );\n\t\tresultLength = getMessageLength( header + COMMAND_WORDSIZE );\n\t\tif( !checkCommandInfo( &cmdResult, resultLength ) || \\\n\t\t\tcmdResult.type != COMMAND_RESULT || \\\n\t\t\tcmdResult.flags != COMMAND_FLAG_NONE )\n\t\t\t{\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR );\n\t\t\t}\n\t\tif( cmdResult.noArgs != 1 || cmdResult.noStrArgs )\n\t\t\t{\n\t\t\t/* Make sure the parameters are valid for a non-error return */\n\t\t\tif( sentCmd.type == COMMAND_PUSHDATA )\n\t\t\t\t{\n\t\t\t\tif( cmdResult.noArgs != 2 || cmdResult.noStrArgs )\n\t\t\t\t\t{\n\t\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t\treturn( CRYPT_ERROR );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tif( cmdResult.noArgs != 1 || cmdResult.noStrArgs != 1 )\n\t\t\t\t\t{\n\t\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t\treturn( CRYPT_ERROR );\n\t\t\t\t\t}\n\t\t\t}\n\n\t\t/* Process the fixed message header and make sure it's valid */\n\t\tbufPtr = buffer + COMMAND_FIXED_DATA_SIZE;\n\t\tstatus = getMessageWord( bufPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The push data command is a special case since it returns a\n\t\t\t   bytes copied value even if an error occurs */\n\t\t\tif( sentCmd.type == COMMAND_PUSHDATA )\n\t\t\t\t{\n\t\t\t\tconst long bytesCopied = \\\n\t\t\t\t\t\t\tgetMessageWord( bufPtr + COMMAND_WORDSIZE );\n\n\t\t\t\tif( bytesCopied < 0 )\n\t\t\t\t\t{\n\t\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t\treturn( CRYPT_ERROR );\n\t\t\t\t\t}\n\t\t\t\tcmdResult.arg[ 0 ] = cmd->arg[ 0 ] + bytesCopied;\n\t\t\t\tcmdResult.noArgs = 1;\n\t\t\t\t}\n\t\t\t*cmd = cmdResult;\n\t\t\treturn( status );\n\t\t\t}\n\t\tassert( cryptStatusOK( status ) );\n\n\t\t/* Read the rest of the server's message */\n\t\tresultLength = getMessageWord( bufPtr + COMMAND_WORDSIZE );\n\t\tif( isPushPop )\n\t\t\t{\n\t\t\t/* It's a variable-length transformation, we have to return a\n\t\t\t   non-negative number of bytes */\n\t\t\tif( resultLength <= 0 )\n\t\t\t\t{\n\t\t\t\tif( resultLength == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t/* We've run out of data, return to the caller */\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\treturn( CRYPT_ERROR );\n\t\t\t\t}\n\t\t\tif( cmd->type == COMMAND_PUSHDATA )\n\t\t\t\tcmd->arg[ 0 ] += resultLength;\n\t\t\telse\n\t\t\t\tcmd->strArgLen[ 0 ] += resultLength;\n\t\t\tif( sentCmd.type == COMMAND_POPDATA )\n\t\t\t\t{\n\t\t\t\tmemcpy( payloadPtr, payloadStartPtr + COMMAND_WORDSIZE,\n\t\t\t\t\t\tresultLength );\n\n\t\t\t\t/* If we got less than what we asked for, there's nothing\n\t\t\t\t   more available, exit */\n\t\t\t\tif( resultLength < fragmentLength )\n\t\t\t\t\tdataLength = resultLength;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's an encrypt/decrypt, the result must be a 1:1\n\t\t\t   transformation unless it's a hash, in which case nothing is\n\t\t\t   returned */\n\t\t\tif( resultLength )\n\t\t\t\t{\n\t\t\t\tif( resultLength != fragmentLength )\n\t\t\t\t\t{\n\t\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t\treturn( CRYPT_ERROR );\n\t\t\t\t\t}\n\t\t\t\tmemcpy( payloadPtr, payloadStartPtr + COMMAND_WORDSIZE,\n\t\t\t\t\t\tresultLength );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If no data was returned, it was a hash, set a pseudo-\n\t\t\t\t   result length which is the same size as the amount of\n\t\t\t\t   data fed in */\n\t\t\t\tresultLength = fragmentLength;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Move on to the next fragment */\n\t\tpayloadPtr += resultLength;\n\t\tdataLength -= resultLength;\n\t\t}\n\twhile( dataLength > 0 );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_RPCAPI */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tClient-side Translation Handling\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* When the cryptlib client is using a different character set, we need to\n   map from the internal to the external character set.  The following\n   function checks for attribute values that contain text strings.  In\n   addition the functions cryptGetKey(), cryptGetPrivateKey(), \n   cryptAddPrivateKey(), and cryptLogin() use text strings that need to be \n   mapped to the internal character set */\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\nstatic BOOLEAN needsTranslation( const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tif( attribute < CRYPT_CTXINFO_LAST )\n\t\t{\n\t\tif( attribute < CRYPT_OPTION_LAST )\n\t\t\t{\n\t\t\treturn( ( attribute == CRYPT_ATTRIBUTE_ERRORMESSAGE || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_INFO_DESCRIPTION || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_INFO_COPYRIGHT || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_FILTER || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_CACERTNAME || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_CERTNAME || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_CRLNAME || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_KEYS_LDAP_EMAILNAME || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_DEVICE_PKCS11_DVR01 || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_DEVICE_PKCS11_DVR02 || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_NET_SOCKS_SERVER || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_NET_SOCKS_USERNAME || \\\n\t\t\t\t\t  attribute == CRYPT_OPTION_NET_HTTP_PROXY ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\t\t\t}\n\t\treturn( ( attribute == CRYPT_CTXINFO_NAME_ALGO || \\\n\t\t\t\t  attribute == CRYPT_CTXINFO_NAME_MODE || \\\n\t\t\t\t  attribute == CRYPT_CTXINFO_KEYING_VALUE || \\\n\t\t\t\t  attribute == CRYPT_CTXINFO_LABEL ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute <= CRYPT_CERTINFO_LAST_NAME )\n\t\t{\n\t\tif( attribute < CRYPT_CERTINFO_FIRST_NAME )\n\t\t\t{\n\t\t\treturn( ( attribute == CRYPT_CERTINFO_DN || \\\n\t\t\t\t\t  attribute == CRYPT_CERTINFO_PKIUSER_ID || \\\n\t\t\t\t\t  attribute == CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD || \\\n\t\t\t\t\t  attribute == CRYPT_CERTINFO_PKIUSER_REVPASSWORD ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\t\t\t}\n\t\treturn( ( attribute == CRYPT_CERTINFO_COUNTRYNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_STATEORPROVINCENAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_LOCALITYNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_ORGANIZATIONNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_ORGANIZATIONALUNITNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_COMMONNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_OTHERNAME_TYPEID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_RFC822NAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_DNSNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute <= CRYPT_CERTINFO_LAST_EXTENSION )\n\t\t{\n\t\treturn( ( attribute == CRYPT_CERTINFO_CHALLENGEPASSWORD || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_BIOMETRICINFO_URL || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_QCSTATEMENT_SEMANTICS || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_PROCURE_COUNTRY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_MONETARY_CURRENCY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SIGG_RESTRICTION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SUBJECTDIR_TYPE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CERTPOLICYID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CERTPOLICY_CPSURI || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERACQUIRERBIN || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTLANGUAGE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTCITY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTPOSTALCODE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERCOUNTRY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SET_MERAUTHFLAG ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute <= CRYPT_CERTINFO_LAST_CMS )\n\t\t{\n\t\treturn( ( attribute == CRYPT_CERTINFO_CMS_SECLABEL_POLICY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SECLABEL_CATTYPE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SECLABEL_CATVALUE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_POLICY || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGPOLICYID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SCEP_MESSAGETYPE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SCEP_PKISTATUS || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SCEP_FAILINFO || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_SCEP_TRANSACTIONID || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SPCAGENCYURL || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute < CRYPT_KEYINFO_LAST )\n\t\t{\n\t\treturn( ( attribute == CRYPT_KEYINFO_QUERY || \\\n\t\t\t\t  attribute == CRYPT_KEYINFO_QUERY_REQUESTS ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute < CRYPT_DEVINFO_LAST )\n\t\t{\n\t\treturn( ( attribute == CRYPT_DEVINFO_INITIALISE || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_AUTHENT_USER || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_AUTHENT_SUPERVISOR || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_SET_AUTHENT_USER || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_ZEROISE || \\\n\t\t\t\t  attribute == CRYPT_DEVINFO_LABEL ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute < CRYPT_ENVINFO_LAST )\n\t\t{\n\t\treturn( ( attribute == CRYPT_ENVINFO_PASSWORD || \\\n\t\t\t\t  attribute == CRYPT_ENVINFO_RECIPIENT || \\\n\t\t\t\t  attribute == CRYPT_ENVINFO_PRIVATEKEY_LABEL ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( attribute < CRYPT_SESSINFO_LAST )\n\t\t{\n\t\treturn( ( attribute == CRYPT_SESSINFO_USERNAME || \\\n\t\t\t\t  attribute == CRYPT_SESSINFO_PASSWORD || \\\n\t\t\t\t  attribute == CRYPT_SESSINFO_SERVER_NAME || \\\n\t\t\t\t  attribute == CRYPT_SESSINFO_CLIENT_NAME ) ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\treturn( ( attribute == CRYPT_USERINFO_PASSWORD ) ? TRUE : FALSE );\n\t}\n\n#ifdef EBCDIC_CHARS\n  #define nativeStrlen( string )\tstrlen( string )\n  #define nativeToCryptlibString( dest, destMaxLen, src, length ) \\\n\t\t  ebcdicToAscii( dest, src, length )\n  #define cryptlibToNativeString( dest, destMaxLen, src, length ) \\\n\t\t  asciiToEbcdic( dest, src, length )\n#else\n  #define nativeStrlen( string )\twcslen( string )\n  #define nativeToCryptlibString( dest, destMaxLen, src, length ) \\\n\t\t  unicodeToAscii( dest, destMaxLen, src, length )\n  #define cryptlibToNativeString( dest, destMaxLen, src, length ) \\\n\t\t  asciiToUnicode( dest, destMaxLen, src, length )\n#endif /* EBCDIC vs. Unicode translation */\n\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some functions take null-terminated strings as parameters, since these\n   can be ASCII or Unicode strings depending on the environment we need to\n   define a situation-specific get-string-length function to handle them */\n\n#ifdef nativeStrlen\n  #define strParamLen\tnativeStrlen\n#else\n  #define strParamLen\tstrlen\n#endif /* System-specific string parameter length functions */\n\n/* Internal parameter errors are reported in terms of the parameter type (e.g.\n   invalid object, invalid attribute), but externally they're reported in\n   terms of parameter numbers.  Before we return error values to the caller,\n   we have to map them from the internal representation to the position they\n   occur in in the function parameter list.  The following function takes a\n   list of parameter types and maps the returned parameter type error to a\n   parameter position error */\n\ntypedef enum {\n\tARG_D,\t\t\t/* Dummy placeholder */\n\tARG_O,\t\t\t/* Object */\n\tARG_V,\t\t\t/* Value (attribute) */\n\tARG_N,\t\t\t/* Numeric arg */\n\tARG_S,\t\t\t/* String arg */\n\tARG_LAST\n\t} ERRORMAP;\n\nstatic int mapError( const ERRORMAP *errorMap, const int errorMapSize, \n\t\t\t\t\t const int status )\n\t{\n\tERRORMAP type;\n\tint count = 0, i, LOOP_ITERATOR;\n\n\t/* If it's not an internal parameter error, let it out */\n\tif( !cryptArgError( status ) )\n\t\t{\n\t\tassert( cryptStandardError( status ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Map the parameter error to a position error */\n\tswitch( status )\n\t\t{\n\t\tcase CRYPT_ARGERROR_OBJECT:\n\t\t\ttype = ARG_O;\n\t\t\tbreak;\n\t\tcase CRYPT_ARGERROR_VALUE:\n\t\t\ttype = ARG_V;\n\t\t\tbreak;\n\t\tcase CRYPT_ARGERROR_NUM1:\n\t\tcase CRYPT_ARGERROR_NUM2:\n\t\t\ttype = ARG_N;\n\t\t\tcount = CRYPT_ARGERROR_NUM1 - status;\n\t\t\tbreak;\n\t\tcase CRYPT_ARGERROR_STR1:\n\t\tcase CRYPT_ARGERROR_STR2:\n\t\t\ttype = ARG_S;\n\t\t\tcount = CRYPT_ARGERROR_STR1 - status;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tLOOP_SMALL( i = 0, errorMap[ i ] != ARG_LAST && \\\n\t\t\t\t\t   i < errorMapSize, i++ )\n\t\t{\n\t\tif( errorMap[ i ] == type && !count-- )\n\t\t\treturn( CRYPT_ERROR_PARAM1 - i );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < errorMapSize );\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCreate/Destroy Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A flag to record whether the external API initialisation function has\n   been called.  This merely reflects the current state of the cryptInit()/\n   cryptEnd() calls at the external API level rather than the internal state\n   of the kernel, and is used to try and catch problems with people who\n   don't call cryptInit() */\n\nstatic BOOLEAN initCalled = FALSE;\n\n/* Initialise and shut down cryptlib.  These functions are a type of super-\n   create/destroy in that they create/destroy an instantiation of cryptlib.\n   Unlike the other functions in this module, these can't pass control to\n   the kernel because it hasn't been instantiated yet, so they pass the call\n   down to the internal init/shutdown functions */\n\nC_CHECK_RETVAL \\\nC_RET cryptInit( void )\n\t{\n\tint status;\n\n\tstatus = initCryptlib();\n\tif( cryptStatusOK( status ) )\n\t\tinitCalled = TRUE;\n\treturn( status );\n\t}\n\nC_RET cryptEnd( void )\n\t{\n\tinitCalled = FALSE;\n\treturn( endCryptlib() );\n\t}\n\n/* Create an encryption context */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateContext( C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t  C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t  C_IN CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_CONTEXT } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isWritePtr( cryptContext, sizeof( CRYPT_CONTEXT ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*cryptContext = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( cryptAlgo <= CRYPT_ALGO_NONE || \\\n\t\tcryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = cryptAlgo;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*cryptContext = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Create an encryption context via the device */\n\n#ifdef USE_DEVICES\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptDeviceCreateContext( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t    C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t\t    C_IN CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { 0, OBJECT_TYPE_CONTEXT } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_D, ARG_N, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( device ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( cryptContext, sizeof( CRYPT_CONTEXT ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\t*cryptContext = CRYPT_ERROR;\n\tif( cryptAlgo <= CRYPT_ALGO_NONE || \\\n\t\tcryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = device;\n\tcmd.arg[ 2 ] = cryptAlgo;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*cryptContext = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_DEVICES */\n\n/* Create a certificate */\n\n#ifdef USE_CERTIFICATES\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateCert( C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_CERTIFICATE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isWritePtr( certificate, sizeof( CRYPT_CERTIFICATE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*certificate = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( certType <= CRYPT_CERTTYPE_NONE || \\\n\t\tcertType >= CRYPT_CERTTYPE_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = certType;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*certificate = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_CERTIFICATES */\n\n/* Open a device */\n\n#ifdef USE_DEVICES\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptDeviceOpen( C_OUT CRYPT_DEVICE C_PTR device,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t   C_IN_OPT C_STR name )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 1,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_DEVICE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *namePtr = NULL;\n#else\n\tconst char *namePtr = name;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint nameLen = 0, status;\n\n\t/* Perform basic error checking */\n\tif( !isReadPtr( device, sizeof( CRYPT_DEVICE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*device = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( deviceType <= CRYPT_DEVICE_NONE || deviceType >= CRYPT_DEVICE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( ( deviceType == CRYPT_DEVICE_PKCS11 || \\\n\t\t  deviceType == CRYPT_DEVICE_CRYPTOAPI ) && \\\n\t\t( !isReadPtr( name, MIN_NAME_LENGTH ) || \\\n\t\t  strParamLen( name ) < MIN_NAME_LENGTH || \\\n\t\t  strParamLen( name ) >= MAX_ATTRIBUTE_SIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tif( name != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t name, nativeStrlen( name ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tnamePtr = nameBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tif( namePtr != NULL )\n\t\t{\n\t\tnameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );\n\t\tif( nameLen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = deviceType;\n\tcmd.strArg[ 0 ] = ( void * ) namePtr;\n\tcmd.strArgLen[ 0 ] = nameLen;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*device = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_DEVICES */\n\n/* Create an envelope */\n\n#ifdef USE_ENVELOPES\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateEnvelope( C_OUT CRYPT_ENVELOPE C_PTR envelope,\n\t\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t   C_IN CRYPT_FORMAT_TYPE formatType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_ENVELOPE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic error checking */\n\tif( !isWritePtr( envelope, sizeof( CRYPT_ENVELOPE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*envelope = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( formatType <= CRYPT_FORMAT_NONE || \\\n\t\tformatType >= CRYPT_FORMAT_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = formatType;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*envelope = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_ENVELOPES */\n\n/* Open/create a keyset */\n\n#ifdef USE_KEYSETS\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \\\nC_RET cryptKeysetOpen( C_OUT CRYPT_KEYSET C_PTR keyset,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t   C_IN C_STR name, C_IN CRYPT_KEYOPT_TYPE options )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 4, 1,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_KEYSET } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_S, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *namePtr = nameBuffer;\n#else\n\tconst char *namePtr = name;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint nameLen, status;\n\n\t/* Perform basic error checking */\n\tif( !isReadPtr( keyset, sizeof( CRYPT_KEYSET ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*keyset = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( keysetType <= CRYPT_KEYSET_NONE || keysetType >= CRYPT_KEYSET_LAST )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isReadPtr( name, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( name ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( name ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( options < CRYPT_KEYOPT_NONE || \\\n\t\toptions >= CRYPT_KEYOPT_LAST_EXTERNAL )\n\t\t{\n\t\t/* CRYPT_KEYOPT_NONE is a valid setting for this parameter */\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t name, nativeStrlen( name ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tnameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );\n\tif( nameLen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = keysetType;\n\tcmd.arg[ 3 ] = options;\n\tcmd.strArg[ 0 ] = ( void * ) namePtr;\n\tcmd.strArgLen[ 0 ] = nameLen;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*keyset = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_KEYSETS */\n\n/* Create a session */\n\n#ifdef USE_SESSIONS\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateSession( C_OUT CRYPT_SESSION C_PTR session,\n\t\t\t\t\t\t  C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t  C_IN CRYPT_SESSION_TYPE sessionType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_SESSION } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_O, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic error checking */\n\tif( !isWritePtr( session, sizeof( CRYPT_SESSION ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*session = CRYPT_ERROR;\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( sessionType <= CRYPT_SESSION_NONE || \\\n\t\tsessionType >= CRYPT_SESSION_LAST )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.arg[ 2 ] = sessionType;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*session = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_SESSIONS */\n\n/* Log on/create a user object */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nC_RET cryptLogin( C_OUT CRYPT_USER C_PTR user,\n\t\t\t\t  C_IN C_STR name, C_IN C_STR password )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT, COMMAND_FLAG_NONE, 2, 2,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_USER } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_S, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE nameBuffer[ CRYPT_MAX_TEXTSIZE + 1 ], *namePtr = nameBuffer;\n\tBYTE passwordBuffer[ CRYPT_MAX_TEXTSIZE + 1 ], *passwordPtr = passwordBuffer;\n#else\n\tconst char *namePtr = name, *passwordPtr = password;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint nameLen, passwordLen, status;\n\n\t/* Perform basic error checking */\n\tif( !isReadPtr( user, sizeof( CRYPT_USER ) ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t*user = CRYPT_ERROR;\n\tif( !isReadPtr( name, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( name ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( name ) > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtr( password, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( password ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( password ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( nameBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t name, nativeStrlen( name ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tstatus = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t password, nativeStrlen( password ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tnameLen = strStripWhitespace( &namePtr, namePtr, strlen( namePtr ) );\n\tif( nameLen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tpasswordLen = strStripWhitespace( &passwordPtr, passwordPtr, \n\t\t\t\t\t\t\t\t\t  strlen( passwordPtr ) );\n\tif( passwordLen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.strArg[ 0 ] = ( void * ) namePtr;\n\tcmd.strArgLen[ 0 ] = nameLen;\n\tcmd.strArg[ 1 ] = ( void * ) passwordPtr;\n\tcmd.strArgLen[ 1 ] = passwordLen;\n\tstatus = DISPATCH_COMMAND( cmdCreateObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*user = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Destroy object functions */\n\nC_RET cryptDestroyObject( C_IN CRYPT_HANDLE cryptHandle )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_DESTROYOBJECT, COMMAND_FLAG_NONE, 1, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = cryptHandle;\n\tstatus = DISPATCH_COMMAND( cmdDestroyObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_RET cryptDestroyCert( C_IN CRYPT_CERTIFICATE certificate )\n\t{\n\treturn( cryptDestroyObject( certificate ) );\n\t}\nC_RET cryptDestroyContext( C_IN CRYPT_CONTEXT cryptContext )\n\t{\n\treturn( cryptDestroyObject( cryptContext ) );\n\t}\nC_RET cryptDestroyEnvelope( C_IN CRYPT_ENVELOPE cryptEnvelope )\n\t{\n\treturn( cryptDestroyObject( cryptEnvelope ) );\n\t}\nC_RET cryptDeviceClose( C_IN CRYPT_DEVICE device )\n\t{\n\treturn( cryptDestroyObject( device ) );\n\t}\nC_RET cryptKeysetClose( C_IN CRYPT_KEYSET keyset )\n\t{\n\treturn( cryptDestroyObject( keyset ) );\n\t}\nC_RET cryptDestroySession( C_IN CRYPT_SESSION session )\n\t{\n\treturn( cryptDestroyObject( session ) );\n\t}\nC_RET cryptLogout( C_IN CRYPT_USER user )\n\t{\n\treturn( cryptDestroyObject( user ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Manipulation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get an attribute */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptGetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t C_OUT int C_PTR value )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETATTRIBUTE, COMMAND_FLAG_NONE, 2, 0,\n\t\t  { DEFAULTUSER_OBJECT_HANDLE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( attributeType <= CRYPT_ATTRIBUTE_NONE || attributeType >= CRYPT_ATTRIBUTE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isWritePtr( value, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t*value = CRYPT_ERROR;\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptHandle != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptHandle;\n\tcmd.arg[ 1 ] = attributeType;\n\tstatus = DISPATCH_COMMAND( cmdGetAttribute, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* At this point we run into a problem with the representation of \n\t\t   BOOLEAN values, which are encoded in a fault-resistant format\n\t\t   internally but represented as a straight 0 or 1 externally.  We\n\t\t   don't have access to type information here so we can't tell \n\t\t   whether the value being returned is a BOOLEAN or not, and \n\t\t   hardcoding in the attributes that correspond to BOOLEAN values is\n\t\t   impractical because there are over 80 of them.  \n\t\t   \n\t\t   The best that we can do is build on the knowledge that the value \n\t\t   for TRUE is highly unlikely to ever occur as a normal value (it's \n\t\t   not a valid cryptlib ID, length, or anything else) and convert it \n\t\t   to the value 1 (TRUE_ALT) when we see it */\n\t\tif( cmd.arg[ 0 ] == TRUE )\n\t\t\t*value = TRUE_ALT;\n\t\telse\n\t\t\t*value = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 4 ) ) \\\nC_RET cryptGetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t   C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t   C_OUT_OPT void C_PTR value,\n\t\t\t\t\t\t\t   C_OUT int C_PTR valueLength )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETATTRIBUTE, COMMAND_FLAG_NONE, 3, RETURN_VALUE( 1 ),\n\t\t  { DEFAULTUSER_OBJECT_HANDLE, 0, TRUE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_S, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( attributeType <= CRYPT_ATTRIBUTE_NONE || \\\n\t\tattributeType >= CRYPT_ATTRIBUTE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isWritePtr( valueLength, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\t*valueLength = CRYPT_ERROR;\n\tif( value != NULL )\n\t\t*( ( BYTE * ) value ) = '\\0';\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( value == NULL )\n\t\t{\n\t\tcmd.flags = COMMAND_FLAG_RET_LENGTH;\n\t\tcmd.noStrArgs = 0;\n\t\t}\n\tif( cryptHandle != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptHandle;\n\tcmd.arg[ 1 ] = attributeType;\t/* arg[ 2 ] = TRUE from template */\n\tcmd.strArg[ 0 ] = value;\n\tcmd.strArgLen[ 0 ] = RETURN_VALUE( MAX_ATTRIBUTE_SIZE );\n\tstatus = DISPATCH_COMMAND( cmdGetAttribute, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*valueLength = ( value == NULL ) ? cmd.arg[ 0 ] : cmd.strArgLen[ 0 ];\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\t\tif( value != NULL && *valueLength > 0 && \\\n\t\t\tneedsTranslation( attributeType ) )\n\t\t\t{\n\t\t\tBYTE buffer[ MAX_ATTRIBUTE_SIZE ];\n\n\t\t\tif( *valueLength >= MAX_ATTRIBUTE_SIZE )\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\tmemcpy( buffer, value, *valueLength );\n\t\t\tcryptlibToNativeString( value, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\tbuffer, *valueLength );\n  #ifdef UNICODE_CHARS\n\t\t\t*valueLength *= sizeof( wchar_t );\n  #endif /* UNICODE_CHARS */\n\t\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Set an attribute */\n\nC_RET cryptSetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t C_IN int value )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_SETATTRIBUTE, COMMAND_FLAG_NONE, 3, 0,\n\t\t  { DEFAULTUSER_OBJECT_HANDLE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( attributeType <= CRYPT_ATTRIBUTE_NONE || \\\n\t\tattributeType >= CRYPT_ATTRIBUTE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptHandle != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptHandle;\n\tcmd.arg[ 1 ] = attributeType;\n\tcmd.arg[ 2 ] = value;\n\tstatus = DISPATCH_COMMAND( cmdSetAttribute, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_RET cryptSetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t   C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t   C_IN void C_PTR value, C_IN int valueLength )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_SETATTRIBUTE, COMMAND_FLAG_NONE, 2, 1,\n\t\t  { DEFAULTUSER_OBJECT_HANDLE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_S, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE valueBuffer[ MAX_ATTRIBUTE_SIZE ];\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint length = valueLength, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( attributeType <= CRYPT_ATTRIBUTE_NONE || \\\n\t\tattributeType >= CRYPT_ATTRIBUTE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtr( value, 1 ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( attributeType == CRYPT_CTXINFO_KEY_COMPONENTS )\n\t\t{\n\t\t/* Public key components constitute a special case since the\n\t\t   composite structures used are quite large */\n\t\tif( valueLength != sizeof( CRYPT_PKCINFO_RSA ) && \\\n\t\t\tvalueLength != sizeof( CRYPT_PKCINFO_DLP ) && \\\n\t\t\tvalueLength != sizeof( CRYPT_PKCINFO_ECC ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\telse\n\t\t{\n\t\tif( valueLength < 1 || valueLength >= MAX_ATTRIBUTE_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\tif( !isReadPtrDynamic( value, valueLength ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tif( needsTranslation( attributeType ) )\n\t\t{\n\t\tstatus = nativeToCryptlibString( valueBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t value, valueLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\tvalue = valueBuffer;\n  #ifdef UNICODE_CHARS\n\t\tlength = status;\n  #endif /* UNICODE_CHARS */\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n#if defined( __WINDOWS__ ) && defined( __WIN32__ ) && !defined( __WIN64__ )\n\t/* In Vista/VS 2008 Microsoft switched the Win32 time_t from 32 to 64 \n\t   bits, a theoretically commendable move but one that makes it \n\t   impossible to create a single DLL that works with code compiled with \n\t   different versions of Visual Studio or with different languages (it's\n\t   not a problem with Win64 since the time_t there is always 64 bits).  \n\t   To get around the Win32 issue we try and detect a mismatch of time_t \n\t   types and transparently convert them.  We first check that it's \n\t   within the range where it could be a time attribute to avoid having \n\t   to iterate through the whole list on every attribute-set operation, \n\t   and only then check for an exact match */\n\tif( attributeType >= CRYPT_CERTINFO_VALIDFROM && \\\n\t\tattributeType <= CRYPT_CERTINFO_CMS_MLEXP_TIME )\n\t\t{\n\t\tif( ( attributeType == CRYPT_CERTINFO_VALIDFROM || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_VALIDTO || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_THISUPDATE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_NEXTUPDATE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_REVOCATIONDATE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_OCSP_ARCHIVECUTOFF || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_SIGG_DATEOFCERTGEN || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_PRIVATEKEY_NOTAFTER || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_INVALIDITYDATE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_CMS_SIGNINGTIME || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_CMS_MLEXP_TIME ) && \\\n\t\t\tlength != sizeof( time_t ) )\n\t\t\t{\n\t\t\tvoid *timeValuePtr;\n\t\t\ttime_t time64, time32;\n\n\t\t\t/* It looks like we have a time_t size mismatch, try and correct\n\t\t\t   it */\n\t\t\tif( length != 4 && length != 8 )\n\t\t\t\t{\n\t\t\t\t/* A time_t can only be 32 or 64 bits */\n\t\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t\t\t}\n\t\t\tif( length == 4 )\n\t\t\t\t{\n\t\t\t\t/* time_t is 64 bits and we've been given 32, convert to a\n\t\t\t\t   64-bit value */\n\t\t\t\ttime64 = *( ( unsigned int * ) value );\n\t\t\t\ttimeValuePtr = &time64;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* time_t is 32 bits and we've been given 64, convert to a\n\t\t\t\t   32-bit value */\n\t\t\t\tconst __int64 timeValue = *( ( __int64 * ) value );\n\t\t\t\tif( timeValue < MIN_TIME_VALUE || timeValue >= ULONG_MAX )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t\t\ttime32 = *( ( time_t * ) value );\n\t\t\t\ttimeValuePtr = &time32;\n\t\t\t\t}\n\t\t\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\t\t\tcmd.arg[ 0 ] = cryptHandle;\n\t\t\tcmd.arg[ 1 ] = attributeType;\n\t\t\tcmd.strArg[ 0 ] = ( void * ) timeValuePtr;\n\t\t\tcmd.strArgLen[ 0 ] = sizeof( time_t );\n\t\t\tstatus = DISPATCH_COMMAND( cmdSetAttribute, cmd );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t\t\t  status ) );\n\t\t\t}\n\t\t}\n#endif /* Win32 */\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptHandle != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptHandle;\n\tcmd.arg[ 1 ] = attributeType;\n\tcmd.strArg[ 0 ] = ( void * ) value;\n\tcmd.strArgLen[ 0 ] = length;\n\tstatus = DISPATCH_COMMAND( cmdSetAttribute, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Delete an attribute */\n\nC_RET cryptDeleteAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\tC_IN CRYPT_ATTRIBUTE_TYPE attributeType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_DELETEATTRIBUTE, COMMAND_FLAG_NONE, 2, 0,\n\t\t  { DEFAULTUSER_OBJECT_HANDLE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptHandle ) && cryptHandle != CRYPT_UNUSED )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( attributeType <= CRYPT_ATTRIBUTE_NONE || \\\n\t\tattributeType >= CRYPT_ATTRIBUTE_LAST )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptHandle != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptHandle;\n\tcmd.arg[ 1 ] = attributeType;\n\tstatus = DISPATCH_COMMAND( cmdDeleteAttribute, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEncryption Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a key into an encryption context */\n\nC_CHECK_RETVAL \\\nC_RET cryptGenerateKey( C_IN CRYPT_CONTEXT cryptContext )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GENKEY, COMMAND_FLAG_NONE, 1, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptContext ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = cryptContext;\n\tstatus = DISPATCH_COMMAND( cmdGenKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Encrypt/decrypt data */\n\nC_RET cryptEncrypt( C_IN CRYPT_CONTEXT cryptContext,\n\t\t\t\t\tC_INOUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_ENCRYPT, COMMAND_FLAG_NONE, 1, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_S, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking.  In theory we should also\n\t   check for writability since the encryption does an in-place update,\n\t   however when we're hashing data it's valid for the data to be read-\n\t   only so we only check for readability.  In addition when hashing we\n\t   could be doing a hash-wrapup call so we allow a zero length and only\n\t   check the buffer if the length is nonzero */\n\tif( !isHandleRangeValid( cryptContext ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isIntegerRange( length ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( length > 0 && !isReadPtrDynamic( buffer, length ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = cryptContext;\n\tcmd.strArg[ 0 ] = ( length == 0 ) ? \"\" : buffer;\n\tcmd.strArgLen[ 0 ] = length;\n\tstatus = DISPATCH_COMMAND( cmdEncrypt, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_RET cryptDecrypt( C_IN CRYPT_CONTEXT cryptContext,\n\t\t\t\t\tC_INOUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_DECRYPT, COMMAND_FLAG_NONE, 1, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_S, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( cryptContext ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isIntegerRange( length ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isWritePtrDynamic( buffer, length ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = cryptContext;\n\tcmd.strArg[ 0 ] = buffer;\n\tcmd.strArgLen[ 0 ] = length;\n\tstatus = DISPATCH_COMMAND( cmdDecrypt, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCertificate Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTIFICATES\n\n/* Sign/sig.check a certificate object.  The possibilities for signing are \n   as follows:\n\n\t\t\t\t\t\tSigner\n\tType  |\t\tCert\t\t\t\tChain\n\t------+--------------------+---------------\n\tCert  | Cert\t\t\t   | Cert\n\t\t  |\t\t\t\t\t   |\n\tChain | Chain, length = 2  | Chain, length = n+1\n\n   For sig.checking the certificate object is checked against an issuing \n   key/certificate or against a CRL, either as a raw CRL or a keyset contain \n   revocation information */\n\nC_CHECK_RETVAL \\\nC_RET cryptSignCert( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t C_IN CRYPT_CONTEXT signContext )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CERTSIGN, COMMAND_FLAG_NONE, 2, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isHandleRangeValid( signContext ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = certificate;\n\tcmd.arg[ 1 ] = signContext;\n\tstatus = DISPATCH_COMMAND( cmdCertSign, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL \\\nC_RET cryptCheckCert( C_IN CRYPT_HANDLE certificate,\n\t\t\t\t\t  C_IN CRYPT_HANDLE sigCheckKey )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CERTCHECK, COMMAND_FLAG_NONE, 2, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_V, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isHandleRangeValid( sigCheckKey ) && \\\n\t\t( sigCheckKey != CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = certificate;\n\tcmd.arg[ 1 ] = sigCheckKey;\n\tstatus = DISPATCH_COMMAND( cmdCertCheck, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Import/export a certificate, CRL, certification request, or certificate \n   chain.  In the export case this just copies the internal encoded object \n   to an external buffer.  For certificate/certificate chain export the \n   possibilities are as follows:\n\n\t\t\t\t\t\tExport\n\tType  |\t\tCert\t\t\t\tChain\n\t------+--------------------+---------------\n\tCert  | Cert\t\t\t   | Cert as chain\n\t\t  |\t\t\t\t\t   |\n\tChain | Currently selected | Chain\n\t\t  | cert in chain\t   | */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \\\nC_RET cryptImportCert( C_IN void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_OUT CRYPT_CERTIFICATE C_PTR certificate )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CREATEOBJECT_INDIRECT, COMMAND_FLAG_NONE, 2, 1,\n\t\t  { SYSTEM_OBJECT_HANDLE, OBJECT_TYPE_CERTIFICATE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_S, ARG_N, ARG_N, ARG_O, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( certObjectLength < MIN_CERTSIZE || \\\n\t\tcertObjectLength >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtrDynamic( certObject, certObjectLength ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( cryptUser != CRYPT_UNUSED && !isHandleRangeValid( cryptUser ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isWritePtr( certificate, sizeof( CRYPT_CERTIFICATE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\t*certificate = CRYPT_ERROR;\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptUser != CRYPT_UNUSED )\n\t\tcmd.arg[ 0 ] = cryptUser;\n\tcmd.strArg[ 0 ] = ( void * ) certObject;\n\tcmd.strArgLen[ 0 ] = certObjectLength;\n\tstatus = DISPATCH_COMMAND( cmdCreateObjectIndirect, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*certificate = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL \\\nC_RET cryptExportCert( C_OUT_OPT void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectMaxLength,\n\t\t\t\t\t   C_OUT int C_PTR certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_CERTFORMAT_TYPE certFormatType,\n\t\t\t\t\t   C_IN CRYPT_HANDLE certificate )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_EXPORTOBJECT, COMMAND_FLAG_NONE, 2, RETURN_VALUE( 1 ) };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_S, ARG_D, ARG_N, ARG_V, ARG_O, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( certObject != NULL )\n\t\t{\n\t\tif( certObjectMaxLength < MIN_CERTSIZE || \\\n\t\t\tcertObjectMaxLength >= MAX_BUFFER_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\tif( !isWritePtrDynamic( certObject, certObjectMaxLength ) )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\tmemset( certObject, 0, MIN_CERTSIZE );\n\t\t}\n\tif( !isWritePtr( certObjectLength, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t*certObjectLength = CRYPT_ERROR;\n\tif( certFormatType <= CRYPT_CERTFORMAT_NONE || \\\n\t\tcertFormatType >= CRYPT_CERTFORMAT_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( certObject == NULL )\n\t\t{\n\t\tcmd.flags = COMMAND_FLAG_RET_LENGTH;\n\t\tcmd.noStrArgs = 0;\n\t\t}\n\tcmd.arg[ 0 ] = certificate;\n\tcmd.arg[ 1 ] = certFormatType;\n\tcmd.strArg[ 0 ] = certObject;\n\tcmd.strArgLen[ 0 ] = certObjectMaxLength;\n\tstatus = DISPATCH_COMMAND( cmdExportObject, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*certObjectLength = ( certObject == NULL ) ? \\\n\t\t\t\t\t\t\tcmd.arg[ 0 ] : cmd.strArgLen[ 0 ];\n#if defined( EBCDIC_CHARS )\n\t\tif( ( certFormatType == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \\\n\t\t\t  certFormatType == CRYPT_CERTFORMAT_TEXT_CERTCHAIN || \\\n\t\t\t  certFormatType == CRYPT_CERTFORMAT_XML_CERTIFICATE || \\\n\t\t\t  certFormatType == CRYPT_CERTFORMAT_XML_CERTCHAIN ) && \\\n\t\t\tcertObject != NULL )\n\t\t\t{\n\t\t\t/* It's text-encoded certificate data, convert it to the native \n\t\t\t   text format before we return */\n\t\t\tcryptlibToNativeString( certObject, certObjectMaxLength,\n\t\t\t\t\t\t\t\t\tcertObject, *certObjectLength );\n\t\t\t}\n#endif /* EBCDIC_CHARS */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n#ifdef USE_KEYSETS\n\n/* CA management functions */\n\nC_CHECK_RETVAL \\\nC_RET cryptCAAddItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_CERTIFICATE certificate )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_SETKEY, COMMAND_FLAG_NONE, 3, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = certificate;\n\tcmd.arg[ 2 ] = TRUE;\n\tstatus = DISPATCH_COMMAND( cmdSetKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptCAGetItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t  C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN_OPT C_STR keyID )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_D, ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = NULL;\n#else\n\tconst char *keyIDPtr = keyID;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tBOOLEAN isCert = FALSE;\n\tint keyIDlen = 0, status;\n\n\t/* Perform basic client-side error checking.  Because of keyset queries \n\t   we have to accept CRYPT_KEYID_NONE and a null keyID as well as \n\t   obviously valid key IDs */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( certificate, sizeof( CRYPT_HANDLE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\t*certificate = CRYPT_ERROR;\n\tif( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertType == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\tcertType == CRYPT_CERTTYPE_CERTCHAIN )\n\t\tisCert = TRUE;\n\telse\n\t\t{\n\t\tif( certType != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\t\tcertType != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\t\tcertType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\t\tcertType != CRYPT_CERTTYPE_PKIUSER )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t}\n\tif( keyIDtype < CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( keyIDtype == CRYPT_KEYID_NONE )\n\t\t{\n\t\tif( keyID != NULL )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\telse\n\t\t{\n\t\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tif( keyID != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tkeyIDPtr = keyIDBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tif( keyIDPtr != NULL )\n\t\t{\n\t\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\t\tif( keyIDlen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tif( isCert )\n\t\t{\n\t\t/* If we're being asked for a standard certificate, the caller \n\t\t   should really be using cryptGetPublicKey(), however for \n\t\t   orthogonality we convert the request into a standard public-key \n\t\t   read.  Note that this leads to some ambiguity since we can't \n\t\t   explicitly specify what we want returned for a certificate read \n\t\t   (for example we could get a chain if we ask for a single \n\t\t   certificate or a single certificate if we ask for a chain, \n\t\t   depending on what's there), but it's less confusing than refusing \n\t\t   any request to read a certificate */\n\t\tcmd.arg[ 1 ] = KEYMGMT_ITEM_PUBLICKEY;\n\t\t}\n\telse\n\t\t{\n\t\tcmd.arg[ 1 ] = ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \\\n\t\t\t\t\t   KEYMGMT_ITEM_PKIUSER : KEYMGMT_ITEM_REQUEST;\n\t\t}\n\tcmd.arg[ 2 ] = keyIDtype;\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen ;\n\tstatus = DISPATCH_COMMAND( cmdGetKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*certificate = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_RET cryptCADeleteItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN C_STR keyID )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_DELETEKEY, COMMAND_FLAG_NONE, 3, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;\n#else\n\tconst char *keyIDPtr = keyID;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint keyIDlen, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( certType != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\tcertType != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\tcertType != CRYPT_CERTTYPE_PKIUSER )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( keyIDtype <= CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\tif( keyIDlen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = keyIDtype;\n\tif( certType == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\t/* Allow a delete of a certificate for the same reason as given above \n\t\t   for cryptCAGetItem() */\n\t\tcmd.noArgs = 2;\n\t\t}\n\telse\n\t\t{\n\t\tcmd.arg[ 2 ] = ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \\\n\t\t\t\t\t   CRYPT_CERTTYPE_PKIUSER : CRYPT_CERTTYPE_REQUEST_CERT;\n\t\t}\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen;\n\tstatus = DISPATCH_COMMAND( cmdDeleteKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL \\\nC_RET cryptCACertManagement( C_OUT_OPT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t\t\t C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT caKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certRequest )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_CERTMGMT, COMMAND_FLAG_NONE, 4, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_D, ARG_V, ARG_O, ARG_N, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( certificate != NULL )\n\t\t{\n\t\tif( !isWritePtr( certificate, sizeof( CRYPT_HANDLE ) ) )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t*certificate = CRYPT_ERROR;\n\t\t}\n\tif( action < CRYPT_CERTACTION_FIRST_USER || \\\n\t\taction > CRYPT_CERTACTION_LAST_USER )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isHandleRangeValid( caKey ) && \\\n\t\t!( ( action == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\t\t action == CRYPT_CERTACTION_CLEANUP ) && caKey == CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( !isHandleRangeValid( certRequest ) && \\\n\t\t!( ( action == CRYPT_CERTACTION_ISSUE_CRL || \\\n\t\t\t action == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\t\t action == CRYPT_CERTACTION_CLEANUP ) && \\\n\t\t   certRequest == CRYPT_UNUSED ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( certificate == NULL )\n\t\tcmd.flags = COMMAND_FLAG_RET_NONE;\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = action;\n\tcmd.arg[ 2 ] = caKey;\n\tcmd.arg[ 3 ] = certRequest;\n\tstatus = DISPATCH_COMMAND( cmdCertMgmt, cmd );\n\tif( cryptStatusOK( status ) && certificate != NULL )\n\t\t{\n\t\t*certificate = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_KEYSETS */\n#endif /* USE_CERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope/Session Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_ENVELOPES ) || defined( USE_SESSIONS )\n\n/* Push data into an envelope/session object */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptPushData( C_IN CRYPT_HANDLE envelope, C_IN void C_PTR buffer,\n\t\t\t\t\t C_IN int length, C_OUT int C_PTR bytesCopied )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_PUSHDATA, COMMAND_FLAG_NONE, 1, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_S, ARG_N, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint dummy, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( envelope ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isReadPtrDynamic( buffer, length ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( length <= 0 || length >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( bytesCopied == NULL )\n\t\t{\n\t\t/* If the user isn't interested in the bytes copied count, point at a\n\t\t   dummy location */\n\t\tbytesCopied = &dummy;\n\t\t}\n\t*bytesCopied = 0;\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = envelope;\n\tcmd.strArg[ 0 ] = ( void * ) buffer;\n\tcmd.strArgLen[ 0 ] = length;\n\tstatus = DISPATCH_COMMAND( cmdPushData, cmd );\n\t*bytesCopied = cmd.arg[ 0 ];\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Pop data from an envelope/session object */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptPopData( C_IN CRYPT_ENVELOPE envelope, C_OUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length, C_OUT int C_PTR bytesCopied )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_POPDATA, COMMAND_FLAG_NONE, 2, RETURN_VALUE( 1 ) };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_S, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( envelope ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtrDynamic( buffer, length ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( length <= 0 || length >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tmemset( buffer, 0, min( length, 16 ) );\n\tif( !isWritePtr( bytesCopied, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\t*bytesCopied = 0;\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = envelope;\n\tcmd.arg[ 1 ] = length;\n\tcmd.strArg[ 0 ] = ( void * ) buffer;\n\tcmd.strArgLen[ 0 ] = RETURN_VALUE( length );\n\tstatus = DISPATCH_COMMAND( cmdPopData, cmd );\n\t*bytesCopied = cmd.strArgLen[ 0 ];\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Flush data through an envelope/session object */\n\nC_CHECK_RETVAL \\\nC_RET cryptFlushData( C_IN CRYPT_HANDLE envelope )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_FLUSHDATA, COMMAND_FLAG_NONE, 1, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( envelope ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = envelope;\n\tstatus = DISPATCH_COMMAND( cmdFlushData, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_ENVELOPES || USE_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyset Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_KEYSETS\n\n/* Retrieve a key from a keyset or equivalent object */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptGetPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_OUT CRYPT_HANDLE C_PTR cryptKey,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN_OPT C_STR keyID )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_D, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = NULL;\n#else\n\tconst char *keyIDPtr = keyID;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint keyIDlen = 0, status;\n\n\t/* Perform basic client-side error checking.  Because of keyset queries\n\t   we have to accept CRYPT_KEYID_NONE and a null keyID as well as\n\t   obviously valid key IDs */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( cryptKey, sizeof( CRYPT_HANDLE ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\t*cryptKey = CRYPT_ERROR;\n\tif( keyIDtype < CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( keyIDtype == CRYPT_KEYID_NONE )\n\t\t{\n\t\tif( keyID != NULL )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\telse\n\t\t{\n\t\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tif( keyID != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tkeyIDPtr = keyIDBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tif( keyIDPtr != NULL )\n\t\t{\n\t\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\t\tif( keyIDlen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = KEYMGMT_ITEM_PUBLICKEY;\n\tcmd.arg[ 2 ] = keyIDtype;\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen;\n\tstatus = DISPATCH_COMMAND( cmdGetKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*cryptKey = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptGetPrivateKey( C_IN CRYPT_HANDLE keyset,\n\t\t\t\t\t\t  C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t  C_IN C_STR keyID, C_IN_OPT C_STR password )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 2 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_D, ARG_N, ARG_S, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;\n\tBYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;\n#else\n\tconst char *keyIDPtr = keyID, *passwordPtr = password;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint keyIDlen, passwordLen = 0, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( cryptContext, sizeof( CRYPT_CONTEXT ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\t*cryptContext = CRYPT_ERROR;\n\tif( keyIDtype <= CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( password != NULL && \\\n\t\t( !isReadPtr( password, MIN_NAME_LENGTH ) || \\\n\t\t  strParamLen( password ) < MIN_NAME_LENGTH || \\\n\t\t  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( password != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t password, nativeStrlen( password ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\tpasswordPtr = passwordBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\tif( keyIDlen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( passwordPtr != NULL )\n\t\t{\n\t\tpasswordLen = strStripWhitespace( &passwordPtr, passwordPtr, \n\t\t\t\t\t\t\t\t\t\t  strlen( passwordPtr ) );\n\t\tif( passwordLen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = KEYMGMT_ITEM_PRIVATEKEY;\n\tcmd.arg[ 2 ] = keyIDtype;\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen;\n\tcmd.strArg[ 1 ] = ( void * ) passwordPtr;\n\tcmd.strArgLen[ 1 ] = passwordLen;\n\tstatus = DISPATCH_COMMAND( cmdGetKey, cmd );\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tzeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*cryptContext = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptGetKey( C_IN CRYPT_HANDLE keyset,\n\t\t\t\t   C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t   C_IN CRYPT_KEYID_TYPE keyIDtype, C_IN C_STR keyID, \n\t\t\t\t   C_IN_OPT C_STR password )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_GETKEY, COMMAND_FLAG_NONE, 3, 2 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_D, ARG_N, ARG_S, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;\n\tBYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;\n#else\n\tconst char *keyIDPtr = keyID, *passwordPtr = password;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint keyIDlen, passwordLen = 0, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( cryptContext, sizeof( CRYPT_CONTEXT ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\t*cryptContext = CRYPT_ERROR;\n\tif( keyIDtype <= CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( password != NULL && \\\n\t\t( !isReadPtr( password, MIN_NAME_LENGTH ) || \\\n\t\t  strParamLen( password ) < MIN_NAME_LENGTH || \\\n\t\t  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( password != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t password, nativeStrlen( password ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\tpasswordPtr = passwordBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\tif( keyIDlen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( passwordPtr != NULL )\n\t\t{\n\t\tpasswordLen = strStripWhitespace( &passwordPtr, passwordPtr, \n\t\t\t\t\t\t\t\t\t\t  strlen( passwordPtr ) );\n\t\tif( passwordLen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = KEYMGMT_ITEM_SECRETKEY;\n\tcmd.arg[ 2 ] = keyIDtype;\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen;\n\tcmd.strArg[ 1 ] = ( void * ) passwordPtr;\n\tcmd.strArgLen[ 1 ] = passwordLen;\n\tstatus = DISPATCH_COMMAND( cmdGetKey, cmd );\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tzeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*cryptContext = cmd.arg[ 0 ];\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Add a key from a keyset or equivalent object */\n\nC_CHECK_RETVAL \\\nC_RET cryptAddPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certificate )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_SETKEY, COMMAND_FLAG_NONE, 2, 0 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = certificate;\n\tstatus = DISPATCH_COMMAND( cmdSetKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptAddPrivateKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t  C_IN CRYPT_HANDLE cryptKey,\n\t\t\t\t\t\t  C_IN C_STR password )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_SETKEY, COMMAND_FLAG_NONE, 2, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE passwordBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *passwordPtr = NULL;\n#else\n\tconst char *passwordPtr = password;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint passwordLen = 0, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isHandleRangeValid( cryptKey ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( password != NULL && \\\n\t\t( !isReadPtr( password, MIN_NAME_LENGTH ) || \\\n\t\t  isBadPassword( password ) || \\\n\t\t  strParamLen( password ) < MIN_NAME_LENGTH || \\\n\t\t  strParamLen( password ) >= MAX_ATTRIBUTE_SIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tif( password != NULL )\n\t\t{\n\t\tstatus = nativeToCryptlibString( passwordBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t\t password, nativeStrlen( password ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\tpasswordPtr = passwordBuffer;\n\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tif( passwordPtr != NULL )\n\t\t{\n\t\tpasswordLen = strStripWhitespace( &passwordPtr, passwordPtr, \n\t\t\t\t\t\t\t\t\t\t  strlen( passwordPtr ) );\n\t\tif( passwordLen <= 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = cryptKey;\n\tcmd.strArg[ 0 ] = ( void * ) passwordPtr;\n\tcmd.strArgLen[ 0 ] = passwordLen;\n\tstatus = DISPATCH_COMMAND( cmdSetKey, cmd );\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tzeroise( passwordBuffer, MAX_ATTRIBUTE_SIZE + 1 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n/* Delete a key from a keyset or equivalent object */\n\nC_RET cryptDeleteKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN C_STR keyID )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_DELETEKEY, COMMAND_FLAG_NONE, 2, 1 };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tBYTE keyIDBuffer[ MAX_ATTRIBUTE_SIZE + 1 ], *keyIDPtr = keyIDBuffer;\n#else\n\tconst char *keyIDPtr = keyID;\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\tint keyIDlen, status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( keyset ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( keyIDtype <= CRYPT_KEYID_NONE || \\\n\t\tkeyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtr( keyID, MIN_NAME_LENGTH ) || \\\n\t\tstrParamLen( keyID ) < MIN_NAME_LENGTH || \\\n\t\tstrParamLen( keyID ) >= MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\tstatus = nativeToCryptlibString( keyIDBuffer, MAX_ATTRIBUTE_SIZE,\n\t\t\t\t\t\t\t\t\t keyID, nativeStrlen( keyID ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\n\t/* Check and clean up any string parameters if required */\n\tkeyIDlen = strStripWhitespace( &keyIDPtr, keyIDPtr, strlen( keyIDPtr ) );\n\tif( keyIDlen <= 0 )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = keyset;\n\tcmd.arg[ 1 ] = keyIDtype;\n\tcmd.strArg[ 0 ] = ( void * ) keyIDPtr;\n\tcmd.strArgLen[ 0 ] = keyIDlen;\n\tstatus = DISPATCH_COMMAND( cmdDeleteKey, cmd );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_KEYSETS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUser Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tMisc Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* cryptlib/object query functions */\n\nC_CHECK_RETVAL \\\nC_RET cryptQueryCapability( C_IN CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\tC_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_QUERYCAPABILITY, COMMAND_FLAG_NONE, 2, RETURN_VALUE( 1 ),\n\t\t  { SYSTEM_OBJECT_HANDLE } };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( cryptAlgo < CRYPT_ALGO_NONE || \\\n\t\tcryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( cryptQueryInfo != NULL )\n\t\t{\n\t\tif( !isWritePtr( cryptQueryInfo, sizeof( CRYPT_QUERY_INFO ) ) )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\tmemset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );\n\t\t}\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Dispatch the command.  We need to map parameter errors down one\n\t   because the system object is invisible to the caller */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptQueryInfo == NULL )\n\t\t{\n\t\tcmd.flags = COMMAND_FLAG_RET_LENGTH;\n\t\tcmd.noStrArgs = 0;\n\t\t}\n\tcmd.arg[ 1 ] = cryptAlgo;\n\tcmd.strArg[ 0 ] = cryptQueryInfo;\n\tcmd.strArgLen[ 0 ] = RETURN_VALUE( MAX_ATTRIBUTE_SIZE );\n\tstatus = DISPATCH_COMMAND( cmdQueryCapability, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\t\tif( cryptQueryInfo != NULL )\n\t\t\t{\n\t\t\tBYTE buffer[ MAX_ATTRIBUTE_SIZE ];\n\t\t\tconst int algoNameLength = \\\n\t\t\t\t\t\tstrlen( ( char * ) cryptQueryInfo->algoName ) + 1;\n\n\t\t\tmemcpy( buffer, cryptQueryInfo->algoName, algoNameLength );\n\t\t\tcryptlibToNativeString( cryptQueryInfo->algoName,\n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, buffer, \n\t\t\t\t\t\t\t\t\talgoNameLength );\n\t\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n\n#ifdef USE_DEVICES\n\nC_CHECK_RETVAL \\\nC_RET cryptDeviceQueryCapability( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t\t  C_IN CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ COMMAND_QUERYCAPABILITY, COMMAND_FLAG_NONE, 2, RETURN_VALUE( 1 ) };\n\tstatic const ERRORMAP errorMap[] = \\\n\t\t{ ARG_O, ARG_N, ARG_N, ARG_S, ARG_LAST, ARG_LAST };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\t/* Perform basic client-side error checking */\n\tif( !isHandleRangeValid( device ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( cryptAlgo < CRYPT_ALGO_NONE || \\\n\t\tcryptAlgo >= CRYPT_ALGO_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( cryptQueryInfo != NULL )\n\t\t{\n\t\tif( !isWritePtr( cryptQueryInfo, sizeof( CRYPT_QUERY_INFO ) ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tmemset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );\n\t\t}\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tif( cryptQueryInfo == NULL )\n\t\t{\n\t\tcmd.flags = COMMAND_FLAG_RET_LENGTH;\n\t\tcmd.noStrArgs = 0;\n\t\t}\n\tcmd.arg[ 0 ] = device;\n\tcmd.arg[ 1 ] = cryptAlgo;\n\tcmd.strArg[ 0 ] = cryptQueryInfo;\n\tcmd.strArgLen[ 0 ] = RETURN_VALUE( MAX_ATTRIBUTE_SIZE );\n\tstatus = DISPATCH_COMMAND( cmdQueryCapability, cmd );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#if defined( EBCDIC_CHARS ) || defined( UNICODE_CHARS )\n\t\tif( cryptQueryInfo != NULL )\n\t\t\t{\n\t\t\tBYTE buffer[ MAX_ATTRIBUTE_SIZE ];\n\t\t\tconst int algoNameLength = \\\n\t\t\t\t\t\tstrlen( ( char * ) cryptQueryInfo->algoName ) + 1;\n\n\t\t\tmemcpy( buffer, cryptQueryInfo->algoName, algoNameLength );\n\t\t\tcryptlibToNativeString( cryptQueryInfo->algoName,\n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, buffer, \n\t\t\t\t\t\t\t\t\talgoNameLength );\n\t\t\t}\n#endif /* EBCDIC_CHARS || UNICODE_CHARS */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( mapError( errorMap, FAILSAFE_ARRAYSIZE( errorMap, ERRORMAP ), \n\t\t\t\t\t  status ) );\n\t}\n#endif /* USE_DEVICES */\n\n/* Add random data to the random pool.  This should eventually be replaced\n   by some sort of device control mechanism, the problem with doing this is\n   that it's handled by the system device which isn't visible to the user */\n\nC_RET cryptAddRandom( C_IN void C_PTR randomData, C_IN int randomDataLength )\n\t{\n\t/* Perform basic error checking */\n\tif( randomData == NULL )\n\t\t{\n\t\tif( randomDataLength != CRYPT_RANDOM_FASTPOLL && \\\n\t\t\trandomDataLength != CRYPT_RANDOM_SLOWPOLL )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( randomDataLength <= 0 || randomDataLength >= MAX_BUFFER_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\tif( !isReadPtrDynamic( randomData, randomDataLength ) )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t}\n\n\t/* Make sure that the user has remembered to initialise cryptlib */\n\tif( !initCalled )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* If we're adding data to the pool, add it now and exit.  Since the data\n\t   is of unknown provenance (and empirical evidence indicates that it\n\t   won't be very random) we give it a weight of zero for estimation\n\t   purposes */\n\tif( randomData != NULL )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n#if !defined( NDEBUG ) && ( defined( __WINDOWS__ ) || defined( CONFIG_FUZZ ) )\nif( randomDataLength == 5 && !memcmp( randomData, \"xyzzy\", 5 ) )\n{\t/* For debugging tests only */\nBYTE buffer[ 256 + 8 ];\nint kludge = 100, status;\n\nmemset( buffer, '*', 256 );\nsetMessageData( &msgData, buffer, 256 );\nstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\nif( cryptStatusOK( status ) )\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &kludge, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\nreturn( status );\n}\n#endif /* Windows debug */\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) randomData, \n\t\t\t\t\t\trandomDataLength );\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY ) );\n\t\t}\n\n\t/* Perform either a fast or slow poll for random system data */\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t ( randomDataLength == CRYPT_RANDOM_SLOWPOLL ) ? \\\n\t\t\t\t\t\t\t\tMESSAGE_VALUE_TRUE : MESSAGE_VALUE_FALSE,\n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_RANDOM_POLL ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tStubs/Replacements for Disabled Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If certain functionality is disabled then we have to provide stub \n   replacements for the functions */\n\n#ifndef USE_CERTIFICATES\n\nC_RET cryptCreateCert( C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_CERTTYPE_TYPE certType )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptSignCert( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t C_IN CRYPT_CONTEXT signContext )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCheckCert( C_IN CRYPT_HANDLE certificate,\n\t\t\t\t\t  C_IN CRYPT_HANDLE sigCheckKey )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptImportCert( C_IN void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_OUT CRYPT_CERTIFICATE C_PTR certificate )\n\t{\n\tUNUSED_ARG( certObject );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptExportCert( C_OUT_OPT void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectMaxLength,\n\t\t\t\t\t   C_OUT int C_PTR certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_CERTFORMAT_TYPE certFormatType,\n\t\t\t\t\t   C_IN CRYPT_HANDLE certificate )\n\t{\n\tUNUSED_ARG( certObject );\n\tUNUSED_ARG( certObjectLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptGetCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid,\n\t\t\t\t\t\t\t C_OUT int C_PTR criticalFlag,\n\t\t\t\t\t\t\t C_OUT void C_PTR extension,\n\t\t\t\t\t\t\t C_IN int extensionMaxLength,\n\t\t\t\t\t\t\t C_OUT int C_PTR extensionLength )\n\t{\n\tUNUSED_ARG( oid );\n\tUNUSED_ARG( criticalFlag );\n\tUNUSED_ARG( extension );\n\tUNUSED_ARG( extensionLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptAddCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid, C_IN int criticalFlag,\n\t\t\t\t\t\t\t C_IN void C_PTR extension,\n\t\t\t\t\t\t\t C_IN int extensionLength )\n\t{\n\tUNUSED_ARG( oid );\n\tUNUSED_ARG( extension );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptDeleteCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t\tC_IN char C_PTR oid )\n\t{\n\tUNUSED_ARG( oid );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_CERTIFICATES */\n\n#if !defined( USE_CERTIFICATES ) || !defined( USE_KEYSETS )\n\nC_RET cryptCAAddItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_CERTIFICATE certificate )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCAGetItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t  C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN_OPT C_STR keyID )\n\t{\n\tUNUSED_ARG( keyID );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCADeleteItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN C_STR keyID )\n\t{\n\tUNUSED_ARG( keyID );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCACertManagement( C_OUT_OPT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t\t\t C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT caKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certRequest )\n\t{\n\tUNUSED_ARG( certificate );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_CERTIFICATES || !USE_KEYSETS */\n\n#ifdef USE_PSEUDOCERTIFICATES \n\nC_RET cryptCreateAttachedCert( C_IN CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t   C_IN void C_PTR certObject,\n\t\t\t\t\t\t\t   C_IN int certObjectLength )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\t/* Perform basic error checking */\n\tif( !isHandleRangeValid( cryptContext ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( certObjectLength < MIN_CERTSIZE || \\\n\t\tcertObjectLength >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isReadPtrDynamic( certObject, certObjectLength ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\n\t/* Create the pseudo-certificate object */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, certObject,\n\t\t\t\t\t\t\t\t\t\tcertObjectLength, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_NONE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Attach the pseudo-certificate to the context */\n\tstatus = krnlSendMessage( cryptContext, MESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t  &createInfo.cryptHandle, \n\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\tif( cryptStatusError( status ) )\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n#endif /* USE_PSEUDOCERTIFICATES */\n\n#ifndef USE_DEVICES\n\nC_RET cryptDeviceCreateContext( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t    C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t\t    C_IN CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tUNUSED_ARG( cryptContext );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptDeviceOpen( C_OUT CRYPT_DEVICE C_PTR device,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t   C_IN_OPT C_STR name )\n\t{\n\tUNUSED_ARG( device );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptDeviceQueryCapability( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t\t  C_IN CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo )\n\t{\n\tUNUSED_ARG( cryptQueryInfo );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_DEVICES */\n\n#ifndef USE_ENVELOPES\n\nC_RET cryptCreateEnvelope( C_OUT CRYPT_ENVELOPE C_PTR envelope,\n\t\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t   C_IN CRYPT_FORMAT_TYPE formatType )\n\t{\n\tUNUSED_ARG( envelope );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_ENVELOPES */\n\n#if !defined( USE_ENVELOPES ) && !defined( USE_SESSIONS )\n\nC_RET cryptPushData( C_IN CRYPT_HANDLE envelope, C_IN void C_PTR buffer,\n\t\t\t\t\t C_IN int length, C_OUT int C_PTR bytesCopied )\n\t{\n\tUNUSED_ARG( buffer );\n\tUNUSED_ARG( bytesCopied );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptPopData( C_IN CRYPT_ENVELOPE envelope, C_OUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length, C_OUT int C_PTR bytesCopied )\n\t{\n\tUNUSED_ARG( buffer );\n\tUNUSED_ARG( bytesCopied );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptFlushData( C_IN CRYPT_HANDLE envelope )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_ENVELOPES && !USE_SESSIONS */\n\n#ifndef USE_KEYSETS\n\nC_RET cryptKeysetOpen( C_OUT CRYPT_KEYSET C_PTR keyset,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t   C_IN C_STR name, C_IN CRYPT_KEYOPT_TYPE options )\n\t{\n\tUNUSED_ARG( keyset );\n\tUNUSED_ARG( name );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptGetPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_OUT CRYPT_HANDLE C_PTR cryptKey,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN_OPT C_STR keyID )\n\t{\n\tUNUSED_ARG( cryptKey );\n\tUNUSED_ARG( keyID );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptGetPrivateKey( C_IN CRYPT_HANDLE keyset,\n\t\t\t\t\t\t  C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t  C_IN C_STR keyID, C_IN C_STR password )\n\t{\n\tUNUSED_ARG( cryptContext );\n\tUNUSED_ARG( keyID );\n\tUNUSED_ARG( password );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptGetKey( C_IN CRYPT_HANDLE keyset,\n\t\t\t\t   C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t   C_IN CRYPT_KEYID_TYPE keyIDtype, C_IN C_STR keyID, \n\t\t\t\t   C_IN C_STR password )\n\t{\n\tUNUSED_ARG( cryptContext );\n\tUNUSED_ARG( keyID );\n\tUNUSED_ARG( password );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptAddPrivateKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t  C_IN CRYPT_HANDLE cryptKey,\n\t\t\t\t\t\t  C_IN C_STR password )\n\t{\n\tUNUSED_ARG( password );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptAddPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certificate )\n\t{\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptDeleteKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN C_STR keyID )\n\t{\n\tUNUSED_ARG( keyID );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_KEYSETS */\n\n#ifndef USE_SESSIONS\n\nC_RET cryptCreateSession( C_OUT CRYPT_SESSION C_PTR session,\n\t\t\t\t\t\t  C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t  C_IN CRYPT_SESSION_TYPE sessionType )\n\t{\n\tUNUSED_ARG( session );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* !USE_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFuzzing Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Debug function to handle fuzzing */\n\n#ifdef CONFIG_FUZZ\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with fuzz data injection enabled (debug build only).\" )\n  #ifdef CONFIG_LIBFUZZER\n\t#pragma message( \"  Building with additional libfuzzer support (debug build only).\" )\n  #endif /* CONFIG_LIBFUZZER */\n#endif /* Warn about special features enabled */\n\n#include \"io/stream_int.h\"\t\t/* For STREAM_MFLAG_PSEUDO_HTTP */\n#include \"session/session.h\"\n\n/* Helper function in session/sess_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fuzzInnerProtocol( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t   IN_DATALENGTH const int bufSize );\n\n/* One-shot initialisation function for session objects, called before \n   repeatedly feeding fuzz data to the object, and the function to feed fuzz\n   data to the session */\n\nC_RET cryptFuzzInit( C_IN CRYPT_SESSION cryptSession,\n\t\t\t\t\t C_IN CRYPT_CONTEXT cryptContext )\n\t{\n\tSESSION_INFO *sessionInfoPtr;\n\tint status;\n\n\tassert( isHandleRangeValid( cryptSession ) );\n\tassert( ( cryptContext == CRYPT_UNUSED ) || \\\n\t\t\tisHandleRangeValid( cryptContext ) );\n\n\t/* Make sure that any network finalisation has been performed.  We have \n\t   to do this explicitly since we're bypassing the normal session init\n\t   process */\n\t( void ) krnlWaitSemaphore( SEMAPHORE_DRIVERBIND );\n\n\t/* Get the session state information so that we can call directly into\n\t   internal functions */\n\tstatus = krnlAcquireObject( cryptSession, OBJECT_TYPE_SESSION, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &sessionInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Perform any necessary final session initialistion */\n\tif( sessionInfoPtr->sendBuffer == NULL )\n\t\t{\n\t\tREQUIRES( rangeCheck( sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t\t  1, MAX_BUFFER_SIZE ) );\n\t\tsessionInfoPtr->receiveBuffer = \\\n\t\t\t\t\t\t\tsafeBufferAlloc( sessionInfoPtr->receiveBufSize );\n\t\tif( sessionInfoPtr->receiveBuffer == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tif( sessionInfoPtr->sendBufSize != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t\t\t  1, MAX_BUFFER_SIZE ) );\n\t\t\tsessionInfoPtr->sendBuffer = \\\n\t\t\t\t\t\t\tsafeBufferAlloc( sessionInfoPtr->receiveBufSize );\n\t\t\tif( sessionInfoPtr->sendBuffer == NULL )\n\t\t\t\t{\n\t\t\t\tsafeBufferFree( sessionInfoPtr->receiveBuffer );\n\t\t\t\tsessionInfoPtr->receiveBuffer = NULL;\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->sendBufSize = sessionInfoPtr->receiveBufSize;\n\t\t\t}\n\t\t}\n\tif( cryptContext != CRYPT_UNUSED )\n\t\t{\n\t\tsessionInfoPtr->privateKey = cryptContext;\n\t\tkrnlSendNotifier( sessionInfoPtr->privateKey, IMESSAGE_INCREFCOUNT );\n\t\t}\n\tswitch( sessionInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_SESSION_TSP:\n\t\t\t/* Set a dummy message imprint size */\n\t\t\tsessionInfoPtr->sessionTSP->imprintSize = 1;\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_CMP:\n\t\t\t/* Set a dummy request object and auth key */\n\t\t\tsessionInfoPtr->iCertRequest = 0;\n\t\t\tsessionInfoPtr->iAuthInContext = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\tkrnlReleaseObject( cryptSession );\n\n\treturn( CRYPT_OK );\n\t}\n\nC_RET cryptSetFuzzData( C_IN CRYPT_SESSION cryptSession, \n\t\t\t\t\t\tC_IN void *data, C_IN int dataLength,\n\t\t\t\t\t\tC_IN CRYPT_SUBPROTOCOL_TYPE subProtocolType )\n\t{\n\tSESSION_INFO *sessionInfoPtr;\n\tSES_TRANSACT_FUNCTION transactFunction;\n\tint status;\n\n\tassert( isHandleRangeValid( cryptSession ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\t/* Get the session state information so that we can call directly into\n\t   internal functions */\n\tstatus = krnlAcquireObject( cryptSession, OBJECT_TYPE_SESSION, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &sessionInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttransactFunction = ( SES_TRANSACT_FUNCTION ) \\\n\t\t\t\t\t   FNPTR_GET( sessionInfoPtr->transactFunction );\n\tREQUIRES_OBJECT( transactFunction != NULL, cryptSession );\n\n\t/* Set up an emulated network I/O stream to read input from and process\n\t   the input as far as we can */\n\tsMemPseudoConnect( &sessionInfoPtr->stream, data, dataLength );\n\tif( sessionInfoPtr->type == CRYPT_SESSION_RTCS || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_OCSP || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_TSP || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_CMP || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_SCEP )\n\t\t{\n\t\t/* It's an HTTP pseudo-stream, mark it as such */\n\t\tSET_FLAG( sessionInfoPtr->stream.flags, STREAM_MFLAG_PSEUDO_HTTP );\n\t\t}\n\tif( subProtocolType != CRYPT_SUBPROTOCOL_NONE )\n\t\t{\n\t\tBYTE buffer[ 4096 ];\n\t\tconst int length = min( dataLength, 4096 );\n\n\t\t/* If we're fuzzing WebSockets data then it's coming from a client\n\t\t   and so is masked, make sure that we unmask it */\n\t\tif( subProtocolType == CRYPT_SUBPROTOCOL_WEBSOCKETS )\n\t\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSERVER );\n\n\t\tif( length <= 0 )\n\t\t\treturn( CRYPT_OK );\n\t\tmemcpy( buffer, data, length );\n\t\tstatus = fuzzInnerProtocol( sessionInfoPtr, buffer, length );\n\t\t}\n\telse\n\t\tstatus = transactFunction( sessionInfoPtr );\n\tsMemDisconnect( &sessionInfoPtr->stream );\n\n\tkrnlReleaseObject( cryptSession );\n\n\treturn( status );\n\t}\n\n/* Fuzzing function for HTTP data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportReadFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t  OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t  IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t\t  IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( maxLength == 1 );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* This function can only be called from the higher-level read buffering \n\t   layer when stream->bufPos >= stream->bufEnd, which means that we've \n\t   run out of input.  Since no more can arrive (if it was connected to a\n\t   real network stream it'd eventually result in a CRYPT_ERROR_TIMEOUT),\n\t   we always return a CRYPT_ERROR_UNDERFLOW */\n\treturn( CRYPT_ERROR_UNDERFLOW );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportWriteFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t   IN_BUFFER( maxLength ) const BYTE *buffer, \n\t\t\t\t\t\t\t\t   IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t\t   IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\n\t*length = maxLength;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportDummyFunction( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nC_RET cryptFuzzSpecial( C_IN CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\tC_IN void *data, C_IN int dataLength, \n\t\t\t\t\t\tC_IN int isServer )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tHTTP_URI_INFO httpReqInfo;\n\tERROR_INFO errorInfo;\n\tNET_STREAM_INFO netStream;\n\tSTREAM stream;\n\tBYTE buffer[ SAFEBUFFER_SIZE( 8192 ) + 8 ] STACK_ALIGN_DATA;\n\tint status;\n\n\tassert( cryptContext == CRYPT_UNUSED || \\\n\t\t\tisHandleRangeValid( cryptContext ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tsMemPseudoConnect( &stream, data, dataLength );\n\tmemset( &netStream, 0, sizeof( NET_STREAM_INFO ) );\n\tINIT_FLAGS( netStream.nFlags, STREAM_NFLAG_NONE );\n\tif( isServer )\n\t\t{\n\t\tINIT_FLAGS( netStream.nhFlags, \\\n\t\t\t\t\tSTREAM_NHFLAG_GET | STREAM_NHFLAG_POST );\n\t\t}\n\telse\n\t\t{\n\t\tINIT_FLAGS( netStream.nhFlags, STREAM_NHFLAG_NONE );\n\t\t}\n\tsetStreamLayerHTTP( &netStream );\n\tnetStream.protocol = STREAM_PROTOCOL_HTTP;\n\tnetStream.port = 80;\n\tSET_FLAGS( stream.flags, \n\t\t\t   STREAM_MFLAG_PSEUDO_HTTP | STREAM_MFLAG_PSEUDO_RAW );\n\tFNPTR_SET( netStream.transportReadFunction,\n\t\t\t   transportReadFunction );\n\tFNPTR_SET( netStream.transportWriteFunction,\n\t\t\t   transportWriteFunction );\n\tFNPTR_SET( netStream.transportConnectFunction,\n\t\t\t   transportDummyFunction );\n\tFNPTR_SET( netStream.transportDisconnectFunction,\n\t\t\t   transportDummyFunction );\n\tFNPTR_SET( netStream.transportCheckFunction,\n\t\t\t   transportDummyFunction );\n\tFNPTR_SET( netStream.transportOKFunction,\n\t\t\t   transportDummyFunction );\n\tFNPTR_SET( netStream.connectFunctionOpt, NULL );\n\tFNPTR_SET( netStream.disconnectFunctionOpt, NULL );\n\tDATAPTR_SET( netStream.virtualStateInfo, NULL );\n\tFNPTR_SET( netStream.virtualGetDataFunction, NULL );\n\tFNPTR_SET( netStream.virtualPutDataFunction, NULL );\n\tFNPTR_SET( netStream.virtualGetErrorInfoFunction, NULL );\n\tDATAPTR_SET( stream.netStream, &netStream );\n\tif( isServer )\n\t\tSET_FLAGS( netStream.nFlags, STREAM_NFLAG_ISSERVER );\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), 8192 );\n\tmemset( &httpReqInfo, 0, sizeof( HTTP_URI_INFO ) );\n\tstatus = initHttpInfoReadEx( &httpDataInfo, SAFEBUFFER_PTR( buffer ), \n\t\t\t\t\t\t\t\t 8192, &httpReqInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sread( &stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &stream, &errorInfo );\n\t\treturn( status );\n\t\t}\n\tsMemDisconnect( &stream );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* libfuzzer/honggfuzz requires additional functionality added to the \n   standard fuzz build */\n\n#ifdef CONFIG_LIBFUZZER\n\nint LLVMFuzzerTestOneInput( const BYTE *data, const size_t dataLength ) \n\t{\n\tstatic BOOLEAN isInitialised = FALSE;\n\n\t/* Since libfuzzer/honggfuzz is used to fuzz libraries rather than \n\t   applications, we won't have been initialised yet, so we need to \n\t   perform initialise functions on the first call */\n\tif( !isInitialised )\n\t\t{\n\t\tint status;\n\n\t\tstatus = cryptInit();\n\t\tassert( cryptStatusOK( status ) );\t/* Trigger fuzzer alert */\n\t\tisInitialised = TRUE;\n\t\t}\n\n\t/* libFuzzer can pass in zero-length input, which we can't do anything\n\t   with but which triggers an exception in cryptFuzzSpecial() */\n\tif( data == NULL || dataLength <= 0 )\n\t\treturn( 0 );\n\n\t( void ) cryptFuzzSpecial( CRYPT_UNUSED, data, dataLength, FALSE );\n\treturn( 0 );\n\t}\n#endif /* CONFIG_LIBFUZZER */\n\n#endif /* CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCustom Code Insertion Point\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This section can be used to insert custom code for application-specific \n   purposes.  It's normally not used, and isn't present in the standard \n   distribution */\n\n#if !defined( NDEBUG ) && 1\n\nC_RET cryptDelayRandom( C_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT hashContext )\n\t{\n\tif( signContext != CRYPT_UNUSED )\n\t\t{\n\t\tMECHANISM_SIGN_INFO mechanismInfo;\n\t\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\t\tint status;\n\n\t\tsetMechanismSignInfo( &mechanismInfo, buffer, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t  hashContext, CRYPT_UNUSED, signContext );\n\t\tstatus = krnlSendMessage( signContext, IMESSAGE_DEV_SIGN, \n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_SIG_PKCS1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( insertCryptoDelay() );\n\t}\n\n#if defined( CONFIG_FAULTS ) || defined( CONFIG_FUZZ )\n\n/* Debug function to handle fault injection, which sets the global value \n   that controls the type of fault to simulate.  Note that this function is\n   added unconditionally (provided that it's a debug build) since it's part \n   of the self-test code */\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with crypto fault injection enabled (debug build only).\" )\n#endif /* Warn about special features enabled */\n\n#ifdef CONFIG_FUZZ \nstatic int faultType;\t/* Dummy value for fuzz build */\n#endif /* CONFIG_FUZZ  */\n\nC_RET cryptSetFaultType( C_IN int type )\n\t{\n\tfaultType = type;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_FAULTS || CONFIG_FUZZ */\n\n/* Debug function to set the memory-allocation invocation number at which\n   we fail the malloc() */\n\n#ifdef CONFIG_FAULT_MALLOC\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with memory fault injection enabled (debug build only).\" )\n#endif /* Warn about special features enabled */\n\nC_RET cryptSetMemFaultCount( C_IN int number )\n\t{\n\tclFaultAllocSetCount( number );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_FAULT_MALLOC */\n\n#ifdef CONFIG_SUITEB_TESTS \n\n/* Special kludge function to enable nonstandard behaviour for Suite B \n   tests.  This just passes the call on down to the low-level internal\n   Suite B configuration code */\n\nint sslSuiteBTestConfig( const int magicValue );\n\nC_RET cryptSuiteBTestConfig( C_IN int magicValue )\n\t{\n\treturn( sslSuiteBTestConfig( magicValue ) );\n\t}\n#endif /* CONFIG_SUITEB_TESTS  */\n\n#endif /* Debug-mode only test code */\n"
  },
  {
    "path": "deps/cl345/cryptcrt.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Certificate Management Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* \"By the power vested in me, I now declare this text string and this bit\n\tstring 'name' and 'key'.  What RSA has joined, let no man put asunder\".\n\t\t\t\t\t\t\t\t\t\t\t-- Bob Blakley */\n#include <ctype.h>\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"cert.h\"\n  #include \"asn1.h\"\n#else\n  #include \"cert/cert.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n/* Warn about building at nonstandard compliance levels */\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #if defined( USE_CERTLEVEL_PKIX_FULL )\n\t#pragma message( \"  Building with nonstandard compliance level CERTLEVEL_PKIX_FULL.\" )\n  #elif defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\t#pragma message( \"  Building with nonstandard compliance level CERTLEVEL_PKIX_PARTIAL.\" )\n  #elif defined( USE_CERTLEVEL_PKIX_PARTIAL )\n  #endif /* Certificate compliance level */\n#endif /* Warn about special features enabled */\n\n/* The minimum size for an OBJECT IDENTIFIER expressed as ASCII characters */\n\n#define MIN_ASCII_OIDSIZE\t7\n\n#if defined( USE_CERTIFICATES )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Compare values to data in a certificate */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN compareCertInfo( const CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_COMPARE ) \\\n\t\t\t\t\t\t\t\t\tconst MESSAGE_COMPARE_TYPE compareType,\n\t\t\t\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataLength,\n\t\t\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tint status;\n\n\tassert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES_B( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES_B( isEnumRange( compareType, MESSAGE_COMPARE ) );\n\tREQUIRES_B( ( compareType == MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t\t  data == NULL && dataLength == 0 && \\\n\t\t\t\t  isHandleRangeValid( iCryptCert ) ) || \\\n\t\t\t\t( compareType != MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t\t  data != NULL && isShortIntegerRangeNZ( dataLength ) && \\\n\t\t\t\t  iCryptCert == CRYPT_UNUSED ) );\n\n\tswitch( compareType )\n\t\t{\n\t\tcase MESSAGE_COMPARE_SUBJECT:\n\t\t\tif( dataLength != certInfoPtr->subjectDNsize || \\\n\t\t\t\tmemcmp( data, certInfoPtr->subjectDNptr,\n\t\t\t\t\t\tcertInfoPtr->subjectDNsize ) )\n\t\t\t\treturn( FALSE );\n\t\t\treturn( TRUE );\n\n\t\tcase MESSAGE_COMPARE_ISSUERANDSERIALNUMBER:\n\t\t\t{\n\t\t\tSTREAM stream;\n\t\t\tvoid *dataPtr DUMMY_INIT_PTR;\n\t\t\tint dataLeft DUMMY_INIT, serialNoLength, length;\n\n\t\t\tif( certInfoPtr->type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\tcertInfoPtr->type != CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Comparing an iAndS can get quite tricky because of assorted \n\t\t\t   braindamage in encoding methods so that two dissimilar \n\t\t\t   iAndSs aren't necessarily supposed to be regarded as non-\n\t\t\t   equal.  First we try a trivial reject check, if that passes \n\t\t\t   we compare the issuerName and serialNumber with corrections \n\t\t\t   for common encoding braindamage.  Note that even this \n\t\t\t   comparison can fail since older versions of the Entegrity \n\t\t\t   toolkit (from the early 1990s) rewrote T61Strings in \n\t\t\t   certificates as PrintableStrings in recipientInfo which means \n\t\t\t   that any kind of straight comparison on these would fail.  We \n\t\t\t   don't bother handling this sort of thing, and it's likely \n\t\t\t   that most other software won't either (this situation only \n\t\t\t   occurs when a certificate issuerName contains PrintableString \n\t\t\t   text incorrectly encoded as T61String, which is rare enough \n\t\t\t   that it required artifically-created certificates just to \n\t\t\t   reproduce the problem).  In addition the trivial reject check \n\t\t\t   can also fail since in an extreme encoding braindamage case a \n\t\t\t   BMPString rewritten as a PrintableString would experience a \n\t\t\t   large enough change in length to fail the check, but as with \n\t\t\t   the Entegrity problem this is a level of brokenness up with \n\t\t\t   which we will not put */\n\t\t\tlength = sizeofShortObject( \\\n\t\t\t\t\t\t\tcertInfoPtr->issuerDNsize + \\\n\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\tcertInfoPtr->cCertCert->serialNumberLength ) );\n\t\t\tif( length < dataLength - 2 || length > dataLength + 2 )\n\t\t\t\t{\n\t\t\t\t/* Trivial reject, the lengths are too dissimilar for any \n\t\t\t\t   fixup attempts to work */\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* We also disallow obviously-invalid lengths at this point to \n\t\t\t   ensure that we don't try and do anything with invalid data */\n\t\t\tif( length < 16 || length > MAX_INTLENGTH_SHORT || \\\n\t\t\t\tdataLength < 16 || dataLength > MAX_INTLENGTH_SHORT )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* We got past the trivial reject check, try a more detailed check, \n\t\t\t   first the issuerName */\n\t\t\tsMemConnect( &stream, data, dataLength );\n\t\t\tstatus = readSequence( &stream, NULL );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tdataLeft = dataLength - stell( &stream );\n\t\t\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, dataLeft );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\t\t\t\n\t\t\t\tstatus = getObjectLength( dataPtr, dataLeft, &length );\n\t\t\tif( cryptStatusOK( status ) )\t\t\t\n\t\t\t\tstatus = readUniversal( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tANALYSER_HINT( dataPtr != NULL );\n\t\t\tif( length != certInfoPtr->issuerDNsize || \\\n\t\t\t\tmemcmp( dataPtr, certInfoPtr->issuerDNptr,\n\t\t\t\t\t\tcertInfoPtr->issuerDNsize ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Compare the serialNumber */\n\t\t\tstatus = readGenericHole( &stream, &serialNoLength, 1, \n\t\t\t\t\t\t\t\t\t  BER_INTEGER );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, \n\t\t\t\t\t\t\t\t\t\t   serialNoLength );\n\t\t\t\t}\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( !compareSerialNumber( certInfoPtr->cCertCert->serialNumber,\n\t\t\t\t\t\t\t\t\t  certInfoPtr->cCertCert->serialNumberLength,\n\t\t\t\t\t\t\t\t\t  dataPtr, serialNoLength ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\tcase MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER:\n\t\t\t{\n\t\t\tBYTE sKID[ 128 + 8 ];\n\t\t\tint sKIDlength;\n\n\t\t\t/* Fetch the certificate's subjectKeyIdentifier and see whether \n\t\t\t   it matches what we've been given */\n\t\t\tstatus = getCertComponentString( ( CERT_INFO * ) certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, \n\t\t\t\t\t\t\t\t\t\t\t sKID, 128, &sKIDlength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\treturn( ( sKIDlength == dataLength && \\\n\t\t\t\t\t  !memcmp( sKID, data, sKIDlength ) ) ? TRUE : FALSE );\n\t\t\t}\n\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHA1:\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHA2:\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHAng:\n\t\tcase MESSAGE_COMPARE_CERTOBJ:\n\t\t\t{\n\t\t\tstatic const MAP_TABLE fingerprintMapTable[] = {\n\t\t\t\t{ MESSAGE_COMPARE_CERTOBJ, CRYPT_CERTINFO_FINGERPRINT_SHA1 },\n\t\t\t\t{ MESSAGE_COMPARE_FINGERPRINT_SHA1, CRYPT_CERTINFO_FINGERPRINT_SHA1 },\n\t\t\t\t{ MESSAGE_COMPARE_FINGERPRINT_SHA2, CRYPT_CERTINFO_FINGERPRINT_SHA2 },\n\t\t\t\t{ MESSAGE_COMPARE_FINGERPRINT_SHAng, CRYPT_CERTINFO_FINGERPRINT_SHAng },\n\t\t\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t\t\t};\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tBYTE fingerPrint[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\t\tint fingerPrintLength, attributeToCompare;\n\n\t\t\tstatus = mapValue( compareType, &attributeToCompare, \n\t\t\t\t\t\t\t   fingerprintMapTable,\n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( fingerprintMapTable, \\\n\t\t\t\t\t\t\t\t\t\t\t\t   MAP_TABLE ) );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\n\t\t\t/* If the certificate hasn't been signed yet we can't compare \n\t\t\t   the fingerprint */\n\t\t\tif( certInfoPtr->certificate == NULL )\n\t\t\t\treturn( FALSE );\n\t\t\t\n\t\t\t/* Get the certificate fingerprint and compare it to what we've \n\t\t\t   been given */\n\t\t\tstatus = getCertComponentString( ( CERT_INFO * ) certInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t attributeToCompare, fingerPrint, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t\t\t\t &fingerPrintLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* If it's a straight fingerprint compare, compare the \n\t\t\t   certificate fingerprint to the user-supplied value */\n\t\t\tif( compareType != MESSAGE_COMPARE_CERTOBJ )\n\t\t\t\t{\n\t\t\t\treturn( ( dataLength == fingerPrintLength && \\\n\t\t\t\t\t\t  !memcmp( data, fingerPrint, fingerPrintLength ) ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\t\t\t\t}\n\t\t\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t\t\t/* It's a full certificate compare, compare the encoded \n\t\t\t   certificate data via the fingerprints */\n\t\t\tsetMessageData( &msgData, fingerPrint, fingerPrintLength );\n\t\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_FINGERPRINT_SHA1 );\n\t\t\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t\t\t}\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\n/* Check the usage of a certificate against a MESSAGE_CHECK_TYPE check */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkCertUsage( INOUT CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t   IN_ENUM( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\tconst MESSAGE_CHECK_TYPE checkType )\n\t{\n\tint complianceLevel, keyUsageValue, checkKeyFlag = CHECKKEY_FLAG_NONE;\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isEnumRange( checkType, MESSAGE_CHECK ) );\n\n\t/* Map the check type to a key usage that we check for */\n\tswitch( checkType )\n\t\t{\n\t\tcase MESSAGE_CHECK_PKC_PRIVATE:\n\t\t\t/* This check type can be encountered when checking a private \n\t\t\t   key with a certificate attached */\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_NONE;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_ENCRYPT:\n\t\tcase MESSAGE_CHECK_PKC_ENCRYPT_AVAIL:\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_DECRYPT:\n\t\tcase MESSAGE_CHECK_PKC_DECRYPT_AVAIL:\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_SIGN:\n\t\tcase MESSAGE_CHECK_PKC_SIGN_AVAIL:\n\t\t\t/* In theory we should also check for KEYUSAGE_CA alongside \n\t\t\t   KEYUSAGE_SIGN, however KEYUSAGE_CA is an odd special case of \n\t\t\t   signing in which a signing key is allowed to sign any \n\t\t\t   conceivable bit pattern except for one that looks like a \n\t\t\t   certificate, and vice versa.  This means that while a CA key \n\t\t\t   can be used for signing, it can't be used to sign anything \n\t\t\t   other than a certificate, so a check for general signing \n\t\t\t   capability should fail.\n\t\t\t   \n\t\t\t   This however leads to a problematic situation in which a \n\t\t\t   check for the signing capability of a context would indicate\n\t\t\t   that it's unusable if it's associated with a CA certificate\n\t\t\t   rather than a general signing certificate.  Because of this\n\t\t\t   we have a special-case check that checks for data-that's-a-\n\t\t\t   certificate signing capability rather than just data-that-\n\t\t\t   isnt-a-certificate signing capability */\n\t\t\tkeyUsageValue = KEYUSAGE_SIGN;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_PRIVATEKEY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_SIGCHECK:\n\t\tcase MESSAGE_CHECK_PKC_SIGCHECK_AVAIL:\n\t\t\t/* See above comment for the non-check for KEYUSAGE_CA */\n\t\t\tkeyUsageValue = KEYUSAGE_SIGN;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_SIGN_CA:\n\t\tcase MESSAGE_CHECK_PKC_SIGN_CA_AVAIL:\n\t\t\t/* See comment above for the check of KEYUSAGE_CA */\n\t\t\tkeyUsageValue = KEYUSAGE_CA;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_CA | CHECKKEY_FLAG_PRIVATEKEY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_SIGCHECK_CA:\n\t\tcase MESSAGE_CHECK_PKC_SIGCHECK_CA_AVAIL:\n\t\t\t/* See comment above for the check of KEYUSAGE_CA.  \n\t\t\t   MESSAGE_CHECK_CACERT_FINAL is a special-case version of \n\t\t\t   MESSAGE_CHECK_PKC_SIGN/SIGCHECK_CA that's used internally by\n\t\t\t   the kernel */\n\t\t\tkeyUsageValue = KEYUSAGE_CA;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_CA;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_KA_EXPORT:\n\t\tcase MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL:\n\t\t\t/* exportOnly usage falls back to plain keyAgreement if \n\t\t\t   necessary */\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_KEYAGREEMENT | \\\n\t\t\t\t\t\t\tCRYPT_KEYUSAGE_ENCIPHERONLY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC_KA_IMPORT:\n\t\tcase MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL:\n\t\t\t/* importOnly usage falls back to plain keyAgreement if \n\t\t\t   necessary */\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_KEYAGREEMENT | \\\n\t\t\t\t\t\t\tCRYPT_KEYUSAGE_DECIPHERONLY;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_CHECK_PKC:\n\t\t\t/* If we're just checking for generic PKC functionality then \n\t\t\t   any kind of usage is OK */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase MESSAGE_CHECK_CERT:\n\t\t\t/* A generic check for certificate validity that doesn't require\n\t\t\t   full certificate processing as a MESSAGE_CRT_SIGCHECK would,\n\t\t\t   used when there's no signing certificate available but we \n\t\t\t   want to perform a generic check that the certificate is \n\t\t\t   generally OK, such as not being expired */\n\t\t\tstatus = checkCertBasic( certInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Convert the status value to the correct form */\n\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\t\t}\n\n\t\t\t/* Check the validity.  Because this is a nonspecific check we \n\t\t\t   allow any key usage */\n\t\t\tkeyUsageValue = CRYPT_KEYUSAGE_KEYENCIPHERMENT | \\\n\t\t\t\t\t\t\tKEYUSAGE_SIGN | KEYUSAGE_CA;\n\t\t\tcheckKeyFlag = CHECKKEY_FLAG_GENCHECK;\n\t\t\tbreak;\t\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tENSURES( keyUsageValue != CRYPT_KEYUSAGE_NONE || \\\n\t\t\t checkKeyFlag != CHECKKEY_FLAG_NONE );\n\n\t/* Certificate requests are special-case objects in that the key they \n\t   contain is usable only for signature checking of the self-signature \n\t   on the object (it can't be used for general-purpose usages, which \n\t   would make it equivalent to a trusted self-signed certificate).  This \n\t   is problematic because the keyUsage may indicate that the key is \n\t   valid for other things as well, or not valid for signature checking.  \n\t   To get around this we indicate that the key has a single trusted \n\t   usage, signature checking, and disallow any other usage regardless of \n\t   what the keyUsage says.  The actual keyUsage usage is only valid once \n\t   the request has been converted into a certificate */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\tcertInfoPtr->type == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\tif( checkType == MESSAGE_CHECK_PKC_SIGCHECK || \\\n\t\t\tcheckType == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL )\n\t\t\treturn( CRYPT_OK );\n\t\tsetErrorInfo( certInfoPtr, CRYPT_CERTINFO_TRUSTED_USAGE, \n\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\t/* Only certificate objects with associated public keys are valid for \n\t   check messages (which are checking the capabilities of the key) */\n\tREQUIRES( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN );\n\n\t/* Certificate collections are pure container objects for which the base \n\t   certificate object doesn't correspond to an actual certificate */\n\tREQUIRES( !TEST_FLAG( certInfoPtr->flags, CERT_FLAG_CERTCOLLECTION ) );\n\n\t/* Check the key usage for the certificate */\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = checkKeyUsage( certInfoPtr, checkKeyFlag, keyUsageValue, \n\t\t\t\t\t\t\tcomplianceLevel, &certInfoPtr->errorLocus, \n\t\t\t\t\t\t\t&certInfoPtr->errorType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert the status value to the correct form */\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Export the certificate's data contents in ASN.1-encoded form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exportCertData( CERT_INFO *certInfoPtr, \n\t\t\t\t\t\t   IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormat,\n\t\t\t\t\t\t   OUT_BUFFER_OPT( certDataMaxLength, *certDataLength ) \\\n\t\t\t\t\t\t\tvoid *certData,\n\t\t\t\t\t\t   IN_DATALENGTH_Z const int certDataMaxLength,\n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *certDataLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\tassert( ( certData == NULL && certDataMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( certData, certDataMaxLength ) );\n\tassert( isWritePtr( certDataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isEnumRange( certFormat, CRYPT_CERTFORMAT ) );\n\tREQUIRES( ( certData == NULL && certDataMaxLength == 0 ) || \\\n\t\t\t  ( certData != NULL && \\\n\t\t\t\tcertDataMaxLength > 0 && \\\n\t\t\t\tcertDataMaxLength < MAX_BUFFER_SIZE ) );\n\n\t/* Clear return value */\n\t*certDataLength = 0;\n\n\t/* Unsigned object types like CMS attributes aren't signed like other \n\t   certificate objects so they aren't pre-encoded when we sign them and \n\t   have the potential to change on each use if the same CMS attributes \n\t   are reused for multiple signatures.  Because of this we write them \n\t   out on export rather than copying the pre-encoded form from an \n\t   internal buffer */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )\n\t\t{\n\t\tWRITECERT_FUNCTION writeCertFunction;\n\t\tSTREAM stream;\n\n\t\tREQUIRES( certFormat == CRYPT_ICERTFORMAT_DATA );\n\n\t\twriteCertFunction = \\\n\t\t\t\tgetCertWriteFunction( CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\t\tENSURES( writeCertFunction != NULL );\n\t\tsMemOpenOpt( &stream, certData, certDataMaxLength );\n\t\tstatus = writeCertFunction( &stream, certInfoPtr, NULL, \n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*certDataLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( status );\n\t\t}\n\n\t/* Some objects aren't signed or are pseudo-signed or optionally signed \n\t   and have to be handled specially.  RTCS requests and responses are \n\t   never signed (they're pure data containers like CMS attributes, with \n\t   protection being provided by CMS).  OCSP requests can be optionally \n\t   signed but usually aren't, so if we're fed an OCSP request without \n\t   any associated encoded data we pseudo-sign it to produce encoded data.  \n\t   PKI user data is never signed but needs to go through a one-off setup \n\t   process to initialise the user data fields, so it has the same \n\t   semantics as a pseudo-signed object.  CRMF revocation requests are \n\t   never signed (thus ruling out suicide-note revocations) */\n\tif( ( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \\\n\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t  certInfoPtr->type == CRYPT_CERTTYPE_PKIUSER || \\\n\t\t  certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) && \\\n\t\tcertInfoPtr->certificate == NULL )\n\t\t{\n\t\tstatus = signCert( certInfoPtr, CRYPT_UNUSED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If we're exporting a single certificate from a chain, lock the \n\t   currently selected certificate in the chain and export that */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\tcertInfoPtr->cCertCert->chainPos >= 0 && \\\n\t\t( certFormat == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\t  certFormat == CRYPT_CERTFORMAT_TEXT_CERTIFICATE || \\\n\t\t  certFormat == CRYPT_CERTFORMAT_XML_CERTIFICATE ) )\n\t\t{\n\t\tCERT_INFO *certChainInfoPtr;\n\n\t\tENSURES( certInfoPtr->cCertCert->chainPos >= 0 && \\\n\t\t\t\t certInfoPtr->cCertCert->chainPos < MAX_CHAINLENGTH );\n\t\tstatus = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ], \n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = exportCert( certData, certDataMaxLength, certDataLength, \n\t\t\t\t\t\t\t certFormat, certChainInfoPtr );\n\t\tkrnlReleaseObject( certChainInfoPtr->objectHandle );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( ( TEST_FLAG( certInfoPtr->flags, \n\t\t\t\t\t\t  CERT_FLAG_CERTCOLLECTION ) && \\\n\t\t\t   certInfoPtr->certificate == NULL ) || \\\n\t\t\t certInfoPtr->certificate != NULL );\n\treturn( exportCert( certData, certDataMaxLength, certDataLength, \n\t\t\t\t\t\tcertFormat, certInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tInternal Certificate/Key Management Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import a certificate blob or certificate chain by sending get_next_cert \n   messages to the source object to obtain all the certificates in a chain.  \n   Returns the length of the certificate.\n   \n   This isn't really a direct certificate function since the control flow \n   sequence is:\n\n\timport indirect: \n\t\tGETNEXTCERT -> source object\n\t\t\tsource object: \n\t\t\t\tCREATEOBJECT_INDIRECT -> system device\n\t\t\t\t\tsystem device: createCertificate() \n\t\tGETNEXTCERT -> source object\n\t\t\tsource object: \n\t\t\t\tCREATEOBJECT_INDIRECT -> system device\n\t\t\t\t\tsystem device: createCertificate() \n\t\t[...]\t\t\t\t\t\n\n   however this seems to be the best place to put the code (sol lucet \n   omnibus) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint iCryptImportCertIndirect( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCertSource, \n\t\t\t\t\t\t\t  IN_ENUM( CRYPT_KEYID ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t  IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyIDlength,\n\t\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyIDlength ) );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* We're importing a sequence of certificates as a chain from a source \n\t   object, assemble the collection via the object */\n\treturn( assembleCertChain( iCertificate, iCertSource, keyIDtype, \n\t\t\t\t\t\t\t   keyID, keyIDlength, options ) );\n\t}\n\n/* Check that a given key ID actually corresponds to the certificate that \n   we've got.  This is used to verify that the certificate that a get-key\n   function has given us is actually the correct one for the key ID that\n   we specified.  Obviously this should be the case, but if the get-key\n   can lie to us and the caller blindly accepts the certificate and uses\n   it they could end up trying to fetch a certificate belonging to A,\n   being fed one belonging to B, and \"verify\" information from B believing\n   it to be from A.\n\n   This is another oddly-placed function that's placed here mostly because\n   there's nowhere else obvious to put it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptVerifyID( IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\tIN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyIDlength )\n\t{\n\tMESSAGE_COMPARE_TYPE compareType;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyIDlength >= min( MIN_ID_LENGTH, MIN_NAME_LENGTH ) && \\\n\t\t\t  keyIDlength < MAX_INTLENGTH_SHORT );\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_NAME:\n\t\tcase CRYPT_KEYID_URI:\n\t\t\t/* The definitions of these are sufficiently vague, generally \n\t\t\t   being \"whatever identifier is commonly associated with the \n\t\t\t   certificate\", that we can't easily reject a certificate based\n\t\t\t   on them */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\tcompareType = MESSAGE_COMPARE_KEYID;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IKEYID_PGPKEYID:\n\t\t\t/* This key ID has two subtypes, the PGP and the OpenPGP ID.  To\n\t\t\t   deal with this we try for the PGP one now and then fall back\n\t\t\t   to a second check with the OpenPGP one if this one fails */\n\t\t\tcompareType = MESSAGE_COMPARE_KEYID_PGP;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IKEYID_CERTID:\n\t\t\t/* Some sources (database keysets) truncate the certID to 128 \n\t\t\t   bits/16 bytes so we have to explicitly read the certID and\n\t\t\t   then compare that subset that we've been given */\n\t\t\tif( keyIDlength != KEYID_SIZE )\n\t\t\t\t{\n\t\t\t\tBYTE buffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t\t\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );\n\t\t\t\tstatus = krnlSendMessage( iCertificate, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\tmsgData.length < keyIDlength || \\\n\t\t\t\t\tmemcmp( buffer, keyID, keyIDlength ) )\n\t\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tcompareType = MESSAGE_COMPARE_FINGERPRINT_SHA1;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IKEYID_SUBJECTID:\n\t\tcase CRYPT_IKEYID_ISSUERID:\n\t\t\t{\n\t\t\tDYNBUF nameDB;\n\t\t\tBYTE nameHash[ KEYID_SIZE + 8 ];\n\t\t\tconst int idLength = min( keyIDlength, KEYID_SIZE );\n\n\t\t\t/* Compare the hashed subjectName (used by PKCS #15 files and \n\t\t\t   database keysets) or the hashed issuerAndSerialNumber (used by \n\t\t\t   PKCS #15 files).  We can't hard-wire in KEYID_SIZE for the\n\t\t\t   size of the hashed value because some sources use the full\n\t\t\t   KEYID_SIZE and some truncate it to 128 bits/16 bytes, so we\n\t\t\t   use the shorter of KEYID_SIZE and the user-provided ID size */\n\t\t\tstatus = dynCreate( &nameDB, iCertificate, \n\t\t\t\t\t\t\t\t( keyIDtype == CRYPT_IKEYID_SUBJECTID ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_SUBJECT : \\\n\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\thashData( nameHash, idLength, dynData( nameDB ), \n\t\t\t\t\t  dynLength( nameDB ) );\n\t\t\tdynDestroy( &nameDB );\n\t\t\treturn( memcmp( nameHash, keyID, idLength ) ? \\\n\t\t\t\t\tCRYPT_ERROR_INVALID : CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_IKEYID_ISSUERANDSERIALNUMBER:\n\t\t\tcompareType = MESSAGE_COMPARE_ISSUERANDSERIALNUMBER;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make sure that the key ID that we've been given matches the one in \n\t   the certificate.  What error code to use to indicate a problem is\n\t   rather unclear since there's really no way to say \"the data source\n\t   lied to us about the certificate that it returned\", the least\n\t   inappropriate code seems to be CRYPT_ERROR_INVALID (in any case since\n\t   this situation should never really occur it's not worth losing too\n\t   much sleep over it) */\n\tsetMessageData( &msgData, ( MESSAGE_DATA * ) keyID, keyIDlength );\n\tstatus = krnlSendMessage( iCertificate, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t  compareType );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If we were looking for a PGP keyID and the comparison on the OpenPGP\n\t   ID failed, fall back to checking the older PGP 2.x ID */\n\tif( keyIDtype == CRYPT_IKEYID_PGPKEYID )\n\t\t{\n\t\tstatus = krnlSendMessage( iCertificate, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID_OPENPGP );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tDEBUG_DIAG_ERRMSG(( \"Certificate fetched for ID type %s doesn't \"\n\t\t\t\t\t\t\"actually correspond to the given ID\", \n\t\t\t\t\t\tgetKeyIDName( keyIDtype ) ));\n\treturn( CRYPT_ERROR_INVALID );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Management API Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle attribute data sent to or read from a certificate object.  We have\n   to do this in a standalone function since it's called from several places\n   in the certificate message handler */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int processCertAttribute( INOUT CERT_INFO *certInfoPtr,\n\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t INOUT void *messageDataPtr, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\tint *valuePtr = ( int * ) messageDataPtr;\n\n\tassert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t  message == MESSAGE_SETATTRIBUTE_S || \\\n\t\t\t  message == MESSAGE_DELETEATTRIBUTE );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Process get/set/delete attribute messages */\n\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t{\n\t\tif( attribute == CRYPT_ATTRIBUTE_ERRORTYPE )\n\t\t\t{\n\t\t\t*valuePtr = certInfoPtr->errorType;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( attribute == CRYPT_ATTRIBUTE_ERRORLOCUS )\n\t\t\t{\n\t\t\t*valuePtr = certInfoPtr->errorLocus;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\treturn( getCertComponent( certInfoPtr, attribute, valuePtr ) );\n\t\t}\n\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t{\n\t\treturn( getCertComponentString( certInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\tmsgData->data, msgData->length, \n\t\t\t\t\t\t\t\t\t\t&msgData->length ) );\n\t\t}\n\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t{\n\t\tconst int value = *valuePtr;\n\t\tBOOLEAN validCursorPosition;\n\t\t\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES )\n\t\t\t{\n\t\t\tvalidCursorPosition = \\\n\t\t\t\t( attribute >= CRYPT_CERTINFO_FIRST_CMS && \\\n\t\t\t\t  attribute <= CRYPT_CERTINFO_LAST_CMS ) ? TRUE : FALSE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tvalidCursorPosition = \\\n\t\t\t\t( attribute >= CRYPT_CERTINFO_FIRST_EXTENSION && \\\n\t\t\t\t  attribute <= CRYPT_CERTINFO_LAST_EXTENSION ) ? TRUE : FALSE;\n\t\t\t}\n\n\t\t/* If it's a completed certificate we can only add a restricted \n\t\t   class of component selection control values to the object.  We\n\t\t   don't use continuation characters for the more complex isXYZ()\n\t\t   expressions because the resulting string is too long for some\n\t\t   broken compilers */\n\t\tREQUIRES( certInfoPtr->certificate == NULL || \\\n\t\t\t\t  isDNSelectionComponent( attribute ) ||\n\t\t\t\t  isGeneralNameSelectionComponent( attribute ) || \n\t\t\t\t  /* Cursor control */\n\t\t\t\t  attribute == CRYPT_CERTINFO_CURRENT_CERTIFICATE || \\\n\t\t\t\t  attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t\t  attribute == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t\t  attribute == CRYPT_ATTRIBUTE_CURRENT_INSTANCE ||\n\t\t\t\t  /* Certificate handling control component */\n\t\t\t\t  attribute == CRYPT_CERTINFO_TRUSTED_USAGE || \\\n\t\t\t\t  attribute == CRYPT_CERTINFO_TRUSTED_IMPLICIT || \\\n\t\t\t\t  attribute == CRYPT_IATTRIBUTE_INITIALISED || \n\t\t\t\t  /* Misc.components */\n\t\t\t\t  attribute == CRYPT_IATTRIBUTE_PKIUSERINFO );\n\n\t\t/* If it's an initialisation message, there's nothing to do (we get \n\t\t   these when importing a certificate, when the import is complete \n\t\t   the import code sends this message to move the certificate into \n\t\t   the high state because it's already signed) */\n\t\tif( attribute == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If the passed-in value is a cursor-positioning code, make sure \n\t\t   that it's valid */\n\t\tif( value < 0 && value != CRYPT_UNUSED && \\\n\t\t\t( value > CRYPT_CURSOR_FIRST || value < CRYPT_CURSOR_LAST ) &&\n\t\t\t!validCursorPosition && attribute != CRYPT_CERTINFO_SELFSIGNED )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\treturn( addCertComponent( certInfoPtr, attribute, value ) );\n\t\t}\n\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t{\n\t\treturn( addCertComponentString( certInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\tmsgData->data, msgData->length ) );\n\t\t}\n\tif( message == MESSAGE_DELETEATTRIBUTE )\n\t\treturn( deleteCertComponent( certInfoPtr, attribute ) );\n\n\tretIntError();\n\t}\n\n/* Handle a message sent to a certificate context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int certificateMessageFunction( INOUT TYPECAST( CERT_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t   void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t   IN_INT_Z const int messageValue )\n\t{\n\tCERT_INFO *certInfoPtr = ( CERT_INFO * ) objectInfoPtr;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  sanityCheckCert( certInfoPtr ) );\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( ( message == MESSAGE_CRT_SIGCHECK && \\\n\t\t\t\tmessageValue == CRYPT_UNUSED ) || \\\n\t\t\t  isIntegerRange( messageValue ) );\n\n\t/* Process destroy object messages */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* Clear the encoded certificate and miscellaneous components if\n\t\t   necessary.  Note that there's no need to clear the associated\n\t\t   encryption context (if any) since this is a dependent object of\n\t\t   the certificate and is destroyed by the kernel when the \n\t\t   certificate is destroyed */\n\t\tif( certInfoPtr->certificate != NULL )\n\t\t\t{\n\t\t\tzeroise( certInfoPtr->certificate, certInfoPtr->certificateSize );\n\t\t\tclFree( \"certificateMessageFunction\", certInfoPtr->certificate );\n\t\t\t}\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t{\n\t\t\tif( certInfoPtr->cCertCert->serialNumber != NULL && \\\n\t\t\t\tcertInfoPtr->cCertCert->serialNumber != \\\n\t\t\t\t\tcertInfoPtr->cCertCert->serialNumberBuffer )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertCert->serialNumber );\n\t\t\t\t}\n\t\t\t}\n#ifdef USE_CERTREQ\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t{\n\t\t\tif( certInfoPtr->cCertReq->serialNumber != NULL && \\\n\t\t\t\tcertInfoPtr->cCertReq->serialNumber != \\\n\t\t\t\t\tcertInfoPtr->cCertReq->serialNumberBuffer )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertReq->serialNumber );\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERTREQ */\n#ifdef USE_CERT_OBSOLETE \n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t\t{\n\t\t\tif( certInfoPtr->cCertCert->subjectUniqueID != NULL )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertCert->subjectUniqueID );\n\t\t\t\t}\n\t\t\tif( certInfoPtr->cCertCert->issuerUniqueID != NULL )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertCert->issuerUniqueID );\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERT_OBSOLETE */\n\t\tif( certInfoPtr->publicKeyData != NULL )\n\t\t\tclFree( \"certificateMessageFunction\", certInfoPtr->publicKeyData  );\n\t\tif( certInfoPtr->subjectDNdata != NULL )\n\t\t\tclFree( \"certificateMessageFunction\", certInfoPtr->subjectDNdata );\n\t\tif( certInfoPtr->issuerDNdata != NULL )\n\t\t\tclFree( \"certificateMessageFunction\", certInfoPtr->issuerDNdata );\n#ifdef USE_CERTREV\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t{\n\t\t\tif( certInfoPtr->cCertRev->responderUrl != NULL )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertRev->responderUrl );\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERTREV */\n#ifdef USE_CERTVAL\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t\t{\n\t\t\tif( certInfoPtr->cCertVal->responderUrl != NULL )\n\t\t\t\t{\n\t\t\t\tclFree( \"certificateMessageFunction\", \n\t\t\t\t\t\tcertInfoPtr->cCertVal->responderUrl );\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERTVAL */\n\n\t\t/* Clear the DN's if necessary */\n\t\tif( DATAPTR_ISSET( certInfoPtr->issuerName ) )\n\t\t\tdeleteDN( &certInfoPtr->issuerName );\n\t\tif( DATAPTR_ISSET( certInfoPtr->subjectName ) )\n\t\t\tdeleteDN( &certInfoPtr->subjectName );\n\n\t\t/* Clear the attributes and validity/revocation info if necessary */\n\t\tif( DATAPTR_ISSET( certInfoPtr->attributes ) )\n\t\t\tdeleteAttributes( &certInfoPtr->attributes );\n#ifdef USE_CERTVAL\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_RTCS_REQUEST || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t\t{\n\t\t\tCERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;\n\n\t\t\tif( DATAPTR_ISSET( certValInfo->validityInfo ) )\n\t\t\t\tdeleteValidityEntries( &certValInfo->validityInfo );\n\t\t\t}\n#endif /* USE_CERTVAL */\n#ifdef USE_CERTREV\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CRL || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_REQUEST || \\\n\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t{\n\t\t\tCERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;\n\n\t\t\tif( DATAPTR_ISSET( certRevInfo->revocations ) )\n\t\t\t\tdeleteRevocationEntries( &certRevInfo->revocations );\n\t\t\t}\n#endif /* USE_CERTREV */\n\n\t\t/* Clear the certificate chain if necessary */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\t\tcertInfoPtr->cCertCert->chainEnd > 0 )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\tENSURES( certInfoPtr->cCertCert->chainEnd >= 0 && \\\n\t\t\t\t\t certInfoPtr->cCertCert->chainEnd < MAX_CHAINLENGTH );\n\t\t\tLOOP_EXT( i = 0, i < certInfoPtr->cCertCert->chainEnd, i++, \n\t\t\t\t\t  MAX_CHAINLENGTH )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( certInfoPtr->cCertCert->chain[ i ],\n\t\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\t/* If it's a certificate chain lock the currently selected \n\t\t   certificate in the chain unless the message being processed is a \n\t\t   certificate cursor movement command or something specifically \n\t\t   directed at the entire chain (for example a get type or self-\n\t\t   signed status command - we want to get the type/status of the \n\t\t   chain, not of the certificates within it) */\n\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\t\tcertInfoPtr->cCertCert->chainPos >= 0 && \\\n\t\t\t!( ( message == MESSAGE_SETATTRIBUTE ) && \\\n\t\t\t   ( messageValue == CRYPT_CERTINFO_CURRENT_CERTIFICATE ) ) && \\\n\t\t\t!( ( message == MESSAGE_GETATTRIBUTE ) && \\\n\t\t\t   ( messageValue == CRYPT_CERTINFO_CERTTYPE || \\\n\t\t\t\t messageValue == CRYPT_CERTINFO_SELFSIGNED ) ) )\n\t\t\t{\n\t\t\tCERT_INFO *certChainInfoPtr;\n\t\t\tint status;\n\n\t\t\tENSURES( certInfoPtr->cCertCert->chainPos >= 0 && \\\n\t\t\t\t\t certInfoPtr->cCertCert->chainPos < MAX_CHAINLENGTH );\n\t\t\tstatus = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ], \n\t\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tANALYSER_HINT( certChainInfoPtr != NULL );\n\t\t\tstatus = processCertAttribute( certChainInfoPtr, message, \n\t\t\t\t\t\t\t\t\t\t   messageDataPtr, messageValue );\n\t\t\tkrnlReleaseObject( certChainInfoPtr->objectHandle );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\treturn( processCertAttribute( certInfoPtr, message, messageDataPtr, \n\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t}\n\n\t/* Process messages that compare the object */\n\tif( message == MESSAGE_COMPARE )\n\t\t{\n\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\tif( messageValue == MESSAGE_COMPARE_CERTOBJ )\n\t\t\t{\n\t\t\t/* A certificate object compare passes in a certificate handle \n\t\t\t   rather than data */\n\t\t\treturn( compareCertInfo( certInfoPtr, messageValue, NULL, 0,\n\t\t\t\t\t\t\t\t\t *( ( CRYPT_CERTIFICATE * ) messageDataPtr ) ) ? \\\n\t\t\t\t\t\t\t\t\t CRYPT_OK : CRYPT_ERROR );\n\t\t\t}\n\t\treturn( compareCertInfo( certInfoPtr, messageValue, msgData->data,\n\t\t\t\t\t\t\t\t msgData->length, CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\t CRYPT_OK : CRYPT_ERROR );\n\t\t}\n\n\t/* Process messages that check a certificate */\n\tif( message == MESSAGE_CHECK )\n\t\treturn( checkCertUsage( certInfoPtr, messageValue ) );\n\n\t/* Process internal notification messages */\n\tif( message == MESSAGE_CHANGENOTIFY )\n\t\t{\n\t\t/* If the object is being accessed for cryptlib-internal use, save/\n\t\t   restore the internal state */\n\t\tif( messageValue == MESSAGE_CHANGENOTIFY_STATE )\n\t\t\t{\n\t\t\tif( messageDataPtr == MESSAGE_VALUE_TRUE )\n\t\t\t\t{\n\t\t\t\t/* Save the current volatile state so that any changes made \n\t\t\t\t   while the object is in use aren't reflected back to the \n\t\t\t\t   caller after the cryptlib-internal use has completed */\n\t\t\t\tsaveSelectionState( certInfoPtr->selectionState, \n\t\t\t\t\t\t\t\t\tcertInfoPtr );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Restore the volatile state from before the object was \n\t\t\t\t   used */\n\t\t\t\trestoreSelectionState( certInfoPtr->selectionState, \n\t\t\t\t\t\t\t\t\t   certInfoPtr );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_CRT_SIGN )\n\t\t{\n\t\tint status;\n\n\t\tREQUIRES( certInfoPtr->certificate == NULL );\n\n\t\t/* Make sure that the signing object can actually be used for \n\t\t   signing.  This could be CA signing, or general-purpose signing.  \n\t\t   first we check for CA signing capability */\n\t\tstatus = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC_SIGN_CA );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If it's something that can only be signed by a CA and this \n\t\t\t   isn't a CA key, it's an error */\n\t\t\tif( certInfoPtr->type == CRYPT_CERTTYPE_ATTRIBUTE_CERT || \\\n\t\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN || \\\n\t\t\t\tcertInfoPtr->type == CRYPT_CERTTYPE_CRL )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* Check for a general-purpose signing capability */\n\t\t\tstatus = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC_SIGN );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* This isn't available either, the only time that we can \n\t\t\t\t   use a signing object that can't sign is when we have a \n\t\t\t\t   CRMF request, which can be created with an encryption-\n\t\t\t\t   only key if the private key POP is performed via an out-\n\t\t\t\t   of-band mechanism.  If this is the case we make sure that \n\t\t\t\t   the key can decrypt, which is the other way of performing \n\t\t\t\t   POP if a signing key isn't available */\n\t\t\t\tif( certInfoPtr->type != CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t\tstatus = krnlSendMessage( messageValue, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC_DECRYPT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* We're changing data in a certificate, clear the error \n\t\t   information */\n\t\tclearErrorInfo( certInfoPtr );\n\n\t\treturn( signCert( certInfoPtr, messageValue ) );\n\t\t}\n\tif( message == MESSAGE_CRT_SIGCHECK )\n\t\t{\n\t\tREQUIRES( certInfoPtr->certificate != NULL || \\\n\t\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_RTCS_RESPONSE || \\\n\t\t\t\t  certInfoPtr->type == CRYPT_CERTTYPE_OCSP_RESPONSE );\n\n\t\t/* We're checking data in a certificate, clear the error \n\t\t   information */\n\t\tclearErrorInfo( certInfoPtr );\n\n\t\treturn( checkCertValidity( certInfoPtr, messageValue ) );\n\t\t}\n\tif( message == MESSAGE_CRT_EXPORT )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\treturn( exportCertData( certInfoPtr, messageValue, \n\t\t\t\t\t\t\t\tmsgData->data, msgData->length,\n\t\t\t\t\t\t\t\t&msgData->length ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Create a certificate object, returning a pointer to the locked \n   certificate info ready for further initialisation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificateInfo( OUT_PTR_COND CERT_INFO **certInfoPtrPtr, \n\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tCRYPT_CERTIFICATE iCertificate;\n\tCERT_INFO *certInfoPtr;\n\tOBJECT_SUBTYPE subType;\n\tint storageSize, status;\n\n\tassert( isWritePtr( certInfoPtrPtr, sizeof( CERT_INFO * ) ) );\n\n\tREQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isEnumRange( certType, CRYPT_CERTTYPE ) );\n\n\t/* Clear return value */\n\t*certInfoPtrPtr = NULL;\n\n\t/* Set up subtype-specific information */\n\tswitch( certType )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n#ifdef USE_ATTRCERT\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n#endif /* USE_ATTRCERT */\n\t\t\tsubType = ( certType == CRYPT_CERTTYPE_CERTIFICATE ) ? \\\n\t\t\t\t\t  SUBTYPE_CERT_CERT : SUBTYPE_CERT_ATTRCERT;\n\t\t\tstorageSize = sizeof( CERT_CERT_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\t/* A certificate chain is a special case of a certificate (and/\n\t\t\t   or vice versa) so it uses the same subtype-specific \n\t\t\t   storage */\n\t\t\tsubType = SUBTYPE_CERT_CERTCHAIN;\n\t\t\tstorageSize = sizeof( CERT_CERT_INFO );\n\t\t\tbreak;\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\t\tsubType = SUBTYPE_CERT_CERTREQ;\n\t\t\tstorageSize = 0;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\tsubType = ( certType == CRYPT_CERTTYPE_REQUEST_CERT ) ? \\\n\t\t\t\t\t  SUBTYPE_CERT_REQ_CERT : SUBTYPE_CERT_REQ_REV;\n\t\t\tstorageSize = sizeof( CERT_REQ_INFO );\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\tsubType = SUBTYPE_CERT_CRL;\n\t\t\tstorageSize = sizeof( CERT_REV_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\tsubType = ( certType == CRYPT_CERTTYPE_OCSP_REQUEST ) ? \\\n\t\t\t\t\t  SUBTYPE_CERT_OCSP_REQ : SUBTYPE_CERT_OCSP_RESP;\n\t\t\tstorageSize = sizeof( CERT_REV_INFO );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CMSATTR\n\t\tcase CRYPT_CERTTYPE_CMS_ATTRIBUTES:\n\t\t\tsubType = SUBTYPE_CERT_CMSATTR;\n\t\t\tstorageSize = 0;\n\t\t\tbreak;\n#endif /* USE_CMSATTR */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\tsubType = ( certType == CRYPT_CERTTYPE_RTCS_REQUEST ) ? \\\n\t\t\t\t\t  SUBTYPE_CERT_RTCS_REQ : SUBTYPE_CERT_RTCS_RESP;\n\t\t\tstorageSize = sizeof( CERT_VAL_INFO );\n\t\t\tbreak;\n#endif /* USE_CERTVAL */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\tsubType = SUBTYPE_CERT_PKIUSER;\n\t\t\tstorageSize = sizeof( CERT_PKIUSER_INFO );\n\t\t\tbreak;\n#endif /* USE_PKIUSER */\n\n\t\tdefault:\n\t\t\t/* In theory this should be a retIntError() but since some \n\t\t\t   certificate types could be disabled we return a more\n\t\t\t   conservative not-available error */\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* Create the certificate object */\n\tstatus = krnlCreateObject( &iCertificate, ( void ** ) &certInfoPtr, \n\t\t\t\t\t\t\t   sizeof( CERT_INFO ) + storageSize, \n\t\t\t\t\t\t\t   OBJECT_TYPE_CERTIFICATE, subType,\n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, iCryptOwner, \n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, \n\t\t\t\t\t\t\t   certificateMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( certInfoPtr != NULL );\n\tcertInfoPtr->objectHandle = iCertificate;\n\tcertInfoPtr->ownerHandle = iCryptOwner;\n\tcertInfoPtr->type = certType;\n\tINIT_FLAGS( certInfoPtr->flags, CERT_FLAG_NONE );\n\tDATAPTR_SET( certInfoPtr->subjectName, NULL );\n\tDATAPTR_SET( certInfoPtr->issuerName, NULL );\n\tDATAPTR_SET( certInfoPtr->attributes, NULL );\n\tDATAPTR_SET( certInfoPtr->attributeCursor, NULL );\n\tDATAPTR_SET( certInfoPtr->selectionState.savedAttributeCursor, NULL );\n\tswitch( certInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\tcertInfoPtr->cCertCert = ( CERT_CERT_INFO * ) certInfoPtr->storage;\n\t\t\tcertInfoPtr->cCertCert->chainPos = CRYPT_ERROR;\n\t\t\tcertInfoPtr->cCertCert->trustedUsage = CRYPT_ERROR;\n\t\t\tbreak;\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\tcertInfoPtr->cCertReq = ( CERT_REQ_INFO * ) certInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n\t\tcase CRYPT_CERTTYPE_CRL:\n\t\tcase CRYPT_CERTTYPE_OCSP_REQUEST:\n\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\tcertInfoPtr->cCertRev = ( CERT_REV_INFO * ) certInfoPtr->storage;\n\t\t\tDATAPTR_SET( certInfoPtr->cCertRev->revocations, NULL );\n\t\t\tDATAPTR_SET( certInfoPtr->cCertRev->currentRevocation, NULL );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n\t\tcase CRYPT_CERTTYPE_RTCS_REQUEST:\n\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\tcertInfoPtr->cCertVal = ( CERT_VAL_INFO * ) certInfoPtr->storage;\n\t\t\tDATAPTR_SET( certInfoPtr->cCertVal->validityInfo, NULL );\n\t\t\tDATAPTR_SET( certInfoPtr->cCertVal->currentValidity, NULL );\n\t\t\tbreak;\n#endif /* USE_CERTREV */\n\n#ifdef USE_PKIUSER\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\tcertInfoPtr->cCertUser = ( CERT_PKIUSER_INFO * ) certInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_PKIUSER */\n\n#ifdef USE_CERTREQ\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\t\t/* No special storage requirements */\n\t\t\tbreak;\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CMSATTR\n\t\tcase CRYPT_CERTTYPE_CMS_ATTRIBUTES:\n\t\t\t/* No special storage requirements */\n\t\t\tbreak;\n#endif /* USE_CMSATTR */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Set up the default version number.  These values are set here mostly \n\t   so that attempting to read the version attribute won't return a \n\t   version of 0.\n\n\t   In some cases this is an indication only and will be modified based \n\t   on information added to the object (for example the CRL version is \n\t   implicitly set based on whether extensions are added or not).  If this \n\t   can happen we start with the lowest version available (the default \n\t   v1) which will be automatically incremented whenever information that \n\t   can't be represented with that format version is added */\n\tswitch( certType )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\tcase CRYPT_CERTTYPE_CERTCHAIN:\n\t\t\tcertInfoPtr->version = 3;\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_ATTRIBUTE_CERT:\n\t\t\tcertInfoPtr->version = 2;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tcertInfoPtr->version = 1;\n\t\t\tbreak;\n\t\t}\n\n\t/* Set up any internal objects to contain invalid handles */\n\tcertInfoPtr->iPubkeyContext = CRYPT_ERROR;\n\n\t/* Set the state information to its initial state */\n\tinitSelectionInfo( certInfoPtr );\n\n\t/* Return the certificate information */\n\t*certInfoPtrPtr = certInfoPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificate( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo, \n\t\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\t   STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_CERTIFICATE iCertificate;\n\tCERT_INFO *certInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRange( createInfo->arg1, CRYPT_CERTTYPE ) );\n\tREQUIRES( createInfo->arg2 == 0 && createInfo->strArg1 == NULL && \\\n\t\t\t  createInfo->strArgLen1 == 0 );\n\n\t/* Pass the call on to the lower-level open function */\n\tstatus = createCertificateInfo( &certInfoPtr, createInfo->cryptOwner,\n\t\t\t\t\t\t\t\t\tcreateInfo->arg1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCertificate = certInfoPtr->objectHandle;\n\n\t/* We've finished setting up the object-type-specific info, tell the \n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCertificate, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusOK( status ) )\n\t\tcreateInfo->cryptHandle = iCertificate;\n\treturn( status );\n\t}\n\n/* Create a certificate by instantiating it from its encoded form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificateIndirect( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\t\t\t   STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_CERTIFICATE iCertificate;\n\tint status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRangeOpt( createInfo->arg1, CRYPT_CERTTYPE ) );\n\tREQUIRES( createInfo->strArg1 != NULL );\n\tREQUIRES( createInfo->strArgLen1 > 16 && \\\n\t\t\t  createInfo->strArgLen1 < MAX_INTLENGTH ); \n\t\t\t  /* May be CMS attribute (short) or a mega-CRL (long ) */\n\tREQUIRES( ( createInfo->arg2 == 0 && createInfo->strArg2 == NULL && \\\n\t\t\t\tcreateInfo->strArgLen2 == 0 ) || \\\n\t\t\t  ( ( createInfo->arg2 == CRYPT_IKEYID_KEYID || \\\n\t\t\t\t  createInfo->arg2 == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \\\n\t\t\t\tcreateInfo->strArg2 != NULL && \\\n\t\t\t\tcreateInfo->strArgLen2 > 2 && \\\n\t\t\t\tcreateInfo->strArgLen2 < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isFlagRangeZ( createInfo->arg3, KEYMGMT ) && \\\n\t\t\t  ( createInfo->arg3 & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\tREQUIRES( createInfo->arg2 == 0 || createInfo->arg3 == 0 );\n\n\t/* Pass the call through to the low-level import function */\n\tstatus = importCert( createInfo->strArg1, createInfo->strArgLen1,\n\t\t\t\t\t\t &iCertificate, createInfo->cryptOwner,\n\t\t\t\t\t\t createInfo->arg2, createInfo->strArg2, \n\t\t\t\t\t\t createInfo->strArgLen2, createInfo->arg3,\n\t\t\t\t\t\t createInfo->arg1 );\n\tif( cryptStatusOK( status ) )\n\t\tcreateInfo->cryptHandle = iCertificate;\n\treturn( status );\n\t}\n\n/* Generic management function for this class of object */\n\nCHECK_RETVAL \\\nint certManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tREQUIRES( action == MANAGEMENT_ACTION_PRE_INIT );\n\n\tswitch( action )\n\t\t{\n\t\tcase MANAGEMENT_ACTION_PRE_INIT:\n#ifndef CONFIG_FUZZ\n\t\t\tif( !sanityCheckExtensionTables() )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Certificate class initialisation failed\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n#endif /* !CONFIG_FUZZ */\n\t\t\tinitAttributes();\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Extension Blob Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get/add/delete certificate attributes */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3, 6 ) ) \\\nC_RET cryptGetCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid, \n\t\t\t\t\t\t\t C_OUT int C_PTR criticalFlag,\n\t\t\t\t\t\t\t C_OUT_OPT void C_PTR extension, \n\t\t\t\t\t\t\t C_IN int extensionMaxLength,\n\t\t\t\t\t\t\t C_OUT int C_PTR extensionLength )\n\t{\n\tCERT_INFO *certInfoPtr;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tBYTE binaryOID[ MAX_OID_SIZE + 8 ];\n\tvoid *dataPtr;\n#ifdef EBCDIC_CHARS\n\tchar asciiOID[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n#endif /* EBCDIC_CHARS */\n\tint binaryOidLen, value, dataLength, status;\n\n\t/* Perform basic parameter error checking */\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isReadPtr( oid, MIN_ASCII_OIDSIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isWritePtr( criticalFlag, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t*criticalFlag = CRYPT_ERROR;\n\tif( extension != NULL )\n\t\t{\n\t\tif( extensionMaxLength <= 4 || \\\n\t\t\textensionMaxLength >= MAX_INTLENGTH_SHORT )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\tif( !isWritePtrDynamic( extension, extensionMaxLength ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tmemset( extension, 0, min( 16, extensionMaxLength ) );\n\t\t}\n\tif( !isWritePtr( extensionLength, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM6 );\n\t*extensionLength = 0;\n\tif( strlen( oid ) < MIN_ASCII_OIDSIZE || \\\n\t\tstrlen( oid ) > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#ifdef EBCDIC_CHARS\n\tstrlcpy_s( asciiOID, CRYPT_MAX_TEXTSIZE, oid );\n\tebcdicToAscii( asciiOID, asciiOID, strlen( asciiOID ) );\n\tif( cryptStatusError( textToOID( asciiOID, strlen( asciiOID ), \n\t\t\t\t\t\t\t\t\t binaryOID, MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#else\n\tif( cryptStatusError( textToOID( oid, strlen( oid ), binaryOID, \n\t\t\t\t\t\t\t\t\t MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#endif /* EBCDIC_CHARS */\n\n\t/* Perform object error checking.  Normally this is handled by the \n\t   kernel, however since this function accesses multiple parameters and\n\t   the target isn't a cryptlib attribute we have to handle the access\n\t   ourselves here.  In order to avoid potential race conditions we \n\t   check whether the object is internal twice, once before we lock it \n\t   and again afterwards.  We perform the check by reading the locked\n\t   property attribute, which is always available */\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tstatus = krnlAcquireObject( certificate, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_PARAM1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_PROPERTY_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t}\n\n\t/* Lock the currently selected certificate in a certificate chain if \n\t   necessary */\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\tcertInfoPtr->cCertCert->chainPos >= 0 )\n\t\t{\n\t\tCERT_INFO *certChainInfoPtr;\n\n\t\tENSURES( certInfoPtr->cCertCert->chainPos >= 0 && \\\n\t\t\t\t certInfoPtr->cCertCert->chainPos < MAX_CHAINLENGTH );\n\t\tstatus = krnlAcquireObject( certInfoPtr->cCertCert->chain[ certInfoPtr->cCertCert->chainPos ], \n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certChainInfoPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_PARAM1 );\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertInfoPtr = certChainInfoPtr;\n\t\t}\n\n\t/* Locate the attribute identified by the OID and get its information */\n\tattributePtr = findAttributeByOID( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t   binaryOID, binaryOidLen );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tstatus = getBlobAttributeDataPtr( attributePtr, &dataPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( dataPtr != NULL );\n\t*criticalFlag = checkAttributeProperty( attributePtr, \n\t\t\t\t\t\t\t\t\t\t\tATTRIBUTE_PROPERTY_CRITICAL ) ? \\\n\t\t\t\t\t1 : 0;\t/* Note use of external-format BOOLEAN values */\n\tstatus = attributeCopyParams( extension, extensionMaxLength, \n\t\t\t\t\t\t\t\t  extensionLength, dataPtr, dataLength );\n\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\treturn( status );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptAddCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid, C_IN int criticalFlag,\n\t\t\t\t\t\t\t C_IN void C_PTR extension,\n\t\t\t\t\t\t\t C_IN int extensionLength )\n\t{\n\tCERT_INFO *certInfoPtr;\n\tBYTE binaryOID[ MAX_OID_SIZE + 8 ];\n#ifdef EBCDIC_CHARS\n\tchar asciiOID[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n#endif /* EBCDIC_CHARS */\n\tint binaryOidLen, value, status;\n\n\t/* Perform basic parameter error checking */\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isReadPtr( oid, MIN_ASCII_OIDSIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( extensionLength <= 4 || extensionLength > MAX_ATTRIBUTE_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\tif( !isReadPtrDynamic( extension, extensionLength ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( cryptStatusError( checkCertObjectEncoding( extension, \n\t\t\t\t\t\t\t\t\t\t\t\t   extensionLength ) ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( strlen( oid ) < MIN_ASCII_OIDSIZE || \\\n\t\tstrlen( oid ) > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#ifdef EBCDIC_CHARS\n\tstrlcpy_s( asciiOID, CRYPT_MAX_TEXTSIZE, oid );\n\tebcdicToAscii( asciiOID, asciiOID, strlen( asciiOID ) );\n\tif( cryptStatusError( textToOID( asciiOID, strlen( asciiOID ), \n\t\t\t\t\t\t\t\t\t binaryOID, MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#else\n\tif( cryptStatusError( textToOID( oid, strlen( oid ), binaryOID,\n\t\t\t\t\t\t\t\t\t MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#endif /* EBCDIC_CHARS */\n\n\t/* Perform object error checking.  Normally this is handled by the \n\t   kernel, however since this function accesses multiple parameters and\n\t   the target isn't a cryptlib attribute we have to handle the access\n\t   ourselves here.  In order to avoid potential race conditions we \n\t   check whether the object is internal twice, once before we lock it \n\t   and again afterwards.  We perform the check by reading the locked\n\t   property attribute, which is always available */\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tstatus = krnlAcquireObject( certificate, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_PARAM1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_PROPERTY_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t}\n\tif( certInfoPtr->certificate != NULL || \\\n\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\t  certInfoPtr->cCertCert->chainPos >= 0 ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\tif( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\tcriticalFlag != CRYPT_UNUSED )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t}\n\n\t/* Add the attribute to the certificate */\n\tstatus = addAttribute( \\\n\t\t\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \\\n\t\t\t\t\tATTRIBUTE_CMS : ATTRIBUTE_CERTIFICATE, \n\t\t\t\t&certInfoPtr->attributes, binaryOID, binaryOidLen,\n\t\t\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CMS_ATTRIBUTES ) ? \\\n\t\t\t\t\tFALSE : ( criticalFlag ? TRUE : FALSE ), \n\t\t\t\textension, extensionLength, 0 );\n\tif( status == CRYPT_ERROR_INITED )\n\t\t{\n\t\t/* If the attribute is already present, set error information for it.\n\t\t   We can't set an error locus since it's an unknown blob */\n\t\tsetErrorInfo( certInfoPtr, CRYPT_ATTRIBUTE_NONE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t}\n\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\treturn( status );\n\t}\n\nC_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptDeleteCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t\tC_IN char C_PTR oid )\n\t{\n\tCERT_INFO *certInfoPtr;\n\tDATAPTR_ATTRIBUTE attributePtr;\n\tBYTE binaryOID[ MAX_OID_SIZE + 8 ];\n#ifdef EBCDIC_CHARS\n\tchar asciiOID[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n#endif /* EBCDIC_CHARS */\n\tint binaryOidLen, value, status;\n\n\t/* Perform basic parameter error checking */\n\tif( !isHandleRangeValid( certificate ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isReadPtr( oid, MIN_ASCII_OIDSIZE ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( strlen( oid ) < MIN_ASCII_OIDSIZE || \\\n\t\tstrlen( oid ) > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#ifdef EBCDIC_CHARS\n\tstrlcpy_s( asciiOID, CRYPT_MAX_TEXTSIZE, oid );\n\tebcdicToAscii( asciiOID, asciiOID, strlen( asciiOID ) );\n\tif( cryptStatusError( textToOID( asciiOID, strlen( asciiOID ), \n\t\t\t\t\t\t\t\t\t binaryOID, MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#else\n\tif( cryptStatusError( textToOID( oid, strlen( oid ), binaryOID,\n\t\t\t\t\t\t\t\t\t MAX_OID_SIZE, &binaryOidLen ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n#endif /* EBCDIC_CHARS */\n\n\t/* Perform object error checking.  Normally this is handled by the \n\t   kernel, however since this function accesses multiple parameters and\n\t   the target isn't a cryptlib attribute we have to handle the access\n\t   ourselves here.  In order to avoid potential race conditions we \n\t   check whether the object is internal twice, once before we lock it \n\t   and again afterwards.  We perform the check by reading the locked\n\t   property attribute, which is always available */\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tstatus = krnlAcquireObject( certificate, OBJECT_TYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &certInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_PARAM1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( certificate, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_PROPERTY_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t}\n\tif( certInfoPtr->certificate != NULL || \\\n\t\t( certInfoPtr->type == CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\t  certInfoPtr->cCertCert->chainPos >= 0 ) )\n\t\t{\n\t\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Find the attribute identified by the OID and delete it */\n\tattributePtr = findAttributeByOID( certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t\t   binaryOID, binaryOidLen );\n\tif( DATAPTR_ISNULL( attributePtr ) )\n\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\telse\n\t\t{\n\t\tDATAPTR_DN dnDummy;\n\n\t\t/* Since a blob attribute doesn't have any internal structure,\n\t\t   there's no possibility of a DN being associated with it, so we\n\t\t   pass in a dummy null DN reference */\n\t\tDATAPTR_SET( dnDummy, NULL );\n\t\t( void ) deleteAttribute( &certInfoPtr->attributes, \n\t\t\t\t\t\t\t\t  &certInfoPtr->attributeCursor, \n\t\t\t\t\t\t\t\t  attributePtr, &dnDummy );\n\t\t}\n\tkrnlReleaseObject( certInfoPtr->objectHandle );\n\treturn( status );\n\t}\n\n#elif defined( USE_PSEUDOCERTIFICATES )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPseudo-Certificate Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions to deal with pseudo-certificates, basic certificate-like \n   objects that serve purely as containers for encoded certificate data,\n   and as targets for kernel messages for protocols like SSL/TLS and\n   CMS/PKCS #7 that require the use of certificate objects */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int certificateMessageFunction( INOUT TYPECAST( CERT_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t   void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t   IN_INT_Z const int messageValue )\n\t{\n\tCERT_INFO *certInfoPtr = ( CERT_INFO * ) objectInfoPtr;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( CERT_INFO ) ) );\n\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( ( message == MESSAGE_CRT_SIGCHECK && \\\n\t\t\t\tmessageValue == CRYPT_UNUSED ) || \\\n\t\t\t  isIntegerRange( messageValue ) );\n\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* Clear the encoded certificate if necessary.  This is the only \n\t\t   certificate component that's used for pseudo-certificates */\n\t\tif( certInfoPtr->certificate != NULL )\n\t\t\t{\n\t\t\tzeroise( certInfoPtr->certificate, certInfoPtr->certificateSize );\n\t\t\tclFree( \"certificateMessageFunction\", certInfoPtr->certificate );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t{\n\t\tint *valuePtr = ( int * ) messageDataPtr;\n\n\t\t/* Used to perform basic object checks on pseudo-certificates */\n\t\tif( messageValue == CRYPT_CERTINFO_IMMUTABLE )\n\t\t\t{\n\t\t\t*valuePtr = TRUE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( messageValue == CRYPT_CERTINFO_CERTTYPE )\n\t\t\t{\n\t\t\t*valuePtr = CRYPT_CERTTYPE_CERTIFICATE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t{\n\t\t/* Needed to handle object initialisation */\n\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\tif( message == MESSAGE_CHECK )\n\t\t{\n\t\t/* Needed to handle making a certificate a dependent object of a \n\t\t   private key */\n\t\tif( messageValue == MESSAGE_CHECK_PKC_SIGN_AVAIL || \\\n\t\t\tmessageValue == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL || \\\n\t\t\tmessageValue == MESSAGE_CHECK_PKC_ENCRYPT_AVAIL || \\\n\t\t\tmessageValue == MESSAGE_CHECK_PKC_DECRYPT_AVAIL )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Needed to handle checking of private keys with certificates \n\t\t   attached */\n\t\tif( messageValue == MESSAGE_CHECK_PKC_PRIVATE || \\\n\t\t\tmessageValue == MESSAGE_CHECK_PKC_DECRYPT || \\\n\t\t\tmessageValue == MESSAGE_CHECK_PKC_SIGN )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Needed to handle general certificate health checks */\n\t\tif( messageValue == MESSAGE_CHECK_CERT )\n\t\t\treturn( CRYPT_OK );\n\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\tif( message == MESSAGE_CRT_EXPORT )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\treturn( attributeCopy( msgData, certInfoPtr->certificate, \n\t\t\t\t\t\t\t   certInfoPtr->certificateSize ) );\n\t\t}\n\n\t/* Nothing else is handled */\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n/* Create a certificate by instantiating it from its encoded form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificateIndirect( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\t\t\t   STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_CERTIFICATE iCertificate;\n\tCERT_INFO *certInfoPtr;\n\tvoid *certBuffer;\n\tint status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRangeOpt( createInfo->arg1, CRYPT_CERTTYPE ) );\n\tREQUIRES( createInfo->strArg1 != NULL );\n\tREQUIRES( createInfo->strArgLen1 > 16 && \\\n\t\t\t  createInfo->strArgLen1 < MAX_INTLENGTH ); \n\t\t\t  /* May be CMS attribute (short) or a mega-CRL (long ) */\n\tREQUIRES( createInfo->arg2 == 0 && createInfo->strArg2 == NULL && \\\n\t\t\t  createInfo->strArgLen2 == 0 );\t/* keyID */\n\tREQUIRES( isFlagRangeZ( createInfo->arg3, KEYMGMT ) && \\\n\t\t\t  ( createInfo->arg3 & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\tREQUIRES( createInfo->arg2 == 0 || createInfo->arg3 == 0 );\n\n\t/* Allocate a buffer for the encoded certificate data and create and \n\t   initialise the certificate object associated with it */\n\tREQUIRES( rangeCheck( createInfo->strArgLen1, \n\t\t\t\t\t\t  16 + 1, MAX_INTLENGTH - 1 ) );\n\tif( ( certBuffer = clAlloc( \"createCertificateIndirect\", \n\t\t\t\t\t\t\t\tcreateInfo->strArgLen1 ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tstatus = krnlCreateObject( &iCertificate, ( void ** ) &certInfoPtr, \n\t\t\t\t\t\t\t   sizeof( CERT_INFO ) + sizeof( CERT_CERT_INFO ), \n\t\t\t\t\t\t\t   OBJECT_TYPE_CERTIFICATE, SUBTYPE_CERT_CERT,\n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, \n\t\t\t\t\t\t\t   DEFAULTUSER_OBJECT_HANDLE, ACTION_PERM_NONE_ALL, \n\t\t\t\t\t\t\t   certificateMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"createCertificateIndirect\", certBuffer );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( certInfoPtr != NULL );\n\tcertInfoPtr->objectHandle = iCertificate;\n\tcertInfoPtr->ownerHandle = DEFAULTUSER_OBJECT_HANDLE;\n\tcertInfoPtr->type = CRYPT_CERTTYPE_CERTIFICATE;\n\tcertInfoPtr->cCertCert = ( CERT_CERT_INFO * ) certInfoPtr->storage;\n\tcertInfoPtr->cCertCert->chainPos = CRYPT_ERROR;\n\tcertInfoPtr->cCertCert->trustedUsage = CRYPT_ERROR;\n\tcertInfoPtr->iPubkeyContext = CRYPT_ERROR;\n\tcertInfoPtr->flags |= CERT_FLAG_DATAONLY;\n\tDATAPTR_SET( certInfoPtr->subjectName, NULL );\n\tDATAPTR_SET( certInfoPtr->issuerName, NULL );\n\tinitSelectionInfo( certInfoPtr );\n\n\t/* Copy in the certificate object for later use */\n\tmemcpy( certBuffer, createInfo->strArg1, createInfo->strArgLen1 );\n\tcertInfoPtr->certificate = certBuffer;\n\tcertInfoPtr->certificateSize = createInfo->strArgLen1;\n\n\t/* We've finished setting up the object-type-specific information, tell \n\t   the kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCertificate, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tcreateInfo->cryptHandle = iCertificate;\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/cryptctx.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Encryption Context Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* \"Modern cryptography is nothing more than a mathematical framework for\n\tdebating the implications of various paranoid delusions\"\n\t\t\t\t\t\t\t\t\t\t\t\t- Don Alvarez */\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"context.h\"\n  #include \"asn1.h\"\n#else\n  #include \"context/context.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n/* When we're allocating subtype-specific data to be stored alongside the\n   main CONTEXT_INFO, we align it to a certain block size both for efficient\n   access and to ensure that the pointer to it from the main CONTEXT_INFO\n   doesn't result in a segfault.  The following works for all current \n   processor types */\n\n#define STORAGE_ALIGN_SIZE\t8\n#define CONTEXT_INFO_ALIGN_SIZE\t\\\n\t\troundUp( sizeof( CONTEXT_INFO ), STORAGE_ALIGN_SIZE )\n#define ALIGN_CONTEXT_PTR( basePtr, type ) \\\n\t\t( type * ) ( ( BYTE * ) ( basePtr ) + CONTEXT_INFO_ALIGN_SIZE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check context data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkDataItem( IN_BUFFER( dataLen ) const void *data, \n\t\t\t\t\t\t\t  IN const int dataLen,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) const int dataMaxLen )\n\t{\n\tassert( isReadPtr( data, dataLen ) );\n\n\tREQUIRES_B( dataMaxLen >= 8 && dataMaxLen <= MAX_INTLENGTH_SHORT );\n\n\t/* If there's no data present, we're done */\n\tif( isEmptyData( data, dataLen ) )\n\t\treturn( TRUE );\n\n\t/* Check that the data length is within the allowed range */\n\tif( dataLen <= 0 || dataLen > dataMaxLen ) \n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckContext( const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* Check general context data */\n\tif( !isEnumRange( contextInfoPtr->type, CONTEXT ) || \\\n\t\t!CHECK_FLAGS( contextInfoPtr->flags, CONTEXT_FLAG_NONE, \n\t\t\t\t\t  CONTEXT_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContext: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( contextInfoPtr->capabilityInfo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckCert: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check associated handles */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_STATICCONTEXT ) )\n\t\t{\n\t\tif( contextInfoPtr->objectHandle != 0 || \\\n\t\t\tcontextInfoPtr->ownerHandle != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Spurious object handles\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isHandleRangeValid( contextInfoPtr->objectHandle ) || \\\n\t\t\t!( contextInfoPtr->ownerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t   isHandleRangeValid( contextInfoPtr->ownerHandle ) ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Object handles\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check subtype-specific data */\n\tswitch( contextInfoPtr->type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\t{\n\t\t\tconst CONV_INFO *convInfo;\n\n\t\t\t/* Check context info storage.  See the discussion in \n\t\t\t   initContextStorage() for why we check for only 8- and 16-byte \n\t\t\t   alignment */\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_STATICCONTEXT ) )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxConv != \\\n\t\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, CONV_INFO ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto context storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tconvInfo = contextInfoPtr->ctxConv;\n\t\t\t\tif( convInfo->key != \\\n\t\t\t\t\t\tptr_align( ( BYTE * ) convInfo + sizeof( CONV_INFO ), 8 ) && \\\n\t\t\t\t\tconvInfo->key != \\\n\t\t\t\t\t\tptr_align( ( BYTE * ) convInfo + sizeof( CONV_INFO ), 16 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto context key storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Statically-initialised contexts don't have the subtype-\n\t\t\t\t   specific information contiguous with the main context \n\t\t\t\t   storage, but still need to have aligned key storage \n\t\t\t\t   memory */\n\t\t\t\tconvInfo = contextInfoPtr->ctxConv;\n\t\t\t\tif( convInfo->key != ptr_align( convInfo->key, 8 ) && \\\n\t\t\t\t\tconvInfo->key != ptr_align( convInfo->key, 16 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto context key storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tassert( isReadPtr( convInfo, sizeof( CONV_INFO ) ) );\n\n\t\t\t/* Check general conventional-context data.  The encryption mode\n\t\t\t   can be CRYPT_MODE_NONE until it's explicitly set */\n\t\t\tif( !isEnumRangeOpt( convInfo->mode, CRYPT_MODE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto mode\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Check key and IV data */\n\t\t\tif( !checkDataItem( convInfo->userKey, convInfo->userKeyLength, \n\t\t\t\t\t\t\t\tCRYPT_MAX_KEYSIZE ) || \\\n\t\t\t\t!checkDataItem( convInfo->iv, convInfo->ivLength, \n\t\t\t\t\t\t\t\tCRYPT_MAX_IVSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto key/IV\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Check PRF data */\n\t\t\tif( !checkDataItem( convInfo->salt, convInfo->saltLength,\n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto salt\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( convInfo->keySetupIterations < 0 || \\\n\t\t\t\tconvInfo->keySetupIterations > MAX_KEYSETUP_ITERATIONS )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto key setup iterations\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( convInfo->keySetupAlgorithm != CRYPT_ALGO_NONE && \\\n\t\t\t\t!isHashAlgo( convInfo->keySetupAlgorithm ) && \\\n\t\t\t\t!isMacAlgo( convInfo->keySetupAlgorithm ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Crypto key setup algorithm\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTEXT_PKC:\n\t\t\t{\n\t\t\tconst PKC_INFO *pkcInfo;\n\n\t\t\t/* Check context info storage */\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_STATICCONTEXT ) )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxPKC != \\\n\t\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, PKC_INFO ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: PKC context storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tpkcInfo = contextInfoPtr->ctxPKC;\n\n\t\t\tassert( isReadPtr( pkcInfo, sizeof( PKC_INFO ) ) );\n\n\t\t\t/* The PKC info is sufficiently complex that it has its own\n\t\t\t   checking function */\n\t\t\tif( !sanityCheckPKCInfo( pkcInfo ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: PKC info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTEXT_HASH:\n\t\t\t{\n\t\t\tconst HASH_INFO *hashInfo;\n\n\t\t\t/* Check context info storage */\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_STATICCONTEXT ) )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxHash != \\\n\t\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, HASH_INFO ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Hash context storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\thashInfo = contextInfoPtr->ctxHash;\n\t\t\t\tif( hashInfo->hashInfo != \\\n\t\t\t\t\t\tptr_align( ( BYTE * ) hashInfo + sizeof( HASH_INFO ), 8 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Hash context state storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Statically-initialised contexts don't have the subtype-\n\t\t\t\t   specific information contiguous with the main context \n\t\t\t\t   storage, but still need to have aligned key storage \n\t\t\t\t   memory */\n\t\t\t\thashInfo = contextInfoPtr->ctxHash;\n\t\t\t\tif( hashInfo->hashInfo != ptr_align( hashInfo->hashInfo, 8 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Hash context state storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tassert( isReadPtr( hashInfo, sizeof( HASH_INFO ) ) );\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTEXT_MAC:\n\t\t\t{\n\t\t\tconst MAC_INFO *macInfo;\n\n\t\t\t/* Check context info storage */\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_STATICCONTEXT ) )\n\t\t\t\t{\n\t\t\t\tif( contextInfoPtr->ctxMAC != \\\n\t\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, MAC_INFO ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC context storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tmacInfo = contextInfoPtr->ctxMAC;\n\t\t\t\tif( macInfo->macInfo != \\\n\t\t\t\t\t\tptr_align( ( BYTE * ) macInfo + sizeof( MAC_INFO ), 8 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC context state storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Statically-initialised contexts don't have the subtype-\n\t\t\t\t   specific information contiguous with the main context \n\t\t\t\t   storage, but still need to have aligned key storage \n\t\t\t\t   memory */\n\t\t\t\tmacInfo = contextInfoPtr->ctxMAC;\n\t\t\t\tif( macInfo->macInfo != ptr_align( macInfo->macInfo, 8 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC context state storage\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tassert( isReadPtr( macInfo, sizeof( MAC_INFO ) ) );\n\n\t\t\t/* Check key data */\n\t\t\tif( !checkDataItem( macInfo->userKey, macInfo->userKeyLength, \n\t\t\t\t\t\t\t\tCRYPT_MAX_KEYSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC key\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Check PRF data */\n\t\t\tif( !checkDataItem( macInfo->salt, macInfo->saltLength, \n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC salt\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( macInfo->keySetupIterations < 0 || \\\n\t\t\t\tmacInfo->keySetupIterations > MAX_KEYSETUP_ITERATIONS )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC key setup iterations\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( macInfo->keySetupAlgorithm != CRYPT_ALGO_NONE && \\\n\t\t\t\t( macInfo->keySetupAlgorithm < CRYPT_ALGO_FIRST_MAC || \\\n\t\t\t\t  macInfo->keySetupAlgorithm > CRYPT_ALGO_LAST_MAC ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: MAC key setup algorithm\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\t{\n\t\t\tconst GENERIC_INFO *genericInfo;\n\n\t\t\t/* Check context info storage */\n\t\t\tif( contextInfoPtr->ctxGeneric != \\\n\t\t\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, GENERIC_INFO ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Generic context storage\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tgenericInfo = contextInfoPtr->ctxGeneric;\n\n\t\t\tassert( isReadPtr( genericInfo, sizeof( GENERIC_INFO ) ) );\n\n\t\t\t/* Check key data */\n\t\t\tif( !checkDataItem( genericInfo->genericSecret, \n\t\t\t\t\t\t\t\tgenericInfo->genericSecretLength, \n\t\t\t\t\t\t\t\tCRYPT_MAX_KEYSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Generic secret\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Check KDF data */\n\t\t\tif( !checkDataItem( genericInfo->kdfParams, \n\t\t\t\t\t\t\t\tgenericInfo->kdfParamSize,\n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE ) || \\\n\t\t\t\t!checkDataItem( genericInfo->encAlgoParams, \n\t\t\t\t\t\t\t\tgenericInfo->encAlgoParamSize, \n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE ) || \\\n\t\t\t\t!checkDataItem( genericInfo->macAlgoParams, \n\t\t\t\t\t\t\t\tgenericInfo->macAlgoParamSize, \n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckContext: Generic secret parameters\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that context function pointers have been set up correctly */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkContextFunctions( IN const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* We can't call sanityCheckContext() at this point because the storage\n\t   for the context data that we want to sanity-check hasn't been set\n\t   up yet.  The best that we can do is perform a subset of the standard\n\t   sanity checks */ \n\n\tswitch( contextInfoPtr->type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->loadKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->generateKeyFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->encryptFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->decryptFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_PKC:\n\t\t\t{\n\t\t\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\n\t\t\t/* Get the capability info for the context */\n\t\t\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\t\t\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->loadKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->generateKeyFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tswitch( capabilityInfoPtr->cryptAlgo )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\t\t/* RSA can get a bit complicated because the same \n\t\t\t\t\t   operation is used for both sign/verify and decrypt/\n\t\t\t\t\t   encrypt, and if the context doesn't support \n\t\t\t\t\t   encryption (for example because it's tied to a \n\t\t\t\t\t   signing-only hardware device) then the absence of an \n\t\t\t\t\t   encrypt/decrypt capability isn't an error */\n\t\t\t\t\tif( !( FNPTR_ISSET( contextInfoPtr->encryptFunction ) && \\\n\t\t\t\t\t\t   FNPTR_ISSET( contextInfoPtr->decryptFunction ) ) && \\\n\t\t\t\t\t\t!( capabilityInfoPtr->signFunction != NULL && \\\n\t\t\t\t\t\t   capabilityInfoPtr->sigCheckFunction != NULL ) )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t\t\tif( capabilityInfoPtr->signFunction == NULL || \\\n\t\t\t\t\t\tcapabilityInfoPtr->sigCheckFunction == NULL )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif( !FNPTR_ISSET( contextInfoPtr->encryptFunction ) || \\\n\t\t\t\t\t\t!FNPTR_ISSET( contextInfoPtr->decryptFunction ) )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->ctxPKC->writePublicKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->ctxPKC->writePrivateKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->ctxPKC->readPublicKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->ctxPKC->readPrivateKeyFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTEXT_HASH:\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->encryptFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->decryptFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_MAC:\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->loadKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->generateKeyFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->encryptFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->decryptFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\tif( !FNPTR_ISSET( contextInfoPtr->loadKeyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( contextInfoPtr->generateKeyFunction ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Perform any context-specific checks that a context meets the given \n   requirements (general checks have already been performed by the kernel).  \n   Although these checks are automatically performed by the kernel when we \n   try and use the context, they're duplicated here to allow for better \n   error reporting by catching problems when the context is first passed to \n   a cryptlib function rather than much later and at a lower level when the \n   kernel disallows the action */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkContext( INOUT CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t IN_ENUM( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\tconst MESSAGE_CHECK_TYPE checkType )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isEnumRange( checkType, MESSAGE_CHECK ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If it's a check that an object's ready for key generation then we can \n\t   perform the check without requiring any algorithm-specific \n\t   gyrations */\n\tif( checkType == MESSAGE_CHECK_KEYGEN_READY )\n\t\t{\n\t\t/* Make sure that there isn't already a key loaded */\n\t\tif( !needsKey( contextInfoPtr ) )\n\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\t/* Make sure that we can actually generate a key.  This should be\n\t\t   enforced by the kernel anyway but we use a backup check here */\n\t\tif( capabilityInfoPtr->generateKeyFunction == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a check for the (potential) ability to perform conventional \n\t   encryption or MACing at some point in the future, without necessarily \n\t   currently having a key loaded for the task, we're done */\n\tif( checkType == MESSAGE_CHECK_CRYPT_READY || \\\n\t\tcheckType == MESSAGE_CHECK_MAC_READY )\n\t\treturn( CRYPT_OK );\n\n\t/* Perform general checks */\n\tif( contextInfoPtr->type != CONTEXT_HASH && needsKey( contextInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* If it's a hash, MAC, conventional encryption, or basic PKC check, \n\t   we're done */\n\tif( checkType == MESSAGE_CHECK_CRYPT || \\\n\t\tcheckType == MESSAGE_CHECK_HASH || \\\n\t\tcheckType == MESSAGE_CHECK_MAC || \\\n\t\tcheckType == MESSAGE_CHECK_PKC )\n\t\treturn( CRYPT_OK );\n\n\t/* Check for key-agreement algorithms */\n\tif( isKeyxAlgo( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\t/* (EC)DH can never be used for encryption or signatures (if it is \n\t\t   then we call it Elgamal).  Note that the status of (EC)DH is a \n\t\t   bit ambiguous in that every (EC)DH key is both a public and \n\t\t   private key, in order to avoid confusion in situations where \n\t\t   we're checking for real private keys we always denote a (EC)DH \n\t\t   context as key-agreement only without taking a side about \n\t\t   whether it's a public or private key */\n\t\treturn( ( checkType == MESSAGE_CHECK_PKC_KA_EXPORT || \\\n\t\t\t\t  checkType == MESSAGE_CHECK_PKC_KA_IMPORT ) ? \\\n\t\t\t\tCRYPT_OK : CRYPT_ARGERROR_OBJECT );\n\t\t}\n\tif( checkType == MESSAGE_CHECK_PKC_KA_EXPORT || \\\n\t\tcheckType == MESSAGE_CHECK_PKC_KA_IMPORT )\n\t\t{\n\t\t/* A key agreement check requires a key agreement algorithm */\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\t/* We're down to various public-key checks */\n\tREQUIRES( checkType == MESSAGE_CHECK_PKC_PRIVATE || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_ENCRYPT || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_DECRYPT || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_SIGCHECK || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_SIGN || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_SIGCHECK_CA || \\\n\t\t\t  checkType == MESSAGE_CHECK_PKC_SIGN_CA || \\\n\t\t\t  checkType == MESSAGE_CHECK_CERT );\n\n\t/* Check that it's a private key if this is required */\n\tif( ( checkType == MESSAGE_CHECK_PKC_PRIVATE || \\\n\t\t  checkType == MESSAGE_CHECK_PKC_DECRYPT || \\\n\t\t  checkType == MESSAGE_CHECK_PKC_SIGN ) && \\\n\t\tTEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process an attribute compare message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processCompareMessage( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_COMPARE ) \\\n\t\t\t\t\t\t\t\t\t\tconst MESSAGE_COMPARE_TYPE message,\n\t\t\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( data, dataLength ) );\n\n\tREQUIRES( message == MESSAGE_COMPARE_HASH || \\\n\t\t\t  message == MESSAGE_COMPARE_ICV || \\\n\t\t\t  message == MESSAGE_COMPARE_KEYID || \\\n\t\t\t  message == MESSAGE_COMPARE_KEYID_PGP || \\\n\t\t\t  message == MESSAGE_COMPARE_KEYID_OPENPGP );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( message )\n\t\t{\n\t\tcase MESSAGE_COMPARE_HASH:\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_HASH || \\\n\t\t\t\t\t  contextInfoPtr->type == CONTEXT_MAC  );\n\n\t\t\t/* If it's a hash or MAC context, compare the hash value */\n\t\t\tif( !TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\tCONTEXT_FLAG_HASH_DONE ) )\n\t\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t\tif( contextInfoPtr->type == CONTEXT_HASH )\n\t\t\t\t{\n\t\t\t\tif( dataLength == capabilityInfoPtr->blockSize && \\\n\t\t\t\t\tcompareDataConstTime( data, contextInfoPtr->ctxHash->hash,\n\t\t\t\t\t\t\t\t\t\t  dataLength ) )\n\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( contextInfoPtr->type == CONTEXT_MAC )\n\t\t\t\t{\n\t\t\t\tif( dataLength == capabilityInfoPtr->blockSize && \\\n\t\t\t\t\tcompareDataConstTime( data, contextInfoPtr->ctxMAC->mac,\n\t\t\t\t\t\t\t\t\t\t  dataLength ) )\n\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase MESSAGE_COMPARE_ICV:\n\t\t\t{\n\t\t\tBYTE icv[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\t\tint status;\n\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\n\t\t\tif( contextInfoPtr->ctxConv->mode != CRYPT_MODE_GCM )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_ICV, \n\t\t\t\t\t\t\t\t\tcontextInfoPtr, icv, dataLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( compareDataConstTime( data, icv, dataLength ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase MESSAGE_COMPARE_KEYID:\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\n\t\t\t/* If it's a PKC context, compare the key ID */\n\t\t\tif( dataLength == KEYID_SIZE && \\\n\t\t\t\t!memcmp( data, contextInfoPtr->ctxPKC->keyID,\n\t\t\t\t\t\t KEYID_SIZE ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tbreak;\n\n#ifdef USE_PGP\n\t\tcase MESSAGE_COMPARE_KEYID_PGP:\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\n\t\t\t/* If it's a PKC context, compare the PGP key ID */\n\t\t\tif( TEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t\t   PKCINFO_FLAG_PGPKEYID_SET ) && \\\n\t\t\t\tdataLength == PGP_KEYID_SIZE && \\\n\t\t\t\t!memcmp( data, contextInfoPtr->ctxPKC->pgp2KeyID,\n\t\t\t\t\t\t PGP_KEYID_SIZE ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tbreak;\n\n\t\tcase MESSAGE_COMPARE_KEYID_OPENPGP:\n\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_PKC );\n\n\t\t\t/* If it's a PKC context, compare the OpenPGP key ID */\n\t\t\tif( TEST_FLAG( contextInfoPtr->ctxPKC->flags, \n\t\t\t\t\t\t   PKCINFO_FLAG_OPENPGPKEYID_SET ) && \\\n\t\t\t\tdataLength == PGP_KEYID_SIZE && \\\n\t\t\t\t!memcmp( data, contextInfoPtr->ctxPKC->openPgpKeyID,\n\t\t\t\t\t\t PGP_KEYID_SIZE ) )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* The comparison failed */\n\treturn( CRYPT_ERROR );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInternal Context Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a context can perform a certain operation.  This is used\n   frequently enough that it's implemented as a dedicated function, wrapping\n   krnlSendMessage() */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkContextCapability( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\t\t\tconst MESSAGE_CHECK_TYPE checkType )\n\t{\n\tint status;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES_B( isEnumRange( checkType, MESSAGE_CHECK ) );\n\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL, \n\t\t\t\t\t\t\t  checkType );\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tContext Storage Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Fix up potential alignment issues arising from the cloning of contexts */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int fixupContextStorage( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\tvoid *typeStorage, \n\t\t\t\t\t\t\t\tconst void *subtypeStorage,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int originalOffset,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int storageAlignSize )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint newOffset, stateStorageSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( sanityCheckContext( contextInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( originalOffset ) );\n\tREQUIRES( storageAlignSize > 0 && storageAlignSize < 128 );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Check whether the keying data offset has changed from the original to\n\t   the cloned context */\n\tnewOffset = ptr_diff( subtypeStorage, typeStorage );\n\tif( newOffset == originalOffset )\n\t\treturn( CRYPT_OK );\n\n\t/* The start of the context subtype data within the context memory block \n\t   has changed due to the cloned memory block starting at a different \n\t   offset, so we need to move the subtype data do its new location */\n\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATESIZE,\n\t\t\t\t\t\t\t\t\t\t\t\t NULL, &stateStorageSize, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmemmove( ( BYTE * ) typeStorage + newOffset, \n\t\t\t ( BYTE * ) typeStorage + originalOffset, stateStorageSize );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise pointers to context-specific storage areas */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initContextStorage( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int storageAlignSize )\n\t{\n\tint offset = 0;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* We can't call sanityCheckContext() at this point because the storage\n\t   for the context data that we want to sanity-check hasn't been set\n\t   up yet.  The best that we can do is perform a subset of the standard\n\t   sanity checks */ \n\tREQUIRES( isEnumRange( contextInfoPtr->type, CONTEXT ) && \\\n\t\t\t  CHECK_FLAGS( contextInfoPtr->flags, CONTEXT_FLAG_NONE, \n\t\t\t\t\t\t   CONTEXT_FLAG_MAX ) );\n\tREQUIRES( ( contextInfoPtr->type == CONTEXT_PKC && \\\n\t\t\t\tstorageAlignSize == 0 ) || \\\n\t\t\t  ( ( contextInfoPtr->type == CONTEXT_HASH || \\\n\t\t\t\t  contextInfoPtr->type == CONTEXT_MAC || \\\n\t\t\t\t  contextInfoPtr->type == CONTEXT_GENERIC ) && \\\n\t\t\t\tstorageAlignSize == 8 ) || \\\n\t\t\t  ( contextInfoPtr->type == CONTEXT_CONV && \\\n\t\t\t\t( storageAlignSize == 8 || storageAlignSize == 16 ) ) );\n\t\t\t  /* The storage alignment size defaults to 8 bytes, currently\n\t\t\t     the only other used value is 16 bytes for AES hardware */\n\n\t/* This function is used to initialise both pristine and cloned \n\t   contexts.  If it's the latter then the cloning operation may have \n\t   moved the relative position of the key data around in memory, since \n\t   the granularity of its allocation differs from that of the memory \n\t   allocator.  To handle this we use the following pattern:\n\n\t\tRemember the old offset of the context subtype data from the \n\t\t\tcontext type data.\n\t\tSet up the context type and subtype data pointers.\n\t\tIf this is a cloned context and the new offset of the context \n\t\t\tsubtype data differs from the old one, fix up any alignment \n\t\t\tissues */\n\tswitch( contextInfoPtr->type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\t/* Remember the offset of the subtype data from the type data */\n\t\t\tif( contextInfoPtr->ctxConv != NULL )\n\t\t\t\t{\n\t\t\t\toffset = ptr_diff( contextInfoPtr->ctxConv->key, \n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxConv );\n\t\t\t\t}\n\n\t\t\t/* Calculate the offsets of the context storage and keying \n\t\t\t   data */\n\t\t\tcontextInfoPtr->ctxConv = \\\n\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, CONV_INFO );\n\t\t\tcontextInfoPtr->ctxConv->key = \\\n\t\t\t\t\tptr_align( ( BYTE * ) contextInfoPtr->ctxConv + sizeof( CONV_INFO ), \n\t\t\t\t\t\t\t   storageAlignSize );\n\n\t\t\t/* If this is a new context, we're done */\n\t\t\tif( offset == 0 )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* It's a cloned context, fix up any potential alignment-\n\t\t\t   related issues */\n\t\t\treturn( fixupContextStorage( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxConv, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxConv->key,\n\t\t\t\t\t\t\t\t\t\t offset, storageAlignSize ) );\n\n\t\tcase CONTEXT_HASH:\n\t\t\t/* Remember the offset of the subtype data from the type data */\n\t\t\tif( contextInfoPtr->ctxHash != NULL )\n\t\t\t\t{\n\t\t\t\toffset = ptr_diff( contextInfoPtr->ctxHash->hashInfo,\n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxHash );\n\t\t\t\t}\n\n\t\t\t/* Calculate the offsets of the context storage and hash state \n\t\t\t   data */\n\t\t\tcontextInfoPtr->ctxHash = \\\n\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, HASH_INFO );\n\t\t\tcontextInfoPtr->ctxHash->hashInfo = \\\n\t\t\t\t\tptr_align( ( BYTE * ) contextInfoPtr->ctxHash + sizeof( HASH_INFO ), \n\t\t\t\t\t\t\t   storageAlignSize );\n\n\t\t\t/* If this is a new context, we're done */\n\t\t\tif( offset == 0 )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* It's a cloned context, fix up any potential alignment-\n\t\t\t   related issues */\n\t\t\treturn( fixupContextStorage( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxHash, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxHash->hashInfo,\n\t\t\t\t\t\t\t\t\t\t offset, storageAlignSize ) );\n\n\t\tcase CONTEXT_MAC:\n\t\t\t/* Remember the offset of the subtype data from the type data */\n\t\t\tif( contextInfoPtr->ctxMAC != NULL )\n\t\t\t\t{\n\t\t\t\toffset = ptr_diff( contextInfoPtr->ctxMAC->macInfo,\n\t\t\t\t\t\t\t\t   contextInfoPtr->ctxMAC );\n\t\t\t\t}\n\n\t\t\t/* Calculate the offsets of the context storage and MAC state \n\t\t\t   data */\n\t\t\tcontextInfoPtr->ctxMAC = \\\n\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, MAC_INFO );\n\t\t\tcontextInfoPtr->ctxMAC->macInfo = \\\n\t\t\t\t\tptr_align( ( BYTE * ) contextInfoPtr->ctxMAC + sizeof( MAC_INFO ), \n\t\t\t\t\t\t\t   storageAlignSize );\n\n\t\t\t/* If this is a new context, we're done */\n\t\t\tif( offset == 0 )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* It's a cloned context, fix up any potential alignment-\n\t\t\t   related issues */\n\t\t\treturn( fixupContextStorage( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxMAC, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->ctxMAC->macInfo,\n\t\t\t\t\t\t\t\t\t\t offset, storageAlignSize ) );\n\n\t\tcase CONTEXT_PKC:\n\t\t\tcontextInfoPtr->ctxPKC = \\\n\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, PKC_INFO );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\tcontextInfoPtr->ctxGeneric = \\\n\t\t\t\t\tALIGN_CONTEXT_PTR( contextInfoPtr, GENERIC_INFO );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tContext Message Handler\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle a message sent to an encryption context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int contextMessageFunction( INOUT TYPECAST( CONTEXT_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t   void *messageDataPtr,\n\t\t\t\t\t\t\t\t   IN_INT_Z const int messageValue )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCONTEXT_INFO *contextInfoPtr = ( CONTEXT_INFO * ) objectInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  ( message == MESSAGE_CHANGENOTIFY && \\\n\t\t\t    messageValue == MESSAGE_CHANGENOTIFY_OBJHANDLE ) || \\\n\t\t\t  sanityCheckContext( contextInfoPtr ) );\n\t\t\t  /* MESSAGE_CHANGENOTIFY_OBJHANDLE is sent after an object \n\t\t\t     clone operation before the internal state pointers have\n\t\t\t\t been corrected from the original to the cloned object */\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isIntegerRange( messageValue ) );\n\n\t/* Get the capability info for the context */\n\tcapabilityInfoPtr = DATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Process destroy object messages */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\tconst CONTEXT_TYPE contextType = contextInfoPtr->type;\n\n\t\tREQUIRES( messageDataPtr == NULL && messageValue == 0 );\n\n\t\t/* Perform any algorithm-specific shutdown */\n\t\tif( capabilityInfoPtr->endFunction != NULL )\n\t\t\tcapabilityInfoPtr->endFunction( contextInfoPtr );\n\n\t\t/* If this is a context that's implemented via built-in crypto \n\t\t   hardware, perform any required cleanup */\n#ifdef HAS_DEVCRYPTO\n\t\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\t\thwCryptoEnd( contextInfoPtr );\n#endif /* HAS_DEVCRYPTO */\n\n\t\t/* Perform context-type-specific cleanup */\n\t\tif( contextType == CONTEXT_PKC )\n\t\t\t{\n\t\t\tendContextBignums( contextInfoPtr->ctxPKC, \n\t\t\t\t\t\t\t   GET_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_DUMMY ) ? \n\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_DELETEATTRIBUTE );\n\t\tREQUIRES( isAttribute( messageValue ) || \\\n\t\t\t\t  isInternalAttribute( messageValue ) );\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getContextAttribute( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t ( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getContextAttributeS( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( setContextAttribute( contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t *( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t\t messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setContextAttributeS( contextInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t\t  msgData->length, messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_DELETEATTRIBUTE )\n\t\t\treturn( deleteContextAttribute( contextInfoPtr, messageValue ) );\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process action messages */\n\tif( isActionMessage( message ) )\n\t\t{\n\t\treturn( processActionMessage( contextInfoPtr, message, \n\t\t\t\t\t\t\t\t\t  messageDataPtr, messageValue ) );\n\t\t}\n\n\t/* Process messages that compare object properties or clone the object */\n\tif( message == MESSAGE_COMPARE )\n\t\t{\n\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );\n\n\t\treturn( processCompareMessage( contextInfoPtr, messageValue,\n\t\t\t\t\t\t\t\t\t   msgData->data, msgData->length ) );\n\t\t}\n\n\t/* Process messages that check a context */\n\tif( message == MESSAGE_CHECK )\n\t\treturn( checkContext( contextInfoPtr, messageValue ) );\n\n\t/* Process internal notification messages */\n\tif( message == MESSAGE_CHANGENOTIFY )\n\t\t{\n\t\tswitch( messageValue )\n\t\t\t{\n\t\t\tcase MESSAGE_CHANGENOTIFY_STATE:\n\t\t\t\t/* State-change reflected down from the controlling certificate \n\t\t\t\t   object, this doesn't affect us */\n\t\t\t\tbreak;\n\n\t\t\tcase MESSAGE_CHANGENOTIFY_OBJHANDLE:\n\t\t\t\t{\n\t\t\t\tconst CRYPT_HANDLE iCryptHandle = *( ( int * ) messageDataPtr );\n\t\t\t\tint storageAlignSize;\n\n\t\t\t\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV || \\\n\t\t\t\t\t\t  contextInfoPtr->type == CONTEXT_HASH || \\\n\t\t\t\t\t\t  contextInfoPtr->type == CONTEXT_MAC );\n\t\t\t\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\t\t\t\tREQUIRES( contextInfoPtr->objectHandle != iCryptHandle );\n\n\t\t\t\t/* We've been cloned, update the object handle and internal \n\t\t\t\t   state pointers, and perform any deep clong operations \n\t\t\t\t   that may be required */\n\t\t\t\tcontextInfoPtr->objectHandle = iCryptHandle;\n\t\t\t\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATEALIGNTYPE,\n\t\t\t\t\t\t\t\t\t\t\tNULL, &storageAlignSize, 0 );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tstatus = initContextStorage( contextInfoPtr, storageAlignSize );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n#ifdef HAS_DEVCRYPTO\n\t\t\t\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HWCRYPTO ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = hwCryptoCloneState( contextInfoPtr );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n#endif /* HAS_DEVCRYPTO */\n\n\t\t\t\t/* Make sure that the context data is valid, both because we \n\t\t\t\t   didn't check it earlier since the storage pointers were \n\t\t\t\t   set wrong from the cloning process, and to verify that \n\t\t\t\t   the fixup operation went OK */\n\t\t\t\tENSURES( sanityCheckContext( contextInfoPtr ) );\n\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase MESSAGE_CHANGENOTIFY_OWNERHANDLE:\n\t\t\t\t{\n\t\t\t\tconst CRYPT_HANDLE iCryptHandle = *( ( int * ) messageDataPtr );\n\n\t\t\t\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\n\t\t\t\t/* The second stage of a cloning, update the owner handle */\n\t\t\t\tcontextInfoPtr->ownerHandle = iCryptHandle;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_CTX_GENKEY )\n\t\t{\n\t\tstatic const int actionFlags = \\\n\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL ) | \\\n\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \\\n\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );\n\t\tconst CTX_GENERATEKEY_FUNCTION generateKeyFunction = \\\n\t\t\t\t\t\t( CTX_GENERATEKEY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( contextInfoPtr->generateKeyFunction );\n\n\t\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV || \\\n\t\t\t\t  contextInfoPtr->type == CONTEXT_MAC || \\\n\t\t\t\t  contextInfoPtr->type == CONTEXT_PKC || \\\n\t\t\t\t  contextInfoPtr->type == CONTEXT_GENERIC );\n\t\tREQUIRES( needsKey( contextInfoPtr ) );\n\t\tREQUIRES( generateKeyFunction != NULL );\n\n\t\t/* If it's a private key context or a persistent context we need to \n\t\t   have a key label set before we can continue */\n\t\tif( ( ( contextInfoPtr->type == CONTEXT_PKC ) || \\\n\t\t\t  TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ) && \\\n\t\t\tcontextInfoPtr->labelSize <= 0 )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t\t/* Generate a new key into the context */\n\t\tstatus = generateKeyFunction( contextInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* There's now a key loaded, remember this and disable further key \n\t\t   generation.  The kernel won't allow a keygen anyway once the \n\t\t   object is in the high state but taking this additional step can't \n\t\t   hurt */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n\t\treturn( krnlSendMessage( contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t ( MESSAGE_CAST ) &actionFlags, \n\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ACTIONPERMS ) );\n\t\t}\n\tif( message == MESSAGE_CTX_GENIV )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\t\tconst int ivSize = capabilityInfoPtr->blockSize;\n\n\t\tREQUIRES( contextInfoPtr->type == CONTEXT_CONV );\n\n\t\t/* If it's not a conventional encryption context or it's a mode that\n\t\t   doesn't use an IV then the generate IV operation is meaningless */\n\t\tif( !needsIV( contextInfoPtr->ctxConv->mode ) || \\\n\t\t\tisStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t/* Generate a new IV and load it */\n\t\tsetMessageData( &msgData, iv, ivSize );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = capabilityInfoPtr->initParamsFunction( contextInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tKEYPARAM_IV, iv, ivSize );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tContext Creation/Access Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create an encryption context based on an encryption capability template.\n   This is a common function called by devices to create a context once\n   they've got the appropriate capability template */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint createContextFromCapability( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t\t\t const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( CREATEOBJECT ) const int objectFlags )\n\t{\n\tconst CRYPT_ALGO_TYPE cryptAlgo = capabilityInfoPtr->cryptAlgo;\n\tconst CONTEXT_TYPE contextType = \\\n\t\t\t\t( isConvAlgo( cryptAlgo ) ) ? CONTEXT_CONV : \\\n\t\t\t\t( isPkcAlgo( cryptAlgo ) ) ? CONTEXT_PKC : \\\n\t\t\t\t( isHashAlgo( cryptAlgo ) ) ? CONTEXT_HASH : \\\n\t\t\t\t( isMacAlgo( cryptAlgo ) ) ? CONTEXT_MAC : \\\n\t\t\t\t( isSpecialAlgo( cryptAlgo ) ) ? CONTEXT_GENERIC : \\\n\t\t\t\tCONTEXT_NONE;\n\tCONTEXT_INFO *contextInfoPtr;\n\tOBJECT_SUBTYPE subType;\n\tconst int createFlags = objectFlags | \\\n\t\t\t\t\t\t\t( needsSecureMemory( contextType ) ? \\\n\t\t\t\t\t\t\tCREATEOBJECT_FLAG_SECUREMALLOC : 0 );\n\tint sideChannelProtectionLevel, storageSize;\n\tint stateStorageSize = 0, stateStorageAlignSize = 0;\n\tint actionFlags = 0, actionPerms = ACTION_PERM_ALL, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tREQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isFlagRangeZ( objectFlags, CREATEOBJECT ) );\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES( isEnumRange( contextType, CONTEXT ) );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Get general config information */\n\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &sideChannelProtectionLevel,\n\t\t\t\t\t\t\t  CRYPT_OPTION_MISC_SIDECHANNELPROTECTION );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( contextType != CONTEXT_PKC )\n\t\t{\n\t\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATESIZE,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, &stateStorageSize, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = capabilityInfoPtr->getInfoFunction( CAPABILITY_INFO_STATEALIGNTYPE,\n\t\t\t\t\t\t\t\t\t\t\t\tNULL, &stateStorageAlignSize, 0 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Set up subtype-specific information */\n\tswitch( contextType )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\tsubType = SUBTYPE_CTX_CONV;\n\t\t\tstorageSize = sizeof( CONV_INFO );\n\t\t\tif( capabilityInfoPtr->encryptFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->encryptCBCFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->encryptCFBFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->encryptGCMFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL );\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->decryptFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptCBCFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptCFBFunction != NULL || \\\n\t\t\t\tcapabilityInfoPtr->decryptGCMFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t\t\t\t   ACTION_PERM_ALL );\n\t\t\t\t}\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_PKC:\n\t\t\tsubType = SUBTYPE_CTX_PKC;\n\t\t\tstorageSize = sizeof( PKC_INFO );\n\t\t\tif( isDlpAlgo( cryptAlgo ) || isEccAlgo( cryptAlgo ) )\n\t\t\t\t{\n\t\t\t\t/* The DLP- and ECDLP-based PKC's have somewhat specialised \n\t\t\t\t   usage requirements so we don't allow direct access by \n\t\t\t\t   users */\n\t\t\t\tactionPerms = ACTION_PERM_NONE_EXTERNAL;\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->encryptFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t\t\t\t   actionPerms );\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->decryptFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t\t\t\t   actionPerms );\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->signFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN,\n\t\t\t\t\t\t\t\t\t\t\t   actionPerms );\n\t\t\t\t}\n\t\t\tif( capabilityInfoPtr->sigCheckFunction != NULL )\n\t\t\t\t{\n\t\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t\t\t\t\t\t\t\t   actionPerms );\n\t\t\t\t}\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_HASH:\n\t\t\tsubType = SUBTYPE_CTX_HASH;\n\t\t\tstorageSize = sizeof( HASH_INFO );\n\t\t\tactionFlags = MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_MAC:\n\t\t\tsubType = SUBTYPE_CTX_MAC;\n\t\t\tstorageSize = sizeof( MAC_INFO );\n\t\t\tactionFlags = MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t  MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL );\n\t\t\tbreak;\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\tsubType = SUBTYPE_CTX_GENERIC;\n\t\t\tstorageSize = sizeof( GENERIC_INFO );\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_NONE_EXTERNAL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( actionFlags <= 0 )\n\t\t{\n\t\t/* There are no actions enabled for this capability, bail out rather \n\t\t   than creating an unusable context */\n\t\tDEBUG_DIAG(( \"No actions available for this capability\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* Create the context and initialise the variables in it.  The storage is\n\t   allocated as follows:\n\n\t\t+-----------+\t\t\t\t\t\t  --+\n\t\t|\t\t\t|\t\t\t\t\t\t\t|\n\t\t| CTX_INFO\t| ---- typeInfo ----+\t\t|\n\t\t|\t\t\t|\t\t\t\t\t|\t\t| CONTEXT_INFO_ALIGN_SIZE\n\t\t+-----------+\t\t\t\t\t|\t\t|\n\t\t|###########| Pad to 8-byte boundary\t|\n\t\t+-----------+ <-----------------+\t  --+\n\t\t|\t\t\t|\t\t\t\t\t\t\t|\n\t\t| typeInfo\t| -- subtypeInfo ---+\t\t| storageSize\n\t\t|\t\t\t|\t\t\t\t\t|\t\t|\n\t\t+-----------+\t\t\t\t\t|\t  --+\n\t\t|###########| Pad to ALIGNSIZE boundary\n\t\t+-----------+ <-----------------+\t  --- Aligned by initContextStorage()\n\t\t|\t\t\t|\n\t\t|subtypeInfo|\n\t\t|\t\t\t|\n\t\t+-----------+ \n\n\t   In the above the typeInfo is one of { CONV_INFO, PKC_INFO, HASH_INFO,\n\t   MAC_INFO, or GENERIC_INFO }, and the subtypeInfo is the information\n\t   associated with the type, for example keying data for a CONV_INFO.\n\n\t   Note that the typeInfo and subtypeInfo have different alignment \n\t   handling, the typeInfo is aligned relative to the CTX_INFO at a \n\t   multiple of CONTEXT_INFO_ALIGN_SIZE bytes and the subtypeInfo is \n\t   aligned at an absolute memory postion at a multiple of \n\t   CAPABILITY_INFO_STATEALIGNTYPE bytes.  The latter is necessary \n\t   because the subtypeInfo holds low-level algorithm state information \n\t   that can require specific memory alignment when used with exotic \n\t   instruction modes like SIMD/vector or crypto hardware-assist \n\t   operations.  This leads to some complications when cloning contexts,\n\t   see the comments in initContextStorage() for details.\n\n\t   Since we don't know at this point what the alignment requirements for\n\t   the key storage will be because we don't know what contextInfoPtr \n\t   will by until it's allocated, we over-allocate the state storage by\n\t   ALIGNSIZE bytes to allow the key data to be aligned with an ALIGNSIZE \n\t   block.\n\n\t   The aligned-alloc for the key storage can get quite complex, some \n\t   Unix systems have posix_memalign(), and VC++ 2005 and newer have \n\t   _aligned_malloc(), but these are too non-portable to rely on.  What we\n\t   have to do instead is allocate enough spare space at the end of the key\n\t   data for alignment.  Since the address for the start of the key data\n\t   has to be be a multiple of ALIGNSIZE, adding ALIGNSIZE extra bytes to\n\t   the allocation guarantees that we have enough space, with the key data\n\t   starting somewhere in the first 16 bytes of the allocated block.  The \n\t   rest is done by initContextStorage() */\n\tstatus = krnlCreateObject( iCryptContext, ( void ** ) &contextInfoPtr,\n\t\t\t\t\t\t\t   CONTEXT_INFO_ALIGN_SIZE + storageSize + \\\n\t\t\t\t\t\t\t\t\t( stateStorageSize + stateStorageAlignSize ), \n\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT, subType, createFlags, \n\t\t\t\t\t\t\t   iCryptOwner, actionFlags, \n\t\t\t\t\t\t\t   contextMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( contextInfoPtr != NULL );\n\tcontextInfoPtr->objectHandle = *iCryptContext;\n\tcontextInfoPtr->ownerHandle = iCryptOwner;\n\tINIT_FLAGS( contextInfoPtr->flags, CONTEXT_FLAG_NONE );\n\tDATAPTR_SET( contextInfoPtr->capabilityInfo, ( void * ) capabilityInfoPtr );\n\tcontextInfoPtr->type = contextType;\n#ifdef USE_DEVICES\n\tcontextInfoPtr->deviceObject = \\\n\t\tcontextInfoPtr->altDeviceObject = CRYPT_ERROR;\n#endif /* USE_DEVICES */\n\tstatus = initContextStorage( contextInfoPtr, stateStorageAlignSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Enqueue a destroy message for the context and tell the kernel \n\t\t   that we're done */\n\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DESTROY );\n\t\tkrnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\t\treturn( status );\n\t\t}\n\tif( sideChannelProtectionLevel > 0 )\n\t\t{\n\t\tSET_FLAG( contextInfoPtr->flags, \n\t\t\t\t  CONTEXT_FLAG_SIDECHANNELPROTECTION );\n\t\t}\n\tif( objectFlags & CREATEOBJECT_FLAG_DUMMY )\n\t\t{\n\t\t/* This is a dummy object, remember that it's just a placeholder \n\t\t   with actions handled externally */  \t\t\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY );\n\t\t}\n\tif( objectFlags & CREATEOBJECT_FLAG_PERSISTENT )\n\t\t{\n\t\t/* If it's a persistent object backed by a permanent key in a crypto \n\t\t   device, record this */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\tif( contextInfoPtr->type == CONTEXT_PKC )\n\t\t{\n\t\tPKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;\n\n\t\t/* Initialise the overall PKC information */\n\t\tmemset( pkcInfo, 0, sizeof( PKC_INFO ) );\n\t\tINIT_FLAGS( pkcInfo->flags, PKCINFO_FLAG_NONE );\n\n\t\t/* If it's a non-dummy object, initialise the bignums */\n\t\tif( !( objectFlags & CREATEOBJECT_FLAG_DUMMY ) )\n\t\t\t{\n\t\t\tstatus = initContextBignums( pkcInfo, isEccAlgo( cryptAlgo ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t\t  TRUE : FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Enqueue a destroy message for the context and tell the \n\t\t\t\t   kernel that we're done */\n\t\t\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DESTROY );\n\t\t\t\tkrnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Reflect the dummy flag down into the PKC info as well for \n\t\t\t   situations where only the PKC_INFO data is available */\n\t\t\tSET_FLAG( contextInfoPtr->ctxPKC->flags, PKCINFO_FLAG_DUMMY );\n\t\t\t}\n\t\t}\n\tif( contextInfoPtr->type == CONTEXT_CONV )\n\t\t{\n\t\t/* Set the default encryption mode, which is always CBC if possible,\n\t\t   and the corresponding en/decryption handler */\n\t\tif( capabilityInfoPtr->encryptCBCFunction != NULL )\n\t\t\t{\n\t\t\tcontextInfoPtr->ctxConv->mode = CRYPT_MODE_CBC;\n\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t   capabilityInfoPtr->encryptCBCFunction );\n\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t   capabilityInfoPtr->decryptCBCFunction );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* There's no CBC mode available, fall back to increasingly\n\t\t\t   sub-optimal choices of mode.  For stream ciphers the only \n\t\t\t   available mode is (pseudo-)CFB so this isn't a problem, but \n\t\t\t   for block ciphers it'll cause problems because most crypto \n\t\t\t   protocols only allow CBC mode.  In addition we don't fall\n\t\t\t   back to GCM, which is a sufficiently unusual mode that we\n\t\t\t   require it to be explicitly enabled by the user */\n#ifdef USE_CFB\n\t\t\tif( capabilityInfoPtr->encryptCFBFunction != NULL )\n\t\t\t\t{\n\t\t\t\tcontextInfoPtr->ctxConv->mode = CRYPT_MODE_CFB;\n\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t   capabilityInfoPtr->encryptCFBFunction );\n\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t\t   capabilityInfoPtr->decryptCFBFunction );\n\t\t\t\t}\n\t\t\telse\n#endif /* USE_CFB */\n\t\t\t\t{\n\t\t\t\tcontextInfoPtr->ctxConv->mode = CRYPT_MODE_ECB;\n\t\t\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t\t\t   capabilityInfoPtr->encryptFunction );\n\t\t\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t\t\t   capabilityInfoPtr->decryptFunction );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There's only one possible en/decryption handler */\n\t\tFNPTR_SET( contextInfoPtr->encryptFunction,\n\t\t\t\t   capabilityInfoPtr->encryptFunction );\n\t\tFNPTR_SET( contextInfoPtr->decryptFunction,\n\t\t\t\t   capabilityInfoPtr->decryptFunction );\n\t\t}\n\tif( contextInfoPtr->type != CONTEXT_HASH )\n\t\t{\n\t\t/* Set up the key handling functions */\n\t\tinitKeyHandling( contextInfoPtr );\n\t\t}\n\tif( contextInfoPtr->type == CONTEXT_PKC )\n\t\t{\n\t\t/* Set up the key read/write functions */\n\t\tinitKeyID( contextInfoPtr );\n\t\tinitPubKeyRead( contextInfoPtr );\n\t\tinitPrivKeyRead( contextInfoPtr );\n\t\tinitKeyWrite( contextInfoPtr );\n\t\t}\n\n\t/* Make sure that all the function pointers have been set up as \n\t   required */\n\tENSURES( checkContextFunctions( contextInfoPtr ) );\n\n\t/* We've finished setting up the object type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusOK( status ) && contextInfoPtr->type == CONTEXT_HASH )\n\t\t{\n\t\t/* If it's a hash context then there's no explicit keygen or load so \n\t\t   we need to send an \"object initialised\" message to get the kernel \n\t\t   to move it into the high state.  If this isn't done then any \n\t\t   attempt to use the object will be blocked */\n\t\tstatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t*iCryptContext = CRYPT_ERROR;\n\t\treturn( status );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Create an encryption context object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createContext( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t   IN TYPECAST( CAPABILITY_INFO * ) const void *auxDataPtr, \n\t\t\t\t   IN_FLAGS_Z( CREATEOBJECT ) const int auxValue )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tint status;\n\n\tassert( isReadPtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\tassert( isReadPtr( auxDataPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tREQUIRES( isFlagRangeZ( auxValue, CREATEOBJECT ) );\n\tREQUIRES( isEnumRange( createInfo->arg1, CRYPT_ALGO ) );\n\n\t/* Find the capability corresponding to the algorithm */\n\tcapabilityInfoPtr = findCapabilityInfo( auxDataPtr, createInfo->arg1 );\n\tif( capabilityInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Pass the call on to the lower-level create function */\n\tstatus = createContextFromCapability( &iCryptContext,\n\t\t\t\t\t\t\t\t\t\t  createInfo->cryptOwner,\n\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr, auxValue );\n\tif( cryptStatusOK( status ) )\n\t\tcreateInfo->cryptHandle = iCryptContext;\n\treturn( status );\n\t}\n\n#ifdef CONFIG_DIRECT_API\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nC_RET cryptGetDirectAPI( C_IN CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\t C_OUT void C_PTR C_PTR contextPtr,\n\t\t\t\t\t\t C_OUT CRYPT_DIRECT_FUNCTION C_PTR encryptFunction,\n\t\t\t\t\t\t C_OUT CRYPT_DIRECT_FUNCTION C_PTR decryptFunction )\n\t{\n\tconst CONTEXT_INFO *contextInfoPtr;\n\tCRYPT_DIRECT_FUNCTION encryptFnPtr, decryptFnPtr;\n\tint dummy, status;\n\n\t/* Perform basic parameter error checking */\n\tstatus = krnlSendMessage( cryptContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &dummy, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM1 : status );\n\tif( !isWritePtr( contextPtr, sizeof( void * ) ) )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isWritePtr( encryptFunction, sizeof( CRYPT_DIRECT_FUNCTION * ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( !isWritePtr( decryptFunction, sizeof( CRYPT_DIRECT_FUNCTION * ) ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\n\t/* Clear return values */\n\t*contextPtr = NULL;\n\t*encryptFunction = *decryptFunction = NULL;\n\n\t/* Retrieve pointers to the internal encrypt/decrypt functions */\n\tstatus = krnlAcquireObject( cryptContext, OBJECT_TYPE_CONTEXT,\n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &contextInfoPtr,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_PARAM1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tencryptFnPtr = ( CRYPT_DIRECT_FUNCTION ) \\\n\t\t\t\t   FNPTR_GET( contextInfoPtr->encryptFunction );\n\tdecryptFnPtr = ( CRYPT_DIRECT_FUNCTION ) \\\n\t\t\t\t   FNPTR_GET( contextInfoPtr->decryptFunction );\n\tkrnlReleaseObject( cryptContext );\n\tif( encryptFnPtr == NULL || decryptFnPtr == NULL )\n\t\treturn( CRYPT_ERROR_INTERNAL );\n\n\t*contextPtr = ( void * ) contextInfoPtr;\n\t*encryptFunction = encryptFnPtr;\n\t*decryptFunction = decryptFnPtr;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_DIRECT_API */\n"
  },
  {
    "path": "deps/cl345/cryptdev.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib Crypto Device Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"capabil.h\"\n  #include \"device.h\"\n#else\n  #include \"device/capabil.h\"\n  #include \"device/device.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check device data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckDevice( IN const DEVICE_INFO *deviceInfoPtr )\n\t{\n\tassert( isReadPtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\t/* Check general device data.  CRYPT_DEVICE_NONE is the system device so\n\t   we allow a device type of CRYPT_DEVICE_NONE */\n\tif( !isEnumRangeOpt( deviceInfoPtr->type, CRYPT_DEVICE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDevice: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !CHECK_FLAGS( deviceInfoPtr->flags, DEVICE_FLAG_NONE, \n\t\t\t\t\t  DEVICE_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDevice: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEmptyData( deviceInfoPtr->label, deviceInfoPtr->labelLen ) )\n\t\t{\n\t\tif( deviceInfoPtr->labelLen <= 0 || \\\n\t\t\tdeviceInfoPtr->labelLen > CRYPT_MAX_TEXTSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: Label\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check safe pointers.  We don't have to check the function pointers\n\t   because they're validated each time they're dereferenced */\n\tif( !DATAPTR_ISVALID( deviceInfoPtr->capabilityInfoList ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDevice: Data pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check associated handles */\n\tif( deviceInfoPtr->type == CRYPT_DEVICE_NONE )\n\t\t{\n\t\tif( deviceInfoPtr->objectHandle != SYSTEM_OBJECT_HANDLE || \\\n\t\t\tdeviceInfoPtr->ownerHandle != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: System device handles\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isHandleRangeValid( deviceInfoPtr->objectHandle ) || \\\n\t\t\tdeviceInfoPtr->ownerHandle != DEFAULTUSER_OBJECT_HANDLE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: Object handles\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check function and data pointers */\n\tif( !DATAPTR_ISSET( deviceInfoPtr->capabilityInfoList ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckDevice: Capability function\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check subtype-specific data */\n\tswitch( deviceInfoPtr->type )\n\t\t{\n\t\tcase CRYPT_DEVICE_NONE:\n\t\t\t{\n\t\t\tconst SYSTEMDEV_INFO *systemInfo = deviceInfoPtr->deviceSystem;\n\n\t\t\tassert( isReadPtr( systemInfo, sizeof( SYSTEMDEV_INFO ) ) );\n\n\t\t\t/* Check the nonce RNG data */\n\t\t\tif( systemInfo->nonceDataInitialised == FALSE )\n\t\t\t\t{\n\t\t\t\tif( !isEmptyData( systemInfo->nonceData, \n\t\t\t\t\t\t\t\t  systemInfo->nonceHashSize ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: Spurious nonce RNG data\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( systemInfo->nonceDataInitialised != TRUE || \\\n\t\t\t\t\tsystemInfo->nonceHashSize < MIN_HASHSIZE || \\\n\t\t\t\t\tsystemInfo->nonceHashSize > CRYPT_MAX_HASHSIZE || \\\n\t\t\t\t\tisEmptyData( systemInfo->nonceData, \n\t\t\t\t\t\t\t\t systemInfo->nonceHashSize ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: Nonce RNG data\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n\n#ifdef USE_PKCS11\n\t\tcase CRYPT_DEVICE_PKCS11:\n\t\t\t{\n\t\t\tconst PKCS11_INFO *pkcs11Info = deviceInfoPtr->devicePKCS11;\n\n\t\t\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\t\t\t/* Check general device information */\n\t\t\tif( pkcs11Info->minPinSize != 0 || pkcs11Info->maxPinSize != 0 )\n\t\t\t\t{\n\t\t\t\tif( pkcs11Info->minPinSize < 4 || \\\n\t\t\t\t    pkcs11Info->minPinSize > pkcs11Info->maxPinSize || \\\n\t\t\t\t\tpkcs11Info->maxPinSize > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: PIN size\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n \t\t\t/* Check device type-specific information */\n\t\t\tif( pkcs11Info->deviceNo < 0 || \\\n\t\t\t\tpkcs11Info->deviceNo > 16 )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: Device number\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !isEmptyData( pkcs11Info->defaultSSOPin, \\\n\t\t\t\t\t\t\t  pkcs11Info->defaultSSOPinLen ) )\n\t\t\t\t{\n\t\t\t\tif( pkcs11Info->defaultSSOPinLen <= 0 || \\\n\t\t\t\t\tpkcs11Info->defaultSSOPinLen > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckDevice: SSO PIN size\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\t\tcase CRYPT_DEVICE_CRYPTOAPI:\n\t\t\t{\n\t\t\tconst CRYPTOAPI_INFO *cryptoapiInfo = deviceInfoPtr->deviceCryptoAPI;\n\n\t\t\tassert( isReadPtr( cryptoapiInfo, sizeof( CRYPTOAPI_INFO ) ) );\n\n\t\t\t/* Nothing to check */\n\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_CRYPTOAPI */\n\n#ifdef USE_HARDWARE\n\t\tcase CRYPT_DEVICE_HARDWARE:\n\t\t\t{\n\t\t\tconst HARDWARE_INFO *hardwareInfo = deviceInfoPtr->deviceHardware;\n\n\t\t\tassert( isReadPtr( hardwareInfo, sizeof( HARDWARE_INFO ) ) );\n\n\t\t\t/* Nothing to check */\n\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_HARDWARE */\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that device function pointers have been set up correctly.  This is a\n   setup check not related to sanityCheckDevice() */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkDeviceFunctions( IN const DEVICE_INFO *deviceInfoPtr )\n\t{\n\tassert( isReadPtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\tif( !FNPTR_ISSET( deviceInfoPtr->initFunction ) || \\\n\t\t!FNPTR_ISSET( deviceInfoPtr->controlFunction ) || \\\n\t\t!FNPTR_ISSET( deviceInfoPtr->shutdownFunction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"checkDeviceFunctions: General functions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( deviceInfoPtr->type == CRYPT_DEVICE_NONE )\n\t\t{\n\t\t/* The system device needs to supply a get-random function */\n\t\tif( !FNPTR_ISNULL( deviceInfoPtr->getItemFunction ) || \\\n\t\t\t!FNPTR_ISNULL( deviceInfoPtr->setItemFunction ) || \\\n\t\t\t!FNPTR_ISNULL( deviceInfoPtr->deleteItemFunction ) || \\\n\t\t\t!FNPTR_ISNULL( deviceInfoPtr->getFirstItemFunction ) || \\\n\t\t\t!FNPTR_ISNULL( deviceInfoPtr->getNextItemFunction ) || \\\n\t\t\t!FNPTR_ISSET( deviceInfoPtr->getRandomFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"checkDeviceFunctions: Random function\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !FNPTR_ISSET( deviceInfoPtr->getItemFunction ) || \\\n\t\t\t!FNPTR_ISSET( deviceInfoPtr->setItemFunction ) || \\\n\t\t\t!FNPTR_ISSET( deviceInfoPtr->deleteItemFunction ) || \\\n\t\t\t!FNPTR_ISSET( deviceInfoPtr->getFirstItemFunction ) || \\\n\t\t\t!FNPTR_ISSET( deviceInfoPtr->getNextItemFunction ) || \\\n\t\t\t!FNPTR_ISVALID( deviceInfoPtr->getRandomFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"checkDeviceFunctions: Data access functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\t\n\treturn( TRUE );\n\t}\n\n/* Process a crypto mechanism message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nstatic int processMechanismMessage( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE action,\n\t\t\t\t\t\t\t\t\tIN_ENUM( MECHANISM ) \\\n\t\t\t\t\t\t\t\t\t\tconst MECHANISM_TYPE mechanism,\n\t\t\t\t\t\t\t\t\tINOUT void *mechanismInfo,\n\t\t\t\t\t\t\t\t\tINOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tCRYPT_DEVICE localCryptDevice = deviceInfoPtr->objectHandle;\n\tMECHANISM_FUNCTION mechanismFunction = NULL;\n\tint refCount, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( messageExtInfo, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isMechanismActionMessage( action ) );\n\tREQUIRES( isEnumRange( mechanism, MECHANISM ) );\n\tREQUIRES( mechanismInfo != NULL );\n\n\t/* Find the function to handle this action and mechanism */\n\tif( deviceInfoPtr->mechanismFunctions != NULL )\n\t\t{\n\t\tLOOP_LARGE( i = 0,\n\t\t\t\t\ti < deviceInfoPtr->mechanismFunctionCount && \\\n\t\t\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE, \n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( deviceInfoPtr->mechanismFunctions[ i ].action == action && \\\n\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )\n\t\t\t\t{\n\t\t\t\tmechanismFunction = \\\n\t\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].function;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < deviceInfoPtr->mechanismFunctionCount );\n\t\t}\n\tif( mechanismFunction == NULL && \\\n\t\tlocalCryptDevice != SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\t/* This isn't the system object, fall back to the system object and \n\t\t   see if it can handle the mechanism.  We do it this way rather \n\t\t   than sending the message through the kernel a second time because \n\t\t   all the kernel checking of message parameters has already been \n\t\t   done, this saves the overhead of a second, redundant kernel pass.  \n\t\t   This code was only ever used with Fortezza devices, with PKCS #11 \n\t\t   devices the support for various mechanisms is too patchy to allow \n\t\t   us to rely on it so we always use system mechanisms which we know \n\t\t   will get it right.\n\t\t   \n\t\t   Because it should never be used in normal use, we throw an \n\t\t   exception if we get here inadvertently.  If this doesn't stop \n\t\t   execution then the krnlAcquireObject() will since it will refuse \n\t\t   to allocate the system object */\n\t\tassert( INTERNAL_ERROR );\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\tstatus = krnlSuspendObject( deviceInfoPtr->objectHandle, &refCount );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tlocalCryptDevice = SYSTEM_OBJECT_HANDLE;\n\t\tstatus = krnlAcquireObject( SYSTEM_OBJECT_HANDLE, /* Will always fail */\n\t\t\t\t\t\t\t\t\tOBJECT_TYPE_DEVICE,\n\t\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &deviceInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tREQUIRES_OBJECT( deviceInfoPtr->mechanismFunctions != NULL,\n\t\t\t\t\t\t deviceInfoPtr->objectHandle );\n\t\tLOOP_LARGE( i = 0, \n\t\t\t\t\ti < deviceInfoPtr->mechanismFunctionCount && \\\n\t\t\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE,\n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( deviceInfoPtr->mechanismFunctions[ i ].action == action && \\\n\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )\n\t\t\t\t{\n\t\t\t\tmechanismFunction = \\\n\t\t\t\t\t\tdeviceInfoPtr->mechanismFunctions[ i ].function;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < deviceInfoPtr->mechanismFunctionCount );\n\t\t}\n\tif( mechanismFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* If the message has been sent to the system object, unlock it to allow \n\t   it to be used by others and dispatch the message */\n\tif( localCryptDevice == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\tstatus = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tassert( ( mechanism >= MECHANISM_SELFTEST_ENC && \\\n\t\t\t\t  mechanism <= MECHANISM_SELFTEST_KDF && \\\n\t\t\t\t  refCount <= 2 ) || \\\n\t\t\t\trefCount == 1 );\n\t\t\t\t/* The system object can send itself a resursive \n\t\t\t\t   selftest mechanism message */\n\t\treturn( mechanismFunction( NULL, mechanismInfo ) );\n\t\t}\n\n\t/* Send the message to the device */\n\treturn( mechanismFunction( deviceInfoPtr, mechanismInfo ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDevice API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Default object creation routines used when the device code doesn't set\n   anything up */\n\nstatic const CREATEOBJECT_FUNCTION_INFO defaultCreateFunctions[] = {\n\t{ OBJECT_TYPE_CONTEXT, createContext },\n\t{ OBJECT_TYPE_NONE, NULL }\n\t};\n\n/* Handle a message sent to a device object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int deviceMessageFunction( INOUT TYPECAST( MESSAGE_FUNCTION_EXTINFO * ) \\\n\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_INT_SHORT_Z const int messageValue )\n\t{\n\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo = \\\n\t\t\t\t\t\t( MESSAGE_FUNCTION_EXTINFO * ) objectInfoPtr;\n\tDEVICE_INFO *deviceInfoPtr = \\\n\t\t\t\t\t\t( DEVICE_INFO * ) messageExtInfo->objectInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isShortIntegerRange( messageValue ) );\n\n\t/* Process the destroy object message */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* Shut down the device if required */\n\t\tif( TEST_FLAG( deviceInfoPtr->flags, DEVICE_FLAG_ACTIVE ) )\n\t\t\t{\n\t\t\tconst DEV_SHUTDOWNFUNCTION shutdownFunction = \\\n\t\t\t\t\t\t( DEV_SHUTDOWNFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->shutdownFunction );\n\n\t\t\tif( shutdownFunction != NULL )\n\t\t\t\tshutdownFunction( deviceInfoPtr );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE_S );\n\t\tREQUIRES( isAttribute( messageValue ) || \\\n\t\t\t\t  isInternalAttribute( messageValue ) );\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getDeviceAttribute( deviceInfoPtr, \n\t\t\t\t\t\t\t\t\t\t( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tmessageValue, messageExtInfo ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getDeviceAttributeS( deviceInfoPtr, \n\t\t\t\t\t\t\t\t\t\t ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t messageValue, messageExtInfo ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( setDeviceAttribute( deviceInfoPtr, \n\t\t\t\t\t\t\t\t\t\t *( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t\t messageValue, messageExtInfo ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setDeviceAttributeS( deviceInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t\t msgData->length, messageValue,\n\t\t\t\t\t\t\t\t\t\t messageExtInfo ) );\n\t\t\t}\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process action messages */\n\tif( isMechanismActionMessage( message ) )\n\t\t{\n\t\treturn( processMechanismMessage( deviceInfoPtr, message, \n\t\t\t\t\t\t\t\t\t\t messageValue, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t messageExtInfo ) );\n\t\t}\n\n\t/* Process messages that check a device */\n\tif( message == MESSAGE_CHECK )\n\t\t{\n\t\t/* The check for whether this device type can contain an object that\n\t\t   can perform the requested operation has already been performed by\n\t\t   the kernel so there's nothing further to do here */\n\t\tREQUIRES( ( messageValue == MESSAGE_CHECK_PKC_ENCRYPT_AVAIL || \\\n\t\t\t\t\tmessageValue == MESSAGE_CHECK_PKC_DECRYPT_AVAIL || \\\n\t\t\t\t\tmessageValue == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL || \\\n\t\t\t\t\tmessageValue == MESSAGE_CHECK_PKC_SIGN_AVAIL ) && \\\n\t\t\t\t  ( deviceInfoPtr->type == CRYPT_DEVICE_PKCS11 || \\\n\t\t\t\t\tdeviceInfoPtr->type == CRYPT_DEVICE_CRYPTOAPI || \\\n\t\t\t\t\tdeviceInfoPtr->type == CRYPT_DEVICE_HARDWARE ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_SELFTEST )\n\t\t{\n\t\tconst DEV_SELFTESTFUNCTION selftestFunction = \\\n\t\t\t\t\t( DEV_SELFTESTFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->selftestFunction );\n\n\t\t/* If the device doesn't have a self-test capability then there's \n\t\t   not much that we can do */\n\t\tif( selftestFunction == NULL )\n\t\t\treturn( CRYPT_OK );\n\n\t\treturn( selftestFunction( deviceInfoPtr, messageExtInfo ) );\n\t\t}\n\tif( message == MESSAGE_KEY_GETKEY )\n\t\t{\n\t\tconst DEV_GETITEMFUNCTION getItemFunction = \\\n\t\t\t\t\t( DEV_GETITEMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getkeyInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( getItemFunction != NULL );\n\n\t\t/* Create a context via an object in the device */\n\t\treturn( getItemFunction( deviceInfoPtr,\n\t\t\t\t\t\t\t\t &getkeyInfo->cryptHandle, messageValue,\n\t\t\t\t\t\t\t\t getkeyInfo->keyIDtype, getkeyInfo->keyID,\n\t\t\t\t\t\t\t\t getkeyInfo->keyIDlength, getkeyInfo->auxInfo,\n\t\t\t\t\t\t\t\t &getkeyInfo->auxInfoLength,\n\t\t\t\t\t\t\t\t getkeyInfo->flags ) );\n\t\t}\n\tif( message == MESSAGE_KEY_SETKEY )\n\t\t{\n\t\tconst DEV_SETITEMFUNCTION setItemFunction = \\\n\t\t\t\t\t( DEV_SETITEMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->setItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *setkeyInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( setItemFunction != NULL );\n\n\t\t/* Update the device with the cert */\n\t\treturn( setItemFunction( deviceInfoPtr, setkeyInfo->cryptHandle ) );\n\t\t}\n\tif( message == MESSAGE_KEY_DELETEKEY )\n\t\t{\n\t\tconst DEV_DELETEITEMFUNCTION deleteItemFunction = \\\n\t\t\t\t\t( DEV_DELETEITEMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->deleteItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *deletekeyInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( deleteItemFunction != NULL );\n\n\t\t/* Delete an object in the device */\n\t\treturn( deleteItemFunction( deviceInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t\tdeletekeyInfo->keyIDtype, \n\t\t\t\t\t\t\t\t\tdeletekeyInfo->keyID, \n\t\t\t\t\t\t\t\t\tdeletekeyInfo->keyIDlength ) );\n\t\t}\n\tif( message == MESSAGE_KEY_GETFIRSTCERT )\n\t\t{\n\t\tconst DEV_GETFIRSTITEMFUNCTION getFirstItemFunction = \\\n\t\t\t\t\t( DEV_GETFIRSTITEMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getFirstItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getnextcertInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( getFirstItemFunction != NULL );\n\t\tREQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );\n\t\tREQUIRES( messageValue == KEYMGMT_ITEM_PUBLICKEY );\n\n\t\t/* Fetch a cert in a cert chain from the device */\n\t\treturn( getFirstItemFunction( deviceInfoPtr, \n\t\t\t\t\t\t&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,\n\t\t\t\t\t\tgetnextcertInfo->keyIDtype, getnextcertInfo->keyID,\n\t\t\t\t\t\tgetnextcertInfo->keyIDlength, messageValue,\n\t\t\t\t\t\tgetnextcertInfo->flags ) );\n\t\t}\n\tif( message == MESSAGE_KEY_GETNEXTCERT )\n\t\t{\n\t\tconst DEV_GETNEXTITEMFUNCTION getNextItemFunction = \\\n\t\t\t\t\t( DEV_GETNEXTITEMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getNextItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getnextcertInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( getNextItemFunction != NULL );\n\t\tREQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );\n\n\t\t/* Fetch a cert in a cert chain from the device */\n\t\treturn( getNextItemFunction( deviceInfoPtr,\n\t\t\t\t\t\t&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,\n\t\t\t\t\t\tgetnextcertInfo->flags ) );\n\t\t}\n\tif( message == MESSAGE_DEV_QUERYCAPABILITY )\n\t\t{\n\t\tconst CAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t\t\tDATAPTR_GET( deviceInfoPtr->capabilityInfoList );\n\t\tconst void *capabilityInfoPtr;\n\t\tCRYPT_QUERY_INFO *queryInfo = ( CRYPT_QUERY_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( capabilityInfoListPtr != NULL );\n\n\t\t/* Find the information for this algorithm and return the appropriate\n\t\t   information */\n\t\tcapabilityInfoPtr = findCapabilityInfo( capabilityInfoListPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tmessageValue );\n\t\tif( capabilityInfoPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\tgetCapabilityInfo( queryInfo, capabilityInfoPtr );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( message == MESSAGE_DEV_CREATEOBJECT )\n\t\t{\n\t\tCRYPT_DEVICE iCryptDevice = deviceInfoPtr->objectHandle;\n\t\tCREATEOBJECT_FUNCTION createObjectFunction = NULL;\n\t\tconst void *auxInfo = NULL;\n\n\t\tREQUIRES( isEnumRange( messageValue, OBJECT_TYPE ) );\n\n\t\t/* If the device can't have objects created within it, complain */\n\t\tif( TEST_FLAG( deviceInfoPtr->flags, DEVICE_FLAG_READONLY ) )\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\t/* Find the function to handle this object */\n\t\tif( deviceInfoPtr->createObjectFunctions != NULL )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\t\t\t\n\t\t\tLOOP_MED( i = 0,\n\t\t\t\t\t  i < deviceInfoPtr->createObjectFunctionCount && \\\n\t\t\t\t\t\tdeviceInfoPtr->createObjectFunctions[ i ].type != OBJECT_TYPE_NONE,\n\t\t\t\t\t  i++ )\n\t\t\t\t{\n\t\t\t\tif( deviceInfoPtr->createObjectFunctions[ i ].type == messageValue )\n\t\t\t\t\t{\n\t\t\t\t\tcreateObjectFunction  = \\\n\t\t\t\t\t\tdeviceInfoPtr->createObjectFunctions[ i ].function;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tENSURES( i < deviceInfoPtr->createObjectFunctionCount );\n\t\t\t}\n\t\tif( createObjectFunction  == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t/* Get any auxiliary info that we may need to create the object */\n\t\tif( messageValue == OBJECT_TYPE_CONTEXT )\n\t\t\t{\n\t\t\tauxInfo = DATAPTR_GET( deviceInfoPtr->capabilityInfoList );\n\n\t\t\tENSURES( DATAPTR_ISVALID( deviceInfoPtr->capabilityInfoList ) );\n\t\t\t}\n\n\t\t/* If the message has been sent to the system object, unlock it to\n\t\t   allow it to be used by others and dispatch the message.  This is\n\t\t   safe because the auxInfo for the system device is in a static,\n\t\t   read-only segment and persists even if the system device is\n\t\t   destroyed */\n\t\tif( deviceInfoPtr->objectHandle == SYSTEM_OBJECT_HANDLE )\n\t\t\t{\n\t\t\tint refCount;\n\n\t\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\t\tstatus = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tassert( refCount == 1 );\n\t\t\tstatus = createObjectFunction( messageDataPtr, auxInfo,\n\t\t\t\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Create a dummy object, with all details handled by the device.\n\t\t\t   Unlike the system device we don't unlock the device info \n\t\t\t   before we call the create object function because there may be\n\t\t\t   auxiliary info held in the device object that we need in order\n\t\t\t   to create the object.  This is OK since we're not tying up the\n\t\t\t   system device but only some auxiliary crypto device */\n\t\t\tstatus = createObjectFunction( messageDataPtr, auxInfo,\n\t\t\t\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_DUMMY );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Make the newly-created object a dependent object of the device */\n\t\treturn( krnlSendMessage( \\\n\t\t\t\t\t( ( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr )->cryptHandle,\n\t\t\t\t\tIMESSAGE_SETDEPENDENT, ( MESSAGE_CAST ) &iCryptDevice,\n\t\t\t\t\tSETDEP_OPTION_INCREF ) );\n\t\t}\n\tif( message == MESSAGE_DEV_CREATEOBJECT_INDIRECT )\n\t\t{\n\t\tCRYPT_HANDLE iCryptHandle;\n\t\tconst CRYPT_DEVICE iCryptDevice = deviceInfoPtr->objectHandle;\n#ifdef USE_CERTIFICATES\n\t\tint refCount;\n#endif /* USE_CERTIFICATES */\n\t\tint value;\n\n\t\t/* At the moment the only objects where can be created in this manner\n\t\t   are certificates */\n\t\tREQUIRES( messageValue == OBJECT_TYPE_CERTIFICATE );\n\t\tREQUIRES( deviceInfoPtr->objectHandle == SYSTEM_OBJECT_HANDLE );\n\n\t\t/* Unlock the system object to allow it to be used by others and\n\t\t   dispatch the message */\n#ifdef USE_CERTIFICATES\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\tstatus = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tassert( refCount == 1 );\n\t\tstatus = createCertificateIndirect( messageDataPtr, NULL, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiCryptHandle = \\\n\t\t\t( ( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr )->cryptHandle;\n#else\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#endif /* USE_CERTIFICATES */\n\n\t\t/* Make the newly-created object a dependent object of the device.  \n\t\t   There's one special-case situation where we don't do this and \n\t\t   that's when we're importing a certificate chain, which is a \n\t\t   collection of individual certificate objects each of which have\n\t\t   already been made dependent on the device.  We could detect this\n\t\t   in one of two ways, either implicitly by reading the \n\t\t   CRYPT_IATTRIBUTE_SUBTYPE attribute and assuming that if it's a\n\t\t   SUBTYPE_CERT_CERTCHAIN that the owner will have been set, or \n\t\t   simply by reading the depending user object.  Explcitly checking\n\t\t   for ownership seems to be the best approach, although it may\n\t\t   pass through a case in which we've inadvertently set the owner\n\t\t   without intending do, in which case a backup check of the\n\t\t   subtype could be used to catch this */\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t\t  &value, OBJECT_TYPE_USER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* The object is already owned, don't try and set an owner */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\treturn( krnlSendMessage( iCryptHandle, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t ( MESSAGE_CAST ) &iCryptDevice, \n\t\t\t\t\t\t\t\t SETDEP_OPTION_INCREF ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Open a device.  This is a common function called to create both the\n   internal system device object and general devices */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int openDevice( OUT_HANDLE_OPT CRYPT_DEVICE *iCryptDevice,\n\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_USER iCryptOwner,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_DEVICE ) \\\n\t\t\t\t\t\t\tconst CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t   IN_BUFFER_OPT( nameLength ) const char *name, \n\t\t\t\t\t   IN_LENGTH_TEXT_Z const int nameLength,\n\t\t\t\t\t   OUT_PTR_OPT DEVICE_INFO **deviceInfoPtrPtr )\n\t{\n\tDEVICE_INFO *deviceInfoPtr;\n\tDEV_INITFUNCTION initFunction;\n\tOBJECT_SUBTYPE subType;\n\tstatic const MAP_TABLE subtypeMapTbl[] = {\n\t\t{ CRYPT_DEVICE_NONE, SUBTYPE_DEV_SYSTEM },\n\t\t{ CRYPT_DEVICE_PKCS11, SUBTYPE_DEV_PKCS11 },\n\t\t{ CRYPT_DEVICE_CRYPTOAPI, SUBTYPE_DEV_CRYPTOAPI },\n\t\t{ CRYPT_DEVICE_HARDWARE, SUBTYPE_DEV_HARDWARE },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tint value, storageSize, status;\n\n\tassert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );\n\tassert( ( name == NULL && nameLength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( name, nameLength ) ) );\n\tassert( isWritePtr( deviceInfoPtrPtr, sizeof( DEVICE_INFO * ) ) );\n\n\tREQUIRES( ( deviceType == CRYPT_DEVICE_NONE && \\\n\t\t\t\tiCryptOwner == CRYPT_UNUSED ) || \\\n\t\t\t  ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t\tisHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isEnumRangeOpt( deviceType, CRYPT_DEVICE ) );\n\tREQUIRES( ( name == NULL && nameLength == 0 ) || \\\n\t\t\t  ( name != NULL && \\\n\t\t\t    nameLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tnameLength <= CRYPT_MAX_TEXTSIZE ) );\n\n\t/* Clear return values */\n\t*iCryptDevice = CRYPT_ERROR;\n\t*deviceInfoPtrPtr = NULL;\n\n\t/* Fortezza support was removed as of cryptlib 3.4.0 so we add a special-\n\t   case check to make sure that we don't try and use it */\n\tif( deviceType == CRYPT_DEVICE_FORTEZZA )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Set up subtype-specific information */\n\tstatus = mapValue( deviceType, &value, subtypeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( subtypeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsubType = value;\n\tswitch( deviceType )\n\t\t{\n\t\tcase CRYPT_DEVICE_NONE:\n\t\t\tstorageSize = sizeof( SYSTEMDEV_INFO );\n\t\t\tbreak;\n\n#ifdef USE_PKCS11\n\t\tcase CRYPT_DEVICE_PKCS11:\n\t\t\tstorageSize = sizeof( PKCS11_INFO );\n\t\t\tbreak;\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\t\tcase CRYPT_DEVICE_CRYPTOAPI:\n\t\t\tstorageSize = sizeof( CRYPTOAPI_INFO );\n\t\t\tbreak;\n#endif /* USE_CRYPTOAPI */\n\n#ifdef USE_HARDWARE\n\t\tcase CRYPT_DEVICE_HARDWARE:\n\t\t\tstorageSize = sizeof( HARDWARE_INFO );\n\t\t\tbreak;\n#endif /* USE_HARDWARE */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Create the device object and connect it to the device */\n\tstatus = krnlCreateObject( iCryptDevice, ( void ** ) &deviceInfoPtr,\n\t\t\t\t\t\t\t   sizeof( DEVICE_INFO ) + storageSize,\n\t\t\t\t\t\t\t   OBJECT_TYPE_DEVICE, subType,\n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, iCryptOwner,\n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, deviceMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( deviceInfoPtr != NULL );\n\t*deviceInfoPtrPtr = deviceInfoPtr;\n\tdeviceInfoPtr->objectHandle = *iCryptDevice;\n\tdeviceInfoPtr->ownerHandle = iCryptOwner;\n\tINIT_FLAGS( deviceInfoPtr->flags, DEVICE_FLAG_NONE );\n\tdeviceInfoPtr->type = deviceType;\n\tswitch( deviceType )\n\t\t{\n\t\tcase CRYPT_DEVICE_NONE:\n\t\t\tdeviceInfoPtr->deviceSystem = \\\n\t\t\t\t\t\t\t( SYSTEMDEV_INFO * ) deviceInfoPtr->storage;\n\t\t\tbreak;\n\n#ifdef USE_PKCS11\n\t\tcase CRYPT_DEVICE_PKCS11:\n\t\t\tdeviceInfoPtr->devicePKCS11 = \\\n\t\t\t\t\t\t\t( PKCS11_INFO * ) deviceInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\t\tcase CRYPT_DEVICE_CRYPTOAPI:\n\t\t\tdeviceInfoPtr->deviceCryptoAPI = \\\n\t\t\t\t\t\t\t( CRYPTOAPI_INFO * ) deviceInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_CRYPTOAPI */\n\n#ifdef USE_HARDWARE\n\t\tcase CRYPT_DEVICE_HARDWARE:\n\t\t\tdeviceInfoPtr->deviceHardware = \\\n\t\t\t\t\t\t\t( HARDWARE_INFO * ) deviceInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_HARDWARE */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tdeviceInfoPtr->storageSize = storageSize;\n\n\t/* Set up access information for the device */\n\tswitch( deviceType )\n\t\t{\n\t\tcase CRYPT_DEVICE_NONE:\n\t\t\tstatus = setDeviceSystem( deviceInfoPtr );\n\t\t\tbreak;\n\n#ifdef USE_PKCS11\n\t\tcase CRYPT_DEVICE_PKCS11:\n\t\t\tif( name == NULL )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tENSURES( nameLength >= MIN_NAME_LENGTH && \\\n\t\t\t\t\t nameLength <= CRYPT_MAX_TEXTSIZE );\n\t\t\tstatus = setDevicePKCS11( deviceInfoPtr, name, nameLength );\n\t\t\tbreak;\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\t\tcase CRYPT_DEVICE_CRYPTOAPI:\n\t\t\tstatus = setDeviceCryptoAPI( deviceInfoPtr );\n\t\t\tbreak;\n#endif /* USE_CRYPTOAPI */\n\n#ifdef USE_HARDWARE\n\t\tcase CRYPT_DEVICE_HARDWARE:\n\t\t\tstatus = setDeviceHardware( deviceInfoPtr );\n\t\t\tbreak;\n#endif /* USE_HARDWARE */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tdeviceInfoPtr->createObjectFunctions == NULL )\n\t\t{\n\t\t/* The device-specific code hasn't set up anything, use the default\n\t\t   create-object functions, which just create encryption contexts\n\t\t   using the device capability information */\n\t\tdeviceInfoPtr->createObjectFunctions = defaultCreateFunctions;\n\t\tdeviceInfoPtr->createObjectFunctionCount = \\\n\t\t\tFAILSAFE_ARRAYSIZE( defaultCreateFunctions, CREATEOBJECT_FUNCTION_INFO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( checkDeviceFunctions( deviceInfoPtr ) );\n\n\t/* Connect to the device */\n\tinitFunction = ( DEV_INITFUNCTION ) \\\n\t\t\t\t   FNPTR_GET( deviceInfoPtr->initFunction );\n\tREQUIRES( initFunction != NULL );\n\tstatus = initFunction( deviceInfoPtr, name, nameLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Since this function is called on object creation, if it fails \n\t\t   there's no object to get extended error information from so we \n\t\t   dump the error info as a diagnostic for debugging purposes */\n#ifdef USE_PKCS11\n\t\tif( deviceType == CRYPT_DEVICE_PKCS11 )\n\t\t\t{\n\t\t\tDEBUG_OP( const PKCS11_INFO *pkcs11Info = deviceInfoPtr->devicePKCS11 );\n\n\t\t\tDEBUG_DIAG_ERRMSG(( \"Device open failed, status %s, error \"\n\t\t\t\t\t\t\t\t\"string:\\n  '%s'\", getStatusName( status ),\n\t\t\t\t\t\t\t\tgetErrorInfoString( &pkcs11Info->errorInfo ) ));\n\t\t\t}\n#endif /* USE_PKCS11 */\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a (non-system) device object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createDevice( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t  STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t  STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tDEVICE_INFO *deviceInfoPtr = NULL;\n\tint initStatus, status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRange( createInfo->arg1, CRYPT_DEVICE ) );\n\tREQUIRES( ( createInfo->arg1 != CRYPT_DEVICE_PKCS11 && \\\n\t\t\t\tcreateInfo->arg1 != CRYPT_DEVICE_CRYPTOAPI ) || \\\n\t\t\t  ( createInfo->strArgLen1 >= MIN_NAME_LENGTH && \\\n\t\t\t\tcreateInfo->strArgLen1 <= CRYPT_MAX_TEXTSIZE ) );\n\n\t/* Wait for any async device driver binding to complete */\n\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )\n\t\t{\n\t\t/* The kernel is shutting down, bail out */\n\t\tDEBUG_DIAG(( \"Exiting due to kernel shutdown\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Pass the call on to the lower-level open function */\n\tinitStatus = openDevice( &iCryptDevice, createInfo->cryptOwner,\n\t\t\t\t\t\t\t createInfo->arg1, createInfo->strArg1,\n\t\t\t\t\t\t\t createInfo->strArgLen1, &deviceInfoPtr );\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( deviceInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\n\t\t/* Since no object has been created there's nothing to get a \n\t\t   detailed error string from, but we can at least send the \n\t\t   information to the debug output */\n#ifdef USE_PKCS11\n\t\tDEBUG_PRINT(( \"Device open error: %s.\\n\",\n\t\t\t\t\t  ( deviceInfoPtr->type == CRYPT_DEVICE_PKCS11 && \\\n\t\t\t\t\t\tdeviceInfoPtr->devicePKCS11 != NULL && \\\n\t\t\t\t\t\tdeviceInfoPtr->devicePKCS11->errorInfo.errorStringLength > 0 ) ? \\\n\t\t\t\t\t    deviceInfoPtr->devicePKCS11->errorInfo.errorString : \\\n\t\t\t\t\t\t\"<<<No information available>>>\" ));\n#endif /* USE_PKCS11 */\n\n\t\t/* The init failed, make sure that the object gets destroyed when we\n\t\t   notify the kernel that the setup process is complete */\n\t\tkrnlSendNotifier( iCryptDevice, IMESSAGE_DESTROY );\n\t\t}\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCryptDevice, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusOK( status ) && \\\n\t\tcreateInfo->arg1 == CRYPT_DEVICE_CRYPTOAPI )\n\t\t{\n\t\t/* If it's a device that doesn't require an explicit login, move it\n\t\t   into the initialised state */\n\t\tstatus = krnlSendMessage( iCryptDevice, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\tif( cryptStatusError( status ) )\n\t\t\tkrnlSendNotifier( iCryptDevice, IMESSAGE_DESTROY );\n\t\t}\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\tcreateInfo->cryptHandle = iCryptDevice;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the internal system device object.  This is somewhat special in\n   that it can't be destroyed through a normal message (it can only be done\n   from one place in the kernel) so if the open fails we don't use the normal\n   signalling mechanism to destroy it but simply return an error code to the\n   caller (the cryptlib init process).  This causes the init to fail and\n   destroys the object when the kernel shuts down */\n\nCHECK_RETVAL \\\nstatic int createSystemDeviceObject( void )\n\t{\n\tCRYPT_DEVICE iSystemObject;\n\tDEVICE_INFO *deviceInfoPtr;\n\tint initStatus, status;\n\n\t/* Pass the call on to the lower-level open function.  This device is\n\t   unique and has no owner or type.\n\n\t   Normally if an object init fails we tell the kernel to destroy it by \n\t   sending it a destroy message, which is processed after the object's \n\t   status has been set to normal.  However we don't have the privileges \n\t   to do this for the system object (or the default user object) so we \n\t   just pass the error code back to the caller, which causes the \n\t   cryptlib init to fail.\n\t   \n\t   In addition the init can fail in one of two ways the object isn't\n\t   even created (deviceInfoPtr == NULL, nothing to clean up) in which \n\t   case we bail out immediately, or the object is created but wasn't set \n\t   up properly (deviceInfoPtr is allocated, but the object can't be \n\t   used) in which case we bail out after we update its status.\n\n\t   A failure at this point is a bit problematic because it's not \n\t   possible to inform the caller that the system object was successfully \n\t   created but something went wrong after that.  That is, it's assumed\n\t   that create-object operations are atomic so that a failure status\n\t   indicates that all allocations and whatnot were rolled back, but \n\t   since the system object can only be destroyed from within the kernel\n\t   once it's been created there's no way to roll back the creation of an\n\t   incomplete system object.  In fact it's not even clear what *could* \n\t   cause a failure at this point apart from \"circumstances beyond our \n\t   control\" (memory corruption, a coding error, or something similar).  \n\t   Because this is a can't-occur situation the best course of action for \n\t   backing out of having a partially-initialised system object that's \n\t   created at and exists at a level below what the standard system \n\t   cleanup routines can handle is uncertain.\n\t   \n\t   At the moment we just exit and (potentialy) leak the memory, if this\n\t   situation ever occurs then presumably the calling application will \n\t   exit and the OS will release the memory for us.  This is somewhat\n\t   ugly, but it's not really clear what other action we can take in the\n\t   error handler for a can-never-occur error */\n\tinitStatus = openDevice( &iSystemObject, CRYPT_UNUSED, CRYPT_DEVICE_NONE,\n\t\t\t\t\t\t\t NULL, 0, &deviceInfoPtr );\n\tif( deviceInfoPtr == NULL )\n\t\treturn( initStatus );\t/* Create object failed, return immediately */\n\tENSURES( iSystemObject == SYSTEM_OBJECT_HANDLE );\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iSystemObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\n\t/* The object has been initialised, move it into the initialised state */\n\treturn( krnlSendMessage( iSystemObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t MESSAGE_VALUE_UNUSED,\n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED ) );\n\t}\n\n/* Generic management function for this class of object.  Unlike the usual\n   multilevel init process which is followed for other objects, the devices\n   have an OR rather than an AND relationship since the devices are\n   logically independent so we set a flag for each device type that's\n   successfully initialised rather than recording an init level */\n\ntypedef CHECK_RETVAL int ( *DEVICEINIT_FUNCTION )( void );\ntypedef void ( *DEVICEND_FUNCTION )( void );\ntypedef struct {\n\tconst DEVICEINIT_FUNCTION deviceInitFunction;\n\tconst DEVICEND_FUNCTION deviceEndFunction;\n\tconst int initFlag;\n\t} DEVICEINIT_INFO;\n\t\t\n#define DEV_NONE_INITED\t\t\t0x00\n#define DEV_PKCS11_INITED\t\t0x01\n#define DEV_CRYPTOAPI_INITED\t0x02\n#define DEV_HARDWARE_INITED\t\t0x04\n\nCHECK_RETVAL \\\nint deviceManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tstatic const DEVICEINIT_INFO deviceInitTbl[] = {\n#ifdef USE_PKCS11\n\t\t{ deviceInitPKCS11, deviceEndPKCS11, DEV_PKCS11_INITED },\n#endif /* USE_PKCS11 */\n#ifdef USE_CRYPTOAPI\n\t\t{ deviceInitCryptoAPI, deviceEndCryptoAPI, DEV_CRYPTOAPI_INITED },\n#endif /* USE_CRYPTOAPI */\n#ifdef USE_HARDWARE\n\t\t{ deviceInitHardware, deviceEndHardware, DEV_HARDWARE_INITED },\n#endif /* USE_HARDWARE */\n\t\t{ NULL, NULL, 0 }, { NULL, NULL, 0 }\n\t\t};\n\tstatic int initFlags = DEV_NONE_INITED;\n\tint i, status, LOOP_ITERATOR;\n\n\tREQUIRES( action == MANAGEMENT_ACTION_PRE_INIT || \\\n\t\t\t  action == MANAGEMENT_ACTION_INIT || \\\n\t\t\t  action == MANAGEMENT_ACTION_PRE_SHUTDOWN || \\\n\t\t\t  action == MANAGEMENT_ACTION_SHUTDOWN );\n\n\tswitch( action )\n\t\t{\n\t\tcase MANAGEMENT_ACTION_PRE_INIT:\n\t\t\tstatus = createSystemDeviceObject();\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{ DEBUG_DIAG(( \"System object creation failed\" )); }\n\t\t\telse\n\t\t\t\t{ DEBUG_DIAG(( \"Created system object\" )); }\n\t\t\treturn( status );\n\n\t\tcase MANAGEMENT_ACTION_INIT:\n#ifndef CONFIG_FUZZ\n\t\t\tLOOP_SMALL( i = 0,\n\t\t\t\t\t\tdeviceInitTbl[ i ].deviceInitFunction != NULL && \\\n\t\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( deviceInitTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tDEVICEINIT_INFO ),\n\t\t\t\t\t\ti++ )\n\t\t\t\t{\n\t\t\t\tif( krnlIsExiting() )\n\t\t\t\t\t{\n\t\t\t\t\t/* The kernel is shutting down, exit */\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t\t}\n\t\t\t\tstatus = deviceInitTbl[ i ].deviceInitFunction();\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\tinitFlags |= deviceInitTbl[ i ].initFlag;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tENSURES( i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t DEVICEINIT_INFO ) );\n#endif /* !CONFIG_FUZZ */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase MANAGEMENT_ACTION_PRE_SHUTDOWN:\n\t\t\t/* In theory we could signal the background entropy poll to \n\t\t\t   start wrapping up at this point, however if the background \n\t\t\t   polling is being performed in a thread or task then the \n\t\t\t   shutdown is already signalled via the kernel shutdown flag.  \n\t\t\t   If it's performed by forking off a process, as it is on Unix \n\t\t\t   systems, there's no easy way to communicate with this process \n\t\t\t   so the shutdown function just kill()s it.  Because of this we \n\t\t\t   don't try and do anything here, although this call is left in \n\t\t\t   place as a no-op in case it's needed in the future */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase MANAGEMENT_ACTION_SHUTDOWN:\n\t\t\tLOOP_MED( i = 0,\n\t\t\t\t\t  deviceInitTbl[ i ].deviceEndFunction != NULL && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( deviceInitTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\tDEVICEINIT_INFO ),\n\t\t\t\t\t  i++ )\n\t\t\t\t{\n\t\t\t\tif( initFlags & deviceInitTbl[ i ].initFlag )\n\t\t\t\t\tdeviceInitTbl[ i ].deviceEndFunction();\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tENSURES( i < FAILSAFE_ARRAYSIZE( deviceInitTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t DEVICEINIT_INFO ) );\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n"
  },
  {
    "path": "deps/cl345/cryptenv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Enveloping Routines\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1996-2012\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"envelope.h\"\n#else\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n/* The default size for the envelope buffer.  On 16-bit systems they're\n   smaller because of memory and int size limitations */\n\n#if defined( CONFIG_CONSERVE_MEMORY )\n  #define DEFAULT_BUFFER_SIZE\t\t8192\n#elif INT_MAX <= 32767\n  #define DEFAULT_BUFFER_SIZE\t\t16384\n#else\n  #define DEFAULT_BUFFER_SIZE\t\t32768\n#endif /* OS-specific envelope size defines */\n\n/* When pushing and popping data, overflow and underflow errors can be\n   recovered from by adding or removing data so we don't retain the error\n   state for these error types */\n\n#define isRecoverableError( status ) \\\n\t\t( ( status ) == CRYPT_ERROR_OVERFLOW || \\\n\t\t  ( status ) == CRYPT_ERROR_UNDERFLOW )\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check overall envelope data.  This is a general check for \n   reasonable values that's more targeted at catching inadvertent memory \n   corruption than a strict sanity check, format-specific sanity checks are\n   performed by individual modules */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckEnvelope( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Check overall envelope data.  The contentType and usage can be un-set \n\t   until data is pushed into the envelope, so we allow _NONE values for\n\t   these as well as actual values */\n\tif( !isEnumRange( envelopeInfoPtr->type, CRYPT_FORMAT ) || \\\n\t\t!isEnumRangeOpt( envelopeInfoPtr->contentType, CRYPT_CONTENT ) || \\\n\t\t!isEnumRangeOpt( envelopeInfoPtr->usage, ACTION ) || \\\n\t\tenvelopeInfoPtr->version < 0 || \\\n\t\tenvelopeInfoPtr->version > 10 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !CHECK_FLAGS( envelopeInfoPtr->flags, ENVELOPE_FLAG_NONE, \n\t\t\t\t\t  ENVELOPE_FLAG_MAX ) || \\\n\t\t!CHECK_FLAGS( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NONE, \n\t\t\t\t\t  ENVDATA_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers.  We don't have to check the function pointers\n\t   because they're validated each time they're dereferenced */\n\tif( !DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) || \\\n\t\t!DATAPTR_ISVALID( envelopeInfoPtr->actionList ) || \\\n\t\t!DATAPTR_ISVALID( envelopeInfoPtr->postActionList ) || \\\n\t\t!DATAPTR_ISVALID( envelopeInfoPtr->lastAction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Action lists\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !DATAPTR_ISVALID( envelopeInfoPtr->contentList ) || \\\n\t\t!DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Content list\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check encryption action values */\n\tif( envelopeInfoPtr->cryptActionSize != CRYPT_UNUSED && \\\n\t\t!isShortIntegerRange( envelopeInfoPtr->cryptActionSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Crypt actions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( envelopeInfoPtr->signActionSize != CRYPT_UNUSED && \\\n\t\t!isShortIntegerRange( envelopeInfoPtr->signActionSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Sign actions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isShortIntegerRange( envelopeInfoPtr->extraDataSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Extra data\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check buffer values */\n\tif( envelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \\\n\t\tenvelopeInfoPtr->bufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Buffer size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( envelopeInfoPtr->buffer == NULL )\n\t\t{\n\t\tif( envelopeInfoPtr->bufPos != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Spurious buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( envelopeInfoPtr->bufPos < 0 || \\\n\t\t\tenvelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !safeBufferCheck( envelopeInfoPtr->buffer, \n\t\t\t\t\t\t\t  envelopeInfoPtr->bufSize ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Buffer state\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( envelopeInfoPtr->auxBuffer == NULL )\n\t\t{\n\t\tif( envelopeInfoPtr->auxBufPos != 0 || \\\n\t\t\tenvelopeInfoPtr->auxBufSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Spurious auxiliary buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( envelopeInfoPtr->auxBufSize <= 0 || \\\n\t\t\tenvelopeInfoPtr->auxBufSize > MAX_BUFFER_SIZE || \\\n\t\t\tenvelopeInfoPtr->auxBufPos < 0 || \\\n\t\t\tenvelopeInfoPtr->auxBufPos > envelopeInfoPtr->auxBufSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Auxiliary buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( envelopeInfoPtr->partialBufPos < 0 || \\\n\t\tenvelopeInfoPtr->partialBufPos > PARTIAL_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Partial buffer info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( envelopeInfoPtr->blockBufferPos < 0 || \\\n\t\tenvelopeInfoPtr->blockBufferPos >= CRYPT_MAX_IVSIZE || \\\n\t\tenvelopeInfoPtr->blockSize < 0 || \\\n\t\tenvelopeInfoPtr->blockSize > CRYPT_MAX_IVSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Block buffer info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( envelopeInfoPtr->oobEventCount < 0 || \\\n\t\tenvelopeInfoPtr->oobEventCount > 10 || \\\n\t\t!isShortIntegerRange( envelopeInfoPtr->oobDataLeft ) || \\\n\t\tenvelopeInfoPtr->oobBufSize < 0 || \\\n\t\tenvelopeInfoPtr->oobBufSize > OOB_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: OOB info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check state information */\n\tif( !isEnumRangeOpt( envelopeInfoPtr->state, ENVELOPE_STATE ) || \\\n\t\t!isEnumRangeOpt( envelopeInfoPtr->envState, ENVSTATE ) || \\\n\t\t!isEnumRangeOpt( envelopeInfoPtr->deenvState, DEENVSTATE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: State\" ));\n\t\treturn( FALSE );\n\t\t}\n#ifdef USE_PGP\n\tif( !isEnumRangeOpt( envelopeInfoPtr->pgpDeenvState, PGP_DEENVSTATE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: PGP state\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_PGP */\n\n\t/* Check data size information */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\t!isIntegerRange( envelopeInfoPtr->payloadSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Payload size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isIntegerRange( envelopeInfoPtr->segmentSize ) || \\\n\t\t!isIntegerRange( envelopeInfoPtr->dataLeft ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Segment size\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check segmentation values */\n\tif( !isIntegerRange( envelopeInfoPtr->segmentStart ) || \\\n\t\t!isIntegerRange( envelopeInfoPtr->segmentDataStart ) || \\\n\t\t!isIntegerRange( envelopeInfoPtr->segmentDataEnd ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Segment info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check associated handles */\n\tif( !isHandleRangeValid( envelopeInfoPtr->objectHandle ) || \\\n\t\t!( envelopeInfoPtr->ownerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t   isHandleRangeValid( envelopeInfoPtr->ownerHandle ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvelope: Object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Data Handling Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Push data into an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int envelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t IN_BUFFER_OPT( length ) const void *buffer,\n\t\t\t\t\t\t IN_DATALENGTH_Z const int length, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tconst ENV_PROCESSPOSTAMBLE_FUNCTION processPostambleFunction = \\\n\t\t\t\t( ENV_PROCESSPOSTAMBLE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->processPostambleFunction );\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( ( buffer == NULL && length == 0 ) || \\\n\t\t\tisReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( ( buffer == NULL && length == 0 ) || \\\n\t\t\t  ( buffer != NULL && length > 0 && length < MAX_BUFFER_SIZE ) );\n\tREQUIRES( processPostambleFunction != NULL );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If we haven't started processing data yet, handle the initial data\n\t   specially */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t{\n\t\tconst ENV_CHECKMISSINGINFO_FUNCTION checkMissingInfoFunction = \\\n\t\t\t\t\t( ENV_CHECKMISSINGINFO_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->checkMissingInfoFunction );\n\t\tconst ENV_PROCESSPREAMBLE_FUNCTION processPreambleFunction = \\\n\t\t\t\t\t( ENV_PROCESSPREAMBLE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->processPreambleFunction );\n\n\t\tREQUIRES( checkMissingInfoFunction != NULL );\n\t\tREQUIRES( processPreambleFunction != NULL );\n\n\t\t/* Make sure that all of the information that we need to proceed is \n\t\t   present */\n\t\tstatus = checkMissingInfoFunction( envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t( buffer == NULL ) ? TRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If the envelope buffer hasn't been allocated yet, allocate it now */\n\t\tif( envelopeInfoPtr->buffer == NULL )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->buffer = \\\n\t\t\t\t\t\t\t\tsafeBufferAlloc( envelopeInfoPtr->bufSize );\n\t\t\tif( envelopeInfoPtr->buffer == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tmemset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );\n\t\t\t}\n\n\t\t/* Emit the header information into the envelope */\n\t\tstatus = processPreambleFunction( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( !isRecoverableError( status ) )\n\t\t\t\tenvelopeInfoPtr->errorState = status;\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* The envelope is ready to process data, move it into the high\n\t\t   state */\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->errorState = status;\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Move on to the data-processing state */\n\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_DATA;\n\t\t}\n\n\t/* If we're in the main data processing state, add the data and perform\n\t   any necessary actions on it */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_DATA )\n\t\t{\n\t\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\n\t\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t\tif( length > 0 )\n\t\t\t{\n\t\t\t/* Copy the data to the envelope */\n\t\t\tstatus = copyToEnvelopeFunction( envelopeInfoPtr, buffer, \n\t\t\t\t\t\t\t\t\t\t\t length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( !isRecoverableError( status ) )\n\t\t\t\t\tenvelopeInfoPtr->errorState = status;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t*bytesCopied = status;\n\n\t\t\treturn( ( *bytesCopied < length ) ? \\\n\t\t\t\t\tCRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t\t\t}\n\n\t\t/* This was a flush, move on to the postdata state */\n\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_POSTDATA;\n\t\tenvelopeInfoPtr->envState = ENVSTATE_NONE;\n\t\t}\n\n\tENSURES( envelopeInfoPtr->state == ENVELOPE_STATE_POSTDATA );\n\n\t/* We're past the main data-processing state, emit the postamble */\n\tstatus = processPostambleFunction( envelopeInfoPtr, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( !isRecoverableError( status ) )\n\t\t\tenvelopeInfoPtr->errorState = status;\n\t\treturn( status );\n\t\t}\n\tenvelopeInfoPtr->state = ENVELOPE_STATE_FINISHED;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int deenvelopePush( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t   IN_BUFFER_OPT( length ) const void *buffer,\n\t\t\t\t\t\t   IN_DATALENGTH_Z const int length, \n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\tBYTE *bufPtr = ( BYTE * ) buffer;\n\tint bytesIn = length, status = CRYPT_OK;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( ( buffer == NULL && length == 0 ) || \\\n\t\t\tisReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( ( buffer == NULL && length == 0 ) || \\\n\t\t\t  ( buffer != NULL && length > 0 && length < MAX_BUFFER_SIZE ) );\n\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If we haven't started processing data yet, handle the initial data\n\t   specially */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t{\n\t\tENV_PROCESSPREAMBLE_FUNCTION processPreambleFunction;\n\t\tBOOLEAN copiedData = FALSE;\n\n\t\t/* Perform any initialisation actions */\n\t\tif( envelopeInfoPtr->buffer == NULL )\n\t\t\t{\n\t\t\t/* Allocate the envelope buffer */\n\t\t\tenvelopeInfoPtr->buffer = \\\n\t\t\t\t\t\t\t\tsafeBufferAlloc( envelopeInfoPtr->bufSize );\n\t\t\tif( envelopeInfoPtr->buffer == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tmemset( envelopeInfoPtr->buffer, 0, envelopeInfoPtr->bufSize );\n\n\t\t\t/* Try and determine what the data format being used is.  If it \n\t\t\t   looks like PGP data, try and process it as such, otherwise \n\t\t\t   default to PKCS #7/CMS/S/MIME */\n#ifdef USE_PGP\n\t\t\tif( length > 0 && ( bufPtr[ 0 ] & 0x80 ) )\n\t\t\t\t{\n\t\t\t\t/* When we initially created the envelope we defaulted to CMS\n\t\t\t\t   formatting so we have to select PGP de-enveloping before \n\t\t\t\t   we can continue */\n\t\t\t\tenvelopeInfoPtr->type = CRYPT_FORMAT_PGP;\n\t\t\t\tinitPGPDeenveloping( envelopeInfoPtr );\n\t\t\t\t}\n\t\t\telse\n#endif /* USE_PGP */\n\t\t\t\t{\n\t\t\t\t/* The distinction between CRYPT_FORMAT_CRYPTLIB, \n\t\t\t\t   CRYPT_FORMAT_PKCS7/CRYPT_FORMAT_CMS, and \n\t\t\t\t   CRYPT_FORMAT_SMIME is only necessary when enveloping\n\t\t\t\t   because it affects the enveloping semantics (for\n\t\t\t\t   example whether we use issuerAndSerialNumber or\n\t\t\t\t   keyIdentifier to identify keys), so we identify all\n\t\t\t\t   PKCS #7/CMS/whatever envelopes as CRYPT_FORMAT_CMS */\n\t\t\t\tenvelopeInfoPtr->type = CRYPT_FORMAT_CMS;\n\t\t\t\t}\n\t\t\t}\n\t\tprocessPreambleFunction = ( ENV_PROCESSPREAMBLE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->processPreambleFunction );\n\t\tENSURES( processPreambleFunction != NULL );\n\n\t\t/* Since we're processing out-of-band information, just copy it in\n\t\t   directly */\n\t\tif( bytesIn > 0 )\n\t\t\t{\n\t\t\tconst int bytesToCopy = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr->bufPos, bytesIn );\n\n\t\t\tENSURES( bytesToCopy >= 0 && bytesToCopy <= length && \\\n\t\t\t\t\t envelopeInfoPtr->bufPos + \\\n\t\t\t\t\t\tbytesToCopy <= envelopeInfoPtr->bufSize );\n\t\t\tif( bytesToCopy > 0 )\n\t\t\t\t{\n\t\t\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, bytesToCopy,\n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\t\t\t\tmemcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,\n\t\t\t\t\t\tbufPtr, bytesToCopy );\n\t\t\t\tenvelopeInfoPtr->bufPos += bytesToCopy;\n\t\t\t\tbytesIn -= bytesToCopy;\n\t\t\t\t*bytesCopied = bytesToCopy;\n\t\t\t\tbufPtr += bytesToCopy;\n\t\t\t\tcopiedData = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Process the preamble */\n\t\tstatus = processPreambleFunction( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed at least some data and it's a non-fatal\n\t\t\t   error like an underflow, suppress it.  We need to do this\n\t\t\t   because the copy function above will always consume input (if\n\t\t\t   it can) and if we returned an error at this point it would\n\t\t\t   indicate to the caller that they can ignore the bytes-copied\n\t\t\t   parameter */\n\t\t\tif( isRecoverableError( status ) )\n\t\t\t\t{\n\t\t\t\tif( copiedData )\n\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* It's a fatal error, make it persistent */\n\t\t\t\tenvelopeInfoPtr->errorState = status;\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* The envelope is ready to process data, move it into the high\n\t\t   state */\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The envelope may already have been moved into the high state \n\t\t\t   as a side-effect of adding de-enveloping information (whether \n\t\t\t   the transition occurs here or in res_denv.c depends on the \n\t\t\t   order in which the caller performs operations) so if we get a \n\t\t\t   permission error it's means that we're already in the high \n\t\t\t   state and we can ignore it */\n\t\t\tif( status != CRYPT_ERROR_PERMISSION )\n\t\t\t\t{\n\t\t\t\tenvelopeInfoPtr->errorState = status;\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\n\t\t/* Move on to the data-processing state */\n\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_DATA;\n\t\t}\n\n\t/* If we're in the main data processing state, add the data and perform\n\t   any necessary actions on it */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_DATA )\n\t\t{\n\t\t/* If there's data to be copied, copy it into the envelope.  If we've\n\t\t   come from the predata state we may have zero bytes to copy if\n\t\t   everything was consumed by the preamble processing, or there may\n\t\t   be room to copy more in now if the preamble processing consumed \n\t\t   some of what was present */\n\t\tif( bytesIn > 0 )\n\t\t\t{\n\t\t\t/* Copy the data to the envelope */\n\t\t\tconst int byteCount = \\\n\t\t\t\tcopyToEnvelopeFunction( envelopeInfoPtr, bufPtr, bytesIn );\n\t\t\tif( cryptStatusError( byteCount ) )\n\t\t\t\t{\n\t\t\t\tif( !isRecoverableError( byteCount ) )\n\t\t\t\t\tenvelopeInfoPtr->errorState = byteCount;\n\t\t\t\treturn( byteCount );\n\t\t\t\t}\n\t\t\t*bytesCopied += byteCount;\n\t\t\tbytesIn -= byteCount;\n\t\t\tbufPtr += byteCount;\n\t\t\t}\n\n\t\t/* If we've reached the end of the payload (either by having seen the\n\t\t   EOC octets with the indefinite encoding or by having reached the \n\t\t   end of the single segment with the definite encoding), move on to \n\t\t   the postdata state */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS ) || \\\n\t\t\t( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\t\t  envelopeInfoPtr->segmentSize <= 0 ) )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_POSTDATA;\n\t\t\tenvelopeInfoPtr->deenvState = DEENVSTATE_NONE;\n\t\t\t}\n\n#ifdef USE_PGP\n\t\t/* Special-case for the wierd non-length-encoding that some PGP \n\t\t   implementations use for compressed data which uses neither a\n\t\t   definite nor indefinite-length encoding but consists of an \n\t\t   implicit \"until you run out of input\", see the comment in the PGP\n\t\t   readPacketHeader() for more details.  To accomodate this lack of\n\t\t   the data's ability to tell us when it's ended, if we're processing\n\t\t   PGP compressed data and there's no length information present and\n\t\t   it's a data flush we assume that that's all there is */\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\t\tenvelopeInfoPtr->usage == ACTION_COMPRESS && \\\n\t\t\tenvelopeInfoPtr->payloadSize == CRYPT_UNUSED && \\\n\t\t\tlength <= 0 )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_POSTDATA;\n\t\t\tenvelopeInfoPtr->deenvState = DEENVSTATE_NONE;\n\t\t\t}\n#endif /* USE_PGP */\n\t\t}\n\n\t/* If we're past the main data-processing state, process the postamble */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_POSTDATA )\n\t\t{\n\t\tconst ENV_PROCESSPOSTAMBLE_FUNCTION processPostambleFunction = \\\n\t\t\t\t\t( ENV_PROCESSPOSTAMBLE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->processPostambleFunction );\n\n\t\tREQUIRES( processPostambleFunction != NULL );\n\n\t\t/* Since we're processing trailer information, just copy it in\n\t\t   directly */\n\t\tif( bytesIn > 0 )\n\t\t\t{\n\t\t\tconst int bytesToCopy = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr->bufPos, bytesIn );\n\n\t\t\tENSURES( bytesToCopy >= 0 && bytesToCopy <= bytesIn && \\\n\t\t\t\t\t envelopeInfoPtr->bufPos + \\\n\t\t\t\t\t\tbytesToCopy <= envelopeInfoPtr->bufSize );\n\t\t\tif( bytesToCopy > 0 )\n\t\t\t\t{\n\t\t\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, bytesToCopy,\n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\t\t\t\tmemcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,\n\t\t\t\t\t\tbufPtr, bytesToCopy );\n\t\t\t\tenvelopeInfoPtr->bufPos += bytesToCopy;\n\t\t\t\t*bytesCopied += bytesToCopy;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Process the postamble.  Note that we need to check the caller-\n\t\t   supplied length value rather than the local bytesIn value to \n\t\t   determine whether this is a flush, since bytesIn is adjusted as \n\t\t   data is consumed and may have reached zero by the time we get \n\t\t   here.\n\t\t\n\t\t   During this processing we can encounter two special types of \n\t\t   recoverable error, CRYPT_ERROR_UNDERFLOW (we need more data to \n\t\t   continue) or OK_SPECIAL (we processed all of the data but there's \n\t\t   out-of-band information still to go).  If it's one of these then \n\t\t   we don't treat it as a standard error */\n\t\tstatus = processPostambleFunction( envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   ( length <= 0 ) ? TRUE : FALSE );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t{\n\t\t\tif( !isRecoverableError( status ) )\n\t\t\t\t{\n\t\t\t\tenvelopeInfoPtr->errorState = status;\n\n\t\t\t\t/* MACd and authenticated-encrypted envelopes differ \n\t\t\t\t   somewhat from signed envelopes in that the integrity \n\t\t\t\t   check results are available immediately that payload \n\t\t\t\t   processing is complete rather than afterwards as the \n\t\t\t\t   result of user action with signature metadata.  As a \n\t\t\t\t   result the postamble processing can return a \n\t\t\t\t   CRYPT_ERROR_SIGNATURE to indicate that although all data \n\t\t\t\t   was processed successfully (which would normally produce \n\t\t\t\t   a CRYPT_OK result) the integrity check for the data \n\t\t\t\t   failed.  To reconcile the two status values we treat the \n\t\t\t\t   envelope as if a CRYPT_OK had been returned (by marking \n\t\t\t\t   processing as being complete) while recording a \n\t\t\t\t   CRYPT_ERROR_SIGNATURE.  However we do return the \n\t\t\t\t   signature error since the user may be using authenticated \n\t\t\t\t   encryption and not even be aware that they should perform \n\t\t\t\t   an explicit check for a signature failure */\n\t\t\t\tif( status == CRYPT_ERROR_SIGNATURE && \\\n\t\t\t\t\t( envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_AUTHENC ) ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_FINISHED;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES( status == CRYPT_OK || status == OK_SPECIAL );\n\n\t\t/* If the postamble processing routine returns OK_SPECIAL then it's \n\t\t   processed enough of the postamble for the caller to continue, but \n\t\t   there's more to go so we shouldn't change the overall state yet */\n\t\tif( status == CRYPT_OK )\n\t\t\t{\n\t\t\t/* We've processed all data, we're done unless it's a detached\n\t\t\t   sig with the data supplied out-of-band */\n\t\t\tenvelopeInfoPtr->state = \\\n\t\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) ? \\\n\t\t\t\t\t\tENVELOPE_STATE_EXTRADATA : ENVELOPE_STATE_FINISHED;\n\t\t\t}\n\n\t\t/* At this point we always exit since the out-of-band data has to be\n\t\t   processed in a separate push */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's extra out-of-band data present, process it separately.  \n\t   This is slightly complicated by the fact that the single envelope is\n\t   being used to process two independent lots of data, so we have to be \n\t   careful to distinguish between handling of the main payload data and \n\t   handling of this additional out-of-band data */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_EXTRADATA )\n\t\t{\n\t\tconst ENV_PROCESSEXTRADATA_FUNCTION processExtraDataFunction = \\\n\t\t\t\t\t( ENV_PROCESSEXTRADATA_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->processExtraDataFunction );\n\n\t\tREQUIRES( processExtraDataFunction != NULL );\n\n\t\t/* We pass this point twice, the first time round we check the state \n\t\t   and if it's DEENVSTATE_DONE (set when processing of the main data \n\t\t   was completed) we reset it to DEENVSTATE_NONE and make sure that \n\t\t   it's a flush */\n\t\tif( envelopeInfoPtr->deenvState == DEENVSTATE_DONE )\n\t\t\t{\n\t\t\t/* We've finished with the main payload data, reset the state for \n\t\t\t   the additional out-of-band data.  Normally we exit here since \n\t\t\t   it's a flush, however if the hash value was supplied \n\t\t\t   externally (which means that hashing was never active, since \n\t\t\t   it was done by the caller) we drop through to the wrap-up, \n\t\t\t   since there's no second flush of payload data to be performed \n\t\t\t   and so the flush applies to both sets of data */\n\t\t\tenvelopeInfoPtr->deenvState = DEENVSTATE_NONE;\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t   ENVDATA_FLAG_HASHACTIONSACTIVE ) )\n\t\t\t\treturn( length ? CRYPT_ERROR_BADDATA : CRYPT_OK );\n\t\t\t}\n\n\t\t/* This is just raw additional data so we feed it directly to the \n\t\t   processing function.  If this is a flush then the buffer will be\n\t\t   set to NULL which the low-level routines don't allow so we \n\t\t   substitute an empty buffer */\n\t\tstatus = processExtraDataFunction( envelopeInfoPtr, \n\t\t\t\t\t\t\t( buffer == NULL ) ? \"\" : buffer, length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t*bytesCopied = length;\n\t\t\tif( length <= 0 )\n\t\t\t\tenvelopeInfoPtr->state = ENVELOPE_STATE_FINISHED;\n\t\t\t}\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Pop data from an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int envelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\tOUT_BUFFER( length, *bytesCopied ) void *buffer,\n\t\t\t\t\t\tIN_DATALENGTH const int length, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tconst ENV_COPYFROMENVELOPE_FUNCTION copyFromEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYFROMENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyFromEnvelopeFunction );\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( copyFromEnvelopeFunction != NULL );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If we haven't reached the data yet force a flush to try and get to \n\t   it.  We can end up with this condition if the caller doesn't push in\n\t   any enveloping information, or pushes in enveloping information and \n\t   then immediately tries to pop data without an intervening flush (or \n\t   implicit flush on the initial push) to resolve the state of the data \n\t   in the envelope */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t{\n\t\tint dummy;\n\n\t\t/* If no data has been pushed yet then we can't go any further.  \n\t\t   This typically happens if the user calls cryptPopData() without\n\t\t   first calling cryptPushData() */\n\t\tif( envelopeInfoPtr->bufPos <= 0 )\n\t\t\t{\n\t\t\t/* There is one situation in which we can pop data without first\n\t\t\t   pushing anything and that's when we're using a detached\n\t\t\t   signature and the hash value has been supplied externally,\n\t\t\t   in which case there's nothing to push */\n\t\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t\t}\n\n\t\tstatus = envelopePush( envelopeInfoPtr, NULL, 0, &dummy );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If we still haven't got anywhere return an underflow error */\n\t\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\t/* Copy the data from the envelope to the output */\n\tstatus = copyFromEnvelopeFunction( envelopeInfoPtr, buffer, length, \n\t\t\t\t\t\t\t\t\t   bytesCopied, ENVCOPY_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\tenvelopeInfoPtr->errorState = status;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int deenvelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t  OUT_BUFFER( length, *bytesCopied ) void *buffer,\n\t\t\t\t\t\t  IN_DATALENGTH const int length, \n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tconst ENV_COPYFROMENVELOPE_FUNCTION copyFromEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYFROMENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyFromEnvelopeFunction );\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( copyFromEnvelopeFunction != NULL );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If we haven't reached the data yet force a flush to try and get to \n\t   it.  We can end up with this condition if the caller doesn't push in\n\t   any de-enveloping information, or pushes in de-enveloping information \n\t   and then immediately tries to pop data without an intervening flush \n\t   (or implicit flush on the initial push) to resolve the state of the \n\t   data in the envelope */\n\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t{\n\t\tint dummy;\n\n\t\t/* If no data has been pushed yet then we can't go any further.  \n\t\t   This typically happens if the user calls cryptPopData() without\n\t\t   first calling cryptPushData() */\n\t\tif( envelopeInfoPtr->bufPos <= 0 )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t\tstatus = deenvelopePush( envelopeInfoPtr, NULL, 0, &dummy );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If we still haven't got anywhere return an underflow error */\n\t\tif( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\t/* Copy the data from the envelope to the output */\n\tstatus = copyFromEnvelopeFunction( envelopeInfoPtr, buffer, length, \n\t\t\t\t\t\t\t\t\t   bytesCopied, ENVCOPY_FLAG_NONE );\n\tif( cryptStatusError( status ) && !isRecoverableError( status ) )\n\t\tenvelopeInfoPtr->errorState = status;\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEnvelope Message Handler\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle a message sent to an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int envelopeMessageFunction( INOUT TYPECAST( ENVELOPE_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tvoid *messageDataPtr,\n\t\t\t\t\t\t\t\t\tIN_INT_Z const int messageValue )\n\t{\n\tENVELOPE_INFO *envelopeInfoPtr = ( ENVELOPE_INFO * ) objectInfoPtr;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isIntegerRange( messageValue ) );\n\n\t/* Process destroy object messages */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\tint status = CRYPT_OK;\n\n\t\t/* Check to see whether the envelope still needs operations \n\t\t   performed on it to resolve the state of the data within it (for \n\t\t   example if the caller pushes data but doesn't flush it, there \n\t\t   will be a few bytes left that can't be popped).  For enveloping, \n\t\t   destroying the envelope while it's in any state other than \n\t\t   ENVELOPE_STATE_PREDATA or ENVELOPE_STATE_FINISHED or if there's \n\t\t   data still left in the buffer is regarded as an error.  For de-\n\t\t   enveloping we have to be more careful since deenveloping \n\t\t   information required to resolve the envelope state could be \n\t\t   unavailable so we shouldn't return an error if something like a \n\t\t   signature check remains to be done.  What we therefore do is \n\t\t   check to see whether we've processed any data yet and report an \n\t\t   error if there's data left in the envelope or if we're destroying \n\t\t   it in the middle of processing data */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t{\n\t\t\tconst BOOLEAN isAuthEnvelope = \\\n\t\t\t\t\t( envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_AUTHENC ) ) ) ? \\\n\t\t\t\t\tTRUE : FALSE;\n\n\t\t\t/* If we've got to the point of processing data in the envelope\n\t\t\t   and there's either more to come or some left to pop, we\n\t\t\t   shouldn't be destroying it yet.  This straightforward check \n\t\t\t   is complicated by the integrity check performed with \n\t\t\t   authenticated envelopes, leading to two special cases:\n\t\t\t   \n\t\t\t   1. If the integrity checks fails then the integrity-check-\n\t\t\t\t  failed status prevents the user from popping the \n\t\t\t\t  (corrupted) data so that there may be data left in the \n\t\t\t\t  envelope through no fault of the user.  In this case we \n\t\t\t\t  don't treat the data-left status as an error.\n\t\t\t\t  \n\t\t\t\t2. If an attacker truncates the data in an attempt to \n\t\t\t\t   convert a fatal CRYPT_ERROR_SIGNATURE into a more benign \n\t\t\t\t   CRYPT_ERROR_UNDERFLOW then we want to try and alert the \n\t\t\t\t   caller to the fact that there's a problem, so we convert \n\t\t\t\t   a non-finished state for an authenticated envelope into \n\t\t\t\t   an integrity-check failure */\n\t\t\tif( envelopeInfoPtr->state == ENVELOPE_STATE_DATA )\n\t\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\tif( ( envelopeInfoPtr->state == ENVELOPE_STATE_POSTDATA || \\\n\t\t\t\t  envelopeInfoPtr->state == ENVELOPE_STATE_FINISHED ) && \\\n\t\t\t\tenvelopeInfoPtr->dataLeft > 0 && \\\n\t\t\t\t!( isAuthEnvelope && \\\n\t\t\t\t   envelopeInfoPtr->errorState == CRYPT_ERROR_SIGNATURE ) )\n\t\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\tif( status == CRYPT_ERROR_INCOMPLETE && isAuthEnvelope )\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If we're in the middle of processing data we shouldn't be\n\t\t\t   destroying the envelope yet */\n\t\t\tif( envelopeInfoPtr->state != ENVELOPE_STATE_PREDATA && \\\n\t\t\t\tenvelopeInfoPtr->state != ENVELOPE_STATE_FINISHED )\n\t\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\tif( envelopeInfoPtr->bufPos > 0 )\n\t\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\t}\n\n\t\t/* Delete the action and content lists */\n\t\tdeleteActionLists( envelopeInfoPtr );\n\t\tif( DATAPTR_ISSET( envelopeInfoPtr->contentList ) )\n\t\t\tdeleteContentList( envelopeInfoPtr );\n\n#ifdef USE_COMPRESSION\n\t\t/* Delete the zlib compression state information if necessary */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t   ENVELOPE_FLAG_ZSTREAMINITED ) )\n\t\t\t{\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t\tinflateEnd( &envelopeInfoPtr->zStream );\n\t\t\telse\n\t\t\t\tdeflateEnd( &envelopeInfoPtr->zStream );\n\t\t\t}\n#endif /* USE_COMPRESSION */\n\n\t\t/* Clean up keysets */\n\t\tif( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( envelopeInfoPtr->iSigCheckKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( envelopeInfoPtr->iEncryptionKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\n\t\t/* Clean up other envelope objects */\n\t\tif( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( envelopeInfoPtr->iExtraCertChain,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\n\t\t/* Clear and free the buffers if necessary */\n\t\tif( envelopeInfoPtr->buffer != NULL )\n\t\t\t{\n\t\t\tzeroise( envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );\n\t\t\tsafeBufferFree( envelopeInfoPtr->buffer );\n\t\t\t}\n\t\tif( envelopeInfoPtr->auxBuffer != NULL )\n\t\t\t{\n\t\t\tzeroise( envelopeInfoPtr->auxBuffer, envelopeInfoPtr->auxBufSize );\n\t\t\tclFree( \"envelopeMessageFunction\", envelopeInfoPtr->auxBuffer );\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_DELETEATTRIBUTE );\n\t\tREQUIRES( isAttribute( messageValue ) || \\\n\t\t\t\t  isInternalAttribute( messageValue ) );\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getEnvelopeAttribute( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  ( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getEnvelopeAttributeS( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t   messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( setEnvelopeAttribute( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  *( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setEnvelopeAttributeS( envelopeInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t\t   msgData->length, messageValue ) );\n\t\t\t}\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_ENV_PUSHDATA )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\t\tconst int length = msgData->length;\n\t\tint bytesCopied, status;\n\n\t\tassert( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t( isReadPtrDynamic( msgData->data, msgData->length ) ) );\n\n\t\tREQUIRES( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t  ( msgData->data != NULL && \\\n\t\t\t\t    msgData->length > 0 && msgData->length < MAX_BUFFER_SIZE ) );\n\n\t\t/* Unless we're told otherwise, we've copied zero bytes */\n\t\tmsgData->length = 0;\n\n\t\t/* Make sure that everything is in order */\n\t\tif( length == 0 )\n\t\t\t{\n\t\t\t/* If it's a flush make sure that we're in a state where this is\n\t\t\t   valid.  We can only perform a flush on enveloping if we're in\n\t\t\t   the data or postdata state, on deenveloping a flush can\n\t\t\t   happen at any time since the entire payload could be buffered\n\t\t\t   pending the addition of a deenveloping resource, so the\n\t\t\t   envelope goes from pre -> post in one step.  There is however\n\t\t\t   one special case in which a push in the pre-data state is \n\t\t\t   valid and that's when we're creating a zero-length CMS signed \n\t\t\t   message as a means of communicating authenticated attributes \n\t\t\t   (of all the standard users of CMS, only SCEP normally does \n\t\t\t   this).  In order to indicate that this special case is in\n\t\t\t   effect we require that the user set the ENVELOPE_ATTRONLY \n\t\t\t   flag before pushing data, although for completeness we could \n\t\t\t   also check the CMS attributes for the presence of SCEP \n\t\t\t   attributes.  The downside of this additional checking is that \n\t\t\t   it makes any non-SCEP use of signature-only CMS envelopes \n\t\t\t   impossible */\n\t\t\tif( envelopeInfoPtr->state == ENVELOPE_STATE_FINISHED )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) && \\\n\t\t\t\t( envelopeInfoPtr->state != ENVELOPE_STATE_DATA && \\\n\t\t\t\t  envelopeInfoPtr->state != ENVELOPE_STATE_POSTDATA ) && \\\n\t\t\t\t!( envelopeInfoPtr->state == ENVELOPE_STATE_PREDATA && \\\n\t\t\t\t   envelopeInfoPtr->usage == ACTION_SIGN && \\\n\t\t\t\t   envelopeInfoPtr->type == CRYPT_FORMAT_CMS && \\\n\t\t\t\t   TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ATTRONLY ) ) )\n\t\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( envelopeInfoPtr->state == ENVELOPE_STATE_FINISHED )\n\t\t\t\treturn( CRYPT_ERROR_COMPLETE );\n\t\t\t}\n\t\tif( cryptStatusError( envelopeInfoPtr->errorState ) )\n\t\t\treturn( envelopeInfoPtr->errorState );\n\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) && \\\n\t\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_NOSEGMENT ) && \\\n\t\t\tenvelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* If we're enveloping using a non-segmenting encoding of the \n\t\t\t   payload then the caller has to explicitly set the payload \n\t\t\t   size before they can add any data */\n\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DATASIZE, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\n\t\t/* Send the data to the envelope */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t{\n\t\t\tstatus = deenvelopePush( envelopeInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t\t length, &bytesCopied );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = envelopePush( envelopeInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t   length, &bytesCopied );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmsgData->length = bytesCopied;\n\t\telse\n\t\t\t{\n\t\t\t/* In some cases data can be copied even if an error status is\n\t\t\t   returned.  The most usual case is when the error is\n\t\t\t   recoverable (underflow or overflow), however when we're de-\n\t\t\t   enveloping we can also copy data but then stall with a \n\t\t\t   CRYPT_ENVELOPE_RESOURCE notification */\n\t\t\tif( ( isRecoverableError( status ) && bytesCopied > 0 ) || \\\n\t\t\t\t( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t ENVELOPE_FLAG_ISDEENVELOPE ) && \\\n\t\t\t\t   status == CRYPT_ENVELOPE_RESOURCE && bytesCopied > 0 ) )\n\t\t\t\tmsgData->length = bytesCopied;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tif( message == MESSAGE_ENV_POPDATA )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\t\tconst int length = msgData->length;\n\t\tint bytesCopied, status;\n\n\t\tassert( isWritePtrDynamic( msgData->data, msgData->length ) );\n\n\t\tREQUIRES( msgData->length > 0 && msgData->length < MAX_BUFFER_SIZE );\n\n\t\t/* Unless we're told otherwise, we've copied zero bytes */\n\t\tmsgData->length = 0;\n\n\t\t/* Make sure that everything is in order */\n\t\tif( cryptStatusError( envelopeInfoPtr->errorState ) )\n\t\t\treturn( envelopeInfoPtr->errorState );\n\n\t\t/* Get the data from the envelope */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t{\n\t\t\tstatus = deenvelopePop( envelopeInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t\tlength, &bytesCopied );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = envelopePop( envelopeInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t  length, &bytesCopied );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmsgData->length = bytesCopied;\n\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Create an envelope.  This is a low-level function encapsulated by\n   createEnvelope() and used to manage error exits */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int initEnvelope( OUT_HANDLE_OPT CRYPT_ENVELOPE *iCryptEnvelope,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t OUT_PTR_OPT ENVELOPE_INFO **envelopeInfoPtrPtr )\n\t{\n\tENVELOPE_INFO *envelopeInfoPtr;\n\tconst BOOLEAN isDeenvelope = ( formatType == CRYPT_FORMAT_AUTO ) ? \\\n\t\t\t\t\t\t\t\t TRUE : FALSE;\n\tconst int subType = \\\n\t\t\tisDeenvelope ? SUBTYPE_ENV_DEENV : \\\n\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\tSUBTYPE_ENV_ENV_PGP : SUBTYPE_ENV_ENV;\n\tconst int storageSize = 3 * sizeof( CONTENT_LIST );\n\tint status;\n\n\tassert( isWritePtr( iCryptEnvelope, sizeof( CRYPT_ENVELOPE * ) ) );\n\tassert( isWritePtr( envelopeInfoPtrPtr, sizeof( ENVELOPE_INFO * ) ) );\n\n\tREQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( formatType > CRYPT_FORMAT_NONE && \\\n\t\t\t  formatType < CRYPT_FORMAT_LAST_EXTERNAL );\n\n\t/* Clear return values */\n\t*iCryptEnvelope = CRYPT_ERROR;\n\t*envelopeInfoPtrPtr = NULL;\n\n\t/* If PGP support is disabled we can't specify PGP as a target format */\n#ifndef USE_PGP\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n#endif /* USE_PGP */\n\n\t/* Create the envelope object */\n\tstatus = krnlCreateObject( iCryptEnvelope, ( void ** ) &envelopeInfoPtr, \n\t\t\t\t\t\t\t   sizeof( ENVELOPE_INFO ) + storageSize, \n\t\t\t\t\t\t\t   OBJECT_TYPE_ENVELOPE, subType, \n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, iCryptOwner, \n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, envelopeMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( envelopeInfoPtr != NULL );\n\t*envelopeInfoPtrPtr = envelopeInfoPtr;\n\tenvelopeInfoPtr->objectHandle = *iCryptEnvelope;\n\tenvelopeInfoPtr->ownerHandle = iCryptOwner;\n\tenvelopeInfoPtr->bufSize = DEFAULT_BUFFER_SIZE;\n\tif( isDeenvelope )\n\t\tINIT_FLAGS( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE );\n\telse\n\t\tINIT_FLAGS( envelopeInfoPtr->flags, ENVELOPE_FLAG_NONE );\n\tenvelopeInfoPtr->type = formatType;\n\tenvelopeInfoPtr->state = ENVELOPE_STATE_PREDATA;\n\tINIT_FLAGS( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NONE );\n\tDATAPTR_SET( envelopeInfoPtr->preActionList, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->actionList, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->postActionList, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->contentList, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, NULL );\n\tenvelopeInfoPtr->storageSize = storageSize;\n\tstatus = initMemPool( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t  envelopeInfoPtr->storage, storageSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up any internal objects to contain invalid handles */\n\tenvelopeInfoPtr->iCryptContext = \\\n\t\tenvelopeInfoPtr->iExtraCertChain = CRYPT_ERROR;\n\tenvelopeInfoPtr->iSigCheckKeyset = envelopeInfoPtr->iEncryptionKeyset = \\\n\t\tenvelopeInfoPtr->iDecryptionKeyset = CRYPT_ERROR;\n\tenvelopeInfoPtr->payloadSize = CRYPT_UNUSED;\n\n\t/* Set up the enveloping methods */\n\tif( isDeenvelope )\n\t\t{\n\t\t/* For de-enveloping we default to PKCS #7/CMS/SMIME, if the data \n\t\t   is in some other format we'll adjust the function pointers once \n\t\t   the user pushes in the first data quantity */\n\t\tinitCMSDeenveloping( envelopeInfoPtr );\n\t\tinitDeenvelopeStreaming( envelopeInfoPtr );\n\t\tinitDenvResourceHandling( envelopeInfoPtr );\n\t\t}\n\telse\n\t\t{\n\t\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t\tinitPGPEnveloping( envelopeInfoPtr );\n\t\telse\n\t\t\tinitCMSEnveloping( envelopeInfoPtr );\n\t\tinitEnvelopeStreaming( envelopeInfoPtr );\n\t\tinitEnvResourceHandling( envelopeInfoPtr );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createEnvelope( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo, \n\t\t\t\t\tSTDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\tSTDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_ENVELOPE iCryptEnvelope;\n\tENVELOPE_INFO *envelopeInfoPtr = NULL;\n\tint initStatus, status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( createInfo->arg1 > CRYPT_FORMAT_NONE && \\\n\t\t\t  createInfo->arg1 < CRYPT_FORMAT_LAST_EXTERNAL );\n\n\t/* Pass the call on to the lower-level open function */\n\tinitStatus = initEnvelope( &iCryptEnvelope, createInfo->cryptOwner,\n\t\t\t\t\t\t\t   createInfo->arg1, &envelopeInfoPtr );\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( envelopeInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\n\t\t/* Since no object has been created there's nothing to get a \n\t\t   detailed error string from, but we can at least send the \n\t\t   information to the debug output */\n\t\tDEBUG_PRINT(( \"Envelope create error: %s.\\n\",\n\t\t\t\t\t  ( envelopeInfoPtr->errorInfo.errorStringLength > 0 ) ? \\\n\t\t\t\t\t    envelopeInfoPtr->errorInfo.errorString : \\\n\t\t\t\t\t\t\"<<<No information available>>>\" ));\n\n\t\t/* The init failed, make sure that the object gets destroyed when we \n\t\t   notify the kernel that the setup process is complete */\n\t\tkrnlSendNotifier( iCryptEnvelope, IMESSAGE_DESTROY );\n\t\t}\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\tcreateInfo->cryptHandle = iCryptEnvelope;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/cryptkey.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Keyset Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"pgp_rw.h\"\n  #include \"keyset.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check keyset data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckKeyset( const KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isReadPtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\t/* Check overall keyset data */\n\tif( keysetInfoPtr->type == KEYSET_FILE )\n\t\t{\n\t\tif( !isEnumRange( keysetInfoPtr->subType, KEYSET_SUBTYPE ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: General info (file keyset)\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isEnumRange( keysetInfoPtr->type, KEYSET ) || \\\n\t\t\tkeysetInfoPtr->subType != KEYSET_SUBTYPE_NONE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: General info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( !CHECK_FLAGS( keysetInfoPtr->flags, KEYSET_FLAG_NONE, \n\t\t\t\t\t  KEYSET_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckKeyset: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check keyset data storage */\n\tif( DATAPTR_ISSET( keysetInfoPtr->keyData ) )\n\t\t{\n\t\tif( keysetInfoPtr->keyDataSize <= 0 || \\\n\t\t\tkeysetInfoPtr->keyDataSize >= MAX_BUFFER_SIZE || \\\n\t\t\tkeysetInfoPtr->keyDataNoObjects < 0 || \\\n\t\t\tkeysetInfoPtr->keyDataNoObjects > 16 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: Keyset data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !DATAPTR_ISNULL( keysetInfoPtr->keyData ) || \\\n\t\t\tkeysetInfoPtr->keyDataSize != 0 || \\\n\t\t\tkeysetInfoPtr->keyDataNoObjects != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: Spurious keyset data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check subtype-specific data */\n\tswitch( keysetInfoPtr->type )\n\t\t{\n\t\tcase KEYSET_FILE:\n\t\t\t{\n\t\t\tconst FILE_INFO *fileInfo = keysetInfoPtr->keysetFile;\n\n\t\t\tif( fileInfo->iHardwareDevice != CRYPT_UNUSED && \\\n\t\t\t\t!isHandleRangeValid( fileInfo->iHardwareDevice ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: File info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n#ifdef USE_HTTP\n\t\tcase KEYSET_HTTP:\n\t\t\t{\n\t\t\tconst HTTP_INFO *httpInfo = keysetInfoPtr->keysetHTTP;\n\n\t\t\tif( httpInfo->bufPos < 0 || \\\n\t\t\t\thttpInfo->bufPos >= MAX_BUFFER_SIZE )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: HTTP info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_HTTP */\n\n#ifdef USE_LDAP\n\t\tcase KEYSET_LDAP:\n\t\t\t/* Nothing further to check */\n\t\t\tbreak;\n#endif /* USE_LDAP */\n\n#if defined( USE_DBMS )\n\t\tcase KEYSET_DBMS:\n\t\t\t{\n\t\t\tconst DBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\n\t\t\t/* Perform a rather ugly check of the DBMS flags, unfortunately\n\t\t\t   we can't see these values outside dbms.h */\n\t\t\tif( !CHECK_FLAGS( dbmsInfo->flags, 0, 0x20 ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckKeyset: DBMS info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_DBMS */\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\t/* Check associated handles */\n\tif( !isHandleRangeValid( keysetInfoPtr->objectHandle ) || \\\n\t\t!( keysetInfoPtr->ownerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t   isHandleRangeValid( keysetInfoPtr->ownerHandle ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckKeyset: Object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that keyset function pointers have been set up correctly */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkKeysetFunctions( IN const KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isReadPtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\t/* Check universal access functions */\n\tif( !FNPTR_ISSET( keysetInfoPtr->initFunction ) || \\\n\t\t!FNPTR_ISSET( keysetInfoPtr->shutdownFunction ) || \\\n\t\t!FNPTR_ISSET( keysetInfoPtr->getItemFunction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"checkKeysetFunctions: Basic keyset functions\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check subtype-specific functions */\n\tswitch( keysetInfoPtr->type )\n\t\t{\n\t\tcase KEYSET_FILE:\n#ifndef USE_PKCS12_WRITE\n\t\t\tif( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 )\n\t\t\t\t{\n\t\t\t\tif( !FNPTR_ISNULL( keysetInfoPtr->setItemFunction ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"checkKeysetFunctions: Suprious PKCS #12 write function\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n#endif /* USE_PKCS12_WRITE */\n\t\t\tif( !FNPTR_ISSET( keysetInfoPtr->setItemFunction ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"checkKeysetFunctions: Basic file access functions\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 )\n\t\t\t\t{\n\t\t\t\tif( !FNPTR_ISSET( keysetInfoPtr->getSpecialItemFunction ) || \\\n\t\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->setSpecialItemFunction ) || \\\n\t\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->deleteItemFunction ) || \\\n\t\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->getFirstItemFunction ) || \\\n\t\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->getNextItemFunction ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"checkKeysetFunctions: P15 access functions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n#ifdef USE_HTTP\n\t\tcase KEYSET_HTTP:\n\t\t\t/* No additional access functions available */\n\t\t\tbreak;\n#endif /* USE_HTTP */\n\n#ifdef USE_LDAP\n\t\tcase KEYSET_LDAP:\n\t\t\tif( !FNPTR_ISSET( keysetInfoPtr->setItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->deleteItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->isBusyFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->getAttributeFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->setAttributeFunction ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"checkKeysetFunctions: DBMS functions\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n#endif /* USE_LDAP */\n\n#if defined( USE_DBMS )\n\t\tcase KEYSET_DBMS:\n\t\t\tif( !FNPTR_ISSET( keysetInfoPtr->getFirstItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->getNextItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->setItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->deleteItemFunction ) || \\\n\t\t\t\t!FNPTR_ISSET( keysetInfoPtr->isBusyFunction ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"checkKeysetFunctions: DBMS functions\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n#endif /* USE_DBMS */\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Clear the extended error information that may be present from a previous\n   operation prior to beginning a new operation */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void resetErrorInfo( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tERROR_INFO *errorInfo = &keysetInfoPtr->errorInfo;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\t}\n\n/* Prepare to update a keyset, performing various access checks and pre-\n   processing of information */\n\ntypedef struct {\n\tCRYPT_KEYID_TYPE keyIDtype;\t\t/* KeyID type */\n\tBUFFER_FIXED( keyIDlength ) \\\n\tconst void *keyID;\t\t\t\t/* KeyID value */\n\tint keyIDlength;\n\t} KEYID_INFO;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initKeysetUpdate( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t INOUT_OPT KEYID_INFO *keyIDinfo, \n\t\t\t\t\t\t\t OUT_BUFFER_OPT_FIXED( keyIdMaxLength ) \\\n\t\t\t\t\t\t\t\tvoid *keyIDbuffer,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int keyIdMaxLength,\n\t\t\t\t\t\t\t const BOOLEAN isRead )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( ( keyIDinfo == NULL && \\\n\t\t\t  keyIDbuffer == NULL && keyIdMaxLength == 0 ) || \\\n\t\t\t( isWritePtr( keyIDinfo, sizeof( KEYID_INFO ) ) && \\\n\t\t\t  isReadPtrDynamic( keyIDbuffer, keyIdMaxLength ) ) );\n\n\tREQUIRES( ( keyIDinfo == NULL && \\\n\t\t\t\tkeyIDbuffer == NULL && keyIdMaxLength == 0 ) || \\\n\t\t\t  ( keyIDinfo != NULL && \\\n\t\t\t\tkeyIDbuffer != NULL && keyIdMaxLength == KEYID_SIZE ) );\n\tREQUIRES( isRead == TRUE || isRead == FALSE );\n\n\t/* Clear return values */\n\tif( keyIDbuffer != NULL )\n\t\tmemset( keyIDbuffer, 0, min( 16, keyIdMaxLength ) );\n\n\t/* If we're in the middle of a query we can't do anything else */\n\tif( FNPTR_ISSET( keysetInfoPtr->isBusyFunction ) )\n\t\t{\n\t\tconst KEY_ISBUSY_FUNCTION isBusyFunction = \\\n\t\t\t\t\t( KEY_ISBUSY_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( keysetInfoPtr->isBusyFunction );\n\n\t\tREQUIRES( isBusyFunction != NULL );\n\n\t\tif( isBusyFunction( keysetInfoPtr ) )\n\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t}\n\n\t/* If we've been passed a full issuerAndSerialNumber as a key ID and the \n\t   keyset needs an issuerID, convert it */\n\tif( keyIDinfo != NULL && \\\n\t\tkeyIDinfo->keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \\\n\t\t( keysetInfoPtr->type == KEYSET_DBMS || \\\n\t\t  ( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t    keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) ) )\n\t\t{\n\t\tHASHINFO hashInfo;\n\t\tSTREAM stream;\n\t\tint hashSize, payloadStart DUMMY_INIT, length, status;\n\n\t\t/* Hash the full iAndS to get an issuerID and use that for the \n\t\t   keyID.  This is complicated by the fact that there exist one or \n\t\t   two broken implementations out there that use a non-DER encoding\n\t\t   of the iAndS wrapper (for example encoding the length as \n\t\t   '82 00 nn' instead of 'nn').  To handle this we read the wrapper\n\t\t   and then write our own correctly-encoded version to a buffer\n\t\t   that we hash seperately from the iAndS payload */\n\t\tsMemConnect( &stream, keyIDinfo->keyID, keyIDinfo->keyIDlength );\n\t\tstatus = readSequence( &stream, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tpayloadStart = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tHASH_FUNCTION hashFunction;\n\t\t\tBYTE buffer[ 8 + 8 ];\n\n\t\t\tREQUIRES( payloadStart > 0 && \\\n\t\t\t\t\t  payloadStart < keyIDinfo->keyIDlength );\n\n\t\t\t/* We've processed the wrapper, write our own known-good version\n\t\t\t   and then hash that and the iAndS payload */\n\t\t\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, &hashSize );\n\t\t\tsMemOpen( &stream, buffer, 8 );\n\t\t\tstatus = writeSequence( &stream, length );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\thashFunction( hashInfo, NULL, 0, buffer, stell( &stream ), \n\t\t\t\t\t\t  HASH_STATE_START );\n\t\t\tsMemClose( &stream );\n\t\t\thashFunction( hashInfo, keyIDbuffer, keyIdMaxLength, \n\t\t\t\t\t\t  ( BYTE * ) keyIDinfo->keyID + payloadStart, \n\t\t\t\t\t\t  keyIDinfo->keyIDlength - payloadStart, \n\t\t\t\t\t\t  HASH_STATE_END );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\n\t\t\t/* The attempt to read the wrapper failed, just hash the whole \n\t\t\t   thing as a blob and continue */\n\t\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t\t\t &hashSize );\n\t\t\thashFunctionAtomic( keyIDbuffer, keyIdMaxLength, keyIDinfo->keyID, \n\t\t\t\t\t\t\t\tkeyIDinfo->keyIDlength );\n\t\t\t}\n\t\tkeyIDinfo->keyIDtype = CRYPT_IKEYID_ISSUERID;\n\t\tkeyIDinfo->keyID = keyIDbuffer;\n\t\tkeyIDinfo->keyIDlength = hashSize;\n\t\t}\n\n\t/* If this is a read access there's nothing further to do */\n\tif( isRead )\n\t\treturn( CRYPT_OK );\n\n\t/* This is a write update, make sure that we can write to the keyset.  \n\t   This covers all possibilities, both keyset types for which writing \n\t   isn't supported and individual keysets that we can't write to \n\t   because of things like file permissions, so once we pass this check \n\t   we know that we can write to the keyset */\n\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_READONLY ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFlat-file Keyset Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* OID information used to read the header of a PKCS #15 file.  Since the \n   PKCS #15 content can be further wrapped in CMS AuthData we have to check\n   for both types of content */\n\nstatic const CMS_CONTENT_INFO oidInfoPkcs15Data = { 0, 0 };\n\nstatic const OID_INFO keyFileOIDinfo[] = {\n\t{ OID_PKCS15_CONTENTTYPE, TRUE, &oidInfoPkcs15Data },\n\t{ OID_CMS_AUTHDATA, FALSE, &oidInfoPkcs15Data },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* Identify a flat-file keyset type */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getKeysetType( INOUT STREAM *stream,\n\t\t\t\t\t\t  OUT_ENUM_OPT( KEYSET_SUBTYPE ) KEYSET_SUBTYPE *subType )\n\t{\n\tlong length;\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( subType, sizeof( KEYSET_SUBTYPE ) ) );\n\n\t/* Clear return value */\n\t*subType = KEYSET_SUBTYPE_NONE;\n\n\t/* Try and guess the basic type */\n\tstatus = value = sPeek( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value == BER_SEQUENCE )\n\t\t{\n\t\t/* Read the length of the object, which should be between 64 and 64K \n\t\t   bytes in size.  We have to allow for very tiny files to handle \n\t\t   PKCS #15 files that contain only configuration data, and rather \n\t\t   large ones to handle the existence of large numbers of trusted \n\t\t   certificates, with a maximum of 32 objects * ~2K per object we \n\t\t   can get close to 64K in size.  The length may also be zero if the \n\t\t   indefinite encoding form is used.  Although PKCS #15 specifies \n\t\t   the use of DER, it doesn't hurt to allow this at least for the \n\t\t   outer wrapper, if Microsoft ever move to PKCS #15 they're bound \n\t\t   to get it wrong */\n\t\tstatus = readLongSequence( stream, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( length != CRYPT_UNUSED && ( length < 64 || length > 65535L ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Check for a PKCS #12/#15 file */\n\t\tstatus = value = peekTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value == BER_INTEGER )\n\t\t\t{\n\t\t\tlong version;\n\n\t\t\t/* Check for a PKCS #12 version number */\n\t\t\tstatus = readShortInteger( stream, &version );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( version != 3 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t*subType = KEYSET_SUBTYPE_PKCS12;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Check for a PKCS #15 file type, either direct PKCS #15 content \n\t\t   or PKCS #15 wrapped in CMS AuthData */\n\t\tstatus = readOID( stream, keyFileOIDinfo, \n\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( keyFileOIDinfo, OID_INFO ),\n\t\t\t\t\t\t  &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*subType = KEYSET_SUBTYPE_PKCS15;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef USE_PGP\n\tvalue = pgpGetPacketType( value );\n\tif( value == PGP_PACKET_PUBKEY || value == PGP_PACKET_SECKEY )\n\t\t{\n\t\tKEYSET_SUBTYPE type;\n\n\t\t/* Determine the file type based on the initial CTB */\n\t\ttype = ( value == PGP_PACKET_PUBKEY ) ? \\\n\t\t\t   KEYSET_SUBTYPE_PGP_PUBLIC : KEYSET_SUBTYPE_PGP_PRIVATE;\n\n\t\t/* Perform a sanity check to make sure that the rest looks like a \n\t\t   PGP keyring */\n\t\tstatus = pgpReadPacketHeader( stream, &value, &length, 64, 4096 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( type == KEYSET_SUBTYPE_PGP_PUBLIC )\n\t\t\t{\n\t\t\tif( length < 64 || length > 1024  )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( length < 200 || length > 4096 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tstatus = value = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value != PGP_VERSION_2 && value != PGP_VERSION_3 && \\\n\t\t\tvalue != PGP_VERSION_OPENPGP )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t*subType = type;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_PGP */\n\n\t/* \"It doesn't look like anything from here\" */\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n\n/* Open a flat-file keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 6 ) ) \\\nstatic int openKeysetStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_BUFFER( nameLength ) const char *name,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_NAME_LENGTH ) \\\n\t\t\t\t\t\t\t\tconst int nameLength,\n\t\t\t\t\t\t\t IN_ENUM_OPT( CRYPT_KEYOPT ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_KEYOPT_TYPE options,\n\t\t\t\t\t\t\t OUT_BOOL BOOLEAN *isReadOnly, \n\t\t\t\t\t\t\t OUT_ENUM_OPT( KEYSET_SUBTYPE ) \\\n\t\t\t\t\t\t\t\tKEYSET_SUBTYPE *keysetSubType )\n\t{\n\tKEYSET_SUBTYPE subType = KEYSET_SUBTYPE_PKCS15;\n\tchar nameBuffer[ MAX_ATTRIBUTE_SIZE + 1 + 8 ];\n\tconst int suffixPos = nameLength - 4;\n\tint openMode, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\tassert( isWritePtr( isReadOnly, sizeof( BOOLEAN ) ) );\n\tassert( isWritePtr( keysetSubType, sizeof( KEYSET_SUBTYPE ) ) );\n\n\tREQUIRES( isEnumRangeOpt( options, CRYPT_KEYOPT ) );\n\tREQUIRES( nameLength >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Clear return values */\n\t*isReadOnly = FALSE;\n\t*keysetSubType = KEYSET_SUBTYPE_NONE;\n\n\t/* Convert the keyset name into a null-terminated string */\n\tREQUIRES( rangeCheck( nameLength, 1, MAX_ATTRIBUTE_SIZE ) );\n\tmemcpy( nameBuffer, name, nameLength );\n\tnameBuffer[ nameLength ] = '\\0';\n\n\t/* Get the expected subtype based on the keyset name.  The default is\n\t   PKCS #15 if no contraindication is found in the file suffix */\n\tif( suffixPos > 0 && nameBuffer[ suffixPos ] == '.' )\n\t\t{\n\t\tif( !strCompare( nameBuffer + suffixPos + 1, \"pgp\", 3 ) || \\\n\t\t\t!strCompare( nameBuffer + suffixPos + 1, \"gpg\", 3 ) || \\\n\t\t\t!strCompare( nameBuffer + suffixPos + 1, \"pkr\", 3 ) )\n\t\t\tsubType = KEYSET_SUBTYPE_PGP_PUBLIC;\n\t\tif( !strCompare( nameBuffer + suffixPos + 1, \"skr\", 3 ) )\n\t\t\tsubType = KEYSET_SUBTYPE_PGP_PRIVATE;\n\t\tif( !strCompare( nameBuffer + suffixPos + 1, \"pfx\", 3 ) || \\\n\t\t\t!strCompare( nameBuffer + suffixPos + 1, \"p12\", 3 ) )\n\t\t\tsubType = KEYSET_SUBTYPE_PKCS12;\n\t\t}\n\n\t/* If the file is read-only, put the keyset into read-only mode */\n\tif( fileReadonly( nameBuffer ) )\n\t\t{\n\t\t/* If we want to create a new file we can't do it if we don't have\n\t\t   write permission */\n\t\tif( options == CRYPT_KEYOPT_CREATE )\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\t/* Open the file in read-only mode */\n\t\t*isReadOnly = TRUE;\n\t\topenMode = FILE_FLAG_READ;\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're creating the file, open it in write-only mode.  Since\n\t\t   we'll (presumably) be storing private keys in it we mark it as\n\t\t   both private (owner-access-only ACL) and sensitive (store in\n\t\t   secure storage if possible) */\n\t\tif( options == CRYPT_KEYOPT_CREATE )\n\t\t\t{\n\t\t\topenMode = FILE_FLAG_WRITE | FILE_FLAG_EXCLUSIVE_ACCESS | \\\n\t\t\t\t\t   FILE_FLAG_PRIVATE | FILE_FLAG_SENSITIVE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Open it for read or read/write depending on whether the\n\t\t\t   readonly flag is set */\n\t\t\topenMode = ( options == CRYPT_KEYOPT_READONLY ) ? \\\n\t\t\t\t\t   FILE_FLAG_READ : FILE_FLAG_READ | FILE_FLAG_WRITE;\n\t\t\t}\n\t\t}\n\tif( options == CRYPT_IKEYOPT_EXCLUSIVEACCESS )\n\t\topenMode |= FILE_FLAG_EXCLUSIVE_ACCESS;\n\n\t/* Pre-open the file containing the keyset.  This initially opens it in\n\t   read-only mode for auto-detection of the file type so we can check for\n\t   various problems */\n\tstatus = sFileOpen( stream, nameBuffer, FILE_FLAG_READ );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The file can't be opened, if the create-new-file flag isn't set \n\t\t   return an error.  If it is set, make sure that we're trying to \n\t\t   create a writeable keyset type */\n\t\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t\treturn( status );\n\t\tif( !isWriteableFileKeyset( subType ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t/* Try and create a new file */\n\t\tstatus = sFileOpen( stream, nameBuffer, openMode );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The file isn't open at this point so we have to exit \n\t\t\t   explicitly rather than falling through to the error handler\n\t\t\t   below */\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're opening an existing keyset, get its type and make sure\n\t\t   that it's valid */\n\t\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t\t{\n\t\t\tBYTE buffer[ SAFEBUFFER_SIZE( 512 ) + 8 ] STACK_ALIGN_DATA;\n\n\t\t\tmemset( buffer, 0, 512 );\t/* Keep static analysers happy */\n\t\t\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), 512 );\n\t\t\tsioctlSetString( stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t\t\t SAFEBUFFER_PTR( buffer ), 512 );\n\t\t\tstatus = getKeysetType( stream, &subType );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* \"It doesn't look like anything from here\" */\n\t\t\t\tsFileClose( stream );\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tsseek( stream, 0 );\n\t\t\tsioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );\n\t\t\t}\n\n\t\t/* If it's a cryptlib keyset we can open it in any mode */\n\t\tif( isWriteableFileKeyset( subType ) )\n\t\t\t{\n\t\t\t/* If we're opening it something other than read-only mode, \n\t\t\t   reopen it in that mode.  Note that in theory this could make \n\t\t\t   us subject to a TOCTTOU attack but the only reason that we're \n\t\t\t   opening the file initially is to determine its type, so if an \n\t\t\t   attacker slips in a different file on the re-open it'll \n\t\t\t   either be a no-op if it's the same file type or we'll get a\n\t\t\t   CRYPT_ERROR_BADDATA if it's the same file type */\n\t\t\tif( openMode != FILE_FLAG_READ )\n\t\t\t\t{\n\t\t\t\tsFileClose( stream );\n\t\t\t\tstatus = sFileOpen( stream, nameBuffer, openMode );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\t/* Exit with file closed */\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If it's a non-cryptlib keyset we can't open it for anything \n\t\t\t   other than read-only access.  We return a not-available error \n\t\t\t   rather than a permission error since this isn't a problem with\n\t\t\t   access permissions for the file but the fact that the code to\n\t\t\t   write the key doesn't exist */\n\t\t\tif( options != CRYPT_KEYOPT_READONLY )\n\t\t\t\tstatus = CRYPT_ERROR_NOTAVAIL;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsFileClose( stream );\n\t\treturn( status );\n\t\t}\n\n\t*keysetSubType = subType;\n\treturn( CRYPT_OK );\n\t}\n\n/* Some flat-file keysets have subtype-specific access restrictions that \n   are too specific to be captured by the general ACLs.  To handle these, we\n   need to provide subtype-specific checking, which is handled by the \n   following function */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isFileKeysetAccessPermitted( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE accessType,\n\t\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isRead )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES_B( keysetInfoPtr->type == KEYSET_FILE );\n\tREQUIRES_B( isEnumRange( accessType, KEYMGMT_ITEM ) );\n\tREQUIRES_B( isRead == TRUE || isRead == FALSE );\n\n\tswitch( keysetInfoPtr->subType )\n\t\t{\n\t\tcase KEYSET_SUBTYPE_PGP_PUBLIC:\n\t\t\t/* PGP keysets have odd requirements for write in that a private\n\t\t\t   key is required in order for it to be written to a public \n\t\t\t   keyring if it's a signing key.  This is because of the \n\t\t\t   requirement to have signed metadata associated with the key, \n\t\t\t   which requires the presence of a private key */\n\t\t\tif( accessType == KEYMGMT_ITEM_PUBLICKEY && isRead )\n\t\t\t\treturn( TRUE );\n\t\t\tif( ( accessType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\t  accessType == KEYMGMT_ITEM_PUBLICKEY ) && !isRead )\n\t\t\t\treturn( TRUE );\n\t\t\treturn( FALSE );\n\n\t\tcase KEYSET_SUBTYPE_PGP_PRIVATE:\n\t\t\tif( ( accessType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\t  accessType == KEYMGMT_ITEM_PUBLICKEY ) && isRead )\n\t\t\t\treturn( TRUE );\n\t\t\treturn( FALSE );\n\n\t\tcase KEYSET_SUBTYPE_PKCS12:\n\t\t\tif( accessType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\taccessType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t\treturn( TRUE );\n\t\t\treturn( FALSE );\n\n\t\tcase KEYSET_SUBTYPE_PKCS15:\n\t\t\tif( accessType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\taccessType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\taccessType == KEYMGMT_ITEM_SECRETKEY || \\\n\t\t\t\taccessType == KEYMGMT_ITEM_DATA || \\\n\t\t\t\taccessType == KEYMGMT_ITEM_KEYMETADATA )\n\t\t\t\treturn( TRUE );\n\t\t\treturn( FALSE );\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\n/* Complete the open of a file keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int completeKeysetFileOpen( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ENUM( KEYSET_SUBTYPE ) \\\n\t\t\t\t\t\t\t\t\t\tKEYSET_SUBTYPE subType,\n\t\t\t\t\t\t\t\t   INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   IN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_NAME_LENGTH ) \\\n\t\t\t\t\t\t\t\t\t\tconst int nameLength,\n\t\t\t\t\t\t\t\t   IN_ENUM_OPT( CRYPT_KEYOPT ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_KEYOPT_TYPE options )\n\t{\n\tFILE_INFO *fileInfo = keysetInfoPtr->keysetFile;\n\tBYTE buffer[ SAFEBUFFER_SIZE( STREAM_BUFSIZE ) + 8 ] STACK_ALIGN_DATA;\n\tKEY_INIT_FUNCTION initFunction;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isEnumRange( subType, KEYSET_SUBTYPE ) );\n\tREQUIRES( nameLength >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isEnumRangeOpt( options, CRYPT_KEYOPT ) );\n\n\t/* Remember the key file's name (as a null-terminated string for \n\t   filesystem access) and I/O stream */\n\tif( nameLength > MAX_PATH_LENGTH - 1 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tkeysetInfoPtr->subType = subType;\n\tREQUIRES( rangeCheck( nameLength, 1, MAX_PATH_LENGTH - 1 ) );\n\tmemcpy( fileInfo->fileName, name, nameLength );\n\tfileInfo->fileName[ nameLength ] = '\\0';\n\tmemcpy( &fileInfo->stream, stream, sizeof( STREAM ) );\n\n\t/* Set various values to their default settings */\n\tfileInfo->iHardwareDevice = CRYPT_UNUSED;\n\n\t/* Make sure that we don't accidentally reuse the standalone stream */\n\tmemset( stream, 0, sizeof( STREAM ) );\n\n\t/* Set up the access information for the file */\n\tswitch( keysetInfoPtr->subType )\n\t\t{\n\t\tcase KEYSET_SUBTYPE_PKCS12:\n\t\t\tstatus = setAccessMethodPKCS12( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tcase KEYSET_SUBTYPE_PKCS15:\n\t\t\tstatus = setAccessMethodPKCS15( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tcase KEYSET_SUBTYPE_PGP_PUBLIC:\n\t\t\tstatus = setAccessMethodPGPPublic( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tcase KEYSET_SUBTYPE_PGP_PRIVATE:\n\t\t\tstatus = setAccessMethodPGPPrivate( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Normally if an access method is unavailable we'd return\n\t\t   CRYPT_ARGERROR_NUM1 to indicate that the overall CRYPT_KEYSET_xxx\n\t\t   type isn't supported, however in the case of CRYPT_KEYSET_FILE\n\t\t   we're dealing with subtypes rather than the CRYPT_KEYSET_FILE in\n\t\t   general.  To deal with this, if the subtype is anything other than\n\t\t   PKCS #15 files then we report it as CRYPT_ERROR_NOTAVAIL to indicate\n\t\t   that while CRYPT_KEYSET_FILE as a whole may be supported, this\n\t\t   particular subtype isn't.  For PKCS #15 files, the generic \"file\n\t\t   keyset\", we report it as a standard CRYPT_ARGERROR_NUM1 */\n\t\tif( status == CRYPT_ARGERROR_NUM1 && \\\n\t\t\tsubType != KEYSET_SUBTYPE_PKCS15 )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\treturn( status );\n\t\t}\n\tENSURES( checkKeysetFunctions( keysetInfoPtr ) );\n\n\t/* Read the keyset contents into memory */\n\tinitFunction = ( KEY_INIT_FUNCTION ) \\\n\t\t\t\t   FNPTR_GET( keysetInfoPtr->initFunction );\n\tREQUIRES( initFunction != NULL );\n\tmemset( buffer, 0, min( 16, STREAM_BUFSIZE ) );\t\n\t\t\t/* Keep static analysers happy */\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\tsioctlSetString( &fileInfo->stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\tstatus = initFunction( keysetInfoPtr, NULL, 0, \n\t\t\t\t\t\t   ( options == CRYPT_KEYOPT_CREATE ) ? \\\n\t\t\t\t\t\t\t CRYPT_KEYOPT_CREATE : CRYPT_KEYOPT_NONE );\n\tsioctlSet( &fileInfo->stream, STREAM_IOCTL_IOBUFFER, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Since this function is called on object creation, if it fails \n\t\t   there's no object to get extended error information from so we \n\t\t   dump the error info as a diagnostic for debugging purposes */\n\t\tDEBUG_DIAG_ERRMSG(( \"Keyset open failed, status %s, error string:\\n  %s\", \n\t\t\t\t\t\t\tgetStatusName( status ),\n\t\t\t\t\t\t\tgetErrorInfoString( &keysetInfoPtr->errorInfo ) ));\n\t\treturn( status );\n\t\t}\n\n\t/* If we've got the keyset open in read-only mode then we don't need to \n\t   touch it again since everything is cached in-memory, so we can close \n\t   the file stream */\n\tif( ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 || \\\n\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 || \\\n\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) && \\\n\t\t( options == CRYPT_KEYOPT_READONLY ) )\n\t\tsFileClose( &fileInfo->stream );\n\telse\n\t\t{\n\t\t/* Remember that the stream is still open for further access */\n\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_STREAM_OPEN );\n\t\t}\n\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_OPEN );\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyset Message Handler\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle a message sent to a keyset object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int keysetMessageFunction( INOUT TYPECAST( KEYSET_INFO * ) \\\n\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_INT_Z const int messageValue )\n\t{\n\tKEYSET_INFO *keysetInfoPtr = ( KEYSET_INFO * ) objectInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isShortIntegerRange( messageValue ) );\n\n\t/* Process the destroy object message */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* If the keyset is active, perform any required cleanup functions */\n\t\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_OPEN ) )\n\t\t\t{\n\t\t\tconst KEY_SHUTDOWN_FUNCTION shutdownFunction = \\\n\t\t\t\t\t\t( KEY_SHUTDOWN_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->shutdownFunction );\n\n\t\t\tREQUIRES( shutdownFunction != NULL );\n\n\t\t\t/* Shut down the keyset */\n\t\t\tstatus = shutdownFunction( keysetInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tassert( INTERNAL_ERROR );\n\n\t\t\t\t/* The shutdown failed for some reason.  This can only \n\t\t\t\t   really ever happen for file keysets, in general there's \n\t\t\t\t   not much that we can do about this (see the long comment\n\t\t\t\t   about file-close failure conditions in io/file.c), \n\t\t\t\t   however in order to avoid leaving a potentially corrupted\n\t\t\t\t   file on disk we try and delete it if the shutdown fails.\n\t\t\t\t   (There are a pile of tradeoffs to be made here, for \n\t\t\t\t   example in theory we could rename the file to something\n\t\t\t\t   like .bak so that the user could try and recover \n\t\t\t\t   whatever's left in there, however it's unlikely that \n\t\t\t\t   they'll be able to do much with an unknown-condition \n\t\t\t\t   binary blob and in any case since we have no idea what\n\t\t\t\t   condition the file is in it's probably best to remove it\n\t\t\t\t   rather than to leave who knows what lying around on \n\t\t\t\t   disk) */\n\t\t\t\tif( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\tTEST_FLAG( keysetInfoPtr->flags, \n\t\t\t\t\t\t\t   KEYSET_FLAG_STREAM_OPEN ) )\n\t\t\t\t\t{\n\t\t\t\t\tsFileClose( &keysetInfoPtr->keysetFile->stream );\n\t\t\t\t\tfileErase( keysetInfoPtr->keysetFile->fileName );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* If it's a non-file keyset or a file keyset without an open\n\t\t\t   stream, we're done.  Since we cache all information in a file \n\t\t\t   keyset and close the stream immediately afterwards if we've \n\t\t\t   opened it in read-only mode, we only close the underlying \n\t\t\t   stream for a file keyset if it's still active.  Note the \n\t\t\t   distinction between the keyset being active and the stream \n\t\t\t   being active, for file keysets the keyset can be active \n\t\t\t   without being associated with an open stream */\n\t\t\tif( keysetInfoPtr->type != KEYSET_FILE || \\\n\t\t\t\t!TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_STREAM_OPEN ) )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* The keyset has an open file stream */\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\t  TEST_FLAG( keysetInfoPtr->flags, \n\t\t\t\t\t\t\t\t KEYSET_FLAG_STREAM_OPEN ) );\n\n\t\t\t/* If the file keyset was updated in any way the update may have \n\t\t\t   changed the overall file size, in which case we need to clear \n\t\t\t   any leftover data from the previous version of the keyset \n\t\t\t   before we close the file */\n\t\t\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY ) )\n\t\t\t\tfileClearToEOF( &keysetInfoPtr->keysetFile->stream );\n\n\t\t\t/* Close the keyset file (the keyset-specific handler sees only \n\t\t\t   an I/O stream and doesn't perform any file-level functions, \n\t\t\t   so we have to do this here) */\n\t\t\tstatus = sFileClose( &keysetInfoPtr->keysetFile->stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Try and remove the keyset if the file close failed and \n\t\t\t\t   would have left the file in an indeterminate state, see \n\t\t\t\t   the comment in io/file.c for more information */\n\t\t\t\tfileErase( keysetInfoPtr->keysetFile->fileName );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If it's a newly-created empty keyset file or one in which \n\t\t\t\t   all of the keys have been deleted, remove it.  This \n\t\t\t\t   situation can occur if there's some sort of error on \n\t\t\t\t   writing and no keys are ever written to the keyset */\n\t\t\t\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY ) )\n\t\t\t\t\tfileErase( keysetInfoPtr->keysetFile->fileName );\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE_S );\n\n\t\t/* If it's a keyset-specific attribute, forward it directly to\n\t\t   the low-level code */\n#ifdef USE_LDAP\n\t\tif( messageValue >= CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS && \\\n\t\t\tmessageValue <= CRYPT_OPTION_KEYS_LDAP_EMAILNAME )\n\t\t\t{\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\n\t\t\tif( message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\tmessage == MESSAGE_SETATTRIBUTE_S )\n\t\t\t\t{\n\t\t\t\tconst KEY_SETATTRIBUTE_FUNCTION setAttributeFunction = \\\n\t\t\t\t\t\t\t( KEY_SETATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->setAttributeFunction );\n\n\t\t\t\tREQUIRES( setAttributeFunction != NULL );\n\n\t\t\t\tstatus = setAttributeFunction( keysetInfoPtr, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t\t   messageValue );\n\t\t\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( keysetInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst KEY_GETATTRIBUTE_FUNCTION getAttributeFunction = \\\n\t\t\t\t\t\t\t( KEY_GETATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->getAttributeFunction );\n\n\t\t\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S );\n\t\t\t\tREQUIRES( getAttributeFunction != NULL );\n\n\t\t\t\tstatus = getAttributeFunction( keysetInfoPtr, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t\t   messageValue );\n\t\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( keysetInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n#endif /* USE_LDAP */\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getKeysetAttribute( keysetInfoPtr, \n\t\t\t\t\t\t\t\t\t\t( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tmessageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getKeysetAttributeS( keysetInfoPtr, \n\t\t\t\t\t\t\t\t\t\t ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( setKeysetAttribute( keysetInfoPtr, \n\t\t\t\t\t\t\t\t\t\t*( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t\tmessageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setKeysetAttributeS( keysetInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t\t msgData->length, messageValue ) );\n\t\t\t}\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process messages that check a keyset */\n\tif( message == MESSAGE_CHECK )\n\t\t{\n\t\t/* The check for whether this keyset type can contain an object that \n\t\t   can perform the requested operation has already been performed by \n\t\t   the kernel so there's nothing further to do here */\n\t\tREQUIRES( ( messageValue != MESSAGE_CHECK_PKC_PRIVATE && \\\n\t\t\t\t\tmessageValue != MESSAGE_CHECK_PKC_DECRYPT && \\\n\t\t\t\t\tmessageValue != MESSAGE_CHECK_PKC_DECRYPT_AVAIL && \\\n\t\t\t\t\tmessageValue != MESSAGE_CHECK_PKC_SIGN && \\\n\t\t\t\t\tmessageValue != MESSAGE_CHECK_PKC_SIGN_AVAIL ) || \n\t\t\t\t  ( keysetInfoPtr->type != KEYSET_DBMS && \\\n\t\t\t\t\tkeysetInfoPtr->type != KEYSET_LDAP && \\\n\t\t\t\t\tkeysetInfoPtr->type != KEYSET_HTTP ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_KEY_GETKEY )\n\t\t{\n\t\tconst KEY_GETITEM_FUNCTION getItemFunction = \\\n\t\t\t\t\t\t\t( KEY_GETITEM_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->getItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getkeyInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\t\tCONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \\\n\t\t\t\t\t\t\t getkeyInfo->keyIDtype, getkeyInfo->keyID, \\\n\t\t\t\t\t\t\t getkeyInfo->keyIDlength );\n\t\tBYTE keyIDbuffer[ KEYID_SIZE + 8 ];\n\n\t\tCONST_SET_STRUCT( keyIDinfo.keyIDtype = getkeyInfo->keyIDtype; \\\n\t\t\t\t\t\t  keyIDinfo.keyID = getkeyInfo->keyID; \\\n\t\t\t\t\t\t  keyIDinfo.keyIDlength = getkeyInfo->keyIDlength );\n\n\t\tREQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\t  keyIDinfo.keyID != NULL && \\\n\t\t\t\t  keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\t  keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );\n\t\tREQUIRES( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\t  keysetInfoPtr->type == KEYSET_FILE );\n\t\tREQUIRES( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_DATA ) || \\\n\t\t\t\t  ( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );\n\t\tREQUIRES( ( messageValue != KEYMGMT_ITEM_REQUEST && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_REVREQUEST && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_REVOCATIONINFO && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_PKIUSER ) || \\\n\t\t\t\t  keysetInfoPtr->type == KEYSET_DBMS );\n\t\tREQUIRES( getItemFunction != NULL );\n\n\t\t/* Get the key */\n\t\tresetErrorInfo( keysetInfoPtr );\n\t\tstatus = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer,\n\t\t\t\t\t\t\t\t   KEYID_SIZE, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t!isFileKeysetAccessPermitted( keysetInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t\t\t  TRUE ) )\n\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\treturn( getItemFunction( keysetInfoPtr, &getkeyInfo->cryptHandle, \n\t\t\t\t\t\t\tmessageValue, keyIDinfo.keyIDtype, \n\t\t\t\t\t\t\tkeyIDinfo.keyID, keyIDinfo.keyIDlength, \n\t\t\t\t\t\t\tgetkeyInfo->auxInfo, &getkeyInfo->auxInfoLength, \n\t\t\t\t\t\t\tgetkeyInfo->flags ) );\n\t\t}\n\tif( message == MESSAGE_KEY_SETKEY )\n\t\t{\n\t\tconst KEY_SETITEM_FUNCTION setItemFunction = \\\n\t\t\t\t\t\t\t( KEY_SETITEM_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->setItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *setkeyInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\t  ( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\t( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC || \\\n\t\t\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 || \\\n\t\t\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 ) ) );\n\t\tREQUIRES( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_DATA && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_KEYMETADATA ) || \\\n\t\t\t\t  ( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );\n\t\tREQUIRES( ( messageValue != KEYMGMT_ITEM_REQUEST && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_REVREQUEST && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_REVOCATIONINFO && \\\n\t\t\t\t\tmessageValue != KEYMGMT_ITEM_PKIUSER ) || \\\n\t\t\t\t  ( keysetInfoPtr->type == KEYSET_DBMS ) );\n\t\tREQUIRES( setItemFunction != NULL );\n\n\t\t/* Set the key.  This is currently the only way to associate a \n\t\t   certificate with a context (that is, it's not possible to add a \n\t\t   certificate to an existing context directly).  At first glance \n\t\t   this should be possible since the required access checks are \n\t\t   performed by the kernel: The object is of the correct type (a \n\t\t   certificate), in the high state (it's been signed), and the \n\t\t   certificate owner and context owner are the same.  However the \n\t\t   actual process of attaching the certificate to the context is \n\t\t   quite tricky.  The certificate will have a public-key context \n\t\t   already attached to it from when the certificate was created or \n\t\t   imported.  In order to attach this to the other context we'd need \n\t\t   to first destroy the context associated with the certificate and \n\t\t   then replace it with the other context, which is both messy and \n\t\t   non-atomic.  There are also complications surrounding use with \n\t\t   devices, where contexts aren't really full cryptlib objects but \n\t\t   just dummy values that point back to the device for handling of \n\t\t   operations.  Going via a keyset/device bypasses these issues, but \n\t\t   doing it directly shows up all of these problems */\n\t\tresetErrorInfo( keysetInfoPtr );\n\t\tstatus = initKeysetUpdate( keysetInfoPtr, NULL, NULL, 0, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t!isFileKeysetAccessPermitted( keysetInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t\t\t  FALSE ) )\n\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\tstatus = setItemFunction( keysetInfoPtr, setkeyInfo->cryptHandle, \n\t\t\t\t\t\t\tmessageValue, setkeyInfo->auxInfo, \n\t\t\t\t\t\t\tsetkeyInfo->auxInfoLength, setkeyInfo->flags );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* The update succeeded, remember that the data in the keyset has \n\t\t   changed */\n\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY );\n\t\tCLEAR_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( message == MESSAGE_KEY_DELETEKEY )\n\t\t{\n\t\tconst KEY_DELETEITEM_FUNCTION deleteItemFunction = \\\n\t\t\t\t\t\t\t( KEY_DELETEITEM_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->deleteItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *deletekeyInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\t\tCONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \\\n\t\t\t\t\t\t\t deletekeyInfo->keyIDtype, deletekeyInfo->keyID, \\\n\t\t\t\t\t\t\t deletekeyInfo->keyIDlength );\n\t\tBYTE keyIDbuffer[ KEYID_SIZE + 8 ];\n\n\t\tCONST_SET_STRUCT( keyIDinfo.keyIDtype = deletekeyInfo->keyIDtype; \\\n\t\t\t\t\t\t  keyIDinfo.keyID = deletekeyInfo->keyID; \\\n\t\t\t\t\t\t  keyIDinfo.keyIDlength = deletekeyInfo->keyIDlength );\n\n\t\tREQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\t  keyIDinfo.keyID != NULL && \\\n\t\t\t\t  keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\t  keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );\n\t\tREQUIRES( deleteItemFunction != NULL );\n\n\t\t/* Delete the key */\n\t\tresetErrorInfo( keysetInfoPtr );\n\t\tstatus = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer,\n\t\t\t\t\t\t\t\t   KEYID_SIZE, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = deleteItemFunction( keysetInfoPtr, messageValue, \n\t\t\t\t\t\t\tkeyIDinfo.keyIDtype, keyIDinfo.keyID, \n\t\t\t\t\t\t\tkeyIDinfo.keyIDlength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* The update succeeded, remember that the data in the keyset \n\t\t\t   has changed */\n\t\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tif( message == MESSAGE_KEY_GETFIRSTCERT )\n\t\t{\n\t\tconst KEY_GETFIRSTITEM_FUNCTION getFirstItemFunction = \\\n\t\t\t\t\t\t\t( KEY_GETFIRSTITEM_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->getFirstItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getnextcertInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\t\tCONST_INIT_STRUCT_3( KEYID_INFO keyIDinfo, \\\n\t\t\t\t\t\t\t getnextcertInfo->keyIDtype, getnextcertInfo->keyID, \\\n\t\t\t\t\t\t\t getnextcertInfo->keyIDlength );\n\t\tBYTE keyIDbuffer[ KEYID_SIZE + 8 ];\n\n\t\tCONST_SET_STRUCT( keyIDinfo.keyIDtype = getnextcertInfo->keyIDtype; \\\n\t\t\t\t\t\t  keyIDinfo.keyID = getnextcertInfo->keyID; \\\n\t\t\t\t\t\t  keyIDinfo.keyIDlength = getnextcertInfo->keyIDlength );\n\n\t\tREQUIRES( keyIDinfo.keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\t  keyIDinfo.keyID != NULL && \\\n\t\t\t\t  keyIDinfo.keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\t  keyIDinfo.keyIDlength < MAX_ATTRIBUTE_SIZE );\n\t\tREQUIRES( getnextcertInfo->auxInfo != NULL && \\\n\t\t\t\t  getnextcertInfo->auxInfoLength == sizeof( int ) );\n\t\tREQUIRES( getFirstItemFunction != NULL );\n\n\t\t/* Fetch the first certificate in a sequence from the keyset */\n\t\tresetErrorInfo( keysetInfoPtr );\n\t\tstatus = initKeysetUpdate( keysetInfoPtr, &keyIDinfo, keyIDbuffer, \n\t\t\t\t\t\t\t\t   KEYID_SIZE, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( getFirstItemFunction( keysetInfoPtr,\n\t\t\t\t\t\t\t&getnextcertInfo->cryptHandle, \n\t\t\t\t\t\t\tgetnextcertInfo->auxInfo, messageValue, \n\t\t\t\t\t\t\tkeyIDinfo.keyIDtype, keyIDinfo.keyID, \n\t\t\t\t\t\t\tkeyIDinfo.keyIDlength, getnextcertInfo->flags ) );\n\t\t}\n\tif( message == MESSAGE_KEY_GETNEXTCERT )\n\t\t{\n\t\tconst KEY_GETNEXTITEM_FUNCTION getNextItemFunction = \\\n\t\t\t\t\t\t\t( KEY_GETNEXTITEM_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->getNextItemFunction );\n\t\tMESSAGE_KEYMGMT_INFO *getnextcertInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( getnextcertInfo->keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\t  getnextcertInfo->keyID == NULL && \\\n\t\t\t\t  getnextcertInfo->keyIDlength == 0 );\n\t\tREQUIRES( ( getnextcertInfo->auxInfo == NULL && \\\n\t\t\t\t\tgetnextcertInfo->auxInfoLength == 0 ) || \\\n\t\t\t\t  ( getnextcertInfo->auxInfo != NULL && \\\n\t\t\t\t\tgetnextcertInfo->auxInfoLength == sizeof( int ) ) );\n\t\t\t\t  /* The state variable may be absent for a one-off\n\t\t\t\t\t fetch */\n\t\tREQUIRES( isFlagRangeZ( getnextcertInfo->flags, KEYMGMT ) && \\\n\t\t\t\t  ( getnextcertInfo->flags & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\t\tREQUIRES( getNextItemFunction != NULL );\n\n\t\t/* Fetch the next certificate in a sequence from the keyset */\n\t\treturn( getNextItemFunction( keysetInfoPtr, \n\t\t\t\t\t\t\t&getnextcertInfo->cryptHandle, \n\t\t\t\t\t\t\tgetnextcertInfo->auxInfo, getnextcertInfo->flags ) );\n\t\t}\n#ifdef USE_DBMS\n\tif( message == MESSAGE_KEY_CERTMGMT )\n\t\t{\n\t\tMESSAGE_CERTMGMT_INFO *certMgmtInfo = \\\n\t\t\t\t\t\t\t\t( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;\n\n\t\tREQUIRES( messageValue >= CRYPT_CERTACTION_CERT_CREATION && \\\n\t\t\t\t  messageValue <= CRYPT_CERTACTION_LAST_USER );\n\n\t\t/* Perform the certificate management operation */\n\t\tresetErrorInfo( keysetInfoPtr );\n\t\tstatus = initKeysetUpdate( keysetInfoPtr, NULL, NULL, 0, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = keysetInfoPtr->keysetDBMS->certMgmtFunction( keysetInfoPtr,\n\t\t\t\t\t\t\t( certMgmtInfo->cryptCert != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\t&certMgmtInfo->cryptCert : NULL, \n\t\t\t\t\t\t\tcertMgmtInfo->caKey, certMgmtInfo->request, \n\t\t\t\t\t\t\tmessageValue );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* The update succeeded, remember that the data in the keyset has\n\t\t\t   changed */\n\t\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n#endif /* USE_DBMS */\n\n\tretIntError();\n\t}\n\n/* Open a keyset.  This is a low-level function encapsulated by createKeyset()\n   and used to manage error exits */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 7 ) ) \\\nstatic int openKeyset( OUT_HANDLE_OPT CRYPT_KEYSET *iCryptKeyset,\n\t\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t   IN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t   IN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_NAME_LENGTH ) const int nameLength,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options,\n\t\t\t\t\t   OUT_PTR_OPT KEYSET_INFO **keysetInfoPtrPtr )\n\t{\n\tKEYSET_INFO *keysetInfoPtr;\n\tSTREAM stream;\n\tKEYSET_SUBTYPE keysetSubType DUMMY_INIT;\n\tOBJECT_SUBTYPE subType;\n\tKEY_INIT_FUNCTION initFunction;\n\tBOOLEAN isReadOnly = ( options == CRYPT_KEYOPT_READONLY ) ? TRUE : FALSE;\n\tint storageSize, status;\n\n\tassert( isWritePtr( iCryptKeyset, sizeof( CRYPT_KEYSET ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\tassert( isWritePtr( keysetInfoPtrPtr, sizeof( KEYSET_INFO * ) ) );\n\n\tREQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isEnumRange( keysetType, CRYPT_KEYSET ) );\n\tREQUIRES( nameLength >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isEnumRangeOpt( options, CRYPT_KEYOPT ) );\n\n\t/* Clear the return values */\n\t*iCryptKeyset = CRYPT_ERROR;\n\t*keysetInfoPtrPtr = NULL;\n\n\t/* Perform general checks that can be done before we create the object */\n\tif( ( keysetType == CRYPT_KEYSET_HTTP && \\\n\t\t  options != CRYPT_KEYOPT_READONLY ) || \\\n\t\t( keysetType == CRYPT_KEYSET_LDAP && \\\n\t\t  options == CRYPT_KEYOPT_CREATE ) )\n\t\t{\n\t\t/* We can't open an HTTP keyset for anything other than read-only\n\t\t   access, and we can't create an LDAP directory */\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\tif( keysetType == CRYPT_KEYSET_FILE && nameLength > MAX_PATH_LENGTH - 1 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t/* Set up subtype-specific information */\n\tswitch( keysetType )\n\t\t{\n\t\tcase CRYPT_KEYSET_FILE:\n\t\t\tsubType = SUBTYPE_KEYSET_FILE_READONLY;\n\t\t\tstorageSize = sizeof( FILE_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_HTTP:\n\t\t\tsubType = SUBTYPE_KEYSET_HTTP;\n\t\t\tstorageSize = sizeof( HTTP_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_LDAP:\n\t\t\tsubType = SUBTYPE_KEYSET_LDAP;\n\t\t\tstorageSize = sizeof( LDAP_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_ODBC:\n\t\tcase CRYPT_KEYSET_DATABASE:\n\t\t\tsubType = SUBTYPE_KEYSET_DBMS;\n\t\t\tstorageSize = sizeof( DBMS_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_ODBC_STORE:\n\t\tcase CRYPT_KEYSET_DATABASE_STORE:\n\t\t\tsubType = SUBTYPE_KEYSET_DBMS_STORE;\n\t\t\tstorageSize = sizeof( DBMS_INFO );\n\t\t\tbreak;\n\t\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Handle compiler warnings of uninitialised variables, unfortunately \n\t   since it's non-scalar data we can't do this with the usual \n\t   DUMMY_INIT */\n\tmemset( &stream, 0, sizeof( STREAM ) );\t\n\n\t/* If it's a flat-file keyset which is implemented on top of an I/O \n\t   stream make sure that we can open the stream before we try and \n\t   create the keyset object */\n\tif( keysetType == CRYPT_KEYSET_FILE )\n\t\t{\n\t\tstatus = openKeysetStream( &stream, name, nameLength, options, \n\t\t\t\t\t\t\t\t   &isReadOnly, &keysetSubType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If the keyset contains the full set of search keys and index\n\t\t   information needed to handle all keyset operations (e.g. \n\t\t   certificate chain building, query by key usage types) we mark it \n\t\t   as a full-function keyset with the same functionality as a DBMS \n\t\t   keyset rather than just a generic flat-file store */\n\t\tif( keysetSubType == KEYSET_SUBTYPE_PKCS15 )\n\t\t\tsubType = SUBTYPE_KEYSET_FILE;\n\n\t\t/* If it's a limited keyset type that nonetheless allows writing\n\t\t   at least one public/private key, mark it as a restricted-function\n\t\t   keyset */\n#ifdef USE_PKCS12\n\t\tif( keysetSubType == KEYSET_SUBTYPE_PKCS12 )\n\t\t\tsubType = SUBTYPE_KEYSET_FILE_PARTIAL;\n#endif /* USE_PKCS12 */\n#ifdef USE_PGP\n\t\tif( keysetSubType == KEYSET_SUBTYPE_PGP_PUBLIC )\n\t\t\tsubType = SUBTYPE_KEYSET_FILE_PARTIAL;\n#endif /* USE_PGP */\n\n\t\t/* Make sure that the open-mode that's been specified is compatible\n\t\t   with the object subtype */\n\t\tswitch( subType )\n\t\t\t{\n\t\t\tcase SUBTYPE_KEYSET_FILE:\n\t\t\t\t/* All access modes allowed */\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_KEYSET_FILE_PARTIAL:\n\t\t\t\t/* Update access not allowed */\n\t\t\t\tif( options != CRYPT_KEYOPT_READONLY && \\\n\t\t\t\t\toptions != CRYPT_KEYOPT_CREATE )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_KEYSET_FILE_READONLY:\n\t\t\t\t/* Only read access allowed */\n\t\t\t\tif( options != CRYPT_KEYOPT_READONLY )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\n\t/* Create the keyset object */\n\tstatus = krnlCreateObject( iCryptKeyset, ( void ** ) &keysetInfoPtr, \n\t\t\t\t\t\t\t   sizeof( KEYSET_INFO ) + storageSize, \n\t\t\t\t\t\t\t   OBJECT_TYPE_KEYSET, subType, \n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, iCryptOwner, \n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, keysetMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( keysetType == CRYPT_KEYSET_FILE )\n\t\t\tsFileClose( &stream );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( keysetInfoPtr != NULL );\n\t*keysetInfoPtrPtr = keysetInfoPtr;\n\tkeysetInfoPtr->objectHandle = *iCryptKeyset;\n\tkeysetInfoPtr->ownerHandle = iCryptOwner;\n\tif( isReadOnly )\n\t\tINIT_FLAGS( keysetInfoPtr->flags, KEYSET_FLAG_READONLY );\n\telse\n\t\tINIT_FLAGS( keysetInfoPtr->flags, KEYSET_FLAG_NONE );\n\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\tswitch( keysetType )\n\t\t{\n\t\tcase CRYPT_KEYSET_FILE:\n\t\t\tkeysetInfoPtr->type = KEYSET_FILE;\n\t\t\tkeysetInfoPtr->keysetFile = ( FILE_INFO * ) keysetInfoPtr->storage;\n\t\t\tbreak;\n\n#ifdef USE_HTTP\n\t\tcase CRYPT_KEYSET_HTTP:\n\t\t\tkeysetInfoPtr->type = KEYSET_HTTP;\n\t\t\tkeysetInfoPtr->keysetHTTP = ( HTTP_INFO * ) keysetInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_HTTP */\n\n#ifdef USE_LDAP\n\t\tcase CRYPT_KEYSET_LDAP:\n\t\t\tkeysetInfoPtr->type = KEYSET_LDAP;\n\t\t\tkeysetInfoPtr->keysetLDAP = ( LDAP_INFO * ) keysetInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_LDAP */\n\n#ifdef USE_DBMS\n\t\tdefault:\n\t\t\tkeysetInfoPtr->type = KEYSET_DBMS;\n\t\t\tkeysetInfoPtr->keysetDBMS = ( DBMS_INFO * ) keysetInfoPtr->storage;\n\t\t\tbreak;\n#endif /* USE_DBMS */\n\t\t}\n\tkeysetInfoPtr->storageSize = storageSize;\n\n\t/* If it's a flat-file keyset which is implemented on top of an I/O \n\t   stream, handle it specially */\n\tif( keysetType == CRYPT_KEYSET_FILE )\n\t\t{\n\t\tstatus = completeKeysetFileOpen( keysetInfoPtr, keysetSubType, \n\t\t\t\t\t\t\t\t\t\t &stream, name, nameLength, \n\t\t\t\t\t\t\t\t\t\t options );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsFileClose( &keysetInfoPtr->keysetFile->stream );\n\t\t\tif( options == CRYPT_KEYOPT_CREATE )\n\t\t\t\t{\n\t\t\t\t/* It's a newly-created file, make sure that we don't leave \n\t\t\t\t   it lying around on disk */\n\t\t\t\tfileErase( keysetInfoPtr->keysetFile->fileName );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\t\t\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Wait for any async keyset driver binding to complete.  We do this as \n\t   late as possible to prevent file keyset reads that occur on startup \n\t   (for example to get configuration options) from stalling the startup \n\t   process */\n\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )\n\t\t{\n\t\t/* The kernel is shutting down, bail out */\n\t\tDEBUG_DIAG(( \"Exiting due to kernel shutdown\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* It's a specific type of keyset, set up the access information for it\n\t   and connect to it */\n\tswitch( keysetType )\n\t\t{\n\t\tcase CRYPT_KEYSET_ODBC:\n\t\tcase CRYPT_KEYSET_DATABASE:\n\t\tcase CRYPT_KEYSET_ODBC_STORE:\n\t\tcase CRYPT_KEYSET_DATABASE_STORE:\n\t\t\tstatus = setAccessMethodDBMS( keysetInfoPtr, keysetType );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_HTTP:\n\t\t\tstatus = setAccessMethodHTTP( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_LDAP:\n\t\t\tstatus = setAccessMethodLDAP( keysetInfoPtr );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( checkKeysetFunctions( keysetInfoPtr ) );\n\n\t/* Initialise keyset access */\n\tinitFunction = ( KEY_INIT_FUNCTION ) \\\n\t\t\t\t   FNPTR_GET( keysetInfoPtr->initFunction );\n\tREQUIRES( initFunction != NULL );\n\tstatus = initFunction( keysetInfoPtr, name, nameLength, \n\t\t\t\t\t\t   ( options == CRYPT_KEYOPT_CREATE ) ? \\\n\t\t\t\t\t\t\t CRYPT_KEYOPT_CREATE : CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_OPEN );\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a keyset object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createKeyset( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t  STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t  STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_KEYSET iCryptKeyset;\n\tKEYSET_INFO *keysetInfoPtr = NULL;\n\tint initStatus, status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRange( createInfo->arg1, CRYPT_KEYSET ) );\n\tREQUIRES( isEnumRangeOpt( createInfo->arg2, CRYPT_KEYOPT ) );\n\tREQUIRES( createInfo->strArgLen1 >= MIN_NAME_LENGTH && \\\n\t\t\t  createInfo->strArgLen1 < MAX_ATTRIBUTE_SIZE );\n\n\t/* Pass the call on to the lower-level open function */\n\tinitStatus = openKeyset( &iCryptKeyset, createInfo->cryptOwner,\n\t\t\t\t\t\t\t createInfo->arg1, createInfo->strArg1, \n\t\t\t\t\t\t\t createInfo->strArgLen1, createInfo->arg2,\n\t\t\t\t\t\t\t &keysetInfoPtr );\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( keysetInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\n\t\t/* Since no object has been created there's nothing to get a \n\t\t   detailed error string from, but we can at least send the \n\t\t   information to the debug output */\n\t\tDEBUG_PRINT_COND( initStatus != CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t\t\t  ( \"Keyset open error: %s.\\n\",\n\t\t\t\t\t\t\t( keysetInfoPtr->errorInfo.errorStringLength > 0 ) ? \\\n\t\t\t\t\t\t\t  keysetInfoPtr->errorInfo.errorString : \\\n\t\t\t\t\t\t\t  \"<<<No information available>>>\" ));\n\n\t\t/* The init failed, make sure that the object gets destroyed when we \n\t\t   notify the kernel that the setup process is complete */\n\t\tkrnlSendNotifier( iCryptKeyset, IMESSAGE_DESTROY );\n\t\t}\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\tcreateInfo->cryptHandle = iCryptKeyset;\n\treturn( CRYPT_OK );\n\t}\n\n/* Generic management function for this class of object */\n\nCHECK_RETVAL \\\nint keysetManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tstatic int initLevel = 0;\n\tint status;\n\n\tREQUIRES( action == MANAGEMENT_ACTION_INIT || \\\n\t\t\t  action == MANAGEMENT_ACTION_SHUTDOWN );\n\n\tswitch( action )\n\t\t{\n\t\tcase MANAGEMENT_ACTION_INIT:\n#ifdef CONFIG_FUZZ\n\t\t\treturn( CRYPT_OK );\n#endif /* CONFIG_FUZZ */\n\t\t\tstatus = dbxInitODBC();\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tinitLevel++;\n\t\t\t\tif( krnlIsExiting() )\n\t\t\t\t\t{\n\t\t\t\t\t/* The kernel is shutting down, exit */\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t\t}\n\t\t\t\tstatus = dbxInitLDAP();\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tinitLevel++;\n\t\t\treturn( status );\n\n\t\tcase MANAGEMENT_ACTION_SHUTDOWN:\n\t\t\tif( initLevel > 1 )\n\t\t\t\t{\n\t\t\t\tdbxEndLDAP();\n\t\t\t\t}\n\t\t\tif( initLevel > 0 )\n\t\t\t\t{\n\t\t\t\tdbxEndODBC();\n\t\t\t\t}\n\t\t\tinitLevel = 0;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/cryptkrn.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Kernel Interface Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CRYPTKRN_DEFINED\n\n#define _CRYPTKRN_DEFINED\n\n/* Macros to handle code correctness checking of critical sections of the \n   code such as the kernel and CSPRNG (sed quis custodiet ipsos custodes?), \n   extending the design-by-contract macros in misc/int_api.h */\n\n/* Value of a variable at the start of block scope, used for postcondition \n   predicates.  The pointer is declared as BYTE * rather than the more \n   general void * in order to allow range comparisons, and a BYTE * rather \n   than char * because of compilers that complain about comparisons between \n   signed and unsigned pointer types.  Note that these declarations must be \n   the last in any set of variable declarations since some of the higher-\n   overhead checks are only applied in the debug build and the release build \n   expands them to nothing, leaving only the terminating semicolon on the \n   line, which must follow all other declarations */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#define ORIGINAL_VALUE( x )\t\t\torig_##x\n#define ORIGINAL_INT( x )\t\t\tconst int orig_##x = ( int ) x\n#define ORIGINAL_PTR( x )\t\t\tconst BYTE *orig_##x = ( const BYTE * ) x\n\n#else\n\n#define ORIGINAL_VALUE( x )\n#define ORIGINAL_INT( x )\n#define ORIGINAL_PTR( x )\n\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/* Sometimes we can't use the preprocessor tricks above because the value \n   being saved isn't a primitive type or the variable value isn't available \n   at the start of the block, in which case we have to use the somewhat less \n   transparent macros below.\n   \n   In a small number of cases the values declared by these macros are only\n   used in debug builds, leading to unused-variable warnings in release \n   builds.  This is infrequent enough that there's not much point in adding\n   even further special-casing for them */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#define ORIGINAL_INT_VAR( x, y )\tconst int orig_##x = ( y )\n#define DECLARE_ORIGINAL_INT( x )\tint orig_##x\n#define STORE_ORIGINAL_INT( x, y )\torig_##x = ( y )\n\n#else\n\n#define ORIGINAL_INT_VAR( x, y )\n#define DECLARE_ORIGINAL_INT( x )\n#define STORE_ORIGINAL_INT( x, y )\n\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/* Some checks have a relatively high overhead (for example for_all and \n   there_exists on arrays) so we only perform them in the debug build */\n\n#if !( defined( NDEBUG ) || defined( CONFIG_CONSERVE_MEMORY_EXTRA ) )\n\n/* Universal qualifiers: for_all, there_exists.  Because of the typical use \n   of 'i' as loop variables we'll get compiler warnings about duplicate \n   variable declarations, unfortunately we can't fix this with something \n   like '_local_##iter' because the loop test condition is a free-form \n   expression and there's no easy way to create a localised form of all \n   references to the loop variable inside the expression */\n\n#define FORALL( iter, start, end, condition ) \\\n\t\t{ \\\n\t\tint iter; \\\n\t\t\\\n\t\tfor( iter = ( start ); iter < ( end ); iter++ ) \\\n\t\t\tassert( condition ); \\\n\t\t}\n\n#define EXISTS( iter, start, end, condition ) \\\n\t\t{ \\\n\t\tint iter; \\\n\t\t\\\n\t\tfor( iter = ( start ); iter < ( end ); iter++ ) \\\n\t\t\t{ \\\n\t\t\tif( condition ) \\\n\t\t\t\tbreak; \\\n\t\t\t} \\\n\t\tassert( iter < ( end ) ); \\\n\t\t}\n#else\n\n/* Non-debug version, no-op out the various checks */\n\n#define TEMP_INT( a )\n#define TEMP_VAR( a )\n#define FORALL( a, b, c, d )\n#define EXISTS( a, b, c, d )\n\n#endif /* !( NDEBUG || CONFIG_CONSERVE_MEMORY_EXTRA ) */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Message Types\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The object types */\n\ntypedef enum {\n\tOBJECT_TYPE_NONE,\t\t\t\t/* No object type */\n\tOBJECT_TYPE_CONTEXT,\t\t\t/* Context */\n\tOBJECT_TYPE_KEYSET,\t\t\t\t/* Keyset */\n\tOBJECT_TYPE_ENVELOPE,\t\t\t/* Envelope */\n\tOBJECT_TYPE_CERTIFICATE,\t\t/* Certificate */\n\tOBJECT_TYPE_DEVICE,\t\t\t\t/* Crypto device */\n\tOBJECT_TYPE_SESSION,\t\t\t/* Secure session */\n\tOBJECT_TYPE_USER,\t\t\t\t/* User object */\n\tOBJECT_TYPE_LAST\t\t\t\t/* Last possible object type */\n\t} OBJECT_TYPE;\n\n/* Object subtypes.  The subtype names aren't needed by the kernel (it just \n   treats the values as an anonymous bitfield during an ACL check) but they \n   are used in the ACL definitions and by the code that calls \n   krnlCreateObject(), so they need to be defined here.\n\n   Because there are so many object subtypes we have to split them across \n   two 32-bit bitfields in order to permit a simple bitwise AND check, if we \n   ordered them by the more obvious major and minor type (that is, object \n   type and subtype) this wouldn't be necessary but it would increase the \n   size of the compiled ACL table (from 2 * 32 bits to NO_OBJECT_TYPES * \n   32 bits) and would make automated consistency checking difficult since \n   it's no longer possible to spot a case where a subtype bit for object A \n   has inadvertently been set for object B.\n\n   To resolve this, we divide the subtype bit field into two smaller bit \n   fields (classes) with the high two bits designating which class the \n   subtype is in (actually we use the bits one below the high bit since \n   this may be interpreted as a sign bit by some preprocessors even if it's \n   declared as a xxxxUL, so in the following discussion we're talking about \n   logical rather than physical high bits).  Class A is always 01xxx..., \n   class B is always 10xxx...  If we get an entry that has 11xxx... we know \n   that the ACL entry is inconsistent.  This isn't pretty, but it's the \n   least ugly way to do it that still allows the ACL table to be built \n   using the preprocessor.\n\n   Note that the device and keyset values must be in the same class, since \n   they're interchangeable for many message types and this simplifies some \n   of the MKACL() macros that only need to initialise one class type.\n   \n   The different between SUBTYPE_KEYSET_FILE, SUBTYPE_KEYSET_FILE_PARTIAL,\n   and SUBTYPE_KEYSET_FILE_READONLY is that SUBTYPE_KEYSET_FILE stores a \n   full index of key ID types and allows storage of any data type, \n   SUBTYPE_KEYSET_FILE_PARTIAL only handles one or two key IDs and a \n   restricted set of data types so that only a single private key and \n   associated public key and certificate can be stored, and \n   SUBTYPE_KEYSET_FILE_READONLY is even more restricted and can't be \n   updated in any sensible manner.\n   \n   The difference between SUBTYPE_KEYSET_DBMS and SUBTYPE_KEYSET_DBMS_STORE \n   is similar, the former is a simple certificate-and-CRL store while the \n   latter stores assorted CA management data items and supports extended \n   operations */\n\n#define SUBTYPE_CLASS_MASK\t\t\t0x70000000L\n#define SUBTYPE_CLASS_A\t\t\t\t0x10000000L\n#define SUBTYPE_CLASS_B\t\t\t\t0x20000000L\n#define SUBTYPE_CLASS_C\t\t\t\t0x40000000L\n\n#define MK_SUBTYPE_A( value )\t\t( SUBTYPE_CLASS_A | ( 1L << ( value - 1 ) ) )\n#define MK_SUBTYPE_B( value )\t\t( SUBTYPE_CLASS_B | ( 1L << ( value - 1 ) ) )\n#define MK_SUBTYPE_C( value )\t\t( SUBTYPE_CLASS_C | ( 1L << ( value - 1 ) ) )\n\n#define SUBTYPE_NONE\t\t\t\t0x00000000L\n\n#define SUBTYPE_CTX_CONV\t\t\tMK_SUBTYPE_A( 1 )\n#define SUBTYPE_CTX_PKC\t\t\t\tMK_SUBTYPE_A( 2 )\n#define SUBTYPE_CTX_HASH\t\t\tMK_SUBTYPE_A( 3 )\n#define SUBTYPE_CTX_MAC\t\t\t\tMK_SUBTYPE_A( 4 )\n#define SUBTYPE_CTX_GENERIC\t\t\tMK_SUBTYPE_A( 5 )\n\n#define SUBTYPE_CERT_CERT\t\t\tMK_SUBTYPE_A( 6 )\n#define SUBTYPE_CERT_CERTREQ\t\tMK_SUBTYPE_A( 7 )\n#define SUBTYPE_CERT_REQ_CERT\t\tMK_SUBTYPE_A( 8 )\n#define SUBTYPE_CERT_REQ_REV\t\tMK_SUBTYPE_A( 9 )\n#define SUBTYPE_CERT_CERTCHAIN\t\tMK_SUBTYPE_A( 10 )\n#define SUBTYPE_CERT_ATTRCERT\t\tMK_SUBTYPE_A( 11 )\n#define SUBTYPE_CERT_CRL\t\t\tMK_SUBTYPE_A( 12 )\n#define SUBTYPE_CERT_CMSATTR\t\tMK_SUBTYPE_A( 13 )\n#define SUBTYPE_CERT_RTCS_REQ\t\tMK_SUBTYPE_A( 14 )\n#define SUBTYPE_CERT_RTCS_RESP\t\tMK_SUBTYPE_A( 15 )\n#define SUBTYPE_CERT_OCSP_REQ\t\tMK_SUBTYPE_A( 16 )\n#define SUBTYPE_CERT_OCSP_RESP\t\tMK_SUBTYPE_A( 17 )\n#define SUBTYPE_CERT_PKIUSER\t\tMK_SUBTYPE_A( 18 )\n\n#define SUBTYPE_ENV_ENV\t\t\t\tMK_SUBTYPE_B( 1 )\n#define SUBTYPE_ENV_ENV_PGP\t\t\tMK_SUBTYPE_B( 2 )\n#define SUBTYPE_ENV_DEENV\t\t\tMK_SUBTYPE_B( 3 )\n\n#define SUBTYPE_KEYSET_FILE\t\t\tMK_SUBTYPE_B( 4 )\n#define SUBTYPE_KEYSET_FILE_PARTIAL\tMK_SUBTYPE_B( 5 )\n#define SUBTYPE_KEYSET_FILE_READONLY MK_SUBTYPE_B( 6 )\n#define SUBTYPE_KEYSET_DBMS\t\t\tMK_SUBTYPE_B( 7 )\n#define SUBTYPE_KEYSET_DBMS_STORE\tMK_SUBTYPE_B( 8 )\n#define SUBTYPE_KEYSET_HTTP\t\t\tMK_SUBTYPE_B( 9 )\n#define SUBTYPE_KEYSET_LDAP\t\t\tMK_SUBTYPE_B( 10 )\n\n#define SUBTYPE_DEV_SYSTEM\t\t\tMK_SUBTYPE_B( 11 )\n#define SUBTYPE_DEV_PKCS11\t\t\tMK_SUBTYPE_B( 12 )\n#define SUBTYPE_DEV_CRYPTOAPI\t\tMK_SUBTYPE_B( 13 )\n#define SUBTYPE_DEV_HARDWARE\t\tMK_SUBTYPE_B( 14 )\n\n#define SUBTYPE_SESSION_SSH\t\t\tMK_SUBTYPE_C( 1 )\n#define SUBTYPE_SESSION_SSH_SVR\t\tMK_SUBTYPE_C( 2 )\n#define SUBTYPE_SESSION_SSL\t\t\tMK_SUBTYPE_C( 3 )\n#define SUBTYPE_SESSION_SSL_SVR\t\tMK_SUBTYPE_C( 4 )\n#define SUBTYPE_SESSION_RTCS\t\tMK_SUBTYPE_C( 5 )\n#define SUBTYPE_SESSION_RTCS_SVR\tMK_SUBTYPE_C( 6 )\n#define SUBTYPE_SESSION_OCSP\t\tMK_SUBTYPE_C( 7 )\n#define SUBTYPE_SESSION_OCSP_SVR\tMK_SUBTYPE_C( 8 )\n#define SUBTYPE_SESSION_TSP\t\t\tMK_SUBTYPE_C( 9 )\n#define SUBTYPE_SESSION_TSP_SVR\t\tMK_SUBTYPE_C( 10 )\n#define SUBTYPE_SESSION_CMP\t\t\tMK_SUBTYPE_C( 11 )\n#define SUBTYPE_SESSION_CMP_SVR\t\tMK_SUBTYPE_C( 12 )\n#define SUBTYPE_SESSION_SCEP\t\tMK_SUBTYPE_C( 13 )\n#define SUBTYPE_SESSION_SCEP_SVR\tMK_SUBTYPE_C( 14 )\n#define SUBTYPE_SESSION_CERT_SVR\tMK_SUBTYPE_C( 15 )\n\n#define SUBTYPE_USER_SO\t\t\t\tMK_SUBTYPE_C( 16 )\n#define SUBTYPE_USER_NORMAL\t\t\tMK_SUBTYPE_C( 17 )\n#define SUBTYPE_USER_CA\t\t\t\tMK_SUBTYPE_C( 18 )\n\n#define SUBTYPE_LAST\t\t\t\tSUBTYPE_USER_CA\n\n/* The data type used to store subtype values */\n\n#ifdef SYSTEM_16BIT\n  typedef long OBJECT_SUBTYPE;\n#else\n  typedef int OBJECT_SUBTYPE;\n#endif /* 16- vs.32-bit systems */\n\n/* Message flags.  Normally messages can only be sent to external objects, \n   however we can also explicitly send them to internal objects which means \n   that we use the internal rather than external access ACL.  This can only \n   be done from inside cryptlib, for example when an object sends a message \n   to a subordinate object */\n\n#define MESSAGE_FLAG_INTERNAL\t\t0x100\n#define MKINTERNAL( message )\t\t( message | MESSAGE_FLAG_INTERNAL )\n\n/* A mask to extract the basic message type */\n\n#define MESSAGE_MASK\t\t\t\t0xFF\n\n/* The message types that can be sent to an object via krnlSendMessage(). \n   By default messages can only be sent to externally visible objects, there \n   are also internal versions that can be sent to all objects.  The object \n   messages have the following arguments:\n\n\tType\t\t\t\t\t\t\t\tDataPtr\t\t\tValue\n\t---------------------------\t\t\t-------\t\t\t-----\n\tMESSAGE_DESTROY\t\t\t\t\t\tNULL\t\t\t0\n\tMESSAGE_INC/DECREFCOUNT\t\t\t\tNULL\t\t\t0\n\tMESSAGE_GETDEPENDENT\t\t\t\t&objectHandle\tobjectType\n\tMESSAGE_SETDEPENDENT\t\t\t\t&objectHandle\tincRefCount\n\tMESSAGE_CLONE\t\t\t\t\t\tNULL\t\t\tcloneContext\n\tMESSAGE_GET/SETATTRIBUTE\t\t\t&value\t\t\tattributeType\n\tMESSAGE_DELETEATTRIBUTE\t\t\t\tNULL\t\t\tattributeType\n\tMESSAGE_COMPARE\t\t\t\t\t\t&value\t\t\tcompareType\n\tMESSAGE_CHECK\t\t\t\t\t\tNULL\t\t\trequestedUse\n\tMESSAGE_SELFTEST\t\t\t\t\tNULL\t\t\t0\n\n\tMESSAGE_CHANGENOTIFY\t\t\t\t&value\t\t\tattributeType\n\n\tMESSAGE_CTX_ENCRYPT/DECRYPT/SIGN/-\n\t\tSIGCHECK/HASH\t\t\t\t\t&value\t\t\tvalueLength\n\tMESSAGE_CTX_GENKEY\t\t\t\t\tNULL\t\t\t0\n\tMESSAGE_CTX_GENIV\t\t\t\t\tNULL\t\t\t0\n\n\tMESSAGE_CRT_SIGN,\t\t\t\t\tNULL\t\t\tsigKey\n\tMESSAGE_CRT_SIGCHECK,\t\t\t\tNULL\t\t\tverifyObject\n\tMESSAGE_CRT_EXPORT,\t\t\t\t\t&value\t\t\tformatType\n\n\tMESSAGE_DEV_QUERYCAPABILITY\t\t\t&queryInfo\t\talgorithm\n\tMESSAGE_DEV_EXPORT/IMPORT/SIGN/-\n\t\tSIGCHECK/DERIVE/KDF\t\t\t\t&mechanismInfo\tmechanismType\n\tMESSAGE_DEV_CREATEOBJECT\t\t\t&createInfo\t\tobjectType\n\tMESSAGE_DEV_CREATEOBJECT_INDIRECT\t&createInfo\t\tobjectType\n\n\tMESSAGE_ENV_PUSH/POPDATA\t\t\t&value\t\t\t0\n\n\tMESSAGE_KEY_GET/SET/DELETEKEY\t\t&keymgmtInfo\titemType\n\tMESSAGE_KEY_GETFIRST/NEXTCERT\t\t&keymgmtInfo\titemType\n\tMESSAGE_KEY_CERTMGMT\t\t\t\t&certMgmtInfo\taction \n\t\n\tMESSAGE_USER_USERMGMT\t\t\t\t&value\t\t\taction\n\tMESSAGE_USER_TRUSTMGMT\t\t\t\t&value\t\t\taction */\n\ntypedef enum {\n\tMESSAGE_NONE,\t\t\t\t/* No message type */\n\n\t/* Control messages to externally visible objects (the internal versions \n\t   are defined further down).  These messages are handled directly by \n\t   the kernel and don't affect the object itself except for \n\t   MESSAGE_DESTROY which is generated by the kernel in response to the \n\t   final MESSAGE_DECREFCOUNT sent to an object.  These are forwarded out \n\t   to the object to get it to clean up its state before the kernel \n\t   destroys it */\n\tMESSAGE_DESTROY,\t\t\t/* Destroy the object */\n\tMESSAGE_INCREFCOUNT,\t\t/* Increment object ref.count */\n\tMESSAGE_DECREFCOUNT,\t\t/* Decrement object ref.count */\n\tMESSAGE_GETDEPENDENT,\t\t/* Get dependent object */\n\tMESSAGE_SETDEPENDENT,\t\t/* Set dependent object (e.g.ctx->dev) */\n\tMESSAGE_CLONE,\t\t\t\t/* Clone the object */\n\n\t/* Attribute messages.  The reason for the numeric vs.non-numeric \n\t   attribute messages is that for improved error checking the data types \n\t   that these work with are explicitly specified by the user based on \n\t   which function they call to get/set them rather than being implicitly \n\t   specified by the attribute ID.  Because of the explicit typing, the \n\t   handlers have to be able to check to make sure that the actual type \n\t   matches what the user specified, so we need one message type for \n\t   numeric attributes and one for string attributes */\n\tMESSAGE_GETATTRIBUTE,\t\t/* Get numeric object attribute */\n\tMESSAGE_GETATTRIBUTE_S,\t\t/* Get string object attribute */\n\tMESSAGE_SETATTRIBUTE,\t\t/* Set numeric object attribute */\n\tMESSAGE_SETATTRIBUTE_S,\t\t/* Set string object attribute */\n\tMESSAGE_DELETEATTRIBUTE,\t/* Delete object attribute */\n\n\t/* General messages.  The check message is used for informational \n\t   purposes only so that problems (e.g. an attempt to use a public key \n\t   where a private key is required) can be reported to the user \n\t   immediately as a function parameter error rather than appearing much \n\t   later as an object use permission error when the kernel blocks the \n\t   access.  Final access checking is always still done at the kernel \n\t   level to avoid the confused deputy problem */\n\tMESSAGE_COMPARE,\t\t\t/* Compare objs. or obj.properties */\n\tMESSAGE_CHECK,\t\t\t\t/* Check object info */\n\tMESSAGE_SELFTEST,\t\t\t/* Perform a self-test */\n\n\t/* Messages sent from the kernel to object message handlers.  These never \n\t   originate from outside the kernel but are generated in response to \n\t   other messages to notify an object of a change in its state */\n\tMESSAGE_CHANGENOTIFY,\t\t/* Notification of obj.status chge.*/\n\n\t/* Object-type-specific messages */\n\tMESSAGE_CTX_ENCRYPT,\t\t/* Context: Action = encrypt */\n\tMESSAGE_CTX_DECRYPT,\t\t/* Context: Action = decrypt */\n\tMESSAGE_CTX_SIGN,\t\t\t/* Context: Action = sign */\n\tMESSAGE_CTX_SIGCHECK,\t\t/* Context: Action = sigcheck */\n\tMESSAGE_CTX_HASH,\t\t\t/* Context: Action = hash */\n\tMESSAGE_CTX_GENKEY,\t\t\t/* Context: Generate a key */\n\tMESSAGE_CTX_GENIV,\t\t\t/* Context: Generate an IV */\n\tMESSAGE_CRT_SIGN,\t\t\t/* Cert: Action = sign cert */\n\tMESSAGE_CRT_SIGCHECK,\t\t/* Cert: Action = check/verify cert */\n\tMESSAGE_CRT_EXPORT,\t\t\t/* Cert: Export encoded cert data */\n\tMESSAGE_DEV_QUERYCAPABILITY,/* Device: Query capability */\n\tMESSAGE_DEV_EXPORT,\t\t\t/* Device: Action = export key */\n\tMESSAGE_DEV_IMPORT,\t\t\t/* Device: Action = import key */\n\tMESSAGE_DEV_SIGN,\t\t\t/* Device: Action = sign */\n\tMESSAGE_DEV_SIGCHECK,\t\t/* Device: Action = sig.check */\n\tMESSAGE_DEV_DERIVE,\t\t\t/* Device: Action = derive key */\n\tMESSAGE_DEV_KDF,\t\t\t/* Device: Action = KDF */\n\tMESSAGE_DEV_CREATEOBJECT,\t/* Device: Create object */\n\tMESSAGE_DEV_CREATEOBJECT_INDIRECT,\t/* Device: Create obj.from data */\n\tMESSAGE_ENV_PUSHDATA,\t\t/* Envelope: Push data */\n\tMESSAGE_ENV_POPDATA,\t\t/* Envelope: Pop data */\n\tMESSAGE_KEY_GETKEY,\t\t\t/* Keyset: Instantiate ctx/cert */\n\tMESSAGE_KEY_SETKEY,\t\t\t/* Keyset: Add ctx/cert */\n\tMESSAGE_KEY_DELETEKEY,\t\t/* Keyset: Delete key/cert */\n\tMESSAGE_KEY_GETFIRSTCERT,\t/* Keyset: Get first cert in sequence */\n\tMESSAGE_KEY_GETNEXTCERT,\t/* Keyset: Get next cert in sequence */\n\tMESSAGE_KEY_CERTMGMT,\t\t/* Keyset: Cert management */\n\tMESSAGE_USER_USERMGMT,\t\t/* User: User management */\n\tMESSAGE_USER_TRUSTMGMT,\t\t/* User: Trust management */\n\tMESSAGE_LAST,\t\t\t\t/* Last valid message type */\n\n\t/* Internal-object versions of the above messages */\n\tIMESSAGE_DESTROY = MKINTERNAL( MESSAGE_DESTROY ),\n\tIMESSAGE_INCREFCOUNT = MKINTERNAL( MESSAGE_INCREFCOUNT ),\n\tIMESSAGE_DECREFCOUNT = MKINTERNAL( MESSAGE_DECREFCOUNT ),\n\tIMESSAGE_GETDEPENDENT = MKINTERNAL( MESSAGE_GETDEPENDENT ),\n\tIMESSAGE_SETDEPENDENT = MKINTERNAL( MESSAGE_SETDEPENDENT ),\n\tIMESSAGE_CLONE = MKINTERNAL( MESSAGE_CLONE ),\n\n\tIMESSAGE_GETATTRIBUTE = MKINTERNAL( MESSAGE_GETATTRIBUTE ),\n\tIMESSAGE_GETATTRIBUTE_S = MKINTERNAL( MESSAGE_GETATTRIBUTE_S ),\n\tIMESSAGE_SETATTRIBUTE = MKINTERNAL( MESSAGE_SETATTRIBUTE ),\n\tIMESSAGE_SETATTRIBUTE_S = MKINTERNAL( MESSAGE_SETATTRIBUTE_S ),\n\tIMESSAGE_DELETEATTRIBUTE = MKINTERNAL( MESSAGE_DELETEATTRIBUTE ),\n\n\tIMESSAGE_COMPARE = MKINTERNAL( MESSAGE_COMPARE ),\n\tIMESSAGE_CHECK = MKINTERNAL( MESSAGE_CHECK ),\n\tIMESSAGE_SELFTEST = MKINTERNAL( MESSAGE_SELFTEST ),\n\n\tIMESSAGE_CHANGENOTIFY = MKINTERNAL( MESSAGE_CHANGENOTIFY ),\n\n\tIMESSAGE_CTX_ENCRYPT = MKINTERNAL( MESSAGE_CTX_ENCRYPT ),\n\tIMESSAGE_CTX_DECRYPT = MKINTERNAL( MESSAGE_CTX_DECRYPT ),\n\tIMESSAGE_CTX_SIGN = MKINTERNAL( MESSAGE_CTX_SIGN ),\n\tIMESSAGE_CTX_SIGCHECK = MKINTERNAL( MESSAGE_CTX_SIGCHECK ),\n\tIMESSAGE_CTX_HASH = MKINTERNAL( MESSAGE_CTX_HASH ),\n\tIMESSAGE_CTX_GENKEY = MKINTERNAL( MESSAGE_CTX_GENKEY ),\n\tIMESSAGE_CTX_GENIV = MKINTERNAL( MESSAGE_CTX_GENIV ),\n\tIMESSAGE_CRT_SIGN = MKINTERNAL( MESSAGE_CRT_SIGN ),\n\tIMESSAGE_CRT_SIGCHECK = MKINTERNAL( MESSAGE_CRT_SIGCHECK ),\n\tIMESSAGE_CRT_EXPORT = MKINTERNAL( MESSAGE_CRT_EXPORT ),\n\tIMESSAGE_DEV_QUERYCAPABILITY = MKINTERNAL( MESSAGE_DEV_QUERYCAPABILITY ),\n\tIMESSAGE_DEV_EXPORT = MKINTERNAL( MESSAGE_DEV_EXPORT ),\n\tIMESSAGE_DEV_IMPORT = MKINTERNAL( MESSAGE_DEV_IMPORT ),\n\tIMESSAGE_DEV_SIGN = MKINTERNAL( MESSAGE_DEV_SIGN ),\n\tIMESSAGE_DEV_SIGCHECK = MKINTERNAL( MESSAGE_DEV_SIGCHECK ),\n\tIMESSAGE_DEV_DERIVE = MKINTERNAL( MESSAGE_DEV_DERIVE ),\n\tIMESSAGE_DEV_KDF = MKINTERNAL( MESSAGE_DEV_KDF ),\n\tIMESSAGE_DEV_CREATEOBJECT = MKINTERNAL( MESSAGE_DEV_CREATEOBJECT ),\n\tIMESSAGE_DEV_CREATEOBJECT_INDIRECT = MKINTERNAL( MESSAGE_DEV_CREATEOBJECT_INDIRECT ),\n\tIMESSAGE_ENV_PUSHDATA = MKINTERNAL( MESSAGE_ENV_PUSHDATA ),\n\tIMESSAGE_ENV_POPDATA = MKINTERNAL( MESSAGE_ENV_POPDATA ),\n\tIMESSAGE_KEY_GETKEY = MKINTERNAL( MESSAGE_KEY_GETKEY ),\n\tIMESSAGE_KEY_SETKEY = MKINTERNAL( MESSAGE_KEY_SETKEY ),\n\tIMESSAGE_KEY_DELETEKEY = MKINTERNAL( MESSAGE_KEY_DELETEKEY ),\n\tIMESSAGE_KEY_GETFIRSTCERT = MKINTERNAL( MESSAGE_KEY_GETFIRSTCERT ),\n\tIMESSAGE_KEY_GETNEXTCERT = MKINTERNAL( MESSAGE_KEY_GETNEXTCERT ),\n\tIMESSAGE_KEY_CERTMGMT = MKINTERNAL( MESSAGE_KEY_CERTMGMT ),\n\tIMESSAGE_USER_USERMGMT = MKINTERNAL( MESSAGE_USER_USERMGMT ),\n\tIMESSAGE_USER_TRUSTMGMT = MKINTERNAL( MESSAGE_USER_TRUSTMGMT ),\n\tIMESSAGE_LAST = MKINTERNAL( MESSAGE_LAST )\n\t} MESSAGE_TYPE;\n\n/* The properties that MESSAGE_COMPARE can compare */\n\ntypedef enum {\n\tMESSAGE_COMPARE_NONE,\t\t\t/* No comparison type */\n\tMESSAGE_COMPARE_HASH,\t\t\t/* Compare hash/MAC value */\n\tMESSAGE_COMPARE_ICV,\t\t\t/* Compare ICV value */\n\tMESSAGE_COMPARE_KEYID,\t\t\t/* Compare key IDs */\n\tMESSAGE_COMPARE_KEYID_PGP,\t\t/* Compare PGP key IDs */\n\tMESSAGE_COMPARE_KEYID_OPENPGP,\t/* Compare OpenPGP key IDs */\n\tMESSAGE_COMPARE_SUBJECT,\t\t/* Compare subject */\n\tMESSAGE_COMPARE_ISSUERANDSERIALNUMBER,\t/* Compare iAndS */\n\tMESSAGE_COMPARE_SUBJECTKEYIDENTIFIER,\t/* Compare subjectKeyIdentifier */\n\tMESSAGE_COMPARE_FINGERPRINT_SHA1,/* Compare cert.fingerprint */\n\tMESSAGE_COMPARE_FINGERPRINT_SHA2,/* Compare fingerprint, SHA2 */\n\tMESSAGE_COMPARE_FINGERPRINT_SHAng,/* Compare fingerprint, SHAng */\n\tMESSAGE_COMPARE_CERTOBJ,\t\t/* Compare cert objects */\n\tMESSAGE_COMPARE_LAST\t\t\t/* Last possible compare type */\n\t} MESSAGE_COMPARE_TYPE;\n\n/* The checks that MESSAGE_CHECK performs.  There are a number of variations \n   of the checking we can perform, either the object is initialised in a \n   state to perform the required action (meaning that it has to be in the \n   high state), the object is ready to be initialised for the required \n   action, for example an encryption context about to have a key loaded for \n   encryption (meaning that it has to be in the low state), or the check is \n   on a passive container object that constrains another object (for example \n   a cert being attached to a context) for which the state isn't important \n   in this instance.  Usually we check to make sure that the cert is in the \n   high state, but when a cert is being created/imported it may not be in \n   the high state yet at the time the check is being carried out */\n\ntypedef enum {\n\t/* Standard checks, for which the object must be initialised in a state \n\t   to perform this operation */\n\tMESSAGE_CHECK_NONE,\t\t\t\t/* No check type */\n\tMESSAGE_CHECK_PKC,\t\t\t\t/* Public or private key context */\n\tMESSAGE_CHECK_PKC_PRIVATE,\t\t/* Private key context */\n\tMESSAGE_CHECK_PKC_ENCRYPT,\t\t/* Public encryption context */\n\tMESSAGE_CHECK_PKC_DECRYPT,\t\t/* Private decryption context */\n\tMESSAGE_CHECK_PKC_SIGCHECK,\t\t/* Public signature check context */\n\tMESSAGE_CHECK_PKC_SIGN,\t\t\t/* Private signature context */\n\tMESSAGE_CHECK_PKC_KA_EXPORT,\t/* Key agreement - export context */\n\tMESSAGE_CHECK_PKC_KA_IMPORT,\t/* Key agreement - import context */\n\tMESSAGE_CHECK_CRYPT,\t\t\t/* Conventional encryption context */\n\tMESSAGE_CHECK_HASH,\t\t\t\t/* Hash context */\n\tMESSAGE_CHECK_MAC,\t\t\t\t/* MAC context */\n\n\t/* Checks that an object is ready to be initialised to perform this \n\t   operation */\n\tMESSAGE_CHECK_CRYPT_READY,\t\t/* Ready for conv.encr. init */\n\tMESSAGE_CHECK_MAC_READY,\t\t/* Ready for MAC init */\n\tMESSAGE_CHECK_KEYGEN_READY,\t\t/* Ready for key generation */\n\n\t/* Checks on purely passive container objects that constrain action \n\t   objects */\n\tMESSAGE_CHECK_PKC_ENCRYPT_AVAIL,/* Encryption available */\n\tMESSAGE_CHECK_PKC_DECRYPT_AVAIL,/* Decryption available */\n\tMESSAGE_CHECK_PKC_SIGCHECK_AVAIL,\t/* Signature check available */\n\tMESSAGE_CHECK_PKC_SIGN_AVAIL,\t/* Signature available */\n\tMESSAGE_CHECK_PKC_KA_EXPORT_AVAIL,\t/* Key agreement - export available */\n\tMESSAGE_CHECK_PKC_KA_IMPORT_AVAIL,\t/* Key agreement - import available */\n\n\t/* The use of certificates introduces an oddball special case in which a\n\t   signing key is allowed to sign any conceivable bit pattern except for \n\t   one that looks like a certificate, and vice versa.  This means that \n\t   while a CA key can be used for signing, it can't be used to sign c\n\t   anything other than a certificate, so a check for a general signing \n\t   capability via MESSAGE_CHECK_PKC_SIGN/MESSAGE_CHECK_PKC_SIGCHECK \n\t   should fail.\n\n\t   This leads to a problematic situation in which a check for the \n\t   signing capability of a context would indicate that it's unusable if \n\t   it's associated with a CA certificate rather than a general signing \n\t   certificate.  Because of this we have to provide special-case checks \n\t   that checks for data-that-looks-like-a-certificate signing rather \n\t   than the default data-that-isnt-a-certificate signing capability.  \n\t   The following checks mirror the standard checks, but apply to \n\t   certificate-only signing */\n\tMESSAGE_CHECK_PKC_SIGCHECK_CA,\t/* Certificate sig.check */\n\tMESSAGE_CHECK_PKC_SIGN_CA,\t\t/* Certificate signing */\n\tMESSAGE_CHECK_PKC_SIGCHECK_CA_AVAIL,/* Certificate sig.check available */\n\tMESSAGE_CHECK_PKC_SIGN_CA_AVAIL,/* Certificate signing available */\n\n\t/* Miscellaneous checks for meta-capabilities not directly connected \n\t   with object actions.  The certificate check is used to verify that a \n\t   certificate is generally valid (for example not expired) without \n\t   having to performing a full signature verification up to a trusted \n\t   root.  This is used to verify certificates passed in as parameters, \n\t   for example server certificates, to ensure that the client doesn't \n\t   get invalid data back when it tries to connect to the server */\n\tMESSAGE_CHECK_CERT,\t\t\t\t/* Generic certificate */\n\n\tMESSAGE_CHECK_LAST\t\t\t\t/* Last possible check type */\n\t} MESSAGE_CHECK_TYPE;\n\n/* The notifications that a MESSAGE_CHANGENOTIFY can deliver */\n\ntypedef enum {\n\tMESSAGE_CHANGENOTIFY_NONE,\t\t/* No notification type */\n\tMESSAGE_CHANGENOTIFY_STATE,\t\t/* Object should save/rest.int.state */\n\tMESSAGE_CHANGENOTIFY_OBJHANDLE,\t/* Object cloned, handle changed */\n\tMESSAGE_CHANGENOTIFY_OWNERHANDLE,\t/* Object cloned, owner handle changed */\n\tMESSAGE_CHANGENOTIFY_LAST\t\t/* Last possible notification type */\n\t} MESSAGE_CHANGENOTIFY_TYPE;\n\n/* The operations that a MESSAGE_USER_USERMGMT can perform */\n\ntypedef enum {\n\tMESSAGE_USERMGMT_NONE,\t\t\t/* No operation type */\n\tMESSAGE_USERMGMT_ZEROISE,\t\t/* Zeroise users */\n\tMESSAGE_USERMGMT_LAST\t\t\t/* Last possible operation type */\n\t} MESSAGE_USERMGMT_TYPE;\n\n/* The operations that a MESSAGE_USER_TRUSTMGMT can perform */\n\ntypedef enum {\n\tMESSAGE_TRUSTMGMT_NONE,\t\t\t/* No operation type */\n\tMESSAGE_TRUSTMGMT_ADD,\t\t\t/* Add trusted cert */\n\tMESSAGE_TRUSTMGMT_DELETE,\t\t/* Delete trusted cert */\n\tMESSAGE_TRUSTMGMT_CHECK,\t\t/* Check trust status of cert */\n\tMESSAGE_TRUSTMGMT_GETISSUER,\t/* Get trusted issuer cert */\n\tMESSAGE_TRUSTMGMT_LAST\t\t\t/* Last possible operation type */\n\t} MESSAGE_TRUSTMGMT_TYPE;\n\n/* Options for the MESSAGE_SETDEPENDENT message */\n\ntypedef enum {\n\tSETDEP_OPTION_NONE,\t\t\t\t/* No option type */\n\tSETDEP_OPTION_NOINCREF,\t\t\t/* Don't inc.dep.objs reference count */\n\tSETDEP_OPTION_INCREF,\t\t\t/* Increment dep.objs reference count */\n\tSETDEP_OPTION_LAST\t\t\t\t/* Last possible option type */\n\t} MESSAGE_SETDEPENDENT_TYPE;\n\n/* When getting/setting string data that consists of (value, length) pairs, \n   we pass a pointer to a value-and-length structure rather than a pointer \n   to the data itself */\n\ntypedef struct {\n\tBUFFER_FIXED( length ) \\\n\tvoid *data;\t\t\t\t\t\t\t/* Data */\n\tint length;\t\t\t\t\t\t\t/* Length */\n\t} MESSAGE_DATA;\n\n#define setMessageData( msgDataPtr, dataPtr, dataLength ) \\\n\t{ \\\n\t( msgDataPtr )->data = ( dataPtr ); \\\n\t( msgDataPtr )->length = ( dataLength ); \\\n\t}\n\n/* When passing constant data to krnlSendMessage() we get compiler warnings \n   because the function is prototyped as taking a 'void *', and the same for\n   krnlAcquireObject(), which takes a 'void **'.  The following symbolic \n   values for use in casts correct the parameter mismatch */\n\ntypedef void *MESSAGE_CAST;\ntypedef void **MESSAGE_PTR_CAST;\n\n/* Some messages communicate standard data values that are used again and \n   again, so we predefine values for these that can be used globally */\n\n#define MESSAGE_VALUE_TRUE\t\t\t( ( MESSAGE_CAST ) &messageValueTrue )\n#define MESSAGE_VALUE_FALSE\t\t\t( ( MESSAGE_CAST ) &messageValueFalse )\n#define MESSAGE_VALUE_OK\t\t\t( ( MESSAGE_CAST ) &messageValueCryptOK )\n#define MESSAGE_VALUE_ERROR\t\t\t( ( MESSAGE_CAST ) &messageValueCryptError )\n#define MESSAGE_VALUE_UNUSED\t\t( ( MESSAGE_CAST ) &messageValueCryptUnused )\n#define MESSAGE_VALUE_DEFAULT\t\t( ( MESSAGE_CAST ) &messageValueCryptUseDefault )\n#define MESSAGE_VALUE_CURSORFIRST\t( ( MESSAGE_CAST ) &messageValueCursorFirst )\n#define MESSAGE_VALUE_CURSORNEXT\t( ( MESSAGE_CAST ) &messageValueCursorNext )\n#define MESSAGE_VALUE_CURSORPREVIOUS ( ( MESSAGE_CAST ) &messageValueCursorPrevious )\n#define MESSAGE_VALUE_CURSORLAST\t( ( MESSAGE_CAST ) &messageValueCursorLast )\n\nextern const int messageValueTrue, messageValueFalse;\nextern const int messageValueCryptOK, messageValueCryptError;\nextern const int messageValueCryptUnused, messageValueCryptUseDefault;\nextern const int messageValueCursorFirst, messageValueCursorNext;\nextern const int messageValueCursorPrevious, messageValueCursorLast;\n\n/* Check for membership within an attribute class */\n\n#define isAttribute( attribute ) \\\n\t( ( attribute ) > CRYPT_ATTRIBUTE_NONE && \\\n\t  ( attribute ) < CRYPT_ATTRIBUTE_LAST )\n#define isInternalAttribute( attribute ) \\\n\t( ( attribute ) > CRYPT_IATTRIBUTE_FIRST && \\\n\t  ( attribute ) < CRYPT_IATTRIBUTE_LAST )\n\n/* Check whether a message is in a given message class, used in object \n   message handlers */\n\n#define isAttributeMessage( message ) \\\n\t( ( message ) >= MESSAGE_GETATTRIBUTE && \\\n\t  ( message ) <= MESSAGE_DELETEATTRIBUTE )\n#define isActionMessage( message ) \\\n\t( ( message ) >= MESSAGE_CTX_ENCRYPT && \\\n\t  ( message ) <= MESSAGE_CTX_HASH )\n#define isMechanismActionMessage( message ) \\\n\t( ( message ) >= MESSAGE_DEV_EXPORT && \\\n\t  ( message ) <= MESSAGE_DEV_KDF )\n\n/* The following handles correspond to built-in fixed object types that are \n   available throughout the architecture.  Currently there are two objects, \n   an internal system object that encapsulates the built-in RNG and the \n   built-in mechanism types (if this ever becomes a bottleneck the two can be \n   separated into different objects) and a default user object which is used \n   when there are no explicit user objects being employed */\n\n#define SYSTEM_OBJECT_HANDLE\t0\t/* Internal system object */\n#define DEFAULTUSER_OBJECT_HANDLE 1\t/* Default user object */\n\n#define NO_SYSTEM_OBJECTS\t\t2\t/* Total number of system objects */\n\n/* The maximum number of objects.  By default we use a fixed limit set to an\n   appropriate large-enough value because the only time anyone that would \n   really be creating thousands of objects is if they're leaking them and\n   setting a fixed limit means this is detected without the code having to\n   run for days or weeks leaking handles, however we allow a dynamically-\n   configurable limit set via CONFIG_NUM_OBJECTS if someone really needs to \n   use vast numbers of objects */\n\n#if defined( CONFIG_CONSERVE_MEMORY )\n  #define MAX_NO_OBJECTS\t\t\t128\n#elif defined( CONFIG_NUM_OBJECTS )\n  #if CONFIG_NUM_OBJECTS != 128 && CONFIG_NUM_OBJECTS != 256 && \\\n\t  CONFIG_NUM_OBJECTS != 512 && CONFIG_NUM_OBJECTS != 1024 && \\\n\t  CONFIG_NUM_OBJECTS != 2048 && CONFIG_NUM_OBJECTS != 4096 && \\\n\t  CONFIG_NUM_OBJECTS != 8192 && CONFIG_NUM_OBJECTS != 16384 \n\t#error CONFIG_NUM_OBJECTS must be 128, 256, 512, 1K, 2K, 4K, 8K, or 16K\n  #endif /* CONFIG_NUM_OBJECTS settings */\n  #define MAX_NO_OBJECTS\t\t\tCONFIG_NUM_OBJECTS\n#else\n  #define MAX_NO_OBJECTS\t\t\t1024\n#endif /* Memory-starved environments */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAction Message Types\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Action messages come in two types, direct action messages and mechanism-\n   action messages.  Action messages apply directly to action objects (for \n   example transform a block of data) while mechanism-action messages apply \n   to device objects and involve extra formatting above and beyond the \n   direct action (for example perform PKCS #1 padding and then transform a \n   block of data).\n\n   Each object that processes direct action messages can can have a range of \n   permission settings that control how action messages sent to it are \n   handled.  The most common case is that the action isn't available for \n   this object, ACTION_PERM_NOTAVAIL.  This is an all-zero permission, so \n   the default is deny-all unless the action is explicitly permitted.  The \n   other permissions are ACTION_PERM_NONE, which means that the action is in \n   theory available but has been turned off, ACTION_PERM_NONE_EXTERNAL, \n   which means that the action is only valid if the message is coming from \n   inside cryptlib, and ACTION_PERM_ALL, which means that the action is \n   available for anyone.  In order to set all permissions to a certain value \n   (e.g. NONE_EXTERNAL), we define overall values xxx_ALL that (in \n   combination with the kernel-enforced ratchet) can be used to set all \n   settings to (at most) the given value.\n\n   The order of the action bits is:\n\n\t  hash   sign  encr\n\t\t|\t  |\t\t|\n\txx xx xx xx xx xx\n\t |\t   |\t |\n\tkgen sigch  decr\n\n    x. .x|x. .x|x. .x\tHex digits\n\n   Common settings are 0xCFF (new PKC, all operations), 0x0F (key-loaded \n   conv., all operations), and 0xAA (key-loaded PKC, internal-only \n   operations).\n\n   The kernel enforces a ratchet for these setting that only allows them to \n   be set to a more restrictive value than their existing one.  If a setting \n   starts out as not available on object creation, it can never be enabled. \n   If a setting starts as 'none-external', it can only be set to a straight \n   'none', but never to 'all' */\n\n#define ACTION_PERM_NOTAVAIL\t\t0x00\n#define ACTION_PERM_NONE\t\t\t0x01\n#define ACTION_PERM_NONE_EXTERNAL\t0x02\n#define ACTION_PERM_ALL\t\t\t\t0x03\n\n#define ACTION_PERM_NONE_ALL\t\t\t0x000\n#define ACTION_PERM_NONE_EXTERNAL_ALL\t0xAAA\n#define ACTION_PERM_ALL_MAX\t\t\t\t0xFFF\n\n#define ACTION_PERM_BASE\tMESSAGE_CTX_ENCRYPT\n#define ACTION_PERM_MASK\t0x03\n#define ACTION_PERM_BITS\t2\n#define ACTION_PERM_COUNT\t( MESSAGE_CTX_GENKEY - \\\n\t\t\t\t\t\t\t  MESSAGE_CTX_ENCRYPT + 1 )\n#define ACTION_PERM_LAST\t\\\n\t\t( 1 << ( ( ( ACTION_PERM_COUNT ) * ACTION_PERM_BITS ) + 1 ) )\n#define ACTION_PERM_SHIFT( action ) \\\n\t\t( ( ( action ) - ACTION_PERM_BASE ) * ACTION_PERM_BITS )\n#define MK_ACTION_PERM( action, perm ) \\\n\t\t( ( perm ) << ACTION_PERM_SHIFT( action ) )\n#define MK_ACTION_PERM_NONE_EXTERNAL( action ) \\\n\t\t( ( action ) & ACTION_PERM_NONE_EXTERNAL_ALL )\n\n/* Symbolic defines to allow the action flags to be range-checked alongside \n   all of the other flag types */\n\n#define ACTION_PERM_FLAG_NONE\t\t0x000\n#define ACTION_PERM_FLAG_MAX\t\t0xFFF\n\n/* The mechanism types.  The distinction between the PKCS #1 and raw PKCS #1 \n   mechanisms is somewhat artificial in that they do the same thing, however \n   it's easier for the kernel to perform security checks on parameters if \n   the two are distinct */\n\ntypedef enum {\n\tMECHANISM_NONE,\t\t\t\t/* No mechanism type */\n\n\t/* En/decryption mechanisms, parameter MECHANISM_WRAP_INFO */\n\tMECHANISM_ENC_PKCS1,\t\t/* PKCS #1 en/decrypt */\n\tMECHANISM_ENC_PKCS1_PGP,\t/* PKCS #1 using PGP formatting */\n\tMECHANISM_ENC_PKCS1_RAW,\t/* PKCS #1 returning uninterpreted data */\n\tMECHANISM_ENC_OAEP,\t\t\t/* OAEP en/decrypt */\n\tMECHANISM_ENC_CMS,\t\t\t/* CMS key wrap */\n\n\t/* Signature mechanisms, parameter MECHANISM_SIGN_INFO */\n\tMECHANISM_SIG_PKCS1,\t\t/* PKCS #1 sign */\n\tMECHANISM_SIG_SSL,\t\t\t/* SSL sign with dual hashes */\n\n\t/* Key derivation mechanisms, parameter MECHANISM_DERIVE_INFO.  This is\n\t   also used for the KDF mechanism, which uses PBKDF2 with a single \n\t   iteration */\n\tMECHANISM_DERIVE_PBKDF2,\t/* PBKDF2 / PKCS #5v2 derive */\n\tMECHANISM_DERIVE_PKCS12,\t/* PKCS #12 derive */\n\tMECHANISM_DERIVE_SSL,\t\t/* SSL derive */\n\tMECHANISM_DERIVE_TLS,\t\t/* TLS derive */\n\tMECHANISM_DERIVE_TLS12,\t\t/* TLS 1.2 derive */\n\tMECHANISM_DERIVE_CMP,\t\t/* CMP/Entrust derive */\n\tMECHANISM_DERIVE_PGP,\t\t/* OpenPGP S2K derive */\n\n\t/* Key wrap mechanisms, parameter MECHANISM_WRAP_INFO */\n\tMECHANISM_PRIVATEKEYWRAP,\t/* Private key wrap */\n\tMECHANISM_PRIVATEKEYWRAP_PKCS8,\t/* PKCS #8 private key wrap */\n\tMECHANISM_PRIVATEKEYWRAP_PGP2,\t/* PGP 2.x private key wrap */\n\tMECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD,/* Legacy OpenPGP private key wrap */\n\tMECHANISM_PRIVATEKEYWRAP_OPENPGP,/* OpenPGP private key wrap */\n\n\t/* Self-test mechanisms for the above families, taking the same \n\t   parameters as the mechanism family type */\n\tMECHANISM_SELFTEST_ENC,\t\t/* Test encryption mechanisms */\n\tMECHANISM_SELFTEST_SIG,\t\t/* Test signature mechanisms */\n\tMECHANISM_SELFTEST_DERIVE,\t/* Test derivation mechanisms */\n\tMECHANISM_SELFTEST_KDF,\t\t/* Test KDF mechanisms */\n\tMECHANISM_LAST\t\t\t\t/* Last possible mechanism type */\n\t} MECHANISM_TYPE;\n\n/* A structure to hold information needed by the key export/import mechanism. \n   The key can be passed as raw key data or as a context if tied to hardware \n   that doesn't allow keying material outside the hardware's security \n   perimeter:\n\n\tPKCS #1,\twrappedData = wrapped key\n\tPKCS #1 PGP\tkeyData = -\n\t\t\t\tkeyContext = context containing key\n\t\t\t\twrapContext = wrap/unwrap PKC context\n\t\t\t\tauxContext = CRYPT_UNUSED\n\t\t\t\tauxInfo = CRYPT_UNUSED\n\tPKCS #1\traw\twrappedData = wrapped raw data\n\t\t\t\tkeyData = raw data\n\t\t\t\tkeyContext = CRYPT_UNUSED\n\t\t\t\twrapContext = wrap/unwrap PKC context\n\t\t\t\tauxContext = CRYPT_UNUSED\n\t\t\t\tauxInfo = CRYPT_UNUSED\n\tOAEP\t\twrappedData = wrapped key\n\t\t\t\tkeyData = -\n\t\t\t\tkeyContext = context containing key\n\t\t\t\twrapContext = wrap/unwrap PKC context\n\t\t\t\tauxContext = CRYPT_UNUSED\n\t\t\t\tauxInfo = MGF1 hash algorithm\n\t\t\t\t( auxInfoExt = MGF1 hash parameter )\n\tCMS\t\t\twrappedData = wrapped key\n\t\t\t\tkeyData = -\n\t\t\t\tkeyContext = context containing key\n\t\t\t\twrapContext = wrap/unwrap conventional context\n\t\t\t\tauxContext = CRYPT_UNUSED\n\t\t\t\tauxInfo = CRYPT_UNUSED\n\tPrivate\t\twrappedData = padded encrypted private key components\n\tkey wrap\tkeyData = -\n\t\t\t\tkeyContext = context containing private key\n\t\t\t\twrapContext = wrap/unwrap conventional context\n\t\t\t\tauxContext = CRYPT_UNUSED \n\t\t\t\tauxInfo = CRYPT_UNUSED */\n\ntypedef struct {\n\tBUFFER_OPT_FIXED( wrappedDataLength ) \\\n\t\tvoid *wrappedData;\t\t\t\t\t/* Wrapped key */\n\tint wrappedDataLength;\n\tBUFFER_FIXED( keyDataLength ) \\\n\t\tvoid *keyData;\t\t\t\t\t\t/* Raw key */\n\tint keyDataLength;\n\tVALUE_HANDLE_OPT CRYPT_HANDLE keyContext;/* Context containing raw key */\n\tVALUE_HANDLE CRYPT_HANDLE wrapContext;\t/* Wrap/unwrap context */\n\tVALUE_HANDLE_OPT CRYPT_HANDLE auxContext;/* Auxiliary context */\n\tint auxInfo;\t\t\t\t\t\t\t/* Auxiliary info */\n\t} MECHANISM_WRAP_INFO;\n\n/* A structure to hold information needed by the sign/sig check mechanism: \n\n\tPKCS #1\t\tsignature = signature\n\t\t\t\thashContext = hash to sign\n\t\t\t\tsignContext = signing key\n\n\tSSL\t\t\tsignature = signature\n\t\t\t\thashContext, hashContext2 = dual hashes to sign\n\t\t\t\tsignContext = signing key */\n\ntypedef struct {\n\tBUFFER_OPT_FIXED( signatureLength ) \\\n\t\tvoid *signature;\t\t\t\t\t/* Signature */\n\tint signatureLength;\n\tVALUE_HANDLE CRYPT_CONTEXT hashContext;\t/* Hash context */\n\tVALUE_HANDLE CRYPT_CONTEXT hashContext2;/* Secondary hash context */\n\tVALUE_HANDLE CRYPT_HANDLE signContext;\t/* Signing context */\n\t} MECHANISM_SIGN_INFO;\n\n/* A structure to hold information needed by the key derivation mechanism. \n   This differs from the KDF mechanism that follows in that the \"Derive\" \n   form is used with an iteration count for password-based key derivation \n   while the \"KDF\" form is used without an iteration count for straight key \n   derivation from a master secret.  An exception to this is the SSL/TLS \n   derivation, which uses the resulting data in so many ways that it's not \n   possible to perform a generic context -> context transformation but \n   requires a generalisation in which the raw output data is available: \n\n\tPKCS #5,\tdataOut = key data\n\tCMP, PGP\tdataIn = password\n\t\t\t\thashAlgo = hash algorithm\n\t\t\t\tsalt = salt\n\t\t\t\titerations = iteration count\n\tSSL/TLS/\tdataOut = key data/master secret\n\t\tTLS 1.2\tdataIn = master secret/premaster secret\n\t\t\t\thashAlgo = CRYPT_USE_DEFAULT\n\t\t\t\tsalt = client || server random/server || client random\n\t\t\t\titerations = 1 */\n\ntypedef struct {\n\tBUFFER_OPT_FIXED( dataOutLength ) \\\n\t\tvoid *dataOut;\t\t\t\t\t\t/* Output keying information */\n\tint dataOutLength;\n\tBUFFER_FIXED( dataInLength ) \\\n\t\tconst void *dataIn;\t\t\t\t\t/* Input keying information */\n\tint dataInLength;\n\tVALUE_HANDLE CRYPT_ALGO_TYPE hashAlgo;\t/* Hash algorithm */\n\tint hashParam;\t\t\t\t\t\t\t/* Optional algorithm parameters */\n\tBUFFER_OPT_FIXED( saltLength ) \\\n\t\tconst void *salt;\t\t\t\t\t/* Salt/randomiser */\n\tint saltLength;\n\tint iterations;\t\t\t\t\t\t\t/* Iterations of derivation function */\n\t} MECHANISM_DERIVE_INFO;\n\n/* A structure to hold information needed by the KDF mechanism:\n\n\tCMS AuthEnc\tkeyContext = encryption/MAC context \n\t\t\t\tmasterKeyContext = context containing master secret \n\t\t\t\thashAlgo = hash algorithm\n\t\t\t\tsalt = salt */\n\ntypedef struct {\n\tVALUE_HANDLE CRYPT_HANDLE keyContext;\t/* Context containing derived key */\n\tVALUE_HANDLE CRYPT_HANDLE masterKeyContext;/* Context containing master key */\n\tVALUE_HANDLE CRYPT_ALGO_TYPE hashAlgo;\t/* Hash algorithm */\n\tint hashParam;\t\t\t\t\t\t\t/* Optional algorithm parameters */\n\tBUFFER_OPT_FIXED( saltLength ) \\\n\t\tconst void *salt;\t\t\t\t\t/* Salt/randomiser */\n\tint saltLength;\n\t} MECHANISM_KDF_INFO;\n\n/* Macros to make it easier to work with the mechanism info types.  The \n   shortened name forms in the macro args are necessary to avoid clashes with \n   the struct members.  The long lines are necessary because older Borland \n   compilers can't handle line breaks at this point in a macro definition */\n\n#define clearMechanismInfo( mechanismInfo ) \\\n\t\tmemset( mechanismInfo, 0, sizeof( *mechanismInfo ) )\n\n#define setMechanismWrapInfo( mechanismInfo, wrapped, wrappedLen, key, keyLen, keyCtx, wrapCtx ) \\\n\t\t{ \\\n\t\tmemset( mechanismInfo, 0, sizeof( MECHANISM_WRAP_INFO ) ); \\\n\t\t( mechanismInfo )->wrappedData = ( wrapped ); \\\n\t\t( mechanismInfo )->wrappedDataLength = ( wrappedLen ); \\\n\t\t( mechanismInfo )->keyData = ( key ); \\\n\t\t( mechanismInfo )->keyDataLength = ( keyLen ); \\\n\t\t( mechanismInfo )->keyContext = ( keyCtx ); \\\n\t\t( mechanismInfo )->wrapContext = ( wrapCtx ); \\\n\t\t( mechanismInfo )->auxContext = \\\n\t\t\t( mechanismInfo )->auxInfo = CRYPT_UNUSED; \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( mechanismInfo )->keyContext ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n#define setMechanismWrapInfoEx( mechanismInfo, wrapped, wrappedLen, key, keyLen, keyCtx, wrapCtx, auxCtx, auxInf ) \\\n\t\t{ \\\n\t\tmemset( mechanismInfo, 0, sizeof( MECHANISM_WRAP_INFO ) ); \\\n\t\t( mechanismInfo )->wrappedData = ( wrapped ); \\\n\t\t( mechanismInfo )->wrappedDataLength = ( wrappedLen ); \\\n\t\t( mechanismInfo )->keyData = ( key ); \\\n\t\t( mechanismInfo )->keyDataLength = ( keyLen ); \\\n\t\t( mechanismInfo )->keyContext = ( keyCtx ); \\\n\t\t( mechanismInfo )->wrapContext = ( wrapCtx ); \\\n\t\t( mechanismInfo )->auxContext = ( auxCtx ); \\\n\t\t( mechanismInfo )->auxInfo = ( auxInf ); \\\n\t\t}\n\n#define setMechanismSignInfo( mechanismInfo, sig, sigLen, hashCtx, hashCtx2, signCtx ) \\\n\t\t{ \\\n\t\tmemset( mechanismInfo, 0, sizeof( MECHANISM_SIGN_INFO ) ); \\\n\t\t( mechanismInfo )->signature = ( sig ); \\\n\t\t( mechanismInfo )->signatureLength = ( sigLen ); \\\n\t\t( mechanismInfo )->hashContext = ( hashCtx ); \\\n\t\t( mechanismInfo )->hashContext2 = ( hashCtx2 ); \\\n\t\t( mechanismInfo )->signContext = ( signCtx ); \\\n\t\t}\n\n#define setMechanismDeriveInfo( mechanismInfo, out, outLen, in, inLen, hAlgo, slt, sltLen, iters ) \\\n\t\t{ \\\n\t\tmemset( mechanismInfo, 0, sizeof( MECHANISM_DERIVE_INFO ) ); \\\n\t\t( mechanismInfo )->dataOut = ( out ); \\\n\t\t( mechanismInfo )->dataOutLength = ( outLen ); \\\n\t\t( mechanismInfo )->dataIn = ( in ); \\\n\t\t( mechanismInfo )->dataInLength = ( inLen ); \\\n\t\t( mechanismInfo )->hashAlgo = ( hAlgo ); \\\n\t\t( mechanismInfo )->salt = ( slt ); \\\n\t\t( mechanismInfo )->saltLength = ( sltLen ); \\\n\t\t( mechanismInfo )->iterations = ( iters ); \\\n\t\t}\n\n#define setMechanismKDFInfo( mechanismInfo, keyCtx, masterKeyCtx, hAlgo, slt, sltLen ) \\\n\t\t{ \\\n\t\tmemset( mechanismInfo, 0, sizeof( MECHANISM_KDF_INFO ) ); \\\n\t\t( mechanismInfo )->keyContext = ( keyCtx ); \\\n\t\t( mechanismInfo )->masterKeyContext = ( masterKeyCtx ); \\\n\t\t( mechanismInfo )->hashAlgo = ( hAlgo ); \\\n\t\t( mechanismInfo )->salt = ( slt ); \\\n\t\t( mechanismInfo )->saltLength = ( sltLen ); \\\n\t\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc Message Types\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Beside the general value+length and mechanism messages, we also have a \n   number of special-purposes messages that require their own parameter \n   data structures.  These are:\n\n   Create object messages, used to create objects via a device, either \n   directly or indirectly by instantiating the object from encoded data (for \n   example a certificate object from a certificate).  Usually the device is \n   the system object, but it can also be used to create contexts in hardware \n   devices.  In addition to the creation parameters we also pass in the \n   owner's user object to be stored with the object data for use when \n   needed.\n   \n   For the create-indirect certificate case, the arguments are:\n\n\targ1\t\tCertificate object type.\n\targ2\t\tOptional certificate object ID type, used as an indicator of \n\t\t\t\tthe primary object in a collection like a certificate chain \n\t\t\t\tor set.\n\targ3\t\tOptional KEYMGMT_FLAGs.\n\tstrArg1\t\tCertificate object data.\n\tstrArg2\t\tOptional certificate object ID (see arg2) */\n\ntypedef struct {\n\tVALUE_HANDLE CRYPT_HANDLE cryptHandle;\t/* Handle to created object */\n\tVALUE_HANDLE CRYPT_USER cryptOwner;\t\t/* New object's owner */\n\tint arg1, arg2, arg3;\t\t\t\t\t/* Integer args */\n\tBUFFER_OPT_FIXED( strArgLen1 ) \\\n\t\tconst void *strArg1;\n\tBUFFER_OPT_FIXED( strArgLen2 ) \\\n\t\tconst void *strArg2;\t\t\t\t/* String args */\n\tVALUE_INT int strArgLen1;\n\tVALUE_INT_SHORT int strArgLen2;\n\t} MESSAGE_CREATEOBJECT_INFO;\n\n#define setMessageCreateObjectInfo( createObjectInfo, a1 ) \\\n\t\t{ \\\n\t\tmemset( createObjectInfo, 0, sizeof( MESSAGE_CREATEOBJECT_INFO ) ); \\\n\t\t( createObjectInfo )->cryptHandle = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->cryptOwner = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->arg1 = ( a1 ); \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( createObjectInfo )->cryptHandle ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n#define setMessageCreateObjectIndirectInfo( createObjectInfo, data, dataLen, type ) \\\n\t\t{ \\\n\t\tmemset( createObjectInfo, 0, sizeof( MESSAGE_CREATEOBJECT_INFO ) ); \\\n\t\t( createObjectInfo )->cryptHandle = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->cryptOwner = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->strArg1 = ( data ); \\\n\t\t( createObjectInfo )->strArgLen1 = ( dataLen ); \\\n\t\t( createObjectInfo )->arg1 = ( type ); \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( createObjectInfo )->cryptHandle ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n#define setMessageCreateObjectIndirectInfoEx( createObjectInfo, data, dataLen, type, options ) \\\n\t\t{ \\\n\t\tmemset( createObjectInfo, 0, sizeof( MESSAGE_CREATEOBJECT_INFO ) ); \\\n\t\t( createObjectInfo )->cryptHandle = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->cryptOwner = CRYPT_ERROR; \\\n\t\t( createObjectInfo )->strArg1 = ( data ); \\\n\t\t( createObjectInfo )->strArgLen1 = ( dataLen ); \\\n\t\t( createObjectInfo )->arg1 = ( type ); \\\n\t\t( createObjectInfo )->arg3 = ( options ); \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( createObjectInfo )->cryptHandle ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n#define updateMessageCreateObjectIndirectInfo( createObjectInfo, idType, id, idLength ) \\\n\t\t{ \\\n\t\t( createObjectInfo )->arg2 = ( idType ); \\\n\t\t( createObjectInfo )->strArg2 = ( id ); \\\n\t\t( createObjectInfo )->strArgLen2 = ( idLength ); \\\n\t\t}\n\n/* Key management messages, used to set, get and delete keys.  The item type, \n   keyIDtype, keyID, and keyIDlength are mandatory, the aux.info depends on \n   the type of message (optional password for private key get/set, state \n   information for get next cert, null otherwise), and the flags are \n   generally only required where the keyset can hold multiple types of keys \n   (for example a crypto device acting as a keyset, or a PKCS #15 token).\n\n   An itemType of KEYMGMT_ITEM_PUBLICKEY is somewhat more general than its \n   name implies in that keysets/devices that store private key information \n   alongside public-key data may delete both types of items if asked to \n   delete a KEYMGMT_ITEM_PUBLICKEY since the two items are (implicitly) \n   connected.\n\n   An itemType of KEYMGMT_ITEM_REQUEST is distinct from the subtype \n   KEYMGMT_ITEM_REVREQUEST because the former is for certification requests \n   while the latter is for revocation requests, the distinction is made \n   because some protocols only allow certification but not revocation \n   requests and we want to trap these as soon as possible rather than some \n   way down the road when error reporting becomes a lot more nonspecific.\n\n   An itemType of KEYMGMT_ITEM_KEYMETADATA is a KEYMGMT_ITEM_PRIVATEKEY with \n   the context passed in being a dummy context with actual keying data held \n   in a crypto device.  What's stored in the keyset is purely the \n   surrounding metadata like labels, dates, and ID information.  This is \n   distinct from a KEYMGMT_ITEM_PRIVATEKEY both to allow for better checking \n   by the kernel, since a KEYMGMT_ITEM_KEYMETADATA object may not be in the \n   high state yet when it's used and doens't need a password like a \n   KEYMGMT_ITEM_PRIVATEKEY does.  In addition keeping the types distinct is \n   a safety feature since otherwise we'd need to allow a special-case \n   KEYMGMT_ITEM_PRIVATEKEY store without a password, which is just asking \n   for trouble.  Note that KEYMGMT_ITEM_PRIVATEKEY items are write-only, for \n   reads they're treated the same as KEYMGMT_ITEM_PRIVATEKEY except that a \n   dummy context is created.\n\n   In addition to the flags that are used to handle various special-case \n   read accesses, we can also specify a usage preference (e.g. \n   confidentiality vs.signature) for cases where we may have multiple keys \n   with the same keyID that differ only in required usage */\n\ntypedef enum {\n\tKEYMGMT_ITEM_NONE,\t\t\t/* No item type */\n\tKEYMGMT_ITEM_PUBLICKEY,\t\t/* Access public key */\n\tKEYMGMT_ITEM_PRIVATEKEY,\t/* Access private key */\n\tKEYMGMT_ITEM_SECRETKEY,\t\t/* Access secret key */\n\tKEYMGMT_ITEM_REQUEST,\t\t/* Access cert request */\n\tKEYMGMT_ITEM_REVREQUEST,\t/* Access cert revocation request */\n\tKEYMGMT_ITEM_PKIUSER,\t\t/* Access PKI user info */\n\tKEYMGMT_ITEM_REVOCATIONINFO,/* Access revocation info/CRL */\n\tKEYMGMT_ITEM_KEYMETADATA,\t/* Access key metadata for dummy ctx.*/\n\tKEYMGMT_ITEM_DATA,\t\t\t/* Other data (for PKCS #15 tokens) */\n\tKEYMGMT_ITEM_LAST\t\t\t/* Last possible item type */\n\t} KEYMGMT_ITEM_TYPE;\n\n#define KEYMGMT_FLAG_NONE\t\t\t0x0000\t/* No flag type */\n#define KEYMGMT_FLAG_CHECK_ONLY\t\t0x0001\t/* Perform existence check only */\n#define KEYMGMT_FLAG_LABEL_ONLY\t\t0x0002\t/* Get key label only */\n#define KEYMGMT_FLAG_UPDATE\t\t\t0x0004\t/* Update existing (allow dups) */\n#define KEYMGMT_FLAG_DATAONLY_CERT\t0x0008\t/* Create data-only certificate */\n#define KEYMGMT_FLAG_CERT_AS_CERTCHAIN 0x010 /* Force creation of cert.chain\n\t\t\t\t\t\t\t\t\t\t\t\teven if single cert.present */\n#define KEYMGMT_FLAG_USAGE_CRYPT\t0x0020\t/* Prefer encryption key */\n#define KEYMGMT_FLAG_USAGE_SIGN\t\t0x0040\t/* Prefer signature key */\n#define KEYMGMT_FLAG_GETISSUER\t\t0x0080\t/* Get issuing PKI user for cert */\n#define KEYMGMT_FLAG_INITIALOP\t\t0x0100\t/* Initial cert issue operation */\n#define KEYMGMT_FLAG_MAX\t\t\t0x01FF\t/* Maximum possible flag value */\n\n#define KEYMGMT_MASK_USAGEOPTIONS\t( KEYMGMT_FLAG_USAGE_CRYPT | \\\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_SIGN )\n#define KEYMGMT_MASK_CERTOPTIONS\t( KEYMGMT_FLAG_DATAONLY_CERT | \\\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_CERT_AS_CERTCHAIN | \\\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_CRYPT | \\\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_SIGN )\ntypedef struct {\n\tVALUE_HANDLE CRYPT_HANDLE cryptHandle;\t/* Returned key */\n\tVALUE_HANDLE CRYPT_KEYID_TYPE keyIDtype;/* Key ID type */\n\tBUFFER_OPT_FIXED( keyIDlength ) \\\n\t\tconst void *keyID;\t\t\t\t\t/* Key ID */\n\tVALUE_INT_SHORT int keyIDlength;\n\tBUFFER_OPT_FIXED( auxInfoLength ) \\\n\t\tvoid *auxInfo;\t\t\t\t\t\t/* Aux.info (e.g.password for private key) */\n\tVALUE_INT_SHORT int auxInfoLength;\n\tint flags;\t\t\t\t\t\t\t\t/* Access options */\n\t} MESSAGE_KEYMGMT_INFO;\n\n#define setMessageKeymgmtInfo( keymgmtInfo, idType, id, idLength, aux, auxLen, keyFlags ) \\\n\t\t{ \\\n\t\t( keymgmtInfo )->cryptHandle = CRYPT_ERROR; \\\n\t\t( keymgmtInfo )->keyIDtype = ( idType ); \\\n\t\t( keymgmtInfo )->keyID = ( id ); \\\n\t\t( keymgmtInfo )->keyIDlength = ( idLength ); \\\n\t\t( keymgmtInfo )->auxInfo = ( aux ); \\\n\t\t( keymgmtInfo )->auxInfoLength = ( auxLen ); \\\n\t\t( keymgmtInfo )->flags = ( keyFlags ); \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( keymgmtInfo )->cryptHandle ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n/* Cert management messages used to handle CA operations.  All fields are \n   mandatory, however the cryptCert and request fields may be set to \n   CRYPT_UNUSED to indicate 'don't care' conditions */\n\ntypedef struct {\n\tCRYPT_CERTIFICATE cryptCert;\t/* Returned cert */\n\tCRYPT_CONTEXT caKey;\t\t\t/* CA key to sign item */\n\tCRYPT_CERTIFICATE request;\t\t/* Request for operation */\n\t} MESSAGE_CERTMGMT_INFO;\n\n#define setMessageCertMgmtInfo( certMgmtInfo, mgmtCaKey, mgmtRequest ) \\\n\t\t{ \\\n\t\t( certMgmtInfo )->cryptCert = CRYPT_ERROR; \\\n\t\t( certMgmtInfo )->caKey = ( mgmtCaKey ); \\\n\t\t( certMgmtInfo )->request = ( mgmtRequest ); \\\n\t\tANALYSER_HINT( isHandleRangeValid( ( certMgmtInfo )->cryptCert ) ); \\\n\t\t}\t\t\t   /* Hack for unimplemented VALUE() op.in VS 2013 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* cryptlib initialisation/shutdown functions */\n\nCHECK_RETVAL \\\nint initCryptlib( void );\nCHECK_RETVAL \\\nint endCryptlib( void );\n#if defined( __PALMOS__ ) || defined( __WIN32__ ) || defined( __WINCE__ )\n  void preInit( void );\n  void postShutdown( void );\n#endif /* Systems with OS-specific pre-init/post-shutdown facilities */\n\n/* Prototype for an object's message-handling function */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\ntypedef int ( *MESSAGE_FUNCTION )( INOUT void *objectInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ENUM( MESSAGE ) \\\n\t\t\t\t\t\t\t\t\t\tconst MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t   void *messageDataPtr,\n\t\t\t\t\t\t\t\t   const int messageValue );\n\n/* If the message-handler can unlock an object to allow other threads \n   access, it has to be able to inform the kernel of this.  The following \n   structure and macros allow this information to be passed back to the \n   kernel via the message function's objectInfoPtr */\n\ntypedef struct {\n\tvoid *objectInfoPtr;\t\t\t\t\t/* Original objectInfoPtr */\n\tBOOLEAN isUnlocked;\t\t\t\t\t\t/* Whether obj.is now unlocked */\n\t} MESSAGE_FUNCTION_EXTINFO;\n\n#define initMessageExtInfo( messageExtInfo, objectInfo ) \\\n\t\t{ \\\n\t\tmemset( messageExtInfo, 0, sizeof( MESSAGE_FUNCTION_EXTINFO ) ); \\\n\t\t( messageExtInfo )->objectInfoPtr = objectInfo; \\\n\t\t}\n#define setMessageObjectLocked( messageExtInfo ) \\\n\t\t( messageExtInfo )->isUnlocked = FALSE\n#define setMessageObjectUnlocked( messageExtInfo ) \\\n\t\t( messageExtInfo )->isUnlocked = TRUE\n#define isMessageObjectUnlocked( messageExtInfo ) \\\n\t\t( ( messageExtInfo )->isUnlocked )\n\n/* Object management functions.  A dummy object is one that exists but \n   doesn't have the capabilities of the actual object, for example an \n   encryption context that just maps to underlying crypto hardware.  This \n   doesn't affect krnlCreateObject(), but is used by the object-type-\n   specific routines that decorate the results of krnlCreateObject() with \n   object-specific extras.\n   \n   Since krnlSendMessage() is the universal entry-point for the kernel API,\n   it's heavily annotated to provide compile-time warnings of issues.  Since\n   this is checked anyway at runtime, it's not clear whether this is really\n   useful or just a gratuitous means of exercising the static analyser's \n   capabilities... */\n\n#define CREATEOBJECT_FLAG_NONE\t\t0x00\t/* No create-object flags */\n#define CREATEOBJECT_FLAG_SECUREMALLOC \\\n\t\t\t\t\t\t\t\t\t0x01\t/* Use krnlMemAlloc() to alloc.*/\n#define CREATEOBJECT_FLAG_DUMMY\t\t0x02\t/* Dummy obj.used as placeholder */\n#define CREATEOBJECT_FLAG_PERSISTENT 0x04\t/* Obj.backed by key in device */\n#define CREATEOBJECT_FLAG_MAX\t\t0x0F\t/* Maximum possible flag value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \\\nint krnlCreateObject( OUT_HANDLE_OPT int *objectHandle,\n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( objectDataSize ) void **objectDataPtr, \n\t\t\t\t\t  IN_LENGTH_SHORT const int objectDataSize,\n\t\t\t\t\t  IN_ENUM( OBJECT_TYPE ) const OBJECT_TYPE type, \n\t\t\t\t\t  IN_ENUM( SUBTYPE ) const OBJECT_SUBTYPE subType,\n\t\t\t\t\t  IN_FLAGS_Z( CREATEOBJECT ) const int createObjectFlags, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_USER owner,\n\t\t\t\t\t  IN_FLAGS_Z( ACTION_PERM ) const int actionFlags,\n\t\t\t\t\t  IN MESSAGE_FUNCTION messageFunction );\nRETVAL \\\nPARAMCHECK_MESSAGE( MESSAGE_DESTROY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_INCREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DECREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETDEPENDENT, OUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETDEPENDENT, IN, IN ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CLONE, PARAM_NULL, IN_HANDLE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE, OUT, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE_S, INOUT, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE, IN, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE_S, IN, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DELETEATTRIBUTE, PARAM_NULL, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_COMPARE, IN, IN_ENUM( MESSAGE_COMPARE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CHECK, PARAM_NULL, IN_ENUM( MESSAGE_CHECK ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SELFTEST, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CHANGENOTIFY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_ENCRYPT, INOUT, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_DECRYPT, INOUT, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_SIGN, IN, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_SIGCHECK, IN, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_HASH, IN, IN_LENGTH_Z ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_GENKEY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_GENIV, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_SIGN, PARAM_NULL, IN_HANDLE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_SIGCHECK, PARAM_NULL, IN_HANDLE_OPT ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_EXPORT, INOUT, IN_ENUM( CRYPT_CERTFORMAT ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_QUERYCAPABILITY, OUT, IN_ALGO ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_EXPORT, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_IMPORT, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_SIGN, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_SIGCHECK, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_DERIVE, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_KDF, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT_INDIRECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_ENV_PUSHDATA, INOUT, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_ENV_POPDATA, INOUT, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_SETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_DELETEKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETFIRSTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETNEXTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_CERTMGMT, INOUT, IN_ENUM( CRYPT_CERTACTION ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_USER_USERMGMT, INOUT, IN_ENUM( MESSAGE_USERMGMT ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_USER_TRUSTMGMT, IN, IN_ENUM( MESSAGE_TRUSTMGMT ) ) \\\n\t\t\t\t\t/* Actually INOUT for MESSAGE_TRUSTMGMT_GETISSUER, but too \\\n\t\t\t\t\t   complex to annotate */ \\\nint krnlSendMessage( IN_HANDLE const int objectHandle, \n\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t void *messageDataPtr, const int messageValue );\n\n/* Since some messages contain no data but act only as notifiers, we define \n   the following macro to make using them less messy */\n\n#define krnlSendNotifier( handle, message ) \\\n\t\tkrnlSendMessage( handle, message, NULL, 0 )\n\n/* In some rare cases we have to access an object directly without sending \n   it a message.  This happens either with certs where we're already \n   processing a message for one cert and need to access internal data in \n   another cert, when we're working with a crypto device tied to a context \n   where we need access to both context and device internals at the same \n   time, or when we're updating config data in a user object.  This type of \n   access is handled by the following function, which also explicitly \n   disallows any access types apart from the three described here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint krnlAcquireObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t   IN_ENUM( OBJECT_TYPE ) const OBJECT_TYPE type,\n\t\t\t\t\t   OUT_PTR_COND void **objectPtr, \n\t\t\t\t\t   IN_ERROR const int errorCode );\nRETVAL \\\nint krnlReleaseObject( IN_HANDLE const int objectHandle );\n\n/* In even rarer cases, we have to allow a second thread access to an object \n   when another thread has it locked, providing a (somewhat crude) mechanism \n   for making kernel calls interruptible and resumable.  This only occurs in \n   two cases, for the system object when a background polling thread is \n   adding entropy to the system device and for the user object when we're \n   saving configuration data to persistent storage (we temporarily unlock it \n   to allow other threads access, since the act of writing the marshalled \n   data to storage doesn't require the user object) */\n\nRETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint krnlSuspendObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t   OUT_INT_Z int *refCount );\nCHECK_RETVAL \\\nint krnlResumeObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t  IN_INT_Z const int refCount );\n\n/* When the kernel is closing down, any cryptlib-internal threads should \n   exit as quickly as possible.  For threads coming in from the outside this \n   happens automatically because any message it tries to send fails, but for \n   internal worker threads (for example the async driver-binding thread or \n   randomness polling threads) that don't perform many kernel calls, the \n   thread has to periodically check whether the kernel is still active.  The \n   following function is used to indicate whether the kernel is shutting \n   down */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN krnlIsExiting( void );\n\n/* Semaphores and mutexes */\n\ntypedef enum {\n\tSEMAPHORE_NONE,\t\t\t\t\t/* No semaphore */\n\tSEMAPHORE_DRIVERBIND,\t\t\t/* Async driver bind */\n\tSEMAPHORE_LAST\t\t\t\t\t/* Last possible semaphore */\n\t} SEMAPHORE_TYPE;\n\ntypedef enum {\n\tMUTEX_NONE,\t\t\t\t\t\t/* No mutex */\n\tMUTEX_RANDOM,\t\t\t\t\t/* Randomness subsystem */\n#ifdef USE_SESSIONS\n\tMUTEX_SCOREBOARD,\t\t\t\t/* Session scoreboard */\n\tMUTEX_SOCKETPOOL,\t\t\t\t/* Network socket pool */\n\tMUTEX_CRYPTODELAY,\t\t\t\t/* Crypto failure delay */\n#endif /* USE_SESSIONS */\n\tMUTEX_LAST\t\t\t\t\t\t/* Last possible mutex */\n\t} MUTEX_TYPE;\n\n/* Execute a function in a background thread.  This takes a pointer to the \n   function to execute in the background thread, a block of memory for \n   thread state storage, a set of parameters to pass to the thread function, \n   and an optional semaphore ID to set once the thread is started.  A \n   function is run via a background thread as follows:\n\n\tvoid threadFunction( const THREAD_PARAMS *threadParams )\n\t\t{\n\t\t}\n\n\tkrnlDispatchThread( threadFunction, &threadState, ptrParam, intParam, \n\t\t\t\t\t\tSEMAPHORE_ID );\n\n   Note that the thread parameters must be held in static storage because \n   the caller's stack frame may have long since disappeared before the \n   thread gets to access them */\n\nstruct TF;\n\ntypedef void ( *THREAD_FUNCTION )( const struct TF *threadParams );\n\ntypedef BYTE THREAD_STATE[ 48 ];\n\ntypedef struct TF {\n\tvoid *ptrParam;\t\t\t\t\t/* Pointer parameter */\n\tint intParam;\t\t\t\t\t/* Integer parameter */\n\t} THREAD_PARAMS;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlDispatchThread( THREAD_FUNCTION threadFunction,\n\t\t\t\t\t\tTHREAD_STATE threadState, void *ptrParam, \n\t\t\t\t\t\tconst int intParam, const SEMAPHORE_TYPE semaphore );\n\n/* Wait on a semaphore, enter and exit a mutex */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN krnlWaitSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore );\nCHECK_RETVAL \\\nint krnlEnterMutex( IN_ENUM( MUTEX ) const MUTEX_TYPE mutex );\nvoid krnlExitMutex( IN_ENUM( MUTEX ) const MUTEX_TYPE mutex );\n\n/* Delay by a given amount of milliseconds */\n\nCHECK_RETVAL \\\nint krnlWait( IN_RANGE( 1, 10000 ) const int milliSeconds );\n\n/* Secure memory handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlMemalloc( OUT_BUFFER_ALLOC_OPT( size ) void **pointer, \n\t\t\t\t  IN_LENGTH int size );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlMemfree( INOUT_PTR void **pointer );\n\n#ifdef NEED_ENUMFIX\n  #undef OBJECT_TYPE_LAST\n  #undef MESSAGE_COMPARE_LAST\n  #undef MESSAGE_CHECK_LAST\n  #undef MESSAGE_CHANGENOTIFY_LAST\n  #undef MECHANISM_LAST\n  #undef KEYMGMT_ITEM_LAST\n  #undef SEMAPHORE_LAST\n  #undef MUTEX_LAST\n#endif /* NEED_ENUMFIX */\n#endif /* _CRYPTKRN_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cryptlib.asn",
    "content": "-/ This specification makes one slight deviation from standard ASN.1 syntax\n   to overcome an annoyance in ASN.1 which requires a separate -- at the\n   start of each and every line of comment.  Instead, this specification uses\n   -//- comment delimiters (which work like C's /**/) in place of standard\n   ASN.1 delimiters /-\n\ncryptlib DEFINITIONS ::=\nBEGIN\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\tPKCS #7 Data Formats\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ There are several variants of the PKCS #7/S/MIME/CMS format which gradually\n   get more flexible (but not necessarily better) over time.  The initial\n   format was PKCS #7 1.5 and earlier, 1.6 was a quick update which changed a\n   number of SETs to SEQUENCEs (which don't require sorting of the encoded\n   components), this doesn't appear to have been used by anything.  S/MIME 3/\n   CMS was an extended form of S/MIME 2 which fiddled with some of the inner\n   fields but was mostly the same as PKCS #7 1.5.  1.5 is a significant\n   improvement on most of its successors /-\n\nContentInfo ::= SEQUENCE {\n\tcontentType\t\t\tOBJECT IDENTIFIER,\n\tcontent\t\t\t[0]\tEXPLICIT ANY DEFINED BY contentType OPTIONAL\n\t}\n\n-/ Raw data /-\n\nData ::= OCTET STRING\t\t\t\t\t\t-- PKCS #7 1\n\n-/ Authenticated data: Digested, signed, MAC'd data /-\n\nDigestedData ::= SEQUENCE {\t\t\t\t\t-- PKCS #7 5\n\tversion\t\t\t\tINTEGER (0),\t\t-- PKCS #7 v1.5\n\tdigestAlgorithm\t\tAlgorithmIdentifier,-- v=2 for non id-Data\n\tencapContentInfo\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontent\t\t[0]\tEXPLICIT OCTET STRING\n\t\t},\n\tdigest\t\t\t\tOCTET STRING\n\t}\n\nSignedData ::= SEQUENCE {\t\t\t\t\t-- PKCS #7 2\n\tversion\t\t\t\tINTEGER (1),\t\t-- PKCS #7 v1.5\n\tdigestAlgorithms\tSET OF AlgorithmIdentifier,\n\tencapContentInfo\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontent\t\t[0]\tEXPLICIT OCTET STRING\n\t\t}\n\tcertificates\t[0]\tSET OF Certificate,\n\tsignerInfos\t\t\tSET OF SignerInfo\n\t}\n\nAuthenticatedData ::= SEQUENCE {\t\t\t-- PKCS #9 16 1 2\n\tversion\t\t\t\tINTEGER (0),\t\t-- S/MIME v3\n\trecipientInfos\t\tSET OF RecipientInfo,\n\tmacAlgorithm\t\tAlgorithmIdentifier,\n\tencapContentInfo\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontent\t\t[0]\tEXPLICIT OCTET STRING\n\t\t}\n\tauthAttrs\t\t[1]\tSET OF Attribute OPTIONAL,\n\tmac\t\t\t\t\tOCTET STRING\n\tunauthAttrs\t\t[2]\tSET OF Attribute OPTIONAL\n\t}\n\n-/ Encrypted data: Raw encrypted, enveloped /-\n\nEncryptedData ::= SEQUENCE {\t\t\t\t-- PKCS #7 6\n\tversion\t\t\t\tINTEGER (0),\t\t-- PKCS #7 v1.5\n\tencrContentInfo\t\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontentEncrAlgo\tAlgorithmIdentifier,\n\t\tcontent\t\t[0]\tOCTET STRING\n\t\t}\n\t}\n\nEnvelopedData ::= SEQUENCE {\t\t\t\t-- PKCS #7 3\n\tversion\t\t\t\tINTEGER (0),\t\t-- PKCS #7 v1.5, v=2 for origInfo\n\trecipientInfos\t\tSET OF RecipientInfo,\n\tencrContentInfo\t\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontentEncrAlgo\tAlgorithmIdentifier,\n\t\tcontent\t\t[0]\tOCTET STRING\n\t\t},\n\tunauthAttrs\t\t[1]\tSET OF Attribute OPTIONAL\n\t}\n\n-/ Combined encrypted + authenticated data /-\n\n AuthEnvelopedData ::= SEQUENCE {\t\t\t-- PKCS #9 16 1 23\n \tversion\t\t\t\tINTEGER (0),\t\t-- CMS\n\trecipientInfos\t\tSET OF RecipientInfo,\n\tencrContentInfo\t\tSEQUENCE {\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data/Sig/Encr/Env,\n\t\tcontentEncrAlgo\tAlgorithmIdentifier,\n\t\tcontent\t\t[0]\tOCTET STRING\n\t\t},\n\tauthAttrs\t\t[1]\tSET OF Attribute OPTIONAL,\n\tmac\t\t\t\t\tOCTET STRING\n\tunauthAttrs\t\t[2]\tSET OF Attribute OPTIONAL\n\t}\n\n-/ Attributes.  Contrast these with certificate attributes, identified as\n   Extensions, which use hole encodings rather than proper ASN.1\n   structures /-\n\nAttribute ::= SEQUENCE {\n\ttype\t\t\tOBJECT IDENTIFIER,\n\tvalue\t\t\tSET OF ANY\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\tKey Management\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ The parameters used to derive the conventional encryption key from the\n   user key.  Usually we use the key directly, but sometimes it may have\n   been derived from a longer user key, which is encoded in this record /-\n\nPBKDF2 ::= SEQUENCE {\t\t\t\t\t\t-- PKCS #5v2 key setup parameters\n\talgorithm\t\tAlgorithmIdentifier (pkcs-5 12),\n\tparams\t\t\tSEQUENCE {\n\t\tsalt\t\tOCTET STRING,\t\t\t-- Key setup salt\n\t\titerationCount\t\t\t\t\t\t-- Key setup iterations\n\t\t\t\t\tINTEGER (1..MAX),\n\t\t}\n\t}\n\n-/ CMS key transport information /-\n\nKeyTransRecipientInfo ::= SEQUENCE {\t\t-- CMS - S/MIME\n\tversion\t\t\tINTEGER (0),\t\t\t-- CMS\n\tissuerAndSerial\tIssuerAndSerialNumber,\t-- Encrypting certificate\n\talgorithm\t\tAlgorithmIdentifier,\t-- Encryption algorithm\n\tencryptedKey\tOCTET STRING\t\t\t-- Encryped key\n\t}\nKeyTransRecipientInfo ::= SEQUENCE {\t\t-- CMS - cryptlib\n\tversion\t\t\tINTEGER (2),\t\t\t-- CMS\n\tkeyID\t\t[0]\tSubjectKeyIdentifier,\t-- Key ID of encrypting key\n\talgorithm\t\tAlgorithmIdentifier,\t-- Encryption algorithm\n\tencryptedKey\tOCTET STRING\t\t\t-- Encrypted key\n\t}\n\n-/ CMS key agreement information, which is officially called\n   KeyAgreeRecipientInfo but in order for it to make sense it really needs\n   to be named FortezzaRecipientInfo /-\n\nFortezzaRecipientInfo ::= SEQUENCE {\t\t-- CMS - S/MIME\n\tversion\t\t\tINTEGER (3),\t\t\t-- CMS\n\toriginator\t[0]\tEXPLICIT [ 0 ] SubjectKeyIdentifier,-- Originator pub.key\n\tukm\t\t\t[1]\tEXPLICIT OCTET STRING,\t-- Nonce, Ra\n\talgorithm\t\tAlgorithmIdentifier,\t-- Fortezza key wrap OID\n\trecipientKeys\tSEQUENCE OF SEQUENCE {\n\t\trKeyId\t[0]\tSEQUENCE { SubjectKeyIdentifier }, -- Recip.pubk\n\t\tencryptedKey OCTET STRING\t\t\t-- Encr.key info, TEK( MEK )\n\t\t}\n\t}\n\n-/ CMS conventional key transport information.  This structure is somewhat\n   misnamed since it's really just a kludge to work with pre-distributed\n   shared RC2 or 3DES keys for S/MIME-based mailing lists and not a general-\n   purpose KEK object, however by using the PWRI AlgorithmIdentifier for\n   KEKRI we can turn it into a general-purpose key transport mechanism /-\n\nKEKRecipientInfo ::= SEQUENCE {\n\tversion\t\t\tINTEGER (4),\t\t\t-- CMS\n\tkekid\t\t\tSEQUENCE {\n\t\tkeyIdent\tOCTET STRING\t\t\t-- Magic ID for KEK\n\t\t},\n\tkeyEncAlgo\t\tAlgorithmIdentifier,\t-- Key wrap algorithm\n\tencryptedKey\tOCTET STRING\t\t\t-- Encrypted key\n\t}\n\n-/ CMS password-based key transport information.  This is also misnamed since\n   it's actually general-purpose and does what KEKRecipientInfo should do /-\n\nPasswordRecipientInfo ::= SEQUENCE {\n\tversion\t\t\tINTEGER (0),\t\t\t-- CMS\n\tkeyDerivationAlgorithm\t\t\t\t\t-- KEK derivation algorithm,\n\t\t\t\t[0]\tAlgorithmIdentifier OPTIONAL,\t-- PBKDF2 if present\n\tkeyEncryptionAlgorithm\t\t\t\t\t-- KEK algorithm\n\t\t\t\t\tAlgorithmIdentifier,\t-- PWRI-KEK\n\tencryptedKey\tOCTET STRING\n\t}\n\n-/ CMS key management /-\n\nRecipientInfo ::= CHOICE {\n\tktri\t\t\tKeyTransRecipientInfo,\t-- Public-key encrypted key\n\tkari\t\t[1] FortezzaRecipientInfo,\t-- Fortezza key-agreement info\n\tkekri\t\t[2] KEKRecipientInfo,\t\t-- Conventionally encrypted key\n\tpwri\t\t[3]\tPasswordRecipientInfo\t-- Password-encrypted key\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\tSignatures\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ CMS signature information /-\n\nSignerInfo ::= SEQUENCE {\t\t\t\t\t-- CMS - S/MIME\n\tversion\t\t\tINTEGER (1),\t\t\t-- CMS\n\tissuerAndSerial\tIssuerAndSerialNumber,\t-- Signing certificate\n\thashAlgorithm\tAlgorithmIdentifier,\t-- Hash algorithm type\n\tsignedAttributes\t\t\t\t\t\t-- Authenticated attributes\n\t\t\t\t[0]\tSET OF Attribute OPTIONAL,\n\tsignatureAlgorithm\t\t\t\t\t\t-- Signature algorithm type\n\t\t\t\t\tAlgorithmIdentifier,\n\tsignature\t\tOCTET STRING\t\t\t-- The signature itself\n\tunsignedAttrs\t\t\t\t\t\t\t-- Countersignature\n\t\t\t\t[1]\tSET OF Attribute OPTIONAL\n\t}\nSignerInfo ::= SEQUENCE {\t\t\t\t\t-- CMS - cryptlib\n\tversion\t\t\tINTEGER (3),\t\t\t-- CMS\n\tkeyID\t\t[0]\tSubjectKeyIdentifier,\t-- Key ID of signing key\n\thashAlgorithm\tAlgorithmIdentifier,\t-- Hash algorithm type\n\tsignatureAlgorithm\t\t\t\t\t\t-- Signature algorithm type\n\t\t\t\t\tAlgorithmIdentifier,\n\tsignature\t\tOCTET STRING\t\t\t-- The signature itself\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\tPublic/Private Keys\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ PKCS #15 uses a very object-oriented design that follows PKCS #11 and\n   uses a lot of the expressive power of ASN.1 in the specification of its\n   PDUs.  The basic PKCS #15 object is defined as follows:\n\n\tPKCS15Object( ClassAttributes, SubclassAttributes, TypeAttributes ) ->\n\t\tSEQUENCE {\n\t\t\tcommonAttr\t\tCommonObjectAttributes,\n\t\t\tclassAttr\t\tClassAttributes,\n\t\t\tsubclassAttr[0]\tSubclassAttributes OPTIONAL,\n\t\t\ttypeAttr\t[1]\tTypeAttributes\n\t\t\t}\n\n   with the attributes being filled in on a per-object basis.  Every object\n   contains common object attributes, and every key or certificate object\n   contains common key or cert class attributes.  In addition the public and\n   private key subclasses contain subclass-specific attributes, but they\n   don't contain anything which isn't present elsewhere so they're omitted.\n   Note the explicit use of EXPLICIT tagging, this is required because dummy\n   parameters like TypeAttributes are always explict-tagged to ensure tag\n   uniqueness (it's like the CHOICE explicit-tag rule):\n\n\t\t\t\t\tKey\t\t\t\t\t\t\t\t\tCert\n\tSEQUENCE {\n\t\tSEQUENCE {\t\t\t\t\t\t\t\t\t\t\t-- CommonObjectAttr\n\t\t\tlabel\t\tUTF8String,\n\t\t\t...\n\t\t\t},\n\t\tSEQUENCE {\t\t\t\t\t\t\tSEQUENCE {\t\t-- ClassAttr\n\t\t\tiD\t\t\tOCTET STRING,\t\t\tiD\t\t\tOCTET STRING,\n\t\t\tusage\t\tBIT STRING,\t\t\t\tauthority\tBOOLEAN DEF FALSE,\n\t\t\taccessFlags\tBIT STRING OPTIONAL,\ttrusted\t[1] SEQUENCE { usage BIT STR },\n\t\t\t...\t\t\t\t\t\t\t\t\tkeyID\t[2] SEQUENCE OF KeyID,\n\t\t\t},\t\t\t\t\t\t\t\t\timpTrust[3]\tBOOLEAN DEFAULT FALSE,\n\t\t\t\t\t\t\t\t\t\t\t\t...\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t[0] EXPLICIT SEQUENCE {\t\t\t\t\t\t\t\t-- SubclassAttr\n\t\t\t...\t\t\tSEQUENCE OPTIONAL,\n\t\t\tkeyID\t[0]\tSEQUENCE OF KeyID,\n\t\t\t...\n\t\t\t} OPTIONAL,\n\t\t[1] EXPLICIT SEQUENCE {\t\t\t\t\t\t\t\t-- TypeAttr\n\t\t\t<data>\n\t\t\t}\n\t\t}\n\t\t\t\tcryptlib config/user data\n\tSEQUENCE {\n\t\tSEQUENCE {\t\t\t\t\t\t\t\t\t\t\t-- CommonObjectAttr\n\t\t\tlabel\t\tUTF8String,\n\t\t\t...\n\t\t\t},\n\t\tSEQUENCE {\t\t\t\t\t\t\t\t\t\t\t-- ClassAttr\n\t\t\t...\n\t\t\tappOID\t\tOBJECT IDENTIFIER (cryptlib),\n\t\t\t...\n\t\t\t},\n\t\t[1] EXPLICIT SEQUENCE {\n\t\t\t<data>\n\t\t\t}\n\t\t} /-\n\nPKCS15CommonObjectAttributes ::= SEQUENCE {\n\tlabel\t\t\tUTF8String OPTIONAL,\t-- Object label\n\t...\n\t}\n\n-/ Class attributes.  Note that the validFrom/validTo attributes were\n   added for PKCS #11 support after the PKCS #15 / ISO 7816-15 split and\n   are for the PKCS #15 v1.2 spec  /-\n\nPKCS15CommonKeyAttributes ::= SEQUENCE {\n\tiD\t\t\t\tOCTET STRING,\t\t\t-- Cross-reference to cert\n\tusage\t\t\tBIT STRING,\t\t\t\t-- PKCS #11 usage flags\n\taccessFlags\t\tBIT STRING b'01101' OPT,-- PKCS #11 access flags\n\tvalidFrom\t\tGeneralisedTime OPTIONAL,\n\tvalidTo\t\t[0]\tGeneralisedTime OPTIONAL,\n\t...\n\t}\n\nPKCS15CommonCertificateAttributes ::= SEQUENCE {\n\tiD\t\t\t\tOCTET STRING,\t\t\t-- Cross-reference to key\n\tauthority\t\tBOOLEAN DEFAULT FALSE,\t-- CA flag\n\tdummy\t\t\tSEQUENCE {} OPTIONAL,\t-- Not used\n\tdummy\t\t[0]\tSEQUENCE {} OPTIONAL,\t-- Not used\n\ttrusted\t\t[1]\tSEQUENCE {\n\t\tkeyUsage\tBIT STRING,\t\t\t\t-- Key usage cert is trusted for\n\t\t...\n\t\t} OPTIONAL,\n\tkeyID\t\t[2]\tSEQUENCE OF KeyID OPTIONAL,\n\timpTrust\t[3]\tBOOLEAN OPTIONAL,\n\tvalidFrom\t\tGeneralisedTime OPTIONAL,\n\tvalidTo\t\t[4] GeneralisedTime OPTIONAL,\n\t...\n\t}\n\nPKCS15CommonSecretKeyAttributes ::= SEQUENCE {\n\t...\n\t}\n\nPKCS15CommonDataObjectAttributes ::= SEQUENCE {\n\tapplicationName\tUTF8String OPTIONAL,\t-- One or both must be present\n\tapplicationOID\tOBJECT IDENTIFIER OPTIONAL,\n\tiD\t\t\t\tOCTET STRING OPTIONAL,\n\t...\n\t}\n\n-/ Subclass attributes.  These are required for public/private keys, for\n   which the ID information isn't present in the class attributes as it is\n   for certificates.  Unfortunately the ID information also isn't present\n   in the public-key subclass attributes, which means that looking up a\n   raw public key by ID is impossible /-\n\nPKCS15CommonPrivateKeyAttributes ::= SEQUENCE {\n\tkeyID\t\t[0]\tSEQUENCE OF KeyID OPTIONAL,\n\t...\n\t}\n\n-/ Key identifiers.  Note that the pgp/openPGP IDs were added after the\n   PKCS #15 / ISO 7816-15 split and are for the PKCS #15 v1.2 spec /-\n\nPKCS15KeyIdentifier ::= TYPED CHOICE {\n\tiAndS\t\t\tSEQUENCE {\t\t\t\t-- Not written, conv.to iAndSHash on rd\n\t\tid\t\t\tINTEGER (1),\n\t\tvalue\t\tIssuerAndSerialNumber\n\t\t},\n\tsubjectKeyID\tSEQUENCE {\t\t\t\t-- Only used if different from iD\n\t\tid\t\t\tINTEGER (2),\n\t\tvalue\t\tOCTET STRING\n\t\t},\n\tiAndSHash\t\tSEQUENCE {\t\t\t\t-- Written and read\n\t\tid\t\t\tINTEGER (3),\n\t\tvalue\t\tOCTET STRING SIZE(20)\n\t\t},\n\tiHash\t\t\tSEQUENCE {\t\t\t\t-- Written and read\n\t\tid\t\t\tINTEGER (6),\n\t\tvalue\t\tOCTET STRING SIZE(20)\n\t\t},\n\tsHash\t\t\tSEQUENCE {\t\t\t\t-- Written and read\n\t\tid\t\t\tINTEGER (7),\n\t\tvalue\t\tOCTET STRING SIZE(20)\n\t\t},\n\tpgp\t\t\t\tSEQUENCE {\t\t\t\t-- Written and read\n\t\tid\t\t\tINTEGER (8),\n\t\tvalue\t\tOCTET STRING SIZE(8)\n\t\t},\n\topenPGP\t\t\tSEQUENCE {\t\t\t\t-- Written and read\n\t\tid\t\t\tINTEGER (9),\n\t\tvalue\t\tOCTET STRING SIZE(8)\n\t\t},\n\t...\n\t}\n\n-/ Private key information (DLP = DSA/DH/KEA/etc) /-\n\nPKCS15PrivateRSAKeyAttributes ::= SEQUENCE {\n\tvalue\t\t\t[2]\tEnvelopedData {\n\t\t\t\t\t\tSEQUENCE {\n\t\tmodulus\t\t[0]\tINTEGER OPTIONAL,\t-- n, not written\n\t\tpublicExp\t[1]\tINTEGER OPTIONAL,\t-- e, not written\n\t\tprivateExp\t[2]\tINTEGER OPTIONAL,\t-- d, not written\n\t\tprime1\t\t[3]\tINTEGER OPTIONAL,\t-- p\n\t\tprime2\t\t[4]\tINTEGER OPTIONAL,\t-- q\n\t\texponent1\t[5]\tINTEGER OPTIONAL,\t-- d mod p-1\n\t\texponent2\t[6]\tINTEGER OPTIONAL,\t-- d mod q-1\n\t\tcoefficient\t[7]\tINTEGER OPTIONAL\t-- q^-1 mod p\n\t\t\t\t\t\t}\n\t\t},\n\tmodulusLength\t\tINTEGER,\n\t...\n\t}\n\nPKCS15PrivateDLPKeyAttributes ::= SEQUENCE {\n\tvalue\t\t\t[2] EnvelopedData {\n\t\t\t\t\t\tINTEGER\t\t\t\t-- DSA x value\n\t\t\t\t\t\t},\n\t...\n\t}\n\nPKCS15PrivateKey ::= CHOICE {\n\tprivateRSAKey\t\tPKCS15Object{ PKCS15CommonKeyAttributes,\t\t-- ClassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15CommonPrivateKeyAttributes,\t-- SubclassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15PrivateRSAKeyAttributes },\t-- TypeAttr\n\tprivateDSAKey\t[2]\tPKCS15Object{ PKCS15CommonKeyAttributes,\n\t\t\t\t\t\t\t\t\t  PKCS15CommonPrivateKeyAttributes,\n\t\t\t\t\t\t\t\t\t  PKCS15PrivateDSAKeyAttributes }\n\t}\n\n-/ This expands out to:\n\n\tSEQUENCE {\n\t\tkeyAttr\t\t\tPKCS15CommonKeyAttributes,\n\t\tprivKeyAttr\t\tPKCS15CommonPrivateKeyAttributes,\n\t\tkeyData\t\t[1]\t{ SEQUENCE { [2] IMPLICIT { Enveloped key data } } }\n\t\t}\n\n   Note that when the PKCS #15 keyset is being used as structured storage\n   for a crypto hardware device then the direct-protected option\n   '[2] EnvelopedData' is replaced by an indirect 'Path' reference, where:\n\n\tPath ::= SEQUENCE {\n\t\tpath\t\t\tOCTET STRING\n\t\t}\n\n   So the above would become:\n\n\tSEQUENCE {\n\t\tkeyAttr\t\t\tPKCS15CommonKeyAttributes,\n\t\tprivKeyAttr\t\tPKCS15CommonPrivateKeyAttributes,\n\t\tkeyData\t\t[1]\t{ SEQUENCE { SEQUENCE { OCTET STRING } } }\n\t\t}\n\n   with the key components stored in the crypto hardware, referenced by the\n   value in the OCTET STRING /-\n\n-/ Public key information (DLP = DSA/DH/KEA/etc) /-\n\nPKCS15PublicRSAKeyAttributes ::= SEQUENCE {\n\tvalue\t\t\t[0]\tEXPLICIT {\n\t\t\t\t\t[1]\tSubjectPublicKeyInfo\n\t\t\t\t\t\t},\n\tmodulusLength\t\tINTEGER,\n\t...\n\t}\n\nPKCS15PublicDLPKeyAttributes ::= SEQUENCE {\n\tvalue\t\t\t[0]\tEXPLICIT SubjectPublicKeyInfo,\n\t...\n\t}\n\nPKCS15PublicKey ::= CHOICE {\n\tpublicRSAKey\t\tPKCS15Object{ PKCS15CommonKeyAttributes,\t\t-- ClassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15CommonPublicKeyAttributes,\t-- SubclassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15PublicRSAKeyAttributes },\t-- TypeAttr\n\tpublicDSAKey\t[2]\tPKCS15Object{ PKCS15CommonKeyAttributes,\n\t\t\t\t\t\t\t\t\t  PKCS15CommonPublicKeyAttributes,\n\t\t\t\t\t\t\t\t\t  PKCS15PublicDSAKeyAttributes }\n\t}\n\n-/ This expands out to:\n\n\tSEQUENCE {\n\t\tkeyAttr\t\t\tPKCS15CommonKeyAttributes,\n\t\tprivKeyAttr\t\tPKCS15CommonPublicKeyAttributes,\n\t\tkeyData\t\t[1]\t{ SEQUENCE { [0] { Public-key data } } }\n\t\t} /-\n\n-/ Certificate information /-\n\nPKCS15X509CertificateAttributes ::= SEQUENCE {\n\tvalue\t\t\t[0]\tCertificate,\n\t...\n\t}\n\nPKCS15Certificate ::= CHOICE {\n\tx509Certificate\t\tPKCS15Object{ PKCS15CommonCertificateAttributes\t-- ClassAttr\n\t\t\t\t\t\t\t\t\t  NULL,\t\t\t\t\t\t\t\t-- SubclassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15X509CertificateAttributes }\t-- TypeAttr\n\t}\n\n-/ This expands out to:\n\n\tSEQUENCE {\n\t\tcertAttr\t\tPKCS15CommonCertificateAttributes,\n\t\tclassAttr\t\tNULL,\n\t\tcertData\t[1]\t{ SEQUENCE { [0] IMPLICIT Certificate } }\n\t\t} /-\n\n-/ Secret key information /-\n\nPKCS15GenericSecretKeyAttributes ::= {\n\tvalue\t\t\t[2] EnvelopedData {\n\t\t\t\t\t\tOCTET STRING\t\t-- Raw secret key\n\t\t\t\t\t\t}\n\t}\n\nPKCS15SecretKey ::= CHOICE {\n\tdes3Key\t\t\t[4] PKCS15Object{ PKCS15CommonKeyAttributes,\t\t-- ClassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15CommonSecretKeyAttributes,\t-- SubclassAttr\n\t\t\t\t\t\t\t\t\t  PKCS15GenericSecretKeyAttributes },-- TypeAttr\n\t}\n\n-/ This expands out to:\n\n\tSEQUENCE {\n\t\tkeyAttr\t\t\tPKCS15CommonKeyAttributes,\n\t\tsecKeyAttr\t\tPKCS15CommonSecretKeyAttributes,\n\t\tkeyData\t\t[1]\t{ [2] { Enveloped key data } }\n\t\t} /-\n\n-/ Data information /-\n\nConfigOption ::= SEQUENCE {\n\ttype\t\t\t\tINTEGER,\t\t\t-- CRYPT_PROPERTY_xxx\n\tvalue\t\t\t\tANY DEFINED BY type\t-- BOOLEAN, INTEGER, UTF8String\n\t}\n\nConfigOptions ::= SEQUENCE OF ConfigOption\n\nUserIndexEntry ::= SEQUENCE {\n\tiD\t\t\t\t\tOCTET STRING SIZE(16),\t-- User ID\n\tcreatorID\t\t\tOCTET STRING SIZE(16),\t-- Creating SO's ID\n\tname\t\t\t\tUTF8String,\t\t\t\t-- User name\n\tfileReference\t\tINTEGER\t\t\t\t\t-- Reference to user file\n\t}\n\nUserIndex ::= SEQUENCE OF UserIndexEntry\n\nUserInfo ::= SEQUENCE {\n\trole\t\t\t\tENUMERATED,\t\t\t\t-- SO/user/CA\n\tiD\t\t\t\t\tOCTET STRING SIZE(16),\t-- User ID\n\tcreatorID\t\t\tOCTET STRING SIZE(16),\t-- Creating SO's ID\n\tname\t\t\t\tUTF8String,\t\t\t\t-- User name\n\t}\n\n// Other user data, has to be stored elsewhere\n//\tstate\t\t\t\tENUMERATED,\t\t\t\t-- SO inited/user inited/locked\n//\tencSecKey\t\t\tEncryptedData OPTIONAL\t-- (Used for CAs)\n\nPKCS15OidDO ::= SEQUENCE {\n\ttype\t\t\t\tOBJECT IDENTIFIER,\n\tvalue\t\t\t\tANY DEFINED BY type\t-- ConfigOptions/UserIndex/UserInfo\n\t}\n\nPKCS15Data ::= CHOICE {\n\toidDO\t\t\t[1]\tPKCS15Object { PKCS15CommonDataObjectAttributes,\n\t\t\t\t\t\t\t\t\t   NULL,\n\t\t\t\t\t\t\t\t\t   PKCS15OidDO }\n\t}\n\n-/ Overall object wrappers. The tagging is [n] PKCS15Objects.foo\n   [0] PKCS15ObjectValue.objects /-\n\nPrivateKeys ::= [0][0] SEQUENCE OF PKCS15PrivateKey\nPublicKeys ::= [1][0] SEQUENCE OF PKCS15PublicKey\nSecretKeys ::= [3][0] SEQUENCE OF PKCS15SecretKey\nCertificates ::= [4][0] SEQUENCE OF PKCS15Certificate\nDataObjects ::= [7][0] SEQUENCE OF PKCS15Data\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\tUser/Config Info\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ User information /-\n\n-/ PKI user information needed for CMP.  The attributes always include an\n   sKID (to uniquely identify the user info) and optionally additional\n   template attributes that are applied to certificate(s) created for this\n   user.  The dual use of the attributes is somewhat ugly, in theory we\n   could split the two into attributes required for PKI user management and\n   attributes to apply to the issued certificate, but because the only one\n   that's used for user management is the sKID it's easier to special-case\n   it in the cert handling code /-\n\nuserData ::= SEQUENCE {\n\tname\t\t\t\tName,\t\t\t\t\t-- Name for CMP\n\tencAlgo\t\t\t\tAlgorithmIdentifier,\t-- Algo to encrypt passwords\n\tencPW\t\t\t\tOCTET STRING,\t\t\t-- Encrypted passwords\n\tattributes\t\t\tAttributes\n\t}\n\nuserPW ::= SEQUENCE {\n\tissuePW\t\t\t\tOCTET STRING SIZE(11),\t-- Password for ir\n\trevPW\t\t\t\tOCTET STRING SIZE(11)\t-- Password for rr\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\tMisc\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ OCSP /-\n\nOCSPRequest ::= SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- tbsRequest\n\t\tversion\t\t[0]\tEXPLICIT INTEGER DEFAULT 0,\n\t\t\t\t\t\t\t\t\t\t\t-- Must be 1 if !certID used\n\t\treqName\t\t[1]\tEXPLICIT ... OPTIONAL\n\t\t\t\t\t\t\t\t\t\t\t-- Ignored\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- requestList\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- request\n\t\t\tcertID\t\tCertID,\n\t\t\tsingleReqExt\n\t\t\t\t\t[0] EXPLICIT Extensions OPTIONAL\n\t\t\t\t}\n\t\t\t},\n\t\treqExts\t\t[2] EXPLICIT Extensions OPTIONAL\n\t\t},\n\tsignature\t\t[0] EXPLICIT SEQUENCE {\n\t\tsigAlgo\t\t\tAlgorithmIdentifier,\n\t\tsig\t\t\t\tBIT STRING,\n\t\tcerts\t\t[0]\tEXPLICIT SEQUENCE OF Certificate OPTIONAL\n\t\t} OPTIONAL\n\t}\n\nOCSPResponse ::= SEQUENCE {\n\trespStatus\t\t\tENUMERATED,\t\t\t-- 0 = OK\n\trespBytes\t\t[0]\tEXPLICIT SEQUENCE {\n\t\trespType\t\tOBJECT IDENTIFIER,\t-- id-pkix-ocsp-basic\n\t\tresp\t\t\tOCTET STRING {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- basicOCSPResponse\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- tbsRespData\n\t\t\tversion [0] EXPLICIT ... OPTIONAL,-- Ignored\n\t\t\trespID\t\t...,\t\t\t\t-- Ignored\n\t\t\tproducedAt\t...,\t\t\t\t-- Ignored\n\t\t\tresponses\tSEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- singleResponse\n\t\t\t\tcertID\t...,\t\t\t\t-- Ignored\n\t\t\t\tcertStatus [0] EXPLICIT = OK, else !OK\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\trespExts[0]\tEXPLICIT Extensions OPTIONAL\n\t\t\t\t}\n\t\tsigAlgo\t\t\tAlgorithmIdentifier,\n\t\tsignature\t\tBIT STRING\n\t\tcerts\t\t[0]\tEXPLICIT SEQUENCE OF Certificate OPTIONAL\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\nCertID ::= CHOICE {\n\tcertID\t\t\t\tSEQUENCE {\n\t\thashAlgo\t\tAlgorithmIdentifier,\n\t\tiNameHash\t\tOCTET STRING,\t\t-- Hash of issuerName\n\t\tiKeyHash\t\tOCTET STRING,\t\t-- Hash of issuer SPKI w/o tag+len\n\t\tserialNo\t\tINTEGER\n\t\t\t\t\t\t},\n\tissuerAndSerial\t[0]\tIssuerAndSerialNumber,\t-- OCSPv2 only\n\tcertificate\t\t[1]\tCertificate,\t\t-- OCSPv2 only\n\tcertHash\t\t[2] OCTET STRING\t\t-- OCSPv2 only\n\t}\n\n-/ RTCS /-\n\nRTCSRequests ::= SEQUENCE {\n\tresponseType\t\tRTCSResponseType DEFAULT rtcsBasic,\n\t\t\t\t\t\tSEQUENCE OF {\t\t-- requests\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- requestInfo\n\t\tcertHash\t\tOCTET STRING SIZE(20),\n\t\t\t}\n\t\t}\n\tattributes\tAttributes OPTIONAL,\n\t}\n\nRTCSResponsesBasic ::= SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- responseBasic\n\tcertHash\t\t\tOCTET STRING SIZE(20),\n\tstatus\t\t\t\tBOOLEAN\n\t\t}\n\t}\n\nRTCSResponsesExtended ::= SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- responseBasic/Extended\n\tcertHash\t\t\tOCTET STRING SIZE(20),\n\tstatus\t\t\t\tENUMERATED,\n\tstatusInfo\t\t\tANY DEFINED BY status,\n\tattributes\t\t[0]\tAttributes OPTIONAL\t-- For ext.response\n\t\t}\n\t}\n\n-/ Timestamping /-\n\nTSARequest ::= SEQUENCE {\n\tversion\t\t\t\tINTEGER (1),\n\tmsgImprint\t\t\tSEQUENCE {\n\t\talgorithm\t\tAlgorithmIdentifier,\n\t\thash\t\t\tOCTET STRING\n\t\t},\n\tpolicy\t\t\t\tOBJECT IDENTIFIER OPTIONAL,\n\t\t\t\t\t\t\t\t\t\t\t-- Ignored\n\tnonce\t\t\t\tINTEGER OPTIONAL,\t-- Copy to output if present\n\tincludeSigCerts\t\tBOOLEAN DEFAULT FALSE,\n\t\t\t\t\t\t\t\t\t\t\t-- Include signer certs if set\n\textensions\t\t[0]\tExtensions OPTIONAL\t-- Reject if present\n\t}\n\nTSAResponse ::= SEQUENCE {\n\tstatus\t\t\t\tSEQUENCE {\n\t\tstatus\t\t\tINTEGER,\t\t\t-- 0 = OK\n\t\t\t\t\t\t... OPTIONAL\n\t\t},\n\ttimeStamp\t\t\tContentInfo\n\t}\n\nTSTInfo ::= SEQUENCE {\n\tversion\t\t\t\tINTEGER (1),\n\tpolicy\t\t\t\tOBJECT IDENTIFIER,\n\tmsgImprint\t\t\tSEQUENCE { ... }\t-- From request\n\tserialNo\t\t\tINTEGER,\t\t\t-- Unique value\n\tgenTime\t\t\t\tGeneralizedTime,\t-- Current time\n\tnonce\t\t\t\tINTEGER OPTIONAL\t-- From input if present\n\t}\n\n-/ PKCS #12.  Note that what's deployed (and documented here) bears very\n   little resemblance to what's given in the specification /-\n\nPFX ::= SEQUENCE {\n\tversion\t\t\t\tINTEGER (3),\n\tauthSafe\t\t\tSEQUENCE {\t\t\t-- ContentInfo\n\t\tcontentType\t\tOBJECT IDENTIFIER id-Data,\n\t\tcontent\t\t[0]\tEXPLICIT OCTET STRING {\n\t\t\tsafeConts\tSEQUENCE OF {\n\t\t\t\t\t\tCHOICE {\t\t\t-- Effectively a CHOICE\n\t\t\t\tp12Data\tPKCS12Data,\t\t\t-- Data for encrypted keys\n\t\t\t\tp12Encr\tPKCS12Encr\t\t\t-- EncrData for public keys\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tmacData\t\t\t\tSEQUENCE {\n\t\tmac\t\t\t\tSEQUENCE {\n\t\t\talgorithm\tAlgorithmIdentifier,\n\t\t\tmac\t\t\tOCTET STRING\n\t\t\t}\n\t\tmacSalt\t\t\tOCTET STRING,\n\t\titerations\t\tINTEGER DEFAULT 1\t-- Usually set to 2,000\n\t\t}\n\t}\n\nPKCS12Data ::= SEQUENCE {\t\t\t\t\t-- For encrypted private keys\n\tcontentType\t\t\tOBJECT IDENTIFIER id-Data,\n\tcontent\t\t\t[0]\tEXPLICIT OCTET STRING {\n\t\tsafeContents\tSEQUENCE OF PKCS12Bag -- SIZE(1)\n\t\t}\n\t}\n\nPKCS12Bag ::= SEQUENCE {\n\tbagId\t\t\t\tOBJECT IDENTIFIER pkcs8ShroudedKeyBag,\n\tbagValue\t\t[0]\tEXPLICIT SEQUENCE {\n\t\tencryptionAlgo\tSEQUENCE {\n\t\t\talgo\t\tOBJECT IDENTIFIER pbeWithSHAAnd2-KeyTripleDES-CBC,\n\t\t\tpbeParams\tSEQUENCE {\n\t\t\t\tsalt\tOCTET STRING,\n\t\t\t\titers\tINTEGER\n\t\t\t\t}\n\t\t\t}\n\t\tencryptedData\tOCTET STRING\t\t-- Encrypted PKCS #8\n\t\t}\n\tbagAttributes\t\tSET OF Attribute\n\t}\n\nPKCS8 ::= SEQUENCE {\t\t\t\t\t\t-- Within PKCS12Bag above\n\tversion\t\t\t\tINTEGER (0),\n\talgorithm\t\t\tAlgorithmIdentifier,\n\tkey\t\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (0),\n\t\tkeyValues\t\t...\n\t\t\t\t\t\t}\n\tattributes\t\t[0]\tSET OF Attribute OPTIONAL\n\t}\n\nPKCS12Encr ::= SEQUENCE {\t\t\t\t\t-- For public certificates\n\tcontentType\t\t\tOBJECT IDENTIFIER id-EncryptedData,\n\tcontent\t\t\t[0]\tEXPLICIT SEQUENCE {\n\t\tversion\t\t\tINTEGER (0),\n\t\tencContentInfo\tSEQUENCE {\n\t\t\tcontentType\tOBJECT IDENTIFIER id-Data,\n\t\t\tcontentEncAlgo SEQUENCE {\n\t\t\t\talgo\tOBJECT IDENTIFIER pbeWithSHAAnd40BitRC2-CBC,\n\t\t\t\tpbeParams SEQUENCE {\n\t\t\t\t\tsalt OCTET STRING,\n\t\t\t\t\titers INTEGER\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tencryptedData OCTET STRING\t\t-- Encrypted PKCS12CertBag\n\t\t\t}\n\t\t}\n\t}\n\nPKCS12CertBag ::= SEQUENCE OF SEQUENCE {\t-- Within PKCS12Enc above\n\tbagId\t\t\t\tOBJECT IDENTIFIER pkcs12CertBag,\n\tbagValue\t\t[0]\tEXPLICIT SEQUENCE {\n\t\tcertId\t\t\tOBJECT IDENTIFIER x509Certificate,\n\t\tcertValue\t[0]\tEXPLICIT OCTET STRING {\n\t\t\tcert\t\tCertificate\n\t\t\t}\n\t\t}\n\tbagAttributes\t\tSET OF Attribute\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\tCertificate Mismanagement Protocol\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ \"If an undergraduate student handed this in as an assignment I'd fail them\n\ton the grounds that it shows a complete lack of understanding of the\n\tprinciples of workable protocol design\" /-\n\nxxxRequest ::= SEQUENCE {\t\t\t\t\t-- ir/cr/kur, 3.3.1/3.3.3/3.3.5\n\theader\t\t\t\tSEQUENCE {\t\t\t--\tProfile = B8\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t[4]\tEXPLICIT DirectoryName,\t-- DN of subject\n\t\trecipient\t[4]\tEXPLICIT DirectoryName,\t-- DN of CA\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2] EXPLICIT OCTET STRING,\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),\t-- Random\n\t\tnonce\t\t[5] EXPLICIT OCTET STRING SIZE (16),\t-- Random\n\t\t},\n\tbody\t\t\t[0]\tEXPLICIT SEQUENCE {\t-- [2] in cr, [7] in kur\n\t\tcertReqMsg\t\tSEQUENCE {\t\t\t-- RFC 2510\n\t\t\t\t\t\tSEQUENCE {\n\t\t\tcReqID\t\tINTEGER (0),\n\t\t\tcTemplate\tSEQUENCE {\n\t\t\t\tvalidity[1] TIME OPTIONAL,\n\t\t\t\tsubject\t[5] EXPLICIT Name,\n\t\t\t\tpubKey\t[6] SubjectPublicKeyInfo,\n\t\t\t\texts\t[9] Extensions OPTIONAL\n\t\t\t\t\t\t},\n\t\t\tcControls\tSEQUENCE OF Attribute OPTIONAL\t\t-- Ignored\n\t\t\t\t\t},\n\t\tpop\t\t\t[1] EXPLICIT Signature\t-- From X.509, for sig.key\nor\t\tpop\t\t\t[2] EXPLICIT [1] INTEGER (0)\n\t\t\t\t\t\t\t\t\t\t\t-- For encr-only key\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- ir = MAC, cr/kur = SIG\n\t}\n\nxxxResponse ::= SEQUENCE {\t\t\t\t\t-- ip/cp/kup, 3.3.2/3.3.4/3.3.6\n\theader\t\t\t\tSEQUENCE {\t\t\t--\tProfile = B8\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\tnonceX\t\t[5] EXPLICIT OCTET STRING SIZE (16),-- Needed in CertConf\n\t\t...\n\t\t},\n\tbody\t\t\t[1] EXPLICIT SEQUENCE {\t\t\t-- [3] in cp, [8] in kup\n\t\tcaPubs\t\t[1] EXPLICIT SEQUENCE {...} OPTIONAL,-- Ignored\n\t\tresponse\t\tSEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\t\tcertReqID\tINTEGER (0),\n\t\t\tstatus\t\tSEQUENCE {\t\t\t-- PKIStatusInfo, 3.2.3\n\t\t\t\tstatus\tINTEGER,\n\t\t\t\tstatusStr SEQUENCE OF UTF8String OPTIONAL,\n\t\t\t\tfailInfo BIT STRING OPTIONAL\n\t\t\t\t},\n\t\t\tcertKeyPair\tSEQUENCE {\t\t\t-- If status == 0 or 1\n\t\t\t\tcert[0]\tEXPLICIT Certificate,\nor\t\t\t\tencCert\t\t\t\t\t\t-- For encr-only key\n\t\t\t\t\t[1] EXPLICIT EncryptedCert,\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- ip = MAC, cp/kup = SIG\n\t}\n\nCertConf ::= SEQUENCE {\t\t\t\t\t\t-- 3.3.18, profile = B8\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\tnonce\t\t[5] EXPLICIT OCTET STRING SIZE (16),-- Random\n\t\tnonceX\t\t[6] EXPLICIT OCTET STRING SIZE (16),-- Copied from InitResp\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t},\n\tbody\t\t   [24]\tEXPLICIT SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\tcertHash\t\tOCTET STRING\n\t\tcertReqID\t\tINTEGER (0),\n\t\t\t}\n\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- ix = MAC, cx/kux = SIG\n\t}\n\nConf ::= SEQUENCE {\t\t\t\t\t\t\t-- 3.3.17, profile = B8\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t},\n\tbody\t\t   [19]\tEXPLICIT NULL,\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- ix = MAC, cx/kux = SIG\n\t}\n\nRevRequest ::= SEQUENCE {\t\t\t\t\t-- rr, 3.3.9\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t[4]\tEXPLICIT DirectoryName,\t-- DN of subject\n\t\trecipient\t[4]\tEXPLICIT DirectoryName,\t-- DN of CA\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2] EXPLICIT OCTET STRING,\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),\t-- Random\n\t\tnonce\t\t[5] EXPLICIT OCTET STRING SIZE (16),\t-- Random\n\t\t},\n\tbody\t\t   [11]\tEXPLICIT SEQUENCE {\n\t\trevDetails\t\tSEQUENCE {\n\t\t\tcTemplate\tSEQUENCE {\t\t\t-- RFC 2510\n\t\t\t\tserial\t[1] INTEGER,\n\t\t\t\tissuer\t[3] EXPLICIT NAME\n\t\t\t\t\t\t},\n\t\t\tcrlEntries\tExtensions OPTIONAL\n\t\t\t\t\t}\n\t\t\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- MAC or SIG\n\t}\n\nRevResponse ::= SEQUENCE {\t\t\t\t\t-- rp, 3.3.10\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (PBMac),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t},\n\tbody\t\t   [12]\tEXPLICIT SEQUENCE {\n\t\tstatus\t\t\tSEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\t\t\t-- PKIStatusInfo, 3.2.3\n\t\t\tstatus\t\tINTEGER,\n\t\t\tstatusStr\tSEQUENCE OF UTF8String OPTIONAL,\n\t\t\tfailInfo\tBIT STRING OPTIONAL\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t}\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- MAC or SIG\n\t}\n\nGenMsg ::= SEQUENCE {\t\t\t\t\t\t-- 3.3.19/3.3.20\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (sigAlgo),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t},\n\tbody\t\t   [21]\tEXPLICIT SEQUENCE OF {\n\t\t\t\t\t\tSEQUENCE {\n\t\tinfoType\t\tOBJECT IDENTIFIER,\n\t\tintoValue\t\tANY DEFINED BY infoType OPTIONAL\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- MAC or SIG\n\t}\n\nError ::= SEQUENCE {\t\t\t\t\t\t-- 3.3.21\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsender\t\t\tSEQUENCE {...},\t\t-- Ignored\n\t\trecipient\t\tSEQUENCE {...},\t\t-- Ignored\n\t\tmessageTime\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier (sigAlgo),\n\t\tprotKeyID\t[2]\tEXPLICIT OCTET STRING,\t\t\t-- Must match previous\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Must match previous\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t},\n\tbody\t\t   [23]\tEXPLICIT SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\tstatus\t\t\tINTEGER,\n\t\t\t\t\t\tSEQUENCE {\n\t\t\tstatusMsg\tUTF8String,\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t\t} OPTIONAL,\n\t\tfailInfo\t\tBIT STRING OPTIONAL\n\t\t\t\t\t\t},\n\t\terrorCode\t\tINTEGER OPTIONAL,\n\t\t\t\t\t\tSEQUENCE {\n\t\t\terrorMsg\tUTF8String,\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t\t} OPTIONAL\n\t\t\t\t\t},\n\tprotection\t\t[0]\tEXPLICIT BIT STRING\t-- SIG\n\t}\n\n-/ The MAC information used when the protection is a MAC /-\n\nMacInfo ::= SEQUENCE {\n\talgoID\t\t\t\tOBJECT IDENTIFIER (entrustMAC),\n\talgoParams\t\t\tSEQUENCE {\n\t\tsalt\t\t\tOCTET STRING,\n\t\tpwHashAlgo\t\tAlgorithmIdentifier (SHA-1),\n\t\titerations\t\tINTEGER,\n\t\tmacAlgo\t\t\tAlgorithmIdentifier (HMAC-SHA1)\n\t\t}\n\t}\n\n-/ The encrypted data when the cert is returned encrypted /-\n\nEncryptedCert ::= SEQUENCE {\n\tdummy\t\t\t[0]\t... OPTIONAL,\t\t-- Ignored\n\tcekAlg\t\t\t[1]\tAlgorithmIdentifier,-- CEK algorithm\n\tencCEK\t\t\t[2]\tBIT STRING,\t\t\t-- Encrypted CEK\n\tdummy\t\t\t[3]\t... OPTIONAL,\t\t-- Ignored\n\tdummy\t\t\t[4] ... OPTIONAL,\t\t-- Ignored\n\tencData\t\t\tBIT STRING\n\t}\n\n------------------------------------------------------------------------------\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n--\t\t\t\t\t\tCertificate Messages over CMS\t\t\t\t\t\t--\n--\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t--\n------------------------------------------------------------------------------\n\n-/ CMC request and response messages.  Certificates are returned as signing\n   certs attached to the CMS signed data /-\n\nPKIData ::= SEQUENCE {\n\tattributes\t\tSEQUENCE OF TaggedAttribute, -- Control attrs.\n\trequests\t\tSEQUENCE OF TaggedReq,\t-- Cert.requests\n\tcms\t\t\t\tSEQUENCE OF TaggedCMS,\t-- CMS messages\n\tother\t\t\tSEQUENCE OF OtherMsg\t-- Type-and-value pairs\n\t}\n\nPKIResp ::= SEQUENCE {\n\tattributes\t\tSEQUENCE OF TaggedAttribute, -- Control attrs.\n\tcms\t\t\t\tSEQUENCE OF TaggedCMS,\t-- CMS messages\n\tother\t\t\tSEQUENCE OF OtherMsg\t-- Type-and-value pairs\n\t}\n\n-/ TaggedXYZ types.  OtherMsg is identical to TaggedAttribute except that\n   the value field is ANY DEFINED BY /-\n\nTaggedAttribute ::= SEQUENCE {\n\tiD\t\t\t\tINTEGER,\t\t\t\t-- Unique 32-bit ID for this attr.\n\ttype\t\t\tOBJECT IDENTIFIER,\n\tvalues\t\t\tSEQUENCE OF Attribute\n\t}\n\nTaggedCMS ::= SEQUENCE {\n\tiD\t\t\t\tINTEGER,\t\t\t\t-- Unique 32-bit ID for this attr.\n\tvalue\t\t\tCMS\n\t}\n\nEND\n"
  },
  {
    "path": "deps/cl345/cryptlib.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Core Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n\n/* Prototypes for functions in init.c.  These should actually be annotated\n   with CHECK_RETVAL_ACQUIRELOCK( MUTEX_LOCKNAME( initialisation ) and\n   RELEASELOCK( MUTEX_LOCKNAME( initialisation ) ) but the mutex locking\n   types aren't visible outside the kernel and in any case the annotation is\n   only required where the functions are defined, so we just annotate them\n   normally here */\n\nCHECK_RETVAL \\\nint krnlBeginInit( void );\nvoid krnlCompleteInit( void );\nCHECK_RETVAL \\\nint krnlBeginShutdown( void );\nRETVAL \\\nint krnlCompleteShutdown( void );\n\n/* Somewhat untidy direct-access mechanism for functions that have to be \n   performed mid-startup or mid-shutdown */\n\nint destroyObjects( void );\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\nCHECK_RETVAL \\\nint testFunctionality( void );\nCHECK_RETVAL \\\nint testKernel( void );\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/* Some messages communicate standard data values that are used again and\n   again so we predefine values for these that can be used globally */\n\nconst int messageValueTrue = TRUE;\nconst int messageValueFalse = FALSE;\nconst int messageValueCryptOK = CRYPT_OK;\nconst int messageValueCryptError = CRYPT_ERROR;\nconst int messageValueCryptUnused = CRYPT_UNUSED;\nconst int messageValueCryptUseDefault = CRYPT_USE_DEFAULT;\nconst int messageValueCursorFirst = CRYPT_CURSOR_FIRST;\nconst int messageValueCursorNext = CRYPT_CURSOR_NEXT;\nconst int messageValueCursorPrevious = CRYPT_CURSOR_PREVIOUS;\nconst int messageValueCursorLast = CRYPT_CURSOR_LAST;\n\n/* Safe pointers need a NULL-equivalent value which we also define here */\n\nconst DATAPTR DATAPTR_NULL = DATAPTR_INIT;\nconst FNPTR FNPTR_NULL = FNPTR_INIT;\n\n/* OS X Snow Leopard broke dlopen(), if it's called from a (sub-)thread then \n   it dies with a SIGTRAP.  Specifically, if you dlopen() a shared library \n   linked with CoreFoundation from a thread and the calling app wasn't \n   linked with CoreFoundation then the function CFInitialize() inside \n   dlopen() checks if the thread is the main thread (specifically \n   CFInitialize is declared with __attribute__ ((constructor))) and if it \n   isn't being called from the main thread it crashes with a SIGTRAP.  The \n   inability to call dlopen() from a thread was apparently a requirement in \n   pre-Snow Leopard versions as well but was never enforced.  One possible \n   workaround for this would be to require that any application that uses \n   cryptlib also link in CoreFoundation, but this will be rather error-\n   prone, so we disable asynchronous driver binding instead */\n\n#if defined( __APPLE__ )\n  #undef USE_THREAD_FUNCTIONS\n#endif /* __APPLE__  */\n\n/* If we're fuzzing we also disable threaded init in order to make the \n   startup behaviour deterministic */\n\n#if defined( CONFIG_FUZZ )\n  #undef USE_THREAD_FUNCTIONS\n#endif /* CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStartup/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The initialisation and shutdown actions performed for various object\n   types.  The pre-init actions are used to handle various preparatory\n   actions that are required before the actual init can be performed, for\n   example to create the system device and user object, which are needed by\n   the init routines.  The pre-shutdown actions are used to signal to various\n   subsystems that a shutdown is about to occur, for example to allow the\n   networking subsystem to gracefully exit from any currently occurring \n   network I/O.\n\n   The certificate init is somewhat special in that it only performs an\n   internal consistency check rather than performing any actual \n   initialisation.  As such it's not performed as part of the asynchronous\n   init since it has the potential to abort the cryptlib startup and as\n   such can't be allowed to come back at a later date an retroactively shut \n   things down after other crypto operations have already occurred.  In fact\n   since it's part of the startup self-test it's done in the pre-init, as a\n   failure to complete the self-test will result in an immediate abort of the\n   init process.\n\n   The order of the init/shutdown actions is:\n\n\t\t\t\t\tObject type\t\tAction\n\t\t\t\t\t-----------\t\t------\n\tPre-init:\t\tCert\t\t\tSelf-test only\n\t\t\t\t\tDevice\t\t\tCreate system object\n\n\tInit:\t\t\tUser\t\t\tCreate default user object\n\t\t\t\t\tKeyset\t\t\tDrivers - keysets\t\t\t| Done async.\n\t\t\t\t\tDevice\t\t\tDrivers - devices\t\t\t| if\n\t\t\t\t\tSession\t\t\tDrivers - networking\t\t| available\n\t\t\t\t   [Several]\t\tKernel self-test\n\n\tPre-shutdown:\tSession\t\t\tNetworking - signal socket close\n\t\t\t\t\tDevice\t\t\tSystem object - signal entropy poll end\n\n\tShutdown:\t\tUser\t\t\tDestroy default user object\t| Done by\n\t\t\t\t\tDevice\t\t\tDestroy system object\t\t| kernel\n\t\t\t\t\tKeyset\t\t\tDrivers - keysets\n\t\t\t\t\tDevice\t\t\tDrivers - devices\n\t\t\t\t\tSession\t\t\tDrivers - networking\n\n   The init order is determined by the following object dependencies:\n\n\tAll -> Device\n\t\t\t(System object handles many message types).\n\tUser -> Keyset, Cert \n\t\t\t(Default user object reads config data from the default keyset \n\t\t\t to init drivers for keysets, devices, and networking, and \n\t\t\t trusted certs.  The default keyset isn't read via a loadable \n\t\t\t keyset driver so it doesn't require the keyset driver init).\n\tSelf-test -> Several\n\t\t\t(Kernel self-test creates several ephemeral objects in order to \n\t\t\t test the kernel mechanisms).\n\n   The shutdown order is determined by the following dependencies:\n\n\tSession (Networking needs to shut down to release any objects that are \n\t\t\t blocked waiting on network I/O)\n\tDevice (System object needs to shut down ongoing entropy poll)\n\n   After this the shutdown proper can take place.  The shutdown order is\n   noncritical, provided that the pre-shutdown actions have occurred.\n\n   In theory the user and system objects are destroyed as part of the \n   standard shutdown, however the kernel prevents these objects from ever\n   being explicitly destroyed so they're destroyed implicitly by the\n   destroyObjects() cleanup call */\n\nCHECK_RETVAL \\\nint certManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\nCHECK_RETVAL \\\nint deviceManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\nCHECK_RETVAL \\\nint keysetManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\nCHECK_RETVAL \\\nint sessionManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\nCHECK_RETVAL \\\nint userManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\n\ntypedef CHECK_RETVAL \\\n\t\tint ( *MANAGEMENT_FUNCTION )( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action );\n\nstatic const MANAGEMENT_FUNCTION preInitFunctions[] = {\n  #ifdef USE_CERTIFICATES\n\tcertManagementFunction,\n  #endif /* USE_CERTIFICATES */\n\tdeviceManagementFunction, \n\tNULL, NULL \n\t};\nstatic const MANAGEMENT_FUNCTION initFunctions[] = {\n\tuserManagementFunction, \n\tNULL, NULL \n\t};\nstatic const MANAGEMENT_FUNCTION asyncInitFunctions[] = {\n  #ifdef USE_KEYSETS\n\tkeysetManagementFunction, \n  #endif /* USE_KEYSETS */\n\tdeviceManagementFunction, \n  #ifdef USE_SESSIONS\n\tsessionManagementFunction, \n  #endif /* USE_SESSIONS */\n\tNULL, NULL \n\t};\nstatic const MANAGEMENT_FUNCTION preShutdownFunctions[] = {\n  #ifdef USE_SESSIONS\n\tsessionManagementFunction, \n  #endif /* USE_SESSIONS */\n\tdeviceManagementFunction, \n\tNULL, NULL \n\t};\nstatic const MANAGEMENT_FUNCTION shutdownFunctions[] = {\n\t/*userManagementFunction,*/ /*deviceManagementFunction,*/ \n  #ifdef USE_KEYSETS\n\tkeysetManagementFunction, \n  #endif /* USE_KEYSETS */\n\tdeviceManagementFunction, \n  #ifdef USE_SESSIONS\n\tsessionManagementFunction, \n  #endif /* USE_SESSIONS */\n\tNULL, NULL \n\t};\n\n/* Dispatch a set of management actions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int dispatchManagementAction( IN_ARRAY( mgmtFunctionCount ) \\\n\t\t\t\t\t\t\t\t\t\tconst MANAGEMENT_FUNCTION *mgmtFunctions,\n\t\t\t\t\t\t\t\t\t IN_INT_SHORT const int mgmtFunctionCount,\n\t\t\t\t\t\t\t\t\t IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tint i, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isReadPtr( mgmtFunctions, \\\n\t\t\t\t\t   sizeof( MANAGEMENT_FUNCTION ) * mgmtFunctionCount ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( mgmtFunctionCount ) );\n\tREQUIRES( isEnumRange( action, MANAGEMENT_ACTION ) );\n\n\t/* If we're performing a startup and the kernel is shutting down, bail \n\t   out now */\n\tif( ( action == MANAGEMENT_ACTION_INIT ) && krnlIsExiting() )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Dispatch each management action in turn */\n\tLOOP_MED( i = 0, i < mgmtFunctionCount && \\\n\t\t\t\t\t mgmtFunctions[ i ] != NULL, i++ )\n\t\t{\n\t\tconst int localStatus = mgmtFunctions[ i ]( action );\n\t\tif( cryptStatusError( localStatus ) && cryptStatusOK( status ) )\n\t\t\tstatus = localStatus;\n\n\t\t/* If we're performing a startup and the kernel is shutting down, \n\t\t   bail out now */\n\t\tif( ( action == MANAGEMENT_ACTION_INIT ) && krnlIsExiting() )\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n\n/* Under various OSes we bind to a number of drivers at runtime.  We can\n   either do this sychronously or asynchronously depending on the setting of \n   a config option.  By default we use the async init since it speeds up the \n   startup.  Synchronisation is achieved by having the open/init functions \n   in the modules that require the drivers call krnlWaitSemaphore() on the \n   driver binding semaphore, which blocks until the drivers are bound if an \n   async bind is in progress, or returns immediately if no bind is in \n   progress */\n\n#ifdef USE_THREAD_FUNCTIONS\n\nvoid threadedBind( const THREAD_PARAMS *threadParams )\n\t{\n\tassert( isReadPtr( threadParams, sizeof( THREAD_PARAMS ) ) );\n\n\t( void ) dispatchManagementAction( asyncInitFunctions, \n\t\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( asyncInitFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\t   MANAGEMENT_ACTION_INIT );\n\t}\n#endif /* USE_THREAD_FUNCTIONS */\n\n/* Perform various sanity checks on the build process.  Since this will \n   typically be running on an embedded system there's not much that we can \n   (safely) do in terms of user I/O except to return a special-case return \n   code and hope that the user checks the embedded systems section of the \n   manual for more details, although we do try and produce diagnostic output \n   if this is enabled */\n\n#ifdef INC_ALL\t\t\t\t\t/* For OS/architecture names */\n  #include \"bn.h\"\n  #include \"osconfig.h\"\n#else\n  #include \"bn/bn.h\"\n  #include \"crypt/osconfig.h\"\n#endif /* Compiler-specific includes */\n\nstatic BOOLEAN sanityCheckBuild( void )\n\t{\n\tBYTE data[ 16 ];\n\n\t/* Before we begin any checking, dump general build parameters */\n\tDEBUG_PUTS(( \"** Build parameters **\" ));\n\tDEBUG_PRINT(( \"System is \" SYSTEM_NAME \", %d bit \", \n\t\t\t\t  sizeof( size_t ) * 8 ));\n#ifdef DATA_LITTLEENDIAN\n\tDEBUG_PUTS(( \"little-endian.\" ));\n#else\n\tDEBUG_PUTS(( \"big-endian.\" ));\n#endif /* DATA_LITTLEENDIAN */\n\tDEBUG_PRINT(( \"Long long size = %d, long size = %d, int size = %d, \"\n\t\t\t\t  \"short size = %d.\\n\", sizeof( LONGLONG_TYPE ) * 8,\n\t\t\t\t  sizeof( long ) * 8, sizeof( int ) * 8, \n\t\t\t\t  sizeof( short ) * 8 ));\n\tDEBUG_PRINT(( \"char is %d-bit %ssigned, wchar is %d-bit %ssigned.\\n\",\n\t\t\t\t  sizeof( char ) * 8, ( ( char ) -1 < 0 ) ? \"\" : \"un\", \n\t\t\t\t  sizeof( wchar_t ) * 8, ( ( wchar_t ) -1 < 0 ) ? \"\" : \"un\" ));\n\tDEBUG_PRINT(( \"Extended build options:\" ));\n#ifdef USE_CAST\n\tDEBUG_PRINT(( \" USE_CAST\" ));\n#endif /* USE_CAST */\n#ifdef USE_CERT_DNSTRING\n\tDEBUG_PRINT(( \" USE_CERT_DNSTRING\" ));\n#endif /* USE_CERT_DNSTRING */\n#ifdef USE_CERT_OBSOLETE\n\tDEBUG_PRINT(( \" USE_CERT_OBSOLETE\" ));\n#endif /* USE_CERT_OBSOLETE */\n#if defined( USE_CERTLEVEL_PKIX_FULL )\n\tDEBUG_PRINT(( \" USE_CERTLEVEL_PKIX_FULL\" ));\n#elif defined( USE_CERTLEVEL_PKIX_PARTIAL )\n\tDEBUG_PRINT(( \" USE_CERTLEVEL_PKIX_PARTIAL\" ));\n#elif defined( USE_CERTLEVEL_STANDARD )\n\tDEBUG_PRINT(( \" USE_CERTLEVEL_STANDARD\" ));\n#elif defined( USE_CERTLEVEL_REDUCED )\n\tDEBUG_PRINT(( \" USE_CERTLEVEL_REDUCED\" ));\n#elif defined( USE_CERT_OBSCURE )\n\tDEBUG_PRINT(( \" USE_CERT_OBSCURE\" ));\n#else\n\tDEBUG_PRINT(( \" (Unknown cert level)\" ));\n#endif /* Certificate level */\n#ifdef USE_CFB\n\tDEBUG_PRINT(( \" USE_CFB\" ));\n#endif /* USE_CFB */\n#ifdef USE_CMSATTR_OBSCURE\n\tDEBUG_PRINT(( \" USE_CMSATTR_OBSCURE\" ));\n#endif /* USE_CMSATTR_OBSCURE */\n#ifdef USE_DEPRECATED_ALGORITHMS\n\tDEBUG_PRINT(( \" USE_DEPRECATED_ALGORITHMS\" ));\n#endif /* USE_DEPRECATED_ALGORITHMS */\n#ifdef USE_DES\n\tDEBUG_PRINT(( \" USE_DES\" ));\n#endif /* USE_DES */\n#ifdef USE_DNSSRV\n\tDEBUG_PRINT(( \" USE_DNSSRV\" ));\n#endif /* USE_DNSSRV */\n#ifdef USE_EAP\n\tDEBUG_PRINT(( \" USE_EAP\" ));\n#endif /* USE_EAP */\n#ifdef USE_ECDH\n\tDEBUG_PRINT(( \" USE_ECDH\" ));\n#endif /* USE_ECDH */\n#ifdef USE_ECDSA\n\tDEBUG_PRINT(( \" USE_ECDSA\" ));\n#endif /* USE_ECDSA */\n#ifdef USE_ELGAMAL\n\tDEBUG_PRINT(( \" USE_ELGAMAL\" ));\n#endif /* USE_ELGAMAL */\n#ifdef USE_EMBEDDED_OS\n\tDEBUG_PRINT(( \" USE_EMBEDDED_OS\" ));\n#endif /* USE_EMBEDDED_OS */\n#ifdef USE_ERRMSGS\n\tDEBUG_PRINT(( \" USE_ERRMSGS\" ));\n#endif /* USE_ERRMSGS */\n#ifdef USE_GCM\n\tDEBUG_PRINT(( \" USE_GCM\" ));\n#endif /* USE_GCM */\n#ifdef USE_HARDWARE\n\tDEBUG_PRINT(( \" USE_HARDWARE\" ));\n#endif /* USE_HARDWARE */\n#ifdef USE_IDEA\n\tDEBUG_PRINT(( \" USE_IDEA\" ));\n#endif /* USE_IDEA */\n#ifdef USE_JAVA\n\tDEBUG_PRINT(( \" USE_JAVA\" ));\n#endif /* USE_JAVA */\n#ifdef USE_LDAP\n\tDEBUG_PRINT(( \" USE_LDAP\" ));\n#endif /* USE_LDAP */\n#ifdef USE_OAEP\n\tDEBUG_PRINT(( \" USE_OAEP\" ));\n#endif /* USE_OAEP */\n#ifdef USE_OBSCURE_ALGORITHMS\n\tDEBUG_PRINT(( \" USE_OBSCURE_ALGORITHMS\" ));\n#endif /* USE_OBSCURE_ALGORITHMS */\n#ifdef USE_ODBC\n\tDEBUG_PRINT(( \" USE_ODBC\" ));\n#endif /* USE_ODBC */\n#ifdef USE_PATENTED_ALGORITHMS\n\tDEBUG_PRINT(( \" USE_PATENTED_ALGORITHMS\" ));\n#endif /* USE_PATENTED_ALGORITHMS */\n#ifdef USE_PGP2\n\tDEBUG_PRINT(( \" USE_PGP2\" ));\n#endif /* USE_PGP2 */\n#ifdef USE_PKCS11\n\tDEBUG_PRINT(( \" USE_PKCS11\" ));\n#endif /* USE_PKCS11 */\n#ifdef USE_PKCS12\n\tDEBUG_PRINT(( \" USE_PKCS12\" ));\n#endif /* USE_PKCS12 */\n#ifdef USE_PKCS12_WRITE\n\tDEBUG_PRINT(( \" USE_PKCS12_WRITE\" ));\n#endif /* USE_PKCS12_WRITE */\n#ifdef USE_PSEUDOCERTIFICATES\n\tDEBUG_PRINT(( \" USE_PSEUDOCERTIFICATES\" ));\n#endif /* USE_PSEUDOCERTIFICATES */\n#ifdef USE_RC2\n\tDEBUG_PRINT(( \" USE_RC2\" ));\n#endif /* USE_RC2 */\n#ifdef USE_RC4\n\tDEBUG_PRINT(( \" USE_RC4\" ));\n#endif /* USE_RC4 */\n#ifdef USE_RSA_SUITES\n\tDEBUG_PRINT(( \" USE_RSA_SUITES\" ));\n#endif /* USE_RSA_SUITES */\n#ifdef USE_SHA2_EXT\n\tDEBUG_PRINT(( \" USE_SHA2_EXT\" ));\n#endif /* USE_SHA2_EXT */\n#ifdef USE_SSH_EXTENDED\n\tDEBUG_PRINT(( \" USE_SSH_EXTENDED\" ));\n#endif /* USE_SSH_EXTENDED */\n#ifdef USE_SSH_CTR\n\tDEBUG_PRINT(( \" USE_SSH_CTR\" ));\n#endif /* USE_SSH_CTR */\n#ifdef USE_SSL3\n\tDEBUG_PRINT(( \" USE_SSL3\" ));\n#endif /* USE_SSL3 */\n#ifdef USE_THREADS\n\tDEBUG_PRINT(( \" USE_THREADS\" ));\n#endif /* USE_THREADS */\n#ifdef USE_TPM\n\tDEBUG_PRINT(( \" USE_TPM\" ));\n#endif /* USE_TPM */\n#ifdef USE_WEBSOCKETS\n\tDEBUG_PRINT(( \" USE_WEBSOCKETS\" ));\n#endif /* USE_WEBSOCKETS */\n\tDEBUG_PRINT(( \".\\n\" ));\n\tDEBUG_PUTS(( \"Build date/time for file \" __FILE__ \" is \" __DATE__ \", \" \n\t\t\t\t __TIME__ \".\" ));\n#ifdef __STDC_VERSION__\n\tDEBUG_PRINT(( \"STDC_VERSION = %ld.\\n\", __STDC_VERSION__ ));\n#endif /* __STDC_VERSION__ */\n#ifdef _POSIX_VERSION\n\tDEBUG_PRINT(( \"POSIX_VERSION = %ld.\\n\", _POSIX_VERSION ));\n#endif /* _POSIX_VERSION */\n#ifdef __clang__\n\tDEBUG_PUTS(( \"clang version = \" __clang_version__ \".\" ));\n#endif /* __clang__ */\n#ifdef __GNUC__\n\tDEBUG_PUTS(( \"gcc version = \" __VERSION__ \".\" ));\n#endif /* __GNUC__ */\n#ifdef __HP_cc\n\tDEBUG_PRINTF(( \"HP cc version = %06d.\\n\", __HP_cc ));\n#endif /* __HP_cc */\n#ifdef _MSC_VER\n\tDEBUG_PRINT(( \"Visual C version = %ld.\\n\", _MSC_VER ));\n#endif /* _MSC_VER */\n#ifdef __SUNPRO_C\n\tDEBUG_PRINT(( \"SunPro cc version = %X.\\n\", __SUNPRO_C ));\n#endif /* __SUNPRO_C */\n#if defined( __xlc__ )\n\tDEBUG_PRINT(( \"IBM xlc version = %X.\\n\", __xlC__ ));\n#elif defined( __IBMC__ )\n\tDEBUG_PRINT(( \"IBM c89 version = %X.\\n\", __IBMC__ ));\n#endif /* Different, semi-overlapping IBM compilers */\n#if defined( __GNUC__ ) || defined( __clang__ )\n\tif( !__builtin_constant_p( MK_TOKEN( \"1234\" ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"Warning: Call stack tokens arent being computed by \"\n\t\t\t\t\t \"the preprocessor,\\n         this will lead to code \"\n\t\t\t\t\t \"bloat in control-flow integrity checks.\" ));\n\t\t}\n#endif /* Warn on non-preprocessor evaluation of MK_TOKEN() */\n\n\t/* Perform a sanity check to make sure that the endianness was set \n\t   right.  The crypto self-test that's performed a bit later on will \n\t   catch this problem as well but it's better to do an explicit check \n\t   here that catches the endianness problem rather than just returning a \n\t   generic self-test fail error */\n#ifdef DATA_LITTLEENDIAN\n\tif( *( ( long * ) \"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) < 0 )\n#else\n\tif( *( ( long * ) \"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) >= 0 )\n#endif /* DATA_LITTLEENDIAN */\n\t\t\t{\n\t\t\t/* We should probably sound klaxons as well at this point */\n\t\t\tDEBUG_PUTS(( \"CPU endianness is configured incorrectly, see \"\n\t\t\t\t\t\t \"the cryptlib manual for details.\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t/* Make sure that the compiler doesn't use variable-size enums.  This is \n\t   done by, for example, the PalmOS SDK for backwards compatibility with \n\t   architectural decisions made for 68K-based PalmPilots, and at least \n\t   one ARM compiler, as permitted by the ARM AAPCS (section 7.1.3), \n\t   which says that \"this ABI delegates a choice of representation of \n\t   enumerated types to a platform ABI\", followed by a long discussion of \n\t   all the problems that this causes, after which it's allowed anyway,\n\t   but it can also be optionally enabled for compilers like gcc, so just \n\t   to be safe we check all compilers except the ones that we know never \n\t   do this */\n#if !defined( _MSC_VER )\n\tif( sizeof( CRYPT_ALGO_TYPE ) != sizeof( int ) || \\\n\t\tsizeof( CRYPT_MODE_TYPE ) != sizeof( int ) ||\n\t\tsizeof( CRYPT_ATTRIBUTE_TYPE ) != sizeof( int ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"Compiler uses variable-length enumerated types, see \"\n\t\t\t\t\t \"the cryptlib manual for details.\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* Microsoft compilers */\n\n\t/* Make sure that isValidPointer() isn't reporting valid pointers as\n\t   being invalid.  This could in theory happen on some hypothetical OS\n\t   that does odd things with memory layouts so we check for it here */\n\tif( !isValidPointer( data ) || !isValidPointer( preInitFunctions ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"isValidPointer() macro reports data or code pointer \"\n\t\t\t\t\t \"is invalid when it's valid, see misc/safety.h.\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Initialise and shut down the system */\n\nCHECK_RETVAL \\\nint initCryptlib( void )\n\t{\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint initLevel = 0, status;\n\n\t/* Let the user know that we're in the cryptlib startup code if they're in\n\t   debug mode */\n\tDEBUG_PUTS(( \"\" ));\n\tDEBUG_PUTS(( \"***************************\" ));\n\tDEBUG_PUTS(( \"* Beginning cryptlib init *\" ));\n\tDEBUG_PUTS(( \"***************************\" ));\n\tDEBUG_PUTS(( \"\" ));\n\n\t/* Perform any required sanity checks on the build process.  This would\n\t   be caught by the self-test but sometimes people don't run this so we\n\t   perform a minimal sanity check here to avoid failing in the startup\n\t   self-tests that follow */\n\tif( !sanityCheckBuild() )\n\t\t{\n\t\tDEBUG_DIAG(( \"Build sanity-check failed\" ));\n\t\tretIntError();\n\t\t}\n\tCFI_CHECK_UPDATE( \"sanityCheckBuild\" );\n\n\t/* Initiate the kernel startup */\n\tDEBUG_PUTS(( \"** Initialising kernel **\" ));\n\tstatus = krnlBeginInit();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Kernel init failed, status = %d\", status ));\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"krnlBeginInit\" );\n\n\t/* Verify that core functionality and universal crypto algorithms are \n\t   working as required, unless we're running a fuzzing build for which \n\t   we don't want to get held up too long in startup */\n#if !defined( CONFIG_FUZZ ) && !defined( CONFIG_CONSERVE_MEMORY_EXTRA )\n\tDEBUG_PUTS(( \"** Running general functionality self-tests **\" ));\n\tstatus = testFunctionality();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"General functionality test failed, status = %d\", \n\t\t\t\t\t status ));\n\t\tassert( DEBUG_WARN );\n\t\tkrnlCompleteShutdown();\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n#endif /* !CONFIG_FUZZ && !CONFIG_CONSERVE_MEMORY_EXTRA */\n\tCFI_CHECK_UPDATE( \"testFunctionality\" );\n\n\t/* Perform OS-specific additional initialisation inside the kernel init \n\t   lock */\n\tDEBUG_PUTS(( \"** Initialising system variables **\" ));\n\tstatus = initSysVars();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"OS-specific initialisation failed, status = %d\", \n\t\t\t\t\t status ));\n\t\tassert( DEBUG_WARN );\n\t\tkrnlCompleteShutdown();\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tCFI_CHECK_UPDATE( \"initSysVars\" );\n\n\t/* Perform the multi-phase bootstrap */\n\tDEBUG_PUTS(( \"** Running pre-init actions **\" ));\n\tstatus = dispatchManagementAction( preInitFunctions, \n\t\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( preInitFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\t   MANAGEMENT_ACTION_PRE_INIT );\n\tassertNoFault( cryptStatusOK( status ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinitLevel = 1;\n\t\tCFI_CHECK_UPDATE( \"preInitFunctions\" );\n\t\tDEBUG_PUTS(( \"** Running init actions **\" ));\n\t\tstatus = dispatchManagementAction( initFunctions, \n\t\t\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( initFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_ACTION_INIT );\n\t\tassertNoFault( cryptStatusOK( status ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef USE_THREAD_FUNCTIONS\n\t\tBOOLEAN_INT asyncInit = FALSE;\n#endif /* USE_THREAD_FUNCTIONS */\n\n\t\tinitLevel = 2;\n\t\tCFI_CHECK_UPDATE( \"initFunctions\" );\n\n\t\t/* Perform the final init phase asynchronously or synchronously \n\t\t   depending on the config option setting.  We always send this \n\t\t   query to the default user object since no other user objects \n\t\t   exist at this time */\n\t\tDEBUG_PUTS(( \"** Running async init actions **\" ));\n#ifdef USE_THREAD_FUNCTIONS\n\t\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &asyncInit, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_MISC_ASYNCINIT );\n\t\tif( cryptStatusOK( status ) && asyncInit == TRUE )\n\t\t\t{\n\t\t\t/* We use the kernel's thread storage for this thread, so we \n\t\t\t   specify the thread data storage as NULL */\n\t\t\tstatus = krnlDispatchThread( threadedBind, NULL, NULL, 0,\n\t\t\t\t\t\t\t\t\t\t SEMAPHORE_DRIVERBIND );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* The thread couldn't be started, try again with a \n\t\t\t\t   synchronous init */\n\t\t\t\tasyncInit = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\tif( !asyncInit )\n#endif /* USE_THREAD_FUNCTIONS */\n\t\tstatus = dispatchManagementAction( asyncInitFunctions, \n\t\t\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( asyncInitFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\t\t   MANAGEMENT_ACTION_INIT );\n\t\tassertNoFault( cryptStatusOK( status ) );\n\t\t}\n#if !defined( CONFIG_FUZZ ) && !defined( CONFIG_CONSERVE_MEMORY_EXTRA )\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tCFI_CHECK_UPDATE( \"asyncInitFunctions\" );\n\n\t\t/* Everything's set up, verify that the core crypto algorithms and \n\t\t   kernel security mechanisms are working as required, unless we're\n\t\t   running a fuzzing build for which we don't want to get held up\n\t\t   too long in startup */\n\t\tDEBUG_PUTS(( \"** Running kernel self-tests **\" ));\n\t\tstatus = testKernel();\n\t\tassertNoFault( cryptStatusOK( status ) );\n\t\t}\n#else\n\tCFI_CHECK_UPDATE( \"asyncInitFunctions\" );\n#endif /* !CONFIG_FUZZ && !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\t/* If anything failed, shut down the internal functions and services\n\t   before we exit */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( initLevel >= 1 )\n\t\t\t{\n\t\t\t/* Shut down any external interfaces */\n\t\t\t( void ) dispatchManagementAction( preShutdownFunctions, \n\t\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( preShutdownFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\tMANAGEMENT_ACTION_PRE_SHUTDOWN );\n\t\t\tdestroyObjects();\n\t\t\t( void ) dispatchManagementAction( shutdownFunctions, \n\t\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( shutdownFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tMANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\t\t\tMANAGEMENT_ACTION_SHUTDOWN );\n\t\t\t}\n\t\tkrnlCompleteShutdown();\n\t\treturn( status );\n\t\t}\n\n\t/* Complete the kernel startup */\n\tDEBUG_PUTS(( \"** Completing kernel init **\" ));\n\tkrnlCompleteInit();\n\tCFI_CHECK_UPDATE( \"krnlCompleteInit\" );\n\n\t/* Let the user know that the cryptlib startup has completed \n\t   successfully if they're in debug mode */\n\tDEBUG_PUTS(( \"\" ));\n\tDEBUG_PUTS(( \"***************************\" ));\n\tDEBUG_PUTS(( \"* cryptlib init completed *\" ));\n\tDEBUG_PUTS(( \"***************************\" ));\n\tDEBUG_PUTS(( \"\" ));\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"sanityCheckBuild\", \"krnlBeginInit\", \n\t\t\t\t\t\t\t\t\t\"testFunctionality\", \"initSysVars\", \n\t\t\t\t\t\t\t\t\t\"preInitFunctions\", \"initFunctions\", \n\t\t\t\t\t\t\t\t\t\"asyncInitFunctions\", \"krnlCompleteInit\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint endCryptlib( void )\n\t{\n\tint status;\n\n\t/* Let the user know that we're in the cryptlib shutdown code if they're \n\t   in debug mode */\n\tDEBUG_PUTS(( \"\" ));\n\tDEBUG_PUTS(( \"*******************************\" ));\n\tDEBUG_PUTS(( \"* Beginning cryptlib shutdown *\" ));\n\tDEBUG_PUTS(( \"*******************************\" ));\n\tDEBUG_PUTS(( \"\" ));\n\n\t/* Initiate the kernel shutdown */\n\tstatus = krnlBeginShutdown();\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Reverse the process carried out in the multi-phase bootstrap */\n\t( void ) dispatchManagementAction( preShutdownFunctions, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( preShutdownFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\tMANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\tMANAGEMENT_ACTION_PRE_SHUTDOWN );\n\tstatus = destroyObjects();\n\t( void ) dispatchManagementAction( shutdownFunctions, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( shutdownFunctions, \\\n\t\t\t\t\t\t\t\t\t\t\t\tMANAGEMENT_FUNCTION ),\n\t\t\t\t\t\t\tMANAGEMENT_ACTION_SHUTDOWN );\n\n\t/* Complete the kernel shutdown */\n\tkrnlCompleteShutdown();\n\n\t/* Let the user know that the cryptlib shutdown has completed \n\t   successfully if they're in debug mode */\n\tDEBUG_PUTS(( \"\" ));\n\tDEBUG_PUTS(( \"*******************************\" ));\n\tDEBUG_PUTS(( \"* cryptlib shutdown completed *\" ));\n\tDEBUG_PUTS(( \"*******************************\" ));\n\tDEBUG_PUTS(( \"\" ));\n\n\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/cryptlib.cfg",
    "content": "<?xml version=\"1.0\"?>\n<def>\n\n<!-- cppcheck configuration file for cryptlib -->\n<!-- Stream functions: stdio -->\n\n<function name=\"sputc\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>0:255</valid></arg>\n</function>\n<function name=\"sgetc\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sread\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"swrite\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sflush\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sseek\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>0:</valid></arg>\n</function>\n<function name=\"stell\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sioctlSet\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:50</valid></arg>\n  <arg nr=\"3\"><not-bool/></arg>\n</function>\n<function name=\"sioctlSetString\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:50</valid></arg>\n  <arg nr=\"3\"><not-null/><not-uninit/></arg>\n  <arg nr=\"4\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sioctlGet\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:50</valid></arg>\n  <arg nr=\"3\"><not-null/></arg>\n  <arg nr=\"4\"><not-bool/><valid>1:</valid></arg>\n</function>\n\n<!-- Stream functions: Nonstandard -->\n\n<function name=\"sSkip\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sPeek\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n\n<!-- Stream functions: Error handling -->\n\n<function name=\"sSetError\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-bool/><valid>-1000:0</valid></arg>\n</function>\n<function name=\"sClearError\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n\n<!-- Stream functions: Query -->\n\n<function name=\"sIsNullStream\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n\n<!-- Stream functions: Memory -->\n\n<function name=\"sMemOpen\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sMemOpenOpt\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/></arg>\n  <arg nr=\"3\"><not-bool/><valid>0:</valid></arg>\n</function>\n<function name=\"sMemNullOpen\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n</function>\n<function name=\"sMemClose\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sMemConnect\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sMemDisconnect\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n\n<!-- Stream functions: Memory direct-access -->\n\n<function name=\"sMemDataLeft\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sMemGetDataBlock\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sMemGetDataBlockAbs\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-bool/><valid>0:</valid></arg>\n  <arg nr=\"3\"><not-null/></arg>\n  <arg nr=\"4\"><not-bool/><valid>1:</valid></arg>\n</function>\n<function name=\"sMemGetDataBlockRemaining\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/></arg>\n  <arg nr=\"3\"><not-null/></arg>\n</function>\n\n<!-- Stream functions: File -->\n\n<function name=\"sFileOpen\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:50</valid></arg>\n</function>\n<function name=\"sFileClose\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n\n<!-- Stream functions: File Nonstandard -->\n\n<function name=\"sFileToMemStream\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-null/></arg>\n  <arg nr=\"4\"><not-bool/><valid>1:</valid></arg>\n</function>\n\n<!-- Stream functions: File low-level -->\n\n<function name=\"fileReadonly\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"fileClearToEOF\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"fileErase\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"fileBuildCryptlibPath\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:</valid></arg>\n  <arg nr=\"3\"><not-null/></arg>\n  <arg nr=\"4\"><not-null/><not-uninit/></arg>\n  <arg nr=\"5\"><not-bool/><valid>1:</valid></arg>\n  <arg nr=\"6\"><not-bool/><valid>1:20</valid></arg>\n</function>\n\n<!-- Stream functions: Network -->\n\n<function name=\"sNetParseURL\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-null/><not-uninit/></arg>\n  <arg nr=\"3\"><not-bool/><valid>1:</valid></arg>\n  <arg nr=\"4\"><not-bool/><valid>0:20</valid></arg>\n</function>\n<function name=\"sNetConnect\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:10</valid></arg>\n  <arg nr=\"3\"><not-null/><not-uninit/></arg>\n  <arg nr=\"4\"><not-null/></arg>\n</function>\n<function name=\"sNetListen\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/></arg>\n  <arg nr=\"2\"><not-bool/><valid>1:10</valid></arg>\n  <arg nr=\"3\"><not-null/><not-uninit/></arg>\n  <arg nr=\"4\"><not-null/></arg>\n</function>\n<function name=\"sNetDisconnect\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n</function>\n<function name=\"sNetGetErrorInfo\">\n  <noreturn>false</noreturn>\n  <arg nr=\"1\"><not-null/><not-uninit/></arg>\n  <arg nr=\"2\"><not-null/></arg>\n</function>  \n\n<function name=\"my_printf_s\">\n  <noreturn>false</noreturn>\n  <formatstr secure=\"true\"/>\n  <arg nr=\"1\"><formatstr/><not-uninit/><not-null/></arg>\n</function>\n \n</def>\n"
  },
  {
    "path": "deps/cl345/cryptlib.exp",
    "content": "cryptAddCertExtension\ncryptAddPrivateKey\ncryptAddPublicKey\ncryptAddRandom\ncryptAsyncCancel\ncryptAsyncQuery\ncryptCAAddItem\ncryptCACertManagement\ncryptCADeleteItem\ncryptCAGetItem\ncryptCheckCert\ncryptCheckSignature\ncryptCheckSignatureEx\ncryptCreateCert\ncryptCreateContext\ncryptCreateEnvelope\ncryptCreateSession\ncryptCreateSignature\ncryptCreateSignatureEx\ncryptDecrypt\ncryptDeleteAttribute\ncryptDeleteCertExtension\ncryptDeleteKey\ncryptDestroyCert\ncryptDestroyContext\ncryptDestroyEnvelope\ncryptDestroyObject\ncryptDestroySession\ncryptDeviceClose\ncryptDeviceCreateContext\ncryptDeviceOpen\ncryptDeviceQueryCapability\ncryptEncrypt\ncryptEnd\ncryptExportCert\ncryptExportKey\ncryptExportKeyEx\ncryptFlushData\ncryptGenerateKey\ncryptGenerateKeyAsync\ncryptGetAttribute\ncryptGetAttributeString\ncryptGetCertExtension\ncryptGetKey\ncryptGetPrivateKey\ncryptGetPublicKey\ncryptImportCert\ncryptImportKey\ncryptImportKeyEx\ncryptInit\ncryptKeysetClose\ncryptKeysetOpen\ncryptLogin\ncryptLogout\ncryptPopData\ncryptPushData\ncryptQueryCapability\ncryptQueryObject\ncryptSetAttribute\ncryptSetAttributeString\ncryptSignCert\n"
  },
  {
    "path": "deps/cl345/cryptlib.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t  cryptlib Header File\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2019\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CRYPTLIB_DEFINED\n\n#define _CRYPTLIB_DEFINED\n\n/* The current cryptlib version: 3.4.5 */\n\n#define CRYPTLIB_VERSION\t345\n\n/* Fixup for Windows support.  We need to include windows.h for various types\n   and prototypes needed for DLLs.  In addition wincrypt.h defines some\n   values with the same names as cryptlib ones, so we need to check for this\n   and issue a warning not to mix cryptlib with CryptoAPI (that's like taking\n   a bank vault and making one side out of papier mache).\n\n   A second, less likely condition can occur when wincrypt.h is included\n   after cryptlib.h, which shouldn't happen if developers follow the\n   convention of including local headers after system headers, but can occur\n   if they ignore this convention.  The NOCRYPT doesn't fix this since\n   wincrypt.h can be pulled in indirectly and unconditionally, for example\n   via winldap.h -> schnlsp.h -> schannel.h -> wincrypt.h.  To fix this, we\n   create a redundant define for CRYPT_MODE_ECB which produces a compile\n   error if wincrypt.h is included after cryptlib.h.  Since thie will\n   conflict with the enum, we have to place it after the CRYPT_MODE_xxx\n   enums */\n\n#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \\\n\t  defined( __WIN32__ ) || defined( _WIN32_WCE ) ) && \\\n\t  !defined( _SCCTK ) && !defined( _CVI_ )\n  #ifndef WIN32_LEAN_AND_MEAN\n\t#define WIN32_LEAN_AND_MEAN\t/* Skip RPC, OLE, Multimedia, etc */\n  #endif /* WIN32_LEAN_AND_MEAN */\n  #define NOCRYPT\t\t\t\t/* Disable include of wincrypt.h */\n  #include <windows.h>\n\n  /* Catch use of CryptoAPI and cryptlib at the same time.  wxWidgets \n     includes wincrypt.h by default so we undefine the conflicting values \n\t and assume that the warning above will let users know that CryptoAPI \n\t use isn't going to work properly, for anything else we require that the\n\t user explicitly fix things */\n  #if defined( CRYPT_MODE_ECB )\n\t#pragma message( \"Warning: Both cryptlib.h and wincrypt.h have been included into the same source file.\" )\n\t#pragma message( \"         These contain conflicting type names that prevent both from being used simultaneously.\" )\n\t#ifdef __WXWINDOWS__\n\t  #pragma message( \"         To allow compilation to proceed the wincrypt.h encryption modes have been undefined.\" )\n\t  #undef CRYPT_MODE_ECB\n\t  #undef CRYPT_MODE_CBC\n\t  #undef CRYPT_MODE_CFB\n\t  #undef CRYPT_MODE_GCM\n\t#else\n\t  #pragma message( \"         To allow compilation to proceed you need to avoid including wincrypt.h in your code.\" )\n\t  #error \"cryptlib.h and wincrypt.h can't both be used at the same time due to conflicting type names\"\n\t#endif /* __WXWINDOWS__ */\n  #endif /* Clash with wincrypt.h defines */\n#endif /* Windows other than a cross-development environment */\n\n/* Machine-dependant types to allow use in special library types such as\n   DLLs.  Under Win32 and BeOS we need to use the dllimport and dllexport\n   directives for the DLL/shared-lib version so we define the type used for\n   functions depending on whether we're being included via the cryptlib-\n   internal crypt.h or not */\n\n#if ( defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || \\\n\t  defined( _WIN32_WCE ) ) && !( defined( STATIC_LIB ) || defined( _SCCTK ) )\n  #define C_PTR\t*\t\t\t\t\t/* General pointer */\n  #if defined( _WIN32_WCE )\n\t/* Rather than relying on _UNICODE being defined (which would cause\n\t   problems if cryptlib is built with char * but the calling app is built\n\t   with wchar_t *), we always use the default native char type, which is\n\t   ASCII (or at least 8-bit) under Win32 and Unicode under WinCE */\n\t#define C_CHR wchar_t\n  #else\n\t#define C_CHR char\n  #endif /* WinCE vs. Win32 */\n  #define C_STR C_CHR *\n  #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x500 )\n\t#ifdef _CRYPT_DEFINED\n\t  #define C_RET\tint\t_export _stdcall\t\t/* BC++ DLL export ret.val.*/\n\t#else\n\t  #define C_RET\tint\t_import _stdcall\t\t/* BC++ DLL import ret.val.*/\n\t#endif /* CRYPT_DEFINED */\n  #else\n\t#ifdef _CRYPT_DEFINED\n\t  #define C_RET\t__declspec( dllexport ) int\t__stdcall\t/* DLL export ret.val.*/\n\t#else\n\t  #define C_RET\t__declspec( dllimport ) int\t__stdcall\t/* DLL import ret.val.*/\n\t#endif /* CRYPT_DEFINED */\n  #endif /* BC++ vs.VC++ DLL functions */\n#elif defined( _WINDOWS ) && !defined( STATIC_LIB )\n  #define C_PTR\tFAR *\t\t\t\t/* DLL pointer */\n  #define C_CHR char\n  #define C_STR C_CHR FAR *\t\t\t/* DLL string pointer */\n  #define C_RET\tint FAR PASCAL _export\t/* DLL return value */\n#elif defined( __BEOS__ )\n/* #include <BeBuild.h>\t\t\t\t// _EXPORT/_IMPORT defines */\n  #define C_PTR *\n  #define C_CHR char\n  #define C_STR C_CHR *\n  #ifdef _STATIC_LINKING\n\t#define C_RET int\n  #else\n\t#ifdef _CRYPT_DEFINED\n\t  #define C_RET\t__declspec( dllexport ) int\t/* Shared lib export ret.val.*/\n\t#else\n\t  #define C_RET\t__declspec( dllimport ) int\t/* Shared lib import ret.val.*/\n\t#endif /* CRYPT_DEFINED */\n  #endif /* Static vs. shared lib */\n#elif defined( __SYMBIAN32__ )\n  #ifdef _CRYPT_DEFINED\n\t#define C_RET\tEXPORT_C\t\t\t\t\t/* DLL export ret.val.*/\n  #else\n\t#define C_RET\tIMPORT_C\t\t\t\t\t/* DLL import ret.val.*/\n  #endif /* CRYPT_DEFINED */\n#else\n  #define C_PTR\t*\n  #define C_CHR char\n  #define C_STR C_CHR *\n  #define C_RET\tint\n#endif /* Windows vs.everything else function types */\n\n/* Symbolic defines to make it clearer how the function parameters behave */\n\n#define C_IN\t\tconst\t\t\t/* Input-only */\n#define C_IN_OPT\tconst\t\t\t/* Input-only, may be NULL */\n#define C_OUT\t\t\t\t\t\t/* Output-only */\n#define C_OUT_OPT\t\t\t\t\t/* Output-only, may be NULL */\n#define C_INOUT\t\t\t\t\t\t/* Modified in-place */\n\n/* Additional defines for compilers that provide extended function and \n   function-parameter checking */\n\n#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )\n  #define C_CHECK_RETVAL\t\t\t__attribute__(( warn_unused_result ))\n  #ifdef _CRYPT_DEFINED\n\t#define C_NONNULL_ARG( argIndex )\t/* Too dangerous to use inside clib */\n  #else\n\t#define C_NONNULL_ARG( argIndex )\t__attribute__(( nonnull argIndex ))\n  #endif /* _CRYPT_DEFINED */\n#elif defined( _MSC_VER ) && defined( _PREFAST_ )\n  #ifdef __ATTR_SAL\t\t\t\t/* Attribute SAL */\n\t#define C_CHECK_RETVAL\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t\t_Success_( return == CRYPT_OK )\n\t#define C_NONNULL_ARG( argIndex )\n\t#undef C_IN_OPT\n\t#define C_IN_OPT\t\t\t\t_In_opt_ const\n\t#undef C_OUT_OPT\n\t#define C_OUT_OPT\t\t\t\t_Out_opt_\n\t#undef C_INOUT\n\t#define C_INOUT\t\t\t\t\t_Inout_\n  #else\n\t#define C_CHECK_RETVAL\t\t\t__checkReturn \\\n\t\t\t\t\t\t\t\t\t__success( result == CRYPT_OK ) \\\n\t\t\t\t\t\t\t\t\t__range( MAX_ERROR, CRYPT_OK )\n\t#define C_NONNULL_ARG( argIndex )\n\t#undef C_IN_OPT\n\t#define C_IN_OPT\t\t\t\t__in_opt const\n\t#undef C_OUT_OPT\n\t#define C_OUT_OPT\t\t\t\t__out_opt\n\t#undef C_INOUT\n\t#define C_INOUT\t\t\t\t\t__inout\n  #endif /* Declspec vs. Attribute SAL */\n#else\n  #define C_CHECK_RETVAL\n  #define C_NONNULL_ARG( argIndex )\n#endif /* Compiler-specific annotations */\n\n#ifdef _CRYPTLIB_DEFINED\t\t\t/* Disable use in non-C versions of header */\n\n/* Alongside the externally visible types, cryptlib also has various internal\n   types that are extended forms of the external types that are invisible\n   to the user (e.g. SignedPublicKeyAndChallenge == certRequest).  These can\n   only be used internally and are blocked by the security kernel, so they\n   can never be accessed from outside cryptlib (in fact for good measure\n   they're blocked before they even get to the kernel by preliminary range\n   checks in the API wrapper functions).  The only reason they're defined\n   here is because it's not possible to extend an enum outside the point\n   where it's originally defined */\n\n#endif /* _CRYPTLIB_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAlgorithm and Object Types\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Algorithm and mode types */\n\ntypedef enum {\t\t\t\t\t\t/* Algorithms */\n\t/* No encryption */\n\tCRYPT_ALGO_NONE,\t\t\t\t/* No encryption */\n\n\t/* Conventional encryption */\n\tCRYPT_ALGO_DES,\t\t\t\t\t/* DES */\n\tCRYPT_ALGO_3DES,\t\t\t\t/* Triple DES */\n\tCRYPT_ALGO_IDEA,\t\t\t\t/* IDEA (only used for PGP 2.x) */\n\tCRYPT_ALGO_CAST,\t\t\t\t/* CAST-128 (only used for OpenPGP) */\n\tCRYPT_ALGO_RC2,\t\t\t\t\t/* RC2 (disabled by default, used for PKCS #12) */\n\tCRYPT_ALGO_RC4,\t\t\t\t\t/* RC4 (insecure, deprecated) */\n\tCRYPT_ALGO_RESERVED1,\t\t\t/* Formerly RC5 */\n\tCRYPT_ALGO_AES,\t\t\t\t\t/* AES */\n\tCRYPT_ALGO_RESERVED2,\t\t\t/* Formerly Blowfish */\n\n\t/* Public-key encryption */\n\tCRYPT_ALGO_DH = 100,\t\t\t/* Diffie-Hellman */\n\tCRYPT_ALGO_RSA,\t\t\t\t\t/* RSA */\n\tCRYPT_ALGO_DSA,\t\t\t\t\t/* DSA */\n\tCRYPT_ALGO_ELGAMAL,\t\t\t\t/* ElGamal */\n\tCRYPT_ALGO_RESERVED3,\t\t\t/* Formerly KEA */\n\tCRYPT_ALGO_ECDSA,\t\t\t\t/* ECDSA */\n\tCRYPT_ALGO_ECDH,\t\t\t\t/* ECDH */\n\n\t/* Hash algorithms */\n\tCRYPT_ALGO_RESERVED4 = 200,\t\t/* Formerly MD2 */\n\tCRYPT_ALGO_RESERVED5,\t\t\t/* Formerly MD4 */\n\tCRYPT_ALGO_MD5,\t\t\t\t\t/* MD5 (only used for TLS 1.0/1.1) */\n\tCRYPT_ALGO_SHA1,\t\t\t\t/* SHA/SHA1 */\n\tCRYPT_ALGO_RESERVED6,\t\t\t/* Formerly RIPE-MD 160 */\n\tCRYPT_ALGO_SHA2,\t\t\t\t/* SHA-256 */\n\t\tCRYPT_ALGO_SHA256 = CRYPT_ALGO_SHA2,/* Alternate name */\n\tCRYPT_ALGO_SHAng,\t\t\t\t/* Future SHA-nextgen standard */\n\n\t/* MACs */\n\tCRYPT_ALGO_RESREVED_7 = 300,\t/* Formerly HMAC-MD5 */\n\tCRYPT_ALGO_HMAC_SHA1,\t\t\t/* HMAC-SHA */\n\tCRYPT_ALGO_RESERVED8,\t\t\t/* Formerly HMAC-RIPEMD-160 */\n\tCRYPT_ALGO_HMAC_SHA2,\t\t\t/* HMAC-SHA2 */\n\tCRYPT_ALGO_HMAC_SHAng,\t\t\t/* HMAC-future-SHA-nextgen */\n\n#ifdef _CRYPT_DEFINED\n\t/* Alongside the usual types we also need a generic secret-key store\n\t   for use with mechanisms that convert a single secret value into\n\t   multiple derived keying values like encryption keys, MAC keys,\n\t   IVs, and so on.  The following algorithm type implements this \n\t   generic-secret crypto object */\n\tCRYPT_IALGO_GENERIC_SECRET = 1000,/* Generic-secret object */\n#endif /* _CRYPT_DEFINED */\n\n\t/* Vendors may want to use their own algorithms that aren't part of the\n\t   general cryptlib suite.  The following values are for vendor-defined\n\t   algorithms, and can be used just like the named algorithm types (it's\n\t   up to the vendor to keep track of what _VENDOR1 actually corresponds\n\t   to) */\n#ifdef USE_VENDOR_ALGOS\n\tCRYPT_ALGO_VENDOR1 = 10000, CRYPT_ALGO_VENDOR2, CRYPT_ALGO_VENDOR3,\n#endif /* USE_VENDOR_ALGOS */\n\n\tCRYPT_ALGO_LAST,\t\t\t\t/* Last possible crypt algo value */\n#ifdef _CRYPT_DEFINED\n\tCRYPT_ALGO_LAST_EXTERNAL = CRYPT_ALGO_HMAC_SHAng + 1,\n#endif /* _CRYPT_DEFINED */\n\n\t/* In order that we can scan through a range of algorithms with\n\t   cryptQueryCapability(), we define the following boundary points for\n\t   each algorithm class */\n\tCRYPT_ALGO_FIRST_CONVENTIONAL = 1,\n\tCRYPT_ALGO_LAST_CONVENTIONAL = 99,\n\tCRYPT_ALGO_FIRST_PKC = 100,\n\tCRYPT_ALGO_LAST_PKC = 199,\n\tCRYPT_ALGO_FIRST_HASH = 200,\n\tCRYPT_ALGO_LAST_HASH = 299,\n\tCRYPT_ALGO_FIRST_MAC = 300,\n\tCRYPT_ALGO_LAST_MAC = 399\n\t} CRYPT_ALGO_TYPE;\n\ntypedef enum {\t\t\t\t\t\t/* Block cipher modes */\n\tCRYPT_MODE_NONE,\t\t\t\t/* No encryption mode */\n\tCRYPT_MODE_ECB,\t\t\t\t\t/* ECB */\n\tCRYPT_MODE_CBC,\t\t\t\t\t/* CBC */\n\tCRYPT_MODE_CFB,\t\t\t\t\t/* CFB */\n\tCRYPT_MODE_GCM,\t\t\t\t\t/* GCM */\n\tCRYPT_MODE_LAST\t\t\t\t\t/* Last possible crypt mode value */\n\t} CRYPT_MODE_TYPE;\n\n#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \\\n\t  defined( __WIN32__ ) ) && !defined( _SCCTK )\n  /* Force an error if wincrypt.h is included after cryptlib.h, see note at\n     the start of the file */\n  #define CRYPT_MODE_ECB\t1\n#endif /* Windows other than a cross-development environment */\n\n/* Keyset subtypes */\n\ntypedef enum {\t\t\t\t\t\t/* Keyset types */\n\tCRYPT_KEYSET_NONE,\t\t\t\t/* No keyset type */\n\tCRYPT_KEYSET_FILE,\t\t\t\t/* Generic flat file keyset */\n\tCRYPT_KEYSET_HTTP,\t\t\t\t/* Web page containing cert/CRL */\n\tCRYPT_KEYSET_LDAP,\t\t\t\t/* LDAP directory service */\n\tCRYPT_KEYSET_ODBC,\t\t\t\t/* Generic ODBC interface */\n\tCRYPT_KEYSET_DATABASE,\t\t\t/* Generic RDBMS interface */\n\tCRYPT_KEYSET_ODBC_STORE,\t\t/* ODBC certificate store */\n\tCRYPT_KEYSET_DATABASE_STORE,\t/* Database certificate store */\n\tCRYPT_KEYSET_LAST\t\t\t\t/* Last possible keyset type */\n\n#ifdef _CRYPT_DEFINED\n\t/* Useful defines used internally for range checking */\n\t, CRYPT_FIRST_RDBMS = CRYPT_KEYSET_ODBC,\n\tCRYPT_LAST_RDBMS = CRYPT_KEYSET_DATABASE_STORE\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_KEYSET_TYPE;\n\n/* Device subtypes */\n\ntypedef enum {\t\t\t\t\t\t/* Crypto device types */\n\tCRYPT_DEVICE_NONE,\t\t\t\t/* No crypto device */\n\tCRYPT_DEVICE_FORTEZZA,\t\t\t/* Fortezza card - Placeholder only */\n\tCRYPT_DEVICE_PKCS11,\t\t\t/* PKCS #11 crypto token */\n\tCRYPT_DEVICE_CRYPTOAPI,\t\t\t/* Microsoft CryptoAPI */\n\tCRYPT_DEVICE_HARDWARE,\t\t\t/* Generic crypo HW plugin */\n\tCRYPT_DEVICE_LAST\t\t\t\t/* Last possible crypto device type */\n\t} CRYPT_DEVICE_TYPE;\n\n/* Certificate subtypes */\n\ntypedef enum {\t\t\t\t\t\t/* Certificate object types */\n\tCRYPT_CERTTYPE_NONE,\t\t\t/* No certificate type */\n\tCRYPT_CERTTYPE_CERTIFICATE,\t\t/* Certificate */\n\tCRYPT_CERTTYPE_ATTRIBUTE_CERT,\t/* Attribute certificate */\n\tCRYPT_CERTTYPE_CERTCHAIN,\t\t/* PKCS #7 certificate chain */\n\tCRYPT_CERTTYPE_CERTREQUEST,\t\t/* PKCS #10 certification request */\n\tCRYPT_CERTTYPE_REQUEST_CERT,\t/* CRMF certification request */\n\tCRYPT_CERTTYPE_REQUEST_REVOCATION,\t/* CRMF revocation request */\n\tCRYPT_CERTTYPE_CRL,\t\t\t\t/* CRL */\n\tCRYPT_CERTTYPE_CMS_ATTRIBUTES,\t/* CMS attributes */\n\tCRYPT_CERTTYPE_RTCS_REQUEST,\t/* RTCS request */\n\tCRYPT_CERTTYPE_RTCS_RESPONSE,\t/* RTCS response */\n\tCRYPT_CERTTYPE_OCSP_REQUEST,\t/* OCSP request */\n\tCRYPT_CERTTYPE_OCSP_RESPONSE,\t/* OCSP response */\n\tCRYPT_CERTTYPE_PKIUSER,\t\t\t/* PKI user information */\n#ifdef _CRYPT_DEFINED\n\t/* Alongside the usual types we can also wind up with various\n\t   certificate-bagging schemes such as cert chains and sequences that\n\t   can't be exported in this format and therefore aren't visible to the\n\t   user, but that need to be distinguished internally.  The following\n\t   types are only visible internally */\n\tCRYPT_ICERTTYPE_CMS_CERTSET,\t/* CMS SET OF Certificate = cert chain */\n\tCRYPT_ICERTTYPE_SSL_CERTCHAIN,\t/* SSL certificate chain = cert chain */\n\tCRYPT_ICERTTYPE_REVINFO,\t\t/* Revocation info/single CRL entry */\n#endif /* _CRYPT_DEFINED */\n\tCRYPT_CERTTYPE_LAST\t\t\t\t/* Last possible cert.type */\n#ifdef _CRYPT_DEFINED\n\t, CRYPT_CERTTYPE_LAST_EXTERNAL = CRYPT_CERTTYPE_PKIUSER + 1\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_CERTTYPE_TYPE;\n\n/* Envelope/data format subtypes */\n\ntypedef enum {\n\tCRYPT_FORMAT_NONE,\t\t\t\t/* No format type */\n\tCRYPT_FORMAT_AUTO,\t\t\t\t/* Deenv, auto-determine type */\n\tCRYPT_FORMAT_CRYPTLIB,\t\t\t/* cryptlib native format */\n\tCRYPT_FORMAT_CMS,\t\t\t\t/* PKCS #7 / CMS / S/MIME fmt.*/\n\t\tCRYPT_FORMAT_PKCS7 = CRYPT_FORMAT_CMS,\n\tCRYPT_FORMAT_SMIME,\t\t\t\t/* As CMS with MSG-style behaviour */\n\tCRYPT_FORMAT_PGP,\t\t\t\t/* PGP format */\n#ifdef _CRYPT_DEFINED\n\t/* Alongside the usual types we can also wind up with various protocol-\n\t   specific format types such as SSL and SSH.  The following types are\n\t   only visible internally */\n\tCRYPT_IFORMAT_SSL,\t\t\t\t/* SSL/TLS format */\n\tCRYPT_IFORMAT_TLS12,\t\t\t/* TLS 1.2 format */\n\tCRYPT_IFORMAT_SSH,\t\t\t\t/* SSH format */\n#endif /* _CRYPT_DEFINED */\n\tCRYPT_FORMAT_LAST\t\t\t\t/* Last possible format type */\n#ifdef _CRYPT_DEFINED\n\t, CRYPT_FORMAT_LAST_EXTERNAL = CRYPT_FORMAT_PGP + 1\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_FORMAT_TYPE;\n\n/* Session subtypes */\n\ntypedef enum {\n\tCRYPT_SESSION_NONE,\t\t\t\t/* No session type */\n\tCRYPT_SESSION_SSH,\t\t\t\t/* SSH */\n\tCRYPT_SESSION_SSH_SERVER,\t\t/* SSH server */\n\tCRYPT_SESSION_SSL,\t\t\t\t/* SSL/TLS */\n\t\tCRYPT_SESSION_TLS = CRYPT_SESSION_SSL,\n\tCRYPT_SESSION_SSL_SERVER,\t\t/* SSL/TLS server */\n\t\tCRYPT_SESSION_TLS_SERVER = CRYPT_SESSION_SSL_SERVER,\n\tCRYPT_SESSION_RTCS,\t\t\t\t/* RTCS */\n\tCRYPT_SESSION_RTCS_SERVER,\t\t/* RTCS server */\n\tCRYPT_SESSION_OCSP,\t\t\t\t/* OCSP */\n\tCRYPT_SESSION_OCSP_SERVER,\t\t/* OCSP server */\n\tCRYPT_SESSION_TSP,\t\t\t\t/* TSP */\n\tCRYPT_SESSION_TSP_SERVER,\t\t/* TSP server */\n\tCRYPT_SESSION_CMP,\t\t\t\t/* CMP */\n\tCRYPT_SESSION_CMP_SERVER,\t\t/* CMP server */\n\tCRYPT_SESSION_SCEP,\t\t\t\t/* SCEP */\n\tCRYPT_SESSION_SCEP_SERVER,\t\t/* SCEP server */\n\tCRYPT_SESSION_CERTSTORE_SERVER,\t/* HTTP cert store interface */\n\tCRYPT_SESSION_LAST\t\t\t\t/* Last possible session type */\n\t} CRYPT_SESSION_TYPE;\n\n/* User subtypes */\n\ntypedef enum {\n\tCRYPT_USER_NONE,\t\t\t\t/* No user type */\n\tCRYPT_USER_NORMAL,\t\t\t\t/* Normal user */\n\tCRYPT_USER_SO,\t\t\t\t\t/* Security officer */\n\tCRYPT_USER_CA,\t\t\t\t\t/* CA user */\n\tCRYPT_USER_LAST\t\t\t\t\t/* Last possible user type */\n\t} CRYPT_USER_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAttribute Types\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Attribute types.  These are arranged in the following order:\n\n\tPROPERTY\t- Object property\n\tATTRIBUTE\t- Generic attributes\n\tOPTION\t\t- Global or object-specific config.option\n\tCTXINFO\t\t- Context-specific attribute\n\tCERTINFO\t- Certificate-specific attribute\n\tKEYINFO\t\t- Keyset-specific attribute\n\tDEVINFO\t\t- Device-specific attribute\n\tENVINFO\t\t- Envelope-specific attribute\n\tSESSINFO\t- Session-specific attribute\n\tUSERINFO\t- User-specific attribute */\n\ntypedef enum {\n\tCRYPT_ATTRIBUTE_NONE,\t\t\t/* Non-value */\n\n\t/* Used internally */\n\tCRYPT_PROPERTY_FIRST,\n\n\t/*********************/\n\t/* Object attributes */\n\t/*********************/\n\n\t/* Object properties */\n\tCRYPT_PROPERTY_HIGHSECURITY,\t/* Owned+non-forwardcount+locked */\n\tCRYPT_PROPERTY_OWNER,\t\t\t/* Object owner */\n\tCRYPT_PROPERTY_FORWARDCOUNT,\t/* No.of times object can be forwarded */\n\tCRYPT_PROPERTY_LOCKED,\t\t\t/* Whether properties can be chged/read */\n\tCRYPT_PROPERTY_USAGECOUNT,\t\t/* Usage count before object expires */\n\tCRYPT_PROPERTY_NONEXPORTABLE,\t/* Whether key is nonexp.from context */\n\n\t/* Used internally */\n\tCRYPT_PROPERTY_LAST, CRYPT_GENERIC_FIRST,\n\n\t/* Extended error information */\n\tCRYPT_ATTRIBUTE_ERRORTYPE,\t\t/* Type of last error */\n\tCRYPT_ATTRIBUTE_ERRORLOCUS,\t\t/* Locus of last error */\n\tCRYPT_ATTRIBUTE_ERRORMESSAGE,\t/* Detailed error description */\n\n\t/* Generic information */\n\tCRYPT_ATTRIBUTE_CURRENT_GROUP,\t/* Cursor mgt: Group in attribute list */\n\tCRYPT_ATTRIBUTE_CURRENT,\t\t/* Cursor mgt: Entry in attribute list */\n\tCRYPT_ATTRIBUTE_CURRENT_INSTANCE,\t/* Cursor mgt: Instance in attribute list */\n\tCRYPT_ATTRIBUTE_BUFFERSIZE,\t\t/* Internal data buffer size */\n\n\t/* Used internally */\n\tCRYPT_GENERIC_LAST, CRYPT_OPTION_FIRST = 100,\n\n\t/****************************/\n\t/* Configuration attributes */\n\t/****************************/\n\n\t/* cryptlib information (read-only) */\n\tCRYPT_OPTION_INFO_DESCRIPTION,\t/* Text description */\n\tCRYPT_OPTION_INFO_COPYRIGHT,\t/* Copyright notice */\n\tCRYPT_OPTION_INFO_MAJORVERSION,\t/* Major release version */\n\tCRYPT_OPTION_INFO_MINORVERSION,\t/* Minor release version */\n\tCRYPT_OPTION_INFO_STEPPING,\t\t/* Release stepping */\n\n\t/* Encryption options */\n\tCRYPT_OPTION_ENCR_ALGO,\t\t\t/* Conventional ncryption algorithm */\n\tCRYPT_OPTION_ENCR_HASH,\t\t\t/* Hash algorithm */\n\tCRYPT_OPTION_ENCR_MAC,\t\t\t/* MAC algorithm */\n\n\t/* PKC options */\n\tCRYPT_OPTION_PKC_ALGO,\t\t\t/* PKC algorithm */\n\tCRYPT_OPTION_PKC_KEYSIZE,\t\t/* PKC key size */\n\n\t/* Placeholder for obsolete options */\n\tCRYPT_OPTION_DUMMY1,\n\tCRYPT_OPTION_DUMMY2,\n\n\t/* Keying options */\n\tCRYPT_OPTION_KEYING_ALGO,\t\t/* Key processing algorithm */\n\tCRYPT_OPTION_KEYING_ITERATIONS,\t/* Key processing iterations */\n\n\t/* Certificate options */\n\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES,\t/* Whether to sign unrecog.attrs */\n\tCRYPT_OPTION_CERT_VALIDITY,\t\t/* Certificate validity period */\n\tCRYPT_OPTION_CERT_UPDATEINTERVAL,\t/* CRL update interval */\n\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\t/* PKIX compliance level for cert chks.*/\n\tCRYPT_OPTION_CERT_REQUIREPOLICY,\t/* Whether explicit policy req'd for certs */\n\n\t/* CMS/SMIME options */\n\tCRYPT_OPTION_CMS_DEFAULTATTRIBUTES,\t/* Add default CMS attributes */\n\t\tCRYPT_OPTION_SMIME_DEFAULTATTRIBUTES = CRYPT_OPTION_CMS_DEFAULTATTRIBUTES,\n\n\t/* LDAP keyset options */\n\tCRYPT_OPTION_KEYS_LDAP_OBJECTCLASS,\t/* Object class */\n\tCRYPT_OPTION_KEYS_LDAP_OBJECTTYPE,\t/* Object type to fetch */\n\tCRYPT_OPTION_KEYS_LDAP_FILTER,\t\t/* Query filter */\n\tCRYPT_OPTION_KEYS_LDAP_CACERTNAME,\t/* CA certificate attribute name */\n\tCRYPT_OPTION_KEYS_LDAP_CERTNAME,\t/* Certificate attribute name */\n\tCRYPT_OPTION_KEYS_LDAP_CRLNAME,\t\t/* CRL attribute name */\n\tCRYPT_OPTION_KEYS_LDAP_EMAILNAME,\t/* Email attribute name */\n\n\t/* Crypto device options */\n\tCRYPT_OPTION_DEVICE_PKCS11_DVR01,\t/* Name of first PKCS #11 driver */\n\tCRYPT_OPTION_DEVICE_PKCS11_DVR02,\t/* Name of second PKCS #11 driver */\n\tCRYPT_OPTION_DEVICE_PKCS11_DVR03,\t/* Name of third PKCS #11 driver */\n\tCRYPT_OPTION_DEVICE_PKCS11_DVR04,\t/* Name of fourth PKCS #11 driver */\n\tCRYPT_OPTION_DEVICE_PKCS11_DVR05,\t/* Name of fifth PKCS #11 driver */\n\tCRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY,/* Use only hardware mechanisms */\n\n\t/* Network access options */\n\tCRYPT_OPTION_NET_SOCKS_SERVER,\t\t/* Socks server name */\n\tCRYPT_OPTION_NET_SOCKS_USERNAME,\t/* Socks user name */\n\tCRYPT_OPTION_NET_HTTP_PROXY,\t\t/* Web proxy server */\n\tCRYPT_OPTION_NET_CONNECTTIMEOUT,\t/* Timeout for network connection setup */\n\tCRYPT_OPTION_NET_READTIMEOUT,\t\t/* Timeout for network reads */\n\tCRYPT_OPTION_NET_WRITETIMEOUT,\t\t/* Timeout for network writes */\n\n\t/* Miscellaneous options */\n\tCRYPT_OPTION_MISC_ASYNCINIT,\t/* Whether to init cryptlib async'ly */\n\tCRYPT_OPTION_MISC_SIDECHANNELPROTECTION, /* Protect against side-channel attacks */\n\n\t/* cryptlib state information */\n\tCRYPT_OPTION_CONFIGCHANGED,\t\t/* Whether in-mem.opts match on-disk ones */\n\tCRYPT_OPTION_SELFTESTOK,\t\t/* Whether self-test was completed and OK */\n\n\t/* Used internally */\n\tCRYPT_OPTION_LAST, CRYPT_CTXINFO_FIRST = 1000,\n\n\t/**********************/\n\t/* Context attributes */\n\t/**********************/\n\n\t/* Algorithm and mode information */\n\tCRYPT_CTXINFO_ALGO,\t\t\t\t/* Algorithm */\n\tCRYPT_CTXINFO_MODE,\t\t\t\t/* Mode */\n\tCRYPT_CTXINFO_NAME_ALGO,\t\t/* Algorithm name */\n\tCRYPT_CTXINFO_NAME_MODE,\t\t/* Mode name */\n\tCRYPT_CTXINFO_KEYSIZE,\t\t\t/* Key size in bytes */\n\tCRYPT_CTXINFO_BLOCKSIZE,\t\t/* Block size */\n\tCRYPT_CTXINFO_IVSIZE,\t\t\t/* IV size */\n\tCRYPT_CTXINFO_KEYING_ALGO,\t\t/* Key processing algorithm */\n\tCRYPT_CTXINFO_KEYING_ITERATIONS,/* Key processing iterations */\n\tCRYPT_CTXINFO_KEYING_SALT,\t\t/* Key processing salt */\n\tCRYPT_CTXINFO_KEYING_VALUE,\t\t/* Value used to derive key */\n\n\t/* State information */\n\tCRYPT_CTXINFO_KEY,\t\t\t\t/* Key */\n\tCRYPT_CTXINFO_KEY_COMPONENTS,\t/* Public-key components */\n\tCRYPT_CTXINFO_IV,\t\t\t\t/* IV */\n\tCRYPT_CTXINFO_HASHVALUE,\t\t/* Hash value */\n\n\t/* Misc.information */\n\tCRYPT_CTXINFO_LABEL,\t\t\t/* Label for private/secret key */\n\tCRYPT_CTXINFO_PERSISTENT,\t\t/* Obj.is backed by device or keyset */\n\n\t/* Used internally */\n\tCRYPT_CTXINFO_LAST, CRYPT_CERTINFO_FIRST = 2000,\n\n\t/**************************/\n\t/* Certificate attributes */\n\t/**************************/\n\n\t/* Because there are so many cert attributes, we break them down into\n\t   blocks to minimise the number of values that change if a new one is\n\t   added halfway through */\n\n\t/* Pseudo-information on a cert object or meta-information which is used\n\t   to control the way that a cert object is processed */\n\tCRYPT_CERTINFO_SELFSIGNED,\t\t/* Cert is self-signed */\n\tCRYPT_CERTINFO_IMMUTABLE,\t\t/* Cert is signed and immutable */\n\tCRYPT_CERTINFO_XYZZY,\t\t\t/* Cert is a magic just-works cert */\n\tCRYPT_CERTINFO_CERTTYPE,\t\t/* Certificate object type */\n\tCRYPT_CERTINFO_FINGERPRINT_SHA1,/* Certificate fingerprints */\n\tCRYPT_CERTINFO_FINGERPRINT_SHA2,\n\tCRYPT_CERTINFO_FINGERPRINT_SHAng,\n\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,/* Cursor mgt: Rel.pos in chain/CRL/OCSP */\n\tCRYPT_CERTINFO_TRUSTED_USAGE,\t/* Usage that cert is trusted for */\n\tCRYPT_CERTINFO_TRUSTED_IMPLICIT,/* Whether cert is implicitly trusted */\n\tCRYPT_CERTINFO_SIGNATURELEVEL,\t/* Amount of detail to include in sigs.*/\n\n\t/* General certificate object information */\n\tCRYPT_CERTINFO_VERSION,\t\t\t/* Cert.format version */\n\tCRYPT_CERTINFO_SERIALNUMBER,\t/* Serial number */\n\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\t/* Public key */\n\tCRYPT_CERTINFO_CERTIFICATE,\t\t/* User certificate */\n\t\tCRYPT_CERTINFO_USERCERTIFICATE = CRYPT_CERTINFO_CERTIFICATE,\n\tCRYPT_CERTINFO_CACERTIFICATE,\t/* CA certificate */\n\tCRYPT_CERTINFO_ISSUERNAME,\t\t/* Issuer DN */\n\tCRYPT_CERTINFO_VALIDFROM,\t\t/* Cert valid-from time */\n\tCRYPT_CERTINFO_VALIDTO,\t\t\t/* Cert valid-to time */\n\tCRYPT_CERTINFO_SUBJECTNAME,\t\t/* Subject DN */\n\tCRYPT_CERTINFO_ISSUERUNIQUEID,\t/* Issuer unique ID */\n\tCRYPT_CERTINFO_SUBJECTUNIQUEID,\t/* Subject unique ID */\n\tCRYPT_CERTINFO_CERTREQUEST,\t\t/* Cert.request (DN + public key) */\n\tCRYPT_CERTINFO_THISUPDATE,\t\t/* CRL/OCSP current-update time */\n\tCRYPT_CERTINFO_NEXTUPDATE,\t\t/* CRL/OCSP next-update time */\n\tCRYPT_CERTINFO_REVOCATIONDATE,\t/* CRL/OCSP cert-revocation time */\n\tCRYPT_CERTINFO_REVOCATIONSTATUS,/* OCSP revocation status */\n\tCRYPT_CERTINFO_CERTSTATUS,\t\t/* RTCS certificate status */\n\tCRYPT_CERTINFO_DN,\t\t\t\t/* Currently selected DN in string form */\n\tCRYPT_CERTINFO_PKIUSER_ID,\t\t/* PKI user ID */\n\tCRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\t/* PKI user issue password */\n\tCRYPT_CERTINFO_PKIUSER_REVPASSWORD,\t\t/* PKI user revocation password */\n\tCRYPT_CERTINFO_PKIUSER_RA,\t\t/* PKI user is an RA */\n\n\t/* X.520 Distinguished Name components.  This is a composite field, the\n\t   DN to be manipulated is selected through the addition of a\n\t   pseudocomponent, and then one of the following is used to access the\n\t   DN components directly */\n\tCRYPT_CERTINFO_COUNTRYNAME = CRYPT_CERTINFO_FIRST + 100,\t/* countryName */\n\tCRYPT_CERTINFO_STATEORPROVINCENAME,\t/* stateOrProvinceName */\n\tCRYPT_CERTINFO_LOCALITYNAME,\t\t/* localityName */\n\tCRYPT_CERTINFO_ORGANIZATIONNAME,\t/* organizationName */\n\t\tCRYPT_CERTINFO_ORGANISATIONNAME = CRYPT_CERTINFO_ORGANIZATIONNAME,\n\tCRYPT_CERTINFO_ORGANIZATIONALUNITNAME,\t/* organizationalUnitName */\n\t\tCRYPT_CERTINFO_ORGANISATIONALUNITNAME = CRYPT_CERTINFO_ORGANIZATIONALUNITNAME,\n\tCRYPT_CERTINFO_COMMONNAME,\t\t/* commonName */\n\n\t/* X.509 General Name components.  These are handled in the same way as\n\t   the DN composite field, with the current GeneralName being selected by\n\t   a pseudo-component after which the individual components can be\n\t   modified through one of the following */\n\tCRYPT_CERTINFO_OTHERNAME_TYPEID,\t\t/* otherName.typeID */\n\tCRYPT_CERTINFO_OTHERNAME_VALUE,\t\t\t/* otherName.value */\n\tCRYPT_CERTINFO_RFC822NAME,\t\t\t\t/* rfc822Name */\n\t\tCRYPT_CERTINFO_EMAIL = CRYPT_CERTINFO_RFC822NAME,\n\tCRYPT_CERTINFO_DNSNAME,\t\t\t\t\t/* dNSName */\n#if 0\t/* Not supported, these are never used in practice and have an\n\t\t   insane internal structure */\n\tCRYPT_CERTINFO_X400ADDRESS,\t\t\t\t/* x400Address */\n#endif /* 0 */\n\tCRYPT_CERTINFO_DIRECTORYNAME,\t\t\t/* directoryName */\n\tCRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER,\t/* ediPartyName.nameAssigner */\n\tCRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME,\t/* ediPartyName.partyName */\n\tCRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\t/* uniformResourceIdentifier */\n\t\tCRYPT_CERTINFO_URL = CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\tCRYPT_CERTINFO_IPADDRESS,\t\t\t\t/* iPAddress */\n\tCRYPT_CERTINFO_REGISTEREDID,\t\t\t/* registeredID */\n\n\t/* X.509 certificate extensions.  Although it would be nicer to use names\n\t   that match the extensions more closely (e.g.\n\t   CRYPT_CERTINFO_BASICCONSTRAINTS_PATHLENCONSTRAINT), these exceed the\n\t   32-character ANSI minimum length for unique names, and get really\n\t   hairy once you get into the weird policy constraints extensions whose\n\t   names wrap around the screen about three times.\n\n\t   The following values are defined in OID order, this isn't absolutely\n\t   necessary but saves an extra layer of processing when encoding them */\n\n\t/* 1 2 840 113549 1 9 7 challengePassword.  This is here even though it's\n\t   a CMS attribute because SCEP stuffs it into PKCS #10 requests */\n\tCRYPT_CERTINFO_CHALLENGEPASSWORD = CRYPT_CERTINFO_FIRST + 200,\n\n\t/* 1 3 6 1 4 1 3029 3 1 4 cRLExtReason */\n\tCRYPT_CERTINFO_CRLEXTREASON,\n\n\t/* 1 3 6 1 4 1 3029 3 1 5 keyFeatures */\n\tCRYPT_CERTINFO_KEYFEATURES,\n\n\t/* 1 3 6 1 5 5 7 1 1 authorityInfoAccess */\n\tCRYPT_CERTINFO_AUTHORITYINFOACCESS,\n\tCRYPT_CERTINFO_AUTHORITYINFO_RTCS,\t\t/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_AUTHORITYINFO_OCSP,\t\t/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS,\t/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE,\t/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_AUTHORITYINFO_CRLS,\t\t/* accessDescription.accessLocation */\n\n\t/* 1 3 6 1 5 5 7 1 2 biometricInfo */\n\tCRYPT_CERTINFO_BIOMETRICINFO,\n\tCRYPT_CERTINFO_BIOMETRICINFO_TYPE,\t\t/* biometricData.typeOfData */\n\tCRYPT_CERTINFO_BIOMETRICINFO_HASHALGO,\t/* biometricData.hashAlgorithm */\n\tCRYPT_CERTINFO_BIOMETRICINFO_HASH,\t\t/* biometricData.dataHash */\n\tCRYPT_CERTINFO_BIOMETRICINFO_URL,\t\t/* biometricData.sourceDataUri */\n\n\t/* 1 3 6 1 5 5 7 1 3 qcStatements */\n\tCRYPT_CERTINFO_QCSTATEMENT,\n\tCRYPT_CERTINFO_QCSTATEMENT_SEMANTICS,\n\t\t\t\t\t/* qcStatement.statementInfo.semanticsIdentifier */\n\tCRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY,\n\t\t\t\t\t/* qcStatement.statementInfo.nameRegistrationAuthorities */\n\n\t/* 1 3 6 1 5 5 7 1 7 ipAddrBlocks */\n\tCRYPT_CERTINFO_IPADDRESSBLOCKS,\n\tCRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY,\t/* addressFamily */\n/*\tCRYPT_CERTINFO_IPADDRESSBLOCKS_INHERIT,\t// ipAddress.inherit */\n\tCRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX,\t/* ipAddress.addressPrefix */\n\tCRYPT_CERTINFO_IPADDRESSBLOCKS_MIN,\t\t/* ipAddress.addressRangeMin */\n\tCRYPT_CERTINFO_IPADDRESSBLOCKS_MAX,\t\t/* ipAddress.addressRangeMax */\n\n\t/* 1 3 6 1 5 5 7 1 8 autonomousSysIds */\n\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS,\n/*\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_INHERIT,// asNum.inherit */\n\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID,\t/* asNum.id */\n\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN,\t/* asNum.min */\n\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX,\t/* asNum.max */\n\n\t/* 1 3 6 1 5 5 7 48 1 2 ocspNonce */\n\tCRYPT_CERTINFO_OCSP_NONCE,\t\t\t\t/* nonce */\n\n\t/* 1 3 6 1 5 5 7 48 1 4 ocspAcceptableResponses */\n\tCRYPT_CERTINFO_OCSP_RESPONSE,\n\tCRYPT_CERTINFO_OCSP_RESPONSE_OCSP,\t\t/* OCSP standard response */\n\n\t/* 1 3 6 1 5 5 7 48 1 5 ocspNoCheck */\n\tCRYPT_CERTINFO_OCSP_NOCHECK,\n\n\t/* 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff */\n\tCRYPT_CERTINFO_OCSP_ARCHIVECUTOFF,\n\n\t/* 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess */\n\tCRYPT_CERTINFO_SUBJECTINFOACCESS,\n\tCRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING,/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY,/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY,/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST,/* accessDescription.accessLocation */\n\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT,/* accessDescription.accessLocation */\n\n\t/* 1 3 36 8 3 1 siggDateOfCertGen */\n\tCRYPT_CERTINFO_SIGG_DATEOFCERTGEN,\n\n\t/* 1 3 36 8 3 2 siggProcuration */\n\tCRYPT_CERTINFO_SIGG_PROCURATION,\n\tCRYPT_CERTINFO_SIGG_PROCURE_COUNTRY,\t/* country */\n\tCRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION,\t/* typeOfSubstitution */\n\tCRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR,\t/* signingFor.thirdPerson */\n\n\t/* 1 3 36 8 3 3 siggAdmissions */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS,\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY,\t/* authority */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID,\t/* namingAuth.iD */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL,\t/* namingAuth.uRL */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT,\t/* namingAuth.text */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM,\t/* professionItem */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID,\t/* professionOID */\n\tCRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER,\t/* registrationNumber */\n\n\t/* 1 3 36 8 3 4 siggMonetaryLimit */\n\tCRYPT_CERTINFO_SIGG_MONETARYLIMIT,\n\tCRYPT_CERTINFO_SIGG_MONETARY_CURRENCY,\t/* currency */\n\tCRYPT_CERTINFO_SIGG_MONETARY_AMOUNT,\t/* amount */\n\tCRYPT_CERTINFO_SIGG_MONETARY_EXPONENT,\t/* exponent */\n\n\t/* 1 3 36 8 3 5 siggDeclarationOfMajority */\n\tCRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY,\n\tCRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY,\t/* fullAgeAtCountry */\n\n\t/* 1 3 36 8 3 8 siggRestriction */\n\tCRYPT_CERTINFO_SIGG_RESTRICTION,\n\n\t/* 1 3 36 8 3 13 siggCertHash */\n\tCRYPT_CERTINFO_SIGG_CERTHASH,\n\n\t/* 1 3 36 8 3 15 siggAdditionalInformation */\n\tCRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION,\n\n\t/* 1 3 101 1 4 1 strongExtranet */\n\tCRYPT_CERTINFO_STRONGEXTRANET,\n\tCRYPT_CERTINFO_STRONGEXTRANET_ZONE,\t\t/* sxNetIDList.sxNetID.zone */\n\tCRYPT_CERTINFO_STRONGEXTRANET_ID,\t\t/* sxNetIDList.sxNetID.id */\n\n\t/* 2 5 29 9 subjectDirectoryAttributes */\n\tCRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES,\n\tCRYPT_CERTINFO_SUBJECTDIR_TYPE,\t\t\t/* attribute.type */\n\tCRYPT_CERTINFO_SUBJECTDIR_VALUES,\t\t/* attribute.values */\n\n\t/* 2 5 29 14 subjectKeyIdentifier */\n\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\n\t/* 2 5 29 15 keyUsage */\n\tCRYPT_CERTINFO_KEYUSAGE,\n\n\t/* 2 5 29 16 privateKeyUsagePeriod */\n\tCRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD,\n\tCRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE,\t/* notBefore */\n\tCRYPT_CERTINFO_PRIVATEKEY_NOTAFTER,\t\t/* notAfter */\n\n\t/* 2 5 29 17 subjectAltName */\n\tCRYPT_CERTINFO_SUBJECTALTNAME,\n\n\t/* 2 5 29 18 issuerAltName */\n\tCRYPT_CERTINFO_ISSUERALTNAME,\n\n\t/* 2 5 29 19 basicConstraints */\n\tCRYPT_CERTINFO_BASICCONSTRAINTS,\n\tCRYPT_CERTINFO_CA,\t\t\t\t\t\t/* cA */\n\t\tCRYPT_CERTINFO_AUTHORITY = CRYPT_CERTINFO_CA,\n\tCRYPT_CERTINFO_PATHLENCONSTRAINT,\t\t/* pathLenConstraint */\n\n\t/* 2 5 29 20 cRLNumber */\n\tCRYPT_CERTINFO_CRLNUMBER,\n\n\t/* 2 5 29 21 cRLReason */\n\tCRYPT_CERTINFO_CRLREASON,\n\n\t/* 2 5 29 23 holdInstructionCode */\n\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE,\n\n\t/* 2 5 29 24 invalidityDate */\n\tCRYPT_CERTINFO_INVALIDITYDATE,\n\n\t/* 2 5 29 27 deltaCRLIndicator */\n\tCRYPT_CERTINFO_DELTACRLINDICATOR,\n\n\t/* 2 5 29 28 issuingDistributionPoint */\n\tCRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT,\n\tCRYPT_CERTINFO_ISSUINGDIST_FULLNAME,\t/* distributionPointName.fullName */\n\tCRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY,\t/* onlyContainsUserCerts */\n\tCRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY,\t/* onlyContainsCACerts */\n\tCRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY,\t/* onlySomeReasons */\n\tCRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL,\t/* indirectCRL */\n\n\t/* 2 5 29 29 certificateIssuer */\n\tCRYPT_CERTINFO_CERTIFICATEISSUER,\n\n\t/* 2 5 29 30 nameConstraints */\n\tCRYPT_CERTINFO_NAMECONSTRAINTS,\n\tCRYPT_CERTINFO_PERMITTEDSUBTREES,\t\t/* permittedSubtrees */\n\tCRYPT_CERTINFO_EXCLUDEDSUBTREES,\t\t/* excludedSubtrees */\n\n\t/* 2 5 29 31 cRLDistributionPoint */\n\tCRYPT_CERTINFO_CRLDISTRIBUTIONPOINT,\n\tCRYPT_CERTINFO_CRLDIST_FULLNAME,\t\t/* distributionPointName.fullName */\n\tCRYPT_CERTINFO_CRLDIST_REASONS,\t\t\t/* reasons */\n\tCRYPT_CERTINFO_CRLDIST_CRLISSUER,\t\t/* cRLIssuer */\n\n\t/* 2 5 29 32 certificatePolicies */\n\tCRYPT_CERTINFO_CERTIFICATEPOLICIES,\n\tCRYPT_CERTINFO_CERTPOLICYID,\t\t/* policyInformation.policyIdentifier */\n\tCRYPT_CERTINFO_CERTPOLICY_CPSURI,\n\t\t/* policyInformation.policyQualifiers.qualifier.cPSuri */\n\tCRYPT_CERTINFO_CERTPOLICY_ORGANIZATION,\n\t\t/* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization */\n\tCRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS,\n\t\t/* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers */\n\tCRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT,\n\t\t/* policyInformation.policyQualifiers.qualifier.userNotice.explicitText */\n\n\t/* 2 5 29 33 policyMappings */\n\tCRYPT_CERTINFO_POLICYMAPPINGS,\n\tCRYPT_CERTINFO_ISSUERDOMAINPOLICY,\t/* policyMappings.issuerDomainPolicy */\n\tCRYPT_CERTINFO_SUBJECTDOMAINPOLICY,\t/* policyMappings.subjectDomainPolicy */\n\n\t/* 2 5 29 35 authorityKeyIdentifier */\n\tCRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER,\n\tCRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER,\t/* keyIdentifier */\n\tCRYPT_CERTINFO_AUTHORITY_CERTISSUER,\t/* authorityCertIssuer */\n\tCRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER,\t/* authorityCertSerialNumber */\n\n\t/* 2 5 29 36 policyConstraints */\n\tCRYPT_CERTINFO_POLICYCONSTRAINTS,\n\tCRYPT_CERTINFO_REQUIREEXPLICITPOLICY,\t/* policyConstraints.requireExplicitPolicy */\n\tCRYPT_CERTINFO_INHIBITPOLICYMAPPING,\t/* policyConstraints.inhibitPolicyMapping */\n\n\t/* 2 5 29 37 extKeyUsage */\n\tCRYPT_CERTINFO_EXTKEYUSAGE,\n\tCRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,\t/* individualCodeSigning */\n\tCRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,\t/* commercialCodeSigning */\n\tCRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,\t/* certTrustListSigning */\n\tCRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING,\t/* timeStampSigning */\n\tCRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO,\t/* serverGatedCrypto */\n\tCRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM,\t/* encrypedFileSystem */\n\tCRYPT_CERTINFO_EXTKEY_SERVERAUTH,\t\t/* serverAuth */\n\tCRYPT_CERTINFO_EXTKEY_CLIENTAUTH,\t\t/* clientAuth */\n\tCRYPT_CERTINFO_EXTKEY_CODESIGNING,\t\t/* codeSigning */\n\tCRYPT_CERTINFO_EXTKEY_EMAILPROTECTION,\t/* emailProtection */\n\tCRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM,\t/* ipsecEndSystem */\n\tCRYPT_CERTINFO_EXTKEY_IPSECTUNNEL,\t\t/* ipsecTunnel */\n\tCRYPT_CERTINFO_EXTKEY_IPSECUSER,\t\t/* ipsecUser */\n\tCRYPT_CERTINFO_EXTKEY_TIMESTAMPING,\t\t/* timeStamping */\n\tCRYPT_CERTINFO_EXTKEY_OCSPSIGNING,\t\t/* ocspSigning */\n\tCRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE,\t/* directoryService */\n\tCRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE,\t\t/* anyExtendedKeyUsage */\n\tCRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO,\t/* serverGatedCrypto */\n\tCRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,\t/* serverGatedCrypto CA */\n\t\tCRYPT_CERTINFO_EXTKEYUSAGE_LAST = CRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,\n\n\t/* 2 5 29 40 crlStreamIdentifier */\n\tCRYPT_CERTINFO_CRLSTREAMIDENTIFIER,\n\n\t/* 2 5 29 46 freshestCRL */\n\tCRYPT_CERTINFO_FRESHESTCRL,\n\tCRYPT_CERTINFO_FRESHESTCRL_FULLNAME,\t/* distributionPointName.fullName */\n\tCRYPT_CERTINFO_FRESHESTCRL_REASONS,\t\t/* reasons */\n\tCRYPT_CERTINFO_FRESHESTCRL_CRLISSUER,\t/* cRLIssuer */\n\n\t/* 2 5 29 47 orderedList */\n\tCRYPT_CERTINFO_ORDEREDLIST,\n\n\t/* 2 5 29 51 baseUpdateTime */\n\tCRYPT_CERTINFO_BASEUPDATETIME,\n\n\t/* 2 5 29 53 deltaInfo */\n\tCRYPT_CERTINFO_DELTAINFO,\n\tCRYPT_CERTINFO_DELTAINFO_LOCATION,\t\t/* deltaLocation */\n\tCRYPT_CERTINFO_DELTAINFO_NEXTDELTA,\t\t/* nextDelta */\n\n\t/* 2 5 29 54 inhibitAnyPolicy */\n\tCRYPT_CERTINFO_INHIBITANYPOLICY,\n\n\t/* 2 5 29 58 toBeRevoked */\n\tCRYPT_CERTINFO_TOBEREVOKED,\n\tCRYPT_CERTINFO_TOBEREVOKED_CERTISSUER,\t/* certificateIssuer */\n\tCRYPT_CERTINFO_TOBEREVOKED_REASONCODE,\t/* reasonCode */\n\tCRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME,\t/* revocationTime */\n\tCRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER,/* certSerialNumber */\n\n\t/* 2 5 29 59 revokedGroups */\n\tCRYPT_CERTINFO_REVOKEDGROUPS,\n\tCRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER,/* certificateIssuer */\n\tCRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE,/* reasonCode */\n\tCRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE,/* invalidityDate */\n\tCRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER,/* startingNumber */\n\tCRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER,\t/* endingNumber */\n\n\t/* 2 5 29 60 expiredCertsOnCRL */\n\tCRYPT_CERTINFO_EXPIREDCERTSONCRL,\n\n\t/* 2 5 29 63 aaIssuingDistributionPoint */\n\tCRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT,\n\tCRYPT_CERTINFO_AAISSUINGDIST_FULLNAME,\t/* distributionPointName.fullName */\n\tCRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY,/* onlySomeReasons */\n\tCRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL,\t/* indirectCRL */\n\tCRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS,\t/* containsUserAttributeCerts */\n\tCRYPT_CERTINFO_AAISSUINGDIST_AACERTS,\t/* containsAACerts */\n\tCRYPT_CERTINFO_AAISSUINGDIST_SOACERTS,\t/* containsSOAPublicKeyCerts */\n\n\t/* 2 16 840 1 113730 1 x Netscape extensions */\n\tCRYPT_CERTINFO_NS_CERTTYPE,\t\t\t\t/* netscape-cert-type */\n\tCRYPT_CERTINFO_NS_BASEURL,\t\t\t\t/* netscape-base-url */\n\tCRYPT_CERTINFO_NS_REVOCATIONURL,\t\t/* netscape-revocation-url */\n\tCRYPT_CERTINFO_NS_CAREVOCATIONURL,\t\t/* netscape-ca-revocation-url */\n\tCRYPT_CERTINFO_NS_CERTRENEWALURL,\t\t/* netscape-cert-renewal-url */\n\tCRYPT_CERTINFO_NS_CAPOLICYURL,\t\t\t/* netscape-ca-policy-url */\n\tCRYPT_CERTINFO_NS_SSLSERVERNAME,\t\t/* netscape-ssl-server-name */\n\tCRYPT_CERTINFO_NS_COMMENT,\t\t\t\t/* netscape-comment */\n\n\t/* 2 23 42 7 0 SET hashedRootKey */\n\tCRYPT_CERTINFO_SET_HASHEDROOTKEY,\n\tCRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT,\t/* rootKeyThumbPrint */\n\n\t/* 2 23 42 7 1 SET certificateType */\n\tCRYPT_CERTINFO_SET_CERTIFICATETYPE,\n\n\t/* 2 23 42 7 2 SET merchantData */\n\tCRYPT_CERTINFO_SET_MERCHANTDATA,\n\tCRYPT_CERTINFO_SET_MERID,\t\t\t\t/* merID */\n\tCRYPT_CERTINFO_SET_MERACQUIRERBIN,\t\t/* merAcquirerBIN */\n\tCRYPT_CERTINFO_SET_MERCHANTLANGUAGE,\t/* merNames.language */\n\tCRYPT_CERTINFO_SET_MERCHANTNAME,\t\t/* merNames.name */\n\tCRYPT_CERTINFO_SET_MERCHANTCITY,\t\t/* merNames.city */\n\tCRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE,/* merNames.stateProvince */\n\tCRYPT_CERTINFO_SET_MERCHANTPOSTALCODE,\t/* merNames.postalCode */\n\tCRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME,\t/* merNames.countryName */\n\tCRYPT_CERTINFO_SET_MERCOUNTRY,\t\t\t/* merCountry */\n\tCRYPT_CERTINFO_SET_MERAUTHFLAG,\t\t\t/* merAuthFlag */\n\n\t/* 2 23 42 7 3 SET certCardRequired */\n\tCRYPT_CERTINFO_SET_CERTCARDREQUIRED,\n\n\t/* 2 23 42 7 4 SET tunneling */\n\tCRYPT_CERTINFO_SET_TUNNELING,\n\t\tCRYPT_CERTINFO_SET_TUNNELLING = CRYPT_CERTINFO_SET_TUNNELING,\n\tCRYPT_CERTINFO_SET_TUNNELINGFLAG,\t\t/* tunneling */\n\t\tCRYPT_CERTINFO_SET_TUNNELLINGFLAG = CRYPT_CERTINFO_SET_TUNNELINGFLAG,\n\tCRYPT_CERTINFO_SET_TUNNELINGALGID,\t\t/* tunnelingAlgID */\n\t\tCRYPT_CERTINFO_SET_TUNNELLINGALGID = CRYPT_CERTINFO_SET_TUNNELINGALGID,\n\n\t/* S/MIME attributes */\n\n\t/* 1 2 840 113549 1 9 3 contentType */\n\tCRYPT_CERTINFO_CMS_CONTENTTYPE = CRYPT_CERTINFO_FIRST + 500,\n\n\t/* 1 2 840 113549 1 9 4 messageDigest */\n\tCRYPT_CERTINFO_CMS_MESSAGEDIGEST,\n\n\t/* 1 2 840 113549 1 9 5 signingTime */\n\tCRYPT_CERTINFO_CMS_SIGNINGTIME,\n\n\t/* 1 2 840 113549 1 9 6 counterSignature */\n\tCRYPT_CERTINFO_CMS_COUNTERSIGNATURE,\t/* counterSignature */\n\n\t/* 1 2 840 113549 1 9 13 signingDescription */\n\tCRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION,\n\n\t/* 1 2 840 113549 1 9 15 sMIMECapabilities */\n\tCRYPT_CERTINFO_CMS_SMIMECAPABILITIES,\n\tCRYPT_CERTINFO_CMS_SMIMECAP_3DES,\t\t/* 3DES encryption */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_AES,\t\t/* AES encryption */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_CAST128,\t/* CAST-128 encryption */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_SHAng,\t\t/* SHA2-ng hash */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_SHA2,\t\t/* SHA2-256 hash */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_SHA1,\t\t/* SHA1 hash */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng,\t/* HMAC-SHA2-ng MAC */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2,\t/* HMAC-SHA2-256 MAC */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1,\t/* HMAC-SHA1 MAC */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256,\t/* AuthEnc w.256-bit key */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128,\t/* AuthEnc w.128-bit key */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng,\t/* RSA with SHA-ng signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2,\t/* RSA with SHA2-256 signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1,\t/* RSA with SHA1 signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1,\t/* DSA with SHA-1 signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng,/* ECDSA with SHA-ng signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2,\t/* ECDSA with SHA2-256 signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1,\t/* ECDSA with SHA-1 signing */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA,\t/* preferSignedData */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY,\t/* canNotDecryptAny */\n\tCRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE,\t/* preferBinaryInside */\n\n\t/* 1 2 840 113549 1 9 16 2 1 receiptRequest */\n\tCRYPT_CERTINFO_CMS_RECEIPTREQUEST,\n\tCRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER, /* contentIdentifier */\n\tCRYPT_CERTINFO_CMS_RECEIPT_FROM,\t\t/* receiptsFrom */\n\tCRYPT_CERTINFO_CMS_RECEIPT_TO,\t\t\t/* receiptsTo */\n\n\t/* 1 2 840 113549 1 9 16 2 2 essSecurityLabel */\n\tCRYPT_CERTINFO_CMS_SECURITYLABEL,\n\tCRYPT_CERTINFO_CMS_SECLABEL_POLICY,\t\t/* securityPolicyIdentifier */\n\tCRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION, /* securityClassification */\n\tCRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK,/* privacyMark */\n\tCRYPT_CERTINFO_CMS_SECLABEL_CATTYPE,\t/* securityCategories.securityCategory.type */\n\tCRYPT_CERTINFO_CMS_SECLABEL_CATVALUE,\t/* securityCategories.securityCategory.value */\n\n\t/* 1 2 840 113549 1 9 16 2 3 mlExpansionHistory */\n\tCRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY,\n\tCRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER, /* mlData.mailListIdentifier.issuerAndSerialNumber */\n\tCRYPT_CERTINFO_CMS_MLEXP_TIME,\t\t\t/* mlData.expansionTime */\n\tCRYPT_CERTINFO_CMS_MLEXP_NONE,\t\t\t/* mlData.mlReceiptPolicy.none */\n\tCRYPT_CERTINFO_CMS_MLEXP_INSTEADOF,\t\t/* mlData.mlReceiptPolicy.insteadOf.generalNames.generalName */\n\tCRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO,\t/* mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName */\n\n\t/* 1 2 840 113549 1 9 16 2 4 contentHints */\n\tCRYPT_CERTINFO_CMS_CONTENTHINTS,\n\tCRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION,\t/* contentDescription */\n\tCRYPT_CERTINFO_CMS_CONTENTHINT_TYPE,\t/* contentType */\n\n\t/* 1 2 840 113549 1 9 16 2 9 equivalentLabels */\n\tCRYPT_CERTINFO_CMS_EQUIVALENTLABEL,\n\tCRYPT_CERTINFO_CMS_EQVLABEL_POLICY,\t\t/* securityPolicyIdentifier */\n\tCRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION, /* securityClassification */\n\tCRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK,/* privacyMark */\n\tCRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE,\t/* securityCategories.securityCategory.type */\n\tCRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE,\t/* securityCategories.securityCategory.value */\n\n\t/* 1 2 840 113549 1 9 16 2 12 signingCertificate */\n\tCRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE,\n\tCRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID, /* certs.essCertID */\n\tCRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES,/* policies.policyInformation.policyIdentifier */\n\n\t/* 1 2 840 113549 1 9 16 2 47 signingCertificateV2 */\n\tCRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2,\n\tCRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2, /* certs.essCertID */\n\tCRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES,/* policies.policyInformation.policyIdentifier */\n\n\t/* 1 2 840 113549 1 9 16 2 15 signaturePolicyID */\n\tCRYPT_CERTINFO_CMS_SIGNATUREPOLICYID,\n\tCRYPT_CERTINFO_CMS_SIGPOLICYID,\t\t\t/* sigPolicyID */\n\tCRYPT_CERTINFO_CMS_SIGPOLICYHASH,\t\t/* sigPolicyHash */\n\tCRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI,\t/* sigPolicyQualifiers.sigPolicyQualifier.cPSuri */\n\tCRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION,\n\t\t/* sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization */\n\tCRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS,\n\t\t/* sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers */\n\tCRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT,\n\t\t/* sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText */\n\n\t/* 1 2 840 113549 1 9 16 9 signatureTypeIdentifier */\n\tCRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER,\n\tCRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG, /* originatorSig */\n\tCRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG,\t/* domainSig */\n\tCRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES, /* additionalAttributesSig */\n\tCRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG,\t/* reviewSig */\n\n\t/* 1 2 840 113549 1 9 25 3 randomNonce */\n\tCRYPT_CERTINFO_CMS_NONCE,\t\t\t\t/* randomNonce */\n\n\t/* SCEP attributes:\n\t   2 16 840 1 113733 1 9 2 messageType\n\t   2 16 840 1 113733 1 9 3 pkiStatus\n\t   2 16 840 1 113733 1 9 4 failInfo\n\t   2 16 840 1 113733 1 9 5 senderNonce\n\t   2 16 840 1 113733 1 9 6 recipientNonce\n\t   2 16 840 1 113733 1 9 7 transID */\n\tCRYPT_CERTINFO_SCEP_MESSAGETYPE,\t\t/* messageType */\n\tCRYPT_CERTINFO_SCEP_PKISTATUS,\t\t\t/* pkiStatus */\n\tCRYPT_CERTINFO_SCEP_FAILINFO,\t\t\t/* failInfo */\n\tCRYPT_CERTINFO_SCEP_SENDERNONCE,\t\t/* senderNonce */\n\tCRYPT_CERTINFO_SCEP_RECIPIENTNONCE,\t\t/* recipientNonce */\n\tCRYPT_CERTINFO_SCEP_TRANSACTIONID,\t\t/* transID */\n\n\t/* 1 3 6 1 4 1 311 2 1 10 spcAgencyInfo */\n\tCRYPT_CERTINFO_CMS_SPCAGENCYINFO,\n\tCRYPT_CERTINFO_CMS_SPCAGENCYURL,\t\t/* spcAgencyInfo.url */\n\n\t/* 1 3 6 1 4 1 311 2 1 11 spcStatementType */\n\tCRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE,\n\tCRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING,\t/* individualCodeSigning */\n\tCRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING,\t/* commercialCodeSigning */\n\n\t/* 1 3 6 1 4 1 311 2 1 12 spcOpusInfo */\n\tCRYPT_CERTINFO_CMS_SPCOPUSINFO,\n\tCRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME,\t/* spcOpusInfo.name */\n\tCRYPT_CERTINFO_CMS_SPCOPUSINFO_URL,\t\t/* spcOpusInfo.url */\n\n\t/* Used internally */\n\tCRYPT_CERTINFO_LAST, CRYPT_KEYINFO_FIRST = 3000,\n\n\t/*********************/\n\t/* Keyset attributes */\n\t/*********************/\n\n\tCRYPT_KEYINFO_QUERY,\t\t\t/* Keyset query */\n\tCRYPT_KEYINFO_QUERY_REQUESTS,\t/* Query of requests in cert store */\n\n\t/* Used internally */\n\tCRYPT_KEYINFO_LAST, CRYPT_DEVINFO_FIRST = 4000,\n\n\t/*********************/\n\t/* Device attributes */\n\t/*********************/\n\n\tCRYPT_DEVINFO_INITIALISE,\t/* Initialise device for use */\n\t\tCRYPT_DEVINFO_INITIALIZE = CRYPT_DEVINFO_INITIALISE,\n\tCRYPT_DEVINFO_AUTHENT_USER,\t/* Authenticate user to device */\n\tCRYPT_DEVINFO_AUTHENT_SUPERVISOR,\t/* Authenticate supervisor to dev.*/\n\tCRYPT_DEVINFO_SET_AUTHENT_USER,\t/* Set user authent.value */\n\tCRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR,\t/* Set supervisor auth.val.*/\n\tCRYPT_DEVINFO_ZEROISE,\t/* Zeroise device */\n\t\tCRYPT_DEVINFO_ZEROIZE = CRYPT_DEVINFO_ZEROISE,\n\tCRYPT_DEVINFO_LOGGEDIN,\t\t/* Whether user is logged in */\n\tCRYPT_DEVINFO_LABEL,\t\t/* Device/token label */\n\n\t/* Used internally */\n\tCRYPT_DEVINFO_LAST, CRYPT_ENVINFO_FIRST = 5000,\n\n\t/***********************/\n\t/* Envelope attributes */\n\t/***********************/\n\n\t/* Pseudo-information on an envelope or meta-information which is used to\n\t   control the way that data in an envelope is processed */\n\tCRYPT_ENVINFO_DATASIZE,\t\t\t/* Data size information */\n\tCRYPT_ENVINFO_COMPRESSION,\t\t/* Compression information */\n\tCRYPT_ENVINFO_CONTENTTYPE,\t\t/* Inner CMS content type */\n\tCRYPT_ENVINFO_DETACHEDSIGNATURE,/* Detached signature */\n\tCRYPT_ENVINFO_SIGNATURE_RESULT,\t/* Signature check result */\n\tCRYPT_ENVINFO_INTEGRITY,\t\t/* Integrity-protection level */\n\n\t/* Resources required for enveloping/deenveloping */\n\tCRYPT_ENVINFO_PASSWORD,\t\t\t/* User password */\n\tCRYPT_ENVINFO_KEY,\t\t\t\t/* Conventional encryption key */\n\tCRYPT_ENVINFO_SIGNATURE,\t\t/* Signature/signature check key */\n\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA,\t/* Extra information added to CMS sigs */\n\tCRYPT_ENVINFO_RECIPIENT,\t\t/* Recipient email address */\n\tCRYPT_ENVINFO_PUBLICKEY,\t\t/* PKC encryption key */\n\tCRYPT_ENVINFO_PRIVATEKEY,\t\t/* PKC decryption key */\n\tCRYPT_ENVINFO_PRIVATEKEY_LABEL,\t/* Label of PKC decryption key */\n\tCRYPT_ENVINFO_ORIGINATOR,\t\t/* Originator info/key */\n\tCRYPT_ENVINFO_SESSIONKEY,\t\t/* Session key */\n\tCRYPT_ENVINFO_HASH,\t\t\t\t/* Hash value */\n\tCRYPT_ENVINFO_TIMESTAMP,\t\t/* Timestamp information */\n\n\t/* Keysets used to retrieve keys needed for enveloping/deenveloping */\n\tCRYPT_ENVINFO_KEYSET_SIGCHECK,\t/* Signature check keyset */\n\tCRYPT_ENVINFO_KEYSET_ENCRYPT,\t/* PKC encryption keyset */\n\tCRYPT_ENVINFO_KEYSET_DECRYPT,\t/* PKC decryption keyset */\n\n\t/* Used internally */\n\tCRYPT_ENVINFO_LAST, CRYPT_SESSINFO_FIRST = 6000,\n\n\t/**********************/\n\t/* Session attributes */\n\t/**********************/\n\n\t/* Pseudo-information about the session */\n\tCRYPT_SESSINFO_ACTIVE,\t\t\t/* Whether session is active */\n\tCRYPT_SESSINFO_CONNECTIONACTIVE,/* Whether network connection is active */\n\n\t/* Security-related information */\n\tCRYPT_SESSINFO_USERNAME,\t\t/* User name */\n\tCRYPT_SESSINFO_PASSWORD,\t\t/* Password */\n\tCRYPT_SESSINFO_PRIVATEKEY,\t\t/* Server/client private key */\n\tCRYPT_SESSINFO_KEYSET,\t\t\t/* Certificate store */\n\tCRYPT_SESSINFO_AUTHRESPONSE,\t/* Session authorisation OK */\n\n\t/* Client/server information */\n\tCRYPT_SESSINFO_SERVER_NAME,\t\t/* Server name */\n\tCRYPT_SESSINFO_SERVER_PORT,\t\t/* Server port number */\n\tCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,/* Server key fingerprint */\n\tCRYPT_SESSINFO_CLIENT_NAME,\t\t/* Client name */\n\tCRYPT_SESSINFO_CLIENT_PORT,\t\t/* Client port number */\n\tCRYPT_SESSINFO_SESSION,\t\t\t/* Transport mechanism */\n\tCRYPT_SESSINFO_NETWORKSOCKET,\t/* User-supplied network socket */\n\n\t/* Generic protocol-related information */\n\tCRYPT_SESSINFO_VERSION,\t\t\t/* Protocol version */\n\tCRYPT_SESSINFO_REQUEST,\t\t\t/* Cert.request object */\n\tCRYPT_SESSINFO_RESPONSE,\t\t/* Cert.response object */\n\tCRYPT_SESSINFO_CACERTIFICATE,\t/* Issuing CA certificate */\n\n\t/* Protocol-specific information */\n\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\t/* Request type */\n\tCRYPT_SESSINFO_CMP_PRIVKEYSET,\t/* Private-key keyset */\n\tCRYPT_SESSINFO_SSH_CHANNEL,\t\t/* SSH current channel */\n\tCRYPT_SESSINFO_SSH_CHANNEL_TYPE,/* SSH channel type */\n\tCRYPT_SESSINFO_SSH_CHANNEL_ARG1,/* SSH channel argument 1 */\n\tCRYPT_SESSINFO_SSH_CHANNEL_ARG2,/* SSH channel argument 2 */\n\tCRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,/* SSH channel active */\n\tCRYPT_SESSINFO_SSL_OPTIONS,\t\t/* SSL/TLS protocol options */\n\tCRYPT_SESSINFO_SSL_SUBPROTOCOL,\t/* SSL/TLS additional sub-protocol */\n\tCRYPT_SESSINFO_SSL_WSPROTOCOL,\t/* SSL/TLS WebSockets sub-protocol */\n\tCRYPT_SESSINFO_SSL_EAPCHALLENGE,/* SSL/TLS EAP challenge */\n\tCRYPT_SESSINFO_SSL_EAPKEY,\t\t/* SSL/TLS EAP key */\n\tCRYPT_SESSINFO_TSP_MSGIMPRINT,\t/* TSP message imprint */\n\n\t/* Used internally */\n\tCRYPT_SESSINFO_LAST, CRYPT_USERINFO_FIRST = 7000,\n\n\t/**********************/\n\t/* User attributes */\n\t/**********************/\n\n\t/* Security-related information */\n\tCRYPT_USERINFO_PASSWORD,\t\t/* Password */\n\n\t/* User role-related information */\n\tCRYPT_USERINFO_CAKEY_CERTSIGN,\t/* CA cert signing key */\n\tCRYPT_USERINFO_CAKEY_CRLSIGN,\t/* CA CRL signing key */\n\tCRYPT_USERINFO_CAKEY_RTCSSIGN,\t/* CA RTCS signing key */\n\tCRYPT_USERINFO_CAKEY_OCSPSIGN,\t/* CA OCSP signing key */\n\n\t/* Used internally for range checking */\n\tCRYPT_USERINFO_LAST, CRYPT_ATTRIBUTE_LAST = CRYPT_USERINFO_LAST\n\n#ifdef _CRYPT_DEFINED\n\t/***********************/\n\t/* Internal attributes */\n\t/***********************/\n\n\t/* The following attributes are only visible internally and are protected\n\t   from any external access by the kernel (and for good measure by checks\n\t   in other places as well).  The two attributes CRYPT_IATTRIBUTE_KEY_SPKI\n\t   and CRYPT_IATTRIBUTE_SPKI are actually the same thing, the difference\n\t   is that the former is write-only for contexts and the latter is read-\n\t   only for certificates (the former is used when loading a context from\n\t   a key contained in a device, where the actual key components aren't\n\t   directly available in the context but may be needed in the future for\n\t   things like cert requests).  Because a single object can act as both a\n\t   context and a cert, having two explicitly different attribute names\n\t   makes things less confusing.  In addition, some public-key attributes\n\t   have _PARTIAL variants that load the public-key components but don't\n\t   initialise the key/move the context into the high state.  This is\n\t   used for formats in which public and private-key components are loaded\n\t   separately */\n\t, CRYPT_IATTRIBUTE_FIRST = 8000,\n\tCRYPT_IATTRIBUTE_TYPE,\t\t\t/* Object type */\n\tCRYPT_IATTRIBUTE_SUBTYPE,\t\t/* Object subtype */\n\tCRYPT_IATTRIBUTE_STATUS,\t\t/* Object status */\n\tCRYPT_IATTRIBUTE_INTERNAL,\t\t/* Object internal flag */\n\tCRYPT_IATTRIBUTE_ACTIONPERMS,\t/* Object action permissions */\n\tCRYPT_IATTRIBUTE_LOCKED,\t\t/* Object locked for exclusive use */\n\tCRYPT_IATTRIBUTE_INITIALISED,\t/* Object inited (in high state) */\n\n\t/* Context internal attributes */\n\tCRYPT_IATTRIBUTE_KEYSIZE,\t\t/* Key size (written to non-native ctxs) */\n\tCRYPT_IATTRIBUTE_KEYFEATURES,\t/* Key feature info */\n\tCRYPT_IATTRIBUTE_KEYID,\t\t\t/* Key ID */\n\tCRYPT_IATTRIBUTE_KEYID_PGP2,\t/* PGP 2 key ID */\n\tCRYPT_IATTRIBUTE_KEYID_OPENPGP,\t/* OpenPGP key ID */\n\tCRYPT_IATTRIBUTE_KEY_SPKI,\t\t/* SubjectPublicKeyInfo */\n\tCRYPT_IATTRIBUTE_KEY_PGP,\t\t/* PGP-format public key */\n\tCRYPT_IATTRIBUTE_KEY_SSH,\t\t/* SSHv2-format public key */\n\tCRYPT_IATTRIBUTE_KEY_SSL,\t\t/* SSL-format public key */\n\tCRYPT_IATTRIBUTE_KEY_SSL_EXT,\t/* TLS-extended-format public key */\n\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL,/* SubjectPublicKeyInfo w/o trigger */\n\tCRYPT_IATTRIBUTE_KEY_PGP_PARTIAL,/* PGP public key w/o trigger */\n\tCRYPT_IATTRIBUTE_KEY_DLPPARAM,\t/* DLP domain parameters */\n\tCRYPT_IATTRIBUTE_KEY_ECCPARAM,\t/* ECC domain parameters */\n\tCRYPT_IATTRIBUTE_PGPVALIDITY,\t/* PGP key validity */\n\tCRYPT_IATTRIBUTE_DEVICEOBJECT,\t/* Device object handle */\n\tCRYPT_IATTRIBUTE_DEVICESTORAGEID,/* Storage ID for data in device */\n\tCRYPT_IATTRIBUTE_EXISTINGLABEL,\t/* Existing label for object in device */\n\tCRYPT_IATTRIBUTE_KEYING_ALGO_PARAM,/* Opt.params for C_C_KEYING_ALGO */\n\tCRYPT_IATTRIBUTE_KDFPARAMS,\t\t/* Opt.KDF params for generic-secret */\n\tCRYPT_IATTRIBUTE_ENCPARAMS,\t\t/* Encryption params for generic-secret */\n\tCRYPT_IATTRIBUTE_MACPARAMS,\t\t/* MAC params for generic-secret */\n\tCRYPT_IATTRIBUTE_AAD,\t\t\t/* AAD for authenticated-encr.modes */\n\tCRYPT_IATTRIBUTE_ICV,\t\t\t/* ICV for authenticated-encr.modes */\n\n\t/* Certificate internal attributes */\n\tCRYPT_IATTRIBUTE_SUBJECT,\t\t/* SubjectName */\n\tCRYPT_IATTRIBUTE_ISSUER,\t\t/* IssuerName */\n\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,\t/* IssuerAndSerial */\n\tCRYPT_IATTRIBUTE_HOLDERNAME,\t/* Best approximation to cert.owner name */\n\tCRYPT_IATTRIBUTE_HOLDERURI,\t\t/* Best approximation to cert.owner URI */\n\tCRYPT_IATTRIBUTE_SPKI,\t\t\t/* Encoded SubjectPublicKeyInfo */\n\tCRYPT_IATTRIBUTE_CERTKEYALGO,\t/* PKC algo.used for certificate */\n\tCRYPT_IATTRIBUTE_CERTHASHALGO,\t/* Hash algo.used for certificate */\n\tCRYPT_IATTRIBUTE_CERTCOLLECTION,/* Certs added to cert chain */\n\tCRYPT_IATTRIBUTE_CRLENTRY,\t\t/* Individual entry from CRL */\n\tCRYPT_IATTRIBUTE_RESPONDERURL,\t/* RTCS/OCSP responder name */\n\tCRYPT_IATTRIBUTE_RTCSREQUEST,\t/* RTCS req.info added to RTCS resp.*/\n\tCRYPT_IATTRIBUTE_OCSPREQUEST,\t/* OCSP req.info added to OCSP resp.*/\n\tCRYPT_IATTRIBUTE_REVREQUEST,\t/* CRMF rev.request added to CRL */\n\tCRYPT_IATTRIBUTE_PKIUSERINFO,\t/* Additional user info added to cert.req.*/\n\tCRYPT_IATTRIBUTE_BLOCKEDATTRS,\t/* Template of disallowed attrs.in cert */\n\tCRYPT_IATTRIBUTE_REQFROMRA,\t\t/* Cert request came from RA */\n\tCRYPT_IATTRIBUTE_AUTHCERTID,\t/* Authorising cert ID for a cert/rev.req.*/\n\tCRYPT_IATTRIBUTE_ESSCERTID,\t\t/* ESSCertID */\n\tCRYPT_IATTRIBUTE_CERTCOPY,\t\t/* Copy of cert object */\n\tCRYPT_IATTRIBUTE_CERTCOPY_DATAONLY,\t/* Copy of cert object as data-only cert */\n\n\t/* Device internal attributes */\n\tCRYPT_IATTRIBUTE_ENTROPY,\t\t/* Polled entropy data */\n\tCRYPT_IATTRIBUTE_ENTROPY_QUALITY,/* Quality of entropy data */\n\tCRYPT_IATTRIBUTE_RANDOM_POLL,\t/* Slow/fast entropy poll */\n\tCRYPT_IATTRIBUTE_RANDOM_LOPICKET,/* Low picket for random data attrs.*/\n\tCRYPT_IATTRIBUTE_RANDOM,\t\t/* Random data */\n\tCRYPT_IATTRIBUTE_RANDOM_NZ,\t\t/* Nonzero random data */\n\tCRYPT_IATTRIBUTE_RANDOM_HIPICKET,/* High picket for random data attrs.*/\n\tCRYPT_IATTRIBUTE_RANDOM_NONCE,\t/* Basic nonce */\n\tCRYPT_IATTRIBUTE_TIME,\t\t\t/* Reliable (hardware-based) time value */\n\n\t/* Envelope internal attributes */\n\tCRYPT_IATTRIBUTE_INCLUDESIGCERT,/* Whether to include signing cert(s) */\n\tCRYPT_IATTRIBUTE_ATTRONLY,\t\t/* Signed data contains only CMS attrs.*/\n\n\t/* Keyset internal attributes */\n\tCRYPT_IATTRIBUTE_CONFIGDATA,\t/* Config information */\n\tCRYPT_IATTRIBUTE_USERINDEX,\t\t/* Index of users */\n\tCRYPT_IATTRIBUTE_USERID,\t\t/* User ID */\n\tCRYPT_IATTRIBUTE_USERINFO,\t\t/* User information */\n\tCRYPT_IATTRIBUTE_TRUSTEDCERT,\t/* First trusted cert */\n\tCRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT,\t/* Successive trusted certs */\n\tCRYPT_IATTRIBUTE_HWSTORAGE,\t\t/* Associated device for priv.key data */\n\n\t/* Session internal attributes */\n\tCRYPT_IATTRIBUTE_ENC_TIMESTAMP,\t/* Encoded TSA timestamp */\n\n\t/* User internal attributes */\n\tCRYPT_IATTRUBUTE_CERTKEYSET,\t/* Keyset to send trusted certs to */\n\tCRYPT_IATTRIBUTE_CTL,\t\t\t/* Cert.trust list */\n\tCRYPT_IATTRIBUTE_LAST,\n\n\t/* Subrange values used internally for range checking */\n\tCRYPT_CERTINFO_FIRST_CERTINFO = CRYPT_CERTINFO_FIRST + 1,\n\tCRYPT_CERTINFO_LAST_CERTINFO = CRYPT_CERTINFO_PKIUSER_RA,\n\t\tCRYPT_CERTINFO_FIRST_PSEUDOINFO = CRYPT_CERTINFO_SELFSIGNED,\n\t\tCRYPT_CERTINFO_LAST_PSEUDOINFO = CRYPT_CERTINFO_SIGNATURELEVEL,\n\tCRYPT_CERTINFO_FIRST_NAME = CRYPT_CERTINFO_COUNTRYNAME,\n\tCRYPT_CERTINFO_LAST_NAME = CRYPT_CERTINFO_REGISTEREDID,\n\t\tCRYPT_CERTINFO_FIRST_DN = CRYPT_CERTINFO_COUNTRYNAME,\n\t\tCRYPT_CERTINFO_LAST_DN = CRYPT_CERTINFO_COMMONNAME,\n\t\tCRYPT_CERTINFO_FIRST_GENERALNAME = CRYPT_CERTINFO_OTHERNAME_TYPEID,\n\t\tCRYPT_CERTINFO_LAST_GENERALNAME = CRYPT_CERTINFO_REGISTEREDID,\n\tCRYPT_CERTINFO_FIRST_EXTENSION = CRYPT_CERTINFO_CHALLENGEPASSWORD,\n\tCRYPT_CERTINFO_LAST_EXTENSION = CRYPT_CERTINFO_SET_TUNNELINGALGID,\n\tCRYPT_CERTINFO_FIRST_CMS = CRYPT_CERTINFO_CMS_CONTENTTYPE,\n\tCRYPT_CERTINFO_LAST_CMS = CRYPT_CERTINFO_LAST - 1,\n\tCRYPT_SESSINFO_FIRST_SPECIFIC = CRYPT_SESSINFO_REQUEST,\n\tCRYPT_SESSINFO_LAST_SPECIFIC = CRYPT_SESSINFO_TSP_MSGIMPRINT\n\n\t/* Point at which private-use values start.  Attribute values sometimes\n\t   need to be extended with additional pseudo-values in object-specific\n\t   cases, for example the certificate-management code extends the\n\t   explicit certificate attributes with additional implicit values used\n\t   internally to handle certificates.  In order to allow for these\n\t   additional values we place them beyond the private-use value below */\n\t, CRYPT_XATTRIBUTE_PRIVATE = 10000\n\n\t/* Pseudo-value to make attributes have the same size as integers on\n\t   compilers that use variable-size enums.  This is required in order\n\t   to make kernel ACL management easier, see the comments with the \n\t   pseudo-ACLs in acl.h for details */\n\t, CRYPT_XATTRIBUTE_MAX = INT_MAX - 100\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_ATTRIBUTE_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Subtypes and Related Values\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Flags for the X.509 keyUsage extension */\n\n#define CRYPT_KEYUSAGE_NONE\t\t\t\t\t0x000\n#define CRYPT_KEYUSAGE_DIGITALSIGNATURE\t\t0x001\n#define CRYPT_KEYUSAGE_NONREPUDIATION\t\t0x002\n#define CRYPT_KEYUSAGE_KEYENCIPHERMENT\t\t0x004\n#define CRYPT_KEYUSAGE_DATAENCIPHERMENT\t\t0x008\n#define CRYPT_KEYUSAGE_KEYAGREEMENT\t\t\t0x010\n#define CRYPT_KEYUSAGE_KEYCERTSIGN\t\t\t0x020\n#define CRYPT_KEYUSAGE_CRLSIGN\t\t\t\t0x040\n#define CRYPT_KEYUSAGE_ENCIPHERONLY\t\t\t0x080\n#define CRYPT_KEYUSAGE_DECIPHERONLY\t\t\t0x100\n#define CRYPT_KEYUSAGE_LAST\t\t\t\t\t0x200\t/* Last possible value */\n#ifdef _CRYPT_DEFINED\n#define CRYPT_KEYUSAGE_FLAG_NONE\t\t\t0x000\t/* Defines for range checking */\n#define CRYPT_KEYUSAGE_FLAG_MAX\t\t\t\t0x1FF\n#endif /* _CRYPT_DEFINED */\n\n/* X.509 cRLReason and cryptlib cRLExtReason codes */\n\nenum { CRYPT_CRLREASON_UNSPECIFIED, CRYPT_CRLREASON_KEYCOMPROMISE,\n\t   CRYPT_CRLREASON_CACOMPROMISE, CRYPT_CRLREASON_AFFILIATIONCHANGED,\n\t   CRYPT_CRLREASON_SUPERSEDED, CRYPT_CRLREASON_CESSATIONOFOPERATION,\n\t   CRYPT_CRLREASON_CERTIFICATEHOLD, CRYPT_CRLREASON_REMOVEFROMCRL = 8,\n\t   CRYPT_CRLREASON_PRIVILEGEWITHDRAWN, CRYPT_CRLREASON_AACOMPROMISE,\n\t   CRYPT_CRLREASON_LAST, /* End of standard CRL reasons */\n\t   CRYPT_CRLREASON_NEVERVALID = 20, CRYPT_CRLEXTREASON_LAST };\n\n/* X.509 CRL reason flags.  These identify the same thing as the cRLReason\n   codes but allow for multiple reasons to be specified.  Note that these\n   don't follow the X.509 naming since in that scheme the enumerated types\n   and bitflags have the same names */\n\n#define CRYPT_CRLREASONFLAG_UNUSED\t\t\t\t0x001\n#define CRYPT_CRLREASONFLAG_KEYCOMPROMISE\t\t0x002\n#define CRYPT_CRLREASONFLAG_CACOMPROMISE\t\t0x004\n#define CRYPT_CRLREASONFLAG_AFFILIATIONCHANGED\t0x008\n#define CRYPT_CRLREASONFLAG_SUPERSEDED\t\t\t0x010\n#define CRYPT_CRLREASONFLAG_CESSATIONOFOPERATION 0x020\n#define CRYPT_CRLREASONFLAG_CERTIFICATEHOLD\t\t0x040\n#define CRYPT_CRLREASONFLAG_LAST\t\t\t\t0x080\t/* Last poss.value */\n\n/* X.509 CRL holdInstruction codes */\n\nenum { CRYPT_HOLDINSTRUCTION_NONE, CRYPT_HOLDINSTRUCTION_CALLISSUER,\n\t   CRYPT_HOLDINSTRUCTION_REJECT, CRYPT_HOLDINSTRUCTION_PICKUPTOKEN,\n\t   CRYPT_HOLDINSTRUCTION_LAST };\n\n/* Certificate checking compliance levels */\n\ntypedef enum { \n\tCRYPT_COMPLIANCELEVEL_OBLIVIOUS, CRYPT_COMPLIANCELEVEL_REDUCED,\n\tCRYPT_COMPLIANCELEVEL_STANDARD, CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL,\n\tCRYPT_COMPLIANCELEVEL_PKIX_FULL, CRYPT_COMPLIANCELEVEL_LAST \n\t} CRYPT_COMPLIANCELEVEL_TYPE;\n\n/* Flags for the Netscape netscape-cert-type extension */\n\n#define CRYPT_NS_CERTTYPE_SSLCLIENT\t\t\t0x001\n#define CRYPT_NS_CERTTYPE_SSLSERVER\t\t\t0x002\n#define CRYPT_NS_CERTTYPE_SMIME\t\t\t\t0x004\n#define CRYPT_NS_CERTTYPE_OBJECTSIGNING\t\t0x008\n#define CRYPT_NS_CERTTYPE_RESERVED\t\t\t0x010\n#define CRYPT_NS_CERTTYPE_SSLCA\t\t\t\t0x020\n#define CRYPT_NS_CERTTYPE_SMIMECA\t\t\t0x040\n#define CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA\t0x080\n#define CRYPT_NS_CERTTYPE_LAST\t\t\t\t0x100\t/* Last possible value */\n\n/* Flags for the SET certificate-type extension */\n\n#define CRYPT_SET_CERTTYPE_CARD\t\t\t\t0x001\n#define CRYPT_SET_CERTTYPE_MER\t\t\t\t0x002\n#define CRYPT_SET_CERTTYPE_PGWY\t\t\t\t0x004\n#define CRYPT_SET_CERTTYPE_CCA\t\t\t\t0x008\n#define CRYPT_SET_CERTTYPE_MCA\t\t\t\t0x010\n#define CRYPT_SET_CERTTYPE_PCA\t\t\t\t0x020\n#define CRYPT_SET_CERTTYPE_GCA\t\t\t\t0x040\n#define CRYPT_SET_CERTTYPE_BCA\t\t\t\t0x080\n#define CRYPT_SET_CERTTYPE_RCA\t\t\t\t0x100\n#define CRYPT_SET_CERTTYPE_ACQ\t\t\t\t0x200\n#define CRYPT_SET_CERTTYPE_LAST\t\t\t\t0x400\t/* Last possible value */\n\n/* CMS contentType values */\n\ntypedef enum { CRYPT_CONTENT_NONE, CRYPT_CONTENT_DATA,\n\t\t\t   CRYPT_CONTENT_SIGNEDDATA, CRYPT_CONTENT_ENVELOPEDDATA,\n\t\t\t   CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA,\n\t\t\t   CRYPT_CONTENT_DIGESTEDDATA, CRYPT_CONTENT_ENCRYPTEDDATA,\n\t\t\t   CRYPT_CONTENT_COMPRESSEDDATA, CRYPT_CONTENT_AUTHDATA, \n\t\t\t   CRYPT_CONTENT_AUTHENVDATA, CRYPT_CONTENT_TSTINFO,\n\t\t\t   CRYPT_CONTENT_SPCINDIRECTDATACONTEXT,\n\t\t\t   CRYPT_CONTENT_RTCSREQUEST, CRYPT_CONTENT_RTCSRESPONSE,\n\t\t\t   CRYPT_CONTENT_RTCSRESPONSE_EXT, CRYPT_CONTENT_MRTD, \n\t\t\t   CRYPT_CONTENT_LAST\n\t\t\t } CRYPT_CONTENT_TYPE;\n\n/* ESS securityClassification codes */\n\nenum { CRYPT_CLASSIFICATION_UNMARKED, CRYPT_CLASSIFICATION_UNCLASSIFIED,\n\t   CRYPT_CLASSIFICATION_RESTRICTED, CRYPT_CLASSIFICATION_CONFIDENTIAL,\n\t   CRYPT_CLASSIFICATION_SECRET, CRYPT_CLASSIFICATION_TOP_SECRET,\n\t   CRYPT_CLASSIFICATION_LAST = 255 };\n\n/* RTCS certificate status */\n\ntypedef enum { \n\tCRYPT_CERTSTATUS_NONE,\t\t\t/* No certificate status */\n\tCRYPT_CERTSTATUS_VALID,\t\t\t/* Certificate valid */\n\tCRYPT_CERTSTATUS_NOTVALID,\t\t/* Certificate isn't valid */\n\tCRYPT_CERTSTATUS_NONAUTHORITATIVE, /* Response is non-authoritative */\n\tCRYPT_CERTSTATUS_UNKNOWN,\t\t/* Certificate status unknown */\n\tCRYPT_CERTSTATUS_LAST\t\t\t/* Last possible certificate status */\n\t} CRYPT_CERTSTATUS_TYPE;\n\n/* OCSP revocation status */\n\nenum { CRYPT_OCSPSTATUS_NOTREVOKED, CRYPT_OCSPSTATUS_REVOKED,\n\t   CRYPT_OCSPSTATUS_UNKNOWN };\n\n/* The amount of detail to include in signatures when signing certificate\n   objects */\n\ntypedef enum {\n\tCRYPT_SIGNATURELEVEL_NONE,\t\t/* Include only signature */\n\tCRYPT_SIGNATURELEVEL_SIGNERCERT,/* Include signer cert */\n\tCRYPT_SIGNATURELEVEL_ALL,\t\t/* Include all relevant info */\n\tCRYPT_SIGNATURELEVEL_LAST\t\t/* Last possible sig.level type */\n\t} CRYPT_SIGNATURELEVEL_TYPE;\n\n/* The level of integrity protection to apply to enveloped data.  The \n   default envelope protection for an envelope with keying information \n   applied is encryption, this can be modified to use MAC-only protection\n   (with no encryption) or hybrid encryption + authentication */\n\ntypedef enum {\n\tCRYPT_INTEGRITY_NONE,\t\t\t/* No integrity protection */\n\tCRYPT_INTEGRITY_MACONLY,\t\t/* MAC only, no encryption */\n\tCRYPT_INTEGRITY_FULL\t\t\t/* Encryption + ingerity protection */\n\t} CRYPT_INTEGRITY_TYPE;\n\n/* The certificate export format type, which defines the format in which a\n   certificate object is exported */\n\ntypedef enum {\n\tCRYPT_CERTFORMAT_NONE,\t\t\t/* No certificate format */\n\tCRYPT_CERTFORMAT_CERTIFICATE,\t/* DER-encoded certificate */\n\tCRYPT_CERTFORMAT_CERTCHAIN,\t\t/* PKCS #7 certificate chain */\n\tCRYPT_CERTFORMAT_TEXT_CERTIFICATE,\t/* base-64 wrapped cert */\n\tCRYPT_CERTFORMAT_TEXT_CERTCHAIN,\t/* base-64 wrapped cert chain */\n\tCRYPT_CERTFORMAT_XML_CERTIFICATE,\t/* XML wrapped cert */\n\tCRYPT_CERTFORMAT_XML_CERTCHAIN,\t/* XML wrapped cert chain */\n#ifdef _CRYPT_DEFINED\n\tCRYPT_ICERTFORMAT_CERTSET,\t\t/* SET OF Certificate */\n\tCRYPT_ICERTFORMAT_CERTSEQUENCE,\t/* SEQUENCE OF Certificate */\n\tCRYPT_ICERTFORMAT_SSL_CERTCHAIN,/* SSL certificate chain */\n\tCRYPT_ICERTFORMAT_DATA,\t\t\t/* Non-signed object data */\n\tCRYPT_ICERTFORMAT_SMIME_CERTIFICATE,/* S/MIME cert.request or cert chain */\n\t\t\t/* Used as an internal format specifier when the format is \n\t\t\t   autodetected to tell the base64 decoding code to strip MIME \n\t\t\t   headers before the base64 data */\n#endif /* _CRYPT_DEFINED */\n\tCRYPT_CERTFORMAT_LAST\t\t\t/* Last possible cert.format type */\n#ifdef _CRYPT_DEFINED\n\t, CRYPT_CERTFORMAT_LAST_EXTERNAL = CRYPT_CERTFORMAT_XML_CERTCHAIN + 1\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_CERTFORMAT_TYPE;\n\n/* CMP request types */\n\ntypedef enum {\n\tCRYPT_REQUESTTYPE_NONE,\t\t\t/* No request type */\n\tCRYPT_REQUESTTYPE_INITIALISATION,\t/* Initialisation request */\n\t\tCRYPT_REQUESTTYPE_INITIALIZATION = CRYPT_REQUESTTYPE_INITIALISATION,\n\tCRYPT_REQUESTTYPE_CERTIFICATE,\t/* Certification request */\n\tCRYPT_REQUESTTYPE_KEYUPDATE,\t/* Key update request */\n\tCRYPT_REQUESTTYPE_REVOCATION,\t/* Cert revocation request */\n\tCRYPT_REQUESTTYPE_PKIBOOT,\t\t/* PKIBoot request */\n\tCRYPT_REQUESTTYPE_LAST\t\t\t/* Last possible request type */\n\t} CRYPT_REQUESTTYPE_TYPE;\n\n/* Key ID types */\n\ntypedef enum {\n\tCRYPT_KEYID_NONE,\t\t\t\t/* No key ID type */\n\tCRYPT_KEYID_NAME,\t\t\t\t/* Key owner name */\n\tCRYPT_KEYID_URI,\t\t\t\t/* Key owner URI */\n\t\tCRYPT_KEYID_EMAIL = CRYPT_KEYID_URI, /* Synonym: owner email addr.*/\n#ifdef _CRYPT_DEFINED\n\t/* Internal key ID types */\n\tCRYPT_IKEYID_KEYID,\t\t\t\t/* SubjectKeyIdentifier/internal ID */\n\tCRYPT_IKEYID_PGPKEYID,\t\t\t/* PGP/OpenPGP key ID */\n\tCRYPT_IKEYID_CERTID,\t\t\t/* Certificate hash */\n\tCRYPT_IKEYID_SUBJECTID,\t\t\t/* Hashed subjectName */\n\tCRYPT_IKEYID_ISSUERID,\t\t\t/* Hashed issuerAndSerialNumber */\n\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER,\t/* issuerAndSerialNumber */\n#endif /* _CRYPT_DEFINED */\n\tCRYPT_KEYID_LAST\t\t\t\t/* Last possible key ID type */\n#ifdef _CRYPT_DEFINED\n\t, CRYPT_KEYID_LAST_EXTERNAL = CRYPT_KEYID_URI + 1/* Last external key ID */\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_KEYID_TYPE;\n\n/* The encryption object types */\n\ntypedef enum {\n\tCRYPT_OBJECT_NONE,\t\t\t\t/* No object type */\n\tCRYPT_OBJECT_ENCRYPTED_KEY,\t\t/* Conventionally encrypted key */\n\tCRYPT_OBJECT_PKCENCRYPTED_KEY,\t/* PKC-encrypted key */\n\tCRYPT_OBJECT_KEYAGREEMENT,\t\t/* Key agreement information */\n\tCRYPT_OBJECT_SIGNATURE,\t\t\t/* Signature */\n\tCRYPT_OBJECT_LAST\t\t\t\t/* Last possible object type */\n\t} CRYPT_OBJECT_TYPE;\n\n/* Object/attribute error type information */\n\ntypedef enum {\n\tCRYPT_ERRTYPE_NONE,\t\t\t\t/* No error information */\n\tCRYPT_ERRTYPE_ATTR_SIZE,\t\t/* Attribute data too small or large */\n\tCRYPT_ERRTYPE_ATTR_VALUE,\t\t/* Attribute value is invalid */\n\tCRYPT_ERRTYPE_ATTR_ABSENT,\t\t/* Required attribute missing */\n\tCRYPT_ERRTYPE_ATTR_PRESENT,\t\t/* Non-allowed attribute present */\n\tCRYPT_ERRTYPE_CONSTRAINT,\t\t/* Cert: Constraint violation in object */\n\tCRYPT_ERRTYPE_ISSUERCONSTRAINT,\t/* Cert: Constraint viol.in issuing cert */\n\tCRYPT_ERRTYPE_LAST\t\t\t\t/* Last possible error info type */\n\t} CRYPT_ERRTYPE_TYPE;\n\n/* Cert store management action type */\n\ntypedef enum {\n\tCRYPT_CERTACTION_NONE,\t\t\t/* No cert management action */\n\tCRYPT_CERTACTION_CREATE,\t\t/* Create cert store */\n\tCRYPT_CERTACTION_CONNECT,\t\t/* Connect to cert store */\n\tCRYPT_CERTACTION_DISCONNECT,\t/* Disconnect from cert store */\n\tCRYPT_CERTACTION_ERROR,\t\t\t/* Error information */\n\tCRYPT_CERTACTION_ADDUSER,\t\t/* Add PKI user */\n\tCRYPT_CERTACTION_DELETEUSER,\t/* Delete PKI user */\n\tCRYPT_CERTACTION_REQUEST_CERT,\t/* Cert request */\n\tCRYPT_CERTACTION_REQUEST_RENEWAL,/* Cert renewal request */\n\tCRYPT_CERTACTION_REQUEST_REVOCATION,/* Cert revocation request */\n\tCRYPT_CERTACTION_CERT_CREATION,\t/* Cert creation */\n\tCRYPT_CERTACTION_CERT_CREATION_COMPLETE,/* Confirmation of cert creation */\n\tCRYPT_CERTACTION_CERT_CREATION_DROP,\t/* Cancellation of cert creation */\n\tCRYPT_CERTACTION_CERT_CREATION_REVERSE,\t/* Cancel of creation w.revocation */\n\tCRYPT_CERTACTION_RESTART_CLEANUP, /* Delete reqs after restart */\n\tCRYPT_CERTACTION_RESTART_REVOKE_CERT, /* Complete revocation after restart */\n\tCRYPT_CERTACTION_ISSUE_CERT,\t/* Cert issue */\n\tCRYPT_CERTACTION_ISSUE_CRL,\t\t/* CRL issue */\n\tCRYPT_CERTACTION_REVOKE_CERT,\t/* Cert revocation */\n\tCRYPT_CERTACTION_EXPIRE_CERT,\t/* Cert expiry */\n\tCRYPT_CERTACTION_CLEANUP,\t\t/* Clean up on restart */\n\tCRYPT_CERTACTION_LAST\t\t\t/* Last possible cert store log action */\n#ifdef _CRYPT_DEFINED\n\t/* User-settable action types for cert mgmt.actions */\n\t, CRYPT_CERTACTION_FIRST_USER = CRYPT_CERTACTION_ISSUE_CERT,\n\tCRYPT_CERTACTION_LAST_USER = CRYPT_CERTACTION_CLEANUP\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_CERTACTION_TYPE;\n\n/* Session sub-protocol types */\n\ntypedef enum {\n\tCRYPT_SUBPROTOCOL_NONE,\t\t\t/* No sub-protocol type */\n\tCRYPT_SUBPROTOCOL_WEBSOCKETS,\t/* Websockets */\n\tCRYPT_SUBPROTOCOL_EAPTTLS,\t\t/* EAP-TTLS */\n\tCRYPT_SUBPROTOCOL_LAST\t\t\t/* Last possible sub-protocol type */\n\t} CRYPT_SUBPROTOCOL_TYPE;\n\n/* SSL/TLS protocol options.  CRYPT_SSLOPTION_MINVER_SSLV3 is the same as \n   CRYPT_SSLOPTION_NONE since this is the baseline, although it'll never be\n   encountered since SSLv3 is disabled */\n\n#define CRYPT_SSLOPTION_NONE\t\t\t\t0x000\n#define CRYPT_SSLOPTION_MINVER_SSLV3\t\t0x000\t/* Min.protocol version */\n#define CRYPT_SSLOPTION_MINVER_TLS10\t\t0x001\n#define CRYPT_SSLOPTION_MINVER_TLS11\t\t0x002\n#define CRYPT_SSLOPTION_MINVER_TLS12\t\t0x003\n#define CRYPT_SSLOPTION_MINVER_TLS13\t\t0x004\n#define CRYPT_SSLOPTION_MANUAL_CERTCHECK\t0x008\t/* Require manual cert.verif.*/\n#define CRYPT_SSLOPTION_DISABLE_NAMEVERIFY\t0x010\t/* Disable cert hostname check */\n#define CRYPT_SSLOPTION_DISABLE_CERTVERIFY\t0x020\t/* Disable certificate check */\n#define CRYPT_SSLOPTION_SUITEB_128\t\t\t0x100\t/* SuiteB security levels (may */\n#define CRYPT_SSLOPTION_SUITEB_256\t\t\t0x200\t/*  vanish in future releases) */\n#ifdef _CRYPT_DEFINED\n#define CRYPT_SSLOPTION_MAX\t\t\t\t\t0x7F\t/* Defines for range checking */\n#endif /* _CRYPT_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGeneral Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The maximum user key size - 2048 bits */\n\n#define CRYPT_MAX_KEYSIZE\t\t256\n\n/* The maximum IV/cipher block size - 256 bits */\n\n#define CRYPT_MAX_IVSIZE\t\t32\n\n/* The maximum public-key component size - 4096 bits, and maximum component\n   size for ECCs - 576 bits (to handle the P521 curve) */\n\n#define CRYPT_MAX_PKCSIZE\t\t512\n#define CRYPT_MAX_PKCSIZE_ECC\t72\n\n/* The maximum hash size - 512 bits.  Before 3.4 this was 256 bits, in the \n   3.4 release it was increased to 512 bits to accommodate SHA-3 */\n\n#define CRYPT_MAX_HASHSIZE\t\t64\n\n/* The maximum size of a text string (e.g.key owner name) */\n\n#define CRYPT_MAX_TEXTSIZE\t\t64\n\n/* A magic value indicating that the default setting for this parameter\n   should be used.  The parentheses are to catch potential erroneous use \n   in an expression */\n\n#define CRYPT_USE_DEFAULT\t\t( -100 )\n\n/* A magic value for unused parameters */\n\n#define CRYPT_UNUSED\t\t\t( -101 )\n\n/* Cursor positioning codes for certificate/CRL extensions.  The parentheses \n   are to catch potential erroneous use in an expression */\n\n#define CRYPT_CURSOR_FIRST\t\t( -200 )\n#define CRYPT_CURSOR_PREVIOUS\t( -201 )\n#define CRYPT_CURSOR_NEXT\t\t( -202 )\n#define CRYPT_CURSOR_LAST\t\t( -203 )\n\n/* The type of information polling to perform to get random seed \n   information.  These values have to be negative because they're used\n   as magic length values for cryptAddRandom().  The parentheses are to \n   catch potential erroneous use in an expression */\n\n#define CRYPT_RANDOM_FASTPOLL\t( -300 )\n#define CRYPT_RANDOM_SLOWPOLL\t( -301 )\n\n/* Whether the PKC key is a public or private key */\n\n#define CRYPT_KEYTYPE_PRIVATE\t0\n#define CRYPT_KEYTYPE_PUBLIC\t1\n\n/* Keyset open options */\n\ntypedef enum {\n\tCRYPT_KEYOPT_NONE,\t\t\t\t/* No options */\n\tCRYPT_KEYOPT_READONLY,\t\t\t/* Open keyset in read-only mode */\n\tCRYPT_KEYOPT_CREATE,\t\t\t/* Create a new keyset */\n#ifdef _CRYPT_DEFINED\n\t/* Internal keyset options */\n\tCRYPT_IKEYOPT_EXCLUSIVEACCESS,\t/* As _NONE but open for exclusive access */\n#endif /* _CRYPT_DEFINED */\n\tCRYPT_KEYOPT_LAST\t\t\t\t/* Last possible key option type */\n#ifdef _CRYPT_DEFINED\n\t, CRYPT_KEYOPT_LAST_EXTERNAL = CRYPT_KEYOPT_CREATE + 1\n\t\t\t\t\t\t\t\t\t/* Last external keyset option */\n#endif /* _CRYPT_DEFINED */\n\t} CRYPT_KEYOPT_TYPE;\n\n/* The various cryptlib objects - these are just integer handles */\n\ntypedef int CRYPT_CERTIFICATE;\ntypedef int CRYPT_CONTEXT;\ntypedef int CRYPT_DEVICE;\ntypedef int CRYPT_ENVELOPE;\ntypedef int CRYPT_KEYSET;\ntypedef int CRYPT_SESSION;\ntypedef int CRYPT_USER;\n\n/* Sometimes we don't know the exact type of a cryptlib object, so we use a\n   generic handle type to identify it */\n\ntypedef int CRYPT_HANDLE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEncryption Data Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Results returned from the capability query */\n\ntypedef struct {\n\t/* Algorithm information */\n\tC_CHR algoName[ CRYPT_MAX_TEXTSIZE ];/* Algorithm name */\n\tint blockSize;\t\t\t\t\t/* Block size of the algorithm */\n\tint minKeySize;\t\t\t\t\t/* Minimum key size in bytes */\n\tint keySize;\t\t\t\t\t/* Recommended key size in bytes */\n\tint maxKeySize;\t\t\t\t\t/* Maximum key size in bytes */\n\t} CRYPT_QUERY_INFO;\n\n/* Results returned from the encoded object query.  These provide\n   information on the objects created by cryptExportKey()/\n   cryptCreateSignature() */\n\ntypedef struct {\n\t/* The object type */\n\tCRYPT_OBJECT_TYPE objectType;\n\n\t/* The encryption algorithm and mode */\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tCRYPT_MODE_TYPE cryptMode;\n\n\t/* The hash algorithm for signature objects or PRF algorithm for derived \n\t   keys */\n\tCRYPT_ALGO_TYPE hashAlgo;\n\n\t/* The salt and PRF iterations for derived keys */\n\tunsigned char salt[ CRYPT_MAX_HASHSIZE ];\n\tint saltSize;\n\tint iterations;\n\t} CRYPT_OBJECT_INFO;\n\n/* Key information for the public-key encryption algorithms.  These fields\n   are not accessed directly, but can be manipulated with the init/set/\n   destroyComponents() macros */\n\ntypedef struct {\n\t/* Status information */\n\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\n\t/* Public components */\n\tunsigned char n[ CRYPT_MAX_PKCSIZE ];\t/* Modulus */\n\tint nLen;\t\t\t\t\t/* Length of modulus in bits */\n\tunsigned char e[ CRYPT_MAX_PKCSIZE ];\t/* Public exponent */\n\tint eLen;\t\t\t\t\t/* Length of public exponent in bits */\n\n\t/* Private components */\n\tunsigned char d[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent */\n\tint dLen;\t\t\t\t\t/* Length of private exponent in bits */\n\tunsigned char p[ CRYPT_MAX_PKCSIZE ];\t/* Prime factor 1 */\n\tint pLen;\t\t\t\t\t/* Length of prime factor 1 in bits */\n\tunsigned char q[ CRYPT_MAX_PKCSIZE ];\t/* Prime factor 2 */\n\tint qLen;\t\t\t\t\t/* Length of prime factor 2 in bits */\n\tunsigned char u[ CRYPT_MAX_PKCSIZE ];\t/* Mult.inverse of q, mod p */\n\tint uLen;\t\t\t\t\t/* Length of private exponent in bits */\n\tunsigned char e1[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent 1 (PKCS) */\n\tint e1Len;\t\t\t\t\t/* Length of private exponent in bits */\n\tunsigned char e2[ CRYPT_MAX_PKCSIZE ];\t/* Private exponent 2 (PKCS) */\n\tint e2Len;\t\t\t\t\t/* Length of private exponent in bits */\n\t} CRYPT_PKCINFO_RSA;\n\ntypedef struct {\n\t/* Status information */\n\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\n\t/* Public components */\n\tunsigned char p[ CRYPT_MAX_PKCSIZE ];\t/* Prime modulus */\n\tint pLen;\t\t\t\t\t/* Length of prime modulus in bits */\n\tunsigned char q[ CRYPT_MAX_PKCSIZE ];\t/* Prime divisor */\n\tint qLen;\t\t\t\t\t/* Length of prime divisor in bits */\n\tunsigned char g[ CRYPT_MAX_PKCSIZE ];\t/* h^( ( p - 1 ) / q ) mod p */\n\tint gLen;\t\t\t\t\t/* Length of g in bits */\n\tunsigned char y[ CRYPT_MAX_PKCSIZE ];\t/* Public random integer */\n\tint yLen;\t\t\t\t\t/* Length of public integer in bits */\n\n\t/* Private components */\n\tunsigned char x[ CRYPT_MAX_PKCSIZE ];\t/* Private random integer */\n\tint xLen;\t\t\t\t\t/* Length of private integer in bits */\n\t} CRYPT_PKCINFO_DLP;\n\ntypedef enum {\n\t/* Named ECC curves.  Since these need to be mapped to all manner of\n\t   protocol- and mechanism-specific identifiers, when updating this list \n\t   grep for occurrences of the string \"P256\" (the most common one) and \n\t   check whether any related mapping tables need to be updated */\n\tCRYPT_ECCCURVE_NONE,\t\t/* No ECC curve type */\n\tCRYPT_ECCCURVE_P256,\t\t/* NIST P256/X9.62 P256v1/SECG p256r1 curve */\n\tCRYPT_ECCCURVE_P384,\t\t/* NIST P384, SECG p384r1 curve */\n\tCRYPT_ECCCURVE_P521,\t\t/* NIST P521, SECG p521r1 */\n\tCRYPT_ECCCURVE_BRAINPOOL_P256, /* Brainpool p256r1 */\n\tCRYPT_ECCCURVE_BRAINPOOL_P384, /* Brainpool p384r1 */\n\tCRYPT_ECCCURVE_BRAINPOOL_P512, /* Brainpool p512r1 */\n\tCRYPT_ECCCURVE_LAST\t\t\t/* Last valid ECC curve type */\n\t} CRYPT_ECCCURVE_TYPE;\n\ntypedef struct {\n\t/* Status information */\n\tint isPublicKey;\t\t\t/* Whether this is a public or private key */\n\n\t/* Curve domain parameters.  Either the curveType or the explicit domain\n\t   parameters must be provided */\n\tCRYPT_ECCCURVE_TYPE curveType;\t/* Named curve */\n\tunsigned char p[ CRYPT_MAX_PKCSIZE_ECC ];/* Prime defining Fq */\n\tint pLen;\t\t\t\t\t/* Length of prime in bits */\n\tunsigned char a[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining curve */\n\tint aLen;\t\t\t\t\t/* Length of element a in bits */\n\tunsigned char b[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining curve */\n\tint bLen;\t\t\t\t\t/* Length of element b in bits */\n\tunsigned char gx[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining point */\n\tint gxLen;\t\t\t\t\t/* Length of element gx in bits */\n\tunsigned char gy[ CRYPT_MAX_PKCSIZE_ECC ];/* Element in Fq defining point */\n\tint gyLen;\t\t\t\t\t/* Length of element gy in bits */\n\tunsigned char n[ CRYPT_MAX_PKCSIZE_ECC ];/* Order of point */\n\tint nLen;\t\t\t\t\t/* Length of order in bits */\n\tunsigned char h[ CRYPT_MAX_PKCSIZE_ECC ];/* Optional cofactor */\n\tint hLen;\t\t\t\t\t/* Length of cofactor in bits */\n\n\t/* Public components */\n\tunsigned char qx[ CRYPT_MAX_PKCSIZE_ECC ];/* Point Q on the curve */\n\tint qxLen;\t\t\t\t\t/* Length of point xq in bits */\n\tunsigned char qy[ CRYPT_MAX_PKCSIZE_ECC ];/* Point Q on the curve */\n\tint qyLen;\t\t\t\t\t/* Length of point xy in bits */\n\n\t/* Private components */\n\tunsigned char d[ CRYPT_MAX_PKCSIZE_ECC ];/* Private random integer */\n\tint dLen;\t\t\t\t\t/* Length of integer in bits */\n\t} CRYPT_PKCINFO_ECC;\n\n/* Macros to initialise and destroy the structure that stores the components\n   of a public key */\n\n#define cryptInitComponents( componentInfo, componentKeyType ) \\\n\t{ memset( ( componentInfo ), 0, sizeof( *componentInfo ) ); \\\n\t  ( componentInfo )->isPublicKey = ( ( componentKeyType ) ? 1 : 0 ); }\n\n#define cryptDestroyComponents( componentInfo ) \\\n\tmemset( ( componentInfo ), 0, sizeof( *componentInfo ) )\n\n/* Macros to set a component of a public key */\n\n#define cryptSetComponent( destination, source, length ) \\\n\t{ memcpy( ( destination ), ( source ), ( ( length ) + 7 ) >> 3 ); \\\n\t  ( destination##Len ) = length; }\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tStatus Codes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* No error in function call */\n\n#define CRYPT_OK\t\t\t\t0\t\t/* No error */\n\n/* Error in parameters passed to function.  The parentheses are to catch \n   potential erroneous use in an expression */\n\n#define CRYPT_ERROR_PARAM1\t\t( -1 )\t/* Bad argument, parameter 1 */\n#define CRYPT_ERROR_PARAM2\t\t( -2 )\t/* Bad argument, parameter 2 */\n#define CRYPT_ERROR_PARAM3\t\t( -3 )\t/* Bad argument, parameter 3 */\n#define CRYPT_ERROR_PARAM4\t\t( -4 )\t/* Bad argument, parameter 4 */\n#define CRYPT_ERROR_PARAM5\t\t( -5 )\t/* Bad argument, parameter 5 */\n#define CRYPT_ERROR_PARAM6\t\t( -6 )\t/* Bad argument, parameter 6 */\n#define CRYPT_ERROR_PARAM7\t\t( -7 )\t/* Bad argument, parameter 7 */\n\n/* Errors due to insufficient resources */\n\n#define CRYPT_ERROR_MEMORY\t\t( -10 )\t/* Out of memory */\n#define CRYPT_ERROR_NOTINITED\t( -11 )\t/* Data has not been initialised */\n#define CRYPT_ERROR_INITED\t\t( -12 )\t/* Data has already been init'd */\n#define CRYPT_ERROR_NOSECURE\t( -13 )\t/* Opn.not avail.at requested sec.level */\n#define CRYPT_ERROR_RANDOM\t\t( -14 )\t/* No reliable random data available */\n#define CRYPT_ERROR_FAILED\t\t( -15 )\t/* Operation failed */\n#define CRYPT_ERROR_INTERNAL\t( -16 )\t/* Internal consistency check failed */\n\n/* Security violations */\n\n#define CRYPT_ERROR_NOTAVAIL\t( -20 )\t/* This type of opn.not available */\n#define CRYPT_ERROR_PERMISSION\t( -21 )\t/* No permiss.to perform this operation */\n#define CRYPT_ERROR_WRONGKEY\t( -22 )\t/* Incorrect key used to decrypt data */\n#define CRYPT_ERROR_INCOMPLETE\t( -23 )\t/* Operation incomplete/still in progress */\n#define CRYPT_ERROR_COMPLETE\t( -24 )\t/* Operation complete/can't continue */\n#define CRYPT_ERROR_TIMEOUT\t\t( -25 )\t/* Operation timed out before completion */\n#define CRYPT_ERROR_INVALID\t\t( -26 )\t/* Invalid/inconsistent information */\n#define CRYPT_ERROR_SIGNALLED\t( -27 )\t/* Resource destroyed by extnl.event */\n\n/* High-level function errors */\n\n#define CRYPT_ERROR_OVERFLOW\t( -30 )\t/* Resources/space exhausted */\n#define CRYPT_ERROR_UNDERFLOW\t( -31 )\t/* Not enough data available */\n#define CRYPT_ERROR_BADDATA\t\t( -32 )\t/* Bad/unrecognised data format */\n#define CRYPT_ERROR_SIGNATURE\t( -33 )\t/* Signature/integrity check failed */\n\n/* Data access function errors */\n\n#define CRYPT_ERROR_OPEN\t\t( -40 )\t/* Cannot open object */\n#define CRYPT_ERROR_READ\t\t( -41 )\t/* Cannot read item from object */\n#define CRYPT_ERROR_WRITE\t\t( -42 )\t/* Cannot write item to object */\n#define CRYPT_ERROR_NOTFOUND\t( -43 )\t/* Requested item not found in object */\n#define CRYPT_ERROR_DUPLICATE\t( -44 )\t/* Item already present in object */\n\n/* Data enveloping errors */\n\n#define CRYPT_ENVELOPE_RESOURCE\t( -50 )\t/* Need resource to proceed */\n\n/* Macros to examine return values */\n\n#define cryptStatusError( status )\t( ( status ) < CRYPT_OK )\n#define cryptStatusOK( status )\t\t( ( status ) == CRYPT_OK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tGeneral Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following is necessary to stop C++ name mangling */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n\n/* Initialise and shut down cryptlib */\n\nC_CHECK_RETVAL \\\nC_RET cryptInit( void );\nC_RET cryptEnd( void );\n\n/* Query cryptlibs capabilities */\n\nC_CHECK_RETVAL \\\nC_RET cryptQueryCapability( C_IN CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\tC_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo );\n\n/* Create and destroy an encryption context */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateContext( C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t  C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t  C_IN CRYPT_ALGO_TYPE cryptAlgo );\nC_RET cryptDestroyContext( C_IN CRYPT_CONTEXT cryptContext );\n\n/* Generic \"destroy an object\" function */\n\nC_RET cryptDestroyObject( C_IN CRYPT_HANDLE cryptObject );\n\n/* Generate a key into a context */\n\nC_CHECK_RETVAL \\\nC_RET cryptGenerateKey( C_IN CRYPT_CONTEXT cryptContext );\n\n/* Encrypt/decrypt/hash a block of memory */\n\nC_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptEncrypt( C_IN CRYPT_CONTEXT cryptContext, C_INOUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length );\nC_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptDecrypt( C_IN CRYPT_CONTEXT cryptContext, C_INOUT void C_PTR buffer,\n\t\t\t\t\tC_IN int length );\n\n/* Get/set/delete attribute functions */\n\nC_RET cryptSetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t C_IN int value );\nC_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptSetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t   C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t   C_IN void C_PTR value, C_IN int valueLength );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptGetAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t C_OUT int C_PTR value );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 4 ) ) \\\nC_RET cryptGetAttributeString( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t   C_IN CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t   C_OUT_OPT void C_PTR value,\n\t\t\t\t\t\t\t   C_OUT int C_PTR valueLength );\nC_RET cryptDeleteAttribute( C_IN CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\tC_IN CRYPT_ATTRIBUTE_TYPE attributeType );\n\n/* Oddball functions: Add random data to the pool, query an encoded signature\n   or key data.  These are due to be replaced once a suitable alternative can\n   be found */\n\nC_RET cryptAddRandom( C_IN void C_PTR randomData, C_IN int randomDataLength );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 3 ) ) \\\nC_RET cryptQueryObject( C_IN void C_PTR objectData,\n\t\t\t\t\t\tC_IN int objectDataLength,\n\t\t\t\t\t    C_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMid-level Encryption Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export and import an encrypted session key */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptExportKey( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyMaxLength,\n\t\t\t\t\t  C_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptExportKeyEx( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyMaxLength,\n\t\t\t\t\t\tC_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\tC_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptImportKey( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext,\n\t\t\t\t\t\tC_OUT_OPT CRYPT_CONTEXT C_PTR returnedContext );\n\n/* Create and check a digital signature */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptCreateSignature( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\tC_IN int signatureMaxLength,\n\t\t\t\t\t\t\tC_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT hashContext );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptCreateSignatureEx( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\t  C_IN int signatureMaxLength,\n\t\t\t\t\t\t\t  C_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\t  C_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_CERTIFICATE extraData );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCheckSignature( C_IN void C_PTR signature,\n\t\t\t\t\t\t   C_IN int signatureLength,\n\t\t\t\t\t\t   C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t   C_IN CRYPT_CONTEXT hashContext );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCheckSignatureEx( C_IN void C_PTR signature,\n\t\t\t\t\t\t\t C_IN int signatureLength,\n\t\t\t\t\t\t\t C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t C_OUT_OPT CRYPT_HANDLE C_PTR extraData );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKeyset Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open and close a keyset */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \\\nC_RET cryptKeysetOpen( C_OUT CRYPT_KEYSET C_PTR keyset,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t   C_IN C_STR name, C_IN CRYPT_KEYOPT_TYPE options );\nC_RET cryptKeysetClose( C_IN CRYPT_KEYSET keyset );\n\n/* Get a key from a keyset or device */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptGetPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN_OPT C_STR keyID );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptGetPrivateKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t  C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t  C_IN C_STR keyID, C_IN_OPT C_STR password );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptGetKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t   C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t   C_IN CRYPT_KEYID_TYPE keyIDtype, C_IN C_STR keyID, \n\t\t\t\t   C_IN_OPT C_STR password );\n\n/* Add/delete a key to/from a keyset or device */\n\nC_CHECK_RETVAL \\\nC_RET cryptAddPublicKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certificate );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptAddPrivateKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t  C_IN CRYPT_HANDLE cryptKey,\n\t\t\t\t\t\t  C_IN C_STR password );\nC_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptDeleteKey( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN C_STR keyID );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCertificate Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create/destroy a certificate */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateCert( C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_CERTTYPE_TYPE certType );\nC_RET cryptDestroyCert( C_IN CRYPT_CERTIFICATE certificate );\n\n/* Get/add/delete certificate extensions.  These are direct data insertion\n   functions whose use is discouraged, so they fix the string at char *\n   rather than C_STR */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3, 6 ) ) \\\nC_RET cryptGetCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid,\n\t\t\t\t\t\t\t C_OUT int C_PTR criticalFlag,\n\t\t\t\t\t\t\t C_OUT_OPT void C_PTR extension,\n\t\t\t\t\t\t\t C_IN int extensionMaxLength,\n\t\t\t\t\t\t\t C_OUT int C_PTR extensionLength );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptAddCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t C_IN char C_PTR oid, C_IN int criticalFlag,\n\t\t\t\t\t\t\t C_IN void C_PTR extension,\n\t\t\t\t\t\t\t C_IN int extensionLength );\nC_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptDeleteCertExtension( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t    C_IN char C_PTR oid );\n\n/* Sign/sig.check a certificate/certification request */\n\nC_CHECK_RETVAL \\\nC_RET cryptSignCert( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t C_IN CRYPT_CONTEXT signContext );\nC_CHECK_RETVAL \\\nC_RET cryptCheckCert( C_IN CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t  C_IN CRYPT_HANDLE sigCheckKey );\n\n/* Import/export a certificate/certification request */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 4 ) ) \\\nC_RET cryptImportCert( C_IN void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_OUT CRYPT_CERTIFICATE C_PTR certificate );\nC_CHECK_RETVAL \\\nC_RET cryptExportCert( C_OUT_OPT void C_PTR certObject,\n\t\t\t\t\t   C_IN int certObjectMaxLength,\n\t\t\t\t\t   C_OUT int C_PTR certObjectLength,\n\t\t\t\t\t   C_IN CRYPT_CERTFORMAT_TYPE certFormatType,\n\t\t\t\t\t   C_IN CRYPT_CERTIFICATE certificate );\n\n/* CA management functions */\n\nC_CHECK_RETVAL \\\nC_RET cryptCAAddItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_IN CRYPT_CERTIFICATE certificate );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptCAGetItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t  C_OUT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t  C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t  C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t  C_IN_OPT C_STR keyID );\nC_NONNULL_ARG( ( 4 ) ) \\\nC_RET cryptCADeleteItem( C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t C_IN CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t\t C_IN CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t C_IN C_STR keyID );\nC_CHECK_RETVAL \\\nC_RET cryptCACertManagement( C_OUT_OPT CRYPT_CERTIFICATE C_PTR certificate,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t\t\t C_IN CRYPT_KEYSET keyset,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT caKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CERTIFICATE certRequest );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope and Session Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create/destroy an envelope */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateEnvelope( C_OUT CRYPT_ENVELOPE C_PTR envelope,\n\t\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t   C_IN CRYPT_FORMAT_TYPE formatType );\nC_RET cryptDestroyEnvelope( C_IN CRYPT_ENVELOPE envelope );\n\n/* Create/destroy a session */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCreateSession( C_OUT CRYPT_SESSION C_PTR session,\n\t\t\t\t\t\t  C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t\t  C_IN CRYPT_SESSION_TYPE formatType );\nC_RET cryptDestroySession( C_IN CRYPT_SESSION session );\n\n/* Add/remove data to/from and envelope or session */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptPushData( C_IN CRYPT_HANDLE envelope, C_IN void C_PTR buffer,\n\t\t\t\t\t C_IN int length, C_OUT int C_PTR bytesCopied );\nC_CHECK_RETVAL \\\nC_RET cryptFlushData( C_IN CRYPT_HANDLE envelope );\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 4 ) ) \\\nC_RET cryptPopData( C_IN CRYPT_HANDLE envelope, C_OUT void C_PTR buffer,\n\t\t\t\t    C_IN int length, C_OUT int C_PTR bytesCopied );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDevice Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open and close a device */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptDeviceOpen( C_OUT CRYPT_DEVICE C_PTR device,\n\t\t\t\t\t   C_IN CRYPT_USER cryptUser,\n\t\t\t\t\t   C_IN CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t   C_IN_OPT C_STR name );\nC_RET cryptDeviceClose( C_IN CRYPT_DEVICE device );\n\n/* Query a devices capabilities */\n\nC_CHECK_RETVAL \\\nC_RET cryptDeviceQueryCapability( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t\t  C_IN CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t  C_OUT_OPT CRYPT_QUERY_INFO C_PTR cryptQueryInfo );\n\n/* Create an encryption context via the device */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2 ) ) \\\nC_RET cryptDeviceCreateContext( C_IN CRYPT_DEVICE device,\n\t\t\t\t\t\t\t    C_OUT CRYPT_CONTEXT C_PTR cryptContext,\n\t\t\t\t\t\t\t    C_IN CRYPT_ALGO_TYPE cryptAlgo );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUser Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Log on and off (create/destroy a user object) */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nC_RET cryptLogin( C_OUT CRYPT_USER C_PTR user,\n\t\t\t\t  C_IN C_STR name, C_IN C_STR password );\nC_RET cryptLogout( C_IN CRYPT_USER user );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDirect API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef CONFIG_DIRECT_API\n\ntypedef C_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3 ) ) \\\n\t\tint ( *CRYPT_DIRECT_FUNCTION )( void *contextPtr, void *buffer, \n\t\t\t\t\t\t\t\t\t\tconst int length );\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 2, 3 ) ) \\\nC_RET cryptGetDirectAPI( C_IN CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\t C_OUT void C_PTR C_PTR contextPtr,\n\t\t\t\t\t\t C_OUT CRYPT_DIRECT_FUNCTION C_PTR encryptFunction,\n\t\t\t\t\t\t C_OUT CRYPT_DIRECT_FUNCTION C_PTR decryptFunction );\n\n#endif /* CONFIG_DIRECT_API */\n\n#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n\n#endif /* _CRYPTLIB_DEFINED */\n"
  },
  {
    "path": "deps/cl345/cryptlib.sld",
    "content": "; cryptlib Library Definition File for PalmOS\n;\n; We need at least PalmOS 5 (more likely 6) to run.\n\nOSVERSION\t5\nARMARCH\t\t0\nREVISION\t3\nRESOURCEID\t0\n\n; Library type (shared lib) and creator\n\nTYPE\t\tslib\nCREATOR\t\tclib\n\n; Shared libraries must have one library entry function.\n\nENTRY\t\tcryptlibMain\n\n; Exported functions.  Note that the blank line after the EXPORTS\n; keyword is required.\n\nEXPORTS\n\t\t\tcryptAddCertExtension\n\t\t\tcryptAddPrivateKey\n\t\t\tcryptAddPublicKey\n\t\t\tcryptAddRandom\n\t\t\tcryptAsyncCancel\n\t\t\tcryptAsyncQuery\n\t\t\tcryptCAAddItem\n\t\t\tcryptCACertManagement\n\t\t\tcryptCADeleteItem\n\t\t\tcryptCAGetItem\n\t\t\tcryptCheckCert\n\t\t\tcryptCheckSignature\n\t\t\tcryptCheckSignatureEx\n\t\t\tcryptCreateCert\n\t\t\tcryptCreateContext\n\t\t\tcryptCreateEnvelope\n\t\t\tcryptCreateSession\n\t\t\tcryptCreateSignature\n\t\t\tcryptCreateSignatureEx\n\t\t\tcryptDecrypt\n\t\t\tcryptDeleteAttribute\n\t\t\tcryptDeleteCertExtension\n\t\t\tcryptDeleteKey\n\t\t\tcryptDestroyCert\n\t\t\tcryptDestroyContext\n\t\t\tcryptDestroyEnvelope\n\t\t\tcryptDestroyObject\n\t\t\tcryptDestroySession\n\t\t\tcryptDeviceClose\n\t\t\tcryptDeviceCreateContext\n\t\t\tcryptDeviceOpen\n\t\t\tcryptDeviceQueryCapability\n\t\t\tcryptEncrypt\n\t\t\tcryptEnd\n\t\t\tcryptExportCert\n\t\t\tcryptExportKey\n\t\t\tcryptExportKeyEx\n\t\t\tcryptFlushData\n\t\t\tcryptGenerateKey\n\t\t\tcryptGenerateKeyAsync\n\t\t\tcryptGetAttribute\n\t\t\tcryptGetAttributeString\n\t\t\tcryptGetCertExtension\n\t\t\tcryptGetKey\n\t\t\tcryptGetPrivateKey\n\t\t\tcryptGetPublicKey\n\t\t\tcryptImportCert\n\t\t\tcryptImportKey\n\t\t\tcryptImportKeyEx\n\t\t\tcryptInit\n\t\t\tcryptKeysetClose\n\t\t\tcryptKeysetOpen\n\t\t\tcryptLogin\n\t\t\tcryptLogout\n\t\t\tcryptPopData\n\t\t\tcryptPushData\n\t\t\tcryptQueryCapability\n\t\t\tcryptQueryObject\n\t\t\tcryptSetAttribute\n\t\t\tcryptSetAttributeString\n\t\t\tcryptSignCert\n"
  },
  {
    "path": "deps/cl345/cryptses.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Secure Session Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"asn1.h\"\n  #include \"stream.h\"\n  #include \"session.h\"\n  #include \"scorebrd.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"io/stream.h\"\n  #include \"session/session.h\"\n  #include \"session/scorebrd.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check overall session data.  This is a general check for \n   reasonable values that's more targeted at catching inadvertent memory \n   corruption than a strict sanity check, protocol-specific sanity checks are\n   performed by individual modules */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkObjectHandle( const CRYPT_HANDLE cryptHandle )\n\t{\n\treturn( ( cryptHandle == CRYPT_ERROR || \\\n\t\t\t  isHandleRangeValid( cryptHandle ) ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSession( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Check general session data */\n\tif( !isEnumRange( sessionInfoPtr->type, CRYPT_SESSION ) || \\\n\t\tsessionInfoPtr->version < 0 || sessionInfoPtr->version > 5 \n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\t\t|| !isEnumRangeOpt( sessionInfoPtr->subProtocol, CRYPT_SUBPROTOCOL ) \n#endif /* USE_WEBSOCKETS || USE_EAP */\n\t\t)\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !CHECK_FLAGS( sessionInfoPtr->flags, \n\t\t\t\t\t  SESSION_FLAG_NONE, SESSION_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t!isConvAlgo( sessionInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Crypt algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->integrityAlgo != CRYPT_ALGO_NONE && \\\n\t\t!isHashAlgo( sessionInfoPtr->integrityAlgo ) && \\\n\t\t!isMacAlgo( sessionInfoPtr->integrityAlgo ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Integrity algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( sessionInfoPtr->authResponse, AUTHRESPONSE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Auth response\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->clientReqAttrFlags < SESSION_NEEDS_NONE || \\\n\t\tsessionInfoPtr->clientReqAttrFlags > SESSION_NEEDS_MAX || \\\n\t\tsessionInfoPtr->serverReqAttrFlags < SESSION_NEEDS_NONE || \\\n\t\tsessionInfoPtr->serverReqAttrFlags > SESSION_NEEDS_MAX )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Client/server attribute flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers.  We don't have to check the function pointers\n\t   because they're validated each time they're dereferenced */\n\tif( !DATAPTR_ISVALID( sessionInfoPtr->protocolInfo ) || \\\n\t\t!DATAPTR_ISVALID( sessionInfoPtr->attributeList ) || \\\n\t\t!DATAPTR_ISVALID( sessionInfoPtr->attributeListCurrent ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Attribute list\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check data buffer information */\n\tif( !sanityCheckSessionRead( sessionInfoPtr ) || \\\n\t\t!sanityCheckSessionWrite( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Buffer information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check crypto information */\n\tif( !checkObjectHandle( sessionInfoPtr->iKeyexCryptContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iKeyexAuthContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iCryptInContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iCryptOutContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iAuthInContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iAuthOutContext ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iCertRequest ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->iCertResponse ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->privateKey ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->cryptKeyset ) || \\\n\t\t!checkObjectHandle( sessionInfoPtr->privKeyset ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Crypto object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( ( sessionInfoPtr->cryptBlocksize != 0 && \\\n\t\t  sessionInfoPtr->cryptBlocksize != 1 &&\t\t/* Stream cipher */ \n\t\t  ( sessionInfoPtr->cryptBlocksize < MIN_IVSIZE || \\\n\t\t\tsessionInfoPtr->cryptBlocksize > CRYPT_MAX_IVSIZE ) ) || \\\n\t\t( sessionInfoPtr->authBlocksize != 0 && \\\n\t\t  ( sessionInfoPtr->authBlocksize < MIN_HASHSIZE || \\\n\t\t\tsessionInfoPtr->authBlocksize > CRYPT_MAX_HASHSIZE ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Crypt/auth block size\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check network information */\n\tif( TEST_FLAG( sessionInfoPtr->flags,\n\t\t\t\t   SESSION_FLAG_PARTIALOPEN | SESSION_FLAG_ISOPEN ) )\n\t\t{\n\t\t/* Before the session is activated, one or more of these can be set\n\t\t   to CRYPT_ERROR to indicate that they're not set yet */\n\t\tif( sessionInfoPtr->readTimeout < 0 || \\\n\t\t\tsessionInfoPtr->readTimeout > MAX_NETWORK_TIMEOUT || \\\n\t\t\tsessionInfoPtr->writeTimeout < 0 || \\\n\t\t\tsessionInfoPtr->writeTimeout > MAX_NETWORK_TIMEOUT || \\\n\t\t\tsessionInfoPtr->connectTimeout < 5 || \\\n\t\t\tsessionInfoPtr->connectTimeout > MAX_NETWORK_TIMEOUT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSession: Timeouts\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check associated handles */\n\tif( !isHandleRangeValid( sessionInfoPtr->objectHandle ) || \\\n\t\t!( sessionInfoPtr->ownerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t   isHandleRangeValid( sessionInfoPtr->ownerHandle ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSession: Object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckProtocolInfo( const PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isReadPtr( protocolInfo, sizeof( PROTOCOL_INFO ) ) );\n\n\t/* Check general information */\n\tif( !isFlagRangeZ( protocolInfo->flags, SESSION ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( protocolInfo->version < 0 || protocolInfo->version >= 5 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Protocol version\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check buffer/packet size information */\n\tif( protocolInfo->isReqResp != TRUE && protocolInfo->isReqResp != FALSE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Request/response indicator\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( protocolInfo->isReqResp )\n\t\t{\n\t\tif( protocolInfo->bufSize != 0 || \\\n\t\t\tprotocolInfo->sendBufStartOfs != 0 || \\\n\t\t\tprotocolInfo->maxPacketSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Request/response protocol buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( protocolInfo->bufSize < MIN_BUFFER_SIZE || \\\n\t\t\tprotocolInfo->bufSize >= MAX_BUFFER_SIZE || \\\n\t\t\tprotocolInfo->sendBufStartOfs < 5 || \n\t\t\tprotocolInfo->sendBufStartOfs >= protocolInfo->maxPacketSize || \\\n\t\t\tprotocolInfo->maxPacketSize > protocolInfo->bufSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Transport protocol buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check network information */\n\tif( protocolInfo->port <= 21 || protocolInfo->port > 65534L || \\\n\t\t( ( protocolInfo->flags & SESSION_FLAG_ISHTTPTRANSPORT ) && \\\n\t\t\tprotocolInfo->port != 80 ) || \\\n\t\t( !( protocolInfo->flags & SESSION_FLAG_ISHTTPTRANSPORT ) && \\\n\t\t\tprotocolInfo->port == 80 ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckProtocolInfo: Network port\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkSessionFunctions( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_B( protocolInfo != NULL );\n\tREQUIRES_B( sanityCheckProtocolInfo( protocolInfo ) );\n\n\t/* We can't call sanityCheckSession() at this point because the storage\n\t   for the session data that we want to sanity-check hasn't been set\n\t   up yet.  The best that we can do is perform a subset of the standard\n\t   sanity checks */ \n\n\t/* Check function pointers */\n\tif( !FNPTR_ISSET( sessionInfoPtr->shutdownFunction ) || \\\n\t\t!FNPTR_ISSET( sessionInfoPtr->connectFunction ) || \\\n\t\t!FNPTR_ISSET( sessionInfoPtr->transactFunction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"checkSessionFunctions: General functions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( protocolInfo->isReqResp )\n\t\t{\n\t\tif( !FNPTR_ISNULL( sessionInfoPtr->readHeaderFunction ) || \\\n\t\t\t!FNPTR_ISNULL( sessionInfoPtr->processBodyFunction ) || \\\n\t\t\t!FNPTR_ISNULL( sessionInfoPtr->preparePacketFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"checkSessionFunctions: Spurious data transfer functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !FNPTR_ISSET( sessionInfoPtr->readHeaderFunction ) || \\\n\t\t\t!FNPTR_ISSET( sessionInfoPtr->processBodyFunction ) || \\\n\t\t\t!FNPTR_ISSET( sessionInfoPtr->preparePacketFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"checkSessionFunctions: Data transfer functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSession Message Handler\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle a message sent to a session object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sessionMessageFunction( INOUT TYPECAST( CONTEXT_INFO * ) \\\n\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t   void *messageDataPtr,\n\t\t\t\t\t\t\t\t   IN_INT_Z const int messageValue )\n\t{\n\tSESSION_INFO *sessionInfoPtr = ( SESSION_INFO * ) objectInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( message == MESSAGE_DESTROY || \\\n\t\t\t  sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isIntegerRange( messageValue ) );\n\n\t/* Process destroy object messages */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* Close the session.  Since we're about to destroy/delete the \n\t\t   session object anyway, we ignore any error return value */\n\t\t( void ) closeSession( sessionInfoPtr );\n\n\t\t/* Clear session attributes if necessary */\n\t\tif( DATAPTR_ISSET( sessionInfoPtr->attributeList ) )\n\t\t\tdeleteSessionInfoAll( sessionInfoPtr );\n\n\t\t/* Clear and free session state information if necessary.  Note that \n\t\t   this has to follow the deletion of session attributes since the \n\t\t   sanity check performed there detects the missingn session \n\t\t   buffers if they're cleared first */\n\t\tif( sessionInfoPtr->sendBuffer != NULL )\n\t\t\t{\n\t\t\tzeroise( sessionInfoPtr->sendBuffer,\n\t\t\t\t\t sessionInfoPtr->sendBufSize );\n\t\t\tsafeBufferFree( sessionInfoPtr->sendBuffer );\n\t\t\tsessionInfoPtr->sendBuffer = NULL;\n\t\t\t}\n\t\tif( sessionInfoPtr->receiveBuffer != NULL )\n\t\t\t{\n\t\t\tzeroise( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufSize );\n\t\t\tsafeBufferFree( sessionInfoPtr->receiveBuffer );\n\t\t\tsessionInfoPtr->receiveBuffer = NULL;\n\t\t\t}\n\n\t\t/* Clean up any session-related objects if necessary */\n\t\tif( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iKeyexAuthContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iKeyexAuthContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iCertRequest != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->iCertResponse != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->privateKey != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( sessionInfoPtr->privKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sessionInfoPtr->privKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\t/* If it's a protocol-specific attribute, forward it directly to\n\t\t   the low-level code */\n\t\tif( message != MESSAGE_DELETEATTRIBUTE && \\\n\t\t\t( ( messageValue >= CRYPT_SESSINFO_FIRST_SPECIFIC && \\\n\t\t\t\tmessageValue <= CRYPT_SESSINFO_LAST_SPECIFIC ) || \\\n\t\t\t  messageValue == CRYPT_IATTRIBUTE_ENC_TIMESTAMP ) )\n\t\t\t{\n\t\t\tif( message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\tmessage == MESSAGE_SETATTRIBUTE_S )\n\t\t\t\t{\n\t\t\t\tconst SES_SETATTRIBUTE_FUNCTION setAttributeFunction = \\\n\t\t\t\t\t\t\t( SES_SETATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( sessionInfoPtr->setAttributeFunction );\n\n\t\t\t\tREQUIRES( setAttributeFunction != NULL );\n\n\t\t\t\t/* Perform any protocol-specific additional checks if \n\t\t\t\t   necessary */\n\t\t\t\tif( FNPTR_ISSET( sessionInfoPtr->checkAttributeFunction ) )\n\t\t\t\t\t{\n\t\t\t\t\tconst SES_CHECKATTRIBUTE_FUNCTION checkAttributeFunction = \\\n\t\t\t\t\t\t\t( SES_CHECKATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( sessionInfoPtr->checkAttributeFunction );\n\n\t\t\t\t\tREQUIRES( checkAttributeFunction != NULL );\n\n\t\t\t\t\tstatus = checkAttributeFunction( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tmessageDataPtr, messageValue );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\n\t\t\t\tstatus = setAttributeFunction( sessionInfoPtr, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t\t   messageValue );\n\t\t\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( sessionInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst SES_GETATTRIBUTE_FUNCTION getAttributeFunction = \\\n\t\t\t\t\t\t\t( SES_GETATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( sessionInfoPtr->getAttributeFunction );\n\n\t\t\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S );\n\t\t\t\tREQUIRES( getAttributeFunction != NULL );\n\n\t\t\t\tstatus = getAttributeFunction( sessionInfoPtr, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t\t   messageValue );\n\t\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( sessionInfoPtr, messageValue, \n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getSessionAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t ( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getSessionAttributeS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( setSessionAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t *( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t\t messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setSessionAttributeS( sessionInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t\t  msgData->length, messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_DELETEATTRIBUTE )\n\t\t\treturn( deleteSessionAttribute( sessionInfoPtr, messageValue ) );\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_ENV_PUSHDATA )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\t\tconst int length = msgData->length;\n\t\tint bytesCopied;\n\n\t\t/* Unless we're told otherwise, we've copied zero bytes */\n\t\tmsgData->length = 0;\n\n\t\t/* If the session isn't open yet, perform an implicit open */\n\t\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_ACTIVE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* The session is ready to process data, move it into the high\n\t\t\t   state */\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) );\n\t\tENSURES( sessionInfoPtr->sendBuffer != NULL );\n\n\t\t/* Make sure that everything is in order */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED ) )\n\t\t\t{\n\t\t\t/* If the other side has closed its receive channel (which is \n\t\t\t   our send channel), we can't send any more data, although we \n\t\t\t   can still get data on our receive channel if we haven't closed\n\t\t\t   it as well.  The closing of the other side's send channel is \n\t\t\t   detected during a read and isn't a write error but a normal \n\t\t\t   state change in the channel so we don't treat it as an error \n\t\t\t   when it's seen at the read stage until the caller actually \n\t\t\t   tries to write data to the closed channel */\n\t\t\tsessionInfoPtr->writeErrorState = CRYPT_ERROR_COMPLETE;\n\t\t\t}\n\t\tif( sessionInfoPtr->writeErrorState != CRYPT_OK )\n\t\t\treturn( sessionInfoPtr->writeErrorState );\n\n\t\t/* Write the data */\n\t\tclearErrorInfo( sessionInfoPtr );\n\t\tstatus = putSessionData( sessionInfoPtr, msgData->data, length, \n\t\t\t\t\t\t\t\t &bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmsgData->length = bytesCopied;\n\t\tENSURES( ( cryptStatusError( status ) && bytesCopied == 0 ) || \\\n\t\t\t\t ( cryptStatusOK( status ) && bytesCopied >= 0 ) );\n\t\treturn( status );\n\t\t}\n\tif( message == MESSAGE_ENV_POPDATA )\n\t\t{\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\t\tconst int length = msgData->length;\n\t\tint bytesCopied;\n\n\t\t/* Unless we're told otherwise, we've copied zero bytes */\n\t\tmsgData->length = 0;\n\n\t\t/* If the session isn't open, there's nothing to pop */\n\t\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t\tENSURES( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) );\n\t\tENSURES( sessionInfoPtr->receiveBuffer != NULL );\n\n\t\t/* Make sure that everything is in order */\n\t\tif( sessionInfoPtr->readErrorState != CRYPT_OK )\n\t\t\treturn( sessionInfoPtr->readErrorState );\n\n\t\t/* Read the data */\n\t\tclearErrorInfo( sessionInfoPtr );\n\t\tstatus = getSessionData( sessionInfoPtr, msgData->data, length,\n\t\t\t\t\t\t\t\t &bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmsgData->length = bytesCopied;\n\t\tENSURES( ( cryptStatusError( status ) && bytesCopied == 0 ) || \\\n\t\t\t\t ( cryptStatusOK( status ) && bytesCopied >= 0 ) );\n\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Open a session.  This is a low-level function encapsulated by createSession()\n   and used to manage error exits */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int openSession( OUT_HANDLE_OPT CRYPT_SESSION *iCryptSession,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\tIN_ENUM( CRYPT_SESSION ) \\\n\t\t\t\t\t\t\tconst CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t\tOUT_PTR_OPT SESSION_INFO **sessionInfoPtrPtr )\n\t{\n\tCRYPT_SESSION_TYPE sessionBaseType;\n\tSESSION_INFO *sessionInfoPtr;\n\tconst PROTOCOL_INFO *protocolInfo;\n\tstatic const MAP_TABLE subtypeMapTbl[] = {\n\t\t{ CRYPT_SESSION_SSH, SUBTYPE_SESSION_SSH },\n\t\t{ CRYPT_SESSION_SSH_SERVER, SUBTYPE_SESSION_SSH_SVR },\n\t\t{ CRYPT_SESSION_SSL, SUBTYPE_SESSION_SSL },\n\t\t{ CRYPT_SESSION_SSL_SERVER, SUBTYPE_SESSION_SSL_SVR },\n\t\t{ CRYPT_SESSION_RTCS, SUBTYPE_SESSION_RTCS },\n\t\t{ CRYPT_SESSION_RTCS_SERVER, SUBTYPE_SESSION_RTCS_SVR },\n\t\t{ CRYPT_SESSION_OCSP, SUBTYPE_SESSION_OCSP },\n\t\t{ CRYPT_SESSION_OCSP_SERVER, SUBTYPE_SESSION_OCSP_SVR },\n\t\t{ CRYPT_SESSION_TSP, SUBTYPE_SESSION_TSP },\n\t\t{ CRYPT_SESSION_TSP_SERVER, SUBTYPE_SESSION_TSP_SVR },\n\t\t{ CRYPT_SESSION_CMP, SUBTYPE_SESSION_CMP },\n\t\t{ CRYPT_SESSION_CMP_SERVER, SUBTYPE_SESSION_CMP_SVR },\n\t\t{ CRYPT_SESSION_SCEP, SUBTYPE_SESSION_SCEP },\n\t\t{ CRYPT_SESSION_SCEP_SERVER, SUBTYPE_SESSION_SCEP_SVR },\n\t\t{ CRYPT_SESSION_CERTSTORE_SERVER, SUBTYPE_SESSION_CERT_SVR },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tstatic const MAP_TABLE basetypeMapTbl[] = {\n\t\t{ CRYPT_SESSION_SSH, CRYPT_SESSION_SSH },\n\t\t{ CRYPT_SESSION_SSH_SERVER, CRYPT_SESSION_SSH },\n\t\t{ CRYPT_SESSION_SSL, CRYPT_SESSION_SSL },\n\t\t{ CRYPT_SESSION_SSL_SERVER, CRYPT_SESSION_SSL },\n\t\t{ CRYPT_SESSION_RTCS, CRYPT_SESSION_RTCS },\n\t\t{ CRYPT_SESSION_RTCS_SERVER, CRYPT_SESSION_RTCS },\n\t\t{ CRYPT_SESSION_OCSP, CRYPT_SESSION_OCSP },\n\t\t{ CRYPT_SESSION_OCSP_SERVER, CRYPT_SESSION_OCSP },\n\t\t{ CRYPT_SESSION_TSP, CRYPT_SESSION_TSP },\n\t\t{ CRYPT_SESSION_TSP_SERVER, CRYPT_SESSION_TSP },\n\t\t{ CRYPT_SESSION_CMP, CRYPT_SESSION_CMP },\n\t\t{ CRYPT_SESSION_CMP_SERVER, CRYPT_SESSION_CMP },\n\t\t{ CRYPT_SESSION_SCEP, CRYPT_SESSION_SCEP },\n\t\t{ CRYPT_SESSION_SCEP_SERVER, CRYPT_SESSION_SCEP },\n\t\t{ CRYPT_SESSION_CERTSTORE_SERVER, CRYPT_SESSION_CERTSTORE_SERVER },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tOBJECT_SUBTYPE subType;\n\tint value, storageSize, status;\n\n\tassert( isWritePtr( iCryptSession, sizeof( CRYPT_SESSION * ) ) );\n\tassert( isWritePtr( sessionInfoPtrPtr, sizeof( SESSION_INFO * ) ) );\n\n\tREQUIRES( ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isEnumRange( sessionType, CRYPT_SESSION ) );\n\n\t/* Clear return values */\n\t*iCryptSession = CRYPT_ERROR;\n\t*sessionInfoPtrPtr = NULL;\n\n\t/* Map the external session type to a base type and internal object\n\t   subtype */\n\tstatus = mapValue( sessionType, &value, subtypeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( subtypeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsubType = value;\n\tstatus = mapValue( sessionType, &value, basetypeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( basetypeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsessionBaseType = value;\n\n\t/* Set up subtype-specific information */\n\tswitch( sessionBaseType )\n\t\t{\n\t\tcase CRYPT_SESSION_SSH:\n\t\t\tstorageSize = sizeof( SSH_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_SSL:\n\t\t\tstorageSize = sizeof( SSL_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_TSP:\n\t\t\tstorageSize = sizeof( TSP_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_CMP:\n\t\t\tstorageSize = sizeof( CMP_INFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_SCEP:\n\t\t\tstorageSize = sizeof( SCEP_INFO );\n\t\t\tbreak;\n\t\t\n\t\tcase CRYPT_SESSION_RTCS:\n\t\tcase CRYPT_SESSION_OCSP:\n\t\tcase CRYPT_SESSION_CERTSTORE_SERVER:\n\t\t\tstorageSize = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Create the session object */\n\tstatus = krnlCreateObject( iCryptSession, ( void ** ) &sessionInfoPtr, \n\t\t\t\t\t\t\t   sizeof( SESSION_INFO ) + storageSize, \n\t\t\t\t\t\t\t   OBJECT_TYPE_SESSION, subType, \n\t\t\t\t\t\t\t   CREATEOBJECT_FLAG_NONE, iCryptOwner, \n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, sessionMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( sessionInfoPtr != NULL );\n\t*sessionInfoPtrPtr = sessionInfoPtr;\n\tsessionInfoPtr->objectHandle = *iCryptSession;\n\tsessionInfoPtr->ownerHandle = iCryptOwner;\n\tsessionInfoPtr->type = sessionBaseType;\n\tif( ( sessionType != sessionBaseType ) || \\\n\t\t( sessionType == CRYPT_SESSION_CERTSTORE_SERVER ) )\n\t\t{\n\t\t/* If it's a server session, mark it as such.  An HTTP certstore \n\t\t   session is a special case in that it's always a server session */\n\t\tINIT_FLAGS( sessionInfoPtr->flags, SESSION_FLAG_ISSERVER );\n\t\t}\n\telse\n\t\tINIT_FLAGS( sessionInfoPtr->flags, SESSION_FLAG_NONE );\n\tINIT_FLAGS( sessionInfoPtr->protocolFlags, 0 );\n\tDATAPTR_SET( sessionInfoPtr->attributeList, NULL );\n\tDATAPTR_SET( sessionInfoPtr->attributeListCurrent, NULL );\n\tif( storageSize > 0 )\n\t\t{\n\t\tswitch( sessionBaseType )\n\t\t\t{\n\t\t\tcase CRYPT_SESSION_SSH:\n\t\t\t\tsessionInfoPtr->sessionSSH = \\\n\t\t\t\t\t\t\t\t( SSH_INFO * ) sessionInfoPtr->storage;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSION_SSL:\n\t\t\t\tsessionInfoPtr->sessionSSL = \\\n\t\t\t\t\t\t\t\t( SSL_INFO * ) sessionInfoPtr->storage;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSION_TSP:\n\t\t\t\tsessionInfoPtr->sessionTSP = \\\n\t\t\t\t\t\t\t\t( TSP_INFO * ) sessionInfoPtr->storage;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSION_CMP:\n\t\t\t\tsessionInfoPtr->sessionCMP = \\\n\t\t\t\t\t\t\t\t( CMP_INFO * ) sessionInfoPtr->storage;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSION_SCEP:\n\t\t\t\tsessionInfoPtr->sessionSCEP = \\\n\t\t\t\t\t\t\t\t( SCEP_INFO * ) sessionInfoPtr->storage;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tsessionInfoPtr->storageSize = storageSize;\n\n\t/* Set up any internal objects to contain invalid handles */\n\tsessionInfoPtr->iKeyexCryptContext = \\\n\t\tsessionInfoPtr->iKeyexAuthContext = CRYPT_ERROR;\n\tsessionInfoPtr->iCryptInContext = \\\n\t\tsessionInfoPtr->iCryptOutContext = CRYPT_ERROR;\n\tsessionInfoPtr->iAuthInContext = \\\n\t\tsessionInfoPtr->iAuthOutContext = CRYPT_ERROR;\n\tsessionInfoPtr->iCertRequest = \\\n\t\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\tsessionInfoPtr->privateKey = CRYPT_ERROR;\n\tsessionInfoPtr->cryptKeyset = CRYPT_ERROR;\n\tsessionInfoPtr->privKeyset =  CRYPT_ERROR;\n\tsessionInfoPtr->networkSocket = CRYPT_ERROR;\n\tsessionInfoPtr->readTimeout = \\\n\t\tsessionInfoPtr->writeTimeout = \\\n\t\t\tsessionInfoPtr->connectTimeout = CRYPT_ERROR;\n\n\t/* Set up function pointers to contain null entries */\n\tFNPTR_SET( sessionInfoPtr->shutdownFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->connectFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, NULL ); \n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->checkAttributeFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->transactFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->readHeaderFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->processBodyFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->preparePacketFunction, NULL );\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\tFNPTR_SET( sessionInfoPtr->activateOuterSubprotocolFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->closeOuterSubprotocolFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->activateInnerSubprotocolFunction, NULL );\n\tFNPTR_SET( sessionInfoPtr->closeInnerSubprotocolFunction, NULL );\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\n\t/* Set up the access information for the session and initialise it */\n\tswitch( sessionBaseType )\n\t\t{\n\t\tcase CRYPT_SESSION_CERTSTORE_SERVER:\n\t\t\tstatus = setAccessMethodCertstore( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_CMP:\n\t\t\tstatus = setAccessMethodCMP( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_RTCS:\n\t\t\tstatus = setAccessMethodRTCS( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_OCSP:\n\t\t\tstatus = setAccessMethodOCSP( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_SCEP:\n\t\t\tstatus = setAccessMethodSCEP( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_SSH:\n\t\t\tstatus = setAccessMethodSSH( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_SSL:\n\t\t\tstatus = setAccessMethodSSL( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tcase CRYPT_SESSION_TSP:\n\t\t\tstatus = setAccessMethodTSP( sessionInfoPtr );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a session type that uses the scoreboard, set up the \n\t   scoreboard information for the session */\n\tif( sessionType == CRYPT_SESSION_SSL || \\\n\t\tsessionType == CRYPT_SESSION_SSL_SERVER )\n\t\t{\n\t\tvoid *scoreboardInfo = getScoreboardInfoStorage();\n\n\t\tDATAPTR_SET( sessionInfoPtr->sessionSSL->scoreboardInfoPtr, \n\t\t\t\t\t scoreboardInfo );\n\t\t}\n\n\t/* Check that the protocol info is OK */\n\tprotocolInfo = DATAPTR_GET( sessionInfoPtr->protocolInfo );\n\tENSURES( protocolInfo != NULL );\n\tENSURES( sanityCheckProtocolInfo( protocolInfo ) );\n\n\t/* Copy mutable protocol-specific information into the session info */\n\tSET_FLAGS( sessionInfoPtr->flags, protocolInfo->flags );\n\tsessionInfoPtr->clientReqAttrFlags = protocolInfo->clientReqAttrFlags;\n\tsessionInfoPtr->serverReqAttrFlags = protocolInfo->serverReqAttrFlags;\n\tsessionInfoPtr->version = protocolInfo->version;\n\tif( protocolInfo->isReqResp )\n\t\t{\n\t\tsessionInfoPtr->sendBufSize = CRYPT_UNUSED;\n\t\tsessionInfoPtr->receiveBufSize = MIN_BUFFER_SIZE;\n\t\t}\n\telse\n\t\t{\n\t\tsessionInfoPtr->sendBufSize = sessionInfoPtr->receiveBufSize = \\\n\t\t\t\tprotocolInfo->bufSize;\n\t\tsessionInfoPtr->sendBufStartOfs = sessionInfoPtr->receiveBufStartOfs = \\\n\t\t\t\tsessionInfoPtr->sendBufPos = protocolInfo->sendBufStartOfs;\n\t\tsessionInfoPtr->maxPacketSize = protocolInfo->maxPacketSize;\n\t\t}\n\n\t/* Install default handlers if no session-specific ones are provided */\n\tstatus = initSessionIO( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check that the handlers are all OK */\n\tENSURES( checkSessionFunctions( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createSession( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t   STDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_SESSION iCryptSession;\n\tSESSION_INFO *sessionInfoPtr = NULL;\n\tint initStatus, status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( isEnumRange( createInfo->arg1, CRYPT_SESSION ) );\n\n\t/* Pass the call on to the lower-level open function */\n\tinitStatus = openSession( &iCryptSession, createInfo->cryptOwner,\n\t\t\t\t\t\t\t  createInfo->arg1, &sessionInfoPtr );\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( sessionInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\n\t\t/* Since no object has been created there's nothing to get a \n\t\t   detailed error string from, but we can at least send the \n\t\t   information to the debug output */\n\t\tDEBUG_PRINT(( \"Session create error: %s.\\n\",\n\t\t\t\t\t  ( sessionInfoPtr->errorInfo.errorStringLength > 0 ) ? \\\n\t\t\t\t\t    sessionInfoPtr->errorInfo.errorString : \\\n\t\t\t\t\t\t\"<<<No information available>>>\" ));\n\n\t\t/* The init failed, make sure that the object gets destroyed when we \n\t\t   notify the kernel that the setup process is complete */\n\t\tkrnlSendNotifier( iCryptSession, IMESSAGE_DESTROY );\n\t\t}\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCryptSession, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\tcreateInfo->cryptHandle = iCryptSession;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Generic management function for this class of object */\n\nCHECK_RETVAL \\\nint sessionManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tstatic int initLevel = 0;\n\tint status;\n\n\tREQUIRES( action == MANAGEMENT_ACTION_INIT || \\\n\t\t\t  action == MANAGEMENT_ACTION_PRE_SHUTDOWN || \\\n\t\t\t  action == MANAGEMENT_ACTION_SHUTDOWN );\n\n\tswitch( action )\n\t\t{\n\t\tcase MANAGEMENT_ACTION_INIT:\n\t\t\tstatus = netInitTCP();\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tinitLevel++;\n\t\t\t\tif( krnlIsExiting() )\n\t\t\t\t\t{\n\t\t\t\t\t/* The kernel is shutting down, exit */\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t\t}\n\t\t\t\tstatus = initScoreboard( getScoreboardInfoStorage() );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tinitLevel++;\n\t\t\treturn( status );\n\n\t\tcase MANAGEMENT_ACTION_PRE_SHUTDOWN:\n\t\t\t/* We have to wait for the driver binding to complete before we\n\t\t\t   can start the shutdown process */\n\t\t\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )\n\t\t\t\t{\n\t\t\t\t/* The kernel is shutting down, bail out */\n\t\t\t\tDEBUG_DIAG(( \"Exiting due to kernel shutdown\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t}\n\t\t\tif( initLevel > 0 )\n\t\t\t\tnetSignalShutdown();\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase MANAGEMENT_ACTION_SHUTDOWN:\n\t\t\tif( initLevel > 1 )\n\t\t\t\tendScoreboard( getScoreboardInfoStorage() );\n\t\t\tif( initLevel > 0 )\n\t\t\t\tnetEndTCP();\n\t\t\tinitLevel = 0;\n\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/cryptusr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib User Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* cryptlib's role-based access control mechanisms are present only for\n   forwards-compatibility with future cryptlib versions that will include\n   role-based access control if there's user demand for it.  The following\n   code implements basic user management routines, but the full role-based\n   access control functionality isn't present.  Some of the code related to\n   this is therefore present only in template form */\n\n#include <stdio.h>\t\t/* For sprintf_s() */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"trustmgr.h\"\n  #include \"user.h\"\n#else\n  #include \"cert/trustmgr.h\"\n  #include \"misc/user.h\"\n#endif /* Compiler-specific includes */\n\n/* Default user info.  The default user is a special type that has both \n   normal user and SO privileges.  This is because in its usual usage mode \n   where cryptlib is functioning as a single-user system the user doesn't \n   know about the existence of user objects and just wants everything to \n   work the way that they expect.  Because of this the default user has to \n   be able to perform the full range of available operations, requiring that \n   they appear as both a normal user and an SO.\n\n   For now the default user is marked as an SO user because the kernel checks\n   don't allow dual-type objects and some operations require that the user be\n   at least an SO user, once a distinction is made between SOs and users this\n   will need to be fixed */\n\nstatic const USER_FILE_INFO defaultUserInfo = {\n#if 0\t/* 18/05/02 Disabled since ACL checks are messed up by the existence\n\t\t   of dual-user roles */\n\tCRYPT_USER_NONE,\t\t\t\t/* Special-case SO+normal user */\n#else\n\tCRYPT_USER_SO,\t\t\t\t\t/* Special-case SO user */\n#endif /* 0 */\n\tUSER_STATE_USERINITED,\t\t\t/* Initialised, ready for use */\n\t\"Default cryptlib user\", 21,\t/* Pre-set user name */\n\t\"<<<<DEFAULT_USER>>>>\", \"<<<<DEFAULT_USER>>>>\",\n\tCRYPT_UNUSED\t\t\t\t\t/* No corresponding user file */\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process user-object-specific messages */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processUserManagement( INOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\t\t\t  STDC_UNUSED void *userMgtInfo, \n\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_USERMGMT ) \\\n\t\t\t\t\t\t\t\t\tconst MESSAGE_USERMGMT_TYPE userMgtType )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\t\n\tREQUIRES( isEnumRange( userMgtType, MESSAGE_USERMGMT ) );\n\n\tswitch( userMgtType )\n\t\t{\n\t\tcase MESSAGE_USERMGMT_ZEROISE:\n\t\t\tSET_FLAG( userInfoPtr->flags, USER_FLAG_ZEROISE );\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n#ifdef USE_CERTIFICATES\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processTrustManagement( INOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\t\t\t   INOUT_HANDLE CRYPT_HANDLE *iCertificate, \n\t\t\t\t\t\t\t\t   IN_ENUM( MESSAGE_TRUSTMGMT ) \\\n\t\t\t\t\t\t\t\t\tconst MESSAGE_TRUSTMGMT_TYPE trustMgtType )\n\t{\n\tint status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_HANDLE ) ) );\n\n\tREQUIRES( isEnumRange( trustMgtType, MESSAGE_TRUSTMGMT ) );\n\n\tswitch( trustMgtType )\n\t\t{\n\t\tcase MESSAGE_TRUSTMGMT_ADD:\n\t\t\t/* Add the cert to the trust info */\n\t\t\tstatus = addTrustEntry( userInfoPtr->trustInfo, \n\t\t\t\t\t\t\t\t\t*iCertificate, NULL, 0, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tuserInfoPtr->trustInfoChanged = TRUE;\n\t\t\treturn( setOption( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t   userInfoPtr->configOptionsCount,\n\t\t\t\t\t\t\t   CRYPT_OPTION_CONFIGCHANGED, TRUE ) );\n\n\t\tcase MESSAGE_TRUSTMGMT_DELETE:\n\t\t\t{\n\t\t\tvoid *entryToDelete;\n\n\t\t\t/* Find the entry to delete and remove it (fides, ut anima, unde \n\t\t\t   abiit eo nunquam redit - Publius Syrus) */\n\t\t\tif( ( entryToDelete = findTrustEntry( userInfoPtr->trustInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t  *iCertificate, FALSE ) ) == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tdeleteTrustEntry( userInfoPtr->trustInfo, entryToDelete );\n\t\t\tuserInfoPtr->trustInfoChanged = TRUE;\n\t\t\treturn( setOption( userInfoPtr->configOptions,\n\t\t\t\t\t\t\t   userInfoPtr->configOptionsCount,\n\t\t\t\t\t\t\t   CRYPT_OPTION_CONFIGCHANGED, TRUE ) );\n\t\t\t}\n\n\t\tcase MESSAGE_TRUSTMGMT_CHECK:\n\t\t\t/* Check whether the cert is present in the trusted certs\n\t\t\t   collection */\n\t\t\treturn( ( findTrustEntry( userInfoPtr->trustInfo, \n\t\t\t\t\t\t\t\t\t  *iCertificate, FALSE ) != NULL ) ? \\\n\t\t\t\t\tCRYPT_OK : CRYPT_ERROR_INVALID );\n\n\t\tcase MESSAGE_TRUSTMGMT_GETISSUER:\n\t\t\t{\n\t\t\tvoid *trustedIssuerInfo;\n\n\t\t\t/* Get the trusted issuer of this certificate */\n\t\t\ttrustedIssuerInfo = findTrustEntry( userInfoPtr->trustInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t*iCertificate, TRUE );\n\t\t\tif( trustedIssuerInfo == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t\t/* Get the issuer cert and return it to the caller */\n\t\t\treturn( getTrustedCert( trustedIssuerInfo, iCertificate ) );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_CERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGeneral User Object Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle a message sent to a user object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int userMessageFunction( INOUT TYPECAST( USER_INFO * ) \\\n\t\t\t\t\t\t\t\t\tvoid *objectInfoPtr,\n\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\tvoid *messageDataPtr, \n\t\t\t\t\t\t\t\tIN_INT_Z const int messageValue )\n\t{\n\tUSER_INFO *userInfoPtr = ( USER_INFO * ) objectInfoPtr;\n\n\tassert( isWritePtr( objectInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isEnumRange( message, MESSAGE ) );\n\tREQUIRES( isIntegerRange( messageValue ) );\n\n\t/* Process destroy object messages */\n\tif( message == MESSAGE_DESTROY )\n\t\t{\n\t\t/* Clean up any user-related crypto objects if necessary */\n\t\tif( userInfoPtr->iCryptContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( userInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( userInfoPtr->iKeyset != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( userInfoPtr->iKeyset, IMESSAGE_DECREFCOUNT );\n\n#ifdef USE_KEYSETS\n\t\t/* If we're doing a zeroise, clear any persistent user data.  It's a\n\t\t   bit unclear what to do in case of an error at this point since \n\t\t   we're in the middle of a shutdown anyway.  We can't really cancel\n\t\t   the shutdown because the zeroise fails (what do you do if there's\n\t\t   an exception in the exception handler?) so we just have to \n\t\t   continue and ignore the failure */\n\t\tif( TEST_FLAG( userInfoPtr->flags, USER_FLAG_ZEROISE ) )\n\t\t\t( void ) zeroiseUsers( userInfoPtr );\n#endif /* USE_KEYSETS */\n\n\t\t/* Clean up the trust info and config options */\n#ifdef USE_CERTIFICATES\n\t\tif( DATAPTR_ISSET( userInfoPtr->trustInfo ) )\n\t\t\tendTrustInfo( userInfoPtr->trustInfo );\n#endif /* USE_CERTIFICATES */\n\t\tif( userInfoPtr->configOptions != NULL )\n\t\t\t{\n\t\t\tendOptions( userInfoPtr->configOptions, \n\t\t\t\t\t\tuserInfoPtr->configOptionsCount );\n\t\t\t}\n#ifdef USE_KEYSETS\n\t\tif( userInfoPtr->userIndexPtr != NULL )\n\t\t\tendUserIndex( userInfoPtr->userIndexPtr );\n#endif /* USE_KEYSETS */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're doing a zeroise, don't process any further messages except a \n\t   destroy */\n\tif( TEST_FLAG( userInfoPtr->flags, USER_FLAG_ZEROISE ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Process attribute get/set/delete messages */\n\tif( isAttributeMessage( message ) )\n\t\t{\n\t\tREQUIRES( message == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE || \\\n\t\t\t\t  message == MESSAGE_SETATTRIBUTE_S || \\\n\t\t\t\t  message == MESSAGE_DELETEATTRIBUTE );\n\t\tREQUIRES( isAttribute( messageValue ) || \\\n\t\t\t\t  isInternalAttribute( messageValue ) );\n\n\t\tif( message == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\treturn( getUserAttribute( userInfoPtr, \n\t\t\t\t\t\t\t\t\t  ( int * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_GETATTRIBUTE_S )\n\t\t\t{\n\t\t\treturn( getUserAttributeS( userInfoPtr, \n\t\t\t\t\t\t\t\t\t   ( MESSAGE_DATA * ) messageDataPtr,\n\t\t\t\t\t\t\t\t\t   messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE )\n\t\t\t{\n\t\t\t/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message \n\t\t\t   with no parameters so we don't pass it down to the attribute-\n\t\t\t   handling code */\n\t\t\tif( messageValue == CRYPT_IATTRIBUTE_INITIALISED )\n\t\t\t\t{\n\t\t\t\tREQUIRES( userInfoPtr->objectHandle == \\\n\t\t\t\t\t\t\t\tDEFAULTUSER_OBJECT_HANDLE );\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\treturn( setUserAttribute( userInfoPtr, \n\t\t\t\t\t\t\t\t\t  *( ( int * ) messageDataPtr ),\n\t\t\t\t\t\t\t\t\t  messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_SETATTRIBUTE_S )\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;\n\n\t\t\treturn( setUserAttributeS( userInfoPtr, msgData->data, \n\t\t\t\t\t\t\t\t\t   msgData->length, messageValue ) );\n\t\t\t}\n\t\tif( message == MESSAGE_DELETEATTRIBUTE )\n\t\t\treturn( deleteUserAttribute( userInfoPtr, messageValue ) );\n\n\t\tretIntError();\n\t\t}\n\n\t/* Process object-specific messages */\n\tif( message == MESSAGE_USER_USERMGMT )\n\t\t{\n\t\treturn( processUserManagement( userInfoPtr, messageDataPtr,\n\t\t\t\t\t\t\t\t\t   messageValue ) );\n\t\t}\n#ifdef USE_CERTIFICATES\n\tif( message == MESSAGE_USER_TRUSTMGMT )\n\t\t{\n\t\treturn( processTrustManagement( userInfoPtr, messageDataPtr,\n\t\t\t\t\t\t\t\t\t    messageValue ) );\n\t\t}\n#endif /* USE_CERTIFICATES */\n\n\tretIntError();\n\t}\n\n/* Open a user object.  This is a low-level function encapsulated by\n   createUser() and used to manage error exits */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int openUser( OUT_HANDLE_OPT CRYPT_USER *iCryptUser, \n\t\t\t\t\t IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t const USER_FILE_INFO *userInfoTemplate,\n\t\t\t\t\t OUT_PTR_OPT USER_INFO **userInfoPtrPtr )\n\t{\n\tUSER_INFO *userInfoPtr;\n\tUSER_FILE_INFO *userFileInfo;\n\tstatic const MAP_TABLE subtypeMapTbl[] = {\n\t\t{ CRYPT_USER_SO, SUBTYPE_USER_SO },\n\t\t{ CRYPT_USER_CA, SUBTYPE_USER_CA },\n\t\t{ CRYPT_USER_NORMAL, SUBTYPE_USER_NORMAL },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tOBJECT_SUBTYPE subType;\n\tint value, status;\n\n\tassert( isWritePtr( iCryptUser, sizeof( CRYPT_USER * ) ) );\n\tassert( isReadPtr( userInfoTemplate, sizeof( USER_FILE_INFO ) ) );\n\tassert( isWritePtr( userInfoPtrPtr, sizeof( USER_INFO * ) ) );\n\n\tREQUIRES( ( iCryptOwner == SYSTEM_OBJECT_HANDLE ) || \\\n\t\t\t  ( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\n\t/* The default user is a special type that has both normal user and SO\n\t   privileges.  This is because in its usual usage mode where cryptlib \n\t   is functioning as a single-user system the user doesn't know about \n\t   the existence of user objects and just wants everything to work the \n\t   way that they expect.  Because of this the default user has to be \n\t   able to perform the full range of available operations, requiring \n\t   that they appear as both a normal user and an SO */\n#if 0\t/* 18/05/02 Disabled since ACL checks are messed up by the existence\n\t\t   of dual-user roles */\n\tassert( userInfoTemplate->type == CRYPT_USER_NORMAL || \\\n\t\t\tuserInfoTemplate->type == CRYPT_USER_SO || \\\n\t\t\tuserInfoTemplate->type == CRYPT_USER_CA || \\\n\t\t\t( userInfoTemplate->type == CRYPT_USER_NONE && \\\n\t\t\t  userInfoTemplate->userNameLength == \\\n\t\t\t\t\t\t\t\tdefaultUserInfo.userNameLength && \\\n\t\t\t  !memcmp( userInfoTemplate->userName, defaultUserInfo.userName,\n\t\t\t\t\t   defaultUserInfo.userNameLength ) ) );\n#endif /* 0 */\n\n\t/* Clear return values */\n\t*iCryptUser = CRYPT_ERROR;\n\t*userInfoPtrPtr = NULL;\n\n\t/* Create the user object */\n\tstatus = mapValue( userInfoTemplate->type, &value, subtypeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( subtypeMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsubType = value;\n\tstatus = krnlCreateObject( iCryptUser, ( void ** ) &userInfoPtr, \n\t\t\t\t\t\t\t   sizeof( USER_INFO ), OBJECT_TYPE_USER, \n\t\t\t\t\t\t\t   subType, CREATEOBJECT_FLAG_NONE, iCryptOwner,\n\t\t\t\t\t\t\t   ACTION_PERM_NONE_ALL, userMessageFunction );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( userInfoPtr != NULL );\n\t*userInfoPtrPtr = userInfoPtr;\n\tuserInfoPtr->objectHandle = *iCryptUser;\n\tuserFileInfo = &userInfoPtr->userFileInfo;\n\tuserFileInfo->type = userInfoTemplate->type;\n\tuserFileInfo->state = userInfoTemplate->state;\n\tuserFileInfo->fileRef = userInfoTemplate->fileRef;\n\tREQUIRES( rangeCheck( userInfoTemplate->userNameLength, \n\t\t\t\t\t\t  1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( userFileInfo->userName, userInfoTemplate->userName,\n\t\t\tuserInfoTemplate->userNameLength );\n\tuserFileInfo->userNameLength = userInfoTemplate->userNameLength;\n\tmemcpy( userFileInfo->userID, userInfoTemplate->userID, KEYID_SIZE );\n\tmemcpy( userFileInfo->creatorID, userInfoTemplate->creatorID, \n\t\t\tKEYID_SIZE );\n\n\t/* Set up any internal objects to contain invalid handles */\n\tuserInfoPtr->iKeyset = userInfoPtr->iCryptContext = CRYPT_ERROR;\n\n\t/* Initialise the config options and trust info */\n#ifdef USE_CERTIFICATES\n\tstatus = initTrustInfo( &userInfoPtr->trustInfo );\n#endif /* USE_CERTIFICATES */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = initOptions( &userInfoPtr->configOptions,\n\t\t\t\t\t\t\t  &userInfoPtr->configOptionsCount );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createUser( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\tSTDC_UNUSED const void *auxDataPtr, \n\t\t\t\tSTDC_UNUSED const int auxValue )\n\t{\n\tCRYPT_USER iCryptUser;\n\tUSER_INFO *userInfoPtr;\n#ifdef USE_KEYSETS\n\tchar userFileName[ 16 + 8 ];\n#endif /* USE_KEYSETS */\n\tint fileRef, initStatus, status;\n\n\tassert( isWritePtr( createInfo, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\tREQUIRES( auxDataPtr == NULL && auxValue == 0 );\n\tREQUIRES( createInfo->strArgLen1 >= MIN_NAME_LENGTH && \\\n\t\t\t  createInfo->strArgLen1 <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( createInfo->strArgLen2 >= MIN_NAME_LENGTH && \\\n\t\t\t  createInfo->strArgLen2 <= CRYPT_MAX_TEXTSIZE );\n\n\t/* We can't create another user object with the same name as the\n\t   cryptlib default user (actually we could and nothing bad would happen,\n\t   but we reserve the use of this name just in case) */\n\tif( createInfo->strArgLen1 == defaultUserInfo.userNameLength && \\\n\t\t!strCompare( createInfo->strArg1, defaultUserInfo.userName,\n\t\t\t\t\t defaultUserInfo.userNameLength ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n/* Problem: Access to any user info is via the root user object, however */\n/* we don't have access to it at this point.  Pass it in as auxDataPtr? */\n/* Need to differentiate cryptCreateUser() vs. cryptLogin(), login uses */\n/* the default user object as its target?  This is complex, we really */\n/* need to target the message at the default user to get access to the user */\n/* info index, but then it won't go through cryptdev's create-object- */\n/* handling any more */\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n#if 0\n\t/* Find the user information for the given user */\n\tstatus = fileRef = findUserIndexEntry( USERID_NAME, createInfo->strArg1,\n\t\t\t\t\t\t\t\t\t\t   createInfo->strArgLen1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we get a special-case OK status, we're in the zeroised state\n\t\t   with no user info present, make sure that the user is logging in\n\t\t   with the default SO password */\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\tstatus = ( isZeroisePassword( createInfo->strArg2, \\\n\t\t\t\t\t\t\t\t\t\t  createInfo->strArgLen2 ) ) ? \\\n\t\t\t\t\t CRYPT_OK : CRYPT_ERROR_WRONGKEY;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tfileRef = -1;\t/* No user file present yet for primary SO */\n\n\t\t/* We're logging in as the primary SO with the SO default password,\n\t\t   create the primary SO user object */\n\t\tassert( isZeroisePassword( createInfo->strArg2, \\\n\t\t\t\t\t\t\t\t   createInfo->strArgLen2 ) );\n\t\tinitStatus = openUser( &iCryptUser, createInfo->cryptOwner,\n\t\t\t\t\t\t\t   getPrimarySoUserInfo(), &userInfoPtr );\n\t\t}\n\telse\n\t\t{\n\t\tUSER_FILE_INFO userFileInfo;\n\n\t\t/* We're in the non-zeroised state, no user can use the default SO\n\t\t   password */\n\t\tif( isZeroisePassword( createInfo->strArg2, createInfo->strArgLen2 ) )\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t\t/* Read the user info from the user file and perform access\n\t\t   verification */\n\t\tstatus = getCheckUserInfo( &userFileInfo, fileRef );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Pass the call on to the lower-level open function */\n\t\tassert( createInfo->strArgLen1 == userFileInfo.userNameLength && \\\n\t\t\t\t!memcmp( createInfo->strArg1, userFileInfo.userName,\n\t\t\t\t\t\t userFileInfo.userNameLength ) );\n\t\tinitStatus = openUser( &iCryptUser, createInfo->cryptOwner,\n\t\t\t\t\t\t\t   &userFileInfo, &userInfoPtr );\n\t\tzeroise( &userFileInfo, sizeof( USER_FILE_INFO ) );\n\t\t}\n#endif\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n{\t/* Get rid of compiler warnings */\nuserInfoPtr = NULL;\ninitStatus = CRYPT_ERROR_FAILED;\niCryptUser = CRYPT_UNUSED;\nfileRef = 0;\n}\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( userInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\n\t\t/* The init failed, make sure that the object gets destroyed when we\n\t\t   notify the kernel that the setup process is complete */\n\t\tkrnlSendNotifier( iCryptUser, IMESSAGE_DESTROY );\n\t\t}\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iCryptUser, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\n#ifdef USE_KEYSETS\n\t/* If the user object has a corresponding user info file, read any\n\t   stored config options into the object.  We have to do this after\n\t   it's initialised because the config data, coming from an external\n\t   (and therefore untrusted) source has to go through the kernel's\n\t   ACL checking */\n\tif( fileRef >= 0 )\n\t\t{\n\t\tsprintf_s( userFileName, 16, \"u%06x\", fileRef );\n\t\tstatus = readConfig( iCryptUser, userFileName, \n\t\t\t\t\t\t\t userInfoPtr->trustInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The config data read failed, we can't create the user \n\t\t\t   object that uses it */\n\t\t\tkrnlSendNotifier( iCryptUser, IMESSAGE_DESTROY );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_KEYSETS */\n\tcreateInfo->cryptHandle = iCryptUser;\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the default user object */\n\nCHECK_RETVAL \\\nstatic int createDefaultUserObject( void )\n\t{\n\tCRYPT_USER iUserObject;\n\tUSER_INFO *userInfoPtr;\n\tint initStatus, status;\n\n\t/* Pass the call on to the lower-level open function.  This user is\n\t   unique and has no owner or type.\n\n\t   Normally if an object init fails we tell the kernel to destroy it by \n\t   sending it a destroy message, which is processed after the object's \n\t   status has been set to normal.  However we don't have the privileges \n\t   to do this for the default user object (or the system object) so we \n\t   just pass the error code back to the caller, which causes the \n\t   cryptlib init to fail.\n\n\t   In addition the init can fail in one of two ways, either the object \n\t   isn't even created (deviceInfoPtr == NULL, nothing to clean up), in \n\t   which case we bail out immediately, or the object is created but wasn't \n\t   set up properly (deviceInfoPtr is allocated, but the object can't be \n\t   used) in which case we bail out after we update its status */\n\tinitStatus = openUser( &iUserObject, SYSTEM_OBJECT_HANDLE, &defaultUserInfo,\n\t\t\t\t\t\t   &userInfoPtr );\n\tif( cryptStatusError( initStatus ) )\n\t\t{\n\t\t/* If the create object failed, return immediately */\n\t\tif( userInfoPtr == NULL )\n\t\t\treturn( initStatus );\n\t\t}\n\tENSURES( iUserObject == DEFAULTUSER_OBJECT_HANDLE );\n#if defined( USE_KEYSETS ) && !defined( CONFIG_FUZZ )\n\tif( cryptStatusOK( initStatus ) )\n\t\t{\n\t\t/* Read the user index.  We make this part of the object init because\n\t\t   it's used for access control, unlike the config option read where\n\t\t   we can fall back to defaults if there's a problem this one is\n\t\t   critical enough that we abort the cryptlib init if it fails */\n\t\tinitStatus = initUserIndex( &userInfoPtr->userIndexPtr );\n\t\t}\n#endif /* USE_KEYSETS && !CONFIG_FUZZ */\n\n\t/* We've finished setting up the object-type-specific info, tell the\n\t   kernel that the object is ready for use */\n\tstatus = krnlSendMessage( iUserObject, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );\n\tif( cryptStatusError( initStatus ) || cryptStatusError( status ) )\n\t\treturn( cryptStatusError( initStatus ) ? initStatus : status );\n\n#if defined( USE_KEYSETS ) && !defined( CONFIG_FUZZ )\n\t/* Read any stored config options into the object.  We have to do this \n\t   after it's initialised because the config data, coming from an \n\t   external (and therefore untrusted) source has to go through the \n\t   kernel's ACL checking.  \n\t   \n\t   What to do in case of an error reading the config file is a bit \n\t   problematic, we don't want to cause whatever application is using\n\t   cryptlib to abort mysteriously just because a bit in some config file \n\t   that most people don't even know exists got flipped, so we treat the \n\t   read as an opportunistic read and fall back to built-in safe defaults \n\t   if there's a problem, warning the user in debug mode */\n\tstatus = readConfig( iUserObject, \"cryptlib\", userInfoPtr->trustInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG_ERRMSG(( \"Configuration file read failed with status %s, \"\n\t\t\t\t\t\t\t\"using built-in defaults\", \n\t\t\t\t\t\t\tgetStatusName( status ) ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n#endif /* USE_KEYSETS && !CONFIG_FUZZ */\n\n\t/* The object has been initialised, move it into the initialised state */\n\treturn( krnlSendMessage( iUserObject, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED ) );\n\t}\n\n/* Generic management function for this class of object */\n\nCHECK_RETVAL \\\nint userManagementFunction( IN_ENUM( MANAGEMENT_ACTION ) \\\n\t\t\t\t\t\t\t\tconst MANAGEMENT_ACTION_TYPE action )\n\t{\n\tint status;\n\n\tREQUIRES( action == MANAGEMENT_ACTION_INIT );\n\n\tswitch( action )\n\t\t{\n\t\tcase MANAGEMENT_ACTION_INIT:\n\t\t\tstatus = createDefaultUserObject();\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{ DEBUG_DIAG(( \"User object creation failed\" )); }\n\t\t\telse\n\t\t\t\t{ DEBUG_DIAG(( \"Created default user object\" )); }\n\t\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n"
  },
  {
    "path": "deps/cl345/device/capabil.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Encryption Capability Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CRYPTCAP_DEFINED\n\n#define _CRYPTCAP_DEFINED\n\n/* The information processed by the initParams() function */\n\ntypedef enum {\n\tKEYPARAM_NONE,\t\t\t/* No crypto paramter type */\n\tKEYPARAM_MODE,\t\t\t/* Encryption mode */\n\tKEYPARAM_IV,\t\t\t/* Initialisation vector */\n\tKEYPARAM_BLOCKSIZE,\t\t/* Hash/MAC output size */\n\tKEYPARAM_AAD,\t\t\t/* AAD for authenticated-encr.modes */\n\tKEYPARAM_LAST\t\t\t/* Last possible crypto parameter type */\n\t} KEYPARAM_TYPE;\n\n/* The CONTEXT_INFO structure is only visible inside modules that have access\n   to context internals, if we use it anywhere else we just treat it as a\n   generic void *.  In addition since the CONTEXT_INFO contains the \n   capability info struct, it can't be declared yet at this point so we have \n   to provide a forward declaration for it */\n\n#ifdef _CRYPTCTX_DEFINED\n  struct CI;\n  #define CI_STRUCT\t\tstruct CI\n#else\n  #define CI_STRUCT\t\tvoid\n#endif /* _CRYPTCTX_DEFINED */\n\n/* The information returned by the capability get-info function */\n\ntypedef enum {\n\tCAPABILITY_INFO_NONE,\t\t\t/* No info */\n\tCAPABILITY_INFO_STATESIZE,\t\t/* Size of algorithm state info */\n\tCAPABILITY_INFO_STATEALIGNTYPE,\t/* Alignment requirements for state info */\n\tCAPABILITY_INFO_ICV,\t\t\t/* ICV for authenticated-encr.modes */\n\tCAPABILITY_INFO_LAST\t\t\t/* Last possible capability info type */\n\t} CAPABILITY_INFO_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The structure used to store information about the crypto capabilities */\n\ntypedef CHECK_RETVAL \\\n\t\tint ( *CAP_SELFTEST_FUNCTION )( void );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\n\t\tint ( *CAP_GETINFO_FUNCTION )( IN_ENUM( CAPABILITY_INFO ) \\\n\t\t\t\t\t\t\t\t\t\tconst CAPABILITY_INFO_TYPE type, \n\t\t\t\t\t\t\t\t\t   INOUT_OPT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   OUT void *data, \n\t\t\t\t\t\t\t\t\t   IN_INT_Z const int length );\ntypedef RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CAP_END_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CAP_INITPARAMS_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYPARAM ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst KEYPARAM_TYPE paramType,\n\t\t\t\t\t\t\t\t\t\t  IN_OPT const void *data, \n\t\t\t\t\t\t\t\t\t\t  IN_INT const int dataLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CAP_INITKEY_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   IN_BUFFER_OPT( keyLength ) const void *key, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int keyLength );\n\t\t\t\t\t\t\t\t\t   /* The key data can be NULL if it's a PKC \n\t\t\t\t\t\t\t\t\t\t  context whose key components have been \n\t\t\t\t\t\t\t\t\t\t  read directly into the context, which \n\t\t\t\t\t\t\t\t\t\t  is also why we can't use IN_LENGTH_KEY \n\t\t\t\t\t\t\t\t\t\t  for the length */\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CAP_GENERATEKEY_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t   IN_RANGE( bytesToBits( MIN_KEYSIZE ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tbytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int keySizeBits );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *CAP_ENCRYPTSPECIAL_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_Z int length );\n\t\t\t\t\t\t\t\t\t\t\t  /* Length may be zero for hash functions */\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *CAP_ENCRYPT_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH int length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *CAP_SIGN_FUNCTION )( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t\t\t\t    INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t    IN_LENGTH_SHORT_MIN( 32 ) int length );\n\ntypedef struct CA {\n\t/* Basic identification information for the algorithm */\n\tconst CRYPT_ALGO_TYPE cryptAlgo;/* The encryption algorithm */\n\tconst int blockSize;\t\t\t/* The basic block size of the algorithm */\n\tBUFFER_FIXED( algoNameLen ) \\\n\tconst char *algoName;\t\t\t/* Algorithm name */\n\tconst int algoNameLen;\t\t\t/* Algorithm name length */\n\n\t/* Keying information.  Note that the maximum sizes may vary (for\n\t   example for two-key triple DES vs.three-key triple DES) so the\n\t   crypt query functions should be used to determine the actual size\n\t   for a particular context rather than just using maxKeySize */\n\tconst int minKeySize;\t\t\t/* Minimum key size in bytes */\n\tconst int keySize;\t\t\t\t/* Recommended key size in bytes */\n\tconst int maxKeySize;\t\t\t/* Maximum key size in bytes */\n\n\t/* The functions for implementing the algorithm */\n\tCAP_SELFTEST_FUNCTION selfTestFunction;\n\tCAP_GETINFO_FUNCTION getInfoFunction;\n\tCAP_END_FUNCTION endFunction;\n\tCAP_INITPARAMS_FUNCTION initParamsFunction;\n\tCAP_INITKEY_FUNCTION initKeyFunction;\n\tCAP_GENERATEKEY_FUNCTION generateKeyFunction;\n\tCAP_ENCRYPTSPECIAL_FUNCTION encryptFunction;\n\tCAP_ENCRYPT_FUNCTION decryptFunction;\n\tCAP_ENCRYPT_FUNCTION encryptCBCFunction, decryptCBCFunction;\n\tCAP_ENCRYPT_FUNCTION encryptCFBFunction, decryptCFBFunction;\n\tCAP_ENCRYPT_FUNCTION encryptGCMFunction, decryptGCMFunction;\n\tCAP_SIGN_FUNCTION signFunction, sigCheckFunction;\n\n\t/* Non-native implementations may require extra parameters (for example\n\t   to specify the algorithm and mode in the manner required by the\n\t   non-native implementation), the following values can be used to store\n\t   these parameters */\n\tconst int param1, param2, param3, param4;\n\t} CAPABILITY_INFO;\n\n/* An encapsulating list type for the list of capabilities.  This is a \n   distinct structure that's used to build a linked list of the read-only \n   capability info structures */\n\ntypedef struct CL {\n\tDATAPTR info;\n\tDATAPTR next;\n\t} CAPABILITY_INFO_LIST;\n\n/* Since cryptlib's CAPABILITY_INFO is fixed, all of the fields are declared\n   const so that they'll be allocated in the code segment.  This doesn't quite \n   work for some types of crypto devices since things like the available key \n   lengths can vary depending on the underlying hardware or software, so we \n   provide an equivalent structure that makes the variable fields non-const.  \n   Once the fields are set up, the result is copied into a dynamically-\n   allocated CAPABILITY_INFO block at which point the fields are treated as \n   const by the code */\n\ntypedef struct {\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\n\tconst int blockSize;\n\tBUFFER_FIXED( algoNameLen ) \\\n\tconst char *algoName;\n\tconst int algoNameLen;\n\n\tint minKeySize;\t\t\t\t\t\t/* Non-const */\n\tint keySize;\t\t\t\t\t\t/* Non-const */\n\tint maxKeySize;\t\t\t\t\t\t/* Non-const */\n\n\tCAP_SELFTEST_FUNCTION selfTestFunction;\n\tCAP_GETINFO_FUNCTION getInfoFunction;\n\tCAP_END_FUNCTION endFunction;\n\tCAP_INITPARAMS_FUNCTION initParamsFunction;\n\tCAP_INITKEY_FUNCTION initKeyFunction;\n\tCAP_GENERATEKEY_FUNCTION generateKeyFunction;\n\tCAP_ENCRYPTSPECIAL_FUNCTION encryptFunction;\n\tCAP_ENCRYPT_FUNCTION decryptFunction;\n\tCAP_ENCRYPT_FUNCTION encryptCBCFunction, decryptCBCFunction;\n\tCAP_ENCRYPT_FUNCTION encryptCFBFunction, decryptCFBFunction;\n\tCAP_ENCRYPT_FUNCTION encryptGCMFunction, decryptGCMFunction;\n\tCAP_SIGN_FUNCTION signFunction, sigCheckFunction;\n\n\tint param1, param2, param3, param4;\t/* Non-const */\n\t} VARIABLE_CAPABILITY_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInternal API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for capability access functions */\n\ntypedef const CAPABILITY_INFO * ( *GETCAPABILITY_FUNCTION )( void );\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *get3DESCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getAESCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getCASTCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDESCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getIDEACapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRC2Capability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRC4Capability( void );\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getMD5Capability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getSHA1Capability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getSHA2Capability( void );\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getHmacMD5Capability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getHmacSHA1Capability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getHmacSHA2Capability( void );\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDHCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getDSACapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getElgamalCapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getRSACapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getECDSACapability( void );\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getECDHCapability( void );\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst CAPABILITY_INFO *getGenericSecretCapability( void );\n\n/* Prototypes for functions in cryptctx.c, used by devices to create native \n   contexts */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createContext( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t   IN const void *auxDataPtr, \n\t\t\t\t   IN_FLAGS_Z( CREATEOBJECT ) const int auxValue );\n\n/* Prototypes for capability functions in context/ctx_misc.c */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst CAPABILITY_INFO *findCapabilityInfo(\n\t\t\t\t\t\tconst CAPABILITY_INFO_LIST *capabilityInfoList,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid getCapabilityInfo( OUT CRYPT_QUERY_INFO *cryptQueryInfo,\n\t\t\t\t\t\tconst CAPABILITY_INFO *capabilityInfoPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckCapability( const CAPABILITY_INFO *capabilityInfoPtr );\n\n/* Fallback functions to handle context-specific information that isn't \n   specific to a particular context.  The initial request goes to the \n   context, if that doesn't want to handle it it passes it on to the default \n   handler */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getDefaultInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type, \n\t\t\t\t\tINOUT_OPT CI_STRUCT *contextInfoPtr,\n\t\t\t\t\tOUT void *data, \n\t\t\t\t\tIN_INT_Z const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initGenericParams( INOUT CI_STRUCT *contextInfoPtr, \n\t\t\t\t\t   IN_ENUM( KEYPARAM ) const KEYPARAM_TYPE paramType,\n\t\t\t\t\t   IN_OPT const void *data, \n\t\t\t\t\t   IN_INT const int dataLength );\n\n#endif /* _CRYPTCAP_DEFINED */\n"
  },
  {
    "path": "deps/cl345/device/dev_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Crypto Device Attribute Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"capabil.h\"\n  #include \"device.h\"\n#else\n  #include \"device/capabil.h\"\n  #include \"device/device.h\"\n#endif /* Compiler-specific includes */\n\n/* When we get random data from a device we run the (practical) FIPS 140 \n   tests over the output to make sure that it's really random, at least as \n   far as the tests can tell us.  If the data fails the test we get more and \n   try again.  The following value defines how many times we retry before \n   giving up.  In test runs, a count of 2 failures is reached every ~50,000 \n   iterations, 5 is never reached (in fact with 1M tests, 3 is never \n   reached) */\n\n#define NO_ENTROPY_FAILURES\t5\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( deviceInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorInited( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( deviceInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT,\n\t\t\t\t\t   CRYPT_ERROR_INITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( deviceInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT,\n\t\t\t\t\t   CRYPT_ERROR_NOTFOUND ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead a Random-data Attribute\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a random data block with FIPS 140 checking */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getRandomChecked( INOUT DEVICE_INFO *deviceInfoPtr, \n\t\t\t\t\t\t\t OUT_BUFFER_FIXED( length ) void *data,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t INOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tconst DEV_GETRANDOMFUNCTION getRandomFunction = \\\n\t\t\t\t( DEV_GETRANDOMFUNCTION ) \\\n\t\t\t\tFNPTR_GET( deviceInfoPtr->getRandomFunction );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( data, length ) );\n\tassert( messageExtInfo == NULL || \\\n\t\t\t( isWritePtr( messageExtInfo, \\\n\t\t\t\t\t\t  sizeof( MESSAGE_FUNCTION_EXTINFO ) ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( getRandomFunction != NULL );\n\n\t/* Get random data from the device and check it using the FIPS 140 \n\t   tests.  If it's less than 64 bits then we let it pass since the \n\t   sample size is too small to be useful, samples this small are only \n\t   ever drawn from the generator for use as padding with crypto keys \n\t   that are always >= 64 bits which will themselves have been checked\n\t   when they were read, so a problem with the generator will be \n\t   detected even if we don't check small samples */\n\tLOOP_SMALL( i = 0, i < NO_ENTROPY_FAILURES, i++ )\n\t\t{\n\t\tint status;\n\n\t\tstatus = getRandomFunction( deviceInfoPtr, data, length, \n\t\t\t\t\t\t\t\t\tmessageExtInfo );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( length < 8 || checkEntropy( data, length ) ) )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We couldn't get anything that passed the FIPS 140 tests, we can't\n\t   go any further */\n\tzeroise( data, length );\n\tDEBUG_DIAG(( \"Random data didn't pass FIPS 140 tests after %d \"\n\t\t\t\t \"iterations\", NO_ENTROPY_FAILURES ));\n\tassert( DEBUG_WARN );\n\treturn( CRYPT_ERROR_RANDOM );\n\t}\n\n/* Get a random data block with no zero bytes, for PKCS #1 padding */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getRandomNonzero( INOUT DEVICE_INFO *deviceInfoPtr, \n\t\t\t\t\t\t\t OUT_BUFFER_FIXED( length ) void *data,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int length )\n\t{\n\tBYTE randomBuffer[ 128 + 8 ], *outBuffer = data;\n\tint count, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( data, length ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\t/* The extraction of data is a little complex because we don't know how \n\t   much data we'll need (as a rule of thumb it'll be size + ( size / 256 ) \n\t   bytes, but in a worst-case situation we could need to draw out \n\t   megabytes of data), so we copy out 128 bytes worth at a time (a \n\t   typical value for a 1K bit key) and keep going until we've filled the \n\t   output requirements */\n\tLOOP_LARGE_INITCHECK( count = 0, count < length )\n\t\t{\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Copy as much as we can from the randomness pool.  We don't allow \n\t\t   the device to be unlocked during this process since we may need\n\t\t   it again for further reads */\n\t\tstatus = getRandomChecked( deviceInfoPtr, randomBuffer, 128, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( data, length );\n\t\t\treturn( status );\n\t\t\t}\n\t\tLOOP_LARGE_ALT( i = 0, count < length && i < 128, i++ )\n\t\t\t{\n\t\t\tif( randomBuffer[ i ] != 0 )\n\t\t\t\toutBuffer[ count++ ] = randomBuffer[ i ];\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tFORALL( i, 0, length, \\\n\t\t\toutBuffer[ i ] != 0 );\n\tzeroise( randomBuffer, 128 );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getDeviceAttribute( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\tOUT_INT_Z int *valuePtr, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\tINOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\tassert( isWritePtr( messageExtInfo, \\\n\t\t\tsizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_ERRORTYPE:\n\t\t\t*valuePtr = deviceInfoPtr->errorType;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORLOCUS:\n\t\t\t*valuePtr = deviceInfoPtr->errorLocus;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_DEVINFO_LOGGEDIN:\n\t\t\tif( TEST_FLAG( deviceInfoPtr->flags, DEVICE_FLAG_REMOVABLE ) )\n\t\t\t\t{\n\t\t\t\tconst DEV_CONTROLFUNCTION controlFunction = \\\n\t\t\t\t\t\t\t( DEV_CONTROLFUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->controlFunction );\n\n\t\t\t\tint status;\n\n\t\t\t\tREQUIRES( controlFunction != NULL );\n\n\t\t\t\t/* If it's a removable device the user could implicitly log \n\t\t\t\t   out by removing it so we have to perform an explicit \n\t\t\t\t   check to see whether it's still there */\n\t\t\t\tstatus = controlFunction( deviceInfoPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_DEVINFO_LOGGEDIN, NULL, 0, NULL );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tassert( !isMessageObjectUnlocked( messageExtInfo ) );\n\t\t\t\t}\n\t\t\t*valuePtr = TEST_FLAG( deviceInfoPtr->flags, \n\t\t\t\t\t\t\t\t   DEVICE_FLAG_LOGGEDIN ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getDeviceAttributeS( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\tassert( isWritePtr( messageExtInfo, \\\n\t\t\tsizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_ERRORMESSAGE:\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tERROR_INFO *errorInfo;\n\n\t\t\tswitch( deviceInfoPtr->type )\n\t\t\t\t{\n#ifdef USE_PKCS11\n\t\t\t\tcase CRYPT_DEVICE_PKCS11:\n\t\t\t\t\terrorInfo = &deviceInfoPtr->devicePKCS11->errorInfo;\n\t\t\t\t\tbreak;\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\t\t\t\tcase CRYPT_DEVICE_CRYPTOAPI:\n\t\t\t\t\terrorInfo = &deviceInfoPtr->deviceCryptoAPI->errorInfo;\n\t\t\t\t\tbreak;\n#endif /* USE_CRYPTOAPI */\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn( exitErrorNotFound( deviceInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORMESSAGE ) );\n\t\t\t\t}\n\n\t\t\tif( errorInfo->errorStringLength > 0 )\n\t\t\t\t{\n\t\t\t\treturn( attributeCopy( msgData, errorInfo->errorString,\n\t\t\t\t\t\t\t\t\t   errorInfo->errorStringLength ) );\n\t\t\t\t}\n#endif /* USE_ERRMSGS */\n\t\t\treturn( exitErrorNotFound( deviceInfoPtr,\n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_ERRORMESSAGE ) );\n\t\t\t}\n\n\t\tcase CRYPT_DEVINFO_LABEL:\n\t\t\tif( deviceInfoPtr->label == NULL )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( deviceInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_DEVINFO_LABEL ) );\n\t\t\t\t}\n\t\t\treturn( attributeCopy( msgData, deviceInfoPtr->label,\n\t\t\t\t\t\t\t\t   strlen( deviceInfoPtr->label ) ) );\n\n\t\tcase CRYPT_IATTRIBUTE_RANDOM:\n\t\t\t{\t\n\t\t\tconst DEV_GETRANDOMFUNCTION getRandomFunction = \\\n\t\t\t\t\t\t( DEV_GETRANDOMFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getRandomFunction );\n\n\t\t\tif( getRandomFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_RANDOM );\n\t\t\treturn( getRandomChecked( deviceInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t\t  msgData->length, messageExtInfo ) );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_RANDOM_NZ:\n\t\t\t{\n\t\t\tconst DEV_GETRANDOMFUNCTION getRandomFunction = \\\n\t\t\t\t\t\t( DEV_GETRANDOMFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getRandomFunction );\n\n\t\t\tif( getRandomFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_RANDOM );\n\t\t\treturn( getRandomNonzero( deviceInfoPtr, msgData->data,\n\t\t\t\t\t\t\t\t\t  msgData->length ) );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_RANDOM_NONCE:\n\t\t\t{\n\t\t\tconst DEV_GETRANDOMFUNCTION getRandomFunction = \\\n\t\t\t\t\t\t( DEV_GETRANDOMFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getRandomFunction );\n\t\t\tconst DEV_CONTROLFUNCTION controlFunction = \\\n\t\t\t\t\t\t( DEV_CONTROLFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->controlFunction );\n\n\t\t\tREQUIRES( controlFunction != NULL );\n\n\t\t\tif( getRandomFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_RANDOM );\n\n\t\t\treturn( controlFunction( deviceInfoPtr, \n\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_RANDOM_NONCE,\n\t\t\t\t\t\t\t\t\t msgData->data, msgData->length, \n\t\t\t\t\t\t\t\t\t messageExtInfo ) );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_TIME:\n\t\t\t{\n\t\t\tconst DEV_CONTROLFUNCTION controlFunction = \\\n\t\t\t\t\t\t( DEV_CONTROLFUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( deviceInfoPtr->controlFunction );\n\t\t\ttime_t *timePtr = msgData->data;\n\t\t\tint status;\n\n\t\t\tREQUIRES( controlFunction != NULL );\n\n\t\t\t/* If the device doesn't contain a time source we can't provide \n\t\t\t   time information */\n\t\t\tif( !TEST_FLAG( deviceInfoPtr->flags, DEVICE_FLAG_TIME ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t\t/* Get the time from the device */\n\t\t\tstatus = controlFunction( deviceInfoPtr, CRYPT_IATTRIBUTE_TIME,\n\t\t\t\t\t\t\t\t\t  msgData->data, msgData->length, NULL );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Perform a sanity check on the returned value, if it's too far \n\t\t\t   out then we don't trust it */\n\t\t\tif( *timePtr <= MIN_TIME_VALUE )\n\t\t\t\t{\n\t\t\t\t*timePtr = 0;\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint setDeviceAttribute( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\tIN_INT_Z const int value, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tconst DEV_CONTROLFUNCTION controlFunction = \\\n\t\t\t\t( DEV_CONTROLFUNCTION ) \\\n\t\t\t\tFNPTR_GET( deviceInfoPtr->controlFunction );\n\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( messageExtInfo, \\\n\t\t\tsizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( controlFunction != NULL );\n\n\t/* Send the control information to the device */\n\treturn( controlFunction( deviceInfoPtr, attribute, NULL, value, \n\t\t\t\t\t\t\t messageExtInfo ) );\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint setDeviceAttributeS( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t IN_LENGTH const int dataLength,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tconst DEV_CONTROLFUNCTION controlFunction = \\\n\t\t\t\t( DEV_CONTROLFUNCTION ) \\\n\t\t\t\tFNPTR_GET( deviceInfoPtr->controlFunction );\n\tint status;\n\n\tassert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( messageExtInfo, \\\n\t\t\tsizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( dataLength ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( controlFunction != NULL );\n\n\t/* If the user is logging on to the device we have to perform a bit of \n\t   extra processing */\n\tif( attribute == CRYPT_DEVINFO_AUTHENT_USER || \\\n\t\tattribute == CRYPT_DEVINFO_AUTHENT_SUPERVISOR )\n\t\t{\n\t\tconst DEV_GETRANDOMFUNCTION getRandomFunction = \\\n\t\t\t\t\t( DEV_GETRANDOMFUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( deviceInfoPtr->getRandomFunction );\n\n\t\t/* Make sure that a login is actually required for the device */\n\t\tif( !TEST_FLAG( deviceInfoPtr->flags, DEVICE_FLAG_NEEDSLOGIN ) )\n\t\t\treturn( exitErrorInited( deviceInfoPtr, attribute ) );\n\n\t\t/* Send the logon information to the device */\n\t\tstatus = controlFunction( deviceInfoPtr, attribute,\n\t\t\t\t\t\t\t\t  ( void * ) data, dataLength, \n\t\t\t\t\t\t\t\t  messageExtInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tassert( !isMessageObjectUnlocked( messageExtInfo ) );\n\n\t\t/* The user has logged in, if the token has a hardware RNG grab 256 \n\t\t   bits of entropy and send it to the system device.  Since we have \n\t\t   no idea how good this entropy is (it could be just a DES-based \n\t\t   PRNG using a static key or even an LFSR, which some smart cards \n\t\t   use) we don't set any entropy quality indication */\n\t\tif( getRandomFunction != NULL )\n\t\t\t{\n\t\t\tBYTE buffer[ 32 + 8 ];\n\n\t\t\tstatus = getRandomFunction( deviceInfoPtr, buffer, 32, NULL );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tMESSAGE_DATA msgData2;\n\n\t\t\t\tsetMessageData( &msgData2, buffer, 32 );\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData2, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t\t}\n\t\t\tzeroise( buffer, 32 );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Send the control information to the device */\n\treturn( controlFunction( deviceInfoPtr, attribute, \n\t\t\t\t\t\t\t ( void * ) data, dataLength, messageExtInfo ) );\n\t}\n"
  },
  {
    "path": "deps/cl345/device/device.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Device Interface Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _DEVICE_DEFINED\n\n#define _DEVICE_DEFINED\n\n#if defined( INC_ALL )\n  #include \"dev_mech.h\"\n#else\n  #include \"mechs/dev_mech.h\"\n#endif /* Compiler-specific includes */\n\n/* The maximum length of error message we can store */\n\n#define MAX_ERRMSG_SIZE\t\t512\n\n/* Device information flags.  The flags are:\n\n\tACTIVE: A session with the device is currently active and needs to be \n\t\tshut down when the device object is destroyed.\n\n\tLOGGEDIN: Whether the user is currently logged in.  \n\n\tNEEDSLOGIN: This type of device needs a user login before it can be used, \n\t\tset when the device is first opened.\n\n\tNEEDSCLEANUP: The device hasn't been fully initialised yet, so cleanup\n\t\tactions (for example deleting incompletely-created objects) need to \n\t\tbe performed when it's closed.  This typically happens when a \n\t\tstandard { open, configure, close } cycle is interrupted, so that it\n\t\tbecomes { open, close }, with non- or partially-initialised objects\n\t\tbeing left from the open phase.\n\n\tREMOVABLE: Whether the device is removable.\n\t\n\tTIME: Device has onboard time source */\n\n#define DEVICE_FLAG_NONE\t\t0x000\t/* No device flag */\n#define DEVICE_FLAG_NEEDSLOGIN\t0x0001\t/* User must log in to use dev.*/\n#define DEVICE_FLAG_READONLY\t0x0002\t/* Device can't be written to */\n#define DEVICE_FLAG_REMOVABLE\t0x0004\t/* Device is removable */\n#define DEVICE_FLAG_ACTIVE\t\t0x0008\t/* Device is currently active */\n#define DEVICE_FLAG_LOGGEDIN\t0x0010\t/* User is logged into device */\n#define DEVICE_FLAG_TIME\t\t0x0020\t/* Device has on-board time source */\n#define DEVICE_FLAG_NEEDSCLEANUP 0x0040\t/* Device partially initialised */\n#define DEVICE_FLAG_MAX\t\t\t0x007F\t/* Maximum possible flag value */\n\n/* Devices can be used to create further objects.  Most can only create \n   contexts, but the system object can create any kind of object */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CREATEOBJECT_FUNCTION )( INOUT \\\n\t\t\t\t\t\t\t\t\t\tMESSAGE_CREATEOBJECT_INFO *objectInfo,\n\t\t\t\t\t\t\t\t\t\tconst void *auxDataPtr,\n\t\t\t\t\t\t\t\t\t\tconst int auxValue );\ntypedef struct {\n\tconst OBJECT_TYPE type;\n\tconst CREATEOBJECT_FUNCTION function;\n\t} CREATEOBJECT_FUNCTION_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The internal fields in a deviec that hold data for the various keyset\n   types.   These are implemented as a union to conserve memory with some of \n   the more data-intensive types.  In addition the structures provide a \n   convenient way to group the device type-specific parameters */\n\n#define NONCERNG_PRIVATE_STATESIZE\t\t8\n\ntypedef struct {\n\t/* Nonce PRNG information.  This uses a nonce RNG state consisting of a\n\t   block of data of the same size as the nonce hash function followed\n\t   by 64 bits of private state that's mixed into the hashed data, see\n\t   the comment in getNonce() in device/system.c for details */\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE + NONCERNG_PRIVATE_STATESIZE ) \\\n\tBYTE nonceData[ ( CRYPT_MAX_HASHSIZE + \\\n\t\t\t\t\t  NONCERNG_PRIVATE_STATESIZE ) + 8 ];/* Nonce RNG state */\n\tFNPTR nonceHashFunction;\n\tint nonceHashSize;\n\tBOOLEAN nonceDataInitialised;\t/* Whether nonce RNG initialised */\n\t\n\t/* Checksum for the nonce data.  Note that when adding non nonce-related\n\t   fields to this structure the checksum calculation in getNonce() in\n\t   devices/system.c will need to be adjusted */\n\tint nonceChecksum;\t\t\t\t/* Checksum for nonce data */\n\t} SYSTEMDEV_INFO;\n\n#ifdef USE_PKCS11\n\ntypedef struct {\n\t/* General device information.  The labelBuffer provides storage for the\n\t   label data pointed to from the DEVICE_INFO */\n\tint minPinSize, maxPinSize;\t\t/* Minimum, maximum PIN lengths */\n\tBYTE labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Device label */\n\n\t/* Device type-specific information */\n\tunsigned long hSession;\t\t\t/* Session handle */\n\tlong slotID;\t\t\t\t\t/* Slot ID for multi-slot device */\n\tint deviceNo;\t\t\t\t\t/* Index into PKCS #11 token table */\n\tvoid *functionListPtr;\t\t\t/* PKCS #11 driver function list pointer */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, defaultSSOPinLen ) \\\n\tchar defaultSSOPin[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* SSO PIN from dev.init */\n\tint defaultSSOPinLen;\n\n\t/* Device state information.  This records the active object for multi-\n\t   part operations where we can only perform one per hSession.  Because\n\t   we have to set this to CRYPT_ERROR if there's none active, we make\n\t   it a signed long rather than the unsigned long that's usually used\n\t   for PKCS #11 handles */\n\tlong hActiveSignObject;\t\t\t/* Currently active sig.object */\n\n\t/* Last-error information returned from lower-level code */\n\tERROR_INFO errorInfo;\n\t} PKCS11_INFO;\n#endif /* USE_PKCS11 */\n\n#ifdef USE_CRYPTOAPI\n\n#if defined( __WIN32__ ) && VC_GE_2005( _MSC_VER )\n  #define CAPI_HANDLE ULONG_PTR\t\t/* May be 64 bits on Win64 */\n#else\n  #define CAPI_HANDLE unsigned long\t/* Always 32 bits on Win32 */\n#endif /* Older vs.newer CryptoAPI types */\n\ntypedef struct {\n\t/* General device information */\n\tBYTE labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Device label */\n\n\t/* Device type-specific information */\n\tCAPI_HANDLE hProv;\t\t\t\t/* CryptoAPI provider handle */\n\tvoid *hCertStore;\t\t\t\t/* Cert store for key/cert storage */\n\tCAPI_HANDLE hPrivateKey;\t\t/* Key for session key import/export */\n\tint privateKeySize;\t\t\t\t/* Size of import/export key */\n\tconst void *hCertChain;\t\t\t/* Cached copy of current cert chain */\n\n\t/* Last-error information returned from lower-level code */\n\tERROR_INFO errorInfo;\n\t} CRYPTOAPI_INFO;\n#endif /* USE_CRYPTOAPI */\n\n#ifdef USE_HARDWARE\n\ntypedef struct {\n\t/* General device information */\n\tBYTE labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Device label */\n\n\t/* Device type-specific information */\n\tCRYPT_KEYSET iCryptKeyset;\t\t\t/* Key storage */\n\n\t/* Last-error information returned from lower-level code */\n\tERROR_INFO errorInfo;\n\t} HARDWARE_INFO;\n#endif /* USE_HARDWARE */\n\n/* Defines to make access to the union fields less messy */\n\n#define deviceSystem\tdeviceInfo.systemInfo\n#define devicePKCS11\tdeviceInfo.pkcs11Info\n#define deviceCryptoAPI\tdeviceInfo.cryptoapiInfo\n#define deviceHardware\tdeviceInfo.hardwareInfo\n\n/* The structure which stores information on a device */\n\nstruct DI;\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *DEV_INITFUNCTION )( INOUT struct DI *deviceInfo, \n\t\t\t\t\t\t\t\t   IN_BUFFER_OPT( nameLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *name,\n\t\t\t\t\t\t\t\t   IN_LENGTH_TEXT_Z const int nameLength );\ntypedef STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tvoid ( *DEV_SHUTDOWNFUNCTION )( INOUT struct DI *deviceInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DEV_CONTROLFUNCTION )( INOUT struct DI *deviceInfo,\n\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER_OPT( dataLength ) void *data, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataLength,\n\t\t\t\t\t\t\t\t\t  INOUT_OPT \\\n\t\t\t\t\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *DEV_SELFTESTFUNCTION )( INOUT struct DI *deviceInfo,\n\t\t\t\t\t\t\t\t\t   INOUT \\\n\t\t\t\t\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\n\t\tint ( *DEV_GETITEMFUNCTION )( INOUT struct DI *deviceInfo,\n\t\t\t\t\t\t\t\t\t  OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t\t  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( keyIDlength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *keyID, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER_OPT( *auxInfoLength ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *auxInfo, \n\t\t\t\t\t\t\t\t\t  INOUT_LENGTH_SHORT_Z int *auxInfoLength, \n\t\t\t\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) const int flags );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DEV_SETITEMFUNCTION )( INOUT struct DI *deviceInfo,\n\t\t\t\t\t\t\t\t\t  IN_HANDLE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_HANDLE iCryptHandle );\ntypedef RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\n\t\tint ( *DEV_DELETEITEMFUNCTION )( INOUT struct DI *deviceInfo,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t\t\t IN_KEYID \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *keyID, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_KEYID \\\n\t\t\t\t\t\t\t\t\t\t\tconst int keyIDlength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\n\t\tint ( *DEV_GETFIRSTITEMFUNCTION )( INOUT struct DI *deviceInfo, \n\t\t\t\t\t\t\t\t\t\t   OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t\t\t   OUT int *stateInfo, \n\t\t\t\t\t\t\t\t\t\t   IN_KEYID \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *keyID, \n\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t\t\t\t\t\t\t   IN_FLAGS_Z( KEYMGMT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int options );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\n\t\tint ( *DEV_GETNEXTITEMFUNCTION )( INOUT struct DI *deviceInfo, \n\t\t\t\t\t\t\t\t\t\t  OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t\t\t  INOUT int *stateInfo, \n\t\t\t\t\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int options );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *DEV_GETRANDOMFUNCTION )( INOUT struct DI *deviceInfo, \n\t\t\t\t\t\t\t\t\t\tOUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t\t\t\tINOUT_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo );\n\ntypedef struct DI {\n\t/* General device information.  Alongside various handles used to access\n\t   the device we also record whether the user has authenticated\n\t   themselves to the device since some devices have multiple user-access\n\t   states and the user needs to be logged out of one state before they\n\t   can log in to another state.  In addition we also record the device\n\t   label which the caller can query for use in prompts displayed to the\n\t   user */\n\tCRYPT_DEVICE_TYPE type;\t\t\t/* Device type */\n\tSAFE_FLAGS flags;\t\t\t\t/* Device information flags */\n\tBUFFER_FIXED( labelLen ) \\\n\tchar *label;\t\t\t\t\t/* Device label */\n\tint labelLen;\n\n\t/* Each device provides various capabilities which are held in the \n\t   following list.  When we need to create an object via the device, we\n\t   look up the requirements in the capability info and feed it to\n\t   createObjectFromCapability() */\n\tDATAPTR capabilityInfoList;\n\n\t/* Device type-specific information */\n\tunion {\n\t\tSYSTEMDEV_INFO *systemInfo;\n#ifdef USE_PKCS11\n\t\tPKCS11_INFO *pkcs11Info;\n#endif /* USE_PKCS11 */\n#ifdef USE_CRYPTOAPI\n\t\tCRYPTOAPI_INFO *cryptoapiInfo;\n#endif /* USE_CRYPTOAPI */\n#ifdef USE_HARDWARE\n\t\tHARDWARE_INFO *hardwareInfo;\n#endif /* USE_HARDWARE */\n\t\t} deviceInfo;\n\n\t/* Pointers to device access methods */\n\tFNPTR initFunction, shutdownFunction, controlFunction;\n\tFNPTR selftestFunction, getItemFunction, setItemFunction;\n\tFNPTR deleteItemFunction, getFirstItemFunction;\n\tFNPTR getNextItemFunction, getRandomFunction;\n\n\t/* Information for the system device */\n\tconst MECHANISM_FUNCTION_INFO *mechanismFunctions;\n\tconst CREATEOBJECT_FUNCTION_INFO *createObjectFunctions;\n\tvoid *randomInfo;\n\tint mechanismFunctionCount, createObjectFunctionCount;\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the \n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\n\t/* Variable-length storage for the type-specific data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} DEVICE_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInternal API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check device data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckDevice( IN const DEVICE_INFO *deviceInfoPtr );\n\n/* Device attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getDeviceAttribute( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\tOUT_INT_Z int *valuePtr, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\tINOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getDeviceAttributeS( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t MESSAGE_FUNCTION_EXTINFO *messageExtInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint setDeviceAttribute( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\tIN_INT_Z const int value, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint setDeviceAttributeS( INOUT DEVICE_INFO *deviceInfoPtr,\n\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t IN_LENGTH const int dataLength,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t MESSAGE_FUNCTION_EXTINFO *messageExtInfo );\n\n/* Prototypes for device mapping functions */\n\n#ifdef USE_PKCS11\n  CHECK_RETVAL \\\n  int deviceInitPKCS11( void );\n  void deviceEndPKCS11( void );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n  int setDevicePKCS11( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t   IN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\t   IN_LENGTH_ATTRIBUTE const int nameLength );\n#else\n  #define deviceInitPKCS11()\t\t\tCRYPT_OK\n  #define deviceEndPKCS11()\n  #define setDevicePKCS11( x, y, z )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_PKCS11 */\n#ifdef USE_CRYPTOAPI\n  CHECK_RETVAL \\\n  int deviceInitCryptoAPI( void );\n  void deviceEndCryptoAPI( void );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setDeviceCryptoAPI( INOUT DEVICE_INFO *deviceInfo );\n#else\n  #define deviceInitCryptoAPI()\t\t\tCRYPT_OK\n  #define deviceEndCryptoAPI()\n  #define setDeviceCryptoAPI( x )\t\tCRYPT_ARGERROR_NUM1\n#endif /* USE_CRYPTOAPI */\n#ifdef USE_HARDWARE\n  CHECK_RETVAL \\\n  int deviceInitHardware( void );\n  void deviceEndHardware( void );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setDeviceHardware( INOUT DEVICE_INFO *deviceInfo );\n#else\n  #define deviceInitHardware()\t\t\tCRYPT_OK\n  #define deviceEndHardware()\n  #define setDeviceHardware( x )\t\tCRYPT_ARGERROR_NUM1\n#endif /* USE_HARDWARE */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setDeviceSystem( INOUT DEVICE_INFO *deviceInfo );\n\n#endif /* _DEVICE_DEFINED */\n"
  },
  {
    "path": "deps/cl345/device/hardware.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Generic Crypto HW Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"hardware.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/hardware.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HARDWARE\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get access to the hardware device associated with a context */\n\nstatic int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t\t\t CRYPT_DEVICE *iCryptDevice, \n\t\t\t\t\t\t\t\t HARDWARE_INFO **hwInfoPtrPtr )\n\t{\n\tCRYPT_DEVICE iLocalDevice;\n\tDEVICE_INFO *deviceInfo;\n\tint status;\n\n\tassert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );\n\tassert( isWritePtr( hwInfoPtrPtr, sizeof( HARDWARE_INFO * ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Clear return values */\n\t*iCryptDevice = CRYPT_ERROR;\n\t*hwInfoPtrPtr = NULL;\n\n\t/* Get the the device associated with this context */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iLocalDevice, OBJECT_TYPE_DEVICE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get the hardware information from the device information */\n\tstatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE, \n\t\t\t\t\t\t\t\t( MESSAGE_PTR_CAST ) &deviceInfo, \n\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*iCryptDevice = iLocalDevice;\n\t*hwInfoPtrPtr = deviceInfo->deviceHardware;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a reference to the cryptographic hardware object that underlies a \n   cryptlib object.  This is used to connect a template object from a\n   PKCS #15 storage object to the corresponding hardware object via the\n   storageID that's recorded in the storage object */\n\nstatic int getHardwareReference( const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t int *keyHandle )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE storageID[ KEYID_SIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( keyHandle, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\tsetMessageData( &msgData, storageID, KEYID_SIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = hwLookupItem( storageID, KEYID_SIZE, keyHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* In theory this is an internal error but in practice we shouldn't\n\t\t   treat this as too fatal, what it really means is that the crypto\n\t\t   hardware (which we don't control and therefore can't do too much\n\t\t   about) is out of sync with the PKCS #15 storage object.  This can \n\t\t   happen for example during the development process when the \n\t\t   hardware is reinitialised but the storage object isn't, or from\n\t\t   any one of a number of other circumstances beyond our control.  \n\t\t   To deal with this we return a standard notfound error but also \n\t\t   output a diagnostic message for developers to let them know that\n\t\t   they need to check hardware/storage object synchronisation */\n\t\tDEBUG_DIAG(( \"Object held in PKCS #15 object store doesn't \"\n\t\t\t\t\t \"correspond to anything known to the crypto \"\n\t\t\t\t\t \"hardware HAL\" ));\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Open and close the PKCS #15 storage object associated with this \n   device */\n\nstatic int openStorageObject( CRYPT_KEYSET *iCryptKeyset,\n\t\t\t\t\t\t\t  const CRYPT_KEYOPT_TYPE options,\n\t\t\t\t\t\t\t  const CRYPT_DEVICE iCryptDevice )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tchar storageFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint storageFilePathLen, status;\n\n\tassert( isWritePtr( iCryptKeyset, sizeof( CRYPT_KEYSET ) ) );\n\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\tREQUIRES( isHandleRangeValid( iCryptDevice ) );\n\n\t/* Clear return value */\n\t*iCryptKeyset = CRYPT_ERROR;\n\n\t/* Try and open/create the PKCS #15 storage object */\n\tstatus = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&storageFilePathLen, \"CLKEYS\", 6, \n\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );\n\tif( options != CRYPT_KEYOPT_NONE )\n\t\tcreateInfo.arg2 = options;\n\tcreateInfo.strArg1 = storageFilePath;\n\tcreateInfo.strArgLen1 = storageFilePathLen;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_KEYSET );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Now that we've got the storage object we have to perform a somewhat \n\t   awkward double-linked-list update of the keyset to give it the handle \n\t   of the owning device since we need to create any contexts for keys \n\t   fetched from the storage object via the hardware device rather than \n\t   the default system device.  In theory we could also do this via a new \n\t   get-owning-object message but we still need to signal to the keyset \n\t   that it's a storage object rather than a standard keyset so this \n\t   action serves a second purpose anyway and we may as well use it to \n\t   explicitly set the owning-device handle at the same time.\n\n\t   Note that we don't set the storage object as a dependent object of \n\t   the device because it's not necessarily constant across device \n\t   sessions.  In particular if we initialise or zeroise the device then \n\t   the storage object will be reset, but there's no way to switch \n\t   dependent objects without destroying and recreating the parent.  In\n\t   addition it's not certain whether the storage-object keyset should\n\t   really be a dependent object or not, in theory it's nice because it\n\t   allows keyset-specific messages/accesses to be sent to the device and\n\t   automatically routed to the keyset (standard accesses will still go \n\t   to the device, so for example a getItem() will be handled as a \n\t   device-get rather than a keyset-get) but such unmediated access to \n\t   the underlying keyset probably isn't a good idea anyway */\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCryptDevice, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_HWSTORAGE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iCryptKeyset = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int closeStorageObject( const CRYPT_KEYSET iCryptKeyset,\n\t\t\t\t\t\t\t   const BOOLEAN cleanup )\n\t{\n\tchar storageFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint storageFilePathLen, status;\n\n\tREQUIRES( isHandleRangeValid( iCryptKeyset ) );\n\tREQUIRES( cleanup == TRUE || cleanup == FALSE );\n\n\t/* Close the storage object and, if there's no cleanup required, exit */\n\tkrnlSendNotifier( iCryptKeyset, IMESSAGE_DECREFCOUNT );\n\tif( !cleanup )\n\t\treturn( CRYPT_OK );\n\n\t/* Delete the storage object */\n\tstatus = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&storageFilePathLen, \"CLKEYS\", 6, \n\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tfileErase( storageFilePath );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tInit/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the capability information */\n\n#define MAX_DEVICE_CAPABILITIES\t\t32\n\nstatic CAPABILITY_INFO_LIST capabilityInfoList[ MAX_DEVICE_CAPABILITIES ];\n\n/* Initialise the cryptographic hardware and its crypto capability \n   interface */\n\nCHECK_RETVAL \\\nint deviceInitHardware( void )\n\t{\n\tCAPABILITY_INFO *capabilityInfo;\n\tstatic BOOLEAN initCalled = FALSE;\n\tint noCapabilities, i, status, LOOP_ITERATOR;\n\n\t/* If we've previously tried to initialise the hardware, don't try it \n\t   again */\n\tif( initCalled )\n\t\treturn( CRYPT_OK );\n\tinitCalled = TRUE;\n\n\t/* Get the hardware capability information */\n\tstatus = hwGetCapabilities( &capabilityInfo, &noCapabilities );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG_ERRMSG(( \"Couldn't get native hardware capabilities, \"\n\t\t\t\t\t\t\t\"status %s\", getStatusName( status ) ));\n\t\treturn( status );\n\t\t}\n\tENSURES( noCapabilities > 0 && \\\n\t\t\t noCapabilities < MAX_DEVICE_CAPABILITIES );\n\n\t/* Build the list of available capabilities */\n\tmemset( capabilityInfoList, 0, \n\t\t\tsizeof( CAPABILITY_INFO_LIST ) * MAX_DEVICE_CAPABILITIES );\n\tLOOP_MED( i = 0, i < noCapabilities && \\\n\t\t\t\t\t capabilityInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE, i++ )\n\t\t{\n\t\tREQUIRES( sanityCheckCapability( &capabilityInfo[ i ] ) );\n\t\t\n\t\tDATAPTR_SET( capabilityInfoList[ i ].info, &capabilityInfo[ i ] );\n\t\tDATAPTR_SET( capabilityInfoList[ i ].next, NULL );\n\t\tif( i > 0 )\n\t\t\t{\n\t\t\tDATAPTR_SET( capabilityInfoList[ i - 1 ].next, \n\t\t\t\t\t\t &capabilityInfoList[ i ] );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < noCapabilities );\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid deviceEndHardware( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDevice Init/Shutdown/Device Control Routines\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Close a previously-opened session with the device.  We have to have this\n   before the initialisation function since it may be called by it if the \n   initialisation process fails */\n\nstatic void shutdownFunction( DEVICE_INFO *deviceInfo )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\t/* Shut down access to the storage object */\n\tif( hardwareInfo->iCryptKeyset != CRYPT_ERROR )\n\t\t{\n\t\t( void ) closeStorageObject( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\tTEST_FLAG( deviceInfo->flags, \n\t\t\t\t\t\t\t\t   DEVICE_FLAG_NEEDSCLEANUP ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\t\thardwareInfo->iCryptKeyset = CRYPT_ERROR;\n\t\t}\n\tCLEAR_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE | \\\n\t\t\t\t\t\t\t\t   DEVICE_FLAG_LOGGEDIN | \\\n\t\t\t\t\t\t\t\t   DEVICE_FLAG_NEEDSCLEANUP );\n\t}\n\n/* Open a session with the device */\n\nstatic int initFunction( DEVICE_INFO *deviceInfo, const char *name,\n\t\t\t\t\t\t const int nameLength )\n\t{\n\tCRYPT_KEYSET iCryptKeyset;\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tint status;\n\n\tUNUSED_ARG( name );\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\t/* Set up any internal objects to contain invalid handles */\n\thardwareInfo->iCryptKeyset = CRYPT_ERROR;\n\n\t/* Set up the device ID information */\n\tmemcpy( hardwareInfo->labelBuffer, \"Cryptographic hardware device\", 29 );\n\tdeviceInfo->label = hardwareInfo->labelBuffer;\n\tdeviceInfo->labelLen = 29;\n\n\t/* Since this is a built-in hardware device it's always present and \n\t   available */\n\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE | DEVICE_FLAG_LOGGEDIN );\n\n\t/* Try and open the PKCS #15 storage object.  If we can't open it it \n\t   means that either it doesn't exist (i.e. persistent key storage\n\t   isn't supported) or the device hasn't been initialised yet.  This \n\t   isn't a fatal error, although it does mean that public-key \n\t   operations will be severely restricted since these depend on storing \n\t   key metadata in the storage object */\n\tstatus = openStorageObject( &iCryptKeyset, CRYPT_KEYOPT_NONE,\n\t\t\t\t\t\t\t\tdeviceInfo->objectHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\t/* Storage object not available */\n\thardwareInfo->iCryptKeyset = iCryptKeyset;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Handle device control functions */\n\nstatic int controlFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\tconst void *data, const int dataLength,\n\t\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tint status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isAttribute( type ) || isInternalAttribute( type ) );\n\n\tUNUSED_ARG( hardwareInfo );\n\tUNUSED_ARG( messageExtInfo );\n\n\t/* Handle user authorisation.  Since this is a built-in hardware device \n\t   it's always available for use so these are just dummy routines, \n\t   although they can be expanded to call down into the HAL for actual\n\t   authentication if any hardware with such a facility is ever used */\n\tif( type == CRYPT_DEVINFO_AUTHENT_USER || \\\n\t\ttype == CRYPT_DEVINFO_AUTHENT_SUPERVISOR )\n\t\t{\n\t\t/* Authenticate the user */\n\t\t/* ... */\n\n\t\t/* The device is now ready for use */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN );\t\t\n\t\tkrnlSendMessage( deviceInfo->objectHandle, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle authorisation value change */\n\tif( type == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR )\n\t\t{\n\t\t/* Set SO PIN */\n\t\t/* ... */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( type == CRYPT_DEVINFO_SET_AUTHENT_USER )\n\t\t{\n\t\t/* Set user PIN */\n\t\t/* ... */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle initialisation and zeroisation */\n\tif( type == CRYPT_DEVINFO_INITIALISE || \\\n\t\ttype == CRYPT_DEVINFO_ZEROISE )\n\t\t{\n\t\tCRYPT_KEYSET iCryptKeyset;\n\n\t\t/* Shut down any existing state if necessary in preparation for the \n\t\t   zeroise/initialise.  Since this clears all state we manually \n\t\t   reset the device-active flag since we're still active, just with\n\t\t   all information cleared */\n\t\tif( hardwareInfo->iCryptKeyset != CRYPT_ERROR )\n\t\t\tshutdownFunction( deviceInfo );\n\t\thwInitialise();\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE );\n\n\t\t/* The only real difference between a zeroise and an initialise is\n\t\t   that the zeroise only clears existing state and exits while the \n\t\t   initialise resets the state with the device ready to be used \n\t\t   again */\n\t\tif( type == CRYPT_DEVINFO_ZEROISE )\n\t\t\t{\n\t\t\tchar storageFilePath[ MAX_PATH_LENGTH + 1 + 8 ];\n\t\t\tint storageFilePathLen;\n\n\t\t\t/* Zeroise the device */\n\t\t\tstatus = fileBuildCryptlibPath( storageFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t\t\t&storageFilePathLen, \"CLKEYS\", 6, \n\t\t\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstorageFilePath[ storageFilePathLen ] = '\\0';\n\t\t\t\tfileErase( storageFilePath );\n\t\t\t\t}\n\t\t\tCLEAR_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Initialise the device.  In theory we're already in the logged-in\n\t\t   state but if the initialise was preceded by a zeroise then this\n\t\t   will have been cleared, so we explicitly re-set it.  In addition\n\t\t   we set the needs-cleanup flag to indicate that if the device is\n\t\t   closed before performing further initialisation then the storage\n\t\t   object should be removed */\n\t\tstatus = openStorageObject( &iCryptKeyset, CRYPT_KEYOPT_CREATE,\n\t\t\t\t\t\t\t\t\tdeviceInfo->objectHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thardwareInfo->iCryptKeyset = iCryptKeyset;\n\t\tSET_FLAG( deviceInfo->flags, \n\t\t\t\t  DEVICE_FLAG_LOGGEDIN | DEVICE_FLAG_NEEDSCLEANUP );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle high-reliability time */\n\tif( type == CRYPT_IATTRIBUTE_TIME )\n\t\t{\n\t\ttime_t *timePtr = ( time_t * ) data;\n\n\t\tUNUSED_ARG( timePtr );\n\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get random data from the device.  The messageExtInfo parameter is used\n   to handle recursive messages sent to the system device during the \n   randomness-polling process and isn't used here */\n\nstatic int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,\n\t\t\t\t\t\t\t  const int length,\n\t\t\t\t\t\t\t  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tUNUSED_ARG( messageExtInfo );\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Fill the buffer with random data */\n\treturn( hwGetRandom( buffer, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGet/Set/Delete Item Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Instantiate an object in a device.  This works like the create context\n   function but instantiates a cryptlib object using data already contained\n   in the device (for example a stored private key or certificate).  If the\n   value being read is a public key and there's a certificate attached then \n   the instantiated object is a native cryptlib object rather than a device\n   object with a native certificate object attached because there doesn't \n   appear to be any good reason to create the public-key object in the \n   device, and the cryptlib native object will probably be faster anyway */\n\nstatic int getItemFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tCRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tconst void *keyID, const int keyIDlength,\n\t\t\t\t\t\t\tvoid *auxInfo, int *auxInfoLength, \n\t\t\t\t\t\t\tconst int flags )\n\t{\n#if 0\n\tconst CRYPT_DEVICE cryptDevice = deviceInfo->objectHandle;\n\tCRYPT_CERTIFICATE iCryptCert = CRYPT_UNUSED;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tHW_KEYINFO keyInfo;\n\tMESSAGE_DATA msgData;\n\tconst int extraFlags = ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \\\n\t\t\t\t\t\t   KEYMGMT_FLAG_DATAONLY_CERT : 0;\n\tint keyHandle, p15status, status;\n#endif\n\tCRYPT_CONTEXT iLocalContext;\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint keyHandle, status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );\n\tREQUIRES( auxInfo == NULL && *auxInfoLength == 0 );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\n#if 1\n\t/* Redirect the fetch down to the PKCS #15 storage object, which will\n\t   create either a dummy context that we have to connect to the actual\n\t   hardware for a private-key object or a native public-key/certificate \n\t   object if it's a non-private-key item */\n\tif( hardwareInfo->iCryptKeyset == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tsetMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t   NULL, 0, flags );\n\tstatus = krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo,\n\t\t\t\t\t\t\t  itemType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalContext = getkeyInfo.cryptHandle;\n\n\t/* If it's a public-key fetch, we've created a native object and we're\n\t   done */\n\tif( itemType != KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\t*iCryptContext = iLocalContext;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It was a private-key fetch, we need to connect the dummy context that\n\t   was created with the underlying hardware.  When this final step\n\t   has been completed we can move the context to the initialised state */\n\tstatus = getHardwareReference( iLocalContext, &keyHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &keyHandle, CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n#else\n\t/* As a first step we redirect the fetch down to the PKCS #15 storage \n\t   object to get any certificate that may be associated with the item.\n\t   We always do this because if we're fetching a public key then this\n\t   is all that we need and if we're fetching a private key then we'll\n\t   associate the certificate with it if it's present */\n\tif( hardwareInfo->iCryptKeyset == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tsetMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t   NULL, 0, flags | extraFlags );\n\tp15status = krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t\t IMESSAGE_KEY_GETKEY, &getkeyInfo,\n\t\t\t\t\t\t\t\t KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusOK( p15status ) )\n\t\t{\n\t\tiCryptCert = getkeyInfo.cryptHandle;\n\n\t\t/* If we were after a public key, we're done */\n\t\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t{\n\t\t\t*iCryptContext = iCryptCert;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* If we were after a private key and the keyID is one that isn't\n\t\t   stored locally, extract it from the returned private key */\n\t\t// This won't work, there's no CRYPT_IKEYID_KEYID or \n\t\t// CRYPT_IKEYID_PGPKEYID with the cert, only an \n\t\t// CRYPT_IKEYID_ISSUERANDSERIALNUMBER\n\t\t}\n\n\t/* Look up the private key, which we may use directly or simply extract\n\t   the public-key components from.  If there's an error then we \n\t   preferentially return the error code from the storage object, which \n\t   is likely to be more informative than a generic CRYPT_ERROR_NOTFOUND \n\t   from the hardware lookup */\n\tstatus = hwLookupItemInfo( keyIDtype, keyID, keyIDlength, &keyHandle, \n\t\t\t\t\t\t\t   &keyInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptStatusError( p15status ) ? p15status : status );\n\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t/* There's no certificate present but we do have private-key \n\t\t   components from which we can extract the public-key portion to\n\t\t   create a native context instead of a device one.  This solves a \n\t\t   variety of problems including the fact that performing public-key \n\t\t   operations natively is often much faster than the time it takes\n\t\t   to marshall the data and get it to the crypto hardware, and that \n\t\t   if we do it ourselves we can defend against a variety of RSA \n\t\t   padding and timing attacks that have come up since the device \n\t\t   firmware was done */\n\t\tsetMessageCreateObjectInfo( &createInfo, keyInfo.cryptAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiLocalContext = createInfo.cryptHandle;\n\n\t\t/* Send the keying information to the context.  We don't set the \n\t\t   action flags because there are none recorded at the hardware \n\t\t   level */\n\t\tstatus = setPublicComponents( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  keyInfo.cryptAlgo, \n\t\t\t\t\t\t\t\t\t  &keyInfo.publicKeyInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t*iCryptContext = iLocalContext;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a private key, create a dummy context for the device object, \n\t   remember the device that it's contained in, and record the handle for \n\t   the device-internal key */\n\tcapabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList, \n\t\t\t\t\t\t\t\t\t\t\tkeyInfo.cryptAlgo );\n\tif( capabilityInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tstatus = createContextFromCapability( &iLocalContext, cryptDevice, \n\t\t\t\t\t\t\t\t\t\t  capabilityInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  CREATEOBJECT_FLAG_DUMMY | \\\n\t\t\t\t\t\t\t\t\t\t  CREATEOBJECT_FLAG_PERSISTENT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( iCryptCert != CRYPT_UNUSED )\n\t\t\tkrnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &cryptDevice, \n\t\t\t\t\t\t\t  SETDEP_OPTION_INCREF );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &keyHandle, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\tif( iCryptCert != CRYPT_UNUSED )\n\t\t\tkrnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Set the object's label, send the keying information to the context, \n\t   and mark it as initialised (i.e. with a key loaded).  Setting the \n\t   label requires special care because the label that we're setting \n\t   matches that of an existing object, so trying to set it as a standard \n\t   CRYPT_CTXINFO_LABEL will return a CRYPT_ERROR_DUPLICATE error when \n\t   the context code checks for the existence of an existing label.  To \n\t   handle this, we use the attribute CRYPT_IATTRIBUTE_EXISTINGLABEL to \n\t   indicate that we're setting a label that matches an existing object \n\t   in the device */\n\tif( keyInfo.labelLength <= 0 )\n\t\t{\n\t\t/* If there's no label present, use a dummy value */\n\t\tstrlcpy_s( keyInfo.label, CRYPT_MAX_TEXTSIZE, \"Label-less private key\" );\n\t\tkeyInfo.labelLength = 22;\n\t\t}\n\tsetMessageData( &msgData, keyInfo.label, keyInfo.labelLength );\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = setPublicComponents( iLocalContext, keyInfo.cryptAlgo, \n\t\t\t\t\t\t\t\t\t  &keyInfo.publicKeyInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\tif( cryptStatusOK( status ) && ( iCryptCert != CRYPT_UNUSED ) )\n\t\t{\n\t\t/* If there's a certificate present, attach it to the context.  The \n\t\t   certificate is an internal object used only by the context so we \n\t\t   tell the kernel to mark it as owned by the context only */\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCryptCert, \n\t\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\tif( iCryptCert != CRYPT_UNUSED )\n\t\t\tkrnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );\n\t\t}\n#endif /* 1 */\n\n\t*iCryptContext = iLocalContext;\n\treturn( CRYPT_OK );\n\t}\n\n/* Add an object to a device.  This can only ever add a certificate\n   (enforced by the kernel ACLs) so we don't have to perform any \n   special-case handling */\n\nstatic int setItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\tconst CRYPT_HANDLE iCryptHandle )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\n\t/* Redirect the add down to the PKCS #15 storage object */\n\tif( hardwareInfo->iCryptKeyset == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = iCryptHandle;\n\treturn( krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t IMESSAGE_KEY_SETKEY, &setkeyInfo,\n\t\t\t\t\t\t\t KEYMGMT_ITEM_PUBLICKEY ) );\n\t}\n\n/* Delete an object in a device */\n\nstatic int deleteItemFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t   const KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   const void *keyID, const int keyIDlength )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo, deletekeyInfo;\n\tint status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME );\n\tREQUIRES( keyIDlength > 0 && keyIDlength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Perform the delete both from the PKCS #15 storage object and the\n\t   native storage.  This gets a bit complicated because in order to \n\t   find the hardware object we have to extract the storageID, and in\n\t   order to get that we have to instantiate a dummy private-key object\n\t   to contain it.  In addition if the object that's stored isn't a\n\t   private-key object then there's no associated cryptographic \n\t   hardware object.  To handle this we try and instantiate a dummy\n\t   private-key object in order to get the storageID.  If this succeeds,\n\t   we locate the underlying hardware object and delete it.  Finally, we\n\t   delete the PKCS #15 object, either a pure public-key/certificate \n\t   object or the private-key metadata for the cryptographic hardware\n\t   object */\n\tif( hardwareInfo->iCryptKeyset == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tsetMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo,\n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint keyHandle;\n\n\t\t/* It's a private-key object, get its hardware reference and delete \n\t\t   it.  If this fails we continue anyway because we know that \n\t\t   there's also a PKCS #15 object to delete */\n\t\tstatus = getHardwareReference( getkeyInfo.cryptHandle, &keyHandle );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t( void ) hwDeleteItem( keyHandle );\n\t\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tsetMessageKeymgmtInfo( &deletekeyInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\treturn( krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t IMESSAGE_KEY_DELETEKEY, &deletekeyInfo,\n\t\t\t\t\t\t\t itemType ) );\n\t}\n\n/* Get the sequence of certificates in a chain from a device.  Since these \n   functions operate only on certificates we can redirect them straight down \n   to the underlying storage object */\n\nstatic int getFirstItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\t CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t int *stateInfo, \n\t\t\t\t\t\t\t\t const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t const void *keyID, const int keyIDlength,\n\t\t\t\t\t\t\t\t const KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t\t\t\t\t const int options )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tMESSAGE_KEYMGMT_INFO getnextcertInfo;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\n\tREQUIRES( keyIDtype == CRYPT_IKEYID_KEYID );\n\tREQUIRES( keyIDlength > 4 && keyIDlength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\n\t/* Get the first certificate */\n\tsetMessageKeymgmtInfo( &getnextcertInfo, keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t   stateInfo, sizeof( int ), options );\n\treturn( krnlSendMessage( hardwareInfo->iCryptKeyset, \n\t\t\t\t\t\t\t IMESSAGE_KEY_GETFIRSTCERT, &getnextcertInfo, \n\t\t\t\t\t\t\t KEYMGMT_ITEM_PUBLICKEY ) );\n\t}\n\nstatic int getNextItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tint *stateInfo, const int options )\n\t{\n\tHARDWARE_INFO *hardwareInfo = deviceInfo->deviceHardware;\n\tMESSAGE_KEYMGMT_INFO getnextcertInfo;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( *stateInfo ) || \\\n\t\t\t  *stateInfo == CRYPT_ERROR );\n\n\tUNUSED_ARG( hardwareInfo );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* If the previous certificate was the last one, there's nothing left to \n\t   fetch */\n\tif( *stateInfo == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Get the next certificate */\n\tsetMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0, \n\t\t\t\t\t\t   stateInfo, sizeof( int ), options );\n\treturn( krnlSendMessage( hardwareInfo->iCryptKeyset, \n\t\t\t\t\t\t\t IMESSAGE_KEY_GETNEXTCERT, &getnextcertInfo, \n\t\t\t\t\t\t\t KEYMGMT_ITEM_PUBLICKEY ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCryptographic HAL Assist Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following helper routines provide common functionality needed by most \n   cryptographic HALs, which avoids having to reimplement the same code in \n   each HAL module.  These are called from the HAL to provide services such \n   as keygen assist and various context-management functions */\n\n/* Set up a mapping from a context to its associated information in the\n   underlying hardware.  This generates a storageID for the information and\n   records it and the hardware handle in the context.  The caller has to \n   record the storageID alongside the crypto information held by the \n   hardware for later use to look up the information */\n\nint setPersonalityMapping( CONTEXT_INFO *contextInfoPtr, const int keyHandle,\n\t\t\t\t\t\t   void *storageID, const int storageIDlength )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tHARDWARE_INFO *hardwareInfo;\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ KEYID_SIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( storageID, storageIDlength ) );\n\n\tREQUIRES( keyHandle >= 0 && keyHandle < INT_MAX );\n\tREQUIRES( storageIDlength >= 4 && storageIDlength <= KEYID_SIZE );\n\n\t/* Set up the mapping information in the context */\n\tstatus = hwGetRandom( buffer, KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, buffer, KEYID_SIZE );\n\tstatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_DEVICESTORAGEID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &keyHandle, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy the storageID back to the caller */\n\tmemcpy( storageID, buffer, storageIDlength );\n\n\t/* If it's a non-PKC context then there's nothing further to do */\n\tif( contextInfoPtr->type != CONTEXT_PKC )\n\t\treturn( CRYPT_OK );\n\n\t/* As a variation of the above, if it's a public-key context then we \n\t   don't want to persist it to the storage object because public-key\n\t   contexts a bit of an anomaly, when generating our own keys we always \n\t   have full private keys and when obtaining public keys from an \n\t   external source they'll be in the form of certificates so there isn't \n\t   really much need for persistent raw public keys.  At the moment the \n\t   only time they're used is for the self-test, and potentially \n\t   polluting the (typically quite limited) crypto hardware storage with \n\t   unneeded public keys doesn't seem like a good idea */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY ) )\n\t\treturn( CRYPT_OK );\n\n\t/* It's a PKC context, prepare to persist the key metadata to the \n\t   underlying PKCS #15 object store */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &hardwareInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hardwareInfo->iCryptKeyset == CRYPT_ERROR )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Since this is a dummy context that contains no actual keying \n\t   information (the key data is held in hardware) we set it as \n\t   KEYMGMT_ITEM_KEYMETADATA */\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, NULL, 0, \n\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = contextInfoPtr->objectHandle;\n\tstatus = krnlSendMessage( hardwareInfo->iCryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_SETKEY, &setkeyInfo,\n\t\t\t\t\t\t\t  KEYMGMT_ITEM_KEYMETADATA );\n\tkrnlReleaseObject( iCryptDevice );\n\n\treturn( status );\n\t}\n\n/* Many hardware devices have no native public/private key generation \n   support or can only generate something like the DLP x value, which is \n   just a raw string of random bits, but can't generate a full set of\n   public/private key parameters since these require complex bignum\n   operations not supported by the underlying cryptologic.  To handle this\n   we provide supplementary software support routines that generate the\n   key parameters using native contexts and bignum code and then pass them\n   back to the crypto HAL to load into the cryptlogic */\n\nstatic int generateKeyComponents( CONTEXT_INFO *staticContextInfo,\n\t\t\t\t\t\t\t\t  PKC_INFO *contextData, \n\t\t\t\t\t\t\t\t  const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t\t  const int keySizeBits )\n\t{\n\tint status;\n\n\tassert( isWritePtr( staticContextInfo, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( contextData, sizeof( PKC_INFO ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Initialise a static context to generate the key into */\n\tstatus = staticInitContext( staticContextInfo, CONTEXT_PKC, \n\t\t\t\t\t\t\t\tcapabilityInfoPtr, contextData, \n\t\t\t\t\t\t\t\tsizeof( PKC_INFO ), NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate a key into the static context */\n\tstatus = capabilityInfoPtr->generateKeyFunction( staticContextInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t\t keySizeBits );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstaticDestroyContext( staticContextInfo );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int rsaGenerateComponents( CRYPT_PKCINFO_RSA *rsaKeyInfo,\n\t\t\t\t\t\t\t\t  const int keySizeBits )\n\t{\n\tCONTEXT_INFO staticContextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tint length, status;\n\n\tassert( isWritePtr( rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Clear return value */\n\tcryptInitComponents( rsaKeyInfo, FALSE );\n\n\t/* Generate the key components */\n\tstatus = generateKeyComponents( &staticContextInfo, &contextData, \n\t\t\t\t\t\t\t\t\tgetRSACapability(), keySizeBits );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Extract the newly-generated key components for the caller to use */\n\trsaKeyInfo->nLen = BN_num_bits( &pkcInfo->rsaParam_n );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_n, rsaKeyInfo->n );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->nLen ) );\n\trsaKeyInfo->eLen = BN_num_bits( &pkcInfo->rsaParam_e );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_e, rsaKeyInfo->e );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->eLen ) );\n\trsaKeyInfo->pLen = BN_num_bits( &pkcInfo->rsaParam_p );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_p, rsaKeyInfo->p );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->pLen ) );\n\trsaKeyInfo->qLen = BN_num_bits( &pkcInfo->rsaParam_q );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_q, rsaKeyInfo->q );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->qLen ) );\n\trsaKeyInfo->e1Len = BN_num_bits( &pkcInfo->rsaParam_exponent1 );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_exponent1, rsaKeyInfo->e1 );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->e1Len ) );\n\trsaKeyInfo->e2Len = BN_num_bits( &pkcInfo->rsaParam_exponent2 );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_exponent2, rsaKeyInfo->e2 );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->e2Len ) );\n\trsaKeyInfo->uLen = BN_num_bits( &pkcInfo->rsaParam_u );\n\tlength = BN_bn2bin( &pkcInfo->rsaParam_u, rsaKeyInfo->u );\n\tENSURES( length == bitsToBytes( rsaKeyInfo->uLen ) );\n\tstaticDestroyContext( &staticContextInfo );\n\n\treturn( status );\n\t}\n\n#if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL )\n\nstatic int dlpGenerateComponents( CRYPT_PKCINFO_DLP *dlpKeyInfo,\n\t\t\t\t\t\t\t\t  const int keySizeBits,\n\t\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCONTEXT_INFO staticContextInfo;\n\tPKC_INFO contextData, *pkcInfo = &contextData;\n\tint length, status;\n\n\tassert( isWritePtr( dlpKeyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t  cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t  cryptAlgo == CRYPT_ALGO_ELGAMAL );\n\n\t/* Clear return value */\n\tcryptInitComponents( dlpKeyInfo, FALSE );\n\n\t/* Generate the key components */\n\tswitch( cryptAlgo )\n\t\t{\n#ifdef USE_DH\n\t\tcase CRYPT_ALGO_DH:\n\t\t\tstatus = generateKeyComponents( &staticContextInfo, &contextData, \n\t\t\t\t\t\t\t\t\t\t\tgetDHCapability(), keySizeBits );\n\t\t\tbreak;\n#endif /* USE_DH */\n\n#ifdef USE_DSA\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tstatus = generateKeyComponents( &staticContextInfo, &contextData, \n\t\t\t\t\t\t\t\t\t\t\tgetDSACapability(), keySizeBits );\n\t\t\tbreak;\n#endif /* USE_DSA */\n\n#ifdef USE_ELGAMAL\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tstatus = generateKeyComponents( &staticContextInfo, &contextData, \n\t\t\t\t\t\t\t\t\t\t\tgetElgamalCapability(), keySizeBits );\n\t\t\tbreak;\n#endif /* USE_ELGAMAL */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Extract the newly-generated key components for the caller to use */\n\tdlpKeyInfo->pLen = BN_num_bits( &pkcInfo->dlpParam_p );\n\tlength = BN_bn2bin( &pkcInfo->dlpParam_p, dlpKeyInfo->p );\n\tENSURES( length == bitsToBytes( dlpKeyInfo->pLen ) );\n\tdlpKeyInfo->gLen = BN_num_bits( &pkcInfo->dlpParam_g );\n\tlength = BN_bn2bin( &pkcInfo->dlpParam_g, dlpKeyInfo->g );\n\tENSURES( length == bitsToBytes( dlpKeyInfo->gLen ) );\n\tdlpKeyInfo->qLen = BN_num_bits( &pkcInfo->dlpParam_q );\n\tlength = BN_bn2bin( &pkcInfo->dlpParam_q, dlpKeyInfo->q );\n\tENSURES( length == bitsToBytes( dlpKeyInfo->qLen ) );\n\tdlpKeyInfo->yLen = BN_num_bits( &pkcInfo->dlpParam_y );\n\tlength = BN_bn2bin( &pkcInfo->dlpParam_y, dlpKeyInfo->y );\n\tENSURES( length == bitsToBytes( dlpKeyInfo->yLen ) );\n\tdlpKeyInfo->xLen = BN_num_bits( &pkcInfo->dlpParam_x );\n\tlength = BN_bn2bin( &pkcInfo->dlpParam_x, dlpKeyInfo->x );\n\tENSURES( length == bitsToBytes( dlpKeyInfo->xLen ) );\n\tstaticDestroyContext( &staticContextInfo );\n\n\treturn( status );\n\t}\n#endif /* USE_DH || USE_DSA || USE_ELGAMAL */\n\nint generatePKCcomponents( CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t   void *keyInfo, const int keySizeBits )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keyInfo != NULL );\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tswitch( capabilityInfoPtr->cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tstatus = rsaGenerateComponents( keyInfo, keySizeBits );\n\t\t\tbreak;\n\n#if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL )\n\t\tcase CRYPT_ALGO_DH:\n\t\tcase CRYPT_ALGO_DSA:\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tstatus = dlpGenerateComponents( keyInfo, keySizeBits, \n\t\t\t\t\t\t\t\t\t\t\tcapabilityInfoPtr->cryptAlgo );\n\t\t\tbreak;\n#endif /* USE_DH || USE_DSA || USE_ELGAMAL */\n\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the public-key data (needed for certificates and the like) to \n\t   the context */\n\treturn( setPKCinfo( contextInfoPtr, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\tkeyInfo ) );\n\t}\n\n/* Send public-key data to the context for use with certificate objects */\n\nint setPKCinfo( CONTEXT_INFO *contextInfoPtr, \n\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo, const void *keyInfo )\n\t{\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ];\n\tMESSAGE_DATA msgData;\n\tint keyDataSize, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( cryptAlgo == CRYPT_ALGO_RSA && \\\n\t\t\t  isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) ) || \\\n\t\t\t( cryptAlgo != CRYPT_ALGO_RSA && \\\n\t\t\t  isReadPtr( keyInfo, sizeof( CRYPT_PKCINFO_DLP ) ) ) );\n\n\tREQUIRES( cryptAlgo == CRYPT_ALGO_DH || \\\n\t\t\t  cryptAlgo == CRYPT_ALGO_RSA || \\\n\t\t\t  cryptAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t  cryptAlgo == CRYPT_ALGO_ELGAMAL );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all that we're doing here is sending in encoded public key data for \n\t   use by objects such as certificates */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\t{\n\t\t\tconst CRYPT_PKCINFO_RSA *rsaKeyInfo = \\\n\t\t\t\t\t\t( CRYPT_PKCINFO_RSA * ) keyInfo;\n\n\t\t\tif( rsaKeyInfo->isPublicKey ) \n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\t\telse\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t\tstatus = writeFlatPublicKey( keyDataBuffer, \n\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE * 4, &keyDataSize, \n\t\t\t\t\t\t\tCRYPT_ALGO_RSA, 0, rsaKeyInfo->n, \n\t\t\t\t\t\t\tbitsToBytes( rsaKeyInfo->nLen ), rsaKeyInfo->e, \n\t\t\t\t\t\t\tbitsToBytes( rsaKeyInfo->eLen ), NULL, 0, \n\t\t\t\t\t\t\tNULL, 0 );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_ALGO_DH:\n\t\tcase CRYPT_ALGO_DSA:\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\t{\n\t\t\tconst CRYPT_PKCINFO_DLP *dlpKeyInfo = \\\n\t\t\t\t\t\t( CRYPT_PKCINFO_DLP * ) keyInfo;\n\n\t\t\tif( dlpKeyInfo->isPublicKey ) \n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY );\n\t\t\telse\n\t\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t\tstatus = writeFlatPublicKey( keyDataBuffer, \n\t\t\t\t\t\tCRYPT_MAX_PKCSIZE * 4, &keyDataSize, cryptAlgo, 0,\n\t\t\t\t\t\tdlpKeyInfo->p, bitsToBytes( dlpKeyInfo->pLen ), \n\t\t\t\t\t\tdlpKeyInfo->q, bitsToBytes( dlpKeyInfo->qLen ), \n\t\t\t\t\t\tdlpKeyInfo->g, bitsToBytes( dlpKeyInfo->gLen ), \n\t\t\t\t\t\tdlpKeyInfo->y, bitsToBytes( dlpKeyInfo->yLen ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\treturn( krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL ) );\n\t}\n\n/* Send encryption/MAC keying metadata to the context */\n\nint setConvInfo( const CRYPT_CONTEXT iCryptContext, const int keySize )\n\t{\n\tassert( isHandleRangeValid( iCryptContext ) );\n\n\tREQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE );\n\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t ( MESSAGE_CAST ) &keySize, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_KEYSIZE ) );\n\t}\n\n/* The default cleanup function, which simply frees the context-related data \n   used by the cryptographic hardware if it's an ephemeral key */\n\nint cleanupHardwareContext( const CONTEXT_INFO *contextInfoPtr )\n\t{\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* If this is non-ephemeral context data then we leave it intact when \n\t   the corresponding context is destroyed, the only way to delete it is \n\t   with an explicit deleteItem() */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\treturn( CRYPT_OK );\n\n\t/* We have to be careful about deleting the context data since it may\n\t   not have been set up yet, for example if we're called due to a \n\t   failure in the complete-creation/initialisation step of setting up a \n\t   context */\n\tif( contextInfoPtr->deviceObject != CRYPT_ERROR )\n\t\thwDeleteItem( contextInfoPtr->deviceObject );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Mechanisms supported by the hardware.  These are actually cryptlib native \n   mechanisms, but not the full set supported by the system device since \n   functions like private key export aren't available.  The  list is sorted \n   in order of frequency of use in order to make lookups a bit faster */\n\nstatic const MECHANISM_FUNCTION_INFO mechanismFunctions[] = {\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },\n#endif /* USE_SSL && USE_RSA_SUITES */\n#ifdef USE_PGP\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },\n#endif /* USE_PGP */\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PBKDF2, ( MECHANISM_FUNCTION ) derivePBKDF2 },\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },\n#endif /* USE_PGP || USE_PGPKEYS */\n#ifdef USE_SSL\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveSSL },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveTLS },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },\n#endif /* USE_SSL */\n#ifdef USE_CMP\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },\n#endif /* USE_CMP */\n#ifdef USE_PKCS12\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },\n#endif /* USE_PKCS12 */\n\t{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }\n\t};\n\n/* Set up the function pointers to the device methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setDeviceHardware( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tFNPTR_SET( deviceInfo->initFunction, initFunction );\n\tFNPTR_SET( deviceInfo->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( deviceInfo->controlFunction, controlFunction );\n\tFNPTR_SET( deviceInfo->getItemFunction, getItemFunction );\n\tFNPTR_SET( deviceInfo->setItemFunction, setItemFunction );\n\tFNPTR_SET( deviceInfo->deleteItemFunction, deleteItemFunction );\n\tFNPTR_SET( deviceInfo->getFirstItemFunction, getFirstItemFunction );\n\tFNPTR_SET( deviceInfo->getNextItemFunction, getNextItemFunction );\n\tFNPTR_SET( deviceInfo->getRandomFunction, getRandomFunction );\n\tDATAPTR_SET( deviceInfo->capabilityInfoList, capabilityInfoList );\n\tdeviceInfo->mechanismFunctions = mechanismFunctions;\n\tdeviceInfo->mechanismFunctionCount = \\\n\t\tFAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_HARDWARE */\n"
  },
  {
    "path": "deps/cl345/device/hardware.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Generic Crypto HW Header\t\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The access functions that must be provided by each HAL module */\n\nint hwGetCapabilities( const CAPABILITY_INFO **capabilityInfo,\n\t\t\t\t\t   int *noCapabilities );\nint hwGetRandom( void *buffer, const int length );\nint hwLookupItem( const void *keyID, const int keyIDlength, int *keyHandle );\nint hwDeleteItem( const int keyHandle );\nint hwInitialise( void );\n\n/* Helper functions in hardware.c that may be used by HAL modules */\n\nint setPersonalityMapping( CONTEXT_INFO *contextInfoPtr, const int keyHandle,\n\t\t\t\t\t\t   void *storageID, const int storageIDlength );\nint generatePKCcomponents( CONTEXT_INFO *contextInfoPtr, void *keyInfo, \n\t\t\t\t\t\t   const int keySizeBits );\nint setPKCinfo( CONTEXT_INFO *contextInfoPtr, \n\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo, const void *keyInfo );\nint setConvInfo( const CRYPT_CONTEXT iCryptContext, const int keySize );\nint cleanupHardwareContext( const CONTEXT_INFO *contextInfoPtr );\n"
  },
  {
    "path": "deps/cl345/device/hw_dummy.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Dummy Crypto HAL Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is a template for use when adding support for custom \n   cryptographic hardware to cryptlib.  It implements dummy versions of the\n   cryptographic operations that are provided by the custom hardware.  See\n   the inline comments for what's needed at each stage */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"hardware.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/hardware.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HARDWARE\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPersonality Storage\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Each key, along with its associated identifiers, certificates, and other\n   metadata, constitutes a personality.  cryptlib manages most of this \n   information externally, the only data that's stored here is the keying\n   information in whatever format the cryptographic hardware uses and a \n   short binary unique-ID value, the storageID, that cryptlib uses to look \n   up a personality.  \n   \n   Externally, cryptlib maintains a 160-bit value as a storageID but this \n   module only needs to use as much of it as required to avoid a false\n   positive match.  In this case we use 64 bits of the storageID to look up\n   a personality */\n\n#define STORAGEID_SIZE\t\t8\n\n/* Private key data will generally be stored in a hardware-specific internal\n   format.  For demonstration purposes we assume that this consists of \n   32-bit big-endian words (chosen because the most widely-deployed \n   architectures are little-endian, so this guarantees that if there's a\n   problem it'll be caught by the different endianness), which we need to \n   convert to and from the generic CRYPT_PKCINFO_RSA/CRYPT_PKCINFO_DLP \n   format on import and export.  The following structure is used to store \n   data in the dummy hardware-internal format.  The layout of the data is \n   as follows:\n\n\tIndex\tRSA value\tDLP value\tECC value\n\t-----\t---------\t---------\t---------\n\t  0\t\t\tn\t\t\tp\t\t\tp\n\t  1\t\t\te\t\t\tq\t\t\ta\n\t  2\t\t\td\t\t\tq\t\t\tb\n\t  3\t\t\tp\t\t\ty\t\t\tgx\n\t  4\t\t\tq\t\t\tx\t\t\tgy\n\t  5\t\t\tu\t\t\t\t\t\tr\n\t  6\t\t\te1\t\t\t\t\t\th\n\t  7\t\t\te2\t\t\t\t\t\t[...] */\t\n\ntypedef struct {\n\tLONG data[ CRYPT_MAX_PKCSIZE / sizeof( LONG ) ];\n\tint dataSize;\n\t} BIGNUM_STORAGE;\n\n#define NO_BIGNUMS\t\t8\n\n/* Each personality contains (at least) the storageID used to reference it\n   and whatever keying information is needed by the underlying cryptographic\n   hardware.  The following structure contains the information stored for \n   each personality.  The inUse flag is a convenience feature, it can also \n   be indicated through a convention such as an all-zero storageID */\n\ntypedef struct {\n\t/* General management information */\n\tBOOLEAN inUse;\t\t\t\t/* Whether this personality is in use */\n\tBYTE storageID[ STORAGEID_SIZE ];/* ID used to look up this personality */\n\n\t/* Key data storage */\n\tunion {\n\t\tBYTE convKeyInfo[ CRYPT_MAX_KEYSIZE ];\n\t\tBIGNUM_STORAGE pkcKeyInfo[ NO_BIGNUMS ];\n\t\t} keyInfo;\n\t} PERSONALITY_INFO;\n\n/* Storage for each personality.  This would typically be held either in \n   internal protected memory (for example battery-backed device-internal \n   SRAM) or encrypted external memory that's transparently accessed as \n   standard memory.  The memory doesn't explicitly have to be zeroed since\n   cryptlib does this on device initialisation, it's done here merely as\n   a convenience during debugging */\n\n#define NO_PERSONALITIES\t8\n\nstatic PERSONALITY_INFO personalityInfo[ NO_PERSONALITIES ] = { 0 };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPersonality Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following routines manage access to the personality storage and \n   represent an example implementation matching the sample PERSONALITY_INFO\n   structure defined earlier.  The routines look up a personality given its\n   storageID, find a free personality slot to use when instantiating a new\n   personality (or in more high-level terms when loading or generating a\n   key for an encryption context), and delete a personality */\n\n/* Look up a personality given a key ID */\n\nstatic int lookupPersonality( const void *keyID, const int keyIDlength,\n\t\t\t\t\t\t\t  int *keyHandle )\n\t{\n\tconst int storageIDlength = min( keyIDlength, STORAGEID_SIZE );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( isWritePtr( keyHandle, sizeof( int ) ) );\n\n\tREQUIRES( keyIDlength >= 4 && keyIDlength <= KEYID_SIZE );\n\n\t/* Clear return value */\n\t*keyHandle = CRYPT_ERROR;\n\n\t/* Scan the personality table looking for one matching the given \n\t   storageID */\n\tLOOP_MED( i = 0, i < NO_PERSONALITIES, i++ )\n\t\t{\n\t\tPERSONALITY_INFO *personalityInfoPtr = &personalityInfo[ i ];\n\n\t\tif( !personalityInfoPtr->inUse )\n\t\t\tcontinue;\n\t\tif( !memcmp( personalityInfoPtr->storageID, keyID, storageIDlength ) )\n\t\t\t{\n\t\t\t*keyHandle = i;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* Find a free personality */\n\nstatic int findFreePersonality( int *keyHandle )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( keyHandle, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*keyHandle = CRYPT_ERROR;\n\n\t/* Scan the personality table looking for a free slot */\n\tLOOP_MED( i = 0, i < NO_PERSONALITIES, i++ )\n\t\t{\n\t\tPERSONALITY_INFO *personalityInfoPtr = &personalityInfo[ i ];\n\n\t\tif( !personalityInfoPtr->inUse )\n\t\t\t{\n\t\t\tzeroise( personalityInfoPtr, sizeof( PERSONALITY_INFO ) );\n\t\t\t*keyHandle = i;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_ERROR_OVERFLOW );\n\t}\n\n/* Delete a personality */\n\nstatic void deletePersonality( const int keyHandle )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr;\n\n\tREQUIRES_V( keyHandle >= 0 && keyHandle < NO_PERSONALITIES );\n\n\tif( keyHandle < 0 || keyHandle >= NO_PERSONALITIES )\n\t\treturn;\n\tpersonalityInfoPtr = &personalityInfo[ keyHandle ];\n\tzeroise( personalityInfoPtr, sizeof( PERSONALITY_INFO ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions used to convert from the dummy hardware-internal bignum format \n   (big-endian 32-bit words) to the generic external format */\n\nstatic void bignumToInternal( LONG *outData, int *outDataLength, \n\t\t\t\t\t\t\t  const BYTE *inData, const int inDataLength )\n\t{\n\tint inIndex, outIndex = 0, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( outData, CRYPT_MAX_PKCSIZE ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( inData, inDataLength ) );\n\n\tREQUIRES_V( inDataLength > 0 && inDataLength <= CRYPT_MAX_PKCSIZE );\n\n\tLOOP_LARGE( i = 0, i < CRYPT_MAX_PKCSIZE / sizeof( LONG ), i++ )\n\t\toutData[ i ] = 0L;\n\tENSURES_V( LOOP_BOUND_OK );\n\tLOOP_LARGE( inIndex = 0, inIndex < inDataLength, inIndex += sizeof( LONG ) )\n\t\t{\n\t\toutData[ outIndex++ ] = mgetLong( inData );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t*outDataLength = outIndex;\n\t}\n\nstatic void bignumToExternal( BYTE *outData, int *outDataLength,\n\t\t\t\t\t\t\t  const LONG *inData, const int inDataLength )\n\t{\n\tint inIndex = 0, outIndex, LOOP_ITERATOR;\n\n\tassert( isWritePtr( outData, CRYPT_MAX_PKCSIZE ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( inData, inDataLength * sizeof( LONG ) ) );\n\n\tREQUIRES_V( inDataLength > 0 && \\\n\t\t\t\tinDataLength <= CRYPT_MAX_PKCSIZE / sizeof( LONG ) );\n\n\tmemset( outData, 0, CRYPT_MAX_PKCSIZE );\n\tLOOP_LARGE( outIndex = 0, outIndex < inDataLength, outIndex++ )\n\t\t{\n\t\tconst LONG value = inData[ inIndex++ ];\n\n\t\tmputLong( outData, value );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t*outDataLength = outIndex * sizeof( LONG );\n\t}\n\n/* Dummy functions used to \"encrypt\" data and generate \"random\" data in the \n   absence of any actual hardware functionality */\n\nstatic void dummyEncrypt( const PERSONALITY_INFO *personalityInfoPtr,\n\t\t\t\t\t\t  BYTE *data, const int length,\n\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t  const CRYPT_MODE_TYPE cryptMode )\n\t{\n\tint i;\n\n\tassert( isReadPtr( personalityInfoPtr, sizeof( PERSONALITY_INFO ) ) );\n\tassert( isWritePtrDynamic( data, length ) );\n\n\tREQUIRES_V( cryptAlgo > CRYPT_ALGO_NONE && \\\n\t\t\t\tcryptAlgo < CRYPT_ALGO_LAST_EXTERNAL );\n\tREQUIRES_V( isEnumRangeOpt( cryptMode, CRYPT_MODE ) );\n\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tBYTE bignumData[ CRYPT_MAX_PKCSIZE + 8 ];\n\t\tint bignumDataLength;\n\n\t\tbignumToExternal( bignumData, &bignumDataLength, \n\t\t\t\t\t\t  personalityInfoPtr->keyInfo.pkcKeyInfo[ 0 ].data,\n\t\t\t\t\t\t  personalityInfoPtr->keyInfo.pkcKeyInfo[ 0 ].dataSize );\n\t\tfor( i = 0; i < length; i++ )\n\t\t\tdata[ i ] ^= bignumData[ i ];\n\n\t\treturn;\n\t\t}\n\n\t/* We have to be a bit careful with the conventional encryption because \n\t   the self-tests encrypt data in variable-length quantities to check \n\t   for things like chaining problems, which means that for stream \n\t   ciphers we really can't do anything more than repeatedly XOR with a\n\t   fixed key byte */\n#ifdef USE_CFB\n\tif( cryptMode == CRYPT_MODE_CFB )\n\t\t{\n\t\tconst int keyDataOffset = CRYPT_MODE_CFB ? 0 : 1;\n\n\t\tfor( i = 0; i < length; i++ )\n\t\t\tdata[ i ] ^= personalityInfoPtr->keyInfo.convKeyInfo[ keyDataOffset ];\n\t\t}\n\telse\n#endif /* USE_CFB */\n\t\t{\n\t\t/* It's a block mode, we can at least use ECB, although we still \n\t\t   can't chain because we don't know where we are in the data \n\t\t   stream */\n\t\tfor( i = 0; i < length; i++ )\n\t\t\tdata[ i ] ^= personalityInfoPtr->keyInfo.convKeyInfo[ i % 16 ];\n\t\t}\n\t}\n\nstatic void dummyGenRandom( void *buffer, const int length )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE ], *bufPtr = buffer;\n\tstatic int counter = 0;\n\tint hashSize, i;\n\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES_V( length >= 1 && length < MAX_BUFFER_SIZE );\n\n\t/* Fill the buffer with random-ish data.  This gets a bit tricky because\n\t   we need to fool the entropy tests so we can't just fill it with a \n\t   fixed (or even semi-random) pattern but have to set up a somewhat\n\t   kludgy PRNG */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\tmemset( hashBuffer, counter, hashSize );\n\tcounter++;\n\tfor( i = 0; i < length; i++ )\n\t\t{\n\t\tif( i % hashSize == 0 )\n\t\t\t{\n\t\t\thashFunctionAtomic( hashBuffer, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\thashBuffer, hashSize );\n\t\t\t}\n\t\tbufPtr[ i ] = hashBuffer[ i % hashSize ];\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSymmetric Capability Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a self-test */\n\nstatic int aesSelfTest( void )\n\t{\n\t/* Perform the self-test */\n\t/* ... */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Load a key */\n\nstatic int completeInitKeyAES( CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t   PERSONALITY_INFO *personalityInfoPtr,\n\t\t\t\t\t\t\t   const int keyHandle, const int keySize )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( personalityInfoPtr, sizeof( PERSONALITY_INFO ) ) );\n\n\tREQUIRES( keyHandle >= 0 && keyHandle < NO_PERSONALITIES );\n\tREQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE );\n\n\t/* This personality is now active and in use, initialise the metadata \n\t   and set up the mapping from the crypto hardware personality to the\n\t   context using the helper function in hardware.c */\n\tstatus = setConvInfo( contextInfoPtr->objectHandle, keySize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = setPersonalityMapping( contextInfoPtr, keyHandle, \n\t\t\t\t\t\t\t\t\t\tpersonalityInfoPtr->storageID, \n\t\t\t\t\t\t\t\t\t\tSTORAGEID_SIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeletePersonality( keyHandle );\n\t\treturn( status );\n\t\t}\n\tpersonalityInfoPtr->inUse = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int aesInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr;\n\tint keyHandle, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( keyLength >= 1 && keyLength <= CRYPT_MAX_KEYSIZE );\n\n\t/* Find a free personality slot to store the key */\n\tstatus = findFreePersonality( &keyHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpersonalityInfoPtr = &personalityInfo[ keyHandle ];\n\n\t/* Load the key into the personality */\n\tmemcpy( personalityInfoPtr->keyInfo.convKeyInfo, key, keyLength );\n\treturn( completeInitKeyAES( contextInfoPtr, personalityInfoPtr, \n\t\t\t\t\t\t\t\tkeyHandle, keyLength ) );\n\t}\n\n/* Generate a key */\n\nstatic int aesGenerateKey( CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const int keySizeBits )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr;\n\tconst int keyLength = bitsToBytes( keySizeBits );\n\tint keyHandle, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) );\n\n\t/* Find a free personality slot to store the key */\n\tstatus = findFreePersonality( &keyHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpersonalityInfoPtr = &personalityInfo[ keyHandle ];\n\n\t/* Use the hardware RNG to generate the encryption key */\n\tstatus = hwGetRandom( personalityInfoPtr->keyInfo.convKeyInfo, keyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeletePersonality( keyHandle );\n\t\treturn( status );\n\t\t}\n\treturn( completeInitKeyAES( contextInfoPtr, personalityInfoPtr, \n\t\t\t\t\t\t\t\tkeyHandle, keyLength ) );\n\t}\n\n/* Encrypt/decrypt data */\n\nstatic int aesEncryptECB( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES, \n\t\t\t\t  CRYPT_MODE_ECB );\n\treturn( CRYPT_OK );\n\t}\nstatic int aesDecryptECB( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES, \n\t\t\t\t  CRYPT_MODE_ECB );\n\treturn( CRYPT_OK );\n\t}\n\nstatic int aesEncryptCBC( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES,\n\t\t\t\t  CRYPT_MODE_CBC );\n\treturn( CRYPT_OK );\n\t}\nstatic int aesDecryptCBC( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES,\n\t\t\t\t  CRYPT_MODE_CBC );\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_CFB\n\nstatic int aesEncryptCFB( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES,\n\t\t\t\t  CRYPT_MODE_CFB );\n\treturn( CRYPT_OK );\n\t}\nstatic int aesDecryptCFB( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\t  int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length <= MAX_INTLENGTH );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_AES,\n\t\t\t\t  CRYPT_MODE_CFB );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CFB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAsymmetric Capability Interface Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a self-test */\n\nstatic int rsaSelfTest( void )\n\t{\n\t/* Perform the self-test */\n\t/* ... */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Load a key */\n\nstatic int completeInitKeyRSA( CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t   PERSONALITY_INFO *personalityInfoPtr,\n\t\t\t\t\t\t\t   const int keyHandle )\n\t{\n\tint status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( personalityInfoPtr, sizeof( PERSONALITY_INFO ) ) );\n\n\tREQUIRES( keyHandle >= 0 && keyHandle < NO_PERSONALITIES );\n\n\t/* This personality is now active and in use, set up the mapping from \n\t   the crypto hardware personality to the context using the helper \n\t   function in hardware.c */\n\tstatus = setPersonalityMapping( contextInfoPtr, keyHandle,\n\t\t\t\t\t\t\t\t\tpersonalityInfoPtr->storageID, \n\t\t\t\t\t\t\t\t\tSTORAGEID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeletePersonality( keyHandle );\n\t\treturn( status );\n\t\t}\n\tpersonalityInfoPtr->inUse = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic void rsaKeyToInternal( BIGNUM_STORAGE *bignumStorage,\n\t\t\t\t\t\t\t  const CRYPT_PKCINFO_RSA *rsaKeyInfo )\n\t{\n\tassert( isWritePtr( bignumStorage, \\\n\t\t\t\t\t\tsizeof( BIGNUM_STORAGE ) * NO_BIGNUMS ) );\n\tassert( isReadPtr( rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) ) );\n\n\t/* Convert the RSA key components from the generic external \n\t   representation to the hardware-specific internal format */\n\tbignumToInternal( bignumStorage[ 0 ].data, &bignumStorage[ 0 ].dataSize, \n\t\t\t\t\t  rsaKeyInfo->n, bitsToBytes( rsaKeyInfo->nLen ) );\n\tbignumToInternal( bignumStorage[ 1 ].data, &bignumStorage[ 1 ].dataSize, \n\t\t\t\t\t  rsaKeyInfo->e, bitsToBytes( rsaKeyInfo->eLen ) );\n\tif( rsaKeyInfo->isPublicKey )\n\t\treturn;\n\tif( rsaKeyInfo->dLen > 0 )\n\t\t{\n\t\tbignumToInternal( bignumStorage[ 2 ].data, \n\t\t\t\t\t\t  &bignumStorage[ 2 ].dataSize, \n\t\t\t\t\t\t  rsaKeyInfo->d, bitsToBytes( rsaKeyInfo->dLen ) );\n\t\t}\n\tbignumToInternal( bignumStorage[ 3 ].data, \n\t\t\t\t\t  &bignumStorage[ 3 ].dataSize, \n\t\t\t\t\t  rsaKeyInfo->p, bitsToBytes( rsaKeyInfo->pLen ) );\n\tbignumToInternal( bignumStorage[ 4 ].data, \n\t\t\t\t\t  &bignumStorage[ 4 ].dataSize, \n\t\t\t\t\t  rsaKeyInfo->q, bitsToBytes( rsaKeyInfo->qLen ) );\n\tif( rsaKeyInfo->e1Len > 0 )\n\t\t{\n\t\tbignumToInternal( bignumStorage[ 5 ].data, \n\t\t\t\t\t\t  &bignumStorage[ 5 ].dataSize, \n\t\t\t\t\t\t  rsaKeyInfo->e1, bitsToBytes( rsaKeyInfo->e1Len ) );\n\t\tbignumToInternal( bignumStorage[ 6 ].data, \n\t\t\t\t\t\t  &bignumStorage[ 6 ].dataSize, \n\t\t\t\t\t\t  rsaKeyInfo->e2, bitsToBytes( rsaKeyInfo->e2Len ) );\n\t\tbignumToInternal( bignumStorage[ 7 ].data, \n\t\t\t\t\t\t  &bignumStorage[ 7 ].dataSize, \n\t\t\t\t\t\t  rsaKeyInfo->u, bitsToBytes( rsaKeyInfo->uLen ) );\n\t\t}\n\t}\n\nstatic int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint keyHandle, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( keyLength == sizeof( CRYPT_PKCINFO_RSA ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Find a free personality slot to store the key */\n\tstatus = findFreePersonality( &keyHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpersonalityInfoPtr = &personalityInfo[ keyHandle ];\n\n\t/* Load the key into the personality and copy the public-key portions \n\t   (needed for certificates and the like) to the context using the \n\t   helper function in hardware.c */\n\trsaKeyToInternal( personalityInfoPtr->keyInfo.pkcKeyInfo, key );\n\tstatus = setPKCinfo( contextInfoPtr, capabilityInfoPtr->cryptAlgo, key );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeletePersonality( keyHandle );\n\t\treturn( status );\n\t\t}\n\treturn( completeInitKeyRSA( contextInfoPtr, personalityInfoPtr, \n\t\t\t\t\t\t\t\tkeyHandle ) );\n\t}\n\n/* Generate a key */\n\nstatic int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const int keySizeBits )\n\t{\n\tCRYPT_PKCINFO_RSA rsaKeyInfo;\n\tPERSONALITY_INFO *personalityInfoPtr;\n\tint keyHandle, status;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Find a free personality slot to store the key */\n\tstatus = findFreePersonality( &keyHandle );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpersonalityInfoPtr = &personalityInfo[ keyHandle ];\n\n\t/* Since the hardware doesn't provide native keygen capabilities we\n\t   generate the key components using the helper function in hardware.c */\n\tstatus = generatePKCcomponents( contextInfoPtr, &rsaKeyInfo, \n\t\t\t\t\t\t\t\t\tkeySizeBits );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeletePersonality( keyHandle );\n\t\treturn( status );\n\t\t}\n\trsaKeyToInternal( personalityInfoPtr->keyInfo.pkcKeyInfo, &rsaKeyInfo );\n\tzeroise( &rsaKeyInfo, sizeof( CRYPT_PKCINFO_RSA ) );\n\treturn( completeInitKeyRSA( contextInfoPtr, personalityInfoPtr, \n\t\t\t\t\t\t\t\tkeyHandle ) );\n\t}\n\n/* Encrypt/decrypt data */\n\nstatic int rsaEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t   int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_RSA, \n\t\t\t\t  CRYPT_MODE_NONE );\n\treturn( CRYPT_OK );\n\t}\n\nstatic int rsaDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t   int length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_RSA, \n\t\t\t\t  CRYPT_MODE_NONE );\n\treturn( CRYPT_OK );\n\t}\n\n/* Sign/sig check data */\n\nstatic int rsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\tint length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_RSA,\n\t\t\t\t  CRYPT_MODE_NONE );\n\treturn( CRYPT_OK );\n\t}\n\nstatic int rsaSigCheck( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\t\tint length )\n\t{\n\tPERSONALITY_INFO *personalityInfoPtr = \\\n\t\t\t\t&personalityInfo[ contextInfoPtr->deviceObject ];\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\tdummyEncrypt( personalityInfoPtr, buffer, length, CRYPT_ALGO_RSA,\n\t\t\t\t  CRYPT_MODE_NONE );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tHash/MAC Capability Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a self-test */\n\nstatic int shaSelfTest( void )\n\t{\n\t/* Perform the self-test */\n\t/* ... */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return context subtype-specific information */\n\nstatic int shaGetInfo( const CAPABILITY_INFO_TYPE type,\n\t\t\t\t\t   CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t   void *data, const int length )\n\t{\n\tif( type == CAPABILITY_INFO_STATESIZE )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t/* Return the amount of hash-state storage needed by the SHA-1 \n\t\t   routines.  This will be allocated by cryptlib and made available\n\t\t   as contextInfoPtr->ctxHash->hashInfo */\n\t\t/* ... */\n\t\t*valuePtr = 0;\t/* Dummy version doesn't need storage */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getDefaultInfo( type, contextInfoPtr, data, length ) );\n\t}\n\n/* Hash data */\n\nstatic int shaHash( CONTEXT_INFO *contextInfoPtr, void *buffer, \n\t\t\t\t\tint length )\n\t{\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( length == 0 || isWritePtrDynamic( buffer, length ) );\n\n\t/* If the hash state was reset to allow another round of hashing,\n\t   reinitialise things */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\t{\n\t\t/* Initialise hash state in contextInfoPtr->ctxHash->hashInfo */\n\t\t/* ... */\n\t\t}\n\n\tif( length > 0 )\n\t\t{\n\t\t/* Perform the hashing using the hash state information in \n\t\t   contextInfoPtr->ctxHash->hashInfo */\n\t\t/* ... */\n\t\t}\n\telse\n\t\t{\n\t\t/* Wrap up the hashing from the state information in \n\t\t   contextInfoPtr->ctxHash->hashInfo, with the result placed in \n\t\t   contextInfoPtr->ctxHash->hash */\n\t\t/* ... */\n\t\tmemset( contextInfoPtr->ctxHash->hash, 'X', 20 );\t/* Dummy hash val.*/\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHardware External Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The capability information for this device */\n\nstatic const CAPABILITY_INFO capabilities[] = {\n\t/* The RSA capabilities */\n\t{ CRYPT_ALGO_RSA, bitsToBytes( 0 ), \"RSA\", 3,\n\t\tMIN_PKCSIZE, bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE,\n\t\trsaSelfTest, getDefaultInfo, cleanupHardwareContext, NULL, rsaInitKey, rsaGenerateKey, \n\t\trsaEncrypt, rsaDecrypt, NULL, NULL, NULL, NULL, NULL, NULL, \n\t\trsaSign, rsaSigCheck },\n\n\t/* The AES capabilities */\n\t{ CRYPT_ALGO_AES, bitsToBytes( 128 ), \"AES\", 3,\n\t\tbitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ),\n\t\taesSelfTest, getDefaultInfo, cleanupHardwareContext, initGenericParams, aesInitKey, aesGenerateKey,\n\t\taesEncryptECB, aesDecryptECB, aesEncryptCBC, aesDecryptCBC\n#ifdef USE_CFB\n\t\t, aesEncryptCFB, aesDecryptCFB \n#else\n\t\t, NULL, NULL\n#endif /* USE_CFB */\n#ifdef USE_GCM\n\t\t, NULL, NULL /* For GCM */ \n#endif /* USE_GCM */\n\t\t},\n\n\t/* The SHA-1 capabilities */\n\t{ CRYPT_ALGO_SHA1, bitsToBytes( 160 ), \"SHA-1\", 5,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ),\n\t\tshaSelfTest, shaGetInfo, NULL, NULL, NULL, NULL, shaHash, shaHash },\n\n\t/* The end-of-list marker.  This value isn't linked into the \n\t   capabilities list when we call initCapabilities() */\n\t{ CRYPT_ALGO_NONE }, { CRYPT_ALGO_NONE }\n\t};\n\n/* Return the hardware capabilities list */\n\nint hwGetCapabilities( const CAPABILITY_INFO **capabilityInfo,\n\t\t\t\t\t   int *noCapabilities )\n\t{\n\tassert( isReadPtr( capabilityInfo, sizeof( CAPABILITY_INFO * ) ) );\n\tassert( isWritePtr( noCapabilities, sizeof( int ) ) );\n\n\t*capabilityInfo = capabilities;\n\t*noCapabilities = FAILSAFE_ARRAYSIZE( capabilities, CAPABILITY_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get random data from the hardware */\n\nint hwGetRandom( void *buffer, const int length )\n\t{\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length >= 1 && length < MAX_BUFFER_SIZE );\n\n\t/* Fill the buffer with random-ish data */\n\tdummyGenRandom( buffer, length );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Look up an item held in the hardware */\n\nint hwLookupItem( const void *keyID, const int keyIDlength, int *keyHandle )\n\t{\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( isWritePtr( keyHandle, sizeof( int ) ) );\n\n\tREQUIRES( keyIDlength >= 4 && keyIDlength <= KEYID_SIZE );\n\n\t/* Clear return value */\n\t*keyHandle = CRYPT_ERROR;\n\n\treturn( lookupPersonality( keyID, keyIDlength, keyHandle ) );\n\t}\n\n/* Delete an item held in the hardware */\n\nint hwDeleteItem( const int keyHandle )\n\t{\n\tREQUIRES( keyHandle >= 0 && keyHandle < NO_PERSONALITIES );\n\n\tdeletePersonality( keyHandle );\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise/zeroise the hardware, which for this device just consists of \n   clearing the hardware personalities */\n\nint hwInitialise( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tLOOP_MED( i = 0, i < NO_PERSONALITIES, i++ )\n\t\tdeletePersonality( i );\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_HARDWARE */\n"
  },
  {
    "path": "deps/cl345/device/ms_capi.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib CryptoAPI Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2006\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following code is purely a test framework used to test the ability to\n   work with CryptoAPI keys.  Much of the code is only present as a rough\n   sketch.  It's not part of cryptlib, and shouldn't be used as a cryptlib\n   component */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n/* The size of the (packed) header used for key blobs */\n\n#define BLOBHEADER_SIZE\t\t\t8\n\n#ifdef USE_CRYPTOAPI\n\n#if defined( _MSC_VER )\n  #pragma message( \"  Building with CAPI device interface enabled.\" )\n#endif /* Warn with VC++ */\n\n/* The following define is needed to enable crypto functions in the include\n   file.  This would probably be defined by the compiler since it's not \n   defined in any header file, but it doesn't seem to be enabled by \n   default */\n\n#ifndef _WIN32_WINNT\n  #define _WIN32_WINNT\t0x0500\n#endif /* _WIN32_WINNT */\n\n/* cryptlib.h includes a trap for inclusion of wincrypt.h before cryptlib.h\n   which results in a compiler error if both files are included.  To disable \n   this, we need to undefine the CRYPT_MODE_ECB defined in cryptlib.h */\n\n#undef CRYPT_MODE_ECB\n\n#include <wincrypt.h>\n\n/* CryptoAPI uses the same mode names as cryptlib but different values, \n   fortunately this is done with #defines so we can remove them at this\n   point */\n\n#undef CRYPT_MODE_ECB\n#undef CRYPT_MODE_CBC\n#undef CRYPT_MODE_CFB\n#undef CRYPT_MODE_CTR\n\n/* Symbolic defines to represent non-initialised values */\n\n#define CALG_NONE\t\t\t0\n#define HCRYPTPROV_NONE\t\t0\n\n/* Some parts of CryptoAPI (inconsistently) require the use of Unicode,\n   winnls.h was already included via the global include of windows.h however\n   it isn't needed for any other part of cryptlib so it was disabled via\n   NONLS.  Since winnls.h is now locked out, we have to un-define the guards\n   used earlier to get it included */\n\n#undef _WINNLS_\n#undef NONLS\n#include <winnls.h>\n\n/* Older versions of wincrypt.h don't contain defines and typedefs that we\n   require.  Defines can be detected with #ifdef but typedefs can't, to \n   handle this we rely on checking for values that aren't defined in older \n   versions of wincrypt.h, which only go up to KP_PUB_EX_VAL */\n\n#ifndef KP_ADMIN_PIN\n  /* Misc values */\n  #define HCERTCHAINENGINE\t\t\t\tvoid *\n  #define USAGE_MATCH_TYPE_AND\t\t\t0\n  #define USAGE_MATCH_TYPE_OR\t\t\t1\n  #define CERT_COMPARE_KEY_IDENTIFIER\t15\n  #define CERT_FIND_KEY_IDENTIFIER\t\t( CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT )\n  #define CERT_CHAIN_CACHE_END_CERT\t\t\t\t\t0x00000001\n  #define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY\t0x80000000\n  #define CRYPT_ACQUIRE_CACHE_FLAG\t\t\t\t\t0x00000001\n\n  /* Certificate chain match information */\n  typedef struct {\n\tDWORD dwType;\n\tCERT_ENHKEY_USAGE Usage;\n\t} CERT_USAGE_MATCH;\n  typedef struct {\n\tDWORD cbSize;\n\tCERT_USAGE_MATCH RequestedUsage;\n\tCERT_USAGE_MATCH RequestedIssuancePolicy;\n\tDWORD dwUrlRetrievalTimeout;\n\tBOOL fCheckRevocationFreshnessTime;\n\tDWORD dwRevocationFreshnessTime;\n\t} CERT_CHAIN_PARA, *PCERT_CHAIN_PARA;\n\n  /* Certificate chain information */\n  typedef struct {\n\tDWORD dwErrorStatus;\n\tDWORD dwInfoStatus;\n\t} CERT_TRUST_STATUS, *PCERT_TRUST_STATUS;\n  typedef struct {\n\tDWORD cbSize;\n\tPCCERT_CONTEXT pCertContext;\n\tCERT_TRUST_STATUS TrustStatus;\n\tvoid *pRevocationInfo;\t\t// PCERT_REVOCATION_INFO pRevocationInfo;\n\tvoid *pIssuanceUsage;\t\t// PCERT_ENHKEY_USAGE pIssuanceUsage;\n\tvoid *pApplicationUsage;\t// PCERT_ENHKEY_USAGE pApplicationUsage;\n\tLPCWSTR pwszExtendedErrorInfo;\n\t} CERT_CHAIN_ELEMENT, *PCERT_CHAIN_ELEMENT;\n  typedef struct {\n\tDWORD cbSize;\n\tPCTL_ENTRY pCtlEntry;\n\tPCCTL_CONTEXT pCtlContext;\n\t} CERT_TRUST_LIST_INFO, *PCERT_TRUST_LIST_INFO;\n  typedef struct {\n\tDWORD cbSize;\n\tCERT_TRUST_STATUS TrustStatus;\n\tDWORD cElement;\n\tPCERT_CHAIN_ELEMENT *rgpElement;\n\tPCERT_TRUST_LIST_INFO pTrustListInfo;\n\tBOOL fHasRevocationFreshnessTime;\n\tDWORD dwRevocationFreshnessTime;\n\t} CERT_SIMPLE_CHAIN, *PCERT_SIMPLE_CHAIN;\n  typedef struct CCC {\n\tDWORD cbSize;\n\tCERT_TRUST_STATUS TrustStatus;\n\tDWORD cChain;\n\tPCERT_SIMPLE_CHAIN *rgpChain;\n\tDWORD cLowerQualityChainContext;\n\tstruct CCC **rgpLowerQualityChainContext;\n\tBOOL fHasRevocationFreshnessTime;\n\tDWORD dwRevocationFreshnessTime;\n\t} CERT_CHAIN_CONTEXT;\n  typedef const CERT_CHAIN_CONTEXT *PCCERT_CHAIN_CONTEXT;\n#endif /* Pre-1999 wincrypt.h */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tInit/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Global function pointers.  These are necessary because the functions need\n   to be dynamically linked since not all systems contain the necessary\n   DLL's.  Explicitly linking to them will make cryptlib unloadable on some\n   systems */\n\n#define NULL_HINSTANCE\t( HINSTANCE ) NULL\n\nstatic HINSTANCE hCryptoAPI = NULL_HINSTANCE;\nstatic HINSTANCE hAdvAPI32 = NULL_HINSTANCE;\n\ntypedef BOOL ( WINAPI *CERTADDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,\n\t\t\t\t\tPCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,\n\t\t\t\t\tPCCERT_CONTEXT *ppStoreContext );\ntypedef BOOL ( WINAPI *CERTADDENCODEDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,\n\t\t\t\t\tDWORD dwCertEncodingType, const BYTE *pbCertEncoded, \n\t\t\t\t\tDWORD cbCertEncoded, DWORD dwAddDisposition, \n\t\t\t\t\tPCCERT_CONTEXT *ppCertContext );\ntypedef BOOL ( WINAPI *CERTCLOSESTORE )( HCERTSTORE hCertStore, DWORD dwFlags );\ntypedef PCCERT_CONTEXT ( WINAPI *CERTCREATECERTIFICATECONTEXT )( DWORD dwCertEncodingType,\n\t\t\t\t\tconst BYTE *pbCertEncoded, DWORD cbCertEncoded );\ntypedef BOOL ( WINAPI *CERTDELETECERTIFICATEFROMSTORE )( PCCERT_CONTEXT pCertContext );\ntypedef PCCERT_CONTEXT ( WINAPI *CERTFINDCERTIFICATEINSTORE )( HCERTSTORE hCertStore,\n\t\t\t\t\tDWORD dwCertEncodingType, DWORD dwFindFlags, \n\t\t\t\t\tDWORD dwFindType, const void *pvFindPara, \n\t\t\t\t\tPCCERT_CONTEXT pPrevCertContext );\ntypedef VOID ( WINAPI *CERTFREECERTIFICATECHAIN )( PCCERT_CHAIN_CONTEXT pChainContext );\ntypedef BOOL ( WINAPI *CERTFREECERTIFICATECONTEXT )( PCCERT_CONTEXT pCertContext );\ntypedef BOOL ( WINAPI *CERTGETCERTIFICATECHAIN )( HCERTCHAINENGINE hChainEngine,\n\t\t\t\t\tPCCERT_CONTEXT pCertContext, LPFILETIME pTime, \n\t\t\t\t\tHCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara,\n\t\t\t\t\tDWORD dwFlags, LPVOID pvReserved, \n\t\t\t\t\tPCCERT_CHAIN_CONTEXT *ppChainContext );\ntypedef BOOL ( WINAPI *CERTGETCERTIFICATECONTEXTPROPERTY )( PCCERT_CONTEXT pCertContext,\n\t\t\t\t\tDWORD dwPropId, void *pvData, DWORD *pcbData );\ntypedef PCCERT_CONTEXT ( WINAPI *CERTGETSUBJECTCERTIFICATEFROMSTORE )( HCERTSTORE hCertStore,\n\t\t\t\t\tDWORD dwCertEncodingType, PCERT_INFO pCertId );\ntypedef BOOL ( WINAPI *CERTSETCERTIFICATEPROPERTY )( PCCERT_CONTEXT pCertContext,\n\t\t\t\t\tDWORD dwPropId, DWORD dwFlags, const void *pvData );\ntypedef HCERTSTORE ( WINAPI *CERTOPENSYSTEMSTORE )( HCRYPTPROV hprov,\n\t\t\t\t\tLPCSTR szSubsystemProtocol );\n\ntypedef BOOL ( WINAPI *CRYPTACQUIRECERTIFICATEPRIVATEKEY )( PCCERT_CONTEXT pCert,\n\t\t\t\t\tDWORD dwFlags, void *pvReserved, HCRYPTPROV *phCryptProv, \n\t\t\t\t\tDWORD *pdwKeySpec, BOOL *pfCallerFreeProv );\ntypedef BOOL ( WINAPI *CRYPTACQUIRECONTEXTA )( HCRYPTPROV *phProv, LPCSTR pszContainer,\n\t\t\t\t\tLPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTCREATEHASH )( HCRYPTPROV hProv, ALG_ID Algid, \n\t\t\t\t\tHCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH* phHash );\ntypedef BOOL ( WINAPI *CRYPTDECRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,\n\t\t\t\t\tDWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );\ntypedef BOOL ( WINAPI *CRYPTDESTROYHASH )( HCRYPTHASH hHash );\ntypedef BOOL ( WINAPI *CRYPTDESTROYKEY )( HCRYPTKEY hKey );\ntypedef BOOL ( WINAPI *CRYPTENCRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,\n\t\t\t\t\tDWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen );\ntypedef BOOL ( WINAPI *CRYPTEXPORTKEY )( HCRYPTKEY hKey, HCRYPTKEY hExpKey,\n\t\t\t\t\tDWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );\ntypedef BOOL ( WINAPI *CRYPTFINDCERTIFICATEKEYPROVINFO )( PCCERT_CONTEXT pCert,\n\t\t\t\t\tDWORD dwFlags, void *pvReserved );\ntypedef BOOL ( WINAPI *CRYPTGENKEY )( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags,\n\t\t\t\t\tHCRYPTKEY *phKey );\ntypedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer );\ntypedef BOOL ( WINAPI *CRYPTGETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam, BYTE* pbData,\n\t\t\t\t\tDWORD* pdwDataLen, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTGETPROVPARAM )( HCRYPTPROV hProv, DWORD dwParam, \n\t\t\t\t\tBYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTGETUSERKEY )( HCRYPTPROV hProv, DWORD dwKeySpec, \n\t\t\t\t\tHCRYPTKEY* phUserKey );\ntypedef BOOL ( WINAPI *CRYPTHASHDATA )( HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen,\n\t\t\t\t\tDWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTIMPORTKEY )( HCRYPTPROV hProv, CONST BYTE *pbData,\n\t\t\t\t\tDWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey );\ntypedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTSETHASHPARAM )( HCRYPTHASH hHash, DWORD dwParam, \n\t\t\t\t\tBYTE* pbData, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTSETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam, \n\t\t\t\t\tBYTE *pbData, DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTSIGNHASH )( HCRYPTHASH hHash, DWORD dwKeySpec, \n\t\t\t\t\tLPCTSTR sDescription, DWORD dwFlags, BYTE* pbSignature, \n\t\t\t\t\tDWORD* pdwSigLen );\n\nstatic CERTADDCERTIFICATETOSTORE pCertAddCertificateContextToStore = NULL;\nstatic CERTADDENCODEDCERTIFICATETOSTORE pCertAddEncodedCertificateToStore = NULL;\nstatic CERTCREATECERTIFICATECONTEXT pCertCreateCertificateContext = NULL;\nstatic CERTDELETECERTIFICATEFROMSTORE pCertDeleteCertificateFromStore = NULL;\nstatic CERTCLOSESTORE pCertCloseStore = NULL;\nstatic CERTFINDCERTIFICATEINSTORE pCertFindCertificateInStore = NULL;\nstatic CERTFREECERTIFICATECHAIN pCertFreeCertificateChain = NULL;\nstatic CERTFREECERTIFICATECONTEXT pCertFreeCertificateContext = NULL;\nstatic CERTGETCERTIFICATECHAIN pCertGetCertificateChain = NULL;\nstatic CERTGETCERTIFICATECONTEXTPROPERTY pCertGetCertificateContextProperty = NULL;\nstatic CERTGETSUBJECTCERTIFICATEFROMSTORE pCertGetSubjectCertificateFromStore = NULL;\nstatic CERTSETCERTIFICATEPROPERTY pCertSetCertificateContextProperty = NULL;\nstatic CERTOPENSYSTEMSTORE pCertOpenSystemStore = NULL;\n\nstatic CRYPTACQUIRECERTIFICATEPRIVATEKEY pCryptAcquireCertificatePrivateKey = NULL;\nstatic CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL;\nstatic CRYPTCREATEHASH pCryptCreateHash = NULL;\nstatic CRYPTDECRYPT pCryptDecrypt = NULL;\nstatic CRYPTDESTROYHASH pCryptDestroyHash = NULL;\nstatic CRYPTDESTROYKEY pCryptDestroyKey = NULL;\nstatic CRYPTENCRYPT pCryptEncrypt = NULL;\nstatic CRYPTEXPORTKEY pCryptExportKey = NULL;\nstatic CRYPTFINDCERTIFICATEKEYPROVINFO pCryptFindCertificateKeyProvInfo = NULL;\nstatic CRYPTGENKEY pCryptGenKey = NULL;\nstatic CRYPTGENRANDOM pCryptGenRandom = NULL;\nstatic CRYPTGETKEYPARAM pCryptGetKeyParam = NULL;\nstatic CRYPTGETPROVPARAM pCryptGetProvParam = NULL;\nstatic CRYPTGETUSERKEY pCryptGetUserKey = NULL;\nstatic CRYPTHASHDATA pCryptHashData = NULL;\nstatic CRYPTIMPORTKEY pCryptImportKey = NULL;\nstatic CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;\nstatic CRYPTSETHASHPARAM pCryptSetHashParam = NULL;\nstatic CRYPTSETKEYPARAM pCryptSetKeyParam = NULL;\nstatic CRYPTSIGNHASH pCryptSignHash = NULL;\n\n/* Dynamically load and unload any necessary DBMS libraries */\n\nCHECK_RETVAL \\\nint deviceInitCryptoAPI( void )\n\t{\n\t/* If the CryptoAPI module is already linked in, don't do anything */\n\tif( hCryptoAPI != NULL_HINSTANCE )\n\t\treturn( CRYPT_OK );\n\n\t/* Obtain handles to the modules containing the CryptoAPI functions */\n\tif( ( hAdvAPI32 = GetModuleHandle( \"AdvAPI32.DLL\" ) ) == NULL || \\\n\t\t( hCryptoAPI = DynamicLoad( \"Crypt32.dll\" ) ) == NULL_HINSTANCE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't bind to CryptoAPI interface \"\n\t\t\t\t\t \"'AdvAPI32.DLL'/'Crypt32.dll'\" ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Get pointers to the crypt functions */\n\tpCryptAcquireCertificatePrivateKey = ( CRYPTACQUIRECERTIFICATEPRIVATEKEY ) GetProcAddress( hCryptoAPI, \"CryptAcquireCertificatePrivateKey\" );\n\tpCryptAcquireContextA = ( CRYPTACQUIRECONTEXTA ) GetProcAddress( hAdvAPI32, \"CryptAcquireContextA\" );\n\tpCryptCreateHash = ( CRYPTCREATEHASH ) GetProcAddress( hAdvAPI32, \"CryptCreateHash\" );\n\tpCryptDecrypt = ( CRYPTDECRYPT ) GetProcAddress( hAdvAPI32, \"CryptDecrypt\" );\n\tpCryptDestroyHash = ( CRYPTDESTROYHASH ) GetProcAddress( hAdvAPI32, \"CryptDestroyHash\" );\n\tpCryptDestroyKey = ( CRYPTDESTROYKEY ) GetProcAddress( hAdvAPI32, \"CryptDestroyKey\" );\n\tpCryptEncrypt = ( CRYPTENCRYPT ) GetProcAddress( hAdvAPI32, \"CryptEncrypt\" );\n\tpCryptExportKey = ( CRYPTEXPORTKEY ) GetProcAddress( hAdvAPI32, \"CryptExportKey\" );\n\tpCryptFindCertificateKeyProvInfo = ( CRYPTFINDCERTIFICATEKEYPROVINFO ) GetProcAddress( hCryptoAPI, \"CryptFindCertificateKeyProvInfo\" );\n\tpCryptGenKey = ( CRYPTGENKEY ) GetProcAddress( hAdvAPI32, \"CryptGenKey\" );\n\tpCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32, \"CryptGenRandom\" );\n\tpCryptGetKeyParam = ( CRYPTGETKEYPARAM ) GetProcAddress( hAdvAPI32, \"CryptGetKeyParam\" );\n\tpCryptGetProvParam = ( CRYPTGETPROVPARAM ) GetProcAddress( hAdvAPI32, \"CryptGetProvParam\" );\n\tpCryptGetUserKey = ( CRYPTGETUSERKEY ) GetProcAddress( hAdvAPI32, \"CryptGetUserKey\" );\n\tpCryptHashData = ( CRYPTHASHDATA ) GetProcAddress( hAdvAPI32, \"CryptHashData\" );\n\tpCryptImportKey = ( CRYPTIMPORTKEY ) GetProcAddress( hAdvAPI32, \"CryptImportKey\" );\n\tpCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32, \"CryptReleaseContext\" );\n\tpCryptSetHashParam = ( CRYPTSETHASHPARAM ) GetProcAddress( hAdvAPI32, \"CryptSetHashParam\" );\n\tpCryptSetKeyParam = ( CRYPTSETKEYPARAM ) GetProcAddress( hAdvAPI32, \"CryptSetKeyParam\" );\n\tpCryptSignHash = ( CRYPTSIGNHASH ) GetProcAddress( hAdvAPI32, \"CryptSignHashA\" );\n\n\t/* Get pointers to the certificate functions */\n\tpCertAddCertificateContextToStore = ( CERTADDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, \"CertAddCertificateContextToStore\" );\n\tpCertAddEncodedCertificateToStore = ( CERTADDENCODEDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, \"CertAddEncodedCertificateToStore\" );\n\tpCertCreateCertificateContext = ( CERTCREATECERTIFICATECONTEXT ) GetProcAddress( hCryptoAPI, \"CertCreateCertificateContext\" );\n\tpCertDeleteCertificateFromStore = ( CERTDELETECERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, \"CertDeleteCertificateFromStore\" );\n\tpCertCloseStore = ( CERTCLOSESTORE ) GetProcAddress( hCryptoAPI, \"CertCloseStore\" );\n\tpCertFindCertificateInStore = ( CERTFINDCERTIFICATEINSTORE ) GetProcAddress( hCryptoAPI, \"CertFindCertificateInStore\" );\n\tpCertFreeCertificateChain = ( CERTFREECERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, \"CertFreeCertificateChain\" );\n\tpCertFreeCertificateContext = ( CERTFREECERTIFICATECONTEXT )  GetProcAddress( hCryptoAPI, \"CertFreeCertificateContext\" );\n\tpCertGetCertificateChain = ( CERTGETCERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, \"CertGetCertificateChain\" );\n\tpCertGetCertificateContextProperty = ( CERTGETCERTIFICATECONTEXTPROPERTY ) GetProcAddress( hCryptoAPI, \"CertGetCertificateContextProperty\" );\n\tpCertGetSubjectCertificateFromStore = ( CERTGETSUBJECTCERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, \"CertGetSubjectCertificateFromStore\" );\n\tpCertSetCertificateContextProperty = ( CERTSETCERTIFICATEPROPERTY ) GetProcAddress( hCryptoAPI, \"CertSetCertificateContextProperty\" );\n\tpCertOpenSystemStore = ( CERTOPENSYSTEMSTORE ) GetProcAddress( hCryptoAPI, \"CertOpenSystemStoreA\" );\n\n\t/* Make sure that we got valid pointers for every CryptoAPI function */\n\tif( pCertAddCertificateContextToStore == NULL || \\\n\t\tpCertAddEncodedCertificateToStore == NULL || \n\t\tpCertCreateCertificateContext == NULL ||\n\t\tpCertDeleteCertificateFromStore == NULL ||\n\t\tpCertCloseStore == NULL || pCertFindCertificateInStore == NULL ||\n\t\tpCertFreeCertificateChain == NULL || \n\t\tpCertFreeCertificateContext == NULL || \n\t\tpCertGetCertificateChain == NULL ||\n\t\tpCertGetCertificateContextProperty  == NULL ||\n\t\tpCertGetSubjectCertificateFromStore == NULL || \n\t\tpCertSetCertificateContextProperty == NULL ||\n\t\tpCertOpenSystemStore == NULL || \n\t\tpCryptAcquireCertificatePrivateKey == NULL ||\n\t\tpCryptAcquireContextA == NULL || pCryptCreateHash == NULL || \n\t\tpCryptDecrypt == NULL || pCryptEncrypt == NULL || \n\t\tpCryptExportKey == NULL || pCryptDestroyHash == NULL || \n\t\tpCryptDestroyKey == NULL || \n\t\tpCryptFindCertificateKeyProvInfo == NULL || pCryptGenKey == NULL || \n\t\tpCryptGenRandom == NULL || pCryptGetKeyParam == NULL || \n\t\tpCryptGetProvParam == NULL || pCryptGetUserKey == NULL || \n\t\tpCryptHashData == NULL || pCryptImportKey == NULL || \n\t\tpCryptReleaseContext == NULL || pCryptSetHashParam == NULL || \n\t\tpCryptSetKeyParam == NULL || pCryptSignHash == NULL )\n\t\t{\n\t\t/* Free the library reference and reset the handle */\n\t\tDynamicUnload( hCryptoAPI );\n\t\thCryptoAPI = NULL_HINSTANCE;\n\t\tDEBUG_DIAG(( \"Couldn't bind to CryptoAPI driver functions\" ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid deviceEndCryptoAPI( void )\n\t{\n\tif( hCryptoAPI != NULL_HINSTANCE )\n\t\tDynamicUnload( hCryptoAPI );\n\thCryptoAPI = NULL_HINSTANCE;\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get access to the PKCS #11 device associated with a context */\n\nstatic int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t\t\t CRYPT_DEVICE *iCryptDevice, \n\t\t\t\t\t\t\t\t CRYPTOAPI_INFO **cryptoapiInfoPtrPtr )\n\t{\n\tCRYPT_DEVICE iLocalDevice;\n\tDEVICE_INFO *deviceInfo;\n\tint cryptStatus;\n\n\t/* Clear return values */\n\t*iCryptDevice = CRYPT_ERROR;\n\t*cryptoapiInfoPtrPtr = NULL;\n\n\t/* Get the the device associated with this context */\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t   &iLocalDevice, OBJECT_TYPE_DEVICE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Get the CryptoAPI information from the device information */\n\tcryptStatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE, \n\t\t\t\t\t\t\t\t\t ( MESSAGE_PTR_CAST ) &deviceInfo, \n\t\t\t\t\t\t\t\t\t CRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\t*iCryptDevice = iLocalDevice;\n\t*cryptoapiInfoPtrPtr = deviceInfo->deviceCryptoAPI;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Map a CryptoAPI-specific error to a cryptlib error */\n\nstatic int mapError( CRYPTOAPI_INFO *cryptoapiInfo, const int defaultError )\n\t{\n\tconst DWORD errorCode = GetLastError();\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &cryptoapiInfo->errorInfo;\n\tint messageLength, LOOP_ITERATOR;\n#endif /* USE_ERRMSGS */\n\n\t/* Get the error message for this error.  FormatMessage() adds EOL \n\t   terminators so we have to strip those before we pass the string back \n\t   to the caller.  There's an incredibly arcane way of telling \n\t   FormatMessage() to do this via escape codes passed in as part of a \n\t   va_arg argument list, but aside from being complex to set up this \n\t   also means that the function will try and insert information such as \n\t   filenames from the argument list when required (there's no way to \n\t   tell in advance which arguments are required), so this is more \n\t   trouble than it's worth */\n#ifdef USE_ERRMSGS\n\tFormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0,\n\t\t\t\t   errorInfo->errorString, MAX_ERRMSG_SIZE - 1, NULL );\n\tLOOP_LARGE( messageLength = strlen( errorInfo->errorString ),\n\t\t\t\tmessageLength > 0 && \\\n\t\t\t\t\t( errorInfo->errorString[ messageLength - 1 ] == '\\n' || \\\n\t\t\t\t\t  errorInfo->errorString[ messageLength - 1 ] == '\\r' ),\n\t\t\t\tmessageLength-- );\n\tENSURES( LOOP_BOUND_OK );\n\terrorInfo->errorStringLength = messageLength;\n#endif /* USE_ERRMSGS */\n\n\t/* Translate the CAPI error code into the cryptlib equivalent */\n\tswitch( errorCode )\n\t\t{\n\t\tcase CRYPT_E_UNKNOWN_ALGO:\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\tcase ERROR_BUSY:\n\t\t\treturn( CRYPT_ERROR_TIMEOUT );\n\n\t\tcase ERROR_MORE_DATA:\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\tcase ERROR_NO_MORE_ITEMS:\n\t\t\treturn( CRYPT_ERROR_COMPLETE );\n\n\t\tcase NTE_BAD_DATA:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\tcase CRYPT_E_EXISTS:\n\t\tcase NTE_EXISTS:\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t\tcase ERROR_NOT_ENOUGH_MEMORY:\n\t\tcase NTE_NO_MEMORY:\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t\tcase CRYPT_E_SECURITY_SETTINGS:\n\t\tcase NTE_PERM:\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\tcase NTE_BAD_SIGNATURE:\n\t\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\t\tcase CRYPT_E_NO_MATCH:\n\t\tcase CRYPT_E_NOT_FOUND:\n\t\tcase NTE_KEYSET_NOT_DEF:\n\t\tcase NTE_NOT_FOUND:\n\t\tcase NTE_PROV_DLL_NOT_FOUND:\n\t\tcase NTE_PROV_TYPE_NO_MATCH:\n\t\tcase NTE_PROV_TYPE_NOT_DEF:\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\treturn( defaultError );\n\t}\n\nstatic int mapDeviceError( CONTEXT_INFO *contextInfoPtr, const int defaultError )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tint status;\n\n\t/* Get the device associated with this context, set the error information\n\t   in it, and exit */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = mapError( cryptoapiInfo, defaultError );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\n/* Map cryptlib to/from CryptoAPI algorithm IDs */\n\nstatic const MAP_TABLE algoMapTbl[] = {\n\t/* PKC algorithms */\n\t{ CRYPT_ALGO_RSA, CALG_RSA_SIGN },\n\t{ CRYPT_ALGO_RSA, CALG_RSA_KEYX },\n\t{ CRYPT_ALGO_DSA, CALG_DSS_SIGN },\n\n\t/* Encryption algorithms */\n\t{ CRYPT_ALGO_DES, CALG_DES },\n\t{ CRYPT_ALGO_3DES, CALG_3DES },\n\t{ CRYPT_ALGO_RC2, CALG_RC2 },\n\t{ CRYPT_ALGO_RC4, CALG_RC4 },\n\n\t/* Hash algorithms */\n\t{ CRYPT_ALGO_MD5, CALG_MD5 },\n\t{ CRYPT_ALGO_SHA1, CALG_SHA },\n\n\t{ CRYPT_ALGO_NONE, 0 }, { CRYPT_ALGO_NONE, 0 }\n\t};\n\nstatic ALG_ID cryptlibToCapiID( const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tint value, status;\n\n\tstatus = mapValue( cryptAlgo, &value, algoMapTbl,\n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ) );\n\tENSURES_EXT( cryptStatusOK( status ), CALG_NONE );\n\t\n\treturn( value );\n\t}\n\nstatic CRYPT_ALGO_TYPE capiToCryptlibID( const ALG_ID algID )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tLOOP_MED( i = 0, algoMapTbl[ i ].source != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ), i++ )\n\t\t{\n\t\tif( ( ALG_ID ) algoMapTbl[ i ].destination == algID )\n\t\t\tbreak;\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, CRYPT_ALGO_NONE );\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ), \n\t\t\t\t CRYPT_ALGO_NONE );\n\tif( algoMapTbl[ i ].source == CRYPT_ALGO_NONE )\n\t\treturn( CRYPT_ALGO_NONE );\n\treturn( algoMapTbl[ i ].source );\n\t}\n\n/* Copy an MPI into the little-endian order required by CryptoAPI, returning\n   the end position of the copied MPI */\n\nstatic BYTE *copyMPI( BYTE *dest, const BYTE *src, const int srcLen,\n\t\t\t\t\t  const int srcRequiredLen )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tdest += srcLen - 1;\n\tLOOP_MAX( i = 0, i < srcLen, i++ )\n\t\t*dest-- = *src++;\n\tENSURES_N( LOOP_BOUND_OK );\n\tdest += srcLen + 1;\n\tif( srcLen < srcRequiredLen )\n\t\t{\n\t\t/* CryptoAPI blobs don't contain any length information but \n\t\t   implicitly specify all lengths in terms of the size of the\n\t\t   main MPI component, so if the actual length is less than the\n\t\t   assumed length we pad the remainder out with zeroes */\n\t\tLOOP_LARGE( i = 0, i < srcRequiredLen - srcLen, i++ )\n\t\t\t*dest++ = 0;\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\t}\n\t\n\treturn( dest );\n\t}\n\n/* Create the special-case RSA key with e=1 that's needed to allow direct \n   key import and export */\n\nstatic int createExportKey( const HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey, \n\t\t\t\t\t\t\tint *privateKeySize )\n\t{\n\tBLOBHEADER *blobHeaderPtr;\n\tRSAPUBKEY *pubKeyPtr;\n\tBYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;\n\tDWORD keyBlobLen = 1024;\n\tBOOL result;\n\tint bitLen16;\n\n\t/* Generate a private key and export it as a private key blob:\n\n\t\tOfs\tValue\n\n\t\t  0\tBLOBHEADER blobheader {\n\t\t\t  0\tBYTE bType;\n\t\t\t  1\tBYTE bVersion;\n\t\t\t  2 WORD reserved;\n\t\t\t  4\tALG_ID aiKeyAlg; }\n\t\t  8\tRSAPUBKEY rsapubkey {\n\t\t\t  8 DWORD magic;\n\t\t\t 12\tDWORD bitlen;\n\t\t\t 16\tDWORD pubexp; }\n\t\t 20\tBYTE modulus[ rsapubkey.bitlen / 8 ];\n\t\t\tBYTE prime1[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE prime2[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE exponent1[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE exponent2[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE coefficient[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE privateExponent[ rsapubkey.bitlen / 8 ]; */\n\tif( !pCryptGenKey( hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, hPrivateKey ) || \\\n\t\t!pCryptExportKey( *hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen ) || \\\n\t\t!pCryptDestroyKey( *hPrivateKey ) )\n\t\treturn( CRYPT_ERROR );\n\n\t/* Perform a general sanity check on the returned data */\n\tblobHeaderPtr = ( BLOBHEADER * ) keyBlob;\n\tif( blobHeaderPtr->bType != PRIVATEKEYBLOB || \\\n\t\tblobHeaderPtr->bVersion != CUR_BLOB_VERSION || \\\n\t\tblobHeaderPtr->aiKeyAlg != CALG_RSA_KEYX )\n\t\t{\n\t\tpCryptDestroyKey( *hPrivateKey );\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Set the public exponent to 1 (little-endian 32-bit value) and skip to \n\t   the private exponents */\n\tpubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );\n\tbitLen16 = ( pubKeyPtr->bitlen / 16 );\n\tpubKeyPtr->pubexp = 1;\n\tkeyBlobPtr = keyBlob + 20 + ( pubKeyPtr->bitlen / 8 ) + bitLen16 + bitLen16;\n\n\t/* Set the two exponents to 1 */\n\t*keyBlobPtr++ = 1;\n\tmemset( keyBlobPtr, 0, bitLen16 - 1 );\n\tkeyBlobPtr += bitLen16 - 1;\n\t*keyBlobPtr++ = 1;\n\tmemset( keyBlobPtr, 0, bitLen16 - 1 );\n\tkeyBlobPtr += bitLen16 - 1;\n\n\t/* Set the private exponent to 1 */\n\tkeyBlobPtr += bitLen16;\t\t/* Skip coefficient */\n\t*keyBlobPtr++ = 1;\n\tmemset( keyBlobPtr, 0, bitLen16 - 1 );\n\tkeyBlobPtr += bitLen16 - 1;\n\n\t/* Finally, re-import the hacked key and clean up */\n\tresult = pCryptImportKey( hProv, keyBlob, keyBlobLen, 0, 0, hPrivateKey );\n\tif( result )\n\t\t*privateKeySize = pubKeyPtr->bitlen / 8;\n\telse\n\t\t*hPrivateKey = 0;\n\tzeroise( keyBlob, keyBlobLen );\n\n\treturn( result ? CRYPT_OK : CRYPT_ERROR );\n\t}\n\n/* Import a raw session key using the exponent-one RSA key */\n\nstatic int importPlainKey( const HCRYPTPROV hProv, \n\t\t\t\t\t\t   const HCRYPTKEY hPrivateKey, \n\t\t\t\t\t\t   const int privateKeySize, HCRYPTKEY *hSessionKey, \n\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo, const BYTE *keyData, \n\t\t\t\t\t\t   const int keyDataSize, void *errorInfoPtr )\n\t{\n\tBLOBHEADER *blobHeaderPtr;\n\tBYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;\n\tALG_ID algID;\n\tDWORD *dwPtr;\n\tBOOL result;\n\tconst int blobSize = sizeof( BLOBHEADER ) + sizeof( ALG_ID ) + privateKeySize;\n\tint i, LOOP_ITERATOR;\n\n\t/* Set up a SIMPLEBLOB:\n\n\t\tOfs\tValue\n\t\t  0\tBLOBHEADER blobheader {\n\t\t\t  0\tBYTE bType;\n\t\t\t  1\tBYTE bVersion;\n\t\t\t  2 WORD reserved;\n\t\t\t  4\tALG_ID aiKeyAlg; }\n\t\t  8\tALG_ID algid;\n\t\t 12\tBYTE encryptedkey[ rsapubkey.bitlen/8 ]; */\n\tmemset( keyBlob, 0, 1024 );\n\talgID = cryptlibToCapiID( cryptAlgo );\n\tif( algID == 0 )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Set up the BLOBHEADER part of the blob */\n\tblobHeaderPtr = ( BLOBHEADER * ) keyBlob;\n    blobHeaderPtr->bType = SIMPLEBLOB;\n\tblobHeaderPtr->bVersion = CUR_BLOB_VERSION;\n\tblobHeaderPtr->aiKeyAlg = algID;\n\n\t/* Set up the private-key algorithm ID */\n\tdwPtr = ( DWORD * )( keyBlob + BLOBHEADER_SIZE );\n\t*dwPtr = CALG_RSA_KEYX;\n\n\t/* Store the key as byte-reversed PKCS #1 padded data (or at least close \n\t   enough to it to work for the import) */\n\tkeyBlobPtr = keyBlob + 12;\n\tLOOP_LARGE( i = keyDataSize - 1, i >= 0, i-- )\n\t\t*keyBlobPtr++ = keyData[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\t*keyBlobPtr++ = 0;\n\tmemset( keyBlobPtr, 2, privateKeySize - ( keyDataSize + 2 ) );\n\n\t/* Import the key from the faked PKCS #1 wrapped form */\n\tresult = pCryptImportKey( hProv, keyBlob, blobSize, hPrivateKey, 0, hSessionKey );\n\tzeroise( keyBlob, blobSize );\n\tif( !result )\n\t\treturn( mapDeviceError( errorInfoPtr, CRYPT_ERROR_FAILED ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Load a CryptoAPI public key into a cryptlib native context */\n\nstatic int getPubkeyComponents( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t\t\tconst HCRYPTKEY hKey, BYTE *n, int *nLen, \n\t\t\t\t\t\t\t\tBYTE *e, int *eLen )\n\t{\n\tBLOBHEADER *blobHeaderPtr;\n\tRSAPUBKEY *pubKeyPtr;\n\tBYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ], *nPtr;\n\tBYTE buffer[ 16 + 8 ], *bufPtr = buffer;\n\tDWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;\n\tint exponent, length;\n\n\t/* Clear return values */\n\tmemset( n, 0, 8 );\n\tmemset( e, 0, 8 );\n\t*nLen = *eLen = 0;\n\n\t/* Get the public key components */\n\tif( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );\n\n\t/* Perform a general sanity check on the returned data */\n\tblobHeaderPtr = ( BLOBHEADER * ) keyBlob;\n\tif( blobHeaderPtr->bType != PUBLICKEYBLOB || \\\n\t\tblobHeaderPtr->bVersion != CUR_BLOB_VERSION )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* Extract the public key components */\n\tpubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );\n\texponent = pubKeyPtr->pubexp;\n\tnPtr = keyBlob + 20;\n\tlength = pubKeyPtr->bitlen / 8;\n\twhile( length > 0 && nPtr[ length ] == 0 )\n\t\tlength--;\n\tcopyMPI( n, nPtr, length, length );\n\t*nLen = length;\n\tlength = ( exponent <= 0xFF ) ? 1 : \\\n\t\t\t ( exponent <= 0xFFFF ) ? 2 : \\\n\t\t\t ( exponent <= 0xFFFFFFL ) ? 3 : 4;\n\tmputLong( bufPtr, exponent );\n\tmemcpy( e, buffer + ( 4 - length ), length );\n\t*eLen = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int capiToCryptlibContext( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t\t\t  const HCRYPTKEY hKey, \n\t\t\t\t\t\t\t\t  CRYPT_CONTEXT *cryptContextPtr )\n\t{\n\tCRYPT_PKCINFO_RSA rsaKey;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint nLen, eLen, status;\n\n\t/* Clear return value */\n\t*cryptContextPtr = CRYPT_ERROR;\n\n\t/* Extract the public-key components from the CryptoAPI context */\n\tstatus = getPubkeyComponents( cryptoapiInfo, hKey, n, &nLen, e, &eLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy the public-key components into the cryptlib format */\n\tcryptInitComponents( &rsaKey, CRYPT_KEYTYPE_PUBLIC );\n\tcryptSetComponent( ( &rsaKey )->n, n, bytesToBits( nLen ) );\n\tcryptSetComponent( ( &rsaKey )->e, e, bytesToBits( eLen ) );\n\tzeroise( n, CRYPT_MAX_PKCSIZE );\n\tzeroise( e, CRYPT_MAX_PKCSIZE );\n\n\t/* Create the RSA context */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyComponents( &rsaKey );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the key into the context */\n\tsetMessageData( &msgData, \"CryptoAPI RSA key\", 17 );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, &rsaKey, sizeof( CRYPT_PKCINFO_RSA ) );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS );\n\t\t}\n\tcryptDestroyComponents( &rsaKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed to load CryptoAPI public key data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t*cryptContextPtr = createInfo.cryptHandle;\n\treturn( CRYPT_OK );\n\t}\n\n/* Compare a CryptoAPI private key with a certificate to check whether the\n   certificate corresponds to the key */\n\nstatic BOOLEAN isCertKey( const CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t  const HCRYPTKEY hKey, \n\t\t\t\t\t\t  const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\treturn( TRUE );\n\t}\n\n/* Get a certificate using a key/certificate identifier */\n\nstatic int getCertificate( const CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t   const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t   const void *keyID, const int keyIDlength,\n\t\t\t\t\t\t   PCCERT_CONTEXT *pCertContextPtr )\n\t{\n\tPCCERT_CONTEXT pCertContext = NULL;\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_NAME:\n\t\t\t{\n\t\t\tCERT_RDN certRDN;\n\t\t\tCERT_RDN_ATTR certRDNAttr;\n\n\t\t\t/* Find a certificate by CN */\n\t\t\tmemset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );\n\t\t\tcertRDNAttr.pszObjId = szOID_COMMON_NAME;\n\t\t\tcertRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;\n\t\t\tcertRDNAttr.Value.pbData = ( void * ) keyID;\n\t\t\tcertRDNAttr.Value.cbData = keyIDlength;\n\t\t\tmemset( &certRDN, 0, sizeof( CERT_RDN ) );\n\t\t\tcertRDN.rgRDNAttr = &certRDNAttr;\n\t\t\tcertRDN.cRDNAttr = 1;\n\t\t\tpCertContext = \\\n\t\t\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,\n\t\t\t\t\t\t\t&certRDN, NULL );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_KEYID_URI:\n\t\t\t{\n\t\t\tCERT_RDN certRDN;\n\t\t\tCERT_RDN_ATTR certRDNAttr;\n\n\t\t\t/* There doesn't appear to be any way to locate a certificate \n\t\t\t   using the email address in an altName, so we have to restrict \n\t\t\t   ourselves to the most commonly-used OID for certificates in \n\t\t\t   DNs */\n\t\t\tmemset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );\n\t\t\tcertRDNAttr.pszObjId = szOID_RSA_emailAddr ;\n\t\t\tcertRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;\n\t\t\tcertRDNAttr.Value.pbData = ( void * ) keyID;\n\t\t\tcertRDNAttr.Value.cbData = keyIDlength;\n\t\t\tmemset( &certRDN, 0, sizeof( CERT_RDN ) );\n\t\t\tcertRDN.rgRDNAttr = &certRDNAttr;\n\t\t\tcertRDN.cRDNAttr = 1;\n\t\t\tpCertContext = \\\n\t\t\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,\n\t\t\t\t\t\t\t&certRDN, NULL );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_IKEYID_CERTID:\n\t\t\t{\n\t\t\tCRYPT_DATA_BLOB cryptDataBlob;\n\n\t\t\tmemset( &cryptDataBlob, 0, sizeof( CRYPT_DATA_BLOB ) );\n\t\t\tcryptDataBlob.pbData = ( void * ) keyID;\n\t\t\tcryptDataBlob.cbData = keyIDlength;\n\t\t\tpCertContext = \\\n\t\t\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH,\n\t\t\t\t\t\t\t&cryptDataBlob, NULL );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\t{\n#if 0\n\t\t\tCERT_ID certID;\n\n\t\t\tcertID.dwIdChoice = CERT_ID_KEY_IDENTIFIER;\n\t\t\tcertID.KeyId.pbData = ( void * ) keyID;\n\t\t\tcertID.KeyId.cbData = keyIDlength;\n\t\t\tpCertContext = \\\n\t\t\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_CERT_ID,\n\t\t\t\t\t\t\t&certID, NULL );\n#else\n\t\t\tCRYPT_HASH_BLOB hashBlob;\n\n\t\t\thashBlob.pbData = ( void * ) keyID;\n\t\t\thashBlob.cbData = keyIDlength;\n\t\t\tpCertContext = \\\n\t\t\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER,\n\t\t\t\t\t\t\t&hashBlob, NULL );\n#endif /* 0 */\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_IKEYID_ISSUERANDSERIALNUMBER:\n\t\t\t{\n\t\t\tCERT_INFO certInfo;\n\t\t\tSTREAM stream;\n\t\t\tvoid *dataPtr DUMMY_INIT_PTR;\n\t\t\tint length DUMMY_INIT, status;\n\n\t\t\tmemset( &certInfo, 0, sizeof( CERT_INFO ) );\n\t\t\tsMemConnect( &stream, keyID, keyIDlength );\n\t\t\tstatus = readSequence( &stream, NULL );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = getStreamObjectLength( &stream, &length );\n\t\t\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tcertInfo.Issuer.pbData = dataPtr;\t\t/* Issuer DN */\n\t\t\tcertInfo.Issuer.cbData = length;\n\t\t\tstatus = sSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = getStreamObjectLength( &stream, &length );\n\t\t\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcertInfo.SerialNumber.pbData = dataPtr;\t/* Serial number */\n\t\t\tcertInfo.SerialNumber.cbData = length;\n\t\t\tstatus = sSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\t\t\tassert( sStatusOK( &stream ) );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tpCertContext = \\\n\t\t\t\tpCertGetSubjectCertificateFromStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, &certInfo );\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\tif( pCertContext == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t*pCertContextPtr = pCertContext;\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a certificate chain from a leaf certificate */\n\nstatic int getCertificateChain( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t\t\tconst PCCERT_CONTEXT pCertContext,\n\t\t\t\t\t\t\t\tPCCERT_CHAIN_CONTEXT *pChainContextPtr )\n\t{\n\tCERT_CHAIN_PARA chainPara;\n\tCERT_USAGE_MATCH certUsage;\n\tCERT_ENHKEY_USAGE enhkeyUsage;\n\tPCCERT_CHAIN_CONTEXT pChainContext;\n\n\t/* Clear return value */\n\t*pChainContextPtr = NULL;\n\n\t/* Get the chain from the supplied certificate up to a root \n\t   certificate */\n\tmemset( &enhkeyUsage, 0, sizeof( CERT_ENHKEY_USAGE ) );\n\tenhkeyUsage.cUsageIdentifier = 0;\n\tenhkeyUsage.rgpszUsageIdentifier = NULL;\n\tmemset( &certUsage, 0, sizeof( CERT_USAGE_MATCH ) );\n\tcertUsage.dwType = USAGE_MATCH_TYPE_AND;\n\tcertUsage.Usage = enhkeyUsage;\n\tmemset( &chainPara, 0, sizeof( CERT_CHAIN_PARA ) );\n\tchainPara.cbSize = sizeof( CERT_CHAIN_PARA );\n\tchainPara.RequestedUsage = certUsage;\n\tif( !pCertGetCertificateChain( NULL, pCertContext, NULL, NULL, &chainPara,\n\t\t\t\t\t\t\t\t   CERT_CHAIN_CACHE_END_CERT | \\\n\t\t\t\t\t\t\t\t   CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY, \n\t\t\t\t\t\t\t\t   NULL, &pChainContext ) )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\t*pChainContextPtr = pChainContext;\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a certificate from a public/private key and vice versa */\n\nstatic int getCertificateFromKey( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t\t\t  const HCRYPTKEY hKey,\n\t\t\t\t\t\t\t\t  const BOOLEAN isSigningKey,\n\t\t\t\t\t\t\t\t  PCCERT_CONTEXT *pCertContextPtr )\n\t{\n\tPCCERT_CONTEXT pCertContext;\n\tCERT_PUBLIC_KEY_INFO pubKeyInfo;\n\tBYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ];\n\tDWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;\n\n\t/* Clear return value */\n\t*pCertContextPtr = NULL;\n\n\t/* Extract the public-key components from the public or private key */\n\tif( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )\n\t\t{\n\t\tpCryptDestroyKey( hKey );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* Get the certificate for the context's public key */\n\tmemset( &pubKeyInfo, 0, sizeof( CERT_PUBLIC_KEY_INFO ) );\n\tpubKeyInfo.Algorithm.pszObjId = isSigningKey ? \\\n\t\t\t\t\t\t\t\t\tCERT_DEFAULT_OID_PUBLIC_KEY_SIGN : \\\n\t\t\t\t\t\t\t\t\tCERT_DEFAULT_OID_PUBLIC_KEY_XCHG;\n\tpubKeyInfo.PublicKey.pbData = keyBlob;\n\tpubKeyInfo.PublicKey.cbData = keyBlobLen;\n\tpCertContext = \\\n\t\tpCertFindCertificateInStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\tX509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY,\n\t\t\t\t\t\t&pubKeyInfo, NULL );\n\tif( pCertContext == NULL )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\t*pCertContextPtr = pCertContext;\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\n\nstatic int getPrivKeyFromCertificate( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t\t\t\t  const PCCERT_CONTEXT pCertContext,\n\t\t\t\t\t\t\t\t\t  HCRYPTKEY *hKeyPtr )\n\t{\n\tHCRYPTPROV hProv;\n\tHCRYPTKEY hKey;\n\tDWORD dwKeySpec;\n\tBOOL fCallerFreeProv;\n\n\t/* Clear return value */\n\t*hKeyPtr = 0;\n\n\t/* Get the provider and key-type from the certificate and use that to \n\t   get the key */\n\tif( !pCryptAcquireCertificatePrivateKey( pCertContext, \n\t\t\t\t\t\t\t\t\tCRYPT_ACQUIRE_CACHE_FLAG, NULL,\n\t\t\t\t\t\t\t\t\t&hProv, &dwKeySpec, &fCallerFreeProv ) )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\tif( !pCryptGetUserKey( hProv, dwKeySpec, &hKey ) )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\t*hKeyPtr = hKey;\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/* Create a private-key context using a CryptoAPI native key */\n\nstatic int createPrivkeyContext( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t\t CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t\t\t\t const HCRYPTKEY hKey,\n\t\t\t\t\t\t\t\t const char *label )\n\t{\n\tALG_ID algID;\n\tDWORD dwDataLen = sizeof( ALG_ID );\n\tconst CAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t\t\tDATAPTR_GET( deviceInfo->capabilityInfoList );\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tREQUIRES( capabilityInfoListPtr != NULL );\n\n\t/* Clear return values */\n\t*iCryptContext = CRYPT_ERROR;\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\n\t/* Get the algorithm type and look up the corresponding capability \n\t   information */\n\tif( !pCryptGetKeyParam( hKey, KP_ALGID, ( BYTE * ) &algID, &dwDataLen, \n\t\t\t\t\t\t\t0 ) || \\\n\t\t( *cryptAlgo = capiToCryptlibID( algID ) ) == CRYPT_ALGO_NONE )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tcapabilityInfoPtr = findCapabilityInfo( capabilityInfoListPtr, \n\t\t\t\t\t\t\t\t\t\t\t*cryptAlgo );\n\tif( capabilityInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Create a dummy context for the key, remember the device it's \n\t   contained in, the object's label, and the handle for the device-\n\t   internal key, and mark it as initialised (i.e. with a key loaded) */\n\tstatus = createContextFromCapability( iCryptContext, \n\t\t\t\t\t\t\t\tdeviceInfo->ownerHandle, capabilityInfoPtr, \n\t\t\t\t\t\t\t\tCREATEOBJECT_FLAG_DUMMY | \\\n\t\t\t\t\t\t\t\tCREATEOBJECT_FLAG_PERSISTENT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tkrnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );\n\tkrnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &hKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) label, \n\t\t\t\t\tmin( strlen( label ), CRYPT_MAX_TEXTSIZE ) );\n#if 0\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t/* Send the keying information to the context.  This is only \n\t\t   possible for RSA keys since it's not possible to read y from a \n\t\t   DSA private key object (see the comments in the DSA code for more \n\t\t   on this), however the only time this is necessary is when a \n\t\t   certificate is being generated for a key that was pre-generated \n\t\t   in the device by someone else, which is typically done in Europe \n\t\t   where DSA isn't used so this shouldn't be a problem */\n\t\t// Use getPubkeyComponents()\n\t\tcryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext, \n\t\t\t\t\t\t\t\t\t\t\t  hObject );\n\telse\n\t\tcryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t   &keySize, CRYPT_IATTRIBUTE_KEYSIZE );\n#endif\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t   MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_INITIALISED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDevice Init/Shutdown/Device Control Routines\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions to get and free device capability information */\n\nstatic int getCapabilities( DEVICE_INFO *deviceInfo );\nstatic void freeCapabilities( DEVICE_INFO *deviceInfo );\n\n/* Close a previously-opened session with the device.  We have to have this\n   before the initialisation function since it may be called by it if the \n   initialisation process fails */\n\nstatic void shutdownFunction( DEVICE_INFO *deviceInfo )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\n\t/* Log out and close the session with the device */\n\tif( TEST_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN ) )\n\t\t{\n\t\tif( cryptoapiInfo->hPrivateKey )\n\t\t\tpCryptDestroyKey( cryptoapiInfo->hPrivateKey );\n\t\tpCryptReleaseContext( cryptoapiInfo->hProv, 0 );\n\t\t}\n\tif( cryptoapiInfo->hCertStore != NULL )\n\t\t{\n\t\tpCertCloseStore( cryptoapiInfo->hCertStore, 0 );\n\t\tcryptoapiInfo->hCertStore = 0;\n\t\t}\n\tcryptoapiInfo->hProv = HCRYPTPROV_NONE;\n\tCLEAR_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE | \\\n\t\t\t\t\t\t\t\t   DEVICE_FLAG_LOGGEDIN );\n\n\t/* Free the device capability information */\n\tfreeCapabilities( deviceInfo );\n\t}\n\n/* Open a session with the device */\n\nstatic int initFunction( DEVICE_INFO *deviceInfo, const char *name,\n\t\t\t\t\t\t const int nameLength )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\tHCRYPTPROV hProv;\n\tHCERTSTORE hCertStore;\n\tchar providerNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\tchar keysetNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\tconst char *keysetName = NULL;\n\tDWORD value;\n\tint i, driverNameLength = nameLength, status, LOOP_ITERATOR;\n\n\t/* Check whether a keyset name has been specified */\n\tstrlcpy_s( keysetNameBuffer, CRYPT_MAX_TEXTSIZE, \"MY\" );/* Default keyset */\n\tLOOP_LARGE( i = 1, i < nameLength - 1, i++ )\n\t\t{\n\t\tif( name[ i ] == ':' && name[ i + 1 ] == ':' )\n\t\t\t{\n\t\t\tconst int keysetNameLength = nameLength - ( i + 2 );\n\n\t\t\tif( i > CRYPT_MAX_TEXTSIZE || keysetNameLength <= 0 || \\\n\t\t\t\tkeysetNameLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\t\t/* We've got a keyset name appended to the provider name, break \n\t\t\t   out the provider and keyset names */\n\t\t\tmemcpy( providerNameBuffer, name, i );\n\t\t\tproviderNameBuffer[ i ] = '\\0';\n\t\t\tmemcpy( keysetNameBuffer, name + i + 2, keysetNameLength );\n\t\t\tkeysetNameBuffer[ keysetNameLength ] = '\\0';\n\t\t\tname = providerNameBuffer;\n\t\t\tkeysetName = keysetNameBuffer;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we're auto-detecting the device, try various choices */\n\tif( driverNameLength == 12 && \\\n\t\t!strnicmp( \"[Autodetect]\", name, driverNameLength ) )\n\t\t{\n\t\tif( CryptAcquireContextA( &hProv, keysetName, MS_ENHANCED_PROV, \n\t\t\t\t\t\t\t\t  PROV_RSA_FULL, 0 ) )\n\t\t\tcryptoapiInfo->hProv = hProv;\n\t\telse\n\t\t\t{\n\t\t\tif( CryptAcquireContextA( &hProv, keysetName, MS_DEF_PROV, \n\t\t\t\t\t\t\t\t\t  PROV_RSA_FULL, 0 ) )\n\t\t\t\tcryptoapiInfo->hProv = hProv;\n\t\t\telse\n\t\t\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Try and find a specific provider */\n\t\tif( CryptAcquireContextA( &hProv, keysetName, name, PROV_RSA_FULL, 0 ) )\n\t\t\tcryptoapiInfo->hProv = hProv;\n\t\t}\n\n\t/* Get information on device-specific capabilities */\n\tvalue = CRYPT_MAX_TEXTSIZE + 1;\n\tif( !CryptGetProvParam( cryptoapiInfo->hProv, PP_NAME, \n\t\t\t\t\t\t\tcryptoapiInfo->labelBuffer, &value, 0 ) )\n\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\tdeviceInfo->label = cryptoapiInfo->labelBuffer;\n\tdeviceInfo->labelLen = value;\n\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE );\n\n\t/* Set up the capability information for this device */\n\tstatus = getCapabilities( deviceInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( ( status == CRYPT_ERROR ) ? CRYPT_ERROR_OPEN : status );\n\t\t}\n\n\t/* Create the special-purpose key needed to allow symmetric key loads */\n\tstatus = createExportKey( cryptoapiInfo->hProv, \n\t\t\t\t\t\t\t  &cryptoapiInfo->hPrivateKey, \n\t\t\t\t\t\t\t  &cryptoapiInfo->privateKeySize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* Open the certificate store used to store/retrieve certificates */\n\thCertStore = pCertOpenSystemStore( cryptoapiInfo->hProv, \n\t\t\t\t\t\t\t\t\t   keysetNameBuffer );\n\tif( hCertStore == NULL )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\tcryptoapiInfo->hCertStore = hCertStore;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Handle device control functions */\n\nstatic int controlFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\tconst void *data, const int dataLength,\n\t\t\t\t\t\t\tMESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tMisc.Device Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get random data from the device */\n\nstatic int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,\n\t\t\t\t\t\t\t  const int length,\n\t\t\t\t\t\t\t  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\n\tif( pCryptGenRandom( cryptoapiInfo->hProv, length, buffer ) )\n\t\treturn( CRYPT_OK );\n\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );\n\t}\n\n/* Instantiate an object in a device.  This works like the create context\n   function but instantiates a cryptlib object using data already contained\n   in the device (for example a stored private key or certificate).  If the\n   value being read is a public key and there's a certificate attached, the\n   instantiated object is a native cryptlib object rather than a device\n   object with a native certificate object attached because there doesn't \n   appear to be any good reason to create the public-key object in the \n   device.\n\n   CryptoAPI doesn't have any concept of multiple private keys, only a \n   default encryption + signature key for the provider as a whole, and an \n   optional additional signature key to complement the encryption (and \n   signature if necessary) one.  In addition the ties between a private key \n   and its associated certificate(s) are rather tenuous, requiring jumping \n   through several levels of indirection in order to get from one to the \n   other.  To handle this, we have to use a meet-in-the-middle approach \n   where we try to go from private key to certificate if the identity of the \n   private key is obvious (the user has specifically asked for a private \n   decryption or signature key), or from certificate to private key in all \n   other cases */\n\nstatic int getItemFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tCRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tconst void *keyID, const int keyIDlength,\n\t\t\t\t\t\t\tvoid *auxInfo, int *auxInfoLength, \n\t\t\t\t\t\t\tconst int flags )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n//\tCRYPT_CERTIFICATE iCryptCert;\n\tHCRYPTKEY hKey = 0;\n\tPCCERT_CONTEXT pCertContext = NULL;\n\tPCCERT_CHAIN_CONTEXT pChainContext = NULL;\n\tDWORD dwKeySpec = 0;\n\tCRYPT_CERTIFICATE iCryptCert;\n\tCRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;\n\tconst char *label = \"Private key\";\n\tint status;\n\n\tassert( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\titemType == KEYMGMT_ITEM_PRIVATEKEY );\n\n\t/* If we're searching for the key by label and the user has specified \n\t   one of the special-case key descriptions, get the appropriate key */\n\tif( keyIDtype == CRYPT_KEYID_NAME )\n\t\t{\n\t\tif( keyIDlength == 13 && \\\n\t\t\t!memcmp( keyID, \"Signature key\", 13 ) )\n\t\t\tdwKeySpec = AT_SIGNATURE;\n\t\telse\n\t\t\tif( keyIDlength == 14 && \\\n\t\t\t\t!memcmp( keyID, \"Encryption key\", 14 ) )\n\t\t\t\tdwKeySpec = AT_KEYEXCHANGE;\n\t\t}\n\n\t/* If we haven't got a key type from the label and we're looking for a \n\t   particular usage, get the appropriate key */\n\tif( dwKeySpec == 0 && itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\tif( flags & KEYMGMT_FLAG_USAGE_SIGN ) \n\t\t\tdwKeySpec = AT_SIGNATURE;\n\t\telse\n\t\t\tif( flags & KEYMGMT_FLAG_USAGE_CRYPT ) \n\t\t\t\tdwKeySpec = AT_KEYEXCHANGE;\n\t\t}\n\n\t/* If we still haven't got a key type, try and get the certificate for\n\t   the given ID */\n\tif( dwKeySpec != 0 )\n\t\t{\n\t\t/* Get the required key type */\n\t\tif( !pCryptGetUserKey( cryptoapiInfo->hProv, dwKeySpec, &hKey ) )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\tlabel = ( dwKeySpec == AT_SIGNATURE ) ? \\\n\t\t\t\t\"Signature key\" : \"Encryption key\";\n\n\t\t/* If we're only doing a presence check, we don't need the key and \n\t\t   can exit */\n\t\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\t\t{\n\t\t\tpCryptDestroyKey( hKey ); \n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Since CryptoAPI doesn't have any concept of key labels, the best \n\t\t   that we can do is provide a generic description of the intended \n\t\t   key usage as a form of pseudo-label */\n\t\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t\t{\n\t\t\tstrlcpy_s( auxInfo, *auxInfoLength, label );\n\t\t\t*auxInfoLength = strlen( label );\n\t\t\tpCryptDestroyKey( hKey ); \n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* We've got the key, try and get the associated certificate */\n\t\tstatus = getCertificateFromKey( cryptoapiInfo, hKey, \n\t\t\t\t\t\t\t\t\t\t( flags & KEYMGMT_FLAG_USAGE_SIGN ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tTRUE : FALSE, &pCertContext );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY ) \n\t\t\t{\n\t\t\t/* We couldn't get a certificate for the key, if we're after a \n\t\t\t   public key return it as a native context */\n\t\t\tstatus = capiToCryptlibContext( cryptoapiInfo, hKey, \n\t\t\t\t\t\t\t\t\t\t\tiCryptContext );\n\t\t\tpCryptDestroyKey( hKey ); \n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tassert( !( flags & KEYMGMT_FLAG_LABEL_ONLY ) );\n\n\t\t/* We don't have a definite private key ID indicator, go via the\n\t\t   certificate instead */\n\t\tstatus = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t\t\t &pCertContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If we're only doing a presence check, we don't need the key and \n\t\t   can exit */\n\t\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\t\t{\n\t\t\tpCertFreeCertificateContext( pCertContext );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* If we're after a private key, try and find the one corresponding\n\t\t   to the certificate */\n\t\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t\t{\n#if 1\n\t\t\tCERT_KEY_CONTEXT certKeyContext;\n\t\t\tDWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );\n\n\t\t\tif( !pCertGetCertificateContextProperty( pCertContext, \n\t\t\t\t\t\t\t\t\tCERT_KEY_CONTEXT_PROP_ID,\n\t\t\t\t\t\t\t\t\t&certKeyContext, &certKeyContextSize ) || \\\n\t\t\t\t!pCryptGetUserKey( certKeyContext.hCryptProv, \n\t\t\t\t\t\t\t\t   certKeyContext.dwKeySpec, &hKey ) )\n\t\t\t\treturn( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );\n\n#else\t\t/* Need to uncomment gPKFC() above */\n\t\t\tstatus = getPrivKeyFromCertificate( cryptoapiInfo, pCertContext, \n\t\t\t\t\t\t\t\t\t\t\t\t&hKey );\n#endif\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tpCertFreeCertificateContext( pCertContext );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If we've got a priavte key, create a device context for it */\n\tif( hKey != 0 )\n\t\t{\n\t\tstatus = createPrivkeyContext( deviceInfo, iCryptContext, \n\t\t\t\t\t\t\t\t\t   &cryptAlgo, hKey, label );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( pCertContext != NULL )\n\t\t\t\tpCertFreeCertificateContext( pCertContext );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* If there's no certificate available for the key, we're done */\n\tif( pCertContext == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* We've got a key and certificate, try and get the rest of the chain \n\t   for the certificate */\n{\nBOOLEAN publicComponentsOnly = FALSE;\n\n\tstatus = iCryptImportCertIndirect( &iCryptCert,\n\t\t\t\t\t\t\t\tdeviceInfo->objectHandle, keyIDtype, keyID,\n\t\t\t\t\t\t\t\tkeyIDlength, publicComponentsOnly ? \\\n\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_NONE : \\\n\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT );\n}\n\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* If we're getting a public key, the returned information is the \n\t\t   certificate chain */\n\t\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t*iCryptContext = iCryptCert;\n\t\telse\n\t\t\t{\n\t\t\t/* If we're getting a private key, attach the certificate chain \n\t\t\t   to the context.  The certificate is an internal object used \n\t\t\t   only by the context so we tell the kernel to mark it as owned \n\t\t\t   by the context only */\n\t\t\tstatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t\t   &iCryptCert, SETDEP_OPTION_NOINCREF );\n\t\t\t}\n\t\t}\n\t\n\t/* Clean up */\n\tpCertFreeCertificateContext( pCertContext );\n\tpCertFreeCertificateChain( pChainContext );\n\treturn( status );\n\n#if 0\n\t\t{\n\t\tconst int keyTemplateCount = ( keyID == NULL ) ? 1 : 2;\n\n\t\t/* Try and find the object with the given label/ID, or the first \n\t\t   object of the given class if no ID is given */\n\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) \\\n\t\t\t\t\t\t\t\t  ( ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t  &pubkeyClass : &privkeyClass );\n\t\tif( keyIDtype != CRYPT_KEYID_NONE )\n\t\t\t{\n\t\t\tif( keyIDtype == CRYPT_IKEYID_KEYID )\n\t\t\t\tkeyTemplate[ 1 ].type = CKA_ID;\n\t\t\tkeyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;\n\t\t\tkeyTemplate[ 1 ].ulValueLen = keyIDlength;\n\t\t\t}\n\t\tcryptStatus = findObject( deviceInfo, &hObject, keyTemplate, \n\t\t\t\t\t\t\t\t  keyTemplateCount );\n\t\tif( cryptStatus == CRYPT_ERROR_NOTFOUND && \\\n\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t{\n\t\t\t/* Some devices may only contain private key objects with \n\t\t\t   associated certificates that can't be picked out of the other \n\t\t\t   cruft that's present without going via the private key, so if \n\t\t\t   we're looking for a public key and don't find one, we try \n\t\t\t   again for a private key whose sole function is to point to an \n\t\t\t   associated certificate */\n\t\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;\n\t\t\tcryptStatus = findObject( deviceInfo, &hObject, keyTemplate, \n\t\t\t\t\t\t\t\t\t  keyTemplateCount );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\n\t\t\t/* Remember that although we've got a private key object, we only \n\t\t\t   need it to find the associated certificate and not finding an \n\t\t\t   associated certificate is an error */\n\t\t\tcertViaPrivateKey = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* If we're looking for any kind of private key and we either have an\n\t   explicit certificate ID but couldn't find a certificate for it or we \n\t   don't have a proper ID to search on and a generic search found more \n\t   than one matching object, chances are we're after a generic decrypt \n\t   key.  The former only occurs in misconfigured or limited-memory \n\t   tokens, the latter only in rare tokens that store more than one \n\t   private key, typically one for signing and one for verification.  \n\t   \n\t   If either of these cases occur we try again looking specifically for \n\t   a decryption key.  Even this doesn't always work, there's are some\n\t   >1-key tokens that mark a signing key as a decryption key so we still \n\t   get a CRYPT_ERROR_DUPLICATE error.\n\t   \n\t   Finally, if we can't find a decryption key either, we look for an\n\t   unwrapping key.  This may or may not work, depending on whether we \n\t   have a decryption key marked as valid for unwrapping but not \n\t   decryption, or a key that's genuinely only valid for unwrapping, but\n\t   at this point we're ready to try anything */\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \\\n\t\t  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \\\n\t\t( cryptStatus == CRYPT_ERROR_DUPLICATE ) )\n\t\t{\n\t\tstatic const CK_BBOOL bTrue = TRUE;\n\t\tCK_ATTRIBUTE decryptKeyTemplate[] = {\n\t\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }\n\t\t\t};\n\n\t\tcryptStatus = findObject( deviceInfo, &hObject, \n\t\t\t\t\t\t\t\t  decryptKeyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\tdecryptKeyTemplate[ 1 ].type = CKA_UNWRAP;\n\t\t\tcryptStatus = findObject( deviceInfo, &hObject, \n\t\t\t\t\t\t\t\t\t  decryptKeyTemplate, 2 );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* If we're just checking whether an object exists, return now.  If all \n\t   we want is the key label, copy it back to the caller and exit */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\treturn( CRYPT_OK );\n\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\treturn( getObjectLabel( deviceInfo, hObject, auxInfo, \n\t\t\t\t\t\t\t\tauxInfoLength ) );\n\n\t/* We found something, map the key type to a cryptlib algorithm ID,\n\t   determine the key size, and find its capabilities */\n\tkeyTypeTemplate.pValue = &keyType;\n\tC_GetAttributeValue( cryptoapiInfo->hProv, hObject, \n\t\t\t\t\t\t &keyTypeTemplate, 1 );\n\tENSURES( isIntegerRange( keyType ) );\n\tswitch( ( int ) keyType )\n\t\t{\n\t\tcase CKK_RSA:\n\t\t\tcryptAlgo = CRYPT_ALGO_RSA;\n\t\t\tkeySizeTemplate.type = CKA_MODULUS;\n\t\t\tbreak;\n\t\tcase CKK_DSA:\n\t\t\tcryptAlgo = CRYPT_ALGO_DSA;\n\t\t\tkeySizeTemplate.type = CKA_PRIME;\n\t\t\tbreak;\n\t\tcase CKK_DH:\n\t\t\tcryptAlgo = CRYPT_ALGO_DH;\n\t\t\tkeySizeTemplate.type = CKA_PRIME;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tC_GetAttributeValue( cryptoapiInfo->hProv, hObject, \n\t\t\t\t\t\t &keySizeTemplate, 1 );\n\tkeySize = keySizeTemplate.ulValueLen;\n\tcapabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo, \n\t\t\t\t\t\t\t\t\t\t\tcryptAlgo );\n\tif( capabilityInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Try and find a certificate which matches the key.  The process is as\n\t   follows:\n\n\t\tif certificate object found in issuerAndSerialNumber search\n\t\t\tcreate native data-only certificate object\n\t\t\tattach certificate object to key\n\t\telse\n\t\t\tif public key\n\t\t\t\tif certificate\n\t\t\t\t\tcreate native certificate (+context) object\n\t\t\t\telse\n\t\t\t\t\tcreate device pubkey object, mark as \"key loaded\"\n\t\t\telse\n\t\t\t\tcreate device privkey object, mark as \"key loaded\"\n\t\t\t\tif certificate\n\t\t\t\t\tcreate native data-only certificate object\n\t\t\t\t\tattach certificate object to key\n\n\t   The reason for doing things this way is given in the comments earlier\n\t   on in this function */\n\tif( privateKeyViaCert )\n\t\t{\n\t\t/* We've already got the certificate object handle, instantiate a \n\t\t   native data-only certificate from it */\n\t\tcryptStatus = instantiateCert( deviceInfo, hCertificate, \n\t\t\t\t\t\t\t\t\t   &iCryptCert, FALSE );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tcertPresent = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tcryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert, \n\t\t\t\t\t\t\t\t\t\t  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t\t\t  FINDCERT_NORMAL : FINDCERT_DATAONLY );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means \n\t\t\t   there's no certificate present, however anything else is an \n\t\t\t   error.  In addition if we've got a private key whose only \n\t\t\t   function is to point to an associated certificate then not \n\t\t\t   finding anything is also an error */\n\t\t\tif( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )\n\t\t\t\treturn( cryptStatus );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We got the certificate, if we're being asked for a public key \n\t\t\t   then we've created a native object to contain it so we return \n\t\t\t   that */\n\t\t\tcertPresent = TRUE;\n\t\t\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t\t{\n\t\t\t\t*iCryptContext = iCryptCert;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n/* Update a device with a certificate */\n\nstatic int setItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\tconst CRYPT_HANDLE iCryptHandle )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\tHCRYPTKEY hKey;\n\tDWORD dwKeySpec = 0;\n\tCRYPT_CERTIFICATE iCryptCert;\n\tBOOLEAN seenNonDuplicate = FALSE;\n\tint iterationCount = 0, status;\n\n\t/* Lock the certificate for our exclusive use (in case it's a \n\t   certificate chain, we also select the first certificate in the \n\t   chain), update the device with the certificate, and unlock it to \n\t   allow others access */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check whether the leaf certificate matches any of the user's private \n\t   keys */\n\tif( pCryptGetUserKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, &hKey ) )\n\t\t{\n\t\tif( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )\n\t\t\tdwKeySpec = AT_KEYEXCHANGE;\n\t\tpCryptDestroyKey( hKey ); \n\t\t}\n\telse\n\t\t{\n\t\tif( pCryptGetUserKey( cryptoapiInfo->hProv, AT_SIGNATURE, &hKey ) )\n\t\t\t{\n\t\t\tif( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )\n\t\t\t\tdwKeySpec = AT_SIGNATURE;\n\t\t\tpCryptDestroyKey( hKey ); \n\t\t\t}\n\t\t}\n\n\t/* Add each certificate in the chain to the store */\n\tdo\n\t\t{\n\t\tDYNBUF certDB;\n\t\tBOOL result = FALSE;\n\n\t\t/* Get the certificate data and add it to the store */\n\t\tstatus = dynCreate( &certDB, iCryptHandle, \n\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If the certificate corresponds to one of the user's private keys \n\t\t   and a binding between the key and a certificate isn't already \n\t\t   established, establish one now */\n\t\tif( dwKeySpec != 0 )\n\t\t\t{\n\t\t\tPCCERT_CONTEXT pCertContext;\n\t\t\tCERT_KEY_CONTEXT certKeyContext;\n\t\t\tDWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );\n\n\t\t\t/* Check whether the certificate is already bound to a key and \n\t\t\t   if not, bind it to the appropriate private key */\n\t\t\tpCertContext = pCertCreateCertificateContext( X509_ASN_ENCODING, \n\t\t\t\t\t\t\t\t\tdynData( certDB ), dynLength( certDB ) );\n\t\t\tif( pCertContext != NULL && \\\n\t\t\t\t!pCertGetCertificateContextProperty( pCertContext, \n\t\t\t\t\t\t\t\t\tCERT_KEY_CONTEXT_PROP_ID,\n\t\t\t\t\t\t\t\t\t&certKeyContext, &certKeyContextSize ) )\n\t\t\t\t{\n#if 1\n\t\t\t\t/* Check the certificate stores synchronising the \n\t\t\t\t   certificate's CERT_KEY_PROV_INFO_PROP_ID with any present \n\t\t\t\t   private keys if required */\n\t\t\t\tpCryptFindCertificateKeyProvInfo( pCertContext, 0, NULL );\n#elif 0\n\t\t\t\tCRYPT_KEY_PROV_INFO keyProvInfo;\n\t\t\t\tBYTE buffer[ 256 + 8 ];\n\t\t\t\tDWORD length = 256;\n\t\t\t\twchar_t provName[ 256 + 8 ], container[ 256 + 8 ];\n\n\t\t\t\tif( pCryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,\n\t\t\t\t\t\t\t\t\t\tbuffer, &length, 0 ) )\n\t\t\t\t\tMultiByteToWideChar( GetACP(), 0, buffer, length + 1, \n\t\t\t\t\t\t\t\t\t\t provName, 256 );\n\t\t\t\tif( pCryptGetProvParam( cryptoapiInfo->hProv, PP_CONTAINER,\n\t\t\t\t\t\t\t\t\t\tbuffer, &length, 0 ) )\n\t\t\t\t\tMultiByteToWideChar( GetACP(), 0, buffer, length + 1, \n\t\t\t\t\t\t\t\t\t\t container, 256 );\n\t\t\t\tmemset( &keyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ) );\n\t\t\t\tkeyProvInfo.pwszContainerName = container;\n\t\t\t\tkeyProvInfo.pwszProvName = provName;\n\t\t\t\tkeyProvInfo.dwProvType = PROV_RSA_FULL;\n\t\t\t\tkeyProvInfo.cProvParam = 0;\n\t\t\t\tkeyProvInfo.dwKeySpec = dwKeySpec;\n\t\t\t\tpCertSetCertificateContextProperty( pCertContext, \n\t\t\t\t\t\t\t\t\tCERT_KEY_PROV_HANDLE_PROP_ID, 0,\n\t\t\t\t\t\t\t\t\t&keyProvInfo );\n#elif 0\n\t\t\t\tmemset( &certKeyContext, 0, sizeof( CERT_KEY_CONTEXT ) );\n\t\t\t\tcertKeyContext.cbSize = sizeof( CERT_KEY_CONTEXT );\n\t\t\t\tcertKeyContext.dwKeySpec = dwKeySpec;\n\t\t\t\tcertKeyContext.hCryptProv = cryptoapiInfo->hProv;\n\t\t\t\tpCertSetCertificateContextProperty( pCertContext, \n\t\t\t\t\t\t\t\t\tCERT_KEY_CONTEXT_PROP_ID, 0,\n\t\t\t\t\t\t\t\t\t&certKeyContext );\n#endif\n\t\t\t\t}\n\n\t\t\t/* Add the certificate to the store */\n\t\t\tif( pCertContext != NULL )\n\t\t\t\t{\n\t\t\t\tresult = pCertAddCertificateContextToStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\t\tpCertContext, CERT_STORE_ADD_NEW, NULL );\n\t\t\t\tpCertFreeCertificateContext( pCertContext );\n\t\t\t\t}\n\n\t\t\t/* We've now added a bound certificate, don't bind the key to \n\t\t\t   any more certificates */\n\t\t\tdwKeySpec = 0;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Add the certificate to the store */\n\t\t\tresult = pCertAddEncodedCertificateToStore( cryptoapiInfo->hCertStore,\n\t\t\t\t\t\t\tX509_ASN_ENCODING, dynData( certDB ), \n\t\t\t\t\t\t\tdynLength( certDB ), CERT_STORE_ADD_NEW, NULL );\n\t\t\t}\n\t\tdynDestroy( &certDB );\n\t\tif( result )\n\t\t\tseenNonDuplicate = TRUE;\n\t\t}\n\twhile( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK && \\\n\t\t   iterationCount++ < FAILSAFE_ITERATIONS_MED );\n\tif( iterationCount >= FAILSAFE_ITERATIONS_MED )\n\t\tretIntError();\n\n\tkrnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE, \n\t\t\t\t\t CRYPT_IATTRIBUTE_LOCKED );\n\n\treturn( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );\n\t}\n\n/* Delete an object in a device */\n\nstatic int deleteItemFunction( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t   const KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   const void *keyID, const int keyIDlength )\n\t{\n#if 0\n\tstatic const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tCK_OBJECT_HANDLE hPrivkey = CRYPT_ERROR, hCertificate = CRYPT_ERROR;\n\tCK_OBJECT_HANDLE hPubkey = CRYPT_ERROR;\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\titemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tassert( keyIDtype == CRYPT_KEYID_NAME );\n\tassert( keyIDlength > 0 && keyIDlength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Find the object to delete based on the label.  Since we can have \n\t   multiple related objects (e.g. a key and a certificate) with the same \n\t   label, a straight search for all objects with a given label could \n\t   return CRYPT_ERROR_DUPLICATE so we search for the objects by type as \n\t   well as label.  In addition even a search for specific objects can \n\t   return CRYPT_ERROR_DUPLICATE so we use the Ex version of findObject() \n\t   to make sure we don't get an error if multiple objects exist.  \n\t   Although cryptlib won't allow more than one object with a given label \n\t   to be created, other applications might create duplicate labels.  The \n\t   correct behaviour in these circumstances is uncertain, what we do for \n\t   now is delete the first object we find that matches the label.\n\t   \n\t   First we try for a certificate and use that to find associated keys */\n\tcryptStatus = findObjectEx( deviceInfo, &hCertificate, certTemplate, 3 );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\t/* We got a certificate, if there are associated keys delete them as \n\t\t   well */\n\t\tcryptStatus = findObjectFromObject( deviceInfo, hCertificate, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PUBLIC_KEY, &hPubkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CRYPT_ERROR;\n\t\tcryptStatus = findObjectFromObject( deviceInfo, hCertificate, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, &hPrivkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CRYPT_ERROR;\n\t\t}\n\telse\n\t\t{\n\t\t/* We didn't find a certificate with the given label, try for public \n\t\t   and private keys */\n\t\tcryptStatus = findObjectEx( deviceInfo, &hPubkey, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CRYPT_ERROR;\n\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;\n\t\tcryptStatus = findObjectEx( deviceInfo, &hPrivkey, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CRYPT_ERROR;\n\n\t\t/* There may be an unlabelled certificate present, try and find it by \n\t\t   looking for a certificate matching the key ID */\n\t\tif( hPubkey != CRYPT_ERROR || hPrivkey != CRYPT_ERROR )\n\t\t\t{\n\t\t\tcryptStatus = findObjectFromObject( deviceInfo, \n\t\t\t\t\t\t\t( hPrivkey != CRYPT_ERROR ) ? hPrivkey : hPubkey, \n\t\t\t\t\t\t\tCKO_CERTIFICATE, &hCertificate );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\thCertificate = CRYPT_ERROR;\n\t\t\t}\n\t\t}\n\n\t/* If we found a public key with a given label but no private key, try \n\t   and find a matching private key by ID, and vice versa */\n\tif( hPubkey != CRYPT_ERROR && hPrivkey == CRYPT_ERROR )\n\t\t{\n\t\tcryptStatus = findObjectFromObject( deviceInfo, hPubkey, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, &hPrivkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CRYPT_ERROR;\n\t\t}\n\tif( hPrivkey != CRYPT_ERROR && hPubkey == CRYPT_ERROR )\n\t\t{\n\t\tcryptStatus = findObjectFromObject( deviceInfo, hPrivkey, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PUBLIC_KEY, &hPubkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CRYPT_ERROR;\n\t\t}\n\tif( hPrivkey == CRYPT_ERROR && hPubkey == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Reset the status values, which may contain error values due to not \n\t   finding various objects to delete above */\n\tcryptStatus = CRYPT_OK;\n\tstatus = CKR_OK;\n\n\t/* Delete the objects */\n\tif( hCertificate != CRYPT_ERROR )\n\t\tstatus = C_DestroyObject( cryptoapiInfo->hProv, hCertificate );\n\tif( hPubkey != CRYPT_ERROR )\n\t\t{\n\t\tint status2;\n\n\t\tstatus2 = C_DestroyObject( cryptoapiInfo->hProv, hPubkey );\n\t\tif( status2 != CKR_OK && status == CKR_OK )\n\t\t\tstatus = status2;\n\t\t}\n\tif( hPrivkey != CRYPT_ERROR )\n\t\t{\n\t\tint status2;\n\n\t\tstatus2 = C_DestroyObject( cryptoapiInfo->hProv, hPrivkey );\n\t\tif( status2 != CKR_OK && status == CKR_OK )\n\t\t\tstatus = status2;\n\t\t}\n\tif( status != CKR_OK )\n\t\tcryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );\n\treturn( cryptStatus );\n#endif\n\n\treturn( CRYPT_ERROR );\n\t}\n\n/* Get the sequence of certificates in a chain from a device.  Unfortunately \n   we can't really make the certificate chain fetch stateless without re-\n   doing the read of the entire chain from the CryptoAPI certificate store \n   for each fetch.  To avoid this performance hit we cache the chain in the \n   device information and pick out each certificate in turn during the \n   findNext */\n\nstatic int getFirstItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\t CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t int *stateInfo, \n\t\t\t\t\t\t\t\t const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t const void *keyID, const int keyIDlength,\n\t\t\t\t\t\t\t\t const KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t\t\t\t\t const int options )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\tPCCERT_CONTEXT pCertContext;\n\tPCCERT_CHAIN_CONTEXT pChainContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( keyIDtype == CRYPT_IKEYID_KEYID );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( keyIDlength > 4 && keyIDlength < MAX_INTLENGTH_SHORT );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\tassert( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\tcryptoapiInfo->hCertChain = NULL;\n\n\t/* Try and find the certificate with the given ID.  This should work \n\t   because we've just read the ID for the indirect-import that lead to \n\t   the getFirst call */\n\tstatus = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t\t &pCertContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed to load CryptoAPI certificate data\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\n\t/* Now try and get the chain from the certificate.  If this fails, we \n\t   just use the standalone certificate */\n\tstatus = getCertificateChain( cryptoapiInfo, pCertContext, \n\t\t\t\t\t\t\t\t  &pChainContext );\n\tif( cryptStatusOK( status ) )\n\t\tcryptoapiInfo->hCertChain = pChainContext;\n\n\t/* Import the leaf certificate as a cryptlib object */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, \n\t\t\t\t\t\t\t\t\t\tpCertContext->pbCertEncoded, \n\t\t\t\t\t\t\t\t\t\tpCertContext->cbCertEncoded,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tpCertFreeCertificateContext( pCertContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( cryptoapiInfo->hCertChain != NULL )\n\t\t\tpCertFreeCertificateChain( cryptoapiInfo->hCertChain );\n\t\treturn( status );\n\t\t}\n\n\t/* Remember that we've got the leaf certificate in the chain */\n\tassert( pChainContext->cChain == 1 );\n\t*stateInfo = 1;\n\treturn( CRYPT_OK );\n\t}\n\nstatic int getNextItemFunction( DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tint *stateInfo, const int options )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\tPCCERT_CHAIN_CONTEXT pChainContext = cryptoapiInfo->hCertChain;\n\tPCERT_SIMPLE_CHAIN pCertSimpleChain;\n\tPCERT_CHAIN_ELEMENT pCertChainElement;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\tassert( *stateInfo == CRYPT_ERROR || *stateInfo >= 1 );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* If the previous certificate was the last one, there's nothing left to \n\t   fetch */\n\tif( cryptoapiInfo->hCertChain == NULL )\n\t\t{\n\t\t*stateInfo = CRYPT_ERROR;\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tpCertSimpleChain = pChainContext->rgpChain[ 0 ];\n\tif( *stateInfo < 1 || *stateInfo > pCertSimpleChain->cElement )\n\t\t{\n\t\tpCertFreeCertificateChain( cryptoapiInfo->hCertChain );\n\t\tcryptoapiInfo->hCertChain = NULL;\n\t\t*stateInfo = CRYPT_ERROR;\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* Get the next certificate in the chain */\n\tpCertChainElement = pCertSimpleChain->rgpElement[ *stateInfo ];\n\tsetMessageCreateObjectIndirectInfo( &createInfo, \n\t\t\t\t\t\t\tpCertChainElement->pCertContext->pbCertEncoded, \n\t\t\t\t\t\t\tpCertChainElement->pCertContext->cbCertEncoded,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tpCertFreeCertificateChain( cryptoapiInfo->hCertChain );\n\t\tcryptoapiInfo->hCertChain = NULL;\n\t\t*stateInfo = CRYPT_ERROR;\n\t\treturn( status );\n\t\t}\n\t( *stateInfo )++;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tCapability Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Clean up the object associated with a context */\n\nstatic int genericEndFunction( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Since the device object that corresponds to the cryptlib object is\n\t   created on-demand, it may not exist yet if the action that triggers\n\t   the on-demand creation hasn't been taken yet.  If no device object\n\t   exists, we're done */\n\tif( contextInfoPtr->deviceObject == CRYPT_ERROR )\n\t\treturn( CRYPT_OK );\n\n\t/* Destroy the object */\n\tif( capabilityInfoPtr->keySize > 0 )\n\t\tpCryptDestroyKey( contextInfoPtr->deviceObject );\n\telse\n\t\tpCryptDestroyHash( contextInfoPtr->deviceObject );\n\treturn( CRYPT_OK );\n\t}\n\n/* RSA algorithm-specific mapping functions.  Since CryptoAPI adds its own\n   PKCS #1 padding, we add/remove the cryptlib-added padding to fake out the \n   presence of a raw RSA mechanism */\n\nstatic int rsaSetKeyInfo( CRYPTOAPI_INFO *cryptoapiInfo,\n\t\t\t\t\t\t  CONTEXT_INFO *contextInfoPtr )\n\t{\n\tBYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];\n\tMESSAGE_DATA msgData;\n\tint nLen, eLen, keyDataSize, status;\n\n\t/* Extract the public-key components from the CryptoAPI context */\n\tstatus = getPubkeyComponents( cryptoapiInfo, \n\t\t\t\t\t\t\t\t  contextInfoPtr->deviceObject, \n\t\t\t\t\t\t\t\t  n, &nLen, e, &eLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all we're doing here is sending in encoded public key data for use by \n\t   objects such as certificates */\n\tstatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,\n\t\t\t\t\t\t\t\t &keyDataSize, CRYPT_ALGO_RSA, 0,\n\t\t\t\t\t\t\t\t n, nLen, e, eLen, NULL, 0, NULL, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\t\tstatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\t\t}\n\treturn( status );\n\t}\n\nstatic int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tCRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;\n\tHCRYPTKEY hKey;\n\tBLOBHEADER *blobHeaderPtr;\n\tRSAPUBKEY *pubKeyPtr;\n\tBYTE keyBlob[ ( CRYPT_MAX_PKCSIZE * 8 ) + 8 ], *keyBlobPtr;\n\tDWORD exponent = 0L;\n\tBOOL result;\n\tconst int nLen = bitsToBytes( rsaKey->nLen );\n\tint i, status, LOOP_ITERATOR;\n\n\t/* CryptoAPI sets some awkward constraints on key formats, only allowing\n\t   exponents that can be represented as 32-bit ints and requiring that\n\t   the lengths of all MPIs be explicitly specified by the modulus size,\n\t   so we have to check whether the key components are in this form \n\t   before we can try and load the key */\n\tif( bitsToBytes( rsaKey->eLen ) > sizeof( DWORD ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( !rsaKey->isPublicKey && \\\n\t\t( ( bitsToBytes( rsaKey->pLen ) > nLen / 2 ) || \\\n\t\t  ( bitsToBytes( rsaKey->qLen ) > nLen / 2 ) || \\\n\t\t  ( bitsToBytes( rsaKey->e1Len ) > nLen / 2 ) || \\\n\t\t  ( bitsToBytes( rsaKey->e2Len ) > nLen / 2 ) || \\\n\t\t  ( bitsToBytes( rsaKey->uLen ) > nLen / 2 ) || \\\n\t\t  ( bitsToBytes( rsaKey->dLen ) > nLen ) ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Get the exponent as a DWORD */\n\tLOOP_LARGE( i = 0, i < bitsToBytes( rsaKey->eLen ), i++ )\n\t\texponent = ( exponent << 8 ) | rsaKey->e[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the blob header:\n\n\t\tOfs\tValue\n\t\t  0\tBLOBHEADER blobheader {\n\t\t\t  0\tBYTE bType;\n\t\t\t  1\tBYTE bVersion;\n\t\t\t  2 WORD reserved;\n\t\t\t  4\tALG_ID aiKeyAlg; }\n\t\t  8\tRSAPUBKEY rsapubkey {\n\t\t\t  8 DWORD magic;\n\t\t\t 12\tDWORD bitlen;\n\t\t\t 16\tDWORD pubexp; }\n\t\t 20\tBYTE modulus[ rsapubkey.bitlen / 8 ];\n\t\t\tBYTE prime1[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE prime2[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE exponent1[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE exponent2[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE coefficient[ rsapubkey.bitlen / 16 ];\n\t\t\tBYTE privateExponent[ rsapubkey.bitlen / 8 ]; */\n\tmemset( keyBlob, 0, CRYPT_MAX_PKCSIZE * 8 );\n\tblobHeaderPtr = ( BLOBHEADER * ) keyBlob;\n\tblobHeaderPtr->bType = intToByte( ( rsaKey->isPublicKey ) ? \\\n\t\t\t\t\t\t\t\t\t  PUBLICKEYBLOB : PRIVATEKEYBLOB );\n\tblobHeaderPtr->bVersion = CUR_BLOB_VERSION;\n\tblobHeaderPtr->aiKeyAlg = CALG_RSA_KEYX;\n\n\t/* Set up the public-key components.  CryptoAPI requires that the \n\t   modulus length be a multiple of 8 bits, so we have to round up the \n\t   length to the nearest byte boundary */\n\tpubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );\n\tpubKeyPtr->magic = ( rsaKey->isPublicKey ) ? 0x31415352 : 0x32415352;\n\tpubKeyPtr->bitlen = roundUp( rsaKey->nLen, 8 );\n\tpubKeyPtr->pubexp = exponent;\n\tkeyBlobPtr = keyBlob + BLOBHEADER_SIZE + ( 3 * sizeof( DWORD ) );\n\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->n, nLen, nLen );\n\n\t/* Set up the private-key components if necessary */\n\tif( !rsaKey->isPublicKey )\n\t\t{\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->p, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->pLen ), nLen / 2 );\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->q, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->qLen ), nLen / 2 );\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->e1, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->e1Len ), nLen / 2 );\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->e2, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->e2Len ), nLen / 2 );\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->u, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->uLen ), nLen / 2 );\n\t\tkeyBlobPtr = copyMPI( keyBlobPtr, rsaKey->d, \n\t\t\t\t\t\t\t  bitsToBytes( rsaKey->dLen ), nLen );\n\t\t}\n\n\t/* Import the key blob and clean up */\n\tresult = pCryptImportKey( cryptoapiInfo->hProv, keyBlob, \n\t\t\t\t\t\t\t  keyBlobPtr - keyBlob, 0, 0, &hKey );\n\tif( result )\n\t\t{\n\t\t/* Note that the following will break under Win64 since the hKey is\n\t\t   a 64-bit pointer while the deviceObject is a 32-bit unsigned \n\t\t   value, this code is experimental and only enabled for Win32 debug \n\t\t   so this isn't a problem at the moment */\n\t\tcontextInfoPtr->deviceObject = ( long ) hKey;\n\t\t}\n\telse\n\t\tstatus = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );\n\tzeroise( keyBlob, CRYPT_MAX_PKCSIZE * 8 );\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = rsaSetKeyInfo( cryptoapiInfo, contextInfoPtr );\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\nstatic int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tHCRYPTKEY hPrivateKey;\n\tBOOL result;\n\tint status;\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the key.  CryptoAPI kludges the key size information by \n\t   masking it into the high bits of the flags parameter.  We make the\n\t   key exportable, because the ability to hand out keys in PKCS #12 \n\t   format is the prime (only?) motivation for anyone using CryptoAPI */\n\tresult = pCryptGenKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, \n\t\t\t\t\t\t   CRYPT_EXPORTABLE | ( keysizeBits << 16 ), \n\t\t\t\t\t\t   &hPrivateKey );\n\tif( result )\n\t\t{\n\t\t/* Note that the following will break under Win64 since the hKey is\n\t\t   a 64-bit pointer while the deviceObject is a 32-bit unsigned \n\t\t   value, this code is experimental and only enabled for Win32 debug \n\t\t   so this isn't a problem at the moment */\n\t\tcontextInfoPtr->deviceObject = ( long ) hPrivateKey;\n\t\t}\n\telse\n\t\tstatus = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = rsaSetKeyInfo( cryptoapiInfo, contextInfoPtr );\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\nstatic int rsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tSTREAM stream;\n\tHCRYPTHASH hHash;\n\tBYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ], *bufPtr = buffer;\n\tALG_ID algID;\n\tDWORD resultLength = length;\n\tBOOL result;\n\tint i, status, LOOP_ITERATOR;\n\n\t/* CryptoAPI adds its own PKCS #1 padding, so we have to reverse-engineer\n\t   the encoding and padding that's already been added */\n\tassert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 1 );\n\tLOOP_LARGE( i = 2, i < length, i++ )\n\t\t{\n\t\tif( bufPtr[ i ] == 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\ti++;\t/* Skip final 0 byte */\n\tsMemConnect( &stream, bufPtr + i, length - i );\n\tstatus = readMessageDigest( &stream, &cryptAlgo, hashBuffer, \n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE, &i );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\talgID = cryptlibToCapiID( cryptAlgo );\n\tif( algID == 0 )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* CryptoAPI can only sign hash values inside hash objects, luckily \n\t   there's a function whose sole purpose is to allow hash values to be \n\t   loaded directly into hash objects that we can use to create the hash\n\t   to be signed.\n\t   \n\t   Once we've got the hash though, things get tricky.  CryptSignHash() \n\t   doesn't let you specify which key you want to use for signing, but it \n\t   does let you indicate that you want to use the default encryption-only \n\t   key as your signature key.  This is sort of like building a car where \n\t   the steering wheel won't turn, but in compensation the fuel tank will\n\t   explode if you hit the horn */\n\tresult = pCryptCreateHash( cryptoapiInfo->hProv, algID, 0, 0, &hHash );\n\tif( !result )\n\t\t{\n\t\tstatus = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( status );\n\t\t}\n\tresult = pCryptSetHashParam( hHash, HP_HASHVAL, hashBuffer, 0 );\n\tif( result )\n\t\tresult = pCryptSignHash( hHash, AT_KEYEXCHANGE, NULL, 0, \n\t\t\t\t\t\t\t\t tempBuffer, &resultLength );\n\tpCryptDestroyHash( hHash );\n\tif( result )\n\t\t{\n\t\tcopyMPI( buffer, tempBuffer, resultLength, resultLength );\n\t\tzeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );\n\n\t\t/* Restore any truncated leading zeroes if necessary */\n\t\tif( resultLength < length )\n\t\t\t{\n\t\t\tconst int delta = length - resultLength;\n\t\n\t\t\tmemmove( ( BYTE * ) buffer + delta, tempBuffer, resultLength );\n\t\t\tmemset( buffer, 0, delta );\n\t\t\t}\n\t\t}\n\tif( !result )\n\t\tstatus = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\nstatic int rsaVerify( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and more importanyly because there's no way to get at the\n\t   hash information that's needed to create the hash object, so that\n\t   the trick used in rsaSign() won't work */\n\tretIntError();\n\t}\n\nstatic int rsaEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tBYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ], *tempPtr, *bufPtr = buffer;\n\tDWORD resultLength;\n\tint i, LOOP_ITERATOR;\n\n\t/* CryptoAPI adds its own PKCS #1 padding, so we have to undo the \n\t   padding that's already been added */\n\tassert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 2 );\n\tLOOP_LARGE( i = 2, i < length, i++ )\n\t\t{\n\t\tif( bufPtr[ i ] == 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\ti++;\t/* Skip final 0 byte */\n\n\t/* Change the data into the little-endian order required by CryptoAPI, \n\t   encrypt it, reverse the order again */\n\ttempPtr = copyMPI( tempBuffer, bufPtr + i, length - i, length - i );\n\tresultLength = tempPtr - tempBuffer;\n\tif( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, TRUE, 0, \n\t\t\t\t\t\ttempBuffer, &resultLength, length ) )\n\t\t{\n\t\tzeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\t\t}\n\tcopyMPI( buffer, tempBuffer, resultLength, resultLength );\n\tzeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );\n\n\t/* Restore any truncated leading zeroes if necessary */\n\tif( resultLength < length )\n\t\t{\n\t\tconst int delta = length - resultLength;\n\n\t\tmemmove( ( BYTE * ) buffer + delta, tempBuffer, resultLength );\n\t\tmemset( buffer, 0, delta );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nstatic int rsaDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tBYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ], *tempPtr, *bufPtr = buffer;\n\tDWORD resultLength;\n\tint i, LOOP_ITERATOR;\n\n\t/* Change the data into the little-endian order required by CryptoAPI, \n\t   decrypt it, and reverse the order again */\n\ttempPtr = copyMPI( tempBuffer, bufPtr, length, length );\n\tresultLength = tempPtr - tempBuffer;\n\tif( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, \n\t\t\t\t\t\ttempBuffer, &resultLength ) )\n\t\t{\n\t\tzeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\t\t}\n\tcopyMPI( buffer, tempBuffer, resultLength, resultLength );\n\tzeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );\n\n\t/* Redo the PKCS #1 padding that was stripped by CryptoAPI */\n\tmemmove( bufPtr + length - resultLength, bufPtr, resultLength );\n\tbufPtr[ 0 ] = 0;\n\tbufPtr[ 1 ] = 2;\n\tLOOP_LARGE( i = 2, i < length - resultLength - 1, i++ )\n\t\tbufPtr[ i ] = 0xA5;\n\tENSURES( LOOP_BOUND_OK );\n\tbufPtr[ i ] = 0;\n\tassert( i + 1 + resultLength == length );\n\treturn( CRYPT_OK );\n\t}\n\n/* DSA algorithm-specific mapping functions */\n\n#if 0\n\nstatic int dsaSetKeyInfo( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr, \n//\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPrivateKey,\n//\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPublicKey,\n\t\t\t\t\t\t  const void *p, const int pLen,\n\t\t\t\t\t\t  const void *q, const int qLen,\n\t\t\t\t\t\t  const void *g, const int gLen,\n\t\t\t\t\t\t  const void *y, const int yLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];\n\tBYTE idBuffer[ KEYID_SIZE + 8 ];\n\tint keyDataSize, cryptStatus;\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all we're doing here is sending in encoded public key data for use by \n\t   objects such as certificates */\n\tcryptStatus = keyDataSize = writeFlatPublicKey( NULL, 0, CRYPT_ALGO_DSA, 0,\n\t\t\t\t\t\t\t\t\t\t\t\t\tp, pLen, q, qLen, \n\t\t\t\t\t\t\t\t\t\t\t\t\tg, gLen, y, yLen );\n\tif( !cryptStatusError( cryptStatus ) )\n\t\tcryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_ALGO_DSA, 0, p, pLen, q, qLen, \n\t\t\t\t\t\t\t\t\t\t  g, gLen, y, yLen );\n\tif( !cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\t\tcryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Remember what we've set up */\n\tkrnlSendMessage( contextInfoPtr->objectHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &hPrivateKey, \n\t\t\t\t\t CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\n\t/* Get the key ID from the context and use it as the object ID.  Since \n\t   some objects won't allow after-the-even ID updates, we don't treat a\n\t   failure to update as an error */\n\tsetMessageData( &msgData, idBuffer, KEYID_SIZE );\n\tcryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tCK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };\n\n\t\tif( hPublicKey != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tC_SetAttributeValue( cryptoapiInfo->hProv, hPublicKey, \n\t\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\t\t}\n\t\tC_SetAttributeValue( cryptoapiInfo->hProv, hPrivateKey, \n\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\t}\n\t\n\treturn( cryptStatus );\n\treturn( CRYPT_ERROR );\n\t}\n#endif /* 0 */\n\nstatic int dsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tCRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) key;\n\tHCRYPTKEY hKey;\n\tBLOBHEADER *blobHeaderPtr;\n\tDSSPUBKEY *pubKeyPtr;\n\tBYTE keyBlob[ ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ], *keyBlobPtr;\n\tBOOL result;\n\tconst int pLen = bitsToBytes( dlpKey->pLen );\n\tint status;\n\n\t/* CryptoAPI sets some awkward constraints on key formats, only allowing\n\t   a prime size up to 1024 bits, so we have to check whether the key \n\t   components are in this form before we can try and load the key */\n\tif( dlpKey->pLen > 1024 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the blob header:\n\n\t\tOfs\tValue\n\t\t  0\tBLOBHEADER blobheader {\n\t\t\t  0\tBYTE bType;\n\t\t\t  1\tBYTE bVersion;\n\t\t\t  2 WORD reserved;\n\t\t\t  4\tALG_ID aiKeyAlg; }\n\t\t  8\tDSSPUBKEY_VER3 dsspubkey {\n\t\t\t  8 DWORD magic;\n\t\t\t 12\tDWORD bitlen; }\n\t\t 16\tBYTE p[ 128 ];\n\t\t\tBYTE q[ 20 ];\n\t\t\tBYTE g[ 128 ];\n\t\t\tBYTE y[ 128 ]; */\n\tmemset( keyBlob, 0, CRYPT_MAX_PKCSIZE * 4 );\n\tblobHeaderPtr = ( BLOBHEADER * ) keyBlob;\n\tblobHeaderPtr->bType = intToByte( ( dlpKey->isPublicKey ) ? \\\n\t\t\t\t\t\t\t\t\t  PUBLICKEYBLOB : PRIVATEKEYBLOB );\n\tblobHeaderPtr->bVersion = CUR_BLOB_VERSION;\n\tblobHeaderPtr->aiKeyAlg = CALG_DSS_SIGN;\n\n\t/* Set up the public-key components.  CryptoAPI requires that the \n\t   modulus length be a multiple of 8 bits, so we have to round up the \n\t   length to the nearest byte boundary */\n\tpubKeyPtr = ( DSSPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );\n\tpubKeyPtr->magic = 0x31535344;\n\tpubKeyPtr->bitlen = roundUp( dlpKey->pLen, 8 );\n\tkeyBlobPtr = keyBlob + BLOBHEADER_SIZE + ( 2 * sizeof( DWORD ) );\n\tkeyBlobPtr = copyMPI( keyBlobPtr, dlpKey->p, pLen, 128 );\n\tkeyBlobPtr = copyMPI( keyBlobPtr, dlpKey->q, \n\t\t\t\t\t\t  bitsToBytes( dlpKey->qLen ), 20 );\n\tkeyBlobPtr = copyMPI( keyBlobPtr, dlpKey->g, \n\t\t\t\t\t\t  bitsToBytes( dlpKey->gLen ), 128 );\n\tkeyBlobPtr = copyMPI( keyBlobPtr, dlpKey->y, \n\t\t\t\t\t\t  bitsToBytes( dlpKey->yLen ), 128 );\n\n\t/* Set up the private-key components if necessary */\n\tif( !dlpKey->isPublicKey )\n\t\t{\n\t\t}\n\n\t/* Import the key blob and clean up */\n\tresult = pCryptImportKey( cryptoapiInfo->hProv, keyBlob, \n\t\t\t\t\t\t\t  keyBlobPtr - keyBlob, 0, 0, &hKey );\n\tif( result )\n\t\t{\n\t\t/* Note that the following will break under Win64 since the hKey is\n\t\t   a 64-bit pointer while the deviceObject is a 32-bit unsigned \n\t\t   value, this code is experimental and only enabled for Win32 debug \n\t\t   so this isn't a problem at the moment */\n\t\tcontextInfoPtr->deviceObject = ( long ) hKey;\n\t\t}\n\telse\n\t\tstatus = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );\n\tzeroise( keyBlob, CRYPT_MAX_PKCSIZE * 4 );\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\nstatic int dsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )\n\t{\n#if 0\n\tstatic const CK_MECHANISM mechanism = { CKM_DSA_KEY_PAIR_GEN, NULL_PTR, 0 };\n\tstatic const CK_BBOOL bTrue = TRUE;\n\tconst CK_ULONG modulusBits = keysizeBits;\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t};\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIME, NULL, 0 },\n\t\t{ CKA_SUBPRIME, NULL, 0 },\n\t\t{ CKA_BASE, NULL, 0 },\n\t\t};\n\tCK_ATTRIBUTE yValueTemplate = { CKA_VALUE, NULL, CRYPT_MAX_PKCSIZE * 2 };\n\tCK_OBJECT_HANDLE hPublicKey, hPrivateKey;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tCRYPT_DEVICE iCryptDevice;\n\tBYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ], label[ 8 + 8 ];\n\tCK_RV status;\n\tSTREAM stream;\n\tlong length;\n\tint keyLength = bitsToBytes( keysizeBits ), cryptStatus;\n\n\t/* CKM_DSA_KEY_PAIR_GEN is really a Clayton's key generation mechanism \n\t   since it doesn't actually generate the p, q, or g values (presumably \n\t   it dates back to the original FIPS 186 shared domain parameters idea).\n\t   Because of this we'd have to generate half the key ourselves in a \n\t   native context, then copy portions from the native context over in \n\t   flat form and complete the keygen via the device.  The easiest way to\n\t   do this is to create a native DSA context, generate a key, grab the\n\t   public portions, and destroy the context again (i.e. generate a full\n\t   key on a superscalar 2GHz RISC CPU, then throw half of it away, and \n\t   regenerate it on a 5MHz 8-bit tinkertoy).  Since the keygen can take \n\t   awhile and doesn't require the device, we do it before we grab the \n\t   device */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DSA );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, label, 8 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( int * ) &keyLength, CRYPT_CTXINFO_KEYSIZE );\n\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t   IMESSAGE_CTX_GENKEY, NULL, FALSE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tsetMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 2 );\n\t\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the public key information by extracting the flat values from \n\t   the SubjectPublicKeyInfo.  Note that the data used is represented in\n\t   DER-canonical form, there may be PKCS #11 implementations that\n\t   can't handle this (for example they may require q to be zero-padded\n\t   to make it exactly 20 bytes rather than (say) 19 bytes if the high\n\t   byte is zero) */\n\tsMemConnect( &stream, pubkeyBuffer, msgData.length );\n\treadSequence( &stream, NULL );\t\t\t\t/* SEQUENCE */\n\treadSequence( &stream, NULL );\t\t\t\t\t/* SEQUENCE */\n\treadUniversal( &stream );\t\t\t\t\t\t\t/* OID */\n\treadSequence( &stream, NULL );\t\t\t\t\t\t/* SEQUENCE */\n\treadGenericHole( &stream, &length );\t\t\t\t\t/* p */\n\tpublicKeyTemplate[ 3 ].pValue = sMemBufPtr( &stream );\n\tpublicKeyTemplate[ 3 ].ulValueLen = length;\n\tsSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\treadGenericHole( &stream, &length );\t\t\t\t\t/* q */\n\tpublicKeyTemplate[ 4 ].pValue = sMemBufPtr( &stream );\n\tpublicKeyTemplate[ 4 ].ulValueLen = length;\n\tsSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\treadGenericHole( &stream, &length );\t\t\t\t\t/* g */\n\tpublicKeyTemplate[ 5 ].pValue = sMemBufPtr( &stream );\n\tpublicKeyTemplate[ 5 ].ulValueLen = length;\n\tassert( sStatusOK( &stream ) );\n\tsMemDisconnect( &stream );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the keys */\n\tstatus = C_GenerateKeyPair( cryptoapiInfo->hProv,\n\t\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) publicKeyTemplate, 5,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) privateKeyTemplate, 4,\n\t\t\t\t\t\t\t\t&hPublicKey, &hPrivateKey );\n\tcryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Read back the generated y value, send the public key information to \n\t   the context, and set up the key ID info.  The odd two-phase y value \n\t   read is necessary for buggy implementations that fail if the given \n\t   size isn't exactly the same as the data size */\n\tstatus = C_GetAttributeValue( cryptoapiInfo->hProv, hPublicKey,\n\t\t\t\t\t\t\t\t  &yValueTemplate, 1 );\n\tif( status == CKR_OK )\n\t\t{\n\t\tyValueTemplate.pValue = pubkeyBuffer;\n\t\tstatus = C_GetAttributeValue( cryptoapiInfo->hProv, hPublicKey, \n\t\t\t\t\t\t\t\t\t  &yValueTemplate, 1 );\n\t\t}\n\tcryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = dsaSetKeyInfo( deviceInfo, contextInfoPtr, \n\t\t\thPrivateKey, hPublicKey,\n\t\t\tpublicKeyTemplate[ 3 ].pValue, publicKeyTemplate[ 3 ].ulValueLen, \n\t\t\tpublicKeyTemplate[ 4 ].pValue, publicKeyTemplate[ 4 ].ulValueLen, \n\t\t\tpublicKeyTemplate[ 5 ].pValue, publicKeyTemplate[ 5 ].ulValueLen,\n\t\t\tyValueTemplate.pValue, yValueTemplate.ulValueLen );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tC_DestroyObject( cryptoapiInfo->hProv, hPublicKey );\n\t\tC_DestroyObject( cryptoapiInfo->hProv, hPrivateKey );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n#endif /* 0 */\n\treturn( CRYPT_ERROR );\n\t}\n\nstatic int dsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n#if 0\n\tstatic const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tBIGNUM *r, *s;\n\tBYTE signature[ 40 + 8 ];\n\tint cryptStatus;\n\n\tassert( length == sizeof( DLP_PARAMS ) );\n\tassert( dlpParams->inParam1 != NULL && \\\n\t\t\tdlpParams->inLen1 == 20 );\n\tassert( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );\n\tassert( dlpParams->outParam != NULL && \\\n\t\t\tdlpParams->outLen >= ( 2 + 20 ) * 2 );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptStatus = genericSign( deviceInfo, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t   dlpParams->inParam1, dlpParams->inLen1,\n\t\t\t\t\t\t\t   signature, 40 );\n\tkrnlReleaseObject( iCryptDevice );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Encode the result as a DL data block.  We have to do this as via \n\t   bignums, but this isn't a big deal since DSA signing via tokens is\n\t   almost never used */\n\tr = BN_new();\n\ts = BN_new();\n\tif( r != NULL && s != NULL )\n\t\t{\n\t\tBN_bin2bn( signature, 20, r );\n\t\tBN_bin2bn( signature + 20, 20, s );\n\t\tcryptStatus = encodeDLValues( dlpParams->outParam, dlpParams->outLen, \n\t\t\t\t\t\t\t\t\t  r, s, dlpParams->formatType );\n\t\tif( !cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\tdlpParams->outLen = cryptStatus;\n\t\t\tcryptStatus = CRYPT_OK;\t/* encodeDLValues() returns a byte count */\n\t\t\t}\n\t\tBN_clear_free( s );\n\t\tBN_clear_free( r );\n\t\t}\n\treturn( cryptStatus );\n#endif /* 0 */\n\treturn( CRYPT_ERROR );\n\t}\n\nstatic int dsaVerify( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n#if 0\n\tstatic const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tBIGNUM *r, *s;\n\tBYTE signature[ 40 + 8 ];\n\tint cryptStatus;\n\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and because some tokens don't support public-key \n\t   operations */\n\n\tassert( length == sizeof( DLP_PARAMS ) );\n\tassert( dlpParams->inParam1 != NULL && dlpParams->inLen1 == 20 );\n\tassert( dlpParams->inParam2 != NULL && \\\n\t\t\t( ( dlpParams->formatType == CRYPT_FORMAT_CRYPTLIB && \\\n\t\t\t\tdlpParams->inLen2 >= 46 ) || \\\n\t\t\t  ( dlpParams->formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\tdlpParams->inLen2 == 44 ) || \\\n\t\t\t\t( dlpParams->formatType == CRYPT_IFORMAT_SSH && \\\n\t\t\t\tdlpParams->inLen2 == 40 ) ) );\n\tassert( dlpParams->outParam == NULL && dlpParams->outLen == 0 );\n\n\t/* Decode the values from a DL data block and make sure r and s are\n\t   valid */\n\tcryptStatus = decodeDLValues( dlpParams->inParam2, dlpParams->inLen2, \n\t\t\t\t\t\t\t\t  &r, &s, dlpParams->formatType );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* This code can never be called, since DSA public-key contexts are \n\t   always native contexts */\n\tretIntError();\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptStatus = genericVerify( deviceInfo, contextInfoPtr, &mechanism, buffer,\n\t\t\t\t\t\t\t\t 20, signature, 40 );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n#endif /* 0 */\n\treturn( CRYPT_ERROR );\n\t}\n\n/* Conventional cipher-specific mapping functions */\n\nstatic int cipherInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t\t  const int keyLength )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPTOAPI_INFO *cryptoapiInfo;\n\tHCRYPTKEY hSessionKey;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint keySize = keyLength, status;\n\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Get the information for the device associated with this context */\n\tstatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   &iCryptDevice, &cryptoapiInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy the key to internal storage */\n\tif( contextInfoPtr->ctxConv->userKey != key )\n\t\tmemcpy( contextInfoPtr->ctxConv->userKey, key, keyLength );\n\tcontextInfoPtr->ctxConv->userKeyLength = keyLength;\n\n\t/* Special-case handling for 2-key vs.3-key 3DES */\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_3DES )\n\t\t{\n\t\t/* If the supplied key contains only two DES keys, adjust the key to\n\t\t   make it the equivalent of 3-key 3DES.  In addition since the\n\t\t   nominal keysize is for 2-key 3DES, we have to make the actual size\n\t\t   the maximum size, corresponding to 3-key 3DES */\n\t\tif( keyLength <= bitsToBytes( 64 * 2 ) )\n\t\t\tmemcpy( contextInfoPtr->ctxConv->userKey + bitsToBytes( 64 * 2 ),\n\t\t\t\t\tcontextInfoPtr->ctxConv->userKey, bitsToBytes( 64 ) );\n\t\tkeySize = capabilityInfoPtr->maxKeySize;\n\t\t}\n\n\t/* Import the key via the hideous decrypt-with-exponent-one RSA key \n\t   kludge */\n\tstatus = importPlainKey( cryptoapiInfo->hProv, \n\t\t\t\t\t\t\t cryptoapiInfo->hPrivateKey, \n\t\t\t\t\t\t\t cryptoapiInfo->privateKeySize, &hSessionKey, \n\t\t\t\t\t\t\t capabilityInfoPtr->cryptAlgo, key, keySize, \n\t\t\t\t\t\t\t contextInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Note that the following will break under Win64 since the hKey is\n\t\t   a 64-bit pointer while the deviceObject is a 32-bit unsigned \n\t\t   value, this code is experimental and only enabled for Win32 debug \n\t\t   so this isn't a problem at the moment */\n\t\tcontextInfoPtr->deviceObject = ( long ) hSessionKey;\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( status );\n\t}\n\n/* Set up algorithm-specific encryption parameters */\n\nstatic int initCryptParams( CONTEXT_INFO *contextInfoPtr )\n\t{\n\tenum { CAPI_CRYPT_MODE_NONE, CAPI_CRYPT_MODE_CBC, \n\t\t   CAPI_CRYPT_MODE_ECB, CAPI_CRYPT_MODE_CTR,\n\t\t   CAPI_CRYPT_MODE_CFB };\n\tconst CRYPT_MODE_TYPE mode = contextInfoPtr->ctxConv->mode;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tDWORD dwMode;\n\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* If it's a native stream cipher (rather than a block cipher being run\n\t   in stream cipher mode), there's nothing to do */\n\tif( isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the values from the CryptoAPI header aren't \n\t   overriding the cryptlib values */\n\tassert( CRYPT_MODE_ECB == 1 );\n\tassert( CRYPT_MODE_CBC == 2 );\n\tassert( CRYPT_MODE_CFB == 3 );\n\tassert( CRYPT_MODE_GCM == 4 );\n\n\t/* CryptoAPI uses the same mode names as cryptlib but different values, \n\t   so we have to override the naming with our own names here and then \n\t   map the cryptlib values to the CryptoAPI ones */\n\tswitch( mode )\n\t\t{\n\t\tcase CRYPT_MODE_ECB:\n\t\t\tdwMode = CAPI_CRYPT_MODE_ECB;\n\t\t\tbreak;\n\t\tcase CRYPT_MODE_CBC:\n\t\t\tdwMode = CAPI_CRYPT_MODE_CBC;\n\t\t\tbreak;\n\t\tcase CRYPT_MODE_CFB:\n\t\t\tdwMode = CAPI_CRYPT_MODE_CFB;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\t\t\n\t/* Set the mode parameter for the CryptoAPI object */\n\tif( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE,\n\t\t\t\t\t\t   ( BYTE * ) &dwMode, 0 ) )\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );\n\tif( mode == CRYPT_MODE_CFB )\n\t\t{\n\t\tconst DWORD dwModeBits = capabilityInfoPtr->blockSize * 8;\n\n\t\t/* CryptoAPI defaults to 8-bit feedback for CFB and OFB (!!) so we \n\t\t   have to fix the feedback amount if we're using a stream mode */\n\t\tif( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE_BITS,\n\t\t\t\t\t\t\t   ( BYTE * ) &dwModeBits, 0 ) )\n\t\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );\n\t\t}\n\n\t/* If there's no IV present, we're done */\n\tif( mode == CRYPT_MODE_ECB )\n\t\treturn( CRYPT_OK );\n\n\t/* Set the IV parameter for the CryptoAPI object */\n\tif( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_IV,\n\t\t\t\t\t\t   contextInfoPtr->ctxConv->currentIV, 0 ) )\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* En/decrypt/hash data */\n\nstatic int cipherEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tDWORD resultLength = length;\n\n\t/* Finalise the encryption parameters if necessary.  We couldn't do this\n\t   earlier because the device-level object isn't instantiated until the \n\t   key is loaded */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY_INITED ) )\n\t\t{\n\t\tint status;\n\n\t\tstatus = initCryptParams( contextInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY_INITED );\n\t\t}\n\n\t/* Encrypt the data.  We always set the bFinal flag to FALSE since \n\t   setting it to TRUE tries to apply message padding, resets the IV, and \n\t   various other unwanted side-effects */\n\tif( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer, \n\t\t\t\t\t\t&resultLength, length ) )\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\treturn( CRYPT_OK );\n\t}\n\nstatic int cipherDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tDWORD resultLength = length;\n\n\t/* Finalise the encryption parameters if necessary.  We couldn't do this\n\t   earlier because the device-level object isn't instantiated until the \n\t   key is loaded */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY_INITED ) )\n\t\t{\n\t\tint status;\n\n\t\tstatus = initCryptParams( contextInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_DUMMY_INITED );\n\t\t}\n\n\t/* Decrypt the data.  We always set the bFinal flag to FALSE since \n\t   setting it to TRUE tries to process message padding, resets the IV, \n\t   and various other unwanted side-effects */\n\tif( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer, \n\t\t\t\t\t\t&resultLength ) )\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\t/* Not used, see the comment in the capability information */\n\nstatic int hashFunction( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )\n\t{\n\tif( !pCryptHashData( contextInfoPtr->deviceObject, buffer, length, 0 ) )\n\t\treturn( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Capability Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Templates for the various capabilities.  These contain only basic \n   information, the remaining fields are filled in when the capability is \n   set up */\n\nstatic CAPABILITY_INFO capabilityTemplates[] = {\n\t/* Encryption capabilities */\n\t{ CRYPT_ALGO_3DES, bitsToBytes( 64 ), \"3DES\", 4,\n\t\tbitsToBytes( 64 + 8 ), bitsToBytes( 128 ), bitsToBytes( 192 ) },\n\t{ CRYPT_ALGO_RC2, bitsToBytes( 64 ), \"RC2\", 3,\n\t\tbitsToBytes( 40 ), bitsToBytes( 128 ), bitsToBytes( 1024 ) },\n\t{ CRYPT_ALGO_RC4, bitsToBytes( 8 ), \"RC4\", 3,\n\t\tbitsToBytes( 40 ), bitsToBytes( 128 ), 256 },\n\t{ CRYPT_ALGO_AES, bitsToBytes( 128 ), \"AES\", 3,\n\t\tbitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ) },\n\n\t/* Hash capabilities */\n\t{ CRYPT_ALGO_MD5, bitsToBytes( 128 ), \"MD5\", 3,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },\n\t{ CRYPT_ALGO_SHA1, bitsToBytes( 160 ), \"SHA1\", 3,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },\n\n\t/* Public-key capabilities */\n\t{ CRYPT_ALGO_RSA, bitsToBytes( 0 ), \"RSA\", 3,\n\t\tbitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },\n\t{ CRYPT_ALGO_DSA, bitsToBytes( 0 ), \"DSA\", 3,\n\t\tbitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },\n\n\t/* Hier ist der Mast zu ende */\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n\n/* Mapping of CryptoAPI provider capabilities to cryptlib capabilities */\n\ntypedef struct {\n\t/* Mapping information from CryptoAPI to cryptlib algorithms.  For some\n\t   PKC algorithms CryptoAPI creates two virtual algorithm types (badly,\n\t   it's easily confused between the two), one for signing and one for \n\t   encryption.  The first algorithm type is always the one with \n\t   encryption capability, if there's one with signature capability or \n\t   it's a signature-only algorithm we specify it as the optional \n\t   alternative algorithm type */\n\tconst ALG_ID algoID;\t\t\t\t/* CryptoAPI algorithm type */\n\tconst ALG_ID altAlgoID;\t\t\t\t/* CryptoAPI alt.algorithm type */\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\t/* cryptlib algo and mode */\n\tconst CRYPT_MODE_TYPE cryptMode;\n\n\t/* Function pointers */\n\tint ( *endFunction )( CONTEXT_INFO *contextInfoPtr );\n\tint ( *initKeyFunction )( CONTEXT_INFO *contextInfoPtr, const void *key, const int keyLength );\n\tint ( *generateKeyFunction )( CONTEXT_INFO *contextInfoPtr, const int keySizeBits );\n\tint ( *encryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );\n\tint ( *decryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );\n\tint ( *signFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );\n\tint ( *sigCheckFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );\n\t} MECHANISM_INFO;\n\nstatic const MECHANISM_INFO mechanismInfo[] = {\n\t{ CALG_RSA_KEYX, CALG_RSA_SIGN, CRYPT_ALGO_RSA, CRYPT_MODE_NONE, \n\t  NULL, rsaInitKey, rsaGenerateKey, \n\t  rsaEncrypt, rsaDecrypt, rsaSign, rsaVerify },\n\t{ CALG_NONE, CALG_DSS_SIGN, CRYPT_ALGO_DSA, CRYPT_MODE_NONE, \n\t  NULL, dsaInitKey, dsaGenerateKey, \n\t  NULL, NULL, dsaSign, dsaVerify },\n\t{ CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_ECB, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_CBC, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_ECB, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_ECB, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_CBC, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n\t{ CALG_RC4, CALG_NONE, CRYPT_ALGO_RC4, CRYPT_PSEUDOMODE_RC4, \n\t  genericEndFunction, cipherInitKey, NULL, \n\t  cipherEncrypt, cipherDecrypt, NULL, NULL },\n#if 0\t/* Although CAPI supports the hash mechanisms, as with PKCS #11\n\t\t   we always use cryptlib native contexts for this */\n\t{ CALG_MD5, CALG_NONE, CRYPT_ALGO_MD5, CRYPT_MODE_NONE,\n\t  genericEndFunction, NULL, NULL, \n\t  hashFunction, hashFunction, NULL, NULL },\n\t{ CALG_SHA1, CALG_NONE, CRYPT_ALGO_SHA1, CRYPT_MODE_NONE,\n\t  genericEndFunction, NULL, NULL, \n\t  hashFunction, hashFunction, NULL, NULL },\n#endif /* 0 */\n\t{ CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE },\n\t\t{ CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE }\n\t};\n\n/* Fill out a capability information based on CryptoAPI algorithm \n   information */\n\nstatic CAPABILITY_INFO *addCapability( const DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t\t\t   const PROV_ENUMALGS_EX *capiAlgoInfo,\n\t\t\t\t\t\t\t\t\t   const MECHANISM_INFO *mechanismInfoPtr,\n\t\t\t\t\t\t\t\t\t   const CAPABILITY_INFO *existingCapabilityInfo )\n\t{\n\tVARIABLE_CAPABILITY_INFO *capabilityInfo = \\\n\t\t\t\t\t( VARIABLE_CAPABILITY_INFO * ) existingCapabilityInfo;\n\tint i, LOOP_ITERATOR;\n\n\t/* If it's a new capability, copy across the template for this \n\t   capability */\n\tif( capabilityInfo == NULL )\n\t\t{\n\t\tif( ( capabilityInfo = \\\n\t\t\t\tclAlloc( \"addCapability\", sizeof( CAPABILITY_INFO ) ) ) == NULL )\n\t\t\treturn( NULL );\n\t\tLOOP_MED( i = 0, \n\t\t\t\t  capabilityTemplates[ i ].cryptAlgo != mechanismInfoPtr->cryptAlgo && \\\n\t\t\t\t\tcapabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ), \\\n\t\t\t\t  i++ );\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ) );\n\t\tassert( i < sizeof( capabilityTemplates ) / sizeof( CAPABILITY_INFO ) && \\\n\t\t\t\tcapabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE );\n\t\tmemcpy( capabilityInfo, &capabilityTemplates[ i ],\n\t\t\t\tsizeof( CAPABILITY_INFO ) );\n\t\t}\n\n\t/* Set up the keysize information, limiting the maximum key size to \n\t   match the cryptlib native max.key size, both for consistency and \n\t   because cryptlib performs buffer allocation based on the maximum \n\t   native buffer size.  Since CryptoAPI specifies key sizes for unkeyed \n\t   hash algorithms, we only set the keysize if there's really a key\n\t   present.  In addition it indicates the number of bits involved in \n\t   keying rather than the nominal key size, so we have to adjust the\n\t   reported size to match the conventionally-used value */\n\tif( capabilityInfo->keySize > 0 )\n\t\t{\n\t\tint minKeySize = bitsToBytes( capiAlgoInfo->dwMinLen );\n\t\tint maxKeySize = bitsToBytes( capiAlgoInfo->dwMaxLen );\n\n\t\tif( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_DES && \\\n\t\t\tminKeySize == 7 )\n\t\t\t{\n\t\t\t/* Adjust 56 bits -> 8 bytes */\n\t\t\tminKeySize = maxKeySize = 8;\n\t\t\t}\n\t\tif( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_3DES && \\\n\t\t\tminKeySize == 21 )\n\t\t\t{\n\t\t\t/* Adjust 168 bits -> 24 bytes */\n\t\t\tminKeySize = maxKeySize = 24;\n\t\t\t}\n\t\tif( minKeySize > capabilityInfo->minKeySize )\n\t\t\tcapabilityInfo->minKeySize = minKeySize;\n\t\tif( capabilityInfo->keySize < capabilityInfo->minKeySize )\n\t\t\tcapabilityInfo->keySize = capabilityInfo->minKeySize;\n\t\tcapabilityInfo->maxKeySize = min( maxKeySize, \n\t\t\t\t\t\t\t\t\t\t  capabilityInfo->maxKeySize );\n\t\tif( capabilityInfo->keySize > capabilityInfo->maxKeySize )\n\t\t\tcapabilityInfo->keySize = capabilityInfo->maxKeySize;\n\t\tcapabilityInfo->endFunction = genericEndFunction;\n\t\t}\n\n\t/* Set up the device-specific handlers */\n\tcapabilityInfo->getInfoFunction = getDefaultInfo;\n\tif( mechanismInfoPtr->cryptAlgo != CRYPT_ALGO_RSA && \\\n\t\tmechanismInfoPtr->cryptAlgo != CRYPT_ALGO_DSA )\n\t\tcapabilityInfo->initParamsFunction = initGenericParams;\n\tcapabilityInfo->endFunction = mechanismInfoPtr->endFunction;\n\tcapabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;\n\tcapabilityInfo->generateKeyFunction = mechanismInfoPtr->generateKeyFunction;\n\tif( mechanismInfoPtr->algoID == capiAlgoInfo->aiAlgid )\n\t\t{\n\t\tif( mechanismInfoPtr->cryptMode == CRYPT_MODE_CFB )\n\t\t\t{\n\t\t\t/* Stream ciphers have an implicit mode of CFB */\n\t\t\tcapabilityInfo->encryptCFBFunction = mechanismInfoPtr->encryptFunction;\n\t\t\t}\n\t\telse\n\t\t\tcapabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;\n\t\tif( mechanismInfoPtr->cryptMode == CRYPT_MODE_CFB )\n\t\t\t{\n\t\t\t/* Stream ciphers have an implicit mode of CFB */\n\t\t\tcapabilityInfo->decryptCFBFunction = mechanismInfoPtr->decryptFunction;\n\t\t\t}\n\t\telse\n\t\t\tcapabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;\n\t\tif( mechanismInfoPtr->cryptMode != CRYPT_MODE_NONE )\n\t\t\t{\n\t\t\tcapabilityInfo->encryptCBCFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\tcapabilityInfo->decryptCBCFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n#if 0\t\t/* CAPI requires the encryption of full blocks even in a stream \n\t\t\t   cipher mode, which doesn't match the standard cryptlib \n\t\t\t   behaviour.  To avoid this problem, we mark the stream cipher\n\t\t\t   modes as not available */\n\t\t\tcapabilityInfo->encryptCFBFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\tcapabilityInfo->decryptCFBFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n\t\t\tcapabilityInfo->encryptCTRFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\tcapabilityInfo->decryptCTRFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n#endif /* 0 */\n\t\t\t}\n\t\t}\n\tif( mechanismInfoPtr->altAlgoID == capiAlgoInfo->aiAlgid )\n\t\t{\n\t\tcapabilityInfo->signFunction = mechanismInfoPtr->signFunction;\n\t\tcapabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;\n\t\t}\n\n\treturn( ( CAPABILITY_INFO * ) capabilityInfo );\n\t}\n\n/* Set the capability information based on device capabilities.  Since\n   CryptoAPI devices can have assorted capabilities, we have to build this \n   up on the fly rather than using a fixed table like the built-in \n   capabilities */\n\nstatic void freeCapabilities( DEVICE_INFO *deviceInfo )\n\t{\n\tCAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t( CAPABILITY_INFO_LIST * ) DATAPTR_GET( deviceInfo->capabilityInfoList );\n\n\tREQUIRES_V( DATAPTR_ISVALID( deviceInfo->capabilityInfoList ) );\n\n\t/* If the list was empty, return now */\n\tif( capabilityInfoListPtr == NULL )\n\t\treturn;\n\tDATAPTR_SET( deviceInfo->capabilityInfoList, NULL );\n\n\twhile( capabilityInfoListPtr != NULL )\n\t\t{\n\t\tCAPABILITY_INFO_LIST *listItemToFree = capabilityInfoListPtr;\n\t\tCAPABILITY_INFO *itemToFree = ( CAPABILITY_INFO * ) DATAPTR_GET( listItemToFree->info );\n\n\t\tREQUIRES_V( itemToFree != NULL );\n\t\tREQUIRES_V( DATAPTR_ISVALID( capabilityInfoListPtr->next ) );\n\t\tcapabilityInfoListPtr = DATAPTR_GET( capabilityInfoListPtr->next );\n\n\t\tzeroise( itemToFree, sizeof( CAPABILITY_INFO ) );\n\t\tclFree( \"freeCapabilities\", itemToFree );\n\t\tzeroise( listItemToFree, sizeof( CAPABILITY_INFO_LIST ) );\n\t\tclFree( \"freeCapabilities\", listItemToFree );\n\t\t}\n\t}\n\nstatic int getCapabilities( DEVICE_INFO *deviceInfo )\n\t{\n\tCRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;\n\tCAPABILITY_INFO_LIST *capabilityInfoListTail = \\\n\t\t( CAPABILITY_INFO_LIST * ) DATAPTR_GET( deviceInfo->capabilityInfoList );\n\tconst CAPABILITY_INFO *capabilityInfoPtr = NULL;\n\tPROV_ENUMALGS_EX capiAlgoInfo;\n\tDWORD length = sizeof( PROV_ENUMALGS_EX );\n\tint iterationCount = 0, LOOP_ITERATOR;\n\n\tassert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ) );\n\n\tREQUIRES( capabilityInfoListTail != NULL );\n\n\t/* Step through each available CryptoAPI algorithm type adding the \n\t   appropriate cryptlib capability for it */\n\tif( !pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX, \n\t\t\t\t\t\t\t ( BYTE * ) &capiAlgoInfo, &length, CRYPT_FIRST ) )\n\t\treturn( CRYPT_ERROR );\n\tdo\n\t\t{\n\t\tCAPABILITY_INFO_LIST *newCapabilityList, *capabilityInfoListPtr;\n\t\tCAPABILITY_INFO *newCapability;\n\t\tCRYPT_ALGO_TYPE cryptAlgo;\n\t\tint i;\n\n\t\t/* Check whether this algorithm type corresponds to a cryptlib\n\t\t   capability */\n\t\tLOOP_LARGE( i = 0, mechanismInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO ),\n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( mechanismInfo[ i ].algoID == capiAlgoInfo.aiAlgid || \\\n\t\t\t\t( mechanismInfo[ i ].altAlgoID != CALG_NONE && \\\n\t\t\t\t  mechanismInfo[ i ].altAlgoID == capiAlgoInfo.aiAlgid ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( i >= FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO ) )\n\t\t\tretIntError();\n\t\tif( mechanismInfo[ i ].cryptAlgo == CRYPT_ALGO_NONE )\n\t\t\tcontinue;\n\t\tcryptAlgo = mechanismInfo[ i ].cryptAlgo;\n\n\t\t/* Check whether this is a variation of an existing capability */\n\t\tLOOP_MED( capabilityInfoListPtr = ( CAPABILITY_INFO_LIST * ) \\\n\t\t\t\t\t\tDATAPTR_GET( deviceInfo->capabilityInfoList ), \n\t\t\t\t  capabilityInfoListPtr != NULL,\n\t\t\t\t  capabilityInfoListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( capabilityInfoListPtr->next ) )\n\t\t\t{\n\t\t\tcapabilityInfoPtr = DATAPTR_GET( capabilityInfoListPtr->info );\n\n\t\t\tREQUIRES( capabilityInfoPtr != NULL );\n\t\t\t\n\t\t\tif( capabilityInfoPtr->cryptAlgo == cryptAlgo )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( capabilityInfoListPtr != NULL )\n\t\t\t{\n\t\t\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t\t\taddCapability( deviceInfo, &capiAlgoInfo, &mechanismInfo[ i ], \n\t\t\t\t\t\t   capabilityInfoPtr );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Add capabilities for all mechanisms corresponding to the current\n\t\t   CryptoAPI algorithm type.  If the assertion below triggers then \n\t\t   the CryptoAPI provider is broken since it's returning \n\t\t   inconsistent information such as illegal key length data, \n\t\t   conflicting algorithm information, etc etc.  This assertion is \n\t\t   included here to detect buggy drivers early on rather than \n\t\t   forcing users to step through the CryptoAPI glue code to find out \n\t\t   why an operation is failing.\n\t\t   \n\t\t   Because some providers mapped down to tinkertoy smart cards \n\t\t   support only the bare minimum functionality (e.g.RSA private key \n\t\t   ops and nothing else), we allow asymmetric functionality for \n\t\t   PKCs */\n\t\tnewCapability = addCapability( deviceInfo, &capiAlgoInfo, \n\t\t\t\t\t\t\t\t\t   &mechanismInfo[ i ], NULL );\n\t\tif( newCapability == NULL )\n\t\t\tbreak;\n\t\tREQUIRES( sanityCheckCapability( newCapability ) );\n\t\tif( ( newCapabilityList = \\\n\t\t\t\t\t\tclAlloc( \"getCapabilities\", \\\n\t\t\t\t\t\t\t\t sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"getCapabilities\", newCapability );\n\t\t\tcontinue;\n\t\t\t}\n\t\tDATAPTR_SET( newCapabilityList->info, newCapability );\n\t\tDATAPTR_SET( newCapabilityList->next, NULL );\n\t\tif( DATAPTR_ISNULL( deviceInfo->capabilityInfoList ) )\n\t\t\t{\n\t\t\tDATAPTR_SET( deviceInfo->capabilityInfoList,\n\t\t\t\t\t\t newCapabilityList );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tDATAPTR_SET( capabilityInfoListTail->next, \n\t\t\t\t\t\t newCapabilityList );\n\t\t\t}\n\t\tcapabilityInfoListTail = newCapabilityList;\n\t\t}\n\twhile( pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX, \n\t\t\t\t\t\t\t   ( BYTE * ) &capiAlgoInfo, &length, 0 ) && \\\n\t\t   iterationCount++ < FAILSAFE_ITERATIONS_LARGE );\n\tif( iterationCount >= FAILSAFE_ITERATIONS_LARGE )\n\t\tretIntError();\n\n\treturn( ( DATAPTR_ISNULL( deviceInfo->capabilityInfoList ) ) ? \\\n\t\t\tCRYPT_ERROR : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Mechanisms supported by CryptoAPI devices.  These are actually cryptlib \n   native mechanisms since many aren't supported by CryptoAPI, but not the \n   full set supported by the system device since functions like private key \n   export aren't available except in the nonstandard blob format invented \n   by Microsoft.  The list is sorted in order of frequency of use in order \n   to make lookups a bit faster */\n\nstatic const MECHANISM_FUNCTION_INFO mechanismFunctions[] = {\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },\n#endif /* USE_SSL && USE_RSA_SUITES */\n#ifdef USE_PGP\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },\n#endif /* USE_PGP */\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PBKDF2, ( MECHANISM_FUNCTION ) derivePBKDF2 },\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },\n#endif /* USE_PGP || USE_PGPKEYS */\n#ifdef USE_SSL\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveSSL },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveTLS },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },\n#endif /* USE_SSL */\n#ifdef USE_CMP\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },\n#endif /* USE_CMP */\n#ifdef USE_PKCS12\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },\n#endif /* USE_PKCS12 */\n\t{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }\n\t};\n\n/* Set up the function pointers to the device methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setDeviceCryptoAPI( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\t/* Make sure that the CryptoAPI driver DLL is loaded */\n\tif( hCryptoAPI == NULL_HINSTANCE )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\tFNPTR_SET( deviceInfo->initFunction, initFunction );\n\tFNPTR_SET( deviceInfo->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( deviceInfo->controlFunction, controlFunction );\n\tFNPTR_SET( deviceInfo->getItemFunction, getItemFunction );\n\tFNPTR_SET( deviceInfo->setItemFunction, setItemFunction );\n\tFNPTR_SET( deviceInfo->deleteItemFunction, deleteItemFunction );\n\tFNPTR_SET( deviceInfo->getFirstItemFunction, getFirstItemFunction );\n\tFNPTR_SET( deviceInfo->getNextItemFunction, getNextItemFunction );\n\tFNPTR_SET( deviceInfo->getRandomFunction, getRandomFunction );\n\tdeviceInfo->mechanismFunctions = mechanismFunctions;\n\tdeviceInfo->mechanismFunctionCount = \\\n\t\tFAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CRYPTOAPI */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib PKCS #11 Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"pkcs11_api.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/pkcs11_api.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n/* Define the following to generate conventional/MAC keys inside the PKCS \n   #11 device rather than in cryptlib.  Note that this imposes a number of\n   restrictions on the use of encryption keys, see the note for\n   cipherGenerateKey() for more details */\n\n#define USE_HW_KEYGEN\n\n/* Some devices use extended login mechanisms to get around PKCS #11's\n   somewhat-simplistic username-and-password model, if we detect the\n   presence of the extended mechanism we enable extended-login\n   functionality */\n\n#if 0\t\t/* Private vendor #1's extensions for token login */\n#define CKU_EXTENDED\t\t3\n/* When CKU_EXTENDED is used, the data passed to C_Login() is no longer a\n   straight string but the following structured value */\ntypedef struct {\n\tCK_UTF8CHAR_PTR\t*username;\t/* User name */\n\tCK_ULONG name_len;\t\t\t/* Length of user name */\n\tCK_VOID_PTR context;\t\t/* Token-specific context data */\n\tCK_ULONG context_size;\t\t/* Size of context data */\n\t} CK_EXTENDED_LOGIN;\n#endif /* 0 */\n\n#ifdef CKU_EXTENDED\n  #define USE_EXTENDED_LOGIN\n#endif /* CKU_EXTENDED */\n\n#ifdef USE_PKCS11\n\n/* The max. number of drivers we can work with and the max.number of slots\n   per driver */\n\n#define MAX_PKCS11_DRIVERS\t\t5\n#define MAX_PKCS11_SLOTS\t\t16\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Map a PKCS #11-specific error to a cryptlib error */\n\nCHECK_RETVAL \\\nint pkcs11MapError( const CK_RV errorCode,\n\t\t\t\t\tIN_STATUS const int defaultError )\n\t{\n\tREQUIRES( cryptStatusError( defaultError ) );\n\tREQUIRES( isIntegerRange( errorCode ) );\n\n\tswitch( ( int ) errorCode )\n\t\t{\n\t\tcase CKR_OK:\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CKR_HOST_MEMORY:\n\t\tcase CKR_DEVICE_MEMORY:\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t\tcase CKR_DEVICE_ERROR:\n\t\tcase CKR_DEVICE_REMOVED:\n\t\tcase CKR_TOKEN_NOT_PRESENT:\n\t\t\treturn( CRYPT_ERROR_SIGNALLED );\n\n\t\tcase CKR_PIN_INCORRECT:\n\t\tcase CKR_PIN_INVALID:\n\t\tcase CKR_PIN_LEN_RANGE:\n\t\tcase CKR_PIN_EXPIRED:\n\t\tcase CKR_PIN_LOCKED:\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t\tcase CKR_DATA_INVALID:\n\t\tcase CKR_ENCRYPTED_DATA_INVALID:\n\t\tcase CKR_WRAPPED_KEY_INVALID:\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\tcase CKR_SIGNATURE_INVALID:\n\t\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\t\tcase CKR_KEY_NOT_WRAPPABLE:\n\t\tcase CKR_KEY_UNEXTRACTABLE:\n\t\tcase CKR_TOKEN_WRITE_PROTECTED:\n\t\tcase CKR_INFORMATION_SENSITIVE:\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t\tcase CKR_DATA_LEN_RANGE:\n\t\tcase CKR_ENCRYPTED_DATA_LEN_RANGE:\n\t\tcase CKR_SIGNATURE_LEN_RANGE:\n\t\tcase CKR_UNWRAPPING_KEY_SIZE_RANGE:\n\t\tcase CKR_WRAPPING_KEY_SIZE_RANGE:\n\t\tcase CKR_WRAPPED_KEY_LEN_RANGE:\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\tcase CKR_SESSION_EXISTS:\n\t\tcase CKR_SESSION_READ_ONLY_EXISTS:\n\t\tcase CKR_SESSION_READ_WRITE_SO_EXISTS:\n\t\tcase CKR_USER_ALREADY_LOGGED_IN:\n\t\tcase CKR_USER_ANOTHER_ALREADY_LOGGED_IN:\n\t\tcase CKR_CRYPTOKI_NOT_INITIALIZED:\n\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\tcase CKR_USER_NOT_LOGGED_IN:\n\t\tcase CKR_USER_PIN_NOT_INITIALIZED:\n\t\tcase CKR_CRYPTOKI_ALREADY_INITIALIZED:\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t\tcase CKR_RANDOM_NO_RNG:\n\t\t\treturn( CRYPT_ERROR_RANDOM );\n\n\t\tcase CKR_OPERATION_ACTIVE:\n\t\t\treturn( CRYPT_ERROR_TIMEOUT );\n\n\t\tcase CKR_TOKEN_NOT_RECOGNIZED:\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\treturn( defaultError );\n\t}\n\n/* Extract the time from a PKCS #11 tokenInfo structure */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\ntime_t getTokenTime( const CK_TOKEN_INFO *tokenInfo )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 32 + 8 ];\n\ttime_t theTime = MIN_TIME_VALUE + 1;\n\tint length DUMMY_INIT, status;\n\n\tassert( isReadPtr( tokenInfo, sizeof( CK_TOKEN_INFO ) ) );\n\n\t/* Convert the token time to an ASN.1 time string that we can read using\n\t   the standard ASN.1 routines by writing a dummy time value and inserting \n\t   the token's time string in its place */\n\tsMemOpen( &stream, buffer, 32 );\n\tstatus = writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( 0 );\n\tmemcpy( buffer + 2, tokenInfo->utcTime, 14 );\n\tsMemConnect( &stream, buffer, length );\n\tstatus = readGeneralizedTime( &stream, &theTime );\n\tsMemDisconnect( &stream );\n\t\n\treturn( ( cryptStatusOK( status ) ) ? theTime : 0 );\n\t}\n\n/* Get access to the PKCS #11 device associated with a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getContextDeviceInfo( IN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_DEVICE *iCryptDevice, \n\t\t\t\t\t\t  OUT_PTR_COND PKCS11_INFO **pkcs11InfoPtrPtr )\n\t{\n\tCRYPT_DEVICE iLocalDevice;\n\tDEVICE_INFO *deviceInfo;\n\tint cryptStatus;\n\n\tassert( isWritePtr( iCryptDevice, sizeof( CRYPT_DEVICE ) ) );\n\tassert( isWritePtr( pkcs11InfoPtrPtr, sizeof( PKCS11_INFO * ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Clear return values */\n\t*iCryptDevice = CRYPT_ERROR;\n\t*pkcs11InfoPtrPtr = NULL;\n\n\t/* Get the the device associated with this context */\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t   &iLocalDevice, OBJECT_TYPE_DEVICE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Get the PKCS #11 information from the device information */\n\tcryptStatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE, \n\t\t\t\t\t\t\t\t\t ( MESSAGE_PTR_CAST ) &deviceInfo, \n\t\t\t\t\t\t\t\t\t CRYPT_ERROR_SIGNALLED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\t*iCryptDevice = iLocalDevice;\n\t*pkcs11InfoPtrPtr = deviceInfo->devicePKCS11;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create and try and use a dummy object to check for various PKCS #11 \n   driver bugs.  Note that this can produce false positives with, \n   unfortunately, no workaround, see the long comment for \n   CRYPT_DEVINFO_INITIALISE in the controlFunction() below for details */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDriverBugs( const PKCS11_INFO *pkcs11Info )\n\t{\n\tstatic const CK_OBJECT_CLASS class = CKO_SECRET_KEY;\n\tconst CK_KEY_TYPE type = CKK_DES;\n\tstatic const CK_BBOOL bFalse = CK_FALSE, bTrue = CK_TRUE;\n\tconst CK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE, \"12345678\", 8 }\t/* Dummy key value */\n\t\t};\n\tconst CK_MECHANISM mechanism = { CKM_DES_ECB, NULL, 0 };\n\tCK_OBJECT_HANDLE hObject;\n\tCK_RV status;\n\n\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\t/* Try and create the sort of object that'd normally require a login.  \n\t   This can fail for reasons other than driver bugs (for example DES \n\t   isn't supported for this token type) so we only check for the \n\t   specific error code returned by a login bug */\n\tstatus = C_CreateObject( pkcs11Info->hSession, \n\t\t\t\t\t\t\t ( CK_ATTRIBUTE_PTR ) keyTemplate, 7, &hObject );\n\tif( status == CKR_USER_NOT_LOGGED_IN )\n\t\t{\n\t\tDEBUG_DIAG(( \"PKCS #11 driver bug detected, attempt to log in to \"\n\t\t\t\t\t \"the device apparently succeeded but logged-on \"\n\t\t\t\t\t \"operation failed with CKR_USER_NOT_LOGGED_IN\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\tENSURES( hObject != CK_OBJECT_NONE );\n\n\t/* Try and use the object to encrypt data (or at least call the pre-\n\t   encrypt call, which should be enough to shake out most bugs) */\n\tstatus = C_EncryptInit( pkcs11Info->hSession, \n\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism, hObject );\n\tC_DestroyObject( pkcs11Info->hSession, hObject );\n\tif( status != CKR_OK )\n\t\t{\n\t\tDEBUG_DIAG(( \"PKCS #11 driver bug detected, attempt to use object \"\n\t\t\t\t\t \"in logged-in device failed with error code %lX, this \"\n\t\t\t\t\t \"can happen when using C_InitToken() rather than the \"\n\t\t\t\t\t \"proprietary vendor-supplied utility to initialise \"\n\t\t\t\t\t \"the device\", status ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDevice Init/Shutdown/Device Control Routines\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle device control functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int controlFunction( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( dataLength ) void *data, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataLength,\n\t\t\t\t\t\t\tINOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tCK_RV status;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isAttribute( type ) || isInternalAttribute( type ) );\n\n\t/* Handle token present/active checks */\n\tif( type == CRYPT_DEVINFO_LOGGEDIN )\n\t\t{\n\t\tCK_TOKEN_INFO tokenInfo;\n\t\tCK_SLOT_INFO slotInfo;\n\n\t\t/* Check whether the user is still logged in.  This is rather \n\t\t   problematic because some devices can't detect a token removal, \n\t\t   and if they do they often can't report it to the driver.  It's \n\t\t   also possible in some devices to remove the token and re-insert \n\t\t   it later without that being regarded as logging out (or you can \n\t\t   remove the smart card and insert your frequent flyer card and \n\t\t   it's still regarded as a card present).  In addition if the \n\t\t   reader supports its own authentication mechanisms (even if it \n\t\t   forces a logout if the token is removed) it's possible for the \n\t\t   user to reinsert the token and reauthenticate themselves and it \n\t\t   appears as if they never logged out.  In fact the only totally \n\t\t   foolproof way to detect a token removal/change is to try and use \n\t\t   the token to perform a crypto operation, which is a rather \n\t\t   suboptimal detection mechanism.\n\n\t\t   Because of this, the best that we can do here is check the token-\n\t\t   present flag and report a token-changed error if it's not set.  \n\t\t   In addition since some devices only do a minimal check with\n\t\t   C_GetSlotInfo() (e.g. checking whether a microswitch is held\n\t\t   open by something in the slot, see above) we first call\n\t\t   C_GetTokenInfo(), which has a greater chance of actually trying\n\t\t   to access the token, before we call C_GetSlotInfo().\n\n\t\t   If there's a problem reported, we don't perform an implicit \n\t\t   shutdown since the user may choose to re-authenticate to the \n\t\t   device or perform some other action that we have no control over \n\t\t   in response to the token-removed notification */\n\t\tstatus = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );\n\t\tstatus = C_GetSlotInfo( pkcs11Info->slotID, &slotInfo );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );\n\t\tif( !( slotInfo.flags & CKF_TOKEN_PRESENT ) )\n\t\t\treturn( CRYPT_ERROR_SIGNALLED );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle user authorisation */\n\tif( type == CRYPT_DEVINFO_AUTHENT_USER || \\\n\t\ttype == CRYPT_DEVINFO_AUTHENT_SUPERVISOR )\n\t\t{\n#ifdef USE_EXTENDED_LOGIN\n\t\tconst CK_USER_TYPE userType = CKU_EXTENDED;\n#else\n\t\tconst CK_USER_TYPE userType = \\\n\t\t\t\t( type == CRYPT_DEVINFO_AUTHENT_USER ) ? CKU_USER : CKU_SO;\n#endif /* USE_EXTENDED_LOGIN */\n\t\t\n\t\tREQUIRES( data != NULL );\n\n\t\t/* Make sure that the PIN is within range */\n\t\tif( dataLength < pkcs11Info->minPinSize || \\\n\t\t\tdataLength > pkcs11Info->maxPinSize )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* If the user is already logged in, log them out before we try\n\t\t   logging in with a new authentication value */\n\t\tif( TEST_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN ) )\n\t\t\t{\n\t\t\tC_Logout( pkcs11Info->hSession );\n\t\t\tCLEAR_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN );\n\t\t\t}\n\n\t\t/* Authenticate the user to the device */\n\t\tstatus = C_Login( pkcs11Info->hSession, userType, \n\t\t\t\t\t\t  ( CK_CHAR_PTR ) data,\n\t\t\t\t\t\t  ( CK_ULONG ) dataLength );\n\t\tif( status != CKR_OK )\n\t\t\t{\n\t\t\tint cryptStatus;\n\n\t\t\t/* The check for CKR_USER_ALREADY_LOGGED_IN is logical since we \n\t\t\t   may already be logged in from another session, however \n\t\t\t   several buggy drivers return CKR_USER_ALREADY_LOGGED_IN \n\t\t\t   without actually logging the user in so that all further \n\t\t\t   operations fail with CKR_USER_NOT_LOGGED_IN.  To try and\n\t\t\t   detect this, if we get a CKR_USER_ALREADY_LOGGED_IN we try\n\t\t\t   and create the sort of object that's likely to require a\n\t\t\t   login and use that to see whether we're really logged in or\n\t\t\t   not */\n\t\t\tif( status != CKR_USER_ALREADY_LOGGED_IN )\n\t\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\t\tcryptStatus = checkDriverBugs( pkcs11Info );\n\t\t\treturn( cryptStatusError( cryptStatus ) ? \\\n\t\t\t\t\tcryptStatus : CRYPT_ERROR_FAILED );\n\t\t\t}\n\n\t\t/* The device is now ready for use */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle authorisation value changes.  The initialise SO/user PIN \n\t   functionality is a bit awkward in that it has to fill the gap between \n\t   C_InitToken() (which usually sets the SSO PIN but may also take an\n\t   initialisation PIN and leave the token in a state where the only valid\n\t   operation is to set the SSO PIN) and C_SetPIN() (which can only set the \n\t   SSO PIN for the SSO or the user PIN for the user).  Setting the user \n\t   PIN by the SSO, which is usually required to perform any useful (non-\n\t   administrative) function with the token, requires the special-case \n\t   C_InitPIN().  In addition we can't speculatively set the user PIN to \n\t   be the same as the SSO PIN (which would be useful because in most \n\t   cases the user *is* the SSO, thus ensuring that the device behaves as \n\t   expected when the user isn't even aware that there are SSO and user \n\t   roles) because devices that implement an FSM for initialisation will \n\t   move into an undesired state once the SSO -> user change is triggered.\n\n\t   The FSM for initialisation on devices that perform a multi-stage\n\t   bootstrap and require all of the various intialisation functions to\n\t   be used one after the other (e.g. Fortezza) is:\n\n\t\t\tuninitialised/zeroised\n\t\t\t\t\tv\n\t\t\t\tC_InitToken\t\t\t(enter init or SSO PIN)\n\t\t\t\t\tv\n\t\t\t\tinitialised\n\t\t\t\t\tv\n\t\t\t\tC_SetPIN\t\t\t(change init PIN -> SSO PIN)\n\t\t\t\t\tv\n\t\t\t  SSO initialised\n\t\t\t\t\tv\n\t\t\t\tC_InitPIN\t\t\t(set user PIN)\n\t\t\t\t\tv\n\t\t\t  user initialised\n\t\t\t\t\tv\n\t\t\t\tC_Logout\n\t\t\t\tC_Login\t\t\t\t(move from SO -> user state)\n\n\t\tThe final logout/login is only needed with some tokens, in others\n\t\tthe move to user state is automatic once the user PIN is set by the\n\t\tSO */\n\tif( type == CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR )\n\t\t{\n\t\tREQUIRES( data != NULL );\n\n\t\t/* Make sure that the PIN is within range */\n\t\tif( dataLength < pkcs11Info->minPinSize || \\\n\t\t\tdataLength > pkcs11Info->maxPinSize )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* Make sure that there's an SSO PIN present from a previous device\n\t\t   initialisation */\n\t\tif( pkcs11Info->defaultSSOPinLen <= 0 )\n\t\t\t{\n\t\t\tsetErrorInfo( deviceInfo, CRYPT_DEVINFO_INITIALISE, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\n\t\t/* Change the SSO PIN from the initialisation PIN.  Once we've done \n\t\t   this we clear the initial SSO PIN, since it's no longer valid in \n\t\t   the new state */\n\t\tstatus = C_SetPIN( pkcs11Info->hSession, \n\t\t\t\t\t\t   ( CK_CHAR_PTR ) pkcs11Info->defaultSSOPin,\n\t\t\t\t\t\t   pkcs11Info->defaultSSOPinLen, \n\t\t\t\t\t\t   ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );\n\t\tzeroise( pkcs11Info->defaultSSOPin, CRYPT_MAX_TEXTSIZE );\n\t\tpkcs11Info->defaultSSOPinLen = 0;\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\t}\n\tif( type == CRYPT_DEVINFO_SET_AUTHENT_USER )\n\t\t{\n\t\tREQUIRES( data != NULL );\n\n\t\t/* Make sure that the PIN is within range */\n\t\tif( dataLength < pkcs11Info->minPinSize || \\\n\t\t\tdataLength > pkcs11Info->maxPinSize )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\tstatus = C_InitPIN( pkcs11Info->hSession, ( CK_CHAR_PTR ) data, \n\t\t\t\t\t\t\t( CK_ULONG ) dataLength );\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\t}\n\n\t/* Handle initialisation and zeroisation */\n\tif( type == CRYPT_DEVINFO_INITIALISE || \\\n\t\ttype == CRYPT_DEVINFO_ZEROISE )\n\t\t{\n\t\tCK_SESSION_HANDLE hSession;\n\t\tCK_CHAR label[ 32 + 8 ];\n\t\tint cryptStatus;\n\n\t\tREQUIRES( data != NULL );\n\n\t\t/* Make sure that the PIN is within range */\n\t\tif( dataLength < pkcs11Info->minPinSize || \\\n\t\t\tdataLength > pkcs11Info->maxPinSize )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* If there's a session active with the device, log out and terminate\n\t\t   the session, since the token initialisation will reset this */\n\t\tif( pkcs11Info->hSession != CK_OBJECT_NONE )\n\t\t\t{\n\t\t\tC_Logout( pkcs11Info->hSession );\n\t\t\tC_CloseSession( pkcs11Info->hSession );\n\t\t\tpkcs11Info->hSession = CK_OBJECT_NONE;\n\t\t\t}\n\n\t\t/* Initialise/clear the device, setting the initial SSO PIN */\n\t\tmemset( label, ' ', 32 );\n\t\tstatus = C_InitToken( pkcs11Info->slotID, \n\t\t\t\t\t\t\t  ( CK_CHAR_PTR ) data,\n\t\t\t\t\t\t\t  ( CK_ULONG ) dataLength, label );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\t\t/* Reopen the session with the device */\n\t\tstatus = C_OpenSession( pkcs11Info->slotID,\n\t\t\t\t\t\t\t\tCKF_RW_SESSION | CKF_SERIAL_SESSION,\n\t\t\t\t\t\t\t\tNULL_PTR, NULL_PTR, &hSession );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_OPEN ) );\n\t\tENSURES( hSession != CK_OBJECT_NONE );\n\t\tpkcs11Info->hSession = hSession;\n\n\t\t/* If it's a straight zeroise, we're done */\n\t\tif( type == CRYPT_DEVINFO_ZEROISE )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* We're initialising it, log in as supervisor.  In theory we could \n\t\t   also set the initial user PIN to the same as the SSO PIN at this\n\t\t   point because the user usually won't be aware of the presence of\n\t\t   an SSO role or the need to set a PIN for it, but this can run into\n\t\t   problems with tokens that only allow the user PIN to be modified\n\t\t   by the SSO after they've set it for the first time, so if the user\n\t\t   *is* aware of the existence of an SSO role then once they log in\n\t\t   as SSO they can no longer set the user PIN */\n\t\tstatus = C_Login( pkcs11Info->hSession, CKU_SO,\n\t\t\t\t\t\t  ( CK_CHAR_PTR ) data, ( CK_ULONG ) dataLength );\n\t\tif( status != CKR_OK )\n\t\t\t{\n\t\t\tC_Logout( pkcs11Info->hSession );\n\t\t\tC_CloseSession( pkcs11Info->hSession );\n\t\t\tpkcs11Info->hSession = CK_OBJECT_NONE;\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\t\t}\n\n\t\t/* Remember the default SSO PIN for use with a future C_SetPIN() */\n\t\tREQUIRES( rangeCheck( dataLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( pkcs11Info->defaultSSOPin, data, dataLength );\n\t\tpkcs11Info->defaultSSOPinLen = dataLength;\n\n\t\t/* A number of PKCS #11 devices can't actually be initialised \n\t\t   through C_InitToken() but require a vendor-supplied proprietary\n\t\t   application to do this, apparently succeeding with C_InitToken() \n\t\t   but then failing in various strange and unpredictable ways later\n\t\t   on.  We try and detect this situation here by creating a dummy\n\t\t   object in the device and trying to use it.\n\t\t   \n\t\t   This can, unfortunately, lead to a second type of problem.  If\n\t\t   the device doesn't allow object creation under an SO login then\n\t\t   it looks like we've got a buggy driver.  The alternative to \n\t\t   checking here, waiting for a user login, also doesn't work \n\t\t   because by then the caller will have performed SO operations that\n\t\t   will have failed in the presence of a buggy driver \n\t\t   \n\t\t   At the moment there's no much that we can do about this, \n\t\t   checkDriverBugs() logs diagnostic information about the problem\n\t\t   and if necessary and it's known that C_InitToken() actually\n\t\t   works this call can be disabled */\n\t\tcryptStatus = checkDriverBugs( pkcs11Info );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\n\t\t/* We're logged in and ready to go */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle high-reliability time */\n\tif( type == CRYPT_IATTRIBUTE_TIME )\n\t\t{\n\t\tCK_TOKEN_INFO tokenInfo;\n\t\ttime_t *timePtr = ( time_t * ) data, theTime;\n\n\t\tREQUIRES( data != NULL );\n\n\t\t/* Get the token's time, returned as part of the token information \n\t\t   structure */\n\t\tstatus = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_SIGNALLED ) );\n\t\tif( ( theTime = getTokenTime( &tokenInfo ) ) <= MIN_TIME_VALUE )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t*timePtr = theTime;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tCapability Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt, decrypt */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int genericEncrypt( const PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const CK_MECHANISM *pMechanism, \n\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) void *buffer,\n\t\t\t\t\t\t   IN_LENGTH const int length, \n\t\t\t\t\t\t   IN_LENGTH const int outLength )\n\t{\n\tCK_ULONG resultLen = outLength;\n\tCK_RV status;\n\n\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( length == outLength );\n\n\tstatus = C_EncryptInit( pkcs11Info->hSession,\n\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t\tcontextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\tstatus = C_Encrypt( pkcs11Info->hSession, buffer, length,\n\t\t\t\t\t\t\tbuffer, &resultLen );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int genericDecrypt( const PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t   const CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const CK_MECHANISM *pMechanism, \n\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) void *buffer,\n\t\t\t\t\t\t   IN_LENGTH const int length )\n\t{\n\tCK_ULONG resultLen = length;\n\tCK_RV status;\n\n\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\n\tstatus = C_DecryptInit( pkcs11Info->hSession,\n\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t\tcontextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\tstatus = C_Decrypt( pkcs11Info->hSession, buffer, length,\n\t\t\t\t\t\t\tbuffer, &resultLen );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Clean up the object associated with a context.  The CONTEXT_INFO * is\n   actually a const in this case but we need to leave it non-const to make\n   it type-compatible with the function pointer in the CONTEXT_INFO */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint genericEndFunction( /* const */ INOUT CONTEXT_INFO *contextInfoPtr )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tint cryptStatus;\n\n\tassert( isReadPtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* Since the device object that corresponds to the cryptlib object is\n\t   created on-demand, it may not exist yet if the action that triggers\n\t   the on-demand creation hasn't been taken yet.  If no device object\n\t   exists, we're done */\n\tif( contextInfoPtr->deviceObject == CRYPT_ERROR )\n\t\treturn( CRYPT_OK );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* If we're deleting an object that's in the middle of a multi-stage \n\t   operation, record the fact that the operation has now ended.  We\n\t   have to perform this tracking explicitly since PKCS #11 only allows\n\t   one multi-stage operation per session */\n\tif( pkcs11Info->hActiveSignObject == contextInfoPtr->deviceObject )\n\t\tpkcs11Info->hActiveSignObject = CK_OBJECT_NONE;\n\n\t/* If this is a persistent object, we can't destroy it.  This is a bit\n\t   problematic since PKCS #11 doesn't differentiate between releasing\n\t   an object handle and destroying (deleting) it, which means that\n\t   repeatedly instantiating a persistent object (via getItemFunction())\n\t   and then destroying it leaks a PKCS #11 handle each time.  \n\t   Unfortunately there's nothing that we can do about this since the\n\t   problem lies at the PKCS #11 level */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Destroy the object */\n\tC_DestroyObject( pkcs11Info->hSession, contextInfoPtr->deviceObject );\n\tif( contextInfoPtr->altDeviceObject != CK_OBJECT_NONE )\n\t\t{\n\t\tC_DestroyObject( pkcs11Info->hSession, \n\t\t\t\t\t\t contextInfoPtr->altDeviceObject );\n\t\t}\n\tkrnlReleaseObject( iCryptDevice );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tConventional Crypto/MAC Key Load Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a PKCS #11 mechanism corresponding to a cryptlib algorithm and \n   optional mode */\n\ntypedef enum { MECH_NONE, MECH_CONV, MECH_MAC, MECH_CONV_KEYGEN, \n\t\t\t   MECH_MAC_KEYGEN, MECH_LAST } GETMECH_TYPE;\n\nstatic CK_MECHANISM_TYPE getMechanism( const GETMECH_TYPE mechType,\n\t\t\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t\t   IN_MODE const CRYPT_MODE_TYPE cryptMode );\n\n/* Set up a key template and context information in preparation for creating \n   a device object */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void adjustKeyParity( INOUT_BUFFER_FIXED( length ) BYTE *key, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int length )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( key, length ) );\n\n\tREQUIRES_V( isShortIntegerRangeNZ( length ) );\n\n\t/* Adjust a key to have odd parity, needed for DES keys */\n\tLOOP_MED( i = 0, i < length, i++ )\n\t\t{\n\t\tint ch = byteToInt( key[ i ] );\n\t\t\n\t\tch = ( ch & 0x55 ) + ( ( ch >> 1 ) & 0x55 );\n\t\tch = ( ch & 0x33 ) + ( ( ch >> 2 ) & 0x33 );\n\t\tif( !( ( ch + ( ch >> 4 ) ) & 0x01 ) )\n\t\t\tkey[ i ] ^= 1;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\n/* Load a key into a device object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int initKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\tINOUT_ARRAY( templateCount ) \\\n\t\t\t\t\t\tCK_ATTRIBUTE *keyTemplate, \n\t\t\t\t\tIN_RANGE( 4, 10 ) const int templateCount, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCK_OBJECT_HANDLE hObject;\n\tCK_RV status;\n\tBYTE *contextKeyPtr;\n\tint *contextKeyLenPtr;\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint keySize, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( keyTemplate, \\\n\t\t\t\t\t\t\t   templateCount * sizeof( CK_ATTRIBUTE ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( templateCount >= 8 && templateCount <= 10 );\n\tREQUIRES( isShortIntegerRangeNZ( keyLength ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tcryptAlgo = capabilityInfoPtr->cryptAlgo;\n\tkeySize = ( cryptAlgo == CRYPT_ALGO_DES || \\\n\t\t\t\tcryptAlgo == CRYPT_ALGO_3DES ) ? \\\n\t\t\t\tcapabilityInfoPtr->keySize : keyLength;\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up pointers to the appropriate object sub-type data */\n\tif( contextInfoPtr->type == CONTEXT_CONV )\n\t\t{\n\t\tcontextKeyPtr = contextInfoPtr->ctxConv->userKey;\n\t\tcontextKeyLenPtr = &contextInfoPtr->ctxConv->userKeyLength;\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( contextInfoPtr->type == CONTEXT_MAC );\n\n\t\tcontextKeyPtr = contextInfoPtr->ctxMAC->userKey;\n\t\tcontextKeyLenPtr = &contextInfoPtr->ctxMAC->userKeyLength;\n\t\t}\n\n\t/* Copy the key to internal storage */\n\tif( contextKeyPtr != key )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyLength, 1, CRYPT_MAX_KEYSIZE ) );\n\t\tmemcpy( contextKeyPtr, key, keyLength );\n\t\t}\n\t*contextKeyLenPtr = keyLength;\n\n\t/* Special-case handling for 2-key vs.3-key 3DES */\n\tif( cryptAlgo == CRYPT_ALGO_3DES )\n\t\t{\n\t\t/* If the supplied key contains only two DES keys, adjust the key to \n\t\t   make it the equivalent of 3-key 3DES.  In addition since the \n\t\t   nominal keysize is for 2-key 3DES, we have to make the actual \n\t\t   size the maximum size, corresponding to 3-key 3DES */\n\t\tif( keyLength <= bitsToBytes( 64 * 2 ) )\n\t\t\t{\n\t\t\tmemcpy( contextKeyPtr + bitsToBytes( 64 * 2 ),\n\t\t\t\t\tcontextKeyPtr, bitsToBytes( 64 ) );\n\t\t\t}\n\t\tkeySize = capabilityInfoPtr->maxKeySize;\n\t\t}\n\n\t/* If we're using DES we have to adjust the key parity because the spec \n\t   says so, almost all implementations do this anyway but there's always \n\t   the odd one out that we have to cater for */\n\tif( cryptAlgo == CRYPT_ALGO_DES || cryptAlgo == CRYPT_ALGO_3DES )\n\t\tadjustKeyParity( contextKeyPtr, keySize );\n\n\t/* Set up the key values.  Since the key passed in by the user may be \n\t   smaller than the keysize required by algorithms that use fixed-size \n\t   keys, we use the (optionally) zero-padded key of the correct length \n\t   held in the context rather than the variable-length user-supplied \n\t   one */\n\tREQUIRES( keyTemplate[ 7 ].type == CKA_VALUE );\n\tkeyTemplate[ 7 ].pValue = contextKeyPtr;\n\tkeyTemplate[ 7 ].ulValueLen = keySize;\n\n\t/* Load the key into the token */\n\tstatus = C_CreateObject( pkcs11Info->hSession, keyTemplate, \n\t\t\t\t\t\t\t templateCount, &hObject );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tENSURES( hObject != CK_OBJECT_NONE );\n\n\t\tcontextInfoPtr->deviceObject = hObject;\n\t\t}\n\telse\n\t\t{\n\t\tzeroise( contextInfoPtr->ctxConv->userKey, keyLength );\n\t\tcontextInfoPtr->ctxConv->userKeyLength = 0;\n\t\t}\n\tzeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherInitKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyLength )\n\t{\n\tstatic const CK_OBJECT_CLASS class = CKO_SECRET_KEY;\n\tstatic const CK_BBOOL bFalse = CK_FALSE, bTrue = CK_TRUE;\n\tCK_KEY_TYPE type;\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t/* General-purpose fields */\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE, NULL_PTR, 0 },\n\t\t/* Persistent-object only fields */\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }\n\t\t};\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int templateCount = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( keyLength ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\ttype = capabilityInfoPtr->paramKeyType;\n\n\t/* If this is meant to be a persistent object, modify the template to \n\t   make it a persistent token object and adjust the template entry count\n\t   to include the object label */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\tkeyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;\n\n\treturn( initKey( contextInfoPtr, keyTemplate, templateCount, \n\t\t\t\t\t key, keyLength ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hmacInitKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tstatic const CK_OBJECT_CLASS class = CKO_SECRET_KEY;\n\tstatic const CK_BBOOL bFalse = CK_FALSE, bTrue = CK_TRUE;\n\tCK_KEY_TYPE type;\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t/* General-purpose fields */\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE, NULL_PTR, 0 },\n\t\t/* Persistent-object only fields */\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }\n\t\t};\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int templateCount = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( keyLength ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\ttype = capabilityInfoPtr->paramKeyType;\n\n\t/* If this is meant to be a persistent object, modify the template to \n\t   make it a persistent token object and adjust the template entry count\n\t   to include the object label */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\tkeyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;\n\n\treturn( initKey( contextInfoPtr, keyTemplate, templateCount, \n\t\t\t\t\t key, keyLength ) );\n\t}\n\n/* Generate a key into a device object.  Normally we generate keys inside\n   cryptlib and load them into the device object (so a keygen becomes a\n   keygen inside cryptlib followed by a cipherInitKey()) in order to make \n   sure that the key data is accessible from the context.  If we didn't do \n   this, the user would have to be very careful to perform all key wrap/\n   unwrap operations only via device objects.  This is particularly\n   problematic with public-key operations since cryptlib always instantiates\n   public-key objects as cryptlib native objects since they're so much \n   quicker in that form.  So for example importing a certificate and then\n   using it to wrap a conventional encryption key that's been generated in\n   a device is impossible because the key to wrap isn't accessible to the\n   public-key context tied to the certificate.  Because of this, \n   USE_HW_KEYGEN should be used with great care */\n\n#ifdef USE_HW_KEYGEN\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int generateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tINOUT_ARRAY( templateCount ) \\\n\t\t\t\t\t\t\tCK_ATTRIBUTE *keyTemplate, \n\t\t\t\t\t\tIN_RANGE( 4, 10 ) const int templateCount, \n\t\t\t\t\t\tconst BOOLEAN isMAC )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCK_MECHANISM mechanism = { 0, NULL_PTR, 0 };\n\tCK_OBJECT_HANDLE hObject;\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( keyTemplate, \\\n\t\t\t\t\t\t\t   templateCount * sizeof( CK_ATTRIBUTE ) ) );\n\n\tREQUIRES( templateCount >= 4 && templateCount <= 10 );\n\tREQUIRES( isMAC == TRUE || isMAC == FALSE );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tmechanism.mechanism = capabilityInfoPtr->paramKeyGen;\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Generate the key into the token */\n\tstatus = C_GenerateKey( pkcs11Info->hSession, &mechanism, \n\t\t\t\t\t\t\tkeyTemplate, templateCount, &hObject );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tENSURES( hObject != CK_OBJECT_NONE );\n\n\t\tcontextInfoPtr->deviceObject = hObject;\n\t\t}\n\tzeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int cipherGenerateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t  IN_RANGE( bytesToBits( MIN_KEYSIZE ),\n\t\t\t\t\t\t\t\t\t\tbytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tstatic const CK_OBJECT_CLASS class = CKO_SECRET_KEY;\n\tstatic const CK_BBOOL bFalse = CK_FALSE, bTrue = CK_TRUE;\n\tconst CK_ULONG length = bitsToBytes( keySizeBits );\n\tCK_KEY_TYPE type;\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t/* General-purpose fields */\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },\n\t\t/* Persistent-object only fields */\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }\n\t\t};\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int templateCount = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\ttype = capabilityInfoPtr->paramKeyType;\n\n\t/* If this is meant to be a persistent object, modify the template to \n\t   make it a persistent token object and adjust the template entry count\n\t   to include the object label */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\tkeyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;\n\n\treturn( generateKey( contextInfoPtr, keyTemplate, templateCount, FALSE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int hmacGenerateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\tIN_RANGE( bytesToBits( MIN_KEYSIZE ),\n\t\t\t\t\t\t\t\t\t  bytesToBits( CRYPT_MAX_PKCSIZE ) ) \\\n\t\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tstatic const CK_OBJECT_CLASS class = CKO_SECRET_KEY;\n\tstatic const CK_BBOOL bFalse = CK_FALSE, bTrue = CK_TRUE;\n\tCK_KEY_TYPE type;\n\tconst CK_ULONG length = bitsToBytes( keySizeBits );\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t/* General-purpose fields */\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },\n\t\t/* Persistent-object only fields */\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }\n\t\t};\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tconst int templateCount = TEST_FLAG( contextInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_KEYSIZE ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_KEYSIZE ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\ttype = capabilityInfoPtr->paramKeyType;\n\n\t/* If this is meant to be a persistent object, modify the template to \n\t   make it a persistent token object and adjust the template entry count\n\t   to include the object label */\n\tif( TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT ) )\n\t\tkeyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;\n\n\treturn( generateKey( contextInfoPtr, keyTemplate, templateCount, TRUE ) );\n\t}\n#else\n\n#define cipherGenerateKey\tNULL\n#define hmacGenerateKey\t\tNULL\n\n#endif /* USE_HW_KEYGEN */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Conventional Crypto Mapping Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherEncrypt( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  INOUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t\t\t\t  IN_LENGTH const int length, \n\t\t\t\t\t\t  const CK_MECHANISM_TYPE mechanismType )\n\t{\n\tCK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tint ivSize, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tivSize = capabilityInfoPtr->blockSize;\n\n\t/* Set up mode-specific IV parameters if required */\n\tif( needsIV( contextInfoPtr->ctxConv->mode ) && \\\n\t\t!isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tmechanism.pParameter = contextInfoPtr->ctxConv->currentIV;\n\t\tmechanism.ulParameterLen = ivSize;\n\t\t}\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\tcryptStatus = genericEncrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,\n\t\t\t\t\t\t\t\t  length, length );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tif( needsIV( contextInfoPtr->ctxConv->mode ) && \\\n\t\t\t!isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t{\n\t\t\t/* Since PKCS #11 assumes that either all data is encrypted at \n\t\t\t   once or that a given mechanism is devoted entirely to a single \n\t\t\t   operation, we have to preserve the state (the IV) across \n\t\t\t   calls */\n\t\t\tREQUIRES( length >= ivSize );\n\n\t\t\tREQUIRES( rangeCheck( ivSize, 1, CRYPT_MAX_IVSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxConv->currentIV, \\\n\t\t\t\t\t( BYTE * ) buffer + length - ivSize, ivSize );\n\t\t\t}\n\t\t}\n\tkrnlReleaseObject( iCryptDevice );\n\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherDecrypt( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  INOUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t\t\t\t  IN_LENGTH const int length, \n\t\t\t\t\t\t  const CK_MECHANISM_TYPE mechanismType )\n\t{\n\tCK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tBYTE ivBuffer[ CRYPT_MAX_IVSIZE + 8 ];\n\tint ivSize, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tivSize = capabilityInfoPtr->blockSize;\n\n\t/* Set up mode-specific IV parameters if required.  In addition we have \n\t   to save the end of the ciphertext as the IV for the next block */\n\tif( needsIV( contextInfoPtr->ctxConv->mode ) && \\\n\t\t!isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tREQUIRES( length >= ivSize );\n\n\t\tmechanism.pParameter = contextInfoPtr->ctxConv->currentIV;\n\t\tmechanism.ulParameterLen = ivSize;\n\n\t\tREQUIRES( rangeCheck( ivSize, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( ivBuffer, ( BYTE * ) buffer + length - ivSize, ivSize );\n\t\t}\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\tcryptStatus = genericDecrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,\n\t\t\t\t\t\t\t\t  length );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tif( needsIV( contextInfoPtr->ctxConv->mode ) && \\\n\t\t\t!isStreamCipher( capabilityInfoPtr->cryptAlgo ) )\n\t\t\t{\n\t\t\t/* Since PKCS #11 assumes that either all data is encrypted at \n\t\t\t   once or that a given mechanism is devoted entirely to a single \n\t\t\t   operation, we have to preserve the state (the IV) across \n\t\t\t   calls */\n\t\t\tREQUIRES( rangeCheck( ivSize, 1, CRYPT_MAX_IVSIZE ) );\n\t\t\tmemcpy( contextInfoPtr->ctxConv->currentIV, ivBuffer, ivSize );\n\t\t\t}\n\t\t}\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\n/* Map a cryptlib algorithm and mode to a PKCS #11 mechanism type, with\n   shortcuts for the most frequently-used algorithm(s) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherEncryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_3DES )\n\t\treturn( cipherEncrypt( contextInfoPtr, buffer, length, CKM_DES3_ECB ) );\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_AES )\n\t\treturn( cipherEncrypt( contextInfoPtr, buffer, length, CKM_AES_ECB ) );\n\treturn( cipherEncrypt( contextInfoPtr, buffer, length, \n\t\t\t\t\tgetMechanism( MECH_CONV, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  CRYPT_MODE_ECB ) ) );\n\t}\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherEncryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\treturn( cipherEncrypt( contextInfoPtr, buffer, length, \n\t\t\t\t\t\t   capabilityInfoPtr->paramDefaultMech ) );\n\t}\n#if defined( USE_RC4 ) \nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherEncryptCTR( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 )\n\t\treturn( cipherEncrypt( contextInfoPtr, buffer, length, CKM_RC4 ) );\n\treturn( cipherEncrypt( contextInfoPtr, buffer, length, \n\t\t\t\tgetMechanism( MECH_CONV, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t  CRYPT_MODE_ECB ) ) );\n\t\t\t\t\t\t\t  /* Pseudo-mode */\n\t}\n#endif /* USE_RC4 */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherDecryptECB( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_3DES )\n\t\treturn( cipherDecrypt( contextInfoPtr, buffer, length, CKM_DES3_ECB ) );\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_AES )\n\t\treturn( cipherDecrypt( contextInfoPtr, buffer, length, CKM_AES_ECB ) );\n\treturn( cipherDecrypt( contextInfoPtr, buffer, length, \n\t\t\t\t\tgetMechanism( MECH_CONV, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  CRYPT_MODE_ECB ) ) );\n\t}\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherDecryptCBC( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\treturn( cipherDecrypt( contextInfoPtr, buffer, length, \n\t\t\t\t\t\t   capabilityInfoPtr->paramDefaultMech ) );\n\t}\n#if defined( USE_RC4 ) \nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int cipherDecryptCTR( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH int length )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRangeNZ( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tif( capabilityInfoPtr->cryptAlgo == CRYPT_ALGO_RC4 )\n\t\treturn( cipherDecrypt( contextInfoPtr, buffer, length, CKM_RC4 ) );\n\treturn( cipherDecrypt( contextInfoPtr, buffer, length, \n\t\t\t\t\tgetMechanism( MECH_CONV, capabilityInfoPtr->cryptAlgo, \n\t\t\t\t\t\t\t\t  CRYPT_MODE_ECB ) ) );\n\t\t\t\t\t\t\t\t  /* Pseudo-mode */\n\t}\n#endif /* USE_RC4 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMAC Mapping Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* MAC data.  The PKCS #11 way of handling this is rather problematic since\n   the HMAC operation is associated with a session and not with the the HMAC\n   object.  This means that we can only have a single HMAC operation in \n   effect at any one time.  To protect against users starting a second \n   HMAC/sign operation, we record the device object handle of the currently \n   active signing object and don't allow any further signature operations to\n   be initiated if there's an object currently in use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hmac( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t IN_LENGTH_Z int length )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCK_MECHANISM mechanism = { 0, NULL_PTR, 0 };\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( ( length == 0 ) || isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( isIntegerRange( length ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\tmechanism.mechanism = capabilityInfoPtr->paramDefaultMech;\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* If we're currently in the middle of a multi-stage sign operation we\n\t   can't start a new one.  We have to perform this tracking explicitly \n\t   since PKCS #11 only allows one multi-stage operation per session */\n\tif( pkcs11Info->hActiveSignObject != CK_OBJECT_NONE && \\\n\t\tpkcs11Info->hActiveSignObject != contextInfoPtr->deviceObject )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t}\n\n\t/* If we haven't initialised the MAC operation yet, start it now */\n\tif( !TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED ) )\n\t\t{\n\t\tstatus = C_SignInit( pkcs11Info->hSession, &mechanism, \n\t\t\t\t\t\t\t contextInfoPtr->deviceObject );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_HASH_INITED );\n\t\tpkcs11Info->hActiveSignObject = contextInfoPtr->deviceObject;\n\t\t}\n\n\tif( length > 0 )\n\t\tstatus = C_SignUpdate( pkcs11Info->hSession, buffer, length  );\n\telse\n\t\t{\n\t\tCK_ULONG dummy;\n\n\t\tstatus = C_SignFinal( pkcs11Info->hSession, \n\t\t\t\t\t\t\t  contextInfoPtr->ctxMAC->mac, &dummy );\n\t\tpkcs11Info->hActiveSignObject = CK_OBJECT_NONE;\n\t\t}\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Capability Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Conventional encryption and MAC mechanism information */\n\nstatic const PKCS11_MECHANISM_INFO mechanismInfoConv[] = {\n\t/* Conventional encryption mechanisms */\n\t{ CKM_DES_ECB, CKM_DES_KEY_GEN, CKM_DES_CBC, CKF_NONE, \n\t  CRYPT_ALGO_DES, CRYPT_MODE_ECB, CKK_DES,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptECB, cipherDecryptECB, NULL, NULL },\n\t{ CKM_DES_CBC, CKM_DES_KEY_GEN, CKM_DES_CBC, CKF_NONE, \n\t  CRYPT_ALGO_DES, CRYPT_MODE_CBC, CKK_DES,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },\n\t{ CKM_DES3_ECB, CKM_DES3_KEY_GEN, CKM_DES3_CBC, CKF_NONE, \n\t  CRYPT_ALGO_3DES, CRYPT_MODE_ECB, CKK_DES3,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptECB, cipherDecryptECB, NULL, NULL },\n\t{ CKM_DES3_CBC, CKM_DES3_KEY_GEN, CKM_DES3_CBC, CKF_NONE, \n\t  CRYPT_ALGO_3DES, CRYPT_MODE_CBC, CKK_DES3,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },\n#ifdef USE_RC4\n\t{ CKM_RC4, CKM_RC4_KEY_GEN, CKM_RC4, CKF_NONE, \n\t  CRYPT_ALGO_RC4, CRYPT_PSEUDOMODE_RC4, CKK_RC4,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptCTR, cipherDecryptCTR, NULL, NULL },\n#endif /* USE_RC4 */\n\t{ CKM_AES_ECB, CKM_AES_KEY_GEN, CKM_AES_CBC, CKF_NONE, \n\t  CRYPT_ALGO_AES, CRYPT_MODE_ECB, CKK_AES,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptECB, cipherDecryptECB, NULL, NULL },\n\t{ CKM_AES_CBC, CKM_AES_KEY_GEN, CKM_AES_CBC, CKF_NONE, \n\t  CRYPT_ALGO_AES, CRYPT_MODE_CBC, CKK_AES,\n\t  genericEndFunction, cipherInitKey, cipherGenerateKey, \n\t  cipherEncryptCBC, cipherDecryptCBC, NULL, NULL },\n\n\t/* MAC mechanisms.  The positioning of the encrypt/decrypt functions is \n\t   a bit odd because cryptlib treats hashing as an encrypt/decrypt\n\t   operation while PKCS #11 treats it as a sign/verify operation, the\n\t   function names correspond to the PKCS #11 usage but the position is\n\t   for cryptlib usage.  In addition there aren't any HMAC key types so\n\t   it's necessary to use CKK_GENERIC_SECRET (there's actually a bug in\n\t   the standard around this because CKK_GENERIC_SECRET keys can't be \n\t   used for en/decryption or sign/verify, at the moment some \n\t   implementations allow them to be used with HMAC and some don't).  In\n\t   order to allow for implementations that define their own HMAC keygen\n\t   and key types, we use macros for CKM_x_HMAC_KEY_GEN and CKK_x_HMAC \n\t   that expand either to the vendor-specific type or the generic CKM/CKK\n\t   types */\n\t{ CKM_SHA_1_HMAC, CKM_SHA_1_HMAC_KEY_GEN, CKM_SHA_1_HMAC, CKF_NONE, \n\t  CRYPT_ALGO_HMAC_SHA1, CRYPT_MODE_NONE, CKK_SHA_1_HMAC,\n\t  genericEndFunction, hmacInitKey, hmacGenerateKey, \n\t  hmac, hmac, NULL, NULL },\n\t{ CKM_SHA256_HMAC, CKM_SHA256_HMAC_KEY_GEN, CKM_SHA256_HMAC, CKF_NONE, \n\t  CRYPT_ALGO_HMAC_SHA2, CRYPT_MODE_NONE, CKK_SHA256_HMAC,\n\t  genericEndFunction, hmacInitKey, hmacGenerateKey, \n\t  hmac, hmac, NULL, NULL },\n\n\t{ CKM_NONE, CKM_NONE, CKM_NONE, CKF_NONE, CRYPT_ERROR, CRYPT_ERROR },\n\t\t{ CKM_NONE, CKM_NONE, CKM_NONE, CKF_NONE, CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst PKCS11_MECHANISM_INFO *getMechanismInfoConv( OUT_LENGTH_SHORT int *mechanismInfoSize )\n\t{\n\tassert( isWritePtr( mechanismInfoSize, sizeof( int ) ) );\n\n\t*mechanismInfoSize = FAILSAFE_ARRAYSIZE( mechanismInfoConv, \\\n\t\t\t\t\t\t\t\t\t\t\t PKCS11_MECHANISM_INFO );\n\treturn( mechanismInfoConv );\n\t}\n\n/* Map a cryptlib conventional-encryption algorithm and mode to a PKCS #11\n   mechanism */\n\nstatic CK_MECHANISM_TYPE getMechanism( const GETMECH_TYPE mechType,\n\t\t\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t\t   IN_MODE const CRYPT_MODE_TYPE cryptMode )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_EXT( ( ( mechType == MECH_CONV && \\\n\t\t\t\t\t  isConvAlgo( cryptAlgo ) && \\\n\t\t\t\t\t  cryptMode > CRYPT_MODE_NONE && \\\n\t\t\t\t\t  cryptMode < CRYPT_MODE_LAST ) || \n\t\t\t\t\t( mechType == MECH_CONV_KEYGEN && \\\n\t\t\t\t\t  isConvAlgo( cryptAlgo ) && \\\n\t\t\t\t\t  cryptMode == CRYPT_MODE_NONE ) || \n\t\t\t\t\t( ( mechType == MECH_MAC || \\\n\t\t\t\t\t\tmechType == MECH_MAC_KEYGEN ) && \\\n\t\t\t\t\t  isMacAlgo( cryptAlgo ) && \\\n\t\t\t\t\t  cryptMode == CRYPT_MODE_NONE ) ), CKM_NONE );\n\n\t/* Find a match for the algorithm type.  If it's a MAC algorithm or \n\t   keygen mechanism, we're done */\n\tLOOP_MED( i = 0, mechanismInfoConv[ i ].cryptAlgo != cryptAlgo && \\\n\t\t\t\t\t mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ),\n\t\t\t  i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, CKM_NONE );\n\tENSURES_EXT( ( i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ) ),\n\t\t\t\t CKM_NONE );\n\tENSURES_EXT( ( i < sizeof( mechanismInfoConv ) / sizeof( PKCS11_MECHANISM_INFO ) && \\\n\t\t\t\t   mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR ), CKM_NONE );\n\tif( mechType == MECH_MAC )\n\t\treturn( mechanismInfoConv[ i ].mechanism );\n\tif( mechType == MECH_CONV_KEYGEN || mechType == MECH_MAC_KEYGEN )\n\t\treturn( mechanismInfoConv[ i ].keygenMechanism );\n\n\t/* It's a conventional-encryption mechanism, we have to match the \n\t   encryption mode as well */\n\tENSURES_EXT( mechType == MECH_CONV, CKM_NONE );\n\tLOOP_MED_CHECKINC( mechanismInfoConv[ i ].cryptMode != cryptMode && \\\n\t\t\t\t\t   mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ),\n\t\t\t\t\t   i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, CKM_NONE );\n\tENSURES_EXT( ( i < FAILSAFE_ARRAYSIZE( mechanismInfoConv, PKCS11_MECHANISM_INFO ) ),\n\t\t\t\t CKM_NONE );\n\tENSURES_EXT( ( i < sizeof( mechanismInfoConv ) / sizeof( PKCS11_MECHANISM_INFO ) && \\\n\t\t\t\t mechanismInfoConv[ i ].cryptAlgo != CRYPT_ERROR ), CKM_NONE );\n\n\treturn( mechanismInfoConv[ i ].mechanism );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Mechanisms supported by PKCS #11 devices.  These are actually cryptlib \n   native mechanisms (support of the various mechanisms in devices is too \n   patchy to rely on, see for example the comments about PKCS vs.raw RSA\n   mechanisms elsewhere), but not the full set supported by the system \n   device since functions like private key export aren't available.  The \n   list is sorted in order of frequency of use in order to make lookups a \n   bit faster */\n\nstatic const MECHANISM_FUNCTION_INFO mechanismFunctions[] = {\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },\n#endif /* USE_SSL && USE_RSA_SUITES */\n#ifdef USE_PGP\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },\n#endif /* USE_PGP */\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PBKDF2, ( MECHANISM_FUNCTION ) derivePBKDF2 },\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },\n#endif /* USE_PGP || USE_PGPKEYS */\n#ifdef USE_SSL\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveSSL },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveTLS },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },\n#endif /* USE_SSL */\n#ifdef USE_CMP\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },\n#endif /* USE_CMP */\n#ifdef USE_PKCS12\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },\n#endif /* USE_PKCS12 */\n\t{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }\n\t};\n\n/* Set up the function pointers to the device methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setDevicePKCS11( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t IN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\t IN_LENGTH_ATTRIBUTE const int nameLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\n\tREQUIRES( nameLength > 0 && nameLength < MAX_ATTRIBUTE_SIZE );\n\n\tstatus = initPKCS11Init( deviceInfo, name, nameLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tFNPTR_SET( deviceInfo->controlFunction, controlFunction );\n\tDATAPTR_SET( deviceInfo->capabilityInfoList, NULL );\n\tinitPKCS11Read( deviceInfo );\n\tinitPKCS11Write( deviceInfo );\n\tdeviceInfo->mechanismFunctions = mechanismFunctions;\n\tdeviceInfo->mechanismFunctionCount = \\\n\t\tFAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11.h",
    "content": "/* pkcs11.h include file for PKCS #11. */\n/* $Revision: 1.4 $ */\n\n/* License to copy and use this software is granted provided that it is\n * identified as \"RSA Security Inc. PKCS #11 Cryptographic Token Interface\n * (Cryptoki)\" in all material mentioning or referencing this software.\n\n * License is also granted to make and use derivative works provided that\n * such works are identified as \"derived from the RSA Security Inc. PKCS #11\n * Cryptographic Token Interface (Cryptoki)\" in all material mentioning or\n * referencing the derived work.\n\n * RSA Security Inc. makes no representations concerning either the\n * merchantability of this software or the suitability of this software for\n * any particular purpose. It is provided \"as is\" without express or implied\n * warranty of any kind.\n */\n\n#ifndef _PKCS11_H_\n#define _PKCS11_H_ 1\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Before including this file (pkcs11.h) (or pkcs11t.h by\n * itself), 6 platform-specific macros must be defined.  These\n * macros are described below, and typical definitions for them\n * are also given.  Be advised that these definitions can depend\n * on both the platform and the compiler used (and possibly also\n * on whether a Cryptoki library is linked statically or\n * dynamically).\n *\n * In addition to defining these 6 macros, the packing convention\n * for Cryptoki structures should be set.  The Cryptoki\n * convention on packing is that structures should be 1-byte\n * aligned.\n *\n * If you're using Microsoft Developer Studio 5.0 to produce\n * Win32 stuff, this might be done by using the following\n * preprocessor directive before including pkcs11.h or pkcs11t.h:\n *\n * #pragma pack(push, cryptoki, 1)\n *\n * and using the following preprocessor directive after including\n * pkcs11.h or pkcs11t.h:\n *\n * #pragma pack(pop, cryptoki)\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to produce Win16 stuff, this might be done by using\n * the following preprocessor directive before including\n * pkcs11.h or pkcs11t.h:\n *\n * #pragma pack(1)\n *\n * In a UNIX environment, you're on your own for this.  You might\n * not need to do (or be able to do!) anything.\n *\n *\n * Now for the macros:\n *\n *\n * 1. CK_PTR: The indirection string for making a pointer to an\n * object.  It can be used like this:\n *\n * typedef CK_BYTE CK_PTR CK_BYTE_PTR;\n *\n * If you're using Microsoft Developer Studio 5.0 to produce\n * Win32 stuff, it might be defined by:\n *\n * #define CK_PTR *\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to produce Win16 stuff, it might be defined by:\n *\n * #define CK_PTR far *\n *\n * In a typical UNIX environment, it might be defined by:\n *\n * #define CK_PTR *\n *\n *\n * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes\n * an exportable Cryptoki library function definition out of a\n * return type and a function name.  It should be used in the\n * following fashion to define the exposed Cryptoki functions in\n * a Cryptoki library:\n *\n * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(\n *   CK_VOID_PTR pReserved\n * )\n * {\n *   ...\n * }\n *\n * If you're using Microsoft Developer Studio 5.0 to define a\n * function in a Win32 Cryptoki .dll, it might be defined by:\n *\n * #define CK_DEFINE_FUNCTION(returnType, name) \\\n *   returnType __declspec(dllexport) name\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to define a function in a Win16 Cryptoki .dll, it\n * might be defined by:\n *\n * #define CK_DEFINE_FUNCTION(returnType, name) \\\n *   returnType __export _far _pascal name\n *\n * In a UNIX environment, it might be defined by:\n *\n * #define CK_DEFINE_FUNCTION(returnType, name) \\\n *   returnType name\n *\n *\n * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes\n * an importable Cryptoki library function declaration out of a\n * return type and a function name.  It should be used in the\n * following fashion:\n *\n * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(\n *   CK_VOID_PTR pReserved\n * );\n *\n * If you're using Microsoft Developer Studio 5.0 to declare a\n * function in a Win32 Cryptoki .dll, it might be defined by:\n *\n * #define CK_DECLARE_FUNCTION(returnType, name) \\\n *   returnType __declspec(dllimport) name\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to declare a function in a Win16 Cryptoki .dll, it\n * might be defined by:\n *\n * #define CK_DECLARE_FUNCTION(returnType, name) \\\n *   returnType __export _far _pascal name\n *\n * In a UNIX environment, it might be defined by:\n *\n * #define CK_DECLARE_FUNCTION(returnType, name) \\\n *   returnType name\n *\n *\n * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro\n * which makes a Cryptoki API function pointer declaration or\n * function pointer type declaration out of a return type and a\n * function name.  It should be used in the following fashion:\n *\n * // Define funcPtr to be a pointer to a Cryptoki API function\n * // taking arguments args and returning CK_RV.\n * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);\n *\n * or\n *\n * // Define funcPtrType to be the type of a pointer to a\n * // Cryptoki API function taking arguments args and returning\n * // CK_RV, and then define funcPtr to be a variable of type\n * // funcPtrType.\n * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);\n * funcPtrType funcPtr;\n *\n * If you're using Microsoft Developer Studio 5.0 to access\n * functions in a Win32 Cryptoki .dll, in might be defined by:\n *\n * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \\\n *   returnType __declspec(dllimport) (* name)\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to access functions in a Win16 Cryptoki .dll, it might\n * be defined by:\n *\n * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \\\n *   returnType __export _far _pascal (* name)\n *\n * In a UNIX environment, it might be defined by:\n *\n * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \\\n *   returnType (* name)\n *\n *\n * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes\n * a function pointer type for an application callback out of\n * a return type for the callback and a name for the callback.\n * It should be used in the following fashion:\n *\n * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);\n *\n * to declare a function pointer, myCallback, to a callback\n * which takes arguments args and returns a CK_RV.  It can also\n * be used like this:\n *\n * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);\n * myCallbackType myCallback;\n *\n * If you're using Microsoft Developer Studio 5.0 to do Win32\n * Cryptoki development, it might be defined by:\n *\n * #define CK_CALLBACK_FUNCTION(returnType, name) \\\n *   returnType (* name)\n *\n * If you're using an earlier version of Microsoft Developer\n * Studio to do Win16 development, it might be defined by:\n *\n * #define CK_CALLBACK_FUNCTION(returnType, name) \\\n *   returnType _far _pascal (* name)\n *\n * In a UNIX environment, it might be defined by:\n *\n * #define CK_CALLBACK_FUNCTION(returnType, name) \\\n *   returnType (* name)\n *\n *\n * 6. NULL_PTR: This macro is the value of a NULL pointer.\n *\n * In any ANSI/ISO C environment (and in many others as well),\n * this should best be defined by\n *\n * #ifndef NULL_PTR\n * #define NULL_PTR 0\n * #endif\n */\n\n\n/* All the various Cryptoki types and #define'd values are in the\n * file pkcs11t.h. */\n#if defined( INC_ALL )\n  #include \"pkcs11t.h\"\n#else\n  #include \"device/pkcs11t.h\"\n#endif /* Compiler-specific includes */\n\n#define __PASTE(x,y)      x##y\n\n\n/* ==============================================================\n * Define the \"extern\" form of all the entry points.\n * ==============================================================\n */\n\n#define CK_NEED_ARG_LIST  1\n#define CK_PKCS11_FUNCTION_INFO(name) \\\n  extern CK_DECLARE_FUNCTION(CK_RV, name)\n\n/* pkcs11f.h has all the information about the Cryptoki\n * function prototypes. */\n#if defined( INC_ALL )\n  #include \"pkcs11f.h\"\n#else\n  #include \"device/pkcs11f.h\"\n#endif /* Compiler-specific includes */\n\n#undef CK_NEED_ARG_LIST\n#undef CK_PKCS11_FUNCTION_INFO\n\n\n/* ==============================================================\n * Define the typedef form of all the entry points.  That is, for\n * each Cryptoki function C_XXX, define a type CK_C_XXX which is\n * a pointer to that kind of function.\n * ==============================================================\n */\n\n#define CK_NEED_ARG_LIST  1\n#define CK_PKCS11_FUNCTION_INFO(name) \\\n  typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))\n\n/* pkcs11f.h has all the information about the Cryptoki\n * function prototypes. */\n#if defined( INC_ALL )\n  #include \"pkcs11f.h\"\n#else\n  #include \"device/pkcs11f.h\"\n#endif /* Compiler-specific includes */\n\n#undef CK_NEED_ARG_LIST\n#undef CK_PKCS11_FUNCTION_INFO\n\n\n/* ==============================================================\n * Define structed vector of entry points.  A CK_FUNCTION_LIST\n * contains a CK_VERSION indicating a library's Cryptoki version\n * and then a whole slew of function pointers to the routines in\n * the library.  This type was declared, but not defined, in\n * pkcs11t.h.\n * ==============================================================\n */\n\n#define CK_PKCS11_FUNCTION_INFO(name) \\\n  __PASTE(CK_,name) name;\n\nstruct CK_FUNCTION_LIST {\n\n  CK_VERSION    version;  /* Cryptoki version */\n\n/* Pile all the function pointers into the CK_FUNCTION_LIST. */\n/* pkcs11f.h has all the information about the Cryptoki\n * function prototypes. */\n#if defined( INC_ALL )\n  #include \"pkcs11f.h\"\n#else\n  #include \"device/pkcs11f.h\"\n#endif /* Compiler-specific includes */\n\n};\n\n#undef CK_PKCS11_FUNCTION_INFO\n\n\n#undef __PASTE\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "deps/cl345/device/pkcs11_api.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #11 API Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2006\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKCS11\n\n/* Before we can include the PKCS #11 headers we need to define a few OS-\n   specific things that are required by the headers */\n\n#ifdef __WINDOWS__\n  #ifdef __WIN16__\n\t#pragma pack( 1 )\t\t\t\t\t/* Struct packing */\n\t#define CK_PTR\tfar *\t\t\t\t/* Pointer type */\n\t#define CK_DEFINE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\treturnType __export _far _pascal name\n\t#define CK_DECLARE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\t returnType __export _far _pascal name\n\t#define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \\\n\t\t\t\t\t\t\t\treturnType __export _far _pascal (* name)\n\t#define CK_CALLBACK_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\t  returnType (_far _pascal * name)\n  #else\n\t#pragma pack( push, cryptoki, 1 )\t/* Struct packing */\n\t#define CK_PTR\t*\t\t\t\t\t/* Pointer type */\n\t#define CK_DEFINE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\treturnType __declspec( dllexport ) name\n\t#define CK_DECLARE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\t returnType __declspec( dllimport ) name\n\t#define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \\\n\t\t\t\t\t\t\t\treturnType __declspec( dllimport ) (* name)\n\t#define CK_CALLBACK_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\t  returnType (* name)\n  #endif /* Win16 vs.Win32 */\n#else\n  #define CK_PTR\t*\t\t\t\t\t/* Pointer type */\n  #define CK_DEFINE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t  returnType name\n  #define CK_DECLARE_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t   returnType name\n  #define CK_DECLARE_FUNCTION_POINTER( returnType, name ) \\\n\t\t\t\t\t\t\t\t\t   returnType (* name)\n  #define CK_CALLBACK_FUNCTION( returnType, name ) \\\n\t\t\t\t\t\t\t\treturnType (* name)\n#endif /* __WINDOWS__ */\n#ifndef NULL_PTR\n  #define NULL_PTR\tNULL\n#endif /* NULL_PTR */\n\n/* Pull in the PKCS #11 headers */\n\n#if defined( INC_ALL )\n  #include \"pkcs11.h\"\n#else\n  #include \"device/pkcs11.h\"\n#endif /* Compiler-specific includes */\n\n/* The use of dynamically bound function pointers vs.statically linked\n   functions requires a bit of sleight of hand since we can't give the\n   pointers the same names as prototyped functions.  To get around this we\n   redefine the actual function names to the names of the pointers */\n\n#define C_CloseSession\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_CloseSession\n#define C_CreateObject\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_CreateObject\n#define C_Decrypt\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Decrypt\n#define C_DecryptInit\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_DecryptInit\n#define C_DeriveKey\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_DeriveKey\n#define C_DestroyObject\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_DestroyObject\n#define C_Digest\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Digest\n#define C_DigestInit\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_DigestInit\n#define C_Encrypt\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Encrypt\n#define C_EncryptInit\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_EncryptInit\n#define C_Finalize\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Finalize\n#define C_FindObjects\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_FindObjects\n#define C_FindObjectsFinal\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_FindObjectsFinal\n#define C_FindObjectsInit\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_FindObjectsInit\n#define C_GenerateKey\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GenerateKey\n#define C_GenerateKeyPair\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GenerateKeyPair\n#define C_GenerateRandom\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GenerateRandom\n#define C_GetAttributeValue\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetAttributeValue\n#define C_GetMechanismInfo\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetMechanismInfo\n#define C_GetInfo\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetInfo\n#define C_GetSlotInfo\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetSlotInfo\n#define C_GetSlotList\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetSlotList\n#define C_GetTokenInfo\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_GetTokenInfo\n#define C_Initialize\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Initialize\n#define C_InitPIN\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_InitPIN\n#define C_InitToken\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_InitToken\n#define C_Login\t\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Login\n#define C_Logout\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Logout\n#define C_OpenSession\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_OpenSession\n#define C_SetAttributeValue\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_SetAttributeValue\n#define C_SetPIN\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_SetPIN\n#define C_Sign\t\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Sign\n#define C_SignFinal\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_SignFinal\n#define C_SignInit\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_SignInit\n#define C_SignUpdate\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_SignUpdate\n#define C_Verify\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_Verify\n#define C_VerifyInit\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_VerifyInit\n#define C_WrapKey\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_WrapKey\n#define C_UnwrapKey\t\t\t( ( CK_FUNCTION_LIST_PTR )( pkcs11Info->functionListPtr ) )->C_UnwrapKey\n\n/* Mapping of PKCS #11 device capabilities to cryptlib capabilities.  We \n   don't use the hash functions because they're always *much* faster in\n   software on the host system (as are the symmetric ciphers in most \n   cases) */\n\ntypedef RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *P11_END_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *P11_INITKEY_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int keyLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *P11_GENERATEKEY_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int keySizeBits );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *P11_ENCRYPT_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_Z int length );\n\t\t\t\t\t\t\t\t\t   /* Length may be zero for hash functions */\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *P11_DECRYPT_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t\t   INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH int length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *P11_SIGN_FUNCTION )( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t\t    INOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\t\t    IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) int length );\n\ntypedef struct {\n\t/* Mapping information.  The mechanism type is the specific mechanism for\n\t   this algorithm and mode, for example CKM_DES_CFB64 (= { CRYPT_ALGO_DES,\n\t   CRYPT_MODE_CFB }, the default mechanism is the default mechanism for \n\t   the algorithm (without taking the mode into account), for example\n\t   CKM_DES_CBC.  The reason why we specify both is that cryptlib records\n\t   a single capability for each algorithm while PKCS #11 has distinct \n\t   parameters for each mode of an algorithm.  By recording the most common\n\t   algorithm+mode combination (CBC mode), we can short-circuit having to \n\t   search the PKCS #11 mechanism table for the common case where that mode\n\t   is being used */\n\tconst CK_MECHANISM_TYPE mechanism;\t/* Mechanism type for this algo/mode */\n\tconst CK_MECHANISM_TYPE keygenMechanism; /* Supplementary keygen mechanism */\n\tconst CK_MECHANISM_TYPE defaultMechanism;/* Default mechanism for this algo */\n\tconst CK_FLAGS requiredFlags;\t\t/* Required flags for this mechanism */\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\t/* cryptlib algo and mode */\n\tconst CRYPT_MODE_TYPE cryptMode;\n\n\t/* Equivalent PKCS #11 parameters */\n\tconst CK_KEY_TYPE keyType;\t\t\t/* PKCS #11 key type */\n\n\t/* Function pointers */\n\tP11_END_FUNCTION endFunction;\n\tP11_INITKEY_FUNCTION initKeyFunction;\n\tP11_GENERATEKEY_FUNCTION generateKeyFunction;\n\tP11_ENCRYPT_FUNCTION encryptFunction;\n\tP11_DECRYPT_FUNCTION decryptFunction;\n\tP11_SIGN_FUNCTION signFunction, sigCheckFunction;\n\t} PKCS11_MECHANISM_INFO;\n\n/* Encryption contexts can store extra implementation-dependant parameters.\n   The following macro maps these generic parameter names to the PKCS #11\n   values */\n\n#define paramKeyType\t\t\tparam1\n#define paramKeyGen\t\t\t\tparam2\n#define paramDefaultMech\t\tparam3\n\n/* Special non-mechanism/object types used as an EOF markers.  Unfortunately \n   PKCS #11 uses all mechanisms down to 0 and it's an unsigned value so \n   there's no facility for a CKM_NONE value along the lines of CRYPT_ERROR, \n   and similarly object handles can also take any value, the best that we \n   can do is use CRYPT_ERROR (all ones) and hope that nothing decides to \n   return an object handle with this value.  With mechanisms we're a bit \n   safer, it'd have to be some weird vendor-defined value to match \n   CKM_NONE */\n\n#define CKM_NONE\t\t\t\t( ( CK_MECHANISM_TYPE ) CRYPT_ERROR )\n#define CK_OBJECT_NONE\t\t\t( ( CK_OBJECT_HANDLE ) CRYPT_ERROR )\n#define CKA_NONE\t\t\t\t( ( CK_ATTRIBUTE_TYPE ) CRYPT_ERROR )\n#define CKF_NONE\t\t\t\t0\n\n/* The HMAC mechanisms in PKCS #11 don't work because they have to be keyed \n   with generic secret keys (rather than specific HMAC keys) but generic \n   secret keys can't be used with HMAC operations.  There are two possible\n   workarounds for this, either ignore the restrictions on generic secret \n   keys so that they can be used with HMAC objects or define vendor-specific \n   HMAC mechanisms and keys.  The latter approach is used by nCipher, who \n   define their own CKA/CKM/CKK values based around a custom magic ID \n   value */\n\n#define VENDOR_NCIPHER\t\t\t0xDE436972UL\n#define CKA_NCIPHER\t\t\t\t( CKA_VENDOR_DEFINED | VENDOR_NCIPHER )\n#define CKM_NCIPHER\t\t\t\t( CKM_VENDOR_DEFINED | VENDOR_NCIPHER )\n#define CKK_NCIPHER\t\t\t\t( CKK_VENDOR_DEFINED | VENDOR_NCIPHER )\n\n#ifdef NCIPHER_PKCS11\n  #define CKK_MD5_HMAC\t\t\t( CKK_NCIPHER + 2 )\n  #define CKK_SHA_1_HMAC\t\t( CKK_NCIPHER + 1 )\n  #define CKK_RIPEMD160_HMAC\tCKK_GENERIC_SECRET\n  #define CKK_SHA256_HMAC\t\tCKK_GENERIC_SECRET\n  #define CKM_MD5_HMAC_KEY_GEN\t( CKM_NCIPHER + 6 )\n  #define CKM_SHA_1_HMAC_KEY_GEN ( CKM_NCIPHER + 3 )\n  #define CKM_RIPEMD160_HMAC_KEY_GEN CKK_GENERIC_SECRET\n  #define CKM_SHA256_HMAC_KEY_GEN CKK_GENERIC_SECRET\n#else\n  #define CKK_MD5_HMAC\t\t\tCKK_GENERIC_SECRET\n  #define CKK_SHA_1_HMAC\t\tCKK_GENERIC_SECRET\n  #define CKK_RIPEMD160_HMAC\tCKK_GENERIC_SECRET\n  #define CKK_SHA256_HMAC\t\tCKK_GENERIC_SECRET\n  #define CKM_MD5_HMAC_KEY_GEN\tCKM_GENERIC_SECRET_KEY_GEN\n  #define CKM_SHA_1_HMAC_KEY_GEN CKM_GENERIC_SECRET_KEY_GEN\n  #define CKM_RIPEMD160_HMAC_KEY_GEN CKK_GENERIC_SECRET\n  #define CKM_SHA256_HMAC_KEY_GEN CKM_GENERIC_SECRET_KEY_GEN\n#endif /* NCIPHER_PKCS11 */\n\n/* Prototypes for functions in pkcs11.c */\n\nCHECK_RETVAL \\\nint pkcs11MapError( const CK_RV errorCode,\n\t\t\t\t\tIN_STATUS const int defaultError );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint getContextDeviceInfo( IN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_DEVICE *iCryptDevice, \n\t\t\t\t\t\t  OUT_PTR_COND PKCS11_INFO **pkcs11InfoPtrPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\ntime_t getTokenTime( const CK_TOKEN_INFO *tokenInfo );\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst PKCS11_MECHANISM_INFO *getMechanismInfoConv( OUT_LENGTH_SHORT int *mechanismInfoSize );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint genericEndFunction( INOUT CONTEXT_INFO *contextInfoPtr );\n\n/* Prototypes for functions in pkcs11_init.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initPKCS11Init( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\tIN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\tIN_LENGTH_SHORT const int nameLength );\n\n/* Prototypes for functions in pkcs11_pkc.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint rsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hRsaKey,\n\t\t\t\t\t\t\tconst BOOLEAN nativeContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hDsaKey,\n\t\t\t\t\t\t\tconst BOOLEAN nativeContext );\n#if defined( USE_ECDSA )\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint ecdsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t  const CK_OBJECT_HANDLE hEcdsaKey,\n\t\t\t\t\t\t\t  const BOOLEAN nativeContext );\n#endif /* USE_ECDSA */\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst PKCS11_MECHANISM_INFO *getMechanismInfoPKC( OUT int *mechanismInfoSize );\n\n/* Prototypes for functions in pkcs11_rd/wr.c */\n\nCHECK_RETVAL_RANGE( ACTION_PERM_FLAG_NONE, ACTION_PERM_FLAG_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getActionFlags( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\tconst CK_OBJECT_HANDLE hObject,\n\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addIAndSToTemplate( INOUT_ARRAY_C( 2 ) CK_ATTRIBUTE *certTemplate, \n\t\t\t\t\t\tIN_BUFFER( iAndSLength ) const void *iAndSPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int iAndSLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getEccCurveType( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\tCRYPT_ECCCURVE_TYPE *curveType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint findObject( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\tOUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\tIN_ARRAY( templateCount ) \\\n\t\t\t\t\tconst CK_ATTRIBUTE *objectTemplate,\n\t\t\t\tIN_RANGE( 1, 64 ) const CK_ULONG templateCount );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint findObjectEx( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t  OUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\t  IN_ARRAY( templateCount ) \\\n\t\t\t\t\tconst CK_ATTRIBUTE *objectTemplate,\n\t\t\t\t  IN_RANGE( 1, 64 ) const CK_ULONG templateCount );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint findObjectFromObject( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hSourceObject, \n\t\t\t\t\t\t  const CK_OBJECT_CLASS objectClass,\n\t\t\t\t\t\t  OUT CK_OBJECT_HANDLE *hObject );\nvoid initPKCS11Read( INOUT DEVICE_INFO *deviceInfo ) \\\n\t\t\t\t\t STDC_NONNULL_ARG( ( 1 ) );\nvoid initPKCS11Write( INOUT DEVICE_INFO *deviceInfo ) \\\n\t\t\t\t\t  STDC_NONNULL_ARG( ( 1 ) );\n\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11_init.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #11 Init/Shutdown Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"pkcs11_api.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/pkcs11_api.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS11\n\n/* The max. number of drivers we can work with and the max.number of slots\n   per driver */\n\n#define MAX_PKCS11_DRIVERS\t\t5\n#define MAX_PKCS11_SLOTS\t\t16\n\n/* The default slot to look for tokens in */\n\n#define DEFAULT_SLOT\t\t\t0\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get random data from the device */\n\nstatic int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,\n\t\t\t\t\t\t\t  const int length,\n\t\t\t\t\t\t\t  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tCK_RV status;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tstatus = C_GenerateRandom( pkcs11Info->hSession, buffer, length );\n\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t}\n\n/* Perform a self-test */\n\nstatic int selfTestFunction( void )\n\t{\n\t/* PKCS #11 doesn't provide any explicit means of performing a self-\n\t   test of a capability, and having to go through the gyrations needed \n\t   to do this via the PKCS #11 interface is excessively complex, so we\n\t   just assume that everything is OK.  In general what a device does is\n\t   device-specific, for example as part of FIPS 140 requirements or even\n\t   just as general good engineering many will perform a self-test on\n\t   power-up while others (typically smart cards) barely do any checking\n\t   at all.  The result that we return here is an implicit \"whatever the\n\t   device does\" */\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tInit/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Whether the PKCS #11 library has been initialised or not, this is\n   initialised on demand the first time it's accessed */\n\nstatic BOOLEAN pkcs11Initialised = FALSE;\n\n/* Since we can be using multiple PKCS #11 drivers, we define an array of\n   them and access the appropriate one by name */\n\ntypedef struct {\n\tchar name[ 32 + 1 + 8 ];\t\t/* Name of device */\n\tINSTANCE_HANDLE hPKCS11;\t\t/* Handle to driver */\n\tCK_FUNCTION_LIST_PTR functionListPtr;\t/* Driver access information */\n\t} PKCS11_DRIVER_INFO;\n\nstatic PKCS11_DRIVER_INFO pkcs11InfoTbl[ MAX_PKCS11_DRIVERS + 8 ];\n\n/* Dynamically load and unload any necessary PKCS #11 drivers */\n\nstatic int loadPKCS11driver( PKCS11_DRIVER_INFO *pkcs11Info,\n\t\t\t\t\t\t\t const char *driverName )\n\t{\n\tCK_C_GetFunctionList pC_GetFunctionList;\n\tCK_INFO info DUMMY_INIT_STRUCT;\n\tCK_RV status;\n#ifdef __WIN16__\n\tUINT errorMode;\n#endif /* __WIN16__ */\n\tBOOLEAN isInitialised = FALSE;\n\tconst char *description;\n\tint descriptionLength;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_DRIVER_INFO ) ) );\n\tassert( isReadPtr( driverName, 4 ) );\n\n\t/* Obtain a handle to the device driver module */\n#ifdef __WIN16__\n\terrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );\n\tpkcs11Info->hPKCS11 = LoadLibrary( driverName );\n\tSetErrorMode( errorMode );\n\tif( pkcs11Info->hPKCS11 < HINSTANCE_ERROR )\n\t\t{\n\t\tpkcs11Info->hPKCS11 = NULL_HINSTANCE;\n\t\treturn( CRYPT_ERROR );\n\t\t}\n#else\n\tif( ( pkcs11Info->hPKCS11 = DynamicLoad( driverName ) ) == NULL_INSTANCE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't load PKCS #11 driver '%s'\", driverName ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n#endif /* OS-specific dynamic load */\n\tDEBUG_DIAG(( \"Loaded PKCS #11 driver '%s'\", driverName ));\n\n\t/* Get the access information for the PKCS #11 library, initialise it, \n\t   and get information on the device.  There are four types of PKCS #11 \n\t   driver around: v1, v1-like claiming to be v2, v2-like claiming to be \n\t   v1, and v2.  cryptlib can in theory handle all of these, however \n\t   there are some problem areas with v1 (for example v1 uses 16-bit \n\t   values while v2 uses 32-bit ones, this is usually OK because data is \n\t   passed around as 32-bit values with the high bits zeroed but some \n\t   implementations may leave garbage in the high 16 bits that leads to \n\t   all sorts of confusion).  Because of this we explicitly fail if \n\t   something claims to be v1 even though it might work in practice */\n\tpC_GetFunctionList = ( CK_C_GetFunctionList ) \\\n\t\t\t\tDynamicBind( pkcs11Info->hPKCS11, \"C_GetFunctionList\" );\n\tif( pC_GetFunctionList == NULL )\n\t\tstatus = CKR_GENERAL_ERROR;\n\telse\n\t\t{\n\t\tCK_FUNCTION_LIST_PTR functionListPtr;\n\n\t\t/* The following two-step initialisation is needed because PKCS #11 \n\t\t   uses a 1-byte alignment on structs, which means that if we pass\n\t\t   in the pkcs11Info member address directly we run into alignment\n\t\t   problems with 64-bit architectures */\n\t\tstatus = pC_GetFunctionList( &functionListPtr ) & 0xFFFF;\n\t\tif( status == CKR_OK )\n\t\t\tpkcs11Info->functionListPtr = functionListPtr;\n\t\t}\n\tif( status != CKR_OK )\n\t\t{\n\t\t/* Free the library reference and clear the information */\n\t\tDynamicUnload( pkcs11Info->hPKCS11 );\n\t\tmemset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );\n\t\tDEBUG_DIAG(( \"Couldn't bind to PKCS #11 driver functions via \"\n\t\t\t\t\t \"C_GetFunctionList(), PKCS #11 error code %04X\", \n\t\t\t\t\t status ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\tstatus = C_Initialize( NULL_PTR ) & 0xFFFF;\n\tif( status == CKR_ARGUMENTS_BAD && \\\n\t\tstrFindStr( driverName, strlen( driverName ), \"softokn3.\", 9 ) >= 0 )\n\t\t{\n\t\ttypedef struct CK_C_INITIALIZE_ARGS {\n\t\t\tCK_CREATEMUTEX CreateMutex;\n\t\t\tCK_DESTROYMUTEX DestroyMutex;\n\t\t\tCK_LOCKMUTEX LockMutex;\n\t\t\tCK_UNLOCKMUTEX UnlockMutex;\n\t\t\tCK_FLAGS flags;\n\t\t\tCK_VOID_PTR LibraryParameters;\n\t\t\tCK_VOID_PTR pReserved;\n\t\t\t} Netscape_CK_C_INITIALIZE_ARGS;\n\t\tNetscape_CK_C_INITIALIZE_ARGS initArgs;\n\n\t\t/* Netscape invented their own extension to CK_C_INITIALIZE_ARGS, \n\t\t   adding a 'LibraryParameters' string to allow the specification of \n\t\t   free-form parameters.  If the Netscape library's C_Initialize()\n\t\t   is called then it'll return CKR_ARGUMENTS_BAD (rather than \n\t\t   assuming sensible default values), so that we have to call it \n\t\t   again with explicitly-specified parameters.\n\n\t\t   Even this doesn't work properly though, according to the Netscape \n\t\t   docs we can set LibraryParameters to NULL, but this still results \n\t\t   in C_Initialize() returning CKR_ARGUMENTS_BAD.  Later in the docs\n\t\t   is a requirement that the softokn3 library be passed a \n\t\t   \"parameters=\" string, but it's unclear what parameters need to be \n\t\t   set, to what values, and what effect these values may have on the\n\t\t   behaviour of existing configs for applications like Firefox.  The\n\t\t   following config lets the C_Initialize() call succeed but causes\n\t\t   odd failures later in other PKCS #11 functions */\n\t\tDEBUG_DIAG(( \"Driver is the buggy Netscape/NSS one that requires \"\n\t\t\t\t\t \"nonstandard initialisation, see the code comment for \"\n\t\t\t\t\t \"details\" ));\n\t\tassert( DEBUG_WARN );\n\t\tmemset( &initArgs, 0, sizeof( Netscape_CK_C_INITIALIZE_ARGS ) );\n\t\tinitArgs.LibraryParameters = \\\n\t\t\t\"configdir='.' certPrefix='' keyPrefix='' secmod='secmod.db' \"\n\t\t\t\"flags=noModDB,noCertDB,noKeyDB,optimizeSpace,readOnly\";\n\t\tstatus = C_Initialize( &initArgs );\n\t\t}\n\tif( status == CKR_OK || status == CKR_CRYPTOKI_ALREADY_INITIALIZED )\n\t\t{\n\t\tisInitialised = TRUE;\n\t\tstatus = C_GetInfo( &info ) & 0xFFFF;\n\t\tif( status == CKR_OK && info.cryptokiVersion.major <= 1 )\n\t\t\t{\n\t\t\t/* It's v1, we can't work with it */\n\t\t\tstatus = CKR_FUNCTION_NOT_SUPPORTED;\n\t\t\t}\n\t\t}\n\tif( status != CKR_OK )\n\t\t{\n\t\tif( isInitialised )\n\t\t\tC_Finalize( NULL_PTR );\n\t\tDynamicUnload( pkcs11Info->hPKCS11 );\n\t\tmemset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );\n\t\tDEBUG_DIAG(( \"Couldn't initialise PKCS #11 interface via \"\n\t\t\t\t\t \"C_Initialize(), PKCS #11 error code %04X\", status ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Copy out the device driver's name so that the user can access it by \n\t   name.  Some vendors erroneously null-terminate the string so we check \n\t   for nulls as well */\n\tstatus = \\\n\t\tdescriptionLength = strStripWhitespace( &description, \n\t\t\t\t\t\t\t\t\t\t\t\tinfo.libraryDescription, 32 );\n\tif( cryptStatusError( status ) || descriptionLength <= 0 )\n\t\tmemcpy( pkcs11Info->name, \"<<<No description>>>\", 20 + 1 );\n\telse\n\t\t{\n\t\tREQUIRES( rangeCheck( descriptionLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( pkcs11Info->name, description, descriptionLength );\n\t\tpkcs11Info->name[ descriptionLength ] = '\\0';\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid deviceEndPKCS11( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tif( pkcs11Initialised )\n\t\t{\n\t\tLOOP_MED( i = 0, i < MAX_PKCS11_DRIVERS, i++ )\n\t\t\t{\n\t\t\tif( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )\n\t\t\t\t{\n\t\t\t\tPKCS11_DRIVER_INFO *pkcs11Info = &pkcs11InfoTbl[ i ];\n\t\t\t\t\t\t/* Needed for the macro that wraps C_Finalize() */\n\n\t\t\t\tC_Finalize( NULL_PTR );\n\n\t\t\t\tDynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );\n\t\t\t\t}\n\t\t\tpkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK );\n\t\t}\n\tpkcs11Initialised = FALSE;\n\t}\n\nCHECK_RETVAL \\\nint deviceInitPKCS11( void )\n\t{\n\tint tblIndex = 0, optionIndex, status, LOOP_ITERATOR;\n\n\t/* If we've previously tried to initialise the drivers, don't try it \n\t   again */\n\tif( pkcs11Initialised )\n\t\treturn( CRYPT_OK );\n\tmemset( pkcs11InfoTbl, 0, sizeof( pkcs11InfoTbl ) );\n\n\t/* Try and link in each driver specified in the config options.  Since\n\t   this is a general systemwide config option, we always query the built-\n\t   in default user object */\n\tLOOP_MED( optionIndex = 0, optionIndex < MAX_PKCS11_DRIVERS, optionIndex++ )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tchar deviceDriverName[ MAX_PATH_LENGTH + 1 + 8 ];\n\n\t\tsetMessageData( &msgData, deviceDriverName, MAX_PATH_LENGTH );\n\t\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\tIMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\toptionIndex + CRYPT_OPTION_DEVICE_PKCS11_DVR01 );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\t\tdeviceDriverName[ msgData.length ] = '\\0';\n\t\tstatus = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex ], \n\t\t\t\t\t\t\t\t   deviceDriverName );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\ttblIndex++;\n\t\t\tpkcs11Initialised = TRUE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If it's a Unix system and there were no drivers explicitly specified,\n\t   try with the default driver name \"libpkcs11.so\".  Unlike Windows,\n\t   where there are large numbers of PKCS #11 vendors and we have to use\n\t   vendor-specific names, under Unix there are very few vendors and \n\t   there's usually only one device/driver in use which inevitably \n\t   co-opts /usr/lib for its own use, so we can always try for a standard\n\t   name and location.  As a backup measure we also try for the nCipher \n\t   PKCS #11 driver, which is by far the most commonly used one on Unix \n\t   systems (this may sometimes be found as /usr/lib/libcknfast.so).\n\n\t   An unfortunate side-effect of this handling is that if there's more\n\t   than one PKCS #11 driver present and the user forgets to explicitly\n\t   specify it then this may load the wrong one, however the chances of\n\t   there being multiple drivers present on a Unix system is close to \n\t   zero so it's probably better to take the more user-friendly option\n\t   of trying to load a default driver */\n#ifdef __UNIX__\n\tif( !pkcs11Initialised )\n\t\t{\n\t\tstatus = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex ], \n\t\t\t\t\t\t\t\t   \"libpkcs11.so\" );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tpkcs11Initialised = TRUE;\n\t\t}\n\tif( !pkcs11Initialised )\n\t\t{\n\t\tstatus = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex ], \n\t\t\t\t\t\t\t\t   \"/opt/nfast/toolkits/pkcs11/libcknfast.so\" );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tpkcs11Initialised = TRUE;\n\t\t}\n#endif /* __UNIX__ */\n\t\n\treturn( pkcs11Initialised ? CRYPT_OK : CRYPT_ERROR );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Capability Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The reported key size for PKCS #11 implementations is rather inconsistent,\n   most are reported in bits, a number don't return a useful value, and a few\n   are reported in bytes.  The following macros sort out which algorithms\n   have valid key size information and which report the length in bytes */\n\n#define keysizeValid( algo ) \\\n\t( ( algo ) == CRYPT_ALGO_DH || ( algo ) == CRYPT_ALGO_RSA || \\\n\t  ( algo ) == CRYPT_ALGO_DSA || ( algo ) == CRYPT_ALGO_ECDSA || \\\n\t  ( algo ) == CRYPT_ALGO_RC4 )\n#define keysizeInBytes( algo )\t( FALSE )\t/* No currently-used algo */\n\n/* Templates for the various capabilities.  These contain only basic \n   information, the remaining fields are filled in when the capability is \n   set up */\n\nstatic CAPABILITY_INFO capabilityTemplates[] = {\n\t/* Encryption capabilities */\n\t{ CRYPT_ALGO_DES, bitsToBytes( 64 ), \"DES\", 3,\n\t\tMIN_KEYSIZE, bitsToBytes( 64 ), bitsToBytes( 64 ) },\n\t{ CRYPT_ALGO_3DES, bitsToBytes( 64 ), \"3DES\", 4,\n\t\tbitsToBytes( 64 + 8 ), bitsToBytes( 128 ), bitsToBytes( 192 ) },\n#ifdef USE_RC4\n\t{ CRYPT_ALGO_RC4, bitsToBytes( 8 ), \"RC4\", 3,\n\t\tMIN_KEYSIZE, bitsToBytes( 128 ), 256 },\n#endif /* USE_RC4 */\n\t{ CRYPT_ALGO_AES, bitsToBytes( 128 ), \"AES\", 3,\n\t\tbitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ) },\n\n\t/* Hash capabilities */\n#ifdef USE_MD5\n\t{ CRYPT_ALGO_MD5, bitsToBytes( 128 ), \"MD5\", 3,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },\n#endif /* USE_MD5 */\n\t{ CRYPT_ALGO_SHA1, bitsToBytes( 160 ), \"SHA-1\", 5,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },\n\t{ CRYPT_ALGO_SHA2, bitsToBytes( 256 ), \"SHA-2\", 5,\n\t\tbitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },\n\n\t/* MAC capabilities */\n\t{ CRYPT_ALGO_HMAC_SHA1, bitsToBytes( 160 ), \"HMAC-SHA1\", 9,\n\t  bitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE },\n\t{ CRYPT_ALGO_HMAC_SHA2, bitsToBytes( 256 ), \"HMAC-SHA2\", 9,\n\t  bitsToBytes( 64 ), bitsToBytes( 128 ), CRYPT_MAX_KEYSIZE },\n\n\t/* Public-key capabilities */\n#ifdef USE_DH\n\t{ CRYPT_ALGO_DH, bitsToBytes( 0 ), \"Diffie-Hellman\", 14,\n\t\tMIN_PKCSIZE, bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },\n#endif /* USE_DH */\n\t{ CRYPT_ALGO_RSA, bitsToBytes( 0 ), \"RSA\", 3,\n\t\tMIN_PKCSIZE, bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },\n#ifdef USE_DSA\n\t{ CRYPT_ALGO_DSA, bitsToBytes( 0 ), \"DSA\", 3,\n\t\tMIN_PKCSIZE, bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },\n#endif /* USE_DSA */\n#ifdef USE_ECDSA\n\t{ CRYPT_ALGO_ECDSA, bitsToBytes( 0 ), \"ECDSA\", 5,\n\t\tMIN_PKCSIZE_ECC, bitsToBytes( 256 ), CRYPT_MAX_PKCSIZE_ECC },\n#endif /* USE_ECDSA */\n\n\t/* Hier ist der Mast zu ende */\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n\n/* Query a given capability for a device and fill out a capability \n   information record for it if present */\n\nstatic CAPABILITY_INFO *getCapability( const DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t\t\t   const PKCS11_MECHANISM_INFO *mechanismInfoPtr,\n\t\t\t\t\t\t\t\t\t   const int maxMechanisms )\n\t{\n\tVARIABLE_CAPABILITY_INFO *capabilityInfo;\n\tCK_MECHANISM_INFO pMechanism;\n\tCK_RV status;\n\tconst CRYPT_ALGO_TYPE cryptAlgo = mechanismInfoPtr->cryptAlgo;\n\tconst BOOLEAN isPKC = isPkcAlgo( cryptAlgo ) ? TRUE : FALSE;\n\tconst CK_FLAGS keyGenFlag = isPKC ? CKF_GENERATE_KEY_PAIR : CKF_GENERATE;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tBOOLEAN_INT hardwareOnly;\n\tint noMechanisms, i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( mechanismInfoPtr, \\\n\t\t\t\t\t\t\t  maxMechanisms * sizeof( PKCS11_MECHANISM_INFO ) ) );\n\n\t/* Set up canary values for the mechanism information in case the driver\n\t   blindly reports success for every mechanism that we ask for */\n\tmemset( &pMechanism, 0, sizeof( CK_MECHANISM_INFO ) );\n\tpMechanism.ulMinKeySize = 0xA5A5;\n\tpMechanism.ulMaxKeySize = 0x5A5A;\n\n\t/* Get the information for this mechanism.  Since many PKCS #11 drivers\n\t   implement some of their capabilities using God knows what sort of \n\t   software implementation, we provide the option to skip emulated \n\t   mechanisms if required */\n\tstatus = C_GetMechanismInfo( pkcs11Info->slotID, \n\t\t\t\t\t\t\t\t mechanismInfoPtr->mechanism,\n\t\t\t\t\t\t\t\t &pMechanism );\n\tif( status != CKR_OK )\n\t\treturn( NULL );\n\tif( pMechanism.ulMinKeySize == 0xA5A5 && \\\n\t\tpMechanism.ulMaxKeySize == 0x5A5A )\n\t\t{\n\t\t/* The driver reported that this mechanism is available but didn't\n\t\t   update the mechanism information, it's lying */\n\t\tDEBUG_DIAG(( \"Driver reports that mechanism %X is available even \"\n\t\t\t\t\t \"though it isn't\", mechanismInfoPtr->mechanism ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( NULL );\n\t\t}\n\tstatus = krnlSendMessage( deviceInfo->ownerHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &hardwareOnly, \n\t\t\t\t\t\t\t  CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY );\n\tif( cryptStatusOK( status ) && hardwareOnly == TRUE && \\\n\t\t!( pMechanism.flags & CKF_HW ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Skipping mechanism %X, which is only available in \"\n\t\t\t\t\t \"software emulation\", mechanismInfoPtr->mechanism ));\n\t\treturn( NULL );\n\t\t}\n\tif( mechanismInfoPtr->requiredFlags != CKF_NONE )\n\t\t{\n\t\t/* Make sure that the driver flags indicate support for the specific \n\t\t   functionality that we require */\n\t\tif( ( mechanismInfoPtr->requiredFlags & \\\n\t\t\t  pMechanism.flags ) != mechanismInfoPtr->requiredFlags )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Driver reports that mechanism %X only has \"\n\t\t\t\t\t\t \"capabilities %lX when we require %lX\", \n\t\t\t\t\t\t mechanismInfoPtr->mechanism, \n\t\t\t\t\t\t mechanismInfoPtr->requiredFlags & pMechanism.flags,\n\t\t\t\t\t\t mechanismInfoPtr->requiredFlags ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( NULL );\n\t\t\t}\n\t\t}\n\n\t/* Copy across the template for this capability */\n\tif( ( capabilityInfo = clAlloc( \"getCapability\", \\\n\t\t\t\t\t\t\t\t\tsizeof( CAPABILITY_INFO ) ) ) == NULL )\n\t\treturn( NULL );\n\tLOOP_MED( i = 0, \n\t\t\t  capabilityTemplates[ i ].cryptAlgo != cryptAlgo && \\\n\t\t\t\tcapabilityTemplates[ i ].cryptAlgo != CRYPT_ERROR && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ), \n\t\t\t  i++ );\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ) );\n\tENSURES_N( capabilityTemplates[ i ].cryptAlgo != CRYPT_ERROR );\n\tmemcpy( capabilityInfo, &capabilityTemplates[ i ],\n\t\t\tsizeof( CAPABILITY_INFO ) );\n\n\t/* Set up the keysize information if there's anything useful available */\n\tif( keysizeValid( cryptAlgo ) )\n\t\t{\n\t\tint minKeySize = ( int ) pMechanism.ulMinKeySize;\n\t\tint maxKeySize = ( int ) pMechanism.ulMaxKeySize;\n\t\t\t\t\t\t /* isIntegerRange() checked below */\n\n\t\t/* Adjust the key size to bytes and make sure that all values are \n\t\t   consistent.  Some implementations report silly bounds (e.g. 1-bit \n\t\t   RSA, \"You naughty minKey\" or alternatively 4Gbit RSA) so we \n\t\t   adjust them to a sane value if necessary.  We also limit the \n\t\t   maximum key size to match the cryptlib native maximum key size, \n\t\t   both for consistency and because cryptlib performs buffer \n\t\t   allocation based on the maximum native buffer size */\n\t\tif( !isIntegerRange( pMechanism.ulMinKeySize ) || \\\n\t\t\tpMechanism.ulMinKeySize >= 10000L )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Driver reports invalid minimum key size %lu for \"\n\t\t\t\t\t\t \"%s algorithm\", pMechanism.ulMinKeySize,\n\t\t\t\t\t\t capabilityInfo->algoName ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tminKeySize = 0;\n\t\t\t}\n\t\tif( !isIntegerRange( pMechanism.ulMaxKeySize ) || \\\n\t\t\tpMechanism.ulMaxKeySize >= 100000L )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Driver reports invalid maximum key size %lu for \"\n\t\t\t\t\t\t \"%s algorithm\", pMechanism.ulMaxKeySize,\n\t\t\t\t\t\t capabilityInfo->algoName ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tmaxKeySize = CRYPT_MAX_KEYSIZE;\n\t\t\t}\n\t\tif( !keysizeInBytes( cryptAlgo ) )\n\t\t\t{\n\t\t\tminKeySize = bitsToBytes( minKeySize );\n\t\t\tmaxKeySize = bitsToBytes( maxKeySize );\n\t\t\t}\n\t\tif( minKeySize > capabilityInfo->minKeySize )\n\t\t\tcapabilityInfo->minKeySize = minKeySize;\n\t\tif( capabilityInfo->keySize < capabilityInfo->minKeySize )\n\t\t\tcapabilityInfo->keySize = capabilityInfo->minKeySize;\n\t\tcapabilityInfo->maxKeySize = min( maxKeySize, \n\t\t\t\t\t\t\t\t\t\t  capabilityInfo->maxKeySize );\n\t\tif( capabilityInfo->maxKeySize < capabilityInfo->minKeySize )\n\t\t\t{\n\t\t\t/* Serious braindamage in the driver, we'll just have to make\n\t\t\t   a sensible guess */\n\t\t\tDEBUG_DIAG(( \"Driver reports maximum key size %d < minimum key \"\n\t\t\t\t\t\t \"size %d for %s algorithm\", \n\t\t\t\t\t\t capabilityInfo->maxKeySize, \n\t\t\t\t\t\t capabilityInfo->minKeySize, \n\t\t\t\t\t\t capabilityInfo->algoName ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tif( isPKC )\n\t\t\t\t{\n\t\t\t\tcapabilityInfo->maxKeySize = \\\n\t\t\t\t\tmax( capabilityInfo->minKeySize, bitsToBytes( 2048 ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tcapabilityInfo->maxKeySize = 16;\n\t\t\t}\n\t\tif( capabilityInfo->keySize > capabilityInfo->maxKeySize )\n\t\t\tcapabilityInfo->keySize = capabilityInfo->maxKeySize;\n\t\t}\n\n\t/* Set up the device-specific handlers */\n\tcapabilityInfo->selfTestFunction = selfTestFunction;\n\tcapabilityInfo->getInfoFunction = getDefaultInfo;\n\tif( !isPKC )\n\t\tcapabilityInfo->initParamsFunction = initGenericParams;\n\tcapabilityInfo->endFunction = mechanismInfoPtr->endFunction;\n\tcapabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;\n\tif( pMechanism.flags & keyGenFlag )\n\t\t{\n\t\tcapabilityInfo->generateKeyFunction = \\\n\t\t\t\t\t\t\t\t\tmechanismInfoPtr->generateKeyFunction;\n\t\t}\n\tif( pMechanism.flags & CKF_SIGN )\n\t\t{\n\t\t/* cryptlib treats hashing as an encrypt/decrypt operation while \n\t\t   PKCS #11 treats it as a sign/verify operation, so we have to\n\t\t   juggle the function pointers based on the underlying algorithm\n\t\t   type */\n\t\tif( isPKC )\n\t\t\tcapabilityInfo->signFunction = mechanismInfoPtr->signFunction;\n\t\telse\n\t\t\tcapabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;\n\t\t}\n\tif( pMechanism.flags & CKF_VERIFY )\n\t\t{\n\t\t/* See comment above */\n\t\tif( isPKC )\n\t\t\tcapabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;\n\t\telse\n\t\t\tcapabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;\n\t\t}\n\tif( pMechanism.flags & CKF_ENCRYPT )\n\t\t{\n\t\t/* Not all devices implement all modes, so we have to be careful to \n\t\t   set up the pointer for the exact mode that's supported */\n\t\tswitch( mechanismInfoPtr->cryptMode )\n\t\t\t{\n\t\t\tcase CRYPT_MODE_CBC:\n\t\t\t\tcapabilityInfo->encryptCBCFunction = mechanismInfoPtr->encryptFunction;\n\t\t\t\tbreak;\n\n#ifdef USE_CFB\n\t\t\tcase CRYPT_MODE_CFB:\n\t\t\t\tcapabilityInfo->encryptCFBFunction = mechanismInfoPtr->encryptFunction;\n\t\t\t\tbreak;\n#endif /* USE_CFB */\n\n\t\t\tcase CRYPT_MODE_GCM:\n\t\t\t\tcapabilityInfo->encryptGCMFunction = mechanismInfoPtr->encryptFunction;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\t/* ECB or a PKC */\n\t\t\t\tcapabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tif( pMechanism.flags & CKF_DECRYPT )\n\t\t{\n\t\t/* Not all devices implement all modes, so we have to be careful to \n\t\t   set up the pointer for the exact mode that's supported */\n\t\tswitch( mechanismInfoPtr->cryptMode )\n\t\t\t{\n\t\t\tcase CRYPT_MODE_CBC:\n\t\t\t\tcapabilityInfo->decryptCBCFunction = mechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n\n#ifdef USE_CFB\n\t\t\tcase CRYPT_MODE_CFB:\n\t\t\t\tcapabilityInfo->decryptCFBFunction = mechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n#endif /* USE_CFB */\n\n\t\t\tcase CRYPT_MODE_GCM:\n\t\t\t\tcapabilityInfo->decryptGCMFunction = mechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\t/* ECB or a PKC */\n\t\t\t\tcapabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tif( cryptAlgo == CRYPT_ALGO_DH && pMechanism.flags & CKF_DERIVE )\n\t\t{\n\t\t/* DH is a special-case that doesn't really have an encrypt function \n\t\t   and where \"decryption\" is actually a derivation */\n\t\tcapabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;\n\t\tcapabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;\n\t\t}\n\n\t/* Keygen capabilities are generally present as separate mechanisms,\n\t   sometimes CKF_GENERATE/CKF_GENERATE_KEY_PAIR is set for the main \n\t   mechanism and sometimes it's set for the separate one so if it isn't \n\t   present in the main one we check the alternative one */\n\tif( !( pMechanism.flags & keyGenFlag ) && \\\n\t\t( mechanismInfoPtr->keygenMechanism != CKM_NONE ) )\n\t\t{\n\t\tstatus = C_GetMechanismInfo( pkcs11Info->slotID, \n\t\t\t\t\t\t\t\t\t mechanismInfoPtr->keygenMechanism,\n\t\t\t\t\t\t\t\t\t &pMechanism );\n\t\tif( status == CKR_OK && ( pMechanism.flags & keyGenFlag ) && \\\n\t\t\t( !hardwareOnly || ( pMechanism.flags & CKF_HW ) ) )\n\t\t\t{\n\t\t\t/* Some tinkertoy tokens don't implement key generation in \n\t\t\t   hardware but instead do it on the host PC (!!!) and load the\n\t\t\t   key into the token afterwards, so we have to perform another \n\t\t\t   check here to make sure that they're doing things right */\n\t\t\tcapabilityInfo->generateKeyFunction = \\\n\t\t\t\t\t\t\t\t\tmechanismInfoPtr->generateKeyFunction;\n\t\t\t}\n\t\t}\n\n\t/* Record mechanism-specific parameters if required */\n\tif( isConvAlgo( cryptAlgo ) || isMacAlgo( cryptAlgo ) )\n\t\t{\n\t\tcapabilityInfo->paramKeyType = mechanismInfoPtr->keyType;\n\t\tcapabilityInfo->paramKeyGen = mechanismInfoPtr->keygenMechanism;\n\t\tcapabilityInfo->paramDefaultMech = mechanismInfoPtr->defaultMechanism;\n\t\t}\n\n\t/* Some drivers report bizarre combinations of capabilities like (for \n\t   RSA) sign, verify, and decrypt but not encrypt, which will fail later \n\t   sanity checks.  If we run into one of these we force the capabilities \n\t   to be consistent by disabling any for which only partial capabilities\n\t   are supported */\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( capabilityInfo->decryptFunction != NULL && \\\n\t\t\tcapabilityInfo->encryptFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Driver reports decryption but not encryption \"\n\t\t\t\t\t\t \"capability for %s algorithm, disabling \"\n\t\t\t\t\t\t \"encryption\", capabilityInfo->algoName ));\n\t\t\tcapabilityInfo->decryptFunction = NULL;\n\t\t\t}\n\t\tif( capabilityInfo->signFunction != NULL && \\\n\t\t\tcapabilityInfo->sigCheckFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Driver reports signature-generation but not \"\n\t\t\t\t\t\t \"signature-verification capability for %s \"\n\t\t\t\t\t\t \"algorithm, disabling signing\", \n\t\t\t\t\t\t capabilityInfo->algoName ));\n\t\t\tcapabilityInfo->signFunction = NULL;\n\t\t\t}\n\n\t\t/* If we've now disabled all capabilities, we can't use this \n\t\t   algorithm */\n\t\tif( capabilityInfo->decryptFunction == NULL && \\\n\t\t\tcapabilityInfo->signFunction == NULL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Use of algorithm %s disabled since no consistent \"\n\t\t\t\t\t\t \"set of capabilities is available\", \n\t\t\t\t\t\t capabilityInfo->algoName ));\n\t\t\tclFree( \"getCapability\", capabilityInfo );\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( NULL );\n\t\t\t}\n\t\t}\n\n\t/* If it's not a conventional encryption algo, we're done */\n\tif( !isConvAlgo( cryptAlgo ) )\n\t\treturn( ( CAPABILITY_INFO * ) capabilityInfo );\n\n\t/* PKCS #11 handles encryption modes by defining a separate mechanism for\n\t   each one.  In order to enumerate all the modes available for a \n\t   particular algorithm we check for each mechanism in turn and set up \n\t   the appropriate function pointers if it's available */\n\tLOOP_MED( ( mechanismInfoPtr++, noMechanisms = 0 ), \n\t\t\t  mechanismInfoPtr->cryptAlgo == cryptAlgo && \\\n\t\t\t\tnoMechanisms < maxMechanisms, \n\t\t\t  ( mechanismInfoPtr++, noMechanisms++ ) )\n\t\t{\n\t\t/* There's a different form of the existing mechanism available,\n\t\t   check whether the driver implements it */\n\t\tstatus = C_GetMechanismInfo( pkcs11Info->slotID, \n\t\t\t\t\t\t\t\t\t mechanismInfoPtr->mechanism,\n\t\t\t\t\t\t\t\t\t &pMechanism );\n\t\tif( status != CKR_OK )\n\t\t\tcontinue;\n\n\t\t/* Set up the pointer for the appropriate encryption mode */\n\t\tswitch( mechanismInfoPtr->cryptMode )\n\t\t\t{\n\t\t\tcase CRYPT_MODE_CBC:\n\t\t\t\tif( pMechanism.flags & CKF_ENCRYPT )\n\t\t\t\t\tcapabilityInfo->encryptCBCFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\t\tif( pMechanism.flags & CKF_DECRYPT )\n\t\t\t\t\tcapabilityInfo->decryptCBCFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n#ifdef USE_CFB\n\t\t\tcase CRYPT_MODE_CFB:\n\t\t\t\tif( pMechanism.flags & CKF_ENCRYPT )\n\t\t\t\t\tcapabilityInfo->encryptCFBFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\t\tif( pMechanism.flags & CKF_DECRYPT )\n\t\t\t\t\tcapabilityInfo->decryptCFBFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n#endif /* USE_CFB */\n\t\t\tcase CRYPT_MODE_GCM:\n\t\t\t\tif( pMechanism.flags & CKF_ENCRYPT )\n\t\t\t\t\tcapabilityInfo->encryptGCMFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->encryptFunction;\n\t\t\t\tif( pMechanism.flags & CKF_DECRYPT )\n\t\t\t\t\tcapabilityInfo->decryptGCMFunction = \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfoPtr->decryptFunction;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Null();\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( noMechanisms < maxMechanisms );\n\n\treturn( ( CAPABILITY_INFO * ) capabilityInfo );\n\t}\n\n/* Set the capability information based on device capabilities.  Since\n   PKCS #11 devices can have assorted capabilities (and can vary depending\n   on what's plugged in), we have to build this up on the fly rather than\n   using a fixed table like the built-in capabilities */\n\nstatic void freeCapabilities( DEVICE_INFO *deviceInfo )\n\t{\n\tCAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t( CAPABILITY_INFO_LIST * ) DATAPTR_GET( deviceInfo->capabilityInfoList );\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES_V( DATAPTR_ISVALID( deviceInfo->capabilityInfoList ) );\n\n\t/* If the list was empty, return now */\n\tif( capabilityInfoListPtr == NULL )\n\t\treturn;\n\tDATAPTR_SET( deviceInfo->capabilityInfoList, NULL );\n\n\tassert( isWritePtr( capabilityInfoListPtr, \n\t\t\t\t\t\tsizeof( CAPABILITY_INFO_LIST ) ) );\n\n\tLOOP_MED_CHECK( capabilityInfoListPtr != NULL )\n\t\t{\n\t\tCAPABILITY_INFO_LIST *listItemToFree = capabilityInfoListPtr;\n\t\tCAPABILITY_INFO *itemToFree = \\\n\t\t\t\t( CAPABILITY_INFO * ) DATAPTR_GET( listItemToFree->info );\n\n\t\tREQUIRES_V( itemToFree != NULL );\n\t\tREQUIRES_V( sanityCheckCapability( itemToFree ) );\n\t\tREQUIRES_V( DATAPTR_ISVALID( capabilityInfoListPtr->next ) );\n\t\tcapabilityInfoListPtr = DATAPTR_GET( capabilityInfoListPtr->next );\n\n\t\tzeroise( itemToFree, sizeof( CAPABILITY_INFO ) );\n\t\tclFree( \"freeCapabilities\", itemToFree );\n\t\tzeroise( listItemToFree, sizeof( CAPABILITY_INFO_LIST ) );\n\t\tclFree( \"freeCapabilities\", listItemToFree );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\nstatic int getCapabilities( DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tconst PKCS11_MECHANISM_INFO *mechanismInfoPtr, \n\t\t\t\t\t\t\tconst int maxMechanisms )\n\t{\n\tCAPABILITY_INFO_LIST *capabilityInfoListTail = \\\n\t\t( CAPABILITY_INFO_LIST * ) DATAPTR_GET( deviceInfo->capabilityInfoList );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( mechanismInfoPtr, \\\n\t\t\t\t\t\t\t  maxMechanisms * sizeof( PKCS11_MECHANISM_INFO ) ) );\n\n\tstatic_assert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ),\n\t\t\t\t   \"Variable capability-info-struct\" );\n\n\tREQUIRES( DATAPTR_ISVALID( deviceInfo->capabilityInfoList ) );\n\n\t/* Find the end of the list to add new capabilities */\n\tif( capabilityInfoListTail != NULL )\n\t\t{\n\t\tLOOP_MED_CHECK( DATAPTR_ISSET( capabilityInfoListTail->next ) )\n\t\t\t{\n\t\t\tcapabilityInfoListTail =\t\n\t\t\t\t\tDATAPTR_GET( capabilityInfoListTail->next );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( capabilityInfoListTail != NULL );\n\t\t}\n\n\t/* Add capability information for each recognised mechanism type */\n\tLOOP_MED( i = 0, i < maxMechanisms && \\\n\t\t\t\t\t mechanismInfoPtr[ i ].mechanism != CKM_NONE, i++ )\n\t\t{\n\t\tCAPABILITY_INFO_LIST *newCapabilityList;\n\t\tCAPABILITY_INFO *newCapability;\n\t\tconst CRYPT_ALGO_TYPE cryptAlgo = mechanismInfoPtr[ i ].cryptAlgo;\n\n\t\t/* If the assertion below triggers then the PKCS #11 driver is \n\t\t   broken since it's returning inconsistent information such as \n\t\t   illegal key length data, conflicting algorithm information, etc \n\t\t   etc.  This assertion is included here to detect buggy drivers \n\t\t   early on rather than forcing users to step through the PKCS #11 \n\t\t   glue code to find out why an operation is failing.\n\t\t   \n\t\t   Because some tinkertoy implementations support only the bare \n\t\t   minimum functionality (e.g.RSA private key ops and nothing else),\n\t\t   we allow asymmetric functionality for PKCs */\n\t\tnewCapability = getCapability( deviceInfo, &mechanismInfoPtr[ i ],\n\t\t\t\t\t\t\t\t\t   maxMechanisms - i );\n\t\tif( newCapability == NULL )\n\t\t\tcontinue;\n\t\tREQUIRES( sanityCheckCapability( newCapability ) );\n\t\tif( ( newCapabilityList = \\\n\t\t\t\t\t\tclAlloc( \"getCapabilities\", \\\n\t\t\t\t\t\t\t\t sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"getCapabilities\", newCapability );\n\t\t\tcontinue;\n\t\t\t}\n\t\tDATAPTR_SET( newCapabilityList->info, newCapability );\n\t\tDATAPTR_SET( newCapabilityList->next, NULL );\n\t\tif( DATAPTR_ISNULL( deviceInfo->capabilityInfoList ) )\n\t\t\t{\n\t\t\tDATAPTR_SET( deviceInfo->capabilityInfoList, \n\t\t\t\t\t\t newCapabilityList );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tDATAPTR_SET( capabilityInfoListTail->next, \n\t\t\t\t\t\t newCapabilityList );\n\t\t\t}\n\t\tcapabilityInfoListTail = newCapabilityList;\n\n\t\t/* Since there may be alternative mechanisms to the current one \n\t\t   defined, we have to skip mechanisms until we find a ones for a\n\t\t   new algorithm */\n\t\tLOOP_MED_CHECKINC( mechanismInfoPtr[ i + 1 ].cryptAlgo == cryptAlgo && \\\n\t\t\t\t\t\t   i < maxMechanisms, i++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < maxMechanisms );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < maxMechanisms );\n\n\treturn( ( DATAPTR_ISNULL( deviceInfo->capabilityInfoList ) ) ? \\\n\t\t\tCRYPT_ERROR : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDevice Init/Shutdown/Device Control Routines\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Close a previously-opened session with the device.  We have to have this\n   before the initialisation function since it may be called by it if the \n   initialisation process fails */\n\nstatic void shutdownFunction( DEVICE_INFO *deviceInfo )\n\t{\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\t/* Log out and close the session with the device */\n\tif( TEST_FLAG( deviceInfo->flags, DEVICE_FLAG_LOGGEDIN ) )\n\t\tC_Logout( pkcs11Info->hSession );\n\tC_CloseSession( pkcs11Info->hSession );\n\tpkcs11Info->hSession = CK_OBJECT_NONE;\n\tCLEAR_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE | \\\n\t\t\t\t\t\t\t\t   DEVICE_FLAG_LOGGEDIN );\n\n\t/* Free the device capability information */\n\tfreeCapabilities( deviceInfo );\n\t}\n\n/* Open a session with the device */\n\nstatic int initFunction( DEVICE_INFO *deviceInfo, const char *name,\n\t\t\t\t\t\t const int nameLength )\n\t{\n\tCK_SESSION_HANDLE hSession;\n\tCK_SLOT_ID slotList[ MAX_PKCS11_SLOTS + 8 ];\n\tCK_ULONG slotCount = MAX_PKCS11_SLOTS;\n\tCK_SLOT_INFO slotInfo;\n\tCK_TOKEN_INFO tokenInfo;\n\tCK_RV status;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tconst PKCS11_MECHANISM_INFO *mechanismInfoPtr;\n\tchar *labelPtr;\n\tint tokenSlot = DEFAULT_SLOT, i, labelLength, mechanismInfoSize;\n\tint cryptStatus, cryptStatus2, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( nameLength ) );\n\n\t/* Get information on all available slots */\n\tmemset( slotList, 0, sizeof( slotList ) );\n\tstatus = C_GetSlotList( CK_TRUE, slotList, &slotCount );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_OPEN ) );\n\tif( slotCount <= 0 )\n\t\t{\n\t\t/* There are token slots present but no tokens in the slots */\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\t/* Check whether a token name (used to select the slot) has been \n\t   specified */\n\tLOOP_LARGE( i = 1, i < nameLength - 1, i++ )\n\t\t{\n\t\tif( name[ i ] == ':' && name[ i + 1 ] == ':' )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( i < nameLength - 1 )\n\t\t{\n\t\tconst char *tokenName = name + i + 2;\t/* Skip '::' */\n\t\tconst int tokenNameLength = nameLength - ( i + 2 );\n\n\t\tif( tokenNameLength <= 0 )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\t/* Some tokens don't implement named slots, so we also allow them to \n\t\t   be specified using slot counts */\n\t\tif( tokenNameLength == 1 && isDigit( *tokenName ) )\n\t\t\t{\n\t\t\ttokenSlot = *tokenName - '0';\n\t\t\tif( tokenSlot < 0 || tokenSlot > 9 )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( tokenSlot > slotCount - 1 )\t/* Slots numbered from zero */\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tstatus = C_GetTokenInfo( slotList[ tokenSlot ], &tokenInfo );\n\t\t\tif( status != CKR_OK )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Check each (named) slot for a token matching the given name */\n\t\t\tLOOP_MED( tokenSlot = 0, tokenSlot < slotCount, tokenSlot++ )\n\t\t\t\t{\n\t\t\t\tstatus = C_GetTokenInfo( slotList[ tokenSlot ], &tokenInfo );\n\t\t\t\tif( status == CKR_OK && \\\n\t\t\t\t\t!strCompare( tokenName, tokenInfo.label, tokenNameLength ) )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tif( tokenSlot >= slotCount )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t}\n\tpkcs11Info->slotID = slotList[ tokenSlot ];\n\n\t/* Get information on device-specific capabilities */\n\tstatus = C_GetSlotInfo( pkcs11Info->slotID, &slotInfo );\n\tif( status != CKR_OK )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_OPEN ) );\n\t\t}\n\tif( slotInfo.flags & CKF_REMOVABLE_DEVICE )\n\t\t{\n\t\t/* The device is removable */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_REMOVABLE );\n\t\t}\n\tstatus = C_GetTokenInfo( pkcs11Info->slotID, &tokenInfo );\n\tif( status != CKR_OK )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_OPEN ) );\n\t\t}\n\tif( tokenInfo.flags & CKF_RNG )\n\t\t{\n\t\t/* The device has an onboard RNG that we can use */\n\t\tFNPTR_SET( deviceInfo->getRandomFunction, getRandomFunction );\n\t\t}\n#if 0\t/* The Spyrus driver for pre-Lynks-II cards returns the local system \n\t\t   time (with a GMT/localtime offset), ignoring the fact that the \n\t\t   token has an onboard clock, so having the CKF_CLOCK_ON_TOKEN not \n\t\t   set is accurate, although having it ignore the presence of the \n\t\t   clock isn't very valid */\n\tif( !( tokenInfo.flags & CKF_CLOCK_ON_TOKEN ) && \\\n\t\t( !strCompare( tokenInfo.label, \"Lynks Token\", 11 ) || \\\n\t\t  !strCompare( tokenInfo.model, \"Rosetta\", 7 ) ) )\n\t\t{\n\t\t/* Fix buggy Spyrus PKCS #11 drivers which claim that the token\n\t\t   doesn't have a RTC even though it does (the Rosetta (smart card) \n\t\t   form of the token is even worse, it returns garbage in the label \n\t\t   and manufacturer fields, but the model field is OK).  There is a \n\t\t   chance that there's a genuine problem with the clock (there are \n\t\t   batches of tokens with bad clocks) but the time check that  \n\t\t   follows below will catch those */\n\t\ttokenInfo.flags |= CKF_CLOCK_ON_TOKEN;\n\t\t}\n#endif /* 0 */\n\tif( tokenInfo.flags & CKF_CLOCK_ON_TOKEN )\n\t\t{\n\t\tconst time_t theTime = getTokenTime( &tokenInfo );\n\t\tconst time_t currentTime = getTime();\n\n\t\t/* The token claims to have an onboard clock that we can use.  Since\n\t\t   this could be arbitrarily inaccurate we compare it with the \n\t\t   system time and only rely on it if it's within +/- 1 day of the\n\t\t   system time.\n\t\t   \n\t\t   There is a second check that we should make to catch drivers that\n\t\t   claim to read the time from the token but actually use the local\n\t\t   computer's time, but this isn't easy to do.  The most obvious way\n\t\t   is to set the system time to a bogus value and check whether this\n\t\t   matches the returned time, but this is somewhat drastic and \n\t\t   requires superuser privs on most systems.  An alternative is to \n\t\t   check whether the claimed token time exactly matches the system \n\t\t   time, but this will produce false positives if (for example) the\n\t\t   token has been recently synchronised to the system time.  For now\n\t\t   all we can do is throw an exception if it appears that the token\n\t\t   time is faked */\n\t\tif( theTime > MIN_TIME_VALUE && \\\n\t\t\ttheTime >= currentTime - 86400 && \\\n\t\t\ttheTime <= currentTime + 86400 )\n\t\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_TIME );\n\n\t\t/* If this check is triggered then the token time may be faked since \n\t\t   it's identical to the host system time, see the comment above for \n\t\t   details.  We make an exception for soft-tokens (if we can detect \n\t\t   them), which will (by definition) have the same time as the \n\t\t   system time */\n\t\tif( !( pkcs11InfoTbl[ pkcs11Info->deviceNo ].name[ 0 ] && \\\n\t\t\t   !strCompare( pkcs11InfoTbl[ pkcs11Info->deviceNo ].name, \n\t\t\t\t\t\t\t\"Software\", 8 ) ) && \\\n\t\t\ttheTime == currentTime )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"PKCS #11 token time is the same as the host \"\n\t\t\t\t\t\t \"system time, token time may be faked by the \"\n\t\t\t\t\t\t \"driver.\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\t}\n\t\t}\n\tif( tokenInfo.flags & CKF_WRITE_PROTECTED )\n\t\t{\n\t\t/* The device can't have data on it changed */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_READONLY );\n\t\t}\n\tif( ( tokenInfo.flags & CKF_LOGIN_REQUIRED ) || \\\n\t\t!( tokenInfo.flags & CKF_USER_PIN_INITIALIZED ) )\n\t\t{\n\t\t/* The user needs to log in before using various device functions.\n\t\t   We check for the absence of CKF_USER_PIN_INITIALIZED as well as \n\t\t   the more obvious CKF_LOGIN_REQUIRED because if we've got an \n\t\t   uninitialised device there's no PIN set so some devices will \n\t\t   report that there's no login required (or at least none is \n\t\t   possible).  We need to introduce some sort of pipeline stall if \n\t\t   this is the case because otherwise the user could successfully \n\t\t   perform some functions that don't require a login (where the \n\t\t   exact details of what's allowed without a login are device-\n\t\t   specific) before running into mysterious failures when they get \n\t\t   to functions that do require a login.  To avoid this, we make an \n\t\t   uninitialised device look like a login-required device, so the \n\t\t   user gets an invalid-PIN error if they try and proceed */\n\t\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_NEEDSLOGIN );\n\t\t}\n\tif( !isIntegerRange( tokenInfo.ulMinPinLen ) || \\\n\t\t( pkcs11Info->minPinSize = ( int ) tokenInfo.ulMinPinLen ) < 4 )\n\t\t{\n\t\t/* Some devices report silly PIN sizes */\n\t\tDEBUG_DIAG(( \"Driver reports suspicious minimum PIN size %lu, \"\n\t\t\t\t\t \"using 4\", tokenInfo.ulMinPinLen ));\n\t\tpkcs11Info->minPinSize = 4;\n\t\t}\n\tif( !isIntegerRange( tokenInfo.ulMaxPinLen ) || \\\n\t\t( pkcs11Info->maxPinSize = ( int ) tokenInfo.ulMaxPinLen ) < 4 )\n\t\t{\n\t\t/* Some devices report silly PIN sizes (setting this to ULONG_MAX or\n\t\t   4GB, which becomes -1 as an int, counts as silly).  Since we can't\n\t\t   differentiate between 0xFFFFFFFF = bogus value and 0xFFFFFFFF = \n\t\t   ULONG_MAX we play it safe and set the limit to 8 bytes, which most\n\t\t   devices should be able to handle */\n\t\tDEBUG_DIAG(( \"Driver reports suspicious maximum PIN size %lu, \"\n\t\t\t\t\t \"using 8\", tokenInfo.ulMinPinLen ));\n\t\tpkcs11Info->maxPinSize = 8;\n\t\t}\n\tif( pkcs11Info->maxPinSize > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\t/* Similarly, some drivers will report the maximum PIN size as \n\t\t   whatever the developer chose to hardcode in, if we get a\n\t\t   suspiciously large PIN size we clip it at CRYPT_MAX_TEXTSIZE */\n\t\tpkcs11Info->maxPinSize = CRYPT_MAX_TEXTSIZE;\n\t\t}\n\tstatus = labelLength = \\\n\t\t\t\tstrStripWhitespace( &labelPtr, tokenInfo.label, 32 );\n\tif( !cryptStatusError( status ) && labelLength > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( labelLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( pkcs11Info->labelBuffer, labelPtr, labelLength );\n\t\tsanitiseString( pkcs11Info->labelBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\tlabelLength );\n\t\t}\n\telse\n\t\t{\n\t\t/* There's no label for the token, use the device label instead */\n\t\tif( pkcs11InfoTbl[ pkcs11Info->deviceNo ].name[ 0 ] )\n\t\t\t{\n\t\t\tlabelLength = \\\n\t\t\t\tmin( strlen( pkcs11InfoTbl[ pkcs11Info->deviceNo ].name ),\n\t\t\t\t\t CRYPT_MAX_TEXTSIZE );\n\n\t\t\tREQUIRES( rangeCheck( labelLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( pkcs11Info->labelBuffer, \n\t\t\t\t\tpkcs11InfoTbl[ pkcs11Info->deviceNo ].name, labelLength );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tmemcpy( pkcs11Info->labelBuffer, \"<<<Unknown>>>\", 13 );\n\t\t\tlabelLength = 13;\n\t\t\t}\n\t\t}\n\tpkcs11Info->hActiveSignObject = CK_OBJECT_NONE;\n\tdeviceInfo->label = pkcs11Info->labelBuffer;\n\tdeviceInfo->labelLen = labelLength;\n\n\t/* Open a session with the device.  This gets a bit awkward because we \n\t   can't tell whether a R/W session is OK without opening a session, but \n\t   we can't open a session unless we know whether a R/W session is OK, \n\t   so we first try for a RW session and if that fails we go for a read-\n\t   only session */\n\tstatus = C_OpenSession( pkcs11Info->slotID, \n\t\t\t\t\t\t\tCKF_RW_SESSION | CKF_SERIAL_SESSION, NULL_PTR, \n\t\t\t\t\t\t\tNULL_PTR, &hSession );\n\tif( status == CKR_TOKEN_WRITE_PROTECTED )\n\t\t{\n\t\tstatus = C_OpenSession( pkcs11Info->slotID, \n\t\t\t\t\t\t\t\tCKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, \n\t\t\t\t\t\t\t\t&hSession );\n\t\t}\n\tif( status != CKR_OK )\n\t\t{\n\t\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_OPEN );\n\t\tif( cryptStatus == CRYPT_ERROR_OPEN && \\\n\t\t\t!( tokenInfo.flags & CKF_USER_PIN_INITIALIZED ) )\n\t\t\t{\n\t\t\t/* We couldn't do much with the error code, it could be that the\n\t\t\t   token hasn't been initialised yet but unfortunately PKCS #11 \n\t\t\t   doesn't define an error code for this condition.  In addition\n\t\t\t   many tokens will allow a session to be opened and then fail \n\t\t\t   with a \"PIN not set\" error at a later point (which allows for\n\t\t\t   more accurate error reporting), however a small number won't\n\t\t\t   allow a session to be opened and return some odd-looking error\n\t\t\t   because there's nothing useful available.  The best way to\n\t\t\t   report this in a meaningful manner to the caller is to check\n\t\t\t   whether the user PIN has been initialised, if it hasn't then \n\t\t\t   it's likely that the token as a whole hasn't been initialised \n\t\t\t   so we return a not initialised error */\n\t\t\tcryptStatus = CRYPT_ERROR_NOTINITED;\n\t\t\t}\n\t\treturn( cryptStatus );\n\t\t}\n\tENSURES( hSession != CK_OBJECT_NONE );\n\tpkcs11Info->hSession = hSession;\n\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE );\n\n\t/* Set up the capability information for this device.  Since there can \n\t   be devices that have one set of capabilities but not the other (e.g.\n\t   a smart card that only performs RSA ops), we allow one of the two\n\t   sets of mechanism information setups to fail, but not both */\n\tmechanismInfoPtr = getMechanismInfoPKC( &mechanismInfoSize );\n\tcryptStatus = getCapabilities( deviceInfo, mechanismInfoPtr, \n\t\t\t\t\t\t\t\t   mechanismInfoSize );\n\tmechanismInfoPtr = getMechanismInfoConv( &mechanismInfoSize );\n\tcryptStatus2 = getCapabilities( deviceInfo, mechanismInfoPtr, \n\t\t\t\t\t\t\t\t\tmechanismInfoSize );\n\tif( cryptStatusError( cryptStatus ) && cryptStatusError( cryptStatus2 ) )\n\t\t{\n\t\tshutdownFunction( deviceInfo );\n\t\treturn( ( cryptStatus == CRYPT_ERROR ) ? \\\n\t\t\t\tCRYPT_ERROR_OPEN : cryptStatus );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Set up the function pointers to the init/shutdown methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initPKCS11Init( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\tIN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\tIN_LENGTH_SHORT const int nameLength )\n\t{\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tint i, driverNameLength = nameLength, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( nameLength ) );\n\n\t/* Make sure that the PKCS #11 driver DLL's are loaded */\n\tif( !pkcs11Initialised )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\t/* Check whether there's a token name appended to the driver name */\n\tLOOP_LARGE( i = 1, i < nameLength - 1, i++ )\n\t\t{\n\t\tif( name[ i ] == ':' && name[ i + 1 ] == ':' )\n\t\t\t{\n\t\t\tdriverNameLength = i;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we're auto-detecting the device, use the first one that we find.  \n\t   There are two basic approaches to this, to keep going until we find\n\t   something that responds, or to try the first device and report an\n\t   error if it doesn't respond.  Both have their own problems, keeping\n\t   going will find (for example) the device in slot 2 if slot 1 is \n\t   empty, but will also return a completely unexpected device if slot 1\n\t   contains a device that isn't responding for some reason.  Conversely,\n\t   only checking the first device will fail if slot 1 is empty but slot\n\t   2 isn't.  Users seem to prefer the obvious-fail approach, so we only\n\t   check the first device and fail if there's a problem.  If they\n\t   explicitly want a secondary slot, they can specify it by name */\n\tif( driverNameLength == 12 && \\\n\t\t!strnicmp( \"[Autodetect]\", name, driverNameLength ) )\n\t\t{\n\t\tif( !pkcs11InfoTbl[ 0 ].name[ 0 ] )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\tpkcs11Info->deviceNo = 0;\n\t\t}\n\telse\n\t\t{\n\t\t/* Try and find the driver based on its name */\n\t\tLOOP_MED( i = 0, i < MAX_PKCS11_DRIVERS, i++ )\n\t\t\t{\n\t\t\tif( !strnicmp( pkcs11InfoTbl[ i ].name, name, driverNameLength ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( i >= MAX_PKCS11_DRIVERS )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\tpkcs11Info->deviceNo = i;\n\t\t}\n\n\t/* Set up remaining function and access information */\n\tFNPTR_SET( deviceInfo->initFunction, initFunction );\n\tFNPTR_SET( deviceInfo->shutdownFunction, shutdownFunction );\n\tdeviceInfo->devicePKCS11->functionListPtr = \\\n\t\t\t\t\tpkcs11InfoTbl[ pkcs11Info->deviceNo ].functionListPtr;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11_pkc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #11 PKC Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Tell context.h that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"pkcs11_api.h\"\n  #include \"asn1.h\"\n  #include \"asn1.h_ext\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/pkcs11_api.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS11\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an attribute value, used to read public-key components.  The odd \n   two-phase read is necessary for buggy implementations that fail if the \n   given size isn't exactly the same as the data size */\n\nstatic int readAttributeValue( PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t   const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t   const CK_ATTRIBUTE_TYPE attrType, \n\t\t\t\t\t\t\t   void *buffer, const int bufMaxLen,\n\t\t\t\t\t\t\t   int *length )\n\t{\n\tCK_ATTRIBUTE attrTemplate = { attrType, NULL_PTR, bufMaxLen };\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, bufMaxLen ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\t/* Clear return value */\n\tmemset( buffer, 0, min( 16, bufMaxLen ) );\n\t*length = CRYPT_ERROR;\n\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject, \n\t\t\t\t\t\t\t\t  &attrTemplate, 1 );\n\tif( status == CKR_OK )\n\t\t{\n\t\tattrTemplate.pValue = buffer;\n\t\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject, \n\t\t\t\t\t\t\t\t\t  &attrTemplate, 1 );\n\t\t}\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusOK( status ) )\n\t\t*length = attrTemplate.ulValueLen;\n\treturn( cryptStatus );\n\t}\n\n/* Set an entry in a template to a given value.  To make this easier to call \n   we wrap it in a macro that takes care of the FAILSAFE_ARRAYSIZE that's\n   required for each call */\n\n#define setTemplate( template, attribute, value, length ) \\\n\t\tsetTemplateEntry( template, \\\n\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( template, CK_ATTRIBUTE ), \\\n\t\t\t\t\t\t  attribute, value, length )\n\nstatic void setTemplateEntry( INOUT_ARRAY( templateSize ) \\\n\t\t\t\t\t\t\t\tCK_ATTRIBUTE *template, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int templateSize, \n\t\t\t\t\t\t\t  const CK_ATTRIBUTE_TYPE attribute, \n\t\t\t\t\t\t\t  IN_BUFFER( length ) const void *value, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int length )\n\t{\n\tCK_ATTRIBUTE *templatePtr = NULL;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( template, \\\n\t\t\t\t\t\t\t   templateSize * sizeof( CK_ATTRIBUTE ) ) );\n\tassert( isReadPtrDynamic( value, length ) );\n\n\tREQUIRES_V( templateSize > 0 && templateSize < 100 );\n\tREQUIRES_V( isShortIntegerRangeNZ( length ) );\n\n\tLOOP_MED( i = 0, i < templateSize && template[ i ].type != CKA_NONE, i++ )\n\t\t{\n\t\tif( template[ i ].type == attribute )\n\t\t\t{\n\t\t\ttemplatePtr = &template[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( templatePtr != NULL );\n\ttemplatePtr->pValue = ( void * ) value;\n\ttemplatePtr->ulValueLen = length;\n\t}\n\n/* Count the number of entries in a template.  Since arrays are oversized by \n   two entries and FAILSAFE_ARRAYSIZE is the array size - 1, the template \n   size should equal FAILSAFE_ARRAYSIZE, with the array size being one \n   smaller than that.\n   \n   For the debug build we check that this is actually the case, for the \n   release build we just return the (constant) value FAILSAFE_ARRAYSIZE - 1 */\n\n#ifdef NDEBUG\n  #define templateCount( template ) \\\n\t\t  FAILSAFE_ARRAYSIZE( template, CK_ATTRIBUTE ) - 1\n#else\n\n#define templateCount( template ) \\\n\t\ttemplateEntryCount( template, \\\n\t\t\t\t\t\t    FAILSAFE_ARRAYSIZE( template, CK_ATTRIBUTE ) )\n\nstatic int templateEntryCount( IN_ARRAY( templateSize ) \\\n\t\t\t\t\t\t\t\t\tconst CK_ATTRIBUTE *template, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int templateSize )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( template, \\\n\t\t\t\t\t\t\t  templateSize * sizeof( CK_ATTRIBUTE ) ) );\n\n\tREQUIRES_EXT( templateSize > 0 && templateSize < 100, 0 );\n\n\tLOOP_MED( i = 0, i < templateSize && template[ i ].type != CKA_NONE, i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, 0 );\n\tENSURES_EXT( i == templateSize - 1, 0 );\n\n\treturn( i );\n\t}\n#endif /* Release vs. debug build */\n\n/* When we've generated or loaded a key, the underlying device may impose\n   additional usage restrictions on it that go beyond what we've requested \n   at object-creation time.  In order to deal with this we read back the \n   attributes that are set for the newly-created device object and update \n   the object's action flags to reflect this */\n\nstatic int updateActionFlags( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t  const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t  const BOOLEAN isPrivateKey )\n\t{\n\tint actionFlags, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\tcryptStatus = actionFlags = \\\n\t\t\tgetActionFlags( pkcs11Info, hObject, \n\t\t\t\t\t\t\tisPrivateKey ? KEYMGMT_ITEM_PRIVATEKEY : \\\n\t\t\t\t\t\t\t\t\t\t   KEYMGMT_ITEM_PUBLICKEY, \n\t\t\t\t\t\t\tcryptAlgo );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t ( MESSAGE_CAST ) &actionFlags, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ACTIONPERMS ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tCapability Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sign data, check a signature.  We use Sign and Verify rather than the\n   xxxRecover variants because there's no need to use Recover, and because\n   many implementations don't do Recover */\n\nstatic int genericSign( PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\tCONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\tconst CK_MECHANISM *pMechanism, \n\t\t\t\t\t\tconst void *inBuffer, const int inLength, \n\t\t\t\t\t\tvoid *outBuffer, const int outLength )\n\t{\n\tCK_ULONG resultLen = outLength;\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\tassert( isWritePtrDynamic( outBuffer, outLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( inLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( outLength ) );\n\n\t/* If we're currently in the middle of a multi-stage sign operation we\n\t   can't start a new one.  We have to perform this tracking explicitly \n\t   since PKCS #11 only allows one multi-stage operation per session */\n\tif( pkcs11Info->hActiveSignObject != CK_OBJECT_NONE )\n\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\n\tstatus = C_SignInit( pkcs11Info->hSession,\n\t\t\t\t\t\t ( CK_MECHANISM_PTR ) pMechanism, \n\t\t\t\t\t\t contextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\tstatus = C_Sign( pkcs11Info->hSession, ( CK_BYTE_PTR ) inBuffer, \n\t\t\t\t\t\t inLength, outBuffer, &resultLen );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int genericVerify( PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t  CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t  const CK_MECHANISM *pMechanism, \n\t\t\t\t\t\t  const void *inBuffer, const int inLength, \n\t\t\t\t\t\t  void *outBuffer, const int outLength )\n\t{\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );\n\tassert( isReadPtrDynamic( inBuffer, inLength ) );\n\tassert( isWritePtrDynamic( outBuffer, outLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( inLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( outLength ) );\n\n\t/* If we're currently in the middle of a multi-stage sign operation we\n\t   can't start a new one.  We have to perform this tracking explicitly \n\t   since PKCS #11 only allows one multi-stage operation per session */\n\tif( pkcs11Info->hActiveSignObject != CK_OBJECT_NONE )\n\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\n\tstatus = C_VerifyInit( pkcs11Info->hSession,\n\t\t\t\t\t\t   ( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t   contextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\tstatus = C_Verify( pkcs11Info->hSession, ( CK_BYTE_PTR ) inBuffer, \n\t\t\t\t\t\t   inLength, outBuffer, outLength );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encrypt, decrypt */\n\nstatic int genericEncrypt( PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t   CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const CK_MECHANISM *pMechanism, void *buffer,\n\t\t\t\t\t\t   const int length, const int outLength )\n\t{\n\tCK_ULONG resultLen = outLength;\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtrDynamic( buffer, outLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( isShortIntegerRangeNZ( outLength ) );\n\n\tstatus = C_EncryptInit( pkcs11Info->hSession,\n\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t\tcontextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\t{\n\t\tstatus = C_Encrypt( pkcs11Info->hSession, buffer, length,\n\t\t\t\t\t\t\tbuffer, &resultLen );\n\t\t}\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\t/* When performing RSA operations some buggy implementations perform \n\t   leading-zero trunction, so we restore leading zeroes if necessary */\n\tENSURES( isIntegerRange( resultLen ) );\n\tif( ( pMechanism->mechanism == CKM_RSA_X_509 || \\\n\t\t  pMechanism->mechanism == CKM_RSA_PKCS ) && \\\n\t\t( int ) resultLen < length )\n\t\t{\n\t\tconst int delta = length - resultLen;\n\n\t\tREQUIRES( boundsCheck( delta, resultLen, length ) );\n\t\tmemmove( ( BYTE * ) buffer + delta, buffer, resultLen );\n\t\tmemset( buffer, 0, delta );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int genericDecrypt( PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t   CONTEXT_INFO *contextInfoPtr,\n\t\t\t\t\t\t   const CK_MECHANISM *pMechanism, void *buffer,\n\t\t\t\t\t\t   const int length, int *resultLength )\n\t{\n\tCK_ULONG resultLen = length;\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtr( pMechanism, sizeof( CK_MECHANISM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( resultLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\tstatus = C_DecryptInit( pkcs11Info->hSession,\n\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t\tcontextInfoPtr->deviceObject );\n\tif( status == CKR_OK )\n\t\tstatus = C_Decrypt( pkcs11Info->hSession, buffer, length,\n\t\t\t\t\t\t\tbuffer, &resultLen );\n\tif( status == CKR_KEY_FUNCTION_NOT_PERMITTED )\n\t\t{\n\t\tstatic const CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY;\n\t\tstatic const CK_KEY_TYPE secretKeyType = CKK_GENERIC_SECRET;\n\t\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\t\tCK_ATTRIBUTE symTemplate[] = { \n\t\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &secretKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &secretKeyType, sizeof( CK_KEY_TYPE ) },\n\t\t\t{ CKA_EXTRACTABLE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t\t{ CKA_VALUE_LEN, &resultLen, sizeof( CK_ULONG ) },\n\t\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t\t};\n\t\tCK_OBJECT_HANDLE hSymKey;\n\n\t\t/* If a straight decrypt isn't allowed, try an unwrap instead and \n\t\t   then export the key.  This works because we're using the same\n\t\t   mechanism as for decrypt and converting the entire \"unwrapped key\"\n\t\t   into a generic secret key that we then extract, which is the\n\t\t   same as doing a straight decrypt of the data (this sort of thing\n\t\t   should require a note from your mother before you're allowed to do\n\t\t   it).  The reason why it's done in this roundabout manner is that \n\t\t   this is what Netscape tries first, so people doing a minimal \n\t\t   implementation do this first and don't bother with anything else.  \n\t\t   Note that doing it this way is rather slower than a straight \n\t\t   decrypt, which is why we try for decrypt first */\n\t\tstatus = C_UnwrapKey( pkcs11Info->hSession,\n\t\t\t\t\t\t\t  ( CK_MECHANISM_PTR ) pMechanism,\n\t\t\t\t\t\t\t  contextInfoPtr->deviceObject, buffer, length,\n\t\t\t\t\t\t\t  symTemplate, templateCount( symTemplate ), \n\t\t\t\t\t\t\t  &hSymKey );\n\t\tif( status == CKR_OK )\n\t\t\t{\n\t\t\tCK_ATTRIBUTE valueTemplate[] = { CKA_VALUE, buffer, length };\n\n\t\t\tstatus = C_GetAttributeValue( pkcs11Info->hSession, \n\t\t\t\t\t\t\t\t\t\t  hSymKey, valueTemplate, 1 );\n\t\t\tif( status == CKR_OK )\n\t\t\t\tresultLen = valueTemplate[ 0 ].ulValueLen;\n\t\t\tC_DestroyObject( pkcs11Info->hSession, hSymKey );\n\t\t\t}\n\t\t}\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\n\t/* When performing raw RSA operations some buggy implementations perform \n\t   leading-zero trunction, so we restore leading zeroes if necessary.  We\n\t   can't do the restore with the PKCS mechanism since it always returns a \n\t   result length shorter than the input length */\n\tENSURES( isIntegerRange( resultLen ) );\n\tif( pMechanism->mechanism == CKM_RSA_X_509 && \\\n\t\t( int ) resultLen < length )\n\t\t{\n\t\tconst int delta = length - resultLen;\n\n\t\tREQUIRES( boundsCheck( delta, resultLen, length ) );\n\t\tmemmove( ( BYTE * ) buffer + delta, buffer, resultLen );\n\t\tmemset( buffer, 0, delta );\n\t\tresultLen = length;\n\t\t}\n\n\t/* Some mechanisms change the data length, in which case we need to tell\n\t   the caller how much was actually returned */\n\tif( resultLength != NULL )\n\t\t*resultLength = ( int ) resultLen;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDH Mapping Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_DH\n\n/* DH algorithm-specific mapping functions.  These work somewhat differently\n   from the other PKC functions because DH objects are ephemeral, the only \n   fixed values being p and g.  In addition there's no real concept of \n   public and private keys, only an object where the CKA_VALUE attribute\n   contains y (nominally the public key) and one where it contains x\n   (nominally the private key).  The use of DH objects then is as follows:\n\n\tload/genkey: genkey with supplied p and g to produce x and y values;\n\t\t\t\t save \"public key\" (y) as altObjectHandle;\n\n\tDH phase 1:  return public key CKA_VALUE (= y);\n\n\tDH phase 2:  derive using private key, y' = mechanism parameters */\n\nint dhSetPublicComponents( PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t   const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t   const CK_OBJECT_HANDLE hDhKey,\n\t\t\t\t\t\t   const void *q, const int qLen )\n\t{\n\tBYTE p[ CRYPT_MAX_PKCSIZE + 8 ], g[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE y[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 3 ) + 8 ];\n\tMESSAGE_DATA msgData;\n\tint pLen, gLen DUMMY_INIT, yLen DUMMY_INIT, keyDataSize, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtrDynamic( q, qLen ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( qLen > 0 && qLen <= CRYPT_MAX_PKCSIZE );\n\n\t/* Get the public key components from the device */\n\tcryptStatus = readAttributeValue( pkcs11Info, hDhKey, CKA_PRIME, \n\t\t\t\t\t\t\t\t\t  p, CRYPT_MAX_PKCSIZE, &pLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hDhKey, CKA_BASE, \n\t\t\t\t\t\t\t\t\t\t  g, CRYPT_MAX_PKCSIZE, &gLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hDhKey, CKA_VALUE, \n\t\t\t\t\t\t\t\t\t\t  y, CRYPT_MAX_PKCSIZE, &yLen );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all that we're doing here is sending in encoded public key data for \n\t   use by objects such as certificates */\n\tcryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 3,\n\t\t\t\t\t\t\t\t\t  &keyDataSize, CRYPT_ALGO_DH, 0,\n\t\t\t\t\t\t\t\t\t  p, pLen, g, gLen, q, qLen, y, yLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\t\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t   &msgData, \n\t\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\t\t}\n\treturn( cryptStatus );\n\t}\n\nstatic int dhInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t  const int keyLength )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_DERIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_DERIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIME, NULL, 0 },\n\t\t{ CKA_BASE, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_OBJECT_HANDLE hPublicKey, hPrivateKey;\n\tCK_RV status;\n\tconst CRYPT_PKCINFO_DLP *dhKey = ( CRYPT_PKCINFO_DLP * ) key;\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( keyLength == sizeof( CRYPT_PKCINFO_DLP ) );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Generate the keys.  We can't set CKA_SENSITIVE for the private key \n\t   because although this is appropriate for the key (we don't want people\n\t   extracting the x value), some implementations carry it over to the \n\t   derived key in phase 2 and make that non-extractable as well */\n\tsetTemplate( publicKeyTemplate, CKA_PRIME, dhKey->p, dhKey->pLen );\n\tsetTemplate( publicKeyTemplate, CKA_BASE, dhKey->g, dhKey->gLen );\n\tstatus = C_GenerateKeyPair( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) publicKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ),\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) privateKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate ),\n\t\t\t\t\t\t\t\t&hPublicKey, &hPrivateKey );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context */\n\tcryptStatus = dhSetPublicComponents( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hPublicKey, dhKey->q, \n\t\t\t\t\t\t\t\t\t\t bitsToBytes( dhKey->qLen ) );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Remember what we've set up.  Unlike conventional PKC algorithms for\n\t   which we only store the private-key object handle, for DH key \n\t   agreement we need to store the handles for both objects */\n\tcryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &hPrivateKey, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcontextInfoPtr->altDeviceObject = hPublicKey;\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int dhGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )\n\t{\n\tCRYPT_PKCINFO_DLP dhKey;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 3 ) + 8 ], label[ 8 + 8 ];\n\tSTREAM stream;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\t\n\tREQUIRES( keysizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keysizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* CKM_DH_KEY_PAIR_GEN is really a Clayton's key generation mechanism \n\t   since it doesn't actually generate the p, g values.  Because of this \n\t   we have to generate half the key ourselves in a native context, then \n\t   copy portions from the native context over in flat form and complete \n\t   the keygen via the device.  The easiest way to do this is to create a \n\t   native DH context, generate a key, grab the public portions, and \n\t   destroy the context again.  Since the keygen can take awhile and \n\t   doesn't require the device, we do it before we grab the device */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DH );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, label, 8 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\tcryptStatus = krnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\tIMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tsetMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 3 );\n\t\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the public key information by extracting the flat values from \n\t   the SubjectPublicKeyInfo.  Note that the data used is represented in\n\t   DER-canonical form, there may be PKCS #11 implementations that can't \n\t   handle this (for example they may require p to be zero-padded to make \n\t   it exactly n bytes rather than (say) n - 1 bytes if the high byte is \n\t   zero) */\n\tcryptInitComponents( &dhKey, CRYPT_KEYTYPE_PUBLIC );\n\tsMemConnect( &stream, pubkeyBuffer, msgData.length );\n\treadSequence( &stream, NULL );\t\t\t\t\t/* SEQUENCE */\n\treadSequence( &stream, NULL );\t\t\t\t\t\t/* SEQUENCE */\n\treadUniversal( &stream );\t\t\t\t\t\t\t\t/* OID */\n\treadSequence( &stream, NULL );\t\t\t\t\t\t\t/* SEQUENCE */\n\treadGenericHole( &stream, &length, 16, BER_INTEGER  );\t\t/* p */\n\tcryptStatus = sread( &stream, dhKey.p, length );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tdhKey.pLen = bytesToBits( length );\n\t\treadGenericHole( &stream, &length, 16, BER_INTEGER  );\t/* q */\n\t\tcryptStatus = sread( &stream, dhKey.q, length );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tdhKey.qLen = bytesToBits( length );\n\t\treadGenericHole( &stream, &length, 16, BER_INTEGER  );\t/* g */\n\t\tcryptStatus = sread( &stream, dhKey.g, length );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tdhKey.gLen = bytesToBits( length );\n\tsMemDisconnect( &stream );\n\tREQUIRES( cryptStatusOK( cryptStatus ) );\n\n\t/* From here on it's a standard DH key load */\n\treturn( dhInitKey( contextInfoPtr, &dhKey, sizeof( CRYPT_PKCINFO_DLP  ) ) );\n\t}\n\nstatic int dhEncrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == sizeof( KEYAGREE_PARAMS ) );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Get the y value from phase 1 of the DH key agreement (generated when \n\t   the key was loaded/generated) from the device */\n\tcryptStatus = readAttributeValue( pkcs11Info, \n\t\t\t\t\t\tcontextInfoPtr->altDeviceObject, CKA_VALUE, \n\t\t\t\t\t\tkeyAgreeParams->publicValue, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t&keyAgreeParams->publicValueLen );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int dhDecrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY;\n\tstatic const CK_KEY_TYPE secretKeyType = CKK_GENERIC_SECRET;\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, NULL_PTR, 0 };\n\tCK_ULONG valueLen;\n\tCK_ATTRIBUTE symTemplate[] = { \n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &secretKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &secretKeyType, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_EXTRACTABLE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VALUE_LEN, &valueLen, sizeof( CK_ULONG ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_OBJECT_HANDLE hSymKey;\n\tCK_RV status;\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tKEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length == sizeof( KEYAGREE_PARAMS ) );\n\tREQUIRES( keyAgreeParams->publicValue != NULL && \\\n\t\t\t  keyAgreeParams->publicValueLen >= MIN_PKCSIZE && \\\n\t\t\t  keyAgreeParams->publicValueLen < MAX_INTLENGTH_SHORT );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Use the supplied y value to perform phase 2 of the DH key agreement.  \n\t   Since PKCS #11 mechanisms don't allow the resulting data to be \n\t   returned directly, we move it into a generic secret-key object and\n\t   then read it from that */\n\tvalueLen = keyAgreeParams->publicValueLen;\t/* symTemplate[4].pValue */\n\tmechanism.pParameter = keyAgreeParams->publicValue;\n\tmechanism.ulParameterLen = keyAgreeParams->publicValueLen;\n\tstatus = C_DeriveKey( pkcs11Info->hSession, &mechanism,\n\t\t\t\t\t\t  contextInfoPtr->deviceObject, \n\t\t\t\t\t\t  symTemplate, templateCount( symTemplate ), \n\t\t\t\t\t\t  &hSymKey );\n\tif( status == CKR_OK )\n\t\t{\n\t\tCK_ATTRIBUTE valueTemplate[] = { CKA_VALUE, keyAgreeParams->wrappedKey, \n\t\t\t\t\t\t\t\t\t\t valueLen };\n\n\t\tstatus = C_GetAttributeValue( pkcs11Info->hSession, \n\t\t\t\t\t\t\t\t\t  hSymKey, valueTemplate, 1 );\n\t\tif( status == CKR_OK )\n\t\t\tkeyAgreeParams->wrappedKeyLen = valueTemplate[ 0 ].ulValueLen;\n\t\tC_DestroyObject( pkcs11Info->hSession, hSymKey );\n\t\t}\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n#endif /* USE_DH */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRSA Mapping Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* RSA algorithm-specific mapping functions.  Externally we always appear to \n   use the X.509 (raw) mechanism for the encrypt/decrypt/sign/verify \n   functions since cryptlib does its own padding (with workarounds for \n   various bugs and peculiarities).  Internally however we have to use the\n   PKCS mechanism since some implementations don't support the X.509\n   mechanism, and add/remove the padding to fake out the presence of a raw\n   RSA mechanism */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint rsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hRsaKey,\n\t\t\t\t\t\t\tconst BOOLEAN nativeContext )\n\t{\n\tBYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];\n\tMESSAGE_DATA msgData;\n\tint nLen, eLen DUMMY_INIT, keyDataSize, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* Get the public key components from the device */\n\tcryptStatus = readAttributeValue( pkcs11Info, hRsaKey, CKA_MODULUS, \n\t\t\t\t\t\t\t\t\t  n, CRYPT_MAX_PKCSIZE, &nLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hRsaKey, CKA_PUBLIC_EXPONENT, \n\t\t\t\t\t\t\t\t\t\t  e, CRYPT_MAX_PKCSIZE, &eLen );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all that we're doing here is sending in encoded public key data for \n\t   use by objects such as certificates */\n\tcryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,\n\t\t\t\t\t\t\t\t\t  &keyDataSize, CRYPT_ALGO_RSA, 0,\n\t\t\t\t\t\t\t\t\t  n, nLen, e, eLen, NULL, 0, NULL, 0 );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\tif( nativeContext )\n\t\t{\n\t\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KEY_SPKI ) );\n\t\t}\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL ) );\n\t}\n\nstatic int rsaSetKeyInfo( PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t  CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPrivateKey,\n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPublicKey )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE idBuffer[ KEYID_SIZE + 8 ];\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\t/* Remember what we've set up.  Note that PKCS #11 tokens create \n\t   distinct public- and private-key objects but we're only interested\n\t   in the private-key one, so we store the private-key object handle\n\t   in the context */\n\tcryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &hPrivateKey, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\n\t/* Get the key ID from the context and use it as the object ID.  Since \n\t   some objects won't allow after-the-event ID updates, we don't treat a \n\t   failure to update as an error.  We do however assert on it in debug \n\t   mode since if we later want to update the key with a certificate then \n\t   we need the ID set in order to locate the object that the certificate \n\t   is associated with */\n\tsetMessageData( &msgData, idBuffer, KEYID_SIZE );\n\tcryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tCK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };\n\t\tCK_RV status;\n\n\t\tif( hPublicKey != CK_OBJECT_NONE )\n\t\t\t{\n\t\t\tstatus = C_SetAttributeValue( pkcs11Info->hSession, hPublicKey, \n\t\t\t\t\t\t\t\t\t\t  &idTemplate, 1 );\n\t\t\tassert( status == CKR_OK );\n\t\t\t}\n\t\tstatus = C_SetAttributeValue( pkcs11Info->hSession, hPrivateKey, \n\t\t\t\t\t\t\t\t\t  &idTemplate, 1 );\n\t\tassert( status == CKR_OK );\n\t\t}\n\t\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tstatic const CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY;\n\tstatic const CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_KEY_TYPE type = CKK_RSA;\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &pubKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_MODULUS, NULL, 0 },\n\t\t{ CKA_PUBLIC_EXPONENT, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_MODULUS, NULL, 0 },\n\t\t{ CKA_PUBLIC_EXPONENT, NULL, 0 },\n\t\t{ CKA_PRIVATE_EXPONENT, NULL, 0 },\n\t\t{ CKA_PRIME_1, NULL, 0 },\n\t\t{ CKA_PRIME_2, NULL, 0 },\n\t\t{ CKA_EXPONENT_1, NULL, 0 },\n\t\t{ CKA_EXPONENT_2, NULL, 0 },\n\t\t{ CKA_COEFFICIENT, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tconst CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;\n\tCK_ATTRIBUTE *keyTemplate = rsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\tpublicKeyTemplate : privateKeyTemplate;\n\tconst int keyTemplateCount = rsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ) : \\\n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate );\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCK_OBJECT_HANDLE hRsaKey;\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\t\n\tREQUIRES( keyLength == sizeof( CRYPT_PKCINFO_RSA ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the key values */\n\tif( rsaKey->isPublicKey )\n\t\t{\n\t\tsetTemplate( publicKeyTemplate, CKA_MODULUS, rsaKey->n, \n\t\t\t\t\t bitsToBytes( rsaKey->nLen ) );\n\t\tsetTemplate( publicKeyTemplate, CKA_PUBLIC_EXPONENT, rsaKey->e, \n\t\t\t\t\t bitsToBytes( rsaKey->eLen ) );\n\t\t}\n\telse\n\t\t{\n\t\tsetTemplate( privateKeyTemplate, CKA_MODULUS, rsaKey->n, \n\t\t\t\t\t bitsToBytes( rsaKey->nLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_PUBLIC_EXPONENT, rsaKey->e, \n\t\t\t\t\t bitsToBytes( rsaKey->eLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_PRIVATE_EXPONENT, rsaKey->d, \n\t\t\t\t\t bitsToBytes( rsaKey->dLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_PRIME_1, rsaKey->p, \n\t\t\t\t\t bitsToBytes( rsaKey->pLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_PRIME_2, rsaKey->q, \n\t\t\t\t\t bitsToBytes( rsaKey->qLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_EXPONENT_1, rsaKey->e1, \n\t\t\t\t\t bitsToBytes( rsaKey->e1Len ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_EXPONENT_2, rsaKey->e2, \n\t\t\t\t\t bitsToBytes( rsaKey->e2Len ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_COEFFICIENT, rsaKey->u, \n\t\t\t\t\t bitsToBytes( rsaKey->uLen ) );\n\t\t}\n\n\t/* Load the key into the token */\n\tstatus = C_CreateObject( pkcs11Info->hSession, keyTemplate, \n\t\t\t\t\t\t\t keyTemplateCount, &hRsaKey );\n\tzeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * keyTemplateCount );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\t/* If we're trying to set a public key and this is one of those\n\t\t   tinkertoy tokens that only does private-key ops, return a more\n\t\t   appropriate error code */\n\t\tif( rsaKey->isPublicKey && \\\n\t\t\tcapabilityInfoPtr->encryptFunction == NULL &&\n\t\t\tcapabilityInfoPtr->sigCheckFunction == NULL )\n\t\t\tcryptStatus = CRYPT_ERROR_NOTAVAIL;\n\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tcryptStatus = rsaSetPublicComponents( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t  contextInfoPtr->objectHandle, hRsaKey,\n\t\t\t\t\t\t\t\t\t\t  FALSE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = rsaSetKeyInfo( pkcs11Info, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t hRsaKey, CK_OBJECT_NONE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hRsaKey, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t\t\t rsaKey->isPublicKey ? FALSE : TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\tC_DestroyObject( pkcs11Info->hSession, hRsaKey );\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tstatic const BYTE exponent[] = { 0x01, 0x00, 0x01 };\n\tconst CK_ULONG modulusBits = keysizeBits;\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PUBLIC_EXPONENT, ( CK_VOID_PTR ) exponent, sizeof( exponent ) },\n\t\t{ CKA_MODULUS_BITS, ( CK_VOID_PTR ) &modulusBits, sizeof( CK_ULONG ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_OBJECT_HANDLE hPublicKey, hPrivateKey;\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tCK_RV status;\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keysizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keysizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Generate the keys */\n\tstatus = C_GenerateKeyPair( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism,\n\t\t\t\t\t\t\t\tpublicKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ), \n\t\t\t\t\t\t\t\tprivateKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate ),\n\t\t\t\t\t\t\t\t&hPublicKey, &hPrivateKey );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tcryptStatus = rsaSetPublicComponents( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t  contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t  hPublicKey, FALSE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = rsaSetKeyInfo( pkcs11Info, contextInfoPtr, hPrivateKey, \n\t\t\t\t\t\t\t\t\t hPublicKey );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hPrivateKey, CRYPT_ALGO_RSA, TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tC_DestroyObject( pkcs11Info->hSession, hPublicKey );\n\t\tC_DestroyObject( pkcs11Info->hSession, hPrivateKey );\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaSign( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tBYTE *bufPtr = buffer;\n\tconst int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint cryptStatus, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == keySize );\n\n\t/* Undo the PKCS #1 padding to make CKM_RSA_PKCS look like \n\t   CKM_RSA_X_509 */\n\tREQUIRES( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 1 && bufPtr[ 2 ] == 0xFF );\n\tLOOP_MAX( i = 2, i < keySize, i++ )\n\t\t{\n\t\tif( bufPtr[ i ] == 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\ti++;\t/* Skip final 0 byte */\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericSign( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t   bufPtr + i, keySize - i, buffer, keySize );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaVerify( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_RSA_X_509, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tBYTE data[ CRYPT_MAX_PKCSIZE + 8 ];\n\tconst int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint cryptStatus;\n\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and because some tokens don't support public-key \n\t   operations */\n\tDEBUG_DIAG(( \"Warning: rsaVerify() called for device object, should \"\n\t\t\t\t \"be handled via native object\" ));\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == keySize );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericVerify( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t\t data, keySize, buffer, keySize );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaEncrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tBYTE *bufPtr = buffer;\n\tconst int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint cryptStatus, i, LOOP_ITERATOR;\n\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and because some tokens don't support public-key \n\t   operations.  The only way that it can be invoked is by calling\n\t   cryptEncrypt() directly on a device context */\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == keySize );\n\n\t/* Undo the PKCS #1 padding to make CKM_RSA_PKCS look like \n\t   CKM_RSA_X_509 */\n\tassert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 2 );\n\tLOOP_MAX( i = 2, i < keySize, i++ )\n\t\t{\n\t\tif( bufPtr[ i ] == 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\ti++;\t/* Skip final 0 byte */\n\tREQUIRES( boundsCheck( i, keySize - i, length ) );\n\tmemmove( bufPtr, bufPtr + i, keySize - i );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericEncrypt( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t\t  bufPtr, keySize - i, keySize );\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int rsaDecrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tMESSAGE_DATA msgData;\n\tBYTE *bufPtr = buffer;\n\tconst int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint cryptStatus, i, resultLen, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == keySize );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericDecrypt( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t\t  buffer, keySize, &resultLen );\n\tkrnlReleaseObject( iCryptDevice );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Redo the PKCS #1 padding so CKM_RSA_PKCS look like CKM_RSA_X_509.  \n\t   Note that this doesn't have to be cryptographically strong since\n\t   it gets stripped as soon as we return to the caller, it just has\n\t   to be random:\n\n\t  bufPtr\t\t\t\t\t\t\t keySize\n\t\t|\t\t\t\t\t\t\t\t\t|\n\t\t+---+---+------------+---+----------+\n\t\t| 0 | 1 |   random   | 0 |   key    |\n\t\t+---+---+------------+---+----------+\n\t\t\t\t|\t\t\t |\t |\t\t\t|\n\t\t\t\t<------------>\t <---------->\n\t\t\t\t keySize -\t\t   resultLen\n\t\t\t\t resultLen - 3\n\n\t   This gets a bit ugly because the random padding has to be nonzero,\n\t   which would require using the non-nonce RNG.  To work around this,\n\t   we look for any zeroes in the data and fill them with some other\n\t   value */\n\tREQUIRES( boundsCheck( keySize - resultLen, resultLen, length ) );\n\tmemmove( bufPtr + keySize - resultLen, bufPtr, resultLen );\n\tbufPtr[ 0 ] = 0;\n\tbufPtr[ 1 ] = 2;\n\tsetMessageData( &msgData, bufPtr + 2, keySize - resultLen - 3 );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tLOOP_EXT( i = 2, i < keySize - resultLen - 1, i++,\n\t\t\t  CRYPT_MAX_PKCSIZE + 1 )\n\t\t{\n\t\tif( bufPtr[ i ] == 0 )\n\t\t\t{\n\t\t\t/* Create some sort of non-constant non-zero value to replace \n\t\t\t   the zero byte with, since PKCS #1 can't have zero bytes.  \n\t\t\t   Note again that this doesn't have to be a strong random \n\t\t\t   value, it just has to vary a bit */\n\t\t\tconst int pad = 0xAA ^ ( i & 0xFF );\n\t\t\tbufPtr[ i ] = pad ? intToByte( pad ) : 0x21;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tbufPtr[ keySize - resultLen - 1 ] = 0;\n\tENSURES( 2 + ( keySize - resultLen - 3 ) + 1 + resultLen == keySize );\n\n\treturn( cryptStatus );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDSA Mapping Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_DSA\n\n/* DSA algorithm-specific mapping functions */\n\nstatic int dsaSetKeyInfo( PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t  const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPrivateKey,\n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hPublicKey,\n\t\t\t\t\t\t  const void *p, const int pLen,\n\t\t\t\t\t\t  const void *q, const int qLen,\n\t\t\t\t\t\t  const void *g, const int gLen,\n\t\t\t\t\t\t  const void *y, const int yLen,\n\t\t\t\t\t\t  const BOOLEAN nativeContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ];\n\tBYTE idBuffer[ KEYID_SIZE + 8 ];\n\tint keyDataSize, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtrDynamic( p, pLen ) );\n\tassert( isReadPtrDynamic( q, qLen ) );\n\tassert( isReadPtrDynamic( g, gLen ) );\n\tassert( isReadPtrDynamic( y, yLen ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all that we're doing here is sending in encoded public key data for \n\t   use by objects such as certificates */\n\tcryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 3,\n\t\t\t\t\t\t\t\t\t  &keyDataSize, CRYPT_ALGO_DSA, 0,\n\t\t\t\t\t\t\t\t\t  p, pLen, q, qLen, g, gLen, y, yLen );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\tif( nativeContext )\n\t\t{\n\t\t/* If we're just setting public key components for a native context, \n\t\t   we're done */\n\t\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KEY_SPKI ) );\n\t\t}\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Remember what we've set up.  Note that PKCS #11 tokens create \n\t   distinct public- and private-key objects but we're only interested\n\t   in the private-key one, so we store the private-key object handle\n\t   in the context */\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &hPrivateKey, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Get the key ID from the context and use it as the object ID.  Since \n\t   some objects won't allow after-the-event ID updates, we don't treat a \n\t   failure to update as an error */\n\tsetMessageData( &msgData, idBuffer, KEYID_SIZE );\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tCK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };\n\n\t\tif( hPublicKey != CRYPT_UNUSED )\n\t\t\tC_SetAttributeValue( pkcs11Info->hSession, hPublicKey, \n\t\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\tC_SetAttributeValue( pkcs11Info->hSession, hPrivateKey, \n\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\t}\n\t\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hDsaKey,\n\t\t\t\t\t\t\tconst BOOLEAN nativeContext )\n\t{\n\tBYTE p[ CRYPT_MAX_PKCSIZE + 8 ], q[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE g[ CRYPT_MAX_PKCSIZE + 8 ], y[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint pLen, qLen DUMMY_INIT, gLen DUMMY_INIT, yLen DUMMY_INIT;\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* Get the public key components from the device */\n\tcryptStatus = readAttributeValue( pkcs11Info, hDsaKey, CKA_PRIME, \n\t\t\t\t\t\t\t\t\t  p, CRYPT_MAX_PKCSIZE, &pLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hDsaKey, CKA_SUBPRIME, \n\t\t\t\t\t\t\t\t\t\t  q, CRYPT_MAX_PKCSIZE, &qLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hDsaKey, CKA_BASE, \n\t\t\t\t\t\t\t\t\t\t  g, CRYPT_MAX_PKCSIZE, &gLen );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hDsaKey, CKA_VALUE, \n\t\t\t\t\t\t\t\t\t\t  y, CRYPT_MAX_PKCSIZE, &yLen );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\treturn( dsaSetKeyInfo( pkcs11Info, iCryptContext, CK_OBJECT_NONE, hDsaKey, \n\t\t\t\t\t\t   p, pLen, q, qLen, g, gLen, y, yLen, nativeContext ) );\n\t}\n\nstatic int dsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, \n\t\t\t\t\t   const int keyLength )\n\t{\n\tstatic const CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY;\n\tstatic const CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_KEY_TYPE type = CKK_DSA;\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &pubKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_PRIME, NULL, 0 },\n\t\t{ CKA_SUBPRIME, NULL, 0 },\n\t\t{ CKA_BASE, NULL, 0 },\n\t\t{ CKA_VALUE, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_PRIME, NULL, 0 },\n\t\t{ CKA_SUBPRIME, NULL, 0 },\n\t\t{ CKA_BASE, NULL, 0 },\n\t\t{ CKA_VALUE, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tconst CRYPT_PKCINFO_DLP *dsaKey = ( CRYPT_PKCINFO_DLP * ) key;\n\tCK_ATTRIBUTE *keyTemplate = dsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\tpublicKeyTemplate : privateKeyTemplate;\n\tconst int keyTemplateCount = dsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ) : \\\n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate );\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tCK_OBJECT_HANDLE hDsaKey;\n\tCK_RV status;\n\tBYTE yValue[ CRYPT_MAX_PKCSIZE + 8 ];\n\tconst void *yValuePtr;\n\tint yValueLength, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( keyLength == sizeof( CRYPT_PKCINFO_DLP ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Creating a private-key object is somewhat problematic since the \n\t   PKCS #11 interpretation of DSA reuses CKA_VALUE for x in the private\n\t   key and y in the public key, so it's not possible to determine y from\n\t   a private key because the x value is sensitive and can't be extracted\n\t   (this isn't used in C_CreateObject() but is needed later for\n\t   dsaSetKeyInfo()).\n\n\t   Because of this we have to create a native private-key context (which \n\t   will generate the y value from x), read out the y value, and destroy\n\t   it again (see the comments in the DSA generate key section for more on\n\t   this problem).  Since this doesn't require the device, we do it before \n\t   we grab the device */\n\tif( !dsaKey->isPublicKey )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\t\tMESSAGE_DATA msgData;\n\t\tSTREAM stream;\n\t\tBYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 3 ) + 8 ], label[ 8 + 8 ];\n\t\tvoid *yValueDataPtr DUMMY_INIT_PTR;\n\t\tint yValueDataSize;\n\n\t\t/* Create a native private-key DSA context, which generates the y \n\t\t   value internally */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DSA );\n\t\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tsetMessageData( &msgData, label, 8 );\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) dsaKey, \n\t\t\t\t\t\tsizeof( CRYPT_PKCINFO_DLP ) );\n\t\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_KEY_COMPONENTS );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( cryptStatus );\n\t\t\t}\n\n\t\t/* Get the public key data and extract the y value from it.  Note \n\t\t   that the data used is represented in DER-canonical form, there may \n\t\t   be PKCS #11 implementations that can't handle this (for example \n\t\t   they may require y to be zero-padded to make it exactly 64 bytes \n\t\t   rather than (say) 63 bytes if the high byte is zero) */\n\t\tsetMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 3 );\n\t\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tsMemConnect( &stream, msgData.data, msgData.length );\n\t\treadSequence( &stream, NULL );\t\t/* SEQUENCE { */\n\t\treadUniversal( &stream );\t\t\t\t/* AlgoID */\n\t\treadBitStringHole( &stream, NULL, 16, DEFAULT_TAG );/* BIT STRING */\n\t\tstatus = readGenericHole( &stream, &yValueDataSize, 16, \n\t\t\t\t\t\t\t\t  BER_INTEGER  );/* INTEGER */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = sMemGetDataBlock( &stream, &yValueDataPtr, \n\t\t\t\t\t\t\t\t\t   yValueDataSize );\n\t\t\t}\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tENSURES( yValueDataSize >= 16 && \\\n\t\t\t\t yValueDataSize <= CRYPT_MAX_PKCSIZE );\n\t\tREQUIRES( rangeCheck( yValueDataSize, 1, CRYPT_MAX_PKCSIZE ) );\n\t\tmemcpy( yValue, yValueDataPtr, yValueDataSize );\n\t\tsMemDisconnect( &stream );\n\n\t\t/* The y value is the recovered value from the key data */\n\t\tyValuePtr = yValue;\n\t\tyValueLength = yValueDataSize;\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a public key, use the pre-generated y value */\n\t\tyValuePtr = dsaKey->y,\n\t\tyValueLength = bitsToBytes( dsaKey->yLen );\n\t\t}\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the key values */\n\tif( dsaKey->isPublicKey )\n\t\t{\n\t\tsetTemplate( publicKeyTemplate, CKA_PRIME, dsaKey->p, \n\t\t\t\t\t bitsToBytes( dsaKey->pLen ) );\n\t\tsetTemplate( publicKeyTemplate, CKA_SUBPRIME, dsaKey->q, \n\t\t\t\t\t bitsToBytes( dsaKey->qLen ) );\n\t\tsetTemplate( publicKeyTemplate, CKA_BASE, dsaKey->g, \n\t\t\t\t\t bitsToBytes( dsaKey->gLen ) );\n\t\tsetTemplate( publicKeyTemplate, CKA_VALUE, dsaKey->y, \n\t\t\t\t\t bitsToBytes( dsaKey->yLen ) );\n\t\t}\n\telse\n\t\t{\n\t\tsetTemplate( privateKeyTemplate, CKA_PRIME, dsaKey->p, \n\t\t\t\t\t bitsToBytes( dsaKey->pLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_SUBPRIME, dsaKey->q, \n\t\t\t\t\t bitsToBytes( dsaKey->qLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_BASE, dsaKey->g, \n\t\t\t\t\t bitsToBytes( dsaKey->gLen ) );\n\t\tsetTemplate( privateKeyTemplate, CKA_VALUE, dsaKey->x, \n\t\t\t\t\t bitsToBytes( dsaKey->xLen ) );\n\t\t}\n\n\t/* Load the key into the token */\n\tstatus = C_CreateObject( pkcs11Info->hSession, keyTemplate,\n\t\t\t\t\t\t\t keyTemplateCount, &hDsaKey );\n\tzeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * keyTemplateCount );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\t/* If we're trying to set a public key and this is one of those\n\t\t   tinkertoy tokens that only does private-key ops, return a more\n\t\t   appropriate error code */\n\t\tif( dsaKey->isPublicKey && \\\n\t\t\tcapabilityInfoPtr->sigCheckFunction == NULL )\n\t\t\tcryptStatus = CRYPT_ERROR_NOTAVAIL;\n\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tcryptStatus = dsaSetKeyInfo( pkcs11Info, contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t hDsaKey, CK_OBJECT_NONE,\n\t\t\t\t\t\t\t\t dsaKey->p, bitsToBytes( dsaKey->pLen ), \n\t\t\t\t\t\t\t\t dsaKey->q, bitsToBytes( dsaKey->qLen ),\n\t\t\t\t\t\t\t\t dsaKey->g, bitsToBytes( dsaKey->gLen ),\n\t\t\t\t\t\t\t\t yValuePtr, yValueLength, FALSE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hDsaKey, CRYPT_ALGO_DSA,\n\t\t\t\t\t\t\t\t\t\t dsaKey->isPublicKey ? FALSE : TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\tC_DestroyObject( pkcs11Info->hSession, hDsaKey );\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int dsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_DSA_KEY_PAIR_GEN, NULL_PTR, 0 };\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIME, NULL, 0 },\n\t\t{ CKA_SUBPRIME, NULL, 0 },\n\t\t{ CKA_BASE, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_OBJECT_HANDLE hPublicKey, hPrivateKey;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tBYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 3 ) + 8 ], label[ 8 + 8 ];\n\tCK_RV status;\n\tSTREAM stream;\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keysizeBits >= bytesToBits( MIN_PKCSIZE ) && \\\n\t\t\t  keysizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\n\t/* CKM_DSA_KEY_PAIR_GEN is really a Clayton's key generation mechanism \n\t   since it doesn't actually generate the p, q, or g values (presumably \n\t   it dates back to the original FIPS 186 shared domain parameters idea).\n\t   Because of this we'd have to generate half the key ourselves in a \n\t   native context, then copy portions from the native context over in \n\t   flat form and complete the keygen via the device.  The easiest way to\n\t   do this is to create a native DSA context, generate a key, grab the\n\t   public portions, and destroy the context again (i.e. generate a full\n\t   key on a superscalar 2GHz RISC CPU, then throw half of it away, and \n\t   regenerate it on a 5MHz 8-bit tinkertoy).  Since the keygen can take \n\t   awhile and doesn't require the device, we do it before we grab the \n\t   device */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DSA );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, label, 8 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\tcryptStatus = krnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\tIMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tsetMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 3 );\n\t\tcryptStatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the public key information by extracting the flat values from \n\t   the SubjectPublicKeyInfo.  Note that the data used is represented in\n\t   DER-canonical form, there may be PKCS #11 implementations that\n\t   can't handle this (for example they may require q to be zero-padded\n\t   to make it exactly 20 bytes rather than (say) 19 bytes if the high\n\t   byte is zero) */\n\tsMemConnect( &stream, pubkeyBuffer, msgData.length );\n\treadSequence( &stream, NULL );\t\t\t\t/* SEQUENCE */\n\treadSequence( &stream, NULL );\t\t\t\t\t/* SEQUENCE */\n\treadUniversal( &stream );\t\t\t\t\t\t\t/* OID */\n\treadSequence( &stream, NULL );\t\t\t\t\t\t/* SEQUENCE */\n\tcryptStatus = readGenericHole( &stream, &length, 16,\t/* p */\n\t\t\t\t\t\t\t\t   BER_INTEGER  );\n\tif( cryptStatusOK( cryptStatus ) && !isShortIntegerRangeNZ( length ) )\n\t\tcryptStatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\tif( cryptStatusError( cryptStatus ) )\n\t\tretIntError();\n\tsetTemplate( publicKeyTemplate, CKA_PRIME, dataPtr, length );\n\tsSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\tcryptStatus = readGenericHole( &stream, &length, 16, \t/* q */\n\t\t\t\t\t\t\t\t   BER_INTEGER  );\n\tif( cryptStatusOK( cryptStatus ) && !isShortIntegerRangeNZ( length ) )\n\t\tcryptStatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\tif( cryptStatusError( cryptStatus ) )\n\t\tretIntError();\n\tsetTemplate( publicKeyTemplate, CKA_SUBPRIME, dataPtr, length );\n\tsSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\tcryptStatus = readGenericHole( &stream, &length, 16, \t/* g */\n\t\t\t\t\t\t\t\t   BER_INTEGER  );\n\tif( cryptStatusOK( cryptStatus ) && !isShortIntegerRangeNZ( length ) )\n\t\tcryptStatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\tif( cryptStatusError( cryptStatus ) )\n\t\tretIntError();\n\tsetTemplate( publicKeyTemplate, CKA_BASE, dataPtr, length );\n\tsMemDisconnect( &stream );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Generate the keys */\n\tstatus = C_GenerateKeyPair( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) publicKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ),\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) privateKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate ),\n\t\t\t\t\t\t\t\t&hPublicKey, &hPrivateKey );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Read back the generated y value, send the public key information to \n\t   the context, and set up the key ID information */\n\tcryptStatus = readAttributeValue( pkcs11Info, hPublicKey, CKA_VALUE,\n\t\t\t\t\t\t\t\t\t  pubkeyBuffer, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t\t\t  &length );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = dsaSetKeyInfo( pkcs11Info, contextInfoPtr->objectHandle, \n\t\t\thPrivateKey, hPublicKey,\n\t\t\tpublicKeyTemplate[ 3 ].pValue, publicKeyTemplate[ 3 ].ulValueLen, \n\t\t\tpublicKeyTemplate[ 4 ].pValue, publicKeyTemplate[ 4 ].ulValueLen, \n\t\t\tpublicKeyTemplate[ 5 ].pValue, publicKeyTemplate[ 5 ].ulValueLen,\n\t\t\tpubkeyBuffer, length, FALSE );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hPrivateKey, CRYPT_ALGO_DSA, TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tC_DestroyObject( pkcs11Info->hSession, hPublicKey );\n\t\tC_DestroyObject( pkcs11Info->hSession, hPrivateKey );\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nstatic int dsaSign( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tDLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\tPKC_INFO *dsaKey = contextInfoPtr->ctxPKC;\n\tconst PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \\\n\t\t\t\t\t\t( PKC_ENCODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( dsaKey->encodeDLValuesFunction );\n\tBIGNUM *r, *s;\n\tBYTE signature[ 40 + 8 ];\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length == sizeof( DLP_PARAMS ) );\n\tREQUIRES( dlpParams->inParam1 != NULL && \\\n\t\t\t  dlpParams->inLen1 == 20 );\n\tREQUIRES( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );\n\tREQUIRES( dlpParams->outParam != NULL && \\\n\t\t\t  dlpParams->outLen >= ( 2 + 20 ) * 2 && \\\n\t\t\t  dlpParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( encodeDLValuesFunction != NULL );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericSign( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t   dlpParams->inParam1, dlpParams->inLen1, \n\t\t\t\t\t\t\t   signature, 40 );\n\tkrnlReleaseObject( iCryptDevice );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Encode the result as a DL data block.  We have to do this via bignums, \n\t   but this isn't a big deal since DSA signing via tokens is almost never \n\t   used */\n\tr = BN_new();\n\tif( r == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\ts = BN_new();\n\tif( s == NULL )\n\t\t{\n\t\tBN_free( r );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tcryptStatus = importBignum( r, signature, 20, \n\t\t\t\t\t\t\t    bitsToBytes( 160 - 32 ), 20, NULL, \n\t\t\t\t\t\t\t\tKEYSIZE_CHECK_NONE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = importBignum( s, signature + 20, 20,\n\t\t\t\t\t\t\t\t    bitsToBytes( 160 - 32 ), 20, NULL, \n\t\t\t\t\t\t\t\t\tKEYSIZE_CHECK_NONE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = \\\n\t\t\tencodeDLValuesFunction( dlpParams->outParam, dlpParams->outLen, \n\t\t\t\t\t\t\t\t\t&dlpParams->outLen, r, s, \n\t\t\t\t\t\t\t\t\tdlpParams->formatType );\n\t\t}\n\tBN_clear_free( s );\n\tBN_clear_free( r );\n\treturn( cryptStatus );\n\t}\n\nstatic int dsaVerify( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )\n\t{\n/*\tstatic const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 }; */\n/*\tCRYPT_DEVICE iCryptDevice; */\n\tconst DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;\n\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and because some tokens don't support public-key \n\t   operations */\n\tDEBUG_DIAG(( \"Warning: dsaVerify() called for device object, should \"\n\t\t\t\t \"be handled via native object\" ));\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\t\n\tREQUIRES( length == sizeof( DLP_PARAMS ) );\n\tREQUIRES( dlpParams->inParam1 != NULL && dlpParams->inLen1 == 20 );\n\tREQUIRES( dlpParams->inParam2 != NULL && \\\n\t\t\t  ( ( dlpParams->formatType == CRYPT_FORMAT_CRYPTLIB && \\\n\t\t\t\t  dlpParams->inLen2 >= 46 ) || \\\n\t\t\t\t( dlpParams->formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\t  dlpParams->inLen2 == 44 ) || \\\n\t\t\t\t( dlpParams->formatType == CRYPT_IFORMAT_SSH && \\\n\t\t\t\t  dlpParams->inLen2 == 40 ) ) );\n\tREQUIRES( dlpParams->outParam == NULL && dlpParams->outLen == 0 );\n\n\t/* This code can never be called since DSA public-key contexts are \n\t   always native contexts */\n\tretIntError();\n\t}\n#endif /* USE_DSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tECDSA Mapping Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_ECDSA\n\n/* The maximum possible size for an ECDSA SPKI */\n\n#define MAX_ECDSA_SPKI_SIZE\t( 16 + MAX_OID_SIZE + MAX_OID_SIZE + \\\n\t\t\t\t\t\t\t  MAX_PKCSIZE_ECCPOINT )\n\n/* Get an ECDSA SPKI by creating a native public- or private-key context \n   (which will generate, if necessary, and encode the EC point value), read \n   it out, and destroy it again (see the comments in the ECDSA init/generate \n   key section for more on this problem) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int ecdsaGetSPKI( const CRYPT_PKCINFO_ECC *ecdsaKey,\n\t\t\t\t\t\t OUT_BUFFER( spkiMaxLen, *spkiLen ) BYTE *spki, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) const int spkiMaxLen,\n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( spkiMaxLen ) int *spkiLen )\n\t{\n\tCRYPT_CONTEXT iTempEccKey;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE label[ 8 + 8 ];\n\tint cryptStatus;\n\n\tassert( isReadPtr( ecdsaKey, sizeof( CRYPT_PKCINFO_ECC ) ) );\n\tassert( isWritePtrDynamic( spki, spkiMaxLen ) );\n\tassert( isWritePtr( spkiLen, sizeof( int ) ) );\n\n\tREQUIRES( spkiMaxLen >= 32 && spkiMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( spki, 0, min( 16, spkiMaxLen ) );\n\t*spkiLen = 0;\n\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_ECDSA );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tiTempEccKey = createInfo.cryptHandle;\n\tsetMessageData( &msgData, label, 8 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tkrnlSendMessage( iTempEccKey, IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t CRYPT_CTXINFO_LABEL );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) ecdsaKey, \n\t\t\t\t\tsizeof( CRYPT_PKCINFO_ECC ) );\n\tcryptStatus = krnlSendMessage( iTempEccKey, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_CTXINFO_KEY_COMPONENTS );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iTempEccKey, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Get the public key data */\n\tsetMessageData( &msgData, spki, spkiMaxLen );\n\tcryptStatus = krnlSendMessage( iTempEccKey, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );\n\tkrnlSendNotifier( iTempEccKey, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t*spkiLen = msgData.length;\n\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int ecdsaSetKeyInfo( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hPrivateKey,\n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hPublicKey,\n\t\t\t\t\t\t\tIN_ENUM( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE curveType,\n\t\t\t\t\t\t\tIN_BUFFER( ecPointSize ) const void *ecPoint,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) const int ecPointSize,\n\t\t\t\t\t\t\tconst BOOLEAN nativeContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE keyDataBuffer[ MAX_ECDSA_SPKI_SIZE + 8 ];\n\tBYTE idBuffer[ KEYID_SIZE + 8 ];\n\tint keyDataSize, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtrDynamic( ecPoint, ecPointSize ) );\n\n\tREQUIRES( isEnumRange( curveType, CRYPT_ECCCURVE ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( ecPointSize >= 16 && ecPointSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* Send the public key data to the context.  We send the keying \n\t   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than \n\t   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context \n\t   into the high state.  We don't want to do this because we're already \n\t   in the middle of processing a message that does this on completion, \n\t   all that we're doing here is sending in encoded public key data for \n\t   use by objects such as certificates */\n\tcryptStatus = writeFlatPublicKey( keyDataBuffer, MAX_ECDSA_SPKI_SIZE,\n\t\t\t\t\t\t\t\t\t  &keyDataSize, CRYPT_ALGO_ECDSA, \n\t\t\t\t\t\t\t\t\t  curveType, ecPoint, ecPointSize, \n\t\t\t\t\t\t\t\t\t  NULL, 0, NULL, 0, NULL, 0 );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetMessageData( &msgData, keyDataBuffer, keyDataSize );\n\tif( nativeContext )\n\t\t{\n\t\t/* If we're just setting public key components for a native context, \n\t\t   we're done */\n\t\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KEY_SPKI ) );\n\t\t}\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Remember what we've set up.  Note that PKCS #11 tokens create \n\t   distinct public- and private-key objects but we're only interested\n\t   in the private-key one, so we store the private-key object handle\n\t   in the context */\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &hPrivateKey, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Get the key ID from the context and use it as the object ID.  Since \n\t   some objects won't allow after-the-event ID updates, we don't treat a \n\t   failure to update as an error */\n\tsetMessageData( &msgData, idBuffer, KEYID_SIZE );\n\tcryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tCK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };\n\n\t\tif( hPublicKey != CRYPT_UNUSED )\n\t\t\tC_SetAttributeValue( pkcs11Info->hSession, hPublicKey, \n\t\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\tC_SetAttributeValue( pkcs11Info->hSession, hPrivateKey, \n\t\t\t\t\t\t\t &idTemplate, 1 );\n\t\t}\n\t\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint ecdsaSetPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t  const CK_OBJECT_HANDLE hEcdsaKey,\n\t\t\t\t\t\t\t  const BOOLEAN nativeContext )\n\t{\n\tCRYPT_ECCCURVE_TYPE curveType;\n\tSTREAM stream;\n\tBYTE encodedPoint[ 8 + MAX_PKCSIZE_ECCPOINT + 8 ];\n\tvoid *pointPtr DUMMY_INIT_PTR;\n\tint encodedPointSize DUMMY_INIT, pointSize, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* Get the public key components from the device */\n\tcryptStatus = getEccCurveType( pkcs11Info, hEcdsaKey, &curveType );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = readAttributeValue( pkcs11Info, hEcdsaKey, CKA_EC_POINT, \n\t\t\t\t\t\t\t\t\t\t  encodedPoint, 8 + MAX_PKCSIZE_ECCPOINT, \n\t\t\t\t\t\t\t\t\t\t  &encodedPointSize );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* For no known reason the ECC point is further encoded by wrapping it \n\t   inside an OCTET STRING, so we have to undo this encoding before we\n\t   can continue */\n\tsMemConnect( &stream, encodedPoint, encodedPointSize );\n\tcryptStatus = readOctetStringHole( &stream, &pointSize, \n\t\t\t\t\t\t\t\t\t   MIN_PKCSIZE_ECCPOINT_THRESHOLD, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = sMemGetDataBlock( &stream, &pointPtr, pointSize );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\treturn( ecdsaSetKeyInfo( pkcs11Info, iCryptContext, CK_OBJECT_NONE, \n\t\t\t\t\t\t\t hEcdsaKey, curveType, pointPtr, pointSize,\n\t\t\t\t\t\t\t nativeContext ) );\n\t}\n\n/* ECDSA algorithm-specific mapping functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int ecdsaInitKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t IN_LENGTH_FIXED( sizeof( CRYPT_PKCINFO_ECC ) ) \\\n\t\t\t\t\t\t\tconst int keyLength )\n\t{\n\tstatic const CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY;\n\tstatic const CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_KEY_TYPE type = CKK_EC;\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &pubKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_EC_PARAMS, NULL, 0 },\n\t\t{ CKA_EC_POINT, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_EC_PARAMS, NULL, 0 },\n\t\t{ CKA_VALUE, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tconst CRYPT_PKCINFO_ECC *ecdsaKey = ( CRYPT_PKCINFO_ECC * ) key;\n\tCK_ATTRIBUTE *keyTemplate = ecdsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\tpublicKeyTemplate : privateKeyTemplate;\n\tconst int keyTemplateCount = ecdsaKey->isPublicKey ? \\\n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ) : \\\n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate );\n\tCK_OBJECT_HANDLE hEcdsaKey;\n\tCK_RV status;\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( contextInfoPtr->capabilityInfo );\n\tSTREAM stream;\n\tBYTE oidBuffer[ MAX_OID_SIZE + 8 ];\n\tBYTE spkiBuffer[ MAX_ECDSA_SPKI_SIZE + 8 ];\n\tBYTE encodedPoint[ 8 + MAX_PKCSIZE_ECCPOINT + 8 ];\n\tvoid *ecPointPtr DUMMY_INIT_PTR;\n\tint oidSize DUMMY_INIT, spkiSize, encodedPointSize DUMMY_INIT;\n\tint ecPointSize, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( keyLength == sizeof( CRYPT_PKCINFO_ECC ) );\n\tREQUIRES( capabilityInfoPtr != NULL );\n\n\t/* Get the information that we'll need to specify the public-key \n\t   parameters */\n\tsMemOpen( &stream, oidBuffer, MAX_OID_SIZE );\n\tcryptStatus = writeECCOID( &stream, ecdsaKey->curveType );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\toidSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Creating both public- and private-key ECDSA objects is problematic.  \n\t   For the public-key object we need to encode the EC point in the \n\t   peculiar X9.62 form, wrapped up in an OCTET STRING (because the spec \n\t   says so).  The private-key object on the other hand doesn't use \n\t   CKA_EC_POINT at all so it's not possible to determine it from a \n\t   private key (this isn't used in C_CreateObject() but is needed later \n\t   for ecdsaSetKeyInfo()).\n\n\t   Because of this we have to create a native public- or private-key \n\t   context (which will generate and encode the EC point value), read it \n\t   out, and destroy it again (see the comments in the ECDSA generate key \n\t   section for more on this problem).  Since this doesn't require the \n\t   device, we do it before we grab the device */\n\tcryptStatus = ecdsaGetSPKI( ecdsaKey, spkiBuffer, MAX_ECDSA_SPKI_SIZE, \n\t\t\t\t\t\t\t\t&spkiSize );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsMemConnect( &stream, spkiBuffer, spkiSize );\n\treadSequence( &stream, NULL );\t\t/* SEQUENCE { */\n\treadUniversal( &stream );\t\t\t\t/* AlgoID */\n\tcryptStatus = readBitStringHole( &stream, &ecPointSize, 16, \n\t\t\t\t\t\t\t\t\t DEFAULT_TAG );/* BIT STRING */\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = sMemGetDataBlock( &stream, &ecPointPtr, ecPointSize );\n\tENSURES( cryptStatusOK( cryptStatus ) );\n\tsMemDisconnect( &stream );\n\n\t/* Write the encoded EC point, wrapped in an OCTET STRING tag */\n\tsMemOpen( &stream, encodedPoint, 8 + MAX_PKCSIZE_ECCPOINT );\n\tcryptStatus = writeOctetString( &stream, ecPointPtr, ecPointSize, \n\t\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tencodedPointSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( cryptStatus ) );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the key values */\n\tif( ecdsaKey->isPublicKey )\n\t\t{\n\t\tsetTemplate( publicKeyTemplate, CKA_EC_PARAMS, oidBuffer, oidSize );\n\t\tsetTemplate( publicKeyTemplate, CKA_EC_POINT, encodedPoint, \n\t\t\t\t\t encodedPointSize );\n\t\t}\n\telse\n\t\t{\n\t\tsetTemplate( privateKeyTemplate, CKA_EC_PARAMS, oidBuffer, oidSize );\n\t\tsetTemplate( privateKeyTemplate, CKA_VALUE, ecdsaKey->d, \n\t\t\t\t\t bitsToBytes( ecdsaKey->dLen ) );\n\t\t}\n\n\t/* Load the key into the token */\n\tstatus = C_CreateObject( pkcs11Info->hSession, keyTemplate,\n\t\t\t\t\t\t\t keyTemplateCount, &hEcdsaKey );\n\tzeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * keyTemplateCount );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\t/* If we're trying to set a public key and this is one of those\n\t\t   tinkertoy tokens that only does private-key ops, return a more\n\t\t   appropriate error code */\n\t\tif( ecdsaKey->isPublicKey && \\\n\t\t\tcapabilityInfoPtr->sigCheckFunction == NULL )\n\t\t\tcryptStatus = CRYPT_ERROR_NOTAVAIL;\n\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context and set up the key ID \n\t   information */\n\tcryptStatus = ecdsaSetKeyInfo( pkcs11Info, contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t   hEcdsaKey, CK_OBJECT_NONE,\n\t\t\t\t\t\t\t\t   ecdsaKey->curveType,\n\t\t\t\t\t\t\t\t   ecPointPtr, ecPointSize, FALSE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hEcdsaKey, CRYPT_ALGO_ECDSA,\n\t\t\t\t\t\t\t\t\t\t ecdsaKey->isPublicKey ? FALSE : TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\tC_DestroyObject( pkcs11Info->hSession, hEcdsaKey );\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int ecdsaGenerateKey( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_PKCSIZE_ECC * 8 ) \\\n\t\t\t\t\t\t\t\tconst int keySizeBits )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_ECDSA_KEY_PAIR_GEN, NULL_PTR, 0 };\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_ATTRIBUTE privateKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_ATTRIBUTE publicKeyTemplate[] = {\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },\n\t\t{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_EC_PARAMS, NULL, 0 },\n\t\t{ CKA_NONE }, { CKA_NONE }\n\t\t};\n\tCK_OBJECT_HANDLE hPublicKey, hPrivateKey;\n\tCK_RV status;\n\tCRYPT_DEVICE iCryptDevice;\n\tCRYPT_ECCCURVE_TYPE curveType;\n\tPKCS11_INFO *pkcs11Info;\n\tSTREAM stream;\n\tBYTE oidBuffer[ MAX_OID_SIZE + 8 ];\n\tint oidSize DUMMY_INIT, cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\n\tREQUIRES( keySizeBits >= bytesToBits( MIN_PKCSIZE_ECC ) && \\\n\t\t\t  keySizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE_ECC ) );\n\n\t/* Get the information that we'll need to specify the public-key \n\t   parameters */\n\tcryptStatus = getECCFieldID( bitsToBytes( keySizeBits ), &curveType );\n\tENSURES( cryptStatusOK( cryptStatus ) );\n\tsMemOpen( &stream, oidBuffer, MAX_OID_SIZE );\n\tcryptStatus = writeECCOID( &stream, curveType );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\toidSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsetTemplate( publicKeyTemplate, CKA_EC_PARAMS, oidBuffer, oidSize );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Generate the keys */\n\tstatus = C_GenerateKeyPair( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t( CK_MECHANISM_PTR ) &mechanism,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) publicKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( publicKeyTemplate ),\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) privateKeyTemplate, \n\t\t\t\t\t\t\t\ttemplateCount( privateKeyTemplate ),\n\t\t\t\t\t\t\t\t&hPublicKey, &hPrivateKey );\n\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlReleaseObject( iCryptDevice );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the public key information to the context and set up the key ID \n\t   information */\n\tcryptStatus = ecdsaSetPublicComponents( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t\tcontextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t\thPublicKey, FALSE );\n// Returns CKR_ATTRIBUTE_TYPE_INVALID on CKA_EC_PARAMS read.\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = updateActionFlags( pkcs11Info, \n\t\t\t\t\t\t\t\t\t\t contextInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t\t hPrivateKey, CRYPT_ALGO_ECDSA, TRUE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tC_DestroyObject( pkcs11Info->hSession, hPublicKey );\n\t\tC_DestroyObject( pkcs11Info->hSession, hPrivateKey );\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember that this object is backed by a crypto device */\n\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_PERSISTENT );\n\t\t}\n\n\tkrnlReleaseObject( iCryptDevice );\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int ecdsaSign( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t  INOUT_BUFFER_FIXED( noBytes ) BYTE *buffer, \n\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n\tstatic const CK_MECHANISM mechanism = { CKM_ECDSA, NULL_PTR, 0 };\n\tCRYPT_DEVICE iCryptDevice;\n\tPKCS11_INFO *pkcs11Info;\n\tDLP_PARAMS *eccParams = ( DLP_PARAMS * ) buffer;\n\tPKC_INFO *dsaKey = contextInfoPtr->ctxPKC;\n\tconst PKC_ENCODEDLVALUES_FUNCTION encodeDLValuesFunction = \\\n\t\t\t\t\t\t( PKC_ENCODEDLVALUES_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( dsaKey->encodeDLValuesFunction );\n\tBIGNUM *r, *s;\n\tBYTE signature[ ( CRYPT_MAX_PKCSIZE_ECC * 2 ) + 8 ];\n\tconst int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );\n\tint cryptStatus;\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( eccParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( eccParams->inParam1, eccParams->inLen1 ) );\n\tassert( isWritePtrDynamic( eccParams->outParam, eccParams->outLen ) );\n\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( eccParams->inParam2 == NULL && eccParams->inLen2 == 0 );\n\tREQUIRES( eccParams->outLen >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  eccParams->outLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( encodeDLValuesFunction != NULL );\n\n\t/* Get the information for the device associated with this context */\n\tcryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t\t\t&iCryptDevice, &pkcs11Info );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = genericSign( pkcs11Info, contextInfoPtr, &mechanism, \n\t\t\t\t\t\t\t   eccParams->inParam1, eccParams->inLen1, \n\t\t\t\t\t\t\t   signature, CRYPT_MAX_PKCSIZE_ECC * 2 );\n\tkrnlReleaseObject( iCryptDevice );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* PKCS #11 uses a bizarre signature-encoding form in which signing \n\t   creates a fixed-length byte string of which the first half is r and \n\t   the second half is s, zero-padded as required.  Before we can return \n\t   this to the caller we have to rewrite it in X9.62 form.  We have to \n\t   do this via bignums, but this isn't a big deal since ECDSA signing \n\t   via tokens is almost never used */\n\tr = BN_new();\n\tif( r == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\ts = BN_new();\n\tif( s == NULL )\n\t\t{\n\t\tBN_free( r );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tcryptStatus = importBignum( r, signature, keySize, \n\t\t\t\t\t\t\t\tMIN_PKCSIZE_ECC_THRESHOLD, keySize, NULL, \n\t\t\t\t\t\t\t\tKEYSIZE_CHECK_NONE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = importBignum( s, signature + keySize, keySize,\n\t\t\t\t\t\t\t\t    MIN_PKCSIZE_ECC_THRESHOLD, keySize, NULL, \n\t\t\t\t\t\t\t\t\tKEYSIZE_CHECK_NONE );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = \\\n\t\t\tencodeDLValuesFunction( eccParams->outParam, eccParams->outLen, \n\t\t\t\t\t\t\t\t\t&eccParams->outLen, r, s, \n\t\t\t\t\t\t\t\t\teccParams->formatType );\n\t\t}\n\tBN_clear_free( s );\n\tBN_clear_free( r );\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int ecdsaVerify( INOUT CONTEXT_INFO *contextInfoPtr, \n\t\t\t\t\t\tIN_BUFFER( noBytes ) BYTE *buffer, \n\t\t\t\t\t\tIN_LENGTH_FIXED( sizeof( DLP_PARAMS ) ) int noBytes )\n\t{\n/*\tstatic const CK_MECHANISM mechanism = { CKM_ECDSA, NULL_PTR, 0 }; */\n/*\tCRYPT_DEVICE iCryptDevice; */\n\tDLP_PARAMS *eccParams = ( DLP_PARAMS * ) buffer;\n\n\t/* This function is present but isn't used as part of any normal \n\t   operation because cryptlib does the same thing much faster in \n\t   software and because some tokens don't support public-key \n\t   operations */\n\tDEBUG_DIAG(( \"Warning: ecdsaVerify() called for device object, should \"\n\t\t\t\t \"be handled via native object\" ));\n\n\tassert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );\n\tassert( isWritePtr( eccParams, sizeof( DLP_PARAMS ) ) );\n\tassert( isReadPtrDynamic( eccParams->inParam1, eccParams->inLen1 ) );\n\tassert( isReadPtrDynamic( eccParams->inParam2, eccParams->inLen2 ) );\n\n\tREQUIRES( noBytes == sizeof( DLP_PARAMS ) );\n\tREQUIRES( eccParams->outParam == NULL && eccParams->outLen == 0 );\n\n\t/* This code can never be called since ECDSA public-key contexts are \n\t   always native contexts */\n\tretIntError();\n\t}\n#endif /* USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Capability Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* PKC mechanism information */\n\nstatic const PKCS11_MECHANISM_INFO mechanismInfoPKC[] = {\n\t/* The handling of the RSA mechanism is a bit odd.  Almost everyone \n\t   supports CKM_RSA_X_509 even though what's reported as being supported \n\t   is CKM_RSA_PKCS, however the PKCS mechanism is often implemented in a \n\t   buggy manner with all sorts of problems with handling the padding.  \n\t   The safest option would be to use the raw RSA one and do the padding \n\t   ourselves, which means that it'll always be done right.  Since some \n\t   implementations report raw RSA as being unavailable even though it's \n\t   present, we detect it by checking for the PKCS mechanism but using \n\t   raw RSA.  However, some implementations genuinely don't do raw RSA, so\n\t   the code fakes it by removing/adding dummy PKCS padding as required \n\t   so that the caller sees raw RSA and the device sees PKCS.  This is a\n\t   compromise: We can handle the real (rather than faked) PKCS padding\n\t   ourselves and work around bugs in the output from other \n\t   implementations, but we can't implement any new mechanisms other than\n\t   PKCS without support in the device.  The only implementation where \n\t   even this causes problems is some versions of GemSAFE, which don't do \n\t   raw RSA and also get the PKCS mechanism wrong */\n#ifdef USE_DH\n\t{ CKM_DH_PKCS_DERIVE, CKM_DH_PKCS_KEY_PAIR_GEN, CKM_NONE, CKF_NONE, \n\t  CRYPT_ALGO_DH, CRYPT_MODE_NONE, CKK_DH,\n\t  NULL, dhInitKey, dhGenerateKey, \n\t  dhEncrypt, dhDecrypt, NULL, NULL },\n#endif /* USE_DH */\n\t{ CKM_RSA_PKCS, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_NONE, CKF_NONE, \n\t  CRYPT_ALGO_RSA, CRYPT_MODE_NONE, CKK_RSA,\n\t  NULL, rsaInitKey, rsaGenerateKey, \n\t  rsaEncrypt, rsaDecrypt, rsaSign, rsaVerify },\n#ifdef USE_DSA\n\t{ CKM_DSA, CKM_DSA_KEY_PAIR_GEN, CKM_NONE, CKF_NONE, \n\t  CRYPT_ALGO_DSA, CRYPT_MODE_NONE, CKK_DSA,\n\t  NULL, dsaInitKey, dsaGenerateKey, \n\t  NULL, NULL, dsaSign, dsaVerify },\n#endif /* USE_DSA */\n#ifdef USE_ECDSA\n\t{ CKM_ECDSA, CKM_EC_KEY_PAIR_GEN, CKM_NONE, CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS, \n\t  CRYPT_ALGO_ECDSA, CRYPT_MODE_NONE, CKK_ECDSA,\n\t  NULL, ecdsaInitKey, ecdsaGenerateKey, \n\t  NULL, NULL, ecdsaSign, ecdsaVerify },\n#endif /* USE_ECDSA */\n\t{ CKM_NONE, CKM_NONE, CKM_NONE, CKF_NONE, CRYPT_ERROR, CRYPT_ERROR, },\n\t\t{ CKM_NONE, CKM_NONE, CKM_NONE, CKF_NONE, CRYPT_ERROR, CRYPT_ERROR, }\n\t};\n\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst PKCS11_MECHANISM_INFO *getMechanismInfoPKC( OUT int *mechanismInfoSize )\n\t{\n\tassert( isWritePtr( mechanismInfoSize, sizeof( int ) ) );\n\n\t*mechanismInfoSize = FAILSAFE_ARRAYSIZE( mechanismInfoPKC, \\\n\t\t\t\t\t\t\t\t\t\t\t PKCS11_MECHANISM_INFO );\n\treturn( mechanismInfoPKC );\n\t}\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib PKCS #11 Item Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define PKC_CONTEXT\t\t/* Tell context.h that we're working with PKC contexts */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"pkcs11_api.h\"\n  #include \"asn1.h\"\n  #if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t#include \"asn1_ext.h\"\n  #endif /* USE_ECDH || USE_ECDSA */\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/pkcs11_api.h\"\n  #include \"enc_dec/asn1.h\"\n  #if defined( USE_ECDH ) || defined( USE_ECDSA )\n\t#include \"enc_dec/asn1_ext.h\"\n  #endif /* USE_ECDH || USE_ECDSA */\n#endif /* Compiler-specific includes */\n\n/* In some rare situations only incomplete PKCS #11 support is available in \n   the underlying device, for example with a token that's been initialised \n   via CryptoAPI (which doesn't populate all the PKCS #11 fields) but which \n   is now being accessed through a PKCS #11 driver.  Define the following\n   to have cryptlib perform an object search by enumerating every object of \n   the required type in the token and matching by the requested ID \n   information */\n\n#define PKCS11_FIND_VIA_CRYPTLIB\n\n/* We sometimes need to read things into local memory from a device in a \n   manner that can't be handled by a dynBuf since the data is coming from a\n   device rather than a cryptlib object.  The following value defines the \n   maximum size of the on-stack buffer, if the data is larger than this then \n   we dynamically allocate the buffer (this almost never occurs) */\n\n#define MAX_STACK_BUFFER_SIZE\t\t1024\n\n/* When we're searching for an object such as a certificate, we need to \n   impose an upper bound on the number of objects that we search through\n   before we give up.  It's a bit unclear what this bound should be, it's\n   highly unlikely that any device will ever store more than a handful of\n   certificates but we don't want to bail out too quickly just in case we\n   hit some oddball HSM that's being used to store large numbers of\n   objects.  Setting the limit at 256 seems to be a reasonable tradeoff */\n\n#define MAX_OBJECTS_SEARCHED\t\t256\n\n#ifdef USE_PKCS11\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a PKCS #11 attribute value.  If the passed-in buffer is large enough\n   to contain the value (it almost always is) then we use that, otherwise\n   we dynamically allocate the storage for it, which is why the caller has\n   to call an explicit cleanup function when they're finished with the \n   data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5, 6 ) ) \\\nstatic int getAttributeValue( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\t  const CK_OBJECT_HANDLE hObject, \n\t\t\t\t\t\t\t  const CK_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( *valueLength ) void **value, \n\t\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *valueLength,\n\t\t\t\t\t\t\t  OUT_BUFFER( valueBufLength, *valueLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *valueBuffer,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int valueBufLength )\n\t{\n\tCK_ATTRIBUTE valueTemplate = \\\n\t\t{ type, NULL_PTR, 0 };\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( value, sizeof( void * ) ) );\n\tassert( isWritePtr( valueLength, sizeof( int ) ) );\n\tassert( isWritePtrDynamic( valueBuffer, valueBufLength ) );\n\n\tREQUIRES( valueBufLength >= 16 && valueBufLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*value = NULL;\n\tmemset( valueBuffer, 0, min( 16, valueBufLength ) );\n\t*valueLength = 0;\n\n\t/* Find out how big the attribute value is */\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject,\n\t\t\t\t\t\t\t\t  &valueTemplate, 1 );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );\n\n\t/* If it's larger than the supplied buffer, allocate the storage \n\t   dynamically */\n\tif( valueTemplate.ulValueLen > valueBufLength )\n\t\t{\n\t\tif( valueTemplate.ulValueLen <= 0 || \\\n\t\t\tvalueTemplate.ulValueLen >= MAX_INTLENGTH_SHORT )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tif( ( valueTemplate.pValue = clAlloc( \"getAttributeValue\", \\\n\t\t\t\t\t( size_t ) ( valueTemplate.ulValueLen ) ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\telse\n\t\tvalueTemplate.pValue = valueBuffer;\n\n\t/* Get the attribute value */\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject,\n\t\t\t\t\t\t\t\t  &valueTemplate, 1 );\n\tif( status != CKR_OK )\n\t\t{\n\t\tif( valueTemplate.pValue != valueBuffer )\n\t\t\tclFree( \"getAttributeValue\", valueTemplate.pValue );\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );\n\t\t}\n\t*value = valueTemplate.pValue;\n\t*valueLength = valueTemplate.ulValueLen;\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void getAttributeValueEnd( IN void *value, \n\t\t\t\t\t\t\t\t  const void *valueBuffer )\n\t{\n\tassert( isReadPtr( value, 16 ) );\n\tassert( isReadPtr( valueBuffer, 16 ) );\n\n\tif( value != valueBuffer )\n\t\tclFree( \"getAttributeValueEnd\", value );\n\t}\n\n/* Get the label for an object, truncating overly long labels if required.  \n   We can't use a dynBuf for this because it's a PKCS #11 attribute rather \n   than a cryptlib attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int getObjectLabel( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t   const CK_OBJECT_HANDLE hObject, \n\t\t\t\t\t\t   OUT_BUFFER( maxLabelSize, *labelLength ) \\\n\t\t\t\t\t\t\t\tchar *label, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int maxLabelSize, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLabelSize ) \\\n\t\t\t\t\t\t\t\tint *labelLength )\n\t{\n\tchar labelBuffer[ CRYPT_MAX_TEXTSIZE + 8 ], *localLabel;\n\tint localLabelLength, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtrDynamic( label, maxLabelSize ) );\n\tassert( isWritePtr( labelLength, sizeof( int ) ) );\n\n\tREQUIRES( maxLabelSize >= 16 && maxLabelSize < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( label, 0, maxLabelSize );\n\t*labelLength = 0;\n\n\tcryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_LABEL, \n\t\t\t\t\t\t\t\t\t &localLabel, &localLabelLength, \n\t\t\t\t\t\t\t\t\t labelBuffer, CRYPT_MAX_TEXTSIZE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\t*labelLength = min( localLabelLength, maxLabelSize );\n\tREQUIRES( rangeCheck( *labelLength, 1, maxLabelSize ) );\n\tmemcpy( label, localLabel, *labelLength );\n\tgetAttributeValueEnd( localLabel, labelBuffer );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a flag for an object.  An absent value is treated as FALSE */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN readFlag( const PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t const CK_ATTRIBUTE_TYPE flagType )\n\t{\n\tCK_BBOOL bFlag = CK_FALSE;\n\tCK_ATTRIBUTE flagTemplate = { flagType, &bFlag, sizeof( CK_BBOOL ) };\n\n\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\t/* Some buggy implementations return CKR_OK but forget to set the\n\t   data value in the template (!!!) so we have to initialise bFlag\n\t   to a default of CK_FALSE to handle this */\n\treturn( ( C_GetAttributeValue( pkcs11Info->hSession, hObject,\n\t\t\t\t\t\t\t\t   &flagTemplate, 1 ) == CKR_OK && bFlag ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/* Get the permitted-action flags for an object */\n\nCHECK_RETVAL_RANGE( ACTION_PERM_FLAG_NONE, ACTION_PERM_FLAG_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getActionFlags( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\tconst CK_OBJECT_HANDLE hObject,\n\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tconst BOOLEAN checkSign = ( isSigAlgo( cryptAlgo ) || \\\n\t\t\t\t\t\t\t\tisMacAlgo( cryptAlgo ) ) ? \\\n\t\t\t\t\t\t\t  TRUE : FALSE;\n\tconst BOOLEAN checkCrypt = ( isCryptAlgo( cryptAlgo ) || \\\n\t\t\t\t\t\t\t\t isConvAlgo( cryptAlgo ) ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tconst BOOLEAN checkWrap = isCryptAlgo( cryptAlgo ) ? \\\n\t\t\t\t\t\t\t  TRUE : FALSE;\n\tBOOLEAN cryptAllowed = FALSE, sigAllowed = FALSE;\n\tint actionFlags = 0;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY );\n\tREQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_MAC ); \n\n\t/* Get the permitted actions for the object.  Some devices report bogus \n\t   capabilities (for example encrypt for a MAC object) so we restrict \n\t   the actions that we check for to try and weed out false positives.  \n\t   The kernel won't allow the setting of an invalid action anyway, but \n\t   it's better to be safe here.\n\t   \n\t   We also have to provide special translation for the sign and sig-\n\t   check action flags, PKCS #11 treats the MAC operation as a member\n\t   of the signature family while cryptlib treats it as a member of the\n\t   hash family so if we get a sign/sigcheck permitted action for a MAC \n\t   object we map it to a hash permitted action */\n\tif( ( checkCrypt && readFlag( pkcs11Info, hObject, CKA_ENCRYPT ) ) || \\\n\t\t( checkWrap && readFlag( pkcs11Info, hObject, CKA_WRAP ) ) )\n\t\t{\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );\n\t\tcryptAllowed = TRUE;\n\t\t}\n\tif( ( checkCrypt && itemType != KEYMGMT_ITEM_PUBLICKEY && \\\n\t\t  readFlag( pkcs11Info, hObject, CKA_DECRYPT ) ) || \\\n\t\t( checkWrap && itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t  readFlag( pkcs11Info, hObject, CKA_UNWRAP ) ) )\n\t\t{\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );\n\t\tcryptAllowed = TRUE;\n\t\t}\n\tif( checkSign && itemType != KEYMGMT_ITEM_PUBLICKEY && \\\n\t\treadFlag( pkcs11Info, hObject, CKA_SIGN ) )\n\t\t{\n\t\tif( isMacAlgo( cryptAlgo ) )\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );\n\t\telse\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );\n\t\tsigAllowed = TRUE;\n\t\t}\n\tif( checkSign && readFlag( pkcs11Info, hObject, CKA_VERIFY ) )\n\t\t{\n\t\tif( isMacAlgo( cryptAlgo ) )\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL );\n\t\telse\n\t\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );\n\t\tsigAllowed = TRUE;\n\t\t}\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* If there are any restrictions on the key usage then we have to \n\t\t   make it internal-only because of RSA's signature/encryption \n\t\t   duality */\n\t\tif( !( cryptAllowed && sigAllowed ) )\n\t\t\tactionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );\n\t\t}\n\telse\n\t\t{\n\t\tif( isDlpAlgo( cryptAlgo ) || isEccAlgo( cryptAlgo ) )\n\t\t\t{\n\t\t\t/* Because of the special-case data formatting requirements for \n\t\t\t   DLP/ECDLP algorithms we make the usage internal-only */\n\t\t\tactionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );\n\t\t\t}\n\t\t}\n\n\treturn( actionFlags );\n\t}\n\n/* Get cryptlib algorithm and capability information for a PKCS #11 object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \\\nstatic int getMechanismInfo( const PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\t const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t const void *capabilityInfoList, \n\t\t\t\t\t\t\t const BOOLEAN isPKC,\n\t\t\t\t\t\t\t const CAPABILITY_INFO **capabilityInfoPtrPtr,\n\t\t\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo )\n\t{\n\tCK_KEY_TYPE keyType DUMMY_INIT;\n\tCK_ATTRIBUTE keyTypeTemplate = \\\n\t\t{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &keyType, sizeof( CK_KEY_TYPE ) };\n\tCK_RV status;\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tconst PKCS11_MECHANISM_INFO *mechanismInfoPtr;\n\tint mechanismInfoSize, i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtr( capabilityInfoPtrPtr, sizeof( CAPABILITY_INFO ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\n\tREQUIRES( capabilityInfoList != NULL );\n\tREQUIRES( isPKC == TRUE || isPKC == FALSE );\n\n\t/* Clear return values */\n\t*capabilityInfoPtrPtr = NULL;\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\n\t/* Get the key type (equivalent to the cryptlib algoID) for this \n\t   object */\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject, \n\t\t\t\t\t\t\t\t  &keyTypeTemplate, 1 );\n\tif( status != CKR_OK )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't read CKA_KEY_TYPE\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Hack for PKCS #11's broken HMAC \"support\", PKCS #11 has no HMAC \n\t   object types so if we find a generic secret key object we assume that \n\t   it's an HMAC-SHA1 object, the most common type */\n\tif( keyType == CKK_GENERIC_SECRET )\n\t\t{\n\t\t*cryptAlgo = CRYPT_ALGO_HMAC_SHA1;\n\t\tcapabilityInfoPtr = findCapabilityInfo( capabilityInfoList, \n\t\t\t\t\t\t\t\t\t\t\t\t*cryptAlgo );\n\t\tif( capabilityInfoPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t*capabilityInfoPtrPtr = capabilityInfoPtr;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the equivalent cryptlib algorithm type and use that to get the\n\t   capability information for the algorithm */\n\tif( isPKC )\n\t\tmechanismInfoPtr = getMechanismInfoPKC( &mechanismInfoSize );\n\telse\n\t\tmechanismInfoPtr = getMechanismInfoConv( &mechanismInfoSize );\n\tLOOP_MED( i = 0, i < mechanismInfoSize && \\\n\t\t\t\t\t mechanismInfoPtr[ i ].keyType != keyType, i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tif( i >= mechanismInfoSize )\n\t\t{\n\t\t/* If we can't find a match for the PKCS #11 algorithm type in the \n\t\t   list of mechanisms then we're trying to instantiate an object \n\t\t   that uses an unsupported algorithm type */\n\t\tDEBUG_DIAG(( \"Tried to read object with unsupported PKCS #11 \"\n\t\t\t\t\t \"algorithm type %d\", keyType ));\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tmechanismInfoPtr = &mechanismInfoPtr[ i ];\n\t*cryptAlgo = mechanismInfoPtr->cryptAlgo;\n\tcapabilityInfoPtr = findCapabilityInfo( capabilityInfoList, *cryptAlgo );\n\tif( capabilityInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t*capabilityInfoPtrPtr = capabilityInfoPtr;\n\t\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* Get the named curve type for an ECC object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getEccCurveType( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t OUT_ENUM_OPT( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\tCRYPT_ECCCURVE_TYPE *curveType )\n\t{\n\tCRYPT_ECCCURVE_TYPE curve;\n\tSTREAM stream;\n\tBYTE ecOidBuffer[ MAX_OID_SIZE + 8 ], *ecOid;\n\tint ecOidLength, cryptStatus;\n\n\tassert( isWritePtr( curveType, sizeof( CRYPT_ECCCURVE_TYPE ) ) );\n\n\t/* Clear return value */\n\t*curveType = CRYPT_ECCCURVE_NONE;\n\n\t/* ECC algorithms are a serious pain, the only parameter that we have \n\t   available for them is CKA_EC_PARAMS, an OID for the curve that's \n\t   being used.  In order to get the curve type from that we have to read \n\t   the OID and then convert it to the named-curve type */\n\tcryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_EC_PARAMS,\n\t\t\t\t\t\t\t\t\t &ecOid, &ecOidLength, ecOidBuffer,\n\t\t\t\t\t\t\t\t\t MAX_OID_SIZE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tsMemConnect( &stream, ecOid, ecOidLength );\n\tcryptStatus = readECCOID( &stream, &curve );\n\tsMemDisconnect( &stream );\n\tgetAttributeValueEnd( ecOid, ecOidBuffer );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t*curveType = curve;\n\n\treturn( cryptStatus );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Template Manipulation Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add the components of an issuerAndSerialnumber to a certificate \n   template */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readIAndS( INOUT STREAM *stream,\n\t\t\t\t\t  INOUT CK_ATTRIBUTE *certTemplateI, \n\t\t\t\t\t  INOUT CK_ATTRIBUTE *certTemplateS )\n\t{\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( certTemplateI, sizeof( CK_ATTRIBUTE ) ) );\n\tassert( isWritePtr( certTemplateS, sizeof( CK_ATTRIBUTE ) ) );\n\n\t/* We don't clear the return values since these have already been \n\t   partially initialised with attribute information by the caller */\n\n\t/* Read the wrapper tag */\n\tcryptStatus = readSequence( stream, NULL );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Read the issuer DN and add it to the template */\n\tcryptStatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( cryptStatus ) && !isShortIntegerRangeNZ( length ) )\n\t\tcryptStatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcertTemplateI->ulValueLen = length;\n\t\tcryptStatus = sMemGetDataBlock( stream, &dataPtr, length );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcertTemplateI->pValue = dataPtr;\n\t\tcryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Read the serial number and add it to the template */\n\tcryptStatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( cryptStatus ) && !isShortIntegerRangeNZ( length ) )\n\t\tcryptStatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcertTemplateS->ulValueLen = length;\n\t\tcryptStatus = sMemGetDataBlock( stream, &dataPtr, length );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcertTemplateS->pValue = dataPtr;\n\t\tcryptStatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t}\n\treturn( cryptStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addIAndSToTemplate( INOUT_ARRAY_C( 2 ) CK_ATTRIBUTE *certTemplate, \n\t\t\t\t\t\tIN_BUFFER( iAndSLength ) const void *iAndSPtr, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int iAndSLength )\n\t{\n\tSTREAM stream;\n\tint cryptStatus;\n\n\tassert( isWritePtr( certTemplate, sizeof( CK_ATTRIBUTE ) * 2 ) );\n\tassert( isReadPtrDynamic( iAndSPtr, iAndSLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( iAndSLength ) );\n\n\t/* We don't clear the return value since this has already been \n\t   partially initialised with attribute information by the caller */\n\n\t/* Parse the iAndS data and add it to the template */\n\tsMemConnect( &stream, iAndSPtr, iAndSLength );\n\tcryptStatus = readIAndS( &stream, &certTemplate[ 0 ], \n\t\t\t\t\t\t\t &certTemplate[ 1 ] );\n\tsMemDisconnect( &stream );\n\treturn( cryptStatus );\n\t}\n\n/* Set up a search template for an issuerAndSerialNumber.  Because Netscape \n   incorrectly used the raw serial number instead of the DER-encoded form \n   and other applications copied this, we also set up an alternative \n   template with the serial number in this alternative form that we fall \n   back to if a search using the correct form fails */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int initIAndSTemplate( OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplate,\n\t\t\t\t\t\t\t  OUT_ARRAY_C( 4 ) CK_ATTRIBUTE *iAndSTemplateAlt,\n\t\t\t\t\t\t\t  IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t  IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tstatic const CK_ATTRIBUTE initTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_ISSUER, NULL_PTR, 0 },\n\t\t{ CKA_SERIAL_NUMBER, NULL_PTR, 0 }\n\t\t};\n\tSTREAM stream;\n\tint offset DUMMY_INIT, length, cryptStatus;\n\n\tassert( isWritePtr( iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) ) );\n\tassert( isWritePtr( iAndSTemplateAlt, 4 * sizeof( CK_ATTRIBUTE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Set up the issuerAndSerialNumber template */\n\tmemcpy( iAndSTemplate, initTemplate, 4 * sizeof( CK_ATTRIBUTE ) );\n\tcryptStatus = addIAndSToTemplate( &iAndSTemplate[ 2 ], keyID, \n\t\t\t\t\t\t\t\t\t  keyIDlength );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Set up the alternate template to the same as the main template, but \n\t   with the tag and length stripped from the serial number */\n\tmemcpy( iAndSTemplateAlt, iAndSTemplate, 4 * sizeof( CK_ATTRIBUTE ) );\n\tsMemConnect( &stream, iAndSTemplateAlt[ 3 ].pValue, \n\t\t\t\t iAndSTemplateAlt[ 3 ].ulValueLen );\n\tcryptStatus = readGenericHole( &stream, &length, 1, BER_INTEGER );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\toffset = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tiAndSTemplateAlt[ 3 ].pValue = \\\n\t\t\t\t( BYTE * ) iAndSTemplateAlt[ 3 ].pValue + offset;\n\tiAndSTemplateAlt[ 3 ].ulValueLen = length;\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tCertificate Import Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Instantiate a certificate object from a PKCS #11 object handle */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int instantiateCert( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hCertificate, \n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\tconst BOOLEAN createContext )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( createContext == TRUE || createContext == FALSE );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\t/* Fetch the certificate data into local memory.  We can't use a dynBuf \n\t   for this because it's a PKCS #11 attribute rather than a cryptlib \n\t   attribute */\n\tcryptStatus = getAttributeValue( pkcs11Info, hCertificate, CKA_VALUE, \n\t\t\t\t\t\t\t\t\t &bufPtr, &length, buffer, \n\t\t\t\t\t\t\t\t\t MAX_STACK_BUFFER_SIZE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Import the certificate as a cryptlib object */\n\tsetMessageCreateObjectIndirectInfoEx( &createInfo, bufPtr, length,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE, \n\t\t\t\t\t\t\tcreateContext ? KEYMGMT_FLAG_NONE : \\\n\t\t\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t\t   &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tgetAttributeValueEnd( bufPtr, buffer );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t*iCryptCert = createInfo.cryptHandle;\n\treturn( cryptStatus );\n\t}\n\n/* Get a certificate chain from a device */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getCertChain( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t\t const CK_OBJECT_HANDLE hCertificate, \n\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert, \n\t\t\t\t\t\t const BOOLEAN createContext )\n\t{\n\tCK_ATTRIBUTE idTemplate = \\\n\t\t{ CKA_ID, NULL_PTR, 0 };\n\tCK_RV status;\n\tBYTE keyID[ MAX_STACK_BUFFER_SIZE + 8 ];\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( createContext == TRUE || createContext == FALSE );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\t/* Find the ID for this certificate */\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hCertificate, \n\t\t\t\t\t\t\t\t  &idTemplate, 1 );\n\tif( status == CKR_OK && idTemplate.ulValueLen <= MAX_STACK_BUFFER_SIZE )\n\t\t{\n\t\tidTemplate.pValue = keyID;\n\t\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hCertificate,\n\t\t\t\t\t\t\t\t\t  &idTemplate, 1 );\n\t\t}\n\tif( status != CKR_OK || idTemplate.ulValueLen > MAX_STACK_BUFFER_SIZE )\n\t\t{\n\t\t/* We couldn't get the ID to build the chain or it's too large to be\n\t\t   usable, we can at least still return the individual certificate */\n\t\treturn( instantiateCert( pkcs11Info, hCertificate, iCryptCert, \n\t\t\t\t\t\t\t\t createContext ) );\n\t\t}\n\n\t/* Create the certificate chain via an indirect import */\n\treturn( iCryptImportCertIndirect( iCryptCert, iCertSource, \n\t\t\t\t\t\t\tCRYPT_IKEYID_KEYID, keyID, idTemplate.ulValueLen, \n\t\t\t\t\t\t\tcreateContext ? KEYMGMT_FLAG_NONE : \\\n\t\t\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tFind-Item Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an object based on a given template.  There are two variations of \n   this, one that finds one and only one object and the other that returns \n   the first object that it finds without treating the presence of multiple \n   objects as an error.\n   \n   The way in which this call works has special significance, there are PKCS\n   #11 implementations that don't allow any other calls during the init/find/\n   final sequence so the code is structured to always call them one after \n   the other without any intervening calls.  In addition some drivers are\n   confused over whether they're 1.x or 2.x and may or may not implement\n   C_FindObjectsFinal().  Because of this we call it if it exists, if it \n   doesn't then we assume that the driver can handle cleanup itself (this \n   situation shouldn't occur because we've checked for 1.x drivers earlier, \n   but there are one or two drivers where it does happen) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int findDeviceObjects( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\t  OUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\t\t\t\t  IN_ARRAY( templateCount ) \\\n\t\t\t\t\t\t\t\tconst CK_ATTRIBUTE *objectTemplate,\n\t\t\t\t\t\t\t  IN_RANGE( 1, 64 ) const CK_ULONG templateCount,\n\t\t\t\t\t\t\t  const BOOLEAN onlyOne )\n\t{\n\tCK_OBJECT_HANDLE hObjectArray[ 2 + 8 ];\n\tCK_ULONG ulObjectCount;\n\tCK_RV status;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );\n\tassert( isReadPtrDynamic( objectTemplate, \\\n\t\t\t\t\t\t\t  sizeof( CK_ATTRIBUTE ) * templateCount ) );\n\t\n\tREQUIRES( templateCount >= 1 && templateCount <= 64 );\n\tREQUIRES( onlyOne == TRUE || onlyOne == FALSE );\n\n\t/* Clear return value */\n\t*hObject = CK_OBJECT_NONE;\n\n\tstatus = C_FindObjectsInit( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) objectTemplate,\n\t\t\t\t\t\t\t\ttemplateCount );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );\n\tstatus = C_FindObjects( pkcs11Info->hSession, hObjectArray, 2, \n\t\t\t\t\t\t\t&ulObjectCount );\n\tif( C_FindObjectsFinal != NULL )\n\t\tC_FindObjectsFinal( pkcs11Info->hSession );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );\n\tif( ulObjectCount <= 0 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( ulObjectCount > 1 && onlyOne )\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t*hObject = hObjectArray[ 0 ];\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint findObject( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\tOUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\tIN_ARRAY( templateCount ) \\\n\t\t\t\t\tconst CK_ATTRIBUTE *objectTemplate,\n\t\t\t\tIN_RANGE( 1, 64 ) const CK_ULONG templateCount )\n\t{\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );\n\tassert( isReadPtrDynamic( objectTemplate, \\\n\t\t\t\t\t\t\t  sizeof( CK_ATTRIBUTE ) * templateCount ) );\n\n\tREQUIRES( templateCount >= 1 && templateCount <= 64 );\n\n\treturn( findDeviceObjects( pkcs11Info, hObject, \n\t\t\t\t\t\t\t   objectTemplate, templateCount, TRUE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint findObjectEx( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t  OUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\t  IN_ARRAY( templateCount ) \\\n\t\t\t\t\tconst CK_ATTRIBUTE *objectTemplate,\n\t\t\t\t  IN_RANGE( 1, 64 ) const CK_ULONG templateCount )\n\t{\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE  ) ) );\n\tassert( isReadPtrDynamic( objectTemplate, \\\n\t\t\t\t\t\t\t  sizeof( CK_ATTRIBUTE ) * templateCount ) );\n\n\tREQUIRES( templateCount >= 1 && templateCount <= 64 );\n\n\treturn( findDeviceObjects( pkcs11Info, hObject, \n\t\t\t\t\t\t\t   objectTemplate, templateCount, FALSE ) );\n\t}\n\n/* Find an object from a source object by matching IDs.  This is used to\n   find a key matching a certificate, a public key matching a private key, \n   or other objects with similar relationships */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint findObjectFromObject( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t  const CK_OBJECT_HANDLE hSourceObject, \n\t\t\t\t\t\t  const CK_OBJECT_CLASS objectClass,\n\t\t\t\t\t\t  OUT CK_OBJECT_HANDLE *hObject )\n\t{\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &objectClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_ID, NULL_PTR, 0 }\n\t\t};\n\tBYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );\n\n\t/* Clear return value */\n\t*hObject = CK_OBJECT_NONE;\n\n\t/* We're looking for a key whose ID matches that of the source object, \n\t   read its certificate ID.  We can't use a dynBuf for this because it's \n\t   a PKCS #11 attribute rather than a cryptlib attribute */\n\tcryptStatus = getAttributeValue( pkcs11Info, hSourceObject, CKA_ID, \n\t\t\t\t\t\t\t\t\t &bufPtr, &length, buffer, \n\t\t\t\t\t\t\t\t\t MAX_STACK_BUFFER_SIZE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Find the key object with the given ID */\n\tkeyTemplate[ 1 ].pValue = bufPtr;\n\tkeyTemplate[ 1 ].ulValueLen = length;\n\tcryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );\n\tgetAttributeValueEnd( bufPtr, buffer );\n\n\treturn( cryptStatus );\n\t}\n\n/* Find a certificate object based on various search criteria:\n   \n\t- Find a certificate matching a supplied template - certFromTemplate()\n\t- Find a certificate matching a given label - certFromLabel()\n\t- Find a certificate matching a given ID - certFromID()\n\t- Find a certificate matching the ID of an object hObject - certFromObject()\n\t- Find any X.509 certificate - certFromLabel(), no label supplied.\n\n  These are general-purpose functions whose behaviour can be modified through\n  the following action codes */\n\ntypedef enum {\n\tFINDCERT_NONE,\t\t\t/* No find-cert flag */\n\tFINDCERT_NORMAL,\t\t/* Instantiate standard a certificate+context */\n\tFINDCERT_DATAONLY,\t\t/* Instantiate data-only certificate */\n\tFINDCERT_P11OBJECT,\t\t/* Return handle to PKCS #11 object */\n\tFINDCERT_LAST\t\t\t/* Maximum possible flag value */\n\t} FINDCERT_ACTION_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int findCertFromTemplate( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t\t\t\t IN_ARRAY( templateCount ) \\\n\t\t\t\t\t\t\t\t\tconst CK_ATTRIBUTE *findTemplate,\n\t\t\t\t\t\t\t\t IN_RANGE( 1, 64 ) const int templateCount,\n\t\t\t\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t\t OUT_OPT CK_OBJECT_HANDLE *hCertificate,\n\t\t\t\t\t\t\t\t IN_ENUM( FINDCERT ) \\\n\t\t\t\t\t\t\t\t\tconst FINDCERT_ACTION_TYPE findAction )\n\t{\n\tCK_OBJECT_HANDLE hFindCertificate;\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtrDynamic( findTemplate, \\\n\t\t\t\t\t\t\t  sizeof( CK_ATTRIBUTE ) * templateCount ) );\n\tassert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \\\n\t\t\t  hCertificate == NULL ) || \\\n\t\t\t( iCryptCert == NULL && \\\n\t\t\t  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( templateCount >= 1 && templateCount <= 64 );\n\tREQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \\\n\t\t\t  ( iCryptCert == NULL && hCertificate != NULL ) );\n\tREQUIRES( isEnumRange( findAction, FINDCERT ) );\n\n\t/* Clear return values */\n\tif( iCryptCert != NULL )\n\t\t*iCryptCert = CRYPT_ERROR;\n\tif( hCertificate != NULL )\n\t\t*hCertificate = CK_OBJECT_NONE;\n\n\t/* Try and find the certificate from the given template */\n\tcryptStatus = findObject( pkcs11Info, &hFindCertificate, findTemplate, \n\t\t\t\t\t\t\t  templateCount );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tif( findAction == FINDCERT_P11OBJECT )\n\t\t{\n\t\t*hCertificate = hFindCertificate;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( getCertChain( pkcs11Info, iCertSource, hFindCertificate, iCryptCert, \n\t\t\t\t\t\t  ( findAction == FINDCERT_NORMAL ) ? TRUE : FALSE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findCertFromLabel( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t\t\t  const CK_ATTRIBUTE_TYPE labelType,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( labelLength ) const char *label, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int labelLength,\n\t\t\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t  OUT_OPT CK_OBJECT_HANDLE *hCertificate,\n\t\t\t\t\t\t\t  IN_ENUM( FINDCERT ) \\\n\t\t\t\t\t\t\t\t\tconst FINDCERT_ACTION_TYPE findAction )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_LABEL, NULL, 0 }\n\t\t};\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( ( label == NULL && labelLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( label, labelLength ) );\n\tassert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \\\n\t\t\t  hCertificate == NULL ) || \\\n\t\t\t( iCryptCert == NULL && \\\n\t\t\t  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( ( label == NULL && labelLength == 0 ) || \\\n\t\t\t  ( label != NULL && isShortIntegerRangeNZ( labelLength ) ) );\n\tREQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \\\n\t\t\t  ( iCryptCert == NULL && hCertificate != NULL ) );\n\tREQUIRES( isEnumRange( findAction, FINDCERT ) );\n\n\t/* Clear return values */\n\tif( iCryptCert != NULL )\n\t\t*iCryptCert = CRYPT_ERROR;\n\tif( hCertificate != NULL )\n\t\t*hCertificate = CK_OBJECT_NONE;\n\n\t/* Try and find the certificate with the given label if there's one\n\t   supplied.  Usually this is the CKA_LABEL but it can also be something \n\t   like a CKA_URL */\n\tif( label != NULL )\n\t\t{\n\t\tcertTemplate[ 2 ].type = labelType;\n\t\tcertTemplate[ 2 ].pValue = ( CK_VOID_PTR ) label;\n\t\tcertTemplate[ 2 ].ulValueLen = labelLength;\n\t\t}\n\treturn( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate, \n\t\t\t\t\t\t\t\t  ( label == NULL ) ? 2 : 3, iCryptCert, \n\t\t\t\t\t\t\t\t  hCertificate, findAction ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int findCertFromID( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t\t   IN_BUFFER( certIDlength ) const void *certID, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int certIDlength,\n\t\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t   OUT_OPT CK_OBJECT_HANDLE *hCertificate,\n\t\t\t\t\t\t   IN_ENUM( FINDCERT ) \\\n\t\t\t\t\t\t\t\tconst FINDCERT_ACTION_TYPE findAction )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_ID, ( CK_VOID_PTR ) certID, certIDlength }\n\t\t};\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isReadPtrDynamic( certID, certIDlength ) );\n\tassert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \\\n\t\t\t  hCertificate == NULL ) || \\\n\t\t\t( iCryptCert == NULL && \\\n\t\t\t  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( isShortIntegerRangeNZ( certIDlength ) );\n\tREQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \\\n\t\t\t  ( iCryptCert == NULL && hCertificate != NULL ) );\n\tREQUIRES( isEnumRange( findAction, FINDCERT ) );\n\n\t/* Clear return values */\n\tif( iCryptCert != NULL )\n\t\t*iCryptCert = CRYPT_ERROR;\n\tif( hCertificate != NULL )\n\t\t*hCertificate = CK_OBJECT_NONE;\n\n\t/* Try and find the certificate with the given ID */\n\treturn( findCertFromTemplate( pkcs11Info, iCertSource, certTemplate, 3, \n\t\t\t\t\t\t\t\t  iCryptCert, hCertificate, findAction ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int findCertFromObject( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t\t\t   const CK_OBJECT_HANDLE hObject, \n\t\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t   IN_ENUM( FINDCERT ) \\\n\t\t\t\t\t\t\t\t\tconst FINDCERT_ACTION_TYPE findAction )\n\t{\n\tBYTE buffer[ MAX_STACK_BUFFER_SIZE + 8 ], *bufPtr;\n\tint length, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( isEnumRange( findAction, FINDCERT ) );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\t/* We're looking for a certificate whose ID matches the object, read the \n\t   key ID from the device.  We can't use a dynBuf for this because it's a \n\t   PKCS #11 attribute rather than a cryptlib attribute */\n\tcryptStatus = getAttributeValue( pkcs11Info, hObject, CKA_ID, &bufPtr, \n\t\t\t\t\t\t\t\t\t &length, buffer, MAX_STACK_BUFFER_SIZE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Look for a certificate with the same ID as the key */\n\tcryptStatus = findCertFromID( pkcs11Info, iCertSource, bufPtr, length, \n\t\t\t\t\t\t\t\t  iCryptCert, NULL, findAction );\n\tgetAttributeValueEnd( bufPtr, buffer );\n\treturn( cryptStatus );\n\t}\n\n/* Find an object using a non-PKCS #11 ID.  This is a special-case function\n   that's used in rare situations where only incomplete PKCS #11 format\n   support is available in the underlying device, for example with a token\n   that's been initialised via CryptoAPI (which doesn't populate all of the \n   PKCS #11 fields) but which is now being accessed through a PKCS #11 \n   driver.  It works by enumerating every object (of the required type, \n   which in this case is only certificates) in the token, creating a \n   cryptlib native object from them, and matching by the ID information\n   provided by cryptlib.\n   \n   Since this complex search function is used by both findCert() (which \n   always tries to return a complete certificate chain) and getFirst()/\n   getNext() (which are called indirectly by findCert() and which only \n   require a PKCS #11 certificate object handle to turn into a single\n   standalone certificate) we have to provide a dual-purpose interface, \n   one that returns a certificate chain when called from findCert() and a \n   second one that returns a PKCS #11 certificate object handle when called \n   from getFirst()/getNext() as called by findCert() */\n\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int matchID( IN_HANDLE CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tMESSAGE_DATA msgData;\n\tchar buffer[ MAX_ATTRIBUTE_SIZE + 8 ];\n\tint cryptStatus;\n\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_NONE );\n\t\t\t  /* _NONE is by subject DN, i.e. child.issuerDN */\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_NAME:\n\t\t\t/* This identifier is usually an arbitrary user-defined label\n\t\t\t   attached to the object, in the absence of this we use the \n\t\t\t   certificate CN (or equivalent) as the item to match on.  This\n\t\t\t   is consistent with the use in updateCertificate(), which sets \n\t\t\t   the holder name as the PKCS #11 label when a new certificate \n\t\t\t   is added (only explicitly-created public- or private-key \n\t\t\t   objects have user-defined labels) */\n\t\t\tsetMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );\n\t\t\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t\t   &msgData, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_HOLDERNAME );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tif( msgData.length != keyIDlength || \\\n\t\t\t\tstrCompare( msgData.data, keyID, keyIDlength ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_KEYID_URI:\n\t\t\tsetMessageData( &msgData, buffer, MAX_ATTRIBUTE_SIZE );\n\t\t\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t\t   &msgData, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_HOLDERURI );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tif( msgData.length != keyIDlength || \\\n\t\t\t\tstrCompare( msgData.data, keyID, keyIDlength ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\tsetMessageData( &msgData, ( void * ) keyID, keyIDlength );\n\t\t\treturn( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_KEYID ) );\n\n\t\tcase CRYPT_IKEYID_ISSUERANDSERIALNUMBER:\n\t\t\tsetMessageData( &msgData, ( void * ) keyID, keyIDlength );\n\t\t\treturn( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_ISSUERANDSERIALNUMBER ) );\n\n\t\tcase CRYPT_KEYID_NONE:\n\t\t\t/* This is a special-case code to used denote a match of the \n\t\t\t   subject name, specifically the issuer DN of the child \n\t\t\t   certificate (which is the next certificate's subject DN) when \n\t\t\t   chain building */\n\t\t\tsetMessageData( &msgData, ( void * ) keyID, keyIDlength );\n\t\t\treturn( krnlSendMessage( iCryptCert, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_SUBJECT ) );\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int searchDeviceObjects( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t\tOUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t\tOUT_OPT CK_OBJECT_HANDLE *hObject,\n\t\t\t\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\tconst BOOLEAN onlyOne )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t};\n\tCK_OBJECT_HANDLE hMatchedObject = CK_OBJECT_NONE;\n\tCK_ULONG ulObjectCount;\n\tCK_RV status;\n\tCRYPT_CERTIFICATE iMatchedCert = CRYPT_ERROR;\n\tBOOLEAN foundMatch = FALSE;\n\tint i, cryptStatus = CRYPT_ERROR_NOTFOUND, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \\\n\t\t\t  hObject == NULL ) || \\\n\t\t\t( iCryptCert == NULL && \\\n\t\t\t  isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( ( iCryptCert != NULL && hObject == NULL ) || \\\n\t\t\t  ( iCryptCert == NULL && hObject != NULL ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_NONE );\n\t\t\t  /* _NONE is by subject DN, i.e. child.issuerDN */\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( onlyOne == TRUE || onlyOne == FALSE );\n\n\t/* Clear return values */\n\tif( iCryptCert != NULL )\n\t\t*iCryptCert = CRYPT_ERROR;\n\tif( hObject != NULL )\n\t\t*hObject = CK_OBJECT_NONE;\n\n\tstatus = C_FindObjectsInit( pkcs11Info->hSession, \n\t\t\t\t\t\t\t\t( CK_ATTRIBUTE_PTR ) &certTemplate, 2 );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTFOUND ) );\n\tLOOP_LARGE( i = 0, i < MAX_OBJECTS_SEARCHED, i++ )\n\t\t{\n\t\tCK_OBJECT_HANDLE hMatchObject;\n\t\tCRYPT_CERTIFICATE iMatchCert;\n\n\t\t/* Try and get the next object of the requested type */\n\t\tstatus = C_FindObjects( pkcs11Info->hSession, &hMatchObject, 1, \n\t\t\t\t\t\t\t\t&ulObjectCount );\n\t\tif( status != CKR_OK )\n\t\t\t{\n\t\t\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_NOTFOUND );\n\t\t\tbreak;\n\t\t\t}\n\t\tif( ulObjectCount <= 0 )\n\t\t\t{\n\t\t\tcryptStatus = CRYPT_ERROR_NOTFOUND;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Check whether this certificate meets the match criteria.  If \n\t\t   we're matching on keyID thn we have to create the context \n\t\t   associated with the certificate in order to calculate the keyID, \n\t\t   otherwise we use a data-only certificate */\n\t\tcryptStatus = instantiateCert( pkcs11Info, hMatchObject, &iMatchCert, \n\t\t\t\t\t\t\t\t\t   ( keyIDtype == CRYPT_IKEYID_KEYID ) ? \\\n\t\t\t\t\t\t\t\t\t\t TRUE : FALSE );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* We couldn't create a certificate from the stored data, this\n\t\t\t   is a non-fatal error since there may be more objects present\n\t\t\t   so we move on to those */\n\t\t\tcontinue;\n\t\t\t}\n\t\tcryptStatus = matchID( iMatchCert, keyIDtype, keyID, keyIDlength );\n\t\tif( cryptStatusOK( cryptStatus ) && !foundMatch )\n\t\t\t{\n\t\t\t/* We've found a matching certificate, remember it for later */\n\t\t\thMatchedObject = hMatchObject;\n\t\t\tiMatchedCert = iMatchCert;\n\t\t\t}\n\t\telse\n\t\t\tkrnlSendNotifier( iMatchCert, IMESSAGE_DECREFCOUNT );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\tcontinue;\n\n\t\t/* We've found a matching certificate, if we're looking for a first-\n\t\t   match then we're done */\n\t\tif( !onlyOne )\n\t\t\tbreak;\n\n\t\t/* We're only looking for one matching certificate, if we've found a \n\t\t   second match then this is an error */\n\t\tif( foundMatch )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );\n\t\t\tiMatchedCert = CRYPT_ERROR;\n\t\t\thMatchedObject = CK_OBJECT_NONE;\n\t\t\tcryptStatus = CRYPT_ERROR_DUPLICATE;\n\t\t\tbreak;\n\t\t\t}\n\t\tfoundMatch = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( C_FindObjectsFinal != NULL )\n\t\tC_FindObjectsFinal( pkcs11Info->hSession );\n\tif( i >= MAX_OBJECTS_SEARCHED )\n\t\t{\n\t\t/* This isn't really a hard error, but we should notify the caller\n\t\t   about it if we're in debug mode */\n\t\tDEBUG_DIAG(( \"Failed to locate matching object after checking %s \"\n\t\t\t\t\t \"items\", MAX_OBJECTS_SEARCHED ));\n\t\tassert( DEBUG_WARN );\n\t\tcryptStatus = CRYPT_ERROR_NOTFOUND;\n\t\t}\n\t/* We can't exit on cryptStatus at this point since the last status \n\t   encountered may have been a CRYPT_ERROR_NOTFOUND if we're checking \n\t   for the existence of only a single certificate by enumerating all \n\t   certificates present */\n\n\t/* If we found a matching certificate, return it to the caller */\n\tif( iMatchedCert != CRYPT_ERROR )\n\t\t{\n\t\tif( iCryptCert != NULL )\n\t\t\t*iCryptCert = iMatchedCert;\n\t\telse\n\t\t\t{\n\t\t\tkrnlSendNotifier( iMatchedCert, IMESSAGE_DECREFCOUNT );\n\t\t\t*hObject = hMatchedObject;\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( cryptStatus );\n\t}\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\n/* Umbrella find-a-certificate function */\n\t\t\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int findCert( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t IN_HANDLE const CRYPT_DEVICE iCertSource, \n\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t OUT_OPT CK_OBJECT_HANDLE *hCertificate )\n\t{\n\tCK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\tCK_OBJECT_HANDLE hFindCertificate;\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\tconst FINDCERT_ACTION_TYPE findAction = \\\n\t\t\t( hCertificate != NULL ) ? FINDCERT_P11OBJECT : FINDCERT_NORMAL;\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( ( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) && \\\n\t\t\t  hCertificate == NULL ) || \\\n\t\t\t( iCryptCert == NULL && \\\n\t\t\t  isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertSource ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( iCryptCert != NULL && hCertificate == NULL ) || \\\n\t\t\t  ( iCryptCert == NULL && hCertificate != NULL ) );\n\n\t/* Clear return values */\n\tif( iCryptCert != NULL )\n\t\t*iCryptCert = CRYPT_ERROR;\n\tif( hCertificate != NULL )\n\t\t*hCertificate = CK_OBJECT_NONE;\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_IKEYID_ISSUERANDSERIALNUMBER:\n\t\t\tcryptStatus = initIAndSTemplate( iAndSTemplate, \n\t\t\t\t\t\t\t\t\t\t\t iAndSTemplateAlt,\n\t\t\t\t\t\t\t\t\t\t\t keyID, keyIDlength );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tcryptStatus = findCertFromTemplate( pkcs11Info, iCertSource, \n\t\t\t\t\t\t\t\t\t\t\t\tiAndSTemplate, 4, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t\t\tNULL, findAction );\n\t\t\tif( cryptStatus == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\tcryptStatus = findCertFromTemplate( pkcs11Info, iCertSource, \n\t\t\t\t\t\t\t\t\t\t\t\t\tiAndSTemplateAlt, 4, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t\t\t\tNULL, findAction );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\tcryptStatus = findCertFromID( pkcs11Info, iCertSource, \n\t\t\t\t\t\t\t\t\t\t  keyID, keyIDlength, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t  hCertificate, findAction );\n\t\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYID_NAME:\n\t\tcase CRYPT_KEYID_URI:\n\t\t\tcryptStatus = findCertFromLabel( pkcs11Info, iCertSource, \n\t\t\t\t\t\t\t\t\t\t\t ( keyIDtype == CRYPT_KEYID_NAME ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t\tCKA_LABEL : CKA_URL,\n\t\t\t\t\t\t\t\t\t\t\t keyID, keyIDlength, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t\t hCertificate, findAction );\n\t\t\tif( cryptStatus == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\t/* Some devices use the iD in place of the label, if a \n\t\t\t\t   search by label fails we try again with the label as the \n\t\t\t\t   iD */\n\t\t\t\tcryptStatus = findCertFromID( pkcs11Info, iCertSource, \n\t\t\t\t\t\t\t\t\t\t\t  keyID, keyIDlength, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t\t  hCertificate, findAction );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* A standard search has failed, this may be because the necessary PKCS \n\t   #11 ID information isn't present in the token, in which case we \n\t   optionally try again by performing the search ourselves */\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\tcryptStatus = searchDeviceObjects( pkcs11Info, NULL, &hFindCertificate, \n\t\t\t\t\t\t\t\t\t   keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t\t\t\t   TRUE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\treturn( getCertChain( pkcs11Info, iCertSource, hFindCertificate, \n\t\t\t\t\t\t\t  iCryptCert, \n\t\t\t\t\t\t\t  ( findAction == FINDCERT_NORMAL ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE ) );\n\t\t}\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\n\treturn( cryptStatus );\n\t}\n\n/* Find a public- or private-key object.  Alongside the standard cryptlib \n   status code we return an extended information code to handle the \n   convoluted search strategy required in getItemFunction(), see the \n   comments inline for the reason for the extra codes */\n\ntypedef enum {\n\tFIND_PUBPRIV_NONE,\t\t/* No find-cert flag */\n\tFIND_PUBPRIV_CERTVIAKEY,/* Key found via certificate */\n\tFIND_PUBPRIV_KEYVIACERT,/* Certificate found via key */\n\tFIND_PUBPRIV_LAST\t\t/* Maximum possible flag value */\n\t} FIND_PUBPRIV_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \\\nstatic int findPubPrivKey( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t   OUT CK_OBJECT_HANDLE *hObject,\n\t\t\t\t\t\t   OUT CK_OBJECT_HANDLE *hCertificate,\n\t\t\t\t\t\t   OUT_ENUM_OPT( FIND_PUBPRIV ) \\\n\t\t\t\t\t\t\t\tFIND_PUBPRIV_TYPE *findType,\n\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t   IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t   IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\t   const BOOLEAN isPublicKey )\n\t{\n\tstatic const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) \\\n\t\t\t\t\t ( isPublicKey ? &pubkeyClass : &privkeyClass ), \n\t\t\t\t\t\t\t\t\t\tsizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( hObject, sizeof( CK_OBJECT_HANDLE ) ) );\n\tassert( isWritePtr( hCertificate, sizeof( CK_OBJECT_HANDLE ) ) );\n\tassert( isWritePtr( findType, sizeof( FIND_PUBPRIV_TYPE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isPublicKey == TRUE || isPublicKey == FALSE );\n\n\t/* Clear return values */\n\t*hObject = CK_OBJECT_NONE;\n\t*hCertificate = CK_OBJECT_NONE;\n\t*findType = FIND_PUBPRIV_NONE;\n\n\t/* Try and find the object with the given label/ID, or the first object \n\t   of the given class if no ID is given */\n\tif( keyIDtype == CRYPT_IKEYID_KEYID )\n\t\tkeyTemplate[ 1 ].type = CKA_ID;\n\tcryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );\n\tif( cryptStatus != CRYPT_ERROR_NOTFOUND )\n\t\treturn( cryptStatus );\n\n\t/* Some devices use the iD in place of the label, if we're doing a \n\t   search by label and it fails then we try again with the label as \n\t   the iD */\n\tif( keyIDtype == CRYPT_KEYID_NAME )\n\t\t{\n\t\tkeyTemplate[ 1 ].type = CKA_ID;\n\t\tcryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );\n\t\tkeyTemplate[ 1 ].type = CKA_LABEL;\n\t\tif( cryptStatus != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Some devices may only contain private key objects with associated \n\t   certificates that can't be picked out of the other cruft that's \n\t   present without going via the private key, so if we're looking for a \n\t   public key and don't find one we try again for a private key whose \n\t   sole function is to point to an associated certificate */\n\tif( isPublicKey )\n\t\t{\n\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;\n\t\tcryptStatus = findObject( pkcs11Info, hObject, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\t\n\t\t/* Tell the caller that although we've got a private key object we \n\t\t   only need it to find the associated certificate and not finding \n\t\t   an associated certificate is an error */\n\t\t*findType = FIND_PUBPRIV_CERTVIAKEY;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* A standard search has failed, this may be because the necessary PKCS \n\t   #11 ID information isn't present in the token, in which case we \n\t   optionally try again by performing the search ourselves */\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\tcryptStatus = searchDeviceObjects( pkcs11Info, NULL, hCertificate, \n\t\t\t\t\t\t\t\t\t   keyIDtype, keyID, keyIDlength, TRUE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* We've found the identified certificate, use it to find the \n\t   corresponding private key */\n\tcryptStatus = findObjectFromObject( pkcs11Info, *hCertificate, \n\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, hObject );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\t\n\t/* Tell the caller that we've already got a certificate to attach to \n\t   the private key */\n\t*findType = FIND_PUBPRIV_KEYVIACERT;\n\n\treturn( CRYPT_OK );\n#else\n\treturn( CRYPT_ERROR_NOTFOUND );\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tRead an Item from a Device\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set public-key information (in the form of the SubjectPublicKeyInfo) for \n   a native object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setPublicComponents( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\tconst CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\tconst BOOLEAN isPrivateKey,\n\t\t\t\t\t\t\t\tconst BOOLEAN nativeContext )\n\t{\n\tCK_OBJECT_HANDLE hPubKeyObject DUMMY_INIT;\n\tint cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\tREQUIRES( nativeContext == TRUE || nativeContext == FALSE );\n\n\t/* If it's an RSA object then we can set the public components from it \n\t   directly */\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\treturn( rsaSetPublicComponents( pkcs11Info, iCryptContext, hObject, \n\t\t\t\t\t\t\t\t\t\tnativeContext ) );\n\t\t}\n\n\t/* If we're creating a private-key object then we need to be able to set \n\t   the SubjectPublicKeyInfo for it.  Only RSA allows us to access the\n\t   public-key components from a private-key object, for everything else \n\t   we need to locate a corresponding public-key object in order to get\n\t   the public-key components */\n\tif( isPrivateKey )\n\t\t{\n\t\tcryptStatus = findObjectFromObject( pkcs11Info, hObject, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PUBLIC_KEY, &hPubKeyObject );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the SubjectPublicKey information to the context */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\treturn( dsaSetPublicComponents( pkcs11Info, iCryptContext, \n\t\t\t\t\t\t\t\t\t\t\thPubKeyObject, \n\t\t\t\t\t\t\t\t\t\t\tnativeContext ) );\n\n#if defined( USE_ECDSA )\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\treturn( ecdsaSetPublicComponents( pkcs11Info, iCryptContext, \n\t\t\t\t\t\t\t\t\t\t\t  hPubKeyObject, \n\t\t\t\t\t\t\t\t\t\t\t  nativeContext ) );\n#endif /* USE_ECDSA */\n\t\t}\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n/* Instantiate an object in a device.  This works like the create context\n   function but instantiates a cryptlib object using data already contained\n   in the device (for example public-key components stored with a private \n   key or a stored certificate) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createNativeObject( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t   const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_CONTEXT iLocalContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint actionFlags, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY );\n\tREQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_MAC ); \n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Get the permitted-action flags for the object.  If no usage is \n\t   allowed then we can't do anything with the object so we don't even \n\t   try and create it */\n\tactionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );\n\tif( actionFlags <= 0 )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* We're creating a public-key context, make it a native context instead \n\t   of a device one.  This solves a variety of problems including the \n\t   fact that some devices (which function purely as key stores coupled \n\t   to modexp accelerators) only support private-key operations, that \n\t   performing public-key operations natively is much, much faster than \n\t   on any token, and finally that if we do it ourselves we can defend \n\t   against a variety of RSA padding and timing attacks that have come up \n\t   since the device firmware was done */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tcryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t   OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tiLocalContext = createInfo.cryptHandle;\n\n\t/* Send the SubjectPublicKeyInfo and action permissions for the \n\t   context */\n\tcryptStatus = setPublicComponents( pkcs11Info, iLocalContext, hObject, \n\t\t\t\t\t\t\t\t\t   cryptAlgo, \n\t\t\t\t\t\t\t\t\t   ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \\\n\t\t\t\t\t\t\t\t\t\t TRUE : FALSE, TRUE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t   &actionFlags, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\t*iCryptContext = iLocalContext;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7 ) ) \\\nstatic int createDeviceObject( INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t   const CK_OBJECT_HANDLE hObject,\n\t\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iOwnerHandle,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_DEVICE iDeviceHandle,\n\t\t\t\t\t\t\t   const CAPABILITY_INFO *capabilityInfoPtr,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t   IN_RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int keySize )\n\t{\n\tCRYPT_CONTEXT iLocalContext;\n\tMESSAGE_DATA msgData;\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint createFlags = CREATEOBJECT_FLAG_DUMMY;\n\tint actionFlags, labelLength, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtr( capabilityInfoPtr, sizeof( CAPABILITY_INFO ) ) );\n\n\tREQUIRES( ( iCryptCert == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iOwnerHandle ) );\n\tREQUIRES( isHandleRangeValid( iDeviceHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY );\n\tREQUIRES( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_MAC );\n\tREQUIRES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_PKCSIZE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Check whether this is a persistent object */\n\tif( readFlag( pkcs11Info, hObject, CKA_TOKEN ) )\n\t\tcreateFlags |= CREATEOBJECT_FLAG_PERSISTENT;\n\n\t/* Get the permitted-action flags for the object */\n\tactionFlags = getActionFlags( pkcs11Info, hObject, itemType, cryptAlgo );\n\tif( actionFlags <= 0 )\n\t\t{\n\t\t/* If no usage is allowed then we can't do anything with the object \n\t\t   so we don't even try to create it */\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Create a dummy context for the key and remember the device that it's \n\t   contained in */\n\tcryptStatus = getObjectLabel( pkcs11Info, hObject, label, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE, &labelLength );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tif( labelLength <= 0 )\n\t\t{\n\t\t/* If there's no label present, use a dummy value */\n\t\tstrlcpy_s( label, CRYPT_MAX_TEXTSIZE, \"Label-less PKCS #11 key\" );\n\t\tlabelLength = 23;\n\t\t}\n\tcryptStatus = createContextFromCapability( &iLocalContext, \n\t\t\t\t\t\t\tiOwnerHandle, capabilityInfoPtr, \n\t\t\t\t\t\t\tcreateFlags | CREATEOBJECT_FLAG_PERSISTENT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &iDeviceHandle, \n\t\t\t\t\t\t\t\t   SETDEP_OPTION_INCREF );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t   &actionFlags, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Set the object's label.  This requires special care because the label \n\t   that we're setting matches that of an existing object so trying to \n\t   set it as a standard CRYPT_CTXINFO_LABEL will return a \n\t   CRYPT_ERROR_DUPLICATE error when the context code checks for the \n\t   existence of an existing label.  To handle this we use the attribute \n\t   CRYPT_IATTRIBUTE_EXISTINGLABEL to indicate that we're setting a label \n\t   that matches an existing object in the device */\n\tsetMessageData( &msgData, label, min( labelLength, CRYPT_MAX_TEXTSIZE ) );\n\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_EXISTINGLABEL );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Send the keying information to the context.  For non-PKC contexts we \n\t   only need to set the key length to let the user query the key size, \n\t   for PKC contexts we also have to set the key components so that they \n\t   can be written into certificates */\n\tif( isPkcAlgo( cryptAlgo ) )\n\t\t{\n\t\tcryptStatus = setPublicComponents( pkcs11Info, iLocalContext, \n\t\t\t\t\t\t\t\t\t\t   hObject, cryptAlgo, TRUE, FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &keySize, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Finally, record the handle for the device-internal key and mark it as \n\t   initialised (i.e. with a key loaded) */\n\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &hObject, \n\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_DEVICEOBJECT );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t   MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_INITIALISED );\n\t\t}\n\tif( cryptStatusOK( cryptStatus ) && ( iCryptCert != CRYPT_UNUSED ) )\n\t\t{\n\t\t/* If it's a public key and there's a certificate present attach it \n\t\t   to the context.  The certificate is an internal object used only \n\t\t   by the context so we tell the kernel to mark it as owned by the \n\t\t   context only */\n\t\tcryptStatus = krnlSendMessage( iLocalContext, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t\t   ( MESSAGE_CAST ) &iCryptCert, \n\t\t\t\t\t\t\t\t\t   SETDEP_OPTION_NOINCREF );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( cryptStatus );\n\t\t}\n\t*iCryptContext = iLocalContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get an item from a device and instantiate either a native or a device \n   object from it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int getSecretKey( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t INOUT PKCS11_INFO *pkcs11Info,\n\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tstatic const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;\n\tconst CAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t\t\tDATAPTR_GET( deviceInfo->capabilityInfoList );\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCK_ULONG secKeySize DUMMY_INIT;\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &secKeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_LABEL, NULL_PTR, 0 }\n\t\t};\n\tCK_ATTRIBUTE secKeySizeTemplate = \\\n\t\t{ CKA_VALUE_LEN, &secKeySize, sizeof( CK_ULONG ) };\n\tCK_OBJECT_HANDLE hObject = CK_OBJECT_NONE;\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint status, cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( capabilityInfoListPtr != NULL );\n\n\t/* Clear return value */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* Try and find the object with the given label/ID */\n\tif( keyIDtype == CRYPT_IKEYID_KEYID )\n\t\tkeyTemplate[ 1 ].type = CKA_ID;\n\tkeyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;\n\tkeyTemplate[ 1 ].ulValueLen = keyIDlength;\n\tcryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );\n\tif( cryptStatus == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* Some devices use the iD in place of the label, if a search by \n\t\t   label fails we try again with the label as the iD */\n\t\tkeyTemplate[ 1 ].type = CKA_ID;\n\t\tcryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* If it's just an existence check, return now */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\treturn( CRYPT_OK );\n\n\t/* We found something, map the key type to a cryptlib algorithm ID and \n\t   find its capabilities */\n\tcryptStatus = getMechanismInfo( pkcs11Info, hObject, \n\t\t\t\t\t\t\t\t\tcapabilityInfoListPtr, FALSE, \n\t\t\t\t\t\t\t\t\t&capabilityInfoPtr, &cryptAlgo );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject, \n\t\t\t\t\t\t\t\t  &secKeySizeTemplate, 1 );\n\tif( status != CKR_OK )\n\t\treturn( pkcs11MapError( status, CRYPT_ERROR_NOTINITED ) );\n\tENSURES( secKeySize >= MIN_KEYSIZE && \\\n\t\t\t secKeySize <= CRYPT_MAX_KEYSIZE );\n\n\t/* Create the object as a device object */\n\treturn( createDeviceObject( pkcs11Info, iCryptHandle, hObject, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED, deviceInfo->ownerHandle, \n\t\t\t\t\t\t\t    deviceInfo->objectHandle, capabilityInfoPtr,\n\t\t\t\t\t\t\t    KEYMGMT_ITEM_SECRETKEY, cryptAlgo, \n\t\t\t\t\t\t\t\tsecKeySize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5, 8 ) ) \\\nstatic int getItemFunction( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tIN_OPT void *auxInfo, \n\t\t\t\t\t\t\tINOUT_LENGTH_SHORT_Z int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tstatic const MAP_TABLE keySizeMapTbl[] = {\n\t\t{ CRYPT_ALGO_RSA, CKA_MODULUS },\n\t\t{ CRYPT_ALGO_DSA, CKA_PRIME },\n\t\t{ CRYPT_ALGO_DH, CKA_PRIME },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tconst CAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t\tDATAPTR_GET( deviceInfo->capabilityInfoList );\n\tconst CAPABILITY_INFO *capabilityInfoPtr;\n\tCK_ATTRIBUTE keySizeTemplate = { 0, NULL, 0 };\n\tCK_OBJECT_HANDLE hObject = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;\n\tCK_RV status;\n\tCRYPT_CERTIFICATE iCryptCert DUMMY_INIT;\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tBOOLEAN certViaPrivateKey = FALSE, privateKeyViaCert = FALSE;\n\tBOOLEAN certPresent = FALSE;\n\tint keySize DUMMY_INIT, cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( ( auxInfo == NULL && *auxInfoLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( auxInfo, *auxInfoLength ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \\\n\t\t\t  ( auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( *auxInfoLength ) ) );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( capabilityInfoListPtr != NULL );\n\n\t/* Clear return value */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* If we're looking for a secret key then it's fairly straightforward */\n\tif( itemType == KEYMGMT_ITEM_SECRETKEY )\n\t\t{\n\t\treturn( getSecretKey( deviceInfo, pkcs11Info, iCryptHandle, \n\t\t\t\t\t\t\t  keyIDtype, keyID, keyIDlength, flags ) );\n\t\t}\n\n\t/* If we're looking for a public key, try for a certificate first.  Some \n\t   non-crypto-capable devices don't have an explicit CKO_PUBLIC_KEY but \n\t   only a CKO_CERTIFICATE and some apps delete the public key since it's\n\t   redundant, so we try to create a certificate object before we try \n\t   anything else.  If the keyID type is an ID or label then this won't \n\t   necessarily locate the certificate since it could be unlabelled or \n\t   have a different label/ID, so if this fails we try again by going via \n\t   the private key with the given label/ID */\n\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t{\n\t\tCK_OBJECT_HANDLE hCertificateLabelObject DUMMY_INIT;\n\n\t\tif( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) )\n\t\t\t{\n\t\t\tcryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,\n\t\t\t\t\t\t\t\t\tkeyIDtype, keyID, keyIDlength, NULL, \n\t\t\t\t\t\t\t\t\t&hCertificateLabelObject );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tcryptStatus = findCert( pkcs11Info, deviceInfo->objectHandle,\n\t\t\t\t\t\t\t\t\tkeyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t\t\t\t&iCryptCert, NULL );\n\t\t\t}\n\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t{\n\t\t\t/* If we're just checking whether an object exists, return now.  \n\t\t\t   If all we want is the key label, copy it back to the caller \n\t\t\t   and exit */\n\t\t\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\t\t\treturn( CRYPT_OK );\n\t\t\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t\t\t{\n\t\t\t\treturn( getObjectLabel( pkcs11Info, hCertificateLabelObject, \n\t\t\t\t\t\t\t\t\t\tauxInfo, *auxInfoLength, \n\t\t\t\t\t\t\t\t\t\tauxInfoLength ) );\n\t\t\t\t}\n\t\t\t*iCryptHandle = iCryptCert;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* If we're looking for a specific match on a certificate (rather \n\t\t   than just a general public key) and we don't find anything, exit \n\t\t   now */\n\t\tif( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )\n\t\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Either there were no certificates found or we're looking for a \n\t   private key (or, somewhat unusually, a raw public key).  At this \n\t   point we can approach the problem from one of two sides, if we've \n\t   got an issuerAndSerialNumber we have to find the matching certificate \n\t   and get the key from that, otherwise we find the key and get the \n\t   certificate from that */\n\tif( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER )\n\t\t{\n\t\tCK_ATTRIBUTE iAndSTemplate[ 4 + 8 ], iAndSTemplateAlt[ 4 + 8 ];\n\n\t\t/* Try and find the certificate from the given template.  Note that\n\t\t   we can't use findCert() for this because it returns a cryptlib\n\t\t   certificate and not a PKCS #11 object handle */\n\t\tcryptStatus = initIAndSTemplate( iAndSTemplate, iAndSTemplateAlt,\n\t\t\t\t\t\t\t\t\t\t keyID, keyIDlength );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tcryptStatus = findObject( pkcs11Info, &hCertificate, \n\t\t\t\t\t\t\t\t  iAndSTemplate, 4 );\n\t\tif( cryptStatus == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tcryptStatus = findObject( pkcs11Info, &hCertificate, \n\t\t\t\t\t\t\t\t\t  iAndSTemplateAlt, 4 );\n\t\t\t}\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\t\tif( cryptStatus == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tcryptStatus = searchDeviceObjects( pkcs11Info, NULL, \n\t\t\t\t\t\t\t\t\t\t\t   &hCertificate, keyIDtype, \n\t\t\t\t\t\t\t\t\t\t\t   keyID, keyIDlength, TRUE );\n\t\t\t}\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t{\n\t\t\t/* We've found the identified certificate, use it to find the \n\t\t\t   corresponding private key */\n\t\t\tcryptStatus = findObjectFromObject( pkcs11Info, hCertificate, \n\t\t\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, &hObject );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\treturn( cryptStatus );\n\t\n\t\t\t/* Remember that we've already got a certificate to attach to \n\t\t\t   the private key */\n\t\t\tprivateKeyViaCert = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If we didn't find anything it may be because whoever set up \n\t\t\t   the token didn't set the iAndS rather than because there's no\n\t\t\t   key there so we only bail out if we got some unexpected type \n\t\t\t   of error */\n\t\t\tif( cryptStatus != CRYPT_ERROR_NOTFOUND )\n\t\t\t\treturn( cryptStatus );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tFIND_PUBPRIV_TYPE findType;\n\n\t\tcryptStatus = findPubPrivKey( pkcs11Info, &hObject, &hCertificate, \n\t\t\t\t\t\t\t\t&findType, keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t\t\t( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tswitch( findType )\n\t\t\t{\n\t\t\tcase FIND_PUBPRIV_NONE:\n\t\t\t\t/* No special handling */\n\t\t\t\tbreak;\n\n\t\t\tcase FIND_PUBPRIV_CERTVIAKEY:\n\t\t\t\t/* Remember that although we've got a private key object, we \n\t\t\t\t   only need it to find the associated certificate and not \n\t\t\t\t   finding an associated certificate is an error */\n\t\t\t\tcertViaPrivateKey = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase FIND_PUBPRIV_KEYVIACERT:\n\t\t\t\t/* Remember that we've already got a certificate to attach \n\t\t\t\t   to the private key */\n\t\t\t\tprivateKeyViaCert = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\n\t/* If we're looking for any kind of private key and we either have an\n\t   explicit certificate ID but couldn't find a certificate for it or we \n\t   don't have a proper ID to search on and a generic search found more \n\t   than one matching object, chances are that we're after a generic \n\t   decrypt key.  The former only occurs in misconfigured or limited-\n\t   memory tokens, the latter only in rare tokens that store more than \n\t   one private key, typically one for signing and one for verification.  \n\t   \n\t   If either of these cases occur then we try again looking specifically \n\t   for a decryption key.  Even this doesn't always work, there are some\n\t   >1-key tokens that mark a signing key as a decryption key so we still \n\t   get a CRYPT_ERROR_DUPLICATE error.\n\t   \n\t   Finally, if we can't find a decryption key either, we look for an\n\t   unwrapping key.  This may or may not work depending on whether we \n\t   have a decryption key marked as valid for unwrapping but not \n\t   decryption or a key that's genuinely only valid for unwrapping, but\n\t   at this point we're ready to try anything */\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \\\n\t\t  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \\\n\t\t( cryptStatus == CRYPT_ERROR_DUPLICATE ) )\n\t\t{\n\t\tstatic const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;\n\t\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\t\tCK_ATTRIBUTE decryptKeyTemplate[] = {\n\t\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t\t{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }\n\t\t\t};\n\n\t\tcryptStatus = findObject( pkcs11Info, &hObject, \n\t\t\t\t\t\t\t\t  decryptKeyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) && \\\n\t\t\tcryptStatus != CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tdecryptKeyTemplate[ 1 ].type = CKA_UNWRAP;\n\t\t\tcryptStatus = findObject( pkcs11Info, &hObject, \n\t\t\t\t\t\t\t\t\t  decryptKeyTemplate, 2 );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\n\t/* Sanity check that we actually found something */\n\tENSURES( hObject != CK_OBJECT_NONE );\n\n\t/* If we're just checking whether an object exists, return now.  If all \n\t   we want is the key label, copy it back to the caller and exit */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\treturn( CRYPT_OK );\n\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t{\n\t\treturn( getObjectLabel( pkcs11Info, hObject, auxInfo, *auxInfoLength,\n\t\t\t\t\t\t\t\tauxInfoLength ) );\n\t\t}\n\n\t/* We found something, map the key type to a cryptlib algorithm ID,\n\t   determine the key size, and find its capabilities */\n\tcryptStatus = getMechanismInfo( pkcs11Info, hObject, \n\t\t\t\t\t\t\t\t\tcapabilityInfoListPtr, TRUE, \n\t\t\t\t\t\t\t\t\t&capabilityInfoPtr, &cryptAlgo );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\tCRYPT_ECCCURVE_TYPE curveType;\n\n\t\t/* Get the field size for the named curve */\n\t\tcryptStatus = getEccCurveType( pkcs11Info, hObject, &curveType );\n\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\tcryptStatus = getECCFieldSize( curveType, &keySize, FALSE );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\t}\n\telse\n#endif /* USE_ECDH || USE_ECDSA */\n\t\t{\n\t\tcryptStatus = mapValue( cryptAlgo, &keySize, keySizeMapTbl, \n\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( keySizeMapTbl, MAP_TABLE ) );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* This can happen if the object that we're fetching uses an\n\t\t\t   unknown or non-PKC algorithm */\n\t\t\treturn( cryptStatus );\n\t\t\t}\n\t\tkeySizeTemplate.type = keySize;\t\t/* For int vs. enum */\n\t\tstatus = C_GetAttributeValue( pkcs11Info->hSession, hObject, \n\t\t\t\t\t\t\t\t\t  &keySizeTemplate, 1 );\n\t\tif( status != CKR_OK )\n\t\t\treturn( pkcs11MapError( status, CRYPT_ERROR_FAILED ) );\n\t\tkeySize = keySizeTemplate.ulValueLen;\n\t\t}\n\tENSURES( keySize >= MIN_PKCSIZE_ECC && \\\n\t\t\t keySize <= CRYPT_MAX_PKCSIZE );\n\n\t/* Try and find a certificate that matches the key.  The process is as\n\t   follows:\n\n\t\tif certificate object found in issuerAndSerialNumber search\n\t\t\t-- Implies key == private key\n\t\t\tcreate native data-only certificate object\n\t\t\tattach certificate object to key\n\t\telse\n\t\t\t{\n\t\t\tif public key read\n\t\t\t\t{\n\t\t\t\tif certificate\n\t\t\t\t\tcreate native certificate (+context) object\n\t\t\t\telse\n\t\t\t\t\tcreate context object\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tcreate device privkey object, mark as \"key loaded\"\n\t\t\t\tif certificate\n\t\t\t\t\tcreate native data-only certificate object\n\t\t\t\t\tattach certificate object to key\n\t\t\t\t}\n\t\t\t}\n\n\t   The reason for doing things this way is given in the comments earlier\n\t   on in this function */\n\tif( privateKeyViaCert )\n\t\t{\n\t\t/* Sanity check that we actually found a certificate */\n\t\tREQUIRES( hCertificate != CK_OBJECT_NONE );\n\n\t\t/* We've already got the certificate object handle, instantiate a \n\t\t   native data-only certificate from it */\n\t\tcryptStatus = getCertChain( pkcs11Info, deviceInfo->objectHandle, \n\t\t\t\t\t\t\t\t\thCertificate, &iCryptCert, FALSE );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tcertPresent = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tcryptStatus = findCertFromObject( pkcs11Info, deviceInfo->objectHandle, \n\t\t\t\t\t\t\t\t\t\t  hObject, &iCryptCert, \n\t\t\t\t\t\t\t\t\t\t  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \\\n\t\t\t\t\t\t\t\t\t\t  FINDCERT_NORMAL : FINDCERT_DATAONLY );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means \n\t\t\t   that there's no certificate present, however anything else is \n\t\t\t   an error.  In addition if we've got a private key whose only \n\t\t\t   function is to point to an associated certificate then not \n\t\t\t   finding anything is also an error */\n\t\t\tif( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )\n\t\t\t\treturn( cryptStatus );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We got the certificate, if we're being asked for a public key \n\t\t\t   then we've created a native object to contain it so we return \n\t\t\t   that */\n\t\t\tcertPresent = TRUE;\n\t\t\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t\t\t{\n\t\t\t\t*iCryptHandle = iCryptCert;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Create the object.  If it's a public-key object we create a native\n\t   object for the reasons given in createNativeObject(), otherwise we\n\t   create a device object */\n\tif( itemType == KEYMGMT_ITEM_PUBLICKEY )\n\t\t{\n\t\treturn( createNativeObject( pkcs11Info, iCryptHandle, hObject,\n\t\t\t\t\t\t\t\t\tKEYMGMT_ITEM_PUBLICKEY, cryptAlgo ) );\n\t\t}\n\tcryptStatus = createDeviceObject( pkcs11Info, iCryptHandle, hObject, \n\t\t\t\t\t\t\t\t\t  certPresent ? iCryptCert : CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  deviceInfo->ownerHandle, \n\t\t\t\t\t\t\t\t\t  deviceInfo->objectHandle, \n\t\t\t\t\t\t\t\t\t  capabilityInfoPtr, \n\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY, cryptAlgo, \n\t\t\t\t\t\t\t\t\t  keySize );\n\tif( cryptStatusError( cryptStatus ) && certPresent )\n\t\tkrnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );\n\treturn( cryptStatus );\n\t}\n\n/* Get the sequence of certificates in a chain from a device */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int getFirstItemFunction( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t OUT int *stateInfo,\n\t\t\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_ID, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tCK_OBJECT_HANDLE hCertificate;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tint cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\n\tREQUIRES( keyIDtype == CRYPT_IKEYID_KEYID );\n\tREQUIRES( keyIDlength >= 1 && keyIDlength < MAX_ATTRIBUTE_SIZE );\n\t\t\t  /* The keyID can be as little as a single byte when coming \n\t\t\t     from a non-cryptlib source */\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\n\t/* Try and find the certificate with the given ID.  This should work \n\t   because we've just read the ID for the indirect-import that lead to \n\t   the getFirst() call.  Note that we can't use findCert() for this \n\t   because it uses getCertChain() to build the full chain of \n\t   certificates from the leaf, which would end up calling back to \n\t   here */\n\tcryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );\n\tENSURES( cryptStatusOK( cryptStatus ) );\n\n\t/* Instantiate the certificate from the device */\n\tcryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate, \n\t\t\t\t\t\t\t\t   ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\t\t\t FALSE : TRUE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\t*stateInfo = *iCertificate;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getNextItemFunction( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tINOUT int *stateInfo, \n\t\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_SUBJECT, NULL, 0 }\n\t\t};\n\tCK_OBJECT_HANDLE hCertificate;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tDYNBUF subjectDB;\n\tint cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( *stateInfo ) || *stateInfo == CRYPT_ERROR );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* If the previous certificate was the last one, there's nothing left to \n\t   fetch */\n\tif( *stateInfo == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Get the issuerName of the previous certificate, which is the \n\t   subjectName of the certificate that we want */\n\tcryptStatus = dynCreate( &subjectDB, *stateInfo, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ISSUER );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcertTemplate[ 2 ].pValue = dynData( subjectDB );\n\tcertTemplate[ 2 ].ulValueLen = dynLength( subjectDB );\n\n\t/* Get the certificate with the subject's issuer DN.  Note that we\n\t   can't use findCert() for this because it uses getCertChain() to\n\t   build the full chain of certificates from the leaf, which would end\n\t   up calling back to here */\n\tcryptStatus = findObject( pkcs11Info, &hCertificate, certTemplate, 3 );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tcryptStatus = instantiateCert( pkcs11Info, hCertificate, iCertificate, \n\t\t\t\t\t\t\t\t\t   ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\t\t\t\t FALSE : TRUE );\n\t\t}\n#ifdef PKCS11_FIND_VIA_CRYPTLIB\n\telse\n\t\t{\n\t\tcryptStatus = searchDeviceObjects( pkcs11Info, iCertificate, NULL,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_KEYID_NONE,\n\t\t\t\t\t\t\t\t\t\t   dynData( subjectDB ), \n\t\t\t\t\t\t\t\t\t\t   dynLength( subjectDB ), TRUE );\n\t\t}\n#endif /* PKCS11_FIND_VIA_CRYPTLIB */\n\tdynDestroy( &subjectDB );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\t*stateInfo = CRYPT_ERROR;\n\t\treturn( cryptStatus );\n\t\t}\n\t*stateInfo = *iCertificate;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the function pointers to the read methods */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPKCS11Read( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tFNPTR_SET( deviceInfo->getItemFunction, getItemFunction );\n\tFNPTR_SET( deviceInfo->getFirstItemFunction, getFirstItemFunction );\n\tFNPTR_SET( deviceInfo->getNextItemFunction, getNextItemFunction );\n\t}\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib PKCS #11 Item Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"context.h\"\n  #include \"device.h\"\n  #include \"pkcs11_api.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"context/context.h\"\n  #include \"device/device.h\"\n  #include \"device/pkcs11_api.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS11\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert a time_t to a PKCS #11 CK_DATE */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void convertDate( OUT CK_DATE *date, const time_t theTime )\n\t{\n\tSTREAM stream;\n\tBYTE dateBuffer[ 32 + 8 ];\n\tint cryptStatus;\n\n\tassert( isWritePtr( date, sizeof( CK_DATE ) ) );\n\n\t/* Clear return value */\n\tmemset( date, 0, sizeof( CK_DATE ) );\n\n\t/* Convert the time_t value to an ASN.1 time string that we can use to\n\t   populate the CK_DATE fields, which are stored as ASCII text strings */\n\tsMemOpen( &stream, dateBuffer, 32 );\n\tcryptStatus = writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );\n\tsMemDisconnect( &stream );\n\tENSURES_V( cryptStatusOK( cryptStatus ) );\n\tmemcpy( date->year, dateBuffer + 2, 4 );\n\tmemcpy( date->month, dateBuffer + 6, 2 );\n\tmemcpy( date->day, dateBuffer + 8, 2 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tCertificate R/W Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up certificate information and load it into the device */\n\n#define addTemplateValue( certTemplatePtr, valueType, valuePtr, valueLen ) \\\n\t\t{ \\\n\t\t( certTemplatePtr ).type = valueType; \\\n\t\t( certTemplatePtr ).pValue = valuePtr; \\\n\t\t( certTemplatePtr ).ulValueLen = valueLen; \\\n\t\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int updateCertificate( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\t  const BOOLEAN isLeafCert )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tstatic const CK_BBOOL bTrue = CK_TRUE;\n\tCK_DATE startDate, endDate;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },\n\t\t{ CKA_ID, NULL_PTR, 0 },\n\t\t{ CKA_SUBJECT, NULL_PTR, 0 },\n\t\t{ CKA_ISSUER, NULL_PTR, 0 },\n\t\t{ CKA_SERIAL_NUMBER, NULL_PTR, 0 },\n\t\t{ CKA_VALUE, NULL_PTR, 0 },\n\t\t/* Optional fields, filled in if required and the driver supports this */\n\t\t{ CKA_NONE, NULL_PTR, 0 },\t/*  8 */\n\t\t{ CKA_NONE, NULL_PTR, 0 },\t/*  9 */\n\t\t{ CKA_NONE, NULL_PTR, 0 },\t/* 10 */\n\t\t{ CKA_NONE, NULL_PTR, 0 },\t/* 11 */\n\t\t};\n\tCK_OBJECT_HANDLE hObject;\n\tCK_RV status;\n\tMESSAGE_DATA msgData;\n\tDYNBUF subjectDB, iAndSDB, certDB;\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBOOLEAN hasURL = FALSE;\n\ttime_t theTime;\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ], uri[ MAX_URL_SIZE + 8 ];\n\tint templateCount = 8, cryptStatus;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( isLeafCert == TRUE || isLeafCert == FALSE );\n\n\t/* Get the keyID from the certificate */\n\tsetMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tcertTemplate[ 3 ].pValue = msgData.data;\n\tcertTemplate[ 3 ].ulValueLen = msgData.length;\n\n\t/* If it's a leaf certificate, use the keyID to locate the corresponding \n\t   public or private key object.  This is used as a check to ensure that \n\t   the certificate corresponds to a key in the device.  In theory this \n\t   would allow us to read the label from the key so that we can reuse it \n\t   for the certificate, but there doesn't seem to be any good reason for \n\t   this and it could lead to problems with multiple certificates with the \n\t   same labels so we don't do it */\n\tif( isLeafCert )\n\t\t{\n\t\tstatic const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;\n\t\tstatic const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;\n\t\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t\t{ CKA_ID, NULL_PTR, 0 }\n\t\t\t};\n\n\t\tkeyTemplate[ 1 ].pValue = certTemplate[ 3 ].pValue;\n\t\tkeyTemplate[ 1 ].ulValueLen = certTemplate[ 3 ].ulValueLen;\n\t\tcryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* Couldn't find a private key with this ID, try for a public key */\n\t\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubkeyClass;\n\t\t\tcryptStatus = findObject( pkcs11Info, &hObject, keyTemplate, 2 );\n\t\t\t}\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Get the validFrom and validTo dates.  These aren't currently used for\n\t   anything, but could be used in the future to handle superceded \n\t   certificates in the same way that it's done for PKCS #15 keysets */\n\tsetMessageData( &msgData, &theTime, sizeof( time_t ) );\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t   &msgData, CRYPT_CERTINFO_VALIDFROM );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\tconvertDate( &startDate, theTime );\n\t\tsetMessageData( &msgData, &theTime, sizeof( time_t ) );\n\t\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t   &msgData, CRYPT_CERTINFO_VALIDTO );\n\t\t}\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tconvertDate( &endDate, theTime );\n\n\t/* Get the subjectName and issuerAndSerialNumber from the certificate */\n\tcryptStatus = dynCreate( &subjectDB, iCryptHandle, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_SUBJECT );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = dynCreate( &iAndSDB, iCryptHandle, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tdynDestroy( &subjectDB );\n\t\treturn( cryptStatus );\n\t\t}\n\tcertTemplate[ 4 ].pValue = dynData( subjectDB );\n\tcertTemplate[ 4 ].ulValueLen = dynLength( subjectDB );\n\tcryptStatus = addIAndSToTemplate( &certTemplate[ 5 ], dynData( iAndSDB ), \n\t\t\t\t\t\t\t\t\t  dynLength( iAndSDB ) );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tdynDestroy( &subjectDB );\n\t\tdynDestroy( &iAndSDB );\n\t\treturn( cryptStatus );\n\t\t}\n\n\t/* Get the certificate data */\n\tcryptStatus = dynCreateCert( &certDB, iCryptHandle, \n\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\tdynDestroy( &subjectDB );\n\t\tdynDestroy( &iAndSDB );\n\t\treturn( cryptStatus );\n\t\t}\n\tcertTemplate[ 7 ].pValue = dynData( certDB );\n\tcertTemplate[ 7 ].ulValueLen = dynLength( certDB );\n\n\t/* Get the certificate holder name (label) from the certificate if \n\t  available */\n\tsetMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE  );\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_HOLDERNAME );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\t/* We've found a holder name, use it as the certificate object \n\t\t   label */\n\t\taddTemplateValue( certTemplate[ templateCount ], \n\t\t\t\t\t\t  CKA_LABEL, msgData.data, msgData.length );\n\t\ttemplateCount++;\n\t\t}\n\n\t/* Add the certificate dates.  These have to be located between the \n\t   label and the URI so that we can selectively back out the attributes \n\t   that don't work for this driver, see the comments further down for \n\t   more details */\n\taddTemplateValue( certTemplate[ templateCount ], \n\t\t\t\t\t  CKA_START_DATE, ( CK_VOID_PTR ) &startDate, sizeof( CK_DATE ) );\n\ttemplateCount++;\n\taddTemplateValue( certTemplate[ templateCount ], \n\t\t\t\t\t  CKA_END_DATE, ( CK_VOID_PTR ) &endDate, sizeof( CK_DATE ) );\n\ttemplateCount++;\n\n\t/* Get the URI from the certificate if available */\n\tsetMessageData( &msgData, uri, MAX_URL_SIZE );\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t   &msgData, CRYPT_IATTRIBUTE_HOLDERURI );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\t/* We've found a holder URI, use it as the certificate object URL */\n\t\taddTemplateValue( certTemplate[ templateCount ], \n\t\t\t\t\t\t  CKA_URL, msgData.data, msgData.length );\n\t\ttemplateCount++;\n\t\thasURL = TRUE;\n\t\t}\n\n\t/* Reset the status value, which may contain error values due to not \n\t   finding various object attributes above */\n\tcryptStatus = CRYPT_OK;\n\n\t/* We've finally got everything available, try and update the device with\n\t   the certificate data.  In theory we should also set CKA_PRIVATE = FALSE\n\t   but the Dallas iButton driver doesn't allow this so we have to rely on\n\t   drivers doing the right thing with the default setting */\n\tstatus = C_CreateObject( pkcs11Info->hSession,\n\t\t\t\t\t\t\t ( CK_ATTRIBUTE_PTR ) certTemplate, templateCount, \n\t\t\t\t\t\t\t &hObject );\n\tif( hasURL && ( status == CKR_TEMPLATE_INCONSISTENT || \\\n\t\t\t\t\tstatus == CKR_ATTRIBUTE_TYPE_INVALID ) )\n\t\t{\n\t\t/* Support for the PKCS #11 v2.20 attribute CKA_URL is pretty hit-\n\t\t   and-miss, some drivers from ca.2000 support it but others from \n\t\t   ca.2007 still don't so if we get a CKR_ATTRIBUTE_TYPE_INVALID \n\t\t   return code we try again without the CKA_URL */\n\t\ttemplateCount--;\n\t\tstatus = C_CreateObject( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t ( CK_ATTRIBUTE_PTR ) certTemplate, \n\t\t\t\t\t\t\t\t templateCount, &hObject );\n\t\t}\n\tif( status == CKR_TEMPLATE_INCONSISTENT || \\\n\t\tstatus == CKR_ATTRIBUTE_TYPE_INVALID )\n\t\t{\n\t\t/* Even support for dates is hit-and-miss so if we're still getting\n\t\t   CKR_ATTRIBUTE_TYPE_INVALID we try again without the \n\t\t   CKA_START_DATE/CKA_END_DATE */\n\t\ttemplateCount -= 2;\n\t\tstatus = C_CreateObject( pkcs11Info->hSession,\n\t\t\t\t\t\t\t\t ( CK_ATTRIBUTE_PTR ) certTemplate, \n\t\t\t\t\t\t\t\t templateCount, &hObject );\n\t\t}\n\tif( status != CKR_OK )\n\t\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\n\t/* Clean up */\n\tdynDestroy( &subjectDB );\n\tdynDestroy( &iAndSDB );\n\tdynDestroy( &certDB );\n\treturn( cryptStatus );\n\t}\n\n/* Update a device using the certificates in a certificate chain */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int updateCertChain( INOUT PKCS11_INFO *pkcs11Info, \n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_ISSUER, NULL_PTR, 0 },\n\t\t{ CKA_SERIAL_NUMBER, NULL_PTR, 0 },\n\t\t};\n\tBOOLEAN isLeafCert = TRUE, itemAdded = FALSE;\n\tint value, cryptStatus, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* If we've been passed a standalone certificate, check whether it's \n\t   implicitly trusted, which allows it to be added without requiring the \n\t   presence of a corresponding public/private key in the device */\n\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( cryptStatus ) )\n\t\t{\n\t\treturn( ( cryptStatus == CRYPT_ARGERROR_OBJECT ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : cryptStatus );\n\t\t}\n\tif( value == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\tBOOLEAN_INT implicitTrusted;\n\n\t\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t   &implicitTrusted, \n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_TRUSTED_IMPLICIT );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* If the certificate is implicitly trusted we indicate that it's \n\t\t   (effectively) a non-leaf certificate so that it can be added even \n\t\t   if there's no corresponding key already in the device */\n\t\tif( implicitTrusted == TRUE )\n\t\t\tisLeafCert = FALSE;\n\t\t}\n\n\t/* Add each certificate in the chain to the device */\n\tLOOP_MED_CHECKINC( cryptStatusOK( cryptStatus ),\n\t\t\t\t\t   cryptStatus = krnlSendMessage( iCryptCert, \n\t\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t{\n\t\tCK_OBJECT_HANDLE hObject;\n\t\tDYNBUF iAndSDB;\n\n\t\t/* If the certificate is already present, don't do anything */\n\t\tcryptStatus = dynCreate( &iAndSDB, iCryptCert, \n\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tcryptStatus = addIAndSToTemplate( &certTemplate[ 2 ], \n\t\t\t\t\t\t\t\t\t\t  dynData( iAndSDB ), \n\t\t\t\t\t\t\t\t\t\t  dynLength( iAndSDB ) );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t{\n\t\t\t/* In theory we could simply skip any certificates for which we \n\t\t\t   can't decode the iAndS, but in practice it's probably better \n\t\t\t   to fail and warn the user than to continue with only some \n\t\t\t   certificates added */\n\t\t\tdynDestroy( &iAndSDB );\n\t\t\treturn( cryptStatus );\n\t\t\t}\n\t\tcryptStatus = findObject( pkcs11Info, &hObject, certTemplate, 4 );\n\t\tdynDestroy( &iAndSDB );\n\t\tif( cryptStatusOK( cryptStatus ) )\n\t\t\t{\n\t\t\t/* The certificate is already present, there's nothing to do */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Add the certificate */\n\t\tcryptStatus = updateCertificate( pkcs11Info, iCryptCert, \n\t\t\t\t\t\t\t\t\t\t isLeafCert );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\treturn( cryptStatus );\n\t\tisLeafCert = FALSE;\n\t\titemAdded = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( itemAdded ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tWrite an Item to a Device\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Update a device with a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptHandle )\n\t{\n\tCRYPT_CERTIFICATE iCryptCert;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tBOOLEAN_INT immutable;\n\tint cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\n\t/* If the certificate isn't signed then we can't store it in this \n\t   state */\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t   &immutable, CRYPT_CERTINFO_IMMUTABLE );\n\tif( cryptStatusError( cryptStatus ) || !immutable )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Lock the certificate for our exclusive use (in case it's a \n\t   certificate chain we also select the first certificate in the \n\t   chain), update the device with the certificate, and unlock it to \n\t   allow others access */\n\tcryptStatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t   &iCryptCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t   MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( cryptStatus ) )\n\t\treturn( cryptStatus );\n\tcryptStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t   MESSAGE_VALUE_CURSORFIRST, \n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\tcryptStatus = updateCertChain( pkcs11Info, iCryptCert );\n\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\n\treturn( cryptStatus );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDelete an Item from a Device\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an object in a device */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int deleteItemFunction( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tstatic const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;\n\tstatic const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;\n\tstatic const CK_OBJECT_CLASS secKeyClass = CKO_SECRET_KEY;\n\tstatic const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;\n\tstatic const CK_CERTIFICATE_TYPE certType = CKC_X_509;\n\tCK_ATTRIBUTE certTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },\n\t\t{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tCK_ATTRIBUTE keyTemplate[] = {\n\t\t{ CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },\n\t\t{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }\n\t\t};\n\tCK_OBJECT_HANDLE hPrivkey = CK_OBJECT_NONE, hCertificate = CK_OBJECT_NONE;\n\tCK_OBJECT_HANDLE hPubkey = CK_OBJECT_NONE, hSecretKey = CK_OBJECT_NONE;\n\tCK_RV status;\n\tPKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;\n\tint cryptStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Find the object to delete based on the label.  Since we can have \n\t   multiple related objects (e.g. a key and a certificate) with the same \n\t   label, a straight search for all objects with a given label could \n\t   return CRYPT_ERROR_DUPLICATE so we search for the objects by type as \n\t   well as label.  In addition even a search for specific objects can \n\t   return CRYPT_ERROR_DUPLICATE so we use the -Ex version of findObject() \n\t   to make sure we don't get an error if multiple objects exist.  \n\t   Although cryptlib won't allow more than one object with a given label \n\t   to be created, other applications might create duplicate labels.  The \n\t   correct behaviour in these circumstances is uncertain, what we do for \n\t   now is delete the first object we find that matches the label.\n\t   \n\t   First we try for a certificate and use that to find associated keys */\n\tcryptStatus = findObjectEx( pkcs11Info, &hCertificate, certTemplate, 3 );\n\tif( cryptStatusOK( cryptStatus ) )\n\t\t{\n\t\t/* We got a certificate, if there are associated keys delete them as \n\t\t   well */\n\t\tcryptStatus = findObjectFromObject( pkcs11Info, hCertificate, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PUBLIC_KEY, &hPubkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CK_OBJECT_NONE;\n\t\tcryptStatus = findObjectFromObject( pkcs11Info, hCertificate, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, &hPrivkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CK_OBJECT_NONE;\n\t\t}\n\telse\n\t\t{\n\t\t/* We didn't find a certificate with the given label, try for \n\t\t   public, private, and secret keys */\n\t\thCertificate = CK_OBJECT_NONE;\n\t\tcryptStatus = findObjectEx( pkcs11Info, &hPubkey, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CK_OBJECT_NONE;\n\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;\n\t\tcryptStatus = findObjectEx( pkcs11Info, &hPrivkey, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CK_OBJECT_NONE;\n\t\tkeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &secKeyClass;\n\t\tcryptStatus = findObjectEx( pkcs11Info, &hSecretKey, keyTemplate, 2 );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thSecretKey = CK_OBJECT_NONE;\n\n\t\t/* There may be an unlabelled certificate present, try and find it \n\t\t   by looking for a certificate matching the key ID */\n\t\tif( hPubkey != CK_OBJECT_NONE || hPrivkey != CK_OBJECT_NONE )\n\t\t\t{\n\t\t\tcryptStatus = findObjectFromObject( pkcs11Info, \n\t\t\t\t\t\t\t( hPrivkey != CK_OBJECT_NONE ) ? hPrivkey : hPubkey, \n\t\t\t\t\t\t\tCKO_CERTIFICATE, &hCertificate );\n\t\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\t\thCertificate = CK_OBJECT_NONE;\n\t\t\t}\n\t\t}\n\n\t/* If we found a public key with a given label but no private key, try \n\t   and find a matching private key by ID, and vice versa */\n\tif( hPubkey != CK_OBJECT_NONE && hPrivkey == CK_OBJECT_NONE )\n\t\t{\n\t\tcryptStatus = findObjectFromObject( pkcs11Info, hPubkey, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PRIVATE_KEY, &hPrivkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPrivkey = CK_OBJECT_NONE;\n\t\t}\n\tif( hPrivkey != CK_OBJECT_NONE && hPubkey == CK_OBJECT_NONE )\n\t\t{\n\t\tcryptStatus = findObjectFromObject( pkcs11Info, hPrivkey, \n\t\t\t\t\t\t\t\t\t\t\tCKO_PUBLIC_KEY, &hPubkey );\n\t\tif( cryptStatusError( cryptStatus ) )\n\t\t\thPubkey = CK_OBJECT_NONE;\n\t\t}\n\tif( hPrivkey == CK_OBJECT_NONE && hPubkey == CK_OBJECT_NONE && \\\n\t\thSecretKey == CK_OBJECT_NONE && hCertificate == CK_OBJECT_NONE )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Reset the status values, which may contain error values due to not \n\t   finding various objects to delete above */\n\tcryptStatus = CRYPT_OK;\n\tstatus = CKR_OK;\n\n\t/* Delete the objects */\n\tif( hCertificate != CK_OBJECT_NONE )\n\t\tstatus = C_DestroyObject( pkcs11Info->hSession, hCertificate );\n\tif( hPubkey != CK_OBJECT_NONE )\n\t\t{\n\t\tint status2;\n\n\t\tstatus2 = C_DestroyObject( pkcs11Info->hSession, hPubkey );\n\t\tif( status2 != CKR_OK && status == CKR_OK )\n\t\t\tstatus = status2;\n\t\t}\n\tif( hPrivkey != CK_OBJECT_NONE )\n\t\t{\n\t\tint status2;\n\n\t\tstatus2 = C_DestroyObject( pkcs11Info->hSession, hPrivkey );\n\t\tif( status2 != CKR_OK && status == CKR_OK )\n\t\t\tstatus = status2;\n\t\t}\n\tif( hSecretKey != CK_OBJECT_NONE )\n\t\t{\n\t\tint status2;\n\n\t\tstatus2 = C_DestroyObject( pkcs11Info->hSession, hSecretKey );\n\t\tif( status2 != CKR_OK && status == CKR_OK )\n\t\t\tstatus = status2;\n\t\t}\n\tif( status != CKR_OK )\n\t\tcryptStatus = pkcs11MapError( status, CRYPT_ERROR_FAILED );\n\treturn( cryptStatus );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the function pointers to the write methods */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPKCS11Write( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tFNPTR_SET( deviceInfo->setItemFunction, setItemFunction );\n\tFNPTR_SET( deviceInfo->deleteItemFunction, deleteItemFunction );\n\t}\n#endif /* USE_PKCS11 */\n"
  },
  {
    "path": "deps/cl345/device/pkcs11f.h",
    "content": "/* pkcs11f.h include file for PKCS #11. */\n/* $Revision: 1.4 $ */\n\n/* License to copy and use this software is granted provided that it is\n * identified as \"RSA Security Inc. PKCS #11 Cryptographic Token Interface\n * (Cryptoki)\" in all material mentioning or referencing this software.\n\n * License is also granted to make and use derivative works provided that\n * such works are identified as \"derived from the RSA Security Inc. PKCS #11\n * Cryptographic Token Interface (Cryptoki)\" in all material mentioning or\n * referencing the derived work.\n\n * RSA Security Inc. makes no representations concerning either the\n * merchantability of this software or the suitability of this software for\n * any particular purpose. It is provided \"as is\" without express or implied\n * warranty of any kind.\n */\n\n/* This header file contains pretty much everything about all the */\n/* Cryptoki function prototypes.  Because this information is */\n/* used for more than just declaring function prototypes, the */\n/* order of the functions appearing herein is important, and */\n/* should not be altered. */\n\n/* General-purpose */\n\n/* C_Initialize initializes the Cryptoki library. */\nCK_PKCS11_FUNCTION_INFO(C_Initialize)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_VOID_PTR   pInitArgs  /* if this is not NULL_PTR, it gets\n                            * cast to CK_C_INITIALIZE_ARGS_PTR\n                            * and dereferenced */\n);\n#endif\n\n\n/* C_Finalize indicates that an application is done with the\n * Cryptoki library. */\nCK_PKCS11_FUNCTION_INFO(C_Finalize)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_VOID_PTR   pReserved  /* reserved.  Should be NULL_PTR */\n);\n#endif\n\n\n/* C_GetInfo returns general information about Cryptoki. */\nCK_PKCS11_FUNCTION_INFO(C_GetInfo)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_INFO_PTR   pInfo  /* location that receives information */\n);\n#endif\n\n\n/* C_GetFunctionList returns the function list. */\nCK_PKCS11_FUNCTION_INFO(C_GetFunctionList)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_FUNCTION_LIST_PTR_PTR ppFunctionList  /* receives pointer to\n                                            * function list */\n);\n#endif\n\n\n\n/* Slot and token management */\n\n/* C_GetSlotList obtains a list of slots in the system. */\nCK_PKCS11_FUNCTION_INFO(C_GetSlotList)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_BBOOL       tokenPresent,  /* only slots with tokens? */\n  CK_SLOT_ID_PTR pSlotList,     /* receives array of slot IDs */\n  CK_ULONG_PTR   pulCount       /* receives number of slots */\n);\n#endif\n\n\n/* C_GetSlotInfo obtains information about a particular slot in\n * the system. */\nCK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID       slotID,  /* the ID of the slot */\n  CK_SLOT_INFO_PTR pInfo    /* receives the slot information */\n);\n#endif\n\n\n/* C_GetTokenInfo obtains information about a particular token\n * in the system. */\nCK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID        slotID,  /* ID of the token's slot */\n  CK_TOKEN_INFO_PTR pInfo    /* receives the token information */\n);\n#endif\n\n\n/* C_GetMechanismList obtains a list of mechanism types\n * supported by a token. */\nCK_PKCS11_FUNCTION_INFO(C_GetMechanismList)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID            slotID,          /* ID of token's slot */\n  CK_MECHANISM_TYPE_PTR pMechanismList,  /* gets mech. array */\n  CK_ULONG_PTR          pulCount         /* gets # of mechs. */\n);\n#endif\n\n\n/* C_GetMechanismInfo obtains information about a particular\n * mechanism possibly supported by a token. */\nCK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID            slotID,  /* ID of the token's slot */\n  CK_MECHANISM_TYPE     type,    /* type of mechanism */\n  CK_MECHANISM_INFO_PTR pInfo    /* receives mechanism info */\n);\n#endif\n\n\n/* C_InitToken initializes a token. */\nCK_PKCS11_FUNCTION_INFO(C_InitToken)\n#ifdef CK_NEED_ARG_LIST\n/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */\n(\n  CK_SLOT_ID      slotID,    /* ID of the token's slot */\n  CK_UTF8CHAR_PTR pPin,      /* the SO's initial PIN */\n  CK_ULONG        ulPinLen,  /* length in bytes of the PIN */\n  CK_UTF8CHAR_PTR pLabel     /* 32-byte token label (blank padded) */\n);\n#endif\n\n\n/* C_InitPIN initializes the normal user's PIN. */\nCK_PKCS11_FUNCTION_INFO(C_InitPIN)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_UTF8CHAR_PTR   pPin,      /* the normal user's PIN */\n  CK_ULONG          ulPinLen   /* length in bytes of the PIN */\n);\n#endif\n\n\n/* C_SetPIN modifies the PIN of the user who is logged in. */\nCK_PKCS11_FUNCTION_INFO(C_SetPIN)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_UTF8CHAR_PTR   pOldPin,   /* the old PIN */\n  CK_ULONG          ulOldLen,  /* length of the old PIN */\n  CK_UTF8CHAR_PTR   pNewPin,   /* the new PIN */\n  CK_ULONG          ulNewLen   /* length of the new PIN */\n);\n#endif\n\n\n\n/* Session management */\n\n/* C_OpenSession opens a session between an application and a\n * token. */\nCK_PKCS11_FUNCTION_INFO(C_OpenSession)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID            slotID,        /* the slot's ID */\n  CK_FLAGS              flags,         /* from CK_SESSION_INFO */\n  CK_VOID_PTR           pApplication,  /* passed to callback */\n  CK_NOTIFY             Notify,        /* callback function */\n  CK_SESSION_HANDLE_PTR phSession      /* gets session handle */\n);\n#endif\n\n\n/* C_CloseSession closes a session between an application and a\n * token. */\nCK_PKCS11_FUNCTION_INFO(C_CloseSession)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession  /* the session's handle */\n);\n#endif\n\n\n/* C_CloseAllSessions closes all sessions with a token. */\nCK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SLOT_ID     slotID  /* the token's slot */\n);\n#endif\n\n\n/* C_GetSessionInfo obtains information about the session. */\nCK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE   hSession,  /* the session's handle */\n  CK_SESSION_INFO_PTR pInfo      /* receives session info */\n);\n#endif\n\n\n/* C_GetOperationState obtains the state of the cryptographic operation\n * in a session. */\nCK_PKCS11_FUNCTION_INFO(C_GetOperationState)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,             /* session's handle */\n  CK_BYTE_PTR       pOperationState,      /* gets state */\n  CK_ULONG_PTR      pulOperationStateLen  /* gets state length */\n);\n#endif\n\n\n/* C_SetOperationState restores the state of the cryptographic\n * operation in a session. */\nCK_PKCS11_FUNCTION_INFO(C_SetOperationState)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR      pOperationState,      /* holds state */\n  CK_ULONG         ulOperationStateLen,  /* holds state length */\n  CK_OBJECT_HANDLE hEncryptionKey,       /* en/decryption key */\n  CK_OBJECT_HANDLE hAuthenticationKey    /* sign/verify key */\n);\n#endif\n\n\n/* C_Login logs a user into a token. */\nCK_PKCS11_FUNCTION_INFO(C_Login)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_USER_TYPE      userType,  /* the user type */\n  CK_UTF8CHAR_PTR   pPin,      /* the user's PIN */\n  CK_ULONG          ulPinLen   /* the length of the PIN */\n);\n#endif\n\n\n/* C_Logout logs a user out from a token. */\nCK_PKCS11_FUNCTION_INFO(C_Logout)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession  /* the session's handle */\n);\n#endif\n\n\n\n/* Object management */\n\n/* C_CreateObject creates a new object. */\nCK_PKCS11_FUNCTION_INFO(C_CreateObject)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_ATTRIBUTE_PTR  pTemplate,   /* the object's template */\n  CK_ULONG          ulCount,     /* attributes in template */\n  CK_OBJECT_HANDLE_PTR phObject  /* gets new object's handle. */\n);\n#endif\n\n\n/* C_CopyObject copies an object, creating a new object for the\n * copy. */\nCK_PKCS11_FUNCTION_INFO(C_CopyObject)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE    hSession,    /* the session's handle */\n  CK_OBJECT_HANDLE     hObject,     /* the object's handle */\n  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new object */\n  CK_ULONG             ulCount,     /* attributes in template */\n  CK_OBJECT_HANDLE_PTR phNewObject  /* receives handle of copy */\n);\n#endif\n\n\n/* C_DestroyObject destroys an object. */\nCK_PKCS11_FUNCTION_INFO(C_DestroyObject)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_OBJECT_HANDLE  hObject    /* the object's handle */\n);\n#endif\n\n\n/* C_GetObjectSize gets the size of an object in bytes. */\nCK_PKCS11_FUNCTION_INFO(C_GetObjectSize)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_OBJECT_HANDLE  hObject,   /* the object's handle */\n\n  CK_ULONG_PTR      pulSize    /* receives size of object */\n);\n#endif\n\n\n/* C_GetAttributeValue obtains the value of one or more object\n * attributes. */\nCK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,   /* the session's handle */\n  CK_OBJECT_HANDLE  hObject,    /* the object's handle */\n  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs; gets vals */\n  CK_ULONG          ulCount     /* attributes in template */\n);\n#endif\n\n\n/* C_SetAttributeValue modifies the value of one or more object\n * attributes */\nCK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,   /* the session's handle */\n  CK_OBJECT_HANDLE  hObject,    /* the object's handle */\n  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs and values */\n  CK_ULONG          ulCount     /* attributes in template */\n);\n#endif\n\n\n/* C_FindObjectsInit initializes a search for token and session\n * objects that match a template. */\nCK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,   /* the session's handle */\n  CK_ATTRIBUTE_PTR  pTemplate,  /* attribute values to match */\n  CK_ULONG          ulCount     /* attrs in search template */\n);\n#endif\n\n\n/* C_FindObjects continues a search for token and session\n * objects that match a template, obtaining additional object\n * handles. */\nCK_PKCS11_FUNCTION_INFO(C_FindObjects)\n#ifdef CK_NEED_ARG_LIST\n(\n CK_SESSION_HANDLE    hSession,          /* session's handle */\n CK_OBJECT_HANDLE_PTR phObject,          /* gets obj. handles */\n CK_ULONG             ulMaxObjectCount,  /* max handles to get */\n CK_ULONG_PTR         pulObjectCount     /* actual # returned */\n);\n#endif\n\n\n/* C_FindObjectsFinal finishes a search for token and session\n * objects. */\nCK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession  /* the session's handle */\n);\n#endif\n\n\n\n/* Encryption and decryption */\n\n/* C_EncryptInit initializes an encryption operation. */\nCK_PKCS11_FUNCTION_INFO(C_EncryptInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,  /* the encryption mechanism */\n  CK_OBJECT_HANDLE  hKey         /* handle of encryption key */\n);\n#endif\n\n\n/* C_Encrypt encrypts single-part data. */\nCK_PKCS11_FUNCTION_INFO(C_Encrypt)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pData,               /* the plaintext data */\n  CK_ULONG          ulDataLen,           /* bytes of plaintext */\n  CK_BYTE_PTR       pEncryptedData,      /* gets ciphertext */\n  CK_ULONG_PTR      pulEncryptedDataLen  /* gets c-text size */\n);\n#endif\n\n\n/* C_EncryptUpdate continues a multiple-part encryption\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,           /* session's handle */\n  CK_BYTE_PTR       pPart,              /* the plaintext data */\n  CK_ULONG          ulPartLen,          /* plaintext data len */\n  CK_BYTE_PTR       pEncryptedPart,     /* gets ciphertext */\n  CK_ULONG_PTR      pulEncryptedPartLen /* gets c-text size */\n);\n#endif\n\n\n/* C_EncryptFinal finishes a multiple-part encryption\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_EncryptFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,                /* session handle */\n  CK_BYTE_PTR       pLastEncryptedPart,      /* last c-text */\n  CK_ULONG_PTR      pulLastEncryptedPartLen  /* gets last size */\n);\n#endif\n\n\n/* C_DecryptInit initializes a decryption operation. */\nCK_PKCS11_FUNCTION_INFO(C_DecryptInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,  /* the decryption mechanism */\n  CK_OBJECT_HANDLE  hKey         /* handle of decryption key */\n);\n#endif\n\n\n/* C_Decrypt decrypts encrypted data in a single part. */\nCK_PKCS11_FUNCTION_INFO(C_Decrypt)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,           /* session's handle */\n  CK_BYTE_PTR       pEncryptedData,     /* ciphertext */\n  CK_ULONG          ulEncryptedDataLen, /* ciphertext length */\n  CK_BYTE_PTR       pData,              /* gets plaintext */\n  CK_ULONG_PTR      pulDataLen          /* gets p-text size */\n);\n#endif\n\n\n/* C_DecryptUpdate continues a multiple-part decryption\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pEncryptedPart,      /* encrypted data */\n  CK_ULONG          ulEncryptedPartLen,  /* input length */\n  CK_BYTE_PTR       pPart,               /* gets plaintext */\n  CK_ULONG_PTR      pulPartLen           /* p-text size */\n);\n#endif\n\n\n/* C_DecryptFinal finishes a multiple-part decryption\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_DecryptFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,       /* the session's handle */\n  CK_BYTE_PTR       pLastPart,      /* gets plaintext */\n  CK_ULONG_PTR      pulLastPartLen  /* p-text size */\n);\n#endif\n\n\n\n/* Message digesting */\n\n/* C_DigestInit initializes a message-digesting operation. */\nCK_PKCS11_FUNCTION_INFO(C_DigestInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,   /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism  /* the digesting mechanism */\n);\n#endif\n\n\n/* C_Digest digests data in a single part. */\nCK_PKCS11_FUNCTION_INFO(C_Digest)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,     /* the session's handle */\n  CK_BYTE_PTR       pData,        /* data to be digested */\n  CK_ULONG          ulDataLen,    /* bytes of data to digest */\n  CK_BYTE_PTR       pDigest,      /* gets the message digest */\n  CK_ULONG_PTR      pulDigestLen  /* gets digest length */\n);\n#endif\n\n\n/* C_DigestUpdate continues a multiple-part message-digesting\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_DigestUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_BYTE_PTR       pPart,     /* data to be digested */\n  CK_ULONG          ulPartLen  /* bytes of data to be digested */\n);\n#endif\n\n\n/* C_DigestKey continues a multi-part message-digesting\n * operation, by digesting the value of a secret key as part of\n * the data already digested. */\nCK_PKCS11_FUNCTION_INFO(C_DigestKey)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_OBJECT_HANDLE  hKey       /* secret key to digest */\n);\n#endif\n\n\n/* C_DigestFinal finishes a multiple-part message-digesting\n * operation. */\nCK_PKCS11_FUNCTION_INFO(C_DigestFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,     /* the session's handle */\n  CK_BYTE_PTR       pDigest,      /* gets the message digest */\n  CK_ULONG_PTR      pulDigestLen  /* gets byte count of digest */\n);\n#endif\n\n\n\n/* Signing and MACing */\n\n/* C_SignInit initializes a signature (private key encryption)\n * operation, where the signature is (will be) an appendix to\n * the data, and plaintext cannot be recovered from the\n *signature. */\nCK_PKCS11_FUNCTION_INFO(C_SignInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,  /* the signature mechanism */\n  CK_OBJECT_HANDLE  hKey         /* handle of signature key */\n);\n#endif\n\n\n/* C_Sign signs (encrypts with private key) data in a single\n * part, where the signature is (will be) an appendix to the\n * data, and plaintext cannot be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_Sign)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,        /* the session's handle */\n  CK_BYTE_PTR       pData,           /* the data to sign */\n  CK_ULONG          ulDataLen,       /* count of bytes to sign */\n  CK_BYTE_PTR       pSignature,      /* gets the signature */\n  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */\n);\n#endif\n\n\n/* C_SignUpdate continues a multiple-part signature operation,\n * where the signature is (will be) an appendix to the data,\n * and plaintext cannot be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_SignUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_BYTE_PTR       pPart,     /* the data to sign */\n  CK_ULONG          ulPartLen  /* count of bytes to sign */\n);\n#endif\n\n\n/* C_SignFinal finishes a multiple-part signature operation,\n * returning the signature. */\nCK_PKCS11_FUNCTION_INFO(C_SignFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,        /* the session's handle */\n  CK_BYTE_PTR       pSignature,      /* gets the signature */\n  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */\n);\n#endif\n\n\n/* C_SignRecoverInit initializes a signature operation, where\n * the data can be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,   /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism, /* the signature mechanism */\n  CK_OBJECT_HANDLE  hKey        /* handle of the signature key */\n);\n#endif\n\n\n/* C_SignRecover signs data in a single operation, where the\n * data can be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_SignRecover)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,        /* the session's handle */\n  CK_BYTE_PTR       pData,           /* the data to sign */\n  CK_ULONG          ulDataLen,       /* count of bytes to sign */\n  CK_BYTE_PTR       pSignature,      /* gets the signature */\n  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */\n);\n#endif\n\n\n\n/* Verifying signatures and MACs */\n\n/* C_VerifyInit initializes a verification operation, where the\n * signature is an appendix to the data, and plaintext cannot\n *  cannot be recovered from the signature (e.g. DSA). */\nCK_PKCS11_FUNCTION_INFO(C_VerifyInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */\n  CK_OBJECT_HANDLE  hKey         /* verification key */\n);\n#endif\n\n\n/* C_Verify verifies a signature in a single-part operation,\n * where the signature is an appendix to the data, and plaintext\n * cannot be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_Verify)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,       /* the session's handle */\n  CK_BYTE_PTR       pData,          /* signed data */\n  CK_ULONG          ulDataLen,      /* length of signed data */\n  CK_BYTE_PTR       pSignature,     /* signature */\n  CK_ULONG          ulSignatureLen  /* signature length*/\n);\n#endif\n\n\n/* C_VerifyUpdate continues a multiple-part verification\n * operation, where the signature is an appendix to the data,\n * and plaintext cannot be recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_BYTE_PTR       pPart,     /* signed data */\n  CK_ULONG          ulPartLen  /* length of signed data */\n);\n#endif\n\n\n/* C_VerifyFinal finishes a multiple-part verification\n * operation, checking the signature. */\nCK_PKCS11_FUNCTION_INFO(C_VerifyFinal)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,       /* the session's handle */\n  CK_BYTE_PTR       pSignature,     /* signature to verify */\n  CK_ULONG          ulSignatureLen  /* signature length */\n);\n#endif\n\n\n/* C_VerifyRecoverInit initializes a signature verification\n * operation, where the data is recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */\n  CK_OBJECT_HANDLE  hKey         /* verification key */\n);\n#endif\n\n\n/* C_VerifyRecover verifies a signature in a single-part\n * operation, where the data is recovered from the signature. */\nCK_PKCS11_FUNCTION_INFO(C_VerifyRecover)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,        /* the session's handle */\n  CK_BYTE_PTR       pSignature,      /* signature to verify */\n  CK_ULONG          ulSignatureLen,  /* signature length */\n  CK_BYTE_PTR       pData,           /* gets signed data */\n  CK_ULONG_PTR      pulDataLen       /* gets signed data len */\n);\n#endif\n\n\n\n/* Dual-function cryptographic operations */\n\n/* C_DigestEncryptUpdate continues a multiple-part digesting\n * and encryption operation. */\nCK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pPart,               /* the plaintext data */\n  CK_ULONG          ulPartLen,           /* plaintext length */\n  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */\n  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */\n);\n#endif\n\n\n/* C_DecryptDigestUpdate continues a multiple-part decryption and\n * digesting operation. */\nCK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */\n  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */\n  CK_BYTE_PTR       pPart,               /* gets plaintext */\n  CK_ULONG_PTR      pulPartLen           /* gets plaintext len */\n);\n#endif\n\n\n/* C_SignEncryptUpdate continues a multiple-part signing and\n * encryption operation. */\nCK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pPart,               /* the plaintext data */\n  CK_ULONG          ulPartLen,           /* plaintext length */\n  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */\n  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */\n);\n#endif\n\n\n/* C_DecryptVerifyUpdate continues a multiple-part decryption and\n * verify operation. */\nCK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,            /* session's handle */\n  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */\n  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */\n  CK_BYTE_PTR       pPart,               /* gets plaintext */\n  CK_ULONG_PTR      pulPartLen           /* gets p-text length */\n);\n#endif\n\n\n\n/* Key management */\n\n/* C_GenerateKey generates a secret key, creating a new key\n * object. */\nCK_PKCS11_FUNCTION_INFO(C_GenerateKey)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE    hSession,    /* the session's handle */\n  CK_MECHANISM_PTR     pMechanism,  /* key generation mech. */\n  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new key */\n  CK_ULONG             ulCount,     /* # of attrs in template */\n  CK_OBJECT_HANDLE_PTR phKey        /* gets handle of new key */\n);\n#endif\n\n\n/* C_GenerateKeyPair generates a public-key/private-key pair,\n * creating new key objects. */\nCK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE    hSession,                    /* session\n                                                     * handle */\n  CK_MECHANISM_PTR     pMechanism,                  /* key-gen\n                                                     * mech. */\n  CK_ATTRIBUTE_PTR     pPublicKeyTemplate,          /* template\n                                                     * for pub.\n                                                     * key */\n  CK_ULONG             ulPublicKeyAttributeCount,   /* # pub.\n                                                     * attrs. */\n  CK_ATTRIBUTE_PTR     pPrivateKeyTemplate,         /* template\n                                                     * for priv.\n                                                     * key */\n  CK_ULONG             ulPrivateKeyAttributeCount,  /* # priv.\n                                                     * attrs. */\n  CK_OBJECT_HANDLE_PTR phPublicKey,                 /* gets pub.\n                                                     * key\n                                                     * handle */\n  CK_OBJECT_HANDLE_PTR phPrivateKey                 /* gets\n                                                     * priv. key\n                                                     * handle */\n);\n#endif\n\n\n/* C_WrapKey wraps (i.e., encrypts) a key. */\nCK_PKCS11_FUNCTION_INFO(C_WrapKey)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,        /* the session's handle */\n  CK_MECHANISM_PTR  pMechanism,      /* the wrapping mechanism */\n  CK_OBJECT_HANDLE  hWrappingKey,    /* wrapping key */\n  CK_OBJECT_HANDLE  hKey,            /* key to be wrapped */\n  CK_BYTE_PTR       pWrappedKey,     /* gets wrapped key */\n  CK_ULONG_PTR      pulWrappedKeyLen /* gets wrapped key size */\n);\n#endif\n\n\n/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new\n * key object. */\nCK_PKCS11_FUNCTION_INFO(C_UnwrapKey)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE    hSession,          /* session's handle */\n  CK_MECHANISM_PTR     pMechanism,        /* unwrapping mech. */\n  CK_OBJECT_HANDLE     hUnwrappingKey,    /* unwrapping key */\n  CK_BYTE_PTR          pWrappedKey,       /* the wrapped key */\n  CK_ULONG             ulWrappedKeyLen,   /* wrapped key len */\n  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */\n  CK_ULONG             ulAttributeCount,  /* template length */\n  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */\n);\n#endif\n\n\n/* C_DeriveKey derives a key from a base key, creating a new key\n * object. */\nCK_PKCS11_FUNCTION_INFO(C_DeriveKey)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE    hSession,          /* session's handle */\n  CK_MECHANISM_PTR     pMechanism,        /* key deriv. mech. */\n  CK_OBJECT_HANDLE     hBaseKey,          /* base key */\n  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */\n  CK_ULONG             ulAttributeCount,  /* template length */\n  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */\n);\n#endif\n\n\n\n/* Random number generation */\n\n/* C_SeedRandom mixes additional seed material into the token's\n * random number generator. */\nCK_PKCS11_FUNCTION_INFO(C_SeedRandom)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,  /* the session's handle */\n  CK_BYTE_PTR       pSeed,     /* the seed material */\n  CK_ULONG          ulSeedLen  /* length of seed material */\n);\n#endif\n\n\n\n/* C_GenerateRandom generates random data. */\nCK_PKCS11_FUNCTION_INFO(C_GenerateRandom)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession,    /* the session's handle */\n  CK_BYTE_PTR       RandomData,  /* receives the random data */\n  CK_ULONG          ulRandomLen  /* # of bytes to generate */\n);\n#endif\n\n\n\n/* Parallel function management */\n\n/* C_GetFunctionStatus is a legacy function; it obtains an\n * updated status of a function running in parallel with an\n * application. */\nCK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession  /* the session's handle */\n);\n#endif\n\n\n/* C_CancelFunction is a legacy function; it cancels a function\n * running in parallel. */\nCK_PKCS11_FUNCTION_INFO(C_CancelFunction)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_SESSION_HANDLE hSession  /* the session's handle */\n);\n#endif\n\n\n\n/* Functions added in for Cryptoki Version 2.01 or later */\n\n/* C_WaitForSlotEvent waits for a slot event (token insertion,\n * removal, etc.) to occur. */\nCK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)\n#ifdef CK_NEED_ARG_LIST\n(\n  CK_FLAGS flags,        /* blocking/nonblocking flag */\n  CK_SLOT_ID_PTR pSlot,  /* location that receives the slot ID */\n  CK_VOID_PTR pRserved   /* reserved.  Should be NULL_PTR */\n);\n#endif\n"
  },
  {
    "path": "deps/cl345/device/pkcs11t.h",
    "content": "/* pkcs11t.h include file for PKCS #11. */\n/* $Revision: 1.10 $ */\n\n/* License to copy and use this software is granted provided that it is\n * identified as \"RSA Security Inc. PKCS #11 Cryptographic Token Interface\n * (Cryptoki)\" in all material mentioning or referencing this software.\n\n * License is also granted to make and use derivative works provided that\n * such works are identified as \"derived from the RSA Security Inc. PKCS #11\n * Cryptographic Token Interface (Cryptoki)\" in all material mentioning or\n * referencing the derived work.\n\n * RSA Security Inc. makes no representations concerning either the\n * merchantability of this software or the suitability of this software for\n * any particular purpose. It is provided \"as is\" without express or implied\n * warranty of any kind.\n */\n\n/* See top of pkcs11.h for information about the macros that\n * must be defined and the structure-packing conventions that\n * must be set before including this file. */\n\n#ifndef _PKCS11T_H_\n#define _PKCS11T_H_ 1\n\n#define CRYPTOKI_VERSION_MAJOR 2\n#define CRYPTOKI_VERSION_MINOR 20\n#define CRYPTOKI_VERSION_AMENDMENT 3\n\n#define CK_TRUE 1\n#define CK_FALSE 0\n\n#ifndef CK_DISABLE_TRUE_FALSE\n#ifndef FALSE\n#define FALSE CK_FALSE\n#endif\n\n#ifndef TRUE\n#define TRUE CK_TRUE\n#endif\n#endif\n\n/* an unsigned 8-bit value */\ntypedef unsigned char     CK_BYTE;\n\n/* an unsigned 8-bit character */\ntypedef CK_BYTE           CK_CHAR;\n\n/* an 8-bit UTF-8 character */\ntypedef CK_BYTE           CK_UTF8CHAR;\n\n/* a BYTE-sized Boolean flag */\ntypedef CK_BYTE           CK_BBOOL;\n\n/* an unsigned value, at least 32 bits long */\ntypedef unsigned long int CK_ULONG;\n\n/* a signed value, the same size as a CK_ULONG */\n/* CK_LONG is new for v2.0 */\ntypedef long int          CK_LONG;\n\n/* at least 32 bits; each bit is a Boolean flag */\ntypedef CK_ULONG          CK_FLAGS;\n\n\n/* some special values for certain CK_ULONG variables */\n#define CK_UNAVAILABLE_INFORMATION (~0UL)\n#define CK_EFFECTIVELY_INFINITE    0\n\n\ntypedef CK_BYTE     CK_PTR   CK_BYTE_PTR;\ntypedef CK_CHAR     CK_PTR   CK_CHAR_PTR;\ntypedef CK_UTF8CHAR CK_PTR   CK_UTF8CHAR_PTR;\ntypedef CK_ULONG    CK_PTR   CK_ULONG_PTR;\ntypedef void        CK_PTR   CK_VOID_PTR;\n\n/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */\ntypedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;\n\n\n/* The following value is always invalid if used as a session */\n/* handle or object handle */\n#define CK_INVALID_HANDLE 0\n\n\ntypedef struct CK_VERSION {\n  CK_BYTE       major;  /* integer portion of version number */\n  CK_BYTE       minor;  /* 1/100ths portion of version number */\n} CK_VERSION;\n\ntypedef CK_VERSION CK_PTR CK_VERSION_PTR;\n\n\ntypedef struct CK_INFO {\n  /* manufacturerID and libraryDecription have been changed from\n   * CK_CHAR to CK_UTF8CHAR for v2.10 */\n  CK_VERSION    cryptokiVersion;     /* Cryptoki interface ver */\n  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */\n  CK_FLAGS      flags;               /* must be zero */\n\n  /* libraryDescription and libraryVersion are new for v2.0 */\n  CK_UTF8CHAR   libraryDescription[32];  /* blank padded */\n  CK_VERSION    libraryVersion;          /* version of library */\n} CK_INFO;\n\ntypedef CK_INFO CK_PTR    CK_INFO_PTR;\n\n\n/* CK_NOTIFICATION enumerates the types of notifications that\n * Cryptoki provides to an application */\n/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG\n * for v2.0 */\ntypedef CK_ULONG CK_NOTIFICATION;\n#define CKN_SURRENDER       0\n\n/* The following notification is new for PKCS #11 v2.20 amendment 3 */\n#define CKN_OTP_CHANGED     1\n\n\ntypedef CK_ULONG          CK_SLOT_ID;\n\ntypedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;\n\n\n/* CK_SLOT_INFO provides information about a slot */\ntypedef struct CK_SLOT_INFO {\n  /* slotDescription and manufacturerID have been changed from\n   * CK_CHAR to CK_UTF8CHAR for v2.10 */\n  CK_UTF8CHAR   slotDescription[64];  /* blank padded */\n  CK_UTF8CHAR   manufacturerID[32];   /* blank padded */\n  CK_FLAGS      flags;\n\n  /* hardwareVersion and firmwareVersion are new for v2.0 */\n  CK_VERSION    hardwareVersion;  /* version of hardware */\n  CK_VERSION    firmwareVersion;  /* version of firmware */\n} CK_SLOT_INFO;\n\n/* flags: bit flags that provide capabilities of the slot\n *      Bit Flag              Mask        Meaning\n */\n#define CKF_TOKEN_PRESENT     0x00000001  /* a token is there */\n#define CKF_REMOVABLE_DEVICE  0x00000002  /* removable devices*/\n#define CKF_HW_SLOT           0x00000004  /* hardware slot */\n\ntypedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;\n\n\n/* CK_TOKEN_INFO provides information about a token */\ntypedef struct CK_TOKEN_INFO {\n  /* label, manufacturerID, and model have been changed from\n   * CK_CHAR to CK_UTF8CHAR for v2.10 */\n  CK_UTF8CHAR   label[32];           /* blank padded */\n  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */\n  CK_UTF8CHAR   model[16];           /* blank padded */\n  CK_CHAR       serialNumber[16];    /* blank padded */\n  CK_FLAGS      flags;               /* see below */\n\n  /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,\n   * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been\n   * changed from CK_USHORT to CK_ULONG for v2.0 */\n  CK_ULONG      ulMaxSessionCount;     /* max open sessions */\n  CK_ULONG      ulSessionCount;        /* sess. now open */\n  CK_ULONG      ulMaxRwSessionCount;   /* max R/W sessions */\n  CK_ULONG      ulRwSessionCount;      /* R/W sess. now open */\n  CK_ULONG      ulMaxPinLen;           /* in bytes */\n  CK_ULONG      ulMinPinLen;           /* in bytes */\n  CK_ULONG      ulTotalPublicMemory;   /* in bytes */\n  CK_ULONG      ulFreePublicMemory;    /* in bytes */\n  CK_ULONG      ulTotalPrivateMemory;  /* in bytes */\n  CK_ULONG      ulFreePrivateMemory;   /* in bytes */\n\n  /* hardwareVersion, firmwareVersion, and time are new for\n   * v2.0 */\n  CK_VERSION    hardwareVersion;       /* version of hardware */\n  CK_VERSION    firmwareVersion;       /* version of firmware */\n  CK_CHAR       utcTime[16];           /* time */\n} CK_TOKEN_INFO;\n\n/* The flags parameter is defined as follows:\n *      Bit Flag                    Mask        Meaning\n */\n#define CKF_RNG                     0x00000001  /* has random #\n                                                 * generator */\n#define CKF_WRITE_PROTECTED         0x00000002  /* token is\n                                                 * write-\n                                                 * protected */\n#define CKF_LOGIN_REQUIRED          0x00000004  /* user must\n                                                 * login */\n#define CKF_USER_PIN_INITIALIZED    0x00000008  /* normal user's\n                                                 * PIN is set */\n\n/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0.  If it is set,\n * that means that *every* time the state of cryptographic\n * operations of a session is successfully saved, all keys\n * needed to continue those operations are stored in the state */\n#define CKF_RESTORE_KEY_NOT_NEEDED  0x00000020\n\n/* CKF_CLOCK_ON_TOKEN is new for v2.0.  If it is set, that means\n * that the token has some sort of clock.  The time on that\n * clock is returned in the token info structure */\n#define CKF_CLOCK_ON_TOKEN          0x00000040\n\n/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0.  If it is\n * set, that means that there is some way for the user to login\n * without sending a PIN through the Cryptoki library itself */\n#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100\n\n/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0.  If it is true,\n * that means that a single session with the token can perform\n * dual simultaneous cryptographic operations (digest and\n * encrypt; decrypt and digest; sign and encrypt; and decrypt\n * and sign) */\n#define CKF_DUAL_CRYPTO_OPERATIONS  0x00000200\n\n/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the\n * token has been initialized using C_InitializeToken or an\n * equivalent mechanism outside the scope of PKCS #11.\n * Calling C_InitializeToken when this flag is set will cause\n * the token to be reinitialized. */\n#define CKF_TOKEN_INITIALIZED       0x00000400\n\n/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is\n * true, the token supports secondary authentication for\n * private key objects. This flag is deprecated in v2.11 and\n   onwards. */\n#define CKF_SECONDARY_AUTHENTICATION  0x00000800\n\n/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an\n * incorrect user login PIN has been entered at least once\n * since the last successful authentication. */\n#define CKF_USER_PIN_COUNT_LOW       0x00010000\n\n/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,\n * supplying an incorrect user PIN will it to become locked. */\n#define CKF_USER_PIN_FINAL_TRY       0x00020000\n\n/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the\n * user PIN has been locked. User login to the token is not\n * possible. */\n#define CKF_USER_PIN_LOCKED          0x00040000\n\n/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,\n * the user PIN value is the default value set by token\n * initialization or manufacturing, or the PIN has been\n * expired by the card. */\n#define CKF_USER_PIN_TO_BE_CHANGED   0x00080000\n\n/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an\n * incorrect SO login PIN has been entered at least once since\n * the last successful authentication. */\n#define CKF_SO_PIN_COUNT_LOW         0x00100000\n\n/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,\n * supplying an incorrect SO PIN will it to become locked. */\n#define CKF_SO_PIN_FINAL_TRY         0x00200000\n\n/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO\n * PIN has been locked. SO login to the token is not possible.\n */\n#define CKF_SO_PIN_LOCKED            0x00400000\n\n/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,\n * the SO PIN value is the default value set by token\n * initialization or manufacturing, or the PIN has been\n * expired by the card. */\n#define CKF_SO_PIN_TO_BE_CHANGED     0x00800000\n\ntypedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;\n\n\n/* CK_SESSION_HANDLE is a Cryptoki-assigned value that\n * identifies a session */\ntypedef CK_ULONG          CK_SESSION_HANDLE;\n\ntypedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;\n\n\n/* CK_USER_TYPE enumerates the types of Cryptoki users */\n/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for\n * v2.0 */\ntypedef CK_ULONG          CK_USER_TYPE;\n/* Security Officer */\n#define CKU_SO    0\n/* Normal user */\n#define CKU_USER  1\n/* Context specific (added in v2.20) */\n#define CKU_CONTEXT_SPECIFIC   2\n\n/* CK_STATE enumerates the session states */\n/* CK_STATE has been changed from an enum to a CK_ULONG for\n * v2.0 */\ntypedef CK_ULONG          CK_STATE;\n#define CKS_RO_PUBLIC_SESSION  0\n#define CKS_RO_USER_FUNCTIONS  1\n#define CKS_RW_PUBLIC_SESSION  2\n#define CKS_RW_USER_FUNCTIONS  3\n#define CKS_RW_SO_FUNCTIONS    4\n\n\n/* CK_SESSION_INFO provides information about a session */\ntypedef struct CK_SESSION_INFO {\n  CK_SLOT_ID    slotID;\n  CK_STATE      state;\n  CK_FLAGS      flags;          /* see below */\n\n  /* ulDeviceError was changed from CK_USHORT to CK_ULONG for\n   * v2.0 */\n  CK_ULONG      ulDeviceError;  /* device-dependent error code */\n} CK_SESSION_INFO;\n\n/* The flags are defined in the following table:\n *      Bit Flag                Mask        Meaning\n */\n#define CKF_RW_SESSION          0x00000002  /* session is r/w */\n#define CKF_SERIAL_SESSION      0x00000004  /* no parallel */\n\ntypedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;\n\n\n/* CK_OBJECT_HANDLE is a token-specific identifier for an\n * object  */\ntypedef CK_ULONG          CK_OBJECT_HANDLE;\n\ntypedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;\n\n\n/* CK_OBJECT_CLASS is a value that identifies the classes (or\n * types) of objects that Cryptoki recognizes.  It is defined\n * as follows: */\n/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for\n * v2.0 */\ntypedef CK_ULONG          CK_OBJECT_CLASS;\n\n/* The following classes of objects are defined: */\n/* CKO_HW_FEATURE is new for v2.10 */\n/* CKO_DOMAIN_PARAMETERS is new for v2.11 */\n/* CKO_MECHANISM is new for v2.20 */\n#define CKO_DATA              0x00000000\n#define CKO_CERTIFICATE       0x00000001\n#define CKO_PUBLIC_KEY        0x00000002\n#define CKO_PRIVATE_KEY       0x00000003\n#define CKO_SECRET_KEY        0x00000004\n#define CKO_HW_FEATURE        0x00000005\n#define CKO_DOMAIN_PARAMETERS 0x00000006\n#define CKO_MECHANISM         0x00000007\n\n/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */\n#define CKO_OTP_KEY           0x00000008\n\n#define CKO_VENDOR_DEFINED    0x80000000\n\ntypedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;\n\n/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a\n * value that identifies the hardware feature type of an object\n * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */\ntypedef CK_ULONG          CK_HW_FEATURE_TYPE;\n\n/* The following hardware feature types are defined */\n/* CKH_USER_INTERFACE is new for v2.20 */\n#define CKH_MONOTONIC_COUNTER  0x00000001\n#define CKH_CLOCK           0x00000002\n#define CKH_USER_INTERFACE  0x00000003\n#define CKH_VENDOR_DEFINED  0x80000000\n\n/* CK_KEY_TYPE is a value that identifies a key type */\n/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */\ntypedef CK_ULONG          CK_KEY_TYPE;\n\n/* the following key types are defined: */\n#define CKK_RSA             0x00000000\n#define CKK_DSA             0x00000001\n#define CKK_DH              0x00000002\n\n/* CKK_ECDSA and CKK_KEA are new for v2.0 */\n/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */\n#define CKK_ECDSA           0x00000003\n#define CKK_EC              0x00000003\n#define CKK_X9_42_DH        0x00000004\n#define CKK_KEA             0x00000005\n\n#define CKK_GENERIC_SECRET  0x00000010\n#define CKK_RC2             0x00000011\n#define CKK_RC4             0x00000012\n#define CKK_DES             0x00000013\n#define CKK_DES2            0x00000014\n#define CKK_DES3            0x00000015\n\n/* all these key types are new for v2.0 */\n#define CKK_CAST            0x00000016\n#define CKK_CAST3           0x00000017\n/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */\n#define CKK_CAST5           0x00000018\n#define CKK_CAST128         0x00000018\n#define CKK_RC5             0x00000019\n#define CKK_IDEA            0x0000001A\n#define CKK_SKIPJACK        0x0000001B\n#define CKK_BATON           0x0000001C\n#define CKK_JUNIPER         0x0000001D\n#define CKK_CDMF            0x0000001E\n#define CKK_AES             0x0000001F\n\n/* BlowFish and TwoFish are new for v2.20 */\n#define CKK_BLOWFISH        0x00000020\n#define CKK_TWOFISH         0x00000021\n\n/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */\n#define CKK_SECURID         0x00000022\n#define CKK_HOTP            0x00000023\n#define CKK_ACTI            0x00000024\n\n/* Camellia is new for PKCS #11 v2.20 amendment 3 */\n#define CKK_CAMELLIA                   0x00000025\n/* ARIA is new for PKCS #11 v2.20 amendment 3 */\n#define CKK_ARIA                       0x00000026\n\n\n#define CKK_VENDOR_DEFINED  0x80000000\n\n\n/* CK_CERTIFICATE_TYPE is a value that identifies a certificate\n * type */\n/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG\n * for v2.0 */\ntypedef CK_ULONG          CK_CERTIFICATE_TYPE;\n\n/* The following certificate types are defined: */\n/* CKC_X_509_ATTR_CERT is new for v2.10 */\n/* CKC_WTLS is new for v2.20 */\n#define CKC_X_509           0x00000000\n#define CKC_X_509_ATTR_CERT 0x00000001\n#define CKC_WTLS            0x00000002\n#define CKC_VENDOR_DEFINED  0x80000000\n\n\n/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute\n * type */\n/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for\n * v2.0 */\ntypedef CK_ULONG          CK_ATTRIBUTE_TYPE;\n\n/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which\n   consists of an array of values. */\n#define CKF_ARRAY_ATTRIBUTE    0x40000000\n\n/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1\n   and relates to the CKA_OTP_FORMAT attribute */\n#define CK_OTP_FORMAT_DECIMAL      0\n#define CK_OTP_FORMAT_HEXADECIMAL  1\n#define CK_OTP_FORMAT_ALPHANUMERIC 2\n#define CK_OTP_FORMAT_BINARY       3\n\n/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1\n   and relates to the CKA_OTP_..._REQUIREMENT attributes */\n#define CK_OTP_PARAM_IGNORED       0\n#define CK_OTP_PARAM_OPTIONAL      1\n#define CK_OTP_PARAM_MANDATORY     2\n\n/* The following attribute types are defined: */\n#define CKA_CLASS              0x00000000\n#define CKA_TOKEN              0x00000001\n#define CKA_PRIVATE            0x00000002\n#define CKA_LABEL              0x00000003\n#define CKA_APPLICATION        0x00000010\n#define CKA_VALUE              0x00000011\n\n/* CKA_OBJECT_ID is new for v2.10 */\n#define CKA_OBJECT_ID          0x00000012\n\n#define CKA_CERTIFICATE_TYPE   0x00000080\n#define CKA_ISSUER             0x00000081\n#define CKA_SERIAL_NUMBER      0x00000082\n\n/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new\n * for v2.10 */\n#define CKA_AC_ISSUER          0x00000083\n#define CKA_OWNER              0x00000084\n#define CKA_ATTR_TYPES         0x00000085\n\n/* CKA_TRUSTED is new for v2.11 */\n#define CKA_TRUSTED            0x00000086\n\n/* CKA_CERTIFICATE_CATEGORY ...\n * CKA_CHECK_VALUE are new for v2.20 */\n#define CKA_CERTIFICATE_CATEGORY        0x00000087\n#define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088\n#define CKA_URL                         0x00000089\n#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008A\n#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008B\n#define CKA_CHECK_VALUE                 0x00000090\n\n#define CKA_KEY_TYPE           0x00000100\n#define CKA_SUBJECT            0x00000101\n#define CKA_ID                 0x00000102\n#define CKA_SENSITIVE          0x00000103\n#define CKA_ENCRYPT            0x00000104\n#define CKA_DECRYPT            0x00000105\n#define CKA_WRAP               0x00000106\n#define CKA_UNWRAP             0x00000107\n#define CKA_SIGN               0x00000108\n#define CKA_SIGN_RECOVER       0x00000109\n#define CKA_VERIFY             0x0000010A\n#define CKA_VERIFY_RECOVER     0x0000010B\n#define CKA_DERIVE             0x0000010C\n#define CKA_START_DATE         0x00000110\n#define CKA_END_DATE           0x00000111\n#define CKA_MODULUS            0x00000120\n#define CKA_MODULUS_BITS       0x00000121\n#define CKA_PUBLIC_EXPONENT    0x00000122\n#define CKA_PRIVATE_EXPONENT   0x00000123\n#define CKA_PRIME_1            0x00000124\n#define CKA_PRIME_2            0x00000125\n#define CKA_EXPONENT_1         0x00000126\n#define CKA_EXPONENT_2         0x00000127\n#define CKA_COEFFICIENT        0x00000128\n#define CKA_PRIME              0x00000130\n#define CKA_SUBPRIME           0x00000131\n#define CKA_BASE               0x00000132\n\n/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */\n#define CKA_PRIME_BITS         0x00000133\n#define CKA_SUBPRIME_BITS      0x00000134\n#define CKA_SUB_PRIME_BITS     CKA_SUBPRIME_BITS\n/* (To retain backwards-compatibility) */\n\n#define CKA_VALUE_BITS         0x00000160\n#define CKA_VALUE_LEN          0x00000161\n\n/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,\n * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,\n * and CKA_EC_POINT are new for v2.0 */\n#define CKA_EXTRACTABLE        0x00000162\n#define CKA_LOCAL              0x00000163\n#define CKA_NEVER_EXTRACTABLE  0x00000164\n#define CKA_ALWAYS_SENSITIVE   0x00000165\n\n/* CKA_KEY_GEN_MECHANISM is new for v2.11 */\n#define CKA_KEY_GEN_MECHANISM  0x00000166\n\n#define CKA_MODIFIABLE         0x00000170\n\n/* CKA_ECDSA_PARAMS is deprecated in v2.11,\n * CKA_EC_PARAMS is preferred. */\n#define CKA_ECDSA_PARAMS       0x00000180\n#define CKA_EC_PARAMS          0x00000180\n\n#define CKA_EC_POINT           0x00000181\n\n/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,\n * are new for v2.10. Deprecated in v2.11 and onwards. */\n#define CKA_SECONDARY_AUTH     0x00000200\n#define CKA_AUTH_PIN_FLAGS     0x00000201\n\n/* CKA_ALWAYS_AUTHENTICATE ...\n * CKA_UNWRAP_TEMPLATE are new for v2.20 */\n#define CKA_ALWAYS_AUTHENTICATE  0x00000202\n\n#define CKA_WRAP_WITH_TRUSTED    0x00000210\n#define CKA_WRAP_TEMPLATE        (CKF_ARRAY_ATTRIBUTE|0x00000211)\n#define CKA_UNWRAP_TEMPLATE      (CKF_ARRAY_ATTRIBUTE|0x00000212)\n\n/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */\n#define CKA_OTP_FORMAT                0x00000220\n#define CKA_OTP_LENGTH                0x00000221\n#define CKA_OTP_TIME_INTERVAL         0x00000222\n#define CKA_OTP_USER_FRIENDLY_MODE    0x00000223\n#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224\n#define CKA_OTP_TIME_REQUIREMENT      0x00000225\n#define CKA_OTP_COUNTER_REQUIREMENT   0x00000226\n#define CKA_OTP_PIN_REQUIREMENT       0x00000227\n#define CKA_OTP_COUNTER               0x0000022E\n#define CKA_OTP_TIME                  0x0000022F\n#define CKA_OTP_USER_IDENTIFIER       0x0000022A\n#define CKA_OTP_SERVICE_IDENTIFIER    0x0000022B\n#define CKA_OTP_SERVICE_LOGO          0x0000022C\n#define CKA_OTP_SERVICE_LOGO_TYPE     0x0000022D\n\n\n/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET\n * are new for v2.10 */\n#define CKA_HW_FEATURE_TYPE    0x00000300\n#define CKA_RESET_ON_INIT      0x00000301\n#define CKA_HAS_RESET          0x00000302\n\n/* The following attributes are new for v2.20 */\n#define CKA_PIXEL_X                     0x00000400\n#define CKA_PIXEL_Y                     0x00000401\n#define CKA_RESOLUTION                  0x00000402\n#define CKA_CHAR_ROWS                   0x00000403\n#define CKA_CHAR_COLUMNS                0x00000404\n#define CKA_COLOR                       0x00000405\n#define CKA_BITS_PER_PIXEL              0x00000406\n#define CKA_CHAR_SETS                   0x00000480\n#define CKA_ENCODING_METHODS            0x00000481\n#define CKA_MIME_TYPES                  0x00000482\n#define CKA_MECHANISM_TYPE              0x00000500\n#define CKA_REQUIRED_CMS_ATTRIBUTES     0x00000501\n#define CKA_DEFAULT_CMS_ATTRIBUTES      0x00000502\n#define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503\n#define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600)\n\n#define CKA_VENDOR_DEFINED     0x80000000\n\n/* CK_ATTRIBUTE is a structure that includes the type, length\n * and value of an attribute */\ntypedef struct CK_ATTRIBUTE {\n  CK_ATTRIBUTE_TYPE type;\n  CK_VOID_PTR       pValue;\n\n  /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */\n  CK_ULONG          ulValueLen;  /* in bytes */\n} CK_ATTRIBUTE;\n\ntypedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;\n\n\n/* CK_DATE is a structure that defines a date */\ntypedef struct CK_DATE{\n  CK_CHAR       year[4];   /* the year (\"1900\" - \"9999\") */\n  CK_CHAR       month[2];  /* the month (\"01\" - \"12\") */\n  CK_CHAR       day[2];    /* the day   (\"01\" - \"31\") */\n} CK_DATE;\n\n\n/* CK_MECHANISM_TYPE is a value that identifies a mechanism\n * type */\n/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for\n * v2.0 */\ntypedef CK_ULONG          CK_MECHANISM_TYPE;\n\n/* the following mechanism types are defined: */\n#define CKM_RSA_PKCS_KEY_PAIR_GEN      0x00000000\n#define CKM_RSA_PKCS                   0x00000001\n#define CKM_RSA_9796                   0x00000002\n#define CKM_RSA_X_509                  0x00000003\n\n/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS\n * are new for v2.0.  They are mechanisms which hash and sign */\n#define CKM_MD2_RSA_PKCS               0x00000004\n#define CKM_MD5_RSA_PKCS               0x00000005\n#define CKM_SHA1_RSA_PKCS              0x00000006\n\n/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and\n * CKM_RSA_PKCS_OAEP are new for v2.10 */\n#define CKM_RIPEMD128_RSA_PKCS         0x00000007\n#define CKM_RIPEMD160_RSA_PKCS         0x00000008\n#define CKM_RSA_PKCS_OAEP              0x00000009\n\n/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,\n * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */\n#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000A\n#define CKM_RSA_X9_31                  0x0000000B\n#define CKM_SHA1_RSA_X9_31             0x0000000C\n#define CKM_RSA_PKCS_PSS               0x0000000D\n#define CKM_SHA1_RSA_PKCS_PSS          0x0000000E\n\n#define CKM_DSA_KEY_PAIR_GEN           0x00000010\n#define CKM_DSA                        0x00000011\n#define CKM_DSA_SHA1                   0x00000012\n#define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020\n#define CKM_DH_PKCS_DERIVE             0x00000021\n\n/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,\n * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for\n * v2.11 */\n#define CKM_X9_42_DH_KEY_PAIR_GEN      0x00000030\n#define CKM_X9_42_DH_DERIVE            0x00000031\n#define CKM_X9_42_DH_HYBRID_DERIVE     0x00000032\n#define CKM_X9_42_MQV_DERIVE           0x00000033\n\n/* CKM_SHA256/384/512 are new for v2.20 */\n#define CKM_SHA256_RSA_PKCS            0x00000040\n#define CKM_SHA384_RSA_PKCS            0x00000041\n#define CKM_SHA512_RSA_PKCS            0x00000042\n#define CKM_SHA256_RSA_PKCS_PSS        0x00000043\n#define CKM_SHA384_RSA_PKCS_PSS        0x00000044\n#define CKM_SHA512_RSA_PKCS_PSS        0x00000045\n\n/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */\n#define CKM_SHA224_RSA_PKCS            0x00000046\n#define CKM_SHA224_RSA_PKCS_PSS        0x00000047\n\n#define CKM_RC2_KEY_GEN                0x00000100\n#define CKM_RC2_ECB                    0x00000101\n#define CKM_RC2_CBC                    0x00000102\n#define CKM_RC2_MAC                    0x00000103\n\n/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */\n#define CKM_RC2_MAC_GENERAL            0x00000104\n#define CKM_RC2_CBC_PAD                0x00000105\n\n#define CKM_RC4_KEY_GEN                0x00000110\n#define CKM_RC4                        0x00000111\n#define CKM_DES_KEY_GEN                0x00000120\n#define CKM_DES_ECB                    0x00000121\n#define CKM_DES_CBC                    0x00000122\n#define CKM_DES_MAC                    0x00000123\n\n/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */\n#define CKM_DES_MAC_GENERAL            0x00000124\n#define CKM_DES_CBC_PAD                0x00000125\n\n#define CKM_DES2_KEY_GEN               0x00000130\n#define CKM_DES3_KEY_GEN               0x00000131\n#define CKM_DES3_ECB                   0x00000132\n#define CKM_DES3_CBC                   0x00000133\n#define CKM_DES3_MAC                   0x00000134\n\n/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,\n * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,\n * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */\n#define CKM_DES3_MAC_GENERAL           0x00000135\n#define CKM_DES3_CBC_PAD               0x00000136\n#define CKM_CDMF_KEY_GEN               0x00000140\n#define CKM_CDMF_ECB                   0x00000141\n#define CKM_CDMF_CBC                   0x00000142\n#define CKM_CDMF_MAC                   0x00000143\n#define CKM_CDMF_MAC_GENERAL           0x00000144\n#define CKM_CDMF_CBC_PAD               0x00000145\n\n/* the following four DES mechanisms are new for v2.20 */\n#define CKM_DES_OFB64                  0x00000150\n#define CKM_DES_OFB8                   0x00000151\n#define CKM_DES_CFB64                  0x00000152\n#define CKM_DES_CFB8                   0x00000153\n\n#define CKM_MD2                        0x00000200\n\n/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */\n#define CKM_MD2_HMAC                   0x00000201\n#define CKM_MD2_HMAC_GENERAL           0x00000202\n\n#define CKM_MD5                        0x00000210\n\n/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */\n#define CKM_MD5_HMAC                   0x00000211\n#define CKM_MD5_HMAC_GENERAL           0x00000212\n\n#define CKM_SHA_1                      0x00000220\n\n/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */\n#define CKM_SHA_1_HMAC                 0x00000221\n#define CKM_SHA_1_HMAC_GENERAL         0x00000222\n\n/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,\n * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,\n * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */\n#define CKM_RIPEMD128                  0x00000230\n#define CKM_RIPEMD128_HMAC             0x00000231\n#define CKM_RIPEMD128_HMAC_GENERAL     0x00000232\n#define CKM_RIPEMD160                  0x00000240\n#define CKM_RIPEMD160_HMAC             0x00000241\n#define CKM_RIPEMD160_HMAC_GENERAL     0x00000242\n\n/* CKM_SHA256/384/512 are new for v2.20 */\n#define CKM_SHA256                     0x00000250\n#define CKM_SHA256_HMAC                0x00000251\n#define CKM_SHA256_HMAC_GENERAL        0x00000252\n\n/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */\n#define CKM_SHA224                     0x00000255\n#define CKM_SHA224_HMAC                0x00000256\n#define CKM_SHA224_HMAC_GENERAL        0x00000257\n\n#define CKM_SHA384                     0x00000260\n#define CKM_SHA384_HMAC                0x00000261\n#define CKM_SHA384_HMAC_GENERAL        0x00000262\n#define CKM_SHA512                     0x00000270\n#define CKM_SHA512_HMAC                0x00000271\n#define CKM_SHA512_HMAC_GENERAL        0x00000272\n\n/* SecurID is new for PKCS #11 v2.20 amendment 1 */\n#define CKM_SECURID_KEY_GEN            0x00000280\n#define CKM_SECURID                    0x00000282\n\n/* HOTP is new for PKCS #11 v2.20 amendment 1 */\n#define CKM_HOTP_KEY_GEN    0x00000290\n#define CKM_HOTP            0x00000291\n\n/* ACTI is new for PKCS #11 v2.20 amendment 1 */\n#define CKM_ACTI            0x000002A0\n#define CKM_ACTI_KEY_GEN    0x000002A1\n\n/* All of the following mechanisms are new for v2.0 */\n/* Note that CAST128 and CAST5 are the same algorithm */\n#define CKM_CAST_KEY_GEN               0x00000300\n#define CKM_CAST_ECB                   0x00000301\n#define CKM_CAST_CBC                   0x00000302\n#define CKM_CAST_MAC                   0x00000303\n#define CKM_CAST_MAC_GENERAL           0x00000304\n#define CKM_CAST_CBC_PAD               0x00000305\n#define CKM_CAST3_KEY_GEN              0x00000310\n#define CKM_CAST3_ECB                  0x00000311\n#define CKM_CAST3_CBC                  0x00000312\n#define CKM_CAST3_MAC                  0x00000313\n#define CKM_CAST3_MAC_GENERAL          0x00000314\n#define CKM_CAST3_CBC_PAD              0x00000315\n#define CKM_CAST5_KEY_GEN              0x00000320\n#define CKM_CAST128_KEY_GEN            0x00000320\n#define CKM_CAST5_ECB                  0x00000321\n#define CKM_CAST128_ECB                0x00000321\n#define CKM_CAST5_CBC                  0x00000322\n#define CKM_CAST128_CBC                0x00000322\n#define CKM_CAST5_MAC                  0x00000323\n#define CKM_CAST128_MAC                0x00000323\n#define CKM_CAST5_MAC_GENERAL          0x00000324\n#define CKM_CAST128_MAC_GENERAL        0x00000324\n#define CKM_CAST5_CBC_PAD              0x00000325\n#define CKM_CAST128_CBC_PAD            0x00000325\n#define CKM_RC5_KEY_GEN                0x00000330\n#define CKM_RC5_ECB                    0x00000331\n#define CKM_RC5_CBC                    0x00000332\n#define CKM_RC5_MAC                    0x00000333\n#define CKM_RC5_MAC_GENERAL            0x00000334\n#define CKM_RC5_CBC_PAD                0x00000335\n#define CKM_IDEA_KEY_GEN               0x00000340\n#define CKM_IDEA_ECB                   0x00000341\n#define CKM_IDEA_CBC                   0x00000342\n#define CKM_IDEA_MAC                   0x00000343\n#define CKM_IDEA_MAC_GENERAL           0x00000344\n#define CKM_IDEA_CBC_PAD               0x00000345\n#define CKM_GENERIC_SECRET_KEY_GEN     0x00000350\n#define CKM_CONCATENATE_BASE_AND_KEY   0x00000360\n#define CKM_CONCATENATE_BASE_AND_DATA  0x00000362\n#define CKM_CONCATENATE_DATA_AND_BASE  0x00000363\n#define CKM_XOR_BASE_AND_DATA          0x00000364\n#define CKM_EXTRACT_KEY_FROM_KEY       0x00000365\n#define CKM_SSL3_PRE_MASTER_KEY_GEN    0x00000370\n#define CKM_SSL3_MASTER_KEY_DERIVE     0x00000371\n#define CKM_SSL3_KEY_AND_MAC_DERIVE    0x00000372\n\n/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,\n * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and\n * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */\n#define CKM_SSL3_MASTER_KEY_DERIVE_DH  0x00000373\n#define CKM_TLS_PRE_MASTER_KEY_GEN     0x00000374\n#define CKM_TLS_MASTER_KEY_DERIVE      0x00000375\n#define CKM_TLS_KEY_AND_MAC_DERIVE     0x00000376\n#define CKM_TLS_MASTER_KEY_DERIVE_DH   0x00000377\n\n/* CKM_TLS_PRF is new for v2.20 */\n#define CKM_TLS_PRF                    0x00000378\n\n#define CKM_SSL3_MD5_MAC               0x00000380\n#define CKM_SSL3_SHA1_MAC              0x00000381\n#define CKM_MD5_KEY_DERIVATION         0x00000390\n#define CKM_MD2_KEY_DERIVATION         0x00000391\n#define CKM_SHA1_KEY_DERIVATION        0x00000392\n\n/* CKM_SHA256/384/512 are new for v2.20 */\n#define CKM_SHA256_KEY_DERIVATION      0x00000393\n#define CKM_SHA384_KEY_DERIVATION      0x00000394\n#define CKM_SHA512_KEY_DERIVATION      0x00000395\n\n/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */\n#define CKM_SHA224_KEY_DERIVATION      0x00000396\n\n#define CKM_PBE_MD2_DES_CBC            0x000003A0\n#define CKM_PBE_MD5_DES_CBC            0x000003A1\n#define CKM_PBE_MD5_CAST_CBC           0x000003A2\n#define CKM_PBE_MD5_CAST3_CBC          0x000003A3\n#define CKM_PBE_MD5_CAST5_CBC          0x000003A4\n#define CKM_PBE_MD5_CAST128_CBC        0x000003A4\n#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5\n#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5\n#define CKM_PBE_SHA1_RC4_128           0x000003A6\n#define CKM_PBE_SHA1_RC4_40            0x000003A7\n#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8\n#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9\n#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AA\n#define CKM_PBE_SHA1_RC2_40_CBC        0x000003AB\n\n/* CKM_PKCS5_PBKD2 is new for v2.10 */\n#define CKM_PKCS5_PBKD2                0x000003B0\n\n#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0\n\n/* WTLS mechanisms are new for v2.20 */\n#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0\n#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1\n#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2\n#define CKM_WTLS_PRF                        0x000003D3\n#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4\n#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5\n\n#define CKM_KEY_WRAP_LYNKS             0x00000400\n#define CKM_KEY_WRAP_SET_OAEP          0x00000401\n\n/* CKM_CMS_SIG is new for v2.20 */\n#define CKM_CMS_SIG                    0x00000500\n\n/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */\n#define CKM_KIP_DERIVE\t               0x00000510\n#define CKM_KIP_WRAP\t               0x00000511\n#define CKM_KIP_MAC\t               0x00000512\n\n/* Camellia is new for PKCS #11 v2.20 amendment 3 */\n#define CKM_CAMELLIA_KEY_GEN           0x00000550\n#define CKM_CAMELLIA_ECB               0x00000551\n#define CKM_CAMELLIA_CBC               0x00000552\n#define CKM_CAMELLIA_MAC               0x00000553\n#define CKM_CAMELLIA_MAC_GENERAL       0x00000554\n#define CKM_CAMELLIA_CBC_PAD           0x00000555\n#define CKM_CAMELLIA_ECB_ENCRYPT_DATA  0x00000556\n#define CKM_CAMELLIA_CBC_ENCRYPT_DATA  0x00000557\n#define CKM_CAMELLIA_CTR               0x00000558\n\n/* ARIA is new for PKCS #11 v2.20 amendment 3 */\n#define CKM_ARIA_KEY_GEN               0x00000560\n#define CKM_ARIA_ECB                   0x00000561\n#define CKM_ARIA_CBC                   0x00000562\n#define CKM_ARIA_MAC                   0x00000563\n#define CKM_ARIA_MAC_GENERAL           0x00000564\n#define CKM_ARIA_CBC_PAD               0x00000565\n#define CKM_ARIA_ECB_ENCRYPT_DATA      0x00000566\n#define CKM_ARIA_CBC_ENCRYPT_DATA      0x00000567\n\n/* Fortezza mechanisms */\n#define CKM_SKIPJACK_KEY_GEN           0x00001000\n#define CKM_SKIPJACK_ECB64             0x00001001\n#define CKM_SKIPJACK_CBC64             0x00001002\n#define CKM_SKIPJACK_OFB64             0x00001003\n#define CKM_SKIPJACK_CFB64             0x00001004\n#define CKM_SKIPJACK_CFB32             0x00001005\n#define CKM_SKIPJACK_CFB16             0x00001006\n#define CKM_SKIPJACK_CFB8              0x00001007\n#define CKM_SKIPJACK_WRAP              0x00001008\n#define CKM_SKIPJACK_PRIVATE_WRAP      0x00001009\n#define CKM_SKIPJACK_RELAYX            0x0000100a\n#define CKM_KEA_KEY_PAIR_GEN           0x00001010\n#define CKM_KEA_KEY_DERIVE             0x00001011\n#define CKM_FORTEZZA_TIMESTAMP         0x00001020\n#define CKM_BATON_KEY_GEN              0x00001030\n#define CKM_BATON_ECB128               0x00001031\n#define CKM_BATON_ECB96                0x00001032\n#define CKM_BATON_CBC128               0x00001033\n#define CKM_BATON_COUNTER              0x00001034\n#define CKM_BATON_SHUFFLE              0x00001035\n#define CKM_BATON_WRAP                 0x00001036\n\n/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,\n * CKM_EC_KEY_PAIR_GEN is preferred */\n#define CKM_ECDSA_KEY_PAIR_GEN         0x00001040\n#define CKM_EC_KEY_PAIR_GEN            0x00001040\n\n#define CKM_ECDSA                      0x00001041\n#define CKM_ECDSA_SHA1                 0x00001042\n\n/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE\n * are new for v2.11 */\n#define CKM_ECDH1_DERIVE               0x00001050\n#define CKM_ECDH1_COFACTOR_DERIVE      0x00001051\n#define CKM_ECMQV_DERIVE               0x00001052\n\n#define CKM_JUNIPER_KEY_GEN            0x00001060\n#define CKM_JUNIPER_ECB128             0x00001061\n#define CKM_JUNIPER_CBC128             0x00001062\n#define CKM_JUNIPER_COUNTER            0x00001063\n#define CKM_JUNIPER_SHUFFLE            0x00001064\n#define CKM_JUNIPER_WRAP               0x00001065\n#define CKM_FASTHASH                   0x00001070\n\n/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,\n * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,\n * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are\n * new for v2.11 */\n#define CKM_AES_KEY_GEN                0x00001080\n#define CKM_AES_ECB                    0x00001081\n#define CKM_AES_CBC                    0x00001082\n#define CKM_AES_MAC                    0x00001083\n#define CKM_AES_MAC_GENERAL            0x00001084\n#define CKM_AES_CBC_PAD                0x00001085\n\n/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */\n#define CKM_AES_CTR                    0x00001086\n\n/* BlowFish and TwoFish are new for v2.20 */\n#define CKM_BLOWFISH_KEY_GEN           0x00001090\n#define CKM_BLOWFISH_CBC               0x00001091\n#define CKM_TWOFISH_KEY_GEN            0x00001092\n#define CKM_TWOFISH_CBC                0x00001093\n\n\n/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */\n#define CKM_DES_ECB_ENCRYPT_DATA       0x00001100\n#define CKM_DES_CBC_ENCRYPT_DATA       0x00001101\n#define CKM_DES3_ECB_ENCRYPT_DATA      0x00001102\n#define CKM_DES3_CBC_ENCRYPT_DATA      0x00001103\n#define CKM_AES_ECB_ENCRYPT_DATA       0x00001104\n#define CKM_AES_CBC_ENCRYPT_DATA       0x00001105\n\n#define CKM_DSA_PARAMETER_GEN          0x00002000\n#define CKM_DH_PKCS_PARAMETER_GEN      0x00002001\n#define CKM_X9_42_DH_PARAMETER_GEN     0x00002002\n\n#define CKM_VENDOR_DEFINED             0x80000000\n\ntypedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;\n\n\n/* CK_MECHANISM is a structure that specifies a particular\n * mechanism  */\ntypedef struct CK_MECHANISM {\n  CK_MECHANISM_TYPE mechanism;\n  CK_VOID_PTR       pParameter;\n\n  /* ulParameterLen was changed from CK_USHORT to CK_ULONG for\n   * v2.0 */\n  CK_ULONG          ulParameterLen;  /* in bytes */\n} CK_MECHANISM;\n\ntypedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;\n\n\n/* CK_MECHANISM_INFO provides information about a particular\n * mechanism */\ntypedef struct CK_MECHANISM_INFO {\n    CK_ULONG    ulMinKeySize;\n    CK_ULONG    ulMaxKeySize;\n    CK_FLAGS    flags;\n} CK_MECHANISM_INFO;\n\n/* The flags are defined as follows:\n *      Bit Flag               Mask        Meaning */\n#define CKF_HW                 0x00000001  /* performed by HW */\n\n/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,\n * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,\n * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,\n * and CKF_DERIVE are new for v2.0.  They specify whether or not\n * a mechanism can be used for a particular task */\n#define CKF_ENCRYPT            0x00000100\n#define CKF_DECRYPT            0x00000200\n#define CKF_DIGEST             0x00000400\n#define CKF_SIGN               0x00000800\n#define CKF_SIGN_RECOVER       0x00001000\n#define CKF_VERIFY             0x00002000\n#define CKF_VERIFY_RECOVER     0x00004000\n#define CKF_GENERATE           0x00008000\n#define CKF_GENERATE_KEY_PAIR  0x00010000\n#define CKF_WRAP               0x00020000\n#define CKF_UNWRAP             0x00040000\n#define CKF_DERIVE             0x00080000\n\n/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,\n * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They\n * describe a token's EC capabilities not available in mechanism\n * information. */\n#define CKF_EC_F_P             0x00100000\n#define CKF_EC_F_2M            0x00200000\n#define CKF_EC_ECPARAMETERS    0x00400000\n#define CKF_EC_NAMEDCURVE      0x00800000\n#define CKF_EC_UNCOMPRESS      0x01000000\n#define CKF_EC_COMPRESS        0x02000000\n\n#define CKF_EXTENSION          0x80000000 /* FALSE for this version */\n\ntypedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;\n\n\n/* CK_RV is a value that identifies the return value of a\n * Cryptoki function */\n/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */\ntypedef CK_ULONG          CK_RV;\n\n#define CKR_OK                                0x00000000\n#define CKR_CANCEL                            0x00000001\n#define CKR_HOST_MEMORY                       0x00000002\n#define CKR_SLOT_ID_INVALID                   0x00000003\n\n/* CKR_FLAGS_INVALID was removed for v2.0 */\n\n/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */\n#define CKR_GENERAL_ERROR                     0x00000005\n#define CKR_FUNCTION_FAILED                   0x00000006\n\n/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,\n * and CKR_CANT_LOCK are new for v2.01 */\n#define CKR_ARGUMENTS_BAD                     0x00000007\n#define CKR_NO_EVENT                          0x00000008\n#define CKR_NEED_TO_CREATE_THREADS            0x00000009\n#define CKR_CANT_LOCK                         0x0000000A\n\n#define CKR_ATTRIBUTE_READ_ONLY               0x00000010\n#define CKR_ATTRIBUTE_SENSITIVE               0x00000011\n#define CKR_ATTRIBUTE_TYPE_INVALID            0x00000012\n#define CKR_ATTRIBUTE_VALUE_INVALID           0x00000013\n#define CKR_DATA_INVALID                      0x00000020\n#define CKR_DATA_LEN_RANGE                    0x00000021\n#define CKR_DEVICE_ERROR                      0x00000030\n#define CKR_DEVICE_MEMORY                     0x00000031\n#define CKR_DEVICE_REMOVED                    0x00000032\n#define CKR_ENCRYPTED_DATA_INVALID            0x00000040\n#define CKR_ENCRYPTED_DATA_LEN_RANGE          0x00000041\n#define CKR_FUNCTION_CANCELED                 0x00000050\n#define CKR_FUNCTION_NOT_PARALLEL             0x00000051\n\n/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */\n#define CKR_FUNCTION_NOT_SUPPORTED            0x00000054\n\n#define CKR_KEY_HANDLE_INVALID                0x00000060\n\n/* CKR_KEY_SENSITIVE was removed for v2.0 */\n\n#define CKR_KEY_SIZE_RANGE                    0x00000062\n#define CKR_KEY_TYPE_INCONSISTENT             0x00000063\n\n/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,\n * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,\n * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for\n * v2.0 */\n#define CKR_KEY_NOT_NEEDED                    0x00000064\n#define CKR_KEY_CHANGED                       0x00000065\n#define CKR_KEY_NEEDED                        0x00000066\n#define CKR_KEY_INDIGESTIBLE                  0x00000067\n#define CKR_KEY_FUNCTION_NOT_PERMITTED        0x00000068\n#define CKR_KEY_NOT_WRAPPABLE                 0x00000069\n#define CKR_KEY_UNEXTRACTABLE                 0x0000006A\n\n#define CKR_MECHANISM_INVALID                 0x00000070\n#define CKR_MECHANISM_PARAM_INVALID           0x00000071\n\n/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID\n * were removed for v2.0 */\n#define CKR_OBJECT_HANDLE_INVALID             0x00000082\n#define CKR_OPERATION_ACTIVE                  0x00000090\n#define CKR_OPERATION_NOT_INITIALIZED         0x00000091\n#define CKR_PIN_INCORRECT                     0x000000A0\n#define CKR_PIN_INVALID                       0x000000A1\n#define CKR_PIN_LEN_RANGE                     0x000000A2\n\n/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */\n#define CKR_PIN_EXPIRED                       0x000000A3\n#define CKR_PIN_LOCKED                        0x000000A4\n\n#define CKR_SESSION_CLOSED                    0x000000B0\n#define CKR_SESSION_COUNT                     0x000000B1\n#define CKR_SESSION_HANDLE_INVALID            0x000000B3\n#define CKR_SESSION_PARALLEL_NOT_SUPPORTED    0x000000B4\n#define CKR_SESSION_READ_ONLY                 0x000000B5\n#define CKR_SESSION_EXISTS                    0x000000B6\n\n/* CKR_SESSION_READ_ONLY_EXISTS and\n * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */\n#define CKR_SESSION_READ_ONLY_EXISTS          0x000000B7\n#define CKR_SESSION_READ_WRITE_SO_EXISTS      0x000000B8\n\n#define CKR_SIGNATURE_INVALID                 0x000000C0\n#define CKR_SIGNATURE_LEN_RANGE               0x000000C1\n#define CKR_TEMPLATE_INCOMPLETE               0x000000D0\n#define CKR_TEMPLATE_INCONSISTENT             0x000000D1\n#define CKR_TOKEN_NOT_PRESENT                 0x000000E0\n#define CKR_TOKEN_NOT_RECOGNIZED              0x000000E1\n#define CKR_TOKEN_WRITE_PROTECTED             0x000000E2\n#define CKR_UNWRAPPING_KEY_HANDLE_INVALID     0x000000F0\n#define CKR_UNWRAPPING_KEY_SIZE_RANGE         0x000000F1\n#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT  0x000000F2\n#define CKR_USER_ALREADY_LOGGED_IN            0x00000100\n#define CKR_USER_NOT_LOGGED_IN                0x00000101\n#define CKR_USER_PIN_NOT_INITIALIZED          0x00000102\n#define CKR_USER_TYPE_INVALID                 0x00000103\n\n/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES\n * are new to v2.01 */\n#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN    0x00000104\n#define CKR_USER_TOO_MANY_TYPES               0x00000105\n\n#define CKR_WRAPPED_KEY_INVALID               0x00000110\n#define CKR_WRAPPED_KEY_LEN_RANGE             0x00000112\n#define CKR_WRAPPING_KEY_HANDLE_INVALID       0x00000113\n#define CKR_WRAPPING_KEY_SIZE_RANGE           0x00000114\n#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT    0x00000115\n#define CKR_RANDOM_SEED_NOT_SUPPORTED         0x00000120\n\n/* These are new to v2.0 */\n#define CKR_RANDOM_NO_RNG                     0x00000121\n\n/* These are new to v2.11 */\n#define CKR_DOMAIN_PARAMS_INVALID             0x00000130\n\n/* These are new to v2.0 */\n#define CKR_BUFFER_TOO_SMALL                  0x00000150\n#define CKR_SAVED_STATE_INVALID               0x00000160\n#define CKR_INFORMATION_SENSITIVE             0x00000170\n#define CKR_STATE_UNSAVEABLE                  0x00000180\n\n/* These are new to v2.01 */\n#define CKR_CRYPTOKI_NOT_INITIALIZED          0x00000190\n#define CKR_CRYPTOKI_ALREADY_INITIALIZED      0x00000191\n#define CKR_MUTEX_BAD                         0x000001A0\n#define CKR_MUTEX_NOT_LOCKED                  0x000001A1\n\n/* The following return values are new for PKCS #11 v2.20 amendment 3 */\n#define CKR_NEW_PIN_MODE                      0x000001B0\n#define CKR_NEXT_OTP                          0x000001B1\n\n/* This is new to v2.20 */\n#define CKR_FUNCTION_REJECTED                 0x00000200\n\n#define CKR_VENDOR_DEFINED                    0x80000000\n\n\n/* CK_NOTIFY is an application callback that processes events */\ntypedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(\n  CK_SESSION_HANDLE hSession,     /* the session's handle */\n  CK_NOTIFICATION   event,\n  CK_VOID_PTR       pApplication  /* passed to C_OpenSession */\n);\n\n\n/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec\n * version and pointers of appropriate types to all the\n * Cryptoki functions */\n/* CK_FUNCTION_LIST is new for v2.0 */\ntypedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;\n\ntypedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;\n\ntypedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;\n\n\n/* CK_CREATEMUTEX is an application callback for creating a\n * mutex object */\ntypedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(\n  CK_VOID_PTR_PTR ppMutex  /* location to receive ptr to mutex */\n);\n\n\n/* CK_DESTROYMUTEX is an application callback for destroying a\n * mutex object */\ntypedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(\n  CK_VOID_PTR pMutex  /* pointer to mutex */\n);\n\n\n/* CK_LOCKMUTEX is an application callback for locking a mutex */\ntypedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(\n  CK_VOID_PTR pMutex  /* pointer to mutex */\n);\n\n\n/* CK_UNLOCKMUTEX is an application callback for unlocking a\n * mutex */\ntypedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(\n  CK_VOID_PTR pMutex  /* pointer to mutex */\n);\n\n\n/* CK_C_INITIALIZE_ARGS provides the optional arguments to\n * C_Initialize */\ntypedef struct CK_C_INITIALIZE_ARGS {\n  CK_CREATEMUTEX CreateMutex;\n  CK_DESTROYMUTEX DestroyMutex;\n  CK_LOCKMUTEX LockMutex;\n  CK_UNLOCKMUTEX UnlockMutex;\n  CK_FLAGS flags;\n  CK_VOID_PTR pReserved;\n} CK_C_INITIALIZE_ARGS;\n\n/* flags: bit flags that provide capabilities of the slot\n *      Bit Flag                           Mask       Meaning\n */\n#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001\n#define CKF_OS_LOCKING_OK                  0x00000002\n\ntypedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;\n\n\n/* additional flags for parameters to functions */\n\n/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */\n#define CKF_DONT_BLOCK     1\n\n/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.\n * CK_RSA_PKCS_OAEP_MGF_TYPE  is used to indicate the Message\n * Generation Function (MGF) applied to a message block when\n * formatting a message block for the PKCS #1 OAEP encryption\n * scheme. */\ntypedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;\n\ntypedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;\n\n/* The following MGFs are defined */\n/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512\n * are new for v2.20 */\n#define CKG_MGF1_SHA1         0x00000001\n#define CKG_MGF1_SHA256       0x00000002\n#define CKG_MGF1_SHA384       0x00000003\n#define CKG_MGF1_SHA512       0x00000004\n/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */\n#define CKG_MGF1_SHA224       0x00000005\n\n/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.\n * CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source\n * of the encoding parameter when formatting a message block\n * for the PKCS #1 OAEP encryption scheme. */\ntypedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;\n\ntypedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;\n\n/* The following encoding parameter sources are defined */\n#define CKZ_DATA_SPECIFIED    0x00000001\n\n/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.\n * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the\n * CKM_RSA_PKCS_OAEP mechanism. */\ntypedef struct CK_RSA_PKCS_OAEP_PARAMS {\n        CK_MECHANISM_TYPE hashAlg;\n        CK_RSA_PKCS_MGF_TYPE mgf;\n        CK_RSA_PKCS_OAEP_SOURCE_TYPE source;\n        CK_VOID_PTR pSourceData;\n        CK_ULONG ulSourceDataLen;\n} CK_RSA_PKCS_OAEP_PARAMS;\n\ntypedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;\n\n/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.\n * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the\n * CKM_RSA_PKCS_PSS mechanism(s). */\ntypedef struct CK_RSA_PKCS_PSS_PARAMS {\n        CK_MECHANISM_TYPE    hashAlg;\n        CK_RSA_PKCS_MGF_TYPE mgf;\n        CK_ULONG             sLen;\n} CK_RSA_PKCS_PSS_PARAMS;\n\ntypedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;\n\n/* CK_EC_KDF_TYPE is new for v2.11. */\ntypedef CK_ULONG CK_EC_KDF_TYPE;\n\n/* The following EC Key Derivation Functions are defined */\n#define CKD_NULL                 0x00000001\n#define CKD_SHA1_KDF             0x00000002\n\n/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.\n * CK_ECDH1_DERIVE_PARAMS provides the parameters to the\n * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,\n * where each party contributes one key pair.\n */\ntypedef struct CK_ECDH1_DERIVE_PARAMS {\n  CK_EC_KDF_TYPE kdf;\n  CK_ULONG ulSharedDataLen;\n  CK_BYTE_PTR pSharedData;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n} CK_ECDH1_DERIVE_PARAMS;\n\ntypedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;\n\n\n/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.\n * CK_ECDH2_DERIVE_PARAMS provides the parameters to the\n * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */\ntypedef struct CK_ECDH2_DERIVE_PARAMS {\n  CK_EC_KDF_TYPE kdf;\n  CK_ULONG ulSharedDataLen;\n  CK_BYTE_PTR pSharedData;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n  CK_ULONG ulPrivateDataLen;\n  CK_OBJECT_HANDLE hPrivateData;\n  CK_ULONG ulPublicDataLen2;\n  CK_BYTE_PTR pPublicData2;\n} CK_ECDH2_DERIVE_PARAMS;\n\ntypedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;\n\ntypedef struct CK_ECMQV_DERIVE_PARAMS {\n  CK_EC_KDF_TYPE kdf;\n  CK_ULONG ulSharedDataLen;\n  CK_BYTE_PTR pSharedData;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n  CK_ULONG ulPrivateDataLen;\n  CK_OBJECT_HANDLE hPrivateData;\n  CK_ULONG ulPublicDataLen2;\n  CK_BYTE_PTR pPublicData2;\n  CK_OBJECT_HANDLE publicKey;\n} CK_ECMQV_DERIVE_PARAMS;\n\ntypedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;\n\n/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the\n * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */\ntypedef CK_ULONG CK_X9_42_DH_KDF_TYPE;\ntypedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;\n\n/* The following X9.42 DH key derivation functions are defined\n   (besides CKD_NULL already defined : */\n#define CKD_SHA1_KDF_ASN1        0x00000003\n#define CKD_SHA1_KDF_CONCATENATE 0x00000004\n\n/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.\n * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the\n * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party\n * contributes one key pair */\ntypedef struct CK_X9_42_DH1_DERIVE_PARAMS {\n  CK_X9_42_DH_KDF_TYPE kdf;\n  CK_ULONG ulOtherInfoLen;\n  CK_BYTE_PTR pOtherInfo;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n} CK_X9_42_DH1_DERIVE_PARAMS;\n\ntypedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;\n\n/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.\n * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the\n * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation\n * mechanisms, where each party contributes two key pairs */\ntypedef struct CK_X9_42_DH2_DERIVE_PARAMS {\n  CK_X9_42_DH_KDF_TYPE kdf;\n  CK_ULONG ulOtherInfoLen;\n  CK_BYTE_PTR pOtherInfo;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n  CK_ULONG ulPrivateDataLen;\n  CK_OBJECT_HANDLE hPrivateData;\n  CK_ULONG ulPublicDataLen2;\n  CK_BYTE_PTR pPublicData2;\n} CK_X9_42_DH2_DERIVE_PARAMS;\n\ntypedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;\n\ntypedef struct CK_X9_42_MQV_DERIVE_PARAMS {\n  CK_X9_42_DH_KDF_TYPE kdf;\n  CK_ULONG ulOtherInfoLen;\n  CK_BYTE_PTR pOtherInfo;\n  CK_ULONG ulPublicDataLen;\n  CK_BYTE_PTR pPublicData;\n  CK_ULONG ulPrivateDataLen;\n  CK_OBJECT_HANDLE hPrivateData;\n  CK_ULONG ulPublicDataLen2;\n  CK_BYTE_PTR pPublicData2;\n  CK_OBJECT_HANDLE publicKey;\n} CK_X9_42_MQV_DERIVE_PARAMS;\n\ntypedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;\n\n/* CK_KEA_DERIVE_PARAMS provides the parameters to the\n * CKM_KEA_DERIVE mechanism */\n/* CK_KEA_DERIVE_PARAMS is new for v2.0 */\ntypedef struct CK_KEA_DERIVE_PARAMS {\n  CK_BBOOL      isSender;\n  CK_ULONG      ulRandomLen;\n  CK_BYTE_PTR   pRandomA;\n  CK_BYTE_PTR   pRandomB;\n  CK_ULONG      ulPublicDataLen;\n  CK_BYTE_PTR   pPublicData;\n} CK_KEA_DERIVE_PARAMS;\n\ntypedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;\n\n\n/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and\n * CKM_RC2_MAC mechanisms.  An instance of CK_RC2_PARAMS just\n * holds the effective keysize */\ntypedef CK_ULONG          CK_RC2_PARAMS;\n\ntypedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;\n\n\n/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC\n * mechanism */\ntypedef struct CK_RC2_CBC_PARAMS {\n  /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for\n   * v2.0 */\n  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */\n\n  CK_BYTE       iv[8];            /* IV for CBC mode */\n} CK_RC2_CBC_PARAMS;\n\ntypedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;\n\n\n/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the\n * CKM_RC2_MAC_GENERAL mechanism */\n/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */\ntypedef struct CK_RC2_MAC_GENERAL_PARAMS {\n  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */\n  CK_ULONG      ulMacLength;      /* Length of MAC in bytes */\n} CK_RC2_MAC_GENERAL_PARAMS;\n\ntypedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \\\n  CK_RC2_MAC_GENERAL_PARAMS_PTR;\n\n\n/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and\n * CKM_RC5_MAC mechanisms */\n/* CK_RC5_PARAMS is new for v2.0 */\ntypedef struct CK_RC5_PARAMS {\n  CK_ULONG      ulWordsize;  /* wordsize in bits */\n  CK_ULONG      ulRounds;    /* number of rounds */\n} CK_RC5_PARAMS;\n\ntypedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;\n\n\n/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC\n * mechanism */\n/* CK_RC5_CBC_PARAMS is new for v2.0 */\ntypedef struct CK_RC5_CBC_PARAMS {\n  CK_ULONG      ulWordsize;  /* wordsize in bits */\n  CK_ULONG      ulRounds;    /* number of rounds */\n  CK_BYTE_PTR   pIv;         /* pointer to IV */\n  CK_ULONG      ulIvLen;     /* length of IV in bytes */\n} CK_RC5_CBC_PARAMS;\n\ntypedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;\n\n\n/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the\n * CKM_RC5_MAC_GENERAL mechanism */\n/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */\ntypedef struct CK_RC5_MAC_GENERAL_PARAMS {\n  CK_ULONG      ulWordsize;   /* wordsize in bits */\n  CK_ULONG      ulRounds;     /* number of rounds */\n  CK_ULONG      ulMacLength;  /* Length of MAC in bytes */\n} CK_RC5_MAC_GENERAL_PARAMS;\n\ntypedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \\\n  CK_RC5_MAC_GENERAL_PARAMS_PTR;\n\n\n/* CK_MAC_GENERAL_PARAMS provides the parameters to most block\n * ciphers' MAC_GENERAL mechanisms.  Its value is the length of\n * the MAC */\n/* CK_MAC_GENERAL_PARAMS is new for v2.0 */\ntypedef CK_ULONG          CK_MAC_GENERAL_PARAMS;\n\ntypedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;\n\n/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */\ntypedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {\n  CK_BYTE      iv[8];\n  CK_BYTE_PTR  pData;\n  CK_ULONG     length;\n} CK_DES_CBC_ENCRYPT_DATA_PARAMS;\n\ntypedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;\n\ntypedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {\n  CK_BYTE      iv[16];\n  CK_BYTE_PTR  pData;\n  CK_ULONG     length;\n} CK_AES_CBC_ENCRYPT_DATA_PARAMS;\n\ntypedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;\n\n/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the\n * CKM_SKIPJACK_PRIVATE_WRAP mechanism */\n/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */\ntypedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {\n  CK_ULONG      ulPasswordLen;\n  CK_BYTE_PTR   pPassword;\n  CK_ULONG      ulPublicDataLen;\n  CK_BYTE_PTR   pPublicData;\n  CK_ULONG      ulPAndGLen;\n  CK_ULONG      ulQLen;\n  CK_ULONG      ulRandomLen;\n  CK_BYTE_PTR   pRandomA;\n  CK_BYTE_PTR   pPrimeP;\n  CK_BYTE_PTR   pBaseG;\n  CK_BYTE_PTR   pSubprimeQ;\n} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;\n\ntypedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \\\n  CK_SKIPJACK_PRIVATE_WRAP_PTR;\n\n\n/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the\n * CKM_SKIPJACK_RELAYX mechanism */\n/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */\ntypedef struct CK_SKIPJACK_RELAYX_PARAMS {\n  CK_ULONG      ulOldWrappedXLen;\n  CK_BYTE_PTR   pOldWrappedX;\n  CK_ULONG      ulOldPasswordLen;\n  CK_BYTE_PTR   pOldPassword;\n  CK_ULONG      ulOldPublicDataLen;\n  CK_BYTE_PTR   pOldPublicData;\n  CK_ULONG      ulOldRandomLen;\n  CK_BYTE_PTR   pOldRandomA;\n  CK_ULONG      ulNewPasswordLen;\n  CK_BYTE_PTR   pNewPassword;\n  CK_ULONG      ulNewPublicDataLen;\n  CK_BYTE_PTR   pNewPublicData;\n  CK_ULONG      ulNewRandomLen;\n  CK_BYTE_PTR   pNewRandomA;\n} CK_SKIPJACK_RELAYX_PARAMS;\n\ntypedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \\\n  CK_SKIPJACK_RELAYX_PARAMS_PTR;\n\n\ntypedef struct CK_PBE_PARAMS {\n  CK_BYTE_PTR      pInitVector;\n  CK_UTF8CHAR_PTR  pPassword;\n  CK_ULONG         ulPasswordLen;\n  CK_BYTE_PTR      pSalt;\n  CK_ULONG         ulSaltLen;\n  CK_ULONG         ulIteration;\n} CK_PBE_PARAMS;\n\ntypedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;\n\n\n/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the\n * CKM_KEY_WRAP_SET_OAEP mechanism */\n/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */\ntypedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {\n  CK_BYTE       bBC;     /* block contents byte */\n  CK_BYTE_PTR   pX;      /* extra data */\n  CK_ULONG      ulXLen;  /* length of extra data in bytes */\n} CK_KEY_WRAP_SET_OAEP_PARAMS;\n\ntypedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \\\n  CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;\n\n\ntypedef struct CK_SSL3_RANDOM_DATA {\n  CK_BYTE_PTR  pClientRandom;\n  CK_ULONG     ulClientRandomLen;\n  CK_BYTE_PTR  pServerRandom;\n  CK_ULONG     ulServerRandomLen;\n} CK_SSL3_RANDOM_DATA;\n\n\ntypedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {\n  CK_SSL3_RANDOM_DATA RandomInfo;\n  CK_VERSION_PTR pVersion;\n} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;\n\ntypedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \\\n  CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;\n\n\ntypedef struct CK_SSL3_KEY_MAT_OUT {\n  CK_OBJECT_HANDLE hClientMacSecret;\n  CK_OBJECT_HANDLE hServerMacSecret;\n  CK_OBJECT_HANDLE hClientKey;\n  CK_OBJECT_HANDLE hServerKey;\n  CK_BYTE_PTR      pIVClient;\n  CK_BYTE_PTR      pIVServer;\n} CK_SSL3_KEY_MAT_OUT;\n\ntypedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;\n\n\ntypedef struct CK_SSL3_KEY_MAT_PARAMS {\n  CK_ULONG                ulMacSizeInBits;\n  CK_ULONG                ulKeySizeInBits;\n  CK_ULONG                ulIVSizeInBits;\n  CK_BBOOL                bIsExport;\n  CK_SSL3_RANDOM_DATA     RandomInfo;\n  CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;\n} CK_SSL3_KEY_MAT_PARAMS;\n\ntypedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;\n\n/* CK_TLS_PRF_PARAMS is new for version 2.20 */\ntypedef struct CK_TLS_PRF_PARAMS {\n  CK_BYTE_PTR  pSeed;\n  CK_ULONG     ulSeedLen;\n  CK_BYTE_PTR  pLabel;\n  CK_ULONG     ulLabelLen;\n  CK_BYTE_PTR  pOutput;\n  CK_ULONG_PTR pulOutputLen;\n} CK_TLS_PRF_PARAMS;\n\ntypedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;\n\n/* WTLS is new for version 2.20 */\ntypedef struct CK_WTLS_RANDOM_DATA {\n  CK_BYTE_PTR pClientRandom;\n  CK_ULONG    ulClientRandomLen;\n  CK_BYTE_PTR pServerRandom;\n  CK_ULONG    ulServerRandomLen;\n} CK_WTLS_RANDOM_DATA;\n\ntypedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;\n\ntypedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {\n  CK_MECHANISM_TYPE   DigestMechanism;\n  CK_WTLS_RANDOM_DATA RandomInfo;\n  CK_BYTE_PTR         pVersion;\n} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;\n\ntypedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \\\n  CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;\n\ntypedef struct CK_WTLS_PRF_PARAMS {\n  CK_MECHANISM_TYPE DigestMechanism;\n  CK_BYTE_PTR       pSeed;\n  CK_ULONG          ulSeedLen;\n  CK_BYTE_PTR       pLabel;\n  CK_ULONG          ulLabelLen;\n  CK_BYTE_PTR       pOutput;\n  CK_ULONG_PTR      pulOutputLen;\n} CK_WTLS_PRF_PARAMS;\n\ntypedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;\n\ntypedef struct CK_WTLS_KEY_MAT_OUT {\n  CK_OBJECT_HANDLE hMacSecret;\n  CK_OBJECT_HANDLE hKey;\n  CK_BYTE_PTR      pIV;\n} CK_WTLS_KEY_MAT_OUT;\n\ntypedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;\n\ntypedef struct CK_WTLS_KEY_MAT_PARAMS {\n  CK_MECHANISM_TYPE       DigestMechanism;\n  CK_ULONG                ulMacSizeInBits;\n  CK_ULONG                ulKeySizeInBits;\n  CK_ULONG                ulIVSizeInBits;\n  CK_ULONG                ulSequenceNumber;\n  CK_BBOOL                bIsExport;\n  CK_WTLS_RANDOM_DATA     RandomInfo;\n  CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;\n} CK_WTLS_KEY_MAT_PARAMS;\n\ntypedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;\n\n/* CMS is new for version 2.20 */\ntypedef struct CK_CMS_SIG_PARAMS {\n  CK_OBJECT_HANDLE      certificateHandle;\n  CK_MECHANISM_PTR      pSigningMechanism;\n  CK_MECHANISM_PTR      pDigestMechanism;\n  CK_UTF8CHAR_PTR       pContentType;\n  CK_BYTE_PTR           pRequestedAttributes;\n  CK_ULONG              ulRequestedAttributesLen;\n  CK_BYTE_PTR           pRequiredAttributes;\n  CK_ULONG              ulRequiredAttributesLen;\n} CK_CMS_SIG_PARAMS;\n\ntypedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;\n\ntypedef struct CK_KEY_DERIVATION_STRING_DATA {\n  CK_BYTE_PTR pData;\n  CK_ULONG    ulLen;\n} CK_KEY_DERIVATION_STRING_DATA;\n\ntypedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \\\n  CK_KEY_DERIVATION_STRING_DATA_PTR;\n\n\n/* The CK_EXTRACT_PARAMS is used for the\n * CKM_EXTRACT_KEY_FROM_KEY mechanism.  It specifies which bit\n * of the base key should be used as the first bit of the\n * derived key */\n/* CK_EXTRACT_PARAMS is new for v2.0 */\ntypedef CK_ULONG CK_EXTRACT_PARAMS;\n\ntypedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;\n\n/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.\n * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to\n * indicate the Pseudo-Random Function (PRF) used to generate\n * key bits using PKCS #5 PBKDF2. */\ntypedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;\n\ntypedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;\n\n/* The following PRFs are defined in PKCS #5 v2.0. */\n#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001\n\n\n/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.\n * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the\n * source of the salt value when deriving a key using PKCS #5\n * PBKDF2. */\ntypedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;\n\ntypedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;\n\n/* The following salt value sources are defined in PKCS #5 v2.0. */\n#define CKZ_SALT_SPECIFIED        0x00000001\n\n/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.\n * CK_PKCS5_PBKD2_PARAMS is a structure that provides the\n * parameters to the CKM_PKCS5_PBKD2 mechanism. */\ntypedef struct CK_PKCS5_PBKD2_PARAMS {\n        CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE           saltSource;\n        CK_VOID_PTR                                pSaltSourceData;\n        CK_ULONG                                   ulSaltSourceDataLen;\n        CK_ULONG                                   iterations;\n        CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;\n        CK_VOID_PTR                                pPrfData;\n        CK_ULONG                                   ulPrfDataLen;\n        CK_UTF8CHAR_PTR                            pPassword;\n        CK_ULONG_PTR                               ulPasswordLen;\n} CK_PKCS5_PBKD2_PARAMS;\n\ntypedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;\n\n/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */\n\ntypedef CK_ULONG CK_OTP_PARAM_TYPE;\ntypedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */\n\ntypedef struct CK_OTP_PARAM {\n    CK_OTP_PARAM_TYPE type;\n    CK_VOID_PTR pValue;\n    CK_ULONG ulValueLen;\n} CK_OTP_PARAM;\n\ntypedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;\n\ntypedef struct CK_OTP_PARAMS {\n    CK_OTP_PARAM_PTR pParams;\n    CK_ULONG ulCount;\n} CK_OTP_PARAMS;\n\ntypedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;\n\ntypedef struct CK_OTP_SIGNATURE_INFO {\n    CK_OTP_PARAM_PTR pParams;\n    CK_ULONG ulCount;\n} CK_OTP_SIGNATURE_INFO;\n\ntypedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;\n\n/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */\n#define CK_OTP_VALUE          0\n#define CK_OTP_PIN            1\n#define CK_OTP_CHALLENGE      2\n#define CK_OTP_TIME           3\n#define CK_OTP_COUNTER        4\n#define CK_OTP_FLAGS          5\n#define CK_OTP_OUTPUT_LENGTH  6\n#define CK_OTP_OUTPUT_FORMAT  7\n\n/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */\n#define CKF_NEXT_OTP          0x00000001\n#define CKF_EXCLUDE_TIME      0x00000002\n#define CKF_EXCLUDE_COUNTER   0x00000004\n#define CKF_EXCLUDE_CHALLENGE 0x00000008\n#define CKF_EXCLUDE_PIN       0x00000010\n#define CKF_USER_FRIENDLY_OTP 0x00000020\n\n/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */\ntypedef struct CK_KIP_PARAMS {\n    CK_MECHANISM_PTR  pMechanism;\n    CK_OBJECT_HANDLE  hKey;\n    CK_BYTE_PTR       pSeed;\n    CK_ULONG          ulSeedLen;\n} CK_KIP_PARAMS;\n\ntypedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;\n\n/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */\ntypedef struct CK_AES_CTR_PARAMS {\n    CK_ULONG ulCounterBits;\n    CK_BYTE cb[16];\n} CK_AES_CTR_PARAMS;\n\ntypedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;\n\n/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */\ntypedef struct CK_CAMELLIA_CTR_PARAMS {\n    CK_ULONG ulCounterBits;\n    CK_BYTE cb[16];\n} CK_CAMELLIA_CTR_PARAMS;\n\ntypedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;\n\n/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */\ntypedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {\n    CK_BYTE      iv[16];\n    CK_BYTE_PTR  pData;\n    CK_ULONG     length;\n} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;\n\ntypedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;\n\n/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */\ntypedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {\n    CK_BYTE      iv[16];\n    CK_BYTE_PTR  pData;\n    CK_ULONG     length;\n} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;\n\ntypedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;\n\n#endif\n"
  },
  {
    "path": "deps/cl345/device/system.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib System Device Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"capabil.h\"\n  #include \"device.h\"\n  #include \"random.h\"\n#else\n  #include \"crypt.h\"\n  #include \"device/capabil.h\"\n  #include \"device/device.h\"\n  #include \"random/random.h\"\n#endif /* Compiler-specific includes */\n\n/* Mechanisms supported by the system device.  Since the mechanism space is \n   sparse, dispatching is handled by looking up the required mechanism in a \n   table of (action, mechanism, function) triples.  The table is sorted by \n   order of most-frequently-used mechanisms to speed things up, although the \n   overhead is vanishingly small anyway */\n\nstatic const MECHANISM_FUNCTION_INFO mechanismFunctions[] = {\n#ifdef USE_PKC\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },\n  #if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },\n  #endif /* USE_SSL && USE_RSA_SUITES */\n  #ifdef USE_OAEP\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_OAEP, ( MECHANISM_FUNCTION ) exportOAEP },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_OAEP, ( MECHANISM_FUNCTION ) importOAEP },\n  #endif /* USE_OAEP */\n#endif /* USE_PKC */\n#ifdef USE_PGP\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },\n#endif /* USE_PGP */\n#ifdef USE_INT_CMS\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },\n#endif /* USE_INT_CMS */\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PBKDF2, ( MECHANISM_FUNCTION ) derivePBKDF2 },\n#if defined( USE_ENVELOPES ) && defined( USE_CMS )\n\t{ MESSAGE_DEV_KDF, MECHANISM_DERIVE_PBKDF2, ( MECHANISM_FUNCTION ) kdfPBKDF2 },\n#endif /* USE_ENVELOPES && USE_CMS */\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },\n#endif /* USE_PGP || USE_PGPKEYS */\n#ifdef USE_SSL\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveSSL },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveTLS },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS12, ( MECHANISM_FUNCTION ) deriveTLS12 },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },\n\t{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },\n#endif /* USE_SSL */\n#ifdef USE_CMP\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },\n#endif /* USE_CMP */\n#ifdef USE_PKCS12\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },\n#endif /* USE_PKCS12 */\n#if defined( USE_KEYSETS ) && defined( USE_PKC )\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_PRIVATEKEYWRAP, ( MECHANISM_FUNCTION ) exportPrivateKey },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP, ( MECHANISM_FUNCTION ) importPrivateKey },\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_PRIVATEKEYWRAP_PKCS8, ( MECHANISM_FUNCTION ) exportPrivateKeyPKCS8 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_PKCS8, ( MECHANISM_FUNCTION ) importPrivateKeyPKCS8 },\n#endif /* USE_KEYSETS && USE_PKC */\n#ifdef USE_PGPKEYS\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_PGP2, ( MECHANISM_FUNCTION ) importPrivateKeyPGP2 },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD, ( MECHANISM_FUNCTION ) importPrivateKeyOpenPGPOld },\n\t{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_OPENPGP, ( MECHANISM_FUNCTION ) importPrivateKeyOpenPGP },\n#endif /* USE_PGPKEYS */\n#ifndef CONFIG_NO_SELFTEST\n\t{ MESSAGE_DEV_EXPORT, MECHANISM_SELFTEST_ENC, ( MECHANISM_FUNCTION ) pkcWrapSelftest },\n\t{ MESSAGE_DEV_SIGN, MECHANISM_SELFTEST_SIG, ( MECHANISM_FUNCTION ) signSelftest },\n\t{ MESSAGE_DEV_DERIVE, MECHANISM_SELFTEST_DERIVE, ( MECHANISM_FUNCTION ) deriveSelftest },\n\t{ MESSAGE_DEV_KDF, MECHANISM_SELFTEST_KDF, ( MECHANISM_FUNCTION ) kdfSelftest },\n#endif /* CONFIG_NO_SELFTEST */\n\t{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }\n\t};\n\n/* Object creation functions supported by the system device.  These are\n   sorted in order of frequency of use in order to make lookups a bit\n   faster */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificate( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo, \n\t\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\t   STDC_UNUSED const int auxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createEnvelope( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo, \n\t\t\t\t\tSTDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\tSTDC_UNUSED const int auxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createSession( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t   STDC_UNUSED const int auxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createKeyset( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t  STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t  STDC_UNUSED const int auxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createDevice( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t  STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t  STDC_UNUSED const int auxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createUser( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\tSTDC_UNUSED const void *auxDataPtr, \n\t\t\t\tSTDC_UNUSED const int auxValue );\n\nstatic const CREATEOBJECT_FUNCTION_INFO createObjectFunctions[] = {\n\t{ OBJECT_TYPE_CONTEXT, createContext },\n#ifdef USE_CERTIFICATES\n\t{ OBJECT_TYPE_CERTIFICATE, createCertificate },\n#endif /* USE_CERTIFICATES */\n#ifdef USE_ENVELOPES\n\t{ OBJECT_TYPE_ENVELOPE, createEnvelope },\n#endif /* USE_ENVELOPES */\n#ifdef USE_SESSIONS\n\t{ OBJECT_TYPE_SESSION, createSession },\n#endif /* USE_SESSIONS */\n#ifdef USE_KEYSETS\n\t{ OBJECT_TYPE_KEYSET, createKeyset },\n#endif /* USE_KEYSETS */\n\t{ OBJECT_TYPE_DEVICE, createDevice },\n\t{ OBJECT_TYPE_USER, createUser },\n\t{ OBJECT_TYPE_NONE, NULL }, { OBJECT_TYPE_NONE, NULL }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRandomness Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get random data.  We have to unlock the device around the randomness \n   fetch because background polling threads need to be able to send entropy\n   data to it:\n\n\t\t\t\tSystem\t\t\tRandomness\n\t\t\t\t------\t\t\t----------\n\tgetRand ------>|\t\t\t\t|\n\t\t\t   [Suspend]\t\t\t|\n\t\t\t\t   |--------------->|\n\t\t\t\t   |\t\t\t\t|\n\t\t\t\t   |<===============| Entropy\n\t\t\t\t   |<===============| Entropy\n\t\t\t\t   |<===============| Entropy Quality\n\t\t\t\t   |\t\t\t\t|\n\t\t\t\t   |<---------------|\n\t\t\t   [Resume]\t\t\t\t|\n   \n   If the caller has specified that it's unlockable and the reference count\n   is one or less (meaning that we've been sent the message directly), we \n   leave it unlocked.  Otherwise we re-lock it afterwards. \n\n   Note that there's a tiny chance of a race condition if the system object \n   is destroyed between the unlock and the acquisition of the randomness \n   mutex (which means that the randomInfo could be freed while we're getting \n   the random data), however there's no easy way around this short of using\n   a complex multiple-mutex interlock, and in any case there's only so much \n   that we can do to help a user who pulls data structures out from under \n   active threads */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getRandomFunction( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( length ) void *buffer,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t\t\t  INOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tint refCount, status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfo ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\t/* Clear the return value and make sure that we fail the FIPS 140 tests\n\t   on the output if there's a problem */\n\tzeroise( buffer, length );\n\n\t/* If the system device is already unlocked (which can happen if this \n\t   function is called in a loop, for example if multiple chunks of \n\t   randomness are read) just return the randomness directly */\n\tif( messageExtInfo != NULL && isMessageObjectUnlocked( messageExtInfo ) )\n\t\treturn( getRandomData( deviceInfo->randomInfo, buffer, length ) );\n\n\t/* Unlock the system device, get the data, and re-lock it if necessary.\n\t   This is necessary for two reasons, firstly because the background \n\t   poll can take awhile and we don't want to block all messages to the\n\t   system object while it's in progress, and secondly so that the \n\t   background polling thread can send entropy to the system object */\n\tstatus = krnlSuspendObject( deviceInfo->objectHandle, &refCount );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = getRandomData( deviceInfo->randomInfo, buffer, length );\n\tif( messageExtInfo == NULL || refCount > 1 )\n\t\t{\n\t\tint resumeStatus;\n\n\t\t/* The object isn't unlockable or it's been locked recursively, \n\t\t   re-lock it */\n\t\tresumeStatus = krnlResumeObject( SYSTEM_OBJECT_HANDLE, refCount );\n\t\tif( cryptStatusError( resumeStatus ) )\n\t\t\t{\n\t\t\t/* We couldn't re-lock the system object, let the caller know.\n\t\t\t   Since this is a shouldn't-occur condition we also warn the \n\t\t\t   user in the debug version */\n\t\t\tDEBUG_DIAG(( \"Failed to re-lock system object\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tif( messageExtInfo != NULL )\n\t\t\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Tell the caller that we've left the object unlocked so they don't\n\t\t   have to do anything further with it */\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\t}\n\treturn( status );\n\t}\n\n/* Get a random (but not necessarily cryptographically strong random) nonce.\n   Some nonces can simply be fresh (for which a monotonically increasing\n   sequence will do), some should be random (for which a hash of the\n   sequence is adequate), and some need to be unpredictable.  In order to\n   avoid problems arising from the inadvertent use of a nonce with the wrong\n   properties we use unpredictable nonces in all cases, even where it isn't\n   strictly necessary.\n\n   This simple generator divides the nonce state into a public section of\n   the same size as the hash output and a private section that contains 64\n   bits of data from the crypto RNG, which influences the public section.\n   The public and private sections are repeatedly hashed to produce the\n   required amount of output.  Note that this leaks a small amount of\n   information about the crypto RNG output since an attacker knows that\n   public_state_n = hash( public_state_n - 1, private_state ) but this\n   isn't a major weakness */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checksumNonceData( INOUT SYSTEMDEV_INFO *systemInfo )\n\t{\n\tconst int oldChecksum = systemInfo->nonceChecksum;\n\tint newChecksum;\n\n\tassert( isWritePtr( systemInfo, sizeof( SYSTEMDEV_INFO ) ) );\n\n\tsystemInfo->nonceChecksum = 0;\n\tnewChecksum = checksumData( systemInfo, sizeof( SYSTEMDEV_INFO ) );\n\tsystemInfo->nonceChecksum = newChecksum;\n\n\treturn( ( oldChecksum == newChecksum ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getNonce( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t OUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSYSTEMDEV_INFO *systemInfo = deviceInfo->deviceSystem;\n\tHASH_FUNCTION_ATOMIC nonceHashFunction;\n\tBYTE *noncePtr = data;\n\tint nonceLength, LOOP_ITERATOR;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Handling of CRYPT_IATTRIBUTE_RANDOM_NONCE gets complicated because \n\t   it may trigger an entropy poll, for which the system device has to \n\t   be unlocked so that it doesn't stall or block any subsequent messages \n\t   to the device.  The normal process for this is:\n\n\t\tkSendMsg( GETATTR_S, IATTR_NONCE );\n\t\tsystem.c:getNonce() ->\n\t\t\tkSendMsg( GETATTR_S, IATTR_RANDOM );\n\n\t\tsystem.c:getRandomFunction() ->\n\t\t\tkSuspendObj( SYSTEM_DEVICE );\n\n\t\t\trandom.c:getRandomData() ->\t\t\t\n\t\t\t\tif( randomQual < 100 )\n\t\t\t\t\tslowPoll();\n\t\t\t\t\t\t\t\t\t\t\t\tkSendMsg( SETATTR_S, IATTR_ENTROPY );\n\t\t\t\t\t\t\t\t\t\t\t\tkSendMsg( SETATTR_S, IATTR_ENTROPY_QUAL );\n\t\t\tkResumeObj( SYSTEM_DEVICE );\n\n\t   In the presence of a second thread that sends a \n\t   CRYPT_IATTRIBUTE_RANDOM_NONCE message to the system device we have:\n\n\t\tkSendMsg( GETATTR_S, IATTR_NONCE );\t\tkSendMsg( GETATTR_S, IATTR_NONCE );\n\t\tsystem.c:getNonce() ->\n\t\t\tkSendMsg( GETATTR_S, IATTR_RANDOM );\n\n\t\tsystem.c:getRandomFunction() ->\n\t\t\tkSuspendObj( SYSTEM_DEVICE );\n\t\t\t\t\t\t\t\t\t\t\t\tsystem.c:getNonce() ->\n\t\t\t\t\t\t\t\t\t\t\t\t\tkSendMsg( GETATTR_S, IATTR_RANDOM );\n\n\t   At this point two threads are both in getNonce().  Since the system \n\t   object is already unlocked, kSuspendObj() isn't called and the code \n\t   path continues:\n\n\t\t\trandom.c:getRandomData();\t\t\trandom.c:getRandomData();\n\n\t   random.c:getRandomData() uses MUTEX_RANDOM to enforce mutual \n\t   exclusion, but before that the system device's randomness functions \n\t   aren't protected.  This only affects CRYPT_IATTRIBUTE_RANDOM_NONCE \n\t   and not the other get-randomness functions because they call directly \n\t   into the randomness subsystem, but the nonce RNG is implemented in \n\t   the system device which is unlocked at this point.\n\n\t   Dealing with this is isn't really possible without introducing some \n\t   form of additional mutex somewhere that's used only by the system \n\t   device for CRYPT_IATTRIBUTE_RANDOM_NONCE, and only for this one \n\t   obscure race condition (there's no serious damage done, it's just \n\t   that the nonce RNG gets initialised twice).\n\n\t   In place of this extra complication, what we do is call the \n\t   randomness subsystem to get a single byte, which triggers any \n\t   required entropy polling in a manner protected by the randomness \n\t   mutex, which serialises access at that point.  In other words we \n\t   borrow the randomness mutex to also act as a mutex for the nonce RNG.\n\n\t   There's still a race condition possible at this point if one thread \n\t   is pre-empted after the call into the randomness subsystem, allowing \n\t   the second thread to continue so that both now enter the following \n\t   code block, however the chances are now greatly reduced */\n\tif( !systemInfo->nonceDataInitialised )\n\t\t{\n\t\tBYTE buffer[ 1 + 8 ];\n\t\tint status;\n\n\t\tstatus = getRandomFunction( deviceInfo, buffer, 1, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If the nonce generator hasn't been initialised yet we set up the\n\t   hashing and get 64 bits of private nonce state.  What to do if the\n\t   attempt to initialise the state fails is somewhat debatable.  Since\n\t   nonces are only ever used in protocols alongside crypto keys and an\n\t   RNG failure will be detected when the key is generated we can\n\t   generally ignore a failure at this point.  \n\t   \n\t   However nonces are sometimes also used in non-crypto contexts (for \n\t   example to generate certificate serial numbers) where this detection \n\t   in the RNG won't happen.  On the other hand we shouldn't really abort \n\t   processing just because we can't get some no-value nonce data so what \n\t   we do is retry the fetch of nonce data (in case the system object was \n\t   busy and the first attempt timed out) and if that fails too fall back \n\t   to the system time.  \n\t   \n\t   This is no longer unpredictable, but the only location where \n\t   unpredictability matters is when used in combination with crypto \n\t   operations for which the absence of random data will be detected \n\t   during key generation */\n\tif( !systemInfo->nonceDataInitialised )\n\t\t{\n\t\tHASH_FUNCTION_ATOMIC hashFunction;\n\t\tMESSAGE_DATA msgData;\n\t\tint hashSize, status;\n\n\t\t/* Get the 64-bit private portion of the nonce data, which follows\n\t\t   the public portion at the start of the buffer.  Note that we\n\t\t   have to set the nonceHashSize after we get the random data since\n\t\t   the device info is sanity-checked when we send the get-random\n\t\t   message to it and a nonceHashSize with no nonce data would fail\n\t\t   the sanity check */\n\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0,\n\t\t\t\t\t\t\t\t &hashFunction, &hashSize );\n\t\tsetMessageData( &msgData, systemInfo->nonceData + hashSize, \n\t\t\t\t\t\t\t\t  NONCERNG_PRIVATE_STATESIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tconst time_t theTime = getTime();\n\n\t\t\tmemcpy( systemInfo->nonceData + hashSize, \n\t\t\t\t\t&theTime, sizeof( time_t ) );\n\t\t\t}\n\t\tFNPTR_SET( systemInfo->nonceHashFunction, hashFunction );\n\t\tsystemInfo->nonceHashSize = hashSize;\n\t\tsystemInfo->nonceDataInitialised = TRUE;\n\t\t( void ) checksumNonceData( systemInfo );\n\n\t\tENSURES( systemInfo->nonceHashSize >= MIN_HASHSIZE && \\\n\t\t\t\t systemInfo->nonceHashSize <= CRYPT_MAX_HASHSIZE );\n\t\tENSURES( isEmptyData( systemInfo->nonceData, 0 ) );\n\t\tENSURES( !isEmptyData( systemInfo->nonceData + \\\n\t\t\t\t\t\t\t\t\tsystemInfo->nonceHashSize, 0 ) );\n\t\t}\n\tENSURES( checksumNonceData( systemInfo ) );\n\tnonceHashFunction = ( HASH_FUNCTION_ATOMIC ) \\\n\t\t\t\t\t\tFNPTR_GET( systemInfo->nonceHashFunction );\n\tENSURES( nonceHashFunction != NULL );\n\n\t/* Shuffle the public state and copy it to the output buffer until it's\n\t   full */\n\tLOOP_LARGE_INITCHECK( nonceLength = dataLength, nonceLength > 0 )\n\t\t{\n\t\tconst int bytesToCopy = min( nonceLength, systemInfo->nonceHashSize );\n\n\t\t/* Hash the state and copy the appropriate amount of data to the\n\t\t   output buffer */\n\t\tnonceHashFunction( systemInfo->nonceData, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t   systemInfo->nonceData,\n\t\t\t\t\t\t   systemInfo->nonceHashSize + \\\n\t\t\t\t\t\t\t\tNONCERNG_PRIVATE_STATESIZE );\n\t\tREQUIRES( boundsCheckZ( dataLength - nonceLength, bytesToCopy, \n\t\t\t\t\t\t\t\tdataLength ) );\n\t\tmemcpy( noncePtr, systemInfo->nonceData, bytesToCopy );\n\n\t\t/* Move on to the next block of the output buffer */\n\t\tnoncePtr += bytesToCopy;\n\t\tnonceLength -= bytesToCopy;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t( void ) checksumNonceData( systemInfo );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Perform the algorithm self-test.  This returns two status values, the \n   overall status of calling the function as the standard return value and\n   the status of the algorithm tests as a by-reference parameter */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int algorithmSelfTest( INOUT \\\n\t\t\t\t\t\t\t\tCAPABILITY_INFO_LIST **capabilityInfoListPtrPtr,\n\t\t\t\t\t\t\t  OUT_STATUS int *testStatus )\n\t{\n\tDATAPTR capabilityInfoListHead;\n\tCAPABILITY_INFO_LIST *capabilityInfoListPtr;\n\tCAPABILITY_INFO_LIST *capabilityInfoListPrevPtr = NULL;\n\tBOOLEAN algoTested = FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( capabilityInfoListPtrPtr, \n\t\t\t\t\t   sizeof( CAPABILITY_INFO_LIST * ) ) );\n\n\t/* Clear return value */\n\t*testStatus = CRYPT_OK;\n\n\t/* The capability info list is built using safe pointers but we've been\n\t   passed a standard pointer, in order to manipulate it we have to \n\t   convert it to a safe pointer */\n\tDATAPTR_SET( capabilityInfoListHead, *capabilityInfoListPtrPtr );\n\n\t/* Test each available capability */\n\tLOOP_MED( capabilityInfoListPtr = *capabilityInfoListPtrPtr, \n\t\t\t  capabilityInfoListPtr != NULL,\n\t\t\t  capabilityInfoListPtr = DATAPTR_GET( capabilityInfoListPtr->next ) )\n\t\t{\n\t\tconst CAPABILITY_INFO *capabilityInfoPtr = \\\n\t\t\t\t\tDATAPTR_GET( capabilityInfoListPtr->info );\n\t\tint localStatus;\n\n\t\tREQUIRES( capabilityInfoPtr != NULL );\n\t\tREQUIRES( sanityCheckCapability( capabilityInfoPtr ) );\n\t\tREQUIRES( capabilityInfoPtr->selfTestFunction != NULL );\n\n\t\t/* Perform the self-test for this algorithm type */\n\t\tlocalStatus = capabilityInfoPtr->selfTestFunction();\n\t\tif( cryptStatusError( localStatus ) )\n\t\t\t{\n\t\t\t/* The self-test failed, remember the status if it's the first \n\t\t\t   failure and disable this algorithm */\n\t\t\tif( cryptStatusOK( *testStatus ) )\n\t\t\t\t*testStatus = localStatus;\n\t\t\tdeleteSingleListElement( capabilityInfoListHead, \n\t\t\t\t\t\t\t\t\t capabilityInfoListPrevPtr, \n\t\t\t\t\t\t\t\t\t capabilityInfoListPtr,\n\t\t\t\t\t\t\t\t\t CAPABILITY_INFO_LIST );\n\t\t\tDEBUG_DIAG(( \"Algorithm %s failed self-test\", \n\t\t\t\t\t\t capabilityInfoPtr->algoName ));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\talgoTested = TRUE;\n\n\t\t\t/* Remember the last successfully-tested capability */\n\t\t\tcapabilityInfoListPrevPtr = capabilityInfoListPtr;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we've updated the list head, reflect the changed safe pointer back \n\t   to the original pointer */\n\tif( DATAPTR_GET( capabilityInfoListHead ) != *capabilityInfoListPtrPtr )\n\t\t*capabilityInfoListPtrPtr = DATAPTR_GET( capabilityInfoListHead );\n\n\treturn( algoTested ? CRYPT_OK : CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* Perform the mechanism self-test.  This is performed in addition to the \n   algorithm tests if the user requests a test of all algorithms.  \n   \n   Only low-level mechanism functionality is tested since the high-level \n   tests either produce non-constant results that can't be checked against a \n   fixed value or require the creation of multiple contexts to hold keys.\n   For example to check the key wrap mechanisms the order of operations\n   would be:\n\n\tcreate PKC context;\n\tcreate conventional context;\n\tload key into conventional context;\n\twrap conventional context using PKC context;\n\tdestroy conventional context;\n\tcreate conventional context;\n\tunwrap conventional context using PKC context;\n\tdestroy conventional context;\n\tdestroy PKC context;\n\n   requiring a PKC and two conventional contexts for each test */\n\n/* Perform a self-test */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int selftestFunction( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\t INOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tCAPABILITY_INFO_LIST *capabilityInfoListPtr = \\\n\t\t\t( CAPABILITY_INFO_LIST * ) DATAPTR_GET( deviceInfo->capabilityInfoList );\n\tMECHANISM_WRAP_INFO pkcWrapMechanismInfo;\n\tMECHANISM_SIGN_INFO signMechanismInfo;\n\tMECHANISM_DERIVE_INFO deriveMechanismInfo;\n\tMECHANISM_KDF_INFO kdfMechanismInfo;\n\tBYTE buffer[ 8 + 8 ];\n\tint refCount, status, testStatus;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( isWritePtr( messageExtInfo, \\\n\t\t\t\t\t\tsizeof( MESSAGE_FUNCTION_EXTINFO ) ) );\n\n\tREQUIRES( sanityCheckDevice( deviceInfo ) );\n\tREQUIRES( capabilityInfoListPtr != NULL );\n\n\t/* The self-tests need randomness for some of their operations, in order\n\t   to pre-empt a lack of this from causing a failure somewhere deep down\n\t   in the crypto code we perform a dummy read of first the randomness \n\t   source and then the nonce source to force a full initialisation of \n\t   the randomness subsystem */\n\tstatus = getRandomFunction( deviceInfo, buffer, 8, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tzeroise( buffer, 8 );\n\tstatus = getNonce( deviceInfo, buffer, 8 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tzeroise( buffer, 8 );\n\n\t/* Perform an algorithm self-test.  This returns two status values, the\n\t   status of calling the self-test function and the status of the tests\n\t   that were performed.  The function call may succeed (status == \n\t   CRYPT_OK) but one of the tests performed by the function may have \n\t   failed (testStatus != CRYPT_OK), so we have to exit on either type of\n\t   error */\n\tstatus = algorithmSelfTest( &capabilityInfoListPtr, &testStatus );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( cryptStatusError( testStatus ) )\n\t\t{\n\t\t/* One or more of the self-tests failed, update the capability list \n\t\t   since the failed capabilities will have been removed from the \n\t\t   list */\n\t\tDATAPTR_SET( deviceInfo->capabilityInfoList, capabilityInfoListPtr );\n\t\treturn( testStatus );\n\t\t}\n\n\t/* Since the mechanism self-tests can be quite lengthy and require \n\t   recursive handling of messages by the system object (without actually \n\t   requiring access to the system object state) we unlock it before \n\t   running the tests to avoid it becoming a bottleneck */\n\tstatus = krnlSuspendObject( deviceInfo->objectHandle, &refCount );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageObjectUnlocked( messageExtInfo );\n\t\n\t/* Perform the mechanism self-tests */\n\tsetMechanismWrapInfo( &pkcWrapMechanismInfo, NULL, 0, NULL, 0, \n\t\t\t\t\t\t  CRYPT_UNUSED, CRYPT_UNUSED );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_EXPORT, &pkcWrapMechanismInfo,\n\t\t\t\t\t\t\t  MECHANISM_SELFTEST_ENC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMechanismSignInfo( &signMechanismInfo, NULL, 0, CRYPT_UNUSED, \n\t\t\t\t\t\t  CRYPT_UNUSED, CRYPT_UNUSED );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_SIGN, &signMechanismInfo,\n\t\t\t\t\t\t\t  MECHANISM_SELFTEST_SIG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMechanismDeriveInfo( &deriveMechanismInfo, NULL, 0, NULL, 0, 0, \n\t\t\t\t\t\t\tNULL, 0, 0 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_DERIVE, &deriveMechanismInfo,\n\t\t\t\t\t\t\t  MECHANISM_SELFTEST_DERIVE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMechanismKDFInfo( &kdfMechanismInfo, CRYPT_UNUSED, CRYPT_UNUSED, 0, \n\t\t\t\t\t\t NULL, 0 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_KDF, &kdfMechanismInfo,\n\t\t\t\t\t\t\t  MECHANISM_SELFTEST_KDF );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDevice Init/Shutdown/Device Control Routines\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and shut down the system device */\n\nCHECK_RETVAL \\\nstatic int initCapabilities( void );\t\t/* Fwd.dec for fn.*/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initFunction( INOUT DEVICE_INFO *deviceInfo, \n\t\t\t\t\t\t STDC_UNUSED const char *name,\n\t\t\t\t\t\t STDC_UNUSED const int nameLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tREQUIRES( name == NULL && nameLength == 0 );\n\n\t/* Set up the capability information for this device */\n\tstatus = initCapabilities();\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the randomness information */\n\tstatus = initRandomInfo( &deviceInfo->randomInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Complete the initialisation and mark the device as active */\n\tdeviceInfo->label = \"cryptlib system device\";\n\tdeviceInfo->labelLen = strlen( deviceInfo->label );\n\tSET_FLAG( deviceInfo->flags, DEVICE_FLAG_ACTIVE | \\\n\t\t\t\t\t\t\t\t DEVICE_FLAG_LOGGEDIN | \\\n\t\t\t\t\t\t\t\t DEVICE_FLAG_TIME );\n\n\tENSURES( sanityCheckDevice( deviceInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void shutdownFunction( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tendRandomInfo( &deviceInfo->randomInfo );\n\t}\n\n/* Handle device control functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int controlFunction( INOUT DEVICE_INFO *deviceInfo,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( dataLength ) void *data, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataLength,\n\t\t\t\t\t\t\tINOUT_OPT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )\n\t{\n\tint refCount, status;\n\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\tassert( data == NULL || isReadPtrDynamic( data, dataLength ) );\n\t\n\tREQUIRES( sanityCheckDevice( deviceInfo ) );\n\tREQUIRES( type == CRYPT_IATTRIBUTE_ENTROPY || \\\n\t\t\t  type == CRYPT_IATTRIBUTE_ENTROPY_QUALITY || \\\n\t\t\t  type == CRYPT_IATTRIBUTE_RANDOM_POLL || \\\n\t\t\t  type == CRYPT_IATTRIBUTE_RANDOM_NONCE || \\\n\t\t\t  type == CRYPT_IATTRIBUTE_TIME );\n\tREQUIRES( ( ( type == CRYPT_IATTRIBUTE_ENTROPY || \\\n\t\t\t\t  type == CRYPT_IATTRIBUTE_RANDOM_NONCE ) && \\\n\t\t\t\t( data != NULL && isIntegerRangeNZ( dataLength ) ) ) || \\\n\t\t\t  ( type == CRYPT_IATTRIBUTE_TIME && \\\n\t\t\t\tdata != NULL && dataLength == sizeof( time_t ) ) || \\\n\t\t\t  ( type == CRYPT_IATTRIBUTE_RANDOM_POLL && \\\n\t\t\t\tdata == NULL && \\\n\t\t\t\t( dataLength == FALSE || dataLength == TRUE ) ) || \\\n\t\t\t  ( type == CRYPT_IATTRIBUTE_ENTROPY_QUALITY && \\\n\t\t\t\t( data == NULL && isShortIntegerRange( dataLength ) ) ) );\n\n\t/* Handle entropy addition.  Since this can take awhile, we do it with\n\t   the system object unlocked.  See the comment in getRandomFunction()\n\t   about the possibility of a race condition */\n\tif( type == CRYPT_IATTRIBUTE_ENTROPY )\n\t\t{\n\t\tstatus = krnlSuspendObject( deviceInfo->objectHandle, &refCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\treturn( addEntropyData( deviceInfo->randomInfo, data, dataLength ) );\n\t\t}\n\tif( type == CRYPT_IATTRIBUTE_ENTROPY_QUALITY )\n\t\t{\n\t\tstatus = krnlSuspendObject( deviceInfo->objectHandle, &refCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\t\treturn( addEntropyQuality( deviceInfo->randomInfo, dataLength ) );\n\t\t}\n\tif( type == CRYPT_IATTRIBUTE_RANDOM_POLL )\n\t\t{\n\t\tstatus = krnlSuspendObject( deviceInfo->objectHandle, &refCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsetMessageObjectUnlocked( messageExtInfo );\n\n\t\t/* Perform a slow or fast poll as required */\n\t\tif( dataLength == TRUE )\n\t\t\tslowPoll();\n\t\telse\n\t\t\tfastPoll();\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Handle nonces */\n\tif( type == CRYPT_IATTRIBUTE_RANDOM_NONCE )\n\t\treturn( getNonce( deviceInfo, data, dataLength ) );\n\n\t/* Handle high-reliability time */\n\tif( type == CRYPT_IATTRIBUTE_TIME )\n\t\t{\n\t\ttime_t *timePtr = ( time_t * ) data;\n\n\t\t*timePtr = getTime();\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDevice Capability Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The cryptlib intrinsic capability list */\n\n#define MAX_NO_CAPABILITIES\t\t32\n\nstatic const GETCAPABILITY_FUNCTION getCapabilityTable[] = {\n#ifdef USE_3DES\n\tget3DESCapability,\n#endif /* USE_3DES */\n#ifdef USE_AES\n\tgetAESCapability,\n#endif /* USE_AES */\n#ifdef USE_CAST\n\tgetCASTCapability,\n#endif /* USE_CAST */\n#ifdef USE_DES\n\tgetDESCapability,\n#endif /* USE_DES */\n#ifdef USE_IDEA\n\tgetIDEACapability,\n#endif /* USE_IDEA */\n#ifdef USE_RC2\n\tgetRC2Capability,\n#endif /* USE_RC2 */\n#ifdef USE_RC4\n\tgetRC4Capability,\n#endif /* USE_RC4 */\n\n#ifdef USE_MD5\n\tgetMD5Capability,\n#endif /* USE_MD5 */\n\tgetSHA1Capability,\n\tgetSHA2Capability,\n\n\tgetHmacSHA1Capability,\n\tgetHmacSHA2Capability,\n\n#ifdef USE_DH\n\tgetDHCapability,\n#endif /* USE_DH */\n#ifdef USE_DSA\n\tgetDSACapability,\n#endif /* USE_DSA */\n#ifdef USE_ELGAMAL\n\tgetElgamalCapability,\n#endif /* USE_ELGAMAL */\n#ifdef USE_RSA\n\tgetRSACapability,\n#endif /* USE_RSA */\n#ifdef USE_ECDSA\n\tgetECDSACapability,\n#endif /* USE_ECDSA */\n#ifdef USE_ECDH\n\tgetECDHCapability,\n#endif /* USE_ECDH */\n\n\tgetGenericSecretCapability,\n\n\t/* Vendors may want to use their own algorithms, which aren't part of the\n\t   general cryptlib suite.  The following provides the ability to include\n\t   vendor-specific algorithm capabilities defined in the file\n\t   vendalgo.c */\n#ifdef USE_VENDOR_ALGOS\n\t#include \"vendalgo.c\"\n#endif /* USE_VENDOR_ALGOS */\n\n\t/* End-of-list marker */\n\tNULL, NULL\n\t};\n\nstatic CAPABILITY_INFO_LIST capabilityInfoList[ MAX_NO_CAPABILITIES ];\n\n/* Initialise the capability information */\n\nCHECK_RETVAL \\\nstatic int initCapabilities( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Build the list of available capabilities */\n\tmemset( capabilityInfoList, 0,\n\t\t\tsizeof( CAPABILITY_INFO_LIST ) * MAX_NO_CAPABILITIES );\n\tLOOP_LARGE( i = 0, \n\t\t\t\tgetCapabilityTable[ i ] != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( getCapabilityTable, \\\n\t\t\t\t\t\t\t\t\t\t\tGETCAPABILITY_FUNCTION ),\n\t\t\t\ti++ )\n\t\t{\n\t\tconst CAPABILITY_INFO *capabilityInfoPtr = getCapabilityTable[ i ]();\n\n#ifndef CONFIG_FUZZ\n\t\tREQUIRES( sanityCheckCapability( capabilityInfoPtr ) );\n#endif /* !CONFIG_FUZZ */\n\n\t\tDATAPTR_SET( capabilityInfoList[ i ].info, \n\t\t\t\t\t ( void * ) capabilityInfoPtr );\n\t\tDATAPTR_SET( capabilityInfoList[ i ].next, NULL );\n\t\tif( i > 0 )\n\t\t\t{\n\t\t\tDATAPTR_SET( capabilityInfoList[ i - 1 ].next, &capabilityInfoList[ i ] );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( getCapabilityTable, \\\n\t\t\t\t\t\t\t\t\t GETCAPABILITY_FUNCTION ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDevice Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the function pointers to the device methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setDeviceSystem( INOUT DEVICE_INFO *deviceInfo )\n\t{\n\tassert( isWritePtr( deviceInfo, sizeof( DEVICE_INFO ) ) );\n\n\tFNPTR_SET( deviceInfo->initFunction, initFunction );\n\tFNPTR_SET( deviceInfo->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( deviceInfo->controlFunction, controlFunction );\n\tFNPTR_SET( deviceInfo->getItemFunction, NULL );\n\tFNPTR_SET( deviceInfo->setItemFunction, NULL );\n\tFNPTR_SET( deviceInfo->deleteItemFunction, NULL );\n\tFNPTR_SET( deviceInfo->getFirstItemFunction, NULL );\n\tFNPTR_SET( deviceInfo->getNextItemFunction, NULL );\n#ifndef CONFIG_NO_SELFTEST\n\tFNPTR_SET( deviceInfo->selftestFunction, selftestFunction );\n#endif /* !CONFIG_NO_SELFTEST */\n\tFNPTR_SET( deviceInfo->getRandomFunction, getRandomFunction );\n\tDATAPTR_SET( deviceInfo->capabilityInfoList, capabilityInfoList );\n\tdeviceInfo->createObjectFunctions = createObjectFunctions;\n\tdeviceInfo->createObjectFunctionCount = \\\n\t\tFAILSAFE_ARRAYSIZE( createObjectFunctions, CREATEOBJECT_FUNCTION_INFO );\n\tdeviceInfo->mechanismFunctions = mechanismFunctions;\n\tdeviceInfo->mechanismFunctionCount = \\\n\t\tFAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  ASN.1 Constants and Structures\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ASN1_DEFINED\n\n#define _ASN1_DEFINED\n\n#include <time.h>\n#if defined( INC_ALL )\n  #include \"stream.h\"\n#else\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tBER/DER Constants and Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Definitions for the ISO 8825:1990 Basic Encoding Rules */\n\n/* Tag class */\n\n#define BER_UNIVERSAL\t\t\t0x00\n#define BER_APPLICATION\t\t\t0x40\n#define BER_CONTEXT_SPECIFIC\t0x80\n#define BER_PRIVATE\t\t\t\t0xC0\n\n/* Whether the encoding is constructed or primitive */\n\n#define BER_CONSTRUCTED\t\t\t0x20\n#define BER_PRIMITIVE\t\t\t0x00\n\n/* The ID's for universal tag numbers 0-31.  Tag number 0 is reserved for\n   encoding the end-of-contents value when an indefinite-length encoding\n   is used */\n\nenum { BER_ID_RESERVED, BER_ID_BOOLEAN, BER_ID_INTEGER, BER_ID_BITSTRING,\n\t   BER_ID_OCTETSTRING, BER_ID_NULL, BER_ID_OBJECT_IDENTIFIER,\n\t   BER_ID_OBJECT_DESCRIPTOR, BER_ID_EXTERNAL, BER_ID_REAL,\n\t   BER_ID_ENUMERATED, BER_ID_EMBEDDED_PDV, BER_ID_STRING_UTF8, BER_ID_13,\n\t   BER_ID_14, BER_ID_15, BER_ID_SEQUENCE, BER_ID_SET,\n\t   BER_ID_STRING_NUMERIC, BER_ID_STRING_PRINTABLE, BER_ID_STRING_T61,\n\t   BER_ID_STRING_VIDEOTEX, BER_ID_STRING_IA5, BER_ID_TIME_UTC,\n\t   BER_ID_TIME_GENERALIZED, BER_ID_STRING_GRAPHIC, BER_ID_STRING_ISO646,\n\t   BER_ID_STRING_GENERAL, BER_ID_STRING_UNIVERSAL, BER_ID_29,\n\t   BER_ID_STRING_BMP, BER_ID_LAST };\n\n/* The encodings for the universal types */\n\n#define BER_EOC\t\t\t\t\t0\t/* Pseudo-type for first EOC octet */\n#define BER_RESERVED\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_RESERVED )\n#define BER_BOOLEAN\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BOOLEAN )\n#define BER_INTEGER\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_INTEGER )\n#define BER_BITSTRING\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BITSTRING )\n#define BER_OCTETSTRING\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OCTETSTRING )\n#define BER_NULL\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_NULL )\n#define BER_OBJECT_IDENTIFIER\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_IDENTIFIER )\n#define BER_OBJECT_DESCRIPTOR\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_DESCRIPTOR )\n#define BER_EXTERNAL\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EXTERNAL )\n#define BER_REAL\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_REAL )\n#define BER_ENUMERATED\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_ENUMERATED )\n#define BER_EMBEDDED_PDV\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EMBEDDED_PDV )\n#define BER_STRING_UTF8\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UTF8 )\n#define BER_13\t\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_13 )\n#define BER_14\t\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_14 )\n#define BER_15\t\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_15 )\n#define BER_SEQUENCE\t\t\t( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SEQUENCE )\n#define BER_SET\t\t\t\t\t( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SET )\n#define BER_STRING_NUMERIC\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_NUMERIC )\n#define BER_STRING_PRINTABLE\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_PRINTABLE )\n#define BER_STRING_T61\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_T61 )\n#define BER_STRING_VIDEOTEX\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_VIDEOTEX )\n#define BER_STRING_IA5\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_IA5 )\n#define BER_TIME_UTC\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_UTC )\n#define BER_TIME_GENERALIZED\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_GENERALIZED )\n#define BER_STRING_GRAPHIC\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GRAPHIC )\n#define BER_STRING_ISO646\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_ISO646 )\n#define BER_STRING_GENERAL\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GENERAL )\n#define BER_STRING_UNIVERSAL\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UNIVERSAL )\n#define BER_29\t\t\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BER29 )\n#define BER_STRING_BMP\t\t\t( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_BMP )\n\n/* The encodings for constructed, indefinite-length tags and lengths */\n\n#define BER_OCTETSTRING_INDEF\tMKDATA( \"\\x24\\x80\" )\n#define BER_SEQUENCE_INDEF\t\tMKDATA( \"\\x30\\x80\" )\n#define BER_SET_INDEF\t\t\tMKDATA( \"\\x31\\x80\" )\n#define BER_CTAG0_INDEF\t\t\tMKDATA( \"\\xA0\\x80\" )\n#define BER_END_INDEF\t\t\tMKDATA( \"\\x00\\x00\" )\n\n/* Masks to extract information from a tag number */\n\n#define BER_CLASS_MASK\t\t\t0xC0\n#define BER_CONSTRUCTED_MASK\t0x20\n#define BER_SHORT_ID_MASK\t\t0x1F\n\n/* The maximum value for the short tag encoding, and the magic value which \n   indicates that a long encoding of the number is being used */\n\n#define MAX_SHORT_BER_ID\t\t( BER_STRING_BMP + 1 )\n#define LONG_BER_ID\t\t\t\t0x1F\n\n/* Turn an identifier into a context-specific tag, and extract the value from\n   a tag.  Normally these are constructed, but in a few special cases they\n   are primitive */\n\n#define MAKE_CTAG( identifier ) \\\n\t\t( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | ( identifier ) )\n#define MAKE_CTAG_PRIMITIVE( identifier ) \\\n\t\t( BER_CONTEXT_SPECIFIC | ( identifier ) )\n#define EXTRACT_CTAG( tag ) \\\n\t\t( ( tag ) & ~( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tASN.1 Constants and Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Special-case tags.  If DEFAULT_TAG is given the basic type (e.g. INTEGER,\n   ENUMERATED) is used, otherwise the value is used as a context-specific\n   tag.  If NO_TAG is given, processing of the tag is skipped.  If ANY_TAG\n   is given, the tag is ignored.  The parentheses are to catch potential\n   erroneous use in an expression */\n\n#define DEFAULT_TAG\t\t\t( -1 )\n#define NO_TAG\t\t\t\t( -2 )\n#define ANY_TAG\t\t\t\t( -3 )\n\n/* The highest encoded tag value */\n\n#define MAX_TAG\t\t\t\t( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | \\\n\t\t\t\t\t\t\t  MAX_SHORT_BER_ID )\n\n/* The highest allowed raw tag value before encoding as a primitive or\n   constructed tag or before encoding as a content-specific tag.  In \n   addition to the standard MAX_TAG_VALUE we also have a value for universal\n   tags whose basic form is constructed (SETs and SEQUENCES), which would \n   fall outside the normal MAX_TAG_VALUE range.\n\n   Due to CMP's braindamaged use of tag values to communicate message type \n   information we have to be fairly permissive with the context-specific \n   tag range because CMP burns up tag values up to the mid-20s, however we \n   can restrict the range if CMP isn't being used */\n\n#define MAX_TAG_VALUE\t\tMAX_SHORT_BER_ID\n#define MAX_CONSTR_TAG_VALUE BER_SET\n#ifdef USE_CMP\n  #define MAX_CTAG_VALUE\t30\n#else\n  #define MAX_CTAG_VALUE\t10\n#endif /* USE_CMP */\n\n/* The minimum and maximum allowed size for an (encoded) object identifier */\n\n#define MIN_OID_SIZE\t\t5\n#define MAX_OID_SIZE\t\t32\n\n/* When reading an OID selection with readOID() we sometimes need to allow\n   a catch-all default value that's used when nothing else matches.  This is\n   typically used for type-and-value data where we want to ignore anything\n   that we don't recognise.  The following value is used as a match-all\n   wildcard.  It's longer than any normal OID to make it possible to do a\n   quick-reject match based only on the length.  The second byte is set to\n   0x0E (= 14) to make the standard sizeofOID() macro work, since this \n   examines the length field of the encoded OID */\n\n#define WILDCARD_OID\t\t( ( const BYTE * ) \\\n\t\t\t\t\t\t\t  \"\\xFF\\x0E\\xFF\\x00\\xFF\\x00\\xFF\\x00\\xFF\\x00\\xFF\\x00\\xFF\\x00\\xFF\\x00\" )\n#define WILDCARD_OID_SIZE\t16\n\n/* A macro to make make declaring OIDs simpler */\n\n#define MKOID( value )\t\t( ( const BYTE * ) value )\n\n/* Macros and functions to work with indefinite-length tags.  The only ones\n   used are SEQUENCE and [0] (for the outer encapsulation) and OCTET STRING\n   (for the data itself) */\n\n#define writeOctetStringIndef( stream )\tswrite( stream, BER_OCTETSTRING_INDEF, 2 )\n#define writeSequenceIndef( stream )\tswrite( stream, BER_SEQUENCE_INDEF, 2 )\n#define writeSetIndef( stream )\t\t\tswrite( stream, BER_SET_INDEF, 2 )\n#define writeCtag0Indef( stream )\t\tswrite( stream, BER_CTAG0_INDEF, 2 )\n#define writeEndIndef( stream )\t\t\tswrite( stream, BER_END_INDEF, 2 )\n\n#define sizeofEOC()\t\t\t\t\t\t2\nRETVAL_RANGE( FALSE, TRUE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkEOC( INOUT STREAM *stream );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tASN.1 Function Prototypes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/peek at a tag and make sure that it's (approximately) valid, and \n   write a tag.  The latter translates directly to sputc(), but we use a\n   macro to make explicit what's going on */\n\nRETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readTag( INOUT STREAM *stream );\nRETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint peekTag( INOUT STREAM *stream );\n#define writeTag( stream, tag )\tsputc( stream, tag )\n\n/* peekTag() is a somewhat awkward function because it can return an error\n   code alongside the tag, so code like:\n\n\tif( peekTag() == tag1 )\n\t\tstatus = read1();\n\tif( peekTag() == tag2 )\n\t\tstatus = read2();\n\n   to read a sequence of optional elements can conclude with an OK status \n   but an error on the stream if an earlier peekTag() returns an error (so\n   that all sunsequent peekTags() don't match the tag).  To deal with this\n   we define a macro that checks that the status from an earlier read\n   is OK, peeks at the next tag, and checks that the result isn't an error\n   status.  The resulting usage is:\n\n\tstatus = read();\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\tstatus = read(); */\n\n#define checkStatusPeekTag( stream, status, tag ) \\\n\t\t( !cryptStatusError( status ) && \\\n\t\t  ( ( status ) = ( tag ) = peekTag( stream ), !cryptStatusError( status ) ) )\n\n/* Alongside the standard checkStatusPeekTag() we also provide a version\n   that checks whether we should still be looking for new tags, for use\n   when we're reading a SEQUENCE OF/SET OF.\n   \n   Note that this sets status to a non-error/CRYPT_OK value, which means \n   that the status can't be checked using cryptStatusOK() but has to be \n   checked with !cryptStatusError() */\n\n#define checkStatusLimitsPeekTag( stream, status, tag, endPos ) \\\n\t\t( !cryptStatusError( status ) && \\\n\t\t  stell( stream ) < ( endPos ) && \\\n\t\t  ( ( status ) = ( tag ) = peekTag( stream ), !cryptStatusError( status ) ) )\n\n/* Determine the size of an object once it's wrapped up with a tag and\n   length */\n\nRETVAL_LENGTH_NOERROR \\\nlong sizeofObject( IN_LENGTH_Z const long length );\nRETVAL_LENGTH_SHORT_NOERROR \\\nint sizeofShortObject( IN_LENGTH_SHORT_Z const int length );\n\n/* Generalized ASN.1 type manipulation routines.  readRawObject() reads a\n   complete object (including tag and length data) while readUniversal()\n   just skips it.  Since readRawObject() always requires a tag, we don't\n   have the xxx/xxxData() variants that exist for other functions */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversalData( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal( INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readRawObject( INOUT STREAM *stream, \n\t\t\t\t   OUT_BUFFER( bufferMaxLength, *bufferLength ) BYTE *buffer, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( 3 ) const int bufferMaxLength, \n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\tint *bufferLength, \n\t\t\t\t   IN_TAG_ENCODED const int tag );\n\n#define writeRawObject( stream, object, size ) \\\n\t\tswrite( stream, object, size )\n\n/* Routines for handling OBJECT IDENTIFIERS.  The sizeof() macro determines\n   the length of an encoded object identifier as tag + length + value.\n   Write OID routines equivalent to the ones for other ASN.1 types don't\n   exist since OIDs are always read and written as a blob with sread()/\n   swrite().  OIDs are never tagged so we don't need any special-case\n   handling for tags.\n\n   When there's a choice of possible OIDs, the list of OID values and\n   corresponding selection IDs is provided in an OID_INFO structure (we also\n   provide a shortcut readFixedOID() function when there's only a single OID\n   that's valid at that point).  The read OID value is checked against each\n   OID in the OID_INFO list, if a match is found the selectionID is returned.\n\n   The OID_INFO includes a pointer to further user-supplied information\n   related to this OID that may be used by the user, set when the OID list\n   is initialised.  For example it could point to OID-specific handlers for\n   the data.  When the caller needs to work with the extraInfo field, it's\n   necessary to return the complete OID_INFO entry rather than just the\n   selection ID, which is done by the ..Ex() form of the function */\n\ntypedef struct {\n\tconst BYTE *oid;\t\t/* OID */\n\tconst int selectionID;\t/* Value to return for this OID */\n\tconst void *extraInfo;\t/* Additional info for this selection */\n\t} OID_INFO;\n\n#define sizeofOID( oid )\t( 1 + 1 + ( int ) oid[ 1 ] )\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readOID( INOUT STREAM *stream, \n\t\t\t IN_ARRAY( noOidSelectionEntries ) \\\n\t\t\t const OID_INFO *oidSelection, \n\t\t\t IN_RANGE( 1, 50 ) const int noOidSelectionEntries,\n\t\t\t OUT_RANGE( CRYPT_ERROR, noOidSelectionEntries ) \\\n\t\t\t int *selectionID );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readOIDEx( INOUT STREAM *stream, \n\t\t\t   IN_ARRAY( noOidSelectionEntries ) \\\n\t\t\t   const OID_INFO *oidSelection, \n\t\t\t   IN_RANGE( 1, 50 ) const int noOidSelectionEntries,\n\t\t\t   OUT_OPT_PTR_COND const OID_INFO **oidSelectionValue );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedOID( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( oidLength ) \\\n\t\t\t\t  const BYTE *oid, IN_LENGTH_OID const int oidLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readEncodedOID( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER( oidMaxLength, *oidLength ) BYTE *oid, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 5 ) const int oidMaxLength, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( oidMaxLength ) int *oidLength, \n\t\t\t\t\tIN_TAG_ENCODED const int tag );\n#define writeOID( stream, oid ) \\\n\t\t\t\t  swrite( ( stream ), ( oid ), sizeofOID( oid ) )\n\n/* Routines for handling large integers.  When we're writing these we can't\n   use sizeofObject() directly because the internal representation is\n   unsigned whereas the encoded form is signed.  The following macro performs\n   the appropriate conversion on the data length before passing it on to\n   sizeofObject() */\n\n#define sizeofInteger( value, valueLength ) \\\n\t\t( int ) sizeofObject( ( valueLength ) + \\\n\t\t\t\t\t\t\t  ( ( *( BYTE * )( value ) & 0x80 ) ? 1 : 0 ) )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readIntegerTag( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER_OPT( integerMaxLength, \\\n\t\t\t\t\t\t\t\t\t*integerLength ) BYTE *integer, \n\t\t\t\t\tIN_LENGTH_SHORT const int integerMaxLength, \n\t\t\t\t\tOUT_OPT_LENGTH_SHORT_Z int *integerLength, \n\t\t\t\t\tIN_TAG_EXT const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( integerLength ) const BYTE *integer, \n\t\t\t\t  IN_LENGTH_SHORT const int integerLength, \n\t\t\t\t  IN_TAG const int tag );\n\n#define readIntegerData( stream, integer, integerLength, maxLength )\t\\\n\t\treadIntegerTag( stream, integer, integerLength, maxLength, NO_TAG )\n#define readInteger( stream, integer, integerLength, maxLength )\t\\\n\t\treadIntegerTag( stream, integer, integerLength, maxLength, DEFAULT_TAG )\n\n/* Routines for handling bignums.  We use void * rather than BIGNUM * to save\n   having to include the bignum header everywhere where ASN.1 is used */\n\n#define sizeofBignum( bignum ) \\\n\t\t( ( int ) sizeofObject( signedBignumSize( bignum ) ) )\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *READ_BIGNUM_FUNCTION )( INOUT STREAM *stream, INOUT void *bignum, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t\t\t\t   IN_OPT const void *maxRange, \n\t\t\t\t\t\t\t\t\t   IN_TAG_EXT const int tag );\n\nRETVAL_RANGE_NOERROR( 0, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint signedBignumSize( IN TYPECAST( BIGNUM * ) const void *bignum );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumTag( INOUT STREAM *stream, INOUT void *bignum, \n\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t   IN_LENGTH_PKC const int maxLength, \n\t\t\t\t   IN_OPT const void *maxRange, \n\t\t\t\t   IN_TAG_EXT const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumTag( INOUT STREAM *stream, \n\t\t\t\t\tIN const void *bignum, \n\t\t\t\t\tIN_TAG const int tag );\n\n#define readBignum( stream, bignum, minLen, maxLen, maxRange ) \\\n\t\treadBignumTag( stream, bignum, minLen, maxLen, maxRange, DEFAULT_TAG )\n#define writeBignum( stream, bignum ) \\\n\t\twriteBignumTag( stream, bignum, DEFAULT_TAG )\n\n/* Special-case bignum read routine that explicitly checks for a too-short \n   key and returns CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA \n   that'd otherwise be returned */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumChecked( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t   IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t   IN_OPT const void *maxRange );\n\n/* Another special-case bignum routine that verifies that the bignum data to\n   be read corresponds to the in-memory bignum.  This is used after calling\n   readBignum() to verify that no corruption occurred when the bignum data \n   was transferred into the in-memory forum */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkBignumRead( INOUT STREAM *stream, INOUT void *bignum, \n\t\t\t\t\t STDC_UNUSED IN_LENGTH_PKC const int dummy1, \n\t\t\t\t\t STDC_UNUSED IN_LENGTH_PKC const int dummy2, \n\t\t\t\t\t STDC_UNUSED IN_OPT const void *dummy3, \n\t\t\t\t\t IN_TAG_EXT const int tag );\n\n/* Generally most integers will be non-bignum values, so we also define\n   routines to handle values that will fit into a machine word */\n\n#define sizeofShortInteger( value )\t\\\n\t( ( ( value ) < 0x80 ) ? 3 : \\\n\t  ( ( ( long ) value ) < 0x8000L ) ? 4 : \\\n\t  ( ( ( long ) value ) < 0x800000L ) ? 5 : \\\n\t  ( ( ( long ) value ) < 0x80000000UL ) ? 6 : 7 )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeShortInteger( INOUT STREAM *stream, \n\t\t\t\t\t   IN_INT_Z const long integer, \n\t\t\t\t\t   IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readShortIntegerTag( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_INT_Z long *value, \n\t\t\t\t\t\t IN_TAG_EXT const int tag );\n\n#define readShortIntegerData( stream, integer )\t\\\n\t\treadShortIntegerTag( stream, integer, NO_TAG )\n#define readShortInteger( stream, integer )\t\\\n\t\treadShortIntegerTag( stream, integer, DEFAULT_TAG )\n\n/* Routines for handling enumerations */\n\n#define sizeofEnumerated( value )\t( ( ( value ) < 128 ) ? 3 : 4 )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeEnumerated( INOUT STREAM *stream, \n\t\t\t\t\t IN_RANGE( 0, 999 ) const int enumerated, \n\t\t\t\t\t IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readEnumeratedTag( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_INT_Z int *enumeration, \n\t\t\t\t\t   IN_TAG_EXT const int tag );\n\n#define readEnumeratedData( stream, enumeration ) \\\n\t\treadEnumeratedTag( stream, enumeration, NO_TAG )\n#define readEnumerated( stream, enumeration ) \\\n\t\treadEnumeratedTag( stream, enumeration, DEFAULT_TAG )\n\n/* Routines for handling booleans */\n\n#define sizeofBoolean()\t( sizeof( BYTE ) + sizeof( BYTE ) + sizeof( BYTE ) )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBoolean( INOUT STREAM *stream, const BOOLEAN boolean, \n\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBooleanTag( INOUT STREAM *stream, \n\t\t\t\t\tOUT_OPT_BOOL BOOLEAN *boolean, \n\t\t\t\t\tIN_TAG_EXT const int tag );\n\n#define readBooleanData( stream, boolean ) \\\n\t\treadBooleanTag( stream, boolean, NO_TAG )\n#define readBoolean( stream, boolean ) \\\n\t\treadBooleanTag( stream, boolean, DEFAULT_TAG )\n\n/* Routines for handling null values */\n\n#define sizeofNull()\t( sizeof( BYTE ) + sizeof( BYTE ) )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeNull( INOUT STREAM *stream, IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readNullTag( INOUT STREAM *stream, IN_TAG_EXT const int tag );\n\n#define readNullData( stream )\treadNullTag( stream, NO_TAG )\n#define readNull( stream )\t\treadNullTag( stream, DEFAULT_TAG )\n\n/* Routines for handling octet strings */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeOctetString( INOUT STREAM *stream, \n\t\t\t\t\t  IN_BUFFER( length ) \\\n\t\t\t\t\t  const BYTE *string, \n\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readOctetStringTag( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER( maxLength, *stringLength ) \\\n\t\t\t\t\t\t\tBYTE *string, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\tint *stringLength, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int minLength, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxLength, \n\t\t\t\t\t\tIN_TAG_EXT const int tag );\n\n#define readOctetStringData( stream, string, stringLength, minLength, maxLength ) \\\n\t\treadOctetStringTag( stream, string, stringLength, minLength, maxLength, NO_TAG )\n#define readOctetString( stream, string, stringLength, minLength, maxLength ) \\\n\t\treadOctetStringTag( stream, string, stringLength, minLength, maxLength, DEFAULT_TAG )\n\n/* Routines for handling character strings.  There are a number of oddball\n   character string types that are all handled through the same functions -\n   it's not worth having a seperate function to handle each of the half-dozen\n   types */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCharacterString( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_BUFFER( length ) const void *string, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t\t  IN_TAG_ENCODED const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint readCharacterString( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_BUFFER_OPT( stringMaxLength, *stringLength ) \\\n\t\t\t\t\t\t\tvoid *string, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\t\tint *stringLength, \n\t\t\t\t\t\t IN_TAG_EXT const int tag );\n\n/* Routines for handling bit strings.  The sizeof() values are 3 bytes for\n   the tag, length, and surplus-bits value, and the data itself */\n\n#define sizeofBitString( value )\t\\\n\t( 3 + ( ( ( ( long ) value ) > 0xFFFFFFL ) ? 4 : \\\n\t\t\t( ( ( long ) value ) > 0xFFFFL ) ? 3 : \\\n\t\t\t( ( value ) > 0xFF ) ? 2 : ( value ) ? 1 : 0 ) )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBitString( INOUT STREAM *stream, \n\t\t\t\t\tIN_INT_Z const int bitString, \n\t\t\t\t\tIN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBitStringTag( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_OPT_INT_Z int *bitString, \n\t\t\t\t\t  IN_TAG_EXT const int tag );\n\n#define readBitStringData( stream, bitString ) \\\n\t\treadBitStringTag( stream, bitString, NO_TAG )\n#define readBitString( stream, bitString ) \\\n\t\treadBitStringTag( stream, bitString, DEFAULT_TAG )\n\n/* Routines for handling UTC and Generalized time */\n\n#define sizeofUTCTime()\t\t\t( 1 + 1 + 13 )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUTCTime( INOUT STREAM *stream, const time_t timeVal, \n\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readUTCTimeTag( INOUT STREAM *stream, OUT time_t *timeVal, \n\t\t\t\t\tIN_TAG_EXT const int tag );\n\n#define readUTCTimeData( stream, time )\treadUTCTimeTag( stream, time, NO_TAG )\n#define readUTCTime( stream, time )\t\treadUTCTimeTag( stream, time, DEFAULT_TAG )\n\n#define sizeofGeneralizedTime()\t( 1 + 1 + 15 )\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeGeneralizedTime( INOUT STREAM *stream, const time_t timeVal, \n\t\t\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGeneralizedTimeTag( INOUT STREAM *stream, OUT time_t *timeVal, \n\t\t\t\t\t\t\tIN_TAG_EXT const int tag );\n\n#define readGeneralizedTimeData( stream, time )\t\\\n\t\treadGeneralizedTimeTag( stream, time, NO_TAG )\n#define readGeneralizedTime( stream, time )\t\\\n\t\treadGeneralizedTimeTag( stream, time, DEFAULT_TAG )\n\n/* Utilitity routines for reading and writing constructed objects and\n   equivalent holes.  As with the other ASN.1-read routines we need\n   variants to check for different permitted conditions:\n\n\tLength = 1 ... MAX, most cases.\n\tLength = 0 ... MAX, occasional cases where a zero-length SEQUENCE\n\t\t\t\t\t\tis permitted.\n\tLength = 1 ... MAX || INDEF.\n   \n   The difference between writeOctet/BitStringHole() and writeGenericHole() \n   is that the octet/bit-string versions create a normal or context-\n   specific-tagged string while the generic version creates a pure hole with \n   no processing of tags.\n\n   Note that readGenericHole() takes a full encoded tag value, since we\n   don't know what form it has to be turned into when reading the tag.\n   In addition it has to be able to read zero-length values in order to\n   deal with broken encodings */\n\ntypedef enum { \n\tLENGTH_CHECK_NONE,\t\t/* No length check type */\n\tLENGTH_CHECK_ZERO,\t\t/* 0 ... MAX */\n\tLENGTH_CHECK_NONZERO,\t/* 1 ... MAX */\n\tLENGTH_CHECK_NONZERO_INDEF,\t/* 1 ... MAX || INDEF */\n\tLENGTH_CHECK_LAST\t\t/* Last possible length check type */\n\t} LENGTH_CHECK_TYPE;\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readSequenceExt( INOUT STREAM *stream,\n\t\t\t\t\t /* PARAMCHECK */ int *length,\n\t\t\t\t\t IN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType );\n#define readSequence( stream, length ) \\\n\t\treadSequenceExt( stream, length, LENGTH_CHECK_NONZERO )\n#define readSequenceZ( stream, length ) \\\n\t\treadSequenceExt( stream, length, LENGTH_CHECK_ZERO )\n#define readSequenceI( stream, length ) \\\n\t\treadSequenceExt( stream, length, LENGTH_CHECK_NONZERO_INDEF )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readSetExt( INOUT STREAM *stream,\n\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType );\n#define readSet( stream, length ) \\\n\t\treadSetExt( stream, length, LENGTH_CHECK_NONZERO )\n#define readSetZ( stream, length ) \\\n\t\treadSetExt( stream, length, LENGTH_CHECK_ZERO )\n#define readSetI( stream, length ) \\\n\t\treadSetExt( stream, length, LENGTH_CHECK_NONZERO_INDEF )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readConstructedExt( INOUT STREAM *stream,\n\t\t\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\t\t\tIN_TAG const int tag,\n\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType );\n#define readConstructed( stream, length, tag ) \\\n\t\treadConstructedExt( stream, length, tag, LENGTH_CHECK_NONZERO )\n#define readConstructedZ( stream, length, tag ) \\\n\t\treadConstructedExt( stream, length, tag, LENGTH_CHECK_ZERO )\n#define readConstructedI( stream, length, tag ) \\\n\t\treadConstructedExt( stream, length, tag, LENGTH_CHECK_NONZERO_INDEF )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readOctetStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int minLength, \n\t\t\t\t\t\t IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBitStringHole( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,\n\t\t\t\t\t   IN_LENGTH_SHORT const int minLength,\n\t\t\t\t\t   IN_TAG const int tag );\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_MIN( minLength ) ) \\\nint readGenericHoleExt( INOUT STREAM *stream,\n\t\t\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int minLength,\n\t\t\t\t\t\tIN_TAG_ENCODED const int tag,\n\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType );\n#define readGenericHole( stream, length, minLength, tag ) \\\n\t\treadGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_NONZERO )\n#define readGenericHoleZ( stream, length, minLength, tag ) \\\n\t\treadGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_ZERO )\n#define readGenericHoleI( stream, length, minLength, tag ) \\\n\t\treadGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_NONZERO_INDEF )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeSequence( INOUT STREAM *stream, \n\t\t\t\t   IN_LENGTH_Z const long length );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeSet( INOUT STREAM *stream, \n\t\t\t  IN_LENGTH_SHORT_Z const int length );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeConstructed( INOUT STREAM *stream, \n\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOctetStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t\t  IN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBitStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int length,\n\t\t\t\t\t\tIN_TAG const int tag );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeGenericHole( INOUT STREAM *stream, \n\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t  IN_TAG const int tag );\n\n/* Read a generic object header, used to find the length of an object being\n   read as a blob */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGenericObjectHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t\t const BOOLEAN isLongObject );\n\n/* Read an arbitrary-length constructed object's data into a memory buffer.  \n   This is the arbitrary-length form of readRawObject() */\n\n#define OBJECT_HEADER_DATA_SIZE\t\t16\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readRawObjectAlloc( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER_ALLOC_OPT( *objectLengthPtr ) \\\n\t\t\t\t\t\t\tvoid **objectPtrPtr,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\tint *objectLengthPtr,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( OBJECT_HEADER_DATA_SIZE ) \\\n\t\t\t\t\t\t\tconst int minLength,\n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxLength );\n\n/* Determine the length of an ASN.1-encoded object (this just reads the\n   outer length if present, but will burrow down into the object if necessary\n   if the length is indefinite) and check that an object has valid encoding.\n\n   There are four variants of this check, of the type subtypes the non-length \n   option is a generic check and the length option returns the actual parsed \n   object size, which may be smaller than the supposed size.  \n   \n   Beyond this there are two different types of checks, the \n   checkCertObjectEncoding() form checks for the presence of OCTET STRING \n   and BIT STRING holes, the checkObjectEncoding() form checks either less \n   aggressively or not at all (see the long comment in asn1_chk.c for \n   details).  This is possible because non-certificate objects use the CMS\n   form for attributes, SEQUENCE { OID, SET {} } rather than the certificate\n   form, SEQUENCE { OID, OCTET STRING {} } */\n\ntypedef enum {\n\tCHECK_ENCODING_NONE,\t\t/* Don't check for encapsulated content */\n\tCHECK_ENCODING_ENCAPS,\t\t/* Check for any encapsulated content */\n\tCHECK_ENCODING_SEMIENCAPS,\t/* Check for some encapsulated content */\n\tCHECK_ENCODING_LAST\t\t\t/* Last possible check type */\n\t} CHECK_ENCODING_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getStreamObjectLength( INOUT STREAM *stream, OUT_DATALENGTH_Z int *length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getObjectLength( IN_BUFFER( objectLength ) \\\n\t\t\t\t\t const void *objectPtr, \n\t\t\t\t\t IN_DATALENGTH const int objectLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t IN_DATALENGTH const int objectLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkObjectEncodingLength( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *objectActualSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t\t IN_DATALENGTH const int objectLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkCertObjectEncodingLength( IN_BUFFER( objectLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *objectPtr, \n\t\t\t\t\t\t\t\t   IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *objectActualSize );\n\n/* Full-length equivalents of length/encapsulating-object read routines.\n   These are used explicitly in the rare situations where long lengths are\n   valid, all other ASN.1 code only works with short lengths.  Because these\n   can be quite long, they allow definite or indefinite lengths.\n\n   Note that readLongGenericHole() takes a full encoded tag value, since we \n   don't know what form it has to be turned into when reading the tag */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongSequence( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_OPT_LENGTH_INDEF long *length );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongSet( INOUT STREAM *stream, OUT_OPT_LENGTH_INDEF long *length );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongConstructed( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t IN_TAG const int tag );\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongGenericHoleExt( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT_OPT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t\tIN_TAG_ENCODED const int tag,\n\t\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType );\n#define readLongGenericHole( stream, length, tag ) \\\n\t\treadLongGenericHoleExt( stream, length, tag, LENGTH_CHECK_NONZERO )\n#define readLongGenericHoleZ( stream, length, tag ) \\\n\t\treadLongGenericHoleExt( stream, length, tag, LENGTH_CHECK_ZERO )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getLongStreamObjectLength( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z long *length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getLongObjectLength( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t IN_DATALENGTH const long objectLength,\n\t\t\t\t\t\t OUT_DATALENGTH_Z long *length );\n\n#endif /* USE_INT_ASN1 */\n#endif /* !_ASN1_DEFINED */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_algid.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tASN.1 Algorithm Identifier Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tObject/Algorithm Identifier Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the AlgorithmIdentifier OID table */\n\n#if defined( INC_ALL )\n  #include \"asn1_oids.h\"\n#else\n  #include \"enc_dec/asn1_oids.h\"\n#endif /* Compiler-specific includes */\n\n/* Map an OID to an algorithm type */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5, 6 ) ) \\\nstatic int oidToAlgorithm( IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t   IN_RANGE( 1, MAX_OID_SIZE ) const int oidLength, \n\t\t\t\t\t\t   IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type,\n\t\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t\t   OUT_INT_Z int *param1, \n\t\t\t\t\t\t   OUT_INT_Z int *param2 )\n\t{\n\tBYTE oidByte;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( param1, sizeof( int ) ) );\n\tassert( isWritePtr( param2, sizeof( int ) ) );\n\n\tREQUIRES( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\tREQUIRES( isEnumRange( type, ALGOID_CLASS ) );\n\n\t/* Clear return values */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\t*param1 = *param2 = 0;\n\n\t/* If the OID is shorter than the minimum possible algorithm OID value, \n\t   don't try and process it */\n\tif( oidLength < 7 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\toidByte = oid[ 6 ];\n\n\t/* Look for a matching OID.  For quick-reject matching we check the byte\n\t   furthest inside the OID that's likely to not match (large groups of \n\t   OIDs have common prefixes due to being in the same arc), this rejects \n\t   the majority of mismatches without requiring a full comparison */\n\tLOOP_LARGE( i = 0, algoIDinfoTbl[ i ].algorithm != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ), i++ )\n\t\t{\n\t\tconst ALGOID_INFO *algoIDinfoPtr = &algoIDinfoTbl[ i ];\n\n\t\tif( algoIDinfoPtr->algoClass == type && \\\n\t\t\toidLength == sizeofOID( algoIDinfoPtr->oid ) && \\\n\t\t\talgoIDinfoPtr->oid[ 6 ] == oidByte && \\\n\t\t\t!memcmp( algoIDinfoPtr->oid, oid, oidLength ) )\n\t\t\t{\n\t\t\t*cryptAlgo = algoIDinfoPtr->algorithm;\n\t\t\t*param1 = algoIDinfoPtr->subAlgo;\n\t\t\t*param2 = algoIDinfoPtr->parameter;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ) );\n\n\t/* No algorithm for this OID found */\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n/* Map an algorithm and optional parameters (sub-algorithm/mode and encoding/\n   key size/block size) to an OID.  This can be called either to check \n   whether an algorithm is encodable (checkValid = FALSE) or as part of an \n   actual encoding, throwing an exception if the parameters can't be encoded \n   (checkValid = TRUE).\n   \n   The parameters passed to this are rather complex, and come in the \n   following variants:\n\n\tcryptAlgo\t\tsubAlgo\t\tparameter\n\t---------\t\t-------\t\t---------\n\tAny\t\t\t\t0\t\t\t0\n\tConv\t\t\tMode\t\t0\n\tConv\t\t\tMode\t\tKeysize\n\tHash\t\t\t0\t\t\tHash width\n\tPKC-Sig\t\t\tHash\t\t0\n\tPKC-Sig\t\t\tHash\t\tHash width\n\tPKC-Enc\t\t\t0\t\t\tEncoding */\n\n#define ALGOTOOID_REQUIRE_VALID\t\tTRUE\n#define ALGOTOOID_CHECK_VALID\t\tFALSE\n\nCHECK_RETVAL_PTR \\\nstatic const BYTE *algorithmToOID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t   IN_ALGO_OPT const int subAlgo,\n\t\t\t\t\t\t\t\t   IN_RANGE( 0, ALGOID_ENCODING_LAST ) \\\n\t\t\t\t\t\t\t\t\t\tconst int parameter,\n\t\t\t\t\t\t\t\t   const BOOLEAN checkValid )\n\t{\n\tconst BYTE *oid = NULL;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES_N( ( subAlgo == 0 && parameter == 0 ) || \\\n\t\t\t\t( isConvAlgo( cryptAlgo ) && \\\n\t\t\t\t  subAlgo > CRYPT_MODE_NONE && \\\n\t\t\t\t  subAlgo < CRYPT_MODE_LAST && \\\n\t\t\t\t  parameter >= 0 && parameter <= CRYPT_MAX_KEYSIZE ) || \\\n\t\t\t\t( ( isParameterisedHashAlgo( cryptAlgo ) || \\\n\t\t\t\t\tisParameterisedMacAlgo( cryptAlgo) ) && \\\n\t\t\t\t  subAlgo == 0 && \\\n\t\t\t\t  parameter >= MIN_HASHSIZE && parameter <= CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t\t( isSigAlgo( cryptAlgo ) && \\\n\t\t\t\t  isHashAlgo( subAlgo ) && \\\n\t\t\t\t  ( parameter == 0 || \\\n\t\t\t\t    ( parameter >= MIN_HASHSIZE && \\\n\t\t\t\t\t  parameter <= CRYPT_MAX_HASHSIZE ) ) ) || \\\n\t\t\t\t( isCryptAlgo( cryptAlgo ) && \\\n\t\t\t\t  subAlgo == 0 && \\\n\t\t\t\t  parameter > ALGOID_ENCODING_NONE && \\\n\t\t\t\t  parameter < ALGOID_ENCODING_LAST ) );\n\tREQUIRES_N( checkValid == TRUE || checkValid == FALSE );\n\n\tLOOP_LARGE( i = 0, algoIDinfoTbl[ i ].algorithm != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ), i++ )\n\t\t{\n\t\tif( algoIDinfoTbl[ i ].algorithm == cryptAlgo )\n\t\t\t{\n\t\t\toid = algoIDinfoTbl[ i ].oid;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ) );\n\tif( subAlgo != 0 )\n\t\t{\n\t\toid = NULL;\n\t\tLOOP_LARGE_CHECKINC( algoIDinfoTbl[ i ].algorithm == cryptAlgo && \\\n\t\t\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ), \n\t\t\t\t\t\t\t i++ )\n\t\t\t{\n\t\t\tif( algoIDinfoTbl[ i ].subAlgo == subAlgo )\n\t\t\t\t{\n\t\t\t\toid = algoIDinfoTbl[ i ].oid;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ) );\n\t\t}\n\tif( parameter != 0 )\n\t\t{\n\t\toid = NULL;\n\t\tLOOP_LARGE_CHECKINC( algoIDinfoTbl[ i ].algorithm == cryptAlgo && \\\n\t\t\t\t\t\t\t algoIDinfoTbl[ i ].subAlgo == subAlgo && \\\n\t\t\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ),\n\t\t\t\t\t\t\t i++ )\n\t\t\t{\n\t\t\tif( algoIDinfoTbl[ i ].parameter == parameter )\n\t\t\t\t{\n\t\t\t\toid = algoIDinfoTbl[ i ].oid;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( i < FAILSAFE_ARRAYSIZE( algoIDinfoTbl, ALGOID_INFO ) );\n\t\t}\n\tif( oid != NULL )\n\t\treturn( oid );\n\tif( !checkValid )\n\t\treturn( NULL );\n\tretIntError_Null();\n\t}\n\n/* Read the start of an AlgorithmIdentifier record, used by a number of\n   routines.  The parameters are as follows:\n   \n\tEncryption: param1 = Mode for algorithm.\n\tPKC enc: param2 = Encoding format specifier. \n\tPKC sig: param1 = Hash algorithm used with signature algorithm,\n\t\t\t param2 = Optional hash width for variable-width hashes.\n\tHash: param2 = Optional hash width for variable-width hashes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readAlgoIDheader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t\t\t OUT_OPT_RANGE( 0, 999 ) int *param1, \n\t\t\t\t\t\t\t OUT_OPT_RANGE( 0, 999 ) int *param2, \n\t\t\t\t\t\t\t OUT_OPT_LENGTH_SHORT_Z int *extraLength, \n\t\t\t\t\t\t\t IN_TAG const int tag,\n\t\t\t\t\t\t\t IN_ENUM( ALGOID_CLASS ) \\\n\t\t\t\t\t\t\t\t\tconst ALGOID_CLASS_TYPE type )\n\t{\n\tCRYPT_ALGO_TYPE localCryptAlgo;\n\tBYTE oidBuffer[ MAX_OID_SIZE + 8 ];\n\tint oidLength, algoParam1, algoParam2, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( param1 == NULL || isWritePtr( param1, sizeof( int ) ) );\n\tassert( param2 == NULL || isWritePtr( param2, sizeof( int ) ) );\n\tassert( extraLength == NULL || \\\n\t\t\tisWritePtr( extraLength, sizeof( int ) ) );\n\n\tREQUIRES_S( ( param1 == NULL && param2 == NULL ) || \\\n\t\t\t\t( param1 != NULL && param2 != NULL ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isEnumRange( type, ALGOID_CLASS ) );\n\t\n\t/* Clear the return values */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\tif( param1 != NULL )\n\t\t*param1 = *param2 = 0;\n\tif( extraLength != NULL )\n\t\t*extraLength = 0;\n\n\t/* Determine the algorithm information based on the AlgorithmIdentifier\n\t   field */\n\tif( tag == DEFAULT_TAG )\n\t\treadSequence( stream, &length );\n\telse\n\t\treadConstructed( stream, &length, tag );\n\tstatus = readEncodedOID( stream, oidBuffer, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength -= oidLength;\n\tif( oidLength != sizeofOID( oidBuffer ) || \\\n\t\t!isShortIntegerRange( length ) )\n\t\t{\n\t\t/* It's a stream-related error, make it persistent */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tstatus = oidToAlgorithm( oidBuffer, oidLength, type, &localCryptAlgo, \n\t\t\t\t\t\t\t &algoParam1, &algoParam2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*cryptAlgo = localCryptAlgo;\n\tif( param1 != NULL )\n\t\t{\n\t\t*param1 = algoParam1;\n\t\t*param2 = algoParam2;\n\t\t}\n\n\t/* If the caller has specified that there should be no parameters \n\t   present, make sure that there's either no data or an ASN.1 NULL or\n\t   zero-length SEQUENCE (for OAEP) present and nothing else */\n\tif( extraLength == NULL )\n\t\t{\n\t\t/* If there are no parameters then we're done */\n\t\tif( length <= 0 )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* There are parameters, usually an ASN.1 NULL but for OAEP an\n\t\t   empty SEQUENCE */\n#ifdef USE_OAEP\n\t\tif( algoParam2 == ALGOID_ENCODING_OAEP )\n\t\t\t{\n\t\t\tstatus = readSequenceZ( stream, &length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( length != 0 )\n\t\t\t\t{\n\t\t\t\t/* It's a stream-related error, make it persistent */\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_OAEP */\n\t\treturn( readNull( stream ) );\n\t\t}\n\n\t/* If the parameters are null parameters, check them and exit */\n\tif( length == sizeofNull() )\n\t\treturn( readNull( stream ) );\n\n\t/* Handle any remaining parameters */\n\t*extraLength = length;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tEncryptionAlgorithmIdentifier Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* EncryptionAlgorithmIdentifier parameters:\n\n\taesXcbc: AES FIPS\n\n\t\tiv\t\t\t\tOCTET STRING SIZE (16)\n\n\taesXcfb: AES FIPS\n\n\t\tSEQUENCE {\n\t\t\tiv\t\t\tOCTET STRING SIZE (16),\n\t\t\tnoOfBits\tINTEGER (128)\n\t\t\t}\n\n\tcast5cbc: RFC 2144\n\t\tSEQUENCE {\n\t\t\tiv\t\t\tOCTET STRING DEFAULT 0,\n\t\t\tkeyLen\t\tINTEGER (128)\n\t\t\t}\n\n\trc2CBC: RFC 2311\n\t\tSEQUENCE {\n\t\t\trc2Param\tINTEGER (58),\t-- 128 bit key\n\t\t\tiv\t\t\tOCTET STRING SIZE (8)\n\t\t\t}\n\n\trc4: (Unsure where this one is from)\n\t\tNULL\n\n   Because of the somewhat haphazard nature of encryption\n   AlgorithmIdentifier definitions we can only handle the following\n   algorithm/mode combinations:\n\n\tAES ECB, CBC, CFB\n\tCAST128 CBC\n\tDES ECB, CBC, CFB\n\t3DES ECB, CBC, CFB\n\tRC2 ECB, CBC\n\tRC4\n\n   In addition to the standard AlgorithmIdentifiers there's also a generic-\n   secret pseudo-algorithm used for key-diversification purposes:\n\n\tauthEnc128/authEnc256: RFC 6476\n\t\tSEQUENCE {\n\t\t\tprf ::= [ 0 ] SEQUENCE {\n\t\t\t\tsalt\t\t\tOCTET STRING SIZE(0),\n\t\t\t\titerationCount\tINTEGER (1),\n\t\t\t\tprf\t\t\t\tAlgorithmIdentifier\n\t\t\t\t} DEFAULT PBKDF2,\n\t\t\tencAlgo\t\tAlgorithmIdentifier,\n\t\t\tmacAlgo\t\tAlgorithmIdentifier */\n\n/* Magic value to denote 128-bit RC2 keys */\n\n#define RC2_KEYSIZE_MAGIC\t\t58\n\n/* Read an EncryptionAlgorithmIdentifier/DigestAlgorithmIdentifier */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readAuthEncParamData( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *offset,\n\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\t\t\tint *length,\n\t\t\t\t\t\t\t\t IN_TAG_ENCODED const int tag,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int maxLength )\n\t{\n\tconst int paramStart = stell( stream );\n\tint paramLength, tagValue, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( offset, sizeof( int ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES_S( tag >= 1 && tag < MAX_TAG );\n\tREQUIRES_S( isShortIntegerRangeNZ( maxLength ) );\n\tREQUIRES_S( !cryptStatusError( paramStart ) );\n\n\t/* Clear return values */\n\t*offset = *length = 0;\n\n\t/* Get the start and length of the parameter data */\n\tstatus = tagValue = readTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tagValue != tag )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = readUniversalData( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tparamLength = stell( stream ) - paramStart;\n\n\t/* Make sure that it appears valid */\n\tif( paramLength < 8 || paramLength > maxLength )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t*offset = paramStart;\n\t*length = paramLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readGenericSecretParams( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\tINOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_Z const int startOffset )\n\t{\n\tconst int maxLength = AUTHENCPARAM_MAX_SIZE - 8;\t/* -8 for outer wrapper + OID */\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isShortIntegerRange( startOffset ) );\n\n\t/* For AuthEnc data we need to MAC the encoded parameter data after \n\t   we've processed it, so we save a copy for the caller.  In addition \n\t   the caller needs a copy of the encryption and MAC parameters to use \n\t   when creating the encryption and MAC contexts, so we record the \n\t   position within the encoded parameter data.  First we tunnel down \n\t   into the parameter data to find the locations of the encryption and \n\t   MAC parameters */\n\tstatus = readSequence( stream, NULL );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\t/* Optional KDF parameters */\n\t\tstatus = readAuthEncParamData( stream,\n\t\t\t\t\t\t\t\t\t   &queryInfo->kdfParamStart, \n\t\t\t\t\t\t\t\t\t   &queryInfo->kdfParamLength, \n\t\t\t\t\t\t\t\t\t   MAKE_CTAG( 0 ), maxLength - 16 );\n\t\t\t\t\t\t\t\t\t   /* -16 for enc/MAC param.*/\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Read the encryption and MAC algorithm parameters */\n\tstatus = readAuthEncParamData( stream,\n\t\t\t\t\t\t\t\t   &queryInfo->encParamStart, \n\t\t\t\t\t\t\t\t   &queryInfo->encParamLength, \n\t\t\t\t\t\t\t\t   BER_SEQUENCE,\n\t\t\t\t\t\t\t\t   maxLength - \\\n\t\t\t\t\t\t\t\t\t\t( queryInfo->kdfParamLength + 8 ) );\n\t\t\t\t\t\t\t\t\t\t/* -8 for MAC param */\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readAuthEncParamData( stream,\n\t\t\t\t\t\t\t\t   &queryInfo->macParamStart, \n\t\t\t\t\t\t\t\t   &queryInfo->macParamLength,\n\t\t\t\t\t\t\t\t   BER_SEQUENCE,\n\t\t\t\t\t\t\t\t   maxLength - \\\n\t\t\t\t\t\t\t\t\t\t( queryInfo->kdfParamLength + \\\n\t\t\t\t\t\t\t\t\t\t  queryInfo->encParamLength ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* The encryption/MAC parameter positions are taken from the start of \n\t   the encoded data, not from the start of the stream so we need to\n\t   adjust the position by the offset from the start */\n\tqueryInfo->kdfParamStart -= startOffset;\n\tqueryInfo->encParamStart -= startOffset;\n\tqueryInfo->macParamStart -= startOffset;\n\n\t/* Finally, save the overall encoded parameter data for the caller to\n\t   process */\n\tlength = stell( stream ) - startOffset;\n\tif( length <= 16 || length > AUTHENCPARAM_MAX_SIZE )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tstatus = sseek( stream, startOffset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sread( stream, queryInfo->authEncParamData, length );\n\tif( cryptStatusOK( status ) )\n\t\tqueryInfo->authEncParamLength = length;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readAlgoIDInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t   IN_TAG const int tag,\n\t\t\t\t\t\t   IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type )\n\t{\n\tconst int startOffset = stell( stream );\n\tint param1, param2, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isEnumRange( type, ALGOID_CLASS ) );\n\tREQUIRES_S( !cryptStatusError( startOffset ) );\n\n\t/* Read the AlgorithmIdentifier header and OID */\n\tstatus = readAlgoIDheader( stream, &queryInfo->cryptAlgo, &param1, \n\t\t\t\t\t\t\t   &param2, &length, tag, type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isConvAlgo( queryInfo->cryptAlgo ) )\n\t\t{\n\t\t/* For conventional algorithms, the parameter is the encryption mode\n\t\t   and the optional second parameter is the key size */\n\t\tqueryInfo->cryptMode = param1;\n\t\tif( param2 != 0 )\n\t\t\tqueryInfo->keySize = param2;\n\t\t}\n\telse\n\t\t{\n\t\tif( isHashAlgo( queryInfo->cryptAlgo ) || \\\n\t\t\tisMacAlgo( queryInfo->cryptAlgo ) )\n\t\t\t{\n\t\t\t/* For hash/MAC algorithms, the optional parameter is the hash \n\t\t\t   width */\n\t\t\tREQUIRES( param1 == 0 );\n\t\t\tif( param2 != 0 )\n\t\t\t\tqueryInfo->hashAlgoParam = param2;\n\t\t\t}\n\t\t}\n\n\t/* Some broken implementations use sign + hash algoIDs in places where\n\t   a hash algoID is called for, if we find one of these we modify the\n\t   read AlgorithmIdentifier information to make it look like a hash\n\t   algoID */\n\tif( isPkcAlgo( queryInfo->cryptAlgo ) && isHashAlgo( param1 ) )\n\t\tqueryInfo->cryptAlgo = param1;\t/* Turn pkcWithHash into hash */\n\n\t/* Hash algorithms will either have NULL parameters or none at all\n\t   depending on which interpretation of which standard the sender used\n\t   so if it's not a conventional encryption algorithm we process the\n\t   NULL if required and return */\n\tif( isHashAlgo( queryInfo->cryptAlgo ) || \\\n\t\tisMacAlgo( queryInfo->cryptAlgo ) )\n\t\treturn( ( length > 0 ) ? readNull( stream ) : CRYPT_OK );\n\n\t/* If it's not a hash/MAC algorithm it has to be a conventional\n\t   encryption (or at least authenticated-encryption, handled via a\n\t   generic-secret context) algorithm */\n\tif( !isConvAlgo( queryInfo->cryptAlgo ) && \\\n\t\t!isSpecialAlgo( queryInfo->cryptAlgo ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Read the algorithm-specific parameters.  In theory we should do\n\t   something with some of the values like the IV size parameter, but\n\t   since the standard never explains what to do if it's something other\n\t   than the algorithm block size (Left pad? Right pad? Sign-extend?\n\t   Repeat the data?) it's safer not to do anything (\"Never check for an\n\t   error that you don't know how to handle\").  In any case there are no\n\t   known cases of these strange values ever being used (probably because\n\t   all existing software would break) so we make sure that they're \n\t   present but otherwise ignore them */\n\tswitch( queryInfo->cryptAlgo )\n\t\t{\n#ifdef USE_3DES\n\t\tcase CRYPT_ALGO_3DES:\n#endif /* USE_3DES */\n\t\tcase CRYPT_ALGO_AES:\n#ifdef USE_DES\n\t\tcase CRYPT_ALGO_DES:\n#endif /* USE_DES */\n\t\t\tif( queryInfo->cryptMode == CRYPT_MODE_ECB )\n\t\t\t\t{\n\t\t\t\t/* The NULL parameter has already been read in\n\t\t\t\t   readAlgoIDheader() */\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( queryInfo->cryptMode == CRYPT_MODE_CBC )\n\t\t\t\t{\n\t\t\t\treturn( readOctetString( stream, queryInfo->iv,\n\t\t\t\t\t\t\t\t&queryInfo->ivLength,\n\t\t\t\t\t\t\t\t( queryInfo->cryptAlgo == CRYPT_ALGO_AES ) ? \\\n\t\t\t\t\t\t\t\t\t16 : MIN_IVSIZE, CRYPT_MAX_IVSIZE ) );\n\t\t\t\t}\n\t\t\treadSequence( stream, NULL );\n\t\t\treadOctetString( stream, queryInfo->iv, &queryInfo->ivLength,\n\t\t\t\t\t\t\t MIN_IVSIZE, CRYPT_MAX_IVSIZE );\n\t\t\treturn( readShortInteger( stream, NULL ) );\n\n#ifdef USE_CAST\n\t\tcase CRYPT_ALGO_CAST:\n\t\t\treadSequence( stream, NULL );\n\t\t\treadOctetString( stream, queryInfo->iv, &queryInfo->ivLength,\n\t\t\t\t\t\t\t MIN_IVSIZE, CRYPT_MAX_IVSIZE );\n\t\t\treturn( readShortInteger( stream, NULL ) );\n#endif /* USE_CAST */\n\n#ifdef USE_RC2\n\t\tcase CRYPT_ALGO_RC2:\n\t\t\t/* In theory we should check that the parameter value ==\n\t\t\t   RC2_KEYSIZE_MAGIC (corresponding to a 128-bit key) but in\n\t\t\t   practice this doesn't really matter, we just use whatever we\n\t\t\t   find inside the PKCS #1 padding */\n\t\t\treadSequence( stream, NULL );\n\t\t\tif( queryInfo->cryptMode != CRYPT_MODE_CBC )\n\t\t\t\treturn( readShortInteger( stream, NULL ) );\n\t\t\treadShortInteger( stream, NULL );\n\t\t\treturn( readOctetString( stream, queryInfo->iv,\n\t\t\t\t\t\t\t\t\t &queryInfo->ivLength,\n\t\t\t\t\t\t\t\t\t MIN_IVSIZE, CRYPT_MAX_IVSIZE ) );\n#endif /* USE_RC2 */\n\n#ifdef USE_RC4\n\t\tcase CRYPT_ALGO_RC4:\n\t\t\t/* The NULL parameter has already been read in\n\t\t\t   readAlgoIDheader() */\n\t\t\treturn( CRYPT_OK );\n#endif /* USE_RC4 */\n\n\t\tcase CRYPT_IALGO_GENERIC_SECRET:\n\t\t\treturn( readGenericSecretParams( stream, queryInfo, \n\t\t\t\t\t\t\t\t\t\t\t startOffset ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get the size of an EncryptionAlgorithmIdentifier record */\n\nCHECK_RETVAL_LENGTH \\\nint sizeofCryptContextAlgoID( IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tSTREAM nullStream;\n\tint status;\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Determine how large the algoID and associated parameters are.  \n\t   Because this is a rather complex operation the easiest way to do it \n\t   is to write to a null stream and get its size */\n\tsMemNullOpen( &nullStream );\n\tstatus = writeCryptContextAlgoID( &nullStream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = stell( &nullStream );\n\tsMemClose( &nullStream );\n\treturn( status );\n\t}\n\n/* Write an EncryptionAlgorithmIdentifier record */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeGenericSecretParams( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t\t IN_BUFFER( oidSize ) const BYTE *oid,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_OID const int oidSize )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE kdfData[ AUTHENCPARAM_MAX_SIZE + 8 ];\n\tBYTE encAlgoData[ AUTHENCPARAM_MAX_SIZE + 8 ];\n\tBYTE macAlgoData[ AUTHENCPARAM_MAX_SIZE + 8 ];\n\tint kdfDataSize = 0, encAlgoDataSize, macAlgoDataSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidSize ) && \\\n\t\t\toidSize == sizeofOID( oid ) );\n\n\tREQUIRES_S( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES_S( oidSize >= MIN_OID_SIZE && oidSize <= MAX_OID_SIZE );\n\n\t/* Get the encoded parameters for the optional KDF data and encryption \n\t   and MAC contexts that will be derived from the generic-secret \n\t   context */\n\tsetMessageData( &msgData, kdfData, AUTHENCPARAM_MAX_SIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KDFPARAMS );\n\tif( cryptStatusOK( status ) )\t\n\t\t{\n\t\t/* The KDF data is optional so it may not be present */\n\t\tkdfDataSize = msgData.length;\n\t\t}\n\tsetMessageData( &msgData, encAlgoData, AUTHENCPARAM_MAX_SIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENCPARAMS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tencAlgoDataSize = msgData.length;\n\tsetMessageData( &msgData, macAlgoData, AUTHENCPARAM_MAX_SIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_MACPARAMS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmacAlgoDataSize = msgData.length;\n\n\t/* Write the pre-encoded AuthEnc parameter data */\n\twriteSequence( stream, oidSize + \\\n\t\t\t\t\t\t   sizeofObject( kdfDataSize + \\\n\t\t\t\t\t\t\t\t\t\t encAlgoDataSize + \\\n\t\t\t\t\t\t\t\t\t\t macAlgoDataSize ) );\n\tswrite( stream, oid, oidSize );\n\twriteSequence( stream, kdfDataSize + encAlgoDataSize + \\\n\t\t\t\t\t\t   macAlgoDataSize );\n\tif( kdfDataSize > 0 )\n\t\tswrite( stream, kdfData, kdfDataSize );\n\tswrite( stream, encAlgoData, encAlgoDataSize );\n\treturn( swrite( stream, macAlgoData, macAlgoDataSize ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeCryptContextAlgoID( INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tconst BYTE *oid;\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\tint algorithm, mode = CRYPT_MODE_NONE;\t/* enum vs.int */\n\tint algoParam = 0, oidSize, ivSize = 0, sizeofIV = 0, paramSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isHandleRangeValid( iCryptContext ) );\n\n\t/* Extract the information that we need to write the\n\t   AlgorithmIdentifier */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && algorithm != CRYPT_IALGO_GENERIC_SECRET )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\t\t}\n\tif( cryptStatusOK( status ) && !isStreamCipher( algorithm ) && \\\n\t\tneedsIV( mode ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, iv, CRYPT_MAX_IVSIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tivSize = msgData.length;\n\t\t\tsizeofIV = sizeofShortObject( ivSize );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && isParameterisedConvAlgo( algorithm ) )\n\t\t{\n\t\t/* Some algorithms are parameterised, so we have to extract \n\t\t   additional information to deal with them */\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &algoParam, CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't extract information needed to write \"\n\t\t\t\t\t \"AlgoID\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\n\tENSURES_S( isConvAlgo( algorithm ) || \\\n\t\t\t   algorithm == CRYPT_IALGO_GENERIC_SECRET );\n\n\t/* Get the OID for this algorithm */\n\tif( ( oid = algorithmToOID( algorithm, mode, algoParam, \\\n\t\t\t\t\t\t\t\tALGOTOOID_CHECK_VALID ) ) == NULL )\n\t\t{\n\t\t/* Some algorithm+mode combinations can't be encoded using the\n\t\t   available PKCS #7 OIDs, the best that we can do in this case is\n\t\t   alert the user in debug mode and return a CRYPT_ERROR_NOTAVAIL */\n\t\tDEBUG_DIAG(( \"Tried to write non-PKCS #7 algorithm ID\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\toidSize = sizeofOID( oid );\n\tENSURES_S( oidSize >= MIN_OID_SIZE && oidSize <= MAX_OID_SIZE );\n\n\t/* Write the algorithm-specific parameters */\n\tswitch( algorithm )\n\t\t{\n#ifdef USE_3DES\n\t\tcase CRYPT_ALGO_3DES:\n#endif /* USE_3DES */\n\t\tcase CRYPT_ALGO_AES:\n#ifdef USE_DES\n\t\tcase CRYPT_ALGO_DES:\n#endif /* USE_DES */\n\t\t\t{\n\t\t\tconst int noBits = ( algorithm == CRYPT_ALGO_AES ) ? 128 : 64;\n\n\t\t\tANALYSER_HINT( ivSize > 0 && ivSize < CRYPT_MAX_IVSIZE );\n\n\t\t\tparamSize = \\\n\t\t\t\t( mode == CRYPT_MODE_ECB ) ? sizeofNull() : \\\n\t\t\t\t( mode == CRYPT_MODE_CBC ) ? sizeofIV : \\\n\t\t\t\t  sizeofShortObject( sizeofIV + sizeofShortInteger( noBits ) );\n\t\t\twriteSequence( stream, oidSize + paramSize );\n\t\t\tswrite( stream, oid, oidSize );\n\t\t\tif( mode == CRYPT_MODE_ECB )\n\t\t\t\treturn( writeNull( stream, DEFAULT_TAG ) );\n\t\t\tif( mode == CRYPT_MODE_CBC )\n\t\t\t\treturn( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );\n\t\t\twriteSequence( stream, sizeofIV + sizeofShortInteger( noBits ) );\n\t\t\twriteOctetString( stream, iv, ivSize, DEFAULT_TAG );\n\t\t\treturn( writeShortInteger( stream, noBits, DEFAULT_TAG ) );\n\t\t\t}\n\n#ifdef USE_CAST\n\t\tcase CRYPT_ALGO_CAST:\n\t\t\tREQUIRES( ivSize == 8 );\n\n\t\t\tparamSize = sizeofIV + sizeofShortInteger( 128 );\n\t\t\twriteSequence( stream, oidSize + \\\n\t\t\t\t\t\t\t\t   sizeofShortObject( paramSize ) );\n\t\t\tswrite( stream, oid, oidSize );\n\t\t\twriteSequence( stream, paramSize );\n\t\t\twriteOctetString( stream, iv, ivSize, DEFAULT_TAG );\n\t\t\treturn( writeShortInteger( stream, 128, DEFAULT_TAG ) );\n#endif /* USE_CAST */\n\n#ifdef USE_RC2\n\t\tcase CRYPT_ALGO_RC2:\n\t\t\tparamSize = ( ( mode == CRYPT_MODE_ECB ) ? 0 : sizeofIV ) + \\\n\t\t\t\t\t\tsizeofShortInteger( RC2_KEYSIZE_MAGIC );\n\t\t\twriteSequence( stream, oidSize + \\\n\t\t\t\t\t\t\t\t   sizeofShortObject( paramSize ) );\n\t\t\tswrite( stream, oid, oidSize );\n\t\t\twriteSequence( stream, paramSize );\n\t\t\tif( mode != CRYPT_MODE_CBC )\n\t\t\t\t{\n\t\t\t\treturn( writeShortInteger( stream, RC2_KEYSIZE_MAGIC,\n\t\t\t\t\t\t\t\t\t\t   DEFAULT_TAG ) );\n\t\t\t\t}\n\t\t\twriteShortInteger( stream, RC2_KEYSIZE_MAGIC, DEFAULT_TAG );\n\t\t\treturn( writeOctetString( stream, iv, ivSize, DEFAULT_TAG ) );\n#endif /* USE_RC2 */\n\n#ifdef USE_RC4\n\t\tcase CRYPT_ALGO_RC4:\n\t\t\twriteSequence( stream, oidSize + sizeofNull() );\n\t\t\tswrite( stream, oid, oidSize );\n\t\t\treturn( writeNull( stream, DEFAULT_TAG ) );\n#endif /* USE_RC4 */\n\n\t\tcase CRYPT_IALGO_GENERIC_SECRET:\n\t\t\treturn( writeGenericSecretParams( stream, iCryptContext, \n\t\t\t\t\t\t\t\t\t\t\t  oid, oidSize ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAlgorithmIdentifier Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Because AlgorithmIdentifiers are only defined for a subset of the\n   algorithms that cryptlib supports we have to check that the algorithm\n   and mode being used can be represented in encoded form before we try to\n   do anything with it */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode )\n\t{\n\tREQUIRES_B( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES_B( isEnumRangeOpt( cryptMode, CRYPT_MODE ) );\n\n\treturn( ( algorithmToOID( cryptAlgo, cryptMode, 0, \\\n\t\t\t\t\t\t\t  ALGOTOOID_CHECK_VALID ) != NULL ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/* Determine the size of an AlgorithmIdentifier record.  For algorithms with\n   sub-parameters (AES, SHA-2) the OIDs are the same size so there's no need\n   to explicitly deal with them.\n\n   The subAlgo parameter passed to this is rather complex and comes in the \n   following variants:\n\n\tcryptAlgo\t\tsubAlgo\t\n\t---------\t\t-------\n\tAny\t\t\t\t0\n\tConv\t\t\tMode\n\tHash\t\t\tHash width\n\tPKC-Sig\t\t\tHash\n\tPKC-Enc\t\t\tEncoding */\n\nCHECK_RETVAL_LENGTH_SHORT \\\nstatic int algoIDSize( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t   IN_RANGE( 0, 999 ) const int subAlgo, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extraLength )\n\t{\n\tconst BYTE *oid;\n\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES( subAlgo == 0 || \\\n\t\t\t  ( isConvAlgo( cryptAlgo ) && \\\n\t\t\t\tsubAlgo > CRYPT_MODE_NONE && subAlgo < CRYPT_MODE_LAST ) || \\\n\t\t\t  ( ( isParameterisedHashAlgo( cryptAlgo ) || \\\n\t\t\t\t\tisParameterisedMacAlgo( cryptAlgo) ) && \\\n\t\t\t\tsubAlgo >= MIN_HASHSIZE && subAlgo <= CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t  ( isSigAlgo( cryptAlgo ) && isHashAlgo( subAlgo ) ) || \\\n\t\t\t  ( isCryptAlgo( cryptAlgo ) && \\\n\t\t\t\tsubAlgo > ALGOID_ENCODING_NONE && \\\n\t\t\t\tsubAlgo < ALGOID_ENCODING_LAST ) );\n\tREQUIRES( isShortIntegerRange( extraLength ) );\n\n\t/* Map the algorithm parameters to an OID.  This gets a bit awkward \n\t   because the subAlgo parameter can be either an encryption mode for a\n\t   { algorithm, mode } or { sigAlgo, hash } combination or a block/key \n\t   size/encoding specifier for an algorithm like AES and SHA-2 or RSA \n\t   encryption/signatures.  Because of this we call algorithmToOID() in \n\t   one of two ways depending on what the subAlgo parameter is */\n\tif( ( subAlgo > CRYPT_MODE_NONE && subAlgo < CRYPT_MODE_LAST ) || \\\n\t\t( subAlgo >= CRYPT_ALGO_FIRST_HASH && subAlgo < CRYPT_ALGO_LAST_HASH ) )\n\t\toid = algorithmToOID( cryptAlgo, subAlgo, 0, ALGOTOOID_REQUIRE_VALID );\n\telse\n\t\toid = algorithmToOID( cryptAlgo, 0, subAlgo, ALGOTOOID_REQUIRE_VALID );\n\tREQUIRES( oid != NULL );\n\n\t/* Return the overall encoded algorithmID size.  For OAEP the additional\n\t   data is a zero-length SEQUENCE, but that's the same size as an ASN.1\n\t   NULL so we don't need to treat is specially */\n\treturn( sizeofShortObject( sizeofOID( oid ) + \\\n\t\t\t\t\t\t\t   ( ( extraLength > 0 ) ? extraLength : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   sizeofNull() ) ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\treturn( algoIDSize( cryptAlgo, CRYPT_ALGO_NONE, 0 ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoIDex( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\tIN_RANGE( 0, 999 ) const int subAlgo )\n\t{\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES( ( subAlgo > CRYPT_MODE_NONE && subAlgo < CRYPT_MODE_LAST ) || \\\n\t\t\t  ( subAlgo >= MIN_HASHSIZE && subAlgo <= CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t  ( subAlgo > ALGOID_ENCODING_NONE && \\\n\t\t\t    subAlgo < ALGOID_ENCODING_LAST ) );\n\t\t\t  /* The subAlgo information is either an encryption mode, a\n\t\t\t     key/hash/block size, or an encoding format specifier */\n\n\treturn( algoIDSize( cryptAlgo, subAlgo, 0 ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoIDparam( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extraLength )\n\t{\n\tREQUIRES( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES( isShortIntegerRange( extraLength ) );\n\n\treturn( algoIDSize( cryptAlgo, CRYPT_ALGO_NONE, extraLength ) );\n\t}\n\n/* Write an AlgorithmIdentifier record.  There are three versions of \n   this:\n\n\twriteAlgoID: Write an AlgorithmIdentifier record.\n\n\twriteAlgoIDex: Write an AlgorithmIdentifier record.  The parameter \n\t\tvalue is used for aWithB algorithms like rsaWithSHA1, with the \n\t\tcontext containing the 'A' algorithm and the parameter indicating \n\t\tthe 'B' algorithm, for algorithms that have subtypes like SHA2's \n\t\tSHA2-256, SHA2-384, and SHA2-512, and to specify encoding mechanisms\n\t\tlike PKCS #1 vs. OAEP.\n\n\twriteAlgoIDparams: Write an AlgorithmIdentifier record, leaving extra\n\t\tspace for algorithm parameters at the end */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoID( INOUT STREAM *stream, \n\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\treturn( writeAlgoIDex( stream, cryptAlgo, CRYPT_ALGO_NONE, 0 ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t   IN_RANGE( 0, 999 ) const int parameter, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int extraLength )\n\t{\n\tconst BYTE *oid;\n\tint paramLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES_S( parameter == CRYPT_ALGO_NONE || \\\n\t\t\t\t( parameter >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t\t\t  parameter <= CRYPT_ALGO_LAST_HASH ) || \\\n\t\t\t\t( isHashMacExtAlgo( cryptAlgo ) && \\\n\t\t\t\t  parameter >= MIN_HASHSIZE && \\\n\t\t\t\t  parameter <= CRYPT_MAX_HASHSIZE ) || \\\n\t\t\t\t( isPkcAlgo( cryptAlgo ) && \\\n\t\t\t\t  parameter > ALGOID_ENCODING_NONE && \\\n\t\t\t\t  parameter < ALGOID_ENCODING_LAST ) );\n\tREQUIRES_S( isShortIntegerRange( extraLength ) );\n\n\t/* Determine how long the additional parameter data will be */\n\tif( extraLength > 0 )\n\t\tparamLength = extraLength;\n\telse\n\t\t{\n#ifdef USE_OAEP\n\t\tif( parameter == ALGOID_ENCODING_OAEP )\n\t\t\tparamLength = sizeofObject( 0 );\n\t\telse\n#endif /* USE_OAEP */\n\t\t\tparamLength = sizeofNull();\n\t\t}\n\n\t/* Map the algorithm parameters to an OID.  This gets a bit awkward \n\t   because the parameter can be either a a sub-algorithm like rsaWithXXX,\n\t   a block/key size for an algorithm like AES and SHA-2, or an encoding\n\t   specifier.  Because of this we call algorithmToOID in one of two ways \n\t   depending on what the parameter is */\n\tif( parameter >= CRYPT_ALGO_FIRST_HASH && parameter <= CRYPT_ALGO_LAST_HASH )\n\t\toid = algorithmToOID( cryptAlgo, parameter, 0, ALGOTOOID_REQUIRE_VALID );\n\telse\n\t\toid = algorithmToOID( cryptAlgo, 0, parameter, ALGOTOOID_REQUIRE_VALID );\n\tREQUIRES_S( oid != NULL );\n\n\t/* Write the AlgorithmIdentifier field */\n\twriteSequence( stream, sizeofOID( oid ) + paramLength );\n\tstatus = swrite( stream, oid, sizeofOID( oid ) );\n\tif( extraLength > 0 )\n\t\t{\n\t\t/* Parameters will be written by the caller */\n\t\treturn( status );\n\t\t}\n\n#ifdef USE_OAEP\n\t/* OAEP algoIDs have a zero-length SEQUENCE as their default parameter \n\t   rather than an ASN.1 NULL */\n\tif( parameter == ALGOID_ENCODING_OAEP && extraLength == 0 )\n\t\treturn( writeSequence( stream, 0 ) );\n#endif /* USE_OAEP */\n\n\t/* No extra parameters so we need to write an ASN.1 NULL */\n\treturn( writeNull( stream, DEFAULT_TAG ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoIDparam( INOUT STREAM *stream, \n\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int extraLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\tREQUIRES_S( isShortIntegerRange( extraLength ) );\n\n\treturn( writeAlgoIDex( stream, cryptAlgo, CRYPT_ALGO_NONE, extraLength ) );\n\t}\n\n/* Read an AlgorithmIdentifier record.  There are three versions of \n   this:\n\n\treadAlgoID: Reads an algorithm, assumes that there are no secondary \n\t\talgorithm or mode and algorithm parameters present and returns an \n\t\terror if there are.\n\n\treadAlgoIDex: Reads an algorithm, secondary algorithm or mode, \n\t\tand optional algorithm parameter (e.g. SHA-2 subtype when the \n\t\talgorithm is SHA-2).  Assumes that there are no explicit \n\t\talgorithm parameters present and returns an error if there are.\n\n\treadAlgoIDparams: Reads an algorithm and the length of the extra \n\t\tinformation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readAlgoID( INOUT STREAM *stream, \n\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\tIN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\n\tREQUIRES_S( type == ALGOID_CLASS_HASH || type == ALGOID_CLASS_PKC || \\\n\t\t\t\ttype == ALGOID_CLASS_PKCSIG );\n\n\treturn( readAlgoIDheader( stream, cryptAlgo, NULL, NULL, NULL, \n\t\t\t\t\t\t\t  DEFAULT_TAG, type ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t  OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t  OUT_OPT_ALGO_Z CRYPT_ALGO_TYPE *altCryptAlgo,\n\t\t\t\t  OUT_INT_Z int *parameter,\n\t\t\t\t  IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type )\n\t{\n\tint altAlgo, param, status;\t/* 'altAlgo' must be type integer */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( altCryptAlgo == NULL || \\\n\t\t\tisWritePtr( altCryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( parameter, sizeof( int ) ) );\n\n\tREQUIRES_S( ( type == ALGOID_CLASS_HASH && altCryptAlgo == NULL ) || \\\n\t\t\t\t( type == ALGOID_CLASS_PKC && altCryptAlgo == NULL ) || \\\n\t\t\t\t( type == ALGOID_CLASS_PKCSIG && altCryptAlgo != NULL ) );\n\n\t/* Clear return value (the others are cleared by readAlgoIDheader()) */\n\tif( altCryptAlgo != NULL )\n\t\t*altCryptAlgo = CRYPT_ALGO_NONE;\n\t*parameter = 0;\n\n\t/* If we're reading anything other than a signature algorithm there's\n\t   only the algorithm and an optional parameter to read */\n\tif( type != ALGOID_CLASS_PKCSIG )\n\t\t{\n\t\tint dummy;\n\n\t\treturn( readAlgoIDheader( stream, cryptAlgo, &dummy, parameter, \n\t\t\t\t\t\t\t\t  NULL, DEFAULT_TAG, type ) );\n\t\t}\n\n\t/* We're reading a signature algorithm, there's a secondary algorithm \n\t   (e.g. RSA with SHA-1) and an optional parameter (e.g. 64 bytes to \n\t   denote SHA2-512), otherwise it's either a hash algorithm with an \n\t   optional parameter (e.g. 64 = SHA2-512) or a PKC algorithm with an \n\t   optional encoding specifier (e.g. PKCS #1, OAEP) */\n\tstatus = readAlgoIDheader( stream, cryptAlgo, &altAlgo, &param, NULL, \n\t\t\t\t\t\t\t   DEFAULT_TAG, type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*altCryptAlgo = altAlgo;\t/* CRYPT_MODE_TYPE vs. integer */\n\tif( param < ALGOID_ENCODING_NONE )\n\t\t*parameter = param;\t\t/* Don't return encoding specifier */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readAlgoIDparam( INOUT STREAM *stream, \n\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *extraLength,\n\t\t\t\t\t IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( extraLength, sizeof( int ) ) );\n\n\tREQUIRES_S( type == ALGOID_CLASS_PKC );\n\n\treturn( readAlgoIDheader( stream, cryptAlgo, NULL, NULL, extraLength, \n\t\t\t\t\t\t\t  DEFAULT_TAG, type ) );\n\t}\n\n/* Determine the size of an AlgorithmIdentifier record from a context.  See\n   the comment for sizeofAlgoIDex() for why we don't have to deal with\n   parameterised algorithms */\n\nCHECK_RETVAL_LENGTH \\\nint sizeofContextAlgoID( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t IN_RANGE( 0, 999 ) const int parameter )\n\t{\n\tint algorithm, status;\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( parameter == 0 || \\\n\t\t\t  ( parameter > ALGOID_ENCODING_NONE && \\\n\t\t\t\tparameter < ALGOID_ENCODING_LAST ) || \\\n\t\t\t  isHashAlgo( parameter ) );\n\n\t/* Write the algoID only */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isHashMacExtAlgo( algorithm ) )\n\t\t{\n\t\tint blockSize;\n\n\t\tREQUIRES( parameter == 0 );\n\n\t\t/* The extended hash algorithms can have various different hash \n\t\t   sizes, to get the exact variant that's being used we have to \n\t\t   query the block size */\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( algoIDSize( algorithm, blockSize, 0 ) );\n\t\t}\n\tif( isHashAlgo( parameter ) )\n\t\t{\n\t\tREQUIRES( isSigAlgo( algorithm ) );\n\n\t\t/* It's a signature algorithm, e.g. RSA + SHA-1 */\n\t\treturn( algoIDSize( algorithm, parameter, 0 ) );\n\t\t}\n\tif( parameter == 0 )\n\t\t{\n\t\t/* It's a pure algorithm */\n\t\treturn( algoIDSize( algorithm, CRYPT_ALGO_NONE, 0 ) );\n\t\t}\n\n\tREQUIRES( isEnumRange( parameter, ALGOID_ENCODING ) );\n\n\t/* It's an encryption algorithm + encoding type, e.g. RSA + PKCS #1 */\n\treturn( algoIDSize( algorithm, parameter, 0 ) );\n\t}\n\n/* Write an AlgorithmIdentifier record from a context.  The associatedAlgo \n   parameter is used for aWithB algorithms like rsaWithSHA1, with the \n   context containing the 'A' algorithm and the parameter indicating the 'B' \n   algorithm */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeContextAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isHandleRangeValid( iCryptContext ) );\n\n\treturn( writeContextAlgoIDex( stream, iCryptContext, CRYPT_ALGO_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeContextAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_RANGE( 0, 999 ) const int parameter )\n\t{\n\tint algorithm, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES_S( parameter == CRYPT_ALGO_NONE || \\\n\t\t\t\tisHashAlgo( parameter ) || \\\n\t\t\t\t( parameter > ALGOID_ENCODING_NONE && \\\n\t\t\t\t  parameter < ALGOID_ENCODING_LAST ) );\n\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isHashMacExtAlgo( algorithm ) )\n\t\t{\n\t\tint blockSize;\n\n\t\tREQUIRES( parameter == CRYPT_ALGO_NONE );\n\n\t\t/* The extended hash algorithms can have various different hash \n\t\t   sizes, to get the exact variant that's being used we have to \n\t\t   query the block size */\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( writeAlgoIDex( stream, algorithm, blockSize, 0 ) );\n\t\t}\n\treturn( writeAlgoIDex( stream, algorithm, parameter, 0 ) );\n\t}\n\n/* Turn an AlgorithmIdentifier into a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readContextAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t   OUT_OPT QUERY_INFO *queryInfo, \n\t\t\t\t\t   IN_TAG const int tag,\n\t\t\t\t\t   IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type )\n\t{\n\tQUERY_INFO localQueryInfo, *queryInfoPtr = queryInfo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint mode, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( iCryptContext == NULL || \\\n\t\t\tisWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( queryInfo == NULL || \\\n\t\t\tisWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( type == ALGOID_CLASS_CRYPT || type == ALGOID_CLASS_HASH || \\\n\t\t\t\ttype == ALGOID_CLASS_AUTHENC );\n\n\t/* Clear return value */\n\tif( iCryptContext != NULL )\n\t\t*iCryptContext = CRYPT_ERROR;\n\n\t/* If the user isn't interested in the algorithm details, use a local \n\t   query structure to contain them */\n\tif( queryInfo == NULL )\n\t\tqueryInfoPtr = &localQueryInfo;\n\n\t/* Clear optional return value */\n\tmemset( queryInfoPtr, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the algorithm info.  If we're not creating a context from the\n\t   info, we're done */\n\tstatus = readAlgoIDInfo( stream, queryInfoPtr, tag, type );\n\tif( cryptStatusError( status ) || iCryptContext == NULL )\n\t\treturn( status );\n\n\t/* Create the object from it */\n\tsetMessageCreateObjectInfo( &createInfo, queryInfoPtr->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isHashMacExtAlgo( queryInfoPtr->cryptAlgo ) )\n\t\t{\n\t\t/* It's a variable-width hash algorithm, set the output width */\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &queryInfoPtr->hashAlgoParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( queryInfoPtr->cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\t/* If it's not a conventional encryption algorithm, we're done */\n\t\t*iCryptContext = createInfo.cryptHandle;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES_S( isConvAlgo( queryInfoPtr->cryptAlgo ) );\n\tmode = queryInfoPtr->cryptMode;\t/* int vs.enum */\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusOK( status ) && \\\n\t\t!isStreamCipher( queryInfoPtr->cryptAlgo ) )\n\t\t{\n\t\tint ivLength;\n\n\t\t/* It's a block cipher, get the IV information as well */\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &ivLength,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tsetMessageData( &msgData, queryInfoPtr->iv,\n\t\t\t\t\t\t\tmin( ivLength, queryInfoPtr->ivLength ) );\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there's an error in the parameters stored with the key then \n\t\t   we'll get an arg or attribute error when we try to set the \n\t\t   attribute so we translate it into an error code which is \n\t\t   appropriate for the situation.  In addition since this is \n\t\t   (arguably) a stream format error (the data read from the stream \n\t\t   is invalid) we also set the stream status */\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tif( cryptArgError( status ) )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\treturn( status );\n\t\t}\n\t*iCryptContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a non-crypto algorithm identifier, used for things like \n   content types.  This just wraps the given OID up in the \n   AlgorithmIdentifier and writes it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGenericAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t   IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t   IN_LENGTH_OID const int oidLength )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) && \\\n\t\t\toidLength == sizeofOID( oid ) );\n\n\tREQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\n\t/* Read the AlgorithmIdentifier wrapper and OID.  One possible \n\t   complication here is the standard NULL vs.absent AlgorithmIdentifier \n\t   parameter issue, to handle this we allow either option */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readFixedOID( stream, oid, oidLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength -= oidLength;\n\tif( length > 0 )\n\t\treturn( readNull( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeGenericAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\tIN_LENGTH_OID const int oidLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) && \\\n\t\t\toidLength == sizeofOID( oid ) );\n\n\tREQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\n\twriteSequence( stream, oidLength );\n\treturn( writeOID( stream, oid ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tECC OID Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\n/* ECC curves are identified by OIDs, in order to map to and from these when \n   working with external representations of ECC parameters we need mapping \n   functions for the conversion */\n\nstatic const OID_INFO eccOIDinfo[] = {\n\t/* NIST P-256, X9.62 p256r1, SECG p256r1, 1 2 840 10045 3 1 7 */\n\t{ MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\xCE\\x3D\\x03\\x01\\x07\" ), CRYPT_ECCCURVE_P256 },\n\t/* NIST P-384, SECG p384r1, 1 3 132 0 34 */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x81\\x04\\x00\\x22\" ), CRYPT_ECCCURVE_P384 },\n\t/* NIST P-521, SECG p521r1, 1 3 132 0 35 */\n\t{ MKOID( \"\\x06\\x05\\x2B\\x81\\x04\\x00\\x23\" ), CRYPT_ECCCURVE_P521 },\n\t/* Brainpool p256r1, 1 3 36 3 3 2 8 1 1 7 */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x24\\x03\\x03\\x02\\x08\\x01\\x01\\x07\" ), CRYPT_ECCCURVE_BRAINPOOL_P256 },\n\t/* Brainpool p384r1, 1 3 36 3 3 2 8 1 1 11 */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x24\\x03\\x03\\x02\\x08\\x01\\x01\\x0B\" ), CRYPT_ECCCURVE_BRAINPOOL_P384 },\n\t/* Brainpool p512r1, 1 3 36 3 3 2 8 1 1 13 */\n\t{ MKOID( \"\\x06\\x09\\x2B\\x24\\x03\\x03\\x02\\x08\\x01\\x01\\x0D\" ), CRYPT_ECCCURVE_BRAINPOOL_P512 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readECCOID( INOUT STREAM *stream, \n\t\t\t\tOUT_OPT CRYPT_ECCCURVE_TYPE *curveType )\n\t{\n\tint selectionID, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( curveType, sizeof( CRYPT_ECCCURVE_TYPE ) ) );\n\n\t/* Clear return value */\n\t*curveType = CRYPT_ECCCURVE_NONE;\n\n\t/* Read the ECC OID */\n\tstatus = readOID( stream, eccOIDinfo, \n\t\t\t\t\t  FAILSAFE_ARRAYSIZE( eccOIDinfo, OID_INFO ), \n\t\t\t\t\t  &selectionID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*curveType = selectionID;\t/* enum vs.int */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_LENGTH \\\nint sizeofECCOID( const CRYPT_ECCCURVE_TYPE curveType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES( isEnumRange( curveType, CRYPT_ECCCURVE ) );\n\n\tLOOP_SMALL( i = 0, i < FAILSAFE_ARRAYSIZE( eccOIDinfo, OID_INFO ) && \\\n\t\t\t\t\t   eccOIDinfo[ i ].oid != NULL, i++ )\n\t\t{\n\t\tif( eccOIDinfo[ i ].selectionID == curveType )\n\t\t\treturn( sizeofOID( eccOIDinfo[ i ].oid ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tretIntError();\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeECCOID( INOUT STREAM *stream, \n\t\t\t\t const CRYPT_ECCCURVE_TYPE curveType )\n\t{\n\tconst BYTE *oid = NULL;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isEnumRange( curveType, CRYPT_ECCCURVE ) );\n\n\tLOOP_SMALL( i = 0, i < FAILSAFE_ARRAYSIZE( eccOIDinfo, OID_INFO ) && \\\n\t\t\t\t\t   eccOIDinfo[ i ].oid != NULL, i++ )\n\t\t{\n\t\tif( eccOIDinfo[ i ].selectionID == curveType )\n\t\t\t{\n\t\t\toid = eccOIDinfo[ i ].oid;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( eccOIDinfo, OID_INFO ) );\n\tENSURES( oid != NULL );\n\n\treturn( writeOID( stream, oid ) );\n\t}\n#endif /* USE_ECDH || USE_ECDSA */\n\n#endif /* USE_INT_ASN1 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_chk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t   ASN.1 Checking Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n/* The maximum nesting level for constructed or encapsulated objects (this\n   can get surprisingly high for some of the more complex attributes).  This\n   value is chosen to pass all normal certs while avoiding stack overflows\n   for artificial bad data */\n\n#define MAX_NESTING_LEVEL\t50\n\n/* When we parse a nested data object encapsulated within a larger object,\n   the length is initially set to a magic value which is adjusted to the\n   actual length once we start parsing the object.  The MAX_BUFFER_SIZE - 1\n   value means that it's as large as possible while still passing the \n   parameter sanity checks */\n\n#define LENGTH_MAGIC\t\t( MAX_BUFFER_SIZE - 1 )\n\n/* Current parse state.  This is used to check for potential BIT STRING and\n   OCTET STRING targets for OCTET/BIT STRING holes, which are always\n   preceded by an AlgorithmIdentifier.  In order to detect these without\n   having to know every imaginable AlgorithmIdentifier OID, we check for the\n   following sequence of events:\n\n\tSEQUENCE {\t\t\t-- ASN1_STATE_SEQUENCE\n\t\tOID,\t\t\t-- ASN1_STATE_HOLE_OID\n\t\tNULL\t\t\t-- ASN1_STATE_NULL\n\t\t},\n\t\t\t\t\t\t-- ASN1_STATE_CHECK_HOLE_BITSTRING\n\tBIT STRING | ...\n\n\tSEQUENCE {\t\t\t-- ASN1_STATE_SEQUENCE\n\t\tOID,\t\t\t-- ASN1_STATE_HOLE_OID\n\t\t[ BOOLEAN OPT,\t-- ASN1_STATE_BOOLEAN ]\n\t\t\t\t\t\t-- ASN1_STATE_CHECK_HOLE_OCTETSTRING\n\t\tOCTET STRING | ...\n\n   Once we reach any of the ASN1_STATE_CHECK_HOLE_* states, if we hit a \n   BIT STRING or OCTET STRING as the next item then we try and locate \n   encapsulated content within it.\n   \n   This type of checking is rather awkward in the (otherwise stateless) code \n   but is the only way to be sure that it's safe to try burrowing into an \n   OCTET STRING or BIT STRING to try to find encapsulated data, since \n   otherwise even with relatively strict checking there's still a very small \n   chance that random data will look like a nested object.\n\n   The handling of BIT STRING encapsulation is complicated by the fact that\n   for crypto use it really only occurs in one of two cases:\n\n\tSEQUENCE {\n\t\tOID,\n\t\tNULL\n\t\t},\n\tBIT STRING {\n\t\tSEQUENCE {\n\t\t\tINTEGER\n\t\t\t...\n\n   for public keys and:\n\n\tSEQUENCE {\n\t\tOID,\n\t\tNULL\n\t\t},\n\tBIT STRING ...\n\n   for signatures (with an additional complication for DLP keys that the \n   NULL for the public-key parameters is replaced by a SEQUENCE { ... }\n   containing the public parameters).  This means that there's little point \n   in trying to track the state because any occurrence of a potential BIT \n   STRING hole has a 50:50 chance of actually being one or not.  Because of\n   this we don't bother tracking the state for BIT STRINGs but rely on the\n   encapsulation-check to catch them.  This should be fairly safe because we\n   require that the value be:\n\n\t[ SEQUENCE ][ = outerLength - SEQUENCE-hdrSize ]\n\t\t[ INTEGER ][ <= innerlength - INTEGER-hdrSize ]\n\n   which provides at least 26-28 bits of safety */\n\ntypedef enum {\n\t/* Generic non-state */\n\tASN1_STATE_NONE,\n\n\t/* States corresponding to ASN.1 primitives */\n\tASN1_STATE_BOOLEAN, ASN1_STATE_NULL, ASN1_STATE_OID, ASN1_STATE_SEQUENCE,\n\n\t/* States corresponding to different parts of a SEQUENCE { OID, optional,\n\t   potential OCTET/BIT STRING } sequence */\n\tASN1_STATE_HOLE_OID, /*ASN1_STATE_CHECK_HOLE_BITSTRING,*/ \n\tASN1_STATE_CHECK_HOLE_OCTETSTRING,\n\n\t/* Error state */\n\tASN1_STATE_ERROR,\n\t\n\tASN1_STATE_LAST\n\t} ASN1_STATE;\n\n/* Structure to hold info on an ASN.1 item */\n\ntypedef struct {\n\tint tag;\t\t\t\t/* Tag */\n\tlong length;\t\t\t/* Data length */\n\tint headerSize;\t\t\t/* Size of tag+length */\n\tBOOLEAN isIndefinite;\t/* Item has indefinite length */\n\t} ASN1_ITEM;\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get an ASN.1 object's tag and length */\n\nCHECK_RETVAL_ENUM( ASN1_STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getItem( INOUT STREAM *stream, \n\t\t\t\t\tOUT ASN1_ITEM *item )\n\t{\n\tconst long offset = stell( stream );\n\tlong length;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( item, sizeof( ASN1_ITEM ) ) );\n\n\tREQUIRES_EXT( isIntegerRange( offset ), ASN1_STATE_ERROR );\n\n\t/* Clear return value */\n\tmemset( item, 0, sizeof( ASN1_ITEM ) );\n\n\t/* Read the tag.  We can't use peekTag() for this since we may be \n\t   reading EOC octets, which would be rejected by peekTag() */\n\tstatus = item->tag = sPeek( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( ASN1_STATE_ERROR );\n\tif( item->tag == BER_EOC )\n\t\t{\n\t\t/* It looks like EOC octets, make sure that they're in order */\n\t\tstatus = checkEOC( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( ASN1_STATE_ERROR );\n\t\tif( status == TRUE )\n\t\t\t{\n\t\t\titem->headerSize = 2;\n\t\t\treturn( ASN1_STATE_NONE );\n\t\t\t}\n\t\t}\n\n\t/* If it's a NULL, special-case the read since the length will be \n\t   zero */\n\tif( item->tag == BER_NULL )\n\t\t{\n\t\tint ch;\n\n\t\t( void ) sgetc( stream );\t/* Skip tag */\n\t\tstatus = ch = sgetc( stream );\n\t\tif( cryptStatusError( status ) || ( ch != 0 ) )\n\t\t\treturn( ASN1_STATE_ERROR );\n\t\titem->headerSize = 2;\n\n\t\treturn( ASN1_STATE_NONE );\n\t\t}\n\n\t/* Make sure that the tag is at least vaguely valid before we try the \n\t   readLongGenericHole() */\n\tif( item->tag <= 0 || item->tag >= MAX_TAG )\n\t\treturn( ASN1_STATE_ERROR );\n\n\t/* It's not an EOC, read the tag and length as a generic hole */\n\tstatus = readLongGenericHoleZ( stream, &length, item->tag );\n\tif( cryptStatusError( status ) )\n\t\treturn( ASN1_STATE_ERROR );\n\titem->headerSize = stell( stream ) - offset;\n\tif( length == CRYPT_UNUSED )\n\t\titem->isIndefinite = TRUE;\n\telse\n\t\t{\n\t\t/* If the length that we've just read is larger than the object \n\t\t   itself, it's an error */\n\t\tif( length < 0 || length >= MAX_BUFFER_SIZE - 1 ) \n\t\t\treturn( ASN1_STATE_ERROR );\n\n\t\titem->length = length;\n\t\t}\n\treturn( ASN1_STATE_NONE );\n\t}\n\n/* Check whether an ASN.1 object is encapsulated inside an OCTET STRING or\n   BIT STRING.  After performing the various checks we have to explicitly\n   clear the stream error state since the probing for valid data could have\n   set the error indicator if nothing valid was found.\n\n   Note that this is a no-biased test since the best that we can do is guess \n   at the presence of encapsulated content and we can't risk rejecting valid\n   content based on false positives.  This means that unfortunately \n   maliciously-encoded nested content with (for example) an incorrect inner \n   length will slip past our checks, and we have to rely on the robustness \n   of the general ASN1-read code to avoid problems with it.  It's not \n   obvious whether this is really a serious problem or not though (apart from\n   it being a certificational weakness), a too-short length will result in \n   whatever additional padding is present being skipped by the general ASN1-\n   read code, a too-long length will result in an immediate error as the \n   decoder encounters garbage from reading past the TLV that follows */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkEncapsulation( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN_LENGTH const int length,\n\t\t\t\t\t\t\t\t   const BOOLEAN isBitstring,\n\t\t\t\t\t\t\t\t   IN_ENUM_OPT( ASN1_STATE ) \\\n\t\t\t\t\t\t\t\t\t\tconst ASN1_STATE state )\n\t{\n\tBOOLEAN isEncapsulated = TRUE;\n\tconst long streamPos = stell( stream );\n\tint tag, innerLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_B( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES_B( isBitstring == TRUE || isBitstring == FALSE );\n\tREQUIRES_B( state >= ASN1_STATE_NONE && state < ASN1_STATE_ERROR );\n\tREQUIRES_B( isIntegerRange( streamPos ) );\n\n\t/* Make sure that the tag is in order */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsClearError( stream );\n\t\tsseek( stream, streamPos );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that there's an encapsulated object present.  This is a \n\t   reasonably effective check, but unfortunately this same effectiveness \n\t   means that it'll reject nested objects with incorrect lengths.  It's \n\t   not really possible to fix this, either there'll be false positives \n\t   due to true OCTET/BIT STRINGs that look like they might contain \n\t   nested data or there'll be no false positives but nested content \n\t   with slightly incorrect encodings will be missed (see the comment at\n\t   the start for more on this) */\n\tstatus = readGenericHole( stream, &innerLength, 1, DEFAULT_TAG );\n\tif( cryptStatusError( status ) || \\\n\t\t( stell( stream ) - streamPos ) + innerLength != length )\n\t\t{\n\t\tsClearError( stream );\n\t\tsseek( stream, streamPos );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* A BIT STRING that encapsulates something only ever contains\n\t   { SEQUENCE { INTEGER, ... } } */\n\tif( isBitstring )\n\t\t{\n\t\t/* Make sure that there's a SEQUENCE containing an INTEGER present */\n\t\tif( tag != BER_SEQUENCE || peekTag( stream ) != BER_INTEGER || \\\n\t\t\tcryptStatusError( readGenericHole( stream, &innerLength, 1,\n\t\t\t\t\t\t\t\t\t\t\t   BER_INTEGER ) ) || \\\n\t\t\tinnerLength > length - 4 )\n\t\t\t{\n\t\t\tisEncapsulated = FALSE;\n\t\t\t}\n\n\t\tsClearError( stream );\n\t\tsseek( stream, streamPos );\n\t\treturn( isEncapsulated );\n\t\t}\n\n\t/* An OCTET STRING is more complex.  This could encapsulate any of:\n\n\t\tBIT STRING: keyUsage, crlReason, Netscape certType, must be\n\t\t\t<= 16 bits and a valid bitstring.\n\t\tGeneralisedTime: invalidityDate: Valid length for a GeneralisedTime,\n\t\t\tfollowed by two numeric digits.\n\t\tIA5String: Netscape extensions, perform an approximate length range \n\t\t\tcheck and verify that the first two characters are IA5.\n\t\tINTEGER: deltaCRLIndicator, crlNumber, must be <= 16 bits and a \n\t\t\tpositive integer.\n\t\tOCTET STRING: keyID, again the most that we can do is perform an\n\t\t\tapproximate length range check.\n\t\tOID: holdInstructionCode, again just an approximate length range \n\t\t\tcheck.\n\t\tSEQUENCE: most extensions, a bit difficult to check but again we can \n\t\t\tmake sure that the length is right for strict encapsulation (via\n\t\t\tthe check above) and that the inner content is a valid ASN.1\n\t\t\tobject */\n\tswitch( tag )\n\t\t{\n\t\tcase BER_BITSTRING:\n\t\t\tif( innerLength < 0 || innerLength > 2 )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst int ch = sgetc( stream );\n\n\t\t\t\tif( ch < 0 || ch > 7 )\n\t\t\t\t\tisEncapsulated = FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase BER_TIME_GENERALIZED:\n\t\t\tif( innerLength != 15 )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst int ch1 = sgetc( stream );\n\t\t\t\tconst int ch2 = sgetc( stream );\n\n\t\t\t\tif( !isDigit( ch1 ) || !isDigit( ch2 ) )\n\t\t\t\t\tisEncapsulated = FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase BER_INTEGER:\n\t\t\tif( innerLength < 0 || innerLength > 2 )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst int ch = sgetc( stream );\n\n\t\t\t\tif( ch < 0 )\n\t\t\t\t\tisEncapsulated = FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase BER_STRING_IA5:\n\t\t\tif( innerLength < 2 || innerLength > 256 )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst int ch1 = sgetc( stream );\n\t\t\t\tconst int ch2 = sgetc( stream );\n\n\t\t\t\tif( !isPrint( ch1 ) || !isPrint( ch2 ) )\n\t\t\t\t\tisEncapsulated = FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase BER_OCTETSTRING:\n\t\t\tif( innerLength < 2 || innerLength > 256 )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\tbreak;\n\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\tif( innerLength < MIN_OID_SIZE - 2 || \\\n\t\t\t\tinnerLength > MAX_OID_SIZE )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\tbreak;\n\n\t\tcase BER_SEQUENCE:\n\t\t\tstatus = tag = peekTag( stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tisEncapsulated = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = readGenericHole( stream, &innerLength, 1, \n\t\t\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tisEncapsulated = FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tisEncapsulated = FALSE;\n\t\t}\n\tsClearError( stream );\n\tsseek( stream, streamPos );\n\treturn( isEncapsulated );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Primitive ASN.1 Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a primitive ASN.1 object */\n\nCHECK_RETVAL_ENUM( ASN1_STATE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ASN1_STATE checkASN1( INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_DATALENGTH_Z const long length,\n\t\t\t\t\t\t\t const BOOLEAN isIndefinite,\n\t\t\t\t\t\t\t IN_RANGE( 0, MAX_NESTING_LEVEL ) const int level,\n\t\t\t\t\t\t\t IN_ENUM_OPT( ASN1_STATE ) ASN1_STATE state,\n\t\t\t\t\t\t\t IN_ENUM_OPT( CHECK_ENCODING ) \\\n\t\t\t\t\t\t\t\tconst CHECK_ENCODING_TYPE checkType,\n\t\t\t\t\t\t\t const BOOLEAN checkDataElements );\n\nCHECK_RETVAL_ENUM( ASN1_STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic ASN1_STATE checkPrimitive( INOUT STREAM *stream, const ASN1_ITEM *item,\n\t\t\t\t\t\t\t\t  IN_RANGE( 1, MAX_NESTING_LEVEL ) const int level, \n\t\t\t\t\t\t\t\t  IN_ENUM_OPT( ASN1_STATE ) const ASN1_STATE state,\n\t\t\t\t\t\t\t\t  IN_ENUM_OPT( CHECK_ENCODING ) \\\n\t\t\t\t\t\t\t\t\t\tconst CHECK_ENCODING_TYPE checkType )\n\t{\n\tint length = ( int ) item->length, ch, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( item, sizeof( ASN1_ITEM ) ) );\n\t\n\tREQUIRES_EXT( level > 0 && level <= MAX_NESTING_LEVEL, ASN1_STATE_ERROR );\n\tREQUIRES_EXT( state >= ASN1_STATE_NONE && state < ASN1_STATE_ERROR, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( isEnumRangeOpt( checkType, CHECK_ENCODING ), \n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( isIntegerRange( item->length ), ASN1_STATE_ERROR );\n\tREQUIRES_EXT( length >= 0 && length < MAX_BUFFER_SIZE, ASN1_STATE_ERROR );\n\n\t/* Make sure that we're not processing suspiciosly deeply nested data */\n\tif( level >= MAX_NESTING_LEVEL )\n\t\treturn( ASN1_STATE_ERROR );\n\n\t/* Check for a zero-length item.  In theory only NULL and EOC elements \n\t   (BER_RESERVED) are allowed to have a zero length */\n\tif( length <= 0 && item->tag != BER_NULL && item->tag != BER_RESERVED )\n\t\t{\n\t\t/* There are other cases where zero lengths can occur:\n\n\t\t\tOCTET STRING: When using PBKDF2 as a general-purpose KDF (for\n\t\t\t\tCMS authEnc encryption), the salt is omitted, which means \n\t\t\t\tthat it's encoded as a zero-length value.  It would be \n\t\t\t\tbetter to perform context checking to see whether it's in \n\t\t\t\tthe right location but the most information that we have at \n\t\t\t\tthis point is the nesting level, we allow a zero-length \n\t\t\t\tOCTET STRING at a nesting level between 16 and 30, which \n\t\t\t\toccurs for CMS authEnveloped data */\n\t\tif( !( item->tag == BER_OCTETSTRING && level >= 16 && level <= 30 ) )\n\t\t\treturn( ASN1_STATE_ERROR );\n\n\t\t/* Since this is a zero-length element, there's nothing further to\n\t\t   check */\n\t\treturn( ASN1_STATE_NONE );\n\t\t}\n\n\t/* Perform a general check that everything is OK.  We don't check for \n\t   invalid content except where it would impede decoding of the data in\n\t   order to avoid failing on all of the broken certificates out there */\n\tswitch( item->tag )\n\t\t{\n\t\tcase BER_BOOLEAN:\n\t\t\tif( length != 1 )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\treturn( cryptStatusError( sgetc( stream ) ) ? \\\n\t\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_BOOLEAN );\n\n\t\tcase BER_INTEGER:\n\t\tcase BER_ENUMERATED:\n\t\t\tif( !isShortIntegerRangeNZ( length ) || \\\n\t\t\t\tcryptStatusError( \\\n\t\t\t\t\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT ) ) )\n\t\t\t\t{\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\treturn( ASN1_STATE_NONE );\n\n\t\tcase BER_BITSTRING:\n\t\t\tif( length < 2 )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\n\t\t\t/* Check the number of unused bits */\n\t\t\tch = sgetc( stream );\n\t\t\tlength--;\n\t\t\tif( !isShortIntegerRange( length ) || ch < 0 || ch > 7 )\n\t\t\t\t{\n\t\t\t\t/* Invalid number of unused bits */\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\n\t\t\t/* If it's short enough to be a bit flag, it's just a sequence \n\t\t\t   of bits */\n\t\t\tif( length <= 4 )\n\t\t\t\t{\n\t\t\t\tif( length > 0 && \\\n\t\t\t\t\tcryptStatusError( \\\n\t\t\t\t\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT ) ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t\t}\n\t\t\t\treturn( ASN1_STATE_NONE );\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase BER_OCTETSTRING:\n\t\t\t{\n\t\t\tconst BOOLEAN isBitstring = ( item->tag == BER_BITSTRING ) ? \\\n\t\t\t\t\t\t\t\t\t\tTRUE : FALSE;\n\t\t\tBOOLEAN checkEncaps = ( checkType == CHECK_ENCODING_ENCAPS ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\n\t\t\t/* If we're checking for the presence of hole encodings at a \n\t\t\t   certain level, things get a bit more tricky because we want\n\t\t\t   to try and avoid false positives as much as possible.  The\n\t\t\t   following somewhat ugly heuristics enable hole-encoding \n\t\t\t   checking under conditions where they occur in data that we \n\t\t\t   can encounter */\n\t\t\tif( checkType == CHECK_ENCODING_SEMIENCAPS )\n\t\t\t\t{\n\t\t\t\tif( isBitstring )\n\t\t\t\t\t{\n\t\t\t\t\t/* SCEP, CMP, and RTCS have BIT STRINGs in certificate\n\t\t\t\t\t   signatures 7 levels down */\n\t\t\t\t\tif( level >= 7 )\n\t\t\t\t\t\tcheckEncaps = TRUE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t/* CMS (and by extension SCEP) have OCTET STRING \n\t\t\t\t\t   encrypted content 5 levels down */\n\t\t\t\t\tif( level >= 5 && length > 256 )\n\t\t\t\t\t\tcheckEncaps = TRUE;\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/* SCEP and CMP have OCTET STRINGs in certificate\n\t\t\t\t\t\t   attributes 9 and 12 levels down */\n\t\t\t\t\t\tif( level >= 9 )\n\t\t\t\t\t\t\tcheckEncaps = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* Check to see whether an OCTET STRING or BIT STRING hole is \n\t\t\t   allowed at this point.  An OCTET STRING must be preceded by \n\t\t\t   { SEQ, OID, {BOOLEAN} }), a BIT STRING hole can't easily be \n\t\t\t   checked based on what precedes it (see the comment for \n\t\t\t   ASN1_STATE) but is checked based on the contents of the hole */\n\t\t\tif( checkEncaps && \\\n\t\t\t\t( isBitstring || state == ASN1_STATE_HOLE_OID || \\\n\t\t\t\t\t\t\t\t state == ASN1_STATE_CHECK_HOLE_OCTETSTRING ) && \\\n\t\t\t\tcheckEncapsulation( stream, length, isBitstring, state ) )\n\t\t\t\t{\n\t\t\t\tASN1_STATE encapsState;\n\n\t\t\t\t/* It looks like it's a hole encoding, handle it as a \n\t\t\t\t   constructed item */\n\t\t\t\tencapsState = checkASN1( stream, length, item->isIndefinite,\n\t\t\t\t\t\t\t\t\t\t level + 1, ASN1_STATE_NONE, checkType, \n\t\t\t\t\t\t\t\t\t\t TRUE );\n\t\t\t\treturn( ( encapsState < ASN1_STATE_NONE || \\\n\t\t\t\t\t\t  encapsState >= ASN1_STATE_ERROR ) ? \\\n\t\t\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_NONE );\n\t\t\t\t}\n\n\t\t\t/* Skip the data */\n\t\t\tif( length <= 0 )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\treturn( cryptStatusError( \\\n\t\t\t\t\t\tsSkip( stream, length, SSKIP_MAX ) ) ? \\\n\t\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_NONE );\n\t\t\t}\n\n\t\tcase BER_OBJECT_IDENTIFIER:\n\t\t\tif( length < 3 )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\tif( length > MAX_OID_SIZE - 2 )\n\t\t\t\t{\n\t\t\t\t/* Microsoft invented their own gibberish OIDs off the arc \n\t\t\t\t   1 3 6 1 4 1 311 21 8, beyond which the contents are just \n\t\t\t\t   noise.  These OIDs are technically valid (in the usual \n\t\t\t\t   sense that an MPEG of a cat encoded in there is valid) \n\t\t\t\t   but look like garbage, so they'd normally get rejected by \n\t\t\t\t   the sanity-checking code.  In order to be able to process \n\t\t\t\t   Microsoft-generated certificates we kludge around them by \n\t\t\t\t   performing an explicit check for this particular arc and \n\t\t\t\t   not rejecting the input if it's one of these */\n\t\t\t\tif( state == ASN1_STATE_SEQUENCE && length < 48 )\n\t\t\t\t\t{\n\t\t\t\t\tBYTE oidBuffer[ 48 + 8 ];\n\t\t\t\t\tint status;\n\n\t\t\t\t\tstatus = sread( stream, oidBuffer, length );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t\tif( memcmp( oidBuffer, \n\t\t\t\t\t\t\t\t\"\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x15\\x08\", 9 ) )\n\t\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\n\t\t\t\t\t/* It's a Microsoft gibberish OID, report it as a \n\t\t\t\t\t   standard OID */\n\t\t\t\t\treturn( ASN1_STATE_OID );\n\t\t\t\t\t}\n\n\t\t\t\t/* Total OID size (including tag and length, since they're \n\t\t\t\t   treated as a blob) should be less than a sane limit */\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\tif( !isShortIntegerRangeNZ( length ) )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\treturn( cryptStatusError( \\\n\t\t\t\t\t\tsSkip( stream, length, MAX_INTLENGTH_SHORT ) ) ? \\\n\t\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_OID );\n\n\t\tcase BER_RESERVED:\t\t\t/* EOC */\n\t\t\treturn( ASN1_STATE_NONE );\n\n\t\tcase BER_NULL:\n\t\t\treturn( ASN1_STATE_NULL );\n\n\t\tcase BER_STRING_BMP:\n\t\tcase BER_STRING_GENERAL:\t/* Produced by Entrust software */\n\t\tcase BER_STRING_IA5:\n\t\tcase BER_STRING_ISO646:\n\t\tcase BER_STRING_NUMERIC:\n\t\tcase BER_STRING_PRINTABLE:\n\t\tcase BER_STRING_T61:\n\t\tcase BER_STRING_UTF8:\n\t\t\tif( length <= 0 )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\treturn( cryptStatusError( \\\n\t\t\t\t\t\tsSkip( stream, length, SSKIP_MAX ) ) ? \\\n\t\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_NONE );\n\n\t\tcase BER_TIME_UTC:\n\t\tcase BER_TIME_GENERALIZED:\n\t\t\tif( item->tag == BER_TIME_GENERALIZED )\n\t\t\t\t{\n\t\t\t\tif( length != 15 )\n\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( length != 13 )\n\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\tLOOP_MED( i = 0, i < length - 1, i++ )\n\t\t\t\t{\n\t\t\t\tch = sgetc( stream );\n\t\t\t\tif( cryptStatusError( ch ) || !isDigit( ch ) )\n\t\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\tENSURES_EXT( LOOP_BOUND_OK, ASN1_STATE_ERROR );\n\t\t\tif( sgetc( stream ) != 'Z' )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\treturn( ASN1_STATE_NONE );\n\n\t\tdefault:\n\t\t\t/* Disallowed or unrecognised primitive */\n\t\t\treturn( ASN1_STATE_ERROR );\n\t\t}\n\n\tretIntError_Ext( ASN1_STATE_ERROR );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck Complex ASN.1 Objects\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a single ASN.1 object.  checkASN1() and checkASN1Object() are \n   mutually recursive, the ...Object() version only exists to avoid a\n   large if... else chain in checkASN1().  A typical checking run is\n   as follows:\n\n\t30 nn\t\t\tcASN1 -> cAObj -> cASN1\n\t   30 nn\t\t\t\t\t\t  cASN1 -> cAObj -> cASN1\n\t\t  04 nn nn\t\t\t\t\t\t\t\t\t\tcASN1 -> cPrim\n\n\t30 80\t\t\tcASN1 -> cAObj -> cASN1\n\t   30 80\t\t\t\t\t\t  cASN1 -> cAObj -> cASN1\n\t\t  04 nn nn\t\t\t\t\t\t\t\t\t\tcASN1 -> cPrim\n\t   00 00\t\t\t\t\t\t  cASN1 <- cAObj <- cASN1\n\t00 00\t\t\tcASN1 <- cAObj <- cASN1\n\n   The use of checkASN1Object() leads to an (apparently) excessively deep \n   call hierarchy, but that's mostly just an artefact of the way that it's \n   diagrammed here */\n\nCHECK_RETVAL_ENUM( ASN1_STATE ) STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic ASN1_STATE checkASN1Object( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   const ASN1_ITEM *item,\n\t\t\t\t\t\t\t\t   IN_RANGE( 1, MAX_NESTING_LEVEL ) \\\n\t\t\t\t\t\t\t\t\t\tconst int level, \n\t\t\t\t\t\t\t\t   IN_ENUM_OPT( ASN1_STATE ) \\\n\t\t\t\t\t\t\t\t\t\tconst ASN1_STATE state,\n\t\t\t\t\t\t\t\t   IN_ENUM_OPT( CHECK_ENCODING ) \\\n\t\t\t\t\t\t\t\t\t\tconst CHECK_ENCODING_TYPE checkType,\n\t\t\t\t\t\t\t\t   const BOOLEAN checkDataElements )\n\t{\n\tASN1_STATE newState;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( item, sizeof( ASN1_ITEM ) ) );\n\n\tREQUIRES_EXT( level > 0 && level <= MAX_NESTING_LEVEL, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( state >= ASN1_STATE_NONE && state < ASN1_STATE_ERROR, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( isEnumRangeOpt( checkType, CHECK_ENCODING ), \n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( ( checkDataElements == TRUE && item->headerSize ) || \\\n\t\t\t\t  checkDataElements == FALSE, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\t\t\t\t  /* Definite-length items are handled by the caller for a \n\t\t\t\t     length-only check */\n\n\t/* Make sure that we're not processing suspiciosly deeply nested data */\n\tif( level >= MAX_NESTING_LEVEL )\n\t\treturn( ASN1_STATE_ERROR );\n\n\t/* Check the contents for validity.  A straight data-length check doesn't \n\t   check nested elements since all it cares about is finding the overall \n\t   length with as little effort as possible */\n\tif( ( item->tag & BER_CLASS_MASK ) == BER_UNIVERSAL )\n\t\t{\n\t\t/* If it's constructed, parse the nested object(s) */\n\t\tif( ( item->tag & BER_CONSTRUCTED_MASK ) == BER_CONSTRUCTED )\n\t\t\t{\n\t\t\t/* Special-case for zero-length SEQUENCE/SET */\n\t\t\tif( item->length <= 0 && !item->isIndefinite )\n\t\t\t\treturn( ASN1_STATE_NONE );\n\n\t\t\treturn( checkASN1( stream, item->length, item->isIndefinite,\n\t\t\t\t\t\t\t   level + 1, ( item->tag == BER_SEQUENCE ) ? \\\n\t\t\t\t\t\t\t\t\tASN1_STATE_SEQUENCE : ASN1_STATE_NONE,\n\t\t\t\t\t\t\t   checkType, checkDataElements ) );\n\t\t\t}\n\n\t\t/* It's primitive, check the primitive element with optional state\n\t\t   update: SEQ + OID -> HOLE_OID; OID + { NULL | BOOLEAN } -> \n\t\t   HOLE_BITSTRING/HOLE_OCTETSTRING */\n\t\tnewState = checkPrimitive( stream, item, level + 1, state, checkType );\n\t\tif( newState < ASN1_STATE_NONE || newState >= ASN1_STATE_ERROR )\n\t\t\treturn( ASN1_STATE_ERROR );\n\t\tif( state == ASN1_STATE_SEQUENCE && newState == ASN1_STATE_OID )\n\t\t\treturn( ASN1_STATE_HOLE_OID );\n\t\tif( state == ASN1_STATE_HOLE_OID )\n\t\t\t{\n#if 0\t/* See comment at start */\n\t\t\tif( newState == ASN1_STATE_NULL )\n\t\t\t\treturn( ASN1_STATE_CHECK_HOLE_BITSTRING );\n#endif /* 0 */\n\t\t\tif( newState == ASN1_STATE_BOOLEAN )\n\t\t\t\treturn( ASN1_STATE_CHECK_HOLE_OCTETSTRING );\n\t\t\t}\n\t\treturn( ASN1_STATE_NONE );\n\t\t}\n\n\t/* Zero-length objects are usually an error, however PKCS #10 has an\n\t   attribute-encoding ambiguity that produces zero-length tagged \n\t   extensions and OCSP has its braindamaged context-specific tagged \n\t   NULLs so we don't complain about them if they have low-valued \n\t   context-specific tags */\n\tif( item->length <= 0 && !item->isIndefinite )\n\t\t{\n\t\treturn( ( ( item->tag & BER_CLASS_MASK ) == BER_CONTEXT_SPECIFIC && \\\n\t\t\t\t  EXTRACT_CTAG( item->tag ) <= 3 ) ? \\\n\t\t\t\tASN1_STATE_NONE : ASN1_STATE_ERROR );\n\t\t}\n\n\tENSURES_EXT( item->length > 0 || item->isIndefinite, ASN1_STATE_ERROR );\n\n\t/* If it's constructed, parse the nested object(s) */\n\tif( ( item->tag & BER_CONSTRUCTED_MASK ) == BER_CONSTRUCTED )\n\t\t{\n\t\tnewState = checkASN1( stream, item->length, item->isIndefinite,\n\t\t\t\t\t\t\t  level + 1, ASN1_STATE_NONE, checkType,\n\t\t\t\t\t\t\t  checkDataElements );\n\t\treturn( ( newState < ASN1_STATE_NONE || newState >= ASN1_STATE_ERROR ) ? \\\n\t\t\t\tASN1_STATE_ERROR : ASN1_STATE_NONE );\n\t\t}\n\n\t/* It's a context-specific tagged item that could contain anything, just \n\t   skip it */\n\tif( ( item->length <= 0 ) || \\\n\t\t( ( item->tag & BER_CLASS_MASK ) != BER_CONTEXT_SPECIFIC ) )\n\t\t{\n\t\treturn( ASN1_STATE_ERROR );\n\t\t}\n\treturn( cryptStatusError( \\\n\t\t\t\tsSkip( stream, item->length, SSKIP_MAX ) ) ? \\\n\t\t\tASN1_STATE_ERROR : ASN1_STATE_NONE );\n\t}\n\n/* Check a complex ASN.1 object.  In order to handle huge CRLs with tens or \n   hundreds of thousands of individual entries we can't use a fixed loop \n   failsafe iteration count but have to vary it based on the size of the \n   input data.  Luckily this situation is relatively easy to check for, it \n   only occurs at a nesting level of 6 (when we find the CRL entries) and we \n   only have to enable it when the data length is more than 30K since the \n   default FAILSAFE_ITERATIONS_LARGE will handle anything smaller than that */\n\nCHECK_RETVAL_ENUM( ASN1_STATE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ASN1_STATE checkASN1( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_DATALENGTH_Z const long length, \n\t\t\t\t\t\t\t const BOOLEAN isIndefinite, \n\t\t\t\t\t\t\t IN_RANGE( 0, MAX_NESTING_LEVEL ) const int level, \n\t\t\t\t\t\t\t IN_ENUM_OPT( ASN1_STATE ) ASN1_STATE state, \n\t\t\t\t\t\t\t IN_ENUM_OPT( CHECK_ENCODING ) \\\n\t\t\t\t\t\t\t\tconst CHECK_ENCODING_TYPE checkType,\n\t\t\t\t\t\t\t const BOOLEAN checkDataElements )\n\t{\n\tASN1_ITEM item;\n\tASN1_STATE newState DUMMY_INIT;\n\tconst long maxIterationCount = ( level == 6 && length > 30000 ) ? \\\n\t\t\t\t\t\t\t\t\t length / 25 : FAILSAFE_ITERATIONS_LARGE - 1;\n\tlong localLength = length, lastPos = stell( stream );\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_EXT( ( level > 0 && level <= MAX_NESTING_LEVEL ) || \\\n\t\t\t\t  ( level == 0 && length == LENGTH_MAGIC ), \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( isIndefinite == TRUE || isIndefinite == FALSE, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( ( isIndefinite && length == 0 ) || \\\n\t\t\t\t  ( !isIndefinite && length >= 0 && length < MAX_BUFFER_SIZE ),\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( state >= ASN1_STATE_NONE && state < ASN1_STATE_ERROR, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( isEnumRangeOpt( checkType, CHECK_ENCODING ), \n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( checkDataElements == TRUE || checkDataElements == FALSE, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\tREQUIRES_EXT( lastPos >= 0 && lastPos < MAX_BUFFER_SIZE, \\\n\t\t\t\t  ASN1_STATE_ERROR );\n\n\t/* Make sure that we're not processing suspiciosly deeply nested data */\n\tif( level >= MAX_NESTING_LEVEL )\n\t\treturn( ASN1_STATE_ERROR );\n\n\tLOOP_MAX( iterationCount = 0,\n\t\t\t  ( newState = getItem( stream, &item ) ) == ASN1_STATE_NONE && \\\n\t\t\t\titerationCount < maxIterationCount,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\t/* If this is the top level (for which the length isn't known in\n\t\t   advance) and the item has a definite length, set the length to \n\t\t   the item's length */\n\t\tif( level <= 0 && !item.isIndefinite )\n\t\t\tlocalLength = item.headerSize + item.length;\n\n\t\t/* If this is an EOC (tag == BER_RESERVED) for an indefinite item, \n\t\t   we're done */\n\t\tif( isIndefinite && item.tag == BER_RESERVED )\n\t\t\treturn( ASN1_STATE_NONE );\n\n\t\t/* Check the object */\n\t\tif( !checkDataElements && !item.isIndefinite )\n\t\t\t{\n\t\t\t/* Shortcut to save a level of recursion, if we're not \n\t\t\t   interested in the data elements (i.e. if we're just doing a\n\t\t\t   length check) and the item has a definite length, just skip \n\t\t\t   over it and continue */\n\t\t\tif( item.length > 0 && \\\n\t\t\t\tcryptStatusError( sSkip( stream, item.length, SSKIP_MAX ) ) )\n\t\t\t\t{\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tnewState = checkASN1Object( stream, &item, level + 1, state, \n\t\t\t\t\t\t\t\t\t\tcheckType, checkDataElements );\n\t\t\tif( newState < ASN1_STATE_NONE || newState >= ASN1_STATE_ERROR )\n\t\t\t\treturn( ASN1_STATE_ERROR );\n\t\t\t}\n\n\t\t/* If it's an indefinite-length object, we have to keep going until \n\t\t   we find the EOC octets */\n\t\tif( isIndefinite )\n\t\t\tcontinue;\n\n\t\t/* If the outermost object was of indefinite length and we've come \n\t\t   back to the top level, exit.  The isIndefinite flag won't be set\n\t\t   at this point because we can't know the length status before we\n\t\t   start, but it's implicitly indicated by finding a length of\n\t\t   LENGTH_MAGIC at the topmost level */\n\t\tif( level == 0 && length == LENGTH_MAGIC )\n\t\t\treturn( ASN1_STATE_NONE );\n\n\t\t/* Check whether we've reached the end of the current (definite-\n\t\t   length) object */\n\t\tlocalLength -= stell( stream ) - lastPos;\n\t\tlastPos = stell( stream );\n\t\tif( localLength < 0 || localLength >= MAX_BUFFER_SIZE )\n\t\t\treturn( ASN1_STATE_ERROR );\n\t\tif( localLength == 0 )\n\t\t\t{\n\t\t\t/* We've reached the end of the object, we're done */\n\t\t\treturn( newState );\n\t\t\t}\n\n\t\t/* We're reading more data from the current object, propagate any\n\t\t   state updates */\n\t\tstate = newState;\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, ASN1_STATE_ERROR );\n\tif( iterationCount >= maxIterationCount )\n\t\t{\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( ASN1_STATE_ERROR );\n\t\t}\n\n\treturn( ( newState == ASN1_STATE_NONE ) ? \\\n\t\t\tASN1_STATE_NONE : ASN1_STATE_ERROR );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tASN.1 Check Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the encoding of a complete object and determine its length (qui \n   omnes insidias timet in nullas incidit - Pubilius Syrus) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkEncoding( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t  IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t  OUT_OPT_DATALENGTH_Z int *objectActualSize,\n\t\t\t\t\t\t  IN_ENUM_OPT( CHECK_ENCODING ) \\\n\t\t\t\t\t\t\t\tconst CHECK_ENCODING_TYPE checkType )\n\t{\n\tSTREAM stream;\n\tASN1_STATE state;\n\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\tassert( objectActualSize == NULL || \\\n\t\t\tisWritePtr( objectActualSize, sizeof( int ) ) );\n\t\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( checkType, CHECK_ENCODING ) );\n\n\t/* Clear return value */\n\tif( objectActualSize != NULL )\n\t\t*objectActualSize = 0;\n\n\tsMemConnect( &stream, objectPtr, objectLength );\n\tstate = checkASN1( &stream, LENGTH_MAGIC, FALSE, 0, ASN1_STATE_NONE, \n\t\t\t\t\t   checkType, TRUE );\n\tif( state >= ASN1_STATE_NONE && state < ASN1_STATE_ERROR )\n\t\t{\n\t\t/* We've processed the object, return its length if required */\n\t\tif( objectActualSize != NULL )\n\t\t\t*objectActualSize = stell( &stream );\n\t\t}\n\tsMemDisconnect( &stream );\n\treturn( ( state < ASN1_STATE_NONE ) ? CRYPT_ERROR_INTERNAL : \\\n\t\t\t( state >= ASN1_STATE_ERROR ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t IN_DATALENGTH const int objectLength )\n\t{\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\t\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Check an ASN.1 object in the absence of hole encodings.  This is \n\t   possible because non-certificate objects use the CMS form for \n\t   attributes, SEQUENCE { OID, SET {} } rather than the certificate \n\t   form, SEQUENCE { OID, OCTET STRING {} } */\n\treturn( checkEncoding( objectPtr, objectLength, NULL, \n\t\t\t\t\t\t   CHECK_ENCODING_NONE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkObjectEncodingLength( IN_BUFFER( objectLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *objectPtr, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *objectActualSize )\n\t{\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\tassert( isWritePtr( objectActualSize, sizeof( int ) ) );\n\t\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*objectActualSize = 0;\n\n\t/* Check an ASN.1 object in the absence of hole encodings in most cases.  \n\t   This is an awkward intersection between CHECK_ENCODING_NONE (for CMS \n\t   objects) and CHECK_ENCODING_ENCAPS (for certificate objects) that \n\t   occurs in things like PKI messaging, where a more general CMS object \n\t   may have a certificate attached */\n\treturn( checkEncoding( objectPtr, objectLength, objectActualSize, \n\t\t\t\t\t\t   CHECK_ENCODING_SEMIENCAPS ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkCertObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t\t IN_DATALENGTH const int objectLength )\n\t{\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\t\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Check an ASN.1 object in the presence of OCTET STRING and BIT STRING \n\t   holes */\n\treturn( checkEncoding( objectPtr, objectLength, NULL, \n\t\t\t\t\t\t   CHECK_ENCODING_ENCAPS ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkCertObjectEncodingLength( IN_BUFFER( objectLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *objectPtr, \n\t\t\t\t\t\t\t\t   IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *objectActualSize )\n\t{\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\tassert( isWritePtr( objectActualSize, sizeof( int ) ) );\n\t\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*objectActualSize = 0;\n\n\t/* Check an ASN.1 object in the presence of OCTET STRING and BIT STRING \n\t   holes */\n\treturn( checkEncoding( objectPtr, objectLength, objectActualSize, \n\t\t\t\t\t\t   CHECK_ENCODING_ENCAPS ) );\n\t}\n\n/* Recursively dig into an ASN.1 object as far as we need to to determine \n   its length */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int findObjectLength( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_DATALENGTH_Z long *length, \n\t\t\t\t\t\t\t const BOOLEAN isLongObject )\n\t{\n\tconst long startPos = stell( stream );\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\tREQUIRES( isLongObject == TRUE || isLongObject == FALSE );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Try for a definite length (quo usque tandem?) */\n\tstatus = readGenericObjectHeader( stream, &localLength, isLongObject );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's an indefinite-length object, burrow down into it to find its \n\t   actual length */\n\tif( localLength == CRYPT_UNUSED )\n\t\t{\n\t\tASN1_STATE state;\n\n\t\t/* We have to be a bit careful how we handle error reporting for \n\t\t   this since we can run out of input and hit an underflow while \n\t\t   we're in the process of burrowing through the data.  This is \n\t\t   somewhat unfortunate since it leads to non-orthogonal behaviour \n\t\t   because a definite length only requires checking a few bytes at \n\t\t   the start of the data but an indefinite length requires \n\t\t   processing the entire data quantity in order to determine where \n\t\t   it ends */\n\t\tsseek( stream, startPos );\n\t\tstate = checkASN1( stream, LENGTH_MAGIC, FALSE, 0, ASN1_STATE_NONE,\n\t\t\t\t\t\t   CHECK_ENCODING_NONE, FALSE );\n\t\tif( state < ASN1_STATE_NONE || state >= ASN1_STATE_ERROR )\n\t\t\t{\n\t\t\treturn( ( state < ASN1_STATE_NONE ) ? \\\n\t\t\t\t\t\tCRYPT_ERROR_INTERNAL : \\\n\t\t\t\t\t( sGetStatus( stream ) == CRYPT_ERROR_UNDERFLOW ) ? \\\n\t\t\t\t\t\tCRYPT_ERROR_UNDERFLOW : \\\n\t\t\t\t\t\tCRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tlocalLength = stell( stream ) - startPos;\n\t\t}\n\telse\n\t\t{\n\t\t/* We've read the length information directly from the object rather\n\t\t   than calculating it ourselves, make sure that the it's within \n\t\t   bounds */\n\t\tif( localLength > sMemDataLeft( stream ) )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t\t/* It's a definite-length object, add the size of the tag+length */\n\t\tlocalLength += stell( stream ) - startPos;\n\t\t}\n\n\t/* An object needs to consist of at least a tag and a length */\n\tif( !isIntegerRange( localLength ) || localLength <= 1 + 1 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If it's not a long object, make sure that the length is within bounds.  \n\t   We have to do this explicitly here because indefinite-length objects\n\t   can be arbitrarily large so the length isn't checked as it is for\n\t   readGenericHoleI() */\n\tif( !isLongObject && localLength > MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t*length = localLength;\n\treturn( sseek( stream, startPos ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getStreamObjectLength( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length )\n\t{\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tstatus = findObjectLength( stream, &localLength, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t*length = localLength;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getLongStreamObjectLength( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z long *length )\n\t{\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tstatus = findObjectLength( stream, &localLength, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\t*length = localLength;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getObjectLength( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t IN_DATALENGTH const int objectLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *length )\n\t{\n\tSTREAM stream;\n\tlong localLength DUMMY_INIT;\n\tint status;\n\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tsMemConnect( &stream, objectPtr, objectLength );\n\tstatus = findObjectLength( &stream, &localLength, FALSE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*length = localLength;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getLongObjectLength( IN_BUFFER( objectLength ) const void *objectPtr, \n\t\t\t\t\t\t IN_DATALENGTH const long objectLength,\n\t\t\t\t\t\t OUT_DATALENGTH_Z long *length )\n\t{\n\tSTREAM stream;\n\tlong localLength;\n\tint status;\n\n\tassert( isReadPtrDynamic( objectPtr, objectLength ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tsMemConnect( &stream, objectPtr, objectLength );\n\tstatus = findObjectLength( &stream, &localLength, TRUE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*length = localLength;\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_ASN1 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_ext.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tASN.1 Supplemental Read/Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage Digest Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write a message digest value.  This is another one of those oddball\n   functions which is present here because it's the least inappropriate place\n   to put it */\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofMessageDigest( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo, \n\t\t\t\t\t\t IN_LENGTH_HASH const int hashSize )\n\t{\n\tint algoInfoSize, hashInfoSize, status;\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\n\tif( isParameterisedHashAlgo( hashAlgo ) )\n\t\tstatus = algoInfoSize = sizeofAlgoIDex( hashAlgo, hashSize );\n\telse\n\t\tstatus = algoInfoSize = sizeofAlgoID( hashAlgo );\n\tENSURES( !cryptStatusError( status ) );\n\thashInfoSize = sizeofObject( hashSize );\n\tENSURES( algoInfoSize > 8 && algoInfoSize < MAX_INTLENGTH_SHORT );\n\tENSURES( hashInfoSize > hashSize && hashInfoSize < MAX_INTLENGTH_SHORT );\n\n\treturn( sizeofObject( algoInfoSize + hashInfoSize ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint writeMessageDigest( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\tIN_BUFFER( hashSize ) const void *hash, \n\t\t\t\t\t\tIN_LENGTH_HASH const int hashSize )\n\t{\n\tint algoInfoSize, status;\n\t\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( hash, hashSize ) );\n\n\tREQUIRES_S( isHashAlgo( hashAlgo ) );\n\tREQUIRES_S( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\n\tif( isParameterisedHashAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = algoInfoSize = sizeofAlgoIDex( hashAlgo, hashSize );\n\t\tENSURES( !cryptStatusError( status ) );\n\t\twriteSequence( stream, algoInfoSize + sizeofShortObject( hashSize ) );\n\t\tstatus = writeAlgoIDex( stream, hashAlgo, hashSize, 0 );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = algoInfoSize = sizeofAlgoID( hashAlgo );\n\t\tENSURES( !cryptStatusError( status ) );\n\t\twriteSequence( stream, algoInfoSize + sizeofShortObject( hashSize ) );\n\t\tstatus = writeAlgoID( stream, hashAlgo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeOctetString( stream, hash, hashSize, DEFAULT_TAG );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readMessageDigest( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,\n\t\t\t\t\t   OUT_BUFFER( hashMaxLen, *hashSize ) void *hash, \n\t\t\t\t\t   IN_LENGTH_HASH const int hashMaxLen, \n\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( hashMaxLen ) int *hashSize )\n\t{\n\tint hashAlgoSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( hashAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtrDynamic( hash, hashMaxLen ) );\n\tassert( isWritePtr( hashSize, sizeof( int ) ) );\n\n\tREQUIRES_S( hashMaxLen >= MIN_HASHSIZE && hashMaxLen <= 8192 );\n\n\t/* Clear the return values */\n\tmemset( hash, 0, min( 16, hashMaxLen ) );\n\t*hashSize = 0;\n\n\t/* Read the message digest, enforcing sensible size values */\n\tstatus = readSequence( stream, NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDex( stream, hashAlgo, NULL, &hashAlgoSize, \n\t\t\t\t\t\t\t   ALGOID_CLASS_HASH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readOctetString( stream, hash, hashSize, MIN_HASHSIZE, \n\t\t\t\t\t\t\t\t  hashMaxLen );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a parameterised hash algorithm, make sure that the amount of \n\t   hash data matches the algorithm parameter */\n\tif( hashAlgoSize != 0 && hashAlgoSize != *hashSize )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMS Header Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read and write CMS headers.  When reading CMS headers we check a bit more\n   than just the header OID, which means that we need to provide additional\n   information alongside the OID information.  This is provided as\n   CMS_CONTENT_INFO in the OID info extra data field */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCMSheader( INOUT STREAM *stream, \n\t\t\t\t   IN_ARRAY( noOidInfoEntries ) const OID_INFO *oidInfo, \n\t\t\t\t   IN_RANGE( 1, 50 ) const int noOidInfoEntries, \n\t\t\t\t   OUT_OPT_INT_Z int *selectionID,\n\t\t\t\t   OUT_OPT_LENGTH_INDEF long *dataSize, \n\t\t\t\t   IN_FLAGS_Z( READCMS ) const int flags )\n\t{\n\tconst OID_INFO *oidInfoPtr;\n\tBOOLEAN isData = FALSE, isDetachedSig = FALSE;\n\tlong savedLength = CRYPT_UNUSED, savedLengthDataStart DUMMY_INIT;\n\tlong length, value;\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oidInfo, \\\n\t\t\t\t\t\t\t  sizeof( OID_INFO ) * noOidInfoEntries ) );\n\tassert( dataSize == NULL || isWritePtr( dataSize, sizeof( long ) ) );\n\n\tREQUIRES_S( noOidInfoEntries > 0 && noOidInfoEntries <= 50 );\n\tREQUIRES_S( isFlagRangeZ( flags, READCMS ) );\n\tREQUIRES_S( !( ( flags & ( READCMS_FLAG_DEFINITELENGTH | \\\n\t\t\t\t\t\t\t   READCMS_FLAG_DEFINITELENGTH_OPT ) ) && \\\n\t\t\t\t   ( dataSize == NULL ) ) );\n\tREQUIRES_S( !( ( flags & READCMS_FLAG_WRAPPERONLY ) && \\\n\t\t\t\t   ( oidInfo[ 0 ].extraInfo != NULL ) ) );\n\tREQUIRES_S( !( flags & READCMS_FLAG_AUTHENC ) );\n\n\t/* Clear return values */\n\tif( selectionID != NULL )\n\t\t*selectionID = 0;\n\tif( dataSize != NULL )\n\t\t*dataSize = 0;\n\n\t/* Read the outer SEQUENCE and OID.  We can't use a normal\n\t   readSequence() here because the data length could be much longer than\n\t   the maximum allowed in the readSequence() sanity check */\n\tstatus = readLongSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != CRYPT_UNUSED )\n\t\t{\n\t\tsavedLength = length;\n\t\tsavedLengthDataStart = stell( stream );\n\t\t}\n\tstatus = readOIDEx( stream, oidInfo, noOidInfoEntries, &oidInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the content type is data then the content is an OCTET STRING \n\t   rather than a SEQUENCE so we remember the type for later.  Since \n\t   there are a pile of CMS OIDs of the same length as OID_CMS_DATA, we \n\t   check for a match on the last byte before we perform a full OID \n\t   match */\n\tstatic_assert_opt( sizeofOID( OID_CMS_DATA ) == 11, \\\n\t\t\t\t\t   \"Data OID size\" );\n\tif( sizeofOID( oidInfoPtr->oid ) == sizeofOID( OID_CMS_DATA ) && \\\n\t\toidInfoPtr->oid[ 10 ] == OID_CMS_DATA[ 10 ] && \\\n\t\t!memcmp( oidInfoPtr->oid, OID_CMS_DATA, \\\n\t\t\t\t sizeofOID( OID_CMS_DATA ) ) )\n\t\t{\n\t\tisData = TRUE;\n\t\t}\n\n\t/* Check for the special-case situation of a detached signature, for \n\t   which the the total content consists only of the OID, which means \n\t   that the overall object is SEQUENCE { OID data } */\n\tif( length != CRYPT_UNUSED )\n\t\t{\n\t\tif( length <= sizeofOID( oidInfoPtr->oid ) )\n\t\t\t{\n\t\t\tif( length != sizeofOID( oidInfoPtr->oid ) )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\tisDetachedSig = TRUE;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Some Microsoft software produces an indefinite encoding for a \n\t\t   single OID so we have to check for this */\n\t\tstatus = checkEOC( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( status == TRUE )\n\t\t\tisDetachedSig = TRUE;\n\t\t}\n\tif( isDetachedSig )\n\t\t{\n\t\t/* It appears to be a detached signature, make sure that the \n\t\t   requirements are met, namely that it's data content and present\n\t\t   in an inner header */\n\t\tif( !( isData && ( flags & READCMS_FLAG_INNERHEADER ) ) )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t\t/* It's a detached signature, we're done */\n\t\tif( selectionID != NULL )\n\t\t\t*selectionID = oidInfoPtr->selectionID;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read the content [0] tag and OCTET STRING/SEQUENCE.  This requires\n\t   some special-case handling, see the comment in writeCMSHeader() for\n\t   more details */\n\tstatus = readLongConstructed( stream, &length, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != CRYPT_UNUSED )\n\t\t{\n\t\tsavedLength = length;\n\t\tsavedLengthDataStart = stell( stream );\n\t\t}\n\tif( flags & READCMS_FLAG_WRAPPERONLY )\n\t\t{\n\t\t/* We're only reading the outer wrapper in order to accomodate\n\t\t   redundantly nested CMS content types, don't try and read\n\t\t   any further */\n\t\tENSURES( !( flags & ( READCMS_FLAG_DEFINITELENGTH | \\\n\t\t\t\t\t\t\t  READCMS_FLAG_DEFINITELENGTH_OPT ) ) );\n\t\tif( dataSize != NULL )\n\t\t\t*dataSize = length;\n\t\tif( selectionID != NULL )\n\t\t\t*selectionID = oidInfoPtr->selectionID;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isData )\n\t\t{\n\t\t/* It's pure data content, it must be an OCTET STRING */\n\t\tif( tag != BER_OCTETSTRING && \\\n\t\t\ttag != ( BER_OCTETSTRING | BER_CONSTRUCTED ) )\n\t\t\t{\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( flags & READCMS_FLAG_INNERHEADER )\n\t\t\t{\n\t\t\t/* It's an inner header, it should be an OCTET STRING but\n\t\t\t   alternative interpretations are possible based on the old\n\t\t\t   PKCS #7 definition of inner content */\n\t\t\tif( tag != BER_OCTETSTRING && \\\n\t\t\t\ttag != ( BER_OCTETSTRING | BER_CONSTRUCTED ) && \\\n\t\t\t\ttag != BER_SEQUENCE )\n\t\t\t\t{\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's an outer header containing other than data, it must be a\n\t\t\t   SEQUENCE */\n\t\t\tif( tag != BER_SEQUENCE )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tstatus = readLongGenericHole( stream, &length, tag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length == CRYPT_UNUSED && \\\n\t\t( flags & ( READCMS_FLAG_DEFINITELENGTH | \\\n\t\t\t\t\tREADCMS_FLAG_DEFINITELENGTH_OPT ) ) )\n\t\t{\n\t\t/* We've been asked to provide a definite length but the currently\n\t\t   available length information is indefinite, see if there's length\n\t\t   information present from an earlier header */\n\t\tif( savedLength == CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* If we've been asked to provide a definite length but there's \n\t\t\t   none available, return an error */\n\t\t\tif( flags & READCMS_FLAG_DEFINITELENGTH )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The content length is the originally read length minus the\n\t\t\t   data read since that point */\n\t\t\tlength = savedLength - ( stell( stream ) - savedLengthDataStart );\n\t\t\tif( !isIntegerRangeNZ( length ) )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\n\t/* If it's structured (i.e. not data in an OCTET STRING), check the\n\t   version number of the content if required */\n\tif( !isData && oidInfoPtr->extraInfo != NULL )\n\t\t{\n\t\tconst CMS_CONTENT_INFO *contentInfoPtr = oidInfoPtr->extraInfo;\n\t\tconst int startPos = stell( stream );\n\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value < contentInfoPtr->minVersion || \\\n\t\t\tvalue > contentInfoPtr->maxVersion )\n\t\t\t{\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t\n\t\t/* Adjust the length value for the additional content that we've \n\t\t   read if necessary */\n\t\tif( length != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tlength -= stell( stream ) - startPos;\n\t\t\tif( !isIntegerRangeNZ( length ) )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\n\t/* Finally, if there's a definite length given then there has to be \n\t   some content present, at least a SEQUENCE/OCTET STRING containing a\n\t   single ASN.1 item */\n\tif( length != CRYPT_UNUSED )\n\t\t{\n\t\t/* Data is a raw OCTET STRING rather than compound data, so the \n\t\t   length can be a single byte */\n\t\tif( isData )\n\t\t\t{\n\t\t\tif( length < 1 )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( length < sizeofObject( sizeofObject( 1 ) ) )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\n\tif( dataSize != NULL )\n\t\t*dataSize = length;\n\tif( selectionID != NULL )\n\t\t*selectionID = oidInfoPtr->selectionID;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCMSheader( INOUT STREAM *stream, \n\t\t\t\t\tIN_BUFFER( contentOIDlength ) const BYTE *contentOID, \n\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\tIN_LENGTH_INDEF const long dataSize, \n\t\t\t\t\tconst BOOLEAN isInnerHeader )\n\t{\n\tBOOLEAN isOctetString = ( isInnerHeader || \\\n\t\t\t\t\t\t\t  ( contentOIDlength == 11 && \\\n\t\t\t\t\t\t\t  !memcmp( contentOID, OID_CMS_DATA, 11 ) ) ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( contentOID, contentOIDlength ) && \\\n\t\t\tcontentOIDlength == sizeofOID( contentOID ) );\n\n\tREQUIRES_S( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );\n\tREQUIRES_S( contentOIDlength >= MIN_OID_SIZE && \\\n\t\t\t\tcontentOIDlength <= MAX_OID_SIZE );\n\tREQUIRES_S( dataSize == CRYPT_UNUSED || isIntegerRange( dataSize ) );\n\t\t\t\t/* May be zero for degenerate (detached) signatures */\n\tREQUIRES( isInnerHeader == TRUE || isInnerHeader == FALSE );\n\n\t/* The handling of the wrapper type for the content is rather complex.\n\t   If it's an outer header, it's an OCTET STRING for data and a SEQUENCE\n\t   for everything else.  If it's an inner header it usually follows the\n\t   same rule, however for signed data the content was changed from\n\n\t\tcontent [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL\n\n\t   in PKCS #7 to\n\n\t\teContent [0] EXPLICIT OCTET STRING OPTIONAL\n\n\t   for CMS (it was always an OCTET STRING for encrypted data).  To\n\t   complicate things, there are some older implementations based on the\n\t   original PKCS #7 interpretation that use a SEQUENCE (namely\n\t   AuthentiCode).  To resolve this we use an OCTET STRING for inner\n\t   content unless the content type is spcIndirectDataContext */\n\tif( isInnerHeader && contentOIDlength == 12 && \\\n\t\t!memcmp( contentOID, OID_MS_SPCINDIRECTDATACONTEXT, 12 ) )\n\t\tisOctetString = FALSE;\n\n\t/* If a size is given, write the definite form */\n\tif( dataSize != CRYPT_UNUSED )\n\t\t{\n\t\tint status;\n\n\t\twriteSequence( stream, contentOIDlength + ( ( dataSize > 0 ) ? \\\n\t\t\t\t\t   sizeofObject( sizeofObject( dataSize ) ) : 0 ) );\n\t\tstatus = swrite( stream, contentOID, contentOIDlength );\n\t\tif( dataSize <= 0 )\n\t\t\treturn( status );\t/* No content, exit */\n\t\twriteConstructed( stream, sizeofObject( dataSize ), 0 );\n\t\tif( isOctetString )\n\t\t\treturn( writeOctetStringHole( stream, dataSize, DEFAULT_TAG ) );\n\t\treturn( writeSequence( stream, dataSize ) );\n\t\t}\n\n\t/* No size given, write the indefinite form */\n\twriteSequenceIndef( stream );\n\tswrite( stream, contentOID, contentOIDlength );\n\twriteCtag0Indef( stream );\n\treturn( isOctetString ? writeOctetStringIndef( stream ) : \\\n\t\t\t\t\t\t\twriteSequenceIndef( stream ) );\n\t}\n\n/* Read and write an encryptedContentInfo header.  The inner content may be\n   implicitly or explicitly tagged depending on the exact content type */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofCMSencrHeader( IN_BUFFER( contentOIDlength ) const BYTE *contentOID, \n\t\t\t\t\t\t IN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\t IN_LENGTH_INDEF const long dataSize, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tSTREAM nullStream;\n\tint length, cryptInfoSize DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( contentOID, contentOIDlength ) && \\\n\t\t\tcontentOIDlength == sizeofOID( contentOID ) );\n\n\tREQUIRES( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );\n\tREQUIRES( contentOIDlength >= MIN_OID_SIZE && \\\n\t\t\t  contentOIDlength <= MAX_OID_SIZE );\n\tREQUIRES( dataSize == CRYPT_UNUSED || isIntegerRangeNZ( dataSize ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Determine the encoded size of the AlgorithmIdentifier */\n\tsMemNullOpen( &nullStream );\n\tstatus = writeCryptContextAlgoID( &nullStream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\tcryptInfoSize = stell( &nullStream );\n\tsMemClose( &nullStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate the encoded size of the SEQUENCE + OID + AlgoID + [0] for\n\t   the definite or indefinite forms */\n\tif( dataSize == CRYPT_UNUSED )\n\t\t{\n\t\t/* The size 2 is for the tag + 0x80 indefinite-length indicator and \n\t\t   the EOC octets at the end */\n\t\treturn( 2 + contentOIDlength + cryptInfoSize + 2 );\n\t\t}\n\tlength = sizeofObject( contentOIDlength + cryptInfoSize + \\\n\t\t\t\t\t\t   sizeofObject( dataSize ) ) - dataSize;\n\tENSURES( isIntegerRange( length ) );\n\treturn( length );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCMSencrHeader( INOUT STREAM *stream, \n\t\t\t\t\t   IN_ARRAY( noOidInfoEntries ) const OID_INFO *oidInfo,\n\t\t\t\t\t   IN_RANGE( 1, 50 ) const int noOidInfoEntries, \n\t\t\t\t\t   OUT_OPT_INT_Z int *selectionID,\n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t   OUT_OPT QUERY_INFO *queryInfo,\n\t\t\t\t\t   IN_FLAGS_Z( READCMS ) const int flags )\n\t{\n\tQUERY_INFO localQueryInfo, *queryInfoPtr = ( queryInfo == NULL ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t   &localQueryInfo : queryInfo;\n\tlong length;\n\tint tag, selectionValue, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oidInfo, \\\n\t\t\t\t\t\t\t  sizeof( OID_INFO ) * noOidInfoEntries ) );\n\tassert( iCryptContext == NULL || \\\n\t\t\tisWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( queryInfo == NULL || \\\n\t\t\tisWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES_S( noOidInfoEntries > 0 && noOidInfoEntries <= 50 );\n\tREQUIRES_S( isFlagRangeZ( flags, READCMS ) );\n\tREQUIRES_S( ( flags & ~( READCMS_FLAG_AUTHENC | \\\n\t\t\t\t\t\t\t READCMS_FLAG_DEFINITELENGTH ) ) == 0 );\n\n\t/* Clear return values */\n\tif( selectionID != NULL )\n\t\t*selectionID = 0;\n\tif( iCryptContext != NULL )\n\t\t*iCryptContext = CRYPT_ERROR;\n\tmemset( queryInfoPtr, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the outer SEQUENCE, content-type OID, and encryption \n\t   AlgorithmIdentifier.  We can't use a normal readSequence() here \n\t   because the data length could be much longer than the maximum allowed \n\t   in the readSequence() sanity check */\n\treadLongSequence( stream, NULL );\n\tstatus = readOID( stream, oidInfo, noOidInfoEntries, &selectionValue );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readContextAlgoID( stream, iCryptContext, queryInfoPtr,\n\t\t\t\t\t\tDEFAULT_TAG, ( flags & READCMS_FLAG_AUTHENC ) ? \\\n\t\t\t\t\t\t\tALGOID_CLASS_AUTHENC : ALGOID_CLASS_CRYPT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up any further query info fields.  Since this isn't a proper key \n\t   exchange or signature object we can't properly set up all of the \n\t   remaining fields like the type (it's not any CRYPT_OBJECT_TYPE) or \n\t   version fields */\n\tqueryInfoPtr->formatType = CRYPT_FORMAT_CMS;\n\n\t/* Read the content [0] tag, which may be either primitive or constructed\n\t   depending on the content */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readLongGenericHole( stream, &length, tag );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Make sure that the inner content type has the correct tag */\n\t\tif( tag != MAKE_CTAG( 0 ) && tag != MAKE_CTAG_PRIMITIVE( 0 ) )\n\t\t\t{\n\t\t\tsSetError( stream, CRYPT_ERROR_BADDATA );\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\n\t\t/* If we've been asked to provide a definite length but there's none \n\t\t   available, return an error */\n\t\tif( ( flags & READCMS_FLAG_DEFINITELENGTH ) && \\\n\t\t\tlength == CRYPT_UNUSED )\n\t\t\t{\n\t\t\tsSetError( stream, CRYPT_ERROR_BADDATA );\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( iCryptContext != NULL )\n\t\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tif( selectionID != NULL )\n\t\t*selectionID = selectionValue;\n\tqueryInfoPtr->size = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCMSencrHeader( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_BUFFER( contentOIDlength ) const BYTE *contentOID, \n\t\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\tIN_LENGTH_INDEF const long dataSize,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tSTREAM nullStream;\n\tint cryptInfoSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( contentOID, contentOIDlength ) && \\\n\t\t\tcontentOIDlength == sizeofOID( contentOID ) );\n\n\tREQUIRES_S( contentOID[ 0 ] == BER_OBJECT_IDENTIFIER );\n\tREQUIRES_S( contentOIDlength >= MIN_OID_SIZE && \\\n\t\t\t\tcontentOIDlength <= MAX_OID_SIZE );\n\tREQUIRES_S( dataSize == CRYPT_UNUSED || isIntegerRangeNZ( dataSize ) );\n\tREQUIRES_S( isHandleRangeValid( iCryptContext ) );\n\n\t/* Determine the encoded size of the AlgorithmIdentifier */\n\tsMemNullOpen( &nullStream );\n\tstatus = writeCryptContextAlgoID( &nullStream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\tcryptInfoSize = stell( &nullStream );\n\tsMemClose( &nullStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If a size is given, write the definite form */\n\tif( dataSize != CRYPT_UNUSED )\n\t\t{\n\t\twriteSequence( stream, contentOIDlength + cryptInfoSize + \\\n\t\t\t\t\t   sizeofObject( dataSize ) );\n\t\tswrite( stream, contentOID, contentOIDlength );\n\t\tstatus = writeCryptContextAlgoID( stream, iCryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( writeOctetStringHole( stream, dataSize, 0 ) );\n\t\t}\n\n\t/* No size given, write the indefinite form */\n\twriteSequenceIndef( stream );\n\tswrite( stream, contentOID, contentOIDlength );\n\tstatus = writeCryptContextAlgoID( stream, iCryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( writeCtag0Indef( stream ) );\n\t}\n#endif /* USE_INT_ASN1 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_ext.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tASN.1 Supplementary Constants and Structures\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ASN1OID_DEFINED\n\n#define _ASN1OID_DEFINED\n\n/* Additional information required when reading a CMS header.  This is\n   pointed to by the extraInfo member of the ASN.1 OID_INFO structure and\n   contains CMS version number information */\n\ntypedef struct {\n\tconst int minVersion;\t/* Minimum version number for content type */\n\tconst int maxVersion;\t/* Maximum version number for content type */\n\t} CMS_CONTENT_INFO;\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tASN.1 OIDs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The cryptlib (strictly speaking DDS) OID arc is as follows:\n\n\t1 3 6 1 4 1 3029 = dds\n\t\t\t\t\t 1 = algorithm\n\t\t\t\t\t   1 = symmetric encryption\n\t\t\t\t\t\t 1 = blowfishECB\n\t\t\t\t\t\t 2 = blowfishCBC\n\t\t\t\t\t\t 3 = blowfishCFB\n\t\t\t\t\t\t 4 = blowfishOFB\n\t\t\t\t\t   2 = public-key encryption\n\t\t\t\t\t\t 1 = elgamal\n\t\t\t\t\t   3 = hash\n\t\t\t\t\t   4 = MAC\n\t\t\t\t\t   5 = ECC\n\t\t\t\t\t 2 = mechanism\n\t\t\t\t\t 3 = attribute\n\t\t\t\t\t   1 = PKIX fixes\n\t\t\t\t\t\t 1 = cryptlibPresenceCheck\n\t\t\t\t\t\t 2 = pkiBoot\n\t\t\t\t\t\t (3 unused)\n\t\t\t\t\t\t 4 = cRLExtReason\n\t\t\t\t\t\t 5 = keyFeatures\n\t\t\t\t\t   2 = CMS\n\t\t\t\t\t 4 = content-type\n\t\t\t\t\t   1 = cryptlib\n\t\t\t\t\t\t 1 = cryptlibConfigData\n\t\t\t\t\t\t 2 = cryptlibUserIndex\n\t\t\t\t\t\t 3 = cryptlibUserInfo\n\t\t\t\t\t\t 4 = cryptlibRtcsRequest\n\t\t\t\t\t\t 5 = cryptlibRtcsResponse\n\t\t\t\t\t\t 6 = cryptlibRtcsResponseExt\n\t\t\t\t\t x36\\xDD\\x24\\x36 = TSA policy ('snooze policy, \"Anything \n\t\t\t\t\t\t\t\t\t   that arrives, we sign\").\n\t\t\t\t\t x58 x59 x5A x5A x59 = XYZZY cert policy */\n\n/* Attribute OIDs */\n\n#define OID_CRYPTLIB_PRESENCECHECK\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x03\\x01\\x01\" )\n#define OID_ESS_CERTID\t\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x0C\" )\n#define OID_TSP_TSTOKEN\t\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x02\\x0E\" )\n#define OID_PKCS9_FRIENDLYNAME\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x14\" )\n#define OID_PKCS9_LOCALKEYID\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x15\" )\n#define OID_PKCS9_X509CERTIFICATE MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x16\\x01\" )\n\n/* The PKCS #9 OID for cert extensions in a certification request, from the\n   CMMF draft.  Naturally MS had to define their own incompatible OID for\n   this, so we check for this as well */\n\n#define OID_PKCS9_EXTREQ\t\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x0E\" )\n#define OID_MS_EXTREQ\t\t\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x0E\" )\n\n/* Content-type OIDs */\n\n#define OID_CMS_DATA\t\t\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x01\" )\n#define OID_CMS_SIGNEDDATA\t\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x02\" )\n#define OID_CMS_ENVELOPEDDATA\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x03\" )\n#define OID_CMS_DIGESTEDDATA\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x05\" )\n#define OID_CMS_ENCRYPTEDDATA\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x06\" )\n#define OID_CMS_AUTHDATA\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x01\\x02\" )\n#define OID_CMS_TSTOKEN\t\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x01\\x04\" )\n#define OID_CMS_COMPRESSEDDATA\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x01\\x09\" )\n#define OID_CMS_AUTHENVDATA\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x01\\x17\" )\n#define OID_CRYPTLIB_CONTENTTYPE MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\" )\n#define OID_CRYPTLIB_CONFIGDATA\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x01\" )\n#define OID_CRYPTLIB_USERINDEX\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x02\" )\n#define OID_CRYPTLIB_USERINFO\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x03\" )\n#define OID_CRYPTLIB_RTCSREQ\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x04\" )\n#define OID_CRYPTLIB_RTCSRESP\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x05\" )\n#define OID_CRYPTLIB_RTCSRESP_EXT\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x04\\x01\\x06\" )\n#define OID_MS_SPCINDIRECTDATACONTEXT MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x01\\x04\" )\n#define OID_NS_CERTSEQ\t\t\tMKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x86\\xF8\\x42\\x02\\x05\" )\n#define OID_OCSP_RESPONSE_OCSP MKOID( \"\\x06\\x09\\x2B\\x06\\x01\\x05\\x05\\x07\\x30\\x01\\x01\" )\n#define OID_PKIBOOT\t\t\t\tMKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x03\\x01\\x02\" )\n#define OID_PKCS12_SHROUDEDKEYBAG MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x0A\\x01\\x02\" )\n#define OID_PKCS12_CERTBAG\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x0A\\x01\\x03\" )\n#define OID_PKCS15_CONTENTTYPE\tMKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0F\\x03\\x01\" )\n\n/* Misc OIDs */\n\n#define OID_ANYPOLICY\t\t\tMKOID( \"\\x06\\x04\\x55\\x1D\\x20\\x00\" )\n#define OID_TSP_POLICY\t\t\tMKOID( \"\\x06\\x0B\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x36\\xDD\\x24\\x36\" )\n#define OID_CRYPTLIB_XYZZYCERT\tMKOID( \"\\x06\\x0C\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x58\\x59\\x5A\\x5A\\x59\" )\n#define OID_PKCS12_PBEWITHSHAAND3KEYTRIPLEDESCBC MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x01\\x03\" )\n#define OID_PKCS12_PBEWITHSHAAND2KEYTRIPLEDESCBC MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x01\\x04\" )\n#define OID_PKCS12_PBEWITHSHAAND40BITRC2CBC MKOID( \"\\x06\\x0A\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x0C\\x01\\x06\" )\n#define OID_RPKI_POLICY\t\t\tMKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x07\\x0E\\x02\" )\n#define OID_ZLIB\t\t\t\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x08\" )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tASN.1 Support Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Additional specifiers for algorithm classes and encoding formats.  This\n   allows us to differentiate between RSA-for-encryption and RSA-for-signing\n   and similar cases where the algorithm alone isn't enough.\n   \n   The encoding specifier is a value that's used as a generic parameter in\n   a location that can also specify an encryption mode or numeric value like\n   a key or hash/block size, so we need to put it in a range that falls\n   outside these values.  This means that ALGOID_ENCODING_NONE has a non-zero\n   value since the values after zero are already taken by CRYPT_MODE_xxx */\n\ntypedef enum {\n\tALGOID_CLASS_NONE,\t\t/* No AlgoID class */\n\tALGOID_CLASS_CRYPT,\t\t/* Encryption algorithms */\n\tALGOID_CLASS_HASH,\t\t/* Hash/MAC algorithm */\n\tALGOID_CLASS_AUTHENC,\t/* Authenticated-encryption algorithm */\n\tALGOID_CLASS_PKC,\t\t/* Generic PKC algorithm */\n\tALGOID_CLASS_PKCSIG,\t/* PKC signature algorithm (+ hash algorithm) */\n\tALGOID_CLASS_LAST\t\t/* Last possible AlgoID class */\n\t} ALGOID_CLASS_TYPE;\n\ntypedef enum {\n\tALGOID_ENCODING_NONE = 500,\t/* No encoding type */\n\tALGOID_ENCODING_PKCS1,\t/* PKCS #1 */\n\tALGOID_ENCODING_OAEP,\t/* OAEP */\n\tALGOID_ENCODING_DLP,\t/* DSA/ECDSA */\n\tALGOID_ENCODING_LAST\t/* Last possible encoding type */\n\t} ALGOID_ENCODING_TYPE;\n\n/* AlgorithmIdentifier routines.  The reason for the apparently redundant \n   CHECK_RETVAL specifiers on some of the write functions is because they \n   won't necessarily set the stream error state if they encounter an error\n   obtaining algorithm parameters or during some other non-stream-related\n   operation.\n\n   The difference between read/writeAlgoID() and read/writeAlgoIDparam() is \n   that the latter take an additional length parameter for when the \n   AlgorithmIdentifier contains additional parameters beyond the OID */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoID( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoIDex( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\tIN_RANGE( 0, 999 ) const int subAlgo );\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofAlgoIDparam( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extraLength );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoID( INOUT STREAM *stream, \n\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t   IN_RANGE( 0, 999 ) const int parameter, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int extraLength );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoIDparam( INOUT STREAM *stream, \n\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int extraLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2) ) \\\nint readAlgoID( INOUT STREAM *stream, \n\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\tIN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t  OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t  OUT_OPT_ALGO_Z CRYPT_ALGO_TYPE *altCryptAlgo,\n\t\t\t\t  OUT_INT_Z int *parameter,\n\t\t\t\t  IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readAlgoIDparam( INOUT STREAM *stream, \n\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *extraLength,\n\t\t\t\t\t IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type );\n\n/* Alternative versions that read/write various algorithm ID types (algo and\n   mode only or full details depending on the option parameter) from contexts */\n\nCHECK_RETVAL_LENGTH \\\nint sizeofContextAlgoID( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t IN_RANGE( 0, 999 ) const int parameter );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readContextAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t   OUT_OPT QUERY_INFO *queryInfo, \n\t\t\t\t\t   IN_TAG const int tag,\n\t\t\t\t\t   IN_ENUM( ALGOID_CLASS ) const ALGOID_CLASS_TYPE type );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeContextAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeContextAlgoIDex( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_RANGE( 0, 999 ) const int parameter );\nCHECK_RETVAL_LENGTH \\\nint sizeofCryptContextAlgoID( IN_HANDLE const CRYPT_CONTEXT iCryptContext );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeCryptContextAlgoID( INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext );\n\n/* Another alternative that reads/writes a non-crypto algorithm identifier,\n   used for things like content types.  This just wraps the given OID up\n   in the AlgorithmIdentifier and writes it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGenericAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t   IN_BUFFER( oidLength ) \\\n\t\t\t\t\t   const BYTE *oid, \n\t\t\t\t\t   IN_LENGTH_OID const int oidLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeGenericAlgoID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_BUFFER( oidLength ) \\\n\t\t\t\t\t\tconst BYTE *oid, \n\t\t\t\t\t\tIN_LENGTH_OID const int oidLength );\n\n/* ECC OID support routines */\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n\nCHECK_RETVAL_LENGTH \\\nint sizeofECCOID( const CRYPT_ECCCURVE_TYPE curveType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readECCOID( INOUT STREAM *stream, \n\t\t\t\tOUT_OPT CRYPT_ECCCURVE_TYPE *curveType );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeECCOID( INOUT STREAM *stream, \n\t\t\t\t const CRYPT_ECCCURVE_TYPE curveType );\n\n#endif /* USE_ECDH || USE_ECDSA */\n\n/* Read/write a message digest */\n\nCHECK_RETVAL_LENGTH_SHORT \\\nint sizeofMessageDigest( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo, \n\t\t\t\t\t\t IN_LENGTH_HASH const int hashSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readMessageDigest( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,\n\t\t\t\t\t   OUT_BUFFER( hashMaxLen, *hashSize ) void *hash, \n\t\t\t\t\t   IN_LENGTH_HASH const int hashMaxLen, \n\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( hashMaxLen ) int *hashSize );\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint writeMessageDigest( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\tIN_BUFFER( hashSize ) const void *hash, \n\t\t\t\t\t\tIN_LENGTH_HASH const int hashSize );\n\n/* Read/write CMS headers.  The readCMSheader() flags are:\n\n\tREADCMS_FLAG_AUTHENC: The content uses authenticated encryption, which\n\t\t\thas a different set of permitted content-encryption algorithms \n\t\t\tthan standard encryption.\n\n\tREADCMS_FLAG_DEFINITELENGTH: Try and obtain a definite length from \n\t\t\tsomewhere in the CMS header rather than returning CRYPT_UNUSED\n\t\t\tfor the length, return an error if there's no definite length\n\t\t\tavailable.  Note that this changes processing in the calling\n\t\t\tcode because it can no longer use the length to determine \n\t\t\twhether it should perform EOC checks if there's an indefinite\n\t\t\tlength somwwhere in the header.\n\n\tREADCMS_FLAG_DEFINITELENGTH_OPT: As READCMS_FLAG_DEFINITELENGTH but \n\t\t\treturn a length of CRYPT_UNUSED if there's no definite length\n\t\t\tinformation available.\n\n\tREADCMS_FLAG_INNERHEADER: This is an inner header, the content wrapper\n\t\t\tcan be an OCTET STRING as well as the more usual SEQUENCE.\n\n\tREADCMS_FLAG_WRAPPERONLY: Only read the outer SEQUENCE, OID, [0] wrapper\n\t\t\twithout reading the final layer of inner encapsulation, used\n\t\t\twhen one CMS content type is redundantly nested directly inside \n\t\t\tanother (Microsoft did this for PKCS #12) */\n\n#define READCMS_FLAG_NONE\t\t\t0x00\t/* No CMS read flag */\n#define READCMS_FLAG_INNERHEADER\t0x01\t/* Inner CMS header */\n#define READCMS_FLAG_AUTHENC\t\t0x02\t/* Content uses auth.enc */\n#define READCMS_FLAG_WRAPPERONLY\t0x04\t/* Only read wrapper */\n#define READCMS_FLAG_DEFINITELENGTH\t0x08\t/* Try and get definite len */\n#define READCMS_FLAG_DEFINITELENGTH_OPT 0x10/* Opt.try and get def.len */\n#define READCMS_FLAG_MAX\t\t\t0x1F\t/* Maximum possible flag value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCMSheader( INOUT STREAM *stream, \n\t\t\t\t   IN_ARRAY( noOidInfoEntries ) \\\n\t\t\t\t   const OID_INFO *oidInfo, \n\t\t\t\t   IN_RANGE( 1, 50 ) const int noOidInfoEntries, \n\t\t\t\t   OUT_OPT_INT_Z int *selectionID,\n\t\t\t\t   OUT_OPT_LENGTH_INDEF long *dataSize, \n\t\t\t\t   IN_FLAGS_Z( READCMS ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCMSheader( INOUT STREAM *stream, \n\t\t\t\t\tIN_BUFFER( contentOIDlength ) \\\n\t\t\t\t\tconst BYTE *contentOID, \n\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\tIN_LENGTH_INDEF const long dataSize, \n\t\t\t\t\tconst BOOLEAN isInnerHeader );\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofCMSencrHeader( IN_BUFFER( contentOIDlength ) \\\n\t\t\t\t\t\t const BYTE *contentOID, \n\t\t\t\t\t\t IN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\t IN_LENGTH_INDEF const long dataSize, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readCMSencrHeader( INOUT STREAM *stream, \n\t\t\t\t\t   IN_ARRAY( noOidInfoEntries ) \\\n\t\t\t\t\t   const OID_INFO *oidInfo,\n\t\t\t\t\t   IN_RANGE( 1, 50 ) const int noOidInfoEntries, \n\t\t\t\t\t   OUT_OPT_INT_Z int *selectionID,\n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t   OUT_OPT QUERY_INFO *queryInfo,\n\t\t\t\t\t   IN_FLAGS_Z( READCMS ) const int flags );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCMSencrHeader( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_BUFFER( contentOIDlength ) \\\n\t\t\t\t\t\tconst BYTE *contentOID, \n\t\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\tIN_LENGTH_INDEF const long dataSize,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext );\n\n#endif /* USE_INT_ASN1 */\n#endif /* _ASN1OID_DEFINED */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_oids.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tASN.1 AlgorithmIdentifier OID Tables\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1992-2011\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A table mapping OIDs to algorithm types.  We take advantage of the fact\n   that object identifiers were designed to be handled in the encoded form\n   (without any need for decoding) and compare expected OIDs with the raw\n   encoded form.  Some OIDs are for pure algorithms, others are for aWithB\n   type combinations (usually encryption + hash).  As a variation on this,\n   some algorithms have two (or even more parameters), for example 3DES\n   encryption + CBC mode, or AES encryption + CBC mode + 128-bit key size.\n   In order to deal with this we allow two parameters alongside the main\n   algorithm:\n\n\tSignature: param1 = hash algorithm.\n\tEncryption (PKC): param1 = encoding mech (if required).\n\tEncryption (conv): param1 = mode, param2 = key size (if required).\n\tHash: param1 = block size (if required).\n\n   In order for the table to work for encoding, the values have to be sorted \n   based on their parameters, so that a given algorithm is followed by its\n   sub-OIDs sorted first on param1 and then param2.\n\n   There are multiple OIDs for RSA, the main ones being rsa (which doesn't\n   specify an exact data format and is deprecated), rsaEncryption (as per\n   PKCS #1, recommended), and rsaSignature (ISO 9796).  We use rsaEncryption\n   and its derived forms (e.g. md5WithRSAEncryption) rather than alternatives\n   like md5WithRSA.  There is also an OID for rsaKeyTransport that uses\n   PKCS #1 padding but isn't defined by RSADSI.\n\n   There are a great many OIDs for DSA and/or SHA.  We list the less common\n   ones after all the other OIDs so that we always encode the more common\n   form, but can decode many forms (there are even more OIDs for SHA or DSA\n   with common parameters that we don't bother with).\n\n   AES has a whole series of OIDs that vary depending on the key size used,\n   this usually isn't of any use since we can tell the keysize from other \n   places but is needed in a few situations such as when we're deriving a \n   key into an AES context */\n\ntypedef struct {\n\tconst CRYPT_ALGO_TYPE algorithm;\t/* The basic algorithm */\n\tconst int subAlgo;\t\t\t\t\t/* Algorithm subtype or mode */\n\tconst int parameter;\t\t\t\t/* Encoding format or key/hash size */\n\tconst ALGOID_CLASS_TYPE algoClass;\t/* Algorithm class */\n\tconst BYTE *oid;\t\t\t\t\t/* The OID for this algorithm */\n#ifndef NDEBUG\n\tconst char *description;\t\t\t/* Description for this algorithm */\n#endif /* !NDEBUG */\n\t} ALGOID_INFO;\n\n#ifndef NDEBUG\n  #define MKDESC( description )\t\t, description\n#else\n  #define MKDESC( description )\n#endif /* !NDEBUG */\n\nstatic const ALGOID_INFO algoIDinfoTbl[] = {\n\t/* RSA and <hash>WithRSA */\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x01\" )\n\t  MKDESC( \"rsaEncryption (1 2 840 113549 1 1 1)\" ) },\n#ifdef USE_OAEP\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_OAEP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x07\" )\n\t  MKDESC( \"rsaOAEP (1 2 840 113549 1 1 7\" ) },\n#endif /* USE_OAEP */\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_MD5, 0, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x04\" )\n\t  MKDESC( \"md5withRSAEncryption (1 2 840 113549 1 1 4)\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1, 0, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x05\" )\n\t  MKDESC( \"sha1withRSAEncryption (1 2 840 113549 1 1 5)\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1, 0, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1D\" )\n\t  MKDESC( \"Another sha-1WithRSAEncryption (1 3 14 3 2 29)\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1, 0, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x06\\x2B\\x24\\x03\\x03\\x01\\x01\" ) \n\t  MKDESC( \"Another rsaSignatureWithsha1 (1 3 36 3 3 1 1)\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2, 32, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0B\" )\n\t  MKDESC( \"sha256withRSAEncryption (1 2 840 113549 1 1 11)\" ) },\n  #ifdef USE_SHA2_EXT\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2, 48, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0C\" )\n\t  MKDESC( \"sha384withRSAEncryption (1 2 840 113549 1 1 12)\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2, 64, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0D\" )\n\t  MKDESC( \"sha512withRSAEncryption (1 2 840 113549 1 1 13)\" ) },\n  #endif /* USE_SHA2_EXT */\n\t/* The following four ALGOID_CLASS_PKC entries are bug workarounds for \n\t   implementations that erroneously use xxxWithRSA when they should be \n\t   using straight RSA */\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x05\" )\n\t  MKDESC( \"Bug workaround for implementations using sha1WithRSA instead of RSA\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0B\" )\n\t  MKDESC( \"Bug workaround for implementations using sha256WithRSA instead of RSA\" ) },\n  #ifdef USE_SHA2_EXT\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0C\" )\n\t  MKDESC( \"Bug workaround for implementations using sha384WithRSA instead of RSA\" ) },\n\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x01\\x0D\" )\n\t  MKDESC( \"Bug workaround for implementations using sha512WithRSA instead of RSA\" ) },\n  #endif /* USE_SHA2_EXT */\n\n\t/* DSA and dsaWith<hash> */\n#ifdef USE_DSA\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x04\\x01\" ) \n\t  MKDESC( \"dsa (1 2 840 10040 4 1)\" ) },\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x0C\" ) \n\t  MKDESC( \"Peculiar deprecated dsa (1 3 14 3 2 12)\" ) },\n\t  /* Peculiar deprecated dsa (1 3 14 3 2 12), but used by CDSA and the\n\t     German PKI profile */\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x38\\x04\\x03\" )\n\t  MKDESC( \"dsaWithSha1 (1 2 840 10040 4 3)\" ) },\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1B\" )\n\t  MKDESC( \"Another dsaWithSHA1 (1 3 14 3 2 27)\" ) },\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x02\\x01\\x01\\x02\" )\n\t  MKDESC( \"Yet another dsaWithSHA-1 (2 16 840 1 101 2 1 1 2)\" ) },\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x0D\" ) \n\t  MKDESC( \"JDK 1.1 erroneous dsaWithSHA(-0) used as dsaWithSHA-1\" ) },\n\t  /* When they ran out of valid dsaWithSHA's, they started using invalid\n\t     ones.  This one is from JDK 1.1 and is actually dsaWithSHA(-0), but \n\t\t it's used as if it were dsaWithSHA-1 (1 3 14 3 2 13) */\n\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA2, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x03\\x02\" ) \n\t  MKDESC( \"dsaWithSha256 (2 16 840 1 101 3 4 3 2)\" ) },\n#endif /* USE_DSA */\n\n\t/* Elgamal */\n#ifdef USE_ELGAMAL\n\t{ CRYPT_ALGO_ELGAMAL, CRYPT_ALGO_NONE, ALGOID_ENCODING_PKCS1, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x0A\\x2B\\x06\\x01\\x04\\x01\\x97\\x55\\x01\\x02\\x01\" )\n\t  MKDESC( \"elgamal (1 3 6 1 4 1 3029 1 2 1)\" ) },\n#endif /* USE_ELGAMAL */\n\n\t/* DH */\n#ifdef USE_DH\n\t{ CRYPT_ALGO_DH, CRYPT_ALGO_NONE, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3E\\x02\\x01\" )\n\t  MKDESC( \"dhPublicKey (1 2 840 10046 2 1)\" ) },\n#endif /* USE_DH */\n\n\t/* ECDSA and ecdsaWith<hash>.  The xxxWithRecommended/Specified are a\n\t   complex mess and aren't normally used by anything (for example they\n\t   were explicitly excluded from the PKIX/SMIME specs because there's no\n\t   point to them) but due to the fact that there's no public use of ECC\n\t   certs by CAs there are oddball private-label CAs that use them with\n\t   no correcting factor in the form of rejection by implementations \n\t   present.  For now we ignore them in the hope that the oddball private\n\t   uses will eventually go away */\n#if defined( USE_ECDSA ) || defined( USE_ECDH )\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_NONE, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKC,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x02\\x01\" )\n\t  MKDESC( \"ecPublicKey (1 2 840 10045 2 1)\" ) },\n#endif /* USE_ECDSA || USE_ECDH */\n#ifdef USE_ECDSA\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x01\" )\n\t  MKDESC( \"ecdsaWithSHA1 (1 2 840 10045 4 1)\" ) },\n  #if 0\t\t/* These are too awkward to support easily, and PKIX says they \n\t\t\t   shouldn't be used anyway */\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x02\" )\n\t  MKDESC( \"ecdsaWithRecommended (= ...withSHA1) (1 2 840 10045 4 2)\" ) },\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA1, ALGOID_ENCODING_DLP, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x07\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x03\" ) \n\t  MKDESC( \"ecdsaWithSpecified (= ...withSHA1) (1 2 840 10045 4 3)\" ) },\n  #endif /* 0 */\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, 32, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x03\\x02\" )\n\t  MKDESC( \"ecdsaWithSHA256 (1 2 840 10045 4 3 2)\" ) },\n  #ifdef USE_SHA2_EXT\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, 48, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x03\\x03\" )\n\t  MKDESC( \"ecdsaWithSHA384 (1 2 840 10045 4 3 3)\" ) },\n\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, 64, ALGOID_CLASS_PKCSIG,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\xCE\\x3D\\x04\\x03\\x04\" )\n\t  MKDESC( \"ecdsaWithSHA512 (1 2 840 10045 4 3 4)\" ) },\n  #endif /* USE_SHA2_EXT */\n#endif /* USE_ECDSA */\n\n\t/* Hash algorithms */\n#ifdef USE_MD5\n\t{ CRYPT_ALGO_MD5, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x05\" )\n\t  MKDESC( \"md5 (1 2 840 113549 2 5)\" ) },\n\t{ CRYPT_ALGO_MD5, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x02\\x82\\x06\\x01\\x0A\\x01\\x03\\x02\" ) \n\t  MKDESC( \"Another md5 (0 2 262 1 10 1 3 2)\" ) },\n\t{ CRYPT_ALGO_MD5, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x0B\\x60\\x86\\x48\\x01\\x86\\xF8\\x37\\x01\\x02\\x08\\x32\" )\n\t  MKDESC( \"Yet another md5 (2 16 840 1 113719 1 2 8 50)\" ) },\n#endif /* USE_MD5 */\n\t{ CRYPT_ALGO_SHA1, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1A\" )\n\t  MKDESC( \"sha1 (1 3 14 3 2 26)\" ) },\n\t{ CRYPT_ALGO_SHA1, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x0B\\x60\\x86\\x48\\x01\\x86\\xF8\\x37\\x01\\x02\\x08\\x52\" )\n\t  MKDESC( \"Another sha1 (2 16 840 1 113719 1 2 8 82)\" ) },\n\t{ CRYPT_ALGO_SHA2, CRYPT_ALGO_NONE, 32, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x01\" )\n\t  MKDESC( \"sha2-256 (2 16 840 1 101 3 4 2 1)\" ) },\n  #ifdef USE_SHA2_EXT\n\t{ CRYPT_ALGO_SHA2, CRYPT_ALGO_NONE, 48, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x02\" )\n\t  MKDESC( \"sha2-384 (2 16 840 1 101 3 4 2 2)\" ) },\n\t{ CRYPT_ALGO_SHA2, CRYPT_ALGO_NONE, 64, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x03\" )\n\t  MKDESC( \"sha2-512 (2 16 840 1 101 3 4 2 3)\" ) },\n  #endif /* USE_SHA2_EXT */\n\n\t/* MAC algorithms */\n\t{ CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2B\\x06\\x01\\x05\\x05\\x08\\x01\\x02\" )\n\t  MKDESC( \"hmac-SHA (1 3 6 1 5 5 8 1 2)\" ) },\n\t{ CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x07\" )\n\t  MKDESC( \"Another hmacWithSHA1 (1 2 840 113549 2 7)\" ) },\n\t{ CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_NONE, 32, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x09\" )\n\t  MKDESC( \"hmacWithSHA256 (1 2 840 113549 2 9)\" ) },\n  #ifdef USE_SHA2_EXT\n\t{ CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_NONE, 48, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x0A\" )\n\t  MKDESC( \"hmacWithSHA384 (1 2 840 113549 2 10)\" ) },\n\t{ CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_NONE, 64, ALGOID_CLASS_HASH,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x02\\x0B\" )\n\t  MKDESC( \"hmacWithSHA512 (1 2 840 113549 2 11)\" ) },\n  #endif /* USE_SHA2_EXT */\n\n\t/* Encryption algorithms */\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_ECB, 16, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x01\" )\n\t  MKDESC( \"aes128-ECB (2 16 840 1 101 3 4 1 1)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_ECB, 24, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x15\" )\n\t  MKDESC( \"aes192-ECB (2 16 840 1 101 3 4 1 21)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_ECB, 32, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x29\" )\n\t  MKDESC( \"aes256-ECB (2 16 840 1 101 3 4 1 41)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CBC, 16, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x02\" )\n\t  MKDESC( \"aes128-CBC (2 16 840 1 101 3 4 1 2)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CBC, 24, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x16\" )\n\t  MKDESC( \"aes192-CBC (2 16 840 1 101 3 4 1 22)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CBC, 32, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x2A\" )\n\t  MKDESC( \"aes256-CBC (2 16 840 1 101 3 4 1 42)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CFB, 16, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x04\" )\n\t  MKDESC( \"aes128-CFB (2 16 840 1 101 3 4 1 4)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CFB, 24, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x18\" )\n\t  MKDESC( \"aes192-CFB (2 16 840 1 101 3 4 1 24)\" ) },\n\t{ CRYPT_ALGO_AES, CRYPT_MODE_CFB, 32, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x01\\x2C\" )\n\t  MKDESC( \"aes256-CFB (2 16 840 1 101 3 4 1 44)\" ) },\n#ifdef USE_CAST\n\t{ CRYPT_ALGO_CAST, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF6\\x7D\\x07\\x42\\x0A\" )\n\t  MKDESC( \"cast5CBC (1 2 840 113533 7 66 10)\" ) },\n#endif /* USE_CAST */\n#ifdef USE_DES\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_ECB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x06\" )\n\t  MKDESC( \"desECB (1 3 14 3 2 6)\" ) },\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_ECB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x02\\x82\\x06\\x01\\x0A\\x01\\x02\\x02\\x01\" )\n\t  MKDESC( \"Another desECB (0 2 262 1 10 1 2 2 1)\" ) },\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x07\" )\n\t  MKDESC( \"desCBC (1 3 14 3 2 7)\" ) },\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x02\\x82\\x06\\x01\\x0A\\x01\\x02\\x02\\x02\" ) \n\t  MKDESC( \"Another desCBC (0 2 262 1 10 1 2 2 2)\" ) },\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_CFB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x09\" )\n\t  MKDESC( \"desCFB (1 3 14 3 2 9)\" ) },\n\t{ CRYPT_ALGO_DES, CRYPT_MODE_CFB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x02\\x82\\x06\\x01\\x0A\\x01\\x02\\x02\\x05\" )\n\t  MKDESC( \"Another desCFB (0 2 262 1 10 1 2 2 5)\" ) },\n#endif /* USE_DES */\n\t{ CRYPT_ALGO_3DES, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x07\" )\n\t  MKDESC( \"des-EDE3-CBC (1 2 840 113549 3 7)\" ) },\n\t{ CRYPT_ALGO_3DES, CRYPT_MODE_CFB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x09\" )\n\t  MKDESC( \"des-EDE3-CFB (1 2 840 113549 3 9)\" ) },\n\t{ CRYPT_ALGO_3DES, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x09\\x02\\x82\\x06\\x01\\x0A\\x01\\x02\\x03\\x02\" )\n\t  MKDESC( \"Another des3CBC (0 2 262 1 10 1 2 3 2)\" ) },\n#ifdef USE_RC2\n\t{ CRYPT_ALGO_RC2, CRYPT_MODE_CBC, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x02\" )\n\t  MKDESC( \"rc2CBC (1 2 840 113549 3 2)\" ) },\n\t{ CRYPT_ALGO_RC2, CRYPT_MODE_ECB, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x03\" )\n\t  MKDESC( \"rc2ECB (1 2 840 113549 3 3)\" ) },\n#endif /* USE_RC2 */\n#ifdef USE_RC4\n\t{ CRYPT_ALGO_RC4, CRYPT_PSEUDOMODE_RC4, 0, ALGOID_CLASS_CRYPT,\n\t  MKOID( \"\\x06\\x08\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x03\\x04\" )\n\t  MKDESC( \"rc4 (1 2 840 113549 3 4)\" ) },\n#endif /* USE_RC4 */\n\n\t/* Authenticated encryption algorithms */\n\t{ CRYPT_IALGO_GENERIC_SECRET, CRYPT_ALGO_NONE, 16, ALGOID_CLASS_AUTHENC,\n\t  MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x0F\" )\n\t  MKDESC( \"authEnc128 (1 2 840 113549 1 9 16 3 15)\" ) },\n\t{ CRYPT_IALGO_GENERIC_SECRET, CRYPT_ALGO_NONE, 32, ALGOID_CLASS_AUTHENC,\n\t  MKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x10\" )\n\t  MKDESC( \"authEnc256 (1 2 840 113549 1 9 16 3 16)\" ) },\n\n\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_NONE, NULL MKDESC( \"\" ) },\n\t\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0, ALGOID_CLASS_NONE, NULL MKDESC( \"\" ) }\n\t};\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tASN.1 Read Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"bn.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"bn/bn.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* When specifying a tag we can use either the default tag for the object\n   (indicated with the value DEFAULT_TAG) or a special-case tag.  The \n   following macro selects the correct value.  Since these are all primitive \n   objects we force the tag type to a primitive tag */\n\n#define selectTag( tag, defaultTag )\t\\\n\t\t( ( ( tag ) == DEFAULT_TAG ) ? ( defaultTag ) : \\\n\t\t\t\t\t\t\t\t\t   ( MAKE_CTAG_PRIMITIVE( tag ) ) )\n\n/* When reading numeric values the encoder whose data we're processing may\n   have added spurious leading zero padding.  The follow value defines the\n   maximum number of bytes of data that we'll accept (before leading zeroes\n   are stripped) */\n\n#define MAX_NUMERIC_DATA_BYTES\t\t8\n\n/* Read a numeric value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readNumericValue( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_LENGTH_INDEF long *value,\n\t\t\t\t\t\t\t IN_RANGE( 1, MAX_NUMERIC_DATA_BYTES ) \\\n\t\t\t\t\t\t\t\tconst int valueByteCount,\n\t\t\t\t\t\t\t const BOOLEAN isZeroValueOK,\n\t\t\t\t\t\t\t const BOOLEAN isShortLength )\n\t{\n\tBYTE buffer[ MAX_NUMERIC_DATA_BYTES + 8 ], *bufPtr = buffer;\n\tlong localValue;\n\tint noBytes = valueByteCount, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( value, sizeof( long ) ) );\n\n\tREQUIRES( noBytes >= 1 && noBytes <= MAX_NUMERIC_DATA_BYTES );\n\tREQUIRES( isZeroValueOK == TRUE || isZeroValueOK == FALSE );\n\tREQUIRES( isShortLength == TRUE || isShortLength == FALSE );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\tstatus = sread( stream, buffer, noBytes );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Handle leading zero octets (a single zero byte is OK, since it's an\n\t   encoding of a zero value).  Since BER lengths can be encoded in \n\t   peculiar ways (at least one text uses a big-endian 32-bit encoding \n\t   for everything) we allow up to MAX_NUMERIC_DATA_BYTES bytes of \n\t   non-DER length data, but only the last 2 or 4 of these (for short \n\t   or long lengths respectively) can be nonzero */\n\tif( buffer[ 0 ] == 0 && noBytes > 1 )\n\t\t{\n\t\t/* Oddball length encoding with leading zero(es) */\n\t\tLOOP_SMALL( i = 0, i < noBytes && buffer[ i ] == 0, i++ );\n\t\tENSURES_S( LOOP_BOUND_OK );\n\t\tnoBytes -= i;\n\t\tif( noBytes <= 0 )\n\t\t\treturn( CRYPT_OK );\t/* Very broken encoding of a zero length */\n\t\tbufPtr += i;\t\t\t/* Skip leading zero(es) */\n\t\t}\n\n\t/* Make sure that the leading-zero-adjusted length size is reasonable */\n\tif( noBytes < 0 || noBytes > ( isShortLength ? 2 : 4 ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t/* Read and check the length value */\n\tLOOP_SMALL( ( localValue = 0, i = 0 ), i < noBytes, i++ )\n\t\t{\n\t\tconst long localValueTmp = localValue << 8;\n\t\tconst int data = byteToInt( bufPtr[ i ] );\n\n\t\tif( localValue >= ( MAX_INTLENGTH >> 8 ) || \\\n\t\t\tlocalValueTmp >= MAX_INTLENGTH - data )\n\t\t\t{\n\t\t\t/* Integer overflow */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\tlocalValue = localValueTmp | data;\n\t\tif( !isIntegerRange( localValue ) )\n\t\t\t{\n\t\t\t/* Integer overflow */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tif( isShortLength )\n\t\t{\n\t\tif( !isShortIntegerRange( localValue ) || ( localValue & 0xFFFF8000UL ) )\n\t\t\t{\n\t\t\t/* Length must be < 32K for short lengths */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !isIntegerRange( localValue ) || ( localValue & 0x80000000UL ) )\n\t\t\t{\n\t\t\t/* Length must be < MAX_INTLENGTH for standard data */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t\t}\n\t\t}\n\tif( localValue <= 0 && !isZeroValueOK )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\tENSURES_S( isIntegerRange( localValue ) );\n\t*value = localValue;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the length octets for an ASN.1 data type with special-case handling\n   for long and short lengths and indefinite-length encodings:\n\n\t0x00 - 0x7F\t\t\t\t\tBasic length\n\t0x80\t\t\t\t\t\tOndefinite\n\t0x81 0xnn\t\t\t\t\t8-bit length\n\t0x82 0xnn 0xnn\t\t\t\t16-bit length\n\t0x83 0xnn 0xnn 0xnn\t\t\t24-bit length\n\t0x84 0xnn 0xnn 0xnn 0xnn\t32-bit length\n   \n   The short-length read is limited to MAX_INTLENGTH_SHORT, which is a sane \n   limit for most PKI data and one that doesn't cause type conversion \n   problems on systems where sizeof( int ) != sizeof( long ).  If the caller \n   indicates that indefinite lengths are OK for short lengths we return \n   OK_SPECIAL if we encounter one.  Long length reads always allow \n   indefinite lengths since these are quite likely for large objects */\n\ntypedef enum {\n\tREADLENGTH_NONE,\t\t/* No length read behaviour */\n\tREADLENGTH_SHORT,\t\t/* Short length, no indef.allowed */\n\tREADLENGTH_SHORT_INDEF,\t/* Short length, indef.to OK_SPECIAL */\n\tREADLENGTH_LONG_INDEF,\t/* Long length, indef.to OK_SPECIAL */\n\tREADLENGTH_LAST\t\t\t/* Last possible read type */\n\t} READLENGTH_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readLengthValue( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT_LENGTH_INDEF long *length,\n\t\t\t\t\t\t\tIN_ENUM( READLENGTH ) const READLENGTH_TYPE readType )\n\t{\n\tBOOLEAN shortLen = ( readType == READLENGTH_SHORT || \\\n\t\t\t\t\t\t readType == READLENGTH_SHORT_INDEF ) ? \\\n\t\t\t\t\t   TRUE : FALSE;\n\tlong dataLength;\n\tint noLengthOctets, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES_S( isEnumRange( readType, READLENGTH ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Read the first byte of length data.  If it's a short length, we're\n\t   done */\n\tstatus = dataLength = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !( dataLength & 0x80 ) )\n\t\t{\n\t\t*length = dataLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read the actual length octets */\n\tnoLengthOctets = dataLength & 0x7F;\n\tif( noLengthOctets <= 0 )\n\t\t{\n\t\t/* If indefinite lengths aren't allowed, signal an error */\n\t\tif( readType != READLENGTH_SHORT_INDEF && \\\n\t\t\treadType != READLENGTH_LONG_INDEF )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t\t/* It's an indefinite length encoding, we're done */\n\t\t*length = CRYPT_UNUSED;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( noLengthOctets > MAX_NUMERIC_DATA_BYTES )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\treturn( readNumericValue( stream, length, noLengthOctets, FALSE, \n\t\t\t\t\t\t\t  shortLen ) );\n\t}\n\n/* Read a (non-bignum) numeric value, used by readInteger() and \n   readEnumerated() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readNumeric( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_OPT_LENGTH_Z long *value,\n\t\t\t\t\t\tIN_TAG_EXT const int tag,\n\t\t\t\t\t\tconst BOOLEAN isInteger )\n\t{\n\tconst int tagToRead = selectTag( tag, isInteger ? \\\n\t\t\t\t\t\t\t\t\t BER_INTEGER : BER_ENUMERATED );\n\tlong localValue, length;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( value == NULL || isWritePtr( value, sizeof( long ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isInteger == TRUE || isInteger == FALSE );\n\n\t/* Clear return value */\n\tif( value != NULL )\n\t\t*value = 0L;\n\n\t/* Read the identifier field if necessary and the length, and make sure \n\t   that it's a non-bignum value */\n\tif( tag != NO_TAG && readTag( stream ) != tagToRead )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = readLengthValue( stream, &length, READLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\treturn( 0 );\t\t/* Zero-length data */\n\tif( length > MAX_NUMERIC_DATA_BYTES )\n\t\t{\n\t\t/* We allow up to MAX_NUMERIC_DATA_BYTES bytes of data to \n\t\t   accommodate broken encodings that add leading zeroes.  The actual \n\t\t   value's range will be checked in readNumericValue() */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\n\tstatus = readNumericValue( stream, &localValue, length, TRUE, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != NULL )\n\t\t*value = localValue;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a constrained-length data value, used by several routines.  Note\n   that, since this is a constrained read, 'length' may be much larger than\n   'bufferMaxLength', this is not an error since the data being read is\n   truncated to 'bufferMaxLength' */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int readConstrainedData( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tOUT_BUFFER_OPT( bufferMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t*bufferLength ) BYTE *buffer, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int bufferMaxLength,\n\t\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *bufferLength, \n\t\t\t\t\t\t\t\tIN_LENGTH const int length )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( buffer == NULL || isWritePtrDynamic( buffer, bufferMaxLength ) );\n\tassert( isWritePtr( bufferLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( bufferMaxLength ) );\n\tREQUIRES_S( isShortIntegerRangeNZ( length ) );\n\n\t/* Clear return value */\n\tif( buffer != NULL )\n\t\tmemset( buffer, 0, min( 16, bufferMaxLength ) );\n\t*bufferLength = 0;\n\n\t/* If we don't care about the return value, skip it and exit */\n\tif( buffer == NULL )\n\t\t{\n\t\t*bufferLength = length;\n\t\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t\t}\n\n\t/* If the object will fit into the buffer, read it and exit */\n\tif( length <= bufferMaxLength )\n\t\t{\n\t\t*bufferLength = length;\n\t\treturn( sread( stream, buffer, length ) );\n\t\t}\n\n\t/* Read the object, limiting the number of bytes read to the maximum \n\t   buffer size */\n\t*bufferLength = bufferMaxLength;\n\tstatus = sread( stream, buffer, bufferMaxLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sSkip( stream, length - bufferMaxLength, \n\t\t\t\t   MAX_INTLENGTH_SHORT ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Routines for Primitive Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a tag and make sure that it's (approximately) valid */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkTag( IN_BYTE const int tag )\n\t{\n\t/* Make sure that it's (approximately) valid: Not an EOC, and within the\n\t   allowed range */\n\tif( tag <= 0 || tag >= MAX_TAG )\n\t\treturn( FALSE );\n\t\n\t/* Make sure that it's not an application-specific or private tag */\n\tif( ( tag & BER_CLASS_MASK ) == BER_APPLICATION ||\n\t\t( tag & BER_CLASS_MASK ) == BER_PRIVATE )\n\t\treturn( FALSE );\n\n\t/* If its's a context-specific tag make sure that the tag value is \n\t   within the allowed range */\n\tif( ( tag & BER_CLASS_MASK ) == BER_CONTEXT_SPECIFIC && \\\n\t\t( tag & BER_SHORT_ID_MASK ) >= MAX_CTAG_VALUE )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nRETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readTag( INOUT STREAM *stream )\n\t{\n\tint tag, status;\n\n\t/* Read the tag */\n\tstatus = tag = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !checkTag( tag ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( tag );\n\t}\n\nRETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint peekTag( INOUT STREAM *stream )\n\t{\n\tint tag, status;\n\n\t/* Peek at the tag value */\n\tstatus = tag = sPeek( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !checkTag( tag ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( tag );\n\t}\n\n/* Check for constructed data end-of-contents octets.  Note that this \n   is a standard integer-return function that can return either a boolean \n   TRUE/FALSE or alternatively a stream error code if there's a problem, so \n   it's not a purely boolean function */\n\nRETVAL_RANGE( FALSE, TRUE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkEOC( INOUT STREAM *stream )\n\t{\n\tBYTE eocBuffer[ 2 + 8 ];\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Read the tag and check for an EOC octet pair.  Note that we can't use\n\t   peekTag()/readTag() for this because an EOC isn't a valid tag */\n\tstatus = tag = sPeek( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag != BER_EOC )\n\t\treturn( FALSE );\n\tstatus = sread( stream, eocBuffer, 2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( memcmp( eocBuffer, \"\\x00\\x00\", 2 ) )\n\t\t{\n\t\t/* An EOC tag needs to be combined with a length of zero */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Read a short (<= 256 bytes) raw object without decoding it.  This is used\n   to read short data blocks like object identifiers, which are only ever\n   handled in encoded form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readRawObject( INOUT STREAM *stream, \n\t\t\t\t   OUT_BUFFER( bufferMaxLength, *bufferLength ) \\\n\t\t\t\t\t\tBYTE *buffer, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( 3 ) const int bufferMaxLength, \n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\tint *bufferLength, \n\t\t\t\t   IN_TAG_ENCODED const int tag )\n\t{\n\tint length, offset = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, bufferMaxLength ) );\n\tassert( isWritePtr( bufferLength, sizeof( int ) ) );\n\n\tREQUIRES_S( bufferMaxLength >= 3 && \\\n\t\t\t\tbufferMaxLength < MAX_INTLENGTH_SHORT );\n\t\t\t\t/* Need to be able to process at least the tag, length, and \n\t\t\t\t   one byte of content */\n\tREQUIRES_S( ( tag == NO_TAG ) || ( tag >= 1 && tag <= MAX_TAG ) );\n\t\t\t\t/* Note tag != 0 */\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bufferMaxLength ) );\n\t*bufferLength = 0;\n\n\t/* Read the identifier field and length.  We need to remember each byte \n\t   as it's read so we can't just call readLengthValue() for the length, \n\t   but since we only need to handle lengths that can be encoded in one \n\t   or two bytes this isn't a problem.  Since this function reads a \n\t   complete encoded object, the tag (if known) must be specified so \n\t   there's no capability to use DEFAULT_TAG */\n\tif( tag != NO_TAG )\n\t\t{\n\t\tint objectTag;\n\t\t\n\t\tstatus = objectTag = readTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( objectTag != tag )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\tbuffer[ offset++ ] = intToByte( objectTag );\n\t\t}\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tbuffer[ offset++ ] = intToByte( length );\n\tif( length & 0x80 )\n\t\t{\n\t\t/* If the object is indefinite-length or longer than 256 bytes (i.e. \n\t\t   the length-of-length is anything other than 1) we don't want to \n\t\t   handle it */\n\t\tif( length != 0x81 )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t\t/* Certain types should never have a length that can't be encoded in\n\t\t   a single byte, if we find something like this then it's an \n\t\t   error.  This check exists mostly to catch malformed OIDs, which \n\t\t   are only ever processed in raw form, so an invalid or non-\n\t\t   canonical encoding will result in an OID that can't ever be \n\t\t   matched */\n\t\tif( tag == BER_ID_BOOLEAN || tag == BER_ID_OBJECT_IDENTIFIER || \\\n\t\t\ttag == BER_ID_ENUMERATED || tag == BER_ID_TIME_UTC || \\\n\t\t\ttag == BER_ID_TIME_GENERALIZED )\n\t\t\t{\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\n\t\t/* Read the single-byte length */\n\t\tstatus = length = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tbuffer[ offset++ ] = intToByte( length );\n\t\t}\n\tif( length <= 0 || length > 0xFF )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( offset + length > bufferMaxLength )\n\t\t{\n\t\t/* We treat this as a stream error even though technically it's an\n\t\t   insufficient-buffer-space error because the data object has \n\t\t   violated the implicit format constraint of being larger than the\n\t\t   maximum size specified by the caller */\n\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t}\n\n\t/* Read in the rest of the data */\n\t*bufferLength = offset + length;\n\tENSURES( boundsCheck( offset, length, bufferMaxLength ) );\n\treturn( sread( stream, buffer + offset, length ) );\n\t}\n\n/* Read a large integer value.  The header-read code is shared among \n   integer-as-bytes and integer-as-bignum read routines, and reads the tag \n   and length and skips any leading zero bytes before the nuneric data */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readIntegerHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN_TAG_EXT const int tag )\n\t{\n\tlong length;\n\tint noLeadingZeroes, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Read the identifier field if necessary and the length */\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_INTEGER ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = readLengthValue( stream, &length, READLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\treturn( 0 );\t\t/* Zero-length data */\n\tENSURES( isShortIntegerRangeNZ( length ) )\n\n\t/* ASN.1 encoded values are signed while the internal representation is\n\t   unsigned so we skip any leading zero bytes needed to encode a value\n\t   that has the high bit set.  If we get a value with the (supposed) \n\t   sign bit set we treat it as an unsigned value since a number of \n\t   implementations get this wrong.  As with length encodings, we allow\n\t   up to MAX_NUMERIC_DATA_BYTES bytes of non-DER leading zeroes */\n\tLOOP_SMALL( noLeadingZeroes = 0, \n\t\t\t\tnoLeadingZeroes < length && \\\n\t\t\t\t\tnoLeadingZeroes < MAX_NUMERIC_DATA_BYTES && \\\n\t\t\t\t\tsPeek( stream ) == 0,\n\t\t\t\tnoLeadingZeroes++ )\n\t\t{\n\t\tstatus = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES_S( status == 0 );\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tif( noLeadingZeroes >= MAX_NUMERIC_DATA_BYTES )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\treturn( length - noLeadingZeroes );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readIntegerTag( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER_OPT( integerMaxLength, \\\n\t\t\t\t\t\t\t\t\t*integerLength ) BYTE *integer, \n\t\t\t\t\tIN_LENGTH_SHORT const int integerMaxLength, \n\t\t\t\t\tOUT_OPT_LENGTH_SHORT_Z int *integerLength, \n\t\t\t\t\tIN_TAG_EXT const int tag )\n\t{\n\tint localIntegerLength, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( integer == NULL || \\\n\t\t\tisWritePtrDynamic( integer, integerMaxLength ) );\n\tassert( integerLength == NULL || \\\n\t\t\tisWritePtr( integerLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( integerMaxLength ) );\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Clear return values */\n\tif( integer != NULL )\n\t\tmemset( integer, 0, min( 16, integerMaxLength ) );\n\tif( integerLength != NULL )\n\t\t*integerLength = 0;\n\n\t/* Read the integer header info */\n\tstatus = length = readIntegerHeader( stream, tag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\treturn( 0 );\t/* Zero-length data */\n\n\t/* Read in the numeric value, limiting the size to the maximum buffer \n\t   size.  This is safe because the only situation where this can occur \n\t   is when we're reading some blob (whose value we don't care about) \n\t   dressed up as an integer rather than for any real integer */\n\tstatus = readConstrainedData( stream, integer, integerMaxLength,\n\t\t\t\t\t\t\t\t  &localIntegerLength, length );\n\tif( cryptStatusOK( status ) && integerLength != NULL )\n\t\t*integerLength = localIntegerLength;\n\treturn( status );\n\t}\n\n#ifdef USE_PKC\n\n/* Read a bignum integer value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readBignumInteger( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange, \n\t\t\t\t\t\t\t  IN_TAG_EXT const int tag,\n\t\t\t\t\t\t\t  IN_ENUM_OPT( KEYSIZE_CHECK ) \\\n\t\t\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_S( minLength > 0 && minLength <= maxLength && \\\n\t\t\t\tmaxLength <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isEnumRangeOpt( checkType, KEYSIZE_CHECK ) );\n\n\t/* Read the integer header info */\n\tstatus = length = readIntegerHeader( stream, tag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\tBOOLEAN bnStatus;\n\n\t\t/* It's a read of a zero value, make it explicit */\n\t\tbnStatus = BN_zero( bignum );\n\t\tENSURES( bnStatus );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read the value into a fixed buffer */\n\tif( length > CRYPT_MAX_PKCSIZE )\n\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\tstatus = sread( stream, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = importBignum( bignum, buffer, length, minLength, maxLength, \n\t\t\t\t\t\t   maxRange, checkType );\n\tif( cryptStatusError( status ) )\n\t\tstatus = sSetError( stream, status );\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumTag( INOUT STREAM *stream, \n\t\t\t\t   INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t   IN_LENGTH_PKC const int maxLength, \n\t\t\t\t   IN_OPT TYPECAST( BIGNUM * ) const void *maxRange, \n\t\t\t\t   IN_TAG_EXT const int tag )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength, \n\t\t\t\t\t\t\t   maxRange, tag, KEYSIZE_CHECK_NONE ) );\n\t}\n\n/* Special-case bignum read routine that explicitly checks for a too-short \n   key and returns CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA \n   that'd otherwise be returned */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumChecked( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t   IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t   IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength, \n\t\t\t\t\t\t\t   maxRange, DEFAULT_TAG, KEYSIZE_CHECK_PKC ) );\n\t}\n\n/* Another special-case bignum routine that verifies that the bignum data to\n   be read corresponds to the in-memory bignum.  This is used after calling\n   readBignum() to verify that no corruption occurred when the bignum data \n   was transferred into the in-memory forum.  The reason for all the dummy\n   parameters is that it has to have the same function signature as \n   readBignumTag(), which it can be interchanged with */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkBignumRead( INOUT STREAM *stream, INOUT void *bignum, \n\t\t\t\t\t STDC_UNUSED IN_LENGTH_PKC const int dummy1, \n\t\t\t\t\t STDC_UNUSED IN_LENGTH_PKC const int dummy2, \n\t\t\t\t\t STDC_UNUSED IN_OPT const void *dummy3, \n\t\t\t\t\t IN_TAG_EXT const int tag )\n\t{\n\tvoid *bignumData;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\n\t/* Get a pointer to the bignum data and verify that it matches what's in \n\t   the bignum.  We don't have to perform the same level of checking that\n\t   we did for readBignumTag() since we've already read and checked the\n\t   metadata */\n\tstatus = length = readIntegerHeader( stream, tag );\n\tif( !cryptStatusError( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sMemGetDataBlock( stream, &bignumData, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( verifyBignumImport( bignum, bignumData, length ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_FAILED );\n\t}\n#endif /* USE_PKC */\n\n/* Read a universal type and discard it (used to skip unknown or unwanted\n   types) */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversalData( INOUT STREAM *stream )\n\t{\n\tlong length;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = readLengthValue( stream, &length, READLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\treturn( CRYPT_OK );\t/* Zero-length data */\n\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\treadTag( stream );\n\treturn( readUniversalData( stream ) );\n\t}\n\n/* Read a short integer value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readShortIntegerTag( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_INT_Z long *value, \n\t\t\t\t\t\t IN_TAG_EXT const int tag )\n\t{\n\treturn( readNumeric( stream, value, tag, TRUE ) );\n\t}\n\n/* Read an enumerated value.  This is encoded like an ASN.1 integer so we\n   just read it as such */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readEnumeratedTag( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_INT_Z int *enumeration, \n\t\t\t\t\t   IN_TAG_EXT const int tag )\n\t{\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( enumeration == NULL || \\\n\t\t\tisWritePtr( enumeration, sizeof( int ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Clear return value */\n\tif( enumeration != NULL )\n\t\t*enumeration = 0;\n\n\tstatus = readNumeric( stream, &value, tag, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value < 0 || value > 1000 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tENSURES( isIntegerRange( value ) );\n\tif( enumeration != NULL )\n\t\t*enumeration = ( int ) value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a null value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readNullTag( INOUT STREAM *stream, IN_TAG_EXT const int tag )\n\t{\n\tint value;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Read the identifier if necessary */\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_NULL ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tvalue = sgetc( stream );\n\tif( cryptStatusError( value ) )\n\t\treturn( value );\n\tif( value != 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a boolean value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBooleanTag( INOUT STREAM *stream, \n\t\t\t\t\tOUT_OPT_BOOL BOOLEAN *boolean, \n\t\t\t\t\tIN_TAG_EXT const int tag )\n\t{\n\tBYTE buffer[ 2 + 8 ];\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( boolean == NULL || \\\n\t\t\tisWritePtr( boolean, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Clear return value */\n\tif( boolean != NULL )\n\t\t*boolean = FALSE;\n\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_BOOLEAN ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = sread( stream, buffer, 2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( buffer[ 0 ] != 1 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( boolean != NULL )\n\t\t*boolean = ( buffer[ 1 ] != 0 ) ? TRUE : FALSE;\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an OID and check it against a permitted value or a selection of \n   permitted values */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readOIDEx( INOUT STREAM *stream, \n\t\t\t   IN_ARRAY( noOidSelectionEntries ) const OID_INFO *oidSelection, \n\t\t\t   IN_RANGE( 1, 50 ) const int noOidSelectionEntries,\n\t\t\t   OUT_OPT_PTR_COND const OID_INFO **oidSelectionValue )\n\t{\n\tstatic const OID_INFO nullOidSelection = { NULL, CRYPT_ERROR, NULL };\n\tBYTE buffer[ MAX_OID_SIZE + 8 ];\n\tint length, oidEntry, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oidSelection, \\\n\t\t\t\t\t\t\t  sizeof( OID_INFO ) * noOidSelectionEntries ) );\n\tassert( oidSelectionValue == NULL || \\\n\t\t\tisReadPtr( oidSelectionValue, sizeof( OID_INFO * ) ) );\n\n\tREQUIRES_S( noOidSelectionEntries > 0 && noOidSelectionEntries <= 50 );\n\n\t/* Clear return value */\n\tif( oidSelectionValue != NULL )\n\t\t*oidSelectionValue = &nullOidSelection;\n\n\t/* Read the OID data */\n\tstatus = readRawObject( stream, buffer, MAX_OID_SIZE, &length, \n\t\t\t\t\t\t\tBER_OBJECT_IDENTIFIER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES_S( length == sizeofOID( buffer ) );\n\n\t/* Try and find the entry for the OID.  Since related groups of OIDs \n\t   typically have identical lengths, we use the last byte of the OID\n\t   as a quick-reject check to avoid performing a full OID comparison\n\t   for each entry */\n\tLOOP_MED( oidEntry = 0, oidEntry < noOidSelectionEntries && \\\n\t\t\t\t\t\t\toidSelection[ oidEntry ].oid != NULL, \n\t\t\t  oidEntry++ )\n\t\t{\n\t\tconst BYTE *oidPtr = oidSelection[ oidEntry ].oid;\n\t\tconst int oidLength = sizeofOID( oidPtr );\n\n\t\t/* Check for a match-any wildcard OID */\n\t\tif( oidLength == WILDCARD_OID_SIZE && \\\n\t\t\toidPtr[ WILDCARD_OID_SIZE - 1 ] == \\\n\t\t\t\t\t\tWILDCARD_OID[ WILDCARD_OID_SIZE - 1 ] && \\\n\t\t\t!memcmp( oidPtr, WILDCARD_OID, WILDCARD_OID_SIZE ) )\n\t\t\t{\n\t\t\t/* The wildcard must be the last entry in the list */\n\t\t\tENSURES_S( oidEntry + 1 < noOidSelectionEntries && \\\n\t\t\t\t\t   oidSelection[ oidEntry + 1 ].oid == NULL );\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Check for a standard OID match */\n\t\tif( length == oidLength && \\\n\t\t\tbuffer[ length - 1 ] == oidPtr[ length - 1 ] && \\\n\t\t\t!memcmp( buffer, oidPtr, length ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tif( oidEntry >= noOidSelectionEntries || \\\n\t\toidSelection[ oidEntry ].oid == NULL )\n\t\t{\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\n\tif( oidSelectionValue != NULL )\n\t\t*oidSelectionValue = &oidSelection[ oidEntry ];\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readOID( INOUT STREAM *stream, \n\t\t\t IN_ARRAY( noOidSelectionEntries ) const OID_INFO *oidSelection, \n\t\t\t IN_RANGE( 1, 50 ) const int noOidSelectionEntries,\n\t\t\t OUT_RANGE( CRYPT_ERROR, \\\n\t\t\t\t\t\tnoOidSelectionEntries ) int *selectionID )\n\t{\n\tconst OID_INFO *oidSelectionInfo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oidSelection, \\\n\t\t\t\t\t\t\t  sizeof( OID_INFO ) * noOidSelectionEntries ) );\n\tassert( isWritePtr( selectionID, sizeof( int ) ) );\n\n\tREQUIRES_S( noOidSelectionEntries > 0 && noOidSelectionEntries <= 50 );\n\n\t/* Clear return value */\n\t*selectionID = CRYPT_ERROR;\n\n\tstatus = readOIDEx( stream, oidSelection, noOidSelectionEntries, \n\t\t\t\t\t\t&oidSelectionInfo );\n\tif( cryptStatusOK( status ) )\n\t\t*selectionID = oidSelectionInfo->selectionID;\n\treturn( status );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedOID( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t  IN_LENGTH_OID const int oidLength )\n\t{\n\tCONST_INIT_STRUCT_A2( OID_INFO oidInfo[ 3 ], oid, NULL );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) && \\\n\t\t\toidLength == sizeofOID( oid ) && \\\n\t\t\toid[ 0 ] == BER_OBJECT_IDENTIFIER );\n\n\tREQUIRES_S( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\t\t\t\t/* Must be first for static analysis tools */\n\tREQUIRES_S( oidLength == sizeofOID( oid ) && \\\n\t\t\t\toid[ 0 ] == BER_OBJECT_IDENTIFIER );\n\n\t/* Set up a one-entry OID_INFO list to pass down to readOID() */\n\tCONST_SET_STRUCT_A( memset( oidInfo, 0, sizeof( OID_INFO ) * 3 ); \\\n\t\t\t\t\t\toidInfo[ 0 ].oid = oid );\n\treturn( readOIDEx( stream, oidInfo, 3, NULL ) );\n\t}\n\n/* Read a raw OID in encoded form */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readEncodedOID( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER( oidMaxLength, *oidLength ) BYTE *oid, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 5 ) const int oidMaxLength, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( oidMaxLength ) int *oidLength, \n\t\t\t\t\tIN_TAG_ENCODED const int tag )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( oid, oidMaxLength ) );\n\tassert( isWritePtr( oidLength, sizeof( int ) ) );\n\n\tREQUIRES_S( oidMaxLength >= MIN_OID_SIZE && \\\n\t\t\t\toidMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_S( tag == NO_TAG || tag == BER_OBJECT_IDENTIFIER );\n\n\t/* Clear return values */\n\tmemset( oid, 0, min( 16, oidMaxLength ) );\n\t*oidLength = 0;\n\n\t/* Read the encoded OID and make sure that it's the right size for a\n\t   minimal-length OID: tag (optional) + length + minimal-length OID \n\t   data */\n\tstatus = readRawObject( stream, oid, oidMaxLength, &length, tag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < ( tag == NO_TAG ? 0 : 1 ) + 1 + 3 || \\\n\t\tlength > oidMaxLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t*oidLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an octet string value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int readString( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_BUFFER_OPT( maxLength, *stringLength ) \\\n\t\t\t\t\t\t\tBYTE *string, \n\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLength ) int *stringLength,\n\t\t\t\t\t   IN_LENGTH_SHORT const int minLength, \n\t\t\t\t\t   IN_LENGTH_SHORT const int maxLength, \n\t\t\t\t\t   IN_TAG_EXT const int tag, \n\t\t\t\t\t   const BOOLEAN isOctetString )\n\t{\n\tlong length;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( string == NULL || isWritePtrDynamic( string, maxLength ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\n\tREQUIRES_S( minLength > 0 && minLength <= maxLength && \\\n\t\t\t\tmaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_S( ( isOctetString && \\\n\t\t\t\t  ( tag == NO_TAG || tag == DEFAULT_TAG ) ) || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isOctetString == TRUE || isOctetString == FALSE );\n\n\t/* Clear return values */\n\tif( string != NULL )\n\t\tmemset( string, 0, min( 16, maxLength ) );\n\t*stringLength = 0;\n\n\t/* Read the string, limiting the size to the maximum buffer size.  If \n\t   it's an octet string we make this a hard limit, however if it's a \n\t   text string we simply read as much as will fit in the buffer and \n\t   discard the rest.  This is required to handle the widespread ignoring\n\t   of string length limits in certificates and other PKI-related data */\n\tif( isOctetString )\n\t\t{\n\t\tif( tag != NO_TAG && \\\n\t\t\treadTag( stream ) != selectTag( tag, BER_OCTETSTRING ) )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\telse\n\t\t{\n\t\tif( readTag( stream ) != tag )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tstatus = readLengthValue( stream, &length, READLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < minLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\tif( ( isOctetString && length > maxLength ) || \\\n\t\t( length >= MAX_INTLENGTH_SHORT ) )\n\t\t{\n\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t}\n\treturn( readConstrainedData( stream, string, maxLength, stringLength, \n\t\t\t\t\t\t\t\t length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readOctetStringTag( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER( maxLength, *stringLength ) BYTE *string, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) int *stringLength, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int minLength, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxLength, \n\t\t\t\t\t\tIN_TAG_EXT const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( string == NULL || isWritePtrDynamic( string, maxLength ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\n\tREQUIRES_S( minLength > 0 && minLength <= maxLength && \\\n\t\t\t\tmaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\treturn( readString( stream, string, stringLength, minLength, maxLength, \n\t\t\t\t\t\ttag, TRUE ) );\n\t}\n\n/* Read a character string.  This handles any of the myriad ASN.1 character\n   string types.  The handling of the tag works somewhat differently here to\n   the usual manner in that since the function is polymorphic, the tag\n   defines the character string type and is always used (there's no\n   NO_TAG or DEFAULT_TAG option like the other functions use).  This works \n   because the plethora of string types means that the higher-level routines \n   that read them invariably have to sort out the valid tag types \n   themselves */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint readCharacterString( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_BUFFER_OPT( stringMaxLength, *stringLength ) \\\n\t\t\t\t\t\t\tvoid *string, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\t\tint *stringLength, \n\t\t\t\t\t\t IN_TAG_EXT const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( string == NULL || isWritePtrDynamic( string, stringMaxLength ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( stringMaxLength ) );\n\tREQUIRES_S( tag >= 0 && tag < MAX_TAG_VALUE );\n\n\treturn( readString( stream, string, stringLength, 1, stringMaxLength, \n\t\t\t\t\t\ttag, FALSE ) );\n\t}\n\n/* Read a bit string */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBitStringTag( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_OPT_INT_Z int *bitString, \n\t\t\t\t\t  IN_TAG_EXT const int tag )\n\t{\n\tint length, data, mask, flag, value, noBits, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( bitString == NULL || isWritePtr( bitString, sizeof( int ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\t\n\t/* Clear return value */\n\tif( bitString != NULL )\n\t\t*bitString = 0;\n\n\t/* Make sure that we have a bitstring with between 0 and sizeof( int ) \n\t   bits.  This isn't as machine-dependant as it seems, the only place \n\t   where bit strings longer than one or two bytes are used is with CMP's \n\t   bizarre encoding of error subcodes that just provide further \n\t   information above and beyond the main error code and text message, \n\t   and CMP is highly unlikely to be used on a 16-bit machine */\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_BITSTRING ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength--;\t/* Adjust for bit count */\n\tif( length < 0 || length > 4 || length > sizeof( int ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tstatus = noBits = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( noBits < 0 || noBits > 7 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( length <= 0 )\n\t\treturn( CRYPT_OK );\t\t/* Zero value */\n\tENSURES_S( length >= 1 && length <= min( 4, sizeof( int ) ) );\n\tENSURES_S( noBits >= 0 && noBits <= 7 );\n\n\t/* Convert the bit count from the unused-remainder bit count into the \n\t   total bit count */\n\tnoBits = ( length * 8 ) - noBits;\n\tENSURES_S( noBits >= 0 && noBits <= 32 );\n\n\t/* ASN.1 bitstrings start at bit 0 so we need to reverse the order of \n\t   the bits before we return the value.  This uses a straightforward way\n\t   of doing it rather than the more efficient but hard-to-follow:\n\n\t\tdata = ( data & 0x55555555 ) << 1 | ( data >> 1 ) & 0x55555555;\n\t\tdata = ( data & 0x33333333 ) << 2 | ( data >> 2 ) & 0x33333333;\n\t\tdata = ( data & 0x0F0F0F0F ) << 4 | ( data >> 4 ) & 0x0F0F0F0F;\n\t\tdata = ( data << 24 ) | ( ( data & 0xFF00 ) << 8 ) | \\\n\t\t\t   ( ( data >> 8 ) & 0xFF00 || ( data >> 24 );\n\n\t  which swaps adjacent bits, then 2-bit fields, then 4-bit fields, and \n\t  so on */\n\tstatus = data = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_SMALL( ( mask = 0x80, i = 1 ), i < length, ( mask <<= 8, i++ ) )\n\t\t{\n\t\tconst long dataValTmp = data << 8;\n\t\tint dataTmp;\n\n\t\tstatus = dataTmp = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( data >= ( MAX_INTLENGTH >> 8 ) || \\\n\t\t\tdataValTmp >= MAX_INTLENGTH - data )\n\t\t\t{\n\t\t\t/* Integer overflow */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\tdata = dataValTmp | dataTmp;\n\t\tif( !isIntegerRange( data ) )\n\t\t\t{\n\t\t\t/* Integer overflow */\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tLOOP_MED( ( value = 0, flag = 1, i = 0 ), i < noBits, \n\t\t\t  ( flag <<= 1, i++ ) )\n\t\t{\n\t\tif( data & mask )\n\t\t\tvalue |= flag;\n\t\tdata <<= 1;\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tif( !isIntegerRange( value ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( bitString != NULL )\n\t\t*bitString = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a UTCTime and GeneralizedTime value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readTime( INOUT STREAM *stream, OUT time_t *timePtr, \n\t\t\t\t\t const BOOLEAN isUTCTime )\n\t{\n\tBYTE buffer[ 16 + 8 ];\n\tstruct tm theTime,  gmTimeInfo, *gmTimeInfoPtr = &gmTimeInfo;\n\ttime_t utcTime, gmTime;\n\tchar *bufPtr;\n\tint value = 0, length, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( timePtr, sizeof( time_t ) ) );\n\n\tREQUIRES( isUTCTime == TRUE || isUTCTime == FALSE );\n\n\t/* Clear return value */\n\t*timePtr = 0;\n\n\t/* Read the length field and make sure that it's of the correct size.  \n\t   There's only one encoding allowed although in theory the encoded \n\t   value could range in length from 11 to 17 bytes for UTCTime and 13 to \n\t   19 bytes for GeneralizedTime.  We formerly also allowed 11-byte \n\t   UTCTimes because an obsolete encoding rule allowed the time to be \n\t   encoded without seconds and Sweden Post hadn't realised that this had \n\t   changed yet, but these certs have now expired */\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ( isUTCTime && length != 13 ) || ( !isUTCTime && length != 15 ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tENSURES_S( length == 13 || length == 15 );\n\n\t/* Read the encoded time data and make sure that the contents are \n\t   valid */\n\tmemset( buffer, 0, 16 );\n\tstatus = sread( stream, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MED( i = 0, i < length - 1, i++ )\n\t\t{\n\t\tif( !isDigit( buffer[ i ] ) )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tif( buffer[ length - 1 ] != 'Z' )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tbufPtr = ( char * ) buffer;\t/* We now know it's 'char *' not 'BYTE *' */\n\n\t/* Decode the time fields */\n\tmemset( &theTime, 0, sizeof( struct tm ) );\n\ttheTime.tm_isdst = -1;\t\t/* Get the system to adjust for DST */\n\tif( !isUTCTime )\n\t\t{\n\t\tstatus = strGetNumeric( bufPtr, 2, &value, 19, 20 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tvalue = ( value - 19 ) * 100;\t/* Adjust for the century */\n\t\tbufPtr += 2;\n\t\t}\n\tstatus = strGetNumeric( bufPtr, 2, &theTime.tm_year, 0, 99 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttheTime.tm_year += value;\n\t\tstatus = strGetNumeric( bufPtr + 2, 2, &theTime.tm_mon, 1, 12 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttheTime.tm_mon--;\t\t\t\t/* Months are zero-based */\n\t\tstatus = strGetNumeric( bufPtr + 4, 2, &theTime.tm_mday, 1, 31 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = strGetNumeric( bufPtr + 6, 2, &theTime.tm_hour, 0, 23 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = strGetNumeric( bufPtr + 8, 2, &theTime.tm_min, 0, 59 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = strGetNumeric( bufPtr + 10, 2, &theTime.tm_sec, 0, 59 );\n\tif( cryptStatusError( status ) )\n\t\treturn( sSetError( stream, status ) );\n\n\t/* Finally, convert the decoded value to the local time.  Since the \n\t   UTCTime format doesn't take centuries into account (and you'd think \n\t   that when the ISO came up with the world's least efficient time \n\t   encoding format they could have spared another two bytes to fully \n\t   specify the year), we have to adjust by one century for years < 50 if \n\t   the format is UTCTime.  Note that there are some implementations that \n\t   currently roll over a century from 1970 (the Unix/Posix epoch and \n\t   sort-of ISO/ANSI C epoch although they never come out and say it) \n\t   but hopefully these will be fixed by 2050 when it would become an\n\t   issue.\n\n\t   In theory we could also check for an at least vaguely sane input \n\t   value range on the grounds that (a) some systems' mktime()s may be \n\t   broken and (b) some mktime()s may allow (and return) outrageous date \n\t   values that others don't, however it's probably better to simply be \n\t   consistent with what the system does rather than to try and \n\t   second-guess the intent of the mktime() authors.\n\n\t\t\"The time is out of joint; o cursed spite,\n\t\t That ever I was born to set it right\"\t- Shakespeare, \"Hamlet\" */\n\tif( isUTCTime && theTime.tm_year < 50 )\n\t\ttheTime.tm_year += 100;\n\tutcTime = mktime( &theTime );\n\tif( utcTime < 0 )\n\t\t{\n\t\t/* Some Java-based apps with 64-bit times use ridiculous validity\n\t\t   dates (yes, we're going to be keeping the same key in active use\n\t\t   for *forty years*) that postdate the time_t range when time_t is \n\t\t   a signed 32-bit value.  If we can't convert the time, we check \n\t\t   for a year after the time_t overflow (2038) and try again.  In\n\t\t   theory we should just reject objects with such broken dates but\n\t\t   since we otherwise accept all sorts of rubbish we at least try \n\t\t   and accept these as well */\n\t\tif( theTime.tm_year >= 138 && theTime.tm_year < 180 )\n\t\t\t{\n\t\t\ttheTime.tm_year = 136;\t\t/* 2036 */\n\t\t\tutcTime = mktime( &theTime );\n\t\t\t}\n\n\t\t/* Some broken apps set dates to 1/1/1970, handling times this close \n\t\t   to the epoch is problematic because once any possible DST \n\t\t   adjustment is taken into account it's no longer possible to\n\t\t   represent the converted time as a time_t unless the system allows\n\t\t   it to be negative (Windows doesn't, many Unixen do, but having\n\t\t   cryptlib return a negative time value is probably a bad thing).  \n\t\t   To handle this, if we find a date set anywhere during January 1970 \n\t\t   we manually set the time to the minimum valid time value */\n\t\tif( theTime.tm_year == 70 && theTime.tm_mon == 0 )\n\t\t\t{\n\t\t\t*timePtr = MIN_STORED_TIME_VALUE + 1;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tif( utcTime < MIN_STORED_TIME_VALUE )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( utcTime >= MAX_TIME_VALUE )\n\t\t{\n\t\t/* The time is dangerously close to Y2038, clamp it at a safe \n\t\t   value */\n\t\tutcTime = MAX_TIME_VALUE - 1;\n\t\t}\n\n\t/* Convert the UTC time to local time.  This is complicated by the fact \n\t   that although the C standard library can convert from local time -> \n\t   UTC it can't convert the time back, so we treat the UTC time as \n\t   local time (gmtime_s() always assumes that the input is local time) \n\t   and covert to GMT and back, which should give the offset from GMT.  \n\t   Since we can't assume that time_t is signed we have to treat a \n\t   negative and positive offset separately (see the comment in the \n\t   \"utcTime < gmTime\" portion below).\n\t   \n\t   An extra complication is added by daylight savings time adjustment, \n\t   some (hopefully most by now) systems adjust for DST by default, some \n\t   don't, and some allow it to be configured by the user so that it can \n\t   vary from machine to machine so we have to make it explicit as part \n\t   of the conversion process.\n\t   \n\t   Even this still isn't perfect because it displays the time adjusted \n\t   for DST now rather than DST when the time value was created.  This \n\t   will occur when the code is run within about 12-13 hours either way \n\t   of the time at which the DST switchover occurs at that particular \n\t   locality and doesn't necessarily have to be during the switchover \n\t   hour since being in a different time zone to GMT can change the time \n\t   by many hours, flipping it across the switchover hour.\n\t   \n\t   This problem is more or less undecidable, the code used here has the \n\t   property that the values for Windows agree with those for Unix and \n\t   other systems, but it can't handle the DST flip because there's no\n\t   way to find out whether it's happened to us or not */\n\tgmTimeInfoPtr = gmTime_s( &utcTime, gmTimeInfoPtr );\n\tif( gmTimeInfoPtr == NULL )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tgmTimeInfoPtr->tm_isdst = -1;\t\t/* Force correct DST adjustment */\n\tgmTime = mktime( gmTimeInfoPtr );\n\tif( gmTime < MIN_STORED_TIME_VALUE )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( utcTime < gmTime )\n\t\t{\n\t\t/* If time_t is signed, then this and the expression in the \"else\"\n\t\t   branch do the same thing since in the following line if e.g. \n\t\t   utcTime > gmTime then ( gmTime - utcTime ) is negative, so\n\t\t   subtracting that means adding it, the same as the \"else\" portion\n\t\t   below, however we leave the two distinct for cases where time_t\n\t\t   is unsigned */\n\t\t*timePtr = utcTime - ( gmTime - utcTime );\n\t\t}\n\telse\n\t\t*timePtr = utcTime + ( utcTime - gmTime );\n\tif( *timePtr >= MAX_TIME_VALUE )\n\t\t*timePtr = MAX_TIME_VALUE - 1;\n\n\t/* This still isn't quite perfect since it can't handle the time at a \n\t   DST changeover.  This is really a user problem (\"Don't do that, \n\t   then\") but if necessary can be corrected by converting back to GMT as \n\t   a sanity check and applying a +/- 1 hour correction if there's a \n\t   mismatch */\n#if 0\n\tgmTimeInfoPtr = gmTime_s( timePtr );\n\tgmTimeInfoPtr->tm_isdst = -1;\n\tgmTime = mktime( gmTimeInfoPtr );\n\tif( gmTime != utcTime )\n\t\t{\n\t\t*timePtr += 3600;\t\t/* Try +1 first */\n\t\tgmTimeInfoPtr = gmTime_s( timePtr, gmTimeInfoPtr );\n\t\tgmTimeInfoPtr->tm_isdst = -1;\n\t\tgmTime = mktime( gmTimeInfoPtr );\n\t\tif( gmTime != utcTime )\n\t\t\t*timePtr -= 7200;\t/* Nope, use -1 instead */\n\t\t}\n#endif /* 0 */\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readUTCTimeTag( INOUT STREAM *stream, OUT time_t *timeVal, \n\t\t\t\t\tIN_TAG_EXT const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( timeVal, sizeof( time_t ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Clear return value */\n\t*timeVal = 0;\n\t\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_TIME_UTC ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( readTime( stream, timeVal, TRUE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGeneralizedTimeTag( INOUT STREAM *stream, OUT time_t *timeVal, \n\t\t\t\t\t\t\tIN_TAG_EXT const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( timeVal, sizeof( time_t ) ) );\n\n\tREQUIRES_S( tag == NO_TAG || tag == DEFAULT_TAG || \\\n\t\t\t\t( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* Clear return value */\n\t*timeVal = 0;\n\t\n\tif( tag != NO_TAG && readTag( stream ) != selectTag( tag, BER_TIME_GENERALIZED ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( readTime( stream, timeVal, FALSE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Routines for Constructed Objects\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the header for a constructed object.  This performs a more strict \n   check than the checkTag() function used when reading the tag because\n   we know that we're reading a constructed object or hole and can restrict\n   the permitted values accordingly.  The behaviour of the read is \n   controlled by the following flags:\n\n\tFLAG_BITSTRING: The object being read is a BIT STRING with an extra \n\t\tunused-bits count at the start.  This explicit indication is \n\t\trequired because implicit tagging can obscure the fact that what's\n\t\tbeing read is a BIT STRING.\n\n\tFLAG_INDEFOK: Indefinite-length objects are permitted for short-object\n\t\treads.\n\n\tFLAG_UNIVERSAL: Normally we perform a sanity check to make sure that \n\t\twhat we're reading has a valid tag for a constructed object or a \n\t\thole, however if we're reading the object as a blob then we're more \n\t\tliberal in what we allow, although we still perform some minimal \n\t\tchecking */\n\n#define READOBJ_FLAG_NONE\t\t0x00\t/* No flag */\n#define READOBJ_FLAG_BITSTRING\t0x01\t/* Object is BIT STRING */\n#define READOBJ_FLAG_INDEFOK\t0x02\t/* Indefinite lengths allowed */\n#define READOBJ_FLAG_UNIVERSAL\t0x04\t/* Relax type-checking requirements */\n#define READOBJ_FLAG_MAX\t\t0x0F\t/* Maximum possible flag value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkReadTag( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_TAG_ENCODED_EXT const int tag,\n\t\t\t\t\t\t const BOOLEAN allowRelaxedMatch )\n\t{\n\tint tagValue, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( ( tag == ANY_TAG ) || ( tag >= 1 && tag < MAX_TAG ) );\n\t\t\t\t/* Note tag != 0 */\n\tREQUIRES( allowRelaxedMatch == TRUE || allowRelaxedMatch == FALSE );\n\n\t/* Read the identifier field */\n\tstatus = tagValue = readTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag != ANY_TAG )\n\t\t{\n\t\t/* If we have to get an exact match, make sure that the tag matches \n\t\t   what we're expecting */\n\t\tif( tagValue != tag )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Even if we're prepared to accept (almost) any tag we still have to \n\t   check for valid universal tags: BIT STRING, primitive or constructed \n\t   OCTET STRING, SEQUENCE, or SET */\n\tif( tagValue == BER_BITSTRING || tagValue == BER_OCTETSTRING || \\\n\t\ttagValue == ( BER_OCTETSTRING | BER_CONSTRUCTED ) || \\\n\t\ttagValue == BER_SEQUENCE || tagValue == BER_SET )\n\t\treturn( CRYPT_OK );\n\n\t/* In addition we can accept context-specific tagged items up to \n\t   MAX_CTAG_VALUE */\n\tif( ( tagValue & BER_CLASS_MASK ) == BER_CONTEXT_SPECIFIC && \\\n\t\t( tagValue & BER_SHORT_ID_MASK ) <= MAX_CTAG_VALUE )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're reading an object as a genuine blob rather than a \n\t   constructed object or hole we allow a wider range of tags that \n\t   wouldn't normally be permitted as holes.  Currently only INTEGERs\n\t   are read in this manner, from their use as generic blobs in \n\t   certificate serial numbers and the like */\n\tif( allowRelaxedMatch && tagValue == BER_INTEGER )\n\t\treturn( CRYPT_OK );\n\n\t/* Anything else is invalid */\n\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readObjectHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_OPT_LENGTH_SHORT_INDEF int *length, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int minLength, \n\t\t\t\t\t\t\t IN_TAG_ENCODED_EXT const int tag, \n\t\t\t\t\t\t\t IN_FLAGS_Z( READOBJ ) const int flags )\n\t{\n\tlong dataLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRange( minLength ) );\n\tREQUIRES_S( ( tag == ANY_TAG ) || ( tag >= 1 && tag < MAX_TAG ) );\n\t\t\t\t/* Note tag != 0 */\n\tREQUIRES( isFlagRangeZ( flags, READOBJ ) );\n\n\t/* Clear return value */\n\tif( length != NULL )\n\t\t*length = 0;\n\n\t/* Read the identifier field and length.  If the indefiniteOK flag is \n\t   set or the length is being ignored by the caller then we allow \n\t   indefinite lengths.  The latter is because it makes handling of \n\t   infinitely-nested SEQUENCEs and whatnot easier if we don't have to \n\t   worry about definite vs. indefinite-length encodings (ex duobus malis \n\t   minimum eligendum est), and if indefinite lengths really aren't OK \n\t   then they'll be picked up when the caller runs into the EOC at the \n\t   end of the object */\n\tstatus = checkReadTag( stream, tag, \n\t\t\t\t\t\t   ( flags & READOBJ_FLAG_UNIVERSAL ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readLengthValue( stream, &dataLength,\n\t\t\t\t\t\t\t  ( ( flags & READOBJ_FLAG_INDEFOK ) || \\\n\t\t\t\t\t\t\t\tlength == NULL ) ? \\\n\t\t\t\t\t\t\t\tREADLENGTH_SHORT_INDEF : READLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a bit string then there's an extra unused-bits count.  Since \n\t   this is a hole encoding we don't bother about the actual value except \n\t   to check that it has a sensible value */\n\tif( flags & READOBJ_FLAG_BITSTRING )\n\t\t{\n\t\tint value;\n\n\t\tif( dataLength != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tdataLength--;\n\t\t\tif( !isIntegerRange( dataLength ) )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\tstatus = value = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value < 0 || value > 7 )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\n\t/* Make sure that the length is in order (it has to be less than \n\t   MAX_INTLENGTH_SHORT for short lengths) and return it to the caller \n\t   if necessary */\n\tif( dataLength != CRYPT_UNUSED )\n\t\t{\n\t\tif( dataLength < minLength || \\\n\t\t\tdataLength >= MAX_INTLENGTH_SHORT || \\\n\t\t\tdataLength >= MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tif( length != NULL )\n\t\t*length = dataLength;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readLongObjectHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t OUT_OPT_LENGTH_INDEF long *length,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int minLength, \n\t\t\t\t\t\t\t\t IN_TAG_ENCODED_EXT const int tag, \n\t\t\t\t\t\t\t\t IN_FLAGS_Z( READOBJ ) const int flags )\n\t{\n\tlong dataLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES_S( isShortIntegerRange( minLength ) );\n\tREQUIRES_S( ( tag == ANY_TAG ) || ( tag >= 1 && tag < MAX_TAG ) );\n\t\t\t\t/* Note tag != 0 */\n\tREQUIRES( flags == READOBJ_FLAG_NONE || \\\n\t\t\t  flags == READOBJ_FLAG_UNIVERSAL );\n\n\t/* Clear return value */\n\tif( length != NULL )\n\t\t*length = 0L;\n\n\t/* Read the identifier field and length */\n\tstatus = checkReadTag( stream, tag,\n\t\t\t\t\t\t   ( flags & READOBJ_FLAG_UNIVERSAL ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readLengthValue( stream, &dataLength, READLENGTH_LONG_INDEF );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the length is in order and return it to the caller if \n\t   necessary */\n\tif( dataLength != CRYPT_UNUSED )\n\t\t{\n\t\tif( dataLength < minLength || dataLength >= MAX_INTLENGTH || \\\n\t\t\tdataLength >= MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tif( length != NULL )\n\t\t*length = dataLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an encapsulating SEQUENCE or SET or BIT STRING/OCTET STRING hole */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readSequenceExt( INOUT STREAM *stream, \n\t\t\t\t\t /* PARAMCHECK */ int *length,\n\t\t\t\t\t IN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( lengthCheckType, LENGTH_CHECK ) );\n\n\treturn( readObjectHeader( stream, length, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_ZERO ) ? 0 : 1, \n\t\t\t\t\tBER_SEQUENCE, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_NONZERO_INDEF ) ? \\\n\t\t\t\t\t  READOBJ_FLAG_INDEFOK : READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readSetExt( INOUT STREAM *stream, \n\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( lengthCheckType, LENGTH_CHECK ) );\n\n\treturn( readObjectHeader( stream, length, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_ZERO ) ? 0 : 1, \n\t\t\t\t\tBER_SET, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_NONZERO_INDEF ) ? \\\n\t\t\t\t\t  READOBJ_FLAG_INDEFOK : READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \\\nint readConstructedExt( INOUT STREAM *stream, \n\t\t\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\t\t\tIN_TAG const int tag,\n\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES_S( ( tag == DEFAULT_TAG ) || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES( isEnumRange( lengthCheckType, LENGTH_CHECK ) );\n\n\treturn( readObjectHeader( stream, length, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_ZERO ) ? 0 : 1, \n\t\t\t\t\t( tag == DEFAULT_TAG ) ? BER_SEQUENCE : MAKE_CTAG( tag ), \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_NONZERO_INDEF ) ? \\\n\t\t\t\t\t  READOBJ_FLAG_INDEFOK : READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readOctetStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int minLength,\n\t\t\t\t\t\t IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES_S( ( tag == DEFAULT_TAG ) || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isShortIntegerRangeNZ( minLength ) );\n\n\treturn( readObjectHeader( stream, length, minLength, \n\t\t\t\t\t\t\t  ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t\t\t\t\tBER_OCTETSTRING : MAKE_CTAG_PRIMITIVE( tag ),\n\t\t\t\t\t\t\t  READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readBitStringHole( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,\n\t\t\t\t\t   IN_LENGTH_SHORT const int minLength, \n\t\t\t\t\t   IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES_S( ( tag == DEFAULT_TAG ) || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isShortIntegerRangeNZ( minLength ) );\n\n\treturn( readObjectHeader( stream, length, minLength, \n\t\t\t\t\t\t\t  ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t\t\t\t\tBER_BITSTRING : MAKE_CTAG_PRIMITIVE( tag ),\n\t\t\t\t\t\t\t  READOBJ_FLAG_BITSTRING ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nPARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \\\nPARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_MIN( minLength ) ) \\\nint readGenericHoleExt( INOUT STREAM *stream, \n\t\t\t\t\t\t/* PARAMCHECK */ int *length,\n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int minLength, \n\t\t\t\t\t\tIN_TAG_ENCODED const int tag,\n\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( int ) ) );\n\n\tENSURES_S( ( tag == DEFAULT_TAG ) || ( tag > 0 && tag < MAX_TAG ) );\n\t\t\t   /* We use MAX_TAG rather than MAX_TAG_VALUE since we don't \n\t\t\t      know what form it has to be turned into when reading \n\t\t\t\t  the tag */\n\tREQUIRES_S( minLength >= ( ( lengthCheckType == LENGTH_CHECK_ZERO ) ? 0 : 1 ) && \\\n\t\t\t\tminLength < MAX_INTLENGTH_SHORT );\n\t\t\t\t/* We allow a length of zero in order to deal with broken \n\t\t\t\t   encodings */\n\tREQUIRES( isEnumRange( lengthCheckType, LENGTH_CHECK ) );\n\n\treturn( readObjectHeader( stream, length, minLength, \n\t\t\t\t\t( tag == DEFAULT_TAG ) ? ANY_TAG : tag, \n\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_NONZERO_INDEF ) ? \\\n\t\t\t\t\t  READOBJ_FLAG_INDEFOK : READOBJ_FLAG_NONE ) );\n\t}\n\n/* Read an abnormally-long encapsulating SEQUENCE or OCTET STRING hole.  \n   This is used in place of the usual read in situations where potentially \n   huge data quantities would fail the sanity check enforced by the \n   standard read.  This form always allows indefinite lengths, which are \n   likely for large objects */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongSequence( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_OPT_LENGTH_INDEF long *length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\n\treturn( readLongObjectHeader( stream, length, 1, BER_SEQUENCE,\n\t\t\t\t\t\t\t\t  READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongSet( INOUT STREAM *stream, OUT_OPT_LENGTH_INDEF long *length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\n\treturn( readLongObjectHeader( stream, length, 1, BER_SET, \n\t\t\t\t\t\t\t\t  READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongConstructed( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_OPT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES_S( ( tag == DEFAULT_TAG ) || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\treturn( readLongObjectHeader( stream, length, 1, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t\t\t\t\t  BER_SEQUENCE : MAKE_CTAG( tag ), \n\t\t\t\t\t\t\t\t  READOBJ_FLAG_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readLongGenericHoleExt( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT_OPT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t\tIN_TAG_ENCODED const int tag,\n\t\t\t\t\t\t\tIN_ENUM( LENGTH_CHECK ) \\\n\t\t\t\t\t\t\t\tconst LENGTH_CHECK_TYPE lengthCheckType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\n\tENSURES_S( ( tag == DEFAULT_TAG ) || ( tag > 0 && tag < MAX_TAG ) );\n\t\t\t   /* We use MAX_TAG rather than MAX_TAG_VALUE since we don't\n\t\t\t      know what form it has to be turned into when reading\n\t\t\t\t  the tag */\n\tREQUIRES( isEnumRange( lengthCheckType, LENGTH_CHECK ) );\n\n\treturn( readLongObjectHeader( stream, length, \n\t\t\t\t\t\t( lengthCheckType == LENGTH_CHECK_ZERO ) ? 0 : 1, \n\t\t\t\t\t\t( tag == DEFAULT_TAG ) ? ANY_TAG : tag,\n\t\t\t\t\t\tREADOBJ_FLAG_NONE ) );\n\t}\n\n/* Read a generic object header, used to find the length of an object being\n   read as a blob */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readGenericObjectHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_LENGTH_INDEF long *length, \n\t\t\t\t\t\t\t const BOOLEAN isLongObject )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES( isLongObject == TRUE || isLongObject == FALSE );\n\n\t/* Clear return value */\n\t*length = 0L;\n\n\tif( !isLongObject )\n\t\t{\n\t\tint localLength, status;\n\n\t\tstatus = readObjectHeader( stream, &localLength, 1, ANY_TAG, \n\t\t\t\t\t\t\t\t   READOBJ_FLAG_INDEFOK | \\\n\t\t\t\t\t\t\t\t   READOBJ_FLAG_UNIVERSAL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*length = localLength;\n\n\t\treturn( status );\n\t\t}\n\n\treturn( readLongObjectHeader( stream, length, 1, ANY_TAG, \n\t\t\t\t\t\t\t\t  READOBJ_FLAG_UNIVERSAL ) );\n\t}\n\n/* Read an arbitrary-length constructed object's data into a memory buffer, \n   used by keyset-read routines that need to read the encoded form of an\n   object into memory.  This is the arbitrary-length form of \n   readRawObject() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readRawObjectAlloc( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER_ALLOC_OPT( *objectLengthPtr ) \\\n\t\t\t\t\t\t\tvoid **objectPtrPtr,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength  ) \\\n\t\t\t\t\t\t\tint *objectLengthPtr,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( OBJECT_HEADER_DATA_SIZE ) \\\n\t\t\t\t\t\t\tconst int minLength, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxLength )\n\t{\n\tSTREAM headerStream;\n\tBYTE buffer[ OBJECT_HEADER_DATA_SIZE + 8 ];\n\tvoid *objectData;\n\tint objectLength, headerSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( objectPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( objectLengthPtr, sizeof( int ) ) );\n\n\tREQUIRES_S( minLength >= OBJECT_HEADER_DATA_SIZE && \\\n\t\t\t\tminLength < maxLength && \\\n\t\t\t\tmaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*objectPtrPtr = NULL;\n\t*objectLengthPtr = 0;\n\n\t/* Find out how much data we need to read.  This may be a non-seekable\n\t   stream so we have to grab the first OBJECT_HEADER_DATA_SIZE bytes \n\t   from the stream and decode them to see what's next */\n\tstatus = sread( stream, buffer, OBJECT_HEADER_DATA_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &headerStream, buffer, OBJECT_HEADER_DATA_SIZE );\n\tstatus = readGenericHole( &headerStream, &objectLength, \n\t\t\t\t\t\t\t  OBJECT_HEADER_DATA_SIZE, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\theaderSize = stell( &headerStream );\n\tsMemDisconnect( &headerStream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsSetError( stream, status );\n\t\treturn( status );\n\t\t}\n\tobjectLength += headerSize;\n\n\t/* Make sure that the object has a sensible length */\n\tif( objectLength < minLength || objectLength > maxLength )\n\t\t{\n\t\tsSetError( stream, CRYPT_ERROR_BADDATA );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Allocate storage for the object data and copy the already-read \n\t   portion to the start of the storage */\n\tREQUIRES( rangeCheck( objectLength, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( objectData = clAlloc( \"readRawObjectAlloc\", \n\t\t\t\t\t\t\t\tobjectLength ) ) == NULL )\n\t\t{\n\t\t/* This isn't technically a stream error, but all ASN.1 stream \n\t\t   functions need to set the stream error status */\n\t\tsSetError( stream, CRYPT_ERROR_MEMORY );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tmemcpy( objectData, buffer, OBJECT_HEADER_DATA_SIZE );\n\n\t/* Read the remainder of the object data into the memory buffer and \n\t   check that the overall object is valid */\n\tstatus = sread( stream, ( BYTE * ) objectData + OBJECT_HEADER_DATA_SIZE,\n\t\t\t\t\tobjectLength - OBJECT_HEADER_DATA_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( objectData, objectLength );\n\t\tclFree( \"readRawObjectAlloc\", objectData );\n\t\treturn( status );\n\t\t}\n\tstatus = checkObjectEncoding( objectData, objectLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( objectData, objectLength );\n\t\tclFree( \"readRawObjectAlloc\", objectData );\n\t\tsSetError( stream, CRYPT_ERROR_BADDATA );\n\t\treturn( status );\n\t\t}\n\n\t*objectPtrPtr = objectData;\n\t*objectLengthPtr = objectLength;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_ASN1 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/asn1_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tASN.1 Write Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"bn.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"bn/bn.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_ASN1\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate the size of the encoded length octets */\n\nCHECK_RETVAL_RANGE( 1, 5 ) \\\nstatic int calculateLengthSize( IN_LENGTH_Z const long length )\n\t{\n\tREQUIRES( isIntegerRange( length ) );\n\n\t/* Use the short form of the length octets if possible */\n\tif( length <= 0x7F )\n\t\treturn( 1 );\n\n\t/* Use the long form of the length octets, a length-of-length followed \n\t   by an 8, 16, 24, or 32-bit length.  We order the comparisons by \n\t   likelihood of occurrence, shorter lengths are far more common than \n\t   longer ones */\n\tif( length <= 0xFF )\n\t\treturn( 1 + 1 );\n\tif( length <= 0xFFFFL )\n\t\treturn( 1 + 2 );\n\treturn( 1 + ( ( length > 0xFFFFFFL ) ? 4 : 3 ) );\n\t}\n\n/* Write the length octets for an ASN.1 item */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeLength( INOUT STREAM *stream, IN_LENGTH_Z const long length )\n\t{\n\tBYTE buffer[ 8 + 8 ];\n\tconst int noLengthOctets = ( length <= 0xFF ) ? 1 : \\\n\t\t\t\t\t\t\t   ( length <= 0xFFFFL ) ? 2 : \\\n\t\t\t\t\t\t\t   ( length <= 0xFFFFFFL ) ? 3 : 4;\n\tint bufPos = 1;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( length ) );\n\n\t/* Use the short form of the length octets if possible */\n\tif( length <= 0x7F )\n\t\treturn( sputc( stream, length & 0xFF ) );\n\n\t/* Encode the number of length octets followed by the octets themselves */\n\tbuffer[ 0 ] = intToByte( 0x80 | noLengthOctets );\n\tif( noLengthOctets > 3 )\n\t\tbuffer[ bufPos++ ] = intToByte( ( length >> 24 ) & 0xFF );\n\tif( noLengthOctets > 2 )\n\t\tbuffer[ bufPos++ ] = intToByte( ( length >> 16 ) & 0xFF );\n\tif( noLengthOctets > 1 )\n\t\tbuffer[ bufPos++ ] = intToByte( ( length >> 8 ) & 0xFF );\n\tbuffer[ bufPos++ ] = intToByte( length & 0xFF );\n\treturn( swrite( stream, buffer, bufPos ) );\n\t}\n\n/* Write a (non-bignum) numeric value, used by several routines.  The \n   easiest way to do this is to encode the bytes starting from the LSB\n   and then output them in reverse order to get a big-endian encoding */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeNumeric( INOUT STREAM *stream, IN_INT const long integer )\n\t{\n\tBYTE buffer[ 16 + 8 ];\n\tlong intValue = integer;\n\tint length = 0, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( integer ) );\n\n\t/* The value 0 is handled specially */\n\tif( intValue == 0 )\n\t\treturn( swrite( stream, \"\\x01\\x00\", 2 ) );\n\n\t/* Assemble the encoded value in little-endian order */\n\tif( intValue > 0 )\n\t\t{\n\t\tLOOP_SMALL_CHECKINC( intValue > 0, intValue >>= 8 )\n\t\t\t{\n\t\t\tbuffer[ length++ ] = intToByte( intValue & 0xFF );\n\t\t\t}\n\t\tENSURES_S( LOOP_BOUND_OK );\n\n\t\t/* Make sure that we don't inadvertently set the sign bit if the \n\t\t   high bit of the value is set */\n\t\tif( buffer[ length - 1 ] & 0x80 )\n\t\t\tbuffer[ length++ ] = 0x00;\n\t\t}\n\telse\n\t\t{\n\t\t/* Write a negative integer values.  This code is never executed \n\t\t   (and is actually checked for by the precondition at the start of\n\t\t   this function), it's present only in case it's ever needed in the \n\t\t   future */\n\t\tLOOP_SMALL_CHECKINC( intValue != -1 && length < sizeof( int ), \n\t\t\t\t\t\t\t intValue >>= 8 )\n\t\t\t{\n\t\t\tbuffer[ length++ ] = intToByte( intValue & 0xFF );\n\t\t\t}\n\t\tENSURES_S( LOOP_BOUND_OK );\n\n\t\t/* Make sure that we don't inadvertently clear the sign bit if the \n\t\t   high bit of the value is clear */\n\t\tif( !( buffer[ length - 1 ] & 0x80 ) )\n\t\t\tbuffer[ length++ ] = 0xFF;\n\t\t}\n\tENSURES_S( length > 0 && length <= 8 );\n\n\t/* Output the value in reverse (big-endian) order */\n\tsputc( stream, length );\n\tLOOP_SMALL( i = length - 1, i > 0, i-- )\n\t\tsputc( stream, buffer[ i ] );\n\tENSURES_S( LOOP_BOUND_OK );\n\treturn( sputc( stream, buffer[ 0 ] ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSizeof Routines\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine the encoded size of an object given only a length.  This\n   function is a bit problematic because it's frequently called as part \n   of a complex expression, where in theory it should never be passed a \n   negative value but due to some sort of exceptional circumstances may\n   end up being passed one.  Since this is a can't-occur condition, we \n   don't want to go overboard with checking for it (it would require having \n   to check the return value of every single use of sizeofObject() within a\n   complex expression), but also need some means of being able to cope with\n   it.  To deal with this we always return a safe length of zero on error.\n   \n   In addition to the general sizeofObject(), we also provide a \n   sizeofShortObject() that avoids the need to cast values to ints all over \n   the code */\n\nRETVAL_LENGTH_NOERROR \\\nlong sizeofObject( IN_LENGTH_Z const long length )\n\t{\n\t/* If we've been passed an error code as input or we're about to exceed \n\t   the maximum safe length range, don't try and go any further */\n\tif( length < 0 || length > MAX_INTLENGTH - 16 )\n\t\t{\n\t\tDEBUG_DIAG( ( \"Invalid value passed to sizeofObject()\" ) );\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n\t\t}\n\n\treturn( 1 + calculateLengthSize( length ) + length );\n\t}\n\nRETVAL_LENGTH_SHORT_NOERROR \\\nint sizeofShortObject( IN_LENGTH_SHORT_Z const int length )\n\t{\n\t/* If we've been passed an error code as input or we're about to exceed \n\t   the maximum safe length range, don't try and go any further */\n\tif( length < 0 || length > MAX_INTLENGTH_SHORT - 16 )\n\t\t{\n\t\tDEBUG_DIAG( ( \"Invalid value passed to sizeofShortObject()\" ) );\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n\t\t}\n\n\treturn( 1 + calculateLengthSize( length ) + length );\n\t}\n\n#ifdef USE_PKC\n\n/* Determine the size of a bignum.  When we're writing these we can't use \n   sizeofObject() directly because the internal representation is unsigned \n   whereas the encoded form is signed */\n\nRETVAL_RANGE_NOERROR( 0, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint signedBignumSize( IN TYPECAST( BIGNUM * ) const void *bignum )\n\t{\n\tconst int length = BN_num_bytes( bignum );\n\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\t/* The output from this function is typically used in calculations\n\t   involving multiple bignums, for which it doesn't make much sense to\n\t   individually check the return value of each function call for a\n\t   condition that can only be caused by an internal error, so we throw\n\t   an exception in debug mode but otherwise convert the condition to\n\t   a no-op length value */\n\tif( cryptStatusError( length ) )\n\t\tretIntError_Ext( 0 );\n\n\t/* Return the bignum length plus a leading zero byte if the high bit is \n\t   set */\n\treturn( length + ( ( BN_high_bit( ( BIGNUM * ) bignum ) ) ? 1 : 0 ) );\n\t}\n#endif /* USE_PKC */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tWrite Routines for Primitive Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a short/large/bignum integer value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeShortInteger( INOUT STREAM *stream, \n\t\t\t\t\t   IN_INT_Z const long integer, \n\t\t\t\t\t   IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( integer ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_INTEGER : MAKE_CTAG_PRIMITIVE( tag ) );\n\treturn( writeNumeric( stream, integer ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( integerLength ) const BYTE *integer, \n\t\t\t\t  IN_LENGTH_SHORT const int integerLength, \n\t\t\t\t  IN_TAG const int tag )\n\t{\n\tconst int leadingZero = ( integerLength > 0 && ( *integer & 0x80 ) ) ? \\\n\t\t\t\t\t\t\t1 : 0;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( integer, integerLength ) );\n\n\tREQUIRES_S( isShortIntegerRange( integerLength ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_INTEGER : MAKE_CTAG_PRIMITIVE( tag ) );\n\twriteLength( stream, integerLength + leadingZero );\n\tif( leadingZero )\n\t\tsputc( stream, 0 );\n\treturn( swrite( stream, integer, integerLength ) );\n\t}\n\n#ifdef USE_PKC\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumTag( INOUT STREAM *stream, \n\t\t\t\t\tIN TYPECAST( BIGNUM * ) const void *bignum, \n\t\t\t\t\tIN_TAG const int tag )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_S( !BN_is_zero( ( BIGNUM * ) bignum ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* If it's a dummy write, don't go through the full encoding process.\n\t   This optimisation both speeds things up and reduces unnecessary\n\t   writing of key data to memory */\n\tif( sIsNullStream( stream ) )\n\t\t{\n\t\treturn( sSkip( stream, sizeofBignum( bignum ), \n\t\t\t\t\t   MAX_INTLENGTH_SHORT ) );\n\t\t}\n\n\tstatus = exportBignum( buffer, CRYPT_MAX_PKCSIZE, &length, bignum );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Stream( stream );\n\tstatus = writeInteger( stream, buffer, length, tag );\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\treturn( status );\n\t}\n#endif /* USE_PKC */\n\n/* Write an enumerated value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeEnumerated( INOUT STREAM *stream, \n\t\t\t\t\t IN_RANGE( 0, 999 ) const int enumerated, \n\t\t\t\t\t IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( enumerated >= 0 && enumerated < 1000 );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_ENUMERATED : MAKE_CTAG_PRIMITIVE( tag ) );\n\treturn( writeNumeric( stream, ( long ) enumerated ) );\n\t}\n\n/* Write a null value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeNull( INOUT STREAM *stream, IN_TAG const int tag )\n\t{\n\tBYTE buffer[ 8 + 8 ];\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\tbuffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t  BER_NULL : intToByte( MAKE_CTAG_PRIMITIVE( tag ) );\n\tbuffer[ 1 ] = 0;\n\treturn( swrite( stream, buffer, 2 ) );\n\t}\n\n/* Write a boolean value */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBoolean( INOUT STREAM *stream, const BOOLEAN boolean, \n\t\t\t\t  IN_TAG const int tag )\n\t{\n\tBYTE buffer[ 8 + 8 ];\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( boolean == TRUE || boolean == FALSE );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\tbuffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t  BER_BOOLEAN : intToByte( MAKE_CTAG_PRIMITIVE( tag ) );\n\tbuffer[ 1 ] = 1;\n\tbuffer[ 2 ] = boolean ? 0xFF : 0;\n\treturn( swrite( stream, buffer, 3 ) );\n\t}\n\n/* Write an octet string */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeOctetString( INOUT STREAM *stream, \n\t\t\t\t\t  IN_BUFFER( length ) const BYTE *string, \n\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( string, length ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( length ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_OCTETSTRING : MAKE_CTAG_PRIMITIVE( tag ) );\n\twriteLength( stream, length );\n\treturn( swrite( stream, string, length ) );\n\t}\n\n/* Write a character string.  This handles any of the myriad ASN.1 character\n   string types.  The handling of the tag works somewhat differently here to\n   the usual manner in that since the function is polymorphic, the tag\n   defines the character string type and is always used (there's no\n   DEFAULT_TAG like the other functions use) */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeCharacterString( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_BUFFER( length ) const void *string, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t\t  IN_TAG_ENCODED const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( string, length ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( length ) );\n\tREQUIRES_S( ( tag >= BER_STRING_UTF8 && tag <= BER_STRING_BMP ) || \\\n\t\t\t\t( tag >= MAKE_CTAG_PRIMITIVE( 0 ) && \\\n\t\t\t\t  tag <= MAKE_CTAG_PRIMITIVE( MAX_CTAG_VALUE ) ) );\n\n\twriteTag( stream, tag );\n\twriteLength( stream, length );\n\treturn( swrite( stream, string, length ) );\n\t}\n\n/* Write a bit string */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBitString( INOUT STREAM *stream, IN_INT_Z const int bitString, \n\t\t\t\t\tIN_TAG const int tag )\n\t{\n\tBYTE buffer[ 16 + 8 ];\n#if UINT_MAX > 0xFFFF\n\tconst int maxIterations = 32;\n#else\n\tconst int maxIterations = 16;\n#endif /* 16 vs.32-bit systems */\n\tunsigned int value = 0;\n\tint data = bitString, noBits = 0, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( bitString >= 0 && bitString < INT_MAX );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\t/* ASN.1 bitstrings start at bit 0, so we need to reverse the order of\n\t  the bits before we write them out */\n\tLOOP_MED( i = 0, i < maxIterations, i++ )\n\t\t{\n\t\t/* Update the number of significant bits */\n\t\tif( data > 0 )\n\t\t\tnoBits++;\n\n\t\t/* Reverse the bits */\n\t\tvalue <<= 1;\n\t\tif( data & 1 )\n\t\t\tvalue |= 1;\n\t\tdata >>= 1;\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\n\t/* Write the data as an ASN.1 BITSTRING.  This has the potential to lose\n\t   some bits on 16-bit systems, but the only place where bit strings \n\t   longer than one or two bytes are used is with CMP's bizarre encoding \n\t   of error subcodes that just provide further information above and \n\t   beyond the main error code and text message, and it's unlikely that \n\t   too many people will be running a CMP server on a DOS box */\n\tbuffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \\\n\t\t\t\t  BER_BITSTRING : intToByte( MAKE_CTAG_PRIMITIVE( tag ) );\n\tbuffer[ 1 ] = 1 + intToByte( ( ( noBits + 7 ) >> 3 ) );\n\tbuffer[ 2 ] = intToByte( ~( ( noBits - 1 ) & 7 ) & 7 );\n#if UINT_MAX > 0xFFFF\n\tbuffer[ 3 ] = intToByte( ( value >> 24 ) & 0xFF );\n\tbuffer[ 4 ] = intToByte( ( value >> 16 ) & 0xFF );\n\tbuffer[ 5 ] = intToByte( ( value >> 8 ) & 0xFF );\n\tbuffer[ 6 ] = intToByte( value & 0xFF );\n#else\n\tbuffer[ 3 ] = intToByte( ( value >> 8 ) & 0xFF );\n\tbuffer[ 4 ] = intToByte( value & 0xFF );\n#endif /* 16 vs.32-bit systems */\n\treturn( swrite( stream, buffer, 3 + ( ( noBits + 7 ) >> 3 ) ) );\n\t}\n\n/* Write a canonical UTCTime and GeneralizedTime value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeTime( INOUT STREAM *stream, const time_t timeVal, \n\t\t\t\t\t  IN_TAG const int tag, const BOOLEAN isUTCTime )\n\t{\n\tstruct tm timeInfo, *timeInfoPtr = &timeInfo;\n\tchar buffer[ 20 + 8 ];\n\tconst int length = isUTCTime ? 13 : 15;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\tREQUIRES_S( isUTCTime == TRUE || isUTCTime == FALSE );\n\n\ttimeInfoPtr = gmTime_s( &timeVal, timeInfoPtr );\n\tENSURES_S( timeInfoPtr != NULL && timeInfoPtr->tm_year > 90 );\n\tbuffer[ 0 ] = ( tag != DEFAULT_TAG ) ? \\\n\t\t\t\t\tintToByte( MAKE_CTAG_PRIMITIVE( tag ) ) : \\\n\t\t\t\t  isUTCTime ? BER_TIME_UTC : BER_TIME_GENERALIZED;\n\tbuffer[ 1 ] = intToByte( length );\n\tif( isUTCTime )\n\t\t{\n\t\tsprintf_s( buffer + 2, 16, \"%02d%02d%02d%02d%02d%02dZ\", \n\t\t\t\t   timeInfoPtr->tm_year % 100, timeInfoPtr->tm_mon + 1, \n\t\t\t\t   timeInfoPtr->tm_mday, timeInfoPtr->tm_hour, \n\t\t\t\t   timeInfoPtr->tm_min, timeInfoPtr->tm_sec );\n\t\t}\n\telse\n\t\t{\n\t\tsprintf_s( buffer + 2, 16, \"%04d%02d%02d%02d%02d%02dZ\", \n\t\t\t\t   timeInfoPtr->tm_year + 1900, timeInfoPtr->tm_mon + 1, \n\t\t\t\t   timeInfoPtr->tm_mday, timeInfoPtr->tm_hour, \n\t\t\t\t   timeInfoPtr->tm_min, timeInfoPtr->tm_sec );\n\t\t}\n\treturn( swrite( stream, buffer, length + 2 ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUTCTime( INOUT STREAM *stream, const time_t timeVal, \n\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\treturn( writeTime( stream, timeVal, tag, TRUE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeGeneralizedTime( INOUT STREAM *stream, const time_t timeVal, \n\t\t\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\treturn( writeTime( stream, timeVal, tag, FALSE) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tWrite Routines for Constructed Objects\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the start of an encapsulating SEQUENCE, SET, or generic tagged\n   constructed object.  The difference between writeOctet/BitStringHole() and\n   writeGenericHole() is that the octet/bit-string versions create a normal\n   or context-specific-tagged primitive string while the generic version \n   creates a pure hole with no processing of tags */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeSequence( INOUT STREAM *stream, \n\t\t\t\t   IN_LENGTH_Z const long length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( isIntegerRange( length ) );\n\n\twriteTag( stream, BER_SEQUENCE );\n\treturn( writeLength( stream, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeSet( INOUT STREAM *stream, \n\t\t\t  IN_LENGTH_SHORT_Z const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isShortIntegerRange( length ) );\n\n\twriteTag( stream, BER_SET );\n\treturn( writeLength( stream, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeConstructed( INOUT STREAM *stream, \n\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( length ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_SEQUENCE : MAKE_CTAG( tag ) );\n\treturn( writeLength( stream, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeOctetStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( length ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_OCTETSTRING : MAKE_CTAG_PRIMITIVE( tag ) );\n\treturn( writeLength( stream, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBitStringHole( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int length,\n\t\t\t\t\t\tIN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isShortIntegerRange( length ) );\n\tREQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );\n\n\twriteTag( stream, ( tag == DEFAULT_TAG ) ? \\\n\t\t\t  BER_BITSTRING : MAKE_CTAG_PRIMITIVE( tag ) );\n\twriteLength( stream, length + 1 );\t/* +1 for bit count */\n\treturn( sputc( stream, 0 ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeGenericHole( INOUT STREAM *stream, \n\t\t\t\t\t  IN_LENGTH_Z const long length,\n\t\t\t\t\t  IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( length ) );\n\tREQUIRES_S( tag >= 0 && tag < MAX_TAG_VALUE );\n\n\twriteTag( stream, tag );\n\treturn( writeLength( stream, length ) );\n\t}\n#endif /* USE_INT_ASN1 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/base64.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Base64 Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_BASE64\n\n/* Base64 encode/decode tables from RFC 1113 */\n\n#define BPAD\t\t'='\t\t/* Padding for odd-sized output */\n#define BEOL\t\t0x80\t/* CR or LF */\n#define BEOF\t\t0x81\t/* EOF marker '=' */\n#define BERR\t\t0xFF\t/* Illegal character marker */\n\nstatic const char binToAscii[] = \\\n\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nstatic const BYTE asciiToBin[ 256 ] = { \n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* 00 */\n\tBERR, BERR, BEOL, BERR, BERR, BEOL, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* 10 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* 20 */\n\tBERR, BERR, BERR, 0x3E, BERR, BERR, BERR, 0x3F,\n\t0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,\t/* 30 */\n\t0x3C, 0x3D, BERR, BERR, BERR, BEOF, BERR, BERR,\n\tBERR, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,\t/* 40 */\n\t0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,\n\t0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,\t/* 50 */\n\t0x17, 0x18, 0x19, BERR, BERR, BERR, BERR, BERR,\n\tBERR, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,\t/* 60 */\n\t0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,\n\t0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,\t/* 70 */\n\t0x31, 0x32, 0x33, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* 80 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* 90 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* A0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* B0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* C0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* D0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* E0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR,\t/* F0 */\n\tBERR, BERR, BERR, BERR, BERR, BERR, BERR, BERR\n\t};\n\n/* The size of lines for base64-encoded data.  This is only used for \n   encoding, for decoding we adjust to whatever size the sender has used, \n   however we require at least some minimum line size as well as a maximum \n   line size when we check for the validity of base64-encoded data */\n\n#define BASE64_LINESIZE\t\t64\n#define BASE64_MIN_LINESIZE\t56\n#define BASE64_MAX_LINESIZE\t128\n\n/* base64 data can be preceded by all manner of additional header lines, \n   blank lines, PEM type-and-value pairs, and so on, the following is the\n   maximum number of lines that we'll accept before declaring an error */\n\n#define MAX_HEADER_LINES\t30\n\n/* The size of the buffer for reading a line of text */\n\n#define LINEBUFFER_SIZE\t\t512\n\n/* Basic single-character en/decode functions.  We mask the value to 6 or 8 \n   bits both as a range check and to avoid generating negative array offsets \n   if the sign bit is set, since the strings are passed as 'char *'s */\n\n#define encode( data )\tbinToAscii[ ( data ) & 0x3F ]\n#define decode( data )\tasciiToBin[ ( data ) & 0xFF ]\n\n/* The headers and trailers used for base64-encoded certificate objects.  \n   These are used for both en- and de-coding, thus the presence of \n   apparently redundant entries such as the duplicated \"-----BEGIN NEW \n   CERTIFICATE REQUEST-----\" */\n\ntypedef struct {\n\tconst CRYPT_CERTTYPE_TYPE type;\n\tBUFFER_FIXED( headerLen ) \\\n\tconst char *header;\n\tconst int headerLen;\n\tBUFFER_FIXED( trailerLen ) \\\n\tconst char *trailer;\n\tconst int trailerLen;\n\t} HEADER_INFO;\nstatic const HEADER_INFO headerInfo[] = {\n\t{ CRYPT_CERTTYPE_CERTIFICATE,\n\t  \"-----BEGIN CERTIFICATE-----\" EOL, 27 + EOL_LEN,\n\t  \"-----END CERTIFICATE-----\" EOL, 25 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_CERTIFICATE,\t/* Alternative form */\n\t  \"-----BEGIN X509 CERTIFICATE-----\" EOL, 32 + EOL_LEN,\n\t  \"-----END X509 CERTIFICATE-----\" EOL, 30 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_ATTRIBUTE_CERT,\n\t  \"-----BEGIN ATTRIBUTE CERTIFICATE-----\" EOL, 37 + EOL_LEN,\n\t  \"-----END ATTRIBUTE CERTIFICATE-----\" EOL, 35 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_CERTCHAIN,\n\t  \"-----BEGIN CERTIFICATE CHAIN-----\" EOL, 33 + EOL_LEN,\n\t  \"-----END CERTIFICATE CHAIN-----\" EOL, 31 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_CERTCHAIN,\t\t/* Alternative form */\n\t  \"-----BEGIN PKCS7-----\" EOL, 21 + EOL_LEN,\n\t  \"-----END PKCS7-----\" EOL, 29 + EOL_LEN },\n#ifdef USE_CERTREQ\n\t{ CRYPT_CERTTYPE_CERTREQUEST,\n\t  \"-----BEGIN NEW CERTIFICATE REQUEST-----\" EOL, 39 + EOL_LEN,\n\t  \"-----END NEW CERTIFICATE REQUEST-----\" EOL, 37 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_CERTREQUEST,\t/* Alternative form */\n\t  \"-----BEGIN CERTIFICATE REQUEST-----\" EOL, 35 + EOL_LEN,\n\t  \"-----END CERTIFICATE REQUEST-----\" EOL, 33 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_REQUEST_CERT,\t/* See note above */\n\t  \"-----BEGIN NEW CERTIFICATE REQUEST-----\" EOL, 39 + EOL_LEN,\n\t  \"-----END NEW CERTIFICATE REQUEST-----\" EOL, 37 + EOL_LEN },\n#endif /* USE_CERTREQ */\n#ifdef USE_CERTREV\n\t{ CRYPT_CERTTYPE_CRL,\n\t  \"-----BEGIN CERTIFICATE REVOCATION LIST-----\"  EOL, 43 + EOL_LEN,\n\t  \"-----END CERTIFICATE REVOCATION LIST-----\" EOL, 41 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_CRL,\t\t\t/* Alternative form */\n\t  \"-----BEGIN X509 CRL-----\"  EOL, 24 + EOL_LEN,\n\t  \"-----END X509 CRL-----\" EOL, 22 + EOL_LEN },\n#endif /* USE_CERTREV */\n\t{ CRYPT_CERTTYPE_NONE,\t\t\t/* Universal catch-all */\n\t  \"-----BEGIN CERTIFICATE OBJECT-----\"  EOL, 34 + EOL_LEN,\n\t  \"-----END CERTIFICATE OBJECT-----\" EOL, 32 + EOL_LEN },\n\t{ CRYPT_CERTTYPE_NONE,\t\t\t/* Universal catch-all */\n\t  \"-----BEGIN CERTIFICATE OBJECT-----\"  EOL, 34 + EOL_LEN,\n\t  \"-----END CERTIFICATE OBJECT-----\" EOL, 32 + EOL_LEN }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDecode Format-checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check for raw base64 data.  There isn't a 100% reliable check that we can \n   apply for this but if the first BASE64_MIN_LINESIZE characters are all \n   valid base64 data and the first characters match the encoded form of data \n   handled by cryptlib then it's reasonably certain that it's base64 data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkBase64( INOUT STREAM *stream, const BOOLEAN isPEM )\n\t{\n\tBYTE buffer[ BASE64_MAX_LINESIZE + 8 ];\n\tBYTE decodeBuffer[ BASE64_MAX_LINESIZE + 8 ];\n\tint decodedLen, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isPEM == TRUE || isPEM == FALSE );\n\n\t/* Make sure that there's enough data present to perform a reliable\n\t   check */\n\tstatus = sread( stream, buffer, BASE64_MIN_LINESIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that the content is some form of encoded key or certificate \n\t   data. For certificate data that begins with 30 8x the corresponding \n\t   base64 values are MI...; for an SSH public key that begins 00 00 it's \n\t   AA...; for a PGP public key that begins 99 0x it's mQ... \n\n\t   Unfortunately in the case of MIME-encoded data with a MIME header, \n\t   the header is likely to begin with \"MIME-Version\", which happens to \n\t   match the base64-encoded form of 30 8x = \"MI\", so this quick-reject \n\t   filter won't catch this one particular case, however it'll be caught\n\t   by the next check because '-' and the ':' after the MIME-Version \n\t   aren't valid base64 charactes */\n\tif( memcmp( buffer, \"MI\", 2 ) && \\\n\t\tmemcmp( buffer, \"AA\", 2 ) && \\\n\t\tmemcmp( buffer, \"mQ\", 2 ) )\n\t\treturn( FALSE );\n\n\t/* Check that we have at least one minimal-length line of valid base64-\n\t   encoded data */\n\tstatus = base64decode( decodeBuffer, BASE64_MAX_LINESIZE, &decodedLen,\n\t\t\t\t\t\t   buffer, BASE64_MIN_LINESIZE, CRYPT_CERTFORMAT_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* If it's supposed to be PEM data, check that it's delimited by \n\t   linebreaks, or at least that there's a linebreak visible before \n\t   encountering BASE64_MAX_LINESIZE characters */\n\tif( isPEM )\n\t\t{\n\t\tBOOLEAN hasLineBreak = FALSE;\n\t\tint i, LOOP_ITERATOR;\n\n\t\tstatus = sread( stream, buffer, \n\t\t\t\t\t\t( BASE64_MAX_LINESIZE - BASE64_MIN_LINESIZE ) + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tLOOP_LARGE( i = 0, i < ( BASE64_MAX_LINESIZE - \\\n\t\t\t\t\t\t\t\t BASE64_MIN_LINESIZE ) + 1, i++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( decode( buffer[ i ] ) );\n\t\t\tif( ch == BEOL || ch == BEOF || ch == BERR )\n\t\t\t\t{\n\t\t\t\thasLineBreak = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tif( !hasLineBreak )\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check for PEM-encapsulated data.  All that we need to look for is the\n   '-----..' header, which is fairly simple although we also need to handle\n   SSH's mutant '---- ...' variant (4 dashes and a space) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkPEMHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *headerLength )\n\t{\n\tBOOLEAN isSSH = FALSE, isPGP = FALSE;\n\tchar buffer[ LINEBUFFER_SIZE + 8 ], *bufPtr = buffer;\n\tint length, position DUMMY_INIT, lineCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( headerLength, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*headerLength = 0;\n\n\t/* Check for the initial 5 dashes and 'BEGIN ' (unless we're SSH, in\n\t   which case we use 4 dashes, a space, and 'BEGIN ') */\n\tstatus = readTextLine( ( READCHAR_FUNCTION ) sgetc, stream, \n\t\t\t\t\t\t   buffer, LINEBUFFER_SIZE, &length, NULL, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < 5 + 6 + 5 + 5 )\n\t\t{\n\t\t/* We need room for at least the shortest possible string, \n\t\t   '-----' (5) + 'BEGIN ' (6) + 'PKCS7' (5) + '-----' (5) */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( memcmp( bufPtr, \"-----BEGIN \", 11 ) &&\t/* PEM/PGP form */\n\t\tmemcmp( bufPtr, \"---- BEGIN \", 11 ) )\t/* SSH form */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tbufPtr += 11;\n\tlength -= 11;\n\n\t/* Skip the object name.  We know that we have enough data present for \n\t   the compare because we've just checked it above */\n\tif( !strCompare( bufPtr, \"SSH2 \", 5 ) )\n\t\tisSSH = TRUE;\n\telse\n\t\t{\n\t\tif( !strCompare( bufPtr, \"PGP \", 4 ) )\n\t\t\tisPGP = TRUE;\n\t\t}\n\tLOOP_EXT_CHECKINC( length >= 4, length--, LINEBUFFER_SIZE + 1 )\n\t\t{\n\t\tif( *bufPtr == '-' )\n\t\t\tbreak;\n\t\tbufPtr++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( length != 5 && length != 4 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Check the the trailing 5 (4 for SSH) dashes */\n\tif( strCompare( bufPtr, \"-----\", length ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If it's not SSH or PGP data, we're done */\n\tif( !isSSH && !isPGP )\n\t\t{\n\t\t*headerLength = stell( stream );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* At this point SSH and PGP can continue with an arbitrary number of\n\t   type : value pairs that we have to strip before we get to the\n\t   payload.  SSH runs the header straight into the body so the only way \n\t   to tell whether we've hit the body is to check for the absence of the \n\t   ':' separator, while PGP uses a conventional header format with a \n\t   blank line as the delimiter so all that we have to do is look for a \n\t   zero-length line */\n\tLOOP_MED( lineCount = 0, lineCount < MAX_HEADER_LINES, lineCount++ )\n\t\t{\n\t\tposition = stell( stream );\n\t\tstatus = readTextLine( ( READCHAR_FUNCTION ) sgetc, stream, \n\t\t\t\t\t\t\t   buffer, LINEBUFFER_SIZE, &length, NULL, \n\t\t\t\t\t\t\t   FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( isSSH && strFindCh( buffer, length, ':' ) < 0 )\n\t\t\tbreak;\n\t\tif( isPGP && length <= 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( lineCount >= MAX_HEADER_LINES )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( isSSH )\n\t\t{\n\t\t/* Return to the point before the line without the ':' */\n\t\tsseek( stream, position );\n\t\t}\n\t*headerLength = stell( stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Look for the EOL marker at the end of a line of text.  There's one\n   problematic special case here in which, if the encoding has produced\n   bricktext, the end of the data will coincide with the EOL.  For\n   CRYPT_CERTFORMAT_TEXT_CERTIFICATE this will give us '-----END...' (or\n   SSH's mutant variant '---- END...') on the next line which is easy to \n   check for, but for CRYPT_ICERTFORMAT_SMIME_CERTIFICATE what we end up \n   with depends on the calling code.  \n   \n   It could either truncate immediately at the end of the data (which it \n   isn't supposed to) so we get '\\0', it could truncate after the EOL (so \n   we get EOL + '\\0'), it could continue with a futher content type after a \n   blank line (so we get EOL + EOL), or it could truncate without the '\\0' \n   so we get garbage, which is the caller's problem.  \n   \n   Because of this we look for all of these situations and, if any are \n   found, return an OK_SPECIAL EOL indicator */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int checkEOL( IN_BUFFER( srcLen ) const BYTE *src, \n\t\t\t\t\t IN_DATALENGTH const int srcLen,\n\t\t\t\t\t OUT_DATALENGTH_Z int *eolSize,\n\t\t\t\t\t IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE format )\n\t{\n\tint srcIndex = 0;\n\n\tassert( isReadPtrDynamic( src, srcLen ) );\n\tassert( isWritePtr( eolSize, sizeof( int ) ) );\n\n\tREQUIRES( srcLen > 0 && srcLen < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRange( format, CRYPT_CERTFORMAT ) );\n\n\t/* Clear return value */\n\t*eolSize = 0;\n\n\t/* Check for a '\\0' at the end of the data */\n\tif( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE && src[ 0 ] == '\\0' )\n\t\treturn( OK_SPECIAL );\t/* We're at EOF, not just EOL */\n\n\t/* Check for EOL */\n\tif( *src == '\\n' )\n\t\tsrcIndex++;\n\telse\n\t\t{\n\t\tif( *src == '\\r' )\n\t\t\t{\n\t\t\tsrcIndex++;\n\n\t\t\t/* Some broken implementations emit two CRs before the LF.\n\t\t\t   Stripping these extra CRs clashes with other broken\n\t\t\t   implementations that emit only CRs, which means that we'll\n\t\t\t   be stripping the EOT blank line in MIME encapsulation,\n\t\t\t   however the two-CR bug (usually from older versions of\n\t\t\t   Netscape) appears to be more prevalent than the CR-only\n\t\t\t   bug (old Mac software) */\n\t\t\tif( ( srcIndex < srcLen ) && src[ srcIndex ] == '\\r' )\n\t\t\t\tsrcIndex++;\n\t\t\tif( ( srcIndex < srcLen ) && src[ srcIndex ] == '\\n' )\n\t\t\t\tsrcIndex++;\n\t\t\t}\n\t\t}\n\tif( srcIndex >= srcLen )\n\t\t{\n\t\t/* We're at EOF, not just EOL */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* Check for '\\0' or EOL (S/MIME), '----END...' (PEM), or\n\t   '---- END' (SSH) after EOL */\n\tif( format == CRYPT_ICERTFORMAT_SMIME_CERTIFICATE )\n\t\t{\n\t\tif( src[ srcIndex ] == '\\0' || src[ srcIndex ] == '\\n' || \\\n\t\t\tsrc[ srcIndex ] == '\\r' )\n\t\t\t{\n\t\t\t/* We're at EOF, not just EOL */\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\t}\n\tif( format == CRYPT_CERTFORMAT_TEXT_CERTIFICATE && \\\n\t\tsrcIndex + 9 <= srcLen && \\\n\t\tsrc[ srcIndex ] == '-' )\n\t\t{\n\t\tif( !strCompare( src + srcIndex, \"-----END \", 9 ) )\n\t\t\treturn( OK_SPECIAL );\t/* PEM EOF */\n\t\tif( !strCompare( src + srcIndex, \"---- END \", 9 ) )\n\t\t\treturn( OK_SPECIAL );\t/* SSH EOF */\n\t\t}\n\n\t/* If we were expecting an EOL but didn't find one then there's a \n\t   problem with the data */\n\tif( srcIndex <= 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\tENSURES( srcIndex > 0 && srcIndex < srcLen );\n\t*eolSize = srcIndex;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a data item has a header that identifies it as some form of\n   encoded object and return the start position of the encoded data.  For\n   S/MIME certificate data this can in theory get quite complex because\n   there are many possible variations in the headers.  \n   \n   Some early S/MIME agents used a content type of \"application/x-pkcs7-mime\",\n   \"application/x-pkcs7-signature\", and \"application/x-pkcs10\", while newer\n   ones use the same without the \"x-\" at the start.  In addition Netscape\n   have their own MIME data types for certificates, \"application/x-x509-\"\n   \"{user-cert|ca-cert|email-cert}, and this tradition is perpetuated by the\n   mass of further types in the neverending stream of RFCs that PKIX churns \n   out.\n   \n   There are a whole pile of other possible headers as well, none of them \n   terribly relevant for our purposes, so all that we check for is the base64 \n   indicator */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint base64checkHeader( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t   IN_DATALENGTH_MIN( MIN_CERTSIZE ) \\\n\t\t\t\t\t\t\tconst int dataLength,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tCRYPT_CERTFORMAT_TYPE *format,\n\t\t\t\t\t   OUT_DATALENGTH_Z int *startPos )\n\t{\n\tSTREAM stream;\n\tBOOLEAN seenTransferEncoding = FALSE, isBinaryEncoding = FALSE;\n\tBOOLEAN seenDash = FALSE, isBase64;\n\tint position DUMMY_INIT, lineCount, length, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( format, sizeof( CRYPT_CERTFORMAT_TYPE ) ) );\n\tassert( isWritePtr( startPos, sizeof( int ) ) );\n\n\tREQUIRES( dataLength >= MIN_CERTSIZE && dataLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*format = CRYPT_CERTFORMAT_NONE;\n\t*startPos = 0;\n\n\tsMemConnect( &stream, data, dataLength );\n\n\t/* Perform a quick check to weed out unencoded certificate data, which \n\t   is usually the case.  Certificates and related objects are always an \n\t   ASN.1 SEQUENCE so if we find data that begins with this value then we\n\t   perform the check for a certificate object */\n\tif( sPeek( &stream ) == BER_SEQUENCE )\n\t\t{\n\t\t/* For very large objects (which can only be CRLs) we can get an \n\t\t   overflow error trying to read a short length so if the length is \n\t\t   suspiciously long we allow a long length.  We don't do this \n\t\t   unconditionally in order to reduce potential false positives */\n\t\tif( dataLength < MAX_INTLENGTH_SHORT )\n\t\t\tstatus = readSequenceI( &stream, NULL );\n\t\telse\n\t\t\tstatus = readLongSequence( &stream, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tsClearError( &stream );\n\t\tsseek( &stream, 0 );\n\t\t}\n\n\t/* Sometimes the object can be preceded by a few blank lines, which we\n\t   ignore */\n\tLOOP_MED( ( length = 0, lineCount = 0 ), \n\t\t\t  length <= 0 && lineCount < MAX_HEADER_LINES, lineCount++ )\n\t\t{\n\t\tchar buffer[ LINEBUFFER_SIZE + 8 ];\n\n\t\tposition = stell( &stream );\n\t\tstatus = readTextLine( ( READCHAR_FUNCTION ) sgetc, &stream, \n\t\t\t\t\t\t\t   buffer, LINEBUFFER_SIZE, &length, NULL, \n\t\t\t\t\t\t\t   FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( buffer[ 0 ] == '-' )\n\t\t\tseenDash = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( lineCount >= MAX_HEADER_LINES )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tsseek( &stream, position );\n\n\t/* If the data starts with a dash check for PEM header encapsulation \n\t   followed by a base64-encoded body */\n\tif( seenDash )\n\t\t{\n\t\tstatus = checkPEMHeader( &stream, &position );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( !checkBase64( &stream, TRUE ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\t*format = CRYPT_CERTFORMAT_TEXT_CERTIFICATE;\n\t\t*startPos = position;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Check for non-encapsulated base64 data */\n\tif( checkBase64( &stream, FALSE ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\t*format = CRYPT_CERTFORMAT_TEXT_CERTIFICATE;\n\t\t*startPos = position;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tsseek( &stream, position );\n\n\t/* It doesn't look like base64 encoded data, check for an S/MIME header */\n\tLOOP_MED( ( length = 1, lineCount = 0 ),\n\t\t\t  length > 0 && lineCount < MAX_HEADER_LINES, lineCount++ )\n\t\t{\n\t\tchar buffer[ LINEBUFFER_SIZE + 8 ];\n\n\t\tstatus = readTextLine( ( READCHAR_FUNCTION ) sgetc, &stream, \n\t\t\t\t\t\t\t   buffer, LINEBUFFER_SIZE, &length, NULL, \n\t\t\t\t\t\t\t   TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( !seenTransferEncoding && length >= ( 26 + 1 + 6 ) && \\\n\t\t\t!strCompare( buffer, \"Content-Transfer-Encoding:\", 26 ) )\n\t\t\t{\n\t\t\tint bufPos = strSkipWhitespace( buffer + 26, length - 26 );\n\n\t\t\t/* Check for a valid content encoding type.  The first part of\n\t\t\t   the check verifies that there's a space present, which is a \n\t\t\t   bit of an odd check because the RFCs that cover this (2045, \n\t\t\t   2822) specify the encoding as \"'Content-Transfer-Encoding:' \n\t\t\t   mechanism\" with no space between the colon and the mechanism \n\t\t\t   string, however all known implementations add a space so we\n\t\t\t   check for this.  \n\t\t\t   \n\t\t\t   The second part of the check verifies that there's enough \n\t\t\t   data left after the \"Content-Transfer-Encoding:\" and any\n\t\t\t   skipped whitespace for the encoding type:\n\n\t\t\t\t\t\t\t\t\t\t  26  bufPos  min = 6\n\t\t\t\t\t\t\t\t\t\t   |--->|----->\n\t\t\t\t+--------------------------+----+---------\n\t\t\t\t|Content-Transfer-Encoding:|\t|xxxxxx...\n\t\t\t\t+--------------------------+----+--------- */\n\t\t\tif( bufPos < 1 || 26 + bufPos + 6 > length )\n\t\t\t\tcontinue;\n\t\t\tbufPos += 26;\t/* Skip \"Content-Transfer-Encoding:\" */\n\t\t\tif( !strCompare( buffer + bufPos, \"base64\", 6 ) )\n\t\t\t\tseenTransferEncoding = TRUE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !strCompare( buffer + bufPos, \"binary\", 6 ) )\n\t\t\t\t\tseenTransferEncoding = isBinaryEncoding = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( lineCount >= MAX_HEADER_LINES || !seenTransferEncoding )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tposition = stell( &stream );\n\n\t/* Make sure that the content is some form of encoded certificate using\n\t   the same check as the one that we used earlier */\n\tif( isBinaryEncoding )\n\t\t{\n\t\t/* See the comment earlier in this function for the read strategy \n\t\t   used here */\n\t\tif( dataLength < MAX_INTLENGTH_SHORT )\n\t\t\tstatus = readSequenceI( &stream, NULL );\n\t\telse\n\t\t\tstatus = readLongSequence( &stream, NULL );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t*startPos = position;\n\t\t*format = CRYPT_CERTFORMAT_CERTIFICATE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tisBase64 = checkBase64( &stream, FALSE );\n\tsMemDisconnect( &stream );\n\tif( !isBase64 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*startPos = position;\n\t*format = CRYPT_ICERTFORMAT_SMIME_CERTIFICATE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBase64 Decoding Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Decode a base64-encoded binary object.  This has to resort to a somewhat\n   unusual decoding strategy because of the fact that some broken \n   implementations don't split lines across base64-encoded block boundaries,\n   so that part of a base64-encoded block can start on one line but continue \n   on the next.  To deal with this, we shift the decoded data into an \n   accumulator and write out its contents once it's absorbed a full block.  \n   This means that we can skip intervening EOL characters without needing to \n   have a full block on each line */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeAccumulator( INOUT STREAM *stream, \n\t\t\t\t\t\t\t const unsigned long accumulator,\n\t\t\t\t\t\t\t IN_RANGE( 2, 4 ) const int byteCount )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( byteCount >= 2 && byteCount <= 4 );\n\n\tif( byteCount == 4 )\n\t\t{\n\t\t/* A full block of four bytes decoded to three */\n\t\tsputc( stream, intToByte( accumulator >> 16 ) );\n\t\tsputc( stream, intToByte( accumulator >> 8 ) );\n\t\treturn( sputc( stream, intToByte( accumulator ) ) );\n\t\t}\n\tif( byteCount == 3 )\n\t\t{\n\t\t/* Three bytes decoded to two */\n\t\tsputc( stream, intToByte( accumulator >> 10 ) );\n\t\treturn( sputc( stream, intToByte( accumulator >> 2 ) ) );\n\t\t}\n\t/* Two bytes decoded to one */\n\treturn( sputc( stream, intToByte( accumulator >> 4 ) ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint base64decode( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int destMaxLen, \n\t\t\t\t  OUT_DATALENGTH_Z int *destLen,\n\t\t\t\t  IN_BUFFER( srcLen ) const BYTE *src, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int srcLen, \n\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE format )\n\t{\n\tSTREAM stream;\n\tunsigned long accumulator = 0;\n\tint srcIndex, byteCount = 0, status DUMMY_INIT, LOOP_ITERATOR;\n\n\tassert( destMaxLen > 10 && isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( srcLen >= 10 && isReadPtrDynamic( src, srcLen ) );\n\n\tREQUIRES( destMaxLen > 10 && destMaxLen < MAX_BUFFER_SIZE );\n\tREQUIRES( srcLen >= 10 && srcLen < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( format, CRYPT_CERTFORMAT ) );\n\n\t/* Clear return values */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\n\tsMemOpen( &stream, dest, destMaxLen );\n\n\t/* Decode the encoded object.  Since we're processing arbitrary-sized \n\t   input we can't use the usual FAILSAFE_ITERATIONS_MAX to bound the \n\t   loop because the input could be larger than this so we use \n\t   MAX_BUFFER_SIZE instead */\n\tLOOP_EXT( srcIndex = 0,\n\t\t\t  srcIndex < srcLen && srcIndex < MAX_BUFFER_SIZE,\n\t\t\t  srcIndex++, MAX_BUFFER_SIZE )\n\t\t{\n\t\tconst unsigned int value = byteToInt( decode( src[ srcIndex ] ) );\n\n\t\t/* Process special-case characters */\n\t\tif( value == BERR )\n\t\t\t{\n\t\t\t/* It's an invalid value */\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tif( value == BEOL )\n\t\t\t{\n\t\t\tint eolDataSize;\n\n\t\t\t/* If it's fixed-format data (so a pure base64 string) then \n\t\t\t   there can't be an EOL present */\n\t\t\tif( format == CRYPT_CERTFORMAT_NONE )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\n\t\t\t/* It's  CR or LF, skip it */\n\t\t\tstatus = checkEOL( src + srcIndex, srcLen - srcIndex, \n\t\t\t\t\t\t\t   &eolDataSize, format );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If we get an OK_SPECIAL status then it means that we've \n\t\t\t\t   reached the EOF */\n\t\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t\tbreak;\n\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tsrcIndex += eolDataSize - 1;\t/* Loop increments srcIndex */\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( value == BEOF )\n\t\t\t{\n\t\t\t/* It's a '=' padding character, we've reached the end of the \n\t\t\t   encoded data */\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* We've got another six bits of valid data, shift them into the \n\t\t   accumulator */\n\t\taccumulator = ( accumulator << 6 ) | value;\n\t\tbyteCount++;\n\n\t\t/* If we've filled the accumulator, write it to the output */\n\t\tif( byteCount >= 4 )\n\t\t\t{\n\t\t\tstatus = writeAccumulator( &stream, accumulator, byteCount );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\t/* Reset the accumulator */\n\t\t\taccumulator = 0;\n\t\t\tbyteCount = 0;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( srcIndex < MAX_BUFFER_SIZE );\n\n\t/* If there's a single byte left then this is an error since it can't be \n\t   decoded into a valid byte as it only represents six bits of data */\n\tif( byteCount == 1 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Write any leftover bytes in the accumulator */\n\tif( byteCount > 0 )\n\t\t{\n\t\tstatus = writeAccumulator( &stream, accumulator, byteCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t*destLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Calculate the size of a quantity of data once it's en/decoded */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint base64decodeLen( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t IN_DATALENGTH_MIN( 10 ) const int dataLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *decodedLength )\n\t{\n\tSTREAM stream;\n\tint length = 0, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( decodedLength, sizeof( int ) ) );\n\n\tREQUIRES( dataLength >= 10 && dataLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*decodedLength = 0;\n\n\t/* Skip ahead until we find the end of the decodable data.  This ignores \n\t   base64 errors on the input stream since at this point all that we're \n\t   interested in is how much we can decode from it and not whether it's \n\t   valid or not.\n\n\t   Since we're processing arbitrary-sized input we can't use the usual\n\t   FAILSAFE_ITERATIONS_MAX to bound the loop because the input could be\n\t   larger than this so we use MAX_BUFFER_SIZE instead */\n\tsMemConnect( &stream, data, dataLength );\n\tLOOP_EXT( i = 0, i < dataLength, i++, MAX_BUFFER_SIZE + 1 )\n\t\t{\n\t\tint ch, status;\n\n\t\tstatus = ch = sgetc( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( ch == BPAD )\n\t\t\tbreak;\n\t\tif( ch == '\\r' || ch == '\\n' )\n\t\t\t{\n\t\t\t/* Don't try and decode out-of-band data */\n\t\t\tcontinue;\n\t\t\t}\n\t\tch = byteToInt( decode( ch ) );\n\t\tif( ch == BERR || ch == BEOF )\n\t\t\tbreak;\n\t\tlength++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\tstatic_assert( MAX_BUFFER_SIZE < MAX_INTLENGTH / 3,\n\t\t\t\t   \"Integer overflow check for base64\" );\n\tENSURES( length < MAX_INTLENGTH / 3 );\n\n\t/* Return a rough estimate of how much room the decoded data will occupy.\n\t   This overestimates by a few bytes, but a strict value isn't necessary \n\t   since it's only used for memory buffer allocation */\n\t*decodedLength = ( length * 3 ) / 4;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBase64 Encoding Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the header/trailer info for a given export format */\n\nstatic const HEADER_INFO *getHeaderInfo( IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tint index, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRangeOpt( certType, CRYPT_CERTTYPE ) );\n\n\tLOOP_MED( index = 0, headerInfo[ index ].type != CRYPT_CERTTYPE_NONE && \\\n\t\t\t\t\t\t index < FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO ),\n\t\t\t  index++ )\n\t\t{\n\t\tif( headerInfo[ index ].type == certType )\n\t\t\treturn( &headerInfo[ index ] );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( index < FAILSAFE_ARRAYSIZE( headerInfo, HEADER_INFO ) );\n\n\tretIntError_Null();\n\t}\n\n/* Calculate the size of a quantity of data once it's encoded */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint base64encodeLen( IN_DATALENGTH_MIN( 10 ) const int dataLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encodedLength,\n\t\t\t\t\t IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tconst HEADER_INFO *headerInfoPtr;\n\tint length;\n\n\tassert( isWritePtr( encodedLength, sizeof( int ) ) );\n\n\tREQUIRES( dataLength >= 10 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( certType, CRYPT_CERTTYPE ) );\n\t\n\tif( dataLength >= MAX_INTLENGTH / 4 )\n\t\t{\n\t\t/* Catch overflows in the length calculation, this is a can-never-\n\t\t   happen situation so the check is mostly to keep static \n\t\t   analysers happy */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tlength = roundUp( ( dataLength * 4 ) / 3, 4 );\n\tENSURES( length >= 10 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*encodedLength = 0;\n\n\t/* If we're encoding the data as a raw base64 string then we're done */\n\tif( certType == CRYPT_CERTTYPE_NONE )\n\t\t{\n\t\t*encodedLength = length;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Find the header/trailer info for this format */\n\theaderInfoPtr = getHeaderInfo( certType );\n\tENSURES( headerInfoPtr != NULL );\n\n\t/* Calculate the extra length due to EOLs and delimiters */\n\tlength += ( ( roundUp( length, BASE64_LINESIZE ) / BASE64_LINESIZE ) * EOL_LEN );\n\tlength += headerInfoPtr->headerLen + headerInfoPtr->trailerLen;\n\n\tENSURES( length >= 64 && length < MAX_BUFFER_SIZE );\n\n\t*encodedLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encode a block of binary data into the base64 format */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint base64encode( OUT_BUFFER( destMaxLen, *destLen ) char *dest, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int destMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen,\n\t\t\t\t  IN_BUFFER( srcLen ) const void *src, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int srcLen, \n\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tconst HEADER_INFO *headerInfoPtr DUMMY_INIT_PTR;\n\tSTREAM stream;\n\tconst BYTE *srcPtr = src;\n\tint srcIndex, lineByteCount, remainder = srcLen % 3;\n\tint status DUMMY_INIT, LOOP_ITERATOR;\n\n\tassert( destMaxLen > 10 && isWritePtrDynamic( dest, destMaxLen ) );\n\tassert( isWritePtr( destLen, sizeof( int ) ) );\n\tassert( srcLen >= 10 && isReadPtrDynamic( src, srcLen ) );\n\n\tREQUIRES( destMaxLen >= 10 && destMaxLen > srcLen && \\\n\t\t\t  destMaxLen < MAX_BUFFER_SIZE );\n\tREQUIRES( srcLen >= 10 && srcLen < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( certType, CRYPT_CERTTYPE ) );\n\n\t/* Clear return values */\n\tmemset( dest, 0, min( 16, destMaxLen ) );\n\t*destLen = 0;\n\n\tsMemOpen( &stream, dest, destMaxLen );\n\n\t/* If it's an encoded certificate object rather than raw base64 data, \n\t   add the header */\n\tif( certType != CRYPT_CERTTYPE_NONE )\n\t\t{\n\t\theaderInfoPtr = getHeaderInfo( certType );\n\t\tENSURES( headerInfoPtr != NULL );\n\t\tstatus = swrite( &stream, headerInfoPtr->header, \n\t\t\t\t\t\t headerInfoPtr->headerLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Encode the data */\n\tLOOP_EXT( ( srcIndex = 0, lineByteCount = 0 ), srcIndex < srcLen, \n\t\t\t  lineByteCount += 4, MAX_BUFFER_SIZE / 4 )\n\t\t{\n\t\tconst int srcLeft = srcLen - srcIndex;\n\n\t\t/* If we've reached the end of a line of binary data and it's a\n\t\t   certificate object rather than a raw binary blob, add the EOL \n\t\t   marker */\n\t\tif( certType != CRYPT_CERTTYPE_NONE && \\\n\t\t\tlineByteCount >= BASE64_LINESIZE )\n\t\t\t{\n\t\t\tstatus = swrite( &stream, EOL, EOL_LEN );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tlineByteCount = 0;\n\t\t\t}\n\n\t\t/* Encode a block of data from the input buffer */\n\t\tsputc( &stream, encode( ( srcPtr[ srcIndex ] >> 2 ) & 0x3F ) );\n\t\tif( srcLeft < 2 )\n\t\t\t{\n\t\t\tREQUIRES( remainder == 1 );\n\t\t\tstatus = sputc( &stream, encode( ( srcPtr[ srcIndex ] << 4 ) & 0x30 ) );\n\t\t\tbreak;\n\t\t\t}\n\t\tsputc( &stream, encode( ( ( srcPtr[ srcIndex ] << 4 ) & 0x30 ) | \\\n\t\t\t\t\t\t\t\t( ( srcPtr[ srcIndex + 1 ] >> 4 ) & 0x0F ) ) );\n\t\tsrcIndex++;\n\t\tif( srcLeft < 3 )\n\t\t\t{\n\t\t\tREQUIRES( remainder == 2 );\n\t\t\tstatus = sputc( &stream, encode( ( srcPtr[ srcIndex ] << 2 ) & 0x3C ) );\n\t\t\tbreak;\n\t\t\t}\n\t\tsputc( &stream, encode( ( ( srcPtr[ srcIndex ] << 2 ) & 0x3C ) | \\\n\t\t\t\t\t\t\t\t( ( srcPtr[ srcIndex + 1 ] >> 6 ) & 0x03 ) ) );\n\t\tsrcIndex++;\n\t\tstatus = sputc( &stream, encode( srcPtr[ srcIndex++ ] & 0x3F ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* If it's a certificate object, add any required padding and the \n\t   trailer */\n\tif( certType != CRYPT_CERTTYPE_NONE )\n\t\t{\n\t\t/* Add any necessary padding.  For 0 bytes of remainder there's no \n\t\t   padding (the data fits exactly), for 1 byte of remainder there's \n\t\t   2 bytes of padding (\"X==\"), and for 2 bytes of remainder there's \n\t\t   1 byte of padding (\"XX=\") */\n\t\tif( remainder > 0 )\n\t\t\t{\n\t\t\tstatus = sputc( &stream, BPAD );\n\t\t\tif( remainder == 1 )\n\t\t\t\tstatus = sputc( &stream, BPAD );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Add the trailer */\n\t\tswrite( &stream, EOL, EOL_LEN );\n\t\tstatus = swrite( &stream, headerInfoPtr->trailer, \n\t\t\t\t\t\t headerInfoPtr->trailerLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\t*destLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_BASE64 */\n"
  },
  {
    "path": "deps/cl345/enc_dec/base64_id.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t cryptlib PKI UserID En/Decoding Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_BASE64ID\n\n/* The number of bits in each code group of 5 characters */\n\n#define BITS_PER_GROUP\t( 5 * 5 )\t/* 5 chars encoding 5 bits each */\n\n/* En/decode tables for text representations of binary keys.  For the two\n   mask tables, only positions 4...7 are used */\n\nstatic const char codeTable[] = \\\n\t\t\t\"ABCDEFGHJKLMNPQRSTUVWXYZ23456789____\";\t/* No O/0, I/1 */\nstatic const int hiMask[] = \\\n\t\t\t{ 0x00, 0x00, 0x00, 0x00, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00 };\nstatic const int loMask[] = \\\n\t\t\t{ 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0x00, 0x00 };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPKI User ID Encoding Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Adjust the binary form of a PKI user ID so that it can be encoded into a\n   fixed number of text characters.  This function is required because key \n   lookup is performed on the decoded form of the ID that's supplied via PKI \n   user requests, if we used the non-adjusted form for the key lookup then \n   we couldn't locate the stored user info that's indexed from the adjusted \n   form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int adjustPKIUserValue( INOUT_BUFFER( valueMaxLength, *valueLength ) \\\n\t\t\t\t\t\t\t\t\tBYTE *value, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) \\\n\t\t\t\t\t\t\t\t\tconst int valueMaxLength, \n\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( valueMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *valueLength,\n\t\t\t\t\t\t\t   IN_RANGE( 3, 4 ) const int noCodeGroups )\n\t{\n\tassert( isWritePtrDynamic( value, valueMaxLength ) );\n\tassert( isWritePtr( valueLength, sizeof( int ) ) );\n\t\n\tREQUIRES( valueMaxLength >= 32 && valueMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( noCodeGroups == 3 || noCodeGroups == 4 );\n\n\t/* Mask off any bits at the end of the data that can't be encoded using\n\t   the given number of code groups */\n\tif( noCodeGroups == 3 )\n\t\t{\n\t\t/* Length = ( ( roundUp( 3 * BITS_PER_GROUP, 8 ) / 8 ) - 1 )\n\t\t\t\t  = ( 80 / 8 ) - 1\n\t\t\t\t  = 9\n\t\t   Mask = ( 0xFF << ( 8 - ( ( 3 * BITS_PER_GROUP ) % 8 ) ) ) \n\t\t\t\t= ( 0xFF << ( 8 - 3 ) )\n\t\t\t\t= 0xE0 */\n\t\tvalue[ 8 ] &= 0xE0;\n\t\t*valueLength = 9;\n\t\t}\n\telse\n\t\t{\n\t\t/* Length = ( ( roundUp( 4 * BITS_PER_GROUP, 8 ) / 8 ) - 1 )\n\t\t\t\t  = ( 104 / 8 ) - 1\n\t\t\t\t  = 12\n\t\t   Mask = ( 0xFF << ( 8 - ( ( 4 * BITS_PER_GROUP ) % 8 ) ) ) \n\t\t\t\t= ( 0xFF << ( 8 - 4 ) )\n\t\t\t\t= 0xF0 */\n\t\tvalue[ 11 ] &= 0xF0;\n\t\t*valueLength = 12;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Encode a text representation of a binary key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint encodePKIUserValue( OUT_BUFFER( encValMaxLen, *encValLen ) char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int encValMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( encValMaxLen ) int *encValLen,\n\t\t\t\t\t\tIN_BUFFER( valueLen ) const BYTE *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int valueLen, \n\t\t\t\t\t\tIN_RANGE( 3, 4 ) const int noCodeGroups )\n\t{\n\tBYTE valBuf[ 128 + 8 ];\n\tconst int dataBytes = ( roundUp( noCodeGroups * BITS_PER_GROUP, 8 ) / 8 );\n\tint i, byteCount = 0, bitCount = 0, length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( encVal, encValMaxLen ) );\n\tassert( isWritePtr( encValLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( value, dataBytes ) );\n\n\tREQUIRES( encValMaxLen >= 10 && encValMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( valueLen >= 8 && valueLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( noCodeGroups == 3 || noCodeGroups == 4 );\n\tREQUIRES( dataBytes >= 10 && dataBytes < 64 );\n\tREQUIRES( valueLen >= dataBytes - 1 );\n\t\t\t  /* There must be enough input data present to produce the \n\t\t\t     required number of output bytes minus one for the checksum\n\t\t\t\t at the start */\n\n\t/* Clear return values */\n\tmemset( encVal, 0, min( 16, encValMaxLen ) );\n\t*encValLen = 0;\n\n\t/* Copy across the data bytes, leaving a gap at the start for the\n\t   checksum */\n\tREQUIRES( boundsCheck( 1, dataBytes - 1, 128 ) );\n\tmemcpy( valBuf + 1, value, dataBytes - 1 );\n\tstatus = adjustPKIUserValue( valBuf + 1, 128 - 1, &length, \n\t\t\t\t\t\t\t\t noCodeGroups );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength += 1;\n\n\t/* Calculate the Fletcher checksum and prepend it to the data bytes\n\t   This is easier than handling the addition of a non-byte-aligned\n\t   quantity to the end of the data */\n\tvalBuf[ 0 ] = intToByte( checksumData( valBuf + 1, length - 1 ) & 0xFF );\n\n\t/* Encode the binary data as text */\n\tLOOP_MED( ( length = 0, i = 1 ), i <= noCodeGroups * 5, i++ )\n\t\t{\n\t\tint chunkValue;\n\n\t\t/* Extract the next 5-bit chunk and convert it to text form */\n\t\tif( bitCount < 3 )\n\t\t\t{\n\t\t\t/* Everything's present in one byte, shift it down to the LSB */\n\t\t\tchunkValue = ( valBuf[ byteCount ] >> ( 3 - bitCount ) ) & 0x1F;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( bitCount == 3 )\n\t\t\t\t{\n\t\t\t\t/* It's the 5 LSBs */\n\t\t\t\tchunkValue = valBuf[ byteCount ] & 0x1F;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* The data spans two bytes, shift the bits from the high\n\t\t\t\t   byte up and the bits from the low byte down */\n\t\t\t\tchunkValue = ( ( valBuf[ byteCount ] & \\\n\t\t\t\t\t\t\t\t hiMask[ bitCount ] ) << ( bitCount - 3 ) ) | \\\n\t\t\t\t\t\t\t ( ( valBuf[ byteCount + 1 ] & \\\n\t\t\t\t\t\t\t\t loMask[ bitCount ] ) >> ( 11 - bitCount ) );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( chunkValue >= 0 && chunkValue <= 0x20 );\n\t\tencVal[ length++ ] = codeTable[ chunkValue ];\n\t\tif( length < encValMaxLen && ( i % 5 ) == 0 && i < noCodeGroups * 5 )\n\t\t\tencVal[ length++ ] = '-';\n\t\tENSURES( length < encValMaxLen );\n\n\t\t/* Advance by 5 bits */\n\t\tbitCount += 5;\n\t\tif( bitCount >= 8 )\n\t\t\t{\n\t\t\tbitCount -= 8;\n\t\t\tbyteCount++;\n\t\t\t}\n\t\tENSURES( bitCount >= 0 && bitCount < 8 );\n\t\tENSURES( byteCount >= 0 && byteCount < 64 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*encValLen = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKI User ID Decoding Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a text string appears to be an encoded PKI user value */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isPKIUserValue( IN_BUFFER( encValLength ) const char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int encValLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( encVal, encValLength ) );\n\n\tREQUIRES_B( encValLength > 10 && encValLength < MAX_INTLENGTH_SHORT );\n\n\t/* Check whether a user value is of the form XXXXX-XXXXX-XXXXX{-XXXXX}.  \n\t   Although we shouldn't be seeing O/0 or I/1 in the input we don't\n\t   specifically check for these since they could be present as typos.\n\t   In other words we're checking for the presence of an input pattern\n\t   that matches an encoded PKI user value, not for the validity of the\n\t   value itself, which will be checked by decodePKIUserValue() */\n\tif( ( encValLength != ( 3 * 5 ) + 2 ) && \\\n\t\t( encValLength != ( 4 * 5 ) + 3 ) )\n\t\treturn( FALSE );\n\tLOOP_MED_INITCHECK( i = 0, i < encValLength )\n\t\t{\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\t/* Decode each character group.  We know from the length check above\n\t\t   that this won't run off the end of the data, so we don't have to\n\t\t   check the index value */\n\t\tLOOP_SMALL_ALT( j = 0, j < 5, j++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( encVal[ i++ ] );\n\n\t\t\tif( !isAlnum( ch ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tif( i < encValLength && encVal[ i++ ] != '-' )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Decode a text representation of a binary key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint decodePKIUserValue( OUT_BUFFER( valueMaxLen, *valueLen ) BYTE *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int valueMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen,\n\t\t\t\t\t\tIN_BUFFER( encValLength ) const char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int encValLength )\n\t{\n\tBYTE valBuf[ 128 + 8 ];\n\tchar encBuf[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint i, byteCount = 0, bitCount = 0, length = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( value, valueMaxLen ) );\n\tassert( isWritePtr( valueLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( encVal, encValLength ) );\n\n\tREQUIRES( valueMaxLen >= 10 && valueMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( encValLength ) );\n\n\t/* Clear return values */\n\tmemset( value, 0, min( 16, valueMaxLen ) );\n\t*valueLen = 0;\n\n\t/* Make sure that the input has a reasonable length (this should have \n\t   been checked by the caller using isPKIUserValue(), so we throw an\n\t   exception if the check fails).  We return CRYPT_ERROR_BADDATA rather \n\t   than the more obvious CRYPT_ERROR_OVERFLOW since something returned \n\t   from this low a level should be a consistent error code indicating \n\t   that there's a problem with the PKI user value as a whole */\n\tif( encValLength < ( 3 * 5 ) || encValLength > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"PKI user value has invalid length\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\tREQUIRES( isPKIUserValue( encVal, encValLength ) );\n\n\t/* Undo the formatting of the encoded value from XXXXX-XXXXX-XXXXX... \n\t   to XXXXXXXXXXXXXXX... */\n\tLOOP_LARGE_INITCHECK( i = 0, i < encValLength )\n\t\t{\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\tLOOP_SMALL_ALT( j = 0, j < 5, j++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( encVal[ i++ ] );\n\n\t\t\t/* Note that we've just incremented 'i', so the range check is\n\t\t\t   '>' rather than '>=' */\n\t\t\tif( !isAlnum( ch ) || i > encValLength )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tencBuf[ length++ ] = intToByte( toUpper( ch ) );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( i < encValLength && encVal[ i++ ] != '-' )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( ( length % 5 ) != 0 || length > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Decode the text data into binary */\n\tmemset( valBuf, 0, 128 );\n\tLOOP_LARGE( i = 0, i < length, i ++ )\n\t\t{\n\t\tconst int ch = byteToInt( encBuf[ i ] );\n\t\tint chunkValue, LOOP_ITERATOR_ALT;\n\n\t\tLOOP_MED_ALT( chunkValue = 0, chunkValue < 0x20, chunkValue++ )\n\t\t\t{\n\t\t\tif( codeTable[ chunkValue ] == ch )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( chunkValue >= 0x20 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Extract the next 5-bit chunk and convert it to text form */\n\t\tif( bitCount < 3 )\n\t\t\t{\n\t\t\t/* Everything's present in one byte, shift it up into position */\n\t\t\tvalBuf[ byteCount ] |= chunkValue << ( 3 - bitCount );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( bitCount == 3 )\n\t\t\t\t{\n\t\t\t\t/* It's the 5 LSBs */\n\t\t\t\tvalBuf[ byteCount ] |= chunkValue;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* The data spans two bytes, shift the bits from the high\n\t\t\t\t   byte down and the bits from the low byte up */\n\t\t\t\tvalBuf[ byteCount ] |= \\\n\t\t\t\t\t\t\tintToByte( ( chunkValue >> ( bitCount - 3 ) ) & \\\n\t\t\t\t\t\t\t\t\t\t hiMask[ bitCount ] );\n\t\t\t\tvalBuf[ byteCount + 1 ] = \\\n\t\t\t\t\t\t\tintToByte( ( chunkValue << ( 11 - bitCount ) ) & \\\n\t\t\t\t\t\t\t\t\t\t loMask[ bitCount ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Advance by 5 bits */\n\t\tbitCount += 5;\n\t\tif( bitCount >= 8 )\n\t\t\t{\n\t\t\tbitCount -= 8;\n\t\t\tbyteCount++;\n\t\t\t}\n\t\tENSURES( bitCount >= 0 && bitCount < 8 );\n\t\tENSURES( byteCount >= 0 && byteCount < 64 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Calculate the Fletcher checksum and make sure that it matches the\n\t   value at the start of the data bytes */\n\tif( bitCount > 0 )\n\t\tbyteCount++;\t/* More bits in the last partial byte */\n\tif( valBuf[ 0 ] != ( checksumData( valBuf + 1, byteCount - 1 ) & 0xFF ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Return the decoded value to the caller */\n\tENSURES( byteCount >= 2 && byteCount - 1 <= valueMaxLen );\n\tREQUIRES( boundsCheck( 1, byteCount - 1, valueMaxLen ) );\n\tmemcpy( value, valBuf + 1, byteCount - 1 );\n\t*valueLen = byteCount - 1;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_BASE64ID */\n"
  },
  {
    "path": "deps/cl345/enc_dec/misc_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous (Non-ASN.1) Read/Write Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"bn.h\"\n  #include \"misc_rw.h\"\n#else\n  #include \"crypt.h\"\n  #include \"bn/bn.h\"\n  #include \"enc_dec/misc_rw.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read large integer data */\n\ntypedef enum {\n\tLENGTH_NONE,\t\t/* No length type */\n\tLENGTH_16U,\t\t\t/* Unsigned int, 16-bit length */\n\tLENGTH_16U_BITS,\t/* Unsigned int, 16-bit length, length in bits */\n\tLENGTH_32,\t\t\t/* Signed int, 32-bit length */\n\tLENGTH_LAST\t\t\t/* Last possible length type */\n\t} LENGTH_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int readInteger( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t\t\t*integerLength ) void *integer, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) int *integerLength,\n\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength,\n\t\t\t\t\t\tIN_ENUM( LENGTH ) const LENGTH_TYPE lengthType,\n\t\t\t\t\t\tIN_ENUM_OPT( KEYSIZE_CHECK ) \\\n\t\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tint length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( integer == NULL || isWritePtrDynamic( integer, maxLength ) );\n\tassert( isWritePtr( integerLength, sizeof( int ) ) );\n\n\tREQUIRES_S( minLength > 0 && minLength < maxLength && \\\n\t\t\t\tmaxLength <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_S( isEnumRange( lengthType, LENGTH ) );\n\tREQUIRES_S( isEnumRangeOpt( checkType, KEYSIZE_CHECK ) );\n\n\t/* Clear return values */\n\tif( integer != NULL )\n\t\tmemset( integer, 0, min( 16, maxLength ) );\n\t*integerLength = 0;\n\n\t/* Read the length and make sure that it's within range, with a 2-byte \n\t   allowance for extra zero-padding (the exact length will be checked \n\t   later after the padding is stripped) */\n\tif( lengthType == LENGTH_16U || lengthType == LENGTH_16U_BITS )\n\t\tstatus = length = readUint16( stream );\n\telse\n\t\tstatus = length = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( lengthType == LENGTH_16U_BITS )\n\t\tlength = bitsToBytes( length );\n\tif( checkType != KEYSIZE_CHECK_NONE )\n\t\t{\n\t\tREQUIRES( ( checkType == KEYSIZE_CHECK_ECC && \\\n\t\t\t\t\tminLength >= MIN_PKCSIZE_ECCPOINT ) || \\\n\t\t\t\t  ( checkType != KEYSIZE_CHECK_ECC && \\\n\t\t\t\t\tminLength >= MIN_PKCSIZE_THRESHOLD ) );\n\n\t\t/* If the length is below the minimum allowed but still looks at \n\t\t   least vaguely valid, report it as a too-short key rather than a\n\t\t   bad data error */\n\t\tif( checkType == KEYSIZE_CHECK_ECC )\n\t\t\t{\n\t\t\tif( isShortECCKey( length ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( isShortPKCKey( length ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n\t\t}\n\tif( length < minLength || length > maxLength + 2 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t/* If we're reading a signed integer then the sign bit can't be set \n\t   since this would produce a negative value.  This differs from the \n\t   ASN.1 code, where the incorrect setting of the sign bit is so common \n\t   that we always treat integers as unsigned */\n\tif( lengthType == LENGTH_32 && ( sPeek( stream ) & 0x80 ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t/* Skip possible leading-zero padding and repeat the length check once\n\t   the zero-padding has been adjusted */\n\tLOOP_MAX_CHECKINC( length > 0 && sPeek( stream ) == 0, length-- )\n\t\t{\n\t\tstatus = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( checkType != KEYSIZE_CHECK_NONE )\n\t\t{\n\t\t/* Repeat the earlier check on the adjusted value */\n\t\tif( checkType == KEYSIZE_CHECK_ECC )\n\t\t\t{\n\t\t\tif( isShortECCKey( length ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( isShortPKCKey( length ) )\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n\t\t}\n\tif( length < minLength || length > maxLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t/* Read the value */\n\t*integerLength = length;\n\tif( integer == NULL )\n\t\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\treturn( sread( stream, integer, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Read Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read 16- and 32-bit integer values */\n\nRETVAL_RANGE( 0, 0xFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint16( INOUT STREAM *stream )\n\t{\n\tBYTE buffer[ UINT16_SIZE + 8 ];\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sread( stream, buffer, UINT16_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tvalue = ( ( long ) buffer[ 0 ] << 8 ) | buffer[ 1 ];\n\tif( !isIntegerRange( value ) || \\\n\t\tvalue > 0xFFFFL || value >= INT_MAX )\n\t\t{\n\t\t/* On 16-bit systems, INT_MAX may be less than 0xFFFFL */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\treturn( value );\n\t}\n\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint32( INOUT STREAM *stream )\n\t{\n\tBYTE buffer[ UINT32_SIZE + 8 ];\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sread( stream, buffer, UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( buffer[ 0 ] & 0x80 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tvalue = ( ( long ) buffer[ 0 ] << 24 ) | \\\n\t\t\t( ( long ) buffer[ 1 ] << 16 ) | \\\n\t\t\t( ( long ) buffer[ 2 ] << 8 ) | \\\n\t\t\t\t\t   buffer[ 3 ];\n\tif( !isIntegerRange( value ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( value );\n\t}\n\n/* Read 32-bit time values */\n\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readUint32Time( INOUT STREAM *stream, OUT time_t *timeVal )\n\t{\n\tBYTE buffer[ UINT32_SIZE + 8 ];\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( timeVal, sizeof( time_t ) ) );\n\n\t/* Clear return value */\n\t*timeVal = 0;\n\n\tstatus = sread( stream, buffer, UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( buffer[ 0 ] & 0x80 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tvalue = ( ( long ) buffer[ 0 ] << 24 ) | \\\n\t\t\t( ( long ) buffer[ 1 ] << 16 ) | \\\n\t\t\t( ( long ) buffer[ 2 ] << 8 ) | \\\n\t\t\t\t\t   buffer[ 3 ];\n\tif( value < MIN_STORED_TIME_VALUE || value >= MAX_TIME_VALUE )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t*timeVal = ( time_t ) value;\n\treturn( CRYPT_OK );\n\t}\n\n/* Read 64-bit integer values */\n\n#ifdef USE_WEBSOCKETS\n\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint64( INOUT STREAM *stream )\n\t{\n\tBYTE buffer[ ( UINT64_SIZE / 2 ) + 8 ];\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* This is never a 64-bit value but always an overprovisioned int/long, \n\t   so we verify that the top four bytes are zero and then read it as\n\t   a Uint32 */\n\tstatus = sread( stream, buffer, UINT64_SIZE / 2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( memcmp( buffer, \"\\x00\\x00\\x00\\x00\", UINT64_SIZE / 2 ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( readUint32( stream ) );\n\t}\n#endif /* USE_WEBSOCKETS */\n\n/* Read a string preceded by a 32-bit length */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readData32( INOUT STREAM *stream, \n\t\t\t\t\t   OUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t\t   IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataMaxLength ) int *dataLength,\n\t\t\t\t\t   const BOOLEAN includeLengthField,\n\t\t\t\t\t   const BOOLEAN zeroLengthOK )\n\t{\n\tBYTE *dataPtr = data;\n\tconst int headerSize = includeLengthField ? UINT32_SIZE : 0;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( dataMaxLength ) );\n\tREQUIRES_S( includeLengthField == TRUE || includeLengthField == FALSE );\n\tREQUIRES_S( zeroLengthOK == TRUE || zeroLengthOK == FALSE );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\tstatus = length = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\t/* Zero length value */\n\t\tif( !zeroLengthOK )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tif( includeLengthField )\n\t\t\t{\n\t\t\tmemset( data, 0, UINT32_SIZE );\n\t\t\t*dataLength = UINT32_SIZE;\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( !isShortIntegerRangeNZ( length ) )\n\t\t{\n\t\t/* Avoid integer-overflow warning in the following check */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tif( headerSize + length > dataMaxLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tif( includeLengthField )\n\t\t{\n\t\tdataPtr[ 0 ] = intToByte( ( length >> 24 ) & 0xFF );\n\t\tdataPtr[ 1 ] = intToByte( ( length >> 16 ) & 0xFF );\n\t\tdataPtr[ 2 ] = intToByte( ( length >> 8 ) & 0xFF );\n\t\tdataPtr[ 3 ] = intToByte( length & 0xFF );\n\t\t}\n\t*dataLength = headerSize + length;\n\treturn( sread( stream, dataPtr + headerSize, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readString32( INOUT STREAM *stream, \n\t\t\t\t  OUT_BUFFER( stringMaxLength, \\\n\t\t\t\t\t\t\t  *stringLength ) void *string, \n\t\t\t\t  IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( stringMaxLength ) int *stringLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( string, stringMaxLength ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( stringMaxLength ) );\n\n\t/* Read the string, limiting the size to the maximum buffer size */\n\treturn( readData32( stream, string, stringMaxLength, stringLength, \n\t\t\t\t\t\tFALSE, FALSE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readString32Opt( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER( stringMaxLength, \\\n\t\t\t\t\t\t\t\t *stringLength ) void *string, \n\t\t\t\t\t IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\tint *stringLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( string, stringMaxLength ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\n\tREQUIRES_S( isShortIntegerRangeNZ( stringMaxLength ) );\n\n\t/* Read the string, limiting the size to the maximum buffer size, and \n\t   with zero-length strings allowed */\n\treturn( readData32( stream, string, stringMaxLength, stringLength, \n\t\t\t\t\t\tFALSE, TRUE ) );\n\t}\n\n/* Read a raw object preceded by a 32-bit length */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readRawObject32( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER( bufferMaxLength, *bufferLength ) \\\n\t\t\t\t\t\tvoid *buffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( UINT32_SIZE + 1 ) \\\n\t\t\t\t\t\tconst int bufferMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\tint *bufferLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, bufferMaxLength ) );\n\tassert( isWritePtr( bufferLength, sizeof( int ) ) );\n\n\tREQUIRES_S( bufferMaxLength >= UINT32_SIZE + 1 && \\\n\t\t\t\tbufferMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Read the string, limiting the size to the maximum buffer size */\n\treturn( readData32( stream, buffer, bufferMaxLength, bufferLength, \n\t\t\t\t\t\tTRUE, FALSE ) );\n\t}\n\n/* Read a universal type and discard it, used to skip unknown or unwanted\n   types.  Since it's only used to skip short no-op fields, we limit the\n   maximum length to MAX_INTLENGTH_SHORT */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readUniversal( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( lengthType == LENGTH_16U || lengthType == LENGTH_32 );\n\n\t/* Read the length and skip the data */\n\tif( lengthType == LENGTH_16U )\n\t\tstatus = length = readUint16( stream );\n\telse\n\t\tstatus = length = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\treturn( CRYPT_OK );\t\t/* Zero-length data */\n\tif( !isShortIntegerRangeNZ( length ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal16( INOUT STREAM *stream )\n\t{\n\treturn( readUniversal( stream, LENGTH_16U ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal32( INOUT STREAM *stream )\n\t{\n\treturn( readUniversal( stream, LENGTH_32 ) );\n\t}\n\n/* Read (large) integers in various formats */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16U( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t\t*integerLength ) void *integer, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\tIN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t maxLength, LENGTH_16U, KEYSIZE_CHECK_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t\t\t*integerLength ) void *integer, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t maxLength, LENGTH_16U_BITS, KEYSIZE_CHECK_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger32( INOUT STREAM *stream, \n\t\t\t\t   OUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t   *integerLength ) void *integer, \n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLength  ) int *integerLength, \n\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t   IN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t maxLength, LENGTH_32, KEYSIZE_CHECK_NONE ) );\n\t}\n\n/* Special-case large integer read routines that explicitly check for a too-\n   short key and return CRYPT_ERROR_NOSECURE rather than the \n   CRYPT_ERROR_BADDATA that'd otherwise be returned */\n\n#ifdef USE_SSL\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16UChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_BUFFER_OPT( maxLength, *integerLength ) \\\n\t\t\t\t\t\t\t\tvoid *integer, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t   IN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t maxLength, LENGTH_16U, KEYSIZE_CHECK_PKC ) );\n\t}\n#endif /* USE_SSL */\n\n#ifdef USE_SSH\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger32Checked( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_BUFFER_OPT( maxLength, *integerLength ) \\\n\t\t\t\t\t\t\t\tvoid *integer, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength )\n\t{\n\t/* Perform the appropriate length check for the algorithm type.  The\n\t   way that this is currently done is a bit of a nasty hack, but it\n\t   saves having to create a special-case ECC-only function that's only\n\t   used in one place */\n\tif( minLength == MIN_PKCSIZE_ECCPOINT && \\\n\t\tmaxLength == MAX_PKCSIZE_ECCPOINT )\n\t\t{\n\t\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t\t maxLength, LENGTH_32, KEYSIZE_CHECK_ECC ) );\n\t\t}\n\treturn( readInteger( stream, integer, integerLength, minLength,\n\t\t\t\t\t\t maxLength, LENGTH_32, KEYSIZE_CHECK_PKC ) );\n\t}\n#endif /* USE_SSH */\n\n#ifdef USE_PKC\n\n/* Read integers as bignums in various formats */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readBignumInteger( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum,\n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength,\n\t\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange, \n\t\t\t\t\t\t\t  IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType,\n\t\t\t\t\t\t\t  IN_ENUM_OPT( KEYSIZE_CHECK ) \\\n\t\t\t\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( bignum, sizeof( BIGNUM ) ) );\n\tassert( maxRange == NULL || isReadPtr( maxRange, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_S( minLength > 0 && minLength < maxLength && \\\n\t\t\t\tmaxLength <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_S( isEnumRange( lengthType, LENGTH ) );\n\tREQUIRES_S( isEnumRangeOpt( checkType, KEYSIZE_CHECK ) );\n\n\t/* Read the integer data */\n\tstatus = readInteger( stream, buffer, &length, minLength, maxLength, \n\t\t\t\t\t\t  lengthType, checkType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Convert the value to a bignum.  Note that we use the KEYSIZE_CHECK\n\t   parameter for both readInteger() and importBignum(), since the \n\t   former merely checks the byte count while the latter actually parses \n\t   and processes the bignum */\n\tstatus = importBignum( bignum, buffer, length, minLength, maxLength, \n\t\t\t\t\t\t   maxRange, checkType );\n\tif( cryptStatusError( status ) )\n\t\tstatus = sSetError( stream, status );\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\treturn( status );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength,\n\t\t\t\t\t\t\t   maxRange, LENGTH_16U, KEYSIZE_CHECK_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC_BITS const int minBits,\n\t\t\t\t\t\t\t  IN_LENGTH_PKC_BITS const int maxBits,\n\t\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )\n\t{\n\treturn( readBignumInteger( stream, bignum, bitsToBytes( minBits ),\n\t\t\t\t\t\t\t   bitsToBytes( maxBits ), maxRange, \n\t\t\t\t\t\t\t   LENGTH_16U_BITS, KEYSIZE_CHECK_NONE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger32( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t IN_OPT TYPECAST( BIGNUM * ) const void *maxRange )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength, \n\t\t\t\t\t\t\t   maxRange, LENGTH_32, KEYSIZE_CHECK_NONE ) );\n\t}\n\n/* Special-case bignum read routines that explicitly check for a too-short \n   key and return CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA\n   that'd otherwise be returned */\n\n#ifdef USE_SSL\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16UChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength, NULL, \n\t\t\t\t\t\t\t   LENGTH_16U, KEYSIZE_CHECK_PKC ) );\n\t}\n#endif /* USE_SSL */\n\n#ifdef USE_PGP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16UbitsChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\t\t IN_LENGTH_PKC_BITS const int minBits,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_PKC_BITS const int maxBits )\n\t{\n\treturn( readBignumInteger( stream, bignum, bitsToBytes( minBits ),\n\t\t\t\t\t\t\t   bitsToBytes( maxBits ), NULL, \n\t\t\t\t\t\t\t   LENGTH_16U_BITS, KEYSIZE_CHECK_PKC ) );\n\t}\n#endif /* USE_PGP */\n\n#ifdef USE_SSH\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger32Checked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength )\n\t{\n\treturn( readBignumInteger( stream, bignum, minLength, maxLength, \n\t\t\t\t\t\t\t   NULL, LENGTH_32, KEYSIZE_CHECK_PKC ) );\n\t}\n#endif /* USE_SSH */\n#endif /* USE_PKC */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Write Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write 16-, 32- and 64-bit integer values */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint16( INOUT STREAM *stream, \n\t\t\t\t IN_RANGE( 0, 0xFFFF ) const int value )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( value ) && value <= 0xFFFFL );\n\n\tsputc( stream, ( value >> 8 ) & 0xFF );\n\treturn( sputc( stream, value & 0xFF ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint32( INOUT STREAM *stream, IN_INT_Z const long value )\n\t{\n\tBYTE buffer[ UINT32_SIZE + 8 ];\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( value ) );\n\n\tbuffer[ 0 ] = intToByte( ( value >> 24 ) & 0xFF );\n\tbuffer[ 1 ] = intToByte( ( value >> 16 ) & 0xFF );\n\tbuffer[ 2 ] = intToByte( ( value >> 8 ) & 0xFF );\n\tbuffer[ 3 ] = intToByte( value & 0xFF );\n\treturn( swrite( stream, buffer, UINT32_SIZE ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint64( INOUT STREAM *stream, IN_INT_Z const long value )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( isIntegerRange( value ) );\n\n\tswrite( stream, \"\\x00\\x00\\x00\\x00\", UINT64_SIZE / 2 );\n\treturn( writeUint32( stream, value ) );\n\t}\n\n/* Write 32-bit time values */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint32Time( INOUT STREAM *stream, const time_t timeVal )\n\t{\n\tREQUIRES_S( timeVal >= MIN_TIME_VALUE );\n\n\treturn( writeUint32( stream, ( int ) timeVal ) );\n\t}\n\n/* Write a string preceded by a 32-bit length */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeString32( INOUT STREAM *stream, \n\t\t\t\t   IN_BUFFER( stringLength ) const void *string, \n\t\t\t\t   IN_LENGTH_SHORT const int stringLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\tREQUIRES_S( isIntegerRangeNZ( stringLength ) );\n\n\twriteUint32( stream, stringLength );\n\treturn( swrite( stream, string, stringLength ) );\n\t}\n\n/* Write large integers in various formats */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeInteger( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\t\t IN_LENGTH_PKC const int integerLength,\n\t\t\t\t\t\t IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )\n\t{\n\tconst BYTE *intPtr = integer;\n\tint length = integerLength, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( integer, integerLength ) );\n\n\tREQUIRES_S( integerLength > 0 && integerLength <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_S( isEnumRange( lengthType, LENGTH ) );\n\n\t/* Integers may be passed to us from higher-level code with leading \n\t   zeroes as part of the encoding.  Before we write them out we strip\n\t   out any superfluous leading zeroes that may be present */\n\tLOOP_LARGE_CHECKINC( length > 0 && *intPtr == 0, ( length--, intPtr++ ) )\n\t\t{\n\t\t/* In theory this could be a problem since quietly changing the \n\t\t   length of a low-level internal value before writing it will cause \n\t\t   problems with higher-level code that doesn't expect to have the \n\t\t   data length of internal components changed, however in practice it\n\t\t   only occurs with PGP signatures which are just a raw integer\n\t\t   value, so we don't invoke any kind of warning */\n\t\t/* assert( DEBUG_WARN ); */\n\t\t}\n\tENSURES_S( LOOP_BOUND_OK );\n\tENSURES_S( length > 0 );\n\n\tswitch( lengthType )\n\t\t{\n\t\tcase LENGTH_16U:\n\t\t\twriteUint16( stream, length );\n\t\t\tbreak;\n\n\t\tcase LENGTH_16U_BITS:\n\t\t\twriteUint16( stream, bytesToBits( length ) );\n\t\t\tbreak;\n\n\t\tcase LENGTH_32:\n\t\t\t{\n\t\t\tconst int leadingOneBit = ( *intPtr & 0x80 ) ? 1 : 0;\n\n\t\t\twriteUint32( stream, length + leadingOneBit );\n\t\t\tif( leadingOneBit )\n\t\t\t\tsputc( stream, 0 );\t/* MPIs are signed values */\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\treturn( swrite( stream, intPtr, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t IN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\t IN_LENGTH_PKC const int integerLength )\n\t{\n\treturn( writeInteger( stream, integer, integerLength, LENGTH_16U ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\t\t IN_LENGTH_PKC const int integerLength )\n\t{\n\treturn( writeInteger( stream, integer, integerLength, LENGTH_16U_BITS ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger32( INOUT STREAM *stream, \n\t\t\t\t\tIN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\tIN_LENGTH_PKC const int integerLength )\n\t{\n\treturn( writeInteger( stream, integer, integerLength, LENGTH_32 ) );\n\t}\n\n#ifdef USE_PKC\n\n/* Write integers from bignums in various formats */\n\nCHECK_RETVAL_RANGE( UINT32_SIZE, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofBignumInteger32( const void *bignum )\n\t{\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\treturn( UINT32_SIZE + BN_high_bit( ( BIGNUM * ) bignum ) + \\\n\t\t\t\t\t\t  BN_num_bytes( bignum ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeBignumInteger( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   TYPECAST( BIGNUM * ) const void *bignum,\n\t\t\t\t\t\t\t   IN_ENUM( LENGTH ) const LENGTH_TYPE lengthType )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint bnLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( bignum, sizeof( BIGNUM ) ) );\n\n\tREQUIRES_S( isEnumRange( lengthType, LENGTH ) );\n\n\tstatus = exportBignum( buffer, CRYPT_MAX_PKCSIZE, &bnLength, bignum );\n\tENSURES_S( cryptStatusOK( status ) );\n\tENSURES_S( bnLength > 0 && bnLength <= CRYPT_MAX_PKCSIZE );\n\tif( lengthType == LENGTH_16U_BITS )\n\t\t{\n\t\tint bitCount;\n\n\t\t/* We can't call down to writeInteger() from here because we need to \n\t\t   write a precise length in bits rather than a value reconstructed \n\t\t   from the byte count.  This also means that we can't easily \n\t\t   perform the leading-zero truncation that writeInteger() does \n\t\t   without a lot of low-level fiddling that duplicates code in\n\t\t   writeInteger() */\n\t\tstatus = bitCount = BN_num_bits( bignum );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\twriteUint16( stream, bitCount );\n\t\tstatus = swrite( stream, buffer, bnLength );\n\t\t}\n\telse\n\t\tstatus = writeInteger( stream, buffer, bnLength, lengthType );\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\treturn( status );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t\t   TYPECAST( BIGNUM * ) const void *bignum )\n\t{\n\treturn( writeBignumInteger( stream, bignum, LENGTH_16U ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   TYPECAST( BIGNUM * ) const void *bignum )\n\t{\n\treturn( writeBignumInteger( stream, bignum, LENGTH_16U_BITS ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBignumInteger32( INOUT STREAM *stream, \n\t\t\t\t\t\t  TYPECAST( BIGNUM * ) const void *bignum )\n\t{\n\treturn( writeBignumInteger( stream, bignum, LENGTH_32 ) );\n\t}\n#endif /* USE_PKC */\n"
  },
  {
    "path": "deps/cl345/enc_dec/misc_rw.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous (Non-ASN.1) Routines Header File\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2004\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _MISCRW_DEFINED\n\n#define _MISCRW_DEFINED\n\n#include <time.h>\n#if defined( INC_ALL )\n  #include \"stream.h\"\n#else\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tConstants and Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sizes of encoded integer values */\n\n#define UINT16_SIZE\t\t2\n#define UINT32_SIZE\t\t4\n#define UINT64_SIZE\t\t8\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFunction Prototypes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read and write 16-, 32-, and 64-bit integer values */\n\nRETVAL_RANGE( 0, 0xFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint16( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint16( INOUT STREAM *stream, IN_RANGE( 0, 0xFFFF ) const int value );\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint32( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint32( INOUT STREAM *stream, IN_INT_Z const long value );\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint64( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint64( INOUT STREAM *stream, IN_INT_Z const long value );\n\n/* Read and write 32-bit time values */\n\nRETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readUint32Time( INOUT STREAM *stream, OUT time_t *timeVal );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint32Time( INOUT STREAM *stream, const time_t timeVal );\n\n/* Read and write strings preceded by 32-bit lengths */\n\n#define sizeofString32( stringLength )\t( UINT32_SIZE + stringLength )\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readString32( INOUT STREAM *stream, \n\t\t\t\t  OUT_BUFFER( stringMaxLength, \\\n\t\t\t\t\t\t\t  *stringLength ) void *string, \n\t\t\t\t  IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\tint *stringLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readString32Opt( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER( stringMaxLength, \\\n\t\t\t\t\t\t\t\t *stringLength ) void *string, \n\t\t\t\t\t IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\tint *stringLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeString32( INOUT STREAM *stream, \n\t\t\t\t   IN_BUFFER( stringLength ) const void *string, \n\t\t\t\t   IN_LENGTH_SHORT const int stringLength );\n\n/* Read a raw object preceded by a 32-bit length */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readRawObject32( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER( bufferMaxLength, *bufferLength ) \\\n\t\t\t\t\t\tvoid *buffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( UINT32_SIZE + 1 ) \\\n\t\t\t\t\t\tconst int bufferMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\tint *bufferLength );\n\n/* Read a universal type and discard it (used to skip unknown or unwanted\n   types) */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal16( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUniversal32( INOUT STREAM *stream );\n\n/* Read and write unsigned (large) integers preceded by 16- and 32-bit\n   lengths, lengths in bits */\n\n#define sizeofInteger16U( integerLength )\t( UINT16_SIZE + integerLength )\n#define sizeofInteger32( integer, integerLength ) \\\n\t\t( UINT32_SIZE + ( ( ( ( BYTE * ) integer )[ 0 ] & 0x80 ) ? 1 : 0 ) + \\\n\t\t\t\t\t\tintegerLength )\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16U( INOUT STREAM *stream, \n\t\t\t\t\tOUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t\t*integerLength ) void *integer, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) int *integerLength, \n\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\tIN_LENGTH_PKC const int maxLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t\t\t*integerLength ) void *integer, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( maxLength ) int *integerLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger32( INOUT STREAM *stream, \n\t\t\t\t   OUT_BUFFER_OPT( maxLength, \\\n\t\t\t\t\t\t\t\t   *integerLength ) void *integer, \n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLength ) int *integerLength, \n\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t   IN_LENGTH_PKC const int maxLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t IN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\t IN_LENGTH_PKC const int integerLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\t\t IN_LENGTH_PKC const int integerLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInteger32( INOUT STREAM *stream, \n\t\t\t\t\tIN_BUFFER( integerLength ) const void *integer, \n\t\t\t\t\tIN_LENGTH_PKC const int integerLength );\n\n/* Special-case large integer read routines that explicitly check for a too-\n   short key and return CRYPT_ERROR_NOSECURE rather than the \n   CRYPT_ERROR_BADDATA that'd otherwise be returned */\n\n#ifdef USE_SSL\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger16UChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_BUFFER_OPT( maxLength, *integerLength ) \\\n\t\t\t\t\t\t\tvoid *integer, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\t\t   IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t   IN_LENGTH_PKC const int maxLength );\n#endif /* USE_SSL */\n#ifdef USE_SSH\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readInteger32Checked( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_BUFFER_OPT( maxLength, *integerLength ) \\\n\t\t\t\t\t\t\tvoid *integer, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\tint *integerLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength );\n#endif /* USE_SSH */\n\n#ifdef USE_PKC\n\n/* Read and write bignum integers */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM ) const void *maxRange );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumInteger16U( INOUT STREAM *stream, \n\t\t\t\t\t\t   TYPECAST( BIGNUM ) const void *bignum );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC_BITS const int minBits, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC_BITS const int maxBits,\n\t\t\t\t\t\t\t  IN_OPT TYPECAST( BIGNUM ) const void *maxRange );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeBignumInteger16Ubits( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   TYPECAST( BIGNUM * ) const void *bignum );\nCHECK_RETVAL_RANGE( UINT32_SIZE, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sizeofBignumInteger32( const void *bignum );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger32( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT TYPECAST( BIGNUM ) void *bignum, \n\t\t\t\t\t\t IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t IN_LENGTH_PKC const int maxLength, \n\t\t\t\t\t\t IN_OPT TYPECAST( BIGNUM ) const void *maxRange );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeBignumInteger32( INOUT STREAM *stream, \n\t\t\t\t\t\t  TYPECAST( BIGNUM ) const void *bignum );\n\n/* Special-case bignum read routines that explicitly check for a too-short \n   key and return CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA\n   that'd otherwise be returned */\n\n#ifdef USE_SSL\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16UChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int maxLength );\n#endif /* USE_SSL */\n#ifdef USE_PGP\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger16UbitsChecked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\t\t IN_LENGTH_PKC_BITS const int minBits,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_PKC_BITS const int maxBits );\n#endif /* USE_PGP */\n#ifdef USE_SSH\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readBignumInteger32Checked( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT TYPECAST( BIGNUM * ) void *bignum, \n\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int maxLength );\n#endif /* USE_SSH */\n#endif /* USE_PKC */\n#endif /* !_MISCRW_DEFINED */\n"
  },
  {
    "path": "deps/cl345/enc_dec/pgp_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous (Non-ASN.1) Read/Write Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"pgp_rw.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/pgp_rw.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Read/Write Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a length in OpenPGP or PGP2 format */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readOpenPGPLength( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT_LENGTH_Z long *length,\n\t\t\t\t\t\t\t  OUT_BOOL BOOLEAN *indefiniteLength,\n\t\t\t\t\t\t\t  const BOOLEAN indefOK )\n\t{\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\tassert( isWritePtr( indefiniteLength, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES_S( indefOK == TRUE || indefOK == FALSE );\n\n\t/* Clear return values */\n\t*length = 0;\n\t*indefiniteLength = FALSE;\n\n\t/* Get the initial length byte to allow us to decode what else is \n\t   there */\n\tstatus = localLength = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* 0...191 is a literal value */\n\tif( localLength <= 191 )\n\t\t{\n\t\t*length = localLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* 192...223 is a 13-bit value with offset 192, giving a length in the \n\t   range 192...8383 */\n\tif( localLength <= 223 )\n\t\t{\n\t\tconst int value = sgetc( stream );\n\t\tif( cryptStatusError( value ) )\n\t\t\treturn( value );\n\t\tlocalLength = ( ( localLength - 192 ) << 8 ) + value + 192;\n\t\tif( localLength < 192 || localLength > 8383 )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t*length = localLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* 224...254 is PGP's annoying interpretation of indefinite-length \n\t   encoding.  This is an incredible pain to handle but fortunately \n\t   except for McAfee's PGP implementation and GPG under some \n\t   circumstances when it's used in a pipeline it doesn't seem to be used \n\t   by anything.  The only data type that would normally need indefinite \n\t   lengths, compressed data, uses the 2.x CTB 0xA3 instead */\n\tif( localLength < 255 )\n\t\t{\n\t\tif( !indefOK )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t\t/* Unlike ASN.1, which encodes an outer indefinite-length marker and \n\t\t   then encodes each sub-segment as a data unit within it, PGP \n\t\t   encodes a partial length as a sequence of power-of-two exponent \n\t\t   values with a standard length encoding for the last sub-segment.\n\t\t   So once we're in indefinite-length mode we have to record the \n\t\t   current *type* of the length (as well as its value) to determine \n\t\t   whether more length packets follow */\n\t\t*indefiniteLength = TRUE;\n\t\tlocalLength = 1 << ( localLength & 0x1F );\n\t\tif( !isIntegerRangeNZ( localLength ) )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t*length = localLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES_S( localLength == 255 );\n\n\t/* 255 is a marker that a standard 32-bit length follows */\n\tstatus = localLength = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*length = localLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPGP2Length( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_LENGTH_Z long *length, \n\t\t\t\t\t\t   IN_BYTE const int ctb )\n\t{\n\tlong localLength;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES_S( ctb >= 0 && ctb <= 0xFF );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* It's a PGP 2.x CTB, decode the length as a byte, word, or long */\n\tswitch( ctb & 3 )\n\t\t{\n\t\tcase 0:\n\t\t\tlocalLength = sgetc( stream );\n\t\t\tbreak;\n\n\t\tcase 1:\n\t\t\tlocalLength = readUint16( stream );\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tlocalLength = readUint32( stream );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* A length value of 3 indicates that the data length is \n\t\t\t   determined externally, this is a deprecated PGP 2.x value \n\t\t\t   that we don't handle */\n\t\t\tlocalLength = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( localLength ) )\n\t\treturn( localLength );\n\tif( !isIntegerRange( localLength ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t*length = localLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read PGP variable-length length values and packet headers (CTB + length).  \n   We also have a short-length version which is used to read small packets \n   such as keyrings and sigs and which ensures that the length is in the \n   range 1...16K */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int pgpReadLength( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxLength ) long *length, \n\t\t\t\t\t\t  IN_BYTE const int ctb, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int minLength, \n\t\t\t\t\t\t  IN_LENGTH const int maxLength, \n\t\t\t\t\t\t  const BOOLEAN indefOK )\n\t{\n\tBOOLEAN indefiniteLength = FALSE;\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\n\tREQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tminLength < maxLength && maxLength < MAX_INTLENGTH );\n\tREQUIRES_S( indefOK == TRUE || indefOK == FALSE );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* If it doesn't look like PGP data, don't go any further */\n\tif( !pgpIsCTB( ctb ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\n\t/* If it's an OpenPGP CTB, undo the hand-Huffman-coding */\n\tif( pgpGetPacketVersion( ctb ) == PGP_VERSION_OPENPGP )\n\t\t{\n\t\tstatus = readOpenPGPLength( stream, &localLength, \n\t\t\t\t\t\t\t\t\t&indefiniteLength, indefOK );\n\t\t}\n\telse\n\t\tstatus = readPGP2Length( stream, &localLength, ctb );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( localLength < minLength || localLength > maxLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t*length = localLength;\n\treturn( indefiniteLength ? OK_SPECIAL : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readPacketHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_OPT_BYTE int *ctb, \n\t\t\t\t\t\t\t OUT_OPT_LENGTH_Z long *length, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int minLength, \n\t\t\t\t\t\t\t IN_LENGTH const int maxLength, \n\t\t\t\t\t\t\t const BOOLEAN indefOK )\n\t{\n\tlong localLength;\n\tint localCTB, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\t\n\tREQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tminLength < maxLength && maxLength < MAX_INTLENGTH );\n\tREQUIRES_S( indefOK == TRUE || indefOK == FALSE );\n\n\t/* Clear return values */\n\tif( ctb != NULL )\n\t\t*ctb = 0;\n\tif( length != NULL )\n\t\t*length = 0;\n\n\t/* Examine the CTB and figure out whether we need to perform any \n\t   special-case handling */\n\tstatus = localCTB = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !pgpIsCTB( localCTB ) )\n\t\t{\n\t\t/* If it doesn't look like PGP data, don't go any further */\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tif( localCTB == PGP_CTB_COMPRESSED )\n\t\t{\n\t\t/* If it's a compressed data packet, there's no length present.\n\t\t   Normally we reject any indefinite-length packets since these\n\t\t   can't be processed sensibly (PGP 2.x, which used intermediate\n\t\t   files for everything, just read to EOF, OpenPGP deprecates them\n\t\t   because this doesn't exactly lead to portable implementations).\n\t\t   However, compressed-data packets can only be stored in this\n\t\t   manner but can still be processed because the user has to\n\t\t   explicitly flush the data at some point and we assume that this\n\t\t   is EOF.\n\t\t   \n\t\t   For this reason we don't return OK_SPECIAL to indicate an \n\t\t   indefinite-length encoding because this isn't a standard \n\t\t   segmented encoding but a virtual definite-length that ends when\n\t\t   the user says it ends.   This is far uglier than the PKCS #7/CMS/\n\t\t   SMIME equivalent where we've got an explicit end-of-data\n\t\t   indication, but it's the best that we can do.\n\t\t   \n\t\t   In addition it's not clear what we should return as the \"length\"\n\t\t   value for this non-length, the contract with the caller says that\n\t\t   we'll only permit a returned value within the range \n\t\t   { minLength ... maxLength } but there isn't any length present.  \n\t\t   To deal with this we return a fake length equal to minLength, \n\t\t   which means that we stick to the contract, and which will be \n\t\t   ignored by any caller that can process compressed data since, by \n\t\t   definition, the length value is meaningless */\n\t\tif( ctb != NULL )\n\t\t\t*ctb = localCTB;\n\t\tif( length != NULL )\n\t\t\t*length = minLength;\t/* See comment above */\n\t\treturn( CRYPT_OK );\t/* Not-really-indef. return status */\n\t\t}\n\n\t/* Now that we know the format, get the length information */\n\tstatus = pgpReadLength( stream, &localLength, localCTB,\n\t\t\t\t\t\t\tminLength, maxLength, indefOK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tint type;\n\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\n\t\t/* It's an indefinite-length encoding, this is only valid for\n\t\t   payload data packets so we make sure that we've got one of these\n\t\t   packet types present */\n\t\tENSURES_S( indefOK );\n\t\ttype = pgpGetPacketType( localCTB );\n\t\tif( type != PGP_PACKET_DATA && type != PGP_PACKET_COPR && \\\n\t\t\ttype != PGP_PACKET_ENCR && type != PGP_PACKET_ENCR_MDC )\n\t\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\t\t}\n\tif( ctb != NULL )\n\t\t*ctb = localCTB;\n\tif( length != NULL )\n\t\t*length = localLength;\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pgpReadShortLength( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *length, \n\t\t\t\t\t\tIN_BYTE const int ctb )\n\t{\n\tlong localLength;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tstatus = pgpReadLength( stream, &localLength, ctb, 0, \n\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isIntegerRange( localLength ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*length = ( int ) localLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpReadPacketHeader( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb, \n\t\t\t\t\t\t OUT_OPT_LENGTH_Z long *length, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int minLength,\n\t\t\t\t\t\t IN_LENGTH const long maxLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\t\n\tREQUIRES_S( minLength >= 0 && minLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tmaxLength > minLength && maxLength < MAX_INTLENGTH );\n\n\treturn( readPacketHeader( stream, ctb, length, minLength, maxLength, \n\t\t\t\t\t\t\t  FALSE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpReadPacketHeaderI( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb, \n\t\t\t\t\t\t  OUT_OPT_LENGTH_Z long *length, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int minLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ctb == NULL || isWritePtr( ctb, sizeof( int ) ) );\n\tassert( length == NULL || isWritePtr( length, sizeof( long ) ) );\n\t\n\tREQUIRES_S( isShortIntegerRange( minLength ) );\n\n\treturn( readPacketHeader( stream, ctb, length, minLength, \n\t\t\t\t\t\t\t  MAX_INTLENGTH - 1, TRUE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pgpReadPartialLength( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_LENGTH_Z long *length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\t\n\t/* This is a raw length value so we have to feed in a pseudo-CTB */\n\treturn( pgpReadLength( stream, length, PGP_CTB_OPENPGP,\n\t\t\t\t\t\t   0, MAX_INTLENGTH - 1, TRUE ) );\n\t}\n\n/* Write PGP variable-length length values and packet headers (CTB + \n   length) */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWriteLength( INOUT STREAM *stream, \n\t\t\t\t\tIN_LENGTH const long length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( isIntegerRangeNZ( length ) );\n\n\tif( length <= 191 )\n\t\treturn( sputc( stream, length ) );\n\tif( length <= 8383 )\n\t\t{\n\t\tconst long adjustedLength = length - 192;\n\n\t\tsputc( stream, ( ( adjustedLength >> 8 ) & 0xFF ) + 192 );\n\t\treturn( sputc( stream, ( adjustedLength & 0xFF ) ) );\n\t\t}\n\tsputc( stream, 0xFF );\n\tsputc( stream, ( length >> 24 ) & 0xFF );\n\tsputc( stream, ( length >> 16 ) & 0xFF );\n\tsputc( stream, ( length >> 8 ) & 0xFF );\n\treturn( sputc( stream, ( length & 0xFF ) ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWritePacketHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_ENUM( PGP_PACKET ) const PGP_PACKET_TYPE packetType,\n\t\t\t\t\t\t  IN_LENGTH const long length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( isEnumRange( packetType, PGP_PACKET ) );\n\tREQUIRES_S( isIntegerRangeNZ( length ) );\n\n\tsputc( stream, PGP_CTB_OPENPGP | packetType );\n\treturn( pgpWriteLength( stream, length ) );\n\t}\n#endif /* USE_PGP */\n"
  },
  {
    "path": "deps/cl345/enc_dec/pgp_rw.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous (Non-ASN.1) Routines Header File\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2004\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _PGPRW_DEFINED\n\n#define _PGPRW_DEFINED\n\n#include <time.h>\n#if defined( INC_ALL )\n  #include \"misc_rw.h\"\n  #include \"stream.h\"\n  #include \"pgp.h\"\n#else\n  #include \"enc_dec/misc_rw.h\"\n  #include \"io/stream.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFunction Prototypes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write PGP length values */\n\n#define pgpSizeofLength( length ) \\\n\t\t( ( length < 0 ) ? length : \\\n\t\t  ( length <= 191 ) ? 1 : \\\n\t\t  ( length <= 8383 ) ? 2 : 4 )\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pgpReadShortLength( INOUT STREAM *stream, \n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *length, \n\t\t\t\t\t\tIN_BYTE const int ctb );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pgpReadPartialLength( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_LENGTH_Z long *length );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWriteLength( INOUT STREAM *stream, IN_LENGTH const long length );\n\n/* Read/write PGP packet headers.  The difference between \n   pgpReadPacketHeader() and pgpReadPacketHeaderI() is that the latter \n   allows indefinite-length encoding for partial lengths.  Once we've\n   read an indefinite length, we have to use pgpReadPartialLengh() to\n   read subsequence partial-length values */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpReadPacketHeader( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb, \n\t\t\t\t\t\t OUT_OPT_LENGTH_Z long *length, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int minLength,\n\t\t\t\t\t\t IN_LENGTH const long maxLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpReadPacketHeaderI( INOUT STREAM *stream, OUT_OPT_BYTE int *ctb, \n\t\t\t\t\t\t  OUT_OPT_LENGTH_Z long *length, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int minLength );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWritePacketHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_ENUM( PGP_PACKET ) \\\n\t\t\t\t\t\t\tconst PGP_PACKET_TYPE packetType,\n\t\t\t\t\t\t  IN_LENGTH const long length );\n\n#endif /* _PGPRW_DEFINED */\n"
  },
  {
    "path": "deps/cl345/envelope/cms_denv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib De-enveloping Routines\t\t\t\t\t\t*\n*\t\t\t\t\t Copyright Peter Gutmann 1996-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMS\n\n/* The maximum number of data items that we can process in the header or \n   trailer.  This isn't an absolute limit but more a sanity check in invalid\n   headers/trailers */\n\n#define MAX_DATA_ITEMS\t\t32\n\n/* OID information used to read enveloped data */\n\nstatic const CMS_CONTENT_INFO oidInfoSignedData = { 0, 3 };\nstatic const CMS_CONTENT_INFO oidInfoEnvelopedData = { 0, 4 };\nstatic const CMS_CONTENT_INFO oidInfoEncryptedData = { 0, 2 };\nstatic const CMS_CONTENT_INFO oidInfoCompressedData = { 0, 0 };\nstatic const CMS_CONTENT_INFO oidInfoAuthData = { 0, 0 };\nstatic const CMS_CONTENT_INFO oidInfoAuthEnvData = { 0, 0 };\n\nstatic const OID_INFO envelopeOIDinfo[] = {\n\t{ OID_CMS_DATA, ACTION_NONE },\n\t{ OID_CMS_SIGNEDDATA, ACTION_SIGN, &oidInfoSignedData },\n\t{ OID_CMS_ENVELOPEDDATA, ACTION_KEYEXCHANGE, &oidInfoEnvelopedData },\n\t{ OID_CMS_ENCRYPTEDDATA, ACTION_CRYPT, &oidInfoEncryptedData },\n\t{ OID_CMS_COMPRESSEDDATA, ACTION_COMPRESS, &oidInfoCompressedData },\n\t{ OID_CMS_AUTHDATA, ACTION_MAC, &oidInfoAuthData },\n\t{ OID_CMS_AUTHENVDATA, ACTION_xxx, &oidInfoAuthEnvData },\n\t{ OID_CMS_TSTOKEN, ACTION_NONE },\n\t{ OID_MS_SPCINDIRECTDATACONTEXT, ACTION_NONE },\n\t{ OID_CRYPTLIB_RTCSREQ, ACTION_NONE },\n\t{ OID_CRYPTLIB_RTCSRESP, ACTION_NONE },\n\t{ OID_CRYPTLIB_RTCSRESP_EXT, ACTION_NONE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\nstatic const OID_INFO nestedContentOIDinfo[] = {\n\t{ OID_CMS_DATA, CRYPT_CONTENT_DATA },\n\t{ OID_CMS_SIGNEDDATA, CRYPT_CONTENT_SIGNEDDATA },\n\t{ OID_CMS_ENVELOPEDDATA, CRYPT_CONTENT_ENVELOPEDDATA },\n\t{ OID_CMS_ENCRYPTEDDATA, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t{ OID_CMS_COMPRESSEDDATA, CRYPT_CONTENT_COMPRESSEDDATA },\n\t{ OID_CMS_AUTHDATA, CRYPT_CONTENT_AUTHDATA },\n\t{ OID_CMS_AUTHENVDATA, CRYPT_CONTENT_AUTHENVDATA },\n\t{ OID_CMS_TSTOKEN, CRYPT_CONTENT_TSTINFO },\n\t{ OID_MS_SPCINDIRECTDATACONTEXT, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },\n\t{ OID_CRYPTLIB_RTCSREQ, CRYPT_CONTENT_RTCSREQUEST },\n\t{ OID_CRYPTLIB_RTCSRESP, CRYPT_CONTENT_RTCSRESPONSE },\n\t{ OID_CRYPTLIB_RTCSRESP_EXT, CRYPT_CONTENT_RTCSRESPONSE_EXT },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckEnvCMSDenv( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckEnvelope( envelopeInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvCMSDenv: Envelope check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the general envelope state is in order */\n\tif( !TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvCMSDenv: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tContent-list Processing Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n\n/* Add information on different object types to a content-list entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int initExternalContentInfo( CONTENT_LIST *contentListItem,\n\t\t\t\t\t\t\t\t\tIN_ENUM( CONTENT ) \\\n\t\t\t\t\t\t\t\t\t\tconst CONTENT_TYPE contentType,\n\t\t\t\t\t\t\t\t\tconst QUERY_INFO *queryInfo )\n\t{\n\tCONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;\n\n\tassert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( contentType == CONTENT_AUTHENC || \\\n\t\t\t  contentType == CONTENT_CRYPT );\n\n\tcontentListItem->envInfo = CRYPT_ENVINFO_SESSIONKEY;\n\n\t/* If it's authenticated encrypted data, remember the optional KDF and \n\t   encryption and MAC algorithm parameters */\n\tif( contentType == CONTENT_AUTHENC )\n\t\t{\n\t\tCONTENT_AUTHENC_INFO *authEncInfo = &contentListItem->clAuthEncInfo;\n\n\t\tauthEncInfo->authEncAlgo = queryInfo->cryptAlgo;\n\t\tREQUIRES( rangeCheck( queryInfo->authEncParamLength, 1, 128 ) );\n\t\tmemcpy( authEncInfo->authEncParamData, queryInfo->authEncParamData,\n\t\t\t\tqueryInfo->authEncParamLength );\n\t\tauthEncInfo->authEncParamLength = queryInfo->authEncParamLength;\n\t\tif( queryInfo->kdfParamLength > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( queryInfo->kdfParamStart,\n\t\t\t\t\t\t\t\t   queryInfo->kdfParamLength,\n\t\t\t\t\t\t\t\t   queryInfo->authEncParamLength ) );\n\t\t\tauthEncInfo->kdfData = authEncInfo->authEncParamData + \\\n\t\t\t\t\t\t\t\t   queryInfo->kdfParamStart;\n\t\t\tauthEncInfo->kdfDataLength = queryInfo->kdfParamLength;\n\t\t\t}\n\t\tREQUIRES( boundsCheck( queryInfo->encParamStart,\n\t\t\t\t\t\t\t   queryInfo->encParamLength,\n\t\t\t\t\t\t\t   queryInfo->authEncParamLength ) );\n\t\tauthEncInfo->encParamData = authEncInfo->authEncParamData + \\\n\t\t\t\t\t\t\t\t\tqueryInfo->encParamStart;\n\t\tauthEncInfo->encParamDataLength = queryInfo->encParamLength;\n\t\tREQUIRES( boundsCheck( queryInfo->macParamStart,\n\t\t\t\t\t\t\t   queryInfo->macParamLength,\n\t\t\t\t\t\t\t   queryInfo->authEncParamLength ) );\n\t\tauthEncInfo->macParamData = authEncInfo->authEncParamData + \\\n\t\t\t\t\t\t\t\t\tqueryInfo->macParamStart;\n\t\tauthEncInfo->macParamDataLength = queryInfo->macParamLength;\n\n\t\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's conventionally encrypted data, remember the encryption algorithm \n\t   parameters */\n\tencrInfo->cryptAlgo = queryInfo->cryptAlgo;\n\tencrInfo->cryptMode = queryInfo->cryptMode;\n\tif( queryInfo->ivLength > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( queryInfo->ivLength, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( encrInfo->saltOrIV, queryInfo->iv, queryInfo->ivLength );\n\t\tencrInfo->saltOrIVsize = queryInfo->ivLength;\n\t\t}\n\n\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int initPkcContentInfo( CONTENT_LIST *contentListItem,\n\t\t\t\t\t\t\t   const QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t   IN_BUFFER( objectSize ) const void *object, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int objectSize )\n\t{\n\tconst BYTE *objectPtr = object;\t/* For pointer maths */\n\n\tassert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\tassert( isReadPtrDynamic( object, objectSize ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( objectSize ) );\n\n\t/* Remember the details of the enveloping information that we require \n\t   to continue */\n\tif( queryInfo->type == CRYPT_OBJECT_PKCENCRYPTED_KEY )\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_PRIVATEKEY;\n\telse\n\t\t{\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_SIGNATURE;\n\t\tcontentListItem->clSigInfo.hashAlgo = queryInfo->hashAlgo;\n\t\tcontentListItem->clSigInfo.hashAlgoParam = queryInfo->hashAlgoParam;\n\t\t}\n\tif( queryInfo->formatType == CRYPT_FORMAT_CMS )\n\t\t{\n\t\tREQUIRES( boundsCheck( queryInfo->iAndSStart, queryInfo->iAndSLength, \n\t\t\t\t\t\t\t   objectSize ) );\n\t\tcontentListItem->issuerAndSerialNumber = objectPtr + queryInfo->iAndSStart;\n\t\tcontentListItem->issuerAndSerialNumberSize = queryInfo->iAndSLength;\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( rangeCheck( queryInfo->keyIDlength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( contentListItem->keyID, queryInfo->keyID,\n\t\t\t\tqueryInfo->keyIDlength );\n\t\tcontentListItem->keyIDsize = queryInfo->keyIDlength;\n\t\t}\n\tREQUIRES( boundsCheck( queryInfo->dataStart, queryInfo->dataLength, \n\t\t\t\t\t\t   objectSize ) );\n\tcontentListItem->payload = objectPtr + queryInfo->dataStart;\n\tcontentListItem->payloadSize = queryInfo->dataLength;\n\tif( queryInfo->type == CRYPT_OBJECT_SIGNATURE && \\\n\t\tqueryInfo->formatType == CRYPT_FORMAT_CMS && \\\n\t\tqueryInfo->unauthAttributeStart > 0 )\n\t\t{\n\t\tCONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;\n\n\t\tREQUIRES( boundsCheck( queryInfo->unauthAttributeStart,\n\t\t\t\t\t\t\t   queryInfo->unauthAttributeLength, \n\t\t\t\t\t\t\t   objectSize ) );\n\t\tsigInfo->extraData2 = objectPtr + queryInfo->unauthAttributeStart;\n\t\tsigInfo->extraData2Length = queryInfo->unauthAttributeLength;\n\t\t}\n\n\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int initEncKeyContentInfo( CONTENT_LIST *contentListItem,\n\t\t\t\t\t\t\t\t  const QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t\t  IN_BUFFER( objectSize ) const void *object, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int objectSize )\n\t{\n\tCONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;\n\tconst BYTE *objectPtr = object;\t/* For pointer maths */\n\n\tassert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\tassert( isReadPtrDynamic( object, objectSize ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( objectSize ) );\n\n\t/* Remember the details of the enveloping information that we require \n\t   to continue */\n\tif( queryInfo->keySetupAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_PASSWORD;\n\t\tencrInfo->keySetupAlgo = queryInfo->keySetupAlgo;\n\t\tencrInfo->keySetupAlgoParam = queryInfo->keySetupAlgoParam;\n\t\tencrInfo->keySetupIterations = queryInfo->keySetupIterations;\n\t\tif( queryInfo->keySize > 0 )\n\t\t\tencrInfo->keySize = queryInfo->keySize;\n\t\tif( queryInfo->saltLength > 0 )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( queryInfo->saltLength, 1, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\t\tmemcpy( encrInfo->saltOrIV, queryInfo->salt,\n\t\t\t\t\tqueryInfo->saltLength );\n\t\t\tencrInfo->saltOrIVsize = queryInfo->saltLength;\n\t\t\t}\n\t\t}\n\telse\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_KEY;\n\tencrInfo->cryptAlgo = queryInfo->cryptAlgo;\n\tencrInfo->cryptMode = queryInfo->cryptMode;\n\tREQUIRES( boundsCheck( queryInfo->dataStart, queryInfo->dataLength, \n\t\t\t\t\t\t   objectSize ) );\n\tcontentListItem->payload = objectPtr + queryInfo->dataStart;\n\tcontentListItem->payloadSize = queryInfo->dataLength;\n\n\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add information about an object to an envelope's content information list.  \n   The content information can be supplied in one of two ways, either \n   implicitly via the data in the stream or explicitly via a QUERY_INFO\n   structure */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int addContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   INOUT_OPT STREAM *stream, \n\t\t\t\t\t\t\t   IN_OPT const QUERY_INFO *externalQueryInfo,\n\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *itemSize )\n\t{\n\tconst CONTENT_LIST *contentListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\tQUERY_INFO queryInfo;\n\tCONTENT_LIST *contentListItem;\n\tvoid *contentListObjectPtr = NULL;\n\tCONTENT_TYPE contentType;\n\tconst BOOLEAN infoProvidedExternally = \\\n\t\t\t\t\t( externalQueryInfo != NULL ) ? TRUE : FALSE;\n\tint objectSize = 0, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( ( stream == NULL && \\\n\t\t\t  isReadPtr( externalQueryInfo, sizeof( QUERY_INFO ) ) ) || \\\n\t\t\t( isWritePtr( stream, sizeof( STREAM ) ) && \\\n\t\t\t  externalQueryInfo == NULL ) );\n\tassert( isWritePtr( itemSize, sizeof( int ) ) );\n\n\tREQUIRES( ( stream == NULL && externalQueryInfo != NULL ) || \\\n\t\t\t  ( stream != NULL && externalQueryInfo == NULL ) );\n\n\t/* Clear return values */\n\t*itemSize = 0;\n\n\t/* Make sure that there's room to add another list item */\n\tif( !moreContentItemsPossible( contentListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Find the size of the object, allocate a buffer for it, and copy it\n\t   across */\n\tif( !infoProvidedExternally )\n\t\t{\n\t\t/* See what we've got.  This call verifies that all of the object \n\t\t   data is present in the stream so in theory we don't have to check \n\t\t   the following reads, but we check them anyway just to be sure */\n\t\tstatus = queryAsn1Object( stream, &queryInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES( isIntegerRangeNZ( queryInfo.size ) );\n\t\tobjectSize = ( int ) queryInfo.size;\n\n\t\t/* If it's a valid but unrecognised object type (a new RecipientInfo \n\t\t   type that was added after this version of cryptlib was released), \n\t\t   skip it and continue (if there are no recognised RecipientInfo \n\t\t   types, the code will automatically fall back to asking the user \n\t\t   for a raw session key).  Alternatively, we could just add it to \n\t\t   the content list as an unrecognised object type, but this would \n\t\t   lead to confusion for the caller when non-object-types appear \n\t\t   when they query the current component */\n\t\tif( queryInfo.type == CRYPT_OBJECT_NONE )\n\t\t\t{\n\t\t\tstatus = sSkip( stream, objectSize, SSKIP_MAX );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t*itemSize = objectSize;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Read the object data into memory */\n\t\tREQUIRES( rangeCheck( objectSize, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( contentListObjectPtr = clAlloc( \"addContentListItem\", \\\n\t\t\t\t\t\t\t\t\t\t\t  objectSize ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tstatus = sread( stream, contentListObjectPtr, objectSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"addContentListItem\", contentListObjectPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* The query information has been provided externally, use that */\n\t\tmemcpy( &queryInfo, externalQueryInfo, sizeof( QUERY_INFO ) );\n\t\t}\n\tENSURES( infoProvidedExternally || isIntegerRangeNZ( queryInfo.size ) );\n\t\t\t /* If the query information is supplied externally then it's a \n\t\t\t    template that doesn't correspond to any actual data */\n\n\t/* Determine the type of content that we're working with */\n\tif( queryInfo.type == CRYPT_OBJECT_SIGNATURE )\n\t\tcontentType = CONTENT_SIGNATURE;\n\telse\n\t\t{\n\t\tif( isSpecialAlgo( queryInfo.cryptAlgo ) )\n\t\t\tcontentType = CONTENT_AUTHENC;\n\t\telse\n\t\t\tcontentType = CONTENT_CRYPT;\n\t\t}\n\n\t/* Allocate memory for the new content list item and copy information on\n\t   the item across */\n\tstatus = createContentListItem( &contentListItem, \n\t\t\t\t\tenvelopeInfoPtr->memPoolState, contentType, \n\t\t\t\t\tqueryInfo.formatType, contentListObjectPtr, \n\t\t\t\t\tobjectSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( contentListObjectPtr != NULL )\n\t\t\tclFree( \"addContentListItem\", contentListObjectPtr );\n\t\treturn( status );\n\t\t}\n\tif( infoProvidedExternally )\n\t\t{\n\t\t/* It's externally-supplied encryption algorithm details from an\n\t\t   encrypted data header, either standard encrypted data or \n\t\t   authenticated encrypted data */\n\t\tstatus = initExternalContentInfo( contentListItem, contentType, \n\t\t\t\t\t\t\t\t\t\t  &queryInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tif( queryInfo.type == CRYPT_OBJECT_PKCENCRYPTED_KEY || \\\n\t\t\tqueryInfo.type == CRYPT_OBJECT_SIGNATURE )\n\t\t\t{\n\t\t\t/* Remember the details of the enveloping information that we \n\t\t\t   require to continue */\n\t\t\tstatus = initPkcContentInfo( contentListItem, &queryInfo,\n\t\t\t\t\t\t\t\t\t\t contentListObjectPtr, objectSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tif( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY )\n\t\t\t{\n\t\t\t/* Remember the details of the enveloping information that we \n\t\t\t   require to continue */\n\t\t\tstatus = initEncKeyContentInfo( contentListItem, &queryInfo,\n\t\t\t\t\t\t\t\t\t\t\tcontentListObjectPtr, objectSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tstatus = appendContentListItem( envelopeInfoPtr, contentListItem );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeleteContentListItem( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t   contentListItem );\n\t\tif( contentListObjectPtr != NULL )\n\t\t\tclFree( \"addContentListItem\", contentListObjectPtr );\n\t\treturn( status );\n\t\t}\n\tENSURES( isIntegerRange( queryInfo.size ) );\n\t*itemSize = ( int ) queryInfo.size;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHeader Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the outer CMS envelope header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processEnvelopeHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( DEENVSTATE ) DEENV_STATE *state )\n\t{\n\tint status, action;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( state, sizeof( DEENV_STATE ) ) );\n\n\t/* Clear return value */\n\t*state = DEENVSTATE_NONE;\n\n\t/* Read the outer CMS header */\n\tstatus = readCMSheader( stream, envelopeOIDinfo,\n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( envelopeOIDinfo, OID_INFO ),\n\t\t\t\t\t\t\t&action, &envelopeInfoPtr->payloadSize, \n\t\t\t\t\t\t\tREADCMS_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine the next state to continue processing */\n\tswitch( action )\n\t\t{\n\t\tcase ACTION_NONE:\n\t\t\t/* Since we're going straight to the data payload there's no \n\t\t\t   nested content type so we explicitly set it to \"data\" */\n\t\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;\n\t\t\t*state = DEENVSTATE_DATA;\n\t\t\tbreak;\n\n\t\tcase ACTION_KEYEXCHANGE:\n\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\t*state = DEENVSTATE_SET_ENCR;\n\t\t\tbreak;\n\n\t\tcase ACTION_xxx:\n\t\t\t/* Authenticated encryption is a variant of a standard encrypted \n\t\t\t   envelope */\n\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC );\n\t\t\t*state = DEENVSTATE_SET_ENCR;\n\t\t\tbreak;\n\n\t\tcase ACTION_CRYPT:\n\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\t*state = DEENVSTATE_ENCRCONTENT;\n\t\t\tbreak;\n\n\t\tcase ACTION_MAC:\n\t\t\t/* MACd envelopes have key exchange information at the start \n\t\t\t   just like ACTION_KEYEXCHANGE but the later processing is \n\t\t\t   different so we treat them as a special case here */\n\t\t\tenvelopeInfoPtr->usage = ACTION_MAC;\n\t\t\t*state = DEENVSTATE_SET_ENCR;\n\t\t\tbreak;\n\n\t\tcase ACTION_COMPRESS:\n\t\t\t/* With compressed data all that we need to do is check that the \n\t\t\t   fixed AlgorithmIdentifier is present and set up the \n\t\t\t   decompression stream, after which we go straight to the \n\t\t\t   content */\n\t\t\tstatus = readGenericAlgoID( stream, OID_ZLIB, \n\t\t\t\t\t\t\t\t\t\tsizeofOID( OID_ZLIB ) ); \n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tenvelopeInfoPtr->usage = ACTION_COMPRESS;\n#ifdef USE_COMPRESSION\n\t\t\tif( inflateInit( &envelopeInfoPtr->zStream ) != Z_OK )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED );\n\t\t\t*state = DEENVSTATE_CONTENT;\n#else\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#endif /* USE_COMPRESSION */\n\t\t\tbreak;\n\n\t\tcase ACTION_SIGN:\n\t\t\tenvelopeInfoPtr->usage = ACTION_SIGN;\n\t\t\t*state = DEENVSTATE_SET_HASH;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the encrypted content header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processEncryptionHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tQUERY_INFO queryInfo;\n\tint contentType, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\t/* Read the encrypted content header */\n\tstatus = readCMSencrHeader( stream, nestedContentOIDinfo, \n\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( nestedContentOIDinfo, OID_INFO ),\n\t\t\t\t\t\t&contentType, NULL, &queryInfo,\n\t\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \\\n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_AUTHENC ) ? \\\n\t\t\t\t\t\t\tREADCMS_FLAG_AUTHENC : READCMS_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tenvelopeInfoPtr->contentType = contentType;\n\tenvelopeInfoPtr->payloadSize = queryInfo.size;\n\n\t/* We've reached encrypted data, we can't go any further until we can \n\t   either recover the session key from a key exchange object or are fed \n\t   the session key directly */\n\tif( actionListPtr == NULL )\n\t\t{\n\t\tint dummy;\n\n\t\t/* Since the content can be indefinite-length we clear the size \n\t\t   field to give it a sensible setting */\n\t\tqueryInfo.size = 0;\n\t\treturn( addContentListItem( envelopeInfoPtr, NULL, &queryInfo, \n\t\t\t\t\t\t\t\t\t&dummy ) );\n\t\t}\n\tREQUIRES( actionListPtr != NULL && \\\n\t\t\t  actionListPtr->action == ACTION_CRYPT );\n\n\t/* If the session key was recovered from a key exchange action but we \n\t   ran out of input data before we could read the encryptedContent \n\t   information it'll be present in the action list so we use it to set \n\t   things up for the decryption.  This can only happen if the caller \n\t   pushes in just enough data to get past the key exchange actions but \n\t   not enough to recover the encryptedContent information and then \n\t   pushes in a key exchange action in response to the \n\t   CRYPT_ERROR_UNDERFLOW error */\n\treturn( initEnvelopeEncryption( envelopeInfoPtr,\n\t\t\t\t\t\t\tactionListPtr->iCryptHandle,\n\t\t\t\t\t\t\tqueryInfo.cryptAlgo, queryInfo.cryptMode,\n\t\t\t\t\t\t\tqueryInfo.iv, queryInfo.ivLength,\n\t\t\t\t\t\t\tFALSE ) );\n\t}\n\n/* Process the hash object header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processHashHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tACTION_LIST *actionListPtr;\n\tint hashAlgo DUMMY_INIT, hashAlgoParam = 0;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Create the hash object from the data */\n\tstatus = readContextAlgoID( stream, &iHashContext, NULL, DEFAULT_TAG,\n\t\t\t\t\t\t\t\tALGOID_CLASS_HASH );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\t\t}\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgoParam, CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check whether an identical hash action is already present, either \n\t   through being supplied externally or from a duplicate entry in the \n\t   set of digest/MAC algorithms in the envelope header */\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ), \n\t\t\t  actionListPtr != NULL, \n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tint actionHashAlgo, actionHashAlgoParam = 0;\n\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &actionHashAlgo, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusOK( status ) && isHashMacExtAlgo( actionHashAlgo ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &actionHashAlgoParam, \n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tactionHashAlgo == hashAlgo && \\\n\t\t\tactionHashAlgoParam == hashAlgoParam )\n\t\t\t{\n\t\t\t/* There's a duplicate action present, destroy the one that \n\t\t\t   we've just created and continue */\n\t\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We didn't find any duplicates, append the new hash action to the \n\t   action list and remember that hashing is now active */\n\tstatus = addAction( envelopeInfoPtr, \n\t\t\t\t\t\t( envelopeInfoPtr->usage == ACTION_MAC ) ? \\\n\t\t\t\t\t\t\tACTION_MAC : ACTION_HASH, iHashContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\n\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\tENSURES( actionListPtr != NULL && \\\n\t\t\t ( actionListPtr->action == ACTION_HASH || \\\n\t\t\t   actionListPtr->action == ACTION_MAC ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTrailer Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process EOCs that separate the payload from the trailer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processPayloadEOCs( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* If the payload has an indefinite-length encoding, make sure that the\n\t   required EOCs are present */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\tif( ( status = checkEOC( stream ) ) != TRUE || \\\n\t\t\t( status = checkEOC( stream ) ) != TRUE )\n\t\t\t{\n\t\t\treturn( cryptStatusError( status ) ? \\\n\t\t\t\t\tstatus : CRYPT_ERROR_BADDATA );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the data was encoded using a mixture of definite and indefinite \n\t   encoding there may be EOC's present even though the length is known \n\t   so we skip them if necessary */\n\tif( ( status = checkEOC( stream ) ) == TRUE )\n\t\tstatus = checkEOC( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check for a possible soft error when reading data.  This is necessary \n   because if we're performing a standard data push then the caller expects \n   to get a CRYPT_OK status with a bytes-copied count, but if they've got as \n   far as the trailer data then they'll get a CRYPT_ERROR_UNDERFLOW unless \n   we special-case the handling of the return status.  This is complicated \n   by the fact that we have to carefully distinguish a CRYPT_ERROR_UNDERFLOW \n   due to running out of input from a CRYPT_ERROR_UNDERFLOW incurred for any \n   other reason such as parsing the input data */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkSoftError( IN_ERROR const int status, \n\t\t\t\t\t\t\t   const BOOLEAN isFlush )\n\t{\n\tREQUIRES_B( cryptStatusError( status ) );\n\tREQUIRES_B( isFlush == TRUE || isFlush == FALSE );\n\n\t/* If it's not a flush and we've run out of data, report it as a soft \n\t   error */\n\tif( !isFlush && status == CRYPT_ERROR_UNDERFLOW )\n\t\treturn( TRUE );\n\t\t\n\treturn( FALSE );\n\t}\n\n/* Complete processing of the authenticated payload for hashed, MACd, \n   signed, and authenticated encrypted data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completePayloadProcessing( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ENV_PROCESSEXTRADATA_FUNCTION processExtraDataFunction = \\\n\t\t\t\t( ENV_PROCESSEXTRADATA_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->processExtraDataFunction );\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( processExtraDataFunction != NULL );\n\n\t/* When we reach this point there may still be unhashed data left in the \n\t   buffer.  It won't have been hashed yet because the hashing is \n\t   performed when the data is copied out, after unwrapping and \n\t   deblocking and whatnot, so we hash it before we wrap up the \n\t   hashing (the exception to this is authenticated encrypted data which\n\t   is MACd before decryption, but that's handled internally by the data-\n\t   decoding process) */\n\tif( envelopeInfoPtr->dataLeft > 0 )\n\t\t{\n\t\tint status;\n\n\t\tstatus = processExtraDataFunction( envelopeInfoPtr, \n\t\t\t\t\t\tenvelopeInfoPtr->buffer, envelopeInfoPtr->dataLeft );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Wrap up the hashing */\n\treturn( processExtraDataFunction( envelopeInfoPtr, \"\", 0 ) );\n\t}\n\n/* Process the signed data trailer */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processSignedTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT_ENUM( DEENVSTATE ) DEENV_STATE *state,\n\t\t\t\t\t\t\t\t const BOOLEAN isFlush )\n\t{\n\tDEENV_STATE newState;\n\tint tag, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( state, sizeof( DEENV_STATE ) ) );\n\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\n\t/* Read the SignedData EOC's if necessary */\n\tstatus = processPayloadEOCs( envelopeInfoPtr, stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( checkSoftError( status, isFlush ) ? \\\n\t\t\t\tOK_SPECIAL : status );\n\t\t}\n\n\t/* Check whether there's a certificate chain to follow */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( checkSoftError( status, isFlush ) ? \\\n\t\t\t\tOK_SPECIAL : status );\n\t\t}\n\tnewState = ( tag == MAKE_CTAG( 0 ) ) ? \\\n\t\t\t   DEENVSTATE_CERTSET : DEENVSTATE_SET_SIG;\n\n\t/* If we've seen all of the signed data, complete the hashing */\n\tif( !TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t{\n\t\tstatus = completePayloadProcessing( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Move on to the next state */\n\t*state = newState;\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the MACd data trailer.  Note that some data-formatting errors \n   encountered at this level may be converted into an authentication-failure \n   status by the calling code to avoid truncation attacks, see the comment\n   in processPostable() for more details */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processMacTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT_BOOL BOOLEAN *failedMAC,\n\t\t\t\t\t\t\t  const BOOLEAN isFlush )\n\t{\n\tACTION_LIST *actionListPtr;\n\tMESSAGE_DATA msgData;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( failedMAC, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\n\t/* Clear return value */\n\t*failedMAC = FALSE;\n\n\t/* Read the AuthenticatedData EOCs if necessary */\n\tstatus = processPayloadEOCs( envelopeInfoPtr, stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( checkSoftError( status, isFlush ) ? \\\n\t\t\t\tOK_SPECIAL : status );\n\t\t}\n\n\t/* Read the MAC value that follows the payload */\n\tstatus = readOctetString( stream, hash, &hashSize, MIN_HASHSIZE, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( checkSoftError( status, isFlush ) ? \\\n\t\t\t\tOK_SPECIAL : status );\n\t\t}\n\n\t/* Complete the payload processing and compare the read MAC value with \n\t   the calculated one */\n\tstatus = completePayloadProcessing( envelopeInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, hash, hashSize );\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC );\n\tENSURES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_HASH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Unlike signatures a failed MAC check (reported as a CRYPT_ERROR\n\t\t   comparison result) is detected immediately rather than after the\n\t\t   payload processing has completed.  However if we bail out now \n\t\t   then any later checks of things like signature metadata will fail \n\t\t   because the envelope regards processing as still being incomplete \n\t\t   so we have to continue processing data until we at least get the \n\t\t   envelope to the finished state */\n\t\tassert( status == CRYPT_ERROR );\n\t\t*failedMAC = TRUE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process any remaining EOCs.  This gets a bit complicated because there \n   can be a variable number of EOCs depending on where definite and \n   indefinite encodings were used so we look for at least one EOC and at \n   most a number that depends on the data type being processed */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processEOCTrailer( const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t\t  const BOOLEAN isFlush )\n\t{\n\tint noEOCs, i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\n\t/* Consume any EOCs up to the maximum amount possible.  In theory we \n\t   could be rather liberal with trailing EOCs since it's not really \n\t   necessary for the caller to push in every last one, however if we\n\t   assume that seeing at least one EOC is enough to signal the end of\n\t   all content this can lead to problems if adding the EOCs occurs\n\t   over a pushData boundary.  What can happen here is that the code will \n\t   see the start of the string of EOCs on the first push, record the \n\t   end-of-data-reached state, and then report a CRYPT_ERROR_COMPLETE \n\t   when the remainder of the string of EOCs are pushed the next time\n\t   round.  To avoid this problem we have to be pedantic and require\n\t   that callers push all EOCs */\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_NONE:\n\t\t\tnoEOCs = 2;\n\t\t\tbreak;\n\n\t\tcase ACTION_CRYPT:\n\t\t\t/* Authenticated encryption is a special case since there's a \n\t\t\t   MAC value present after the data, which means that we've \n\t\t\t   already consumed two of the four EOCs present at the end of \n\t\t\t   encrypted data in getting to the MAC value */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t\tnoEOCs = 2;\n\t\t\telse\n\t\t\t\tnoEOCs = 4;\n\t\t\tbreak;\n\n\t\tcase ACTION_SIGN:\n\t\tcase ACTION_MAC:\n\t\t\tnoEOCs = 3;\n\t\t\tbreak;\n\n\t\tcase ACTION_COMPRESS:\n\t\t\tnoEOCs = 5;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tLOOP_SMALL( i = 0, i < noEOCs, i++ )\n\t\t{\n\t\tconst int value = checkEOC( stream );\n\t\tif( cryptStatusError( value ) )\n\t\t\t{\n\t\t\treturn( checkSoftError( value, isFlush ) ? \\\n\t\t\t\t\tOK_SPECIAL : value );\n\t\t\t}\n\t\tif( value == FALSE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tProcess Envelope Preamble/Postamble\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the non-data portions of an envelope.  This is a complex event-\n   driven state machine, but instead of reading along a (hypothetical\n   Turing-machine) tape someone has taken the tape and cut it into bits and\n   keeps feeding them to us and saying \"See what you can do with this\" (and\n   occasionally \"Where's the bloody spoons?\").  The following code implements\n   this state machine:\n\n\t\t\tKeyex / MAC / XXXX\n\tNONE ----------------------------------------> SET_ENCR \n\t\t\t\t\t\t\t\t\t\t\t\t\t  |\n\t\t\t\t\t\t\t\t\t\t\t\t\t  v\n\t\t\tSign\t\t\t\t+------------------ ENCR <----+\n\t\t --------> SET_HASH\t\t|\t\t\t\t\t  | |Keyex|\t\n\t\t\t\t\t\t|\t\t|\t\t\t\t\t  |\t+-----+\n\t\t\t\t\t\t|\t\t|(MAC)\t\t\t\t  |(Non-MAC)\n\t\t\tSessionkey\t|\t\t|\t\t\t\t\t  v\n\t\t --------------------------------------> ENCRCONTENT\n\t\t\t\t\t\t|\t\t|\t\t\t\t\t  |\t\n\t\t\t\t\t\tv\t\t|\t\t\t\t\t  |\n\t\t\t\t+----> HASH\t   MAC\t\t\t\t\t  |\n\t\t\t\t|Hash |\t|\t\t|\t\t\t\t\t  |\n\t\t\t\t+-----+\t|\t\t|\t\t\t\t\t  |\n\t\t\t\t\t\t \\\t   /\t\t\t\t\t  |\n\t\t\tCopr.\t\t  v\t  v\t\t\t\t\t\t  |\n\t\t --------------> CONTENT\t\t\t\t\t  |\n\t\t\t\t\t\t\t+-------+\t+-------------+\n\t\t\t\t\t\t\t\t\t|\t|\n\t\t\tData\t\t\t\t\tv\tv\n\t\t -------------------------> DATA\n\t\t\t\t\t\t\t\t\t  |\n\t\t\t\t\t\t\t\t\t  v\n\t\t\t\t\t\t\t\t\tDONE\n\n\tIf type == Sign and detached-sig, CONTENT transitions directly to DONE */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tDEENV_STATE state = envelopeInfoPtr->deenvState;\n\tSTREAM stream;\n\tint remainder, streamPos = 0, noHeaderItems;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckEnvCMSDenv( envelopeInfoPtr ) );\n\n\tsMemConnect( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufPos );\n\n\t/* If we haven't started doing anything yet try and read the outer\n\t   header fields */\n\tif( state == DEENVSTATE_NONE )\n\t\t{\n\t\tstatus = processEnvelopeHeader( envelopeInfoPtr, &stream, &state );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Invalid CMS envelope header\" ) );\n\t\t\t}\n\n\t\t/* Remember how far we got */\n\t\tstreamPos = stell( &stream );\n\t\t}\n\n\t/* Keep consuming information until we either run out of input or reach \n\t   the data payload.  The limit of MAX_DATA_ITEMS header items would \n\t   never occur in any normal usage but in theory it's possible to \n\t   generate S/MIME messages with large numbers of recipients for mailing \n\t   lists so we set the limit at MAX_DATA_ITEMS */\n\tstatic_assert( MAX_DATA_ITEMS < FAILSAFE_ITERATIONS_MED, \\\n\t\t\t\t   \"MAX_DATA_ITEMS\" );\n\tLOOP_MED( noHeaderItems = 0, \n\t\t\t  cryptStatusOK( status ) && state != DEENVSTATE_DONE && \\\n\t\t\t\t\tnoHeaderItems < MAX_DATA_ITEMS, \n\t\t\t  noHeaderItems++ )\n\t\t{\n\t\tswitch( state )\n\t\t\t{\n\t\t\t/* Read the start of the SET OF RecipientInfo/SET OF \n\t\t\t   DigestAlgorithmIdentifier */\n\t\t\tcase DEENVSTATE_SET_ENCR:\n\t\t\t\t{\n\t\t\t\tlong setLongLength;\n\n\t\t\t\t/* Read the SET tag and length.  We have to read the length \n\t\t\t\t   as a long value in order to handle cases where there's a \n\t\t\t\t   large amount of key management data involving a great \n\t\t\t\t   many recipients */\n\t\t\t\tstatus = readLongSet( &stream, &setLongLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid SET OF RecipientInfo header\", 35 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tenvelopeInfoPtr->hdrSetLength = setLongLength;\n\n\t\t\t\t/* Remember where we are and move on to the next state.  \n\t\t\t\t   Some implementations use the indefinite-length encoding \n\t\t\t\t   for this so if there's no length given (setLength == \n\t\t\t\t   CRYPT_UNUSED) we have to look for the EOC after each \n\t\t\t\t   entry read */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = DEENVSTATE_ENCR;\n\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase DEENVSTATE_SET_HASH:\n\t\t\t\t{\n\t\t\t\tint setLength;\n\n\t\t\t\t/* Read the SET tag and length */\n\t\t\t\tstatus = readSetI( &stream, &setLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid SET OF DigestAlgorithmIdentifier \"\n\t\t\t\t\t\t\t\t\t\"header\", 47 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( setLength <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\t/* There are numerous garbled interpretations of what \n\t\t\t\t\t   constitutes a PKCS #7 certificate chain (empty SET OF \n\t\t\t\t\t   DigestAlgorithmIdentifier + PKCS#7 data OID is the\n\t\t\t\t\t   correct one, but there are also ones with a nonempty \n\t\t\t\t\t   SET OF DigestAlgorithmIdentifier or with the data \n\t\t\t\t\t   being present as a zero-length OCTET STRING).  If we \n\t\t\t\t\t   find an empty SET OF DigestAlgorithmIdentifier then \n\t\t\t\t\t   we warn that this probably isn't meant to be signed \n\t\t\t\t\t   data, for the rest there's not much that we can do */\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"SET OF DigestAlgorithmIdentifier is \"\n\t\t\t\t\t\t\t\t\t\"empty, is this a raw certificate \"\n\t\t\t\t\t\t\t\t\t\"chain?\", 75 );\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tenvelopeInfoPtr->hdrSetLength = setLength;\n\n\t\t\t\t/* Remember where we are and move on to the next state.  \n\t\t\t\t   Some implementations use the indefinite-length encoding \n\t\t\t\t   for this so if there's no length given (setLength == \n\t\t\t\t   CRYPT_UNUSED) we have to look for the EOC after each \n\t\t\t\t   entry read */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = DEENVSTATE_HASH;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Read and remember a key exchange object from an \n\t\t\t   EncryptionKeyInfo record */\n\t\t\tcase DEENVSTATE_ENCR:\n\t\t\t\t{\n\t\t\t\tint contentItemLength;\n\n\t\t\t\t/* Add the object to the content information list */\n\t\t\t\tstatus = addContentListItem( envelopeInfoPtr, &stream, NULL, \n\t\t\t\t\t\t\t\t\t\t\t &contentItemLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid EncryptionKeyInfo key exchange \"\n\t\t\t\t\t\t\t\t\t\"record\", 45 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state if\n\t\t\t\t   necessary */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tif( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )\n\t\t\t\t\t{\n\t\t\t\t\tif( contentItemLength > envelopeInfoPtr->hdrSetLength )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tenvelopeInfoPtr->hdrSetLength -= contentItemLength;\n\t\t\t\t\tif( envelopeInfoPtr->hdrSetLength <= 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstate = ( envelopeInfoPtr->usage == ACTION_MAC ) ? \\\n\t\t\t\t\t\t\t\tDEENVSTATE_MAC : DEENVSTATE_ENCRCONTENT;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tconst int value = checkEOC( &stream );\n\t\t\t\t\tif( cryptStatusError( value ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tif( value == TRUE )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstate = ( envelopeInfoPtr->usage == ACTION_MAC ) ? \\\n\t\t\t\t\t\t\t\tDEENVSTATE_MAC : DEENVSTATE_ENCRCONTENT;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Read the encrypted content information */\n\t\t\tcase DEENVSTATE_ENCRCONTENT:\n\t\t\t\tstatus = processEncryptionHeader( envelopeInfoPtr, &stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* We may get non-data-related errors like \n\t\t\t\t\t   CRYPT_ERROR_WRONGKEY so we only set extended error \n\t\t\t\t\t   information if it's a data-related error */\n\t\t\t\t\tif( isDataError( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\t\"Invalid encrypted content header\", 32 );\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = DEENVSTATE_DATA;\n\t\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\t\t\t\tif( DATAPTR_ISNULL( envelopeInfoPtr->actionList ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we haven't got a session key to decrypt the data \n\t\t\t\t\t   that follows then we can't go beyond this point */\n\t\t\t\t\tstatus = CRYPT_ENVELOPE_RESOURCE;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Read and remember a MAC object from a MACAlgorithmIdentifier\n\t\t\t   record */\n\t\t\tcase DEENVSTATE_MAC:\n\t\t\t\tstatus = processHashHeader( envelopeInfoPtr, &stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid MACd content header\", 27 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = DEENVSTATE_CONTENT;\n\t\t\t\tbreak;\n\n\t\t\t/* Read and remember a hash object from a \n\t\t\t   DigestAlgorithmIdentifier record */\n\t\t\tcase DEENVSTATE_HASH:\n\t\t\t\tstatus = processHashHeader( envelopeInfoPtr, &stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid hashed content header\", 29 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state if\n\t\t\t\t   necessary */\n\t\t\t\tif( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )\n\t\t\t\t\t{\n\t\t\t\t\tconst int hashInfoLength = stell( &stream ) - streamPos;\n\t\t\t\t\tif( hashInfoLength < 0 || \\\n\t\t\t\t\t\thashInfoLength > envelopeInfoPtr->hdrSetLength )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tenvelopeInfoPtr->hdrSetLength -= hashInfoLength;\n\t\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\t\tif( envelopeInfoPtr->hdrSetLength <= 0 )\n\t\t\t\t\t\tstate = DEENVSTATE_CONTENT;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tconst int value = checkEOC( &stream );\n\t\t\t\t\tif( cryptStatusError( value ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tif( value == TRUE )\n\t\t\t\t\t\tstate = DEENVSTATE_CONTENT;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/* Read the encapsulated content header */\n\t\t\tcase DEENVSTATE_CONTENT:\n\t\t\t\t{\n\t\t\t\tint contentType;\n\n\t\t\t\tstatus = \\\n\t\t\t\t\treadCMSheader( &stream, nestedContentOIDinfo,\n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( nestedContentOIDinfo, \n\t\t\t\t\t\t\t\t\t\t\t\t\t   OID_INFO ),\n\t\t\t\t\t\t\t\t   &contentType, &envelopeInfoPtr->payloadSize, \n\t\t\t\t\t\t\t\t   READCMS_FLAG_INNERHEADER );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid encapsulated content header\", 35 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tenvelopeInfoPtr->contentType = contentType;\n\n\t\t\t\t/* If there's no content included and it's not an attributes-\n\t\t\t\t   only message then this is a detached signature with the \n\t\t\t\t   content supplied anderswhere */\n\t\t\t\tif( envelopeInfoPtr->payloadSize == 0 && \\\n\t\t\t\t\t!TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\tENVELOPE_FLAG_ATTRONLY ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t  ENVELOPE_FLAG_DETACHED_SIG );\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = ( envelopeInfoPtr->payloadSize == 0 && \\\n\t\t\t\t\t\t  TEST_FLAG( envelopeInfoPtr->flags,\n\t\t\t\t\t\t\t\t\t ENVELOPE_FLAG_DETACHED_SIG | \\\n\t\t\t\t\t\t\t\t\t ENVELOPE_FLAG_ATTRONLY ) ) ? \\\n\t\t\t\t\t\tDEENVSTATE_DONE : DEENVSTATE_DATA;\n\n\t\t\t\t/* If this is MACd data and we haven't loaded a key to MAC \n\t\t\t\t   the data that follows then we can't go beyond this point */\n\t\t\t\tif( envelopeInfoPtr->usage == ACTION_MAC )\n\t\t\t\t\t{\n\t\t\t\t\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\n\t\t\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\t\t\t\t\tif( actionListPtr == NULL )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = CRYPT_ENVELOPE_RESOURCE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\tREQUIRES( actionListPtr->action == ACTION_MAC );\n\t\t\t\t\tif( !checkContextCapability( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_MAC ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = CRYPT_ENVELOPE_RESOURCE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Start the decryption process if necessary */\n\t\t\tcase DEENVSTATE_DATA:\n\t\t\t\t{\n\t\t\t\tconst ENV_SYNCDEENVELOPEDATA_FUNCTION syncDeenvelopeDataFunction = \\\n\t\t\t\t\t\t( ENV_SYNCDEENVELOPEDATA_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->syncDeenvelopeDataFunction );\n\n\t\t\t\tREQUIRES( syncDeenvelopeDataFunction != NULL );\n\n\t\t\t\t/* Synchronise the data stream processing to the start of \n\t\t\t\t   the encrypted data and move back to the start of the data\n\t\t\t\t   stream */\n\t\t\t\tstatus = syncDeenvelopeDataFunction( envelopeInfoPtr, &stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we get a CRYPT_ERROR_SIGNATURE at this point then \n\t\t\t\t\t   it's because we're using authenticated encryption and \n\t\t\t\t\t   data corruption was detected via a mechanism like a \n\t\t\t\t\t   block padding check failure long before we get to the \n\t\t\t\t\t   MAC verification stage, in which case we pass the \n\t\t\t\t\t   error on up unaltered */\n\t\t\t\t\tif( status == CRYPT_ERROR_SIGNATURE )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Decrypted data corruption detected, \"\n\t\t\t\t\t\t\t\t\t\"block padding check failed\", 62 );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Couldn't synchronise envelope state \"\n\t\t\t\t\t\t\t\t\t\"prior to data payload processing\", 68 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* The data has now been resynchronised with the start of \n\t\t\t\t   stream, and we're done */\n\t\t\t\tstreamPos = 0;\t\n\t\t\t\tstate = DEENVSTATE_DONE;\n\n\t\t\t\tENSURES( checkActions( envelopeInfoPtr ) );\n\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\tif( noHeaderItems >= MAX_DATA_ITEMS )\n\t\t{\n\t\t/* Technically this would be an overflow but that's a recoverable\n\t\t   error so we make it a BADDATA, which is really what it is */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO, \n\t\t\t\t  \"Encountered more than %d envelope header items\",\n\t\t\t\t  noHeaderItems ) );\n\t\t}\n\tenvelopeInfoPtr->deenvState = state;\n\n\t/* At this point we may have a success or an error status, but we need \n\t   to continue with cleanup functions before we exit on error */\n\n\tENSURES( streamPos >= 0 && streamPos < MAX_BUFFER_SIZE && \\\n\t\t\t envelopeInfoPtr->bufPos - streamPos >= 0 );\n\n\t/* Consume the input that we've processed so far by moving everything \n\t   past the current position down to the start of the envelope buffer */\n\tremainder = envelopeInfoPtr->bufPos - streamPos;\n\tREQUIRES( remainder >= 0 && remainder < MAX_BUFFER_SIZE && \\\n\t\t\t  streamPos + remainder <= envelopeInfoPtr->bufSize );\n\tif( remainder > 0 && streamPos > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( streamPos, remainder, \n\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\n\t\tmemmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + streamPos,\n\t\t\t\t remainder );\n\t\t}\n\tenvelopeInfoPtr->bufPos = remainder;\n\tENSURES( sanityCheckEnvCMSDenv( envelopeInfoPtr ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If all went OK but we're still not out of the header information,\n\t   return an underflow error */\n\treturn( ( state != DEENVSTATE_DONE ) ? \\\n\t\t\tCRYPT_ERROR_UNDERFLOW : CRYPT_OK );\n\t}\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t const BOOLEAN isFlush )\n\t{\n\tDEENV_STATE state = envelopeInfoPtr->deenvState;\n\tSTREAM stream;\n\tBOOLEAN failedMAC = FALSE;\n\tint remainder, streamPos = 0, noTrailerItems;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvCMSDenv( envelopeInfoPtr ) );\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\n\t/* If that's all that there is, return */\n\tif( state == DEENVSTATE_NONE && \\\n\t\t!( envelopeInfoPtr->usage == ACTION_SIGN || \\\n\t\t   envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t   ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t TEST_FLAG( envelopeInfoPtr->flags, \\\n\t\t\t\t\t\tENVELOPE_FLAG_AUTHENC ) ) ) && \\\n\t\tenvelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\t{\n\t\t/* Definite-length data with no trailer, there's nothing left to \n\t\t   process */\n\t\tenvelopeInfoPtr->deenvState = DEENVSTATE_DONE;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's not enough data left in the stream to do anything, don't \n\t   try and go any further */\n\tif( envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft < 2 )\n\t\t{\n\t\treturn( checkSoftError( CRYPT_ERROR_UNDERFLOW, isFlush ) ? \\\n\t\t\t\tOK_SPECIAL : CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\t/* Start reading the trailer data from the end of the payload */\n\tsMemConnect( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,\n\t\t\t\t envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft );\n\n\t/* If we haven't started doing anything yet figure out what we should be\n\t   looking for */\n\tif( state == DEENVSTATE_NONE )\n\t\t{\n\t\tswitch( envelopeInfoPtr->usage )\n\t\t\t{\n\t\t\tcase ACTION_SIGN:\n\t\t\t\tstatus = processSignedTrailer( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t\t   &state, isFlush );\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_CRYPT:\n\t\t\t\t/* If it's conventional encrypted data, just look for EOCs */\n\t\t\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\tENVELOPE_FLAG_AUTHENC ) )\n\t\t\t\t\t{\n\t\t\t\t\tstate = DEENVSTATE_EOC;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t/* Fall through for authenticated encrypted data */\n\t\t\t\tSTDC_FALLTHROUGH;\n\n\t\t\tcase ACTION_MAC:\n\t\t\t\t/* The error handling here gets a bit tricky in that an \n\t\t\t\t   attacker could truncate the data and turn a fatal\n\t\t\t\t   CRYPT_ERROR_SIGNATURE into a more benign \n\t\t\t\t   CRYPT_ERROR_UNDERFLOW, which may be ignored by the caller\n\t\t\t\t   if all of the payload data was successfully recovered.  \n\t\t\t\t   On the other hand this could be a genuine underflow with\n\t\t\t\t   the caller still to push in the MAC trailer data, so we\n\t\t\t\t   can't just unconditionally convert an underflow error \n\t\t\t\t   into a CRYPT_ERROR_SIGNATURE.  At best we can convert a\n\t\t\t\t   CRYPT_ERROR_BADDATA or an underflow (or indeed any kind\n\t\t\t\t   of error) on an explicit flush into a signature error, \n\t\t\t\t   but unfortunately we have to leave the \n\t\t\t\t   CRYPT_ERROR_UNDERFLOW on a non-flush because we don't \n\t\t\t\t   know whether the caller has more data to push.  Note that \n\t\t\t\t   this differs from the failedMAC == TRUE behaviour in that \n\t\t\t\t   we return the signature error immediately, since we can't \n\t\t\t\t   go any further as we could for a pure MAC failure with \n\t\t\t\t   the data-processing state still OK */\n\t\t\t\tstatus = processMacTrailer( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t\t&failedMAC, isFlush );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tif( isFlush || status == CRYPT_ERROR_BADDATA )\n\t\t\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tstate = \\\n\t\t\t\t\t\t( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\tDEENVSTATE_EOC : DEENVSTATE_DONE;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/* Just look for EOCs */\n\t\t\t\tstate = DEENVSTATE_EOC;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\t/* If we got an explicit soft-fail error status, let the \n\t\t\t\t   caller know */\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Invalid CMS signed/MACd data trailer\" ) );\n\t\t\t}\n\n\t\t/* Remember how far we got */\n\t\tstreamPos = stell( &stream );\n\t\t}\n\n\t/* Keep consuming information until we run out of input or reach the end\n\t   of the data */\n\tLOOP_MED( noTrailerItems = 0,\n\t\t\t  state != DEENVSTATE_DONE && noTrailerItems < MAX_DATA_ITEMS,\n\t\t\t  noTrailerItems++ )\n\t\t{\n\t\t/* Read the certificate chain */\n\t\tif( state == DEENVSTATE_CERTSET )\n\t\t\t{\n\t\t\tint certSetLength;\n\n\t\t\t/* Read the certificate chain into the auxiliary buffer.  We \n\t\t\t   can't import it yet at this point because we need the \n\t\t\t   SignerInfo to definitively identify the leaf certificate.  \n\t\t\t   Usually there's only one leaf but there will be more than one \n\t\t\t   if there are multiple signatures present or if the sending \n\t\t\t   application decides to shovel in assorted (non-relevant) \n\t\t\t   certificates */\n\t\t\tstatus = getStreamObjectLength( &stream, &certSetLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( checkSoftError( status, isFlush ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = OK_SPECIAL;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\"Invalid signing certificate chain header\", \n\t\t\t\t\t\t\t\t40 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( sMemDataLeft( &stream ) < certSetLength && \\\n\t\t\t\tcheckSoftError( CRYPT_ERROR_UNDERFLOW, isFlush ) )\n\t\t\t\t{\n\t\t\t\tstatus = OK_SPECIAL;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( envelopeInfoPtr->auxBuffer == NULL )\n\t\t\t\t{\n\t\t\t\t/* Allocate a buffer for the certificate chain if necessary.  \n\t\t\t\t   This may already be allocated if the previous attempt to \n\t\t\t\t   read the chain failed due to there being insufficient \n\t\t\t\t   data in the envelope buffer, so we make it conditional on\n\t\t\t\t   the buffer being NULL */\n\t\t\t\tREQUIRES( rangeCheck( certSetLength, 1, MAX_INTLENGTH_SHORT ) );\n\t\t\t\tif( ( envelopeInfoPtr->auxBuffer = \\\n\t\t\t\t\t\tclAlloc( \"processPostamble\", certSetLength ) ) == NULL )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = CRYPT_ERROR_MEMORY;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tenvelopeInfoPtr->auxBufSize = certSetLength;\n\t\t\t\t}\n\t\t\tENSURES( envelopeInfoPtr->auxBufSize == certSetLength );\n\t\t\tstatus = sread( &stream, envelopeInfoPtr->auxBuffer,\n\t\t\t\t\t\t\tenvelopeInfoPtr->auxBufSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\n\t\t\t/* Remember where we are and move on to the next state */\n\t\t\tstreamPos = stell( &stream );\n\t\t\tstate = DEENVSTATE_SET_SIG;\n\t\t\t}\n\n\t\t/* Read the start of the SET OF Signature */\n\t\tif( state == DEENVSTATE_SET_SIG )\n\t\t\t{\n\t\t\tint setLength;\n\n\t\t\t/* Read the SET tag and length */\n\t\t\tstatus = readSetI( &stream, &setLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( checkSoftError( status, isFlush ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = OK_SPECIAL;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\"Invalid SET OF Signature header\", 31 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tenvelopeInfoPtr->hdrSetLength = setLength;\n\n\t\t\t/* Remember where we are and move on to the next state.  Some\n\t\t\t   implementations use the indefinite-length encoding for this so\n\t\t\t   if there's no length given then we have to look for the EOC \n\t\t\t   after each entry read */\n\t\t\tstreamPos = stell( &stream );\n\t\t\tstate = DEENVSTATE_SIG;\n\t\t\t}\n\n\t\t/* Read and remember a signature object from a Signature record */\n\t\tif( state == DEENVSTATE_SIG )\n\t\t\t{\n\t\t\tint contentItemLength;\n\n\t\t\t/* If it's a standard data push, make sure that there's enough \n\t\t\t   data left to continue.  Checking at this point means that we \n\t\t\t   can provide special-case soft-error handling before we try \n\t\t\t   and read the signature data in addContentListItem() */\n\t\t\tif( sMemDataLeft( &stream ) < envelopeInfoPtr->hdrSetLength && \\\n\t\t\t\tcheckSoftError( CRYPT_ERROR_UNDERFLOW, isFlush ) )\n\t\t\t\t{\n\t\t\t\tstatus = OK_SPECIAL;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Add the object to the content information list */\n\t\t\tstatus = addContentListItem( envelopeInfoPtr, &stream, NULL,\n\t\t\t\t\t\t\t\t\t\t &contentItemLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\"Invalid CMS signature record\", 28 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Remember where we are and move on to the next state if\n\t\t\t   necessary */\n\t\t\tstreamPos = stell( &stream );\n\t\t\tif( envelopeInfoPtr->hdrSetLength != CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\tif( contentItemLength < 0 || \\\n\t\t\t\t\tcontentItemLength > envelopeInfoPtr->hdrSetLength )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tenvelopeInfoPtr->hdrSetLength -= contentItemLength;\n\t\t\t\tif( envelopeInfoPtr->hdrSetLength <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstate = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\tDEENVSTATE_EOC : DEENVSTATE_DONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst int value = checkEOC( &stream );\n\t\t\t\tif( cryptStatusError( value ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = value;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( value == TRUE )\n\t\t\t\t\t{\n\t\t\t\t\tstate = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\tDEENVSTATE_EOC : DEENVSTATE_DONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Handle end-of-contents octets */\n\t\tif( state == DEENVSTATE_EOC )\n\t\t\t{\n\t\t\tstatus = processEOCTrailer( envelopeInfoPtr, &stream, isFlush );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we got an explicit soft-fail error status then we \n\t\t\t\t\t   treat it as a standard data push with status == \n\t\t\t\t\t   CRYPT_OK and the byte count indicating how much data \n\t\t\t\t\t   was copied in */\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\"Invalid CMS EOC trailer\", 23 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* We're done */\n\t\t\tstreamPos = stell( &stream );\n\t\t\tstate = DEENVSTATE_DONE;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\tif( noTrailerItems >= MAX_DATA_ITEMS )\n\t\t{\n\t\t/* We can only go once through the loop on a MAC check so we \n\t\t   shouldn't get here with a failed MAC */\n\t\tENSURES( !failedMAC );\n\n\t\t/* Technically this would be an overflow but that's a recoverable\n\t\t   error so we make it a BADDATA, which is really what it is */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO, \n\t\t\t\t  \"Encountered more than %d envelope trailer items\",\n\t\t\t\t  noTrailerItems ) );\n\t\t}\n\tenvelopeInfoPtr->deenvState = state;\n\tENSURES( streamPos >= 0 && streamPos < MAX_BUFFER_SIZE );\n\n\t/* Consume the input that we've processed so far by moving everything \n\t   past the current position down to the start of the memory buffer:\n\n\t\t\t\t\t\t\t\t\t bufPos\n\t\t\t\t\t\t\t\t\t\t| bufSize\n\t\t\t\t\t\t\t\t\t\tv\tv\n\t\t+-----------+-------+-----------+---+\n\t\t|  dataLeft\t|\t\t|\t\t\t|\t|\n\t\t+-----------+-------+-----------+---+\n\t\t\t\t\t|<--+-->|<-- rem -->|\n\t\t\t\t\t\t|\n\t\t\t\t\tstreamPos */\n\tremainder = envelopeInfoPtr->bufPos - \\\n\t\t\t\t( envelopeInfoPtr->dataLeft + streamPos );\n\tREQUIRES( remainder >= 0 && remainder < MAX_BUFFER_SIZE && \\\n\t\t\t  envelopeInfoPtr->dataLeft + streamPos + \\\n\t\t\t\t\tremainder <= envelopeInfoPtr->bufPos );\n\tif( remainder > 0 && streamPos > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( envelopeInfoPtr->dataLeft + streamPos,\n\t\t\t\t\t\t\t   remainder, envelopeInfoPtr->bufPos ) );\n\t\tmemmove( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,\n\t\t\t\t envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft + streamPos,\n\t\t\t\t remainder );\n\t\t}\n\tenvelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + remainder;\n\tENSURES( sanityCheckEnvCMSDenv( envelopeInfoPtr ) );\n\tif( failedMAC )\n\t\t{\n\t\t/* If the MAC check failed then this overrides any other status */\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO, \n\t\t\t\t  \"MAC value doesn't match calculated MAC\" ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If all went OK but we're still not out of the header information, \n\t   return an underflow error */\n\treturn( ( state != DEENVSTATE_DONE ) ? CRYPT_ERROR_UNDERFLOW : CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMSDeenveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_V( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->processPreambleFunction, processPreamble );\n\tFNPTR_SET( envelopeInfoPtr->processPostambleFunction, processPostamble );\n\tFNPTR_SET( envelopeInfoPtr->checkAlgoFunction, cmsCheckAlgo );\n\n\t/* Set up the processing state information */\n\tenvelopeInfoPtr->deenvState = DEENVSTATE_NONE;\n\t}\n#endif /* USE_CMS */\n"
  },
  {
    "path": "deps/cl345/envelope/cms_env.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib CMS Enveloping Routines\t\t\t\t\t*\n*\t\t\t\t\t    Copyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckEnvCMSEnv( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckEnvelope( envelopeInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvCMSEnv: Envelope check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that general envelope state is in order */\n\tif( envelopeInfoPtr->type != CRYPT_FORMAT_CRYPTLIB && \\\n\t\tenvelopeInfoPtr->type != CRYPT_FORMAT_CMS && \\\n\t\tenvelopeInfoPtr->type != CRYPT_FORMAT_SMIME )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvCMSEnv: Type\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvCMSEnv: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that a requested algorithm type is valid with enveloped data */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN cmsCheckAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t  IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode )\n\t{\n\tREQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && \\\n\t\t\t\tcryptAlgo < CRYPT_ALGO_LAST_EXTERNAL );\n\tREQUIRES_B( isEnumRangeOpt( cryptMode, CRYPT_MODE ) );\n\n\treturn( checkAlgoID( cryptAlgo, cryptMode ) );\n\t}\n\n/* Retrieve the principal context type from the envelope's action list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getActionContext( const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_CRYPT:\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_xxx );\n\t\t\telse\n\t\t\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_CRYPT );\n\t\t\tbreak;\n\n\t\tcase ACTION_MAC:\n\t\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t*iCryptContext = actionListPtr->iCryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the OID for a CMS content type.  If no type is explicitly given, we\n   assume raw data */\n\nstatic const OID_INFO contentOIDs[] = {\n\t{ OID_CMS_DATA, CRYPT_CONTENT_DATA },\n\t{ OID_CMS_SIGNEDDATA, CRYPT_CONTENT_SIGNEDDATA },\n\t{ OID_CMS_ENVELOPEDDATA, CRYPT_CONTENT_ENVELOPEDDATA },\n\t{ MKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x07\\x04\" ), CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA },\n\t{ OID_CMS_DIGESTEDDATA, CRYPT_CONTENT_DIGESTEDDATA },\n\t{ OID_CMS_ENCRYPTEDDATA, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t{ OID_CMS_COMPRESSEDDATA, CRYPT_CONTENT_COMPRESSEDDATA },\n\t{ OID_CMS_AUTHDATA, CRYPT_CONTENT_AUTHDATA },\n\t{ OID_CMS_AUTHENVDATA, CRYPT_CONTENT_AUTHENVDATA },\n\t{ OID_CMS_TSTOKEN, CRYPT_CONTENT_TSTINFO },\n\t{ OID_MS_SPCINDIRECTDATACONTEXT, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },\n\t{ OID_CRYPTLIB_RTCSREQ, CRYPT_CONTENT_RTCSREQUEST },\n\t{ OID_CRYPTLIB_RTCSRESP, CRYPT_CONTENT_RTCSRESPONSE },\n\t{ OID_CRYPTLIB_RTCSRESP_EXT, CRYPT_CONTENT_RTCSRESPONSE_EXT },\n\t{ MKOID( \"\\x06\\x06\\x67\\x81\\x08\\x01\\x01\\x01\" ), CRYPT_CONTENT_MRTD },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\nCHECK_RETVAL_PTR \\\nstatic const BYTE *getContentOID( IN_ENUM( CRYPT_CONTENT ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTENT_TYPE contentType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( contentType, CRYPT_CONTENT ) );\n\n\tLOOP_MED( i = 0, \n\t\t\t  contentOIDs[ i ].oid != NULL && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( contentOIDs, OID_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( contentOIDs[ i ].selectionID == contentType )\n\t\t\treturn( contentOIDs[ i ].oid );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\tretIntError_Null();\n\t}\n\n/* Copy as much post-data state information (i.e. signatures) from the\n   auxiliary buffer to the main buffer as possible */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyFromAuxBuffer( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint bytesCopied, dataLeft;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Copy as much of the signature data as we can across */\n\tbytesCopied = min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos,\n\t\t\t\t\t   envelopeInfoPtr->auxBufPos );\n\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, bytesCopied, \n\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\tmemcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,\n\t\t\tenvelopeInfoPtr->auxBuffer, bytesCopied );\n\tenvelopeInfoPtr->bufPos += bytesCopied;\n\n\t/* Since we're in the post-data state any necessary payload data \n\t   segmentation has been completed, however, the caller can't copy out \n\t   any post-payload data because it's past the end-of-segment position. \n\t   In order to allow the buffer to be emptied to make room for new data \n\t   from the auxBuffer we set the end-of-segment position to the end of \n\t   the new data */\n\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\n\t/* If there's anything left, move it down in the buffer */\n\tdataLeft = envelopeInfoPtr->auxBufPos - bytesCopied;\n\tif( dataLeft > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( bytesCopied, dataLeft, \n\t\t\t\t\t\t\t   envelopeInfoPtr->auxBufPos ) );\n\t\tmemmove( envelopeInfoPtr->auxBuffer, \n\t\t\t\t envelopeInfoPtr->auxBuffer + bytesCopied, dataLeft );\n\t\t}\n\tenvelopeInfoPtr->auxBufPos = dataLeft;\n\t\n\tENSURES( dataLeft >= 0 );\n\n\treturn( ( dataLeft > 0 ) ? CRYPT_ERROR_OVERFLOW : CRYPT_OK );\n\t}\n\n/* Write one or more indefinite-length end-of-contents indicators */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeEOCs( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t  IN_RANGE( 1, 8 ) const int count )\n\t{\n\tstatic const BYTE indefEOC[ 16 ] = \\\n\t\t\t\t\t\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t\t\t\t\t  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n\tconst int dataLeft = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;\n\tconst int eocLength = count * sizeofEOC();\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( count >= 1 && count <= 8 );\n\tREQUIRES( eocLength >= sizeofEOC() && \\\n\t\t\t  eocLength <= ( 8 * sizeofEOC() ) );\t/* Count = 1...8 */\n\n\tif( dataLeft < eocLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, eocLength, \n\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\tmemcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos, indefEOC,\n\t\t\teocLength );\n\tenvelopeInfoPtr->bufPos += eocLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEmit Content-Specific Headers\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the header fields that encapsulate any enveloped data:\n\n   SignedData/DigestedData */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeSignedDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t  const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t  const BOOLEAN isSignedData )\n\t{\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tACTION_LIST *actionListPtr;\n\tlong dataSize;\n\tint hashActionSize = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isSignedData == TRUE || isSignedData == FALSE );\n\tREQUIRES( contentOID != NULL );\n\n\t/* Determine the size of the hash actions */\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ), \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tint actionSize;\n\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = actionSize = \\\n\t\t\t\t\tsizeofContextAlgoID( actionListPtr->iCryptHandle, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thashActionSize += actionSize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( isShortIntegerRangeNZ( hashActionSize ) );\n\t\n\t/* Determine the size of the SignedData/DigestedData */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \\\n\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASINDEFTRAILER ) )\n\t\tdataSize = CRYPT_UNUSED;\n\telse\n\t\t{\n\t\t/* Determine the size of the content OID + content */\n\t\tdataSize = ( envelopeInfoPtr->payloadSize > 0 ) ? \\\n\t\t\tsizeofObject( sizeofObject( envelopeInfoPtr->payloadSize ) ) : 0;\n\t\tdataSize = sizeofObject( sizeofOID( contentOID ) + dataSize );\n\n\t\t/* Determine the size of the version, hash algoID, content, \n\t\t   certificate chain, and signatures */\n\t\tdataSize = sizeofShortInteger( 1 ) + sizeofObject( hashActionSize ) + \\\n\t\t\t\t   dataSize + envelopeInfoPtr->extraDataSize + \\\n\t\t\t\t   sizeofObject( envelopeInfoPtr->signActionSize );\n\t\t}\n\tENSURES( dataSize == CRYPT_UNUSED || \\\n\t\t\t   ( dataSize >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\t dataSize < MAX_BUFFER_SIZE ) );\n\n\t/* Write the SignedData/DigestedData header, version number, and SET OF\n\t   DigestInfo */\n\tif( isSignedData )\n\t\t{\n\t\tstatus = writeCMSheader( stream, OID_CMS_SIGNEDDATA, \n\t\t\t\t\t\t\t\t sizeofOID( OID_CMS_SIGNEDDATA ), \n\t\t\t\t\t\t\t\t dataSize, FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeCMSheader( stream, OID_CMS_DIGESTEDDATA, \n\t\t\t\t\t\t\t\t sizeofOID( OID_CMS_DIGESTEDDATA ), \n\t\t\t\t\t\t\t\t dataSize, FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA )\n\t\t{\n\t\t/* If the encapsulated content-type isn't Data, the version number\n\t\t   is 3 rather than 1 (no known implementation actually pays any \n\t\t   attention to this, but the spec requires it so we may as well do\n\t\t   it) */\n\t\twriteShortInteger( stream, 3, DEFAULT_TAG );\n\t\t}\n\telse\n\t\twriteShortInteger( stream, 1, DEFAULT_TAG );\n\twriteSet( stream, hashActionSize );\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ), \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = writeContextAlgoID( stream, actionListPtr->iCryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Write the inner Data header */\n\treturn( writeCMSheader( stream, contentOID, sizeofOID( contentOID ), \n\t\t\t\t\t\t\tenvelopeInfoPtr->payloadSize, TRUE ) );\n\t}\n\n/* EncryptedContentInfo contained within EnvelopedData.  This may also be \n   Authenticated or AuthEnc data so the encryption context can be \n   CRYPT_UNUSED */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getBlockedPayloadSize( IN_LENGTH_INDEF const long payloadSize, \n\t\t\t\t\t\t\t\t  IN_LENGTH_IV const int blockSize,\n\t\t\t\t\t\t\t\t  OUT_LENGTH_INDEF long *blockedPayloadSize )\n\t{\n\tassert( isWritePtr( blockedPayloadSize, sizeof( long ) ) );\n\n\tREQUIRES( payloadSize == CRYPT_UNUSED || \\\n\t\t\t  isIntegerRangeNZ( payloadSize ) );\n\tREQUIRES( blockSize >= 1 && blockSize <= CRYPT_MAX_IVSIZE );\n\n\t/* Clear return value */\n\t*blockedPayloadSize = 0;\n\n\t/* If it's an indefinite length payload the blocked size is also of \n\t   indefinite length */\n\tif( payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\t*blockedPayloadSize = CRYPT_UNUSED;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a stream cipher there's no encryption blocking */\n\tif( blockSize <= 1 )\n\t\t{\n\t\t*blockedPayloadSize = payloadSize;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Calculate the size of the payload after PKCS #5 block padding.  This \n\t   isn't just the size rounded up to the nearest multiple of the block \n\t   size since if the size is already a multiple of the block size it \n\t   expands by another block, so we make the payload look one byte longer \n\t   before rounding to the block size to ensure the one-block expansion */\n\t*blockedPayloadSize = roundUp( payloadSize + 1, blockSize );\n\n\tENSURES( *blockedPayloadSize >= MIN_IVSIZE && \\\n\t\t\t *blockedPayloadSize <= payloadSize + CRYPT_MAX_IVSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeEncryptedContentHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\tIN_BUFFER( contentOIDlength ) const BYTE *contentOID, \n\t\t\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tIN_LENGTH_INDEF const long payloadSize, \n\t\t\t\t\t\t\tIN_LENGTH_IV const long blockSize )\n\t{\n\tlong blockedPayloadSize;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( contentOID, contentOIDlength ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) || \\\n\t\t\t  iCryptContext == CRYPT_UNUSED );\n\tREQUIRES( payloadSize == CRYPT_UNUSED || \\\n\t\t\t  isIntegerRangeNZ( payloadSize ) );\n\tREQUIRES( blockSize >= 1 && blockSize <= CRYPT_MAX_IVSIZE );\n\n\tstatus = getBlockedPayloadSize( payloadSize, blockSize, \n\t\t\t\t\t\t\t\t\t&blockedPayloadSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( writeCMSencrHeader( stream, contentOID, contentOIDlength,\n\t\t\t\t\t\t\t\tblockedPayloadSize, iCryptContext ) );\n\t}\n\n/* EncryptedData, EnvelopedData */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int getEncryptedContentSize( const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( contentOIDlength ) const BYTE *contentOID, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_OID const int contentOIDlength,\n\t\t\t\t\t\t\t\t\tOUT_LENGTH_INDEF long *blockedPayloadSize,\n\t\t\t\t\t\t\t\t\tOUT_LENGTH_Z long *encrContentInfoSize )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tlong length DUMMY_INIT;\n\tint status;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( contentOID, contentOIDlength ) );\n\tassert( isWritePtr( blockedPayloadSize, sizeof( long ) ) );\n\tassert( isWritePtr( encrContentInfoSize, sizeof( long ) ) );\n\n\tREQUIRES( contentOIDlength >= MIN_OID_SIZE && \\\n\t\t\t  contentOIDlength <= MAX_OID_SIZE );\n\n\t/* Clear return values */\n\t*blockedPayloadSize = *encrContentInfoSize = 0;\n\n\t/* Calculate the size of the payload after encryption blocking */\n\tstatus = getBlockedPayloadSize( envelopeInfoPtr->payloadSize, \n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->blockSize,\n\t\t\t\t\t\t\t\t\tblockedPayloadSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate the size of the CMS ContentInfo header */\n\tstatus = getActionContext( envelopeInfoPtr, &iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = length = \\\n\t\t\tsizeofCMSencrHeader( contentOID, contentOIDlength, \n\t\t\t\t\t\t\t\t *blockedPayloadSize, iCryptContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*encrContentInfoSize = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeEncryptionHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t\t  IN_LENGTH_OID const int oidLength, \n\t\t\t\t\t\t\t\t  IN_RANGE( 0, 2 ) const int version, \n\t\t\t\t\t\t\t\t  IN_LENGTH_INDEF const long blockedPayloadSize,\n\t\t\t\t\t\t\t\t  IN_LENGTH_INDEF const long extraSize )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\n\tREQUIRES( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\tREQUIRES( version >= 0 && version <= 2 );\n\tREQUIRES( ( oidLength == sizeofOID( OID_CMS_AUTHDATA ) && \\\n\t\t\t\t!memcmp( oid, OID_CMS_AUTHDATA, \\\n\t\t\t\t\t\t sizeofOID( OID_CMS_AUTHDATA ) ) ) || \\\n\t\t\t  blockedPayloadSize == CRYPT_UNUSED || \\\n\t\t\t  ( blockedPayloadSize >= MIN_IVSIZE && \\\n\t\t\t\tblockedPayloadSize < MAX_INTLENGTH ) );\n\tREQUIRES( extraSize == CRYPT_UNUSED || \\\n\t\t\t  ( extraSize > 0 && extraSize < MAX_BUFFER_SIZE ) );\n\n\tstatus = writeCMSheader( stream, oid, oidLength,\n\t\t\t\t\t\t\t ( blockedPayloadSize == CRYPT_UNUSED || \\\n\t\t\t\t\t\t\t   extraSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_UNUSED : \\\n\t\t\t\t\t\t\t\tsizeofShortInteger( 0 ) + extraSize + \\\n\t\t\t\t\t\t\t\tblockedPayloadSize,\n\t\t\t\t\t\t\t  FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( writeShortInteger( stream, version, DEFAULT_TAG ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeEncryptedDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tlong blockedPayloadSize, encrContentInfoSize;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( contentOID != NULL );\n\n\t/* Calculate the size of the payload due to blocking and the ContentInfo\n\t   header */\n\tstatus = getEncryptedContentSize( envelopeInfoPtr, contentOID,\n\t\t\t\t\t\t\t\t\t  sizeofOID( contentOID ), \n\t\t\t\t\t\t\t\t\t  &blockedPayloadSize, \n\t\t\t\t\t\t\t\t\t  &encrContentInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the EncryptedData header, version number, and\n\t   EncryptedContentInfo header */\n\tstatus = writeEncryptionHeader( stream, OID_CMS_ENCRYPTEDDATA, \n\t\t\t\t\t\t\t\t\tsizeofOID( OID_CMS_ENCRYPTEDDATA ), 0,\n\t\t\t\t\t\t\t\t\tblockedPayloadSize, encrContentInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( writeEncryptedContentHeader( stream, contentOID, \n\t\t\t\tsizeofOID( contentOID ), envelopeInfoPtr->iCryptContext, \n\t\t\t\tenvelopeInfoPtr->payloadSize, envelopeInfoPtr->blockSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeEnvelopedDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tlong blockedPayloadSize, encrContentInfoSize;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( contentOID != NULL );\n\n\t/* Calculate the size of the payload due to blocking and the ContentInfo\n\t   header */\n\tstatus = getEncryptedContentSize( envelopeInfoPtr, contentOID,\n\t\t\t\t\t\t\t\t\t  sizeofOID( contentOID ), \n\t\t\t\t\t\t\t\t\t  &blockedPayloadSize, \n\t\t\t\t\t\t\t\t\t  &encrContentInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the EnvelopedData header and version number and start of the \n\t   SET OF RecipientInfo/EncryptionKeyInfo.  Technically we need to jump \n\t   through all sorts of hoops based on the contents and versions of \n\t   encapsulated RecipientInfo structures but nothing seems to care about \n\t   this so we just use a version of 0 */\n\tstatus = writeEncryptionHeader( stream, OID_CMS_ENVELOPEDDATA, \n\t\t\t\t\t\tsizeofOID( OID_CMS_ENVELOPEDDATA ), 0, \n\t\t\t\t\t\tblockedPayloadSize,\n\t\t\t\t\t\t( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\tCRYPT_UNUSED : \\\n\t\t\t\t\t\t\tsizeofObject( envelopeInfoPtr->cryptActionSize ) + \\\n\t\t\t\t\t\t\t\tencrContentInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\twriteSetIndef( stream ) : \\\n\t\t\twriteSet( stream, envelopeInfoPtr->cryptActionSize ) );\n\t}\n\n/* AuthenticatedData, AuthEnvData */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeAuthenticatedDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\tconst ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tint macActionSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tREQUIRES( contentOID != NULL );\n\n\t/* Determine the encoded size of the MAC info */\n\tmacActionSize = sizeofContextAlgoID( actionListPtr->iCryptHandle, 0 );\n\tif( cryptStatusError( macActionSize ) )\n\t\treturn( macActionSize );\n\n\t/* Write the AuthenticatedData header and version number and start of \n\t   the SET OF RecipientInfo.  Technically this isn't an encryption \n\t   header but it uses the same format */\n \tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\tstatus = writeEncryptionHeader( stream, OID_CMS_AUTHDATA, \n\t\t\t\t\t\t\t\t\t\tsizeofOID( OID_CMS_AUTHDATA ), 0, 1, \n\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\t\t}\n\telse\n\t\t{\n\t\tint macSize, contentInfoSize;\n\n\t\t/* Determine the size of the MAC and the encapsulated content \n\t\t   header */\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &macSize, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcontentInfoSize = sizeofObject( \\\n\t\t\t\t\t\t\tsizeofObject( envelopeInfoPtr->payloadSize ) );\n\t\tcontentInfoSize = sizeofObject( sizeofOID( contentOID ) + \\\n\t\t\t\t\t\t\t\t\t\tcontentInfoSize ) - \\\n\t\t\t\t\t\t  envelopeInfoPtr->payloadSize;\n\t\tREQUIRES( contentInfoSize >= 16 && \\\n\t\t\t\t  contentInfoSize < MAX_INTLENGTH );\n\n\t\t/* Write the data header */\n\t\tstatus = writeEncryptionHeader( stream, OID_CMS_AUTHDATA, \n\t\t\t\t\tsizeofOID( OID_CMS_AUTHDATA ), 0, \n\t\t\t\t\tenvelopeInfoPtr->payloadSize,\n\t\t\t\t\t( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\tCRYPT_UNUSED : \\\n\t\t\t\t\t\tsizeofObject( envelopeInfoPtr->cryptActionSize ) + \\\n\t\t\t\t\t\t\tmacActionSize + contentInfoSize + \\\n\t\t\t\t\t\t\tsizeofObject( macSize ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\twriteSetIndef( stream ) : \\\n\t\t\twriteSet( stream, envelopeInfoPtr->cryptActionSize ) );\n\t}\n\nCHECK_RETVAL \\\nstatic int setKDFParams( IN_HANDLE const CRYPT_CONTEXT iGenericSecret,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE kdfAlgo )\n\t{\n\tstatic const BYTE *fixedParamData = MKDATA( \"\\x04\\x00\\x02\\x01\\x01\" );\n\tMESSAGE_DATA msgData;\t\t\t\t/* OCTET STRING SIZE(0) + INTEGER(1) */\n\tSTREAM stream;\n\tBYTE kdfParamData[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint kdfAlgoIDsize, kdfParamDataSize DUMMY_INIT, status;\n\n\tREQUIRES( isHandleRangeValid( iGenericSecret ) );\n\tREQUIRES( isMacAlgo( kdfAlgo ) && kdfAlgo != CRYPT_ALGO_HMAC_SHA1 );\n\n\t/* Get the KDF algoID size */\n\tstatus = kdfAlgoIDsize = sizeofAlgoID( kdfAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We're using a non-default MAC algorithm, send the custom KDF \n\t   parameters to the context:\n\n\t\tCustomParams ::= [ 0 ] SEQUENCE {\n\t\t\tsalt\t\t\tOCTET STRING SIZE(0),\n\t\t\titerationCount\tINTEGER (1),\n\t\t\tprf\t\t\t\tAlgorithmIdentifier\n\t\t\t} */\n\tsMemOpen( &stream, kdfParamData, CRYPT_MAX_TEXTSIZE );\n\twriteConstructed( &stream, 5 + kdfAlgoIDsize, 0 );\n\tswrite( &stream, fixedParamData, 5 );\n\tstatus = writeAlgoID( &stream, kdfAlgo );\n\tif( cryptStatusOK( status ) )\n\t\tkdfParamDataSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the encoded parameter information to the generic-secret \n\t   context */\n\tsetMessageData( &msgData, kdfParamData, kdfParamDataSize );\n\treturn( krnlSendMessage( iGenericSecret, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_KDFPARAMS ) );\n\t}\n\nCHECK_RETVAL \\\nstatic int setAlgoParams( IN_HANDLE const CRYPT_CONTEXT iGenericSecret,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE algorithmParamData[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint algorithmParamDataSize DUMMY_INIT, status;\n\n\tREQUIRES( isHandleRangeValid( iGenericSecret ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( attribute == CRYPT_IATTRIBUTE_ENCPARAMS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_MACPARAMS );\n\n\t/* Get the algorithm parameter data from the encryption or MAC\n\t   context */\n\tsMemOpen( &stream, algorithmParamData, CRYPT_MAX_TEXTSIZE );\n\tif( attribute == CRYPT_IATTRIBUTE_ENCPARAMS )\n\t\tstatus = writeCryptContextAlgoID( &stream, iCryptContext );\n\telse\n\t\tstatus = writeContextAlgoID( &stream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\talgorithmParamDataSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the encoded parameter information to the generic-secret \n\t   context */\n\tsetMessageData( &msgData, algorithmParamData, algorithmParamDataSize );\n\treturn( krnlSendMessage( iGenericSecret, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, attribute ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeAuthEncDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_CONTEXT iGenericSecret;\n\tconst ACTION_LIST *actionListPtr;\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tlong blockedPayloadSize, encrContentInfoSize;\n\tint macSize = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( contentOID != NULL );\n\n\t/* Authenticated encryption derives the encryption and MAC keys from the\n\t   generic-secret value, with the encryption and MAC algorithm \n\t   parameters being provided in the generic-secret's AlgorithmIdentifier\n\t   value.  In order to work with the generic secret we therefore have to\n\t   send the optional KDF, encryption and MAC parameter data to the \n\t   generic-secret context */\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_xxx ); \n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tiGenericSecret = actionListPtr->iCryptHandle;\n\tif( envelopeInfoPtr->defaultMAC != CRYPT_ALGO_HMAC_SHA1 )\n\t\t{\n\t\tstatus = setKDFParams( iGenericSecret, envelopeInfoPtr->defaultMAC );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_CRYPT ); \n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tstatus = setAlgoParams( iGenericSecret, actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_ENCPARAMS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC ); \n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tstatus = setAlgoParams( iGenericSecret, actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_MACPARAMS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate the size of the payload due to blocking and the ContentInfo\n\t   header */\n\tstatus = getEncryptedContentSize( envelopeInfoPtr, contentOID,\n\t\t\t\t\t\t\t\t\t  sizeofOID( contentOID ), \n\t\t\t\t\t\t\t\t\t  &blockedPayloadSize, \n\t\t\t\t\t\t\t\t\t  &encrContentInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's definite-length content then we have to determine the size of \n\t   the MAC at the end of the data as well */\n\tif( blockedPayloadSize != CRYPT_UNUSED )\n\t\t{\n\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC ); \n\t\tREQUIRES( actionListPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &macSize, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the EnvelopedData header and version number and start of the \n\t   SET OF RecipientInfo/EncryptionKeyInfo */\n\tstatus = writeEncryptionHeader( stream, OID_CMS_AUTHENVDATA, \n\t\t\t\t\t\tsizeofOID( OID_CMS_AUTHENVDATA ), 0, \n\t\t\t\t\t\tblockedPayloadSize,\n\t\t\t\t\t\t( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\tCRYPT_UNUSED : \\\n\t\t\t\t\t\t\tsizeofObject( envelopeInfoPtr->cryptActionSize ) + \\\n\t\t\t\t\t\t\t\tencrContentInfoSize + \\\n\t\t\t\t\t\t\t\tsizeofObject( macSize ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) ? \\\n\t\t\twriteSetIndef( stream ) : \\\n\t\t\twriteSet( stream, envelopeInfoPtr->cryptActionSize ) );\n\t}\n\n/* CompressedData */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCompressedDataHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t  INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( contentOID != NULL );\n\n\t/* Since compressing the data changes its length we have to use the\n\t   indefinite-length encoding even if we know how big the payload is */\n\tenvelopeInfoPtr->payloadSize = CRYPT_UNUSED;\n\n\t/* Write the CompressedData header, version number, and Zlib algoID */\n\tstatus = writeCMSheader( stream, OID_CMS_COMPRESSEDDATA, \n\t\t\t\t\t\t\t sizeofOID( OID_CMS_COMPRESSEDDATA ), \n\t\t\t\t\t\t\t CRYPT_UNUSED, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\twriteGenericAlgoID( stream, OID_ZLIB, sizeofOID( OID_ZLIB ) );\n\n\t/* Write the inner Data header */\n\treturn( writeCMSheader( stream, contentOID, sizeofOID( contentOID ), \n\t\t\t\t\t\t\tCRYPT_UNUSED, TRUE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHeader Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the envelope header */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeEnvelopeHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* If we're encrypting, set up the encryption-related information */\n\tif( envelopeInfoPtr->usage == ACTION_CRYPT )\n\t\t{\n\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_CRYPT );\n\t\tENSURES( actionListPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\tstatus = initEnvelopeEncryption( envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_NONE, CRYPT_MODE_NONE, \n\t\t\t\t\t\t\t\t\t\t NULL, 0, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the appropriate CMS header based on the envelope usage.  The\n\t   DigestedData/ACTION_HASH action is never taken since the higher-level \n\t   code assumes that the presence of hash actions indicates the desire \n\t   to create signed data and returns an error if no signature actions are \n\t   present */\n\tsMemOpen( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_CRYPT:\n\t\t\t/* If we're using authenticated encryption then we have to use\n\t\t\t   a special-form AuthEnc CMS header even though technically\n\t\t\t   it's just an encrypted envelope */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t\t{\n\t\t\t\tstatus = writeAuthEncDataHeader( &stream,\n\t\t\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's standard encrypted data */\n\t\t\tif( DATAPTR_ISNULL( envelopeInfoPtr->preActionList ) )\n\t\t\t\t{\n\t\t\t\tstatus = writeEncryptedDataHeader( &stream,\n\t\t\t\t\t\t\t\t\t\t\t\t   envelopeInfoPtr );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = writeEnvelopedDataHeader( &stream,\n\t\t\t\t\t\t\t\t\t\t\t\t   envelopeInfoPtr );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SIGN:\n\t\t\tstatus = writeSignedDataHeader( &stream, envelopeInfoPtr, TRUE );\n\t\t\tbreak;\n\n\t\tcase ACTION_HASH:\n\t\t\tstatus = writeSignedDataHeader( &stream, envelopeInfoPtr, FALSE );\n\t\t\tbreak;\n\n\t\tcase ACTION_COMPRESS:\n\t\t\tstatus = writeCompressedDataHeader( &stream, envelopeInfoPtr );\n\t\t\tbreak;\n\n\t\tcase ACTION_NONE:\n\t\t\t{\n\t\t\tconst BYTE *contentOID = \\\n\t\t\t\t\t\t\tgetContentOID( envelopeInfoPtr->contentType );\n\n\t\t\tREQUIRES( contentOID != NULL );\n\n\t\t\tstatus = writeCMSheader( &stream, contentOID, \n\t\t\t\t\t\t\t\t\t sizeofOID( contentOID ),\n\t\t\t\t\t\t\t\t\t envelopeInfoPtr->payloadSize, FALSE );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ACTION_MAC:\n\t\t\tstatus = writeAuthenticatedDataHeader( &stream, envelopeInfoPtr );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tenvelopeInfoPtr->bufPos = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're not encrypting with key exchange actions, we're done */\n\tif( ( envelopeInfoPtr->usage != ACTION_CRYPT && \\\n\t\t  envelopeInfoPtr->usage != ACTION_MAC ) || \\\n\t\tDATAPTR_ISNULL( envelopeInfoPtr->preActionList ) )\n\t\t{\n\t\t/* Set the block size mask to all ones if we're not encrypting since \n\t\t   we can begin and end data segments on arbitrary boundaries, and \n\t\t   inform the caller that we're done */\n\t\tif( envelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\tenvelopeInfoPtr->blockSizeMask = ~0;\n\t\tDATAPTR_SET( envelopeInfoPtr->lastAction, NULL );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* Start emitting the key exchange actions */\n\tactionListPtr = findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC );\n\tif( actionListPtr == NULL )\n\t\tactionListPtr = findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE );\n\tENSURES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, \n\t\t\t\t ( ACTION_LIST * ) actionListPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write key exchange actions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeKeyex( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tACTION_LIST *actionListPtr;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Get the appropriate encryption, MAC, or generic-secret context to \n\t   export via the keyex actions */\n\tstatus = getActionContext( envelopeInfoPtr, &iCryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Export the session key/MAC using each of the PKC or conventional \n\t   keys.  If it's a conventional key exchange we force the use of the \n\t   CMS format since there's no reason to use the cryptlib format */\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->lastAction ), \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t  envelopeInfoPtr->bufPos, \n\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\t\tint keyexSize;\n\n\t\tENSURES( isShortIntegerRange( dataLeft ) );\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\t/* Make sure that there's enough room to emit this key exchange \n\t\t   action */\n\t\tif( actionListPtr->encodedSize + 128 > dataLeft )\n\t\t\t{\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Emit the key exchange action */\n\t\tstatus = iCryptExportKey( envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\tenvelopeInfoPtr->bufPos, dataLeft, &keyexSize, \n\t\t\t\t\t\t( actionListPtr->action == ACTION_KEYEXCHANGE ) ? \\\n\t\t\t\t\t\t  CRYPT_FORMAT_CMS : envelopeInfoPtr->type,\n\t\t\t\t\t\tiCryptContext, actionListPtr->iCryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tenvelopeInfoPtr->bufPos += keyexSize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, actionListPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's an indefinite-length header, close off the set of key \n\t   exchange actions */\n\tif( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED )\n\t\treturn( writeEOCs( envelopeInfoPtr, 1 ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTrailer Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the signing certificate chain.  This can grow arbitrarily large and \n   in particular can become larger than the main envelope buffer if multiple \n   signatures with long chains and a small envelope buffer are used, so we \n   emit the certificate chain into a dynamically-allocated auxiliary buffer \n   if there isn't enough room to emit it into the main buffer  */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeCertchainTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tSTREAM stream;\n\tvoid *certChainBufPtr;\n\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t  envelopeInfoPtr->bufPos, \n\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\tconst int eocSize = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t( 3 * sizeofEOC() ) : 0;\n\tint certChainBufSize, certChainSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tENSURES( isShortIntegerRange( dataLeft ) );\n\n\t/* Check whether there's enough room left in the buffer to emit the \n\t   signing certificate chain directly into it */\n\tif( envelopeInfoPtr->extraDataSize + 64 < dataLeft )\n\t\t{\n\t\t/* The certificate chain will fit into the envelope buffer */\n\t\tcertChainBufPtr = envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\t  envelopeInfoPtr->bufPos + eocSize;\n\t\tcertChainBufSize = dataLeft - eocSize;\n\t\t}\n\telse\n\t\t{\n\t\t/* If there's almost no room left in the buffer anyway tell the \n\t\t   caller that they have to pop some data before they can continue.  \n\t\t   Hopefully this will create enough room to emit the certificates \n\t\t   directly into the buffer */\n\t\tif( dataLeft < 1024 )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t/* We can't emit the certificates directly into the envelope buffer, \n\t\t   allocate an auxiliary buffer for them and from there copy them \n\t\t   into the main buffer */\n\t\tREQUIRES( envelopeInfoPtr->auxBuffer == NULL );\n\t\tif( ( envelopeInfoPtr->auxBuffer = \\\n\t\t\t\tclDynAlloc( \"emitPostamble\",\n\t\t\t\t\t\t\tenvelopeInfoPtr->extraDataSize + 64 ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tcertChainBufPtr = envelopeInfoPtr->auxBuffer;\n\t\tcertChainBufSize = envelopeInfoPtr->auxBufSize = \\\n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->extraDataSize + 64;\n\t\t}\n\n\t/* Write the end-of-contents octets for the Data OCTET STRING, [0], and \n\t   SEQUENCE if necessary */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\tstatus = writeEOCs( envelopeInfoPtr, 3 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tenvelopeInfoPtr->lastAction = envelopeInfoPtr->postActionList;\n\n\t/* Write the signing certificate chain if it's a CMS signature and \n\t   they're not explicitly excluded, followed by the SET OF SignerInfo \n\t   header */\n\tsMemOpen( &stream, certChainBufPtr, certChainBufSize );\n\tif( ( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \\\n\t\t  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) && \\\n\t\t!TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_NOSIGNINGCERTS ) )\n\t\t{\n\t\tconst ACTION_LIST *lastActionPtr;\n\n\t\tlastActionPtr = DATAPTR_GET( envelopeInfoPtr->lastAction );\n\t\tENSURES( lastActionPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( lastActionPtr ) );\n\t\tstatus = exportCertToStream( &stream,\n\t\t\t\t\t\t\t( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\t  envelopeInfoPtr->iExtraCertChain : \\\n\t\t\t\t\t\t\t  lastActionPtr->iCryptHandle,\n\t\t\t\t\t\t\tCRYPT_ICERTFORMAT_CERTSET );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_HASINDEFTRAILER ) )\n\t\tstatus = writeSetIndef( &stream );\n\telse\n\t\tstatus = writeSet( &stream, envelopeInfoPtr->signActionSize );\n\tif( cryptStatusOK( status ) )\n\t\tcertChainSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're copying data via the auxBuffer flush as much as we can into \n\t   the main buffer.  If we can't copy it all in, resulting in an overflow\n\t   error, we use the OK_SPECIAL status to tell the caller that although\n\t   an overflow occurred it was due to the auxBuffer copy and not the\n\t   certificate chain write and it's OK to move on to the next state */\n\tif( envelopeInfoPtr->auxBufSize > 0 )\n\t\t{\n\t\tenvelopeInfoPtr->auxBufPos = certChainSize;\n\t\tstatus = copyFromAuxBuffer( envelopeInfoPtr );\n\t\treturn( ( status == CRYPT_ERROR_OVERFLOW ) ? OK_SPECIAL : status );\n\t\t}\n\n\t/* Since we're in the post-data state any necessary payload data \n\t   segmentation has been completed, however the caller can't copy out \n\t   any post-payload data because it's past the end-of-segment position.  \n\t   In order to allow the buffer to be emptied to make room for signature \n\t   data we set the end-of-segment position to the end of the new data */\n\tenvelopeInfoPtr->bufPos += certChainSize;\n\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeSignatures( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *actionListPtr;\n\tint noSigs = 0, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Sign each hash using the associated signature key */\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->lastAction ), \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tACTION_LIST *associatedActionPtr;\n\t\tSIGPARAMS sigParams;\n\t\tconst int sigBufSize = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos, \\\n\t\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT - 1 );\n\t\tint sigSize;\n\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\tREQUIRES( actionListPtr->action == ACTION_SIGN );\n\t\tENSURES( isShortIntegerRange( sigBufSize ) );\n\n\t\t/* Check whether there's enough room left in the buffer to emit the\n\t\t   signature directly into it.  Since signatures are fairly small (a\n\t\t   few hundred bytes) we always require enough room in the buffer\n\t\t   and don't bother with any overflow handling via the auxBuffer */\n\t\tif( actionListPtr->encodedSize + 64 > sigBufSize )\n\t\t\t{\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Set up any necessary signature parameters such as signature \n\t\t   attributes and timestamps if necessary */\n\t\tstatus = cmsInitSigParams( actionListPtr, envelopeInfoPtr->type, \n\t\t\t\t\t\t\t\t   envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t   &sigParams );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* Sign the data */\n\t\tassociatedActionPtr = DATAPTR_GET( actionListPtr->associatedAction );\n\t\tREQUIRES( associatedActionPtr != NULL );\n\t\tstatus = iCryptCreateSignature( envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos, sigBufSize, \n\t\t\t\t\t\t\t&sigSize, envelopeInfoPtr->type,\n\t\t\t\t\t\t\tactionListPtr->iCryptHandle,\n\t\t\t\t\t\t\tassociatedActionPtr->iCryptHandle,\n\t\t\t\t\t\t\t( envelopeInfoPtr->type == CRYPT_FORMAT_CRYPTLIB ) ? \\\n\t\t\t\t\t\t\t\tNULL : &sigParams );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* Since the timestamping process can take awhile, we re-verify the\n\t\t   envelopeInfoPtr and actionListPtr if there's a TSP involved */\n\t\tREQUIRES( sigParams.iTspSession == CRYPT_ERROR || \\\n\t\t\t\t  ( sanityCheckEnvCMSEnv( envelopeInfoPtr ) && \\\n\t\t\t\t\tsanityCheckActionList( actionListPtr ) ) );\n\n\t\tenvelopeInfoPtr->bufPos += sigSize;\n\t\tnoSigs++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, actionListPtr );\n\n\t/* The possibilities for problems when creating a signature are complex \n\t   enough that we provide special-case reporting for specific types of\n\t   problems.  In particular we pull up lower-level information from \n\t   signature-creation related objects if they're being used, and if \n\t   there are multiple signatures being created we identify the \n\t   individual signature that caused the problem */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( actionListPtr->iTspSession != CRYPT_ERROR )\n\t\t\t{\n\t\t\tretExtObj( status, \n\t\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t     actionListPtr->iTspSession,\n\t\t\t\t\t\t \"Couldn't emit signed timestamp to envelope \"\n\t\t\t\t\t\t \"trailer\" ) );\n\t\t\t}\n\t\tif( noSigs <= 0 )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit signature to envelope trailer\" ) );\n\t\t\t}\n\t\tretExt( status,\n\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Couldn't emit signature #%d to envelope trailer\",\n\t\t\t\t  noSigs + 1 ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write MAC value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeMAC( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\tSTREAM stream;\n\tMESSAGE_DATA msgData;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst int eocSize = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t( 3 * sizeofEOC() ) : 0;\n\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t  envelopeInfoPtr->bufPos, 512 );\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Make sure that there's room for the MAC data in the buffer */\n\tif( dataLeft < eocSize + sizeofObject( CRYPT_MAX_HASHSIZE ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tINJECT_FAULT( ENVELOPE_CMS_CORRUPT_AUTH_DATA, \n\t\t\t\t  ENVELOPE_CMS_CORRUPT_AUTH_DATA_1 );\n\n\t/* Write the end-of-contents octets for the Data OCTET STRING, [0], and \n\t   SEQUENCE if necessary */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\tstatus = writeEOCs( envelopeInfoPtr, 3 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Get the MAC value and write it to the buffer */\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC );\n\tENSURES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tINJECT_FAULT( ENVELOPE_CMS_CORRUPT_AUTH_MAC, \n\t\t\t\t  ENVELOPE_CMS_CORRUPT_AUTH_MAC_1 );\n\tsMemOpen( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos, \n\t\t\t  dataLeft );\n\tstatus = writeOctetString( &stream, hash, msgData.length, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tenvelopeInfoPtr->bufPos += length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEmit Envelope Preamble/Postamble\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Output as much of the preamble as possible into the envelope buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emitPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\t/* If we've finished processing the header information, don't do\n\t   anything */\n\tif( envelopeInfoPtr->envState == ENVSTATE_DONE )\n\t\treturn( CRYPT_OK );\n\n\t/* If we haven't started doing anything yet perform various final\n\t   initialisations */\n\tif( envelopeInfoPtr->envState == ENVSTATE_NONE )\n\t\t{\n\t\t/* If there's no nested content type set, default to plain data */\n\t\tif( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )\n\t\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;\n\n\t\t/* If there's an absolute data length set, remember it for when we\n\t\t   copy in data */\n\t\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\t\tenvelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;\n\n\t\t/* Perform any remaining initialisation.  MAC'd data is a special-\n\t\t   case form of encrypted data so we treat them as the same thing\n\t\t   at the key exchange level */\n\t\tif( envelopeInfoPtr->usage == ACTION_CRYPT || \\\n\t\t\tenvelopeInfoPtr->usage == ACTION_MAC )\n\t\t\tstatus = cmsPreEnvelopeEncrypt( envelopeInfoPtr );\n\t\telse\n\t\t\t{\n\t\t\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t\t\tstatus = cmsPreEnvelopeSign( envelopeInfoPtr );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't perform final %s initialisation prior to \"\n\t\t\t\t\t  \"enveloping data\", \n\t\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_SIGN ) ? \\\n\t\t\t\t\t\t\"signing\" : \"encryption\" ) );\n\t\t\t}\n\n\t\t/* Delete any orphaned actions such as automatically-added hash\n\t\t   actions that were overridden with user-supplied alternate\n\t\t   actions */\n\t\tstatus = deleteUnusedActions( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Make sure that we start a new segment when we add the first lot\n\t\t   of payload data after we've emitted the header info */\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_SEGMENTCOMPLETE );\n\n\t\t/* We're ready to go, prepare to emit the outer header */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_HEADER;\n\t\t\n\t\tENSURES( checkActions( envelopeInfoPtr ) );\n\t\t}\n\n\t/* Emit the outer header.  This always follows directly from the final\n\t   initialisation step but we keep the two logically distinct to \n\t   emphasise the fact that the former is merely finalising enveloping \n\t   actions without performing any header processing while the latter is \n\t   the first stage that actually emits header data */\n\tif( envelopeInfoPtr->envState == ENVSTATE_HEADER )\n\t\t{\n\t\tstatus = writeEnvelopeHeader( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If there's nothing else to emit, we're done */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\t\t\t\tENSURES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't create envelope header\" ) );\n\t\t\t}\n\n\t\t/* Move on to the next state */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_KEYINFO;\n\t\t}\n\n\t/* Handle key export actions */\n\tif( envelopeInfoPtr->envState == ENVSTATE_KEYINFO )\n\t\t{\n\t\tstatus = writeKeyex( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit key exchange actions to envelope \"\n\t\t\t\t\t  \"header\" ) );\n\t\t\t}\n\n\t\t/* Move on to the next state */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_ENCRINFO;\n\t\t}\n\n\t/* Handle encrypted content information */\n\tif( envelopeInfoPtr->envState == ENVSTATE_ENCRINFO )\n\t\t{\n\t\tconst ACTION_LIST *actionListPtr;\n\t\tSTREAM stream;\n\t\tconst BYTE *contentOID = getContentOID( envelopeInfoPtr->contentType );\n\t\tconst int originalBufPos = envelopeInfoPtr->bufPos;\n\t\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos, \\\n\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\n\t\tREQUIRES( contentOID != NULL );\n\t\tREQUIRES( isShortIntegerRangeNZ( dataLeft ) );\n\n\t\t/* Make sure that there's enough room to emit the data header.  The\n\t\t   value used is only approximate, if there's not enough room left\n\t\t   the write will also return an overflow error */\n\t\tif( dataLeft < 256 )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t/* Write the encrypted content header */\n\t\tsMemOpen( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,\n\t\t\t\t  dataLeft );\n\t\tif( envelopeInfoPtr->usage == ACTION_MAC )\n\t\t\t{\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\n\t\t\tENSURES( actionListPtr != NULL );\n\t\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\t\t/* If it's authenticated data, there's a MAC algorithm ID \n\t\t\t   preceding standard EncapContent */\n\t\t\tstatus = writeContextAlgoID( &stream, \n\t\t\t\t\t\t\t\t\t\t actionListPtr->iCryptHandle );\n\t\t\tif( cryptStatusOK ( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = writeCMSheader( &stream, contentOID, \n\t\t\t\t\t\t\t\t\t\t sizeofOID( contentOID ),\n\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr->payloadSize, \n\t\t\t\t\t\t\t\t\t\t TRUE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tCRYPT_CONTEXT iCryptContext;\n\n\t\t\t/* It's encrypted data, it's EncrContent */\n\t\t\tstatus = getActionContext( envelopeInfoPtr, &iCryptContext );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = writeEncryptedContentHeader( &stream, contentOID,\n\t\t\t\t\t\t\t\t\tsizeofOID( contentOID ), iCryptContext, \n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->payloadSize, \n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->blockSize );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tenvelopeInfoPtr->bufPos += stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t{\n\t\t\tconst void *macData DUMMY_INIT_PTR;\n\t\t\tint macDataLength DUMMY_INIT;\n\n\t\t\t/* Get the MAC action that we'll be using to protect the \n\t\t\t   content */\n\t\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_MAC );\n\t\t\tENSURES( actionListPtr != NULL );\n\t\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\t\t/* For AuthEnc data we have to MAC the \n\t\t\t   EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier \n\t\t\t   information alongside the payload data to stop an attacker \n\t\t\t   from manipulating the algorithm parameters to cause \n\t\t\t   corruption that won't be detected by the MAC on the payload \n\t\t\t   data.  This requires digging down into the encrypted content\n\t\t\t   header to locate the AlgoID data and MACing that */\n\t\t\tsMemConnect( &stream, envelopeInfoPtr->buffer + originalBufPos,\n\t\t\t\t\t\t envelopeInfoPtr->bufPos - originalBufPos );\n\t\t\treadLongSequence( &stream, NULL );\t/* Outer encapsulation */\n\t\t\tstatus = readUniversal( &stream );\t/* Content-type OID */\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = getStreamObjectLength( &stream, &macDataLength );\n\t\t\tif( cryptStatusOK( status ) )\t\t/* AlgoID */\n\t\t\t\t{\n\t\t\t\tstatus = sMemGetDataBlock( &stream, ( void ** ) &macData, \n\t\t\t\t\t\t\t\t\t\t   macDataLength );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) macData, \n\t\t\t\t\t\t\t\t\t\t  macDataLength );\n\t\t\t\t}\n\t\t\tsMemDisconnect( &stream );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit encrypted content header to envelope \"\n\t\t\t\t\t  \"header\" ) );\n\t\t\t}\n\n\t\t/* We're done */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\t\t}\n\n\tENSURES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Output as much of the postamble as possible into the envelope buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emitPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  STDC_UNUSED const BOOLEAN dummy )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\t/* Before we can emit the trailer we need to flush any remaining data\n\t   from internal buffers */\n\tif( envelopeInfoPtr->envState == ENVSTATE_NONE )\n\t\t{\n\t\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\n\t\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t\tstatus = copyToEnvelopeFunction( envelopeInfoPtr, NULL, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't flush remaining data into envelope \"\n\t\t\t\t\t  \"buffer\" ) );\n\t\t\t}\n\t\tenvelopeInfoPtr->envState = \\\n\t\t\t\t\t( envelopeInfoPtr->usage == ACTION_SIGN ) ? \\\n\t\t\t\t\tENVSTATE_FLUSHED : ENVSTATE_SIGNATURE;\n\t\tINJECT_FAULT( BADSIG_DATA, BADSIG_DATA_CMS_1 );\n\t\t}\n\n\t/* The only message type that has a trailer is signed or authenticated \n\t   data so if we're not signing/authenticating data we can exit now */\n\tif( !( envelopeInfoPtr->usage == ACTION_SIGN || \\\n\t\t   envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t   ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) ) ) )\n\t\t{\n\t\t/* Emit the various end-of-contents octets if necessary */\n\t\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \\\n\t\t\t( envelopeInfoPtr->usage == ACTION_CRYPT &&\n\t\t\t  envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) )\n\t\t\t{\n\t\t\t/* Write the end-of-contents octets for the encapsulated data if\n\t\t\t   necessary.  Normally we have two EOCs, however compressed \n\t\t\t   data requires an extra one due to the explicit tagging */\n\t\t\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \\\n\t\t\t\t( envelopeInfoPtr->usage == ACTION_CRYPT || \\\n\t\t\t\t  envelopeInfoPtr->usage == ACTION_COMPRESS ) )\n\t\t\t\t{\n\t\t\t\tstatus = writeEOCs( envelopeInfoPtr, 3 + \\\n\t\t\t\t\t\t\t\t\t( ( envelopeInfoPtr->usage == \\\n\t\t\t\t\t\t\t\t\t\tACTION_COMPRESS ) ? \\\n\t\t\t\t\t\t\t\t\t  3 : 2 ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Write the remaining end-of-contents octets for the OCTET\n\t\t\t\t   STRING/SEQUENCE, [0], and SEQUENCE */\n\t\t\t\tstatus = writeEOCs( envelopeInfoPtr, 3 );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Couldn't emit final EOC octets\" ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Now that we've written the final end-of-contents octets, set the end-\n\t\t   of-segment-data pointer to the end of the data in the buffer so that\n\t\t   copyFromEnvelope() can copy out the remaining data */\n\t\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\t\tENSURES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's any signature data left in the auxiliary buffer try and \n\t   empty that first */\n\tif( envelopeInfoPtr->auxBufPos > 0 )\n\t\t{\n\t\tstatus = copyFromAuxBuffer( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't flush remaining signature data into \"\n\t\t\t\t\t  \"envelope buffer\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Handle signing certificate chain */\n\tif( envelopeInfoPtr->envState == ENVSTATE_FLUSHED )\n\t\t{\n\t\tstatus = writeCertchainTrailer( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit certificate chain to envelope \"\n\t\t\t\t\t  \"trailer\" ) );\n\t\t\t}\n\n\t\t/* Move on to the next state */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_SIGNATURE;\n\n\t\t/* If we were writing the certificate chain using the auxBuffer as \n\t\t   an intermediate stage because there wasn't enough room to \n\t\t   assemble the complete chain in the main buffer and we then got an\n\t\t   overflow error moving the data out into the main buffer we have \n\t\t   to resume later in the signature state */\n\t\tif( status == OK_SPECIAL )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* Handle signing actions */\n\tREQUIRES( envelopeInfoPtr->envState == ENVSTATE_SIGNATURE );\n\n\t/* Write the signatures/MACs.  The process of writing signatures is \n\t   complex enough that the function itself sets the extended error\n\t   information */\n\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t{\n\t\tstatus = writeSignatures( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeMAC( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit MAC to envelope trailer\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Write the end-of-contents octets for the OCTET STRING/SEQUENCE, [0],\n\t   and SEQUENCE if necessary.  If the trailer has an indefinite length\n\t   then we need to add an EOC for the trailer as well */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED || \\\n\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_HASINDEFTRAILER ) )\n\t\t{\n\t\tstatus = writeEOCs( envelopeInfoPtr,\n\t\t\t\t\t\t\t3 + \\\n\t\t\t\t\t\t\t( TEST_FLAG( envelopeInfoPtr->dataFlags,\n\t\t\t\t\t\t\t\t\t\t ENVDATA_FLAG_HASINDEFTRAILER ) ? \\\n\t\t\t\t\t\t\t  1 : 0 ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit final EOC octets\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Now that we've written the final end-of-contents octets set the end-\n\t   of-segment-data pointer to the end of the data in the buffer so that\n\t   copyFromEnvelope() can copy out the remaining data */\n\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\tENSURES( sanityCheckEnvCMSEnv( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMSEnveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint algorithm, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\t\n\tREQUIRES_V( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->processPreambleFunction, emitPreamble );\n\tFNPTR_SET( envelopeInfoPtr->processPostambleFunction, emitPostamble );\n\tFNPTR_SET( envelopeInfoPtr->checkAlgoFunction, cmsCheckAlgo );\n\n\t/* Set up the processing state information */\n\tenvelopeInfoPtr->envState = ENVSTATE_NONE;\n\n\t/* Remember the current default settings for use with the envelope. \n\t   We force the use of the CBC encryption mode because this is the \n\t   safest and most efficient encryption mode, and the only mode defined \n\t   for many CMS algorithms.  Since the CMS algorithms represent only a \n\t   subset of what's available we have to drop back to fixed values if \n\t   the caller has selected something exotic */\n\tstatus = krnlSendMessage( envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &algorithm, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_HASH );\n\tif( cryptStatusError( status ) || \\\n\t\t!checkAlgoID( algorithm, CRYPT_MODE_NONE ) )\n\t\tenvelopeInfoPtr->defaultHash = CRYPT_ALGO_SHA2;\n\telse\n\t\tenvelopeInfoPtr->defaultHash = algorithm;\t/* int vs.enum */\n\tstatus = krnlSendMessage( envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &algorithm, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_ALGO );\n\tif( cryptStatusError( status ) || \\\n\t\t!checkAlgoID( algorithm, ( algorithm == CRYPT_ALGO_RC4 ) ? \\\n\t\t\t\t\t\t\t\t CRYPT_PSEUDOMODE_RC4 : CRYPT_MODE_CBC ) )\n\t\tenvelopeInfoPtr->defaultAlgo = CRYPT_ALGO_AES;\n\telse\n\t\tenvelopeInfoPtr->defaultAlgo = algorithm;\t/* int vs.enum */\n\tstatus = krnlSendMessage( envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &algorithm, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_MAC );\n\tif( cryptStatusError( status ) || \\\n\t\t!checkAlgoID( algorithm, CRYPT_MODE_NONE ) )\n\t\tenvelopeInfoPtr->defaultMAC = CRYPT_ALGO_HMAC_SHA2;\n\telse\n\t\tenvelopeInfoPtr->defaultMAC = algorithm;\t/* int vs.enum */\n\t}\n#endif /* USE_CMS */\n"
  },
  {
    "path": "deps/cl345/envelope/cms_envpre.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib CMS Pre-enveloping Routines\t\t\t\t*\n*\t\t\t\t\t    Copyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEncrypted Content Pre-processing\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a context for a particular envelope action type */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createActionContext( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\tIN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\tIN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iMasterKeyContext )\n\t{\n\tCRYPT_CONTEXT iActionContext;\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( actionType == ACTION_CRYPT || actionType == ACTION_MAC || \\\n\t\t\t  actionType == ACTION_xxx );\n\tREQUIRES( isConvAlgo( cryptAlgo ) || isMacAlgo( cryptAlgo ) || \\\n\t\t\t  isSpecialAlgo( cryptAlgo ) );\n\tREQUIRES( iMasterKeyContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iMasterKeyContext ) );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\t/* Make sure that we can still add another action */\n\tif( !moreActionsPossible( actionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Create a the appropriate context type and either generate a key for \n\t   it if we're using standard encryption/authentication or derive a key\n\t   from the supplied generic-secret context if we're using authenticated \n\t   encryption */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiActionContext = createInfo.cryptHandle;\n\tif( iMasterKeyContext == CRYPT_UNUSED )\n\t\t{\n\t\t/* We're using standard encryption or authentication, generate a key\n\t\t   into the context */\n\t\tstatus = krnlSendNotifier( iActionContext, IMESSAGE_CTX_GENKEY );\n\t\t}\n\telse\n\t\t{\n\t\tMECHANISM_KDF_INFO mechanismInfo;\n\n\t\t/* We're using authenticated encryption, derive the key for the \n\t\t   context from the generic-secret context */\n\t\tif( actionType == ACTION_CRYPT )\n\t\t\t{\n\t\t\tsetMechanismKDFInfo( &mechanismInfo, iActionContext, \n\t\t\t\t\t\t\t\t iMasterKeyContext, \n\t\t\t\t\t\t\t\t envelopeInfoPtr->defaultMAC, \n\t\t\t\t\t\t\t\t \"encryption\", 10 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsetMechanismKDFInfo( &mechanismInfo, iActionContext, \n\t\t\t\t\t\t\t\t iMasterKeyContext, \n\t\t\t\t\t\t\t\t envelopeInfoPtr->defaultMAC, \n\t\t\t\t\t\t\t\t \"authentication\", 14 );\n\t\t\t}\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iActionContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add the context to the action list */\n\tstatus = addAction( envelopeInfoPtr, actionType, iActionContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iActionContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the contexts needed for the enveloping process */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createEnvelopeContexts( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *actionListPtr;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( DATAPTR_ISNULL( envelopeInfoPtr->actionList ) );\n\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_CRYPT:\n\t\t\t/* If we're performing straight encryption, there's only one \n\t\t\t   context to create */\n\t\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t\t{\n\t\t\t\treturn( createActionContext( envelopeInfoPtr, ACTION_CRYPT,\n\t\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr->defaultAlgo,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED ) );\n\t\t\t\t}\n\n\t\t\t/* We're performing authenticated encryption, we need to create \n\t\t\t   a generic-secret context for the master secret and separate \n\t\t\t   encryption and MAC contexts to provide the protection */\n\t\t\tstatus = createActionContext( envelopeInfoPtr, ACTION_xxx,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IALGO_GENERIC_SECRET,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_UNUSED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_xxx ); \n\t\t\tENSURES( actionListPtr != NULL );\n\t\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\t\tstatus = createActionContext( envelopeInfoPtr, ACTION_CRYPT,\n\t\t\t\t\t\t\t\t\t\t  envelopeInfoPtr->defaultAlgo,\n\t\t\t\t\t\t\t\t\t\t  actionListPtr->iCryptHandle );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = createActionContext( envelopeInfoPtr, ACTION_MAC,\n\t\t\t\t\t\t\t\t\t\t\t  envelopeInfoPtr->defaultMAC,\n\t\t\t\t\t\t\t\t\t\t\t  actionListPtr->iCryptHandle );\n\t\t\t\t}\n\t\t\treturn( status );\n\n\t\tcase ACTION_MAC:\n\t\t\treturn( createActionContext( envelopeInfoPtr, ACTION_MAC,\n\t\t\t\t\t\t\t\t\t\t envelopeInfoPtr->defaultMAC,\n\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED ) );\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Process an individual key exchange action for the main envelope action */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processKeyexchangeAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT ACTION_LIST *preActionListPtr,\n\t\t\t\t\t\t\t\t\t IN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_DEVICE iCryptDevice )\n\t{\n\tACTION_LIST *actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\tint keyexAlgorithm DUMMY_INIT, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( preActionListPtr, sizeof( ACTION_LIST ) ) );\n\t\n\tREQUIRES( preActionListPtr != NULL && \\\n\t\t\t  ( preActionListPtr->action == ACTION_KEYEXCHANGE_PKC || \\\n\t\t\t\tpreActionListPtr->action == ACTION_KEYEXCHANGE ) );\n\tREQUIRES( iCryptDevice == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iCryptDevice ) );\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t/* If the session key/MAC/generic-secret context is tied to a device, \n\t   make sure that the key exchange object is in the same device */\n\tif( iCryptDevice != CRYPT_UNUSED )\n\t\t{\n\t\tCRYPT_DEVICE iKeyexDevice;\n\n\t\tstatus = krnlSendMessage( preActionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  MESSAGE_GETDEPENDENT, &iKeyexDevice,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_DEVICE );\n\t\tif( cryptStatusError( status ) || iCryptDevice != iKeyexDevice )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, \n\t\t\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_CRYPT ) ? \\\n\t\t\t\t\t\t\tCRYPT_ENVINFO_SESSIONKEY : CRYPT_ENVINFO_INTEGRITY,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\t\t}\n\n\t/* Connect the controller to the subject and remember that this action \n\t   now has a controlling action */\n\tDATAPTR_SET( preActionListPtr->associatedAction, actionListPtr );\n\tCLEAR_FLAG( actionListPtr->flags, ACTION_FLAG_NEEDSCONTROLLER );\n\n\t/* Evaluate the size of the exported action.  If it's a conventional key\n\t   exchange we force the use of the CMS format since there's no reason \n\t   to use the cryptlib format.  Note that this assumes that the first \n\t   action is the one that we'll be exporting the key for, which is \n\t   required for authenticated encryption where there can be multiple \n\t   actions (one for encryption and one for authentication) alongside the\n\t   generic-secret action present */\n\tstatus = iCryptExportKey( NULL, 0, &preActionListPtr->encodedSize, \n\t\t\t\t\t\t( preActionListPtr->action == ACTION_KEYEXCHANGE ) ? \\\n\t\t\t\t\t\t\tCRYPT_FORMAT_CMS : envelopeInfoPtr->type,\n\t\t\t\t\t\tactionListPtr->iCryptHandle, \n\t\t\t\t\t\tpreActionListPtr->iCryptHandle );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( preActionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keyexAlgorithm,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there are any key exchange actions that will result in indefinite-\n\t   length encodings present then we can't use a definite-length encoding \n\t   for the key exchange actions */\n\treturn( ( isDlpAlgo( keyexAlgorithm ) || \\\n\t\t\t  isEccAlgo( keyexAlgorithm ) ) ? OK_SPECIAL : CRYPT_OK );\n\t}\n\n/* Pre-process information for encrypted enveloping */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint cmsPreEnvelopeEncrypt( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_DEVICE iCryptDevice = CRYPT_UNUSED;\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tBOOLEAN hasIndefSizeActions = FALSE;\n\tint totalSize, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( envelopeInfoPtr->usage == ACTION_CRYPT || \\\n\t\t\t  envelopeInfoPtr->usage == ACTION_MAC );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\t/* If there are no key exchange actions present, we're done */\n\tif( DATAPTR_ISNULL( envelopeInfoPtr->preActionList ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Create the enveloping context(s) if necessary */\n\tif( actionListPtr == NULL )\n\t\t{\n\t\tstatus = createEnvelopeContexts( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\t\t}\n\telse\n\t\t{\n\t\t/* If the encryption/MAC context is tied to a device, get its handle \n\t\t   so that we can check that all key exchange objects are also in the \n\t\t   same device.\n\n\t\t   In theory if we're using a device for our crypto and performing\n\t\t   authenticated encryption then we'd need to check that all of the \n\t\t   generic-secret, encryption and MAC contexts are contained in the \n\t\t   same device, however since we don't allow these to be explicitly \n\t\t   set by the user (the encryption and MAC keys are derived from the \n\t\t   generic-secret context so it's not possible to set a key-loaded \n\t\t   encryption/MAC context) this can never occur */\n\t\tREQUIRES( DATAPTR_ISNULL( actionListPtr->next ) );\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  MESSAGE_GETDEPENDENT, &iCryptDevice,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_DEVICE );\n\t\tif( cryptStatusError( status ) )\n\t\t\tiCryptDevice = CRYPT_UNUSED;\n\t\t}\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t/* If we're performing straight encryption or MACing, notify the kernel \n\t   that the encryption/MAC context is attached to the envelope.  This is \n\t   an internal object used only by the envelope so we tell the kernel \n\t   not to increment its reference count when it attaches it.  If we're\n\t   performing authenticated encryption then we can't do this because \n\t   we're going via an intermediate generic-secret object from which keys \n\t   will be diversified into distinct encryption and MAC objects */\n\tif( !( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t   TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) ) )\n\t\t{\n\t\tREQUIRES( DATAPTR_ISNULL( actionListPtr->next ) );\n\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t\t  &actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Now walk down the list of key exchange actions evaluating their size\n\t   and connecting each one to the encryption/MAC/generic-secret action */\n\ttotalSize = 0; \n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->preActionList ), \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = processKeyexchangeAction( envelopeInfoPtr, actionListPtr,\n\t\t\t\t\t\t\t\t\t\t   iCryptDevice );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* An OK_SPECIAL state means that this keyex action will result \n\t\t\t   in an indefinite-length encoding */\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\thasIndefSizeActions = TRUE;\n\t\t\t}\n\t\ttotalSize += actionListPtr->encodedSize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tenvelopeInfoPtr->cryptActionSize = hasIndefSizeActions ? \\\n\t\t\t\t\t\t\t\t\t   CRYPT_UNUSED : totalSize;\n\tENSURES( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) || \\\n\t\t\t ( envelopeInfoPtr->cryptActionSize > 0 && \\\n\t\t\t   envelopeInfoPtr->cryptActionSize < MAX_BUFFER_SIZE ) );\n\n\t/* If we're MACing the data (either directly or because we're performing\n\t   authenticated encryption), hashing is now active.  The two actions \n\t   have different flags because standalone MACing hashes plaintext while \n\t   MACing as part of authenticated encryption hashes ciphertext */\n\tif( envelopeInfoPtr->usage == ACTION_MAC )\n\t\t{\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\t}\n\tif( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t{\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t  ENVDATA_FLAG_AUTHENCACTIONSACTIVE );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSigned Content Pre-processing\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up signature parameters such as signature attributes and timestamps \n   if necessary */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint cmsInitSigParams( const ACTION_LIST *actionListPtr,\n\t\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t  IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t  OUT SIGPARAMS *sigParams )\n\t{\n\tBOOLEAN_INT useDefaultAttributes;\n\tint status;\n\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tREQUIRES( formatType == CRYPT_FORMAT_CRYPTLIB || \\\n\t\t\t  formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t  formatType == CRYPT_FORMAT_SMIME );\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\tassert( isWritePtr( sigParams, sizeof( SIGPARAMS ) ) );\n\n\tinitSigParams( sigParams );\n\n\t/* If it's a raw signature, there are no additional signing parameters */\n\tif( formatType == CRYPT_FORMAT_CRYPTLIB )\n\t\treturn( CRYPT_OK );\n\n\t/* Add the timestamping session if there's one present */\n\tif( actionListPtr->iTspSession != CRYPT_ERROR )\n\t\tsigParams->iTspSession = actionListPtr->iTspSession;\n\n\t/* If the caller has provided signing attributes, use those */\n\tif( actionListPtr->iExtraData != CRYPT_ERROR )\n\t\t{\n\t\tsigParams->iAuthAttr = actionListPtr->iExtraData;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There are no siging attributes explicitly specified (which can only \n\t   happen under circumstances controlled by the pre-envelope signing \n\t   code) in which case we either get the signing code to add the default \n\t   ones for us or use none at all if the use of default attributes is \n\t   disabled */\n\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE,  \n\t\t\t\t\t\t\t  &useDefaultAttributes,\n\t\t\t\t\t\t\t  CRYPT_OPTION_CMS_DEFAULTATTRIBUTES );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( useDefaultAttributes == TRUE )\n\t\tsigParams->useDefaultAuthAttr = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process signing certificates and match the content-type in the \n   authenticated attributes with the signed content type if it's anything \n   other than 'data' (the data content-type is added automatically) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processSigningCerts( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t    INOUT ACTION_LIST *actionListPtr )\n\t{\n\tint contentType, dummy, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\t/* If we're including signing certificates and there are multiple \n\t   signing certificates present add the currently-selected one to the \n\t   overall certificate collection */\n\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\tENVELOPE_FLAG_NOSIGNINGCERTS ) && \\\n\t\tenvelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTCOLLECTION );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's no content-type present and the signed content type isn't \n\t   'data' or it's an S/MIME envelope, create signing attributes to hold \n\t   the content-type and smimeCapabilities */\n\tif( actionListPtr->iExtraData == CRYPT_ERROR && \\\n\t\t( envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA || \\\n\t\t  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tactionListPtr->iExtraData = createInfo.cryptHandle;\n\t\t}\n\n\t/* If there are no signed attributes, we're done */\n\tif( actionListPtr->iExtraData == CRYPT_ERROR )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the content-type in the attributes matches the actual \n\t   content type by deleting any existing content-type if necessary and \n\t   adding our one (quietly fixing things is easier than trying to report \n\t   this error back to the caller - ex duobus malis minimum eligendum \n\t   est) */\n\tif( krnlSendMessage( actionListPtr->iExtraData, \n\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE, &dummy, \n\t\t\t\t\t\t CRYPT_CERTINFO_CMS_CONTENTTYPE ) != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* There's already a content-type present, delete it so that we can \n\t\t   add our one.  We ignore the return status from the deletion since \n\t\t   the status from the add that follows will be more meaningful to \n\t\t   the caller */\n\t\t( void ) krnlSendMessage( actionListPtr->iExtraData, \n\t\t\t\t\t\t\t\t  IMESSAGE_DELETEATTRIBUTE, NULL, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_CONTENTTYPE );\n\t\t}\n\tcontentType = envelopeInfoPtr->contentType;\t/* int vs.enum */\n\treturn( krnlSendMessage( actionListPtr->iExtraData, \n\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE, &contentType, \n\t\t\t\t\t\t\t CRYPT_CERTINFO_CMS_CONTENTTYPE ) );\n\t}\n\n/* Pre-process information for signed enveloping */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processSignatureAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t   INOUT ACTION_LIST *actionListPtr )\n\t{\n\tconst ACTION_LIST *associatedActionPtr;\n\tSIGPARAMS sigParams;\n\tint signatureAlgo DUMMY_INIT, signatureSize, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES( actionListPtr != NULL && \\\n\t\t\t  actionListPtr->action == ACTION_SIGN && \\\n\t\t\t  DATAPTR_ISSET( actionListPtr->associatedAction ) );\n\n\t/* Process signing certificates and fix up the content-type in the \n\t   authenticated attributes if necessary */\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \\\n\t\tenvelopeInfoPtr->type == CRYPT_FORMAT_SMIME )\n\t\t{\n\t\tstatus = processSigningCerts( envelopeInfoPtr, actionListPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Set up any necessary signature parameters such as signature \n\t  attributes and timestamps if necessary */\n\tstatus = cmsInitSigParams( actionListPtr, envelopeInfoPtr->type, \n\t\t\t\t\t\t\t   envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t   &sigParams );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Evaluate the size of the exported action */\n\tassociatedActionPtr = DATAPTR_GET( actionListPtr->associatedAction );\n\tREQUIRES( associatedActionPtr != NULL );\n\tstatus = iCryptCreateSignature( NULL, 0, &signatureSize, \n\t\t\t\t\t\tenvelopeInfoPtr->type, actionListPtr->iCryptHandle,\n\t\t\t\t\t\tassociatedActionPtr->iCryptHandle,\n\t\t\t\t\t\t( envelopeInfoPtr->type == CRYPT_FORMAT_CRYPTLIB ) ? \\\n\t\t\t\t\t\t\tNULL : &sigParams );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &signatureAlgo,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isDlpAlgo( signatureAlgo ) || isEccAlgo( signatureAlgo ) || \\\n\t\tactionListPtr->iTspSession != CRYPT_ERROR )\n\t\t{\n\t\t/* If there are any signature actions that will result in indefinite-\n\t\t   length encodings present then we can't use a definite-length \n\t\t   encoding for the signature */\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASINDEFTRAILER );\n\t\tactionListPtr->encodedSize = CRYPT_UNUSED;\n\t\t}\n\telse\n\t\t{\n\t\tactionListPtr->encodedSize = signatureSize;\n\t\tenvelopeInfoPtr->signActionSize += signatureSize;\n\t\t}\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_HASINDEFTRAILER ) )\n\t\tenvelopeInfoPtr->signActionSize = CRYPT_UNUSED;\n\tENSURES( ( envelopeInfoPtr->signActionSize == CRYPT_UNUSED ) || \\\n\t\t\t ( envelopeInfoPtr->signActionSize > 0 && \\\n\t\t\t   envelopeInfoPtr->signActionSize < MAX_BUFFER_SIZE ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint cmsPreEnvelopeSign( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *postActionListPtr;\n\tACTION_LIST *actionListPtr;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( envelopeInfoPtr->usage == ACTION_SIGN );\n\n\tpostActionListPtr = DATAPTR_GET( envelopeInfoPtr->postActionList );\n\tREQUIRES( postActionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( postActionListPtr ) );\n\tREQUIRES( DATAPTR_ISSET( postActionListPtr->associatedAction ) );\n\n\t/* If we're generating a detached signature then the content is supplied\n\t   externally and has zero size */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\tenvelopeInfoPtr->payloadSize = 0;\n\n\t/* If it's an attributes-only message it must be zero-length CMS signed\n\t   data with signing attributes present */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ATTRONLY ) )\n\t\t{\n\t\tif( envelopeInfoPtr->type != CRYPT_FORMAT_CMS || \\\n\t\t\tpostActionListPtr->iExtraData == CRYPT_ERROR )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE_EXTRADATA,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\tif( envelopeInfoPtr->payloadSize > 0 )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\t\t}\n\n\t/* If it's a CMS envelope we have to write the signing certificate chain\n\t   alongside the signatures as extra data unless it's explicitly \n\t   excluded so we record how large the information will be for later */\n\tif( ( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \\\n\t\t  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) && \\\n\t\t!TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_NOSIGNINGCERTS ) )\n\t\t{\n\t\tREQUIRES( DATAPTR_ISVALID( postActionListPtr->next ) );\n\t\tif( DATAPTR_ISSET( postActionListPtr->next ) )\n\t\t\t{\n\t\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t\t/* There are multiple sets of signing certificates present, \n\t\t\t   create a signing-certificate meta-object to hold the overall \n\t\t\t   set of certificates */\n\t\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTCHAIN );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tenvelopeInfoPtr->iExtraCertChain = createInfo.cryptHandle;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\t/* There's a single signing certificate present, determine its \n\t\t\t   size */\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( postActionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_CERTSET );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tenvelopeInfoPtr->extraDataSize = msgData.length;\n\t\t\t}\n\t\t}\n\n\t/* Evaluate the size of each signature action */\n\tLOOP_MED( actionListPtr = ( ACTION_LIST * ) postActionListPtr,  \n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = processSignatureAction( envelopeInfoPtr, actionListPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we're writing the signing certificate chain and there are multiple \n\t   signing certificates present, get the size of the overall certificate \n\t   collection */\n\tif( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,\n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_CERTSET );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tenvelopeInfoPtr->extraDataSize = msgData.length;\n\t\t}\n\tENSURES( envelopeInfoPtr->extraDataSize >= 0 && \\\n\t\t\t envelopeInfoPtr->extraDataSize < MAX_BUFFER_SIZE );\n\n\t/* Hashing is now active (you have no chance to survive make your \n\t   time) */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASHACTIONSACTIVE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMS */\n"
  },
  {
    "path": "deps/cl345/envelope/decode.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Datagram Decoding Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n/*\t\t\t .... NO! ...\t\t\t\t   ... MNO! ...\n\t\t   ..... MNO!! ...................... MNNOO! ...\n\t\t ..... MMNO! ......................... MNNOO!! .\n\t\t.... MNOONNOO!\t MMMMMMMMMMPPPOII!\t MNNO!!!! .\n\t\t ... !O! NNO! MMMMMMMMMMMMMPPPOOOII!! NO! ....\n\t\t\t...... ! MMMMMMMMMMMMMPPPPOOOOIII! ! ...\n\t\t   ........ MMMMMMMMMMMMPPPPPOOOOOOII!! .....\n\t\t   ........ MMMMMOOOOOOPPPPPPPPOOOOMII! ...\n\t\t\t....... MMMMM..\t   OPPMMP\t .,OMI! ....\n\t\t\t ...... MMMM::\t o.,OPMP,.o\t  ::I!! ...\n\t\t\t\t .... NNM:::.,,OOPM!P,.::::!! ....\n\t\t\t\t  .. MMNNNNNOOOOPMO!!IIPPO!!O! .....\n\t\t\t\t ... MMMMMNNNNOO:!!:!!IPPPPOO! ....\n\t\t\t\t   .. MMMMMNNOOMMNNIIIPPPOO!! ......\n\t\t\t\t  ...... MMMONNMMNNNIIIOO!..........\n\t\t\t   ....... MN MOMMMNNNIIIIIO! OO ..........\n\t\t\t......... MNO! IiiiiiiiiiiiI OOOO ...........\n\t\t  ...... NNN.MNO! . O!!!!!!!!!O . OONO NO! ........\n\t\t   .... MNNNNNO! ...OOOOOOOOOOO .  MMNNON!........\n\t\t   ...... MNNNNO! .. PPPPPPPPP .. MMNON!........\n\t\t\t  ...... OO! ................. ON! .......\n\t\t\t\t ................................\n\n   Be very careful when modifying this code, the data manipulation that it\n   performs is somewhat tricky */\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckEnvDecode( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Make sure that the buffer position is within bounds */\n\tif( envelopeInfoPtr->buffer == NULL || \\\n\t\tenvelopeInfoPtr->bufPos < 0 || \\\n\t\tenvelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize || \\\n\t\tenvelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \\\n\t\tenvelopeInfoPtr->bufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvDecode: Buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the block buffer position is within bounds */\n\tif( envelopeInfoPtr->blockSize > 0 && \\\n\t\t( envelopeInfoPtr->blockBufferPos < 0 || \\\n\t\t  envelopeInfoPtr->blockBufferPos >= envelopeInfoPtr->blockSize || \\\n\t\t  envelopeInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvDecode: Block buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the partial buffer position is within bounds */\n\tif( envelopeInfoPtr->partialBufPos < 0 || \\\n\t\tenvelopeInfoPtr->partialBufPos > PARTIAL_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvDecode: Partial buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the out-of-band data buffer is within bounds */\n\tif( envelopeInfoPtr->oobBufSize < 0 || \\\n\t\tenvelopeInfoPtr->oobBufSize > OOB_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvDecode: OOB data\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the envelope internal bookeeping is OK */\n\tif( !isIntegerRange( envelopeInfoPtr->segmentSize ) || \\\n\t\t!isIntegerRange( envelopeInfoPtr->dataLeft ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvDecode: Segments\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Handle the end-of-data, with PKCS #5 block padding if necessary:\n\n\t\t\t   pad\n\t+-------+-------+-------+\n\t|\t\t|\t\t|\t\t|\n\t+-------+-------+-------+\n\t\t\t^\t\t^\n\t\t\t|\t\t|\n\t\t padPtr\t  bPos \n\n   This function needs to return a different error status value if \n   authenticated encryption is being used, because corruption of the PKCS #5\n   padding is probably due to message data corruption (there's admittedly \n   also the extremely unlikely possibility that it's due to buggy sending \n   software).  Since the padding check occurs before the final MAC check, \n   the ensuing CRYPT_ERROR_BADDATA would override the later \n   CRYPT_ERROR_SIGNATURE from the MAC check.  In order to deal with this we\n   convert a CRYPT_ERROR_BADDATA to a CRYPT_ERROR_SIGNATURE if authenticated\n   encryption is being used */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processDataEnd( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst int errorStatus = \\\n\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t   ENVDATA_FLAG_AUTHENCACTIONSACTIVE ) ? \\\n\t\t\t\t\tCRYPT_ERROR_SIGNATURE : CRYPT_ERROR_BADDATA;\n\tint value = 0;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t/* If we're using a block cipher, undo the PKCS #5 padding which is\n\t   present at the end of the block */\n\tif( envelopeInfoPtr->blockSize > 1 )\n\t\t{\n\t\tconst BYTE *padPtr;\n\t\tint padSize, i, LOOP_ITERATOR;\n\n\t\t/* Make sure that the padding size is valid.  There's no easy way to \n\t\t   perform these checks in a timing-independent manner because we're \n\t\t   using them to reject completely malformed data (out-of-bounds \n\t\t   array references), but hopefully the few cycles difference won't \n\t\t   be measurable in the overall scheme of things */\n\t\tpadSize = envelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos - 1 ];\n\t\tif( padSize < 1 || padSize > envelopeInfoPtr->blockSize || \\\n\t\t\tpadSize > envelopeInfoPtr->bufPos )\n\t\t\treturn( errorStatus );\n\n\t\t/* Adjust the buffer for the padding */\n\t\tenvelopeInfoPtr->bufPos -= padSize;\n\t\tENSURES( envelopeInfoPtr->bufPos >= 0 && \\\n\t\t\t\t envelopeInfoPtr->bufPos < envelopeInfoPtr->bufSize );\n\t\tpadPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;\n\n\t\t/* Check the padding data in a timing-independent manner */\n\t\tLOOP_MED( i = 0, i < padSize - 1, i++ )\n\t\t\tvalue |= padPtr[ i ] ^ padSize;\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( value != 0 )\n\t\t\treturn( errorStatus );\n\t\t}\n\n\t/* Remember that we've reached the end of the payload and where the\n\t   payload ends (\"This was the end of the river all right\") */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_ENDOFCONTENTS );\n\tenvelopeInfoPtr->dataLeft = envelopeInfoPtr->bufPos;\n\n\t/* If this is PGP data and there's an MDC packet tacked onto the end of \n\t   the payload, record the fact that it's non-payload data \n\t   (processPgpSegment() has ensured that there's enough data present to \n\t   contain a full MDC packet) */\n#ifdef USE_PGP\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_HASATTACHEDOOB ) )\n\t\t{\n\t\tenvelopeInfoPtr->dataLeft -= PGP_MDC_PACKET_SIZE;\n\t\tENSURES( isIntegerRangeNZ( envelopeInfoPtr->dataLeft ) );\n\t\t}\n#endif /* USE_PGP */\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPayload Segment Processing Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The minimum number of bytes of data that we need in order to try and \n   process a segment header.  For a PGP envelope a partial header is a \n   single byte, for a PKCS #7/CMS envelope it's two bytes (tag + length). \n   The setting can't be set too high because anything below the limit is \n   absorbed into the temporary header buffer, if the final header size is \n   less than what's absorbed by the buffer then the data will be lost \n   because data can't be pushed back out of the header buffer into the \n   main envelope buffer without messing up the buffer accounting due to data \n   (apparently) appearing out of nowhere */\n\n#define MIN_HEADER_BYTES\t2\n\n/* Check for special-case segment conditions for which no further segment-\n   processing action is necessary */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isEndOfSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* If we've already processed the entire payload, don't do anything.\n\t   This can happen when we're using the definite encoding form and the \n\t   EOC flag is set elsewhere as soon as the entire payload has been \n\t   copied to the buffer */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS ) )\n\t\t{\n\t\tREQUIRES( envelopeInfoPtr->segmentSize <= 0 );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* It's a standard segment */\n\treturn( FALSE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isFixedLengthSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* If the payload data is segmented but the first segment doesn't have \n\t   an explicit length then the length of the first segment is defined \n\t   as \"whatever's left\".  This is used to handle PGP's odd indefinite-\n\t   length encoding, for which the initial length has already been read \n\t   when the packet header was read */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_NOFIRSTSEGMENT ) )\n\t\t{\n\t\tREQUIRES_B( envelopeInfoPtr->type == CRYPT_FORMAT_PGP );\n\n\t\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_NOFIRSTSEGMENT );\n\t\tenvelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;\n\t\tenvelopeInfoPtr->payloadSize = CRYPT_UNUSED;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If we're using the definite encoding form there's a single segment \n\t   equal in length to the entire payload */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\t{\n\t\tenvelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If we're using the indefinite form but it's an envelope type that\n\t   doesn't segment data then the length is implicitly defined as \"until \n\t   we run out of input\".  This odd situation is encountered for PGP\n\t   envelopes when working with compressed data for which there's no \n\t   length stored or when we're synchronising the envelope data prior to \n\t   processing and there are abitrary further packets (typically PGP \n\t   signature packets, where we want to process the packets in a \n\t   connected series rather than stopping at the end of the first packet \n\t   in the series) following the current one.  In both cases we don't \n\t   know the overall length because we'd need to be able to look ahead an \n\t   arbitrary distance in the stream to figure out where the compressed \n\t   data or any further packets end */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOLENGTHINFO ) )\n\t\t{\n\t\tREQUIRES( envelopeInfoPtr->type == CRYPT_FORMAT_PGP );\n\t\tREQUIRES( envelopeInfoPtr->segmentSize <= 0 );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* It's a standard segment */\n\treturn( FALSE );\n\t}\n\n/* Process a CMS- or PGP-format sub-segment */\n\n#ifdef USE_CMS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processCmsSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT_LENGTH_Z long *segmentLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( segmentLength, sizeof( long ) ) );\n\n\t/* Clear return value */\n\t*segmentLength = 0;\n\n\t/* Check for the EOCs that mark the end of the overall data */\n\tstatus = checkEOC( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( status == TRUE )\n\t\t{\n\t\t/* We've seen the EOC, wrap up the processing */\n\t\treturn( processDataEnd( envelopeInfoPtr ) );\n\t\t}\n\n\t/* It's a new sub-segment, get its length */\n\tstatus = readLongGenericHole( stream, segmentLength, BER_OCTETSTRING );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( *segmentLength == CRYPT_UNUSED )\n\t\t{\n\t\t/* An indefinite-length encoding within a constructed data item \n\t\t   isn't allowed */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMS */\n\n#ifdef USE_PGP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processPgpSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT_LENGTH_Z long *segmentLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( segmentLength, sizeof( long ) ) );\n\n\t/* Clear return value */\n\t*segmentLength = 0;\n\n\t/* Get the next sub-segment's length */\n\tstatus = pgpReadPartialLength( stream, segmentLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we get an OK_SPECIAL returned then it's just an indication \n\t\t   that we've got another partial length (with other segments to \n\t\t   follow) and not an actual error */\n\t\tif( status == OK_SPECIAL )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Alongside normal errors this may also be an OK_SPECIAL to \n\t\t   indicate that we got another partial length (with other segments \n\t\t   to follow), which the caller will handle as a non-error */\n\t\treturn( status );\n\t\t}\n\n\t/* If it's a terminating zero-length segment, wrap up the processing.\n\t   Unlike CMS, PGP can add other odds and ends at this point so we don't \n\t   exit yet but fall through to the code that follows */\n\tif( *segmentLength <= 0 )\n\t\t{\n\t\tstatus = processDataEnd( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* We've now reached the last segment, if this is a packet with an MDC \n\t   packet tacked on and the MDC data is larger than the length of the \n\t   last segment, adjust its effective size to zero and pretend that it's \n\t   not there since we can't process it and trying to do so would only \n\t   give a false-positive error.\n\t   \n\t   This is rather problematic in that if the sender chooses to break the \n\t   MDC packet across the partial-header boundary it'll include some of \n\t   the MDC data with the payload, but there's no easy solution to this, \n\t   the problem lies in the PGP spec for allowing a length encoding form \n\t   that makes one-pass processing impossible.  Hopefully implementations \n\t   will realise this and never break the MDC data over a partial-length \n\t   header.\n\t   \n\t   What's worse though is that with this strategy an attacker can force \n\t   us to skip processing the MDC by rewriting (with some effort because \n\t   of PGP's weird power-of-two segment length constraints) the packet \n\t   segments so that the MDC is always split across packets.  The \"cure\" \n\t   to this is probably far worse than the disease since it would require \n\t   buffering the last PGP_MDC_PACKET_SIZE - 1 bytes until we're sure \n\t   that the next packet isn't an EOC so that we still need the previous \n\t   lot of decrypted data.  This would lead to severe usability problems \n\t   because the user can never be allowed to extract the last \n\t   PGP_MDC_PACKET_SIZE - 1 bytes of data that they've pushed, all for a \n\t   capability that they don't even know exists */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASATTACHEDOOB ) && \\\n\t\t*segmentLength < PGP_MDC_PACKET_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"MDC data was broken over a partial-length segment\" ));\n\t\tassert( DEBUG_WARN );\n\n\t\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_HASATTACHEDOOB );\n\t\t*segmentLength = 0;\n\t\t}\n\n\t/* Convert the last segment into a definite-length segment.  When we \n\t   return from this the calling code will immediately call \n\t   getNextSegment() again since we've consumed some input, at which \n\t   point the definite-length payload size will be set and the call will \n\t   return with OK_SPECIAL to tell the caller that there's no more length \n\t   information to fetch */\n\tenvelopeInfoPtr->payloadSize = *segmentLength;\n\t*segmentLength = 0;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/* Decode the header for the next segment in the buffer.  Returns the number\n   of bytes consumed */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int getNextSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t   IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t\t\t   IN_LENGTH const int length, \n\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *bytesConsumed )\n\t{\n\tSTREAM stream;\n\tlong segmentLength;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesConsumed, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*bytesConsumed = 0;\n\n\t/* If there's not enough data left to contain the header for a\n\t   reasonable-sized segment, tell the caller to try again with more data \n\t   (the bytesConsumed value has already been set to zero earlier) */\n\tif( length < MIN_HEADER_BYTES )\n\t\treturn( OK_SPECIAL );\n\n\t/* Get the sub-segment info */\n\tsMemConnect( &stream, buffer, length );\n#ifdef USE_PGP\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t{\n\t\tstatus = processPgpSegment( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t&segmentLength );\n\t\t}\n\telse\n#endif /* USE_PGP */\n#ifdef USE_CMS\n\t\t{\n\t\tstatus = processCmsSegment( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t    &segmentLength );\n\t\t}\n#endif /* USE_CMS */\n\tif( cryptStatusOK( status ) )\n\t\t*bytesConsumed = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we got an underflow error this isn't fatal since we can \n\t\t   continue when the user pushes more data, so we return normally\n\t\t   with bytesConsumed set to zero */\n\t\tif( status == CRYPT_ERROR_UNDERFLOW )\n\t\t\treturn( OK_SPECIAL );\n\n\t\treturn( status );\n\t\t}\n\tENSURES( *bytesConsumed > 0 && *bytesConsumed <= length );\n\n\t/* We got the length, return the information to the caller */\n\tenvelopeInfoPtr->segmentSize = segmentLength;\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the header for a new payload data segment. There's one specific \n   situation where we can run into problems and that's where we're pushing \n   indefinite-length data and run out of data halfway through a tag, either \n   an EOC or an OCTET STRING segment (or its PGP equivalent):\n\n\t+-------+-----------+-----+---------+\n\t| Header|\tBody\t|00 00| Trailer |\n\t+-------+-----------+-----+---------+\n\t\t\t\t\t\t   ^\t\n\t\t\t\t\t\t   |\n\t\t\t\t\t\tlength\n\t\t\t\t\t\t   +-------+\n\t\t\t\t\t\t\t\t   v\n\t+-------+--------+----------+--------+----------+-----+---------+\n\t| Header|04 xx xx|\tBody\t|04 xx xx|\tBody\t|00 00|\tTrailer |\n\t+-------+--------+----------+--------+----------+-----+---------+\n\n   In this case getNextSegment() will return OK_SPECIAL and we have to \n   buffer the data somewhere until the next push.  We can't report the \n   remainder to the caller as un-consumed data because this may be an \n   implicit push, for example when we add a keying resource to an encrypted \n   envelope, which continues processing with previously-pushed data when it \n   initialises the cryptovariables from the data.  In this case since no \n   data is being pushed there's no way to report that some of the data was \n   unconsumed, so we have to store it in the partial-header buffer until the \n   next push.\n   \n   This function returns additional operation-control information in the \n   form of a SEG_ACTION_TYPE, which can be one of the following:\n\n\tSEG_ACTION_NONE: Segment information for the next segment has been \n\t\t\t\t\t obtained, processing of data can continue.\n\n\tSEG_ACTION_BREAK: Data consists of a single segment, caller should break \n\t\t\t\t\t  from segment-handling loop.\n\n\tSEG_ACTION_CALLEREXIT: Caller should exit since no further action is \n\t\t\t\t\t\t   possible.\n\n\tSEG_ACTION_CONTINUE: No-op segment (e.g. a zero-size segment), caller \n\t\t\t\t\t\t should try again */\n\ntypedef enum {\n\tSEG_ACTION_NONE,\t\t/* No special segment action */\n\tSEG_ACTION_BREAK,\t\t/* Caller should break from seg-handling loop */\n\tSEG_ACTION_CALLEREXIT,\t/* Caller should exit */\n\tSEG_ACTION_CONTINUE,\t/* No-op segment, caller should try again */\n\tSEG_ACTION_LAST\t\t\t/* Last possible segment action */\n\t} SEG_ACTION_TYPE;\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int processSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t\t\t   IN_LENGTH const int length,\n\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *bytesConsumed,\n\t\t\t\t\t\t   OUT_ENUM_OPT( SEG_ACTION ) \\\n\t\t\t\t\t\t\t\tSEG_ACTION_TYPE *segAction )\n\t{\n\tBYTE *bufPtr = ( BYTE * ) buffer;\n\tconst BYTE *headerPtr = bufPtr;\n\tint headerLength = length, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesConsumed, sizeof( int ) ) );\n\tassert( isWritePtr( segAction, sizeof( SEG_ACTION_TYPE ) ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t/* Clear return values */\n\t*bytesConsumed = 0;\n\t*segAction = SEG_ACTION_NONE;\n\n\t/* If we've already processed the entire payload, don't do anything */\n\tif( isEndOfSegment( envelopeInfoPtr ) )\n\t\t{\n\t\tREQUIRES( envelopeInfoPtr->partialBufPos == 0 );\n\n\t\t/* We're done, tell the caller to exit */\n\t\t*segAction = SEG_ACTION_CALLEREXIT;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a fixed-length segment, no further action is necessary */\n\tif( isFixedLengthSegment( envelopeInfoPtr ) )\n\t\t{\n\t\tREQUIRES( envelopeInfoPtr->partialBufPos == 0 );\n\n\t\t*segAction = SEG_ACTION_BREAK;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* At this point we're after new segment information */\n\tREQUIRES( envelopeInfoPtr->segmentSize == 0 );\n\n\t/* If there's buffered partial header data present from a previous \n\t   operation, use that along with any new data to try and construct a \n\t   complete header */\n\tif( envelopeInfoPtr->partialBufPos > 0 )\n\t\t{\n\t\tconst int remainder = min( PARTIAL_BUFFER_SIZE - \\\n\t\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->partialBufPos,\n\t\t\t\t\t\t\t\t   length );\n\t\tif( remainder > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( envelopeInfoPtr->partialBufPos,\n\t\t\t\t\t\t\t\t   remainder, PARTIAL_BUFFER_SIZE ) );\n\t\t\tmemcpy( envelopeInfoPtr->partialBuffer + \\\n\t\t\t\t\t\tenvelopeInfoPtr->partialBufPos, bufPtr, remainder );\n\t\t\t}\n\t\theaderPtr = envelopeInfoPtr->partialBuffer;\n\t\theaderLength = envelopeInfoPtr->partialBufPos + remainder;\n\t\t}\n\n\t/* Try and get the next segment's information from the header data */\n\tstatus = getNextSegment( envelopeInfoPtr, headerPtr, headerLength, \n\t\t\t\t\t\t\t bytesConsumed );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we don't have enough input data left to read the information \n\t\t   for the next segment, buffer what we've got so far and tell the \n\t\t   caller that we've consumed all of our input */\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\tENSURES( *bytesConsumed <= 0 );\n\n\t\t\t/* Save the partial header information for next time */\n\t\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->partialBufPos,\n\t\t\t\t\t\t\t\t    length, PARTIAL_BUFFER_SIZE ) );\n\t\t\tmemcpy( envelopeInfoPtr->partialBuffer + \\\n\t\t\t\t\t\tenvelopeInfoPtr->partialBufPos, bufPtr, length );\n\t\t\tenvelopeInfoPtr->partialBufPos += length;\n\n\t\t\t/* We've absorbed any remaining data into the partial-header \n\t\t\t   buffer, tell the caller to exit */\n\t\t\t*bytesConsumed = length;\n\t\t\t*segAction = SEG_ACTION_CALLEREXIT;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\n\t/* We've got information on a new segment, clear the buffered header \n\t   data if necessary and adjust for how much data we've consumed */\n\tif( envelopeInfoPtr->partialBufPos > 0 )\n\t\t{\n\t\tENSURES( envelopeInfoPtr->partialBufPos <= *bytesConsumed );\n\n\t\t*bytesConsumed -= envelopeInfoPtr->partialBufPos;\n\t\tenvelopeInfoPtr->partialBufPos = 0;\n\t\t}\n\n\t/* If we've reached the EOC or consumed all of the input data, exit */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS ) || \\\n\t\t( length - *bytesConsumed ) <= 0 )\n\t\t{\n\t\t*segAction = SEG_ACTION_CALLEREXIT;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've got a new data segment, if it's of nonzero size we're done, \n\t   otherwise the caller has to try again */\n\t*segAction = ( envelopeInfoPtr->segmentSize > 0 ) ? \\\n\t\t\t\t SEG_ACTION_NONE : SEG_ACTION_CONTINUE;\t\t\t\t\t\t\t\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCopy to Envelope\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy encrypted data blocks into the envelope buffer with any overflow \n   held in the block buffer.  Only complete blocks are copied into the main\n   envelope buffer, if there's not enough data present for a complete block\n   it's temporarily held in the block buffer:\n\n\t\t\t bytesFromBB\t\t\t  bytesToBB\n\t\tbufPos--+ |\t\t\t\t\t\t  |\n\t\t\t\tv<+>|<-- qBytesToCopy ->|<+>|\n\t+-----------+-----------------------+\t|\n\t|\t\t\t|///|\t|\t\t|\t\t|\t|\t\tMain buffer\n\t+-----------+-----------------------+-------+\n\t\t\t\t  ^\t\t\t ^\t\t\t|///|\t|\tOverflow block buffer\n\t\t\t\t  |\t\t\t |\t\t\t+-------+\n\t\t\t Prev.bBuf\t  New data\t\t  ^\t\n\t\t\t contents\t\t\t\t\t  |\n\t\t\t\t\t\t\t\t\tNew data remaining */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int copyEncryptedDataBlocks( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t\t\t\t\t\tIN_LENGTH const int length,\n\t\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tBYTE *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;\n\tint bytesFromBB = 0, quantizedBytesToCopy, bytesToBB, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE && \\\n\t\t\t  envelopeInfoPtr->bufPos + \\\n\t\t\t\tenvelopeInfoPtr->blockBufferPos + \\\n\t\t\t\tlength <= envelopeInfoPtr->bufSize + \\\n\t\t\t\t\t\t  envelopeInfoPtr->blockSize );\n\tREQUIRES( !TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t  ENVDATA_FLAG_NOLENGTHINFO ) );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If the new data will fit entirely into the block buffer, copy it in\n\t   now and return */\n\tif( envelopeInfoPtr->blockBufferPos + length < envelopeInfoPtr->blockSize )\n\t\t{\n\t\tREQUIRES( boundsCheck( envelopeInfoPtr->blockBufferPos, length,\n\t\t\t\t\t\t\t   CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( envelopeInfoPtr->blockBuffer + envelopeInfoPtr->blockBufferPos, \n\t\t\t\tbuffer, length );\n\t\tenvelopeInfoPtr->blockBufferPos += length;\n\n\t\t/* Adjust the segment size based on what we've consumed */\n\t\tenvelopeInfoPtr->segmentSize -= length;\n\t\t*bytesCopied = length;\n\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there isn't room in the main buffer for even one more block, exit\n\t   without doing anything (bytesCopied is still set to zero from the \n\t   earlier code).  This leads to slightly anomalous behaviour where, \n\t   with no room for a complete block in the main buffer, copying in a \n\t   data length smaller than the block buffer will lead to the data being \n\t   absorbed by the block buffer due to the previous section of code, but \n\t   copying in a length larger than the block buffer will result in no \n\t   data at all being absorbed even if there's still room in the block \n\t   buffer, see the long comment in copyData() for a full discussion of \n\t   this process */\n\tif( envelopeInfoPtr->bufPos + \\\n\t\t\tenvelopeInfoPtr->blockSize > envelopeInfoPtr->bufSize )\n\t\t{\n\t\t/* There's no room for even one more block */\n\t\treturn( CRYPT_OK );\t\n\t\t}\n\n\t/* There's room for at least one more block in the buffer.  First, if\n\t   there are leftover bytes in the block buffer, move them into the main\n\t   buffer */\n\tif( envelopeInfoPtr->blockBufferPos > 0 )\n\t\t{\n\t\tREQUIRES( bytesFromBB >= 0 && \\\n\t\t\t\t  bytesFromBB <= envelopeInfoPtr->blockSize );\n\n\t\tbytesFromBB = envelopeInfoPtr->blockBufferPos;\n\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, bytesFromBB,\n\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\t\tmemcpy( bufPtr, envelopeInfoPtr->blockBuffer, bytesFromBB );\n\t\t}\n\tenvelopeInfoPtr->blockBufferPos = 0;\n\n\t/* Determine how many bytes we can copy into the buffer to fill it to\n\t   the nearest available block size */\n\tquantizedBytesToCopy = ( length + bytesFromBB ) & \\\n\t\t\t\t\t\t   envelopeInfoPtr->blockSizeMask;\n\tquantizedBytesToCopy -= bytesFromBB;\n\tENSURES( quantizedBytesToCopy > 0 && quantizedBytesToCopy <= length && \\\n\t\t\t envelopeInfoPtr->bufPos + bytesFromBB + \\\n\t\t\t\t\tquantizedBytesToCopy <= envelopeInfoPtr->bufSize );\n\tENSURES( ( ( bytesFromBB + quantizedBytesToCopy ) & \\\n\t\t\t   ( envelopeInfoPtr->blockSize - 1 ) ) == 0 );\n\n\t/* Now copy across a number of bytes which is a multiple of the block\n\t   size and decrypt them.  Note that we have to use memmove() rather\n\t   than memcpy() because if we're sync'ing data in the buffer we're\n\t   doing a copy within the buffer rather than copying in data from\n\t   an external source */\n\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos + bytesFromBB, \n\t\t\t\t\t\t\tquantizedBytesToCopy, \n\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\tmemmove( bufPtr + bytesFromBB, buffer, quantizedBytesToCopy );\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_AUTHENCACTIONSACTIVE ) )\n\t\t{\n\t\t/* We're performing authenticated encryotion, hash the ciphertext\n\t\t   before decrypting it */\n\t\tstatus = hashEnvelopeData( envelopeInfoPtr, bufPtr, \n\t\t\t\t\t\t\t\t   bytesFromBB + quantizedBytesToCopy );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( envelopeInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, bufPtr,\n\t\t\t\t\t\t\t  bytesFromBB + quantizedBytesToCopy );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tenvelopeInfoPtr->bufPos += bytesFromBB + quantizedBytesToCopy;\n\tenvelopeInfoPtr->segmentSize -= length;\n\tENSURES( envelopeInfoPtr->bufPos >= 0 && \\\n\t\t\tenvelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );\n\tENSURES( isIntegerRange( envelopeInfoPtr->segmentSize ) );\n\n\t/* If the payload has a definite length and we've reached its end, set\n\t   the EOC flag to make sure that we don't go any further */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\tenvelopeInfoPtr->segmentSize <= 0 )\n\t\t{\n\t\tstatus = processDataEnd( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t\t*bytesCopied = length;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Copy any remainder (the difference between the amount to copy and the\n\t   blocksize-quantized amount) into the block buffer */\n\tbytesToBB = length - quantizedBytesToCopy;\n\tREQUIRES( bytesToBB >= 0 && bytesToBB <= envelopeInfoPtr->blockSize );\n\tif( bytesToBB > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( quantizedBytesToCopy, bytesToBB, length ) );\n\t\tmemcpy( envelopeInfoPtr->blockBuffer, buffer + quantizedBytesToCopy,\n\t\t\t\tbytesToBB );\n\t\t}\n\tenvelopeInfoPtr->blockBufferPos = bytesToBB;\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t*bytesCopied = length;\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy possibly encrypted data into the envelope with special handling for\n   block encryption modes.  Returns the number of bytes copied:\n\n\t\t\t\t\t\t  bPos\t\t\t  bSize\n\t\t\t\t\t\t\t|\t\t\t\t|\n\t\t\t\t\t\t\tv\t\t\t\tv\n\t+-----------------------+---------------+\n\t|\t\t|\t\t|\t\t|\t\t|\t\t|\tMain buffer\n\t+-----------------------+---------------+\n\n\t\t\t\t\t\t\t+-------+\n\t\t\t\t\t\t\t|///|\t|\t\t\tOverflow block buffer\n\t\t\t\t\t\t\t+-------+\n\t\t\t\t\t\t\t\t^\t^\n\t\t\t\t\t\t\t\t|blBufSize\n\t\t\t\t\t\t\t blBufPos\n\n    The main buffer only contains data amounts quantised to the encryption\n\tblock size.  Any additional data is copied into the block buffer, a\n\tstaging buffer used to accumulate data until it can be transferred to\n\tthe main buffer for decryption */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int copyData( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t\t IN_DATALENGTH const int length,\n\t\t\t\t\t OUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tBYTE *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;\n\tint bytesToCopy = length, bytesLeft, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* Figure out how much we can copy across.  First we calculate the\n\t   minimum of the amount of data passed in and the amount remaining in\n\t   the current segment */\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_NOLENGTHINFO ) && \\\n\t\tbytesToCopy > envelopeInfoPtr->segmentSize )\n\t\tbytesToCopy = envelopeInfoPtr->segmentSize;\n\n\t/* Now we check to see if this is affected by the total free space\n\t   remaining in the buffer.  If we're processing data blocks we can have\n\t   two cases, one in which the limit is the amount of buffer space\n\t   available and the other in which the limit is the amount of data\n\t   available.  If the limit is set by the available data then we don't \n\t   have to worry about flushing extra data out of the block buffer into \n\t   the main buffer but if the limit is set by the available buffer space \n\t   we have to reduce the amount that we can copy in based on any extra \n\t   data that will be flushed out of the block buffer.\n\n\t   There are two possible approaches that can be used when the block\n\t   buffer is involved.  The first one copies as much as we can into the\n\t   buffer and, if that isn't enough, maxes out the block buffer with as\n\t   much remaining data as possible.  The second only copies in as much as\n\t   can fit into the buffer, even if there's room in the block buffer for\n\t   a few more bytes.  The second approach is preferable because although\n\t   either will give the impression of a not-quite-full buffer into which\n\t   no more data can be copied, the second minimizes the amount of data\n\t   which is moved into and out of the block buffer.\n\n\t   The first approach may seem slightly more logical, but will only\n\t   cause confusion in the long run.  Consider copying (say) 43 bytes to\n\t   a 43-byte buffer.  The first time this will succeed, after which there\n\t   will be 40 bytes in the buffer (reported to the caller) and 3 in the\n\t   block buffer.  If the caller tries to copy in 3 more bytes to \"fill\"\n\t   the main buffer, they'll again vanish into the block buffer.  A second\n\t   call with three more bytes will copy 2 bytes and return with 1 byte\n\t   uncopied.  In effect this method of using the block buffer extends the\n\t   blocksize-quantized main buffer by the size of the block buffer, which\n\t   will only cause confusion when data appears to vanish when copied into\n\t   it.\n\n\t   In the following length calculation the block buffer content is \n\t   counted as part of the total content in order to implement the second\n\t   buffer-filling strategy */\n\tbytesLeft = envelopeInfoPtr->bufSize - \\\n\t\t\t\t( envelopeInfoPtr->bufPos + envelopeInfoPtr->blockBufferPos );\n\tif( bytesLeft <= 0 )\n\t\t{\n\t\t/* There's no room left to copy anything in, return now (bytesCopied \n\t\t   is still set to zero from the earlier code).  We can't check this \n\t\t   in the calling code because it doesn't know about the internal \n\t\t   buffer-handling strategy that we use so we perform an explicit \n\t\t   check here */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( bytesLeft < bytesToCopy )\n\t\tbytesToCopy = bytesLeft;\n\tENSURES( bytesToCopy > 0 && bytesToCopy <= length );\n\n\t/* If its a block encryption mode then we need to provide special \n\t   handling for odd data lengths that don't match the block size */\n\tif( envelopeInfoPtr->blockSize > 1 )\n\t\t{\n\t\treturn( copyEncryptedDataBlocks( envelopeInfoPtr, buffer,\n\t\t\t\t\t\t\t\t\t\t bytesToCopy, bytesCopied ) );\n\t\t}\n\n\t/* It's unencrypted data or data that's encrypted with a stream cipher, \n\t   just copy over as much of the segment as we can and decrypt it if \n\t   necessary.  We use memmove() for the same reason as given above */\n\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos, bytesToCopy,\n\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\n\tmemmove( bufPtr, buffer, bytesToCopy );\n\tif( envelopeInfoPtr->iCryptContext != CRYPT_ERROR )\n\t\t{\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_AUTHENCACTIONSACTIVE ) )\n\t\t\t{\n\t\t\t/* We're performing authenticated encryption, MAC the \n\t\t\t   ciphertext before decrypting it (this is the technique that's \n\t\t\t   used for CMS data) */\n\t\t\tstatus = hashEnvelopeData( envelopeInfoPtr, bufPtr, bytesToCopy );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, bufPtr,\n\t\t\t\t\t\t\t\t  bytesToCopy );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_HASHACTIONSACTIVE ) )\n\t\t\t{\n\t\t\tint bytesToHash = bytesToCopy;\n\n\t\t\t/* We're performing integrity-protected encryption, hash the \n\t\t\t   plaintext after decrypting it (this is the technique that's\n\t\t\t   used for PGP data).\n\n\t\t\t   PGP complicates things further by optionally tacking an\n\t\t\t   MDC packet onto the end of the data payload, which is \n\t\t\t   encrypted but not hashed.  To handle this, if there's an\n\t\t\t   MDC packet present and we've reached the end of the payload \n\t\t\t   data then we have to adjust the amount of data that gets \n\t\t\t   hashed.  Using the length check to detect EOF is safe even\n\t\t\t   in the presence of indefinite-length data because \n\t\t\t   processPgpSegment() converts the last segment of indefinite-\n\t\t\t   length data into a definite-length one (so payloadSize != \n\t\t\t   CRYPT_UNUSED), and also ensures that there's enough data \n\t\t\t   present to contain a full MDC packet */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t   ENVDATA_FLAG_HASATTACHEDOOB ) && \\\n\t\t\t\tenvelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\t\t\tbytesToCopy >= envelopeInfoPtr->segmentSize )\n\t\t\t\t{\n\t\t\t\tbytesToHash -= PGP_MDC_PACKET_SIZE;\n\t\t\t\tENSURES( bytesToHash > 0 && bytesToHash < MAX_BUFFER_SIZE );\n\t\t\t\t}\n\t\t\tstatus = hashEnvelopeData( envelopeInfoPtr, bufPtr, bytesToHash );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tenvelopeInfoPtr->bufPos += bytesToCopy;\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_NOLENGTHINFO ) )\n\t\tenvelopeInfoPtr->segmentSize -= bytesToCopy;\n\n\t/* If the payload has a definite length and we've reached its end, set\n\t   the EOC flag to make sure that we don't go any further (this also\n\t   handles PGP's form of indefinite-length encoding in which each \n\t   segment except the last is indefinite-length and the last one is a\n\t   standard definite-length segment) */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\tenvelopeInfoPtr->segmentSize <= 0 )\n\t\t{\n\t\tstatus = processDataEnd( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\tENSURES( bytesToCopy > 0 && bytesToCopy <= length );\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t*bytesCopied = bytesToCopy;\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy data into the de-enveloping envelope.  Returns the number of bytes\n   copied */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int copyToDeenvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_BUFFER( length ) const BYTE *buffer, \n\t\t\t\t\t\t\t IN_LENGTH const int length )\n\t{\n\tBYTE *bufPtr = ( BYTE * ) buffer;\n\tconst int maxSegments = ( length <= FAILSAFE_ITERATIONS_LARGE * 1024 ) ? \\\n\t\t\t\t\t\t\t\tFAILSAFE_ITERATIONS_LARGE : \\\n\t\t\t\t\t\t\t\tlength / FAILSAFE_ITERATIONS_LARGE;\n\tint currentLength = length, bytesCopied, segmentCount, LOOP_ITERATOR;\n\t\t/* The calculation for maxIterations is necessary in order to deal \n\t\t   with the use of very large data quantities and buffers, if the\n\t\t   input data contains (say) 1K segments and 10MB of data then we\n\t\t   can exceed the fixed FAILSAFE_ITERATIONS_xxx value so we have to\n\t\t   adjust it dynamically based on the data size */\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( isIntegerRangeNZ( maxSegments ) );\n\n\t/* If we're trying to copy data into a full buffer, return a count of 0\n\t   bytes (the caller may convert this to an overflow error if \n\t   necessary) */\n\tif( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )\n\t\treturn( 0 );\n\n\t/* If we're verifying a detached signature, just hash the data and exit.\n\t   We don't have to check whether hashing is active or not because it'll\n\t   always be active for detached data since this is the only thing \n\t   that's done with it */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t{\n\t\tint status;\n\n\t\tREQUIRES( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t ENVDATA_FLAG_HASHACTIONSACTIVE ) );\n\n\t\tstatus = hashEnvelopeData( envelopeInfoPtr, buffer, currentLength );\n\t\treturn( cryptStatusError( status ) ? status : currentLength );\n\t\t}\n\n\t/* Keep processing data until we either run out of input or we can't copy\n\t   in any more data.  The code sequence within this loop acts as a simple\n\t   FSM so that if we exit at any point then the next call to this\n\t   function will resume where we left off */\n\tLOOP_MAX( segmentCount = 0,\n\t\t\t  segmentCount < maxSegments && currentLength > 0,\n\t\t\t  segmentCount++ )\n\t\t{\n\t\tSEG_ACTION_TYPE segAction = ( envelopeInfoPtr->segmentSize <= 0 ) ? \\\n\t\t\t\t\t\t\t\t\tSEG_ACTION_CONTINUE : SEG_ACTION_NONE;\n\t\tint subSegmentCount, status, LOOP_ITERATOR_ALT;\n\n\t\t/* If there's no segment information currently available then we \n\t\t   need to process a segment header before we can handle any data.  \n\t\t   The use of a loop is necessary to handle some broken \n\t\t   implementations that emit zero-length sub-segments, and as a \n\t\t   corollary it also helps avoid a pile of special-case code to \n\t\t   manage PGP's strange way of handling the last segment in \n\t\t   indefinite-length encodings.  We limit the segment count to 5\n\t\t   sub-segments to make sure that we don't  spend forever trying to \n\t\t   process extremely broken data */\n\t\tLOOP_SMALL_ALT( subSegmentCount = 0, \n\t\t\t\t\t\tsegAction == SEG_ACTION_CONTINUE && \\\n\t\t\t\t\t\t\tsubSegmentCount < 5,\n\t\t\t\t\t\tsubSegmentCount++ )\n\t\t\t{\n\t\t\tint bytesConsumed;\n\n\t\t\tstatus = processSegment( envelopeInfoPtr, bufPtr, currentLength, \n\t\t\t\t\t\t\t\t\t &bytesConsumed, &segAction );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tswitch( segAction )\n\t\t\t\t{\n\t\t\t\tcase SEG_ACTION_CALLEREXIT:\n\t\t\t\t\t{\n\t\t\t\t\tconst int bytesLeft = currentLength - bytesConsumed;\n\n\t\t\t\t\t/* We've completed processing the payload data, exit */\n\t\t\t\t\tENSURES( bytesLeft >= 0 && bytesLeft < length );\n\t\t\t\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\t\t\t\t\t\n\t\t\t\t\treturn( length - bytesLeft );\n\t\t\t\t\t}\n\n\t\t\t\tcase SEG_ACTION_BREAK:\n\t\t\t\t\t/* The data consists of a single segment, there's \n\t\t\t\t\t   nothing further to do.  Since segAction isn't set to \n\t\t\t\t\t   SEG_ACTION_CONTINUE, we'll exit the segment loop at \n\t\t\t\t\t   the end of this iteration */\n\t\t\t\t\tENSURES( bytesConsumed == 0 );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SEG_ACTION_CONTINUE:\n\t\t\t\tcase SEG_ACTION_NONE:\n\t\t\t\t\t/* We either need to process another segment in order to \n\t\t\t\t\t   continue or we've got segment information and can \n\t\t\t\t\t   exit the loop.\n\t\t\t\t\t   \n\t\t\t\t\t   We can get bytesConsumed == 0 if all input was taken\n\t\t\t\t\t   from the header buffer and the header itself was less\n\t\t\t\t\t   than MIN_HEADER_BYTES in size.  This occurs because\n\t\t\t\t\t   we don't try and process data quantities less than \n\t\t\t\t\t   MIN_HEADER_BYTES, if the header eventually fits inside\n\t\t\t\t\t   MIN_HEADER_BYTES then no data is consumed while \n\t\t\t\t\t   processing it */\n\t\t\t\t\tENSURES( bytesConsumed >= 0 );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\n\t\t\t/* Adjust the payload information by the amount of data that was\n\t\t\t   consumed and continue */\n\t\t\tbufPtr += bytesConsumed;\n\t\t\tcurrentLength -= bytesConsumed;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( subSegmentCount >= 5 )\n\t\t\t{\n\t\t\t/* We've processed 5 consecutive sub-segments in a row then \n\t\t\t   there's something wrong with the input data */\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tENSURES( currentLength > 0 && currentLength <= length && \\\n\t\t\t\t currentLength < MAX_BUFFER_SIZE );\n\n\t\t/* Copy the data into the envelope, decrypting it as we go if\n\t\t   necessary.  In theory we could also check to see whether any\n\t\t   more data can fit into the buffer before trying to copy it in\n\t\t   but since this would require knowledge of the internal buffer-\n\t\t   handling strategy used by copyData() we always call it and rely\n\t\t   on a bytesCopied value of zero to indicate that the tank is\n\t\t   full */\n\t\tstatus = copyData( envelopeInfoPtr, bufPtr, currentLength, \n\t\t\t\t\t\t   &bytesCopied );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tbufPtr += bytesCopied;\n\t\tcurrentLength -= bytesCopied;\n\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\t\tENSURES( currentLength >= 0 && currentLength <= length && \\\n\t\t\t\t currentLength < MAX_BUFFER_SIZE );\n\n\t\t/* If we couldn't copy any more data then we're done */\n\t\tif( bytesCopied <= 0 )\n\t\t\tbreak;\n\n\t\tassert( ( envelopeInfoPtr->segmentSize >= 0 ) || \\\n\t\t\t\t( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t ENVDATA_FLAG_NOSEGMENT ) && \\\n\t\t\t\t  ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) && \\\n\t\t\t\t  ( envelopeInfoPtr->segmentSize == CRYPT_UNUSED ) ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( segmentCount >= maxSegments )\n\t\t{\n\t\t/* We've processed a huge number of segments, there's something \n\t\t   wrong with the input */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\treturn( length - currentLength );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCopy from Envelope\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy buffered out-of-band data from earlier processing to the output.  \n   This is only required for PGP envelopes where we have to burrow down into\n   nested content in order to figure out what to do with it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int copyOobData( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\tOUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *length,\n\t\t\t\t\t\tconst BOOLEAN retainInBuffer )\n\t{\n\tconst int oobBytesToCopy = min( maxLength, envelopeInfoPtr->oobBufSize );\n\tconst int oobRemainder = envelopeInfoPtr->oobBufSize - oobBytesToCopy;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( retainInBuffer == TRUE || retainInBuffer == FALSE );\n\tREQUIRES( oobBytesToCopy > 0 && \\\n\t\t\t  oobBytesToCopy <= envelopeInfoPtr->oobBufSize && \\\n\t\t\t  oobBytesToCopy <= OOB_BUFFER_SIZE );\n\n\tREQUIRES( rangeCheck( oobBytesToCopy, 1, OOB_BUFFER_SIZE ) );\n\tmemcpy( buffer, envelopeInfoPtr->oobBuffer, oobBytesToCopy );\n\t*length = oobBytesToCopy;\n\n\t/* If we're retaining the data in the OOB, we're done */\n\tif( retainInBuffer )\n\t\t{\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We're moving data out of the OOB buffer, adjust the OOB buffer \n\t   contents */\n\tif( oobRemainder > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( oobBytesToCopy, oobRemainder,\n\t\t\t\t\t\t\t   OOB_BUFFER_SIZE ) );\n\t\tmemmove( envelopeInfoPtr->oobBuffer,\n\t\t\t\t envelopeInfoPtr->oobBuffer + oobBytesToCopy, oobRemainder );\n\t\t}\n\tenvelopeInfoPtr->oobBufSize = oobRemainder;\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Copy data from the envelope.  Returns the number of bytes copied */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int copyFromDeenvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t   OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t   IN_FLAGS_Z( ENVCOPY ) const int flags )\n\t{\n\tconst BOOLEAN isLookaheadRead = ( flags & ENVCOPY_FLAG_OOBDATA ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE;\n\tint bytesToCopy = maxLength, bytesCopied, oobBytesCopied = 0;\n\tint remainder, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( !isLookaheadRead || \\\n\t\t\t  ( isLookaheadRead && \\\n\t\t\t    ( bytesToCopy > 0 && bytesToCopy <= OOB_BUFFER_SIZE ) ) );\n\tREQUIRES( flags == ENVCOPY_FLAG_NONE || flags == ENVCOPY_FLAG_OOBDATA );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bytesToCopy ) );\n\t*length = 0;\n\n\t/* If we're verifying a detached signature the data is communicated \n\t   out-of-band so there's nothing to copy out (the length is still set\n\t   to zero from the earlier code */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If there's buffered out-of-band data from an earlier lookahead read \n\t   present, insert it into the output stream */\n\tif( envelopeInfoPtr->oobBufSize > 0 )\n\t\t{\n\t\tstatus = copyOobData( envelopeInfoPtr, buffer, bytesToCopy, \n\t\t\t\t\t\t\t  &oobBytesCopied, isLookaheadRead );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tbytesToCopy -= oobBytesCopied;\n\t\tbuffer += oobBytesCopied;\n\t\tif( bytesToCopy <= 0 )\n\t\t\t{\n\t\t\t*length = oobBytesCopied;\n\n\t\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( bytesToCopy > 0 && bytesToCopy <= maxLength && \\\n\t\t\t bytesToCopy < MAX_BUFFER_SIZE );\n\n\t/* If we're using compression, expand the data from the buffer to the\n\t   output via the zStream */\n#ifdef USE_COMPRESSION\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED ) )\n\t\t{\n\t\tconst int originalInLength = bytesToCopy;\n\t\tconst int bytesIn = \\\n\t\t\t( envelopeInfoPtr->dataLeft > 0 && \\\n\t\t\t  envelopeInfoPtr->dataLeft < envelopeInfoPtr->bufPos ) ? \\\n\t\t\tenvelopeInfoPtr->dataLeft : envelopeInfoPtr->bufPos;\n\n\t\t/* Decompress the data into the output buffer.  Note that we use the\n\t\t   length value to determine the length of the output rather than\n\t\t   bytesToCopy since the ratio of bytes in the buffer to bytes of\n\t\t   output isn't 1:1 as it is for other content types.\n\n\t\t   When using PGP 2.x-compatible decompression we have to allow a\n\t\t   return status of Z_BUF_ERROR because it uses a compression format\n\t\t   from a pre-release version of InfoZip that doesn't include\n\t\t   header or trailer information so the decompression code can't\n\t\t   definitely tell that it's reached the end of its input data but\n\t\t   can only report that it can't go any further.\n\n\t\t   When we're trying to suck all remaining compressed data from the \n\t\t   zstream we may get a (rather misleadingly named) Z_BUF_ERROR if \n\t\t   there's both no internally buffered data left and no new input \n\t\t   available to produce any output.  If this is the case we simply\n\t\t   treat it as a nothing-copied condition, since decompression will\n\t\t   continue when the user provides more input.\n\n\t\t   We can also get a Z_BUF_ERROR for some types of (non-fatal) error\n\t\t   situations, for example if we're flushing out data still present\n\t\t   in the zstream (avail_in == 0) and there's a problem such as the\n\t\t   compressor needing more data but there's none available, the zlib\n\t\t   code will report it as a Z_BUF_ERROR.  In this case we convert it\n\t\t   into a (recoverable) underflow error, which isn't always accurate\n\t\t   but is more useful than the generic CRYPT_ERROR_FAILED */\n\t\tenvelopeInfoPtr->zStream.next_in = envelopeInfoPtr->buffer;\n\t\tenvelopeInfoPtr->zStream.avail_in = bytesIn;\n\t\tenvelopeInfoPtr->zStream.next_out = buffer;\n\t\tenvelopeInfoPtr->zStream.avail_out = bytesToCopy;\n\t\tstatus = inflate( &envelopeInfoPtr->zStream, Z_SYNC_FLUSH );\n\t\tif( status != Z_OK && status != Z_STREAM_END && \\\n\t\t\t!( status == Z_BUF_ERROR && \\\n\t\t\t   envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) && \\\n\t\t\t!( status == Z_BUF_ERROR && bytesIn == 0 ) )\n\t\t\t{\n\t\t\tENSURES( status != Z_STREAM_ERROR );\t/* Parameter error */\n\t\t\treturn( ( status == Z_DATA_ERROR ) ? CRYPT_ERROR_BADDATA : \\\n\t\t\t\t\t( status == Z_MEM_ERROR ) ? CRYPT_ERROR_MEMORY : \\\n\t\t\t\t\t( status == Z_BUF_ERROR ) ? CRYPT_ERROR_UNDERFLOW : \\\n\t\t\t\t\tCRYPT_ERROR_FAILED );\n\t\t\t}\n\n\t\t/* Adjust the status information based on the data copied from the\n\t\t   buffer into the zStream (bytesCopied) and the data flushed from\n\t\t   the zStream to the output (bytesToCopy) */\n\t\tbytesCopied = bytesIn - envelopeInfoPtr->zStream.avail_in;\n\t\tbytesToCopy -= envelopeInfoPtr->zStream.avail_out;\n\t\tENSURES( bytesCopied >= 0 && bytesCopied < MAX_BUFFER_SIZE && \\\n\t\t\t\t bytesToCopy >= 0 && bytesToCopy <= originalInLength && \\\n\t\t\t\t bytesToCopy < MAX_BUFFER_SIZE );\n\n\t\t/* If we're doing a lookahead read we can't just copy the data out \n\t\t   of the envelope buffer as we would for any other content type \n\t\t   because we can't undo the decompression step, so we copy the data \n\t\t   that was decompressed into the output buffer to a local buffer \n\t\t   and insert it into the output stream on the next non-lookahead \n\t\t   read.  The size of the read from the OOB buffer has been limited\n\t\t   previously when existing data was detected in the OOB buffer so \n\t\t   the total of the current OOB buffer contents and the amount to \n\t\t   read can never exceed the OOB buffer size */\n\t\tif( isLookaheadRead )\n\t\t\t{\n\t\t\tREQUIRES( envelopeInfoPtr->oobBufSize + \\\n\t\t\t\t\t  originalInLength <= OOB_BUFFER_SIZE );\n\n\t\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->oobBufSize, \n\t\t\t\t\t\t\t\t\toriginalInLength, OOB_BUFFER_SIZE ) );\n\t\t\tmemcpy( envelopeInfoPtr->oobBuffer + envelopeInfoPtr->oobBufSize,\n\t\t\t\t\tbuffer, originalInLength );\n\t\t\tenvelopeInfoPtr->oobBufSize += originalInLength;\n\t\t\t}\n\t\t}\n\telse\n#endif /* USE_COMPRESSION */\n\t\t{\n\t\t/* Copy out as much of the data as we can, making sure that we don't\n\t\t   overrun into any following data */\n\t\tif( bytesToCopy > envelopeInfoPtr->bufPos )\n\t\t\tbytesToCopy = envelopeInfoPtr->bufPos;\n\t\tif( envelopeInfoPtr->dataLeft > 0 && \\\n\t\t\tbytesToCopy > envelopeInfoPtr->dataLeft )\n\t\t\tbytesToCopy = envelopeInfoPtr->dataLeft;\n\t\tENSURES( bytesToCopy >= 0 && bytesToCopy <= maxLength && \\\n\t\t\t\t bytesToCopy < MAX_BUFFER_SIZE );\n\n\t\t/* We perform the postcondition check here because there are \n\t\t   numerous exit points in the following code and this avoids having \n\t\t   to check at every one */\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\n\t\t/* If we're using a block encryption mode and we haven't seen the\n\t\t   end-of-contents yet and there's no data waiting in the block\n\t\t   buffer (which would mean that there's more data to come), we\n\t\t   can't copy out the last block because it might contain padding,\n\t\t   so we decrease the effective data amount by one block's worth.\n\n\t\t   Note that this overestimates the amount to retain by up to \n\t\t   blockSize bytes since we really need to count from the start \n\t\t   rather than the end of the data.  That is, if the caller pushes \n\t\t   in blockSize + 1 bytes then we could pop up to blockSize bytes \n\t\t   since the caller has to push at least blockSize - 1 further bytes \n\t\t   to complete the next block.  The current strategy of always \n\t\t   reserving a full block only allows 1 byte to be popped. \n\n\t\t   Keeping track of how many complete blocks have been processed \n\t\t   just to handle this obscure corner case really isn't worth it, \n\t\t   due to a coding bug this check was performed incorrectly and it \n\t\t   took nine years before anyone triggered it so it's not worth \n\t\t   adding additional handling for this situation */\n\t\tif( envelopeInfoPtr->blockSize > 1 && \\\n\t\t\t!TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\tENVDATA_FLAG_ENDOFCONTENTS ) && \\\n\t\t\tenvelopeInfoPtr->blockBufferPos <= 0 )\n\t\t\tbytesToCopy -= envelopeInfoPtr->blockSize;\n\n\t\t/* If we've ended up with nothing to copy (e.g. due to blocking\n\t\t   requirements), exit */\n\t\tif( bytesToCopy <= 0 )\n\t\t\t{\n\t\t\t*length = oobBytesCopied;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tENSURES( bytesToCopy > 0 && bytesToCopy < MAX_BUFFER_SIZE );\n\n\t\t/* If we've seen the end-of-contents octets and there's no payload\n\t\t   left to copy out, exit */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS ) && \\\n\t\t\tenvelopeInfoPtr->dataLeft <= 0 )\n\t\t\t{\n\t\t\t*length = oobBytesCopied;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* If we're doing a lookahead read just copy the data out without\n\t\t   adjusting the read-data values */\n\t\tif( isLookaheadRead )\n\t\t\t{\n\t\t\tREQUIRES( bytesToCopy > 0 && bytesToCopy <= OOB_BUFFER_SIZE );\n\n\t\t\tREQUIRES( rangeCheck( bytesToCopy, 1, maxLength ) );\n\t\t\tmemcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );\n\t\t\t*length = bytesToCopy;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Hash the payload data if necessary.  This is used for signed/\n\t\t   authenticated-data hashing, PGP also hashes the payload for \n\t\t   encrypted data when it's generating an MDC but that needs to be \n\t\t   done as part of the decryption due to special-case processing \n\t\t   requirements */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_HASHACTIONSACTIVE ) && \\\n\t\t\tenvelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\t{\n\t\t\tstatus = hashEnvelopeData( envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->buffer, \n\t\t\t\t\t\t\t\t\t   bytesToCopy );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We're not using compression, copy the data across directly */\n\t\tREQUIRES( rangeCheck( bytesToCopy, 1, maxLength ) );\n\t\tmemcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );\n\t\tbytesCopied = bytesToCopy;\n\t\t}\n\tENSURES( envelopeInfoPtr->bufPos - bytesCopied >= 0 );\n\n\t/* Move any remaining data down to the start of the buffer  */\n\tremainder = envelopeInfoPtr->bufPos - bytesCopied;\n\tENSURES( remainder >= 0 && remainder < MAX_BUFFER_SIZE && \\\n\t\t\t bytesCopied >= 0 && bytesCopied < MAX_BUFFER_SIZE && \\\n\t\t\t bytesCopied + remainder <= envelopeInfoPtr->bufSize );\n\tif( remainder > 0 && bytesCopied > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( bytesCopied, remainder, \n\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\n\t\tmemmove( envelopeInfoPtr->buffer, \n\t\t\t\t envelopeInfoPtr->buffer + bytesCopied, remainder );\n\t\t}\n\tenvelopeInfoPtr->bufPos = remainder;\n\n\t/* If there's data following the payload, adjust the end-of-payload\n\t   pointer to reflect the data that we've just copied out */\n\tif( envelopeInfoPtr->dataLeft > 0 && bytesCopied > 0 )\n\t\tenvelopeInfoPtr->dataLeft -= bytesCopied;\n\tENSURES( isIntegerRange( envelopeInfoPtr->dataLeft ) );\n\t*length = oobBytesCopied + bytesToCopy;\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tExtra Data Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Synchronise the deenveloping data stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int syncDeenvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\tconst long dataStartPos = stell( stream );\n\tconst int oldBufPos = envelopeInfoPtr->bufPos;\n\tconst int bytesLeftToCopy = sMemDataLeft( stream );\n\tint bytesCopied;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( dataStartPos >= 0 && dataStartPos < MAX_BUFFER_SIZE );\n\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t/* After the envelope header has been processed, what's left is payload\n\t   data that requires special processing because of segmenting and\n\t   decryption and hashing requirements, so we feed it in via a\n\t   copyToDeenvelope() of the data in the buffer.  This is a rather ugly\n\t   hack, but it works because we're moving data backwards in the buffer\n\t   so there shouldn't be any problems for the rare instances where the\n\t   data overlaps.  In the worst case (PKCS #7/CMS short definite-length\n\t   OCTET STRING) we only consume two bytes, the tag and one-byte length,\n\t   but since we're using memmove() in copyData() this shouldn't be a\n\t   problem.\n\n\t   Since we're in effect restarting from the payload data, we reset\n\t   everything that counts to point back to the start of the buffer where\n\t   we'll be moving the payload data.  We don't have to worry about the\n\t   copyToDeenvelope() overflowing the envelope since the source is the\n\t   envelope buffer so the data must fit within the envelope */\n\tenvelopeInfoPtr->bufPos = 0;\n\tif( bytesLeftToCopy <= 0 )\n\t\t{\n\t\t/* Handle the special case of the data ending at exactly this \n\t\t   point.  There's nothing further to do since all data has been\n\t\t   consumed and the next push will give us the payload data */\n\t\tsseek( stream, 0 );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tsMemDisconnect( stream );\n\tsMemConnect( stream, envelopeInfoPtr->buffer, bytesLeftToCopy );\n\tbytesCopied = copyToEnvelopeFunction( envelopeInfoPtr,\n\t\t\t\t\t\t\tenvelopeInfoPtr->buffer + dataStartPos, \n\t\t\t\t\t\t\tbytesLeftToCopy );\n\tif( cryptStatusError( bytesCopied ) )\n\t\t{\n\t\t/* Undo the buffer position reset.  This isn't 100% effective if\n\t\t   there are multiple segments present and we hit an error after\n\t\t   we've copied down enough data to overwrite what's at the start,\n\t\t   but in most cases it allows us to undo the copyToEnvelope(), and \n\t\t   if the data is corrupted we won't be able to get any further \n\t\t   anyway */\n\t\tenvelopeInfoPtr->bufPos = oldBufPos;\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\t\treturn( bytesCopied );\n\t\t}\n\tENSURES( bytesCopied >= 0 && bytesCopied < MAX_BUFFER_SIZE );\n\n\t/* If we copied over less than the total available and have hit the\n\t   end-of-data marker it means that there's extra data following the\n\t   payload.  We need to move this down to the end of the decoded payload \n\t   data since copyToDeenvelope() stops copying as soon as it hits the \n\t   end-of-data.  We use memmove() rather than memcpy() for this since \n\t   we're copying to/from the same buffer:\n\n\t\t\t\t  dataStartPos\n\t\t\t\t\t\t|\n\t\t\t\t\t\tv<--- bLeft --->|\n\t\t+---------------+---------------+--------\n\t\t|\t\t\t\t|///////////////|\t\t\tStart\n\t\t+---------------+---------------+--------\n\n\t\t\t\t  dataStartPos\n\t\t\t\t\t\t|\n\t\t|<- bCop -->|\tv\t\t|<-bToC>|\n\t\t+---------------+---------------+--------\n\t\t|//payload//|\t|\t\t|///////|\t\t\tAfter copyToDeenvelope\n\t\t+---------------+---------------+--------\n\t\t\t\t\t^\t\t\t^\n\t\t\t\t\t|\t\t\t|\n\t\t\t\tdataLeft  dStartPos + bCopied\n\n\t\t+-----------+-------+--------------------\n\t\t|//payload//|///////|\t\t\t\t\t\tEOC\n\t\t+-----------+-------+--------------------\n\t\t\t\t\t^\t\t^\n\t\t\t\t\t|\t\t|\n\t\t\t\t dLeft\t  bufPos */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS ) && \\\n\t\tbytesCopied < bytesLeftToCopy )\n\t\t{\n\t\tconst int bytesToCopy = bytesLeftToCopy - bytesCopied;\n\n\t\tREQUIRES( bytesToCopy > 0 && bytesToCopy < MAX_BUFFER_SIZE );\n\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->dataLeft, bytesToCopy,\n\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufSize ) );\t/* Write */\n\t\tREQUIRES( boundsCheck( dataStartPos + bytesCopied, bytesToCopy,\n\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\t/* Read */\n\t\tmemmove( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,\n\t\t\t\t envelopeInfoPtr->buffer + dataStartPos + bytesCopied,\n\t\t\t\t bytesToCopy );\n\t\tenvelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + bytesToCopy;\n\n\t\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* At this point we've copied everything over */\n\tENSURES( bytesCopied == bytesLeftToCopy );\n\n\tENSURES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Process additional out-of-band data that doesn't get copied into/out of\n   the de-enveloping envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processExtraData( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_BUFFER( length ) const void *buffer, \n\t\t\t\t\t\t\t IN_DATALENGTH_Z const int length )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( length == 0 || isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckEnvDecode( envelopeInfoPtr ) );\n\tREQUIRES( length >= 0 && length < MAX_BUFFER_SIZE );\n\n\t/* If the hash value was supplied externally (which means that there's\n\t   nothing for us to hash since it's already been done by the caller),\n\t   there won't be any hash actions active and we can return immediately */\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags,\n\t\t\t\t\tENVDATA_FLAG_HASHACTIONSACTIVE | \\\n\t\t\t\t\tENVDATA_FLAG_AUTHENCACTIONSACTIVE ) )\n\t\t{\n\t\treturn( ( length > 0 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );\n\t\t}\n\n\t/* If we're still processing data, hash it.  Since authenticated-\n\t   encrypted content hashes the ciphertext before decryption rather than \n\t   the plaintext we only perform hashing of nonzero-length data if we're \n\t   working with straight signed or MACed data */\n\tif( length > 0 )\n\t\t{\n\t\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\tENVDATA_FLAG_HASHACTIONSACTIVE ) )\n\t\t\treturn( CRYPT_OK );\n\t\treturn( hashEnvelopeData( envelopeInfoPtr, buffer, length ) );\n\t\t}\n\n\t/* We're finishing up the hashing, clear the hashing-active flag to\n\t   prevent data from being hashed again if it's processed by other\n\t   code such as copyFromDeenvelope() */\n\tstatus = hashEnvelopeData( envelopeInfoPtr, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\tENVDATA_FLAG_HASHACTIONSACTIVE | \\\n\t\t\t\tENVDATA_FLAG_AUTHENCACTIONSACTIVE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initDeenvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->copyToEnvelopeFunction, copyToDeenvelope );\n\tFNPTR_SET( envelopeInfoPtr->copyFromEnvelopeFunction, copyFromDeenvelope );\n\tFNPTR_SET( envelopeInfoPtr->syncDeenvelopeDataFunction, syncDeenvelopeData );\n\tFNPTR_SET( envelopeInfoPtr->processExtraDataFunction, processExtraData );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/envelope/encode.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Datagram Encoding Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n/*\t\t\t .... NO! ...\t\t\t\t   ... MNO! ...\n\t\t   ..... MNO!! ...................... MNNOO! ...\n\t\t ..... MMNO! ......................... MNNOO!! .\n\t\t.... MNOONNOO!\t MMMMMMMMMMPPPOII!\t MNNO!!!! .\n\t\t ... !O! NNO! MMMMMMMMMMMMMPPPOOOII!! NO! ....\n\t\t\t...... ! MMMMMMMMMMMMMPPPPOOOOIII! ! ...\n\t\t   ........ MMMMMMMMMMMMPPPPPOOOOOOII!! .....\n\t\t   ........ MMMMMOOOOOOPPPPPPPPOOOOMII! ...\n\t\t\t....... MMMMM..\t   OPPMMP\t .,OMI! ....\n\t\t\t ...... MMMM::\t o.,OPMP,.o\t  ::I!! ...\n\t\t\t\t .... NNM:::.,,OOPM!P,.::::!! ....\n\t\t\t\t  .. MMNNNNNOOOOPMO!!IIPPO!!O! .....\n\t\t\t\t ... MMMMMNNNNOO:!!:!!IPPPPOO! ....\n\t\t\t\t   .. MMMMMNNOOMMNNIIIPPPOO!! ......\n\t\t\t\t  ...... MMMONNMMNNNIIIOO!..........\n\t\t\t   ....... MN MOMMMNNNIIIIIO! OO ..........\n\t\t\t......... MNO! IiiiiiiiiiiiI OOOO ...........\n\t\t  ...... NNN.MNO! . O!!!!!!!!!O . OONO NO! ........\n\t\t   .... MNNNNNO! ...OOOOOOOOOOO .  MMNNON!........\n\t\t   ...... MNNNNO! .. PPPPPPPPP .. MMNON!........\n\t\t\t  ...... OO! ................. ON! .......\n\t\t\t\t ................................\n\n   Be very careful when modifying this code, the data manipulation that it\n   performs is somewhat tricky */\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckEnvEncode( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Make sure that the buffer position is within bounds */\n\tif( envelopeInfoPtr->buffer == NULL || \\\n\t\tenvelopeInfoPtr->bufPos < 0 || \\\n\t\tenvelopeInfoPtr->bufPos > envelopeInfoPtr->bufSize || \\\n\t\tenvelopeInfoPtr->bufSize < MIN_BUFFER_SIZE || \\\n\t\tenvelopeInfoPtr->bufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the block buffer position is within bounds */\n\tif( envelopeInfoPtr->blockSize > 0 && \\\n\t\t( envelopeInfoPtr->blockBufferPos < 0 || \\\n\t\t  envelopeInfoPtr->blockBufferPos >= envelopeInfoPtr->blockSize || \\\n\t\t  envelopeInfoPtr->blockSize > CRYPT_MAX_IVSIZE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Block buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the partial and out-of-band data buffer positions are \n\t   clear (they're only used for de-enveloping) */\n\tif( envelopeInfoPtr->partialBufPos != 0 || \\\n\t\tenvelopeInfoPtr->oobBufSize != 0 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Spurious OOB/partial buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we're drained the envelope buffer, we're done */\n\tif( envelopeInfoPtr->segmentStart == 0 && \\\n\t\tenvelopeInfoPtr->segmentDataStart == 0 && \\\n\t\tenvelopeInfoPtr->bufPos == 0 )\n\t\treturn( TRUE );\n\n\t/* Make sure that the buffer internal bookeeping is OK.  First we apply \n\t   the general one-size-fits-all checks, then we apply further \n\t   situation-specific checks */\n\tif( envelopeInfoPtr->segmentStart < 0 || \\\n\t\tenvelopeInfoPtr->segmentStart > envelopeInfoPtr->segmentDataStart || \\\n\t\tenvelopeInfoPtr->segmentStart > MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Segment start\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( envelopeInfoPtr->segmentDataStart < 0 || \\\n\t\tenvelopeInfoPtr->segmentDataStart > envelopeInfoPtr->bufPos || \\\n\t\tenvelopeInfoPtr->segmentDataStart > MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Segment data start\" ));\n\t\treturn( FALSE );\n\t\t}\n\t\n\t/* The situation-specific checks get a bit complicated because we have \n\t   to distinguish between definite- and indefinite-length encodings.  \n\t   For the definite length segmentStart == segmentDataStart since there \n\t   are no intermediate segment headers, for the indefinite length \n\t   segmentStart < segmentDataStart to accomodate the intervening header.\n\n\t   In some rare cases segmentDataStart can be the same as bufPos if \n\t   we're using compression and all input data was absorbed by the \n\t   zStream buffer so we check for segmentDataStart > bufPos rather than \n\t   segmentDataStart >= bufPos */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\t{\n\t\t/* It's a non-segmenting encoding so segmentStart must track \n\t\t   segmentDataStart */\n\t\tif( envelopeInfoPtr->segmentStart != \\\n\t\t\t\t\t\tenvelopeInfoPtr->segmentDataStart )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Non-segmented encoding\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\tif( envelopeInfoPtr->segmentStart >= envelopeInfoPtr->bufPos )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Segmented encoding\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_SEGMENTCOMPLETE ) )\n\t\t{\n\t\t/* If we're just started a new segment and there's no data left in \n\t\t   the envelope buffer, segmentStart may be the same as \n\t\t   segmentDataStart */\n\t\tif( envelopeInfoPtr->segmentStart == 0 && \\\n\t\t\tenvelopeInfoPtr->segmentDataStart == 0 )\n\t\t\treturn( TRUE );\n\t\t}\n\tif( envelopeInfoPtr->segmentStart >= envelopeInfoPtr->segmentDataStart )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvEncode: Segmented encoding nesting\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Apply the hash/MAC actions in the action list to data.  This function is \n   shared with decode.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashEnvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_Z const int dataLength )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( dataLength == 0 || isReadPtrDynamic( data, dataLength ) );\n\n\t/* Since this function is shared by the enveloping and de-enveloping \n\t   code, we can't do a specific sanity-check but have to make do with\n\t   a generic check.  We could in theory check \n\t   envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE and call the \n\t   appropriate function, but the enveloping one isn't visible here.  In \n\t   addition the additional number of checks applied in the env/de-env\n\t   specific functions is minor, and the state will already have been \n\t   checked by the caller before this low-level function was reached */\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( data != NULL );\n\tREQUIRES( dataLength >= 0 && dataLength < MAX_BUFFER_SIZE );\n\n\tLOOP_MED( actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ),\n\t\t\t  actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\t/* If we're using authenticated encryption there may be other \n\t\t   actions present in the action list so we only hash/MAC where\n\t\t   required */\n\t\tif( actionListPtr->action != ACTION_HASH && \\\n\t\t\tactionListPtr->action != ACTION_MAC )\n\t\t\tcontinue;\n\n\t\t/* If the hashing has already been completed due to it being an\n\t\t   externally-supplied value for a detached signature, we don't need \n\t\t   to do anything further */\n\t\tif( TEST_FLAG( actionListPtr->flags, ACTION_FLAG_HASHCOMPLETE ) )\n\t\t\t{\n\t\t\tREQUIRES( dataLength == 0 );\n\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data, \n\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHeader Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine the length of the encoded length value and the threshold at which the\n   length encoding changes for constructed indefinite-length strings.  The\n   length encoding is the actual length if <= 127, or a one-byte length-of-\n   length followed by the length if > 127 */\n\n#define TAG_SIZE\t\t\t\t\t1\t/* Useful symbolic define */\n\n#if INT_MAX > 32767\n\n#define lengthOfLength( length )\t( ( length < 0x80 ) ? 1 : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x100 ) ? 2 : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x10000 ) ? 3 : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x1000000 ) ? 4 : 5 )\n\n#define findThreshold( length )\t\t( ( length < 0x80 ) ? 0x7F : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x100 ) ? 0xFF : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x10000 ) ? 0xFFFF : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x1000000 ) ? 0xFFFFFF : INT_MAX )\n#else\n\n#define lengthOfLength( length )\t( ( length < 0x80 ) ? 1 : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x100 ) ? 2 : 3 )\n\n#define findThreshold( length )\t\t( ( length < 0x80 ) ? 127 : \\\n\t\t\t\t\t\t\t\t\t  ( length < 0x100 ) ? 0xFF : INT_MAX )\n#endif /* 32-bit ints */\n\n/* Begin a new segment in the buffer.  The layout is:\n\n\t\t  bufPos\n\t\t\tv\n\t\t\ttag\tlen\t\t payload\n\t+-------+-+---+---------------------+-------+\n\t|\t\t| |\t  |\t\t\t\t\t\t|\t\t|\n\t+-------+-+---+---------------------+-------+\n\t\t\t^\t  ^\t\t\t\t\t\t^\n\t\t\t|\t  |\t\t\t\t\t\t|\n\t\t sStart sDataStart\t\t\tsDataEnd \n\n   If we're using a definite-length encoding then \n   segmentStart == segmentDataStart = bufPos */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int beginSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint segHeaderSize = 0;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\n\t/* If we're using an indefinite-length encoding we have to factor in the \n\t   length of the segment header.  Since we can't determine the overall\n\t   segment data size at this point we use a worst-case estimate in which\n\t   the segment fills the entire buffer */\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\tsegHeaderSize = TAG_SIZE + \\\n\t\t\t\t\t\tlengthOfLength( envelopeInfoPtr->bufSize );\n\t\t}\n\n\t/* Make sure that there's enough room in the buffer to accommodate the\n\t   start of a new segment.  In the worst case this is 6 bytes (OCTET\n\t   STRING tag + 5-byte length) + 15 bytes (blockBuffer contents for a\n\t   128-bit block cipher).  Although in practice we could eliminate this\n\t   condition, it would require tracking a lot of state information to\n\t   record which data had been encoded into the buffer and whether the\n\t   blockBuffer data had been copied into the buffer, so to keep it\n\t   simple we require enough room to do everything at once */\n\tif( envelopeInfoPtr->bufPos + segHeaderSize + \\\n\t\t\tenvelopeInfoPtr->blockBufferPos >= envelopeInfoPtr->bufSize )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Adjust the buffer position indicators to handle potential\n\t   intermediate headers */\n\tenvelopeInfoPtr->segmentStart = envelopeInfoPtr->bufPos;\n\tif( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )\n\t\t{\n\t\t/* Begin a new segment after the end of the current segment.  We\n\t\t   always leave enough room for the largest allowable length field\n\t\t   because we may have a short segment at the end of the buffer which\n\t\t   is moved to the start of the buffer after data is copied out,\n\t\t   turning it into a longer segment.  For this reason we rely on\n\t\t   completeSegment() to get the length right and move any data down\n\t\t   as required */\n\t\tenvelopeInfoPtr->bufPos += segHeaderSize;\n\t\t}\n\tenvelopeInfoPtr->segmentDataStart = envelopeInfoPtr->bufPos;\n\tENSURES( envelopeInfoPtr->bufPos + \\\n\t\t\t envelopeInfoPtr->blockBufferPos <= envelopeInfoPtr->bufSize );\n\n\t/* Now copy anything left in the block buffer to the start of the new\n\t   segment.  We know that everything will fit because we've checked\n\t   earlier on that the header and blockbuffer contents will fit into\n\t   the remaining space */\n\tif( envelopeInfoPtr->blockBufferPos > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheckZ( envelopeInfoPtr->bufPos,\n\t\t\t\t\t\t\t    envelopeInfoPtr->blockBufferPos,\n\t\t\t\t\t\t\t    envelopeInfoPtr->bufSize ) );\n\t\tmemcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,\n\t\t\t\tenvelopeInfoPtr->blockBuffer, envelopeInfoPtr->blockBufferPos );\n\t\tenvelopeInfoPtr->bufPos += envelopeInfoPtr->blockBufferPos;\n\t\t}\n\tenvelopeInfoPtr->blockBufferPos = 0;\n\n\t/* We've started the new segment, mark it as incomplete */\n\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_SEGMENTCOMPLETE );\n\n\tENSURES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete a segment of data in the buffer.  This is incredibly complicated\n   because we need to take into account the indefinite-length encoding (which\n   has a variable-size length field) and the quantization to the cipher block\n   size.  In particular the indefinite-length encoding means that we can\n   never encode a block with a size of 130 bytes (we get tag + length + 127 =\n   129, then tag + length-of-length + length + 128 = 131), and the same for\n   the next boundary at 256 bytes */\n\n#ifdef USE_CMS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int encodeSegmentHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tSTREAM stream;\n\tconst BOOLEAN isEncrypted = \\\n\t\t\t( envelopeInfoPtr->iCryptContext != CRYPT_ERROR ) ? TRUE : FALSE;\n\tconst int oldHdrLen = envelopeInfoPtr->segmentDataStart - \\\n\t\t\t\t\t\t  envelopeInfoPtr->segmentStart;\n\tBOOLEAN needsPadding = \\\n\t\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_NEEDSPADDING ) ? TRUE : FALSE;\n\tint dataLen = envelopeInfoPtr->bufPos - envelopeInfoPtr->segmentDataStart;\n\tint hdrLen, remainder = 0, status;\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\n\t/* If we're adding PKCS #5 padding try and add one block's worth of\n\t   pseudo-data.  This adjusted data length is then fed into the block\n\t   size quantisation process, after which any odd-sized remainder is\n\t   ignored, and the necessary padding bytes are added to account for the\n\t   difference between the actual and padded size */\n\tif( needsPadding )\n\t\t{\n\t\t/* Check whether the padding will fit onto the end of the data.  This\n\t\t   check isn't completely accurate since the length encoding might\n\t\t   shrink by one or two bytes and allow a little extra data to be\n\t\t   squeezed in, however the extra data could cause the length\n\t\t   encoding to expand again, requiring a complex adjustment process.\n\t\t   To make things easier we ignore this possibility at the expense of\n\t\t   emitting one more segment than is necessary in a few very rare\n\t\t   cases */\n\t\tif( envelopeInfoPtr->segmentDataStart + dataLen + \\\n\t\t\tenvelopeInfoPtr->blockSize < envelopeInfoPtr->bufSize )\n\t\t\tdataLen += envelopeInfoPtr->blockSize;\n\t\telse\n\t\t\tneedsPadding = FALSE;\n\t\t}\n\tENSURES( dataLen > 0 && envelopeInfoPtr->segmentDataStart + \\\n\t\t\t\t\t\t\t\t\tdataLen <= envelopeInfoPtr->bufSize );\n\n\t/* Now that we've made any necessary adjustments to the data length,\n\t   determine the length of the length encoding (which may have grown or\n\t   shrunk since we initially calculated it when we began the segment) */\n\thdrLen = ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) ? \\\n\t\t\t TAG_SIZE + lengthOfLength( dataLen ) : 0;\n\n\t/* Quantize and adjust the length if we're encrypting in a block mode:\n\n\t\t\t   segDataStart\t\t\t\t\t  bufPos\n\t\tsegStart\t|\t\t\t\t\t\t\t|\n\t\t\tv\t\tv<--------- dLen ---------->v\n\t\t----+-------+---------------------------+\n\t\t\t|  hdr\t|///////////////////////|\t|\n\t\t----+-------+---------------------------+\n\t\t\t\t\t|<------ qTotLen ------>|<+>|\n\t\t\t\t\t\t\t\t\t\t\t  |\n\t\t\t\t\t\t\t\t\t\t  remainder */\n\tif( isEncrypted )\n\t\t{\n\t\tint quantisedTotalLen, threshold;\n\n\t\t/* Determine the length due to cipher block-size quantisation */\n\t\tquantisedTotalLen = dataLen & envelopeInfoPtr->blockSizeMask;\n\n\t\t/* If the block-size quantisation has moved the quantised length\n\t\t   across a length-of-length encoding boundary, adjust hdrLen to\n\t\t   account for this */\n\t\tthreshold = findThreshold( quantisedTotalLen );\n\t\tif( quantisedTotalLen <= threshold && dataLen > threshold )\n\t\t\thdrLen--;\n\n\t\t/* Remember how many bytes we can't fit into the current block\n\t\t   (these will be copied into the block buffer for later use), and\n\t\t   the new size of the data due to quantisation */\n\t\tremainder = dataLen - quantisedTotalLen;\n\t\tdataLen = quantisedTotalLen;\n\t\t}\n\tENSURES( ( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && hdrLen == 0 ) || \\\n\t\t\t ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED && \\\n\t\t\t   hdrLen > 0 && hdrLen <= TAG_SIZE + 5 ) );\n\tENSURES( ( envelopeInfoPtr->blockSize == 0 && remainder == 0 ) || \\\n\t\t\t ( envelopeInfoPtr->blockSize > 0 && \\\n\t\t\t   remainder >= 0 && remainder < envelopeInfoPtr->blockSize && \\\n\t\t\t   remainder <= CRYPT_MAX_IVSIZE  ) );\n\n\t/* If there's not enough data present to do anything, tell the caller */\n\tif( dataLen <= 0 )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\tENSURES( dataLen > 0 && dataLen < MAX_BUFFER_SIZE );\n\n\t/* If there's a header between segments and the header length encoding\n\t   has shrunk (either due to the cipher block size quantization\n\t   shrinking the segment or because we've wrapped up a segment at less\n\t   than the original projected length), move the data down.  In the\n\t   worst case the shrinking can cover several bytes if we go from a\n\t   > 255 byte segment to a <= 127 byte one:\n\n\t\t\t   segDataStart\t\t\t\t\t  bufPos\n\t\tsegStart\t|\t\t\t\t\t\t\t|\n\t\t\tv\t\tv\t\t\t\t\t\t\tv\n\t\t----+-------+---------------------------+\n\t\t\t|  hdr\t|///////////////////////////|\tBefore\n\t\t----+-------+---------------------------+\n\t\t\t|<--+-->|\n\t\t\t\t|\n\t\t\toldHdrLen\n\n\t\t   segDataStart'\t\t\t\t bufPos'\n\t\tsegStart|\t\t\t\t\t\t\t|\n\t\t\tv\tv\t\t\t\t\t\t\tv\n\t\t----+-------+-----------------------+---+\n\t\t\t|hdr|///////////////////////////|\t|\tAfter\n\t\t----+-------+-----------------------+---+\n\t\t\t|<+>|<+>|\t\t\t\t\t\t|<+>|\n\t\t\t  |\t  |\t\t\t\t\t\t\t  |\n\t\t\t  | delta\t\t\t\t\t\tdelta\n\t\t\thdrLen */\n\tif( hdrLen > 0 && hdrLen < oldHdrLen )\n\t\t{\n\t\tconst int delta = oldHdrLen - hdrLen;\n\n\t\t/* If there's no data in the segment yet then there's nothing to do */\n\t\tif( envelopeInfoPtr->bufPos > envelopeInfoPtr->segmentDataStart )\n\t\t\t{\n\t\t\tBYTE *segmentDataPtr = envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\t\t\t   envelopeInfoPtr->segmentStart;\n\n\t\t\tREQUIRES( boundsCheck( envelopeInfoPtr->segmentStart + hdrLen, \n\t\t\t\t\t\t\t\t   envelopeInfoPtr->bufPos - \\\n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->segmentDataStart, \n\t\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\n\t\t\tmemmove( segmentDataPtr + hdrLen, segmentDataPtr + oldHdrLen,\n\t\t\t\t\t envelopeInfoPtr->bufPos - envelopeInfoPtr->segmentDataStart );\n\t\t\t}\n\t\tenvelopeInfoPtr->bufPos -= delta;\n\t\tenvelopeInfoPtr->segmentDataStart -= delta;\n\t\t}\n\tENSURES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\tENSURES( envelopeInfoPtr->segmentDataStart + \\\n\t\t\t\t\t\tdataLen <= envelopeInfoPtr->bufSize );\n\n\t/* If we need to add PKCS #5 block padding, do so now (we know from the\n\t   needsPadding and quantisedTotalLen check above that there's enough \n\t   room for this).  Since the extension of the data length to allow for \n\t   padding data is performed by adding one block of pseudo-data and \n\t   letting the block quantisation system take care of any discrepancies \n\t   we can calculate the padding amount as the difference between any \n\t   remainder after quantisation and the block size */\n\tif( needsPadding )\n\t\t{\n\t\tconst int padSize = envelopeInfoPtr->blockSize - remainder;\n\t\tint i, LOOP_ITERATOR;\n\n\t\tENSURES( padSize > 0 && padSize <= envelopeInfoPtr->blockSize && \\\n\t\t\t\t envelopeInfoPtr->bufPos + \\\n\t\t\t\t\t\tpadSize <= envelopeInfoPtr->bufSize );\n\n\t\t/* Add the block padding and set the remainder to zero, since we're\n\t\t   now at an even block boundary */\n\t\tLOOP_MED( i = 0, i < padSize, i++ )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos + i ] = \\\n\t\t\t\t\t\t\t\t\t\t\t\tintToByte( padSize );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tenvelopeInfoPtr->bufPos += padSize;\n\t\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NEEDSPADDING );\n\t\tENSURES( envelopeInfoPtr->bufPos >= 0 && \\\n\t\t\t\t envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );\n\t\t}\n\telse\n\t\t{\n\t\t/* If there are any bytes left over move them across into the block \n\t\t   buffer */\n\t\tif( remainder > 0 )\n\t\t\t{\n\t\t\tREQUIRES( envelopeInfoPtr->bufPos > remainder );\n\t\t\tmemcpy( envelopeInfoPtr->blockBuffer,\n\t\t\t\t\tenvelopeInfoPtr->buffer + envelopeInfoPtr->bufPos - \\\n\t\t\t\t\t\t\t\t\t\t\t  remainder, remainder );\n\t\t\tenvelopeInfoPtr->blockBufferPos = remainder;\n\t\t\tenvelopeInfoPtr->bufPos -= remainder;\n\t\t\t}\n\t\t}\n\n\tENSURES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\n\t/* If we're using the definite length form, exit */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\treturn( CRYPT_OK );\n\n\t/* Insert the OCTET STRING header into the data stream */\n\tsMemOpen( &stream, envelopeInfoPtr->buffer + \\\n\t\t\t\t\t   envelopeInfoPtr->segmentStart, hdrLen );\n\tstatus = writeOctetStringHole( &stream, dataLen, DEFAULT_TAG );\n\tENSURES( cryptStatusOK( status ) && stell( &stream ) == hdrLen );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completeSegment( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tconst BOOLEAN forceCompletion )\n\t{\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\tREQUIRES( forceCompletion == TRUE || forceCompletion == FALSE );\n\n\t/* If we're enveloping data using indefinite encoding and we're not at\n\t   the end of the data, don't emit a sub-segment containing less than\n\t   max( CRYPT_MAX_IVSIZE, 32 ) bytes of data.  This is to protect \n\t   against several things, principally users who write code that \n\t   performs byte-at-a-time enveloping, the following check quantizes the \n\t   data amount to make things slightly more efficient.  The reason for \n\t   the magic value of 32 bytes is that with a default buffer size of 32K \n\t   the loop exit at FAILSAFE_ITERATIONS_LARGE in copyToDeenvelope() \n\t   won't be triggered if the user's code produces worst-case conditions.\n\t   \n\t   The reason for the CRYPT_MAX_IVSIZE is that the final block emitted \n\t   usually needs to be PKCS #5-padded and we don't know at this point \n\t   whether this is the final block or not, so we need to buffer at least\n\t   this much data until we know what we'll be doing with it.\n\t   \n\t   As a side-effect this quantisation avoids occasional inefficiencies \n\t   at boundaries where one or two bytes may still be hanging around from \n\t   a previous data block since they'll be coalesced into the following \n\t   block */\n\tif( !forceCompletion && \\\n\t\tenvelopeInfoPtr->payloadSize == CRYPT_UNUSED && \\\n\t\t( envelopeInfoPtr->bufPos - \\\n\t\t  envelopeInfoPtr->segmentDataStart ) < max( CRYPT_MAX_IVSIZE, 32 ) )\n\t\t{\n\t\t/* We can't emit any of the small sub-segment, however there may be\n\t\t   (non-)data preceding this that we can hand over so we set the\n\t\t   segment data end value to the start of the segment */\n\t\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->segmentStart;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Wrap up the segment */\n#ifdef USE_CMS\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT ) )\n\t\t{\n\t\tstatus = encodeSegmentHeader( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* USE_CMS */\n\tif( envelopeInfoPtr->iCryptContext != CRYPT_ERROR )\n\t\t{\n\t\tvoid *dataPtr = envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\tenvelopeInfoPtr->segmentDataStart;\n\t\tconst int dataLen = envelopeInfoPtr->bufPos - \\\n\t\t\t\t\t\t\tenvelopeInfoPtr->segmentDataStart;\n\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, dataPtr, dataLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_AUTHENCACTIONSACTIVE ) )\n\t\t\t{\n\t\t\t/* We're performing authenticated encryption, hash the \n\t\t\t   ciphertext now that it's available */\n\t\t\tstatus = hashEnvelopeData( envelopeInfoPtr, dataPtr, dataLen );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Remember how much data is now available to be read out */\n\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\n\t/* Mark this segment as complete */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_SEGMENTCOMPLETE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCopy to Envelope\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Flush any remaining data through into the envelope buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int flushEnvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tBOOLEAN needNewSegment = \\\n\t\t\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t   ENVDATA_FLAG_NEEDSPADDING ) ? TRUE : FALSE;\n\tint status;\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\n\t/* If we're using an explicit payload length make sure that we copied in \n\t   as much data as was explicitly declared */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\tenvelopeInfoPtr->segmentSize != 0 )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n#ifdef USE_COMPRESSION\n\t/* If we're using compression, flush any remaining data out of the\n\t   zStream */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED ) )\n\t\t{\n\t\tint bytesToCopy;\n\n\t\t/* If we've just completed a segment, begin a new one.  This action\n\t\t   is slightly anomalous in that normally a flush can't add more\n\t\t   data to the envelope and so we'd never need to start a new\n\t\t   segment during a flush, however since we can have arbitrarily\n\t\t   large amounts of data trapped in subspace via zlib we need to be\n\t\t   able to handle starting new segments at this point */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_SEGMENTCOMPLETE ) )\n\t\t\t{\n\t\t\tstatus = beginSegment( envelopeInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\n\t\t/* Flush any remaining compressed data into the envelope buffer */\n\t\tbytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;\n\t\tenvelopeInfoPtr->zStream.next_in = NULL;\n\t\tenvelopeInfoPtr->zStream.avail_in = 0;\n\t\tenvelopeInfoPtr->zStream.next_out = envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos;\n\t\tenvelopeInfoPtr->zStream.avail_out = bytesToCopy;\n\t\tstatus = deflate( &envelopeInfoPtr->zStream, Z_FINISH );\n\t\tif( status != Z_STREAM_END && status != Z_OK )\n\t\t\t{\n\t\t\t/* There was some problem other than the output buffer being\n\t\t\t   full */\n\t\t\tretIntError();\n\t\t\t}\n\n\t\t/* Adjust the status information based on the data flushed out of\n\t\t   the zStream.  We don't have to check for the output buffer being\n\t\t   full because this case is already handled by the check of the\n\t\t   deflate() return value */\n\t\tenvelopeInfoPtr->bufPos += bytesToCopy - \\\n\t\t\t\t\t\t\t\t   envelopeInfoPtr->zStream.avail_out;\n\t\tENSURES( envelopeInfoPtr->bufPos >= 0 && \\\n\t\t\t\t envelopeInfoPtr->bufPos <= envelopeInfoPtr->bufSize );\n\n\t\t/* If we didn't finish flushing data because the output buffer is\n\t\t   full, complete the segment and tell the caller that they need to\n\t\t   pop some data */\n\t\tif( status == Z_OK )\n\t\t\t{\n\t\t\tstatus = completeSegment( envelopeInfoPtr, TRUE );\n\t\t\treturn( cryptStatusError( status ) ? \\\n\t\t\t\t\tstatus : CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\t}\n#endif /* USE_COMPRESSION */\n\n\t/* If we're encrypting data with a block cipher we need to add PKCS #5\n\t   padding at the end of the last block */\n\tif( envelopeInfoPtr->blockSize > 1 )\n\t\t{\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NEEDSPADDING );\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_SEGMENTCOMPLETE ) )\n\t\t\t{\n\t\t\t/* The current segment has been wrapped up, we need to begin a\n\t\t\t   new segment to contain the padding */\n\t\t\tneedNewSegment = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* If we're carrying over the padding requirement from a previous block \n\t   we need to begin a new block before we can try and add the padding.\n\t   This can happen if there was data left after the previous segment was\n\t   completed or if the addition of padding would have overflowed the\n\t   buffer when the segment was completed, in other words if the\n\t   needPadding flag is still set from the previous call */\n\tif( needNewSegment )\n\t\t{\n\t\tstatus = beginSegment( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )\n\t\t\t{\n\t\t\t/* We've filled the envelope buffer with the new segment header,\n\t\t\t   we can't copy in anything */\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\t}\n\n\t/* Complete the segment if necessary */\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_SEGMENTCOMPLETE ) || \\\n\t\tTEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NEEDSPADDING ) )\n\t\t{\n\t\tstatus = completeSegment( envelopeInfoPtr, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If there wasn't sufficient room to add the trailing PKCS #5 \n\t\t   padding tell the caller to try again */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_NEEDSPADDING ) )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* If there's no hashing being performed or we've completed the hashing, \n\t   we're done.  In addition unlike CMS, PGP handles authenticated \n\t   attributes by extending the hashing of the payload data to cover the \n\t   additional attributes, so if we're using the PGP format we can't wrap \n\t   up the hashing yet */\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags,\n\t\t\t\t\tENVDATA_FLAG_HASHACTIONSACTIVE | \\\n\t\t\t\t\tENVDATA_FLAG_AUTHENCACTIONSACTIVE ) || \\\n\t\tenvelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t{\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've finished processing everything, complete each hash action */\n\tINJECT_FAULT( BADSIG_HASH, BADSIG_HASH_CMS_1 );\n\treturn( hashEnvelopeData( envelopeInfoPtr, \"\", 0 ) );\n\t}\n\n/* Copy data into the envelope.  Returns the number of bytes copied or an\n   overflow error if we're trying to flush data and there isn't room to\n   perform the flush (this somewhat peculiar case is because the caller\n   expects to have 0 bytes copied in this case) */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyToEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER_OPT( length ) const BYTE *buffer, \n\t\t\t\t\t\t   IN_LENGTH_Z const int length )\n\t{\n\tBOOLEAN needCompleteSegment = FALSE;\n\tBYTE *bufPtr;\n\tint bytesToCopy, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( length == 0 || isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\tREQUIRES( ( buffer == NULL && length == 0 ) || \\\n\t\t\t  ( buffer != NULL && length >= 0 && length < MAX_BUFFER_SIZE ) );\n\n\t/* If we're trying to copy into a full buffer, return a count of 0 bytes\n\t   unless we're trying to flush the buffer (the calling routine may\n\t   convert the zero byte count to an overflow error if necessary) */\n\tif( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )\n\t\treturn( ( length > 0 ) ? 0 : CRYPT_ERROR_OVERFLOW );\n\n\t/* If we're generating a detached signature just hash the data and exit */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t{\n\t\t/* Unlike CMS, PGP handles authenticated attributes by extending the \n\t\t   hashing of the payload data to cover the additional attributes \n\t\t   so if this is a flush and we're using the PGP format then we \n\t\t   can't wrap up the hashing yet */\n\t\tif( length <= 0 && envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t\treturn( 0 );\n\n\t\tstatus = hashEnvelopeData( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t   ( length > 0 ) ? \\\n\t\t\t\t\t\t\t\t\t\tbuffer : ( const void * ) \"\", length );\n\t\t\t\t\t\t\t\t\t\t/* Cast needed for gcc */\n\t\treturn( cryptStatusError( status ) ? status : length );\n\t\t}\n\n\t/* If we're flushing data, wrap up the segment and exit.  An OK status \n\t   translates to zero bytes copied */\n\tif( length <= 0 )\n\t\t{\n\t\tstatus = flushEnvelopeData( envelopeInfoPtr );\n\t\treturn( cryptStatusError( status ) ? status : 0 );\n\t\t}\n\n\t/* If we're using an explicit payload length make sure that we don't try \n\t   and copy in more data than has been explicitly declared */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \\\n\t\tlength > envelopeInfoPtr->segmentSize )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* If we've just completed a segment, begin a new one before we add any\n\t   data */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_SEGMENTCOMPLETE ) )\n\t\t{\n\t\tstatus = beginSegment( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( ( status == CRYPT_ERROR_OVERFLOW ) ? 0 : status );\n\t\tif( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )\n\t\t\t{\n\t\t\t/* We've filled the envelope buffer with the new segment header,\n\t\t\t   we can't copy in anything */\n\t\t\treturn( 0 );\n\t\t\t}\n\t\t}\n\n\t/* Copy over as much as we can fit into the envelope buffer */\n\tbufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;\n\tbytesToCopy = envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos;\n\tENSURES( bytesToCopy > 0 && \\\n\t\t\t envelopeInfoPtr->bufPos + \\\n\t\t\t\t\tbytesToCopy <= envelopeInfoPtr->bufSize );\n#ifdef USE_COMPRESSION\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED ) )\n\t\t{\n\t\t/* Compress the data into the envelope buffer */\n\t\tenvelopeInfoPtr->zStream.next_in = ( BYTE * ) buffer;\n\t\tenvelopeInfoPtr->zStream.avail_in = length;\n\t\tenvelopeInfoPtr->zStream.next_out = bufPtr;\n\t\tenvelopeInfoPtr->zStream.avail_out = bytesToCopy;\n\t\tstatus = deflate( &envelopeInfoPtr->zStream, Z_NO_FLUSH );\n\t\tif( status != Z_OK )\n\t\t\t{\n\t\t\t/* There was some problem other than the output buffer being\n\t\t\t   full */\n\t\t\tretIntError();\n\t\t\t}\n\n\t\t/* Adjust the status information based on the data copied into the\n\t\t   zStream and flushed from the zStream into the buffer */\n\t\tenvelopeInfoPtr->bufPos += bytesToCopy - \\\n\t\t\t\t\t\t\t\t   envelopeInfoPtr->zStream.avail_out;\n\t\tbytesToCopy = length - envelopeInfoPtr->zStream.avail_in;\n\n\t\t/* If the buffer is full (there's no more room left for further\n\t\t   input) we need to close off the segment */\n\t\tif( envelopeInfoPtr->zStream.avail_out <= 0 )\n\t\t\tneedCompleteSegment = TRUE;\n\t\t}\n\telse\n#endif /* USE_COMPRESSION */\n\t\t{\n\t\t/* We're not using compression */\n\t\tif( bytesToCopy > length )\n\t\t\tbytesToCopy = length;\n\t\tREQUIRES( boundsCheck( envelopeInfoPtr->bufPos, bytesToCopy, \n\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\n\t\tmemcpy( bufPtr, buffer, bytesToCopy );\n\t\tenvelopeInfoPtr->bufPos += bytesToCopy;\n\n\t\t/* Hash the data if necessary */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_HASHACTIONSACTIVE ) )\n\t\t\t{\n\t\t\tstatus = hashEnvelopeData( envelopeInfoPtr, bufPtr, bytesToCopy );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If the buffer is full (i.e. we've been fed more input data than we\n\t\t   could copy into the buffer) we need to close off the segment */\n\t\tif( bytesToCopy < length )\n\t\t\tneedCompleteSegment = TRUE;\n\t\t}\n\n\t/* Adjust the bytes-left counter if necessary */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\tenvelopeInfoPtr->segmentSize -= bytesToCopy;\n\n\tENSURES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\n\t/* Close off the segment if necessary */\n\tif( needCompleteSegment )\n\t\t{\n\t\tstatus = completeSegment( envelopeInfoPtr, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( bytesToCopy );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCopy from Envelope\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy data from the envelope and begin a new segment in the newly-created\n   room.  If called with a zero length value this will create a new segment\n   without moving any data.  Returns the number of bytes copied */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int copyFromEnvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t\t IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t IN_FLAGS_Z( ENVCOPY ) const int flags )\n\t{\n\tint bytesToCopy = maxLength, remainder;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( maxLength == 0 || isWritePtrDynamic( buffer, maxLength ) );\n\n\tREQUIRES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( flags == ENVCOPY_FLAG_NONE );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, maxLength ) );\n\t*length = 0;\n\n\t/* If the caller wants more data than there is available in the set of\n\t   completed segments try to wrap up the next segment to make more data\n\t   available */\n\tif( bytesToCopy > envelopeInfoPtr->segmentDataEnd )\n\t\t{\n\t\t/* Try and complete the segment if necessary.  This may not be\n\t\t   possible if we're using a block encryption mode and there isn't\n\t\t   enough room at the end of the buffer to encrypt a full block.  In\n\t\t   addition if we're generating a detached signature the data is\n\t\t   communicated out-of-band so there's no segmenting */\n\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\tENVELOPE_FLAG_DETACHED_SIG ) && \\\n\t\t\t!TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\tENVDATA_FLAG_SEGMENTCOMPLETE ) )\n\t\t\t{\n\t\t\tconst int status = completeSegment( envelopeInfoPtr, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Return all of the data that we've got */\n\t\tif( envelopeInfoPtr->segmentDataEnd < bytesToCopy )\n\t\t\tbytesToCopy = envelopeInfoPtr->segmentDataEnd;\n\t\t}\n\tremainder = envelopeInfoPtr->bufPos - bytesToCopy;\n\tENSURES( bytesToCopy >= 0 && bytesToCopy <= envelopeInfoPtr->bufPos );\n\tENSURES( remainder >= 0 && remainder <= envelopeInfoPtr->bufPos );\n\n\t/* Copy the data out and move any remaining data down to the start of the\n\t   buffer  */\n\tif( bytesToCopy > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( bytesToCopy, 1, maxLength ) );\n\t\tmemcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );\n\n\t\t/* Move any remaining data down in the buffer */\n\t\tif( remainder > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( bytesToCopy, remainder,\n\t\t\t\t\t\t\t\t   envelopeInfoPtr->bufPos ) );\n\t\t\tmemmove( envelopeInfoPtr->buffer,\n\t\t\t\t\t envelopeInfoPtr->buffer + bytesToCopy, remainder );\n\t\t\t}\n\t\tenvelopeInfoPtr->bufPos = remainder;\n\n\t\t/* Update the segment location information.  The segment start\n\t\t   values track the start position of the last completed segment and\n\t\t   aren't updated until we begin a new segment so they may \n\t\t   temporarily go negative at this point when the data from the last\n\t\t   completed segment is moved past the start of the buffer.  If this\n\t\t   happens we set them to a safe value of zero to ensure that they\n\t\t   pass the sanity checks elsewhere in the code */\n\t\tenvelopeInfoPtr->segmentStart -= bytesToCopy;\n\t\tif( envelopeInfoPtr->segmentStart < 0 )\n\t\t\tenvelopeInfoPtr->segmentStart = 0;\n\t\tenvelopeInfoPtr->segmentDataStart -= bytesToCopy;\n\t\tif( envelopeInfoPtr->segmentDataStart < 0 )\n\t\t\tenvelopeInfoPtr->segmentDataStart = 0;\n\t\tenvelopeInfoPtr->segmentDataEnd -= bytesToCopy;\n\t\tENSURES( envelopeInfoPtr->segmentDataEnd >= 0 && \\\n\t\t\t\t envelopeInfoPtr->segmentDataEnd < MAX_BUFFER_SIZE );\n\t\t}\n\t*length = bytesToCopy;\n\n\tENSURES( sanityCheckEnvEncode( envelopeInfoPtr ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initEnvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->copyToEnvelopeFunction, copyToEnvelope );\n\tFNPTR_SET( envelopeInfoPtr->copyFromEnvelopeFunction, copyFromEnvelope );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/envelope/env_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Envelope Attribute Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1996-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"envelope.h\"\n#else\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( envelopeInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorInited( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT, \n\t\t\t\t\t   CRYPT_ERROR_INITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotInited( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, \n\t\t\t\t\t   CRYPT_ERROR_NOTINITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( envelopeInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, \n\t\t\t\t\t   CRYPT_ERROR_NOTFOUND ) );\n\t}\n\n/* Reset the internal virtual cursor in a content-list item after we've \n   moved the attribute cursor */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void resetVirtualCursor( INOUT CONTENT_LIST *contentListPtr )\n\t{\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\n\tif( contentListPtr->type != CONTENT_SIGNATURE )\n\t\treturn;\n\tcontentListPtr->clSigInfo.attributeCursorEntry = \\\n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE_RESULT;\n\t}\n\n/* Move the internal virtual cursor within a content-list item */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN moveVirtualCursor( INOUT CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( ATTR ) const ATTR_TYPE attrGetType )\n\t{\n\tstatic const CRYPT_ATTRIBUTE_TYPE attributeOrderList[] = {\n\t\t\t\tCRYPT_ENVINFO_SIGNATURE_RESULT, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA, CRYPT_ENVINFO_TIMESTAMP, \n\t\t\t\tCRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_NONE };\n\tCONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;\n\tCRYPT_ATTRIBUTE_TYPE attributeType = sigInfo->attributeCursorEntry;\n\tBOOLEAN doContinue;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\t\n\tREQUIRES_B( attrGetType == ATTR_NEXT || attrGetType == ATTR_PREV );\n\tREQUIRES_B( sigInfo->attributeCursorEntry != CRYPT_ATTRIBUTE_NONE );\n\n\tLOOP_SMALL_INITCHECK( doContinue = TRUE, doContinue == TRUE )\n\t\t{\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Find the position of the current sub-attribute in the attribute \n\t\t   order list and use that to get its successor/predecessor sub-\n\t\t   attribute */\n\t\tLOOP_SMALL_ALT( i = 0, \n\t\t\t\t\t\tattributeOrderList[ i ] != attributeType && \\\n\t\t\t\t\t\t\tattributeOrderList[ i ] != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE ),\n\t\t\t\t\t\ti++ );\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tENSURES_B( i < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_TYPE ) );\n\t\tif( attributeOrderList[ i ] == CRYPT_ATTRIBUTE_NONE )\n\t\t\t{\n\t\t\t/* We've reached the first/last sub-attribute within the current \n\t\t\t   item/group, tell the caller that there are no more sub-\n\t\t\t   attributes present and they have to move on to the next \n\t\t\t   group */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( attrGetType == ATTR_PREV )\n\t\t\t{\n\t\t\tattributeType = ( i < 1 ) ? CRYPT_ATTRIBUTE_NONE : \\\n\t\t\t\t\t\t\t\t\t\tattributeOrderList[ i - 1 ];\n\t\t\t}\n\t\telse\n\t\t\tattributeType = attributeOrderList[ i + 1 ];\n\t\tif( attributeType == CRYPT_ATTRIBUTE_NONE )\n\t\t\t{\n\t\t\t/* We've reached the first/last sub-attribute within the current \n\t\t\t   item/group, exit as before */\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Check whether the required sub-attribute is present.  If not, we\n\t\t   continue and try the next one */\n\t\tdoContinue = FALSE;\n\t\tswitch( attributeType )\n\t\t\t{\n\t\t\tcase CRYPT_ENVINFO_SIGNATURE_RESULT:\n\t\t\t\tbreak;\t/* Always present */\n\t\t\t\t\n\t\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\t\tif( sigInfo->iSigCheckKey == CRYPT_ERROR )\n\t\t\t\t\tdoContinue = TRUE;\n\t\t\t\tbreak;\n\t\n\t\t\tcase CRYPT_ENVINFO_SIGNATURE_EXTRADATA:\n\t\t\t\tif( sigInfo->iExtraData == CRYPT_ERROR )\n\t\t\t\t\tdoContinue = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_TIMESTAMP:\n\t\t\t\tif( sigInfo->iTimestamp == CRYPT_ERROR )\n\t\t\t\t\tdoContinue = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Boolean();\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tsigInfo->attributeCursorEntry = attributeType;\n\t\n\treturn( TRUE );\n\t}\n\n/* Callback function used to provide external access to content list-\n   internal fields */\n\nCHECK_RETVAL_PTR \\\nstatic const void *getAttrFunction( IN_OPT TYPECAST( CONTENT_LIST * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *attributePtr, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *groupID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *attributeID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *instanceID,\n\t\t\t\t\t\t\t\t\tIN_ENUM( ATTR ) const ATTR_TYPE attrGetType )\n\t{\n\tCONTENT_LIST *contentListPtr = ( CONTENT_LIST * ) attributePtr;\n\tBOOLEAN subGroupMove;\n\n\tassert( contentListPtr == NULL || \\\n\t\t\tisReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( groupID == NULL || \\\n\t\t\tisWritePtr( groupID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( attributeID == NULL || \\\n\t\t\tisWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( instanceID == NULL || \\\n\t\t\tisWritePtr( instanceID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES_N( isEnumRange( attrGetType, ATTR ) );\n\tREQUIRES_N( contentListPtr == NULL || \\\n\t\t\t\tsanityCheckContentList( contentListPtr ) );\n\n\t/* Clear return values */\n\tif( groupID != NULL )\n\t\t*groupID = CRYPT_ATTRIBUTE_NONE;\n\tif( attributeID != NULL )\n\t\t*attributeID = CRYPT_ATTRIBUTE_NONE;\n\tif( instanceID != NULL )\n\t\t*instanceID = CRYPT_ATTRIBUTE_NONE;\n\n\t/* Move to the next or previous attribute if required.  This isn't just a\n\t   case of following the prev/next links because some content-list items\n\t   contain an entire attribute group so positioning by attribute within\n\t   these only changes the current selection within the group (== content-\n\t   list item) rather than moving to the previous/next entry.  Because of \n\t   this we have to special-case the code for composite items (currently \n\t   only signature objects meet this definition) and allow virtual \n\t   positioning within the item */\n\tif( contentListPtr == NULL )\n\t\treturn( NULL );\n\tsubGroupMove = ( ( attrGetType == ATTR_PREV || \\\n\t\t\t\t\t   attrGetType == ATTR_NEXT ) && \\\n\t\t\t\t\t ( contentListPtr->type == CONTENT_SIGNATURE ) ) ? \\\n\t\t\t\t   TRUE : FALSE;\n\tif( subGroupMove )\n\t\tsubGroupMove = moveVirtualCursor( contentListPtr, attrGetType );\n\n\t/* If we're moving by group, move to the next/previous content list\n\t   item and reset the internal virtual cursor.  Note that we always \n\t   advance the cursor to the next/prev attribute, it's up to the calling \n\t   code to manage attribute by attribute vs.group by group moves */\n\tif( !subGroupMove && attrGetType != ATTR_CURRENT )\n\t\t{\n\t\tif( attrGetType == ATTR_PREV ) \n\t\t\t{\n\t\t\tREQUIRES_N( DATAPTR_ISVALID( contentListPtr->prev ) );\n\t\t\tcontentListPtr = DATAPTR_GET( contentListPtr->prev );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES_N( DATAPTR_ISVALID( contentListPtr->next ) );\n\t\t\tcontentListPtr = DATAPTR_GET( contentListPtr->next );\n\t\t\t}\n\t\tif( contentListPtr != NULL )\n\t\t\tresetVirtualCursor( contentListPtr );\n\t\t}\n\tif( contentListPtr == NULL )\n\t\treturn( NULL );\n\n\t/* Return ID information to the caller.  We only return the group ID if\n\t   we've moved within the attribute group, if we've moved from one group\n\t   to another we leave it cleared because envelopes can contain multiple\n\t   groups with the same ID and returning an ID identical to the one from\n\t   the group that we've moved out of would make it look as if we're still \n\t   within the same group.  Note that this relies on the behaviour of the\n\t   attribute-move functions, which first get the current group using \n\t   ATTR_CURRENT and then move to the next or previous using ATTR_NEXT/\n\t   PREV */\n\tif( groupID != NULL && ( attrGetType == ATTR_CURRENT || subGroupMove ) )\n\t\t*groupID = contentListPtr->envInfo;\n\tif( attributeID != NULL && contentListPtr->type == CONTENT_SIGNATURE )\n\t\t*attributeID = contentListPtr->clSigInfo.attributeCursorEntry;\n\treturn( contentListPtr );\n\t}\n\n/* Set attribute-cursor selection information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setCursorSelection( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\tconst int cursorMoveType )\n\t{\n\tconst CONTENT_LIST *contentListCursor;\n\tCONTENT_LIST *contentListCurrent = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t  attribute == CRYPT_ATTRIBUTE_CURRENT );\n\tREQUIRES( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t  cursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) );\n\n\t/* If it's an absolute positioning code, pre-set the attribute cursor if \n\t   required */\n\tif( cursorMoveType == CRYPT_CURSOR_FIRST || \\\n\t\tcursorMoveType == CRYPT_CURSOR_LAST )\n\t\t{\n\t\tCONTENT_LIST *contentListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\n\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentList ) );\n\n\t\tif( contentListPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t/* If it's an absolute attribute positioning code, reset the \n\t\t   attribute cursor to the start of the list before we try to move \n\t\t   it and if it's an attribute positioning code initialise the \n\t\t   attribute cursor if necessary */\n\t\tif( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\tcontentListCurrent == NULL )\n\t\t\t{\n\t\t\tcontentListCurrent = contentListPtr;\n\t\t\tif( contentListCurrent != NULL )\n\t\t\t\tresetVirtualCursor( contentListCurrent );\n\t\t\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, contentListPtr );\n\t\t\t}\n\n\t\t/* If there are no attributes present, return the appropriate error \n\t\t   code.  Note that contentListCurrent can never be NULL at this \n\t\t   point because it's been set to the non-NULL contentListPtr, but \n\t\t   we leave the check in here to make things explicit */\n\t\tif( contentListCurrent == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a relative positioning code, return a not-inited error \n\t\t   rather than a not-found error if the cursor isn't set since there \n\t\t   may be attributes present but the cursor hasn't been initialised \n\t\t   yet by selecting the first or last absolute attribute */\n\t\tif( contentListCurrent == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\tENSURES( contentListCurrent != NULL );\n\n\t/* Move the cursor */\n\tcontentListCursor = attributeMoveCursor( contentListCurrent, \n\t\t\t\t\t\t\t\t\t\t\t getAttrFunction, attribute, \n\t\t\t\t\t\t\t\t\t\t\t cursorMoveType );\n\tif( contentListCursor == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, \n\t\t\t\t ( CONTENT_LIST * ) contentListCursor );\n\treturn( CRYPT_OK );\n\t}\n\n/* Instantiate a certificate chain from a collection of certificates */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int instantiateCertChain( INOUT CONTENT_LIST *contentListItem, \n\t\t\t\t\t\t\t\t IN_BUFFER( certChainDataLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *certChainData, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int certChainDataLength )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtrDynamic( certChainData, certChainDataLength ) );\n\n\tREQUIRES( contentListItem->type == CONTENT_SIGNATURE );\n\tREQUIRES( certChainDataLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  certChainDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Instantiate the certificate chain.  Since this isn't a true \n\t   certificate chain (in the sense of being degenerate PKCS #7 \n\t   SignedData) but only a context-tagged SET OF Certificate, we notify \n\t   the certificate management code of this when it performs the import */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, certChainData,\n\t\t\t\t\t\t\t\t\t\tcertChainDataLength, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ICERTTYPE_CMS_CERTSET );\n\tif( contentListItem->issuerAndSerialNumber == NULL )\n\t\t{\n\t\tupdateMessageCreateObjectIndirectInfo( &createInfo, \n\t\t\t\t\t\t\t\tCRYPT_IKEYID_KEYID, \n\t\t\t\t\t\t\t\tcontentListItem->keyID, \n\t\t\t\t\t\t\t\tcontentListItem->keyIDsize );\n\t\t}\n\telse\n\t\t{\n\t\tupdateMessageCreateObjectIndirectInfo( &createInfo, \n\t\t\t\t\t\t\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER, \n\t\t\t\t\t\t\t\tcontentListItem->issuerAndSerialNumber, \n\t\t\t\t\t\t\t\tcontentListItem->issuerAndSerialNumberSize );\n\t\t}\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\tcontentListItem->clSigInfo.iSigCheckKey = createInfo.cryptHandle;\n\treturn( status );\n\t}\n\n/* Get information on the attribute at the current attribute-cursor \n   position.  This isn't quite as simple as it sounds because trying to \n   obtain the info may require a decrypt or key-import operation in order\n   to obtain it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getCurrentAttributeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\tOUT_INT_Z int *valuePtr )\n\t{\n\tCONTENT_LIST *contentListItem = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( contentListItem != NULL );\n\n\t/* Clear return value */\n\t*valuePtr = CRYPT_ATTRIBUTE_NONE;\n\n\t/* If we need something other than a private key or we need a private \n\t   key but there's no keyset present to fetch it from, just report what \n\t   we need and exit */\n\tif( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY || \\\n\t\tenvelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )\n\t\t{\n\t\t*valuePtr = contentListItem->envInfo;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There's a decryption keyset available, try and get the required key \n\t   from it.  Even though we're accessing the key by (unique) key ID we \n\t   still specify the key type preference in case there's some problem \n\t   with the ID info.  This means that we return a more meaningful error \n\t   message now rather than a usage-related one when we try to use the \n\t   key.\n\n\t   Unlike signature check keyset access, we retry the access every time \n\t   we're called because we may be talking to a device that has a trusted \n\t   authentication path which is outside our control so that the first \n\t   read fails if the user hasn't entered their PIN but a second read \n\t   once they've entered it will succeed */\n\tif( contentListItem->issuerAndSerialNumber == NULL )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, \n\t\t\t\t\t\t( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\tCRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, \n\t\t\t\t\t\tcontentListItem->keyID, contentListItem->keyIDsize, \n\t\t\t\t\t\tNULL, 0, KEYMGMT_FLAG_USAGE_CRYPT );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, \n\t\t\t\t\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\tcontentListItem->issuerAndSerialNumber,\n\t\t\t\t\t\tcontentListItem->issuerAndSerialNumberSize,\n\t\t\t\t\t\tNULL, 0, KEYMGMT_FLAG_USAGE_CRYPT );\n\t\t}\n\tstatus = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset, \n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* Make sure that any argument errors arising from this internal key \n\t\t   fetch don't get propagated back up to the caller.  Note that this \n\t\t   error is converted to a CRYPT_OK later on (see the comment further \n\t\t   down) but we perform the cleanup here to keep things tidy */\n\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\t\t}\n\n\t/* If we managed to get the private key (either bcause it wasn't \n\t   protected by a password if it's in a keyset or because it came from a \n\t   device), push it into the envelope.  If the call succeeds this will \n\t   import the session key and delete the required-information list.\n\n\t   What to do when this operation fails is a bit tricky since the \n\t   supposedly idempotent step of reading an attribute can have side-\n\t   effects if it results in a key being read from a crypto device that \n\t   in turn is used to import a wrapped session key.  Changing the\n\t   externally-visible behaviour isn't really an option because the \n\t   import is normally triggered by the addition of unwrap keying \n\t   material but in this case it's already present, and the caller has\n\t   nothing to add to trigger the import.  Conversely though it's a bit\n\t   confusing to report side-effects of the (invisible) key-unwrap \n\t   process to the caller in response to an attribute read.  However, \n\t   masking the details entirely can lead the caller down a blind alley \n\t   in which they apparently need to add an unwrap key but it's already\n\t   been added via the device and the unwrap process failed.\n\n\t   A compromise solution is to select a return value that definitely\n\t   indicates that there's no chance of continuing and report that, and\n\t   otherwise to indicate that an unwrap key is needed.  The only return\n\t   value that's really a ne pas ultra in this case is \n\t   CRYPT_ERROR_BADDATA, all others are potentially recoverable or at \n\t   least misleading if returned in this context (for example \n\t   CRYPT_ERROR_NOTAVAIL interpreted in the context of read-current-\n\t   attribute has a very different meaning than in the context of unwrap-\n\t   key) */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst ENV_ADDINFO_FUNCTION addInfoFunction = \\\n\t\t\t\t\t( ENV_ADDINFO_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoFunction );\n\n\t\tENSURES( addInfoFunction != NULL );\n\n\t\tstatus = addInfoFunction( envelopeInfoPtr, CRYPT_ENVINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t  getkeyInfo.cryptHandle );\n\t\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tif( status == CRYPT_ERROR_BADDATA )\n\t\t\t{\n\t\t\t/* We've reached a can't-continue condition, report it to the\n\t\t\t   caller */\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\t}\n\n\t/* If we got the key, there's nothing else needed.  If we didn't then we \n\t   still return an OK status since the caller is asking us for the \n\t   resource which is required and not the status of any background \n\t   operation that was performed while trying to obtain it */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tconst CONTENT_LIST *contentListCurrent = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\n\t\tREQUIRES( contentListCurrent != NULL );\n\n\t\t*valuePtr = contentListCurrent->envInfo;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the result of the signature-check process and the key used for \n   signing.  Since the signature check is performed on-demand this can \n   require a considerable amount of additional work */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getSignatureResult( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   OUT_STATUS int *valuePtr )\n\t{\n\tconst ENV_ADDINFO_FUNCTION addInfoFunction = \\\n\t\t\t\t\t( ENV_ADDINFO_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoFunction );\n\tCRYPT_HANDLE iCryptHandle;\n\tconst CONTENT_SIG_INFO *sigInfo;\n\tCONTENT_LIST *contentListItem = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t\t  ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_AUTHENC ) ) || \\\n\t\t\t  contentListItem != NULL );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) );\n\tREQUIRES( addInfoFunction != NULL );\n\n\t/* Clear return value.  Since this is a status-value return and we want\n\t   to fail closed for a signature check, we initialise it to \n\t   CRYPT_ERROR_SIGNATURE */\n\t*valuePtr = CRYPT_ERROR_SIGNATURE;\n\n\t/* If it's a MACd or authenticated-encrypted envelope then the signature \n\t   result isn't held in a content list as for the other signatures since \n\t   the \"signature\" is just a MAC tag appended to the data.  The \n\t   appropriate value to return here is a bit tricky since an attacker \n\t   could corrupt the MAC tag and force a less severe error like \n\t   CRYPT_ERROR_UNDERFLOW (by truncating the data).  However we can only \n\t   get here once we've reached the finished state, which means that all \n\t   of the data (including the MAC tag) has been successfully processed.  \n\t   This means that any persistent error state is regarded as the \n\t   equivalent of a signature error */\n\tif( envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t  TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) ) )\n\t\t{\n\t\t*valuePtr = ( envelopeInfoPtr->errorState != CRYPT_OK ) ? \\\n\t\t\t\t\tCRYPT_ERROR_SIGNATURE : CRYPT_OK;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tREQUIRES( contentListItem != NULL );\n\n\t/* Make sure that the content list item is of the appropriate type, and \n\t   if we've already done this one don't process it a second time.  This \n\t   check is also performed by the addInfo() code but we duplicate it \n\t   here (just for the signature-result attribute) to avoid having to do \n\t   an unnecessary key fetch for non-CMS signatures */\n\tsigInfo = &contentListItem->clSigInfo;\n\tif( contentListItem->envInfo != CRYPT_ENVINFO_SIGNATURE )\n\t\t{\n\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_SIGNATURE_RESULT ) );\n\t\t}\n\tif( TEST_FLAG( contentListItem->flags, CONTENT_FLAG_PROCESSED ) )\n\t\t{\n\t\t*valuePtr = sigInfo->processingResult;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's an encoded certificate chain present and it hasn't been \n\t   instantiated as a certificate object yet, instantiate it now.  We \n\t   don't check the return value since a failure isn't fatal, we can \n\t   still perform the signature check with a key pulled from a keyset */\n\tif( sigInfo->iSigCheckKey == CRYPT_ERROR && \\\n\t\tenvelopeInfoPtr->auxBuffer != NULL )\n\t\t{\n\t\t( void ) instantiateCertChain( contentListItem, \n\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->auxBuffer, \n\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->auxBufSize );\n\t\t}\n\n\t/* If we have a key instantiated from a certificate chain, use that to \n\t   check the signature.  In theory we could also be re-using the key \n\t   from an earlier, not-completed check, however this is only retained \n\t   if the check succeeds (to allow a different key to be tried if the \n\t   check fails) so in practice this never occurs */\n\tif( sigInfo->iSigCheckKey != CRYPT_ERROR )\n\t\t{\n\t\t/* Add the signature-check key with the special type \n\t\t   CRYPT_ENVINFO_SIGNATURE_RESULT to indicate that it's been \n\t\t   provided internally rather than being supplied by the user */\n\t\t*valuePtr = addInfoFunction( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_SIGNATURE_RESULT, \n\t\t\t\t\t\t\t\t\t sigInfo->iSigCheckKey );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We don't have a signature check key available (for example one from a \n\t   CMS certificate chain), make sure that there's a keyset available to \n\t   pull the key from and get the key from it */\n\tif( envelopeInfoPtr->iSigCheckKeyset == CRYPT_ERROR )\n\t\t{\n\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_SIGCHECK ) );\n\t\t}\n\n\t/* Try and get the required key.  Even though we're accessing the key by \n\t   (unique) key ID we still specify the key type preference in case \n\t   there's some problem with the ID info.  This means that we return a \n\t   more meaningful error message now rather than a usage-related one \n\t   when we try to use the key */\n\tif( contentListItem->issuerAndSerialNumber == NULL )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, \n\t\t\t\t\t( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\tCRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, \n\t\t\t\t\tcontentListItem->keyID, contentListItem->keyIDsize, \n\t\t\t\t\tNULL, 0, KEYMGMT_FLAG_USAGE_SIGN );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo,\n\t\t\t\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\t\tcontentListItem->issuerAndSerialNumber,\n\t\t\t\t\tcontentListItem->issuerAndSerialNumberSize,\n\t\t\t\t\tNULL, 0, KEYMGMT_FLAG_USAGE_SIGN );\n\t\t}\n\tstatus = krnlSendMessage( envelopeInfoPtr->iSigCheckKeyset, \n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtObj( status,\n\t\t\t\t   ( status, ENVELOPE_ERRINFO, \n\t\t\t\t     envelopeInfoPtr->iSigCheckKeyset,\n\t\t\t\t\t \"Couldn't retrieve signature-check key from keyset\" ) );\n\t\t}\n\tiCryptHandle = getkeyInfo.cryptHandle;\n\n\t/* Push the public key into the envelope, which performs the signature \n\t   check.  Adding the key increments its reference count since the key \n\t   is usually user-supplied and we need to keep a reference for use by \n\t   the envelope, however since the key that we're using here is an \n\t   internal-use-only key we don't want to do this so we decrement it \n\t   again after it's been added.  In addition we add the signature-check \n\t   key with the special type CRYPT_ENVINFO_SIGNATURE_RESULT to indicate \n\t   that it's been provided internally rather than being user-supplied */\n\t*valuePtr = addInfoFunction( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t CRYPT_ENVINFO_SIGNATURE_RESULT, \n\t\t\t\t\t\t\t\t iCryptHandle );\n\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\n\t/* If the key wasn't used for the signature check (i.e. it wasn't stored \n\t   in the content list for later use, which means it isn't needed any \n\t   more), discard it */\n\tif( sigInfo->iSigCheckKey == CRYPT_ERROR )\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getSignatureKey( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT int *valuePtr )\n\t{\n\tCRYPT_CERTIFICATE sigCheckCert;\n\tCONTENT_LIST *contentListItem = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\tCONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( contentListItem != NULL );\n\n\t/* Clear return value */\n\t*valuePtr = CRYPT_ERROR;\n\n\t/* If there's no signing key present try and instantiate it from an \n\t   attached certificate chain */\n\tif( sigInfo->iSigCheckKey == CRYPT_ERROR )\n\t\t{\n\t\tif( envelopeInfoPtr->auxBuffer == NULL )\n\t\t\t{\n\t\t\t/* There's no attached certificate chain to recover the signing \n\t\t\t   key from, we can't go any further */\n\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_SIGNATURE ) );\n\t\t\t}\n\t\tstatus = instantiateCertChain( contentListItem,\n\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->auxBuffer, \n\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->auxBufSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( exitError( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, status ) );\n\t\t\t}\n\t\t}\n\n\t/* If we instantiated the signature-check key ourselves (either from a \n\t   keyset or from envelope data) rather than having it supplied \n\t   externally, we're done */\n\tif( !TEST_FLAG( contentListItem->flags, CONTENT_FLAG_EXTERNALKEY ) )\n\t\t{\n\t\tkrnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_INCREFCOUNT );\n\t\t*valuePtr = sigInfo->iSigCheckKey;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The signature check key was externally supplied by the caller.  If \n\t   they added a private key+certificate combination as the signature \n\t   check key then this will return a supposed signature-check \n\t   certificate that actually has private-key capabilities.  Even adding \n\t   a simple certificate (+ public key context for the signature check) \n\t   can be dangerous since it can act as a subliminal channel if it's \n\t   passed on to a different user (although exactly how this would be \n\t   exploitable is another question entirely).  To avoid this problem we \n\t   completely isolate the added signature check key by returning a copy \n\t   of the associated certificate object */\n\tstatus = krnlSendMessage( sigInfo->iSigCheckKey, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &sigCheckCert, CRYPT_IATTRIBUTE_CERTCOPY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( exitError( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, status ) );\n\t\t}\n\n\t/* We've created a new instantiation of the signature check key which is \n\t   distinct from the externally-supplied original, replace the existing \n\t   one with the new one and return it to the caller */\n\tkrnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );\n\t*valuePtr = sigInfo->iSigCheckKey = sigCheckCert;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check an attribute add that isn't handled by the table-driven \n   general-purpose checks in setContextAttribute() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nstatic int checkOtherAttribute( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\tIN_INT_Z const int value, \n\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( ACTION ) ACTION_TYPE *usage,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_TYPE *checkType )\n\t{\n\tconst ENV_CHECKALGO_FUNCTION checkAlgoFunction = \\\n\t\t\t\t( ENV_CHECKALGO_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->checkAlgoFunction );\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( usage, sizeof( ACTION_TYPE ) ) );\n\n\tREQUIRES( isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( checkAlgoFunction != NULL );\n\n\t/* Clear return values */\n\t*usage = ACTION_NONE;\n\t*checkType = MESSAGE_CHECK_NONE;\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_ENCR_ALGO:\n\t\t\tif( !checkAlgoFunction( value, \n\t\t\t\t\t\t\tisStreamCipher( value ) ? CRYPT_MODE_CFB : \\\n\t\t\t\t\t\t\t( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\tCRYPT_MODE_CFB : CRYPT_MODE_CBC ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tenvelopeInfoPtr->defaultAlgo = value;\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase CRYPT_OPTION_ENCR_HASH:\n\t\t\tif( !checkAlgoFunction( value, CRYPT_MODE_NONE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tenvelopeInfoPtr->defaultHash = value;\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase CRYPT_OPTION_ENCR_MAC:\n\t\t\tif( !checkAlgoFunction( value, CRYPT_MODE_NONE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tenvelopeInfoPtr->defaultMAC = value;\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase CRYPT_ENVINFO_DATASIZE:\n\t\t\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_DATASIZE ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_CONTENTTYPE:\n\t\t\t/* Exactly what's supposed to happen when PGP is asked to sign \n\t\t\t   non-plain-data is ill-defined.  No command-line PGP option \n\t\t\t   will generate this type of message, and the RFCs don't \n\t\t\t   specify the behaviour (in fact RFC 1991's description of PGP \n\t\t\t   signing is completely wrong).  In practice PGP hashes and \n\t\t\t   signs the payload contents of a PGP literal data packet, \n\t\t\t   however if there are extra layers of processing between the \n\t\t\t   signing and literal packets (e.g. compression or encryption) \n\t\t\t   then what gets hashed isn't specified.  If it's always the \n\t\t\t   payload of the final (literal) data packet we'd have to be \n\t\t\t   able to burrow down through arbitrary amounts of further data \n\t\t\t   and processing in order to get to the payload data to hash \n\t\t\t   (this also makes things like mail gateways that only allow \n\t\t\t   signed messages through infeasible unless the gateway holds \n\t\t\t   everyone's private key in order to get at the plaintext to \n\t\t\t   hash).  Because of this problem we disallow any attempts to \n\t\t\t   set a content-type other than plain data if we're signing a \n\t\t\t   PGP-format message */\n\t\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\t\t\tenvelopeInfoPtr->usage == ACTION_SIGN && \\\n\t\t\t\tvalue != CRYPT_CONTENT_DATA )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* For user-friendliness we allow overwriting a given content \n\t\t\t   type with the same type, which is useful for cases when \n\t\t\t   cryptlib automatically presets the type based on other\n\t\t\t   information */\n\t\t\tif( envelopeInfoPtr->contentType != CRYPT_CONTENT_NONE && \\\n\t\t\t\tenvelopeInfoPtr->contentType != value )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_CONTENTTYPE ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_INTEGRITY:\n\t\t\t/* The integrity-protection flag can't be reset to a value of \n\t\t\t   CRYPT_INTEGRITY_NONE once it's been set to a higher level.  \n\t\t\t   If it could be reset then the caller could set non-MAC-\n\t\t\t   compatible options by clearing the flag and then setting it \n\t\t\t   again afterwards */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE )\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_SIGN )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_SIGNATURE ) );\n\t\t\t\t}\n\t\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\t\t\t( envelopeInfoPtr->contentType != CRYPT_CONTENT_NONE && \\\n\t\t\t\t  envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA ) )\n\t\t\t\t{\n\t\t\t\t/* See the long comment for CRYPT_ENVINFO_CONTENTTYPE \n\t\t\t\t   above.  In short, the processing for signing anything \n\t\t\t\t   other than plain data is undefined in PGP, so we don't \n\t\t\t\t   allow signature types for this content type */\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t\t}\n\t\t\t*checkType = TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) ? \\\n\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_SIGCHECK : \\\n\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_SIGN;\n\t\t\t*usage = ACTION_SIGN;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE_EXTRADATA:\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_SIGN )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n#if 0\t/* 18/7/16 Historic value only needed for Fortezza */\n\t\tcase CRYPT_ENVINFO_ORIGINATOR:\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_ORIGINATOR ) );\n\t\t\t\t}\n\t\t\tif( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_ORIGINATOR ) );\n\t\t\t\t}\n\t\t\t*checkType = MESSAGE_CHECK_PKC_KA_EXPORT;\n\t\t\t*usage = ACTION_CRYPT;\n\t\t\treturn( CRYPT_OK );\n#endif /* 0 */\n\n\t\tcase CRYPT_ENVINFO_HASH:\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tint status;\n\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_SIGN )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_HASH ) );\n\t\t\t\t}\n\t\t\t*checkType = MESSAGE_CHECK_HASH;\n\t\t\t*usage = ACTION_SIGN;\n\n\t\t\t/* We can only perform the following check for envelopes since \n\t\t\t   for de-envelopes the format type won't have been established \n\t\t\t   yet */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Hash contexts, being keyless, are always regarded as being in \n\t\t\t   the high state so the standard kernel check for their \n\t\t\t   readiness for use can't be applied to them.  Instead, we have \n\t\t\t   to explicitly check them here by reading the hash value to \n\t\t\t   see whether the hashing has been finalised */\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t\t\t{\n\t\t\t\t/* If it's a PGP envelope then we still need to hash in \n\t\t\t\t   authenticated attributes, so having the hashing completed \n\t\t\t\t   is an error */\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If it's a CMS envelope then the hashing must be completed \n\t\t\t\t   so that we can read the hash value from the context */\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_ENVINFO_KEYSET_ENCRYPT:\n\t\t\tif( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_KEYSET_ENCRYPT ) );\n\t\t\t\t}\n\t\t\t*checkType = MESSAGE_CHECK_PKC_ENCRYPT_AVAIL;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_KEYSET_DECRYPT:\n\t\t\tif( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_KEYSET_DECRYPT ) );\n\t\t\t\t}\n\t\t\t*checkType = MESSAGE_CHECK_PKC_DECRYPT_AVAIL;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_KEYSET_SIGCHECK:\n\t\t\tif( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_KEYSET_SIGCHECK ) );\n\t\t\t\t}\n\t\t\t*checkType = MESSAGE_CHECK_PKC_SIGCHECK_AVAIL;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getEnvelopeAttribute( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Clear return value */\n\t*valuePtr = 0;\n\n\t/* Generic attributes are valid for all envelope types */\n\tif( attribute == CRYPT_ATTRIBUTE_BUFFERSIZE )\n\t\t{\n\t\t*valuePtr = envelopeInfoPtr->bufSize;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( attribute == CRYPT_ATTRIBUTE_ERRORTYPE )\n\t\t{\n\t\t*valuePtr = envelopeInfoPtr->errorType;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( attribute == CRYPT_ATTRIBUTE_ERRORLOCUS )\n\t\t{\n\t\t*valuePtr = envelopeInfoPtr->errorLocus;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're de-enveloping PGP data, make sure that the attribute is valid \n\t   for PGP envelopes.  We can't perform this check via the ACLs because \n\t   the data type isn't known at envelope creation time so there's a \n\t   single generic de-envelope type for which the ACLs allow the union of \n\t   all de-enveloping attribute types.  The following check weeds out the \n\t   ones that don't work for PGP */\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\tattribute == CRYPT_ENVINFO_SIGNATURE_EXTRADATA )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Make sure that the attribute is valid for this envelope type and state */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_ENCR_ALGO:\n\t\tcase CRYPT_OPTION_ENCR_HASH:\n\t\tcase CRYPT_OPTION_ENCR_MAC:\n\t\t\t/* Algorithm types are valid only for enveloping */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\tbreak;\n\t\t\t\t\t\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ENVINFO_SIGNATURE_RESULT:\n\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\tcase CRYPT_ENVINFO_SIGNATURE_EXTRADATA:\n\t\tcase CRYPT_ENVINFO_TIMESTAMP:\n\t\t\t/* The following checks aren't strictly necessary since we can \n\t\t\t   get some information as soon as it's available, but it leads \n\t\t\t   to less confusion (for example without this check we can get \n\t\t\t   signer info long before we can get the signature results, \n\t\t\t   which could be misinterpreted to mean that the signature is \n\t\t\t   bad) and forces the caller to do things cleanly */\n\t\t\tif( envelopeInfoPtr->usage == ACTION_SIGN && \\\n\t\t\t\tenvelopeInfoPtr->state != ENVELOPE_STATE_FINISHED )\n\t\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\t\t\tif( ( envelopeInfoPtr->usage == ACTION_MAC || \\\n\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t\t\tTEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t   ENVELOPE_FLAG_AUTHENC ) ) ) && \\\n\t\t\t\tattribute == CRYPT_ENVINFO_SIGNATURE_RESULT )\n\t\t\t\t{\n\t\t\t\tif( envelopeInfoPtr->state != ENVELOPE_STATE_FINISHED )\n\t\t\t\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\n\t\t\t\t/* If it's a MACd envelope (either by being directly MACed \n\t\t\t\t   or as as side-effect of using authenticated encryption) \n\t\t\t\t   then the signature result isn't held in a content list as \n\t\t\t\t   for the other signatures since the \"signature\" is just a \n\t\t\t\t   MAC tag appended to the data, so there's no need to check \n\t\t\t\t   for the presence of a content list */\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* We're querying something that resides in the content list, \n\t\t\t   make sure that there's a content list present.  If it's \n\t\t\t   present but nothing is selected, select the first entry */\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) );\n\t\t\tif( DATAPTR_ISNULL( envelopeInfoPtr->contentListCurrent ) )\n\t\t\t\t{\n\t\t\t\tCONTENT_LIST *contentListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\n\t\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentList ) );\n\t\t\t\tif( contentListPtr == NULL )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t   attribute ) );\n\t\t\t\t\t}\n\t\t\t\tresetVirtualCursor( contentListPtr );\n\t\t\t\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, contentListPtr );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tREQUIRES( attribute == CRYPT_ENVINFO_COMPRESSION || \\\n\t\t\t\t\t  attribute == CRYPT_ENVINFO_CONTENTTYPE || \\\n\t\t\t\t\t  attribute == CRYPT_ENVINFO_INTEGRITY || \\\n\t\t\t\t\t  attribute == CRYPT_ENVINFO_DETACHEDSIGNATURE || \\\n\t\t\t\t\t  attribute == CRYPT_IATTRIBUTE_ATTRONLY );\n\t\t}\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\t\treturn( getCurrentAttributeInfo( envelopeInfoPtr, valuePtr ) );\n\n\t\tcase CRYPT_OPTION_ENCR_ALGO:\n\t\t\tif( envelopeInfoPtr->defaultAlgo == CRYPT_ALGO_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_ENCR_ALGO ) );\n\t\t\t\t}\n\t\t\t*valuePtr = envelopeInfoPtr->defaultAlgo;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_ENCR_HASH:\n\t\t\tif( envelopeInfoPtr->defaultHash == CRYPT_ALGO_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_ENCR_HASH ) );\n\t\t\t\t}\n\t\t\t*valuePtr = envelopeInfoPtr->defaultHash;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_ENCR_MAC:\n\t\t\tif( envelopeInfoPtr->defaultMAC == CRYPT_ALGO_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_ENCR_MAC ) );\n\t\t\t\t}\n\t\t\t*valuePtr = envelopeInfoPtr->defaultMAC;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_COMPRESSION:\n\t\t\tif( envelopeInfoPtr->usage == ACTION_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_COMPRESSION ) );\n\t\t\t\t}\n\t\t\t*valuePtr = ( envelopeInfoPtr->usage == ACTION_COMPRESS ) ? \\\n\t\t\t\t\t\tTRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_CONTENTTYPE:\n\t\t\tif( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_CONTENTTYPE ) );\n\t\t\t\t}\n\t\t\t*valuePtr = envelopeInfoPtr->contentType;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_DETACHEDSIGNATURE:\n\t\t\t/* If this isn't signed data or we haven't sorted out the \n\t\t\t   content details yet we don't know whether it's a detached \n\t\t\t   signature or not.  We have to make an exception for PGP \n\t\t\t   signed data because the PGP format doesn't record whether a \n\t\t\t   signature is a detached signature or not.  To resolve this, \n\t\t\t   the lower-level de-enveloping code takes a guess based on \n\t\t\t   whether the user has manually added a hash for signed-data \n\t\t\t   processing or not.  Because of this the detached-signature \n\t\t\t   status can change from (apparently-)false before adding the \n\t\t\t   hash to (apparently-)true after adding it, but there's not \n\t\t\t   much that we can do about this */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_SIGN || \\\n\t\t\t\t( envelopeInfoPtr->type != CRYPT_FORMAT_PGP && \\\n\t\t\t\t  envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE ) )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_DETACHEDSIGNATURE ) );\n\t\t\t\t}\n\t\t\t*valuePtr = TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) ? \\\n\t\t\t\t\t\tTRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE_RESULT:\n\t\t\treturn( getSignatureResult( envelopeInfoPtr, valuePtr ) );\n\n\t\tcase CRYPT_ENVINFO_INTEGRITY:\n\t\t\t*valuePtr = ( envelopeInfoPtr->usage == ACTION_MAC ) ? \\\n\t\t\t\t\t\t\tCRYPT_INTEGRITY_MACONLY : \\\n\t\t\t\t\t\t( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\t\t\t\t\t  TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t ENVELOPE_FLAG_AUTHENC ) ) ? \\\n\t\t\t\t\t\t\tCRYPT_INTEGRITY_FULL : CRYPT_INTEGRITY_NONE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\treturn( getSignatureKey( envelopeInfoPtr, valuePtr ) );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE_EXTRADATA:\n\t\tcase CRYPT_ENVINFO_TIMESTAMP:\n\t\t\t{\n\t\t\tCRYPT_HANDLE iCryptHandle;\n\t\t\tCONTENT_LIST *contentListItem = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\n\t\t\tREQUIRES( contentListItem != NULL );\n\t\t\tREQUIRES( sanityCheckContentList( contentListItem ) );\n\n\t\t\t/* Make sure that there's extra data present */\n\t\t\tiCryptHandle = \\\n\t\t\t\t( attribute == CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) ? \\\n\t\t\t\t\tcontentListItem->clSigInfo.iExtraData : \\\n\t\t\t\t\tcontentListItem->clSigInfo.iTimestamp;\n\t\t\tif( iCryptHandle == CRYPT_ERROR )\n\t\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, attribute ) );\n\n\t\t\t/* Return it to the caller */\n\t\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );\n\t\t\t*valuePtr = iCryptHandle;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_ATTRONLY:\n\t\t\t/* If this isn't signed data then we don't know whether it's an \n\t\t\t   attributes-only message or not */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_SIGN )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ATTRONLY ) );\n\t\t\t\t}\n\t\t\t*valuePtr = TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_ATTRONLY ) ? \\\n\t\t\t\t\t\tTRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getEnvelopeAttributeS( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tCONTENT_LIST *contentListItem;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* If we're querying something that resides in the content list make\n\t   sure that there's a content list present.  If it's present but \n\t   nothing is selected, select the first entry */\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) );\n\tif( attribute == CRYPT_ENVINFO_PRIVATEKEY_LABEL && \\\n\t\tDATAPTR_ISNULL( envelopeInfoPtr->contentListCurrent ) )\n\t\t{\n\t\tCONTENT_LIST *contentListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\n\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentList ) );\n\t\tif( contentListPtr == NULL )\n\t\t\t{\n\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );\n\t\t\t}\n\t\tresetVirtualCursor( contentListPtr );\n\t\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, contentListPtr );\n\t\t}\n\n\t/* Generic attributes are valid for all envelope types */\n\tif( attribute == CRYPT_ATTRIBUTE_ERRORMESSAGE )\n\t\t{\n#ifdef USE_ERRMSGS\n\t\tERROR_INFO *errorInfo = &envelopeInfoPtr->errorInfo;\n\n\t\tif( errorInfo->errorStringLength > 0 )\n\t\t\t{\n\t\t\treturn( attributeCopy( msgData, errorInfo->errorString,\n\t\t\t\t\t\t\t\t   errorInfo->errorStringLength ) );\n\t\t\t}\n#endif /* USE_ERRMSGS */\n\n\t\t/* We don't set extended error information for this atribute because \n\t\t   it's usually read in response to an existing error, which would \n\t\t   overwrite the existing error information */\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tif( attribute == CRYPT_ENVINFO_PRIVATEKEY_LABEL )\n\t\t{\n\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\t\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\t/* Make sure that the current required resource is a private key and\n\t\t   that there's a keyset available to pull the key from */\n\t\tcontentListItem = DATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\t\tREQUIRES( contentListItem != NULL );\n\t\tREQUIRES( sanityCheckContentList( contentListItem ) );\n\t\tif( contentListItem->envInfo != CRYPT_ENVINFO_PRIVATEKEY )\n\t\t\t{\n\t\t\treturn( exitErrorNotFound( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_ENVINFO_PRIVATEKEY_LABEL ) );\n\t\t\t}\n\t\tif( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )\n\t\t\t{\n\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_DECRYPT ) );\n\t\t\t}\n\n\t\t/* Try and get the key label information.  Since we're accessing the \n\t\t   key by (unique) key ID there's no real need to specify a \n\t\t   preference for encryption keys */\n\t\tif( contentListItem->issuerAndSerialNumber == NULL )\n\t\t\t{\n\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, \n\t\t\t\t\t\t\t\t   ( contentListItem->formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\t   CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, \n\t\t\t\t\t\t\t\t   contentListItem->keyID,\n\t\t\t\t\t\t\t\t   contentListItem->keyIDsize,\n\t\t\t\t\t\t\t\t   label, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_LABEL_ONLY );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, \n\t\t\t\t\t\t\t\t   CRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\t\t\t   contentListItem->issuerAndSerialNumber,\n\t\t\t\t\t\t\t\t   contentListItem->issuerAndSerialNumberSize,\n\t\t\t\t\t\t\t\t   label, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_LABEL_ONLY );\n\t\t\t}\n\t\tstatus = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtObj( status,\n\t\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t     envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t\t \"Couldn't retrieve private-key label from \"\n\t\t\t\t\t\t \"keyset/device\" ) );\n\t\t\t}\n\t\treturn( attributeCopy( msgData, getkeyInfo.auxInfo,\n\t\t\t\t\t\t\t   getkeyInfo.auxInfoLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* ACLS for checking attributes added to an envelope.  First, the attribute \n   is checked using the formatType field to make sure that it's permitted \n   for this envelope format type.  Then if there's a usage set, it's checked \n   against the envelope usage, with ACTION_NONE being permitted since the \n   usage type may not have been defined yet, for example if a modifier \n   attribute like CRYPT_ENVINFO_INTEGRITY is added before an attribute like \n   CRYPT_ENVINFO_KEY is added.  Next, if a check-action is defined in the\n   checkType field then the attribute being added is checked against the \n   check-action.  Finally, if a required envelope flag is present, the \n   envelope flags are checked to make sure that that option is enabled.\n\n   Some attributes require more specialised checking, indicated by the usage \n   being ACTION_NONE.  This is handled via custom code in \n   checkOtherAttribute().\n\n   formatAllDeenv is somewhat special in that while the explicit envelope \n   type is CRYPT_FORMAT_AUTO, it can be set to CRYPT_FORMAT_CMS or \n   CRYPT_FORMAT_PGP once we start processing data.  To deal with this we set \n   the requiredFlag to ENVELOPE_ISDEENVELOPE to ensure that something like\n   CRYPT_FORMAT_CMS really is a de-envelope */\n\ntypedef struct {\n\tconst CRYPT_ATTRIBUTE_TYPE type;\t/* Attribute type */\n\tconst CRYPT_FORMAT_TYPE *formatType;/* Permitted envelope types */\n\tconst ACTION_TYPE usage;\t\t\t/* Corresponding usage type, */\n\tconst MESSAGE_CHECK_TYPE checkType;\t/*  check type, and */\n\tconst int requiredFlag;\t\t\t\t/*  required enveloping flag */\n\t} CHECK_INFO;\n\nstatic const CRYPT_FORMAT_TYPE formatAll[] = { \n\tCRYPT_FORMAT_AUTO, CRYPT_FORMAT_CRYPTLIB, CRYPT_FORMAT_CMS, \n\tCRYPT_FORMAT_SMIME, CRYPT_FORMAT_PGP, CRYPT_FORMAT_NONE, \n\tCRYPT_FORMAT_NONE };\nstatic const CRYPT_FORMAT_TYPE formatAllEnv[] = { \n\tCRYPT_FORMAT_CRYPTLIB, CRYPT_FORMAT_CMS, CRYPT_FORMAT_SMIME,\n\tCRYPT_FORMAT_PGP, CRYPT_FORMAT_NONE, CRYPT_FORMAT_NONE };\nstatic const CRYPT_FORMAT_TYPE formatAllDeenv[] = { \n\tCRYPT_FORMAT_AUTO, CRYPT_FORMAT_CMS, CRYPT_FORMAT_PGP, \n\tCRYPT_FORMAT_NONE, CRYPT_FORMAT_NONE };\nstatic const CRYPT_FORMAT_TYPE formatAllCMS[] = {\n\tCRYPT_FORMAT_AUTO, CRYPT_FORMAT_CRYPTLIB, CRYPT_FORMAT_CMS, \n\tCRYPT_FORMAT_SMIME, CRYPT_FORMAT_NONE, CRYPT_FORMAT_NONE };\nstatic const CRYPT_FORMAT_TYPE formatAllSMIME[] = {\n\tCRYPT_FORMAT_AUTO, CRYPT_FORMAT_CMS, CRYPT_FORMAT_SMIME, \n\tCRYPT_FORMAT_NONE, CRYPT_FORMAT_NONE };\nstatic const CRYPT_FORMAT_TYPE formatAllEnvSMIME[] = {\n\tCRYPT_FORMAT_CMS, CRYPT_FORMAT_SMIME, CRYPT_FORMAT_NONE, \n\tCRYPT_FORMAT_NONE };\n\n/* The following lookup table defines the checks that are applied to each \n   attribute as it's added.\n\n\t  Attribute\t\t\t\t\t\tFormat\t\t\tEnv.usage\t\tAction to chk.\t\t\tEnv.flags */\nstatic const CHECK_INFO checkTable[] = {\n#ifdef USE_COMPRESSION\n\t{ CRYPT_ENVINFO_COMPRESSION,\tformatAllEnv,\tACTION_COMPRESS, MESSAGE_CHECK_NONE,\t0 },\n#endif /* USE_COMPRESSION */\n\t{ CRYPT_ENVINFO_DETACHEDSIGNATURE, formatAll,\tACTION_SIGN,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_ENVINFO_INTEGRITY,\t\tformatAllEnv,\tACTION_NONE,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_ENVINFO_KEY,\t\t\tformatAllCMS,\tACTION_CRYPT,\tMESSAGE_CHECK_CRYPT,\t0 },\n\t{ CRYPT_ENVINFO_SIGNATURE,\t\tformatAll,\t\tACTION_NONE,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_ENVINFO_SIGNATURE_EXTRADATA, formatAllEnvSMIME, ACTION_NONE, MESSAGE_CHECK_NONE, 0 },\n\t{ CRYPT_ENVINFO_PUBLICKEY,\t\tformatAllEnv,\tACTION_CRYPT,\tMESSAGE_CHECK_PKC_ENCRYPT, 0 },\n\t{ CRYPT_ENVINFO_PRIVATEKEY,\t\tformatAllDeenv,\tACTION_CRYPT,\tMESSAGE_CHECK_PKC_DECRYPT, ENVELOPE_FLAG_ISDEENVELOPE },\n\t{ CRYPT_ENVINFO_SESSIONKEY,\t\tformatAllCMS,\tACTION_CRYPT,\tMESSAGE_CHECK_CRYPT,\t0 },\n\t{ CRYPT_ENVINFO_HASH,\t\t\tformatAll,\t\tACTION_NONE,\tMESSAGE_CHECK_HASH,\t\tENVELOPE_FLAG_DETACHED_SIG },\n\t{ CRYPT_ENVINFO_TIMESTAMP,\t\tformatAllEnvSMIME, ACTION_SIGN,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_OPTION_ENCR_MAC,\t\tformatAllCMS,\tACTION_NONE,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_IATTRIBUTE_INCLUDESIGCERT, formatAllEnvSMIME, ACTION_SIGN, MESSAGE_CHECK_NONE,\t0 },\n\t{ CRYPT_IATTRIBUTE_ATTRONLY,\tformatAllSMIME,\tACTION_SIGN,\tMESSAGE_CHECK_NONE,\t\t0 },\n\t{ CRYPT_ATTRIBUTE_NONE, NULL, ACTION_NONE, 0 }, { CRYPT_ATTRIBUTE_NONE, NULL, ACTION_NONE, 0 }\n\t};\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setEnvelopeAttribute( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  IN_INT_Z const int value, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst ENV_ADDINFO_FUNCTION addInfoFunction = \\\n\t\t\t\t( ENV_ADDINFO_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoFunction );\n\tMESSAGE_CHECK_TYPE checkType = MESSAGE_CHECK_NONE;\n\tACTION_TYPE usage = ACTION_NONE;\n\tconst CRYPT_FORMAT_TYPE *formatTypeInfo = NULL;\n\tint requiredFlag = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( ( attribute == CRYPT_ENVINFO_COMPRESSION || \\\n\t\t\t\tattribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t\tattribute == CRYPT_ATTRIBUTE_CURRENT ) || \n\t\t\t\t/* Compression = CRYPT_UNUSED, CURRENT = cursor positioning \n\t\t\t\t   code */\n\t\t\t  isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( addInfoFunction != NULL );\n\n\t/* Generic attributes are valid for all envelope types */\n\tif( attribute == CRYPT_ATTRIBUTE_BUFFERSIZE )\n\t\t{\n\t\tenvelopeInfoPtr->bufSize = value;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's meta-information, process it now */\n\tif( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\tattribute == CRYPT_ATTRIBUTE_CURRENT )\n\t\t{\n\t\treturn( setCursorSelection( envelopeInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\tvalue ) );\n\t\t}\n\n\t/* In general we can't add new enveloping information once we've started\n\t   processing data */\n\tif( envelopeInfoPtr->state != ENVELOPE_STATE_PREDATA )\n\t\t{\n\t\t/* We can't add new information once we've started enveloping */\n\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\t/* We can only add signature check information once we've started\n\t\t   de-enveloping */\n\t\tif( attribute != CRYPT_ENVINFO_SIGNATURE )\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* Since the information may not be used for quite some time after it's\n\t   added we do some preliminary checking here to allow us to return an\n\t   error code immediately rather than from some deeply-buried function an\n\t   indeterminate time in the future.  Since much of the checking is\n\t   similar, we use a table-driven check for most types and fall back to\n\t   custom checking for special cases */\n\tLOOP_MED( i = 0,\n\t\t\t  checkTable[ i ].type != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( checkTable, CHECK_INFO ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( checkTable[ i ].type == attribute )\n\t\t\t{\n\t\t\tformatTypeInfo = checkTable[ i ].formatType;\n\t\t\tusage = checkTable[ i ].usage;\n\t\t\tcheckType = checkTable[ i ].checkType;\n\t\t\trequiredFlag = checkTable[ i ].requiredFlag;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( checkTable, CHECK_INFO ) );\n\n\t/* Make sure that this attribute is valid for this envelope type */\n\tif( formatTypeInfo != NULL )\n\t\t{\n\t\tBOOLEAN formatOK = FALSE;\n\n\t\tLOOP_SMALL( i = 0,\n\t\t\t\t\tformatTypeInfo[ i ] != CRYPT_FORMAT_NONE && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( formatAll, \\\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE ),\n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( envelopeInfoPtr->type == formatTypeInfo[ i ] )\n\t\t\t\t{\n\t\t\t\tformatOK = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( formatAll, CRYPT_ATTRIBUTE_TYPE ) );\n\t\tif( !formatOK )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t}\n\n\t/* Make sure that the attribute is valid for the envelope usage type.\n\t   A useage of ACTION_NONE means that the attribute requires special-\n\t   case checking that's outside the scope of the basic ACL */\n\tif( usage != ACTION_NONE )\n\t\t{\n\t\t/* Make sure that the usage requirements for the item that we're \n\t\t   about to add are consistent */\n\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\tenvelopeInfoPtr->usage != usage )\n\t\t\t{\n\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t attribute ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's not a general class of action, perform special-case usage \n\t\t   checking */\n\t\tstatus = checkOtherAttribute( envelopeInfoPtr, value, attribute, \n\t\t\t\t\t\t\t\t\t  &usage, &checkType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* An attribute that's handled internally will return OK_SPECIAL \n\t\t\t   to indicate that there's nothing further to do */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make sure the attribute can be used as required */\n\tif( checkType != MESSAGE_CHECK_NONE )\n\t\t{\n\t\t/* Check the object as appropriate */\n\t\tstatus = krnlSendMessage( value, IMESSAGE_CHECK, NULL, checkType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* Make sure that the object corresponds to a representable algorithm\n\t\t   type.  Note that this check isn't totally foolproof on de-\n\t\t   enveloping PGP data since the user can push in the hash context \n\t\t   before they push in the signed data (to signifiy the use of a \n\t\t   detached signature) so it'd be checked using the default (CMS) \n\t\t   algorithm values rather than the PGP ones */\n\t\tif( checkType == MESSAGE_CHECK_PKC_ENCRYPT || \\\n\t\t\tcheckType == MESSAGE_CHECK_PKC_DECRYPT || \\\n\t\t\tcheckType == MESSAGE_CHECK_PKC_SIGN || \\\n\t\t\tcheckType == MESSAGE_CHECK_PKC_SIGCHECK || \\\n\t\t\tcheckType == MESSAGE_CHECK_CRYPT || \\\n\t\t\tcheckType == MESSAGE_CHECK_HASH || \\\n\t\t\tcheckType == MESSAGE_CHECK_MAC )\n\t\t\t{\n\t\t\tconst ENV_CHECKALGO_FUNCTION checkAlgoFunction = \\\n\t\t\t\t\t( ENV_CHECKALGO_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->checkAlgoFunction );\n\t\t\tint algorithm, mode = CRYPT_MODE_NONE;\n\n\t\t\tREQUIRES( checkAlgoFunction != NULL );\n\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\t\t\tif( cryptStatusOK( status ) && checkType == MESSAGE_CHECK_CRYPT )\n\t\t\t\t{\n\t\t\t\t/* It's a conventional-encryption context, get the mode as \n\t\t\t\t   well */\n\t\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( !checkAlgoFunction( algorithm, mode ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\n\t\t/* If we're using CMS enveloping then the object must have an \n\t\t   initialised certificate of the correct type associated with it.  \n\t\t   Most of this will be caught by the kernel but there are a couple \n\t\t   of special cases (e.g. an attribute certificate where the main \n\t\t   object is a PKC context) which are missed by the general kernel \n\t\t   checks.\n\n\t\t   We can't perform this check on de-enveloping because we don't\n\t\t   know at this stage whether the keying resources needed are \n\t\t   identified by issuerAndSerialNumber or by keyID, a certificate is \n\t\t   only required for the former */\n\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) && \\\n\t\t\t( attribute == CRYPT_ENVINFO_SIGNATURE || \\\n\t\t\t  attribute == CRYPT_ENVINFO_PUBLICKEY || \\\n\t\t\t  attribute == CRYPT_ENVINFO_PRIVATEKEY || \\\n\t\t\t  attribute == CRYPT_ENVINFO_ORIGINATOR ) && \n\t\t\t( envelopeInfoPtr->type == CRYPT_FORMAT_CMS || \\\n\t\t\t  envelopeInfoPtr->type == CRYPT_FORMAT_SMIME ) )\n\t\t\t{\n\t\t\tBOOLEAN_INT isInited;\n\t\t\tint certType;\n\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\t\t\tif( cryptStatusError( status ) ||\n\t\t\t\t( certType != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\t  certType != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\t\t{\n\t\t\t\t/* These objects work with CRYPT_FORMAT_CRYPTLIB but not \n\t\t\t\t   CRYPT_FORMAT_CMS/SMIME, which may be confusing for some\n\t\t\t\t   users so we try and provide somewhat more detailed \n\t\t\t\t   information on what the problem is.  Since it's the\n\t\t\t\t   result of a complex dependency it's a bit difficult to \n\t\t\t\t   do, the following is about the best that we can manage */\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_CERTINFO_CERTIFICATE, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &isInited, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_IMMUTABLE );\n\t\t\tif( cryptStatusError( status ) || !isInited )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that any required envelope flags are set */\n\tif( requiredFlag != 0 )\n\t\t{\n\t\t/* Make sure that the required enveloping flag is set */\n\t\tif( !TEST_FLAGS( envelopeInfoPtr->flags, requiredFlag, \n\t\t\t\t\t\t requiredFlag ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Add it to the envelope */\n\tstatus = addInfoFunction( envelopeInfoPtr, attribute, value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\treturn( exitErrorInited( envelopeInfoPtr, attribute ) );\n\t\treturn( status );\n\t\t}\n\tif( usage != ACTION_NONE )\n\t\t{\n\t\t/* The action was successfully added, update the usage if \n\t\t   necessary */\n\t\tenvelopeInfoPtr->usage = usage;\n\n\t\t/* If we're encrypting the content and using the cryptlib native \n\t\t   format, enable authenticated encryption by default unless we're\n\t\t   using raw session-key based encryption, which precludes using\n\t\t   authenticated encryption.  Unfortunately we can't do this for \n\t\t   CMS / S/MIME because of backwards-compatibility considerations \n\t\t   with other implementations */\n\t\tif( usage == ACTION_CRYPT && \\\n\t\t\tenvelopeInfoPtr->type == CRYPT_FORMAT_CRYPTLIB && \\\n\t\t\tattribute != CRYPT_ENVINFO_SESSIONKEY )\n\t\t\t{\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setEnvelopeAttributeS( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t   IN_LENGTH const int dataLength,\n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst ENV_ADDINFO_FUNCTION addInfoFunction = \\\n\t\t\t\t( ENV_ADDINFO_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoFunction );\n\tconst ENV_ADDINFOSTRING_FUNCTION addInfoStringFunction = \\\n\t\t\t\t( ENV_ADDINFOSTRING_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoStringFunction );\n\tACTION_TYPE usage = ACTION_NONE;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( addInfoFunction != NULL );\n\tREQUIRES( addInfoStringFunction != NULL );\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ENVINFO_PASSWORD:\n\t\t\t/* Set the envelope usage type based on the fact that we've been\n\t\t\t   fed a password */\n\t\t\tif( envelopeInfoPtr->usage == ACTION_NONE )\n\t\t\t\tusage = ACTION_CRYPT;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( envelopeInfoPtr->usage != ACTION_CRYPT && \\\n\t\t\t\t\tenvelopeInfoPtr->usage != ACTION_MAC )\n\t\t\t\t\t{\n\t\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_PASSWORD ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* In general we can't add new enveloping information once we've\n\t\t\t   started processing data */\n\t\t\tif( envelopeInfoPtr->state != ENVELOPE_STATE_PREDATA && \\\n\t\t\t\t!TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t\t\t{\n\t\t\t\t/* We can't add new information once we've started enveloping */\n\t\t\t\treturn( exitErrorInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ENVINFO_PASSWORD ) );\n\t\t\t\t}\n\n\t\t\t/* Add it to the envelope */\n\t\t\tstatus = addInfoStringFunction( envelopeInfoPtr, \n\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PASSWORD, data, dataLength );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ENVINFO_RECIPIENT:\n\t\t\t{\n\t\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\n\t\t\t/* Set the envelope usage type based on the fact that we've been\n\t\t\t   fed a recipient email address */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tusage = ACTION_CRYPT;\n\n\t\t\t/* Make sure that there's a keyset available to pull the \n\t\t\t   recipient's key from */\n\t\t\tif( envelopeInfoPtr->iEncryptionKeyset == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_ENCRYPT ) );\n\t\t\t\t}\n\n\t\t\t/* Try and read the recipient's key from the keyset.  Some \n\t\t\t   keysets (particularly PKCS #11 devices, for which apps set \n\t\t\t   the usage flags more or less at random) may not be able to \n\t\t\t   differentiate between encryption and signature keys based on \n\t\t\t   the information that they have.  This isn't a problem when \n\t\t\t   matching a key based on a unique ID but with the use of the \n\t\t\t   recipient name as the ID there could be multiple possible \n\t\t\t   matches.  After we fetch the key we therefore perform an \n\t\t\t   extra check here to make sure that it really is an encryption-\n\t\t\t   capable key */\n\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_URI, data, \n\t\t\t\t\t\t\t\t   dataLength, NULL, 0, \n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_USAGE_CRYPT );\n\t\t\tstatus = krnlSendMessage( envelopeInfoPtr->iEncryptionKeyset,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\t/* Technically what we're looking for is an email address\n\t\t\t\t   (since this facility is meant for email encryption, thus\n\t\t\t\t   the \"recipient\" in the name) but it's possible that it's \n\t\t\t\t   being used in a more general manner to mean \"any random\n\t\t\t\t   key label\", so if the fetch based on an email address \n\t\t\t\t   fails we try again with a fetch based on a generic name */\n\t\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_NAME, data, \n\t\t\t\t\t\t\t\t\t   dataLength, NULL, 0, \n\t\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_USAGE_CRYPT );\n\t\t\t\tstatus = krnlSendMessage( envelopeInfoPtr->iEncryptionKeyset,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExtObj( status,\n\t\t\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t     envelopeInfoPtr->iEncryptionKeyset,\n\t\t\t\t\t\t\t \"Couldn't retrieve encryption key from keyset\" ) );\n\t\t\t\t}\n\n\t\t\t/* Make sure that the key really is valid for its intended \n\t\t\t   purpose */\n\t\t\tif( !checkContextCapability( getkeyInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( getkeyInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t\t\t( CRYPT_ERROR_NOTAVAIL, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Key for recipient can't be used for encryption\" ) );\n\t\t\t\t}\n\n\t\t\t/* We got the key, add it to the envelope */\n\t\t\tstatus = addInfoFunction( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\t\t\t  getkeyInfo.cryptHandle );\n\t\t\tkrnlSendNotifier( getkeyInfo.cryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\treturn( exitErrorInited( envelopeInfoPtr, attribute ) );\n\t\treturn( status );\n\t\t}\n\tif( usage != ACTION_NONE )\n\t\t{\n\t\t/* The action was successfully added, update the usage if \n\t\t   necessary */\n\t\tenvelopeInfoPtr->usage = usage;\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/envelope/envelope.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Enveloping Routines Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ENV_DEFINED\n\n#define _ENV_DEFINED\n\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n#ifdef USE_COMPRESSION\n  #if defined HAS_ZLIB\n\t#include <zlib.h>\n  #elif defined( INC_ALL )\n\t#include \"zlib.h\"\n  #else\n\t#include \"zlib/zlib.h\"\n  #endif /* Compiler-specific includes */\n#endif /* USE_COMPRESSION */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEnvelope Actions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Types of actions that can be performed on a piece of envelope data.  The \n   two key exchange actions are handled identically, but are given different \n   tags because we place PKC-based key exchange actions (which may be \n   handled automatically on de-enveloping) before conventional key exchange \n   actions (which usually require manual intervention for passphrases).  For \n   this reason the actions are given in their sort order (i.e. \n   ACTION_KEYEXCHANGE_PKC precedes ACTION_KEYEXCHANGE in the action list).\n   The same occurs for the crypto actions ACTION_xxx, ACTION_CRYPT, and\n   ACTION_MAC, which when used for authenticated encryption are applied in\n   that order */\n\ntypedef enum {\n\tACTION_NONE,\t\t\t\t\t/* Non-action */\n\n\t/* Pre-actions */\n\tACTION_KEYEXCHANGE_PKC,\t\t\t/* Generate/read PKC exchange information */\n\tACTION_KEYEXCHANGE,\t\t\t\t/* Generate/read key exchange information */\n\n\t/* Actions */\n\tACTION_xxx,\t\t\t\t\t\t/* Generic-secret XXX action */\n\tACTION_CRYPT,\t\t\t\t\t/* En/decrypt */\n\tACTION_MAC,\t\t\t\t\t\t/* MAC */\n\tACTION_COMPRESS,\t\t\t\t/* Compress */\n\tACTION_HASH,\t\t\t\t\t/* Hash */\n\n\t/* Post-actions */\n\tACTION_SIGN,\t\t\t\t\t/* Generate/check signature */\n\n\tACTION_LAST\t\t\t\t\t\t/* Last valid action type */\n\t} ACTION_TYPE;\n\n/* An 'action list' that defines what we need to do to the content when\n   enveloping data.  There are three action lists, one for actions to perform\n   before enveloping data, one to perform during enveloping (which is \n   actually just a single action rather than a list), and one to perform \n   after enveloping.  ACTION_KEYEXCHANGE and ACTION_KEYEXCHANGE_PKC are found \n   in the pre-enveloping list, ACTION_SIGN in the post-enveloping list, and \n   everything else in the during-enveloping list.\n\n   Some actions are many-to-one, in which a number of controlling actions in\n   one list may act on a single subject action in another list (for example a\n   number of signature actions may sign the output from a single hash\n   action).  This is handled by having the controlling actions maintain\n   pointers to the subject action, for example a number of key export actions\n   would point to one encryption action, with the export actions exporting\n   the session key for the encryption action.\n\n   The flags are:\n\n\tFLAG_ADDEDAUTOMATICALLY: Whether a subject action was added \n\t\tautomatically and invisibly to the caller as a result of adding a \n\t\tcontrolling action, for example a hash action created when a signing \n\t\taction is added.  This is to ensure that we don't return an error \n\t\tthe first time the caller adds an action which is identical to an \n\t\tautomatically added action.\n\n\tFLAG_HASHCOMPLETE: Whether the hashing for a hash action has already \n\t\tbeen completed and we don't need to do it ourselves.  If we're using \n\t\ta detached signature then the hash value will be supplied externally \n\t\tand there's no need to complete the hashing.\n   \n\tFLAG_NEEDSCONTROLLER: Whether this is a subject action that still \n\t\trequires a controlling action.  This allows us to identify unused \n\t\tsubject actions more easily than by scanning all controller->subject \n\t\trelationships */\n\n#define ACTION_FLAG_NONE\t\t\t0x00\t/* No content flag */\n#define ACTION_FLAG_NEEDSCONTROLLER\t0x01\t/* Whether action reqs.controller */\n#define ACTION_FLAG_ADDEDAUTOMATICALLY 0x02\t/* Whether action added automat.*/\n#define ACTION_FLAG_HASHCOMPLETE\t0x04\t/* Whether hash is complete */\n#define ACTION_FLAG_MAX\t\t\t\t0x07\t/* Maximum possible flag value */\n\ntypedef struct AI {\n\t/* Control and status information */\n\tACTION_TYPE action;\t\t\t\t/* Type of action to perform */\n\tSAFE_FLAGS flags;\t\t\t\t/* Action flags */\n\tDATAPTR next;\t\t\t\t\t/* Next item in the list */\n\n\t/* The controlling/subject action.  This points to the subject action \n\t   associated with a controlling action if this is a controlling \n\t   action */\n\tDATAPTR associatedAction;\t\t/* Associated action */\n\n\t/* Information related to the action.  These fields contain various\n\t   pieces of information required as part of the action.  The crypt\n\t   handle contains the encryption context needed to perform the action \n\t   (e.g. encryption, hashing, signing).  If we're generating CMS \n\t   signatures, there may be extra attribute data present which is \n\t   included in the signature, and we may also have countersignature \n\t   information present, typically a timestamping session object */\n\tCRYPT_CONTEXT iCryptHandle;\t\t/* Encryption handle for action */\n\tCRYPT_CERTIFICATE iExtraData;\t/* Extra attribute data for CMS sigs.*/\n\tCRYPT_SESSION iTspSession;\t\t/* Timestamping session object */\n\tint encodedSize;\t\t\t\t/* The encoded size of the action */\n\t} ACTION_LIST;\n\n/* An indicator of which action list we're working with, passed to functions\n   that manipulate action lists */\n\ntypedef enum { \n\tACTIONLIST_NONE,\t\t\t\t/* No action list type */\n\tACTIONLIST_PREACTION,\t\t\t/* Pre-action list */\n\tACTIONLIST_ACTION,\t\t\t\t/* Main action list */\n\tACTIONLIST_POSTACTION,\t\t\t/* Post-action list */\n\tACTIONLIST_LAST\t\t\t\t\t/* Last possible action list type */\n\t} ACTIONLIST_TYPE;\n\n/* Result codes for the checkAction() function when adding an action to\n   an action list.  The two 'action present' results are for the case where \n   the action is already present and shouldn't be added again, and where the \n   action is present from being added as an (invisible to the user) side-\n   effect of another action being added, so that this attempt to add it \n   should be reported as CRYPT_OK rather than CRYPT_INITED */\n\ntypedef enum {\n\tACTION_RESULT_OK,\t\t\t\t/* Action not present, can be added */\n\tACTION_RESULT_EMPTY,\t\t\t/* Action list is empty */\n\tACTION_RESULT_INITED,\t\t\t/* Action present (CRYPT_ERROR_INITED) */\n\tACTION_RESULT_PRESENT,\t\t\t/* Action present (CRYPT_OK) */\n\tACTION_RESULT_ERROR,\t\t\t/* Arg.error (CRYPT_ARGERROR_NUM1) */\n\tACTION_RESULT_LAST\t\t\t\t/* Last valid action result type */\n\t} ACTION_RESULT;\n\n/* Envelope content information types */\n\ntypedef enum {\n\tCONTENT_NONE,\t\t\t\t\t/* No content type */\n\tCONTENT_CRYPT,\t\t\t\t\t/* Encrypted content info */\n\tCONTENT_SIGNATURE,\t\t\t\t/* Signed content info */\n\tCONTENT_AUTHENC,\t\t\t\t/* Auth-enc content info */\n\tCONTENT_LAST\t\t\t\t\t/* Last possible content type */\n\t} CONTENT_TYPE;\n\n/* Content information flags.  These are:\n\n\tFLAG_PROCESSED: The signature object has been processed by having the \n\t\tsignature verified (or at least attempted to be verified).  The \n\t\tverification result is stored/cached with the content info for later \n\t\tuse.\n\n\tFLAG_EXTERNALKEY: The signature-check key was supplied by the user \n\t\trather than being instantiated internally from certificates \n\t\tassociated with the signature */\n\n#define CONTENT_FLAG_NONE\t\t0x00\t/* No content flag */\n#define CONTENT_FLAG_PROCESSED\t0x01\t/* Whether object has been processed */\n#define CONTENT_FLAG_EXTERNALKEY 0x02\t/* Whether key was added externally */\n#define CONTENT_FLAG_MAX\t\t0x03\t/* Maximum possible flag value */\n\n/* A 'content list' which is used to store objects found in the non-data\n   portion of the envelope until we can do something with them when de-\n   enveloping data */\n\n#define clEncrInfo\t\tcontentInfo.contentEncrInfo\n#define clSigInfo\t\tcontentInfo.contentSigInfo\n#define clAuthEncInfo\tcontentInfo.contentAuthEncInfo\n\ntypedef struct {\n\t/* Encryption algorithm/key information */\n\tCRYPT_ALGO_TYPE cryptAlgo;\t\t/* Encryption algo.for this object */\n\tCRYPT_MODE_TYPE cryptMode;\t\t/* Encrytion mode for this object */\n\n\t/* Encryption key setup information */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltOrIVsize ) \\\n\tBYTE saltOrIV[ CRYPT_MAX_HASHSIZE + 8 ];/* Salt for password-derived key or */\n\tint saltOrIVsize;\t\t\t\t/*\t   IV for session encr.context */\n\tCRYPT_ALGO_TYPE keySetupAlgo;\t/* Hash algo.for pw-derived key */\n\tint keySetupAlgoParam;\t\t\t/* Optional algorithm parameter */\n\tint keySetupIterations;\t\t\t/* Iterations for pw-derived key */\n\tint keySize;\t\t\t\t\t/* Key size (if not implicit) */\n\t} CONTENT_ENCR_INFO;\t\n\ntypedef struct {\n\t/* Signature algorithm/key information */\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t/* Hash algo.for signed data */\n\tint hashAlgoParam;\t\t\t\t/* Optional algorithm parameter */\n\tCRYPT_HANDLE iSigCheckKey;\t\t/* Signature check key */\n\n\t/* Authenticated/unauthenticated attribute information.  The pointers\n\t   point to locations within the object pointer data */\n\tCRYPT_CERTIFICATE iExtraData;\t/* Authent.attrib.in CMS signatures */\n\tBUFFER_OPT_FIXED( extraDataLength ) \\\n\tconst void *extraData;\t\t\t/* Authent.attrib.in PGP signatures */\n\tint extraDataLength;\n\tCRYPT_ENVELOPE iTimestamp;\t\t/* Unauth.attrib.in CMS signatures */\n\tBUFFER_OPT_FIXED( extraData2Length ) \\\n\tconst void *extraData2;\t\t\t/* Unauthenticated attributes */\n\tint extraData2Length;\n\n\t/* We only need to process a signed object once, once we've done this we \n\t   store the processing result so that any further attempts to process \n\t   the object will return the previously obtained result (an object can \n\t   be processed multiple times if the user wanders up and down the \n\t   content list using the cursor management capabilities) */\n\tint processingResult;\t\t\t/* Result of processing */\n\t\n\t/* To allow positioning of the cursor within this item (== attribute \n\t   group), we have to keep track of the virtual position within the\n\t   group.  The virtual attribute order is result -> key -> auth.\n\t   attr -> timestamp */\n\tCRYPT_ATTRIBUTE_TYPE attributeCursorEntry;\n\t} CONTENT_SIG_INFO;\n\ntypedef struct {\n\t/* Authenticated-encryption algorithm information */\n\tCRYPT_ALGO_TYPE authEncAlgo;\t/* AuthEnc algo.for this object */\n\n\t/* Authenticated encryption algorithm parameter data.  The various \n\t   pointers point to locations within the authEncParamData, not the\n\t   object pointer data */\n\tBUFFER( 128, authEncParamLength ) \\\n\tBYTE authEncParamData[ 128 + 8 ];\n\tint authEncParamLength;\t\t\t/* AuthEnc parameter data */\n\tBUFFER_FIXED( kdfDataLength ) \\\n\tvoid *kdfData;\n\tint kdfDataLength;\t\t\t\t/* Opt.KDF algorithm params */\n\tBUFFER_FIXED( encParamDataLength ) \\\n\tvoid *encParamData;\n\tint encParamDataLength;\t\t\t/* Encryption algorithm params */\n\tBUFFER_FIXED( macParamDataLength ) \\\n\tvoid *macParamData;\n\tint macParamDataLength;\t\t\t/* MAC algorithm params */\n\t} CONTENT_AUTHENC_INFO;\n\ntypedef struct CL {\n\t/* Control and status information */\n\tCONTENT_TYPE type;\t\t\t\t/* Content type enc/authenc/sig */\n\tCRYPT_ATTRIBUTE_TYPE envInfo;\t/* Env.info required to continue */\n\tCRYPT_FORMAT_TYPE formatType;\t/* Data format */\n\tSAFE_FLAGS flags;\t\t\t\t/* Item flags */\n\tDATAPTR prev, next;\t\t\t\t/* Prev, next items in the list */\n\n\t/* The object contained in this list element.  All object type-specific\n\t   pointers in the xxxInfo data point into fields inside this data.\n\t   \n\t   The object pointer is a safe pointer because it's the primary pointer\n\t   to the object data.  All other pointers are standard pointers because\n\t   they're checked to ensure that they point within { object, \n\t   objectSize }, so there's no need to make each of them safe pointers */\n\tDATAPTR object;\t\t\t\t\t/* The object data */\n\tint objectSize;\t\t\t\t\t/* Size of the object */\n\n\t/* Details on the object.  Here we store whatever is required to process\n\t   the object without having to call queryXXXObject() for the details */\n\tBUFFER( CRYPT_MAX_HASHSIZE, keyIDsize ) \\\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];/* cryptlib key ID */\n\tint keyIDsize;\n\tBUFFER_OPT_FIXED( issuerAndSerialNumberSize ) \\\n\tconst void *issuerAndSerialNumber;/* CMS key ID */\n\tint issuerAndSerialNumberSize;\n\tBUFFER_OPT_FIXED( payloadSize ) \\\n\tconst void *payload;\t\t\t/* Payload data (e.g. encr.key) */\n\tint payloadSize;\n\tunion {\n\t\tCONTENT_ENCR_INFO contentEncrInfo;\t/* Encryption obj-specific infor.*/\n\t\tCONTENT_SIG_INFO contentSigInfo;\t/* Signature obj-specific info.*/\n\t\tCONTENT_AUTHENC_INFO contentAuthEncInfo;/* Auth-enc obj-spec.info */\n\t\t} contentInfo;\n\t} CONTENT_LIST;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDe-envelope Actions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The current state of the (de)enveloping.  The states are the predata state\n   (when we're performing final setup steps and handling header information\n   in the envelope), the data state (when we're enveloping data), the\n   postdata state (when we're handling trailer information), and the\n   extradata state (when we're processing out-of-band data such as the data\n   associated with detached signatures) */\n\ntypedef enum {\n\tENVELOPE_STATE_NONE,\t\t\t/* No envelope state */\n\tENVELOPE_STATE_PREDATA,\t\t\t/* Emitting header information */\n\tENVELOPE_STATE_DATA,\t\t\t/* During (de)enveloping of data */\n\tENVELOPE_STATE_POSTDATA,\t\t/* After (de)enveloping of data */\n\tENVELOPE_STATE_EXTRADATA,\t\t/* Additional out-of-band data */\n\tENVELOPE_STATE_FINISHED,\t\t/* Finished processing */\n\tENVELOPE_STATE_LAST\t\t\t\t/* Last valid enveloping state */\n\t} ENVELOPE_STATE;\n\n/* The current state of the processing of CMS headers that contain non-data\n   during the enveloping process.  Before the enveloping of data begins, the\n   user pushes in a variety of enveloping information, which in turn might\n   trigger the creation of more internal information objects.  Once the\n   enveloping begins, this information is encoded as ASN.1 structures and \n   written into the envelope buffer.  The encoding process can be interrupted \n   at any point when the envelope buffer fills up, so we break it down into a \n   series of atomic states between which the enveloping process can be \n   interrupted by the caller removing data from the envelope.\n\n   There are two sets of states, the first set that covers the encoding of\n   the header information at the start of the envelope (only key exchange\n   information requires this), and the second that covers the information at\n   the end of the envelope (only signatures require this) */\n\ntypedef enum {\n\tENVSTATE_NONE,\t\t\t\t\t/* No header processing/before header */\n\n\t/* Header state information */\n\tENVSTATE_HEADER,\t\t\t\t/* Emitting header */\n\tENVSTATE_KEYINFO,\t\t\t\t/* Emitting key exchange information */\n\tENVSTATE_ENCRINFO,\t\t\t\t/* Emitting EncrContentInfo information */\n\n\tENVSTATE_DATA,\t\t\t\t\t/* Emitting data payload information */\n\n\t/* Trailer state information */\n\tENVSTATE_FLUSHED,\t\t\t\t/* Data flushed through into buffer */\n\tENVSTATE_SIGNATURE,\t\t\t\t/* Emitting signatures */\n\n\tENVSTATE_DONE,\t\t\t\t\t/* Finished processing header/trailer */\n\n\tENVSTATE_LAST\t\t\t\t\t/* Last valid enveloping state */\n\t} ENV_STATE;\n\n/* The current state of the processing of CMS headers that contain non-data\n   in the envelope during the de-enveloping process.  This is implemented as \n   a somewhat complex FSM because the enveloping routines give the user the\n   ability to push in arbitrary amounts of data corresponding to various\n   enveloping structures and simultaneously pop out data/information based \n   on decoding them.  A typical complex enveloped type might contain a \n   number of headers, a session key encrypted with 18 different public keys, \n   five varieties of signature type, and God knows what else, of which the \n   caller might feed us 500 bytes - a small fraction of the total data - and \n   then ask for information on what they've just fed us.  We have to \n   remember how far we got (halfway through an RSA-encrypted DES key fifteen \n   levels of nesting down in an ASN.1 structure), process everything that we \n   can, and then get back to them on what we found.  Then they feed us \n   another few hundred bytes and the whole thing starts anew.\n\n   The state machine works by processing one complete object or part of an\n   object at a time and then moving on to the next state that corresponds to\n   handling another part of the object or another object.  If there isn't\n   enough data present to process a part or subpart, we return an underflow\n   error and try again when more data is added */\n\ntypedef enum {\n\tDEENVSTATE_NONE,\t\t\t\t/* No header processing/before header */\n\n\t/* Header state information */\n\tDEENVSTATE_SET_ENCR,\t\t\t/* Processing start of SET OF EncrKeyInfo */\n\tDEENVSTATE_ENCR,\t\t\t\t/* Processing EncrKeyInfo records */\n\tDEENVSTATE_ENCRCONTENT,\t\t\t/* Processing EncrContentInfo */\n\n\tDEENVSTATE_SET_HASH,\t\t\t/* Processing start of SET OF DigestAlgoID */\n\tDEENVSTATE_HASH,\t\t\t\t/* Processing DigestAlgoID (for hash) records */\n\tDEENVSTATE_MAC,\t\t\t\t\t/* Processing DigestAlgoID (for MAC) records */\n\t\n\tDEENVSTATE_CONTENT,\t\t\t\t/* Processing ContentInfo */\n\tDEENVSTATE_DATA,\t\t\t\t/* Processing data payload */\n\n\t/* Trailer state information */\n\tDEENVSTATE_CERTSET,\t\t\t\t/* Processing optional cert chain */\n\tDEENVSTATE_SET_SIG,\t\t\t\t/* Processing start of SET OF Signature */\n\tDEENVSTATE_SIG,\t\t\t\t\t/* Processing Signature records */\n\tDEENVSTATE_EOC,\t\t\t\t\t/* Processing end-of-contents octets */\n\n\tDEENVSTATE_DONE,\t\t\t\t/* Finished processing header/trailer */\n\n\tDEENVSTATE_LAST\t\t\t\t\t/* Last valid de-enveloping state */\n\t} DEENV_STATE;\n\n/* The current state of processing of PGP headers that contain non-data in \n   the envelope during the de-enveloping process.  These are somewhat \n   different to the ASN.1-encoded objects used by cryptlib in that many of \n   the objects are emitted as discrete packets rather than the nested \n   objects used in ASN.1 objects.  This makes some parts of the processing\n   much easier (less length information to track) and some parts much harder\n   (since just about anything could appear next, you need to maintain a\n   lookahead to figure out what to do next, but you may run out of data\n   before you can determine which state is next).  The handling of content\n   inside encrypted data is particularly messy since there's a plain-data\n   header that has to be removed in a manner which is transparent to the\n   user.\n   \n   The two de-enveloping encrypted-data states are almost identical except \n   for the fact that one performs PGP's odd IV resync while the other \n   doesn't, a requirement buried in the depths of two otherwise identical \n   text blocks in the RFC */\n\ntypedef enum {\n\tPGP_DEENVSTATE_NONE,\t\t\t/* No message processing/before message */\n\n\t/* Header state information */\n\tPGP_DEENVSTATE_ENCR_HDR,\t\t/* PKE/SKE packet */\n\tPGP_DEENVSTATE_ENCR,\t\t\t/* Encrypted data packet */\n\tPGP_DEENVSTATE_ENCR_MDC,\t\t/* Encrypted data with MDC */\n\n\tPGP_DEENVSTATE_DATA,\t\t\t/* Data */\n\tPGP_DEENVSTATE_DATA_HEADER,\t\t/* Out-of-band data inside compressed data */\n\n\tPGP_DEENVSTATE_DONE,\t\t\t/* Finished processing message */\n\n\tPGP_DEENVSTATE_LAST\t\t\t\t/* Last valid de-enveloping state */\n\t} PGP_DEENV_STATE;\n\n/* Envelope information flags.  These are:\n\n\tFLAG_ISDEENVELOPE: The envelope is a de-enveloping envelope.\n\n\tFLAG_DETACHED_SIG: The (signed data) envelope should generate a\n\t\t\tstandalone detached signature rather than signed enveloped data.\n\n\tFLAG_NOSIGNINGCERTS: When generating a S/MIME signed data, don't\n\t\t\tinclude the signing certificates with the data.\n\n\tFLAG_ATTRONLY: The (signed data) envelope only contains authenticated\n\t\t\tattributes, but not actual data.  This is required by SCEP.\n\n\tFLAG_ZSTREAMINITED: Whether the zlib compression/decompression stream\n\t\t\thas been initialised.\n\t\n\tFLAG_AUTHENC: Use authenticated encryption, which adds a MAC tag to\n\t\t\tthe encrypted data */\n\n#define ENVELOPE_FLAG_NONE\t\t\t0x00\t/* No envelope flag */\n#define ENVELOPE_FLAG_ISDEENVELOPE\t0x01\t/* De-enveloping envelope */\n#define ENVELOPE_FLAG_DETACHED_SIG\t0x02\t/* Generate detached signature */\n#define ENVELOPE_FLAG_NOSIGNINGCERTS 0x04\t/* Don't include signing certs */\n#define ENVELOPE_FLAG_ATTRONLY\t\t0x08\t/* Env.contains only auth'd attrs.*/\n#define ENVELOPE_FLAG_ZSTREAMINITED\t0x10\t/* Whether zlib stream has been inited */\n#define ENVELOPE_FLAG_AUTHENC\t\t0x20\t/* Use authenticated encryption */\n#define ENVELOPE_FLAG_MAX\t\t\t0x3F\t/* Maximum possible flag value */\n\n/* Envelope data processing flags.  These are:\n\n\tFLAG_AUTHENACTIONSACTIVE: The (authenticated-encrypted) envelope is\n\t\t\tcurrently hashing payload data.  This differs from \n\t\t\tHASHACTIONSACTIVE in that it hashes ciphertext, not plaintext.\n\n\tFLAG_HASINDEFTRAILER: The (signed) envelope trailer has an indefinite\n\t\t\tlength due to the use of signature algorithms that produce \n\t\t\tvariable-length output that can't be determined in advance.\n\n\tFLAG_HASHACTIONSACTIVE: The (signed) envelope is currently hashing\n\t\t\tpayload data.  This differs from AUTHENCACTIONSACTIVE in that\n\t\t\tit hashes plaintext, not ciphertext.\n\n\tFLAG_NOLENGTHINFO: The payload uses neither a definite- nor \n\t\t\tindefinite-length encoding but continues until the caller tells\n\t\t\tus it's finished.  This is used to handle PGP 2.x compressed\n\t\t\tdata, which just continues until EOF with no length information\n\t\t\tprovided.\n\n\tFLAG_NOSEGMENT: The payload data shouldn't be segmented because a\n\t\t\tdefinite-length encoding is being used.\n\n\tFLAG_NOFIRSTSEGMENT: The payload data is segmented but the first \n\t\t\tsegment doesn't have an explicit length, being defined as \n\t\t\t\"whatever's left after the data at the start has been \n\t\t\tprocessed\".  This is used to handle PGP's indefinite-length\n\t\t\tencoding, which unlike ASN.1's \n\t\t\t\n\t\t\t\t[indef.marker][segment][segment]...[EOC]\n\n\t\t\tis encoded as:\n\n\t\t\t\t[length+cont,segment'][length+cont,segment]...[length,segment]\n\n\t\t\tso the initial length has already been read when the packet\n\t\t\theader was read.  We can't undo the read of the start of the \n\t\t\tfirst packet and treat it as a standard segement because the \n\t\t\tencoding for the first segment (denoted by segment' in the \n\t\t\tdiagram above) and the remaining segments is different so an \n\t\t\tattempt to treat them identically will lead to a decoding error.\n\n\tFLAG_SEGMENTCOMPLETE: An indefinite-length segment has been completed\n\t\t\tan another one must be begun before more payload data can be\n\t\t\temitted.\n\n\tFLAG_ENDOFCONTENTS: The EOC octets on indefinite payload data have \n\t\t\tbeen reached.\n\n\tFLAG_NEEDSPADDING: Before (encrypted) enveloping can been completed \n\t\t\tthe payload data needs PKCS #5 padding added to it.\n\n\tFLAG_HASATTACHEDOOB: The envelope has out-of-band additional data\n\t\t\tattached to the payload data.  This is used by OpenPGP to tack\n\t\t\tan MDC packet onto the end of encrypted data.\n\n   The handling of several of these flags is quite complex, more details can \n   be found in encode/decode.c */\n\n#define ENVDATA_FLAG_NONE\t\t\t0x0000\t/* No envelope data flag */\n#define ENVDATA_FLAG_HASINDEFTRAILER 0x0001\t/* Whether trailer size is indefinite */\n#define ENVDATA_FLAG_HASHACTIONSACTIVE 0x0002 /* Payload hashing is active */\n#define ENVDATA_FLAG_AUTHENCACTIONSACTIVE 0x0004\t/* Payload ciphertext hashing active */\n#define ENVDATA_FLAG_NOLENGTHINFO\t0x0008\t/* No length info for payload avail.*/\n#define ENVDATA_FLAG_NOSEGMENT\t\t0x0010\t/* Don't segment payload data */\n#define ENVDATA_FLAG_NOFIRSTSEGMENT\t0x0020\t/* No first segment length */\n#define ENVDATA_FLAG_SEGMENTCOMPLETE 0x0040\t/* Current segment has been completed */\n#define ENVDATA_FLAG_ENDOFCONTENTS\t0x0080\t/* EOC reached */\n#define ENVDATA_FLAG_NEEDSPADDING\t0x0100\t/* Whether to add PKCS #5 padding */\n#define ENVDATA_FLAG_HASATTACHEDOOB\t0x0200\t/* Whether data has attached OOB extra */\n#define ENVDATA_FLAG_MAX\t\t\t0x03FF\t/* Maximum possible flag value */\n\n/* Envelope data-copy flags.  These are:\n\n\tENVCOPY_FLAG_NONE: Perform no special processing.\n\n\tENVCOPY_FLAG_OOBDATA: Data is out-of-band data that isn't part of the \n\t\t\tnormal data payload */\n\n#define ENVCOPY_FLAG_NONE\t\t0x00\t/* No special action */\n#define ENVCOPY_FLAG_OOBDATA\t0x01\t/* Data is OOB rather than payload data */\n#define ENVCOPY_FLAG_MAX\t\t0x01\t/* Maximum possible flag value */\n\n/* The size of the buffers used to handle read-ahead into out-of-band data \n   at  the start of the payload, and to buffer leftover bytes when the data \n   that we're given is split exactly over a header (OCTET STRING + length\n   for CMS, partial length for PGP) that we can't leave with the payload \n   data but have to store until we get fed the rest of the header.  See\n   the longer comments where the variables are declared for details */\n\n#define OOB_BUFFER_SIZE\t\t\t8\n#define PARTIAL_BUFFER_SIZE\t\t16\n\n/* The structure that stores the information on an envelope */\n\nstruct EI;\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *ENV_ADDINFO_FUNCTION )( INOUT struct EI *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\t\t\t   IN_INT_Z const int value );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\n\t\tint ( *ENV_ADDINFOSTRING_FUNCTION )( INOUT struct EI *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_ENVINFO_PASSWORD, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PASSWORD ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\t\t\t\t\t IN_BUFFER( valueLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst void *value, \n\t\t\t\t\t\t\t\t\t\t\t IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int valueLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *ENV_CHECKMISSINGINFO_FUNCTION )( INOUT struct EI *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isFlush );\ntypedef CHECK_RETVAL \\\n\t\tBOOLEAN ( *ENV_CHECKALGO_FUNCTION )( IN_ALGO \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t\t\t\t\t\t\t IN_MODE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_MODE_TYPE cryptMode );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *ENV_PROCESSPREAMBLE_FUNCTION )( INOUT struct EI *envelopeInfoPtr );\ntypedef CHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *ENV_PROCESSPOSTAMBLE_FUNCTION )( INOUT struct EI *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tconst BOOLEAN isFlush );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *ENV_COPYTOENVELOPE_FUNCTION )( INOUT struct EI *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  IN_BUFFER_OPT( length ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst BYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t\t  IN_DATALENGTH_Z const int length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\n\t\tint ( *ENV_COPYFROMENVELOPE_FUNCTION )( INOUT struct EI *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tOUT_BUFFER( maxLength, *length ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tBYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_FLAGS_Z( ENVCOPY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int flags );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *ENV_PROCESSEXTRADATA_FUNCTION )( INOUT struct EI *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_BUFFER( length ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst void *buffer, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_DATALENGTH_Z const int length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *ENV_SYNCDEENVELOPEDATA_FUNCTION )( INOUT struct EI *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t  INOUT STREAM *stream );\n\ntypedef struct EI {\n\t/* Control and status information */\n\tCRYPT_FORMAT_TYPE type;\t\t\t/* Envelope type */\n\tCRYPT_CONTENT_TYPE contentType;\t/* Inner content type */\n\tACTION_TYPE usage;\t\t\t\t/* Usage (signing, encryption, etc) */\n\tint version;\t\t\t\t\t/* Protocol version/subtype */\n\tSAFE_FLAGS flags;\t\t\t\t/* Envelope information flags */\n\tSAFE_FLAGS dataFlags;\t\t\t/* Envelope data processing flags */\n\n\t/* The list of actions to perform on the data.  There are three sets of\n\t   actions, the preActions (key exchange), the main actions (encryption \n\t   or hashing), and the postActions (signing) */\n\tDATAPTR preActionList, actionList, postActionList;\n\n\t/* When prepending or appending header or trailer information to an\n\t   envelope we need to record the current position in the action list so\n\t   that we can continue later if we run out of room */\n\tDATAPTR lastAction;\n\n\t/* Several action groups produce information which is prepended or\n\t   appended to the data.  The following variables record the encoded size\n\t   of this information.  In some cases the size of the appended\n\t   information isn't known when the enveloping is started so we have to\n\t   use an indefinite-length encoding for the outermost wrapper, if this\n\t   is the case then we set the ENVDATA_HASINDEFTRAILER flag to indicate \n\t   that a definite-length encoding shouldn't be used even if the payload \n\t   size is known */\n\tint cryptActionSize;\t\t\t/* Size of key exchange actions */\n\tint signActionSize;\t\t\t\t/* Size of signatures */\n\tint extraDataSize;\t\t\t\t/* Size of any extra data */\n\n\t/* When de-enveloping we may have objects present that can't be used\n\t   until user-supplied de-enveloping information is added to the\n\t   envelope.  We store these in a linked list in memory until the\n\t   information needed to work with them is present.  We also store a\n\t   pointer to the current position in the list, which is used when\n\t   traversing the list */\n\tDATAPTR contentList, contentListCurrent;\n\n\t/* The public-key encryption/private-key decryption and signature-check\n\t   keysets that are used to look up any keys required during the \n\t   enveloping/de-enveloping process */\n\tCRYPT_KEYSET iDecryptionKeyset;\n\tCRYPT_KEYSET iEncryptionKeyset;\n\tCRYPT_KEYSET iSigCheckKeyset;\n\n\t/* When we're encrypting/decrypting the envelope payload, the one action \n\t   that we'll be performing constantly is encryption.  Similarly, when\n\t   we're signing/sig.checking, we'll be hashing the payload.  In order \n\t   to make this process more efficientm, we record the encryption and \n\t   hashing info here to save having to pull it out of the action list \n\t   whenever it's needed.\n\t   \n\t   The encryption context, of which there's only one, is stored here.\n\t   Note that since there is a second reference held in the action list, \n\t   there's no need to explicitly delete this when we destroy the \n\t   envelope object since it's already been destroyed when the action \n\t   list is destroyed.\n\n\t   For hashing, we may have multiple hash contexts active, so we still\n\t   use the action list for these.  However it's convenient to have \n\t   direct confirmation that we have to hash the payload data to save \n\t   having to check the action list each time, so we set the\n\t   ENVDATA_HASHACTIONSACTIVE flag to indicate that hashing is taking \n\t   place.  This is only set while the hashing is taking place, once \n\t   there's no more data to be hashed it's cleared to prevent out-of-band \n\t   data from being hashed as well */\n\tCRYPT_CONTEXT iCryptContext;\n\n\t/* Some types of key management/signature require additional certs.\n\t   For encryption, there may be originator certs present for use with\n\t   key agreement algorithms; for signing, there may be a signing-cert\n\t   meta-object present to contain the union of multiple sets of signing\n\t   certs if multiple signatures are present.  These are held in the \n\t   following certificate object */\n\tCRYPT_CERTIFICATE iExtraCertChain;\n\n\t/* The encryption/hashing/signature defaults for this envelope.  These\n\t   are recorded here when the envelope is created (so that a later \n\t   change of the default value won't affect the enveloping process) but \n\t   can be changed explicitly on a per-envelope basis by setting the \n\t   options just for the envelope rather than for all of cryptlib */\n\tCRYPT_ALGO_TYPE defaultHash;\t\t/* Default hash algorithm */\n\tCRYPT_ALGO_TYPE defaultAlgo;\t\t/* Default encryption algorithm */\n\tCRYPT_ALGO_TYPE defaultMAC;\t\t\t/* Default MAC algorithm */\n\n#ifdef USE_COMPRESSION\n\t/* zlib stream compression data structure used to hold the compression/\n\t   decompression state */\n\tz_stream zStream;\t\t\t\t/* zlib state variable */\n#endif /* USE_COMPRESSION */\n\n\t/* Buffer information */\n\tBUFFER( bufSize, bufPos ) \\\n\tBYTE *buffer;\t\t\t\t\t/* Data buffer */\n\tint bufSize;\t\t\t\t\t/* Total buffer size */\n\tint bufPos;\t\t\t\t\t\t/* Last data position in buffer */\n\n\t/* Auxiliary buffer used as a staging area for holding signature data \n\t   that may not currently fit into the main buffer.  These are generated \n\t   into the auxiliary buffer and then copied into the main buffer as \n\t   required */\n\tBUFFER_OPT( auxBufSize, auxBufPos ) \\\n\tBYTE *auxBuffer;\t\t\t\t/* Buffer for sig.data */\n\tint auxBufSize, auxBufPos;\t\t/* Current pos and total aux.buf.size */\n\n\t/* When the caller knows in advance how large the payload will be, they \n\t   can advise the enveloping code of this, which allows a more efficient \n\t   encoding of the data.  The following variable records the payload \n\t   size */\n\tlong payloadSize;\n\n\t/* The current state of header processing.  The cryptlib/CMS and PGP\n\t   processing states are kept separate (although they could actually be \n\t   merged into the same variable) because they are conceptually separate \n\t   and shouldn't really be treated as the same thing */\n\tENVELOPE_STATE state;\t\t\t/* Current state of processing */\n\tENV_STATE envState;\t\t\t\t/* Current state of env.non-data proc.*/\n\tDEENV_STATE deenvState;\t\t\t/* Current state of de-env.non-data proc.*/\n#ifdef USE_PGP\n\tPGP_DEENV_STATE pgpDeenvState;\t/* Current state of PGP de-env.n-d proc.*/\n#endif /* USE_PGP */\n\tlong hdrSetLength;\t\t\t\t/* Remaining bytes in SET OF EKeyInfo */\n\n\t/* When we pushe data into an envelope it may end up breaking the push \n\t   over an intermediate header.  This occurs if we're pushing indefinite-\n\t   length data and stop halfway through a tag, either an EOC or an OCTET \n\t   STRING segment (or its PGP equivalent):\n\n\t\t+-------+-----------+-----+---------+\n\t\t| Header|\tBody\t|00 00| Trailer |\n\t\t+-------+-----------+-----+---------+\n\t\t\t\t\t\t\t   ^\t\n\t\t\t\t\t\t\t   |\n\t\t\t\t\t\t\t bufPos\n\t\t\t\t\t\t\t   +-------+\n\t\t\t\t\t\t\t\t\t   v\n\t\t+-------+--------+----------+--------+----------+-----+---------+\n\t\t| Header|04 xx xx|\tBody\t|04 xx xx|\tBody\t|00 00|\tTrailer |\n\t\t+-------+--------+----------+--------+----------+-----+---------+\n\n\t   In this case we can't decode the intermediate header and have to\n\t   buffer the data somewhere until the next push.  We can't report the\n\t   remainder to the caller as un-consumed data because this may be an\n\t   implicit push, for example when we add a keying resource to an \n\t   encrypted envelope, which continues processing with previously-pushed \n\t   data when it initialises the cryptovariables from the data.  In this\n\t   case since no data is being pushed, there's no way to report that \n\t   some of the data was unconsumed.\n\t   \n\t   Because of this we have to buffer any partial information until the\n\t   next data push.  This can only occur when we break across a partial\n\t   header, so the amount of data to be buffered is minimal.\n\t   \n\t   (It also occurs extremely rarely since it requires indefinite-length \n\t   data and there's usually only a single byte location where this can \n\t   occur, this situation almost never occurs) */\n\tBUFFER( PARTIAL_BUFFER_SIZE, partialBufPos ) \\\n\tBYTE partialBuffer[ PARTIAL_BUFFER_SIZE + 8 ];\t/* Buffered partial header data */\n\tint partialBufPos;\n\n\t/* Some data formats place out-of-band data at the start of the payload\n\t   rather than putting it in the header, so we need to be able to peek\n\t   ahead into the processed (e.g. decrypted) data via a lookahead read \n\t   in order to determine what to do next.  The out-of-band (OOB) buffer \n\t   and associated variables take care of this.\n\t   \n\t   The OOB data-left variable keeps track of how many bytes of data \n\t   still need to be removed before we can return actual payload data to \n\t   the caller.  In some cases the amount of data can't be specified as a \n\t   simple byte count but involves format-specific events (e.g. the \n\t   presence of a flag or data count in the OOB data that indicates that \n\t   there's more data present), the OOB event-count variable records how \n\t   many of these events still need to be handled before we can return \n\t   data to the caller.\n\t   \n\t   Finally, some content types (e.g. compressed data) don't allow \n\t   lookahead reads, which are necessary in some cases to determine how \n\t   the payload needs to be handled.  To handle this we have to remember \n\t   the returned OOB data (if it's read via a lookahead read) so that we \n\t   can reinsert it into the output stream on the next read call */\n\tint oobDataLeft;\t\t\t\t/* Remaining out-of-band data in payload */\n\tint oobEventCount;\t\t\t\t/* No.events left to process */\n\tBUFFER( OOB_BUFFER_SIZE, oobBufSize ) \\\n\tBYTE oobBuffer[ OOB_BUFFER_SIZE + 8 ];\t/* Buffered OOB data */\n\tint oobBufSize;\n\n\t/* Information on the current OCTET STRING segment in the buffer during\n\t   the de-enveloping process.  We keep track of the segment start point \n\t   (the byte after the OCTET STRING tag), the segment data start point \n\t   (which may move when the segment is terminated if the length encoding \n\t   shrinks due to a short segment), and whether we've just completed a \n\t   segment (which we need to do before we can pop any data from the \n\t   envelope, this is tracked via the ENVDATA_SEGMENTCOMPLETE flag).  In \n\t   addition we track where the last completed segment ends, as the buffer \n\t   may contain one or more completed segments followed by an incomplete \n\t   segment, and any attempt to read into the incomplete segment will \n\t   require it to be completed first */\n\tint segmentStart;\t\t\t\t/* Segment len+data start point */\n\tint segmentDataStart;\t\t\t/* Segment data start point */\n\tint segmentDataEnd;\t\t\t\t/* End of completed data */\n\n\t/* The remaining data in the current OCTET STRING segment, explicitly \n\t   declared as a long since we may be processing data that came from a \n\t   32-bit machine on a 16-bit machine.  During enveloping this is used\n\t   to track the amount of data left from the user-declared payloadSize\n\t   that can still be added to the envelope.  During de-enveloping, it's \n\t   used to record how much data is left in the current segment */\n\tlong segmentSize;\t\t\t\t/* Remaining data in segment */\n\n\t/* Once the low-level segment-processing code sees the end-of-contents\n\t   octets for the payload, we need to notify the higher-level code that\n\t   anything that follows is out-of-band data that needs to be processed\n\t   at a higher level.  We do this by setting the ENVDATA_ENDOFCONTENTS\n\t   flag to record the fact that we've seen the payload EOC and have \n\t   moved to trailing out-of-band data.  Since the post-payload data\n\t   isn't directly retrievable by the user, we use the dataLeft variable \n\t   to keep track of how much of what's left in the envelope is payload \n\t   that can be copied out */\n\tint dataLeft;\n\n\t/* Block cipher buffer for leftover bytes.  This contains any bytes\n\t   remaining to be en/decrypted when the input data size isn't a\n\t   multiple of the cipher block size */\n\tBUFFER( CRYPT_MAX_IVSIZE, blockBufferPos ) \\\n\tBYTE blockBuffer[ CRYPT_MAX_IVSIZE + 8 ];/* Leftover byte buffer */\n\tint blockBufferPos;\t\t\t\t/* Position in buffer */\n\tint blockSize;\t\t\t\t\t/* Cipher block size */\n\tint blockSizeMask;\t\t\t\t/* Mask for blockSize-sized blocks */\n\n\t/* The overall envelope status.  Some error states (underflow/overflow\n\t   enveloping information errors, randomness errors, and a few others)\n\t   are recoverable whereas other states (bad data) aren't recoverable.\n\t   If we run into a nonrecoverable error, we remember the status here so\n\t   that any further attempts to work with the envelope will return this\n\t   status */\n\tint errorState;\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* Low-level error information */\n\tERROR_INFO errorInfo;\n\n\t/* Pointers to the enveloping/de-enveloping functions */\n\tFNPTR addInfoFunction, addInfoStringFunction, checkMissingInfoFunction;\n\tFNPTR checkAlgoFunction, processPreambleFunction, processPostambleFunction;\n\tFNPTR copyToEnvelopeFunction, copyFromEnvelopeFunction;\n\tFNPTR processExtraDataFunction, syncDeenvelopeDataFunction;\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the \n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\n\t/* The local memory pool used to allocate small data objects attached to \n\t   the envelope */\n\tMEMPOOL_STATE memPoolState;\n\n\t/* Variable-length storage for the type-specific data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} ENVELOPE_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEnveloping Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Envelope attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getEnvelopeAttribute( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getEnvelopeAttributeS( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setEnvelopeAttribute( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  IN_INT_Z const int value, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setEnvelopeAttributeS( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t   IN_LENGTH const int dataLength,\n\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\n\n\n/* Prototypes for envelope action management functions */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *CHECKACTION_FUNCTION )( const ACTION_LIST *actionListPtr,\n\t\t\t\t\t\t\t\t\t   IN_INT_Z const int intParam );\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckActionList( IN const ACTION_LIST *actionListPtr );\nCHECK_RETVAL_BOOL \\\nBOOLEAN moreActionsPossible( IN_OPT const ACTION_LIST *actionListPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t   IN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addActionEx( OUT_OPT_PTR_COND ACTION_LIST **newActionPtrPtr,\n\t\t\t\t INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t IN_ENUM( ACTIONLIST ) const ACTIONLIST_TYPE actionListType,\n\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint replaceAction( INOUT ACTION_LIST *actionListItem,\n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle );\nCHECK_RETVAL_ENUM( ACTION ) \\\nACTION_RESULT checkAction( IN_OPT const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t   IN_ENUM( ACTION ) const ACTION_TYPE actionType, \n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkActionIndirect( IN const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t IN CHECKACTION_FUNCTION checkActionFunction,\n\t\t\t\t\t\t IN_INT_Z const int intParam );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findPreAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( ACTION ) const ACTION_TYPE actionType );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findPostAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findLastAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findActionIndirect( const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t\t\t IN CHECKACTION_FUNCTION checkActionFunction,\n\t\t\t\t\t\t\t\t IN_INT_Z const int intParam );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteActionLists( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteUnusedActions( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkActions( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n\n/* Prototypes for content list management functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckContentList( IN const CONTENT_LIST *contentListPtr );\nCHECK_RETVAL_BOOL \\\nBOOLEAN moreContentItemsPossible( IN_OPT const CONTENT_LIST *contentListPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createContentListItem( OUT_BUFFER_ALLOC_OPT( sizeof( CONTENT_LIST ) ) \\\n\t\t\t\t\t\t\t\tCONTENT_LIST **newContentListItemPtrPtr,\n\t\t\t\t\t\t   INOUT MEMPOOL_STATE memPoolState,\n\t\t\t\t\t\t   IN_ENUM( CONTENT ) const CONTENT_TYPE type,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t   IN_BUFFER_OPT( objectSize ) const void *object, \n\t\t\t\t\t\t   IN_LENGTH_Z const int objectSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint appendContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   INOUT CONTENT_LIST *contentListItem );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid deleteContentListItem( INOUT MEMPOOL_STATE memPoolState,\n\t\t\t\t\t\t\tINOUT CONTENT_LIST *contentListItem );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteContentList( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n\n/* Prototypes for misc.management functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckEnvelope( const ENVELOPE_INFO *envelopeInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addKeysetInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t   IN_RANGE( CRYPT_ENVINFO_KEYSET_SIGCHECK, \\\n\t\t\t\t\t\t\t CRYPT_ENVINFO_KEYSET_DECRYPT ) \\\n\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE keysetFunction,\n\t\t\t\t   IN_HANDLE const CRYPT_KEYSET keyset );\nCHECK_RETVAL_BOOL \\\nBOOLEAN cmsCheckAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t  IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode );\nCHECK_RETVAL_BOOL \\\nBOOLEAN pgpCheckAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t  IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode );\n\n/* Prepare the envelope for data en/decryption */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initEnvelopeEncryption( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\tIN_ALGO_OPT const CRYPT_ALGO_TYPE algorithm, \n\t\t\t\t\t\t\tIN_MODE_OPT const CRYPT_MODE_TYPE mode,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( ivLength ) const BYTE *iv, \n\t\t\t\t\t\t\tIN_LENGTH_IV_Z const int ivLength,\n\t\t\t\t\t\t\tconst BOOLEAN copyContext );\n\n/* Prototypes for enveloping internal functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint cmsPreEnvelopeEncrypt( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint cmsPreEnvelopeSign( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashEnvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_Z const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint cmsInitSigParams( const ACTION_LIST *actionListPtr,\n\t\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t  IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t  OUT SIGPARAMS *sigParams );\n\n/* Prototypes for envelope mapping functions */\n\n#ifdef USE_CMS\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void initCMSEnveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void initCMSDeenveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n#else\n  #define initCMSEnveloping( envelopeInfoPtr )\n  #define initCMSDeenveloping( envelopeInfoPtr )\n#endif /* USE_CMS */\n#ifdef USE_PGP\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void initPGPEnveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void initPGPDeenveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n#else\n  #define initPGPEnveloping( envelopeInfoPtr )\n  #define initPGPDeenveloping( envelopeInfoPtr )\n#endif /* USE_PGP */\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initEnvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initEnvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initDeenvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initDenvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr );\n\n#endif /* _ENV_DEFINED */\n"
  },
  {
    "path": "deps/cl345/envelope/pgp_denv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t cryptlib PGP De-enveloping Routines\t\t\t\t\t*\n*\t\t\t\t\t Copyright Peter Gutmann 1996-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"pgp_rw.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGP\n\n/* The maximum number of data items that we can process in the header or \n   trailer.  This isn't an absolute limit but more a sanity check in invalid\n   headers/trailers */\n\n#define MAX_DATA_ITEMS\t\t16\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckEnvPGPDenv( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckEnvelope( envelopeInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvPGPDenv: Envelope check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that general envelope state is in order */\n\tif( envelopeInfoPtr->type != CRYPT_FORMAT_PGP || \\\n\t\t!TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvPGPDenv: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( envelopeInfoPtr->pgpDeenvState, PGP_DEENVSTATE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvPGPDenv: State\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the out-of-band buffer state is OK.  Most of this has\n\t   been checked by the general envelope check, the oobDataLeft value is \n\t   the general size of a data packet header plus the maximum possible \n\t   length for the variable-length filename portion */\n\tif( envelopeInfoPtr->oobDataLeft < 0 || \\\n\t\tenvelopeInfoPtr->oobDataLeft >= 32 + 256 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckEnvPGPDenv: OOB data\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Get information on a PGP data packet.  If the lengthType value is present \n   then an indefinite length (i.e. partial packet lengths) is permitted, \n   otherwise it isn't */\n\ntypedef enum {\n\tPGP_LENGTH_NONE,\t\t/* No length type */\n\tPGP_LENGTH_NORMAL,\t\t/* Definite length */\n\tPGP_LENGTH_INDEFINITE,\t/* Indefinite length */\n\tPGP_LENGTH_UNKNOWN,\t\t/* \"Until EOF\" length */\n\tPGP_LENGTH_LAST\t\t\t/* Last valid length type */\n\t} PGP_LENGTH_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int getPacketInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  OUT_ENUM_OPT( PGP_PACKET ) \\\n\t\t\t\t\t\t\t\tPGP_PACKET_TYPE *packetType, \n\t\t\t\t\t\t  OUT_LENGTH_Z long *length, \n\t\t\t\t\t\t  OUT_OPT_ENUM( PGP_LENGTH ) \\\n\t\t\t\t\t\t\t\tPGP_LENGTH_TYPE *lengthType,\n\t\t\t\t\t\t  IN_LENGTH_SHORT int minPacketSize,\n\t\t\t\t\t\t  const BOOLEAN checkPacketDataPresent )\n\t{\n\tint ctb, version, type, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( packetType, sizeof( PGP_PACKET_TYPE ) ) );\n\tassert( isWritePtr( length, sizeof( long ) ) );\n\tassert( lengthType == NULL || \\\n\t\t\tisWritePtr( lengthType, sizeof( PGP_LENGTH_TYPE ) ) );\n\n\tENSURES( isShortIntegerRangeNZ( minPacketSize ) );\n\tREQUIRES( checkPacketDataPresent == TRUE || checkPacketDataPresent == FALSE );\n\n\t/* Clear return values */\n\t*packetType = PGP_PACKET_NONE;\n\t*length = 0;\n\tif( lengthType != NULL )\n\t\t*lengthType = PGP_LENGTH_NORMAL;\n\n\t/* Read the packet header and extract information from the CTB.  The \n\t   assignment of version numbers is a bit complicated since it's \n\t   possible to use PGP 2.x packet headers to wrap up OpenPGP packets, \n\t   and in fact a number of apps mix version numbers.  We treat the \n\t   version to report as the highest one that we find */\n\tif( lengthType != NULL )\n\t\tstatus = pgpReadPacketHeaderI( stream, &ctb, length, minPacketSize );\n\telse\n\t\t{\n\t\tstatus = pgpReadPacketHeader( stream, &ctb, length, minPacketSize,\n\t\t\t\t\t\t\t\t\t  MAX_INTLENGTH - 1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\tENSURES( lengthType != NULL );\n\n\t\t/* Remember that the packet uses an indefinite-length encoding */\n\t\t*lengthType = PGP_LENGTH_INDEFINITE;\n\t\t}\n\n\t/* Extract the packet type */\n\tversion = pgpGetPacketVersion( ctb );\n\tif( version > envelopeInfoPtr->version )\n\t\tenvelopeInfoPtr->version = version;\n\ttype = pgpGetPacketType( ctb );\n\tif( type <= PGP_PACKET_NONE || type >= PGP_PACKET_LAST )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*packetType = type;\n\n\t/* Deal with implicit-length compressed data.  This is an oddball \n\t   exception to standard PGP length encodings in that it's neither\n\t   definite nor indefinite-length but merely \"until you run out of\n\t   data\", so we let the caller know this */\n\tif( ctb == PGP_CTB_COMPRESSED )\n\t\t{\n\t\t/* If we're not expecting to read implicit-length data then \n\t\t   encountering it is an error */\n\t\tif( lengthType == NULL )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t*lengthType = PGP_LENGTH_UNKNOWN;\n\t\t}\n\n\t/* Check that all of the packet data is present in the stream if \n\t   required */\n\tif( checkPacketDataPresent && sMemDataLeft( stream ) < *length )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Key Exchange/Signature Packets\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add information about an object to an envelope's content information list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   INOUT_OPT STREAM *stream,\n\t\t\t\t\t\t\t   const BOOLEAN isContinuedSignature )\n\t{\n\tQUERY_INFO queryInfo;\n\tconst CONTENT_LIST *contentListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tCONTENT_LIST *contentListItem;\n\tvoid *object = NULL;\n\tint objectSize = 0, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( ( stream == NULL && actionListPtr == NULL && \\\n\t\t\t  contentListPtr == NULL ) || \\\n\t\t\tisWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( ( stream == NULL && actionListPtr == NULL && \\\n\t\t\t\tcontentListPtr == NULL ) || \\\n\t\t\t  ( stream != NULL ) );\n\tREQUIRES( isContinuedSignature == TRUE || isContinuedSignature == FALSE );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentList ) );\n\n\t/* Make sure that there's room to add another list item */\n\tif( !moreContentItemsPossible( contentListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* PGP 2.x password-encrypted data is detected by the absence of any\n\t   other keying object rather than by finding a concrete object type so\n\t   if we're passed a null stream we add a password pseudo-object */\n\tif( stream == NULL )\n\t\t{\n\t\tCONTENT_ENCR_INFO *encrInfo;\n\n\t\tstatus = createContentListItem( &contentListItem, \n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->memPoolState,\n\t\t\t\t\t\t\t\t\t\tCONTENT_CRYPT, CRYPT_FORMAT_PGP, \n\t\t\t\t\t\t\t\t\t\tNULL, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tencrInfo = &contentListItem->clEncrInfo;\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_PASSWORD;\n\t\tencrInfo->cryptAlgo = CRYPT_ALGO_IDEA;\n\t\tencrInfo->cryptMode = CRYPT_MODE_CFB;\n\t\tencrInfo->keySetupAlgo = CRYPT_ALGO_MD5;\n\t\tstatus = appendContentListItem( envelopeInfoPtr, contentListItem );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"addContentListItem\", contentListItem );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Find the size of the object, allocate a buffer for it if necessary,\n\t   and copy it across.  This call verifies that all of the object data \n\t   is present in the stream so in theory we don't have to check the \n\t   following reads, but we check them anyway just to be sure */\n\tstatus = queryPgpObject( stream, &queryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( queryInfo.type == CRYPT_OBJECT_SIGNATURE && \\\n\t\tqueryInfo.dataStart <= 0 )\n\t\t{\n\t\tENSURES( !isContinuedSignature );\n\n\t\t/* It's a one-pass signature packet, the signature information \n\t\t   follows in another packet that will be added later */\n\t\tENSURES( isIntegerRangeNZ( queryInfo.size ) );\n\t\tstatus = sSkip( stream, ( int ) queryInfo.size, \n\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tENSURES( isIntegerRange( queryInfo.size ) );\n\t\tobjectSize = ( int ) queryInfo.size;\n\t\tREQUIRES( rangeCheck( objectSize, 1, MAX_INTLENGTH ) );\n\t\tif( ( object = clAlloc( \"addContentListItem\", \\\n\t\t\t\t\t\t\t\tobjectSize ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tstatus = sread( stream, object, objectSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"addContentListItem\", object );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* If it's the rest of the signature data from a one-pass signature,\n\t   locate the first half of the signature info and complete the\n\t   information.  In theory this could get ugly because there could be\n\t   multiple one-pass signature packets present but PGP handles multiple \n\t   signatures by nesting them so this isn't a problem */\n\tif( isContinuedSignature )\n\t\t{\n\t\tint LOOP_ITERATOR;\n\t\t\n\t\tLOOP_MED( contentListItem = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t\t  contentListItem != NULL && \\\n\t\t\t\t\tcontentListItem->envInfo != CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t  contentListItem = DATAPTR_GET( contentListItem->next ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( contentListItem != NULL );\n\t\tENSURES( sanityCheckContentList( contentListItem ) );\n\t\tENSURES( DATAPTR_ISNULL( contentListItem->object ) && \\\n\t\t\t\t contentListItem->objectSize == 0 );\n\n\t\t/* Consistency check, make sure that the hash algorithm and key ID \n\t\t   that we've been working with match what's in the signature */\n\t\tif( contentListItem->clSigInfo.hashAlgo != queryInfo.hashAlgo || \\\n\t\t\tcontentListItem->keyIDsize != queryInfo.keyIDlength || \\\n\t\t\tmemcmp( contentListItem->keyID, queryInfo.keyID, \n\t\t\t\t\tqueryInfo.keyIDlength ) )\n\t\t\t{\n\t\t\tclFree( \"addContentListItem\", object );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\n\t\t/* We've got the right content list entry, point it to the newly-\n\t\t   acquired signature data */\n\t\tDATAPTR_SET( contentListItem->object, object );\n\t\tcontentListItem->objectSize = objectSize;\n\t\t}\n\telse\n\t\t{\n\t\t/* Allocate memory for the new content list item and copy information\n\t\t   on the item across */\n\t\tstatus = createContentListItem( &contentListItem, \n\t\t\t\t\t\t\tenvelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t( queryInfo.type == CRYPT_OBJECT_SIGNATURE ) ? \\\n\t\t\t\t\t\t\t\tCONTENT_SIGNATURE : CONTENT_CRYPT, \n\t\t\t\t\t\t\tCRYPT_FORMAT_PGP, object, objectSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( object != NULL )\n\t\t\t\tclFree( \"addContentListItem\", object );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tif( queryInfo.type == CRYPT_OBJECT_PKCENCRYPTED_KEY )\n\t\t{\n\t\tCONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;\n\n\t\t/* Remember details of the enveloping info that we require to \n\t\t   continue */\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_PRIVATEKEY;\n\t\tencrInfo->cryptAlgo = queryInfo.cryptAlgo;\n\t\tREQUIRES( rangeCheck( queryInfo.keyIDlength, 1,\t\n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( contentListItem->keyID, queryInfo.keyID, \n\t\t\t\tqueryInfo.keyIDlength );\n\t\tcontentListItem->keyIDsize = queryInfo.keyIDlength;\n\t\t}\n\tif( queryInfo.type == CRYPT_OBJECT_SIGNATURE )\n\t\t{\n\t\tCONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;\n\t\tconst BYTE *objectPtr = DATAPTR_GET( contentListItem->object );\n\n\t\t/* OpenPGP signed data has a packet with signature data at the \n\t\t   start and then another packet with more data at the end, so we\n\t\t   can't guarantee the presence of object data unless it's the \n\t\t   second of the two */\n\t\tENSURES( objectPtr != NULL || \\\n\t\t\t\t ( queryInfo.iAndSStart == 0 && \\\n\t\t\t\t   queryInfo.attributeStart == 0 && \\\n\t\t\t\t   queryInfo.unauthAttributeStart == 0 ) );\n\n\t\t/* Remember details of the enveloping info that we require to \n\t\t   continue */\n\t\tcontentListItem->envInfo = CRYPT_ENVINFO_SIGNATURE;\n\t\tsigInfo->hashAlgo = queryInfo.hashAlgo;\n\t\tREQUIRES( rangeCheck( queryInfo.keyIDlength, 1,\t\n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( contentListItem->keyID, queryInfo.keyID, \n\t\t\t\tqueryInfo.keyIDlength );\n\t\tcontentListItem->keyIDsize = queryInfo.keyIDlength;\n\t\tif( queryInfo.iAndSStart > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( queryInfo.iAndSStart, \n\t\t\t\t\t\t\t\t   queryInfo.iAndSLength, objectSize ) );\n\t\t\tcontentListItem->issuerAndSerialNumber = objectPtr + queryInfo.iAndSStart;\n\t\t\tcontentListItem->issuerAndSerialNumberSize = queryInfo.iAndSLength;\n\t\t\t}\n\t\tif( queryInfo.attributeStart > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( queryInfo.attributeStart, \n\t\t\t\t\t\t\t\t   queryInfo.attributeLength, objectSize ) );\n\t\t\tsigInfo->extraData = objectPtr + queryInfo.attributeStart;\n\t\t\tsigInfo->extraDataLength = queryInfo.attributeLength;\n\t\t\t}\n\t\tif( queryInfo.unauthAttributeStart > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( queryInfo.unauthAttributeStart, \n\t\t\t\t\t\t\t\t   queryInfo.unauthAttributeLength, objectSize ) );\n\t\t\tsigInfo->extraData2 = objectPtr + queryInfo.unauthAttributeStart;\n\t\t\tsigInfo->extraData2Length = queryInfo.unauthAttributeLength;\n\t\t\t}\n\t\t}\n\tif( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY )\n\t\t{\n\t\tCONTENT_ENCR_INFO *encrInfo = &contentListItem->clEncrInfo;\n\n\t\t/* Remember details of the enveloping info that we require to \n\t\t   continue */\n\t\tif( queryInfo.keySetupAlgo != CRYPT_ALGO_NONE )\n\t\t\t{\n\t\t\t/* In theory PGP allows three different types of password\n\t\t\t   processing, a straight hash of the password, a salted hash of\n\t\t\t   the password, or a salted iterated hash.  Only the last one\n\t\t\t   makes any sense, although no known implementations generate \n\t\t\t   the first two we can in theory create at least the second \n\t\t\t   using GPG with the --s2k-mode argument so we allow that, but\n\t\t\t   not the unsalted hash */\n\t\t\tif( queryInfo.saltLength <= 0 )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Insecure S2K type 0 encountered\" ));\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tcontentListItem->envInfo = CRYPT_ENVINFO_PASSWORD;\n\t\t\tencrInfo->keySetupAlgo = queryInfo.keySetupAlgo;\n\t\t\tencrInfo->keySetupAlgoParam = queryInfo.keySetupAlgoParam;\n\t\t\tencrInfo->keySetupIterations = queryInfo.keySetupIterations;\n\t\t\tREQUIRES( rangeCheck( queryInfo.saltLength, 1, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_IVSIZE ) );\n\t\t\tmemcpy( encrInfo->saltOrIV, queryInfo.salt, \n\t\t\t\t\tqueryInfo.saltLength );\n\t\t\tencrInfo->saltOrIVsize = queryInfo.saltLength;\n\t\t\t}\n\t\telse\n\t\t\tcontentListItem->envInfo = CRYPT_ENVINFO_KEY;\n\t\tencrInfo->cryptAlgo = queryInfo.cryptAlgo;\n\t\tencrInfo->cryptMode = CRYPT_MODE_CFB;\n\t\t}\n\tif( queryInfo.dataStart > 0 )\n\t\t{\n\t\tconst BYTE *objectPtr = DATAPTR_GET( contentListItem->object );\n\n\t\tREQUIRES( DATAPTR_ISSET( contentListItem->object ) );\n\n\t\tREQUIRES( boundsCheck( queryInfo.dataStart, queryInfo.dataLength, \n\t\t\t\t\t\t\t   objectSize ) );\n\t\tcontentListItem->payload = objectPtr + queryInfo.dataStart;\n\t\tcontentListItem->payloadSize = queryInfo.dataLength;\n\t\t}\n\tif( queryInfo.version > envelopeInfoPtr->version )\n\t\tenvelopeInfoPtr->version = queryInfo.version;\n\n\t/* If we're completing the read of the data in a one-pass signature\n\t   packet, we're done */\n\tif( isContinuedSignature )\n\t\t{\n\t\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's signed data, create a hash action to process it.  Because PGP \n\t   only applies one level of signing per packet nesting level we don't \n\t   have to worry that this will add redundant hash actions as there'll \n\t   only ever be one */\n\tif( queryInfo.type == CRYPT_OBJECT_SIGNATURE )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tREQUIRES( moreActionsPossible( actionListPtr ) );\n\n\t\t/* Append a new hash action to the action list */\n\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\tcontentListItem->clSigInfo.hashAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdeleteContentListItem( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t\t   contentListItem );\n\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = addAction( envelopeInfoPtr, ACTION_HASH,\n\t\t\t\t\t\t\tcreateInfo.cryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tdeleteContentListItem( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t\t   contentListItem );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tstatus = appendContentListItem( envelopeInfoPtr, contentListItem );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdeleteContentListItem( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t   contentListItem );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckContentList( contentListItem ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHeader Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the header of a packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processPacketHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT_ENUM( PGP_DEENVSTATE ) \\\n\t\t\t\t\t\t\t\t\tPGP_DEENV_STATE *state,\n\t\t\t\t\t\t\t\tconst BOOLEAN checkState )\n\t{\n\tconst int streamPos = stell( stream );\n\tPGP_PACKET_TYPE packetType;\n\tPGP_LENGTH_TYPE lengthType;\n\tlong packetLength;\n\tint value, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( state, sizeof( PGP_DEENV_STATE ) ) );\n\n\tREQUIRES( checkState == TRUE || checkState == FALSE );\n\tREQUIRES( ( checkState && *state == PGP_DEENVSTATE_ENCR_HDR ) || \\\n\t\t\t  ( !checkState ) );\n\tREQUIRES( streamPos >= 0 && streamPos < MAX_BUFFER_SIZE );\n\n\t/* Read the PGP packet type and figure out what we've got.  If we're at \n\t   the start of the data then we allow noise packets like \n\t   PGP_PACKET_MARKER (with a length of 3), otherwise we only allow \n\t   standard packets */\n\tstatus = getPacketInfo( stream, envelopeInfoPtr, &packetType, \n\t\t\t\t\t\t\t&packetLength, &lengthType,\n\t\t\t\t\t\t\t( *state == PGP_DEENVSTATE_NONE ) ? 3 : 8, \n\t\t\t\t\t\t\tFALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Invalid PGP packet header\" ) );\n\t\t}\n\n\t/* This is a general-purpose function that can process all packet types, \n\t   however in some cases when it's called it should only allow certain\n\t   types (see the state machine diagram at the start of \n\t   processPreamble()).  If the checkState flag is set then we only allow\n\t   the packet types permitted by the state machine rather than accepting\n\t   any packet type */\n\tif( checkState )\n\t\t{\n\t\tENSURES( *state == PGP_DEENVSTATE_ENCR_HDR );\n\n\t\t/* We're processing encryption metadata, the only valid packet types\n\t\t   are further metadata (encrypted-key) packets, or the encrypted\n\t\t   data that follows them */\n\t\tif( ( packetType != PGP_PACKET_SKE ) && \\\n\t\t\t( packetType != PGP_PACKET_PKE ) && \\\n\t\t\t( packetType != PGP_PACKET_ENCR ) && \\\n\t\t\t( packetType != PGP_PACKET_ENCR_MDC ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Expected encrypted-key or encrypted-data packet but \"\n\t\t\t\t\t  \" got packet type %d\", packetType ) );\n\t\t\t}\n\t\t}\n\tif( packetType == PGP_PACKET_MARKER && *state != PGP_DEENVSTATE_NONE )\n\t\t{\n\t\t/* Marker packets are only valid at the start of a message.  This \n\t\t   check is somewhat pointless, but can occur if we hit corrupted\n\t\t   data */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Encountered obsolete PGP 5 marker packet while \"\n\t\t\t\t  \"processing message data\" ) );\n\t\t}\n\tif( lengthType == PGP_LENGTH_INDEFINITE )\n\t\t{\n\t\t/* Only packets containing data payloads can have indefinite \n\t\t   lengths */\n\t\tif( packetType != PGP_PACKET_DATA && \\\n\t\t\tpacketType != PGP_PACKET_ENCR_MDC && \\\n\t\t\tpacketType != PGP_PACKET_ENCR )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Encountered PGP packet type %d with indefinite \"\n\t\t\t\t\t  \"length\", packetType ) );\n\t\t\t}\n\n\t\t/* Remember that the packet uses an indefinite-length encoding */\n\t\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT );\n\t\t}\n\n\t/* Process as much of the header as we can and move on to the next state.  \n\t   Since PGP uses sequential discrete packets, if we encounter any of \n\t   the non-payload packet types we stay in the initial \"none\" state \n\t   because we don't know what's next */\n\tswitch( packetType )\n\t\t{\n\t\tcase PGP_PACKET_DATA:\n\t\t\t{\n\t\t\tlong payloadSize;\n\t\t\tint length;\n\n\t\t\t/* Skip the content-type, filename, and date */\n\t\t\tsSkip( stream, 1, 1 );\n\t\t\tstatus = length = sgetc( stream );\n\t\t\tif( !cryptStatusError( status ) )\n\t\t\t\tstatus = sSkip( stream, length + 4, MAX_INTLENGTH_SHORT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Invalid PGP data packet start\" ) );\n\t\t\t\t}\n\n\t\t\t/* Remember that this is a pure data packet, record the content \n\t\t\t   length, and move on to the payload */\n\t\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;\n\t\t\tpayloadSize = packetLength - ( 1 + 1 + length + 4 );\n\t\t\tif( !isIntegerRangeNZ( payloadSize ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tenvelopeInfoPtr->payloadSize = payloadSize;\n\t\t\t*state = PGP_DEENVSTATE_DATA;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase PGP_PACKET_COPR:\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tenvelopeInfoPtr->usage = ACTION_COMPRESS;\n#ifdef USE_COMPRESSION\n\t\t\tvalue = sgetc( stream );\n\t\t\tif( cryptStatusError( value ) )\n\t\t\t\treturn( value );\n\t\t\tswitch( value )\n\t\t\t\t{\n\t\t\t\tcase PGP_ALGO_ZIP:\n\t\t\t\t\t/* PGP 2.x has a funny compression level based on DOS \n\t\t\t\t\t   memory limits (13-bit windows) and no zlib header \n\t\t\t\t\t   (because it uses very old InfoZIP code).  Setting the \n\t\t\t\t\t   windowSize to a negative value has the undocumented \n\t\t\t\t\t   effect of not reading zlib headers */\n\t\t\t\t\tif( inflateInit2( &envelopeInfoPtr->zStream, -13 ) != Z_OK )\n\t\t\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase PGP_ALGO_ZLIB:\n\t\t\t\t\t/* Standard zlib compression */\n\t\t\t\t\tif( inflateInit( &envelopeInfoPtr->zStream ) != Z_OK )\n\t\t\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t\t}\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED );\n\t\t\tif( lengthType != PGP_LENGTH_UNKNOWN )\n\t\t\t\t{\n\t\t\t\tconst long payloadSize = packetLength - 1;\n\n\t\t\t\t/* All known implementations use the PGP 2.x \"keep going \n\t\t\t\t   until you run out of data\" non-length encoding that's \n\t\t\t\t   neither a definite- nor an indefinite length, but it's \n\t\t\t\t   possible that something somewhere will use a proper \n\t\t\t\t   definite length so we accomodate this here */\n\t\t\t\tif( !isIntegerRangeNZ( payloadSize ) )\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\tenvelopeInfoPtr->payloadSize = payloadSize;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Remember that we have no length information available for \n\t\t\t\t   the payload */\n\t\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t  ENVDATA_FLAG_NOLENGTHINFO );\n\t\t\t\t}\n\t\t\t*state = PGP_DEENVSTATE_DATA;\n\t\t\tbreak;\n#else\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#endif /* USE_COMPRESSION */\n\n\t\tcase PGP_PACKET_SKE:\n\t\tcase PGP_PACKET_PKE:\n\t\t\t/* Read the SKE/PKE packet */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\tsseek( stream, streamPos );\t/* Reset to start of packet */\n\t\t\tstatus = addContentListItem( envelopeInfoPtr, stream, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Invalid PGP %s packet\", \n\t\t\t\t\t\t  ( packetType == PGP_PACKET_SKE ) ? \"SKE\" : \"PKE\" ) );\n\t\t\t\t}\n\t\t\t*state = PGP_DEENVSTATE_ENCR_HDR;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_SIGNATURE:\n\t\tcase PGP_PACKET_SIGNATURE_ONEPASS:\n\t\t\t{\n\t\t\tconst ACTION_LIST *actionListPtr;\n\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\t\t\tENSURES( actionListPtr == NULL || \\\n\t\t\t\t\t sanityCheckActionList( actionListPtr ) );\n\n\t\t\t/* Try and guess whether this is a standalone signature.  This \n\t\t\t   is rather difficult since unlike S/MIME there's no way to \n\t\t\t   tell whether a PGP signature packet is part of other data or \n\t\t\t   a standalone item.  The best that we can do is assume that if \n\t\t\t   the caller added a hash action and we find a signature then \n\t\t\t   it's a detached signature.  Unfortunately there's no way to \n\t\t\t   tell whether a signature packet with no user-supplied hash is \n\t\t\t   a standalone signature or the start of further signed data so \n\t\t\t   we can't handle detached signatures where the user doesn't \n\t\t\t   supply the hash */\n\t\t\tif( envelopeInfoPtr->usage == ACTION_SIGN && \\\n\t\t\t\tactionListPtr != NULL && \\\n\t\t\t\tactionListPtr->action == ACTION_HASH )\n\t\t\t\t{\n\t\t\t\t/* We can't have a detached signature packet as a one-pass \n\t\t\t\t   signature */\n\t\t\t\tif( packetType == PGP_PACKET_SIGNATURE_ONEPASS )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t\t  \"PGP detached signature can't be a one-pass \"\n\t\t\t\t\t\t\t  \"signature packet\" ) );\n\t\t\t\t\t}\n\t\t\t\tSET_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t  ENVELOPE_FLAG_DETACHED_SIG );\n\t\t\t\t}\n\n\t\t\t/* Read the signature/signature information packet.  We allow \n\t\t\t   the usage to be set already if we find a signature packet \n\t\t\t   since it could have been preceded by a one-pass signature \n\t\t\t   packet or be a detached signature */\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\t!( packetType == PGP_PACKET_SIGNATURE && \\\n\t\t\t\t   envelopeInfoPtr->usage == ACTION_SIGN ) )\n\t\t\t\t{\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tenvelopeInfoPtr->usage = ACTION_SIGN;\n\t\t\tsseek( stream, streamPos );\t/* Reset to start of packet */\n\t\t\tstatus = addContentListItem( envelopeInfoPtr, stream, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Invalid PGP %ssignature packet\",\n\t\t\t\t\t\t  ( packetType == PGP_PACKET_SIGNATURE_ONEPASS ) ? \\\n\t\t\t\t\t\t\t\"one-pass \" : \"\" ) );\n\t\t\t\t}\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t\t\t{\n\t\t\t\t/* If it's a one-pass signature there's no payload present \n\t\t\t\t   so we can go straight to the postdata state */\n\t\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\t\t\tenvelopeInfoPtr->payloadSize = 0;\n\t\t\t\t*state = PGP_DEENVSTATE_DONE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t*state = PGP_DEENVSTATE_DATA;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase PGP_PACKET_ENCR_MDC:\n\t\t\t/* The encrypted-data-with-MDC packet is preceded by a version \n\t\t\t   number */\n\t\t\tstatus = value = sgetc( stream );\n\t\t\tif( !cryptStatusError( status ) && value != 1 )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tif( !cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Adjust the length for the version number and make sure \n\t\t\t\t   that what's left is valid.  In theory this check isn't\n\t\t\t\t   necessary because getPacketInfo() has enforced a minimum\n\t\t\t\t   length, but we do it anyway just to be sure */\n\t\t\t\tpacketLength--;\n\t\t\t\tif( !isIntegerRange( packetLength ) )\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Invalid MDC packet header\" ) );\n\t\t\t\t}\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC );\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase PGP_PACKET_ENCR:\n\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE && \\\n\t\t\t\tenvelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tenvelopeInfoPtr->payloadSize = packetLength;\n\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\t*state = ( packetType == PGP_PACKET_ENCR_MDC ) ? \\\n\t\t\t\t\t PGP_DEENVSTATE_ENCR_MDC : PGP_DEENVSTATE_ENCR;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_MARKER:\n\t\t\t/* Obsolete marker packet used to indicate that a message uses \n\t\t\t   features not present in PGP 2.6.x (via its version number), so\n\t\t\t   that any attempt to process it with a 2.x version of PGP \n\t\t\t   produces a message that a newer version is required.  This is \n\t\t\t   just noise, so we skip it */\n\t\t\tif( !isShortIntegerRangeNZ( packetLength ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Invalid PGP marker packet\" ) );\n\t\t\t\t}\n\t\t\treturn( sSkip( stream, packetLength, MAX_INTLENGTH_SHORT ) );\n\t\t\n\t\tdefault:\n\t\t\t/* Unrecognised/invalid packet type */\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Unrecognised PGP packet type %d\", packetType ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Adjust the envelope data size information based on what we've found in \n   any nested packets that we've dug down to through \n   processPacketDataHeader() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int adjustDataInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   const STREAM *stream,\n\t\t\t\t\t\t   IN_LENGTH_OPT const long packetLength )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( packetLength == CRYPT_UNUSED || \\\n\t\t\t  isIntegerRange( packetLength ) );\n\n\t/* If it's a definite-length packet, use the overall packet size.  This \n\t   also skips any MDC packets that may be attached to the end of the \n\t   plaintext */\n\tif( packetLength != CRYPT_UNUSED )\n\t\t{\n\t\tenvelopeInfoPtr->segmentSize = stell( stream ) + packetLength;\n\n\t\t/* If we're using the definite-length encoding (which is the default \n\t\t   for PGP) then the overall payload size is equal to the segment \n\t\t   size */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT ) )\n\t\t\tenvelopeInfoPtr->payloadSize = envelopeInfoPtr->segmentSize;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's not a definite-length packet then it can only be compressed \n\t   data, for which 'ENSURES( packetType == PGP_PACKET_COPR )' */\n\tENSURES( envelopeInfoPtr->payloadSize != CRYPT_UNUSED );\n\n\t/* It's an arbitrary-length compressed data packet, use the length that \n\t   we got earlier from the outer packet */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_ENDOFCONTENTS ) )\n\t\t{\n\t\t/* This is a should-never-occur situation, it's unclear what exactly\n\t\t   we should be doing at this point */\n\t\tDEBUG_DIAG(( \"Found EOC for unknown-length compressed data\" ));\n\t\tassert( DEBUG_WARN );\n\t\t\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tenvelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;\n\n\t/* If we've reached the end of the data (i.e. the entire current segment \n\t   is contained within the data present in the buffer), remember that \n\t   what's left still needs to be processed (e.g. hashed in the case of \n\t   signed data) on the way out */\n\tif( envelopeInfoPtr->segmentSize <= envelopeInfoPtr->bufPos )\n\t\t{\n\t\t/* If the outer packet has an MDC at the end then we need to adjust \n\t\t   the data size to skip the MDC data */\n\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t   ENVDATA_FLAG_HASATTACHEDOOB ) ) \n\t\t\t{\n\t\t\tif( envelopeInfoPtr->segmentSize < PGP_MDC_PACKET_SIZE )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"MDC packet is missing or incomplete, expected \"\n\t\t\t\t\t\t  \"%d bytes but got %ld\", PGP_MDC_PACKET_SIZE, \n\t\t\t\t\t\t  envelopeInfoPtr->segmentSize ) );\n\t\t\t\t}\n\t\t\tenvelopeInfoPtr->segmentSize -= PGP_MDC_PACKET_SIZE;\n\t\t\t}\n\t\tenvelopeInfoPtr->dataLeft = envelopeInfoPtr->segmentSize;\n\t\tenvelopeInfoPtr->segmentSize = 0;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* PGP doesn't provide any indication of what the content of the packet's \n   encrypted payload is so we have to burrow down into the encrypted data to \n   see whether the payload needs any further processing.  To do this we look \n   ahead into the data to see whether we need to strip the header (for a \n   plain data packet) or inform the user that there's a nested content type.  \n   This process is complicated by the fact that there are various ways of \n   representing the length information for both outer and inner packets and \n   the fact that the payload can consist of more than one packet, but we're \n   really only interested in the first one in most cases.  The calculation \n   of the encapsulated payload length is as follows:\n\n\t+---+---+---+........................................\n\t|len|hdr| IV|\t\t\t\t\t\t\t\t\t\t: Encrypted data\n\t+---+---+---+........................................\n\t\t\t\t:\t\t\t\t\t\t\t\t\t\t:\n\t\t\t\t+---+---+---------------------------+---+\n\t\t\t\t|len|hdr|\t\t  Payload\t\t\t| ? | Inner content\n\t\t\t\t+---+---+---------------------------+---+\n\n   Definite payload length:\n\t\tPayload = (inner) length - (inner) hdr.\n\n   Unknown length (only allowed for compressed data): \n\t\tPayload = (leave as is since by definition the compressed data \n\t\t\t\t   extends to EOF).\n\n   Indefinite payload length: This gets complicated because when this occurs \n   it's always accompanied by indefinite-length inner content as well, and \n   because of PGP's bizarre fixed-point encoding that only allows power-of-\n   two lengths the positions never synchronise:\n\n\t+---+---+-------+---+-----------+---+-----------+\n\t|len| IV|\t\t|len|\t\t\t|len|\t\t\t| Encrypted data\n\t+---+---+-------+---+-----------+---+-----------+\n\t\t\t:\n\t\t\t+---+-----------+---+-----------+---+----\n\t\t\t|len|\t\t\t|len|\t\t\t|len|\t  Inner content\n\t\t\t+---+-----------+---+-----------+---+----\n\n   Since there's no way to process both the outer and inner indefinite\n   lengths in a single pass, we leave the inner content unprocessed.\n   This leads to a problem because indicating an inner content type\n   of \"Data\" implies that the caller is getting back raw payload data\n   and not PGP-encapsulated data, so we cheat slightly and report it as\n   compressed data.  This means that the caller will feed it back to us\n   to strip the nested encapsulation, with the \"decompression\" being\n   a straight copy from input to output */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processPacketDataHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\tINOUT_ENUM_OPT( PGP_DEENVSTATE ) \\\n\t\t\t\t\t\t\t\t\t\tPGP_DEENV_STATE *state )\n\t{\n\tstatic const MAP_TABLE typeMapTbl[] = {\n\t\t{ PGP_PACKET_COPR, CRYPT_CONTENT_COMPRESSEDDATA },\n\t\t{ PGP_PACKET_ENCR, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_ENCR_MDC, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_SKE, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_PKE, CRYPT_CONTENT_ENVELOPEDDATA },\n\t\t{ PGP_PACKET_SIGNATURE, CRYPT_CONTENT_SIGNEDDATA },\n\t\t{ PGP_PACKET_SIGNATURE_ONEPASS, CRYPT_CONTENT_SIGNEDDATA },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tconst ENV_COPYFROMENVELOPE_FUNCTION copyFromEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYFROMENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyFromEnvelopeFunction );\n\tSTREAM headerStream;\n\tBYTE buffer[ 32 + 256 + 8 ];\t/* Max.data packet header size */\n\tPGP_PACKET_TYPE packetType;\n\tPGP_LENGTH_TYPE lengthType;\n\tlong packetLength;\n\tint value, length, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( state, sizeof( PGP_DEENV_STATE ) ) );\n\t\n\tREQUIRES( envelopeInfoPtr->oobDataLeft < 32 + 256 );\n\tREQUIRES( copyFromEnvelopeFunction != NULL );\n\n\t/* If this is an indefinite-length payload then we pretend that it's\n\t   compressed data in order to have the caller hand it back to us for\n\t   processing of the inner indefinite-length content, see the comment\n\t   at the start of this function for details */\n\tif( !TEST_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT ) )\n\t\t{\n\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_COMPRESSEDDATA;\n\n\t\t/* Don't try and process the content any further */\n\t\tenvelopeInfoPtr->oobEventCount = envelopeInfoPtr->oobDataLeft = 0;\n\t\t*state = PGP_DEENVSTATE_DONE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're down to stripping raw header data, remove it from the buffer\n\t   and exit */\n\tif( envelopeInfoPtr->oobEventCount <= 0 )\n\t\t{\n\t\tstatus = copyFromEnvelopeFunction( envelopeInfoPtr, buffer, \n\t\t\t\t\t\t\t\t\t\t   envelopeInfoPtr->oobDataLeft, \n\t\t\t\t\t\t\t\t\t\t   &length, ENVCOPY_FLAG_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( length < envelopeInfoPtr->oobDataLeft )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t\t/* We've successfully stripped all of the out-of-band data, clear the\n\t\t   data counter.  If it's compressed data (which doesn't have a 1:1 \n\t\t   correspondence between input and output and which has an unknown-\n\t\t   length encoding so there's no length information to adjust), \n\t\t   exit */\n\t\tenvelopeInfoPtr->oobDataLeft = 0;\n\t\tif( envelopeInfoPtr->usage == ACTION_COMPRESS )\n\t\t\t{\n\t\t\t*state = PGP_DEENVSTATE_DONE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Adjust the current data count by what we've removed.  The reason \n\t\t   we have to do this is because segmentSize records the amount of\n\t\t   data copied in (rather than out, as we've done here) but since it \n\t\t   was copied directly into the envelope buffer as part of the \n\t\t   header-processing rather than via copyToDeenvelope() (which is\n\t\t   what usually adjusts segmentSize for us) we have to manually \n\t\t   adjust the value here */\n\t\tif( envelopeInfoPtr->segmentSize > 0 )\n\t\t\t{\n\t\t\tenvelopeInfoPtr->segmentSize -= length;\n\t\t\tENSURES( isIntegerRange( envelopeInfoPtr->segmentSize ) );\n\n\t\t\t/* If we've reached the end of the data (i.e. the entire current \n\t\t\t   segment is contained within the data present in the buffer) \n\t\t\t   remember that what's left still needs to be processed (e.g. \n\t\t\t   hashed in the case of signed data) on the way out */\n\t\t\tif( envelopeInfoPtr->segmentSize <= envelopeInfoPtr->bufPos )\n\t\t\t\t{\n\t\t\t\tenvelopeInfoPtr->dataLeft = envelopeInfoPtr->segmentSize;\n\t\t\t\tenvelopeInfoPtr->segmentSize = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* We've processed the header, if this is signed data then we start \n\t\t   hashing from this point (the PGP RFCs are wrong in this regard, \n\t\t   only the payload is hashed and not the entire packet) */\n\t\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t\t{\n\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\t\t}\n\n\t\t/* We're done */\n\t\t*state = PGP_DEENVSTATE_DONE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We have to perform all sorts of special-case processing to handle the \n\t   out-of-band packet header at the start of the payload.  Initially, we \n\t   need to find out how much header data is actually present.  The header \n\t   for a plain data packet consists of:\n\n\t\tbyte\tctb\n\t\tbyte[]\tlength\n\t\tbyte\ttype = 'b' | 't'\n\t\tbyte\tfilename length\n\t\tbyte[]\tfilename\n\t\tbyte[4]\ttimestamp\n\t  [\tbyte[]\tpayload data ]\n\n\t   The smallest size for this header (1-byte length, no filename) is \n\t   1 + 1 + 1 + 1 + 4 = 8 bytes.  This is also just enough to get us to \n\t   the filename length for a maximum-size header, which is 1 + 5 + 1 + 1 \n\t   bytes up to the filename length and covers the type + length range \n\t   of every other packet type, which can be from 1 to 1 + 5 bytes.  Thus \n\t   we read 8 bytes, setting the OOB data flag to indicate that this is a \n\t   read-ahead read that doesn't remove data from the buffer */\n\tstatus = copyFromEnvelopeFunction( envelopeInfoPtr, buffer, 8, &length,\n\t\t\t\t\t\t\t\t\t   ENVCOPY_FLAG_OOBDATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < 8 )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t/* Read the header information and see what we've got */\n\tsMemConnect( &headerStream, buffer, length );\n\tstatus = getPacketInfo( &headerStream, envelopeInfoPtr, &packetType,\n\t\t\t\t\t\t\t&packetLength, &lengthType, 8, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &headerStream );\n\t\treturn( status );\n\t\t}\n\tif( lengthType == PGP_LENGTH_INDEFINITE )\n\t\t{\n\t\t/* Remember that the packet uses an indefinite-length encoding */\n\t\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT );\n\t\t}\n\tif( lengthType == PGP_LENGTH_UNKNOWN )\n\t\t{\n\t\t/* It's not-definite-nor-indefinite-length compressed data (see the\n\t\t   comment in getPacketInfo()), the length value is meaningless (or\n\t\t   at least implicitly set to \"until we run out of data\") so set it\n\t\t   to an unknown-length indicator */\n\t\tpacketLength = CRYPT_UNUSED;\n\t\t}\n\n\t/* Compressed data is an odd case because its length is implicitly \n\t   defined as \"until the end of the data stream\", which means that it\n\t   can't be followed by further packets as would occur with, for \n\t   example, signed data in which a signature packet would follow the\n\t   compressed data.  No (known) PGP implementation creates data streams \n\t   like this.  For example GPG, when asked to compress and sign, \n\t   compresses the signed-data packet stream, and when asked to sign \n\t   compressed data encapsulates the compressed data inside a literal-\n\t   data packet.  Any data stream like this is almost certainly an \n\t   error, and in any case can't really be processed, so we reject it */\n\tif( packetType == PGP_PACKET_COPR && \\\n\t\t( envelopeInfoPtr->usage != ACTION_COMPRESS && \\\n\t\t  envelopeInfoPtr->usage != ACTION_CRYPT ) )\n\t\t{\n\t\tsMemDisconnect( &headerStream );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Remember the total data packet size unless it's compressed data, \n\t   which doesn't have a 1:1 correspondence between input and output */\n\tif( envelopeInfoPtr->usage != ACTION_COMPRESS )\n\t\t{\n\t\tstatus = adjustDataInfo( envelopeInfoPtr, &headerStream,\n\t\t\t\t\t\t\t\t packetLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &headerStream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* If it's a literal data packet, parse it so that we can strip it from \n\t   the data that we return to the caller.  We know that the reads can't\n\t   fail because the readahead read has confirmed that there are at least\n\t   8 bytes available, but we check anyway just to be sure */\n\tif( packetType == PGP_PACKET_DATA )\n\t\t{\n\t\tint extraLen;\n\n\t\t( void ) sgetc( &headerStream );\t/* Skip content type */\n\t\tstatus = extraLen = sgetc( &headerStream );\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Make sure that the packet formatting is valid, the content \n\t\t\t   should be the type, filename length, filename, timestamp,\n\t\t\t   and at least one byte of data */\n\t\t\tif( packetLength < 1 + 1 + extraLen + 4 + 1 )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tenvelopeInfoPtr->oobDataLeft = stell( &headerStream ) + \\\n\t\t\t\t\t\t\t\t\t\t\t   extraLen + 4;\n\t\t\t\t}\n\t\t\t}\n\t\tsMemDisconnect( &headerStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Remember that this is a pure data packet */\n\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;\n\n\t\t/* We've processed enough of the header to know what to do next, \n\t\t   move on to the next sub-state where we just consume all of the \n\t\t   input.  This has to be done as a sub-state within the \n\t\t   PGP_DEENVSTATE_DATA_HEADER state since we can encounter a\n\t\t   (recoverable) error between reading the out-of-band data header\n\t\t   and reading the out-of-band data itself */\n\t\tenvelopeInfoPtr->oobEventCount--;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tsMemDisconnect( &headerStream );\n\n\t/* If it's a known packet type, indicate it as the nested content type */\n\tstatus = mapValue( packetType, &value, typeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( typeMapTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tenvelopeInfoPtr->contentType = value;\n\n\t/* Don't try and process the content any further */\n\tenvelopeInfoPtr->oobEventCount = envelopeInfoPtr->oobDataLeft = 0;\n\t*state = PGP_DEENVSTATE_DONE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the start of an encrypted data packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processEncryptedPacket( INOUT ENVELOPE_INFO *envelopeInfoPtr, \n\t\t\t\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN_ENUM( PGP_DEENVSTATE ) \\\n\t\t\t\t\t\t\t\t\tconst PGP_DEENV_STATE state )\n\t{\n\tCRYPT_CONTEXT iMdcContext = CRYPT_UNUSED;\n\tconst ACTION_LIST *actionListPtr;\n\tBYTE ivInfoBuffer[ CRYPT_MAX_IVSIZE + 2 + 8 ];\n\tint ivSize, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( isEnumRange( state, PGP_DEENVSTATE ) );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\tENSURES( actionListPtr == NULL || \\\n\t\t\t sanityCheckActionList( actionListPtr ) );\n\n\t/* If there aren't any non-session-key keying resource objects present \n\t   then we can't go any further until we get a session key */\n\tif( actionListPtr == NULL )\n\t\t{\n\t\t/* There's no session key object present, add a pseudo-object that \n\t\t   takes the place of the (password-derived) session key object in \n\t\t   the content list.  This can only occur for PGP 2.x conventionally-\n\t\t   encrypted data, which didn't encode any algorithm information \n\t\t   with the data, so if we get to this point we know that we've hit \n\t\t   data encrypted with the default IDEA/CFB encryption algorithm \n\t\t   derived from a user password using the default MD5 hash \n\t\t   algorithm */\n\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentList ) );\n\t\tif( DATAPTR_ISNULL( envelopeInfoPtr->contentList ) )\n\t\t\t{\n\t\t\tstatus = addContentListItem( envelopeInfoPtr, NULL, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We can't continue until we're given some sort of keying resource */\n\t\treturn( CRYPT_ENVELOPE_RESOURCE );\n\t\t}\n\tENSURES( actionListPtr != NULL && \\\n\t\t\t actionListPtr->action == ACTION_CRYPT );\n\n\t/* If there's an MDC packet present, prepare a hash action.  We have to \n\t   do this before we perform the IV setup because the decrypted form\n\t   of the IV data is hashed before the payload data is hashed */\n\tif( state == PGP_DEENVSTATE_ENCR_MDC )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tREQUIRES( moreActionsPossible( actionListPtr ) );\n\n\t\t/* Append a hash action to the action list */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiMdcContext = createInfo.cryptHandle;\n\t\tstatus = addAction( envelopeInfoPtr, ACTION_HASH, iMdcContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iMdcContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\n\t\t/* Remember that the end of the payload data is actually an MDC \n\t\t   packet that's been tacked onto the payload */\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASATTACHEDOOB );\n\t\t}\n\n\t/* Read and process PGP's peculiar two-stage IV */\n\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &ivSize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sread( stream, ivInfoBuffer, ivSize + 2 );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = pgpProcessIV( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t   ivInfoBuffer, ivSize + 2, ivSize, \n\t\t\t\t\t\t\t   iMdcContext, FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tenvelopeInfoPtr->iCryptContext = actionListPtr->iCryptHandle;\n\n\t/* If we're keeping track of the outer packet size in case there's no \n\t   inner size info present, adjust it by the data that we've just \n\t   processed */\n\tif( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )\n\t\tenvelopeInfoPtr->payloadSize -= stell( stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTrailer Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check for a possible soft error when reading data.  This is necessary \n   because if we're performing a standard data push then the caller expects \n   to get a CRYPT_OK status with a bytes-copied count, but if they've got as \n   far as the trailer data then they'll get a CRYPT_ERROR_UNDERFLOW unless \n   we special-case the handling of the return status.  This is complicated \n   by the fact that we have to carefully distinguish a CRYPT_ERROR_UNDERFLOW \n   due to running out of input from a CRYPT_ERROR_UNDERFLOW incurred for any \n   other reason such as parsing the input data */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkSoftError( IN_ERROR const int status, \n\t\t\t\t\t\t\t   const BOOLEAN isFlush )\n\t{\n\tREQUIRES_B( cryptStatusError( status ) );\n\tREQUIRES_B( isFlush == TRUE || isFlush == FALSE );\n\n\t/* If it's not a flush and we've run out of data, report it as a soft \n\t   error */\n\tif( !isFlush && status == CRYPT_ERROR_UNDERFLOW )\n\t\treturn( TRUE );\n\t\t\n\treturn( FALSE );\n\t}\n\n/* Process an MDC packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processMDC( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t   const BOOLEAN isFlush )\n\t{\n\tconst ENV_PROCESSEXTRADATA_FUNCTION processExtraDataFunction = \\\n\t\t\t\t( ENV_PROCESSEXTRADATA_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->processExtraDataFunction );\n\tconst ACTION_LIST *actionListPtr;\n\tMESSAGE_DATA msgData;\n\tBYTE *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\tREQUIRES( processExtraDataFunction != NULL );\n\n\t/* Make sure that there's an MDC packet present */\n\tif( envelopeInfoPtr->bufPos - \\\n\t\t\tenvelopeInfoPtr->dataLeft < PGP_MDC_PACKET_SIZE )\n\t\t{\n\t\tif( checkSoftError( CRYPT_ERROR_UNDERFLOW, isFlush ) )\n\t\t\treturn( OK_SPECIAL );\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO,\n\t\t\t\t  \"MDC packet is missing or incomplete, expected %d bytes \"\n\t\t\t\t  \"but got %d\", PGP_MDC_PACKET_SIZE, \n\t\t\t\t  envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft ) );\n\t\t}\n\n\t/* Since this is out-of-band data that follows the payload, we can't \n\t   use copyFromDeenvelope() to retrieve it but have to pull it directly \n\t   from the envelope buffer */\n\tif( bufPtr[ 0 ] != 0xD3 || bufPtr[ 1 ] != 0x14 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Hash the trailer bytes (the start of the MDC packet) and wrap up the \n\t   hashing */\n\tstatus = processExtraDataFunction( envelopeInfoPtr, bufPtr, 2 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = processExtraDataFunction( envelopeInfoPtr, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the MDC value matches our calculated hash value */\n\tsetMessageData( &msgData, bufPtr + 2, PGP_MDC_PACKET_SIZE - 2 );\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_HASH );\n\tENSURES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_HASH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\"MDC value doesn't match calculated MDC\", 38 );\n\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t}\n\n\t/* Record the MDC data as having been consumed */\n\tenvelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft;\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tProcess Envelope Preamble/Postamble\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the non-data portions of a PGP message.  This is a complex event-\n   driven state machine, but instead of reading along a (hypothetical\n   Turing-machine) tape someone has taken the tape and cut it into bits and\n   keeps feeding them to us and saying \"See what you can do with this\" (and\n   occasionally \"Where's the bloody spoons?\").  The following code implements\n   this state machine:\n\n\t\t\tPKE / SKE\n\tNONE ----------------> ENC_HDR <--------+\n\t\t\t\t\t\t\t  |  | PKE/SKE\t|\n\t\t\t\t\t\t\t  |\t +----------+\t\n\t\t\t\t\t\t\t  v\n\t\t\t\t\t\tENCR/ENCR_MDC\n\t\t\t\t\t\t\t  |\n\t\t\tSign/Sig-onepass  |\n\t\t\tCopr.\t\t\t  |\n\t\t\tData\t\t\t  v\t\n\t\t -----------------> DATA\n\t\t\t\t\t\t\t  |\n\t\t\t\t\t\t\t  v\n\t\t\t\t\t\t DATA_HEADER\n\t\t\t\t\t\t\t  |\n\t\t\t\t\t\t\t  v\n\t\t\t\t\t\t\tDONE\n\n   If type == Sign/Sig-onepass and detached-sig, we transition directly to \n   DONE.\n\n   Since PGP uses sequential discrete packets rather than the nested objects \n   encountered in the ASN.1-encoded data format the parsing code is made \n   slightly simpler because (for example) the PKC info is just an \n   unconnected sequence of packets rather than a SEQUENCE or SET OF as for \n   cryptlib and PKCS #7/CMS.  OTOH since there's no indication of what's \n   next we have to perform a complex lookahead to see what actions we have \n   to take once we get to the payload.  The end result is that the code is \n   actually vastly more complex than the CMS equivalent */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tPGP_DEENV_STATE state;\n\tSTREAM stream;\n\tint remainder, streamPos = 0, packetsSeen;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvPGPDenv( envelopeInfoPtr ) );\n\n\t/* If we've finished processing the start of the message, header, don't\n\t   do anything */\n\tstate = envelopeInfoPtr->pgpDeenvState;\n\tif( state == PGP_DEENVSTATE_DONE )\n\t\treturn( CRYPT_OK );\n\n\tsMemConnect( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufPos );\n\n\t/* Keep consuming information until we run out of input or reach the\n\t   plaintext data packet */\n\tstatic_assert( MAX_DATA_ITEMS < FAILSAFE_ITERATIONS_MED, \\\n\t\t\t\t   \"MAX_DATA_ITEMS\" );\n\tLOOP_MED( packetsSeen = 0,\n\t\t\t  cryptStatusOK( status ) && state != PGP_DEENVSTATE_DONE && \\\n\t\t\t\tpacketsSeen < MAX_DATA_ITEMS,\n\t\t\t  packetsSeen++ )\n\t\t{\n\t\tswitch( state )\n\t\t\t{\n\t\t\t/* Read the PGP packet type and figure out what we've got */\n\t\t\tcase PGP_DEENVSTATE_NONE:\n\t\t\t\tstatus = processPacketHeader( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t\t  &state, FALSE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Remember how far we got */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tbreak;\n\n\t\t\t/* Process a PKE/SKE packet.  Since we're in the middle of \n\t\t\t   processing encrypted-data metadata, we set the checkState\n\t\t\t   flag to TRUE to disallow any other packets that the \n\t\t\t   general-purpose processPacketHeader() function may \n\t\t\t   encounter */\n\t\t\tcase PGP_DEENVSTATE_ENCR_HDR:\n\t\t\t\tstatus = processPacketHeader( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t\t  &state, TRUE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tbreak;\n\n\t\t\t\t/* Remember how far we got */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tbreak;\n\n\t\t\t/* Process the start of an encrypted data packet */\n\t\t\tcase PGP_DEENVSTATE_ENCR:\n\t\t\tcase PGP_DEENVSTATE_ENCR_MDC:\n\t\t\t\tstatus = processEncryptedPacket( envelopeInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t\t\t state );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If it's a resource-needed status then it's not an \n\t\t\t\t\t   error */\n\t\t\t\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t/* We may get non-data-related errors like \n\t\t\t\t\t   CRYPT_ERROR_WRONGKEY so we only set extended error \n\t\t\t\t\t   information if it's a data-related error */\n\t\t\t\t\tif( isDataError( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\t\"Invalid PGP encrypted data packet \"\n\t\t\t\t\t\t\t\t\t\t\"header\", 40 );\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Remember where we are and move on to the next state */\n\t\t\t\tstreamPos = stell( &stream );\n\t\t\t\tstate = PGP_DEENVSTATE_DATA;\n\t\t\t\tbreak;\n\n\t\t\t/* Process the start of a data packet */\n\t\t\tcase PGP_DEENVSTATE_DATA:\n\t\t\t\t{\n\t\t\t\tconst ENV_SYNCDEENVELOPEDATA_FUNCTION syncDeenvelopeDataFunction = \\\n\t\t\t\t\t\t( ENV_SYNCDEENVELOPEDATA_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->syncDeenvelopeDataFunction );\n\t\t\t\tSAFE_FLAGS originalDataFlags = envelopeInfoPtr->dataFlags;\n\n\t\t\t\tREQUIRES( syncDeenvelopeDataFunction != NULL );\n\n\t\t\t\t/* Synchronise the data stream processing to the start of \n\t\t\t\t   the encapsulated data.  This is made somewhat complex by \n\t\t\t\t   PGP's awkward packet format (see the comment for \n\t\t\t\t   processPacketDataHeader()) which, unlike CMS:\n\n\t\t\t\t\t[ Hdr [ Encaps [ Octet String ] ] ]\n\n\t\t\t\t   has:\n\t\t\t\t\t\t\t   [ Hdr | Octet String ]\n\t\t\t\t\t  [ Keyex ][ Hdr | Octet String ]\n\t\t\t\t\t[ Onepass ][ Hdr | Octet String ][ Signature ]\n\t\t\t\t\t   [ Copr ][ Hdr | Octet String ]\n\n\t\t\t\t   This means that if we're not processing a data packet \n\t\t\t\t   then the content isn't the payload but a futher set of \n\t\t\t\t   discrete packets that we don't want to touch.  To work \n\t\t\t\t   around this we temporarily set ENVDATA_FLAG_NOLENGTHINFO  \n\t\t\t\t   flag to indicate that it's a blob to be processed as an \n\t\t\t\t   opaque unit, at the same time temporarily clearing any \n\t\t\t\t   other flags that might mess up the opaque-blob handling.\n\n\t\t\t\t   In addition to this, if we're using the indefinite-length\n\t\t\t\t   encoding then the initial segment's length has already \n\t\t\t\t   been read when the packet header was read.  This is \n\t\t\t\t   because PGP's weird indefinite-length encoding works as \n\t\t\t\t   follows:\n\n\t\t\t\t\t[ Type | Length | Continuation flag | Data ]\n\t\t\t\t\t[\t\t Length | Continuation flag | Data ]\n\t\t\t\t\t[\t\t Length | Continuation flag | Data ]\n\t\t\t\t\t...\n\t\t\t\t\t[\t\t Length\t\t\t\t\t\t| Data ]\n\n\t\t\t\t   so we can't simply undo the read of the start of the \n\t\t\t\t   first packet and treat it as a standard segement because \n\t\t\t\t   the encoding for the first segment and the remaining \n\t\t\t\t   segments is different, so an attempt to treat them \n\t\t\t\t   identically will lead to a decoding error.  Instead we \n\t\t\t\t   set ENVDATA_FLAG_NOFIRSTSEGMENT to indicate that the \n\t\t\t\t   first length-read should be skipped.\n\t\t\t   \n\t\t\t\t   Finally, when we reset the flags we have to preserve the \n\t\t\t\t   ENVDATA_FLAG_ENDOFCONTENTS flag, since we may have \n\t\t\t\t   already encountered the last segment during the sync \n\t\t\t\t   operation */\n\t\t\t\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t   ENVDATA_FLAG_NOSEGMENT ) )\n\t\t\t\t\t{\n\t\t\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t\t  ENVDATA_FLAG_NOLENGTHINFO );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t  ENVDATA_FLAG_NOFIRSTSEGMENT );\n\t\t\t\t\t}\n\t\t\t\tstatus = syncDeenvelopeDataFunction( envelopeInfoPtr, &stream );\n\t\t\t\tSET_FLAGS( originalDataFlags,\n\t\t\t\t\t\t   GET_FLAGS( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t\t\t\t  ENVDATA_FLAG_ENDOFCONTENTS ) );\n\t\t\t\tenvelopeInfoPtr->dataFlags = originalDataFlags;\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Couldn't synchronise envelope state \"\n\t\t\t\t\t\t\t\t\t\"prior to data payload processing\", 68 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tstreamPos = 0;\n\n\t\t\t\t/* Move on to the next state.  For plain data we're done,\n\t\t\t\t   however for other content types we have to either process \n\t\t\t\t   or strip out the junk that PGP puts at the start of the \n\t\t\t\t   content */\n\t\t\t\tif( envelopeInfoPtr->usage != ACTION_NONE )\n\t\t\t\t\t{\n\t\t\t\t\tenvelopeInfoPtr->oobEventCount = 1;\n\t\t\t\t\tstate = PGP_DEENVSTATE_DATA_HEADER;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tstate = PGP_DEENVSTATE_DONE;\n\n\t\t\t\tENSURES( checkActions( envelopeInfoPtr ) );\n\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Burrow down into the encapsulated data to see what's next */\n\t\t\tcase PGP_DEENVSTATE_DATA_HEADER:\n\t\t\t\t/* If there's no out-of-band data left to remove at the \n\t\t\t\t   start of the payload then we're done.  This out-of-band \n\t\t\t\t   data handling sometimes requires two passes, the first \n\t\t\t\t   time through oobEventCount is nonzero because it's been \n\t\t\t\t   set in the preceding PGP_DEENVSTATE_DATA state and we \n\t\t\t\t   fall through to processPacketDataHeader() which \n\t\t\t\t   decrements the oobEventCount to zero.  However \n\t\t\t\t   processPacketDataHeader() may need to read out-of-band \n\t\t\t\t   data in which case on the second time around oobDataLeft \n\t\t\t\t   will be nonzero, resulting in a second call to\n\t\t\t\t   processPacketDataHeader() to clear the remaining out-of-\n\t\t\t\t   band data */\n\t\t\t\tif( envelopeInfoPtr->oobEventCount <= 0 && \\\n\t\t\t\t\tenvelopeInfoPtr->oobDataLeft <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstate = PGP_DEENVSTATE_DONE;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* Process the encapsulated data header */\n\t\t\t\tstatus = processPacketDataHeader( envelopeInfoPtr, &state );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we're processing compressed data and there's a \n\t\t\t\t\t   problem with it, return a more specific error \n\t\t\t\t\t   message.  This is a bit of a special case, but there\n\t\t\t\t\t   are various broken third-party Zip implementations \n\t\t\t\t\t   out there so we need to return a bit more detail than\n\t\t\t\t\t   just a generic compressed-data problem error */\n#ifdef USE_COMPRESSION\n\t\t\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \\\n\t\t\t\t\t\t\t\t   ENVELOPE_FLAG_ZSTREAMINITED ) && \\\n\t\t\t\t\t\tenvelopeInfoPtr->zStream.msg != NULL )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tchar errorString[ 128 + 8 ];\n\t\t\t\t\t\tconst int zStreamMsgLen = \\\n\t\t\t\t\t\t\t\tmin( strlen( envelopeInfoPtr->zStream.msg ),\n\t\t\t\t\t\t\t\t\t 128 - 33 );\n\n\t\t\t\t\t\tREQUIRES( boundsCheck( 33, zStreamMsgLen, 128 ) ); \n\t\t\t\t\t\tmemcpy( errorString, \"Invalid zlib compressed \"\n\t\t\t\t\t\t\t\t\t\t\t \"content: \", 33 );\n\t\t\t\t\t\tmemcpy( errorString + 33, envelopeInfoPtr->zStream.msg,\n\t\t\t\t\t\t\t\tzStreamMsgLen );\n\t\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, errorString, \n\t\t\t\t\t\t\t\t\t\t33 + zStreamMsgLen );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n#endif /* USE_COMPRESSION */\n\t\t\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\t\t\"Invalid PGP encapsulated content \"\n\t\t\t\t\t\t\t\t\t\"header\", 39 );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\tif( packetsSeen >= MAX_DATA_ITEMS )\n\t\t{\n\t\t/* Technically this would be an overflow but that's a recoverable\n\t\t   error so we make it a BADDATA, which is really what it is */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tenvelopeInfoPtr->pgpDeenvState = state;\n\n\tENSURES( streamPos >= 0 && streamPos < MAX_BUFFER_SIZE && \\\n\t\t\t envelopeInfoPtr->bufPos - streamPos >= 0 );\n\n\t/* Consume the input that we've processed so far by moving everything \n\t   past the current position down to the start of the envelope buffer */\n\tremainder = envelopeInfoPtr->bufPos - streamPos;\n\tREQUIRES( remainder >= 0 && remainder < MAX_BUFFER_SIZE && \\\n\t\t\t  streamPos + remainder <= envelopeInfoPtr->bufSize );\n\tif( remainder > 0 && streamPos > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( streamPos, remainder, \n\t\t\t\t\t\t\t   envelopeInfoPtr->bufSize ) );\n\t\tmemmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + streamPos,\n\t\t\t\t remainder );\n\t\t}\n\tenvelopeInfoPtr->bufPos = remainder;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckEnvPGPDenv( envelopeInfoPtr ) );\n\n\t/* If all went OK but we're still not out of the header information,\n\t   return an underflow error */\n\treturn( ( state != PGP_DEENVSTATE_DONE ) ? \\\n\t\t\tCRYPT_ERROR_UNDERFLOW : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t const BOOLEAN isFlush )\n\t{\n\tconst ENV_PROCESSEXTRADATA_FUNCTION processExtraDataFunction = \\\n\t\t\t\t( ENV_PROCESSEXTRADATA_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->processExtraDataFunction );\n\tCONTENT_LIST *contentListPtr;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvPGPDenv( envelopeInfoPtr ) );\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\tREQUIRES( processExtraDataFunction != NULL );\n\n\t/* If that's all there is, return */\n\tif( envelopeInfoPtr->usage != ACTION_SIGN && \\\n\t\t!TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\tENVDATA_FLAG_HASATTACHEDOOB ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If there's an MDC packet present, make sure that the integrity check \n\t   matches */\n\tif( TEST_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t   ENVDATA_FLAG_HASATTACHEDOOB ) )\n\t\treturn( processMDC( envelopeInfoPtr, isFlush ) );\n\n\t/* Find the signature information in the content list.  In theory this\n\t   could get ugly because there could be multiple one-pass signature\n\t   packets present but PGP handles multiple signatures by nesting them \n\t   so this isn't a problem */\n\tLOOP_MED( contentListPtr = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t  contentListPtr != NULL && \\\n\t\t\t\tcontentListPtr->envInfo != CRYPT_ENVINFO_SIGNATURE,\n\t\t\t  contentListPtr = DATAPTR_GET( contentListPtr->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( contentListPtr != NULL );\n\tREQUIRES( sanityCheckContentList( contentListPtr ) );\n\n\t/* PGP 2.x prepended (!!) signatures to the signed data, OpenPGP fixed \n\t   this by splitting the signature into a header with signature info and \n\t   a trailer with the actual signature.  If we're processing a PGP 2.x\n\t   signature we'll already have the signature data present so we only \n\t   check for signature data if it's not already available */\n\tif( DATAPTR_ISNULL( contentListPtr->object ) )\n\t\t{\n\t\tSTREAM stream;\n\t\tPGP_PACKET_TYPE packetType;\n\t\tlong packetLength;\n\n\t\t/* Make sure that there's enough data left in the stream to do \n\t\t   something with.  We require a minimum of 44 bytes, the size\n\t\t   of the DSA signature payload */\n\t\tif( envelopeInfoPtr->bufPos - \\\n\t\t\t\tenvelopeInfoPtr->dataLeft < PGP_MAX_HEADER_SIZE + 44 )\n\t\t\t{\n\t\t\treturn( checkSoftError( CRYPT_ERROR_UNDERFLOW, isFlush ) ? \\\n\t\t\t\t\tOK_SPECIAL : CRYPT_ERROR_UNDERFLOW );\n\t\t\t}\n\n\t\tREQUIRES( contentListPtr != NULL );\n\t\tREQUIRES( moreContentItemsPossible( contentListPtr ) );\n\n\t\t/* Read the signature packet at the end of the payload.  We set the \n\t\t   check-data-present flag on the call to getPacketInfo() to ensure \n\t\t   that we get a CRYPT_ERROR_UNDERFLOW if there's not enough data \n\t\t   present to process the packet, which means that we can provide \n\t\t   special-case soft-error handling before we try and read the \n\t\t   packet data in addContentListItem() */\n\t\tsMemConnect( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,\n\t\t\t\t\t envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft );\n\t\tstatus = getPacketInfo( &stream, envelopeInfoPtr, &packetType, \n\t\t\t\t\t\t\t\t&packetLength, NULL, 8, TRUE );\n\t\tif( cryptStatusOK( status ) && packetType != PGP_PACKET_SIGNATURE )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( checkSoftError( status, isFlush ) )\n\t\t\t\treturn( OK_SPECIAL );\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Invalid PGP signature packet header\" ) );\n\t\t\t}\n\t\tsseek( &stream, 0 );\n\t\tstatus = addContentListItem( envelopeInfoPtr, &stream, TRUE );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Invalid PGP signature packet\" ) );\n\t\t\t}\n\t\t}\n\n\t/* When we reach this point there may still be unhashed data left in the \n\t   buffer (it won't have been hashed yet because the hashing is performed \n\t   when the data is copied out, after unwrapping and whatnot) so we hash \n\t   it before we exit.  Since we don't wrap up the hashing as we do with\n\t   any other format (PGP hashes in all sorts of odds and ends after \n\t   hashing the message body) we have to manually turn off hashing here */\n\tif( envelopeInfoPtr->dataLeft > 0 )\n\t\t{\n\t\tstatus = processExtraDataFunction( envelopeInfoPtr,\n\t\t\t\t\t\tenvelopeInfoPtr->buffer, envelopeInfoPtr->dataLeft );\n\t\t}\n\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASHACTIONSACTIVE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckEnvPGPDenv( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPGPDeenveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\t\n\tREQUIRES_V( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->processPreambleFunction, processPreamble );\n\tFNPTR_SET( envelopeInfoPtr->processPostambleFunction, processPostamble );\n\tFNPTR_SET( envelopeInfoPtr->checkAlgoFunction, pgpCheckAlgo );\n\n\t/* Set up the processing state information */\n\tenvelopeInfoPtr->pgpDeenvState = PGP_DEENVSTATE_NONE;\n\n\t/* Turn off segmentation of the envelope payload.  PGP has a single \n\t   length at the start of the data and doesn't segment the payload */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT );\n\t}\n#endif /* USE_PGP */\n"
  },
  {
    "path": "deps/cl345/envelope/pgp_env.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t cryptlib PGP Enveloping Routines\t\t\t\t\t\t*\n*\t\t\t\t\t Copyright Peter Gutmann 1996-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"pgp_rw.h\"\n  #include \"envelope.h\"\n#else\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the envelope state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckPGPEnv( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckEnvelope( envelopeInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPGPEnv: Envelope check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that general envelope state is in order */\n\tif( envelopeInfoPtr->type != CRYPT_FORMAT_PGP || \\\n\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPGPEnv: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that all values related to the auxBuffer are clear, since \n\t   it isn't used for PGP enveloping */\n\tif( envelopeInfoPtr->auxBuffer != NULL || \\\n\t\tenvelopeInfoPtr->auxBufPos != 0 || envelopeInfoPtr->auxBufSize != 0 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPGPEnv: Spurious auxiliary buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that a requested algorithm type is valid with PGP data */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN pgpCheckAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t  IN_MODE_OPT const CRYPT_MODE_TYPE cryptMode )\n\t{\n\tint dummy;\n\n\tREQUIRES_B( cryptAlgo > CRYPT_ALGO_NONE && \\\n\t\t\t\tcryptAlgo < CRYPT_ALGO_LAST_EXTERNAL );\n\tREQUIRES_B( isEnumRangeOpt( cryptMode, CRYPT_MODE ) );\n\n\tif( cryptStatusError( cryptlibToPgpAlgo( cryptAlgo, &dummy ) ) )\n\t\treturn( FALSE );\n\tif( isConvAlgo( cryptAlgo ) )\n\t\t{\n\t\tif( cryptMode != CRYPT_MODE_CFB )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( cryptMode != CRYPT_MODE_NONE )\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Unlike PKCS #7/CMS/SMIME, PGP doesn't contain truly nested messages (with \n   the outer wrapper identifying what's in the inner content) but just puts \n   one lot of data inside the other.  This means that when the caller \n   specifies an inner content type we then have to burrow into the data that \n   they push in order to determine that it actually matches what they've \n   specified as the content type.\n   \n   The following alternative to copyToEnvelope() is enabled when the inner \n   content type isn't plain data.  It checks the data being pushed (as far \n   as it's possible to do so) to ensure that it matches the declared content \n   type */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int copyToEnvelopeAlt( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( length ) const BYTE *buffer, \n\t\t\t\t\t\t\t  IN_LENGTH_Z const int length )\n\t{\n\tstatic const MAP_TABLE typeMapTbl[] = {\n\t\t{ PGP_PACKET_COPR, CRYPT_CONTENT_COMPRESSEDDATA },\n\t\t{ PGP_PACKET_ENCR, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_ENCR_MDC, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_SKE, CRYPT_CONTENT_ENCRYPTEDDATA },\n\t\t{ PGP_PACKET_PKE, CRYPT_CONTENT_ENVELOPEDDATA },\n\t\t{ PGP_PACKET_SIGNATURE, CRYPT_CONTENT_SIGNEDDATA },\n\t\t{ PGP_PACKET_SIGNATURE_ONEPASS, CRYPT_CONTENT_SIGNEDDATA },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\tSTREAM stream;\n\tlong contentLength;\n\tint ctb DUMMY_INIT, version, packetType, value, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( length == 0 || isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\tREQUIRES( ( buffer == NULL && length == 0 ) || \\\n\t\t\t  ( buffer != NULL && length >= 0 && length < MAX_BUFFER_SIZE ) );\n\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t/* If it's a flush then it's always an error, since there must be nested \n\t   content */\n\tif( length <= 0 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Envelope marked as having nested content type %d can't \"\n\t\t\t\t  \"contain no content\", envelopeInfoPtr->contentType ) );\n\t\t}\n\n\t/* Examine the start of the data to try and make sure that it matches \n\t   the content-type that's been set by the user */\n\tif( length > 1 )\n\t\t{\n\t\tsMemConnect( &stream, buffer, length );\n\t\tstatus = pgpReadPacketHeaderI( &stream, &ctb, &contentLength, 1 );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we encountered an error (other than running out of input)\n\t\t\t   then what's being pushed isn't PGP nested content */\n\t\t\tif( status != CRYPT_ERROR_UNDERFLOW )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t\t\t  \"Data for envelope marked as having content type \"\n\t\t\t\t\t\t  \"%d doesn't appear to be PGP content\", \n\t\t\t\t\t\t  envelopeInfoPtr->contentType ) );\n\t\t\t\t}\n\t\t\t\n\t\t\t/* We ran out of data to read, only look at the CTB */\n\t\t\tctb = byteToInt( *buffer );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( length == 1 );\n\n\t\t/* There's too little data to read a full PGP header, just get the \n\t\t   CTB */\n\t\tctb = byteToInt( *buffer );\n\t\t}\n\tversion = pgpGetPacketVersion( ctb );\n\tpacketType = pgpGetPacketType( ctb );\n\tif( ( version != PGP_VERSION_2 && version != PGP_VERSION_OPENPGP ) || \\\n\t\t( packetType <= PGP_PACKET_NONE || packetType >= PGP_PACKET_LAST ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Data for envelope marked as having content type %d \"\n\t\t\t\t  \"doesn't appear to be PGP content\", \n\t\t\t\t  envelopeInfoPtr->contentType ) );\n\t\t}\n\n\t/* Make sure that what we've got matches the declared content-type */\n\tstatus = mapValue( packetType, &value, typeMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( typeMapTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Disallowed content type, set a dummy value to fail the following\n\t\t   test while still allowing for error reporting */\n\t\tvalue = 0;\n\t\t}\n\tif( value != envelopeInfoPtr->contentType || \\\n\t\tversion < PGP_VERSION_2 || version > PGP_VERSION_OPENPGP )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Data for envelope marked as having content type \"\n\t\t\t\t  \"%d appears to actually be content type %d, \"\n\t\t\t\t  \"version %d\", envelopeInfoPtr->contentType, \n\t\t\t\t  value, version ) );\n\t\t}\n\n\t/* Reset the envelope data processing to the standard mechanism and pass \n\t   the data on to the standard function */\n\tinitEnvelopeStreaming( envelopeInfoPtr );\n\treturn( copyToEnvelopeFunction( envelopeInfoPtr, buffer, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Key Exchange/Signature Packets\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* One-pass signature info:\n\n\tbyte\tversion = 3\n\tbyte\tsigType\n\tbyte\thashAlgo\n\tbyte\tsigAlgo\n\tbyte[8]\tkeyID\n\tbyte\t1 \n\n   This is additional header data written at the start of a block of signed\n   data rather than a standard PGP packet so we can't write it using the \n   normal PGP packet read/write routines */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeSignatureInfoPacket( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iHashContext )\n\t{\n\tBYTE keyID[ PGP_KEYID_SIZE + 8 ];\n\tint hashAlgo, signAlgo DUMMY_INIT;\t/* int vs.enum */\n\tint pgpHashAlgo, pgpCryptAlgo DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\n\t/* Get the signature information */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &signAlgo, CRYPT_CTXINFO_ALGO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, keyID, PGP_KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptlibToPgpAlgo( hashAlgo, &pgpHashAlgo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptlibToPgpAlgo( signAlgo, &pgpCryptAlgo );\n\tENSURES( cryptStatusOK( status ) );\n\tINJECT_FAULT( ENVELOPE_PGP_CORRUPT_ONEPASS_ID, \n\t\t\t\t  ENVELOPE_PGP_CORRUPT_ONEPASS_ID_1 );\n\n\t/* Write the signature info packet.  Note that the version 3 value is \n\t   normally used to identify a legal-kludged PGP 2.0 but in this case it \n\t   denotes OpenPGP, which usually has the version 4 value rather than 3 */\n\tpgpWritePacketHeader( stream, PGP_PACKET_SIGNATURE_ONEPASS, \\\n\t\t\t\t\t\t  PGP_VERSION_SIZE + 1 + PGP_ALGOID_SIZE + \\\n\t\t\t\t\t\t\tPGP_ALGOID_SIZE + PGP_KEYID_SIZE + 1 );\n\tsputc( stream, 3 );\t\t/* Version = 3 (OpenPGP) */\n\tsputc( stream, 0 );\t\t/* Binary document signature */\n\tsputc( stream, pgpHashAlgo );\n\tsputc( stream, pgpCryptAlgo );\n\tswrite( stream, keyID, PGP_KEYID_SIZE );\n\treturn( sputc( stream, 1 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Header Packets\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the data header packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeHeaderPacket( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tSTREAM stream;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( envelopeInfoPtr->envState == ENVSTATE_HEADER );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\t/* If we're encrypting, set up the encryption-related information.  \n\t   Since PGP doesn't perform a key exchange of a session key when \n\t   conventionally-encrypting data, the encryption information could be \n\t   coming from either an encryption action (derived from a password) or \n\t   a conventional key exchange action that results in the direct \n\t   creation of a session encryption key */\n\tif( envelopeInfoPtr->usage == ACTION_CRYPT )\n\t\t{\n\t\tconst ACTION_LIST *lastActionPtr;\n\n\t\tREQUIRES( actionListPtr != NULL );\n\n\t\tstatus = initEnvelopeEncryption( envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t\t actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_NONE, CRYPT_MODE_NONE, \n\t\t\t\t\t\t\t\t\t\t NULL, 0, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Prepare to start emitting the key exchange (PKC-encrypted) or \n\t\t   session key (conventionally encrypted) actions */\n\t\tlastActionPtr = findPreAction( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t   ACTION_KEYEXCHANGE_PKC );\n\t\tif( lastActionPtr == NULL )\n\t\t\t{\n\t\t\t/* There's no key exchange action, we're using a raw session key \n\t\t\t   derived from a password */\n\t\t\tlastActionPtr = actionListPtr;\n\t\t\t}\n\t\tENSURES( lastActionPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( lastActionPtr ) );\n\t\tDATAPTR_SET( envelopeInfoPtr->lastAction, \n\t\t\t\t\t ( ACTION_LIST * ) lastActionPtr );\n\n\t\tenvelopeInfoPtr->envState = ENVSTATE_KEYINFO;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're not encrypting data (i.e. there's only a single packet \n\t   present rather than a packet preceded by a pile of key exchange \n\t   actions) we write the appropriate PGP header based on the envelope \n\t   usage */\n\tsMemOpen( &stream, envelopeInfoPtr->buffer, envelopeInfoPtr->bufSize );\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_SIGN:\n\t\t\t{\n\t\t\tconst ACTION_LIST *postActionListPtr;\n\n\t\t\tREQUIRES( actionListPtr != NULL );\n\t\t\tREQUIRES( DATAPTR_ISSET( envelopeInfoPtr->postActionList ) );\n\t\t\tpostActionListPtr = DATAPTR_GET( envelopeInfoPtr->postActionList );\n\t\t\tENSURES( postActionListPtr != NULL );\n\n\t\t\tif( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t\t\t{\n\t\t\t\tstatus = writeSignatureInfoPacket( &stream, \n\t\t\t\t\t\t\t\t\t\tpostActionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\tactionListPtr->iCryptHandle );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Since we can only sign literal data we need to explicitly \n\t\t\t   write an inner data header */\n\t\t\tREQUIRES( envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA );\n\t\t\tenvelopeInfoPtr->envState = ENVSTATE_DATA;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ACTION_NONE:\n\t\t\t/* Write the header followed by an indicator that we're using \n\t\t\t   opaque content, a zero-length filename, and no date */\n\t\t\tpgpWritePacketHeader( &stream, PGP_PACKET_DATA, \n\t\t\t\t\t\t\t\t  envelopeInfoPtr->payloadSize + \\\n\t\t\t\t\t\t\t\t\tPGP_DATA_HEADER_SIZE );\n\t\t\tstatus = swrite( &stream, PGP_DATA_HEADER, PGP_DATA_HEADER_SIZE );\n\n\t\t\t/* The header state remains at ENVSTATE_HEADER, which means that\n\t\t\t   it'll be finalised to ENVSTATE_DONE at the end of this \n\t\t\t   function as no further processing is necessary */\n\t\t\tbreak;\n\n\t\tcase ACTION_COMPRESS:\n\t\t\t/* Compressed data packets use a special unkown-length encoding \n\t\t\t   that doesn't work like any other PGP packet type so we can't \n\t\t\t   use pgpWritePacketHeader() for this packet type but have to \n\t\t\t   hand-assemble the header ourselves */\n\t\t\tsputc( &stream, PGP_CTB_COMPRESSED );\n\t\t\tstatus = sputc( &stream, PGP_ALGO_ZLIB );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tif( envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )\n\t\t\t\t{\n\t\t\t\t/* If there's no inner content type we need to explicitly \n\t\t\t\t   write an inner data header */\n\t\t\t\tenvelopeInfoPtr->envState = ENVSTATE_DATA;\n\t\t\t\t}\n\t\t\tbreak;\n\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tenvelopeInfoPtr->bufPos = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Reset the segmentation state.  Although PGP doesn't segment the \n\t   payload we still have to reset the state to synchronise things like \n\t   payload hashing and encryption.  We also set the block size mask to \n\t   all ones if we're not encrypting since we can begin and end data \n\t   segments on arbitrary boundaries */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_SEGMENTCOMPLETE );\n\tif( envelopeInfoPtr->usage != ACTION_CRYPT )\n\t\tenvelopeInfoPtr->blockSizeMask = ~0;\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, NULL );\n\n\t/* If we're not emitting any inner header, we're done */\n\tif( envelopeInfoPtr->envState == ENVSTATE_HEADER || \\\n\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tHeader/Trailer Processing Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write key exchange actions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeKeyex( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *lastActionPtr;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Export the session key using each of the PKC keys, or write the \n\t   derivation information needed to recreate the session key */\n\tLOOP_MED( lastActionPtr = DATAPTR_GET( envelopeInfoPtr->lastAction ),  \n\t\t\t  lastActionPtr != NULL,\n\t\t\t  lastActionPtr = DATAPTR_GET( lastActionPtr->next ) )\n\t\t{\n\t\tvoid *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;\n\t\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos, \n\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\t\tint keyexSize = 0;\n\n\t\tREQUIRES( sanityCheckActionList( lastActionPtr ) );\n\n\t\t/* Make sure that there's enough room to emit this key exchange \n\t\t   action */\n\t\tif( lastActionPtr->encodedSize + 128 > dataLeft )\n\t\t\t{\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Emit the key exchange action.  The \"key exchange\" for \n\t\t   conventional-encryption actions isn't actually a key exchange \n\t\t   since PGP derives the session key directly from the password, \n\t\t   so all it does is write the key-derivation parameters and\n\t\t   exit.\n\n\t\t   If we're encrypting with an MDC there's a third type of action \n\t\t   present, an ACTION_HASH, but since this is unkeyed there's no\n\t\t   key exchange action to be taken for it */\n\t\tif( lastActionPtr->action == ACTION_KEYEXCHANGE_PKC )\n\t\t\t{\n\t\t\tstatus = iCryptExportKey( bufPtr, dataLeft, &keyexSize, \n\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP, \n\t\t\t\t\t\t\t\t\t  envelopeInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t\t\t  lastActionPtr->iCryptHandle );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( lastActionPtr->action == ACTION_CRYPT )\n\t\t\t\t{\n\t\t\t\tstatus = iCryptExportKey( bufPtr, dataLeft, &keyexSize, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t  envelopeInfoPtr->iCryptContext );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tenvelopeInfoPtr->bufPos += keyexSize;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDATAPTR_SET( envelopeInfoPtr->lastAction, lastActionPtr );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeEncryptedContentHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_CONTEXT iMdcContext = CRYPT_UNUSED;\n\tconst BOOLEAN hasMDC = \\\n\t\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) ? \\\n\t\t\tTRUE : FALSE;\n\tSTREAM stream;\n\tBYTE ivInfoBuffer[ ( CRYPT_MAX_IVSIZE + 2 ) + 8 ];\n\tconst int packetType = hasMDC ? PGP_PACKET_ENCR_MDC : PGP_PACKET_ENCR;\n\tconst int payloadDataSize = PGP_DATA_HEADER_SIZE + \\\n\t\t\t\t\t\t\t    envelopeInfoPtr->payloadSize + \\\n\t\t\t\t\t\t\t\t( hasMDC ? PGP_MDC_PACKET_SIZE : 0 );\n\tconst int dataLeft = min( envelopeInfoPtr->bufSize - \\\n\t\t\t\t\t\t\t\tenvelopeInfoPtr->bufPos, \n\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\tint ivSize, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Get the IV size and make sure that there's enough room to emit the \n\t   encrypted content header (+8 for slop space) */\n\tstatus = krnlSendMessage( envelopeInfoPtr->iCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &ivSize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( dataLeft < PGP_MAX_HEADER_SIZE + ( ivSize + 2 ) + \\\n\t\t\t\t\t\t\t\t\t( hasMDC ? 1 : 0 ) + 8 )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* If we're using an MDC then we need to hash the IV information before \n\t   it's processed in order to create the sort-of-keyed hash */\n\tif( hasMDC )\n\t\t{\n\t\tconst ACTION_LIST *actionListPtr;\n\n\t\tactionListPtr = findAction( envelopeInfoPtr, ACTION_HASH );\n\t\tENSURES( actionListPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\tiMdcContext = actionListPtr->iCryptHandle;\n\t\t}\n\n\t/* Set up the PGP IV information */\n\tstatus = pgpProcessIV( envelopeInfoPtr->iCryptContext, \n\t\t\t\t\t\t   ivInfoBuffer, ivSize + 2, ivSize, \n\t\t\t\t\t\t   iMdcContext, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the encrypted content header, with the length being the size of \n\t   the optional MDC indicator, the inner data CTB and length, and the\n\t   combined inner data header, payload, and optional MDC */\n\tsMemOpen( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos, \n\t\t\t  dataLeft );\n\tpgpWritePacketHeader( &stream, packetType, \n\t\t\t\t\t\t  ( hasMDC ? 1 : 0 ) + ( ivSize + 2 ) + \\\n\t\t\t\t\t\t  1 + pgpSizeofLength( payloadDataSize ) + \\\n\t\t\t\t\t\t  payloadDataSize );\n\tif( hasMDC )\n\t\t{\n\t\t/* MDC-encrypted data has a version number before the data */\n\t\tsputc( &stream, 1 );\n\t\t}\n\tstatus = swrite( &stream, ivInfoBuffer, ivSize + 2 );\n\tif( cryptStatusOK( status ) )\n\t\tenvelopeInfoPtr->bufPos += stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHeader Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a session key to encrypt the envelope contents */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createSessionKey( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_CONTEXT iSessionKeyContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tstatic const int mode = CRYPT_MODE_CFB;\t/* int vs.enum */\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Create a default encryption action */\n\tsetMessageCreateObjectInfo( &createInfo, envelopeInfoPtr->defaultAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiSessionKeyContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iSessionKeyContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendNotifier( iSessionKeyContext, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add the session-key action to the action list */\n\tstatus = addAction( envelopeInfoPtr, ACTION_CRYPT, iSessionKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform any final initialisation actions before starting the enveloping\n   process */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int preEnvelopeEncrypt( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCRYPT_DEVICE iCryptDevice = CRYPT_ERROR;\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tACTION_LIST *actionListCursor;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( envelopeInfoPtr->usage == ACTION_CRYPT );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\tREQUIRES( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ) != NULL );\n\n\t/* Create the session key if necessary */\n\tif( actionListPtr == NULL )\n\t\t{\n\t\tstatus = createSessionKey( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\t\tENSURES( actionListPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\t\t}\n\telse\n\t\t{\n\t\t/* If the session key context is tied to a device, get its handle so \n\t\t   we can check that all key exchange objects are also in the same \n\t\t   device */\n\t\tstatus = krnlSendMessage( actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t\t  MESSAGE_GETDEPENDENT, &iCryptDevice, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_DEVICE );\n\t\tif( cryptStatusError( status ) )\n\t\t\tiCryptDevice = CRYPT_ERROR;\n\t\t}\n\n\t/* Notify the kernel that the session key context is attached to the \n\t   envelope.  This is an internal object used only by the envelope so we\n\t   tell the kernel not to increment its reference count when it attaches\n\t   it */\n\tstatus = krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t  IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t  &actionListPtr->iCryptHandle, \n\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Now walk down the list of key exchange actions connecting each one to \n\t   the session key action. The caller has already guaranteed that there's \n\t   at least one PKC keyex action present */\n\tLOOP_MED( actionListCursor = \\\n\t\t\t\t\tfindPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ), \n\t\t\t  actionListCursor != NULL && \\\n\t\t\t\tactionListCursor->action == ACTION_KEYEXCHANGE_PKC,\n\t\t\t  actionListCursor = DATAPTR_GET( actionListCursor->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckActionList( actionListCursor ) );\n\n\t\t/* If the session key context is tied to a device, make sure that \n\t\t   the key exchange object is in the same device */\n\t\tif( iCryptDevice != CRYPT_ERROR )\n\t\t\t{\n\t\t\tCRYPT_DEVICE iKeyexDevice;\n\n\t\t\tstatus = krnlSendMessage( actionListCursor->iCryptHandle, \n\t\t\t\t\t\t\t\t\t  MESSAGE_GETDEPENDENT, &iKeyexDevice, \n\t\t\t\t\t\t\t\t\t  OBJECT_TYPE_DEVICE );\n\t\t\tif( cryptStatusError( status ) || iCryptDevice != iKeyexDevice )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* Connect the controller to the subject and remember that we now \n\t\t   have a controlling action */\n\t\tDATAPTR_SET( actionListCursor->associatedAction, actionListPtr );\n\t\tCLEAR_FLAG( actionListPtr->flags, ACTION_FLAG_NEEDSCONTROLLER );\n\n\t\t/* Evaluate the size of the exported action.  We only get PKC \n\t\t   actions at this point so we don't have to provide any special-\n\t\t   case handling for other key exchange types */\n\t\tstatus = iCryptExportKey( NULL, 0, &actionListCursor->encodedSize, \n\t\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP, \n\t\t\t\t\t\t\t\t  actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t  actionListCursor->iCryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int preEnvelopeSign( const ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *postActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList );\n\tACTION_LIST *associatedActionPtr;\n\tSIGPARAMS sigParams;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( envelopeInfoPtr->usage == ACTION_SIGN );\n\n\t/* Make sure that there's at least one signing action present */\n\tif( postActionListPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\tassert( isWritePtr( postActionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tassociatedActionPtr = DATAPTR_GET( postActionListPtr->associatedAction );\n\tENSURES( associatedActionPtr != NULL );\n\t\n\t/* Evaluate the size of the signature action */\n\tinitSigParamsPGP( &sigParams, PGP_SIG_DATA, NULL, 0 );\n\treturn( iCryptCreateSignature( NULL, 0, &postActionListPtr->encodedSize, \n\t\t\t\t\t\tCRYPT_FORMAT_PGP, postActionListPtr->iCryptHandle, \n\t\t\t\t\t\tassociatedActionPtr->iCryptHandle, &sigParams ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int preEnvelopeInit( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint status = CRYPT_OK;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* If there's no nested content type set, default to plain data */\n\tif( envelopeInfoPtr->contentType == CRYPT_CONTENT_NONE )\n\t\tenvelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;\n\n\t/* Remember the length information for when we copy in data */\n\tenvelopeInfoPtr->segmentSize = envelopeInfoPtr->payloadSize;\n\n\t/* Perform any remaining initialisation.  Since PGP derives the session \n\t   key directly from the user password we only perform the encryption \n\t   initialisation if there are PKC key exchange actions present */\n\tif( envelopeInfoPtr->usage == ACTION_CRYPT )\n\t\t{\n\t\tif( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ) != NULL )\n\t\t\t{\n\t\t\tstatus = preEnvelopeEncrypt( envelopeInfoPtr );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t\tstatus = preEnvelopeSign( envelopeInfoPtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Couldn't perform final %s initialisation prior to \"\n\t\t\t\t  \"enveloping data\", \n\t\t\t\t  ( envelopeInfoPtr->usage == ACTION_SIGN ) ? \\\n\t\t\t\t\t\"signing\" : \"encryption\" ) );\n\t\t}\n\n\t/* If we're performing authenticated encryption, create the hash object \n\t   that's used to sort-of-MAC the data */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\t\tCRYPT_CONTEXT iHashContext;\n\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiHashContext = createInfo.cryptHandle;\n\t\tstatus = addAction( envelopeInfoPtr, ACTION_HASH, iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\n\t\t/* Since the MDC packet is tacked onto the end of the payload, we \n\t\t   need to increase the effect data size by the size of the MDC\n\t\t   packet data */\n\t\tenvelopeInfoPtr->segmentSize += PGP_MDC_PACKET_SIZE;\n\t\t}\n\n\t/* Delete any orphaned actions such as automatically-added hash actions \n\t   that were overridden with user-supplied alternate actions */\n\tstatus = deleteUnusedActions( envelopeInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( checkActions( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTrailer Processing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process an MDC packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emitMDC( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\tCRYPT_CONTEXT iMdcContext;\n\tACTION_LIST *actionListPtr;\n\tMESSAGE_DATA msgData;\n\tBYTE mdcBuffer[ 2 + CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t/* Make sure that there's enough room left to emit the MDC packet */\n\tif( envelopeInfoPtr->bufSize - \\\n\t\t\tenvelopeInfoPtr->bufPos < PGP_MDC_PACKET_SIZE )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Hash the trailer bytes (the start of the MDC packet, 0xD3 0x14) and \n\t   wrap up the hashing */\n\tactionListPtr = findAction( envelopeInfoPtr, ACTION_HASH );\n\tENSURES( actionListPtr != NULL );\n\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\tiMdcContext = actionListPtr->iCryptHandle;\n\tINJECT_FAULT( BADSIG_DATA, ENVELOPE_BADSIG_DATA_PGP_1 );\n\tstatus = krnlSendMessage( iMdcContext, IMESSAGE_CTX_HASH, \"\\xD3\\x14\", 2 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iMdcContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCLEAR_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_HASHACTIONSACTIVE );\n\n\t/* Append the MDC packet to the payload data */\n\tmemcpy( mdcBuffer, \"\\xD3\\x14\", 2 );\n\tsetMessageData( &msgData, mdcBuffer + 2, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iMdcContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tINJECT_FAULT( BADSIG_HASH, ENVELOPE_BADSIG_HASH_PGP_1 );\n\treturn( copyToEnvelopeFunction( envelopeInfoPtr, mdcBuffer, \n\t\t\t\t\t\t\t\t\tPGP_MDC_PACKET_SIZE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEmit Envelope Preamble/Postamble\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Output as much of the preamble as possible into the envelope buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emitPreamble( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t/* If we've finished processing the header information, don't do\n\t   anything */\n\tif( envelopeInfoPtr->envState == ENVSTATE_DONE )\n\t\treturn( CRYPT_OK );\n\n\t/* If we haven't started doing anything yet, perform various final\n\t   initialisations */\n\tif( envelopeInfoPtr->envState == ENVSTATE_NONE )\n\t\t{\n\t\tstatus = preEnvelopeInit( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* We're ready to go, prepare to emit the outer header */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_HEADER;\n\t\t}\n\n\t/* Emit the outer header.  This always follows directly from the final\n\t   initialisation step but we keep the two logically distinct to \n\t   emphasise the fact that the former is merely finalising enveloping \n\t   actions without performing any header processing while the latter is \n\t   the first stage that actually emits header data */\n\tif( envelopeInfoPtr->envState == ENVSTATE_HEADER )\n\t\t{\n\t\tstatus = writeHeaderPacket( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't create envelope header\" ) );\n\t\t\t}\n\t\tENSURES( envelopeInfoPtr->envState != ENVSTATE_HEADER );\n\t\t}\n\n\t/* Handle key export actions */\n\tif( envelopeInfoPtr->envState == ENVSTATE_KEYINFO )\n\t\t{\n\t\tstatus = writeKeyex( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit key exchange actions to envelope \"\n\t\t\t\t\t  \"header\" ) );\n\t\t\t}\n\n\t\t/* Move on to the next state */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_ENCRINFO;\n\t\t}\n\n\t/* Handle encrypted content information */\n\tif( envelopeInfoPtr->envState == ENVSTATE_ENCRINFO )\n\t\t{\n\t\t/* Write the encrypted content header */\n\t\tstatus = writeEncryptedContentHeader( envelopeInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit encrypted content header to envelope \"\n\t\t\t\t\t  \"header\" ) );\n\t\t\t}\n\n\t\t/* Make sure that we start a new segment if we try to add any data */\n\t\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_SEGMENTCOMPLETE );\n\n\t\t/* If the content type is plain data then we have to push in the \n\t\t   inner data header before we exit */\n\t\tif( envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )\n\t\t\tenvelopeInfoPtr->envState = ENVSTATE_DATA;\n\t\telse\n\t\t\t{\n\t\t\t/* We've processed the header, if this is signed data then we \n\t\t\t   start hashing from this point.  The PGP RFCs are wrong in \n\t\t\t   this regard in that only the payload is hashed and not the \n\t\t\t   entire packet */\n\t\t\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t\t\t{\n\t\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\t\t\t}\n\n\t\t\t/* We're finished */\n\t\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\t\t\t}\n\t\t}\n\n\t/* Handle data payload information */\n\tif( envelopeInfoPtr->envState == ENVSTATE_DATA )\n\t\t{\n\t\tSTREAM stream;\n\t\tBYTE headerBuffer[ 64 + 8 ];\n\n\t\t/* Make sure that there's enough room to emit the data header (+8 \n\t\t   for slop space) */\n\t\tif( envelopeInfoPtr->bufPos + PGP_MAX_HEADER_SIZE + \\\n\t\t\t\tPGP_DATA_HEADER_SIZE + 8 >= envelopeInfoPtr->bufSize )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t/* Write the payload header.  Since this may be encrypted we have to\n\t\t   do it indirectly via copyToEnvelope() */\n\t\tsMemOpen( &stream, headerBuffer, 64 );\n\t\tstatus = pgpWritePacketHeader( &stream, PGP_PACKET_DATA, \n\t\t\t\t\t\tPGP_DATA_HEADER_SIZE + envelopeInfoPtr->payloadSize );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = swrite( &stream, PGP_DATA_HEADER, PGP_DATA_HEADER_SIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* Adjust the running total count by the size of the additional \n\t\t\t   header that's been prepended and copy the header to the\n\t\t\t   envelope */\n\t\t\tenvelopeInfoPtr->segmentSize += stell( &stream );\n\t\t\tstatus = copyToEnvelopeFunction( envelopeInfoPtr, headerBuffer, \n\t\t\t\t\t\t\t\t\t\t\t stell( &stream ) );\n\t\t\t}\n\t\tsMemClose( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't emit data header into envelope header\" ) );\n\t\t\t}\n\n\t\t/* We've processed the header, if this is signed data then we start \n\t\t   hashing from this point.  The PGP RFCs are wrong in this regard \n\t\t   in that only the payload is hashed and not the entire packet */\n\t\tif( envelopeInfoPtr->usage == ACTION_SIGN )\n\t\t\t{\n\t\t\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t\t\t  ENVDATA_FLAG_HASHACTIONSACTIVE );\n\t\t\t}\n\n\t\t/* We're finished */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\t\t}\n\n\t/* If we're processing a nested content-type that isn't plain data, \n\t   temporarily enable an alternate processing function that deals with \n\t   PGP's way of handling this */\n\tif( envelopeInfoPtr->contentType != CRYPT_CONTENT_DATA )\n\t\t{\n\t\tFNPTR_SET( envelopeInfoPtr->copyToEnvelopeFunction, \n\t\t\t\t   copyToEnvelopeAlt );\n\t\t}\n\n\tENSURES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Output as much of the postamble as possible into the envelope buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emitPostamble( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  STDC_UNUSED const BOOLEAN dummy )\n\t{\n\tconst ACTION_LIST *postActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList );\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tSIGPARAMS sigParams;\n\tint sigBufSize, sigSize, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\n\t/* Before we can emit the trailer we need to flush any remaining data\n\t   from internal buffers */\n\tif( envelopeInfoPtr->envState == ENVSTATE_NONE )\n\t\t{\n\t\tconst ENV_COPYTOENVELOPE_FUNCTION copyToEnvelopeFunction = \\\n\t\t\t\t\t( ENV_COPYTOENVELOPE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( envelopeInfoPtr->copyToEnvelopeFunction );\n\n\t\tREQUIRES( copyToEnvelopeFunction != NULL );\n\n\t\t/* If we're using MDC encryption, append the MDC packet to the \n\t\t   payload data */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t{\n\t\t\tstatus = emitMDC( envelopeInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Flush the data through */\n\t\tstatus = copyToEnvelopeFunction( envelopeInfoPtr, NULL, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t  \"Couldn't flush remaining data into envelope \"\n\t\t\t\t\t  \"buffer\" ) );\n\t\t\t}\n\t\tenvelopeInfoPtr->envState = ENVSTATE_FLUSHED;\n\t\t}\n\n\t/* The only PGP packet that has a trailer is signed data using the new\n\t   (post-2.x) one-pass signature packet, if we're not signing data we can\n\t   exit now */\n\tif( envelopeInfoPtr->usage != ACTION_SIGN )\n\t\t{\n\t\t/* We're done */\n\t\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\t\tENSURES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( postActionListPtr != NULL );\n\n\t/* Check whether there's enough room left in the buffer to emit the \n\t   signature directly into it.  Since signatures are fairly small (a few \n\t   hundred bytes) we always require enough room in the buffer and don't \n\t   bother with any overflow handling via the auxBuffer */\n\tsigBufSize = min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos, \n\t\t\t\t\t  MAX_INTLENGTH_SHORT - 1 );\n\tif( postActionListPtr->encodedSize + 64 > sigBufSize )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Sign the data */\n\tinitSigParamsPGP( &sigParams, PGP_SIG_DATA, NULL, 0 );\n\tstatus = iCryptCreateSignature( envelopeInfoPtr->buffer + \\\n\t\t\t\t\t\tenvelopeInfoPtr->bufPos, sigBufSize, &sigSize, \n\t\t\t\t\t\tCRYPT_FORMAT_PGP, postActionListPtr->iCryptHandle, \n\t\t\t\t\t\tactionListPtr->iCryptHandle, &sigParams );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Couldn't emit signature to envelope trailer\" ) );\n\t\t}\n\tenvelopeInfoPtr->bufPos += sigSize;\n\n\t/* Now that we've written the final data, set the end-of-segment-data \n\t   pointer to the end of the data in the buffer so that \n\t   copyFromEnvelope() can copy out the remaining data */\n\tenvelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;\n\tenvelopeInfoPtr->envState = ENVSTATE_DONE;\n\n\tENSURES( sanityCheckPGPEnv( envelopeInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initPGPEnveloping( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tint algorithm, dummy, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_V( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->processPreambleFunction, emitPreamble );\n\tFNPTR_SET( envelopeInfoPtr->processPostambleFunction, emitPostamble );\n\tFNPTR_SET( envelopeInfoPtr->checkAlgoFunction, pgpCheckAlgo );\n\n\t/* Set up the processing state information */\n\tenvelopeInfoPtr->envState = ENVSTATE_NONE;\n\n\t/* Remember the current default settings for use with the envelope.  \n\t   Since the PGP algorithms represent only a subset of what's available \n\t   we have to drop back to fixed values if the caller has selected \n\t   something exotic */\n\tstatus = krnlSendMessage( envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &algorithm, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_HASH );\n\tif( cryptStatusError( status ) || \\\n\t\tcryptStatusError( cryptlibToPgpAlgo( algorithm, &dummy ) ) )\n\t\tenvelopeInfoPtr->defaultHash = CRYPT_ALGO_SHA1;\n\telse\n\t\tenvelopeInfoPtr->defaultHash = algorithm;\t/* int vs.enum */\n\tstatus = krnlSendMessage( envelopeInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &algorithm, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_ALGO );\n\tif( cryptStatusError( status ) || \\\n\t\tcryptStatusError( cryptlibToPgpAlgo( algorithm, &dummy ) ) )\n\t\tenvelopeInfoPtr->defaultAlgo = CRYPT_ALGO_AES;\n\telse\n\t\tenvelopeInfoPtr->defaultAlgo = algorithm;\t/* int vs.enum */\n\tenvelopeInfoPtr->defaultMAC = CRYPT_ALGO_NONE;\n\n\t/* Turn off segmentation of the envelope payload.  PGP has a single \n\t   length at the start of the data and doesn't segment the payload */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, ENVDATA_FLAG_NOSEGMENT );\n\t}\n#endif /* USE_PGP */\n"
  },
  {
    "path": "deps/cl345/envelope/res_actn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Envelope Action Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"envelope.h\"\n#else\n  #include \"envelope/envelope.h\"\n#endif /* Compiler-specific includes */\n\n/* The maximum number of actions that we can add to an action list */\n\n#define MAX_ACTIONS\t\tFAILSAFE_ITERATIONS_MED - 1\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFind an Action\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check an action-list entry */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckActionList( IN const ACTION_LIST *actionListPtr )\n\t{\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\t/* Check overall action list data */\n\tif( !isEnumRange( actionListPtr->action, ACTION ) || \\\n\t\t!CHECK_FLAGS( actionListPtr->flags, ACTION_FLAG_NONE, \n\t\t\t\t\t  ACTION_FLAG_MAX ) || \\\n\t\t( actionListPtr->encodedSize != CRYPT_UNUSED && \\\n\t\t  !isShortIntegerRange( actionListPtr->encodedSize ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckActionList: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers.  We don't have to check the function pointers\n\t   because they're validated each time they're dereferenced */\n\tif( !DATAPTR_ISVALID( actionListPtr->next ) || \\\n\t\t!DATAPTR_ISVALID( actionListPtr->associatedAction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckActionList: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check object handles */\n\tif( ( actionListPtr->iCryptHandle != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( actionListPtr->iCryptHandle ) ) || \\\n\t\t( actionListPtr->iExtraData != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( actionListPtr->iExtraData ) ) || \\\n\t\t( actionListPtr->iTspSession != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( actionListPtr->iTspSession ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckActionList: Object handles\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Find an action of a given type and the last action of a given type.\n   Since the lists are sorted by action type, the generic findAction()\n   finds the start of an action group.\n   \n   The casting to a non-const is a bit ugly but is necessitated by the fact \n   that while the functions don't change the action list entries, the caller \n   will */\n\nCHECK_RETVAL_PTR \\\nstatic ACTION_LIST *findActionEx( IN const ACTION_LIST *actionListPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES_N( actionType == ACTION_KEYEXCHANGE_PKC || \\\n\t\t\t\tactionType == ACTION_KEYEXCHANGE || \\\n\t\t\t\tactionType == ACTION_xxx || \\\n\t\t\t\tactionType == ACTION_CRYPT || \\\n\t\t\t\tactionType == ACTION_MAC || \\\n\t\t\t\tactionType == ACTION_HASH || \\\n\t\t\t\tactionType == ACTION_SIGN );\n\n\tLOOP_MED_CHECKINC( actionListPtr != NULL,\n\t\t\t\t\t   actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tif( actionListPtr->action == actionType )\n\t\t\treturn( ( ACTION_LIST * ) actionListPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findPreAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->preActionList );\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_N( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\tif( actionListPtr == NULL )\n\t\treturn( NULL );\n\n\treturn( findActionEx( actionListPtr, actionType ) );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_N( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\tif( actionListPtr == NULL )\n\t\treturn( NULL );\n\n\treturn( findActionEx( actionListPtr, actionType ) );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findPostAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList );\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_N( DATAPTR_ISVALID( envelopeInfoPtr->postActionList ) );\n\tif( actionListPtr == NULL )\n\t\treturn( NULL );\n\n\treturn( findActionEx( actionListPtr, actionType ) );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findLastAction( IN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tconst ACTION_LIST *actionListPtr, *prevActionPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_N( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES_N( actionType == ACTION_HASH || \\\n\t\t\t\tactionType == ACTION_SIGN );\n\n\t/* Get the appropriate action list for this action.  Since there are \n\t   only two actions that we can look for, both related to signing, the \n\t   action list to use can be inferred from the action type */\n\tif( actionType == ACTION_HASH )\n\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\telse\n\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->postActionList );\n\tif( actionListPtr == NULL )\n\t\treturn( NULL );\n\tENSURES_N( sanityCheckActionList( actionListPtr ) );\n\n\t/* Find the start of the action group */\n\tactionListPtr = findActionEx( actionListPtr, actionType );\n\tif( actionListPtr == NULL )\n\t\treturn( NULL );\n\tENSURES_N( sanityCheckActionList( actionListPtr ) );\n\n\t/* Find the end of the action group */\n\tLOOP_MED( prevActionPtr = actionListPtr,\n\t\t\t  actionListPtr != NULL && actionListPtr->action == actionType,\n\t\t\t  ( prevActionPtr = actionListPtr, \n\t\t\t    actionListPtr = DATAPTR_GET( actionListPtr->next ) ) );\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( ( ACTION_LIST * ) prevActionPtr );\n\t}\n\n/* An indirect action-check function that uses a caller-supplied callback to \n   verify a match for an action */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nACTION_LIST *findActionIndirect( const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t\t\t IN CHECKACTION_FUNCTION checkActionFunction,\n\t\t\t\t\t\t\t\t IN_INT_Z const int intParam )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( actionListStart, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES_N( checkActionFunction != NULL );\n\n\tLOOP_MED( actionListPtr = actionListStart, actionListPtr != NULL,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tint status;\n\t\t\n\t\tREQUIRES_N( sanityCheckActionList( actionListPtr ) );\n\t\t \n\t\tstatus = checkActionFunction( actionListPtr, intParam );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( ( ACTION_LIST * ) actionListPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd/Delete an Action\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether more actions can be added to an action list */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN moreActionsPossible( IN_OPT const ACTION_LIST *actionListPtr )\n\t{\n\tint actionCount, LOOP_ITERATOR;\n\n\tassert( actionListPtr == NULL || \\\n\t\t\tisReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tLOOP_MED( actionCount = 0,\n\t\t\t  actionListPtr != NULL && actionCount < MAX_ACTIONS,\n\t\t\t  ( actionListPtr = DATAPTR_GET( actionListPtr->next ), actionCount++ ) );\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( ( actionCount < MAX_ACTIONS ) ? TRUE : FALSE );\n\t}\n\n/* Add a new action to the end of an action group in an action list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int createNewAction( OUT_OPT_PTR_COND ACTION_LIST **newActionPtrPtr,\n\t\t\t\t\t\t\tINOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( ACTIONLIST ) \\\n\t\t\t\t\t\t\t\tconst ACTIONLIST_TYPE actionListType,\n\t\t\t\t\t\t\tIN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle )\t\t\t\t\t\t\t\n\t{\n\tACTION_LIST *actionListPtr, *prevActionPtr = NULL, *newItem;\n\tint LOOP_ITERATOR;\n\n\tassert( newActionPtrPtr == NULL || \\\n\t\t\tisWritePtr( newActionPtrPtr, sizeof( ACTION_LIST * ) ) );\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isEnumRange( actionListType, ACTIONLIST ) );\n\tREQUIRES( actionType == ACTION_KEYEXCHANGE_PKC || \\\n\t\t\t  actionType == ACTION_KEYEXCHANGE || \\\n\t\t\t  actionType == ACTION_xxx || \\\n\t\t\t  actionType == ACTION_CRYPT || \\\n\t\t\t  actionType == ACTION_MAC || \\\n\t\t\t  actionType == ACTION_HASH || \\\n\t\t\t  actionType == ACTION_SIGN );\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\n\t/* Clear return value */\n\tif( newActionPtrPtr != NULL )\n\t\t*newActionPtrPtr = NULL;\n\n\t/* Get the appropriate action list */\n\tswitch( actionListType )\n\t\t{\n\t\tcase ACTIONLIST_PREACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->preActionList );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_ACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_POSTACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->postActionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->postActionList );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Create the new action list item */\n\tif( ( newItem = getMemPool( envelopeInfoPtr->memPoolState, \\\n\t\t\t\t\t\t\t\tsizeof( ACTION_LIST ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( newItem, 0, sizeof( ACTION_LIST ) );\n\tnewItem->action = actionType;\n\tINIT_FLAGS( newItem->flags, ACTION_FLAG_NONE );\n\tnewItem->iCryptHandle = cryptHandle;\n\tnewItem->iExtraData = CRYPT_ERROR;\n\tnewItem->iTspSession = CRYPT_ERROR;\n\tDATAPTR_SET( newItem->associatedAction, NULL );\n\tDATAPTR_SET( newItem->next, NULL );\n\tENSURES( sanityCheckActionList( newItem ) );\n\n\t/* Find the last action in the action group */\n\tLOOP_MED_CHECKINC( actionListPtr != NULL && \\\n\t\t\t\t\t\t\tactionListPtr->action <= actionType,\n\t\t\t\t\t   actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tprevActionPtr = actionListPtr;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Append the new action to the appropriate action list */\n\tswitch( actionListType )\n\t\t{\n\t\tcase ACTIONLIST_PREACTION:\n\t\t\tinsertSingleListElement( envelopeInfoPtr->preActionList, \n\t\t\t\t\t\t\t\t\t prevActionPtr, newItem, ACTION_LIST );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_ACTION:\n\t\t\tinsertSingleListElement( envelopeInfoPtr->actionList, \n\t\t\t\t\t\t\t\t\t prevActionPtr, newItem, ACTION_LIST );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_POSTACTION:\n\t\t\tinsertSingleListElement( envelopeInfoPtr->postActionList, \n\t\t\t\t\t\t\t\t\t prevActionPtr, newItem, ACTION_LIST );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( newActionPtrPtr != NULL )\n\t\t*newActionPtrPtr = newItem;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addActionEx( OUT_OPT_PTR_COND ACTION_LIST **newActionPtrPtr,\n\t\t\t\t INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t IN_ENUM( ACTIONLIST ) const ACTIONLIST_TYPE actionListType,\n\t\t\t\t IN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tassert( isWritePtr( newActionPtrPtr, sizeof( ACTION_LIST * ) ) );\n\t\t/* Rest are checked in createNewAction() */\n\n\treturn( createNewAction( newActionPtrPtr, envelopeInfoPtr, \n\t\t\t\t\t\t\t actionListType, actionType, cryptHandle ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t   IN_ENUM( ACTION ) const ACTION_TYPE actionType,\n\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\treturn( createNewAction( NULL, envelopeInfoPtr, ACTIONLIST_ACTION, \n\t\t\t\t\t\t\t actionType, cryptHandle ) );\n\t}\n\n/* Replace a context in an action with a different one, used to update an\n   existing action when circumstances change */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint replaceAction( INOUT ACTION_LIST *actionListItem,\n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tassert( isWritePtr( actionListItem, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( actionListItem->iCryptHandle != CRYPT_ERROR && \\\n\t\t\t  actionListItem->iExtraData == CRYPT_ERROR && \\\n\t\t\t  actionListItem->iTspSession == CRYPT_ERROR );\n\tREQUIRES( sanityCheckActionList( actionListItem ) );\n\n\t/* Delete the existing action context and replace it with the new one */\n\tkrnlSendNotifier( actionListItem->iCryptHandle, IMESSAGE_DECREFCOUNT );\n\tactionListItem->iCryptHandle = cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete an action from an action list */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void deleteActionListItem( INOUT MEMPOOL_STATE memPoolState,\n\t\t\t\t\t\t\t\t  INOUT ACTION_LIST *actionListItem )\n\t{\n\tassert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );\n\tassert( isWritePtr( actionListItem, sizeof( ACTION_LIST ) ) );\n\n\t/* Destroy any attached objects and information if necessary and\n\t   clear the list item memory */\n\tif( actionListItem->iCryptHandle != CRYPT_ERROR )\n\t\tkrnlSendNotifier( actionListItem->iCryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( actionListItem->iExtraData != CRYPT_ERROR )\n\t\tkrnlSendNotifier( actionListItem->iExtraData, IMESSAGE_DECREFCOUNT );\n\tif( actionListItem->iTspSession != CRYPT_ERROR )\n\t\tkrnlSendNotifier( actionListItem->iTspSession, IMESSAGE_DECREFCOUNT );\n\tzeroise( actionListItem, sizeof( ACTION_LIST ) );\n\tfreeMemPool( memPoolState, actionListItem );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int deleteAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,\t\n\t\t\t\t\t\t INOUT ACTION_LIST *actionListItem )\n\t{\n\tACTION_LIST *listPrevPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( actionListItem, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES( listPrevPtr != NULL );\n\n\t/* Find the previons entry in the list */\n\tLOOP_MED_CHECKINC( listPrevPtr != NULL && \\\n\t\t\t\t\t\t\tDATAPTR_GET( listPrevPtr->next ) != actionListItem,\n\t\t\t\t\t   listPrevPtr = DATAPTR_GET( listPrevPtr->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Remove the item from the list */\n\tdeleteSingleListElement( envelopeInfoPtr->actionList, listPrevPtr, \n\t\t\t\t\t\t\t actionListItem, ACTION_LIST );\n\n\t/* Clear all data in the list item and free the memory */\n\tdeleteActionListItem( envelopeInfoPtr->memPoolState, actionListItem );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete the action lists */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void deleteActionList( INOUT MEMPOOL_STATE memPoolState,\n\t\t\t\t\t\t\t  INOUT ACTION_LIST *actionListPtr )\n\t{\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tLOOP_MED_CHECK( actionListPtr != NULL )\n\t\t{\n\t\tACTION_LIST *actionListItem = actionListPtr;\n\n\t\tREQUIRES_V( DATAPTR_ISVALID( actionListPtr->next ) );\n\t\tactionListPtr = DATAPTR_GET( actionListPtr->next );\n\t\tdeleteActionListItem( memPoolState, actionListItem );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteActionLists( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *actionListPtr;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckEnvelope( envelopeInfoPtr ) );\n\n\tREQUIRES_V( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\tif( ( actionListPtr = \\\n\t\t\t\tDATAPTR_GET( envelopeInfoPtr->preActionList ) ) != NULL )\n\t\t{\n\t\tdeleteActionList( envelopeInfoPtr->memPoolState, actionListPtr );\n\t\tDATAPTR_SET( envelopeInfoPtr->preActionList, NULL );\n\t\t}\n\tREQUIRES_V( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\tif( ( actionListPtr = \\\n\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList ) ) != NULL )\n\t\t{\n\t\tdeleteActionList( envelopeInfoPtr->memPoolState, actionListPtr );\n\t\tDATAPTR_SET( envelopeInfoPtr->actionList, NULL );\n\t\t}\n\tREQUIRES_V( DATAPTR_ISVALID( envelopeInfoPtr->postActionList ) );\n\tif( ( actionListPtr = \\\n\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList ) ) != NULL )\n\t\t{\n\t\tdeleteActionList( envelopeInfoPtr->memPoolState, actionListPtr );\n\t\tDATAPTR_SET( envelopeInfoPtr->postActionList, NULL );\n\t\t}\n\t}\n\n/* Delete any orphaned actions, for example automatically-added hash actions\n   that were overridden by user-supplied alternate actions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteUnusedActions( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tACTION_LIST *actionListPtr;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\n\t/* Check for unattached encryption, hash/MAC, or generic-secret actions \n\t   and delete them */\n\tLOOP_MED_INITCHECK( actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ), \n\t\t\t\t\t\tactionListPtr != NULL )\n\t\t{\n\t\tACTION_LIST *actionListCurrent = actionListPtr;\n\n\t\tREQUIRES( DATAPTR_ISVALID( actionListPtr->next ) );\n\t\tactionListPtr = DATAPTR_GET( actionListPtr->next );\n\t\tif( ( actionListCurrent->action == ACTION_CRYPT || \\\n\t\t\t  actionListCurrent->action == ACTION_HASH || \\\n\t\t\t  actionListCurrent->action == ACTION_MAC || \\\n\t\t\t  actionListCurrent->action == ACTION_xxx ) && \\\n\t\t\tTEST_FLAG( actionListCurrent->flags, \n\t\t\t\t\t   ACTION_FLAG_NEEDSCONTROLLER ) )\n\t\t\t{\n\t\t\tstatus = deleteAction( envelopeInfoPtr, actionListCurrent );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck an Action\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a new action to make sure that it isn't already present in the\n   action list, producing an ACTION_RESULT outcome */\n\nCHECK_RETVAL_ENUM( ACTION ) \\\nACTION_RESULT checkAction( IN_OPT const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t   IN_ENUM( ACTION ) const ACTION_TYPE actionType, \n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tACTION_LIST *actionListPtr = ( ACTION_LIST * ) actionListStart;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ KEYID_SIZE + 8 ];\n\tint algorithm DUMMY_INIT, status, LOOP_ITERATOR;\n\n\tassert( actionListPtr == NULL || \\\n\t\t\tisReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES_EXT( actionListPtr == NULL || \\\n\t\t\t\t  sanityCheckActionList( actionListPtr ), \n\t\t\t\t  ACTION_RESULT_ERROR );\n\tREQUIRES_EXT( ( actionType == ACTION_KEYEXCHANGE_PKC || \\\n\t\t\t\t\tactionType == ACTION_KEYEXCHANGE || \\\n\t\t\t\t\tactionType == ACTION_CRYPT || \\\n\t\t\t\t\tactionType == ACTION_MAC || \\\n\t\t\t\t\tactionType == ACTION_HASH || \\\n\t\t\t\t\tactionType == ACTION_SIGN ), ACTION_RESULT_ERROR );\n\tREQUIRES_EXT( isHandleRangeValid( cryptHandle ), ACTION_RESULT_ERROR );\n\n\t/* If the action list is empty, there's nothing to check */\n\tif( actionListPtr == NULL )\n\t\treturn( ACTION_RESULT_EMPTY );\n\n\t/* Get identification information for the action object */\n\tswitch( actionType )\n\t\t{\n\t\tcase ACTION_KEYEXCHANGE:\n\t\t\t/* For conventional key wrap we can't really do much, for raw\n\t\t\t   action objects we'd check the algorithm for duplicates but\n\t\t\t   it's perfectly valid to wrap a single session/MAC key using\n\t\t\t   multiple key wrap objects with the same algorithm */\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n\t\tcase ACTION_KEYEXCHANGE_PKC:\n\t\tcase ACTION_SIGN:\n\t\t\t/* It's a PKC object, get the key ID */\n\t\t\tsetMessageData( &msgData, keyID, KEYID_SIZE );\n\t\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\t\tbreak;\n\n\t\tcase ACTION_HASH:\n\t\tcase ACTION_MAC:\n\t\tcase ACTION_CRYPT:\n\t\t\t/* It's a raw action object, get the algorithm */\n\t\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Ext( ACTION_RESULT_ERROR );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( ACTION_RESULT_ERROR );\n\n\t/* Walk down the list from the first to the last action in the action\n\t   group checking each one in turn */\n\tLOOP_MED( actionListPtr = findActionEx( actionListPtr, actionType ), \n\t\t\t  actionListPtr != NULL && actionListPtr->action == actionType,\n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tBOOLEAN isDuplicate = FALSE;\n\t\tint actionAlgo;\n\n\t\tREQUIRES_EXT( actionListPtr == NULL || \\\n\t\t\t\t\t  sanityCheckActionList( actionListPtr ), \n\t\t\t\t\t  ACTION_RESULT_ERROR );\n\n\t\t/* Make sure that we haven't added this action already.  This can\n\t\t   get a bit tricky both because detecting some types of duplicates\n\t\t   is rather hard and because the definition of what's an invalid\n\t\t   duplicate varies somewhat.  For a hash, MAC, and encryption\n\t\t   action we only allow one action of a given algorithm type to\n\t\t   be added.  For a PKC key exchange or signature action we only\n\t\t   allow one action for a given key to be added.  For a conventional\n\t\t   key exchange action we should in theory check for duplicates in\n\t\t   some form but it's not certain what constitutes a duplicate (for\n\t\t   example are two otherwise identical actions with a different\n\t\t   number of key setup iterations considered duplicates or not?) so\n\t\t   for now we assume that the user won't do anything silly (in any \n\t\t   case for any key exchange action the only thing that a duplicate \n\t\t   will do is result in unnecessary bloating of the envelope \n\t\t   header).\n\n\t\t   In addition to the more sophisticated checks we also perform a \n\t\t   few more basic ones for the same object being added twice, which\n\t\t   doesn't catch e.g. inadvertent use of the same keying material\n\t\t   but does catch simple programming errors */\n\t\tif( actionListPtr->iCryptHandle == cryptHandle )\n\t\t\treturn( ACTION_RESULT_INITED );\n\t\tswitch( actionType )\n\t\t\t{\n\t\t\tcase ACTION_KEYEXCHANGE:\n\t\t\t\t/* It's a conventional key exchange, there's not much that\n\t\t\t\t   we can check */\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_KEYEXCHANGE_PKC:\n\t\t\tcase ACTION_SIGN:\n\t\t\t\t/* It's a PKC key exchange or signature action, compare the\n\t\t\t\t   two objects by comparing their keys */\n\t\t\t\tsetMessageData( &msgData, keyID, KEYID_SIZE );\n\t\t\t\tif( cryptStatusOK( \\\n\t\t\t\t\t\tkrnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\t IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_KEYID ) ) )\n\t\t\t\t\tisDuplicate = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase ACTION_HASH:\n\t\t\tcase ACTION_MAC:\n\t\t\tcase ACTION_CRYPT:\n\t\t\t\t/* It's a hash/MAC or session key object, compare the two\n\t\t\t\t   objects by comparing their algorithms */\n\t\t\t\tif( cryptStatusOK( \\\n\t\t\t\t\tkrnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE, &actionAlgo,\n\t\t\t\t\t\t\t\t\t CRYPT_CTXINFO_ALGO ) ) && \\\n\t\t\t\t\tactionAlgo == algorithm )\n\t\t\t\t\tisDuplicate = TRUE;\n\t\t\t\tbreak;\n\n\t\t\t}\n\t\tif( isDuplicate )\n\t\t\t{\n\t\t\t/* If the action was added automatically/implicitly as the\n\t\t\t   result of adding another action then the first attempt to add\n\t\t\t   it explicitly by the caller isn't an error.  The caller will\n\t\t\t   treat the ACTION_RESULT_PRESENT code as CRYPT_OK */\n\t\t\tif( TEST_FLAG( actionListPtr->flags, \n\t\t\t\t\t\t   ACTION_FLAG_ADDEDAUTOMATICALLY ) )\n\t\t\t\t{\n\t\t\t\tCLEAR_FLAG( actionListPtr->flags, \n\t\t\t\t\t\t\tACTION_FLAG_ADDEDAUTOMATICALLY );\n\t\t\t\treturn( ACTION_RESULT_PRESENT );\n\t\t\t\t}\n\n\t\t\treturn( ACTION_RESULT_INITED );\n\t\t\t}\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, ACTION_RESULT_ERROR );\n\n\treturn( ACTION_RESULT_OK );\n\t}\n\n/* An indirect action-check function that uses a caller-supplied callback to \n   verify each action */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkActionIndirect( IN const ACTION_LIST *actionListStart,\n\t\t\t\t\t\t IN CHECKACTION_FUNCTION checkActionFunction,\n\t\t\t\t\t\t IN_INT_Z const int intParam )\n\t{\n\tconst ACTION_LIST *actionListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( actionListStart, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES( sanityCheckActionList( actionListStart ) );\n\tREQUIRES( checkActionFunction != NULL );\n\n\tLOOP_MED( actionListPtr = actionListStart, actionListPtr != NULL, \n\t\t\t  actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t{\n\t\tint status;\n\n\t\tREQUIRES( sanityCheckActionList( actionListPtr ) );\n\n\t\tstatus = checkActionFunction( actionListPtr, intParam );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check that the actions in an envelope are consistent.  There are two \n   approaches to this, take the envelope usage and check that everything is \n   consistent with it, or take the actions and make sure that they're \n   consistent with the usage (and each other).  We perform the latter type \n   of check, which is somewhat simpler.  The requirements that we enforce \n   are:\n\n\t\t\t|\tPre\t\t|\tIn\t\t|\tPost\t|\n\t--------+-----------+-----------+-----------+-----\n\t  SIG\t|\t  -\t\t|\tHash\t|\t Sig\t| CMS\n\t\t\t|\t  -\t\t| 1x Hash\t|  1x Sig\t| PGP\n\t--------+-----------+-----------+-----------+-----\n\t  MAC\t| Keyex,PKC\t|  1x MAC\t|\t  -\t\t| CMS\n\t\t\t|\t  -\t\t|\t  -\t\t|\t  -\t\t| PGP\n\t--------+-----------+-----------+-----------+-----\n\t  COPR\t|\t  -\t\t|\t  -\t\t|\t  -\t\t| CMS\n\t\t\t|\t  -\t\t|\t  -\t\t|\t  -\t\t| PGP\n\t--------+-----------+-----------+-----------+-----\n\t  ENCR\t| Keyex,PKC\t|\tCrypt\t|\t  -\t\t| CMS\n\t\t\t|\t PKC\t| 1x Crypt\t|\t  -\t\t| PGP\n\n   In the case of ENCR the pre-actions can be absent if we're using raw \n   session-key encryption */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkActions( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tconst ACTION_LIST *preActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->preActionList );\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tconst ACTION_LIST *postActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList );\n\tconst ACTION_LIST *actionListCursor, *actionListPtrNext;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckEnvelope( envelopeInfoPtr ) );\n\n\t/* If there are no pre-, post-, or main actions (i.e. it's a compressed\n\t   or data-only envelope), we're done */\n\tif( actionListPtr == NULL )\n\t\t{\n\t\t/* Make sure that the envelope has the appropriate usage for these \n\t\t   actions */\n\t\tif( envelopeInfoPtr->usage != ACTION_COMPRESS && \\\n\t\t\tenvelopeInfoPtr->usage != ACTION_NONE )\n\t\t\treturn( FALSE );\n\n\t\t/* There can be no pre- or post-actions present for this usage */\n\t\tif( preActionListPtr != NULL || postActionListPtr != NULL )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\tREQUIRES_B( DATAPTR_ISVALID( actionListPtr->next ) );\n\tactionListPtrNext = DATAPTR_GET( actionListPtr->next );\n\tREQUIRES_B( actionListPtrNext == NULL || \\\n\t\t\t\tsanityCheckActionList( actionListPtrNext ) );\n\n\t/* If there are pre-actions it has to be a key exchange followed by \n\t   encryption or MAC actions */\n\tif( preActionListPtr != NULL )\n\t\t{\n\t\tint cryptActionCount = 0, macActionCount = 0;\n\t\tint genericSecretActionCount = 0;\n\n\t\t/* Make sure that the envelope has the appropriate usage for these \n\t\t   actions */\n\t\tif( envelopeInfoPtr->usage != ACTION_CRYPT && \\\n\t\t\tenvelopeInfoPtr->usage != ACTION_MAC )\n\t\t\treturn( FALSE );\n\n\t\t/* If there's a pre-action then there has to be a main action \n\t\t   list.  This is checked by the actionListPtr check earlier so\n\t\t   there's no need to explicitly check it again here */\n\t\tENSURES_B( actionListPtr != NULL );\n\n\t\t/* Pre-actions can only be key exchange actions and have to be sorted \n\t\t   by action group */\n\t\tLOOP_MED( actionListCursor = preActionListPtr, \n\t\t\t\t  actionListCursor != NULL && \\\n\t\t\t\t\tactionListCursor->action == ACTION_KEYEXCHANGE_PKC,\n\t\t\t\t  actionListCursor = DATAPTR_GET( actionListCursor->next ) );\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\t\tactionListCursor != NULL )\n\t\t\t{\n\t\t\t/* PGP can't have any conventional keyex actions since the \n\t\t\t   password is used to directly derive the session key */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tLOOP_MED_CHECKINC( actionListCursor != NULL && \\\n\t\t\t\t\t\t\t\tactionListCursor->action == ACTION_KEYEXCHANGE,\n\t\t\t\t\t\t   actionListCursor = DATAPTR_GET( actionListCursor->next ) );\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\tif( actionListCursor != NULL )\n\t\t\treturn( FALSE );\n\n\t\t/* PGP only supports an encryption action followed by an optional \n\t\t   hash action for encryption with MDC */\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t\t{\n\t\t\tif( actionListPtr->action != ACTION_CRYPT )\n\t\t\t\treturn( FALSE );\n\t\t\tif( actionListPtrNext != NULL )\n\t\t\t\t{\n\t\t\t\tREQUIRES_B( DATAPTR_ISVALID( actionListPtrNext->next ) );\n\t\t\t\tif( actionListPtrNext->action != ACTION_HASH || \\\n\t\t\t\t\tDATAPTR_ISSET( actionListPtrNext->next ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* There can't be any post-actions */\n\t\t\tif( postActionListPtr != NULL )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* Key exchange must be followed by a single encryption, one or more \n\t\t   MAC actions, or a sequence of { generic-secret, encryption, MAC } \n\t\t   actions.  First we count the actions present */\n\t\tLOOP_MED( actionListCursor = actionListPtr, \n\t\t\t\t  actionListCursor != NULL,\n\t\t\t\t  actionListCursor = DATAPTR_GET( actionListCursor->next ) )\n\t\t\t{\n\t\t\tREQUIRES_B( sanityCheckActionList( actionListCursor ) );\n\n\t\t\tswitch( actionListCursor->action )\n\t\t\t\t{\n\t\t\t\tcase ACTION_xxx:\n\t\t\t\t\tgenericSecretActionCount++;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase ACTION_CRYPT:\n\t\t\t\t\tcryptActionCount++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ACTION_MAC:\n\t\t\t\t\tmacActionCount++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* Then we make sure that what's present follows the requirements \n\t\t   given above */\n\t\tif( genericSecretActionCount > 0 )\n\t\t\t{\n\t\t\t/* AuthEnc envelope, we need a sequence of { generic-secret, \n\t\t\t   encryption, MAC } */\n\t\t\tif( genericSecretActionCount != 1 || \\\n\t\t\t\tcryptActionCount != 1 || macActionCount != 1 )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( cryptActionCount > 0 )\n\t\t\t\t{\n\t\t\t\t/* Encrypted envelope, we need a single encryption action */\n\t\t\t\tif( cryptActionCount > 1 || \\\n\t\t\t\t\tgenericSecretActionCount != 0 || macActionCount != 0 )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* MACed envelope, we need one or more MAC actions (the check\n\t\t\t\t   for genericSecretActionCount is redudant since we already\n\t\t\t\t   know that it's 0, but it's included here to document the\n\t\t\t\t   required condition) */\n\t\t\t\tif( genericSecretActionCount != 0 || cryptActionCount != 0 )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* There can't be any post-actions */\n\t\tif( postActionListPtr != NULL )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If there are post-actions then it has to be a hash follwed by \n\t   signature actions */\n\tif( postActionListPtr != NULL )\n\t\t{\n\t\tint hashActionCount = 0, sigActionCount = 0;\n\n\t\t/* Make sure that the envelope has the appropriate usage for these \n\t\t   actions */\n\t\tif( envelopeInfoPtr->usage != ACTION_SIGN )\n\t\t\treturn( FALSE );\n\n\t\t/* If there's a post-action then there can't be a pre-action \n\t\t   list.  This is checked by the preActionListPtr check earlier so\n\t\t   there's no need to explicitly check it again here */\n\t\tENSURES_B( preActionListPtr == NULL );\n\n\t\t/* The signature must be preceded by one or more hash actions */\n\t\tLOOP_MED( actionListCursor = actionListPtr, \n\t\t\t\t  actionListCursor != NULL, \n\t\t\t\t  actionListCursor = DATAPTR_GET( actionListCursor->next ) )\n\t\t\t{\n\t\t\tREQUIRES_B( sanityCheckActionList( actionListCursor ) );\n\n\t\t\tif( actionListCursor->action != ACTION_HASH )\n\t\t\t\treturn( FALSE );\n\t\t\thashActionCount++;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* PGP can only have a single hash per signed envelope */\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && hashActionCount > 1 )\n\t\t\treturn( FALSE );\n\n\t\t/* Hash actions must be followed by one or more signature actions */\n\t\tLOOP_MED( actionListCursor = postActionListPtr, \n\t\t\t\t  actionListCursor != NULL,\n\t\t\t\t  actionListCursor = DATAPTR_GET( actionListCursor->next ) )\n\t\t\t{\n\t\t\tREQUIRES_B( sanityCheckActionList( actionListCursor ) );\n\n\t\t\tif( actionListCursor->action != ACTION_SIGN )\n\t\t\t\treturn( FALSE );\n\t\t\tsigActionCount++;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t/* PGP can only have a single signature, multiple signatures are \n\t\t   handled by nesting envelopes */\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && sigActionCount > 1 )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If there's a standalone session-key encryption action then it has to \n\t   be the only action present */\n\tif( actionListPtr->action == ACTION_CRYPT )\n\t\t{\n\t\t/* Make sure that the envelope has the appropriate usage for these \n\t\t   actions */\n\t\tif( envelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\treturn( FALSE );\n\n\t\t/* If we're performing authenticated encryption then the encryption\n\t\t   action has to be followed by a MAC action (CMS) or a hash action\n\t\t   (PGP, which is encrypted and sort-of keyed so it's a sort-of \n\t\t   MAC) */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) )\n\t\t\t{\n\t\t\tconst ACTION_TYPE requiredActionType = \\\n\t\t\t\t( envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\tACTION_HASH : ACTION_MAC;\n\n\t\t\tif( actionListPtrNext == NULL || \\\n\t\t\t\tactionListPtrNext->action != requiredActionType )\n\t\t\t\treturn( FALSE );\n\t\t\tREQUIRES_B( DATAPTR_ISVALID( actionListPtrNext->next ) );\n\t\t\tif( DATAPTR_ISSET( actionListPtrNext->next ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* PGP can optionally follow an encryption action with a hash action\n\t\t   for encryption with MDC */\n\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\t\tactionListPtrNext != NULL )\n\t\t\t{\n\t\t\tif( actionListPtrNext->action != ACTION_HASH )\n\t\t\t\treturn( FALSE );\n\t\t\tREQUIRES_B( DATAPTR_ISVALID( actionListPtrNext->next ) );\n\t\t\tif( DATAPTR_ISSET( actionListPtrNext->next ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* There can only be one encryption action present */\n\t\tif( actionListPtrNext != NULL )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If we're processing PGP-encrypted data with an MDC at the end of the \n\t   encrypted data then it's possible to have an encryption envelope with\n\t   a hash action (which must be followed by an encryption action) */\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\tactionListPtr->action == ACTION_HASH && \\\n\t\tactionListPtrNext != NULL && \\\n\t\tactionListPtrNext->action == ACTION_CRYPT )\n\t\t{\n\t\t/* Make sure that the envelope has the appropriate usage for these \n\t\t   actions */\n\t\tif( envelopeInfoPtr->usage != ACTION_CRYPT )\n\t\t\treturn( FALSE );\n\n\t\t/* Make sure that the encryption action is the only other action */\n\t\tif( actionListPtrNext->action != ACTION_CRYPT )\n\t\t\treturn( FALSE );\n\t\tREQUIRES_B( DATAPTR_ISVALID( actionListPtrNext->next ) );\n\t\tif( DATAPTR_ISSET( actionListPtrNext->next ) )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If it's a MACd envelope then there can only be a single MAC action \n\t   present */\n\tif( envelopeInfoPtr->usage == ACTION_MAC )\n\t\t{\n\t\t/* Make sure that there's only a single MAC action present */\n\t\tif( actionListPtr->action != ACTION_MAC || \\\n\t\t\tactionListPtrNext != NULL )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Anything else has to be a signing envelope */\n\tif( envelopeInfoPtr->usage != ACTION_SIGN )\n\t\treturn( FALSE );\n\n\t/* When we're de-enveloping a signed envelope we can have standalone\n\t   hash actions before we get to the signature data and add post-\n\t   actions */\n\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ISDEENVELOPE ) && \\\n\t\tactionListPtr->action == ACTION_HASH )\n\t\t{\n\t\tLOOP_MED_CHECKINC( actionListPtr != NULL,\n\t\t\t\t\t\t   actionListPtr = DATAPTR_GET( actionListPtr->next ) )\n\t\t\t{\n\t\t\tREQUIRES_B( sanityCheckActionList( actionListPtr ) );\n\n\t\t\tif( actionListPtr->action != ACTION_HASH )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Everything else is an error */\n\treturn( FALSE );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/envelope/res_denv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib De-enveloping Information Management\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"envelope.h\"\n  #include \"pgp.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"envelope/envelope.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/* The maximum number of content items that we can add to a content list.\n   Encrypted messages sent to very large distribution lists can potentially \n   have a large number of per-recipient wrapped keys, although this stuff is\n   so rarely used that way that there's no hard data on it.  So far a bound\n   of 50 items seems to be a pretty safe bet */\n\n#define MAX_CONTENT_ITEMS\t50\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tContent List Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check a content-list entry */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkDataPointer( IN const void *data, \n\t\t\t\t\t\t\t\t IN const int dataLength,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMinLength, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMaxLength )\n\t{\n\t/* We don't perform any precondition checks on the to-be-checked input \n\t   values because the purpose of this function is to check potentially \n\t   invalid values, so we can't assume they have any particular value */\n\tREQUIRES_B( isShortIntegerRangeNZ( dataMinLength ) );\n\tREQUIRES_B( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tdataMinLength < dataMaxLength );\n\n\tif( data == NULL )\n\t\t{\n\t\tif( dataLength != 0 )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\tif( dataLength < dataMinLength || dataLength > dataMaxLength )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckContentCrypt( IN const CONTENT_LIST *contentListPtr )\n\t{\n\tconst CONTENT_ENCR_INFO *contentEncrInfo = &contentListPtr->clEncrInfo;\n\tconst int maxIterations = \\\n\t\t\t\t( contentListPtr->formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\tMAX_KEYSETUP_HASHSPECIFIER : MAX_KEYSETUP_ITERATIONS;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( contentEncrInfo, sizeof( CONTENT_ENCR_INFO ) ) );\n\n\t/* Check crypto parameters */\n\tif( ( contentEncrInfo->cryptAlgo != CRYPT_ALGO_NONE && \\\n\t\t  !isConvAlgo( contentEncrInfo->cryptAlgo ) && \\\n\t\t  !isPkcAlgo( contentEncrInfo->cryptAlgo ) ) || \\\n\t\t( contentEncrInfo->cryptMode < CRYPT_MODE_NONE || \\\n\t\t  contentEncrInfo->cryptMode >= CRYPT_MODE_LAST ) ) \n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Crypto algorithm/mode\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( contentEncrInfo->saltOrIVsize < 0 || \\\n\t\tcontentEncrInfo->saltOrIVsize > CRYPT_MAX_HASHSIZE || \\\n\t\tcontentEncrInfo->keySetupAlgo < CRYPT_ALGO_NONE || \\\n\t\tcontentEncrInfo->keySetupAlgo > CRYPT_ALGO_LAST_EXTERNAL || \\\n\t\tcontentEncrInfo->keySetupIterations < 0 || \\\n\t\tcontentEncrInfo->keySetupIterations > maxIterations || \\\n\t\tcontentEncrInfo->keySize < 0 || \\\n\t\tcontentEncrInfo->keySize > CRYPT_MAX_KEYSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Crypto parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckContentSig( IN const CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t\t\t  IN_OPT const void *objectPtr )\n\t{\n\tconst CONTENT_SIG_INFO *contentSigInfo = &contentListPtr->clSigInfo;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( contentSigInfo, sizeof( CONTENT_SIG_INFO ) ) );\n\tassert( objectPtr == NULL || isReadPtr( objectPtr, 2 ) );\n\n\t/* Check signing parameters */\n\tif( ( contentSigInfo->hashAlgo != CRYPT_ALGO_NONE && \\\n\t\t  !isHashAlgo( contentSigInfo->hashAlgo ) ) || \\\n\t\t( contentSigInfo->hashAlgoParam != 0 && \\\n\t\t  ( contentSigInfo->hashAlgoParam < MIN_HASHSIZE || \\\n\t\t\tcontentSigInfo->hashAlgoParam > CRYPT_MAX_HASHSIZE ) ) || \\\n\t\t( contentSigInfo->iSigCheckKey != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( contentSigInfo->iSigCheckKey ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Signature algorithm info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check data pointers */\n\tif( !checkDataPointer( contentSigInfo->extraData,\n\t\t\t\t\t\t   contentSigInfo->extraDataLength, \n\t\t\t\t\t\t   1, MAX_INTLENGTH_SHORT - 1 ) || \\\n\t\t( contentSigInfo->iTimestamp != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( contentSigInfo->iTimestamp ) ) || \\\n\t\t!checkDataPointer( contentSigInfo->extraData2,\n\t\t\t\t\t\t   contentSigInfo->extraData2Length, \n\t\t\t\t\t\t   1, MAX_INTLENGTH_SHORT - 1 ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Signature attribute info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( objectPtr != NULL )\n\t\t{\n\t\tif( !pointerBoundsCheck( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t contentSigInfo->extraData,\n\t\t\t\t\t\t\t\t contentSigInfo->extraDataLength ) || \\\n\t\t\t!pointerBoundsCheck( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t contentSigInfo->extraData2,\n\t\t\t\t\t\t\t\t contentSigInfo->extraData2Length ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContentList: Signature object data pointers\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check miscellaneous items */\n\tif( !isEnumRangeOpt( contentSigInfo->attributeCursorEntry, CRYPT_ATTRIBUTE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Signature attribute cursor\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckContentAuthenc( IN const CONTENT_LIST *contentListPtr )\n\t{\n\tconst CONTENT_AUTHENC_INFO *contentAuthEncInfo = &contentListPtr->clAuthEncInfo;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtr( contentAuthEncInfo, sizeof( CONTENT_AUTHENC_INFO ) ) );\n\n\t/* If the content-list entry hasn't been set up yet then all parameters \n\t   must be clear */\n\tif( contentAuthEncInfo->authEncAlgo == CRYPT_ALGO_NONE )\n\t\t{\n\t\tif( contentAuthEncInfo->authEncParamLength != 0 || \\\n\t\t\tcontentAuthEncInfo->kdfData != NULL || \\\n\t\t\tcontentAuthEncInfo->kdfDataLength != 0 || \\\n\t\t\tcontentAuthEncInfo->encParamData != NULL || \\\n\t\t\tcontentAuthEncInfo->encParamDataLength != 0 || \\\n\t\t\tcontentAuthEncInfo->macParamData != NULL || \\\n\t\t\tcontentAuthEncInfo->macParamDataLength != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContentList: Authenc spurious parameters\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check authenc parameters */\n\tif( !isSpecialAlgo( contentAuthEncInfo->authEncAlgo ) ) \n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Authenc algorithm\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( contentAuthEncInfo->authEncParamLength <= 0 || \\\n\t\tcontentAuthEncInfo->authEncParamLength > 128 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Authenc parameter size\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check data pointers */\n\tif( !pointerBoundsCheck( contentAuthEncInfo->authEncParamData, \n\t\t\t\t\t\t\t contentAuthEncInfo->authEncParamLength,\n\t\t\t\t\t\t\t contentAuthEncInfo->kdfData,\n\t\t\t\t\t\t\t contentAuthEncInfo->kdfDataLength ) || \\\n\t\t!pointerBoundsCheck( contentAuthEncInfo->authEncParamData, \n\t\t\t\t\t\t\t contentAuthEncInfo->authEncParamLength,\n\t\t\t\t\t\t\t contentAuthEncInfo->encParamData,\n\t\t\t\t\t\t\t contentAuthEncInfo->encParamDataLength ) || \\\n\t\t!pointerBoundsCheck( contentAuthEncInfo->authEncParamData, \n\t\t\t\t\t\t\t contentAuthEncInfo->authEncParamLength,\n\t\t\t\t\t\t\t contentAuthEncInfo->macParamData,\n\t\t\t\t\t\t\t contentAuthEncInfo->macParamDataLength ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Authenc object data pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckContentList( IN const CONTENT_LIST *contentListPtr )\n\t{\n\tconst void *objectPtr = NULL;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\n\t/* Check overall content list data */\n\tif( !isEnumRange( contentListPtr->type, CONTENT ) || \\\n\t\t( contentListPtr->envInfo != CRYPT_ATTRIBUTE_NONE && \\\n\t\t  ( contentListPtr->envInfo <= CRYPT_ENVINFO_FIRST || \\\n\t\t\tcontentListPtr->envInfo >= CRYPT_ENVINFO_LAST ) ) || \\\n\t\tcontentListPtr->formatType <= CRYPT_FORMAT_NONE || \\\n\t\tcontentListPtr->formatType >= CRYPT_FORMAT_LAST_EXTERNAL || \\\n\t\t!CHECK_FLAGS( contentListPtr->flags, CONTENT_FLAG_NONE, \n\t\t\t\t\t  CONTENT_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers.  We don't have to check the function pointers\n\t   because they're validated each time they're dereferenced */\n\tif( !DATAPTR_ISVALID( contentListPtr->prev ) || \\\n\t\t!DATAPTR_ISVALID( contentListPtr->next ) || \\\n\t\t!DATAPTR_ISVALID( contentListPtr->object ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckContentList: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check buffer values */\n\tif( DATAPTR_ISNULL( contentListPtr->object ) )\n\t\t{\n\t\tif( contentListPtr->objectSize != 0 || \\\n\t\t\tcontentListPtr->issuerAndSerialNumber != NULL || \\\n\t\t\tcontentListPtr->issuerAndSerialNumberSize != 0 || \\\n\t\t\tcontentListPtr->payload != NULL || \\\n\t\t\tcontentListPtr->payloadSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContentList: Spurious object data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Get the object pointer.  We know that this is valid because it's\n\t\t   been checked above */\n\t\tobjectPtr = DATAPTR_GET( contentListPtr->object );\n\t\tREQUIRES_B( objectPtr != NULL );\n\n\t\tif( contentListPtr->objectSize < 8 || \\\n\t\t\tcontentListPtr->objectSize >= MAX_INTLENGTH_SHORT || \\\n\t\t\t!checkDataPointer( contentListPtr->issuerAndSerialNumber,\n\t\t\t\t\t\t\t   contentListPtr->issuerAndSerialNumberSize, \n\t\t\t\t\t\t\t   1, MAX_INTLENGTH_SHORT - 1 ) || \\\n\t\t\t!checkDataPointer( contentListPtr->payload,\n\t\t\t\t\t\t\t   contentListPtr->payloadSize, \n\t\t\t\t\t\t\t   1, MAX_INTLENGTH_SHORT - 1 ) || \\\n\t\t\tcontentListPtr->keyIDsize < 0 || \\\n\t\t\tcontentListPtr->keyIDsize > CRYPT_MAX_HASHSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContentList: Object data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !pointerBoundsCheck( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t contentListPtr->issuerAndSerialNumber,\n\t\t\t\t\t\t\t\t contentListPtr->issuerAndSerialNumberSize ) || \\\n\t\t\t!pointerBoundsCheck( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t contentListPtr->payload,\n\t\t\t\t\t\t\t\t contentListPtr->payloadSize ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckContentList: Signature object data pointers\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check subtype-specific data */\n\tswitch( contentListPtr->type )\n\t\t{\n\t\tcase CONTENT_CRYPT:\n\t\t\tif( !sanityCheckContentCrypt( contentListPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CONTENT_SIGNATURE:\n\t\t\tif( !sanityCheckContentSig( contentListPtr, objectPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CONTENT_AUTHENC:\n\t\t\tif( !sanityCheckContentAuthenc( contentListPtr ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check whether more content items can be added to a content list */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN moreContentItemsPossible( IN_OPT const CONTENT_LIST *contentListPtr )\n\t{\n\tint contentListCount, LOOP_ITERATOR;\n\n\tassert( contentListPtr == NULL || \\\n\t\t\tisReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\n\tREQUIRES_B( contentListPtr == NULL || \\\n\t\t\t\tsanityCheckContentList( contentListPtr ) );\n\n\tLOOP_EXT( contentListCount = 0,\n\t\t\t  contentListPtr != NULL && \\\n\t\t\t\t\tcontentListCount < MAX_CONTENT_ITEMS,\n\t\t\t  ( contentListPtr = DATAPTR_GET( contentListPtr->next ),\n\t\t\t\t\tcontentListCount++ ), \n\t\t\t  MAX_CONTENT_ITEMS + 1 );\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( ( contentListCount < MAX_CONTENT_ITEMS ) ? TRUE : FALSE );\n\t}\n\n/* Create a content list item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createContentListItem( OUT_BUFFER_ALLOC_OPT( sizeof( CONTENT_LIST ) ) \\\n\t\t\t\t\t\t\t\tCONTENT_LIST **newContentListItemPtrPtr,\n\t\t\t\t\t\t   INOUT MEMPOOL_STATE memPoolState, \n\t\t\t\t\t\t   IN_ENUM( CONTENT ) const CONTENT_TYPE type,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t   IN_BUFFER_OPT( objectSize ) const void *object, \n\t\t\t\t\t\t   IN_LENGTH_Z const int objectSize )\n\t{\n\tCONTENT_LIST *newItem;\n\n\tassert( isWritePtr( newContentListItemPtrPtr, \\\n\t\t\t\t\t\tsizeof( CONTENT_LIST * ) ) );\n\tassert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );\n\tassert( objectSize == 0 || isReadPtrDynamic( object, objectSize ) );\n\n\tREQUIRES( isEnumRange( type, CONTENT ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( ( object == NULL && objectSize == 0 ) || \\\n\t\t\t  ( object != NULL && \\\n\t\t\t\tobjectSize > 0 && objectSize < MAX_BUFFER_SIZE ) );\n\n\t/* Clear return value */\n\t*newContentListItemPtrPtr = NULL;\n\n\tif( ( newItem = getMemPool( memPoolState, \\\n\t\t\t\t\t\t\t\tsizeof( CONTENT_LIST ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( newItem, 0, sizeof( CONTENT_LIST ) );\n\tnewItem->type = type;\n\tnewItem->formatType = formatType;\n\tINIT_FLAGS( newItem->flags, CONTENT_FLAG_NONE );\n\tDATAPTR_SET( newItem->object, ( void * ) object );\n\tnewItem->objectSize = objectSize;\n\tDATAPTR_SET( newItem->prev, NULL );\n\tDATAPTR_SET( newItem->next, NULL );\n\tif( type == CONTENT_SIGNATURE )\n\t\t{\n\t\tnewItem->clSigInfo.iSigCheckKey = CRYPT_ERROR;\n\t\tnewItem->clSigInfo.iExtraData = CRYPT_ERROR;\n\t\tnewItem->clSigInfo.iTimestamp = CRYPT_ERROR;\n\t\t}\n\t*newContentListItemPtrPtr = newItem;\n\n\tREQUIRES( sanityCheckContentList( newItem ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add an item to the content list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint appendContentListItem( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   INOUT CONTENT_LIST *contentListItem )\n\t{\n\tCONTENT_LIST *contentListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->contentList );\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( contentListPtr == NULL || \\\n\t\t\tisWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\n\t/* Find the end of the list and add the new item */\n\tif( contentListPtr != NULL )\n\t\t{\n\t\tCONTENT_LIST *prevElementPtr;\n\t\tint LOOP_ITERATOR;\n\t\t\n\t\tLOOP_LARGE( prevElementPtr = NULL,\n\t\t\t\t\tcontentListPtr != NULL,\n\t\t\t\t\t( prevElementPtr = contentListPtr,\n\t\t\t\t\t  contentListPtr = DATAPTR_GET( contentListPtr->next ) ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tcontentListPtr = prevElementPtr;\n\t\t}\n\tinsertDoubleListElement( &envelopeInfoPtr->contentList, contentListPtr, \n\t\t\t\t\t\t\t contentListItem, CONTENT_LIST );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete a content list */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid deleteContentListItem( INOUT MEMPOOL_STATE memPoolState,\n\t\t\t\t\t\t\tINOUT CONTENT_LIST *contentListItem )\n\t{\n\tassert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );\n\tassert( isWritePtr( contentListItem, sizeof( CONTENT_LIST ) ) );\n\n\tREQUIRES_V( sanityCheckContentList( contentListItem ) );\n\n\t/* Destroy any attached objects if necessary */\n\tif( contentListItem->type == CONTENT_SIGNATURE )\n\t\t{\n\t\tCONTENT_SIG_INFO *sigInfo = &contentListItem->clSigInfo;\n\n\t\tif( sigInfo->iSigCheckKey != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( sigInfo->iSigCheckKey, IMESSAGE_DECREFCOUNT );\n\t\tif( sigInfo->iExtraData != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( sigInfo->iExtraData, IMESSAGE_DECREFCOUNT );\n\t\tif( sigInfo->iTimestamp != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( sigInfo->iTimestamp, IMESSAGE_DECREFCOUNT );\n\t\t}\n\n\t/* Free any object data */\n\tif( DATAPTR_ISSET( contentListItem->object ) )\n\t\t{\n\t\tvoid *objectPtr = ( void * ) DATAPTR_GET( contentListItem->object );\n\t\t\t /* Although the data is declared 'const' since it can't be \n\t\t\t    modified, we still have to be able to zeroise it on free so \n\t\t\t\twe override the const for this */\n\n\t\tREQUIRES_V( objectPtr != NULL );\n\n\t\tzeroise( objectPtr, contentListItem->objectSize );\n\t\tclFree( \"deleteContentListItem\", objectPtr );\n\t\t}\n\n\t/* Free the item itself */\n\tzeroise( contentListItem, sizeof( CONTENT_LIST ) );\n\tfreeMemPool( memPoolState, contentListItem );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteContentList( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tCONTENT_LIST *contentListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\n\tLOOP_LARGE_INITCHECK( contentListCursor = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t\t\t\t  contentListCursor != NULL )\n\t\t{\n\t\tCONTENT_LIST *contentListItem = contentListCursor;\n\n\t\tREQUIRES( sanityCheckContentList( contentListCursor ) );\n\n\t\tcontentListCursor = DATAPTR_GET( contentListCursor->next );\n\n\t\t/* Erase and free the object buffer if necessary */\n\t\tdeleteDoubleListElement( &envelopeInfoPtr->contentList, \n\t\t\t\t\t\t\t\t contentListItem, CONTENT_LIST );\n\t\tdeleteContentListItem( envelopeInfoPtr->memPoolState, \n\t\t\t\t\t\t\t   contentListItem );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Clear the pointers to the content list */\n\tDATAPTR_SET( envelopeInfoPtr->contentList, NULL );\n\tDATAPTR_SET( envelopeInfoPtr->contentListCurrent, NULL );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tProcess Signature Data \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CMS\n\n/* Process timestamps */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processTimestamp( INOUT CONTENT_LIST *contentListPtr, \n\t\t\t\t\t\t\t IN_BUFFER( timestampLength ) const void *timestamp, \n\t\t\t\t\t\t\t IN_LENGTH_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\tconst int timestampLength )\n\t{\n\tCRYPT_ENVELOPE iTimestampEnvelope;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int bufSize = max( timestampLength + 128, MIN_BUFFER_SIZE );\n\tint status;\n\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtrDynamic( timestamp, timestampLength ) );\n\n\tREQUIRES( timestampLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  timestampLength < MAX_BUFFER_SIZE );\n\n\t/* Create an envelope to contain the timestamp data.  We can't use the\n\t   internal enveloping API for this because we want to retain the final\n\t   envelope and not just recover the data contents (which for a \n\t   timestamp will be empty anyway) */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiTimestampEnvelope = createInfo.cryptHandle;\n\n\t/* Push in the timestamp data */\n\tstatus = krnlSendMessage( iTimestampEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &bufSize, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) timestamp, \\\n\t\t\t\t\t\ttimestampLength );\n\t\tstatus = krnlSendMessage( iTimestampEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iTimestampEnvelope, IMESSAGE_ENV_PUSHDATA, \n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iTimestampEnvelope, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* We've got the timestamp info in a sub-envelope, remember it for\n\t   later */\n\tcontentListPtr->clSigInfo.iTimestamp = iTimestampEnvelope;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process CMS unauthenticated attributes.  We can't handle these as\n   standard CMS attributes since the only thing that we're likely to see \n   here is a countersignature, which isn't an attribute in the normal \n   sense */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processUnauthAttributes( INOUT CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( unauthAttrLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *unauthAttr,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int unauthAttrLength )\n\t{\n\tSTREAM stream;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtrDynamic( unauthAttr, unauthAttrLength ) );\n\n\tREQUIRES( unauthAttrLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  unauthAttrLength < MAX_BUFFER_SIZE );\n\n\t/* Make sure that the unauthenticated attributes are OK.  Normally this\n\t   is done when we import the attributes but since we can't import\n\t   them we have to perform the check explicitly here */\n\tstatus = checkCertObjectEncoding( unauthAttr, unauthAttrLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Process each attribute */\n\tsMemConnect( &stream, unauthAttr, unauthAttrLength );\n\tstatus = readConstructed( &stream, NULL, 1 );\n\tLOOP_LARGE_CHECK( cryptStatusOK( status ) && \\\n\t\t\t\t\t  sMemDataLeft( &stream ) >= MIN_CRYPT_OBJECTSIZE )\n\t\t{\n\t\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\t\tvoid *dataPtr;\n\t\tint oidLength, length DUMMY_INIT;\n\n\t\t/* See what we've got */\n\t\treadSequence( &stream, NULL );\n\t\tstatus = readEncodedOID( &stream, oid, MAX_OID_SIZE, &oidLength, \n\t\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readSet( &stream, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* If it's something that we don't recognise, skip it and continue */\n\t\tif( oidLength != sizeofOID( OID_TSP_TSTOKEN ) || \\\n\t\t\tmemcmp( oid, OID_TSP_TSTOKEN, oidLength ) )\n\t\t\t{\n\t\t\tstatus = readUniversal( &stream );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* We've got a timestamp.  We can't really do much with this at the \n\t\t   moment since although it quacks like a countersignature, in the \n\t\t   PKIX tradition it's subtly (and gratuitously) incompatible in \n\t\t   various ways so that it can't be verified as a standard \n\t\t   countersignature (video meliora proboque deteriora sequor).  \n\t\t   Amusingly, the RFC actually states that this is a stupid way to \n\t\t   do things.  Specifically, instead of using the normal MUST/SHOULD \n\t\t   it first states that the sensible solution to the problem is to \n\t\t   use a countersignature, and then goes on to mandate something \n\t\t   that isn't a countersignature.  Since this isn't the sensible \n\t\t   solution, it's obviously the stupid one.  QED */\n\t\tif( length < MIN_CRYPT_OBJECTSIZE )\n\t\t\t{\n\t\t\t/* It's too short to be a valid timestamp */\n\t\t\tstatus = CRYPT_ERROR_UNDERFLOW;\n\t\t\tcontinue;\n\t\t\t}\n\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = processTimestamp( contentListPtr, dataPtr, length );\n\t\t/* Continue the loop with the cryptStatusOK() check */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Perform additional checks beyond those performed for a standard \n   signature as required by CMS signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int checkCmsSignatureInfo( INOUT CONTENT_LIST *contentListPtr, \n\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iHashContext,\n\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iSigCheckContext,\n\t\t\t\t\t\t\t\t  IN_ENUM( CRYPT_CONTENT ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;\n\tconst void *objectPtr = DATAPTR_GET( contentListPtr->object );\n\tint status;\n\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isHandleRangeValid( iSigCheckContext ) );\n\tREQUIRES( isEnumRange( contentType, CRYPT_CONTENT ) );\n\tREQUIRES( objectPtr != NULL );\n\n\t/* If it's CMS signed data then the signature check key should be \n\t   included with the signed data as a certificate chain, however it's \n\t   possible (though unlikely) that the certificates may be unrelated to \n\t   the signature, in which case the caller will have provided the \n\t   signature check key from an external source */\n\tstatus = iCryptCheckSignature( objectPtr, contentListPtr->objectSize, \n\t\t\t\t\t\t\t\t   CRYPT_FORMAT_CMS,\n\t\t\t\t\t\t\t\t   ( sigInfo->iSigCheckKey == CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\t\t\tiSigCheckContext : sigInfo->iSigCheckKey,\n\t\t\t\t\t\t\t\t   iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t   &sigInfo->iExtraData );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \"Signature verification failed\" ) );\n\t\t}\n\n\t/* If there are authenticated attributes present we have to perform an \n\t   extra check to make sure that the content-type specified in the \n\t   authenticated attributes matches the actual data content type */\n\tif( sigInfo->iExtraData != CRYPT_ERROR )\n\t\t{\n\t\tint signatureContentType;\n\n\t\tstatus = krnlSendMessage( sigInfo->iExtraData, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &signatureContentType, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_CONTENTTYPE );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tsignatureContentType != contentType )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, errorInfo, \n\t\t\t\t\t  \"Content-type in authenticated attributes doesn't \"\n\t\t\t\t\t  \"match actual content type\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If there are unauthenticated attributes present, process them */\n\tif( sigInfo->extraData2 != NULL )\n\t\t{\n\t\tstatus = processUnauthAttributes( contentListPtr, sigInfo->extraData2,\n\t\t\t\t\t\t\t\t\t\t  sigInfo->extraData2Length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid unauthenticated attribute data\") );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tProcess Encryption Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a new encryption or MAC action to the envelope's action list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addActionToList( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\tIN_ENUM( ACTION ) const ACTION_TYPE action )\n\t{\n\tACTION_RESULT actionResult;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( action == ACTION_CRYPT || action == ACTION_MAC );\n\n\t/* Add the action to the envelope action list */\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\tactionResult = checkAction( DATAPTR_GET( envelopeInfoPtr->actionList ), \n\t\t\t\t\t\t\t\taction, iCryptContext );\n\tif( actionResult == ACTION_RESULT_ERROR || \\\n\t\tactionResult == ACTION_RESULT_INITED )\n\t\treturn( CRYPT_ERROR_INITED );\n\treturn( addAction( envelopeInfoPtr, action, iCryptContext ) );\n\t}\n\n#ifdef USE_CMS\n\n/* Initialise a recovered encryption key, either directly if it's a session \n   key or indirectly if it's a generic-secret key used to derive encryption\n   and MAC contexts and keys */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int initKeys( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iMacContext )\n\t{\n\tCRYPT_CONTEXT iAuthEncCryptContext, iAuthEncMacContext;\n\tCRYPT_ALGO_TYPE kdfAlgo DUMMY_INIT;\n\tconst CONTENT_LIST *contentListPtr;\n\tconst CONTENT_ENCR_INFO *encrInfo;\n\tconst CONTENT_AUTHENC_INFO *authEncInfo;\n\tMECHANISM_KDF_INFO mechanismInfo;\n\tCONTENT_ENCR_INFO localEncrInfo;\n\tSTREAM stream;\n\tint value, kdfAlgoParam DUMMY_INIT, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iMacContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\n\t/* Clear return values.  Note that we set the returned context to the\n\t   passed-in context since this is the default (identity) transformation,\n\t   it's only when using authenticated encryption that it gets set to a\n\t   new context */\n\t*iCryptContext = iSessionKeyContext;\n\t*iMacContext = CRYPT_ERROR;\n\n\t/* Check whether we got as far as the encrypted data, which will be \n\t   indicated by the fact that there's content information present from \n\t   which we can set up the decryption */\n\tLOOP_LARGE( contentListPtr = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t\tcontentListPtr != NULL && \\\n\t\t\t\t\tcontentListPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\tcontentListPtr = DATAPTR_GET( contentListPtr->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\tif( contentListPtr == NULL )\n\t\t{\n\t\t/* We didn't get to the encrypted data, the decryption will be set \n\t\t   up by the de-enveloping code when we reach the data */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're using standard (non-authenticated) encryption, the \n\t   encryption parameters have been provided directly as part of the \n\t   content information so we can set up the decryption and exit */\n\tif( contentListPtr->type != CONTENT_AUTHENC )\n\t\t{\n\t\tencrInfo = &contentListPtr->clEncrInfo;\n\t\treturn( initEnvelopeEncryption( envelopeInfoPtr, iSessionKeyContext, \n\t\t\t\t\t\t\t\tencrInfo->cryptAlgo, encrInfo->cryptMode, \n\t\t\t\t\t\t\t\t( encrInfo->saltOrIVsize > 0 ) ? \\\n\t\t\t\t\t\t\t\t\tencrInfo->saltOrIV : NULL, \n\t\t\t\t\t\t\t\tencrInfo->saltOrIVsize, FALSE ) );\n\t\t}\n\n\t/* We're using authenticated encryption, in which case the \"session key\" \n\t   that we've been given is actually a generic-secret context from which \n\t   the encryption and MAC contexts and keys have to be derived */\n\tauthEncInfo = &contentListPtr->clAuthEncInfo;\n\n\t/* Recover the KDF information if it's present.  Early implementations\n\t   erroneously omitted the PBKDF2 AlgorithmIdentifier so we allow for\n\t   versions with or without this value.  Since the entries are skipped \n\t   it just means that there's two more values to skip:\n\n\t\tKdfParams ::= [ 0 ] SEQUENCE {\t\t\t-- 3.4.3 - 3.4.4.1\n\t\t\tsalt\t\t\tOCTET STRING SIZE(0),\n\t\t\titerationCount\tINTEGER (1),\n\t\t\tprf\t\t\t\tAlgorithmIdentifier\n\t\t\t} \n\n\t\tKdfParams ::= [ 0 ] SEQUENCE {\t\t\t-- Present if HMAC != SHA1\n\t\t\tpbkdf2\t\t\tOBJECT IDENTIFIER,\n\t\t\tSEQUENCE {\n\t\t\t\tsalt\t\tOCTET STRING SIZE(0),\n\t\t\t\titerationCount INTEGER (1),\n\t\t\t\tprf\t\t\tAlgorithmIdentifier\t-- HMAC-SHA2, etc\n\t\t\t\t}\n\t\t\t} */\n\tif( authEncInfo->kdfDataLength > 0 )\n\t\t{\n\t\tsMemConnect( &stream, authEncInfo->kdfData, \n\t\t\t\t\t authEncInfo->kdfDataLength );\n\t\treadConstructed( &stream, NULL, 0 );\n\t\tif( peekTag( &stream ) == BER_OBJECT_IDENTIFIER )\n\t\t\t{\n\t\t\treadUniversal( &stream );\t\t/* OID */\n\t\t\treadSequence( &stream, NULL );\n\t\t\t}\n\t\treadUniversal( &stream );\t\t\t/* Salt */\n\t\tstatus = readShortInteger( &stream, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readAlgoIDex( &stream, &kdfAlgo, NULL, \n\t\t\t\t\t\t\t\t   &kdfAlgoParam, ALGOID_CLASS_HASH );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* The PBKDF2 default KDF is HMAC-SHA1 */\n\t\tkdfAlgo = CRYPT_ALGO_HMAC_SHA1;\n\t\tkdfAlgoParam = 0;\n\t\t}\n\n\t/* Recreate the encryption and MAC contexts used for the authenticated \n\t   encryption from the algorithm parameter data stored with the generic-\n\t   secret context */\n\tsMemConnect( &stream, authEncInfo->encParamData, \n\t\t\t\t authEncInfo->encParamDataLength );\n\tstatus = readContextAlgoID( &stream, &iAuthEncCryptContext, NULL, \n\t\t\t\t\t\t\t\tDEFAULT_TAG, ALGOID_CLASS_CRYPT );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, authEncInfo->macParamData, \n\t\t\t\t authEncInfo->macParamDataLength );\n\tstatus = readContextAlgoID( &stream, &iAuthEncMacContext, NULL, \n\t\t\t\t\t\t\t\tDEFAULT_TAG, ALGOID_CLASS_HASH );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Set up the encryption parameters using the parameter data recovered\n\t   from the generic-secret context */\n\tmemset( &localEncrInfo, 0, sizeof( CONTENT_ENCR_INFO ) );\n\tstatus = krnlSendMessage( iAuthEncCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &value, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tlocalEncrInfo.cryptAlgo = value;\t/* int vs.enum */\n\t\tstatus = krnlSendMessage( iAuthEncCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, CRYPT_CTXINFO_MODE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tlocalEncrInfo.cryptMode = value;\t/* int vs.enum */\n\t\tsetMessageData( &msgData, localEncrInfo.saltOrIV, \n\t\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iAuthEncCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlocalEncrInfo.saltOrIVsize = msgData.length;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tencrInfo = &localEncrInfo;\n\n\t/* Derive the encryption and MAC keys from the generic-secret key */\n\tsetMechanismKDFInfo( &mechanismInfo, iAuthEncCryptContext, \n\t\t\t\t\t\t iSessionKeyContext, kdfAlgo, \"encryption\", 10 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMechanismKDFInfo( &mechanismInfo, iAuthEncMacContext, \n\t\t\t\t\t\t\t iSessionKeyContext, kdfAlgo, \"authentication\", 14 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* We've got the encryption context and information ready, set up the \n\t   decryption */\n\tstatus = initEnvelopeEncryption( envelopeInfoPtr, \n\t\t\t\t\t\t\tiAuthEncCryptContext, encrInfo->cryptAlgo, \n\t\t\t\t\t\t\tencrInfo->cryptMode, encrInfo->saltOrIV, \n\t\t\t\t\t\t\tencrInfo->saltOrIVsize, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* MAC the EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier \n\t   information alongside the payload data to prevent an attacker from \n\t   manipulating the algorithm parameters to cause corruption that won't \n\t   be detected by the MAC on the payload data */\n\tstatus = krnlSendMessage( iAuthEncMacContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) authEncInfo->authEncParamData,\n\t\t\t\t\t\t\t  authEncInfo->authEncParamLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t*iCryptContext = iAuthEncCryptContext;\n\t*iMacContext = iAuthEncMacContext;\n\n\t/* We're now MACing the data via a level of indirection (in other words\n\t   we haven't gone directly via a MACAlgorithmIdentifier in the envelope\n\t   header) so we need to explicitly turn on hashing */\n\tSET_FLAG( envelopeInfoPtr->dataFlags, \n\t\t\t  ENVDATA_FLAG_AUTHENCACTIONSACTIVE );\n\n\t/* Let the caller know that the contexts have been switched */\n\treturn( OK_SPECIAL );\n\t}\n#endif /* USE_CMS */\n\n/* Set up the envelope decryption using an added or recovered session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initSessionKeyDecryption( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_HANDLE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t\t\t\t const BOOLEAN isRecoveredSessionKey )\n\t{\n\tCRYPT_CONTEXT iCryptContext = iSessionKeyContext;\n\tCRYPT_CONTEXT iMacContext = CRYPT_ERROR;\n\tBOOLEAN isAuthEnc = FALSE;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\tREQUIRES( isRecoveredSessionKey == TRUE || isRecoveredSessionKey == FALSE );\n\n\t/* If we recovered the session key from a key exchange action rather \n\t   than having it passed directly to us by the user, try and set up the \n\t   decryption */\n\tif( isRecoveredSessionKey )\n\t\t{\n\t\tstatus = initKeys( envelopeInfoPtr, iSessionKeyContext,\n\t\t\t\t\t\t   &iCryptContext, &iMacContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\n\t\t\t/* A return status of OK_SPECIAL means that the context has\n\t\t\t   changed from a single 'session-key' context containing a\n\t\t\t   generic secret to two new contexts, one for encryption and\n\t\t\t   the other for authentication */\n\t\t\tisAuthEnc = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* Add the recovered session encryption action to the action list */\n\tstatus = addActionToList( envelopeInfoPtr, iCryptContext, ACTION_CRYPT );\n\tif( cryptStatusOK( status ) && isAuthEnc )\n\t\tstatus = addActionToList( envelopeInfoPtr, iMacContext, ACTION_MAC );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( isAuthEnc )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\tkrnlSendNotifier( iMacContext, IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* If we're using authenticated encryption (via CMS's encrypt-then-MAC\n\t   rather than PGP's encrypted sort-of-keyed hash) then the generic-\n\t   secret context that was recovered as the 'session-key' has been \n\t   turned into two new contexts, one for encryption and the other for \n\t   authentication, and we can destroy it */\n\tif( envelopeInfoPtr->usage == ACTION_CRYPT && \\\n\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) && \\\n\t\tenvelopeInfoPtr->type != CRYPT_FORMAT_PGP )\n\t\t{\n\t\tREQUIRES( iSessionKeyContext != iCryptContext );\n\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\t}\n\n\t/* Notify the kernel that the encryption/MAC context is attached to the \n\t   envelope.  This is an internal object used only by the envelope so we \n\t   tell the kernel not to increment its reference count when it attaches \n\t   it */\n\treturn( krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t ( MESSAGE_CAST ) &iCryptContext, \n\t\t\t\t\t\t\t SETDEP_OPTION_NOINCREF ) );\n\t}\n\n/* Import a wrapped session key (optionally a generic-secret key if we're\n   going via an intermediate step for authenticated encryption) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int importSessionKey( IN const CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iSessionKeyContext,\n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iSessionKey;\n\tconst CONTENT_LIST *sessionKeyInfoPtr;\n\tconst void *objectPtr = DATAPTR_GET( contentListPtr->object );\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isWritePtr( iSessionKeyContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iImportContext ) );\n\tREQUIRES( objectPtr != NULL );\n\n\t/* Clear return value */\n\t*iSessionKeyContext = CRYPT_ERROR;\n\n#ifdef USE_PGP\n\t/* PGP doesn't provide separate session key information with the\n\t   encrypted data but wraps it up alongside the encrypted key so we\n\t   can't import the wrapped key into a context via the standard key\n\t   import functions but instead have to create the context as part of\n\t   the unwrap process */\n\tif( contentListPtr->formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\treturn( iCryptImportKey( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t CRYPT_FORMAT_PGP, iImportContext,\n\t\t\t\t\t\t\t\t CRYPT_UNUSED, iSessionKeyContext ) );\n\t\t}\n#endif /* USE_PGP */\n\n\t/* Look for the information required to recreate the session key (or\n\t   generic-secret) context */\n\tLOOP_LARGE( sessionKeyInfoPtr = contentListPtr, \n\t\t\t\tsessionKeyInfoPtr != NULL && \\\n\t\t\t\t\tsessionKeyInfoPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\tsessionKeyInfoPtr = DATAPTR_GET( sessionKeyInfoPtr->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\tif( sessionKeyInfoPtr == NULL )\n\t\t{\n\t\t/* We need to read more data before we can recreate the session key */\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\t/* Create the session/generic-secret key context */\n\tif( sessionKeyInfoPtr->type == CONTENT_CRYPT )\n\t\t{\n\t\tconst CONTENT_ENCR_INFO *encrInfo = &sessionKeyInfoPtr->clEncrInfo;\n\n\t\t/* It's conventional encrypted data, import the session key and\n\t\t   set the encryption mode */\n\t\tsetMessageCreateObjectInfo( &createInfo, encrInfo->cryptAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo,\n\t\t\t\t\t  \"Couldn't create decryption context for algorithm %s\",\n\t\t\t\t\t  getAlgoName( encrInfo->cryptAlgo ) ) );\n\t\t\t}\n\t\tif( !isStreamCipher( encrInfo->cryptAlgo ) )\n\t\t\t{\n\t\t\tconst int mode = encrInfo->cryptMode;\t/* int vs.enum */\n\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tconst CONTENT_AUTHENC_INFO *authEncInfo = \\\n\t\t\t\t\t\t\t&sessionKeyInfoPtr->clAuthEncInfo;\n\n\t\t/* It's authenticated-encrypted data, import the generic-secret\n\t\t   context used to create the encryption and MAC contexts */\n\t\tsetMessageCreateObjectInfo( &createInfo, authEncInfo->authEncAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo,\n\t\t\t\t\t  \"Couldn't create decryption context for algorithm %s\",\n\t\t\t\t\t  getAlgoName( authEncInfo->authEncAlgo ) ) );\n\t\t\t}\n\t\t}\n\tiSessionKey = createInfo.cryptHandle;\n\n\t/* Import the wrapped session/generic-secret key */\n\tstatus = iCryptImportKey( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t  contentListPtr->formatType, iImportContext, \n\t\t\t\t\t\t\t  iSessionKey, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iSessionKeyContext = iSessionKey;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAdd De-enveloping Information \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add signature verification information.  Note that the hashAlgo parameter\n   is an int instead of the more obvious CRYPT_ALGO_TYPE because this \n   function is a function parameter of type CHECKACTIONFUNCTION for which \n   the second argument is a generic integer parameter */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int findHashActionFunction( IN const ACTION_LIST *actionListPtr,\n\t\t\t\t\t\t\t\t   IN_ALGO const int hashAlgo )\n\t{\n\tint actionCryptAlgo, status;\n\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\n\t/* Check to see if it's the action that we want */\n\tstatus = krnlSendMessage( actionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &actionCryptAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR );\n\treturn( ( actionCryptAlgo == hashAlgo ) ? CRYPT_OK : CRYPT_ERROR );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int addSignatureInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t INOUT CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE sigCheckContext,\n\t\t\t\t\t\t\t const BOOLEAN isExternalKey )\n\t{\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tCONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;\n\tconst void *objectPtr = DATAPTR_GET( contentListPtr->object );\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\n\tREQUIRES( isHandleRangeValid( sigCheckContext ) );\n\tREQUIRES( isExternalKey == TRUE || isExternalKey == FALSE );\n\tREQUIRES( actionListPtr != NULL );\n\tREQUIRES( objectPtr != NULL );\n\n\t/* If we've already processed this entry, return the cached processing \n\t   result */\n\tif( TEST_FLAG( contentListPtr->flags, CONTENT_FLAG_PROCESSED ) )\n\t\treturn( sigInfo->processingResult );\n\n\t/* Find the hash action that we need to check this signature.  If we \n\t   can't find one, return a bad signature error since something must \n\t   have altered the algorithm ID for the hash */\n\tactionListPtr = findActionIndirect( actionListPtr, findHashActionFunction,\n\t\t\t\t\t\t\t\t\t\tsigInfo->hashAlgo );\n\tif( actionListPtr == NULL || actionListPtr->action != ACTION_HASH )\n\t\t{\n\t\tSET_FLAG( contentListPtr->flags, CONTENT_FLAG_PROCESSED );\n\t\tsigInfo->processingResult = CRYPT_ERROR_SIGNATURE;\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO,\n\t\t\t\t  \"Signature hash algorithm doesn't match hash algorithm \"\n\t\t\t\t  \"applied to enveloped data\" ) );\n\t\t}\n\n\t/* Check the signature.  In theory there's an additional check that we \n\t   need to apply at this point that defends against a (hypothesised) \n\t   attack in which, if there are multiple signatures present and they \n\t   use different-strength hash algorithms and an attacker manages to \n\t   break one of them, the attacker can strip the stronger-algorithm \n\t   signature(s) and leave only the weaker-algorithm one(s), allowing \n\t   them to modify the signed data.  The way to handle this is to include \n\t   a reference to every other signature in the current signature.  \n\t   However there are (currently) no known implementations of this, which \n\t   makes testing somewhat difficult.  In addition the handling gets very \n\t   tricky, for example if the recipient supports only the weak algorithm \n\t   should they reject the message or accept it?  (The RFC that covers \n\t   this, RFC 5750, says that no matter what occurs in terms of absent or \n\t   present strong or weak-algorithm signatures, the recipient MAY \n\t   consider them valid).  Until both implementations, and more \n\t   importantly users who can specify how they want this handled, appear, \n\t   we leave it for future implementation */\n#ifdef USE_CMS\n\tif( contentListPtr->formatType == CRYPT_FORMAT_CMS )\n\t\t{\n\t\tstatus = checkCmsSignatureInfo( contentListPtr, \n\t\t\t\t\t\t\t\t\t\tactionListPtr->iCryptHandle,\n\t\t\t\t\t\t\t\t\t\tsigCheckContext,\n\t\t\t\t\t\t\t\t\t\tenvelopeInfoPtr->contentType,\n\t\t\t\t\t\t\t\t\t\tENVELOPE_ERRINFO );\n\t\t}\n\telse\n#endif /* USE_CMS */\n\t\t{\n\t\tstatus = iCryptCheckSignature( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\tcontentListPtr->formatType, sigCheckContext,\n\t\t\t\t\t\t\t\tactionListPtr->iCryptHandle, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tNULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* We need to do this explicitly here since it's not set by\n\t\t\t   iCryptCheckSignature() as it is for checkCmsSignatureInfo() */\n\t\t\tsetErrorString( ENVELOPE_ERRINFO, \n\t\t\t\t\t\t\t\"Signature verification failed\", 29 );\n\t\t\t}\n\n\t\t/* If it's a format that includes signing key information remember \n\t\t   the key that was used to check the signature in case the user \n\t\t   wants to query it later */\n\t\tif( contentListPtr->formatType != CRYPT_FORMAT_PGP )\n\t\t\t{\n\t\t\tkrnlSendNotifier( sigCheckContext, IMESSAGE_INCREFCOUNT );\n\t\t\tsigInfo->iSigCheckKey = sigCheckContext;\n\t\t\tif( isExternalKey )\n\t\t\t\tSET_FLAG( contentListPtr->flags, CONTENT_FLAG_EXTERNALKEY );\n\t\t\t}\n\t\t}\n\n\t/* There are a few special-case situations in which a failure at this\n\t   point isn't necessarily fatal, but it's hard to predict in advance \n\t   exactly what all of these could be.  The one obvious one is with a\n\t   CRYPT_ERROR_WRONGKEY, which means that the caller can simply retry \n\t   with a different key, so we make this error non-persistent */\n\tif( status == CRYPT_ERROR_WRONGKEY )\n\t\t{\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, ENVELOPE_ERRINFO, \n\t\t\t\t  \"Incorrect key used to verify signature\" ) );\n\t\t}\n\n\t/* Remember the processing result so that we don't have to repeat the \n\t   processing if queried again.  Since we don't need the encoded \n\t   signature data any more after this point we can free it.  This is\n\t   rather more complex than it seems because the content list contains \n\t   various pointers to ID and attribute information inside the object\n\t   data, to deal with this we have to go through and clear every pointer\n\t   value that pointed to the now-freed object data */\n\tclFree( \"addSignatureInfo\", ( void * ) objectPtr );\n\tDATAPTR_SET( contentListPtr->object, NULL );\n\tcontentListPtr->objectSize = 0;\n\tcontentListPtr->issuerAndSerialNumber = \\\n\t\t\tcontentListPtr->payload = NULL;\n\tcontentListPtr->issuerAndSerialNumberSize = \\\n\t\t\tcontentListPtr->payloadSize = 0;\n\tswitch( contentListPtr->type )\n\t\t{\n\t\tcase CONTENT_CRYPT:\n\t\t\t/* All information is stored in the encryption content \n\t\t\t   structure */\n\t\t\tbreak;\n\n\t\tcase CONTENT_SIGNATURE:\n\t\t\t{\n\t\t\tCONTENT_SIG_INFO *contentSigInfo = &contentListPtr->clSigInfo;\n\n\t\t\tcontentSigInfo->extraData = \\\n\t\t\t\t\tcontentSigInfo->extraData2 = NULL;\n\t\t\tcontentSigInfo->extraDataLength = \\\n\t\t\t\t\tcontentSigInfo->extraData2Length = 0;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CONTENT_AUTHENC:\n\t\t\t{\n\t\t\tCONTENT_AUTHENC_INFO *contentAuthEncInfo = \\\n\t\t\t\t\t\t\t\t\t\t\t&contentListPtr->clAuthEncInfo;\n\n\t\t\tcontentAuthEncInfo->kdfData = \\\n\t\t\t\t\tcontentAuthEncInfo->encParamData = \\\n\t\t\t\t\tcontentAuthEncInfo->macParamData = NULL;\n\t\t\tcontentAuthEncInfo->kdfDataLength = \\\n\t\t\t\t\tcontentAuthEncInfo->encParamDataLength = \\\n\t\t\t\t\tcontentAuthEncInfo->macParamDataLength = 0;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\tSET_FLAG( contentListPtr->flags, CONTENT_FLAG_PROCESSED );\n\tsigInfo->processingResult = cryptArgError( status ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_ERROR_SIGNATURE : status;\n\n\tENSURES( sanityCheckContentList( contentListPtr ) );\n\n\treturn( status );\n\t}\n\n/* Add a password for decryption of a private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int addPrivkeyPasswordInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t   IN const CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\t\t   IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\t\t\t   IN_LENGTH_TEXT const int passwordLength )\n\t{\n\tconst ENV_ADDINFO_FUNCTION addInfoFunction = \\\n\t\t\t\t( ENV_ADDINFO_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->addInfoFunction );\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint type, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( addInfoFunction != NULL );\n\n\t/* Make sure that there's a keyset available to pull the key from */\n\tif( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Make sure that we're trying to send the password to something for\n\t   which it makes sense.  Private-key sources aren't just keysets but\n\t   can also be devices, but if we're trying to send a password to a \n\t   device to get a private key then something's gone wrong since it \n\t   should be retrieved automatically from the device, which was unlocked\n\t   via a PIN or password when a session with it was established */\n\tstatus = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &type,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_TYPE );\n\tif( cryptStatusError( status ) || type != OBJECT_TYPE_KEYSET )\n\t\t{\n\t\t/* This one is very difficult to report appropriately, the best that\n\t\t   we can do is report the wrong key for this type of object */\n\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t}\n\n\t/* Try and get the key information */\n\tif( contentListPtr->issuerAndSerialNumber == NULL )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo,\n\t\t\t\t( contentListPtr->formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\tCRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID,\n\t\t\t\tcontentListPtr->keyID, contentListPtr->keyIDsize,\n\t\t\t\t( MESSAGE_CAST ) password, passwordLength, \n\t\t\t\tKEYMGMT_FLAG_USAGE_CRYPT );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo,\n\t\t\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER,\n\t\t\t\tcontentListPtr->issuerAndSerialNumber,\n\t\t\t\tcontentListPtr->issuerAndSerialNumberSize,\n\t\t\t\t( MESSAGE_CAST ) password, passwordLength, \n\t\t\t\tKEYMGMT_FLAG_USAGE_CRYPT );\n\t\t}\n\tstatus = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo,\n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PRIVATEKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtObj( status,\n\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t     envelopeInfoPtr->iDecryptionKeyset,\n\t\t\t\t\t \"Couldn't retrieve private key from decryption \"\n\t\t\t\t\t \"keyset/device\" ) );\n\t\t}\n\n\t/* We managed to get the private key, push it into the envelope.  If the\n\t   call succeeds this will import the session key and delete the \n\t   required-information list, after which we don't need the private key\n\t   any more */\n\tstatus = addInfoFunction( envelopeInfoPtr, CRYPT_ENVINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t  getkeyInfo.cryptHandle );\n\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/* Add a decryption password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 7 ) ) \\\nstatic int addPasswordInfo( IN const CONTENT_LIST *contentListPtr,\n\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\t\tIN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \\\n\t\t\t\t\t\t\t\tconst int passwordLength,\n\t\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iMacContext,\n\t\t\t\t\t\t\tOUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iNewContext,\n\t\t\t\t\t\t\tIN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tconst CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint mode, status;\n\n\tassert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( ( isHandleRangeValid( iMacContext ) && iNewContext == NULL ) || \\\n\t\t\t( iMacContext == CRYPT_UNUSED && \\\n\t\t\t  isWritePtr( iNewContext, sizeof( CRYPT_CONTEXT ) ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( ( isHandleRangeValid( iMacContext ) && iNewContext == NULL ) || \\\n\t\t\t  ( iMacContext == CRYPT_UNUSED && iNewContext != NULL ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( formatType != CRYPT_FORMAT_PGP || iNewContext != NULL );\n\t\t\t  /* PGP can't perform MACing, only encryption */\n\n\t/* Clear return value */\n\tif( iNewContext != NULL )\n\t\t*iNewContext = CRYPT_ERROR;\n\n\t/* Create the appropriate encryption context and derive the key into it */\n\tsetMessageCreateObjectInfo( &createInfo, encrInfo->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\tmode = encrInfo->cryptMode;\t/* int vs.enum */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &mode, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef USE_PGP\n\t\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t\t{\n\t\t\tstatus = pgpPasswordToKey( iCryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\tpassword, passwordLength, encrInfo->keySetupAlgo,\n\t\t\t\t\t\t\t( encrInfo->saltOrIVsize > 0 ) ? \\\n\t\t\t\t\t\t\t\tencrInfo->saltOrIV : NULL, encrInfo->saltOrIVsize,\n\t\t\t\t\t\t\tencrInfo->keySetupIterations );\n\t\t\t}\n\t\telse\n#endif /* USE_PGP */\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\t/* Load the derivation information into the context */\n\t\t\tif( encrInfo->keySetupAlgo != CRYPT_ALGO_NONE )\n\t\t\t\t{\n\t\t\t\tconst int algorithm = encrInfo->keySetupAlgo;\t/* int vs.enum */\n\t\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &algorithm,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ALGO );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &encrInfo->keySetupIterations,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ITERATIONS );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) && encrInfo->keySetupAlgoParam > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &encrInfo->keySetupAlgoParam,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEYING_ALGO_PARAM );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) && encrInfo->keySize > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &encrInfo->keySize,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) encrInfo->saltOrIV,\n\t\t\t\t\t\t\t\tencrInfo->saltOrIVsize );\n\t\t\t\tstatus = krnlSendMessage( iCryptContext,\n\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_SALT );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, \n\t\t\t\t\t\t\t\tpasswordLength );\n\t\t\t\tstatus = krnlSendMessage( iCryptContext,\n\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_VALUE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo,\n\t\t\t\t  \"Couldn't derive key-import key from password\" ) );\n\t\t}\n\n\t/* In PGP there isn't any encrypted session key so the context created \n\t   from the password becomes the bulk encryption context and we're done */\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\t*iNewContext = iCryptContext;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Recover the session key using the password context and destroy it \n\t   when we're done with it */\n\tif( iNewContext == NULL )\n\t\t{\n\t\tconst void *objectPtr = DATAPTR_GET( contentListPtr->object );\n\n\t\tREQUIRES( objectPtr != NULL );\n\n\t\t/* The target is a MAC context (which has already been set up), load\n\t\t   the session key directly into it */\n\t\tstatus = iCryptImportKey( objectPtr, contentListPtr->objectSize,\n\t\t\t\t\t\t\t\t  contentListPtr->formatType, \n\t\t\t\t\t\t\t\t  iCryptContext, iMacContext, NULL );\n\t\t}\n\telse\n\t\t{\n\t\t/* The target is an encryption context, recreate it from the \n\t\t   encrypted session key information */\n\t\tstatus = importSessionKey( contentListPtr, iCryptContext, \n\t\t\t\t\t\t\t\t   iNewContext, errorInfo );\n\t\t}\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo,\n\t\t\t\t  \"Couldn't recover wrapped session key\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDe-enveloping Information Management Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and match what's being added to an information object in the content \n   list */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int matchInfoObject( OUT_PTR_OPT CONTENT_LIST **contentListPtrPtr,\n\t\t\t\t\t\t\tIN const ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo )\n\t{\n\tCONTENT_LIST *contentListPtr;\n\tconst BOOLEAN privateKeyFetch = \\\n\t\t( envInfo == CRYPT_ENVINFO_PASSWORD && \\\n\t\t  envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR ) ? TRUE : FALSE;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( contentListPtrPtr, sizeof( CONTENT_LIST * ) ) );\n\tassert( isReadPtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \\\n\t\t\t  ( envInfo > CRYPT_ENVINFO_FIRST && \\\n\t\t\t\tenvInfo < CRYPT_ENVINFO_LAST ) );\n\n\t/* Clear return value */\n\t*contentListPtrPtr = NULL;\n\n\t/* If we're adding meta-information there's nothing to check */\n\tif( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \\\n\t\tenvInfo == CRYPT_ENVINFO_DETACHEDSIGNATURE || \\\n\t\tenvInfo == CRYPT_ENVINFO_KEYSET_SIGCHECK || \\\n\t\tenvInfo == CRYPT_ENVINFO_KEYSET_ENCRYPT || \\\n\t\tenvInfo == CRYPT_ENVINFO_KEYSET_DECRYPT || \\\n\t\tenvInfo == CRYPT_ENVINFO_HASH )\n\t\treturn( CRYPT_OK );\n\n\t/* If there's already a content-list item selected, make sure that the \n\t   information that we're adding matches the current information object.  \n\t   The one exception to this is that we can be passed password \n\t   information when we require a private key if the private key is \n\t   encrypted */\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->contentListCurrent ) );\n\tcontentListPtr = DATAPTR_GET( envelopeInfoPtr->contentListCurrent );\n\tif( contentListPtr != NULL )\n\t\t{\n\t\tif( contentListPtr->envInfo != envInfo && \\\n\t\t\t!( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \\\n\t\t\t   privateKeyFetch ) )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t*contentListPtrPtr = contentListPtr;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Look for the first information object that matches the supplied \n\t   information */\n\tLOOP_LARGE( contentListPtr = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t\tcontentListPtr != NULL && contentListPtr->envInfo != envInfo,\n\t\t\t\tcontentListPtr = DATAPTR_GET( contentListPtr->next ) );\n\tENSURES( LOOP_BOUND_OK );\n\tif( contentListPtr == NULL && privateKeyFetch )\n\t\t{\n\t\t/* If we didn't find a direct match and we've been given a password, \n\t\t   check for a private key that can (potentially) be decrypted using \n\t\t   the password.  This requires both a keyset/device to fetch the \n\t\t   key from and a private key as the required info type */\n\t\tLOOP_LARGE( contentListPtr = DATAPTR_GET( envelopeInfoPtr->contentList ), \n\t\t\t\t\tcontentListPtr != NULL && \\\n\t\t\t\t\t\tcontentListPtr->envInfo != CRYPT_ENVINFO_PRIVATEKEY,\n\t\t\t\t\tcontentListPtr = DATAPTR_GET( contentListPtr->next ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( contentListPtr == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\tENSURES( sanityCheckContentList( contentListPtr ) );\n\n\t*contentListPtrPtr = contentListPtr;\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete the addition of information to an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completeEnvelopeInfoUpdate( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\t/* Destroy the content list, which at this point will contain only (now-\n\t   irrelevant) key exchange items */\n\tif( DATAPTR_ISSET( envelopeInfoPtr->contentList ) )\n\t\tdeleteContentList( envelopeInfoPtr );\n\n\t/* If the only error was an information required error, we've now\n\t   resolved the problem and can continue */\n\tif( envelopeInfoPtr->errorState == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tenvelopeInfoPtr->errorState = CRYPT_OK;\n\n\t\t/* The envelope is ready to process data, move it into the high\n\t\t   state.  Normally this is handled in the data-push code but this\n\t\t   leads to a race condition when all the data being pushed is\n\t\t   buffered inside the envelope, requiring only that processing be\n\t\t   enabled by adding a resource.  Once the resource is added the\n\t\t   only action left for the caller to perform is a flush, so they \n\t\t   expect that high-state actions should succeed even though the\n\t\t   envelope state machine wouldn't move the envelope into the high\n\t\t   state until some data action (in this case a flush) is \n\t\t   initiated.  To avoid this problem we move the envelope into the\n\t\t   high state as soon as the resource blockage has been cleared,\n\t\t   since any high-state-only information (for example the nested\n\t\t   content type) will now be available */\n\t\treturn( krnlSendMessage( envelopeInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add de-enveloping information to an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addDeenvelopeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\t  IN_INT_Z const int value )\n\t{\n\tCRYPT_HANDLE cryptHandle = ( CRYPT_HANDLE ) value;\n\tCRYPT_CONTEXT iNewContext DUMMY_INIT;\n\tCRYPT_ATTRIBUTE_TYPE localEnvInfo = envInfo;\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tCONTENT_LIST *contentListPtr;\n\tBOOLEAN isExternalKey = TRUE;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \\\n\t\t\t  ( envInfo > CRYPT_ENVINFO_FIRST && \\\n\t\t\t\tenvInfo < CRYPT_ENVINFO_LAST ) );\n\n\t/* A signature-check object can be passed in as a special-case type\n\t   CRYPT_ENVINFO_SIGNATURE_RESULT to indicate that the object was \n\t   obtained internally (for example by instantiating it from an attached \n\t   certificate chain) and doesn't require various special-case \n\t   operations that are applied to user-supplied objects.  If this is the \n\t   case then we convert it to a standard CRYPT_ENVINFO_SIGNATURE and \n\t   remember that it's an internally-supplied key */\n\tif( envInfo == CRYPT_ENVINFO_SIGNATURE_RESULT )\n\t\t{\n\t\tlocalEnvInfo = CRYPT_ENVINFO_SIGNATURE;\n\t\tisExternalKey = FALSE;\n\t\t}\n\n\t/* Since we can add one of a multitude of necessary information types \n\t   we need to check to make sure that what we're adding is appropriate.  \n\t   We do this by trying to match what's being added to the first \n\t   information object of the correct type */\n\tstatus = matchInfoObject( &contentListPtr, envelopeInfoPtr, \n\t\t\t\t\t\t\t  localEnvInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtArg( status,\n\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t \"Added item doesn't match %s envelope information \"\n\t\t\t\t\t \"object\",\n\t\t\t\t\t ( DATAPTR_ISSET( envelopeInfoPtr->contentListCurrent ) ) ? \\\n\t\t\t\t\t\t\"currently selected\" : \"any\" ) );\n\t\t}\n\n\t/* Process non-encryption-related enveloping info */\n\tswitch( localEnvInfo )\n\t\t{\n\t\tcase CRYPT_IATTRIBUTE_ATTRONLY:\n\t\t\t/* This is off by default so we should only be turning it on */\n\t\t\tREQUIRES( value == TRUE );\n\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ATTRONLY );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_DETACHEDSIGNATURE:\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_KEYSET_SIGCHECK:\n\t\tcase CRYPT_ENVINFO_KEYSET_ENCRYPT:\n\t\tcase CRYPT_ENVINFO_KEYSET_DECRYPT:\n\t\t\t/* It's keyset information, keep a record of it for later use */\n\t\t\treturn( addKeysetInfo( envelopeInfoPtr, localEnvInfo, \n\t\t\t\t\t\t\t\t   cryptHandle ) );\n\n\t\tcase CRYPT_ENVINFO_HASH:\n\t\t\t/* The user is checking a detached signature, remember the hash \n\t\t\t   for later.  In theory we should also check the state of the \n\t\t\t   hash context, however PGP requires that it not be completed \n\t\t\t   (since it needs to hash further data) and everything else \n\t\t\t   requires that it be completed, but we don't know at this \n\t\t\t   point whether we're processing PGP or non-PGP data so we \n\t\t\t   can't perform any checking here */\n\t\t\tif( actionListPtr != NULL )\n\t\t\t\t{\n\t\t\t\t/* There's already a hash action present, we can't add \n\t\t\t\t   anything further */\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_HASH,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\t/* In theory at this point we should call moreActionsPossible(), \n\t\t\t   however since we know that actionListPtr == NULL we can \n\t\t\t   always add more actions */\n\n\t\t\t/* Add the hash as an action list item */\n\t\t\tstatus = addAction( envelopeInfoPtr, ACTION_HASH, cryptHandle );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\treturn( krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT ) );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\t/* It's a signature object, check the signature and exit */\n\t\t\tREQUIRES( contentListPtr != NULL );\n\t\t\treturn( addSignatureInfo( envelopeInfoPtr, contentListPtr,\n\t\t\t\t\t\t\t\t\t  cryptHandle, isExternalKey ) );\n\t\t}\n\n\t/* Make sure that we can still add another action */\n\tif( !moreActionsPossible( actionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Since we're performing envelope decryption, there must be content \n\t   info present */\n\tREQUIRES( contentListPtr != NULL );\n\n\t/* Anything that's left at this point related to envelope decryption */\n\tswitch( localEnvInfo )\n\t\t{\n\t\tcase CRYPT_ENVINFO_PRIVATEKEY:\n\t\tcase CRYPT_ENVINFO_KEY:\n\t\t\t/* Import the session key using the KEK */\n\t\t\tstatus = importSessionKey( contentListPtr, cryptHandle, \n\t\t\t\t\t\t\t\t\t   &iNewContext, ENVELOPE_ERRINFO );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ENVINFO_SESSIONKEY:\n\t\t\t{\n\t\t\t/* If we've been given the session key directly then we must \n\t\t\t   have reached the encrypted data so we take a copy and set \n\t\t\t   up the decryption with it */\n\t\t\tconst CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;\n\n\t\t\tstatus = initEnvelopeEncryption( envelopeInfoPtr, cryptHandle,\n\t\t\t\t\t\t\tencrInfo->cryptAlgo, encrInfo->cryptMode,\n\t\t\t\t\t\t\tencrInfo->saltOrIV, encrInfo->saltOrIVsize, TRUE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* The session key context is the newly-created internal \n\t\t\t\t   one */\n\t\t\t\tiNewContext = envelopeInfoPtr->iCryptContext;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've now got the session key, if we recovered it from a key exchange\n\t   action (rather than having it passed directly to us by the user) try\n\t   and set up the decryption */\n\tif( envelopeInfoPtr->usage != ACTION_MAC )\n\t\t{\n\t\tstatus = initSessionKeyDecryption( envelopeInfoPtr, iNewContext,\n\t\t\t\t\t\t\t( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY )\n\t\t\t\tkrnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );\n\t\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\t\t{\n\t\t\t\t/* If the attribute that we added to recover the session key \n\t\t\t\t   is already present, provide extended error information */\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, localEnvInfo, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Complete the envelope information update */\n\treturn( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int addDeenvelopeInfoString( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t\tIN_RANGE( CRYPT_ENVINFO_PASSWORD, \\\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PASSWORD ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\t\t\t\tIN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int valueLength )\n\t{\n\tCRYPT_CONTEXT iNewContext DUMMY_INIT;\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\tCONTENT_LIST *contentListPtr;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( envInfo == CRYPT_ENVINFO_PASSWORD );\n\tREQUIRES( valueLength > 0 && valueLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Since we can add one of a multitude of necessary information types, \n\t   we need to check to make sure that what we're adding is appropriate.  \n\t   We do this by trying to match what's being added to the first \n\t   information object of the correct type */\n\tstatus = matchInfoObject( &contentListPtr, envelopeInfoPtr, envInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtArg( status,\n\t\t\t\t   ( status, ENVELOPE_ERRINFO,\n\t\t\t\t\t \"Added item doesn't match any envelope information \"\n\t\t\t\t\t \"object\" ) );\n\t\t}\n\tENSURES( sanityCheckContentList( contentListPtr ) );\n\n\t/* If we've been given a password and we need private key information, \n\t   it's the password required to decrypt the key so we treat this \n\t   specially.  This action recursively calls addDeenvelopeInfo() with \n\t   the processed private key so we don't have to fall through to the \n\t   session-key processing code below like the other key-handling \n\t   actions */\n\tif( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY )\n\t\t{\n\t\treturn( addPrivkeyPasswordInfo( envelopeInfoPtr, contentListPtr,\n\t\t\t\t\t\t\t\t\t\tvalue, valueLength ) );\n\t\t}\n\n\t/* Make sure that we can still add another action */\n\tif( envelopeInfoPtr->usage != ACTION_MAC && \\\n\t\t!moreActionsPossible( actionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* We've been given a standard decryption password, create a decryption \n\t   context for it, derive the key from the password, and use it to \n\t   import the session/MAC key */\n\tif( envelopeInfoPtr->usage == ACTION_MAC )\n\t\t{\n\t\tif( actionListPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\tstatus = addPasswordInfo( contentListPtr, value, valueLength, \n\t\t\t\t\t\t\t\t  actionListPtr->iCryptHandle, NULL, \n\t\t\t\t\t\t\t\t  envelopeInfoPtr->type, ENVELOPE_ERRINFO );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = addPasswordInfo( contentListPtr, value, valueLength, \n\t\t\t\t\t\t\t\t  CRYPT_UNUSED, &iNewContext,\n\t\t\t\t\t\t\t\t  envelopeInfoPtr->type, ENVELOPE_ERRINFO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've recovered the session key, try and set up the decryption */\n\tif( envelopeInfoPtr->usage != ACTION_MAC )\n\t\t{\n\t\tstatus = initSessionKeyDecryption( envelopeInfoPtr, iNewContext, \n\t\t\t\t\t\t\t\t\t\t   TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );\n\t\t\tif( status == CRYPT_ERROR_INITED )\n\t\t\t\t{\n\t\t\t\t/* If the attribute that we added to recover the session key \n\t\t\t\t   is already present, provide extended error information */\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, envInfo, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Complete the envelope information update */\n\treturn( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initDenvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\t\n\tREQUIRES_V( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->addInfoFunction, addDeenvelopeInfo );\n\tFNPTR_SET( envelopeInfoPtr->addInfoStringFunction, addDeenvelopeInfoString );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/envelope/res_env.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Enveloping Information Management\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"envelope.h\"\n  #include \"pgp.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"envelope/envelope.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PGP\n\n/* Check that an object being added is suitable for use with PGP data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkPgpUsage( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo )\n\t{\n\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->actionList );\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( envInfo > CRYPT_ENVINFO_FIRST && envInfo < CRYPT_ENVINFO_LAST );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\n\t/* If the attribute being added isn't context-related then there's \n\t   nothing PGP-specific to check */\n\tif( envInfo != CRYPT_ENVINFO_PUBLICKEY && \\\n\t\tenvInfo != CRYPT_ENVINFO_PRIVATEKEY && \\\n\t\tenvInfo != CRYPT_ENVINFO_KEY && \\\n\t\tenvInfo != CRYPT_ENVINFO_SESSIONKEY && \\\n\t\tenvInfo != CRYPT_ENVINFO_HASH && \\\n\t\tenvInfo != CRYPT_ENVINFO_SIGNATURE )\n\t\treturn( CRYPT_OK );\n\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\n\t/* PGP doesn't support both PKC and conventional key exchange actions in \n\t   the same envelope since the session key is encrypted for the PKC \n\t   action but derived from the password for the conventional action */\n\tif( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE ) != NULL )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* PGP handles multiple signers by nesting signed data rather than \n\t   attaching multiple signatures so we can only apply a single \n\t   signature per envelope */\n\tif( envInfo == CRYPT_ENVINFO_SIGNATURE && \\\n\t\tDATAPTR_ISSET( envelopeInfoPtr->postActionList ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* PGP doesn't allow multiple hash algorithms to be used when signing \n\t   data, a follow-on from the way that nested sigs are handled */\n\tif( envInfo == CRYPT_ENVINFO_HASH && actionListPtr != NULL )\n\t\t{\n\t\t/* The one exception to this occurs when we're using a detached \n\t\t   signature with an externally-provided hash value and the user \n\t\t   has added a signing key before adding the hash, in which case \n\t\t   a hash action will have been added automatically when the signing \n\t\t   key was added.  In this case the presence of an automatically-\n\t\t   added hash action is OK since it'll be replaced with the hash\n\t\t   value that we're now adding */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) && \\\n\t\t\tactionListPtr->action == ACTION_HASH && \\\n\t\t\tTEST_FLAG( actionListPtr->flags, \n\t\t\t\t\t   ACTION_FLAG_ADDEDAUTOMATICALLY ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/* Clone a context so that we can add the clone to an action list */\n\nstatic int cloneActionContext( OUT_HANDLE_OPT CRYPT_CONTEXT *iClonedContext,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE algorithm )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( iClonedContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptContext ) );\n\tREQUIRES( isEnumRange( algorithm, CRYPT_ALGO ) );\n\n\t/* Clear return value */\n\t*iClonedContext = CRYPT_ERROR;\n\n\tsetMessageCreateObjectInfo( &createInfo, algorithm );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_CLONE, NULL,\n\t\t\t\t\t\t\t  createInfo.cryptHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iClonedContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tMisc.Enveloping Info Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the encryption for an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initEnvelopeEncryption( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\tIN_ALGO_OPT const CRYPT_ALGO_TYPE algorithm, \n\t\t\t\t\t\t\tIN_MODE_OPT const CRYPT_MODE_TYPE mode,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( ivLength ) const BYTE *iv, \n\t\t\t\t\t\t\tIN_LENGTH_IV_Z const int ivLength,\n\t\t\t\t\t\t\tconst BOOLEAN copyContext )\n\t{\n\tCRYPT_CONTEXT iCryptContext = cryptContext;\n\tint contextAlgorithm DUMMY_INIT, contextMode DUMMY_INIT;\n\tint blockSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( ( iv == NULL && ivLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( iv, ivLength ) );\n\n\tREQUIRES( isHandleRangeValid( cryptContext ) );\n\tREQUIRES( ( algorithm == CRYPT_ALGO_NONE && mode == CRYPT_MODE_NONE ) || \\\n\t\t\t  ( isConvAlgo( algorithm ) && \\\n\t\t\t\tisEnumRange( mode, CRYPT_MODE ) ) );\n\tREQUIRES( ( iv == NULL && ivLength == 0 ) || \\\n\t\t\t  ( iv != NULL && \\\n\t\t\t    ivLength >= MIN_IVSIZE && ivLength <= CRYPT_MAX_IVSIZE ) );\n\tREQUIRES( copyContext == TRUE || copyContext == FALSE );\n\n\t/* Extract the information that we need to process data */\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &contextAlgorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &contextMode, CRYPT_CTXINFO_MODE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the context is what's required */\n\tif( algorithm != CRYPT_ALGO_NONE && \\\n\t\t( contextAlgorithm != algorithm || contextMode != mode ) )\n\t\t{\n\t\t/* This can only happen on de-enveloping if the data is corrupted or\n\t\t   if the user is asked for a KEK and tries to supply a session key\n\t\t   instead */\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t}\n\tif( ivLength != 0 && ivLength != blockSize ) \n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If it's a user-supplied context take a copy for our own use.  This is\n\t   only done for non-idempotent user-supplied contexts, for everything\n\t   else we either use cryptlib's object management to handle things for\n\t   us or the context is an internal one created specifically for our own\n\t   use */\n\tif( copyContext )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tsetMessageCreateObjectInfo( &createInfo, contextAlgorithm );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CLONE, NULL,\n\t\t\t\t\t\t\t\t  createInfo.cryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\tiCryptContext = createInfo.cryptHandle;\n\t\t}\n\n\t/* Load the IV into the context and set up the encryption information for\n\t   the envelope */\n\tif( !isStreamCipher( contextAlgorithm ) )\n\t\t{\n\t\tif( iv != NULL )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) iv, ivLength );\n\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* There's no IV specified, generate a new one */\n\t\t\tstatus = krnlSendNotifier( iCryptContext, IMESSAGE_CTX_GENIV );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( copyContext )\n\t\t\t\t{\n\t\t\t\t/* Destroy the copy that we created earlier */\n\t\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tenvelopeInfoPtr->iCryptContext = iCryptContext;\n\tenvelopeInfoPtr->blockSize = blockSize;\n\tenvelopeInfoPtr->blockSizeMask = ~( blockSize - 1 );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the consistency of enveloping resources before we begin enveloping,\n   returning the ID of any missing attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkSignatureActionFunction( IN const ACTION_LIST *actionListPtr,\n\t\t\t\t\t\t\t\t\t\t IN_INT_Z const int signingKeyPresent )\n\t{\n\tassert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );\n\n\t/* If there are no signature-related auxiliary options present, there's\n\t   nothing to check */\n\tif( actionListPtr->iExtraData != CRYPT_ERROR || \\\n\t\tactionListPtr->iTspSession != CRYPT_ERROR )\n\t\treturn( CRYPT_OK );\n\n\t/* There must be a signing key present to handle the signature options */\n\tif( !signingKeyPresent || actionListPtr->iCryptHandle == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkMissingInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t const BOOLEAN isFlush )\n\t{\n\tBOOLEAN signingKeyPresent = FALSE;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( isFlush == TRUE || isFlush == FALSE );\n\n\t/* Make sure that we have the minimum requirements for each usage type\n\t   present */\n\tswitch( envelopeInfoPtr->usage )\n\t\t{\n\t\tcase ACTION_COMPRESS:\n\t\t\tREQUIRES( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t\t ENVELOPE_FLAG_ZSTREAMINITED ) );\n\t\t\tbreak;\n\n\t\tcase ACTION_HASH:\n\t\t\tDEBUG_DIAG(( \"Hashed (rather than MAC'd) enveloping isn't \"\n\t\t\t\t\t\t \"supported\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tbreak;\n\n\t\tcase ACTION_MAC:\n\t\t\t/* If it's a MAC'd envelope then there must be at least one key \n\t\t\t   exchange action present.  A few obscure operation sequences \n\t\t\t   may however set the usage without setting a key exchange \n\t\t\t   action.  For example making the envelope a MAC'd envelope \n\t\t\t   simply indicates that any future key exchange actions should \n\t\t\t   be used for MACing rather than encryption but this is \n\t\t\t   indicative of a logic error in the calling application so we \n\t\t\t   report an error even if, strictly speaking, we could ignore \n\t\t\t   it and continue */\n\t\t\tif( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ) == NULL && \\\n\t\t\t\tfindPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE ) == NULL )\n\t\t\t\t{\n\t\t\t\t/* We return the most generic CRYPT_ENVINFO_KEY error code\n\t\t\t\t   since there are several possible missing attribute types \n\t\t\t\t   that could be required */\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEY, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_CRYPT:\n\t\t\t/* If it's an encryption envelope then there must be a key \n\t\t\t   present at some level.  This situation doesn't normally occur \n\t\t\t   since the higher-level code will only set the usage to \n\t\t\t   encryption once a key exchange action has been added, but we \n\t\t\t   check anyway just to be safe */\n\t\t\tif( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ) == NULL && \\\n\t\t\t\tfindPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE ) == NULL && \\\n\t\t\t\tfindAction( envelopeInfoPtr, ACTION_CRYPT ) == NULL )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEY, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ACTION_SIGN:\n\t\t\t/* If it's a signing envelope then there must be a signature key \n\t\t\t   present */\n\t\t\tif( findPostAction( envelopeInfoPtr, ACTION_SIGN ) == NULL )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\tsigningKeyPresent = TRUE;\n\n\t\t\t/* If it's a detached signature and we're performing a flush (in\n\t\t\t   other words we're wrapping up the enveloping with no data\n\t\t\t   pushed) then there has to be an externally-supplied hash\n\t\t\t   present */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) && isFlush )\n\t\t\t\t{\n\t\t\t\tconst ACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\t\tfindAction( envelopeInfoPtr, ACTION_HASH );\n\t\t\t\t\t\t\t\t\n\t\t\t\tif( actionListPtr == NULL || \\\n\t\t\t\t\tTEST_FLAG( actionListPtr->flags, \n\t\t\t\t\t\t\t   ACTION_FLAG_ADDEDAUTOMATICALLY ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_HASH, \n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\n\tREQUIRES( signingKeyPresent || \\\n\t\t\t  !( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_DETACHED_SIG ) || \\\n\t\t\t\t findAction( envelopeInfoPtr, ACTION_HASH ) ) );\n\n\t/* If there are signature-related options present (signature envelope,\n\t   detached-signature flag set, hash context present, or CMS attributes \n\t   or a TSA session present) there must be a signing key also present */\n\tif( DATAPTR_ISSET( envelopeInfoPtr->postActionList ) )\n\t\t{\n\t\tACTION_LIST *postActionListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->postActionList );\n\t\tint status;\n\n\t\tENSURES( postActionListPtr != NULL );\n\t\tREQUIRES( sanityCheckActionList( postActionListPtr ) );\n\n\t\tstatus = checkActionIndirect( postActionListPtr,\n\t\t\t\t\t\t\t\t\t  checkSignatureActionFunction, \n\t\t\t\t\t\t\t\t\t  signingKeyPresent );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAdd Enveloping Information \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add keyset information (this function is also used by the de-enveloping \n   routines) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addKeysetInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t   IN_RANGE( CRYPT_ENVINFO_KEYSET_SIGCHECK, \\\n\t\t\t\t\t\t\t CRYPT_ENVINFO_KEYSET_DECRYPT ) \\\n\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE keysetFunction,\n\t\t\t\t   IN_HANDLE const CRYPT_KEYSET keyset )\n\t{\n\tCRYPT_KEYSET *iKeysetPtr;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( keysetFunction == CRYPT_ENVINFO_KEYSET_ENCRYPT || \\\n\t\t\t  keysetFunction == CRYPT_ENVINFO_KEYSET_DECRYPT || \\\n\t\t\t  keysetFunction == CRYPT_ENVINFO_KEYSET_SIGCHECK );\n\tREQUIRES( isHandleRangeValid( keyset ) );\n\n\t/* Figure out which keyset we want to set */\n\tswitch( keysetFunction )\n\t\t{\n\t\tcase CRYPT_ENVINFO_KEYSET_ENCRYPT:\n\t\t\tiKeysetPtr = &envelopeInfoPtr->iEncryptionKeyset;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ENVINFO_KEYSET_DECRYPT:\n\t\t\tiKeysetPtr = &envelopeInfoPtr->iDecryptionKeyset;\n\t\t\tbreak;\n\n\t\tcase CRYPT_ENVINFO_KEYSET_SIGCHECK:\n\t\t\tiKeysetPtr = &envelopeInfoPtr->iSigCheckKeyset;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make sure that the keyset hasn't already been set */\n\tif( *iKeysetPtr != CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( envelopeInfoPtr, keysetFunction,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* Remember the new keyset and increment its reference count */\n\t*iKeysetPtr = keyset;\n\treturn( krnlSendNotifier( keyset, IMESSAGE_INCREFCOUNT ) );\n\t}\n\n/* Add an encryption password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int addPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;\n\tCRYPT_CONTEXT iCryptContext;\n\tconst ACTION_LIST *preActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->preActionList );\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tACTION_RESULT actionResult;\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( envelopeInfoPtr->type != CRYPT_FORMAT_PGP );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\n\t/* Make sure that we can still add another action */\n\tif( !moreActionsPossible( preActionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Create the appropriate encryption context.  We have to be careful to \n\t   ensure that we use an algorithm which is compatible with the wrapping \n\t   mechanism */\n\tif( isStreamCipher( cryptAlgo ) || \\\n\t\tcryptStatusError( sizeofAlgoIDex( cryptAlgo, CRYPT_MODE_CBC ) ) )\n\t\tcryptAlgo = DEFAULT_CRYPT_ALGO;\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\n\t/* Derive the key into the context */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, passwordLength );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_VALUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that this key exchange action isn't already present and \n\t   insert it into the action list */\n\tactionResult = checkAction( preActionListPtr, ACTION_KEYEXCHANGE, \n\t\t\t\t\t\t\t\tiCryptContext );\n\tif( actionResult == ACTION_RESULT_ERROR || \\\n\t\tactionResult == ACTION_RESULT_INITED )\n\t\t{\n\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\tstatus = CRYPT_ERROR_INITED;\n\t\t}\n\telse\n\t\t{\n\t\tACTION_LIST *actionListDummy;\n\n\t\tstatus = addActionEx( &actionListDummy, envelopeInfoPtr, \n\t\t\t\t\t\t\t  ACTIONLIST_PREACTION, ACTION_KEYEXCHANGE, \n\t\t\t\t\t\t\t  iCryptContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n#ifdef USE_PGP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int addPgpPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t   IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\t\t   IN_LENGTH_TEXT const int passwordLength )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;\n\tCRYPT_CONTEXT iCryptContext;\n\tconst ACTION_LIST *preActionListPtr = \\\n\t\t\t\t\tDATAPTR_GET( envelopeInfoPtr->preActionList );\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE salt[ PGP_SALTSIZE + 8 ];\n\tstatic const int mode = CRYPT_MODE_CFB;\t/* int vs.enum */\n\tint status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( envelopeInfoPtr->type == CRYPT_FORMAT_PGP );\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\n\t/* Make sure that we can still add another attribute */\n\tif( !moreActionsPossible( preActionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* PGP doesn't support both PKC and conventional key exchange actions or \n\t   multiple conventional key exchange actions in the same envelope since \n\t   the session key is encrypted for the PKC action but derived from the \n\t   password for the conventional action */\n\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\tif( findPreAction( envelopeInfoPtr, ACTION_KEYEXCHANGE_PKC ) != NULL || \\\n\t\tDATAPTR_ISSET( envelopeInfoPtr->actionList ) )\n\t\t{\n\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* Create the appropriate encryption context.  PGP wrapping always uses \n\t   CFB mode (so there are no modes that need to be avoided) and the \n\t   higher-level code has constrained the algorithm type to something \n\t   that's encodable using the PGP data format so we don't need to \n\t   perform any additional checking here */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\n\t/* PGP uses CFB mode for everything so we change the mode from the \n\t   default of CBC to CFB */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate a salt and derive the key into the context */\n\tsetMessageData( &msgData, salt, PGP_SALTSIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = pgpPasswordToKey( iCryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t   password, passwordLength,\n\t\t\t\t\t\t\t\t   envelopeInfoPtr->defaultHash,\n\t\t\t\t\t\t\t\t   salt, PGP_SALTSIZE, PGP_ITERATIONS );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Insert the context into the action list.  Since PGP doesn't perform a \n\t   key exchange of a session key we insert the password-derived context \n\t   directly into the main action list */\n\tstatus = addAction( envelopeInfoPtr, ACTION_CRYPT, iCryptContext );\n\tif( cryptStatusError( status ) )\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n#endif /* USE_PGP */\n\n/* Add a context to an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addContextInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t   IN_ENUM( ACTIONLIST ) \\\n\t\t\t\t\t\t\t\tconst ACTIONLIST_TYPE actionListType,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t   IN_ENUM( ACTION ) const ACTION_TYPE actionType )\n\t{\n\tCRYPT_HANDLE iCryptHandle = cryptHandle;\n\tconst ENV_CHECKALGO_FUNCTION checkAlgoFunction = \\\n\t\t\t\t( ENV_CHECKALGO_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( envelopeInfoPtr->checkAlgoFunction );\n\tACTION_LIST *actionListPtr, *hashActionPtr;\n\tACTION_RESULT actionResult;\n\tint algorithm, mode = CRYPT_MODE_NONE, certHashAlgo, status;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( isEnumRange( actionListType, ACTIONLIST ) );\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( isEnumRange( actionType, ACTION ) );\n\tREQUIRES( checkAlgoFunction != NULL );\n\n\t/* Get the appropriate action list */\n\tswitch( actionListType )\n\t\t{\n\t\tcase ACTIONLIST_PREACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->preActionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->preActionList );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_ACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->actionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList );\n\t\t\tbreak;\n\t\t\n\t\tcase ACTIONLIST_POSTACTION:\n\t\t\tREQUIRES( DATAPTR_ISVALID( envelopeInfoPtr->postActionList ) );\n\t\t\tactionListPtr = DATAPTR_GET( envelopeInfoPtr->postActionList );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make sure that we can still add another attribute */\n\tif( !moreActionsPossible( actionListPtr ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Make sure that the algorithm information is encodable using the \n\t   selected envelope format.  This should already have been checked by\n\t   the calling function but we double-check here because this provides \n\t   a convenient centralised location for it */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && isConvAlgo( algorithm ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !checkAlgoFunction( algorithm, mode ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* If we're adding a hash action and this is a detached signature (so \n\t   that the action contains the hash of the data to be signed by the \n\t   detached signature) then the presence of an automatically-added \n\t   existing hash action isn't a problem, but we need to replace it with \n\t   the explicitly-added action */\n\tif( actionType == ACTION_HASH && \\\n\t\tTEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t{\n\t\tREQUIRES( actionListType == ACTIONLIST_ACTION );\n\n\t\t/* Check whether there's an automatically-added hash action present \n\t\t   that was created as a side-effect of adding a signature key.  If\n\t\t   there is, we just replace the existing action context with the\n\t\t   new one, leaving everything else unchanged */\n\t\thashActionPtr = findAction( envelopeInfoPtr, ACTION_HASH );\n\t\tif( hashActionPtr != NULL )\n\t\t\t{\n\t\t\tREQUIRES( sanityCheckActionList( hashActionPtr ) );\n\n\t\t\tif( TEST_FLAG( hashActionPtr->flags, \n\t\t\t\t\t\t   ACTION_FLAG_ADDEDAUTOMATICALLY ) )\n\t\t\t\t{\n\t\t\t\tstatus = cloneActionContext( &iCryptHandle, iCryptHandle, \n\t\t\t\t\t\t\t\t\t\t\t algorithm );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tstatus = replaceAction( hashActionPtr, iCryptHandle );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\n\t\t\t\t/* This is now an explicitly-added action rather than one \n\t\t\t\t   that was added automatically, as well as one for which we \n\t\t\t\t   don't need to explicitly complete the hashing */\n\t\t\t\tCLEAR_FLAG( hashActionPtr->flags, \n\t\t\t\t\t\t\tACTION_FLAG_ADDEDAUTOMATICALLY );\n\t\t\t\tSET_FLAG( hashActionPtr->flags, ACTION_FLAG_HASHCOMPLETE );\n\t\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Find the insertion point for this action and make sure that it isn't \n\t   already present.  The difference between ACTION_RESULT_INITED and \n\t   ACTION_RESULT_PRESENT is that an inited response indicates that the \n\t   user explicitly added the action and can't add it again while a \n\t   present response indicates that the action was added automatically \n\t   (and transparently) by cryptlib in response to the user adding some \n\t   other action and so its presence shouldn't be reported as an error. \n\t   This is because to the user it doesn't make any difference whether \n\t   the same action was added automatically by cryptlib or explicitly by \n\t   the user */\n\tactionResult = checkAction( actionListPtr, actionType, iCryptHandle );\n\tswitch( actionResult )\n\t\t{\n\t\tcase ACTION_RESULT_OK:\n\t\tcase ACTION_RESULT_EMPTY:\n\t\t\tbreak;\n\n\t\tcase ACTION_RESULT_INITED:\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\n\t\tcase ACTION_RESULT_PRESENT:\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase ACTION_RESULT_ERROR:\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Insert the action into the list.  If it's a non-idempotent context\n\t   (i.e. one whose state can change based on user actions) we clone it\n\t   for our own use, otherwise we just increment its reference count */\n\tif( actionType == ACTION_HASH || actionType == ACTION_CRYPT )\n\t\t{\n\t\tstatus = cloneActionContext( &iCryptHandle, iCryptHandle, \n\t\t\t\t\t\t\t\t\t algorithm );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = addActionEx( &actionListPtr, envelopeInfoPtr, actionListType, \n\t\t\t\t\t\t  actionType, iCryptHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tif( actionType == ACTION_HASH )\n\t\t{\n\t\t/* Remember that we need to hook the hash action up to a signature\n\t\t   action before we start enveloping data */\n\t\tSET_FLAG( actionListPtr->flags, ACTION_FLAG_NEEDSCONTROLLER );\n\n\t\t/* If this is a detached signature for which the hash value was \n\t\t   added explicitly by the user, we don't need to complete the \n\t\t   hashing ourselves since it's already been done by the user */\n\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t\tSET_FLAG( actionListPtr->flags, ACTION_FLAG_HASHCOMPLETE );\n\t\t}\n\n\t/* If the newly-inserted action isn't a controlling action, we're done */\n\tif( actionType != ACTION_SIGN )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether the hash algorithm used in the certificate attached to \n\t   the signing key is stronger than the one that's set for the envelope \n\t   as a whole and if it is, upgrade the envelope hash algo.  This is \n\t   based on the fact that anyone who's able to verify the certificate \n\t   using a stronger hash algorithm must also be able to verify the \n\t   envelope using the stronger algorithm.  This allows a transparent \n\t   upgrade to stronger hash algorithms as they become available */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &certHashAlgo, CRYPT_IATTRIBUTE_CERTHASHALGO );\n\tif( cryptStatusOK( status ) && \\\n\t\tisStrongerHash( certHashAlgo, envelopeInfoPtr->defaultHash ) )\n\t\tenvelopeInfoPtr->defaultHash = certHashAlgo;\n\n\t/* If there's no subject hash action available, create one so that we\n\t   can connect it to the signature action */\n\tif( DATAPTR_ISNULL( envelopeInfoPtr->actionList ) )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t/* Create a default hash action */\n\t\tsetMessageCreateObjectInfo( &createInfo, envelopeInfoPtr->defaultHash );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Add the hash action to the list */\n\t\tstatus = addActionEx( &hashActionPtr, envelopeInfoPtr, ACTIONLIST_ACTION,\n\t\t\t\t\t\t\t  ACTION_HASH, createInfo.cryptHandle );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Remember that the action was added invisibly to the caller so that\n\t\t   we don't return an error if they add it explicitly later on, and \n\t\t   that it needs to be attached to a controlling action before it \n\t\t   can be used */\n\t\tSET_FLAG( hashActionPtr->flags, ACTION_FLAG_ADDEDAUTOMATICALLY | \\\n\t\t\t\t\t\t\t\t\t\tACTION_FLAG_NEEDSCONTROLLER );\n\t\t}\n\telse\n\t\t{\n\t\t/* Find the last hash action that was added */\n\t\thashActionPtr = findLastAction( envelopeInfoPtr, ACTION_HASH );\n\t\tif( hashActionPtr == NULL )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_HASH,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n\n\t/* Connect the signature action to the last hash action that was added\n\t   and remember that this action now has a controlling action */\n\tDATAPTR_SET( actionListPtr->associatedAction, hashActionPtr );\n\tCLEAR_FLAG( hashActionPtr->flags, ACTION_FLAG_NEEDSCONTROLLER );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tEnveloping Information Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add enveloping information to an envelope */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addEnvelopeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\tIN_INT_Z const int value )\n\t{\n\tCRYPT_HANDLE cryptHandle = ( CRYPT_HANDLE ) value;\n\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( ( envInfo == CRYPT_IATTRIBUTE_INCLUDESIGCERT ) || \\\n\t\t\t  ( envInfo == CRYPT_IATTRIBUTE_ATTRONLY ) || \\\n\t\t\t  ( envInfo > CRYPT_ENVINFO_FIRST && \\\n\t\t\t\tenvInfo < CRYPT_ENVINFO_LAST ) );\n\n\t/* If it's a generic \"add a context\" action for a PGP envelope check \n\t   that everything is valid.  This is necessary because the PGP format \n\t   doesn't support the full range of enveloping capabilities */\n#ifdef USE_PGP\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \\\n\t\tenvInfo > CRYPT_ENVINFO_FIRST && \\\n\t\tenvInfo < CRYPT_ENVINFO_LAST )\n\t\t{\n\t\tconst int status = checkPgpUsage( envelopeInfoPtr, envInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsetErrorInfo( envelopeInfoPtr, envInfo,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_PGP */\n\n\t/* If it's meta-information, remember the value */\n\tswitch( envInfo )\n\t\t{\n\t\tcase CRYPT_IATTRIBUTE_INCLUDESIGCERT:\n\t\t\t/* This is on by default so we should only be turning it off */\n\t\t\tREQUIRES( value == FALSE );\n\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_NOSIGNINGCERTS );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_IATTRIBUTE_ATTRONLY:\n\t\t\t/* This is off by default so we should only be turning it on */\n\t\t\tREQUIRES( value == TRUE );\n\n\t\t\t/* Detached-signature and attribute-only messages are mutually \n\t\t\t   exclusive */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_DETACHED_SIG ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_DETACHEDSIGNATURE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ATTRONLY );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_DATASIZE:\n\t\t\tenvelopeInfoPtr->payloadSize = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_CONTENTTYPE:\n\t\t\tenvelopeInfoPtr->contentType = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_DETACHEDSIGNATURE:\n\t\t\tif( value )\n\t\t\t\t{\n\t\t\t\t/* Detached-signature and attribute-only messages are \n\t\t\t\t   mutually exclusive.  Since the attribute-only message \n\t\t\t\t   attribute is internal we can't set extended error \n\t\t\t\t   information for this one */\n\t\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t   ENVELOPE_FLAG_ATTRONLY ) )\n\t\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\tSET_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t  ENVELOPE_FLAG_DETACHED_SIG );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tCLEAR_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_DETACHED_SIG );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ENVINFO_INTEGRITY:\n\t\t\tswitch( value )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_INTEGRITY_NONE:\n\t\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t\tcase CRYPT_INTEGRITY_MACONLY:\n\t\t\t\t\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/* PGP doesn't have MAC-only integrity protection */\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\t\t\t\t}\n\t\t\t\t\tenvelopeInfoPtr->usage = ACTION_MAC;\n\t\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t\tcase CRYPT_INTEGRITY_FULL:\n\t\t\t\t\t/* If we're using authenticated encryption in the form\n\t\t\t\t\t   of crypt + MAC (rather than a combined auth-enc \n\t\t\t\t\t   encryption mode like GCM, or PGP's semi-keyed hash\n\t\t\t\t\t   function that isn't really a MAC) then we can't use a \n\t\t\t\t\t   raw session key because there are effectively two \n\t\t\t\t\t   keys present, one for the encryption and one for the \n\t\t\t\t\t   MACing.\n\t\t\t\t\t   \n\t\t\t\t\t   We generalise the check here to make sure that there \n\t\t\t\t\t   are no main envelope actions set, in practice this \n\t\t\t\t\t   can't happen because setting e.g. a hash action will \n\t\t\t\t\t   set the envelope usage to USAGE_SIGN which precludes \n\t\t\t\t\t   then setting CRYPT_ENVINFO_INTEGRITY, but the more \n\t\t\t\t\t   general check here can't hurt */\n\t\t\t\t\tif( DATAPTR_ISSET( envelopeInfoPtr->actionList ) && \\\n\t\t\t\t\t\tenvelopeInfoPtr->type != CRYPT_FORMAT_PGP )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tsetErrorInfo( envelopeInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t\t\t}\n\n\t\t\t\t\tenvelopeInfoPtr->usage = ACTION_CRYPT;\n\t\t\t\t\tSET_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\t  ENVELOPE_FLAG_AUTHENC );\n\t\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tretIntError();\n\n\t\tcase CRYPT_ENVINFO_KEYSET_SIGCHECK:\n\t\tcase CRYPT_ENVINFO_KEYSET_ENCRYPT:\n\t\tcase CRYPT_ENVINFO_KEYSET_DECRYPT:\n\t\t\t/* It's keyset information, just keep a record of it for later \n\t\t\t   use */\n\t\t\treturn( addKeysetInfo( envelopeInfoPtr, envInfo, cryptHandle ) );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE_EXTRADATA:\n\t\tcase CRYPT_ENVINFO_TIMESTAMP:\n\t\t\t{\n\t\t\tCRYPT_HANDLE *iCryptHandlePtr;\n\t\t\tACTION_LIST *actionListPtr = \\\n\t\t\t\t\t\t\tfindLastAction( envelopeInfoPtr, ACTION_SIGN );\n\n\t\t\tREQUIRES( actionListPtr == NULL || \\\n\t\t\t\t\t  sanityCheckActionList( actionListPtr ) );\n\n\t\t\t/* Find the last signature action that was added and make sure\n\t\t\t   that it doesn't already have an action of this type attached \n\t\t\t   to it */\n\t\t\tif( actionListPtr == NULL )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t\t}\n\t\t\tiCryptHandlePtr = ( envInfo == CRYPT_ENVINFO_SIGNATURE_EXTRADATA ) ? \\\n\t\t\t\t\t\t\t  &actionListPtr->iExtraData : \\\n\t\t\t\t\t\t\t  &actionListPtr->iTspSession;\n\t\t\tif( *iCryptHandlePtr != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, envInfo,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\t/* Increment its reference count and add it to the action */\n\t\t\tkrnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT );\n\t\t\t*iCryptHandlePtr = cryptHandle;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n#if 0\t/* 18/7/16 Historic value only needed for Fortezza */\n\t\tcase CRYPT_ENVINFO_ORIGINATOR:\n\t\t\t/* Historic value only needed for Fortezza */\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n#endif /* 0 */\n\n\t\tcase CRYPT_ENVINFO_COMPRESSION:\n#ifdef USE_COMPRESSION\n\t\t\t/* Make sure that we don't try and initialise the compression\n\t\t\t   multiple times */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t   ENVELOPE_FLAG_ZSTREAMINITED ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_COMPRESSION,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\t/* Initialize the compression */\n\t\t\tif( deflateInit( &envelopeInfoPtr->zStream, \\\n\t\t\t\t\t\t\t Z_DEFAULT_COMPRESSION ) != Z_OK )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tSET_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_ZSTREAMINITED );\n\n\t\t\treturn( CRYPT_OK );\n#else\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n#endif /* USE_COMPRESSION */\n\n\t\tcase CRYPT_ENVINFO_PUBLICKEY:\n\t\tcase CRYPT_ENVINFO_PRIVATEKEY:\n\t\t\treturn( addContextInfo( envelopeInfoPtr, ACTIONLIST_PREACTION,\n\t\t\t\t\t\t\t\t\tcryptHandle, ACTION_KEYEXCHANGE_PKC ) );\n\n\t\tcase CRYPT_ENVINFO_KEY:\n\t\t\t/* PGP doesn't allow KEK-based encryption so if it's a PGP\n\t\t\t   envelope we drop through and treat it as a session key */\n\t\t\tif( envelopeInfoPtr->type != CRYPT_FORMAT_PGP )\n\t\t\t\t{\n\t\t\t\treturn( addContextInfo( envelopeInfoPtr, ACTIONLIST_PREACTION,\n\t\t\t\t\t\t\t\t\t\tcryptHandle, ACTION_KEYEXCHANGE ) );\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase CRYPT_ENVINFO_SESSIONKEY:\n\t\t\t/* We can't add more than one session key */\n\t\t\tif( DATAPTR_ISSET( envelopeInfoPtr->actionList ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\t/* If we're using authenticated encryption in the form of crypt + \n\t\t\t   MAC (rather than a combined auth-enc encryption mode like GCM, \n\t\t\t   or PGP's semi-keyed hash function that isn't really a MAC) \n\t\t\t   then we can't use a raw session key because there are \n\t\t\t   effectively two keys present, one for the encryption and one \n\t\t\t   for the MACing */\n\t\t\tif( TEST_FLAG( envelopeInfoPtr->flags, ENVELOPE_FLAG_AUTHENC ) && \\\n\t\t\t\tenvelopeInfoPtr->type != CRYPT_FORMAT_PGP )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_INTEGRITY,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\n\t\t\treturn( addContextInfo( envelopeInfoPtr, ACTIONLIST_ACTION,\n\t\t\t\t\t\t\t\t\tcryptHandle, ACTION_CRYPT ) );\n\n\t\tcase CRYPT_ENVINFO_HASH:\n\t\t\treturn( addContextInfo( envelopeInfoPtr, ACTIONLIST_ACTION,\n\t\t\t\t\t\t\t\t\tcryptHandle, ACTION_HASH ) );\n\n\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\treturn( addContextInfo( envelopeInfoPtr, ACTIONLIST_POSTACTION,\n\t\t\t\t\t\t\t\t\tcryptHandle, ACTION_SIGN ) );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addEnvelopeInfoString( INOUT ENVELOPE_INFO *envelopeInfoPtr,\n\t\t\t\t\t\t\t\t  IN_RANGE( CRYPT_ENVINFO_PASSWORD, \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PASSWORD ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE envInfo,\n\t\t\t\t\t\t\t\t  IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\t\t\t  IN_LENGTH_TEXT const int valueLength )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( sanityCheckEnvelope( envelopeInfoPtr ) );\n\tREQUIRES( envInfo == CRYPT_ENVINFO_PASSWORD );\n\tREQUIRES( valueLength > 0 && valueLength <= CRYPT_MAX_TEXTSIZE );\n\n#ifdef USE_PGP\n\tif( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )\n\t\treturn( addPgpPasswordInfo( envelopeInfoPtr, value, valueLength ) );\n#endif /* USE_PGP */\n\treturn( addPasswordInfo( envelopeInfoPtr, value, valueLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initEnvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr )\n\t{\n\tassert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );\n\n\tREQUIRES_V( !TEST_FLAG( envelopeInfoPtr->flags, \n\t\t\t\t\t\t\tENVELOPE_FLAG_ISDEENVELOPE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( envelopeInfoPtr->addInfoFunction, addEnvelopeInfo );\n\tFNPTR_SET( envelopeInfoPtr->addInfoStringFunction, addEnvelopeInfoString );\n\tFNPTR_SET( envelopeInfoPtr->checkMissingInfoFunction, checkMissingInfo );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/io/dns.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib DNS Interface Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return extended error information for a DNS error */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getAddrInfoError( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t const int errorCode,\n\t\t\t\t\t\t\t IN_ERROR const int status )\n\t{\n#ifdef USE_ERRMSGS\n  #if defined( __WINDOWS__ )\n\tBYTE errorStringBuffer[ 1024 + 8 ];\n\tint errorStringLen;\n  #elif defined( USE_IPv6 )\n\tconst char *errorString = gai_strerror( errorCode );\n\tconst int errorStringLen = strlen( errorString );\n  #endif /* System-specific error string handling */\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Get the text string describing the error that occurred */\n  #ifdef __WINDOWS__\n\terrorStringLen = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | \\\n\t\t\t\t\t\t\t\t\t FORMAT_MESSAGE_IGNORE_INSERTS | \\\n\t\t\t\t\t\t\t\t\t FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL,\n\t\t\t\t\t\t\t\t\t errorCode,\n\t\t\t\t\t\t\t\t\t MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),\n\t\t\t\t\t\t\t\t\t errorStringBuffer, 1024, NULL );\n\tif( errorStringLen <= 0 )\n\t\t{\n\t\tmemcpy( errorStringBuffer, \"<<<Unknown>>>\", 13 );\n\t\terrorStringLen = 13;\n\t\t}\n\tsetErrorString( NETSTREAM_ERRINFO, errorStringBuffer, errorStringLen );\n  #elif defined( USE_IPv6 )\n\tsetErrorString( NETSTREAM_ERRINFO, errorString, errorStringLen );\n  #else\n\tmapNetworkError( netStream, errorCode, TRUE, status );\n  #endif /* __WINDOWS__ */\n#endif /* USE_ERRMSGS */\n\n\t/* Make the error status fatal and exit */\n\tnetStream->persistentStatus = status;\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tIPv6 API Emulation\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Emulation of IPv6 DNS lookup functions */\n\n#if !defined( USE_IPv6_DNSAPI )\n\n#define getaddrinfo\t\tmy_getaddrinfo\n#define freeaddrinfo\tmy_freeaddrinfo\n#define getnameinfo\t\tmy_getnameinfo\n\n#ifdef EBCDIC_CHARS\n  /* Since we're ASCII internally but the strings passed to these emulated \n     system functions are EBCDIC, we can't do comparisons for character\n\t literals since they'll be the ASCII form, not the EBCDIC form.  To\n\t deal with this, we explicitly give the EBCDIC character code for \n\t character values that we check for */\n  #define DOTTED_DELIMITER\t\t0x4B\n#else\n  #define DOTTED_DELIMITER\t\t'.'\n#endif /* EBCDIC_CHARS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int addAddrInfo( INOUT_OPT struct addrinfo *prevAddrInfoPtr,\n\t\t\t\t\t\tOUT_PTR_COND struct addrinfo **addrInfoPtrPtr,\n\t\t\t\t\t\tIN_BUFFER( addrLen ) const void *address, \n\t\t\t\t\t\tIN_RANGE( IP_ADDR_SIZE, IP_ADDR_SIZE ) \\\n\t\t\t\t\t\t\tconst int addrLen, \n\t\t\t\t\t\tIN_PORT const int port,\n\t\t\t\t\t\tconst int socketType )\n\t{\n\tstruct addrinfo *addrInfoPtr;\n\tstruct sockaddr_in *sockAddrPtr;\n\n\tassert( prevAddrInfoPtr == NULL || \\\n\t\t\tisWritePtr( prevAddrInfoPtr, sizeof( struct addrinfo ) ) );\n\tassert( isWritePtr( addrInfoPtrPtr, sizeof( struct addrinfo * ) ) );\n\tassert( isReadPtrDynamic( address, addrLen ) );\n\t\n\tREQUIRES( addrLen == IP_ADDR_SIZE );\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\n\t/* Clear return value */\n\t*addrInfoPtrPtr = NULL;\n\n\t/* Allocate the new element, clear it, and set fixed fields for IPv4 */\n\taddrInfoPtr = clAlloc( \"addAddrInfo\", sizeof( struct addrinfo ) );\n\tif( addrInfoPtr == NULL )\n\t\treturn( OUT_OF_MEMORY_ERROR );\n\tsockAddrPtr = clAlloc( \"addAddrInfo\", sizeof( struct sockaddr_in ) );\n\tif( sockAddrPtr == NULL )\n\t\t{\n\t\tclFree( \"addAddrInfo\", addrInfoPtr );\n\t\treturn( OUT_OF_MEMORY_ERROR );\n\t\t}\n\tmemset( addrInfoPtr, 0, sizeof( struct addrinfo ) );\n\tmemset( sockAddrPtr, 0, sizeof( struct sockaddr_in ) );\n\tif( prevAddrInfoPtr != NULL )\n\t\tprevAddrInfoPtr->ai_next = addrInfoPtr;\n\taddrInfoPtr->ai_family = PF_INET;\n\taddrInfoPtr->ai_socktype = socketType;\n\taddrInfoPtr->ai_protocol = ( socketType == SOCK_STREAM ) ? \\\n\t\t\t\t\t\t\t   IPPROTO_TCP : IPPROTO_UDP;\n\taddrInfoPtr->ai_addrlen = sizeof( struct sockaddr_in );\n\taddrInfoPtr->ai_addr = ( struct sockaddr * ) sockAddrPtr;\n\n\t/* Set the port and address information.  In general we'd copy the\n\t   address to the sockAddrPtr->sin_addr.s_addr member, however on\n\t   Crays, which don't have 32-bit data types, this is a 32-bit\n\t   bitfield, so we have to use the encapsulating struct */\n\tsockAddrPtr->sin_family = AF_INET;\n\tsockAddrPtr->sin_port = htons( ( in_port_t ) port );\n\tmemcpy( &sockAddrPtr->sin_addr, address, addrLen );\n\t*addrInfoPtrPtr = addrInfoPtr;\n\n\treturn( 0 );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nstatic int SOCKET_API my_getaddrinfo( IN_STRING_OPT const char *nodename,\n\t\t\t\t\t\t\t\t\t  IN_STRING const char *servname,\n\t\t\t\t\t\t\t\t\t  const struct addrinfo *hints,\n\t\t\t\t\t\t\t\t\t  OUT_PTR_COND struct addrinfo **res )\n\t{\n\tstruct hostent *pHostent;\n\tconst int nodenameLen = ( nodename != NULL ) ? strlen( nodename ) : 0;\n#ifdef EBCDIC_CHARS\n\tchar servBuffer[ 16 + 8 ];\n#endif /* EBCDIC_CHARS */\n\tint port, hostErrno, i, status, LOOP_ITERATOR;\n\tgethostbyname_vars();\n\n\tassert( isReadPtr( hints, sizeof( struct addrinfo ) ) );\n\tassert( isWritePtr( res, sizeof( struct addrinfo * ) ) );\n\n\tstatic_assert( sizeof( in_addr_t ) == IP_ADDR_SIZE, \\\n\t\t\t\t   \"in_addr_t size\" );\n\n\tANALYSER_HINT_STRING( nodename );\n\tANALYSER_HINT_STRING( servname );\n\n\t/* Perform basic error checking.  Since this is supposed to be an \n\t   emulation of a (normally) built-in function we don't perform any \n\t   REQUIRES()-style checking but only apply the basic checks that the \n\t   normal built-in form does */\n\tif( servname == NULL || hints == NULL || res == NULL || \\\n\t\t( nodename == NULL && !( hints->ai_flags & AI_PASSIVE ) ) )\n\t\t{\n\t\t/* Provide a more useful diagnostic than the default Unix one of\n\t\t   lighting up a giant '?' in the middle of the dashboard */\n\t\tDEBUG_DIAG(( \"Invalid argument passed to emulated getaddrinfo()\" ));\n\t\treturn( -1 );\n\t\t}\n\n\t/* Clear return value */\n\t*res = NULL;\n\n\t/* Convert the address information from the system character set to\n\t   the internal one if required so that strGetNumeric() can process it.\n\t   This is required because, as an emulated system function, we're\n\t   being passed strings in the system character set and need to back-\n\t   convert them to the internal one if we process them using an internal\n\t   function rather than a system one */\n#ifdef EBCDIC_CHARS\n\tstrcpy( servBuffer, servname );\n\tbufferToAscii( servBuffer, servBuffer );\n\tservname = servBuffer;\n#endif /* EBCDIC_CHARS */\n\n\t/* Convert the text-string port number into a numeric value */\n\tstatus = strGetNumeric( servname, strlen( servname ), &port, 1, 65535 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Provide a more useful diagnostic than the default Unix one of\n\t\t   lighting up a giant '?' in the middle of the dashboard */\n\t\tDEBUG_DIAG(( \"Invalid servname string passed to emulated \"\n\t\t\t\t\t \"getaddrinfo()\" ));\n\t\treturn( -1 );\n\t\t}\n\n\t/* If there's no interface specified and we're creating a server-side\n\t   socket, prepare to listen on any interface.  Note that BeOS can only\n\t   bind to one interface at a time, so INADDR_ANY actually binds to the\n\t   first interface that it finds */\n\tif( nodename == NULL && ( hints->ai_flags & AI_PASSIVE ) )\n\t\t{\n\t\tconst in_addr_t address = INADDR_ANY;\n\n\t\treturn( addAddrInfo( NULL, res, &address, sizeof( in_addr_t  ), \n\t\t\t\t\t\t\t port, hints->ai_socktype ) );\n\t\t}\n\tENSURES( nodename != NULL );\n\n\t/* If it's a dotted address, there's a single address, convert it to\n\t   in_addr form and return it.  Because it's possible to create DNS \n\t   names that look very close to dotted-decimal IP addresses, we scan \n\t   the entire node name looking for something that isn't a dotted-\n\t   decimal address and only assume it's a dotted address if no \n\t   exceptions are found.\n\t   \n\t   Note for EBCDIC use that since this is an emulation of an OS \n\t   function the string is already in EBCDIC form, so we don't use the \n\t   cryptlib-internal functions for this */\n\tLOOP_LARGE( i = 0, i < nodenameLen, i++ )\n\t\t{\n\t\tif( !isdigit( nodename[ i ] ) && nodename[ i ] != DOTTED_DELIMITER )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( i >= nodenameLen )\n\t\t{\n\t\tconst in_addr_t address = inet_addr( nodename );\n\n\t\tif( isBadAddress( address ) )\n\t\t\treturn( HOST_NOT_FOUND_ERROR );\n\t\treturn( addAddrInfo( NULL, res, &address, sizeof( in_addr_t  ), \n\t\t\t\t\t\t\t port, hints->ai_socktype ) );\n\t\t}\n\n\t/* It's a host name, convert it to the in_addr form */\n\tgethostbyname_threadsafe( nodename, pHostent, hostErrno );\n\tif( pHostent == NULL ) \n\t\t{\n\t\t/* Returning an error code at this point gets a bit tricky because\n\t\t   we're emulating a system/library call and so can't return a\n\t\t   proper getaddrinfo()-style EAI_xxx error.  The best that we can\n\t\t   do is return the gethostbyname() errno information if it appears\n\t\t   to contain a useful error code, and failing that fall back to\n\t\t   the OS-specific host-not-found error code */\n\t\tif( hostErrno != 0 && hostErrno != -1 )\n\t\t\treturn( hostErrno );\n\t\treturn( HOST_NOT_FOUND_ERROR );\n\t\t}\n\tENSURES( pHostent->h_length == IP_ADDR_SIZE );\n\tLOOP_MED( i = 0, i < IP_ADDR_COUNT && \\\n\t\t\t\t\t pHostent->h_addr_list[ i ] != NULL, i++ )\n\t\t{\n\t\tint netAPIstatus;\n\n\t\tnetAPIstatus = addAddrInfo( NULL, res, pHostent->h_addr_list[ i ], \n\t\t\t\t\t\t\t\t\tpHostent->h_length, port, \n\t\t\t\t\t\t\t\t\thints->ai_socktype );\n\t\tif( cryptStatusError( netAPIstatus ) )\n\t\t\treturn( netAPIstatus );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( 0 );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void SOCKET_API my_freeaddrinfo( INOUT struct addrinfo *ai )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( ai, sizeof( struct addrinfo ) ) );\n\n\t/* Perform basic error checking.  Since this is supposed to be an \n\t   emulation of a (normally) built-in function we don't perform any \n\t   REQUIRES()-style checking but only apply the basic checks that the \n\t   normal built-in form does */\n\tif( ai == NULL )\n\t\t{\n\t\t/* Provide a more useful diagnostic than the default Unix one of\n\t\t   lighting up a giant '?' in the middle of the dashboard */\n\t\tDEBUG_DIAG(( \"Invalid argument passed to emulated freeaddrinfo()\" ));\n\t\treturn;\n\t\t}\n\n\tLOOP_MED( i = 0, ai != NULL && i < IP_ADDR_COUNT, i++ )\n\t\t{\n\t\tstruct addrinfo *addrInfoCursor = ai;\n\n\t\tai = ai->ai_next;\n\t\tif( addrInfoCursor->ai_addr != NULL )\n\t\t\tclFree( \"my_freeaddrinfo\", addrInfoCursor->ai_addr );\n\t\tclFree( \"my_freeaddrinfo\", addrInfoCursor );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\t\t\t\t\t\t\t\t\t  \nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int SOCKET_API my_getnameinfo( IN_BUFFER( salen ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst struct sockaddr *sa, \n\t\t\t\t\t\t\t\t\t  IN SIZE_TYPE salen,\n\t\t\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( nodelen ) char *node, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT SIZE_TYPE nodelen,\n\t\t\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( servicelen ) \\\n\t\t\t\t\t\t\t\t\t\t\tchar *service, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) SIZE_TYPE \\\n\t\t\t\t\t\t\t\t\t\t\tservicelen,\n\t\t\t\t\t\t\t\t\t  IN int flags )\n\t{\n\tconst struct sockaddr_in *sockAddr = ( struct sockaddr_in * ) sa;\n\tconst char *ipAddress;\n\tint ipAddressLen;\n\n\tassert( isReadPtrDynamic( sa, salen ) && \\\n\t\t\tsalen >= sizeof( struct sockaddr_in ) );\n\tassert( isReadPtrDynamic( node, nodelen ) && nodelen >= 10 );\n\tassert( isReadPtrDynamic( service, servicelen ) && servicelen >= 8 );\n\n\t/* Perform basic error checking.  Since this is supposed to be an \n\t   emulation of a (normally) built-in function we don't perform any \n\t   REQUIRES()-style checking but only apply the basic checks that the \n\t   normal built-in form does */\n\tif( sa == NULL || salen < sizeof( struct sockaddr_in ) || \\\n\t\tsalen > MAX_INTLENGTH_SHORT || \\\n\t\tnode == NULL || nodelen < 10 || nodelen > MAX_INTLENGTH_SHORT || \\\n\t\tservice == NULL || servicelen < 8 || servicelen > MAX_INTLENGTH_SHORT )\n\t\t{\n\t\t/* Provide a more useful diagnostic than the default Unix one of\n\t\t   lighting up a giant '?' in the middle of the dashboard */\n\t\tDEBUG_DIAG(( \"Invalid argument passed to emulated getnameinfo()\" ));\n\t\treturn( -1 );\n\t\t}\n\n\t/* Clear return values */\n\tstrlcpy_s( node, nodelen, \"<Unknown>\" );\n\tstrlcpy_s( service, servicelen, \"0\" );\n\n\t/* Get the remote system's address and port number */\n\tif( ( ipAddress = inet_ntoa( sockAddr->sin_addr ) ) == NULL )\n\t\treturn( -1 );\n\tipAddressLen = strlen( ipAddress );\n\tif( ipAddressLen <= 0 || ipAddressLen > nodelen - 1 )\n\t\treturn( -1 );\n\tmemcpy( node, ipAddress, ipAddressLen );\n\tnode[ ipAddressLen ] = '\\0';\n\tif( sprintf_s( service, servicelen, \"%d\",\n\t\t\t\t   ntohs( sockAddr->sin_port ) ) < 0 )\n\t\treturn( -1 );\n\n\treturn( 0 );\n\t}\n#endif /* !USE_IPv6_DNSAPI */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tDNS Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a host's IP address */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getAddressInfo( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tOUT_PTR_COND struct addrinfo **addrInfoPtrPtr,\n\t\t\t\t\tIN_BUFFER_OPT( nameLen ) const char *name, \n\t\t\t\t\tIN_LENGTH_Z const int nameLen, \n\t\t\t\t\tIN_PORT const int port, const BOOLEAN isServer,\n\t\t\t\t\tconst BOOLEAN isDgramSocket )\n\t{\n\tstruct addrinfo hints;\n\tchar nameBuffer[ MAX_DNS_SIZE + 1 + 8 ], portBuffer[ 16 + 8 ];\n\tint errorCode;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtr( addrInfoPtrPtr, sizeof( struct addrinfo * ) ) );\n\tassert( isServer || name != NULL );\n\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\tREQUIRES( isServer || \\\n\t\t\t  ( !isServer && name != NULL ) );\n\tREQUIRES( ( name == NULL && nameLen == 0 ) || \\\n\t\t\t  ( name != NULL && \\\n\t\t\t\tnameLen > 0 && nameLen < MAX_DNS_SIZE ) );\n\tREQUIRES( isDgramSocket == TRUE || isDgramSocket == FALSE );\n\n\t/* Clear return value */\n\t*addrInfoPtrPtr = NULL;\n\n\t/* Convert the name and port into the null-terminated text-string format \n\t   required by getaddrinfo().  The reason why the port is given as a \n\t   string rather than a port number is that we can also optionally \n\t   specify the port to connect to via a service name.  Of course it's \n\t   more or less pot luck whether the service you want is a recognised \n\t   one so everyone specifies the port anyway, however the reason why \n\t   this unnecessary flexibility is there is because getaddrinfo() was \n\t   seen as a universal replacement for a pile of other functions, \n\t   including (for this case) getservbyname() */\n\tif( name != NULL )\n\t\t{\n\t\tREQUIRES( rangeCheck( nameLen, 1, MAX_DNS_SIZE ) );\n\t\tmemcpy( nameBuffer, name, nameLen );\n\t\tnameBuffer[ nameLen ] = '\\0';\n\t\tname = nameBuffer;\n\t\t}\n\tsprintf_s( portBuffer, 8, \"%d\", port );\n\n\t/* If we're a client and using auto-detection of a PKI service, try and\n\t   locate it via DNS SRV */\n\tif( !isServer && name != NULL && nameLen == 12 && \\\n\t\t( !memcmp( name, \"[Autodetect]\", 12 ) || *name == '_' ) )\n\t\t{\n\t\tint localPort, status;\n\n\t\tstatus = findHostInfo( netStream, nameBuffer, MAX_DNS_SIZE, \n\t\t\t\t\t\t\t   &localPort, name, nameLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tname = nameBuffer;\n\t\tsprintf_s( portBuffer, 8, \"%d\", localPort );\n\t\t}\n\n\t/* Convert the address information to the system character set if \n\t   required */\n#ifdef EBCDIC_CHARS\n\tif( name != NULL )\n\t\tbufferToEbcdic( nameBuffer, nameBuffer );\n\tbufferToEbcdic( portBuffer, portBuffer );\n#endif /* EBCDIC_CHARS */\n\n\t/* Set up the port information and hint information needed by\n\t   getaddrinfo().  The use of PF_UNSPEC is a bit problematic because RFC\n\t   2553 is usually interpreted to mean \"look for all addresses\" rather\n\t   than the more sensible \"look for any address\".  The reason why this\n\t   is a problem is because getaddrinfo() ends up looking for unnecessary\n\t   IPv6 addresses, either by returning IPv6 addresses when the system\n\t   doesn't do IPv6 or spending a lot of time groping around for IPv6\n\t   stuff and/or further unnecessary addresses when it's already got what\n\t   it needs.\n\t   \n\t   This is made worse by confusion over implementation details, for \n\t   example early implementations of getaddrinfo() in glibc would always \n\t   try an AAAA lookup even on an IPv4-only system/network, resulting in \n\t   long delays as the resolver timed out and fell back to a straight A \n\t   lookup.  There was some disagreement over whether this was right or \n\t   wrong, and how to fix it (IPv6 purists who never noticed the problem \n\t   seemed to think that it was right, everyone else thought that it was \n\t   wrong).\n\t   \n\t   Variations of this problem exist, e.g. if an IPv4 address is in \n\t   /etc/hosts and DNS is down, the resolver will still spend ages \n\t   (several minutes in some cases) groping around for an IPv6 address \n\t   before it finally gives up and falls back to what it already knows \n\t   from /etc/hosts.  Switching the hint from AF_UNSPEC to AF_INET \n\t   bypasses this problem, but has the downside of disabling IPv6 use.\n\n\t   This problem was partially fixed post-RFC 2553 by adding the\n\t   AI_ADDRCONFIG flag, which tells getaddrinfo() to only do AAAA queries\n\t   if the system has at least one IPv6 source address configured, and\n\t   the same for A and IPv4 (in other words it applies some common sense,\n\t   which is how it should have behaved in the first place).\n\t   Unfortunately this flag isn't very widely supported yet, so it usually\n\t   ends up being no-op'd out by the auto-config.\n\t   \n\t   In addition under Windows Vista and newer there are always IPv6 \n\t   addresses in use by a bunch of Windows services that simultaneously \n\t   listen on IPv4 and IPv6 addresses, so that things regress back to the \n\t   pre-AI_ADDRCONFIG behaviour, although there seems to be some \n\t   optimisation in place to prevent the DNS-lookup issues from coming \n\t   back as well.  Unfortunately this also means that an attempt to look \n\t   up an address like \"localhost\" for a server-side socket will \n\t   preferentially return an IPv6 address [::1] rather than an IPv4 \n\t   address 127.0.0.1, which works if the client also gets a IPv6 address \n\t   but not if it's expecting the more usual IPv4 one.\n\n\t   Bounds Checker 6.x may crash in the getaddrinfo() call if maximum \n\t   checking is enabled.  To fix this, set the checking level to normal \n\t   rather than maximum */\n\tmemset( &hints, 0, sizeof( struct addrinfo ) );\n\thints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;\n\tif( isServer )\n\t\t{\n\t\t/* If it's a server, set the AI_PASSIVE flag so that if the\n\t\t   interface that we're binding to isn't explicitly specified we get\n\t\t   any interface */\n\t\thints.ai_flags |= AI_PASSIVE;\n\t\t}\n#if 1\n\thints.ai_family = PF_UNSPEC;\n#else\n\tBOOLEAN forceIPv4 = FALSE;\n\tBOOLEAN_INT preferIPV4;\n\n\tstatus = krnlSendMessage( certInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &preferIPV4,\n\t\t\t\t\t\t\t  CRYPT_OPTION_PREFERIPV4 );\n\tif( cryptStatusOK( status ) && preferIPV4 )\n\t\t{\n\t\t/* Override any potential defaulting to IPv6 by the local system \n\t\t   to force the use of IPv4, which is going to be far more probable \n\t\t   than IPv6 for the foreseeable future */\n\t\thints.ai_family = PF_INET;\n\t\tforceIPv4 = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\t/* Just use whatever the local system gives us */\n\t\thints.ai_family = PF_UNSPEC;\n\t\t}\n#endif /* 1 */\n\thints.ai_socktype = isDgramSocket ? SOCK_DGRAM : SOCK_STREAM;\n\terrorCode = getaddrinfo( name, portBuffer, &hints, addrInfoPtrPtr );\n\tif( errorCode != 0 )\n\t\t{\n#if 0\n\t\tif( !forceIPv4 )\n\t\t\treturn( getHostError( netStream, CRYPT_ERROR_OPEN ) );\n\n\t\t/* We overrode the protocol-type selection, which may have been the \n\t\t   cause of the failure, try again with whatever we can get rather \n\t\t   than forcing IPv4 */\n\t\thints.ai_family = PF_UNSPEC;\n\t\tif( getaddrinfo( name, portBuffer, &hints, addrInfoPtrPtr ) )\n\t\t\treturn( getHostError( netStream, CRYPT_ERROR_OPEN ) );\n#else\n\t\treturn( getAddrInfoError( netStream, errorCode, \n\t\t\t\t\t\t\t\t  CRYPT_ERROR_OPEN ) );\n#endif /* 0 */\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid freeAddressInfo( struct addrinfo *addrInfoPtr )\n\t{\n\tassert( isWritePtr( addrInfoPtr, sizeof( struct addrinfo ) ) );\n\n\tfreeaddrinfo( addrInfoPtr );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \\\nvoid getNameInfo( IN_BUFFER( sockAddrLen ) const void *sockAddr,\n\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) const int sockAddrLen,\n\t\t\t\t  OUT_BUFFER( addressMaxLen, *addressLen ) char *address, \n\t\t\t\t  IN_LENGTH_DNS const int addressMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( addressMaxLen ) int *addressLen, \n\t\t\t\t  OUT_PORT_Z int *port )\n\t{\n\tchar nameBuffer[ MAX_DNS_SIZE + 8 ];\n\tchar portBuffer[ 32 + 8 ];\n\tint nameLength, portLength, localPort, status;\n\n\tassert( isReadPtrDynamic( sockAddr, sockAddrLen ) );\n\tassert( isWritePtrDynamic( address, addressMaxLen ) );\n\tassert( isWritePtr( port, sizeof( int ) ) );\n\n\tREQUIRES_V( sockAddrLen >= 8 && sockAddrLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( addressMaxLen >= CRYPT_MAX_TEXTSIZE / 2 && \\\n\t\t\t\taddressMaxLen <= MAX_DNS_SIZE );\n\n\t/* Clear return values */\n\tmemcpy( address, \"<Unknown>\", 9 );\n\t*addressLen = 9;\n\t*port = 0;\n\n\t/* Some Windows implementations of getnameinfo() call down to\n\t   getservbyport() assuming that it will always succeed and therefore\n\t   leave the port/service argument unchanged when it doesn't, so the \n\t   following call must be made with the NI_NUMERICSERV flag specified \n\t   (which it would be anyway, cryptlib always treats the port as a \n\t   numeric arg).  Oddly enough the macro version of this function in \n\t   wspiapi.h used for IPv4-only situations does get it right */\n\tif( getnameinfo( sockAddr, sockAddrLen, nameBuffer, MAX_DNS_SIZE, \n\t\t\t\t\t portBuffer, 32, NI_NUMERICHOST | NI_NUMERICSERV ) != 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't get host name for socket\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\tnameLength = strlen( nameBuffer );\n\tportLength = strlen( portBuffer );\n\tif( nameLength <= 0 || nameLength > addressMaxLen || \\\n\t\tportLength <= 0 || portLength > 8 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Returned host name data is invalid\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n#ifdef EBCDIC_CHARS\n\tebcdicToAscii( nameBuffer, nameBuffer, nameLength );\n\tebcdicToAscii( portBuffer, portBuffer, portLength );\n#endif /* EBCDIC_CHARS */\n\tREQUIRES_V( rangeCheck( nameLength, 1, addressMaxLen ) );\n\tmemcpy( address, nameBuffer, nameLength );\n\t*addressLen = nameLength;\n\tstatus = strGetNumeric( portBuffer, portLength, &localPort, 1, 65536 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Returned host port is invalid\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\t*port = localPort;\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/dns_srv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib DNS SRV Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n/* Use DNS SRV to auto-detect host information.  Note that this code is \n   disabled by default, before enabling it you should make sure that your\n   system's DNS services can't serve as an attack vector due to the \n   complexity of DNS packet processing.  The Unix DNS interface is \n   particularly bad here, the problematic nature of the requirement that \n   implementations manually disassemble the DNS data themselves has been \n   demonstrated by the numerous bugs that have hit implementations that did \n   this, examples being the bind 9.2.1 gethostans() vulnerability and, in a \n   rather extreme example, the l0pht antisniff 1.0 vulnerability which \n   required no less than three successive patches to the same code to \n   finally eradicate the one bug (!!).  The fact that every new \n   implementation that wants to use this functionality has to independently \n   reinvent the code to do it means that these vulnerabilities will be with \n   us more or less forever, which is why this facility is disabled by \n   default */\n\n#if defined( USE_TCP ) && defined( USE_DNSSRV )\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with DNS SRV enabled.\" )\n#endif /* Warn about special features enabled */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tWindows DNS SRV Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __WINDOWS__ ) && !defined( __WIN16__ )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int convertToSrv( OUT_BUFFER_FIXED( srvNameMaxLen ) char *srvName, \n\t\t\t\t\t\t IN_LENGTH_DNS const int srvNameMaxLen, \n\t\t\t\t\t\t IN_STRING const char *hostName )\n\t{\n\tconst int hostNameLength = strlen( hostName ) + 1;\n\tint i, LOOP_ITERATOR;\t   /* For trailing '\\0' */\n\n\tassert( isReadPtrDynamic( srvName, srvNameMaxLen ) );\n\tassert( isReadPtr( hostName, MIN_DNS_SIZE ) );\n\t\n\tANALYSER_HINT_STRING( hostName );\n\n\tREQUIRES( srvNameMaxLen > 16 && srvNameMaxLen <= MAX_DNS_SIZE );\n\tREQUIRES( srvName != hostName );\n\n\t/* Clear return value */\n\tmemset( srvName, 0, min( 16, srvNameMaxLen ) );\n\n\t/* Make sure that the (worst-case) result will fit into the output \n\t   buffer */\n\tif( 16 + hostNameLength > srvNameMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Prepend the service info to the start of the host name.  This\n\t   converts foo.bar.com into _pkiboot._tcp.bar.com in preparation for\n\t   the DNS SRV lookup */\n\tLOOP_LARGE( i = 0, i < hostNameLength, i++ )\n\t\t{\n\t\tif( hostName[ i ] == '.' )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tmemcpy( srvName, \"_pkiboot._tcp.\", 14 );\n\tif( i < hostNameLength )\n\t\t{\n\t\tREQUIRES( boundsCheck( 14, hostNameLength - i, srvNameMaxLen ) );\n\t\tmemcpy( srvName + 14, hostName + i, hostNameLength - i );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( boundsCheck( 14, hostNameLength, srvNameMaxLen ) );\n\t\tmemcpy( srvName + 14, hostName, hostNameLength );\n\t\t}\n\tsrvName[ srvNameMaxLen ] = '\\0';\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getSrvFQDN( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t   OUT_BUFFER_FIXED( fqdnMaxLen ) char *fqdn, \n\t\t\t\t\t   IN_LENGTH_DNS const int fqdnMaxLen )\n\t{\n\tPDNS_RECORD pDns = NULL;\n\tstruct hostent *hostInfo;\n\tstatic char cachedFQDN[ MAX_DNS_SIZE + 8 ];\n\tstatic time_t lastFetchTime = 0;\n#ifdef __WINCE__\n\tchar fqdnBuffer[ MAX_DNS_SIZE + 8 ], *fqdnPtr = fqdnBuffer;\n#else\n\tchar *fqdnPtr;\n#endif /* Win32 vs. WinCE */\n\tint status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( fqdn, fqdnMaxLen ) );\n\n\tREQUIRES( fqdnMaxLen > 0 && fqdnMaxLen <= MAX_DNS_SIZE );\n\n\t/* Clear return value */\n\tmemset( fqdn, 0, min( 16, fqdnMaxLen ) );\n\n\t/* The uncached FQDN check is quite slow and resource-intensive (it\n\t   seems to do a full reload of the DNS subsystem), to lighten the load\n\t   we only try a new one once a minute */\n\tif( lastFetchTime >= getTime() - 60 )\n\t\t{\n\t\tstrlcpy_s( fqdn, fqdnMaxLen, cachedFQDN );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're doing a full autodetect we first have to determine the local \n\t   host's FQDN.  This gets quite tricky because the behavior of\n\t   gethostbyaddr() changed with Win2K so we have to use the DNS API, but\n\t   this isn't available in older versions of Windows.  If we are using\n\t   the DNS API, we have to use the barely-documented\n\t   DNS_QUERY_BYPASS_CACHE option to get what we want.\n\t   \n\t   One relief at least is that the braindead Posix semantics for \n\t   gethostname() (see the comment in the Unix getFQDN() below) don't \n\t   apply under Windows.  If the buffer size is too small, the call\n\t   fails, so we don't need to jump through any hoops to deal with this\n\t   situation */\n\tif( gethostname( cachedFQDN, MAX_DNS_SIZE ) == 0 && \\\n\t\t( hostInfo = gethostbyname( cachedFQDN ) ) != NULL )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_MED( i = 0, i < IP_ADDR_COUNT && \\\n\t\t\t\t\t\t hostInfo->h_addr_list[ i ] != NULL, i++ )\n\t\t\t{\n\t\t\tstruct in_addr address;\n\n\t\t\t/* Reverse the byte order for the in-addr.arpa lookup and\n\t\t\t   convert the address to dotted-decimal notation */\n\t\t\taddress.S_un.S_addr = *( ( DWORD * ) hostInfo->h_addr_list[ i ] );\n\t\t\tsprintf_s( cachedFQDN, MAX_DNS_SIZE, \"%s.in-addr.arpa\",\n\t\t\t\t\t   inet_ntoa( address ) );\n\n\t\t\t/* Check for a name */\n\t\t\tif( DnsQuery( cachedFQDN, DNS_TYPE_PTR, DNS_QUERY_BYPASS_CACHE,\n\t\t\t\t\t\t  NULL, &pDns, NULL ) == ERROR_SUCCESS )\n\t\t\t\tbreak;\n\t\t\tpDns = NULL;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( pDns == NULL )\n\t\t{\n\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\"Couldn't determine FQDN of local machine\", \n\t\t\t\t\t\t\t\t40, CRYPT_ERROR_NOTFOUND, TRUE ) );\n\t\t}\n#ifdef __WINCE__\n\tunicodeToAscii( fqdnBuffer, MAX_DNS_SIZE, pDns->Data.PTR.pNameHost,\n\t\t\t\t\twcslen( pDns->Data.PTR.pNameHost ) + 1 );\n#else\n\tfqdnPtr = pDns->Data.PTR.pNameHost;\n#endif /* Win32 vs. WinCE */\n\tstatus = convertToSrv( cachedFQDN, MAX_DNS_SIZE, fqdnPtr );\n\tDnsFree( pDns, DnsFreeRecordList );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\"Couldn't convert FQDN into SRV query name\", \n\t\t\t\t\t\t\t\t41, CRYPT_ERROR_NOTFOUND, TRUE ) );\n\t\t}\n\n\t/* Remember the value that we just found to lighten the load on the\n\t   resolver when we perform repeat queries */\n\tstrlcpy_s( fqdn, fqdnMaxLen, cachedFQDN );\n\tlastFetchTime = getTime();\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint findHostInfo( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t  OUT_BUFFER_FIXED( hostNameMaxLen ) char *hostName, \n\t\t\t\t  IN_LENGTH_DNS const int hostNameMaxLen, \n\t\t\t\t  OUT_PORT_Z int *hostPort, \n\t\t\t\t  IN_BUFFER( nameLen ) const char *name, \n\t\t\t\t  IN_LENGTH_DNS const int nameLen )\n\t{\n\tPDNS_RECORD pDns = NULL, pDnsInfo = NULL, pDnsCursor;\n\tDNS_STATUS dnsStatus;\n\tchar nameBuffer[ MAX_DNS_SIZE + 8 ];\n\tint priority = 32767, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( hostName, hostNameMaxLen ) );\n\tassert( isWritePtr( hostPort, sizeof( int ) ) );\n\tassert( isReadPtr( name, MIN_DNS_SIZE ) );\n\n\tREQUIRES( hostNameMaxLen > 0 && hostNameMaxLen <= MAX_DNS_SIZE );\n\tREQUIRES( nameLen > 0 && nameLen < MAX_DNS_SIZE );\n\tREQUIRES( hostName != name );\n\n\t/* Clear return values */\n\tmemset( hostName, 0, min( 16, hostNameMaxLen ) );\n\t*hostPort = 0;\n\n\t/* Convert the name to a null-terminated string */\n\tREQUIRES( rangeCheck( nameLen, 1, MAX_DNS_SIZE ) );\n\tmemcpy( nameBuffer, name, nameLen );\n\tnameBuffer[ nameLen ] = '\\0';\n\tname = nameBuffer;\n\n\t/* If we're doing a full autodetect we construct the SRV query using the \n\t   local machine's FQDN.  This fails more often than not because of \n\t   NATing and the use of private networks, but at least we can try */\n\tif( !strCompareZ( name, \"[Autodetect]\" ) )\n\t\t{\n\t\tconst int status = getSrvFQDN( netStream, hostName, hostNameMaxLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tname = hostName;\n\t\t}\n\n\t/* Perform a DNS SRV lookup to find the host info.  SRV has basic load-\n\t   balancing facilities but for now we just use the highest-priority \n\t   host that we find (it's rarely-enough used that we'll be lucky to\n\t   find SRV info let alone any load-balancing setup) */\n\tdnsStatus = DnsQuery( ( const LPSTR ) name, DNS_TYPE_SRV, DNS_QUERY_STANDARD,\n\t\t\t\t\t\t  NULL, &pDns, NULL );\n\tif( dnsStatus != 0 || pDns == NULL )\n\t\t{\n\t\tint dummy;\n\n\t\treturn( getSocketError( netStream, CRYPT_ERROR_NOTFOUND, &dummy ) );\n\t\t}\n\tLOOP_MED( ( pDnsCursor = pDns, i = 0 ), \n\t\t\t  pDnsCursor != NULL && i < IP_ADDR_COUNT,\n\t\t\t  ( pDnsCursor = pDnsCursor->pNext, i++ ) )\n\t\t{\n\t\tif( pDnsCursor->Data.SRV.wPriority < priority )\n\t\t\t{\n\t\t\tpriority = pDnsCursor->Data.SRV.wPriority;\n\t\t\tpDnsInfo = pDnsCursor;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n#ifdef __WINCE__\n\tif( pDnsInfo == NULL || \\\n\t\twcslen( pDnsInfo->Data.SRV.pNameTarget ) + 1 > hostNameMaxLen )\n#else\n\tif( pDnsInfo == NULL || \\\n\t\tstrlen( pDnsInfo->Data.SRV.pNameTarget ) + 1 > hostNameMaxLen )\n#endif /* Win32 vs. WinCE */\n\t\t{\n\t\tDnsFree( pDns, DnsFreeRecordList );\n\t\treturn( setSocketError( netStream, \"Invalid DNS SRV entry for host\", 30,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_NOTFOUND, TRUE ) );\n\t\t}\n\n\t/* Copy over the host info for this SRV record */\n#ifdef __WINCE__\n\tunicodeToAscii( hostName, hostNameMaxLen,\n\t\t\t\t\tpDnsInfo->Data.SRV.pNameTarget, \n\t\t\t\t\twcslen( pDnsInfo->Data.SRV.pNameTarget ) + 1 );\n#else\n\tstrlcpy_s( hostName, hostNameMaxLen, pDnsInfo->Data.SRV.pNameTarget );\n#endif /* Win32 vs. WinCE */\n\t*hostPort = pDnsInfo->Data.SRV.wPort;\n\n\t/* Clean up */\n\tDnsFree( pDns, DnsFreeRecordList );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tUnix DNS SRV Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __UNIX__ ) && \\\n\t  !( defined( __CYGWIN__) || ( defined( sun ) && OSVERSION <= 5 ) || \\\n\t\t defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\t\t defined( __UCLIBC__ ) )\n\n#define SRV_PRIORITY_OFFSET\t( NS_RRFIXEDSZ + 0 )\n#define SRV_WEIGHT_OFFSET\t( NS_RRFIXEDSZ + 2 )\n#define SRV_PORT_OFFSET\t\t( NS_RRFIXEDSZ + 4 )\n#define SRV_NAME_OFFSET\t\t( NS_RRFIXEDSZ + 6 )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getFQDN( STDC_UNUSED INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tOUT_BUFFER_FIXED( fqdnMaxLen ) char *fqdn, \n\t\t\t\t\tIN_LENGTH_DNS const int fqdnMaxLen )\n\t{\n\tstruct hostent *hostInfo;\n\tchar *hostNamePtr = NULL;\n\tint addressCount, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( fqdn, fqdnMaxLen ) );\n\n\tREQUIRES( fqdnMaxLen > 0 && fqdnMaxLen <= MAX_DNS_SIZE );\n\n\t/* Clear return value */\n\tmemset( fqdn, 0, min( 16, fqdnMaxLen ) );\n\n\t/* First get the host name and if it's the FQDN, exit.  gethostname() \n\t   has the idiotic property that if the name doesn't fit into the given\n\t   buffer the function will return a (possibly non-null-terminated) \n\t   truncated value instead of reporting an error.  At least that's \n\t   what the spec says, many implementations don't do this but in case\n\t   there's one that's stupid enough to actually do so we force null-\n\t   termination after we've called the function */\n\tif( gethostname( fqdn, fqdnMaxLen ) == -1 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tfqdn[ fqdnMaxLen - 1 ] = '\\0';\n\tif( strchr( fqdn, '.' ) != NULL )\n\t\t{\n\t\t/* If the hostname has a dot in it, it's the FQDN */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Now get the hostent info and walk through it looking for the FQDN */\n\tif( ( hostInfo = gethostbyname( fqdn ) ) == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tLOOP_MED( addressCount = 0, \n\t\t\t  addressCount < IP_ADDR_COUNT && \\\n\t\t\t\thostInfo->h_addr_list[ addressCount ] != NULL, addressCount++ )\n\t\t{\n\t\tchar **aliasPtrPtr;\t\n\t\tint i, LOOP_ITERATOR_ALT;\n\t\n\t\t/* If the hostname has a dot in it, it's the FQDN.  This should be\n\t\t   the same as the gethostname() output, but we check again just in\n\t\t   case */\n\t\tif( strchr( hostInfo->h_name, '.' ) != NULL )\n\t\t\t{\n\t\t\thostNamePtr = hostInfo->h_name;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Try for the FQDN in the aliases */\n\t\tif( hostInfo->h_aliases == NULL )\n\t\t\tcontinue;\n\t\tLOOP_MED_ALT( ( aliasPtrPtr = hostInfo->h_aliases, i = 0 ),\n\t\t\t\t\t  *aliasPtrPtr != NULL && \\\n\t\t\t\t\t\t!strchr( *aliasPtrPtr, '.' ) && i < IP_ADDR_COUNT, \n\t\t\t\t\t  ( aliasPtrPtr++, i++ ) );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( *aliasPtrPtr != NULL )\n\t\t\t{\n\t\t\thostNamePtr = *aliasPtrPtr;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( hostNamePtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* We found the FQDN, return it to the caller */\n\tif( strlen( hostNamePtr ) + 1 > fqdnMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tstrlcpy_s( fqdn, fqdnMaxLen, hostNamePtr );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint findHostInfo( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t  OUT_BUFFER_FIXED( hostNameMaxLen ) char *hostName, \n\t\t\t\t  IN_LENGTH_DNS const int hostNameMaxLen, \n\t\t\t\t  OUT_PORT_Z int *hostPort, \n\t\t\t\t  IN_BUFFER( nameLen ) const char *name, \n\t\t\t\t  IN_LENGTH_DNS const int nameLen )\n\t{\n\tunion {\n\t\tHEADER header;\n\t\tBYTE buffer[ NS_PACKETSZ + 8 ];\n\t\t} dnsQueryInfo;\n\tBYTE *namePtr, *endPtr;\n\tchar nameBuffer[ MAX_DNS_SIZE + 8 ];\n\tint resultLen, nameSegmentLen, qCount, aCount, minPriority = 32767;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( hostName, hostNameMaxLen ) );\n\tassert( isWritePtr( hostPort, sizeof( int ) ) );\n\tassert( isReadPtr( name, MIN_DNS_SIZE ) );\n\n\tREQUIRES( hostNameMaxLen > 0 && hostNameMaxLen <= MAX_DNS_SIZE );\n\tREQUIRES( nameLen > 0 && nameLen < MAX_DNS_SIZE );\n\tREQUIRES( hostName != name );\n\n\t/* Clear return values */\n\tmemset( hostName, 0, min( 16, hostNameMaxLen ) );\n\t*hostPort = 0;\n\n\t/* Convert the name to a null-terminated string */\n\tREQUIRES( rangeCheck( nameLen, 1, MAX_DNS_SIZE ) );\n\tmemcpy( nameBuffer, name, nameLen );\n\tnameBuffer[ nameLen ] = '\\0';\n\tname = nameBuffer;\n\n\t/* If we're doing a full autodetect, we construct the SRV query using\n\t   the local machine's FQDN.  This fails more often than not because of\n\t   NATing and the use of private networks, but at least we can try */\n\tif( !strCompareZ( name, \"[Autodetect]\" ) )\n\t\t{\n\t\tconst int status = getFQDN( netStream, hostName, hostNameMaxLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tname = hostName;\n\t\t}\n#ifdef EBCDIC_CHARS\n\telse\n\t\t{\n\t\t/* We're about to use OS functions, convert the input to EBCDIC.  If\n\t\t   we've used autodetection the output from getFQDN will already be \n\t\t   in EBCDIC form */\n\t\tname = bufferToEbcdic( hostName, name );\n\t\t}\n#endif /* EBCDIC_CHARS */\n\n\t/* Try and fetch a DNS SRV record (RFC 2782) matching the host info.  \n\t   Unlike Windows' relatively nice DnsQuery() API, Unix has a horribly\n\t   clunky interface that requires manually grovelling through wire-\n\t   format data to dig out the bits of interest.  OpenBSD provides a \n\t   function getrrsetbyname()/freerrset() that's equivalent to Windows' \n\t   DnsQuery()/DnsFree() but it's OpenBSD-only so we can't really rely \n\t   on it being present */\n\tresultLen = res_query( name, C_IN, T_SRV, dnsQueryInfo.buffer,\n\t\t\t\t\t\t   NS_PACKETSZ );\n\tif( resultLen < NS_HFIXEDSZ || resultLen > NS_PACKETSZ )\n\t\t{\n\t\tint dummy;\n\n\t\treturn( getSocketError( netStream, CRYPT_ERROR_NOTFOUND, &dummy ) );\n\t\t}\n\tif( dnsQueryInfo.header.rcode != 0 || dnsQueryInfo.header.tc != 0 )\n\t\t{\n\t\t/* If we get a non-zero response code (rcode) or the results were\n\t\t   truncated (tc), we can't go any further.  In theory a truncated\n\t\t   response is probably OK since many servers return the address\n\t\t   records for the host in the Additional Data section to save the\n\t\t   client having to perform a second lookup and we don't need these\n\t\t   at this point so we can ignore the fact that they've been\n\t\t   truncated, but for now we treat truncation as an error */\n\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\"RR contains non-zero response code or \"\n\t\t\t\t\t\t\t\t\"response was truncated\", 60,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_NOTFOUND, FALSE ) );\n\t\t}\n\tqCount = ntohs( dnsQueryInfo.header.qdcount );\n\taCount = ntohs( dnsQueryInfo.header.ancount );\n\tif( qCount < 0 || qCount > 100 || aCount <= 0 || aCount > 100 )\n\t\t{\n\t\t/* No answer entries (or a suspicious number of entries, which is \n\t\t   less likely), we're done */\n\t\treturn( setSocketError( netStream, \"RR contains no answer entries\", 29,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_NOTFOUND, FALSE ) );\n\t\t}\n\n\t/* Skip the queries */\n\tnamePtr = dnsQueryInfo.buffer + NS_HFIXEDSZ;\n\tendPtr = dnsQueryInfo.buffer + resultLen;\n\tLOOP_LARGE( i = 0, i < qCount && namePtr < endPtr && i < 100, i++ )\n\t\t{\n\t\tnameSegmentLen = dn_skipname( namePtr, endPtr );\n\t\tif( nameSegmentLen <= 0 || nameSegmentLen > MAX_DNS_SIZE )\n\t\t\t{\n\t\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\t\"RR contains invalid question\", 28,\n\t\t\t\t\t\t\t\t\tCRYPT_ERROR_BADDATA, FALSE ) );\n\t\t\t}\n\t\tnamePtr += nameSegmentLen + NS_QFIXEDSZ;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( namePtr > endPtr )\n\t\t{\n\t\treturn( setSocketError( netStream, \"RR contains invalid data\", 24,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_BADDATA, FALSE ) );\n\t\t}\n\n\t/* Process the answers.  SRV has basic load-balancing facilities, but\n\t   for now we just use the highest-priority host that we find (it's\n\t   rarely-enough used that we'll be lucky to find SRV info, let alone\n\t   any load-balancing setup) */\n\tLOOP_MED( i = 0, i < aCount, i++ )\n\t\t{\n\t\tint priority, port;\n\n\t\tnameSegmentLen = dn_skipname( namePtr, endPtr );\n\t\tif( nameSegmentLen <= 0 || nameSegmentLen > MAX_DNS_SIZE || \\\n\t\t\tnamePtr + nameSegmentLen + NS_SRVFIXEDSZ > endPtr )\n\t\t\t{\n\t        return( setSocketError( netStream, \"RR contains invalid answer\", 26,\n\t                                CRYPT_ERROR_BADDATA, FALSE ) );\n\t\t\t}\n\t\tnamePtr += nameSegmentLen;\n\t\tpriority = ntohs( *( ( u_short * ) ( namePtr + SRV_PRIORITY_OFFSET ) ) );\n\t\tport = ntohs( *( ( u_short * ) ( namePtr + SRV_PORT_OFFSET ) ) );\n\t\tnamePtr += NS_SRVFIXEDSZ;\n\t\tif( priority < minPriority )\n\t\t\t{\n\t\t\t/* We've got a new higher-priority host, use that */\n\t\t\tnameSegmentLen = dn_expand( dnsQueryInfo.buffer, endPtr,\n\t\t\t\t\t\t\t\t\t\tnamePtr, hostName, hostNameMaxLen );\n\t\t\t*hostPort = port;\n\t\t\tminPriority = priority;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a lower-priority host, skip it */\n\t\t\tnameSegmentLen = dn_skipname( namePtr, endPtr );\n\t\t\t}\n\t\tif( nameSegmentLen <= 0 || nameSegmentLen > MAX_DNS_SIZE || \\\n\t\t\tnamePtr + nameSegmentLen > endPtr )\n\t\t\t{\n\t        return( setSocketError( netStream, \"RR contains invalid answer\", 26,\n\t                                CRYPT_ERROR_NOTFOUND, FALSE ) );\n\t\t\t}\n\t\thostName[ nameSegmentLen ] = '\\0';\n\t\tnamePtr += nameSegmentLen;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n#ifdef EBCDIC_CHARS\n\tebcdicToAscii( hostName, strlen( hostName ) );\n#endif /* EBCDIC_CHARS */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* OS-specific host detection */\n\n#endif /* USE_TCP && USE_DNSSRV */\n"
  },
  {
    "path": "deps/cl345/io/file.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFile Stream I/O Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __UNIX__ ) && defined( __linux__ )\n  /* In order for the fileReadonly() check to work we need to be able to\n\t check errno, however for this to work the headers that specify that\n\t threading is being used must be the first headers included\n\t (specifically, the include order has to be pthread.h, unistd.h,\n\t everything else) or errno.h, which is pulled in by stdlib.h, gets\n\t set up as an extern int rather than a function */\n  #include \"crypt.h\"\n#endif /* Older Linux broken include-file dependencies */\n#if defined( __Nucleus__ )\n  /* Some other OSes also have the same problem */\n  #include \"crypt.h\"\n#endif /* Nucleus */\n\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n  #include \"file.h\"\n#else\n  #include \"io/stream_int.h\"\n  #include \"io/file.h\"\n#endif /* Compiler-specific includes */\n\n/* In order to get enhanced control over things like file security and\n   buffering we can't use stdio but have to rely on using OS-level file\n   routines, which is essential for working with things like ACL's for\n   sensitive files and forcing disk writes for files we want to erase.\n   Without the forced disk write the data in the cache doesn't get flushed\n   before the file delete request arrives, after which it's discarded rather\n   than being written, so the file never gets overwritten.  In addition some\n   embedded environments don't support stdio so we have to supply our own\n   alternatives.\n\n   When implementing the following for new systems there are certain things\n   that you need to ensure to guarantee error-free operation:\n\n\t- File permissions should be set as indicated by the file open flags.\n\n\t- File sharing controls (shared vs. exclusive access locks) should be\n\t  implemented.\n\n\t- If the file is locked for exclusive access, the open call should either\n\t  block until the lock is released (they're never held for more than a\n\t  fraction of a second) or return CRYPT_ERROR_TIMEOUT depending on how\n\t  the OS handles locks.\n\n   When erasing data, we may run into problems on embedded systems using\n   solid-state storage that implements wear-levelling by using a log-\n   structured filesystem (LFS) type arrangement.  These work by never\n   writing a sector twice but always appending newly-written data at the\n   next free location until the volume is full, at which point a garbage\n   collector runs to reclaim.  A main goal of LFS's is speed (data is\n   written in large sequential writes rather than lots of small random\n   writes) and error-recovery by taking advantage of the characteristics\n   of the log structure, however a side-effect of the write mechanism is\n   that it makes wear-levelling management quite simple.  However, the use\n   of a LFS also makes it impossible to reliably overwrite data, since\n   new writes never touch the existing data.  There's no easy way to cope\n   with this since we have no way of telling what the underlying media is\n   doing with our data.  A mediating factor though is that embedded systems\n   are usually sealed, single-use systems where the chances of a second user\n   accessing the data is low.  The only possible threat then is post system-\n   retirement recovery of the data, presumably if it contains valuable data\n   it'll be disposed of appropriately */\n\n/* If we're using DDNAME I/O under MVS we can't use the Posix I/O APIs but\n   have to use stdio stream I/O functions, enabled via CONFIG_NO_STDIO since\n   we have to use RECFM=x specifiers and other oddities */\n\n#if defined( __MVS__ ) && defined( DDNAME_IO )\n  #define CONFIG_NO_STDIO\n#endif /* __MVS__ && DDNAME_IO */\n\n/* Symbolic defines for stdio-style file access modes */\n\n#if defined( __MVS__ ) && defined( DDNAME_IO )\n  #pragma convlit( suspend )\n  #define MODE_READ\t\t\t\"rb,byteseek\"\n  #define MODE_WRITE\t\t\"wb,byteseek,recfm=*\"\n  #define MODE_READWRITE\t\"rb+,byteseek,recfm=*\"\n  #pragma convlit( resume )\n#elif defined( EBCDIC_CHARS )\n  #pragma convlit( suspend )\n  #define MODE_READ\t\t\t\"rb\"\n  #define MODE_WRITE\t\t\"wb\"\n  #define MODE_READWRITE\t\"rb+\"\n  #pragma convlit( resume )\n#else\n  #define MODE_READ\t\t\t\"rb\"\n  #define MODE_WRITE\t\t\"wb\"\n  #define MODE_READWRITE\t\"rb+\"\n#endif /* Different types of I/O and character sets */\n\n#ifdef USE_FILES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise a file stream structure */\n\nstatic void initFileStream( OUT STREAM *stream,\n\t\t\t\t\t\t\tIN const BOOLEAN isReadOnly )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( isReadOnly == TRUE || isReadOnly == FALSE );\n\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tstream->type = STREAM_TYPE_FILE;\n\tif( isReadOnly )\n\t\tINIT_FLAGS( stream->flags, STREAM_FLAG_READONLY );\n\telse\n\t\tINIT_FLAGS( stream->flags, STREAM_FLAG_NONE );\n\t}\n\n/* Append a filename to a path and add the suffix.  If we're on an EBCDIC \n   system we need two versions of this function, a standard ASCII one for\n   internal-use paths and an EBCDIC one for use with path components coming\n   from the OS like the location of $HOME */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int appendFilename( INOUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen, \n\t\t\t\t\t\t   IN_ENUM( BUILDPATH ) \\\n\t\t\t\t\t\t\t\tconst BUILDPATH_OPTION_TYPE option )\n\t{\n\tconst int partialPathLen = strlen( path );\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  fileNameLen > 0 && fileNameLen < MAX_BUFFER_SIZE ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\tREQUIRES( isEnumRange( option, BUILDPATH ) );\n\n\t/* Clear return value */\n\t*pathLen = 0;\n\n\t/* If we're using a fixed filename it's quite simple, just append it\n\t   and we're done */\n\tif( option == BUILDPATH_RNDSEEDFILE )\n\t\t{\n\t\tif( partialPathLen + 12 > pathMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tREQUIRES( boundsCheck( partialPathLen, 12, pathMaxLen ) );\n\t\tmemcpy( path + partialPathLen, \"randseed.dat\", 12 );\n\t\t*pathLen = partialPathLen + 12;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* User-defined filenames are a bit more complex because we have to\n\t   safely append a variable-length quantity to the path */\n\tif( partialPathLen + fileNameLen + 4 > pathMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tREQUIRES( boundsCheck( partialPathLen + fileNameLen, fileNameLen, \n\t\t\t\t\t\t   pathMaxLen ) );\n\tmemcpy( path + partialPathLen, fileName, fileNameLen );\n\tmemcpy( path + partialPathLen + fileNameLen, \".p15\", 4 );\n\t*pathLen = partialPathLen + fileNameLen + 4;\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef EBCDIC_CHARS\n\n#pragma convlit( suspend )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int appendFilenameEBCDIC( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t\t\t IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int fileNameLen, \n\t\t\t\t\t\t\t\t IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t\t\t const BUILDPATH_OPTION_TYPE option )\n\t{\n\tconst int partialPathLen = strlen( path );\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  fileNameLen > 0 && fileNameLen < MAX_BUFFER_SIZE ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\tREQUIRES( isEnumRange( option, BUILDPATH ) );\n\n\t/* Clear return value */\n\t*pathLen = 0;\n\n\t/* If we're using a fixed filename it's quite simple, just append it\n\t   and we're done */\n\tif( option == BUILDPATH_RNDSEEDFILE )\n\t\t{\n\t\tif( partialPathLen + 12 > pathMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tREQUIRES( boundsCheck( partialPathLen, 12, pathMaxLen ) );\n\t\tmemcpy( path + partialPathLen, \"randseed.dat\", 12 );\n\t\t*pathLen = partialPathLen + 12;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* User-defined filenames are a bit more complex because we have to\n\t   safely append a variable-length quantity to the path */\n\tif( partialPathLen + fileNameLen + 4 > pathMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tREQUIRES( boundsCheck( partialPathLen + fileNameLen, fileNameLen, \n\t\t\t\t\t\t   pathMaxLen ) );\n\tmemcpy( path + partialPathLen, fileName, fileNameLen );\n\tmemcpy( path + partialPathLen + fileNameLen, \".p15\", 4 );\n\t*pathLen = partialPathLen + fileNameLen + 4;\n\n\treturn( CRYPT_OK );\n\t}\n\n#pragma convlit( resume )\n\n#endif /* EBCDIC_CHARS */\n\n/* Wipe a file from the current position to EOF.  If the current position\n   is set to 0 this wipes the entire file.  Vestigia nulla retrorsum */\n\nstatic void eraseFile( STREAM *stream, long position, long length )\n\t{\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES_V( position >= 0 && position < MAX_BUFFER_SIZE );\n\tREQUIRES_V( length >= 0 && length < MAX_BUFFER_SIZE );\n\t\t\t\t/* May be zero if a file-open failed leaving a zero-length \n\t\t\t\t   file */\n\n\t/* Wipe the file.  This is a somewhat basic function that performs a\n\t   single pass of overwriting the data with random data, it's not\n\t   possible to do much better than this without getting very OS-\n\t   specific.\n\n\t   You'll NEVER get rid of me, Toddy */\n\tLOOP_MAX_CHECK( length > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE buffer[ ( BUFSIZ * 2 ) + 8 ];\n\t\tconst int bytesToWrite = min( length, BUFSIZ * 2 );\n\t\tint status;\n\n\t\t/* We need to make sure that we fill the buffer with random data for\n\t\t   each write, otherwise compressing filesystems will just compress\n\t\t   it to nothing.  OTOH we don't want to fail the erase if we can't\n\t\t   get random data, so we perform the write anyway even under the \n\t\t   remote condition that there's no randomness available */\n\t\tsetMessageData( &msgData, buffer, bytesToWrite );\n\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tstatus = fileWrite( stream, buffer, bytesToWrite );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\t/* An error occurred while writing, exit */\n\t\tlength -= bytesToWrite;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t( void ) fileFlush( stream );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAMX File Stream Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __AMX__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const int modes[] = {\n\t\tFJ_O_RDONLY, FJ_O_RDONLY,\n\t\tFJ_O_WRONLY | FJ_O_CREAT | FJ_O_NOSHAREANY,\n\t\tFJ_O_RDWR | FJ_O_NOSHAREWR\n\t\t};\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file */\n\tstream->fd = fjopen( fileName, openMode, ( openMode & FJ_O_CREAT ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t FJ_S_IREAD | FJ_S_IWRITE : 0 );\n\tif( stream->fd < 0 )\n\t\t{\n\t\tconst int errNo = fjfserrno();\n\n\t\treturn( ( errNo == FJ_EACCES || errNo == FJ_ESHARE ) ? \\\n\t\t\t\t\tCRYPT_ERROR_PERMISSION : \\\n\t\t\t\t( errNo == FJ_ENOENT ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tfjclose( stream->fd );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = fjread( stream->fd, buffer, length ) ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( ( byteCount = fjwrite( stream->fd, buffer, length ) ) < 0 || \\\n\t\tbyteCount != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\tfjflush( stream->fd );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream,\t\n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( fjlseek( stream->fd, position, FJ_SEEK_SET ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tstruct fjxstat fileInfo;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( fjstat( fileName, &fileInfo ) < 0 )\n\t\treturn( TRUE );\n\n\treturn( ( fileInfo->_xxx ) ? TRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tstruct fjxstat fileInfo;\n\tint length, position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tif( fjstat( fileName, &fileInfo ) < 0 )\n\t\treturn;\n\tlength = fileInfo._xxx;\n\tif( ( position = fjtell( stream->fd ) ) < 0 )\n\t\treturn;\n\tlength -= position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tfjchsize( stream->fd, position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tstruct fjxstat fileInfo;\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tfjunlink( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tfjstat( fileName, &fileInfo );\n\teraseFile( &stream, 0, fileInfo._xxx );\n\tfjchsize( stream.fd, 0 );\n\n\t/* Reset the file's attributes */\n\tfjfattr( stream.fd, FJ_DA_NORMAL );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tfjunlink( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH && fjisdir( path ) == 0 )\n\t\t{\n\t\t/* The directory doesn't exist, try and create it */\n\t\tif( fjmkdir( path ) < 0 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tuC/OS-II / embOS File Stream Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __UCOSII__ ) || defined( __embOS__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const char *modes[] = { MODE_READ, MODE_READ,\n\t\t\t\t\t\t\t\t   MODE_WRITE, MODE_READWRITE };\n\tconst char *openMode;\n\tint errorCode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file */\n\terrorCode = FS_FOpenEx( fileName, openMode, &stream->pFile );\n\tif( errorCode != 0 )\n\t\t{\n\t\tswitch( errorCode )\n\t\t\t{\n\t\t\tcase FS_ERRCODE_VOLUME_FULL:\n\t\t\tcase FS_ERRCODE_TOO_MANY_FILES_OPEN:\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\t\tcase FS_ERRCODE_PATH_NOT_FOUND:\n\t\t\tcase FS_ERRCODE_VOLUME_NOT_FOUND:\n\t\t\tcase FS_ERRCODE_VOLUME_NOT_MOUNTED:\n\t\t\tcase FS_ERRCODE_FILE_DIR_NOT_FOUND:\n\t\t\tcase FS_ERRCODE_STORAGE_NOT_PRESENT:\n\t\t\tcase FS_ERRCODE_STORAGE_NOT_READY:\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t\n\t\t\tcase FS_ERRCODE_READ_ONLY_FILE:\n\t\t\tcase FS_ERRCODE_READ_ONLY_VOLUME:\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION ); \n\n\t\t\tcase FS_ERRCODE_OUT_OF_MEMORY:\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t\n\t\t\tdefault:\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tFS_FClose( stream->pFile );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = FS_FRead( stream->pFile, 1, length, buffer ) ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tint bytesWritten;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( ( bytesWritten = FS_Write( stream->pFile, buffer, length ) ) < 0 || \\\n\t\tbytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( ( FS_SyncFile( stream->pFile ) == 0 ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( FS_FSeek( stream->pFile, position, FS_SEEK_SET ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tU8 fileAttr;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( ( fileAttr = FS_GetFileAttributes( fileName ) ) == 0xFF )\n\t\treturn( TRUE );\n\n\treturn( ( fileAttr & FS_ATTR_READ_ONLY ) ? TRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tU32 length;\n\tI32 position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tlength = FS_GetFileSize( stream->pFile );\n\tif( length == ( U32 ) -1 )\n\t\treturn;\n\tposition = FS_FTell( stream->pFile );\n\tif( position == -1 )\n\t\treturn;\n\tlength -= position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tFS_Truncate( stream->pFile, 0 );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tFS_Remove( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it.  We use FS_Truncate()\n\t   rather than FS_SetFileSize() since the latter seems to be intended \n\t   more to pre-allocate space for a file rather than to shorten it.\n\t   \n\t   embOS includes a function FS_WipeFile(), but we use eraseFile() for\n\t   portability to uC/OS-II */\n\tfileClearToEOF( &stream );\n\tFS_Truncate( stream.pFile, 0 );\n\n\t/* Reset the file's attributes and delete it */\n\tsFileClose( &stream );\n\tFS_SetFileAttributes( fileName, FS_ATTR_ARCHIVE );\n\tFS_SetFileTime( fileName, 0 );\n\tFS_Remove( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\t/* Create the directory.  This returns 0 on success or 1 if the \n\t\t   directory already exists, so we only exit on a negative error\n\t\t   value */\n\t\tif( FS_CreateDir( path ) < 0 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tuITRON File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* See the comment in str_file.h for uITRON file handling */\n\n#elif defined( __ITRON__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file */\n\treturn( CRYPT_ERROR_OPEN );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tANALYSER_HINT_STRING( fileName );\n\n\treturn( TRUE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tposition = ftell( stream->filePtr );\n\tfseek( stream->filePtr, 0, SEEK_END );\n\tlength = ftell( stream->filePtr ) - position;\n\tfseek( stream->filePtr, position, SEEK_SET );\n\teraseFile( stream, position, length );\n\tchsize( fileno( stream->filePtr ), position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tstruct ftime fileTime;\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tremove( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tfseek( stream.filePtr, 0, SEEK_END );\n\tlength = ( int ) ftell( stream.filePtr );\n\tfseek( stream.filePtr, 0, SEEK_SET );\n\teraseFile( stream, 0, length );\n\n\t/* Truncate the file and reset the timestamps */\n\tchsize( fileno( stream.filePtr ), 0 );\n\tmemset( &fileTime, 0, sizeof( struct ftime ) );\n\tsetftime( fileno( stream.filePtr ), &fileTime );\n\n\t/* Finally, delete the file */\n\tsFileClose( &stream );\n\tremove( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMacintosh File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MAC__ )\n\n/* Convert a C to a Pascal string */\n\nstatic void CStringToPString( const char *cstring, StringPtr pstring )\n\t{\n\tshort len = min( strlen( cstring ), 255 );\n\n\tmemmove( pstring + 1, cstring, len );\n\t*pstring = len;\n\t}\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tStr255 pFileName;\n\tOSErr err;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\n\tCStringToPString( fileName, pFileName );\n\terr = FSMakeFSSpec( 0, 0, pFileName, &stream->fsspec );\n\tif( err == dirNFErr || err == nsvErr )\n\t\t{\n\t\t/* Volume or parent directory not found */\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tif( err != noErr && err != fnfErr )\n\t\t{\n\t\t/* fnfErr is OK since the fsspec is still valid */\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\tif( mode & FILE_FLAG_WRITE )\n\t\t{\n\t\t/* Try and create the file, specifying its type and creator.  The\n\t\t   wierd string-looking constants are Mac compiler-specific and\n\t\t   evaluate to 32-bit unsigned type and creator IDs.  Unfortunately\n\t\t   the type value, which should be '????', triggers warnings about\n\t\t   trigraphs in unnecessarily pedantic compilers so we have to use\n\t\t   the hex equivalent instead */\n\t\terr = FSpCreate( &stream->fsspec, 0x3F3F3F3F /* '????' */, 'CLib', \n\t\t\t\t\t\t smSystemScript );\n\t\tif( err == wPrErr || err == vLckdErr || err == afpAccessDenied )\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\tif( err != noErr && err != dupFNErr && err != afpObjectTypeErr )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\terr = FSpOpenDF( &stream->fsspec, mode & FILE_FLAG_RW_MASK, \n\t\t\t\t\t &stream->refNum );\n\tif( err == nsvErr || err == dirNFErr || err == fnfErr )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( err == opWrErr || err == permErr || err == afpAccessDenied )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\tif( err != noErr )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tFSClose( stream->refNum );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n    long byteCount = length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( FSRead( stream->refNum, &bytesRead, buffer ) != noErr )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tlong bytesWritten = length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( FSWrite( stream->refNum, &bytesWritten, buffer ) != noErr || \\\n\t\t( int ) bytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tFileParam paramBlock;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\tparamBlock.ioCompletion = NULL;\n\tparamBlock.ioFRefNum = stream->refNum;\n\tPBFlushFileSync( ( union ParamBlockRec * ) &paramBlock );\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( SetFPos( stream->refNum, fsFromStart, position ) != noErr )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tStr255 pFileName;\n\tFSSpec fsspec;\n\tOSErr err;\n\tshort refnum;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tCStringToPString( fileName, pFileName );\n\n\terr = FSMakeFSSpec( 0, 0, pFileName, &fsspec );\n\tif ( err == noErr )\n\t\terr = FSpOpenDF( &fsspec, fsRdWrPerm, &refnum );\n\tif ( err == noErr )\n\t\tFSClose( refnum );\n\n\tif ( err == opWrErr || err == permErr || err == afpAccessDenied )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong eof, position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tif( GetFPos( stream->refNum, &position ) != noErr || \\\n\t\tGetEOF( stream->refNum, &eof ) != noErr )\n\t\treturn;\n\tlength = eof - position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tSetFPos( stream->refNum, fsFromStart, position );\n\tSetEOF( stream->refNum, position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tremove( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tSetFPos( stream.refNum, fsFromStart, 0 );\n\tGetEOF( stream.refNum, &length );\n\teraseFile( stream, position, length );\n\tSetFPos( stream.refNum, fsFromStart, 0 );\n\tSetEOF( stream.refNum, 0 );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tFSpDelete( stream.fsspec );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNon-STDIO File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( CONFIG_NO_STDIO )\n\n#if defined( __MVS__ ) || defined( __VMCMS__ ) || \\\n\tdefined( __IBM4758__ ) || defined( __TESTIO__ )\n\n/* Some environments place severe restrictions on what can be done with file\n   I/O, either having no filesystem at all or having one with characteristics\n   that don't fit the stdio model.  For these systems we used our own in-\n   memory buffers and make them look like virtual file streams until they're\n   flushed, at which point they're written to backing store (flash RAM/\n   EEPROM/DASD/whatever non-FS storage is being used) in one go.\n\n   For streams with the sensitive bit set we don't expand the buffer size\n   because the original was probably in protected memory, for non-sensitive\n   streams we expand the size if necessary.  This means that we have to\n   choose a suitably large buffer for sensitive streams (private keys), but\n   one that isn't too big.  16K is about right, since typical private key\n   files with cert chains are 2K */\n\n#endif /* __MVS__ || __VMCMS__ || __IBM4758__ || __TESTIO__ */\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n#ifdef __IBM4758__\n\tconst BOOLEAN useBBRAM = ( mode & FILE_FLAG_SENSITIVE ) ? TRUE : FALSE;\n#elif defined( EBCDIC_CHARS )\n  #pragma convlit( suspend )\n\tstatic const char *modes[] = { MODE_READ, MODE_READ,\n\t\t\t\t\t\t\t\t   MODE_WRITE, MODE_READWRITE };\n  #pragma convlit( resume )\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n#else\n\tstatic const char *modes[] = { MODE_READ, MODE_READ,\n\t\t\t\t\t\t\t\t   MODE_WRITE, MODE_READWRITE };\n#endif /* __IBM4758__ */\n#if defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\tconst char *openMode;\n#endif /* __MVS__ || __VMCMS__ || __TESTIO__ */\n\tlong length;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure as a virtual file stream */\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tstream->type = STREAM_TYPE_MEMORY;\n\tINIT_FLAGS( stream->flags, STREAM_MFLAG_VFILE );\n\tif( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ )\n\t\tSET_FLAG( stream->flags, STREAM_FLAG_READONLY );\n\n#if defined( __IBM4758__ )\n\t/* Make sure that the filename matches the 4758's data item naming\n\t   conventions and remember the filename.  The best error code to return\n\t   if there's a problem is a file open error, since this is buried so\n\t   many levels down that a parameter error won't be meaningful to the\n\t   caller */\n\tif( strlen( fileName ) > 8 )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tstrlcpy_s( stream->name, 8, fileName );\n\n\t/* If we're doing a read, fetch the data into memory */\n\tif( mode & FILE_FLAG_READ )\n\t\t{\n\t\t/* Find out how big the data item is and allocate a buffer for\n\t\t   it */\n\t\tstatus = sccGetPPDLen( ( char * ) fileName, &length );\n\t\tif( status != PPDGood )\n\t\t\t{\n\t\t\treturn( ( status == PPD_NOT_FOUND ) ? CRYPT_ERROR_NOTFOUND : \\\n\t\t\t\t\t( status == PPD_NOT_AUTHORIZED ) ? CRYPT_ERROR_PERMISSION : \\\n\t\t\t\t\tCRYPT_ERROR_OPEN );\n\t\t\t}\n\t\tREQUIRES( rangeCheck( length, 1, MAX_BUFFER_SIZE ) );\n\t\tif( ( stream->buffer = clAlloc( \"sFileOpen\", length ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tstream->bufSize = stream->bufEnd = length;\n\t\tstream->isIOStream = TRUE;\n\n\t\t/* Fetch the data into the buffer so it can be read as a memory\n\t\t   stream */\n\t\tstatus = sccGetPPD( ( char * ) fileName, stream->buffer, length );\n\t\treturn( ( status != PPDGood ) ? CRYPT_ERROR_READ : CRYPT_OK );\n\t\t}\n\n\t/* We're doing a write, make sure that there's enough room available.\n\t   This doesn't guarantee that there'll be enough when the data is\n\t   committed, but it makes sense to at least check when the \"file\" is\n\t   opened */\n\tstatus = sccQueryPPDSpace( &length, useBBRAM ? PPD_BBRAM : PPD_FLASH );\n\tif( status != PPDGood || length < STREAM_VFILE_BUFSIZE )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\t/* Allocate the initial I/O buffer for the data */\n\tif( ( stream->buffer = clAlloc( \"sFileOpen\", \n\t\t\t\t\t\t\t\t\tSTREAM_VFILE_BUFSIZE ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tstream->bufSize = STREAM_VFILE_BUFSIZE;\n\tstream->isSensitive = useBBRAM;\n\n\treturn( CRYPT_OK );\n#elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* If we're going to be doing a write either now or later, we can't open\n\t   the file until we have all of the data that we want to write to it\n\t   available since the open arg has to include the file format\n\t   information, so all we can do at this point is remember the name for\n\t   later use */\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\tstrlcpy_s( stream->name, MAX_PATH_LENGTH, fileName );\n  #ifdef EBCDIC_CHARS\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n  #endif /* EBCDIC_CHARS */\n\n\t/* If we're doing a read, fetch the data into memory */\n\tif( mode & FILE_FLAG_READ )\n\t\t{\n\t\tFILE *filePtr;\n  #if defined( __MVS__ ) || defined( __VMCMS__ ) \n\t\tfldata_t fileData;\n\t\tchar fileBuffer[ MAX_PATH_LENGTH + 8 ];\n  #endif /* __MVS__ || __VMCMS__ */\n\t\tint allocSize = STREAM_VFILE_BUFSIZE;\n\n\t\t/* Open the file and determine how large it is */\n#if !defined( __WIN32__ )\n\t\terrno = 0;\n#endif /* Non-Windows environments */\n\t\tfilePtr = fopen( fileName, openMode );\n\t\tif( filePtr == NULL )\n\t\t\t{\n\t\t\t/* The open failed, determine whether it was because the file \n\t\t\t   doesn't exist or because we can't use that access mode.  We\n\t\t\t   need to distinguish between not-found and failed-to-open\n\t\t\t   status values because not-found is an allowable condition\n\t\t\t   but (presumably found but) failed to open isn't */\n  #if defined( __MVS__ ) || defined( __VMCMS__ ) \n\t\t\t/* An errno value of ENOENT results from a DDNAME not found, 67 \n\t\t\t   (no mnemonic name defined by IBM for DYNALLOC return codes) \n\t\t\t   is member not found and 49 is data set not found */\n\t\t\treturn( ( errno == ENOENT || errno == 67 || errno == 49 ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n  #elif defined( __WIN32__ )\n\t\t\treturn( ( GetLastError() == ERROR_FILE_NOT_FOUND ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n  #else\n\t\t\treturn( errno == ENOENT ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n  #endif /* Nonstandard I/O environments */\n\t\t\t}\n  #if defined( __MVS__ ) || defined( __VMCMS__ ) \n\t\tstatus = fldata( filePtr, fileBuffer, &fileData );\n\t\tif( status )\n\t\t\t{\n\t\t\tfclose( filePtr );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\tlength = fileData.__maxreclen;\n  #else\n\t\tfseek( filePtr, 0L, SEEK_END );\n\t\tlength = ftell( filePtr );\n\t\tfseek( filePtr, 0L, SEEK_SET );\n  #endif /* Nonstandard I/O environments */\n\t\tif( length <= 0 )\n\t\t\t{\n\t\t\tfclose( filePtr );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\tif( stream->flags & STREAM_FLAG_READONLY )\n\t\t\t{\n\t\t\t/* If it's a read-only file we only need to allocate a buffer\n\t\t\t   large enough to hold the existing data */\n\t\t\tallocSize = length;\n\t\t\t}\n\n\t\t/* Fetch the data into a buffer large enough to contain the entire\n\t\t   stream */\n\t\tREQUIRES( rangeCheck( allocSize, 1, MAX_BUFFER_SIZE ) );\n\t\tif( ( stream->buffer = clAlloc( \"sFileOpen\", allocSize ) ) == NULL )\n\t\t\t{\n\t\t\tfclose( filePtr );\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tstream->bufSize = allocSize;\n\t\tstream->bufEnd = length;\n\t\tstatus = fread( stream->buffer, length, 1, filePtr );\n\t\tfclose( filePtr );\n\t\tif( status != 1 )\n\t\t\t{\n\t\t\tclFree( \"sFileOpen\", stream->buffer );\n\t\t\treturn( CRYPT_ERROR_READ );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Allocate the initial I/O buffer for the data */\n\tif( ( stream->buffer = clAlloc( \"sFileOpen\", \n\t\t\t\t\t\t\t\t\tSTREAM_VFILE_BUFSIZE ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tstream->bufSize = STREAM_VFILE_BUFSIZE;\n\n\treturn( CRYPT_OK );\n#else\n\t#error Need to add mechanism to connect stream to backing store\n\treturn( CRYPT_ERROR_OPEN );\n#endif /* Nonstandard I/O environments */\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( sIsVirtualFileStream( stream ) );\n\n#if defined( __IBM4758__ ) || defined( __MVS__ ) || \\\n\tdefined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* Close the file and clear the stream structure */\n\tzeroise( stream->buffer, stream->bufSize );\n\tclFree( \"sFileClose\", stream->buffer );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n#else\n\t#error Need to add mechanism to disconnect stream from backing store\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n#endif /* Nonstandard I/O environments */\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( sIsVirtualFileStream( stream ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\t/* These environments move all data into an in-memory buffer when the\n\t   file is opened so there's never any need to read more data from the\n\t   stream */\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( sIsVirtualFileStream( stream ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* These environments keep all data in an in-memory buffer that's \n\t   committed to backing store when the file is closed so there's never \n\t   any need to write data to the stream */\n\tretIntError();\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n#if defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\tFILE *filePtr;\n\tint count;\n#endif /* __MVS__ || __VMCMS__ || __TESTIO__ */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( sIsVirtualFileStream( stream ) );\n\n#if defined( __IBM4758__ )\n\t/* Write the data to flash or BB memory as appropriate */\n\tif( sccSavePPD( stream->name, stream->buffer, stream->bufEnd,\n\t\t\t( stream->isSensitive ? PPD_BBRAM : PPD_FLASH ) | PPD_TRIPLE ) != PPDGood )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n#elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* Under CMS, MVS, TSO, etc the only consistent way to handle writes is\n\t   to write a fixed-length single-record file containing all the data in\n\t   one record, so we can't really do anything until the data is flushed */\n  #if 0\n\t/* No need to go to this level, a RECFM=* binary file will do just as\n\t   well */\n\tchar formatBuffer[ 64 + 8 ];\n\tsprintf_s( formatBuffer, 64, \"wb,recfm=F,lrecl=%d,noseek\", \n\t\t\t   stream->bufPos );\n\tfilePtr = fopen( stream->name, formatBuffer );\n  #endif /* 0 */\n\tfilePtr = fopen( stream->name, MODE_WRITE );\n\tif( filePtr == NULL )\n\t\treturn( CRYPT_ERROR_WRITE );\n\tcount = fwrite( stream->buffer, stream->bufEnd, 1, filePtr );\n\tfclose( filePtr );\n\treturn( ( count != 1 ) ? CRYPT_ERROR_WRITE : CRYPT_OK );\n#else\n\t#error Need to add mechanism to commit data to backing store\n\treturn( CRYPT_ERROR_WRITE );\n#endif /* Nonstandard I/O environments */\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( sIsVirtualFileStream( stream ) );\n\n#if defined( __IBM4758__ ) || defined( __MVS__ ) || \\\n\tdefined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* These environments move all data into an in-memory buffer when the\n\t   file is opened, so there's never any need to move around in the\n\t   stream */\n\tretIntError();\n#else\n\t#error Need to add mechanism to perform virtual seek on backing store\n\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n#endif /* Nonstandard I/O environments */\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n#if defined( __IBM4758__ ) || defined( __MVS__ ) || \\\n\tdefined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* Since there's no filesystem or no real access control (even under MVS \n\t   et al it'll be handled at a much higher level like RACF or a SAF-\n\t   compatable product), there's no concept of a read-only file, at least \n\t   at a level that we can easily determine programmatically */\n\treturn( FALSE );\n#else\n\t#error Need to add mechanism to determine readability of data in backing store\n\treturn( FALSE );\n#endif /* Nonstandard I/O environments */\n\t}\n\n/* File deletion functions: Wipe a file from the current position to EOF,\n   and wipe and delete a file (although it's not terribly rigorous).\n   Vestigia nulla retrorsum */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( sIsVirtualFileStream( stream ) );\n\n#if defined( __IBM4758__ ) || defined( __MVS__ ) || \\\n\tdefined( __VMCMS__ ) || defined( __TESTIO__ )\n\t/* Data updates on these systems are atomic so there's no remaining data\n\t   left to clear */\n\tUNUSED_ARG( stream );\n#else\n  #error Need to add clear-to-EOF function for data in backing store\n#endif /* Nonstandard I/O environments */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n#if defined( __IBM4758__ )\n\tsccDeletePPD( ( char * ) fileName );\n#elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\tFILE *filePtr;\n  #ifdef EBCDIC_CHARS\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n  #endif /* EBCDIC_CHARS */\n\tint length = CRYPT_ERROR;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n  #if defined( __MVS__ ) && defined( DDNAME_IO )\n\t/* If we're using DDNAME I/O under MVS we can't perform standard\n\t   random-access file operations, the best that we can do is just \n\t   delete the dataset entry */\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n\tremove( fileName );\n\treturn;\n  #elif defined( __MVS__ ) || defined( __VMCMS__ ) \n\t/* Determine how large the file is */\n\t#ifdef EBCDIC_CHARS\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n\t#pragma convlit( suspend )\n\t#endif /* EBCDIC_CHARS */\n\tfilePtr = fopen( fileName, MODE_READWRITE );\n\tif( filePtr != NULL )\n\t\t{\n\t\tfldata_t fileData;\n\t\tchar fileBuffer[ MAX_PATH_LENGTH + 8 ];\n\n\t\tif( fldata( filePtr, fileBuffer, &fileData ) == 0 )\n\t\t\tlength = fileData.__maxreclen;\n\t\t}\n\t#ifdef EBCDIC_CHARS\n\t#pragma convlit( resume )\n\t#endif /* EBCDIC_CHARS */\n  #else\n\t/* Determine how large the file is */\n\tfilePtr = fopen( fileName, MODE_READWRITE );\n\tif( filePtr != NULL )\n\t\t{\n\t\tfseek( filePtr, 0, SEEK_END );\n\t\tlength = ( int ) ftell( filePtr );\n\t\tfseek( filePtr, 0, SEEK_SET );\n\t\t}\n  #endif /* OS environment-specific file handling */\n\n\t/* If we got a length, overwrite the data.  Since the file contains a\n\t   single record we can't perform the write-until-done overwrite used\n\t   on other OS'es, however since we're only going to be deleting short\n\t   private key files using the default stream buffer is OK for this */\n\tif( length > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE buffer[ STREAM_VFILE_BUFSIZE + 8 ];\n\n\t\tlength = max( length, STREAM_VFILE_BUFSIZE );\n\t\tsetMessageData( &msgData, buffer, length );\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tfwrite( buffer, 1, length, filePtr );\n\t\t}\n\tif( filePtr != NULL )\n\t\t{\n\t\tfflush( filePtr );\n\t\tfclose( filePtr );\n\t\t}\n\tremove( fileName );\n#else\n  #error Need to add erase function for data in backing store\n#endif /* Nonstandard I/O environments */\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#if defined( __IBM4758__ )\n\tif( option == BUILDPATH_RNDSEEDFILE )\n\t\t{\n\t\t/* Unlikely to really be necessary since we have a hardware RNG */\n\t\tstrlcpy_s( path, pathMaxLen, \"RANDSEED\" );\n\t\t}\n\telse\n\t\tstrlcpy_s( path, pathMaxLen, fileName );\n\treturn( CRYPT_OK );\n#elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n  #if defined( DDNAME_IO )\n\t/* MVS dataset name userid.CRYPTLIB.filename.  We can't use a PDS since\n\t   multiple members have to be opened in write mode simultaneously */\n\tif( option == BUILDPATH_RNDSEEDFILE )\n\t\tstrlcpy_s( path, pathMaxLen, \"//RANDSEED\" );\n\telse\n\t\t{\n\t\tstrlcpy_s( path, pathMaxLen, \"//CRYPTLIB.\" );\n\t\tstrlcat_s( path, pathMaxLen, fileName );\n\t\t}\n\n\treturn( CRYPT_OK );\n  #else\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n  #endif /* DDNAME_IO */\n#else\n  #error Need to add function to build path to config data in backing store\n\n\treturn( CRYPT_ERROR_OPEN );\n#endif /* OS-specific file path creation */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tNucleus File Stream Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Nucleus__ )\n\n/* The Nucleus FILE interface is a DOS-like API used to access a standard \n   FAT filesystem */\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const UINT16 modes[] = {\n\t\tPO_RDONLY, PO_RDONLY,\n\t\tPO_WRONLY | PO_CREAT,\n\t\tPO_RDWR\n\t\t};\n\tUINT16 openMode;\n\tINT fd;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* Try and open the file */\n\tfd = NU_Open( ( CHAR * ) fileName, openMode, \\\n\t\t\t\t  ( UINT16  ) \\\n\t\t\t\t\t( ( openMode & PO_CREAT ) ? \\\n\t\t\t\t\t  ( PS_IREAD | PS_IWRITE ) : PS_IREAD ) );\n\tif( fd < NU_SUCCESS )\n\t\t{\n\t\treturn( ( fd == NUF_NOFILE ) ? CRYPT_ERROR_NOTFOUND : \\\n\t\t\t\t( fd == NUF_SHARE || \\\n\t\t\t\t  fd == NUF_ACCES ) ? CRYPT_ERROR_PERMISSION : \\\n\t\t\t\tCRYPT_ERROR_OPEN );\n\t\t}\n\tstream->fd = fd;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tNU_Close( stream->fd );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tINT byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = NU_Read( stream->fd, buffer, length ) ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tINT byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( ( byteCount = \\\n\t\t\tNU_Write( stream->fd, ( CHAR * ) buffer, length ) ) < 0 || \\\n\t\tbyteCount != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\tif( NU_Flush( stream->fd ) != NU_SUCCESS )\n\t\treturn( CRYPT_ERROR_WRITE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( NU_Seek( stream->fd, position, PSEEK_SET ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tUINT8 attributes;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( NU_Get_Attributes( &attributes, ( CHAR * ) fileName ) != NU_SUCCESS )\n\t\treturn( TRUE );\n\treturn( ( attributes & ( ARDONLY | AHIDDEN | ASYSTEM ) ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tINT32 length, position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tposition = NU_Seek( stream->fd, 0, PSEEK_CUR );\n\tlength = NU_Seek( stream->fd, 0, PSEEK_END ) - position;\n\tNU_Seek( stream->fd, position, PSEEK_SET );\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tNU_Truncate( stream->fd, position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tDSTAT statInfo;\n\tUINT32 length;\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tNU_Delete( ( CHAR * ) fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tif( NU_Get_First( &statInfo, ( CHAR * ) fileName ) != NU_SUCCESS )\n\t\t{\n\t\tNU_Delete( ( CHAR * ) fileName );\n\t\treturn;\n\t\t}\n\tlength = statInfo.fsize;\n\tNU_Done( &statInfo );\n\teraseFile( &stream, 0, length );\n\tNU_Truncate( stream.fd, 0 );\n\n\t/* Reset the file's attributes */\n\tNU_Set_Attributes( ( CHAR * ) fileName, ANORMAL );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tNU_Delete( ( CHAR * ) fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now.  Detecting whether a directory exists \n\t   is a bit tricky, we use NU_Get_First() as a stat()-substitute and\n\t   try and create the directory on error.  In theory we could check\n\t   speifically for NUF_NOFILE but there could be some other problem\n\t   that causes the NU_Get_First() to fail, so we use NU_Make_Dir() as \n\t   the overall error-catcher */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tDSTAT statInfo;\n\n\t\tif( NU_Get_First( &statInfo, ( CHAR * ) fileName ) != NU_SUCCESS )\n\t\t\t{\n\t\t\t/* The directory doesn't exist, try and create it */\n\t\t\tif( NU_Make_Dir( path ) != NU_SUCCESS )\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\telse\n\t\t\tNU_Done( &statInfo );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPalm OS File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __PALMOS__ )\n\n#include <FeatureMgr.h>\n\n/* In theory it's possible for a system not to have the VFS Manager\n   available, although this seems highly unlikely we check for it just\n   in case using the Feature Manager */\n\nstatic BOOLEAN checkVFSMgr( void )\n\t{\n\tuint32_t vfsMgrVersion;\n\n\treturn( ( FtrGet( sysFileCVFSMgr, vfsFtrIDVersion,\n\t\t\t\t\t  &vfsMgrVersion ) == errNone ) ? TRUE : FALSE );\n\t}\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const int modes[] = {\n\t\tvfsModeRead, vfsModeRead,\n\t\tvfsModeCreate | vfsModeExclusive | vfsModeWrite,\n\t\tvfsModeReadWrite\n\t\t};\n\tuint32_t volIterator = vfsIteratorStart;\n\tuint16_t volRefNum, openMode;\n\tstatus_t err;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* Make sure that VFS services are available and get the default volume\n\t   to open the file on */\n\tif( !checkVFSMgr() )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tif( VFSVolumeEnumerate( &volRefNum, &volIterator ) != errNone )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file */\n\terr = VFSFileOpen( volRefNum, fileName, openMode, &stream->fileRef );\n\tif( err == vfsErrFilePermissionDenied || err == vfsErrIsADirectory || \\\n\t\terr == vfsErrVolumeFull )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\tif( err == vfsErrFileNotFound )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( err != errNone )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tVFSFileClose( stream->fileRef );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tuint32_t byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( VFSFileRead( stream->fileRef, length, buffer,\n\t\t\t\t\t &byteCount ) != errNone )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tuint32_t bytesWritten;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( VFSFileWrite( stream->fileRef, length, buffer,\n\t\t\t\t\t  &bytesWritten ) != errNone || \\\n\t\tbytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* There doesn't seem to be any way to force data to be written do\n\t   backing store, probably because the concept of backing store is\n\t   somewhat hazy in a system that's never really powered down.\n\t   Probably for removable media data is committed fairly quickly to\n\t   handle media removal while for fixed media it's committed as\n\t   required since it can be retained in memory more or less\n\t   indefinitely */\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( VFSFileSeek( stream->fileRef, vfsOriginBeginning,\n\t\t\t\t\t position ) != errNone )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tFileRef fileRef;\n\tuint32_t volIterator = vfsIteratorStart;\n\tuint16_t volRefNum;\n\tstatus_t err;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( VFSVolumeEnumerate( &volRefNum, &volIterator ) != errNone )\n\t\treturn( TRUE );\n\terr = VFSFileOpen( volRefNum, fileName, vfsModeRead, &fileRef );\n\tif( err == errNone )\n\t\tVFSFileClose( fileRef );\n\n\treturn( ( err == vfsErrFilePermissionDenied ) ? TRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tuint32_t length, position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tif( VFSFileSize( stream->fileRef, &length ) != errNone || \\\n\t\tVFSFileTell( stream->fileRef, &position ) != errNone )\n\t\treturn;\n\tlength -= position;\n\tif( length <= 0 || length > MAX_BUFFER_SIZE )\n\t\t{\n\t\t/* There's nothing to do, exit */\n\t\treturn;\t\n\t\t}\n\teraseFile( stream, position, length );\n\tVFSFileResize( stream->fileRef, position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tuint32_t volIterator = vfsIteratorStart, length;\n\tuint16_t volRefNum;\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tif( VFSVolumeEnumerate( &volRefNum, &volIterator ) != errNone )\n\t\treturn;\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tVFSFileDelete( volRefNum, fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tVFSFileSize( stream.fileRef, &length );\n\teraseFile( &stream, 0, length );\n\tVFSFileResize( stream.fileRef, 0 );\n\n\t/* Reset the file's attributes */\n\tVFSFileSetAttributes( stream.fileRef, 0 );\n\tVFSFileSetDate( stream.fileRef, vfsFileDateAccessed, 0 );\n\tVFSFileSetDate( stream.fileRef, vfsFileDateCreated, 0 );\n\tVFSFileSetDate( stream.fileRef, vfsFileDateModified, 0 );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tVFSFileDelete( volRefNum, fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Make sure that VFS services are available */\n\tif( !checkVFSMgr() )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tFileRef fileRef;\n\t\tuint32_t volIterator = vfsIteratorStart;\n \t\tuint16_t volRefNum;\n\n\t\tif( VFSVolumeEnumerate( &volRefNum, &volIterator ) != errNone )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tif( VFSFileOpen( volRefNum, path, vfsModeRead, &fileRef ) == errNone )\n\t\t\tVFSFileClose( fileRef );\n\t\telse\n\t\t\t{\n\t\t\t/* The directory doesn't exist, try and create it */\n\t\t\tif( VFSDirCreate( volRefNum, path ) != errNone )\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tQuadros File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Quadros__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const char *modes[] = { MODE_READ, MODE_READ,\n\t\t\t\t\t\t\t\t   MODE_WRITE, MODE_READWRITE };\n\tconst char *openMode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file.  This is an annoying function because, while \n\t   every other function returns a detailed status code, fsm_open() can\n\t   only return NULL on failure, so the only error status we can return\n\t   is CRYPT_ERROR_OPEN */\n\tstream->filePtr = fsm_open( fileName, openMode );\n\tif( stream->filePtr == NULL )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tfsm_close( stream->filePtr );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = fsm_read( buffer, length, 1, stream->filePtr ) ) <= 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tint bytesWritten;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( ( bytesWritten = fsm_write( buffer, length, 1, stream->filePtr ) ) <= 0 || \\\n\t\tbytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( ( fsm_flush( stream->filePtr ) == F_NO_ERROR ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( fsm_seek( stream->filePtr, position, FS_SEEK_SET ) != F_NO_ERROR )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tunsigned long fileAttr;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( fsm_getpermission( fileName, &fileAttr ) != F_NO_ERROR )\n\t\treturn( TRUE );\n\n\treturn( ( fileAttr & FSSEC_ATTR_READONLY ) ? TRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong length, position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file.  This gets \n\t   quite problematic because fsm_filelength() works by filename rather\n\t   than file handle and it's not clear whether access by filename\n\t   reflects the length until the data is committed to storage.  There's\n\t   also an fsm_stat() but that also works by filename, so we have to\n\t   synthesise the functionality from seek()s and tell()s.  \n\t   \n\t   In addition fsm_truncate() also works by filename, there's an \n\t   fsm_ftruncate() documented but it doesn't seem to actually exist. \n\t   Luckily there's an f_seteof() that truncates at the current position,\n\t   which is what we want to do */\n\tposition = fsm_tell( stream->filePtr );\n\tif( position < 0 )\n\t\treturn;\n\tfsm_seek( stream->filePtr, 0, F_SEEK_END );\n\tlength = fsm_tell( stream->filePtr ) - position;\n\tfsm_seek( stream->filePtr, position, F_SEEK_SET );\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tfsm_seteof( stream->filePtr );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( ( length = fsm_filelength( fileName ) ) < 0 )\n\t\treturn;\n\n\t/* Try and open the file and erase it.  If the open fails, the best that \n\t   we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tfsm_delete( fileName );\n\t\treturn;\n\t\t}\n\teraseFile( &stream, 0, length );\n\tsFileClose( &stream );\n\n\t/* Reset the file's attributes and delete it */\n\tfsm_setpermission( fileName, FSSEC_ATTR_ARC );\n\tfsm_settimedate( fileName, 0, 0 );\n\tfsm_truncate( fileName, 0 );\n\tfsm_delete( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tint fsmStatus;\n\n\t\t/* Try and create the directory, continuing if it already exists.  \n\t\t   In theory we could do an f_findfirst() on the directory name,\n\t\t   but since f_mkdir() gives us what we need there's no need to go\n\t\t   through this level of calisthenics */\n\t\tfsmStatus = fsm_mkdir( path );\n\t\tif( fsmStatus != F_NO_ERROR && fsmStatus != F_ERR_DUPLICATED )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\tTelit\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Telit__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const int modes[] = { M2M_FS_OPEN_READ, M2M_FS_OPEN_READ,\n\t\t\t\t\t\t\t\t M2M_FS_OPEN_MODIFY, \n\t\t\t\t\t\t\t\t M2M_FS_OPEN_MODIFY /* R/W */ };\n\tINT32 openMode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file.  This is an annoying function because, while \n\t   every other function returns a detailed status code, m2m_fs_open() \n\t   can only return NULL on failure so we have to fall back to calling\n\t   m2m_fs_last_error() to see what actually happened */\n\tstream->filePtr = m2m_fs_open( ( CHAR * ) fileName, openMode );\n\tif( stream->filePtr == NULL )\n\t\t{\n\t\tswitch( m2m_fs_last_error() )\n\t\t\t{\n\t\t\tcase M2M_F_ERR_NOTFOUND:\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t\tcase M2M_F_ERR_ACCESSDENIED:\n\t\t\tcase M2M_F_ERR_WRITEPROTECT:\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tm2m_fs_close( stream->filePtr );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = m2m_fs_read( stream->filePtr, buffer, length ) ) <= 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tint bytesWritten;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( ( bytesWritten = m2m_fs_write( stream->filePtr, ( CHAR * ) buffer, \n\t\t\t\t\t\t\t\t\t   length ) ) <= 0 || \\\n\t\tbytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Telit has no filesystem flush command */\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tUINT32 result;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\t/* m2m_fs_seek() returns zero on error, so we have to check whether we \n\t   wanted to seek to position zero to avoid it being treated as an\n\t   error */\n\tresult = m2m_fs_seek( stream->filePtr, position );\n\tif( position != 0 && result == 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Telit doesn't seem to have any concept of file attributes or \n\t   permissions, so we have to assume that all files are writeable */\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong length, position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file.  m2m_fs_tell()\n\t   is another annoying function for which an error result of 0 is also a\n\t   valid return value, so we have to check with m2m_fs_last_error() to \n\t   see what it really is */\n\tif( ( length = m2m_fs_get_size_with_handle( stream->filePtr ) ) == M2M_FS_ERROR )\n\t\treturn;\n\tif( ( position = m2m_fs_tell( stream->filePtr ) ) == 0 && \\\n\t\tm2m_fs_last_error() != M2M_F_NO_ERROR )\n\t\treturn;\n\tlength -= position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\n\t/* Telit currently has no way to truncate a file based on its handle, \n\t   the way it's handled is the somewhat bizarre:\n\n\t\tM2M_T_FS_HANDLE file_handle = m2m_fs_truncate( filename, 0 );\n\t\tm2m_fs_close( file_handle );\n\n\t   (which gives a pretty good idea how it's implemented).  The equally \n\t   puzzling m2m_fs_create() does a better job by creating a zero-byte \n\t   file, but it still requires a filename so we can't use that either */\n#if 0\n\tm2m_fs_create( fileName );\n#endif /* 0 */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( ( length = m2m_fs_get_size( ( CHAR * ) fileName ) ) == M2M_FS_ERROR )\n\t\treturn;\n\n\t/* Try and open the file and erase it.  If the open fails, the best that \n\t   we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tm2m_fs_delete( ( CHAR * ) fileName );\n\t\treturn;\n\t\t}\n\teraseFile( &stream, 0, length );\n\tsFileClose( &stream );\n\n\t/* Truncate the file and delete it.  See the comment in fileClearToEOF()\n\t   for the use of m2m_fs_delete() */\n\tm2m_fs_create( ( CHAR * ) fileName );\n\tm2m_fs_delete( ( CHAR * ) fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tint m2mApiResult;\n\n\t\t/* Try and create the directory, continuing if it already exists */\n\t\tm2mApiResult = m2m_fs_mk_dir( path );\n\t\tif( m2mApiResult != M2M_API_RESULT_SUCCESS && \\\n\t\t\t m2m_fs_last_error() != M2M_F_ERR_DUPLICATED )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tThreadX (via FileX)\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __FileX__ )\n\n/* Using FileX is a bit complicated because it has a form of level -1 \n   filesystem abstraction in which it's necessary to open the underlying\n   device before you can work with the files stored on it.  Since this\n   process is entirely device-specific there's no way to do this from\n   within cryptlib, so we rely on a helper function to which the caller\n   passes an FX_MEDIA structure for the device to be used.  A reference\n   to this is stored locally and used for all operations that require a\n   device to be specified */\n\nstatic FX_MEDIA *media = NULL;\n\nCHECK_RETVAL STDC_NONNULLARG( ( 1 ) ) \\\nint setMedia( FX_MEDIA *mediaPtr )\n\t{\n\tassert( isWritePtr( mediaPtr, sizeof( FX_MEDIA ) ) );\n\n\t/* Remember the user-supplied media information */\n\tmedia = mediaPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const int modes[] = { FX_OPEN_FOR_READ, FX_OPEN_FOR_READ,\n\t\t\t\t\t\t\t\t FX_OPEN_FOR_WRITE, \n\t\t\t\t\t\t\t\t FX_OPEN_FOR_READ | FX_OPEN_FOR_WRITE };\n\tUINT openStatus;\n\tint openMode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* FileX has a somewhat strange way of creating files in which \n\t   fx_file_create() is used to create a directory entry for a file\n\t   and then fx_file_open() actually opens it.  This nasty non-atomic\n\t   open requires special-case handling for the situation where the\n\t   directory-entry create succeeds but the open fails, so we have to\n\t   special-case the handling for this */\n\tif( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_WRITE )\n\t\t{\n\t\tif( fx_file_create( media, fileName ) != FX_SUCCESS )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tif( fx_file_open( media, &stream->filePtr, fileName, \n\t\t\t\t\t\t  FX_OPEN_FOR_WRITE ) != FX_SUCCESS )\n\t\t\t{\n\t\t\tfx_file_delete( media, fileName );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n\n\t/* Try and open the file */\n\topenStatus = fx_file_open( media, &stream->filePtr, fileName, openMode );\n\tif( openStatus != FX_SUCCESS )\n\t\t{\n\t\treturn( ( openStatus == FX_NOT_FOUND ) ? CRYPT_ERROR_NOTFOUND : \\\n\t\t\t\t( openStatus == FX_ACCESS_ERROR || \\\n\t\t\t\t  openStatus == FX_WRITE_PROTECT ) ? CRYPT_ERROR_PERMISSION : \\\n\t\t\t\tCRYPT_ERROR_OPEN );\n\t\t}\n\tstream->position = 0;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tfx_file_close( stream->filePtr );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tULONG byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( fx_file_read( stream->filePtr, buffer, length, \\\n\t\t\t\t\t\t&byteCount ) != FX_SUCCESS ) || \\\n\t\tbyteCount != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\tstream->position += byteCount;\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( fx_file_write( stream->filePtr, buffer, length ) != FX_SUCCESS )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\tstream->position += length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\tif( fx_media_flush( media ) != FX_SUCCESS )\n\t\treturn( CRYPT_ERROR_WRITE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( fx_file_seek( stream->filePtr, position ) != FX_SUCCESS )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\tstream->position = position;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tUINT attributes;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( fx_file_attribute_read( media, fileName, &attributes ) != FX_SUCCESS )\n\t\treturn( TRUE );\n\treturn( ( attributes & ( FX_READ_ONLY | FX_HIDDEN | FX_SYSTEM ) ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* FileX provides no way to determine either the current position in a \n\t   file or its length, so there's no way to use eraseFile() to clear to\n\t   EOF (in theory we could remember the file's pathname on open, parse\n\t   the path to get the encapsulating directory, perform a media flush to\n\t   update the data on disk in the hope that this creates an accurate \n\t   record of the file size rather than just a nearest-cluster-\n\t   approximation until the file is closed, and then use the find-first-\n\t   file results for the file's size, but this seems excessively\n\t   complicated) */\n\tfx_filetruncate_release( stream->filePtr, stream->position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tint length, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tfx_file_delete( media, fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it.  Again, because of \n\t   FileX's idiotic inability to tell us anything about the file (see\n\t   the comment in fileClearToEOF()) we have to perform a byte-at-a-time \n\t   read until the read fails in order to determine how much data is \n\t   present */\n\tLOOP_MAX( length = 0, length < 50000, length++ )\n\t\t{\n\t\tBYTE buffer[ 1 + 8 ];\n\t\tint bytesRead;\n\n\t\tif( ( fx_file_read( stream->filePtr, buffer, 1, \\\n\t\t\t\t\t\t\t&bytesRead ) != FX_SUCCESS ) || bytesRead != 1 )\n\t\t\tbreak;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tfx_file_seek( stream.filePtr, 0 );\n\teraseFile( &stream, 0, length );\n\n\t/* FileX has two forms of file-truncate, one that releases the clusters\n\t   beyond the truncation point and one that doesn't.  Why anyone would\n\t   want to truncate a file and then throw away the clusters that this \n\t   frees is a mystery */\n\tfx_filetruncate_release( stream.filePtr, 0 );\n\n\t/* Reset the file's attributes */\n\tfx_file_attribute_set( stream.filePtr, FJ_DA_NORMAL );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tfx_file_delete( media, fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH && \\\n\t\tfx_directory_name_test( path ) != FX_SUCCESS )\n\t\t{\n\t\t/* The directory doesn't exist, try and create it */\n\t\tif( fx_directory_create( media, path ) != FX_SUCCESS )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tUnix/Unix-like Systems File Stream Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Android__ ) || defined( __BEOS__ ) || \\\n\t  defined( __ECOS__ ) || defined( __iOS__ ) || defined( __MGOS__ ) || \\\n\t  defined( __MVS__ ) || defined( __RTEMS__ ) || \\\n\t  defined( __SYMBIAN32__ ) || defined( __TANDEM_NSK__ ) || \\\n\t  defined( __TANDEM_OSS__ ) || defined( __UNIX__ )\n\n/* Tandem doesn't have ftruncate() even though there's a manpage for it\n   (which claims that it's prototyped in sys/types.h (!!)).  unistd.h has\n   it protected by ( _XOPEN_SOURCE_EXTENDED == 1 && _TNS_R_TARGET ), which\n   implies that we'd better emulate it if we want to make use of it.  For\n   now we do nothing, this is just a placeholder if the Guardian native\n   file layer isn't available */\n\n#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n\nint ftruncate( int fd, off_t length )\n\t{\n\treturn( 0 );\n\t}\n#endif /* Tandem */\n\n/* Mongoose OS only has the most basic filesystem functions, so we need\n   to synthesise the rest */\n\n#if defined( __MGOS__ )\n\n#define R_OK\t1\n#define W_OK\t2\n\nint access( const char *filename, const int flags )\n\t{\n\tstruct stat statInfo;\n\n\tif( stat( filename, &statInfo ) )\n\t\treturn( -1 );\n\tif( statInfo.st_mode & S_IFDIR )\n\t\treturn( 0 );\n\tif( flags & W_OK )\n\t\treturn( ( statInfo.st_mode & S_IWRITE ) ? 0 : -1 );\n\treturn 0;\n\t}\n\nint ftruncate( const int fd, const int offset )\n\t{\n\t/* We can't really do much here since there's no way to do this in \n\t   Mongoose VFS, however since the files are typically only written once\n\t   at config/build time, and even if they're rewritten in a larger size\n\t   the ASN.1 is self-encapsulating so all we'll get is a file whose size\n\t   on backing storage doesn't match the size of the contents */\n\treturn( 0 );\n\t}\n\n/* Some functions don't make any sense on Mongoose OS, e.g. lstat() when \n   there are no symlinks or flush() when there's no cacheing, so we \n   map them to equivalents or no-op them out */\n\n#define lstat\t\t\tstat\n#define fchmod( a, b )\t0\n#define fchown( a, b, c ) 0\n#define fsync( x )\t\t0\n#define getuid()\t\t0\n#define getgid()\t\t0\n#define geteuid()\t\t0\n#define getegid()\t\t0\n\n#endif /* __MGOS__ */\n\n/* Safe file-open function */\n\n#ifndef O_NOFOLLOW\t\t\t/* Avoid following symlinks on open */\n  #define O_NOFOLLOW\t0\n#endif /* O_NOFOLLOW */\n#ifndef O_CLOEXEC\t\t\t/* Don't let forked children inherit handle */\n  #define O_CLOEXEC\t\t0\n#endif /* O_CLOEXEC */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int openFile( INOUT STREAM *stream, IN_STRING const char *fileName,\n\t\t\t\t\t const int flags, const int openMode )\n\t{\n\tint fd DUMMY_INIT, count, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\t\t\t  /* openMode is a unistd.h define so can't be checked against\n\t\t\t     a fixed range */\n\n\t/* A malicious user could have exec()'d us after closing standard I/O\n\t   handles (which we inherit across the exec()), which means that any\n\t   new files that we open will be allocated the same handles as the\n\t   former standard I/O ones.  This could cause private data to be\n\t   written to stdout or error messages emitted by the calling app to go\n\t   into the opened file.  To avoid this, we retry the open if we get the\n\t   same handle as a standard I/O one.\n\t   \n\t   We use the O_NOFOLLOW flag to avoid following symlinks if the OS \n\t   supports it.  Note that this flag is dangerous to use when reading \n\t   things like /dev/random because they're symlinks on some OSes, but \n\t   these types of files aren't accessed through this function */\n\tLOOP_SMALL( count = 0, count < 4, count++ )\n\t\t{\n\t\tfd = open( fileName, flags, openMode | O_NOFOLLOW );\n\t\tif( fd < 0 )\n\t\t\t{\n\t\t\t/* If we're creating the file, the only error condition is a\n\t\t\t   straight open error */\n\t\t\tif( flags & O_CREAT )\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\n\t\t\t/* Determine whether the open failed because the file doesn't\n\t\t\t   exist or because we can't use that access mode */\n\t\t\treturn( ( access( fileName, 0 ) < 0 ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n\t\t\t}\n\n\t\t/* If we got a handle that isn't in the stdio reserved range, we're \n\t\t   done */\n\t\tif( fd > 2 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( count >= 4 )\n\t\t{\n\t\t/* We still couldn't get a kosher file handle after trying to move \n\t\t   past the standard I/O range, something's wrong */\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\tstream->fd = fd;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int safeFileCreate( INOUT STREAM *stream, \n\t\t\t\t\t\t   IN_STRING const char *fileName,\n\t\t\t\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tconst int extraOpenFlags = ( mode & FILE_FLAG_EXCLUSIVE_ACCESS ) ? \\\n\t\t\t\t\t\t\t   O_CLOEXEC : 0;\n\tstruct stat lstatInfo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tREQUIRES( mode != 0 );\n\n\t/* lstat() the file.  If it doesn't exist, create it with O_EXCL.  If it \n\t   does exist, open it for read/write and perform the fstat() check */\n\terrno = 0;\n\tif( lstat( fileName, &lstatInfo ) < 0 )\n\t\t{\n\t\t/* If the lstat() failed for reasons other than the file not \n\t\t   existing, return a file open error */\n\t\tif( errno != ENOENT )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\n\t\t/* The file doesn't exist, create it with O_EXCL to make sure that \n\t\t   an attacker can't slip in a file between the lstat() and open().  \n\t\t   Note that this still doesn't work for some non-local filesystems, \n\t\t   for example it's not supported at all in NFSv2 and even for newer \n\t\t   versions support can be hit-and-miss - under Linux for example it \n\t\t   requires kernel versions 2.6.5 or newer to work */\n\t\tstatus = openFile( stream, fileName, \n\t\t\t\t\t\t   O_CREAT | O_EXCL | O_RDWR | extraOpenFlags,\n\t\t\t\t\t\t   0600 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tstruct stat fstatInfo;\n\t\tconst int uid = getuid(), gid = getgid();\n\n\t\t/* If it's not a normal file or there are links to it, don't even \n\t\t   try and do anything with it */\n\t\tif( !S_ISREG( lstatInfo.st_mode ) || lstatInfo.st_nlink != 1 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\n\t\t/* Open an existing file */\n\t\tstatus = openFile( stream, fileName, O_RDWR | extraOpenFlags, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* fstat() the opened file and check that the file mode bits, inode, \n\t\t   device, and link info match */\n\t\tif( fstat( stream->fd, &fstatInfo ) < 0 || \\\n\t\t\tlstatInfo.st_mode != fstatInfo.st_mode || \\\n\t\t\tlstatInfo.st_dev != fstatInfo.st_dev || \\\n\t\t\tlstatInfo.st_ino != fstatInfo.st_ino || \\\n\t\t\tlstatInfo.st_nlink != fstatInfo.st_nlink )\n\t\t\t{\n\t\t\tclose( stream->fd );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\n\t\t/* If the above check was passed, we know that the lstat() and \n\t\t   fstat() were done to the same file.  Now check that it's a normal \n\t\t   file (this isn't strictly necessary because the fstat() vs. \n\t\t   lstat() st_mode check would also find this) and there's only one \n\t\t   link.  This also catches tricks like an attacker closing stdin/\n\t\t   stdout so that a newly-opened file ends up with those file \n\t\t   handles, with the result that the app using cryptlib ends up \n\t\t   corrupting cryptlib's files when it sends data to stdout.  In \n\t\t   order to counter this we could simply repeatedly open /dev/null \n\t\t   until we get a handle > 2, but the fstat() check will catch this \n\t\t   in a manner that's also safe with systems that don't have a \n\t\t   stdout (so the handle > 2 check wouldn't make much sense) */\n\t\tif( !S_ISREG( fstatInfo.st_mode ) || fstatInfo.st_nlink != 1 )\n\t\t\t{\n\t\t\tclose( stream->fd );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\n\t\t/* A final check that we could perform if we were really paranoid is \n\t\t   to make sure that fstatInfo.st_uid and fstatInfo.st_gid match our \n\t\t   uid and gid, however this is going to result in false positives \n\t\t   if e.g. root tries to open (overwrite) a file belonging to a \n\t\t   normal user.  It's also not really clear why someone would try \n\t\t   and overwrite a file for a less-privileged user as a more-\n\t\t   privileged user, it could be something like a setuid root process\n\t\t   overwriting a standard user's file.  Because of this it's not \n\t\t   possible to model the conditions under which this would occur in \n\t\t   order to determine if a threat exists, the best approximation \n\t\t   that we can make is:\n\n\t\t\t\tFile\t\t\tAccess\t\t\tAction\n\t\t\t\t----\t\t\t------\t\t\t------\n\t\t\t\tuid = self\t\tuid = self\t\tAccess OK.\n\t\t\t\tuid = other\t\tuid = self\t\tAccess denied.\n\t\t\t\tuid = self\t\tuid = root\t\tAccess OK.\n\t\t\t\tuid = other\t\tuid = root\t\t???\n\n\t\t   The tricky one is the ??? case, should we fchown() the file to \n\t\t   the current user (real uid) in this case?  Or root (effective \n\t\t   uid)?\n\n\t\t   In the absence of any clear indication of what's the right\n\t\t   behaviour, if the file isn't owned by the current real or\n\t\t   effective uid/gid then we chown it file to the caller's real \n\t\t   uid and gid */\n\t\tif( !( fstatInfo.st_uid == uid && fstatInfo.st_gid == gid ) && \\\n\t\t\t!( fstatInfo.st_uid == geteuid() && fstatInfo.st_gid == getegid() ) ) \n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"We're not the owner of the keyset, attempting \"\n\t\t\t\t\t\t \"to chown() it\" ));\n\t\t\terrno = 0;\n\t\t\tif( fchown( stream->fd, uid, gid ) < 0 )\n\t\t\t\t{\n\t\t\t\tclose( stream->fd );\n\t\t\t\treturn( ( errno == EPERM ) ? \\\n\t\t\t\t\t\tCRYPT_ERROR_PERMISSION : CRYPT_ERROR_OPEN );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Turn the file into an empty file */\n\t\tif( ftruncate( stream->fd, 0 ) < 0 )\n\t\t\t{\n\t\t\tclose( stream->fd );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n\n\t/* Set the file access permissions so that only the owner can access \n\t   it.  We skip this for BeOS because it doesn't have fchmod() and the \n\t   permissions don't do much anyway */\n#ifndef __BEOS__\n\tif( mode & FILE_FLAG_PRIVATE )\n\t\t{\n\t\tif( fchmod( stream->fd, 0600 ) < 0 )\n\t\t\t{\n\t\t\tclose( stream->fd );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n#endif /* __BEOS__ */\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( INOUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n#ifdef EBCDIC_CHARS\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n#endif /* EBCDIC_CHARS */\n#if !defined( USE_EMBEDDED_OS ) && defined( USE_FCNTL_LOCKING )\n\tstruct flock flockInfo;\n#endif /* !USE_EMBEDDED_OS && USE_FCNTL_LOCKING */\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n#ifdef EBCDIC_CHARS\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n#endif /* EBCDIC_CHARS */\n\n\t/* Defending against writing through links is somewhat difficult since\n\t   there's no atomic way to do this.  What we do is lstat() the file,\n\t   open it as appropriate, and if it's an existing file ftstat() it and\n\t   compare various important fields to make sure that the file wasn't\n\t   changed between the lstat() and the open().  If everything is OK, we\n\t   then use the lstat() information to make sure that it isn't a symlink\n\t   (or at least that it's a normal file) and that the link count is 1.\n\t   These checks also catch other weird things like STREAMS stuff\n\t   fattach()'d over files.  If these checks pass and the file already\n\t   exists we truncate it to mimic the effect of an open with create.\n\n\t   There is a second type of race-condition attack in which the race is\n\t   run at a very low speed instead of high speed (sometimes called a \n\t   cryogenic sleep attack) in which an attacker SIGSTOP's us after the \n\t   lstat() (which generally isn't possible for processes not owned by\n\t   the user but is possible for setuid ones), deletes the file, waits \n\t   for the inode number to roll around, creates a link with the \n\t   (reused) inode, and then SIGCONT's us again.  Checking for a link \n\t   count > 1 catches the link problem.\n\n\t   Another workaround would be to check the inode generation number\n\t   st_gen, but virtually nothing supports this */\n\tif( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_WRITE )\n\t\t{\n\t\tstatus = safeFileCreate( stream, fileName, mode );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tstatic const int modes[] = { O_RDONLY, O_RDONLY, O_WRONLY, O_RDWR };\n\t\tconst int extraOpenFlags = ( mode & FILE_FLAG_EXCLUSIVE_ACCESS ) ? \\\n\t\t\t\t\t\t\t\t   O_CLOEXEC : 0;\n\n\t\t/* Open an existing file for read access */\n\t\tstatus = openFile( stream, fileName, \n\t\t\t\t\t\t   modes[ mode & FILE_FLAG_RW_MASK ] | extraOpenFlags, \n\t\t\t\t\t\t   0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Lock the file if possible to make sure that no-one else tries to do\n\t   things to it.  Locking under Unix basically doesn't work, so most of\n\t   the following is just feel-good stuff, we try and do the right thing\n\t   but there's really nothing we can do to guarantee proper performance.\n\t   If available we use the (BSD-style) flock(), if not we fall back to \n\t   Posix fcntl() locking (both mechanisms are broken, but flock() is \n\t   less broken).  In addition there's lockf(), but that's just a wrapper \n\t   around fcntl(), so there's no need to special-case it.\n\t   \n\t   fcntl() locking has two disadvantages over flock():\n\n\t   1. Locking is per-process rather than per-thread (specifically it's\n\t\t  based on processes and inodes rather than flock()'s file table\n\t\t  entries, for which any new handles created via dup()/fork()/open()\n\t\t  all refer to the same file table entry so there's a single location\n\t\t  at which to handle locking), so another thread in the same process\n\t\t  could still access the file (mind you with flock()'s file table \n\t\t  based locking you get the same thing repeated at a higher level \n\t\t  with fork() giving multiple processes \"exclusive\" access to a \n\t\t  file).\n\t\t  \n\t\t  Whether this shared-exclusive access is a good thing or not is \n\t\t  context-dependant: We want multiple threads to be able to read \n\t\t  from the file (if one keyset handle is shared among threads), but\n\t\t  not necessarily for multiple threads to be able to write.  We could\n\t\t  if necessary use mutexes for per-thread lock synchronisation, but\n\t\t  this gets incredibly ugly since we then have to duplicate parts of\n\t\t  the the system file table with per-thread mutexes, mess around with\n\t\t  an fstat() on each file access to determine if we're accessing an\n\t\t  already-open file, wrap all that up in more mutexes, etc etc, as\n\t\t  well as being something that's symtomatic of a user application bug\n\t\t  rather than normal behaviour that we can defend against.\n\n\t   2. Closing *any* descriptor for an fcntl()-locked file releases *all*\n\t\t  locks on the file (!!) (one manpage appropriately describes this\n\t\t  behaviour as \"the completely stupid semantics of System V and IEEE\n\t\t  Std 1003.1-1988 (= POSIX.1)\").  In other words if two threads or\n\t\t  processes open an fcntl()-locked file for shared read access then\n\t\t  the first close of the file releases all locks on it.  Since\n\t\t  fcntl() requires a file handle to work, the only way to determine\n\t\t  whether a file is locked requires opening it, but as soon as we\n\t\t  close it again (for example to abort the access if there's a lock\n\t\t  on it) all locks are released.\n\n\t   flock() sticks with the much more sensible 4.2BSD-based last-close\n\t   semantics, however it doesn't usually work with NFS unless special\n\t   hacks have been applied (for example under Linux it requires kernel\n\t   versions >= 2.6.12 to work).  fcntl() passes lock requests to\n\t   rpc.lockd to handle, but this is its own type of mess since it's\n\t   often unreliable, so it's really not much worse than flock().  In\n\t   addition locking support under filesystems like AFS is often\n\t   nonexistant, with the lock apparently succeeding but no lock actually\n\t   being applied, or the lock applying only to the locally buffered\n\t   copy.  Even under local Linux filesystems, mandatory locking is only \n\t   enabled if the filesystem is mounted with the \"-o mand\" option is \n\t   used, which is rarely the case (it's off by default).\n\n\t   Locking is almost always advisory only, but even mandatory locking\n\t   can be bypassed by tricks such as copying the original, unlinking it,\n\t   and renaming the copy back to the original (the unlinked - and still\n\t   locked - original goes away once the handle is closed) - this\n\t   mechanism is standard practice for many Unix utilities like text\n\t   editors.  A common mandatory locking implementation uses the sgid bit\n\t   (a directory bit that wouldn't normally be used for a file) and the\n\t   group execute bit to indicate that a file is subject to locking, \n\t   which another process can turn off/on and therefore disable the \n\t   locking.  In addition since NFS ignores sgid, mandatory locking \n\t   doesn't work there (see also the above comment about NFS).\n\n\t   Finally, mandatory locking is wierd in that an open for write (or \n\t   read, on a write-locked file) will succeed, it's only a later attempt \n\t   to read/write that will fail.  In addition major implementations like\n\t   Linux and Slowaris diverge from the SysV specs for mandatory\n\t   locking (the *BSD's don't support it at all), and different versions \n\t   differ in how they diverage.\n\n\t   This mess is why dotfile-locking is still so popular, but that's\n\t   probably going a bit far for simple keyset accesses */\n#ifndef USE_EMBEDDED_OS /* Embedded systems have no locking */\n\terrno = 0;\n  #ifndef USE_FCNTL_LOCKING\n\tif( flock( stream->fd, ( mode & FILE_FLAG_EXCLUSIVE_ACCESS ) ? \\\n\t\t\t\t\t\t   LOCK_EX | LOCK_NB : LOCK_SH | LOCK_NB ) < 0 && \\\n\t\terrno == EWOULDBLOCK )\n\t\t{\n\t\tclose( stream->fd );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n  #else\n\tmemset( &flockInfo, 0, sizeof( struct flock ) );\n\tflockInfo.l_type = ( mode & FILE_FLAG_EXCLUSIVE_ACCESS ) ? \\\n\t\t\t\t\t   F_WRLCK : F_RDLCK;\n\tflockInfo.l_whence = SEEK_SET;\n\tflockInfo.l_start = flockInfo.l_len = 0;\n\tif( fcntl( stream->fd, F_SETLK, &flockInfo ) < 0 && \\\n\t\t( errno == EACCES || errno == EDEADLK ) )\n\t\t{\n\t\t/* Now we're in a bind.  If we close the file and exit, the lock\n\t\t   we've just detected on the file is released (see the comment on\n\t\t   this utter braindamage above).  OTOH if we don't close the file\n\t\t   we'll leak the file handle, which is bad for long-running\n\t\t   processes.  Feedback from users indicates that leaking file\n\t\t   handles is less desirable than the possiblity of having the file\n\t\t   unlocked during an update (the former is a situation that occurs\n\t\t   far more frequently than the latter), so we close the handle and\n\t\t   hope that the update by the other process completes quickly */\n\t\tclose( stream->fd );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n  #endif /* flock() vs. fcntl() locking */\n#endif /* USE_EMBEDDED_OS */\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tBOOLEAN closeOK = TRUE;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Unlock the file if necessary.  If we're using fcntl() locking there's\n\t   no need to unlock the file since all locks are automatically released\n\t   as soon as any handle to it is closed (see the long comment above for\n\t   more on this complete braindamage) */\n#if !defined( USE_EMBEDDED_OS ) && !defined( USE_FCNTL_LOCKING )\n\tflock( stream->fd, LOCK_UN );\n#endif /* !USE_EMBEDDED_OS && !USE_FCNTL_LOCKING */\n\n\t/* Close the file.  In theory this shouldn't really be able to fail, but \n\t   NFS can elay the error reporting until this point rather than \n\t   reporting it during a write when it actually occurs.  Some disk quota \n\t   management systems can also cause problems, since the data is \n\t   buffered and the final size calculation doesn't occur until a set \n\t   quantization boundary is crossed or the file is closed.  AFS is even \n\t   worse, it caches copies of files being worked on locally and then \n\t   copies them back to the remote server, so the close can fail if the \n\t   copy fails, leaving nothing on the remote server, or a previous copy, \n\t   or a zero-length file.\n\n\t   There's not too much that we can do in the case of this condition, \n\t   the status itself is a bit weird because (apart from an EBADF or \n\t   EINTR) the close has actually succeeded, what's failed is some other \n\t   operation unrelated to the close.  The fsync() that was used earlier \n\t   will catch most problems, but not ones like AFS' invisible copy-to-\n\t   server operation on close.\n\n\t   The best that we can do is return a write-problem error indicator if \n\t   the close fails.  There's nothing that can be done to recover from \n\t   this, but where possible the caller can at least try to clean up the \n\t   file rather than leaving an incomplete file on disk */\n\tif( close( stream->fd ) < 0 )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\tcloseOK = FALSE;\n\t\t}\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( closeOK ? CRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = read( stream->fd, buffer, length ) ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( write( stream->fd, buffer, length ) != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage.  Unfortunately this\n   doesn't quite give the guarantees that it's supposed to because some\n   drives report a successful disk flush when all they've done is committed\n   the data to the drive's cache without actually having written it to disk\n   yet.  Directly-connected PATA/SATA drives mostly get it right, but\n   drives behind a glue layer like Firewire, USB, or RAID controllers often\n   ignore the SCSI SYNCHRONIZE CACHE / ATA FLUSH CACHE / FLUSH CACHE EXT /\n   FLUSH TRACK CACHE commands (that is, the glue layer discards them before\n   they get to the drive).  To get around this problem, Apple introducted\n   the FS_FULLFSYNC fcntl in OS X, but even this only works if the glue\n   layer doesn't discard cache flush commands that it generates.\n\n   The problem is endemic in drive design in general.  In order to produce\n   better benchmark results, drives issue write-completion notifications\n   when the data hits the track cache, in the hope that the host will issue\n   another write request to follow the current one so the two writes can\n   occur back-to-back.  The SCSI design solved this with tag queueing, which\n   allowed (typically) 16 write requests to be enqueued, rather than having\n   the host wait for each one to announce that it had completed.  This was\n   back-enginered into the ATA spec as tagged command queueing (TCQ), but \n   ATA allowed the completion of a tagged request to depend on whether the\n   write cache was enabled or not (it was enabled by default, since disabling\n   it produced a ~50% performance hit).  As a result, it had no effect, since\n   the drive would still post the completion notification as soon as the data\n   hit the cache - TCQ added more complexity with no real benefit.\n\n   This was finally fixed with native command queueing (NCQ), which works \n   more like the original SCSI tagged queueing in that there's a flag in\n   the write command that forces the drive to only report a write-completion \n   when the data is committed to stable media */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( ( fsync( stream->fd ) == 0 ) ? \\\n\t\t\tCRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( lseek( stream->fd, position, SEEK_SET ) == ( off_t ) -1 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n#ifdef EBCDIC_CHARS\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n#else\n\tassert( isReadPtr( fileName, 2 ) );\n#endif /* EBCDIC_CHARS */\n\terrno = 0;\n\tif( access( fileName, W_OK ) < 0 && errno != ENOENT )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tstruct stat fstatInfo;\n\tlong position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tif( fstat( stream->fd, &fstatInfo ) < 0 )\n\t\treturn;\n\tposition = lseek( stream->fd, 0, SEEK_CUR );\n\tlength = fstatInfo.st_size - position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n#ifdef __GNUC__\n\t/* Work around a persistent bogus warning in gcc.  Unfortunately this \n\t   generates a second warning about 'x' being unused, but it's less\n\t   problematic than the return-value-unused one */\n\t{ int dummy = ftruncate( stream->fd, position ); }\n#else\n\t( void ) ftruncate( stream->fd, position );\n#endif /* gcc with clang bug */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tstruct stat fstatInfo;\n#ifndef USE_EMBEDDED_OS /* Embedded systems have no file timestamps */\n  #if defined( __FreeBSD__ )\n\tstruct timeval timeVals[ 2 ];\n  #elif !( defined( __APPLE__ ) || defined( __FreeBSD__ ) || \\\n\t\t   defined( __linux__ ) )\n\tstruct utimbuf timeStamp;\n  #endif /* OS-specific variable declarations */\n#endif /* USE_EMBEDDED_OS */\n#ifdef EBCDIC_CHARS\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n#endif /* EBCDIC_CHARS */\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n#ifdef EBCDIC_CHARS\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n#endif /* EBCDIC_CHARS */\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tunlink( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tif( fstat( stream.fd, &fstatInfo ) == 0 )\n\t\teraseFile( &stream, 0, fstatInfo.st_size );\n#ifdef __GNUC__\n\t/* Work around a persistent bogus warning in gcc.  Unfortunately this \n\t   generates a second warning about 'x' being unused, but it's less\n\t   problematic than the return-value-unused one */\n\t{ int dummy = ftruncate( stream.fd, 0 ); }\n#else\n\t( void ) ftruncate( stream.fd, 0 );\n#endif /* gcc with clang bug */\n\n\t/* Reset the time stamps and delete the file.  On BSD filesystems that\n\t   support creation times (e.g. UFS2), the handling of creation times\n\t   has been kludged into utimes() by having it called twice.  The first\n\t   call sets the creation time provided that it's older than the\n\t   current creation time (which it always is, since we set it to the\n\t   epoch).  The second call then works as utimes() normally would.\n\n\t   Both the unlink() and utimes() calls use filenames rather than\n\t   handles, which unfortunately makes them subject to race conditions\n\t   where an attacker renames the file before the access.  Some systems\n\t   support the newer BSD futimes() (generally via glibc), but for the\n\t   rest we're stuck with using the unsafe calls.  The problem of unsafe\n\t   functions however is mitigated by the fact that we're acting on\n\t   files in restricted-access directories for which attackers shouldn't\n\t   be able to perform renames (but see the note further on on the safe \n\t   use of mkdir(), which a determined attacker could also bypass if they\n\t   really wanted to), and the fact that the file data is overwritten \n\t   before it's unlinked, so the most that an attacker who can bypass the \n\t   directory permissions can do is cause us to delete another file in a\n\t   generic DoS that they could perform anyway if they have the user's\n\t   rights */\n#ifndef USE_EMBEDDED_OS /* Embedded systems have no file timestamps */\n  #if defined( __Android__ )\n\tsFileClose( &stream );\n\tutimes( fileName, NULL );\t/* Android's Linux doesn't have futimes() */\n  #elif defined( __APPLE__ )\n\tfutimes( stream.fd, NULL );\n\tsFileClose( &stream );\n  #elif defined( __FreeBSD__ )\n\tmemset( timeVals, 0, sizeof( struct timeval ) * 2 );\n\tfutimes( stream.fd, timeVals );\n\tfutimes( stream.fd, timeVals );\n\tsFileClose( &stream );\n  #elif defined( __UCLIBC__ )\n\tsFileClose( &stream );\n\tutimes( fileName, NULL );\t/* uClibc doesn't have futimes() */\n  #elif defined( __linux__ )\n\tstatus = 0; errno = 0;\n\tif( futimes( stream.fd, NULL ) < 0 )\n\t\tstatus = errno;\t\t\t/* futimes() isn't available on all platforms */\n\tsFileClose( &stream );\n\tif( status == ENOSYS )\t\t/* futimes() failed, fall back to utimes() */\n\t\tutimes( fileName, NULL );\n  #else\n\tsFileClose( &stream );\n\tmemset( &timeStamp, 0, sizeof( struct utimbuf ) );\n\tutime( fileName, &timeStamp );\n  #endif /* OS-specific size and date-mangling */\n#else\n\tsFileClose( &stream );\n#endif /* USE_EMBEDDED_OS */\n\tunlink( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\n#if defined( USE_EMBEDDED_OS )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Embedded OSes have little in the way of filesystems so rather than \n\t   trying to second-guess what might be available we just dump \n\t   everything in the current directory */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n#else\n\n#include <pwd.h>\n#ifdef __iOS__ \n  #include <CoreFoundation/CoreFoundation.h>\n#endif /* __iOS__ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tstruct passwd *passwd;\n\tint length;\n#ifdef __iOS__ \n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n\tstruct passwd passwdInfo;\n#endif /* __iOS__ */\n#ifdef EBCDIC_CHARS\n\tchar fileNameBuffer[ MAX_PATH_LENGTH + 8 ];\n\tint status;\n#endif /* EBCDIC_CHARS */\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary.  In theory we \n\t   could perform further checking here to ensure that all directories in \n\t   the path to the target file are safe (i.e. not generally writeable) \n\t   because otherwise an attacker could remove a directory in the path \n\t   and substitute one of their own with the same name, which means that \n\t   we'd end up writing our config data into a directory that they \n\t   control, but in practice there's no easy way to enforce this because \n\t   it's unclear what the definition of \"safe\" is since it varies \n\t   depending on who the current user is, or more specifically what \n\t   rights the user currently has.  In addition the checking itself is \n\t   subject to race conditions which makes it complex to perform (see the \n\t   hoops that the file-open operation has to jump through above for a \n\t   small example of this).  In general when the system config is broken \n\t   enough to allow this type of attack there's not much more that we can \n\t   achieve with various Rube Goldberg checks, and on most systems all \n\t   it'll do is lead to lots of false positives because of the unclear \n\t   definition of what should be considered \"safe\" */\n#ifdef EBCDIC_CHARS\n\tfileName = bufferToEbcdic( fileNameBuffer, fileName );\n\t#pragma convlit( suspend )\n#endif /* EBCDIC_CHARS */\n\t/* Get the path to the user's home directory */\n\tif( ( passwd = getpwuid( getuid() ) ) == NULL )\n\t\t{\n\t\t/* iOS in the emulator and possibly in some sandboxed environments \n\t\t   doesn't have the user in the user database, or has a getpwuid()\n\t\t   that doesn't retrieve the information from it, so we fall back\n\t\t   to an iOS-specific call to get the same information, specifically\n\t\t   the Swift-based CFCopyHomeDirectoryURL() (and not the more \n\t\t   obvious NSHomeDirectory(), because Apple says so, in \n\t\t   documentation at the bottom of a locked filing cabinet in a \n\t\t   disused lavatory with a sign on the door saying \"Beware of OS X\n\t\t   10.5\"), which gets the home directory as a URL of the form\n\t\t   \"file:///<HOME>Library/Developer/CoreSimulator/Devices/...\" and\n\t\t   ending in a sequence of GUIDs and other garbage, but at least \n\t\t   it's something that's compatible with what pw_dir would have */\n#ifdef __iOS__\n\t\tif( CFStringGetCString( CFURLGetString( CFCopyHomeDirectoryURL() ), \n\t\t\t\t\t\t\t\tfileNameBuffer, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\tkCFStringEncodingUTF8 ) == true )\n\t\t\t{\n\t\t\tmemset( &passwdInfo, 0, sizeof( struct passwd ) );\n\t\t\tpasswd = &passwdInfo;\n\t\t\tpasswd->pw_dir = fileNameBuffer;\n\t\t\t}\n\t\telse\n#endif /* __iOS__ */\n\t\treturn( CRYPT_ERROR_OPEN );\t/* Huh?  User not in passwd file */\n\t\t}\n\tif( ( length = strlen( passwd->pw_dir ) ) > MAX_PATH_LENGTH - 64 )\n\t\treturn( CRYPT_ERROR_OPEN );\t/* You're kidding, right? */\n\n\t/* Set up the path to the cryptlib directory */\n#if defined( __APPLE__ )\n\tif( length + 32 >= pathMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\t/* OS X uses slighly longer paths */\n#else\n\tif( length + 16 >= pathMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n#endif /* OS X */\n\tREQUIRES( rangeCheck( length, 1, pathMaxLen ) );\n\tmemcpy( path, passwd->pw_dir, length );\n\tif( path[ length - 1 ] != '/' )\n\t\tpath[ length++ ] = '/';\n#if defined( __APPLE__ )\n\t/* Like Windows, OS X has a predefined location for storing user config\n\t   data */\n\tstrlcpy_s( path + length, pathMaxLen - length, \n\t\t\t   \"Library/Preferences/cryptlib\" );\n#else\n\tstrlcpy_s( path + length, pathMaxLen - length, \".cryptlib\" );\n#endif /* OS X */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now.  In theory we could eliminate potential \n\t   problems with race conditions by creating the directory and then \n\t   walking up the directory tree ensuring that only root and the current \n\t   user (via getuid()/geteuid()) have write access (so we're guaranteed \n\t   safe access to the newly-created directory), but this is a bit too \n\t   restrictive in that it can fail under otherwise valid situations with \n\t   group-accessible directories.  \n\t   \n\t   Dealing with the situation where the directory already exists is even \n\t   more problematic.  mkdir() is atomic (except for some very old NFS \n\t   implementations) and has an implied O_EXCL, failing with a EEXIST if \n\t   it already exists, however there's no way to know whether what we \n\t   created is what we end up with once we write a file.  On the other \n\t   hand an attacker would need root privs to exploit this (i.e. to remove \n\t   what we create and replace it with one that they control), in which \n\t   case they can get to us anyway.\n\n\t   In the case of opening an existing directory, we can run into the\n\t   same problem, however in that case the attacker would need to create\n\t   something that both they and we can access (again, unless they're \n\t   root).  We can check for this by verifying that the directory we\n\t   find has 0x00 permissions.  They can still defeat this by replacing\n\t   it between the check and the later creation of a file inside it, but\n\t   then we're back to the tree-walk above.\n\n\t   An additional defence is that the safe-file-open is already extremely \n\t   careful about creating the file in the directory securely, so we rely \n\t   on that rather than risking mysterious failures by going further with\n\t   Rube Goldberg-style checking */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tstruct stat statInfo;\n\n\t\t/* If the directory doesn't exist, try and create it */\n\t\tif( access( path, F_OK ) < 0 )\n\t\t\t{\n\t\t\terrno = 0;\n\t\t\tif( mkdir( path, 0700 ) < 0 )\n\t\t\t\t{\n\t\t\t\t/* This long-winded form of returning based on errno is \n\t\t\t\t   required instead of the more obvious \n\t\t\t\t   \"( errno == X ) ? A : B\" because it's hiding a function \n\t\t\t\t   call that's used to make it thread-safe, without this the\n\t\t\t\t   hackery breaks down and produces compile errors in some\n\t\t\t\t   environments */\n\t\t\t\tif( errno == EACCES )\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The directory exists, make sure that it looks OK: A directory, \n\t\t\t   no links, and restrictive permissions */\n\t\t\terrno = 0;\n\t\t\tif( stat( path, &statInfo ) < 0 || \\\n\t\t\t\t!S_ISDIR( statInfo.st_mode ) || statInfo.st_nlink != 1 )\n\t\t\t\t{\n\t\t\t\t/* See comment above */\n\t\t\t\tif( errno == EACCES )\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t\t}\n\t\t\tif( ( statInfo.st_mode & ( S_IRGRP | S_IWGRP | S_IXGRP ) ) || \\\n\t\t\t\t( statInfo.st_mode & ( S_IROTH | S_IWOTH | S_IXOTH ) ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Keyset directory has insecure permissions\" ));\n\t\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Add the filename to the path */\n\tstrlcat_s( path, pathMaxLen, \"/\" );\n#ifndef EBCDIC_CHARS\n\tANALYSER_HINT( fileName != NULL );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#else\n\tstatus = appendFilenameEBCDIC( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\t\t   fileNameLen, option );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tebcdicToAscii( path, path, *pathLen );\n\t#pragma convlit( resume )\n\n\treturn( CRYPT_OK );\n#endif /* EBCDIC_CHARS */\n\t}\n#endif /* OS-specific filesystem handling */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tVxWorks File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VxWorks__ )\n\n/* Some file functions can only be performed via ioctl()'s.  These include:\n\n\tchmod() - FIOATTRIBSET, dosFsLib, best-effort use only.\n\n\tflush() - FIOFLUSH, dosFsLib, rt11FsLib, fallback to FIOSYNC for nfsDrv.\n\n\tfstat() - FIOFSTATGET, dosFsLib, nfsDrv, rt11FsLib.\n\n\tftruncate() - FIOTRUNC, dosFsLib.\n\n\ttell() - FIOWHERE, dosFsLib, nfsDrv, rt11FsLib.\n\n\tutime() - FIOTIMESET, not documented to be supported, but probably\n\t\t\tpresent for utime() support in dirLib, best-effort use only.\n\t\t\tFor dosFsLib the only way to set the time is to install a time\n\t\t\thook via dosFsDateTimeInstall() before accessing the file, have\n\t\t\tit report the desired time when the file is accessed, and then\n\t\t\tuninstall it again afterwards, which is too unsafe to use\n\t\t\t(it'd affect all files on the filesystem.\n\n   Of these ftruncate() is the only problem, being supported only in\n   dosFsLib */\n\n/* When performing file accesses, we use the Unix-style errno to interpret\n   errors.  Unlike some other threaded systems which use preprocessor\n   tricks to turn errno into a function that returns a value on a per-thread\n   basis, VxWorks stores the last error in the TCB, so that errno can read\n   it directly from the TCB.\n\n   The error status is a 32-bit value, of which the high 16 bits are the\n   module number and the low 16 bits are the module-specific error.  However,\n   module 0 is reserved for Unix-compatible errors, allowing direct use of\n   the standard errno.h values.  This is complicated by the fact that the\n   error may also be a module-specific one, so we need a special function to\n   sort out the actual error details */\n\nCHECK_RETVAL \\\nstatic int getErrorCode( const int defaultErrorCode )\n\t{\n\tconst int moduleNo = errno >> 16;\n\tconst int errNo = errno & 0xFFFFL;\n\n\t/* If it's a Unix-compatible error code, we can use it directly */\n\tif( moduleNo == 0 )\n\t\t{\n\t\tswitch( errNo )\n\t\t\t{\n\t\t\tcase EPERM:\n\t\t\tcase EACCES:\n\t\t\tcase EROFS:\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\tcase ENOENT:\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tcase ENOMEM:\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tcase EBUSY:\n\t\t\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\t\tcase EEXIST:\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a module-specific error, check whether there's anything\n\t\t   that we can use */\n\t\tswitch( errNo )\n\t\t\t{\n\t\t\tcase S_ioLib_WRITE_PROTECTED:\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\tcase S_ioLib_DISK_NOT_PRESENT:\n\t\t\tcase S_iosLib_DEVICE_NOT_FOUND:\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t}\n\n\treturn( defaultErrorCode );\n\t}\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file.  We don't have to jump through the hoops that\n\t   are required for Unix because VxWorks doesn't support links (or the\n\t   functions that Unix provides to detec them) */\n\terrno = 0;\n\tif( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_WRITE )\n\t\t{\n\t\t/* We're creating the file, we have to use creat() rather than\n\t\t   open(), which can only open an existing file (well, except for\n\t\t   NFS filesystems) */\n\t\tif( ( stream->fd = creat( fileName, 0600 ) ) == ERROR )\n\t\t\treturn( getErrorCode( CRYPT_ERROR_OPEN ) );\n\t\t}\n\telse\n\t\t{\n\t\tconst int openMode = \\\n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t  O_RDONLY : O_RDWR;\n\n\t\t/* Open an existing file */\n\t\tif( ( stream->fd = open( fileName, openMode, 0600 ) ) == ERROR )\n\t\t\t{\n\t\t\t/* The open failed, determine whether it was because the file\n\t\t\t   doesn't exist or because we can't use that access mode */\n\t\t\treturn( getErrorCode( CRYPT_ERROR_OPEN ) );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tclose( stream->fd );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = read( stream->fd, buffer, length ) ) == ERROR )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( write( stream->fd, ( void * ) buffer, length ) != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage.  We use FIOFLUSH rather\n   then FIOSYNC, since the latter re-reads the written data into I/O buffers\n   while all we're interested in is forcing a commit.  However, nfsDrv only\n   supports FIOSYNC, so we try that as a fallback if FIOFLUSH fails */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( ioctl( stream->fd, FIOFLUSH, 0 ) == ERROR && \\\n\t\t\tioctl( stream->fd, FIOSYNC, 0 ) == ERROR ? \\\n\t\t\tCRYPT_ERROR_WRITE : CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( lseek( stream->fd, position, SEEK_SET ) == ERROR )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tint fd;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* The only way to tell whether a file is writeable is to try to open it\n\t   for writing, since there's no access() function */\n\terrno = 0;\n\tif( ( fd = open( fileName, O_RDWR, 0600 ) ) == ERROR )\n\t\t{\n\t\t/* We couldn't open it, check to see whether this is because it\n\t\t   doesn't exist or because it's not writeable */\n\t\treturn( getErrorCode( CRYPT_ERROR_OPEN ) == CRYPT_ERROR_PERMISSION ? \\\n\t\t\t\tTRUE : FALSE );\n\t\t}\n\tclose( fd );\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tstruct stat statStruct;\n\tlong position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file.  We use the\n\t   long-winded method of determining the overall length since it doesn't\n\t   require the presence of dirLib for fstat() */\n\tposition = ioctl( stream->fd, FIOWHERE, 0 );\n\tif( ioctl( stream->fd, FIOFSTATGET, ( int ) &statStruct ) != ERROR )\n\t\tlength = statStruct.st_size  - position;\n\telse\n\t\t{\n\t\t/* No stat support, do it via lseek() instead */\n\t\tlseek( stream->fd, 0, SEEK_END );\n\t\tlength = ioctl( stream->fd, FIOWHERE, 0 ) - position;\n\t\tlseek( stream->fd, position, SEEK_SET );\n\t\t}\n\teraseFile( stream, position, length );\n\tioctl( stream->fd, FIOTRUNC, position );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n\tstruct stat statStruct;\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tremove( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it.  We use the long-winded\n\t   method of determining the overall length since it doesn't require the\n\t   presence of dirLib for fstat() */\n\tif( ioctl( stream.fd, FIOFSTATGET, ( int ) &statStruct ) != ERROR )\n\t\tlength = statStruct.st_size;\n\telse\n\t\t{\n\t\t/* No stat support, do it via lseek() instead */\n\t\tlseek( stream.fd, 0, SEEK_END );\n\t\tlength = ioctl( stream.fd, FIOWHERE, 0 );\n\t\tlseek( stream.fd, 0, SEEK_SET );\n\t\t}\n\teraseFile( &stream, 0, length );\n\n\t/* Truncate the file and reset the attributes and timestamp.  We ignore \n\t   return codes since some filesystems don't support these ioctl()'s */\n\tioctl( stream.fd, FIOTRUNC, 0 );\n\tioctl( stream.fd, FIOATTRIBSET, 0 );\n\tioctl( stream.fd, FIOTIMESET, 0 );\n\n\t/* Finally, delete the file */\n\tsFileClose( &stream );\n\tremove( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWindows File Stream Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __WIN32__ ) || defined( __WINCE__ )\n\n/* File flags to use when accessing a file and attributes to use when\n   creating a file.  For access we tell the OS that we'll be reading the\n   file sequentially, for creation we prevent the OS from groping around\n   inside the file.  We could also be (inadvertently) opening the client\n   side of a named pipe, which would allow a server to impersonate us if\n   we're not careful.  To handle this we set the impersonation level to\n   SecurityAnonymous, which prevents the server from doing anything with our\n   capabilities.  Note that the pipe flag SECURITY_SQOS_PRESENT flag clashes\n   with the file flag FILE_FLAG_OPEN_NO_RECALL (indicating that data\n   shouldn't be moved in from remote storage if it currently resides there),\n   this isn't likely to be a problem.  The SECURITY_ANONYMOUS define\n   evaluates to zero, which means that it won't clash with any file flags,\n   however if future flags below the no-recall flag (0x00100000) are defined\n   for CreateFile() care needs to be taken that they don't run down into the\n   area used by the pipe flags around 0x000x0000 */\n\n#ifndef __WINCE__\n  #ifndef FILE_ATTRIBUTE_NOT_CONTENT_INDEXED\n\t#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED\t0x00002000\n  #endif /* VC++ <= 6.0 */\n  #define FILE_FLAGS\t\t\t\t( FILE_FLAG_SEQUENTIAL_SCAN | \\\n\t\t\t\t\t\t\t\t\t  SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS )\n  #define FILE_CREATE_ATTRIBUTES\t0\n  #define FILE_ADDITIONAL_ATTRIBUTES FILE_ATTRIBUTE_NOT_CONTENT_INDEXED\n#else\n  /* WinCE doesn't recognise the extended file flags */\n  #define FILE_FLAGS\t\t\t\t0\n  #define FILE_CREATE_ATTRIBUTES\t0\n  #define FILE_ADDITIONAL_ATTRIBUTES 0\n#endif /* Win32 vs.WinCE */\n#ifndef INVALID_FILE_ATTRIBUTES\n  #define INVALID_FILE_ATTRIBUTES\t( ( DWORD ) -1 )\n#endif /* INVALID_FILE_ATTRIBUTES */\n#ifndef INVALID_SET_FILE_POINTER\n  #define INVALID_SET_FILE_POINTER\t( ( DWORD ) -1 )\n#endif /* INVALID_SET_FILE_POINTER */\n\n/* Older versions of the Windows SDK don't include the defines for system\n   directories so we define them ourselves if necesary.  Note that we use\n   CSIDL_APPDATA, which expands to 'Application Data', rather than\n   CSIDL_LOCAL_APPDATA, which expands to 'Local Settings/Application Data',\n   because although the latter is technically safer (it's not part of the\n   roaming profile, so it'll never leave the local machine), it's\n   technically intended for less-important/discardable data and temporary\n   files */\n\n#ifndef CSIDL_PERSONAL\n  #define CSIDL_PERSONAL\t\t0x05\t/* 'My Documents' */\n#endif /* !CSIDL_PERSONAL */\n#ifndef CSIDL_APPDATA\n  #define CSIDL_APPDATA\t\t\t0x1A\t/* '<luser name>/Application Data' */\n#endif /* !CSIDL_APPDATA */\n#ifndef CSIDL_FLAG_CREATE\n  #define CSIDL_FLAG_CREATE\t\t0x8000\t/* Force directory creation */\n#endif /* !CSIDL_FLAG_CREATE */\n#ifndef SHGFP_TYPE_CURRENT\n  #define SHGFP_TYPE_CURRENT\t0\n#endif /* !SHGFP_TYPE_CURRENT */\n\n/* Older versions of the Windows SDK don't include the defines for services\n   added in Windows XP so we define them ourselves if necessary */\n\n#ifndef SECURITY_LOCAL_SERVICE_RID\n  #define SECURITY_LOCAL_SERVICE_RID\t19\n  #define SECURITY_NETWORK_SERVICE_RID\t20\n#endif /* !SECURITY_LOCAL_SERVICE_RID */\n\n/* Check whether a user's SID is known to a server providing a network\n   share, so that we can set file ACLs based on it */\n\n#ifndef __WINCE__\n\n#define TOKEN_BUFFER_SIZE\t256\n#define SID_BUFFER_SIZE\t\t256\n#define UNI_BUFFER_SIZE\t\t( 256 + _MAX_PATH )\n#define PATH_BUFFER_SIZE\t( _MAX_PATH + 16 )\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isSpecialSID( INOUT SID *pUserSid )\n\t{\n\tBYTE sidBuffer[ SID_BUFFER_SIZE + 8 ];\n\tSID *pSid = ( PSID ) sidBuffer;\n\tSID_IDENTIFIER_AUTHORITY identifierAuthority = SECURITY_NT_AUTHORITY;\n\n\tassert( isWritePtr( pUserSid, sizeof( SID ) ) );\n\n\t/* Create a SID for each special-case account and check whether it\n\t   matches the current user's SID.  It would be easier to use\n\t   IsWellKnownSid() for this check, but this only appeared in Windows\n\t   XP.  In addition IsWellKnowSID() contains a large (and ever-growing) \n\t   number of SIDs that aren't appropriate here, it's main use is to work \n\t   in conjunction with CreateWellKnownSID() to allow creation of a known \n\t   SID without having to jump through the usual SID-creation hoops */\n\tInitializeSid( pSid, &identifierAuthority, 1 );\n\t*( GetSidSubAuthority( pSid, 0 ) ) = SECURITY_LOCAL_SYSTEM_RID;\n\tif( EqualSid( pSid, pUserSid ) )\n\t\treturn( TRUE );\n\t*( GetSidSubAuthority( pSid, 0 ) ) = SECURITY_LOCAL_SERVICE_RID;\n\tif( EqualSid( pSid, pUserSid ) )\n\t\treturn( TRUE );\n\t*( GetSidSubAuthority( pSid, 0 ) ) = SECURITY_NETWORK_SERVICE_RID;\n\tif( EqualSid( pSid, pUserSid ) )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic const char *getUncName( OUT UNIVERSAL_NAME_INFO *nameInfo,\n\t\t\t\t\t\t\t   const char *fileName )\n\t{\n\ttypedef DWORD ( *WNETGETUNIVERSALNAMEA )( LPCSTR lpLocalPath,\n\t\t\t\tDWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize );\n\tWNETGETUNIVERSALNAMEA pWNetGetUniversalNameA;\n\tHINSTANCE hMPR;\n\tDWORD uniBufSize = UNI_BUFFER_SIZE;\n\tBOOLEAN gotUNC = FALSE;\n\n\tassert( isWritePtr( nameInfo, sizeof( UNIVERSAL_NAME_INFO ) ) );\n\tassert( isReadPtr( fileName, sizeof( char * ) ) );\n\n\t/* Clear return value */\n\tmemset( nameInfo, 0, sizeof( UNIVERSAL_NAME_INFO ) );\n\n\t/* Load the MPR library.  We can't (safely) use an opportunistic\n\t   GetModuleHandle() before the DynamicLoad() for this because the code\n\t   that originally loaded the DLL might do a DynamicUnload() in another\n\t   thread, causing the library to be removed from under us.  In any case\n\t   DynamicLoad() does this for us, merely incrementing the reference \n\t   count if the DLL is already loaded */\n\thMPR = DynamicLoad( \"Mpr.dll\" );\n\tif( hMPR == NULL )\n\t\t{\n\t\t/* Should never happen, we can't have a mapped network drive if no\n\t\t   network is available */\n\t\treturn( NULL );\n\t\t}\n\n\t/* Get the translated UNC name.  The UNIVERSAL_NAME_INFO struct is one\n\t   of those variable-length ones where the lpUniversalName member points\n\t   to extra data stored off the end of the struct, so we overlay it onto\n\t   a much larger buffer */\n\tpWNetGetUniversalNameA = ( WNETGETUNIVERSALNAMEA ) \\\n\t\t\t\t\t\t\t GetProcAddress( hMPR, \"WNetGetUniversalNameA\" );\n\tif( pWNetGetUniversalNameA != NULL && \\\n\t\tpWNetGetUniversalNameA( fileName, UNIVERSAL_NAME_INFO_LEVEL,\n\t\t\t\t\t\t\t\tnameInfo, &uniBufSize ) == NO_ERROR )\n\t\tgotUNC = TRUE;\n\tDynamicUnload( hMPR );\n\n\treturn( gotUNC ? nameInfo->lpUniversalName : NULL );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkUserKnown( IN_BUFFER( fileNameLength ) const char *fileName, \n\t\t\t\t\t\t\t   const int fileNameLength )\n\t{\n\tHANDLE hToken;\n\tBYTE uniBuffer[ UNI_BUFFER_SIZE + 8 ];\n\tBYTE tokenBuffer[ TOKEN_BUFFER_SIZE + 8 ];\n\tchar pathBuffer[ PATH_BUFFER_SIZE + 8 ];\n\tchar nameBuffer[ PATH_BUFFER_SIZE + 8 ];\n\tchar domainBuffer[ PATH_BUFFER_SIZE + 8 ];\n\tconst char *fileNamePtr = ( char * ) fileName;\n\tUNIVERSAL_NAME_INFO *nameInfo = ( UNIVERSAL_NAME_INFO * ) uniBuffer;\n\tTOKEN_USER *pTokenUser = ( TOKEN_USER * ) tokenBuffer;\n\tSID_NAME_USE eUse;\n\tDWORD nameBufSize = PATH_BUFFER_SIZE, domainBufSize = PATH_BUFFER_SIZE;\n\tBOOLEAN isMappedDrive = FALSE, tokenOK = FALSE;\n\tint fileNamePtrLength = fileNameLength, serverNameLength, length;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( fileName, fileNameLength ) );\n\n\tstatic_assert( sizeof( UNIVERSAL_NAME_INFO ) + _MAX_PATH <= UNI_BUFFER_SIZE, \\\n\t\t\t\t   \"UNC buffer size\" );\n\n\tREQUIRES_B( fileNameLength > 0 && fileNameLength < _MAX_PATH );\n\n\t/* WinCE doesn't have any ACL-based security, there's nothing to do */\n#ifdef __WINCE__\n\treturn( TRUE );\n#endif /* WinCE */\n\n\t/* Canonicalise the path name.  This turns relative paths into absolute\n\t   ones and converts forward to backwards slashes.  The latter is\n\t   necessary because while the Windows filesystem functions will accept\n\t   Unix-style forward slashes in paths, the WNetGetUniversalName()\n\t   networking function doesn't.\n\n\t   Note that this doesn't perform any checking that the path is valid, \n\t   it merely converts it into a somewhat canonical form, \"somewhat\" \n\t   meaning that long/short paths (\"Program Files\" vs. \"PROGRA~1\") aren't \n\t   converted to any particular form.\n\t   \n\t   GetFullPathName() has a weird return value where it can return a\n\t   success (nonzero) status even if it fails, which occurs when the\n\t   resulting string is too long to fit into the buffer.  In this case it \n\t   returns the required buffer size, so we have to check whether the \n\t   return value falls within a certain range rather than just being \n\t   nonzero.\n\t   \n\t   Finally, GetFullPathName() isn't thread-safe (!!).  OTOH Microsoft \n\t   provides no suggestions for an alternative when it warns about the \n\t   non-thread-safety of this function, so we just have to use it and \n\t   hope no other thread is calling it at the same time */\n\tlength = GetFullPathName( fileNamePtr, PATH_BUFFER_SIZE, pathBuffer, \n\t\t\t\t\t\t\t  NULL );\n\tif( length > 0 && length < PATH_BUFFER_SIZE )\n\t\t{\n\t\t/* The call succeeded, continue with the (mostly-)canonicalised \n\t\t   form, otherwise try and continue with the original form */\n\t\tfileNamePtr = pathBuffer;\n\t\tfileNamePtrLength = length;\n\t\t}\n\n\t/* If the path is too short to contain a drive letter or UNC path, it\n\t   must be local */\n\tif( fileNamePtrLength <= 2 )\n\t\treturn( TRUE );\n\n\t/* If there's a drive letter present, check whether it's a local or\n\t   remote drive.  GetDriveType() is rather picky about what it'll accept\n\t   so we have to extract just the drive letter from the path.  We could\n\t   also use IsNetDrive() for this, but this requires dynamically pulling\n\t   it in from shell32.dll, and even then it's only present in version 5.0\n\t   or later, so it's easier to use GetDriveType() */\n\tif( fileNamePtr[ 1 ] == ':' )\n\t\t{\n\t\tchar drive[ 8 + 8 ];\n\n\t\tmemcpy( drive, fileNamePtr, 2 );\n\t\tdrive[ 2 ] = '\\0';\n\t\tif( GetDriveType( drive ) != DRIVE_REMOTE )\n\t\t\t{\n\t\t\t/* It's a local drive, the user should be known */\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tisMappedDrive = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's not a UNC name, it's local (or something weird like a\n\t\t   mapped web page to which we shouldn't be writing keys anyway) */\n\t\tif( memcmp( fileNamePtr, \"\\\\\\\\\", 2 ) )\n\t\t\treturn( TRUE );\n\t\t}\n\n\t/* If it's a mapped network drive, get the name in UNC form.  What to do\n\t   in case of failure is a bit tricky.  If we get here we know that it's\n\t   a network share, but if there's some problem mapping it to a UNC (the\n\t   usual reason for this will be that there's a problem with the network\n\t   and the share is a cached remnant of a persistent connection), all we\n\t   can do is fail safe and hope that the user is known */\n\tif( isMappedDrive )\n\t\t{\n\t\tfileNamePtr = getUncName( nameInfo, fileNamePtr );\n\t\tif( fileNamePtr == NULL )\n\t\t\treturn( TRUE );\n\t\t}\n\n\tassert( !memcmp( fileNamePtr, \"\\\\\\\\\", 2 ) );\n\n\t/* We've got the network share in UNC form, extract the server name.  If\n\t   for some reason the name is still an absolute path, the following will\n\t   convert it to \"x:\\\", which is fine */\n\tLOOP_LARGE( serverNameLength = 2, \n\t\t\t\tserverNameLength < fileNamePtrLength && \\\n\t\t\t\t\tfileNamePtr[ serverNameLength ] != '\\\\', \\\n\t\t\t\tserverNameLength++ );\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( serverNameLength <= 0 || serverNameLength >= PATH_BUFFER_SIZE - 2 )\n\t\t{\n\t\t/* Server name is too long, default to fail-safe handling */\n\t\treturn( TRUE );\n\t\t}\n\tREQUIRES( boundsCheck( serverNameLength, 1, PATH_BUFFER_SIZE ) );\n\tmemmove( pathBuffer, fileNamePtr, serverNameLength );\n\tstrlcpy_s( pathBuffer + serverNameLength, \n\t\t\t   PATH_BUFFER_SIZE - serverNameLength, \"\\\\\" );\n\n\t/* Get the current user's SID */\n\tif( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) || \\\n\t\tOpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )\n\t\t{\n\t\tDWORD cbTokenUser;\n\n\t\ttokenOK = GetTokenInformation( hToken, TokenUser, pTokenUser,\n\t\t\t\t\t\t\t\t\t   TOKEN_BUFFER_SIZE, &cbTokenUser );\n\t\tCloseHandle( hToken );\n\t\t}\n\tif( !tokenOK )\n\t\treturn( TRUE );\t\t\t/* Default fail-safe */\n\n\t/* Check whether this is a special-case account that can't be mapped to\n\t   an account on the server */\n\tif( isSpecialSID( pTokenUser->User.Sid ) )\n\t\t{\n\t\t/* The user with this SID may be known to the server, but it\n\t\t   represents a different entity on the server than it does on the\n\t\t   local system */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check whether the user with this SID is known to the server.  We\n\t   get some additional info in the form of the eUse value, which\n\t   indicates the general class of the SID (e.g. SidTypeUser,\n\t   SidTypeGroup, SidTypeDomain, SidTypeAlias, etc, but these aren't of\n\t   much use to us */\n\tif( !LookupAccountSid( pathBuffer, pTokenUser->User.Sid,\n\t\t\t\t\t\t   nameBuffer, &nameBufSize,\n\t\t\t\t\t\t   domainBuffer, &domainBufSize, &eUse ) && \\\n\t\tGetLastError() == ERROR_NONE_MAPPED )\n\t\t{\n\t\t/* The user with this SID isn't known to the server */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Either the user is known to the server or it's a fail-safe */\n\treturn( TRUE );\n\t}\n#endif /* !__WINCE__ */\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n#ifndef __WINCE__\n\tHANDLE hFile;\n\tUINT uErrorMode;\n\tconst char *fileNamePtr = fileName;\n#else\n\twchar_t fileNameBuffer[ _MAX_PATH + 16 ], *fileNamePtr = fileNameBuffer;\n#endif /* __WINCE__ */\n\tvoid *aclInfo = NULL;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\n\t/* Convert the filename to the native character set if necessary */\n#ifdef __WINCE__\n\tstatus = asciiToUnicode( fileNameBuffer, _MAX_PATH, fileName,\n\t\t\t\t\t\t\t strlen( fileName ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_OPEN );\n#endif /* __WINCE__ */\n\n\t/* Don't allow the use of escapes that disable path parsing, and make\n\t   sure that the path has a sensible length.  There are in theory \n\t   various additional checks that we could add at this point, for \n\t   example to try and detect spurious dots and spaces in the path, which \n\t   are handled by Windows in unexpected ways, generally by removing \n\t   them.\n\t   \n\t   For example \"foo...   . ... ...\" would be opened as \"foo.\".  This can \n\t   lead to tricks like specifying a name like \"foo.exe  ..  .. \n\t   <to MAX_PATH>.txt\" which is then truncated at MAX_PATH and the morse \n\t   code also truncated to create \"foo.exe\" instead of a text file.  \n\t   Alternatively it's also possible to force the creation of files with \n\t   trailing dots and spaces by using an alternate data stream specifier \n\t   \"::<name>\" after the trailing junk, since ADS parsing occurs after \n\t   stripping of trailing junk, so the ADS specifier protects the junk.\n\t   \n\t   On the other hand it's not exactly clear why a user would be doing \n\t   something like this with their crypto keyset, or even whether we can \n\t   evade all the various other tricks they could play at the filesystem \n\t   level */\n\tif( !memcmp( fileNamePtr, \"\\\\\\\\\", 2 ) )\n\t\t{\n\t\tconst int length = strlen( ( char * ) fileNamePtr );\n\n\t\tif( length >= 4 && !memcmp( fileNamePtr, \"\\\\\\\\?\\\\\", 4 ) )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\telse\n\t\t{\n\t\tif( !memcmp( fileNamePtr, L\"\\\\\\\\\", 4 ) )\n\t\t\t{\n\t\t\tconst int length = wcslen( ( wchar_t * ) fileNamePtr );\n\n\t\t\tif( length >= 8 && !memcmp( fileNamePtr, L\"\\\\\\\\?\\\\\", 8 ) )\n\t\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n\n\t/* Check for files that end in a dot, which can be created by low-level \n\t   functions like CreateFile() but that cause problems with other \n\t   Windows APIs and tools.  Note the comments about tricks with path\n\t   truncation and ADS specifiers above, a sufficiently determined user \n\t   can always create a file ending in a dot, but again it's uncertain \n\t   why someone would be doing this with their own crypto keyset */\n#ifdef __WINCE__\n\tif( ( wchar_t * ) fileNamePtr[ wcslen( ( wchar_t * ) fileNamePtr ) ] == L'.' )\n\t\treturn( CRYPT_ERROR_OPEN );\n#else\n\tif( fileNamePtr[ strlen( fileNamePtr ) ] == '.' )\n\t\treturn( CRYPT_ERROR_OPEN );\n#endif /* __WINCE__ */\n\n\t/* If we're creating the file and we don't want others to get to it, set\n\t   up the security attributes to reflect this if the OS supports it.\n\t   Unfortunately creating the file with ACLs doesn't always work when\n\t   the file is located on a network share because what's:\n\n\t\tcreate file, ACL = user SID access\n\n\t   on a local drive can become:\n\n\t\tcreate file, ACL = <unknown SID> access\n\n\t   on the network share if the user is accessing it as a member of a\n\t   group and their individual SID isn't known to the server.  As a\n\t   result, they can't read the file that they've just created.  To get\n\t   around this, we need to perform an incredibly convoluted check (via\n\t   checkUserKnown()) to see whether the path is a network path and if\n\t   so, if the user is known to the server providing the network share.\n\n\t   An extension of this problem occurs where the user *is* known on the\n\t   local and server system, but the two are logically different.  This\n\t   occurs for the System/LocalSystem service account and,for Windows XP\n\t   and newer, LocalService and NetworkService.  To handle this,\n\t   checkUserKnown() also checks whether the user is running under one of\n\t   these accounts */\n#ifndef __WINCE__\n\tif( ( mode & FILE_FLAG_WRITE ) && ( mode & FILE_FLAG_PRIVATE ) && \\\n\t\tcheckUserKnown( fileNamePtr, strlen( fileNamePtr ) ) )\n\t\t{\n\t\t/* It's a filesystem that supports ACLs and it's safe for us to \n\t\t   apply them, make sure only the current user can access the file.\n\t\t   We have to explicitly request delete access alongside the usual\n\t\t   read and write otherwise the user can't later delete the file\n\t\t   after they've created it */\n\t\taclInfo = initACLInfo( FILE_GENERIC_READ | FILE_GENERIC_WRITE | \\\n\t\t\t\t\t\t\t   DELETE );\n\t\tif( aclInfo == NULL )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#endif /* __WINCE__ */\n\n\t/* Check that the file isn't a special file type, for example a device \n\t   pseudo-file.  This includes not only files like CON, PRN, AUX, COM1-9 \n\t   and LPT1-9 but also variations like \"com5.p15\", since the suffix is \n\t   ignored.\n\t   \n\t   WinCE doesn't have these pseudo-files, so this function doesn't exist \n\t   there.  In theory we could check for the various FILE_ATTRIBUTE_xxxROM \n\t   variations, but that'll be handled automatically by CreateFile().  \n\t   \n\t   We perform this check before we try any of the open actions since \n\t   it's most likely to catch accidental access to the wrong file, and we \n\t   want to have the chance to bail out before making irreversible \n\t   changes like the call to DeleteFile() below.  To avoid race \n\t   conditions, a further check is carried out after the file is \n\t   opened */\n#ifndef __WINCE__\n\thFile = CreateFile( fileNamePtr, GENERIC_READ, FILE_SHARE_READ, NULL,\n\t\t\t\t\t\tOPEN_EXISTING, FILE_FLAGS, NULL );\n\tif( hFile != INVALID_HANDLE_VALUE )\n\t\t{\n\t\tconst DWORD type = GetFileType( hFile );\n\n\t\tCloseHandle( hFile );\n\t\tif( type != FILE_TYPE_DISK )\n\t\t\t{\n\t\t\tif( aclInfo != NULL )\n\t\t\t\tfreeACLInfo( aclInfo );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n#endif /* __WINCE__ */\n\n\t/* Try and open the file */\n#ifndef __WINCE__\n\tuErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );\n#endif /* __WINCE__ */\n\tif( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_WRITE )\n\t\t{\n\t\tBOOL fSuccess;\n\n\t\t/* If we're creating the file, we need to remove any existing file\n\t\t   of the same name before we try and create a new one, otherwise\n\t\t   the OS will pick up the permissions for the existing file and\n\t\t   apply them to the new one.  This is safe because if an attacker\n\t\t   tries to slip in a wide-open file between the delete and the\n\t\t   create, we'll get a file-already-exists status returned that we\n\t\t   can trap and turn into an error.  Since the DeleteFile() can fail \n\t\t   in ways that indicate that the following CreateFile() isn't going \n\t\t   to succeed either, we check for certain failure cases and exit \n\t\t   immediately if we encounter them */\n\t\tfSuccess = DeleteFile( fileNamePtr );\n\t\tif( !fSuccess && GetLastError() == ERROR_ACCESS_DENIED )\n\t\t\t{\n\t\t\tif( aclInfo != NULL )\n\t\t\t\tfreeACLInfo( aclInfo );\n\n\t\t\t/* This is a sufficiently odd problem that we call extra \n\t\t\t   attention to it in debug mode */\n\t\t\tDEBUG_DIAG(( \"Attempt to delete file '%s' in order to replace \"\n\t\t\t\t\t\t \"it failed\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\t\tstream->hFile = CreateFile( fileNamePtr, GENERIC_READ | GENERIC_WRITE, 0,\n\t\t\t\t\t\t\t\t\tgetACLInfo( aclInfo ), CREATE_ALWAYS,\n\t\t\t\t\t\t\t\t\tFILE_CREATE_ATTRIBUTES | FILE_FLAGS, NULL );\n\t\tif( stream->hFile != INVALID_HANDLE_VALUE )\n\t\t\t{\n\t\t\tif( GetLastError() == ERROR_ALREADY_EXISTS )\n\t\t\t\t{\n\t\t\t\t/* There was already something there that wasn't hit by the \n\t\t\t\t   delete, we can't be sure that the file has the required \n\t\t\t\t   semantics */\n\t\t\t\tCloseHandle( stream->hFile );\n\t\t\t\tDeleteFile( fileNamePtr );\n\t\t\t\tstream->hFile = INVALID_HANDLE_VALUE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Some file attributes can't be set at file create time but \n\t\t\t\t   have to be set once the file has been created, so we set \n\t\t\t\t   them at this point.  We don't worry if this operation \n\t\t\t\t   fails since the attributes are merely nice-to-have rather\n\t\t\t\t   than critical */\n\t\t\t\tconst DWORD dwAttrs = GetFileAttributes( fileNamePtr ); \n\t\t\t\tif( dwAttrs != INVALID_FILE_ATTRIBUTES && \\\n\t\t\t\t\t( dwAttrs & FILE_ADDITIONAL_ATTRIBUTES ) != FILE_ADDITIONAL_ATTRIBUTES ) \n\t\t\t\t\t{\n\t\t\t\t\t( void ) SetFileAttributes( fileNamePtr, \n\t\t\t\t\t\t\t\t\tdwAttrs | FILE_ADDITIONAL_ATTRIBUTES );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tconst int openMode = ( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\t\t GENERIC_READ : GENERIC_READ | GENERIC_WRITE;\n\t\tconst int shareMode = ( mode & FILE_FLAG_EXCLUSIVE_ACCESS ) ? \\\n\t\t\t\t\t\t\t  0 : FILE_SHARE_READ;\n\n\t\tstream->hFile = CreateFile( fileNamePtr, openMode, shareMode, NULL,\n\t\t\t\t\t\t\t\t\tOPEN_EXISTING, FILE_FLAGS, NULL );\n#ifndef __WINCE__\n\t\tif( stream->hFile != INVALID_HANDLE_VALUE && \\\n\t\t\tGetFileType( stream->hFile ) != FILE_TYPE_DISK )\n\t\t\t{\n\t\t\t/* This repeats the check that we made earlier before trying \n\t\t\t   to open the file, and works around a potential race condition \n\t\t\t   in which an attacker creates a special file after we perform \n\t\t\t   the check (since the usual targets, CON, AUX, and so on, are\n\t\t\t   OS pseudo-files it shouldn't be an issue in that case, but \n\t\t\t   there are other special-case files that could be created that \n\t\t\t   aren't hardcoded into the OS that we can also catch here) */\n\t\t\tCloseHandle( stream->hFile );\n\t\t\tif( aclInfo != NULL )\n\t\t\t\tfreeACLInfo( aclInfo );\n\t\t\tSetErrorMode( uErrorMode );\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n#endif /* __WINCE__ */\n\t\t}\n#ifndef __WINCE__\n\tSetErrorMode( uErrorMode );\n#endif /* __WINCE__ */\n\tif( stream->hFile == INVALID_HANDLE_VALUE )\n\t\t{\n\t\t/* Translate the Win32 error code into an equivalent cryptlib error\n\t\t   code */\n\t\tswitch( GetLastError() )\n\t\t\t{\n\t\t\tcase ERROR_FILE_NOT_FOUND:\n\t\t\tcase ERROR_PATH_NOT_FOUND:\n\t\t\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\t\t\t\tbreak;\n\n\t\t\tcase ERROR_ACCESS_DENIED:\n\t\t\t\tstatus = CRYPT_ERROR_PERMISSION;\n\t\t\t\tbreak;\n\n\t\t\tcase ERROR_BUSY:\n\t\t\t\tstatus = CRYPT_ERROR_TIMEOUT;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstatus = CRYPT_ERROR_OPEN;\n\t\t\t}\n\t\t}\n\n\t/* In theory we could also use something like SHChangeNotify( \n\t   SHCNE_CREATE, SHCNF_PATH, fileName, NULL ) at this point to tell \n\t   other apps that we've created the file, but since this is a private \n\t   config/key file that's not really meant to be messed with by other \n\t   apps, we leave it up to them to discover that there's been a change \n\t   if they really feel they need to know this */\n\n\t/* Clean up */\n\tif( aclInfo != NULL )\n\t\tfreeACLInfo( aclInfo );\n\treturn( status );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tCloseHandle( stream->hFile );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n    DWORD byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( !ReadFile( stream->hFile, buffer, length, &byteCount, NULL ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tDWORD bytesWritten;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( !WriteFile( stream->hFile, buffer, length, &bytesWritten, NULL ) || \\\n\t\t( int ) bytesWritten != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( FlushFileBuffers( stream->hFile ) ? CRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( SetFilePointer( stream->hFile, position, NULL,\n\t\t\t\t\t\tFILE_BEGIN ) == INVALID_SET_FILE_POINTER )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tHANDLE hFile;\n#ifdef __WINCE__\n\twchar_t fileNameBuffer[ _MAX_PATH + 16 ], *fileNamePtr = fileNameBuffer;\n\tint status;\n#else\n\tconst char *fileNamePtr = fileName;\n#endif /* __WINCE__ */\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Convert the filename to the native character set if necessary */\n#ifdef __WINCE__\n\tstatus = asciiToUnicode( fileNameBuffer, _MAX_PATH, fileName,\n\t\t\t\t\t\t\t strlen( fileName ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( TRUE );\n#endif /* __WINCE__ */\n\n\t/* The only way to tell whether a file is writeable is to try to open it\n\t   for writing.  An access()-based check is pointless because it just\n\t   calls GetFileAttributes() and checks for the read-only bit being set.\n\t   Even if we wanted to check for this basic level of access, it\n\t   wouldn't work because writes can still be blocked if it's a read-only\n\t   file system or a network share */\n\thFile = CreateFile( fileNamePtr, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,\n\t\t\t\t\t\tFILE_ATTRIBUTE_NORMAL, NULL );\n\tif( hFile == INVALID_HANDLE_VALUE )\n\t\t{\n\t\t/* Translate the Win32 error code into an equivalent cryptlib error\n\t\t   code */\n\t\treturn( ( GetLastError() == ERROR_ACCESS_DENIED ) ? TRUE : FALSE );\n\t\t}\n\tCloseHandle( hFile );\n\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tif( ( position = SetFilePointer( stream->hFile, 0, NULL,\n\t\t\t\t\t\t\tFILE_CURRENT ) ) == INVALID_SET_FILE_POINTER )\n\t\treturn;\n\tlength = GetFileSize( stream->hFile, NULL ) - position;\n\tif( length <= 0 )\n\t\treturn;\t/* Nothing to do, exit */\n\teraseFile( stream, position, length );\n\tSetFilePointer( stream->hFile, position, NULL, FILE_BEGIN );\n\tSetEndOfFile( stream->hFile );\n\tFlushFileBuffers( stream->hFile );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n#ifdef __WINCE__\n\twchar_t fileNameBuffer[ _MAX_PATH + 16 ], *fileNamePtr = fileNameBuffer;\n#else\n\tconst char *fileNamePtr = fileName;\n#endif /* __WINCE__ */\n\tint status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Convert the filename to the native character set if necessary */\n#ifdef __WINCE__\n\tstatus = asciiToUnicode( fileNameBuffer, _MAX_PATH, fileName, \n\t\t\t\t\t\t\t strlen( fileName ) + 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn;\t\t/* Error converting filename string, exit */\n#endif /* __WINCE__ */\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tDeleteFile( fileNamePtr );\n\t\treturn;\n\t\t}\n\teraseFile( &stream, 0, GetFileSize( stream.hFile, NULL ) );\n\n\t/* Truncate the file and if we're erasing the entire file, reset the\n\t   timestamps */\n\tSetFilePointer( stream.hFile, 0, NULL, FILE_BEGIN );\n\tSetEndOfFile( stream.hFile );\n\tSetFileTime( stream.hFile, 0, 0, 0 );\n\n\t/* Commit the changes to disk before calling DeleteFile().  If we \n\t   didn't do this then the OS would drop all changes once DeleteFile() \n\t   was called, leaving the original more or less intact on disk */\n\tFlushFileBuffers( stream.hFile );\n\n\t/* Delete the file */\n\tsFileClose( &stream );\n\tDeleteFile( fileNamePtr );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\n#if defined( __WIN32__ )\n\n#if VC_GE_2005( _MSC_VER )\n  #pragma warning( push )\n  #pragma warning( disable : 4255 )\t/* Errors in VersionHelpers.h */\n  #include <VersionHelpers.h>\n  #pragma warning( pop )\n#endif /* VC++ >= 2005 */\n#ifdef __WIN64__\n  #define WIN_DEFAULT_USER_HANDLE\tIntToPtr( -1 )\n#else\n  #define WIN_DEFAULT_USER_HANDLE\t( HANDLE ) -1\n#endif /* 32- vs. 64-bit Windows */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int getFolderPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen )\n\t{\n\ttypedef HRESULT ( WINAPI *SHGETFOLDERPATH )( HWND hwndOwner,\n\t\t\t\t\t\t\t\t\t\tint nFolder, HANDLE hToken,\n\t\t\t\t\t\t\t\t\t\tDWORD dwFlags, LPTSTR lpszPath );\n\tSHGETFOLDERPATH pSHGetFolderPath;\n#if VC_LT_2010( _MSC_VER )\n\tconst int osMajorVersion = getSysVar( SYSVAR_OSMAJOR );\n#endif /* VC++ < 2010 */\n\tBOOLEAN gotPath = FALSE;\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\tmemset( path, 0, min( 16, pathMaxLen ) );\n\t*pathLen = 0;\n\n\t/* SHGetFolderPath() doesn't have an explicit buffer-size parameter to\n\t   pass to the function, it always assumes a buffer of at least MAX_PATH\n\t   bytes, so before we can call it we have to ensure that we've got at\n\t   least this much room in the output buffer */\n\tREQUIRES( pathMaxLen >= MAX_PATH );\n\n\t/* Build the path to the configuration file if necessary.  We can't\n\t   (safely) use an opportunistic GetModuleHandle() before the\n\t   DynamicLoad() for this because the code that originally loaded the\n\t   DLL might do a DynamicUnload() in another thread, causing the library \n\t   to be removed from under us.  In any case DynamicLoad() does this for \n\t   us, merely incrementing the reference count if the DLL is already\n\t   loaded */\n#if VC_LT_2010( _MSC_VER )\n\tif( osMajorVersion <= 4 )\n\t\t{\n\t\tHINSTANCE hComCtl32, hSHFolder;\n\n\t\t/* Try and find the location of the closest thing that Windows has\n\t\t   to a home directory.  This is a bit of a problem function in that\n\t\t   both the function name and parameters have changed over time, and\n\t\t   it's only included in pre-Win2K versions of the OS via a kludge\n\t\t   DLL that takes the call and redirects it to the appropriate\n\t\t   function anderswhere.  Under certain (very unusual) circumstances\n\t\t   this kludge can fail if shell32.dll and comctl32.dll aren't\n\t\t   mapped into the process' address space yet, so we have to check\n\t\t   for the presence of these DLLs in memory as well as for the\n\t\t   successful load of the kludge DLL.  In addition the function name\n\t\t   changed yet again for Vista to SHGetKnownFolderPath(), but the\n\t\t   existing SHGetFolderPath() is provided as a wrapper for\n\t\t   SHGetKnownFolderPath() so we use that in all cases to keep\n\t\t   things simple.  Finally, the use of the CSIDL_FLAG_CREATE flag \n\t\t   can cause performance issues if it requires groping around on a \n\t\t   network (for example due to having your profile folder redirected \n\t\t   to a network share that's offline), but this is fairly uncommon \n\t\t   so it shouldn't be a problem */\n\t\thComCtl32 = DynamicLoad( \"ComCtl32.dll\" );\n\t\tif( hComCtl32 != NULL )\n\t\t\t{\n\t\t\tif( ( hSHFolder = DynamicLoad( \"SHFolder.dll\" ) ) != NULL )\n\t\t\t\t{\n\t\t\t\tpSHGetFolderPath = ( SHGETFOLDERPATH ) \\\n\t\t\t\t\t\t\t   GetProcAddress( hSHFolder, \"SHGetFolderPathA\" );\n\t\t\t\tif( pSHGetFolderPath != NULL && \\\n\t\t\t\t\tpSHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,\n\t\t\t\t\t\t\t\t\t  NULL, SHGFP_TYPE_CURRENT, path ) == S_OK )\n\t\t\t\t\tgotPath = TRUE;\n\t\t\t\tDynamicUnload( hSHFolder );\n\t\t\t\t}\n\t\t\tDynamicUnload( hComCtl32 );\n\t\t\t}\n\t\t}\n\telse\n#endif /* VC++ < 2010 */\n\t\t{\n#if VC_LT_2010( _MSC_VER )\n\t\tconst int osMinorVersion = getSysVar( SYSVAR_OSMINOR );\n\t\tconst BOOLEAN isXPOrNewer = ( osMajorVersion > 5 || \\\n\t\t\t\t\t\t\t\t\t( osMajorVersion == 5 && \\\n\t\t\t\t\t\t\t\t\t  osMinorVersion >= 1 ) ) ? TRUE : FALSE;\n#else\n\t\tconst BOOLEAN isXPOrNewer = IsWindowsXPOrGreater() ? TRUE : FALSE;\n#endif /* VC++ < 2010 */\n\t\tchar defaultUserPath[ MAX_PATH + 16 ];\n\t\tBOOLEAN isDefaultUserPath = FALSE;\n\t\tHINSTANCE hShell32;\n\n\t\t/* Try and find the location of the closest thing that Windows has\n\t\t   to a home directory.  Note that this call can fail in nonobvious \n\t\t   ways in specific situations such as when we're being run as a \n\t\t   service (with no logged-on user) and so SHGetFolderPath() has no \n\t\t   user profile to access, which means it returns the default-user \n\t\t   profile.  In this case we don't have privileges to access it, and \n\t\t   the CreateDirectory() call that follows will fail.  There's no \n\t\t   programmatic way that we can address this here since it's \n\t\t   something caused by the calling application that we're part of, \n\t\t   the caller can take various steps such as explicitly calling \n\t\t   LoadUserProfile() to ensure that there's a user profile set when \n\t\t   SHGetFolderPath() gets called, but LoadUserProfile() in turn \n\t\t   requires admin or LocalSystem privs.  The best that we can do \n\t\t   here is to get the path for the default-user profile (which is \n\t\t   only possible for WinXP or newer) and if that matches the path \n\t\t   that the standard SHGetFolderPath() returned, record a diagnostic \n\t\t   and return an error, since the attempt to create a subdirectory \n\t\t   in the default-user path below will fail (and even if it doesn't \n\t\t   fail it's not safe to continue with it since whatever we store \n\t\t   there will be replicated for any new user that logs on) */\n\t\thShell32 = DynamicLoad( \"Shell32.dll\" );\n\t\tif( hShell32 != NULL )\n\t\t\t{\n\t\t\tpSHGetFolderPath = ( SHGETFOLDERPATH ) \\\n\t\t\t\t\t\t\t   GetProcAddress( hShell32, \"SHGetFolderPathA\" );\n\t\t\tif( pSHGetFolderPath != NULL )\n\t\t\t\t{\n\t\t\t\tif( pSHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,\n\t\t\t\t\t\t\t\t\t  NULL, SHGFP_TYPE_CURRENT, path ) == S_OK )\n\t\t\t\t\tgotPath = TRUE;\n\t\t\t\tif( gotPath && isXPOrNewer && \\\n\t\t\t\t\tpSHGetFolderPath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,\n\t\t\t\t\t\t\t\t\t  WIN_DEFAULT_USER_HANDLE, \n\t\t\t\t\t\t\t\t\t  SHGFP_TYPE_CURRENT, \n\t\t\t\t\t\t\t\t\t  defaultUserPath ) == S_OK )\n\t\t\t\t\t{\n\t\t\t\t\tif( !strcmp( path, defaultUserPath ) )\n\t\t\t\t\t\tisDefaultUserPath = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tDynamicUnload( hShell32 );\n\t\t\t}\n\t\tif( isDefaultUserPath )\n\t\t\t{\n\t\t\t/* We've ended up with the profile for the default user, which \n\t\t\t   we can't store per-user configuration data in, warn the \n\t\t\t   caller (if possible) and exit */\n\t\t\tDEBUG_DIAG(( \"No Windows user profile available, is this \"\n\t\t\t\t\t\t \"application running as a service or using \"\n\t\t\t\t\t\t \"impersonation?\" ));\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t\t}\n\t\t}\n\tif( gotPath )\n\t\t{\n\t\t*pathLen = strlen( path );\n\t\tif( *pathLen < 3 )\n\t\t\t{\n\t\t\t/* Under WinNT and Win2K the LocalSystem account doesn't have \n\t\t\t   its own profile so SHGetFolderPath() will report success but \n\t\t\t   return a zero-length path if we're running as a service.  In \n\t\t\t   this case we use the nearest equivalent that LocalSystem has \n\t\t\t   to its own directories, which is the Windows directory.  This \n\t\t\t   is safe because LocalSystem always has permission to write \n\t\t\t   there */\n\t\t\tif( !GetWindowsDirectory( path, pathMaxLen - 8 ) )\n\t\t\t\t*path = '\\0';\n\t\t\t*pathLen = strlen( path );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We didn't get the folder path, fall back to dumping data in the \n\t   Windows directory.  This will probably fail on systems where the user \n\t   doesn't have privs to write there but if SHGetFolderPath() fails it's \n\t   an indication that something's wrong anyway.\n\n\t   If this too fails, we fall back to the root dir.  This has the same \n\t   problems as the Windows directory for non-admin users, but we try it \n\t   just in case the user manually copied the config there as a last \n\t   resort */\n\tif( GetWindowsDirectory( path, pathMaxLen - 8 ) )\n\t\t*pathLen = strlen( path );\n\telse\n\t\t{\n\t\t*path = '\\0';\n\t\t*pathLen = 0;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* __WIN32__ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH ) \\\n\t\t\t\t\t\t\t\tconst BUILDPATH_OPTION_TYPE option )\n\t{\n#if defined( __WIN32__ )\n  #if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n\t#define HRESULT\t\tDWORD\t/* Not defined in older BC++ headers */\n  #endif /* BC++ before 5.5 */\n\tchar *pathPtr = path;\n\tint length, status;\n#elif defined( __WINCE__ )\n\twchar_t pathBuffer[ _MAX_PATH + 8 ], *pathPtr = pathBuffer;\n\tBOOLEAN gotPath = FALSE;\n\tint length;\n#endif /* Win32 vs. WinCE */\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n#if defined( __WIN32__ )\n\t/* Get the path to the user data folder/directory */\n\tstatus = getFolderPath( path, pathMaxLen, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length + 16 >= pathMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tstrlcpy_s( pathPtr + length, pathMaxLen - length, \"\\\\cryptlib\" );\n#elif defined( __WINCE__ )\n\tif( SHGetSpecialFolderPath( NULL, pathPtr, CSIDL_APPDATA, TRUE ) || \\\n\t\tSHGetSpecialFolderPath( NULL, pathPtr, CSIDL_PERSONAL, TRUE ) )\n\t\t{\n\t\t/* We have to check for the availability of two possible locations\n\t\t   since some older PocketPC versions don't have CSIDL_APPDATA */\n\t\tgotPath = TRUE;\n\t\t}\n\tif( !gotPath )\n\t\t{\n\t\t/* This should never happen under WinCE since the get-path\n\t\t   functionality is always available */\n\t\twcscpy( pathPtr, L\"\\\\Windows\" );\n\t\t}\n\tlength = wcslen( pathPtr );\n\n\t/* Make sure that the path buffer meets the minimum-length requirements.  \n\t   We have to check both that the Unicode version of the string fits \n\t   into the Unicode path buffer and that the resulting ASCII-converted \n\t   form fits into the output buffer */\n\tREQUIRES( ( length + 16 ) * sizeof( wchar_t ) <= _MAX_PATH && \\\n\t\t\t  length + 16 <= pathMaxLen );\n\n\twcscat( pathPtr, L\"\\\\cryptlib\" );\n#endif /* Win32 vs. WinCE */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( ( option == BUILDPATH_CREATEPATH ) && \\\n\t\tGetFileAttributes( pathPtr ) == INVALID_FILE_ATTRIBUTES )\n\t\t{\n\t\tvoid *aclInfo = NULL;\n\t\tBOOLEAN retVal = TRUE;\n\n\t\tif( ( aclInfo = initACLInfo( FILE_ALL_ACCESS ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tretVal = CreateDirectory( pathPtr, getACLInfo( aclInfo ) );\n\t\tfreeACLInfo( aclInfo );\n\t\tif( !retVal )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#if defined( __WINCE__ )\n\tunicodeToAscii( path, pathMaxLen, pathPtr, wcslen( pathPtr ) + 1 );\n#endif /* __WINCE__ */\n\n\t/* Add the filename to the path */\n\tstrlcat_s( path, pathMaxLen, \"\\\\\" );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tXilinx XMK\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __XMK__ )\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const int modes[] = { MFS_MODE_READ, MFS_MODE_READ,\n\t\t\t\t\t\t\t\t MFS_MODE_CREATE, MFS_MODE_WRITE };\n\tint openMode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to read from the file, check whether it exists */\n\tif( ( mode & FILE_FLAG_READ ) && mfs_exists_file( fileName ) != 1 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Try and open the file */\n\tif( ( stream->fd = mfs_file_open( fileName, openMode ) ) < 0 )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tmfs_file_close( stream->fd );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = mfs_file_read( stream->fd, buffer, length ) ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tif( mfs_file_write( stream->fd, buffer, length ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Since the backing store is flash memory and writing simply copies it\n\t   to flash, there's no real way to flush data to disk */\n\treturn( CRYPT_OK );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\t/* MFS doesn't support any type of writing other than appending to the\n\t   end of the file, so if we try and seek in a non-readonly file we\n\t   return an error */\n\tif( !( stream->flags & STREAM_FLAG_READONLY ) )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_WRITE );\n\t\t}\n\n\tif( mfs_file_lseek( stream->fd, position, MFS_SEEK_SET ) < 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* All non-ROM filesystems are writeable under MFS, in theory a ROM-based\n\t   FS would be non-writeable but there's no way to tell whether the\n\t   underlying system is ROM or RAM */\n\treturn( FALSE );\n\t}\n\n/* File deletion functions: Wipe a file from the current position to EOF,\n   and wipe and delete a file (although it's not terribly rigorous).  Since\n   MFS doesn't support any type of file writes except appending data to an\n   existing file, the best that we can do is to simply delete the file\n   without trying to overwrite it */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\treturn;\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Delete the file */\n\tmfs_delete_file( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now */\n\tif( option == BUILDPATH_CREATEPATH && mfs_exists_file( path ) != 2 )\n\t\t{\n\t\t/* The directory doesn't exist, try and create it */\n\t\tif( mfs_create_dir( path ) <= 0 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n#ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n#endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEverything Else (Generic stdio)\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#else\n\n/* BC++ 3.1 is rather anal-retentive about not allowing extensions when in\n   ANSI mode */\n\n#if defined( __STDC__ ) && ( __BORLANDC__ == 0x410 )\n  #define fileno( filePtr )\t\t( ( filePtr )->fd )\n#endif /* BC++ 3.1 in ANSI mode */\n\n/* When checking whether a file is read-only we also have to check (via\n   errno) to make sure that the file actually exists since the access check\n   will return a false positive for a nonexistant file */\n\n#if defined( __MSDOS16__ ) || defined( __OS2__ ) || defined( __WIN16__ )\n  #include <errno.h>\n#endif /* __MSDOS16__ || __OS2__ || __WIN16__ */\n\n/* Some OS'es don't define W_OK for the access check */\n\n#ifndef W_OK\n  #define W_OK\t\t\t\t2\n#endif /* W_OK */\n\n/* Watcom C under DOS supports file-time access via DOS functions */\n\n#if defined( __WATCOMC__ ) && defined( __DOS__ )\n  #include <dos.h>\n\n  struct ftime {\n\tunsigned short ft_tsec : 5;\t\t/* Two seconds */\n\tunsigned short ft_min : 6;\t\t/* Minutes */\n\tunsigned short ft_hour : 5;\t\t/* Hours */\n\tunsigned short ft_day : 5;\t\t/* Days */\n\tunsigned short ft_month : 4;\t/* Months */\n\tunsigned short ft_year : 7;\t\t/* Year - 1980 */\n\t};\n#endif /* Watcom C under DOS */\n\n/* Extra system-specific includes */\n\n#ifdef __WIN16__\n  #include <direct.h>\n#endif /* Win16 */\n\n/* SMX includes stdio-like functionality but with the names prefixed by \n   'sfs_', to handle this we map them to the equivalent stdio names */\n\n#ifdef __SMX__\n  /* If we're cross-compiling then some values and functions-as-macros may \n     already be set in the host environment */\n  #ifdef SEEK_CUR\n\t#undef SEEK_CUR\n\t#undef SEEK_END\n\t#undef SEEK_SET\n  #endif /* SEEK_xxx */\n  #ifdef ferror\n\t#undef ferror\n  #endif /* ferror */\n\n  /* SMX doesn't have an ferror() so we no-op it out */\n  #define ferror( file )\t0\n\n  /* Mapping from SFS to stdio naming */\n  #define SEEK_CUR\tSFS_SEEK_CUR\n  #define SEEK_END\tSFS_SEEK_END\n  #define SEEK_SET\tSFS_SEEK_SET\n  #define fclose\tsfs_fclose\n  #define fflush\tsfs_fflush\n  #define fopen( filename, mode ) \\\n\t\t  sfs_fopen( ( char * ) filename, mode )\n  #define fread\t\tsfs_fread\n  #define fseek\t\tsfs_fseek\n  #define ftell\t\tsfs_ftell\n  #define fwrite( ptr, size, nitems, stream ) \\\n\t\t   sfs_fwrite( ( void * ) ptr, size, nitems, stream )\n  #define remove( filename ) \\\n\t\t  sfs_fdelete( ( char * ) filename )\n#endif /* __SMX__ */\n\n/* Open/close a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode )\n\t{\n\tstatic const char *modes[] = { MODE_READ, MODE_READ,\n\t\t\t\t\t\t\t\t   MODE_WRITE, MODE_READWRITE };\n\tconst char *openMode;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( mode != 0 );\n\n\t/* Initialise the stream structure */\n\tinitFileStream( stream, \n\t\t\t\t\t( ( mode & FILE_FLAG_RW_MASK ) == FILE_FLAG_READ ) ? \\\n\t\t\t\t\t\tTRUE : FALSE );\n\topenMode = modes[ mode & FILE_FLAG_RW_MASK ];\n\n\t/* If we're trying to write to the file, check whether we've got\n\t   permission to do so */\n\tif( ( mode & FILE_FLAG_WRITE ) && fileReadonly( fileName ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Try and open the file */\n#if defined( __TANDEMNSK__ ) || defined( __TI_COMPILER_VERSION__ )\n\terrno = 0;\n#endif /* Tandem || TI embedded */\n\tstream->filePtr = fopen( fileName, openMode );\n#if defined( __BEOS__ ) || defined( __MSDOS16__ ) || \\\n\tdefined( __WIN16__ ) || defined( __WINCE__ ) || defined( __OS2__ ) || \\\n\tdefined( __SYMBIAN32__ )\n\tif( stream->filePtr == NULL )\n\t\t{\n\t\t/* The open failed, determine whether it was because the file doesn't\n\t\t   exist or because we can't use that access mode */\n\t\treturn( ( access( fileName, 0 ) < 0 ) ? \\\n\t\t\t\t  CRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n\t\t}\n#elif defined( __MQXRTOS__ )\n\tif( stream->filePtr == NULL )\n\t\t{\n\t\tconst int errorCode = _task_get_error();\n\n\t\treturn( ( errorCode == MFS_FILE_NOT_FOUND || \\\n\t\t\t\t  errorCode == MFS_PATH_NOT_FOUND ) ? \\\n\t\t\t\t  CRYPT_ERROR_NOTFOUND : \\\n\t\t\t\t( errorCode == MFS_ACCESS_DENIED ) ? \\\n\t\t\t\t  CRYPT_ERROR_PERMISSION : \\\n\t\t\t\t  CRYPT_ERROR_OPEN );\n\t\t}\n#elif defined( __SMX__ )\n\tif( stream->filePtr == NULL )\n\t\t{\n\t\tconst int lastError = sfs_getlasterror( 0 );\n\n\t\treturn( ( lastError == SFS_ERR_FILE_NOT_EXIST ) ? \\\n\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n\t\t}\n#elif defined( __TANDEMNSK__ ) || defined( __TI_COMPILER_VERSION__ )\n\tif( stream->filePtr == NULL )\n\t\t{\n\t\treturn( ( errno == ENOENT ) ? \\\n\t\t\t\tCRYPT_ERROR_NOTFOUND : CRYPT_ERROR_OPEN );\n\t\t}\n#else\n  #error Need to add file open error-handling\n#endif /* OS-specific file open error-handling */\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\t/* Close the file and clear the stream structure */\n\tfclose( stream->filePtr );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write a block of data from/to a file stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead )\n\t{\n\tint byteCount;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*bytesRead = 0;\n\n\tif( ( byteCount = fread( buffer, 1, length, stream->filePtr ) ) < length && \\\n\t\t( byteCount < 0 || ferror( stream->filePtr ) ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\t*bytesRead = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* The macro-remapped function that fwrite() ends up as has the buffer \n\t   as a non-const parameter, so we cast it to that to avoid compiler\n\t   complaints */\n\tif( fwrite( ( void * ) buffer, 1, length, stream->filePtr ) != length )\n\t\treturn( sSetError( stream, CRYPT_ERROR_WRITE ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Commit data in a file stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\n\treturn( fflush( stream->filePtr ) == 0 ? CRYPT_OK : CRYPT_ERROR_WRITE );\n\t}\n\n/* Change the read/write position in a file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream, \n\t\t\t  IN_DATALENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\tif( fseek( stream->filePtr, position, SEEK_SET ) )\n\t\treturn( sSetError( stream, CRYPT_ERROR_READ ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether a file is writeable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName )\n\t{\n#if defined( __BEOS__ ) || defined( __MSDOS16__ ) || \\\n\tdefined( __WIN16__ ) || defined( __OS2__ ) || defined( __SYMBIAN32__ )\n\tif( access( fileName, R_OK ) == 0 && access( fileName, W_OK ) < 0 )\n\t\treturn( TRUE );\n#elif defined( __MQXRTOS__ )\n\tFILE *filePtr;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tif( ( filePtr = fopen( fileName, MODE_READWRITE ) ) == NULL )\n\t\t{\n\t\tconst int errorCode = _task_get_error();\n\n\t\tif( errorCode == MFS_ACCESS_DENIED || \\\n\t\t\terrorCode == MFS_DISK_IS_WRITE_PROTECTED || \\\n\t\t\terrorCode == MFS_SHARING_VIOLATION )\n\t\t\treturn( TRUE );\n\t\t}\n\telse\n\t\tfclose( filePtr );\n#elif defined( __SMX__ )\n\tFILEINFO fileInfo;\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tif( !sfs_getprop( fileName, &fileInfo ) )\n\t\treturn( TRUE );\n\treturn( ( fileInfo.bAttr & SFS_ATTR_READ_ONLY ) ? TRUE : FALSE );\n#elif defined( __TANDEMNSK__ ) || defined( __TI_COMPILER_VERSION__ )\n\tFILE *filePtr;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\terrno = 0;\n\tif( ( filePtr = fopen( fileName, MODE_READWRITE ) ) == NULL )\n\t\t{\n\t\tif( errno == EACCES )\n\t\t\treturn( TRUE );\n\t\t}\n\telse\n\t\tfclose( filePtr );\n#else\n  #error Need to add file accessibility call\n#endif /* OS-specific file accessibility check */\n\n\treturn( FALSE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream )\n\t{\n\tlong position, length;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_V( stream->type == STREAM_TYPE_FILE );\n\n\t/* Wipe everything past the current position in the file */\n\tposition = ftell( stream->filePtr );\n\tfseek( stream->filePtr, 0, SEEK_END );\n\tlength = ftell( stream->filePtr ) - position;\n\tfseek( stream->filePtr, position, SEEK_SET );\n\teraseFile( stream, position, length );\n#if defined( __AMIGA__ )\n\tSetFileSize( fileno( stream->filePtr ), OFFSET_BEGINNING, position );\n#elif defined( __MSDOS16__ ) || defined( __MSDOS32__ )\n\tchsize( fileno( stream->filePtr ), position );\n#elif defined( __OS2__ )\n\tDosSetFileSize( fileno( stream->filePtr ), position );\n#elif defined( __SMX__ )\n\tsfs_fseek( stream->filePtr, position, SFS_SEEK_SET );\n\tsfs_ftruncate( stream->filePtr );\n#elif defined( __WIN16__ )\n\t_chsize( fileno( stream->filePtr ), position );\n#endif /* OS-specific size mangling */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName )\n\t{\n\tSTREAM stream;\n#if defined( __AMIGA__ )\n\tstruct DateStamp dateStamp;\n#elif defined( __MSDOS16__ ) || defined( __MSDOS32__ )\n\tstruct ftime fileTime;\n#elif defined( __OS2__ )\n\tFILESTATUS info;\n#elif defined( __SMX__ )\n\tFILEINFO fileInfo;\n#elif defined( __WIN16__ )\n\tHFILE hFile;\n#endif /* OS-specific variable declarations */\n\tint length, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Try and open the file so that we can erase it.  If this fails, the\n\t   best that we can do is a straight unlink */\n\tstatus = sFileOpen( &stream, fileName,\n\t\t\t\t\t\tFILE_FLAG_READ | FILE_FLAG_WRITE | \\\n\t\t\t\t\t\tFILE_FLAG_EXCLUSIVE_ACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\tremove( fileName );\n\t\treturn;\n\t\t}\n\n\t/* Determine the size of the file and erase it */\n\tfseek( stream.filePtr, 0, SEEK_END );\n\tlength = ( int ) ftell( stream.filePtr );\n\tfseek( stream.filePtr, 0, SEEK_SET );\n\teraseFile( &stream, 0, length );\n\n\t/* Truncate the file and reset the timestamps.  This is only possible \n\t   through a file handle on some systems, on others the caller has to do \n\t   it via the filename */\n#if defined( __AMIGA__ )\n\tSetFileSize( fileno( stream.filePtr ), OFFSET_BEGINNING, 0 );\n#elif defined( __MSDOS16__ ) || defined( __MSDOS32__ )\n\tchsize( fileno( stream.filePtr ), 0 );\n\tmemset( &fileTime, 0, sizeof( struct ftime ) );\n  #if defined( __WATCOMC__ )\n\t_dos_setftime( fileno( stream.filePtr ), \\\n\t\t\t\t   *( ( unsigned short * ) &fileTime + 1 ), \\\n\t\t\t\t   *( ( unsigned short * ) &fileTime ) );\n  #else\n\tsetftime( fileno( stream.filePtr ), &fileTime );\n  #endif /* __WATCOMC__ */\n#elif defined( __OS2__ )\n\tDosSetFileSize( fileno( stream.filePtr ), 0 );\n#elif defined( __SMX__ )\n\tsfs_fseek( stream.filePtr, 0, SFS_SEEK_SET );\n\tsfs_ftruncate( stream.filePtr );\n#elif defined( __WIN16__ )\n\t_chsize( fileno( stream.filePtr ), 0 );\n#endif /* OS-specific size mangling */\n\n\t/* Truncate the file to 0 bytes if we couldn't do it via the file \n\t   handle, reset the time stamps, and delete it */\n\tsFileClose( &stream );\n#if defined( __AMIGA__ )\n\tmemset( dateStamp, 0, sizeof( struct DateStamp ) );\n\tSetFileDate( fileName, &dateStamp );\n#elif defined( __OS2__ )\n\tDosQueryPathInfo( ( PSZ ) fileName, FIL_STANDARD, &info, sizeof( info ) );\n\tmemset( &info.fdateLastWrite, 0, sizeof( info.fdateLastWrite ) );\n\tmemset( &info.ftimeLastWrite, 0, sizeof( info.ftimeLastWrite ) );\n\tmemset( &info.fdateLastAccess, 0, sizeof( info.fdateLastAccess ) );\n\tmemset( &info.ftimeLastAccess, 0, sizeof( info.ftimeLastAccess ) );\n\tmemset( &info.fdateCreation, 0, sizeof( info.fdateCreation ) );\n\tmemset( &info.ftimeCreation, 0, sizeof( info.ftimeCreation ) );\n\tDosSetPathInfo( ( PSZ ) fileName, FIL_STANDARD, &info, sizeof( info ), 0 );\n#elif defined( __SMX__ )\n\tmemset( &fileInfo, 0, sizeof( FILEINFO ) );\n\tfileInfo.st_mtime.wYear = fileInfo.st_ctime.wYear = 2000;\n\tfileInfo.st_mtime.wMonth = fileInfo.st_ctime.wMonth = 1;\n\tfileInfo.st_mtime.wDay = fileInfo.st_ctime.wDay = 1;\n\tsfs_setprop( ( char * ) fileName, &fileInfo, \n\t\t\t\t SFS_SET_ATTRIBUTE | SFS_SET_CREATETIME | SFS_SET_WRITETIME );\n#elif defined( __WIN16__ )\n\t/* Under Win16 we can't really do anything without resorting to MSDOS int\n\t   21h calls, the that best we can do is truncate the file using \n\t   _lcreat() */\n\thFile = _lcreat( fileName, 0 );\n\tif( hFile != HFILE_ERROR )\n\t\t_lclose( hFile );\n#endif /* OS-specific size and date-mangling */\n\n\t/* Finally, delete the file */\n\tremove( fileName );\n\t}\n\n/* Build the path to a file in the cryptlib directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH_OPTION ) \\\n\t\t\t\t\t\t   const BUILDPATH_OPTION_TYPE option )\n\t{\n#if defined( __OS2__ )\n\tULONG aulSysInfo[ 1 ] = { 0 };\n#endif /* OS-specific info */\n\n\tassert( isWritePtrDynamic( path, pathMaxLen ) );\n\tassert( isWritePtr( pathLen, sizeof( int ) ) );\n\tassert( ( option == BUILDPATH_RNDSEEDFILE ) || \\\n\t\t\tisReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( pathMaxLen > 32 && pathMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( ( option == BUILDPATH_CREATEPATH || \\\n\t\t\t\t  option == BUILDPATH_GETPATH ) && fileName != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( fileNameLen ) ) || \\\n\t\t\t  ( option == BUILDPATH_RNDSEEDFILE && fileName == NULL && \\\n\t\t\t    fileNameLen == 0 ) );\n\n\t/* Make sure that the open fails if we can't build the path */\n\t*path = '\\0';\n\n\t/* Build the path to the configuration file if necessary */\n#if defined( __MSDOS__ )\n\tstrlcpy_s( path, pathMaxLen, \"c:/dos/\" );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#elif defined( __WIN16__ )\n\tGetWindowsDirectory( path, pathMaxLen - 32 );\n\tstrlcat_s( path, pathMaxLen, \"\\\\cryptlib\" );\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now.  There's no way to check for its\n\t   existence in advance, so we try and create it unconditionally but\n\t   ignore EACCESS errors */\n\tif( ( option == BUILDPATH_CREATEPATH ) && \\\n\t\t!_mkdir( path ) && ( errno != EACCES ) )\n\t\treturn( CRYPT_ERROR_OPEN );\n\n\t/* Add the filename to the path */\n\tstrlcat_s( path, pathMaxLen, \"\\\\\" );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#elif defined( __OS2__ )\n\tDosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, ( PVOID ) aulSysInfo,\n\t\t\t\t\t sizeof( ULONG ) );\t\t/* Get boot drive info */\n\tif( *aulSysInfo == 0 )\n\t\treturn( CRYPT_ERROR_OPEN );\t/* No boot drive info */\n\tpath[ 0 ] = *aulSysInfo + 'A' - 1;\n\tstrlcpy_s( path + 1, pathMaxLen - 1, \":\\\\OS2\\\\\" );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#elif defined( __SMX__ )\n  #ifdef CONFIG_FILE_PATH\n\tREQUIRES( strlen( CONFIG_FILE_PATH ) >= 1 );\n\tstrlcpy_s( path, pathMaxLen, CONFIG_FILE_PATH );\n  #endif /* CONFIG_FILE_PATH */\n\n\t/* If we're being asked to create the cryptlib directory and it doesn't\n\t   already exist, create it now.  We use sfs_getprop() to check for\n\t   existence, and if it doesn't exist we create it */\n\tif( option == BUILDPATH_CREATEPATH )\n\t\t{\n\t\tFILEINFO fileInfo;\n\n\t\tif( sfs_getprop( fileName, &fileInfo ) != 0 && \\\n\t\t\tsfs_mkdir( path ) != PASS )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n  #ifdef CONFIG_FILE_PATH\n\tif( path[ strlen( path ) - 1 ] != '/' )\n\t\tstrlcat_s( path, pathMaxLen, \"/\" );\n  #endif /* CONFIG_FILE_PATH */\n\n\t/* Add the filename to the path */\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#elif defined( __TANDEMNSK__ )\n\tstrlcpy_s( path, pathMaxLen, \"$system.system.\" );\n\tif( option == BUILDPATH_RNDSEEDFILE )\n\t\tstrlcat_s( path, pathMaxLen, \"randseed\" );\n\telse\n\t\tstrlcat_s( path, pathMaxLen, fileName );\n\treturn( CRYPT_OK );\n#elif defined( __SYMBIAN32__ )\n\tstrlcpy_s( path, pathMaxLen, \"C:\\\\SYSTEM\\\\DATA\\\\\" );\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName, \n\t\t\t\t\t\t\tfileNameLen, option ) );\n#elif defined( __MGOS__ ) || defined( __MQXRTOS__ ) || \\\n\t  defined( __TI_COMPILER_VERSION__ )\n\treturn( appendFilename( path, pathMaxLen, pathLen, fileName,\n\t\t\t\t\t\t\tfileNameLen, option ) );\n#else\n  #error Need to add function to build the config file path\n\n\treturn( CRYPT_ERROR_OPEN );\n#endif /* OS-specific file path creation */\n\t}\n#endif /* OS-specific file stream handling */\n#endif /* USE_FILES */\n"
  },
  {
    "path": "deps/cl345/io/file.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFile Stream I/O Header\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _STRFILE_DEFINED\n\n#define _STRFILE_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tAMX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __AMX__ )\n\n#include <fjzzz.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tDOS/Win16\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MSDOS16__ ) || defined( __WIN16__ )\n\n#include <io.h>\n#include <errno.h>\t\t\t/* Needed for access() check */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tIBM 4758\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __IBM4758__ )\n\n#include <scc_err.h>\n#include <scc_int.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tMacintosh\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MAC__ )\n\n#include <Script.h>\n#if defined __MWERKS__\n  #pragma mpwc_relax off\n  #pragma extended_errorcheck on\n#endif /* __MWERKS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tMongoose OS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MGOS__ )\n\n#include <mgos_vfs.h>\n\n/* The Mongoose VFS header defines the Unix-style I/O functions, but with \n   the prefix \"mgos_vfs_\", so we map them back to standard names.  We have \n   to be careful with mapping stat() because there's also a struct stat */\n\n#define open\t\t\tmgos_vfs_open\n#define close\t\t\tmgos_vfs_close\n#define read\t\t\tmgos_vfs_read\n#define write\t\t\tmgos_vfs_write\n#define stat( a, b )\tmgos_vfs_stat( a, b )\n#define fstat\t\t\tmgos_vfs_fstat\n#define lseek\t\t\tmgos_vfs_lseek\n#define unlink\t\t\tmgos_vfs_unlink\n#define rename\t\t\tmgos_vfs_rename\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tMQX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MQXRTOS__ )\n\n/* The MQX fio.h redefines every stdio function to MQX_internal names, if \n   we're cross-compiling and stdio functions are already present as macros \n   then we have to undefine them to let MQX re-define them.  If they're \n   present as typedefs then we have to map them to something harmless.  \n   \n   Finally, we have to define __STDC__ to remove some hacks that are enabled\n   in the MQX headers if this isn't defined */\n\n#ifdef _MSC_VER\n  #ifdef feof\n\t#undef feof\n\t#undef ferror\n\t#undef stdin\n\t#undef stdout\n\t#undef stderr\n\t#define FILE\t\t__FILE\n  #endif /* Conflicting defines */\n  #define __STDC__\t\t1\n#endif\n\n#include <mfs.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tNucleus\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Nucleus__ )\n\n#include <pcdisk.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tOS/2\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __OS2__ )\n\n#define INCL_DOSFILEMGR\t\t/* DosQueryPathInfo(),DosSetFileSize(),DosSetPathInfo */\n#define INCL_DOSMISC\t\t/* DosQuerySysInfo() */\n#include <os2.h>\t\t\t/* FILESTATUS */\n#include <io.h>\n#include <errno.h>\t\t\t/* Needed for access() check */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tQuadros\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Quadros__ )\n\n#include <udefs_s.h>\n#include <api_s.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tSMX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __SMX__ )\n\n#include <smx.h>\n#include <smxfs.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tTelit\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Telit__ )\n\n#include <m2m_fs_api.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tThreadX (via FileX)\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __FileX__ )\n\n#include <fx_api.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tTI RTS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __TI_COMPILER_VERSION__ )\n\n#include <errno.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tuITRON\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ITRON__ )\n\n/* uITRON has a file API (ITRON/FILE) derived from the BTRON persistent\n   object store interface, but the only documentationm for this is for BTRON\n   and it's only available in Japanese.  Because of the inability to obtain\n   either documentation or an implementation to code against, anyone with\n   access to the required documentation/implementation will need to fill in\n   the required headers and functions here */\n\n#error You need to set up the ITRON/FILE headers and interface in str_file.c\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUnix/Unix-like Systems\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Android__ ) || defined( __BEOS__ ) || \\\n\t  defined( __ECOS__ ) || defined( __iOS__ ) || defined( __MVS__ ) || \\\n\t  defined( __RTEMS__ ) || defined( __SYMBIAN32__ ) || \\\n\t  defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\t  defined( __UNIX__ )\n\n#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n  /* Needed for lstat() in sys/lstat.h */\n  #define _XOPEN_SOURCE_EXTENDED\t1\n#endif /* Tandem */\n#include <errno.h>\n#include <fcntl.h>\n#include <sys/types.h>\n#if !( defined( __ECOS__ ) || defined( __TANDEM_NSK__ ) || \\\n\t   defined( __TANDEM_OSS__ ) )\n  #include <sys/file.h>\n#endif /* Tandem */\n#include <sys/stat.h>\n#if defined( _AIX ) || defined( __alpha__ ) || defined( _MPRAS ) || \\\n\tdefined( __osf__ ) || defined( __SCO_VERSION__ )\n  #include <sys/mode.h>\n#endif /* Vaguely SYSV-ish systems */\n#include <unistd.h>\n#if defined( _AIX ) || defined( __alpha__ ) || defined( __BEOS__ ) || \\\n\tdefined( __bsdi__ ) || defined( _CRAY ) || defined( __FreeBSD__ ) || \\\n\tdefined( __iOS__ ) || defined( __linux__ ) || defined( _MPRAS ) || \\\n\tdefined( __MVS__ ) || defined( _M_XENIX ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __osf__ ) || defined( __QNX__ ) || \\\n\tdefined( __SCO_VERSION__ ) || defined( sun ) || \\\n\tdefined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n  #include <utime.h>\t\t\t/* It's a SYSV thing... */\n#endif /* SYSV Unixen */\n#if defined( __APPLE__ ) || defined( __linux__ )\n  #include <sys/time.h>\t\t\t/* For futimes() */\n#endif /* OS X || Linux */\n#ifdef __CYGWIN__\n  #include <sys/utime.h>\n#endif /* __CYGWIN__ */\n\n/* By default we try and use flock()-locking, if this isn't available we\n   fall back to fcntl() locking (see the long comment further on).  Actually\n   Slowaris does have flock() but there are lots of warnings in the manpage\n   about using it only on BSD platforms and it requires the BSD libraries to\n   work.  SunOS did support it without any problems, it's only the SVR4 \n   Slowaris that breaks it - the Solaris flock() is really just a \n   compatibility hack around fcntl() locking, even up to the very latest \n   versions (Solaris 10), and there are various weird side-effects and\n   problems that make it too dangerous to use.  In addition UnixWare \n   (== SCO) supports something called flockfile() but this only provides \n   thread-level locking that isn't useful */\n\n#if defined( _AIX ) || defined( __BEOS__ ) || defined( __CYGWIN__ ) || \\\n\tdefined( __hpux ) || defined( _MPRAS ) || defined( __MVS__ ) || \\\n\tdefined( _M_XENIX ) || defined( __SCO_VERSION__ ) || \\\n\t( defined( sun ) && ( OSVERSION >= 5 ) ) || \\\n\tdefined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n  #define USE_FCNTL_LOCKING\n#endif /* Some older SYSV-ish systems */\n\n/* Older versions of SCO didn't have ftruncate() but did have the equivalent\n   function chsize() */\n\n#if ( defined( _M_XENIX ) && ( OSVERSION == 3 ) )\n  #define ftruncate( a, b )\tchsize( a, b )\n#endif /* SCO */\n\n/* SunOS 4 doesn't have memmove(), but Solaris does, so we define memmove()\n   to bcopy() under 4.  In addition SunOS doesn't define the fseek()\n   position indicators so we define these as well */\n\n#if defined( __UNIX__ ) && defined( sun ) && ( OSVERSION == 4 )\n  #define memmove\t\t\t\tbcopy\n\n  #define SEEK_SET\t\t\t\t0\n  #define SEEK_CUR\t\t\t\t1\n  #define SEEK_END\t\t\t\t2\n#endif /* SunOS 4 */\n\n/* Some versions of Cygwin don't define the locking constants */\n\n#if defined( __CYGWIN__ ) && !defined( LOCK_SH )\n  #define LOCK_SH\t\t1\n  #define LOCK_EX\t\t2\n  #define LOCK_NB\t\t4\n  #define LOCK_UN\t\t8\n#endif /* Cygwin */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tVxWorks\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VxWorks__ )\n\n#include <vxWorks.h>\n#include <ioLib.h>\n#include <errno.h>\n#include <ioctl.h>\n#include <sys/stat.h>\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tXilinx XMK\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __XMK__ )\n\n#include <xilmfs.h>\n\n#endif /* OS-specific includes and defines */\n\n#endif /* _STRFILE_DEFINED */\n"
  },
  {
    "path": "deps/cl345/io/http.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib HTTP Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"http.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"io/http.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HTTP\n\n/* HTTP error/warning messages and equivalent cryptlib status codes.  This \n   mapping is somewhat problematic in that the HTTP-level status codes can \n   be overwritten/replaced by intermediaries like proxies and captive \n   portals, for example if an intermediate device is under heavy load or \n   thinks it's under attack then it can return a different HTTP status than \n   what the actual client or server sent.  In addition at the same time that \n   we're mapping HTTP status codes to approximate cryptlib codes, so the \n   remote system could be mapping its status codes to approximate HTTP ones.  \n   For this reason we map the HTTP codes to the most generic equivalents \n   possible, mostly CRYPT_ERROR_READ with an occasional \n   CRYPT_ERROR_PERMISSION when it's obviously that, e.g. a 403.\n\n   The mapped status for 30x redirects is somewhat special-case, see the \n   comment in readResponseHeader() for details.  \n   \n   This table also contains known non-HTTP codes in the expectation that, \n   when used as a general-purpose substrate, it'll be pressed into use in \n   all sorts of situations */\n\n#define HTTP_STATUSSTRING_LENGTH\t3\n\nstatic const HTTP_STATUS_INFO httpStatusInfo[] = {\n\t{ 100, \"100\", \"Continue\", 8, OK_SPECIAL },\n#ifdef USE_WEBSOCKETS\n\t{ 101, \"101\", \"Switching Protocols\", 19, OK_SPECIAL },\n#else\n\t{ 101, \"101\", \"Switching Protocols\", 19, CRYPT_ERROR_READ },\n#endif /* USE_WEBSOCKETS */\n\t{ 110, \"110\", \"Warning: Response is stale\", 26, CRYPT_OK },\n\t{ 111, \"111\", \"Warning: Revalidation failed\", 28, CRYPT_OK },\n\t{ 112, \"112\", \"Warning: Disconnected operation\", 31, CRYPT_OK },\n\t{ 113, \"113\", \"Warning: Heuristic expiration\", 29, CRYPT_OK },\n\t{ 199, \"199\", \"Warning: Miscellaneous warning\", 30, CRYPT_OK },\n\t{ 200, \"200\", \"OK\", 2, CRYPT_OK },\n\t{ 201, \"201\", \"Created\", 7, CRYPT_ERROR_READ },\n\t{ 202, \"202\", \"Accepted\", 8, CRYPT_ERROR_READ },\n\t{ 203, \"203\", \"Non-Authoritative Information\", 29, CRYPT_OK },\n\t{ 204, \"204\", \"No Content\", 10, CRYPT_ERROR_READ },\n\t{ 205, \"205\", \"Reset Content\", 13, CRYPT_ERROR_READ },\n\t{ 206, \"206\", \"Partial Content\", 15, CRYPT_ERROR_READ },\n\t{ 214, \"214\", \"Warning: Transformation applied\", 31, CRYPT_OK },\n\t{ 250, \"250\", \"RTSP: Low on Storage Space\", 26, CRYPT_OK },\n\t{ 299, \"299\", \"Warning: Miscellaneous persistent warning\", 41, CRYPT_OK },\n\t{ 300, \"300\", \"Multiple Choices\", 16, CRYPT_ERROR_READ },\n\t{ 301, \"301\", \"Moved Permanently\", 17, OK_SPECIAL },\n\t{ 302, \"302\", \"Moved Temporarily/Found\", 23, OK_SPECIAL },\n\t{ 303, \"303\", \"See Other\", 9, CRYPT_ERROR_READ },\n\t{ 304, \"304\", \"Not Modified\", 12, CRYPT_ERROR_READ },\n\t{ 305, \"305\", \"Use Proxy\", 9, CRYPT_ERROR_READ },\n\t{ 306, \"306\", \"Unused/obsolete\", 15, CRYPT_ERROR_READ },\n\t{ 307, \"307\", \"Temporary Redirect\", 18, OK_SPECIAL },\n\t{ 400, \"400\", \"Bad Request\", 11, CRYPT_ERROR_READ },\n\t{ 401, \"401\", \"Unauthorized\", 12, CRYPT_ERROR_PERMISSION },\n\t{ 402, \"402\", \"Payment Required\", 16, CRYPT_ERROR_READ },\n\t{ 403, \"403\", \"Forbidden\", 9, CRYPT_ERROR_PERMISSION },\n\t{ 404, \"404\", \"Not Found\", 9, CRYPT_ERROR_NOTFOUND },\n\t{ 405, \"405\", \"Method Not Allowed\", 18, CRYPT_ERROR_NOTAVAIL },\n\t{ 406, \"406\", \"Not Acceptable\", 14, CRYPT_ERROR_PERMISSION },\n\t{ 407, \"407\", \"Proxy Authentication Required\", 29, CRYPT_ERROR_PERMISSION },\n\t{ 408, \"408\", \"Request Time-out\", 16, CRYPT_ERROR_READ },\n\t{ 409, \"409\", \"Conflict\", 8, CRYPT_ERROR_READ },\n\t{ 410, \"410\", \"Gone\", 4, CRYPT_ERROR_NOTFOUND },\n\t{ 411, \"411\", \"Length Required\", 15, CRYPT_ERROR_READ },\n\t{ 412, \"412\", \"Precondition Failed\", 19, CRYPT_ERROR_READ },\n\t{ 413, \"413\", \"Request Entity too Large\", 24, CRYPT_ERROR_OVERFLOW },\n\t{ 414, \"414\", \"Request-URI too Large\", 21, CRYPT_ERROR_OVERFLOW },\n\t{ 415, \"415\", \"Unsupported Media Type\", 22, CRYPT_ERROR_READ },\n\t{ 416, \"416\", \"Requested range not satisfiable\", 31, CRYPT_ERROR_READ },\n\t{ 417, \"417\", \"Expectation Failed\", 18, CRYPT_ERROR_READ },\n\t{ 418, \"418\", \"I'm a teapot\", 12, CRYPT_ERROR_READ },\n\t{ 421, \"421\", \"Misdirected Request\", 19, CRYPT_ERROR_READ },\n\t{ 422, \"422\", \"Unprocessable Entity\", 20, CRYPT_ERROR_READ },\n\t{ 423, \"423\", \"Locked\", 6, CRYPT_ERROR_READ },\n\t{ 424, \"424\", \"Failed Dependency\", 17, CRYPT_ERROR_READ },\n\t{ 426, \"426\", \"Upgrade Required\", 16, CRYPT_ERROR_READ },\n\t{ 428, \"428\", \"Precondition Required\", 21, CRYPT_ERROR_READ },\n\t{ 429, \"429\", \"Too Many Requests\", 17, CRYPT_ERROR_OVERFLOW },\n\t{ 431, \"431\", \"Request Header Fields Too Large\", 31, CRYPT_ERROR_OVERFLOW },\n\t{ 444, \"444\", \"Connection Closed Without Response\", 34, CRYPT_ERROR_READ },\n\t{ 451, \"451\", \"RTSP: Parameter not Understood\", 30, CRYPT_ERROR_BADDATA },\n#if 0\t/* Also allegedly... */\n\t{ 451, \"451\", \"Unavailable For Legal Reasons\", 29, CRYPT_ERROR_READ },\n#endif /* 0 */\n\t{ 452, \"452\", \"RTSP: Conference not Found\", 26, CRYPT_ERROR_NOTFOUND },\n\t{ 453, \"453\", \"RTSP: Not enough Bandwidth\", 26, CRYPT_ERROR_NOTAVAIL },\n\t{ 454, \"454\", \"RTSP: Session not Found\", 23, CRYPT_ERROR_NOTFOUND },\n\t{ 455, \"455\", \"RTSP: Method not Valid in this State\", 36, CRYPT_ERROR_NOTAVAIL },\n\t{ 456, \"456\", \"RTSP: Header Field not Valid for Resource\", 41, CRYPT_ERROR_NOTAVAIL },\n\t{ 457, \"457\", \"RTSP: Invalid Range\", 19, CRYPT_ERROR_READ },\n\t{ 458, \"458\", \"RTSP: Parameter is Read-Only\", 28, CRYPT_ERROR_PERMISSION },\n\t{ 459, \"459\", \"RTSP: Aggregate Operation not Allowed\", 37, CRYPT_ERROR_PERMISSION },\n\t{ 460, \"460\", \"RTSP: Only Aggregate Operation Allowed\", 38, CRYPT_ERROR_PERMISSION },\n\t{ 461, \"461\", \"RTSP: Unsupported Transport\", 27, CRYPT_ERROR_NOTAVAIL },\n\t{ 462, \"462\", \"RTSP: Destination Unreachable\", 29, CRYPT_ERROR_OPEN },\n\t{ 499, \"499\", \"Client Closed Request\", 21, CRYPT_ERROR_READ },\n\t{ 500, \"500\", \"Internal Server Error\", 21, CRYPT_ERROR_READ },\n\t{ 501, \"501\", \"Not Implemented\", 15, CRYPT_ERROR_NOTAVAIL },\n\t{ 502, \"502\", \"Bad Gateway\", 11, CRYPT_ERROR_READ },\n\t{ 503, \"503\", \"Service Unavailable\", 19, CRYPT_ERROR_NOTAVAIL },\n\t{ 504, \"504\", \"Gateway Time-out\", 16, CRYPT_ERROR_TIMEOUT },\n\t{ 505, \"505\", \"HTTP Version not supported\", 26, CRYPT_ERROR_READ },\n\t{ 510, \"510\", \"HTTP-Ext: Not Extended\", 22, CRYPT_ERROR_READ },\n\t{ 551, \"551\", \"RTSP: Option not supported\", 26, CRYPT_ERROR_READ },\n\t{ 0, NULL, \"Unrecognised HTTP status condition\", 34, CRYPT_ERROR_READ },\n\t\t{ 0, NULL, \"Unrecognised HTTP status condition\", 34, CRYPT_ERROR_READ }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check HTTP data info */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckHttpDataInfo( const HTTP_DATA_INFO *httpDataInfo )\n\t{\n\tassert( isReadPtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );\n\n\t/* Check HTTP data information */\n\tif( httpDataInfo->buffer == NULL )\n\t\t{\n\t\tif( httpDataInfo->bufSize != 0 || \\\n\t\t\thttpDataInfo->bytesToWrite != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Spurious data info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( httpDataInfo->bufSize < MIN_LINEBUF_SIZE || \\\n\t\t\thttpDataInfo->bufSize > MAX_BUFFER_SIZE || \\\n\t\t\t!safeBufferCheck( httpDataInfo->buffer, httpDataInfo->bufSize ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Data buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( httpDataInfo->bytesToWrite < 0 || \\\n\t\thttpDataInfo->bytesToWrite > httpDataInfo->bufSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Data buffer write variables\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( httpDataInfo->bytesAvail < 0 || \\\n\t\thttpDataInfo->bytesAvail > httpDataInfo->bufSize || \\\n\t\thttpDataInfo->bytesTransferred < 0 || \\\n\t\thttpDataInfo->bytesTransferred > httpDataInfo->bufSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Data buffer read variables\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( httpDataInfo->contentType != NULL )\n\t\t{\n\t\tif( httpDataInfo->contentTypeLen < 1 || \\\n\t\t\thttpDataInfo->contentTypeLen > CRYPT_MAX_TEXTSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Content type info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( httpDataInfo->contentTypeLen != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Spurious content type length\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check HTTP control variables */\n\tif( ( httpDataInfo->bufferResize != TRUE && \\\n\t\t  httpDataInfo->bufferResize != FALSE ) || \\\n\t\t( httpDataInfo->responseIsText != TRUE && \\\n\t\t  httpDataInfo->responseIsText != FALSE ) || \\\n\t\thttpDataInfo->reqType < STREAM_HTTPREQTYPE_NONE || \\\n\t\thttpDataInfo->reqType >= STREAM_HTTPREQTYPE_LAST )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: HTTP control variables\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( httpDataInfo->reqStatus ) )\n\t\t{\n\t\t/* If we're sending an error response then there can't also be data \n\t\t   present */\n\t\tif( httpDataInfo->bytesToWrite != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Spurious data for error response\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( httpDataInfo->reqStatus != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Request status\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( httpDataInfo->reqInfo != NULL && \\\n\t\thttpDataInfo->uriInfo != NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckHttpDataInfo: Spurious req/URI info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Initialise HTTP data info.  This is a rather complex function because it \n   has to handle reads and writes.  On read we use { buffer, bufSize } to\n   read into.  On write we also use { buffer, bufSize } as our write buffer \n   but only write dataLength bytes from that.  In addition on read we fill\n   the uriInfo with the peer's URI information, and on write we set the\n   request information (URI and other details) from the reqInfo */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initHttpInfo( INOUT HTTP_DATA_INFO *httpDataInfo, \n\t\t\t\t  OUT_BUFFER_OPT_FIXED( bufSize ) void *buffer, \n\t\t\t\t  IN_LENGTH_Z const int bufSize,\n\t\t\t\t  IN_LENGTH_Z const int dataLength,\n\t\t\t\t  IN_OPT const HTTP_REQ_INFO *reqInfo,\n\t\t\t\t  OUT_OPT HTTP_URI_INFO *uriInfo )\n\t{\n\tassert( isWritePtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );\n\tassert( buffer == NULL || isWritePtr( buffer, bufSize ) );\n\tassert( reqInfo == NULL || isReadPtr( reqInfo, sizeof( HTTP_REQ_INFO ) ) );\n\tassert( uriInfo == NULL || isReadPtr( uriInfo, sizeof( HTTP_URI_INFO ) ) );\n\n\tREQUIRES( dataLength >= 0 && dataLength < MAX_BUFFER_SIZE && \\\n\t\t\t  dataLength <= bufSize );\n\tREQUIRES( ( buffer == NULL && bufSize == 0 && dataLength == 0 ) || \\\n\t\t\t  ( buffer != NULL && \\\n\t\t\t\tbufSize >= MIN_LINEBUF_SIZE && bufSize < MAX_BUFFER_SIZE && \\\n\t\t\t\tsafeBufferCheck( buffer, bufSize ) ) );\n\tREQUIRES( reqInfo == NULL || uriInfo == NULL );\n\n\tmemset( httpDataInfo, 0, sizeof( HTTP_DATA_INFO ) );\n\thttpDataInfo->buffer = buffer;\n\thttpDataInfo->bufSize = bufSize;\n\thttpDataInfo->bytesToWrite = dataLength;\n\thttpDataInfo->reqInfo = reqInfo;\n\tif( uriInfo != NULL )\n\t\t{\n\t\tmemset( uriInfo, 0, sizeof( HTTP_URI_INFO ) );\n\t\thttpDataInfo->uriInfo = uriInfo;\n\t\t}\n\n\tENSURES( sanityCheckHttpDataInfo( httpDataInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return the HTTP_STATUS_INFO that corresponds to a given HTTP status \n   code */\n\nCHECK_RETVAL_PTR \\\nconst HTTP_STATUS_INFO *getHTTPStatusInfo( IN_INT const int httpStatus )\n\t{\n\tstatic const HTTP_STATUS_INFO defaultStatusInfo = \\\n\t\t{ 400, \"400\", \"Bad Request\", 11, CRYPT_ERROR_READ };\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( httpStatus >= MIN_HTTP_STATUS && \\\n\t\t\t\thttpStatus < MAX_HTTP_STATUS );\n\n\t/* Find the HTTP error string that corresponds to the HTTP status\n\t   value */\n\tLOOP_LARGE( i = 0, httpStatusInfo[ i ].httpStatus > 0 && \\\n\t\t\t\t\t   httpStatusInfo[ i ].httpStatus != httpStatus && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( httpStatusInfo, HTTP_STATUS_INFO ),\n\t\t\t  i++ );\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( httpStatusInfo, HTTP_STATUS_INFO ) );\n\tif( httpStatusInfo[ i ].httpStatus > 0 )\n\t\treturn( &httpStatusInfo[ i ] );\n\n\t/* We couldn't find any matching status information, return the default \n\t   status */\n\treturn( &defaultStatusInfo );\n\t}\n\n/* Check an \"HTTP 1.x\" ID string.  No PKI client should be sending us a 0.9\n   ID, so we only allow 1.x */\n\nCHECK_RETVAL_RANGE( 0, 8 ) STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkHTTPID( IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t INOUT STREAM *stream )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tif( dataLength < 8 || strCompare( data, \"HTTP/1.\", 7 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( data[ 7 ] == '0' )\n\t\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_HTTP10 );\n\telse\n\t\t{\n\t\tif( data[ 7 ] != '1' )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\treturn( 8 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tError Handling Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit with extended error information after a readTextLine() call */\n\nSTDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint retTextLineError( INOUT STREAM *stream, \n\t\t\t\t\t  IN_ERROR const int status, \n\t\t\t\t\t  const BOOLEAN isTextLineError, \n\t\t\t\t\t  FORMAT_STRING const char *format, \n\t\t\t\t\t  const int value )\n\t{\n#ifdef USE_ERRMSGS\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n#endif /* USE_ERRMSGS */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( cryptStatusError( status ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tREQUIRES( isTextLineError == TRUE || isTextLineError == FALSE );\n#ifdef USE_ERRMSGS\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n#endif /* USE_ERRMSGS */\n\n\t/* If the extended error information came up from a lower level than \n\t   readCharFunction(), pass it on up to the caller */\n\tif( !isTextLineError )\n\t\treturn( status );\n\n\t/* Extend the readTextLine()-level error information with higher-level\n\t   detail.  This allows us to provide a more useful error report \n\t   (\"Problem with line x\") than just the rather low-level view provided \n\t   by readTextLine() (\"Invalid character 0x8F at position 12\").  The\n\t   argument handling is:\n\n\t\tprintf( format, value ) || printf( stream->errorInfo->errorString );\n\n\t   so that 'format' has the form 'High-level error %d: \", to which the\n\t   low-level string is then appended */\n\tretExtErr( status, \n\t\t\t   ( status, NETSTREAM_ERRINFO, NETSTREAM_ERRINFO, \n\t\t\t     format, value ) );\n\t}\n\n/* Send an HTTP error message.  This function is somewhat unusually placed\n   with the general HTTP parsing functions because it's used by both read \n   and write code but needs access to the HTTP status decoding table, which \n   is part of the parsing code */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendHTTPError( INOUT STREAM *stream, \n   \t\t\t\t   OUT_BUFFER_FIXED( headerBufMaxLen ) char *headerBuffer, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\tconst int headerBufMaxLen, \n\t\t\t\t   IN_INT const int httpStatus )\n\t{\n\tconst NET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tconst HTTP_STATUS_INFO *httpStatusInfoPtr;\n\tSTREAM headerStream;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( headerBuffer, headerBufMaxLen ) );\n\n\tREQUIRES( headerBufMaxLen >= MIN_LINEBUF_SIZE && \\\n\t\t\t  headerBufMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( httpStatus >= 0 && httpStatus < 600 );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t/* Find the HTTP error information that corresponds to the HTTP status\n\t   value */\n\thttpStatusInfoPtr = getHTTPStatusInfo( httpStatus );\n\tREQUIRES( httpStatusInfoPtr != NULL );\n\n\t/* Send the error message to the peer */\n\tsMemOpen( &headerStream, headerBuffer, headerBufMaxLen );\n\tswrite( &headerStream, isHTTP10( netStream ) ? \\\n\t\t\t\"HTTP/1.0 \" : \"HTTP/1.1 \", 9 );\n\tswrite( &headerStream, httpStatusInfoPtr->httpStatusString, \n\t\t\tHTTP_STATUSSTRING_LENGTH );\n\tsputc( &headerStream, ' ' );\n\tswrite( &headerStream, httpStatusInfoPtr->httpErrorString, \n\t\t\thttpStatusInfoPtr->httpErrorStringLength );\n\tswrite( &headerStream, \"\\r\\n\", 2 );\n\tif( httpStatus == 501 )\n\t\t{\n\t\t/* Since the assumption on the web is that anything listening for\n\t\t   HTTP requests is a conventional web server, we provide a bit more\n\t\t   information to (probable) browsers that connect and send a GET\n\t\t   request.  This is also useful for some browsers that hang around\n\t\t   forever waiting for content if they don't see anything following\n\t\t   the HTTP error status */\n\t\tswrite( &headerStream, \"Content-Length: 139\\r\\n\\r\\n\", 23 );\n\t\tswrite( &headerStream,\n\t\t\t\t\"<html><head><title>Invalid PKI Server Request</title></head>\"\n\t\t\t\t\"<body>This is a PKI messaging service, not a standard web \"\n\t\t\t\t\"server.</body></html>\", 139 );\n\t\t}\n\tstatus = swrite( &headerStream, \"\\r\\n\", 2 );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &headerStream );\n\tsMemDisconnect( &headerStream );\n\tENSURES( cryptStatusOK( status ) );\n\treturn( sendHTTPData( stream, headerBuffer, length,\n\t\t\t\t\t\t  TRANSPORT_FLAG_FLUSH ) );\n\t}\n#endif /* USE_HTTP */\n"
  },
  {
    "path": "deps/cl345/io/http.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib HTTP Interface Header\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _HTTP_DEFINED\n\n#define _HTTP_DEFINED\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tHTTP Constants and Data Structures\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of the HTTP text-line buffer when we're using a dedicated buffer\n   to read header lines rather than the main stream buffer, and the minimum \n   size that we'll accept in functions that use the line buffer.  Any data\n   that goes past HTTP_LINEBUF_SIZE is dropped */\n\n#define MIN_LINEBUF_SIZE\t512\n#define HTTP_LINEBUF_SIZE\t1024\n\n/* A macro to determine whether we're talking HTTP 1.0 or 1.1 */\n\n#define isHTTP10( netStream )\t( TEST_FLAG( ( netStream )->nhFlags, \\\n\t\t\t\t\t\t\t\t\t\t\t STREAM_NHFLAG_HTTP10 ) )\n\n/* HTTP state information passed around the various read/write functions */\n\n#define HTTP_FLAG_NONE\t\t0x00\t/* No HTTP info */\n#define HTTP_FLAG_CHUNKED\t0x01\t/* Message used chunked encoding */\n#define HTTP_FLAG_TRAILER\t0x02\t/* Chunked encoding has trailer */\n#define HTTP_FLAG_NOOP\t\t0x04\t/* No-op data (e.g. 100 Continue) */\n#define HTTP_FLAG_TEXTMSG\t0x08\t/* HTTP content is plain text, probably\n\t\t\t\t\t\t\t\t\t   an error message */\n#define HTTP_FLAG_GET\t\t0x10\t/* Operation is HTTP GET */\n#define HTTP_FLAG_UPGRADE\t0x20\t/* Operation is HTTP Upgrade */\n#define HTTP_FLAG_MAX\t\t0x3F\t/* Maximum possible flag value */\n\n/* The minimum and maximum HTTP status values */\n\n#define MIN_HTTP_STATUS\t\t0\n#define MAX_HTTP_STATUS\t\t600\n\n/* HTTP header parsing information as used by readHeaderLines() */\n\ntypedef struct {\n\t/* Returned status information: The body content-length, the HTTP error\n\t   status (if there is one), and general flags information.  The flags\n\t   parameter is used as both an input and an output parameter */\n\tint contentLength;\t/* HTTP body content length */\n\tint httpStatus;\t\t/* HTTP error status, if an HTTP error occurs */\n\tSAFE_FLAGS flags;\t/* General flags */\n\n\t/* Type-specific returned information: The WebSockets subprotocol and\n\t   key/response data */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, wsProtocolLen ) \\\n\tBYTE wsProtocol[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, wsAuthLen ) \\\n\tBYTE wsAuth[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint wsProtocolLen, wsAuthLen;\n\n\t/* Range-checking information: The minimum and maximum allowable\n\t   content-length value */\n\tint minContentLength, maxContentLength;\n\t} HTTP_HEADER_INFO;\n\n#define initHeaderInfo( headerInfo, minLength, maxLength, hdrFlags ) \\\n\t\tmemset( headerInfo, 0, sizeof( HTTP_HEADER_INFO ) ); \\\n\t\tINIT_FLAGS( ( headerInfo )->flags, ( hdrFlags ) ); \\\n\t\t( headerInfo )->minContentLength = ( minLength ); \\\n\t\t( headerInfo )->maxContentLength = ( maxLength );\n\n/* HTTP status information as used by getHTTPStatusInfo() */\n\ntypedef struct {\n\tconst int httpStatus;\t\t\t/* Numeric status value */\n\tBUFFER_FIXED( HTTP_STATUSSTRING_LENGTH ) \\\n\tconst char *httpStatusString;\t/* String status value */\n\tBUFFER_FIXED( httpErrorStringLength ) \\\n\tconst char *httpErrorString;\t/* Text description of status */\n\tconst int httpErrorStringLength;\n\tconst int status;\t\t\t\t/* Equivalent cryptlib status */\n\t} HTTP_STATUS_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Function Prototypes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in http.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckHttpDataInfo( const HTTP_DATA_INFO *httpDataInfo );\nCHECK_RETVAL_PTR \\\nconst HTTP_STATUS_INFO *getHTTPStatusInfo( IN_INT const int httpStatus );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendHTTPError( INOUT STREAM *stream, \n\t\t\t\t   OUT_BUFFER_FIXED( headerBufMaxLen ) char *headerBuffer, \n\t\t\t\t   IN_LENGTH_SHORT_MIN( 256 ) const int headerBufMaxLen, \n\t\t\t\t   IN_INT const int httpStatus );\nCHECK_RETVAL_RANGE( 0, 8 ) STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint checkHTTPID( IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t INOUT STREAM *stream );\n\n/* Prototypes for functions in http_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRequestHeader( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_OPT const HTTP_REQ_INFO *httpReqInfo,\n\t\t\t\t\t\tIN_BUFFER_OPT( contentTypeLen ) const char *contentType, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int contentTypeLen, \n\t\t\t\t\t\tIN_LENGTH_Z const int contentLength,\n\t\t\t\t\t\tconst BOOLEAN forceGet );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendHTTPData( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( length ) void *buffer, \n\t\t\t\t  IN_LENGTH const int length, \n\t\t\t\t  IN_FLAGS_Z( HTTP ) const int flags );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerHTTPwrite( INOUT NET_STREAM_INFO *netStream );\n\n/* Prototypes for functions in http_parse.c.  Most of these functions don't \n   actually return anything in the buffer that's passed in but merely use it \n   as general scratch buffer to save having to give each function its own\n   (sizeable) scratch buffer */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint parseUriInfo( INOUT_BUFFER( dataInLength, *dataOutLength ) char *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataInLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataInLength ) int *dataOutLength, \n\t\t\t\t  INOUT HTTP_URI_INFO *uriInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readFirstHeaderLine( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_BUFFER_FIXED( dataMaxLength ) char *dataBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t\t OUT_RANGE( 0, 999 ) int *httpStatus,\n\t\t\t\t\t\t OUT_BOOL BOOLEAN *isSoftError );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readHeaderLines( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER_FIXED( lineBufMaxLen ) char *lineBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 256 ) const int lineBufMaxLen,\n\t\t\t\t\t INOUT HTTP_HEADER_INFO *headerInfo,\n\t\t\t\t\t OUT_BOOL BOOLEAN *isSoftError );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readTrailerLines( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_BUFFER_FIXED( lineBufMaxLen ) char *lineBuffer, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 256 ) const int lineBufMaxLen );\nSTDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint retTextLineError( INOUT STREAM *stream, IN_ERROR const int status, \n\t\t\t\t\t  const BOOLEAN isTextLineError, \n\t\t\t\t\t  FORMAT_STRING const char *format, \n\t\t\t\t\t  const int value );\n\n#endif /* _HTTP_DEFINED */\n"
  },
  {
    "path": "deps/cl345/io/http_parse.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib HTTP Parsing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"http.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"io/http.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HTTP\n\n/* The various HTTP header types that we can process */\n\ntypedef enum { HTTP_HEADER_NONE, HTTP_HEADER_HOST, HTTP_HEADER_CONTENT_LENGTH,\n\t\t\t   HTTP_HEADER_CONTENT_TYPE, HTTP_HEADER_TRANSFER_ENCODING,\n\t\t\t   HTTP_HEADER_CONTENT_ENCODING,\n\t\t\t   HTTP_HEADER_CONTENT_TRANSFER_ENCODING, HTTP_HEADER_SERVER,\n\t\t\t   HTTP_HEADER_TRAILER, HTTP_HEADER_CONNECTION, \n\t\t\t   HTTP_HEADER_WARNING, HTTP_HEADER_LOCATION, HTTP_HEADER_EXPECT, \n#ifdef USE_WEBSOCKETS\n\t\t\t   HTTP_HEADER_UPGRADE, HTTP_HEADER_WS_PROTOCOL, \n\t\t\t   HTTP_HEADER_WS_VERSION, HTTP_HEADER_WS_KEY, \n\t\t\t   HTTP_HEADER_WS_RESPONSE, \n#endif /* USE_WEBSOCKETS */\n\t\t\t   HTTP_HEADER_LAST\n\t\t\t } HTTP_HEADER_TYPE;\n\n/* HTTP header parsing information.  Note that the first letter of the\n   header string must be uppercase for the case-insensitive quick match */\n\ntypedef struct {\n\tBUFFER_FIXED( headerStringLen ) \\\n\tconst char *headerString;\t\t/* Header string */\n\tconst int headerStringLen;\t\t/* Length of header string */\n\tconst HTTP_HEADER_TYPE headerType;\t/* Type corresponding to header string */\n\t} HTTP_HEADER_PARSE_INFO;\n\nstatic const HTTP_HEADER_PARSE_INFO httpHeaderParseInfo[] = {\n\t{ \"Host:\", 5, HTTP_HEADER_HOST },\n\t{ \"Content-Length:\", 15, HTTP_HEADER_CONTENT_LENGTH },\n\t{ \"Content-Type:\", 13, HTTP_HEADER_CONTENT_TYPE },\n\t{ \"Transfer-Encoding:\", 18, HTTP_HEADER_TRANSFER_ENCODING },\n\t{ \"Content-Encoding:\", 17, HTTP_HEADER_CONTENT_ENCODING },\n\t{ \"Content-Transfer-Encoding:\", 26, HTTP_HEADER_CONTENT_TRANSFER_ENCODING },\n\t{ \"Server:\", 7, HTTP_HEADER_SERVER },\n\t{ \"Trailer:\", 8, HTTP_HEADER_TRAILER },\n\t{ \"Connection:\", 11, HTTP_HEADER_CONNECTION },\n\t{ \"NnCoection:\", 11, HTTP_HEADER_CONNECTION },\n\t{ \"Cneonction:\", 11, HTTP_HEADER_CONNECTION },\n\t\t/* The bizarre spellings are for NetApp NetCache servers, which \n\t\t   unfortunately are widespread enough that we need to provide \n\t\t   special-case handling for them.  For the second mis-spelling we\n\t\t   have to capitalise the first letter for our use since we compare\n\t\t   the uppercase form for a quick match.\n\n\t\t   The reason why NetApp devices do this is because they think that \n\t\t   they can manage connections better than the application that's \n\t\t   creating them, so they rewrite \"Connection: close\" into something\n\t\t   that won't be recognised in order to avoid the connection \n\t\t   actually being closed.  The reason for the 16-bit swap is because\n\t\t   the TCP/IP checksum doesn't detect 16-bit word swaps, so this \n\t\t   allows the connection-control to be invalidated without requiring \n\t\t   a recalculation of the TCP checksum.  \n\t\t   \n\t\t   Someone probably got bonus pay for coming up with this */\n\t{ \"Warning:\", 8, HTTP_HEADER_WARNING },\n\t{ \"Location:\", 9, HTTP_HEADER_LOCATION },\n\t{ \"Expect:\", 7, HTTP_HEADER_EXPECT },\n#ifdef USE_WEBSOCKETS\n\t{ \"Upgrade:\", 8, HTTP_HEADER_UPGRADE },\n\t{ \"Sec-WebSocket-Protocol:\", 23, HTTP_HEADER_WS_PROTOCOL },\n\t{ \"Sec-WebSocket-Version:\", 22, HTTP_HEADER_WS_VERSION },\n\t{ \"Sec-WebSocket-Key:\", 18, HTTP_HEADER_WS_KEY },\n\t{ \"Sec-WebSocket-Accept:\", 21, HTTP_HEADER_WS_RESPONSE },\n#endif /* USE_WEBSOCKETS */\n\t{ NULL, 0, HTTP_HEADER_NONE }, { NULL, 0, HTTP_HEADER_NONE }\n\t};\n\n/* Table used to fingerprint the peer system, used to detect buggy peer\n   applications.  Note that this mechanism isn't totally reliable, for \n   example the presence of IIS can be masked using either Microsoft tools\n   like the URLScan ISAPI filter or commercial tools like ServerMask, but\n   this is really just an opportunistic check that does the best that it \n   can.\n   \n   In addition since different generations of Windows Server have different\n   types of bugs, we detect sub-versions and report more specific \n   indications of what we've encountered in preference to the generic \"it's\n   IIS\" */\n\ntypedef struct {\n\tconst char *idString;\t\t\t/* String used to ID the system */\n\tconst int idStringLen;\n\tconst STREAM_PEER_TYPE systemType;\t/* System type */\n\t} SYSTEM_ID_INFO;\n\nstatic const SYSTEM_ID_INFO systemIdInfo[] = {\n\t{ \"Microsoft-IIS/8\", 15, STREAM_PEER_MICROSOFT_2012 },\n\t{ \"Microsoft-IIS/7\", 15, STREAM_PEER_MICROSOFT_2008 },\n\t{ \"Microsoft-IIS/\", 14, STREAM_PEER_MICROSOFT },\n\t{ \"Microsoft-HTTPAPI\", 17, STREAM_PEER_MICROSOFT },\n\t\t/* This can be returned if the HTTP.SYS driver handles the request\n\t\t   before it gets to IIS, for example for a 400 status.  This isn't\n\t\t   such a big deal because if we're not getting to IIS then we\n\t\t   don't care about its bugs, but we check for it anyway for\n\t\t   consistencies' sake */\n\t{ NULL, 0, STREAM_PEER_NONE },\n\t\t{ NULL, 0, STREAM_PEER_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Callback function used by readTextLine() to read characters from a\n   stream.  When reading text data over a network we don't know how much\n   more data is to come so we have to read a byte at a time looking for an\n   EOL.  In addition we can't use the simple optimisation of reading two\n   bytes at a time because some servers only send a LF even though the spec\n   requires a CRLF.  This is horribly inefficient but is pretty much\n   eliminated through the use of opportunistic read-ahead buffering */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE ch;\n\tint length, status;\n\n\tassert( isWritePtr( streamPtr, sizeof( STREAM ) ) );\n\n\tstatus = bufferedTransportRead( stream, &ch, 1, &length, \n\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_NONE );\n\treturn( cryptStatusError( status ) ? status : ch );\n\t}\n\n/* Decode an escaped character */\n\nCHECK_RETVAL_RANGE( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getEncodedChar( IN_BUFFER( bufSize ) const char *buffer, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int bufSize )\n\t{\n\tint ch, status;\n\n\tassert( isReadPtrDynamic( buffer, bufSize ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( bufSize ) );\n\n\t/* Make sure that there's enough data left to decode the character */\n\tif( bufSize < 2 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Recreate the original character from the hex value */\n\tstatus = strGetHex( buffer, 2, &ch, 0, 0xFF );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a special-case/control character of some kind, report it as \n\t   an error.  This gets rid of things like nulls (treated as string \n\t   terminators by some functions) and CR/LF line terminators, which can \n\t   be embedded into strings to turn a single line of supplied text into \n\t   multi-line responses containing user-controlled type : value pairs \n\t   (in other words they allow user data to be injected into the control\n\t   channel) */\n\tif( !isValidTextChar( ch ) || ch <= 0x1F )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( ch );\n\t}\n\n/* Decode a string as per RFC 1866 */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int decodeRFC1866( IN_BUFFER( bufSize ) char *buffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int bufSize )\n\t{\n\tint srcIndex, destIndex = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( buffer, bufSize ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( bufSize ) );\n\n\tLOOP_MAX_INITCHECK( srcIndex = 0, srcIndex < bufSize )\n\t\t{\n\t\tint ch = byteToInt( buffer[ srcIndex++ ] );\n\n\t\t/* If it's an escaped character, decode it.  If it's not escaped \n\t\t   then we can copy it straight over, the input has already been \n\t\t   sanitised when it was read so there's no need to perform another \n\t\t   check here */\n\t\tif( ch == '%' )\n\t\t\t{\n\t\t\tconst int bytesLeft = bufSize - srcIndex;\n\t\t\tint status;\n\n\t\t\tif( bytesLeft <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tstatus = ch = getEncodedChar( buffer + srcIndex, bytesLeft );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsrcIndex += 2;\n\t\t\t}\n\t\tbuffer[ destIndex++ ] = intToByte( ch );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we've processed an escape sequence (causing the data to change\n\t   size), tell the caller the new length, otherwise tell them that\n\t   nothing's changed */\n\treturn( ( destIndex < srcIndex ) ? destIndex : OK_SPECIAL );\n\t}\n\n/* Convert a hex ASCII string used with chunked encoding into a numeric\n   value (\"It's extra chunky\" / \"What's in it?\" / \"Chunks\") */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getChunkLength( IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tint i, chunkLength = 0, length = dataLength, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Chunk size information can have extensions tacked onto it following a\n\t   ';', strip these before we start */\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\t{\n\t\tif( data[ i ] == ';' )\n\t\t\t{\n\t\t\tint LOOP_ITERATOR_ALT;\n\n\t\t\t/* Move back to the end of the string that precedes the ';' */\n\t\t\tLOOP_MAX_CHECKINC_ALT( i > 0 && data[ i - 1 ] == ' ', i-- );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tlength = i;\t/* Adjust length and force loop exit */\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( !isShortIntegerRangeNZ( length ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the chunk length */\n\tstatus = strGetHex( data, length, &chunkLength, 0, 0xFFFF );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( chunkLength );\n\t}\n\n/* Exit with extended error information relating to header-line parsing */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int retHeaderError( INOUT STREAM *stream, \n\t\t\t\t\t\t   FORMAT_STRING const char *format, \n\t\t\t\t\t\t   IN_BUFFER( strArgLen ) char *strArg, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int strArgLen, \n\t\t\t\t\t\t   const int lineNo )\n\t{\n#ifdef USE_ERRMSGS\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tBYTE argBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\tconst int argBufPos = min( strArgLen, CRYPT_MAX_TEXTSIZE );\n#endif /* USE_ERRMSGS */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\tassert( isWritePtrDynamic( strArg, strArgLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strArgLen ) );\n#ifdef USE_ERRMSGS\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tREQUIRES( rangeCheck( argBufPos, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( argBuffer, strArg, argBufPos ); \n#endif /* USE_ERRMSGS */\n\n\t/* Format the error information.  We add one to the argument length to \n\t   accommodate the trailing '\\0', and two to the line number since it's \n\t   zero-based and the header counts as an extra line */\n\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, format,\n\t\t\t  sanitiseString( argBuffer, argBufPos + 1, argBufPos ),\n\t\t\t  lineNo + 2 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tURI Parsing Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Information needed to parse a URI sub-segment: The character that ends a\n   segment and an optional alternative segment-end character, the minimum \n   and maximum permitted segment size, and a value to indicate how many more\n   characters of data must be available after the current URI segment is \n   consumed.  The alternative segment-end character is used for strings \n   like:\n\n\ttype-info [; more-info]\n\n   where optional additional information may follow the value that we're\n   interested in, separated by a delimiter.  The formatting of the parse\n   info is one of:\n\n\tendChar\taltEndChar\tMatches\n\t-------\t----------\t------------------\n\t\tx\t\t\\0\t\t....x.... (Case 1)\n\t\tx\t\ty\t\t....x....\n\t\t\t\t\t\t....y....\n\t\t\\0\t\ty\t\t....\t  (Case 2)\n\t\t\t\t\t\t....y.... */\n\ntypedef struct {\n\tconst char segmentEndChar, altSegmentEndChar;\n\tconst int segmentMinLength, segmentMaxLength;\n\tconst int dataToFollow;\n\t} URI_PARSE_INFO;\n\n/* Get the length of a sub-segment of a URI */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int getUriSegmentLength( IN_BUFFER( dataMaxLength ) const char *data, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t\t\tconst URI_PARSE_INFO *uriParseInfo,\n\t\t\t\t\t\t\t\tOUT_OPT_BOOL BOOLEAN *altDelimiterFound )\n\t{\n\tconst int maxLength = min( dataMaxLength, uriParseInfo->segmentMaxLength );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\tassert( isReadPtr( uriParseInfo, sizeof( URI_PARSE_INFO  ) ) );\n\tassert( ( uriParseInfo->altSegmentEndChar == '\\0' && \\\n\t\t\t  altDelimiterFound == NULL ) || \\\n\t\t\t( uriParseInfo->altSegmentEndChar > '\\0' && \\\n\t\t\t  isWritePtr( altDelimiterFound, sizeof( BOOLEAN ) ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxLength ) );\n\tREQUIRES( uriParseInfo->segmentMinLength >= 0 && \\\n\t\t\t  uriParseInfo->segmentMinLength < \\\n\t\t\t\t\turiParseInfo->segmentMaxLength && \\\n\t\t\t  uriParseInfo->segmentMaxLength <= 1024 );\n\tREQUIRES( ( uriParseInfo->altSegmentEndChar == '\\0' && \\\n\t\t\t\taltDelimiterFound == NULL ) || \\\n\t\t\t  ( uriParseInfo->altSegmentEndChar > '\\0' && \\\n\t\t\t\taltDelimiterFound != NULL ) );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\tif( altDelimiterFound != NULL )\n\t\t*altDelimiterFound = FALSE;\n\n\t/* Parse the current query sub-segment */\n\tLOOP_MAX( i = 0, i < maxLength, i++ )\n\t\t{\n\t\tif( data[ i ] == uriParseInfo->segmentEndChar )\n\t\t\tbreak;\n\t\tif( uriParseInfo->altSegmentEndChar > '\\0' && \\\n\t\t\tdata[ i ] == uriParseInfo->altSegmentEndChar )\n\t\t\t{\n\t\t\t*altDelimiterFound = TRUE;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If there's an end-char specified (Case 1) and we didn't find it (or \n\t   the alternative end-char if there is one), it's an error.  If there's\n\t   no end-char specified (Case 2), the end of the sub-segment is at the\n\t   end of the data */\n\tif( uriParseInfo->segmentEndChar != '\\0' && i >= dataMaxLength )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Make sure that we both got enough data and that we didn't run out of\n\t   data */\n\tif( i < uriParseInfo->segmentMinLength || \\\n\t\ti >= uriParseInfo->segmentMaxLength )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Finally, if we're expecting further data to follow the current URI \n\t   segment, make sure that it's present */\n\tif( dataMaxLength - i < uriParseInfo->dataToFollow )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t*dataLength = i;\n\treturn( CRYPT_OK );\n\t}\n\n/* Parse a URI of the form \"* '?' attribute '=' value [ '&' ... ] ' ' \",\n   returning the parsed form to the caller (there's always a space at the\n   end because it's followed by the HTTP ID string).  This function needs to \n   return two length values since it decodes the URI string according to RFC \n   1866, which means that its length can change.  So as its standard return \n   value it returns the number of chars consumed, but it also returns the \n   new length of the input as a by-reference parameter */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint parseUriInfo( INOUT_BUFFER( dataInLength, *dataOutLength ) char *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataInLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataInLength ) int *dataOutLength, \n\t\t\t\t  INOUT HTTP_URI_INFO *uriInfo )\n\t{\n\tstatic const URI_PARSE_INFO locationParseInfo = \\\n\t\t\t{ '?', '\\0', 1, CRYPT_MAX_TEXTSIZE, 2 };\n\tstatic const URI_PARSE_INFO attributeParseInfo = \\\n\t\t\t{ '=', '\\0', 3, CRYPT_MAX_TEXTSIZE, 2 };\n\tstatic const URI_PARSE_INFO valueParseInfo = \\\n\t\t\t{ ' ', '&', 3, CRYPT_MAX_TEXTSIZE, 2 };\n\tstatic const URI_PARSE_INFO extraParseInfo = \\\n\t\t\t{ ' ', '\\0', 1, CRYPT_MAX_TEXTSIZE, 2 };\n\tBOOLEAN altDelimiterFound;\n\tconst char *bufPtr = data;\n\tint length = dataInLength, segmentLength, parsedLength, i;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( data, dataInLength ) );\n\tassert( isWritePtr( dataOutLength, sizeof( int ) ) );\n\tassert( isWritePtr( uriInfo, sizeof( HTTP_URI_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataInLength ) );\n\n\t/* Clear return values */\n\tmemset( uriInfo, 0, sizeof( HTTP_URI_INFO ) );\n\t*dataOutLength = 0;\n\n\t/* Decode the URI text.  Since there can be multiple nested levels of\n\t   encoding, we keep iteratively decoding in-place until either \n\t   decodeRFC1866() cries Uncle or we hit the sanity-check limit */\n\tLOOP_SMALL( i = 0, i < 5, i++ )\n\t\t{\n\t\tint decodedLength;\n\n\t\tstatus = decodedLength = decodeRFC1866( data, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\t/* There's been no further change in the data, exit */\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tlength = decodedLength;\t/* Record the new length of the decoded data */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( i >= 5 )\n\t\t{\n\t\t/* Sanity-check limit exceeded.  This could be either a data error\n\t\t   or an internal error, since we can't automatically tell which it \n\t\t   is we report it as a data error */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\t*dataOutLength = length;\n\n\t/* We need to get at least 'x?xxx=xxx' */\n\tif( length < 9 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Parse a URI of the form \"* '?' attribute '=' value [ '&' ... ] ' ' \".\n\t   The URI is followed by the HTTP ID so we know that it always has to\n\t   end on a space, running out of input is an error */\n\tstatus = getUriSegmentLength( bufPtr, length, &segmentLength,\n\t\t\t\t\t\t\t\t  &locationParseInfo, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( rangeCheck( segmentLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( uriInfo->location, bufPtr, segmentLength );\n\turiInfo->locationLen = segmentLength;\n\tbufPtr += segmentLength + 1;\t/* Skip delimiter */\n\tlength -= segmentLength + 1;\n\tparsedLength = segmentLength + 1;\n\tstatus = getUriSegmentLength( bufPtr, length, &segmentLength,\n\t\t\t\t\t\t\t\t  &attributeParseInfo, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( rangeCheck( segmentLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( uriInfo->attribute, bufPtr, segmentLength );\n\turiInfo->attributeLen = segmentLength;\n\tbufPtr += segmentLength + 1;\t/* Skip delimiter */\n\tlength -= segmentLength + 1;\n\tparsedLength += segmentLength + 1;\n\tstatus = getUriSegmentLength( bufPtr, length, &segmentLength,\n\t\t\t\t\t\t\t\t  &valueParseInfo, &altDelimiterFound );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( rangeCheck( segmentLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( uriInfo->value, bufPtr, segmentLength );\n\turiInfo->valueLen = segmentLength;\n\tbufPtr += segmentLength + 1;\t/* Skip delimiter */\n\tlength -= segmentLength + 1;\n\tparsedLength += segmentLength + 1;\n\tif( altDelimiterFound )\n\t\t{\n\t\tstatus = getUriSegmentLength( bufPtr, length, &segmentLength,\n\t\t\t\t\t\t\t\t\t  &extraParseInfo, NULL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tREQUIRES( rangeCheck( segmentLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( uriInfo->extraData, bufPtr, segmentLength );\n\t\turiInfo->extraDataLen = segmentLength;\n\t\tparsedLength += segmentLength + 1;\n\t\t}\n\n\treturn( parsedLength );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Status Line Processing\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an HTTP status code.  Some status values are warnings only and\n   don't return an error status */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int readHTTPStatus( IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t\t   OUT_OPT_RANGE( 0, 999 ) int *httpStatus, \n\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst HTTP_STATUS_INFO *httpStatusInfo;\n\tconst BOOLEAN isResponseStatus = ( httpStatus != NULL ) ? TRUE : FALSE;\n\tBYTE dataBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint value, remainderLength, offset, status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( httpStatus == NULL || \\\n\t\t\tisWritePtr( httpStatus, sizeof( int ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\tif( httpStatus != NULL )\n\t\t*httpStatus = 999;\n\n\t/* Check that the numeric value is in order, being exactly three \n\t   characters followed by a space */\n\tif( dataLength < 3 || strSkipNonWhitespace( data, dataLength ) != 3 )\n\t\t{\n\t\tmemcpy( dataBuffer, data, min( dataLength, CRYPT_MAX_TEXTSIZE ) );\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid/missing HTTP %sstatus code '%s'\", \n\t\t\t\t  isResponseStatus ? \"response \" : \"\",\n\t\t\t\t  sanitiseString( dataBuffer, 3, CRYPT_MAX_TEXTSIZE ) ) );\n\t\t}\n\n\t/* Process the three-digit numeric status code */\n\tstatus = strGetNumeric( data, 3, &value, 1, 999 );\n\tif( cryptStatusError( status ) || \\\n\t\tvalue < MIN_HTTP_STATUS || value >= MAX_HTTP_STATUS )\n\t\t{\n\t\tmemcpy( dataBuffer, data, 3 );\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid HTTP %sstatus code '%s'\", \n\t\t\t\t  isResponseStatus ? \"response \" : \"\",\n\t\t\t\t  sanitiseString( dataBuffer, dataLength, \\\n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) ) );\n\t\t}\n\tif( httpStatus != NULL )\n\t\t*httpStatus = value;\n\n\t/* Try and translate the HTTP status code into a cryptlib equivalent.  \n\t   Most of the HTTP codes don't have any meaning in a cryptlib context \n\t   so they're mapped to a generic CRYPT_ERROR_READ by the HTTP status \n\t   decoding table */\n\thttpStatusInfo = getHTTPStatusInfo( value );\n\tREQUIRES( httpStatusInfo != NULL );\n\n\t/* If we're doing a status read from something in a header line rather\n\t   than an HTTP response (for example a Warning line, which only \n\t   requires a status code but no status message), we're done */\n\tif( !isResponseStatus )\n\t\treturn( CRYPT_OK );\n\n\t/* We're doing a status read from an HTTP response, make sure that \n\t   there's status text present alongside the status code */\n\tremainderLength = dataLength - 3;\n\tif( remainderLength < 2 || \\\n\t\t( offset = strSkipWhitespace( data + 3, remainderLength ) ) < 0 || \\\n\t\tdataLength - offset < 1 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Missing HTTP response status text following response \"\n\t\t\t\t  \"status %03d\", value ) );\n\t\t}\n\n\t/* If it's a special-case condition such as a redirect, tell the caller\n\t   to handle it specially */\n\tif( httpStatusInfo->status == OK_SPECIAL )\n\t\treturn( OK_SPECIAL );\n\n\t/* If it's an error condition, return extended error info (from the\n\t   information we have, not from any externally-supplied message) */\n\tif( httpStatusInfo->status != CRYPT_OK )\n\t\t{\n\t\tassert_nofuzz( httpStatusInfo->httpStatusString != NULL );\n\t\t\t\t\t\t\t/* Catch oddball errors in debug version */\n\t\tretExt( httpStatusInfo->status,\n\t\t\t\t( httpStatusInfo->status, errorInfo, \n\t\t\t\t  \"HTTP response status: %s\", \n\t\t\t\t  httpStatusInfo->httpErrorString ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process an HTTP header line looking for anything that we can handle */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int processHeaderLine( IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( HTTP_HEADER ) \\\n\t\t\t\t\t\t\t\tHTTP_HEADER_TYPE *headerType,\n\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo, \n\t\t\t\t\t\t\t  IN_RANGE( 1, 999 ) const int errorLineNo )\n\t{\n\tconst HTTP_HEADER_PARSE_INFO *headerParseInfoPtr = NULL;\n\tconst int firstChar = toUpper( *data );\n\tint processedLength, dataLeft, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( headerType, sizeof( HTTP_HEADER_TYPE ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\tREQUIRES( errorLineNo > 0 && errorLineNo < 1000 );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\t*headerType = HTTP_HEADER_NONE;\n\n\t/* Look for a header line that we recognise */\n\tLOOP_MED( i = 0, \n\t\t\t  httpHeaderParseInfo[ i ].headerString != NULL && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( httpHeaderParseInfo, \\\n\t\t\t\t\t\t\t\t\t\tHTTP_HEADER_PARSE_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( httpHeaderParseInfo[ i ].headerString[ 0 ] == firstChar && \\\n\t\t\tdataLength >= httpHeaderParseInfo[ i ].headerStringLen && \\\n\t\t\t!strCompare( data, httpHeaderParseInfo[ i ].headerString, \\\n\t\t\t\t\t\t httpHeaderParseInfo[ i ].headerStringLen ) )\n\t\t\t{\n\t\t\theaderParseInfoPtr = &httpHeaderParseInfo[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( httpHeaderParseInfo, \\\n\t\t\t\t\t\t\t\t\t HTTP_HEADER_PARSE_INFO ) );\n\tif( headerParseInfoPtr == NULL )\n\t\t{\n\t\t/* It's nothing that we can handle, exit */\n\t\treturn( 0 );\n\t\t}\n\tprocessedLength = headerParseInfoPtr->headerStringLen;\n\tdataLeft = dataLength - processedLength;\n\n\t/* Make sure that there's an attribute value present.  At this point we \n\t   know that dataLeft >= 0 because of the check performed earlier when\n\t   we went through the httpHeaderParseInfo, so the only exception \n\t   condition that can occur has dataLeft == 0 */\n\tif( dataLeft > 0 )\n\t\t{\n\t\tconst int extraLength = \\\n\t\t\t\tstrSkipWhitespace( data + processedLength, dataLeft );\n\t\tif( cryptStatusError( extraLength ) )\n\t\t\t{\n\t\t\t/* There was a problem, make sure that we fail the following \n\t\t\t   check */\n\t\t\tdataLeft = CRYPT_ERROR;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( extraLength > 0 )\n\t\t\t\t{\n\t\t\t\t/* We skipped some whitespace before the attribute value, \n\t\t\t\t   adjust the consumed/remaining byte counts */\n\t\t\t\tdataLeft -= extraLength;\n\t\t\t\tprocessedLength += extraLength;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( dataLeft < 1 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Missing HTTP header value for '%s' token, line %d\",\n\t\t\t\t  headerParseInfoPtr->headerString, errorLineNo ) );\n\t\t}\n\n\t/* Tell the caller what we found */\n\t*headerType = headerParseInfoPtr->headerType;\n\treturn( processedLength );\n\t}\n\n/* Read the first line in an HTTP response header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readFirstHeaderLine( INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_BUFFER_FIXED( dataMaxLength ) char *dataBuffer, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t\t OUT_RANGE( 0, 999 ) int *httpStatus,\n\t\t\t\t\t\t OUT_BOOL BOOLEAN *isSoftError )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tBOOLEAN textDataError;\n\tint length, processedLength, dataLeft, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( dataBuffer, dataMaxLength ) );\n\tassert( isWritePtr( httpStatus, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( dataMaxLength ) );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t/* Clear return values */\n\tmemset( dataBuffer, 0, min( 16, dataMaxLength ) );\n\t*httpStatus = 999;\n\t*isSoftError = FALSE;\n\n\t/* Read the header and check for an HTTP ID \"HTTP 1.x ...\" */\n\tstatus = readTextLine( readCharFunction, stream, dataBuffer, \n\t\t\t\t\t\t   dataMaxLength, &length, &textDataError, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( retTextLineError( stream, status, textDataError, \n\t\t\t\t\t\t\t\t  \"Invalid first HTTP header line: \", 0 ) );\n\t\t}\n\tif( length < 8 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid first HTTP header line length %d\", length ) );\n\t\t}\n\tstatus = processedLength = checkHTTPID( dataBuffer, length, stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some broken servers can send back God knows what at this point,\n\t\t   to help diagnose the issue we try and provide a copy of what\n\t\t   was sent if possible */\n\t\tif( strIsPrintable( dataBuffer, length ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, NETSTREAM_ERRINFO, \n\t\t\t\t\t\"Expected HTTP header, got '%s'\",\n\t\t\t\t\tsanitiseString( dataBuffer, length,\n\t\t\t\t\t\t\t\t\tmin( MAX_ERRMSG_SIZE - 64, \n\t\t\t\t\t\t\t\t\t\t dataMaxLength ) ) ) );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid HTTP ID/version '%s'\",\n\t\t\t\t  sanitiseString( dataBuffer, length, \n\t\t\t\t\t\t\t\t  min( CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t   dataMaxLength ) ) ) );\n\t\t}\n\tdataLeft = length - processedLength;\n\n\t/* Skip the whitespace between the HTTP ID and status info.  As before\n\t   we know that dataLeft >= 0 so the only exception condition that can\n\t   occur has dataLeft == 0 */\n\tif( dataLeft > 0 )\n\t\t{\n\t\tconst int extraLength = \\\n\t\t\t\tstrSkipWhitespace( dataBuffer + processedLength, dataLeft );\n\t\tif( cryptStatusError( extraLength ) )\n\t\t\t{\n\t\t\t/* There was a problem, make sure that we fail the following \n\t\t\t   check */\n\t\t\tdataLeft = CRYPT_ERROR;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( extraLength > 0 )\n\t\t\t\t{\n\t\t\t\t/* We skipped some whitespace before the HTTP status info,\n\t\t\t\t   adjust the consumed/remaining byte counts */\n\t\t\t\tdataLeft -= extraLength;\n\t\t\t\tprocessedLength += extraLength;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( dataLeft < 1 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Missing HTTP status code '%s'\",\n\t\t\t\t  sanitiseString( dataBuffer, length, \n\t\t\t\t\t\t\t\t  min( CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t   dataMaxLength ) ) ) );\n\t\t}\n\n\t/* Read the HTTP status info */\n\tstatus = readHTTPStatus( dataBuffer + processedLength, dataLeft,\n\t\t\t\t\t\t\t httpStatus, NETSTREAM_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* An error encountered at this point is a soft error in the sense \n\t\t   that we've had a valid HTTP response from the server (even if \n\t\t   it's an error response) and can continue the exchange beyond this \n\t\t   point */\n\t\t*isSoftError = TRUE;\n\t\t}\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Header Line Processing\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the remaining HTTP header lines after the first one */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nint readHeaderLines( INOUT STREAM *stream, \n\t\t\t\t\t OUT_BUFFER_FIXED( lineBufMaxLen ) char *lineBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\t\tconst int lineBufMaxLen,\n\t\t\t\t\t INOUT HTTP_HEADER_INFO *headerInfo,\n\t\t\t\t\t OUT_BOOL BOOLEAN *isSoftError )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tBOOLEAN seenHost = FALSE, seenLength = FALSE;\n\tBOOLEAN seenConnection = FALSE; \n#ifdef USE_WEBSOCKETS\n\tBOOLEAN seenUpgrade = FALSE, seenVersion = FALSE, seenKey = FALSE;\n\tBOOLEAN seenAuth = FALSE;\n#endif /* USE_WEBSOCKETS */\n\tint contentLength = 0, lineCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( lineBuffer, lineBufMaxLen ) );\n\tassert( isWritePtr( headerInfo, sizeof( HTTP_HEADER_INFO ) ) );\n\tassert( isWritePtr( isSoftError, sizeof( BOOLEAN ) ) );\n\n\tstatic_assert( MIN_LINEBUF_SIZE > CRYPT_MAX_TEXTSIZE + 32,\n\t\t\t\t   \"Line buffer length\" );\n\t\t\t\t   /* Checked for in sanitiseString() calls, but there \n\t\t\t\t      should be enough room for most common cases */\n\n\tREQUIRES( lineBufMaxLen >= MIN_LINEBUF_SIZE && \\\n\t\t\t  lineBufMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t/* Clear return values */\n\tmemset( lineBuffer, 0, min( 16, lineBufMaxLen ) );\n\t*isSoftError = FALSE;\n\n\t/* We set the default error return status to 400, \"Bad Request\", to save\n\t   having to spray dozens of httpStatus-set lines throughout the code.  \n\t   On a non-error exit, we reset the httpStatus to 0 */\n\theaderInfo->httpStatus = 400;\n\n\t/* Read each line in the header checking for any fields that we need to\n\t   handle.  We check for a couple of basic problems with the header to\n\t   avoid malformed-header attacks, for example an attacker could send a\n\t   request with two 'Content-Length:' headers, one of which covers the\n\t   entire message body and the other which indicates that there's a\n\t   second request that begins halfway through the message body.  Some\n\t   proxies/caches will take the first length, some the second, if the\n\t   proxy is expected to check/rewrite the request as it passes through\n\t   then the single/dual-message issue can be used to bypass the checking\n\t   on the tunnelled second message.  Because of this we only allow a\n\t   single Host: and Content-Length: header (and, if WebSockets is in use,\n\t   any of the WebSockets-specific headers), and disallow a chunked \n\t    encoding in combination with a content-length (Apache does some\n\t   really strange things with chunked encodings).  We can't be too\n\t   finicky with the checking though or we'll end up rejecting non-\n\t   malicious requests from some of the broken HTTP implementations out\n\t   there */\n\tLOOP_MED( lineCount = 0, lineCount < 30, lineCount++ )\n\t\t{\n\t\tHTTP_HEADER_TYPE headerType;\n\t\tBOOLEAN textDataError;\n\t\tchar *lineBufPtr;\n\t\tint length, lineLength;\n\n\t\t/* Any errors that occur while reading the header line data are \n\t\t   fatal */\n\t\t*isSoftError = FALSE;\n\n\t\tstatus = readTextLine( readCharFunction, stream, lineBuffer,\n\t\t\t\t\t\t\t   lineBufMaxLen, &lineLength, &textDataError, \n\t\t\t\t\t\t\t   TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( retTextLineError( stream, status, textDataError, \n\t\t\t\t\t\t\t\t\t  \"Invalid HTTP header line %d: \", \n\t\t\t\t\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t}\n\n\t\t/* If we've reached the end of the header lines (denoted by a blank\n\t\t   line), exit */\n\t\tif( lineLength <= 0 )\n\t\t\tbreak;\n\n\t\t/* Beyond this point all errors are soft errors in that they arise \n\t\t   due to problems in parsing HTTP headers rather than I/O issues, \n\t\t   so the caller has to call back to read the remaining (possibly\n\t\t   invalid) header lines in order to clear the input stream */\n\t\t*isSoftError = TRUE;\n\n\t\t/* If this is a no-op read (for example lines following a soft error \n\t\t   or a 100 Continue response), all that we're interested in is \n\t\t   draining the input, so we don't try and parse the header line */\n\t\tif( TEST_FLAG( headerInfo->flags, HTTP_FLAG_NOOP ) )\n\t\t\tcontinue;\n\n\t\t/* Process the header line to see what we've got */\n\t\tstatus = length = \\\n\t\t\tprocessHeaderLine( lineBuffer, lineLength, &headerType,\n\t\t\t\t\t\t\t   NETSTREAM_ERRINFO, lineCount + 2 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlineBufPtr = lineBuffer + length;\n\t\tlineLength -= length;\n\t\tENSURES( lineLength > 0 );\t/* Guaranteed by processHeaderLine() */\n\t\tswitch( headerType )\n\t\t\t{\n\t\t\tcase HTTP_HEADER_HOST:\n\t\t\t\t/* Make sure that it's a non-duplicate, and remember that\n\t\t\t\t   we've seen a Host: line, to meet the HTTP 1.1\n\t\t\t\t   requirements */\n\t\t\t\tif( seenHost )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Host:' header, line %d\",\n\t\t\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tseenHost = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_CONTENT_LENGTH:\n\t\t\t\t/* Make sure that it's a non-duplicate and get the content\n\t\t\t\t   length.  At this point all that we do is perform a\n\t\t\t\t   general sanity check that the length looks OK, a specific\n\t\t\t\t   check against the caller-supplied minimum/maximum\n\t\t\t\t   allowable length is performed later since the content\n\t\t\t\t   length may also be provided as a chunked encoding length,\n\t\t\t\t   which we can't check until we've processed all of the\n\t\t\t\t   header lines */\n\t\t\t\tif( seenLength )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Content-Length:' header, \"\n\t\t\t\t\t\t\t  \"line %d\", lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tstatus = strGetNumeric( lineBufPtr, lineLength, \n\t\t\t\t\t\t\t\t\t\t&contentLength, 1, MAX_BUFFER_SIZE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid HTTP content length '%s', line %d\",\n\t\t\t\t\t\t\t  sanitiseString( lineBufPtr, lineLength, \n\t\t\t\t\t\t\t\t\t\t\t  min( CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t\t\t   lineBufMaxLen - length ) ),\n\t\t\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tseenLength = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_CONTENT_TYPE:\n\t\t\t\t{\n\t\t\t\tstatic const URI_PARSE_INFO typeParseInfo = \\\n\t\t\t\t\t\t{ '/', '\\0', 2, CRYPT_MAX_TEXTSIZE, 2 };\n\t\t\t\tstatic const URI_PARSE_INFO subtypeParseInfo = \\\n\t\t\t\t\t\t{ '\\0', ';', 2, CRYPT_MAX_TEXTSIZE, 0 };\n\t\t\t\tBOOLEAN dummy;\n\t\t\t\tchar *contentType;\n\t\t\t\tint contentTypeLen, subTypeLen;\n\n\t\t\t\t/* Sometimes if there's an error it'll be returned as content\n\t\t\t\t   at the HTTP level rather than at the tunnelled-over-HTTP\n\t\t\t\t   protocol level.  The easiest way to check for this would\n\t\t\t\t   be to make sure that the content-type matches the\n\t\t\t\t   expected type and report anything else as an error.\n\t\t\t\t   Unfortunately due to the hit-and-miss handling of content-\n\t\t\t\t   types by PKI software using HTTP as a substrate it's not\n\t\t\t\t   safe to do this, so we have to default to allow-all\n\t\t\t\t   rather than deny-all, treating only straight text as a\n\t\t\t\t   problem type.\n\n\t\t\t\t   To compound the problem there are also apps out there \n\t\t\t\t   that send their PKI messages marked as plain text, so \n\t\t\t\t   this isn't 100% foolproof.  This is particularly \n\t\t\t\t   problematic for web browsers, where so many servers were \n\t\t\t\t   misconfigured to return pretty much anything as \n\t\t\t\t   text/plain that Microsoft added content-type guessing \n\t\t\t\t   code to MSIE to make web pages served from misconfigured \n\t\t\t\t   servers work (you can see this by serving a JPEG file as \n\t\t\t\t   text/plain, MSIE will display it as a JPEG while Mozilla/\n\t\t\t\t   Firefox/Opera/etc will display it as text or prompt for a \n\t\t\t\t   helper app to handle it).  Since this content-type \n\t\t\t\t   guessing is a potential security hole, MS finally made it\n\t\t\t\t   configurable in Windows XP SP2, but it's still enabled\n\t\t\t\t   by default even there.\n\n\t\t\t\t   In practice however errors-via-HTTP is more common than\n\t\t\t\t   certs-via-text.  We try and detect the cert-as-plain-text\n\t\t\t\t   special-case at a later point when we've got the message\n\t\t\t\t   body available.\n\n\t\t\t\t   Since we're now looking at the content-type line (even if\n\t\t\t\t   we don't really process it in any way), we perform at \n\t\t\t\t   least a minimal validity check for * '/' * [ ';*' ] */\n\t\t\t\tstatus = getUriSegmentLength( lineBufPtr, lineLength, \n\t\t\t\t\t\t\t\t\t\t\t  &contentTypeLen, \n\t\t\t\t\t\t\t\t\t\t\t  &typeParseInfo, NULL );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* We need to have at least \"xx/\"* present (length is\n\t\t\t\t\t   guaranteed by getUriSegmentLength()) */\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t\t\"Invalid HTTP content type '%s', line %d\",\n\t\t\t\t\t\t\t\tlineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tcontentType = lineBufPtr;\n\t\t\t\tlineBufPtr += contentTypeLen + 1;\t/* Skip delimiter */\n\t\t\t\tlineLength -= contentTypeLen + 1;\n\t\t\t\tstatus = getUriSegmentLength( lineBufPtr, lineLength, \n\t\t\t\t\t\t\t\t\t\t\t  &subTypeLen, \n\t\t\t\t\t\t\t\t\t\t\t  &subtypeParseInfo, &dummy );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* We need to have at least 'xx/yy' present (length is\n\t\t\t\t\t   guaranteed by getUriSegmentLength()) */\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t\t\"Invalid HTTP content subtype '%s', line %d\",\n\t\t\t\t\t\t\t\tlineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tif( contentTypeLen == 4 && \\\n\t\t\t\t\t!strCompare( contentType, \"text\", 4 ) )\n\t\t\t\t\tSET_FLAG( headerInfo->flags, HTTP_FLAG_TEXTMSG );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase HTTP_HEADER_TRANSFER_ENCODING:\n\t\t\t\tif( lineLength < 7 || \\\n\t\t\t\t\tstrCompare( lineBufPtr, \"Chunked\", 7 ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP transfer encoding method \"\n\t\t\t\t\t\t\t  \"'%s', expected 'Chunked', line %d\",\n\t\t\t\t\t\t\t  lineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n\n\t\t\t\t/* If it's a chunked encoding, the length is part of the\n\t\t\t\t   data and must be read later */\n\t\t\t\tif( seenLength )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Spurious HTTP 'Content-Length:' header for \"\n\t\t\t\t\t\t\t  \"Chunked encoding, line %d\", lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tSET_FLAG( headerInfo->flags, HTTP_FLAG_CHUNKED );\n\t\t\t\tseenLength = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_CONTENT_ENCODING:\n\t\t\t\t/* We can't handle any type of content encoding (e.g. gzip,\n\t\t\t\t   compress, deflate, mpeg4, interpretive dance) except the\n\t\t\t\t   no-op identity encoding */\n\t\t\t\tif( lineLength < 8 || \\\n\t\t\t\t\tstrCompare( lineBufPtr, \"Identity\", 8 ) )\n\t\t\t\t\t{\n\t\t\t\t\theaderInfo->httpStatus = 415;\t/* Unsupp.media type */\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP content encoding method \"\n\t\t\t\t\t\t\t  \"'%s', expected 'Identity', line %d\",\n\t\t\t\t\t\t\t  lineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_CONTENT_TRANSFER_ENCODING:\n\t\t\t\t/* HTTP uses Transfer-Encoding, not the MIME Content-\n\t\t\t\t   Transfer-Encoding types such as base64 or quoted-\n\t\t\t\t   printable.  If any implementations erroneously use a\n\t\t\t\t   C-T-E, we make sure that it's something that we can\n\t\t\t\t   handle */\n\t\t\t\tif( !( lineLength >= 6 && \\\n\t\t\t\t\t   !strCompare( lineBufPtr, \"Binary\", 6 ) ) && \\\n\t\t\t\t\t!( lineLength >= 8 && \\\n\t\t\t\t\t   !strCompare( lineBufPtr, \"Identity\", 8 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\theaderInfo->httpStatus = 415;\t/* Unsupp.media type */\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP content transfer encoding \"\n\t\t\t\t\t\t\t  \"method '%s', expected 'Identity' or \"\n\t\t\t\t\t\t\t  \"'Binary', line %d\", lineBufPtr, lineLength, \n\t\t\t\t\t\t\t  lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_SERVER:\n\t\t\t\t{\n\t\t\t\tconst int firstChar = toUpper( *lineBufPtr );\n\t\t\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t\t\t/* Check to see whether we recognise the peer system type */\n\t\t\t\tLOOP_MED_ALT( i = 0, systemIdInfo[ i ].idString != NULL && \\\n\t\t\t\t\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( systemIdInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t SYSTEM_ID_INFO ), i++ )\n\t\t\t\t\t{\n\t\t\t\t\tconst SYSTEM_ID_INFO *systemIdInfoPtr = &systemIdInfo[ i ];\n\n\t\t\t\t\tif( systemIdInfoPtr->idString[ 0 ] == firstChar && \\\n\t\t\t\t\t\tlineLength >= systemIdInfoPtr->idStringLen && \\\n\t\t\t\t\t\t!strCompare( lineBufPtr, systemIdInfoPtr->idString, \\\n\t\t\t\t\t\t\t\t\t systemIdInfoPtr->idStringLen ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tnetStream->systemType = systemIdInfoPtr->systemType;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\t\tENSURES( i < FAILSAFE_ARRAYSIZE( systemIdInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t SYSTEM_ID_INFO ) );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase HTTP_HEADER_TRAILER:\n\t\t\t\t/* The body is followed by trailer lines, used with chunked\n\t\t\t\t   encodings where some header lines can't be produced until\n\t\t\t\t   the entire body has been generated.  This wasn't added\n\t\t\t\t   until RFC 2616, since many implementations are based on\n\t\t\t\t   RFC 2068 and don't produce this header we don't do\n\t\t\t\t   anything with it.  The trailer can be auto-detected\n\t\t\t\t   anyway, it's only present to tell the receiver to perform\n\t\t\t\t   certain actions such as creating an MD5 hash of the data\n\t\t\t\t   as it arrives */\n\t\t\t\tSET_FLAG( headerInfo->flags, HTTP_FLAG_TRAILER );\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_CONNECTION:\n\t\t\t\tif( seenConnection )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Connection:' header, line %d\",\n\t\t\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\t/* If the other side has indicated that it's going to close\n\t\t\t\t   the connection, record the fact that this is the last \n\t\t\t\t   message in the session */\n\t\t\t\tif( lineLength >= 5 && \\\n\t\t\t\t\t!strCompare( lineBufPtr, \"Close\", 5 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGR );\n\t\t\t\t\t}\n\t\t\t\tif( TEST_FLAG( headerInfo->flags, HTTP_FLAG_UPGRADE ) && \\\n\t\t\t\t\t( lineLength < 7 || \\\n\t\t\t\t\t  strCompare( lineBufPtr, \"Upgrade\", 7 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP connection type '%s', expected \"\n\t\t\t\t\t\t\t  \"'Upgrade', line %d\", lineBufPtr, lineLength, \n\t\t\t\t\t\t\t  lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tseenConnection = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_WARNING:\n\t\t\t\t/* Read the HTTP status info from the warning.  \n\t\t\t\t   readHTTPStatus() will process the error status in the\n\t\t\t\t   warning line, but since we're passing in a NULL pointer \n\t\t\t\t   for the status info it'll only report an error in the\n\t\t\t\t   warning content itself, it won't return the processed\n\t\t\t\t   warning status as an error */\n\t\t\t\tstatus = readHTTPStatus( lineBufPtr, lineLength, NULL, \n\t\t\t\t\t\t\t\t\t\t NETSTREAM_ERRINFO );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP warning information '%s', \"\n\t\t\t\t\t\t\t  \"line %d\", lineBufPtr, lineLength, \n\t\t\t\t\t\t\t  lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_LOCATION:\n\t\t\t\t{\n#if defined( __WIN32__ ) && !defined( NDEBUG ) && 1\n\t\t\t\tURL_INFO urlInfo;\n#endif /* Win32 debug build only */\n\n\t\t\t\t/* Make sure that we've been given an HTTP URL as the \n\t\t\t\t   redirect location.  We need to do this because \n\t\t\t\t   sNetParseURL() will accept a wide range of URL types\n\t\t\t\t   while we only allow \"http://\"* */\n\t\t\t\tif( lineLength < 10 || \\\n\t\t\t\t\tstrCompare( lineBufPtr, \"http://\", 7 ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP redirect location '%s', line %d\",\n\t\t\t\t\t\t\t  lineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n\n\t\t\t\t/* Process the redirect location */\n#if defined( __WIN32__ ) && !defined( NDEBUG ) && 1\n\t\t\t\t/* We don't try and parse the URL other than in the Win32 \n\t\t\t\t   debug build because we don't do redirects yet so there's \n\t\t\t\t   no need to expose ourselves to possibly maliciously-\n\t\t\t\t   created URLs from external sources */\n\t\t\t\tstatus = sNetParseURL( &urlInfo, lineBufPtr, lineLength, \n\t\t\t\t\t\t\t\t\t   URL_TYPE_HTTP );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP redirect location '%s', line %d\",\n\t\t\t\t\t\t\t  lineBufPtr, lineLength, lineCount ) );\n\t\t\t\t\t}\n#endif /* Win32 debug build only */\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase HTTP_HEADER_EXPECT:\n\t\t\t\t/* If the other side wants the go-ahead to continue, give it\n\t\t\t\t   to them.  We do this automatically because we're merely\n\t\t\t\t   using HTTP as a substrate, the real decision will be made\n\t\t\t\t   at the higher-level protocol layer */\n\t\t\t\tif( lineLength >= 12 && \\\n\t\t\t\t\t!strCompare( lineBufPtr, \"100-Continue\", 12 ) )\n\t\t\t\t\t{\n\t\t\t\t\t( void ) sendHTTPError( stream, lineBufPtr, \n\t\t\t\t\t\t\t\t\t\t\tlineBufMaxLen, 100 );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n#ifdef USE_WEBSOCKETS\n\t\t\tcase HTTP_HEADER_UPGRADE:\n\t\t\t\tif( seenUpgrade )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Upgrade:' header, line %d\",\n\t\t\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tif( lineLength < 9 || \\\n\t\t\t\t\tstrCompare( lineBufPtr, \"WebSocket\", 9 ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid HTTP upgrade type '%s', expected \"\n\t\t\t\t\t\t\t  \"'WebSocket', line %d\", lineBufPtr, lineLength, \n\t\t\t\t\t\t\t  lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tseenUpgrade = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_WS_PROTOCOL:\n\t\t\t\tif( lineLength < 2 || lineLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid HTTP subprotocol name length %d, \"\n\t\t\t\t\t\t\t  \"expected %d...%d, line %d\", lineLength,\n\t\t\t\t\t\t\t  2, CRYPT_MAX_TEXTSIZE, lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tREQUIRES( rangeCheck( lineLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\t\tmemcpy( headerInfo->wsProtocol, lineBufPtr, lineLength );\n\t\t\t\theaderInfo->wsProtocolLen = lineLength;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_WS_VERSION:\n\t\t\t\t/* Handling of WebSockets versions is awkward, the RFC \n\t\t\t\t   defines \"some guidance\" on version handling by suggesting \n\t\t\t\t   that the client can request the version of the WebSockets \n\t\t\t\t   protocol that it prefers, which the server can choose to \n\t\t\t\t   accept, or if not send back a \"Sec-WebSocket-Version\" \n\t\t\t\t   with a list of versions it supports, or perhaps multiple \n\t\t\t\t   \"Sec-WebSocket-Version\" headers, and then the client and \n\t\t\t\t   server can chat for awhile about what they'd prefer.\n\n\t\t\t\t   The chances of any of this working are rather remote, so\n\t\t\t\t   we just hardcode in a check for the sole RFC-defined \n\t\t\t\t   version */\n\t\t\t\tif( lineLength < 2 || strCompare( lineBufPtr, \"13\", 2 ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( retHeaderError( stream, \n\t\t\t\t\t\t\t  \"Invalid WebSockets version '%s', expected \"\n\t\t\t\t\t\t\t  \"'13', line %d\", lineBufPtr, lineLength, \n\t\t\t\t\t\t\t  lineCount ) );\n\t\t\t\t\t}\n\t\t\t\tseenVersion = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_WS_KEY:\n\t\t\t\tif( seenKey || seenAuth )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Sec-WebSocket-Key:' \"\n\t\t\t\t\t\t\t  \"header, line %d\", lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tif( lineLength < 16 || lineLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid WebSockets key length %d, \"\n\t\t\t\t\t\t\t  \"expected %d...%d, line %d\", lineLength,\n\t\t\t\t\t\t\t  16, CRYPT_MAX_TEXTSIZE, lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tREQUIRES( rangeCheck( lineLength, 16, CRYPT_MAX_TEXTSIZE ) );\n\t\t\t\tmemcpy( headerInfo->wsAuth, lineBufPtr, lineLength );\n\t\t\t\theaderInfo->wsAuthLen = lineLength;\n\t\t\t\tseenKey = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase HTTP_HEADER_WS_RESPONSE:\n\t\t\t\tif( seenAuth || seenKey )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate HTTP 'Sec-WebSocket-Accept:' \"\n\t\t\t\t\t\t\t  \"header, line %d\", lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tif( lineLength < 16 || lineLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid WebSockets auth length %d, \"\n\t\t\t\t\t\t\t  \"expected %d...%d, line %d\", lineLength,\n\t\t\t\t\t\t\t  16, CRYPT_MAX_TEXTSIZE, lineCount + 2 ) );\n\t\t\t\t\t}\n\t\t\t\tREQUIRES( rangeCheck( lineLength, 16, CRYPT_MAX_TEXTSIZE ) );\n\t\t\t\tmemcpy( headerInfo->wsAuth, lineBufPtr, lineLength );\n\t\t\t\theaderInfo->wsAuthLen = lineLength;\n\t\t\t\tseenAuth = TRUE;\n\t\t\t\tbreak;\n#endif /* USE_WEBSOCKETS */\n\n\t\t\tcase HTTP_HEADER_NONE:\n\t\t\t\t/* It's something that we don't know/care about, skip it */\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( lineCount >= 30 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Received too many HTTP header lines (more than %d)\",\n\t\t\t\t  FAILSAFE_ITERATIONS_MED ) );\n\t\t}\n\n\t/* If this is a tunnel being opened via an HTTP proxy then we're done */\n\tif( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\tTEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_TUNNEL ) )\n\t\t{\n\t\theaderInfo->httpStatus = 0;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If this is a no-op read (for example lines following an error or 100\n\t   Continue response) then all that we're interested in is draining the\n\t   input so we don't check any further */\n\tif( TEST_FLAG( headerInfo->flags, HTTP_FLAG_NOOP ) )\n\t\t{\n\t\theaderInfo->httpStatus = 0;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a chunked encoding for which the length is kludged on before\n\t   the data as a hex string, decode the length value */\n\tif( TEST_FLAG( headerInfo->flags, HTTP_FLAG_CHUNKED ) )\n\t\t{\n\t\tBOOLEAN textDataError;\n\t\tint lineLength;\n\n\t\tstatus = readTextLine( readCharFunction, stream, lineBuffer, \n\t\t\t\t\t\t\t   lineBufMaxLen, &lineLength, &textDataError, \n\t\t\t\t\t\t\t   FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( retTextLineError( stream, status, textDataError, \n\t\t\t\t\t\t\t\t\t  \"Invalid HTTP chunked encoding \"\n\t\t\t\t\t\t\t\t\t  \"header line %d: \", lineCount + 2 ) );\n\t\t\t}\n\t\tif( lineLength <= 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Missing HTTP chunk length, line %d\", lineCount + 2 ) );\n\t\t\t}\n\t\tstatus = contentLength = getChunkLength( lineBuffer, lineLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Invalid length '%s' for HTTP chunked encoding, line \"\n\t\t\t\t\t  \"%d\", sanitiseString( lineBuffer, lineLength, \n\t\t\t\t\t\t\t\t\t\t\tmin( CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t\t\t\t lineBufMaxLen ) ),\n\t\t\t\t\t  lineCount + 2 ) );\n\t\t\t}\n\t\t}\n\n\t/* If we're a server talking HTTP 1.1 and we haven't seen a \"Host:\"\n\t   header from the client, return an error */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t!isHTTP10( netStream ) && !seenHost )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Missing HTTP 1.1 'Host:' header\" ) );\n\t\t}\n\n\t/* If it's a WebSockets protocol upgrade and we haven't the required \n\t   headers, return an error */\n#ifdef USE_WEBSOCKETS \n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\tBOOLEAN wsOK = TRUE;\n\n\t\tif( !seenUpgrade || !seenConnection )\n\t\t\twsOK = FALSE;\n\t\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) )\n\t\t\t{\n\t\t\tif( !seenKey || !seenVersion )\n\t\t\t\twsOK = FALSE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( !seenAuth )\n\t\t\t\twsOK = FALSE;\n\t\t\t}\n\t\tif( !wsOK )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Missing Websockets 'Upgrade:', 'Connection:', or \"\n\t\t\t\t\t  \"'Sec-WebSocket-Key:'/'Sec-WebSocket-Accept:' header\" ) );\n\t\t\t}\n\t\t}\n#endif /* USE_WEBSOCKETS */\n\n\t/* If it's a GET or protocol upgrade request there's no length so we \n\t   can exit now */\n\tif( TEST_FLAG( headerInfo->flags, HTTP_FLAG_GET ) || \\\n\t\tTEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\tif( seenLength )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Unexpected %d bytes HTTP body content received in \"\n\t\t\t\t\t  \"idempotent read\", contentLength ) );\n\t\t\t}\n\n\t\theaderInfo->httpStatus = 0;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that we've been given a length.  In theory a server could\n\t   indicate the length implicitly by closing the connection once it's\n\t   sent the last byte, but this isn't allowed for PKI messages.  The\n\t   client can't use this option either since that would make it\n\t   impossible for us to send back the response */\n\tif( !seenLength )\n\t\t{\n\t\theaderInfo->httpStatus = 411;\t/* Length required */\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Missing HTTP length\" ) );\n\t\t}\n\n\t/* Make sure that the length is sensible */\n\tif( contentLength < headerInfo->minContentLength || \\\n\t\tcontentLength > headerInfo->maxContentLength )\n\t\t{\n\t\tretExt( ( contentLength < headerInfo->minContentLength ) ? \\\n\t\t\t\tCRYPT_ERROR_UNDERFLOW : CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( ( contentLength < headerInfo->minContentLength ) ? \\\n\t\t\t\t\tCRYPT_ERROR_UNDERFLOW : CRYPT_ERROR_OVERFLOW, \n\t\t\t\t  NETSTREAM_ERRINFO,\n\t\t\t\t  \"Invalid HTTP content length %d bytes, expected \"\n\t\t\t\t  \"%d...%d bytes\", contentLength,\n\t\t\t\t  headerInfo->minContentLength, \n\t\t\t\t  headerInfo->maxContentLength ) );\n\t\t}\n\theaderInfo->contentLength = contentLength;\n\n\theaderInfo->httpStatus = 0;\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the HTTP trailer lines that follow chunked data:\n\n\t\t\tCRLF\n\t\t\t\"0\" CRLF\n\t\t\ttrailer-lines*\n\t\t\tCRLF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readTrailerLines( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_BUFFER_FIXED( lineBufMaxLen ) char *lineBuffer, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\t\tconst int lineBufMaxLen )\n\t{\n#ifdef USE_ERRMSGS\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n#endif /* USE_ERRMSGS */\n\tHTTP_HEADER_INFO headerInfo;\n\tBOOLEAN textDataError, dummyBoolean;\n\tint readLength DUMMY_INIT, dummyInt, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( lineBuffer, lineBufMaxLen ) );\n\n\tREQUIRES( lineBufMaxLen >= MIN_LINEBUF_SIZE && \\\n\t\t\t  lineBufMaxLen < MAX_INTLENGTH_SHORT );\n#ifdef USE_ERRMSGS\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n#endif /* USE_ERRMSGS */\n\n\t/* Clear return values */\n\tmemset( lineBuffer, 0, min( 16, lineBufMaxLen ) );\n\n\t/* Read the blank line and chunk length */\n\tstatus = readTextLine( readCharFunction, stream, lineBuffer,\n\t\t\t\t\t\t   lineBufMaxLen, &dummyInt, &textDataError, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readTextLine( readCharFunction, stream, lineBuffer, \n\t\t\t\t\t\t\t   lineBufMaxLen, &readLength, &textDataError, \n\t\t\t\t\t\t\t   FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( retTextLineError( stream, status, textDataError, \n\t\t\t\t\t\t\t\t  \"Invalid HTTP chunked trailer line: \", \n\t\t\t\t\t\t\t\t  0 ) );\n\t\t}\n\n\t/* Make sure that there are no more chunks to follow */\n\tstatus = getChunkLength( lineBuffer, readLength );\n\tif( status != 0 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Unexpected additional data following HTTP chunked \"\n\t\t\t\t  \"data\" ) );\n\t\t}\n\n\t/* Read any remaining trailer lines */\n\tinitHeaderInfo( &headerInfo, 0, 0, HTTP_FLAG_NOOP );\n\treturn( readHeaderLines( stream, lineBuffer, lineBufMaxLen,\n\t\t\t\t\t\t\t &headerInfo, &dummyBoolean ) );\n\t}\n#endif /* USE_HTTP */\n"
  },
  {
    "path": "deps/cl345/io/http_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib HTTP Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"http.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"io/http.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HTTP\n\n/* HTTP request line parsing information */\n\ntypedef struct {\n\tBUFFER_FIXED( reqNameLen ) \\\n\tconst char *reqName;\t\t/* Request name */\n\tint reqNameLen;\t\t\t\t/* Length of request name */\n\tSTREAM_HTTPREQTYPE_TYPE reqType;\t/* Request type */\n\tint reqTypeFlag;\t\t\t/* Stream flag for this request type */\n\t} HTTP_REQUEST_INFO;\n\nstatic const HTTP_REQUEST_INFO httpReqInfo[] = {\n\t{ \"GET\", 3, STREAM_HTTPREQTYPE_GET, STREAM_NHFLAG_GET },\n\t{ \"POST\", 4, STREAM_HTTPREQTYPE_POST, STREAM_NHFLAG_POST },\n\t{ NULL, 0, 0 }, { NULL, 0, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Callback function used by readTextLine() to read characters from a\n   stream.  When reading text data over a network we don't know how much\n   more data is to come so we have to read a byte at a time looking for an\n   EOL.  In addition we can't use the simple optimisation of reading two\n   bytes at a time because some servers only send a LF even though the spec\n   requires a CRLF.  This is horribly inefficient but is pretty much\n   eliminated through the use of opportunistic read-ahead buffering */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE ch;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = bufferedTransportRead( stream, &ch, 1, &length,\n\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_NONE );\n\treturn( cryptStatusError( status ) ? status : ch );\n\t}\n\n/* Clear the HTTP input stream after a soft error has occurred so that \n   further HTTP transactions can be read */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int clearInputStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int lineBufSize )\n\t{\n\tHTTP_HEADER_INFO headerInfo;\n\tBOOLEAN isSoftError;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( lineBuffer, lineBufSize ) );\n\n\tREQUIRES( lineBufSize >= MIN_LINEBUF_SIZE && \\\n\t\t\t  lineBufSize < MAX_INTLENGTH_SHORT );\n\n\t/* Perform a dummy read to clear any remaining HTTP header lines.  Since \n\t   we're merely clearing the input stream after a soft error for further\n\t   reads or to write back an error response, we can ignore a range of\n\t   non-fatal errors that might occur in the process */\n\tinitHeaderInfo( &headerInfo, 1, 8192, HTTP_FLAG_NOOP );\n\tstatus = readHeaderLines( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t\t\t  &headerInfo, &isSoftError );\n\tif( status != CRYPT_ERROR_UNDERFLOW && \\\n\t\tstatus != CRYPT_ERROR_OVERFLOW && \\\n\t\tstatus != CRYPT_ERROR_BADDATA )\n\t\treturn( status );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead Request Header\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an HTTP request header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int readRequestHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int lineBufSize, \n\t\t\t\t\t\t\t  INOUT HTTP_DATA_INFO *httpDataInfo, \n\t\t\t\t\t\t\t  OUT_FLAGS_Z( HTTP ) int *flags )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tHTTP_HEADER_INFO headerInfo;\n\tHTTP_URI_INFO *uriInfo = httpDataInfo->uriInfo;\n\tSTREAM_HTTPREQTYPE_TYPE reqType = STREAM_HTTPREQTYPE_NONE;\n\tBOOLEAN isTextDataError, isSoftError;\n\tchar *bufPtr;\n\tint length, offset, reqNameLen DUMMY_INIT, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( lineBuffer, lineBufSize ) );\n\tassert( isWritePtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );\n\tassert( isWritePtr( flags, sizeof( int ) ) );\n\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES( lineBufSize >= MIN_LINEBUF_SIZE && \\\n\t\t\t  lineBufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckHttpDataInfo( httpDataInfo ) );\n\tREQUIRES( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) );\n\tREQUIRES( ( ( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_GET ) || \\\n\t\t\t\t  TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) ) && \\\n\t\t\t\turiInfo != NULL ) || \\\n\t\t\t  ( !TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_GET ) && \\\n\t\t\t\turiInfo == NULL ) );\n\n\t/* Clear return values */\n\tmemset( lineBuffer, 0, min( 16, lineBufSize ) );\n\t*flags = HTTP_FLAG_NONE;\n\n\t/* Read the header and check for \"POST/GET x HTTP/1.x\".  In theory this\n\t   could be a bit risky because the original CERN server required an\n\t   extra (spurious) CRLF after a POST, so that various early clients sent\n\t   an extra CRLF that isn't included in the Content-Length header and\n\t   ends up preceding the start of the next load of data.  We don't check\n\t   for this because it only applies to very old pure-HTTP (rather than\n\t   HTTP-as-a-transport-layer) clients, which are unlikely to be hitting a\n\t   PKI responder */\n\tstatus = readTextLine( readCharFunction, stream, lineBuffer, \n\t\t\t\t\t\t   lineBufSize, &length, &isTextDataError, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If it's an HTTP-level error (e.g. line too long), send back an\n\t\t   HTTP-level error response */\n\t\tif( status != CRYPT_ERROR_COMPLETE )\n\t\t\t{\n\t\t\tsendHTTPError( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t\t   ( status == CRYPT_ERROR_OVERFLOW ) ? \\\n\t\t\t\t\t\t   414 : 400 );\n\t\t\t}\n\n\t\treturn( retTextLineError( stream, status, isTextDataError, \n\t\t\t\t\t\t\t\t  \"Invalid HTTP request header line 1: \", \n\t\t\t\t\t\t\t\t  0 ) );\n\t\t}\n\tLOOP_MED( i = 0, httpReqInfo[ i ].reqName != NULL && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( httpReqInfo, HTTP_REQUEST_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tconst HTTP_REQUEST_INFO *reqInfoPtr = &httpReqInfo[ i ];\n\n\t\tif( TEST_FLAG( netStream->nhFlags, reqInfoPtr->reqTypeFlag ) && \\\n\t\t\tlength >= reqInfoPtr->reqNameLen && \\\n\t\t\t!strCompare( lineBuffer, reqInfoPtr->reqName, \\\n\t\t\t\t\t\t reqInfoPtr->reqNameLen ) )\n\t\t\t{\n\t\t\treqType = reqInfoPtr->reqType;\n\t\t\treqNameLen = reqInfoPtr->reqNameLen;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( httpReqInfo, HTTP_REQUEST_INFO ) );\n\tif( reqType == STREAM_HTTPREQTYPE_NONE )\n\t\t{\n\t\tchar reqNameBuffer[ 16 + 8 ];\n\n\t\t/* Return the extended error information */\n\t\tif( length <= 0 )\n\t\t\t{\n\t\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 501 );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Invalid empty HTTP request\" ) );\n\t\t\t}\n\t\tif( ( offset = strSkipNonWhitespace( lineBuffer, length ) ) > 0 )\n\t\t\tlength = offset;\n\t\tmemcpy( reqNameBuffer, lineBuffer, min( 16, length ) );\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 501 );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid HTTP request '%s'\",\n\t\t\t\t  sanitiseString( reqNameBuffer, 16, length ) ) );\n\t\t}\n\tbufPtr = lineBuffer + reqNameLen;\n\tlength -= reqNameLen;\n\n\t/* Process the ' '* * ' '* and check for the HTTP ID */\n\tif( length <= 0 || ( offset = strSkipWhitespace( bufPtr, length ) ) < 0 )\n\t\t{\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 400 );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Missing HTTP request URI\" ) );\n\t\t}\n\tbufPtr += offset;\n\tlength -= offset;\n\tif( reqType == STREAM_HTTPREQTYPE_GET && \\\n\t\t!TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\t/* Safety check, make sure that we can handle the HTTP GET */\n\t\tREQUIRES( uriInfo != NULL );\n\n\t\t/* If it's an idempotent read then the client is sending a GET \n\t\t   rather than submitting a POST, process the request details.  \n\t\t   This performs in-place decoding of (possibly encoded) data, so \n\t\t   it returns two length values, the new length after the in-place\n\t\t   decoding has occurred, and the offset of the next character of\n\t\t   data as usual */\n\t\tstatus = offset = parseUriInfo( bufPtr, length, &length, uriInfo );\n\t\t}\n\telse\n\t\t{\n\t\t/* For non-idempotent queries we don't care what the location is\n\t\t   since it's not relevant for anything, so we just skip the URI.\n\t\t   This also avoids complications with absolute vs. relative URLs,\n\t\t   character encoding/escape sequences, and so on */\n\t\tstatus = offset = strSkipNonWhitespace( bufPtr, length );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 400 );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid HTTP GET request URI\" ) );\n\t\t}\n\tbufPtr += offset;\n\tlength -= offset;\n\tif( length <= 0 || ( offset = strSkipWhitespace( bufPtr, length ) ) < 0 )\n\t\t{\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 400 );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Missing HTTP request ID/version\" ) );\n\t\t}\n\tbufPtr += offset;\n\tlength -= offset;\n\tif( length <= 0 || \\\n\t\tcryptStatusError( checkHTTPID( bufPtr, length, stream ) ) )\n\t\t{\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize, 505 );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid HTTP request ID/version\" ) );\n\t\t}\n\n\t/* Process the remaining header lines.  ~32 bytes is the minimum-size\n\t   object that can be returned from any HTTP-based message which is\n\t   exchanged by cryptlib, this being a TSP request */\n\tinitHeaderInfo( &headerInfo, 32, httpDataInfo->bufSize, *flags );\n\tif( reqType == STREAM_HTTPREQTYPE_GET )\n\t\t{\n\t\t/* It's an HTTP GET, make sure that we don't try and read a body */\n\t\tSET_FLAG( headerInfo.flags, HTTP_FLAG_GET );\n\t\t}\n\tstatus = readHeaderLines( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t\t\t  &headerInfo, &isSoftError );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If it's a soft error, clear the input stream of any remaining \n\t\t   header lines */\n\t\tif( isSoftError )\n\t\t\t{\n\t\t\tint localStatus;\n\n\t\t\tlocalStatus = clearInputStream( stream, lineBuffer, \n\t\t\t\t\t\t\t\t\t\t\tlineBufSize );\n\t\t\tif( cryptStatusError( localStatus ) )\n\t\t\t\treturn( localStatus );\n\t\t\t}\n\n\t\t/* We always (try and) send an HTTP error response once we get to\n\t\t   this stage since chances are that it'll be a problem with an\n\t\t   HTTP header rather than a low-level network read problem */\n\t\tsendHTTPError( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t   headerInfo.httpStatus );\n\t\treturn( status );\n\t\t}\n\n\t/* Copy any status info back to the caller */\n\thttpDataInfo->reqType = reqType;\n\tif( reqType != STREAM_HTTPREQTYPE_GET )\n\t\thttpDataInfo->bytesAvail = headerInfo.contentLength;\n\t*flags = GET_FLAGS( headerInfo.flags, HTTP_FLAG_MAX );\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\t/* Safety check, STREAM_NHFLAG_WS_UPGRADE implies the earlier \n\t\t   STREAM_NHFLAG_GET */\n\t\tREQUIRES( uriInfo != NULL );\n\n\t\t/* Copy the protocol-related information up to the caller */\n\t\tif( headerInfo.wsProtocolLen > 0 )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( headerInfo.wsProtocolLen, 1, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( uriInfo->protocol, headerInfo.wsProtocol, \n\t\t\t\t\theaderInfo.wsProtocolLen );\n\t\t\turiInfo->protocolLen = headerInfo.wsProtocolLen;\n\t\t\t}\n\t\tREQUIRES( rangeCheck( headerInfo.wsAuthLen, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( uriInfo->auth, headerInfo.wsAuth, \n\t\t\t\theaderInfo.wsAuthLen );\n\t\turiInfo->authLen = headerInfo.wsAuthLen;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead Response Header\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an HTTP response header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int readResponseHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_LINEBUF_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int lineBufSize, \n\t\t\t\t\t\t\t   INOUT HTTP_DATA_INFO *httpDataInfo, \n\t\t\t\t\t\t\t   OUT_FLAGS_Z( HTTP ) int *flags )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tint repeatCount, persistentStatus = CRYPT_OK, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( lineBuffer, lineBufSize ) );\n\tassert( isWritePtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );\n\tassert( isWritePtr( flags, sizeof( int ) ) );\n\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES( lineBufSize >= MIN_LINEBUF_SIZE && \\\n\t\t\t  lineBufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckHttpDataInfo( httpDataInfo ) );\n\n\t/* Clear return value */\n\t*flags = HTTP_FLAG_NONE;\n\n\t/* Read the returned response header from the server, taking various\n\t   special-case conditions into account.  In theory we could also handle\n\t   the 503 \"Retry-After\" status, but there's no sensible reason why\n\t   anyone should send us this, and even if they do it'll screw up a lot\n\t   of the PKI protocols, which have timeliness constraints built in */\n\tLOOP_SMALL( repeatCount = 0, repeatCount < 5, repeatCount++ )\n\t\t{\n\t\tHTTP_HEADER_INFO headerInfo;\n\t\tBOOLEAN needsSpecialHandling = FALSE;\n\t\tBOOLEAN isSoftError, isResponseSoftError;\n\t\tint httpStatus;\n\n\t\t/* Read the response header */\n\t\tstatus = readFirstHeaderLine( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t\t\t\t\t  &httpStatus, &isResponseSoftError );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Some errors like an HTTP 404 aren't necessarily fatal in the \n\t\t\t   same way as (say) a CRYPT_ERROR_BADDATA because while the \n\t\t\t   latter means that the stream has been corrupted and we can't \n\t\t\t   continue, the former merely means that the requested item \n\t\t\t   wasn't found but we can still submit further requests */\n\t\t\tif( !isResponseSoftError )\n\t\t\t\treturn( status );\n\n\t\t\t/* If it's a special-case header (e.g. a 100 Continue) remember \n\t\t\t   that it needs special handling later, otherwise turn the read \n\t\t\t   into a no-op read that drains the input to get to the next set \n\t\t\t   of data */\n\t\t\tpersistentStatus = status;\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\tneedsSpecialHandling = TRUE;\n\t\t\t\tif( httpStatus == 100 )\n\t\t\t\t\t{\n\t\t\t\t\t/* 100 Continue is a noise status so we also drain the \n\t\t\t\t\t   input in this case */\n\t\t\t\t\t*flags |= HTTP_FLAG_NOOP;\n\t\t\t\t\t}\n\t\t\t\tif( httpStatus == 101 )\n\t\t\t\t\t*flags |= HTTP_FLAG_UPGRADE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t*flags |= HTTP_FLAG_NOOP;\n\t\t\t}\n\n\t\t/* Process the remaining header lines.  5 bytes is the minimum-size\n\t\t   object that can be returned from any HTTP-based message which is\n\t\t   exchanged by cryptlib, this being an OCSP response containing a\n\t\t   single-byte status value, i.e. SEQUENCE { ENUM x }.\n\n\t\t   A soft error at this stage is different from a response soft\n\t\t   error (for example one arising from a 403, which is a valid \n\t\t   response but not the one desired) because it's an error in an \n\t\t   HTTP header line, which is an invalid response but not a fatal\n\t\t   error.  If we get a soft error at this point we clear the\n\t\t   remaining input in order to allow further input to be processed.\n\n\t\t   If the read buffer is dynamically allocated then we allow an\n\t\t   effectively arbitrary content length, otherwise it has to fit \n\t\t   into the fixed-size read buffer.  Unfortunately since CRLs can \n\t\t   reach > 100MB in size it's not really possible to provide any \n\t\t   sensible limit on the length for dynamic-buffer reads, however\n\t\t   to avoid DoS issues we limit it to 8MB until someone complains \n\t\t   that they can't read the 150MB CRLs that their CA is issuing \n\t\t   (yes, there are CAs that are issuing 150MB CRLs) */\n\t\tinitHeaderInfo( &headerInfo, 5,\n\t\t\t\t\t\thttpDataInfo->bufferResize ? \\\n\t\t\t\t\t\t\tmin( MAX_BUFFER_SIZE, 8388608L ) : \\\n\t\t\t\t\t\t\thttpDataInfo->bufSize,\n\t\t\t\t\t\t*flags );\n\t\tstatus = readHeaderLines( stream, lineBuffer, lineBufSize,\n\t\t\t\t\t\t\t\t  &headerInfo, &isSoftError );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( isSoftError )\n\t\t\t\t{\n\t\t\t\tint localStatus;\n\n\t\t\t\tlocalStatus = clearInputStream( stream, lineBuffer, \n\t\t\t\t\t\t\t\t\t\t\t\tlineBufSize );\n\t\t\t\tif( cryptStatusError( localStatus ) )\n\t\t\t\t\treturn( localStatus );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Copy any status info back to the caller */\n\t\t*flags = GET_FLAGS( headerInfo.flags, \n\t\t\t\t\t\t\tHTTP_FLAG_MAX ) & ~HTTP_FLAG_NOOP;\n\t\thttpDataInfo->bytesAvail = headerInfo.contentLength;\n\n\t\t/* If it's not something like a redirect that needs special-case\n\t\t   handling, we're done */\n\t\tif( !needsSpecialHandling )\n\t\t\t{\n\t\t\t/* If this was a soft error due to not finding the requested \n\t\t\t   item, pass the status on to the caller.  The low-level error \n\t\t\t   information will still be present from \n\t\t\t   readFirstHeaderLine() */\n\t\t\tif( isResponseSoftError )\n\t\t\t\t{\n\t\t\t\treturn( cryptStatusError( persistentStatus ) ? \\\n\t\t\t\t\t\tpersistentStatus : CRYPT_ERROR_NOTFOUND );\n\t\t\t\t}\n\n\t\t\t/* There's no special-case handling required, we're done */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n#ifdef USE_WEBSOCKETS\n\t\tREQUIRES( httpStatus == 100 || httpStatus == 101 || \\\n\t\t\t\t  httpStatus == 301 || httpStatus == 302 || \\\n\t\t\t\t  httpStatus == 307 );\n#else\n\t\tREQUIRES( httpStatus == 100 || httpStatus == 301 || \\\n\t\t\t\t  httpStatus == 302 || httpStatus == 307 );\n#endif /* USE_WEBSOCKETS */\n\n\t\t/* If we got a 100 Continue response, try for another header that\n\t\t   follows the first one */\n\t\tif( httpStatus == 100 )\n\t\t\tcontinue;\n\n\t\t/* If we got a 101 Switching Protocols response, make sure that this\n\t\t   is allowed */\n#ifdef USE_WEBSOCKETS\n\t\tif( httpStatus == 101 )\n\t\t\t{\n\t\t\tHTTP_URI_INFO *httpUriInfo = httpDataInfo->uriInfo;\n\n\t\t\t/* If an upgrade response isn't permitted at this point, report\n\t\t\t   the error that readHTTPStatus() in http_parse.c would have\n\t\t\t   returned */\n\t\t\tif( !TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t\t\t( CRYPT_ERROR_READ, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t  \"HTTP response status: Switching Protocols\" ) );\n\t\t\t\t}\n\t\t\tENSURES( httpUriInfo != NULL );\n\t\t\t\n\t\t\t/* Copy the protocol-related information up to the caller */\n\t\t\tif( headerInfo.wsProtocolLen > 0 )\n\t\t\t\t{\n\t\t\t\tREQUIRES( rangeCheck( headerInfo.wsProtocolLen, 1, \n\t\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\t\t\tmemcpy( httpUriInfo->protocol, headerInfo.wsProtocol, \n\t\t\t\t\t\theaderInfo.wsProtocolLen );\n\t\t\t\thttpUriInfo->protocolLen = headerInfo.wsProtocolLen;\n\t\t\t\t}\n\t\t\tREQUIRES( rangeCheck( headerInfo.wsAuthLen, 1, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( httpUriInfo->auth, headerInfo.wsAuth, \n\t\t\t\t\theaderInfo.wsAuthLen );\n\t\t\thttpUriInfo->authLen = headerInfo.wsAuthLen;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_WEBSOCKETS */\n\n\t\t/* A redirect isn't permitted for anything other than an HTTP GET */\n\t\tif( !TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_GET ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t\t( CRYPT_ERROR_READ, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Received invalid HTTP %d redirect during message \"\n\t\t\t\t\t  \"exchange\", httpStatus ) );\n\t\t\t}\t\t\t\n\n\t\t/* If we got a 301, 302, or 307 Redirect then in theory we should\n\t\t   proceed roughly as per the code below, however in practice it's\n\t\t   not nearly as simple as this, because what we're in effect doing\n\t\t   is taking a stream and replacing it with a completely new stream\n\t\t   (different host/abs-path/query info, new socket with optional\n\t\t   proxy handling, etc etc).  One way to do this would be to read\n\t\t   the new location into the current stream buffer and pass it back\n\t\t   with a special status telling the stream-level code to create a\n\t\t   new stream, clean up the old one, and perform a deep copy of the\n\t\t   new stream over to the old one.  We'll leave this for a time when\n\t\t   it's really needed.\n\n\t\t   A less problematic variant occurs when the GET redirects to a \n\t\t   different abs-path on the same server, which just requires \n\t\t   resubmitting the GET with a different abs-path.\n\n\t\t   In addition the semantics of the following pseudocode don't quite\n\t\t   match those of RFC 2616/7230,1,2,3,4,... because of the HTTP-as-a-\n\t\t   substrate use rather than direct use in a browser.  Specifically, \n\t\t   anything other than a GET for a 302 or 307 isn't supposed to \n\t\t   perform an automatic redirect without asking the user, because of \n\t\t   concerns that it'll change the semantics of the request.  However \n\t\t   since we're not an interactive web browser there's no way that we \n\t\t   can ask a user for redirect permission, and in any case since \n\t\t   we're merely using HTTP as a substrate for a cryptographically\n\t\t   protected PKI message (and specifically assuming that the HTTP\n\t\t   layer is completely insecure), any problems will be caught by the\n\t\t   crypto protocol layer */\n#if 0\n\t\tif( !*location )\n\t\t\treturn( CRYPT_ERROR_READ );\n\t\tnetStream->closeSocketFunction( stream );\n\t\tclFree( \"readResponseHeader\", netStream->host );\n\t\tnetStream->host = NULL;\n\t\tstatus = parseLocation( stream, location );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_READ );\n#endif /* 0 */\n\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t( CRYPT_ERROR_READ, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Unable to process HTTP %d redirect\", httpStatus ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* We used up our maximum number of retries, bail out */\n\tretExt( CRYPT_ERROR_READ,\n\t\t\t( CRYPT_ERROR_READ, NETSTREAM_ERRINFO, \n\t\t\t  \"Encountered more than %d HTTP retry/redirect requests\", 5 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Access Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read data from an HTTP stream.  This has a nonstandard interpretation of\n   the read buffer in that it's not a direct pointer to the read buffer but\n   to an HTTP_DATA_INFO structure that contains additional metadata about \n   the HTTP read.  For this reason it's an INOUT_BUFFER rather than an \n   OUT_BUFFER */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT_BUFFER( maxLength, *length ) void *buffer, \n\t\t\t\t\t\t IN_LENGTH_FIXED( sizeof( HTTP_DATA_INFO ) ) \\\n\t\t\t\t\t\t\tconst int maxLength, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *length )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tHTTP_DATA_INFO *httpDataInfo = ( HTTP_DATA_INFO * ) buffer;\n\tchar headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];\n\tint flags = HTTP_FLAG_NONE, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( httpDataInfo->uriInfo == NULL || \\\n\t\t\tisWritePtr( httpDataInfo->uriInfo, sizeof( HTTP_URI_INFO ) ) );\n\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength == sizeof( HTTP_DATA_INFO ) );\n\tREQUIRES( sanityCheckHttpDataInfo( httpDataInfo ) );\n\tREQUIRES( !TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) || \\\n\t\t\t  httpDataInfo->uriInfo != NULL );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Check whether the other side has indicated that it closed the \n\t   connection after the previous message was read.  This operates at a \n\t   different level to the usual stream-level connection management \n\t   because the network connection may still be open but any further \n\t   attempts to do anything with it will return an error */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGR ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_COMPLETE,\n\t\t\t\t( CRYPT_ERROR_COMPLETE, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Peer has closed the connection via HTTP 'Connection: \"\n\t\t\t\t  \"close'\" ) );\n\t\t}\n\n\t/* Read the HTTP packet header */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) )\n\t\t{\n\t\tstatus = readRequestHeader( stream, headerBuffer, HTTP_LINEBUF_SIZE,\n\t\t\t\t\t\t\t\t\thttpDataInfo, &flags );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readResponseHeader( stream, headerBuffer, HTTP_LINEBUF_SIZE,\n\t\t\t\t\t\t\t\t\t httpDataInfo, &flags );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\thttpDataInfo->bytesAvail > httpDataInfo->bufSize )\n\t\t\t{\n\t\t\tvoid *newBuffer;\n\n\t\t\tREQUIRES( httpDataInfo->bytesAvail > MIN_LINEBUF_SIZE && \\\n\t\t\t\t\t  httpDataInfo->bytesAvail < MAX_BUFFER_SIZE );\n\n\t\t\t/* readResponseHeader() will only allow content larger than the \n\t\t\t   buffer size if it's marked as a resizeable buffer */\n\t\t\tREQUIRES( httpDataInfo->bufferResize == TRUE );\n\n\t\t\t/* Adjust the read buffer size to handle the extra data and \n\t\t\t   record the details of the resized buffer */\n\t\t\tnewBuffer = safeBufferAlloc( httpDataInfo->bytesAvail );\n\t\t\tif( newBuffer == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tzeroise( httpDataInfo->buffer, httpDataInfo->bufSize );\n\t\t\tsafeBufferFree( httpDataInfo->buffer );\n\t\t\thttpDataInfo->buffer = newBuffer;\n\t\t\thttpDataInfo->bufSize = httpDataInfo->bytesAvail;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We didn't dynically resize the buffer, let the caller know */\n\t\t\thttpDataInfo->bufferResize = FALSE;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( httpDataInfo->bytesAvail <= httpDataInfo->bufSize );\n\n\tREQUIRES( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) || \\\n\t\t\t  ( httpDataInfo->reqType != STREAM_HTTPREQTYPE_NONE ) );\n\n\t/* If we're the server and the client sends us an HTTP GET, all of the \n\t   information was contained in the header and we're done */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t( httpDataInfo->reqType == STREAM_HTTPREQTYPE_GET ) )\n\t\t{\n\t\t*length = maxLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the peer has sent us a protocol upgrade request, all of the \n\t   information was contained in the header and we're done */\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\t*length = maxLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read the payload data from the client/server */\n\tstatus = bufferedTransportRead( stream, httpDataInfo->buffer, \n\t\t\t\t\t\t\t\t\thttpDataInfo->bytesAvail, \n\t\t\t\t\t\t\t\t\t&httpDataInfo->bytesTransferred, \n\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( httpDataInfo->bytesTransferred < httpDataInfo->bytesAvail )\n\t\t{\n\t\t/* We timed out before reading all of the data.  Usually this will \n\t\t   be reported as a CRYPT_ERROR_TIMEOUT by the lower-level read\n\t\t   routines, however due to the multiple layers of I/O layering that \n\t\t   are possible we perform an explicit check here to make sure that \n\t\t   we got everything */\n\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO, \n\t\t\t\t  \"HTTP read timed out before all data could be read, only \"\n\t\t\t\t  \"got %d of %d bytes\", httpDataInfo->bytesTransferred, \n\t\t\t\t  httpDataInfo->bytesAvail ) );\n\t\t}\n\n\t/* If it's a plain-text error message, return it to the caller */\n\tif( ( flags & HTTP_FLAG_TEXTMSG ) && !httpDataInfo->responseIsText )\n\t\t{\n\t\tBYTE *byteBufPtr = httpDataInfo->buffer;\n\n\t\t/* Usually a body returned as plain text is an error message that\n\t\t   (for some reason) is sent as content rather than an HTTP error,\n\t\t   however in some unusual cases the content will be the requested\n\t\t   object marked as plain text.  We try and filter out genuine PKI\n\t\t   data erroneously marked as text by requiring that the request is \n\t\t   over a minimum size (most error messages are quite short) and \n\t\t   that the first bytes match what would be seen in a PKI object \n\t\t   such as a cert or CRL */\n\t\tif( httpDataInfo->bytesAvail < 256 || ( byteBufPtr[ 0 ] != 0x30 ) || \\\n\t\t\t!( byteBufPtr[ 1 ] & 0x80 ) || \\\n\t\t\t( isAlpha( byteBufPtr[ 2 ] ) && isAlpha( byteBufPtr[ 3 ] ) && \\\n\t\t\t  isAlpha( byteBufPtr[ 4 ] ) ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t\t( CRYPT_ERROR_READ, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"HTTP server reported: '%s'\",\n\t\t\t\t\t  sanitiseString( byteBufPtr, \\\n\t\t\t\t\t\t\t\t\t  httpDataInfo->bufSize,\n\t\t\t\t\t\t\t\t\t  min( httpDataInfo->bytesTransferred, \\\n\t\t\t\t\t\t\t\t\t\t   MAX_ERRMSG_SIZE - 32 ) ) ) );\n\t\t\t}\n\t\t}\n\n\t/* If we're reading chunked data, drain the input by processing the\n\t   trailer.  The reason why there can be extra header lines at the end\n\t   of the chunked data is because it's designed to be an indefinite-\n\t   length streamable format that doesn't require buffering the entire\n\t   message before emitting it.  Since some header information may not be\n\t   available until the entire message has been generated, the HTTP \n\t   specification makes provisions for adding further header lines as a \n\t   trailer.  In theory we should check for the HTTP_FLAG_TRAILER flag \n\t   before reading trailer lines rather than just swallowing the last \n\t   CRLF, however the \"Trailer:\" header wasn't added until RFC 2616 (RFC \n\t   2068 didn't have it) so we can't rely on its presence.  Normally we \n\t   wouldn't have to worry about trailer data, but if it's an HTTP 1.1 \n\t   persistent connection then we need to clear the way for the next lot \n\t   of data */\n\tif( flags & HTTP_FLAG_CHUNKED )\n\t\t{\n\t\tstatus = readTrailerLines( stream, headerBuffer,\n\t\t\t\t\t\t\t\t   HTTP_LINEBUF_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t*length = maxLength;\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerHTTP( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( netStream->readFunction, readFunction );\n\tsetStreamLayerHTTPwrite( netStream );\n\n\t/* The default HTTP operation type is POST, since in most cases it's \n\t   being used as a substrate by a PKI protocol */\n\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_POST );\n\n\t/* HTTP provides its own data-size and flow-control indicators so we\n\t   don't want the higher-level code to try and do this for us */\n\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_ENCAPS );\n\t}\n#endif /* USE_HTTP */\n"
  },
  {
    "path": "deps/cl345/io/http_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib HTTP Write Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"http.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/http.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HTTP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encode a string as per RFC 1866 (although the list of characters that \n   need to be escaped is itself given in RFC 2396, section 2.2 \"Reserved \n   Characters\").  Characters that are permitted/not permitted are:\n\n\t !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n\tx..x.xx....x...xxxxxxxxxxxx.xxxxx\n\n   Because of this it's easier to check for the most likely permitted\n   characters (alphanumerics) first, and only then to check for any special-\n   case characters */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int encodeRFC1866( INOUT STREAM *headerStream, \n\t\t\t\t\t\t  IN_BUFFER( stringLength) const char *string, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int stringLength )\n\t{\n\tstatic const char allowedChars[] = \"$-_.!*'(),\\\"/\\x00\\x00\";\n\t\t\t\t\t  /* RFC 1738 section 2.2 \"URL Character Encoding \n\t\t\t\t\t\t Issues\" + '/' */\n\tint index, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( headerStream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( stringLength ) );\n\n\tLOOP_MAX( index = 0, index < stringLength, index++ )\n\t\t{\n\t\tconst int ch = byteToInt( string[ index ] );\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\tif( isAlnum( ch ) )\n\t\t\t{\n\t\t\tstatus = sputc( headerStream, ch );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( ch == ' ' )\n\t\t\t{\n\t\t\tstatus = sputc( headerStream, '+' );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcontinue;\n\t\t\t}\n\t\tLOOP_MED_ALT( i = 0, \n\t\t\t\t\t  allowedChars[ i ] != '\\0' && \\\n\t\t\t\t\t\tch != allowedChars[ i ] && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( allowedChars, char ), i++ );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( allowedChars, char ) );\n\t\tif( allowedChars[ i ] != '\\0' )\n\t\t\t{\n\t\t\t/* It's in the allowed-chars list, output it verbatim */\n\t\t\tsputc( headerStream, ch );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tchar escapeString[ 8 + 8 ];\n\t\t\tint escapeStringLen;\n\n\t\t\t/* It's a special char, escape it */\n\t\t\tescapeStringLen = sprintf_s( escapeString, 8, \"%%%02X\", ch );\n\t\t\tENSURES( escapeStringLen > 0 && escapeStringLen < 8 );\n\t\t\tstatus = swrite( headerStream, escapeString, escapeStringLen );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* If we time out when sending HTTP header data this would usually be \n   reported as a CRYPT_ERROR_TIMEOUT by the lower-level network I/O \n   routines, however due to the multiple layers of I/O and the fact that to \n   the caller the write of the out-of-band HTTP header data (which can occur \n   as part of a standard HTTP write, but also in a GET or when sending an \n   error response) is invisible, we have to perform an explicit check to \n   make sure that we sent everything */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendHTTPData( INOUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( length ) void *buffer, \n\t\t\t\t  IN_LENGTH const int length, \n\t\t\t\t  IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tint bytesWritten, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t  flags == TRANSPORT_FLAG_FLUSH );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tstatus = bufferedTransportWrite( stream, buffer, length, &bytesWritten, \n\t\t\t\t\t\t\t\t\t flags );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Network-level error, the lower-level layers have reported the \n\t\t   error details */\n\t\treturn( status );\n\t\t}\n\tif( bytesWritten < length )\n\t\t{\n\t\t/* The write timed out, convert the incomplete HTTP header write to \n\t\t   the appropriate timeout error */\n\t\tretExt( CRYPT_ERROR_TIMEOUT, \n\t\t\t\t( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO, \n\t\t\t\t  \"HTTP write timed out before all data could be written\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Request Header\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write an HTTP request header.  The forceGet flag is used when we should \n   be using a POST but a broken server forces the use of a GET */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeReqMethod( INOUT STREAM *stream, \n\t\t\t\t\t\t   const NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t   const BOOLEAN usePost )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( usePost == TRUE || usePost == FALSE );\n\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_TUNNEL ) )\n\t\tswrite( stream, \"CONNECT \", 8 );\n\telse\n\t\t{\n\t\tif( usePost )\n\t\t\tswrite( stream, \"POST \", 5 );\n\t\telse\n\t\t\tswrite( stream, \"GET \", 4 );\n\t\t}\n\tif( TEST_FLAG( netStream->nhFlags,\n\t\t\t\t   STREAM_NHFLAG_PROXY | STREAM_NHFLAG_TUNNEL ) )\n\t\t{\n\t\t/* If we're going through an HTTP proxy/tunnel, send an absolute URL \n\t\t   rather than just the relative location */\n\t\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_PROXY ) )\n\t\t\tswrite( stream, \"http://\", 7 );\n\t\tstatus = swrite( stream, netStream->host, netStream->hostLen );\n\t\tif( cryptStatusOK( status ) && netStream->port != 80 )\n\t\t\t{\n\t\t\tchar portString[ 16 + 8 ];\n\t\t\tint portStringLength;\n\n\t\t\tportStringLength = sprintf_s( portString, 16, \":%d\", \n\t\t\t\t\t\t\t\t\t\t  netStream->port );\n\t\t\tENSURES( portStringLength > 0 && portStringLength < 16 );\n\t\t\tstatus = swrite( stream, portString, portStringLength );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( !TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_TUNNEL ) )\n\t\t{\n\t\tif( netStream->path != NULL && netStream->pathLen > 0 )\n\t\t\t{\n\t\t\tstatus = swrite( stream, netStream->path, \n\t\t\t\t\t\t\t netStream->pathLen );\n\t\t\t}\n\t\telse\n\t\t\tstatus = sputc( stream, '/' );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeReqURI( INOUT STREAM *stream, \n\t\t\t\t\t\tIN const HTTP_REQ_INFO *httpReqInfo )\n\t{\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( httpReqInfo, sizeof( HTTP_REQ_INFO * ) ) );\n\n\t/* If there's no additional URI data present then we're done */\n\tif( httpReqInfo->attributeLen == 0 && httpReqInfo->valueLen == 0 && \\\n\t\thttpReqInfo->extraDataLen == 0 )\n\t\treturn( CRYPT_OK );\n\n\tREQUIRES( httpReqInfo->attributeLen > 0 && \\\n\t\t\t  httpReqInfo->valueLen > 0 );\n\n\t/* Send optional additional request information:\n\n\t\t...?attribute=value&extraData */\n\tsputc( stream, '?' );\n\tswrite( stream, httpReqInfo->attribute, httpReqInfo->attributeLen );\n\tsputc( stream, '=' );\n\tstatus = encodeRFC1866( stream, httpReqInfo->value, \n\t\t\t\t\t\t\thttpReqInfo->valueLen );\n\tif( cryptStatusOK( status ) && httpReqInfo->extraDataLen > 0 )\n\t\t{\n\t\tsputc( stream, '&' );\n\t\tstatus = swrite( stream, httpReqInfo->extraData, \n\t\t\t\t\t\t httpReqInfo->extraDataLen );\n\t\t}\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeReqTrailer( INOUT STREAM *stream, \n\t\t\t\t\t\t\tconst NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* If it's an HTTP 1.0 request we just write the basic header */\n\tif( isHTTP10( netStream ) )\n\t\t{\n\t\tswrite( stream, \" HTTP/1.0\\r\\n\", 11 );\n\t\treturn( swrite( stream, \"Connection: keep-alive\\r\\n\", 24 ) );\n\t\t}\n\n\t/* HTTP 1.1 has an addition Host: header, as well as other situation-\n\t   specific headers, present */\n\tswrite( stream, \" HTTP/1.1\\r\\nHost: \", 17 );\n\tswrite( stream, netStream->host, netStream->hostLen );\n#ifdef USE_WEBSOCKETS\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\treturn( swrite( stream, \"\\r\\n\", 2 ) );\n#endif /* USE_WEBSOCKETS */\n\tswrite( stream, \"\\r\\n\", 2 );\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGW ) )\n\t\treturn( swrite( stream, \"Connection: close\\r\\n\", 19 ) );\n\n\t/* The following shouldn't be required for HTTP 1.1 but there are a \n\t   sufficient number of broken caches and proxies around that we need to \n\t   include it for the ones that helpfully close the *HTTP 1.1 \n\t   persistent* connection for us if they don't see an HTTP 1.0 keepalive \n\t   in the header */\n\treturn( swrite( stream, \"Connection: keep-alive\\r\\n\", 24 ) );\n\t}\n\n#ifdef USE_WEBSOCKETS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeReqUpgradeHeaders( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   IN const HTTP_REQ_INFO *httpReqInfo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( httpReqInfo, sizeof( HTTP_REQ_INFO * ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( httpReqInfo->authLen ) );\n\n\t/* We're doing a WebSockets protocol upgrade, write the necessary \n\t   upgrade headers */\n\tswrite( stream, \"Upgrade: websocket\\r\\n\", 20 );\n\tswrite( stream, \"Connection: upgrade\\r\\n\", 21 );\n\tswrite( stream, \"Sec-WebSocket-Key: \", 19 );\n\tswrite( stream, httpReqInfo->auth, httpReqInfo->authLen );\n\tswrite( stream, \"\\r\\n\", 2 );\n\tif( httpReqInfo->protocolLen > 0 )\n\t\t{\n\t\tswrite( stream, \"Sec-WebSocket-Protocol: \", 24 );\n\t\tswrite( stream, httpReqInfo->protocol, httpReqInfo->protocolLen ); \n\t\tswrite( stream, \"\\r\\n\", 2 );\n\t\t}\n\tswrite( stream, \"Sec-Websocket-Version: 13\\r\\n\", 27 );\n\treturn( swrite( stream, \"\\r\\n\", 2 ) );\n\t}\n#endif /* USE_WEBSOCKETS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeContentHeaders( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tIN_BUFFER( contentTypeLen ) \\\n\t\t\t\t\t\t\t\t\tconst char *contentType, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int contentTypeLen, \n\t\t\t\t\t\t\t\tIN_LENGTH const int contentLength )\n\t{\n\tchar lengthString[ 16 + 8 ];\n\tint lengthStringLength;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( contentType, contentTypeLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( contentTypeLen ) );\n\tREQUIRES( contentLength > 0 && contentLength < MAX_BUFFER_SIZE );\n\n\t/* In terms of cacheing, there are two control directives that we're\n\t   interested in, no-cache and no-store.  The HTTP 1.0 no-cache doesn't \n\t   mean that the data won't be cached, merely that it has to be re-\n\t   validated on each fetch, while the HTTP 1.1 no-store actually means\n\t   what no-cache would seem to mean, that the data will never be stored/\n\t   cached.  However, no-store was meant mostly as a privacy mechanism,\n\t   indicating that a cache shouldn't store user credentials or PII.  In\n\t   the case of browsers, in order to get what you'd expect from no-cache\n\t   you need to use both no-cache and no-store, with different ones\n\t   affecting different browsers, and with the additional twist that some\n\t   browsers implement no-cache like it was no-store */\n\tswrite( stream, \"Content-Type: \", 14 );\n\tswrite( stream, contentType, contentTypeLen );\n\tswrite( stream, \"\\r\\nContent-Length: \", 18 );\n\tlengthStringLength = sprintf_s( lengthString, 16, \"%d\", \n\t\t\t\t\t\t\t\t\tcontentLength );\n\tENSURES( lengthStringLength > 0 && lengthStringLength < 16 );\n\tswrite( stream, lengthString, lengthStringLength );\n\tswrite( stream, \"\\r\\nCache-Control: no-cache, no-store\\r\\n\", 37 );\n\treturn( swrite( stream, \"\\r\\n\", 2 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeRequestHeader( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_OPT const HTTP_REQ_INFO *httpReqInfo,\n\t\t\t\t\t\tIN_BUFFER_OPT( contentTypeLen ) const char *contentType, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int contentTypeLen, \n\t\t\t\t\t\tIN_LENGTH_Z const int contentLength,\n\t\t\t\t\t\tconst BOOLEAN forceGet )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTREAM headerStream;\n\tchar headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];\n\tconst int transportFlag = ( contentLength > 0 && !forceGet ) ? \\\n\t\t\t\t\t\t\t  TRANSPORT_FLAG_NONE : TRANSPORT_FLAG_FLUSH;\n\tint headerLength DUMMY_INIT, status DUMMY_INIT;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( httpReqInfo == NULL ) || \\\n\t\t\tisReadPtr( httpReqInfo, sizeof( HTTP_REQ_INFO * ) ) );\n\tassert( ( contentLength == 0 && contentType == NULL && \\\n\t\t\t  contentTypeLen == 0 ) || \\\n\t\t\t( contentLength >= 1 && \\\n\t\t\t  isReadPtrDynamic( contentType, contentTypeLen ) ) );\n\t\n\tREQUIRES( ( contentLength == 0 && contentType == NULL && \\\n\t\t\t\tcontentTypeLen == 0 ) || \\\n\t\t\t  ( contentLength > 0 && contentLength < MAX_BUFFER_SIZE && \\\n\t\t\t    contentType != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( contentTypeLen ) ) );\n\tREQUIRES( ( httpReqInfo == NULL ) || \\\n\t\t\t  ( httpReqInfo != NULL && \\\n\t\t\t\t( ( httpReqInfo->attributeLen == 0 && \\\n\t\t\t\t\thttpReqInfo->valueLen == 0 ) || \\\n\t\t\t\t  ( httpReqInfo->valueLen > 0 ) ) ) );\n\tREQUIRES( forceGet == TRUE || forceGet == FALSE );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tsMemOpen( &headerStream, headerBuffer, HTTP_LINEBUF_SIZE );\n\tstatus = writeReqMethod( &headerStream, netStream,\n\t\t\t\t\t\t\t ( contentLength > 0 && !forceGet ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE );\n\tENSURES( cryptStatusOK( status ) );\n\tif( httpReqInfo != NULL )\n\t\t{\n\t\tstatus = writeReqURI( &headerStream, httpReqInfo );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\tstatus = writeReqTrailer( &headerStream, netStream );\n\tENSURES( cryptStatusOK( status ) );\n#ifdef USE_WEBSOCKETS\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\tREQUIRES( httpReqInfo != NULL );\n\t\tstatus = writeReqUpgradeHeaders( &headerStream, httpReqInfo );\n\t\t}\n\telse\n#endif /* USE_WEBSOCKETS */\n\t\t{\n\t\tif( !forceGet && contentLength > 0 )\n\t\t\t{\n\t\t\tstatus = writeContentHeaders( &headerStream, contentType, \n\t\t\t\t\t\t\t\t\t\t  contentTypeLen, contentLength );\n\t\t\t}\n\t\telse\n\t\t\tstatus = swrite( &headerStream, \"\\r\\n\", 2 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\theaderLength = stell( &headerStream );\n\tsMemDisconnect( &headerStream );\n\tENSURES( cryptStatusOK( status ) );\n\treturn( sendHTTPData( stream, headerBuffer, headerLength, \n\t\t\t\t\t\t  transportFlag ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Response Header\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write an HTTP response header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRespMethod( INOUT STREAM *stream, \n\t\t\t\t\t\t\tconst NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\tconst BOOLEAN isHTTP10 )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( isHTTP10 == TRUE || isHTTP10 == FALSE );\n\n\t/* Write the appropriate response method */\n\tif( isHTTP10 )\n\t\t{\n\t\tswrite( stream, \"HTTP/1.0 200 OK\\r\\n\", 17 );\n\t\treturn( swrite( stream, \"Connection: keep-alive\\r\\n\", 24 ) );\n\t\t}\n#ifdef USE_WEBSOCKETS\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\treturn( swrite( stream, \n\t\t\t\t\t\t\"HTTP/1.1 101 Switching Underwear\\r\\n\", 34 ) );\n\t\t}\n#endif /* USE_WEBSOCKETS */\n\tswrite( stream, \"HTTP/1.1 200 OK\\r\\n\", 17 );\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGW ) )\n\t\treturn( swrite( stream, \"Connection: close\\r\\n\", 19 ) );\n\n\t/* This shouldn't be required for HTTP 1.1 but there are a sufficient \n\t   number of broken caches and proxies around that we need to include it \n\t   for the ones that helpfully close the *HTTP 1.1 persistent* \n\t   connection for us if they don't see an HTTP 1.0 keepalive in the \n\t   header */\n\treturn( swrite( stream, \"Connection: keep-alive\\r\\n\", 24 ) );\n\t}\n\n#ifdef USE_WEBSOCKETS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeRespUpgradeHeaders( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tIN const HTTP_REQ_INFO *httpReqInfo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( httpReqInfo, sizeof( HTTP_REQ_INFO * ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( httpReqInfo->authLen ) );\n\n\t/* We're doing a WebSockets protocol upgrade, write the necessary \n\t   upgrade headers */\n\tswrite( stream, \"Upgrade: websocket\\r\\n\", 20 );\n\tswrite( stream, \"Connection: upgrade\\r\\n\", 21 );\n\tswrite( stream, \"Sec-WebSocket-Accept: \", 22 );\n\tswrite( stream, httpReqInfo->auth, httpReqInfo->authLen );\n\tswrite( stream, \"\\r\\n\", 2 );\n\tif( httpReqInfo->protocolLen > 0 )\n\t\t{\n\t\tswrite( stream, \"Sec-WebSocket-Protocol: \", 24 );\n\t\tswrite( stream, httpReqInfo->protocol, httpReqInfo->protocolLen ); \n\t\tswrite( stream, \"\\r\\n\", 2 );\n\t\t}\n\treturn( swrite( stream, \"\\r\\n\", 2 ) );\n\t}\n#endif /* USE_WEBSOCKETS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeResponseHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tIN_OPT const HTTP_REQ_INFO *httpReqInfo,\n\t\t\t\t\t\t\t\tIN_BUFFER_OPT( contentTypeLen ) \\\n\t\t\t\t\t\t\t\t\tconst char *contentType, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int contentTypeLen, \n\t\t\t\t\t\t\t\tIN_LENGTH_Z const int contentLength )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTREAM headerStream;\n\tchar headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];\n\tconst int transportFlag = ( contentLength > 0 ) ? \\\n\t\t\t\t\t\t\t  TRANSPORT_FLAG_NONE : TRANSPORT_FLAG_FLUSH;\n\tint headerLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( contentLength == 0 && contentType == NULL && \\\n\t\t\t  contentTypeLen == 0 && \\\n\t\t\t  isReadPtr( httpReqInfo, sizeof( HTTP_REQ_INFO ) ) ) || \\\n\t\t\t( contentLength >= 1 && \\\n\t\t\t  isReadPtrDynamic( contentType, contentTypeLen ) && \\\n\t\t\t  httpReqInfo == NULL ) );\n\n\tREQUIRES( ( contentLength == 0 && contentType == NULL && \\\n\t\t\t\tcontentTypeLen == 0 && httpReqInfo != NULL && \\\n\t\t\t\thttpReqInfo->authLen != 0  ) || \\\n\t\t\t  ( contentLength > 0 && contentLength < MAX_BUFFER_SIZE && \\\n\t\t\t    contentType != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( contentTypeLen ) && \\\n\t\t\t\thttpReqInfo == NULL ) );\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tsMemOpen( &headerStream, headerBuffer, HTTP_LINEBUF_SIZE );\n\tstatus = writeRespMethod( &headerStream, netStream, \n\t\t\t\t\t\t\t  isHTTP10( netStream ) );\n\tENSURES( cryptStatusOK( status ) );\n#ifdef USE_WEBSOCKETS\n\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_WS_UPGRADE ) )\n\t\t{\n\t\tREQUIRES( httpReqInfo != NULL );\n\t\tstatus = writeRespUpgradeHeaders( &headerStream, httpReqInfo );\n\t\t}\n\telse\n#endif /* USE_WEBSOCKETS */\n\t\t{\n\t\tif( contentLength > 0 )\n\t\t\t{\n\t\t\tstatus = writeContentHeaders( &headerStream, contentType, \n\t\t\t\t\t\t\t\t\t\t  contentTypeLen, contentLength );\n\t\t\t}\n\t\telse\n\t\t\tstatus = swrite( &headerStream, \"\\r\\n\", 2 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\theaderLength = stell( &headerStream );\n\tsMemDisconnect( &headerStream );\n\tENSURES( cryptStatusOK( status ) );\n\treturn( sendHTTPData( stream, headerBuffer, headerLength, \n\t\t\t\t\t\t  transportFlag ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Access Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write data to an HTTP stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writeFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_BUFFER( maxLength ) const void *buffer, \n\t\t\t\t\t\t  IN_LENGTH_FIXED( sizeof( HTTP_DATA_INFO ) ) \\\n\t\t\t\t\t\t\tconst int maxLength, \n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *length )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tHTTP_DATA_INFO *httpDataInfo = ( HTTP_DATA_INFO * ) buffer;\n\tBOOLEAN forceGet = FALSE;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\t\n\tREQUIRES( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength == sizeof( HTTP_DATA_INFO ) );\n\tREQUIRES( sanityCheckHttpDataInfo( httpDataInfo ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Send the out-of-band HTTP header data to the client or server */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) )\n\t\t{\n\t\t/* If it's an error status response, send the translated error \n\t\t   status and exit */\n\t\tif( cryptStatusError( httpDataInfo->reqStatus ) )\n\t\t\t{\n\t\t\tchar headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];\n\n\t\t\tstatus = sendHTTPError( stream, headerBuffer, HTTP_LINEBUF_SIZE,\n\t\t\t\t\t\t( httpDataInfo->reqStatus == CRYPT_ERROR_NOTFOUND ) ? \\\n\t\t\t\t\t\t\t404 : \\\n\t\t\t\t\t\t( httpDataInfo->reqStatus == CRYPT_ERROR_PERMISSION ) ? \\\n\t\t\t\t\t\t\t401 : 400 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t*length = maxLength;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tstatus = writeResponseHeader( stream, httpDataInfo->reqInfo, \n\t\t\t\t\t\t\t\t\t  httpDataInfo->contentType,\n\t\t\t\t\t\t\t\t\t  httpDataInfo->contentTypeLen,\n\t\t\t\t\t\t\t\t\t  httpDataInfo->bytesToWrite );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( TEST_FLAG( netStream->nhFlags, \n\t\t\t\t\t\t\t STREAM_NHFLAG_TUNNEL ) || \\\n\t\t\t\t  TEST_FLAG( netStream->nhFlags, \n\t\t\t\t\t\t\t STREAM_NHFLAG_GET ) || \\\n\t\t\t\t  TEST_FLAG( netStream->nhFlags, \n\t\t\t\t\t\t\t STREAM_NHFLAG_POST_AS_GET ) || \\\n\t\t\t\t  httpDataInfo->contentTypeLen > 0 );\n\t\tREQUIRES( !( TEST_FLAG( netStream->nhFlags, \n\t\t\t\t\t\t\t\tSTREAM_NHFLAG_PROXY ) && \n\t\t\t\t\t TEST_FLAG( netStream->nhFlags, \n\t\t\t\t\t\t\t\tSTREAM_NHFLAG_TUNNEL ) ) );\n\t\tREQUIRES( netStream->host != NULL && netStream->hostLen > 0 );\n\n\t\t/* If we have to override the use of the (correct) POST with the \n\t\t   (incorrect) GET in order to deal with a broken server then \n\t\t   instead of writing the full request header we write the start of \n\t\t   the \"HTTP GET...\" line and then exit, leaving the rest of the GET \n\t\t   URI to be written as the payload data */\n\t\tif( TEST_FLAG( netStream->nhFlags, STREAM_NHFLAG_POST_AS_GET ) )\n\t\t\t{\n\t\t\tstatus = writeRequestHeader( stream, httpDataInfo->reqInfo, \n\t\t\t\t\t\t\t\t\t\t NULL, 0, 0, TRUE );\n\t\t\tforceGet = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = writeRequestHeader( stream, httpDataInfo->reqInfo, \n\t\t\t\t\t\t\t\t\t\t httpDataInfo->contentType,\n\t\t\t\t\t\t\t\t\t\t httpDataInfo->contentTypeLen,\n\t\t\t\t\t\t\t\t\t\t httpDataInfo->bytesToWrite, FALSE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're sending a headers-only request, for example for a GET \n\t   request or to return an HTTP error, we're done */\n\tif( httpDataInfo->buffer == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Send the payload data to the client/server */\n\tstatus = bufferedTransportWrite( stream, httpDataInfo->buffer, \n\t\t\t\t\t\t\t\t\t httpDataInfo->bytesToWrite, \n\t\t\t\t\t\t\t\t\t &httpDataInfo->bytesTransferred, \n\t\t\t\t\t\t\t\t\t forceGet ? TRANSPORT_FLAG_NONE : \\\n\t\t\t\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_FLUSH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( forceGet )\n\t\t{\n\t\tSTREAM headerStream;\n\t\tchar headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];\n\t\tint headerLength DUMMY_INIT;\n\n\t\t/* We've been forced to override the use of a POST with a GET due to \n\t\t   a broken server so the header write was split into two parts with \n\t\t   the request data in the middle, we now have to send the remainder \n\t\t   of the header */\n\t\tsMemOpen( &headerStream, headerBuffer, HTTP_LINEBUF_SIZE );\n\t\tstatus = writeReqTrailer( &headerStream, netStream );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tstatus = swrite( &headerStream, \"\\r\\n\", 2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\theaderLength = stell( &headerStream );\n\t\tsMemDisconnect( &headerStream );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tstatus = sendHTTPData( stream, headerBuffer, headerLength, \n\t\t\t\t\t\t\t   TRANSPORT_FLAG_FLUSH );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t*length = maxLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerHTTPwrite( INOUT NET_STREAM_INFO *netStream )\n\t{\n\t/* Set the remaining access method pointers */\n\tFNPTR_SET( netStream->writeFunction, writeFunction );\n\t}\n#endif /* USE_HTTP */\n"
  },
  {
    "path": "deps/cl345/io/memory.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Memory Stream I/O Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Sanity-check the stream state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckStreamMem( const STREAM *stream )\n\t{\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\n\t/* Null streams have no internal buffer so the buffer position \n\t   indicators aren't used */\n\tif( stream->type == STREAM_TYPE_NULL )\n\t\t{\n\t\t/* Null streams, which act as data sinks, have a content-size \n\t\t   indicator so although the buffer size is zero the buffer \n\t\t   position values can be nonzero */\n\t\tif( stream->bufSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckStreamMem: Spurious null stream buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( stream->bufPos < 0 || stream->bufPos > stream->bufEnd || \n\t\t\tstream->bufEnd < 0 || stream->bufEnd >= MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckStreamMem: Null stream position\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If it's not a null stream then it has to be a memory stream */\n\tif( stream->type != STREAM_TYPE_MEMORY )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckStreamMem: Stream type\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the buffer position is within bounds:\n\n\t\t\t\t\t\t\t\t bufEnd\n\t\t\t\t\t\t\t\t\t|\n\t\t\t<------ buffer ------>\tv\n\t\t+---------------------------+\n\t\t|\t\t\t\t\t\t|\t|\n\t\t+---------------------------+\n\t\t\t\t^\t\t\t\t^\n\t\t\t\t|\t\t\t\t|\n\t\t\t bufPos\t\t\t bufEnd */\n\tif( stream->bufPos < 0 || stream->bufPos > stream->bufEnd || \\\n\t\tstream->bufEnd < 0 || stream->bufEnd > stream->bufSize || \\\n\t\tstream->bufSize <= 0 || stream->bufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckStreamMem: Position\" ));\n\t\treturn( FALSE );\n\t\t}\n\t \n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tOpen/Close Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and shut down a memory stream.  Since the return value for the \n   memory stream open functions is rarely (if ever) checked we validate the \n   buffer and length parameters later and create a read-only null stream if \n   they're invalid, so that reads and writes return error conditions if \n   they're attempted.  For the same reason we just use a basic assert() \n   rather than the stronger REQUIRES() so that we can explicitly handle any\n   parameter errors later in the code */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initMemoryStream( OUT STREAM *stream, \n\t\t\t\t\t\t\t const BOOLEAN isNullStream )\n\t{\n\t/* We don't use a REQUIRES() predicate here for the reasons given in the \n\t   comments above */\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isNullStream == TRUE || isNullStream == FALSE );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* Clear the stream data and initialise the stream structure.  Further \n\t   initialisation of stream buffer parameters will be done by the \n\t   caller */\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tstream->type = ( isNullStream ) ? STREAM_TYPE_NULL : STREAM_TYPE_MEMORY;\n\tINIT_FLAGS( stream->flags, STREAM_FLAG_NONE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkMemoryStreamParams( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tIN const void *buffer,\n\t\t\t\t\t\t\t\t\t\t/* May be unintialised for sMemOpen()\n\t\t\t\t\t\t\t\t\t\t   so we can't use IN_BUFFER */ \n\t\t\t\t\t\t\t\t\tIN_LENGTH_Z const int length )\n\t{\n\t/* We don't use a REQUIRES() predicate here for the reasons given in the \n\t   comments above */\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length > 0 && length < MAX_BUFFER_SIZE );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\t/* If there's a problem with the parameters, return an error code but\n\t   also make it a (non-readable, non-writeable) null stream with the \n\t   error state set via retIntError_Stream() so that it can be safely \n\t   used */\n\tif( length < 1 || length >= MAX_BUFFER_SIZE || \\\n\t\t!isReadPtrDynamic( buffer, length ) )\n\t\t{\n\t\tstream->type = STREAM_TYPE_NULL;\n\t\tINIT_FLAGS( stream->flags, STREAM_FLAG_READONLY );\n\t\tretIntError_Stream( stream );\n\t\t}\n\t\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownMemoryStream( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t const BOOLEAN clearStreamBuffer )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t  stream->type == STREAM_TYPE_MEMORY );\n\tREQUIRES( clearStreamBuffer == TRUE || clearStreamBuffer == FALSE );\n\n\t/* Clear the stream structure */\n\tif( clearStreamBuffer && stream->buffer != NULL && stream->bufEnd > 0 )\n\t\tzeroise( stream->buffer, stream->bufEnd );\n\tzeroise( stream, sizeof( STREAM ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Open/close a memory stream or a null stream that serves as a data sink, \n   which is useful for implementing sizeof() functions by writing data to\n   null streams.  If calling sMemOpenOpt() and the buffer parameter is NULL \n   and the length is zero this creates a null stream, otherwise is creates\n   a standard memory stream.  This is useful for functions that follow the\n   convention of being passed a null buffer for a length check and a non-\n   null buffer to produce output.\n   \n   We don't use REQUIRES() predicates for these functions for the reasons\n   given in the comments in initMemoryStream().\n\n   Note that the open/connect functions are declared with a void return \n   type, this is because they're used in hundreds of locations and the only \n   situation in which they can fail is a programming error.  Because of \n   this, problems are caught by throwing exceptions in debug builds rather \n   than having to add error handling for every case where they're used.  In \n   addition the functions always initialise the stream, setting it to an \n   invalid stream if there's an error, so there's no real need to check a\n   return value */ \n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemOpen( OUT STREAM *stream, \n\t\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t   IN_LENGTH const int length )\n\t{\n\tint status;\n\n\t/* REQUIRES() checking done in initMemoryStream() */\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\tassert( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Initialise the memory stream */\n\tstatus = initMemoryStream( stream, FALSE );\n\tENSURES_V( cryptStatusOK( status ) );\n\tstatus = checkMemoryStreamParams( stream, buffer, length );\n\tENSURES_V( cryptStatusOK( status ) );\n\tstream->buffer = buffer;\n\tstream->bufSize = length;\n\n\t/* Clear the stream buffer.  Since this can be arbitrarily large we only \n\t   clear the entire buffer in the debug version */\n#ifdef NDEBUG\n\tmemset( stream->buffer, 0, min( 16, stream->bufSize ) );\n#else\n\tmemset( stream->buffer, 0, stream->bufSize );\n#endif /* NDEBUG */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sMemNullOpen( OUT STREAM *stream )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Initialise the memory stream */\n\tstatus = initMemoryStream( stream, TRUE );\n\tENSURES_V( cryptStatusOK( status ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sMemOpenOpt( OUT STREAM *stream, \n\t\t\t\t  OUT_BUFFER_OPT_FIXED( length ) void *buffer, \n\t\t\t\t  IN_LENGTH_Z const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( buffer == NULL && length == 0 ) || \\\n\t\t\tisReadPtrDynamic( buffer, length ) );\n\n\t/* Note that the following must be given as 'buffer == NULL' without an\n\t   additional 'length == 0' because static-analysis tools can't make the\n\t   connection between 'buffer' and 'length' and will warn that the value\n\t   passed to sMemOpen() may be NULL */\n\tif( buffer == NULL )\n\t\t{\n\t\tsMemNullOpen( stream );\n\t\treturn;\n\t\t}\n\tsMemOpen( stream, buffer, length );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemClose( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckStreamMem( stream ) );\n\tREQUIRES( !TEST_FLAG( stream->flags, STREAM_FLAG_READONLY ) );\n#ifdef CONFIG_FUZZ\n\tREQUIRES( !TEST_FLAG( stream->flags, STREAM_MFLAG_PSEUDO ) );\n#endif /* CONFIG_FUZZ */\n\n\treturn( shutdownMemoryStream( stream, TRUE ) );\n\t}\n\n/* Connect/disconnect a memory stream without destroying the buffer\n   contents */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemConnect( OUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( length ) const void *buffer, \n\t\t\t\t  IN_LENGTH const int length )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length > 0 && length < MAX_BUFFER_SIZE );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\t/* Initialise the memory stream.  We don't use a REQUIRES() predicate \n\t   for the reasons given in the comments in initMemoryStream() */\n\tstatus = initMemoryStream( stream, FALSE );\n\tENSURES_V( cryptStatusOK( status ) );\n\tstatus = checkMemoryStreamParams( stream, buffer, length );\n\tENSURES_V( cryptStatusOK( status ) );\n\tstream->buffer = ( void * ) buffer;\n\tstream->bufSize = length;\n\n\t/* Initialise further portions of the stream structure.  This is a read-\n\t   only stream so what's in the buffer at the start is all we'll ever \n\t   get */\n\tstream->bufEnd = length;\n\tINIT_FLAGS( stream->flags, STREAM_FLAG_READONLY );\n\t}\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemPseudoConnect( OUT STREAM *stream, \n\t\t\t\t\t    IN_BUFFER( length ) const void *buffer,\n\t\t\t\t\t    IN_LENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( length > 0 && length < MAX_BUFFER_SIZE );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\t/* Open the stream as a standard memory stream */\n\tsMemConnect( stream, buffer, length );\n\n\t/* We've now got a standard memory stream, modify it to make it pseudo-\n\t   writeable, in the sense that written data is discarded (this also\n\t   removes the read-only flag from the standard memory stream) */\n\tINIT_FLAGS( stream->flags, STREAM_MFLAG_PSEUDO );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemDisconnect( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckStreamMem( stream ) );\n\n\treturn( shutdownMemoryStream( stream, FALSE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDirect Access Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Memory stream direct-access functions, used when the contents of a memory\n   stream need to be encrypted/decrypted/signed/MACd.  The basic \n   sMemGetDataBlock() returns a data block of a given size from the current\n   stream position, sMemGetDataBlockAbs() returns a data block from the \n   given stream position, and sMemGetDataBlockRemaining() returns a data \n   block containing all remaining data available in the stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getMemoryBlock( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( length ) void **dataPtrPtr,\n\t\t\t\t\t\t   IN_LENGTH_Z const int position, \n\t\t\t\t\t\t   IN_DATALENGTH const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES( sanityCheckStreamMem( stream ) && \\\n\t\t\t  stream->type == STREAM_TYPE_MEMORY );\n\tREQUIRES_S( position >= 0 && position <= stream->bufSize && \\\n\t\t\t\tposition < MAX_BUFFER_SIZE );\n\tREQUIRES_S( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*dataPtrPtr = NULL;\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* Make sure that there's enough data available in the stream to satisfy \n\t   the request.  We check against bufSize rather than bufEnd since the\n\t   caller may be asking for access to all remaining data space in the \n\t   stream rather than just all data read/written so far */\n\tif( position + length < 0 || \\\n\t\tposition + length > stream->bufSize )\n\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\n\t/* Return a pointer to the stream-internal buffer starting at location \n\t   'position' of length 'length' bytes */\n\t*dataPtrPtr = stream->buffer + position;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_RANGE_NOERROR( 0, MAX_BUFFER_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemDataLeft( const STREAM *stream )\n\t{\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) && \\\n\t\t\tstream->type == STREAM_TYPE_MEMORY );\n\n\t/* Check that the input parameters are in order */\n\tif( !isReadPtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* We can't use REQUIRES_S() in this case because the stream is a const \n\t   parameter so instead we return a data-left size of zero */\n\tREQUIRES_EXT( ( sanityCheckStreamMem( stream ) && \\\n\t\t\t\t\tstream->type == STREAM_TYPE_MEMORY ), 0 );\n\n\t/* If there's a problem with the stream don't try to do anything.  \n\t   Unlike the standard stream read/write functions this function simply \n\t   returns a record of internal stream state rather than reporting the \n\t   status of a stream operation, so it's not generally checked by the \n\t   caller.  To indicate an error state the best that we can do is to \n\t   report zero bytes available, which will result in an underflow error \n\t   in the caller */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( 0 );\n\n\treturn( stream->bufSize - stream->bufPos );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sMemGetDataBlock( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( dataSize ) void **dataPtrPtr, \n\t\t\t\t\t  IN_DATALENGTH const int dataSize )\n\t{\n\t/* REQUIRES() checking done in getMemoryBlock() */\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) && \\\n\t\t\tstream->type == STREAM_TYPE_MEMORY );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( dataSize > 0 && dataSize < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\n\treturn( getMemoryBlock( stream, dataPtrPtr, stream->bufPos, dataSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint sMemGetDataBlockAbs( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_DATALENGTH_Z const int position, \n\t\t\t\t\t\t OUT_BUFFER_ALLOC_OPT( dataSize ) void **dataPtrPtr, \n\t\t\t\t\t\t IN_DATALENGTH const int dataSize )\n\t{\n\t/* REQUIRES() checking done in getMemoryBlock() */\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) && \\\n\t\t\tstream->type == STREAM_TYPE_MEMORY );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( position >= 0 && position <= stream->bufSize && \\\n\t\t\tposition < MAX_BUFFER_SIZE );\n\tassert( dataSize > 0 && dataSize < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\n\treturn( getMemoryBlock( stream, dataPtrPtr, position, dataSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint sMemGetDataBlockRemaining( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( *length ) void **dataPtrPtr, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length )\n\t{\n\tconst int dataLeft = sMemDataLeft( stream );\n\tint status;\n\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) && \\\n\t\t\tstream->type == STREAM_TYPE_MEMORY );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\t\t\t/* REQUIRES() checking done in getMemoryBlock() */\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\t*length = 0;\n\n\t/* If there's no data remaining, return an underflow error */\n\tif( cryptStatusError( dataLeft ) )\n\t\treturn( dataLeft );\n\tif( dataLeft <= 0 )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\tstatus = getMemoryBlock( stream, dataPtrPtr, stream->bufPos, dataLeft );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*length = dataLeft;\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/io/net.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tNetwork Stream I/O Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\t\t\t\t/* For INVALID_SOCKET */\n#else\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\t\t\t/* For INVALID_SOCKET */\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check a network stream */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckNetStream( const NET_STREAM_INFO *netStream )\n\t{\n\tassert( isReadPtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* Check overall network stream data.  STREAM_PEER_NONE is a valid\n\t   setting, and in fact the default, since the peer type is only used to\n\t   fingerprint buggy peers */\n\tif( !isEnumRange( netStream->protocol, STREAM_PROTOCOL ) || \\\n\t\t!CHECK_FLAGS( netStream->nFlags, STREAM_NFLAG_NONE, \n\t\t\t\t\t  STREAM_NFLAG_MAX ) || \\\n\t\t!CHECK_FLAGS( netStream->nhFlags, STREAM_NHFLAG_NONE, \n\t\t\t\t\t  STREAM_NHFLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckNetStream: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( netStream->timeout < 0 || \\\n\t\tnetStream->timeout > MAX_NETWORK_TIMEOUT )\n\t\t{\n\t\t/* Servers wait around more or less indefinitely for incoming\n\t\t   connections so we allow a timeout of MAX_INTLENGTH timeout for \n\t\t   servers */\n\t\tif( !( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t\t   netStream->timeout == MAX_INTLENGTH ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Timeout\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( netStream->savedTimeout < 0 || \\\n\t\tnetStream->savedTimeout > MAX_NETWORK_TIMEOUT )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Saved timeout\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( netStream->systemType, STREAM_PEER ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckNetStream: System type\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check network-related information */\n\tif( netStream->host == NULL )\n\t\t{\n\t\tif( netStream->hostLen != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Spurious host\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( netStream->hostLen < MIN_HOST_SIZE || \\\n\t\t\tnetStream->hostLen > MAX_HOST_SIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Host\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( netStream->path == NULL )\n\t\t{\n\t\tif( netStream->pathLen != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Spurious path\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( netStream->pathLen < MIN_LOCATION_SIZE || \\\n\t\t\tnetStream->pathLen > MAX_LOCATION_SIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Path\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_USERSOCKET ) )\n\t\t{\n\t\tif( netStream->port < MIN_PORT_NUMBER || \\\n\t\t\tnetStream->port > MAX_PORT_NUMBER )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Port\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* If it's an unbuffered network stream, all buffer values must be \n\t   zero */\n\tif( netStream->writeBuffer == NULL )\n\t\t{\n\t\tif( netStream->writeBufSize != 0 || netStream->writeBufEnd != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Spurious write buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Make sure that the write buffer position is within bounds */\n\t\tif( netStream->writeBufSize <= 0 || \\\n\t\t\tnetStream->writeBufSize >= MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Write buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( netStream->writeBufEnd < 0 || \\\n\t\t\tnetStream->writeBufEnd > netStream->writeBufSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Write buffer info\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Make sure that the write buffer hasn't been corrupted */\n\t\tif( !safeBufferCheck( netStream->writeBuffer, \n\t\t\t\t\t\t\t  netStream->writeBufSize ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Write buffer corruption\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check the network stream access functions */\n\tif( !FNPTR_ISSET( netStream->writeFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->readFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportConnectFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportDisconnectFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportReadFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportWriteFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportOKFunction ) || \\\n\t\t!FNPTR_ISSET( netStream->transportCheckFunction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Access functions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !FNPTR_ISVALID( netStream->connectFunctionOpt ) || \\\n\t\t!FNPTR_ISVALID( netStream->disconnectFunctionOpt ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Optional access functions\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( DATAPTR_ISNULL( netStream->virtualStateInfo ) )\n\t\t{\n\t\tif( !FNPTR_ISNULL( netStream->virtualGetDataFunction ) || \\\n\t\t\t!FNPTR_ISNULL( netStream->virtualPutDataFunction ) || \\\n\t\t\t!FNPTR_ISNULL( netStream->virtualGetErrorInfoFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Spurious virtual functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !DATAPTR_ISSET( netStream->virtualStateInfo ) || \\\n\t\t\t!FNPTR_ISSET( netStream->virtualGetDataFunction ) || \\\n\t\t\t!FNPTR_ISSET( netStream->virtualPutDataFunction ) || \\\n\t\t\t!FNPTR_ISSET( netStream->virtualGetErrorInfoFunction ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckNetStream: Virtual functions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check for the use of a proxy when opening a stream */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 8 ) ) \\\nstatic int checkForProxy( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t  IN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t\t\t  const NET_CONNECT_INFO *connectInfo,\n\t\t\t\t\t\t  IN_BUFFER( hostLen ) const char *host, \n\t\t\t\t\t\t  IN_LENGTH_DNS const int hostLen,\n\t\t\t\t\t\t  OUT_BUFFER( proxyUrlMaxLen, *proxyUrlLen ) \\\n\t\t\t\t\t\t\tchar *proxyUrlBuffer, \n\t\t\t\t\t\t  IN_LENGTH_DNS const int proxyUrlMaxLen, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( proxyUrlMaxLen ) \\\n\t\t\t\t\t\t\tint *proxyUrlLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\tassert( isWritePtrDynamic( proxyUrlBuffer, proxyUrlMaxLen ) );\n\tassert( isWritePtr( proxyUrlLen, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( protocol, STREAM_PROTOCOL ) );\n\tREQUIRES( proxyUrlMaxLen > 10 && proxyUrlMaxLen <= MAX_DNS_SIZE );\n\n\t/* Clear return value */\n\tmemset( proxyUrlBuffer, 0, min( 16, proxyUrlMaxLen ) );\n\t*proxyUrlLen = 0;\n\n\t/* Check for a local connection, which always bypasses the proxy.  We\n\t   only use the case-insensitive string compares for the text-format\n\t   host names since the numeric forms don't need this.  In addition\n\t   since the IPv4 localhost is a /8, we check for anything with a\n\t   \"127.\" prefix */\n\tif( ( hostLen > 4 && !memcmp( host, \"127.\", 4 ) ) || \\\n\t\t( hostLen == 3 && !memcmp( host, \"::1\", 3 ) ) || \\\n\t\t( hostLen == 9 && !strCompare( host, \"localhost\", 9 ) ) || \\\n\t\t( hostLen == 10 && !strCompare( host, \"localhost.\", 10 ) ) )\n\t\t/* Are you local? */\n\t\t{\n\t\t/* This is a local socket!  We'll have no proxies here! */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Check to see whether we're going through a proxy.  First we check for \n\t   a protocol-specific HTTP proxy (if appropriate), if there's none then \n\t   we check for the more generic case of a SOCKS proxy */\n\tif( protocol == STREAM_PROTOCOL_HTTP )\n\t\t{\n\t\t/* Check whether there's an HTTP proxy configured */\n\t\tsetMessageData( &msgData, proxyUrlBuffer, proxyUrlMaxLen );\n\t\tstatus = krnlSendMessage( connectInfo->iUserObject,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_HTTP_PROXY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( connectInfo->options == NET_OPTION_HOSTNAME )\n\t\t\t\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_PROXY );\n\t\t\telse\n\t\t\t\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_TUNNEL );\n\t\t\t*proxyUrlLen = msgData.length;\n\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\t}\n\n\t/* Check whether there's a SOCKS proxy configured */\n\tsetMessageData( &msgData, proxyUrlBuffer, proxyUrlMaxLen );\n\tstatus = krnlSendMessage( connectInfo->iUserObject,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_OPTION_NET_SOCKS_SERVER );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*proxyUrlLen = msgData.length;\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* There's no proxy configured */\n\treturn( CRYPT_OK );\n\t}\n\n/* Connect a network stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int openNetworkConnection( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t  IN_ENUM( NET_OPTION ) \\\n\t\t\t\t\t\t\t\t\tconst NET_OPTION_TYPE options,\n\t\t\t\t\t\t\t\t  IN_BUFFER_OPT( proxyUrlLen ) const char *proxyUrl, \n\t\t\t\t\t\t\t\t  IN_LENGTH_DNS_Z const int proxyUrlLen )\n\t{\n\tconst STM_TRANSPORTCONNECT_FUNCTION transportConnectFunction = \\\n\t\t\t\t\t\t( STM_TRANSPORTCONNECT_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->transportConnectFunction );\n\tURL_INFO urlInfo;\n\tchar urlBuffer[ MAX_DNS_SIZE + 8 ];\n\tconst char *url = proxyUrl;\n\tint urlLen = proxyUrlLen, status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( proxyUrl, proxyUrlLen ) );\n\n\tREQUIRES( isEnumRange( options, NET_OPTION ) );\n\tREQUIRES( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \\\n\t\t\t  ( proxyUrl != NULL && \\\n\t\t\t\tproxyUrlLen > 0 && proxyUrlLen <= MAX_DNS_SIZE ) );\n\tREQUIRES( transportConnectFunction != NULL );\n\n\t/* If we're using an already-active network socket supplied by the\n\t   user, there's nothing to do */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_USERSOCKET ) )\n\t\t{\n\t\t/* If it's a dummy open to check parameters that can't be validated\n\t\t   at a higher level then we pass the info on down to the low-level \n\t\t   checking routines */\n\t\tif( options == NET_OPTION_NETWORKSOCKET_DUMMY )\n\t\t\t{\n\t\t\tconst STM_TRANSPORTCHECK_FUNCTION transportCheckFunction = \\\n\t\t\t\t\t\t( STM_TRANSPORTCHECK_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->transportCheckFunction );\n\n\t\t\tREQUIRES( transportCheckFunction != NULL );\n\n\t\t\treturn( transportCheckFunction( netStream ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're not going via a proxy, perform a direct open */\n\tif( proxyUrl == NULL )\n\t\t{\n\t\treturn( transportConnectFunction( netStream, netStream->host, \n\t\t\t\t\t\t\t\t\t\t  netStream->hostLen, netStream->port ) );\n\t\t}\n\n\t/* We're going via a proxy, if the user has specified automatic proxy\n\t   detection try and locate the proxy information.  This only works for\n\t   Windows which has built-in proxy discovery support, for everything \n\t   else it's no-op'd out */\n\tif( !strCompareZ( proxyUrl, \"[Autodetect]\" ) )\n\t\t{\n\t\tstatus = findProxyUrl( urlBuffer, MAX_DNS_SIZE, &urlLen, \n\t\t\t\t\t\t\t   netStream->host, netStream->hostLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The proxy URL was invalid, provide more information for the\n\t\t\t   caller */\n\t\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t\t( CRYPT_ERROR_OPEN, NETSTREAM_ERRINFO, \n\t\t\t\t\t  \"Couldn't auto-detect HTTP proxy\" ) );\n\t\t\t}\n\t\turl = urlBuffer;\n\t\t}\n\n\t/* Process the proxy details, either as supplied by the caller or using\n\t   the auto-detected URL from above.  Since this is an HTTP proxy we \n\t   specify the default port as port 80 */\n\tstatus = parseURL( &urlInfo, url, urlLen, 80, URL_TYPE_HTTP, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The proxy URL was invalid, provide more information for the\n\t\t   caller */\n\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t( CRYPT_ERROR_OPEN, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Invalid HTTP proxy URL\" ) );\n\t\t}\n\n\t/* Since we're going via a proxy, open the connection to the proxy\n\t   rather than directly to the target system.  */\n\treturn( transportConnectFunction( netStream, urlInfo.host, \n\t\t\t\t\t\t\t\t\t  urlInfo.hostLen, urlInfo.port ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tNetwork Stream Init/Shutdown Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the network stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int initStream( OUT STREAM *stream, \n\t\t\t\t\t   OUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t   IN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t\t   INOUT const NET_CONNECT_INFO *connectInfo,\n\t\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tint timeout, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\n\tREQUIRES( isEnumRange( protocol, STREAM_PROTOCOL ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Set up the basic network stream info */\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tstream->type = STREAM_TYPE_NETWORK;\n\tINIT_FLAGS( stream->flags, STREAM_FLAG_NONE );\n\tmemset( netStream, 0, sizeof( NET_STREAM_INFO ) );\n\tnetStream->protocol = protocol;\n\tnetStream->port = connectInfo->port;\n\tnetStream->netSocket = netStream->listenSocket = INVALID_SOCKET;\n\tif( isServer )\n\t\tINIT_FLAGS( netStream->nFlags, STREAM_NFLAG_ISSERVER );\n\telse\n\t\tINIT_FLAGS( netStream->nFlags, STREAM_NFLAG_NONE );\n\tif( protocol == STREAM_PROTOCOL_UDP )\n\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM );\n\tINIT_FLAGS( netStream->nhFlags, STREAM_NHFLAG_NONE );\n\n\t/* Initialise the virtual and optional access method pointers.  These \n\t   aren't necessarily set by access functions so we have to explicitly \n\t   clear them here */ \n\tDATAPTR_SET( netStream->virtualStateInfo, NULL );\n\tFNPTR_SET( netStream->virtualGetDataFunction, NULL );\n\tFNPTR_SET( netStream->virtualPutDataFunction, NULL );\n\tFNPTR_SET( netStream->virtualGetErrorInfoFunction, NULL );\n\tFNPTR_SET( netStream->connectFunctionOpt, NULL );\n\tFNPTR_SET( netStream->disconnectFunctionOpt, NULL );\n\n\t/* Set up the stream timeout information.  While we're connecting the \n\t   stream timeout is the connect timeout.  Once we've connected it's set\n\t   to the data transfer timeout, so initially we set the stream timeout\n\t   to the connect timeout and the saved timeout to the data transfer\n\t   timeout */\n\tif( connectInfo->connectTimeout != CRYPT_ERROR )\n\t\t{\n\t\t/* There's an explicit timeout specified, use that */\n\t\ttimeout = connectInfo->connectTimeout;\n\t\t}\n\telse\n\t\t{\n\t\t/* Get the default timeout from the user object */\n\t\tstatus = krnlSendMessage( connectInfo->iUserObject, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_CONNECTTIMEOUT );\n\t\tif( cryptStatusError( status ) )\n\t\t\ttimeout = 30;\n\t\t}\n\tif( timeout < 5 )\n\t\t{\n\t\t/* Enforce the same minimum connect timeout as the kernel ACLs */\n\t\tDEBUG_DIAG(( \"Network connect timeout is < 5s, setting to 5s\" ));\n\t\tassert( DEBUG_WARN );\n\t\ttimeout = 5;\n\t\t}\n\tnetStream->timeout = timeout;\n\tif( connectInfo->timeout != CRYPT_ERROR )\n\t\t{\n\t\t/* There's an explicit timeout specified, use that */\n\t\ttimeout = connectInfo->timeout;\n\t\t}\n\telse\n\t\t{\n\t\t/* Get the default timeout from the user object */\n\t\tstatus = krnlSendMessage( connectInfo->iUserObject, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout, \n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_READTIMEOUT );\n\t\tif( cryptStatusError( status ) )\n\t\t\ttimeout = 30;\n\t\t}\n\tnetStream->savedTimeout = timeout;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Set up pointers to stream-internal buffers if required:\n\n\t+--------+\n\t| STREAM |--+---+\n\t+--------+  |\t|\n\t\t\t\t|\t|\n\t netStream\t|\t| buffer\n\t+-----------+\t|\n\tv\t\t\t\tv\n\t+---------------+---------+----------+---------+--------+------------+\n\t|NET_STREAM_INFO|Read buf.|Write buf.|Host name|Loc.name|Subtype data|\n\t+---------------+---------+----------+---------+--------+------------+\n\t\t\t|\t\t\t\t  ^\t\t\t ^\t\t   ^\t\t^\n\t\t\t|\t\t\t\t  |writeBuffr|host\t   |location|subtypeInfo\n\t\t\t|\t\t\t\t  |\t\t\t |\t\t   |\t\t|\n\t\t\t+-----------------+----------+---------+--------+ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initStreamStorage( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int netStreamAllocSize,\n\t\t\t\t\t\t\t  IN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t\t\t\t  IN_OPT const URL_INFO *urlInfo )\n\t{\n\tint bufferStorageSize = 0;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( ( urlInfo == NULL ) || \\\n\t\t\tisReadPtr( urlInfo, sizeof( URL_INFO ) ) );\n\n\tREQUIRES( stream->type == STREAM_TYPE_NETWORK );\n\t\t\t  /* We can't use the sanity-check function because the stream\n\t\t\t\t hasn't been fully set up yet */\n\tREQUIRES( urlInfo == NULL || \\\n\t\t\t  ( urlInfo != NULL && urlInfo->host != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( urlInfo->hostLen ) ) );\n\tREQUIRES( isEnumRange( protocol, STREAM_PROTOCOL ) );\n\tREQUIRES( isShortIntegerRange( netStreamAllocSize ) );\n\n\t/* If it's an unbuffered stream and there's no URL info to \n\t   record, there's nothing to do */\n\tif( ( protocol == STREAM_PROTOCOL_TCP || \\\n\t\t  protocol == STREAM_PROTOCOL_UDP ) && urlInfo == NULL )\n\t\treturn( CRYPT_OK );\n\n\tnetStream->storageSize = netStreamAllocSize;\n\tif( protocol != STREAM_PROTOCOL_TCP && protocol != STREAM_PROTOCOL_UDP )\n\t\t{\n\t\tstream->buffer = SAFEBUFFER_PTR( netStream->storage );\n\t\tstream->bufSize = NETSTREAM_BUFFER_SIZE;\n\t\tsafeBufferInit( stream->buffer, stream->bufSize );\n\t\tnetStream->writeBuffer = \\\n\t\t\t\t\tSAFEBUFFER_PTR( netStream->storage + \\\n\t\t\t\t\t\t\t\t\tSAFEBUFFER_SIZE( NETSTREAM_BUFFER_SIZE ) );\n\t\tnetStream->writeBufSize = NETSTREAM_BUFFER_SIZE;\n\t\tsafeBufferInit( netStream->writeBuffer, netStream->writeBufSize );\n\t\tbufferStorageSize = SAFEBUFFER_SIZE( NETSTREAM_BUFFER_SIZE ) + \\\n\t\t\t\t\t\t\tSAFEBUFFER_SIZE( NETSTREAM_BUFFER_SIZE );\n\t\t}\n\tif( urlInfo != NULL )\n\t\t{\n\t\tnetStream->host = ( char * ) netStream->storage + bufferStorageSize;\n\t\tREQUIRES( boundsCheckZ( bufferStorageSize, urlInfo->hostLen, \n\t\t\t\t\t\t\t\tnetStream->storageSize ) );\n\t\tmemcpy( netStream->host, urlInfo->host, urlInfo->hostLen );\n\t\tnetStream->hostLen = urlInfo->hostLen;\n\t\tbufferStorageSize += urlInfo->hostLen;\n\t\tif( urlInfo->location != NULL )\n\t\t\t{\n\t\t\tnetStream->path = ( char * ) netStream->storage + bufferStorageSize;\n\t\t\tREQUIRES( boundsCheckZ( bufferStorageSize, urlInfo->locationLen, \n\t\t\t\t\t\t\t\t\tnetStream->storageSize ) );\n\t\t\tmemcpy( netStream->path, urlInfo->location, \n\t\t\t\t\turlInfo->locationLen );\n\t\t\tnetStream->pathLen = urlInfo->locationLen;\n\t\t\t}\n\t\tnetStream->port = urlInfo->port;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Clean up a stream to shut it down */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void cleanupStream( INOUT STREAM *stream, \n\t\t\t\t\t\t   const BOOLEAN cleanupTransport )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_V( cleanupTransport == TRUE || cleanupTransport == FALSE );\n\tREQUIRES_V( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t/* Clean up the transport system if necessary */\n\tif( cleanupTransport && \\\n\t\t!TEST_FLAG( netStream->nFlags, STREAM_NFLAG_USERSOCKET ) )\n\t\t{\n\t\tconst STM_TRANSPORTDISCONNECT_FUNCTION transportDisconnectFunction = \\\n\t\t\t\t\t\t( STM_TRANSPORTDISCONNECT_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->transportDisconnectFunction );\n\n\t\tREQUIRES_V( transportDisconnectFunction != NULL );\n\n\t\t( void ) transportDisconnectFunction( netStream, TRUE );\n\t\t}\n\n\t/* Clean up stream-related buffers if necessary */\n\tzeroise( netStream, sizeof( NET_STREAM_INFO ) + netStream->storageSize );\n\tclFree( \"cleanupStream\", netStream );\n\n\tzeroise( stream, sizeof( STREAM ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tNetwork Stream Connect Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process network connect options */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int processConnectOptions( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\t\t  OUT_OPT URL_INFO *urlInfo,\n\t\t\t\t\t\t\t\t  const NET_CONNECT_INFO *connectInfo,\n\t\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst void *name = connectInfo->name;\n\tint nameLength = connectInfo->nameLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( ( urlInfo == NULL ) || \\\n\t\t\tisWritePtr( urlInfo, sizeof( URL_INFO ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\n\tREQUIRES_S( stream->type == STREAM_TYPE_NETWORK );\n\t\t\t\t/* We can't use the sanity-check function because the stream\n\t\t\t\t   hasn't been fully set up yet */\n\tREQUIRES_S( ( ( connectInfo->options == NET_OPTION_NETWORKSOCKET || \\\n\t\t\t\t\tconnectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) && \\\n\t\t\t\t\turlInfo == NULL ) || \\\n\t\t\t\t( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t\t\t  ( connectInfo->options == NET_OPTION_HOSTNAME || \\\n\t\t\t\t    connectInfo->options == NET_OPTION_VIRTUAL ) && \\\n\t\t\t\t  connectInfo->name != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( connectInfo->nameLength ) && \\\n\t\t\t\t  urlInfo != NULL ) || \\\n\t\t\t\t( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t\t\t  ( connectInfo->options == NET_OPTION_HOSTNAME || \\\n\t\t\t\t    connectInfo->options == NET_OPTION_VIRTUAL ) && \\\n\t\t\t\t  connectInfo->name == NULL && connectInfo->nameLength == 0 && \\\n\t\t\t\t  ( ( connectInfo->interface == NULL && \\\n\t\t\t\t\t  connectInfo->interfaceLength == 0 && urlInfo == NULL ) || \\\n\t\t\t\t\t( connectInfo->interface != NULL && \\\n\t\t\t\t\t  isShortIntegerRangeNZ( connectInfo->interfaceLength ) && \\\n\t\t\t\t\t  urlInfo != NULL ) ) ) );\n\n\t/* Clear return value */\n\tif( urlInfo != NULL )\n\t\tmemset( urlInfo, 0, sizeof( URL_INFO ) );\n\n\t/* If it's a user-supplied network socket remember this */\n\tif( connectInfo->options == NET_OPTION_NETWORKSOCKET || \\\n\t\tconnectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY )\n\t\t{\n\t\tnetStream->netSocket = connectInfo->networkSocket;\n\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_USERSOCKET );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tENSURES_S( connectInfo->options == NET_OPTION_HOSTNAME || \\\n\t\t\t   connectInfo->options == NET_OPTION_VIRTUAL );\n\n\tREQUIRES_S( ( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) && \\\n\t\t\t\t  connectInfo->name == NULL && \\\n\t\t\t\t  connectInfo->nameLength == 0 ) || \\\n\t\t\t\t( connectInfo->name != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( connectInfo->nameLength ) ) );\n\n\t/* If it's a virtual stream, set up the callback information that's used \n\t   to move data to/from the stream */\n\tif( connectInfo->options == NET_OPTION_VIRTUAL )\n\t\t{\n\t\tnetStream->virtualGetDataFunction = \\\n\t\t\t\t\t\t\tconnectInfo->virtualGetDataFunction;\n\t\tnetStream->virtualPutDataFunction = \\\n\t\t\t\t\t\t\tconnectInfo->virtualPutDataFunction;\n\t\tnetStream->virtualGetErrorInfoFunction = \\\n\t\t\t\t\t\t\tconnectInfo->virtualGetErrorInfoFunction;\n\t\tnetStream->virtualStateInfo = connectInfo->virtualStateInfo;\n\t\t}\n\n\t/* If it's a server (i.e. we're opening a listen socket) then the \n\t   name is the interface name to bind to, defaulting to the first\n\t   interface we find/localhost if none is given */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) )\n\t\t{\n\t\tif( connectInfo->interface == NULL )\n\t\t\treturn( CRYPT_OK );\n\t\tname = connectInfo->interface;\n\t\tnameLength = connectInfo->interfaceLength;\n\t\t}\n\tENSURES( urlInfo != NULL );\n\tENSURES( name != NULL );\n\n\t/* Parse the URI into its various components */\n\tstatus = parseURL( urlInfo, name, nameLength, connectInfo->port,\n\t\t\t\t\t   ( netStream->protocol == STREAM_PROTOCOL_HTTP ) ? \\\n\t\t\t\t\t\t\tURL_TYPE_HTTP : URL_TYPE_NONE, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There's an error in the URL format, provide more information to \n\t\t   the caller */\n\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t( CRYPT_ERROR_OPEN, errorInfo, \n\t\t\t\t  \"Invalid %s name/URL\", \n\t\t\t\t  TEST_FLAG( netStream->nFlags, \n\t\t\t\t\t\t\t STREAM_NFLAG_ISSERVER ) ? \\\n\t\t\t\t  \"interface\" : \"host\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete a network connection after the client- or server-specific\n   portions have been handled */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 8 ) ) \\\nstatic int completeConnect( INOUT STREAM *stream,\n\t\t\t\t\t\t\tINOUT NET_STREAM_INFO *netStreamTemplate, \n\t\t\t\t\t\t\tIN const NET_CONNECT_INFO *connectInfo, \n\t\t\t\t\t\t\tIN_OPT const URL_INFO *urlInfo,\n\t\t\t\t\t\t\tIN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( proxyUrlLen ) const char *proxyUrl, \n\t\t\t\t\t\t\tIN_LENGTH_DNS_Z const int proxyUrlLen,\n\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tconst BOOLEAN useTransportBuffering = \\\n\t\t\t\t\t\t( protocol == STREAM_PROTOCOL_TCP || \\\n\t\t\t\t\t\t  protocol == STREAM_PROTOCOL_UDP ) ? \\\n\t\t\t\t\t\tFALSE : TRUE;\n\tSTM_TRANSPORTOK_FUNCTION transportOKFunction;\n\tNET_STREAM_INFO *netStream;\n\tvoid *netStreamInfo;\n\tint netStreamAllocSize = 0, status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( netStreamTemplate, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\tassert( ( urlInfo == NULL ) || \\\n\t\t\tisReadPtr( urlInfo, sizeof( URL_INFO ) ) );\n\tassert( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( proxyUrl, proxyUrlLen ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES_S( stream->type == STREAM_TYPE_NETWORK );\n\t\t\t\t/* We can't use the sanity-check function because the stream\n\t\t\t\t   hasn't been fully set up yet */\n\tREQUIRES_S( urlInfo == NULL || \\\n\t\t\t\t( urlInfo != NULL && urlInfo->host != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( urlInfo->hostLen ) ) );\n\tREQUIRES_S( isEnumRange( protocol, STREAM_PROTOCOL ) );\n\tREQUIRES_S( ( proxyUrl == NULL && proxyUrlLen == 0 ) || \\\n\t\t\t\t( proxyUrl != NULL && \\\n\t\t\t\t  isShortIntegerRangeNZ( proxyUrlLen ) ) );\n\n\t/* Set up the access method pointers.  We can use either direct TCP/IP\n\t   access or a cryptlib stream for transport, and layered over that\n\t   either HTTP or direct access to the TCP or UDP transport layer */\n\tswitch( connectInfo->options )\n\t\t{\n\t\tcase NET_OPTION_VIRTUAL:\n\t\t\tsetAccessMethodTransportVirtual( netStreamTemplate );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tsetAccessMethodTCP( netStreamTemplate );\n\t\t\tbreak;\n\t\t}\n\tswitch( protocol )\n\t\t{\n\t\tcase STREAM_PROTOCOL_TCP:\n\t\tcase STREAM_PROTOCOL_UDP:\n\t\t\tsetStreamLayerDirect( netStreamTemplate );\n\t\t\tbreak;\n\n\t\tcase STREAM_PROTOCOL_HTTP:\n#ifdef USE_HTTP\n\t\t\tsetStreamLayerHTTP( netStreamTemplate );\n#else\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#endif /* USE_HTTP */\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\tENSURES_S( FNPTR_ISSET( netStreamTemplate->writeFunction ) && \\\n\t\t\t   FNPTR_ISSET( netStreamTemplate->readFunction ) );\n\tENSURES_S( FNPTR_ISSET( netStreamTemplate->transportConnectFunction ) && \\\n\t\t\t   FNPTR_ISSET( netStreamTemplate->transportDisconnectFunction ) );\n\tENSURES_S( FNPTR_ISSET( netStreamTemplate->transportReadFunction ) && \\\n\t\t\t   FNPTR_ISSET( netStreamTemplate->transportWriteFunction ) );\n\tENSURES_S( FNPTR_ISSET( netStreamTemplate->transportOKFunction ) && \\\n\t\t\t   FNPTR_ISSET( netStreamTemplate->transportCheckFunction ) );\n\tENSURES_S( DATAPTR_ISVALID( netStreamTemplate->virtualStateInfo ) && \\\n\t\t\t   FNPTR_ISVALID( netStreamTemplate->virtualGetDataFunction ) && \\\n\t\t\t   FNPTR_ISVALID( netStreamTemplate->virtualPutDataFunction ) && \\\n\t\t\t   FNPTR_ISVALID( netStreamTemplate->virtualGetErrorInfoFunction ) );\n\tENSURES_S( FNPTR_ISVALID( netStreamTemplate->connectFunctionOpt ) && \\\n\t\t\t   FNPTR_ISVALID( netStreamTemplate->disconnectFunctionOpt ) );\n\tENSURES_S( TEST_FLAG( netStreamTemplate->nFlags, STREAM_NFLAG_ISSERVER ) || \\\n\t\t\t   ( urlInfo != NULL && \\\n\t\t\t\t urlInfo->host != NULL && urlInfo->hostLen != 0 ) || \\\n\t\t\t   netStreamTemplate->netSocket != CRYPT_ERROR );\n\n\t/* Wait for any async network driver binding to complete and make sure\n\t   that the network interface has been initialised */\n\ttransportOKFunction = ( STM_TRANSPORTOK_FUNCTION ) \\\n\t\t\t\t\t\t  FNPTR_GET( netStreamTemplate->transportOKFunction );\n\tENSURES_S( transportOKFunction != NULL );\n\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) || !transportOKFunction() )\n\t\t{\n\t\t/* Clean up */\n\t\tzeroise( stream, sizeof( STREAM ) );\n\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t( CRYPT_ERROR_NOTINITED, errorInfo, \n\t\t\t\t  \"Networking subsystem not available\" ) );\n\t\t}\n\n\t/* Allocate room for the network stream information and set up an alias \n\t   into the NETWORK_STREAM_INFO portion.  The memory layout is:\n\n\t\t+---------------+---------+----------+---------+--------+------------+\n\t\t|NET_STREAM_INFO|Read buf.|Write buf.|Host name|Loc.name|Subtype data|\n\t\t+---------------+---------+----------+---------+--------+------------+\n\n\t   with the additional variable-length storage held in \n\t   { netStreamInfo->storage, netStreamInfo->storageLen } at the end of\n\t   the netStream structure.  The read and write buffers are safe buffers,\n\t   which means that there are canaries preceding and following the buffer\n\t   data */\n\tif( useTransportBuffering )\n\t\t{\n\t\tnetStreamAllocSize += SAFEBUFFER_SIZE( NETSTREAM_BUFFER_SIZE ) + \\\n\t\t\t\t\t\t\t  SAFEBUFFER_SIZE( NETSTREAM_BUFFER_SIZE );\n\t\t}\n\tif( urlInfo != NULL )\n\t\tnetStreamAllocSize += urlInfo->hostLen + urlInfo->locationLen;\n\tREQUIRES( netStreamAllocSize == 0 || \\\n\t\t\t  rangeCheck( netStreamAllocSize, 1, MAX_BUFFER_SIZE ) );\n\tnetStreamInfo = clAlloc( \"completeConnect\", sizeof( NET_STREAM_INFO ) + \\\n\t\t\t\t\t\t\t\t\t\t\t\tnetStreamAllocSize );\n\tif( netStreamInfo == NULL )\n\t\t{\n\t\tzeroise( stream, sizeof( STREAM ) );\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tmemset( netStreamInfo, 0, \n\t\t\tsizeof( NET_STREAM_INFO ) + netStreamAllocSize );\n\tnetStream = netStreamInfo;\n\n\t/* Initialise the network stream with the net stream template and set up \n\t   internal storage */\n\tmemcpy( netStream, netStreamTemplate, sizeof( NET_STREAM_INFO ) );\n\tstatus = initStreamStorage( stream, netStream, netStreamAllocSize, \n\t\t\t\t\t\t\t\tprotocol, urlInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( netStreamInfo, \n\t\t\t\t sizeof( NET_STREAM_INFO ) + netStreamAllocSize );\n\t\tclFree( \"completeConnect\", netStreamInfo );\n\t\tzeroise( stream, sizeof( STREAM ) );\n\t\treturn( status );\n\t\t}\n\n\t/* The network stream is ready to go, connect it to the overall \n\t   stream */\n\tENSURES_S( sanityCheckNetStream( netStream ) );\n\tDATAPTR_SET( stream->netStream, netStream );\n\n\t/* Open the connection to the remote system */\n\tstatus = openNetworkConnection( netStream, connectInfo->options, \n\t\t\t\t\t\t\t\t\tproxyUrl, proxyUrlLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Copy back the error information to the caller */\n\t\tcopyErrorInfo( errorInfo, NETSTREAM_ERRINFO );\n\n\t\t/* Clean up */\n\t\tcleanupStream( stream, FALSE );\n\t\treturn( status );\n\t\t}\n\n\t/* If we're using optional transport protocol-negotiation step, activate \n\t   that too */\n\tif( FNPTR_ISSET( netStream->connectFunctionOpt ) )\n\t\t{\n\t\tSTM_CONNECT_FUNCTION_OPT connectFunction = \\\n\t\t\t\t\t\t\t\t( STM_CONNECT_FUNCTION_OPT ) \\\n\t\t\t\t\t\t\t\tFNPTR_GET( netStream->connectFunctionOpt );\n\t\tREQUIRES_S( connectFunction != NULL );\n\n\t\tstatus = connectFunction( stream, connectInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If we're not going through a proxy, we're done */\n\tif( proxyUrl == NULL )\n\t\treturn( CRYPT_OK );\n\n#ifdef USE_HTTP\n\t/* Complete the connect via the appropriate proxy type */\n\tstatus = connectViaHttpProxy( stream, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Copy back the error information to the caller */\n\t\tcopyErrorInfo( errorInfo, NETSTREAM_ERRINFO );\n\n\t\t/* Clean up */\n\t\tcleanupStream( stream, FALSE );\n\t\treturn( status );\n\t\t}\n#else\n\tcleanupStream( stream, FALSE );\n\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t( CRYPT_ERROR_NOTAVAIL, errorInfo, \n\t\t\t  \"HTTP proxy support not available\" ) );\n#endif /* USE_HTTP */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Open and close a network connection.  This parses a location string\n   (usually a URL) into <schema>://<host>[:<port>]/<path>[?<query>]\n   components and opens a connection to the host for non-stateless\n   protocols */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetConnect( OUT STREAM *stream, \n\t\t\t\t IN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t const NET_CONNECT_INFO *connectInfo, \n\t\t\t\t OUT ERROR_INFO *errorInfo )\n\t{\n\tNET_STREAM_INFO netStream;\n\tURL_INFO urlInfo, *urlInfoPtr = NULL;\n\tchar proxyUrlBuffer[ MAX_DNS_SIZE + 8 ], *proxyURL = NULL;\n\tint proxyUrlLen = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\tassert( connectInfo->options != NET_OPTION_HOSTNAME || \\\n\t\t\tisReadPtrDynamic( connectInfo->name, \\\n\t\t\t\t\t\t\t  connectInfo->nameLength ) );\n\n\tREQUIRES( protocol == STREAM_PROTOCOL_TCP || \\\n\t\t\t  protocol == STREAM_PROTOCOL_UDP || \\\n\t\t\t  protocol == STREAM_PROTOCOL_HTTP );\n\tREQUIRES( isEnumRange( connectInfo->options, NET_OPTION ) );\n\tREQUIRES( connectInfo->options != NET_OPTION_HOSTNAME || \\\n\t\t\t  ( connectInfo->options == NET_OPTION_HOSTNAME && \\\n\t\t\t    connectInfo->name != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( connectInfo->nameLength ) && \\\n\t\t\t\tconnectInfo->networkSocket == CRYPT_ERROR ) );\n\tREQUIRES( ( connectInfo->options != NET_OPTION_NETWORKSOCKET && \\\n\t\t\t\tconnectInfo->options != NET_OPTION_NETWORKSOCKET_DUMMY ) || \n\t\t\t  ( ( connectInfo->options == NET_OPTION_NETWORKSOCKET || \\\n\t\t\t\t  connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) && \\\n\t\t\t\tconnectInfo->name == NULL && connectInfo->nameLength == 0 && \\\n\t\t\t\tconnectInfo->interface == NULL && connectInfo->interfaceLength == 0 && \\\n\t\t\t\tconnectInfo->networkSocket != CRYPT_ERROR ) );\n\tREQUIRES( connectInfo->options != NET_OPTION_VIRTUAL ||\t\\\n\t\t\t  ( connectInfo->options == NET_OPTION_VIRTUAL && \\\n\t\t\t    connectInfo->name != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( connectInfo->nameLength ) && \\\n\t\t\t\tconnectInfo->networkSocket == CRYPT_ERROR && \\\n\t\t\t\tFNPTR_ISSET( connectInfo->virtualGetDataFunction ) && \\\n\t\t\t\tFNPTR_ISSET( connectInfo->virtualPutDataFunction ) && \n\t\t\t\tFNPTR_ISSET( connectInfo->virtualGetErrorInfoFunction ) && \\\n\t\t\t\tDATAPTR_ISSET( connectInfo->virtualStateInfo ) ) );\n\tREQUIRES( connectInfo->iUserObject == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( connectInfo->iUserObject ) );\n\tREQUIRES( ( connectInfo->authName == NULL && \\\n\t\t\t\tconnectInfo->authNameLength == 0 && \\\n\t\t\t\tconnectInfo->authKey == NULL && \\\n\t\t\t\tconnectInfo->authKeyLength == 0 ) || \\\n\t\t\t  ( connectInfo->authName != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( connectInfo->authNameLength ) && \\\n\t\t\t\tconnectInfo->authKey != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( connectInfo->authKeyLength ) ) );\n\n\t/* Clear return values */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Initialise the network stream info */\n\tstatus = initStream( stream, &netStream, protocol, connectInfo, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( connectInfo->options == NET_OPTION_HOSTNAME || \\\n\t\tconnectInfo->options == NET_OPTION_VIRTUAL )\n\t\turlInfoPtr = &urlInfo;\n\tstatus = processConnectOptions( stream, &netStream, urlInfoPtr, \n\t\t\t\t\t\t\t\t\tconnectInfo, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( connectInfo->options == NET_OPTION_HOSTNAME )\n\t\t{\n\t\tint proxyUrlLength;\n\n\t\tANALYSER_HINT( urlInfoPtr != NULL );\n\n\t\t/* Check for the use of a proxy to establish the connection.  This \n\t\t   function will return OK_SPECIAL if there's a proxy present */\n\t\tstatus = checkForProxy( &netStream, protocol, connectInfo, \n\t\t\t\t\t\t\t\turlInfoPtr->host, urlInfoPtr->hostLen,\n\t\t\t\t\t\t\t\tproxyUrlBuffer, MAX_DNS_SIZE, \n\t\t\t\t\t\t\t\t&proxyUrlLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\n\t\t\t/* There's a proxy present, go via the proxy rather than \n\t\t\t   directly to the user-supplied URL */\n\t\t\tproxyURL = proxyUrlBuffer;\n\t\t\tproxyUrlLen = proxyUrlLength;\n\t\t\t}\n\t\t}\n\n\t/* Set up access mechanisms and complete the connection */\n\tstatus = completeConnect( stream, &netStream, connectInfo, urlInfoPtr, \n\t\t\t\t\t\t\t  protocol, proxyURL, proxyUrlLen, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckNetStream( &netStream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetListen( OUT STREAM *stream, \n\t\t\t\tIN_ENUM( STREAM_PROTOCOL ) \\\n\t\t\t\t\tconst STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\tconst NET_CONNECT_INFO *connectInfo, \n\t\t\t\tOUT ERROR_INFO *errorInfo )\n\t{\n\tNET_STREAM_INFO netStream;\n\tURL_INFO urlInfo, *urlInfoPtr = NULL;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( protocol == STREAM_PROTOCOL_TCP || \\\n\t\t\t  protocol == STREAM_PROTOCOL_UDP || \\\n\t\t\t  protocol == STREAM_PROTOCOL_HTTP );\n\tREQUIRES( connectInfo->options == NET_OPTION_HOSTNAME || \\\n\t\t\t  connectInfo->options == NET_OPTION_NETWORKSOCKET || \\\n\t\t\t  connectInfo->options == NET_OPTION_VIRTUAL );\n\tREQUIRES( connectInfo->options != NET_OPTION_HOSTNAME || \\\n\t\t\t  ( connectInfo->options == NET_OPTION_HOSTNAME && \\\n\t\t\t\t( ( connectInfo->interface == NULL && \\\n\t\t\t\t\tconnectInfo->interfaceLength == 0 ) || \\\n\t\t\t\t  ( connectInfo->interface != NULL && \\\n\t\t\t\t\tisShortIntegerRangeNZ( connectInfo->interfaceLength ) ) ) && \\\n\t\t\t\tconnectInfo->networkSocket == CRYPT_ERROR ) );\n\tREQUIRES( ( connectInfo->options != NET_OPTION_NETWORKSOCKET && \\\n\t\t\t\tconnectInfo->options != NET_OPTION_NETWORKSOCKET_DUMMY ) || \n\t\t\t  ( ( connectInfo->options == NET_OPTION_NETWORKSOCKET || \\\n\t\t\t\t  connectInfo->options == NET_OPTION_NETWORKSOCKET_DUMMY ) && \\\n\t\t\t\tconnectInfo->interface == NULL && connectInfo->interfaceLength == 0 && \\\n\t\t\t\tconnectInfo->networkSocket != CRYPT_ERROR ) );\n\tREQUIRES( connectInfo->options != NET_OPTION_VIRTUAL ||\t\\\n\t\t\t  ( connectInfo->options == NET_OPTION_VIRTUAL && \\\n\t\t\t    connectInfo->name == NULL && connectInfo->nameLength == 0 && \\\n\t\t\t\tconnectInfo->networkSocket == CRYPT_ERROR && \\\n\t\t\t\tFNPTR_ISSET( connectInfo->virtualGetDataFunction ) && \\\n\t\t\t\tFNPTR_ISSET( connectInfo->virtualPutDataFunction ) && \n\t\t\t\tFNPTR_ISSET( connectInfo->virtualGetErrorInfoFunction ) && \\\n\t\t\t\tDATAPTR_ISSET( connectInfo->virtualStateInfo ) ) );\n\tREQUIRES( connectInfo->iUserObject == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( connectInfo->iUserObject ) );\n\tREQUIRES( connectInfo->name == NULL && connectInfo->nameLength == 0 );\n\n\t/* Clear the return values */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Initialise the network stream info */\n\tstatus = initStream( stream, &netStream, protocol, connectInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( connectInfo->options == NET_OPTION_HOSTNAME && \\\n\t\tconnectInfo->interface != NULL )\n\t\turlInfoPtr = &urlInfo;\n\tstatus = processConnectOptions( stream, &netStream, urlInfoPtr, \n\t\t\t\t\t\t\t\t\tconnectInfo, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up access mechanisms and complete the connection */\n\tstatus = completeConnect( stream, &netStream, connectInfo, urlInfoPtr, \n\t\t\t\t\t\t\t  protocol, NULL, 0, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tENSURES( sanityCheckNetStream( &netStream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef CONFIG_FUZZ\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sNetDisconnect( INOUT STREAM *stream )\n\t{\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sNetDisconnect( INOUT STREAM *stream )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\tcleanupStream( stream, TRUE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_FUZZ */\n\n/* Parse a URL into its various components */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sNetParseURL( OUT URL_INFO *urlInfo, \n\t\t\t\t  IN_BUFFER( urlLen ) const BYTE *url, \n\t\t\t\t  IN_LENGTH_SHORT const int urlLen, \n\t\t\t\t  IN_ENUM_OPT( URL_TYPE ) const URL_TYPE urlTypeHint )\n\t{\n\tassert( isWritePtr( urlInfo, sizeof( URL_INFO ) ) );\n\tassert( isReadPtrDynamic( url, urlLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( urlLen ) );\n\tREQUIRES( isEnumRangeOpt( urlTypeHint, URL_TYPE ) );\n\n\treturn( parseURL( urlInfo, url, urlLen, CRYPT_UNUSED, urlTypeHint, \n\t\t\t\t\t  TRUE ) );\n\t}\n\n/* Get extended information about an error status on a network connection.\n   This has to be made explicit rather than being implicitly propagated up\n   from the netStream to the stream in order to preserve an initial error\n   state that might otherwise be overwritten by later errors, for example\n   an sread() error that's overwritten by an error on close that follows\n   the failed read */\n\n#ifdef CONFIG_FUZZ\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sNetGetErrorInfo( INOUT STREAM *stream, OUT ERROR_INFO *errorInfo )\n\t{\n\treturn;\n\t}\n\n#else\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sNetGetErrorInfo( INOUT STREAM *stream, OUT ERROR_INFO *errorInfo )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES_V( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t/* Remember the error code and message */\n\tcopyErrorInfo( errorInfo, NETSTREAM_ERRINFO );\n\t}\n#endif /* CONFIG_FUZZ */\n\n#else\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNetwork Stream Stubs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If there's no networking support present we replace the network access\n   routines with dummy ones that always return an error */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetConnect( OUT STREAM *stream, \n\t\t\t\t IN_ENUM( STREAM_PROTOCOL ) const STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t const NET_CONNECT_INFO *connectInfo, \n\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tUNUSED_ARG( connectInfo );\n\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\treturn( CRYPT_ERROR_OPEN );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetListen( OUT STREAM *stream, \n\t\t\t\tIN_ENUM( STREAM_PROTOCOL ) const STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\tconst NET_CONNECT_INFO *connectInfo, \n\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tUNUSED_ARG( connectInfo );\n\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\treturn( CRYPT_ERROR_OPEN );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sNetDisconnect( INOUT STREAM *stream )\n\t{\n\tUNUSED_ARG( stream );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sNetParseURL( INOUT URL_INFO *urlInfo, \n\t\t\t\t  IN_BUFFER( urlLen ) const BYTE *url, \n\t\t\t\t  IN_LENGTH_SHORT const int urlLen, \n\t\t\t\t  IN_ENUM_OPT( URL_TYPE ) const URL_TYPE urlTypeHint )\n\t{\n\tUNUSED_ARG( url );\n\n\tmemset( urlInfo, 0, sizeof( URL_INFO ) );\n\n\treturn( CRYPT_ERROR_BADDATA );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sNetGetErrorInfo( INOUT STREAM *stream, \n\t\t\t\t\t   OUT ERROR_INFO *errorInfo )\n\t{\n\tUNUSED_ARG( stream );\n\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/net_proxy.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Network Stream Proxy Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSOCKS Proxy Management\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open a connection through a Socks proxy.  This is currently disabled\n   since it doesn't appear to be used by anyone */\n\n#if 0\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint connectViaSocksProxy( INOUT STREAM *stream )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE socksBuffer[ 64 + CRYPT_MAX_TEXTSIZE + 8 ], *bufPtr = socksBuffer;\n\tchar userName[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( stream->type == STREAM_TYPE_NETWORK );\n\n\t/* Get the SOCKS user name, defaulting to \"cryptlib\" if there's none\n\t   set */\n\tsetMessageData( &msgData, userName, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_OPTION_NET_SOCKS_USERNAME );\n\tif( cryptStatusOK( status ) )\n\t\tuserName[ msgData.length ] = '\\0';\n\telse\n\t\tstrlcpy_s( userName, CRYPT_MAX_TEXTSIZE, \"cryptlib\" );\n\n\t/* Build up the SOCKSv4 request string:\n\n\t\tBYTE: version = 4\n\t\tBYTE: command = 1 (connect)\n\t\tWORD: port\n\t\tLONG: IP address\n\t\tSTRING: userName + '\\0'\n\n\t   Note that this has a potential problem in that it requires a DNS \n\t   lookup by the client, which can lead to problems if the client\n\t   can't get DNS requests out because only SOCKSified access is allowed.\n\t   A related problem occurs when SOCKS is being used as a tunnelling\n\t   interface because the DNS lookup will communicate data about the \n\t   client to an observer outside the tunnel.\n\n\t   To work around this there's a so-called SOCKSv4a protocol that has \n\t   the SOCKS proxy perform the lookup:\n\n\t\tBYTE: version = 4\n\t\tBYTE: command = 1 (connect)\n\t\tWORD: port\n\t\tLONG: IP address = 0x00 0x00 0x00 0xFF\n\t\tSTRING: userName + '\\0'\n\t\tSTRING: FQDN + '\\0'\n\n\t   Unfortunately there's no way to tell whether a SOCKS server supports\n\t   4a or only 4, but in any case since SOCKS support is currently \n\t   disabled we leave the poke-and-hope 4a detection until such time as\n\t   someone actually requests it */\n\t*bufPtr++ = 4; *bufPtr++ = 1;\n\tmputWord( bufPtr, netStream->port );\n\tstatus = getIPAddress( stream, bufPtr, netStream->host );\n\tstrlcpy_s( bufPtr + 4, CRYPT_MAX_TEXTSIZE, userName );\n\tlength = 1 + 1 + 2 + 4 + strlen( userName ) + 1;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tnetStream->transportDisconnectFunction( stream, TRUE );\n\t\treturn( status );\n\t\t}\n\n\t/* Send the data to the server and read back the reply */\n\tstatus = netStream->transportWriteFunction( stream, socksBuffer, length,\n\t\t\t\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_FLUSH );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = netStream->transportReadFunction( stream, socksBuffer, 8,\n\t\t\t\t\t\t\t\t\t\t\t\t   TRANSPORT_FLAG_BLOCKING );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The involvement of a proxy complicates matters somewhat because\n\t\t   we can usually connect to the proxy OK but may run into problems\n\t\t   going from the proxy to the remote server, so if we get an error\n\t\t   at this stage (which will typically show up as a read error from\n\t\t   the proxy) we report it as an open error instead */\n\t\tif( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_COMPLETE )\n\t\t\tstatus = CRYPT_ERROR_OPEN;\n\t\tnetStream->transportDisconnectFunction( stream, TRUE );\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that everything is OK:\n\n\t\tBYTE: null = 0\n\t\tBYTE: status = 90 (OK)\n\t\tWORD: port\n\t\tLONG: IP address */\n\tif( socksBuffer[ 1 ] != 90 )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\tnetStream->transportDisconnectFunction( stream, TRUE );\n\t\tstrlcpy_s( netStream->errorInfo->errorString, MAX_ERRMSG_SIZE, \n\t\t\t\t   \"Socks proxy returned\" );\n\t\tLOOP_SMALL( i = 0, i < 8, i++ )\n\t\t\t{\n\t\t\tsprintf_s( netStream->errorInfo->errorString + 20 + ( i * 3 ),\n\t\t\t\t\t   MAX_ERRMSG_SIZE - ( 20 + ( i * 3 ) ), \" %02X\", \n\t\t\t\t\t   socksBuffer[ i ] );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tstrlcat_s( netStream->errorInfo->errorString, MAX_ERRMSG_SIZE, \".\" );\n\t\tnetStream->errorCode = socksBuffer[ 1 ];\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Proxy Management\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_HTTP\n\n/* Open a connection via an HTTP proxy */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint connectViaHttpProxy( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTM_WRITE_FUNCTION writeFunction;\n\tSTM_READ_FUNCTION readFunction;\n\tSTM_TRANSPORTDISCONNECT_FUNCTION transportDisconnectFunction;\n\tHTTP_DATA_INFO httpDataInfo;\n\tBYTE buffer[ SAFEBUFFER_SIZE( 512 ) + 8 ] STACK_ALIGN_DATA;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NETWORK );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\twriteFunction = ( STM_WRITE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( netStream->writeFunction );\n\treadFunction = ( STM_READ_FUNCTION ) \\\n\t\t\t\t   FNPTR_GET( netStream->readFunction );\n\ttransportDisconnectFunction = ( STM_TRANSPORTDISCONNECT_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( netStream->transportDisconnectFunction );\n\tREQUIRES_S( writeFunction != NULL );\n\tREQUIRES_S( readFunction != NULL );\n\tREQUIRES_S( transportDisconnectFunction != NULL );\n\n\t/* Open the connection via the proxy.  To do this we temporarily layer\n\t   HTTP I/O over the TCP I/O, then once the proxy messaging has been\n\t   completed we re-set the stream to pure TCP I/O and clear any stream\n\t   flags that were set during the proxying */\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), 512 );\n\tsetStreamLayerHTTP( netStream );\n\tstatus = initHttpInfoWrite( &httpDataInfo, SAFEBUFFER_PTR( buffer ), \n\t\t\t\t\t\t\t\t512, 512 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeFunction( stream, &httpDataInfo, \n\t\t\t\t\t\t\t\tsizeof( HTTP_DATA_INFO ), &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = initHttpInfoRead( &httpDataInfo, \n\t\t\t\t\t\t\t\t   SAFEBUFFER_PTR( buffer ), 512 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readFunction( stream, &httpDataInfo, \n\t\t\t\t\t\t\t   sizeof( HTTP_DATA_INFO ), &length );\n\t\t}\n\tsetStreamLayerDirect( netStream );\n\tINIT_FLAGS( stream->flags, STREAM_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The involvement of a proxy complicates matters somewhat because\n\t\t   we can usually connect to the proxy OK but may run into problems\n\t\t   going from the proxy to the remote server so if we get an error\n\t\t   at this stage (which will typically show up as a read error from\n\t\t   the proxy) we report it as an open error instead */\n\t\tif( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_COMPLETE )\n\t\t\tstatus = CRYPT_ERROR_OPEN;\n\t\tcopyErrorInfo( errorInfo, NETSTREAM_ERRINFO );\n\t\ttransportDisconnectFunction( netStream, TRUE );\n\t\t}\n\n\treturn( status );\n\t}\n#endif /* USE_HTTP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tProxy Autoconfig Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and auto-detect HTTP proxy information */\n\n#if defined( __WIN32__ )\n\n/* The autoproxy functions were only documented in WinHTTP 5.1 so we have to\n   provide the necessary defines and structures ourselves */\n\n#ifndef WINHTTP_ACCESS_TYPE_DEFAULT_PROXY\n\n#define HINTERNET\tHANDLE\n\ntypedef struct {\n\tDWORD dwFlags;\n\tDWORD dwAutoDetectFlags;\n\tLPCWSTR lpszAutoConfigUrl;\n\tLPVOID lpvReserved;\n\tDWORD dwReserved;\n\tBOOL fAutoLogonIfChallenged;\n\t} WINHTTP_AUTOPROXY_OPTIONS;\n\ntypedef struct {\n\tDWORD dwAccessType;\n\tLPWSTR lpszProxy;\n\tLPWSTR lpszProxyBypass;\n\t} WINHTTP_PROXY_INFO;\n\ntypedef struct {\n\tBOOL fAutoDetect;\n\tLPWSTR lpszAutoConfigUrl;\n\tLPWSTR lpszProxy;\n\tLPWSTR lpszProxyBypass;\n\t} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;\n\n#define WINHTTP_AUTOPROXY_AUTO_DETECT\t1\n#define WINHTTP_AUTO_DETECT_TYPE_DHCP\t1\n#define WINHTTP_AUTO_DETECT_TYPE_DNS_A\t2\n#define WINHTTP_ACCESS_TYPE_NO_PROXY\t1\n#define WINHTTP_NO_PROXY_NAME\t\t\tNULL\n#define WINHTTP_NO_PROXY_BYPASS\t\t\tNULL\n\n#endif /* WinHTTP 5.1 defines and structures */\n\ntypedef HINTERNET ( *WINHTTPOPEN )( LPCWSTR pwszUserAgent, DWORD dwAccessType,\n\t\t\t\t\t\t\t\t\tLPCWSTR pwszProxyName, LPCWSTR pwszProxyBypass,\n\t\t\t\t\t\t\t\t\tDWORD dwFlags );\ntypedef BOOL ( *WINHTTPGETDEFAULTPROXYCONFIGURATION )( WINHTTP_PROXY_INFO* pProxyInfo );\ntypedef BOOL ( *WINHTTPGETIEPROXYCONFIGFORCURRENTUSER )(\n\t\t\t\t\t\t\t\tWINHTTP_CURRENT_USER_IE_PROXY_CONFIG *pProxyConfig );\ntypedef BOOL ( *WINHTTPGETPROXYFORURL )( HINTERNET hSession, LPCWSTR lpcwszUrl,\n\t\t\t\t\t\t\t\t\t\t WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions,\n\t\t\t\t\t\t\t\t\t\t WINHTTP_PROXY_INFO *pProxyInfo );\ntypedef BOOL ( *WINHTTPCLOSEHANDLE )( HINTERNET hInternet );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint findProxyUrl( OUT_BUFFER( proxyMaxLen, *proxyLen ) char *proxy, \n\t\t\t\t  IN_LENGTH_DNS const int proxyMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( proxyMaxLen ) int *proxyLen,\n\t\t\t\t  IN_BUFFER( urlLen ) const char *url, \n\t\t\t\t  IN_LENGTH_DNS const int urlLen )\n\t{\n\tstatic HMODULE hWinHTTP = NULL;\n\tstatic WINHTTPOPEN pWinHttpOpen = NULL;\n\tstatic WINHTTPGETDEFAULTPROXYCONFIGURATION pWinHttpGetDefaultProxyConfiguration = NULL;\n\tstatic WINHTTPGETIEPROXYCONFIGFORCURRENTUSER pWinHttpGetIEProxyConfigForCurrentUser = NULL;\n\tstatic WINHTTPGETPROXYFORURL pWinHttpGetProxyForUrl = NULL;\n\tstatic WINHTTPCLOSEHANDLE pWinHttpCloseHandle = NULL;\n\tWINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = \\\n\t\t\t{ WINHTTP_AUTOPROXY_AUTO_DETECT,\n\t\t\t  WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A,\n\t\t\t  NULL, NULL, 0, FALSE };\n\tWINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyInfo;\n\tWINHTTP_PROXY_INFO proxyInfo;\n\tHINTERNET hSession;\n\tchar urlBuffer[ MAX_DNS_SIZE + 1 + 8 ];\n\twchar_t unicodeURL[ MAX_DNS_SIZE + 1 + 8 ];\n\tsize_t unicodeUrlLen, wcsProxyLen;\n\tint offset, length, proxyStatus;\n\n\tassert( isWritePtrDynamic( proxy, proxyMaxLen ) );\n\tassert( isWritePtr( proxyLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( url, urlLen ) );\n\n\tREQUIRES( proxyMaxLen >= 10 && proxyMaxLen <= MAX_DNS_SIZE );\n\tREQUIRES( urlLen > 0 && urlLen <= MAX_DNS_SIZE );\n\n\t/* Under Win2K SP3 and Windows XP and newer (2003, Vista, etc), or at \n\t   least Windows versions with WinHTTP 5.1 installed in some way (it \n\t   officially shipped with the versions mentioned earlier) we can use \n\t   WinHTTP AutoProxy support, which implements the Web Proxy Auto-\n\t   Discovery (WPAD) protocol from an internet draft that expired in May \n\t   2001.  Under older versions of Windows we have to use the WinINet \n\t   InternetGetProxyInfo, however this consists of a ghastly set of \n\t   kludges that were never meant to be exposed to the outside world \n\t   (they were only crowbarred out of MS as part of the DoJ consent \n\t   decree) and user experience with them is that they don't really work \n\t   except in the one special way in which MS-internal code calls them.  \n\t   Since we don't know what this is, we use the WinHTTP functions \n\t   instead */\n\tif( hWinHTTP == NULL )\n\t\t{\n\t\tif( ( hWinHTTP = DynamicLoad( \"WinHTTP.dll\" ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\tpWinHttpOpen = ( WINHTTPOPEN ) \\\n\t\t\t\t\t\tGetProcAddress( hWinHTTP, \"WinHttpOpen\" );\n\t\tpWinHttpGetDefaultProxyConfiguration = ( WINHTTPGETDEFAULTPROXYCONFIGURATION ) \\\n\t\t\t\t\t\tGetProcAddress( hWinHTTP, \"WinHttpGetDefaultProxyConfiguration\" );\n\t\tpWinHttpGetIEProxyConfigForCurrentUser = ( WINHTTPGETIEPROXYCONFIGFORCURRENTUSER ) \\\n\t\t\t\t\t\tGetProcAddress( hWinHTTP, \"WinHttpGetIEProxyConfigForCurrentUser\" );\n\t\tpWinHttpGetProxyForUrl = ( WINHTTPGETPROXYFORURL ) \\\n\t\t\t\t\t\tGetProcAddress( hWinHTTP, \"WinHttpGetProxyForUrl\" );\n\t\tpWinHttpCloseHandle = ( WINHTTPCLOSEHANDLE ) \\\n\t\t\t\t\t\tGetProcAddress( hWinHTTP, \"WinHttpCloseHandle\" );\n\t\tif( pWinHttpOpen == NULL || pWinHttpGetProxyForUrl == NULL || \\\n\t\t\tpWinHttpCloseHandle == NULL )\n\t\t\t{\n\t\t\tDynamicUnload( hWinHTTP );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t}\n\n\t/* Autoproxy discovery using WinHttpGetProxyForUrl() can be awfully slow,\n\t   often taking several seconds since it requires probing for proxy info\n\t   first using DHCP and then if that fails using DNS.  Since this is done\n\t   via a blocking call everything blocks while it's in progress.  To help \n\t   mitigate this we try for proxy info direct from the registry if it's \n\t   available, avoiding the lengthy autodiscovery process.  This also \n\t   means that discovery will work if no auto-discovery support is present,\n\t   for example on servers where the admin has set the proxy config\n\t   directly with ProxyCfg.exe */\n\tif( pWinHttpGetDefaultProxyConfiguration != NULL && \\\n\t\tpWinHttpGetDefaultProxyConfiguration( &proxyInfo ) && \\\n\t\tproxyInfo.lpszProxy != NULL )\n\t\t{\n\t\tproxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,\n\t\t\t\t\t\t\t\t  proxyInfo.lpszProxy, MAX_DNS_SIZE );\n\t\tGlobalFree( proxyInfo.lpszProxy );\n\t\tif( proxyInfo.lpszProxyBypass != NULL )\n\t\t\tGlobalFree( proxyInfo.lpszProxyBypass );\n\t\tif( proxyStatus == 0 )\n\t\t\t{\n\t\t\t*proxyLen = wcsProxyLen;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\t/* The next fallback is to get the proxy info from MSIE.  This is also\n\t   usually much quicker than WinHttpGetProxyForUrl() although sometimes\n\t   it seems to fall back to that, based on the longish delay involved.\n\t   Another issue with this is that it won't work in a service process\n\t   that isn't impersonating an interactive user (since there isn't a\n\t   current user), but in that case we just fall back to\n\t   WinHttpGetProxyForUrl() */\n\tif( pWinHttpGetIEProxyConfigForCurrentUser != NULL && \\\n\t\tpWinHttpGetIEProxyConfigForCurrentUser( &ieProxyInfo ) )\n\t\t{\n\t\tproxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,\n\t\t\t\t\t\t\t\t  ieProxyInfo.lpszProxy, MAX_DNS_SIZE );\n\t\tif( ieProxyInfo.lpszAutoConfigUrl != NULL )\n\t\t\tGlobalFree( ieProxyInfo.lpszAutoConfigUrl );\n\t\tif( ieProxyInfo.lpszProxy != NULL )\n\t\t\tGlobalFree( ieProxyInfo.lpszProxy );\n\t\tif( ieProxyInfo.lpszProxyBypass != NULL )\n\t\t\tGlobalFree( ieProxyInfo.lpszProxyBypass );\n\t\tif( proxyStatus == 0 )\n\t\t\t{\n\t\t\t*proxyLen = wcsProxyLen;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\t/* WinHttpGetProxyForUrl() requires a schema for the URL that it's\n\t   performing a lookup on, if the URL doesn't contain one we use a\n\t   default value of \"http://\".  In addition we need to convert the\n\t   raw octet string into a null-terminated string for the mbstowcs_s()\n\t   Unicode conversion and following WinHttpGetProxyForUrl() lookup */\n\tif( strFindStr( url, urlLen, \"://\", 3 ) < 0 )\n\t\t{\n\t\tstrlcpy_s( urlBuffer, MAX_DNS_SIZE, \"http://\" );\n\t\toffset = 7;\n\t\tlength = MAX_DNS_SIZE - offset;\n\t\t}\n\telse\n\t\t{\n\t\t/* There's already a schema present, not need to manually add one */\n\t\toffset = 0;\n\t\tlength = urlLen;\n\t\t}\n\tREQUIRES( boundsCheck( offset, length, MAX_DNS_SIZE ) );\n\tmemcpy( urlBuffer + offset, url, length );\n\turlBuffer[ offset + length ] = '\\0';\n\n\t/* Locate the proxy used for accessing the resource at the supplied URL.\n\t   We have to convert to and from Unicode because the WinHTTP functions\n\t   all take Unicode strings as args.\n\n\t   WinHttpGetProxyForUrl() can be rather flaky, in some cases it'll fail\n\t   instantly (without even trying auto-discovery) with GetLastError() =\n\t   87 (parameter error) but then calling it again some time later works\n\t   fine.  Because of this we leave it as the last resort after trying\n\t   all of the other get-proxy mechanisms */\n\thSession = pWinHttpOpen( L\"cryptlib/1.0\",\n\t\t\t\t\t\t\t WINHTTP_ACCESS_TYPE_NO_PROXY,\n\t\t\t\t\t\t\t WINHTTP_NO_PROXY_NAME,\n\t\t\t\t\t\t\t WINHTTP_NO_PROXY_BYPASS, 0 );\n\tif( hSession == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( mbstowcs_s( &unicodeUrlLen, unicodeURL, MAX_DNS_SIZE,\n\t\t\t\t\turlBuffer, MAX_DNS_SIZE ) != 0 )\n\t\t{\n\t\tpWinHttpCloseHandle( hSession );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tunicodeURL[ unicodeUrlLen ] = L'\\0';\n\tmemset( &proxyInfo, 0, sizeof( WINHTTP_PROXY_INFO ) );\n\tif( pWinHttpGetProxyForUrl( hSession, unicodeURL, &autoProxyOptions,\n\t\t\t\t\t\t\t\t&proxyInfo ) != TRUE )\n\t\t{\n\t\tpWinHttpCloseHandle( hSession );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tproxyStatus = wcstombs_s( &wcsProxyLen, proxy, proxyMaxLen,\n\t\t\t\t\t\t\t  proxyInfo.lpszProxy, MAX_DNS_SIZE );\n\tGlobalFree( proxyInfo.lpszProxy );\n\tif( proxyInfo.lpszProxyBypass != NULL )\n\t\tGlobalFree( proxyInfo.lpszProxyBypass );\n\tpWinHttpCloseHandle( hSession );\n\tif( proxyStatus != 0 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t*proxyLen = wcsProxyLen;\n\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\n\ntypedef BOOL ( WINAPI *INTERNETGETPROXYINFO )( LPCSTR lpszUrl, DWORD dwUrlLength,\n\t\t\t\t\t\t\tLPSTR lpszUrlHostName, DWORD dwUrlHostNameLength,\n\t\t\t\t\t\t\tLPSTR* lplpszProxyHostName,\n\t\t\t\t\t\t\tLPDWORD lpdwProxyHostNameLength );\ntypedef BOOL ( WINAPI *INTERNETINITIALIZEAUTOPROXYDLL )( DWORD dwVersion,\n\t\t\t\t\t\t\tLPSTR lpszDownloadedTempFile, LPSTR lpszMime,\n\t\t\t\t\t\t\tAutoProxyHelperFunctions* lpAutoProxyCallbacks,\n\t\t\t\t\t\t\tLPAUTO_PROXY_SCRIPT_BUFFER lpAutoProxyScriptBuffer );\n\nstatic int findProxyUrl( char *proxy, const int proxyMaxLen, \n\t\t\t\t\t\t const char *url, const int urlLen )\n\t{\n\tstatic INTERNETGETPROXYINFO pInternetGetProxyInfo = NULL;\n\tstatic INTERNETINITIALIZEAUTOPROXYDLL pInternetInitializeAutoProxyDll = NULL;\n\tURL_INFO urlInfo;\n\tchar urlHost[ MAX_DNS_SIZE + 8 ];\n\tchar *proxyHost = NULL;\n\tint proxyHostLen, status;\n\n\tassert( isWritePtrDynamic( proxy, proxyMaxLen ) );\n\tassert( isReadPtrDynamic( url, urlLen ) );\n\n\tREQUIRES( proxyMaxLen > 10 && proxyMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( urlLen ) );\n\n\t/* This gets somewhat complicated, under Win2K SP3 and XP and newer (or \n\t   at least Windows versions with WinHTTP 5.1 installed in some way, it\n\t   officially shipped with the versions mentioned earlier) we can use\n\t   WinHTTP AutoProxy support, which implements the Web Proxy Auto-\n\t   Discovery (WPAD) protocol from an internet draft that expired in May\n\t   2001.  Under older versions of Windows we have to use the WinINet\n\t   InternetGetProxyInfo.\n\n\t   These functions were never meant to be used by the general public\n\t   (see the comment below) so they work in an extremely peculiar way\n\t   and only with the exact calling sequence that's used by MS code - it\n\t   looks like they were only intended as components of Windows-internal\n\t   implementation of proxy support since they require manual handling\n\t   of proxy config script downloading, parsing, and all manner of other\n\t   stuff that really doesn't concern us.  Because of the extreme\n\t   difficulty in doing anything with these functions we use the WinHTTP\n\t   approach instead */\n\tif( pInternetGetProxyInfo == NULL )\n\t\t{\n\t\tHMODULE hModJS;\n\n\t\tif( ( hModJS = DynamicLoad( \"JSProxy.dll\" ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\tpInternetGetProxyInfo = ( INTERNETGETPROXYINFO ) \\\n\t\t\t\t\tGetProcAddress( hModJS, \"InternetGetProxyInfo\" );\n\t\tpInternetInitializeAutoProxyDll = ( INTERNETINITIALIZEAUTOPROXYDLL ) \\\n\t\t\t\t\tGetProcAddress( hModJS, \"InternetInitializeAutoProxyDll\" );\n\t\tif( pInternetGetProxyInfo == NULL || \\\n\t\t\tpInternetInitializeAutoProxyDll == NULL )\n\t\t\t{\n\t\t\tDynamicUnload( hModJS );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\n\t\tpInternetInitializeAutoProxyDll( 0, TempFile, NULL,\n\t\t\t\t\t\t\t\t\t\t &HelperFunctions, NULL )\n\t\t}\n\n\t/* InternetGetProxyInfo() is a somewhat screwball undocumented function\n\t   that was crowbarred out of MS as part of the DoJ consent decree.  It\n\t   takes as input four parameters that do the work of a single\n\t   parameter, the null-terminated target URL string.  The documentation\n\t   for the function was initially wrong but has since been partially\n\t   corrected in places after user complaints, although there are still \n\t   missing parts as well as possible errors (why is it necessary to \n\t   specify a length for a supposedly null-terminated string?).  In order \n\t   to meet the strange input-parameter requirements we have to pre-\n\t   parse the target URL in order to provide the various bits and pieces \n\t   that InternetGetProxyInfo() requires */\n\tstatus = parseURL( &urlInfo, url, strlen( url ), 80, URL_TYPE_HTTP );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( urlInfo.hostLen > MAX_DNS_SIZE )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tREQUIRES( rangeCheck( urlInfo.hostLen, 1, MAX_DNS_SIZE );\n\tmemcpy( urlHost, urlInfo.host, urlInfo.hostLen );\n\turlHost[ urlInfo.hostLen ] = '\\0';\n\tif( !pInternetGetProxyInfo( url, strlen( url ), urlHost, urlInfo.hostLen,\n\t\t\t\t\t\t\t\t&proxyHost, &proxyHostLen ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tREQUIRES( rangeCheck( proxyHostLen, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( proxy, proxyHost, proxyHostLen );\n\tproxy[ proxyHostLen ] = '\\0';\n\tGlobalFree( proxyHost );\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n#endif /* Win32 */\n\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/net_trans.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tNetwork Stream Transport Functions\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tTransport-layer Direct Access Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Map the upper-layer I/O functions directly to the transport-layer\n   equivalent.  This is used if we're performing raw I/O without any\n   intermediate protocol layers or buffering */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportDirectReadFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\tOUT_BUFFER( maxLength, *length ) \\\n\t\t\t\t\t\t\t\t\t\t\tvoid *buffer, \n\t\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTM_TRANSPORTREAD_FUNCTION transportReadFunction;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES_S( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\ttransportReadFunction = ( STM_TRANSPORTREAD_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( netStream->transportReadFunction );\n\tREQUIRES_S( transportReadFunction != NULL );\n\n\treturn( transportReadFunction( netStream, buffer, maxLength, length,\n\t\t\t\t\t\t\t\t   TRANSPORT_FLAG_NONE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportDirectWriteFunction( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( maxLength ) const void *buffer, \n\t\t\t\t\t\t\t\t\t\t IN_DATALENGTH const int maxLength,\n\t\t\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTM_TRANSPORTWRITE_FUNCTION transportWriteFunction;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES_S( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\ttransportWriteFunction = ( STM_TRANSPORTWRITE_FUNCTION ) \\\n\t\t\t\t\t\t\t FNPTR_GET( netStream->transportWriteFunction );\n\tREQUIRES_S( transportWriteFunction != NULL );\n\n\treturn( transportWriteFunction( netStream, buffer, maxLength, length,\n\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_NONE ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerDirect( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tFNPTR_SET( netStream->writeFunction, transportDirectWriteFunction );\n\tFNPTR_SET( netStream->readFunction, transportDirectReadFunction );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tTransport-layer Virtual Stream Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send and receive data with a virtual stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int transportVirtualConnectFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const char *host, \n\t\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const int hostNameLen,\n\t\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const int port )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( ( host == NULL && hostNameLen == 0 ) || \\\n\t\t\t  ( host != NULL && \\\n\t\t\t    hostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE ) );\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\n\t/* This is a virtual stream so there's nothing to connect to */\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void transportVirtualDisconnectFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t\t\t\t\tconst BOOLEAN fullDisconnect )\n\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_V( fullDisconnect == TRUE || fullDisconnect == FALSE );\n\tREQUIRES_V( sanityCheckNetStream( netStream ) );\n\n\t/* This is a virtual stream so there's nothing to disconnect from */\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN transportVirtualOKFunction( void )\n\t{\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int transportVirtualCheckFunction( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int transportVirtualGetErrorInfo( INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\t\t\t\t const void *virtualStateInfo,\n\t\t\t\t\t\t\t\t\t\t IN_ERROR const int status )\n\t{\n\tSTM_VIRTUALGETERRORINFO_FUNCTION virtualGetErrorInfoFunction;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtr( virtualStateInfo, sizeof( void * ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tvirtualGetErrorInfoFunction = ( STM_VIRTUALGETERRORINFO_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->virtualGetErrorInfoFunction );\n\tENSURES( virtualGetErrorInfoFunction != NULL );\n\n\t/* Copy the extended error information up from the transport session to\n\t   the virtual network stream */\n\tvirtualGetErrorInfoFunction( virtualStateInfo, NETSTREAM_ERRINFO );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportVirtualReadFunction( INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\t\t\t\t OUT_BUFFER( maxLength, *length ) BYTE *buffer,\n\t\t\t\t\t\t\t\t\t\t IN_DATALENGTH const int maxLength,\n\t\t\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length,\n\t\t\t\t\t\t\t\t\t\t IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tSTM_READ_FUNCTION virtualGetDataFunction;\n\tvoid *virtualStateInfo;\n\tint status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t  flags == TRANSPORT_FLAG_NONBLOCKING || \\\n\t\t\t  flags == TRANSPORT_FLAG_BLOCKING );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* The buffered transport read functions will call the transport read \n\t   functions with TRANSPORT_FLAG_NONBLOCKING set when they perform a\n\t   speculative read to fill the buffering system with any data that may\n\t   be available on the network.  In the case of a virtual stream the \n\t   data is always available in the virtual stream, and an attempt to\n\t   peform a nonblocking read is meaningless, so we turn it into a no-op.\n\n\t   In practice it's a bit more complicated than this, the virtual \n\t   stream is typically backed by some form of physical stream, but we \n\t   can't tell what this is and so can't perform a speculative read on it \n\t   since there will be unknown latencies involved in the translation \n\t   from virtual to possible backing physical media.  In particular, \n\t   unlike a network stream we can't say \"read up to X bytes but don't\n\t   wait around if less than X are available\", we have to read the exact \n\t   number of requested bytes since speculatively trying to read extra\n\t   data may lead to indefinite delays in the physical layer.\n\t   \n\t   Since this is in effect disabling transport buffering, we could call \n\t   directly from the higher-level read function, for example HTTP, \n\t   through to the transport-level read function without going through \n\t   the bufferedTransportRead(), however this would require yet another \n\t   layer of indirection adding even further complexity to the already \n\t   complex path of, in the case of HTTP over TLS:\n\n\t\tHTTP read -> buffered read -> virtual read -> session read -> transport read\n\n\t   In addition the HTTP read code currently hardcodes the calls to the \n\t   buffered read functions, and bypassing that would require another \n\t   level of function pointers */\n\tif( flags == TRANSPORT_FLAG_NONBLOCKING )\n\t\treturn( CRYPT_OK );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\tvirtualGetDataFunction = ( STM_READ_FUNCTION ) \\\n\t\t\t\t\t\t\t FNPTR_GET( netStream->virtualGetDataFunction );\n\tENSURES( virtualGetDataFunction != NULL );\n\tvirtualStateInfo = ( void * ) DATAPTR_GET( netStream->virtualStateInfo );\n\tENSURES( virtualStateInfo != NULL );\n\n\tstatus = virtualGetDataFunction( virtualStateInfo, buffer, maxLength, \n\t\t\t\t\t\t\t\t\t length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( transportVirtualGetErrorInfo( netStream, virtualStateInfo, \n\t\t\t\t\t\t\t\t\t\t\t  status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int transportVirtualWriteFunction( INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t\t\t\t\t\t  IN_BUFFER( maxLength ) const BYTE *buffer,\n\t\t\t\t\t\t\t\t\t\t  IN_DATALENGTH const int maxLength,\n\t\t\t\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *length,\n\t\t\t\t\t\t\t\t\t\t  IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tSTM_WRITE_FUNCTION virtualPutDataFunction;\n\tvoid *virtualStateInfo;\n\tint status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t  flags == TRANSPORT_FLAG_FLUSH );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\tvirtualPutDataFunction = ( STM_WRITE_FUNCTION ) \\\n\t\t\t\t\t\t\t FNPTR_GET( netStream->virtualPutDataFunction );\n\tREQUIRES( virtualPutDataFunction != NULL );\n\tvirtualStateInfo = ( void * ) DATAPTR_GET( netStream->virtualStateInfo );\n\tENSURES( virtualStateInfo != NULL );\n\n\tstatus = virtualPutDataFunction( virtualStateInfo, buffer, maxLength, \n\t\t\t\t\t\t\t\t\t length );\n\tif( cryptStatusOK( status ) && flags == TRANSPORT_FLAG_FLUSH )\n\t\t{\n\t\tint flushBytesCopied;\n\n\t\tstatus = virtualPutDataFunction( virtualStateInfo, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t &flushBytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*length += flushBytesCopied;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( transportVirtualGetErrorInfo( netStream, virtualStateInfo, \n\t\t\t\t\t\t\t\t\t\t\t  status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid setAccessMethodTransportVirtual( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tFNPTR_SET( netStream->transportConnectFunction, \n\t\t\t   transportVirtualConnectFunction );\n\tFNPTR_SET( netStream->transportDisconnectFunction, \n\t\t\t   transportVirtualDisconnectFunction );\n\tFNPTR_SET( netStream->transportOKFunction, \n\t\t\t   transportVirtualOKFunction );\n\tFNPTR_SET( netStream->transportCheckFunction, \n\t\t\t   transportVirtualCheckFunction );\n\tFNPTR_SET( netStream->transportReadFunction, \n\t\t\t   transportVirtualReadFunction );\n\tFNPTR_SET( netStream->transportWriteFunction, \n\t\t\t   transportVirtualWriteFunction );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tBuffering Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Buffered transport-layer read function.  This sits on top of the\n   transport-layer read function and performs speculative read-ahead\n   buffering to improve performance in protocols such as HTTP that have to\n   read a byte at a time in places:\n\n\t\t   bPos\t\t   bEnd\n\t\t\t|\t\t\t|\n\t\t\tv\t\t\tv\n\t+-------+-----------+-------+\n\t|\t\t|///////////|\t\t|\n\t+-------+-----------+-------+\n\t\t\t -- Read -->\n\n   We fill the buffer to bEnd and then empty it by advancing bPos until \n   there isn't enough data left to satisfy the read, whereupon we move the \n   data down and refill from bEnd:\n\n   bPos\t\t   bEnd\n\t|\t\t\t|\n\tv\t\t\tv\n\t+-----------+---------------+\n\t|///////////|\t\t\t\t|\n\t+-----------+---------------+\n\t\t\t\t -- Write --> */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint bufferedTransportRead( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t   IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t   IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTM_TRANSPORTREAD_FUNCTION transportReadFunction;\n\tconst int bytesLeft = stream->bufEnd - stream->bufPos;\n\tint bufferBytesRead, bytesRead, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES_S( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES_S( isShortIntegerRange( bytesLeft ) );\n\tREQUIRES_S( isFlagRangeZ( flags, TRANSPORT ) );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\ttransportReadFunction = ( STM_TRANSPORTREAD_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( netStream->transportReadFunction );\n\tREQUIRES_S( transportReadFunction != NULL );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* If there's enough data in the buffer to satisfy the request, return it\n\t   directly */\n\tif( maxLength <= bytesLeft )\n\t\t{\n\t\tif( maxLength == 1 )\n\t\t\t{\n\t\t\t/* Optimisation for char-at-a-time HTTP header reads */\n\t\t\t*buffer = stream->buffer[ stream->bufPos++ ];\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES_S( boundsCheckZ( stream->bufPos, maxLength,\n\t\t\t\t\t\t\t\t\t  stream->bufEnd ) );\n\t\t\tmemcpy( buffer, stream->buffer + stream->bufPos, maxLength );\n\t\t\tstream->bufPos += maxLength;\n\t\t\t}\n\t\t*length = maxLength;\n\n\t\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We're about to refill the buffer, if there's a gap at the start move\n\t   everything down to make room for the new data */\n\tif( stream->bufPos > 0 )\n\t\t{\n\t\tif( bytesLeft > 0 )\n\t\t\t{\n\t\t\tREQUIRES_S( boundsCheck( stream->bufPos, bytesLeft,\n\t\t\t\t\t\t\t\t     stream->bufEnd ) );\n\t\t\tmemmove( stream->buffer, stream->buffer + stream->bufPos,\n\t\t\t\t\t bytesLeft );\n\t\t\t}\n\t\tstream->bufEnd = bytesLeft;\n\t\tstream->bufPos = 0;\n\t\t}\n\n\tENSURES_S( stream->bufPos == 0 );\n\tENSURES_S( maxLength > bytesLeft );\n\n\t/* If there's more room in the buffer, refill it */\n\tif( stream->bufEnd < stream->bufSize )\n\t\t{\n\t\tint bytesToRead;\n\n\t\t/* Calculate how many bytes we still need to read from the network into \n\t\t   the buffer and how much room there is in it.  If the read count is \n\t\t   less than the available buffer space we only read that much, any \n\t\t   further space will be filled (if possible) by the opportunistic \n\t\t   read that follows */\n\t\tbytesToRead = stream->bufSize - stream->bufEnd;\n\t\tif( bytesToRead > maxLength )\n\t\t\tbytesToRead = maxLength;\n\n\t\t/* Perform an explicitly blocking read of as many bytes as we can/are\n\t\t   asked for.  Since there may be data already present from an\n\t\t   earlier speculative read we only read as much as we actually need \n\t\t   in order to fulfill the request */\n\t\tREQUIRES_S( boundsCheckZ( stream->bufEnd, bytesToRead, \n\t\t\t\t\t\t\t\t  stream->bufSize ) );\n\t\tstatus = transportReadFunction( netStream, \n\t\t\t\t\t\t\t\t\t\tstream->buffer + stream->bufEnd, \n\t\t\t\t\t\t\t\t\t\tbytesToRead, &bytesRead, \n\t\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_BLOCKING );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstream->bufEnd += bytesRead;\n\n\t\t/* If there's room for more, perform an opportunistic nonblocking \n\t\t   read for whatever might still be there.  An error at this point \n\t\t   isn't fatal since this was only a speculative read  */\n\t\tif( stream->bufEnd < stream->bufSize )\n\t\t\t{\n\t\t\tstatus = transportReadFunction( netStream, \n\t\t\t\t\t\t\t\t\t\t\tstream->buffer + stream->bufEnd,\n\t\t\t\t\t\t\t\t\t\t\tstream->bufSize - stream->bufEnd,\n\t\t\t\t\t\t\t\t\t\t\t&bytesRead, \n\t\t\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_NONBLOCKING );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstream->bufEnd += bytesRead;\n\t\t\t}\n\t\t}\n\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t/* Read as much as we can from the buffer */\n\tbufferBytesRead = min( maxLength, stream->bufEnd );\n\tREQUIRES_S( rangeCheck( bufferBytesRead, 1, stream->bufEnd ) );\n\tmemcpy( buffer, stream->buffer, bufferBytesRead );\n\tstream->bufPos = bufferBytesRead;\n\t*length = bufferBytesRead;\n\n\t/* If we could satisfy the entire read from the buffer, we're done */\n\tif( maxLength <= bufferBytesRead )\t/* Actually length == bufferBytesRead */\n\t\t{\n\t\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've drained the stream buffer and there's more to go, read the\n\t   remainder directly into the caller's buffer.  What to return in case\n\t   there's a failure at this point is a bit tricky since we can \n\t   successfully return some data from the internal buffer but then fail \n\t   when we try and replenish the buffer from the network.  For now we \n\t   simply force the operation to be atomic since we're reading datagrams \n\t   that have to be read in their entirety */\n\tREQUIRES_S( boundsCheck( bufferBytesRead, maxLength - bufferBytesRead, \n\t\t\t\t\t\t\t maxLength ) );\n\tstatus = transportReadFunction( netStream, buffer + bufferBytesRead, \n\t\t\t\t\t\t\t\t\tmaxLength - bufferBytesRead, &bytesRead, \n\t\t\t\t\t\t\t\t\tTRANSPORT_FLAG_BLOCKING );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*length += bytesRead;\n\n\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Buffered transport-layer write function.  This sits on top of the\n   transport-layer write function and combines two (or more, although in\n   practice only two ever occur) writes into a single write.  The reason for\n   this is that when using TCP transport the delayed-ACK handling means\n   that performing two writes followed by a read (typical for HTTP messages) \n   leads to poor performance, usually made even worse by TCP slow-start.\n\n   The reason for this is that the TCP MSS is typically 1460 bytes on a LAN\n   (Ethernet) or 512/536 bytes on a WAN while HTTP headers are ~200-300 \n   bytes, far less than the MSS.  When an HTTP message is first sent the TCP \n   congestion window begins at one segment with the TCP slow-start then\n   doubling its size for each ACK.  Sending the headers separately will send \n   one short segment and a second MSS-size segment whereupon the TCP stack \n   will wait for the responder's ACK before continuing.  The responder gets \n   both segments and then delays its ACK for 200ms in the hopes of \n   piggybacking it on responder data, which is never sent since it's still\n   waiting for the rest of the HTTP body from the initiator.  This results \n   in a 200ms (+ assorted RTT) delay in each message sent.\n\n   There's a somewhat related situation that occurs as a result of TCP slow-\n   start and that can't be avoided programmatically in which we can't send \n   more than a single request initially, however most BSD-derived \n   implementations set the server's congestion window to two segments in\n   response to receiving the TCP handshake ACK so for the initial message\n   exchange the client can send a request of 1MSS and the server a response\n   of 2MSS without running into congestion-control problems.\n\n   A related problem is the fact that many TCP implementations will reset the\n   congestion window after one retransmission timeout period if all data sent\n   at that point has been ACKed, which means that both sides now restart with\n   a congestion window of size 1.  Unfortunately there's nothing that can be\n   done about this however hopefully at some point TCP implementations will\n   start to fall into line with RFC 3390 and allow initial windows of ~4K,\n   which will fix this particular problem.\n   \n   There are other, non-portable workarounds for this as well but they're so \n   non-portable that they often don't even work across different versions of \n   the same OS (e.g. different versions of the Linux kernel) let alone \n   variants of one OS type (e.g. OpenBSD vs. FreeBSD).  The least nonportable\n   one is using writev() to combine a seperate header and body, which exists\n   in most Unix versions and Win32.  Easier-to-use but almost totally non-\n   portable are facilities like TCP_CORK (newer Linux kernels) and \n   TCP_NOPUSH (some *BSDs) which delay sending buffer contents until the \n   flag is reset again (so the use is \"set TCP_CORK, write, write, write,\n   reset TCP_CORK\").  Because all of these are far more trouble than they're\n   worth and in any case we're only sending small data quantities via these \n   functions we just assemble the whole datagram ourselves, which works \n   across all OSes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int processIncompleteWrite( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t   IN_DATALENGTH const int bytesWritten,\n\t\t\t\t\t\t\t\t   IN_DATALENGTH_Z const int newDataToWrite,\n\t\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *newDataWritten )\n\t{\n\tconst int bytesLeftToWrite = netStream->writeBufEnd - bytesWritten;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( bytesWritten > 0 && bytesWritten < netStream->writeBufEnd && \\\n\t\t\t  bytesWritten < MAX_BUFFER_SIZE );\n\tREQUIRES( newDataToWrite >= 0 && newDataToWrite < MAX_BUFFER_SIZE );\n\t\t\t  /* May be zero if the write buffer was already full */\n\n\t/* Clear return value */\n\t*newDataWritten = 0;\n\n\t/* Determine how much was written from what the user gave us.  This is\n\t   complicated by the fact that the write buffer may already contain \n\t   buffered data from a previous write so we want to report to the \n\t   caller only what was written from the new data that was supplied:\n\n\t\t\t\t\t\t\t\t\t|<-- newDataToWrite --->|\n\t\t|<---------------------- bufEnd ------------------->|\n\t\t+---------------------------+-----------------------+\n\t\t| Existing data in buffer\t| New data copied in\t|\n\t\t+---------------------------+-----------------------+\n\t\t|<-- bytesWritten --> ........ <-- bytesLeftToWr -->|\n\t\n\t   We can tell whether only existing data or newly-copied-in data was\n\t   written based on whether bytesLeftToWrite covers only the new data \n\t   or whether it reaches back into the existing data in the buffer.  If\n\t   bytesLeftToWrite reaches back into the existing data then no new data\n\t   could be written */\n\tif( bytesLeftToWrite < newDataToWrite )\n\t\t*newDataWritten = newDataToWrite - bytesLeftToWrite;\n\n\t/* We couldn't write all of the data in the buffer, move what's left \n\t   down to the start.  This shouldn't be needed since the caller will \n\t   convert the failure to write the full amount into a write timeout but \n\t   we do it anyway just to be neat */\n\tREQUIRES( boundsCheck( bytesWritten, bytesLeftToWrite,\n\t\t\t\t\t\t   netStream->writeBufEnd ) );\n\tmemmove( netStream->writeBuffer, netStream->writeBuffer + bytesWritten,\n\t\t\t bytesLeftToWrite );\n\tnetStream->writeBufEnd = bytesLeftToWrite;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint bufferedTransportWrite( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_BUFFER( maxLength ) const BYTE *buffer, \n\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\tIN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\tSTM_TRANSPORTWRITE_FUNCTION transportWriteFunction;\n\tconst BYTE *bufPtr = buffer;\n\tint byteCount = maxLength, bytesWritten, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\tREQUIRES_S( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES_S( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t\tflags == TRANSPORT_FLAG_FLUSH );\n\n\t/* Set up the function pointers.  We have to do this after the netStream\n\t   check otherwise we'd potentially be dereferencing a NULL pointer */\n\ttransportWriteFunction = ( STM_TRANSPORTWRITE_FUNCTION ) \\\n\t\t\t\t\t\t\t FNPTR_GET( netStream->transportWriteFunction );\n\tREQUIRES_S( transportWriteFunction != NULL );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* If it's not a flush and the buffer can absorb the data, copy it in and\n\t   exit */\n\tif( !( flags & TRANSPORT_FLAG_FLUSH ) && \\\n\t\tnetStream->writeBufEnd + byteCount <= netStream->writeBufSize )\n\t\t{\n\t\tREQUIRES_S( boundsCheckZ( netStream->writeBufEnd, byteCount,\n\t\t\t\t\t\t\t\t  netStream->writeBufSize ) );\n\t\tmemcpy( netStream->writeBuffer + netStream->writeBufEnd, buffer, \n\t\t\t\tbyteCount );\n\t\tnetStream->writeBufEnd += byteCount;\n\t\t*length = byteCount;\n\n\t\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a flush or there's too much data to buffer, assemble a complete \n\t   buffer and write it */\n\tif( netStream->writeBufEnd > 0 )\n\t\t{\n\t\tint bytesToCopy;\n\n\t\t/* Calculate how much data we can still add to the buffer.  If the write \n\t\t   count is less than the available buffer size we only write that much */\n\t\tbytesToCopy = netStream->writeBufSize - netStream->writeBufEnd;\n\t\tif( bytesToCopy > byteCount )\n\t\t\tbytesToCopy = byteCount;\n\t\tif( bytesToCopy > 0 )\n\t\t\t{\n\t\t\tREQUIRES_S( boundsCheck( netStream->writeBufEnd, bytesToCopy,\n\t\t\t\t\t\t\t\t\t netStream->writeBufSize ) );\n\t\t\tmemcpy( netStream->writeBuffer + netStream->writeBufEnd, buffer,\n\t\t\t\t\tbytesToCopy );\n\t\t\tnetStream->writeBufEnd += bytesToCopy;\n\t\t\t}\n\t\tstatus = transportWriteFunction( netStream, netStream->writeBuffer, \n\t\t\t\t\t\t\tnetStream->writeBufEnd, &bytesWritten, \n\t\t\t\t\t\t\tTRANSPORT_FLAG_FLUSH );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( bytesWritten < netStream->writeBufEnd )\n\t\t\t{\n\t\t\tstatus = processIncompleteWrite( netStream, bytesWritten, \n\t\t\t\t\t\t\t\t\t\t\t bytesToCopy, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tnetStream->writeBufEnd = 0;\n\t\tif( bytesToCopy > 0 ) \n\t\t\t{\n\t\t\tbufPtr += bytesToCopy;\n\t\t\tbyteCount -= bytesToCopy;\n\t\t\tif( byteCount <= 0 )\n\t\t\t\t{\n\t\t\t\t/* We've written everything, exit */\n\t\t\t\t*length = maxLength;\n\n\t\t\t\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES_S( netStream->writeBufEnd == 0 );\n\n\t/* Write anything that's left directly */\n\tstatus = transportWriteFunction( netStream, bufPtr, byteCount, \n\t\t\t\t\t\t\t\t\t &bytesWritten, TRANSPORT_FLAG_FLUSH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( bytesWritten < byteCount )\n\t\t{\n\t\t/* Calculate how much remains to be written.  The overall amount \n\t\t   written was the total amount to write minus what's left \n\t\t   unwritten.  We don't have to update the stream buffer \n\t\t   information this time because the write buffer has already been\n\t\t   emptied */\n\t\tbyteCount -= bytesWritten;\n\t\t*length = maxLength - byteCount;\n\t\t}\n\telse\n\t\t{\n\t\t/* We managed to write everything */\n\t\t*length = maxLength;\n\t\t}\n\n\tENSURES_S( sanityCheckNetStream( netStream ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/net_url.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tNetwork Stream URL Processing Functions\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Sanity-check the URL parse state */\n\n#define checkUrlValue( data, dataLength, minLength, maxLength ) \\\n\t\t( ( data == NULL && dataLength == 0 ) || \\\n\t\t  ( data != NULL && \\\n\t\t\tdataLength >= minLength && dataLength <= maxLength ) )\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckURL( const URL_INFO *urlInfo )\n\t{\n\tassert( isReadPtr( urlInfo, sizeof( URL_INFO ) ) );\n\n\t/* Make sure that the URL type is valid.  URL_TYPE_NONE is valid since \n\t   it denotes an unrecognised URL type */\n\tif( !isEnumRangeOpt( urlInfo->type, URL_TYPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckURL: Type\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure the schema, user info, and location are either absent or \n\t   have valid values */\n\tif( !checkUrlValue( urlInfo->schema, urlInfo->schemaLen, \n\t\t\t\t\t\tMIN_SCHEMA_SIZE + 3, MAX_SCHEMA_SIZE + 3 ) )\n\t\t\t\t\t\t/* [...] + \"://\" */\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckURL: Schema\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !checkUrlValue( urlInfo->userInfo, urlInfo->userInfoLen, \n\t\t\t\t\t\t1, CRYPT_MAX_TEXTSIZE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckURL: User info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !checkUrlValue( urlInfo->location, urlInfo->locationLen, \n\t\t\t\t\t\tMIN_LOCATION_SIZE, MAX_LOCATION_SIZE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckURL: Location\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The host always has to be present */\n\tif( urlInfo->host == NULL || \\\n\t\turlInfo->hostLen < MIN_HOST_SIZE || \\\n\t\turlInfo->hostLen > MAX_HOST_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckURL: Host\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tURL Processing Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a schema */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkSchema( IN_BUFFER( schemaLen ) const void *schema, \n\t\t\t\t\t\tIN_RANGE( 2, 16 ) const int schemaLen,\n\t\t\t\t\t\tOUT_ENUM_OPT( URL_TYPE ) URL_TYPE *urlType,\n\t\t\t\t\t\tIN_ENUM_OPT( URL_TYPE ) URL_TYPE urlTypeHint )\n\t{\n\ttypedef struct {\n\t\tBUFFER_FIXED( schemaLength ) \\\n\t\tconst char *schema;\n\t\tconst int schemaLength;\n\t\tconst URL_TYPE type;\n\t\t} URL_SCHEMA_INFO;\n\tstatic const URL_SCHEMA_INFO urlSchemaInfo[] = {\n\t\t{ \"http://\", 7, URL_TYPE_HTTP },\n\t\t{ \"https://\", 8, URL_TYPE_HTTPS },\n\t\t{ \"wss://\", 6, URL_TYPE_WEBSOCKET },\n\t\t{ \"ssh://\", 6, URL_TYPE_SSH },\n\t\t{ \"scp://\", 6, URL_TYPE_SSH },\n\t\t{ \"sftp://\", 7, URL_TYPE_SSH },\n\t\t{ \"cmp://\", 6, URL_TYPE_CMP },\n\t\t{ \"tsp://\", 6, URL_TYPE_TSP },\n\t\t{ \"ldap://\", 7, URL_TYPE_LDAP },\n\t\t{ NULL, 0, URL_TYPE_NONE }, { NULL, 0, URL_TYPE_NONE }\n\t\t};\n\tURL_TYPE type;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( schema, schemaLen ) );\n\tassert( isWritePtr( urlType, sizeof( URL_TYPE ) ) );\n\n\tREQUIRES( schemaLen >= 2 && schemaLen <= 16 );\n\tREQUIRES( isEnumRangeOpt( urlTypeHint, URL_TYPE ) );\n\n\t/* Clear return value */\n\t*urlType = URL_TYPE_NONE;\n\n\t/* Check whether the schema is one that we recognise */\n\tLOOP_MED( i = 0, \n\t\t\t  urlSchemaInfo[ i ].type != URL_TYPE_NONE && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( urlSchemaInfo, URL_SCHEMA_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( urlSchemaInfo[ i ].schemaLength == schemaLen && \\\n\t\t\t!strCompare( urlSchemaInfo[ i ].schema, schema, schemaLen ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( urlSchemaInfo, URL_SCHEMA_INFO ) );\n\ttype = urlSchemaInfo[ i ].type;\n\n\t/* If there's no URL hint given, we're done */\n\tif( urlTypeHint == URL_TYPE_NONE )\n\t\t{\n\t\t*urlType = type;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that the URL type matches the hint.  A requirement for an \n\t   HTTPS URL can also match an HTTP URL, this type is used for SSL in \n\t   which the use of HTTPS is implied by the fact that an SSL session is \n\t   being used even if it's a straight HTTP URL.  In addition it can also\n\t   match a WSS, secure WebSockets URL, which is an additional transport\n\t   layer over the top of SSL.\n\t   \n\t   On the other hand an explicit HTTP URL must really be HTTP and not \n\t   just a generic HTTP/HTTPS mix */\n\tif( urlTypeHint == URL_TYPE_HTTPS )\n\t\t{\n\t\tif( type != URL_TYPE_HTTP && type != URL_TYPE_HTTPS && \\\n\t\t\ttype != URL_TYPE_WEBSOCKET )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\telse\n\t\t{\n\t\tif( type != urlTypeHint )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\t*urlType = type;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Parse a URI into:\n\n\t<schema>://[<user>@]<host>[:<port>]/<path>[?<query>] components\n\n   This function is intended for use from the internal interface (i.e. to\n   parse URLs supplied by the caller to the cryptlib API) and not so much\n   for the external interface (i.e. URLs supplied by remote systems for\n   processing by cryptlib).  Because of this it's rather more liberal with\n   what it'll accept than a generic URL parser would be.\n   \n   Note though that it does occasionally have to deal with externally-\n   supplied URLs, for example when breaking down a DNS name in a certificate \n   for comparison against the FQDN that the client is connecting to, so it \n   treats input as suspicious (an unqualified 'BYTE *' rather than a clean\n   'char *') until proven otherwise */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint parseURL( OUT URL_INFO *urlInfo, \n\t\t\t  IN_BUFFER( urlLen ) const BYTE *url, \n\t\t\t  IN_LENGTH_SHORT const int urlLen,\n\t\t\t  IN_PORT_OPT const int defaultPort, \n\t\t\t  IN_ENUM_OPT( URL_TYPE ) const URL_TYPE urlTypeHint,\n\t\t\t  const BOOLEAN preParseOnly )\n\t{\n\tconst char *strPtr, *hostName, *location;\n\tint strLen, hostNameLen, locationLen, offset, minLen;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( urlInfo, sizeof( URL_INFO ) ) );\n\tassert( isReadPtrDynamic( url, urlLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( urlLen ) );\n\tREQUIRES( defaultPort == CRYPT_UNUSED || \\\n\t\t\t  ( defaultPort >= MIN_PORT_NUMBER && \\\n\t\t\t\tdefaultPort <= MAX_PORT_NUMBER ) );\n\tREQUIRES( isEnumRangeOpt( urlTypeHint, URL_TYPE ) );\n\tREQUIRES( preParseOnly == TRUE || preParseOnly == FALSE );\n\n\t/* Clear return values */\n\tmemset( urlInfo, 0, sizeof( URL_INFO ) );\n\tif( defaultPort != CRYPT_UNUSED )\n\t\turlInfo->port = defaultPort;\n\n\t/* Make sure that the input contains valid characters */\n\tLOOP_MAX( offset = 0, offset < urlLen, offset++ )\n\t\t{\n\t\tconst int ch = byteToInt( url[ offset ] );\n\n\t\tif( !isValidTextChar( ch ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Skip leading and trailing whitespace */\n\tstrLen = strStripWhitespace( &strPtr, url, urlLen );\n\tif( strLen < MIN_DNS_SIZE || strLen > urlLen || strLen >= MAX_URL_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tANALYSER_HINT( strPtr != NULL );\n\n\t/* Strip syntactic sugar */\n\tif( ( offset = strFindStr( strPtr, strLen, \"://\", 3 ) ) >= 0 )\n\t\t{\n\t\t/* Extract the URI schema */\n\t\tif( offset < MIN_SCHEMA_SIZE || offset > strLen || \\\n\t\t\toffset > MAX_SCHEMA_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\toffset += 3;\t/* Adjust for \"://\" */\n\t\turlInfo->schema = strPtr;\n\t\turlInfo->schemaLen = offset;\n\t\tstrLen = strExtract( &strPtr, strPtr, offset, strLen );\n\t\tif( strLen < MIN_HOST_SIZE || strLen > MAX_URL_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Check whether the schema is one that we recognise */\n\t\tstatus = checkSchema( urlInfo->schema, urlInfo->schemaLen, \n\t\t\t\t\t\t\t  &urlInfo->type, urlTypeHint );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Check for user info before an '@' sign */\n\tif( ( offset = strFindCh( strPtr, strLen, '@' ) ) >= 0 )\n\t\t{\n\t\tconst char *userInfo;\n\t\tint userInfoLen;\n\n\t\t/* Extract the user info */\n\t\tif( offset < 1 || offset > strLen || offset > MAX_URL_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tuserInfoLen = strExtract( &userInfo, strPtr, 0, offset );\n\t\tif( userInfoLen < 1 || userInfoLen > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\turlInfo->userInfo = userInfo;\n\t\turlInfo->userInfoLen = userInfoLen;\n\n\t\t/* Skip the user info */\n\t\tstrLen = strExtract( &strPtr, strPtr, offset + 1, strLen );\n\t\tif( strLen < MIN_HOST_SIZE || strLen > MAX_URL_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* RFC 2732 requires that IPv6 addresses in URLs be delimited by square \n\t   brackets (at least one reason being that they use colons in their \n\t   string representation, which would conflict with the way that ports\n\t   are denoted in URLs) so if we find one at the start of the URI we \n\t   treat it as an IPv6 address */\n\tif( *strPtr == '[' && \\\n\t\t( strLen != 12 || strCompare( strPtr, \"[Autodetect]\", 12 ) ) )\n\t\t{\n\t\t/* Locate the end of the RFC 2732 IPv6 address.  The returned offset \n\t\t   can't be greater than the length - 1 but we make the check \n\t\t   explicit here to be sure */\n\t\tif( ( offset = strFindCh( strPtr, strLen, ']' ) ) <= 0 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tif( offset < 2 || offset > strLen - 1 || offset > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* If we're only pre-parsing the IPv6 address for future use rather \n\t\t   than actually parsing it to pass to the network address-\n\t\t   resolution functions then we have to leave the square-bracket \n\t\t   delimiters in place for when we perform the actual parse later \n\t\t   on */\n\t\tif( preParseOnly )\n\t\t\t{\n\t\t\thostName = strPtr;\n\t\t\thostNameLen = offset + 1;\t/* Include ']' */\n\t\t\tminLen = 4;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Extract the IPv6 address starting at position 1 (past the \n\t\t\t   '[') and ending at position 'offset' (before the ']') with \n\t\t\t   minimum length 2 */\n\t\t\thostNameLen = strExtract( &hostName, strPtr, 1, offset );\n\t\t\tminLen = 2;\n\t\t\t}\n\t\toffset++;\t/* Skip ']' */\n\t\t}\n\telse\n\t\t{\n\t\tint offset2;\n\n\t\t/* It's a non-IPv6 host name, check whether there's anything\n\t\t   following the name */\n\t\toffset = strFindCh( strPtr, strLen, ':' );\n\t\toffset2 = strFindCh( strPtr, strLen, '/' );\n\t\tif( offset < 0 )\n\t\t\toffset = offset2;\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( offset >= 0 );\n\t\t\tif( offset2 >= 0 )\n\t\t\t\toffset = min( offset, offset2 );\n\t\t\t}\n\t\tif( offset <= 0 )\n\t\t\t{\n\t\t\t/* The remaining string is the server name, we're done (the \n\t\t\t   string has already been trimmed in earlier code) */\n\t\t\turlInfo->host = strPtr;\n\t\t\turlInfo->hostLen = strLen;\n\n\t\t\tENSURES( sanityCheckURL( urlInfo ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* There's port/location info following the server name.  Trailing\n\t\t   whitespace will be stripped later */\n\t\thostNameLen = strExtract( &hostName, strPtr, 0, offset );\n\t\tminLen = MIN_HOST_SIZE;\n\t\t}\n\tif( hostNameLen < minLen || hostNameLen > MAX_HOST_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\turlInfo->host = hostName;\n\turlInfo->hostLen = hostNameLen;\n\n\t/* If there's nothing beyond the host name, we're done */\n\tif( offset >= strLen )\n\t\t{\n\t\tENSURES( sanityCheckURL( urlInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tstrLen = strExtract( &strPtr, strPtr, offset, strLen );\n\tif( strLen == 1 && *strPtr == '/' )\n\t\t{\n\t\t/* URLs may end in an optional no-op trailing '/' */\n\t\tENSURES( sanityCheckURL( urlInfo ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( strLen < 3 || strLen > MAX_URL_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Check for a port after a ':' */\n\tif( *strPtr == ':' )\n\t\t{\n\t\tint portStrLen, port;\n\n\t\t/* Skip the colon */\n\t\tstrLen = strExtract( &strPtr, strPtr, 1, strLen );\n\t\tif( strLen < 2 || strLen > MAX_URL_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Get the port to connect to */\n\t\tLOOP_LARGE( portStrLen = 0, \n\t\t\t\t\tportStrLen < strLen && isDigit( strPtr[ portStrLen ] ),\n\t\t\t\t\tportStrLen++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( portStrLen < 2 || portStrLen > 6 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tstatus = strGetNumeric( strPtr, portStrLen, &port, \n\t\t\t\t\t\t\t\tMIN_PORT_NUMBER, MAX_PORT_NUMBER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\turlInfo->port = port;\n\n\t\t/* If there's nothing beyond the port, we're done */\n\t\tif( portStrLen >= strLen )\n\t\t\t{\n\t\t\tENSURES( sanityCheckURL( urlInfo ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tstrLen = strExtract( &strPtr, strPtr, portStrLen, strLen );\n\t\tif( strLen == 1 && *strPtr == '/' )\n\t\t\t{\n\t\t\t/* URLs may end in an optional no-op trailing '/' */\n\t\t\tENSURES( sanityCheckURL( urlInfo ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( strLen < 3 || strLen > MAX_URL_SIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* What's left has to be a location */\n\tif( *strPtr != '/' )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* The location string includes the leading '/' so we set the start \n\t   offset to 0 and not 1 */\n\tlocationLen = strExtract( &location, strPtr, 0, strLen );\n\tif( locationLen < MIN_LOCATION_SIZE || locationLen > MAX_LOCATION_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\turlInfo->location = location;\n\turlInfo->locationLen = locationLen;\n\n\tENSURES( sanityCheckURL( urlInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/stream.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream I/O Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"stream_int.h\"\n#else\n  #include \"io/stream_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Sanity-check the stream state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckStream( const STREAM *stream )\n\t{\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check general stream metadata */\n\tif( !isEnumRange( stream->type, STREAM_TYPE ) || \\\n\t\t!CHECK_FLAGS( stream->flags, STREAM_FLAG_NONE, \n\t\t\t\t\t  STREAM_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckStream: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform stream type-specific checks */\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_NULL:\n\t\t\t/* Check that the stream metadata is valid */\n\t\t\tif( GET_FLAGS( stream->flags, STREAM_FLAG_MAX ) != 0 )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious null stream flags\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Null streams, which act as data sinks, have a virtual \n\t\t\t   content-length indicator so although the buffer size is zero \n\t\t\t   the buffer position values can be nonzero to indicate how \n\t\t\t   much (virtual) data they've absorbed */\n\t\t\tif( stream->buffer != NULL || stream->bufSize != 0 )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious null stream buffer\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( stream->bufPos < 0 || stream->bufPos > stream->bufEnd || \n\t\t\t\tstream->bufEnd < 0 || stream->bufEnd >= MAX_BUFFER_SIZE )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Null stream position\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Null streams have no further requirements so we're done */\n\t\t\treturn( TRUE );\n\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Check that the stream metadata is valid */\n\t\t\tif( TEST_FLAG( stream->flags, STREAM_MFLAG_VFILE ) )\n\t\t\t\t{\n\t\t\t\tif( !TEST_FLAGS( stream->flags, \n\t\t\t\t\t\t\t\t ~( STREAM_FLAG_MASK | \\\n\t\t\t\t\t\t\t\t\tSTREAM_MFLAG_VFILE | \\\n\t\t\t\t\t\t\t\t\tSTREAM_FFLAG_MASK ), 0 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Memory stream flags\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !TEST_FLAGS( stream->flags, ~STREAM_MFLAG_MASK, 0 ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious memory stream flags\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\t/* Check that the stream metadata is valid */\n\t\t\tif( !TEST_FLAGS( stream->flags, ~STREAM_FFLAG_MASK, 0 ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious file stream flags\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* File streams have to be explicitly connected to a buffer \n\t\t\t   after creation so if it's a partially-initialised file \n\t\t\t   stream then we allow an absent buffer */\n\t\t\tif( !TEST_FLAG( stream->flags, STREAM_FFLAG_BUFFERSET ) )\n\t\t\t\t{\n\t\t\t\tif( stream->buffer != NULL || stream->bufPos != 0 || \\\n\t\t\t\t\tstream->bufEnd != 0 || stream->bufSize != 0 )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious file buffer\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\n\t\t\t/* Make sure that the position within the file makes sense */\n\t\t\tif( stream->bufCount < 0 || \\\n\t\t\t\tstream->bufCount >= ( MAX_BUFFER_SIZE / stream->bufSize ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: File stream buffer position\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tbreak;\n#endif /* USE_FILES */\n\n#ifdef USE_TCP\n\t\tcase STREAM_TYPE_NETWORK:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\t/* Stream metadata is stored in the netStream structure, not the \n\t\t\t   main stream so there's no explicit metadata check apart from\n\t\t\t   the check the the netStream pointer is valid */\n\t\t\tif( !DATAPTR_ISVALID( stream->netStream ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Net stream pointer\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tENSURES( netStream != NULL );\n\n\t\t\t/* If it's an unbuffered network stream then all buffer values \n\t\t\t   must be zero */\n\t\t\tif( stream->buffer == NULL )\n\t\t\t\t{\n\t\t\t\tif( stream->bufPos != 0 || stream->bufSize != 0 || \\\n\t\t\t\t\tstream->bufEnd != 0 )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Spurious net stream buffer\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\t\n\n\t\t\t/* Check the network stream information */\n\t\t\tif( !sanityCheckNetStream( netStream ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Net stream info\" ));\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* If it's an unbuffered stream, we're done */\n\t\t\tif( stream->buffer == NULL )\n\t\t\t\treturn( TRUE );\n\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_TCP */\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Everything else requires a buffer */\n\tif( stream->buffer == NULL )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckStream: Stream buffer\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the buffer position is within bounds:\n\n\t\t\t\t\t\t\t\t bufSize\n\t\t\t\t\t\t\t\t\t|\n\t\t\t<------ buffer ------>\tv\n\t\t+---------------------------+\n\t\t|\t\t\t\t\t\t|\t|\n\t\t+---------------------------+\n\t\t\t\t^\t\t\t\t^\n\t\t\t\t|\t\t\t\t|\n\t\t\t bufPos\t\t\t bufEnd */\n\tif( stream->bufPos < 0 || stream->bufPos > stream->bufEnd || \\\n\t\tstream->bufEnd < 0 || stream->bufEnd > stream->bufSize || \\\n\t\tstream->bufSize <= 0 || stream->bufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckStream: Stream buffer info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the buffer hasn't been corrupted.  This check doesn't\n\t   apply to memory streams which are overlaid onto an existing memory \n\t   buffer for which we can't insert canaries */\n\tif( stream->type != STREAM_TYPE_MEMORY )\n\t\t{\n\t\tif( !safeBufferCheck( stream->buffer, stream->bufSize ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckStream: Buffer corruption\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n#ifdef USE_FILES\n\n/* Refill a stream buffer from backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int refillStream( INOUT STREAM *stream )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES_S( stream->bufPos >= stream->bufEnd || \\\n\t\t\t\tTEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) );\n\n\t/* If we've reached EOF then we can't refill the stream */\n\tif( TEST_FLAG( stream->flags, STREAM_FFLAG_EOF ) )\n\t\t{\n\t\t/* If partial reads are allowed return an indication of how much \n\t\t   data we got.  This only works once, after this the persistent \n\t\t   error state will return an underflow error before we get to this\n\t\t   point */\n\t\tstream->status = CRYPT_ERROR_UNDERFLOW;\n\t\treturn( TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) ? \\\n\t\t\t\tOK_SPECIAL : CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\n\t/* If we've moved to a different place in the file prepare to get new \n\t   data into the buffer at the new location */\n\tif( TEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) && \\\n\t\t!TEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED_NOSKIP ) )\n\t\t{\n\t\tstatus = fileSeek( stream, stream->bufCount * stream->bufSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( sSetError( stream, status ) );\n\t\t}\n\n\t/* Try and read more data into the stream buffer */\n\tstatus = fileRead( stream, stream->buffer, stream->bufSize, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( sSetError( stream, status ) );\n\tif( length < stream->bufSize )\n\t\t{\n\t\t/* If we got less than we asked for, remember that we're at the end\n\t\t   of the file */\n\t\tSET_FLAG( stream->flags, STREAM_FFLAG_EOF );\n\t\tif( length == 0 )\n\t\t\t{\n\t\t\t/* We ran out of input on an exact buffer boundary, if partial \n\t\t\t   reads are allowed return an indication of how much data we \n\t\t\t   got.  This only works once, after this the persistent error \n\t\t\t   state will return an underflow error before we get to this \n\t\t\t   point */\n\t\t\tstream->status = CRYPT_ERROR_UNDERFLOW;\n\t\t\treturn( TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) ? \\\n\t\t\t\t\tOK_SPECIAL : CRYPT_ERROR_UNDERFLOW );\n\t\t\t}\n\t\t}\n\n\t/* We've refilled the stream buffer from the file, remember the \n\t   details */\n\tif( !TEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) )\n\t\tstream->bufCount++;\n\tstream->bufEnd = length;\n\tstream->bufPos = 0;\n\tCLEAR_FLAGS( stream->flags, ( STREAM_FFLAG_POSCHANGED | \\\n\t\t\t\t\t\t\t\t  STREAM_FFLAG_POSCHANGED_NOSKIP ) );\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Empty a stream buffer to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int emptyStream( INOUT STREAM *stream, const BOOLEAN forcedFlush )\n\t{\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_FILE );\n\tREQUIRES_S( forcedFlush == TRUE || forcedFlush == FALSE );\n\n\t/* If the stream position has been changed, this can only have been from \n\t   a rewind of the stream, in which case we move back to the start of \n\t   the file */\n\tif( TEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) )\n\t\t{\n\t\tstatus = fileSeek( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( sSetError( stream, status ) );\n\t\t}\n\n\t/* Try and write the data to the stream's backing storage */\n\tstatus = fileWrite( stream, stream->buffer, stream->bufPos );\n\tif( cryptStatusError( status ) )\n\t\treturn( sSetError( stream, status ) );\n\n\t/* Reset the position-changed flag and, if we've written another buffer \n\t   full of data, remember the details.  If it's a forced flush we leave\n\t   everything as is so that we remember the last write position in the \n\t   file */\n\tCLEAR_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED );\n\tif( !forcedFlush )\n\t\t{\n\t\tstream->bufCount++;\n\t\tstream->bufPos = 0;\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_FILES */\n\n#ifdef VIRTUAL_FILE_STREAM \n\n/* Expand a virtual file stream's buffer to make room for new data when it\n   fills up */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int expandVirtualFileStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tIN_LENGTH const int length )\n\t{\n\tvoid *newBuffer;\n\tint newSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( sanityCheckStream( stream ) && \\\n\t\t\t\tsIsVirtualFileStream( stream ) );\n\tREQUIRES_S( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* If it's a small buffer allocated when we initially read a file and it \n\t   doesn't look like we'll be overflowing a standard-size buffer, just \n\t   expand it up to STREAM_VFILE_BUFSIZE */\n\tif( stream->bufSize < STREAM_VFILE_BUFSIZE && \\\n\t\tstream->bufPos + length < STREAM_VFILE_BUFSIZE - 1024 )\n\t\tnewSize = STREAM_VFILE_BUFSIZE;\n\telse\n\t\t{\n\t\t/* Increase the stream buffer size in STREAM_VFILE_BUFSIZE steps */\n\t\tnewSize = stream->bufSize + STREAM_VFILE_BUFSIZE;\n\t\t}\n\n\t/* Allocate the buffer and copy the new data across using a safe realloc \n\t   that wipes the original buffer.  If the malloc fails we return \n\t   CRYPT_ERROR_OVERFLOW rather than CRYPT_ERROR_MEMORY since the former \n\t   is more appropriate for the emulated-I/O environment */\n\tif( ( newBuffer = clDynAlloc( \"expandVirtualFileStream\", \\\n\t\t\t\t\t\t\t\t  stream->bufSize + STREAM_VFILE_BUFSIZE ) ) == NULL )\n\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\tmemcpy( newBuffer, stream->buffer, stream->bufEnd );\n\tzeroise( stream->buffer, stream->bufEnd );\n\tclFree( \"expandVirtualFileStream\", stream->buffer );\n\tstream->buffer = newBuffer;\n\tstream->bufSize = newSize;\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* VIRTUAL_FILE_STREAM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream Read Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read data from a stream */\n\nCHECK_RETVAL_RANGE( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sgetc( INOUT STREAM *stream )\n\t{\n\tint ch;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( stream->buffer, stream->bufSize ) );\n\t\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE );\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Read the data from the stream buffer */\n\t\t\tif( stream->bufPos >= stream->bufEnd )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\tch = byteToInt( stream->buffer[ stream->bufPos++ ] );\n\t\t\tbreak;\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\tREQUIRES_S( TEST_FLAG( stream->flags, \n\t\t\t\t\t\t\t\t   STREAM_FFLAG_BUFFERSET ) );\n\n\t\t\t/* Read the data from the file */\n\t\t\tif( stream->bufPos >= stream->bufEnd || \\\n\t\t\t\tTEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) )\n\t\t\t\t{\n\t\t\t\tint status = refillStream( stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( ( status == OK_SPECIAL ) ? 0 : status );\n\t\t\t\t}\n\t\t\tch = byteToInt( stream->buffer[ stream->bufPos++ ] );\n\t\t\tbreak;\n#endif /* USE_FILES */\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( ch );\n\t}\n\n/* See the comment in stream.h for the use of CHECK_RETVAL rather than\n   CHECK_RETVAL_LENGTH */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sread( INOUT STREAM *stream, \n\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t   IN_LENGTH const int length )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( stream->type == STREAM_TYPE_NETWORK || \\\n\t\t\tisReadPtrDynamic( stream->buffer, stream->bufSize ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\tif( !isWritePtrDynamic( buffer, length ) )\n\t\tretIntError_Stream( stream );\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE || \\\n\t\t\t\tstream->type == STREAM_TYPE_NETWORK );\n\tREQUIRES_S( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t{\n\t\t\tint localLength = length;\n\n#ifdef VIRTUAL_FILE_STREAM \n\t\t\t/* If partial reads are allowed return whatever's left in the\n\t\t\t   stream buffer.  This only occurs for virtual file streams  \n\t\t\t   that have been translated into memory streams */\n\t\t\tif( TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) )\n\t\t\t\t{\n\t\t\t\tREQUIRES_S( sIsVirtualFileStream( stream ) );\n\n\t\t\t\tlocalLength = stream->bufEnd - stream->bufPos;\n\t\t\t\tif( localLength > length )\n\t\t\t\t\tlocalLength = length;\n\t\t\t\t}\n#endif /* VIRTUAL_FILE_STREAM */\n#if defined( USE_TCP ) && !defined( NDEBUG )\n\t\t\tif( sIsPseudoHTTPRawStream( stream ) )\n\t\t\t\t{\n\t\t\t\tconst NET_STREAM_INFO *netStream = \\\n\t\t\t\t\t\tDATAPTR_GET( stream->netStream );\n\t\t\t\tSTM_READ_FUNCTION readFunction;\n\t\t\t\tint bytesRead;\n\n\t\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t\t\t\t/* Set up the function pointers.  We have to do this after \n\t\t\t\t   the netStream check otherwise we'd potentially be \n\t\t\t\t   dereferencing a NULL pointer */\n\t\t\t\treadFunction = ( STM_READ_FUNCTION ) \\\n\t\t\t\t\t\t\t   FNPTR_GET( netStream->readFunction );\n\t\t\t\tREQUIRES_S( readFunction != NULL );\n\n\t\t\t\tstatus = readFunction( stream, buffer, length, &bytesRead );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( sIsPseudoHTTPStream( stream ) )\n\t\t\t\t{\n\t\t\t\tHTTP_DATA_INFO *httpDataInfo = ( HTTP_DATA_INFO * ) buffer;\n\n\t\t\t\tREQUIRES_S( localLength == sizeof( HTTP_DATA_INFO ) );\n\n\t\t\t\t/* Pseudo-streams using HTTP transport have special \n\t\t\t\t   requirements since the output buffer isn't a direct \n\t\t\t\t   pointer to the buffer but an HTTP_DATA_INFO containing \n\t\t\t\t   information on the HTTP stream, so we have to copy\n\t\t\t\t   information across to/from the HTTP_DATA_INFO */\n\t\t\t\tbuffer = httpDataInfo->buffer;\n\t\t\t\thttpDataInfo->bytesAvail = stream->bufEnd;\n\t\t\t\tlocalLength = stream->bufEnd;\n\t\t\t\t}\n#endif /* USE_TCP && !NDEBUG */\n\n\t\t\t/* Read the data from the stream buffer */\n\t\t\tif( stream->bufPos + localLength > stream->bufEnd )\n\t\t\t\t{\n\t\t\t\tmemset( buffer, 0, min( 16, length ) );\t/* Clear output buffer */\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\t\t}\n\t\t\tREQUIRES_S( boundsCheckZ( stream->bufPos, localLength, \n\t\t\t\t\t\t\t\t\t  stream->bufEnd ) );\n\t\t\tmemcpy( buffer, stream->buffer + stream->bufPos, localLength );\n\t\t\tstream->bufPos += localLength;\n\n\t\t\t/* Usually reads are atomic so we just return an all-OK \n\t\t\t   indicator, however if we're performing partial reads we need\n\t\t\t   to return an exact byte count */\n\t\t\tstatus = TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) ? \\\n\t\t\t\t\t localLength : CRYPT_OK;\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\t\t\tif( sIsPseudoStream( stream ) )\n\t\t\t\t{\n\t\t\t\t/* Pseudo-streams are memory streams emulating other stream\n\t\t\t\t   types, so we need to return a byte count */\n\t\t\t\tstatus = localLength;\n\t\t\t\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\t\t\tbreak;\n\t\t\t}\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\t{\n\t\t\tBYTE *bufPtr = buffer;\n\t\t\tint dataLength, bytesCopied = 0, LOOP_ITERATOR;\n\n\t\t\tREQUIRES_S( TEST_FLAG( stream->flags, \n\t\t\t\t\t\t\t\t   STREAM_FFLAG_BUFFERSET ) );\n\n\t\t\t/* Read the data from the file */\n\t\t\tLOOP_LARGE_INITCHECK( dataLength = length, dataLength > 0 )\n\t\t\t\t{\n\t\t\t\tconst int oldDataLength = dataLength;\n\t\t\t\tint bytesToCopy;\n\n\t\t\t\t/* If the stream buffer is empty try and refill it */\n\t\t\t\tif( stream->bufPos >= stream->bufEnd || \\\n\t\t\t\t\tTEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = refillStream( stream );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\treturn( ( status == OK_SPECIAL ) ? \\\n\t\t\t\t\t\t\t\tbytesCopied : status );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t/* Copy as much data as we can out of the stream buffer */\n\t\t\t\tbytesToCopy = min( dataLength, \\\n\t\t\t\t\t\t\t\t   stream->bufEnd - stream->bufPos );\n\t\t\t\tREQUIRES_S( boundsCheckZ( stream->bufPos, bytesToCopy, \n\t\t\t\t\t\t\t\t\t\t  stream->bufEnd ) );\n\t\t\t\tmemcpy( bufPtr, stream->buffer + stream->bufPos, \n\t\t\t\t\t\tbytesToCopy );\n\t\t\t\tstream->bufPos += bytesToCopy;\n\t\t\t\tbufPtr += bytesToCopy;\n\t\t\t\tbytesCopied += bytesToCopy;\n\t\t\t\tdataLength -= bytesToCopy;\n\t\t\t\tENSURES_S( dataLength < oldDataLength );\n\t\t\t\t}\n\t\t\tENSURES_S( LOOP_BOUND_OK );\n\n\t\t\t/* Usually reads are atomic so we just return an all-OK \n\t\t\t   indicator, however if we're performing partial reads we need\n\t\t\t   to return an exact byte count */\n\t\t\tstatus = TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) ? \\\n\t\t\t\t\t bytesCopied : CRYPT_OK;\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_FILES */\n\n#ifdef USE_TCP\n\t\tcase STREAM_TYPE_NETWORK:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\t\t\tSTM_READ_FUNCTION readFunction;\n\t\t\tint bytesRead;\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( netStream->protocol != STREAM_PROTOCOL_HTTP || \\\n\t\t\t\t\t\t( netStream->protocol == STREAM_PROTOCOL_HTTP && \\\n\t\t\t\t\t\t  length == sizeof( HTTP_DATA_INFO ) ) );\n\n\t\t\t/* Set up the function pointers.  We have to do this after the \n\t\t\t   netStream check otherwise we'd potentially be dereferencing a \n\t\t\t   NULL pointer */\n\t\t\treadFunction = ( STM_READ_FUNCTION ) \\\n\t\t\t\t\t\t   FNPTR_GET( netStream->readFunction );\n\t\t\tREQUIRES_S( readFunction != NULL );\n\n\t\t\t/* Read the data from the network.  Reads are normally atomic\n\t\t\t   but if the partial-write flag is set can be restarted after\n\t\t\t   a timeout */\n\t\t\tstatus = readFunction( stream, buffer, length, &bytesRead );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If the lower-level code has indicated that the error \n\t\t\t\t   condition is fatal, make it persistent for the stream */\n\t\t\t\tif( cryptStatusError( netStream->persistentStatus ) )\n\t\t\t\t\tstream->status = netStream->persistentStatus;\n\n\t\t\t\t/* If it's not a special-case CRYPT_ERROR_COMPLETE status,\n\t\t\t\t   exit.  We don't make the error persistent since unlike\n\t\t\t\t   memory or file stream reads, most errors on network reads \n\t\t\t\t   are recoverable */\n\t\t\t\tif( status != CRYPT_ERROR_COMPLETE )\n\t\t\t\t\treturn( status );\n\n\t\t\t\t/* If we get a CRYPT_ERROR_COMPLETE status this means that\n\t\t\t\t   the other side has closed the connection.  This status is \n\t\t\t\t   returned when there are intermediate protocol layers such \n\t\t\t\t   as HTTP or tunnelling over a cryptlib session involved.\n\t\t\t\t   When this occurs we update the stream state and map the \n\t\t\t\t   status to a standard read error.  The exact code to \n\t\t\t\t   return here is a bit uncertain, it isn't specifically a \n\t\t\t\t   read error because either the other side is allowed to \n\t\t\t\t   close the connection after it's said its bit (and so it's \n\t\t\t\t   not a read error), or it has to perform a \n\t\t\t\t   cryptographically protected close (in which case any \n\t\t\t\t   non-OK status indicates a problem).  The most sensible \n\t\t\t\t   status is probably a read error */\n\t\t\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGR );\n\t\t\t\treturn( CRYPT_ERROR_READ );\n\t\t\t\t}\n\t\t\tif( !( TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD ) || \\\n\t\t\t\t   TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ENCAPS ) || \\\n\t\t\t\t   TEST_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM ) ) && \\\n\t\t\t\tbytesRead < length )\n\t\t\t\t{\n\t\t\t\t/* If we didn't read all of the data and partial reads \n\t\t\t\t   aren't allowed report a read timeout.  Note that this \n\t\t\t\t   code path is never taken for HTTP reads (with \n\t\t\t\t   STREAM_NFLAG_ENCAPS set) since the length information is\n\t\t\t\t   conveyed in the HTTP layer */\n\t\t\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t\t\t( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t  \"Read timed out with %d of %d bytes read\",\n\t\t\t\t\t\t  bytesRead, length ) );\n\t\t\t\t}\n\n\t\t\t/* This is an ugly case where we have to follow the Posix \n\t\t\t   semantics of returning a read-bytes count as the return \n\t\t\t   status rather than a by-reference parameter.  If we didn't\n\t\t\t   do this then every trivial memory-stream read would need to\n\t\t\t   pass in a dummy parameter for the read-byte-count value just\n\t\t\t   to handle the one or two calls to a network stream read that\n\t\t\t   needs to return a length */\n\t\t\tstatus = bytesRead;\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_TCP */\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream Write Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write data to a stream */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sputc( INOUT STREAM *stream, IN_BYTE const int ch )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( stream->type == STREAM_TYPE_NULL || \\\n\t\t\tisWritePtrDynamic( stream->buffer, stream->bufSize ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t\tstream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE );\n\tREQUIRES_S( !TEST_FLAG( stream->flags, STREAM_FLAG_READONLY ) );\n\tREQUIRES( ch >= 0 && ch <= 0xFF );\n\n\t/* If there's a problem with the stream don't try to do anything until\n\t   the error is cleared */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* If this is a pseudo-stream then writes are discarded */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tif( sIsPseudoStream( stream ) )\n\t\treturn( CRYPT_OK );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_NULL:\n\t\t\t/* It's a null stream, just record the write and return */\n\t\t\tstream->bufPos++;\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n\t\t\tbreak;\n\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Write the data to the stream buffer */\n\t\t\tif( stream->bufPos >= stream->bufSize )\n\t\t\t\t{\n#ifdef VIRTUAL_FILE_STREAM \n\t\t\t\tif( sIsVirtualFileStream( stream ) )\n\t\t\t\t\t{\n\t\t\t\t\tint status;\n\n\t\t\t\t\tstatus = expandVirtualFileStream( stream, 1 );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\t\t\t\telse\n#endif /* VIRTUAL_FILE_STREAM */\n\t\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t\t\t}\n\t\t\tstream->buffer[ stream->bufPos++ ] = intToByte( ch );\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n#ifdef VIRTUAL_FILE_STREAM \n\t\t\tif( sIsVirtualFileStream( stream ) )\n\t\t\t\t{\n\t\t\t\t/* This is a memory stream emulating a file stream, set the\n\t\t\t\t   dirty bit */\n\t\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_DIRTY );\n\t\t\t\t}\n#endif /* VIRTUAL_FILE_STREAM */\n\t\t\tbreak;\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\tREQUIRES_S( TEST_FLAG( stream->flags, \n\t\t\t\t\t\t\t\t   STREAM_FFLAG_BUFFERSET ) );\n\n\t\t\t/* Write the data to the file */\n\t\t\tif( stream->bufPos >= stream->bufSize )\n\t\t\t\t{\n\t\t\t\tint status;\n\n\t\t\t\tstatus = emptyStream( stream, FALSE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tstream->buffer[ stream->bufPos++ ] = intToByte( ch );\n\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_DIRTY );\n\t\t\tbreak;\n#endif /* USE_FILES */\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* See the comment in stream.h for the use of RETVAL rather than \n   RETVAL_LENGTH */\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint swrite( INOUT STREAM *stream, \n\t\t    IN_BUFFER( length ) const void *buffer, \n\t\t\tIN_LENGTH const int length )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( stream->type == STREAM_TYPE_NULL || \\\n\t\t\tstream->type == STREAM_TYPE_NETWORK || \\\n\t\t\tisWritePtrDynamic( stream->buffer, stream->bufSize ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\tif( !isReadPtrDynamic( buffer, length ) )\n\t\tretIntError_Stream( stream );\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t\tstream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE || \\\n\t\t\t\tstream->type == STREAM_TYPE_NETWORK );\n\tREQUIRES_S( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES_S( !TEST_FLAG( stream->flags, STREAM_FLAG_READONLY ) );\n\n\t/* If there's a problem with the stream don't try to do anything until\n\t   the error is cleared */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* If this is a pseudo-stream then writes are discarded */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tif( sIsPseudoStream( stream ) )\n\t\treturn( CRYPT_OK );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_NULL:\n\t\t\t/* It's a null stream, just record the write and return */\n\t\t\tstream->bufPos += length;\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Write the data to the stream buffer */\n\t\t\tif( stream->bufPos + length > stream->bufSize )\n\t\t\t\t{\n#ifdef VIRTUAL_FILE_STREAM \n\t\t\t\tif( sIsVirtualFileStream( stream ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = expandVirtualFileStream( stream, length );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\t\t\t\telse\n#endif /* VIRTUAL_FILE_STREAM */\n\t\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\t\t\t\t}\n\t\t\tREQUIRES_S( boundsCheckZ( stream->bufPos, length, \n\t\t\t\t\t\t\t\t\t  stream->bufSize ) );\n\t\t\tmemcpy( stream->buffer + stream->bufPos, buffer, length );\n\t\t\tstream->bufPos += length;\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n#ifdef VIRTUAL_FILE_STREAM \n\t\t\tif( sIsVirtualFileStream( stream ) )\n\t\t\t\t{\n\t\t\t\t/* This is a memory stream emulating a file stream, set the\n\t\t\t\t   dirty bit */\n\t\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_DIRTY );\n\t\t\t\t}\n#endif /* VIRTUAL_FILE_STREAM */\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\t{\n\t\t\tconst BYTE *bufPtr = buffer;\n\t\t\tint dataLength, LOOP_ITERATOR;\n\n\t\t\tREQUIRES_S( TEST_FLAG( stream->flags, \n\t\t\t\t\t\t\t\t   STREAM_FFLAG_BUFFERSET ) );\n\n\t\t\t/* Write the data to the file */\n\t\t\tLOOP_LARGE_INITCHECK( dataLength = length, dataLength > 0 )\n\t\t\t\t{\n\t\t\t\tconst int bytesToCopy = \\\n\t\t\t\t\t\tmin( dataLength, stream->bufSize - stream->bufPos );\n\n\t\t\t\tif( bytesToCopy > 0 )\n\t\t\t\t\t{\n\t\t\t\t\tREQUIRES_S( boundsCheckZ( stream->bufPos, bytesToCopy, \n\t\t\t\t\t\t\t\t\t\t\t  stream->bufSize ) );\n\t\t\t\t\tmemcpy( stream->buffer + stream->bufPos, bufPtr, \n\t\t\t\t\t\t\tbytesToCopy );\n\t\t\t\t\tstream->bufPos += bytesToCopy;\n\t\t\t\t\tbufPtr += bytesToCopy;\n\t\t\t\t\tdataLength -= bytesToCopy;\n\t\t\t\t\t}\n\t\t\t\tif( stream->bufPos >= stream->bufSize )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = emptyStream( stream, FALSE );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES_S( LOOP_BOUND_OK );\n\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_DIRTY );\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_FILES */\n\n#ifdef USE_TCP\n\t\tcase STREAM_TYPE_NETWORK:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\t\t\tSTM_WRITE_FUNCTION writeFunction;\n\t\t\tint bytesToWrite = length, bytesWritten;\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( netStream->protocol != STREAM_PROTOCOL_HTTP || \\\n\t\t\t\t\t\t( netStream->protocol == STREAM_PROTOCOL_HTTP && \\\n\t\t\t\t\t\t  length == sizeof( HTTP_DATA_INFO ) ) );\n\n\t\t\t/* Set up the function pointers.  We have to do this after the \n\t\t\t   netStream check otherwise we'd potentially be dereferencing a \n\t\t\t   NULL pointer */\n\t\t\twriteFunction = ( STM_WRITE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( netStream->writeFunction );\n\t\t\tREQUIRES_S( writeFunction != NULL );\n\n\t\t\t/* For an HTTP stream what we're sending to the write function \n\t\t\t   is an HTTP_DATA_INFO structure so we have to extract the \n\t\t\t   actual length information from that */\n\t\t\tif( netStream->protocol == STREAM_PROTOCOL_HTTP )\n\t\t\t\t{\n\t\t\t\tconst HTTP_DATA_INFO *httpDataInfo = \\\n\t\t\t\t\t\t\t\t\t( HTTP_DATA_INFO * ) buffer;\n\t\t\t\tbytesToWrite = httpDataInfo->bytesToWrite;\n\t\t\t\t}\n\n\t\t\t/* Write the data to the network.  Writes are normally atomic\n\t\t\t   but if the partial-write flag is set can be restarted after\n\t\t\t   a timeout */\n\t\t\tstatus = writeFunction( stream, buffer, length, &bytesWritten );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If the lower-level code has indicated that the error \n\t\t\t\t   condition is fatal, make it persistent for the stream */\n\t\t\t\tif( cryptStatusError( netStream->persistentStatus ) )\n\t\t\t\t\tstream->status = netStream->persistentStatus;\n\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tif( netStream->protocol == STREAM_PROTOCOL_HTTP )\n\t\t\t\t{\n\t\t\t\t/* As before, we need to extract the actual written length\n\t\t\t\t   value from the HTTP data structure */\n\t\t\t\tconst HTTP_DATA_INFO *httpDataInfo = \\\n\t\t\t\t\t\t\t\t\t( HTTP_DATA_INFO * ) buffer;\n\t\t\t\tbytesWritten = httpDataInfo->bytesTransferred;\n\t\t\t\t}\n\t\t\tif( bytesWritten < bytesToWrite && \\\n\t\t\t\t!TEST_FLAG( stream->flags, STREAM_FLAG_PARTIALWRITE ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_TIMEOUT, \n\t\t\t\t\t\t( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO, \n\t\t\t\t\t\t  \"Write timed out with %d of %d bytes written\",\n\t\t\t\t\t\t  bytesWritten, bytesToWrite ) );\n\t\t\t\t}\n\t\t\tstatus = bytesWritten;\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_TCP */\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( status );\n\t}\n\n#ifdef USE_FILES\n\n/* Commit data in a stream to backing storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sflush( INOUT STREAM *stream )\n\t{\n\tint status = CRYPT_OK, flushStatus;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( stream->buffer, stream->bufSize ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tif( !isReadPtrDynamic( stream->buffer, stream->bufSize ) )\n\t\tretIntError_Stream( stream );\n\n\tREQUIRES_S( sanityCheckStream( stream ) && \\\n\t\t\t\t( TEST_FLAG( stream->flags, STREAM_FFLAG_BUFFERSET ) || \\\n\t\t\t\t  sIsVirtualFileStream( stream ) ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_FILE || \\\n\t\t\t\tsIsVirtualFileStream( stream ) );\n\tREQUIRES_S( !TEST_FLAG( stream->flags, STREAM_FLAG_READONLY ) );\n\n\t/* If there's a problem with the stream don't try to do anything until\n\t   the error is cleared */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* If the data in the stream buffer is unchanged there's nothing to do */\n\tif( !TEST_FLAG( stream->flags, STREAM_FLAG_DIRTY ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If there's data still in the stream buffer and it's not a virtual \n\t   file stream that's handled via a memory stream (for which the data \n\t   is committed in an atomic operation when the file is flushed), write \n\t   it to disk.  If there's an error at this point we still try and flush \n\t   whatever data we have to disk so we don't bail out immediately if \n\t   there's a problem */\n\tif( stream->bufPos > 0 && !sIsVirtualFileStream( stream ) )\n\t\tstatus = emptyStream( stream, TRUE );\n\n\t/* Commit the data */\n\tflushStatus = fileFlush( stream );\n\tCLEAR_FLAG( stream->flags, STREAM_FLAG_DIRTY );\n\n\treturn( cryptStatusOK( status ) ? flushStatus : status );\n\t}\n#endif /* USE_FILES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMeta-data Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set/clear the error status of a stream.  sSetError() returns the error \n   status that it's passed so that it can be called using\n   'return( sSetError( stream, status ) );' */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sSetError( INOUT STREAM *stream, IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( cryptStatusError( status ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* If there's already an error status set don't try and override it */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\tstream->status = status;\n\n\treturn( status );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sClearError( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError_Void();\n\n\tstream->status = CRYPT_OK;\n\t}\n\n/* Determine whether a stream is a null stream */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sIsNullStream( const STREAM *stream )\n\t{\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isReadPtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError_Boolean();\n\n\treturn( ( stream->type == STREAM_TYPE_NULL ) ? TRUE : FALSE );\n\t}\n\n\n/* Move to an absolute position in a stream */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sseek( INOUT STREAM *stream, IN_LENGTH_Z const long position )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t\tstream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE );\n\tREQUIRES_S( position >= 0 && position < MAX_BUFFER_SIZE );\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_NULL:\n\t\t\t/* Move to the position in the stream buffer.  We never get \n\t\t\t   called directly with an sseek() on a memory stream, but end \n\t\t\t   up here via a translated sSkip() call */\n\t\t\tREQUIRES( isIntegerRange( position ) );\n\t\t\tstream->bufPos = ( int ) position;\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n\t\t\tbreak;\n\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Move to the position in the stream buffer */\n\t\t\tREQUIRES( isIntegerRange( position ) );\n\t\t\tif( ( int ) position > stream->bufSize )\n\t\t\t\t{\n\t\t\t\tstream->bufPos = stream->bufSize;\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\t\t}\n\t\t\tstream->bufPos = ( int ) position;\n\t\t\tif( stream->bufEnd < stream->bufPos )\n\t\t\t\tstream->bufEnd = stream->bufPos;\n\t\t\tbreak;\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\t{\n\t\t\tconst int blockOffset = ( stream->bufSize > 0 ) ? \\\n\t\t\t\t\t\t\t\t\tposition / stream->bufSize : 0;\n\t\t\tconst int byteOffset = ( stream->bufSize > 0 ) ? \\\n\t\t\t\t\t\t\t\t   position % stream->bufSize : 0;\n\n\t\t\t/* If it's a currently-disconnected file stream then all we can \n\t\t\t   do is rewind the stream.  This occurs when we're doing an \n\t\t\t   atomic flush of data to disk and we rewind the stream prior \n\t\t\t   to writing the new/updated data.  The next buffer-connect \n\t\t\t   operation will reset the stream state so there's nothing to \n\t\t\t   do at this point */\n\t\t\tif( !TEST_FLAG( stream->flags, STREAM_FFLAG_BUFFERSET ) )\n\t\t\t\t{\n\t\t\t\tREQUIRES_S( position == 0 );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\t/* Determine which buffer-size block of data we're moving to */\n\t\t\tif( TEST_FLAG( stream->flags, STREAM_FFLAG_EOF ) && \\\n\t\t\t\tblockOffset > stream->bufCount )\n\t\t\t\t{\n\t\t\t\t/* If this is the last buffer's worth and we're trying to \n\t\t\t\t   move past it, it's an error */\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\t\t}\n\t\t\tif( blockOffset != stream->bufCount )\n\t\t\t\t{\n\t\t\t\t/* We're not within the current buffer any more, remember \n\t\t\t\t   that we have to explicitly update the file position on\n\t\t\t\t   the next read */\n\t\t\t\tSET_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED );\n\n\t\t\t\t/* If we're already positioned to read the next bufferful \n\t\t\t\t   of data we don't have to explicitly skip ahead to it */\n\t\t\t\tif( blockOffset == stream->bufCount + 1 ) \n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( stream->flags, \n\t\t\t\t\t\t\t  STREAM_FFLAG_POSCHANGED_NOSKIP );\n\t\t\t\t\t}\n\n\t\t\t\tstream->bufCount = blockOffset;\n\t\t\t\t}\n\n\t\t\t/* Now that we've got the buffer-sized block handled, set up\n\t\t\t   the byte offset within the block */\n\t\t\tif( TEST_FLAG( stream->flags, STREAM_FFLAG_EOF ) && \\\n\t\t\t\tbyteOffset > stream->bufEnd )\n\t\t\t\t{\n\t\t\t\t/* We've tried to move past EOF, this is an error */\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\t\t}\n\n\t\t\tstream->bufPos = byteOffset;\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_FILES */\n\n\t\tdefault:\n\t\t\tretIntError_Stream( stream );\n\t\t}\n\n\tENSURES_S( sanityCheckStream( stream ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return the current posision in a stream */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, MAX_BUFFER_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint stell( const STREAM *stream )\n\t{\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isReadPtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* We can't use REQUIRE_S( sanityCheckStream() ) in this case because \n\t   the stream is a const parameter.  Since stell() is expected to return \n\t   a value in the range 0...stream->bufSize we don't use REQUIRES() \n\t   either but simply return an offset of zero */\n\tREQUIRES_EXT( sanityCheckStream( stream ), 0 );\n\tREQUIRES_EXT( ( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t\t\tstream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\t\tstream->type == STREAM_TYPE_FILE ), 0 );\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Stream is in invalid state\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n\t\t}\n\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_NULL:\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\treturn( stream->bufPos );\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\treturn( ( stream->bufCount * stream->bufSize ) + \\\n\t\t\t\t\tstream->bufPos );\n#endif /* USE_FILES */\n\t\t}\n\n\tretIntError_Ext( 0 );\n\t}\n\n/* Skip a number of bytes in a stream, with a bounds check on the maximum \n   allowable offset to skip */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sSkip( INOUT STREAM *stream, const long offset, \n\t\t   IN_DATALENGTH const long maxOffset )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NULL || \\\n\t\t\t\tstream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE );\n\tREQUIRES_S( offset > 0 );\n\tREQUIRES_S( maxOffset > 0 && maxOffset < MAX_BUFFER_SIZE );\n\n\t/* If there's a problem with the stream don't try to do anything */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* Make sure that the offset to skip is valid */\n\tif( offset > maxOffset || offset >= MAX_BUFFER_SIZE - stream->bufPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( sseek( stream, stream->bufPos + offset ) );\n\t}\n\n/* Peek at the next data value in a stream */\n\nCHECK_RETVAL_RANGE( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sPeek( INOUT STREAM *stream )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( stream->buffer, stream->bufSize ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_MEMORY || \\\n\t\t\t\tstream->type == STREAM_TYPE_FILE );\n\n\t/* If there's a problem with the stream don't try to do anything until\n\t   the error is cleared */\n\tif( cryptStatusError( stream->status ) )\n\t\treturn( stream->status );\n\n\t/* Read the data from the buffer, but without advancing the read pointer\n\t   like sgetc() does */\n\tswitch( stream->type )\n\t\t{\n\t\tcase STREAM_TYPE_MEMORY:\n\t\t\t/* Read the data from the stream buffer */\n\t\t\tif( stream->bufPos >= stream->bufEnd )\n\t\t\t\treturn( sSetError( stream, CRYPT_ERROR_UNDERFLOW ) );\n\t\t\treturn( stream->buffer[ stream->bufPos ] );\n\n#ifdef USE_FILES\n\t\tcase STREAM_TYPE_FILE:\n\t\t\tREQUIRES_S( TEST_FLAG( stream->flags, \n\t\t\t\t\t\t\t\t   STREAM_FFLAG_BUFFERSET ) );\n\n\t\t\t/* Read the data from the file */\n\t\t\tif( stream->bufPos >= stream->bufEnd || \\\n\t\t\t\tTEST_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED ) )\n\t\t\t\t{\n\t\t\t\tint status = refillStream( stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( ( status == OK_SPECIAL ) ? 0 : status );\n\t\t\t\t}\n\t\t\treturn( stream->buffer[ stream->bufPos ] );\n#endif /* USE_FILES */\n\t\t}\n\n\tretIntError_Stream( stream );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tIOCTL Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform an IOCTL on a stream.  There are two variations of this, a get and\n   a set form, which helps with type-checking compared to the usual do-anything\n   ioctl() */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setStreamBuffer( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_BUFFER_OPT( dataLen ) const void *data, \n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int dataLen )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( data == NULL && dataLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLen ) );\n\n\tREQUIRES_S( ( data == NULL && dataLen == 0 ) || \\\n\t\t\t\t( data != NULL && \\\n\t\t\t\t  dataLen > 0 && dataLen < MAX_BUFFER_SIZE ) );\n\tREQUIRES_S( dataLen == 0 || \\\n\t\t\t\tdataLen == 512 || dataLen == 1024 || \\\n\t\t\t\tdataLen == 2048 || dataLen == 4096 || \\\n\t\t\t\tdataLen == 8192 || dataLen == 16384 );\n\n#ifdef VIRTUAL_FILE_STREAM \n\t/* If it's a virtual file stream emulated in memory, don't do anything */\n\tif( sIsVirtualFileStream( stream ) )\n\t\treturn( CRYPT_OK );\n#endif /* VIRTUAL_FILE_STREAM */\n\n\t/* Set up the buffer variables.  File streams don't make use of the \n\t   bufEnd indicator so we set it to the same value as bufSize to ensure \n\t   that the stream passes the sanity checks */\n\tstream->buffer = ( void * ) data;\n\tstream->bufSize = stream->bufEnd = dataLen;\n\n\t/* We've switched to a new I/O buffer, reset all buffer- and stream-\n\t   state related variables and remember that we have to reset the stream \n\t   position since there may be a position-change pending that hasn't \n\t   been reflected down to the underlying file yet (if the position \n\t   change was within the same buffer then the POSCHANGED flag won't have \n\t   been set since only the bufPos will have changed) */\n\tstream->bufPos = stream->bufCount = 0;\n\tsClearError( stream );\n\tCLEAR_FLAGS( stream->flags, ( STREAM_FFLAG_BUFFERSET | \\\n\t\t\t\t\t\t\t\t  STREAM_FFLAG_EOF | \\\n\t\t\t\t\t\t\t\t  STREAM_FFLAG_POSCHANGED_NOSKIP ) );\n\tSET_FLAG( stream->flags, STREAM_FFLAG_POSCHANGED );\n\tif( data != NULL )\n\t\tSET_FLAG( stream->flags, STREAM_FFLAG_BUFFERSET );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlSet( INOUT STREAM *stream, \n\t\t\t   IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t   const int value )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* If this is a pseudo-stream then there's no network information \n\t   present to set information for */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tif( sIsPseudoStream( stream ) )\n\t\treturn( CRYPT_OK );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( ( ( stream->type == STREAM_TYPE_FILE || \\\n\t\t\t\t\tsIsVirtualFileStream( stream ) ) && \\\n\t\t\t\t( type == STREAM_IOCTL_IOBUFFER || \\\n\t\t\t\t  type == STREAM_IOCTL_PARTIALREAD ) ) || \\\n\t\t\t\t( stream->type == STREAM_TYPE_NETWORK ) );\n\tREQUIRES_S( isEnumRange( type, STREAM_IOCTL ) );\n\tREQUIRES_S( isIntegerRange( value ) );\n\n\tswitch( type )\n\t\t{\n\t\tcase STREAM_IOCTL_IOBUFFER:\n\t\t\tREQUIRES_S( value == 0 );\n\n\t\t\treturn( setStreamBuffer( stream, NULL, 0 ) );\n\n\t\tcase STREAM_IOCTL_PARTIALREAD:\n\t\t\tREQUIRES_S( value == FALSE || value == TRUE );\n\n\t\t\tif( value )\n\t\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD );\n\t\t\telse\n\t\t\t\tCLEAR_FLAG( stream->flags, STREAM_FLAG_PARTIALREAD );\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase STREAM_IOCTL_PARTIALWRITE:\n\t\t\tREQUIRES_S( value == FALSE || value == TRUE );\n\n\t\t\tif( value )\n\t\t\t\tSET_FLAG( stream->flags, STREAM_FLAG_PARTIALWRITE );\n\t\t\telse\n\t\t\t\tCLEAR_FLAG( stream->flags, STREAM_FLAG_PARTIALWRITE );\n\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_TCP\n\t\tcase STREAM_IOCTL_READTIMEOUT:\n\t\tcase STREAM_IOCTL_WRITETIMEOUT:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( isIntegerRange( value ) );\n\n\t\t\tnetStream->timeout = value;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_HANDSHAKECOMPLETE:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( value == TRUE );\n\t\t\tREQUIRES_S( isIntegerRangeNZ( netStream->timeout ) );\n\t\t\tREQUIRES_S( netStream->savedTimeout >= 0 && \\\n\t\t\t\t\t\tnetStream->savedTimeout < MAX_NETWORK_TIMEOUT );\n\n\t\t\t/* The security protocol handshake has completed, change the \n\t\t\t   stream timeout value from the connect/handshake timeout to\n\t\t\t   the standard data transfer timeout */\n\t\t\tnetStream->timeout = netStream->savedTimeout;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_LASTMESSAGE:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( value == TRUE );\n\t\t\tREQUIRES_S( netStream->protocol == STREAM_PROTOCOL_HTTP );\n\n\t\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_LASTMSGW );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_HTTPREQTYPES:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( isEnumRange( value, STREAM_HTTPREQTYPE ) );\n\t\t\tREQUIRES_S( netStream->protocol == STREAM_PROTOCOL_HTTP );\n\n\t\t\tCLEAR_FLAG( netStream->nhFlags, STREAM_NHFLAG_REQMASK );\n\t\t\tswitch( value )\n\t\t\t\t{\n\t\t\t\tcase STREAM_HTTPREQTYPE_GET:\n\t\t\t\t\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_GET );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STREAM_HTTPREQTYPE_POST:\n\t\t\t\t\tSET_FLAG( netStream->nhFlags, STREAM_NHFLAG_POST );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STREAM_HTTPREQTYPE_POST_AS_GET:\n\t\t\t\t\t/* This flag modifies the HTTP POST to encode it as a \n\t\t\t\t\t   GET, for b0rken servers that don't support POST */\n\t\t\t\t\tSET_FLAGS( netStream->nhFlags,\n\t\t\t\t\t\t\t   STREAM_NHFLAG_POST | \\\n\t\t\t\t\t\t\t   STREAM_NHFLAG_POST_AS_GET );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STREAM_HTTPREQTYPE_ANY:\n\t\t\t\t\tSET_FLAGS( netStream->nhFlags,\n\t\t\t\t\t\t\t   STREAM_NHFLAG_GET | STREAM_NHFLAG_POST );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase STREAM_HTTPREQTYPE_WS_UPGRADE:\n\t\t\t\t\t/* The WebSockets upgrade request is sent as a GET with\n\t\t\t\t\t   \"Connection: upgrade\", so we enable GET as well as \n\t\t\t\t\t   the WebSockets upgrade */\n\t\t\t\t\tSET_FLAGS( netStream->nhFlags,\n\t\t\t\t\t\t\t   STREAM_NHFLAG_GET | STREAM_NHFLAG_WS_UPGRADE );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_CLOSESENDCHANNEL:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\t\t\tSTM_TRANSPORTDISCONNECT_FUNCTION transportDisconnectFunction;\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( value == TRUE );\n\t\t\tREQUIRES_S( !TEST_FLAG( netStream->nFlags, \n\t\t\t\t\t\t\t\t\tSTREAM_NFLAG_USERSOCKET ) );\n\n\t\t\t/* Set up the function pointers.  We have to do this after the \n\t\t\t   netStream check otherwise we'd potentially be dereferencing a \n\t\t\t   NULL pointer */\n\t\t\ttransportDisconnectFunction = \\\n\t\t\t\t\t\t( STM_TRANSPORTDISCONNECT_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->transportDisconnectFunction );\n\t\t\tREQUIRES_S( transportDisconnectFunction != NULL );\n\n\t\t\t/* If this is a user-supplied socket we can't perform a partial \n\t\t\t   close without affecting the socket as seen by the user so we \n\t\t\t   only perform the partial close if it's a cryptlib-controlled \n\t\t\t   socket */\n\t\t\tif( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_USERSOCKET ) )\n\t\t\t\ttransportDisconnectFunction( netStream, FALSE );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_TCP */\n\t\t}\n\n\tretIntError_Stream( stream );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlSetString( INOUT STREAM *stream, \n\t\t\t\t\t IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t\t\t IN_BUFFER( dataLen ) const void *data, \n\t\t\t\t\t IN_DATALENGTH const int dataLen )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( data, dataLen ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tREQUIRES_S( ( sIsPseudoStream( stream ) && \\\n\t\t\t\t  type == STREAM_IOCTL_ERRORINFO ) || \\\n\t\t\t\t( ( stream->type == STREAM_TYPE_FILE || \\\n\t\t\t\t\tsIsVirtualFileStream( stream ) ) && \\\n\t\t\t\t  ( type == STREAM_IOCTL_ERRORINFO || \\\n\t\t\t\t\ttype == STREAM_IOCTL_IOBUFFER ) ) || \\\n\t\t\t\t( stream->type == STREAM_TYPE_NETWORK ) );\n#else\n\tREQUIRES_S( ( ( stream->type == STREAM_TYPE_FILE || \\\n\t\t\t\t\tsIsVirtualFileStream( stream ) ) && \\\n\t\t\t\t  ( type == STREAM_IOCTL_ERRORINFO || \\\n\t\t\t\t\ttype == STREAM_IOCTL_IOBUFFER ) ) || \\\n\t\t\t\t( stream->type == STREAM_TYPE_NETWORK ) );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\tREQUIRES_S( isEnumRange( type, STREAM_IOCTL ) );\n\tREQUIRES_S( dataLen > 0 && dataLen < MAX_BUFFER_SIZE );\n\n\tswitch( type )\n\t\t{\n\t\tcase STREAM_IOCTL_ERRORINFO:\n\t\t\t{\n#ifdef USE_TCP\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n#endif /* USE_TCP */\n\n\t\t\tREQUIRES_S( dataLen == sizeof( ERROR_INFO ) );\n\n\t\t\t/* If this stream type doesn't record extended error information\n\t\t\t   then there's nothing to do */\n\t\t\tif( stream->type != STREAM_TYPE_NETWORK )\n\t\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_TCP\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\n\t\t\t/* Copy the error information to the stream */\n\t\t\tcopyErrorInfo( NETSTREAM_ERRINFO, data );\n#endif /* USE_TCP */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_IOBUFFER:\n\t\t\tREQUIRES_S( dataLen == 0 || \\\n\t\t\t\t\t\tdataLen == 512 || dataLen == 1024 || \\\n\t\t\t\t\t\tdataLen == 2048 || dataLen == 4096 || \\\n\t\t\t\t\t\tdataLen == 8192 || dataLen == 16384 );\n\t\t\tREQUIRES_S( safeBufferCheck( data, dataLen ) );\n\n\t\t\treturn( setStreamBuffer( stream, data, dataLen ) );\n\t\t}\n\n\tretIntError_Stream( stream );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlGet( INOUT STREAM *stream, \n\t\t\t   IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t   OUT_BUFFER_FIXED( dataMaxLen ) void *data, \n\t\t\t   IN_LENGTH_SHORT const int dataMaxLen )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLen ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( stream, sizeof( STREAM ) ) )\n\t\tretIntError();\n\n\t/* If this is a pseudo-stream then there's no network information \n\t   present to get error information from */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tif( sIsPseudoStream( stream ) )\n\t\t{\n\t\tmemset( data, 0, dataMaxLen );\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\tREQUIRES_S( sanityCheckStream( stream ) );\n\tREQUIRES_S( stream->type == STREAM_TYPE_NETWORK );\n\tREQUIRES_S( isEnumRange( type, STREAM_IOCTL ) );\n\tREQUIRES_S( data != NULL );\n\tREQUIRES_S( isShortIntegerRangeNZ( dataMaxLen ) );\n\n\tswitch( type )\n\t\t{\n#ifdef USE_TCP\n\t\tcase STREAM_IOCTL_READTIMEOUT:\n\t\tcase STREAM_IOCTL_WRITETIMEOUT:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( dataMaxLen == sizeof( int ) );\n\n\t\t\t/* These two values are stored as a shared timeout value\n\t\t\t   which is updated on each data read or write by the\n\t\t\t   caller so there's no need to maintain distinct values */\n\t\t\t*( ( int * ) data ) = netStream->timeout;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_CONNSTATE:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( dataMaxLen == sizeof( int ) );\n\n\t\t\t*( ( int * ) data ) = TEST_FLAG( netStream->nFlags, \n\t\t\t\t\t\t\t\t\t\t\t STREAM_NFLAG_LASTMSGR ) ? \\\n\t\t\t\t\t\t\t\t  FALSE : TRUE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_GETCLIENTNAME:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( isShortIntegerRangeNZ( dataMaxLen ) );\n\n\t\t\tif( netStream->clientAddressLen <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\tif( netStream->clientAddressLen > dataMaxLen )\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\tREQUIRES_S( rangeCheck( netStream->clientAddressLen, 1, \n\t\t\t\t\t\t\t\t\tdataMaxLen ) );\n\t\t\tmemcpy( data, netStream->clientAddress, \n\t\t\t\t\tnetStream->clientAddressLen );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_GETCLIENTNAMELEN:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( dataMaxLen == sizeof( int ) );\n\n\t\t\tif( netStream->clientAddressLen <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*( ( int * ) data ) = netStream->clientAddressLen;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_GETPEERTYPE:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( dataMaxLen == sizeof( STREAM_PEER_TYPE ) );\n\n\t\t\t*( ( STREAM_PEER_TYPE * ) data ) = netStream->systemType;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase STREAM_IOCTL_GETCLIENTPORT:\n\t\t\t{\n\t\t\tNET_STREAM_INFO *netStream = DATAPTR_GET( stream->netStream );\n\n\t\t\tREQUIRES_S( netStream != NULL && sanityCheckNetStream( netStream ) );\n\t\t\tREQUIRES_S( dataMaxLen == sizeof( int ) );\n\n\t\t\tif( netStream->clientPort <= 0 )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t*( ( int * ) data ) = netStream->clientPort;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_TCP */\n\t\t}\n\n\tretIntError_Stream( stream );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_FILES\n\n/* Convert a file stream to a memory stream.  Usually this allocates a \n   buffer and reads the stream into it, however if it's a read-only memory-\n   mapped file it just creates a second reference to the data to save\n   memory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint sFileToMemStream( OUT STREAM *memStream, \n\t\t\t\t\t  INOUT STREAM *fileStream,\n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( length ) void **bufPtrPtr, \n\t\t\t\t\t  IN_DATALENGTH const int length )\n\t{\n\tvoid *bufPtr;\n\tint status;\n\n\tassert( isWritePtr( memStream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( fileStream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( bufPtrPtr, sizeof( void * ) ) );\n\n\t/* Check that the input parameters are in order */\n\tif( !isWritePtr( memStream, sizeof( STREAM ) ) || \\\n\t\t!isWritePtr( fileStream, sizeof( STREAM ) ) || \\\n\t\t!isWritePtr( bufPtrPtr, sizeof( void * ) ) )\n\t\t{\n\t\t/* Since memStream() is an OUT parameter we can't use it with a\n\t\t   retIntError_Stream() but have to use a plain retIntError() */\n\t\tretIntError();\n\t\t}\n\n\t/* We have to use REQUIRES() here rather than REQUIRES_S() since it's \n\t   not certain which of the two streams to set the status for */\n\tREQUIRES( sanityCheckStream( fileStream ) && \\\n\t\t\t  TEST_FLAG( fileStream->flags, STREAM_FFLAG_BUFFERSET ) );\n\tREQUIRES( fileStream->type == STREAM_TYPE_FILE );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( memStream, 0, sizeof( STREAM ) );\n\t*bufPtrPtr = NULL;\n\n#ifdef VIRTUAL_FILE_STREAM \n\t/* If it's a read-only memory-mapped file stream create the memory \n\t   stream as a reference to the file stream */\n\tif( TEST_FLAGS( fileStream->flags, \n\t\t\t\t\tSTREAM_FLAG_READONLY | STREAM_FFLAG_MMAPPED, \n\t\t\t\t\tSTREAM_FLAG_READONLY | STREAM_FFLAG_MMAPPED ) )\n\t\t{\n\t\t/* Make sure that there's enough data left in the memory-mapped\n\t\t   stream to reference it as a file stream */\n\t\tif( length > fileStream->bufSize - fileStream->bufPos )\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t\t/* Create a second reference to the memory-mapped stream and advance \n\t\t   the read pointer in the memory-mapped file stream to mimic the \n\t\t   behaviour of a read from it to the memory stream */\n\t\tsMemConnect( memStream, fileStream->buffer + fileStream->bufPos, \n\t\t\t\t\t length );\n\t\tstatus = sSkip( fileStream, length, SSKIP_MAX );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( memStream );\n\t\t\treturn( status );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* VIRTUAL_FILE_STREAM */\n\n\t/* It's a file stream, allocate a buffer for the data and read it in as\n\t   a memory stream */\n\tREQUIRES( rangeCheck( length, 1, MAX_BUFFER_SIZE ) );\n\tif( ( bufPtr = clAlloc( \"sFileToMemStream\", length ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tstatus = sread( fileStream, bufPtr, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"sFileToMemStream\", bufPtr );\n\t\treturn( status );\n\t\t}\n\tsMemConnect( memStream, bufPtr, length );\n\t*bufPtrPtr = bufPtr;\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_FILES */\n"
  },
  {
    "path": "deps/cl345/io/stream.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSTREAM Class Constants and Structures\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1993-2015\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _STREAM_DEFINED\n\n#define _STREAM_DEFINED\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n#if defined( __WIN32__ ) || defined( __WINCE__ )\n  /* Includes are always handled via the normal system includes */\n#elif defined( __UNIX__ ) || defined( __BEOS__ ) || defined( __XMK__ )\n  #include <unistd.h>\t\t/* For lseek() codes */\n#elif defined( __embOS__ )\n  #include <FS.h>\n#elif defined( __MAC__ )\n  #include <Files.h>\n#elif defined( __MQXRTOS__ )\n  /* MQX handles all stdio-related operations via a complex set of macros\n     mapping something to something else and then something else again, to\n\t deal with this if we're cross-compiling we pull in the internal file.h\n\t header which resolves the conflicts for us */\n  #ifdef _MSC_VER\n\t#include \"io/file.h\"\n  #else\n\t#include <mfs.h>\n  #endif /* Conflicting defines */\n#elif defined( __Nucleus__ )\n  #include <nucleus.h>\n  #include <pcdisk.h>\n#elif defined( __PALMOS__ )\n  #include <VFSMgr.h>\n#elif defined( __Quadros__ )\n  #include <udefs_s.h>\n  #include <api_s.h>\n#elif defined( __SMX__ )\n  #include <smx.h>\n  #include <smxfs.h>\n#elif defined( __Telit__ )\n  #include <m2m_fs_api.h>\n#elif defined( __UCOSII__ )\n  #include <fs_api.h>\t/* For uC/FS 2.x, renamed to fs.h in 3.x */\n#elif !defined( CONFIG_NO_STDIO )\n  #include <stdio.h>\n#endif /* System-specific file I/O headers */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tStream Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Access/option flags for the file stream open call.  These are:\n\n\tFLAG_EXCLUSIVE_ACCESS: Lock the file so that other threads/processes \n\t\tcan't open it until the current thread/process closes it.  This flag \n\t\tis implicitly set if the file R/W bits (via FLAG_RW_MASK) are \n\t\tFILE_WRITE, which creates a new file.  \n\n\tFLAG_READ/FLAG_WRITE: Open file for read/write access.\n\n\tFLAG_PRIVATE/FLAG_SENSITIVE: Specify the sensitivity of data in a file.  \n\t\tThe difference between the private and sensitive flags is that some \n\t\tdata may be private for a given user but not sensitive (e.g.config \n\t\tinfo) while other data may be private and sensitive (e.g.private \n\t\tkeys).  The sensitive flag only has an effect on special systems \n\t\twhere data can be committed to secure storage, since there's usually \n\t\ta very limited amount of this available we only use it for sensitive \n\t\tdata but not generic private data */\n\n#define FILE_FLAG_NONE\t\t0x00\t/* No file flag */\n#define FILE_FLAG_READ\t\t0x01\t/* Open file for read access */\n#define FILE_FLAG_WRITE\t\t0x02\t/* Open file for write access */\n#define FILE_FLAG_EXCLUSIVE_ACCESS 0x04\t/* Don't allow others access */\n#define FILE_FLAG_PRIVATE\t0x08\t/* Set ACL's to allow owner access only */\n#define FILE_FLAG_SENSITIVE\t0x10\t/* Use secure storage if available */\n#define FILE_FLAG_RW_MASK\t0x03\t/* Mask for R/W bits */\n#define FILE_FLAG_MAX\t\t0x1F\t/* Maximum possible flag value */\n\n/* Options for the build-path call */\n\ntypedef enum {\n\tBUILDPATH_NONE,\t\t\t\t\t/* No option type */\n\tBUILDPATH_CREATEPATH,\t\t\t/* Get path to config file, create if nec.*/\n\tBUILDPATH_GETPATH,\t\t\t\t/* Get path to config file */\n\tBUILDPATH_RNDSEEDFILE,\t\t\t/* Get path to random seed file */\n\tBUILDPATH_LAST\t\t\t\t\t/* Last valid option type */\n\t} BUILDPATH_OPTION_TYPE;\n\n/* Stream IOCTL types.  These are: \n\n\tIOCTL_CLOSESENDCHANNEL: Network streams, perform a sender-side close of \n\t\tthe network channel.\n\n\tIOCTL_CONNSTATE/IOCTL_LASTMESSAGE: Network streams, manage the last \n\t\tmessage in a stream.  IOCTL_LASTMESSAGE is write-only and specifies \n\t\tthat this is the last message to be sent, handled in HTTP by adding \n\t\ta \"Connection: close\" to the header.  IOCTL_CONNSTATE is read-only\n\t\tand specifies that the peer has indicated that this is the last \n\t\tmessage to be received (typically by the recipient seeing an HTTP\n\t\t\"Connection: close\"), so that after processing this message the \n\t\tchannel is considered closed.\n\n\tIOCTL_ERRORINFO: Set extended error information for the stream.\n\n\tIOCTL_GETxxx: Network stream, get various network-related parameters.\n\n\tIOCTL_HANDSHAKECOMPLETE: Network streams, change the stream timeout \n\t\tvalue from being applied to the handshake phase to being applied to \n\t\tthe data read/write phase.  Typically the handshake is blocking \n\t\twhile the data read/write is nonblocking, so different timeouts \n\t\tapply.\n\n\tIOCTL_HTTPREQTYPES: Network streams, specify the HTTP request types (as\n\t\ta STREAM_HTTPREQTYPE_xxx) that are permitted for this stream.\n\n\tIOCTL_IOBUFFER: File streams, set/clear the working buffer for I/O.\n\n\tIOCTL_PARTIALREAD/IOCTL_PARTIALWRITE: File streams, allow a read or \n\t\twrite of less than the total data amount specified in the length \n\t\tparameter, used when working with virtual file streams that have \n\t\tbeen translated into memory streams by the stream.c buffering.\n\n\tIOCTL_READTIMEOUT/IOCTL_WRITETIMEOUT: Network streams, set the read/\n\t\twrite timeout */\n\ntypedef enum {\n\tSTREAM_IOCTL_NONE,\t\t\t\t/* No IOCTL type */\n\tSTREAM_IOCTL_IOBUFFER,\t\t\t/* Working buffer for file streams */\n\tSTREAM_IOCTL_PARTIALREAD,\t\t/* Allow read of less than req.amount */\n\tSTREAM_IOCTL_PARTIALWRITE,\t\t/* Allow write of less then req.amount */\n\tSTREAM_IOCTL_READTIMEOUT,\t\t/* Network read timeout */\n\tSTREAM_IOCTL_WRITETIMEOUT,\t\t/* Network write timeout */\n\tSTREAM_IOCTL_HANDSHAKECOMPLETE,\t/* Toggle handshake vs.data timeout */\n\tSTREAM_IOCTL_CONNSTATE,\t\t\t/* Connection state (open/closed) */\n\tSTREAM_IOCTL_LASTMESSAGE,\t\t/* Last message in transaction */\n\tSTREAM_IOCTL_GETCLIENTNAME,\t\t/* Get client name */\n\tSTREAM_IOCTL_GETCLIENTNAMELEN,\t/* Get client name length */\n\tSTREAM_IOCTL_GETCLIENTPORT,\t\t/* Get client port */\n\tSTREAM_IOCTL_GETPEERTYPE,\t\t/* Get peer system type */\n\tSTREAM_IOCTL_HTTPREQTYPES,\t\t/* Permitted HTTP request types */\n\tSTREAM_IOCTL_CLOSESENDCHANNEL,\t/* Close send side of channel */\n\tSTREAM_IOCTL_ERRORINFO,\t\t\t/* Set stream extended error info */\n\tSTREAM_IOCTL_LAST\t\t\t\t/* Last possible IOCTL type */\n\t} STREAM_IOCTL_TYPE;\n\n/* Options for STREAM_IOCTL_HTTPREQTYPES */\n\ntypedef enum {\n\tSTREAM_HTTPREQTYPE_NONE,\t\t/* No HTTP request type */\n\tSTREAM_HTTPREQTYPE_GET,\t\t\t/* HTTP GET only */\n\tSTREAM_HTTPREQTYPE_POST,\t\t/* HTTP POST only */\n\tSTREAM_HTTPREQTYPE_POST_AS_GET,\t/* HTTP GET acting as a POST (b0rken svrs) */\n\tSTREAM_HTTPREQTYPE_ANY,\t\t\t/* HTTP GET or POST */\n\tSTREAM_HTTPREQTYPE_WS_UPGRADE,\t/* WebSockets Upgrade request */\n\tSTREAM_HTTPREQTYPE_LAST\t\t\t/* Last possible HTTP request type */\n\t} STREAM_HTTPREQTYPE_TYPE;\n\n/* Options for STREAM_IOCTL_GETPEERTYPE */\n\ntypedef enum {\n\tSTREAM_PEER_NONE,\t\t\t\t\t/* No information available */\n\tSTREAM_PEER_MICROSOFT,\t\t\t\t/* Windows Server generic */\n\tSTREAM_PEER_MICROSOFT_2008,\t\t\t/* Windows Server, 2008 bugs */\n\tSTREAM_PEER_MICROSOFT_2012,\t\t\t/* Windows Server, 2012 bugs */\n\tSTREAM_PEER_LAST\n\t} STREAM_PEER_TYPE;\n\n/* Stream network protocol types */\n\ntypedef enum {\n\tSTREAM_PROTOCOL_NONE,\t\t\t/* No protocol type */\n\tSTREAM_PROTOCOL_TCP,\t\t\t/* TCP */\n\tSTREAM_PROTOCOL_UDP,\t\t\t/* UDP */\n#ifdef USE_HTTP\n\tSTREAM_PROTOCOL_HTTP,\t\t\t/* HTTP */\n#endif /* USE_HTTP */\n#ifdef USE_EAP\n\tSTREAM_PROTOCOL_EAP,\t\t\t/* EAP */\n#endif /* USE_EAP */\n\tSTREAM_PROTOCOL_LAST\t\t\t/* Last possible protocol type */\n\t} STREAM_PROTOCOL_TYPE;\n\n/* The size of the I/O buffer used to read/write data from/to streams backed \n   by persistent files.  These are allocated on-demand on the stack, so they\n   shouldn't be made too big.  In addition since they may correspond \n   directly to underlying storage media blocks (e.g. disk sectors or flash \n   memory segments) they shouldn't be made smaller than the underlying \n   blocksize either.  Finally, they should be a power of two (this isn't a \n   strict requirement of the code, but is in a good idea in general because \n   of storage media constraints) */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define STREAM_BUFSIZE\t\t512\n#else\n  #define STREAM_BUFSIZE\t\t4096\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* When performing file I/O we need to know how large path names can get in\n   order to perform range checking and allocate buffers.  This gets a bit\n   tricky since not all systems have PATH_MAX, so we first try for PATH_MAX,\n   if that fails we try _POSIX_PATH_MAX (which is a generic 255 bytes and if\n   defined always seems to be less than whatever the real PATH_MAX should be),\n   if that also fails we grab stdio.h and try and get FILENAME_MAX, with an\n   extra check for PATH_MAX in case it's defined in stdio.h instead of\n   limits.h where it should be.  FILENAME_MAX isn't really correct since it's\n   the maximum length of a filename rather than a path, but some environments\n   treat it as if it were PATH_MAX and in any case it's the best that we can\n   do in the absence of anything better */\n\n#if defined( PATH_MAX )\n  #define MAX_PATH_LENGTH\t\tPATH_MAX\n#elif defined( _POSIX_PATH_MAX )\n  #define MAX_PATH_LENGTH\t\t_POSIX_PATH_MAX\n#elif defined( __embOS__ )\n  #define MAX_PATH_LENGTH\t\tFS_MAX_PATH\n#elif defined( __FileX__ )\n  #define MAX_PATH_LENGTH\t\tFX_MAXIMUM_PATH\n#else\n  #ifndef FILENAME_MAX\n\t#include <stdio.h>\n  #endif /* FILENAME_MAX */\n  #if defined( PATH_MAX )\n\t#define MAX_PATH_LENGTH\t\tPATH_MAX\n  #elif defined( MAX_PATH )\n\t#define MAX_PATH_LENGTH\t\tMAX_PATH\n  #elif defined( FILENAME_MAX )\n\t#define MAX_PATH_LENGTH\t\tFILENAME_MAX\n  #elif defined( __MSDOS16__ )\n\t#define FILENAME_MAX\t\t80\n  #else\n\t#error Need to add a MAX_PATH_LENGTH define in io/file.h\n  #endif /* OS-specific path length defines */\n#endif /* PATH_MAX */\n#if MAX_PATH_LENGTH <= 32\n  #error MAX_PATH_LENGTH is <= 32 characters, check your build environment\n#endif /* Too-short MAX_PATH values */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tStream Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The STREAM data type */\n\ntypedef struct ST {\n\t/* General information for the stream */\n\tint type;\t\t\t\t\t/* The stream type, of type STREAM_TYPE */\n\tSAFE_FLAGS flags;\t\t\t/* Stream flags */\n\tint status;\t\t\t\t\t/* Current stream status (clib error code) */\n\n\t/* Information for memory I/O */\n\tBUFFER_OPT( bufSize, bufEnd ) \\\n\tBYTE *buffer;\t\t\t\t/* Buffer to R/W to */\n\tint bufSize;\t\t\t\t/* Total size of buffer */\n\tint bufPos;\t\t\t\t\t/* Current position in buffer */\n\tint bufEnd;\t\t\t\t\t/* Last buffer position with valid data */\n\n\t/* Information for file I/O */\n\tint bufCount;\t\t\t\t/* File position quantised by buffer size */\n#if defined( __WIN32__ ) || defined( __WINCE__ )\n\tHANDLE hFile;\t\t\t\t/* Backing file for the stream */\n  #ifdef __TESTIO__\n\tchar name[ MAX_PATH_LENGTH + 8 ];/* Data item associated with stream */\n  #endif /* __TESTIO__ */\n#elif defined( __AMX__ ) || defined( __Android__ ) || \\\n\t  defined( __BEOS__ ) || defined( __ECOS__ ) || defined( __iOS__ ) || \\\n\t  defined( __MGOS__ ) || \\\n\t  ( defined( __MVS__ ) && !defined( CONFIG_NO_STDIO ) ) || \\\n\t  defined( __RTEMS__ ) || defined( __SYMBIAN32__ ) || \\\n\t  defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\t  defined( __UNIX__ ) || defined( __VxWorks__ ) || defined( __XMK__ )\n\tint fd;\t\t\t\t\t\t/* Backing file for the stream */\n  #ifdef __TESTIO__\n\tchar name[ MAX_PATH_LENGTH + 8 ];/* Data item associated with stream */\n  #endif /* __TESTIO__ */\n#elif defined( __FileX__ )\n\tFX_FILE filePtr;\t\t\t/* File associated with this stream */\n\tlong position;\t\t\t\t/* Position in file */\n#elif defined( __MAC__ )\n\tshort refNum;\t\t\t\t/* File stream reference number */\n\tFSSpec fsspec;\t\t\t\t/* File system specification */\n#elif defined( __MQXRTOS__ )\n\tMQX_FILE *filePtr;\t\t\t/* File associated with this stream */\n#elif defined( __PALMOS__ )\n\tFileRef fileRef;\t\t\t/* File reference number */\n#elif defined( __Quadros__ )\n\tFS_FILE *filePtr;\t\t\t/* File associated with this stream */\n#elif defined( __SMX__ )\n\tFILEHANDLE filePtr;\t\t\t/* File associated with this stream */\n#elif defined( __Telit__ )\n\tM2M_T_FS_HANDLE filePtr;\t/* File associated with this stream */\n#elif defined( __UCOSII__ ) || defined( __embOS__ )\n\tFS_FILE *pFile;\t\t\t\t/* File associated with this stream */\n#elif defined( CONFIG_NO_STDIO )\n  #if defined( __IBM4758__ )\n\tchar name[ 8 + 1 ];\t\t\t/* Data item associated with stream */\n\tBOOLEAN isSensitive;\t\t/* Whether stream contains sensitive data */\n  #elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __TESTIO__ )\n\tchar name[ MAX_PATH_LENGTH + 8 ];/* Data item associated with stream */\n  #endif /* Nonstandard I/O enviroments */\n#elif defined( __Nucleus__ )\n\tINT fd;\t\t\t\t\t\t/* File handle */\n#else\n\tFILE *filePtr;\t\t\t\t/* The file associated with this stream */\n#endif /* System-specific file I/O information */\n\n\t/* Network stream information.  This is dynamically allocated since it's \n\t   only used for (relatively rare) network streams and would lead to a \n\t   lot of wasted memory in the memory streams that are used constantly \n\t   throughout cryptlib */\n#ifdef USE_TCP\n\tDATAPTR netStream;\n#endif /* USE_TCP */\n\t} STREAM;\n\n/* Parsed URL information: schema://user@host:port/location.  This is used \n   to parse URL data from an in-memory string and encodes pointers to \n   locations in the string data */\n\ntypedef enum { URL_TYPE_NONE, URL_TYPE_HTTP, URL_TYPE_HTTPS, \n\t\t\t   URL_TYPE_WEBSOCKET, URL_TYPE_SSH, URL_TYPE_CMP, URL_TYPE_TSP, \n\t\t\t   URL_TYPE_LDAP, URL_TYPE_LAST } URL_TYPE;\n\ntypedef struct {\n\tURL_TYPE type;\n\tBUFFER_OPT_FIXED( schemaLen ) \\\n\tconst char *schema;\n\tint schemaLen;\n\tBUFFER_OPT_FIXED( userInfoLen ) \\\n\tconst char *userInfo;\n\tint userInfoLen;\n\tBUFFER_OPT_FIXED( hostLen ) \\\n\tconst char *host;\n\tint hostLen;\n\tBUFFER_OPT_FIXED( locationLen ) \\\n\tconst char *location;\n\tint locationLen;\n\tint port;\n\t} URL_INFO;\n\n/* HTTP request information as sent in a GET/POST */\n\ntypedef struct {\n\t/* URI information, attribute=value&extraData */\n\tconst char *attribute;\n\tint attributeLen;\n\tconst char *value;\n\tint valueLen;\n\tconst char *extraData;\n\tint extraDataLen;\n\n\t/* Additional information added to request headers */\n\tconst char *protocol;\t\t/* Subprotocol type */\n\tint protocolLen;\n\tconst char *auth;\t\t\t/* Access key/response */\n\tint authLen;\n\t} HTTP_REQ_INFO;\n\n/* HTTP URI information, location?attribute=value&extraData, parsed from a\n   string-form URI by the HTTP read code */\n\ntypedef struct {\n\t/* HTTP URI information */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, locationLen ) \\\n\tchar location[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, attributeLen ) \\\n\tchar attribute[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, valueLen ) \\\n\tchar value[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, extraDataLen ) \\\n\tchar extraData[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint locationLen, attributeLen, valueLen, extraDataLen;\n\n\t/* Additional information that can be sent in request headers */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, protocolLen ) \\\n\tchar protocol[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, authLen ) \\\n\tchar auth[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint protocolLen, authLen;\n\t} HTTP_URI_INFO;\n\n/* Information required when connecting a network stream.  There are so many\n   parameters required that we pack them into a struct to keep the interface\n   more manageable */\n\ntypedef enum {\n\tNET_OPTION_NONE,\t\t\t/* No connect option type */\n\tNET_OPTION_HOSTNAME,\t\t/* Use host/interface name + port */\n\tNET_OPTION_NETWORKSOCKET,\t/* Use user-supplied network socket */\n\tNET_OPTION_NETWORKSOCKET_DUMMY,\t/* Dummy open to check socket OK */\n\tNET_OPTION_VIRTUAL,\t\t\t/* Virtual session layered over actual one */\n\tNET_OPTION_LAST\t\t\t\t/* Last possible connect option type */\n\t} NET_OPTION_TYPE;\n\ntypedef struct {\n\t/* Network link information, either a remote host and port, a pre-\n\t   connected network socket, or read/write/get-error callbacks and state \n\t   storage for a virtual network layer */\n\tBUFFER_OPT_FIXED( nameLength ) \\\n\tconst char *name;\n\tint nameLength;\n\tint port;\t\t\t\t\t/* Remote host info */\n\tconst char *interface;\n\tint interfaceLength;\t\t/* Local interface info */\n\tint networkSocket;\t\t\t/* Pre-connected network socket */\n\tFNPTR virtualGetDataFunction, virtualPutDataFunction;\n\tFNPTR virtualGetErrorInfoFunction;\n\tDATAPTR virtualStateInfo;\t/* State info for virtual R/W */\n\n\t/* Auxiliary information: Owning user object, network status \n\t   information, general option type, and optional authentication \n\t   information */\n\tCRYPT_USER iUserObject;\t\t/* Owning user object */\n\tint timeout, connectTimeout;/* Connect and data xfer.timeouts */\n\tNET_OPTION_TYPE options;\t/* Connect options */\n\tBUFFER_OPT_FIXED( authNameLength ) \\\n\tconst char *authName;\n\tint authNameLength;\t\t\t/* Authentication name */\n\tBUFFER_OPT_FIXED( authKeyLength ) \\\n\tconst char *authKey;\n\tint authKeyLength;\t\t\t/* Authentication key */\n\t} NET_CONNECT_INFO;\n\n#define initNetConnectInfo( netConnectInfo, netUserObject, netTimeout, \\\n\t\t\t\t\t\t\tnetConnectTimeout, netOption ) \\\n\t{ \\\n\tmemset( netConnectInfo, 0, sizeof( NET_CONNECT_INFO ) ); \\\n\t( netConnectInfo )->networkSocket = CRYPT_ERROR; \\\n\tFNPTR_SET( ( netConnectInfo )->virtualGetDataFunction, NULL ); \\\n\tFNPTR_SET( ( netConnectInfo )->virtualPutDataFunction, NULL ); \\\n\tFNPTR_SET( ( netConnectInfo )->virtualGetErrorInfoFunction, NULL ); \\\n\tDATAPTR_SET( ( netConnectInfo )->virtualStateInfo, NULL ); \\\n\t( netConnectInfo )->iUserObject = netUserObject; \\\n\t( netConnectInfo )->timeout = netTimeout; \\\n\t( netConnectInfo )->connectTimeout = netConnectTimeout; \\\n\t( netConnectInfo )->options = netOption; \\\n\t}\n\n/* Information required when reading from/writing to an HTTP stream.  \n   Although we're in theory just using HTTP as a universal substrate,\n   there's a pile of additional HTTP-related data that we have to convey,\n   so when we perform a read or write to an HTTP stream we use a composite\n   data parameter */\n\ntypedef struct {\n\t/* Data payload informtion.  On read the { buffer, bufSize } is the \n\t   amount of buffer space available to read data, with bytesAvail being\n\t   the length of the data item being read into the buffer and \n\t   bytesTransferred being the amount of data actually transferred.  On \n\t   write the { buffer, bufSize } is the data to write and \n\t   bytesTransferred is the amount actually transferred.  We have to\n\t   store this information here because the write call is passed the\n\t   HTTP_DATA_INFO structure rather than the data buffer so we can't \n\t   return a bytes-read or written count as the return value */\n\tBUFFER_UNSPECIFIED( bufSize ) \\\n\tvoid *buffer;\t\t\t\t\t/* Data buffer */\n\tint bufSize;\t\t\t\t\t/* Size of data buffer */\n\tint bytesToWrite;\t\t\t\t/* Bytes to write on write */\n\tint bytesAvail, bytesTransferred;\t/* Actual data bytes on read */\n\tBUFFER_FIXED( contentTypeLen ) \\\n\tconst char *contentType;\t\t/* HTTP content type */\n\tint contentTypeLen;\t\n\n\t/* HTTP read/write control flags.  If the bufferResize flag is set then \n\t   the HTTP read code can dynamically resize the buffer in order to read \n\t   arbitrary-length input.  If the buffer was resized during the read \n\t   then the flag is returned set and the caller has to reset their read \n\t   buffer to { buffer, bufSize }.  If no resize took place then the flag \n\t   is returned cleared.\n\t   \n\t   If the responseIsText flag is set then a text/plain response from the \n\t   server is valid.  Normally messages have application-specific message \n\t   types and the only time we'd see plain text is if the server is \n\t   returning an error message (usually outside the spec of the protocol \n\t   that we're talking), however if additional capabilities have been \n\t   kludged onto the protocol via text-format messages then a response-\n\t   type of text/pain is valid */\n\tBOOLEAN bufferResize;\t\t\t/* Buffer is resizeable */\n\tBOOLEAN responseIsText;\t\t\t/* Response from svr.is text/plain */\n\n\t/* The client's request type and request info (for HTTP GET/POST) or\n\t   the server's parsed URI info from the client, and the server's \n\t   status in response to a client GET/POST request */\n\tSTREAM_HTTPREQTYPE_TYPE reqType;/* HTTP request type */\n\tconst HTTP_REQ_INFO *reqInfo;\n\tHTTP_URI_INFO *uriInfo;\n\tint reqStatus;\t\t\t\t/* HTTP status in response to request */\n\t} HTTP_DATA_INFO;\n\n#define initHttpInfoRead( httpDataInfo, buffer, bufSize ) \\\n\t\tinitHttpInfo( httpDataInfo, buffer, bufSize, 0, NULL, NULL )\n#define initHttpInfoReadEx( httpDataInfo, buffer, bufSize, uriInfo ) \\\n\t\tinitHttpInfo( httpDataInfo, buffer, bufSize, 0, NULL, uriInfo )\n#define initHttpInfoWrite( httpDataInfo, buffer, dataLength, bufSize ) \\\n\t\tinitHttpInfo( httpDataInfo, buffer, bufSize, dataLength, NULL, NULL )\n#define initHttpInfoWriteEx( httpDataInfo, buffer, dataLength, bufSize, reqInfo ) \\\n\t\tinitHttpInfo( httpDataInfo, buffer, bufSize, dataLength, reqInfo, NULL )\n#define initHttpInfoReq( httpDataInfo ) \\\n\t\tinitHttpInfo( httpDataInfo, NULL, 0, 0, NULL, NULL )\n#define initHttpInfoReqEx( httpDataInfo, reqInfo ) \\\n\t\tinitHttpInfo( httpDataInfo, NULL, 0, 0, reqInfo, NULL )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initHttpInfo( INOUT HTTP_DATA_INFO *httpDataInfo, \n\t\t\t\t  OUT_BUFFER_OPT_FIXED( bufSize ) void *buffer, \n\t\t\t\t  IN_LENGTH_Z const int bufSize,\n\t\t\t\t  IN_LENGTH_Z const int dataLength,\n\t\t\t\t  IN_OPT const HTTP_REQ_INFO *reqInfo,\n\t\t\t\t  OUT_OPT HTTP_URI_INFO *uriInfo );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream Function Prototypes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions corresponding to traditional/stdio-type I/O.\n\n   The annotation for sread() and swrite() are a bit dishonest in that in \n   almost all cases what's returned is a pure status code, it's only for \n   network streams and special-case streams that allow partial reads that a \n   length can be returned.  If we were to use CHECK_RETVAL_LENGTH then the \n   belief that a returned status value isn't really a true status gets \n   propagated up through every function that reads or writes data, leading\n   to endless false-positive warnings */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sputc( INOUT STREAM *stream, IN_BYTE const int ch );\nCHECK_RETVAL_RANGE( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sgetc( INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sread( INOUT STREAM *stream, \n\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t   IN_LENGTH const int length );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint swrite( INOUT STREAM *stream, \n\t\t    IN_BUFFER( length ) const void *buffer, \n\t\t\tIN_LENGTH const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sflush( INOUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sseek( INOUT STREAM *stream, IN_LENGTH_Z const long position );\nCHECK_RETVAL_RANGE_NOERROR( 0, MAX_BUFFER_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint stell( const STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlSet( INOUT STREAM *stream, \n\t\t\t   IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t   const int value );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlSetString( INOUT STREAM *stream, \n\t\t\t\t\t IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t\t\t IN_BUFFER( dataLen ) const void *data, \n\t\t\t\t\t IN_DATALENGTH const int dataLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sioctlGet( INOUT STREAM *stream, \n\t\t\t   IN_ENUM( STREAM_IOCTL ) const STREAM_IOCTL_TYPE type, \n\t\t\t   OUT_BUFFER_FIXED( dataMaxLen ) void *data, \n\t\t\t   IN_LENGTH_SHORT const int dataMaxLen );\n\n/* Nonstandard functions: Skip a number of bytes in a stream, peek at the\n   next value in the stream.  The sSkip() call applies a bounds check, the\n   define SSKIP_MAX can be used to denote the maximum length allowed */\n\n#define SSKIP_MAX\t( MAX_BUFFER_SIZE - 1 )\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sSkip( INOUT STREAM *stream, const long offset, \n\t\t   IN_DATALENGTH const long maxOffset );\nCHECK_RETVAL_RANGE( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sPeek( INOUT STREAM *stream );\n\n/* Inquire as to the health of a stream.  Currently these are only used in \n   debugging assertions, in int_api.c when exporting attributes to a stream,\n   and as a safety check in ssl_rw.c/ssh2_rw.c when wrapping a packet that \n   needs direct access to a memory stream */\n\n#define sGetStatus( stream )\t\t( stream )->status\n#define sStatusOK( stream )\t\t\tcryptStatusOK( ( stream )->status )\n\n/* Set/clear a user-defined error state for the stream */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sSetError( INOUT STREAM *stream, IN_ERROR const int status );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sClearError( INOUT STREAM *stream );\n\n/* Stream query functions to determine whether a stream is a null stream,\n   a memory-mapped file stream, or a virtual file stream.  The null stream \n   check is used to short-circuit unnecessary data transfers in higher-level \n   code where writing to a null stream is used to determine overall data \n   sizes.  The memory-mapped stream check is used when we can eliminate \n   extra buffer allocation if all data is available in memory.  The virtual\n   file stream check is used where the low-level access routines have\n   converted a file on a CONFIG_NO_STDIO system to a memory stream that acts\n   like a file stream */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sIsNullStream( const STREAM *stream );\n\n/* Functions to work with memory streams.  A null stream is a special case of a \n   memory stream that just acts as a data sink.  In some cases we may want to \n   open either a null stream or a standard memory stream depending on whether \n   the caller has specified an output buffer or not, in this case we provide a\n   function sMemOpenOpt() to indicate that it's OK for the buffer value to be \n   NULL.\n   \n   Note that the open/connect functions are declared with a void return \n   type, this is because they're used in hundreds of locations and the only \n   situation in which they can fail is a programming error.  Because of \n   this, problems are caught by throwing exceptions in debug builds rather \n   than having to add error handling for every case where they're used.  In \n   addition the functions always initialise the stream, setting it to an \n   invalid stream if there's an error, so there's no real need to check a\n   return value */ \n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemOpen( OUT STREAM *stream, \n\t\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t   IN_LENGTH const int length );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sMemOpenOpt( OUT STREAM *stream, \n\t\t\t\t  OUT_BUFFER_OPT_FIXED( length ) void *buffer, \n\t\t\t\t  IN_LENGTH_Z const int length );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sMemNullOpen( OUT STREAM *stream );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemClose( INOUT STREAM *stream );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemConnect( OUT STREAM *stream, \n\t\t\t\t  IN_BUFFER( length ) const void *buffer, \n\t\t\t\t  IN_LENGTH const int length );\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sMemPseudoConnect( OUT STREAM *stream, \n\t\t\t\t\t    IN_BUFFER( length ) const void *buffer,\n\t\t\t\t\t    IN_LENGTH const int length );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemDisconnect( INOUT STREAM *stream );\n\n/* Memory stream direct-access functions, used when the contents of a memory\n   stream need to be encrypted/decrypted/signed/MACd.  The basic \n   sMemGetDataBlock() returns a data block of a given size from the current\n   stream position, sMemGetDataBlockAbs() returns a data block from the \n   given stream position, and sMemGetDataBlockRemaining() returns a data \n   block containing all remaining data available in the stream.  The stream\n   parameter is given as an INOUT even though the stream contents aren't\n   strictly affected because the functions can set the stream error state \n   in the case of a failure */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, MAX_BUFFER_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint sMemDataLeft( const STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sMemGetDataBlock( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( dataSize ) void **dataPtrPtr, \n\t\t\t\t\t  IN_DATALENGTH const int dataSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint sMemGetDataBlockAbs( INOUT STREAM *stream, \n\t\t\t\t\t\t IN_DATALENGTH_Z const int position, \n\t\t\t\t\t\t OUT_BUFFER_ALLOC_OPT( dataSize ) void **dataPtrPtr, \n\t\t\t\t\t\t IN_DATALENGTH const int dataSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint sMemGetDataBlockRemaining( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( *length ) void **dataPtrPtr, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length );\n\n/* Functions to work with file streams */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sFileOpen( OUT STREAM *stream, IN_STRING const char *fileName, \n\t\t\t   IN_FLAGS( FILE ) const int mode );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sFileClose( INOUT STREAM *stream );\n\n/* Convert a file stream to a memory stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint sFileToMemStream( OUT STREAM *memStream, \n\t\t\t\t\t  INOUT STREAM *fileStream,\n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( length ) void **bufPtrPtr, \n\t\t\t\t\t  IN_DATALENGTH const int length );\n\n/* Special-case file I/O calls */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN fileReadonly( IN_STRING const char *fileName );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileClearToEOF( STREAM *stream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid fileErase( IN_STRING const char *fileName );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint fileBuildCryptlibPath( OUT_BUFFER( pathMaxLen, *pathLen ) char *path, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 32 ) const int pathMaxLen, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( pathMaxLen ) int *pathLen,\n\t\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen,\n\t\t\t\t\t\t   IN_ENUM( BUILDPATH ) \\\n\t\t\t\t\t\t\t\tconst BUILDPATH_OPTION_TYPE option );\n\n/* Functions to work with network streams */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sNetParseURL( OUT URL_INFO *urlInfo, \n\t\t\t\t  IN_BUFFER( urlLen ) const BYTE *url, \n\t\t\t\t  IN_LENGTH_SHORT const int urlLen, \n\t\t\t\t  IN_ENUM_OPT( URL_TYPE ) const URL_TYPE urlTypeHint );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetConnect( OUT STREAM *stream, \n\t\t\t\t IN_ENUM( STREAM_PROTOCOL ) const STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\t const NET_CONNECT_INFO *connectInfo, \n\t\t\t\t OUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint sNetListen( OUT STREAM *stream, \n\t\t\t\tIN_ENUM( STREAM_PROTOCOL ) const STREAM_PROTOCOL_TYPE protocol,\n\t\t\t\tconst NET_CONNECT_INFO *connectInfo, \n\t\t\t\tOUT ERROR_INFO *errorInfo );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sNetDisconnect( INOUT STREAM *stream );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid sNetGetErrorInfo( INOUT STREAM *stream, OUT ERROR_INFO *errorInfo );\n\n/* Initialisation/shutdown functions for network stream interfaces */\n\n#ifdef USE_TCP\n  RETVAL \\\n  int netInitTCP( void );\n  void netSignalShutdown( void );\n  void netEndTCP( void );\n#else\n  #define netInitTCP()\t\t\t\t\t\tCRYPT_OK\n  #define netSignalShutdown()\n  #define netEndTCP()\n#endif /* NET_TCP */\n\n#endif /* _STREAM_DEFINED */\n"
  },
  {
    "path": "deps/cl345/io/stream_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal STREAM Header File\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1993-2011\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _STREAM_INT_DEFINED\n\n#define _STREAM_INT_DEFINED\n\n#if defined( INC_ALL )\n  #include \"stream.h\"\n#else\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tStream Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The stream types */\n\ntypedef enum {\n\tSTREAM_TYPE_NONE,\t\t\t\t\t/* No stream type */\n\tSTREAM_TYPE_NULL,\t\t\t\t\t/* Null stream (/dev/nul) */\n\tSTREAM_TYPE_MEMORY,\t\t\t\t\t/* Memory stream */\n\tSTREAM_TYPE_FILE,\t\t\t\t\t/* File stream */\n\tSTREAM_TYPE_NETWORK,\t\t\t\t/* Network stream */\n\tSTREAM_TYPE_LAST\t\t\t\t\t/* Last possible stream type */\n\t} STREAM_TYPE;\n\n/* General-purpose stream flags.  These are:\n\n\tFLAG_DIRTY: Stream buffer contains data that needs to be committed to\n\t\tbacking store.\n\n\tFLAG_PARTIALREAD: Used for network reads to handle timeouts and for file \n\t\tstreams when we don't know the full extent of a file stream.  When \n\t\tthis is set and we ask for a read of n bytes and there isn't \n\t\tsufficient data present in the file to satisfy the request the \n\t\tstream code returns 0...n bytes rather than an underflow error.\n\n\tFLAG_PARTIALWRITE: Used for network streams when performing bulk data \n\t\ttransfers, in this case the write may time out and can be restarted\n\t\tlater rather than returning a timeout error.\n\n\tFLAG_READONLY: Stream is read-only */\n\n#define STREAM_FLAG_NONE\t\t0x0000\t/* No stream flag */\n#define STREAM_FLAG_READONLY\t0x0001\t/* Read-only stream */\n#define STREAM_FLAG_PARTIALREAD 0x0002\t/* Allow read of less than req.amount */\n#define STREAM_FLAG_PARTIALWRITE 0x0004\t/* Allow write of less than req.amount */\n#define STREAM_FLAG_DIRTY\t\t0x0008\t/* Stream contains un-committed data */\n#define STREAM_FLAG_MASK\t\t0x000F\t/* Mask for general-purpose flags */\n\n/* Memory stream flags.  These are:\n\n\tMFLAG_PSEUDO/PSEUDO_HTTP/PSEUDO_DIRECT: Used for memory streams \n\t\temulating some other stream type, writes are discarded and reads \n\t\tcome from the stream buffer.  The HTTP flag is an additional \n\t\tmodifier to the standard pseudo-stream indicating that it's an\n\t\tHTTP-style read, and the RAW flag is an indicator that the HTTP\n\t\tstream should read the normally out-of-band header (i.e. the HTTP\n\t\twrapper for an encapsulated data type) as well as the actualy data.  \n\t\tThese are only available in debug builds since they're used for \n\t\ttesting purposes.\n\n\tMFLAG_VFILE: The underlying OS doesn't support conventional file I/O (it\n\t\tmay only support, for example, access to fixed blocks of flash \n\t\tmemory) so this is a memory stream emulating a file stream */\n\n#define STREAM_MFLAG_VFILE\t\t0x0020\t/* File stream emulated via mem.stream */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n  #define STREAM_MFLAG_PSEUDO\t0x0040\t/* Stream is pseudo-stream */\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n#ifndef NDEBUG\n  #define STREAM_MFLAG_PSEUDO_HTTP 0x0080\t/* Stream is HTTP pseudo-stream */\n  #define STREAM_MFLAG_PSEUDO_RAW 0x0100\t/* Stream reads raw data */\n#endif /* !NDEBUG */\n#if defined( CONFIG_CONSERVE_MEMORY_EXTRA )\n  #define STREAM_MFLAG_MASK\t\t( 0x0020 | STREAM_FLAG_MASK )\t\n\t\t\t\t\t\t\t\t\t\t/* Mask for memory-only flags */\n#elif defined( NDEBUG )\n  #define STREAM_MFLAG_MASK\t\t( 0x0060 | STREAM_FLAG_MASK )\t\n\t\t\t\t\t\t\t\t\t\t/* Mask for memory-only flags */\n#else\n  #define STREAM_MFLAG_MASK\t\t( 0x01E0 | STREAM_FLAG_MASK )\t\n\t\t\t\t\t\t\t\t\t\t/* Mask for memory-only flags */\n#endif /* Valid stream flags */\n\n/* File stream flags.  These are:\n\n\tFFLAG_BUFFERSET: Used to indicate that the stream has an I/O buffer \n\t\tassociated with it.  A stream can be opened without a buffer, but to\n\t\tread/write data it needs to have a buffer associated with it.  Since\n\t\tthis can be of variable size and sometimes isn't required at all, \n\t\tit's created on-demand rather than always being present, and its \n\t\tpresence is indicated by this flag.\n\t\n\tFFLAG_EOF: The underlying file has reached EOF, no further data can be \n\t\tread once the current buffer is emptied.\n\t\n\tFFLAG_MMAPPED: This is a memory-mapped file stream, used in conjunction\n\t\twith MFLAG_VFILE virtual file streams.\n\n\tFFLAG_POSCHANGED: The position in the underlying file has changed, \n\t\trequiring the file buffer to be refilled from the new position \n\t\tbefore data can be read from it */\n\n#define STREAM_FFLAG_BUFFERSET\t0x0080\t/* Stream has associated buffer */\n#define STREAM_FFLAG_EOF\t\t0x0100\t/* EOF reached on stream */\n#define STREAM_FFLAG_POSCHANGED\t0x0200\t/* File stream position has changed */\n#define STREAM_FFLAG_POSCHANGED_NOSKIP 0x0400\t/* New stream pos.is in following block */\n#define STREAM_FFLAG_MMAPPED\t0x0800\t/* File stream is memory-mapped */\n#define STREAM_FFLAG_MASK\t\t( 0x0F80 | STREAM_FLAG_MASK )\t\n\t\t\t\t\t\t\t\t\t\t/* Mask for file-only flags */\n\n/* The maximum possible stream flag value */\n\n#define STREAM_FLAG_MAX\t\t\t0x0FFF\t/* Maximum possible flag value */\n\n/* Network stream flags.  Since there are quite a number of these and they're\n   only required for the network-specific stream functionality, we give them\n   their own flags variable in the netStream structure instead of using the \n   overall stream flags.  In addition we break them up into general network\n   stream flags and HTTP-specific flags, which form a sizeable family of their\n   own.  The network flags are:\n\n\tNFLAG_DGRAM: The stream is run over UDP rather than the default TCP.\n\n\tNFLAG_ENCAPS: The protocol is running over a lower encapsulation layer \n\t\tthat provides additional packet control information, typically \n\t\tpacket size and flow control information.  HTTP and UDP transport\n\t\tboth provide this type of service, HTTP explicitly and UDP \n\t\timplicitly via its datagram service.  If this flag is set then the \n\t\tlower-level read code overrides some error handling that normally \n\t\ttakes place at a higher level.  For example if a read of n bytes is \n\t\trequested and the encapsulation layer reports that only m bytes, \n\t\tm < n is present, this isn't treated as a read/timeout error.\n\n\tNFLAG_FIRSTREADOK: The first data read from the stream succeeded.  This\n\t\tis used to detect problems due to buggy firewall software, see the\n\t\tcomments in io/tcp.c for details.\n\n\tNFLAG_ISSERVER: The stream is a server stream (default is client).\n\n\tNFLAG_LASTMSGR/NFLAG_LASTMSGR: This is the last message in the exchange.\n\t\tFor a last-message read it means that the other side has indicated\n\t\t(for example through an HTTP \"Connection: close\") that this is the \n\t\tcase.  For a last-message write it means that we should indicate to\n\t\tthe other side (for example through an HTTP \"Connection: close\") \n\t\tthat this is the case.\n\n\tNFLAG_USERSOCKET: The network socket was supplied by the user rather \n\t\tthan being created by cryptlib, so some actions such as socket\n\t\tshutdown should be skipped.\n\n   The HTTP network flags are:\n\n\tNHFLAG_HTTP10: This is an HTTP 1.0 (rather than 1.1) HTTP stream.\n\n\tNHFLAG_HTTPPROXY/NFLAG_HTTPTUNNEL: HTTP proxy control flags.  When the \n\t\tproxy flag is set, HTTP requests are sent as \n\t\t\"GET http://destination-url/location\" (sent to the proxy) rather \n\t\tthan \"GET location\" (sent directly to the target host).  When the \n\t\ttunnel flag is set, the initial network connection-establishment \n\t\trequest is sent as an explicit proxy command \"CONNECT fqdn:port\", \n\t\tafter which normal PDUs for the protocol being tunneled are sent.\n\n\t\tNote that the HTTP tunnel flag is currently never set by anything\n\t\tdue to the removal of the SESSION_USEHTTPTUNNEL flag at a higher\n\t\tlevel, which was only ever set implicitly by being set in the \n\t\tSSL/TLS altProtocolInfo, which in turn was never selected outside\n\t\ta USE_CMP_TRANSPORT block.  The location at which it would be\n\t\tselected (except for the presence of a USE_CMP_TRANSPORT ifdef) is \n\t\tat line 195 of session/sess_attr.c in versions up to 3.4.1.\n\n\tNHFLAG_HTTPGET/NFLAG_HTTPPOST: HTTP allowed-actions flags.\n\n\tNHFLAG_HTTPPOST_AS_GET: Modify the POST to encode it as a GET (ugh), for \n\t\tb0rken servers that don't do POST */\n\n#define STREAM_NFLAG_NONE\t\t0x0000\t/* No network flag */\n#define STREAM_NFLAG_ISSERVER\t0x0001\t/* Stream is server rather than client */\n#define STREAM_NFLAG_USERSOCKET\t0x0002\t/* Network socket was supplied by user */\n#define STREAM_NFLAG_DGRAM\t\t0x0004\t/* Stream is UDP rather than TCP */\n#define STREAM_NFLAG_LASTMSGR\t0x0008\t/* Last message in read exchange */\n#define STREAM_NFLAG_LASTMSGW\t0x0010\t/* Last message in write exchange */\n#define STREAM_NFLAG_ENCAPS\t\t0x0020\t/* Network transport is encapsulated */\n#define STREAM_NFLAG_FIRSTREADOK 0x0040\t/* First data read succeeded */\n#define STREAM_NFLAG_MAX\t\t0x007F\t/* Maximum possible flag value */\n\n#define STREAM_NHFLAG_NONE\t\t0x0000\t/* No network HTTP flag */\n#define STREAM_NHFLAG_HTTP10\t0x0001\t/* HTTP 1.0 stream */\n#define STREAM_NHFLAG_PROXY\t\t0x0002\t/* Use HTTP proxy format for requests */\n#define STREAM_NHFLAG_TUNNEL\t0x0004\t/* Use HTTP proxy tunnel for connect */\n#define STREAM_NHFLAG_GET\t\t0x0008\t/* Allow HTTP GET */\n#define STREAM_NHFLAG_POST\t\t0x0010\t/* Allow HTTP POST */\n#define STREAM_NHFLAG_POST_AS_GET 0x0020 /* Implement POST as GET */\n#define STREAM_NHFLAG_WS_UPGRADE 0x0040\t/* WebSockets Upgrade */\n#define STREAM_NHFLAG_MAX\t\t0x007F\t/* Maximum possible flag value */\n\n#define STREAM_NHFLAG_REQMASK \\\n\t\t( STREAM_NHFLAG_GET | STREAM_NHFLAG_POST | \\\n\t\t  STREAM_NHFLAG_POST_AS_GET )\t/* Mask for permitted HTTP req.types */\n\n/* Network transport-specific flags.  These are:\n\n\tFLAG_FLUSH: Used in writes to buffered streams to force a flush of data in \n\t\tthe stream buffers.\n\t\n\tFLAG_BLOCKING/FLAG_NONBLOCKING: Used to override the stream default \n\t\tbehaviour on reads and writes and force blocking/nonblocking I/O */\n\n#define TRANSPORT_FLAG_NONE\t\t0x00\t/* No transport flag */\n#define TRANSPORT_FLAG_FLUSH\t0x01\t/* Flush data on write */\n#define TRANSPORT_FLAG_NONBLOCKING 0x02\t/* Explicitly perform nonblocking read */\n#define TRANSPORT_FLAG_BLOCKING\t0x04\t/* Explicitly perform blocking read */\n#define TRANSPORT_FLAG_MAX\t\t0x07\t/* Maximum possible flag value */\n\n/* URL component size limits, used when parsing a URL */\n\n#define MIN_SCHEMA_SIZE\t\t\t3\n#define MAX_SCHEMA_SIZE\t\t\t8\n#define MIN_LOCATION_SIZE\t\t3\n#define MAX_LOCATION_SIZE\t\tCRYPT_MAX_TEXTSIZE\n#define MIN_HOST_SIZE\t\t\tMIN_DNS_SIZE\n#define MAX_HOST_SIZE\t\t\tMAX_DNS_SIZE\n\n/* The size of the memory buffer used for virtual file streams, which are \n   used in CONFIG_NO_STDIO environments to store data before it's committed\n   to backing storage */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ ) || \\\n\tdefined( __IBM4758__ ) || defined( __TESTIO__ )\n  #define VIRTUAL_FILE_STREAM\n#endif /* Nonstandard I/O environments */\n\n#define STREAM_VFILE_BUFSIZE\t16384\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tStream Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_TCP\n\n/* The network-stream specific information stored as part of the STREAM\n   data type.  Network streams can work on two levels.  At the lowest \n   level we have the raw network I/O layer, handled by calling \n   setAccessMethodXXX(), which hooks up the transport-level I/O functions.  \n   If there's a requirement to replace the built-in network I/O it can be \n   done by replacing the functionality at this level.\n\n   Layered on top of the transport-level I/O via setStreamLayerXXX() is an \n   optional higher layer protocol such as HTTP which is added by calling \n   the appropriate function to layer the higher-level protocol over the \n   transport-level I/O.  This goes via an intermediate buffering layer that\n   deals with avoiding making repeated calls to the transport-level I/O \n   function, which is a particular problem for HTTP which has to take input \n   a character at a time.  The buffering layer reads ahead as far as it can \n   and then feeds the buffered result back to the caller as required.  We \n   also use write buffering to avoid potential problems with interactions \n   with some transport layers, details are given in the comment for the \n   buffered write function in net_trans.c.\n\n   Alternatively, we can use setStreamLayerDirect() to just pass the call \n   straight down to the transport layer.\n\n   The layering looks as follows:\n\n\t--- httpRead --- bufferedRead ---+--- tcpRead\n\t\t\t\t\t\t\t\t\t |\n\t---------------------------------+\n\n\t--- httpWrite --- bufferedWrite --+---- tcpWrite\n\t\t\t\t\t\t\t\t\t  |\n\t----------------------------------+ */\n\nstruct NS;\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *STM_CONNECT_FUNCTION_OPT )( INOUT struct ST *stream,\n\t\t\t\t\t\t\t\t\t\t   IN const NET_CONNECT_INFO *connectInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *STM_DISCONNECT_FUNCTION_OPT )( INOUT struct ST *stream );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\n\t\tint ( *STM_READ_FUNCTION )( INOUT struct ST *stream, \n\t\t\t\t\t\t\t\t\tOUT_BUFFER( maxLength, *length ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *buffer, \n\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\n\t\tint ( *STM_WRITE_FUNCTION )( INOUT struct ST *stream, \n\t\t\t\t\t\t\t\t\t IN_BUFFER_OPT( maxLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *buffer, \n\t\t\t\t\t\t\t\t\t IN_DATALENGTH_Z const int maxLength,\n\t\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *STM_TRANSPORTCONNECT_FUNCTION )( INOUT struct NS *netStream, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_BUFFER_OPT( hostNameLen ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst char *hostName,\n\t\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_DNS_Z \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int hostNameLen, \n\t\t\t\t\t\t\t\t\t\t\t\tIN_PORT const int port );\ntypedef STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tvoid ( *STM_TRANSPORTDISCONNECT_FUNCTION )( INOUT struct NS *netStream, \n\t\t\t\t\t\t\t\t\t\t\t\t\tconst BOOLEAN fullDisconnect );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\n\t\tint ( *STM_TRANSPORTREAD_FUNCTION )( INOUT struct NS *netStream, \n\t\t\t\t\t\t\t\t\t\t\t OUT_BUFFER( maxLength, *length ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tBYTE *buffer, \n\t\t\t\t\t\t\t\t\t\t\t IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t\t\t\t\t IN_FLAGS_Z( TRANSPORT ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int flags );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\n\t\tint ( *STM_TRANSPORTWRITE_FUNCTION )( INOUT struct NS *netStream, \n\t\t\t\t\t\t\t\t\t\t\t  IN_BUFFER( maxLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst BYTE *buffer,\n\t\t\t\t\t\t\t\t\t\t\t  IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t\t\t\t\t  IN_FLAGS_Z( TRANSPORT ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int flags );\ntypedef CHECK_RETVAL_BOOL \\\n\t\tBOOLEAN ( *STM_TRANSPORTOK_FUNCTION )( void );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *STM_TRANSPORTCHECK_FUNCTION )( INOUT struct NS *netStream );\ntypedef STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tvoid ( *STM_VIRTUALGETERRORINFO_FUNCTION )( const void *virtualStateInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\n\ntypedef struct NS {\n\t/* General information for the network stream.  For a server the\n\t   listenSocket is the (possibly shared) common socket that the server \n\t   is listening on, the netSocket is the ephemeral socket used for\n\t   communications */\n\tSTREAM_PROTOCOL_TYPE protocol;/* Network protocol type */\n\tSAFE_FLAGS nFlags;\t\t\t/* Network-specific flags */\n\tSAFE_FLAGS nhFlags;\t\t\t/* HTTP-specific flags */\n#ifdef __WINDOWS__\n\tUINT_PTR netSocket, listenSocket;/* Network socket */\n#else\n\tint netSocket, listenSocket;/* Network socket */\n#endif /* System-specific socket data types */\n\n\t/* Network timeout information.  The timeout value depends on whether \n\t   the stream is in the connect/handshake phase or the data transfer \n\t   phase.  The handshake phase is logically treated as part of the \n\t   connect phase even though from the stream point of view it's part of \n\t   the data transfer phase.  Initially the stream timeout is set to the \n\t   connect timeout and the saved timeout is set to the data transfer \n\t   timeout.  Once the connect/handshake has completed, the stream \n\t   timeout is set to the saved data transfer timeout and the saved \n\t   timeout is cleared */\n\tint timeout, savedTimeout;\t/* Network comms timeout */\n\n\t/* Network streams require separate read/write buffers for packet\n\t   assembly/disassembly so we provide a write buffer alongside the \n\t   generic stream read buffer */\n\tBUFFER( writeBufSize, writeBufEnd ) \\\n\tBYTE *writeBuffer;\t\t\t/* Write buffer */\n\tint writeBufSize;\t\t\t/* Total size of buffer */\n\tint writeBufEnd;\t\t\t/* Last buffer position with valid data */\n\n\t/* Stream subtype-specific information required for some network stream\n\t   types */\n\tvoid *subTypeInfo;\t\t\t/* Stream subtype-specific information */\n\n\t/* General network-related information.  The server FQDN is held in \n\t   dynamically-allocated storage, the optional path for HTTP is a pointer \n\t   into the host string at the appropriate location */\n\tBUFFER_OPT_FIXED( hostLen ) \\\n\tchar *host;\n\tint hostLen;\n\tBUFFER_OPT_FIXED( pathLen ) \\\n\tchar *path;\n\tint pathLen;\n\tint port;\t\t\t\t\t/* Host name, path on host, and port */\n\tBUFFER( CRYPT_MAX_TEXTSIZE / 2, clientAddressLen ) \\\n\tchar clientAddress[ ( CRYPT_MAX_TEXTSIZE / 2 ) + 4 ];\n\tint clientAddressLen;\t\t/* Client IP address (dotted-decimal) */\n\tint clientPort;\t\t\t\t/* Client port */\n\n\t/* Sometimes we can fingerprint the application running on the peer \n\t   system, which is useful for working around buggy implementations.  \n\t   The following value stores the peer application type, if known */\n\tSTREAM_PEER_TYPE systemType;\n\n\t/* If a network error condition is fatal we set the persistentStatus \n\t   value.  This is checked by the higher-level stream code and copied \n\t   to to stream persistent status if required */\n\tint persistentStatus;\n\n\t/* Last-error information returned from lower-level code */\n\tERROR_INFO errorInfo;\n\n\t/* Network stream read/write functions.  These general-purpose functions \n\t   are for the higher-level entry points, they either call straight down \n\t   to the transport-layer functions or allow the interposition of \n\t   additional layers like HTTP.  For example for an HTTP network read \n\t   the path would be:\n\n\t\treadFunction -> bufferedTransportReadFunction -> \n\t\t\t\t\t\t\t\t\t\ttransportReadFunction\n\t\t\n\t\thttp_rd.c:readFunction() -> bufferedTransportReadFunction -> \n\t\t\t\t\t\t\t\t\t\ttcp_rw.c:readSocketFunction\n\n\t   For an HTTP over TLS read the path would be:\n\t\t\n\t\thttp_rd.c:readFunction() -> bufferedTransportReadFunction -> \n\t\t\t\t\t\t\t\t\t\tnet_trans.c:transportVirtualReadFn \n\t\t\t\t\t\t\t\t\t\t\n\t   For a direct network read the path would be:\n\n\t\treadFunction \n\n\t\ttcp_rw.c:readSocketFunction.\n\n\t   In addition to the read/write functions there also exist optionnal\n\t   connect and disconnect functions for when the protocol (e.g. TLS) is\n\t   wrapped in a lower-level protocol (e.g. EAP) that requires an \n\t   explicit negotiation as part of the connect/disconnect process */\n\tFNPTR connectFunctionOpt, disconnectFunctionOpt;\n\tFNPTR readFunction, writeFunction;\n\n\t/* Transport-layer network functions.  These can be replaced with user-\n\t   defined transport mechanisms if required */\n\tFNPTR transportConnectFunction, transportDisconnectFunction;\n\tFNPTR transportReadFunction, transportWriteFunction;\n\tFNPTR transportOKFunction, transportCheckFunction;\n\n\t/* Virtual stream get/put/get-error-info and state pointers */\n\tFNPTR virtualGetDataFunction, virtualPutDataFunction;\n\tFNPTR virtualGetErrorInfoFunction;\n\tDATAPTR virtualStateInfo;\t/* State info for virtual stream */\n\n\t/* Variable-length storage for the stream buffers */\n\tDECLARE_VARSTRUCT_VARS;\n\t} NET_STREAM_INFO;\n\n/* The size of the network transport stream readahead/write buffers.  We try \n   and make them an optimal size to minimise unnecessary copying and not \n   negatively affect network I/O.  If we make them too big then we'll have \n   to move too much data around when we partially empty them, if we make \n   them too small then the buffering effect is suboptimal.  Since what we're \n   buffering is typically PKI traffic (and rarely UDP packets for UDP \n   transport), a 4K buffer should get most messages in one go.  This also \n   matches many network stacks that use 4K I/O buffers, the BSD default */\n\n#define NETSTREAM_BUFFER_SIZE\t\t4096\n#if NETSTREAM_BUFFER_SIZE > MAX_INTLENGTH_SHORT\n  #error NETSTREAM_BUFFER_SIZE exceeds buffered I/O length check size\n#endif /* NETSTREAM_BUFFER_SIZE > MAX_INTLENGTH_SHORT */\n\n/* Sanity-check a network stream */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckNetStream( const NET_STREAM_INFO *netStream );\n\n#else\n\ntypedef void *NET_STREAM_INFO;\t/* Dummy for function prototypes */\n\n#endif /* USE_TCP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream Function Prototypes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Stream query functions to determine whether a stream is a memory-mapped \n   file stream, a virtual file stream, or a pseudo-stream.  The memory-\n   mapped stream check is used when we can eliminate extra buffer allocation \n   if all data is available in memory.  The virtual file stream check is \n   used where the low-level access routines have converted a file on a \n   CONFIG_NO_STDIO system to a memory stream that acts like a file stream.\n   The pseudo-stream is used for testing purposes to emulate a standard\n   stream like a network stream */\n\n#define sIsMemMappedStream( stream ) \\\n\t\t( ( ( stream )->type == STREAM_TYPE_FILE ) && \\\n\t\t  TEST_FLAG( ( stream )->flags, STREAM_FFLAG_MMAPPED ) )\n#ifdef VIRTUAL_FILE_STREAM \n  #define sIsVirtualFileStream( stream ) \\\n\t\t  ( ( ( stream )->type == STREAM_TYPE_MEMORY ) && \\\n\t\t\tTEST_FLAG( ( stream )->flags, STREAM_MFLAG_VFILE ) )\n#else\n  #define sIsVirtualFileStream( stream )\tFALSE\n#endif /* VIRTUAL_FILE_STREAM */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n  #define sIsPseudoStream( stream ) \\\n\t\t  ( ( ( stream )->type == STREAM_TYPE_MEMORY ) && \\\n\t\t\tTEST_FLAG( ( stream )->flags, STREAM_MFLAG_PSEUDO ) )\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n#ifndef NDEBUG\n  #define sIsPseudoHTTPStream( stream ) \\\n\t\t  ( ( ( stream )->type == STREAM_TYPE_MEMORY ) && \\\n\t\t\tTEST_FLAG( ( stream )->flags, STREAM_MFLAG_PSEUDO_HTTP ) )\n  #define sIsPseudoHTTPRawStream( stream ) \\\n\t\t  ( ( ( stream )->type == STREAM_TYPE_MEMORY ) && \\\n\t\t\tTEST_FLAGS( ( stream )->flags, \\\n\t\t\t\t\t\t( STREAM_MFLAG_PSEUDO_HTTP | STREAM_MFLAG_PSEUDO_RAW ), \\\n\t\t\t\t\t\t( STREAM_MFLAG_PSEUDO_HTTP | STREAM_MFLAG_PSEUDO_RAW ) ) )\n#endif /* !NDEBUG */\n\n/* Prototypes for functions in file.c */\n\n#ifdef USE_FILES\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint fileRead( INOUT STREAM *stream, \n\t\t\t  OUT_BUFFER( length, *bytesRead ) void *buffer, \n\t\t\t  IN_DATALENGTH const int length, \n\t\t\t  OUT_DATALENGTH_Z int *bytesRead );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fileWrite( INOUT STREAM *stream, \n\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t   IN_DATALENGTH const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileFlush( INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint fileSeek( INOUT STREAM *stream,\n\t\t\t  IN_DATALENGTH_Z const long position );\n#endif /* USE_FILES */\n\n/* Network URL processing functions in net_url.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint parseURL( OUT URL_INFO *urlInfo, \n\t\t\t  IN_BUFFER( urlLen ) const BYTE *url, \n\t\t\t  IN_LENGTH_SHORT const int urlLen,\n\t\t\t  IN_PORT_OPT const int defaultPort, \n\t\t\t  IN_ENUM_OPT( URL_TYPE ) const URL_TYPE urlTypeHint,\n\t\t\t  const BOOLEAN preParseOnly );\n\n/* Network proxy functions in net_proxy.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint connectViaSocksProxy( INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint connectViaHttpProxy( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\n#if defined( __WIN32__ )\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint findProxyUrl( OUT_BUFFER( proxyMaxLen, *proxyLen ) char *proxy, \n\t\t\t\t  IN_LENGTH_DNS const int proxyMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( proxyMaxLen ) int *proxyLen,\n\t\t\t\t  IN_BUFFER( urlLen ) const char *url, \n\t\t\t\t  IN_LENGTH_DNS const int urlLen );\n#else\n  #define findProxyUrl( proxy, proxyMaxLen, proxyLen, url, urlLen )\tCRYPT_ERROR_NOTFOUND\n#endif /* Win32 */\n\n/* Prototypes for functions in net_trans.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint bufferedTransportRead( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t   IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t   IN_FLAGS_Z( TRANSPORT ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint bufferedTransportWrite( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_BUFFER( maxLength ) const BYTE *buffer, \n\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\tIN_FLAGS_Z( TRANSPORT ) const int flags );\n\n/* Network access mapping functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCP( INOUT NET_STREAM_INFO *netStream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerHTTP( INOUT NET_STREAM_INFO *netStream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerEAP( INOUT NET_STREAM_INFO *netStream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setStreamLayerDirect( INOUT NET_STREAM_INFO *netStream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTransportVirtual( INOUT NET_STREAM_INFO *netStream );\n\n#endif /* _STREAM_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/io/tcp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TCP/IP Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check an externally-supplied socket to make sure that it's set up as\n   required by cryptlib.  See the long comment in tcp.h about the numerous\n   problems that this theoretically simple operation actually causes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkSocketFunction( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tint value;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\n\t/* Check that we've been passed a valid network socket, and that it's a\n\t   blocking socket.  getSocketNonblockingStatus() is a complex macro\n\t   that tries to return the non-blocking status as a boolean */\n\tgetSocketNonblockingStatus( netStream->netSocket, value );\n\tif( value )\n\t\t{\n\t\treturn( setSocketError( netStream, \"Socket is non-blocking\", 22,\n\t\t\t\t\t\t\t\tCRYPT_ARGERROR_NUM1, TRUE ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tInit/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and shut down the network interface */\n\nRETVAL \\\nint netInitTCP( void )\n\t{\n#ifdef __WINDOWS__\n\tWSADATA wsaData;\n#endif /* __WINDOWS__ */\n\n#ifdef __WINDOWS__\n\tif( WSAStartup( 2, &wsaData ) != 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't initialise Winsock\" ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n#endif /* __WINDOWS__ */\n\n#ifdef __SCO_VERSION__\n\tstruct sigaction act, oact;\n\n\t/* Work around the broken SCO/UnixWare signal-handling, which sometimes\n\t   sends a nonblocking socket a SIGIO (thus killing the process) when\n\t   waiting in a select() (this may have been fixed by the switch to\n\t   blocking sockets necessitated by Winsock bugs with non-blocking\n\t   sockets, and will be fixed long-term when SCO's long death march\n\t   eventually ends).  Since SIGIO is an alias for SIGPOLL, SCO doesn't \n\t   help by reporting this as a \"polling alarm\".  To fix this we need to \n\t   catch and swallow SIGIOs */\n\tmemset( &act, 0, sizeof( act ) );\n\tact.sa_handler = SIG_IGN;\n\tsigemptyset( &act.sa_mask );\n\tif( sigaction( SIGIO, &act, &oact ) < 0 )\n\t\t{\n\t\t/* This assumes that stderr is open, i.e. that we're not a daemon.\n\t\t   This should be the case, at least during the development/debugging\n\t\t   stage */\n\t\tfprintf( stderr, \"cryptlib: sigaction failed, errno = %d, \"\n\t\t\t\t \"file = %s, line = %d.\\n\", errno, __FILE__, __LINE__ );\n\t\tabort();\n\t\t}\n\n\t/* Check for handler override. */\n\tif( oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN )\n\t\t{\n\t\t/* We overwrote the caller's handler, reinstate the old handler and\n\t\t   warn them about this */\n\t\tfprintf( stderr, \"Warning: Conflicting SIGIO handling detected in \"\n\t\t\t\t \"UnixWare socket bug\\n         workaround, file \" __FILE__\n\t\t\t\t \", line %d.  This may cause\\n         false SIGIO/SIGPOLL \"\n\t\t\t\t\"errors.\\n\", __LINE__ );\n\t\tsigaction( SIGIO, &oact, &act );\n\t\t}\n#endif /* UnixWare/SCO */\n\n\t/* Set up the socket pool state information */\n\treturn( initSocketPool() );\n\t}\n\nvoid netEndTCP( void )\n\t{\n#ifdef __WINDOWS__\n\t/* Wipe the Sheets Afterwards and Cleanup */\n\tWSACleanup();\n#endif /* __WINDOWS__ */\n\n#ifdef __SCO_VERSION__\n\tsignal( SIGIO, SIG_DFL );\n#endif /* UnixWare/SCO */\n\t}\n\n/* Return the status of the network interface */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN transportOKFunction( void )\n\t{\n#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n\tstatic BOOLEAN transportOK = FALSE;\n\n\tif( !transportOK )\n\t\t{\n\t\tSOCKET netSocket;\n\n\t\t/* If the networking subsystem isn't enabled, attempting any network\n\t\t   operations will return ENOENT (which isn't a normal return code,\n\t\t   but is the least inappropriate thing to return).  In order to\n\t\t   check this before we get deep into the networking code, we create\n\t\t   a test socket here to make sure that everything is OK.  If the\n\t\t   network transport is unavailable, we re-try each time we're\n\t\t   called in case it's been enabled in the meantime */\n\t\tnetSocket = socket( PF_INET, SOCK_STREAM, 0 );\n\t\tif( !isBadSocket( netSocket ) )\n\t\t\t{\n\t\t\tclosesocket( netSocket );\n\t\t\ttransportOK = TRUE;\n\t\t\t}\n\t\t}\n\treturn( transportOK );\n#else\n\treturn( TRUE );\n#endif /* OS-specific socket availability check */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t System-Specific Problem Workarounds\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __BEOS__ ) && !defined( BONE_VERSION )\n\n/* BeOS doesn't support checking for anything except readability in select()\n   and only supports one or two socket options so we define our own versions \n   of these functions that no-op out unsupported options */\n\n#undef select   /* Restore normal select() around the wrapper */\n\nstatic int my_select( int socket_range, struct fd_set *read_bits,\n\t\t\t\t\t  struct fd_set *write_bits,\n\t\t\t\t\t  struct fd_set *exception_bits,\n\t\t\t\t\t  struct timeval *timeout )\n\t{\n\t/* BeOS doesn't support nonblocking connects, it always waits about a\n\t   minute for the connect and then times out, so if we get a wait on a\n\t   connecting socket we report it as being successful by exiting with\n\t   the fds as set by the caller and a successful return status */\n\tif( read_bits != NULL && write_bits != NULL )\n\t\treturn( 1 );\n\n\t/* If we're checking for writeability the best that we can do is to\n\t   always report the socket as writeable.  Since the socket is a \n\t   blocking socket the data will (eventually) get written */\n\tif( read_bits == NULL && write_bits != NULL )\n\t\t{\n\t\tif( exception_bits != NULL )\n\t\t\tFD_ZERO( exception_bits );\n\t\treturn( 1 );\n\t\t}\n\n\t/* Since BeOS doesn't support checking for writeability or errors, we\n\t   have to clear these values before we call select() so that the \n\t   caller won't find anything still set when we return */\n\tif( write_bits != NULL )\n\t\tFD_ZERO( write_bits );\n\tif( exception_bits != NULL )\n\t\tFD_ZERO( exception_bits );\n\n\treturn( select( socket_range, read_bits, NULL, NULL, timeout ) );\n\t}\n\n#define select( sockets, readFD, writeFD, exceptFD, timeout ) \\\n\t\tmy_select( sockets, readFD, writeFD, exceptFD, timeout )\n\nstatic int my_setsockopt( int socket, int level, int option,\n\t\t\t\t\t\t  const void *data, uint size )\n\t{\n\tif( option != SO_NONBLOCK && option != SO_REUSEADDR )\n\t\treturn( 0 );\n\treturn( setsockopt( socket, level, option, data, size ) );\n\t}\n\nstatic int my_getsockopt( int socket, int level, int option,\n\t\t\t\t\t\t  void *data, uint *size )\n\t{\n\tif( option != SO_ERROR )\n\t\treturn( 0 );\n\t*( ( int * ) data ) = 0;\t/* Clear return status */\n\n\t/* It's unclear whether the following setsockopt actually does anything\n\t   under BeOS or not.  If it fails, the alternative below may work */\n#if 1\n\treturn( setsockopt( socket, level, option, data, *size ) );\n#else\n\tBYTE buffer[ 8 + 8 ];\n\tint count;\n\n\tcount = recv( socket, buffer, 0, 0 );\n\tprintf( \"recv( 0 ) = %d, errno = %d.\\n\", count, errno );\n\tif( count < 0 )\n\t\t*( ( int * ) data ) = errno;\n#endif /* 1 */\n\t}\n#endif /* BeOS without BONE */\n\n#ifdef __embOS__\n\n/* embOS doesn't have any equivalent to errno, it's necessary to explicitly \n   fetch the error code from getsockopt() */\n\nstatic int lastErrno = 0;\n\nint getErrno( SOCKET socket )\n\t{\n\tint errno, status;\n\n\t/* If there's no socket available to get the error code from, return a \n\t   generic error */\n\tif( socket == INVALID_SOCKET )\n\t\treturn( IP_ERR_MISC );\n\n\t/* Try and get the last socket error.  If this fails, we return the \n\t   generic IP_ERR_MISC */\n\tstatus = IP_SOCK_getsockopt( socket, SOL_SOCKET, SO_ERROR, &errno, \n\t\t\t\t\t\t\t\t sizeof( int ) );\n\tif( status != 0 )\n\t\treturn( IP_ERR_MISC );\n\n\t/* Reading the SO_ERROR value clears it, so if we read a zero value we \n\t   return the last read error value, to mimic the behaviour of the Unix \n\t   errno */\n\tif( errno == 0 )\n\t\treturn( lastErrno );\n\n\tlastErrno = errno;\n\treturn( errno );\n\t}\n\nvoid clearErrno( void )\n\t{\n\tlastErrno = 0;\n\t}\n\n/* embOS/IP gets getsockopt() wrong so we have to define our own version \n   that overrides the embOS one.  First we change getsockopt() back to its\n   original define, IP_SOCK_getsockopt(), and then we call it via the \n   wrapper */\n\n#undef getsockopt\n#define getsockopt\t\t\t\tIP_SOCK_getsockopt\n\nint my_getsockopt( int sockfd, int level, int optname, void *optval, \n\t\t\t\t   int *optlen )\n\t{\n\treturn( getsockopt( sockfd, level, optname, optval, *optlen ) );\n\t}\n\n/* embOS/IP doesn't have inet_ntoa() or inet_addr() so we have to provide \n   our own */\n\nchar *inet_ntoa( const struct in_addr in )\n\t{\n\tstatic char buffer[ 32 + 8 ];\n\t\n\tIP_PrintIPAddr( buffer, in.s_addr, 32 );\n\treturn( buffer );\n\t}\n\nunsigned long inet_addr( const char *cp )\n\t{\n\tU32 address;\n\tint status;\n\n\t/* It's unclear whether IP_ResolveHost() will convert dotted-decimal \n\t   strings directly to addresses, for now we use this unless someone\n\t   complains, in order to avoid having to implement a complete\n\t   inet_addr() ourselves */\n\tstatus = IP_ResolveHost( cp, &address, 10000 );\n\tif( status != 0 )\n\t\treturn( INADDR_NONE );\n\treturn( address );\n\t}\n#endif /* __embOS__ */\n\n#ifdef __MQXRTOS__\n\n/* MQX has a select() that looks mostly like a normal select() but isn't,\n   this wrapper maps the standard select() to the MQX version */\n\nstatic int my_select( int socket_range, rtcs_fd_set *read_bits,\n\t\t\t\t\t  rtcs_fd_set *write_bits,\n\t\t\t\t\t  rtcs_fd_set *exception_bits,\n\t\t\t\t\t  struct timeval *timeout )\n\t{\n\tuint32_t timeout_ms;\n\n\t/* Turn the seconds : microseconds timeout value into a millisecond \n\t   value */\n\ttimeout_ms = ( timeout->tv_sec * 1000 ) * ( timeout->tv_usec / 1000 );\n\n\t/* The rounding from microseconds to milliseconds can leave the timeout\n\t   set to zero, which is bad for MQX sinze a value of zero means wait\n\t   indefinitely.  If we get a zero timeout we make it one */\n\tif( timeout_ms == 0 )\n\t\ttimeout_ms = 1;\n\n\t/* Pass the call down to the native select() */\n\treturn( select( socket_range, read_bits, write_bits, exception_bits, \n\t\t\t\t\ttimeout_ms ) );\n\t}\n\n#define select\t\tmy_select\t/* Replace call to select() with wrapper */\n\n/* MQX uses a nonstandard form of send(), to deal with the resulting \n   compiler warning we map the parameter to the appropriate type */ \n\n#define send( socket, buffer, count, flags ) \\\n\t\tsend( socket, ( char * ) buffer, count, flags )\n\n#endif /* __MQXRTOS__ */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCP( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( netStream->transportOKFunction, transportOKFunction );\n\tFNPTR_SET( netStream->transportCheckFunction, checkSocketFunction );\n\tsetAccessMethodTCPConnect( netStream );\n\tsetAccessMethodTCPReadWrite( netStream );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/tcp.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TCP/IP Interface Header\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_TCP\n\n#ifndef _TCP_DEFINED\n\n#define _TCP_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tAMX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __AMX__ )\n\n#include <kn_sock.h>\n\n/* All KwikNet functions have kn_ prefix, to use the standard sockets API\n   names we have to redefine them to the usual names */\n\n#define accept\t\t\t\tkn_accept\n#define bind\t\t\t\tkn_bind\n#define closesocket\t\t\tkn_close\n#define connect\t\t\t\tkn_connect\n#define getsockopt\t\t\tkn_getsockopt\n#define listen\t\t\t\tkn_listen\n#define recv\t\t\t\tkn_recv\n#define select\t\t\t\tkn_select\n#define send\t\t\t\tkn_send\n#define setsockopt\t\t\tkn_setsockopt\n#define shutdown\t\t\tkn_shutdown\n#define socket\t\t\t\tkn_socket\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tBeOS\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're building under BeOS the system may have the new(er) BONE (BeOs\n   Network Environment) network stack.  This didn't quite make it into BeOS\n   v5 before the demise of Be Inc but was leaked after Be folded, as was the\n   experimental/developmental Dano release of BeOS, which would have become\n   BeOS 5.1 and also has a newer network stack.  In order to detect this we\n   have to pull in sys/socket.h before we try anything else */\n\n#elif defined( __BEOS__ )\n\n#include <sys/socket.h>\n\n/* If we're using the original (rather minimal) BeOS TCP/IP stack, we have\n   to provide a customised interface for it rather than using the same one\n   as the generic Unix/BSD interface */\n\n#if !defined( BONE_VERSION ) && !defined( __HAIKU__ )\n\n#include <errno.h>\n#include <fcntl.h>\n#include <netdb.h>\n#include <socket.h>\n\n/* BeOS doesn't define any of the PF_xxx's, howewever it does define some \n   of the AF_xxx equivalents, since these are synonyms we just define the \n   PF_xxx's ourselves */\n\n#define PF_UNSPEC\t\t\t\t0\n#define PF_INET\t\t\t\t\tAF_INET\n\n/* BeOS doesn't define NO_ADDRESS, but NO_DATA is a synonym for this */\n\n#define NO_ADDRESS\t\t\t\tNO_DATA\n\n/* BeOS doesn't have raw sockets, which are used for ICMP messages, however\n   we can use a datagram socket for this instead */\n\n#define SOCK_RAW\t\t\t\tSOCK_DGRAM\n\n/* BeOS doesn't support checking for anything except readability in select()\n   and only supports one or two socket options, so we define our own\n   versions of these functions that no-op out unsupported options */\n\n#define select( sockets, readFD, writeFD, exceptFD, timeout ) \\\n\t\tmy_select( sockets, readFD, writeFD, exceptFD, timeout )\n#define getsockopt( socket, level, optname, optval, optlen ) \\\n\t\tmy_getsockopt( socket, level, optname, optval, optlen )\n#define setsockopt( socket, level, optname, optval, optlen ) \\\n\t\tmy_setsockopt( socket, level, optname, optval, optlen )\n\n/* The following options would be required, but aren't provided by BeOS.  If\n   you're building under a newer BeOS version that supports these options,\n   you'll also need to update my_set/setsockopt() to no longer no-op them\n   out */\n\n#define SO_ERROR\t\t\t\t-1\n#define TCP_NODELAY\t\t\t\t-1\n\n#endif /* !BONE_VERSION && !__HAIKU__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tembOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __embOS__ )\n\n#define IP_BSD_COMPLIANCE\t\t1\t/* Enable BSD sockets compatible API */\n#include <IP.h>\n\n/* embOS/IP uses nonstandard names for some of its constants */\n\n#define FD_SETSIZE\t\t\t\tIP_FD_SETSIZE\n\n/* embOS/IP doesn't have an IPPROTO_TCP/UDP or AF_UNSPEC, however it's only \n   used by the IPv6 emulation layer so we can set it to anything we like \n   (embOS defines PF_UNSPEC to AF_UNSPEC, but forgets to define AF_UNSPEC) */\n\n#if !defined( USE_IPv6_DNSAPI )\n  #define IPPROTO_TCP\t\t\t1\n  #define IPPROTO_TCP\t\t\t2\n  #define AF_UNSPEC\t\t\t\t1\n#endif /* !USE_IPv6_DNSAPI */\n\n/* embOS/IP gets getsockopt() wrong so we have to define our own version \n   that overrides the embOS one */\n\n#undef getsockopt\t\t\t\t/* Defined in IP_socket.h */\n#define getsockopt\t\t\t\tmy_getsockopt\n\nint my_getsockopt( int sockfd, int level, int optname, void *optval, \n\t\t\t\t   int *optlen );\n\n/* embOS doesn't have any equivalent to errno/h_errno, it's necessary to \n   explicitly fetch the error code via a call to getsockopt() */\n\nint getErrno( int socket );\nvoid clearErrno( void );\n\n#define getErrorCode( socket )\tgetErrno( socket )\n#define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\tgetErrno( socket )\n#define clearErrorState\t\t\tclearErrno\n\n/* embOS/IP doesn't have inet_ntoa() or inet_addr() so we have to provide \n   our own */\n\nchar *inet_ntoa( const struct in_addr in );\nunsigned long inet_addr( const char *cp );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tuITRON\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ITRON__ )\n\n/* uITRON has a TCP/IP API but it doesn't seem to be widely used, and the\n   only available documentation is in Japanese.  If you need TCP/IP support\n   under uITRON and have an implementation available, you can add the\n   appropriate interface by replacing tcp.c and dns.c with the equivalent \n   uITRON API glue code */\n\n#error You need to set up the TCP/IP headers and interface in tcp.c/dns.c\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\t\tMQX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MQXRTOS__ )\n\n#include <mqx.h>\n#include <rtcs.h>\n#if RTCSCFG_ENABLE_IP6\n  #define USE_IPv6\n#endif /* RTCSCFG_ENABLE_IP6 */\n\n/* MQX doesn't (by default) support IPv6 but it does support the new IPv6 \n   DNS API functions */\n\n#define USE_IPv6_DNSAPI\n\n/* MQX doesn't define any of the PF_xxx's, howewever it does define\n   the AF_xxx equivalents */\n\n#define PF_UNSPEC\t\t\t\tAF_UNSPEC\n\n/* MQX doesn't support SO_REUSEADDR, to deal with this we call setsockopt()\n   through a wrapper that no-ops out any attempt to use it */\n\n#define SO_REUSEADDR\t\t\t9999\n\n/* MQX doesn't provide a SOCKADDR_STORAGE so we define our own version */\n\nstruct sockaddr_storage {\n\tunion {\n\t\tstruct sockaddr_in6 bigSockaddrStruct;\n\t\tchar padding[ 128 ];\n\t\t} dummyMember;\n\t};\n\n/* MQX doesn't implement IPV6_V6ONLY (needed for getsockopt()), the \n   following define gives it an out-of-range value (see rtcs_sock.h) that \n   results in getsockopt() failing, so the operation is skipped */\n\n#ifndef IPV6_V6ONLY\n  #define IPV6_V6ONLY\t\t\t5000\n#endif /* !IPV6_V6ONLY */\n\n/* MQX has a select() that looks mostly like a normal select() but isn't,\n   it uses its own fd_set types and macros and the last parameter for \n   select() is given as milliseconds rather than a struct timeval.  To deal\n   with this we map the standard names to the MQX ones and call the MQX\n   select via a wrapper that sets up the parameters correctly */\n\n#define fd_set\t\t\t\t\trtcs_fd_set\n\n#define FD_SET\t\t\t\t\tRTCS_FD_SET\n#define FD_ISSET\t\t\t\tRTCS_FD_ISSET\n#define FD_ZERO\t\t\t\t\tRTCS_FD_ZERO\n#define FD_SETSIZE\t\t\t\tRTCSCFG_FD_SETSIZE\n\nstruct timeval {\n\ttime_t tv_sec;\n\ttime_t tv_usec;\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tNucleus\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Nucleus__ )\n\n/* Nucleus has it's own functions for network I/O that provide a sort of \n   weird parallel-universe version of the standard sockets API, we map these \n   to standard sockets functions, types, and constants */\n\n#include <nu_net.h>\n\n#define sockaddr_in\t\t\t\tSCK_SOCKADDR_IP_STRUCT\n#define sin_family\t\t\t\tsck_family\n#define sin_port\t\t\t\tsck_port\n#define sin_addr\t\t\t\tsck_addr\n\n#define AF_INET\t\t\t\t\tSK_FAM_IP\n#define FD_SETSIZE\t\t\t\tFD_ELEMENTS\n#define INADDR_ANY\t\t\t\tIP_ADDR_ANY\n#define PF_INET\t\t\t\t\tSK_FAM_IP\n#define PF_INET6\t\t\t\tSK_FAM_IP6\n#define PF_UNSPEC\t\t\t\tSK_FAM_UNSPEC\n#define SOCK_STREAM\t\t\t\tNU_TYPE_STREAM\n\n#define fd_set\t\t\t\t\tstruct nu_fd_set\n// Nucleus typedefs struct nu_fd_set -> FD_SET, which clashes with\n// the standard sockets FD_SET.\n#define in_addr_t\t\t\t\tUINT32\n#define in_port_t\t\t\t\tUINT16\n\n#define accept\t\t\t\t\tNU_Accept\n#define bind\t\t\t\t\tNU_Bind\n#define close\t\t\t\t\tNU_Close_Socket\n#define connect\t\t\t\t\tNU_Connect\n#define gethostbyname\t\t\tNU_Get_Host_By_Name\n#define getsockopt\t\t\t\tNU_Getsockopt\n#define listen\t\t\t\t\tNU_Listen\n#define recv\t\t\t\t\tNU_Recv\n#define send\t\t\t\t\tNU_Send\n#define select\t\t\t\t\tNU_Select\n#define setsockopt\t\t\t\tNU_Setsockopt\n#define shutdown\t\t\t\tNU_Shutdown\n#define socket\t\t\t\t\tNU_Socket\n\n#define FD_ZERO\t\t\t\t\tNU_FD_Init\n#define FD_ISSET\t\t\t\tNU_FD_Check\n#define FD_SET\t\t\t\t\tNU_FD_Set\n\n/* Nucleus NET has IPv6 support, but in a very hit-and-miss manner, for\n   example the EAI_xxx values aren't defined (so the autodetection in the\n   IPv6 section won't work), but then values like IPV6_V6ONLY are defined.\n   On the other hand standard functions like getaddrinfo() don't exist at\n   all, so for now we have to restrict ourselves to IPv4.  In order to\n   deal with the erratic presence of IPv6 values we undefine any conflicting\n   ones as required */\n\n#undef IPV6_V6ONLY\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tQuadros/ThreadX (via TreckNet stack)\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Quadros__ ) || defined( __ThreadX__ )\n\n/* Quadros uses the TreckNet stack.  ThreadX doesn't have native socket \n   support, there is a ThreadX component called NetX but everyone seems to \n   use assorted non-ThreadX network stacks, of which TreckNet is the most\n   common */\n\n#include <trsocket.h>\n\n#undef USE_DNSSRV\n#undef __WINDOWS__\n\n/* Some versions of the Treck stack don't support all IPv6 options */\n\n#ifndef NI_NUMERICSERV\n  #define NI_NUMERICSERV\t0\t/* Unnecessary for Treck stack */\n#endif /* !NI_NUMERICSERV */\n\n/* The Treck stack doesn't implement IPV6_V6ONLY (needed for getsockopt()), \n   the following define gives it an out-of-range value that results in \n   getsockopt() failing, so the operation is skipped */\n\n#ifndef IPV6_V6ONLY\n  #define IPV6_V6ONLY\t\t\t5000\n#endif /* !IPV6_V6ONLY */\n\n/* Like Windows, Treck uses special names for close() and ioctl() to avoid\n   conflicts with standard system calls, and defines special functions for\n   obtaining error information rather than using a static errno-type\n   value */\n\n#define closesocket\t\t\t\ttfClose\n#define ioctlsocket\t\t\t\ttfIoctl\n#define getErrorCode( socket )\ttfGetSocketError( socket )\n#define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\ttfGetSocketError( socket )\n\n/* Map Treck's nonstandard error names to more standard ones */\n\n#ifndef EADDRNOTAVAIL\n  #define EBADF\t\t\t\t\tTM_EBADF\n  #define EACCES\t\t\t\tTM_EACCES\n  #define EADDRINUSE\t\t\tTM_EADDRINUSE\n  #define EADDRNOTAVAIL\t\t\tTM_EADDRNOTAVAIL\n  #define EAFNOSUPPORT\t\t\tTM_EAFNOSUPPORT\n  #define EAGAIN\t\t\t\tTM_EAGAIN\n  #define EALREADY\t\t\t\tTM_EALREADY\n  #define ECONNABORTED\t\t\tTM_ECONNABORTED\n  #define ECONNREFUSED\t\t\tTM_ECONNREFUSED\n  #define ECONNRESET\t\t\tTM_ECONNRESET\n  #define EINPROGRESS\t\t\tTM_EINPROGRESS\n  #define EINTR\t\t\t\t\tTM_EINTR\n  #define EIO\t\t\t\t\tTM_EIO\n  #define EISCONN\t\t\t\tTM_EISCONN\n  #define EMFILE\t\t\t\tTM_EMFILE\n  #define EMSGSIZE\t\t\t\tTM_EMSGSIZE\n  #define ENETUNREACH\t\t\tTM_ENETUNREACH\n  #define ENOBUFS\t\t\t\tTM_ENOBUFS\n  #define ENODEV\t\t\t\tTM_ENODEV\n  #define ENOPROTOOPT\t\t\tTM_ENOPROTOOPT\n  #define ENOTCONN\t\t\t\tTM_ENOTCONN\n  #define ENOTSOCK\t\t\t\tTM_ENOTSOCK\n  #define EPERM\t\t\t\t\tTM_EPERM\n  #define EPROTOTYPE\t\t\tTM_EPROTOTYPE\n  #define ETIMEDOUT\t\t\t\tTM_ETIMEDOUT\n  #define NO_DATA\t\t\t\tTM_NO_DATA\n#endif /* Standard error names not defined */\n\n/* TreckNet doesn't have an h_errno and no-one seems to know what the \n   substitute for it is, if any, so we no-op it out */\n\n#define h_errno\t\t\t\t\t0\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tTelit\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Telit__ )\n\n/* Telit redefines the entire standard sockets API using its own wrappers\n   that overlay the BSD sockets API.  To deal with this without having to \n   create a complete additional wrapping layer to go back to the BSD sockets \n   API, we redefine the Telit interface and values back to standard BSD ones.\n   \n   Adding to the problem, the Telit stdio.h pulls in headers that define\n   their own versions of some of the values that we use here, so we have to\n   undefine them in order to redefine them to the Telit values */\n\n#include <m2m_type.h>\n#include <m2m_socket_api.h>\n\n#undef FD_ISSET\n#undef FD_SET\n#undef FD_SETSIZE\n#undef FD_ZERO\n#undef fd_set\n\n/* Constants */\n\n#define AF_INET\t\t\t\t\tM2M_SOCKET_BSD_AF_INET\n#define FD_SETSIZE\t\t\t\tM2M_SOCKET_BSD_FD_SETSIZE\n#define INADDR_ANY\t\t\t\tM2M_SOCKET_BSD_INADDR_ANY\n#define IPPROTO_ICMP\t\t\tM2M_SOCKET_BSD_IPPROTO_ICMP\n#define IPPROTO_TCP\t\t\t\tM2M_SOCKET_BSD_IPPROTO_TCP\n#define IPPROTO_UDP\t\t\t\tM2M_SOCKET_BSD_IPPROTO_UDP\n#define PF_INET\t\t\t\t\tM2M_SOCKET_BSD_PF_INET\n#define PF_UNSPEC\t\t\t\tM2M_SOCKET_BSD_PF_UNSPEC\n#define SHUT_WR\t\t\t\t\tM2M_SOCKET_BSD_SHUT_WR\n#define SO_ERROR\t\t\t\tM2M_SOCKET_BSD_SO_ERROR\n#define SO_REUSEADDR\t\t\tM2M_SOCKET_BSD_SO_REUSEADDR\n#define SOCK_DGRAM\t\t\t\tM2M_SOCKET_BSD_SOCK_DGRAM\n#define SOCK_RAW\t\t\t\tM2M_SOCKET_BSD_SOCK_RAW\n#define SOCK_STREAM\t\t\t\tM2M_SOCKET_BSD_SOCK_STREAM\n#define SOL_SOCKET\t\t\t\tM2M_SOCKET_BSD_SOL_SOCKET\n#define TCP_NODELAY\t\t\t\tM2M_SOCKET_BSD_TCP_NODELAY\n\n/* Data structures.  The sockaddr/sockaddr_in/hostent structures are another \n   Telit specialty, they're defined as:\n\n\ttypedef struct M2M_SOCKET_BSD_XXX { ... } M2M_SOCKET_BSD_XXX;\n\n   so they're both a tag and a typedef, and can be used as both\n   M2M_SOCKET_BSD_XXX and 'struct M2M_SOCKET_BSD_XXX' */\n\n#define fd_set\t\t\t\t\tM2M_SOCKET_BSD_FD_SET\n#define hostent\t\t\t\t\tM2M_SOCKET_BSD_HOSTENT\n#define sockaddr\t\t\t\tM2M_SOCKET_BSD_SOCKADDR\n#define sockaddr_in\t\t\t\tM2M_SOCKET_BSD_SOCKADDR_IN\n#define timeval\t\t\t\t\tM2M_SOCKET_BSD_TIMEVAL\n#define tv_sec\t\t\t\t\tm_tv_sec\n#define tv_usec\t\t\t\t\tm_tv_usec\n\n/* Functions */\n\n#define accept\t\t\t\t\tm2m_socket_bsd_accept\n#define bind\t\t\t\t\tm2m_socket_bsd_bind\n#define closesocket\t\t\t\tm2m_socket_bsd_close\n#define connect\t\t\t\t\tm2m_socket_bsd_connect\n#define FD_ISSET\t\t\t\tm2m_socket_bsd_fd_isset_func\n#define FD_SET\t\t\t\t\tm2m_socket_bsd_fd_set_func\n#define FD_ZERO\t\t\t\t\tm2m_socket_bsd_fd_zero_func\n#define getsockopt\t\t\t\tm2m_socket_bsd_get_sock_opt\n#define htons\t\t\t\t\tm2m_socket_bsd_htons\n#define inet_addr\t\t\t\tm2m_socket_bsd_inet_addr\n#define inet_ntoa( addr )\t\tm2m_socket_bsd_addr_str( addr.s_addr )\n#define listen\t\t\t\t\tm2m_socket_bsd_listen\n#define ntohs\t\t\t\t\tm2m_socket_bsd_ntohs\n#define recv\t\t\t\t\tm2m_socket_bsd_recv\n#define recvfrom\t\t\t\tm2m_socket_bsd_recv_from\n#define select\t\t\t\t\tm2m_socket_bsd_select\n#define send\t\t\t\t\tm2m_socket_bsd_send\n#define sendto\t\t\t\t\tm2m_socket_bsd_send_to\n#define shutdown\t\t\t\tm2m_socket_bsd_shutdown\n#define setsockopt\t\t\t\tm2m_socket_bsd_set_sock_opt\n#define socket\t\t\t\t\tm2m_socket_bsd_socket\n\n/* Error names */\n\n#define EACCES\t\t\t\t\tM2M_SOCKET_BSD_EACCES\n#define ENOMEM\t\t\t\t\tM2M_SOCKET_BSD_ENOBUFS\n#define EADDRINUSE\t\t\t\tM2M_SOCKET_BSD_EADDRINUSE\n#define EADDRNOTAVAIL\t\t\tM2M_SOCKET_BSD_EADDRNOTAVAIL\n#define EAFNOSUPPORT\t\t\tM2M_SOCKET_BSD_EAFNOSUPPORT\n#define EALREADY\t\t\t\tM2M_SOCKET_BSD_EALREADY\n#define EBADF\t\t\t\t\tM2M_SOCKET_BSD_EBADF      \n#define ECONNABORTED\t\t\tM2M_SOCKET_BSD_ECONNABORTED   \n#define ECONNREFUSED\t\t\tM2M_SOCKET_BSD_ECONNREFUSED   \n#define ECONNRESET\t\t\t\tM2M_SOCKET_BSD_ECONNRESET     \n#define EINPROGRESS\t\t\t\tM2M_SOCKET_BSD_EINPROGRESS    \n#define EINTR\t\t\t\t\tM2M_SOCKET_BSD_EINTR          \n#define EISCONN\t\t\t\t\tM2M_SOCKET_BSD_EISCONN        \n#define EMFILE\t\t\t\t\tM2M_SOCKET_BSD_EMFILE         \n#define EMSGSIZE\t\t\t\tM2M_SOCKET_BSD_EMSGSIZE       \n#define ENETUNREACH\t\t\t\tM2M_SOCKET_BSD_ENETUNREACH    \n#define ENOBUFS\t\t\t\t\tM2M_SOCKET_BSD_ENOBUFS        \n#define ENOPROTOOPT\t\t\t\tM2M_SOCKET_BSD_ENOPROTOOPT    \n#define ENOTCONN\t\t\t\tM2M_SOCKET_BSD_ENOTCONN       \n#define ENOTSOCK\t\t\t\tM2M_SOCKET_BSD_ENOTSOCK       \n#define EPROTOTYPE\t\t\t\tM2M_SOCKET_BSD_EPROTOTYPE     \n#define ETIMEDOUT\t\t\t\tM2M_SOCKET_BSD_ETIMEDOUT      \n\n/* Telit defines special functions to get error codes rather than using \n   global variables, although they're still global-variable equivalents \n   since there's a single errno shared across all sockets */\n\n#define getErrorCode( socket )\tm2m_socket_errno()\n#define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\tm2m_socket_errno()\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Unix and Unix-compatible Systems\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Guardian sockets originally couldn't handle nonblocking I/O like standard\n   BSD sockets, but required the use of a special non-blocking socket type\n   (nowait sockets) and the use of AWAITIOX() on the I/O tag returned from\n   the nowait socket call, since the async state was tied to this rather\n   than to the socket handle.  One of the early G06 releases added select()\n   support, although even the latest documentation still claims that\n   select() isn't supported.  To avoid having to support two completely\n   different interfaces, we use the more recent (and BSD standard) select()\n   interface.  Anyone running this code on old systems will have to add\n   wrappers for the necessary socket_nw()/accept_nw()/AWAITIOX() calls */\n\n#elif ( defined( __BEOS__ ) && \\\n\t\t( defined( BONE_VERSION ) || defined( __HAIKU__ ) ) ) || \\\n\t  defined( __ECOS__ ) || defined( __MVS__ ) || \\\n\t  defined( __PALMOS__ ) || defined( __RTEMS__ ) || \\\n\t  defined ( __SYMBIAN32__ ) || defined( __TANDEM_NSK__ ) || \\\n\t  defined( __TANDEM_OSS__ ) || defined( __UNIX__ )\n\n/* C_IN is a cryptlib.h value which is also defined in some versions of\n   netdb.h, so we have to undefine it before we include any network header\n   files */\n\n#undef C_IN\n\n/* PHUX and Tandem OSS have broken networking headers that require manually\n   defining _XOPEN_SOURCE_EXTENDED in order for various function prototypes\n   to be enabled.  The Tandem variant of this problem has all the function\n   prototypes for the NSK target and a comment by the 'else' that follows\n   saying that it's for the OSS target, but then an ifdef for\n   _XOPEN_SOURCE_EXTENDED that prevents it from being enabled unless\n   _XOPEN_SOURCE_EXTENDED is also defined */\n\n#if ( defined( __hpux ) && ( OSVERSION >= 10 ) ) || defined( _OSS_TARGET )\n  #define _XOPEN_SOURCE_EXTENDED\t1\n#endif /* Workaround for inconsistent networking headers */\n\n/* In OS X 10.3 (Panther), Apple broke the bind interface by changing the\n   BIND_4_COMPAT define to BIND_8_COMPAT (\"Apple reinvented the wheel and\n   made it square\" is one of the more polite comments on this change).  In\n   order to get things to work, we have to define BIND_8_COMPAT here, which\n   forces the inclusion of nameser_compat.h when we include nameser.h.  All\n   (non-Apple) systems automatically define BIND_4_COMPAT to force this\n   inclusion, since Bind9 support (in the form of anything other than the\n   installed binaries) is still pretty rare.\n   \n   In addition to this, we need to explicitly define the BSD-style \n   BYTE_ORDER (to agument the existing Gnu-style __BYTE_ORDER__) since\n   nameser_compat.h explicitly checks for its presence at the start.  \n   Finally, we also need to define _DARWIN_C_SOURCE to ensure the correct\n   functioning of various BSD-isms in nameser_compat.h.\n   \n   Apple actually managed to make the wheel a cube, not a square */\n\n#if defined( __APPLE__ ) && !defined( BIND_8_COMPAT )\n  #define BIND_8_COMPAT\n  #ifndef BYTE_ORDER\n\t#define LITTLE_ENDIAN\t1234\n\t#define BIG_ENDIAN\t\t4321\n\t#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )\n\t  #define BYTE_ORDER\tLITTLE_ENDIAN\n\t#else\n\t  #define BYTE_ORDER\tBIG_ENDIAN\n\t#endif /* Big vs. little-endian */\n  #endif /* BYTE_ORDER */\n#endif /* Apple braindamage */\n\n#include <errno.h>\n#include <fcntl.h>\n#include <netdb.h>\n#if defined( __APPLE__ ) || defined( __BEOS__ ) || defined( __bsdi__ ) || \\\n\tdefined( __FreeBSD__ ) || defined( __hpux ) || defined( __MVS__ ) || \\\n\tdefined( __NetBSD__ ) || defined( __OpenBSD__ ) || defined( __QNX__ ) || \\\n\t( defined( sun ) && OSVERSION <= 5 ) || defined( __SYMBIAN32__ ) || \\\n\tdefined( __VMCMS__ )\n  #include <netinet/in.h>\n#endif /* OS x || BeOS || *BSDs || PHUX || SunOS 4.x/2.5.x || Symbian OS */\n#include <arpa/inet.h>\n#if !( defined( __CYGWIN__ ) || defined( __PALMOS__ ) || \\\n\t   defined( __SYMBIAN32__ ) || defined( USE_EMBEDDED_OS ) )\n  #include <arpa/nameser.h>\n#endif /* Cygwin || Symbian OS */\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* The following have conflicting definitions in xti.h */\n  #undef T_NULL\n  #undef T_UNSPEC\n#endif /* MVS || VM */\n#if !defined( __MVS__ )\n  /* netinet/tcp.h is a BSD-ism, but all Unixen seem to use this even if\n     XPG4 and SUS say it should be in xti.h */\n  #include <netinet/tcp.h>\n#endif /* !MVS */\n#if !( defined( __CYGWIN__ ) || defined( __PALMOS__ ) || \\\n\t   defined( __SYMBIAN32__ ) || defined( USE_EMBEDDED_OS ) )\n  #include <resolv.h>\n#endif /* Cygwin || Symbian OS */\n#if !defined( TCP_NODELAY ) && !defined( USE_EMBEDDED_OS )\n  #include <xti.h>\n  #if defined( __MVS__ ) || defined( __VMCMS__ )\n\t/* The following have conflicting definitions in nameser.h */\n\t#undef T_NULL\n\t#undef T_UNSPEC\n  #endif /* MVS || VM */\n#endif /* TCP_NODELAY */\n#ifdef __SCO_VERSION__\n  #include <signal.h>\n  #ifndef SIGIO\n\t#include <sys/signal.h>\n  #endif /* SIGIO not defined in signal.h - only from SCO */\n#endif /* UnixWare/SCO */\n#if defined( _AIX ) || defined( __PALMOS__ ) || defined( __QNX__ )\n  #include <sys/select.h>\n#endif /* Aches || Palm OS || QNX */\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#ifdef __PALMOS__\n  /* Needed for close().  unistd.h, which contains this, is normally\n     included by default in Unix environments, but isn't for PalmOS */\n  #include <unistd.h>\n#endif /* Palm OS */\n\n/* AIX and SCO don't define sockaddr_storage in their IPv6 headers so if\n   we detect the use if IPv6 (via IPv6-only status codes) we define a \n   placeholder equivalent here */\n\n#if ( ( defined( _AIX ) && OSVERSION <= 5 ) || \\\n\t  defined( __SCO_VERSION__ ) ) && \\\n\tdefined( EAI_BADFLAGS ) && defined( EAI_NONAME )\n  struct sockaddr_storage {\n\t\tunion {\n\t\t\tstruct sockaddr_in6 bigSockaddrStruct;\n\t\t\tchar padding[ 128 ];\n\t\t\t} dummyMember;\n\t\t};\n#endif /* IPv6 versions without sockaddr_storage */\n\n/* PHUX generally doesn't define h_errno, we have to be careful here since\n   later versions may use macros to get around threading issues so we check\n   for the existence of a macro with the given name before defining our own\n   version */\n\n#if defined( __hpux ) && !defined( h_errno )\n  /* Usually missing from netdb.h */\n  extern int h_errno;\n#endif /* PHUX && !h_errno */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tVxWorks\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VxWorks__ )\n\n/* The VxWorks' netBufLib.h header defines its own clFree() that conflicts \n   with our one.  To deal with this we either use the nonportable \n   push_macro()/pop_macro() pragma if they're available or we re-include \n   misc/debug.h after overriding the include-once mechanism by undefining \n   _DEBUG_DEFINED and overriding the clAlloc()/clFree()-definition-once \n   mechanism by undefining clAlloc().  \n   \n   gcc's support for pop_macro() is typically buggy, so if we don't get \n   clFree() defined after we pop it we fall back to the re-include as well. \n   This is why it's done as a #ifndef rather than a #else */\n\n#if defined( __GNUC__ ) || defined( _MSC_VER )\n  #pragma push_macro( \"clFree\" )\n#endif /* push_macro() support */\n#undef clFree\n\n#include <ioLib.h>\n#include <selectLib.h>\n#include <hostLib.h>\n#include <sockLib.h>\n#include <arpa/inet.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <netinet6/in6.h>\n#include <sys/socket.h>\n\n#undef clFree\n#if defined( __GNUC__ ) || defined( _MSC_VER )\n  #pragma pop_macro( \"clFree\" )\n#endif /* push_macro() support */\n#ifndef clFree\t\t\t\t/* See comment above */\n  #undef _DEBUG_DEFINED\t\t/* Override include-once */\n  #undef clAlloc\t\t\t/* Override define-once */\n  #include \"misc/debug.h\"\n#endif /* push_macro() support */\n\n/* Although VxWorks defines AI_NUMERICSERV, any attempt to use it with \n   getaddrinfo() produces an EAI_BADFLAGS error, so we no-op it out */\n\n#undef AI_NUMERICSERV\n#define AI_NUMERICSERV\t0\n\n/* VxWorks doesn't have an h_errno and no-one seems to know what the \n   substitute for it is, if any, so we no-op it out */\n\n#define h_errno\t\t\t0\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tWindows\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __WINDOWS__ )\n\n/* Winsock2 wasn't available until VC++/eVC++ 4.0 so if we're running an\n   older version we have to use the Winsock1 interface */\n\n#if defined( _MSC_VER ) && ( _MSC_VER <= 800 ) || \\\n\tdefined( __WINCE__ ) && ( _WIN32_WCE < 400 )\n  #include <winsock.h>\n#else\n  #include <winsock2.h>\n  #include <ws2tcpip.h>\n#endif /* Older WinCE vs. newer WinCE and Win32 */\n\n/* VC++ 7 and newer have IPv6 support included in ws2tcpip.h, VC++ 6 can\n   have it bolted-on using the IPv6 Technology Preview but it's not present\n   by default.  In addition the Tech.Preview is quite buggy and unstable,\n   leaking handles and memory and in some cases leading to runaway memory\n   consumption that locks up the machine if the process isn't killed in\n   time, so we don't want to encourage its use */\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 1300 )\n  /* #include <tpipv6.h> */\t/* From IPv6 Tech.Preview */\n#endif /* VC++ 7 and newer */\n\n/* VC++ 7 and newer have DNS headers, for older versions (or for builds \n   using the DDK) we have to define the necessary types and constants \n   ourselves */\n\n#if defined( _MSC_VER ) && ( _MSC_VER > 1300 ) && !defined( WIN_DDK )\n  #include <windns.h>\n#elif defined( _MSC_VER ) && ( _MSC_VER > 800 )\n  /* windns.h is for newer compilers and many people don't have it yet, not \n\t helped by the fact that it's also changed over time.  For example,\n\t DnsRecordListFree() has also been DnsFreeRecordList() and DnsFree() at\n\t various times, with the parameters changing to match.  Because of this,\n\t we have to define our own (very cut-down) subset of what's in there\n\t here.  We define PIP4_ARRAY as a void * since it's only used to specify\n\t optional DNS servers to query, we never need this so we just set the\n\t parameter to NULL.  As with the DnsXXX functions, PIP4_ARRAY has\n\t changed over time.  It was known as PIP_ARRAY in the original VC++ .NET\n\t release but was renamed PIP4_ARRAY for .NET 2003, although some MSDN\n\t entries still refer to PIP_ARRAY even in the 2003 version */\n  typedef LONG DNS_STATUS;\n  typedef void *PIP4_ARRAY;\n  typedef DWORD IP4_ADDRESS;\n  typedef enum { DnsFreeFlat, DnsFreeRecordList } DNS_FREE_TYPE;\n  typedef enum { DnsConfigPrimaryDomainName_W, DnsConfigPrimaryDomainName_A,\n\t\t\t\t DnsConfigPrimaryDomainName_UTF8, DnsConfigAdapterDomainName_W,\n\t\t\t\t DnsConfigAdapterDomainName_A, DnsConfigAdapterDomainName_UTF8,\n\t\t\t\t DnsConfigDnsServerList, DnsConfigSearchList,\n\t\t\t\t DnsConfigAdapterInfo, DnsConfigPrimaryHostNameRegistrationEnabled,\n\t\t\t\t DnsConfigAdapterHostNameRegistrationEnabled,\n\t\t\t\t DnsConfigAddressRegistrationMaxCount, DnsConfigHostName_W,\n\t\t\t\t DnsConfigHostName_A, DnsConfigHostName_UTF8,\n\t\t\t\t DnsConfigFullHostName_W, DnsConfigFullHostName_A,\n\t\t\t\t DnsConfigFullHostName_UTF8 } DNS_CONFIG_TYPE;\n  #define DNS_TYPE_A\t\t\t\t1\n  #define DNS_TYPE_PTR\t\t\t\t12\n  #define DNS_TYPE_SRV\t\t\t\t33\n  #define DNS_QUERY_STANDARD\t\t0\n  #define DNS_QUERY_BYPASS_CACHE\t8\n  typedef struct {\n\t/* Technically these are DWORDs, but only integers are allowed for\n\t   bitfields.  This is OK in this case because sizeof( int ) ==\n\t   sizeof( DWORD ) */\n\tunsigned int Section : 2;\n\tunsigned int Delete : 1;\n\tunsigned int CharSet : 2;\n\tunsigned int Unused : 3;\n\tunsigned int Reserved : 24;\n\t} DNS_RECORD_FLAGS;\n  typedef struct {\n\tIP4_ADDRESS IpAddress;\n\t} DNS_A_DATA, *PDNS_A_DATA;\n  typedef struct {\n\tLPTSTR pNameHost;\n\t} DNS_PTR_DATA, *PDNS_PTR_DATA;\n  typedef struct {\n\tLPTSTR pNameTarget;\n\tWORD wPriority;\n\tWORD wWeight;\n\tWORD wPort;\n\tWORD Pad;\n\t} DNS_SRV_DATA, *PDNS_SRV_DATA;\n  typedef struct _DnsRecord {\n\tstruct _DnsRecord *pNext;\n\tLPTSTR pName;\n\tWORD wType;\n\tWORD wDataLength;\n\tunion {\n\t\tDWORD DW;\n\t\tDNS_RECORD_FLAGS S;\n\t} Flags;\n\tDWORD dwTtl;\n\tDWORD dwReserved;\n\tunion {\n\t\tDNS_A_DATA A;\n\t\tDNS_PTR_DATA PTR, Ptr,\n\t\t\t\t\t NS, Ns,\n\t\t\t\t\t CNAME, Cname,\n\t\t\t\t\t MB, Mb,\n\t\t\t\t\t MD, Md,\n\t\t\t\t\t MF, Mf,\n\t\t\t\t\t MG, Mg,\n\t\t\t\t\t MR, Mr;\n\t#if 0\n\t\tDNS_MINFO_DATA MINFO, Minfo,\n\t\t\t\t\t   RP, Rp;\n\t\tDNS_MX_DATA MX, Mx,\n\t\t\t\t\tAFSDB, Afsdb,\n\t\t\t\t\tRT, Rt;\n\t\tDNS_TXT_DATA HINFO, Hinfo,\n\t\t\t\t\t ISDN, Isdn,\n\t\t\t\t\t TXT, Txt,\n\t\t\t\t\t X25;\n\t\tDNS_NULL_DATA Null;\n\t\tDNS_WKS_DATA WKS, Wks;\n\t\tDNS_AAAA_DATA AAAA;\n\t\tDNS_KEY_DATA KEY, Key;\n\t\tDNS_SIG_DATA SIG, Sig;\n\t\tDNS_ATMA_DATA ATMA, Atma;\n\t\tDNS_NXT_DATA NXT, Nxt;\n\t#endif /* 0 */\n\t\tDNS_SRV_DATA SRV, Srv;\n\t#if 0\n\t\tDNS_TKEY_DATA TKEY, Tkey;\n\t\tDNS_TSIG_DATA TSIG, Tsig;\n\t\tDNS_WINS_DATA WINS, Wins;\n\t\tDNS_WINSR_DATA WINSR, WinsR,\n\t\t\t\t\t   NBSTAT, Nbstat;\n\t#endif /* 0 */\n\t\t} Data;\n\t} DNS_RECORD, *PDNS_RECORD;\n#endif /* VC++ 7 and newer vs. older versions */\n\n/* The Winsock FD_SET() in newer versions of VC++ uses a comma expression \n   that results in the following warning wherever it's used:\n\n\twarning C4548: expression before comma has no effect; expected \n\t\t\t\t   expression with side-effect\n\n   In theory we could use the __pragma operator introduced in VS 2010\n   to disable the warning:\n\n   FD_SET ->\n\t__pragma( warning( push ) ) \\\n\t__pragma( warning( disable:4548 ) ) \\\n\tFD_SET( ... );\n\t__pragma( warning( pop ) )\n\n   but there's no obvious way to define a new macro to replace an existing\n   one, so for now we'll have to live with the warnings */\n\n/* For backwards-compatibility purposes, wspiapi.h overrides the new address/\n   name-handling functions introduced for IPv6 with complex macros that\n   substitute inline function calls that try and dynamically load different\n   libraries depending on the Windows version and call various helper\n   functions to provide the same service.  Since we dynamically load the\n   required libraries, we don't need any of this complexity, so we undefine\n   the macros in order to make our own ones work */\n\n#ifdef getaddrinfo\n  #undef freeaddrinfo\n  #undef getaddrinfo\n  #undef getnameinfo\n#endif /* getaddrinfo defined as macros in wspiapi.h */\n\n/* Set up the appropriate calling convention for the Winsock API */\n\n#if defined( WSAAPI )\n  #define SOCKET_API\tWSAAPI\n#elif defined( WINSOCKAPI )\n  #define SOCKET_API\tWINSOCKAPI\n#else\n  #define SOCKET_API\tFAR PASCAL\n#endif /* WSAAPI */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tCustom TCP Stacks\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( USE_LWIP )\n\n#define LWIP_DNS\t\t1\t\t/* Needed for DNS lookups */\n\n#include \"lwip/sockets.h\"\n#include \"lwip/netdb.h\"\n\n/* LWIP has small pieces of IPv6 (getaddrinfo(), freeaddrinfo()) but none of\n   the surrounding functions (gai_strerror()) or defines (AI_PASSIVE,\n   NI_NUMERICxxx, IPPROTO_IPV6, IPV6_V6ONLY, etc), so we remove the two\n   xxxaddrinfo()s (which exist as macros) and rename the LWIP addrinfo \n   struct to something else so that we can replace it with out own one */\n\n#undef getaddrinfo\n#undef freeaddrinfo\n#define addrinfo\t\t_lwip_addrinfo\n\n/* LWIP doesn't define NO_ADDRESS, but NO_DATA is a synonym for this, or\n   IPPROTO_ICMP */\n\n#define NO_ADDRESS\t\t\t\tNO_DATA\n#define IPPROTO_ICMP\t\t\t1 \n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\t\tOther Systems\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#else\n\n#error You need to set up OS-specific networking include handling in tcp.h\n\n#endif /* OS-specific includes and defines */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tGeneral/Portability Defines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of a (v4) IP address and the number of IP addresses that we try\n   to connect to for a given host, used if we're providing an emulated\n   (IPv4-only) getaddrinfo() */\n\n#define IP_ADDR_SIZE\t4\n#define IP_ADDR_COUNT\t16\n\n/* Test for common socket errors.  For isBadSocket() we don't just compare\n   the socket to INVALID_SOCKET but perform a proper range check both to\n   catch any problems with buggy implementations that may return something\n   other than -1 to indicate an error, and because we're going to use the\n   value in FD_xyz() macros that often don't perform any range checking, and\n   a value outside the range 0...FD_SETSIZE can cause segfaults and other \n   problems.  In addition we exclude stdin/stdout/stderr if they're present, \n   since a socket with these handle values is somewhat suspicious,\n\n   The one exception to this is Windows sockets, which don't use a Berkeley-\n   type bitflag representation and therefore don't have the range problems \n   that the Berkeley implementation does.  In addition they define a socket\n   as an opaque unsigned type for which all values apart from INVALID_SOCKET \n   are (theoretically) valid, so we can't perform a range check like we\n   could for non-Windows implementations.\n   \n   Dealing with error reporting via the global variable errno is a pain\n   because it's only set on error (so it's not cleared if there's no error), \n   and in some cases (odd embedded stacks) not even for that on some code \n   paths.  To deal with this we have to clear it before any call for which \n   it's checked afterwards.  In theory all the checks are guarded with \n   ( function_return == -1 && errno == xxx ), but always clearring errno\n   makes for more defensive programming */\n\n#ifndef INVALID_SOCKET\n  #define INVALID_SOCKET\t\t\t( -1 )\n#endif /* INVALID_SOCKET */\n#if defined( __WINDOWS__ )\n  #define isBadSocket( socket )\t\t( ( socket ) == INVALID_SOCKET )\n#elif defined( STDERR_FILENO )\n  #define isBadSocket( socket )\t\t( ( socket ) <= STDERR_FILENO || \\\n\t\t\t\t\t\t\t\t\t  ( socket ) >= FD_SETSIZE )\n#else\n  #define isBadSocket( socket )\t\t( ( socket ) <= 0 || \\\n\t\t\t\t\t\t\t\t\t  ( socket ) >= FD_SETSIZE )\n#endif /* STDERR_FILENO */\n\n#ifndef SOCKET_ERROR\n  #define SOCKET_ERROR\t\t\t\t( -1 )\n#endif /* !SOCKET_ERROR */\n#ifndef INADDR_NONE\n  #define INADDR_NONE\t\t\t\t( ( in_addr_t ) -1 )\n#endif /* !INADDR_NONE */\n#define isSocketError( status )\t\t( ( status ) == SOCKET_ERROR )\n#define isBadAddress( address )\t\t( ( address ) == INADDR_NONE )\n#if defined( __MQXRTOS__ ) && ( RTCS_ERROR != SOCKET_ERROR )\n  /* MQX defines a return value RTCS_ERROR which happens to coincide with\n     the standard socket error value -1, we check this just to make sure \n\t that the values are consistent */\n  #error SOCKET_ERROR isnt the same as RTCS_ERROR\n#endif /* __MQXRTOS__ */\n\n#if defined( __BEOS__ )\n  #define clearErrorState()\t\t\terrno = 0\n  #if defined( BONE_VERSION )\n\t/* BONE returns \"Operation now in progress\" */\n\t#define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( errno == EWOULDBLOCK || \\\n\t\t\t\t\t\t\t\t\t  errno == 0x80007024 )\n  #else\n\t/* BeOS, even though it supposedly doesn't support nonblocking\n\t   sockets, can return EWOULDBLOCK */\n\t#define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( errno == EWOULDBLOCK )\n  #endif /* BeOS with/without BONE */\n#elif defined( __embOS__ )\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( getErrno( socket ) == IP_ERR_WOULD_BLOCK )\n#elif defined( __MQXRTOS__ )\n  /* It's not clear if MQX supports nonblocking connects, according to the \n     docs a connect always blocks and MQX_EINPROGRESS may only exist for\n\t Posix compatibility purposes */\n  #define clearErrorState()\t\t\tRTCS_set_errno( MQX_OK )\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( RTCS_errno == MQX_EINPROGRESS )\n#elif defined( __SYMBIAN32__ )\n  /* Symbian OS doesn't support nonblocking I/O */\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t0\n#elif defined( __Telit__ )\n  #define clearErrorState()\t\t\t/* No way to clear errors */\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( m2m_socket_errno() == M2M_SOCKET_BSD_EINPROGRESS )\n#elif defined( __WINDOWS__ )\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( WSAGetLastError() == WSAEWOULDBLOCK )\n#else\n  #define clearErrorState()\t\t\terrno = 0\n  #define isNonblockWarning( socket ) \\\n\t\t\t\t\t\t\t\t\t( errno == EINPROGRESS )\n#endif /* OS-specific socket error handling */\n\n/* Every system has its own way of indicating a timeout and a nonblocking\n   connect error.  The following pseudo-error codes are mapped to the \n   appropriate system-specific values */\n\n#if defined( __WINDOWS__ )\n  #define TIMEOUT_ERROR\t\t\t\tWSAETIMEDOUT\n  #define NONBLOCKCONNECT_ERROR\t\tWSAECONNREFUSED\n#elif defined( __embOS__ )\n  #define TIMEOUT_ERROR\t\t\t\tIP_ERR_TIMEOUT\n  #define NONBLOCKCONNECT_ERROR\t\tIP_ERR_CONN_REFUSED\n#elif defined( __MQXRTOS__ )\n  #define TIMEOUT_ERROR\t\t\t\tRTCSERR_TCP_TIMED_OUT\n  #define NONBLOCKCONNECT_ERROR\t\tRTCSERR_TCP_CONN_REFUSED\n#elif defined( __Nucleus__ )\n  #define TIMEOUT_ERROR\t\t\t\tNU_TIMEOUT\n  #define NONBLOCKCONNECT_ERROR\t\tNU_CONNECTION_REFUSED\n#else\n  #define TIMEOUT_ERROR\t\t\t\tETIMEDOUT\n  #define NONBLOCKCONNECT_ERROR\t\tECONNREFUSED\n#endif /* System-specific error types */\n\n/* Values used to disable Nagle via setsockopt() */\n\n#if defined( __embOS__ )\n  #define DISABLE_NAGLE_LEVEL\t\tSOL_SOCKET\n  #define DISABLE_NAGLE_OPTION\t\tTCP_NODELAY\n#elif defined( __MQXRTOS__ )\n  #define DISABLE_NAGLE_LEVEL\t\tSOL_TCP\n  #define DISABLE_NAGLE_OPTION\t\tOPT_NO_NAGLE_ALGORITHM\n#else\n  #define DISABLE_NAGLE_LEVEL\t\tIPPROTO_TCP\n  #define DISABLE_NAGLE_OPTION\t\tTCP_NODELAY\n#endif /* __MQXRTOS__ */\n\n/* Error code handling */\n\n#if defined( __WINDOWS__ )\n  #define getErrorCode( socket )\tWSAGetLastError()\n  #define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\t\tWSAGetLastError()\n#elif defined( __MQXRTOS__ )\n  #define getErrorCode( socket )\tRTCS_get_errno()\n  #define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\t\tRTCS_get_errno()\n#elif !defined( getErrorCode )\n  #if !defined( clearErrorState )\n\t#define clearErrorState()\t\terrno = 0\n  #endif /* !clearErrorState() */\n  #define getErrorCode( socket )\terrno\n  #if ( defined( __MVS__ ) && defined( _OPEN_THREADS ) )\n\t/* MVS converts this into a hidden function in the presence of threads,\n\t   but not transparently like other systems */\n\t#define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\t\t( *__h_errno() )\n  #else\n\t#define getHostErrorCode( socket ) \\\n\t\t\t\t\t\t\t\t\th_errno\n  #endif /* MVS */\n#endif /* OS-specific error code handling */\n\n/* Some OSes use a distinct socket handle type and require the use of \n   separate closesocket() and ioctlsocket() functions because socket handles\n   aren't the same as standard OS handles */\n\n#if !defined( __WINDOWS__ ) && !defined( SOCKET )\n  #define SOCKET\t\t\t\t\tint\n#endif /* SOCKET not already typedef'd or defined */\n#if !defined( __WINDOWS__ ) && !defined( __MQXRTOS__ ) && \\\n\t!defined( closesocket )\n  #if !defined( __BEOS__ ) || \\\n\t  ( defined( __BEOS__ ) && defined( BONE_VERSION ) )\n\t#define closesocket\t\t\t\tclose\n  #endif /* BeOS without BONE */\n  #define ioctlsocket\t\t\t\tioctl\n#endif /* OS-specific portability defines */\n\n/* Many systems don't define the in_*_t's */\n\n#if defined( __APPLE__ ) || defined( __BEOS__ ) || \\\n\tdefined( __bsdi__ ) || defined( _CRAY ) || \\\n\tdefined( __CYGWIN__ ) || defined( __FreeBSD__ ) || \\\n\tdefined( __hpux ) || defined( __linux__ ) || \\\n\tdefined( __NetBSD__ ) || defined( __OpenBSD__ ) || \\\n\tdefined( __QNX__ ) || ( defined( sun ) && OSVERSION <= 5 ) || \\\n\tdefined( __WINDOWS__ )\n  #ifndef in_addr_t\n\t#define in_addr_t\t\t\t\tu_long\n\t#define in_port_t\t\t\t\tu_short\n  #endif /* in_addr_t */\n#elif defined( __embOS__ )\n\t#define in_addr_t\t\t\t\tU32\n\t#define in_port_t\t\t\t\tU16\n#elif defined( __MQXRTOS__ ) || defined( USE_LWIP )\n\t#define in_addr_t\t\t\t\tunsigned long\n\t#define in_port_t\t\t\t\tunsigned short\n#elif defined( __Telit__ )\n\t#define in_addr_t\t\t\t\tUINT32\n\t#define in_port_t\t\t\t\tUINT16\n#endif /* Systems without in_*_t's */\n\n/* The handling of size parameters to socket functions is, as with most\n   things Unix, subject to random portability problems.  The traditional\n   BSD sockets API used int for size parameters to socket functions.  Posix \n   decided it'd be better to use size_t, but then people complained that \n   this wasn't binary-compatible with existing usage because on 64-bit\n   systems size_t != int.  Instead of changing it back to int, Posix defined\n   a new type, socklen_t, which may or may not be an int.  So some systems\n   have int, some have size_t, some have socklen_t defined to int, and some\n   have socklen_t defined to something else.  \n   \n   PHUX, as usual, is particularly bad, defaulting to the BSD form with int \n   unless you define _XOPEN_SOURCE_EXTENDED, in which case you get socklen_t \n   but it's mapped to size_t without any change in the sockets API, which \n   still expects int (the PHUX select() has a similar problem, see the \n   comment in random/unix.c).  \n   \n   Finally, MQX uses uint16_t everywhere except getsockopt(), where it's a \n   uint32_t.  There's no easy way to deal with this so we have to provide a\n   wrapper that uses the correct type.  Making SIZE_TYPE an int/uint32_t is\n   the last painful, with only one function, accept(), needing to be wrapped.\n   \n   To resolve this (where it's possible), we try and use socklen_t if we \n   detect its presence, otherwise we use int where we know it's safe to do \n   so, and failing that we fall back to size_t */\n\n#if defined( socklen_t ) || defined( __socklen_t_defined ) || \\\n\tdefined( _SOCKLEN_T )\n  #define SIZE_TYPE\t\t\t\t\tsocklen_t\n#elif defined( __BEOS__ ) || defined( _CRAY ) || defined( __WINDOWS__ )\n  #define SIZE_TYPE\t\t\t\t\tint\n#else\n  #define SIZE_TYPE\t\t\t\t\tsize_t\n#endif /* Different size types */\n\n/* The Bind namespace (via nameser.h) was cleaned up between the old (widely-\n   used) Bind4 API and the newer (little-used) Bind8/9 one.  In order to\n   handle both, we use the newer definitions, but map them back to the Bind4\n   forms if required.  The only thing this doesn't give us is the HEADER\n   struct, which seems to have no equivalent in Bind8/9 */\n\n#ifndef NS_PACKETSZ\n  #define NS_PACKETSZ\t\t\t\tPACKETSZ\n  #define NS_HFIXEDSZ\t\t\t\tHFIXEDSZ\n  #define NS_RRFIXEDSZ\t\t\t\tRRFIXEDSZ\n  #define NS_QFIXEDSZ\t\t\t\tQFIXEDSZ\n#endif /* Bind8 names */\n\n/* Older versions of QNX don't define HFIXEDSZ */\n\n#if defined( __QNX__ ) && ( OSVERSION <= 4 )\n  #define HFIXEDSZ\t\t\t\t\t12\n#endif /* QNX 4.x */\n\n/* Values defined in some environments but not in others.  MSG_NOSIGNAL is\n   used to avoid SIGPIPEs on writes if the other side closes the connection,\n   if it's not implemented in this environment we just clear the flag */\n\n#ifndef SHUT_WR\n  #define SHUT_WR\t\t\t\t\t1\n#endif /* SHUT_WR */\n#ifndef MSG_NOSIGNAL\n  #define MSG_NOSIGNAL\t\t\t\t0\n#endif /* MSG_NOSIGNAL */\n\n/* If we can't connect, we perform some basic diagnostics to see whether the\n   host is up and reachable.  This requires the use of raw sockets, which \n   aren't available in all environments.\n   \n   embOS supports raw sockets but no sub-protocols within them (e.g. \n   IPPROTO_ICMP), and while there's direct support for pinging a host via \n   IP_SendPing() it's both a custom API and there's no way to see the \n   returned packet, just an OK/not OK return value, so we don't try and do \n   anything further with this */\n\n#if !defined( __embOS__  ) && !defined( __MQXRTOS__ )\n  #define USE_RAW_SOCKETS\n#endif /* !__embOS__ && !__MQXRTOS__ */\n\n/* For some connections that involve long-running sessions we need to be\n   able to gracefully recover from local errors such as an interrupted system\n   call, and remote errors such as the remote process or host crashing and\n   restarting, which we can do by closing and re-opening the connection.  The\n   various situations are:\n\n\tLocal error:\n\t\tRetry the call on EAGAIN or EINTR\n\n\tProcess crashes and restarts:\n\t\tWrite: Remote host sends a RST in response to an attempt to continue\n\t\t\t\ta TCP session that it doesn't remember, which is reported\n\t\t\t\tlocally as the dreaded (if you ssh or NNTP to remote hosts a\n\t\t\t\tlot) connection reset by peer error.\n\t\tRead: Remote host sends a FIN, we read 0 bytes.\n\n\tNetwork problem:\n\t\tWrite: Data is re-sent, if a read is pending it returns ETIMEDOUT,\n\t\t\t\totherwise write returns EPIPE or SIGPIPE (although we try\n\t\t\t\tand avoid the latter using MSG_NOSIGNAL).  Some\n\t\t\t\timplementations may also return ENETUNREACH or EHOSTUNREACH\n\t\t\t\tif they receive the right ICMP information.\n\t\tRead: See above, without the write sematics.\n\n\tHost crashes and restarts:\n\t\tWrite: Looks like a network outage until the host is restarted, then\n\t\t\t\tgets an EPIPE/SIGPIPE.\n\t\tRead: As for write, but gets a ECONNRESET.\n\n   The following macros check for various non-fatal/recoverable error\n   conditions, in the future we may want to address some of the others listed\n   above as well.  A restartable error is a local error for which we can\n   retry the call, a recoverable error is a remote error for which we would\n   need to re-establish the connection.  Note that any version of Winsock\n   newer than the 16-bit ones shouldn't give us an EINPROGRESS, however some\n   early stacks would still give this on occasions such as when another\n   thread was doing (blocking) name resolution, and even with the very latest\n   versions this is still something that can cause problems for other\n   threads */\n\n#if defined( __WINDOWS__ )\n  #define clearErrorState()\n  #define isRecoverableError( status )\t( ( status ) == WSAECONNRESET )\n  #define isRestartableError( socket )\t( WSAGetLastError() == WSAEWOULDBLOCK || \\\n\t\t\t\t\t\t\t\t\t\t  WSAGetLastError() == WSAEINPROGRESS )\n  #define isTimeoutError( socket )\t\t( WSAGetLastError() == WSAETIMEDOUT )\n#elif defined( __embOS__ )\n  #define isRecoverableError( status )\t( ( status ) == IP_ERR_CONN_RESET )\n  #define isRestartableError( socket )\t( getErrno( socket ) == IP_ERR_WOULD_BLOCK || \\\n\t\t\t\t\t\t\t\t\t\t  getErrno( socket ) == IP_ERR_IN_PROGRESS )\n  #define isTimeoutError( socket )\t\t( getErrno( socket ) == IP_ERR_TIMEOUT )\n#elif defined( __MQXRTOS__ )\n  /* We can't use RTCS_get_errno() to get the error since this clears the \n     error state after it's read, so we have to access RTCS_errno \n\t directly.  In addition it's not clear if MQX_EINTR or MQX_EAGAIN will\n\t ever be returned, they're Posix-compatibility codes that probably have\n\t no equivalent in MQX */\n  #define isRecoverableError( status )\t( ( status ) == RTCSERR_TCP_CONN_RESET )\n  #define isRestartableError( socket )\t( RTCS_errno == MQX_EINTR || \\\n\t\t\t\t\t\t\t\t\t\t  RTCS_errno == MQX_EAGAIN )\n  #define isTimeoutError( socket )\t\t( RTCS_errno == RTCSERR_TIMEOUT || \\\n\t\t\t\t\t\t\t\t\t\t  RTCS_errno == RTCSERR_TCP_TIMED_OUT )\n#elif defined( __Telit__ )\n  #define isRecoverableError( status )\t( ( status ) == M2M_SOCKET_BSD_ECONNRESET )\n  #define isRestartableError( socket )\t( m2m_socket_errno() == M2M_SOCKET_BSD_EINTR )\n  #define isTimeoutError( socket )\t\t( m2m_socket_errno() == M2M_SOCKET_BSD_ETIMEDOUT )\n#else\n  #if !defined( clearErrorState )\n\t#define clearErrorState()\t\t\terrno = 0\n  #endif /* !clearErrorState() */\n  #define isRecoverableError( status )\t( ( status ) == ECONNRESET )\n  #define isRestartableError( socket )\t( errno == EINTR || errno == EAGAIN )\n  #define isTimeoutError()\t\t\t\t( errno == ETIMEDOUT )\n#endif /* OS-specific status codes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tIPv6 Defines\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Now that we've included all of the networking headers, try and guess\n   whether this is an IPv6-enabled system.  We can detect this by the\n   existence of definitions for the EAI_xxx return values from\n   getaddrinfo().  Note that we can't safely detect it using the more\n   obvious AF_INET6 since many headers defined this in anticipation of IPv6\n   long before the remaining code support was present */\n\n#if defined( EAI_BADFLAGS ) && defined( EAI_NONAME )\n  #define USE_IPv6\n  #define USE_IPv6_DNSAPI\n#endif /* getaddrinfo() return values defined */\n\n/* Some systems have just enough IPv6 defines present to be awkward (BeOS \n   with the BONE network stack) so we temporarily define IPv6 and then use a \n   stack-specific subset of IPv6 defines further on */\n\n#if defined( __BEOS__ ) && defined( BONE_VERSION )\n  #define USE_IPv6\n#endif /* BeOS with BONE */\n\n/* The generic sockaddr struct used to reserve storage for protocol-specific\n   sockaddr structs.  The IPv4 equivalent is given below in the IPv6-\n   emulation definitions */\n\n#ifdef USE_IPv6\n  #define SOCKADDR_STORAGE\t\t\tstruct sockaddr_storage\n#endif /* IPv6 */\n\n/* IPv6 emulation functions used to provide a single consistent interface.\n   We distinguish between USE_IPv6 for full IPv6 functionality and \n   USE_IPv6_DNSAPI for support for the DNS functions introduced in IPv6, \n   getaddrinfo() et al, without full IPv6 support */\n\n#ifndef USE_IPv6_DNSAPI\n  /* The addrinfo struct used by getaddrinfo() */\n  struct addrinfo {\n\tint ai_flags;\t\t\t\t/* AI_PASSIVE, NI_NUMERICHOST */\n\tint ai_family;\t\t\t\t/* PF_INET */\n\tint ai_socktype;\t\t\t/* SOCK_STREAM */\n\tint ai_protocol;\t\t\t/* IPPROTO_TCP */\n\tsize_t ai_addrlen;\t\t\t/* Length of ai_addr */\n\tchar *ai_canonname;\t\t\t/* CNAME for nodename */\n\tARRAY_FIXED( ai_addrlen ) \\\n\tstruct sockaddr *ai_addr;\t/* IPv4 or IPv6 sockaddr */\n\tstruct addrinfo *ai_next;\t/* Next addrinfo structure list */\n\t};\n\n  /* getaddrinfo() flags and values */\n  #define AI_PASSIVE\t\t0x1\t\t/* Flag for hints are for getaddrinfo() */\n\n  /* An emulation of the getaddrinfo() function family */\n  #define getaddrinfo\t\tmy_getaddrinfo\n  #define freeaddrinfo\t\tmy_freeaddrinfo\n  #define getnameinfo\t\tmy_getnameinfo\n\n  /* Error codes returned by the emulated getaddrinfo() */\n  #if defined( __WINDOWS__ )\n\t#define OUT_OF_MEMORY_ERROR\t\tWSAENOBUFS\n\t#define HOST_NOT_FOUND_ERROR\tWSAHOST_NOT_FOUND\n  #elif defined( __embOS__ )\n\t#define OUT_OF_MEMORY_ERROR\t\tIP_ERR_NO_MEM\n\t#define HOST_NOT_FOUND_ERROR\tIP_ERR_ADDR_NOT_AVAIL\n  #elif defined( __MQXRTOS__ )\n\t#define OUT_OF_MEMORY_ERROR\t\tRTCSERR_OUT_OF_MEMORY\n\t#define HOST_NOT_FOUND_ERROR\tRTCSERR_DNS_INVALID_NAME\n  #elif defined( __Nucleus__ )\n\t#define OUT_OF_MEMORY_ERROR\t\tNU_NO_SOCK_MEMORY\n\t#define HOST_NOT_FOUND_ERROR\tNU_NOT_A_HOST\n  #else\n\t#define OUT_OF_MEMORY_ERROR\t\tENOMEM\n\t#if !( defined( __Quadros__ ) || defined( __Telit__ ) )\n\t  #define HOST_NOT_FOUND_ERROR\tHOST_NOT_FOUND\n\t#else\n\t  #define HOST_NOT_FOUND_ERROR\tEADDRNOTAVAIL\t/* No proper error code */\n\t#endif /* !( __Quadros__ || __Telit__ ) */\n  #endif /* System-specific error types */\n\n  /* Windows uses the Pascal calling convention for these functions, we hide \n     this behind a define that becomes a no-op on non-Windows systems */\n  #ifndef SOCKET_API\n\t#define SOCKET_API\n  #endif /* SOCKET_API */\n#endif /* USE_IPv6_DNSAPI */\n\n#ifndef USE_IPv6\n  /* The generic sockaddr struct used to reserve storage for protocol-\n     specific sockaddr structs.  This isn't quite right but since all\n\t we're using it for is to reserve storage (we never actually look\n\t inside it) it's OK to use here  */\n  typedef char SOCKADDR_STORAGE[ 128 ];\n\n  /* getnameinfo() flags and values.  Windows uses different values for \n     these than anyone else, and even if we're not on an explicitly IPv6-\n\t enabled system we could still end up dynamically pulling in the \n\t required libraries, so we need to ensure that we're using the same flag\n\t values that Windows does */\n  #ifdef __WINDOWS__\n\t#define NI_NUMERICHOST\t0x2\t\t/* Return numeric form of host addr.*/\n\t#define NI_NUMERICSERV\t0x8\t\t/* Return numeric form of host port */\n  #else\n\t#define NI_NUMERICHOST\t0x1\t\t/* Return numeric form of host addr.*/\n\t#define NI_NUMERICSERV\t0x2\t\t/* Return numeric form of host port */\n  #endif /* __WINDOWS__ */\n\n  /* get/setsockopt() flags and values.  Again, we have to use slightly\n     different values for Windows in some cases */\n  #define IPPROTO_IPV6\t\t41\t\t/* IPv6 */\n  #ifndef IPV6_V6ONLY\n\t/* May be overridden by an earlier define for some stacks that turns \n\t   it into a no-op */\n\t#if defined( __WINDOWS__ ) || defined( __VxWorks__ )\n\t  #define IPV6_V6ONLY\t27\t\t/* Force dual stack to use only IPv6 */\n\t#else\n\t  #define IPV6_V6ONLY\t26\t\t/* Force dual stack to use only IPv6 */\n\t#endif /* __WINDOWS__ */\n  #endif /* IPV6_V6ONLY */\n#else\n  /* IPV6_V6ONLY isn't universally defined under Windows even if IPv6 \n\t support is available.  The situations under which this occurs are \n\t rather unclear, it's happened for some x86-64 builds (although not for \n\t straight x86 builds on the same machine), for older WinCE builds, and\n\t in one case for an x86 build using VS 2005, possibly caused by \n\t differences between VS and WinSDK headers.  To resolve this mess, if \n\t IPv6 is defined under Windows but IPV6_V6ONLY isn't, we explicitly \n\t define it ourselves */\n  #if defined( __WINDOWS__ ) && !defined( IPV6_V6ONLY )\n\t#define IPV6_V6ONLY\t\t27\t\t/* Force dual stack to use only IPv6 */\n  #endif /* Some Windows build environments */\n#endif /* USE_IPv6 */\n\n/* A subset of the above for BeOS with the BONE network stack.  See the\n   full IPv6 version above for descriptions of the entries */\n\n#if defined( __BEOS__ ) && defined( BONE_VERSION )\n  #undef USE_IPv6\t\t\t\t\t/* We really don't do IPv6 */\n\n  typedef char SOCKADDR_STORAGE[ 128 ];\n\n  #define getaddrinfo\t\tmy_getaddrinfo\n  #define freeaddrinfo\t\tmy_freeaddrinfo\n  #define getnameinfo\t\tmy_getnameinfo\n\n  static int my_getaddrinfo( const char *nodename, const char *servname,\n\t\t\t\t\t\t\t const struct addrinfo *hints,\n\t\t\t\t\t\t\t struct addrinfo **res );\n  static void my_freeaddrinfo( struct addrinfo *ai );\n  static int my_getnameinfo( const struct sockaddr *sa, SIZE_TYPE salen,\n\t\t\t\t\t\t\t char *node, SIZE_TYPE nodelen,\n\t\t\t\t\t\t\t char *service, SIZE_TYPE servicelen,\n\t\t\t\t\t\t\t int flags );\n#endif /* BeOS with BONE */\n\n/* Older versions of the Sun development tools define some IPv6 options but \n   not others */\n\n#if defined( USE_IPv6 ) && defined( __SUNPRO_C )\n  #ifndef IPV6_V6ONLY\n\t#define IPV6_V6ONLY\t26\t\t/* Force dual stack to use only IPv6 */\n  #endif /* !IPV6_V6ONLY */\n#endif /* Slowaris with older Sun compilers */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tResolver Defines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Values defined in some environments but not in others.  T_SRV and\n   NS_SRVFIXEDSZ are used for DNS SRV lookups.  Newer versions of bind use a\n   ns_t_srv enum for T_SRV but since we can't autodetect this via the\n   preprocessor we always define T_SRV ourselves */\n\n#ifndef T_SRV\n  #define T_SRV\t\t\t\t\t\t33\n#endif /* !T_SRV */\n#ifndef NS_SRVFIXEDSZ\n  #define NS_SRVFIXEDSZ\t\t\t\t( NS_RRFIXEDSZ + 6 )\n#endif /* !NS_SRVFIXEDSZ */\n#ifndef AI_ADDRCONFIG\n  #define AI_ADDRCONFIG\t\t\t\t0\n#endif /* !AI_ADDRCONFIG */\n#ifndef AI_NUMERICSERV\n  #define AI_NUMERICSERV\t\t\t0\n#endif /* !AI_NUMERICSERV */\n\n/* Check whether an address family returned from a DNS lookup is allowed \n   (meaning recognised) */\n\n#ifdef USE_IPv6\n  #define allowedAddressFamily( family ) \\\n\t\t  ( ( ( family ) == AF_INET ) || ( ( family ) == AF_INET6 ) )\n#else\n  #define allowedAddressFamily( family )\t( ( family ) == AF_INET )\n#endif /* IPv6 */\n\n/* gethostbyname is a problem function because the standard version is non-\n   thread-safe due to the use of static internal storage to contain the\n   returned host info.  Some OSes (Windows, PHUX >= 11.0, OSF/1 >= 4.0,\n   Aches >= 4.3) don't have a problem with this because they use thread\n   local storage, but others either require the use of nonstandard _r\n   variants or simply don't handle it at all.  To make it even more\n   entertaining, there are at least three different variations of the _r\n   form:\n\n\tLinux (and glibc systems in general, but not BeOS with BONE):\n\n\tint gethostbyname_r( const char *name, struct hostent *result_buf,\n\t\t\t\t\t\t char *buf, size_t buflen, struct hostent **result,\n\t\t\t\t\t\t int *h_errnop);\n\n\tSlowaris >= 2.5.1, IRIX >= 6.5, QNX:\n\n\tstruct hostent *gethostbyname_r( const char *name,\n\t\t\t\t\t\t\t\t\t struct hostent *result, char *buffer,\n\t\t\t\t\t\t\t\t\t int buflen, int *h_errnop );\n\n\tOSF/1, Aches (deprecated, see above):\n\n\tint gethostbyname_r( const char *name, struct hostent *hptr,\n\t\t\t\t\t\t struct hostent_data *hdptr );\n\n   To work around this mess, we define macros for thread-safe versions of\n   gethostbyname that can be retargeted to the appropriate function as\n   required.\n   \n   In addition, Telit and embOS barely have any DNS functionality, and in\n   contrast to all of their other BSD-equivalent functions provide a \n   gethostbyname() or equivalent that's nothing like the BSD version, which \n   means that we have to emulate it via a complex wrapper */\n\n#if defined( USE_THREADS ) && defined( __GLIBC__ ) && ( __GLIBC__ >= 2 ) && \\\n\t( !defined( __BEOS__ ) || !defined( BONE_VERSION ) )\n  #define gethostbyname_vars() \\\n\t\t  char hostBuf[ 4096 ]; \\\n\t\t  struct hostent hostEnt;\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  hostErrno = 0; \\\n\t\t  if( gethostbyname_r( hostName, &hostEnt, hostBuf, 4096, &hostEntPtr, &hostErrno ) < 0 ) \\\n\t\t\thostEntPtr = NULL\n#elif defined( USE_THREADS ) && \\\n\t  ( ( defined( sun ) && OSVERSION > 4 ) || \\\n\t\t( defined( __sgi ) && OSVERSION >= 6 ) || defined( __QNX__ ) )\n  #define gethostbyname_vars() \\\n\t\t  char hostBuf[ 4096 ]; \\\n\t\t  struct hostent hostEnt;\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  hostErrno = 0; \\\n\t\t  hostEntPtr = gethostbyname_r( hostName, &hostEnt, hostBuf, 4096, &hostErrno )\n#elif defined( USE_THREADS ) && ( defined( USE_LWIP ) )\n  #define gethostbyname_vars() \\\n\t\t  char hostBuf[ 1024 ]; \\\n\t\t  struct hostent hostEnt;\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  hostErrno = 0; \\\n\t\t  if( gethostbyname_r( hostName, &hostEnt, hostBuf, 1024, &hostEntPtr, &hostErrno ) < 0 ) \\\n\t\t\thostEntPtr = NULL\n#elif defined( __embOS__ )\n  #define gethostbyname_vars() \\\n\t\t  char *hAddrList[ 2 ]; \\\n\t\t  struct hostent hostEnt;\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  { \\\n\t\t  U32 hostAddress; \\\n\t\t  int result; \\\n\t\t  \\\n\t\t  hostErrno = 0; \\\n\t\t  result = IP_ResolveHost( hostName, &hostAddress, 10000 ); \\\n\t\t  if( result < 0 ) \\\n\t\t\t{ \\\n\t\t\thostEntPtr = NULL; \\\n\t\t\thostErrno = IP_ERR_ADDR_NOT_AVAIL; \\\n\t\t\t} \\\n\t\t  else \\\n\t\t\t{ \\\n\t\t\thostEntPtr = &hostEnt; \\\n\t\t\tmemset( hostEntPtr, 0, sizeof( struct hostent ) ); \\\n\t\t\thostEntPtr->h_addrtype = AF_INET; \\\n\t\t\thostEntPtr->h_length = IP_ADDR_SIZE; \\\n\t\t\thAddrList[ 0 ] = ( CHAR * ) hostAddress; /* Already in network order */ \\\n\t\t\thAddrList[ 1 ] = NULL; \\\n\t\t\thostEntPtr->h_addr_list = hAddrList; \\\n\t\t\t} \\\n\t\t  }\n#elif defined( __Telit__ )\n  #define gethostbyname_vars() \\\n\t\t  char *hAddrList[ 2 ]; \\\n\t\t  M2M_SOCKET_BSD_HOSTENT hostEnt;\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  { \\\n\t\t  UINT32 hostAddress; \\\n\t\t  \\\n\t\t  hostErrno = 0; \\\n\t\t  hostAddress = m2m_socket_bsd_get_host_by_name( hostName ); \\\n\t\t  if( hostAddress == 0 ) \\\n\t\t\t{ \\\n\t\t\thostEntPtr = NULL; \\\n\t\t\thostErrno = m2m_socket_errno(); \\\n\t\t\t} \\\n\t\t  else \\\n\t\t\t{ \\\n\t\t\thostEntPtr = &hostEnt; \\\n\t\t\tmemset( hostEntPtr, 0, sizeof( M2M_SOCKET_BSD_HOSTENT ) ); \\\n\t\t\thostEntPtr->h_addrtype = M2M_SOCKET_BSD_AF_INET; \\\n\t\t\thostEntPtr->h_length = IP_ADDR_SIZE; \\\n\t\t\thAddrList[ 0 ] = ( CHAR * ) m2m_socket_bsd_htonl( hostAddress ); \\\n\t\t\thAddrList[ 1 ] = NULL; \\\n\t\t\thostEntPtr->h_addr_list = hAddrList; \\\n\t\t\t} \\\n\t\t  }\n#else\n  #define gethostbyname_vars()\n  #define gethostbyname_threadsafe( hostName, hostEntPtr, hostErrno ) \\\n\t\t  hostEntPtr = gethostbyname( hostName ); \\\n\t\t  hostErrno = h_errno\n#endif /* Various gethostbyname variants */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tNon-blocking I/O Defines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The traditional way to set a descriptor to nonblocking mode was an\n   ioctl with FIONBIO, however Posix prefers the O_NONBLOCK flag for fcntl()\n   so we use this if it's available, with some exceptions for systems like\n   VxWorks where it's present but doesn't work as expected.\n\n   Unfortunately if we haven't got the fcntl() interface available there's\n   no way to determine whether a socket is non-blocking or not, which is\n   particularly troublesome for Windows where we need to ensure that the\n   socket is blocking in order to avoid Winsock bugs with nonblocking\n   sockets.  Although WSAIoctl() would appear to provide an interface for\n   obtaining the nonblocking status, it doesn't provide any more\n   functionality than ioctlsocket(), returning an error if we try and read\n   the FIONBIO value.\n\n   If we're just using this as a basic valid-socket check we could also use \n   ( GetFileType( ( HANDLE ) stream->netSocket ) == FILE_TYPE_PIPE ) ? 0 : \\\n   WSAEBADF to check that it's a socket, but there's a bug under all Win9x \n   versions for which GetFileType() on a socket returns FILE_TYPE_UNKNOWN, \n   so we can't reliably detect a socket with this.  In any case though \n   ioctlsocket() will return WSAENOTSOCK if it's not a socket, so this is \n   covered by the default handling anyway.\n\n   The best that we can do in this case is to force the socket to be\n   blocking, which somewhat voids the guarantee that we leave the socket as\n   we found it, but OTOH if we've been passed an invalid socket the caller\n   will have to abort and fix the problem anyway, so changing the socket\n   state isn't such a big deal.\n\n   BeOS is even worse, not only is there no way to determine whether a\n   socket is blocking or not, it'll also quite happily perform socket\n   functions like setsockopt() on a file descriptor (for example stdout),\n   so we can't even use this as a check for socket validity as it is under\n   other OSes.  Because of this the check socket function will always\n   indicate that something vaguely handle-like is a valid socket.\n\n   When we get the nonblocking status, if there's an error getting the\n   status we report it as a non-blocking socket, which results in the socket\n   being reported as invalid, the same as if it were a a genuine non-\n   blocking socket.\n   \n   If we're using the ioctlsocket() interface we make the argument an\n   unsigned long, in most cases this is a 'void *' but under Windows it's\n   an 'unsigned long *' so we use the most restrictive type */\n\n#if defined( F_GETFL ) && defined( F_SETFL ) && defined( O_NONBLOCK ) && \\\n\t!defined( __VxWorks__ )\n  #define getSocketNonblockingStatus( socket, value ) \\\n\t\t\t{ \\\n\t\t\tvalue = fcntl( socket, F_GETFL, 0 ); \\\n\t\t\tvalue = ( isSocketError( value ) || ( value & O_NONBLOCK ) ) ? \\\n\t\t\t\t\tTRUE : FALSE; \\\n\t\t\t}\n  #define setSocketNonblocking( socket ) \\\n\t\t\t{ \\\n\t\t\tconst int flags = fcntl( socket, F_GETFL, 0 ); \\\n\t\t\tfcntl( socket, F_SETFL, flags | O_NONBLOCK ); \\\n\t\t\t}\n  #define setSocketBlocking( socket ) \\\n\t\t\t{ \\\n\t\t\tconst int flags = fcntl( socket, F_GETFL, 0 ); \\\n\t\t\tfcntl( socket, F_SETFL, flags & ~O_NONBLOCK ); \\\n\t\t\t}\n#elif defined( FIONBIO )\n  #define getSocketNonblockingStatus( socket, value ) \\\n\t\t\t{ \\\n\t\t\tunsigned long nonBlock = 0; \\\n\t\t\tvalue = ioctlsocket( socket, FIONBIO, &nonBlock ); \\\n\t\t\tvalue = isSocketError( value ) ? TRUE : FALSE; \\\n\t\t\t}\n  #define setSocketNonblocking( socket ) \\\n\t\t\t{ \\\n\t\t\tunsigned long nonBlock = 1; \\\n\t\t\tioctlsocket( socket, FIONBIO, &nonBlock ); \\\n\t\t\t}\n  #define setSocketBlocking( socket ) \\\n\t\t\t{ \\\n\t\t\tunsigned long nonBlock = 0; \\\n\t\t\tioctlsocket( socket, FIONBIO, &nonBlock ); \\\n\t\t\t}\n#elif defined( __AMX__ ) || defined( __BEOS__ ) || defined( __embOS__ )\n  #define getSocketNonblockingStatus( socket, value ) \\\n\t\t\t{ \\\n\t\t\tint nonBlock = 0; \\\n\t\t\tvalue = getsockopt( socket, SOL_SOCKET, SO_NONBLOCK, &nonBlock, sizeof( int ) ); \\\n\t\t\tvalue = ( isSocketError( value ) || nonBlock ) ? \\\n\t\t\t\t\tTRUE : FALSE; \\\n\t\t\t}\n  #define setSocketNonblocking( socket ) \\\n\t\t\t{ \\\n\t\t\tint nonBlock = 1; \\\n\t\t\tsetsockopt( socket, SOL_SOCKET, SO_NONBLOCK, &nonBlock, sizeof( int ) ); \\\n\t\t\t}\n  #define setSocketBlocking( socket ) \\\n\t\t\t{ \\\n\t\t\tint nonBlock = 0; \\\n\t\t\tsetsockopt( socket, SOL_SOCKET, SO_NONBLOCK, &nonBlock, sizeof( int ) ); \\\n\t\t\t}\n#elif defined( __MQXRTOS__ )\n  #define getSocketNonblockingStatus( socket, value ) \\\n\t\t\t{ \\\n\t\t\tuint32_t size = sizeof( int ); \\\n\t\t\tint nonBlock = 0; \\\n\t\t\tvalue = getsockopt( socket, SOL_SOCKET, OPT_SEND_NOWAIT, &nonBlock, &size ); \\\n\t\t\tvalue = ( isSocketError( value ) || nonBlock ) ? \\\n\t\t\t\t\tTRUE : FALSE; \\\n\t\t\t}\n  #define setSocketNonblocking( socket ) \\\n\t\t\t{ \\\n\t\t\tint nonBlock = 1; \\\n\t\t\tsetsockopt( socket, SOL_SOCKET, OPT_SEND_NOWAIT, &nonBlock, sizeof( int ) ); \\\n\t\t\t}\n  #define setSocketBlocking( socket ) \\\n\t\t\t{ \\\n\t\t\tint nonBlock = 0; \\\n\t\t\tsetsockopt( socket, SOL_SOCKET, OPT_SEND_NOWAIT, &nonBlock, sizeof( int ) ); \\\n\t\t\t}\n#elif defined( __Nucleus__ )\n  /* Nucleus doesn't provide a mechanism to check whether a socket is non-\n     blocking, however the only time that this capability is required is \n\t when we're checking a user-provided socket.  These are created \n\t blocking by default under Nucleus, so we just hardwire the check to say \n\t that it's blocking */\n  #define getSocketNonblockingStatus( socket, value )\tvalue = FALSE\n  #define setSocketNonblocking( socket ) \\\n\t\t\tNU_Fcntl( socket, NU_SETFLAG, NU_NO_BLOCK )\n  #define setSocketBlocking( socket ) \\\n\t\t\tNU_Fcntl( socket, NU_SETFLAG, NU_BLOCK )\n#elif defined( __SYMBIAN32__ )\n  /* Symbian OS doesn't support nonblocking I/O */\n  #define getSocketNonblockingStatus( socket, value )\tvalue = FALSE\n  #define setSocketNonblocking( socket )\n  #define setSocketBlocking( socket )\n#elif defined( __Telit__ )\n  /* Telit doesn't provide a mechanism to check whether a socket is non-\n     blocking, however the only time that this capability is required is \n\t when we're checking a user-provided socket.  These appear to be created\n\t blocking by default under Telit, so we just hardwire the check to say \n\t that it's blocking */\n  #define getSocketNonblockingStatus( socket, value )\tvalue = FALSE\n  #define setSocketNonblocking( socket ) \\\n\t\t\t{ \\\n\t\t\tINT32 nonBlock = 1; \\\n\t\t\tm2m_socket_bsd_ioctl( socket, M2M_SOCKET_BSD_FIONBIO, &nonBlock ); \\\n\t\t\t}\n  #define setSocketBlocking( socket ) \\\n\t\t\t{ \\\n\t\t\tINT32 nonBlock = 0; \\\n\t\t\tm2m_socket_bsd_ioctl( socket, M2M_SOCKET_BSD_FIONBIO, &nonBlock ); \\\n\t\t\t}\n#else\n  #error Need to create macros to handle nonblocking I/O\n#endif /* Handling of blocking/nonblocking sockets */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tMisc.Functions and Defines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in dns.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getAddressInfo( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tOUT_PTR_COND struct addrinfo **addrInfoPtrPtr,\n\t\t\t\t\tIN_BUFFER_OPT( nameLen ) const char *name, \n\t\t\t\t\tIN_LENGTH_Z const int nameLen, \n\t\t\t\t\tIN_PORT const int port, const BOOLEAN isServer,\n\t\t\t\t\tconst BOOLEAN isStreamSocket );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid freeAddressInfo( struct addrinfo *addrInfoPtr );\nSTDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \\\nvoid getNameInfo( IN_BUFFER( sockAddrLen ) const void *sockAddr,\n\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) const int sockAddrLen,\n\t\t\t\t  OUT_BUFFER( addressMaxLen, *addressLen ) char *address, \n\t\t\t\t  IN_LENGTH_DNS const int addressMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( addressMaxLen ) int *addressLen, \n\t\t\t\t  OUT_PORT_Z int *port );\n\n/* Prototypes for functions in dns_srv.c */\n\n#ifdef USE_DNSSRV\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\n  int findHostInfo( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tOUT_BUFFER_FIXED( hostNameMaxLen ) char *hostName, \n\t\t\t\t\tIN_LENGTH_DNS const int hostNameMaxLen, \n\t\t\t\t\tOUT_PORT_Z int *hostPort, \n\t\t\t\t\tIN_BUFFER( nameLen ) const char *name, \n\t\t\t\t\tIN_LENGTH_DNS const int nameLen );\n#else\n  /* If there's no DNS support available in the OS there's not much that we\n\t can do to handle automatic host detection.  Setting hostPort as a side-\n\t effect is necessary because the #define otherwise no-ops it out, \n\t leading to declared-but-not-used warnings from some compilers */\n  #define findHostInfo( netStream, hostName, hostNameLen, hostPort, name, nameLen )\t\\\n\t\t  setSocketError( netStream, \"DNS SRV services not available\", 30, \\\n\t\t\t\t\t\t  CRYPT_ERROR_NOTAVAIL, FALSE ); \\\n\t\t  memset( hostName, 0, min( 16, hostNameLen ) ); \\\n\t\t  *( hostPort ) = 0\n#endif /* USE_DNSSRV */\n#endif /* _TCP_DEFINED */\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/tcp_conn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TCP/IP Connection Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Disable assorted socket handbrakes.  In theory these calls can fail, but \n   there's not much that we can do about it, and in any case things will \n   keep working anyway, so we don't try and handle any errors for this \n   situation */\n\nstatic void disableNagle( const SOCKET netSocket )\n\t{\n\tstatic const int trueValue = 1;\n\n\t( void ) setsockopt( netSocket, DISABLE_NAGLE_LEVEL, \n\t\t\t\t\t\t DISABLE_NAGLE_OPTION, ( void * ) &trueValue, \n\t\t\t\t\t\t sizeof( int ) );\n\t}\n\n#ifdef TCP_QUICKACK\n\nstatic void disableSlowACK( const SOCKET netSocket )\n\t{\n\tstatic const int trueValue = 1;\n\n\t( void ) setsockopt( netSocket, IPPROTO_TCP, TCP_QUICKACK,\n\t\t\t\t\t\t ( void * ) &trueValue, sizeof( int ) );\n\t}\n#else\n  #define disableSlowACK( netSocket )\n#endif /* TCP_QUICKACK */\n\n#ifdef __MQXRTOS__\n\n/* MQX uses nonstandard forms of accept(), bind(), and connect().  To deal \n   with the resulting compiler warnings we map the parameters to the \n   appropriate types */ \n\n#define bind( socket, address, address_len ) \\\n\t\tbind( socket, address, ( uint16_t ) address_len ) \n#define connect( socket, address, address_len ) \\\n\t\tconnect( socket, address, ( uint16_t ) address_len )\n\nstatic int my_accept( int socket, struct sockaddr *address,\n\t\t\t\t\t  int *address_len )\n\t{\n\tuint16_t length;\n\tint retVal;\n\n\t/* Pass the call down to the accept() function, mapping the length \n\t   parameter to the correct type */\n\tretVal = accept( socket, address, &length );\n\t*address_len = length;\n\n\treturn( retVal );\n\t}\n\n#define accept\t\tmy_accept\t/* Replace call to accept() with wrapper */\n\n/* MQX doesn't support SO_REUSEADDR so we provide a wrapper that maps it to\n   a no-op */\n\nstatic int32_t my_setsockopt( uint32_t socket, uint32_t level, \n\t\t\t\t\t\t\t  uint32_t option_name, \n\t\t\t\t\t\t\t  const void *option_value, \n\t\t\t\t\t\t\t  socklen_t option_len )\n\t{\n\t/* No-op out SO_REUSEADDR */\n\tif( option_name == SO_REUSEADDR )\n\t\treturn( RTCS_OK );\n\n\treturn( setsockopt( socket, level, option_name, option_value, \n\t\t\t\t\t\toption_len ) );\n\t}\n\n#define setsockopt\tmy_setsockopt\t/* Replace call to setsockopt() with wrapper */\n\n#endif /* __MQXRTOS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNetwork Socket Manager\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* cryptlib's separation kernel causes some problems with objects that use\n   sockets because it doesn't allow sharing of sockets, which is a problem \n   because the Unix server programming model assumes that a single process \n   will listen on a socket and fork off children to handle incoming \n   connections (in fact the accept() function more or less forces you to do\n   this whether you want to or not).\n   \n   A second problem occurs when a thread is blocked in an object waiting on \n   a socket because there's no way to unblock it apart from killing the \n   thread.  In theory we could create some sort of loopback socket and wait \n   for it alongside the listen socket in the pre-accept select wait, \n   signalling a shutdown by closing the loopback socket, but this starts to \n   get ugly.  In order to work around this we maintain a socket pool that \n   serves two functions:\n\n\t- Maintains a list of sockets that an object is listening on to allow a\n\t  listening socket to be reused rather than having to listen on a\n\t  socket and close it as soon as an incoming connection is made in\n\t  order to switch to the connected socket.\n\n\t- Allows sockets to be closed from another thread, which results in any\n\t  objects waiting on them being woken up and exiting.\n\n   For now we limit the socket pool to a maximum of SOCKETPOOL_SIZE sockets \n   both as a safety feature to protect against runaway use of sockets in the \n   calling application and because cryptlib was never designed to function \n   as a high-volume server application.  If necessary this can be changed to \n   dynamically expand the socket pool.  \n   \n   However it's not a good idea to simply remove the restriction entirely, \n   or set it to too high a value, because this can cause problems with \n   excess consumption of kernel resources.  For example under Windows \n   opening several tens of thousands of connections will eventually return \n   WSAENOBUFS when the nonpaged pool is exhausted.  At this point things \n   start to get problematic because many drivers don't handle the inability \n   to allocate memory very well, and can start to fail and render the whole \n   system unstable.  This is a general resource-consumption problem that \n   affects all users of the shared nonpaged pool, but we can at least make \n   sure that we're not the cause of any crashes by limiting our own \n   consumption */\n\nstatic const SOCKET_INFO SOCKET_INFO_TEMPLATE = \\\n\t\t\t\t{ INVALID_SOCKET, 0, 0, { 0 } };\n\n/* Initialise the socket pool */\n\nCHECK_RETVAL \\\nint initSocketPool( void )\n\t{\n\tSOCKET_INFO *socketInfo = getSocketPoolStorage();\n\tint i, LOOP_ITERATOR;\n\n\t/* Clear the socket pool */\n\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create/add and remove a socket to/from the pool.  The difference between\n   creating and adding a socket is that newSocket() creates and adds a\n   completely new socket while addSocket() adds an externally-created (via\n   accept()) socket */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int newSocket( OUT SOCKET *newSocketPtr, \n\t\t\t\t\t  const struct addrinfo *addrInfoPtr,\n\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tSOCKET_INFO *socketInfo = getSocketPoolStorage();\n\tSOCKET netSocket;\n\tBYTE addrHash[ ADDRHASH_SIZE + 8 ];\n\tint addrChecksum DUMMY_INIT, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( newSocketPtr, sizeof( SOCKET ) ) );\n\tassert( isReadPtr( addrInfoPtr, sizeof( struct addrinfo ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Clear return value */\n\t*newSocketPtr = INVALID_SOCKET;\n\n\t/* Perform any required pre-calculations before we acquire the mutex */\n\tif( isServer )\n\t\t{\n\t\tBYTE hashBuffer[ 16 + 8 ];\n\n\t\taddrChecksum = checksumData( addrInfoPtr->ai_addr, \n\t\t\t\t\t\t\t\t\t addrInfoPtr->ai_addrlen );\n\t\thashData( hashBuffer, 16, addrInfoPtr->ai_addr, \n\t\t\t\t\t\t\t\t  addrInfoPtr->ai_addrlen );\n\t\tmemcpy( addrHash, hashBuffer, ADDRHASH_SIZE );\n\t\t}\n\n\tstatus = krnlEnterMutex( MUTEX_SOCKETPOOL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If this is a server socket (i.e. one bound to a specific interface and\n\t   port), check to see whether there's already a socket bound here and if\n\t   there is, return the existing socket rather than creating a new one.\n\t   This check isn't currently totally foolproof since it compares some\n\t   nonessential fields that may differ for otherwise identical sockets\n\t   (it's difficult to do this in a clean manner because the comparison\n\t   becomes very protocol- and implementation-specific).  A workaround\n\t   would be to check whether the sin_family is AF_INET or AF_INET6 and\n\t   perform an appropriate situation-specific comparison, but this will\n\t   break the nice portability that was added by the RFC 2553 \n\t   reorganisation of socket functions for IPv6 */\n\tif( isServer )\n\t\t{\n\t\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\t\t{\n\t\t\tif( socketInfo[ i ].refCount > 0 && \\\n\t\t\t\tsocketInfo[ i ].addrChecksum == addrChecksum && \\\n\t\t\t\t!memcmp( socketInfo[ i ].addrHash, addrHash, ADDRHASH_SIZE ) )\n\t\t\t\t{\n\t\t\t\tif( socketInfo[ i ].refCount >= 10000 )\n\t\t\t\t\t{\n\t\t\t\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t\t\t\t\tDEBUG_DIAG(( \"Socket %d in socket pool has a reference \"\n\t\t\t\t\t\t\t\t \"count > 10,000\", i ));\n\t\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t\t\t}\n\t\t\t\tENSURES_KRNLMUTEX( socketInfo[ i ].refCount > 0 && \\\n\t\t\t\t\t\t\t\t   socketInfo[ i ].refCount < 10000, \n\t\t\t\t\t\t\t\t   MUTEX_SOCKETPOOL );\n\t\t\t\tENSURES_KRNLMUTEX( !isBadSocket( socketInfo[ i ].netSocket ), \n\t\t\t\t\t\t\t\t   MUTEX_SOCKETPOOL );\n\t\t\t\tsocketInfo[ i ].refCount++;\n\t\t\t\t*newSocketPtr = socketInfo[ i ].netSocket;\n\t\t\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\n\t\t\t\t/* The socket already exists, don't perform any further\n\t\t\t\t   initialisation with it */\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_SOCKETPOOL );\n\t\t}\n\n\t/* Create a new socket entry */\n\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\t{\n\t\t/* Check whether this is a zombie socket that we couldn't close\n\t\t   earlier, usually due to written data being left in the TCP/IP\n\t\t   stack.  As a result it's probably trapped in the TIME_WAIT\n\t\t   state, so we periodically try and close it to free up the\n\t\t   resource */\n\t\tif( socketInfo[ i ].refCount <= 0 && \\\n\t\t\t!isBadSocket( socketInfo[ i ].netSocket ) )\n\t\t\t{\n\t\t\tstatus = closesocket( socketInfo[ i ].netSocket );\n\t\t\tif( !isSocketError( status ) )\n\t\t\t\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\t\t\t}\n\n\t\tif( isBadSocket( socketInfo[ i ].netSocket ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_SOCKETPOOL );\n\tif( i >= SOCKETPOOL_SIZE )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t\tDEBUG_DIAG(( \"Tried to add more than %d sockets to socket pool\", \n\t\t\t\t\t SOCKETPOOL_SIZE ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tnetSocket = socket( addrInfoPtr->ai_family,\n\t\t\t\t\t\taddrInfoPtr->ai_socktype, 0 );\n\tif( isBadSocket( netSocket ) )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\tsocketInfo[ i ].netSocket = netSocket;\n\tsocketInfo[ i ].refCount = 1;\n\tif( isServer )\n\t\t{\n\t\t/* Remember the details for this socket so that we can detect another\n\t\t   attempt to bind to it */\n\t\tsocketInfo[ i ].addrChecksum = addrChecksum;\n\t\tmemcpy( socketInfo[ i ].addrHash, addrHash, ADDRHASH_SIZE );\n\t\t}\n\t*newSocketPtr = netSocket;\n\n\t/* If we're creating a new server socket we can't unlock the socket info\n\t   yet because we need to bind it to a port before we do anything else\n\t   with it.  If we were to unlock the socket info another thread could\n\t   perform an accept() on the incompletely set up socket, so we return\n\t   with the socket info still locked.  When the caller has finished\n\t   setting it up they call newSocketDone() to signal that the socket is \n\t   now really ready for use */\n\tif( isServer )\n\t\treturn( OK_SPECIAL );\n\n\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic void newSocketDone( void )\n\t{\n\t/* The caller has finished setting up a new server socket, unlock the\n\t   socket info to allow others to access it */\n\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t}\n\nCHECK_RETVAL \\\nstatic int addSocket( const SOCKET netSocket )\n\t{\n\tSOCKET_INFO *socketInfo = getSocketPoolStorage();\n\tint i, status, LOOP_ITERATOR;\n\n\tREQUIRES( !isBadSocket( netSocket ) );\n\n\tstatus = krnlEnterMutex( MUTEX_SOCKETPOOL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add an existing socket entry */\n\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\t{\n\t\tif( isBadSocket( socketInfo[ i ].netSocket ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_SOCKETPOOL );\n\tif( i >= SOCKETPOOL_SIZE )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t\tDEBUG_DIAG(( \"Tried to add more than %d sockets to socket pool\", \n\t\t\t\t\t SOCKETPOOL_SIZE ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\tsocketInfo[ i ].netSocket = netSocket;\n\tsocketInfo[ i ].refCount = 1;\n\n\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic void deleteSocket( const SOCKET netSocket )\n\t{\n\tSOCKET_INFO *socketInfo = getSocketPoolStorage();\n\tint i, status, LOOP_ITERATOR;\n\n\tREQUIRES_V( !isBadSocket( netSocket ) );\n\n\tstatus = krnlEnterMutex( MUTEX_SOCKETPOOL );\n\tif( cryptStatusError( status ) )\n\t\treturn;\n\n\t/* Find the entry for this socket in the pool.  There may not be one\n\t   present if the pool has received a shutdown signal and closed all\n\t   network sockets, so if we don't find it we just exit normally */\n\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\t{\n\t\tif( socketInfo[ i ].netSocket == netSocket )\n\t\t\tbreak;\n\t\t}\n\tENSURES_KRNLMUTEX_V( LOOP_BOUND_OK, MUTEX_SOCKETPOOL );\n\tif( i >= SOCKETPOOL_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Socket to delete not present in socket pool, exiting \"\n\t\t\t\t\t \"without further action\" ));\n\t\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t\treturn;\n\t\t}\n\tREQUIRES_KRNLMUTEX_V( socketInfo[ i ].refCount > 0, MUTEX_SOCKETPOOL );\n\n\t/* Decrement the socket's reference count */\n\tsocketInfo[ i ].refCount--;\n\tif( socketInfo[ i ].refCount <= 0 )\n\t\t{\n\t\t/* If the reference count has reached zero, close the socket\n\t\t   and delete the pool entry */\n\t\tstatus = closesocket( socketInfo[ i ].netSocket );\n\t\tif( isSocketError( status ) )\n\t\t\t{\n\t\t\t/* There was a problem closing the socket, mark it as not-\n\t\t\t   present for matching purposes but keep its entry active so\n\t\t\t   that we'll periodically try and close it when we search the\n\t\t\t   socket pool for these slots, and again when we close down */\n\t\t\tsocketInfo[ i ].addrChecksum = 0;\n\t\t\tmemset( socketInfo[ i ].addrHash, 0, ADDRHASH_SIZE );\n\n\t\t\tDEBUG_DIAG(( \"Couldn't close socket pool socket %d\", i ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\t}\n\t\telse\n\t\t\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\t\t}\n\n\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t}\n\n/* Force all objects waiting on sockets to exit by closing their sockets.\n   This is the only portable and reliable way to cause them to terminate \n   since an object waiting on a socket is marked as busy by the cryptlib \n   kernel, and in fact will be blocked inside the OS out of reach of even \n   the cryptlib kernel.  Alternatively, the user can provide their own \n   socket externally and close it from the outside, which will unblock the \n   thread waiting on it.\n\n   A somewhat less drastic alternative to closing the socket is to use\n   shutdown(), but the behaviour of this is somewhat implementation-specific.\n   For example under Slowaris 5.x trying to shutdown a listening socket (to\n   unlock a thread blocking in accept()) returns ENOTCONN from the shutdown()\n   call rather than shutting down the socket, so an actual shutdown requires \n   setting up a dummy connection to the socket to be shut down before it can \n   be shut down.  Trying to shut down a thread blocked in connect() is more \n   or less impossible under Slowaris 5.x.  Other systems are more flexible, \n   but there's not enough consistency to rely on this */\n\nvoid netSignalShutdown( void )\n\t{\n\tSOCKET_INFO *socketInfo = getSocketPoolStorage();\n\tint i, status, LOOP_ITERATOR;\n\n\t/* Exactly what to do if we can't acquire the mutex is a bit complicated\n\t   because at this point our primary goal is to force all objects to exit \n\t   rather than worrying about socket-pool consistency.  On the other\n\t   hand if another object is currently in the middle of cleaning up and\n\t   is holding the socket pool mutex then we don't want to stomp on it \n\t   while it's doing its cleanup.  Since failing to acquire the mutex is \n\t   a special-case exception condition, it's not even possible to plan for\n\t   this since it's uncertain under which conditions (if ever) this \n\t   situation would occur.  For now we play it safe and don't do anything \n\t   if we can't acquire the mutex, which is at least consistent */\n\tstatus = krnlEnterMutex( MUTEX_SOCKETPOOL );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Void();\n\n\t/* For each open socket, close it and clear its pool entry */\n\tLOOP_LARGE( i = 0, i < SOCKETPOOL_SIZE, i++ )\n\t\t{\n\t\tif( !isBadSocket( socketInfo[ i ].netSocket ) )\n\t\t\t{\n\t\t\tclosesocket( socketInfo[ i ].netSocket );\n\t\t\tsocketInfo[ i ] = SOCKET_INFO_TEMPLATE;\n\t\t\t}\n\t\t}\n\tENSURES_KRNLMUTEX_V( LOOP_BOUND_OK, MUTEX_SOCKETPOOL );\n\n\tkrnlExitMutex( MUTEX_SOCKETPOOL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOpen a Client Socket\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open a connection to a remote server.  The connection-open function \n   performs that most amazing of all things, the nonblocking connect.  This \n   is currently done in order to allow a shorter timeout than the default \n   fortnight or so but it also allows for two-phase connects in which we \n   start the connect operation, perform further processing (e.g. signing and \n   encrypting data prior to sending it over the connected socket) and then \n   complete the connect before the first read or write.  \n   \n   Currently we just use a wrapper that performs the two back-to-back as a \n   single operation, so for now it only functions as a timeout-management \n   mechanism - the high-level API for this would be a bit difficult to \n   handle since there's no readily-available facility for handling an \n   interruptible sNetConnect(), the best option would be to handle it via a \n   complete-connect IOCTL.  However since we've got at least a little time \n   to play with in most cases we could perhaps perform a quick entropy poll \n   in the idle interval, if nothing else */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int preOpenSocket( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t  IN_BUFFER( hostNameLen ) const char *host, \n\t\t\t\t\t\t  IN_LENGTH_DNS const int hostNameLen,\n\t\t\t\t\t\t  IN_PORT const int port )\n\t{\n\tSOCKET netSocket DUMMY_INIT;\n\tstruct addrinfo *addrInfoPtr, *addrInfoCursor;\n\tconst BOOLEAN isDgramSocket = \\\n\t\t\tTEST_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM ) ? TRUE : FALSE;\n\tBOOLEAN nonBlockWarning = FALSE;\n\tint addressCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( host, hostNameLen ) );\n\t\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( hostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE );\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\n\t/* Clear return value */\n\tnetStream->netSocket = INVALID_SOCKET;\n\n\t/* Set up addressing information */\n\tstatus = getAddressInfo( netStream, &addrInfoPtr, host, hostNameLen, port, \n\t\t\t\t\t\t\t FALSE, isDgramSocket );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( addrInfoPtr != NULL );\n\n\t/* Create a socket, make it nonblocking, and start the connect to the\n\t   remote server, falling back through alternative addresses if the\n\t   connect fails.  Since this is a nonblocking connect it could still\n\t   fail during the second phase where we can no longer try to recover\n\t   by falling back to an alternative address, but it's better than just\n\t   giving up after the first address that we try.\n\t   \n\t   Unfortunately, the fail-on-first-address behaviour is actually what \n\t   happens in some cases under Vista/Win7 which, like most other IPv6-\n\t   enabled systems preferentially tries to provide an IPv6 address for \n\t   \"localhost\" (see the long comment in openServerSocket()) and allows a \n\t   connect() to the IPv6 address, but then returns a WSAETIMEDOUT if the \n\t   target application is only listening on an IPv4 address.  The code in\n\t   openServerSocket() has a workaround for this, unwinding the fantasy-\n\t   world IPv6-by-default back to the real-world IPv4-by-default */\n\tLOOP_SMALL( ( addrInfoCursor = addrInfoPtr, addressCount = 0 ),\n\t\t\t\taddrInfoCursor != NULL && addressCount < IP_ADDR_COUNT,\n\t\t\t\t( addrInfoCursor = addrInfoCursor->ai_next, addressCount++ ) )\n\t\t{\n\t\t/* If it's not an IPv4 or IPv6 address, continue */\n\t\tif( !allowedAddressFamily( addrInfoCursor->ai_family ) )\n\t\t\tcontinue;\n\n\t\t/* Create a socket and start the connect process */\n\t\tstatus = newSocket( &netSocket, addrInfoCursor, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\t\tsetSocketNonblocking( netSocket );\n\t\tclearErrorState();\n\t\tstatus = connect( netSocket, addrInfoCursor->ai_addr,\n\t\t\t\t\t\t  addrInfoCursor->ai_addrlen );\n\t\tnonBlockWarning = isNonblockWarning( netSocket );\n\t\tif( status >= 0 || nonBlockWarning )\n\t\t\t{\n\t\t\t/* We've got a successfully-started connect, exit */\n\t\t\tbreak;\n\t\t\t}\n\t\tdeleteSocket( netSocket );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( addressCount >= IP_ADDR_COUNT )\n\t\t{\n\t\t/* We went through a suspiciously large number of remote server \n\t\t   addresses without being able to even initiate a connect attempt \n\t\t   to any of them, there's something wrong */\n\t\tDEBUG_DIAG(( \"Iterated through %d server addresses without being \"\n\t\t\t\t\t \"able to connect\", addressCount ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( mapNetworkError( netStream, 0, FALSE, CRYPT_ERROR_OPEN ) );\n\t\t}\n\tfreeAddressInfo( addrInfoPtr );\n\tif( status < 0 && !nonBlockWarning )\n\t\t{\n\t\t/* There was an error condition other than a notification that the\n\t\t   operation hasn't completed yet */\n\t\treturn( mapNetworkError( netStream, getErrorCode( INVALID_SOCKET ), \n\t\t\t\t\t\t\t\t FALSE, CRYPT_ERROR_OPEN ) );\n\t\t}\n\tif( status == 0 )\n\t\t{\n\t\t/* If we're connecting to a local host the connect can complete\n\t\t   immediately rather than returning an in-progress status, in\n\t\t   which case we don't need to do anything else */\n\t\tnetStream->netSocket = netSocket;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The connect is in progress, mark the stream as not-quite-ready for \n\t   use */\n/*\tnetStream->xxx = yyy; */\n\tnetStream->netSocket = netSocket;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completeOpen( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tSTM_TRANSPORTDISCONNECT_FUNCTION transportDisconnectFunction;\n\tSIZE_TYPE intLength = sizeof( int );\n\tint value, status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\n\ttransportDisconnectFunction = ( STM_TRANSPORTDISCONNECT_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( netStream->transportDisconnectFunction );\n\tREQUIRES( transportDisconnectFunction != NULL );\n\n\t/* Wait around until the connect completes.  Some select()s limit the\n\t   size of the second count so we set it to a maximum of about a week,\n\t   although why anyone would wait around that long (and whether any\n\t   network stack would even maintain a SYN_SENT for that amount of time)\n\t   is unclear.\n\t   \n\t   BeOS doesn't allow setting a timeout (that is, it doesn't allow\n\t   asynchronous connects), but it hardcodes in a timeout of about a\n\t   minute so we get a vaguely similar effect */\n\tstatus = ioWait( netStream, min( netStream->timeout, 500000L ), FALSE,\n\t\t\t\t\t IOWAIT_CONNECT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\ttransportDisconnectFunction( netStream, TRUE );\n\t\treturn( status );\n\t\t}\n\n\t/* The socket is readable or writeable, however this may be because of \n\t   an error (it's readable and writeable) or because everything's OK \n\t   (it's writeable) or because everything's OK and there's data waiting \n\t   (it's readable and writeable again), so we have to see what the error \n\t   condition is for the socket to determine what's really happening.\n\n\t   How to best determine all of these conditions is a bit tricky.  Other \n\t   possibilities include calling recv() with a length of zero bytes \n\t   (returns an error if the connect failed), calling connect() again \n\t   (fails with EISCONN if the connect succeeded), and calling \n\t   getmsg( netSocket, NULL, NULL, &( flags = 0 ) ) (fails with \n\t   errno == EAGAIN or EWOULDBLOCK if the only error is that there's \n\t   nothing available yet), but these are somewhat implementation-\n\t   specific and not consistent across different platforms */\n\tstatus = getsockopt( netStream->netSocket, SOL_SOCKET, SO_ERROR,\n\t\t\t\t\t\t ( void * ) &value, &intLength );\n\tif( status == 0 )\n\t\t{\n\t\t/* Berkeley-derived implementation, error is in the value variable */\n\t\tif( value != 0 )\n\t\t\t{\n\t\t\tstatus = mapNetworkError( netStream, value, FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_OPEN );\n\t\t\ttransportDisconnectFunction( netStream, TRUE );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Slowaris, error is in errno */\n\t\tif( isSocketError( status ) )\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\tstatus = getSocketError( netStream, CRYPT_ERROR_OPEN, &dummy );\n\t\t\ttransportDisconnectFunction( netStream, TRUE );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Turn off Nagle if it's a TCP socket (since we do our own optimised \n\t   TCP handling) and make the socket blocking again.  This is necessary \n\t   because with a nonblocking socket Winsock will occasionally return 0 \n\t   bytes from recv() (a sign that the other side has closed the \n\t   connection, see the comment in readSocketFunction()) even though the \n\t   connection is still fully open, and in any case there's no real need \n\t   for a nonblocking socket since we have select() handling timeouts/\n\t   blocking for us.\n\t   \n\t   In theory these calls can fail, but there's not much that we can do \n\t   about it, and in any case things will usually keep working anyway, so\n\t   we don't try and handle any errors for this situation */\n\tif( !TEST_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM ) )\n\t\tdisableNagle( netStream->netSocket );\n\tsetSocketBlocking( netStream->netSocket );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOpen a Server Socket\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wait for a connection from a remote client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int openServerSocket( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t IN_BUFFER_OPT( hostNameLen ) const char *host, \n\t\t\t\t\t\t\t IN_LENGTH_DNS_Z const int hostNameLen,\n\t\t\t\t\t\t\t IN_PORT const int port )\n\t{\n\tSOCKET listenSocket DUMMY_INIT, netSocket;\n\tSOCKADDR_STORAGE clientAddr;\n\tstruct addrinfo *addrInfoPtr, *addrInfoCursor;\n\tstatic const int trueValue = 1;\n\tstatic const int falseValue = 0;\n\tconst BOOLEAN isDgramSocket = \\\n\t\t\tTEST_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM ) ? TRUE : FALSE;\n\tSIZE_TYPE clientAddrLen = sizeof( SOCKADDR_STORAGE );\n\tchar hostNameBuffer[ MAX_DNS_SIZE + 1 + 8 ];\n\tint addressCount, errorCode = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( ( host == NULL && hostNameLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( host, hostNameLen ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( ( host == NULL && hostNameLen == 0 ) || \\\n\t\t\t  ( host != NULL && \\\n\t\t\t\thostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE ) );\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\n\t/* Clear return value */\n\tnetStream->netSocket = INVALID_SOCKET;\n\n\t/* Convert the host name into the null-terminated string required by the \n\t   sockets API if necessary */\n\tif( host != NULL )\n\t\t{\n\t\tREQUIRES( rangeCheck( hostNameLen, 1, MAX_DNS_SIZE ) );\n\t\tmemcpy( hostNameBuffer, host, hostNameLen );\n\t\thostNameBuffer[ hostNameLen ] = '\\0';\n\t\thost = hostNameBuffer;\n\t\t}\n\n\t/* Set up addressing information.  If we're not binding to a specified \n\t   interface we allow connections on any interface.  Note that in \n\t   combination with SO_REUSEADDR and old unpatched Unix kernels this \n\t   allows port hijacking by another process running on the same machine \n\t   that binds to the port with a more specific binding than \"any\".  It\n\t   also allows port hijacking under Windows, where the situation is a \n\t   bit more complex.  Actually it's representative of the problem of the\n\t   port-binding situation in general so it's informative to walk through \n\t   the issue.  \n\t   \n\t   Windows provides a socket option SO_EXCLUSIVEADDRUSE that can be used \n\t   to exclude re-binding to a socket.  Unfortunately what this means is\n\t   that if this option is set for a socket then the port can't be re-\n\t   used right after the socket is closed but only after the connection \n\t   is no longer active, where \"active\" means that it's not only not in \n\t   the ESTABLISHED state but also not in the FIN, FIN_WAIT, FIN_WAIT_2, \n\t   or LAST_ACK state.  However the ability to re-bind to the port at \n\t   this point is exactly what SO_REUSEADDR is supposed to allow.  In \n\t   other words use of SO_EXCLUSIVEADDRUSE is a bit like not setting \n\t   SO_REUSEADDR, with a few technical differences based on how \n\t   SO_EXCLUSIVEADDRUSE works that aren't important here.  \n\t   \n\t   So now we have to not only close the socket but wait for the system \n\t   to send all buffered data, hang around for data acks, send a \n\t   disconnect to the remote system, and wait to get a disconnect back.  \n\t   If the remote system (or a MITM) advertises a zero-length window or \n\t   something similar then the connection can remain \"active\" (in the \n\t   sense of preventing a re-bind, although not necessarily doing \n\t   anything) more or less indefinitely.\n\n\t   This is a nasty situation because while SO_EXCLUSIVEADDRUSE can\n\t   prevent local socket-hijacking attacks it opens us up to remote\n\t   network-based DoS attacks.  In theory if we have complete control\n\t   of the application we can use a background thread to wait in a recv()\n\t   loop until all data is read after performing a shutdown( SD_SEND ) \n\t   and if necessary alert the user that something funny is going on, but \n\t   since we're a library (and sometimes running as a UI-less service) we \n\t   can't really do this.\n\n\t   Given the choice between allowing a local session-hijack or a remote \n\t   DoS, we opt for the session hijack.  Since we're using secured\n\t   protocols over the socket this isn't nearly as serious as (say) a \n\t   socket being used for straight HTTP */\n\tstatus = getAddressInfo( netStream, &addrInfoPtr, host, hostNameLen, \n\t\t\t\t\t\t\t port, TRUE, isDgramSocket );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( addrInfoPtr != NULL );\n\n\t/* Create a new server socket, falling back through alternative \n\t   interfaces if the initial socket creation fails.  This may seem less \n\t   necessary than for the client-side connect but is required because \n\t   getaddrinfo() usually preferentially provides an IPv6 interface even \n\t   if there's no IPv6 configured for the system (see the long comment in \n\t   getAddressInfo() for more on this), so we have to step through until \n\t   we get to an IPv4 interface, or at least one that we can listen on.  \n\t   Qui habet aures audiendi audiat (the speaker appears to be speaking \n\t   metaphorically with 'ears' referring to 'network sockets', latin \n\t   having no native term for the latter) */\n\tLOOP_SMALL( ( addrInfoCursor = addrInfoPtr, addressCount = 0 ), \n\t\t\t\taddrInfoCursor != NULL && addressCount < IP_ADDR_COUNT,\n\t\t\t\t( addrInfoCursor = addrInfoCursor->ai_next, addressCount++ ) )\n\t\t{\n#ifdef USE_IPv6\n\t\tSIZE_TYPE valueLen = sizeof( int );\n\t\tint value;\n#endif /* USE_IPv6 */\n\n\t\t/* If it's not an IPv4 or IPv6 address, continue */\n\t\tif( !allowedAddressFamily( addrInfoCursor->ai_family ) )\n\t\t\tcontinue;\n\n\t\tstatus = newSocket( &listenSocket, addrInfoCursor, TRUE );\n\t\tif( status == CRYPT_OK )\n\t\t\t{\n\t\t\t/* It's a second thread listening on an existing socket,\n\t\t\t   we're done */\n\t\t\tbreak;\n\t\t\t}\n\t\tif( status != OK_SPECIAL )\n\t\t\t{\n\t\t\t/* There was a problem creating the socket, try again with \n\t\t\t   another interface */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* At this point we still have the socket pool locked while we \n\t\t   complete initialisation so we need to call newSocketDone()\n\t\t   before we break out of the loop at any point */\n\n\t\t/* Now we run into some problems with IPv4/IPv6 dual stacks, see \n\t\t   the long comment about this in io/dns.c.  In brief what happens \n\t\t   is that if there's a choice between using IPv4 or IPv6, most \n\t\t   systems will use IPv6 first.  This is typically encountered \n\t\t   through the first entry in the addrInfo list being an IPv6 \n\t\t   interface and the second one being an IPv4 interface, which means \n\t\t   that the default first match will be to an IPv6 interface and not \n\t\t   an IPv4 one.  There's an option to listen on both IPv6 and IPv4 \n\t\t   interfaces, but whether this is enabled is system-dependent, most \n\t\t   Unix systems enable it but Windows disables it.\n\n\t\t   In order for things to work as expected we check for the use of \n\t\t   IPv6 and, if that's being used, check whether the dual-stack \n\t\t   option is enabled.  This is indicated by having the IPV6_V6ONLY \n\t\t   socket option set to FALSE, if it's not enabled (so IPV6_V6ONLY \n\t\t   is set to TRUE, disabling IPv4) then we explicitly enable it for \n\t\t   the socket */\n#ifdef USE_IPv6\n\t\tif( addrInfoCursor->ai_family == AF_INET6 && \\\n\t\t\tgetsockopt( listenSocket, IPPROTO_IPV6, IPV6_V6ONLY,\n\t\t\t\t\t\t( char * ) &value, &valueLen ) == 0 && value == 1 )\n\t\t\t{\n\t\t\tsetsockopt( listenSocket, IPPROTO_IPV6, IPV6_V6ONLY,\n\t\t\t\t\t\t( char * ) &falseValue, sizeof( int ) );\n\t\t\t}\n#endif /* USE_IPv6 */\n\n\t\t/* This is a new socket, set SO_REUSEADDR to avoid TIME_WAIT \n\t\t   problems and prepare to accept connections (nemo surdior est \n\t\t   quam is qui non audiet).  Note that BeOS can only bind to one \n\t\t   interface at a time, so if we're binding to INADDR_ANY under \n\t\t   BeOS we actually bind to the first interface that we find */\n\t\tif( setsockopt( listenSocket, SOL_SOCKET, SO_REUSEADDR,\n\t\t\t\t\t\t( char * ) &trueValue, sizeof( int ) ) || \\\n\t\t\tbind( listenSocket, addrInfoCursor->ai_addr,\n\t\t\t\t  addrInfoCursor->ai_addrlen ) || \\\n\t\t\tlisten( listenSocket, 5 ) )\n\t\t\t{\n\t\t\t/* Remember the error code now in case there's a later error\n\t\t\t   in the cleanup functions that overwrites it */\n\t\t\terrorCode = getErrorCode( listenSocket );\n\n\t\t\t/* Clean up so that we can try again, making sure that we have \n\t\t\t   an appropriate error status set when we continue in case this \n\t\t\t   was our last iteration through the loop */\n\t\t\tdeleteSocket( listenSocket );\n\t\t\tnewSocketDone();\n\t\t\tstatus = CRYPT_ERROR_OPEN;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* We've finished initialising the socket, tell the socket pool\n\t\t   manager that it's safe to let others access the pool */\n\t\tnewSocketDone();\n\t\tstatus = CRYPT_OK;\n\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tfreeAddressInfo( addrInfoPtr );\n\tif( addressCount >= IP_ADDR_COUNT )\n\t\t{\n\t\t/* We went through a suspiciously large number of server addresses \n\t\t   without being able to even initiate a listen attempt on any of \n\t\t   them, there's something wrong */\n\t\tDEBUG_DIAG(( \"Iterated through %d server addresses without being \"\n\t\t\t\t\t \"able to listen\", addressCount ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( mapNetworkError( netStream, 0, FALSE, CRYPT_ERROR_OPEN ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was an error setting up the socket, don't try anything\n\t\t   further */\n\t\treturn( mapNetworkError( netStream, \n\t\t\t\t\t\t\t\t ( errorCode == 0 ) ? \\\n\t\t\t\t\t\t\t\t\t\tgetErrorCode( INVALID_SOCKET ) : \\\n\t\t\t\t\t\t\t\t\t\terrorCode, \n\t\t\t\t\t\t\t\t FALSE, CRYPT_ERROR_OPEN ) );\n\t\t}\n\n\t/* Wait for a connection.  At the moment this always waits forever\n\t   (actually some select()s limit the size of the second count so we\n\t   set it to a maximum of 1 year's worth), but in the future we could\n\t   have a separate timeout value for accepting incoming connections to\n\t   mirror the connection-wait timeout for outgoing connections.\n\n\t   Because of the way that accept works, the socket that we eventually\n\t   and up with isn't the one that we listen on, but we have to\n\t   temporarily make it the one associated with the stream in order for\n\t   ioWait() to work */\n\tnetStream->netSocket = listenSocket;\n\tstatus = ioWait( netStream, min( netStream->timeout, 30000000L ), FALSE,\n\t\t\t\t\t IOWAIT_ACCEPT );\n\tnetStream->netSocket = INVALID_SOCKET;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We have an incoming connection ready to go, accept it.  There's a\n\t   potential complication here in that if a client connects and then\n\t   immediately sends a RST after the TCP handshake has completed,\n\t   ioWait() will return with an indication that there's an incoming\n\t   connection ready to go but the following accept(), if it's called\n\t   after the RST has arrived, will block waiting for the next incoming\n\t   connection.  This is rather unlikely in practice, but could occur\n\t   as part of a DoS by setting the SO_LINGER time to 0 and disconnecting\n\t   immediately.  This has the effect of turning the accept() with\n\t   timeout into an indefinite-wait accept().\n\n\t   To get around this we make the socket temporarily non-blocking, so\n\t   that accept() returns an error if the client has closed the\n\t   connection.  The exact error varies, BSD implementations handle the\n\t   error internally and return to the accept() while SVR4\n\t   implementations return either EPROTO (older, pre-Posix behaviour) or\n\t   ECONNABORTED (newer Posix-compliant behaviour, since EPROTO is also\n\t   used for other protocol-related errors).\n\n\t   Since BSD implementations hide the problem they wouldn't normally\n\t   return an error, however by temporarily making the socket non-\n\t   blocking we force it to return an EWOULDBLOCK if this situation\n\t   occurs.  Since this could lead to a misleading returned error, we\n\t   intercept it and substitute a custom error string.  Note that when\n\t   we make the listen socket blocking again, we also have to make the\n\t   newly-created ephemeral socket blocking, since it inherits its\n\t   attributes from the listen socket.\n\t   \n\t   In addition to all of the blocking/nonblocking shenanigans, we also \n\t   need to disable Nagle on the accepted socket.  This may or may not\n\t   be necessary depending on the sockets implementation, we always\n\t   explicitly set it to be on the safe side */\n\tsetSocketNonblocking( listenSocket );\n\tclearErrorState();\n\tnetSocket = accept( listenSocket, ( struct sockaddr * ) &clientAddr,\n\t\t\t\t\t\t&clientAddrLen );\n\tif( isBadSocket( netSocket ) )\n\t\t{\n\t\tif( isNonblockWarning( listenSocket ) )\n\t\t\t{\n\t\t\tstatus = setSocketError( netStream, \n\t\t\t\t\t\t\t\t\t \"Remote system closed the connection \"\n\t\t\t\t\t\t\t\t\t \"after completing the TCP handshake\", \n\t\t\t\t\t\t\t\t\t 70, CRYPT_ERROR_OPEN, TRUE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\tstatus = getSocketError( netStream, CRYPT_ERROR_OPEN, &dummy );\n\t\t\t}\n\t\tsetSocketBlocking( listenSocket );\n\t\tdeleteSocket( listenSocket );\n\t\treturn( status );\n\t\t}\n\tsetSocketBlocking( listenSocket );\n\tsetSocketBlocking( netSocket );\n\n\t/* Get the IP address of the connected client.  We could get its full\n\t   name, but this can slow down connections because of the time that it\n\t   takes to do the lookup and is less authoritative because of potential\n\t   spoofing.  In any case the caller can still look up the name if they\n\t   need it.  Since we don't want to abort an entire network connect just \n\t   because we can't return the peer's IP address, do don't do anything\n\t   with the return value of this function */\n\t( void ) getNameInfo( ( const struct sockaddr * ) &clientAddr, \n\t\t\t\t\t\t  clientAddrLen, netStream->clientAddress, \n\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE / 2, \n\t\t\t\t\t\t  &netStream->clientAddressLen, \n\t\t\t\t\t\t  &netStream->clientPort );\n\n\t/* Turn off Nagle, since we do our own optimised TCP handling.  In \n\t   theory this call can fail, but there's not much that we can do about \n\t   it, and in any case things will usually keep working anyway, so we \n\t   don't try and handle any errors for this situation */\n\tdisableNagle( netSocket );\n\n\t/* We've got a new connection, add the socket to the pool.  Since this\n\t   was created externally to the pool we don't use newSocket() to create \n\t   a new socket but only add the existing socket */\n\tstatus = addSocket( netSocket );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem adding the new socket, close it and exit.\n\t\t   We don't call deleteSocket() since it wasn't added to the pool,\n\t\t   instead we call closesocket() directly */\n\t\tclosesocket( netSocket );\n\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\"Couldn't add socket to socket pool\", 34,\n\t\t\t\t\t\t\t\tstatus, FALSE ) );\n\t\t}\n\tnetStream->netSocket = netSocket;\n\tnetStream->listenSocket = listenSocket;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOpen/Close Sockets\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open/close a network socket */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int openSocketFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t   IN_BUFFER_OPT( hostNameLen) const char *hostName, \n\t\t\t\t\t\t\t   IN_LENGTH_DNS_Z const int hostNameLen, \n\t\t\t\t\t\t\t   IN_PORT const int port )\n\t{\n\tint status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( ( hostName == NULL && hostNameLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( hostName, hostNameLen ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( ( hostName == NULL && hostNameLen == 0 ) || \\\n\t\t\t  ( hostName != NULL && \\\n\t\t\t\thostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE ) );\n\tREQUIRES( port >= MIN_PORT_NUMBER && port < MAX_PORT_NUMBER );\n\tREQUIRES( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) || \\\n\t\t\t  hostName != NULL );\n\n\t/* If it's a server stream, open a listening socket */\n\tif( TEST_FLAG( netStream->nFlags, STREAM_NFLAG_ISSERVER ) )\n\t\t{\n\t\tconst int savedTimeout = netStream->timeout;\n\n\t\t/* Timeouts for server sockets are actually three-level rather than\n\t\t   the usual two-level model, there's an initial (pre-connect)\n\t\t   timeout while we wait for an incoming connection to arrive, and\n\t\t   then we go to the usual session connect vs. session read/write\n\t\t   timeout mechanism.  To handle the pre-connect phase we set an\n\t\t   (effectively infinite) timeout at this point to ensure that the\n\t\t   server always waits forever for an incoming connection to\n\t\t   appear */\n\t\tnetStream->timeout = MAX_INTLENGTH;\n\t\tstatus = openServerSocket( netStream, hostName, hostNameLen, port );\n\t\tnetStream->timeout = savedTimeout;\n\t\treturn( status );\n\t\t}\n\n\tENSURES( hostName != NULL && \\\n\t\t\t ( hostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE ) );\n\n\t/* It's a client stream, perform a two-part nonblocking open.  Currently\n\t   the two portions are performed back-to-back, in the future we can\n\t   interleave the two and perform general crypto processing like hash/\n\t   MAC context setup for SSL or SSH while the open is completing */\n\tstatus = preOpenSocket( netStream, hostName, hostNameLen, port );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeOpen( netStream );\n\tENSURES( ( cryptStatusError( status ) && \\\n\t\t\t   netStream->netSocket == INVALID_SOCKET ) || \\\n\t\t\t ( cryptStatusOK( status ) && \\\n\t\t\t   netStream->netSocket != INVALID_SOCKET ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem opening the socket, see if we can return \n\t\t   something a bit better than the often rather generic socket-\n\t\t   connect error code */\n\t\treturn( diagnoseConnectionProblem( netStream, hostName, \n\t\t\t\t\t\t\t\t\t\t   hostNameLen, status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Close a connection.  Safely handling closes is extremely difficult due to \n   a combination of the way TCP/IP (and TCP stacks) work and various bugs \n   and quirks in implementations.  After a close (and particularly if short-\n   timeout non-blocking writes are used) there can still be data left in \n   TCP send buffers, and also as unacknowledged segments on the network.  At \n   this point there's no easy way for the TCP stack to know how long it \n   should hang around trying to get the data out and wait for ACKs to come \n   back.  If it doesn't wait long enough, it'll end up discarding unsent \n   data.  If it waits too long, it could potentially wait forever in the \n   presence of network outages or crashed peers.  What's worse, since the \n   socket is now closed, there's no way to report any problems that may \n   occur at this point back to the caller.\n\n   We try and handle this with a combination of shutdown() and close(), but \n   due to implementation bugs/quirks and the TCP stack issues mentioned \n   above this doesn't work all of the time.  The details get very \n   implementation-specific, for example with glibc the manpage says that \n   setting SO_LINGER causes shutdown() not to return until queued messages \n   are sent (which is wrong, and non-glibc implementations like PHUX and \n   Solaris specifically point out that only close() is affected), but that \n   shutdown() discards unsent data.  glibc in turn is dependent on the \n   kernel it's running on top of, under Linux shutdown() returns immediately \n   but data is still sent regardless of the SO_LINGER setting.\n\n   BSD Net/2 and later (which many stacks are derived from, including non-\n   Unix systems like OS/2) returned immediately from a close() but still \n   sent queued data on a best-effort basis.  With SO_LINGER set and a zero \n   timeout the close was abortive (which Linux also implemented starting \n   with the 2.4 kernel), and with a non-zero timeout it would wait until all \n   the data was sent, which meant that it could block almost indefinitely \n   (minutes or even hours, this is the worst-case behaviour mentioned \n   above).  This was finally fixed in 4.4BSD (although a lot of 4.3BSD-\n   derived stacks ended up with the indefinite-wait behaviour), but even \n   then there was some confusion as to whether the wait time was in machine-\n   specific ticks or seconds (Posix finally declared it to be seconds).  \n   Under Winsock, close() simply discards queued data while shutdown() has \n   the same effect as under Linux, sending enqueued data asynchronously \n   regardless of the SO_LINGER setting.\n\n   This is a real mess to sort out safely, the best that we can do is to \n   perform a shutdown() followed later by a close().  Messing with SO_LINGER \n   is too risky and something like performing an ioWait() doesn't work \n   either because it just results in whoever initiated the shutdown being \n   blocked for the I/O wait time, and waiting for a recv() of 0 bytes isn't \n   safe because the higher-level code may need to read back a shutdown ack \n   from the other side which a recv() performed at this point would \n   interfere with.  Under Windows we could handle it by waiting for an \n   FD_CLOSE to be posted but this requires the use of a window handle which \n   we don't have access to, and which may not even exist for some classes of\n   applications */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void closeSocketFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\t const BOOLEAN fullDisconnect )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckNetStream( netStream ) );\n\tREQUIRES_V( fullDisconnect == TRUE || fullDisconnect == FALSE );\n\n\t/* If it's a partial disconnect, close only the send side of the channel.\n\t   The send-side close can help with ensuring that all data queued for\n\t   transmission is sent */\n\tif( !fullDisconnect )\n\t\t{\n\t\tif( netStream->netSocket != INVALID_SOCKET )\n\t\t\tshutdown( netStream->netSocket, SHUT_WR );\n\t\treturn;\n\t\t}\n\n\t/* If it's an open-on-demand HTTP stream then the socket isn't\n\t   necessarily open even if the stream was successfully connected so we \n\t   only close it if necessary.  It's easier handling it at this level\n\t   than expecting the caller to distinguish between an opened-stream-but-\n\t   not-opened-socket and a conventional open stream */\n\tif( netStream->netSocket != INVALID_SOCKET )\n\t\tdeleteSocket( netStream->netSocket );\n\tif( netStream->listenSocket != INVALID_SOCKET )\n\t\tdeleteSocket( netStream->listenSocket );\n\tnetStream->netSocket = netStream->listenSocket = INVALID_SOCKET;\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCPConnect( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( netStream->transportConnectFunction, openSocketFunction );\n\tFNPTR_SET( netStream->transportDisconnectFunction, closeSocketFunction );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/tcp_err.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib TCP/IP Error Handling Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tError Messages\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_ERRMSGS \n\n/* Map of common error codes to strings.  \n\n   The error code supplied by the caller is usually used as the return \n   status code (in which case cryptSpecificCode is set to CRYPT_OK), however \n   if a more specific error code than the default is available then it's \n   specified via the cryptSpecificCode field */\n\ntypedef struct {\n\tconst int errorCode;\t\t/* Native error code */\n\tconst int cryptSpecificCode;/* Specific cryptlib error code */\n\tconst BOOLEAN isFatal;\t\t/* Seriousness level */\n\tBUFFER_FIXED( errorStringLength ) \\\n\tconst char *errorString;\n\tconst int errorStringLength;/* Error message */\n\t} SOCKETERROR_INFO;\n\n#if defined( __WINDOWS__ )\n\nstatic const SOCKETERROR_INFO socketErrorInfo[] = {\n\t{ WSAECONNREFUSED, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"WSAECONNREFUSED: The attempt to connect was rejected\", 52 },\n\t{ WSAEADDRNOTAVAIL, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"WSAEADDRNOTAVAIL: The remote address is not a valid address\", 59 },\n\t{ WSAECONNABORTED, CRYPT_OK, TRUE,\n\t\t\"WSAECONNABORTED: Connection was terminated due to a time-out or \"\n\t\t\"other failure\", 77 },\n\t{ WSAECONNRESET, CRYPT_OK, TRUE,\n\t\t\"WSAECONNRESET: Connection was reset by the remote host executing \"\n\t\t\"a close\", 72 },\n\t{ WSAEHOSTUNREACH, CRYPT_OK, TRUE,\n\t\t\"WSAEHOSTUNREACH: Remote host cannot be reached from this host at \"\n\t\t\"this time\", 74 },\n\t{ WSAEMSGSIZE, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"WSAEMSGSIZE: Message is larger than the maximum supported by the \"\n\t\t\"underlying transport\", 85 },\n\t{ WSAENETDOWN, CRYPT_OK, FALSE,\n\t\t\"WSAENETDOWN: The network subsystem has failed\", 45 },\n\t{ WSAENETRESET, CRYPT_OK, FALSE,\n\t\t\"WSAENETRESET: Connection was broken due to keep-alive detecting a \"\n\t\t\"failure while operation was in progress\", 105 },\n\t{ WSAENETUNREACH, CRYPT_ERROR_NOTAVAIL, FALSE,\n\t\t\"WSAENETUNREACH: Network cannot be reached from this host at this \"\n\t\t\"time\", 69 },\n\t{ WSAENOBUFS, CRYPT_ERROR_MEMORY, FALSE,\n\t\t\"WSAENOBUFS: No buffer space available\", 37 },\n\t{ WSAENOTCONN, CRYPT_OK, TRUE,\n\t\t\"WSAENOTCONN: Socket is not connected\", 36 },\n\t{ WSAETIMEDOUT, CRYPT_ERROR_TIMEOUT, FALSE,\n\t\t\"WSAETIMEDOUT: Function timed out before completion\", 50 },\n\t{ WSAHOST_NOT_FOUND, CRYPT_ERROR_NOTFOUND, FALSE,\n\t\t\"WSAHOST_NOT_FOUND: Host not found\", 34 },\n\t{ WSATRY_AGAIN,  CRYPT_OK, FALSE,\n\t\t\"WSATRY_AGAIN: Host not found (non-authoritative)\", 48 },\n\t{ WSANO_ADDRESS,  CRYPT_OK, FALSE,\n\t\t\"WSANO_ADDRESS: No address record available for this name\", 56 },\n\t{ WSANO_DATA,  CRYPT_OK, FALSE,\n\t\t\"WSANO_DATA: Valid name, no data record of requested type\", 56 },\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n#define hostErrorInfo\tsocketErrorInfo\t\t/* Winsock uses unified error codes */\n\n#elif defined( __embOS__ )\n\nstatic const SOCKETERROR_INFO socketErrorInfo[] = {\n\t{ IP_ERR_MISC, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_MISC: Miscellaneous error\", 32 },\n\t{ IP_ERR_TIMEDOUT, CRYPT_ERROR_TIMEOUT, FALSE,\n\t\t\"IP_ERR_TIMEDOUT: Operation timed out\", 36 },\n\t{ IP_ERR_ISCONN, CRYPT_OK, FALSE, \n\t\t\"IP_ERR_ISCONN: Socket is already connected\", 42 },\n\t{ IP_ERR_OP_NOT_SUPP, CRYPT_ERROR_NOTAVAIL, TRUE,\n\t\t\"IP_ERR_OP_NOT_SUPP: Operation not supported for selected socket\", 63 },\n\t{ IP_ERR_CONN_ABORTED, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_CONN_ABORTED: Connection was aborted\", 43 },\n\t{ IP_ERR_WOULD_BLOCK, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_WOULD_BLOCK: Socket is in non-blocking state and the current \"\n\t\t\"operation would block the socket if not in non-blocking state\", 129 },\n\t{ IP_ERR_CONN_REFUSED, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"IP_ERR_CONN_REFUSED: Connection refused by peer\", 47 },\n\t{ IP_ERR_CONN_RESET, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_CONN_RESET: Connection has been reset\", 45 },\n\t{ IP_ERR_NOT_CONN, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_NOT_CONN: Socket is not connected\", 40 },\n\t{ IP_ERR_ALREADY, CRYPT_OK, FALSE,\n\t\t\"IP_ERR_ALREADY: Socket already is in the requested state\", 57 },\n\t{ IP_ERR_IN_VAL, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_IN_VAL: Passed value for configuration is not valid\", 58 },\n\t{ IP_ERR_MSG_SIZE, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"IP_ERR_MSG_SIZE: Message is too big to send\", 43 },\n\t{ IP_ERR_PIPE, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_PIPE: Socket is not in the correct state for this \"\n\t\t\"operation\", 66 },\n\t{ IP_ERR_DEST_ADDR_REQ, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"IP_ERR_DEST_ADDR_REQ: Destination address has not been specified\", 64 },\n\t{ IP_ERR_SHUTDOWN, CRYPT_ERROR_COMPLETE, TRUE,\n\t\t\"IP_ERR_SHUTDOWN: Connection has been closed as soon as all data \"\n\t\t\"has been received upon a FIN request\", 100 },\n\t{ IP_ERR_NO_PROTO_OPT, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_NO_PROTO_OPT: Unknown option for setsockopt() or \"\n\t\t\"getsockopt()\", 68 },\n\t{ IP_ERR_NO_MEM, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"IP_ERR_NO_MEM: Not enough memory in the memory pool\", 51 },\n\t{ IP_ERR_ADDR_NOT_AVAIL, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"IP_ERR_ADDR_NOT_AVAIL: No known path to send to the specified \"\n\t\t\"address\", 69 },\n\t{ IP_ERR_ADDR_IN_USE, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_ADDR_IN_USE: Socket already has a connection to this address \"\n\t\t\"and port or is already bound to this address\", 112 },\n\t{ IP_ERR_IN_PROGRESS, CRYPT_OK, FALSE,\n\t\t\"IP_ERR_IN_PROGRESS: Operation is still in progress\", 50 },\n\t{ IP_ERR_NO_BUF, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"IP_ERR_NO_BUF: No internal buffer was available\", 47 },\n\t{ IP_ERR_NOT_SOCK, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_NOT_SOCK: Socket has already been opened or has already \"\n\t\t\"been closed\", 74 },\n\t{ IP_ERR_FAULT, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_FAULT: Generic error for a failed operation\", 50 },\n\t{ IP_ERR_NET_UNREACH, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_NET_UNREACH: No path to the desired network available\", 61 },\n\t{ IP_ERR_PARAM, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_PARAM: Invalid parameter to function\", 43 },\n\t{ IP_ERR_LOGIC, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_LOGIC: Logical error that should not have happened\", 57 },\n\t{ IP_ERR_NOMEM, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"IP_ERR_NOMEM: System error: No memory for requested operation\", 61 },\n\t{ IP_ERR_NOBUFFER, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"IP_ERR_NOBUFFER: System error: No internal buffer available for \"\n\t\t\"the requested operation\", 87 },\n\t{ IP_ERR_RESOURCE, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"IP_ERR_RESOURCE: System error: Not enough free resources available \"\n\t\t\"for the requested operation\", 94 },\n\t{ IP_ERR_BAD_STATE, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_BAD_STATE: Socket is in an unexpected state\", 50 },\n\t{ IP_ERR_TIMEOUT, CRYPT_ERROR_TIMEOUT, FALSE,\n\t\t\"IP_ERR_TIMEOUT: Requested operation timed out\", 46 },\n\t{ IP_ERR_NO_ROUTE, CRYPT_OK, TRUE,\n\t\t\"IP_ERR_NO_ROUTE: Net error: Destination is unreachable\", 54 },\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n#define hostErrorInfo\tsocketErrorInfo\t\t/* embOS uses unified error codes */\n\n#elif defined( __Nucleus__ )\n\nstatic const SOCKETERROR_INFO socketErrorInfo[] = {\n\t{ NU_INVALID_PROTOCOL, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_PROTOCOL: Invalid network protocol\", 45 },\n\t{ NU_NO_DATA_TRANSFER, CRYPT_OK, TRUE,\n\t\t\"NU_NO_DATA_TRANSFER: Data was not written/read during send/receive \"\n\t\t\"function\", 75 },\n\t{ NU_NO_PORT_NUMBER, CRYPT_OK, TRUE,\n\t\t\"NU_NO_PORT_NUMBER: No local port number was stored in the socket \"\n\t\t\"descriptor\", 75 },\n\t{ NU_NO_TASK_MATCH, CRYPT_OK, TRUE,\n\t\t\"NU_NO_TASK_MATCH: No task/port number combination existed in the \"\n\t\t\"task table\", 75 },\n\t{ NU_NO_SOCKET_SPACE, CRYPT_ERROR_OVERFLOW, TRUE,\n\t\t\"NU_NO_SOCKET_SPACE: The socket structure list was full when a new \"\n\t\t\"socket descriptor was requested\", 97 },\n\t{ NU_NO_ACTION, CRYPT_OK, TRUE,\n\t\t\"NU_NO_ACTION: No action was processed by the function\", 53 },\n\t{ NU_NOT_CONNECTED, CRYPT_OK, TRUE,\n\t\t\"NU_NOT_CONNECTED: A connection has been closed by the network\", 61 },\n\t{ NU_INVALID_SOCKET, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_SOCKET: The socket ID passed in was not in a valid \"\n\t\t\"range\", 67 },\n\t{ NU_NO_SOCK_MEMORY, CRYPT_OK, TRUE,\n\t\t\"NU_NO_SOCK_MEMORY: Memory allocation failed for internal sockets \"\n\t\t\"structure\", 64 },\n\t{ NU_INVALID_ADDRESS, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_ADDRESS: An incomplete address was sent\", 50 },\n\t{ NU_NO_HOST_NAME, CRYPT_OK, TRUE,\n\t\t\"NU_NO_HOST_NAME: No host name specified in a connect call where a \"\n\t\t\"machine was not previously set up\", 99 },\n\t{ NU_RARP_INIT_FAILED, CRYPT_OK, TRUE,\n\t\t\"NU_RARP_INIT_FAILED: During initialization RARP failed\", 54 },\n\t{ NU_BOOTP_INIT_FAILED, CRYPT_OK, TRUE,\n\t\t\"NU_BOOTP_INIT_FAILED: During initialization BOOTP failed\", 56 },\n\t{ NU_INVALID_PORT, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_PORT: The port number passed in was not in a valid \"\n\t\t\"range\", 67 },\n\t{ NU_NO_BUFFERS, CRYPT_OK, TRUE,\n\t\t\"NU_NO_BUFFERS: There were no buffers to place the outgoing packet \"\n\t\t\"in\", 68 },\n\t{ NU_NOT_ESTAB, CRYPT_OK, TRUE,\n\t\t\"NU_NOT_ESTAB: A connection is open but not in an established state\", 66 },\n\t{ NU_WINDOW_FULL, CRYPT_OK, TRUE,\n\t\t\"NU_WINDOW_FULL: The foreign host's in window is full\", 52 },\n\t{ NU_NO_SOCKETS, CRYPT_OK, TRUE,\n\t\t\"NU_NO_SOCKETS: No sockets were specified\", 40 },\n\t{ NU_NO_DATA, CRYPT_OK, TRUE,\n\t\t\"NU_NO_DATA: None of the specified sockets were data ready\", 57 },\n\t/* NU_Setsockopt()/NU_Getsockopt() errors */\n\t{ NU_INVALID_LEVEL, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_LEVEL: The specified level is invalid\", 48 },\n\t{ NU_INVALID_OPTION, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_OPTION: The specified option is invalid\", 50 },\n\t{ NU_INVAL, CRYPT_OK, TRUE,\n\t\t\"NU_INVAL: General purpose error condition\", 41 },\n\t{ NU_ACCESS, CRYPT_OK, TRUE,\n\t\t\"NU_ACCESS: The attempted operation is not allowed on the socket\", 63 },\n\t/* Standard socket errors again */\n\t{ NU_ADDRINUSE, CRYPT_OK, TRUE,\n\t\t\"NU_ADDRINUSE: The IP Multicast membership already exists\", 56 },\n\t{ NU_HOST_UNREACHABLE, CRYPT_OK, TRUE,\n\t\t\"NU_HOST_UNREACHABLE: Host unreachable\", 37 },\n\t{ NU_MSGSIZE, CRYPT_OK, TRUE,\n\t\t\"NU_MSGSIZE: Packet is to large for interface\", 44 },\n\t{ NU_NOBUFS, CRYPT_OK, TRUE,\n\t\t\"NU_NOBUFS: Could not allocate a memory buffer\", 45 },\n\t{ NU_UNRESOLVED_ADDR, CRYPT_OK, TRUE,\n\t\t\"NU_UNRESOLVED_ADDR: The MAC address was not resolved\", 52 },\n\t{ NU_CLOSING, CRYPT_OK, TRUE,\n\t\t\"NU_CLOSING: The other side in a TCP connection has sent a FIN\", 61 },\n\t{ NU_MEM_ALLOC, CRYPT_OK, TRUE,\n\t\t\"NU_MEM_ALLOC: Failed to allocate memory\", 39 },\n\t{ NU_RESET, CRYPT_OK, TRUE,\n\t\t\"NU_RESET: A multicast membership was added and the MAC chip needs \"\n\t\t\"to be reset\", 77 },\n\t{ NU_DEVICE_DOWN, CRYPT_OK, TRUE,\n\t\t\"NU_DEVICE_DOWN: A device being used by the socket has gone down\", 63 },\n\t/* DNS errors */\n\t{ NU_INVALID_LABEL, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_LABEL: Domain name with an invalid label\", 51 },\n\t{ NU_FAILED_QUERY, CRYPT_OK, TRUE,\n\t\t\"NU_FAILED_QUERY: No response received for a DNS Query\", 53 },\n\t{ NU_DNS_ERROR, CRYPT_OK, TRUE,\n\t\t\"NU_DNS_ERROR: A general DNS error status\", 40 },\n\t{ NU_NOT_A_HOST, CRYPT_OK, TRUE,\n\t\t\"NU_NOT_A_HOST: The host name was not found\", 42 },\n\t{ NU_INVALID_PARM, CRYPT_OK, TRUE,\n\t\t\"NU_INVALID_PARM: A parameter has an invalid value\", 49 },\n\t{ NU_NO_DNS_SERVER, CRYPT_OK, TRUE,\n\t\t\"NU_NO_DNS_SERVER: No DNS server has been registered with the \"\n\t\t\"stack\", 66 },\n\t/* Standard socket errors again */\n\t{ NU_NO_ROUTE_TO_HOST, CRYPT_OK, TRUE,\n\t\t\"NU_NO_ROUTE_TO_HOST: ICMP Destination Unreachable specific \"\n\t\t\"error\", 64 },\n\t{ NU_CONNECTION_REFUSED, CRYPT_OK, TRUE,\n\t\t\"NU_CONNECTION_REFUSED: ICMP Destination Unreachable specific \"\n\t\t\"error\", 66 },\n\t{ NU_MSG_TOO_LONG, CRYPT_OK, TRUE,\n\t\t\"NU_MSG_TOO_LONG: ICMP Destination Unreachable specific error\", 60 },\n\t{ NU_BAD_SOCKETD, CRYPT_OK, TRUE,\n\t\t\"NU_BAD_SOCKETD: Socket descriptor is not valid for the current \"\n\t\t\"operation\", 72 },\n\t{ NU_BAD_LEVEL, CRYPT_OK, TRUE,\n\t\t\"NU_BAD_LEVEL: ???\", 17 },\n\t{ NU_BAD_OPTION, CRYPT_OK, TRUE,\n\t\t\"NU_BAD_OPTION: ???\", 18 },\n\t/* IPv6 errors */\n\t{ NU_DUP_ADDR_FAILED, CRYPT_OK, TRUE,\n\t\t\"NU_DUP_ADDR_FAILED: ???\", 23 },\n\t{ NU_DISCARD_PACKET, CRYPT_OK, TRUE,\n\t\t\"NU_DISCARD_PACKET: ???\", 22 },\n\t/* ICMP errors */\n\t{ NU_DEST_UNREACH_ADMIN, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_ADMIN: ICMP Destination Unreachable: Packet was \"\n\t\t\"rejected due to administration reasons\", 102 },\n\t{ NU_DEST_UNREACH_ADDRESS, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_ADDRESS: ICMP Destination Unreachable: Packet was \"\n\t\t\"rejected because destination address doesn't match an address on \"\n\t\t\"the node\", 139 },\n\t{ NU_DEST_UNREACH_PORT, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_PORT: ICMP Destination Unreachable: Destination \"\n\t\t\"port is not listening on the node\", 97 },\n\t{ NU_TIME_EXCEED_HOPLIMIT, CRYPT_OK, TRUE,\n\t\t\"NU_TIME_EXCEED_HOPLIMIT: ICMP Time Exceeded: Packet has exceeded \"\n\t\t\"the number of hops that it may make\", 100 },\n\t{ NU_TIME_EXCEED_REASM, CRYPT_OK, TRUE,\n\t\t\"NU_TIME_EXCEED_REASM: ICMP Time Exceeded: Packet could not be \"\n\t\t\"reassembled in the maximum allowable time\", 103 },\n\t{ NU_PARM_PROB_HEADER, CRYPT_OK, TRUE,\n\t\t\"NU_PARM_PROB_HEADER: ICMP Parameter Problem: Packet has an error \"\n\t\t\"in the IP header\", 81 },\n\t{ NU_PARM_PROB_NEXT_HDR, CRYPT_OK, TRUE,\n\t\t\"NU_PARM_PROB_NEXT_HDR: ICMP Parameter Problem: Packet has an \"\n\t\t\"invalid next header value in the IPv6 header\", 105 },\n\t{ NU_PARM_PROB_OPTION, CRYPT_OK, TRUE,\n\t\t\"NU_PARM_PROB_OPTION: ICMP Parameter Problem: Invalid option \"\n\t\t\"specified in the IP header\", 86 },\n\t{ NU_DEST_UNREACH_NET, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_NET: ICMP Destination Unreachable: Network is \"\n\t\t\"unreachable\", 73 },\n\t{ NU_DEST_UNREACH_HOST, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_HOST: ICMP Destination Unreachable: Host is \"\n\t\t\"unreachable\", 71 },\n\t{ NU_DEST_UNREACH_PROT, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_PROT: ICMP Destination Unreachable: Protocol is \"\n\t\t\"not recognized on the node\", 90 },\n\t{ NU_DEST_UNREACH_FRAG, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_FRAG: ICMP Destination Unreachable: Packet \"\n\t\t\"requires fragmentation but the node does not support \"\n\t\t\"fragmentation\", 125 },\n\t{ NU_DEST_UNREACH_SRCFAIL, CRYPT_OK, TRUE,\n\t\t\"NU_DEST_UNREACH_SRCFAIL:  ICMP Destination Unreachable: Source \"\n\t\t\"route failed\", 75 },\n\t{ NU_PARM_PROB, CRYPT_OK, TRUE,\n\t\t\"NU_PARM_PROB: ICMP Parameter Problem: Packet has an error in the \"\n\t\t\"IP header\", 74 },\n\t{ NU_SOURCE_QUENCH, CRYPT_OK, TRUE,\n\t\t\"NU_SOURCE_QUENCH: ICMP Source Quench: Node is receiving too many \"\n\t\t\"packets to process\", 83 },\n\t/* Nonblocking socket operation errors */\n\t{ NU_WOULD_BLOCK, CRYPT_OK, TRUE,\n\t\t\"NU_WOULD_BLOCK: Socket is non-blocking but blocking is required to \"\n\t\t\"complete the requested action\", 96 },\n\t/* TCP Keepalive errors */\n\t{ NU_CONNECTION_TIMED_OUT, CRYPT_OK, TRUE,\n\t\t\"NU_CONNECTION_TIMED_OUT: Connection has been closed due to TCP \"\n\t\t\"Keepalive probes not being answered\", 98 },\n\t/* Nonblocking connect errors */\n\t{ NU_IS_CONNECTING, CRYPT_OK, TRUE,\n\t\t\"NU_IS_CONNECTING: Socket is non-blocking and the connection is \"\n\t\t\"being established\", 80 },\n\t/* Standard socket errors again */\n\t{ NU_SOCKET_CLOSED, CRYPT_OK, TRUE,\n\t\t\"NU_SOCKET_CLOSED: The specified socket has been closed\", 54 },\n\t{ NU_TABLE_FULL, CRYPT_OK, TRUE,\n\t\t\"NU_TABLE_FULL: ???\", 18 },\n\t{ NU_NOT_FOUND, CRYPT_OK, TRUE,\n\t\t\"NU_NOT_FOUND: ???\", 17 },\n\t/* IPv6 extension header errors */\n\t{ NU_INVAL_NEXT_HEADER, CRYPT_OK, TRUE,\n\t\t\"NU_INVAL_NEXT_HEADER: ???\", 25 },\n\t{ NU_SEND_ICMP_ERROR, CRYPT_OK, TRUE,\n\t\t\"NU_SEND_ICMP_ERROR: ???\", 23 },\n\t/* Multicast errors */\n\t{ NU_MULTI_TOO_MANY_SRC_ADDRS, CRYPT_OK, TRUE,\n\t\t\"NU_MULTI_TOO_MANY_SRC_ADDRS: Number of source addresses specified \"\n\t\t\"for multicast IP address filtering exceeds \"\n\t\t\"MAX_MULTICAST_SRC_ADDR\", 131 },\n\t{ NU_NOT_A_GROUP_MEMBER, CRYPT_OK, TRUE,\n\t\t\"NU_NOT_A_GROUP_MEMBER: Socket is not a member of the multicast \"\n\t\t\"group specified\", 78 },\n\t{ NU_TOO_MANY_GROUP_MEMBERS, CRYPT_OK, TRUE,\n\t\t\"NU_TOO_MANY_GROUP_MEMBERS: Number of multicast groups has been \"\n\t\t\"reached\", 70 },\n\t/* Physical layer errors */\n\t{ NU_ETH_CABLE_UNPLUGGED, CRYPT_OK, TRUE,\n\t\t\"NU_ETH_CABLE_UNPLUGGED: Ethernet cable is unplugged\", 51 },\n\t{ NU_ETH_CABLE_PLUGGED_IN, CRYPT_OK, TRUE,\n\t\t\"NU_ETH_CABLE_PLUGGED_IN: Ethernet cable has been plugged in\", 59 },\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n#define hostErrorInfo\tsocketErrorInfo\t\t/* Nucleus uses unified error codes */\n\n#elif defined( __MQXRTOS__ )\n\nstatic const SOCKETERROR_INFO socketErrorInfo[] = {\n\t/* Generic Posix-equivalent errors.  Some of these vales are only present \n\t   for ornamental purposes (the more specific RTCS_xxx values are the \n\t   ones that actually get used) so we only map a subset of the more-\n\t   important ones */\n\t{ MQX_EACCES, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"MQX_EACCES: Permission denied\", 29 },\n\t{ MQX_EBADF, CRYPT_OK, FALSE,\n\t\t\"MQX_EBADF: Bad file descriptor\", 30 },\n\t{ MQX_EMFILE, CRYPT_OK, FALSE,\n\t\t\"MQX_EMFILE: Per-process descriptor table is full\", 48 },\n\t{ MQX_ENODEV, CRYPT_OK, TRUE,\n\t\t\"MQX_ENODEV: No such device\", 26 },\n\t{ MQX_EPERM, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"MQX_EPERM: Operation not permitted\", 34 },\n\t/* RTCS generic errors */\n\t{ RTCSERR_OUT_OF_MEMORY, CRYPT_ERROR_MEMORY, FALSE,\n\t\t\"RTCSERR_OUT_OF_MEMORY: Insufficient system resources available to \"\n\t\t\"complete the call\", 83 },\n\t{ RTCSERR_OUT_OF_BUFFERS, CRYPT_ERROR_MEMORY, FALSE,\n\t\t\"RTCSERR_OUT_OF_BUFFERS: Insufficient system resources available to \"\n\t\t\"complete the call\", 84 },\n\t{ RTCSERR_TIMEOUT, CRYPT_ERROR_TIMEOUT, FALSE,\n\t\t\"RTCSERR_TIMEOUT: Function timed out before completion\", 53 },\n\t/* IP-level errors */\n\t{ RTCSERR_IP_UNREACH, CRYPT_OK, FALSE,\n\t\t\"RTCSERR_IP_UNREACH: No route to the network or host is \"\n\t\t\"present\", 62 },\n\t{ RTCSERR_IP_TTL, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"RTCSERR_IP_TTL: TTL expired\", 27 },\n\t{ RTCSERR_IP_SMALLMTU, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"RTCSERR_IP_SMALLMTU: Message is too large to be sent all at \"\n\t\t\"once\", 64 },\n\t{ RTCSERR_IP_CANTFRAG, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"RTCSERR_IP_CANTFRAG: Need to fragment but DF bit set\", 52 },\n\t/* \"TCP/IP\" errors (c.f. \"TCP\" errors) */\n\t{ RTCSERR_TCPIP_NO_BUFFS /* = missing B52s */, CRYPT_ERROR_MEMORY, TRUE,\n\t  \"RTCSERR_TCPIP_NO_BUFFS: No buffer space available\", 49 },\n\t/* \"TCP\" errors (c.f. \"TCP/IP\" errors */\n\t{ RTCSERR_TCP_OPEN_FAILED, CRYPT_ERROR_OPEN, TRUE,\n\t\t\"RTCSERR_TCP_OPEN_FAILED: TcpOpen failed\", 39 },\n\t{ RTCSERR_TCP_IN_PROGRESS, CRYPT_OK, FALSE,\n\t\t\"RTCSERR_TCP_IN_PROGRESS: Connection already in progress\", 55 },\n\t{ RTCSERR_TCP_ADDR_IN_USE, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_TCP_ADDR_IN_USE: Address in use\", 39 },\n\t{ RTCSERR_TCP_ADDR_NA, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"RTCSERR_TCP_ADDR_NA: Specified address is not available from the \"\n\t\t\"local machine\", 78 },\n\t{ RTCSERR_TCP_CONN_ABORTED, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_TCP_CONN_ABORTED: Software caused connection abort\", 58 },\n\t{ RTCSERR_TCP_CONN_RESET, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_TCP_CONN_RESET: Connection was forcibly closed by remote \"\n\t\t\"host\", 69 },\n\t{ RTCSERR_TCP_HOST_DOWN, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_TCP_HOST_DOWN: Host is down\", 35 },\n\t{ RTCSERR_TCP_NOT_CONN, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_TCP_NOT_CONN: Socket is not connected\", 45 },\n\t{ RTCSERR_TCP_TIMED_OUT, CRYPT_ERROR_MEMORY, TRUE,\n\t  \"RTCSERR_TCP_TIMED_OUT: Operation timed out\", 42 },\n\t{ RTCSERR_TCP_CONN_REFUSED, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"RTCSERR_TCP_CONN_REFUSED: Attempt to connect was rejected\", 57 },\n\t{ RTCSERR_TCP_HOST_UNREACH, CRYPT_OK, FALSE,\n\t\t\"RTCSERR_TCP_HOST_UNREACH: No route to the network or host is \"\n\t\t\"present\", 68 },\n\t/* Socket errors */\n\t{ RTCSERR_SOCK_INVALID, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_SOCK_INVALID: Not a socket\", 39 },\n\t{ RTCSERR_SOCK_INVALID_AF, CRYPT_ERROR_NOTAVAIL, TRUE,\n\t\t\"RTCSERR_SOCK_INVALID_AF: Address family not supported\", 53 },\n\t{ RTCSERR_SOCK_NOT_CONNECTED, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_SOCK_NOT_CONNECTED: Socket is not connected\", 51 },\n\t{ RTCSERR_SOCK_IS_CONNECTED, CRYPT_OK, FALSE,\n\t\t\"RTCSERR_SOCK_IS_CONNECTED: Socket is connected\", 46 },\n\t{ RTCSERR_SOCK_EBADF, CRYPT_OK, FALSE,\n\t\t\"RTCSERR_SOCK_EBADF: Bad file descriptor\", 44 },\n\t/* DNS errors */\n\t{ RTCSERR_DNS_NO_NAME_SERVER_RESPONSE, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_DNS_NO_NAME_SERVER_RESPONSE: No name server response\", 60 },\n\t{ RTCSERR_DNS_NO_RESPONSE_FROM_RESOLVER, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_DNS_NO_RESPONSE_FROM_RESOLVER: No response from resolver\", 64 },\n\t{ RTCSERR_DNS_INVALID_NAME, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_DNS_INVALID_NAME: Invalid DNS name\", 42 },\n\t{ RTCSERR_DNS_ALL_SERVERS_QUERIED, CRYPT_OK, TRUE,\n\t\t\"RTCSERR_DNS_ALL_SERVERS_QUERIED: No response after all servers \"\n\t\t\"queried\", 70 },\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n#define hostErrorInfo\tsocketErrorInfo\t\t/* MQX uses unified error codes */\n\n#else\n\nstatic const SOCKETERROR_INFO socketErrorInfo[] = {\n\t{ EACCES, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"EACCES: Permission denied\", 25 },\n\t{ EADDRINUSE, CRYPT_OK, TRUE,\n\t\t\"EADDRINUSE: Address in use\", 26 },\n\t{ EADDRNOTAVAIL, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"EADDRNOTAVAIL: Specified address is not available from the local \"\n\t\t\"machine\", 72 },\n\t{ EAFNOSUPPORT, CRYPT_ERROR_NOTAVAIL, TRUE,\n\t\t\"EAFNOSUPPORT: Address family not supported\", 42 },\n\t{ EALREADY, CRYPT_OK, FALSE,\n\t\t\"EALREADY: Connection already in progress\", 41 },\n\t{ EBADF, CRYPT_OK, FALSE,\n\t\t\"EBADF: Bad file descriptor\", 26 },\n#if !( defined( __PALMOS__ ) || defined( __SYMBIAN32__ ) )\n\t{ ECONNABORTED, CRYPT_OK, TRUE,\n\t\t\"ECONNABORTED: Software caused connection abort\", 46 },\n\t{ ECONNRESET, CRYPT_OK, TRUE,\n\t\t\"ECONNRESET: Connection was forcibly closed by remote host\", 57 },\n#endif /* PalmOS || Symbian OS */\n\t{ ECONNREFUSED, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"ECONNREFUSED: Attempt to connect was rejected\", 45 },\n\t{ EINPROGRESS, CRYPT_OK, FALSE,\n\t\t\"EINPROGRESS: Operation in progress\", 34 },\n\t{ EINTR, CRYPT_OK, FALSE,\n\t\t\"EINTR: Function was interrupted by a signal\", 43 },\n#ifndef __Telit__\n\t{ EIO, CRYPT_OK, TRUE,\n\t\t\"EIO: Input/output error\", 24 },\n#endif /* Telit */\n\t{ EISCONN, CRYPT_OK, FALSE,\n\t\t\"EISCONN: Socket is connected\", 28 },\n\t{ EMFILE, CRYPT_OK, FALSE,\n\t\t\"EMFILE: Per-process descriptor table is full\", 44 },\n#ifndef __SYMBIAN32__\n\t{ EMSGSIZE, CRYPT_ERROR_OVERFLOW, FALSE,\n\t\t\"EMSGSIZE: Message is too large to be sent all at once\", 53 },\n\t{ ENETUNREACH, CRYPT_OK, FALSE,\n\t\t\"ENETUNREACH: No route to the network or host is present\", 55 },\n\t{ ENOBUFS, CRYPT_ERROR_MEMORY, FALSE,\n\t\t\"ENOBUFS: Insufficient system resources available to complete the \"\n\t\t\"call\", 69 },\n#ifndef __Telit__\n\t{ ENODEV, CRYPT_OK, TRUE,\n\t\t\"ENODEV: No such device\", 22 },\n#endif /* Telit */\n\t{ ENOPROTOOPT, CRYPT_OK, TRUE,\n\t\t\"ENOPROTOOPT: Protocol not available\", 35 },\n\t{ ENOTCONN, CRYPT_OK, TRUE,\n\t\t\"ENOTCONN: Socket is not connected\", 33 },\n\t{ ENOTSOCK, CRYPT_OK, TRUE,\n\t\t\"ENOTSOCK: Not a socket\", 22 },\n#endif /* Symbian OS */\n#ifndef __Telit__\n\t{ EPERM, CRYPT_ERROR_PERMISSION, TRUE,\n\t\t\"EPERM: Operation not permitted\", 30 },\n\t{ ENOMEM, CRYPT_ERROR_MEMORY, TRUE,\n\t\t\"ENOMEM: Out of memory\", 21 },\n#endif /* Telit */\n\t{ EPROTOTYPE, CRYPT_ERROR_NOTAVAIL, TRUE,\n\t\t\"EPROTOTYPE: Protocol wrong type for socket\", 42 },\n\t{ ETIMEDOUT, CRYPT_ERROR_TIMEOUT, FALSE,\n\t\t\"ETIMEDOUT: Function timed out before completion\", 47 },\n#if !( defined( __Quadros__ ) || defined( __Telit__ ) )\n\t{ HOST_NOT_FOUND, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"HOST_NOT_FOUND: Not an official hostname or alias\", 49 },\n  #ifndef __ECOS__ \n\t{ NO_ADDRESS, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"NO_ADDRESS: Name is valid but does not have an IP address at the \"\n\t\t\"name server\", 76 },\n  #endif /* !ECOS */\n\t{ TRY_AGAIN, CRYPT_OK, FALSE,\n\t\t\"TRY_AGAIN: Local server did not receive a response from an \"\n\t\t\"authoritative server\", 79 },\n#endif /* Quadros || Telit */\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n\nstatic const SOCKETERROR_INFO hostErrorInfo[] = {\n#if !( defined( __Quadros__ ) || defined( __Telit__ ) )\n\t{ HOST_NOT_FOUND, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"HOST_NOT_FOUND: Host not found\", 30 },\n  #ifndef __ECOS__ \n\t{ NO_ADDRESS, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"NO_ADDRESS: No address record available for this name\", 53 },\n  #endif /* !ECOS */\n\t{ NO_DATA, CRYPT_ERROR_NOTFOUND, TRUE,\n\t\t\"NO_DATA: Valid name, no data record of requested type\", 53 },\n\t{ TRY_AGAIN,  CRYPT_OK, FALSE,\n\t\t\"TRY_AGAIN: Local server did not receive a response from an \"\n\t\t\"authoritative server\", 79 },\n#endif /* Quadros || Telit */\n\t{ CRYPT_ERROR }, { CRYPT_ERROR }\n\t};\n#endif /* System-specific socket error codes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Error Lookup/Mapping Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get and set the low-level error information from a socket- and host-\n   lookup-based error.  In theory under Windows we could also use the \n   Network List Manager to try and get additional diagnostic information \n   but this requires playing with COM objects, the significant extra \n   complexity caused by this isn't worth the tiny additional level of \n   granularity that we might gain in reporting errors.  In any case the NLM \n   functionality seems primarily intended for interactively obtaining \n   information before any networking actions are initiated (\"Do we currently \n   have an Internet connection?\") rather than diagnosing problems afterwards \n   (\"What went wrong with the attempt to initiate an Internet connection?\") */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint mapNetworkError( NET_STREAM_INFO *netStream, \n\t\t\t\t\t const int netStreamErrorCode,\n\t\t\t\t\t const BOOLEAN useHostErrorInfo, \n\t\t\t\t\t IN_ERROR int status )\n\t{\n\tconst SOCKETERROR_INFO *errorInfo = \\\n\t\t\t\t\tuseHostErrorInfo ? hostErrorInfo : socketErrorInfo;\n\tconst int errorInfoSize = useHostErrorInfo ? \\\n\t\t\t\t\tFAILSAFE_ARRAYSIZE( hostErrorInfo, SOCKETERROR_INFO ) : \\\n\t\t\t\t\tFAILSAFE_ARRAYSIZE( socketErrorInfo, SOCKETERROR_INFO );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( useHostErrorInfo == TRUE || useHostErrorInfo == FALSE );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tclearErrorString( &netStream->errorInfo );\n\n\t/* If there's no further error information available then we can't \n\t   report any more detail */\n\tif( netStreamErrorCode == 0 )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, NETSTREAM_ERRINFO, \n\t\t\t\t  \"Networking error code = 0, no error information \"\n\t\t\t\t  \"available\" ) );\n\t\t}\n\n\t/* Try and find a specific error message for this error code */\n\tLOOP_LARGE( i = 0, i < errorInfoSize && \\\n\t\t\t\t\t   errorInfo[ i ].errorCode != CRYPT_ERROR, i++ )\n\t\t{\n\t\tif( errorInfo[ i ].errorCode != netStreamErrorCode )\n\t\t\tcontinue;\n\n\t\t/* We've found matching error information, return it */\n\t\tREQUIRES( errorInfo[ i ].errorStringLength > 10 && \\\n\t\t\t\t  errorInfo[ i ].errorStringLength < 150 );\n\t\tsetErrorString( NETSTREAM_ERRINFO, errorInfo[ i ].errorString, \n\t\t\t\t\t\terrorInfo[ i ].errorStringLength );\n\t\tif( errorInfo[ i ].cryptSpecificCode != CRYPT_OK )\n\t\t\t{\n\t\t\t/* There's a more specific error code than the generic one that \n\t\t\t   we've been given available, use that instead */\n\t\t\tstatus = errorInfo[ i ].cryptSpecificCode;\n\t\t\t}\n\t\tif( errorInfo[ i ].isFatal )\n\t\t\t{\n\t\t\t/* It's a fatal error, make it persistent for the stream */\n\t\t\tnetStream->persistentStatus = status;\n\t\t\t}\n\t\t\t\n\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < errorInfoSize );\n\n\t/* The error code doesn't correspond to anything that we can handle or\n\t   report on, the best that we can do is report the low-level error \n\t   code directly.  Felix, qui potuit rerum cognoscere causas - Virgil */\n\tretExt( status, \n\t\t\t( status, NETSTREAM_ERRINFO,\n\t\t\t  \"Networking error code = %d, no additional information \"\n\t\t\t  \"available\", netStreamErrorCode ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSocketError( NET_STREAM_INFO *netStream, \n\t\t\t\t\tIN_ERROR const int status,\n\t\t\t\t\tOUT_INT_Z int *socketErrorCode )\n\t{\n\tconst int errorCode = getErrorCode( netStream->netSocket );\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtr( socketErrorCode, sizeof( int ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Get the low-level error code and map it to an error string if\n\t   possible */\n\t*socketErrorCode = errorCode;\n\n\treturn( mapNetworkError( netStream, errorCode, FALSE, status ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getHostError( NET_STREAM_INFO *netStream, \n\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Get the low-level error code and map it to an error string if\n\t   possible */\n\treturn( mapNetworkError( netStream, \n\t\t\t\t\t\t\t getHostErrorCode( netStream->netSocket ), TRUE, \n\t\t\t\t\t\t\t status ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setSocketError( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tIN_BUFFER( errorMessageLength ) const char *errorMessage, \n\t\t\t\t\tIN_LENGTH_ERRORMESSAGE const int errorMessageLength,\n\t\t\t\t\tIN_ERROR const int status, \n\t\t\t\t\tconst BOOLEAN isFatal )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtr( errorMessage, 16 ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( errorMessageLength > 16 && \\\n\t\t\t  errorMessageLength <= MAX_INTLENGTH_SHORT );\n\t\t\t  /* MAX_ERRORMESSAGE_SIZE isn't defined at this level */\n\tREQUIRES( cryptStatusError( status ) );\n\tREQUIRES( isFatal == TRUE || isFatal == FALSE );\n\n\t/* Set a cryptlib-supplied socket error message */\n\tsetErrorString( NETSTREAM_ERRINFO, errorMessage, errorMessageLength );\n\tif( isFatal )\n\t\t{\n\t\t/* It's a fatal error, make it persistent for the stream */\n\t\tnetStream->persistentStatus = status;\n\t\t}\n\treturn( status );\n\t}\n#endif /* USE_ERRMSGS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNetwork Diganostic Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If a socket open fails we generally can't provide much information to the \n   caller beyond \"socket open failed\".  This occurs for two reasons, the \n   first being that the network stack dumbs down a lot of the lower-level \n   error information that's returned in the case of a problem, for example \n   ICMP error codes 0, 1, and 5-12 are all combined into \"No route to host\", \n   2 and 3 both become \"Connection refused\", and parameter problem \n   notifications all become \"Protocol not available\".  The second reason is \n   that the caller may be connecting to the wrong port or some similar\n   operator error.\n   \n   To deal with this we perform an opportunistic ping of the first address \n   associated with the name to see if the ICMP reply can tell us more about \n   what's wrong */\n\n#ifdef USE_RAW_SOCKETS\n\n#define getIPVersion( value )\t\t( ( ( value ) & 0xF0 ) >> 4 )\n#define getIP4HeaderLength( value )\t( ( ( value ) & 0x0F ) << 2 )\n#define PACKET_OFFSET_IPVERSION\t\t0\t/* Offset of IP version field */\n#define PACKET_OFFSET_NEXTHEADER\t6\t/* Offset of IPv6 next-header field */\n#define PACKET_OFFSET_PROTOCOL\t\t9\t/* Offset of IPv4 protocol field */\n#define IP4_MIN_HEADERSIZE\t\t\t20\t/* Minimum IPv4 header size */\n#define IP6_HEADERSIZE\t\t\t\t40\t/* IPv6 header size */\n#define ICMP_MIN_PACKETSIZE\t\t\t8\t/* Minimum ICMP packet size */\n#define ICMP_TYPE_ECHO_REPLY\t\t0\t/* ICMP packet type = echo reply */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nstatic int pingHost( INOUT NET_STREAM_INFO *netStream,\n\t\t\t\t\t IN_BUFFER( addressInfoLength ) const void *addressInfo,\n\t\t\t\t\t IN_LENGTH_SHORT const int addressInfoLength,\n\t\t\t\t\t OUT_BUFFER( bufMaxSize, *bufLen ) BYTE *buffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 64 ) const int bufMaxSize, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxSize ) int *bufLen )\n\t{\n\tstatic const BYTE pingPacket[] = {\n\t\t0x08,\t\t\t/* Type 8 = Echo request */\n\t\t0x00,\t\t\t/* Code 0 */\n\t\t0xF7, 0xFF,\t\t/* Checksum, ~0x0800 */\n\t\t0x00, 0x00,\t\t/* Unique ID */\n\t\t0x00, 0x00\t\t/* Sequence number */\n\t\t};\n\tstruct sockaddr recvAddr;\n\tSIZE_TYPE recvAddrSize = sizeof( struct sockaddr );\n\tint length, status;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( addressInfo, addressInfoLength ) );\n\tassert( isWritePtrDynamic( buffer, bufMaxSize ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( isShortIntegerRangeNZ( addressInfoLength ) );\n\tREQUIRES( bufMaxSize >= 64 && bufMaxSize < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bufMaxSize ) );\n\t*bufLen = 0;\n\n\t/* Send a rudimentary ping packet to the remote system.  Apart from \n\t   making the checksum calculation easier, the minimal packet size also\n\t   means that we sidestep any potential MTU/fragmentation issues.  Note \n\t   that we don't connect() the remote system's port and address to the \n\t   socket (if that's even possible for a raw/ICMP socket) because we \n\t   want to receive all ICMP messages sent to us, not just something \n\t   returned from the specific remote system that we're targeting */\n\tstatus = sendto( netStream->netSocket, pingPacket, 8, 0, \n\t\t\t\t\t addressInfo, addressInfoLength );\n\tif( isSocketError( status ) )\n\t\treturn( CRYPT_ERROR_WRITE );\n\n\t/* Try and read the ping response.  We don't go to too much trouble in \n\t   terms of handling exception conditions here since this is an \n\t   opportunistic check only, so we only send a single ping with a 10s\n\t   timeout.\n\n\t   The details of what we get back for a raw socket get rather complex.  \n\t   In general raw sockets can end up receiving most non-TCP/UDP packets\n\t   (that is, most ICMP/IGMP and all unknown-protocol packets), however\n\t   by explicitly selecting IPPROTO_ICMP we've told the kernel that we\n\t   only want to get ICMP packets.  However since we haven't bound the \n\t   socket to a remote address (see the comment for sendto() above) we're \n\t   going to get copies of all ICMP packets that arrive, not just our \n\t   ones.  This makes things a bit complicated since we can't easily \n\t   tell whether an incoming ICMP error packet from an address other than \n\t   the target address is from (say) a router telling us that our ping\n\t   can't get through or something related to network traffic from \n\t   another process on the system.\n\t   \n\t   Under IPv6 we could perform additional filtering with:\n\n\t\t#include <netinet/icmp6.h>\n\n\t\tstruct icmp6_filter filter;\n\n\t\tICMP6_FILTER_SETBLOCKALL( &filter );\n\t\tICMP6_FILTER_SETPASS( ND_xxx, &filter );\n\t\tsetsockopt( socket, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, \n\t\t\t\t\tsizeof( filter ) );\n\n\t   Even then though we have to be careful because there's a race \n\t   condition, ICMP packets that arrive between the socket() and \n\t   setsockopt() will be enqueued for the raw socket, the filtering is a \n\t   performance optimisation rather than an absolute block-list */\n\tstatus = ioWait( netStream, 10, TRUE, IOWAIT_READ );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the response data.  For the reason given above, we only try and \n\t   read the first 512 bytes of response, ignore ICMP checksum problems \n\t   (other layers should be taking care of this, IPv6 removes the \n\t   checksums entirely for this reason), and don't check whether the \n\t   response came from the intended source (which we could do by \n\t   comparing addrInfoCursor->ai_addr->sa_data with recvAddr.sa_data) \n\t   since it could be an ICMP error message from an intermediate system.  \n\t   Performing this address check would also cause problems if the server \n\t   was multihomed, so if the incoming socket is bound to the wildcard \n\t   address and our packet is sent to a non-primary address (alias) but \n\t   comes back from the primary address then we'll appear to have a \n\t   non-match */\n\tmemset( buffer, 0, bufMaxSize );\n\tstatus = length = recvfrom( netStream->netSocket, buffer, bufMaxSize, 0, \n\t\t\t\t\t\t\t\t&recvAddr, &recvAddrSize );\n\tif( isSocketError( status ) )\n\t\treturn( CRYPT_ERROR_READ );\n\tif( length < IP4_MIN_HEADERSIZE + ICMP_MIN_PACKETSIZE || \\\n\t\tlength > 512 )\n\t\treturn( CRYPT_ERROR_BADDATA );\t\n\n\t*bufLen = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processICMP( IN_BUFFER( icmpPacketLength ) const BYTE *icmpPacket,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( IP4_MIN_HEADERSIZE + ICMP_MIN_PACKETSIZE ) \\\n\t\t\t\t\t\t\tconst int icmpPacketLength,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( icmpPacketLength ) int *icmpDataStart )\n\t{\n\tconst int version = getIPVersion( icmpPacket[ PACKET_OFFSET_IPVERSION ] );\n\n\tassert( isReadPtrDynamic( icmpPacket, icmpPacketLength ) );\n\n\tREQUIRES( icmpPacketLength >= IP4_MIN_HEADERSIZE + ICMP_MIN_PACKETSIZE && \\\n\t\t\t  icmpPacketLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*icmpDataStart = 0;\n\n\t/* Make sure that we got back something that at least looks like an \n\t   IPv4 or IPv6 packet */\n\tif( version != 4 && version != 6 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* We got back an IPv4 or IPv6 packet, hopefully an ICMP response.  \n\t   Unfortunately despite the fact that this is an IPPROTO_ICMP socket, \n\t   what we get back is a raw IP packet (due to the use of SOCK_RAW), so \n\t   first we have to pick apart the IP packet to find the ICMP packet \n\t   within it:\n\n\t\t\t  +-- IP4_MIN_HEADERSIZE\n\t\t\t  |\t\t\t\t\t\t  +-- ICMP_MIN_PACKETSIZE\n\t\t\t  v\t\t\t\t\t\t  v\n\t\t+-----------+-----------+-----------+-----------+\n\t\t| IPv4 hdr\t| IPv4 opts\t| ICMPv4 hdr| ICMP data\t|\n\t\t+-----------+-----------+-----------+-----------+\n\t\t|<-- 20 --> |<- 0..40 ->|<--- 8 --->| \n\t\t|<--- headerLength ---->|\n\t\t|<------------------ length ------------------->|\n\n\t\t+-----------+-----------+\n\t\t| IPv4 hdr\t| ICMPv4 hdr| Minimum ICMPv4 packet\n\t\t+-----------+-----------+ */\n\tif( version == 4 )\n\t\t{\n\t\tconst int headerLength = getIP4HeaderLength( icmpPacket[ 0 ] );\n\n\t\t/* Make sure that we got enough data back for an ICMP reply */\n\t\tif( headerLength < IP4_MIN_HEADERSIZE || \\\n\t\t\theaderLength > icmpPacketLength - ICMP_MIN_PACKETSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Now make sure that we've got an ICMP reply */\n\t\tif( icmpPacket[ PACKET_OFFSET_PROTOCOL ] != IPPROTO_ICMP )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t*icmpDataStart = headerLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's an IPv6 packet (which in the current case is rather unlikely \n\t   given that we explicitly send IPv4 pings) and make sure that we've \n\t   got enough data for an ICMP reply:\n\n\t\t\t  +-- IP6_HEADERSIZE\n\t\t\t  |\t\t\t  +-- ICMP_MIN_PACKETSIZE\n\t\t\t  v\t\t\t  v\n\t\t+-----------+-----------+-----------+\n\t\t| IPv6 hdr\t| ICMPv6 hdr| ICMP data\t|\n\t\t+-----------+-----------+-----------+\n\t\t|<-- 40 --> |<--- 8 --->| \n\t\t|<------------ length ------------->|\n\n\t\t+-----------+-----------+\n\t\t| IPv6 hdr\t| ICMPv6 hdr| Minimum ICMPv6 packet\n\t\t+-----------+-----------+ */\n\tENSURES( version == 6 );\n\tif( icmpPacketLength < IP6_HEADERSIZE + ICMP_MIN_PACKETSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Now make sure that we've got an ICMP reply.  The latter serves two \n\t   purposes, it checks that we have what we're after and it rejects \n\t   packets with extra extension headers between the IPv6 header and the \n\t   payload, which we don't bother trying to parse.  The presence of \n\t   these in already-rare IPv6 packets should be even more rare given how \n\t   many systems will drop any IPv6 packets that contain them (for \n\t   example RFC 7872 reports packet drop rates of over 50% for some \n\t   extension header types) */\n\tif( icmpPacket[ PACKET_OFFSET_NEXTHEADER ] != IPPROTO_ICMP )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\n\t*icmpDataStart = IP6_HEADERSIZE;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint diagnoseConnectionProblem( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t   IN_BUFFER( hostNameLen ) const char *host, \n\t\t\t\t\t\t\t   IN_LENGTH_DNS const int hostNameLen,\n\t\t\t\t\t\t\t   IN_ERROR const int originalStatus )\n\t{\n\tNET_STREAM_INFO diagnosticNetStream;\n\tSOCKET netSocket = INVALID_SOCKET;\n\tBYTE buffer[ 512 + 8 ];\n\tstruct addrinfo *addrInfoPtr, *addrInfoCursor;\n\tint addressCount, length DUMMY_INIT, offset, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( host, hostNameLen ) );\n\t\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( hostNameLen > 0 && hostNameLen <= MAX_DNS_SIZE );\n\tREQUIRES( cryptStatusError( originalStatus ) );\n\n\t/* Create an ICMP socket (we use a dummy port of 514 for the address \n\t   lookup which for UDP is the syslog port, ICMP itself doesn't use \n\t   ports).  Under Unix only the superuser can create raw sockets (a\n\t   restriction dating back to the \"if it's on a port < 1024 then you\n\t   can trust it because root on that machine and I were at Oxford\n\t   together\" days designed to prevent users sending custom packets\n\t   onto the net) so this will only work on non-Unix systems, but since\n\t   what we're doing here is opportunistic anyway there's no great need\n\t   to make it work everywhere.\n\t   \n\t   We also always use ICMPv4 via the hardcoded IPPROTO_ICMP rather than\n\t   choosing IPPROTO_ICMPV6 since again this is an opportunistic probe \n\t   and IPv4 is the one most likely to work.   This simplifies other \n\t   special-case handling such as the fact that for an ICMPv6 socket the \n\t   checksum is calculated for us since there's an additional pseudo-\n\t   header included while for ICMPv4 we have to calculate it ourselves.\n\t   \n\t   Finally, as mentioned in the comment at the start of this function,\n\t   we only try for the first address rather than trying to iterate\n\t   through everything that's potentially available */\n\tstatus = getAddressInfo( netStream, &addrInfoPtr, host, hostNameLen, \n\t\t\t\t\t\t\t 514, FALSE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( originalStatus );\n\tANALYSER_HINT( addrInfoPtr != NULL );\n\tLOOP_MED( ( addrInfoCursor = addrInfoPtr, addressCount = 0 ),\n\t\t\t  addrInfoCursor != NULL && addressCount < IP_ADDR_COUNT,\n\t\t\t  ( addrInfoCursor = addrInfoCursor->ai_next, addressCount++ ) )\n\t\t{\n\t\t/* If it's not an IPv4 address, continue */\n\t\tif( addrInfoCursor->ai_family != AF_INET )\n\t\t\tcontinue;\n\n\t\t/* We've found an IPv4 address, create a socket for it */\n\t\tnetSocket = socket( addrInfoCursor->ai_family, SOCK_RAW, \n\t\t\t\t\t\t\tIPPROTO_ICMP );\n\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( isBadSocket( netSocket ) )\n\t\t{\n\t\tfreeAddressInfo( addrInfoPtr );\n\t\treturn( originalStatus );\n\t\t}\n\n\t/* Set up a dummy network stream to handle the I/O */\n\tmemset( &diagnosticNetStream, 0, sizeof( NET_STREAM_INFO  ) );\n\tdiagnosticNetStream.protocol = STREAM_PROTOCOL_UDP;\n\tINIT_FLAGS( diagnosticNetStream.nFlags, STREAM_NFLAG_DGRAM );\n\tINIT_FLAGS( diagnosticNetStream.nhFlags, STREAM_NHFLAG_NONE );\n\tdiagnosticNetStream.port = 514;\n\tdiagnosticNetStream.timeout = 10;\n\tdiagnosticNetStream.netSocket = netSocket;\n\tdiagnosticNetStream.listenSocket = INVALID_SOCKET;\n\tFNPTR_SET( diagnosticNetStream.writeFunction, pingHost );\t/* Dummy fns */\n\tFNPTR_SET( diagnosticNetStream.readFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportConnectFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportDisconnectFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportReadFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportWriteFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportOKFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.transportCheckFunction, pingHost );\n\tFNPTR_SET( diagnosticNetStream.connectFunctionOpt, NULL );\n\tFNPTR_SET( diagnosticNetStream.disconnectFunctionOpt, NULL );\n\tDATAPTR_SET( diagnosticNetStream.virtualStateInfo, NULL );\n\tFNPTR_SET( diagnosticNetStream.virtualGetDataFunction, NULL );\n\tFNPTR_SET( diagnosticNetStream.virtualPutDataFunction, NULL );\n\tFNPTR_SET( diagnosticNetStream.virtualGetErrorInfoFunction, NULL );\n\tENSURES( sanityCheckNetStream( &diagnosticNetStream ) );\n\n\t/* Ping the remote host */\n\tstatus = pingHost( &diagnosticNetStream, addrInfoCursor->ai_addr, \n\t\t\t\t\t   addrInfoCursor->ai_addrlen, buffer, 512, &length );\n\tclosesocket( netSocket );\n\tfreeAddressInfo( addrInfoPtr );\n\tmemset( &diagnosticNetStream, 0, sizeof( NET_STREAM_INFO  ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( originalStatus );\n\n\t/* Postcondition: We've read enough data for an ICMP packet */\n\tENSURES( length >= IP4_MIN_HEADERSIZE + ICMP_MIN_PACKETSIZE && \\\n\t\t\t length <= 512 );\n\n\t/* Process the ICMP response */\n\tstatus = processICMP( buffer, length, &offset );\n\tif( cryptStatusError( status ) )\n\t\treturn( originalStatus );\n\n\t/* Report the result of the ICMP ping to the caller */\n\tif( buffer[ offset ] == ICMP_TYPE_ECHO_REPLY )\n\t\t{\n\t\tretExtErrAlt( originalStatus, \n\t\t\t\t\t  ( originalStatus, NETSTREAM_ERRINFO,\n\t\t\t\t\t\t\", however an ICMP ping to the host succeeded, \"\n\t\t\t\t\t\t\"indicating that the host is up\" ) );\n\t\t}\n\tretExtErrAlt( originalStatus, \n\t\t\t\t  ( originalStatus, NETSTREAM_ERRINFO,\n\t\t\t\t\t\", and an ICMP ping to the host returned ICMP packet \"\n\t\t\t\t\t\"type %d, code %d\", buffer[ offset ], \n\t\t\t\t\tbuffer[ offset + 1 ] ) );\n\t}\n#endif /* USE_RAW_SOCKETS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAdditional Error Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some buggy firewall software will block any data transfer attempts made \n   after the initial connection setup, if we're in a situation where this \n   can happen then we check for the presence of a software firewall and \n   report a problem due to the firewall rather than a general networking \n   problem */\n\n#ifdef __WIN32__\n\n#define MAX_DRIVERS     1024\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkFirewallError( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tINSTANCE_HANDLE hPSAPI = NULL_INSTANCE;\n\ttypedef BOOL ( WINAPI *ENUMDEVICEDRIVERS )( LPVOID *lpImageBase, DWORD cb,\n\t\t\t\t\t\t\t\t\t\t\t\tLPDWORD lpcbNeeded );\n\ttypedef DWORD ( WINAPI *GETDEVICEDRIVERBASENAME )( LPVOID ImageBase,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   LPTSTR lpBaseName,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   DWORD nSize );\n\tENUMDEVICEDRIVERS pEnumDeviceDrivers;\n\tGETDEVICEDRIVERBASENAME pGetDeviceDriverBaseName;\n\tLPVOID drivers[ MAX_DRIVERS + 8 ];\n\tDWORD cbNeeded;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\n\t/* Use the PSAPI library to check for the presence of firewall filter\n\t   drivers.  Since this operation is rarely performed and is only called\n\t   as part of an error handler in which performance isn't a major factor\n\t   we load the library on demand each time (which we'd have to do in any \n\t   case because it's not supported on older systems) rather than using\n\t   an on-init load as we do for the networking functions */\n\tif( ( hPSAPI = DynamicLoad( \"psapi.dll\" ) ) == NULL_INSTANCE )\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\tpEnumDeviceDrivers = ( ENUMDEVICEDRIVERS ) \\\n\t\t\t\t\t\t GetProcAddress( hPSAPI, \"EnumDeviceDrivers\" );\n\tpGetDeviceDriverBaseName = ( GETDEVICEDRIVERBASENAME ) \\\n\t\t\t\t\t\t\t   GetProcAddress( hPSAPI, \"GetDeviceDriverBaseNameA\" );\n\tif( pEnumDeviceDrivers == NULL || \\\n\t\tpGetDeviceDriverBaseName == NULL || \\\n\t\t!pEnumDeviceDrivers( drivers, MAX_DRIVERS * sizeof( LPVOID ), \n\t\t\t\t\t\t\t &cbNeeded ) )\n\t\t{\n\t\tDynamicUnload( hPSAPI );\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\t}\n\n\t/* Check whether a suspect filter driver is present */\n\tLOOP_MAX( i = 0, i < cbNeeded / sizeof( LPVOID ), i++ )\n\t\t{\n\t\ttypedef struct {\n\t\t\tconst char *name;\n\t\t\tconst int nameLen;\n\t\t\tconst BOOLEAN isMcafee;\n\t\t\t} DRIVER_INFO;\n\t\tstatic const DRIVER_INFO driverInfoTbl[] = {\n\t\t\t{ \"cfwids.sys\", 10, TRUE },\t\t/* McAfee Personal IDS */\n\t\t\t{ \"firelm01.sys\", 8, TRUE },\t/* McAfee Host IPS */\n\t\t\t{ \"firehk4x.sys\", 8, TRUE },\t/* McAfee Host IPS */\n\t\t\t{ \"firehk5x.sys\", 8, TRUE },\t/* McAfee Host IPS */\n\t\t\t{ \"fw220.sys\", 5, TRUE },\t\t/* McAfee FW */\n\t\t\t{ \"mfefirek.sys\", 12, TRUE },\t/* McAfree FW Engine */\n\t\t\t{ \"mfehidk.sys\", 11, TRUE },\t/* McAfee link driver */\n\t\t\t{ \"mfetdik.sys\", 11, TRUE },\t/* McAfee FW */\n\t\t\t{ \"mfetdi2k.sys\", 12, TRUE },\t/* McAfee FW */\n\t\t\t{ \"mfewfpk.sys\", 11, TRUE },\t/* McAfee Enterprise FW */\n\t\t\t{ \"mpfirewall.sys\", 10, TRUE },\t/* McAfee Personal FW */\n\t\t\t{ \"mvstdi5x.sys\", 12, TRUE },\t/* McAfee FW driver */\n\t\t\t{ \"spbbcdrv.sys\", 8, FALSE },\t/* Norton Personal FW */\n\t\t\t{ \"symfw.sys\", 9, FALSE },\t\t/* Symantec FW */\n\t\t\t{ \"symids.sys\", 10, FALSE },\t/* Symantec IDS */\n\t\t\t{ \"symndis.sys\", 11, FALSE },\t/* Norton Personal FW */\n\t\t\t{ \"symtdi.sys\", 6, FALSE },\t\t/* Symantec TDI */\n\t\t\t{ \"teefer.sys\", 10, FALSE },\t/* Norton/Symantec FW */\n\t\t\t{ \"teefer2.sys\", 11, FALSE },\t/* Norton/Symantec FW */\n\t\t\t{ \"teefer3.sys\", 11, FALSE },\t/* Norton/Symantec FW */\n\t\t\t{ \"wpsdrvnt.sys\", 12, FALSE },\t/* Symantec CMC FW */\n\t\t\t{ NULL, 0, FALSE }, { NULL, 0, FALSE }\n\t\t\t};\n\t\tchar driverName[ 256 + 8 ];\n\t\tint driverNameLen, driverIndex, LOOP_ITERATOR_ALT;\n\n\t\tdriverNameLen = pGetDeviceDriverBaseName( drivers[ i ], \n\t\t\t\t\t\t\t\t\t\t\t\t  driverName, 256 );\n\t\tif( driverNameLen <= 0 )\n\t\t\tcontinue;\n\t\tLOOP_MED_ALT( driverIndex = 0, \n\t\t\t\t\t  driverInfoTbl[ driverIndex ].name != NULL && \\\n\t\t\t\t\t\tdriverIndex < FAILSAFE_ARRAYSIZE( driverInfoTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  DRIVER_INFO ),\n\t\t\t\t\t  driverIndex++ )\n\t\t\t{\n\t\t\tif( driverNameLen >= driverInfoTbl[ driverIndex ].nameLen && \\\n\t\t\t\t!strnicmp( driverName, driverInfoTbl[ driverIndex ].name,\n\t\t\t\t\t\t   driverInfoTbl[ driverIndex ].nameLen ) )\n\t\t\t\t{\n\t\t\t\tDynamicUnload( hPSAPI );\n\t\t\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t\t\t( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO,\n\t\t\t\t\t\t  \"Network data transfer blocked, probably due to \"\n\t\t\t\t\t\t  \"%s firewall software installed on the PC\", \n\t\t\t\t\t\t  driverInfoTbl[ driverIndex ].isMcafee ? \\\n\t\t\t\t\t\t\t\"McAfee\" : \"Symantec/Norton\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDynamicUnload( hPSAPI );\n\n\treturn( CRYPT_ERROR_TIMEOUT );\n\t}\n#endif /* Win32 */\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/tcp_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal TCP/IP Header File\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDefines and Constants \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wait codes for the ioWait() function */\n\ntypedef enum { \n\tIOWAIT_NONE,\t\t\t/* No I/O wait type */\n\tIOWAIT_READ,\t\t\t/* Wait for read availability */\n\tIOWAIT_WRITE,\t\t\t/* Wait for write availability */\n\tIOWAIT_CONNECT,\t\t\t/* Wait for connect to complete */\n\tIOWAIT_ACCEPT,\t\t\t/* Wait for accept to complete */\n\tIOWAIT_LAST\t\t\t\t/* Last possible wait type */\n\t} IOWAIT_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tData Structures \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The network socket pool, used to deal with the Unix socket programming\n   model which assumes that a single process will listen on a server socket\n   and fork off children as required to deal with connect attempts.  See\n   the disucssion in io/tcp.c for more on how this works.\n   \n   Note that although this data structure is only used in io/tcp_conn.c,\n   we have to declare it here since it's allocated in the static data set\n   at compile time */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define SOCKETPOOL_SIZE\t\t8\n#else\n  #define SOCKETPOOL_SIZE\t\t128\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n#define ADDRHASH_SIZE\t\t\t8\n\ntypedef struct {\n#ifdef __WINDOWS__\n\tUINT_PTR netSocket;\t\t/* Socket handle */\n#else\n\tint netSocket;\t\t\t/* Socket handle */\n#endif /* System-specific socket data types */\n\tint refCount;\t\t\t/* Reference count for the socket */\n\tint addrChecksum;\t\t/* Checksum and hash of family, interface, and */\n\tBYTE addrHash[ ADDRHASH_SIZE + 8 ];\t/*\tport info for server socket */\n\t} SOCKET_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tSupport Functions \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef _STREAM_INT_DEFINED\n\n/* Socket pool access function */\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getSocketPoolStorage( void );\nCHECK_RETVAL \\\nint initSocketPool( void );\n\n/* Prototypes for functions in tcp.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint ioWait( INOUT NET_STREAM_INFO *netStream, \n\t\t\tIN_INT_Z const int timeout,\n\t\t\tconst BOOLEAN previousDataRead, \n\t\t\tIN_ENUM( IOWAIT ) const IOWAIT_TYPE type );\n\n/* Prototypes for functions in tcp_conn.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCPConnect( INOUT NET_STREAM_INFO *netStream );\n\n/* Prototypes for functions in tcp_rw.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCPReadWrite( INOUT NET_STREAM_INFO *netStream );\n\n/* Prototypes for functions in tcp_err.c */\n\n#ifdef USE_ERRMSGS\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint mapNetworkError( NET_STREAM_INFO *netStream, \n\t\t\t\t\t const int netStreamErrorCode,\n\t\t\t\t\t const BOOLEAN useHostErrorInfo, \n\t\t\t\t\t IN_ERROR int status );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSocketError( NET_STREAM_INFO *netStream, \n\t\t\t\t\tIN_ERROR const int status,\n\t\t\t\t\tOUT_INT_Z int *socketErrorCode );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getHostError( NET_STREAM_INFO *netStream, IN_ERROR const int status );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setSocketError( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\tIN_BUFFER( errorMessageLength ) const char *errorMessage, \n\t\t\t\t\tIN_LENGTH_ERRORMESSAGE const int errorMessageLength,\n\t\t\t\t\tIN_ERROR const int status, const BOOLEAN isFatal );\n#else\n#define mapNetworkError( netStream, netStreamErrorCode, useHostErrorInfo, status ) \\\n\t\tstatus\n#define getSocketError( netStream, status, socketErrorCode ) \\\n\t\t*socketErrorCode = getErrorCode( netStream->netSocket ), status\n#define getHostError( netStream, status )\tstatus\n#define setSocketError( netStream, errorMessage, errorMessageLength, status, isFatal ) \\\n\t\tnetStream->persistentStatus = ( isFatal ) ? status : CRYPT_OK, status\n#endif /* USE_ERRMSGS */\n#ifdef USE_RAW_SOCKETS\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint diagnoseConnectionProblem( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t   IN_BUFFER( hostNameLen ) const char *host, \n\t\t\t\t\t\t\t   IN_LENGTH_DNS const int hostNameLen,\n\t\t\t\t\t\t\t   IN_ERROR const int originalStatus );\n#else\n#define diagnoseConnectionProblem( netStream, hostName, hostNameLen, status ) \\\n\t\t\t\t\t\t\t\t   status\n#endif /* USE_RAW_SOCKETS */\n#ifdef __WIN32__\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkFirewallError( INOUT NET_STREAM_INFO *netStream );\n#else\n  #define checkFirewallError( netStream )\tCRYPT_ERROR_TIMEOUT\n#endif /* Windows */\n#endif /* _STREAM_INT_DEFINED */\n\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/io/tcp_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t   cryptlib TCP/IP Read/Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream_int.h\"\n  #include \"tcp.h\"\n  #include \"tcp_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream_int.h\"\n  #include \"io/tcp.h\"\n  #include \"io/tcp_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TCP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNetwork I/O Wait Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wait for I/O to become possible on a socket.  The particular use of \n   select that we employ here is reasonably optimal under load because we're \n   only asking select() to monitor a single descriptor.  There are a variety \n   of inefficiencies related to select that fall into either the category of \n   user <-> kernel copying or of descriptor list scanning.  For the first \n   category, when calling select() the system has to copy an entire list of \n   descriptors into kernel space and then back out again.  Large selects can \n   potentially contain hundreds or thousands of descriptors, which can in \n   turn involve allocating memory in the kernel and freeing it on return.  \n   We're only using one so the amount of data to copy is minimal.\n\n   The second category involves scanning the descriptor list, an O(n) \n   activity.  First the kernel has to scan the list to see whether there's \n   pending activity on a descriptor.  If there aren't any descriptors with \n   activity pending it has to update the descriptor's selinfo entry in the \n   event that the calling process calls tsleep() (used to handle event-based \n   process blocking in the kernel) while waiting for activity on the \n   descriptor.  After the select() returns or the process is woken up from a \n   tsleep() the user process in turn has to scan the list to see which \n   descriptors the kernel indicated as needing attention.  As a result, the \n   list has to be scanned three times.\n\n   These problems arise because select() (and its cousin poll()) are \n   stateless by design so everything has to be recalculated on each call.  \n   After various false starts the kqueue interface is now seen as the best \n   solution to this problem.  However cryptlib's use of only a single \n   descriptor per select() avoids the need to use system-specific and rather \n   non-portable interfaces like kqueue or earlier alternatives like Sun's \n   /dev/poll, FreeBSD's get_next_event(), and SGI's /dev/imon */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint ioWait( INOUT NET_STREAM_INFO *netStream, \n\t\t\tIN_INT_Z const int timeout,\n\t\t\tconst BOOLEAN previousDataRead, \n\t\t\tIN_ENUM( IOWAIT ) const IOWAIT_TYPE type )\n\t{\n\tstatic const struct {\n\t\tconst int status;\n\t\tconst char *errorString;\n\t\t} errorInfo[] = {\n\t\t{ CRYPT_ERROR_OPEN, \"unknown\" },\n\t\t{ CRYPT_ERROR_READ, \"read\" },\t\t/* IOWAIT_READ */\n\t\t{ CRYPT_ERROR_WRITE, \"write\" },\t\t/* IOWAIT_WRITE */\n\t\t{ CRYPT_ERROR_OPEN, \"connect\" },\t/* IOWAIT_CONNECT */\n\t\t{ CRYPT_ERROR_OPEN, \"accept\" },\t\t/* IOWAIT_ACCEPT */\n\t\t{ CRYPT_ERROR_OPEN, \"unknown\" }, { CRYPT_ERROR_OPEN, \"unknown\" }\n\t\t};\n\tMONOTIMER_INFO timerInfo;\n\tstruct timeval tv;\n\tfd_set readfds, writefds, exceptfds;\n\tfd_set *readFDPtr = ( type == IOWAIT_READ || \\\n\t\t\t\t\t\t  type == IOWAIT_CONNECT || \\\n\t\t\t\t\t\t  type == IOWAIT_ACCEPT ) ? &readfds : NULL;\n\tfd_set *writeFDPtr = ( type == IOWAIT_WRITE || \\\n\t\t\t\t\t\t   type == IOWAIT_CONNECT ) ? &writefds : NULL;\n\tint selectIterations, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( isIntegerRange( timeout ) );\n\tREQUIRES( previousDataRead == TRUE || previousDataRead == FALSE );\n\tREQUIRES( isEnumRange( type, IOWAIT ) );\n\n\t/* Check for overflows in FD_SET().  This is an ugly implementation \n\t   issue in which, for sufficiently badly-implemented FD_SET() macros\n\t   (and there are plenty of these around), the macro will just take the \n\t   provided socket descriptor and use it to index the fd_set bitmask.\n\t   This occurs for the most common implementations under Unix (BSD) and \n\t   BSD-derived embedded OSes, Windows gets it right and uses a bounds-\n\t   checked array.  \n\t   \n\t   The maximum socket descriptor is normally given by FD_SETSIZE, \n\t   typically 64 under Windows (but we don't have to worry this since it \n\t   does FD_SET() right) and 256 or sometimes 1024 under Unix, however \n\t   this can be increased explicitly using setrlimit() or, from the \n\t   shell, 'ulimit -n 512' to make it 512, which will cause an overflow.  \n\t   To deal with this, we reject any socket values less than zero (if \n\t   it's a signed variable) or greater than FD_SETSIZE */\n#ifndef __WINDOWS__ \n\tREQUIRES( netStream->netSocket >= 0 && \\\n\t\t\t  netStream->netSocket <= FD_SETSIZE );\n#endif /* !Windows */\n\n\t/* Set up the information needed to handle timeouts and wait on the\n\t   socket.  If there's no timeout then we wait 5ms on the theory that it \n\t   isn't noticeable to the caller but ensures that we at least get a \n\t   chance to get anything that may be pending.  We also have to special-\n\t   case the first iteration of the loop because a timeout of zero will\n\t   always result in the timer being expired, so we force at least one\n\t   iteration through the loop.\n\n\t   The exact wait time depends on the system, but usually it's quantised\n\t   to the system timer quantum.  This means that on Unix systems with a\n\t   1ms timer resolution the wait time is quantised on a 1ms boundary.\n\t   Under everything newer than early Windows NT systems it's quantised \n\t   on a 10ms boundary (some early NT systems had a granularity ranging \n\t   from 7.5 - 15ms but all newer systems use 10ms) and for Win95/98/ME \n\t   it was quantised on a 55ms boundary.  In other words when performing \n\t   a select() on a Win95 box it would either return immediately or wait \n\t   some multiple of 55ms even with the time set to 1ms, but we don't\n\t   have to worry about those Windows versions any more.\n\n\t   In theory we shouldn't have to reset either the fds or the timeval\n\t   each time through the loop since we're only waiting on one descriptor\n\t   so it's always set and the timeval is a const, however some versions\n\t   of Linux can update it if the select fails due to an EINTR (which is\n\t   the exact reason why we'd be going through the loop a second time in\n\t   the first place) and/or if a file descriptor changes status (e.g. due \n\t   to data becoming available) so we have to reset it each time to be on \n\t   the safe side.  It would actually be nice if the tv value were \n\t   updated reliably to reflect how long the select() had to wait since \n\t   it'd provide a nice source of entropy for the randomness pool (we \n\t   could simulate this by readig a high-res timer before and after the\n\t   select() but that would add a pile of highly system-dependent code\n\t   and defeat the intent of using the \"free\" entropy that's provided as \n\t   a side-effect of the select()).\n\n\t   The wait on connect is a slightly special case, the socket will\n\t   become writeable if the connect succeeds normally, but both readable\n\t   and writeable if there's an error on the socket or if there's data\n\t   already waiting on the connection (i.e. it arrives as part of the\n\t   connect).  It's up to the caller to check for these conditions */\n\tstatus = setMonoTimer( &timerInfo, timeout );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MED( ( selectIterations = 0, status = SOCKET_ERROR ), \\\n\t\t\t  isSocketError( status ) && \\\n\t\t\t\t( selectIterations <= 0 || \\\n\t\t\t\t  !checkMonoTimerExpired( &timerInfo ) ) && \\\n\t\t\t\tselectIterations < 20, \n\t\t\t  selectIterations++ )\n\t\t{\n\t\tif( readFDPtr != NULL )\n\t\t\t{\n\t\t\tFD_ZERO( readFDPtr );\n\t\t\tFD_SET( netStream->netSocket, readFDPtr );\n\t\t\t}\n\t\tif( writeFDPtr != NULL )\n\t\t\t{\n\t\t\tFD_ZERO( writeFDPtr );\n\t\t\tFD_SET( netStream->netSocket, writeFDPtr );\n\t\t\t}\n\t\tFD_ZERO( &exceptfds );\n\t\tFD_SET( netStream->netSocket, &exceptfds );\n\t\ttv.tv_sec = timeout;\n\t\ttv.tv_usec = ( timeout <= 0 ) ? 5000 : 0;\n\n\t\t/* See if we can perform the I/O.  This gets a bit complex under \n\t\t   Windows because a socket isn't an int like everywhere else so the\n\t\t   expression 'maxSocket + 1' that's required for the wacky nfds \n\t\t   argument doesn't make much sense.  OTOH Windows ignores this \n\t\t   argument entirely since it serves no purpose (beyond making the\n\t\t   socket-scan macro slightly easier to handle on a PDP-11) because \n\t\t   the fd_sets already contain all the required information, so we \n\t\t   just cast whatever the value ends up as to an int to fit the \n\t\t   function prototype */\n\t\tclearErrorState();\n\t\tstatus = select( ( int ) netStream->netSocket + 1, readFDPtr, \n\t\t\t\t\t\t writeFDPtr, &exceptfds, &tv );\n\n\t\t/* If there's a problem and it's not something transient like an\n\t\t   interrupted system call, exit.  For a transient problem, we just\n\t\t   retry the select until the overall timeout expires */\n\t\tif( isSocketError( status ) && \\\n\t\t\t!isRestartableError( netStream->netSocket ) )\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\treturn( getSocketError( netStream, errorInfo[ type ].status, \n\t\t\t\t\t\t\t\t\t&dummy ) );\n\t\t\t}\n\t\t}\n\tif( selectIterations >= 20 )\n\t\t{\n\t\tchar errorMessage[ 128 + 8 ];\n\t\tint errorMessageLength;\n\n\t\t/* We've gone through the select loop a suspiciously large number\n\t\t   of times, there's something wrong.  In theory we could report \n\t\t   this as a more serious error than a simple timeout since it means\n\t\t   that there's either a bug in our code or a bug in the select()\n\t\t   implementation, but without knowing in advance what caused this\n\t\t   can't-occur condition it's difficult to anticipate the correct\n\t\t   action to take, so all that we do is warn in the debug build */\n\t\tDEBUG_DIAG(( \"select() went through %d iterations without \"\n\t\t\t\t\t \"returning a result\", selectIterations ));\n\t\tassert( DEBUG_WARN );\n\t\terrorMessageLength = sprintf_s( errorMessage, 128,\n\t\t\t\t\t\t\t\t\t\t\"select() on %s went through %d \"\n\t\t\t\t\t\t\t\t\t\t\"iterations without returning a \"\n\t\t\t\t\t\t\t\t\t\t\"result\",\n\t\t\t\t\t\t\t\t\t\terrorInfo[ type ].errorString, \n\t\t\t\t\t\t\t\t\t\tselectIterations );\n\t\treturn( setSocketError( netStream, errorMessage, errorMessageLength,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_TIMEOUT, FALSE ) );\n\t\t}\n\n\t/* If the wait timed out, either explicitly in the select (status == 0)\n\t   or implicitly in the wait loop (isSocketError()), report it as a\n\t   select() timeout error */\n\tif( status == 0 || isSocketError( status ) )\n\t\t{\n\t\tchar errorMessage[ 128 + 8 ];\n\t\tint errorMessageLength;\n\n\t\t/* If we've already received data from a previous I/O, tell the \n\t\t   caller to use that as the transferred byte count even though we \n\t\t   timed out this time round */\n\t\tif( previousDataRead )\n\t\t\treturn( OK_SPECIAL );\n\n\t\t/* If it's a nonblocking wait (usually used as a poll to determine\n\t\t   whether I/O is possible) then a timeout isn't an error.  The\n\t\t   caller can distinguish this from the previous OK_SPECIAL return \n\t\t   by whether previousDataRead was set or not */\n\t\tif( timeout <= 0 )\n\t\t\treturn( OK_SPECIAL );\n\n\t\t/* The select() timed out, exit */\n\t\terrorMessageLength = sprintf_s( errorMessage, 128,\n\t\t\t\t\t\t\t\t\t\t\"Timeout on %s (select()) after %d \"\n\t\t\t\t\t\t\t\t\t\t\"second%s\",\n\t\t\t\t\t\t\t\t\t\terrorInfo[ type ].errorString, \n\t\t\t\t\t\t\t\t\t\ttimeout, ( timeout > 1 ) ? \"s\" : \"\" );\n\t\tENSURES( errorMessageLength > 0 && \\\n\t\t\t\t errorMessageLength < 128 );\n\t\treturn( setSocketError( netStream, errorMessage, errorMessageLength,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_TIMEOUT, FALSE ) );\n\t\t}\n\n\t/* If there's an exception condition on a socket, exit.  This is\n\t   implementation-specific, traditionally under Unix this only indicates\n\t   the arrival of out-of-band data rather than any real error condition,\n\t   but in some cases it can be used to signal errors.  In these cases we\n\t   have to explicitly check for an exception condition because some\n\t   types of errors will result in select() timing out waiting for\n\t   readability rather than indicating an error and returning.  In \n\t   addition for OOB data we could just ignore the notification (which \n\t   happens automatically with the default setting of SO_OOBINLINE = \n\t   false and an indicator to receive SIGURG's not set, the OOB data byte \n\t   just languishes in a side-buffer), however we shouldn't be receiving \n\t   OOB data so we treat that as an error too */\n\tif( FD_ISSET( netStream->netSocket, &exceptfds ) )\n\t\t{\n\t\tint socketErrorCode;\n\n\t\tstatus = getSocketError( netStream, errorInfo[ type ].status, \n\t\t\t\t\t\t\t\t &socketErrorCode );\n\t\tif( socketErrorCode != 0 )\n\t\t\treturn( status );\n\n\t\t/* We got a no-error error code even though there's an exception \n\t\t   condition present, this typically only happens under Windows.  \n\t\t   The most common case is when we're waiting on a nonblocking \n\t\t   connect (type = IOWAIT_CONNECT), in which case a failure to \n\t\t   connect due to e.g. an ECONNREFUSED can be reported as a select() \n\t\t   error.  This is a bit tricky to report on because we can't be \n\t\t   sure what the actual problem is without adding our own timer \n\t\t   handling, in which case a fast reject would be due to an explicit \n\t\t   notification like ECONNREFUSED while a slow reject might be an \n\t\t   ENETUNREACH or something similar (a genuine timeout error should \n\t\t   have been caught by the \"wait timed out\" code above).  Another\n\t\t   option is to retry the connect as a blocking one to get a genuine\n\t\t   error code, but that defeats the point of using a nonblocking \n\t\t   connect to deal with problem conditions.\n\n\t\t   The conflict here is between an honest but rather useless \n\t\t   CRYPT_ERROR_OPEN and a guessed and far more useful, but \n\t\t   potentially misleading, ECONNREFUSED.  Given that this is an\n\t\t   oddball condition to begin with it's unclear how far we should\n\t\t   go down this rathole, for now we assume an ECONNREFUSED */\n\t\tif( type == IOWAIT_CONNECT )\n\t\t\t{\n\t\t\t( void ) mapNetworkError( netStream, NONBLOCKCONNECT_ERROR, \n\t\t\t\t\t\t\t\t\t  FALSE, CRYPT_ERROR_OPEN );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* This is probably a mis-handled select() timeout, which can happen \n\t\t   with Winsock under certain circumstances and seems to be related \n\t\t   to another socket-using application performing network I/O at the \n\t\t   same time as we do the select() wait.  Non-Winsock cases can occur \n\t\t   because some implementations don't treat a soft timeout as an \n\t\t   error, and at least one (Tandem) returns EINPROGRESS rather than \n\t\t   ETIMEDOUT, so we insert a timeout error code ourselves.  \n\t\t\t   \n\t\t   Since we're merely updating the extended internal error \n\t\t   information (we already know what the actual error status is) we \n\t\t   don't need to do anything with the mapError() return value */\n\t\t( void ) mapNetworkError( netStream, TIMEOUT_ERROR, FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_ERROR_TIMEOUT );\n\t\treturn( status );\n\t\t}\n\n\t/* The socket is read for reading or writing */\n\tENSURES( status > 0 );\n\tENSURES( ( type == IOWAIT_READ && \\\n\t\t\t   FD_ISSET( netStream->netSocket, &readfds ) ) || \\\n\t\t\t ( type == IOWAIT_WRITE && \\\n\t\t\t   FD_ISSET( netStream->netSocket, &writefds ) ) || \\\n\t\t\t ( type == IOWAIT_CONNECT && \\\n\t\t\t   ( FD_ISSET( netStream->netSocket, &readfds ) || \\\n\t\t\t\t FD_ISSET( netStream->netSocket, &writefds ) ) ) || \\\n\t\t\t ( type == IOWAIT_ACCEPT ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead Network Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read and write data from and to a socket.  Because data can appear in \n   bits and pieces when reading we have to implement timeout handling at two \n   levels, once via ioWait() and a second time as an overall timeout.  If we \n   only used ioWait() this could potentially stretch the overall timeout to \n   (length * timeout) so we also perform a time check that leads to a worst-\n   case timeout of (timeout-1 + timeout).  This is the same as the \n   implementation of SO_SND/RCVTIMEO in Berkeley-derived implementations, \n   where the timeout value is actually an interval timer rather than an\n   absolute timer.\n\n   In addition to the standard stream-based timeout behaviour we can also be \n   called with flags specifying explicit blocking behaviour (for a read \n   where we know that we're expecting a certain amount of data) or explicit \n   nonblocking behaviour (for speculative reads to fill a buffer).  These \n   flags are used by the buffered-read routines, which try and speculatively \n   read as much data as possible to avoid the many small reads required by \n   some protocols.  We don't do the blocking read using MSG_WAITALL since \n   this can (potentially) block forever if not all of the data arrives.\n\n   Finally, if we're performing an explicit blocking read (which is usually \n   done when we're expecting a predetermined number of bytes) we dynamically \n   adjust the timeout so that if data is streaming in at a steady rate then \n   we don't abort the read just because there's more data to transfer than \n   we can manage in the originally specified timeout interval.  This is \n   especially useful when transferring large data amounts, for which a one-\n   size-fits-all fixed timeout doesn't accurately reflect the amount of time \n   required to transfer the full data amount.\n\n   Handling of return values is as follows:\n\n\ttimeout\t\tbyteCount\t\treturn\n\t-------\t\t---------\t\t------\n\t\t0\t\t\t0\t\t\t\t0\n\t\t0\t\t  > 0\t\t\tbyteCount\n\t  > 0\t\t\t0\t\t\tCRYPT_ERROR_TIMEOUT\n\t  > 0\t\t  > 0\t\t\tbyteCount\n\n   At the sread()/swrite() level if the partial-read/write flags aren't set\n   for the stream, a byteCount < length is also converted to a\n   CRYPTO_ERROR_TIMEOUT */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readSocketFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t   OUT_BUFFER( maxLength, *length ) BYTE *buffer, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\t   IN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tMONOTIMER_INFO timerInfo;\n\tBYTE *bufPtr = buffer;\n\tconst int timeout = ( flags & TRANSPORT_FLAG_NONBLOCKING ) ? 0 : \\\n\t\t\t\t\t\t( flags & TRANSPORT_FLAG_BLOCKING ) ? \\\n\t\t\t\t\t\tmax( NET_TIMEOUT_READ, netStream->timeout ) : \\\n\t\t\t\t\t\tnetStream->timeout;\n\tconst BOOLEAN isDgramSocket = \\\n\t\t\tTEST_FLAG( netStream->nFlags, STREAM_NFLAG_DGRAM ) ? TRUE : FALSE;\n\tint bytesToRead, byteCount = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( ( flags & TRANSPORT_FLAG_NONBLOCKING ) && \\\n\t\t\t\ttimeout == 0 ) || \\\n\t\t\t  ( !( flags & TRANSPORT_FLAG_NONBLOCKING ) && \\\n\t\t\t\tisIntegerRange( timeout ) ) );\n\tREQUIRES( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t  flags == TRANSPORT_FLAG_NONBLOCKING || \\\n\t\t\t  flags == TRANSPORT_FLAG_BLOCKING );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\tstatus = setMonoTimer( &timerInfo, timeout );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MAX_INITCHECK( bytesToRead = maxLength,\n\t\t\t\t\t\tbytesToRead > 0 && \\\n\t\t\t\t\t\t\t( timeout <= 0 || \\\n\t\t\t\t\t\t\t  !checkMonoTimerExpired( &timerInfo ) ) )\n\t\t{\n\t\tint bytesRead;\n\n\t\t/* Wait for data to become available */\n\t\tstatus = ioWait( netStream, timeout, \n\t\t\t\t\t\t ( byteCount > 0 ) ? TRUE : FALSE, IOWAIT_READ );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* We got a timeout but either there's already data present from \n\t\t\t   a previous read or it's a nonblocking wait, so this isn't an\n\t\t\t   error */\n\t\t\tif( byteCount > 0 )\n\t\t\t\t*length = byteCount;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Some buggy firewall software will block any data transfer \n\t\t\t   attempts made after the initial connection setup.  More \n\t\t\t   specifically they'll allow the initial SYN/SYN/ACK to \n\t\t\t   establish the connection state but then block any further \n\t\t\t   information from being transferred.  To handle this we\n\t\t\t   check whether we get a timeout on the first read and if we\n\t\t\t   do then we check for the presence of a software firewall,\n\t\t\t   reporting a problem due to the firewall rather than a\n\t\t\t   general networking problem if we find one */\n\t\t\tif( status == CRYPT_ERROR_TIMEOUT && \\\n\t\t\t\t!TEST_FLAG( netStream->nFlags, STREAM_NFLAG_FIRSTREADOK ) )\n\t\t\t\t{\n\t\t\t\treturn( checkFirewallError( netStream ) );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We've got data waiting, read it */\n\t\tclearErrorState();\n\t\tbytesRead = recv( netStream->netSocket, bufPtr, bytesToRead, 0 );\n\t\tif( isSocketError( bytesRead ) )\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\t/* If it's a restartable read due to something like an\n\t\t\t   interrupted system call, retry the read */\n\t\t\tif( isRestartableError( netStream->netSocket ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Restartable read, recv() indicated error\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* There was a problem with the read */\n\t\t\treturn( getSocketError( netStream, CRYPT_ERROR_READ, &dummy ) );\n\t\t\t}\n\t\tif( bytesRead <= 0 )\n\t\t\t{\n\t\t\t/* Under some odd circumstances (bugs in older versions of \n\t\t\t   Winsock when using non-blocking sockets, or calling select() \n\t\t\t   with a timeout of 0), recv() can return zero bytes without an \n\t\t\t   EOF condition being present, even though it should return an \n\t\t\t   error status if this happens (this could also happen under \n\t\t\t   very old SysV implementations using O_NDELAY for nonblocking \n\t\t\t   I/O).  \n\t\t\t   \n\t\t\t   One situation in which we can legitimately get this (although\n\t\t\t   the status is misleading) is when we don't get an ACK for a \n\t\t\t   previous data send.  If we get here before the ACK timeout \n\t\t\t   occurs then we won't get the ECONNABORTED but instead get \n\t\t\t   recv() == 0 (exactly how we can get recv() == 0 due to the \n\t\t\t   lack of ACK but not an ECONNABORTED at the same point remains \n\t\t\t   a mystery).  \n\t\t\t   \n\t\t\t   An example of a situation in which we can get an ECONNABORTED \n\t\t\t   is when the client sends an HTTP POST to the server, which \n\t\t\t   looks at the HTTP request header, rejects it (e.g. due to \n\t\t\t   excessive content length, which cryptlib will do in order to \n\t\t\t   avoid being DoS'ed by the other side), and sends back an \n\t\t\t   error response and closes the connection without trying to \n\t\t\t   read the body of the request.  The connection is now half-\n\t\t\t   closed, with the client still writing the HTTP body to its \n\t\t\t   side of the connection, which means that it gets buffered in \n\t\t\t   the TCP stack but not sent.  At this point the client tries \n\t\t\t   to read the HTTP response, but in the meantime the outgoing \n\t\t\t   retransmission of the buffered data has failed and the TCP \n\t\t\t   stack on the client shuts down the connection.  This means \n\t\t\t   that the HTTP response that the server sent is never read, \n\t\t\t   and the client gets an ECONNABORTED.\n\n\t\t\t   Dealing with this particular situation is quite difficult, \n\t\t\t   see the comment in the code block for handling \n\t\t\t   byteCount == 0 at the end of this function.\n\t\t\t   \n\t\t\t   To try and catch the more general situation we check for a \n\t\t\t   restartable read due to something like an interrupted system \n\t\t\t   call and retry the read if it is.  This doesn't catch the \n\t\t\t   Winsock zero-delay bug but it may catch problems in other \n\t\t\t   implementations.\n\n\t\t\t   Unfortunately this doesn't work under all circumstances\n\t\t\t   either.  If the connection is genuinely closed select() will\n\t\t\t   return a data-available status and recv() will return zero,\n\t\t\t   both without changing errno.  If the last status set in errno\n\t\t\t   matches the isRestartableError() check, the code will loop\n\t\t\t   forever.  Because of this we can't use the following check,\n\t\t\t   although since it doesn't catch the Winsock zero-delay bug\n\t\t\t   anyway it's probably no big deal.\n\n\t\t\t   The real culprit here is the design flaw in recv(), which\n\t\t\t   uses a valid bytes-received value to indicate an out-of-band\n\t\t\t   condition that should be reported via an error code (\"There's\n\t\t\t   nowt wrong wi' owt what mitherin clutterbucks don't barley\n\t\t\t   grummit\") */\n#if 0\t/* See above comment */\n\t\t\tif( isRestartableError() )\n\t\t\t\t{\n\t\t\t\tassert( !\"Restartable read, recv() indicated no error\" );\n\t\t\t\tcontinue;\n\t\t\t\t}\n#endif /* 0 */\n\n\t\t\t/* Once we encounter this problem, we've fallen and can't get up \n\t\t\t   any more.  WSAGetLastError() reports no error, select() \n\t\t\t   reports data available for reading, and recv() reports zero \n\t\t\t   bytes read.  If the following is used, the code will loop \n\t\t\t   endlessly (or at least until the loop iteration watchdog \n\t\t\t   triggers) waiting for data that can never be read */\n#if 0\t/* See above comment */\n\t\t\tgetSocketError( netStream, CRYPT_ERROR_READ, &dummy );\n\t\t\tstatus = ioWait( netStream, 0, 0, IOWAIT_READ );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tcontinue;\n#endif /* 0 */\n\n\t\t\t/* \"It said its piece, and then it sodded off\" - Baldrick,\n\t\t\t   Blackadder's Christmas Carol */\n\t\t\tbytesToRead = 0;\t/* Force exit from loop */\n\t\t\tcontinue;\n\t\t\t}\n\t\tbufPtr += bytesRead;\n\t\tbytesToRead -= bytesRead;\n\t\tbyteCount += bytesRead;\n\t\tENSURES( bytesToRead >= 0 && bytesToRead < maxLength && \\\n\t\t\t\t bytesToRead < MAX_BUFFER_SIZE );\n\t\tENSURES( byteCount > 0 && byteCount <= maxLength && \\\n\t\t\t\t byteCount < MAX_BUFFER_SIZE );\n\n\t\t/* Remember that we've got some data, used for error diagnosis (see\n\t\t   the long comment above) */\n\t\tSET_FLAG( netStream->nFlags, STREAM_NFLAG_FIRSTREADOK );\n\n\t\t/* Datagram sockets are different from standard stream sockets in \n\t\t   that data amounts are quantised, we get either nothing or a \n\t\t   complete packet.  Since we've already got some data it means that \n\t\t   we got a complete packet, so we're done */\n\t\tif( isDgramSocket )\n\t\t\tbreak;\n\n\t\t/* If this is a blocking read and we've been moving data at a \n\t\t   reasonable rate (~1K/s) and we're about to time out, adjust the \n\t\t   timeout to give us a bit more time.  This is an adaptive process \n\t\t   that grants us more time for the read if data is flowing at \n\t\t   a reasonable rate, but ensures that we don't hang around forever \n\t\t   if data is trickling in at a few bytes a second */\n\t\tif( flags & TRANSPORT_FLAG_BLOCKING )\n\t\t\t{\n\t\t\tENSURES( timeout > 0 );\n\n\t\t\t/* If the timer expiry is imminent but data is still flowing in, \n\t\t\t   extend the timing duration to allow for further data to \n\t\t\t   arrive.  Because of the minimum flow-rate limit that's \n\t\t\t   imposed above this is unlikely to be subject to much of a DoS \n\t\t\t   problem (at worst an attacker can limit us to reading data \n\t\t\t   at 1K/s, which means 16s for SSL/TLS packets and 32s for SSH \n\t\t\t   packets), but to make things a bit less predictable we dither \n\t\t\t   the timeout a bit */\n\t\t\tif( ( byteCount / timeout ) >= 1000 && \\\n\t\t\t\tcheckMonoTimerExpiryImminent( &timerInfo, 5 ) )\n\t\t\t\t{\n\t\t\t\textendMonoTimer( &timerInfo, \n\t\t\t\t\t\t\t\t ( getRandomInteger() % 5 ) + 2 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( maxLength > 0 && byteCount <= 0 )\n\t\t{\n\t\t/* We didn't get anything because the other side closed the\n\t\t   connection.  We report this as a read-complete status rather than\n\t\t   a read error since it isn't necessarily a real error.\n\t\t   \n\t\t   One situation in which we can get this is when we don't get an \n\t\t   ACK for a previous data send, however if we get here before the \n\t\t   ACK timeout occurs then we won't get the ECONNABORTED/\n\t\t   WSAECONNABORTED but instead get recv() == 0.  Getting the \n\t\t   ECONNABORTED is quite difficult, just adding a delay won't work\n\t\t   so we need to wait and then perform a second read.  Because this\n\t\t   is somewhat system-specific, we make it Windows-only for now */\n#ifdef __WINDOWS__\n\t\tBYTE dummyBuffer[ 8 + 8 ];\n  #ifdef USE_ERRMSGS\n\t\tint errorCode;\n  #endif /* USE_ERRMSGS */\n\n\t\tSleep( 500 );\n\t\t( void ) recv( netStream->netSocket, dummyBuffer, 8, 0 );\n  #ifdef USE_ERRMSGS\n\t\t( void ) getSocketError( netStream, CRYPT_ERROR_READ, &errorCode );\n\t\tif( errorCode == WSAECONNABORTED )\n\t\t\treturn( CRYPT_ERROR_COMPLETE );\n  #endif /* USE_ERRMSGS */\n#endif /* __WINDOWS__ */\n\t\treturn( setSocketError( netStream, \n\t\t\t\t\t\t\t\t\"No data was read because the remote system \"\n\t\t\t\t\t\t\t\t\"closed the connection (recv() == 0)\", 78,\n\t\t\t\t\t\t\t\tCRYPT_ERROR_COMPLETE, TRUE ) );\n\t\t}\n\t*length = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite Network Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int writeSocketFunction( INOUT NET_STREAM_INFO *netStream, \n\t\t\t\t\t\t\t\tIN_BUFFER( maxLength ) const BYTE *buffer, \n\t\t\t\t\t\t\t\tIN_DATALENGTH const int maxLength, \n\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length,\n\t\t\t\t\t\t\t\tIN_FLAGS_Z( TRANSPORT ) const int flags )\n\t{\n\tMONOTIMER_INFO timerInfo;\n\tconst BYTE *bufPtr = buffer;\n\tconst int timeout = ( flags & TRANSPORT_FLAG_NONBLOCKING ) ? 0 : \\\n\t\t\t\t\t\t( flags & TRANSPORT_FLAG_BLOCKING ) ? \\\n\t\t\t\t\t\tmax( NET_TIMEOUT_WRITE, netStream->timeout ) : \\\n\t\t\t\t\t\tnetStream->timeout;\n\tint bytesToWrite, byteCount = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, maxLength ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckNetStream( netStream ) );\n\tREQUIRES( maxLength > 0 && maxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( ( flags & TRANSPORT_FLAG_NONBLOCKING ) && \\\n\t\t\t\ttimeout == 0 ) || \\\n\t\t\t  ( !( flags & TRANSPORT_FLAG_NONBLOCKING ) && \\\n\t\t\t\tisIntegerRange( timeout ) ) );\n\tREQUIRES( flags == TRANSPORT_FLAG_NONE || \\\n\t\t\t  flags == TRANSPORT_FLAG_NONBLOCKING || \\\n\t\t\t  flags == TRANSPORT_FLAG_BLOCKING || \\\n\t\t\t  flags == TRANSPORT_FLAG_FLUSH );\n\t\t\t  /* TRANSPORT_FLAG_FLUSH is used by alternative write \n\t\t\t     functions that buffer data, for a socket write there's\n\t\t\t\t always an implicit flush */\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Send data to the remote system.  As with the receive-data code we \n\t   have to work around a large number of quirks and socket \n\t   implementation bugs, although most of the systems that exhibited \n\t   these are now extinct or close to it.  Some very old Winsock stacks \n\t   (Win3.x and early Win95 era) would almost always indicate that a \n\t   socket was writeable even when it wasn't.  Even older (mid-1980s) \n\t   Berkeley-derived implementations could return EWOULDBLOCK on a \n\t   blocking socket if they couldn't get required mbufs so that even if \n\t   select() indicated that the socket was writeable, an actual attempt \n\t   to write would return an error since there were no mbufs available.  \n\n\t   Under Win95 select() could fail to block on a non-blocking socket, \n\t   so that the send() would return EWOULDBLOCK.  One possible reason \n\t   (related to the mbuf problem) for this was that another thread could \n\t   have grabbed memory between the select() and the send() so that there \n\t   was no buffer space available when the send() needed it, although \n\t   this should really have returned WSAENOBUFS rather than \n\t   WSAEWOULDBLOCK.  \n\t   \n\t   There was also a known bug in Win95 (and possibly Win98 as well, \n\t   Q177346) under which a select() would indicate writeability but \n\t   send() would return EWOULDBLOCK.  Another select() executed after the \n\t   failed send() then caused select() to suddenly realise that the \n\t   socket was non-writeable (accidit in puncto, quod non seperatur in \n\t   anno).  \n\t   \n\t   Finally, in some cases send() can return an error but \n\t   WSAGetLastError() indicates that there's no error, so we treat it as \n\t   noise and try again */\n\tstatus = setMonoTimer( &timerInfo, timeout );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MAX_INITCHECK( bytesToWrite = maxLength,\n\t\t\t\t\t\tbytesToWrite > 0 && \\\n\t\t\t\t\t\t\t( timeout <= 0 || \\\n\t\t\t\t\t\t\t  !checkMonoTimerExpired( &timerInfo ) ) )\n\t\t{\n\t\tint bytesWritten;\n\n\t\t/* Wait for the socket to become available */\n\t\tstatus = ioWait( netStream, timeout, \n\t\t\t\t\t\t ( byteCount > 0 ) ? TRUE : FALSE, IOWAIT_WRITE );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* We got a timeout but either there's already data present from \n\t\t\t   a previous read or it's a nonblocking write, so this isn't an\n\t\t\t   error */\n\t\t\tif( byteCount > 0 )\n\t\t\t\t{\n\t\t\t\t*length = byteCount;\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Write the data */\n\t\tclearErrorState();\n\t\tbytesWritten = send( netStream->netSocket, bufPtr, bytesToWrite,\n\t\t\t\t\t\t\t MSG_NOSIGNAL );\n\t\tif( isSocketError( bytesWritten ) )\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\t/* If it's a restartable write due to something like an\n\t\t\t   interrupted system call (or a sockets bug), retry the\n\t\t\t   write */\n\t\t\tif( isRestartableError( netStream->netSocket ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Restartable write, send() indicated error\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n#ifdef __WINDOWS__\n\t\t\t/* If it's a Winsock bug, treat it as a restartable write */\n\t\t\tif( WSAGetLastError() < WSABASEERR )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"send() failed but WSAGetLastError() indicated \"\n\t\t\t\t\t\t\t \"no error, ignoring\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tcontinue;\n\t\t\t\t}\n#endif /* __WINDOWS__ */\n\n\t\t\t/* There was a problem with the write */\n\t\t\treturn( getSocketError( netStream, CRYPT_ERROR_WRITE, &dummy ) );\n\t\t\t}\n\t\tbufPtr += bytesWritten;\n\t\tbytesToWrite -= bytesWritten;\n\t\tbyteCount += bytesWritten;\n\t\tENSURES( bytesToWrite >= 0 && bytesToWrite < maxLength && \\\n\t\t\t\t bytesToWrite < MAX_BUFFER_SIZE );\n\t\tENSURES( byteCount > 0 && byteCount <= maxLength && \\\n\t\t\t\t byteCount < MAX_BUFFER_SIZE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*length = byteCount;\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid setAccessMethodTCPReadWrite( INOUT NET_STREAM_INFO *netStream )\n\t{\n\tassert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( netStream->transportReadFunction, readSocketFunction );\n\tFNPTR_SET( netStream->transportWriteFunction, writeSocketFunction );\n\t}\n#endif /* USE_TCP */\n"
  },
  {
    "path": "deps/cl345/kernel/acl.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tACL Definitions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ACL_DEFINED\n\n#define _ACL_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Type Information\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Bit flags for specifying valid object subtypes.  Since the full field names\n   are rather long, we define a shortened form (only visible within the ACL\n   definitions) that reduces the space required to define them */\n\n#define ST_CTX_CONV\t\t\t\tSUBTYPE_CTX_CONV\n#define ST_CTX_PKC\t\t\t\tSUBTYPE_CTX_PKC\n#define ST_CTX_HASH\t\t\t\tSUBTYPE_CTX_HASH\n#define ST_CTX_MAC\t\t\t\tSUBTYPE_CTX_MAC\n#define ST_CTX_GENERIC\t\t\tSUBTYPE_CTX_GENERIC\n#define ST_CTX_ANY\t\t\t\t( ST_CTX_CONV | ST_CTX_PKC | ST_CTX_HASH | \\\n\t\t\t\t\t\t\t\t  ST_CTX_MAC | ST_CTX_GENERIC )\n\n#define ST_CERT_CERT\t\t\tSUBTYPE_CERT_CERT\n#define ST_CERT_CERTREQ\t\t\tSUBTYPE_CERT_CERTREQ\n#define ST_CERT_REQ_CERT\t\tSUBTYPE_CERT_REQ_CERT\n#define ST_CERT_REQ_REV\t\t\tSUBTYPE_CERT_REQ_REV\n#define ST_CERT_CERTCHAIN\t\tSUBTYPE_CERT_CERTCHAIN\n#define ST_CERT_ATTRCERT\t\tSUBTYPE_CERT_ATTRCERT\n#define ST_CERT_CRL\t\t\t\tSUBTYPE_CERT_CRL\n#define ST_CERT_CMSATTR\t\t\tSUBTYPE_CERT_CMSATTR\n#define ST_CERT_RTCS_REQ\t\tSUBTYPE_CERT_RTCS_REQ\n#define ST_CERT_RTCS_RESP\t\tSUBTYPE_CERT_RTCS_RESP\n#define ST_CERT_OCSP_REQ\t\tSUBTYPE_CERT_OCSP_REQ\n#define ST_CERT_OCSP_RESP\t\tSUBTYPE_CERT_OCSP_RESP\n#define ST_CERT_PKIUSER\t\t\tSUBTYPE_CERT_PKIUSER\n#define ST_CERT_ANY_CERT\t\t( ST_CERT_CERT | ST_CERT_CERTREQ | \\\n\t\t\t\t\t\t\t\t  SUBTYPE_CERT_REQ_CERT | ST_CERT_CERTCHAIN )\n#define ST_CERT_ANY\t\t\t\t( ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | \\\n\t\t\t\t\t\t\t\t  ST_CERT_REQ_REV | ST_CERT_CRL | \\\n\t\t\t\t\t\t\t\t  ST_CERT_CMSATTR | ST_CERT_RTCS_REQ | \\\n\t\t\t\t\t\t\t\t  ST_CERT_RTCS_RESP | ST_CERT_OCSP_REQ | \\\n\t\t\t\t\t\t\t\t  ST_CERT_OCSP_RESP | ST_CERT_PKIUSER )\n\n#define ST_KEYSET_FILE\t\t\tSUBTYPE_KEYSET_FILE\n#define ST_KEYSET_FILE_PARTIAL\tSUBTYPE_KEYSET_FILE_PARTIAL\n#define ST_KEYSET_FILE_RO\t\tSUBTYPE_KEYSET_FILE_READONLY\n#define ST_KEYSET_DBMS\t\t\tSUBTYPE_KEYSET_DBMS\n#define ST_KEYSET_DBMS_STORE\tSUBTYPE_KEYSET_DBMS_STORE\n#define ST_KEYSET_HTTP\t\t\tSUBTYPE_KEYSET_HTTP\n#define ST_KEYSET_LDAP\t\t\tSUBTYPE_KEYSET_LDAP\n#define ST_KEYSET_ANY\t\t\t( ST_KEYSET_FILE | SUBTYPE_KEYSET_FILE_PARTIAL | \\\n\t\t\t\t\t\t\t\t  ST_KEYSET_FILE_RO | ST_KEYSET_DBMS | \\\n\t\t\t\t\t\t\t\t  ST_KEYSET_DBMS_STORE | ST_KEYSET_HTTP | \\\n\t\t\t\t\t\t\t\t  ST_KEYSET_LDAP )\n\n#define ST_ENV_ENV\t\t\t\tSUBTYPE_ENV_ENV\n#define ST_ENV_ENV_PGP\t\t\tSUBTYPE_ENV_ENV_PGP\n#define ST_ENV_DEENV\t\t\tSUBTYPE_ENV_DEENV\n#define ST_ENV_ANY\t\t\t\t( ST_ENV_ENV | ST_ENV_ENV_PGP | ST_ENV_DEENV )\n\n#define ST_DEV_SYSTEM\t\t\tSUBTYPE_DEV_SYSTEM\n#define ST_DEV_P11\t\t\t\tSUBTYPE_DEV_PKCS11\n#define ST_DEV_CAPI\t\t\t\tSUBTYPE_DEV_CRYPTOAPI\n#define ST_DEV_HW\t\t\t\tSUBTYPE_DEV_HARDWARE\n#define ST_DEV_ANY_STD\t\t\t( ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW )\n#define ST_DEV_ANY\t\t\t\t( ST_DEV_ANY_STD | ST_DEV_SYSTEM )\n\n#define ST_SESS_SSH\t\t\t\tSUBTYPE_SESSION_SSH\n#define ST_SESS_SSH_SVR\t\t\tSUBTYPE_SESSION_SSH_SVR\n#define ST_SESS_SSL\t\t\t\tSUBTYPE_SESSION_SSL\n#define ST_SESS_SSL_SVR\t\t\tSUBTYPE_SESSION_SSL_SVR\n#define ST_SESS_RTCS\t\t\tSUBTYPE_SESSION_RTCS\n#define ST_SESS_RTCS_SVR\t\tSUBTYPE_SESSION_RTCS_SVR\n#define ST_SESS_OCSP\t\t\tSUBTYPE_SESSION_OCSP\n#define ST_SESS_OCSP_SVR\t\tSUBTYPE_SESSION_OCSP_SVR\n#define ST_SESS_TSP\t\t\t\tSUBTYPE_SESSION_TSP\n#define ST_SESS_TSP_SVR\t\t\tSUBTYPE_SESSION_TSP_SVR\n#define ST_SESS_CMP\t\t\t\tSUBTYPE_SESSION_CMP\n#define ST_SESS_CMP_SVR\t\t\tSUBTYPE_SESSION_CMP_SVR\n#define ST_SESS_SCEP\t\t\tSUBTYPE_SESSION_SCEP\n#define ST_SESS_SCEP_SVR\t\tSUBTYPE_SESSION_SCEP_SVR\n#define ST_SESS_CERT_SVR\t\tSUBTYPE_SESSION_CERT_SVR\n#define ST_SESS_ANY_SVR\t\t\t( ST_SESS_SSH_SVR | ST_SESS_SSL_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_RTCS_SVR | ST_SESS_OCSP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_TSP_SVR | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_SCEP_SVR | ST_SESS_CERT_SVR )\n#define ST_SESS_ANY_CLIENT\t\t( ST_SESS_SSH | ST_SESS_SSL | ST_SESS_RTCS | \\\n\t\t\t\t\t\t\t\t  ST_SESS_OCSP | ST_SESS_TSP | ST_SESS_CMP | \\\n\t\t\t\t\t\t\t\t  ST_SESS_SCEP )\n#define ST_SESS_ANY_DATA\t\t( ST_SESS_SSH | ST_SESS_SSH_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_SSL | ST_SESS_SSL_SVR )\n#define ST_SESS_ANY_REQRESP\t\t( ST_SESS_RTCS | ST_SESS_RTCS_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_OCSP | ST_SESS_OCSP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_TSP | ST_SESS_TSP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_CMP | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_SCEP | ST_SESS_SCEP_SVR | \\\n\t\t\t\t\t\t\t\t  ST_SESS_CERT_SVR )\n#define ST_SESS_ANY_SEC\t\t\t( ST_SESS_ANY_DATA | \\\n\t\t\t\t\t\t\t\t  ST_SESS_CMP | ST_SESSION_CMP_SVR )\n#define ST_SESS_ANY\t\t\t\t( ST_SESS_ANY_CLIENT | ST_SESS_ANY_SVR )\n\n#define ST_USER_NORMAL\t\t\tSUBTYPE_USER_NORMAL\n#define ST_USER_SO\t\t\t\tSUBTYPE_USER_SO\n#define ST_USER_CA\t\t\t\tSUBTYPE_USER_CA\n#define ST_USER_ANY\t\t\t\t( ST_USER_NORMAL | ST_USER_SO | ST_USER_CA )\n\n/* Subtype values that allow access for any object subtype and for no\n   object subtypes */\n\n#define ST_ANY_A\t\t\t\t( ST_CTX_ANY | ST_CERT_ANY )\n#define ST_ANY_B\t\t\t\t( ST_ENV_ANY | ST_KEYSET_ANY | ST_DEV_ANY )\n#define ST_ANY_C\t\t\t\t( ST_SESS_ANY | ST_USER_ANY )\n#define ST_NONE\t\t\t\t\t0\n\n/* Sometimes it's easier to specify a collection of object types as the \n   entire family modulo a single type, for example ST_CERT_ANY except for\n   ST_CERT_PKIUSER.  To do this we use the following macro, which extracts\n   the bits of the exception value that we want to turn off an uses them\n   as a mask for the family value */\n\n#define MK_ST_EXCEPTION( family, exception ) \\\n\t\t( ( family ) & ~( ( exception ) & ~0x70000000L ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAccess Permission Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"acl_perm.h\"\n#else\n  #include \"kernel/acl_perm.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRouting Information\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Routing types, which specify the routing used for the message.  This\n   routing applies not only for attribute manipulation messages but for all\n   messages in general, so that some of the routing types defined below only\n   apply for non-attribute messages.  The routing types are:\n\n\tROUTE_NONE\n\t\tNot routed (the message or attribute is valid for any object type).\n\n\tROUTE( target )\n\tROUTE_ALT( target, altTarget )\n\tROUTE_ALT2( target, altTarget1, altTarget2 )\n\t\tFixed-target messages always routed to a particular object type or\n\t\tset of types (e.g. a certificate attribute is always routed to a\n\t\tcertificate object; a generate key message is always routed to a\n\t\tcontext).  In some cases alternative targets are possible, e.g. a\n\t\tget-key message can be sent to a keyset or a device.\n\n\tROUTE_FIXED( target )\n\tROUTE_FIXED_ALT( target, altTarget )\n\t\tNot routed, but checked to make sure that they're addressed to the\n\t\trequired target type.  These message types aren't routed because\n\t\tthey're specific to a particular object and are explicitly\n\t\tunroutable.  For example, a get key message sent to a cert or\n\t\tcontext tied to a device shouldn't be forwarded on to the device,\n\t\tsince it would result in the cert acting as a keyset.  This is\n\t\ttheoretically justifiable - \"Get me another cert from the same place\n\t\tthat this one came from\" - but it's stretching the orthogonality of\n\t\tobjects a bit far.\n\n\tROUTE_IMPLICIT\n\t\tFor object attribute manipulation messages, implicitly routed by\n\t\tattribute type.\n\n\tROUTE_SPECIAL( routingFunction )\n\t\tSpecial-case, message-dependent routing */\n\n#define ROUTE_NONE \\\n\t\tOBJECT_TYPE_NONE, NULL\n#define ROUTE( target ) \\\n\t\t( target ), findTargetType\n#define ROUTE_ALT( target, altTarget ) \\\n\t\t( target ) | ( ( altTarget ) << 8 ), findTargetType\n#define ROUTE_ALT2( target, altTarget1, altTarget2 ) \\\n\t\t( target ) | ( ( altTarget1 ) << 8 ) | ( ( altTarget2 ) << 16 ), findTargetType\n#define ROUTE_FIXED( target ) \\\n\t\t( target ), checkTargetType\n#define ROUTE_FIXED_ALT( target, altTarget ) \\\n\t\t( target ) | ( ( altTarget ) << 8 ), checkTargetType\n#define ROUTE_IMPLICIT \\\n\t\tOBJECT_TYPE_LAST, findTargetType\n#define ROUTE_SPECIAL( function ) \\\n\t\tOBJECT_TYPE_NONE, ( route##function )\n\n/* Macros to determine which type of routing to apply */\n\n#define isImplicitRouting( target )\t\t( ( target ) == OBJECT_TYPE_LAST )\n#define isExplicitRouting( target )\t\t( ( target ) == OBJECT_TYPE_NONE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tValue Range Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The value range (for numeric or boolean values) or length range (for\n   variable-length data).  Some values aren't amenable to a simple range\n   check so we also allow various extended types of checking.  To denote that\n   an extended check needs to be performed, we set the low range value to\n   RANGE_EXT_MARKER and the high range value to an indicator of the type of\n   check to be performed.  The range types are:\n\n\tRANGE_ANY\n\t\tAllow any value\n\tRANGE_ALLOWEDVALUES\n\t\textendedInfo contains int [] of allowed values, terminated by\n\t\tCRYPT_ERROR\n\tRANGE_SUBRANGES\n\t\textendedInfo contains subrange [] of allowed subranges, terminated\n\t\tby { CRYPT_ERROR, CRYPT_ERROR }\n\tRANGE_SUBTYPED\n\t\textendedInfo contains sub-acl [] of object type-specific sub-ACLs.\n\t\tThe main ACL is only used as a general template for checks, the real\n\t\tchecking is done via recursive application of the sub-ACL for the\n\t\tspecific object sub-type */\n\ntypedef enum {\n\tRANGEVAL_NONE,\t\t\t\t\t/* No range type */\n\tRANGEVAL_ANY,\t\t\t\t\t/* Any value allowed */\n\tRANGEVAL_ALLOWEDVALUES,\t\t\t/* List of permissible values */\n\tRANGEVAL_SUBRANGES,\t\t\t\t/* List of permissible subranges */\n\tRANGEVAL_SUBTYPED,\t\t\t\t/* Object-subtype-specific sub-ACL */\n\tRANGEVAL_LAST\t\t\t\t\t/* Last valid range type */\n\t} RANGEVAL_TYPE;\n\n#define RANGE_EXT_MARKER\t( -1000 )/* Marker to denote extended range value */\n\n#define RANGE_ANY\t\t\tRANGE_EXT_MARKER, RANGEVAL_ANY\n#define RANGE_ALLOWEDVALUES\tRANGE_EXT_MARKER, RANGEVAL_ALLOWEDVALUES\n#define RANGE_SUBRANGES\t\tRANGE_EXT_MARKER, RANGEVAL_SUBRANGES\n#define RANGE_SUBTYPED\t\tRANGE_EXT_MARKER, RANGEVAL_SUBTYPED\n#define RANGE( low, high )\t( low ), ( high )\n\n/* The maximum possible integer value, used to indicate that any value is\n   allowed (e.g. when returning device-specific error codes).  Note that\n   this differs from the MAX_INTLENGTH value defined in crypt.h, which\n   defines the maximum data length value that can be safely specified by a\n   signed integer */\n\n#define RANGE_MAX\t\t\t( INT_MAX - 128 )\n\n/* Data structures to contain special-case range information */\n\ntypedef struct { const int lowRange, highRange; } RANGE_SUBRANGE_TYPE;\n\n/* Macro to check whether it's an extended range and to extract the special\n   range type */\n\n#define isSpecialRange( attributeACL ) \\\n\t\t( ( attributeACL )->lowRange == RANGE_EXT_MARKER )\n#define getSpecialRangeType( attributeACL )\t( ( attributeACL )->highRange )\n#define getSpecialRangeInfo( attributeACL )\t( ( attributeACL )->extendedInfo )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tACL Flags\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Flags for attribute ACLs:\n\n\tFLAG_OBJECTPROPERTY\n\t\tThis is an object property attribute which is handled by the kernel\n\t\trather than being forwarded to the object.\n\n\tFLAG_TRIGGER\n\t\tSuccessfully setting this attribute triggers a change from the low to\n\t\tthe high state */\n\n#define ATTRIBUTE_FLAG_NONE\t\t0x00\n#define ATTRIBUTE_FLAG_PROPERTY\t0x01\n#define ATTRIBUTE_FLAG_TRIGGER\t0x02\n#define ATTRIBUTE_FLAG_LAST\t\t0x04\n\n/* Miscellaneous ACL flags:\n\n\tFLAG_LOW_STATE\n\tFLAG_HIGH_STATE\n\tFLAG_ANY_STATE\n\t\tWhether the object should be in a particular state.\n\n\tFLAG_ROUTE_TO_CTX\n\tFLAG_ROUTE_TO_CERT\n\t\tWhether routing should be applied to an object to locate an\n\t\tunderlying object (e.g. a PKC object for a certificate or a\n\t\tcertificate for a PKC object).  The need to apply routing is\n\t\tunfortunate but is required in order to apply the subtype check to\n\t\tPKC/cert objects, sorting out which (pre-routed) object types are\n\t\tpermissible is beyond the scope of the ACL validation routines,\n\t\twhich would have to take into consideration the intricacies of all\n\t\tmanner of certificate objects paired with public and private keys */\n\n#define ACL_FLAG_NONE\t\t\t0x00\n#define ACL_FLAG_LOW_STATE\t\t0x01\n#define ACL_FLAG_HIGH_STATE\t\t0x02\n#define ACL_FLAG_ANY_STATE\t\t0x03\n#define ACL_FLAG_ROUTE_TO_CTX\t0x04\n#define ACL_FLAG_ROUTE_TO_CERT\t0x08\n\n#define ACL_FLAG_MASK\t\t\t0x0F\n#define ACL_FLAG_STATE_MASK\t\t0x03\n\n/* Macros to check the misc.ACL flags */\n\n#define checkObjectState( flags, objectHandle ) \\\n\t\t( ( ( flags & ACL_FLAG_LOW_STATE ) && \\\n\t\t\t  !isInHighState( objectHandle ) ) || \\\n\t\t  ( ( flags & ACL_FLAG_HIGH_STATE ) && \\\n\t\t\t  isInHighState( objectHandle ) ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute ACL Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The attribute's type, for attribute ACLs.  The basic values are boolean,\n   numeric, or byte string, there are also some special types such as object\n   handles that place extra constraints on the attribute */\n\ntypedef enum {\n\tATTRIBUTE_VALUE_NONE,\t\t\t/* Non-value */\n\tATTRIBUTE_VALUE_BOOLEAN,\t\t/* Boolean flag */\n\tATTRIBUTE_VALUE_NUMERIC,\t\t/* Numeric value */\n\tATTRIBUTE_VALUE_STRING,\t\t\t/* Byte string */\n\tATTRIBUTE_VALUE_WCSTRING,\t\t/* (Possible) widechar string */\n\tATTRIBUTE_VALUE_OBJECT,\t\t\t/* Object handle */\n\tATTRIBUTE_VALUE_TIME,\t\t\t/* Timestamp */\n\tATTRIBUTE_VALUE_SPECIAL,\t\t/* Special-case value with sub-ACLs */\n\tATTRIBUTE_VALUE_LAST\t\t\t/* Last attribute value type */\n\t} ATTRIBUTE_VALUE_TYPE;\n\n/* Attribute ACL entry.  If the code is compiled in debug mode, we also add\n   the attribute type, which is used for an internal consistency check */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\n\tint ( *ROUTING_FUNCTION )( IN_HANDLE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\t\t\t   OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\tCRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\t\t\t   const long targets );\n\ntypedef struct {\n#ifndef NDEBUG\n\t/* The attribute type, used for consistency checking */\n\tconst CRYPT_ATTRIBUTE_TYPE attribute;/* Attribute */\n#endif /* NDEBUG */\n\n\t/* Attribute type checking information: The attribute value type and\n\t   object subtypes for which the attribute is valid */\n\tconst ATTRIBUTE_VALUE_TYPE valueType;/* Attribute value type */\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\t\t\t\t\t\t\t\t\t/* Object subtypes for which attr.valid */\n\n\t/* Access information: The type of access and object states that are\n\t   permitted, and attribute flags for this attribute */\n\tconst int access;\t\t\t\t/* Permitted access type */\n\tconst int flags;\t\t\t\t/* Attribute flags */\n\n\t/* Routing information: The object type (or types, packed into a single\n\t   value if there are more than one type) that the attribute applies to,\n\t   and the routing function applied to the attribute message */\n\tconst long routingTarget;\t\t/* Target type(s) if routable */\n\tROUTING_FUNCTION routingFunction;\n\n\t/* Attribute value checking information */\n\tconst int lowRange;\t\t\t\t/* Min/max allowed if numeric/boolean, */\n#ifdef SYSTEM_16BIT\n\tconst long highRange;\t\t\t/*\tlength if string */\n#else\n\tconst int highRange;\t\t\t/*\tlength if string */\n#endif /* 16- vs. 32-bit systems */\n\tconst void *extendedInfo;\t\t/* Extended ACL/checking information */\n\t} ATTRIBUTE_ACL;\n\n/* Macros to set up attribute ACL's.  We have one for each of the basic types\n   and two general-purpose ones that provide more control over the values */\n\n#ifndef NDEBUG\n  /* Standard ACL entries */\n  #define MKACL_B( attribute, subTypeA, subTypeB, subTypeC, access, routing ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_BOOLEAN, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, FALSE, TRUE, NULL }\n  #define MKACL_N( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_NUMERIC, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, range, NULL }\n  #define MKACL_S( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, range, NULL }\n  #define MKACL_WCS( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_WCSTRING, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, range, NULL }\n  #define MKACL_O( attribute, subTypeA, subTypeB, subTypeC, access, routing, type ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_OBJECT, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, 0, 0, type }\n  #define MKACL_T( attribute, subTypeA, subTypeB, subTypeC, access, routing ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_TIME, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, 0, 0, NULL }\n  #define MKACL_X( attribute, subTypeA, subTypeB, subTypeC, access, routing, subACL ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_SPECIAL, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, RANGE_SUBTYPED, subACL }\n\n  /* Extended types */\n  #define MKACL_B_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_BOOLEAN, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  flags, routing, FALSE, TRUE, NULL }\n  #define MKACL_N_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_NUMERIC, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  flags, routing, range, NULL }\n  #define MKACL_S_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  flags, routing, range, NULL }\n  #define MKACL_O_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, type ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_OBJECT, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  flags, routing, 0, 0, type }\n  #define MKACL_X_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, subACL ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_SPECIAL, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  flags, routing, RANGE_SUBTYPED, subACL }\n\n  /* General-purpose ACL macros */\n  #define MKACL( attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_EX( attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range, allowed ) \\\n\t\t\t{ attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, range, allowed }\n\n  /* End-of-ACL canary */\n  #define MKACL_END() \\\n\t\t\t{ CRYPT_ERROR, ATTRIBUTE_VALUE_NONE, 0, 0, 0, ACCESS_xxx_xxx, \\\n\t\t\t  0, 0, NULL, 0, 0, NULL }\n\n  /* End-of-ACL marker, used to terminate variable-length sub-ACL lists.  The\n     ST_ANY_A/B/C match ensures that it matches any object types */\n  #define MKACL_END_SUBACL() \\\n\t\t\t{ CRYPT_ERROR, ATTRIBUTE_VALUE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, ACCESS_xxx_xxx, \\\n\t\t\t  0, 0, NULL, 0, 0, NULL }\n#else\n  /* Standard ACL entries */\n  #define MKACL_B( attribute, subTypeA, subTypeB, subTypeC, access, routing ) \\\n\t\t\t{ ATTRIBUTE_VALUE_BOOLEAN, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, FALSE, TRUE, NULL }\n  #define MKACL_N( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_NUMERIC, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_S( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_WCS( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_WCSTRING, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_O( attribute, subTypeA, subTypeB, subTypeC, access, routing, type ) \\\n\t\t\t{ ATTRIBUTE_VALUE_OBJECT, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, 0, 0, type }\n  #define MKACL_T( attribute, subTypeA, subTypeB, subTypeC, access, routing ) \\\n\t\t\t{ ATTRIBUTE_VALUE_TIME, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, 0, 0, NULL }\n  #define MKACL_X( attribute, subTypeA, subTypeB, subTypeC, access, routing, subACL ) \\\n\t\t\t{ ATTRIBUTE_VALUE_SPECIAL, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, RANGE_SUBTYPED, subACL }\n\n  /* Extended types */\n  #define MKACL_B_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing ) \\\n\t\t\t{ ATTRIBUTE_VALUE_BOOLEAN, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, FALSE, TRUE, NULL }\n  #define MKACL_N_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_NUMERIC, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_S_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, range, NULL }\n  #define MKACL_O_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, type ) \\\n\t\t\t{ ATTRIBUTE_VALUE_OBJECT, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, 0, 0, type }\n  #define MKACL_X_EX( attribute, subTypeA, subTypeB, subTypeC, access, flags, routing, subACL ) \\\n\t\t\t{ ATTRIBUTE_VALUE_SPECIAL, subTypeA, subTypeB, subTypeC, access, flags, \\\n\t\t\t  routing, RANGE_SUBTYPED, subACL }\n\n  /* General-purpose ACL macros */\n  #define MKACL( attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range ) \\\n\t\t\t{ valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range, NULL }\n  #define MKACL_EX( attribute, valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range, allowed ) \\\n\t\t\t{ valueType, subTypeA, subTypeB, subTypeC, access, flags, routing, range, allowed }\n\n  /* End-of-ACL canary */\n  #define MKACL_END() \\\n\t\t\t{ ATTRIBUTE_VALUE_NONE, 0, 0, 0, ACCESS_xxx_xxx, \\\n\t\t\t  0, 0, NULL, 0, 0, NULL }\n\n  /* End-of-ACL marker, used to terminate variable-length sub-ACL lists.  The\n     ST_ANY_A/B/C match ensures that it matches any object types */\n  #define MKACL_END_SUBACL() \\\n\t\t\t{ ATTRIBUTE_VALUE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, ACCESS_xxx_xxx, \\\n\t\t\t  0, 0, NULL, 0, 0, NULL }\n#endif /* NDEBUG */\n\n/* The attribute ACLs are usually implemented as a lookup table, but in some\n   cases we may use sparse ACLs to handle special-case situations where only\n   a few attributes need to be checked.  In order to locate the appropriate\n   ACL entry, the 'attribute' member (normally only used for debugging\n   purposes) needs to be present.  To handle this, we define an alternative\n   ACL entry entry type (and associated setup macros) that differs from the\n   standard one in that the attribute member is present unconditionally.\n\n   In addition to this, the \"attribute\" being checked may not be a standard \n   attribute but some other enumerated type, so we have to make the \n   supposed attribute a typeless 'int' to avoid type-conversion issues \n   (CRYPT_ATTRIBUTE_TYPE has an artificial member set to INT_MAX to make \n   sure that it's the same size as an integer for compilers with variable-\n   width enums).\n\n   We have to be especially careful here because the parent type differs\n   depending on whether it's a normal or debug build.  For the debug build\n   the 'attribute' member is present at the start, for the release build\n   it's absent so we place it at the end where it doesn't interfere with the\n   other struct members */\n\ntypedef struct {\n#ifndef NDEBUG\n\tconst int /*CRYPT_ATTRIBUTE_TYPE*/ attribute;/* Attribute */\n#endif /* !NDEBUG */\n\tconst ATTRIBUTE_VALUE_TYPE valueType;/* Attribute value type */\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\tconst int access;\t\t\t\t/* Permitted access type */\n\tconst int flags;\t\t\t\t/* Attribute flags */\n\tconst long routingTarget;\t\t/* Target type if routable */\n\tROUTING_FUNCTION routingFunction;\n\tconst int lowRange;\t\t\t\t/* Min/max allowed if numeric/boolean, */\n\tconst int highRange;\t\t\t/*\tlength if string */\n\tconst void *extendedInfo;\t\t/* Extended access information */\n#ifdef NDEBUG\n\tconst int /*CRYPT_ATTRIBUTE_TYPE*/ attribute;/* Attribute */\n#endif /* NDEBUG */\n\t} ATTRIBUTE_ACL_ALT;\n\n#ifndef NDEBUG\n  #define MKACL_S_ALT( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ attribute, ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, \\\n\t\t\t  0, routing, range, NULL }\n#else\n  #define MKACL_S_ALT( attribute, subTypeA, subTypeB, subTypeC, access, routing, range ) \\\n\t\t\t{ ATTRIBUTE_VALUE_STRING, subTypeA, subTypeB, subTypeC, access, 0, \\\n\t\t\t  routing, range, NULL, attribute }\n#endif /* !NDEBUG */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyset ACL Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key management ACL entry */\n\ntypedef struct {\n\t/* The item type */\n\tconst KEYMGMT_ITEM_TYPE itemType;/* Key management item type */\n\n\t/* Valid keyset types and access types for this item type.  This is a \n\t   matrix giving keyset types for which read/write/delete (R/W/D), \n\t   getFirst/Next (FN), and query (Q) access are valid */\n\tconst OBJECT_SUBTYPE keysetR_subTypeA, keysetR_subTypeB, keysetR_subTypeC;\n\tconst OBJECT_SUBTYPE keysetW_subTypeA, keysetW_subTypeB, keysetW_subTypeC;\n\tconst OBJECT_SUBTYPE keysetD_subTypeA, keysetD_subTypeB, keysetD_subTypeC;\n\tconst OBJECT_SUBTYPE keysetFN_subTypeA, keysetFN_subTypeB, keysetFN_subTypeC;\n\tconst OBJECT_SUBTYPE keysetQ_subTypeA, keysetQ_subTypeB, keysetQ_subTypeC;\n\n\t/* Permitted object types, key IDs, and key management flags for this \n\t   item type */\n\tconst OBJECT_SUBTYPE objSubTypeA, objSubTypeB, objSubTypeC;\n\t\t\t\t\t\t\t\t\t/* Permitted object types for item */\n\tconst CRYPT_KEYID_TYPE *allowedKeyIDs;\t/* Permitted key IDs */\n\tconst int allowedFlags;\t\t\t/* Permitted key management flags */\n\n\t/* Parameter flags for the mechanism information.  These define which\n\t   types of optional/mandatory parameters can and can't be present,\n\t   using an extended form of the ACCESS_xxx flags to indicate whether\n\t   the parameter is required or not/permitted or not for read, write,\n\t   and delete messages */\n\tconst int idUseFlags;\t\t\t/* ID required/not permitted */\n\tconst int pwUseFlags;\t\t\t/* Password required/not permitted */\n\n\t/* In the case of public/private keys the general-purpose ACL entries\n\t   aren't quite specific enough since some keysets require specific\n\t   types of certificates while others require generic public-key objects.\n\t   In the latter case they can have almost any kind of certificate object\n\t   attached, which doesn't matter when we're interested only in the\n\t   public key but does matter if we want a specific type of cert.  If we\n\t   want a specific cert type, we specify the subset of keysets that this\n\t   applies to and the cert type(s) here */\n\tconst OBJECT_SUBTYPE specificKeysetSubTypeA, specificKeysetSubTypeB, \\\n\t\t\t\t\t\t specificKeysetSubTypeC;\n\tconst OBJECT_SUBTYPE specificObjSubTypeA, specificObjSubTypeB, \\\n\t\t\t\t\t\t specificObjSubTypeC;\n\t} KEYMGMT_ACL;\n\n/* Macros to set up key management ACLs.  The basic form treats the RWD and\n   FnQ groups as one value, the _RWD form specifies individual RWD and FnQ\n   values, and the _EX form adds special-case checking for specific object\n   types that must be written to some keyset types */\n\n#define MK_KEYACL( itemType, keysetRWDSubType, keysetFNQSubType, \\\n\t\t\t\t   objectSubType, keyIDs, flags, idUseFlags, pwUseFlags ) \\\n\t\t\t{ itemType, ST_NONE, keysetRWDSubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetRWDSubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetRWDSubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetFNQSubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetFNQSubType, ST_NONE, \\\n\t\t\t  objectSubType, ST_NONE, ST_NONE, \\\n\t\t\t  keyIDs, flags, idUseFlags, pwUseFlags, \\\n\t\t\t  ST_NONE, ST_NONE, ST_NONE, ST_NONE, ST_NONE, ST_NONE }\n#define MK_KEYACL_RWD( itemType, keysetR_SubType, keysetW_SubType, keysetD_SubType, \\\n  \t\t\t\t\t   keysetFN_SubType, keysetQ_SubType, objectSubType, keyIDs, \\\n\t\t\t\t\t   flags, idUseFlags, pwUseFlags ) \\\n\t\t\t{ itemType, ST_NONE, keysetR_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetW_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetD_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetFN_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetQ_SubType, ST_NONE, \\\n\t\t\t  objectSubType, ST_NONE, ST_NONE, \\\n\t\t\t  keyIDs, flags, idUseFlags, pwUseFlags, \\\n\t\t\t  ST_NONE, ST_NONE, ST_NONE, ST_NONE, ST_NONE, ST_NONE }\n#define MK_KEYACL_EX( itemType, keysetR_SubType, keysetW_SubType, keysetD_SubType, \\\n  \t\t\t\t\t  keysetFN_SubType, keysetQ_SubType, objectSubType, keyIDs, \\\n\t\t\t\t\t  flags, idUseFlags, pwUseFlags, specificKeysetType, \\\n\t\t\t\t\t  specificObjectType ) \\\n\t\t\t{ itemType, ST_NONE, keysetR_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetW_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetD_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetFN_SubType, ST_NONE, \\\n\t\t\t  ST_NONE, keysetQ_SubType, ST_NONE, \\\n\t\t\t  objectSubType, ST_NONE, ST_NONE, \\\n\t\t\t  keyIDs, flags, idUseFlags, pwUseFlags, \\\n\t\t\t  ST_NONE, specificKeysetType, ST_NONE, \\\n\t\t\t  specificObjectType, ST_NONE, ST_NONE }\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tParameter ACL Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The parameter's type.  The basic values are boolean, numeric, or byte\n   string, there are also some special types such as object handles that\n   place extra constraints on the attribute */\n\ntypedef enum {\n\tPARAM_VALUE_NONE,\t\t\t\t/* Non-value */\n\tPARAM_VALUE_NUMERIC,\t\t\t/* Numeric value */\n\tPARAM_VALUE_STRING,\t\t\t\t/* Byte string */\n\tPARAM_VALUE_STRING_OPT,\t\t\t/* Byte string or (NULL, 0) */\n\tPARAM_VALUE_STRING_NONE,\t\t/* Empty (NULL, 0) string */\n\tPARAM_VALUE_OBJECT,\t\t\t\t/* Object handle */\n\tPARAM_VALUE_LAST\t\t\t\t/* Last valid parameter type */\n\t} PARAM_VALUE_TYPE;\n\n/* Parameter ACL entry, which defines the type and valid values for a\n   message parameter.  This ACL type is used as a sub-ACL in a variety of\n   other kernel ACLs */\n\ntypedef struct {\n\tconst PARAM_VALUE_TYPE valueType;/* Parameter value type */\n\tconst int lowRange, highRange;\t/* Min/max value or length */\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\t\t\t\t\t\t\t\t\t/* Object subtypes for which param.valid */\n\tconst int flags;\t\t\t\t/* ACL flags */\n\t} PARAM_ACL;\n\n/* Macros to set up parameter ACLs */\n\n#define MKACP_B() \\\n\t\t\t{ PARAM_VALUE_NUMERIC, FALSE, TRUE, 0, 0, 0, 0 }\n#define MKACP_N( min, max ) \\\n\t\t\t{ PARAM_VALUE_NUMERIC, min, max, 0, 0, 0, 0 }\n#define MKACP_N_FIXED( value ) \\\n\t\t\t{ PARAM_VALUE_NUMERIC, value, value, 0, 0, 0, 0 }\n#define MKACP_S( minLen, maxLen ) \\\n\t\t\t{ PARAM_VALUE_STRING, minLen, maxLen, 0, 0, 0, 0 }\n#define MKACP_S_OPT( minLen, maxLen ) \\\n\t\t\t{ PARAM_VALUE_STRING_OPT, minLen, maxLen, 0, 0, 0, 0 }\n#define MKACP_S_NONE() \\\n\t\t\t{ PARAM_VALUE_STRING_NONE, 0, 0, 0, 0, 0, 0 }\n#define MKACP_O( subTypeA, flags ) \\\n\t\t\t{ PARAM_VALUE_OBJECT, 0, 0, subTypeA, ST_NONE, ST_NONE, flags }\n#define MKACP_O_NONE() \\\n\t\t\t{ PARAM_VALUE_NUMERIC, CRYPT_UNUSED, CRYPT_UNUSED, 0, 0, 0, 0 }\n\n/* End-of-mechanism-ACL marker */\n\n#define MKACP_END() \\\n\t\t\t{ PARAM_VALUE_NONE, 0, 0, 0, 0, 0 }\n\n/* Macro to access the parameter ACL information for a given parameter in a\n   list of parameter ACLs */\n\n#define paramInfo( parentACL, paramNo )\t\tparentACL->paramACL[ paramNo ]\n\n/* Macro to get the subtype of an object */\n\n#define objectST( objectHandle )\t\t\tobjectTable[ objectHandle ].subType\n\n/* Macros to check each parameter against a parameter ACL entry */\n\n#define checkParamNumeric( paramACL, value ) \\\n\t\t( paramACL.valueType == PARAM_VALUE_NUMERIC && \\\n\t\t  ( value >= paramACL.lowRange && value <= paramACL.highRange ) )\n\n#define checkParamString( paramACL, data, dataLen ) \\\n\t\t( ( ( paramACL.valueType == PARAM_VALUE_STRING_NONE || \\\n\t\t\t  paramACL.valueType == PARAM_VALUE_STRING_OPT ) && \\\n\t\t\tdata == NULL && dataLen == 0 ) || \\\n\t\t  ( ( paramACL.valueType == PARAM_VALUE_STRING || \\\n\t\t\t  paramACL.valueType == PARAM_VALUE_STRING_OPT ) && \\\n\t\t\t( dataLen >= paramACL.lowRange && \\\n\t\t\t  dataLen <= paramACL.highRange ) && \\\n\t\t\tisReadPtr( data, dataLen ) ) )\n\n#define checkParamObject( paramACL, objectHandle ) \\\n\t\t( ( paramACL.valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\tparamACL.lowRange == CRYPT_UNUSED && \\\n\t\t\tobjectHandle == CRYPT_UNUSED ) || \\\n\t\t  ( paramACL.valueType == PARAM_VALUE_OBJECT && \\\n\t\t\t( ( paramACL.subTypeA & objectST( objectHandle ) ) == \\\n\t\t\t\t\t\t\t\t\tobjectST( objectHandle ) || \\\n\t\t\t  ( paramACL.subTypeB & objectST( objectHandle ) ) == \\\n\t\t\t\t\t\t\t\t\tobjectST( objectHandle ) || \\\n\t\t\t  ( paramACL.subTypeC & objectST( objectHandle ) ) == \\\n\t\t\t\t\t\t\t\t\tobjectST( objectHandle ) ) && \\\n\t\t\tcheckObjectState( paramACL.flags, objectHandle ) ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc.ACL Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Object ACL entry for object parameters for messages.  This is used as a\n   composite entry in various ACLs that apply to objects */\n\ntypedef struct {\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\t\t\t\t\t\t\t\t\t/* Object subtypes for which attr.valid */\n\tconst int flags;\t\t\t\t/* ACL flags */\n\t} OBJECT_ACL;\n\n/* Message ACL entry */\n\ntypedef struct {\n\tconst MESSAGE_TYPE type;\t\t/* Message type */\n\tconst OBJECT_ACL objectACL;\t\t/* Valid objects for message type */\n\t} MESSAGE_ACL;\n\n/* Mechanism ACL entry */\n\ntypedef struct {\n\tconst MECHANISM_TYPE type;\t\t/* Mechanism type */\n\tconst PARAM_ACL paramACL[ 6 ];\t/* Parameter ACL information */\n\t} MECHANISM_ACL;\n\n/* Create-object ACL entry */\n\ntypedef struct CRA {\n\tconst OBJECT_TYPE type;\t\t\t/* Object type */\n\tconst PARAM_ACL paramACL[ 5 ];\t/* Parameter ACL information */\n\tconst int exceptions[ 4 ];\t\t/* Subtypes that need special handling */\n\tconst struct CRA *exceptionACL;\t/* Special-handling ACL */\n\t} CREATE_ACL;\n\n/* Cert mgmt.ACL entry.  These have parameters that work similarly to the\n   mechanism ACLs, except that only a small subset (objects and unused) are\n   used in practice.  In addition some objects require the presence of\n   secondary objects (dependent objects for the main object), for example\n   a CA's PKC context requires an attached CA certificate.  This is\n   specified in the secondary parameter ACL, which mirrors the main\n   parameter ACL */\n\ntypedef struct {\n\tconst CRYPT_CERTACTION_TYPE action;\t/* Cert mgmt.action */\n\tconst int access;\t\t\t\t/* Permitted access type */\n\tconst PARAM_ACL paramACL[ 3 ];\t/* Parameter ACL information */\n\tconst PARAM_ACL secParamACL[ 3 ];/* Parameter ACL for dep.objects */\n\t} CERTMGMT_ACL;\n\n/* Compare-message ACL entry */\n\ntypedef struct {\n\tconst MESSAGE_COMPARE_TYPE compareType;\t/* Compare message type */\n\tconst OBJECT_ACL objectACL;\t\t/* Valid objects for message type */\n\tconst PARAM_ACL paramACL[ 1 ];\t/* Parameter ACL information */\n\t} COMPARE_ACL;\n\n/* Macros to access the parameter ACLs as an array of PARAM_ACL entries */\n\n#define getParamACL( aclInfo )\t\t( &( aclInfo )->paramACL[ 0 ] )\n#define getParamACLSize( aclInfo )\t( sizeof( ( aclInfo )->paramACL ) / sizeof( PARAM_ACL ) )\n\n/* Macros to set up compare ACLs */\n\n#define MK_CMPACL_S( objSTA, lowRange, highRange ) \\\n\t\t\t{ objSTA, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE }, \\\n\t\t\t{ MKACP_S( lowRange, highRange ) }\n#define MK_CMPACL_O( objSTA, pObjSTA ) \\\n\t\t\t{ objSTA, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE }, \\\n\t\t\t{ MKACP_O( pObjSTA, ACL_FLAG_HIGH_STATE ) }\n#define MK_CMPACL_END() \\\n\t\t\t{ ST_NONE, ST_NONE, ST_NONE, ACL_FLAG_NONE }, \\\n\t\t\t{ MKACP_END() }\n\n/* Check-message ACL entry */\n\ntypedef struct {\n\tconst MESSAGE_CHECK_TYPE checkType;\t/* Check message type */\n\tconst MESSAGE_TYPE actionType;\t/* Action corresponding to check */\n\tconst OBJECT_ACL objectACL;\t\t/* Valid objects for message type */\n\t} CHECK_ACL;\n\n/* Macros to set up check ACLs.  For the standard check ACL the first\n   parameter, the check type, is supplied explicitly and isn't present in\n   the macro */\n\n#define MK_CHKACL( action, objSTA ) \\\n\t\t\taction, { objSTA, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE }\n#define MK_CHKACL_EX( action, objSTA, objSTB, flags ) \\\n\t\t\taction, { objSTA, objSTB, ST_NONE, flags }\n#define MK_CHKACL_END() \\\n\t\t\tMESSAGE_NONE, { ST_NONE, ST_NONE, ST_NONE, ACL_FLAG_NONE }\n\n/* Object dependency ACL entry, used when making one object dependent on\n   another */\n\ntypedef struct {\n\tconst OBJECT_TYPE type;\t\t\t/* Object type and subtype */\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\tconst OBJECT_TYPE dType;\t\t/* Dependent object type and subtype */\n\tconst OBJECT_SUBTYPE dSubTypeA, dSubTypeB, dSubTypeC;\n\tconst int flags;\t\t\t\t/* Dependency flags */\n\t} DEPENDENCY_ACL;\n\n/* Macros to set up dependency ACLs */\n\n#define MK_DEPACL( objType, objSTA, objSTB, objSTC, dObjType, dObjSTA, dObjSTB, dObjSTC ) \\\n\t\t\t{ objType, objSTA, objSTB, objSTC, dObjType, dObjSTA, dObjSTB, dObjSTC, DEP_FLAG_NONE }\n#define MK_DEPACL_EX( objType, objSTA, objSTB, objSTC, dObjType, dObjSTA, dObjSTB, dObjSTC, flags ) \\\n\t\t\t{ objType, objSTA, objSTB, objSTC, dObjType, dObjSTA, dObjSTB, dObjSTC, flags }\n#define MK_DEPACL_END() \\\n\t\t\t{ OBJECT_TYPE_NONE, 0, 0, 0, OBJECT_TYPE_NONE, 0, 0, 0, DEP_FLAG_NONE }\n\n/* Flags for the dependency ACLs */\n\n#define DEP_FLAG_NONE\t\t0x00\t/* No dependency flag */\n#define DEP_FLAG_UPDATEDEP\t0x01\t/* Update dependent object */\n\n#endif /* _ACL_DEFINED */\n"
  },
  {
    "path": "deps/cl345/kernel/acl_perm.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tACL Permission Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ACL_PERM_DEFINED\n\n#define _ACL_PERM_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAccess Permission Flags\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write/delete permission flags.  Each object can have two modes, \"low\"\n   and \"high\", whose exact definition depends on the object type.  At some\n   point an operation on an object (loading a key for a context, signing a\n   cert) will move it from the low to the high state, at which point a much\n   more restrictive set of permissions apply.  The permissions are given as\n   RWD_RWD with the first set being for the object in the high state and the\n   second for the object in the low state.\n\n   In addition to the usual external-access permssions, some attributes are\n   only visible internally.  Normal attributes have matching internal-access\n   and external-access permssions but the internal-access-only ones have the\n   external-access permissions turned off.\n\n   Some of the odder combinations arise from ACLs with sub-ACLs, for which\n   the overall access permission is the union of the permissions in all the\n   sub-ACLs.  For example if one sub-ACL has xxx_RWx and another has xWD_xxx,\n   the parent ACL will have xWD_RWx.  Finally, there are a small number of\n   special-case permissions in which internal access differs from external\n   access.  This is used for attributes that are used for control purposes\n   (e.g. identifier information in cert requests) and can be set internally\n   but are read-only externally.\n\n\t\t\t  Internal low ----++---- External high\n\t\t\t  Internal high --+||+--- External low */\n#define ACCESS_xxx_xxx\t\t0x0000\t/* No access */\n#define ACCESS_xxx_xWx\t\t0x0202\t/* Low: Write-only */\n#define ACCESS_xxx_xWD\t\t0x0303\t/* Low: Write/delete */\n#define ACCESS_xxx_Rxx\t\t0x0404\t/* Low: Read-only */\n#define ACCESS_xxx_RWx\t\t0x0606\t/* Low: Read/write */\n#define ACCESS_xxx_RWD\t\t0x0707\t/* Low: All access */\n#define ACCESS_xWx_xWx\t\t0x2222\t/* High: Write-only, Low: Write-only */\n#define ACCESS_xWD_xWD\t\t0x3333\t/* High: Write/delete, Low: Write/delete */\n#define ACCESS_xWx_xxx\t\t0x2020\t/* High: Write-only, Low: None */\n#define ACCESS_Rxx_xxx\t\t0x4040\t/* High: Read-only, Low: None */\n#define ACCESS_Rxx_xWx\t\t0x4242\t/* High: Read-only, Low: Write-only */\n#define ACCESS_Rxx_Rxx\t\t0x4444\t/* High: Read-only, Low: Read-only */\n#define ACCESS_Rxx_RxD\t\t0x4545\t/* High: Read-only, Low: Read/delete */\n#define ACCESS_Rxx_RWx\t\t0x4646\t/* High: Read-only, Low: Read/write */\n#define ACCESS_Rxx_RWD\t\t0x4747\t/* High: Read-only, Low: All access */\n#define ACCESS_RxD_RxD\t\t0x5555\t/* High: Read/delete, Low: Read/delete */\n#define ACCESS_RWx_xxx\t\t0x6060\t/* High: Read/write, Low: None */\n#define ACCESS_RWx_xWx\t\t0x6262\t/* High: Read/write, Low: Write-only */\n#define ACCESS_RWx_Rxx\t\t0x6464\t/* High: Read/write, Low: Read-only */\n#define ACCESS_RWx_RWx\t\t0x6666\t/* High: Read/write, Low: Read/write */\n#define ACCESS_RWx_RWD\t\t0x6767\t/* High: Read/write, Low: All access */\n#define ACCESS_RWD_xxx\t\t0x7070\t/* High: All access, Low: None */\n#define ACCESS_RWD_xWD\t\t0x7373\t/* High: All access, Low: Write/delete */\n#define ACCESS_RWD_RWD\t\t0x7777\t/* High: All access, Low: All access */\n\n#define ACCESS_INT_xxx_xxx\t0x0000\t/* Internal: No access */\n#define ACCESS_INT_xxx_xWx\t0x0200\t/* Internal: None, write-only */\n#define ACCESS_INT_xxx_Rxx\t0x0400\t/* Internal: None, read-only */\n#define ACCESS_INT_xWx_xxx\t0x2000\t/* Internal: Write-only, none */\n#define ACCESS_INT_xWx_xWx\t0x2200\t/* Internal: Write-only, write-only */\n#define ACCESS_INT_Rxx_xxx\t0x4000\t/* Internal: Read-only, none */\n#define ACCESS_INT_Rxx_xWx\t0x4200\t/* Internal: Read-only, write-only */\n#define ACCESS_INT_Rxx_Rxx\t0x4400\t/* Internal: Read-only, read-only */\n#define ACCESS_INT_Rxx_RWx\t0x4600\t/* Internal: Read-only, read/write */\n#define ACCESS_INT_RWx_xxx\t0x6000\t/* Internal: Read/write, none */\n#define ACCESS_INT_RWx_xWx\t0x6200\t/* Internal: Read/write, write-only */\n#define ACCESS_INT_RWx_RWx\t0x6600\t/* Internal: Read/write, read/write */\n\n#define ACCESS_SPECIAL_Rxx_RWx_Rxx_Rxx \\\n\t\t\t\t\t\t\t0x4644\t/* Internal = Read-only, read/write,\n\t\t\t\t\t\t\t\t\t   External = Read-only, read-only */\n#define ACCESS_SPECIAL_Rxx_RWD_Rxx_Rxx \\\n\t\t\t\t\t\t\t0x4744\t/* Internal = Read-only, all access,\n\t\t\t\t\t\t\t\t\t   External = Read-only, read-only */\n\n#define ACCESS_FLAG_x\t\t0x0000\t/* No access permitted */\n#define ACCESS_FLAG_R\t\t0x0004\t/* Read access permitted */\n#define ACCESS_FLAG_W\t\t0x0002\t/* Write access permitted */\n#define ACCESS_FLAG_D\t\t0x0001\t/* Delete access permitted */\n#define ACCESS_FLAG_H_R\t\t0x0040\t/* Read access permitted in high mode */\n#define ACCESS_FLAG_H_W\t\t0x0020\t/* Write access permitted in high mode */\n#define ACCESS_FLAG_H_D\t\t0x0010\t/* Delete access permitted in high mode */\n\n#define ACCESS_MASK_EXTERNAL 0x0077\t/* External-access flags mask */\n#define ACCESS_MASK_INTERNAL 0x7700\t/* Internal-access flags mask */\n\n#define MK_ACCESS_INTERNAL( value )\t( ( value ) << 8 )\n\n/* The basic RWD access flags above are also used for checking some\n   parameters passed with keyset mechanism messages, however in addition to\n   these we have flags for getFirst/getNext functions that are only used\n   with keysets.  Note that although these partially overlap with the high-\n   mode access flags for attributes this isn't a problem since keysets don't\n   distinguish between high and low states.  In addition some of the\n   combinations may seem a bit odd, but that's because they're for mechanism\n   parameters such as key ID information which is needed for reads and\n   deletes but not writes, since it's implicitly included with the key which\n   is being written.  Finally, one type of mechanism has parameter semantics\n   that are too complex to express via a simple ACL entry, these are given a\n   different-looking ACL entry xxXXxx to indicate to readers that this isn't\n   the same as a normal entry with the same value.  In addition to this, the\n   semantics of some of the getFirst/Next accesses are complex enough that\n   we need to hardcode them into the ACL checking, leaving only a\n   representative entry on the ACL definition itself (see key_acl.c for more\n   details) */\n\n#define ACCESS_KEYSET_xxxxx\t0x0000\t/* No access */\n#define ACCESS_KEYSET_xxXXx\t0x0006\t/* Special-case values (params optional) */\n#define ACCESS_KEYSET_xxRxD\t0x0005\t/* Read and delete */\n#define ACCESS_KEYSET_xxRWx\t0x0006\t/* Read/write */\n#define ACCESS_KEYSET_xxRWD\t0x0007\t/* Read/write and delete */\n#define ACCESS_KEYSET_FxRxD\t0x0015\t/* GetFirst, read, and delete */\n#define ACCESS_KEYSET_FNxxx\t0x0018\t/* GetFirst/Next */\n#define ACCESS_KEYSET_FNRWD\t0x001F\t/* All access */\n\n#define ACCESS_FLAG_F\t\t0x0010\t/* GetFirst access permitted */\n#define ACCESS_FLAG_N\t\t0x0008\t/* GetNext access permitted */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tConditional Access Permission Macros \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Many of cryptlib's capabilities can be selectively disabled, in which \n   case we also disable the use of the attributes that go with them.  The \n   following macros take care of this selective disabling */\n\n#define MKPERM( perm )\t\t\t\t\tACCESS_##perm\n#define MKPERM_INT( perm )\t\t\t\tACCESS_INT_##perm\n\n/* Certificate ACL macros */\n\n#ifdef USE_CERTIFICATES\n  #define MKPERM_CERTIFICATES( perm )\tACCESS_##perm\n  #define MKPERM_INT_CERTIFICATES( perm ) ACCESS_INT_##perm\n  #define MKPERM_SPECIAL_CERTIFICATES( perm ) ACCESS_SPECIAL_##perm\n#else\n  #define MKPERM_CERTIFICATES( perm )\tACCESS_xxx_xxx\n  #define MKPERM_INT_CERTIFICATES( perm ) ACCESS_INT_xxx_xxx\n  #define MKPERM_SPECIAL_CERTIFICATES( perm ) ACCESS_xxx_xxx\n#endif /* USE_CERTIFICATES */\n#if defined( USE_CERTIFICATES ) || defined( USE_PSEUDOCERTIFICATES )\n  #define MKPERM_ALT_CERTIFICATES( perm ) ACCESS_##perm\n#else\n  #define MKPERM_ALT_CERTIFICATES( perm ) ACCESS_xxx_xxx\n#endif /* USE_CERTIFICATES || USE_PSEUDOCERTIFICATES */\n\n#ifdef USE_CERTREQ\n  #define MKPERM_CERTREQ( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_CERTREQ( perm )\tACCESS_INT_##perm\n#else\n  #define MKPERM_CERTREQ( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_CERTREQ( perm )\tACCESS_INT_xxx_xxx\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n  #define MKPERM_CERTREV( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_CERTREV( perm )\tACCESS_INT_##perm\n#else\n  #define MKPERM_CERTREV( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_CERTREV( perm )\tACCESS_INT_xxx_xxx\n#endif /* USE_CERTREV */\n\n#if defined( USE_CERTREQ ) || defined( USE_CERTREV )\n  #define MKPERM_CERTREQ_REV( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CERTREQ_REV( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERTREQ || USE_CERTREV */\n\n#ifdef USE_CERTVAL\n  #define MKPERM_CERTVAL( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_CERTVAL( perm )\tACCESS_INT_##perm\n#else\n  #define MKPERM_CERTVAL( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_CERTVAL( perm )\tACCESS_INT_xxx_xxx\n#endif /* USE_CERTVAL */\n\n#if defined( USE_CERTREV ) || defined( USE_CERTVAL )\n  #define MKPERM_CERTREV_VAL( perm )\tACCESS_##perm\n  #define MKPERM_INT_CERTREV_VAL( perm ) ACCESS_INT_##perm\n#else\n  #define MKPERM_CERTREV_VAL( perm )\tACCESS_xxx_xxx\n  #define MKPERM_INT_CERTREV_VAL( perm ) ACCESS_INT_xxx_xxx\n#endif /* USE_CERTREV || USE_CERTVAL */\n\n#ifdef USE_CMSATTR\n  #define MKPERM_CMSATTR( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_CMSATTR( perm )\tACCESS_INT_##perm\n  #define MKPERM_SPECIAL_CMSATTR( perm ) ACCESS_SPECIAL_##perm\n#else\n  #define MKPERM_CMSATTR( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_CMSATTR( perm )\tACCESS_INT_xxx_xxx\n  #define MKPERM_SPECIAL_CMSATTR( perm ) ACCESS_xxx_xxx\n#endif /* USE_CMSATTR */\n\n#ifdef USE_PKIUSER\n  #define MKPERM_PKIUSER( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_PKIUSER( perm )\tACCESS_INT_##perm\n#else\n  #define MKPERM_PKIUSER( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_PKIUSER( perm )\tACCESS_INT_xxx_xxx\n#endif /* USE_PKIUSER */\n\n#ifdef USE_CERT_OBSOLETE\n  #define MKPERM_CERT_OBSOLETE( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CERT_OBSOLETE( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERT_OBSOLETE */\n\n#ifdef USE_CERT_DNSTRING\n  #define MKPERM_DNSTRING( perm )\t\tACCESS_##perm\n#else\n  #define MKPERM_DNSTRING( perm )\t\tACCESS_xxx_xxx\n#endif /* USE_CERT_DNSTRING */\n\n#ifdef USE_CMSATTR_OBSCURE\n  #define MKPERM_CMSATTR_OBSCURE( perm ) ACCESS_##perm\n#else\n  #define MKPERM_CMSATTR_OBSCURE( perm ) ACCESS_xxx_xxx\n#endif /* USE_CMSATTR_OBSCURE */\n\n#if defined( USE_CMSATTR_OBSCURE ) || defined( USE_TSP )\n  #define MKPERM_CMSATTR_OBSCURE_TSP( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CMSATTR_OBSCURE_TSP( perm )\tACCESS_xxx_xxx\n#endif /* USE_CMSATTR_OBSCURE || USE_TSP */\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n  #define MKPERM_CERT_PKIX_PARTIAL( perm ) ACCESS_##perm\n#else\n  #define MKPERM_CERT_PKIX_PARTIAL( perm ) ACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n#if defined( USE_CERTLEVEL_PKIX_PARTIAL ) && defined( USE_CERTREV )\n  #define MKPERM_CERTREV_PKIX_PARTIAL( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CERTREV_PKIX_PARTIAL( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL && USE_CERTREV */\n#if defined( USE_CERTLEVEL_PKIX_FULL ) && defined( USE_CERTREV )\n  #define MKPERM_CERTREV_PKIX_FULL( perm )\t\tACCESS_##perm\n#else\n  #define MKPERM_CERTREV_PKIX_FULL( perm )\t\tACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_FULL && USE_CERTREV */\n\n#if defined( USE_CERTLEVEL_PKIX_PARTIAL ) && defined( USE_CERT_OBSCURE )\n  #define MKPERM_PKIX_PARTIAL_OBSCURE( perm )\tACCESS_##perm\n#else\n  #define MKPERM_PKIX_PARTIAL_OBSCURE( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL && USE_CERT_OBSCURE */\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n  #define MKPERM_CERT_PKIX_FULL( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CERT_PKIX_FULL( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n#if defined( USE_CERTLEVEL_PKIX_FULL ) && \\\n\t( defined( USE_CERTREQ ) || defined( USE_CERTREV ) )\n  #define MKPERM_CERTREQ_REV_PKIX_FULL( perm )\tACCESS_##perm\n#else\n  #define MKPERM_CERTREQ_REV_PKIX_FULL( perm )\tACCESS_xxx_xxx\n#endif /* USE_CERTLEVEL_PKIX_FULL && ( USE_CERTREQ || USE_CERTREV ) */\n\n/* Device ACL macros */\n\n#ifdef USE_PKCS11\n  #define MKPERM_PKCS11( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_PKCS11( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_PKCS11( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_PKCS11( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_PKCS11 */\n\n/* Envelope ACL macros */\n\n#ifdef USE_ENVELOPES\n  #define MKPERM_ENVELOPE( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_ENVELOPE( perm )\tACCESS_INT_##perm\n#else\n  #define MKPERM_ENVELOPE( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_ENVELOPE( perm )\tACCESS_INT_xxx_xxx\n#endif /* USE_ENVELOPES */\n\n#ifdef USE_COMPRESSION\n  #define MKPERM_COMPRESSION( perm )\tACCESS_##perm\n  #define MKPERM_INT_COMPRESSION( perm ) ACCESS_INT_##perm\n#else\n  #define MKPERM_COMPRESSION( perm )\tACCESS_xxx_xxx\n  #define MKPERM_INT_COMPRESSION( perm ) ACCESS_INT_xxx_xxx\n#endif /* USE_COMPRESSION */\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n  #define MKPERM_PGP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_PGP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_PGP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_PGP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_PGP || USE_PGPKEYS */\n\n/* Keyset ACL macros */\n\n#ifdef USE_PKCS15\n  #define MKPERM_PKCS15( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_PKCS15( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_PKCS15( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_PKCS15( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_PKCS15 */\n\n#ifdef USE_DBMS\n  #define MKPERM_DBMS( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_DBMS( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_DBMS( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_DBMS( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_DBMS */\n\n#ifdef USE_LDAP\n  #define MKPERM_LDAP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_LDAP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_LDAP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_LDAP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_LDAP */\n\n#ifdef USE_HTTP\n  #define MKPERM_HTTP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_HTTP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_HTTP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_HTTP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_HTTP */\n\n/* Session ACL macros */\n\n#ifdef USE_TCP\n  #define MKPERM_TCP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_TCP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_TCP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_TCP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_TCP */\n\n#ifdef USE_SESSIONS\n  #define MKPERM_SESSIONS( perm )\t\tACCESS_##perm\n  #define MKPERM_INT_SESSIONS( perm ) ACCESS_INT_##perm\n#else\n  #define MKPERM_SESSIONS( perm )\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_SESSIONS( perm ) ACCESS_INT_xxx_xxx\n#endif /* USE_SESSIONS */\n\n#ifdef USE_CMP\n  #define MKPERM_CMP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_CMP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_CMP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_CMP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_CMP */\n\n#ifdef USE_SCEP\n  #define MKPERM_SCEP( perm )\t\t\tACCESS_##perm\n#else\n  #define MKPERM_SCEP( perm )\t\t\tACCESS_xxx_xxx\n#endif /* USE_SCEP */\n\n#ifdef USE_SSH\n  #define MKPERM_SSH( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_SSH( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_SSH( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_SSH( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_SSH */\n\n#ifdef USE_SSH_EXTENDED\n  #define MKPERM_SSH_EXT( perm )\t\tACCESS_##perm\n#else\n  #define MKPERM_SSH_EXT( perm )\t\tACCESS_xxx_xxx\n#endif /* USE_SSH_EXTENDED */\n\n#ifdef USE_SSL\n  #define MKPERM_SSL( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_SSL( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_SSL( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_SSL( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_SSL */\n\n#ifdef USE_TSP\n  #define MKPERM_TSP( perm )\t\t\tACCESS_##perm\n  #define MKPERM_INT_TSP( perm )\t\tACCESS_INT_##perm\n#else\n  #define MKPERM_TSP( perm )\t\t\tACCESS_xxx_xxx\n  #define MKPERM_INT_TSP( perm )\t\tACCESS_INT_xxx_xxx\n#endif /* USE_TSP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tConditional Access Types \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some ACLs define object types that are permitted rather than access\n   permissions.  The following macros turn these off as required */\n\n#ifdef USE_CERTIFICATES\n  #define MKTYPE_CERTIFICATES( type )\ttype\n#else\n  #define MKTYPE_CERTIFICATES( type )\t0\n#endif /* USE_CERTIFICATES */\n\n#ifdef USE_CERTREQ\n  #define MKTYPE_CERTREQ( type )\t\ttype\n#else\n  #define MKTYPE_CERTREQ( type )\t\t0\n#endif /* USE_CERTREQ */\n\n#ifdef USE_CERTREV\n  #define MKTYPE_CERTREV( type )\t\ttype \n#else\n  #define MKTYPE_CERTREV( type )\t\t0\n#endif /* USE_CERTREV */\n\n#ifdef USE_CERTVAL\n  #define MKTYPE_CERTVAL( type )\t\ttype \n#else\n  #define MKTYPE_CERTVAL( type )\t\t0\n#endif /* USE_CERTVAL */\n\n#ifdef USE_CMSATTR\n  #define MKTYPE_CMSATTR( type )\t\ttype \n#else\n  #define MKTYPE_CMSATTR( type )\t\t0\n#endif /* USE_CMSATTR */\n\n#ifdef USE_PKIUSER\n  #define MKTYPE_PKIUSER( type )\t\ttype \n#else\n  #define MKTYPE_PKIUSER( type )\t\t0\n#endif /* USE_PKIUSER */\n\n/* Device ACL macros */\n\n#ifdef USE_CAPI\n  #define MKTYPE_CAPI( type )\t\t\ttype \n#else\n  #define MKTYPE_CAPI( type )\t\t\t0\n#endif /* USE_CAPI */\n\n#ifdef USE_PKCS11\n  #define MKTYPE_PKCS11( type )\t\t\ttype \n#else\n  #define MKTYPE_PKCS11( type )\t\t\t0\n#endif /* USE_PKCS11 */\n\n/* Envelope ACL macros */\n\n#ifdef USE_ENVELOPES\n  #define MKTYPE_ENVELOPE( type )\t\ttype \n#else\n  #define MKTYPE_ENVELOPE( type )\t\t0\n#endif /* USE_ENVELOPES */\n\n/* Keyset ACL macros */\n\n#ifdef USE_DBMS\n  #define MKTYPE_DBMS( type )\t\t\ttype \n#else\n  #define MKTYPE_DBMS( type )\t\t\t0\n#endif /* USE_DBMS */\n\n#ifdef USE_LDAP\n  #define MKTYPE_LDAP( type )\t\t\ttype \n#else\n  #define MKTYPE_LDAP( type )\t\t\t0\n#endif /* USE_LDAP */\n\n#ifdef USE_HTTP\n  #define MKTYPE_HTTP( type )\t\t\ttype \n#else\n  #define MKTYPE_HTTP( type )\t\t\t0\n#endif /* USE_HTTP */\n\n/* Session ACL macros */\n\n#ifdef USE_CMP\n  #define MKTYPE_CMP( type )\t\t\ttype \n#else\n  #define MKTYPE_CMP( type )\t\t\t0\n#endif /* USE_CMP */\n\n#ifdef USE_OCSP\n  #define MKTYPE_OCSP( type )\t\t\ttype \n#else\n  #define MKTYPE_OCSP( type )\t\t\t0\n#endif /* USE_OCSP */\n\n#ifdef USE_RTCS\n  #define MKTYPE_RTCS( type )\t\t\ttype \n#else\n  #define MKTYPE_RTCS( type )\t\t\t0\n#endif /* USE_RTCS */\n\n#ifdef USE_SCEP\n  #define MKTYPE_SCEP( type )\t\t\ttype \n#else\n  #define MKTYPE_SCEP( type )\t\t\t0\n#endif /* USE_SCEP */\n\n#ifdef USE_SSH\n  #define MKTYPE_SSH( type )\t\t\ttype \n#else\n  #define MKTYPE_SSH( type )\t\t\t0\n#endif /* USE_SSH */\n\n#ifdef USE_SSL\n  #define MKTYPE_SSL( type )\t\t\ttype \n#else\n  #define MKTYPE_SSL( type )\t\t\t0\n#endif /* USE_SSL */\n\n#ifdef USE_TSP\n  #define MKTYPE_TSP( type )\t\t\ttype \n#else\n  #define MKTYPE_TSP( type )\t\t\t0\n#endif /* USE_TSP */\n\n\n\n#endif /* _ACL_PERM_DEFINED */\n"
  },
  {
    "path": "deps/cl345/kernel/attr_acl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Attribute ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream.h\"\t\t/* For MAX_PATH_LENGTH */\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream.h\"\t/* For MAX_PATH_LENGTH */\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* Common object ACLs for various object types */\n\nstatic const OBJECT_ACL objectCtxConv = {\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCtxPKC = {\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX };\nstatic const OBJECT_ACL objectCtxHash = {\n\t\tST_CTX_HASH, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\n\nstatic const OBJECT_ACL objectCertificate = {\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CERT };\nstatic const OBJECT_ACL objectCertificateTemplate = {\n\t\tST_CERT_CERT, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\t\t/* Template for cert.attrs */\nstatic const OBJECT_ACL objectCertRequest = {\n\t\tST_CERT_CERTREQ | ST_CERT_REQ_CERT, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCertRevRequest = {\n\t\tST_CERT_REQ_REV, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\t/* Unsigned obj.*/\nstatic const OBJECT_ACL objectCertSessionRTCSRequest = {\n\t\tST_CERT_RTCS_REQ, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\t/* Unsigned obj.*/\nstatic const OBJECT_ACL objectCertSessionOCSPRequest = {\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\t/* Unsigned obj.*/\nstatic const OBJECT_ACL objectCertSessionCMPRequest = {\n\t\tST_CERT_CERTREQ | ST_CERT_REQ_CERT | ST_CERT_REQ_REV, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\nstatic const OBJECT_ACL objectCertSessionPKCS10Request = {\n\t\tST_CERT_CERTREQ, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\nstatic const OBJECT_ACL objectCertRTCSRequest = {\n\t\tST_CERT_RTCS_REQ, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCertRTCSResponse = {\n\t\tST_CERT_RTCS_RESP, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCertOCSPRequest = {\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCertOCSPResponse = {\n\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\nstatic const OBJECT_ACL objectCertPKIUser = {\n\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, ACL_FLAG_HIGH_STATE };\n\nstatic const OBJECT_ACL objectCMSAttr = {\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, ACL_FLAG_ANY_STATE };\n\nstatic const OBJECT_ACL objectKeyset = {\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE, ACL_FLAG_NONE };\nstatic const OBJECT_ACL objectKeysetCerts = {\n\t\tST_NONE, ST_KEYSET_DBMS | SUBTYPE_KEYSET_DBMS_STORE, ST_NONE, ACL_FLAG_NONE };\nstatic const OBJECT_ACL objectKeysetCertstore = {\n\t\tST_NONE, SUBTYPE_KEYSET_DBMS_STORE, ST_NONE, ACL_FLAG_NONE };\nstatic const OBJECT_ACL objectKeysetPrivate = {\n\t\tST_NONE, ST_KEYSET_FILE | ST_DEV_P11, ST_NONE, ACL_FLAG_NONE };\nstatic const OBJECT_ACL objectKeysetConfigdata = {\n\t\tST_NONE, SUBTYPE_KEYSET_FILE, ST_NONE, ACL_FLAG_NONE };\n\nstatic const OBJECT_ACL objectDeenvelope = {\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, ACL_FLAG_HIGH_STATE };\n\nstatic const OBJECT_ACL objectHardwareDevice = {\n\t\tST_NONE, ST_DEV_HW, ST_NONE, ACL_FLAG_NONE };\n\nstatic const OBJECT_ACL objectSessionDataClient = {\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSL, ACL_FLAG_NONE };\nstatic const OBJECT_ACL objectSessionTSP = {\n\t\tST_NONE, ST_NONE, ST_SESS_TSP, ACL_FLAG_LOW_STATE };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tObject/Property ACLs\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const RANGE_SUBRANGE_TYPE allowedCertCursorSubranges[] = {\n\t/* Alongside the standard attributes and cursor movement codes we also\n\t   allow the selection of the subject and issuer DN pseudo-attributes, \n\t   which is required when we've implicitly moved to another DN by \n\t   selecting a GeneralName */\n\t{ CRYPT_CURSOR_FIRST, CRYPT_CURSOR_LAST },\n\t{ CRYPT_CERTINFO_FIRST_EXTENSION, CRYPT_CERTINFO_LAST_EXTENSION },\n\t{ CRYPT_CERTINFO_ISSUERNAME, CRYPT_CERTINFO_ISSUERNAME },\n\t{ CRYPT_CERTINFO_SUBJECTNAME, CRYPT_CERTINFO_SUBJECTNAME },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const RANGE_SUBRANGE_TYPE allowedCertCursorSubrangesEx[] = {\n\t/* This one is a bit more complex than the other object types, since \n\t   certificates are so complex it's possible to enumerate items at what \n\t   would normally be the attribute-instance level once components of \n\t   GeneralNames are taken into account, so we also allow GeneralName \n\t   entries as complete attributes rather than an instance of an \n\t   attribute.\n\t   \n\t   There's a second special case in which DN entries can be \n\t   multivalued, and depending on whether the DN is a primary DN in the\n\t   certificate (subject or issuer name) this could be either a non-\n\t   attribute type (since primary DNs aren't attributes) or something\n\t   below even the attribute-instance level.  To handle this we allow\n\t   enumeration of multivalued entries in DNs as pseudo-attribute\n\t   instances, and don't allow enumeration of multivalued DNs as \n\t   subclasses of GeneralNames, since the only likely reason for anyone \n\t   doing that is to engage in shenanigans with name checking in\n\t   implementations, and even the standards groups have no real idea of\n\t   what to do with these things */\n\t{ CRYPT_CURSOR_FIRST, CRYPT_CURSOR_LAST },\n\t{ CRYPT_CERTINFO_FIRST_EXTENSION, CRYPT_CERTINFO_LAST_EXTENSION },\n\t{ CRYPT_CERTINFO_FIRST_GENERALNAME, CRYPT_CERTINFO_LAST_GENERALNAME },\n\t{ CRYPT_CERTINFO_FIRST_DN, CRYPT_CERTINFO_LAST_DN },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const RANGE_SUBRANGE_TYPE allowedEnvCursorSubranges[] = {\n\t{ CRYPT_CURSOR_FIRST, CRYPT_CURSOR_LAST },\n\t{ CRYPT_ENVINFO_FIRST, CRYPT_ENVINFO_LAST },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const RANGE_SUBRANGE_TYPE allowedSessionCursorSubranges[] = {\n\t{ CRYPT_CURSOR_FIRST, CRYPT_CURSOR_LAST },\n\t{ CRYPT_SESSINFO_FIRST, CRYPT_SESSINFO_LAST },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nstatic const ATTRIBUTE_ACL subACL_AttributeCurrentGroup[] = {\n\tMKACL_EX(\t/* Certs */\n\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE_SUBRANGES, allowedCertCursorSubranges ),\n\tMKACL_EX(\t/* Envelopes */\n\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedEnvCursorSubranges ),\n\tMKACL_EX(\t/* Sessions */\n\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSessionCursorSubranges ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_AttributeCurrent[] = {\n\tMKACL_EX(\t/* Certs */\n\t\tCRYPT_ATTRIBUTE_CURRENT, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE_SUBRANGES, allowedCertCursorSubranges ),\n\tMKACL_EX(\t/* Envelopes */\n\t\tCRYPT_ATTRIBUTE_CURRENT, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedEnvCursorSubranges ),\n\tMKACL_EX(\t/* Sessions */\n\t\tCRYPT_ATTRIBUTE_CURRENT, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSessionCursorSubranges ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_AttributeCurrentInstance[] = {\n\t/* Only certificates are complex enough to have instances of fields,\n\t   the progression being certificate-extension -> GeneralName ->\n\t   GeneralName-field */\n\tMKACL_EX(\t/* Certs */\n\t\tCRYPT_ATTRIBUTE_CURRENT_INSTANCE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE_SUBRANGES, allowedCertCursorSubrangesEx ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Object properties */\n\nstatic const ATTRIBUTE_ACL propertyACL[] = {\n\tMKACL(\t\t/* Owned+non-forwardable+locked */\n\t\tCRYPT_PROPERTY_HIGHSECURITY, ATTRIBUTE_VALUE_BOOLEAN,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( xWx_xWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( TRUE, TRUE ) ),\n\tMKACL_N_EX(\t/* Object owner */\n\t\tCRYPT_PROPERTY_OWNER,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE_ANY ),\n\tMKACL_N_EX(\t/* No.of times object can be forwarded */\n\t\tCRYPT_PROPERTY_FORWARDCOUNT,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( 1, 1000 ) ),\n\tMKACL(\t\t/* Whether properties can be chged/read */\n\t\tCRYPT_PROPERTY_LOCKED, ATTRIBUTE_VALUE_BOOLEAN,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( TRUE, TRUE ) ),\n\tMKACL_N_EX(\t/* Usage count before object expires */\n\t\tCRYPT_PROPERTY_USAGECOUNT,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( 1, 1000 ) ),\n\tMKACL(\t\t/* Whether key is nonexp.from context */\n\t\tCRYPT_PROPERTY_NONEXPORTABLE, ATTRIBUTE_VALUE_BOOLEAN,\n\t\tST_CTX_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( xxx_xxx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( TRUE, TRUE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/* Generic attributes */\n\nstatic const ATTRIBUTE_ACL genericACL[] = {\n\tMKACL_N(\t/* Type of last error */\n\t\tCRYPT_ATTRIBUTE_ERRORTYPE,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE_NONE, RANGE( CRYPT_ERRTYPE_NONE, CRYPT_ERRTYPE_LAST - 1 ) ),\n\tMKACL_N(\t/* Locus of last error */\n\t\tCRYPT_ATTRIBUTE_ERRORLOCUS,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE_NONE, RANGE( CRYPT_ATTRIBUTE_NONE, CRYPT_ATTRIBUTE_LAST ) ),\n\tMKACL_S(\t/* Detailed error description */\n\t\tCRYPT_ATTRIBUTE_ERRORMESSAGE,\n\t\tST_NONE, ST_ENV_ANY | ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_SESS_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE_NONE, RANGE( 0, 512 ) ),\n\tMKACL_X(\t/* Cursor mgt: Group in attribute list */\n/* In = cursor components, out = component type */\n\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\tST_CERT_ANY, ST_ENV_DEENV, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT2( OBJECT_TYPE_CERTIFICATE, OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),\n\t\tsubACL_AttributeCurrentGroup ),\n\tMKACL_X(\t/* Cursor mgt: Entry in attribute list */\n/* In = cursor components, out = component type */\n\t\tCRYPT_ATTRIBUTE_CURRENT,\n\t\tST_CERT_ANY, ST_ENV_DEENV, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT2( OBJECT_TYPE_CERTIFICATE, OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),\n\t\tsubACL_AttributeCurrent ),\n\tMKACL_X(\t/* Cursor mgt: Instance in attribute list */\n/* In = cursor components, out = component type */\n\t\tCRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tsubACL_AttributeCurrentInstance ),\n\tMKACL_N(\t/* Internal data buffer size */\n\t\tCRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\tST_NONE, ST_ENV_ANY, ST_SESS_ANY, \n\t\tMKPERM( Rxx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ), RANGE( MIN_BUFFER_SIZE, MAX_BUFFER_SIZE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tConfig Option ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const RANGE_SUBRANGE_TYPE allowedEncrAlgoSubranges[] = {\n#ifdef USE_3DES\n\t{ CRYPT_ALGO_3DES, CRYPT_ALGO_3DES },\t\t/* No DES */\n#endif /* USE_3DES */\n\t{ CRYPT_ALGO_AES, CRYPT_ALGO_AES },\t\t\t/* No IDEA, CAST, RC2, RC4, RC5, Blowfish */\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const int allowedLDAPObjectTypes[] = {\n\tCRYPT_CERTTYPE_NONE, CRYPT_CERTTYPE_CERTIFICATE, CRYPT_CERTTYPE_CRL,\n\tCRYPT_ERROR, CRYPT_ERROR\n\t};\n\n/* Config attributes */\n\nstatic const ATTRIBUTE_ACL optionACL[] = {\n\tMKACL_S(\t/* Text description */\n\t\tCRYPT_OPTION_INFO_DESCRIPTION,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 16, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Copyright notice */\n\t\tCRYPT_OPTION_INFO_COPYRIGHT,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 16, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_N(\t/* Major release version */\n\t\tCRYPT_OPTION_INFO_MAJORVERSION,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 3, 3 ) ),\n\tMKACL_N(\t/* Minor release version */\n\t\tCRYPT_OPTION_INFO_MINORVERSION,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 0, 5 ) ),\n\tMKACL_N(\t/* Stepping version */\n\t\tCRYPT_OPTION_INFO_STEPPING,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 1, 50 ) ),\n\n\tMKACL_EX(\t/* Encryption algorithm */\n\t\t/* We restrict the subrange to disallow the selection of the\n\t\t   insecure or deprecated DES, RC2, RC4, and Skipjack algorithms\n\t\t   as the default encryption algorithms */\n\t\tCRYPT_OPTION_ENCR_ALGO, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ), 0,\n\t\tROUTE_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_USER ),\n\t\tRANGE_SUBRANGES, allowedEncrAlgoSubranges ),\n\tMKACL_N(\t/* Hash algorithm */\n\t\t/* We restrict the subrange to disallow the selection of the\n\t\t   insecure or deprecated MD2, MD4, and MD5 algorithms as the\n\t\t   default hash algorithm */\n\t\tCRYPT_OPTION_ENCR_HASH,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_USER ),\n\t\tRANGE( CRYPT_ALGO_SHA1, CRYPT_ALGO_LAST_HASH ) ),\n\tMKACL_N(\t/* MAC algorithm */\n\t\tCRYPT_OPTION_ENCR_MAC,\n\t\tST_NONE, ST_ENV_ENV, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_USER ),\n\t\tRANGE( CRYPT_ALGO_FIRST_MAC, CRYPT_ALGO_LAST_MAC ) ),\n\tMKACL_N(\t/* PKC algorithm */\n\t\tCRYPT_OPTION_PKC_ALGO,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( CRYPT_ALGO_FIRST_PKC, CRYPT_ALGO_LAST_PKC ) ),\n\tMKACL_N(\t/* PKC key size */\n\t\tCRYPT_OPTION_PKC_KEYSIZE,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( bitsToBytes( 512 ), CRYPT_MAX_PKCSIZE ) ),\n\tMKACL_N(\t/* Placeholder for obsolete option */\n\t\tCRYPT_OPTION_DUMMY1,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( xxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 0, 0 ) ),\n\tMKACL_N(\t/* Placeholder for obsolete option */\n\t\tCRYPT_OPTION_DUMMY2,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( xxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 0, 0 ) ),\n\tMKACL_N(\t/* Key processing algorithm */\n\t\t/* Note that this is non-orthongonal to CRYPT_CTXINFO_KEYING_ALGO,\n\t\t   for the configuration option we're specifying a setting for\n\t\t   PBKDF2, for CRYPT_CTXINFO_KEYING_ALGO it's usually PBKDF2 but may\n\t\t   also be PGP-style key derivation which uses the hash directly, \n\t\t   and can also use MD5 if it's enabled */\n\t\tCRYPT_OPTION_KEYING_ALGO,\n\t\tST_CTX_CONV, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_CONTEXT, OBJECT_TYPE_USER ),\n\t\tRANGE( CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_HMAC_SHAng ) ),\n\tMKACL_N(\t/* Key processing iterations */\n\t\tCRYPT_OPTION_KEYING_ITERATIONS,\n\t\tST_CTX_CONV, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_CONTEXT, OBJECT_TYPE_USER ),\n\t\tRANGE( 1, MAX_KEYSETUP_ITERATIONS ) ),\n\n\tMKACL_B(\t/* Whether to sign unrecog.attrs */\n\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_CERTIFICATES( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\tMKACL_N(\t/* Certificate validity period */\n\t\tCRYPT_OPTION_CERT_VALIDITY,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_CERTIFICATES( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 1, 20 * 365 ) ),\n\tMKACL_N(\t/* CRL update interval */\n\t\tCRYPT_OPTION_CERT_UPDATEINTERVAL,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_CERTREV( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 1, 365 ) ),\n\tMKACL_N(\t/* PKIX compliance level for cert chks.*/\n\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_ALT_CERTIFICATES( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( CRYPT_COMPLIANCELEVEL_OBLIVIOUS, \\\n\t\t\t   MAX_COMPLIANCE_LEVEL ) ),\n\tMKACL_B(\t/* Whether explicit policy req'd for certs */\n\t\tCRYPT_OPTION_CERT_REQUIREPOLICY,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_CERTIFICATES( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\n\tMKACL_B(\t/* Add default CMS attributes */\n\t\tCRYPT_OPTION_CMS_DEFAULTATTRIBUTES,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\n\tMKACL_S(\t/* Object class */\n\t\tCRYPT_OPTION_KEYS_LDAP_OBJECTCLASS,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_EX(\t/* Object type to fetch */\n\t\tCRYPT_OPTION_KEYS_LDAP_OBJECTTYPE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ), 0,\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE_ALLOWEDVALUES, allowedLDAPObjectTypes ),\n\tMKACL_S(\t/* Query filter */\n\t\tCRYPT_OPTION_KEYS_LDAP_FILTER,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* CA certificate attribute name */\n\t\tCRYPT_OPTION_KEYS_LDAP_CACERTNAME,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Certificate attribute name */\n\t\tCRYPT_OPTION_KEYS_LDAP_CERTNAME,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* CRL attribute name */\n\t\tCRYPT_OPTION_KEYS_LDAP_CRLNAME,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Email attribute name */\n\t\tCRYPT_OPTION_KEYS_LDAP_EMAILNAME,\n\t\tST_NONE, ST_KEYSET_LDAP, ST_USER_ANY, \n\t\tMKPERM_LDAP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\n\tMKACL_S(\t/* Name of first PKCS #11 driver */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_DVR01,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 2, MAX_PATH_LENGTH ) ),\n\tMKACL_S(\t/* Name of second PKCS #11 driver */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_DVR02,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 2, MAX_PATH_LENGTH ) ),\n\tMKACL_S(\t/* Name of third PKCS #11 driver */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_DVR03,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 2, MAX_PATH_LENGTH ) ),\n\tMKACL_S(\t/* Name of fourth PKCS #11 driver */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_DVR04,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 2, MAX_PATH_LENGTH ) ),\n\tMKACL_S(\t/* Name of fifth PKCS #11 driver */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_DVR05,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 2, MAX_PATH_LENGTH ) ),\n\tMKACL_B(\t/* Use only hardware mechanisms */\n\t\tCRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS11( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\n\tMKACL_S(\t/* Socks server name */\n\t\tCRYPT_OPTION_NET_SOCKS_SERVER,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_TCP( RWD_RWD ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( MIN_DNS_SIZE, MAX_DNS_SIZE ) ),\n\tMKACL_S(\t/* Socks user name */\n\t\tCRYPT_OPTION_NET_SOCKS_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_TCP( RWD_RWD ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Web proxy server */\n\t\tCRYPT_OPTION_NET_HTTP_PROXY,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_HTTP( RWD_RWD ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( MIN_DNS_SIZE, MAX_DNS_SIZE ) ),\n\tMKACL_N(\t/* Timeout for network connection setup */\n\t\tCRYPT_OPTION_NET_CONNECTTIMEOUT,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_TCP( Rxx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( 5, MAX_NETWORK_TIMEOUT ) ),\n\tMKACL_N(\t/* Timeout for network reads */\n\t\tCRYPT_OPTION_NET_READTIMEOUT,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_TCP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( 0, MAX_NETWORK_TIMEOUT ) ),\n\tMKACL_N(\t/* Timeout for network writes */\n\t\tCRYPT_OPTION_NET_WRITETIMEOUT,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY | ST_USER_ANY, \n\t\tMKPERM_TCP( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_SESSION, OBJECT_TYPE_USER ),\n\t\tRANGE( 0, MAX_NETWORK_TIMEOUT ) ),\n\n\tMKACL_B(\t/* Whether to init cryptlib async'ly */\n\t\tCRYPT_OPTION_MISC_ASYNCINIT,\n\t\tST_NONE, ST_NONE, ST_USER_SO, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\tMKACL_N(\t/* Protect against side-channel attacks */\n\t\tCRYPT_OPTION_MISC_SIDECHANNELPROTECTION,\n\t\tST_CTX_PKC, ST_NONE, ST_USER_SO, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE_ALT( OBJECT_TYPE_CONTEXT, OBJECT_TYPE_USER ),\n\t\tRANGE( 0, 2 ) ),\n\n\tMKACL(\t\t/* Whether in-mem.opts match on-disk ones */\n\t\t/* This is a special-case boolean attribute value that can only be\n\t\t   set to FALSE to indicate that the config options should be\n\t\t   flushed to disk */\n\t\tCRYPT_OPTION_CONFIGCHANGED, ATTRIBUTE_VALUE_BOOLEAN,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS15( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( FALSE, FALSE ) ),\n\n\tMKACL_B(\t/* Algorithm self-test status */\n\t\tCRYPT_OPTION_SELFTESTOK, \n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM( RWx_RWx ), \n\t\tROUTE( OBJECT_TYPE_USER ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tContext ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const int allowedPKCKeysizes[] = {\n\tsizeof( CRYPT_PKCINFO_DLP ), sizeof( CRYPT_PKCINFO_RSA ), \n\tsizeof( CRYPT_PKCINFO_ECC ), CRYPT_ERROR, CRYPT_ERROR \n\t};\nstatic const int allowedKeyingAlgos[] = {\n\t/* Hash algos used for PGP */\n#ifdef USE_PGP\n  #ifdef USE_MD5\n\tCRYPT_ALGO_MD5,\n  #endif /* USE_MD5 */\n\tCRYPT_ALGO_SHA1, \n\tCRYPT_ALGO_SHA2,\n#endif /* USE_PGP */\n\t/* MAC algos used for everything else */\n\tCRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_HMAC_SHAng, \n\tCRYPT_ERROR, CRYPT_ERROR\n\t};\n\nstatic const ATTRIBUTE_ACL subACL_CtxinfoBlocksize[] = {\n\tMKACL_N(\t/* Encr. and PKC is determined implicitly algorithm type */\n\t\tCRYPT_CTXINFO_BLOCKSIZE,\n\t\tST_CTX_CONV | ST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 1, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_N(\t/* Some hash/MAC algos have variable-length outputs */\n\t\t/* Hash contexts are a special case because they're moved into the\n\t\t   high state as soon as they're created because there's no further\n\t\t   initialisation to be done.  This means that the output size can\n\t\t   be changed even when they're (effectively) in the high state, \n\t\t   although the actual meaning of this state is somewhat different\n\t\t   than for other context types */\n\t\tCRYPT_CTXINFO_BLOCKSIZE,\n\t\tST_CTX_HASH, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_N(\t/* Some hash/MAC algos have variable-length outputs */\n\t\tCRYPT_CTXINFO_BLOCKSIZE,\n\t\tST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\nstatic const ATTRIBUTE_ACL subACL_CtxinfoPersistent[] = {\n\tMKACL_B(\t/* PKC is determined implicitly by storage type */\n\t\tCRYPT_CTXINFO_PERSISTENT,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ) ),\n\tMKACL_B(\t/* Conv./MAC can be set on create to create persistent object */\n\t\tCRYPT_CTXINFO_PERSISTENT,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Context attributes */\n\nstatic const ATTRIBUTE_ACL contextACL[] = {\n\tMKACL_N(\t/* Algorithm */\n\t\tCRYPT_CTXINFO_ALGO,\n\t\tST_CTX_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( CRYPT_ALGO_NONE + 1, CRYPT_ALGO_LAST - 1 ) ),\n\tMKACL_N(\t/* Mode */\n\t\tCRYPT_CTXINFO_MODE,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( CRYPT_MODE_NONE + 1, CRYPT_MODE_LAST - 1 ) ),\n\tMKACL_S(\t/* Algorithm name */\n\t\tCRYPT_CTXINFO_NAME_ALGO,\n\t\tST_CTX_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 3, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Mode name */\n\t\tCRYPT_CTXINFO_NAME_MODE,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 3, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_N(\t/* Key size in bytes */\n\t\tCRYPT_CTXINFO_KEYSIZE,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) ),\n\tMKACL_X(\t/* Block size in bytes */\n\t\tCRYPT_CTXINFO_BLOCKSIZE,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_HASH | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tsubACL_CtxinfoBlocksize ),\n\tMKACL_N(\t/* IV size in bytes */\n\t\tCRYPT_CTXINFO_IVSIZE,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_IVSIZE, CRYPT_MAX_IVSIZE ) ),\n\tMKACL_EX(\t/* Key processing algorithm */\n\t\t/* The allowed algorithm range is a bit peculiar, usually we only\n\t\t   allow HMAC-SHA1 for normal key derivation, however PGP uses\n\t\t   plain hash algorithms for the derivation and although these\n\t\t   are never applied they are stored in the context when PGP keys\n\t\t   are loaded */\n\t\tCRYPT_CTXINFO_KEYING_ALGO, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ), 0,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE_ALLOWEDVALUES, allowedKeyingAlgos ),\n\tMKACL_N(\t/* Key processing iterations */\n\t\tCRYPT_CTXINFO_KEYING_ITERATIONS,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 1, MAX_KEYSETUP_ITERATIONS ) ),\n\tMKACL_S(\t/* Key processing salt */\n\t\tCRYPT_CTXINFO_KEYING_SALT,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 8, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S_EX(\t/* Value used to derive key */\n\t\tCRYPT_CTXINFO_KEYING_VALUE,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 1, MAX_ATTRIBUTE_SIZE ) ),\n#ifdef USE_FIPS140\n\tMKACL_S_EX(\t/* Key */\n\t\tCRYPT_CTXINFO_KEY,\n\t\tST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_KEYSIZE, CRYPT_MAX_KEYSIZE ) ),\n\tMKACL_EX(\t/* Public-key components */\n\t\tCRYPT_CTXINFO_KEY_COMPONENTS, ATTRIBUTE_VALUE_STRING,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE_ALLOWEDVALUES, allowedPKCKeysizes ),\n#else\n\tMKACL_S_EX(\t/* Key */\n\t\tCRYPT_CTXINFO_KEY,\n\t\tST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_KEYSIZE, CRYPT_MAX_KEYSIZE ) ),\n\tMKACL_EX(\t/* Public-key components */\n\t\tCRYPT_CTXINFO_KEY_COMPONENTS, ATTRIBUTE_VALUE_STRING,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE_ALLOWEDVALUES, allowedPKCKeysizes ),\n#endif /* FIPS 140 keying rules */\n\tMKACL_S(\t/* IV */\n\t\tCRYPT_CTXINFO_IV,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_IVSIZE, CRYPT_MAX_IVSIZE ) ),\n\tMKACL_S(\t/* Hash value */\n\t\tCRYPT_CTXINFO_HASHVALUE,\n\t\tST_CTX_HASH | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( RxD_RxD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* Label for private/secret key */\n\t\tCRYPT_CTXINFO_LABEL,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_X(\t/* Object is backed by a device or keyset */\n\t\tCRYPT_CTXINFO_PERSISTENT,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tsubACL_CtxinfoPersistent ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCertificate ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_CERTIFICATES ) || defined( USE_ENVELOPES )\n\nstatic const RANGE_SUBRANGE_TYPE allowedContentTypeSubranges[] = {\n\t{ CRYPT_CONTENT_DATA, CRYPT_CONTENT_ENVELOPEDDATA },\n#ifdef USE_CMSATTR_OBSCURE\n\t{ CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA, CRYPT_CONTENT_SIGNEDANDENVELOPEDDATA },\n#endif /* USE_CMSATTR_OBSCURE */\n\t{ CRYPT_CONTENT_DIGESTEDDATA, CRYPT_CONTENT_ENCRYPTEDDATA },\n#ifdef USE_COMPRESSION\n\t{ CRYPT_CONTENT_COMPRESSEDDATA, CRYPT_CONTENT_COMPRESSEDDATA },\n#endif /* USE_COMPRESSION */\n#ifdef USE_TSP\n\t{ CRYPT_CONTENT_TSTINFO, CRYPT_CONTENT_TSTINFO },\n#endif /* USE_TSP */\n#ifdef USE_CMSATTR_OBSCURE\n\t{ CRYPT_CONTENT_SPCINDIRECTDATACONTEXT, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },\n#endif /* USE_CMSATTR_OBSCURE */\n#ifdef USE_CERTVAL\n\t{ CRYPT_CONTENT_RTCSREQUEST, CRYPT_CONTENT_RTCSRESPONSE_EXT },\n#endif /* USE_CERTVAL */\n\t{ CRYPT_CONTENT_MRTD, CRYPT_CONTENT_MRTD },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR } \n\t};\n#endif /* USE_CERTIFICATES || USE_ENVELOPES */\n\n#ifdef USE_CERTIFICATES\n\nstatic const int allowedIPAddressSizes[] = \\\n\t{ 4, 16, CRYPT_ERROR, CRYPT_ERROR };\n\nstatic const ATTRIBUTE_ACL subACL_CertinfoFingerprintSHA[] = {\n\tMKACL_S(\t/* Certs: General access */\n\t\tCRYPT_CERTINFO_FINGERPRINT_SHA1,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 20, 20 ) ),\n\tMKACL_S(\t/* Selected other objs (requests, PKI users): Int.access only */\n\t\tCRYPT_CERTINFO_FINGERPRINT_SHA1,\n\t\tST_CERT_ANY_CERT | ST_CERT_REQ_REV | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 20, 20 ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Certificate: General info */\n\nstatic const ATTRIBUTE_ACL certificateACL[] = {\n\tMKACL_B(\t/* Cert is self-signed */\n\t\tCRYPT_CERTINFO_SELFSIGNED,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* Cert is signed and immutable */\n\t\tCRYPT_CERTINFO_IMMUTABLE,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM_ALT_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* Cert is a magic just-works cert */\n\t\tCRYPT_CERTINFO_XYZZY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* Certificate object type */\n\t\tCRYPT_CERTINFO_CERTTYPE,\n\t\tST_CERT_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM_ALT_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CERTTYPE_NONE + 1, CRYPT_CERTTYPE_LAST - 1 ) ),\n\tMKACL_X(\t/* Certificate fingerprint: SHA-1 */\n\t\tCRYPT_CERTINFO_FINGERPRINT_SHA1,\n\t\tST_CERT_ANY_CERT | ST_CERT_REQ_REV | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tsubACL_CertinfoFingerprintSHA ),\n\tMKACL_S(\t/* Certificate fingerprint: SHA-2 */\n\t\tCRYPT_CERTINFO_FINGERPRINT_SHA2,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, 32 ) ),\n\tMKACL_S(\t/* Certificate fingerprint: SHAng */\n\t\tCRYPT_CERTINFO_FINGERPRINT_SHAng,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, 32 ) ),\n\tMKACL_N(\t/* Cursor mgt: Rel.pos in chain/CRL/OCSP */\n\t\t/* The subtype flag is somewhat unusual since it includes as an\n\t\t   allowed subtype a cert, which doesn't have further cert components.\n\t\t   The reason for this is that when the chain is created it's just a\n\t\t   collection of certs, it isn't until all of them are available that\n\t\t   one can be marked the leaf cert and its type changed to cert chain.\n\t\t   Since an object's subtype can't be changed after it's created, we\n\t\t   have to allow cursor movement commands to certs in case one of\n\t\t   them is really the leaf in a cert chain - it's because of the way\n\t\t   the leaf can act as both a cert and a cert chain.  A pure cert\n\t\t   looks just like a one-cert chain, so there's no harm in sending a\n\t\t   movement command to a cert that isn't a chain leaf */\n\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL | ST_CERT_RTCS_REQ | \\\n\t\t\t\t\t   ST_CERT_RTCS_RESP | ST_CERT_OCSP_REQ | \\\n\t\t\t\t\t   ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CURSOR_FIRST, CRYPT_CURSOR_LAST ) ),\n\tMKACL_N(\t/* Usage that cert is trusted for */\n\t\tCRYPT_CERTINFO_TRUSTED_USAGE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_KEYUSAGE_NONE, CRYPT_KEYUSAGE_LAST - 1 ) ),\n\tMKACL_B(\t/* Whether cert is implicitly trusted */\n\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( RWD_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* Amount of detail to include in sigs.*/\n\t\tCRYPT_CERTINFO_SIGNATURELEVEL,\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_SIGNATURELEVEL_NONE, CRYPT_SIGNATURELEVEL_ALL ) ),\n\n\tMKACL_N(\t/* Certificate format version */\n\t\tCRYPT_CERTINFO_VERSION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\t\t\t   ST_CERT_RTCS_REQ | ST_CERT_RTCS_RESP | \\\n\t\t\t\t\t   ST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 3 ) ),\n\tMKACL_S(\t/* Serial number */\n\t\tCRYPT_CERTINFO_SERIALNUMBER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\t\t\t   ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 32 ) ),\n\tMKACL_O(\t/* Public key */\n\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCtxPKC ),\n\tMKACL_O(\t/* User certificate */\n\t\tCRYPT_CERTINFO_CERTIFICATE,\n\t\tST_CERT_CERTCHAIN | ST_CERT_CRL | ST_CERT_REQ_CERT | ST_CERT_REQ_REV | \\\n\t\t\t\t\t\t\tST_CERT_RTCS_REQ | ST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificate ),\n\tMKACL_O(\t/* CA certificate */\n\t\tCRYPT_CERTINFO_CACERTIFICATE,\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificate ),\n\tMKACL_B(\t/* Issuer DN */\n\t\tCRYPT_CERTINFO_ISSUERNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\t\t\t   ST_CERT_CRL | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* Cert valid-from time */\n\t\tCRYPT_CERTINFO_VALIDFROM,\n\t\tST_CERT_CERT | ST_CERT_REQ_CERT | ST_CERT_CERTCHAIN | \\\n\t\t\t\t\t   ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* Cert valid-to time */\n\t\tCRYPT_CERTINFO_VALIDTO,\n\t\tST_CERT_CERT | ST_CERT_REQ_CERT | ST_CERT_CERTCHAIN | \\\n\t\t\t\t\t   ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* Subject DN */\n\t\tCRYPT_CERTINFO_SUBJECTNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* Issuer unique ID */\n\t\tCRYPT_CERTINFO_ISSUERUNIQUEID,\n\t\tST_CERT_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Subject unique ID */\n\t\tCRYPT_CERTINFO_SUBJECTUNIQUEID,\n\t\tST_CERT_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_O(\t/* Cert.request (DN + public key) */\n\t\tCRYPT_CERTINFO_CERTREQUEST,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertRequest ),\n\tMKACL_T(\t/* CRL/OCSP current-update time */\n\t\tCRYPT_CERTINFO_THISUPDATE,\n\t\tST_CERT_CRL | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* CRL/OCSP next-update time */\n\t\tCRYPT_CERTINFO_NEXTUPDATE,\n\t\tST_CERT_CRL | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* CRL/RTCS/OCSP cert-revocation time */\n\t\tCRYPT_CERTINFO_REVOCATIONDATE,\n\t\tST_CERT_CRL | ST_CERT_RTCS_RESP | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_VAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* OCSP revocation status */\n\t\tCRYPT_CERTINFO_REVOCATIONSTATUS,\n\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_OCSPSTATUS_NOTREVOKED, CRYPT_OCSPSTATUS_UNKNOWN ) ),\n\tMKACL_N(\t/* RTCS certificate status */\n\t\tCRYPT_CERTINFO_CERTSTATUS,\n\t\tST_CERT_RTCS_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTVAL( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CERTSTATUS_VALID, CRYPT_CERTSTATUS_UNKNOWN ) ),\n\tMKACL_S(\t/* Currently selected DN in string form */\n\t\tCRYPT_CERTINFO_DN,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_DNSTRING( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* PKI user ID */\n\t\tCRYPT_CERTINFO_PKIUSER_ID,\n\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIUSER( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 17, 17 ) ),\n\tMKACL_S(\t/* PKI user issue password */\n\t\tCRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\n\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIUSER( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 23, 23 ) ),\n\tMKACL_S(\t/* PKI user revocation password */\n\t\tCRYPT_CERTINFO_PKIUSER_REVPASSWORD,\n\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIUSER( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 23, 23 ) ),\n\tMKACL_B(\t/* PKI user is an RA */\n\t\tCRYPT_CERTINFO_PKIUSER_RA,\n\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/* Certificate: Name components */\n\nstatic const ATTRIBUTE_ACL certNameACL[] = {\n\tMKACL_S(\t/* countryName */\n\t\tCRYPT_CERTINFO_COUNTRYNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, 2 ) ),\n\tMKACL_WCS(\t/* stateOrProvinceName */\n\t\tCRYPT_CERTINFO_STATEORPROVINCENAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_WCS(\t/* localityName */\n\t\tCRYPT_CERTINFO_LOCALITYNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_WCS(\t/* organizationName */\n\t\tCRYPT_CERTINFO_ORGANIZATIONNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_WCS(\t/* organizationalUnitName */\n\t\tCRYPT_CERTINFO_ORGANIZATIONALUNITNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_WCS(\t/* commonName */\n\t\tCRYPT_CERTINFO_COMMONNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\n\tMKACL_S(\t/* otherName.typeID */\n\t\tCRYPT_CERTINFO_OTHERNAME_TYPEID,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* otherName.value */\n\t\tCRYPT_CERTINFO_OTHERNAME_VALUE,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* rfc822Name */\n\t\tCRYPT_CERTINFO_RFC822NAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_RFC822_SIZE, MAX_RFC822_SIZE ) ),\n\tMKACL_S(\t/* dNSName */\n\t\tCRYPT_CERTINFO_DNSNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_DNS_SIZE, MAX_DNS_SIZE ) ),\n\tMKACL_N(\t/* directoryName */\n\t\tCRYPT_CERTINFO_DIRECTORYNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_S(\t/* ediPartyName.nameAssigner */\n\t\tCRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* ediPartyName.partyName */\n\t\tCRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* uniformResourceIdentifier */\n\t\tCRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_EX(\t/* iPAddress */\n\t\tCRYPT_CERTINFO_IPADDRESS, ATTRIBUTE_VALUE_STRING,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ), 0,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE_ALLOWEDVALUES, allowedIPAddressSizes ),\n\tMKACL_S(\t/* registeredID */\n\t\tCRYPT_CERTINFO_REGISTEREDID,\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/* Certificate: Extensions */\n\nstatic const ATTRIBUTE_ACL certExtensionACL[] = {\n\t/* 1 2 840 113549 1 9 7 challengePassword.  This is here even though it's\n\t   a CMS attribute because SCEP stuffs it into PKCS #10 requests */\n\tMKACL_S(\t/* nonce */\n\t\tCRYPT_CERTINFO_CHALLENGEPASSWORD,\n\t\tST_CERT_CERTREQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREQ( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\n\t/* 1 3 6 1 4 1 3029 3 1 4 cRLExtReason */\n\tMKACL_N(\t/* cRLExtReason */\n\t\tCRYPT_CERTINFO_CRLEXTREASON,\n\t\tST_CERT_CRL | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREQ_REV( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASON_UNSPECIFIED, CRYPT_CRLEXTREASON_LAST - 1 ) ),\n\n\t/* 1 3 6 1 4 1 3029 3 1 5 keyFeatures */\n\tMKACL_N(\t/* keyFeatures */\n\t\tCRYPT_CERTINFO_KEYFEATURES,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 7 ) ),\n\n\t/* 1 3 6 1 5 5 7 1 1 authorityInfoAccess.  The values are GeneralName\n\t   selectors so the ACL doesn't allow writes, since they can only be\n\t   used to select the GeneralName that's written to */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_AUTHORITYINFOACCESS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_RTCS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_OCSP,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CAISSUERS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CERTSTORE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_AUTHORITYINFO_CRLS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 3 6 1 5 5 7 1 2 biometricInfo */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_BIOMETRICINFO,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* biometricData.typeOfData */\n\t\tCRYPT_CERTINFO_BIOMETRICINFO_TYPE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 1 ) ),\n\tMKACL_S(\t/* biometricData.hashAlgorithm */\n\t\tCRYPT_CERTINFO_BIOMETRICINFO_HASHALGO,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* biometricData.dataHash */\n\t\tCRYPT_CERTINFO_BIOMETRICINFO_HASH,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* biometricData.sourceDataUri */\n\t\tCRYPT_CERTINFO_BIOMETRICINFO_URL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\n\t/* 1 3 6 1 5 5 7 1 3 qcStatements */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_QCSTATEMENT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* qcStatement.statementInfo.semanticsIdentifier */\n\t\tCRYPT_CERTINFO_QCSTATEMENT_SEMANTICS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_N(\t/* qcStatement.statementInfo.nameRegistrationAuthorities */\n\t\t/* This is a GeneralName selector so it can't be written to directly */\n\t\tCRYPT_CERTINFO_QCSTATEMENT_REGISTRATIONAUTHORITY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 3 6 1 5 5 7 1 7 ipAddrBlocks */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_IPADDRESSBLOCKS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* addressFamily */\n\t\tCRYPT_CERTINFO_IPADDRESSBLOCKS_ADDRESSFAMILY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, 2 ) ),\n\tMKACL_S(\t/* ipAddress.addressPrefix */\n\t\t/* See the comment in ext_def.c for the length range */\n\t\tCRYPT_CERTINFO_IPADDRESSBLOCKS_PREFIX,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 19 ) ),\n\tMKACL_S(\t/* ipAddress.addressRangeMin */\n\t\tCRYPT_CERTINFO_IPADDRESSBLOCKS_MIN,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 19 ) ),\n\tMKACL_S(\t/* ipAddress.addressRangeMax */\n\t\tCRYPT_CERTINFO_IPADDRESSBLOCKS_MAX,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 19 ) ),\n\n\t/* 1 3 6 1 5 5 7 1 8 autonomousSysIds */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* asNum.id */\n\t\t/* See the comment in ext_def.c for the AS range */\n\t\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_ID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 500000 ) ),\n\tMKACL_N(\t/* asNum.min */\n\t\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MIN,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 500000 ) ),\n\tMKACL_N(\t/* asNum.max */\n\t\tCRYPT_CERTINFO_AUTONOMOUSSYSIDS_ASNUM_MAX,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 500000 ) ),\n\n\t/* 1 3 6 1 5 5 7 48 1 2 ocspNonce */\n\tMKACL_S(\t/* nonce */\n\t\tCRYPT_CERTINFO_OCSP_NONCE,\n\t\tST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 1 3 6 1 5 5 7 48 1 4 ocspAcceptableResponses */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_OCSP_RESPONSE,\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* OCSP standard response */\n\t\tCRYPT_CERTINFO_OCSP_RESPONSE_OCSP,\n\t\tST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 1 3 6 1 5 5 7 48 1 5 ocspNoCheck */\n\tMKACL_N(\t/* noCheck */\n\t\tCRYPT_CERTINFO_OCSP_NOCHECK,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* 1 3 6 1 5 5 7 48 1 6 ocspArchiveCutoff */\n\tMKACL_T(\t/* archiveCutoff */\n\t\tCRYPT_CERTINFO_OCSP_ARCHIVECUTOFF,\n\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 1 3 6 1 5 5 7 48 1 11 subjectInfoAccess.  The values are GeneralName\n\t   selectors so the ACL doesn't allow writes, since they can only be\n\t   used to select the GeneralName that's written to */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SUBJECTINFOACCESS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_SUBJECTINFO_TIMESTAMPING,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECTREPOSITORY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_SUBJECTINFO_RPKIMANIFEST,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* accessDescription.accessLocation */\n\t\tCRYPT_CERTINFO_SUBJECTINFO_SIGNEDOBJECT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 3 36 8 3 1 dateOfCertGen */\n\tMKACL_T(\t/* dateOfCertGen */\n\t\tCRYPT_CERTINFO_SIGG_DATEOFCERTGEN,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 1 3 36 8 3 2 procuration */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SIGG_PROCURATION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* country */\n\t\tCRYPT_CERTINFO_SIGG_PROCURE_COUNTRY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, 2 ) ),\n\tMKACL_S(\t/* typeOfSubstitution */\n\t\tCRYPT_CERTINFO_SIGG_PROCURE_TYPEOFSUBSTITUTION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_N(\t/* signingFor.thirdPerson */\n\t\tCRYPT_CERTINFO_SIGG_PROCURE_SIGNINGFOR,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 3 36 8 3 3 siggAdmissions */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* authority */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_AUTHORITY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_S(\t/* namingAuth.iD */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* namingAuth.uRL */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_S(\t/* namingAuth.text */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_NAMINGAUTHTEXT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_S(\t/* professionItem */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONITEM,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\tMKACL_S(\t/* professionOID */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_PROFESSIONOID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* registrationNumber */\n\t\tCRYPT_CERTINFO_SIGG_ADMISSIONS_REGISTRATIONNUMBER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\n\t/* 1 3 36 8 3 4 monetaryLimit */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SIGG_MONETARYLIMIT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* currency */\n\t\tCRYPT_CERTINFO_SIGG_MONETARY_CURRENCY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 3 ) ),\n\tMKACL_N(\t/* amount */\n\t\tCRYPT_CERTINFO_SIGG_MONETARY_AMOUNT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 255 ) ),\n\tMKACL_N(\t/* exponent */\n\t\tCRYPT_CERTINFO_SIGG_MONETARY_EXPONENT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 255 ) ),\n\n\t/* 1 3 36 8 3 5 declarationOfMajority */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* fullAgeAtCountry */\n\t\tCRYPT_CERTINFO_SIGG_DECLARATIONOFMAJORITY_COUNTRY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, 2 ) ),\n\n\t/* 1 3 36 8 3 8 restriction */\n\tMKACL_S(\t/* restriction */\n\t\tCRYPT_CERTINFO_SIGG_RESTRICTION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\n\t/* 1 3 36 8 3 13 siggCertHash */\n\tMKACL_S(\t/* certHash */\n\t\tCRYPT_CERTINFO_SIGG_CERTHASH,\n\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, MAX_ATTRIBUTE_SIZE ) ),\n\n\t/* 1 3 36 8 3 15 additionalInformation */\n\tMKACL_S(\t/* additionalInformation */\n\t\tCRYPT_CERTINFO_SIGG_ADDITIONALINFORMATION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_PKIX_PARTIAL_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 128 ) ),\n\n\t/* 1 3 101 1 4 1 strongExtranet */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_STRONGEXTRANET,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* sxNetIDList.sxNetID.zone */\n\t\tCRYPT_CERTINFO_STRONGEXTRANET_ZONE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, RANGE_MAX ) ),\n\tMKACL_S(\t/* sxNetIDList.sxNetID.id */\n\t\tCRYPT_CERTINFO_STRONGEXTRANET_ID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 2 5 29 9 subjectDirectoryAttributes */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SUBJECTDIRECTORYATTRIBUTES,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* attribute.type */\n\t\tCRYPT_CERTINFO_SUBJECTDIR_TYPE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* attribute.values */\n\t\tCRYPT_CERTINFO_SUBJECTDIR_VALUES,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, MAX_ATTRIBUTE_SIZE ) ),\n\n\t/* 2 5 29 14 subjectKeyIdentifier */\n\tMKACL_S(\t/* subjectKeyIdentifier */\n\t\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 2 5 29 15 keyUsage */\n\tMKACL_N(\t/* keyUsage */\n\t\tCRYPT_CERTINFO_KEYUSAGE,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_KEYUSAGE_NONE + 1, CRYPT_KEYUSAGE_LAST - 1 ) ),\n\n\t/* 2 5 29 16 privateKeyUsagePeriod */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_PRIVATEKEYUSAGEPERIOD,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* notBefore */\n\t\tCRYPT_CERTINFO_PRIVATEKEY_NOTBEFORE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_T(\t/* notBefore */\n\t\tCRYPT_CERTINFO_PRIVATEKEY_NOTAFTER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 17 subjectAltName */\n\tMKACL_N(\t/* subjectAltName */\n\t\tCRYPT_CERTINFO_SUBJECTALTNAME,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 18 issuerAltName */\n\tMKACL_N(\t/* issuerAltName */\n\t\tCRYPT_CERTINFO_ISSUERALTNAME,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 19 basicConstraints */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_BASICCONSTRAINTS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* cA */\n\t\tCRYPT_CERTINFO_CA,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* pathLenConstraint */\n\t\tCRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 64 ) ),\n\n\t/* 2 5 29 20 cRLNumber */\n\tMKACL_N(\t/* cRLNumber */\n\t\tCRYPT_CERTINFO_CRLNUMBER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, RANGE_MAX ) ),\n\n\t/* 2 5 29 21 cRLReason */\n\tMKACL_N(\t/* cRLReason */\n\t\t/* We allow a range up to the last extended reason because the cert-\n\t\t   handling code transparently maps one to the other to provide the\n\t\t   illusion of a unified crlReason attribute */\n\t\tCRYPT_CERTINFO_CRLREASON,\n\t\tST_CERT_CRL | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREQ_REV( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASON_UNSPECIFIED, CRYPT_CRLEXTREASON_LAST - 1 ) ),\n\n\t/* 2 5 29 23 holdInstructionCode */\n\tMKACL_N(\t/* holdInstructionCode */\n\t\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE,\n\t\tST_CERT_CRL | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREQ_REV_PKIX_FULL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_HOLDINSTRUCTION_NONE + 1, CRYPT_HOLDINSTRUCTION_LAST - 1 ) ),\n\n\t/* 2 5 29 24 invalidityDate */\n\tMKACL_T(\t/* invalidityDate */\n\t\tCRYPT_CERTINFO_INVALIDITYDATE,\n\t\tST_CERT_CRL | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREQ_REV( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 27 deltaCRLIndicator */\n\tMKACL_N(\t/* deltaCRLIndicator */\n\t\tCRYPT_CERTINFO_DELTACRLINDICATOR,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, RANGE_MAX ) ),\n\n\t/* 2 5 29 28 issuingDistributionPoint */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_ISSUINGDISTRIBUTIONPOINT,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RxD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* distributionPointName.fullName */\n\t\tCRYPT_CERTINFO_ISSUINGDIST_FULLNAME,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RxD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_B(\t/* onlyContainsUserCerts */\n\t\tCRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* onlyContainsCACerts */\n\t\tCRYPT_CERTINFO_ISSUINGDIST_CACERTSONLY,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* onlySomeReasons */\n\t\tCRYPT_CERTINFO_ISSUINGDIST_SOMEREASONSONLY,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASONFLAG_UNUSED, CRYPT_CRLREASONFLAG_LAST - 1 ) ),\n\tMKACL_B(\t/* indirectCRL */\n\t\tCRYPT_CERTINFO_ISSUINGDIST_INDIRECTCRL,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 29 certificateIssuer */\n\tMKACL_N(\t/* certificateIssuer */\n\t\tCRYPT_CERTINFO_CERTIFICATEISSUER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_PARTIAL( Rxx_RxD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 30 nameConstraints */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_NAMECONSTRAINTS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* permittedSubtrees */\n\t\tCRYPT_CERTINFO_PERMITTEDSUBTREES,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* excludedSubtrees */\n\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 31 cRLDistributionPoint */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CRLDISTRIBUTIONPOINT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* distributionPointName.fullName */\n\t\tCRYPT_CERTINFO_CRLDIST_FULLNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* reasons */\n\t\tCRYPT_CERTINFO_CRLDIST_REASONS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASONFLAG_UNUSED, CRYPT_CRLREASONFLAG_LAST - 1 ) ),\n\tMKACL_N(\t/* cRLIssuer */\n\t\tCRYPT_CERTINFO_CRLDIST_CRLISSUER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 32 certificatePolicies */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CERTIFICATEPOLICIES,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* policyInformation.policyIdentifier */\n\t\tCRYPT_CERTINFO_CERTPOLICYID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* policyInformation.policyQualifiers.qualifier.cPSuri */\n\t\tCRYPT_CERTINFO_CERTPOLICY_CPSURI,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.organization */\n\t\tCRYPT_CERTINFO_CERTPOLICY_ORGANIZATION,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 200 ) ),\n\tMKACL_N(\t/* policyInformation.policyQualifiers.qualifier.userNotice.noticeRef.noticeNumbers */\n\t\tCRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 1024 ) ),\n\tMKACL_S(\t/* policyInformation.policyQualifiers.qualifier.userNotice.explicitText */\n\t\tCRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 200 ) ),\n\n\t/* 2 5 29 33 policyMappings */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_POLICYMAPPINGS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* policyMappings.issuerDomainPolicy */\n\t\tCRYPT_CERTINFO_ISSUERDOMAINPOLICY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* policyMappings.subjectDomainPolicy */\n\t\tCRYPT_CERTINFO_SUBJECTDOMAINPOLICY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\n\t/* 2 5 29 35 authorityKeyIdentifier */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_AUTHORITYKEYIDENTIFIER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* keyIdentifier */\n\t\tCRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\tMKACL_N(\t/* authorityCertIssuer */\n\t\tCRYPT_CERTINFO_AUTHORITY_CERTISSUER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_S(\t/* authorityCertSerialNumber */\n\t\tCRYPT_CERTINFO_AUTHORITY_CERTSERIALNUMBER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_PARTIAL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 2 5 29 36 policyConstraints */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_POLICYCONSTRAINTS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* policyConstraints.requireExplicitPolicy */\n\t\tCRYPT_CERTINFO_REQUIREEXPLICITPOLICY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 64 ) ),\n\tMKACL_N(\t/* policyConstraints.inhibitPolicyMapping */\n\t\tCRYPT_CERTINFO_INHIBITPOLICYMAPPING,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 64 ) ),\n\n\t/* 2 5 29 37 extKeyUsage */\n\tMKACL_N(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_EXTKEYUSAGE,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* individualCodeSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_INDIVIDUALCODESIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* commercialCodeSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_COMMERCIALCODESIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* certTrustListSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_CERTTRUSTLISTSIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* timeStampSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_TIMESTAMPSIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* serverGatedCrypto */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_SERVERGATEDCRYPTO,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* encrypedFileSystem */\n\t\tCRYPT_CERTINFO_EXTKEY_MS_ENCRYPTEDFILESYSTEM,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* serverAuth */\n\t\tCRYPT_CERTINFO_EXTKEY_SERVERAUTH,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* clientAuth */\n\t\tCRYPT_CERTINFO_EXTKEY_CLIENTAUTH,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* codeSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_CODESIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* emailProtection */\n\t\tCRYPT_CERTINFO_EXTKEY_EMAILPROTECTION,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ipsecEndSystem */\n\t\tCRYPT_CERTINFO_EXTKEY_IPSECENDSYSTEM,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ipsecTunnel */\n\t\tCRYPT_CERTINFO_EXTKEY_IPSECTUNNEL,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ipsecUser */\n\t\tCRYPT_CERTINFO_EXTKEY_IPSECUSER,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* timeStamping */\n\t\tCRYPT_CERTINFO_EXTKEY_TIMESTAMPING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ocspSigning */\n\t\tCRYPT_CERTINFO_EXTKEY_OCSPSIGNING,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* directoryService */\n\t\tCRYPT_CERTINFO_EXTKEY_DIRECTORYSERVICE,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* anyExtendedKeyUsage */\n\t\t/* This extension exists solely as a bugfix for a circular\n\t\t   definition in the PKIX RFC and introduces a number of further\n\t\t   problems, to avoid falling into this rathole we don't allow\n\t\t   the creation of certs with this usage type */\n\t\tCRYPT_CERTINFO_EXTKEY_ANYKEYUSAGE,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* serverGatedCrypto */\n\t\tCRYPT_CERTINFO_EXTKEY_NS_SERVERGATEDCRYPTO,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* serverGatedCrypto CA */\n\t\tCRYPT_CERTINFO_EXTKEY_VS_SERVERGATEDCRYPTO_CA,\n\t\tST_CERT_ANY_CERT | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTIFICATES( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* 2 5 29 40 crlStreamIdentifier */\n\tMKACL_N(\t/* crlStreamIdentifier */\n\t\tCRYPT_CERTINFO_CRLSTREAMIDENTIFIER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 64 ) ),\n\n\t/* 2 5 29 46 freshestCRL */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_FRESHESTCRL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* distributionPointName.fullName */\n\t\tCRYPT_CERTINFO_FRESHESTCRL_FULLNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* reasons */\n\t\tCRYPT_CERTINFO_FRESHESTCRL_REASONS,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASONFLAG_UNUSED, CRYPT_CRLREASONFLAG_LAST - 1 ) ),\n\tMKACL_N(\t/* cRLIssuer */\n\t\tCRYPT_CERTINFO_FRESHESTCRL_CRLISSUER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_ATTRCERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 2 5 29 47 orderedList */\n\tMKACL_N(\t/* orderedList */\n\t\tCRYPT_CERTINFO_ORDEREDLIST,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 1 ) ),\n\n\t/* 2 5 29 51 baseUpdateTime */\n\tMKACL_T(\t/* baseUpdateTime */\n\t\tCRYPT_CERTINFO_BASEUPDATETIME,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 53 deltaInfo */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_DELTAINFO,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* deltaLocation */\n\t\tCRYPT_CERTINFO_DELTAINFO_LOCATION,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_T(\t/* nextDelta */\n\t\tCRYPT_CERTINFO_DELTAINFO_NEXTDELTA,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 54 inhibitAnyPolicy */\n\tMKACL_N(\t/* inhibitAnyPolicy */\n\t\tCRYPT_CERTINFO_INHIBITANYPOLICY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 64 ) ),\n\n\t/* 2 5 29 58 toBeRevoked */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_TOBEREVOKED,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* certificateIssuer */\n\t\tCRYPT_CERTINFO_TOBEREVOKED_CERTISSUER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* reasonCode */\n\t\tCRYPT_CERTINFO_TOBEREVOKED_REASONCODE,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASON_UNSPECIFIED, CRYPT_CRLEXTREASON_LAST - 1 ) ),\n\tMKACL_T(\t/* revocationTime */\n\t\tCRYPT_CERTINFO_TOBEREVOKED_REVOCATIONTIME,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* certSerialNumber */\n\t\tCRYPT_CERTINFO_TOBEREVOKED_CERTSERIALNUMBER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 2 5 29 59 revokedGroups */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* certificateIssuer */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_CERTISSUER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* reasonCode */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_REASONCODE,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASON_UNSPECIFIED, CRYPT_CRLEXTREASON_LAST - 1 ) ),\n\tMKACL_T(\t/* revocationTime */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_INVALIDITYDATE,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* startingNumber */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_STARTINGNUMBER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\tMKACL_S(\t/* endingNumber */\n\t\tCRYPT_CERTINFO_REVOKEDGROUPS_ENDINGNUMBER,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\n\t/* 2 5 29 60 expiredCertsOnCRL */\n\tMKACL_T(\t/* expiredCertsOnCRL */\n\t\tCRYPT_CERTINFO_EXPIREDCERTSONCRL,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 5 29 63 aaIssuingDistributionPoint */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_AAISSUINGDISTRIBUTIONPOINT,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RxD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* distributionPointName.fullName */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_FULLNAME,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RxD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* onlySomeReasons */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_SOMEREASONSONLY,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CRLREASONFLAG_UNUSED, CRYPT_CRLREASONFLAG_LAST - 1 ) ),\n\tMKACL_B(\t/* indirectCRL */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_INDIRECTCRL,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* containsUserAttributeCerts */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_USERATTRCERTS,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\t\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* containsAACerts */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_AACERTS,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* containsSOAPublicKeyCerts */\n\t\tCRYPT_CERTINFO_AAISSUINGDIST_SOACERTS,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTREV_PKIX_FULL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 16 840 1 113730 1 x Netscape extensions (obsolete) */\n\tMKACL_N(\t/* netscape-cert-type */\n\t\t/* This attribute can't normally be set, however when creating a\n\t\t   template of disallowed attributes to apply to an about-to-be-\n\t\t   issued cert we need to be able to set it to mask out any\n\t\t   attributes of this type that may have come in via a cert\n\t\t   request */\n\t\tCRYPT_CERTINFO_NS_CERTTYPE,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_SPECIAL_CERTIFICATES( Rxx_RWx_Rxx_Rxx ),\t\t/* OBSOLETE */\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_NS_CERTTYPE_SSLCLIENT, CRYPT_NS_CERTTYPE_LAST - 1 ) ),\n\tMKACL_S(\t/* netscape-base-url */\n\t\tCRYPT_CERTINFO_NS_BASEURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-revocation-url */\n\t\tCRYPT_CERTINFO_NS_REVOCATIONURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-ca-revocation-url */\n\t\tCRYPT_CERTINFO_NS_CAREVOCATIONURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-cert-renewal-url */\n\t\tCRYPT_CERTINFO_NS_CERTRENEWALURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-ca-policy-url */\n\t\tCRYPT_CERTINFO_NS_CAPOLICYURL,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-ssl-server-name */\n\t\tCRYPT_CERTINFO_NS_SSLSERVERNAME,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* netscape-comment */\n\t\tCRYPT_CERTINFO_NS_COMMENT,\n\t\tST_CERT_ANY_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, MAX_ATTRIBUTE_SIZE ) ),\n\n\t/* 2 23 42 7 0 SET hashedRootKey */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SET_HASHEDROOTKEY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* rootKeyThumbPrint */\n\t\tCRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 20, 20 ) ),\n\n\t/* 2 23 42 7 1 SET certificateType */\n\tMKACL_N(\t/* certificateType */\n\t\tCRYPT_CERTINFO_SET_CERTIFICATETYPE,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_SET_CERTTYPE_CARD, CRYPT_SET_CERTTYPE_LAST - 1 ) ),\n\n\t/* 2 23 42 7 2 SET merchantData */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SET_MERCHANTDATA,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* merID */\n\t\tCRYPT_CERTINFO_SET_MERID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 30 ) ),\n\tMKACL_S(\t/* merAcquirerBIN */\n\t\tCRYPT_CERTINFO_SET_MERACQUIRERBIN,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 6, 6 ) ),\n\tMKACL_S(\t/* merNames.language */\n\t\tCRYPT_CERTINFO_SET_MERCHANTLANGUAGE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 35 ) ),\n\tMKACL_S(\t/* merNames.name */\n\t\tCRYPT_CERTINFO_SET_MERCHANTNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 50 ) ),\n\tMKACL_S(\t/* merNames.city */\n\t\tCRYPT_CERTINFO_SET_MERCHANTCITY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 50 ) ),\n\tMKACL_S(\t/* merNames.stateProvince */\n\t\tCRYPT_CERTINFO_SET_MERCHANTSTATEPROVINCE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 50 ) ),\n\tMKACL_S(\t/* merNames.postalCode */\n\t\tCRYPT_CERTINFO_SET_MERCHANTPOSTALCODE,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 50 ) ),\n\tMKACL_S(\t/* merNames.countryName */\n\t\tCRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 50 ) ),\n\tMKACL_N(\t/* merCountry */\n\t\tCRYPT_CERTINFO_SET_MERCOUNTRY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 999 ) ),\n\tMKACL_B(\t/* merAuthFlag */\n\t\tCRYPT_CERTINFO_SET_MERAUTHFLAG,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 23 42 7 3 SET certCardRequired */\n\tMKACL_B(\t/* certCardRequired */\n\t\tCRYPT_CERTINFO_SET_CERTCARDREQUIRED,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 2 23 42 7 4 SET tunneling */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_SET_TUNNELING,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_B(\t/* tunneling */\n\t\tCRYPT_CERTINFO_SET_TUNNELINGFLAG,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* tunnelingAlgID */\n\t\tCRYPT_CERTINFO_SET_TUNNELINGALGID,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_CERT_OBSOLETE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/* Certificate: S/MIME attributes */\n\nstatic const ATTRIBUTE_ACL certSmimeACL[] = {\n\t/* 1 2 840 113549 1 9 3 contentType */\n\tMKACL_EX(\t/* contentType */\n\t\tCRYPT_CERTINFO_CMS_CONTENTTYPE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ), 0,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE_SUBRANGES, allowedContentTypeSubranges ),\n\n\t/* 1 2 840 113549 1 9 4 messageDigest */\n\tMKACL_S(\t/* messageDigest */\n\t\tCRYPT_CERTINFO_CMS_MESSAGEDIGEST,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) ),\n\n\t/* 1 2 840 113549 1 9 5 signingTime */\n\tMKACL_T(\t/* signingTime */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGTIME,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SPECIAL_CMSATTR( Rxx_RWD_Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\n\t/* 1 2 840 113549 1 9 6 counterSignature */\n\tMKACL_S(\t/* counterSignature */\n\t\tCRYPT_CERTINFO_CMS_COUNTERSIGNATURE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 64, MAX_ATTRIBUTE_SIZE ) ),\n\n\t/* 1 2 840 113549 1 9 13 signingDescription */\n\tMKACL_S(\t/* counterSignature */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, MAX_ATTRIBUTE_SIZE ) ),\n\n\t/* 1 2 840 113549 1 9 15 sMIMECapabilities */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAPABILITIES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* 3DES encryption */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_3DES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* AES encryption */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_AES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* CAST-128 encryption */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_CAST128,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* SHA2-ng hash */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_SHAng,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* SHA2-256 hash */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_SHA2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* SHA1 hash */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_SHA1,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* HMAC-SHA2-ng MAC */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* HMAC-SHA2-256 MAC */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* HMAC-SHA1 MAC */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* AuthEnc w.256-bit key */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* AuthEnc w.128-bit key */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* RSA with SHA-ng signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* RSA with SHA2-256 signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* RSA with SHA1 signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* DSA with SHA-1 signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ECDSA with SHA-ng signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ECDSA with SHA2-256 signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* ECDSA with SHA-1 signing */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* preferSignedData */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* canNotDecryptAny */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_CANNOTDECRYPTANY,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* preferBinaryInside */\n\t\tCRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE,\n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 1 receiptRequest */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_RECEIPTREQUEST,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* contentIdentifier */\n\t\tCRYPT_CERTINFO_CMS_RECEIPT_CONTENTIDENTIFIER,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 16, 64 ) ),\n\tMKACL_N(\t/* receiptsFrom */\n\t\tCRYPT_CERTINFO_CMS_RECEIPT_FROM,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 0, 1 ) ),\n\tMKACL_N(\t/* receiptsTo */\n\t\tCRYPT_CERTINFO_CMS_RECEIPT_TO,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 2 essSecurityLabel */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SECURITYLABEL,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* securityPolicyIdentifier */\n\t\tCRYPT_CERTINFO_CMS_SECLABEL_POLICY,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_N(\t/* securityClassification */\n\t\tCRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CLASSIFICATION_UNMARKED, CRYPT_CLASSIFICATION_LAST ) ),\n\tMKACL_S(\t/* privacyMark */\n\t\tCRYPT_CERTINFO_CMS_SECLABEL_PRIVACYMARK,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\tMKACL_S(\t/* securityCategories.securityCategory.type */\n\t\tCRYPT_CERTINFO_CMS_SECLABEL_CATTYPE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* securityCategories.securityCategory.value */\n\t\tCRYPT_CERTINFO_CMS_SECLABEL_CATVALUE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 512 ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 3 mlExpansionHistory */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_MLEXPANSIONHISTORY,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* mlData.mailListIdentifier.issuerAndSerialNumber */\n\t\tCRYPT_CERTINFO_CMS_MLEXP_ENTITYIDENTIFIER,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 512 ) ),\n\tMKACL_T(\t/* mlData.expansionTime */\n\t\tCRYPT_CERTINFO_CMS_MLEXP_TIME,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* mlData.mlReceiptPolicy.none */\n\t\tCRYPT_CERTINFO_CMS_MLEXP_NONE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* mlData.mlReceiptPolicy.insteadOf.generalNames.generalName */\n\t\tCRYPT_CERTINFO_CMS_MLEXP_INSTEADOF,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\tMKACL_N(\t/* mlData.mlReceiptPolicy.inAdditionTo.generalNames.generalName */\n\t\tCRYPT_CERTINFO_CMS_MLEXP_INADDITIONTO,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( FALSE, TRUE ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 4 contentHints */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_CONTENTHINTS,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* contentDescription */\n\t\tCRYPT_CERTINFO_CMS_CONTENTHINT_DESCRIPTION,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\tMKACL_N(\t/* contentType */\n\t\tCRYPT_CERTINFO_CMS_CONTENTHINT_TYPE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CONTENT_DATA, CRYPT_CONTENT_LAST - 1 ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 9 equivalentLabels */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_EQUIVALENTLABEL,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* securityPolicyIdentifier */\n\t\tCRYPT_CERTINFO_CMS_EQVLABEL_POLICY,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_N(\t/* securityClassification */\n\t\tCRYPT_CERTINFO_CMS_EQVLABEL_CLASSIFICATION,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_CLASSIFICATION_UNMARKED, CRYPT_CLASSIFICATION_LAST ) ),\n\tMKACL_S(\t/* privacyMark */\n\t\tCRYPT_CERTINFO_CMS_EQVLABEL_PRIVACYMARK,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 64 ) ),\n\tMKACL_S(\t/* securityCategories.securityCategory.type */\n\t\tCRYPT_CERTINFO_CMS_EQVLABEL_CATTYPE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* securityCategories.securityCategory.value */\n\t\tCRYPT_CERTINFO_CMS_EQVLABEL_CATVALUE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 512 ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 12 signingCertificate */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERTIFICATE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE_TSP( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* certs.essCertID */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE_TSP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* policies.policyInformation.policyIdentifier */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERT_POLICIES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE_TSP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 47 signingCertificateV2 */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* certs.essCertID */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* policies.policyInformation.policyIdentifier */\n\t\tCRYPT_CERTINFO_CMS_SIGNINGCERTV2_POLICIES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\n\t/* 1 2 840 113549 1 9 16 2 15 signaturePolicyID */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SIGNATUREPOLICYID,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* signaturePolicyID.sigPolicyID */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICYID,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 3, 32 ) ),\n\tMKACL_S(\t/* signaturePolicyID.sigPolicyHash */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICYHASH,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 32, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.cPSuri */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_CPSURI,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.organization */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_ORGANIZATION,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 200 ) ),\n\tMKACL_N(\t/* signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.noticeRef.noticeNumbers */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_NOTICENUMBERS,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 1024 ) ),\n\tMKACL_S(\t/* signaturePolicyID.sigPolicyQualifiers.sigPolicyQualifier.userNotice.explicitText */\n\t\tCRYPT_CERTINFO_CMS_SIGPOLICY_EXPLICITTEXT,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 200 ) ),\n\n\t/* 1 2 840 113549 1 9 16 9 signatureTypeIdentifier */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SIGTYPEIDENTIFIER,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* originatorSig */\n\t\tCRYPT_CERTINFO_CMS_SIGTYPEID_ORIGINATORSIG,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* domainSig */\n\t\tCRYPT_CERTINFO_CMS_SIGTYPEID_DOMAINSIG,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* additionalAttributesSig */\n\t\tCRYPT_CERTINFO_CMS_SIGTYPEID_ADDITIONALATTRIBUTES,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* reviewSig */\n\t\tCRYPT_CERTINFO_CMS_SIGTYPEID_REVIEWSIG,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* 1 2 840 113549 1 9 25 3 randomNonce */\n\tMKACL_S(\t/* randomNonce */\n\t\t/* This is valid in RTCS requests, which are occasionally\n\t\t   communicated using a CMS content-type that can't provide\n\t\t   attributes so they need to be bundled with the request instead */\n\t\tCRYPT_CERTINFO_CMS_NONCE,\n\t\tST_CERT_CMSATTR | ST_CERT_RTCS_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_CERTVAL( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 4, CRYPT_MAX_HASHSIZE ) ),\n\n\t/* SCEP attributes:\n\t   2 16 840 1 113733 1 9 2 messageType\n\t   2 16 840 1 113733 1 9 3 pkiStatus\n\t   2 16 840 1 113733 1 9 4 failInfo\n\t   2 16 840 1 113733 1 9 5 senderNonce\n\t   2 16 840 1 113733 1 9 6 recipientNonce\n\t   2 16 840 1 113733 1 9 7 transID */\n\tMKACL_S(\t/* messageType */\n\t\tCRYPT_CERTINFO_SCEP_MESSAGETYPE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 2 ) ),\n\tMKACL_S(\t/* pkiStatus */\n\t\tCRYPT_CERTINFO_SCEP_PKISTATUS,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 1 ) ),\n\tMKACL_S(\t/* failInfo */\n\t\tCRYPT_CERTINFO_SCEP_FAILINFO,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 1, 1 ) ),\n\tMKACL_S(\t/* senderNonce */\n\t\tCRYPT_CERTINFO_SCEP_SENDERNONCE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 8, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* recipientNonce */\n\t\tCRYPT_CERTINFO_SCEP_RECIPIENTNONCE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 8, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* transID */\n\t\tCRYPT_CERTINFO_SCEP_TRANSACTIONID,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_SCEP( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, CRYPT_MAX_TEXTSIZE ) ),\n\n\t/* 1 3 6 1 4 1 311 2 1 10 spcAgencyInfo */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SPCAGENCYINFO,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* spcAgencyInfo.url */\n\t\tCRYPT_CERTINFO_CMS_SPCAGENCYURL,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\n\t/* 1 3 6 1 4 1 311 2 1 11 spcStatementType */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SPCSTATEMENTTYPE,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_N(\t/* individualCodeSigning */\n\t\tCRYPT_CERTINFO_CMS_SPCSTMT_INDIVIDUALCODESIGNING,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_N(\t/* commercialCodeSigning */\n\t\tCRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* 1 3 6 1 4 1 311 2 1 12 spcOpusInfo */\n\tMKACL_B(\t/* Extension present flag */\n\t\tCRYPT_CERTINFO_CMS_SPCOPUSINFO,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RxD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* spcOpusInfo.name */\n\t\tCRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( 2, 128 ) ),\n\tMKACL_S(\t/* spcOpusInfo.url */\n\t\tCRYPT_CERTINFO_CMS_SPCOPUSINFO_URL,\n\t\tST_CERT_CMSATTR, ST_NONE, ST_NONE, \n\t\tMKPERM_CMSATTR_OBSCURE( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tRANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n#endif /* USE_CERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKeyset ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_KEYSETS\n\n/* Keyset attributes */\n\nstatic const ATTRIBUTE_ACL keysetACL[] = {\n\tMKACL_S(\t/* Keyset query */\n\t\tCRYPT_KEYINFO_QUERY,\n\t\tST_NONE, ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE, ST_NONE, \n\t\tMKPERM_DBMS( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_KEYSET ),\n\t\tRANGE( 6, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Query of requests in cert store */\n\t\tCRYPT_KEYINFO_QUERY_REQUESTS,\n\t\tST_NONE, ST_KEYSET_DBMS_STORE, ST_NONE, \n\t\tMKPERM_DBMS( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_KEYSET ),\n\t\tRANGE( 6, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n#endif /* USE_KEYSETS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tDevice ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Device attributes */\n\nstatic const ATTRIBUTE_ACL deviceACL[] = {\n\tMKACL_S_EX(\t/* Initialise device for use */\n\t\tCRYPT_DEVINFO_INITIALISE,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xWx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S_EX(\t/* Authenticate user to device */\n\t\t/* This is allowed in both the low and high states since the device\n\t\t   may be in the SSO initialised state and all we're doing is\n\t\t   switching it to the user initialised state */\n\t\tCRYPT_DEVINFO_AUTHENT_USER,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xWx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S_EX(\t/* Authenticate supervisor to dev.*/\n\t\tCRYPT_DEVINFO_AUTHENT_SUPERVISOR,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Set user authent.value */\n\t\tCRYPT_DEVINFO_SET_AUTHENT_USER,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Set supervisor auth.val.*/\n\t\tCRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Zeroise device */\n\t\tCRYPT_DEVINFO_ZEROISE,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_B(\t/* Whether user is logged in */\n\t\tCRYPT_DEVINFO_LOGGEDIN,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_DEVICE ) ),\n\tMKACL_S(\t/* Device/token label */\n\t\tCRYPT_DEVINFO_LABEL,\n\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE, \n\t\tMKPERM( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_DEVICE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tEnvelope ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_ENVELOPES\n\nstatic const RANGE_SUBRANGE_TYPE allowedSigResultSubranges[] = {\n\t/* We make the error subrange start at CRYPT_ERROR_MEMORY rather than\n\t   the generic CRYPT_ERROR_PARAM1, which is the same as CRYPT_ERROR,\n\t   the end-of-range marker */\n\t{ CRYPT_OK, CRYPT_OK },\n\t{ CRYPT_ERROR_MEMORY, CRYPT_ENVELOPE_RESOURCE },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nstatic const ATTRIBUTE_ACL subACL_EnvinfoContentType[] = {\n#if 0\n\tMKACL_N(\t/* Envelope: Read/write */\n\t\tCRYPT_ENVINFO_CONTENTTYPE,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedContentTypeSubranges ),\n\t\tRANGE( CRYPT_CONTENT_NONE + 1, CRYPT_CONTENT_LAST - 1 ) ),\n\tMKACL_N(\t/* Deenvelope: Read-only */\n\t\tCRYPT_ENVINFO_CONTENTTYPE,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( CRYPT_CONTENT_NONE + 1, CRYPT_CONTENT_LAST - 1 ) ),\n#else\n\tMKACL_EX(\t/* Envelope: Read/write */\n\t\tCRYPT_ENVINFO_CONTENTTYPE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedContentTypeSubranges ),\n\tMKACL_EX(\t/* Deenvelope: Read-only */\n\t\tCRYPT_ENVINFO_CONTENTTYPE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ), 0,\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedContentTypeSubranges ),\n#endif /* 0 */\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_EnvinfoIntegrity[] = {\n\tMKACL_N(\t/* Envelope: Write-only */\n\t\tCRYPT_ENVINFO_INTEGRITY,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), \n\t\tRANGE( CRYPT_INTEGRITY_NONE, CRYPT_INTEGRITY_FULL ) ),\n\tMKACL_N(\t/* De-envelope: Read-only */\n\t\tCRYPT_ENVINFO_INTEGRITY,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), \n\t\tRANGE( CRYPT_INTEGRITY_NONE, CRYPT_INTEGRITY_FULL ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_EnvinfoSignature[] = {\n\tMKACL_O(\t/* Envelope: Write-only */\n\t\tCRYPT_ENVINFO_SIGNATURE,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxPKC ),\n\tMKACL_O(\t/* De-envelope: Read/write */\n\t\t/* This is readable and writeable since it can be used to add a sig-\n\t\t   check key to an envelope that doesn't include certs */\n\t\tCRYPT_ENVINFO_SIGNATURE,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxPKC ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_EnvinfoSignatureExtraData[] = {\n\tMKACL_O(\t/* Envelope: Write-only */\n\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA,\n\t\tST_NONE, ST_ENV_ENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCMSAttr ),\n\tMKACL_O(\t/* De-envelope: Read-only */\n\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCMSAttr ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_EnvinfoTimestamp[] = {\n\tMKACL_O(\t/* Envelope: Write-only TSP session */\n\t\tCRYPT_ENVINFO_TIMESTAMP,\n\t\tST_NONE, ST_ENV_ENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectSessionTSP ),\n\tMKACL_O(\t/* De-envelope: Read-only sub-envelope */\n\t\tCRYPT_ENVINFO_TIMESTAMP,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectDeenvelope ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Envelope attributes */\n\nstatic const ATTRIBUTE_ACL envelopeACL[] = {\n\tMKACL_N(\t/* Data size information */\n\t\t/* The maximum length is adjusted by MAX_INTLENGTH_DELTA bytes\n\t\t   because what this attribute specifies is only the payload size\n\t\t   and not the overall message size, which could be up to\n\t\t   MAX_INTLENGTH_DELTA bytes larger */\n\t\tCRYPT_ENVINFO_DATASIZE,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( 0, MAX_INTLENGTH - MAX_INTLENGTH_DELTA ) ),\n\tMKACL_N(\t/* Compression information */\n\t\tCRYPT_ENVINFO_COMPRESSION,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\tMKACL_X(\t/* Inner CMS content type */\n\t\tCRYPT_ENVINFO_CONTENTTYPE,\n\t\tST_NONE, ST_ENV_ANY, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tsubACL_EnvinfoContentType ),\n\tMKACL_B(\t/* Detached signature */\n\t\tCRYPT_ENVINFO_DETACHEDSIGNATURE,\n\t\tST_NONE, ST_ENV_ANY, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ) ),\n\tMKACL_EX(\t/* Signature check result */\n\t\t/* This is a special case because an OK status is positive but an\n\t\t   error status is negative, which spans two range types.  To handle\n\t\t   this we treat it as two distinct subranges, the positive CRYPT_OK\n\t\t   and the negative error values */\n\t\tCRYPT_ENVINFO_SIGNATURE_RESULT, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xxx ), 0,\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE_SUBRANGES, allowedSigResultSubranges ),\n\tMKACL_X(\t/* Integrity-protection level */\n\t\tCRYPT_ENVINFO_INTEGRITY,\n\t\tST_NONE, ST_ENV_ANY, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tsubACL_EnvinfoIntegrity ),\n\tMKACL_S(\t/* User password */\n\t\tCRYPT_ENVINFO_PASSWORD,\n\t\tST_NONE, ST_ENV_ANY, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_O(\t/* Conventional encryption key */\n\t\tCRYPT_ENVINFO_KEY,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxConv ),\n\tMKACL_X(\t/* Signature/signature check key */\n\t\tCRYPT_ENVINFO_SIGNATURE,\n\t\tST_NONE, ST_ENV_ANY, ST_NONE, \n\t\tMKPERM_ENVELOPE( RWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tsubACL_EnvinfoSignature ),\n\tMKACL_X(\t/* Extra information added to CMS sigs */\n\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tsubACL_EnvinfoSignatureExtraData ),\n\tMKACL_S(\t/* Recipient email address */\n\t\tCRYPT_ENVINFO_RECIPIENT,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_O(\t/* PKC encryption key */\n\t\tCRYPT_ENVINFO_PUBLICKEY,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxPKC ),\n\tMKACL_O(\t/* PKC decryption key */\n\t\tCRYPT_ENVINFO_PRIVATEKEY,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),  &objectCtxPKC ),\n\tMKACL_S(\t/* Label of PKC decryption key */\n\t\tCRYPT_ENVINFO_PRIVATEKEY_LABEL,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_O(\t/* Originator info/key */\n\t\t/* 18/7/16 Historic value only needed for Fortezza, permissions\n\t\t\t\t   formerly 'MKPERM_ENVELOPE( xxx_xWx )' */\n\t\tCRYPT_ENVINFO_ORIGINATOR,\n\t\tST_NONE, ST_ENV_ENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxPKC ),\n\tMKACL_O(\t/* Session key */\n\t\tCRYPT_ENVINFO_SESSIONKEY,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxConv ),\n\tMKACL_O(\t/* Hash value */\n\t\tCRYPT_ENVINFO_HASH,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectCtxHash ),\n\tMKACL_X(\t/* Timestamp */\n\t\tCRYPT_ENVINFO_TIMESTAMP,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ),\n\t\tsubACL_EnvinfoTimestamp ),\n\tMKACL_O(\t/* Signature check keyset */\n\t\tCRYPT_ENVINFO_KEYSET_SIGCHECK,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectKeyset ),\n\tMKACL_O(\t/* PKC encryption keyset */\n\t\tCRYPT_ENVINFO_KEYSET_ENCRYPT,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_ENV_PGP, ST_NONE, \n\t\tMKPERM_ENVELOPE( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectKeyset ),\n\tMKACL_O(\t/* PKC decryption keyset */\n\t\tCRYPT_ENVINFO_KEYSET_DECRYPT,\n\t\tST_NONE, ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_ENVELOPE( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_ENVELOPE ), &objectKeyset ),\n\tMKACL_END(), MKACL_END()\n\t};\n#endif /* USE_ENVELOPES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSession ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SESSIONS\n\nstatic const RANGE_SUBRANGE_TYPE allowedSubprotocolSubranges[] = {\n#ifdef USE_WEBSOCKETS\n\t{ CRYPT_SUBPROTOCOL_WEBSOCKETS, CRYPT_SUBPROTOCOL_WEBSOCKETS },\n#endif /* USE_WEBSOCKETS */\n#ifdef USE_EAP\n\t{ CRYPT_SUBPROTOCOL_EAPTTLS, CRYPT_SUBPROTOCOL_EAPTTLS },\n#endif /* USE_EAP */\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const RANGE_SUBRANGE_TYPE allowedSSHChannelSubranges[] = {\n\t{ CRYPT_UNUSED, CRYPT_UNUSED },\n\t{ 1, RANGE_MAX },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\nstatic const int allowedAuthResponses[] = \\\n\t{ CRYPT_UNUSED, FALSE, TRUE, TRUE_ALT, CRYPT_ERROR, CRYPT_ERROR };\n\nstatic const ATTRIBUTE_ACL subACL_SessinfoActive[] = {\n\tMKACL_B_EX(\t/* SSH/SSL: Can only be activated once */\n\t\tCRYPT_SESSINFO_ACTIVE,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_DATA, \n\t\tMKPERM_SESSIONS( Rxx_RWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_SESSION ) ),\n\tMKACL_B_EX(\t/* Ongoing protocol: Persistent connections */\n\t\tCRYPT_SESSINFO_ACTIVE,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_REQRESP, \n\t\tMKPERM_SESSIONS( RWx_RWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_SESSION ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoUsername[] = {\n\tMKACL_S(\t/* SSH/SSL/SCEP client: RWD for client auth */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSL | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSH server: Read-only for client auth */\n\t\t/* We can read this attribute in the low state because we might be\n\t\t   going back to the caller for confirmation before we transition\n\t\t   into the high state */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* CMP server: Read-only for client auth */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSL server: RW for client auth */\n\t\t/* For SSL the username doesn't work like a standard user name but\n\t\t   instead acts as a magic value to identify a shared secret in the\n\t\t   session cache which is used to peform an SSL resume when the\n\t\t   client connects.  Multiple username/password combinations can be\n\t\t   added, what's read back is either the last one added if the\n\t\t   session hasn't been activated, or the one that was used to provide\n\t\t   the encryption keys for the currently-active session */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* CMP client: RWD in both states for persistent conns */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_SESSIONS( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoPassword[] = {\n\tMKACL_S(\t/* SSH/SSL/SCEP client: Write-only for client auth */\n\t\tCRYPT_SESSINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSL | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( xxx_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSH server: Read-only from client auth */\n\t\t/* We can read this attribute in the low state because we might be\n\t\t   going back to the caller for confirmation before we transition\n\t\t   into the high state */\n\t\tCRYPT_SESSINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSL server: Write-only in both states for client auth */\n\t\tCRYPT_SESSINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* CMP client: Write-only in both states for persistent conns */\n\t\tCRYPT_SESSINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoPrivatekey[] = {\n\tMKACL_O(\t/* Server or SSH/SSL/SCEP client: Write-only */\n\t\tCRYPT_SESSINFO_PRIVATEKEY,\n\t\tST_NONE, ST_NONE, MK_ST_EXCEPTION( ST_SESS_ANY_SVR, ST_SESS_CERT_SVR ) | \\\n\t\t\t\t\t\t  ST_SESS_SSH | ST_SESS_SSL | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCtxPKC ),\n\tMKACL_O(\t/* CMP client: Write-only in both states for persistent conns */\n\t\tCRYPT_SESSINFO_PRIVATEKEY,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_SESSIONS( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCtxPKC ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoKeyset[] = {\n\tMKACL_O(\t/* SSH/TLS and cert status/access protocols: Certificate/pubkey auth.source */\n\t\tCRYPT_SESSINFO_KEYSET,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR | ST_SESS_SSL_SVR | \\\n\t\t\t\t\t\t  ST_SESS_RTCS_SVR | ST_SESS_OCSP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_CERT_SVR, \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectKeysetCerts ),\n\tMKACL_O(\t/* Cert management protocols: Certificate store */\n\t\tCRYPT_SESSINFO_KEYSET,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP_SVR | ST_SESS_SCEP_SVR, \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectKeysetCertstore ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoFingerprint[] = {\n\tMKACL_S(\t/* Client: Write-only low, read-only high */\n\t\tCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSH | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 20, 20 ) ),\n\tMKACL_S(\t/* Server: Read-only */\n\t\tCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 20, 20 ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoVersion[] = {\n\tMKACL_N(\t/* SSH: 2 */\n\t\tCRYPT_SESSINFO_VERSION,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 2, 2 ) ),\n#ifdef USE_SSL3\n\tMKACL_N(\t/* SSL: 0 (SSLv3), 1 (TLS 1.0), 2 (TLS 1.1), or 3 (TLS 1.2) */\n\t\tCRYPT_SESSINFO_VERSION,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 0, 3 ) ),\n#else\n\tMKACL_N(\t/* 1 (TLS 1.0), 2 (TLS 1.1), or 3 (TLS 1.2) */\n\t\tCRYPT_SESSINFO_VERSION,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, 3 ) ),\n#endif /* SSLv3 */\n\tMKACL_N(\t/* OCSP: 1 or 2 */\n\t\tCRYPT_SESSINFO_VERSION,\n\t\tST_NONE, ST_NONE, ST_SESS_OCSP | ST_SESS_OCSP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 1, 2 ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoSubprotocol[] = {\n\tMKACL_EX(\t/* SSL client: WebSockets, EAP-TTLS */\n\t\tCRYPT_SESSINFO_SSL_SUBPROTOCOL, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL, \n\t\tMKPERM_SESSIONS( Rxx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSubprotocolSubranges ),\n\tMKACL_EX(\t/* SSL server: WebSockets */\n\t\tCRYPT_SESSINFO_SSL_SUBPROTOCOL, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSubprotocolSubranges ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoRequest[] = {\n\tMKACL_O(\t/* RTCS session: RTCS request */\n\t\tCRYPT_SESSINFO_REQUEST,\n\t\tST_NONE, ST_NONE, ST_SESS_RTCS, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertSessionRTCSRequest ),\n\tMKACL_O(\t/* OCSP session: OCSP request */\n\t\tCRYPT_SESSINFO_REQUEST,\n\t\tST_NONE, ST_NONE, ST_SESS_OCSP, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertSessionOCSPRequest ),\n\tMKACL_O(\t/* CMP session: Cert/rev.request */\n\t\tCRYPT_SESSINFO_REQUEST,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertSessionCMPRequest ),\n\tMKACL_O(\t/* SCEP session: Signed or unsigned PKCS #10 request */\n\t\tCRYPT_SESSINFO_REQUEST,\n\t\tST_NONE, ST_NONE, ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertSessionPKCS10Request ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoResponse[] = {\n\tMKACL_O(\t/* RTCS session: RTCS response */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_RTCS, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertRTCSResponse ),\n\tMKACL_O(\t/* OCSP session: OCSP response */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_OCSP, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertOCSPResponse ),\n\tMKACL_O(\t/* SSL server: Client cert during handshake */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertificate ),\n\tMKACL_O(\t/* SSL, PKI mgt.session: Cert, cert.response */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_CMP | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_SCEP | ST_SESS_SCEP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertificate ),\n\tMKACL_O(\t/* TSP session: CMS enveloped timestamp */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_TSP, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectDeenvelope ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoCACertificate[] = {\n\tMKACL_O(\t/* SCEP: Read/write */\n\t\t/* This is write-only in the low state if supplied by the user, but \n\t\t   read-only in the high state if fetched by cryptlib as part of the \n\t\t   SCEP handshake */\n\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\tST_NONE, ST_NONE, ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertificate ),\n\tMKACL_O(\t/* CMP: Write-only */\n\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCertificate ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoRequesttype[] = {\n\tMKACL_N(\t/* CMP/SCEP client: Read/write */\n\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( CRYPT_REQUESTTYPE_NONE + 1, CRYPT_REQUESTTYPE_LAST - 1 ) ),\n\tMKACL_N(\t/* CMP/SCEP server: Read-only info from client */\n\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP_SVR | ST_SESS_SCEP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( CRYPT_REQUESTTYPE_NONE + 1, CRYPT_REQUESTTYPE_LAST - 1 ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoSSHChannel[] = {\n\tMKACL_EX(\t/* SSH client: Read/write */\n\t\t/* Write = CRYPT_UNUSED to create channel, read = channel number */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH, \n\t\tMKPERM_SSH_EXT( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSSHChannelSubranges ),\n\tMKACL_EX(\t/* SSH server: Read-only info from client */\n\t\t/* Write = CRYPT_UNUSED to create channel, read = channel number */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_xxx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_SUBRANGES, allowedSSHChannelSubranges ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoSSHChannelType[] = {\n\tMKACL_S(\t/* SSH client: Read/write */\n\t\t/* Shortest valid name = \"exec\" */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH, \n\t\tMKPERM_SSH_EXT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 4, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSH server: Read-only info from client */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 7, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\nstatic const ATTRIBUTE_ACL subACL_SessinfoSSHChannelArg1[] = {\n\tMKACL_S(\t/* SSH client: Read/write */\n\t\t/* Shortest valid name = \"sftp\" */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH, \n\t\tMKPERM_SSH_EXT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 4, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSH server: Read-only info from client */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 4, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Session attributes */\n\nstatic const ATTRIBUTE_ACL sessionACL[] = {\n\tMKACL_X_EX(\t/* Whether session is active */\n\t\tCRYPT_SESSINFO_ACTIVE,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY, \n\t\tMKPERM_SESSIONS( RWx_RWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoActive ),\n\tMKACL_B(\t/* Whether network connection is active */\n\t\tCRYPT_SESSINFO_CONNECTIONACTIVE,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ) ),\n\tMKACL_X(\t/* User name */\n\t\tCRYPT_SESSINFO_USERNAME,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_DATA | ST_SESS_CMP | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoUsername ),\n\tMKACL_X(\t/* Password */\n\t\tCRYPT_SESSINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_DATA | ST_SESS_CMP | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( RWD_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoPassword ),\n\tMKACL_X(\t/* Server/client private key */\n\t\tCRYPT_SESSINFO_PRIVATEKEY,\n\t\tST_NONE, ST_NONE, MK_ST_EXCEPTION( ST_SESS_ANY_SVR, ST_SESS_CERT_SVR ) | \\\n\t\t\t\t\t\t  ST_SESS_SSH | ST_SESS_SSL | ST_SESS_CMP | \\\n\t\t\t\t\t\t  ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( xWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoPrivatekey ),\n\tMKACL_X(\t/* Certificate store/auth.keyset */\n\t\tCRYPT_SESSINFO_KEYSET,\n\t\tST_NONE, ST_NONE, MK_ST_EXCEPTION( ST_SESS_ANY_SVR, ST_SESS_TSP_SVR ), \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoKeyset ),\n\tMKACL_EX(\t/* Session authorisation OK */\n\t\tCRYPT_SESSINFO_AUTHRESPONSE, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR | ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( RWx_RWx ), 0,\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_ALLOWEDVALUES, allowedAuthResponses ),\n\tMKACL_S(\t/* Server name */\n\t\tCRYPT_SESSINFO_SERVER_NAME,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY, \n\t\tMKPERM_SESSIONS( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 2, MAX_URL_SIZE ) ),\n\tMKACL_N(\t/* Server port number */\n\t\tCRYPT_SESSINFO_SERVER_PORT,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY, \n\t\tMKPERM_SESSIONS( Rxx_RWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( MIN_PORT_NUMBER, MAX_PORT_NUMBER ) ),\n\tMKACL_X(\t/* Server key fingerprint */\n\t\tCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSH | ST_SESS_SCEP | \\\n\t\t\t\t\t\t  ST_SESS_SSH_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoFingerprint ),\n\tMKACL_S(\t/* Client name */\n\t\tCRYPT_SESSINFO_CLIENT_NAME,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_SVR, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( 2, MAX_URL_SIZE ) ),\n\tMKACL_N(\t/* Client port number */\n\t\tCRYPT_SESSINFO_CLIENT_PORT,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY_SVR, \n\t\tMKPERM_SESSIONS( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( MIN_PORT_NUMBER, MAX_PORT_NUMBER ) ),\n\tMKACL_O(\t/* Transport mechanism - Disabled */\n\t\tCRYPT_SESSINFO_SESSION,\n\t\tST_NONE, ST_NONE, ST_SESS_RTCS | ST_SESS_RTCS_SVR | \\\n\t\t\t\t\t\t  ST_SESS_OCSP | ST_SESS_OCSP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_TSP | ST_SESS_TSP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_CMP | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_SCEP | ST_SESS_SCEP_SVR, \n\t\tMKPERM_SESSIONS( xxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectSessionDataClient ),\n\tMKACL_N(\t/* User-supplied network socket */\n\t\tCRYPT_SESSINFO_NETWORKSOCKET,\n\t\tST_NONE, ST_NONE, ST_SESS_ANY, \n\t\tMKPERM_SESSIONS( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE_ANY ),\n\n\tMKACL_X(\t/* Session protocol version */\n\t\tCRYPT_SESSINFO_VERSION,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR | ST_SESS_SSL | \\\n\t\t\t\t\t\t  ST_SESS_SSL_SVR | ST_SESS_OCSP | ST_SESS_OCSP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoVersion ),\n\tMKACL_X(\t/* Cert.request object */\n\t\t/* The object can be updated in both states for persistent\n\t\t   connections */\n\t\tCRYPT_SESSINFO_REQUEST,\n\t\tST_NONE, ST_NONE, ST_SESS_RTCS | ST_SESS_OCSP | ST_SESS_CMP | \\\n\t\t\t\t\t\t  ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoRequest ),\n\tMKACL_X(\t/* Cert.response object */\n\t\tCRYPT_SESSINFO_RESPONSE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR | ST_SESS_RTCS | \\\n\t\t\t\t\t\t  ST_SESS_OCSP | ST_SESS_TSP | ST_SESS_CMP | \\\n\t\t\t\t\t\t  ST_SESS_CMP_SVR | ST_SESS_SCEP | ST_SESS_SCEP_SVR, \n\t\tMKPERM_SESSIONS( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoResponse ),\n\tMKACL_X(\t/* Issuing CA certificate */\n\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP | ST_SESS_SCEP, \n\t\tMKPERM_SESSIONS( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoCACertificate ),\n\n\tMKACL_X(\t/* CMP/SCEP request type */\n\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP | ST_SESS_CMP_SVR | \\\n\t\t\t\t\t\t  ST_SESS_SCEP | ST_SESS_SCEP_SVR, \n\t\tMKPERM_CMP( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoRequesttype ),\n\tMKACL_O(\t/* Private-key keyset */\n\t\tCRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\tST_NONE, ST_NONE, ST_SESS_CMP, \n\t\tMKPERM_CMP( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectKeysetPrivate ),\n\n\tMKACL_X(\t/* SSH current channel */\n\t\t/* Write = CRYPT_UNUSED to create channel, read = channel number */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoSSHChannel ),\n\tMKACL_X(\t/* SSH channel type */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoSSHChannelType ),\n\tMKACL_X(\t/* SSH channel argument 1 */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoSSHChannelArg1 ),\n\tMKACL_S(\t/* SSH channel argument 2 */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_ARG2,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 5, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_B(\t/* SSH channel active */\n\t\tCRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSH | ST_SESS_SSH_SVR, \n\t\tMKPERM_SSH_EXT( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ) ),\n\n\tMKACL_N(\t/* SSL/TLS protocol options */\n\t\tCRYPT_SESSINFO_SSL_OPTIONS,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR, \n\t\tMKPERM_SSL( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tRANGE( CRYPT_SSLOPTION_NONE, CRYPT_SSLOPTION_MAX ) ),\n\tMKACL_X(\t/* SSL/TLS additional sub-protocol */\n\t\tCRYPT_SESSINFO_SSL_SUBPROTOCOL,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR, \n\t\tMKPERM_SESSIONS( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ),\n\t\tsubACL_SessinfoSubprotocol ),\n\tMKACL_S(\t/* SSL/TLS WebSockets sub-protocol */\n\t\tCRYPT_SESSINFO_SSL_WSPROTOCOL,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL | ST_SESS_SSL_SVR, \n\t\tMKPERM_SSL( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 3, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* SSL/TLS EAP challenge */\n\t\tCRYPT_SESSINFO_SSL_EAPCHALLENGE,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL, \n\t\tMKPERM_SSL( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 8, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* SSL/TLS EAP key */\n\t\tCRYPT_SESSINFO_SSL_EAPKEY,\n\t\tST_NONE, ST_NONE, ST_SESS_SSL, \n\t\tMKPERM_SSL( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), RANGE( 8, CRYPT_MAX_HASHSIZE ) ),\n\n\tMKACL_O(\t/* TSP message imprint */\n\t\t/* The object can be updated in both states for persistent\n\t\t   connections */\n\t\tCRYPT_SESSINFO_TSP_MSGIMPRINT,\n\t\tST_NONE, ST_NONE, ST_SESS_TSP, \n\t\tMKPERM_TSP( xWD_xWD ),\n\t\tROUTE( OBJECT_TYPE_SESSION ), &objectCtxHash ),\n\n\tMKACL_END(), MKACL_END()\n\t};\n#endif /* USE_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tUser ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* User attributes */\n\nstatic const ATTRIBUTE_ACL userACL[] = {\n\tMKACL_S_EX(\t/* Password */\n\t\tCRYPT_USERINFO_PASSWORD,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_PKCS15( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_USER ),\n\t\tRANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\n\tMKACL_O(\t/* CA cert signing key */\n\t\tCRYPT_USERINFO_CAKEY_CERTSIGN,\n\t\tST_NONE, ST_NONE, ST_USER_CA, \n\t\tMKPERM_PKCS15( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectCertificate ),\n\tMKACL_O(\t/* CA CRL signing key */\n\t\tCRYPT_USERINFO_CAKEY_CRLSIGN,\n\t\tST_NONE, ST_NONE, ST_USER_CA, \n\t\tMKPERM_PKCS15( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectCertificate ),\n\tMKACL_O(\t/* CA RTCS signing key */\n\t\tCRYPT_USERINFO_CAKEY_RTCSSIGN,\n\t\tST_NONE, ST_NONE, ST_USER_CA, \n\t\tMKPERM_PKCS15( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectCertificate ),\n\tMKACL_O(\t/* CA OCSP signing key */\n\t\tCRYPT_USERINFO_CAKEY_OCSPSIGN,\n\t\tST_NONE, ST_NONE, ST_USER_CA, \n\t\tMKPERM_PKCS15( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectCertificate ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tInternal ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const int allowedObjectStatusValues[] = {\n\tCRYPT_OK, CRYPT_ERROR_TIMEOUT, CRYPT_ERROR, CRYPT_ERROR };\n\nstatic const ATTRIBUTE_ACL subACL_IAttributeSubject[] = {\n\tMKACL_S(\t/* CRMF objects: Readable in any state (unsigned in CMP msgs) */\n\t\tCRYPT_IATTRIBUTE_SUBJECT,\n\t\tST_CERT_REQ_CERT | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\tMKACL_S(\t/* Other objects: Object must be in high state */\n\t\tCRYPT_IATTRIBUTE_SUBJECT,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CERTREQ | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\tMKACL_END_SUBACL(), MKACL_END_SUBACL()\n\t};\n\n/* Internal attributes */\n\nstatic const ATTRIBUTE_ACL internalACL[] = {\n\tMKACL_N_EX(\t/* Object type */\n\t\tCRYPT_IATTRIBUTE_TYPE,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM_INT( Rxx_Rxx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( OBJECT_TYPE_NONE + 1, OBJECT_TYPE_LAST - 1 ) ),\n\tMKACL_N_EX(\t/* Object subtype */\n\t\tCRYPT_IATTRIBUTE_SUBTYPE,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM_INT( Rxx_Rxx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( OBJECT_TYPE_NONE + 1, OBJECT_TYPE_LAST - 1 ) ),\n\tMKACL_EX(\t/* Object status */\n\t\t/* Write = status value, read = OBJECT_FLAG_xxx (since an object may\n\t\t   be, for example, busy and signalled at the same time) */\n\t\tCRYPT_IATTRIBUTE_STATUS, ATTRIBUTE_VALUE_NUMERIC,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM_INT( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE_ALLOWEDVALUES, allowedObjectStatusValues ),\n\tMKACL(\t\t/* Object internal flag */\n\t\tCRYPT_IATTRIBUTE_INTERNAL, ATTRIBUTE_VALUE_BOOLEAN,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM_INT( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE, RANGE( FALSE, FALSE )  ),\n\tMKACL_N_EX(\t/* Object action permissions */\n\t\tCRYPT_IATTRIBUTE_ACTIONPERMS,\n\t\tST_CTX_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( ACTION_PERM_NOTAVAIL, ACTION_PERM_LAST ) ),\n\tMKACL_B_EX(\t/* Object locked for exclusive use */\n\t\tCRYPT_IATTRIBUTE_LOCKED,\n\t\tST_CTX_PKC | ST_CTX_CONV | ST_CERT_ANY_CERT | ST_CERT_CRL , ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xWx_xWx ), ATTRIBUTE_FLAG_PROPERTY,\n\t\tROUTE_NONE ),\n\tMKACL_N_EX(\t/* Object inited (e.g. key loaded, cert signed) */\n\t\tCRYPT_IATTRIBUTE_INITIALISED,\n\t\tST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t\tMKPERM_INT( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE_NONE, RANGE( CRYPT_UNUSED, CRYPT_UNUSED ) ),\n\n\t/* Context internal attributes */\n\tMKACL_N(\t/* Ctx: Key size (for non-native ctxts) */\n\t\tCRYPT_IATTRIBUTE_KEYSIZE,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) ),\n\tMKACL_N(\t/* Ctx: Key feature info */\n\t\tCRYPT_IATTRIBUTE_KEYFEATURES,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 0, 16 ) ),\n\tMKACL_S(\t/* Ctx: Key ID */\n\t\tCRYPT_IATTRIBUTE_KEYID,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 20, 20 ) ),\n\tMKACL_S(\t/* Ctx: PGP 2 key ID */\n\t\tCRYPT_IATTRIBUTE_KEYID_PGP2,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8, 8 ) ),\n\tMKACL_S(\t/* Ctx: OpenPGP key ID */\n\t\t/* This attribute is writeable in the high state since it may be\n\t\t   retroactively set for objects for which the value couldn't be\n\t\t   calculated at object instantiation time, for example a\n\t\t   certificate that has the OpenPGP information stored alongside\n\t\t   it */\n\t\tCRYPT_IATTRIBUTE_KEYID_OPENPGP,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8, 8 ) ),\n#if !( defined( USE_ECDH ) || defined( USE_ECDSA ) )\n\tMKACL_S_EX(\t/* Ctx: SubjectPublicKeyInfo */\n\t\t/* The attribute length values are only approximate because there's\n\t\t   wrapper data involved, and (for the maximum length) several of\n\t\t   the DLP PKC values are only a fraction of CRYPT_MAX_PKCSIZE, the\n\t\t   rest of the space requirement being allocated to the wrapper */\n\t\tCRYPT_IATTRIBUTE_KEY_SPKI,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8 + MIN_PKCSIZE, CRYPT_MAX_PKCSIZE * 4 ) ),\n\tMKACL_S_EX(\t/* Ctx: PGP-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_PGP,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_PGP( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 10 + MIN_PKCSIZE, CRYPT_MAX_PKCSIZE * 4 ) ),\n\tMKACL_S_EX(\t/* Ctx: SSH-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSH,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSH( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 16 + MIN_PKCSIZE, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S_EX(\t/* Ctx: SSL-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSL,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSL( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 4 + MIN_PKCSIZE, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S_EX(\t/* Ctx: TLS-extended-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSL_EXT,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSL( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 4 + MIN_PKCSIZE, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S(\t/* Ctx: SubjectPublicKeyInfo w/o trigger */\n\t\t/* We allow a read as well as write to handle dummy contexts tied to \n\t\t   hardware that are used as placeholders for crypto hardware \n\t\t   functionality, these aren't necessarily in the high state as\n\t\t   required by CRYPT_IATTRIBUTE_KEY_SPKI when they're accessed \n\t\t   because the hardware may not be ready yet, but we can still\n\t\t   fetch the stored public-key data from them */\n\t\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8 + MIN_PKCSIZE, CRYPT_MAX_PKCSIZE * 4 ) ),\n#else\n\tMKACL_S_EX(\t/* Ctx: SubjectPublicKeyInfo */\n\t\t/* ECC keys are somewhat different, the lower bound is much smaller \n\t\t   but the key data consists of a point on a curve so it's calcuated\n\t\t   as twice the minimum key size */\n\t\tCRYPT_IATTRIBUTE_KEY_SPKI,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8 + MIN_PKCSIZE_ECCPOINT_THRESHOLD, CRYPT_MAX_PKCSIZE * 4 ) ),\n\tMKACL_S_EX(\t/* Ctx: PGP-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_PGP,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_PGP( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 10 + MIN_PKCSIZE_ECCPOINT_THRESHOLD, CRYPT_MAX_PKCSIZE * 4 ) ),\n\tMKACL_S_EX(\t/* Ctx: SSH-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSH,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSH( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 16 + MIN_PKCSIZE_ECC, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S_EX(\t/* Ctx: SSL-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSL,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSL( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1 + 2, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S_EX(\t/* Ctx: TLS-extended-format public key */\n\t\tCRYPT_IATTRIBUTE_KEY_SSL_EXT,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_SSL( Rxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 4 + MIN_PKCSIZE, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ),\n\tMKACL_S(\t/* Ctx: SubjectPublicKeyInfo w/o trigger */\n\t\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 8 + MIN_PKCSIZE_ECCPOINT_THRESHOLD, CRYPT_MAX_PKCSIZE * 4 ) ),\n#endif /* !( USE_ECDH || USE_ECDSA ) */\n\tMKACL_S(\t/* Ctx: PGP public key w/o trigger */\n\t\tCRYPT_IATTRIBUTE_KEY_PGP_PARTIAL,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_PGP( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 10 + MIN_PKCSIZE, CRYPT_MAX_PKCSIZE * 3 ) ),\n#if !defined( USE_DH )\n\tMKACL_N_EX(\t/* DLP domain parameters */\n\t\tCRYPT_IATTRIBUTE_KEY_DLPPARAM,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE,\n\t\tMKPERM_INT( xxx_xxx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( MIN_PKCSIZE, CRYPT_MAX_PKCSIZE ) ),\n#else\n\tMKACL_N_EX(\t/* DLP domain parameters */\n\t\tCRYPT_IATTRIBUTE_KEY_DLPPARAM,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE,\n\t\tMKPERM_INT( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( MIN_PKCSIZE, CRYPT_MAX_PKCSIZE ) ),\n#endif /* !USE_DH */\n#if !( defined( USE_ECDH ) || defined( USE_ECDSA ) )\n\tMKACL_N_EX(\t/* ECC domain parameters */\n\t\tCRYPT_IATTRIBUTE_KEY_ECCPARAM,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE,\n\t\tMKPERM_INT( xxx_xxx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( CRYPT_ECCCURVE_NONE + 1, CRYPT_ECCCURVE_LAST - 1 ) ),\n#else\n\tMKACL_N_EX(\t/* ECC domain parameters */\n\t\tCRYPT_IATTRIBUTE_KEY_ECCPARAM,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE,\n\t\tMKPERM_INT( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( CRYPT_ECCCURVE_NONE + 1, CRYPT_ECCCURVE_LAST - 1 ) ),\n#endif /* !( USE_ECDH || USE_ECDSA ) */\n\tMKACL_T(\t/* Ctx: PGP key validity */\n\t\t/* This attribute is writeable in the high state since it may be\n\t\t   retroactively set for objects for which the value couldn't be\n\t\t   calculated at object instantiation time, for example a\n\t\t   certificate that has the OpenPGP information stored alongside\n\t\t   it */\n\t\tCRYPT_IATTRIBUTE_PGPVALIDITY,\n\t\tST_CTX_PKC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ) ),\n\tMKACL_N(\t/* Ctx: Device object handle */\n\t\tCRYPT_IATTRIBUTE_DEVICEOBJECT,\n\t\tST_CTX_ANY, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE_ANY ),\n\tMKACL_S(\t/* Ctx: Storage ID for data in device */\n\t\tCRYPT_IATTRIBUTE_DEVICESTORAGEID,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_RWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1, KEYID_SIZE ) ),\n\tMKACL_S(\t/* Ctx: Existing label for object in device */\n\t\t/* This is like CRYPT_CTXINFO_LABEL except that what we're setting \n\t\t   is the label for an existing persistent object in a device, so\n\t\t   the context code doesn't reject it if it finds a match for this\n\t\t   label in the device */\n\t\tCRYPT_IATTRIBUTE_EXISTINGLABEL,\n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_N(\t/* Ctx: Optional params for CRYPT_CTXINFO_KEYING_ALGO */\n\t\tCRYPT_IATTRIBUTE_KEYING_ALGO_PARAM,\n\t\tST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xxx_xWx ), \n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 20, CRYPT_MAX_HASHSIZE ) ),\n\tMKACL_S(\t/* Ctx: Opt.KDF params for generic-secret */\n\t\tCRYPT_IATTRIBUTE_KDFPARAMS,\n\t\tST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Ctx: Encryption params for generic-secret */\n\t\tCRYPT_IATTRIBUTE_ENCPARAMS,\n\t\tST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Ctx: MAC params for generic-secret */\n\t\tCRYPT_IATTRIBUTE_MACPARAMS,\n\t\tST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( RWx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* AAD for authenticated-encr.modes */\n\t\tCRYPT_IATTRIBUTE_AAD,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( xWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 1, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* ICV for authenticated-encr.modes */\n\t\tCRYPT_IATTRIBUTE_ICV,\n\t\tST_CTX_CONV, ST_NONE, ST_NONE, \n\t\tMKPERM_INT( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CONTEXT ),\n\t\tRANGE( 12, CRYPT_MAX_HASHSIZE ) ),\n\n\t/* Certificate internal attributes */\n\tMKACL_X(\t/* Cert: SubjectName */\n\t\t/* Although in theory this attribute should only be present for\n\t\t   signed cert objects, it also exists in CRMF objects that are\n\t\t   being used as CMP revocation requests and that aren't signed and\n\t\t   are therefore never in the high state.  Because of this we have to\n\t\t   allow reads in the low state for this one object type */\n\t\tCRYPT_IATTRIBUTE_SUBJECT,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_REQ_CERT | ST_CERT_REQ_REV | \\\n\t\t\t\t\t   ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), subACL_IAttributeSubject ),\n\tMKACL_S(\t/* Cert: IssuerName */\n\t\tCRYPT_IATTRIBUTE_ISSUER,\n\t\tST_CERT_CERT | ST_CERT_REQ_CERT | ST_CERT_CERTCHAIN | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\tMKACL_S(\t/* Cert: IssuerAndSerial */\n\t\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_REQ_REV | ST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\tMKACL_S(\t/* Cert: Best approximation to cert.owner name */\n\t\tCRYPT_IATTRIBUTE_HOLDERNAME,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_REQ_CERT | ST_CERT_REQ_REV | \\\n\t\t\t\t\t   ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 1, CRYPT_MAX_TEXTSIZE ) ),\n\tMKACL_S(\t/* Cert: Best approximation to cert.owner URI */\n\t\tCRYPT_IATTRIBUTE_HOLDERURI,\n\t\tST_CERT_CERT | ST_CERT_CERTREQ | ST_CERT_REQ_CERT | ST_CERT_REQ_REV | \\\n\t\t\t\t\t   ST_CERT_CERTCHAIN | ST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_S(\t/* Cert: Encoded SubjectPublicKeyInfo */\n\t\t/* Although we never need to extract the SPKI from a CRMF request, we\n\t\t   have to be able to read it so we can do a presence check since we\n\t\t   can't issue a cert without having a public key present (although\n\t\t   this would be detcted later on, it allows us to report the error\n\t\t   at an earlier stage by explicitly checking).  Since the same\n\t\t   checks are also applied to PKCS #10 cert requests, we also have to\n\t\t   make it readable for those */\n\t\tCRYPT_IATTRIBUTE_SPKI,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN | ST_CERT_CERTREQ | ST_CERT_REQ_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, CRYPT_MAX_PKCSIZE * 3 ) ),\n\tMKACL_N(\t/* Cert: PKC algo.used for certificate */\n\t\tCRYPT_IATTRIBUTE_CERTKEYALGO,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( CRYPT_ALGO_FIRST_PKC, CRYPT_ALGO_LAST_PKC ) ),\n\tMKACL_N(\t/* Cert: Hash algo.used for certificate */\n\t\t/* Although this attribute is technically valid for most cert types,\n\t\t   it's only used with standard certificates, where it's used as\n\t\t   an implicit indicator of the preferred hash algorithm to use when\n\t\t   signing data */\n\t\tCRYPT_IATTRIBUTE_CERTHASHALGO,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( CRYPT_ALGO_FIRST_HASH, CRYPT_ALGO_LAST_HASH ) ),\n\tMKACL_O_EX(\t/* Cert: Certs added to cert chain */\n\t\t/* This attribute is marked as a trigger attribute since the cert\n\t\t   chain object it affects doesn't contain a true chain of certs but\n\t\t   only a collection of non-duplicate certs that are never\n\t\t   explicitly signed.  To allow it to function as a normal cert\n\t\t   chain, we move it into the high state as soon as at least on cert\n\t\t   is added.  In addition, this is a retriggerable attribute in that\n\t\t   further data can be added after the initial trigger action */\n\t\tCRYPT_IATTRIBUTE_CERTCOLLECTION,\n\t\tST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( xWx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificate ),\n\tMKACL_S(\t/* Cert: Individual entry from CRL */\n\t\tCRYPT_IATTRIBUTE_CRLENTRY,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREV( Rxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 8, MAX_ATTRIBUTE_SIZE ) ),\n\tMKACL_S(\t/* Cert: RTCS/OCSP responder name */\n\t\tCRYPT_IATTRIBUTE_RESPONDERURL,\n\t\tST_CERT_RTCS_REQ | ST_CERT_OCSP_REQ, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREV_VAL( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( MIN_URL_SIZE, MAX_URL_SIZE ) ),\n\tMKACL_O(\t/* Cert: RTCS req.info added to RTCS resp.*/\n\t\tCRYPT_IATTRIBUTE_RTCSREQUEST,\n\t\tST_CERT_RTCS_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTVAL( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertRTCSRequest ),\n\tMKACL_O(\t/* Cert: OCSP req.info added to OCSP resp.*/\n\t\tCRYPT_IATTRIBUTE_OCSPREQUEST,\n\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREV( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertOCSPRequest ),\n\tMKACL_O_EX(\t/* Cert: CRMF rev.request added to CRL */\n\t\t/* This is marked as a trigger attribute since it's used to create a\n\t\t   CRL template from a CRMF request (i.e. to turn a CRMF revocation\n\t\t   request into something that the rest of cryptlib can work with),\n\t\t   so adding it has to create a pseudosigned CRL from which we can\n\t\t   read things like the encoded CRL entry and the\n\t\t   issuerAndSerialNumber */\n\t\tCRYPT_IATTRIBUTE_REVREQUEST,\n\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREV( xxx_xWx ), ATTRIBUTE_FLAG_TRIGGER,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertRevRequest ),\n\tMKACL_O(\t/* Cert: Additional user info added to cert.request */\n\t\tCRYPT_IATTRIBUTE_PKIUSERINFO,\n\t\tST_CERT_CERTREQ | ST_CERT_REQ_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREQ( xWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertPKIUser ),\n\tMKACL_O(\t/* Cert: Template of disallowed attrs.in cert */\n\t\tCRYPT_IATTRIBUTE_BLOCKEDATTRS,\n\t\tST_CERT_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( xxx_xWx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificateTemplate ),\n\tMKACL_B(\t/* Cert request came from RA */\n\t\tCRYPT_IATTRIBUTE_REQFROMRA,\n\t\tST_CERT_REQ_CERT, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREQ( RWx_xxx ), \n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ) ),\n\tMKACL_S(\t/* Cert: Authorising cert ID for a cert/rev.request */\n\t\tCRYPT_IATTRIBUTE_AUTHCERTID,\n\t\tST_CERT_REQ_CERT | ST_CERT_REQ_REV, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTREQ( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 20, 20 ) ),\n\tMKACL_S(\t/* Cert: ESSCertID */\n\t\tCRYPT_IATTRIBUTE_ESSCERTID,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_Rxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 32, 8192 ) ),\n\tMKACL_O(\t/* Cert: Copy of cert object */\n\t\t/* This is used to create a sanitised copy of a (possibly-internal)\n\t\t   cert.for external use */\n\t\tCRYPT_IATTRIBUTE_CERTCOPY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificate ),\n\tMKACL_O(\t/* Cert: Copy of cert object as data-only cert */\n\t\tCRYPT_IATTRIBUTE_CERTCOPY_DATAONLY,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\tMKPERM_INT_CERTIFICATES( Rxx_xxx ),\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), &objectCertificate ),\n\n\t/* Device internal attributes */\n\tMKACL_S(\t/* Dev: Polled entropy data */\n\t\tCRYPT_IATTRIBUTE_ENTROPY,\n\t\tST_NONE, ST_DEV_SYSTEM, ST_NONE, \n\t\tMKPERM_INT( xWx_xWx ), \n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( 1, MAX_BUFFER_SIZE - 1 ) ),\n\tMKACL_N(\t/* Dev: Quality of entropy */\n\t\tCRYPT_IATTRIBUTE_ENTROPY_QUALITY,\n\t\tST_NONE, ST_DEV_SYSTEM, ST_NONE, \n\t\tMKPERM_INT( xWx_xWx ), \n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( 1, 100 ) ),\n\tMKACL_B(\t/* Slow/fast entropy poll */\n\t\tCRYPT_IATTRIBUTE_RANDOM_POLL,\n\t\tST_NONE, ST_DEV_SYSTEM, ST_NONE, \n\t\tMKPERM_INT( xWx_xWx ), \n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ) ),\n\tMKACL_N(\t/* Dev: Low picket for random data attrs.*/\n\t\t/* This and the high picket are used to protect the critical\n\t\t   randomness attributes from accidental access due to fencepost\n\t\t   errors or similar problems. They're marked as non-accessible numeric\n\t\t   attributes (randomness is a string attribute) to ensure they'll both\n\t\t   be trapped as an error in the debug kernel and rejected in normal\n\t\t   use */\n\t\tCRYPT_IATTRIBUTE_RANDOM_LOPICKET,\n\t\tST_NONE, ST_DEV_ANY, ST_NONE, \n\t\tMKPERM_INT( xxx_xxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( 0, 0 ) ),\n\tMKACL_S(\t/* Dev: Random data */\n\t\tCRYPT_IATTRIBUTE_RANDOM,\n\t\tST_NONE, ST_DEV_ANY, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),  \n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) ),\n\tMKACL_S(\t/* Dev: Nonzero random data */\n\t\tCRYPT_IATTRIBUTE_RANDOM_NZ,\n\t\tST_NONE, ST_DEV_ANY, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( MIN_KEYSIZE, CRYPT_MAX_PKCSIZE ) ),\n\tMKACL_N(\t/* Dev: High picket for random data attrs.*/\n\t\tCRYPT_IATTRIBUTE_RANDOM_HIPICKET,\n\t\tST_NONE, ST_DEV_ANY, ST_NONE, \n\t\tMKPERM_INT( xxx_xxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( 0, 0 ) ),\n\tMKACL_S(\t/* Dev: Basic nonce */\n\t\tCRYPT_IATTRIBUTE_RANDOM_NONCE,\n\t\tST_NONE, ST_DEV_SYSTEM, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ), RANGE( 1, MAX_INTLENGTH_SHORT ) ),\n\tMKACL_T(\t/* Dev: Reliable (hardware-based) time value */\n\t\tCRYPT_IATTRIBUTE_TIME,\n\t\tST_NONE, ST_DEV_ANY, ST_NONE, \n\t\tMKPERM_INT( Rxx_xxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_DEVICE ) ),\n\n\t/* Envelope internal attributes */\n\tMKACL_B(\t/* Env: Whether to include signing cert(s) */\n\t\tCRYPT_IATTRIBUTE_INCLUDESIGCERT,\n\t\tST_NONE, ST_ENV_ENV, ST_NONE, \n\t\tMKPERM_INT_ENVELOPE( xxx_xWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_ENVELOPE ) ),\n\tMKACL_B(\t/* Env: Signed data contains only CMS attrs.*/\n\t\tCRYPT_IATTRIBUTE_ATTRONLY,\n\t\tST_NONE, ST_ENV_ENV | ST_ENV_DEENV, ST_NONE, \n\t\tMKPERM_INT_ENVELOPE( xWx_xWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_ENVELOPE ) ),\n\n\t/* Keyset internal attributes */\n\tMKACL_S(\t/* Keyset: Config information */\n\t\tCRYPT_IATTRIBUTE_CONFIGDATA,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( 8, 16384 ) ),\n\tMKACL_S(\t/* Keyset: Index of users */\n\t\tCRYPT_IATTRIBUTE_USERINDEX,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( 16, 16384 ) ),\n\tMKACL_S(\t/* Keyset: User ID */\n\t\tCRYPT_IATTRIBUTE_USERID,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( KEYID_SIZE, KEYID_SIZE ) ),\n\tMKACL_S(\t/* Keyset: User information */\n\t\tCRYPT_IATTRIBUTE_USERINFO,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( RWx_RWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( 64, 16384 ) ),\n\tMKACL_S(\t/* Keyset: First trusted cert */\n\t\tCRYPT_IATTRIBUTE_TRUSTEDCERT,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( 64, 2048 ) ),\n\tMKACL_S(\t/* Keyset: Successive trusted certs */\n\t\tCRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( Rxx_Rxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), RANGE( 64, 2048 ) ),\n\tMKACL_O(\t/* Keyset: Associated device for private key data */\n\t\tCRYPT_IATTRIBUTE_HWSTORAGE,\n\t\tST_NONE, ST_KEYSET_FILE, ST_NONE, \n\t\tMKPERM_INT( xWx_xWx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_KEYSET ), &objectHardwareDevice ),\n\n\t/* Session internal attributes */\n\tMKACL_S(\t/* Session: Encoded TSA timestamp */\n\t\tCRYPT_IATTRIBUTE_ENC_TIMESTAMP,\n\t\tST_NONE, ST_NONE, ST_SESS_TSP, \n\t\tMKPERM_INT_TSP( Rxx_xxx ),\n\t\tROUTE_FIXED( OBJECT_TYPE_SESSION ), RANGE( 128, 8192 ) ),\n\n\t/* User internal attributes */\n\tMKACL_O(\t/* User: Keyset to send trusted certs to */\n\t\tCRYPT_IATTRUBUTE_CERTKEYSET,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_INT( xWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectKeysetConfigdata ),\n\tMKACL_O(\t/* User: Cert.trust list */\n\t\tCRYPT_IATTRIBUTE_CTL,\n\t\tST_NONE, ST_NONE, ST_USER_ANY, \n\t\tMKPERM_INT_CERTIFICATES( RWx_xxx ),\n\t\tROUTE( OBJECT_TYPE_USER ), &objectCertificate ),\n\tMKACL_END(), MKACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Check that a special range entry is consistent */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN specialRangeConsistent( const ATTRIBUTE_ACL *attributeACL )\n\t{\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\n\tswitch( getSpecialRangeType( attributeACL ) )\n\t\t{\n\t\tcase RANGEVAL_ANY:\n\t\t\tif( getSpecialRangeInfo( attributeACL ) != NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase RANGEVAL_ALLOWEDVALUES:\n\t\t\t{\n\t\t\tconst int *rangeVal = getSpecialRangeInfo( attributeACL );\n\t\t\tint i;\n\n\t\t\tif( rangeVal == NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tLOOP_SMALL( i = 0, i < 10, i++ )\n\t\t\t\t{\n\t\t\t\tif( *rangeVal++ == CRYPT_ERROR )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES_B( LOOP_BOUND_OK );\n\t\t\tif( i >= 10 )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase RANGEVAL_SUBRANGES:\n\t\t\t{\n\t\t\tconst RANGE_SUBRANGE_TYPE *rangeVal = \\\n\t\t\t\t\t\t\t\t\tgetSpecialRangeInfo( attributeACL );\n\t\t\tint i;\n\n\t\t\tif( rangeVal == NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tLOOP_SMALL( i = 0, i < 10, i++ )\n\t\t\t\t{\n\t\t\t\tif( rangeVal->highRange == CRYPT_ERROR )\n\t\t\t\t\tbreak;\n\t\t\t\tif( rangeVal->lowRange < 0 )\n\t\t\t\t\t{\n\t\t\t\t\tif( !( rangeVal->lowRange < 0 && \\\n\t\t\t\t\t\t   rangeVal->highRange < 0 ) || \\\n\t\t\t\t\t\trangeVal->lowRange < rangeVal->highRange )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( !( rangeVal->lowRange >= 0 && \\\n\t\t\t\t\t\t   rangeVal->highRange >= 0 ) || \\\n\t\t\t\t\t\trangeVal->lowRange > rangeVal->highRange )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\trangeVal++;\n\t\t\t\t}\n\t\t\tENSURES_B( LOOP_BOUND_OK );\n\t\t\tif( i >= 10 )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that an ACL is consistent */\n\n#define ACCESS_RWx_xxx\t\t0x6060\t/* Special-case used for consistency check */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN aclConsistent( const ATTRIBUTE_ACL *attributeACL,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t  const OBJECT_SUBTYPE subTypeA, \n\t\t\t\t\t\t\t  const OBJECT_SUBTYPE subTypeB,\n\t\t\t\t\t\t\t  const OBJECT_SUBTYPE subTypeC )\n\t{\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\t\n#ifndef NDEBUG\n\tREQUIRES_B( attribute > CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\tattribute < CRYPT_IATTRIBUTE_LAST );\n#endif /* !NDEBUG */\n\tREQUIRES_B( !( subTypeA & ( SUBTYPE_CLASS_B | SUBTYPE_CLASS_C ) ) );\n\tREQUIRES_B( !( subTypeB & ( SUBTYPE_CLASS_A | SUBTYPE_CLASS_C ) ) );\n\tREQUIRES_B( !( subTypeC & ( SUBTYPE_CLASS_A | SUBTYPE_CLASS_B ) ) );\n\n\t/* General consistency checks.  We can only check the attribute type in\n\t   the debug build because it's not present in the release to save\n\t   space */\n#ifndef NDEBUG\n\tif( attributeACL->attribute != attribute )\n\t\treturn( FALSE );\n#endif /* !NDEBUG */\n\tif( attributeACL->flags >= ATTRIBUTE_FLAG_LAST )\n\t\treturn( FALSE );\n\tif( ( attributeACL->subTypeA & ( SUBTYPE_CLASS_B | SUBTYPE_CLASS_C ) ) || \\\n\t\t( attributeACL->subTypeB & ( SUBTYPE_CLASS_A | SUBTYPE_CLASS_C ) ) || \\\n\t\t( attributeACL->subTypeC & ( SUBTYPE_CLASS_A | SUBTYPE_CLASS_B ) ) )\n\t\treturn( FALSE );\n\tif( ( attributeACL->subTypeA & ~( SUBTYPE_CLASS_A | subTypeA ) ) != 0 || \\\n\t\t( attributeACL->subTypeB & ~( SUBTYPE_CLASS_B | subTypeB ) ) != 0 || \\\n\t\t( attributeACL->subTypeC & ~( SUBTYPE_CLASS_C | subTypeC ) ) != 0 )\n\t\treturn( FALSE );\n\n\t/* ACL-specific checks */\n\tswitch( attributeACL->valueType )\n\t\t{\n\t\tcase ATTRIBUTE_VALUE_BOOLEAN:\n\t\t\t/* Some boolean values can only be set to TRUE or FALSE, so it's\n\t\t\t   possible to have a range of { FALSE, FALSE } or\n\t\t\t   { TRUE, TRUE } */\n\t\t\tif( ( attributeACL->lowRange != FALSE && \\\n\t\t\t\t  attributeACL->lowRange != TRUE ) || \\\n\t\t\t\t( attributeACL->highRange != FALSE && \\\n\t\t\t\t  attributeACL->highRange != TRUE ) || \\\n\t\t\t\tattributeACL->extendedInfo != NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_NUMERIC:\n\t\t\tif( isSpecialRange( attributeACL ) )\n\t\t\t\t{\n\t\t\t\tif( !specialRangeConsistent( attributeACL ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( attributeACL->lowRange < 0 )\n\t\t\t\t\t{\n\t\t\t\t\tif( !( attributeACL->lowRange < 0 && \\\n\t\t\t\t\t\t   attributeACL->highRange < 0 ) || \\\n\t\t\t\t\t\tattributeACL->lowRange < attributeACL->highRange )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( !( attributeACL->lowRange >= 0 && \\\n\t\t\t\t\t\t   attributeACL->highRange >= 0 ) || \\\n\t\t\t\t\t\tattributeACL->lowRange > attributeACL->highRange )\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tif( attributeACL->extendedInfo != NULL )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_STRING:\n\t\t\tif( isSpecialRange( attributeACL ) )\n\t\t\t\t{\n\t\t\t\tif( getSpecialRangeType( attributeACL ) != RANGEVAL_ALLOWEDVALUES || \\\n\t\t\t\t\tgetSpecialRangeInfo( attributeACL ) == NULL )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\tif( !specialRangeConsistent( attributeACL ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* The special-case check for MAX_BUFFER_SIZE is needed for\n\t\t\t\t   polled entropy data, which can be of arbitrary length */\n\t\t\t\tif( attributeACL->extendedInfo != NULL )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\tif( attributeACL->lowRange < 0 || \\\n\t\t\t\t\t( attributeACL->highRange > 16384 && \\\n\t\t\t\t\t  attributeACL->highRange != MAX_BUFFER_SIZE - 1 ) || \\\n\t\t\t\t\tattributeACL->lowRange > attributeACL->highRange )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_WCSTRING:\n\t\t\t/* These are text strings and so can never be zero-length.  In \n\t\t\t   theory they can't be length 1 either, but the WCS-ness is\n\t\t\t   optional so they could also be single-byte character \n\t\t\t   strings */\n\t\t\tif( attributeACL->extendedInfo != NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tif( attributeACL->lowRange <= 0 || \\\n\t\t\t\tattributeACL->highRange > 16384 || \\\n\t\t\t\tattributeACL->lowRange > attributeACL->highRange )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_OBJECT:\n\t\t\tif( attributeACL->lowRange != 0 || \\\n\t\t\t\tattributeACL->highRange != 0 || \\\n\t\t\t\tattributeACL->extendedInfo == NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_TIME:\n\t\t\tif( attributeACL->lowRange != 0 || \\\n\t\t\t\tattributeACL->highRange != 0 || \\\n\t\t\t\tattributeACL->extendedInfo != NULL )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_SPECIAL:\n\t\t\t{\n\t\t\tconst ATTRIBUTE_ACL *attributeACLPtr;\n\t\t\tint access = attributeACL->access;\n\t\t\tint subTypes = attributeACL->subTypeA | \\\n\t\t\t\t\t\t   attributeACL->subTypeB | \\\n\t\t\t\t\t\t   attributeACL->subTypeC;\n\n\t\t\tif( !isSpecialRange( attributeACL ) || \\\n\t\t\t\tgetSpecialRangeType( attributeACL ) != RANGEVAL_SUBTYPED || \\\n\t\t\t\tgetSpecialRangeInfo( attributeACL ) == NULL )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Recursively check the sub-ACLs */\n\t\t\tLOOP_MED( attributeACLPtr = getSpecialRangeInfo( attributeACL ), \n\t\t\t\t\t  attributeACLPtr->valueType != ATTRIBUTE_VALUE_NONE,\n\t\t\t\t\t  attributeACLPtr++ )\n\t\t\t\t{\n\t\t\t\tif( !aclConsistent( attributeACLPtr, \n#ifndef NDEBUG\n\t\t\t\t\t\t\t\t\tattributeACL->attribute,\n#else\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE,\n#endif /* !NDEBUG */\n\t\t\t\t\t\t\t\t\tattributeACL->subTypeA,\n\t\t\t\t\t\t\t\t\tattributeACL->subTypeB,\n\t\t\t\t\t\t\t\t\tattributeACL->subTypeC ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tENSURES_B( LOOP_BOUND_OK );\n\n\t\t\t/* Make sure that all subtypes and acess settings in the main\n\t\t\t   attribute are handled in the sub-attributes */\n\t\t\tLOOP_MED( attributeACLPtr = getSpecialRangeInfo( attributeACL ), \n\t\t\t\t\t  attributeACLPtr->valueType != ATTRIBUTE_VALUE_NONE,\n\t\t\t\t\t  attributeACLPtr++ )\n\t\t\t\t{\n\t\t\t\tsubTypes &= ~( attributeACLPtr->subTypeA | \\\n\t\t\t\t\t\t\t   attributeACLPtr->subTypeB | \\\n\t\t\t\t\t\t\t   attributeACLPtr->subTypeC );\n\t\t\t\taccess &= ~attributeACLPtr->access;\n\t\t\t\t}\n\t\t\tENSURES_B( LOOP_BOUND_OK );\n\t\t\tif( subTypes != 0 || access != 0 )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL \\\nint initAttributeACL( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on values used to handle ACL subranges.\n\t   These are somewhat tricky to check automatically since they represent\n\t   variable start and end ranges, we hardcode in absolute values to\n\t   ensure that adding new attributes in the header file will trigger an\n\t   exception here to provide a reminder to change the range-end\n\t   definitions as well */\n\tstatic_assert( CRYPT_CERTINFO_FIRST_CERTINFO == 2001, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_LAST_CERTINFO == 2033, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_PSEUDOINFO == 2001, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_LAST_PSEUDOINFO == 2011, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_NAME == 2100, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_LAST_NAME == 2115, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_DN == 2100, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_LAST_DN == 2105, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_GENERALNAME == 2106, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_LAST_GENERALNAME == 2115, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_EXTENSION == 2200, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTINFO_FIRST_CMS == 2500, \"Attribute value\" );\n\tstatic_assert( CRYPT_SESSINFO_FIRST_SPECIFIC == 6016, \"Attribute value\" );\n\tstatic_assert( CRYPT_SESSINFO_LAST_SPECIFIC == 6031, \"Attribute value\" );\n\tstatic_assert( CRYPT_CERTFORMAT_LAST == 12, \"Attribute value\" );\n\n\t/* Perform a consistency check on the attribute ACLs.  The ACLs are\n\t   complex enough that we assert on each one to quickly catch problems\n\t   when one is changed.  First we check the universal property, generic,\n\t   and option ACLs */\n\tLOOP_LARGE( i = 0, i < CRYPT_PROPERTY_LAST - CRYPT_PROPERTY_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( propertyACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &propertyACL[ i ], i + CRYPT_PROPERTY_FIRST + 1,\n\t\t\t\t\t\t\tST_ANY_A, ST_ANY_B, ST_ANY_C ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Property ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( propertyACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( propertyACL[ CRYPT_PROPERTY_LAST - \\\n\t\t\t\t\t\t  CRYPT_PROPERTY_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\tLOOP_LARGE( i = 0, i < CRYPT_GENERIC_LAST - CRYPT_GENERIC_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( genericACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &genericACL[ i ], i + CRYPT_GENERIC_FIRST + 1,\n\t\t\t\t\t\t\tST_ANY_A, ST_ANY_B, ST_ANY_C ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Generic ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( genericACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( genericACL[ CRYPT_GENERIC_LAST - \\\n\t\t\t\t\t\t CRYPT_GENERIC_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\tLOOP_LARGE( i = 0, i < CRYPT_OPTION_LAST - CRYPT_OPTION_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( optionACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &optionACL[ i ], i + CRYPT_OPTION_FIRST + 1,\n\t\t\t\t\t\t\tST_CTX_CONV | ST_CTX_PKC,\n\t\t\t\t\t\t\tST_ENV_ENV | ST_ENV_ENV_PGP | ST_KEYSET_LDAP,\n\t\t\t\t\t\t\tST_SESS_ANY | ST_USER_ANY ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Option ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef NDEBUG\n\t\tif( optionACL[ i ].attribute >= CRYPT_OPTION_KEYING_ALGO && \\\n\t\t\toptionACL[ i ].attribute <= CRYPT_OPTION_KEYING_ITERATIONS )\n\t\t\t{\n\t\t\tENSURES( optionACL[ i ].subTypeA == ST_CTX_CONV );\n\t\t\tENSURES( optionACL[ i ].subTypeB == ST_NONE );\n\t\t\tENSURES( ( optionACL[ i ].subTypeC & ~( SUBTYPE_CLASS_C | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tST_USER_ANY ) ) == 0 );\n\t\t\t}\n\t\telse\n\t\tif( optionACL[ i ].attribute >= CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS && \\\n\t\t\toptionACL[ i ].attribute <= CRYPT_OPTION_KEYS_LDAP_EMAILNAME )\n\t\t\t{\n\t\t\tENSURES( optionACL[ i ].subTypeA == ST_NONE );\n\t\t\tENSURES( optionACL[ i ].subTypeB == ST_KEYSET_LDAP );\n\t\t\tENSURES( ( optionACL[ i ].subTypeC & ~( SUBTYPE_CLASS_C | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tST_USER_ANY ) ) == 0 );\n\t\t\t}\n\t\telse\n\t\tif( optionACL[ i ].attribute == CRYPT_OPTION_MISC_SIDECHANNELPROTECTION )\n\t\t\t{\n\t\t\tENSURES( optionACL[ i ].subTypeA == ST_CTX_PKC );\n\t\t\tENSURES( optionACL[ i ].subTypeB == ST_NONE );\n\t\t\tENSURES( optionACL[ i ].subTypeC == ST_USER_SO );\n\t\t\t}\n\t\telse\n\t\tif( optionACL[ i ].attribute >= CRYPT_OPTION_ENCR_ALGO && \\\n\t\t\toptionACL[ i ].attribute <= CRYPT_OPTION_ENCR_MAC )\n\t\t\t{\n\t\t\tif( optionACL[ i ].subTypeA != ST_NONE || \\\n\t\t\t\toptionACL[ i ].subTypeB & ~( SUBTYPE_CLASS_B | ST_ENV_ENV | \\\n\t\t\t\t\t\t\t\t\t\t\t ST_ENV_ENV_PGP ) || \n\t\t\t\toptionACL[ i ].subTypeC & ~( SUBTYPE_CLASS_C | ST_USER_ANY ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Encryption property ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\tif( optionACL[ i ].attribute >= CRYPT_OPTION_NET_SOCKS_SERVER && \\\n\t\t\toptionACL[ i ].attribute <= CRYPT_OPTION_NET_WRITETIMEOUT )\n\t\t\t{\n\t\t\tENSURES( optionACL[ i ].subTypeA == ST_NONE && \\\n\t\t\t\t\t optionACL[ i ].subTypeB == ST_NONE );\n\t\t\tENSURES( optionACL[ i ].subTypeC == ( ST_SESS_ANY | ST_USER_ANY ) );\n\t\t\t}\n\t\telse\n\t\tif( optionACL[ i ].subTypeA != ST_NONE || \\\n\t\t\toptionACL[ i ].subTypeB != ST_NONE || \\\n\t\t\toptionACL[ i ].subTypeC & ~( SUBTYPE_CLASS_C | ST_USER_ANY ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Networking property ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#endif /* !NDEBUG */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( optionACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( optionACL[ CRYPT_OPTION_LAST - \\\n\t\t\t\t\t\tCRYPT_OPTION_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\n\t/* Check the context ACLs */\n\tLOOP_LARGE( i = 0, i < CRYPT_CTXINFO_LAST - CRYPT_CTXINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( contextACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &contextACL[ i ], i + CRYPT_CTXINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_CTX_ANY, ST_NONE, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Context ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( contextACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( contextACL[ CRYPT_CTXINFO_LAST - \\\n\t\t\t\t\t\t CRYPT_CTXINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\n\t/* Check the certificate ACLs */\n#ifdef USE_CERTIFICATES\n\tLOOP_LARGE( i = 0, i < CRYPT_CERTINFO_LAST_CERTINFO - CRYPT_CERTINFO_FIRST_CERTINFO && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( certificateACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &certificateACL[ i ],\n\t\t\t\t\t\t\ti + CRYPT_CERTINFO_FIRST_CERTINFO,\n\t\t\t\t\t\t\tST_CERT_ANY, ST_NONE, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certificateACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( certificateACL[ CRYPT_CERTINFO_LAST_CERTINFO - \\\n\t\t\t\t\t\t\t CRYPT_CERTINFO_FIRST_CERTINFO + 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\tLOOP_LARGE( i = 0, i < CRYPT_CERTINFO_LAST_NAME - CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( certNameACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &certNameACL[ i ], i + CRYPT_CERTINFO_FIRST_NAME,\n\t\t\t\t\t\t\tST_CERT_ANY, ST_NONE, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate name ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifdef USE_CERTIFICATES\n  #ifndef NDEBUG\n\t\tENSURES( certNameACL[ i ].attribute == CRYPT_CERTINFO_DIRECTORYNAME || \\\n\t\t\t\t certNameACL[ i ].access == ACCESS_Rxx_RWD );\n  #endif /* !NDEBUG */\n#else\n\t\tENSURES( certNameACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* USE_CERTIFICATES */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certNameACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( certNameACL[ CRYPT_CERTINFO_LAST_NAME - \\\n\t\t\t\t\t\t  CRYPT_CERTINFO_FIRST_NAME + 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\tLOOP_LARGE( i = 0, i < CRYPT_CERTINFO_LAST_EXTENSION - CRYPT_CERTINFO_FIRST_EXTENSION && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( certExtensionACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &certExtensionACL[ i ],\n\t\t\t\t\t\t\ti + CRYPT_CERTINFO_FIRST_EXTENSION,\n\t\t\t\t\t\t\tST_CERT_ANY, ST_NONE, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate extension ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef USE_CERTIFICATES\n\t\tENSURES( certExtensionACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* !USE_CERTIFICATES */\n\t\tif( certExtensionACL[ i ].access == ACCESS_xxx_xxx )\n\t\t\tcontinue;\t/* Disabled attribute */\n\t\tif( ( certExtensionACL[ i ].access & ACCESS_RWD_xxx ) != ACCESS_Rxx_xxx )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate extension ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certExtensionACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( certExtensionACL[ CRYPT_CERTINFO_LAST_EXTENSION - \\\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_FIRST_EXTENSION + 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\tLOOP_LARGE( i = 0, i < CRYPT_CERTINFO_LAST_CMS - CRYPT_CERTINFO_FIRST_CMS && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( certSmimeACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &certSmimeACL[ i ], i + CRYPT_CERTINFO_FIRST_CMS,\n\t\t\t\t\t\t\tST_CERT_CMSATTR | ST_CERT_RTCS_REQ, ST_NONE, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"CMS attribute ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef NDEBUG\n\t\tif( certSmimeACL[ i ].attribute == CRYPT_CERTINFO_CMS_NONCE )\n\t\t\t{\n\t\t\tif( certSmimeACL[ i ].subTypeA & ~( SUBTYPE_CLASS_A | ST_CERT_CMSATTR | \\\n\t\t\t\t\t\t\t\t\t\t\t\tST_CERT_RTCS_REQ ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"CMS attribute ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( certSmimeACL[ i ].subTypeA & ~( SUBTYPE_CLASS_A | ST_CERT_CMSATTR ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"CMS attribute ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\t}\n#endif /* !NDEBUG */\n#ifndef USE_CERTIFICATES\n\t\tENSURES( certSmimeACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* !USE_CERTIFICATES */\n\t\tif( certSmimeACL[ i ].access == ACCESS_xxx_xxx )\n\t\t\tcontinue;\t/* Disabled attribute */\n\t\tif( ( certSmimeACL[ i ].access & ACCESS_RWD_xxx ) != ACCESS_Rxx_xxx )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"CMS attribute ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certSmimeACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( certSmimeACL[ CRYPT_CERTINFO_LAST_CMS - \\\n\t\t\t\t\t\t   CRYPT_CERTINFO_FIRST_CMS + 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n#endif /* USE_CERTIFICATES */\n\n\t/* Check the keyset ACLs */\n#ifdef USE_KEYSETS\n\tLOOP_LARGE( i = 0, i < CRYPT_KEYINFO_LAST - CRYPT_KEYINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( keysetACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &keysetACL[ i ], i + CRYPT_KEYINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_NONE, ST_KEYSET_ANY, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Keyset ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef USE_KEYSETS\n\t\tENSURES( keysetACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* !USE_KEYSETS */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( keysetACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( keysetACL[ CRYPT_KEYINFO_LAST - \\\n\t\t\t\t\t\tCRYPT_KEYINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n#endif /* USE_KEYSETS */\n\n\t/* Check the device ACLs.  We don't perform a USE_DEVICES check to \n\t   parallel the checks done for other object classes because the \n\t   system device is always enabled */\n\tLOOP_LARGE( i = 0, i < CRYPT_DEVINFO_LAST - CRYPT_DEVINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( deviceACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &deviceACL[ i ], i + CRYPT_DEVINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_NONE, ST_DEV_ANY_STD, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Device ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( deviceACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( deviceACL[ CRYPT_DEVINFO_LAST - \\\n\t\t\t\t\t\tCRYPT_DEVINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\n\t/* Check the envelope ACLs */\n#ifdef USE_ENVELOPES\n\tLOOP_LARGE( i = 0, i < CRYPT_ENVINFO_LAST - CRYPT_ENVINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( envelopeACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &envelopeACL[ i ], i + CRYPT_ENVINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_NONE, ST_ENV_ANY, ST_NONE ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Envelope ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef USE_ENVELOPES\n\t\tENSURES( envelopeACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* !USE_ENVELOPES */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( envelopeACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( envelopeACL[ CRYPT_ENVINFO_LAST - \\\n\t\t\t\t\t\t  CRYPT_ENVINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n#endif /* USE_ENVELOPES */\n\n\t/* Check the session ACLs */\n#ifdef USE_SESSIONS\n\tLOOP_LARGE( i = 0, i < CRYPT_SESSINFO_LAST - CRYPT_SESSINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( sessionACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &sessionACL[ i ], i + CRYPT_SESSINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_NONE, ST_NONE, ST_SESS_ANY ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Session ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n#ifndef USE_SESSIONS\n\t\tENSURES( sessionACL[ i ].access == ACCESS_xxx_xxx );\n#endif /* !USE_SESSIONS */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( sessionACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( sessionACL[ CRYPT_SESSINFO_LAST - \\\n\t\t\t\t\t\t CRYPT_SESSINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n#endif /* USE_SESSIONS */\n\n\t/* Check the user ACLs */\n\tLOOP_LARGE( i = 0, i < CRYPT_USERINFO_LAST - CRYPT_USERINFO_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( userACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &userACL[ i ], i + CRYPT_USERINFO_FIRST + 1,\n\t\t\t\t\t\t\tST_NONE, ST_NONE, ST_USER_ANY ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"User ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( userACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( userACL[ CRYPT_USERINFO_LAST - \\\n\t\t\t\t\t  CRYPT_USERINFO_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\n\t/* Check the internal ACLs */\n\tLOOP_LARGE( i = 0, i < CRYPT_IATTRIBUTE_LAST - CRYPT_IATTRIBUTE_FIRST - 1 && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( internalACL, ATTRIBUTE_ACL ), i++ )\n\t\t{\n\t\tif( !aclConsistent( &internalACL[ i ],\n\t\t\t\t\t\t\ti + CRYPT_IATTRIBUTE_FIRST + 1,\n\t\t\t\t\t\t\tST_ANY_A, ST_ANY_B, ST_ANY_C ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Internal ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\tENSURES( ( internalACL[ i ].access & ACCESS_MASK_EXTERNAL ) == 0 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( internalACL, ATTRIBUTE_ACL ) );\n#ifndef NDEBUG\n\tENSURES( internalACL[ CRYPT_IATTRIBUTE_LAST - \\\n\t\t\t\t\t\t  CRYPT_IATTRIBUTE_FIRST - 1 ].attribute == \\\n\t\t\t\t\t\t\t\t\t( CRYPT_ATTRIBUTE_TYPE ) CRYPT_ERROR );\n#endif /* !NDEBUG */\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initAttributeACL( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endAttributeACL( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tACL Lookup Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the ACL for an object attribute */\n\nCHECK_RETVAL_PTR \\\nconst void *findAttributeACL( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t  const BOOLEAN isInternalMessage )\n\t{\n\t/* Precondition: If it's an internal message (i.e. not raw data from the\n\t   user) then the attribute is valid */\n\tREQUIRES_N( !isInternalMessage || \\\n\t\t\t\tisAttribute( attribute ) || isInternalAttribute( attribute ) );\n\tREQUIRES_N( isInternalMessage == TRUE || isInternalMessage == FALSE );\n\n\t/* Perform a hardcoded binary search for the attribute ACL, this minimises\n\t   the number of comparisons necessary to find a match.\n\t   \n\t   All of the checks here are specified as debug-only assertions rather \n\t   than REQUIRES() preconditions since the attribute values that are \n\t   being checked are only present in the debug build to save space.  \n\t   This isn't a major issue since it just catches cases where the static \n\t   list of attributes has expanded but the equally static ACL table \n\t   hasn't, which will be caught by the first run of the self-test */\n\tif( attribute < CRYPT_CTXINFO_LAST )\n\t\t{\n\t\tif( attribute < CRYPT_GENERIC_LAST )\n\t\t\t{\n\t\t\tif( attribute > CRYPT_PROPERTY_FIRST && \\\n\t\t\t\tattribute < CRYPT_PROPERTY_LAST )\n\t\t\t\t{\n\t\t\t\tassert( propertyACL[ attribute - CRYPT_PROPERTY_FIRST - 1 ].attribute == attribute );\n\t\t\t\treturn( &propertyACL[ attribute - CRYPT_PROPERTY_FIRST - 1 ] );\n\t\t\t\t}\n\t\t\tif( attribute > CRYPT_GENERIC_FIRST && \\\n\t\t\t\tattribute < CRYPT_GENERIC_LAST )\n\t\t\t\t{\n\t\t\t\tassert( genericACL[ attribute - CRYPT_GENERIC_FIRST - 1 ].attribute == attribute );\n\t\t\t\treturn( &genericACL[ attribute - CRYPT_GENERIC_FIRST - 1 ] );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t\tattribute < CRYPT_OPTION_LAST )\n\t\t\t\t{\n\t\t\t\tassert( optionACL[ attribute - CRYPT_OPTION_FIRST - 1 ].attribute == attribute );\n\t\t\t\treturn( &optionACL[ attribute - CRYPT_OPTION_FIRST - 1 ] );\n\t\t\t\t}\n\t\t\tif( attribute > CRYPT_CTXINFO_FIRST && \\\n\t\t\t\tattribute < CRYPT_CTXINFO_LAST )\n\t\t\t\t{\n\t\t\t\tassert( contextACL[ attribute - CRYPT_CTXINFO_FIRST - 1 ].attribute == attribute );\n\t\t\t\treturn( &contextACL[ attribute - CRYPT_CTXINFO_FIRST - 1 ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\treturn( NULL );\n\t\t}\n\tif( attribute < CRYPT_KEYINFO_LAST )\n\t\t{\n#ifdef USE_CERTIFICATES\n\t\tif( attribute > CRYPT_CERTINFO_FIRST && \\\n\t\t\tattribute < CRYPT_CERTINFO_LAST )\n\t\t\t{\n\t\t\t/* Certificate attributes are split into subranges so we have to \n\t\t\t   adjust the offsets to get the right ACL.  The subrange \n\t\t\t   specifiers are inclusive ranges rather than bounding values, \n\t\t\t   so we use >= rather than > comparisons */\n\t\t\tif( attribute < CRYPT_CERTINFO_FIRST_EXTENSION )\n\t\t\t\t{\n\t\t\t\tif( attribute >= CRYPT_CERTINFO_FIRST_CERTINFO && \\\n\t\t\t\t\tattribute <= CRYPT_CERTINFO_LAST_CERTINFO )\n\t\t\t\t\t{\n\t\t\t\t\tassert( certificateACL[ attribute - CRYPT_CERTINFO_FIRST_CERTINFO ].attribute == attribute );\n\t\t\t\t\treturn( &certificateACL[ attribute - CRYPT_CERTINFO_FIRST_CERTINFO ] );\n\t\t\t\t\t}\n\t\t\t\tif( attribute >= CRYPT_CERTINFO_FIRST_NAME && \\\n\t\t\t\t\tattribute <= CRYPT_CERTINFO_LAST_NAME )\n\t\t\t\t\t{\n\t\t\t\t\tassert( certNameACL[ attribute - CRYPT_CERTINFO_FIRST_NAME ].attribute == attribute );\n\t\t\t\t\treturn( &certNameACL[ attribute - CRYPT_CERTINFO_FIRST_NAME ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( attribute >= CRYPT_CERTINFO_FIRST_EXTENSION && \\\n\t\t\t\t\tattribute <= CRYPT_CERTINFO_LAST_EXTENSION )\n\t\t\t\t\t{\n\t\t\t\t\tassert( certExtensionACL[ attribute - CRYPT_CERTINFO_FIRST_EXTENSION ].attribute == attribute );\n\t\t\t\t\treturn( &certExtensionACL[ attribute - CRYPT_CERTINFO_FIRST_EXTENSION ] );\n\t\t\t\t\t}\n\t\t\t\tif( attribute >= CRYPT_CERTINFO_FIRST_CMS && \\\n\t\t\t\t\tattribute <= CRYPT_CERTINFO_LAST_CMS )\n\t\t\t\t\t{\n\t\t\t\t\tassert( certSmimeACL[ attribute - CRYPT_CERTINFO_FIRST_CMS ].attribute == attribute );\n\t\t\t\t\treturn( &certSmimeACL[ attribute - CRYPT_CERTINFO_FIRST_CMS ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_CERTIFICATES */\n#ifdef USE_KEYSETS\n\t\tif( attribute > CRYPT_KEYINFO_FIRST && \\\n\t\t\tattribute < CRYPT_KEYINFO_LAST )\n\t\t\t{\n\t\t\tassert( keysetACL[ attribute - CRYPT_KEYINFO_FIRST - 1 ].attribute == attribute );\n\t\t\treturn( &keysetACL[ attribute - CRYPT_KEYINFO_FIRST - 1 ] );\n\t\t\t}\n#endif /* USE_KEYSETS */\n\n\t\treturn( NULL );\n\t\t}\n\tif( attribute < CRYPT_USERINFO_LAST )\n\t\t{\n\t\tif( attribute > CRYPT_DEVINFO_FIRST && \\\n\t\t\tattribute < CRYPT_DEVINFO_LAST )\n\t\t\t{\n\t\t\tassert( deviceACL[ attribute - CRYPT_DEVINFO_FIRST - 1 ].attribute == attribute );\n\t\t\treturn( &deviceACL[ attribute - CRYPT_DEVINFO_FIRST - 1 ] );\n\t\t\t}\n#ifdef USE_ENVELOPES\n\t\tif( attribute > CRYPT_ENVINFO_FIRST && \\\n\t\t\tattribute < CRYPT_ENVINFO_LAST )\n\t\t\t{\n\t\t\tassert( envelopeACL[ attribute - CRYPT_ENVINFO_FIRST - 1 ].attribute == attribute );\n\t\t\treturn( &envelopeACL[ attribute - CRYPT_ENVINFO_FIRST - 1 ] );\n\t\t\t}\n#endif /* USE_ENVELOPES */\n#ifdef USE_SESSIONS\n\t\tif( attribute > CRYPT_SESSINFO_FIRST && \\\n\t\t\tattribute < CRYPT_SESSINFO_LAST )\n\t\t\t{\n\t\t\tassert( sessionACL[ attribute - CRYPT_SESSINFO_FIRST - 1 ].attribute == attribute );\n\t\t\treturn( &sessionACL[ attribute - CRYPT_SESSINFO_FIRST - 1 ] );\n\t\t\t}\n#endif /* USE_SESSIONS */\n\t\tif( attribute > CRYPT_USERINFO_FIRST && \\\n\t\t\tattribute < CRYPT_USERINFO_LAST )\n\t\t\t{\n\t\t\tassert( userACL[ attribute - CRYPT_USERINFO_FIRST - 1 ].attribute == attribute );\n\t\t\treturn( &userACL[ attribute - CRYPT_USERINFO_FIRST - 1 ] );\n\t\t\t}\n\n\t\treturn( NULL );\n\t\t}\n\n\t/* If it's an external message then the internal attributes don't \n\t   exist */\n\tif( !isInternalMessage )\n\t\treturn( NULL );\n\tif( attribute > CRYPT_IATTRIBUTE_FIRST && \\\n\t\tattribute < CRYPT_IATTRIBUTE_LAST )\n\t\t{\n\t\tassert( internalACL[ attribute - CRYPT_IATTRIBUTE_FIRST - 1 ].attribute == attribute );\n\t\treturn( &internalACL[ attribute - CRYPT_IATTRIBUTE_FIRST - 1 ] );\n\t\t}\n\n\tretIntError_Null();\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/certm_acl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCert Management ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* Macro to access the secondary parameter ACL information for a given\n   parameter in a list of parameter ACLs */\n\n#define secParamInfo( parentACL, paramNo )\tparentACL->secParamACL[ paramNo ]\n\n#if defined( USE_CERTIFICATES ) && defined( USE_KEYSETS )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCert Management ACLs\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The ACL tables for each cert management action */\n\nstatic const CERTMGMT_ACL certMgmtACLTbl[] = {\n\t/* Create cert store */\n\t{ CRYPT_CERTACTION_CREATE,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Connect to cert store */\n\t{ CRYPT_CERTACTION_CONNECT,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Disconnect from cert store */\n\t{ CRYPT_CERTACTION_DISCONNECT,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Error information */\n\t{ CRYPT_CERTACTION_ERROR,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Add PKI user */\n\t{ CRYPT_CERTACTION_ADDUSER,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Cert request */\n\t{ CRYPT_CERTACTION_REQUEST_CERT,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Cert renewal request */\n\t{ CRYPT_CERTACTION_REQUEST_RENEWAL,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Cert revocation request */\n\t{ CRYPT_CERTACTION_REQUEST_REVOCATION,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Cert creation */\n\t{ CRYPT_CERTACTION_CERT_CREATION,\n\t  ACTION_PERM_NONE_EXTERNAL,\t\t/* Cert mgmt.use only */\n\t  { MKACP_O( ST_CTX_PKC,\t\t\t/* CA key w/cert (see below) */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CERT_CERTREQ | ST_CERT_REQ_CERT,/* Cert request */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) },\n\t  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN,\t/* CA cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* Confirmation of cert creation */\n\t{ CRYPT_CERTACTION_CERT_CREATION_COMPLETE,\n\t  ACTION_PERM_NONE_EXTERNAL,\t\t/* Cert mgmt.use only */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O( ST_CERT_CERT,\t\t\t/* Completed cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* Cancellation of cert creation */\n\t{ CRYPT_CERTACTION_CERT_CREATION_DROP,\n\t  ACTION_PERM_NONE_EXTERNAL,\t\t/* Cert mgmt.use only */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O( ST_CERT_CERT,\t\t\t/* Completed cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* Cancel of creation w.revocation */\n\t{ CRYPT_CERTACTION_CERT_CREATION_REVERSE,\n\t  ACTION_PERM_NONE_EXTERNAL,\t\t/* Cert mgmt.use only */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O( ST_CERT_CERT,\t\t\t/* Completed cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* Delete reqs after restart */\n\t{ CRYPT_CERTACTION_RESTART_CLEANUP,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Complete revocation after restart */\n\t{ CRYPT_CERTACTION_RESTART_REVOKE_CERT,\n\t  ACTION_PERM_NONE,\t\t\t\t\t/* Cert dbx.use only */\n\t  { MKACP_END() } },\n\n\t/* Cert issue */\n\t{ CRYPT_CERTACTION_ISSUE_CERT,\n\t  ACTION_PERM_ALL,\t\t\t\t\t/* Any access */\n\t  { MKACP_O( ST_CTX_PKC,\t\t\t/* CA key w/cert (see below) */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CERT_CERTREQ | ST_CERT_REQ_CERT,/* Cert request */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) },\n\t  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN,\t/* CA cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* CRL issue */\n\t{ CRYPT_CERTACTION_ISSUE_CRL,\n\t  ACTION_PERM_ALL,\t\t\t\t\t/* Any access */\n\t  { MKACP_O( ST_CTX_PKC,\t\t\t/* CA key w/cert (see below) */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE() },\n\t  { MKACP_O( ST_CERT_CERT | ST_CERT_CERTCHAIN,\t/* CA cert */\n\t\t\t\t ACL_FLAG_HIGH_STATE ) } },\n\n\t/* Cert revocation */\n\t{ CRYPT_CERTACTION_REVOKE_CERT,\n\t  ACTION_PERM_ALL,\t\t\t\t\t/* Any access */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O( ST_CERT_REQ_REV,\t\t/* Rev.request.  Rev.reqs are usually */\n\t\t\t\t ACL_FLAG_ANY_STATE ) } },/* unsigned, but may be in the high\n\t\t\t\t\t\t\t\t\t\t   state if imported from an external\n\t\t\t\t\t\t\t\t\t\t   source */\n\n\t/* Cert expiry */\n\t{ CRYPT_CERTACTION_EXPIRE_CERT,\n\t  ACTION_PERM_ALL,\t\t\t\t\t/* Any access */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* Clean up on restart */\n\t{ CRYPT_CERTACTION_CLEANUP,\n\t  ACTION_PERM_ALL,\t\t\t\t\t/* Any access */\n\t  { MKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* End-of-ACL marker */\n\t{ CRYPT_CERTACTION_NONE,\n\t  ACTION_PERM_NONE,\n\t  { MKACP_END() } },\n\t{ CRYPT_CERTACTION_NONE,\n\t  ACTION_PERM_NONE,\n\t  { MKACP_END() } }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\nCHECK_RETVAL \\\nint initCertMgmtACL( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on the cert management ACLs */\n\tLOOP_LARGE( i = 0, certMgmtACLTbl[ i ].action != CRYPT_CERTACTION_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ), i++ )\n\t\t{\n\t\tconst CERTMGMT_ACL *certMgmtACL = &certMgmtACLTbl[ i ];\n\n\t\t/* Actions and permissions are consistent */\n\t\tENSURES( isEnumRange( certMgmtACL->action, CRYPT_CERTACTION ) );\n\t\tENSURES( certMgmtACL->access == ACTION_PERM_NONE || \\\n\t\t\t\t certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL || \\\n\t\t\t\t certMgmtACL->access == ACTION_PERM_ALL );\n\n\t\t/* If it's a no-access ACL, all mechanisms should be blocked */\n\t\tif( certMgmtACL->access == ACTION_PERM_NONE )\n\t\t\t{\n\t\t\tENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_NONE );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If it's an internal-only ACL, it always needs a request\n\t\t   parameter */\n\t\tif( certMgmtACL->access == ACTION_PERM_NONE_EXTERNAL )\n\t\t\t{\n\t\t\tif( paramInfo( certMgmtACL, 1 ).valueType != PARAM_VALUE_OBJECT || \\\n\t\t\t\t( paramInfo( certMgmtACL, 1 ).subTypeA & \\\n\t\t\t\t\t~( ST_CERT_CERTREQ | ST_CERT_REQ_CERT | \\\n\t\t\t\t\t   ST_CERT_REQ_REV | ST_CERT_CERT ) ) || \\\n\t\t\t\tparamInfo( certMgmtACL, 1 ).subTypeB != ST_NONE || \\\n\t\t\t\tparamInfo( certMgmtACL, 1 ).subTypeC != ST_NONE )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Certificate management ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* If it requires a CA key parameter, it must be a private-key\n\t\t   context with the key loaded and an attached CA certificate */\n\t\tif( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )\n\t\t\t{\n\t\t\tENSURES( paramInfo( certMgmtACL, 0 ).subTypeA == ST_CTX_PKC && \\\n\t\t\t\t\t paramInfo( certMgmtACL, 0 ).subTypeB == ST_NONE && \\\n\t\t\t\t\t paramInfo( certMgmtACL, 0 ).subTypeC == ST_NONE && \\\n\t\t\t\t\t paramInfo( certMgmtACL, 0 ).flags == ACL_FLAG_HIGH_STATE );\n\t\t\tif( ( secParamInfo( certMgmtACL, 0 ).subTypeA & \\\n\t\t\t\t\t~( ST_CERT_CERT | ST_CERT_CERTCHAIN ) ) || \\\n\t\t\t\tsecParamInfo( certMgmtACL, 0 ).subTypeB != ST_NONE || \\\n\t\t\t\tsecParamInfo( certMgmtACL, 0 ).subTypeC != ST_NONE || \\\n\t\t\t\tsecParamInfo( certMgmtACL, 0 ).flags != ACL_FLAG_HIGH_STATE )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Certificate management ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\t\tENSURES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t paramInfo( certMgmtACL, 0 ).lowRange == CRYPT_UNUSED );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initCertMgmtACL( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endCertMgmtACL( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCert Management ACL Check Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions to implement the checks in the cert management ACL tables */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckCertMgmtAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MESSAGE_CERTMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy )\n\t{\n\tconst MESSAGE_CERTMGMT_INFO *mechanismInfo = \\\n\t\t  ( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;\n\tconst CERTMGMT_ACL *certMgmtACL = certMgmtACLTbl;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_CERTMGMT_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( message == MESSAGE_KEY_CERTMGMT || message == IMESSAGE_KEY_CERTMGMT );\n\tREQUIRES( isEnumRange( messageValue, CRYPT_CERTACTION ) );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, certMgmtACL[ i ].action != messageValue && \\\n\t\t\t\t\t certMgmtACL[ i ].action != CRYPT_CERTACTION_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ), \n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( certMgmtACLTbl, CERTMGMT_ACL ) );\n\tENSURES( certMgmtACL[ i ].action != CRYPT_CERTACTION_NONE );\n\tcertMgmtACL = &certMgmtACL[ i ];\n\n\t/* Make sure that the access is valid.  Most cert management actions can\n\t   never be initiated explicitly (they're only used internally by the\n\t   cert management code), a few can be initiated explicitly but only\n\t   internally by some cert management protocols, and an even smaller\n\t   number can be initiated externally */\n\tswitch( certMgmtACL->access )\n\t\t{\n\t\tcase ACTION_PERM_ALL:\n\t\t\t/* Any access is valid */\n\t\t\tbreak;\n\n\t\tcase ACTION_PERM_NONE_EXTERNAL:\n\t\t\t/* Only internal access (e.g. from a cert management protocol)\n\t\t\t   is permitted */\n\t\t\tif( !isInternalMessage( message ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tbreak;\n\n\t\tcase ACTION_PERM_NONE:\n\t\t\t/* No access is permitted, it's a value used only by the cert\n\t\t\t   management code */\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Check the mechanism parameters */\n\tif( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )\n\t\t{\n\t\tif( !fullObjectCheck( mechanismInfo->caKey, message ) || \\\n\t\t\t!isSameOwningObject( objectHandle, mechanismInfo->caKey ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( !checkParamObject( paramInfo( certMgmtACL, 0 ), \\\n\t\t\t\t\t\t\t   mechanismInfo->caKey ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* If there's a secondary parameter present, check it agains the\n\t\t   dependent object.  We perform a basic isValidObject() check\n\t\t   rather than a fullObjectCheck() since the dependent object is\n\t\t   usually internal, and this would fail with an external message */\n\t\tif( secParamInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_OBJECT )\n\t\t\t{\n\t\t\tconst int dependentObject = \\\n\t\t\t\t\t\tobjectTable[ mechanismInfo->caKey ].dependentObject;\n\n\t\t\tif( !isValidObject( dependentObject ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( !checkParamObject( secParamInfo( certMgmtACL, 0 ), \\\n\t\t\t\t\t\t\t\t   dependentObject ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( paramInfo( certMgmtACL, 0 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t  paramInfo( certMgmtACL, 0 ).lowRange == CRYPT_UNUSED );\n\n\t\tif( mechanismInfo->caKey != CRYPT_UNUSED )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tif( paramInfo( certMgmtACL, 1 ).valueType == PARAM_VALUE_OBJECT )\n\t\t{\n\t\tif( !fullObjectCheck( mechanismInfo->request, message ) || \\\n\t\t\t!isSameOwningObject( objectHandle, mechanismInfo->request ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\tif( !checkParamObject( paramInfo( certMgmtACL, 1 ), \\\n\t\t\t\t\t\t\t   mechanismInfo->request ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( paramInfo( certMgmtACL, 1 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t  paramInfo( certMgmtACL, 1 ).lowRange == CRYPT_UNUSED );\n\n\t\tif( mechanismInfo->request != CRYPT_UNUSED )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckCertMgmtAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MESSAGE_CERTMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy )\n\t{\n\tUNUSED_ARG( messageDataPtr );\n\n\treturn( CRYPT_ERROR_PERMISSION );\n\t}\n#endif /* USE_CERTIFICATES && USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/kernel/init.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Initialisation\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check object data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckObject( const OBJECT_INFO *objectInfoPtr )\n\t{\n\tassert( isReadPtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );\n\n\t/* Check general object data */\n\tif( !isEnumRange( objectInfoPtr->type, OBJECT_TYPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Type\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRange( objectInfoPtr->subType, SUBTYPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Subtype\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !CHECK_FLAGS( objectInfoPtr->flags, OBJECT_FLAG_NONE, \n\t\t\t\t\t  OBJECT_FLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !DATAPTR_ISSET( objectInfoPtr->objectPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Object info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( objectInfoPtr->type == OBJECT_TYPE_CONTEXT && \\\n\t\tobjectInfoPtr->subType == SUBTYPE_CTX_PKC )\n\t\t{\n\t\tif( objectInfoPtr->objectSize < 1024 || \\\n\t\t\tobjectInfoPtr->objectSize > MAX_INTLENGTH )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: PKC object size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( objectInfoPtr->objectSize < 32 || \\\n\t\t\tobjectInfoPtr->objectSize > MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Object size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check safe pointers.  We check the function pointer as well even \n\t   though it's somewhat redundant because it's validated each time its \n\t   dereferenced */\n\tif( !DATAPTR_ISVALID( objectInfoPtr->objectPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Object pointer\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !FNPTR_ISVALID( objectInfoPtr->messageFunction ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Message function\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check object properties */\n\tif( objectInfoPtr->type == OBJECT_TYPE_CONTEXT )\n\t\t{\n\t\tswitch( objectInfoPtr->subType )\n\t\t\t{\n\t\t\tcase SUBTYPE_CTX_CONV:\n\t\t\t\tif( objectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t~( MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Conventional actions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_CTX_PKC:\n\t\t\t\tif( objectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t~( MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckObject: PKC actions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_CTX_HASH:\n\t\t\t\tif( objectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t~MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Hash actions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_CTX_MAC:\n\t\t\t\tif( objectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t~( MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckObject: MAC actions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase SUBTYPE_CTX_GENERIC:\n\t\t\t\tif( ( objectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t~MK_ACTION_PERM( MESSAGE_CTX_GENKEY, ACTION_PERM_ALL ) ) && \\\n\t\t\t\t\t( objectInfoPtr->actionFlags != ACTION_PERM_NONE_ALL ) )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Generic actions\" ));\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Boolean();\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( objectInfoPtr->actionFlags != ACTION_PERM_FLAG_NONE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Spurious actions\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( !isIntegerRange( objectInfoPtr->intRefCount ) || \\\n\t\t!isIntegerRange( objectInfoPtr->extRefCount ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Reference count\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isIntegerRange( objectInfoPtr->lockCount ) ) \n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckObject: Lock count\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check object methods and related objects */\n\tif( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE && \\\n\t\t  objectInfoPtr->owner == CRYPT_UNUSED ) || \\\n\t\t( objectInfoPtr->type == OBJECT_TYPE_USER && \\\n\t\t  objectInfoPtr->owner == SYSTEM_OBJECT_HANDLE ) )\n\t\t{\n\t\t/* The system object and default user object have special-case \n\t\t   properties */\n\t\tif( objectInfoPtr->dependentObject != CRYPT_ERROR || \\\n\t\t\tobjectInfoPtr->dependentDevice != CRYPT_ERROR )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Spurious dependent objects\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\n\t\t{\n\t\tif( objectInfoPtr->owner != DEFAULTUSER_OBJECT_HANDLE && \\\n\t\t\t!isHandleRangeValid( objectInfoPtr->owner ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Owner handle\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( objectInfoPtr->dependentObject != CRYPT_ERROR && \\\n\t\t\t!isHandleRangeValid( objectInfoPtr->dependentObject ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Dependent object\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( objectInfoPtr->dependentDevice != CRYPT_ERROR && \\\n\t\t\tobjectInfoPtr->dependentDevice != SYSTEM_OBJECT_HANDLE && \\\n\t\t\t!isHandleRangeValid( objectInfoPtr->dependentDevice ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckObject: Dependent device\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tThread Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Execute a function in a background thread.  This takes a pointer to the\n   function to execute in the background thread, a set of parameters to pass\n   to the function, and an optional semaphore ID to set once the thread is\n   started.  A function is run via a background thread as follows:\n\n\tvoid threadFunction( const THREAD_FUNCTION_PARAMS *threadParams )\n\t\t{\n\t\t}\n\n\tinitThreadParams( &threadParams, ptrParam, intParam );\n\tkrnlDispatchThread( threadFunction, &threadParams, SEMAPHORE_ID ) */\n\n#ifdef USE_THREAD_FUNCTIONS\n\n/* The function that's run as a thread.  This calls the user-supplied\n   service function with the user-supplied parameters */\n\nTHREADFUNC_DEFINE( threadServiceFunction, threadInfoPtr )\n\t{\n\tconst THREAD_INFO *threadInfo = ( THREAD_INFO * ) threadInfoPtr;\n\tconst THREAD_FUNCTION threadFunction = ( THREAD_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( threadInfo->threadFunction );\n\tORIGINAL_INT_VAR( intParam, threadInfo->threadParams.intParam );\n\tORIGINAL_INT_VAR( semaphore, threadInfo->semaphore );\n\t\t/* Note that the above two macros give initialised-but-not-referenced\n\t\t   warnings in release builds */\n\n\tassert( isReadPtr( threadInfoPtr, sizeof( THREAD_INFO ) ) );\n\tassert( threadServiceFunction != NULL );\n\t\t\t/* We can't use a REQUIRES() because of the polymorphic return \n\t\t\t   type */\n\tif( threadFunction == NULL )\n\t\t{\n\t\t/* It's a bit unclear what we should do in this case since it's a \n\t\t   shouldn't-occur condition, exiting now seems to be the least\n\t\t   unsafe action */\n\t\tTHREAD_EXIT( threadInfo->syncHandle );\n\t\t}\n\n\t/* We're running as a thread, call the thread service function and clear\n\t   the associated semaphore (if there is one) when we're done.  We check\n\t   to make sure that the thread params are unchanged to catch erroneous\n\t   use of stack-based storage for the parameter data */\n\tthreadFunction( &threadInfo->threadParams );\n\tassert( threadInfo->threadParams.intParam == ORIGINAL_VALUE( intParam ) );\n\tassert( threadInfo->semaphore == ORIGINAL_VALUE( semaphore ) );\n\tif( threadInfo->semaphore != SEMAPHORE_NONE )\n\t\tclearSemaphore( threadInfo->semaphore );\n\tTHREAD_EXIT( threadInfo->syncHandle );\n\t}\n\n/* Dispatch a function in a background thread.  If the threadParams value\n   is NULL we use the kernel's thread data storage, otherwise we use the\n   caller-provided storage */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlDispatchThread( THREAD_FUNCTION threadFunction,\n\t\t\t\t\t\tTHREAD_STATE threadState, void *ptrParam, \n\t\t\t\t\t\tconst int intParam, const SEMAPHORE_TYPE semaphore )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tTHREAD_INFO *threadInfo = \\\n\t\t\t( threadState == NULL ) ? &krnlData->threadInfo : \\\n\t\t\t\t\t\t\t\t\t  ( THREAD_INFO * ) threadState;\n\tTHREAD_HANDLE dummy = THREAD_INITIALISER;\n\tint status;\n\n\tassert( threadState == NULL || \\\n\t\t\tisWritePtr( threadState, sizeof( THREAD_STATE ) ) );\n\n\tstatic_assert( sizeof( THREAD_STATE ) >= sizeof( THREAD_INFO ), \\\n\t\t\t\t   \"Thread storage size\" );\n\n\t/* Preconditions: The parameters appear valid, and it's a valid\n\t   semaphore (SEMAPHORE_NONE is valid since it indicates that the caller\n\t   doesn't want a semaphore set) */\n\tREQUIRES( threadFunction != NULL );\n\tREQUIRES( isEnumRangeOpt( semaphore, SEMAPHORE ) );\n\n\t/* Initialise the thread parameters */\n\tmemset( threadInfo, 0, sizeof( THREAD_INFO ) );\n\tFNPTR_SET( threadInfo->threadFunction, threadFunction );\n\tthreadInfo->threadParams.ptrParam = ptrParam;\n\tthreadInfo->threadParams.intParam = intParam;\n\tthreadInfo->semaphore = semaphore;\n\n\t/* Fire up the thread and set the associated semaphore if required.\n\t   There's no problem with the thread exiting before we set the\n\t   semaphore because it's a one-shot, so if the thread gets there first\n\t   the attempt to set the semaphore below is ignored */\n\tTHREAD_CREATE( threadServiceFunction, threadInfo, dummy,\n\t\t\t\t   threadInfo->syncHandle, status );\n\tif( cryptStatusOK( status ) && semaphore != SEMAPHORE_NONE )\n\t\tsetSemaphore( semaphore, threadInfo->syncHandle );\n\treturn( status );\n\t}\n#endif /* USE_THREAD_FUNCTIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPre-initialisation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Correct initialisation of the kernel is handled by having the object\n   management functions check the state of the initialisation flag before\n   they do anything and returning CRYPT_ERROR_NOTINITED if cryptlib hasn't\n   been initialised.  Since everything in cryptlib depends on the creation\n   of objects, any attempt to use cryptlib without it being properly\n   initialised are caught.\n\n   Reading the initialisation flag presents something of a chicken-and-egg\n   problem since the read should be protected by the intialisation mutex,\n   but we can't try and grab it unless the mutex has been initialised.  If\n   we just read the flag directly and rely on the object map mutex to\n   protect access we run into a potential race condition on shutdown:\n\n\tthread1\t\t\t\t\t\t\t\tthread2\n\n\tinited = T\t\t\t\t\t\t\tread inited = T\n\tinited = F, destroy objects\n\t\t\t\t\t\t\t\t\t\tlock objects, die\n\n   The usual way to avoid this is to perform an interlocked mutex lock, but\n   this isn't possible here since the initialisation mutex may not be\n   initialised.\n\n   If possible we use dynamic initialisation of the kernel to resolve this,\n   taking advantage of stubs that the compiler inserts into the code to\n   perform initialisation functions when cryptlib is loaded.  If the\n   compiler doesn't support this, we have to use static initialisation.\n   This has a slight potential race condition if two threads call the init\n   function at the same time, but in practice the only thing that can happen\n   is that the initialisation mutex gets initialised twice, leading to a\n   small resource leak when cryptlib shuts down */\n\n#if defined( __WIN32__ ) || defined( __WINCE__ )\n  /* Windows supports dynamic initialisation by allowing the init/shutdown\n\t functions to be called from DllMain(), however if we're building a\n\t static library there won't be a DllMain() so we have to do a static\n\t init */\n  #ifdef STATIC_LIB\n\t#define STATIC_INIT\n  #endif /* STATIC_LIB */\n#elif defined( __GNUC__ ) && defined( __PIC__ ) && defined( USE_THREADS )\n  /* If we're being built as a shared library with gcc, we can use\n\t constructor and destructor functions to automatically perform pre-init\n\t and post-shutdown functions in a thread-safe manner.  By telling gcc\n\t to put the preInit() and postShutdown() functions in the __CTOR_LIST__\n\t and __DTOR_LIST__, they're called automatically before dlopen/dlclose\n\t return */\n  void preInit( void ) __attribute__ ((constructor));\n  void postShutdown( void ) __attribute__ ((destructor));\n#elif defined( __SUNPRO_C ) && ( __SUNPRO_C >= 0x570 )\n  /* The value of __SUNPRO_C bears no relation whatsoever to the actual \n\t version number of the compiler and even Sun's docs give different \n\t values in different places for the same compiler version, but 0x570 \n\t seems to work */\n  #pragma init ( preInit )\n  #pragma fini ( postShutdown )\n#elif defined( __PALMOS__ )\n  /* PalmOS supports dynamic initialisation by allowing the init/shutdown\n\t functions to be called from PilotMain */\n#else\n  #define STATIC_INIT\n#endif /* Systems not supporting dynamic initialisation */\n\n/* Before we can begin and end the initialisation process, we need to\n   initialise the initialisation lock.  This gets a bit complex, and is\n   handled in the following order of preference:\n\n\tA. Systems where the OS contacts a module to tell it to initialise itself\n\t   before it's called directly for the first time.\n\n\tB. Systems where statically initialising the lock to an all-zero value is\n\t   equivalent to intialising it at runtime.\n\n\tC. Systems where the lock must be statically initialised at runtime.\n\n   A and B are thread-safe, C isn't thread-safe but unlikely to be a problem\n   except in highly unusual situations (two different threads entering\n   krnlBeginInit() at the same time) and not something that we can fix\n   without OS support.\n\n   To handle this pre-initialisation, we provide the following functions for\n   use with case A, statically initialise the lock to handle case B, and\n   initialise it if required in krnlBeginInit() to handle case C */\n\nvoid preInit( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\t/* For MUTEX access */\n\tint status;\n\n\tinitBuiltinStorage();\n\tMUTEX_CREATE( initialisation, status );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Error handling at this point gets a bit complicated since these \n\t\t   functions are called before the main() is called or dlopen()\n\t\t   returns, so there's no way to react to an error status.  Even\n\t\t   the debug exception thrown by retIntError() may be dangerous,\n\t\t   but it's only used in the debug version when (presumably) some\n\t\t   sort of debugging support is present.  In any case if the mutex\n\t\t   create fails at this point (a) something is seriously wrong and \n\t\t   (b) presumably successive mutex creations will fail as well, at\n\t\t   which point they can be detected */\n\t\tretIntError_Void();\n\t\t}\n\t}\n\nvoid postShutdown( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\t/* For MUTEX access */\n\n\tMUTEX_DESTROY( initialisation );\n\tdestroyBuiltinStorage();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInitialisation Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Begin and complete the kernel initialisation, leaving the initialisation\n   mutex locked between the two calls to allow external initialisation of\n   further, non-kernel-related items */\n\nCHECK_RETVAL_ACQUIRELOCK( MUTEX_LOCKNAME( initialisation ) ) \\\nint krnlBeginInit( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint status;\n\n#ifdef STATIC_INIT\n\t/* If the krnlData hasn't been set up yet, set it up now */\n\tif( krnlData->initLevel <= INIT_LEVEL_NONE )\n\t\tpreInit();\n#endif /* STATIC_INIT */\n\n\t/* Lock the initialisation mutex to make sure that other threads don't\n\t   try to access it */\n\tMUTEX_LOCK( initialisation );\n\n\t/* If we're already initialised, don't to anything */\n\tif( krnlData->initLevel > INIT_LEVEL_NONE )\n\t\t{\n\t\tMUTEX_UNLOCK( initialisation );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n#ifndef USE_EMBEDDED_OS\n\t/* If the time is screwed up we can't safely do much since so many\n\t   protocols and operations depend on it, however since embedded \n\t   systems may not have RTCs or if they have them they're inevitably \n\t   not set right, we don't perform this sanity-check if it's an\n\t   embedded build */\n\tif( getTime() <= MIN_TIME_VALUE )\n\t\t{\n\t\tMUTEX_UNLOCK( initialisation );\n\t\tDEBUG_DIAG(( \"System time is severely messed up, cannot continue \"\n\t\t\t\t\t \"without a correctly set system clock\" ));\n\t\tretIntError();\n\t\t}\n#endif /* USE_EMBEDDED_OS */\n\n\t/* Initialise the ephemeral portions of the kernel data block.  Since\n\t   the shutdown level value is non-ephemeral (it has to persist across\n\t   shutdowns to handle threads that may still be active inside cryptlib\n\t   when a shutdown occurs), we have to clear this explicitly */\n\tclearKernelData();\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_NONE;\n\n\t/* Initialise all of the kernel modules.  Except for the allocation of\n\t   the kernel object table this is all straight static initialistion\n\t   and self-checking, so we should never fail at this stage */\n\tstatus = initAllocation();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initAttributeACL();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initCertMgmtACL();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initInternalMsgs();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initKeymgmtACL();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initMechanismACL();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initMessageACL();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initObjects();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initObjectAltAccess();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initSemaphores();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initSendMessage();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( initialisation );\n#ifdef CONFIG_FAULT_MALLOC\n\t\t/* If we're using memory fault-injection then a failure at this \n\t\t   point is expected */\n\t\treturn( CRYPT_ERROR_MEMORY );\n#else\n\t\tretIntError();\n#endif /* CONFIG_FAULT_MALLOC */\n\t\t}\n\n\t/* The kernel data block has been initialised */\n\tkrnlData->initLevel = INIT_LEVEL_KRNLDATA;\n\n\treturn( CRYPT_OK );\n\t}\n\nRELEASELOCK( MUTEX_LOCKNAME( initialisation ) ) \\\nvoid krnlCompleteInit( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\t/* We've completed the initialisation process */\n\tkrnlData->initLevel = INIT_LEVEL_FULL;\n\n\tMUTEX_UNLOCK( initialisation );\n\t}\n\n/* Begin and complete the kernel shutdown, leaving the initialisation\n   mutex locked between the two calls to allow external shutdown of\n   further, non-kernel-related items.  The shutdown proceeds as follows:\n\n\tlock initialisation mutex;\n\tsignal internal worker threads (async.init, randomness poll)\n\t\tto exit (shutdownLevel = SHUTDOWN_LEVEL_THREADS);\n\tsignal all non-destroy messages to fail\n\t\t(shutdownLevel = SHUTDOWN_LEVEL_MESSAGES in destroyObjects());\n\tdestroy objects (via destroyObjects());\n\tshut down kernel modules;\n\tshut down kernel mechanisms (semaphores, messages)\n\t\t(shutdownLevel = SHUTDOWN_LEVEL_MUTEXES);\n\tclear kernel data; */\n\nCHECK_RETVAL_ACQUIRELOCK( MUTEX_LOCKNAME( initialisation ) ) \\\nint krnlBeginShutdown( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\t/* Lock the initialisation mutex to make sure that other threads don't\n\t   try to access it */\n\tMUTEX_LOCK( initialisation );\n\n\t/* We can only begin a shutdown if we're fully initialised */\n\tREQUIRES_MUTEX( krnlData->initLevel == INIT_LEVEL_FULL, \\\n\t\t\t\t\tinitialisation );\n\n\t/* If we're already shut down, don't to anything */\n\tif( krnlData->initLevel <= INIT_LEVEL_NONE )\n\t\t{\n\t\tMUTEX_UNLOCK( initialisation );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\tkrnlData->initLevel = INIT_LEVEL_KRNLDATA;\n\n\t/* Signal all remaining internal threads to exit (dum differtur, vita \n\t   transcurrit) */\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_THREADS;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL_RELEASELOCK( MUTEX_LOCKNAME( initialisation ) ) \\\nint krnlCompleteShutdown( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\t/* Once the kernel objects have been destroyed, we're in the closing-down\n\t   state in which no more messages are processed.  There are a few \n\t   special-case situations such as a shutdown that occurs because of a\n\t   failure to initialise that we also need to handle */\n\tREQUIRES( ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\tkrnlData->shutdownLevel == SHUTDOWN_LEVEL_NONE ) || \\\n\t\t\t  ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\tkrnlData->shutdownLevel == SHUTDOWN_LEVEL_MESSAGES ) || \\\n\t\t\t  ( krnlData->initLevel == INIT_LEVEL_FULL && \\\n\t\t\t\tkrnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES ) );\n\n\t/* Shut down all of the kernel modules */\n\tendAllocation();\n\tendAttributeACL();\n\tendCertMgmtACL();\n\tendInternalMsgs();\n\tendKeymgmtACL();\n\tendMechanismACL();\n\tendMessageACL();\n\tendObjects();\n\tendObjectAltAccess();\n\tendSemaphores();\n\tendSendMessage();\n\n\t/* At this point all kernel services have been shut down */\n\tENSURES( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MUTEXES );\n\n\t/* Turn off the lights on the way out.  Note that the kernel data-\n\t   clearing operation leaves the shutdown level set to handle any\n\t   threads that may still be active */\n\tclearKernelData();\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_ALL;\n\tMUTEX_UNLOCK( initialisation );\n\n#ifdef STATIC_INIT\n\tpostShutdown();\n#endif /* STATIC_INIT */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Indicate to a cryptlib-internal worker thread that the kernel is shutting\n   down and the thread should exit as quickly as possible.  We don't protect\n   this check with a mutex since it can be called after the kernel mutexes\n   have been destroyed.  This lack of mutex protection for the flag isn't a\n   serious problem, it's checked at regular intervals by worker threads so\n   if the thread misses the flag update it'll bve caught at the next check */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN krnlIsExiting( void )\n\t{\n\tconst KERNEL_DATA *krnlData = getKrnlData();\n\n\treturn( ( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_THREADS ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Oddball functions that are placed here because there's no other obvious\n   place for them.\n   \n   Sleep for a given number of milliseconds.  This function is used to \n   dither results from (failed) crypto operations in order to make them less\n   susceptible to timing attacks */\n\nCHECK_RETVAL \\\nint krnlWait( IN_RANGE( 1, 10000 ) const int milliSeconds )\n\t{\n\tREQUIRES( milliSeconds >= 1 && milliSeconds <= 10000 );\n\n\tTHREAD_SLEEP( milliSeconds );\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/int_msg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInternal Message Handlers\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDependency ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The ACL tables for each object dependency type */\n\nstatic const DEPENDENCY_ACL dependencyACLTbl[] = {\n\t/* Envelopes and sessions can have conventional encryption and MAC\n\t   contexts attached */\n\tMK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_NONE, ST_SESS_ANY, \\\n\t\t\t   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE, ST_NONE ),\n\n\t/* PKC contexts can have certs attached and vice versa.  Since the\n\t   certificate can change the permissions on the context, we set the\n\t   DEP_FLAG_UPDATEDEP flag to ensure that the cert permissions get\n\t   reflected onto the context */\n\tMK_DEPACL_EX( OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE, ST_NONE, \\\n\t\t\t\t  OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE, \n\t\t\t\t  DEP_FLAG_UPDATEDEP ),\n\tMK_DEPACL_EX( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE, \\\n\t\t\t\t  OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE, ST_NONE, \n\t\t\t\t  DEP_FLAG_UPDATEDEP ),\n\n\t/* Contexts can have crypto devices attached */\n\tMK_DEPACL( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_ANY_STD, ST_NONE ),\n\n\t/* Hardware crypto devices can have PKCS #15 storage objects attached */\n\tMK_DEPACL( OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_HW, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_KEYSET, ST_NONE, ST_KEYSET_FILE, ST_NONE ),\n\n\t/* Anything can have the system device attached, since all objects not\n\t   created via crypto devices are created via the system device */\n\tMK_DEPACL( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_KEYSET, ST_NONE, ST_KEYSET_ANY, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_NONE, ST_SESS_ANY, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_ANY_STD, ST_NONE, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\tMK_DEPACL( OBJECT_TYPE_USER, ST_NONE, ST_NONE, ST_USER_ANY, \\\n\t\t\t   OBJECT_TYPE_DEVICE, ST_NONE, ST_DEV_SYSTEM, ST_NONE ),\n\n\t/* End-of-ACL marker */\n\tMK_DEPACL_END(), MK_DEPACL_END()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Update an action permission.  This implements a ratchet that only allows\n   permissions to be made more restrictive after they've initially been set,\n   so that once a permission is set to a given level it can't be set back to\n   a less restrictive one (i.e. it's a write-up policy) */\n\nCHECK_RETVAL \\\nstatic int updateActionPerms( IN_FLAGS( ACTION_PERM ) int currentPerm, \n\t\t\t\t\t\t\t  IN_FLAGS( ACTION_PERM ) const int newPerm )\n\t{\n\tint permMask = ACTION_PERM_MASK, i, LOOP_ITERATOR;\n\n\t/* Preconditions: The permissions are valid */\n\tREQUIRES( currentPerm > 0 && currentPerm <= ACTION_PERM_ALL_MAX );\n\tREQUIRES( newPerm > 0 && newPerm <= ACTION_PERM_ALL_MAX );\n\n\t/* For each permission, update its value if the new setting is more\n\t   restrictive than the current one.  Since smaller values are more\n\t   restrictive, we can do a simple range comparison and replace the\n\t   existing value if it's larger than the new one */\n\tLOOP_SMALL( i = 0, i < ACTION_PERM_COUNT, i++ )\n\t\t{\n\t\tif( ( newPerm & permMask ) < ( currentPerm & permMask ) )\n\t\t\tcurrentPerm = ( currentPerm & ~permMask ) | ( newPerm & permMask );\n\t\tpermMask <<= ACTION_PERM_BITS;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Postcondition: The new permission is at least as restrictive (or more\n\t   so) than the old one */\n\tFORALL( i, 0, ACTION_PERM_COUNT,\n\t\t\t( currentPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) <= \\\n\t\t\t\t( newPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) );\n\n\treturn( currentPerm );\n\t}\n\n/* Update the action permissions for an object based on the composite\n   permissions for it and a dependent object.  This is a special-case\n   function because it has to operate with the object table unlocked.  This\n   is necessary because the dependent object may be owned by another thread,\n   and if we were to leave the object table locked the two would deadlock if\n   we were sending the object a message while owning the object table at the\n   same time that the other thread was sending a message while owning the\n   object.\n\n   There is one (rather unlikely) potential race condition possible here in\n   which the object is destroyed and replaced by a new one while the object\n   table is unlocked, so we end up updating the action permissions for a\n   different object.  To protect against this, we check the unique ID after\n   we re-lock the object table to make sure that it's the same object */\n\nCHECK_RETVAL \\\nstatic int updateDependentObjectPerms( IN_HANDLE const CRYPT_HANDLE objectHandle,\n\t\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE dependentObject )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_TYPE objectType = objectTable[ objectHandle ].type;\n\tconst CRYPT_CONTEXT contextHandle = \\\n\t\t( objectType == OBJECT_TYPE_CONTEXT ) ? objectHandle : dependentObject;\n\tconst CRYPT_CERTIFICATE certHandle = \\\n\t\t( objectType == OBJECT_TYPE_CERTIFICATE ) ? objectHandle : dependentObject;\n\tconst int uniqueID = objectTable[ objectHandle ].uniqueID;\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint actionFlags = 0, status;\n\tORIGINAL_INT_VAR( oldPerm, objectTable[ contextHandle ].actionFlags );\n\t\t/* Note that the above macro gives initialised-but-not-referenced \n\t\t   warnings in release builds */\n\t\n\t/* Preconditions: Objects are valid, one is a cert and the other a\n\t   context, and they aren't dependent on each other (which would create\n\t   a dependency update loop).  Note that these checks aren't performed\n\t   at runtime since they've already been performed by the calling\n\t   function, all we're doing here is establishing preconditions rather\n\t   than performing actual parameter checking */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidHandle( dependentObject ) );\n\tREQUIRES( ( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT && \\\n\t\t\t\tobjectTable[ dependentObject ].type == OBJECT_TYPE_CERTIFICATE ) || \\\n\t\t\t  ( objectTable[ objectHandle ].type == OBJECT_TYPE_CERTIFICATE && \\\n\t\t\t\tobjectTable[ dependentObject ].type == OBJECT_TYPE_CONTEXT ) );\n\tREQUIRES( objectTable[ objectHandle ].dependentObject != dependentObject || \\\n\t\t\t  objectTable[ dependentObject ].dependentObject != objectHandle );\n\n\t/* Since we're about to send messages to the dependent object, we have to\n\t   unlock the object table.  Since we're about to hand off control to\n\t   other threads, we clear any object-table references since we can't \n\t   rely on them to be consistent when we re-lock the table */\n\tobjectTable = NULL;\n\tMUTEX_UNLOCK( objectTable );\n\n\t/* Make sure that we're not making a private key dependent on a cert,\n\t   which is a public-key object.  We check this here rather than having\n\t   the caller check it because it requires having the object table\n\t   unlocked */\n\tif( objectType == OBJECT_TYPE_CERTIFICATE && \\\n\t\tcheckContextCapability( dependentObject, \n\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_PRIVATE ) )\n\t\t{\n\t\tMUTEX_LOCK( objectTable );\n\t\tretIntError();\n\t\t}\n\n\t/* For each action type, enable its continued use only if the cert\n\t   allows it.  Because the certificate may not have been fully\n\t   initialised yet (for example if we're attaching a context to a\n\t   cert that's in the process of being created), we have to perform\n\t   a passive-container action-available check that also works on a\n\t   low-state object rather than a standard active-object check.  \n\t   \n\t   In addition since the introduction of certificates now requires that\n\t   we distinguish between \"sign any kind of data except data that's a\n\t   certificate\" and \"sign data that's a certificate\", we have to check\n\t   for MESSAGE_CHECK_PKC_SIGN_SPECIAL_AVAIL alongside the standard\n\t   MESSAGE_CHECK_PKC_SIGN_AVAIL.\n\n\t   Because a key with a certificate attached indicates that it's\n\t   (probably) being used for some function that involves interaction\n\t   with a relying party (i.e. that it probably has more value than a raw\n\t   key with no strings attached), we set the action permission to\n\t   ACTION_PERM_NONE_EXTERNAL rather than allowing ACTION_PERM_ALL.  This\n\t   both ensures that it's only used in a safe manner via the cryptlib\n\t   internal mechanisms, and makes sure that it's not possible to utilize\n\t   the signature/encryption duality of some algorithms to create a\n\t   signature where it's been disallowed */\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_SIGN_AVAIL ) || \\\n\t\tcheckContextCapability( certHandle, MESSAGE_CHECK_PKC_SIGN_CA_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_SIGCHECK_AVAIL ) || \\\n\t\tcheckContextCapability( certHandle, MESSAGE_CHECK_PKC_SIGCHECK_CA_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL );\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_ENCRYPT_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_DECRYPT_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );\n\tif( checkContextCapability( certHandle, MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL ) )\n\t\tactionFlags |= \\\n\t\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );\n\n\t/* Inner precondition: The usage shouldn't be all-zero.  Technically it\n\t   can be since there are bound to be certs out there broken enough to do\n\t   this, and certainly under the stricter compliance levels this *will*\n\t   happen, so we make it a warning that's only produced in debug mode */\n\tif( actionFlags == 0 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Action %s is constrained by its associated\",\n\t\t\t\t\t getObjectDescriptionNT( contextHandle ) ));\n\t\tDEBUG_DIAG(( \"certificate %s to not allow any actions\", \n\t\t\t\t\t getObjectDescriptionNT( certHandle ) ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\t}\n\n\t/* We're done querying the dependent object, re-lock the object table, \n\t   reinitialise any references to it, and make sure that the original \n\t   object hasn't been touched */\n\tMUTEX_LOCK( objectTable );\n\tobjectTable = getObjectTable();\n\tif( objectTable[ objectHandle ].uniqueID != uniqueID )\n\t\treturn( CRYPT_ERROR_SIGNALLED );\n\tif( actionFlags == 0 )\n\t\t{\n\t\t/* See the comment above, we can't continue at this point because we \n\t\t   can't set the action permissions attribute to nothing */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tstatus = setPropertyAttribute( contextHandle, CRYPT_IATTRIBUTE_ACTIONPERMS,\n\t\t\t\t\t\t\t\t   &actionFlags );\n\n\t/* Postcondition: The new permission is at least as restrictive (or more\n\t   so) than the old one */\n\tFORALL( i, 0, ACTION_PERM_COUNT,\n\t\t\t( objectTable[ contextHandle ].actionFlags & ( ACTION_PERM_MASK << ( i * 2 ) ) ) <= \\\n\t\t\t( ORIGINAL_VALUE( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );\n\n\treturn( status );\n\t}\n\n/* Convert an internal object reference to an external one */\n\nCHECK_RETVAL \\\nint convertIntToExtRef( IN_HANDLE const int objectHandle )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint status;\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\n\t/* Convert at least one internal reference to the object to an external \n\t   one */\n\tstatus = incRefCount( objectHandle, 0, NULL, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = decRefCount( objectHandle, 0, NULL, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\treturn( status );\n\n\t/* Recovering from an error at this point is tricky, it's a shouldn't-\n\t   occur condition in any case but if it does occur then the fact that \n\t   the object reference is in an unclear state means we can't do a \n\t   straight decRef().  The safest option seems to be to explicitly \n\t   destroy it, which usually produces the correct result but in the case \n\t   of something like fetching a certificate from a session or envelope \n\t   will lead to the session/envelope's reference being destroyed as \n\t   well */\n\t( void ) krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\nCHECK_RETVAL \\\nint initInternalMsgs( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on the object dependency ACL */\n\tLOOP_LARGE( i = 0, dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst DEPENDENCY_ACL *dependencyACL = &dependencyACLTbl[ i ];\n\n\t\tENSURES( isEnumRange( dependencyACL->type, OBJECT_TYPE ) && \\\n\t\t\t\t isEnumRange( dependencyACL->dType, OBJECT_TYPE ) );\n\t\tENSURES( !( dependencyACL->subTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( dependencyACL->subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( dependencyACL->subTypeC & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_B ) ) );\n\t\tENSURES( !( dependencyACL->dSubTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t\t\t SUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( dependencyACL->dSubTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t SUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( dependencyACL->dSubTypeC & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t SUBTYPE_CLASS_B ) ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initInternalMsgs( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endInternalMsgs( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet/Set Property Attributes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get/set object property attributes.  We differentiate between a small\n   number of user-accessible properties such as the object's owner, and\n   properties that are only accessible by cryptlib.  The user-accessible\n   properties can be locked, which makes them immutable (at least to being\n   explicitly set, they can still be implicitly altered, for example setting\n   a new object owner decrements the forwardcount value) and also unreadable\n   by the user */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getPropertyAttribute( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  OUT_BUFFER_FIXED_C( sizeof( int ) ) void *messageDataPtr )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tint *valuePtr = ( int * ) messageDataPtr;\n\n\tassert( isWritePtr( messageDataPtr, sizeof( int ) ) );\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( attribute == CRYPT_PROPERTY_OWNER || \\\n\t\t\t  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \\\n\t\t\t  attribute == CRYPT_PROPERTY_LOCKED || \\\n\t\t\t  attribute == CRYPT_PROPERTY_USAGECOUNT || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_TYPE || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_SUBTYPE || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_STATUS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_INTERNAL || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\tswitch( attribute )\n\t\t{\n\t\t/* User-accessible properties */\n\t\tcase CRYPT_PROPERTY_OWNER:\n\t\t\t/* We allow this to be read since its value can be determined\n\t\t\t   anyway with a trial access */\n\t\t\tif( !TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_OWNED ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTINITED );\n#ifdef USE_THREADS\n\t\t\t/* A small number of implementations use non-scalar thread IDs, \n\t\t\t   which we can't easily handle when all that we have is an \n\t\t\t   integer handle.  However, the need to bind threads to objects \n\t\t\t   only exists because of Win32 security holes arising from the \n\t\t\t   ability to perform thread injection, so this isn't a big \n\t\t\t   issue */\n  #ifdef NONSCALAR_HANDLES\n\t\t\tif( sizeof( objectInfoPtr->objectOwner ) > sizeof( int ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n  #endif /* NONSCALAR_HANDLES */\n\t\t\t*valuePtr = ( int ) objectInfoPtr->objectOwner;\n#else\n\t\t\t*valuePtr = 0;\n#endif /* USE_THREADS */\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_FORWARDCOUNT:\n\t\t\tif( TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_ATTRLOCKED ) )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t*valuePtr = objectInfoPtr->forwardCount;\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_LOCKED:\n\t\t\t/* We allow this to be read since its value can be determined\n\t\t\t   anyway with a trial write */\n\t\t\t*( ( BOOLEAN * ) messageDataPtr ) = \\\n\t\t\t\t\t\tTEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t   OBJECT_FLAG_ATTRLOCKED ) ? TRUE : FALSE;\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_USAGECOUNT:\n\t\t\t*valuePtr = objectInfoPtr->usageCount;\n\t\t\tbreak;\n\n\t\t/* Internal properties */\n\t\tcase CRYPT_IATTRIBUTE_TYPE:\n\t\t\t*valuePtr = objectInfoPtr->type;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_SUBTYPE:\n\t\t\t*valuePtr = objectInfoPtr->subType;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_STATUS:\n\t\t\t*valuePtr = GET_FLAGS( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t   OBJECT_FLAGMASK_STATUS );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_INTERNAL:\n\t\t\t*( ( BOOLEAN * ) messageDataPtr ) = \\\n\t\t\t\t\tTEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t   OBJECT_FLAG_INTERNAL ) ? TRUE : FALSE;\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_ACTIONPERMS:\n\t\t\t*valuePtr = objectInfoPtr->actionFlags;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint setPropertyAttribute( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  IN_BUFFER_C( sizeof( int ) ) void *messageDataPtr )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst int value = *( ( int * ) messageDataPtr );\n\n\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( attribute == CRYPT_PROPERTY_HIGHSECURITY || \\\n\t\t\t  attribute == CRYPT_PROPERTY_OWNER || \\\n\t\t\t  attribute == CRYPT_PROPERTY_FORWARDCOUNT || \\\n\t\t\t  attribute == CRYPT_PROPERTY_LOCKED || \\\n\t\t\t  attribute == CRYPT_PROPERTY_USAGECOUNT || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_STATUS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_INTERNAL || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_ACTIONPERMS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_LOCKED );\n\tREQUIRES( objectHandle >= NO_SYSTEM_OBJECTS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_STATUS );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\tswitch( attribute )\n\t\t{\n\t\t/* User-accessible properties */\n\t\tcase CRYPT_PROPERTY_HIGHSECURITY:\n\t\t\t/* This is a combination property that makes an object owned,\n\t\t\t   non-forwardable, and locked */\n\t\t\tif( TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_ATTRLOCKED ) )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n#ifdef USE_THREADS\n\t\t\tobjectInfoPtr->objectOwner = THREAD_SELF();\n#endif /* USE_THREADS */\n\t\t\tobjectInfoPtr->forwardCount = 0;\n\t\t\tSET_FLAGS( objectInfoPtr->flags, \n\t\t\t\t\t   OBJECT_FLAG_ATTRLOCKED | OBJECT_FLAG_OWNED );\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_OWNER:\n\t\t\t/* This property can still be changed (even if the object is\n\t\t\t   locked) until the forwarding count drops to zero, otherwise\n\t\t\t   locking the object would prevent any forwarding */\n\t\t\tif( objectInfoPtr->forwardCount != CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\tif( objectInfoPtr->forwardCount <= 0 )\n\t\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\tobjectInfoPtr->forwardCount--;\n\t\t\t\t}\n\t\t\tif( value == CRYPT_UNUSED )\n\t\t\t\tCLEAR_FLAG( objectInfoPtr->flags, OBJECT_FLAG_OWNED );\n\t\t\telse\n\t\t\t\t{\n#if defined( USE_THREADS ) \n\t\t\t\t/* See the comment in getPropertyAttribute() about the use \n\t\t\t\t   of scalar vs. non-scalar thread types */\n  #ifdef NONSCALAR_HANDLES\n\t\t\t\tif( sizeof( objectInfoPtr->objectOwner ) <= sizeof( int ) )\n  #endif /* NONSCALAR_HANDLES */\n\t\t\t\t\t{\n\t\t\t\t\tobjectInfoPtr->objectOwner = ( THREAD_HANDLE ) value;\n\t\t\t\t\tSET_FLAG( objectInfoPtr->flags, OBJECT_FLAG_OWNED );\n\t\t\t\t\t}\n#endif /* USE_THREADS */\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_FORWARDCOUNT:\n\t\t\tif( TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_ATTRLOCKED ) )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\tif( objectInfoPtr->forwardCount != CRYPT_UNUSED && \\\n\t\t\t\tobjectInfoPtr->forwardCount < value )\n\t\t\t\t{\n\t\t\t\t/* Once set the forward count can only be decreased, never\n\t\t\t\t   increased */\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t}\n\t\t\tobjectInfoPtr->forwardCount = value;\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_LOCKED:\n\t\t\t/* Precondition: This property can only be set to true */\n\t\t\tREQUIRES( value != FALSE );\n\n\t\t\tSET_FLAG( objectInfoPtr->flags, OBJECT_FLAG_ATTRLOCKED );\n\t\t\tbreak;\n\n\t\tcase CRYPT_PROPERTY_USAGECOUNT:\n\t\t\tif( TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t   OBJECT_FLAG_ATTRLOCKED ) || \\\n\t\t\t\t( objectInfoPtr->usageCount != CRYPT_UNUSED && \\\n\t\t\t\t  objectInfoPtr->usageCount < value ) )\n\t\t\t\t{\n\t\t\t\t/* Once set the usage count can only be decreased, never\n\t\t\t\t   increased */\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t\t}\n\t\t\tobjectInfoPtr->usageCount = value;\n\t\t\tbreak;\n\n\t\t/* Internal properties */\n\t\tcase CRYPT_IATTRIBUTE_STATUS:\n\t\t\t/* We're clearing an error/abnormal state */\n\t\t\tREQUIRES( value == CRYPT_OK );\n\n\t\t\tif( isInvalidObjectState( objectHandle ) )\n\t\t\t\t{\n\t\t\t\t/* If the object is in an abnormal state, we can only (try to)\n\t\t\t\t   return it back to the normal state after the problem is\n\t\t\t\t   resolved */\n\t\t\t\tREQUIRES( value == CRYPT_OK );\n\n\t\t\t\t/* If we're processing a notification from the caller that\n\t\t\t\t   the object init is complete and the object was destroyed\n\t\t\t\t   while it was being created (which sets its state to\n\t\t\t\t   CRYPT_ERROR_SIGNALLED), tell the caller to convert the\n\t\t\t\t   message to a destroy object message unless it's a system\n\t\t\t\t   object, which can't be explicitly destroyed.  In this case\n\t\t\t\t   we just return an error so the cryptlib init fails */\n\t\t\t\tif( TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t   OBJECT_FLAG_SIGNALLED ) )\n\t\t\t\t\t{\n\t\t\t\t\treturn( ( objectHandle < NO_SYSTEM_OBJECTS ) ?\n\t\t\t\t\t\t\tCRYPT_ERROR_SIGNALLED : OK_SPECIAL );\n\t\t\t\t\t}\n\n\t\t\t\t/* We're transitioning the object to the initialised state */\n\t\t\t\tREQUIRES( TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t OBJECT_FLAG_NOTINITED ) );\n\t\t\t\tCLEAR_FLAG( objectInfoPtr->flags, OBJECT_FLAG_NOTINITED );\n\t\t\t\tENSURES( !TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t OBJECT_FLAG_NOTINITED ) );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Postcondition: The object is in a valid state */\n\t\t\tENSURES( !isInvalidObjectState( objectHandle ) );\n\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_INTERNAL:\n\t\t\t{\n\t\t\tint status;\n\n\t\t\t/* Internal objects can be made external after creation or fetch \n\t\t\t   from another object like a keyset, but not the other way \n\t\t\t   round */\n\t\t\tREQUIRES( value == FALSE );\n\n\t\t\t/* Make the object externally accessible */\n\t\t\tREQUIRES( isInternalObject( objectHandle ) );\n\t\t\tCLEAR_FLAG( objectInfoPtr->flags, OBJECT_FLAG_INTERNAL );\n\n\t\t\t/* Now that the object is external we need to convert at least \n\t\t\t   one internal reference to it to an external one */\n\t\t\tstatus = convertIntToExtRef( objectHandle );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_ACTIONPERMS:\n\t\t\t{\n\t\t\tconst int newPerm = \\\n\t\t\t\t\tupdateActionPerms( objectInfoPtr->actionFlags, value );\n\n\t\t\tif( cryptStatusError( newPerm ) )\n\t\t\t\treturn( newPerm );\n\t\t\tobjectInfoPtr->actionFlags = newPerm;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_LOCKED:\n\t\t\t/* Incremement or decrement the object's lock count depending on\n\t\t\t   whether we're locking or unlocking it */\n\t\t\tif( value )\n\t\t\t\t{\n\t\t\t\t/* Precondition: The lock count is positive or zero */\n\t\t\t\tREQUIRES( objectInfoPtr->lockCount >= 0 );\n\n\t\t\t\tobjectInfoPtr->lockCount++;\n\n\t\t\t\tENSURES( objectInfoPtr->lockCount < MAX_INTLENGTH );\n#ifdef USE_THREADS\n\t\t\t\tobjectInfoPtr->lockOwner = THREAD_SELF();\n#endif /* USE_THREADS */\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Precondition: The lock count is positive */\n\t\t\t\tREQUIRES( objectInfoPtr->lockCount > 0 );\n\n\t\t\t\tobjectInfoPtr->lockCount--;\n\n\t\t\t\tENSURES( objectInfoPtr->lockCount >= 0 );\n\t\t\t\t}\n\n\t\t\t/* If it's a certificate, notify it that it should save/restore\n\t\t\t   its internal state */\n\t\t\tif( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE )\n\t\t\t\t{\n\t\t\t\tconst MESSAGE_FUNCTION messageFunction = \\\n\t\t\t\t\t\t\t\t( MESSAGE_FUNCTION ) \\\n\t\t\t\t\t\t\t\tFNPTR_GET( objectInfoPtr->messageFunction );\n\t\t\t\tvoid *objectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\n\t\t\t\tENSURES( messageFunction != NULL );\n\t\t\t\tENSURES( objectPtr != NULL );\n\t\t\t\t( void ) messageFunction( objectPtr, MESSAGE_CHANGENOTIFY, \n\t\t\t\t\t\t\t\t\t\t  messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t  MESSAGE_CHANGENOTIFY_STATE );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUpdate Internal Properties\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Increment/decrement the reference counts for an object.  Since references \n   can be either internal or external, we have to handle the two separately.  \n   If the last external reference is removed then the object becomes \n   internal-only, if all references are removed then the object is \n   destroyed.\n   \n   There's an additional reference-count manipulation facility in the \n   attribute-handling mechanism for CRYPT_IATTRIBUTE_INTERNAL, which \n   transfers a reference from internal to external when making an object \n   external */\n\nCHECK_RETVAL \\\nint incRefCount( IN_HANDLE const int objectHandle, \n\t\t\t\t STDC_UNUSED const int dummy1,\n\t\t\t\t STDC_UNUSED const void *dummy2, \n\t\t\t\t const BOOLEAN isInternal )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tint *referenceCountPtr = isInternal ? \\\n\t\t\t\t\t\t\t &objectTable[ objectHandle ].intRefCount : \\\n\t\t\t\t\t\t\t &objectTable[ objectHandle ].extRefCount;\n\tORIGINAL_INT_VAR( oldRefCount, *referenceCountPtr );\n\n\t/* Preconditions.  Since there are two reference counts, the one that \n\t   we're updating can be zero if the other one is nonzero */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isInternal == TRUE || isInternal == FALSE );\n\tREQUIRES( isShortIntegerRange( *referenceCountPtr ) );\n\n\t/* Make sure that we don't try and increment a reference count a \n\t   suspicious number of times */\n\tif( *referenceCountPtr >= MAX_INTLENGTH_SHORT - 1 )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* Increment the object's reference count */\n\t( *referenceCountPtr )++;\n\n\t/* Postcondition: We incremented the reference count and it's now greater\n\t   than zero (the ground state) */\n\tENSURES( isShortIntegerRangeNZ( *referenceCountPtr ) );\n\tENSURES( *referenceCountPtr == ORIGINAL_VALUE( oldRefCount ) + 1 );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint decRefCount( IN_HANDLE const int objectHandle, \n\t\t\t\t STDC_UNUSED const int dummy1,\n\t\t\t\t STDC_UNUSED const void *dummy2, \n\t\t\t\t const BOOLEAN isInternal )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tint *referenceCountPtr = isInternal ? \\\n\t\t\t\t\t\t\t &objectTable[ objectHandle ].intRefCount : \\\n\t\t\t\t\t\t\t &objectTable[ objectHandle ].extRefCount;\n\tint status;\n\tORIGINAL_INT_VAR( oldRefCount, *referenceCountPtr );\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isInternal == TRUE || isInternal == FALSE );\n\tREQUIRES( isShortIntegerRangeNZ( *referenceCountPtr ) );\n\n\t/* If the last external reference is about to be destroyed, make the \n\t   object internal.  This marks it as invalid for any external access, \n\t   so that to the caller it looks like it's been destroyed even if its \n\t   internal reference count keeps it active */\n\tif( !isInternal && !isInternalObject( objectHandle ) && \\\n\t\t*referenceCountPtr <= 1 )\n\t\t{\n\t\tSET_FLAG( objectTable[ objectHandle ].flags, OBJECT_FLAG_INTERNAL );\n\t\tENSURES( isInternalObject( objectHandle ) );\n\t\t}\n\n\t/* Decrement the object's reference count */\n\t( *referenceCountPtr )--;\n\n\t/* Postconditions: We decremented the reference count and it's greater \n\t   than or equal to zero (the ground state) */\n\tENSURES( *referenceCountPtr >= 0 && \\\n\t\t\t *referenceCountPtr < MAX_INTLENGTH_SHORT - 1 );\n\tENSURES( *referenceCountPtr == ORIGINAL_VALUE( oldRefCount ) - 1 );\n\n\t/* If there are still references to the object present, there's nothing\n\t   further to do */\n\tif( objectTable[ objectHandle ].intRefCount > 0 || \\\n\t\tobjectTable[ objectHandle ].extRefCount > 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* We're about to destroy the object, all references to it have been \n\t   removed */\n\tENSURES( objectTable[ objectHandle ].extRefCount == 0 && \\\n\t\t\t objectTable[ objectHandle ].intRefCount == 0 );\n\n\t/* Destroy the object.  Since this can entail arbitrary amounts of \n\t   processing during the object shutdown phase, we have to unlock the \n\t   object table around the call */\n\tMUTEX_UNLOCK( objectTable );\n\tstatus = krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );\n\tMUTEX_LOCK( objectTable );\n\n\treturn( status );\n\t}\n\n/* Get/set dependent objects for an object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getDependentObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\tconst int targetType,\n\t\t\t\t\t\tIN_BUFFER_C( sizeof( int ) ) \\\n\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t/* This is a bit of a lie since we actually \n\t\t\t\t\t\t\t   return the dependent object through this \n\t\t\t\t\t\t\t   pointer, however making it non-const means \n\t\t\t\t\t\t\t   that we'd have to also un-const every other \n\t\t\t\t\t\t\t   use of this parameter in all other functions \n\t\t\t\t\t\t\t   accessed via this function pointer */\n\t\t\t\t\t\tSTDC_UNUSED const BOOLEAN dummy )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint *valuePtr = ( int * ) messageDataPtr, status;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidType( targetType ) );\n\n\t/* Clear return value */\n\t*valuePtr = CRYPT_ERROR;\n\n\tstatus = findTargetType( objectHandle, valuePtr, targetType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Postconditions: No dependent object found */\n\t\tENSURES( *valuePtr == CRYPT_ERROR );\n\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\t/* Postconditions: We found a dependent object */\n\tENSURES( isValidObject( *valuePtr ) && \\\n\t\t\t isSameOwningObject( *valuePtr, objectHandle ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint setDependentObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\tIN_ENUM( SETDEP_OPTION ) const int option,\n\t\t\t\t\t\tIN_BUFFER_C( sizeof( int ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\tSTDC_UNUSED const BOOLEAN dummy )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst OBJECT_INFO *dependentObjectInfoPtr;\n\tconst int dependentObject = *( ( int * ) messageDataPtr );\n\tconst DEPENDENCY_ACL *dependencyACL = NULL;\n\tint *objectHandlePtr, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t/* Preconditions: Parameters are valid */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( option == SETDEP_OPTION_NOINCREF || \\\n\t\t\t  option == SETDEP_OPTION_INCREF );\n\tREQUIRES( isValidHandle( dependentObject ) );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* Make sure that the object is valid, it may have been signalled after\n\t   the message was sent */\n\tif( !isValidObject( dependentObject ) )\n\t\treturn( CRYPT_ERROR_SIGNALLED );\n\tdependentObjectInfoPtr = &objectTable[ dependentObject ];\n\tREQUIRES( sanityCheckObject( dependentObjectInfoPtr ) );\n\tif( dependentObjectInfoPtr->type == OBJECT_TYPE_DEVICE )\n\t\tobjectHandlePtr = &objectInfoPtr->dependentDevice;\n\telse\n\t\tobjectHandlePtr = &objectInfoPtr->dependentObject;\n\n\t/* Basic validity checks: There can't already be a dependent object set */\n\tif( *objectHandlePtr != CRYPT_ERROR )\n\t\t{\n\t\t/* There's already a dependent object present and we're trying to\n\t\t   overwrite it with a new one, something is seriously wrong */\n\t\tretIntError();\n\t\t}\n\n\t/* More complex validity checks to ensure that the object table is\n\t   consistent: The object isn't already dependent on the dependent object\n\t   (making the dependent object then dependent on the object would\n\t   create a loop), and the object won't be dependent on its own object\n\t   type unless it's a device dependent on the system device */\n\tif( ( ( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ? \\\n\t\t\t  dependentObjectInfoPtr->dependentDevice : \\\n\t\t\t  dependentObjectInfoPtr->dependentObject ) == objectHandle ) || \\\n\t\t( objectInfoPtr->type == dependentObjectInfoPtr->type && \\\n\t\t  dependentObject != SYSTEM_OBJECT_HANDLE ) )\n\t\tretIntError();\n\n\t/* Find the dependency ACL entry for this object/dependent object\n\t   combination.  Since there can be more than one dependent object\n\t   type for an object, we check subtypes as well */\n\tLOOP_MED( i = 0, dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( dependencyACLTbl[ i ].type == objectInfoPtr->type && \\\n\t\t\tdependencyACLTbl[ i ].dType == dependentObjectInfoPtr->type && \\\n\t\t\t( isValidSubtype( dependencyACLTbl[ i ].dSubTypeA, \\\n\t\t\t\t\t\t\t  dependentObjectInfoPtr->subType ) || \\\n\t\t\t  isValidSubtype( dependencyACLTbl[ i ].dSubTypeB, \\\n\t\t\t\t\t\t\t  dependentObjectInfoPtr->subType ) || \\\n\t\t\t  isValidSubtype( dependencyACLTbl[ i ].dSubTypeC, \\\n\t\t\t\t\t\t\t  dependentObjectInfoPtr->subType ) ) )\n\t\t\t{\n\t\t\tdependencyACL = &dependencyACLTbl[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( dependencyACLTbl, DEPENDENCY_ACL ) );\n\tENSURES( dependencyACL != NULL );\n\n\t/* Inner precondition: We have the appropriate ACL for this combination\n\t   of object and dependent object */\n\tREQUIRES( dependencyACL->type == objectInfoPtr->type && \\\n\t\t\t  dependencyACL->dType == dependentObjectInfoPtr->type && \\\n\t\t\t  ( isValidSubtype( dependencyACL->dSubTypeA, \\\n\t\t\t\t\t\t\t\tdependentObjectInfoPtr->subType ) || \\\n\t\t\t\tisValidSubtype( dependencyACL->dSubTypeB, \\\n\t\t\t\t\t\t\t\tdependentObjectInfoPtr->subType ) || \\\n\t\t\t\tisValidSubtype( dependencyACL->dSubTypeC, \\\n\t\t\t\t\t\t\t\tdependentObjectInfoPtr->subType ) ) );\n\n\t/* Type-specific checks.  For PKC context -> cert and cert -> PKC context\n\t   attaches we should also check that the primary PKC object is a\n\t   private-key object and the dependent PKC object is a public-key object\n\t   to catch things like a private key depending on a (public-key) cert,\n\t   however this requires unlocking the object table in order to send the\n\t   context a check message.  Since this requires additional precautions,\n\t   we leave it for updateDependentObjectPerms(), which has to unlock the\n\t   table for its own update operations */\n\tENSURES( isValidSubtype( dependencyACL->subTypeA, \\\n\t\t\t\t\t\t\t objectInfoPtr->subType ) || \\\n\t\t\t isValidSubtype( dependencyACL->subTypeB, \\\n\t\t\t\t\t\t\t objectInfoPtr->subType ) || \\\n\t\t\t isValidSubtype( dependencyACL->subTypeC, \\\n\t\t\t\t\t\t\t objectInfoPtr->subType ) );\n\tENSURES( isValidSubtype( dependencyACL->dSubTypeA, \\\n\t\t\t\t\t\t\t dependentObjectInfoPtr->subType ) || \\\n\t\t\t isValidSubtype( dependencyACL->dSubTypeB, \\\n\t\t\t\t\t\t\t dependentObjectInfoPtr->subType ) || \\\n\t\t\t isValidSubtype( dependencyACL->dSubTypeC, \\\n\t\t\t\t\t\t\t dependentObjectInfoPtr->subType ) );\n\n\t/* Inner precondition */\n\tREQUIRES( *objectHandlePtr == CRYPT_ERROR );\n\tREQUIRES( isSameOwningObject( objectHandle, dependentObject ) );\n\n\t/* Certs and contexts have special relationships in that the cert can\n\t   constrain the use of the context beyond its normal level.  If we're\n\t   performing this type of object attachment, we have to adjust one\n\t   object's behaviour based on the permissions of the other one.  We do\n\t   this before we increment the reference count because the latter can\n\t   never fail so we don't have to worry about undoing the update */\n\tif( dependencyACL->flags & DEP_FLAG_UPDATEDEP )\n\t\t{\n\t\tstatus = updateDependentObjectPerms( objectHandle, dependentObject );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Update the dependent object's reference count if required and record\n\t   the new status in the object table.  Dependent objects can be\n\t   established in one of two ways, by taking an existing object and\n\t   attaching it to another object (which increments its reference count,\n\t   since it's now being referred to by the original owner and by the\n\t   object it's  attached to), or by creating a new object and attaching\n\t   it to another object (which doesn't increment the reference count\n\t   since it's only referred to by the controlling object).  An example of\n\t   the former operation is adding a context from a cert request to a cert\n\t   (the cert request is referenced by both the caller and the cert), an\n\t   example of the latter operation is attaching a data-only cert to a\n\t   context (the cert is only referenced by the context) */\n\tif( option == SETDEP_OPTION_INCREF )\n\t\t{\n\t\tstatus = incRefCount( dependentObject, 0, NULL, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t*objectHandlePtr = dependentObject;\n\n\t/* Postconditions */\n\tENSURES( isValidObject( *objectHandlePtr ) && \\\n\t\t\t isSameOwningObject( objectHandle, *objectHandlePtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Clone an object.  The older copy-on-write implementation didn't actually\n   do anything at this point except check that the access was valid and set\n   the aliased and cloned flags to indicate that the object needed to be\n   handled specially if a write access was made to it, but with the kernel\n   tracking instance data we can do a copy immediately to create two\n   distinct objects */\n\nCHECK_RETVAL \\\nint cloneObject( IN_HANDLE const int objectHandle, \n\t\t\t\t IN_HANDLE const int clonedObject,\n\t\t\t\t STDC_UNUSED const void *dummy1, \n\t\t\t\t STDC_UNUSED const BOOLEAN dummy2 )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tOBJECT_INFO *clonedObjectInfoPtr = &objectTable[ clonedObject ];\n\tconst MESSAGE_FUNCTION messageFunction = ( MESSAGE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( objectInfoPtr->messageFunction );\n\tvoid *objectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\tvoid *clonedObjectPtr = DATAPTR_GET( clonedObjectInfoPtr->objectPtr );\n\tint actionFlags, status;\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) && \\\n\t\t\t  objectHandle >= NO_SYSTEM_OBJECTS );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tREQUIRES( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );\n\tREQUIRES( isValidObject( clonedObject ) && \\\n\t\t\t  clonedObject >= NO_SYSTEM_OBJECTS );\n\tREQUIRES( sanityCheckObject( clonedObjectInfoPtr ) );\n\tREQUIRES( clonedObjectInfoPtr->type == OBJECT_TYPE_CONTEXT );\n\tREQUIRES( objectHandle != clonedObject );\n\tREQUIRES( messageFunction != NULL );\n\tREQUIRES( objectPtr != NULL );\n\tREQUIRES( clonedObjectPtr != NULL );\n\n\t/* Make sure that the original object is in the high state.  This will\n\t   have been checked by the caller anyway, but we check again here to\n\t   make sure */\n\tif( !isInHighState( objectHandle ) )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* Cloning of non-native contexts is somewhat complex because we usually\n\t   can't clone a device object, so we have to detect requests to clone\n\t   these objects and increment their reference count instead.  This\n\t   isn't a major problem because cryptlib always creates native contexts\n\t   for clonable algorithms, if the user explicitly overrides this by\n\t   using their own device-specific context then the usage will usually\n\t   be create, add to envelope, destroy, so there's no need to clone the\n\t   context anyway.  The only that time there's a potential problem is if\n\t   they override the use of native contexts by adding device contexts to\n\t   multiple envelopes, but in that case it's assumed that they'll be\n\t   aware of potential problems with this approach */\n\tif( objectInfoPtr->dependentDevice != SYSTEM_OBJECT_HANDLE )\n\t\treturn( incRefCount( objectHandle, 0, NULL, TRUE ) );\n\n\t/* Since this is an internal-use-only object, lock down the action\n\t   permissions so that only encryption and hash actions from internal\n\t   sources are allowed (assuming they were allowed to begin with).\n\t   Keygen is disabled entirely (there should already be a key loaded),\n\t   and signing isn't possible with a non-PKC object anyway.  This takes\n\t   advantage of the ratchet enforced for the action permissions, which\n\t   can only make them more restrictive than the existing permissions, to\n\t   avoid having to read and modify each permission individually */\n\tactionFlags = \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_NONE_EXTERNAL );\n\tstatus = setPropertyAttribute( clonedObject, CRYPT_IATTRIBUTE_ACTIONPERMS,\n\t\t\t\t\t\t\t\t   &actionFlags );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Postcondition: The cloned object can only be used internally */\n\tENSURES( ( clonedObjectInfoPtr->actionFlags & \\\n\t\t\t\t\t\t\t\t~ACTION_PERM_NONE_EXTERNAL_ALL ) == 0 );\n\n\t/* Inner precondition: The instance data is valid and ready to be\n\t   copied */\n\tassert( isWritePtrDynamic( objectPtr, objectInfoPtr->objectSize ) );\n\tassert( isWritePtrDynamic( clonedObjectPtr, \\\n\t\t\t\t\t\t\t   clonedObjectInfoPtr->objectSize ) );\n\tREQUIRES( objectInfoPtr->objectSize == clonedObjectInfoPtr->objectSize );\n\n\t/* Copy across the object contents and reset any instance-specific\n\t   information.  We only update the owning object if required, in\n\t   almost all cases this will be the system device so there's no need\n\t   to perform the update */\n\tmemcpy( clonedObjectPtr, objectPtr, objectInfoPtr->objectSize );\n\tstatus = messageFunction( clonedObjectPtr, MESSAGE_CHANGENOTIFY,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &clonedObject, \n\t\t\t\t\t\t\t  MESSAGE_CHANGENOTIFY_OBJHANDLE );\n\tif( cryptStatusOK( status ) && \\\n\t\tobjectInfoPtr->owner != clonedObjectInfoPtr->owner )\n\t\t{\n\t\tstatus = messageFunction( clonedObjectPtr, MESSAGE_CHANGENOTIFY,\n\t\t\t\t\t\t\t\t  &clonedObjectInfoPtr->owner,\n\t\t\t\t\t\t\t\t  MESSAGE_CHANGENOTIFY_OWNERHANDLE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've copied across the object's state, the cloned object is now\n\t   initialised ready for use */\n\tSET_FLAG( clonedObjectInfoPtr->flags, OBJECT_FLAG_HIGH );\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/kernel.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Kernel Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _KERNEL_DEFINED\n\n#define _KERNEL_DEFINED\n\n#if defined( INC_ALL )\n  #include \"thread.h\"\n#else\n  #include \"kernel/thread.h\"\n#endif /* Compiler-specific includes */\n\n/* RAY and EGON look over code.\n\n   EGON: The structure of this kernel is exactly like the kind of telemetry\n         tracker that NASA uses to secure dead pulsars in deep space.\n\n   RAY: All message dispatch mechanisms and callback functions.\n\n   PETER (to other jailbirds): Everyone getting this so far?  So what?  I\n         guess they just don't make them like they used to.\n\n   RAY: No!  Nobody ever made them like this!  The architect was either a\n        certified genius or an authentic wacko! */\n\n/* \"There is a fine line between genius and insanity.\n    I have erased this line\" - Oscar Levant\n\t(or \"Nullum magnum ingenium sine mixtura dementiae\" if you want it in\n\tthe usual style) */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tParameter Checking Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Macros to perform validity checks on objects and handles.  These checks\n   are:\n\n\tisValidHandle(): Whether a handle is a valid index into the object table.\n\tisValidObject(): Whether a handle refers to an object in the table.\n\tisFreeObject(): Whether a handle refers to an empty entry in the table.\n\tisInternalObject(): Whether an object is an internal object.\n\tisInvalidObjectState(): Whether an object is in an invalid (error) state.\n\tisInUse(): Whether an object is currently in use (processing a message).\n\tisObjectOwner(): If inUse == TRUE, whether this thread is the one using\n\t\t\t\t\t the object.\n\tisInHighState(): Whether an object is in the 'high' security state.\n\tisSameOwningObject(): Whether two objects have the same owner.  We also\n\t\t\t\t\t\t  have to handle the situation where the first object\n\t\t\t\t\t\t  is a user object, in which case it has to be the\n\t\t\t\t\t\t  owner of the second object.\n\tisObjectAccessValid(): Internal/external object access check.\n\tisValidMessage(): Whether a message type is valid.\n\tisInternalMessage(): Whether a message is an internal message.\n\tisValidType(): Whether an object type is valid\n\tisValidSubtype(): Whether an object subtype is allowed based on access\n\t\t\t\t\t  bitflags */\n\n#define isValidHandle( handle ) \\\n\t\t( ( handle ) >= 0 && ( handle ) < MAX_NO_OBJECTS )\n#define isValidObject( handle ) \\\n\t\t( isValidHandle( handle ) && \\\n\t\t  DATAPTR_GET( objectTable[ ( handle ) ].objectPtr ) != NULL )\n#define isFreeObject( handle ) \\\n\t\t( isValidHandle( handle ) && \\\n\t\t  DATAPTR_GET( objectTable[ ( handle ) ].objectPtr ) == NULL )\n#define isInternalObject( handle ) \\\n\t\t( TEST_FLAG( objectTable[ handle ].flags, OBJECT_FLAG_INTERNAL ) )\n#define isObjectAccessValid( objectHandle, message ) \\\n\t\t!( isInternalObject( objectHandle ) && \\\n\t\t   !( message & MESSAGE_FLAG_INTERNAL ) )\n#define isInvalidObjectState( handle ) \\\n\t\t( TEST_FLAG( objectTable[ ( handle ) ].flags, OBJECT_FLAGMASK_STATUS ) )\n#define isInUse( handle ) \\\n\t\t( objectTable[ ( handle ) ].lockCount > 0 )\n#define isObjectOwner( handle ) \\\n\t\tTHREAD_SAME( objectTable[ ( handle ) ].lockOwner, THREAD_SELF() )\n#define isInHighState( handle ) \\\n\t\t( TEST_FLAG( objectTable[ ( handle ) ].flags, OBJECT_FLAG_HIGH ) )\n#define isSameOwningObject( handle1, handle2 ) \\\n\t\t( objectTable[ ( handle1 ) ].owner == CRYPT_UNUSED || \\\n\t\t  objectTable[ ( handle2 ) ].owner == CRYPT_UNUSED || \\\n\t\t  ( objectTable[ ( handle1 ) ].owner == objectTable[ ( handle2 ) ].owner ) || \\\n\t\t  ( ( handle1 ) == objectTable[ ( handle2 ) ].owner ) )\n#define isValidMessage( message ) \\\n\t\t( ( message ) > MESSAGE_NONE && ( message ) < MESSAGE_LAST )\n#define isInternalMessage( message ) \\\n\t\t( ( message ) & MESSAGE_FLAG_INTERNAL )\n#define isValidType( type ) \\\n\t\t( ( type ) > OBJECT_TYPE_NONE && ( type ) < OBJECT_TYPE_LAST )\n#define isValidSubtype( subtypeMask, subtype ) \\\n\t\t( ( ( subtypeMask ) & ( subtype ) ) == ( subtype ) )\n\n/* The set of object checks is used frequently enough that we combine them\n   into a composite check that performs all of the checks in one place */\n\n#define fullObjectCheck( objectHandle, message ) \\\n\t\t( isValidObject( objectHandle ) && \\\n\t\t  isObjectAccessValid( objectHandle, message ) && \\\n\t\t  checkObjectOwnership( objectTable[ objectHandle ] ) )\n\n/* Macros to test whether a message falls into a certain class.  These tests\n   are:\n\n\tisParamMessage(): Whether a message contains an object as a parameter */\n\n#define isParamMessage( message ) \\\n\t\t( ( message ) == MESSAGE_CRT_SIGN || \\\n\t\t  ( message ) == MESSAGE_CRT_SIGCHECK )\n\n/* Macros to manage object ownership, if the OS supports it */\n\n#define checkObjectOwnership( objectPtr ) \\\n\t\t( !TEST_FLAG( ( objectPtr ).flags, OBJECT_FLAG_OWNED ) || \\\n\t\t  THREAD_SAME( ( objectPtr ).objectOwner, THREAD_SELF() ) )\n\n/* A macro to turn an abnormal status indicated in an object's flags into a\n   status code.  The values are prioritised so that notinited > signalled >\n   busy */\n\n#define getObjectStatusValue( flags ) \\\n\t\t( TEST_FLAG( flags, OBJECT_FLAG_NOTINITED ) ? CRYPT_ERROR_NOTINITED : \\\n\t\t  TEST_FLAG( flags, OBJECT_FLAG_SIGNALLED ) ? CRYPT_ERROR_SIGNALLED : \\\n\t\t  CRYPT_OK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tObject Definitions and Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The information maintained by the kernel for each object */\n\ntypedef struct {\n\t/* Object type and value */\n\tOBJECT_TYPE type;\t\t\t/* Object type */\n\tOBJECT_SUBTYPE subType;\t\t/* Object subtype */\n\tDATAPTR objectPtr;\t\t\t/* Object data */\n\tint objectSize;\t\t\t\t/* Object data size */\n\n\t/* Object properties */\n\tSAFE_FLAGS flags;\t\t\t/* Internal-only, locked, etc */\n\tint actionFlags;\t\t\t/* Permitted actions */\n\tint intRefCount, extRefCount;/* Number of int/ext refs.to this object */\n\tint lockCount;\t\t\t\t/* Message-processing lock recursion count */\n#ifdef USE_THREADS\n\tTHREAD_HANDLE lockOwner;\t/* Lock owner if lockCount > 0 */\n#endif /* USE_THREADS */\n\tint uniqueID;\t\t\t\t/* Unique ID for this object */\n/*\ttime_t lastAccess;\t\t\t// Last access time */\n\n\t/* Object security properties */\n\tint forwardCount;\t\t\t/* Number of times ownership can be transferred */\n\tint usageCount;\t\t\t\t/* Number of times obj.can be used */\n#ifdef USE_THREADS\n\tTHREAD_HANDLE objectOwner;\t/* The object's owner */\n#endif /* USE_THREADS */\n\n\t/* Object methods */\n\tFNPTR messageFunction;\t\t/* The object's message handler */\n\n\t/* Owning and dependent objects */\n\tCRYPT_USER owner;\t\t\t/* Owner object handle */\n\tCRYPT_HANDLE dependentObject;\t/* Dependent object (context or cert) */\n\tCRYPT_HANDLE dependentDevice;\t/* Dependent crypto device */\n\t} OBJECT_INFO;\n\n/* The flags that apply to each object in the table */\n\n#define OBJECT_FLAG_NONE\t\t0x0000\t/* Non-flag */\n#define OBJECT_FLAG_INTERNAL\t0x0001\t/* Internal-use only */\n#define OBJECT_FLAG_NOTINITED\t0x0002\t/* Still being initialised */\n#define OBJECT_FLAG_HIGH\t\t0x0004\t/* In 'high' security state */\n#define OBJECT_FLAG_SIGNALLED\t0x0008\t/* In signalled state */\n#define OBJECT_FLAG_STATICALLOC\t0x0010\t/* Statically allocated object */\n#define OBJECT_FLAG_SECUREMALLOC 0x0020\t/* Uses secure memory */\n#define OBJECT_FLAG_OWNED\t\t0x0040\t/* Object is bound to a thread */\n#define OBJECT_FLAG_ATTRLOCKED\t0x0080\t/* Security properties can't be modified */\n#define OBJECT_FLAG_MAX\t\t\t0x00FF\t/* Last possible flag type */\n\n/* The flags that convey information about an object's status */\n\n#define OBJECT_FLAGMASK_STATUS \\\n\t\t( OBJECT_FLAG_NOTINITED | OBJECT_FLAG_SIGNALLED )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKernel Data Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The object allocation state data.  This controls the allocation of\n   handles to newly-created objects.  The first NO_SYSTEM_OBJECTS handles\n   are system objects that exist with fixed handles, the remainder are\n   allocated pseudorandomly under the control of an LFSR */\n\ntypedef struct {\n\tint objectHandle;\t\t\t/* Current object handle */\n\t} OBJECT_STATE_INFO;\n\n/* A structure to store the details of a message sent to an object, and the\n   size of the message queue.  This defines the maximum nesting depth of\n   messages sent by an object.  Because of the way krnlSendMessage() handles\n   message processing, it's extremely difficult to ever have more than two\n   or three messages in the queue unless an object starts recursively\n   sending itself messages */\n\ntypedef struct {\n\tint objectHandle;\t\t\t/* Handle to send message to */\n\tDATAPTR handlingInfoPtr;\t/* Message handling info */\n\tMESSAGE_TYPE message;\n\tDATAPTR messageDataPtr;\n\tint messageValue;\t\t\t/* Message parameters */\n\t} MESSAGE_QUEUE_DATA;\n\n#define MESSAGE_QUEUE_SIZE\t16\n\n/* Semaphores are one-shots, so that once set and cleared they can't be\n   reset.  This is handled by enforcing the following state transitions:\n\n\tUninited -> Set | Clear\n\tSet -> Set | Clear\n\tClear -> Clear\n\n   The handling is complicated somewhat by the fact that on some systems the\n   semaphore has to be explicitly deleted, but only the last thread to use\n   it can safely delete it.  In order to handle this, we reference-count the\n   semaphore and let the last thread out delete it.  In order to do this we\n   introduce an additional state, preClear, which indicates that while the\n   semaphore object is still present, the last thread out should delete it,\n   bringing it to the true clear state */\n\ntypedef enum {\n\tSEMAPHORE_STATE_UNINITED,\n\tSEMAPHORE_STATE_CLEAR,\n\tSEMAPHORE_STATE_PRECLEAR,\n\tSEMAPHORE_STATE_SET,\n\tSEMAPHORE_STATE_LAST\n\t} SEMAPHORE_STATE;\n\ntypedef struct {\n\tSEMAPHORE_STATE state;\t\t/* Semaphore state */\n\tMUTEX_HANDLE object;\t\t/* Handle to system synchronisation object */\n\tint refCount;\t\t\t\t/* Reference count for handle */\n\t} SEMAPHORE_INFO;\n\n/* A structure to store the details of a thread */\n\ntypedef struct {\n\tFNPTR threadFunction;\t\t\t/* Function to call from thread */\n\tTHREAD_PARAMS threadParams;\t\t/* Thread function parameters */\n\tSEMAPHORE_TYPE semaphore;\t\t/* Optional semaphore to set */\n\tMUTEX_HANDLE syncHandle;\t\t/* Handle to use for thread sync */\n\t} THREAD_INFO;\n\n/* When the kernel starts up and closes down it does so in a multi-stage \n   process that's equivalent to Unix runlevels.  For the startup at the\n   first level the kernel data block and all kernel-level primitive\n   objects like mutexes have been initialised.\n   \n   For the shutdown, at the first level all internal worker threads/tasks \n   must exist.  At the next level all messages to objects except destroy \n   messages fail.  At the final level all kernel-managed primitives such as \n   mutexes and semaphores are no longer available */\n\ntypedef enum {\n\tINIT_LEVEL_NONE,\t\t\t/* Uninitialised */\n\tINIT_LEVEL_KRNLDATA,\t\t/* Kernel data block initialised */\n\tINIT_LEVEL_FULL,\t\t\t/* Full initialisation */\n\tINIT_LEVEL_LAST\t\t\t\t/* Last possible init level */\n\t} INIT_LEVEL;\n\ntypedef enum {\n\tSHUTDOWN_LEVEL_NONE,\t\t/* Normal operation */\n\tSHUTDOWN_LEVEL_THREADS,\t\t/* Internal threads must exit */\n\tSHUTDOWN_LEVEL_MESSAGES,\t/* Only destroy messages are valid */\n\tSHUTDOWN_LEVEL_MUTEXES,\t\t/* Kernel objects become invalid */\n\tSHUTDOWN_LEVEL_ALL,\t\t\t/* Complete shutdown */\n\tSHUTDOWN_LEVEL_LAST\t\t\t/* Last possible shutdown level */\n\t} SHUTDOWN_LEVEL;\n\n/* The kernel data block, containing all variables used by the kernel.  With\n   the exception of the special-case values at the start, all values in this\n   block should be set to use zero/NULL as their ground state (for example a\n   boolean variable should have a ground state of FALSE (zero) rather than\n   TRUE (nonzero)).\n\n   If the objectTable giant lock (or more strictly speaking monolithic lock, \n   since the kernel's message-handling is designed to be straight-line code \n   and so never blocks for any amount of time like the Linux giant lock can) \n   ever proves to be a problem then the solution would be to use lock \n   striping, dividing the load of the object table across NO_TABLE_LOCKS \n   locks.  This gets a bit tricky because the object table is dynamically\n   resizeable, a basic mod_NO_TABLE_LOCKS strategy where every n-th entry \n   uses the same lock works but then we'd still need a giant lock to check \n   whether the table is being resized.  To avoid this we can use a lock-free \n   implementation that operates by acquiring each lock (to make sure we have \n   complete control of the table), checking whether another thread beat us to \n   it, and if not resizing the table.  The pseudocode for this is as \n   follows:\n\n\t// Remember the original table size\n\tconst int oldSize = krnlData->objectTableSize;\n\n\t// Acquire each lock\n\tfor( i = 0; i < NO_LOCKS; i++ )\n\t\tTHREAD_LOCK( krnlData->locks[ i ] );\n\n\t// Check whether another thread beat us to the resize while we were \n\t// acquiring locks\n\tif( krnlData->objectTableSize != oldSize )\n\t\t{\n\t\t// Unlock all the locks\n\t\t// ... //\n\t\treturn;\n\t\t}\n\n\t// We hold all the locks and therefore have exclusive control of the \n\t// table, resize it\n\t// ... //\n\n\t// Release each lock again //\n\tfor( i = 0; i < NO_LOCKS; i++ )\n\t\tTHREAD_UNLOCK( krnlData->locks[ i ] );\n\n   This is a conventional lock-free implementation of such an algorithm but \n   is conceptually ugly in that it accesses protected data outside the lock, \n   which will cause concurrency-checking tools to complain.  Until the fast-\n   path through the kernel actually becomes a real bottleneck it's probably \n   best to leave well enough alone */\n\ntypedef struct {\n\t/* The kernel initialisation state and a lock to protect it.  The\n\t   lock and shutdown level value are handled externally and aren't\n\t   cleared when the kernel data block as a whole is cleared.  Note\n\t   that the shutdown level has to be before the lock so that we can\n\t   statically initialise the data with '{ 0 }', which won't work if\n\t   the lock data is non-scalar */\n\tSHUTDOWN_LEVEL shutdownLevel;\t\t/* Kernel shutdown level */\n#ifdef USE_THREADS\n\tMUTEX_DECLARE_STORAGE( initialisation );\n#endif /* USE_THREADS */\n\t/* Everything from this point on is cleared at init and shutdown */\n\tint initLevel;\t\t\t\t\t\t/* Kernel initialisation level */\n\n\t/* The kernel object table management info */\n\tint objectUniqueID;\t\t\t\t\t/* Unique ID for next object */\n\tOBJECT_STATE_INFO objectStateInfo;\t/* Object allocation state */\n#ifdef USE_THREADS\n\tMUTEX_DECLARE_STORAGE( objectTable );\n#endif /* USE_THREADS */\n\n\t/* The kernel message dispatcher queue */\n\tBUFFER( MESSAGE_QUEUE_SIZE, queueEnd ) \\\n\tMESSAGE_QUEUE_DATA messageQueue[ MESSAGE_QUEUE_SIZE + 8 ];\n\tint queueEnd;\t\t\t\t\t\t/* Points past last queue element */\n\n\t/* The kernel semaphores */\n\tBUFFER_FIXED( SEMAPHORE_LAST ) \\\n\tSEMAPHORE_INFO semaphoreInfo[ SEMAPHORE_LAST + 8 ];\n#ifdef USE_THREADS\n\tMUTEX_DECLARE_STORAGE( semaphore );\n#endif /* USE_THREADS */\n\n\t/* The kernel mutexes.  Since mutexes usually aren't scalar values and\n\t   are declared and accessed via macros that manipulate various fields,\n\t   we have to declare a pile of them individually rather than using an\n\t   array of mutexes */\n#ifdef USE_THREADS\n\tMUTEX_DECLARE_STORAGE( mutex1 );\n  #ifdef USE_SESSIONS\n\tMUTEX_DECLARE_STORAGE( mutex2 );\n\tMUTEX_DECLARE_STORAGE( mutex3 );\n\tMUTEX_DECLARE_STORAGE( mutex4 );\n  #endif /* USE_SESSIONS */\n#endif /* USE_THREADS */\n\n\t/* The kernel thread data */\n#ifdef USE_THREADS\n\tTHREAD_INFO threadInfo;\n#endif /* USE_THREADS */\n\n\t/* The kernel secure memory list and a lock to protect it */\n\tDATAPTR allocatedListHead, allocatedListTail;\n#ifdef USE_THREADS\n\tMUTEX_DECLARE_STORAGE( allocation );\n#endif /* USE_THREADS */\n\n\t/* A marker for the end of the kernel data, used during init/shutdown */\n\tint endMarker;\n\t} KERNEL_DATA;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tACL Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in certm_acl.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckCertMgmtAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MESSAGE_CERTMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy );\n\n/* Prototypes for functions in key_acl.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy );\n\n/* Prototypes for functions in mech_acl.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismWrapAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER_C( sizeof( MECHANISM_WRAP_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_WRAP_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismSignAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER_C( sizeof( MECHANISM_SIGN_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_SIGN_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismDeriveAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t   IN_BUFFER_C( sizeof( MECHANISM_DERIVE_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_DERIVE_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t   IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismKDFAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MECHANISM_KDF_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_KDF_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tIN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy );\n\n/* Prototypes for functions in msg_acl.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN paramAclConsistent( const PARAM_ACL *paramACL,\n\t\t\t\t\t\t\tconst BOOLEAN mustBeEmpty );\nCHECK_RETVAL \\\nint preDispatchSignalDependentObjects( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy4 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 5 ) ) \\\nint preDispatchCheckAttributeAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t IN_OPT const void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE const int messageValue,\n\t\t\t\t\t\t\t\t\t IN TYPECAST( ATTRIBUTE_ACL * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *auxInfo );\nCHECK_RETVAL \\\nint preDispatchCheckCompareParam( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  const void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_COMPARE ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 );\nCHECK_RETVAL \\\nint preDispatchCheckCheckParam( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_CHECK ) const int messageValue,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2 );\nCHECK_RETVAL \\\nint preDispatchCheckActionAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const int dummy2,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy3 );\nCHECK_RETVAL \\\nint preDispatchCheckState( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t   STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t   STDC_UNUSED const int dummy2, \n\t\t\t\t\t\t   STDC_UNUSED const void *dummy3 );\nCHECK_RETVAL \\\nint preDispatchCheckParamHandleOpt( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tIN TYPECAST( MESSAGE_ACL * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *auxInfo );\nCHECK_RETVAL \\\nint preDispatchCheckStateParamHandle( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\t  const int messageValue,\n\t\t\t\t\t\t\t\t\t  IN TYPECAST( MESSAGE_ACL * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *auxInfo );\nCHECK_RETVAL \\\nint preDispatchCheckExportAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  const void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTFORMAT ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckData( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t  IN_BUFFER_C( sizeof( MESSAGE_DATA ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t  STDC_UNUSED const int dummy1,\n\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckCreate( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MESSAGE_CREATEOBJECT_INFO ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\tIN_ENUM( OBJECT_TYPE ) const int messageValue,\n\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy );\nCHECK_RETVAL \\\nint preDispatchCheckUserMgmtAccess( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_USERMGMT ) const int messageValue, \n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2 );\nCHECK_RETVAL \\\nint preDispatchCheckTrustMgmtAccess( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t const void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t STDC_UNUSED const int messageValue, \n\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy );\nCHECK_RETVAL \\\nint postDispatchSignalDependentDevices( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy4 );\nCHECK_RETVAL \\\nint postDispatchMakeObjectExternal( STDC_UNUSED const int dummy,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tconst void *auxInfo );\nCHECK_RETVAL \\\nint postDispatchForwardToDependentObject( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_CHECK ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 );\nCHECK_RETVAL \\\nint postDispatchUpdateUsageCount( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy4 );\nCHECK_RETVAL \\\nint postDispatchChangeState( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t STDC_UNUSED const void *dummy4 );\nCHECK_RETVAL \\\nint postDispatchChangeStateOpt( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\tIN TYPECAST( ATTRIBUTE_ACL * ) const void *auxInfo );\nCHECK_RETVAL \\\nint postDispatchHandleZeroise( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t   IN_ENUM( MESSAGE_USERMGMT ) const int messageValue,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy3 );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check object data */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckObject( const OBJECT_INFO *objectInfoPtr );\n\n/* Prototypes for functions in attr_acl.c */\n\nCHECK_RETVAL_PTR \\\nconst void *findAttributeACL( IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t  const BOOLEAN isInternalMessage );\n\n/* Prototypes for functions in int_msg.c */\n\nCHECK_RETVAL \\\nint convertIntToExtRef( IN_HANDLE const int objectHandle );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getPropertyAttribute( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  OUT_BUFFER_FIXED_C( sizeof( int ) ) void *messageDataPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint setPropertyAttribute( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  IN_BUFFER_C( sizeof( int ) ) void *messageDataPtr );\nCHECK_RETVAL \\\nint incRefCount( IN_HANDLE const int objectHandle, \n\t\t\t\t STDC_UNUSED const int dummy1,\n\t\t\t\t STDC_UNUSED const void *dummy2, \n\t\t\t\t const BOOLEAN isInternal );\nCHECK_RETVAL \\\nint decRefCount( IN_HANDLE const int objectHandle, \n\t\t\t\t STDC_UNUSED const int dummy1,\n\t\t\t\t STDC_UNUSED const void *dummy2, \n\t\t\t\t const BOOLEAN isInternal );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getDependentObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\tconst int targetType,\n\t\t\t\t\t\tIN_BUFFER_C( sizeof( int ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t/* This is a bit of a lie since we actually \n\t\t\t\t\t\t\t   return the dependent object through this \n\t\t\t\t\t\t\t   pointer, however making it non-const means \n\t\t\t\t\t\t\t   that we'd have to also un-const every other \n\t\t\t\t\t\t\t   use of this parameter in all other functions \n\t\t\t\t\t\t\t   accessed via this function pointer */\n\t\t\t\t\t\tSTDC_UNUSED const BOOLEAN dummy );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint setDependentObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\tIN_ENUM( SETDEP_OPTION ) const int option,\n\t\t\t\t\t\tIN_BUFFER_C( sizeof( int ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\tSTDC_UNUSED const BOOLEAN dummy );\nCHECK_RETVAL \\\nint cloneObject( IN_HANDLE const int objectHandle, \n\t\t\t\t IN_HANDLE const int clonedObject,\n\t\t\t\t STDC_UNUSED const void *dummy1, \n\t\t\t\t STDC_UNUSED const BOOLEAN dummy2 );\n\n/* Prototypes for functions in sendmsg.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint checkTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\t const long targets );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint findTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\tconst long targets );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint waitForObject( IN_HANDLE const int objectHandle, \n\t\t\t\t   OUT_PTR_COND OBJECT_INFO **objectInfoPtrPtr );\n#ifndef NDEBUG\nconst char *getObjectTypeDescriptionNT( IN_ENUM( OBJECT_TYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst OBJECT_TYPE type, \n\t\t\t\t\t\t\t\t\t\tIN_ENUM( SUBTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst OBJECT_SUBTYPE subType );\nconst char *getObjectDescriptionNT( IN_HANDLE const int objectHandle );\n#endif /* NDEBUG */\n\n/* Prototypes for functions in objects.c */\n\nCHECK_RETVAL \\\nint destroyObjectData( IN_HANDLE const int objectHandle );\nCHECK_RETVAL \\\nint destroyObjects( void );\n\n/* Prototypes for functions in semaphore.c */\n\n#ifdef USE_THREAD_FUNCTIONS\nvoid setSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore,\n\t\t\t\t   const MUTEX_HANDLE object );\nvoid clearSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore );\n#endif /* USE_THREAD_FUNCTIONS */\n\n/* Prototypes for functions in storage.c */\n\nvoid initBuiltinStorage( void );\nvoid destroyBuiltinStorage( void );\nvoid clearKernelData( void );\nCHECK_RETVAL_PTR_NONNULL \\\nKERNEL_DATA *getKrnlData( void );\nCHECK_RETVAL_PTR_NONNULL \\\nOBJECT_INFO *getObjectTable( void );\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getSystemDeviceStorage( void );\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getDefaultUserObjectStorage( void );\n#ifndef NDEBUG\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getKrnlDataSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getObjectTableSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getSystemDeviceStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getDefaultUserObjectStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getRandomInfoStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getTrustMgrStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getSocketPoolStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getScoreboardInfoStorageSize( void );\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getOptionInfoStorageSize( void );\n#endif /* !NDEBUG */\n\n/* Init/shutdown functions for each kernel module */\n\nCHECK_RETVAL \\\nint initAllocation( void );\nvoid endAllocation( void );\nCHECK_RETVAL \\\nint initAttributeACL( void );\nvoid endAttributeACL( void );\n#if defined( USE_CERTIFICATES ) && defined( USE_KEYSETS )\nCHECK_RETVAL \\\nint initCertMgmtACL( void );\nvoid endCertMgmtACL( void );\n#else\n  #define initCertMgmtACL()\t\tCRYPT_OK\n  #define endCertMgmtACL()\n#endif /* USE_CERTIFICATES && USE_KEYSETS */\nCHECK_RETVAL \\\nint initInternalMsgs( void );\nvoid endInternalMsgs( void );\n#ifdef USE_KEYSETS\nCHECK_RETVAL \\\nint initKeymgmtACL( void );\nvoid endKeymgmtACL( void );\n#else\n  #define initKeymgmtACL()\t\tCRYPT_OK\n  #define endKeymgmtACL()\n#endif /* USE_KEYSETS */\nCHECK_RETVAL \\\nint initMechanismACL( void );\nvoid endMechanismACL( void );\nCHECK_RETVAL \\\nint initMessageACL( void );\nvoid endMessageACL( void );\nCHECK_RETVAL \\\nint initObjects( void );\nvoid endObjects( void );\nCHECK_RETVAL \\\nint initObjectAltAccess( void );\nvoid endObjectAltAccess( void );\nCHECK_RETVAL \\\nint initSemaphores( void );\nvoid endSemaphores( void );\nCHECK_RETVAL \\\nint initSendMessage( void );\nvoid endSendMessage( void );\n\n#endif /* _KERNEL_DEFINED */\n"
  },
  {
    "path": "deps/cl345/kernel/key_acl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKeyset ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKeyset ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* ID information.  This defines the ID types that are valid for retrieving\n   each object type;\n\n\tPublic/private keys: Any ID is valid.  There's some overlap here because \n\t\tin some cases the private key is retrieved by first locating the\n\t\tcorresponding public key (which is what the ID actually points to)\n\t\tand then using that to find the matching private key.\n\n\tSecret keys: Only lookups by name or keyID are possible (all other ID\n\t\ttypes are PKC-related).\n\n\tCert requests: Lookups by name or URI are allowed for the user-level \n\t\tCACertManagement() functions, lookups by certID are used for \n\t\tcryptlib-internal access.\n\n\tPKI users: Lookups by name or URI are allowed for the user-level \n\t\tCACertManagement() functions, lookups by keyID and certID are used \n\t\tfor cryptlib-internal access.  PKI users don't really have a keyID\n\t\tin the sense of a subjectKeyIdentifier, in this case it's a \n\t\trandomly-generated value that's unique for each PKI user.\n\n\tRevocation info: Lookups by certID and issuerID are used for cryptlib-\n\t\tinternal access.\n\n\tData: No ID is used, data objects are implicitly identified by type */\n\nstatic const CRYPT_KEYID_TYPE pubKeyIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID, \n\t\tCRYPT_IKEYID_PGPKEYID, CRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID,\n\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE privKeyIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID, \n\t\tCRYPT_IKEYID_PGPKEYID, CRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID,\n\t\tCRYPT_IKEYID_ISSUERANDSERIALNUMBER, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE secKeyIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_IKEYID_KEYID, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE certReqIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_CERTID, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE revReqIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE pkiUserIDs[] = { \n\t\tCRYPT_KEYID_NAME, CRYPT_KEYID_URI, CRYPT_IKEYID_KEYID,\n\t\tCRYPT_IKEYID_CERTID, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE revInfoIDs[] = { \n\t\tCRYPT_IKEYID_CERTID, CRYPT_IKEYID_ISSUERID, \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\nstatic const CRYPT_KEYID_TYPE dataIDs[] = { \n\t\tCRYPT_KEYID_NONE, CRYPT_KEYID_NONE };\n\n/* Key management ACL information.  These work in the same general way as the\n   crypto mechanism ACL checks enforced by the kernel.  The ACL entries are:\n\n\tValid keyset types for R/W/D access.\n\tValid keyset types for getFirst/Next access.\n\tValid keyset types for query access.\n\tValid object types to write.\n\tValid key IDs for read/getFirst/query access.\n\tValid key management flags in the mechanism info.\n\tAccess type for which an ID parameter is required.\n\tAccess type for which a password (or other aux.info) is required\n\t[ Specific object types requires for some keyset types ]\n\n  The access-type entries are used for parameter checking and represent all\n  access types for which these parameters are required, even if those\n  access types aren't currently allowed by the valid access types entry.\n  This is to allow them to be enabled by changing only the valid access\n  types entry without having to update the other two entries as well.\n\n  In addition, there are a few access types (specifically getFirst/Next and\n  private key reads) for which the semantics of password/aux info use are\n  complex enough that we have to hardcode them, leaving only a\n  representative entry in the ACL definition.  Examples of this are keyset\n  vs. crypto device reads (keysets usually need passwords while a logged-\n  in device doesn't), speculative reads from the keyset to determine\n  presence (which don't require a password), and so on.\n\n  The key ID values are the union of the key ID types that are valid for\n  all of the keysets that can store the given object type.  These are\n  used to implement a two-level check, first the main ACL checks whether\n  this ID type is valid for this object type, and then a secondary ACL\n  is used to determine whether the ID type is valid for the source that\n  the object is being read from.\n\n  The (optional) specific object types entry is required for some keysets\n  that require a specific object (typically a certificate or cert chain)\n  rather than just a generic PKC context for the overall keyset item type.\n  \n  The file keysets have three different subtypes, full-featured ones for \n  which any access is allowed (KEYSET_FILE), mininmal ones for which only\n  a single key can be written but that don't contain enough information\n  for deletion, find-first/find-next, or storage of anything other than\n  public/private keys (KEYSET_FILE_PARTIAL), and ones whose format is\n  sufficiently oddball that only read access is allowed (KEYSET_RO).  The\n  schema for these is as follows (+ = all types, F = full only, - = no \n  access):\n\n\t\t\t|\tR\t|\tW\t|\tD\t| FF/FN\t|\tQ\t|\n\t--------+-------+-------+-------+-------+-------+\n\tPubkey\t|\t+\t|  P/F\t|\tF\t|\tF\t|\t-\t|\n\tPrivkey\t|\t+\t|  P/F\t|\tF\t|\t-\t|\t-\t|\n\tSecret\t|\tF\t|\tF\t|\tF\t|\t-\t|\t-\t|\n\tMetadata|\t-\t|\tF\t|\t-\t|\t-\t|\t-\t|\n\t--------+-------+-------+-------+-------+-------+ */\n\nstatic const KEYMGMT_ACL keyManagementACL[] = {\n\t/* Access public key */\n\tMK_KEYACL_EX( KEYMGMT_ITEM_PUBLICKEY,\n\t\t/* R */\tST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/* W */\tST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_DBMS | \\\n\t\t\t\tST_KEYSET_LDAP | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/* D */\tST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_LDAP | \\\n\t\t\t\tST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/* Fn*/\tST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | \\\n\t\t\t\tST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/* Q */\tST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_LDAP,\n\t\t/*Obj*/\tST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN,\n\t\t/*IDs*/\tpubKeyIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY | \\\n\t\t\t\tKEYMGMT_MASK_CERTOPTIONS,\n\t\tACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx,\n\t\tST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_KEYSET_LDAP | \\\n\t\t\t\t\t\t ST_DEV_P11 | ST_DEV_CAPI,\n\t\tST_CERT_CERT | ST_CERT_CERTCHAIN ),\n\n\t/* Access private key */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_PRIVATEKEY,\n\t\t/* R */\tST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \\\n\t\t\t\tST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/* W */\tST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_DEV_P11 | \\\n\t\t\t\tST_DEV_CAPI | ST_DEV_HW,\n\t\t/* D */\tST_KEYSET_FILE | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW,\n\t\t/*FnQ*/\tST_NONE, ST_NONE,\n\t\t/*Obj*/\tST_CTX_PKC,\n\t\t/*IDs*/\tprivKeyIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY | \\\n\t\t\t\tKEYMGMT_MASK_USAGEOPTIONS,\n\t\tACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxXXx ),\n\n\t/* Access secret key */\n\tMK_KEYACL( KEYMGMT_ITEM_SECRETKEY,\n\t\t/*RWD*/\tST_KEYSET_FILE | ST_DEV_P11,\n\t\t/*FnQ*/\tST_NONE,\n\t\t/*Obj*/\tST_CTX_CONV,\n\t\t/*IDs*/\tsecKeyIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_CHECK_ONLY,\n\t\tACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxXXx ),\n\n\t/* Access certificate request/revocation request */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_REQUEST,\n\t\t/*RWD*/\tST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,\n\t\t/*FnQ*/\tST_NONE, ST_KEYSET_DBMS_STORE,\n\t\t/*Obj*/\tST_CERT_CERTREQ | ST_CERT_REQ_CERT,\n\t\t/*IDs*/\tcertReqIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_UPDATE | KEYMGMT_FLAG_INITIALOP,\n\t\tACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_REVREQUEST,\n\t\t/*RWD*/\tST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_NONE,\n\t\t/*FnQ*/\tST_NONE, ST_KEYSET_DBMS_STORE,\n\t\t/*Obj*/\tST_CERT_REQ_REV,\n\t\t/*IDs*/\trevReqIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_NONE,\n\t\tACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),\n\n\t/* Access PKI user info */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_PKIUSER,\n\t\t/*RWD*/\tST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS_STORE,\n\t\t/*FnQ*/\tST_NONE, ST_NONE,\n\t\t/*Obj*/\tST_CERT_PKIUSER,\n\t\t/*IDs*/\tpkiUserIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_GETISSUER,\n\t\tACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),\n\n\t/* Access revocation information/CRL */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_REVOCATIONINFO,\n\t\t/*RWD*/\tST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE, ST_KEYSET_DBMS, ST_NONE,\n\t\t/*FnQ*/\tST_NONE, ST_NONE,\n\t\t/*Obj*/\tST_CERT_CRL,\n\t\t/*IDs*/\trevInfoIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_CHECK_ONLY,\n\t\tACCESS_KEYSET_FxRxD, ACCESS_KEYSET_FNxxx ),\n\n\t/* Access key metadata for dummy contexts */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_KEYMETADATA,\n\t\t/*RWD*/\tST_NONE, ST_KEYSET_FILE, ST_NONE,\n\t\t/*FnQ*/\tST_NONE, ST_NONE,\n\t\t/*Obj*/\tST_CTX_PKC,\n\t\t/*IDs*/\tprivKeyIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_NONE,\n\t\tACCESS_KEYSET_xxRxD, ACCESS_KEYSET_xxxxx ),\n\n\t/* Other data (for PKCS #15 tokens) */\n\tMK_KEYACL_RWD( KEYMGMT_ITEM_DATA,\n\t\t/*RWD*/\tST_KEYSET_FILE, ST_KEYSET_FILE, ST_NONE,\n\t\t/*FnQ*/\tST_NONE, ST_NONE,\n\t\t/*Obj*/\tST_NONE,\n\t\t/*IDs*/\tdataIDs,\n\t\t/*Flg*/\tKEYMGMT_FLAG_NONE,\n\t\tACCESS_KEYSET_xxRWD, ACCESS_KEYSET_FNxxx ),\n\n\t/* Last item type */\n\tMK_KEYACL( KEYMGMT_ITEM_NONE, ST_NONE, ST_NONE, ST_NONE, NULL, \n\t\tKEYMGMT_FLAG_NONE, ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx ),\n\tMK_KEYACL( KEYMGMT_ITEM_NONE, ST_NONE, ST_NONE, ST_NONE, NULL, \n\t\tKEYMGMT_FLAG_NONE, ACCESS_KEYSET_xxxxx, ACCESS_KEYSET_xxxxx )\n\t};\n\n/* A secondary ACL matching key ID types with keyset types.  This is a \n   refinement of the generic list of permitted IDs per object type to\n   read, since this is actually a three-way match of \n   keysetType :: itemType :: idType.  The keyManagementACL is used to\n   check itemType :: idType, this supplementary ACL takes the result\n   of that check and checks it against keysetType */\n\ntypedef struct {\n\tconst CRYPT_KEYID_TYPE idType;\n\tconst OBJECT_SUBTYPE keysetSubTypeB;\n\t} IDTYPE_ACL;\n\nstatic const IDTYPE_ACL idTypeACL[] = {\n\t{ CRYPT_KEYID_NAME, \n\t  ST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_CAPI | ST_DEV_HW },\n\t{ CRYPT_KEYID_URI, \n\t  ST_KEYSET_ANY | ST_DEV_P11 | ST_DEV_HW },\n\t{ CRYPT_IKEYID_KEYID, \n\t  ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \\\n\t\tST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_P11 | ST_DEV_HW },\n\t{ CRYPT_IKEYID_PGPKEYID, \n\t  ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | ST_KEYSET_FILE_RO | \\\n\t\tST_DEV_HW },\n\t{ CRYPT_IKEYID_CERTID, \n\t  ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE },\n\t{ CRYPT_IKEYID_ISSUERID, \n\t  ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_HW },\n\t{ CRYPT_IKEYID_ISSUERANDSERIALNUMBER, \n\t  ST_KEYSET_FILE | ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE | ST_DEV_P11 | \\\n\t\tST_DEV_HW },\n\t{ CRYPT_KEYID_NONE, ST_NONE },\n\t\t{ CRYPT_KEYID_NONE, ST_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\nCHECK_RETVAL \\\nint initKeymgmtACL( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on the key management ACLs */\n\tLOOP_LARGE( i = 0, keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst KEYMGMT_ACL *keyMgmtACL = &keyManagementACL[ i ];\n\t\tint j;\n\n\t\tif( keyMgmtACL->keysetR_subTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->keysetR_subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t   SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->keysetR_subTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \\\n\t\t\tkeyMgmtACL->keysetR_subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( keyMgmtACL->keysetR_subTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->keysetW_subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t   SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->keysetW_subTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \\\n\t\t\tkeyMgmtACL->keysetW_subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( keyMgmtACL->keysetR_subTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->keysetD_subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t   SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->keysetD_subTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \\\n\t\t\tkeyMgmtACL->keysetD_subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( keyMgmtACL->keysetR_subTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->keysetFN_subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t    SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->keysetFN_subTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI | ST_DEV_HW ) ) != 0 || \\\n\t\t\tkeyMgmtACL->keysetFN_subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( keyMgmtACL->keysetR_subTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->keysetQ_subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t   SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->keysetQ_subTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY ) ) != 0 || \\\n\t\t\tkeyMgmtACL->keysetQ_subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( ( keyMgmtACL->objSubTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t  SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->objSubTypeA & \\\n\t\t\t\t~( SUBTYPE_CLASS_A | ST_CERT_ANY | ST_CTX_PKC | \\\n\t\t\t\t\t\t\t\t\t ST_CTX_CONV ) ) != 0 || \\\n\t\t\tkeyMgmtACL->objSubTypeB != ST_NONE || \\\n\t\t\tkeyMgmtACL->objSubTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tENSURES( keyMgmtACL->allowedKeyIDs != NULL );\n\t\tLOOP_LARGE( j = 0, keyMgmtACL->allowedKeyIDs[ j ] != CRYPT_KEYID_NONE && \\\n\t\t\t\t\t\t   j < FAILSAFE_ITERATIONS_SMALL, j++ )\n\t\t\t{\n\t\t\tENSURES( isEnumRange( keyMgmtACL->allowedKeyIDs[ j ], CRYPT_KEYID ) );\n\t\t\t}\n\t\tENSURES( j < FAILSAFE_ITERATIONS_SMALL );\n\n\t\tENSURES( keyMgmtACL->allowedFlags >= KEYMGMT_FLAG_NONE && \\\n\t\t\t\t keyMgmtACL->allowedFlags < KEYMGMT_FLAG_MAX );\n\n\t\tif( keyMgmtACL->specificKeysetSubTypeA != ST_NONE || \\\n\t\t\t( keyMgmtACL->specificKeysetSubTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->specificKeysetSubTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI ) ) != 0 || \\\n\t\t\tkeyMgmtACL->specificKeysetSubTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\tif( ( keyMgmtACL->specificObjSubTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t\t\t  SUBTYPE_CLASS_C ) ) || \\\n\t\t\t( keyMgmtACL->specificObjSubTypeA & \\\n\t\t\t\t~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) != 0 || \\\n\t\t\tkeyMgmtACL->specificObjSubTypeB != ST_NONE || \\\n\t\t\tkeyMgmtACL->specificObjSubTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ) );\n\n\t/* Perform a consistency check on the supplementary ID ACLs */\n\tLOOP_LARGE( i = 0, idTypeACL[ i ].idType != CRYPT_KEYID_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ),\n\t\t\t\ti++ )\n\t\t{\n\t\tconst IDTYPE_ACL *idACL = &idTypeACL[ i ];\n\n\t\tENSURES( isEnumRange( idACL->idType, CRYPT_KEYID ) );\n\n\t\tif( ( idACL->keysetSubTypeB & \\\n\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_P11 | \\\n\t\t\t\t\t\t\t\t\t ST_DEV_CAPI | ST_DEV_HW ) ) != 0 )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Key management supplementary ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initKeymgmtACL( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endKeymgmtACL( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset ACL Check Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* It's a keyset action message, check the access conditions for the mechanism\n   objects */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy )\n\t{\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tconst MESSAGE_KEYMGMT_INFO *mechanismInfo = \\\n\t\t  ( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\tconst KEYMGMT_ACL *keymgmtACL;\n\tconst int accessType = \\\n\t\t\t( localMessage == MESSAGE_KEY_GETKEY ) ? ACCESS_FLAG_R : \\\n\t\t\t( localMessage == MESSAGE_KEY_SETKEY ) ? ACCESS_FLAG_W : \\\n\t\t\t( localMessage == MESSAGE_KEY_DELETEKEY ) ? ACCESS_FLAG_D : \\\n\t\t\t( localMessage == MESSAGE_KEY_GETFIRSTCERT ) ? ACCESS_FLAG_F : \\\n\t\t\t( localMessage == MESSAGE_KEY_GETNEXTCERT ) ? ACCESS_FLAG_N : 0;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_SUBTYPE subType;\n\tint paramObjectHandle, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_KEYMGMT_INFO ) ) );\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( localMessage == MESSAGE_KEY_GETKEY || \\\n\t\t\t  localMessage == MESSAGE_KEY_SETKEY || \\\n\t\t\t  localMessage == MESSAGE_KEY_DELETEKEY || \\\n\t\t\t  localMessage == MESSAGE_KEY_GETFIRSTCERT || \\\n\t\t\t  localMessage == MESSAGE_KEY_GETNEXTCERT );\n\tREQUIRES( isEnumRange( messageValue, KEYMGMT_ITEM ) );\n\tREQUIRES( accessType != 0 );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, keyManagementACL[ i ].itemType != messageValue && \\\n\t\t\t\t\t keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ), \n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( keyManagementACL, KEYMGMT_ACL ) );\n\tENSURES( keyManagementACL[ i ].itemType != KEYMGMT_ITEM_NONE );\n\tkeymgmtACL = &keyManagementACL[ i ];\n\n\t/* Perform a combined check to ensure that the item type being accessed\n\t   is appropriate for this keyset type and the access type is valid */\n\tsubType = objectST( objectHandle );\n\tswitch( localMessage )\n\t\t{\n\t\tcase MESSAGE_KEY_GETKEY:\n\t\t\tif( !isValidSubtype( keymgmtACL->keysetR_subTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetR_subTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetR_subTypeC, subType ) )\n\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_SETKEY:\n\t\t\tif( !isValidSubtype( keymgmtACL->keysetW_subTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetW_subTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetW_subTypeC, subType ) )\n\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_DELETEKEY:\n\t\t\tif( !isValidSubtype( keymgmtACL->keysetD_subTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetD_subTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->keysetD_subTypeC, subType ) )\n\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_GETFIRSTCERT:\n\t\tcase MESSAGE_KEY_GETNEXTCERT:\n\t\t\t/* The two special-purpose accesses are differentiated by whether\n\t\t\t   there's state information provided.  For a general query the\n\t\t\t   result set is determined by an initially-submitted query\n\t\t\t   which is followed by a sequence of fetches.  For a getFirst/\n\t\t\t   getNext the results are determined by a cert identifier with\n\t\t\t   state held externally in the location pointed to by the\n\t\t\t   auxiliary info pointer */\n\t\t\tif( mechanismInfo->auxInfo == NULL )\n\t\t\t\t{\n\t\t\t\t/* Keyset query.  We report this as an arg error since we'll\n\t\t\t\t   have been passed a CRYPT_KEYID_NONE or empty keyID, this\n\t\t\t\t   is more sensible than an object error since there's\n\t\t\t\t   nothing wrong with the object, the problem is that\n\t\t\t\t   there's no keyID present */\n\t\t\t\tif( !isValidSubtype( keymgmtACL->keysetQ_subTypeA, subType ) && \\\n\t\t\t\t\t!isValidSubtype( keymgmtACL->keysetQ_subTypeB, subType ) && \\\n\t\t\t\t\t!isValidSubtype( keymgmtACL->keysetQ_subTypeC, subType ) )\n\t\t\t\t\treturn( ( mechanismInfo->keyIDtype == CRYPT_KEYID_NONE ) ? \\\n\t\t\t\t\t\t\tCRYPT_ARGERROR_NUM1 : CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* getFirst/next.  We can report an object error here since\n\t\t\t\t   this message is only sent internally */\n\t\t\t\tif( !isValidSubtype( keymgmtACL->keysetFN_subTypeA, subType ) && \\\n\t\t\t\t\t!isValidSubtype( keymgmtACL->keysetFN_subTypeB, subType ) && \\\n\t\t\t\t\t!isValidSubtype( keymgmtACL->keysetFN_subTypeC, subType ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t\t\t\t/* Inner precondition: The state information points to an\n\t\t\t\t   integer value containing a reference to the currently\n\t\t\t\t   fetched object */\n\t\t\t\tassert( isReadPtr( mechanismInfo->auxInfo, sizeof( int ) ) );\n\n\t\t\t\tREQUIRES( mechanismInfo->auxInfoLength == sizeof( int ) );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make sure that there's appropriate ID information present if \n\t   required */\n\tif( keymgmtACL->idUseFlags & accessType )\n\t\t{\n\t\tconst IDTYPE_ACL *idACL = NULL;\n\t\tconst int minKeyIDsize = \\\n\t\t\t\t\t( mechanismInfo->keyIDtype == CRYPT_IKEYID_KEYID ) ? \\\n\t\t\t\t\t  1 : MIN_NAME_LENGTH;\n\t\t\t\t\t/* The keyID can be as little as a single byte when it's \n\t\t\t\t\t   stored in a keyset/device from a non-cryptlib source */\n\t\tBOOLEAN keyIdOK = FALSE;\n\t\tint index;\n\n\t\t/* Make sure that the ID information is present and valid */\n\t\tif( !isEnumRange( mechanismInfo->keyIDtype, CRYPT_KEYID ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( !isInternalMessage( message ) && \\\n\t\t\tmechanismInfo->keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( mechanismInfo->keyIDlength < minKeyIDsize || \\\n\t\t\tmechanismInfo->keyIDlength >= MAX_ATTRIBUTE_SIZE || \\\n\t\t\t!isReadPtrDynamic( mechanismInfo->keyID, \\\n\t\t\t\t\t\t\t   mechanismInfo->keyIDlength ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\t/* Make sure that the key ID is of an appropriate type */\n\t\tLOOP_SMALL( index = 0,\n\t\t\t\t\tkeymgmtACL->allowedKeyIDs[ index ] != CRYPT_KEYID_NONE, \n\t\t\t\t\tindex++ )\n\t\t\t{\n\t\t\tif( keymgmtACL->allowedKeyIDs[ index ] == mechanismInfo->keyIDtype )\n\t\t\t\t{\n\t\t\t\tkeyIdOK = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( !keyIdOK )\n\t\t\t{\n\t\t\t/* If we try and retrieve an object using an inappropriate ID \n\t\t\t   type then this is a programming error, but not a fatal one, \n\t\t\t   so we just report it as an unable-to-find object error */\n\t\t\tDEBUG_DIAG(( \"Tried to retrieve object using inappropriate ID \"\n\t\t\t\t\t\t \"type %d\", mechanismInfo->keyIDtype ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\n\t\t/* Finally, check that the keyID is valid for the keyset type.  This \n\t\t   implements the third stage of the three-way check\n\t\t   keysetType :: itemType :: idType */\n\t\tLOOP_MED( index = 0, idTypeACL[ index ].idType != CRYPT_KEYID_NONE && \\\n\t\t\t\t\t\t\t index < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ), \n\t\t\t\t  index++ )\n\t\t\t{\n\t\t\tif( idTypeACL[ index ].idType == mechanismInfo->keyIDtype )\n\t\t\t\t{\n\t\t\t\tidACL = &idTypeACL[ index ];\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( index < FAILSAFE_ARRAYSIZE( idTypeACL, IDTYPE_ACL ) );\n\t\tif( idACL == NULL || \\\n\t\t\t!isValidSubtype( idACL->keysetSubTypeB, subType ) )\n\t\t\t{\n\t\t\t/* As before if we try and retrieve an object by an \n\t\t\t   inappropriate ID type then this is a nonfatal programming \n\t\t\t   error so we warn in the debug build but otherwise just report \n\t\t\t   it as an unable-to-find object error */\n\t\t\tDEBUG_DIAG(( \"Tried to retrieve object using inappropriate ID \"\n\t\t\t\t\t\t \"type %d\", mechanismInfo->keyIDtype ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that there's a password present/not present if required.\n\t   We only check for incorrect parameters here if they were supplied by\n\t   the user, non-user-supplied parameters (which come from within\n\t   cryptlib) are checked by an assertion later on.  For keyset objects\n\t   the password is optional on reads since it may be a label-only read\n\t   or an opportunistic read that tries to read the key without a\n\t   password initially and falls back to retrying with a password if this\n\t   fails, for device objects the password is never used since it was\n\t   supplied when the user logged on to the device.\n\n\t   Since the semantics of passwords for private keys are too complex to\n\t   express with a simple ACL entry, this check is hardcoded */\n\tif( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\tmessageValue == KEYMGMT_ITEM_SECRETKEY )\n\t\t{\n\t\tif( objectTable[ objectHandle ].type == OBJECT_TYPE_KEYSET )\n\t\t\t{\n\t\t\tif( localMessage == MESSAGE_KEY_SETKEY && \\\n\t\t\t\t( mechanismInfo->auxInfo == NULL || \\\n\t\t\t\t  mechanismInfo->auxInfoLength < MIN_NAME_LENGTH ||\n\t\t\t\t  mechanismInfo->auxInfoLength >= MAX_ATTRIBUTE_SIZE ) )\n\t\t\t\t{\n\t\t\t\t/* Private/secret key writes to a keyset must provide a \n\t\t\t\t   password */\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( objectTable[ objectHandle ].type == OBJECT_TYPE_DEVICE );\n\n\t\t\tif( ( mechanismInfo->flags != KEYMGMT_FLAG_LABEL_ONLY ) && \\\n\t\t\t\t( mechanismInfo->auxInfo != NULL || \\\n\t\t\t\t  mechanismInfo->auxInfoLength != 0 ) )\n\t\t\t\t{\n\t\t\t\t/* Private/secret key access to a device doesn't use a \n\t\t\t\t   password, however the auxInfo parameter is also used to \n\t\t\t\t   contain the label for key label reads so we only check \n\t\t\t\t   it if it's a standard key read */\n\t\t\t\treturn( ( keymgmtACL->idUseFlags & accessType ) ? \\\n\t\t\t\t\t\tCRYPT_ARGERROR_STR2 : CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Inner precondition: Only allowed flags are set, there's only one of\n\t   the usage preference flags set, and the object handle to get/set is\n\t   not present if not required (the presence and validity check when it\n\t   is required is performed further down) */\n\tREQUIRES( !( ~keymgmtACL->allowedFlags & mechanismInfo->flags ) );\n\tREQUIRES( mechanismInfo->flags >= KEYMGMT_FLAG_NONE && \\\n\t\t\t  mechanismInfo->flags < KEYMGMT_FLAG_MAX );\n\tREQUIRES( ( mechanismInfo->flags & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\tREQUIRES( localMessage == MESSAGE_KEY_SETKEY || \\\n\t\t\t  mechanismInfo->cryptHandle == CRYPT_ERROR );\n\n\t/* Inner precondition: There's ID information and a password/aux.data\n\t   present/not present as required.  For a private key read the password\n\t   is optional so we don't check it, for a getFirst/getNext the aux.data\n\t   (a pointer to query state) is used when assembling a cert chain (state\n\t   held in the cert) and not used when performing a general query (state\n\t   held in the keyset) */\n\tassert( ( ( keymgmtACL->idUseFlags & accessType ) && \\\n\t\t\t  mechanismInfo->keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t  isReadPtrDynamic( mechanismInfo->keyID, \\\n\t\t\t\t\t\t\t\tmechanismInfo->keyIDlength ) ) ||\n\t\t\t( !( keymgmtACL->idUseFlags & accessType ) && \\\n\t\t\t  mechanismInfo->keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t  mechanismInfo->keyID == NULL && \\\n\t\t\t  mechanismInfo->keyIDlength == 0 ) );\n\tassert( ( ( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\tmessageValue == KEYMGMT_ITEM_SECRETKEY ) && \\\n\t\t\t  localMessage == MESSAGE_KEY_GETKEY ) ||\n\t\t\t  localMessage == MESSAGE_KEY_GETFIRSTCERT ||\n\t\t\t  localMessage == MESSAGE_KEY_GETNEXTCERT ||\n\t\t\t( ( keymgmtACL->pwUseFlags & accessType ) && \\\n\t\t\t  isReadPtrDynamic( mechanismInfo->auxInfo, \\\n\t\t\t\t\t\t\t\tmechanismInfo->auxInfoLength ) ) ||\n\t\t\t( !( keymgmtACL->pwUseFlags & accessType ) && \\\n\t\t\t  mechanismInfo->auxInfo == NULL && \\\n\t\t\t  mechanismInfo->auxInfoLength == 0 ) );\n\tassert( !( mechanismInfo->flags & KEYMGMT_FLAG_LABEL_ONLY ) || \\\n\t\t\tisReadPtrDynamic( mechanismInfo->auxInfo, \\\n\t\t\t\t\t\t\t  mechanismInfo->auxInfoLength ) );\n\n\tREQUIRES( ( ( keymgmtACL->idUseFlags & accessType ) && \\\n\t\t\t\tmechanismInfo->keyIDtype != CRYPT_KEYID_NONE && \\\n\t\t\t\tmechanismInfo->keyID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( mechanismInfo->keyIDlength ) ) ||\n\t\t\t  ( !( keymgmtACL->idUseFlags & accessType ) && \\\n\t\t\t\tmechanismInfo->keyIDtype == CRYPT_KEYID_NONE && \\\n\t\t\t\tmechanismInfo->keyID == NULL && \\\n\t\t\t\tmechanismInfo->keyIDlength == 0 ) );\n\tREQUIRES( ( ( messageValue == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\tmessageValue == KEYMGMT_ITEM_SECRETKEY ) && \\\n\t\t\t\tlocalMessage == MESSAGE_KEY_GETKEY ) ||\n\t\t\t  localMessage == MESSAGE_KEY_GETFIRSTCERT ||\n\t\t\t  localMessage == MESSAGE_KEY_GETNEXTCERT ||\n\t\t\t  ( ( keymgmtACL->pwUseFlags & accessType ) && \\\n\t\t\t\tmechanismInfo->auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( mechanismInfo->auxInfoLength ) ) ||\n\t\t\t  ( !( keymgmtACL->pwUseFlags & accessType ) && \\\n\t\t\t\tmechanismInfo->auxInfo == NULL && \\\n\t\t\t\tmechanismInfo->auxInfoLength == 0 ) );\n\tREQUIRES( !( mechanismInfo->flags & KEYMGMT_FLAG_LABEL_ONLY ) || \\\n\t\t\t  ( mechanismInfo->auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( mechanismInfo->auxInfoLength ) ) );\n\n\t/* Perform message-type-specific checking of parameters */\n\tswitch( localMessage )\n\t\t{\n\t\tcase MESSAGE_KEY_GETKEY:\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_SETKEY:\n\t\t\t/* Make sure that the object being set is valid and its type is\n\t\t\t   appropriate for this key management item (and via previous\n\t\t\t   checks, keyset) type.  Note that this checks for inclusion in\n\t\t\t   the set of valid objects, in particular a public-key context\n\t\t\t   can have almost any type of certificate object attached but\n\t\t\t   will still be regarded as valid since the context meets the\n\t\t\t   check requirements.  More specific object checks are performed\n\t\t\t   further on */\n\t\t\tparamObjectHandle = mechanismInfo->cryptHandle;\n\t\t\tif( !isValidObject( paramObjectHandle ) || \\\n\t\t\t\t!isSameOwningObject( objectHandle, paramObjectHandle ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tsubType = objectST( paramObjectHandle );\n\t\t\tif( !isValidSubtype( keymgmtACL->objSubTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->objSubTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->objSubTypeC, subType ) )\n\t\t\t\t{\n\t\t\t\t/* If we're only allowed to add contexts, this could be a\n\t\t\t\t   cert object with an associated context, in which case\n\t\t\t\t   we look for an associated context and try again */\n\t\t\t\tif( keymgmtACL->objSubTypeA != ST_CTX_PKC )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\tstatus = findTargetType( paramObjectHandle, \n\t\t\t\t\t\t\t\t\t\t &paramObjectHandle,\n\t\t\t\t\t\t\t\t\t\t OBJECT_TYPE_CONTEXT );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\tobjectST( paramObjectHandle ) != ST_CTX_PKC )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\tif( !isInHighState( paramObjectHandle ) && \\\n\t\t\t\t!( subType == ST_CERT_PKIUSER || \\\n\t\t\t\t   subType == ST_CERT_REQ_REV || \\\n\t\t\t\t   messageValue == KEYMGMT_ITEM_KEYMETADATA ) )\n\t\t\t\t{\n\t\t\t\t/* PKI user info and revocation requests aren't signed, and \n\t\t\t\t   key metadata is contained in a dummy context that may not\n\t\t\t\t   be in the high state yet.  Like private key password \n\t\t\t\t   semantics these are a bit too complex to express in the \n\t\t\t\t   ACL so they're hardcoded */\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\n\t\t\t/* If we don't need to perform an specific-object check, we're\n\t\t\t   done */\n\t\t\tsubType = objectST( objectHandle );\n\t\t\tif( !isValidSubtype( keymgmtACL->specificKeysetSubTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->specificKeysetSubTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->specificKeysetSubTypeC, subType ) )\n\t\t\t\tbreak;\n\n\t\t\t/* We need a specific cert type for this keyset, make sure that\n\t\t\t   we've been passed this and not just a generic PKC-equivalent\n\t\t\t   object */\n\t\t\tstatus = findTargetType( mechanismInfo->cryptHandle, \n\t\t\t\t\t\t\t\t\t &paramObjectHandle, \n\t\t\t\t\t\t\t\t\t OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tsubType = objectST( paramObjectHandle );\n\t\t\tif( !isValidSubtype( keymgmtACL->specificObjSubTypeA, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->specificObjSubTypeB, subType ) && \\\n\t\t\t\t!isValidSubtype( keymgmtACL->specificObjSubTypeC, subType ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( !isInHighState( paramObjectHandle ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_DELETEKEY:\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_GETFIRSTCERT:\n\t\t\tbreak;\n\n\t\tcase MESSAGE_KEY_GETNEXTCERT:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Postcondition: The access and parameters are valid and the object\n\t   being passed in is of the correct type if present.  We don't\n\t   explicitly state this since it's just regurgitating the checks\n\t   already performed above */\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckKeysetAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  IN_BUFFER_C( sizeof( MESSAGE_KEYMGMT_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( KEYMGMT_ITEM ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy )\n\t{\n\tUNUSED_ARG( messageDataPtr );\n\n\treturn( CRYPT_ERROR_PERMISSION );\n\t}\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/kernel/mech_acl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMechanism ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMechanism ACLs\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The ACL tables for each mechanism class */\n\nstatic const MECHANISM_ACL mechanismWrapACL[] = {\n\t/* PKCS #1 encrypt */\n\t{ MECHANISM_ENC_PKCS1,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t MAX_PKCENCRYPTED_SIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\t\t/* Ctx containing key */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Wrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* PKCS #1 encrypt using PGP formatting */\n#ifdef USE_PGP\n\t{ MECHANISM_ENC_PKCS1_PGP,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t MAX_PKCENCRYPTED_SIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Ctx containing key */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Wrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PGP */\n\n\t/* PKCS #1 encrypt of raw data */\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MECHANISM_ENC_PKCS1_RAW,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped raw data */\n\t\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_S( MIN_KEYSIZE,\t\t\t\t/* Raw data */\n\t\t\t\t CRYPT_MAX_KEYSIZE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Wrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_SSL && USE_RSA_SUITES */\n\n\t/* OAEP encrypt */\n#ifdef USE_OAEP\n\t{ MECHANISM_ENC_OAEP,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t MAX_PKCENCRYPTED_SIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\t\t/* Ctx containing key */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Wrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_N( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHAng ) } },\n\t\t\t/* The algoID CRYPT_ALGO_SHA2 + 1 (= CRYPT_ALGO_SHAng) is a \n\t\t\t   special-case placeholder for SHA2-512 until its fate/\n\t\t\t   potential future usage becomes a bit clearer */\n#endif /* USE_OAEP */\n\n\t/* CMS key wrap */\n\t{ MECHANISM_ENC_CMS,\n\t  { MKACP_S_OPT( 8 + 8, CRYPT_MAX_KEYSIZE + 16 ),/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\t\t/* Ctx containing key */\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Wrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* PKCS #15 private key wrap */\n#ifdef USE_PKCS15\n\t{ MECHANISM_PRIVATEKEYWRAP,\n\t  { MKACP_S_OPT( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx containing private key */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Wrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PKCS15 */\n\n\t/* PKCS #8 private key wrap */\n#ifdef USE_PKCS12\n\t{ MECHANISM_PRIVATEKEYWRAP_PKCS8,\n\t  { MKACP_S_OPT( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx containing private key */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Wrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PKCS12 */\n\n\t/* Encrypt mechanism family self-test */\n#ifndef CONFIG_NO_SELFTEST\n\t{ MECHANISM_SELFTEST_ENC,\n\t  { MKACP_S_NONE(),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE(),\n\t    MKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* CONFIG_NO_SELFTEST */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\nstatic const MECHANISM_ACL mechanismUnwrapACL[] = {\n\t/* PKCS #1 decrypt */\n\t{ MECHANISM_ENC_PKCS1,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t MAX_PKCENCRYPTED_SIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_LOW_STATE ),\t\t/* Ctx to contain key */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Unwrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* PKCS #1 decrypt using PGP formatting */\n#ifdef USE_PGP\n\t{ MECHANISM_ENC_PKCS1_PGP,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t MAX_PKCENCRYPTED_SIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O_NONE(),\t\t\t\t\t\t/* Placeholder for ctx to contain key */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Unwrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PGP */\n\n\t/* PKCS #1 decrypt of raw data */\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t{ MECHANISM_ENC_PKCS1_RAW,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped raw data */\n\t\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_S( MIN_KEYSIZE,\t\t\t\t/* Raw data */\n\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Unwrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_SSL && USE_RSA_SUITES */\n\n\t/* OAEP decrypt */\n#ifdef USE_OAEP\n\t{ MECHANISM_ENC_OAEP,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Wrapped key */\n\t\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_LOW_STATE ),\t\t/* Ctx to contain key */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Unwrap PKC context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_N( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHAng ) } },\n\t\t\t/* The algoID CRYPT_ALGO_SHA2 + 1 (= CRYPT_ALGO_SHAng) is a \n\t\t\t   special-case placeholder for SHA2-512 until its fate/\n\t\t\t   potential future usage becomes a bit clearer */\n#endif /* USE_OAEP */\n\n\t/* CMS key unwrap */\n\t{ MECHANISM_ENC_CMS,\n\t  { MKACP_S( 8 + 8, CRYPT_MAX_KEYSIZE + 16 ),/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_CONV | ST_CTX_MAC | ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_LOW_STATE ),\t\t/* Ctx to contain key */\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n\n\t/* PKCS #15 private key unwrap */\n#ifdef USE_PKCS15\n\t{ MECHANISM_PRIVATEKEYWRAP,\n\t  { MKACP_S( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx to contain private key */\n\t\t\t\t ACL_FLAG_LOW_STATE ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PKCS15 */\n\n\t/* PKCS #8 private key unwrap */\n#ifdef USE_PKCS12\n\t{ MECHANISM_PRIVATEKEYWRAP_PKCS8,\n\t  { MKACP_S( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx to contain private key */\n\t\t\t\t ACL_FLAG_LOW_STATE ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PKCS12 */\n\n\t/* PGP 2.x private key unwrap */\n#ifdef USE_PGPKEYS\n\t{ MECHANISM_PRIVATEKEYWRAP_PGP2,\n\t  { MKACP_S( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx to contain private key */\n\t\t\t\t ACL_FLAG_LOW_STATE ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PGPKEYS */\n\n\t/* PGP 5.x private key unwrap */\n#ifdef USE_PGPKEYS\n\t{ MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD,\n\t  { MKACP_S( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx to contain private key */\n\t\t\t\t ACL_FLAG_LOW_STATE ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PGPKEYS */\n\n\t/* OpenPGP private key unwrap */\n#ifdef USE_PGPKEYS\n\t{ MECHANISM_PRIVATEKEYWRAP_OPENPGP,\n\t  { MKACP_S( MIN_PRIVATE_KEYSIZE, \\\n\t\t\t\t MAX_PRIVATE_KEYSIZE ),\t\t/* Wrapped key */\n\t\tMKACP_S_NONE(),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Ctx to contain private key */\n\t\t\t\t ACL_FLAG_LOW_STATE ),\n\t\tMKACP_O( ST_CTX_CONV,\t\t\t\t/* Unwrap context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* USE_PGPKEYS */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\nstatic const MECHANISM_ACL mechanismSignACL[] = {\n\t/* PKCS #1 sign */\n\t{ MECHANISM_SIG_PKCS1,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Signature */\n\t\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\t\t\t\t\t\t/* Secondary hash context */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Signing context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ) } },\n\n\t/* SSL sign with dual hashes */\n#ifdef USE_SSL\n\t{ MECHANISM_SIG_SSL,\n\t  { MKACP_S_OPT( MIN_PKCSIZE,\t\t\t/* Signature */\n\t\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Secondary hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Signing context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ) } },\n#endif /* USE_SSL */\n\n\t/* Sign mechanism family self-test */\n#ifndef CONFIG_NO_SELFTEST\n\t{ MECHANISM_SELFTEST_SIG,\n\t  { MKACP_S_NONE(),\n\t\tMKACP_O_NONE(),\n\t    MKACP_O_NONE(),\n\t\tMKACP_O_NONE() } },\n#endif /* CONFIG_NO_SELFTEST */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\nstatic const MECHANISM_ACL mechanismSigCheckACL[] = {\n\t/* PKCS #1 sig check */\n\t{ MECHANISM_SIG_PKCS1,\n\t  { MKACP_S( MIN_PKCSIZE,\t\t\t\t/* Signature */\n\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O_NONE(),\t\t\t\t\t\t/* Secondary hash context */\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Sig.check context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ) } },\n\n\t/* SSL sign with dual hashes */\n#ifdef USE_SSL\n\t{ MECHANISM_SIG_SSL,\n\t  { MKACP_S( MIN_PKCSIZE,\t\t\t\t/* Signature */\n\t\t\t\t CRYPT_MAX_PKCSIZE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CTX_HASH,\t\t\t\t/* Secondary hash context */\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\n\t\tMKACP_O( ST_CTX_PKC,\t\t\t\t/* Sig.check context */\n\t\t\t\t ACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CTX ) } },\n#endif /* USE_SSL */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\nstatic const MECHANISM_ACL mechanismDeriveACL[] = {\n\t/* PBKDF2 / PKCS #5v2 derive */\n\t{ MECHANISM_DERIVE_PBKDF2,\n\t  { MKACP_S( 1, CRYPT_MAX_KEYSIZE ),\t/* Key data */\n\t\tMKACP_S( MIN_NAME_LENGTH, MAX_ATTRIBUTE_SIZE ),/* Keying material */\n\t\tMKACP_N( CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_HMAC_SHAng ),/* Hash algo */\n\t\tMKACP_N( 0, CRYPT_MAX_HASHSIZE ),\t/* Hash parameters */\n\t\tMKACP_S( 4, 512 ),\t\t\t\t\t/* Salt */\n\t\tMKACP_N( 1, MAX_KEYSETUP_ITERATIONS ) } },\t/* Iterations */\n\n\t/* SSL derive */\n#ifdef USE_SSL\n\t{ MECHANISM_DERIVE_SSL,\n\t  { MKACP_S( 48, 512 ),\t\t\t\t\t/* Master secret/key data */\n\t\tMKACP_S( 48, CRYPT_MAX_PKCSIZE ),\t/* Premaster secret/master secret */\n\t\tMKACP_N_FIXED( CRYPT_USE_DEFAULT ),\t/* SSL uses dual hash */\n\t\tMKACP_N( 0, 0 ),\t\t\t\t\t/* Hash parameters */\n\t\tMKACP_S( 64, 64 ),\t\t\t\t\t/* Salt */\n\t\tMKACP_N( 1, 1 ) } },\t\t\t\t/* Iterations */\n#endif /* USE_SSL */\n\n\t/* TLS/TLS 1.2 derive.  The odd lower bounds on the output and salt are \n\t   needed when generating the TLS hashed MAC and (for the salt and \n\t   output) and when generating a master secret from a fixed shared key \n\t   (for the input) */\n#ifdef USE_SSL\n\t{ MECHANISM_DERIVE_TLS,\n\t  { MKACP_S( 12, 512 ),\t\t\t\t\t/* Master secret/key data (usually 48) */\n\t\tMKACP_S( 6, CRYPT_MAX_PKCSIZE ),\t/* Premaster secret/master secret (us'ly 48) */\n\t\tMKACP_N_FIXED( CRYPT_USE_DEFAULT ),\t/* TLS uses dual hash */\n\t\tMKACP_N( 0, 0 ),\t\t\t\t\t/* Hash parameters */\n\t\tMKACP_S( 13, 512 ),\t\t\t\t\t/* Salt (usually 64) */\n\t\tMKACP_N( 1, 1 ) } },\t\t\t\t/* Iterations */\n\t{ MECHANISM_DERIVE_TLS12,\n\t  { MKACP_S( 12, 512 ),\t\t\t\t\t/* Master secret/key data (usually 48) */\n\t\tMKACP_S( 6, CRYPT_MAX_PKCSIZE ),\t/* Premaster secret/master secret (us'ly 48) */\n\t\tMKACP_N( CRYPT_ALGO_SHA2, CRYPT_ALGO_SHAng ),/* Hash algo */\n\t\tMKACP_N( 0, CRYPT_MAX_HASHSIZE ),\t/* Hash parameters */\n\t\tMKACP_S( 13, 512 ),\t\t\t\t\t/* Salt (usually 64) */\n\t\tMKACP_N( 1, 1 ) } },\t\t\t\t/* Iterations */\n#endif /* USE_SSL */\n\n\t/* CMP/Entrust derive */\n#ifdef USE_CMP\n\t{ MECHANISM_DERIVE_CMP,\n\t  { MKACP_S( 20, 20 ),\t\t\t\t\t/* HMAC-SHA key */\n\t\tMKACP_S( 1, 512 ),\t\t\t\t\t/* Key data */\n\t\tMKACP_N( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHA1 ),/* Hash algo */\n\t\tMKACP_N( 0, 0 ),\t\t\t\t\t/* Hash parameters */\n\t\tMKACP_S( 1, 512 ),\t\t\t\t\t/* Salt */\n\t\tMKACP_N( 1, MAX_KEYSETUP_ITERATIONS ) } },\t/* Iterations */\n#endif /* USE_CMP */\n\n\t/* OpenPGP S2K derive.  The MAX_KEYSETUP_HASHSPECIFIER bound on the \n\t   iterations instead of the more usual MAX_KEYSETUP_ITERATIONS is \n\t   because of PGP's strange handling of this value by counting bytes to \n\t   process through the PRF rather than actual PRF iterations */\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ MECHANISM_DERIVE_PGP,\n\t  { MKACP_S( 16, CRYPT_MAX_KEYSIZE ),\t/* Key data */\n\t\tMKACP_S( MIN_NAME_LENGTH, MAX_ATTRIBUTE_SIZE ),/* Keying material */\n\t\tMKACP_N( CRYPT_ALGO_MD5, CRYPT_ALGO_SHA256 ),/* Hash algo */\n\t\tMKACP_N( 0, 0 ),\t\t\t\t\t/* Hash parameters */\n\t\tMKACP_S( 8, 8 ),\t\t\t\t\t/* Salt */\n\t\tMKACP_N( 0, MAX_KEYSETUP_HASHSPECIFIER ) } }, /* Iterations (0 = don't iterate) */\n#endif /* USE_PGP || USE_PGPKEYS */\n\n\t/* PKCS #12 derive */\n#ifdef USE_PKCS12\n\t{ MECHANISM_DERIVE_PKCS12,\n\t  { MKACP_S( 5, CRYPT_MAX_KEYSIZE ),\t/* Key data (5 for RC2-40) */\n\t\tMKACP_S( MIN_NAME_LENGTH, CRYPT_MAX_TEXTSIZE ),/* Keying material */\n\t\tMKACP_N( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHA1 ),/* Hash algo */\n\t\tMKACP_N( 0, 0 ),\t\t\t\t\t/* Hash parameters */\n\t\tMKACP_S( 9, 512 ),\t\t\t\t\t/* Salt (+ ID byte) */\n\t\tMKACP_N( 1, MAX_KEYSETUP_ITERATIONS ) } },\t/* Iterations */\n#endif /* USE_PKCS12 */\n\n\t/* Derive mechanism family self-test */\n#ifndef CONFIG_NO_SELFTEST\n\t{ MECHANISM_SELFTEST_DERIVE,\n\t  { MKACP_S_NONE(),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_N( 0, 0 ),\n\t\tMKACP_N( 0, 0 ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_N( 0, 0 ) } },\n#endif /* CONFIG_NO_SELFTEST */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\nstatic const MECHANISM_ACL mechanismKDFACL[] = {\n\t/* PKCS #5 KDF */\n\t{ MECHANISM_DERIVE_PBKDF2,\n\t  { MKACP_O( ST_CTX_CONV | ST_CTX_MAC, \n\t\t\t\t ACL_FLAG_LOW_STATE ),\t\t/* Key data */\n\t\tMKACP_O( ST_CTX_GENERIC,\n\t\t\t\t ACL_FLAG_HIGH_STATE ),\t\t/* Keying material */\n\t\tMKACP_N( CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_HMAC_SHAng ),/* Hash algo */\n\t\tMKACP_N( 0, CRYPT_MAX_HASHSIZE ),\t/* Hash parameters */\n\t\tMKACP_S( 8, CRYPT_MAX_TEXTSIZE ) } },\t/* Salt */\n\n\t/* KDF mechanism family self-test */\n#ifndef CONFIG_NO_SELFTEST\n\t{ MECHANISM_SELFTEST_KDF,\n\t  { MKACP_O_NONE(),\n\t    MKACP_O_NONE(),\n\t\tMKACP_N( 0, 0 ),\n\t\tMKACP_N( 0, 0 ),\n\t\tMKACP_S_NONE() } },\n#endif /* CONFIG_NO_SELFTEST */\n\n\t/* End-of-ACL marker */\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } },\n\t{ MECHANISM_NONE,\n\t  { MKACP_END() } }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Ensure that a mechanism ACL is consistent */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN mechanismAclConsistent( IN_ARRAY( mechanismAclSize ) \\\n\t\t\t\t\t\t\t\t\t\tconst MECHANISM_ACL *mechanismACLPtr,\n\t\t\t\t\t\t\t\t\t   IN_RANGE( 1, 16 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int mechanismAclSize )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( mechanismACLPtr, \\\n\t\t\t\t\t\t\t  sizeof( MECHANISM_ACL ) * mechanismAclSize ) );\n\n\tREQUIRES_B( mechanismAclSize > 0 && mechanismAclSize <= 16 );\n\n\tLOOP_MED( i = 0, mechanismACLPtr[ i ].type != MECHANISM_NONE && \\\n\t\t\t\t\t i < mechanismAclSize, i++ )\n\t\t{\n\t\tconst MECHANISM_ACL *mechanismACL = &mechanismACLPtr[ i ];\n\t\tconst PARAM_ACL *paramACL = getParamACL( mechanismACL );\n\t\tconst int paramACLSize = getParamACLSize( mechanismACL );\n\t\tBOOLEAN paramACLEmpty = FALSE;\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\t/* Make sure that the mechanism Acl entries are consistent */\n\t\tif( !isEnumRange( mechanismACL->type, MECHANISM ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Check the paramter ACLs within the mechanism ACL */\n\t\tLOOP_SMALL_ALT( j = 0, j < paramACLSize, j++ )\n\t\t\t{\n\t\t\tif( !paramAclConsistent( &paramACL[ j ], paramACLEmpty ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( paramACL[ j ].valueType == PARAM_VALUE_NONE )\n\t\t\t\tparamACLEmpty = TRUE;\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < mechanismAclSize );\n\n\treturn( TRUE );\n\t}\n\n/* Initialise and check the mechanism ACLs */\n\nCHECK_RETVAL \\\nint initMechanismACL( void )\n\t{\n\t/* Perform a consistency check on the various message ACLs */\n\tif( !mechanismAclConsistent( mechanismWrapACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismWrapACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\tif( !mechanismAclConsistent( mechanismUnwrapACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismUnwrapACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\tif( !mechanismAclConsistent( mechanismSignACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismSignACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\tif( !mechanismAclConsistent( mechanismSigCheckACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismSigCheckACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\tif( !mechanismAclConsistent( mechanismDeriveACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismDeriveACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\tif( !mechanismAclConsistent( mechanismKDFACL, \n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismKDFACL, MECHANISM_ACL ) ) )\n\t\treturn( FALSE );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initMechanismACL( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endMechanismACL( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMechanism ACL Check Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions to implement the checks in the mechanism ACL tables */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismWrapAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER_C( sizeof( MECHANISM_WRAP_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_WRAP_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy )\n\t{\n\tconst MECHANISM_WRAP_INFO *mechanismInfo = \\\n\t\t\t\t( MECHANISM_WRAP_INFO * ) messageDataPtr;\n\tconst MECHANISM_ACL *mechanismACL = \\\n\t\t\t\t( ( message & MESSAGE_MASK ) == MESSAGE_DEV_EXPORT ) ? \\\n\t\t\t\tmechanismWrapACL : mechanismUnwrapACL;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst int mechanismAclSize = \\\n\t\t\t\t( ( message & MESSAGE_MASK ) == MESSAGE_DEV_EXPORT ) ? \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismWrapACL, MECHANISM_ACL ) : \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismUnwrapACL, MECHANISM_ACL );\n\tBOOLEAN isRawMechanism;\n\tint contextHandle, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( message == MESSAGE_DEV_EXPORT || \\\n\t\t\t  message == IMESSAGE_DEV_EXPORT || \\\n\t\t\t  message == MESSAGE_DEV_IMPORT || \\\n\t\t\t  message == IMESSAGE_DEV_IMPORT );\n\tREQUIRES( messageValue == MECHANISM_ENC_PKCS1 || \\\n\t\t\t  messageValue == MECHANISM_ENC_PKCS1_PGP || \\\n\t\t\t  messageValue == MECHANISM_ENC_PKCS1_RAW || \\\n\t\t\t  messageValue == MECHANISM_ENC_OAEP || \\\n\t\t\t  messageValue == MECHANISM_ENC_CMS || \\\n\t\t\t  messageValue == MECHANISM_SELFTEST_ENC || \\\n\t\t\t  messageValue == MECHANISM_PRIVATEKEYWRAP || \\\n\t\t\t  messageValue == MECHANISM_PRIVATEKEYWRAP_PKCS8 || \\\n\t\t\t  messageValue == MECHANISM_PRIVATEKEYWRAP_PGP2 || \\\n\t\t\t  messageValue == MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD || \\\n\t\t\t  messageValue == MECHANISM_PRIVATEKEYWRAP_OPENPGP );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, i < mechanismAclSize && \\\n\t\t\t\t\t mechanismACL[ i ].type != messageValue && \\\n\t\t\t\t\t mechanismACL[ i ].type != MECHANISM_NONE, i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < mechanismAclSize );\n\tENSURES( mechanismACL[ i ].type != MECHANISM_NONE );\n\tmechanismACL = &mechanismACL[ i ];\n\tisRawMechanism = \\\n\t\t( paramInfo( mechanismACL, 2 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t  paramInfo( mechanismACL, 2 ).lowRange == CRYPT_UNUSED ) ? \\\n\t\tTRUE : FALSE;\n\n\t/* Inner precondition: We have an ACL for this mechanism, and the non-\n\t   user-supplied parameters (the ones supplied by cryptlib that must\n\t   be OK) are in order */\n\tREQUIRES( mechanismACL->type != MECHANISM_NONE );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 0 ),\n\t\t\t\t\t\t\t\tmechanismInfo->wrappedData,\n\t\t\t\t\t\t\t\tmechanismInfo->wrappedDataLength ) );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 1 ),\n\t\t\t\t\t\t\t    mechanismInfo->keyData,\n\t\t\t\t\t\t\t    mechanismInfo->keyDataLength ) );\n\tREQUIRES( checkParamObject( paramInfo( mechanismACL, 4 ),\n\t\t\t\t\t\t\t    mechanismInfo->auxContext ) );\n\n\t/* If it's a self-test message then there are no parameters present */\n\tif( message == IMESSAGE_DEV_EXPORT && \\\n\t\tmessageValue == MECHANISM_SELFTEST_ENC )\n\t\t{\n\t\tREQUIRES( mechanismInfo->wrappedData == NULL && \\\n\t\t\t\t  mechanismInfo->wrappedDataLength == 0 && \\\n\t\t\t\t  mechanismInfo->keyData == NULL && \\\n\t\t\t\t  mechanismInfo->keyDataLength == 0 && \\\n\t\t\t\t  mechanismInfo->keyContext == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->wrapContext == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->auxContext == CRYPT_UNUSED );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( messageValue != MECHANISM_SELFTEST_ENC );\n\n\t/* Make sure that the user-supplied parameters are in order, part 1: The\n\t   session key is a valid object of the correct type, and there's a key\n\t   loaded/not loaded as appropriate */\n\tif( !isRawMechanism )\n\t\t{\n\t\tif( !fullObjectCheck( mechanismInfo->keyContext, message ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( paramInfo( mechanismACL, 2 ).flags & ACL_FLAG_ROUTE_TO_CTX )\n\t\t\t{\n\t\t\t/* The key being wrapped may be accessed via an object such as a\n\t\t\t   certificate that isn't the required object type, in order to\n\t\t\t   perform the following check on it we have to first find the\n\t\t\t   ultimate target object */\n\t\t\tstatus = findTargetType( mechanismInfo->keyContext,\t\n\t\t\t\t\t\t\t\t\t &contextHandle, OBJECT_TYPE_CONTEXT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\telse\n\t\t\tcontextHandle = mechanismInfo->keyContext;\n\t\tif( !checkParamObject( paramInfo( mechanismACL, 2 ), contextHandle ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\t/* For raw wrap/unwrap mechanisms the data is supplied as string\n\t\t   data.  In theory this would be somewhat risky since it allows\n\t\t   bypassing of object ownership checks, however these mechanisms\n\t\t   are only accessed from deep within cryptlib (e.g. by the SSH and\n\t\t   SSL/TLS session code, which needs to handle protocol-specific\n\t\t   secret data in special ways) so there's no chance for problems\n\t\t   since the contexts it ends up in are cryptlib-internal,\n\t\t   automatically-created ones belonging to the owner of the session\n\t\t   object */\n\t\tREQUIRES( checkParamObject( paramInfo( mechanismACL, 2 ),\n\t\t\t\t\t\t\t\t\tmechanismInfo->keyContext ) );\n\t\t}\n\n\t/* Make sure that the user-supplied parameters are in order, part 2: The\n\t   wrapping key is a valid object of the correct type with a key loaded */\n\tif( !fullObjectCheck( mechanismInfo->wrapContext, message ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tif( paramInfo( mechanismACL, 3 ).flags & ACL_FLAG_ROUTE_TO_CTX )\n\t\t{\n\t\t/* The wrapping key may be accessed via an object such as a\n\t\t   certificate that isn't the required object type, in order to\n\t\t   perform the following check on it we have to first find the\n\t\t   ultimate target object */\n\t\tstatus = findTargetType( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t &contextHandle, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\telse\n\t\tcontextHandle = mechanismInfo->wrapContext;\n\tif( !checkParamObject( paramInfo( mechanismACL, 3 ), contextHandle ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\n\t/* Make sure that the user-supplied parameters are in order, part 3: Any\n\t   auxiliary info needed for the wrapping/unwrapping is OK.  Reporting \n\t   the specific problem with these checks is a bit tricky because they\n\t   apply to parameters coming from deep within cryptlib-internal \n\t   functions that will never been seen by the user, so it doesn't really\n\t   make sense to report a parameter error for a parameter that the user\n\t   doesn't know exists.  The best that we can do is return a bad-data \n\t   error (sol lucet omnibus), since the auxInfo value has been read from \n\t   externally-supplied encoded data */\n\tif( !checkParamNumeric( paramInfo( mechanismACL, 5 ),\n\t\t\t\t\t\t\tmechanismInfo->auxInfo ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Postcondition: The wrapping key and session key are of the appropriate\n\t   type, there are keys loaded/not loaded as appropriate, and the access\n\t   is valid.  We don't explicitly state this since it's just\n\t   regurgitating the checks already performed above */\n\n\t/* Make sure that all of the objects have the same owner */\n\tif( isRawMechanism )\n\t\t{\n\t\tif( !isSameOwningObject( objectHandle, mechanismInfo->wrapContext ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\telse\n\t\t{\n\t\tif( !isSameOwningObject( objectHandle, mechanismInfo->keyContext ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( !isSameOwningObject( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t\t mechanismInfo->wrapContext ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\n\t/* Postcondition: All the objects have the same owner */\n#ifndef __WINCE__\t/* String too long for compiler */\n\tENSURES( ( isRawMechanism && \\\n\t\t\t   isSameOwningObject( objectHandle, mechanismInfo->wrapContext ) ) || \\\n\t\t\t ( !isRawMechanism && \\\n\t\t\t   isSameOwningObject( objectHandle, mechanismInfo->keyContext ) && \\\n\t\t\t   isSameOwningObject( mechanismInfo->keyContext, \\\n\t\t\t\t\t\t\t\t   mechanismInfo->wrapContext ) ) );\n#endif /* !__WINCE__ */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismSignAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER_C( sizeof( MECHANISM_SIGN_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_SIGN_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy )\n\t{\n\tconst MECHANISM_SIGN_INFO *mechanismInfo = \\\n\t\t\t\t( MECHANISM_SIGN_INFO * ) messageDataPtr;\n\tconst MECHANISM_ACL *mechanismACL = \\\n\t\t\t\t( ( message & MESSAGE_MASK ) == MESSAGE_DEV_SIGN ) ? \\\n\t\t\t\tmechanismSignACL : mechanismSigCheckACL;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst int mechanismAclSize = \\\n\t\t\t\t( ( message & MESSAGE_MASK ) == MESSAGE_DEV_SIGN ) ? \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismSignACL, MECHANISM_ACL ) : \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( mechanismSigCheckACL, MECHANISM_ACL );\n\tint contextHandle, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( message == MESSAGE_DEV_SIGN || \\\n\t\t\t  message == IMESSAGE_DEV_SIGN || \\\n\t\t\t  message == MESSAGE_DEV_SIGCHECK || \\\n\t\t\t  message == IMESSAGE_DEV_SIGCHECK );\n\tREQUIRES( messageValue == MECHANISM_SIG_PKCS1 || \\\n\t\t\t  messageValue == MECHANISM_SIG_SSL || \\\n\t\t\t  messageValue == MECHANISM_SELFTEST_SIG );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, i < mechanismAclSize && \\\n\t\t\t\t\t mechanismACL[ i ].type != messageValue && \\\n\t\t\t\t\t mechanismACL[ i ].type != MECHANISM_NONE, i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < mechanismAclSize );\n\tENSURES( mechanismACL[ i ].type != MECHANISM_NONE );\n\tmechanismACL = &mechanismACL[ i ];\n\n\t/* Inner precondition: We have an ACL for this mechanism, and the non-\n\t   user-supplied parameters (the ones supplied by cryptlib that must\n\t   be OK) are in order */\n\tREQUIRES( mechanismACL->type != MECHANISM_NONE );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 0 ),\n\t\t\t\t\t\t\t\tmechanismInfo->signature,\n\t\t\t\t\t\t\t\tmechanismInfo->signatureLength ) );\n\n\t/* If it's a self-test message then there are no parameters present */\n\tif( message == IMESSAGE_DEV_SIGN && \\\n\t\tmessageValue == MECHANISM_SELFTEST_SIG )\n\t\t{\n\t\tREQUIRES( mechanismInfo->signature == NULL && \\\n\t\t\t\t  mechanismInfo->signatureLength == 0 && \\\n\t\t\t\t  mechanismInfo->hashContext == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->hashContext2 == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->signContext == CRYPT_UNUSED );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( messageValue != MECHANISM_SELFTEST_SIG );\n\n\t/* Make sure that the user-supplied parameters are in order, part 1: The\n\t   hash contexts are valid objects of the correct type.  If there's a\n\t   secondary hash context present we report problems with it as a problem\n\t   with the (logical) single hash context */\n\tif( !fullObjectCheck( mechanismInfo->hashContext, message ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( !checkParamObject( paramInfo( mechanismACL, 1 ),\n\t\t\t\t\t\t   mechanismInfo->hashContext ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( !( paramInfo( mechanismACL, 2 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t   paramInfo( mechanismACL, 2 ).lowRange == CRYPT_UNUSED ) && \\\n\t\t!fullObjectCheck( mechanismInfo->hashContext2, message ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( !checkParamObject( paramInfo( mechanismACL, 2 ),\n\t\t\t\t\t\t   mechanismInfo->hashContext2 ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Make sure that the user-supplied parameters are in order, part 2: The\n\t   sig/sig check context is a valid object of the correct type, and\n\t   there's a key loaded */\n\tif( !fullObjectCheck( mechanismInfo->signContext, message ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tif( paramInfo( mechanismACL, 3 ).flags & ACL_FLAG_ROUTE_TO_CTX )\n\t\t{\n\t\t/* The sig.check key may be accessed via an object such as a\n\t\t   certificate that isn't the required object type, in order to\n\t\t   perform the following check on it we have to first find the\n\t\t   ultimate target object */\n\t\tstatus = findTargetType( mechanismInfo->signContext,\n\t\t\t\t\t\t\t\t &contextHandle, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\telse\n\t\tcontextHandle = mechanismInfo->signContext;\n\tif( !checkParamObject( paramInfo( mechanismACL, 3 ), contextHandle ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\n\t/* Postcondition: The hash and sig/sig check contexts are of the\n\t   appropriate type, there's a key loaded in the sig/sig check context,\n\t   and the access is valid.  We don't explicitly state this since it's\n\t   just regurgitating the checks already performed above */\n\n\t/* Make sure that all of the objects have the same owner */\n\tif( !isSameOwningObject( objectHandle, mechanismInfo->hashContext ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( !isSameOwningObject( mechanismInfo->hashContext, \\\n\t\t\t\t\t\t\t mechanismInfo->signContext ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tif( !( paramInfo( mechanismACL, 2 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t   paramInfo( mechanismACL, 2 ).lowRange == CRYPT_UNUSED ) )\n\t\t{\n\t\tif( !isSameOwningObject( objectHandle, mechanismInfo->hashContext2 ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( !isSameOwningObject( mechanismInfo->hashContext, \\\n\t\t\t\t\t\t\t\t mechanismInfo->signContext ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\t}\n\n\t/* Postcondition: All of the objects have the same owner */\n\tENSURES( isSameOwningObject( objectHandle, mechanismInfo->hashContext ) && \\\n\t\t\t isSameOwningObject( mechanismInfo->hashContext, \\\n\t\t\t\t\t\t\t\t mechanismInfo->signContext ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismDeriveAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t   IN_BUFFER_C( sizeof( MECHANISM_DERIVE_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_DERIVE_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\t   IN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MECHANISM_DERIVE_INFO *mechanismInfo = \\\n\t\t\t\t( MECHANISM_DERIVE_INFO * ) messageDataPtr;\n\tconst MECHANISM_ACL *mechanismACL = mechanismDeriveACL;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( message == MESSAGE_DEV_DERIVE || \\\n\t\t\t  message == IMESSAGE_DEV_DERIVE );\n\tREQUIRES( messageValue == MECHANISM_DERIVE_PBKDF2 || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_PKCS12 || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_SSL || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_TLS || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_TLS12 || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_CMP || \\\n\t\t\t  messageValue == MECHANISM_DERIVE_PGP || \\\n\t\t\t  messageValue == MECHANISM_SELFTEST_DERIVE );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, mechanismACL[ i ].type != messageValue && \\\n\t\t\t\t\t mechanismACL[ i ].type != MECHANISM_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( mechanismDeriveACL, MECHANISM_ACL ),\n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( mechanismDeriveACL, MECHANISM_ACL ) );\n\tENSURES( mechanismACL[ i ].type != MECHANISM_NONE );\n\tmechanismACL = &mechanismACL[ i ];\n\n\t/* If it's a self-test message then there are no parameters present */\n\tif( message == IMESSAGE_DEV_DERIVE && \\\n\t\tmessageValue == MECHANISM_SELFTEST_DERIVE )\n\t\t{\n\t\tREQUIRES( mechanismInfo->dataOut == NULL && \\\n\t\t\t\t  mechanismInfo->dataOutLength == 0 && \\\n\t\t\t\t  mechanismInfo->dataIn == NULL && \\\n\t\t\t\t  mechanismInfo->dataInLength == 0 && \\\n\t\t\t\t  mechanismInfo->hashAlgo == CRYPT_ALGO_NONE && \\\n\t\t\t\t  mechanismInfo->salt == NULL && \\\n\t\t\t\t  mechanismInfo->saltLength == 0 && \\\n\t\t\t\t  mechanismInfo->iterations == 0 );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( messageValue != MECHANISM_SELFTEST_DERIVE );\n\n\t/* Inner precondition: We have an ACL for this mechanism, and the non-\n\t   user-supplied parameters (the ones supplied by cryptlib that must\n\t   be OK) are in order */\n\tREQUIRES( mechanismACL->type != MECHANISM_NONE );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 0 ),\n\t\t\t\t\t\t\t    mechanismInfo->dataOut,\n\t\t\t\t\t\t\t    mechanismInfo->dataOutLength ) );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 1 ),\n\t\t\t\t\t\t\t    mechanismInfo->dataIn,\n\t\t\t\t\t\t\t    mechanismInfo->dataInLength ) );\n\tREQUIRES( checkParamNumeric( paramInfo( mechanismACL, 2 ),\n\t\t\t\t\t\t\t\t mechanismInfo->hashAlgo ) );\n\tREQUIRES( checkParamNumeric( paramInfo( mechanismACL, 3 ),\n\t\t\t\t\t\t\t\t mechanismInfo->hashParam ) );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 4 ),\n\t\t\t\t\t\t\t    mechanismInfo->salt,\n\t\t\t\t\t\t\t    mechanismInfo->saltLength ) );\n\tREQUIRES( checkParamNumeric( paramInfo( mechanismACL, 5 ),\n\t\t\t\t\t\t\t\t mechanismInfo->iterations ) );\n\n\t/* This is a pure data-transformation mechanism, there are no objects\n\t   used so there are no further checks to perform */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckMechanismKDFAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MECHANISM_KDF_INFO ) ) \\\n\t\t\t\t\t\t\t\t\t\t\tTYPECAST( MECHANISM_KDF_INFO * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tIN_ENUM( MECHANISM ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy )\n\t{\n\tconst MECHANISM_KDF_INFO *mechanismInfo = \\\n\t\t\t\t( MECHANISM_KDF_INFO * ) messageDataPtr;\n\tconst MECHANISM_ACL *mechanismACL = mechanismKDFACL;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( message == MESSAGE_DEV_KDF || message == IMESSAGE_DEV_KDF );\n\tREQUIRES( messageValue == MECHANISM_DERIVE_PBKDF2 || \\\n\t\t\t  messageValue == MECHANISM_SELFTEST_KDF );\n\n\t/* Find the appropriate ACL for this mechanism */\n\tLOOP_MED( i = 0, mechanismACL[ i ].type != messageValue && \\\n\t\t\t\t\t mechanismACL[ i ].type != MECHANISM_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( mechanismKDFACL, MECHANISM_ACL ),\n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( mechanismKDFACL, MECHANISM_ACL ) );\n\tENSURES( mechanismACL[ i ].type != MECHANISM_NONE );\n\tmechanismACL = &mechanismACL[ i ];\n\n\t/* If it's a self-test message then there are no parameters present */\n\tif( message == IMESSAGE_DEV_KDF && \\\n\t\tmessageValue == MECHANISM_SELFTEST_KDF )\n\t\t{\n\t\tREQUIRES( mechanismInfo->keyContext == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->masterKeyContext == CRYPT_UNUSED && \\\n\t\t\t\t  mechanismInfo->hashAlgo == CRYPT_ALGO_NONE && \\\n\t\t\t\t  mechanismInfo->salt == NULL && \\\n\t\t\t\t  mechanismInfo->saltLength == 0 );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( messageValue != MECHANISM_SELFTEST_KDF );\n\n\t/* Inner precondition: We have an ACL for this mechanism, and the non-\n\t   user-supplied parameters (the ones supplied by cryptlib that must\n\t   be OK) are in order */\n\tREQUIRES( mechanismACL->type != MECHANISM_NONE );\n\tREQUIRES( fullObjectCheck( mechanismInfo->keyContext, message ) );\n\tREQUIRES( checkParamObject( paramInfo( mechanismACL, 0 ),\n\t\t\t\t\t\t\t\tmechanismInfo->keyContext ) );\n\tREQUIRES( fullObjectCheck( mechanismInfo->masterKeyContext, message ) );\n\tREQUIRES( checkParamObject( paramInfo( mechanismACL, 1 ),\n\t\t\t\t\t\t\t\tmechanismInfo->masterKeyContext ) );\n\tREQUIRES( checkParamNumeric( paramInfo( mechanismACL, 2 ),\n\t\t\t\t\t\t\t\t mechanismInfo->hashAlgo ) );\n\tREQUIRES( checkParamNumeric( paramInfo( mechanismACL, 3 ),\n\t\t\t\t\t\t\t\t mechanismInfo->hashParam ) );\n\tREQUIRES( checkParamString( paramInfo( mechanismACL, 4 ),\n\t\t\t\t\t\t\t\tmechanismInfo->salt,\n\t\t\t\t\t\t\t\tmechanismInfo->saltLength ) );\n\n\t/* This is a pure data-transformation mechanism, there are no objects\n\t   used so there are no further checks to perform */\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/msg_acl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage ACLs Handlers\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tMessage ACLs\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Compare ACL for compare messages */\n\nstatic const COMPARE_ACL compareACLTbl[] = {\n\t/* Hash/MAC value */\n\t{ MESSAGE_COMPARE_HASH,\n\t  MK_CMPACL_S( ST_CTX_HASH | ST_CTX_MAC,\n\t\t\t\t   MIN_HASHSIZE, CRYPT_MAX_HASHSIZE ) },\n\n\t/* ICV value */\n\t{ MESSAGE_COMPARE_ICV,\n\t  MK_CMPACL_S( ST_CTX_CONV,\n\t\t\t\t   12, CRYPT_MAX_HASHSIZE ) },\n\n\t/* PKC keyID */\n\t{ MESSAGE_COMPARE_KEYID,\n\t  MK_CMPACL_S( ST_CTX_PKC,\n\t\t\t\t   MIN_ID_LENGTH, 128 ) },\n\n\t/* PGP keyID */\n\t{ MESSAGE_COMPARE_KEYID_PGP,\n\t  MK_CMPACL_S( ST_CTX_PKC,\n\t\t\t\t   PGP_KEYID_SIZE, PGP_KEYID_SIZE ) },\n\n\t/* OpenPGP keyID */\n\t{ MESSAGE_COMPARE_KEYID_OPENPGP,\n\t  MK_CMPACL_S( ST_CTX_PKC,\n\t\t\t\t   PGP_KEYID_SIZE, PGP_KEYID_SIZE ) },\n\n\t/* X.509 subject DN */\n\t{ MESSAGE_COMPARE_SUBJECT,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   MIN_ID_LENGTH, MAX_ATTRIBUTE_SIZE ) },\n\n\t/* PKCS #7 issuerAndSerialNumber */\n\t{ MESSAGE_COMPARE_ISSUERANDSERIALNUMBER,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   MIN_ID_LENGTH, MAX_ATTRIBUTE_SIZE ) },\n\n\t/* SubjectKeyIdentifier */\n\t{ MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   MIN_ID_LENGTH, MAX_ATTRIBUTE_SIZE ) },\n\n\t/* Certificate fingerprint for various hash algorithms */\n\t{ MESSAGE_COMPARE_FINGERPRINT_SHA1,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   20, 20 ) },\n\t{ MESSAGE_COMPARE_FINGERPRINT_SHA2,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   32, 32 ) },\n\t{ MESSAGE_COMPARE_FINGERPRINT_SHAng,\n\t  MK_CMPACL_S( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   32, 32 ) },\n\n\t/* Certificate object */\n\t{ MESSAGE_COMPARE_CERTOBJ,\n\t  MK_CMPACL_O( MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ),\n\t\t\t\t   MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_ATTRCERT | ST_CERT_CERTCHAIN ) ) },\n\n\t/* End-of-ACL marker */\n\t{ MESSAGE_COMPARE_NONE,\n\t  MK_CMPACL_END() },\n\t{ MESSAGE_COMPARE_NONE,\n\t  MK_CMPACL_END() }\n\t};\n\n/* Check ACL for check messages */\n\n#define PUBKEY_CERT_OBJECT\t\t( ST_CERT_CERT | ST_CERT_ATTRCERT | \\\n\t\t\t\t\t\t\t\t  ST_CERT_CERTCHAIN | \\\n\t\t\t\t\t\t\t\t  MKTYPE_CERTREQ( ST_CERT_CERTREQ | ST_CERT_REQ_CERT ) )\n#define PUBKEY_KEYSET_OBJECT\t( ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | \\\n\t\t\t\t\t\t\t\t  ST_KEYSET_FILE_RO | \\\n\t\t\t\t\t\t\t\t  MKTYPE_DBMS( ST_KEYSET_DBMS | ST_KEYSET_DBMS_STORE ) | \\\n\t\t\t\t\t\t\t\t  MKTYPE_HTTP( ST_KEYSET_HTTP ) | \\\n\t\t\t\t\t\t\t\t  MKTYPE_LDAP( ST_KEYSET_LDAP ) | \\\n\t\t\t\t\t\t\t\t  MKTYPE_PKCS11( ST_DEV_P11 ) | \\\n\t\t\t\t\t\t\t\t  MKTYPE_CAPI( ST_DEV_CAPI ) | ST_DEV_HW )\n#define PRIVKEY_KEYSET_OBJECT\t( ST_KEYSET_FILE | ST_KEYSET_FILE_PARTIAL | \\\n\t\t\t\t\t\t\t\t  ST_KEYSET_FILE_RO | MKTYPE_PKCS11( ST_DEV_P11 ) | \\\n\t\t\t\t\t\t\t\t  MKTYPE_CAPI( ST_DEV_CAPI ) | ST_DEV_HW )\n\nstatic const CHECK_ACL checkACLTbl[] = {\n\t/* PKC actions.  These get somewhat complex to check because the primary\n\t   message target may be a context or certificate object with an \n\t   associated public key so we have to allow both object types */\n\t{ MESSAGE_CHECK_PKC,\t\t\t/* Public or private key context */\n\t  MK_CHKACL( MESSAGE_NONE,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_PRIVATE,\t/* Private key context */\n\t  MK_CHKACL( MESSAGE_NONE,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ) ) },\n\n\t{ MESSAGE_CHECK_PKC_ENCRYPT,\t/* Public encryption context */\n\t  MK_CHKACL( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_DECRYPT,\t/* Private decryption context */\n\t  MK_CHKACL( MESSAGE_CTX_DECRYPT,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGCHECK,\t/* Public signature check context */\n\t  MK_CHKACL( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGN,\t\t/* Private signature context */\n\t  MK_CHKACL( MESSAGE_CTX_SIGN,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_KA_EXPORT,\t/* Key agreement - export context */\n\t  MK_CHKACL( MESSAGE_NONE,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_KA_IMPORT,\t/* Key agreement - import context */\n\t  MK_CHKACL( MESSAGE_NONE,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t/* Conventional encryption/hash/MAC actions */\n\t{ MESSAGE_CHECK_CRYPT,\t\t\t/* Conventional encryption capability */\n\t  MK_CHKACL( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t ST_CTX_CONV ) },\n\n\t{ MESSAGE_CHECK_HASH,\t\t\t/* Hash capability */\n\t  MK_CHKACL( MESSAGE_CTX_HASH,\n\t\t\t\t ST_CTX_HASH ) },\n\n\t{ MESSAGE_CHECK_MAC,\t\t\t/* MAC capability */\n\t  MK_CHKACL( MESSAGE_CTX_HASH,\n\t\t\t\t ST_CTX_MAC ) },\n\n\t/* Checks that an object is ready to be initialised to perform this\n\t   operation */\n\t{ MESSAGE_CHECK_CRYPT_READY,\t/* Ready for init for conv.encr.*/\n\t  MK_CHKACL_EX( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\tST_CTX_CONV, ST_NONE, ACL_FLAG_LOW_STATE ) },\n\n\t{ MESSAGE_CHECK_MAC_READY,\t\t/* Ready for init for MAC */\n\t  MK_CHKACL_EX( MESSAGE_CTX_HASH,\n\t\t\t\t\tST_CTX_MAC, ST_NONE, ACL_FLAG_LOW_STATE ) },\n\n\t{ MESSAGE_CHECK_KEYGEN_READY,\t/* Ready for init key generation */\n\t  MK_CHKACL_EX( MESSAGE_CTX_GENKEY,\n\t\t\t\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ST_NONE, ACL_FLAG_LOW_STATE ) },\n\n\t/* Checks on purely passive container objects that constrain action\n\t   objects (for example a certificate being attached to a context) for \n\t   which the state isn't important in this instance.  Usually we check \n\t   to make sure that the certificate is in the high state, but when a \n\t   certificate is being created/imported it may not be in the high state \n\t   yet at the time the check is being carried out.\n\n\t   In addition to certificates the message can be sent to a keyset to \n\t   check whether it contains keys capable of performing the required \n\t   action */\n\t{ MESSAGE_CHECK_PKC_ENCRYPT_AVAIL,\t/* Encryption available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PUBKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_DECRYPT_AVAIL,\t/* Decryption available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_DECRYPT,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PRIVKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGCHECK_AVAIL,\t/* Signature check available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PUBKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGN_AVAIL,\t\t/* Signature available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_SIGN,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PRIVKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL,/* Key agreement - export available */\n\t  MK_CHKACL_EX( MESSAGE_NONE,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), ST_NONE, ACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL,/* Key agreement - import available */\n\t  MK_CHKACL_EX( MESSAGE_NONE,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), ST_NONE, ACL_FLAG_ANY_STATE ) },\n\n\t/* Special-case versions of the above that check for the ability to \n\t   sign/sigcheck certificate-shaped data rather than general data.  See \n\t   the long comment in cryptkrn.h for more on this.\n\t   \n\t   Technically the _AVAIL variants should also apply the checkCAACLTbl, \n\t   but these variants are only used for kernel-internal checks of \n\t   context capabilities so we don't care whether there's a CA \n\t   certificate attached or not */\n\t{ MESSAGE_CHECK_PKC_SIGCHECK_CA,\t/* Public signature check context */\n\t  MK_CHKACL( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGN_CA,\t\t/* Private signature context */\n\t  MK_CHKACL( MESSAGE_CTX_SIGN,\n\t\t\t\t ST_CTX_PKC | MKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ) ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGCHECK_CA_AVAIL,/* Signature check available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PUBKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t{ MESSAGE_CHECK_PKC_SIGN_CA_AVAIL,\t/* Signature available */\n\t  MK_CHKACL_EX( MESSAGE_CTX_SIGN,\n\t\t\t\t\tMKTYPE_CERTIFICATES( PUBKEY_CERT_OBJECT ), PRIVKEY_KEYSET_OBJECT,\n\t\t\t\t\tACL_FLAG_ANY_STATE ) },\n\n\t/* Misc.actions.  The certificate check is used to verify that a \n\t   certificate is generally valid (for example not expired) without \n\t   having to performing a full signature verification up to a trusted \n\t   root, this is used to verify certificates passed in as parameters \n\t   (for example server certificates) to ensure that the client doesn't \n\t   get invalid data back when it tries to connect to the server.  \n\t   Because the certificate could be used for either signing or \n\t   encryption we don't perform any additional context-based checks but\n\t   just perform a check of the certificate object */\n\t{ MESSAGE_CHECK_CERT,\t\t\t/* Generic certificate check */\n\t  MK_CHKACL( MESSAGE_NONE, \n\t\t\t\t ST_CTX_PKC | ST_CERT_CERT | ST_CERT_CERTCHAIN ) },\n\n\t/* End-of-ACL marker */\n\t{ MESSAGE_CHECK_NONE,\n\t  MK_CHKACL_END() },\n\t{ MESSAGE_CHECK_NONE,\n\t  MK_CHKACL_END() }\n\t};\n\n/* When we export a certificate the easiest way to handle the export check \n   is via a pseudo-ACL that's checked via the standard attribute ACL-\n   checking function.  The following ACL handles certificate exports */\n\nstatic const ATTRIBUTE_ACL_ALT formatPseudoACL[] = {\n\t/* Encoded certificate data */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_CERTIFICATE,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_ANY_CERT | ST_CERT_ATTRCERT ) | \\\n\t\t\tST_CERT_CRL | \\\n\t\t\tST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* Encoded certificate chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_CERTCHAIN,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* Base64-encoded certificate */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_TEXT_CERTIFICATE,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_ANY_CERT | ST_CERT_ATTRCERT ) | \\\n\t\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* Base64-encoded certificate chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_TEXT_CERTCHAIN,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* XML-encoded certificate */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_XML_CERTIFICATE,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_ANY_CERT | ST_CERT_ATTRCERT ) | \\\n\t\t\tST_CERT_CRL, ST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* XML-encoded certificate chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_XML_CERTCHAIN,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* SET OF certificate in chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_ICERTFORMAT_CERTSET,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_INT_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\n\t/* SEQUENCE OF certificate in chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_ICERTFORMAT_CERTSEQUENCE,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_INT_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\n\t/* SSL certificate chain */\n\tMKACL_S_ALT(\n\t\tCRYPT_ICERTFORMAT_SSL_CERTCHAIN,\n\t\tMKTYPE_CERTIFICATES( ST_CERT_CERT | ST_CERT_CERTCHAIN ), \n\t\t\tST_NONE, ST_NONE, \n\t\tACCESS_INT_Rxx_xxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 16, 8192 ) ),\n\n\t/* Encoded non-signed object data.  We allow this attribute to be read\n\t   for objects in the high as well as the low state even though in\n\t   theory it's only present for low (non-signed) objects because the\n\t   object can be in the high state if it was imported from its external\n\t   encoded form */\n\tMKACL_S_ALT(\n\t\tCRYPT_ICERTFORMAT_DATA,\n\t\tST_CERT_CMSATTR | ST_CERT_REQ_REV | ST_CERT_RTCS_REQ | \\\n\t\t\tST_CERT_RTCS_RESP | ST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP | \\\n\t\t\tST_CERT_PKIUSER, ST_NONE, ST_NONE, \n\t\tACCESS_INT_Rxx_Rxx,\n\t\tROUTE( OBJECT_TYPE_CERTIFICATE ), RANGE( 64, 8192 ) ),\n\n\t/* End-of-ACL marker */\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_NONE, ST_NONE, ST_NONE, ST_NONE, \n\t\tACCESS_xxx_xxx,\n\t\tROUTE( OBJECT_TYPE_NONE ), RANGE( 0, 0 ) ),\n\tMKACL_S_ALT(\n\t\tCRYPT_CERTFORMAT_NONE, ST_NONE, ST_NONE, ST_NONE, \n\t\tACCESS_xxx_xxx,\n\t\tROUTE( OBJECT_TYPE_NONE ), RANGE( 0, 0 ) )\n\t};\n\n/* Create-object ACLs */\n\nstatic const CREATE_ACL deviceSpecialACL[] = {\n\t/* PKCS #11 and CryptoAPI devices must include a device name */\n\t{ OBJECT_TYPE_DEVICE,\n\t  { MKACP_N( CRYPT_DEVICE_PKCS11, CRYPT_DEVICE_CRYPTOAPI ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S( MIN_NAME_LENGTH,\n\t\t\t\t CRYPT_MAX_TEXTSIZE ),\t\t/* Device name */\n\t\tMKACP_S_NONE() } },\n\n\t/* End-of-ACL marker */\n\t{ OBJECT_TYPE_NONE, { { 0 } } },\n\t{ OBJECT_TYPE_NONE, { { 0 } } }\n\t};\nstatic const CREATE_ACL createObjectACL[] = {\n\t/* Context object */\n\t{ OBJECT_TYPE_CONTEXT,\n\t  { MKACP_N( CRYPT_ALGO_NONE + 1, CRYPT_ALGO_LAST - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_S_NONE() } },\n\n\t/* Keyset object */\n#ifdef USE_KEYSETS\n\t{ OBJECT_TYPE_KEYSET,\n\t  { MKACP_N( CRYPT_KEYSET_NONE + 1, CRYPT_KEYSET_LAST - 1 ),\n\t\tMKACP_N( CRYPT_KEYOPT_NONE, \n\t\t\t\t CRYPT_KEYOPT_LAST - 1 ),\t/* Keyset options (may be _NONE) */\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S( MIN_NAME_LENGTH, \n\t\t\t\t MAX_ATTRIBUTE_SIZE - 1 ),\t/* Keyset name */\n\t\tMKACP_S_NONE() } },\n#endif /* USE_KEYSETS */\n\n\t/* Envelope object */\n#ifdef USE_ENVELOPES\n\t{ OBJECT_TYPE_ENVELOPE,\n\t  { MKACP_N( CRYPT_FORMAT_NONE + 1, CRYPT_FORMAT_LAST_EXTERNAL - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_S_NONE() } },\n#endif /* USE_ENVELOPES */\n\n\t/* Certificate object */\n#if defined( USE_CERTIFICATES ) || defined( USE_PSEUDOCERTIFICATES )\n\t{ OBJECT_TYPE_CERTIFICATE,\n\t  { MKACP_N( CRYPT_CERTTYPE_NONE + 1, CRYPT_CERTTYPE_LAST - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_S_NONE() } },\n#endif /* USE_CERTIFICATES || USE_PSEUDOCERTIFICATES */\n\n\t/* Device object */\n\t{ OBJECT_TYPE_DEVICE,\n\t  { MKACP_N( CRYPT_DEVICE_NONE + 1, CRYPT_DEVICE_LAST - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S_NONE(),\t\t\t\t\t\t/* See exception list */\n\t\tMKACP_S_NONE() }, \n\t  /* Exceptions: PKCS #11 and CryptoAPI devices have the device name as\n\t     the first string parameter */\n\t  { CRYPT_DEVICE_PKCS11, CRYPT_DEVICE_CRYPTOAPI }, deviceSpecialACL },\n\n\t/* Session object */\n#ifdef USE_SESSIONS\n\t{ OBJECT_TYPE_SESSION,\n\t  { MKACP_N( CRYPT_SESSION_NONE + 1, CRYPT_SESSION_LAST - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S_NONE(),\n\t\tMKACP_S_NONE() } },\n#endif /* USE_SESSIONS */\n\n\t/* User object */\n\t{ OBJECT_TYPE_USER,\n\t  { MKACP_N( CRYPT_USER_NONE + 1, CRYPT_USER_LAST - 1 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S( MIN_NAME_LENGTH, \n\t\t\t\t CRYPT_MAX_TEXTSIZE ),\t\t/* User name */\n\t\tMKACP_S( MIN_NAME_LENGTH, \n\t\t\t\t CRYPT_MAX_TEXTSIZE ) } },\t/* User password */\n\n\t/* End-of-ACL marker */\n\t{ OBJECT_TYPE_NONE, { { 0 } } },\n\t{ OBJECT_TYPE_NONE, { { 0 } } }\n\t};\n\n/* Create-object-indirect ACLs */\n\nstatic const CREATE_ACL certSpecialACL[] = {\n\t/* Certificates can be created as data-only certificates.  The ACL used\n\t   here isn't strictly accurate since we should only allow either \n\t   KEYMGMT_FLAG_NONE or KEYMGMT_FLAG_DATAONLY_CERT and/or\n\t   KEYMGMT_FLAG_CERT_AS_CERTCHAIN, but there's no easy way to do this \n\t   using the existing ACL structure */\n\t{ OBJECT_TYPE_CERTIFICATE,\n\t  { MKACP_N_FIXED( CRYPT_CERTTYPE_CERTIFICATE ),/* Cert.type hint */\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N( KEYMGMT_FLAG_NONE, ( KEYMGMT_FLAG_DATAONLY_CERT | \\\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_CERT_AS_CERTCHAIN ) ),\n\t\t\t\t\t\t\t\t\t\t/* Creation control flag */\n\t\tMKACP_S( 16, MAX_BUFFER_SIZE - 1 ),\t/* Cert.object data */\n\t\tMKACP_S_NONE() } },\n\n\t/* PKCS #7/CMS certificate chains can include an optional key usage to \n\t   select a specific EE certificate in the case of muddled chains that\n\t   contain multiple EE certificates.  In addition they can contain\n\t   modifiers such as KEYMGMT_FLAG_DATAONLY_CERT and \n\t   KEYMGMT_FLAG_CERT_AS_CERTCHAIN */\n\t{ OBJECT_TYPE_CERTIFICATE,\n\t  { MKACP_N_FIXED( CRYPT_CERTTYPE_CERTCHAIN ),/* Cert.type hint */\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_N( KEYMGMT_FLAG_NONE, KEYMGMT_FLAG_MAX ),\n\t\t\t\t\t\t\t\t\t\t/* EE cert usage hint */\n\t\tMKACP_S( 16, MAX_BUFFER_SIZE - 1 ),\t/* Cert.object data */\n\t\tMKACP_S_NONE() } },\n\n\t/* PKCS #7/CMS unordered certificate collections must include a \n\t   identifier for the leaf certificate in the collection in order to \n\t   allow the certificate-import code to pick and assemble the required \n\t   certificates into a chain */\n\t{ OBJECT_TYPE_CERTIFICATE,\n\t  { MKACP_N_FIXED( CRYPT_ICERTTYPE_CMS_CERTSET ),/* Cert.type hint */\n\t\tMKACP_N( CRYPT_IKEYID_KEYID, \n\t\t\t\t CRYPT_IKEYID_ISSUERANDSERIALNUMBER ),/* Key ID type */\n\t\tMKACP_N_FIXED( 0 ),\n\t\tMKACP_S( 16, MAX_BUFFER_SIZE - 1 ),/* Cert.object data */\n\t\tMKACP_S( 3, MAX_INTLENGTH_SHORT - 1 ) } },/* Key ID */\n\n\t/* End-of-ACL marker */\n\t{ OBJECT_TYPE_NONE, { { 0 } } },\n\t{ OBJECT_TYPE_NONE, { { 0 } } }\n\t};\nstatic const CREATE_ACL createObjectIndirectACL[] = {\n\t/* Certificate object instantiated from encoded data */\n\t{ OBJECT_TYPE_CERTIFICATE,\n\t  { MKACP_N( CRYPT_CERTTYPE_NONE, \n\t\t\t\t CRYPT_CERTTYPE_LAST - 1 ),\t/* Cert.type hint (may be _NONE) */\n\t\tMKACP_N_FIXED( 0 ),\t\t\t\t\t/* See exception list */\n\t\tMKACP_N_FIXED( 0 ),\t\t\t\t\t/* See exception list */\n\t\tMKACP_S( 16, MAX_BUFFER_SIZE - 1 ),\t/* Cert.object data */\n\t\tMKACP_S_NONE() },\t\t\t\t\t/* See exception list */\n\t  /* Exception: CMS certificate-set objects have a key ID type as the \n\t     second integer argument and a key ID as the second string \n\t\t argument */\n\t  { CRYPT_CERTTYPE_CERTIFICATE, CRYPT_CERTTYPE_CERTCHAIN, \n\t\t\tCRYPT_ICERTTYPE_CMS_CERTSET }, certSpecialACL },\n\n\t/* End-of-ACL marker */\n\t{ OBJECT_TYPE_NONE, { { 0 } } },\n\t{ OBJECT_TYPE_NONE, { { 0 } } }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a numeric value falls within a range */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkNumericRange( const int value, const int lowRange,\n\t\t\t\t\t\t\t\t  const int highRange )\n\t{\n\t/* Precondition: The range values are either both negative or both\n\t   positive.  This is needed for the range comparison to work */\n\tREQUIRES_B( ( lowRange < 0 && highRange < 0 ) || \\\n\t\t\t\t( lowRange >= 0 && highRange >= 0 && \\\n\t\t\t\t  lowRange <= highRange ) );\n\n\t/* Check whether the value is within the allowed range.  Since some\n\t   values can be negative (e.g. cursor movement codes) we have to\n\t   reverse the range check for negative values */\n\tif( lowRange >= 0 )\n\t\t{\n\t\t/* Positive, it's a standard comparison */\n\t\tif( value >= lowRange && value <= highRange )\n\t\t\treturn( TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES_B( highRange <= lowRange );\n\n\t\t/* Negative, reverse the comparison */\n\t\tif( value >= highRange && value <= lowRange )\n\t\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\n/* Check whether a numeric value falls within a special-case range type */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic BOOLEAN checkAttributeRangeSpecial( IN_ENUM( RANGEVAL ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst RANGEVAL_TYPE rangeType,\n\t\t\t\t\t\t\t\t\t\t   const void *rangeInfo,\n\t\t\t\t\t\t\t\t\t\t   const int value )\n\t{\n\t/* Precondition: The range checking information is valid */\n\tREQUIRES_B( isEnumRange( rangeType, RANGEVAL ) );\n\tREQUIRES_B( rangeInfo != NULL );\n\n\t/* RANGEVAL_ALLOWEDVALUES contains an int [] of permitted values,\n\t   terminated by CRYPT_ERROR */\n\tif( rangeType == RANGEVAL_ALLOWEDVALUES )\n\t\t{\n\t\tconst int *allowedValuesInfo = rangeInfo;\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_SMALL( i = 0, allowedValuesInfo[ i ] != CRYPT_ERROR, i++ )\n\t\t\t{\n\t\t\tif( value == allowedValuesInfo[ i ] )\n\t\t\t\treturn( TRUE );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* RANGEVAL_SUBRANGES contains a SUBRANGE [] of allowed subranges,\n\t   terminated by { CRYPT_ERROR, CRYPT_ERROR } */\n\tif( rangeType == RANGEVAL_SUBRANGES )\n\t\t{\n\t\tconst RANGE_SUBRANGE_TYPE *allowedValuesInfo = rangeInfo;\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_SMALL( i = 0, allowedValuesInfo[ i ].lowRange != CRYPT_ERROR, i++ )\n\t\t\t{\n\t\t\tif( checkNumericRange( value, allowedValuesInfo[ i ].lowRange,\n\t\t\t\t\t\t\t\t   allowedValuesInfo[ i ].highRange ) )\n\t\t\t\treturn( TRUE );\n\t\t\t}\n\t\tENSURES_B( LOOP_BOUND_OK );\n\t\treturn( FALSE );\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n\n/* Check whether a string value falls within the given limits, with special\n   handling for widechar strings.  This sort of thing really shouldn't be\n   in the kernel, but not having it here makes correct string length range\n   checking difficult */\n\n#ifdef USE_WIDECHARS\n\nCHECK_RETVAL_RANGE( 0, INT_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getWideChar( const BYTE *string )\n\t{\n\tlong value = 0;\n\tint i, LOOP_ITERATOR;\n\n#ifdef DATA_LITTLEENDIAN\n\tint shiftAmount = 0;\n\n\t/* Read a widechar value from a byte string */\n\tLOOP_SMALL( i = 0, i < sizeof( wchar_t ), i++ )\n\t\t{\n\t\tvalue |= ( ( long ) ( string[ i ] ) << shiftAmount );\n\t\tshiftAmount += 8;\n\t\t}\n\n#else\n\t/* Read a widechar value from a byte string */\n\tLOOP_SMALL( i = 0, i < sizeof( wchar_t ), i++ )\n\t\tvalue = ( value << 8 ) | string[ i ];\n#endif /* Endianness-specific wchar_t extraction */\n\n\treturn( ( value >= INT_MAX ) ? INT_MAX : ( int ) value );\n\t}\n#endif /* USE_WIDECHARS */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkAttributeRangeWidechar( const void *value,\n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH const int valueLength,\n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int minLength,\n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int maxLength )\n\t{\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( minLength ) );\n\tREQUIRES_B( isShortIntegerRangeNZ( maxLength ) );\n\t\t\t\t/* Also implies ( minLength/maxLength * WCSIZE ) < INT_MAX */\n\tREQUIRES_B( minLength <= maxLength );\n\n#ifdef USE_WIDECHARS\n\t/* If it's not a multiple of wchar_t in size or smaller than a\n\t   wchar_t then it can't be a widechar string */\n\tif( ( valueLength % WCSIZE ) || ( valueLength < WCSIZE ) )\n\t\t{\n\t\treturn( ( valueLength < minLength || valueLength > maxLength ) ? \\\n\t\t\t\tFALSE : TRUE );\n\t\t}\n\n\t/* In theory we could also check whether we're being passed a wchar_t-\n\t   aligned string and reject it if it isn't, but this would miss strings\n\t   being pulled out of byte arrays, which the getWideChar() below deals\n\t   with for us */\n#if 0\n\tif( !IS_ALIGNED_OPT( value, WCSIZE ) )\n\t\treturn( TRUE );\n#endif /* 0 */\n\n\t/* If wchar_t is > 16 bits and the bits above 16 are all zero, it's\n\t   definitely a widechar string */\n#if WCHAR_MAX > 0xFFFF\n\tif( getWideChar( value ) < 0xFFFF )\n\t\t{\n\t\treturn( ( valueLength < ( minLength * WCSIZE ) || \\\n\t\t\t\t  valueLength > ( maxLength * WCSIZE ) ) ? \\\n\t\t\t\tFALSE : TRUE );\n\t\t}\n#endif /* wchar_t > 16 bits */\n\n\t/* Now it gets tricky.  The only thing that we can still safely check\n\t   for is something that's been bloated out into widechars from ASCII */\n\tif( ( valueLength > WCSIZE * 2 ) && \\\n\t\tgetWideChar( value ) < 0xFF && \\\n\t\tgetWideChar( ( const BYTE * ) value + WCSIZE ) < 0xFF )\n\t\t{\n\t\treturn( ( valueLength < ( minLength * WCSIZE ) || \\\n\t\t\t\t  valueLength > ( maxLength * WCSIZE ) ) ? \\\n\t\t\t\tFALSE : TRUE );\n\t\t}\n#endif /* USE_WIDECHARS */\n\n\t/* It's not a widechar string or we can't handle these, perform a\n\t   straight range check */\n\treturn( ( valueLength < minLength || valueLength > maxLength ) ? \\\n\t\t\tFALSE : TRUE );\n\t}\n\n/* Check whether a given action is permitted for an object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkActionPermitted( const OBJECT_INFO *objectInfoPtr,\n\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message )\n\t{\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tint requiredLevel, actualLevel;\n\n\tassert( isReadPtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );\n\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tREQUIRES( isValidMessage( localMessage ) );\n\n\t/* Determine the required level for access.  Like protection rings, the\n\t   lower the value, the higher the privilege level.  Level 3 is all-access,\n\t   level 2 is internal-access only, level 1 is no access, and level 0 is\n\t   not-available (e.g. encryption for hash contexts) */\n\trequiredLevel = objectInfoPtr->actionFlags & \\\n\t\t\t\t\tMK_ACTION_PERM( localMessage, ACTION_PERM_MASK );\n\n\t/* Make sure that the action is enabled at the required level */\n\tif( isInternalMessage( message ) )\n\t\t{\n\t\t/* It's an internal message, the minimal permissions will do */\n\t\tactualLevel = MK_ACTION_PERM( localMessage, ACTION_PERM_NONE_EXTERNAL );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an external message, we need full permissions for access */\n\t\tactualLevel = MK_ACTION_PERM( localMessage, ACTION_PERM_ALL );\n\t\t}\n\tif( requiredLevel < actualLevel )\n\t\t{\n\t\t/* The required level is less than the actual level (e.g. level 2\n\t\t   access attempted from level 3), return more detailed information\n\t\t   about the problem */\n\t\treturn( ( ( requiredLevel >> ACTION_PERM_SHIFT( localMessage ) ) == ACTION_PERM_NOTAVAIL ) ? \\\n\t\t\t\tCRYPT_ERROR_NOTAVAIL : CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the appropriate check ACL for a given message type */\n\nCHECK_RETVAL_PTR \\\nstatic const CHECK_ACL *findCheckACL( IN_ENUM( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\t\t\t\tconst int messageValue )\n\t{\n\tconst CHECK_ACL *checkACL = NULL;\n\n\t/* Precondition: It's a valid check message type */\n\tREQUIRES_N( isEnumRange( messageValue, MESSAGE_CHECK ) );\n\n\t/* Find the appropriate ACL for a given check type */\n\tif( messageValue > MESSAGE_CHECK_NONE && \\\n\t\tmessageValue < MESSAGE_CHECK_LAST )\n\t\tcheckACL = &checkACLTbl[ messageValue - 1 ];\n\tENSURES_N( checkACL != NULL );\n\n\t/* Inner precondition: We have the correct ACL */\n\tREQUIRES_N( checkACL->checkType == messageValue );\n\n\t/* Postcondition: There's a valid ACL present */\n\tassert( isReadPtr( checkACL, sizeof( CHECK_ACL ) ) );\n\n\treturn( checkACL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Ensure that a parameter ACL is consistent.  This is also used to check\n   the parameter ACLs in certm_acl.c and mech_acl.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN paramAclConsistent( const PARAM_ACL *paramACL,\n\t\t\t\t\t\t\tconst BOOLEAN mustBeEmpty )\n\t{\n\tassert( isReadPtr( paramACL, sizeof( PARAM_ACL ) ) );\n\n\tREQUIRES_B( mustBeEmpty == TRUE || mustBeEmpty == FALSE );\n\n\t/* If an ACL doesn't use all of its parameter ACL entries then the last \n\t   few will be all-zero, in which case we check that they are indeed \n\t   empty entries (the remaining entries will be checked by the code\n\t   below) */\n\tif( mustBeEmpty && paramACL->valueType != PARAM_VALUE_NONE )\n\t\treturn( FALSE );\n\n\t/* ACL-specific checks */\n\tswitch( paramACL->valueType )\n\t\t{\n\t\tcase PARAM_VALUE_NONE:\n\t\tcase PARAM_VALUE_STRING_NONE:\n\t\t\t/* These attributes all have implicit parameter checks so the \n\t\t\t   ACL contents are identical */\n\t\t\tif( paramACL->lowRange != 0 || \\\n\t\t\t\tparamACL->highRange != 0 || \\\n\t\t\t\tparamACL->subTypeA != ST_NONE || \\\n\t\t\t\tparamACL->subTypeB != ST_NONE || \\\n\t\t\t\tparamACL->subTypeC != ST_NONE || \\\n\t\t\t\tparamACL->flags != ACL_FLAG_NONE )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase PARAM_VALUE_NUMERIC:\n\t\t\tif( paramACL->lowRange < 0 || \\\n\t\t\t\tparamACL->highRange >= MAX_INTLENGTH || \\\n\t\t\t\tparamACL->lowRange > paramACL->highRange )\n\t\t\t\t{\n\t\t\t\t/* There are two special-case numeric ACLs for which both \n\t\t\t\t   ranges can be -ve and that's when the value is set to \n\t\t\t\t   CRYPT_UNUSED or CRYPT_USE_DEFAULT */\n\t\t\t\tif( !( paramACL->lowRange == CRYPT_UNUSED && \\\n\t\t\t\t\t   paramACL->highRange == CRYPT_UNUSED ) && \\\n\t\t\t\t\t!( paramACL->lowRange == CRYPT_USE_DEFAULT && \\\n\t\t\t\t\t   paramACL->highRange == CRYPT_USE_DEFAULT ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( paramACL->subTypeA != ST_NONE || \\\n\t\t\t\tparamACL->subTypeB != ST_NONE || \\\n\t\t\t\tparamACL->subTypeC != ST_NONE || \\\n\t\t\t\tparamACL->flags != ACL_FLAG_NONE )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase PARAM_VALUE_STRING:\n\t\tcase PARAM_VALUE_STRING_OPT:\n\t\t\tif( paramACL->lowRange < 1 || \\\n\t\t\t\tparamACL->highRange >= MAX_INTLENGTH || \\\n\t\t\t\tparamACL->lowRange > paramACL->highRange )\n\t\t\t\treturn( FALSE );\n\t\t\tif( paramACL->subTypeA != ST_NONE || \\\n\t\t\t\tparamACL->subTypeB != ST_NONE || \\\n\t\t\t\tparamACL->subTypeC != ST_NONE || \\\n\t\t\t\tparamACL->flags != ACL_FLAG_NONE )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase PARAM_VALUE_OBJECT:\n\t\t\tif( paramACL->lowRange != 0 || \\\n\t\t\t\tparamACL->highRange != 0 )\n\t\t\t\treturn( FALSE );\n\t\t\tif( ( paramACL->subTypeA & ( SUBTYPE_CLASS_B | SUBTYPE_CLASS_C ) ) || \\\n\t\t\t\tparamACL->subTypeB != ST_NONE || \\\n\t\t\t\tparamACL->subTypeC != ST_NONE )\n\t\t\t\treturn( FALSE );\n\t\t\tif( paramACL->flags & ~ACL_FLAG_MASK )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Ensure that a create-object ACL is consistent */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN createAclConsistent( const CREATE_ACL *createACL,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN doRecurse )\n\t{\n\tconst PARAM_ACL *paramACL = getParamACL( createACL );\n\tconst int paramACLSize = getParamACLSize( createACL );\n\tBOOLEAN paramACLEmpty = FALSE;\n\tint subType1 = createACL->exceptions[ 0 ];\n\tint subType2 = createACL->exceptions[ 1 ];\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( createACL, sizeof( CREATE_ACL ) ) );\n\n\tREQUIRES_B( doRecurse == TRUE || doRecurse == FALSE );\n\n\t/* Check the parameter ACLs within the create ACL */\n\tLOOP_SMALL( i = 0, i < paramACLSize, i++ )\n\t\t{\n\t\tif( !paramAclConsistent( &paramACL[ i ], paramACLEmpty ) )\n\t\t\treturn( FALSE );\n\t\tif( paramACL[ i ].valueType == PARAM_VALUE_NONE )\n\t\t\tparamACLEmpty = TRUE;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* If there are no exceptions present, we're done */\n\tif( createACL->exceptions[ 0 ] == OBJECT_TYPE_NONE && \\\n\t\tcreateACL->exceptions[ 1 ] == OBJECT_TYPE_NONE && \\\n\t\tcreateACL->exceptionACL == NULL )\n\t\treturn( TRUE );\n\n\t/* Make sure that the exception entries are consistent */\n\tif( ( createACL->exceptions[ 0 ] == OBJECT_TYPE_NONE && \\\n\t\t  createACL->exceptions[ 1 ] != OBJECT_TYPE_NONE ) || \\\n\t\tcreateACL->exceptionACL == NULL )\n\t\treturn( FALSE );\n\n\t/* If we're only checking the current ACL level, we're done */\n\tif( !doRecurse )\n\t\treturn( TRUE );\n\n\t/* Check that the exception ACLs are terminated at some point */\n\tstatic_assert( sizeof( createACL->exceptions ) / sizeof( int ) == 4, \\\n\t\t\t\t   \"Exception ACL size inconsistent\" );\n\tif( createACL->exceptions[ 0 ] != OBJECT_TYPE_NONE && \\\n\t\tcreateACL->exceptions[ 1 ] != OBJECT_TYPE_NONE && \\\n\t\tcreateACL->exceptions[ 2 ] != OBJECT_TYPE_NONE && \\\n\t\tcreateACL->exceptions[ 3 ] != OBJECT_TYPE_NONE )\n\t\treturn( FALSE );\n\n\t/* Check the exception ACLs */\n\tLOOP_MED( i = 0, createACL->exceptionACL[ i ].type != OBJECT_TYPE_NONE, i++ )\n\t\t{\n\t\tconst CREATE_ACL *exceptionACL = &createACL->exceptionACL[ i ];\n\n\t\tif( !createAclConsistent( exceptionACL, FALSE ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Make sure that each of the exception entries in the main ACL is\n\t\t   handled in a sub-ACL, and that there are no duplicates */\n\t\tparamACL = getParamACL( exceptionACL );\n\t\tREQUIRES_B( paramACL->valueType == PARAM_VALUE_NUMERIC );\n\t\tif( subType1 >= paramACL->lowRange && \\\n\t\t\tsubType1 <= paramACL->highRange )\n\t\t\t{\n\t\t\tif( subType1 == 0 )\n\t\t\t\treturn( FALSE );\n\t\t\tsubType1 = 0;\n\t\t\t}\n\t\tif( subType2 >= paramACL->lowRange && \\\n\t\t\tsubType2 <= paramACL->highRange )\n\t\t\t{\n\t\t\tif( subType2 == 0 )\n\t\t\t\treturn( FALSE );\n\t\t\tsubType2 = 0;\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( subType1 != 0 || subType2 != 0 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/* Initialise and check the message ACLs */\n\nCHECK_RETVAL \\\nint initMessageACL( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on the compare ACL */\n\tLOOP_MED( i = 0, compareACLTbl[ i ].compareType != MESSAGE_COMPARE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( compareACLTbl, COMPARE_ACL ), i++ )\n\t\t{\n\t\tconst COMPARE_ACL *compareACL = &compareACLTbl[ i ];\n\t\tconst PARAM_ACL *paramACL = getParamACL( compareACL );\n\t\tconst int paramACLSize = getParamACLSize( compareACL );\n\t\tBOOLEAN paramACLEmpty = FALSE;\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\tENSURES( isEnumRange( compareACL->compareType, MESSAGE_COMPARE ) && \\\n\t\t\t\t compareACL->compareType == i + 1 );\n\t\tif( ( compareACL->objectACL.subTypeA & ~( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t  ST_CTX_ANY | ST_CERT_ANY ) ) || \\\n\t\t\tcompareACL->objectACL.subTypeB != ST_NONE || \\\n\t\t\tcompareACL->objectACL.subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Message ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\tENSURES( ( compareACL->objectACL.flags == 0 ) || \\\n\t\t\t\t ( compareACL->objectACL.flags == ACL_FLAG_HIGH_STATE ) );\n\t\tif( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_STRING )\n\t\t\t{\n\t\t\tENSURES( paramInfo( compareACL, 0 ).lowRange >= MIN_ID_LENGTH && \\\n\t\t\t\t\t paramInfo( compareACL, 0 ).lowRange <= \\\n\t\t\t\t\t\tparamInfo( compareACL, 0 ).highRange && \\\n\t\t\t\t\t paramInfo( compareACL, 0 ).highRange <= MAX_ATTRIBUTE_SIZE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tENSURES( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_OBJECT );\n\t\t\tif( ( paramInfo( compareACL, 0 ).subTypeA & ~( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   ST_CERT_ANY ) ) || \\\n\t\t\t\tparamInfo( compareACL, 0 ).subTypeB != ST_NONE || \\\n\t\t\t\tparamInfo( compareACL, 0 ).subTypeC != ST_NONE )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Message ACLs inconsistent\" ));\n\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t/* Check the paramter ACLs within the compare ACL */\n\t\tLOOP_SMALL_ALT( j = 0, j < paramACLSize, j++ )\n\t\t\t{\n\t\t\tif( !paramAclConsistent( &paramACL[ j ], paramACLEmpty ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( paramACL[ j ].valueType == PARAM_VALUE_NONE )\n\t\t\t\tparamACLEmpty = TRUE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( compareACLTbl, COMPARE_ACL ) );\n\n\t/* Perform a consistency check on the check ACL */\n\tLOOP_MED( i = 0, checkACLTbl[ i ].checkType != MESSAGE_CHECK_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( checkACLTbl, CHECK_ACL ), i++ )\n\t\t{\n\t\tconst CHECK_ACL *checkACL = &checkACLTbl[ i ];\n\n\t\tENSURES( isEnumRange( checkACL->checkType, MESSAGE_CHECK ) && \\\n\t\t\t\t checkACL->checkType == i + 1 );\n\t\tENSURES( checkACL->actionType == MESSAGE_NONE || \\\n\t\t\t\t ( checkACL->actionType >= MESSAGE_CTX_ENCRYPT && \\\n\t\t\t\t   checkACL->actionType <= MESSAGE_CRT_SIGCHECK ) );\n\t\tif( ( checkACL->objectACL.subTypeA & \\\n\t\t\t\t\t~( SUBTYPE_CLASS_A | ST_CTX_ANY | ST_CERT_ANY ) ) || \\\n\t\t\t( checkACL->objectACL.subTypeB & \\\n\t\t\t\t\t~( SUBTYPE_CLASS_B | ST_KEYSET_ANY | ST_DEV_ANY ) ) || \\\n\t\t\tcheckACL->objectACL.subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Check ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\tENSURES( !( checkACL->objectACL.flags & ~ACL_FLAG_ANY_STATE ) )\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( checkACLTbl, CHECK_ACL ) );\n\n\t/* Perform a consistency check on the certificate export pseudo-ACL.\n\t   Because this is a pseudo-ACL that uses CRYPT_CERTFORMAT_TYPE instead \n\t   of CRYPT_ATTRIBUTE_TYPE, we compare entries against \n\t   CRYPT_CERTFORMAT_xxx rather than CRYPT_ATTRIBUTE_xxx */\n\tLOOP_MED( i = 0, formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ), \n\t\t\t  i++ )\n\t\t{\n\t\tconst ATTRIBUTE_ACL_ALT *formatACL = &formatPseudoACL[ i ];\n\n\t\tENSURES( isEnumRange( formatACL->attribute, CRYPT_CERTFORMAT ) );\n\t\tif( ( formatACL->subTypeA & ~( SUBTYPE_CLASS_A | ST_CERT_ANY ) ) || \\\n\t\t\tformatACL->subTypeB != ST_NONE || \\\n\t\t\tformatACL->subTypeC != ST_NONE )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate export ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\tif( formatACL->attribute < CRYPT_CERTFORMAT_LAST_EXTERNAL )\n\t\t\t{\n\t\t\tENSURES( formatACL->access == ACCESS_Rxx_xxx );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tENSURES( formatACL->access == ACCESS_INT_Rxx_xxx || \\\n\t\t\t\t\t formatACL->access == ACCESS_INT_Rxx_Rxx );\n\t\t\t}\n\t\tENSURES( formatACL->valueType == ATTRIBUTE_VALUE_STRING && \\\n\t\t\t\t formatACL->lowRange >= 16 && \\\n\t\t\t\t formatACL->lowRange < formatACL->highRange && \\\n\t\t\t\t formatACL->highRange <= 8192 && \\\n\t\t\t\t formatACL->extendedInfo == NULL );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ) );\n\n\t/* Perform a consistency check on the create-object ACL */\n\tLOOP_MED( i = 0, createObjectACL[ i ].type != OBJECT_TYPE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( createObjectACL, CREATE_ACL ),\n\t\t\t  i++ )\n\t\t{\n\t\tconst CREATE_ACL *createACL = &createObjectACL[ i ];\n\n\t\tENSURES( isValidType( createACL->type ) );\n\t\tENSURES( paramInfo( createACL, 0 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t paramInfo( createACL, 1 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t paramInfo( createACL, 2 ).valueType == PARAM_VALUE_NUMERIC && \\\n\t\t\t\t ( paramInfo( createACL, 3 ).valueType == PARAM_VALUE_STRING_NONE || \\\n\t\t\t\t   paramInfo( createACL, 3 ).valueType == PARAM_VALUE_STRING ) && \\\n\t\t\t\t ( paramInfo( createACL, 4 ).valueType == PARAM_VALUE_STRING_NONE || \\\n\t\t\t\t   paramInfo( createACL, 4 ).valueType == PARAM_VALUE_STRING ) );\n\t\tif( createACL->type == OBJECT_TYPE_CONTEXT )\n\t\t\t{\n\t\t\t/* The algorithm values cover a wide range so we perform a \n\t\t\t   separate check for them in order to allow more precise \n\t\t\t   checking for the other object's values */\n\t\t\tENSURES( isEnumRange( paramInfo( createACL, 0 ).lowRange, CRYPT_ALGO ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Perform a composite check for a vaguely sensible value.  \n\t\t\t   CRYPT_CERTTYPE_LAST is the highest possible value for all of \n\t\t\t   the non-context object types */\n\t\t\tENSURES( paramInfo( createACL, 0 ).lowRange > 0 && \\\n\t\t\t\t\t paramInfo( createACL, 0 ).highRange < CRYPT_CERTTYPE_LAST );\n\t\t\t}\n\n\t\t/* Check the parameter ACLs within the create ACL */\n\t\tENSURES( createAclConsistent( createACL, TRUE ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( createObjectACL, CREATE_ACL ) );\n\n\t/* Perform a consistency check on the create-object-indirect ACL */\n\tLOOP_MED( i = 0, createObjectIndirectACL[ i ].type != OBJECT_TYPE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( createObjectIndirectACL, CREATE_ACL ),\n\t\t\t  i++ )\n\t\t{\n\t\tconst CREATE_ACL *createACL = &createObjectIndirectACL[ i ];\n\n\t\tENSURES( isValidType( createACL->type ) );\n\t\tif( paramInfo( createACL, 0 ).valueType != PARAM_VALUE_NUMERIC || \\\n\t\t\tparamInfo( createACL, 1 ).valueType != PARAM_VALUE_NUMERIC || \\\n\t\t\tparamInfo( createACL, 2 ).valueType != PARAM_VALUE_NUMERIC || \\\n\t\t\tparamInfo( createACL, 3 ).valueType != PARAM_VALUE_STRING || \\\n\t\t\t( paramInfo( createACL, 4 ).valueType != PARAM_VALUE_STRING_NONE && \\\n\t\t\t  paramInfo( createACL, 4 ).valueType != PARAM_VALUE_STRING ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Create-object indirect ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\t\tENSURES( paramInfo( createACL, 0 ).lowRange >= 0 && \\\n\t\t\t\t paramInfo( createACL, 0 ).highRange < CRYPT_CERTTYPE_LAST );\n\t\t\t\t/* The low-range may be 0, which indicates that we're using \n\t\t\t\t   automatic format detection */\n\t\tENSURES( paramInfo( createACL, 3 ).lowRange >= 16 && \\\n\t\t\t\t paramInfo( createACL, 3 ).highRange < MAX_INTLENGTH );\n\t\tif( paramInfo( createACL, 1 ).highRange == 0 && \\\n\t\t\tparamInfo( createACL, 2 ).highRange != 0 )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Create-object ACLs inconsistent\" ));\n\t\t\tretIntError();\n\t\t\t}\n\n\t\t/* Check the parameter ACLs within the create ACL */\n\t\tENSURES( createAclConsistent( createACL, TRUE ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( createObjectIndirectACL, CREATE_ACL ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initMessageACL( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endMessageACL( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage Pre-dispatch Handlers\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If it's a destroy object message, adjust the reference counts of any\n   dependent objects and set the object's state to signalled.  We do this\n   before we send the destroy message to the object in order that any\n   further attempts to access it will fail.  This is handled anyway by the\n   message dispatcher, but setting the status to signalled now means that\n   it's rejected immediately rather than being enqueued and then dequeued\n   again once the destroy message has been processed */\n\nCHECK_RETVAL \\\nint preDispatchSignalDependentObjects( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy4 )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tSTDC_UNUSED int status;\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) && \\\n\t\t\t  objectHandle >= NO_SYSTEM_OBJECTS );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* An inability to change the reference counts of the dependent objects \n\t   doesn't affect the object itself so we can't report it as an error, \n\t   however we can at least warn about it in debug mode */\n\tif( isValidObject( objectInfoPtr->dependentObject ) )\n\t\t{\n\t\t/* Velisurmaaja */\n\t\tstatus = decRefCount( objectInfoPtr->dependentObject, 0, NULL, TRUE );\n\t\tassert( cryptStatusOK( status ) );\n\t\tobjectInfoPtr->dependentObject = CRYPT_ERROR;\n\t\t}\n\tSET_FLAG( objectInfoPtr->flags, OBJECT_FLAG_SIGNALLED );\n\n\t/* Postcondition: The object is now in the destroyed state as far as\n\t   other objects are concerned, and the dependent object is disconnected \n\t   from this object */\n\tENSURES( isInvalidObjectState( objectHandle ) );\n\tENSURES( !isValidObject( objectInfoPtr->dependentObject ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* If it's an attribute get/set/delete, check the access conditions for the\n   object and the message parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 5 ) ) \\\nint preDispatchCheckAttributeAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t IN_OPT const void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE const int messageValue,\n\t\t\t\t\t\t\t\t\t IN TYPECAST( ATTRIBUTE_ACL * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *auxInfo )\n\t{\n\tstatic const int accessTypeTbl[ 7 ][ 2 ] = {\n\t\t/* MESSAGE_GETATTRIBUTE */\t\t\t/* MESSAGE_GETATTRIBUTE_S */\n\t\t{ ACCESS_FLAG_R, ACCESS_FLAG_H_R }, { ACCESS_FLAG_R, ACCESS_FLAG_H_R },\n\t\t/* MESSAGE_SETATTRIBUTE */\t\t\t/* MESSAGE_SETATTRIBUTE_S */\n\t\t{ ACCESS_FLAG_W, ACCESS_FLAG_H_W }, { ACCESS_FLAG_W, ACCESS_FLAG_H_W },\n\t\t/* MESSAGE_DELETEATTRIBUTE */\n\t\t{ ACCESS_FLAG_D, ACCESS_FLAG_H_D }, \n\t\t{ ACCESS_FLAG_x, ACCESS_FLAG_x },\n\t\t\t{ ACCESS_FLAG_x, ACCESS_FLAG_x }\n\t\t};\n\tconst ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tconst BOOLEAN isInternalMessage = isInternalMessage( message ) ? \\\n\t\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tconst int subType = objectInfoPtr->subType;\n\tint accessType, status;\n\n\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\tassert( attributeACL->attribute == messageValue );\n\t\t\t/* Only in debug build, see comment in attr_acl.c */\n\n\t/* Preconditions */\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tREQUIRES( isAttributeMessage( localMessage ) );\n\tREQUIRES( isAttribute( messageValue ) || \\\n\t\t\t  isInternalAttribute( messageValue ) );\n\tREQUIRES( localMessage == MESSAGE_DELETEATTRIBUTE || \\\n\t\t\t  messageDataPtr != NULL );\n\tREQUIRES( localMessage - MESSAGE_GETATTRIBUTE >= 0 && \\\n\t\t\t  localMessage - MESSAGE_GETATTRIBUTE < 5 );\n\n\t/* Get the access permission for this message */\n\taccessType = accessTypeTbl[ localMessage - MESSAGE_GETATTRIBUTE ]\\\n\t\t\t\t\t\t\t  [ TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\t   OBJECT_FLAG_HIGH ) ? 1 : 0 ];\n\n\t/* If it's an internal message, use the internal access permssions */\n\tif( isInternalMessage )\n\t\taccessType = MK_ACCESS_INTERNAL( accessType );\n\n\t/* Make sure that the attribute is valid for this object subtype */\n\tif( !isValidSubtype( attributeACL->subTypeA, subType ) && \\\n\t\t!isValidSubtype( attributeACL->subTypeB, subType ) && \\\n\t\t!isValidSubtype( attributeACL->subTypeC, subType ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Make sure that this type of access is valid for this attribute */\n\tif( !( attributeACL->access & accessType ) )\n\t\t{\n\t\t/* If it's an internal-only attribute being accessed through an \n\t\t   external message then it isn't visible to the user so we return \n\t\t   an attribute value error */\n\t\tif( !( attributeACL->access & ACCESS_MASK_EXTERNAL ) && \\\n\t\t\t!isInternalMessage )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t/* It is visible, return a standard permission error */\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Inner precondition: The attribute is valid for this subtype and is \n\t   externally visible or it's an internal message, and this type of \n\t   access is allowed */\n\tREQUIRES( isValidSubtype( attributeACL->subTypeA, subType ) || \\\n\t\t\t  isValidSubtype( attributeACL->subTypeB, subType ) || \\\n\t\t\t  isValidSubtype( attributeACL->subTypeC, subType ) );\n\tREQUIRES( ( attributeACL->access & ACCESS_MASK_EXTERNAL ) || \\\n\t\t\t  isInternalMessage );\n\tREQUIRES( attributeACL->access & accessType );\n\n\t/* If it's a delete attribute message then there's no attribute data \n\t   being communicated, so we can exit now */\n\tif( localMessage == MESSAGE_DELETEATTRIBUTE )\n\t\t{\n\t\tENSURES( messageDataPtr == NULL );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Inner precondition: We're getting or setting the value of an attribute */\n\tREQUIRES( localMessage == MESSAGE_GETATTRIBUTE || \\\n\t\t\t  localMessage == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t  localMessage == MESSAGE_SETATTRIBUTE || \\\n\t\t\t  localMessage == MESSAGE_SETATTRIBUTE_S );\n\n\t/* Safety check for invalid pointers passed from an internal function */\n\tif( attributeACL->valueType != ATTRIBUTE_VALUE_SPECIAL && \\\n\t\t!isReadPtr( messageDataPtr, \\\n\t\t\t\t\t( attributeACL->valueType == ATTRIBUTE_VALUE_STRING || \\\n\t\t\t\t\t  attributeACL->valueType == ATTRIBUTE_VALUE_WCSTRING || \\\n\t\t\t\t\t  attributeACL->valueType == ATTRIBUTE_VALUE_TIME ) ? \\\n\t\t\t\t\t\tsizeof( MESSAGE_DATA ) : sizeof( int ) ) )\n\t\tretIntError();\n\n\t/* Make sure that the attribute type matches the supplied value type.\n\t   We assert the preconditions for internal messages before the general\n\t   check to ensure that we throw an exception rather than just returning\n\t   an error code for internal programming errors */\n\tswitch( attributeACL->valueType )\n\t\t{\n\t\tcase ATTRIBUTE_VALUE_BOOLEAN:\n\t\t\t/* Inner precondition: If it's an internal message then it must \n\t\t\t   be a numeric value */\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t\t\tREQUIRES( !isInternalMessage || \\\n\t\t\t\t\t  localMessage == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t\t  localMessage == MESSAGE_SETATTRIBUTE );\n\n\t\t\t/* Must be a numeric value */\n\t\t\tif( localMessage != MESSAGE_GETATTRIBUTE && \\\n\t\t\t\tlocalMessage != MESSAGE_SETATTRIBUTE )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* If we're sending the data back to the caller, the only thing\n\t\t\t   that we can check is the presence of a writeable output\n\t\t\t   buffer */\n\t\t\tif( localMessage == MESSAGE_GETATTRIBUTE )\n\t\t\t\t{\n\t\t\t\tif( !isWritePtr( ( void * ) messageDataPtr, sizeof( int ) ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase ATTRIBUTE_VALUE_NUMERIC:\n\t\t\t{\n\t\t\tconst int *valuePtr = messageDataPtr;\n\n\t\t\t/* Inner precondition: If it's an internal message then it must \n\t\t\t   be a numeric value */\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t\t\tREQUIRES( !isInternalMessage || \\\n\t\t\t\t\t  localMessage == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t\t  localMessage == MESSAGE_SETATTRIBUTE );\n\n\t\t\t/* Must be a numeric value */\n\t\t\tif( localMessage != MESSAGE_GETATTRIBUTE && \\\n\t\t\t\tlocalMessage != MESSAGE_SETATTRIBUTE )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* If we're sending the data back to the caller, the only thing\n\t\t\t   that we can check is the presence of a writeable output\n\t\t\t   buffer */\n\t\t\tif( localMessage == MESSAGE_GETATTRIBUTE )\n\t\t\t\t{\n\t\t\t\tif( !isWritePtr( ( void * ) messageDataPtr, sizeof( int ) ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Inner precondition: We're sending data to the object */\n\t\t\tREQUIRES( localMessage == MESSAGE_SETATTRIBUTE );\n\n\t\t\t/* If it's a standard range check, make sure that the attribute\n\t\t\t   value is within the allowed range */\n\t\t\tif( !isSpecialRange( attributeACL ) )\n\t\t\t\t{\n\t\t\t\tif( !checkNumericRange( *valuePtr, attributeACL->lowRange,\n\t\t\t\t\t\t\t\t\t\tattributeACL->highRange ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's a special-case range check */\n\t\t\tREQUIRES( isSpecialRange( attributeACL ) );\n\t\t\tswitch( getSpecialRangeType( attributeACL ) )\n\t\t\t\t{\n\t\t\t\tcase RANGEVAL_ANY:\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RANGEVAL_ALLOWEDVALUES:\n\t\t\t\t\tif( !checkAttributeRangeSpecial( RANGEVAL_ALLOWEDVALUES,\n\t\t\t\t\t\t\t\t\t\t\tgetSpecialRangeInfo( attributeACL ),\n\t\t\t\t\t\t\t\t\t\t\t*valuePtr ) )\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase RANGEVAL_SUBRANGES:\n\t\t\t\t\tif( !checkAttributeRangeSpecial( RANGEVAL_SUBRANGES,\n\t\t\t\t\t\t\t\t\t\t\tgetSpecialRangeInfo( attributeACL ),\n\t\t\t\t\t\t\t\t\t\t\t*valuePtr ) )\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ATTRIBUTE_VALUE_OBJECT:\n\t\t\t{\n\t\t\tconst OBJECT_ACL *objectACL = attributeACL->extendedInfo;\n\t\t\tconst int *valuePtr = messageDataPtr;\n\t\t\tint objectParamHandle, objectParamSubType;\n\n\t\t\t/* Inner precondition: If it's an internal message then it must \n\t\t\t   be a numeric value */\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\n\t\t\tREQUIRES( !isInternalMessage || \\\n\t\t\t\t\t  localMessage == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t\t  localMessage == MESSAGE_SETATTRIBUTE );\n\n\t\t\t/* Must be a numeric value */\n\t\t\tif( localMessage != MESSAGE_GETATTRIBUTE && \\\n\t\t\t\tlocalMessage != MESSAGE_SETATTRIBUTE )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* If we're sending the data back to the caller, the only thing\n\t\t\t   that we can check is the presence of a writeable output\n\t\t\t   buffer */\n\t\t\tif( localMessage == MESSAGE_GETATTRIBUTE )\n\t\t\t\t{\n\t\t\t\tif( !isWritePtr( ( void * ) messageDataPtr, sizeof( int ) ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Inner precondition: We're sending data to the object */\n\t\t\tREQUIRES( localMessage == MESSAGE_SETATTRIBUTE );\n\n\t\t\t/* Must contain a valid object handle */\n\t\t\tif( !fullObjectCheck( *valuePtr, message ) || \\\n\t\t\t\t!isSameOwningObject( objectHandle, *valuePtr ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Object must be of the correct type */\n\t\t\tif( objectACL->flags & ACL_FLAG_ROUTE_TO_CTX )\n\t\t\t\t{\n\t\t\t\tstatus = findTargetType( *valuePtr, &objectParamHandle,\n\t\t\t\t\t\t\t\t\t\t OBJECT_TYPE_CONTEXT );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( objectACL->flags & ACL_FLAG_ROUTE_TO_CERT )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = findTargetType( *valuePtr, &objectParamHandle,\n\t\t\t\t\t\t\t\t\t\t\t OBJECT_TYPE_CERTIFICATE );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tobjectParamHandle = *valuePtr;\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tobjectParamSubType = objectTable[ objectParamHandle ].subType;\n\t\t\tif( !isValidSubtype( objectACL->subTypeA, objectParamSubType ) && \\\n\t\t\t\t!isValidSubtype( objectACL->subTypeB, objectParamSubType ) && \\\n\t\t\t\t!isValidSubtype( objectACL->subTypeC, objectParamSubType ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( ( objectACL->flags & ACL_FLAG_STATE_MASK ) && \\\n\t\t\t\t!checkObjectState( objectACL->flags, objectParamHandle ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Postcondition: Object parameter is valid and accessible,\n\t\t\t   object is of the correct type and state */\n\t\t\tENSURES( fullObjectCheck( *valuePtr, message ) && \\\n\t\t\t\t\t isSameOwningObject( objectHandle, *valuePtr ) );\n\t\t\tENSURES( isValidSubtype( objectACL->subTypeA, \\\n\t\t\t\t\t\t\t\t\t objectParamSubType ) || \\\n\t\t\t\t\t isValidSubtype( objectACL->subTypeB, \\\n\t\t\t\t\t\t\t\t\t objectParamSubType ) || \\\n\t\t\t\t\t isValidSubtype( objectACL->subTypeC, \\\n\t\t\t\t\t\t\t\t\t objectParamSubType ) );\n\t\t\tENSURES( !( objectACL->flags & ACL_FLAG_STATE_MASK ) || \\\n\t\t\t\t\t checkObjectState( objectACL->flags, \\\n\t\t\t\t\t\t\t\t\t   objectParamHandle ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ATTRIBUTE_VALUE_STRING:\n\t\tcase ATTRIBUTE_VALUE_WCSTRING:\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = messageDataPtr;\n\n\t\t\t/* Inner precondition: If it's an internal message then it must \n\t\t\t   be a valid string value or a null value if we're obtaining a \n\t\t\t   length.  Polled entropy data can be arbitrarily large so we \n\t\t\t   don't check its length */\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );\n\t\t\tassert( !isInternalMessage || \\\n\t\t\t\t\t( ( localMessage == MESSAGE_GETATTRIBUTE_S && \\\n\t\t\t\t\t\t( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t\t\t  ( isIntegerRangeNZ( msgData->length ) && \\\n\t\t\t\t\t\t\tisWritePtrDynamic( msgData->data, \\\n\t\t\t\t\t\t\t\t\t\t\t   msgData->length ) ) ) ) || \\\n\t\t\t\t\t  ( localMessage == MESSAGE_SETATTRIBUTE_S && \\\n\t\t\t\t\t\tisReadPtrDynamic( msgData->data, msgData->length ) && \\\n\t\t\t\t\t\t( isShortIntegerRangeNZ( msgData->length ) || \\\n\t\t\t\t\t\t  messageValue == CRYPT_IATTRIBUTE_ENTROPY ) ) ) );\n\n\t\t\t/* Note that the assert()/REQUIRES() appears to be duplicated \n\t\t\t   but differs in some minor details, we use isReadPtr() in the \n\t\t\t   debug version with assert() but only a more basic check for \n\t\t\t   NULL in all versions with REQUIRES() */\n\t\t\tREQUIRES( !isInternalMessage || \\\n\t\t\t\t\t  ( ( localMessage == MESSAGE_GETATTRIBUTE_S && \\\n\t\t\t\t\t\t  ( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t\t\t\t( msgData->data != NULL && \\\n\t\t\t\t\t\t\t  isIntegerRangeNZ( msgData->length ) ) ) ) || \\\n\t\t\t\t\t\t( localMessage == MESSAGE_SETATTRIBUTE_S && \\\n\t\t\t\t\t\t  msgData->data != NULL && \\\n\t\t\t\t\t\t  ( isShortIntegerRangeNZ( msgData->length ) || \\\n\t\t\t\t\t\t\tmessageValue == CRYPT_IATTRIBUTE_ENTROPY ) ) ) );\n\n\t\t\t/* Must be a string value */\n\t\t\tif( localMessage != MESSAGE_GETATTRIBUTE_S && \\\n\t\t\t\tlocalMessage != MESSAGE_SETATTRIBUTE_S )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* If we're sending the data back to the caller, the only thing\n\t\t\t   that we can check is the presence of a writeable output\n\t\t\t   buffer.  We return a string arg error for both the buffer and\n\t\t\t   length, since the length isn't explicitly specified by an\n\t\t\t   external caller */\n\t\t\tif( localMessage == MESSAGE_GETATTRIBUTE_S )\n\t\t\t\t{\n\t\t\t\tif( !( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t\t   ( msgData->length > 0 && \\\n\t\t\t\t\t\t isWritePtrDynamic( msgData->data, \\\n\t\t\t\t\t\t\t\t\t\t\tmsgData->length ) ) ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Inner precondition: We're sending data to the object */\n\t\t\tREQUIRES( localMessage == MESSAGE_SETATTRIBUTE_S );\n\n\t\t\t/* Make sure that the string length is within the allowed\n\t\t\t   range */\n\t\t\tif( isSpecialRange( attributeACL ) )\n\t\t\t\t{\n\t\t\t\tif( !checkAttributeRangeSpecial( \\\n\t\t\t\t\t\t\t\t\tgetSpecialRangeType( attributeACL ),\n\t\t\t\t\t\t\t\t\tgetSpecialRangeInfo( attributeACL ),\n\t\t\t\t\t\t\t\t\tmsgData->length ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( attributeACL->valueType == ATTRIBUTE_VALUE_WCSTRING )\n\t\t\t\t\t{\n\t\t\t\t\tif( !checkAttributeRangeWidechar( msgData->data,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  msgData->length,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  attributeACL->lowRange,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  attributeACL->highRange ) )\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( msgData->length < attributeACL->lowRange || \\\n\t\t\t\t\t\tmsgData->length > attributeACL->highRange )\n\t\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tif( msgData->length > 0 && \\\n\t\t\t\t!isReadPtrDynamic( msgData->data, msgData->length ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ATTRIBUTE_VALUE_TIME:\n\t\t\t{\n\t\t\tconst MESSAGE_DATA *msgData = messageDataPtr;\n\t\t\ttime_t theTime;\n\n\t\t\t/* Inner precondition: If it's an internal message then it must \n\t\t\t   be a string value corresponding to a time_t */\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );\n\t\t\tassert( !isInternalMessage || \\\n\t\t\t\t\t( ( localMessage == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t\t\tlocalMessage == MESSAGE_SETATTRIBUTE_S ) && \\\n\t\t\t\t\t  isReadPtrDynamic( msgData->data, msgData->length ) && \\\n\t\t\t\t\t  msgData->length == sizeof( time_t ) ) );\n\n\t\t\tREQUIRES( !isInternalMessage || \\\n\t\t\t\t\t  ( ( localMessage == MESSAGE_GETATTRIBUTE_S || \\\n\t\t\t\t\t\t  localMessage == MESSAGE_SETATTRIBUTE_S ) && \\\n\t\t\t\t\t\tmsgData->data != NULL && \\\n\t\t\t\t\t\tmsgData->length == sizeof( time_t ) ) );\n\n\t\t\t/* Must be a string value */\n\t\t\tif( localMessage != MESSAGE_GETATTRIBUTE_S && \\\n\t\t\t\tlocalMessage != MESSAGE_SETATTRIBUTE_S )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\t/* If we're sending the data back to the caller, the only thing\n\t\t\t   that we can check is the presence of a writeable output\n\t\t\t   buffer.  We return a string arg error for both the buffer and\n\t\t\t   length, since the length isn't explicitly specified by an\n\t\t\t   external caller */\n\t\t\tif( localMessage == MESSAGE_GETATTRIBUTE_S )\n\t\t\t\t{\n\t\t\t\tif( !( ( msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t\t\t   ( msgData->length > 0 && \\\n\t\t\t\t\t\t isWritePtrDynamic( msgData->data, \\\n\t\t\t\t\t\t\t\t\t\t\tmsgData->length ) ) ) )\n\t\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Inner precondition: We're sending data to the object */\n\t\t\tREQUIRES( localMessage == MESSAGE_SETATTRIBUTE_S );\n\n\t\t\t/* Must contain a time_t in a sensible range */\n\t\t\tif( !isReadPtr( msgData->data, sizeof( time_t ) ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\ttheTime = *( ( time_t * ) msgData->data );\n\t\t\tif( theTime <= MIN_TIME_VALUE || theTime >= MAX_TIME_VALUE )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tif( msgData->length != sizeof( time_t ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase ATTRIBUTE_VALUE_SPECIAL:\n\t\t\t{\n\t\t\tint LOOP_ITERATOR;\n\t\t\t\n\t\t\t/* It's an ACL with an object-subtype-specific sub-ACL, find the\n\t\t\t   precise ACL for this object subtype */\n\t\t\tLOOP_MED( attributeACL = getSpecialRangeInfo( attributeACL ),\n\t\t\t\t\t  attributeACL->valueType != ATTRIBUTE_VALUE_NONE,\n\t\t\t\t\t  attributeACL++ )\n\t\t\t\t{\n\t\t\t\tif( isValidSubtype( attributeACL->subTypeA, subType ) || \\\n\t\t\t\t\tisValidSubtype( attributeACL->subTypeB, subType ) || \\\n\t\t\t\t\tisValidSubtype( attributeACL->subTypeC, subType ) )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tENSURES( attributeACL->valueType != ATTRIBUTE_VALUE_NONE );\n\n\t\t\t/* Recursively check the message against the sub-ACL */\n\t\t\treturn( preDispatchCheckAttributeAccess( objectHandle, message,\n\t\t\t\t\t\t\tmessageDataPtr, messageValue, attributeACL ) );\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* It's a compare message, make sure that the parameters are OK */\n\nCHECK_RETVAL \\\nint preDispatchCheckCompareParam( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  const void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_COMPARE ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst COMPARE_ACL *compareACL;\n\n\t/* Precondition: It's a valid compare message type */\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\tREQUIRES( fullObjectCheck( objectHandle, message ) );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_COMPARE ) );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* Find the appropriate ACL for this compare type.  Note that we don't \n\t   range-check the value of messageValue since it's already been checked\n\t   by the REQUIRES() above */\n\tcompareACL = &compareACLTbl[ messageValue - 1 ];\n\n\t/* Inner precondition: We have the correct ACL, and the full object\n\t   check has been performed by the kernel */\n\tREQUIRES( compareACL->compareType == messageValue );\n\n\t/* Check the message target.  The full object check has already been\n\t   performed by the message dispatcher so all we need to check is the\n\t   compare-specific subtype.  We throw an exception if we find an\n\t   invalid parameter, both because this is an internal message and this\n\t   situation shouldn't occur, and because an error return from a compare\n\t   message is perfectly valid (it denotes a non-match) so parameter\n\t   errors won't otherwise be caught by the caller */\n\tENSURES( isValidSubtype( compareACL->objectACL.subTypeA, \\\n\t\t\t\t\t\t\t objectInfoPtr->subType ) );\n\tif( ( compareACL->objectACL.flags & ACL_FLAG_STATE_MASK ) && \\\n\t\t!checkObjectState( compareACL->objectACL.flags, objectHandle ) )\n\t\tretIntError();\n\n\t/* Check the message parameters.  We throw an exception if we find an\n\t   invalid parameter for the reason given above */\n\tif( paramInfo( compareACL, 0 ).valueType == PARAM_VALUE_OBJECT )\n\t\t{\n\t\tconst CRYPT_HANDLE iCryptHandle = *( ( CRYPT_HANDLE * ) messageDataPtr );\n\n\t\tREQUIRES( fullObjectCheck( iCryptHandle, message ) && \\\n\t\t\t\t  isSameOwningObject( objectHandle, iCryptHandle ) );\n\t\tREQUIRES( checkParamObject( paramInfo( compareACL, 0 ), \\\n\t\t\t\t  iCryptHandle ) );\n\t\t}\n\telse\n\t\t{\n\t\tconst MESSAGE_DATA *msgData = messageDataPtr;\n\n\t\tREQUIRES( checkParamString( paramInfo( compareACL, 0 ),\n\t\t\t\t\t\t\t\t\tmsgData->data, msgData->length ) );\n\t\t}\n\n\t/* Postconditions: The compare parameters are valid, either an object\n\t   handle or a string value at least as big as a minimal-length DN */\n\tassert( ( messageValue == MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t  isValidHandle( *( ( CRYPT_HANDLE * ) messageDataPtr ) ) ) || \\\n\t\t\t( messageValue != MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t  isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) && \\\n\t\t\t  ( ( MESSAGE_DATA * ) messageDataPtr )->length >= MIN_ID_LENGTH && \\\n\t\t\t  isReadPtrDynamic( ( ( MESSAGE_DATA * ) messageDataPtr )->data, \\\n\t\t\t\t\t\t\t\t( ( MESSAGE_DATA * ) messageDataPtr )->length ) ) );\n\n\tENSURES( messageDataPtr != NULL );\n\tENSURES( ( messageValue == MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t   isValidHandle( *( ( CRYPT_HANDLE * ) messageDataPtr ) ) ) || \\\n\t\t\t ( messageValue != MESSAGE_COMPARE_CERTOBJ && \\\n\t\t\t   ( ( ( MESSAGE_DATA * ) messageDataPtr )->data != NULL && \\\n\t\t\t\t ( ( MESSAGE_DATA * ) messageDataPtr )->length >= MIN_ID_LENGTH && \\\n\t\t\t\t ( ( MESSAGE_DATA * ) messageDataPtr )->length < MAX_INTLENGTH ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* It's a check message, make sure that the parameters are OK */\n\nCHECK_RETVAL \\\nint preDispatchCheckCheckParam( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_CHECK ) const int messageValue,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst CHECK_ACL *checkACL;\n\tint status;\n\n\t/* Precondition: It's a valid check message type */\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\tREQUIRES( fullObjectCheck( objectHandle, message ) );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_CHECK ) );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* Find the ACL information for the message type */\n\tcheckACL = findCheckACL( messageValue );\n\tENSURES( checkACL != NULL );\n\n\t/* Check the message target.  The full object check has already been\n\t   performed by the message dispatcher so all we need to check is the\n\t   compare-specific subtype */\n\tif( !( isValidSubtype( checkACL->objectACL.subTypeA, \\\n\t\t\t\t\t\t   objectInfoPtr->subType ) || \\\n\t\t   isValidSubtype( checkACL->objectACL.subTypeB, \\\n\t\t\t\t\t\t   objectInfoPtr->subType ) ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\tif( ( checkACL->objectACL.flags & ACL_FLAG_STATE_MASK ) && \\\n\t\t!checkObjectState( checkACL->objectACL.flags, objectHandle ) )\n\t\t{\n\t\t/* The object is in the wrong state, meaning that it's inited when\n\t\t   it shouldn't be or not inited when it should be, return a more\n\t\t   specific error message */\n\t\treturn( isInHighState( objectHandle ) ? \\\n\t\t\t\tCRYPT_ERROR_INITED : CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Make sure that the object's usage count is still valid.  The usage\n\t   count is a type of meta-capability that overrides all other\n\t   capabilities in that an object with an expired usage count isn't\n\t   valid for anything no matter what the available capabilities are */\n\tif( objectInfoPtr->usageCount != CRYPT_UNUSED && \\\n\t\tobjectInfoPtr->usageCount <= 0 )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* If this is a context and there's an action associated with this\n\t   check, make sure that the requested action is permitted for this\n\t   object */\n\tif( objectInfoPtr->type == OBJECT_TYPE_CONTEXT && \\\n\t\tcheckACL->actionType != MESSAGE_NONE )\n\t\t{\n\t\tconst BOOLEAN isInternalMessage = isInternalMessage( message ) ? \\\n\t\t\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\n\t\t/* Check that the action is permitted.  We convert the return status\n\t\t   to a CRYPT_ERROR_NOTAVAIL, which makes more sense than a generic\n\t\t   object error */\n\t\tstatus = checkActionPermitted( objectInfoPtr, isInternalMessage ? \\\n\t\t\t\t\t\t\t\t\t   MKINTERNAL( checkACL->actionType ) : \\\n\t\t\t\t\t\t\t\t\t   checkACL->actionType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* Postconditions: The object being checked is valid */\n\tENSURES( fullObjectCheck( objectHandle, message ) && \\\n\t\t\t ( isValidSubtype( checkACL->objectACL.subTypeA, \\\n\t\t\t\t\t\t\t   objectInfoPtr->subType ) || \\\n\t\t\t   isValidSubtype( checkACL->objectACL.subTypeB, \\\n\t\t\t\t\t\t\t   objectInfoPtr->subType ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* It's a context action message, check the access conditions for the object */\n\nCHECK_RETVAL \\\nint preDispatchCheckActionAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const int dummy2,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy3 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tint status;\n\n\t/* Precondition: It's a valid access */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isActionMessage( localMessage ) );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* If the object is in the low state, it can't be used for any action */\n\tif( !isInHighState( objectHandle ) )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t/* If there's a usage count set for the object and it's gone to zero, it\n\t   can't be used any more */\n\tif( objectInfoPtr->usageCount != CRYPT_UNUSED && \\\n\t\tobjectInfoPtr->usageCount <= 0 )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Inner precondition: Object is in the high state and can process the\n\t   action message */\n\tREQUIRES( isInHighState( objectHandle ) );\n\tREQUIRES( objectInfoPtr->usageCount == CRYPT_UNUSED || \\\n\t\t\t  objectInfoPtr->usageCount > 0 );\n\n\t/* Check that the requested action is permitted for this object */\n\tstatus = checkActionPermitted( objectInfoPtr, message );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Postcondition */\n\tENSURES( localMessage != MESSAGE_CTX_GENKEY );\n\tENSURES( isInHighState( objectHandle ) );\n\tENSURES( objectInfoPtr->usageCount == CRYPT_UNUSED || \\\n\t\t\t objectInfoPtr->usageCount > 0 );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\tcheckActionPermitted( objectInfoPtr, message ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* If it's a state change trigger message, make sure that the object isn't\n   already in the high state */\n\nCHECK_RETVAL \\\nint preDispatchCheckState( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t   STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t   STDC_UNUSED const int dummy2, \n\t\t\t\t\t\t   STDC_UNUSED const void *dummy3 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\n\t/* Precondition: It's a valid access */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidMessage( localMessage ) );\n\n\tif( isInHighState( objectHandle ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* If it's a keygen message, perform a secondary check to ensure that key\n\t   generation is permitted for this object */\n\tif( localMessage == MESSAGE_CTX_GENKEY )\n\t\t{\n\t\tint status;\n\n\t\t/* Check that the requested action is permitted for this object */\n\t\tstatus = checkActionPermitted( &objectTable[ objectHandle ], message );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Postcondition: Object is in the low state so a state change message\n\t   is valid */\n\tENSURES( !isInHighState( objectHandle ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check the access conditions for a message containing an optional handle\n   as the message parameter */\n\nCHECK_RETVAL \\\nint preDispatchCheckParamHandleOpt( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tIN TYPECAST( MESSAGE_ACL * ) const void *auxInfo )\n\t{\n\tconst MESSAGE_ACL *messageACL = ( MESSAGE_ACL * ) auxInfo;\n\tconst OBJECT_ACL *objectACL = &messageACL->objectACL;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint subType;\n\n\tassert( isReadPtr( messageACL, sizeof( MESSAGE_ACL ) ) );\n\n\t/* Preconditions: The access is valid and we've been supplied a valid\n\t   check ACL */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\tREQUIRES( messageACL->type == ( message & MESSAGE_MASK ) );\n\n\t/* If the object parameter is CRYPT_UNUSED (for example for a self-signed\n\t   certificate), we're OK */\n\tif( messageValue == CRYPT_UNUSED )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the object parameter is valid and accessible */\n\tif( !fullObjectCheck( messageValue, message ) || \\\n\t\t!isSameOwningObject( objectHandle, messageValue ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Make sure that the object parameter subtype is correct */\n\tsubType = objectTable[ messageValue ].subType;\n\tif( !isValidSubtype( objectACL->subTypeA, subType ) && \\\n\t\t!isValidSubtype( objectACL->subTypeB, subType ) && \\\n\t\t!isValidSubtype( objectACL->subTypeC, subType ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Postcondition: Object parameter is valid, accessible, and of the\n\t   correct type */\n\tENSURES( fullObjectCheck( messageValue, message ) && \\\n\t\t\t isSameOwningObject( objectHandle, messageValue ) );\n\tENSURES( isValidSubtype( objectACL->subTypeA, subType ) || \\\n\t\t\t isValidSubtype( objectACL->subTypeB, subType ) || \\\n\t\t\t isValidSubtype( objectACL->subTypeC, subType ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a combined check of the object and the handle */\n\nCHECK_RETVAL \\\nint preDispatchCheckStateParamHandle( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\t  const int messageValue,\n\t\t\t\t\t\t\t\t\t  IN TYPECAST( MESSAGE_ACL * ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *auxInfo )\n\t{\n\tconst MESSAGE_ACL *messageACL = ( MESSAGE_ACL * ) auxInfo;\n\tconst OBJECT_ACL *objectACL = &messageACL->objectACL;\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint subType;\n\n\tassert( isReadPtr( messageACL, sizeof( MESSAGE_ACL ) ) );\n\n\t/* Preconditions: The access is valid and we've been supplied a valid\n\t   check ACL */\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\tREQUIRES( fullObjectCheck( objectHandle, message ) );\n\tREQUIRES( messageACL->type == ( message & MESSAGE_MASK ) );\n\n\tif( isInHighState( objectHandle ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Make sure that the object parameter is valid and accessible */\n\tif( !fullObjectCheck( messageValue, message ) || \\\n\t\t!isSameOwningObject( objectHandle, messageValue ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Make sure that the object parameter subtype is correct */\n\tsubType = objectTable[ messageValue ].subType;\n\tif( !isValidSubtype( objectACL->subTypeA, subType ) && \\\n\t\t!isValidSubtype( objectACL->subTypeB, subType ) && \\\n\t\t!isValidSubtype( objectACL->subTypeC, subType ) )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t/* Postcondition: Object is in the low state so a state change message\n\t   is valid and the object parameter is valid, accessible, and of the\n\t   correct type */\n\tENSURES( !isInHighState( objectHandle ) );\n\tENSURES( fullObjectCheck( messageValue, message ) && \\\n\t\t\t isSameOwningObject( objectHandle, messageValue ) );\n\tENSURES( isValidSubtype( objectACL->subTypeA, subType ) || \\\n\t\t\t isValidSubtype( objectACL->subTypeB, subType ) || \\\n\t\t\t isValidSubtype( objectACL->subTypeC, subType ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* We're exporting a certificate, make sure that the format is valid for\n   this certificate type */\n\nCHECK_RETVAL \\\nint preDispatchCheckExportAccess( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t  const void *messageDataPtr,\n\t\t\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTFORMAT ) const int messageValue,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst ATTRIBUTE_ACL *formatACL;\n\tint i, LOOP_ITERATOR;\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\tREQUIRES( messageDataPtr != NULL );\n\tREQUIRES( isEnumRange( messageValue, CRYPT_CERTFORMAT ) );\n\n\t/* Find the appropriate ACL for this export type.  Because this is a \n\t   pseudo-ACL that uses CRYPT_CERTFORMAT_TYPE instead of \n\t   CRYPT_ATTRIBUTE_TYPE, we compare entries against \n\t   CRYPT_CERTFORMAT_xxx rather than CRYPT_ATTRIBUTE_xxx */\n\tLOOP_MED( i = 0, formatPseudoACL[ i ].attribute != messageValue && \n\t\t\t\t\t formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ),\n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( formatPseudoACL, ATTRIBUTE_ACL_ALT ) );\n\tENSURES( formatPseudoACL[ i ].attribute != CRYPT_CERTFORMAT_NONE );\n\n\t/* The easiest way to handle this check is to use an ACL, treating the\n\t   format type as a pseudo-attribute type.  We can only check the \n\t   attribute type in the debug build because it's not present in the \n\t   release to save space */\n\tformatACL = ( ATTRIBUTE_ACL * ) &formatPseudoACL[ i ];\n#ifndef NDEBUG\n\tENSURES( formatACL->attribute == messageValue );\n#endif /* NDEBUG */\n\n\treturn( preDispatchCheckAttributeAccess( objectHandle,\n\t\t\t\t\t\t\tisInternalMessage( message ) ? \\\n\t\t\t\t\t\t\tIMESSAGE_GETATTRIBUTE_S : MESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\tmessageDataPtr, messageValue, formatACL ) );\n\t}\n\n/* It's data being pushed or popped, make sure that it's a valid data\n   quantity */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckData( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t  IN_BUFFER_C( sizeof( MESSAGE_DATA ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t  STDC_UNUSED const int dummy1,\n\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tconst MESSAGE_DATA *msgData = messageDataPtr;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_DATA ) ) );\n\n\t/* Precondition */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidMessage( localMessage ) );\n\n\t/* Make sure that it's either a flush (buffer = NULL, length = 0)\n\t   or valid data */\n\tif( msgData->data == NULL )\n\t\t{\n\t\tif( localMessage != MESSAGE_ENV_PUSHDATA )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tif( msgData->length != 0 )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\tif( msgData->length <= 0 )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tif( !isReadPtrDynamic( msgData->data, msgData->length ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Postcondition: It's a flush or it's valid data */\n\tENSURES( ( localMessage == MESSAGE_ENV_PUSHDATA && \\\n\t\t\t   msgData->data == NULL && msgData->length == 0 ) || \\\n\t\t\t ( msgData->data != NULL && msgData->length > 0 ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* We're creating a new object, make sure that the create parameters are \n   valid and set the new object's owner to the owner of the object that it's \n   being created through */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint preDispatchCheckCreate( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\tIN_BUFFER_C( sizeof( MESSAGE_CREATEOBJECT_INFO ) ) \\\n\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\tIN_ENUM( OBJECT_TYPE ) const int messageValue,\n\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tconst CREATE_ACL *createACL = \\\n\t\t\t( localMessage == MESSAGE_DEV_CREATEOBJECT ) ? \\\n\t\t\tcreateObjectACL : createObjectIndirectACL;\n\tconst int createAclSize = \\\n\t\t\t( localMessage == MESSAGE_DEV_CREATEOBJECT ) ? \\\n\t\t\tFAILSAFE_ARRAYSIZE( createObjectACL, CREATE_ACL ) : \\\n\t\t\tFAILSAFE_ARRAYSIZE( createObjectIndirectACL, CREATE_ACL );\n\tMESSAGE_CREATEOBJECT_INFO *createInfo = \\\n\t\t\t\t\t( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( messageDataPtr, sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\t/* Precondition */\n\tREQUIRES( fullObjectCheck( objectHandle, message ) && \\\n\t\t\t  objectTable[ objectHandle ].type == OBJECT_TYPE_DEVICE );\n\tREQUIRES( localMessage == MESSAGE_DEV_CREATEOBJECT || \\\n\t\t\t  localMessage == MESSAGE_DEV_CREATEOBJECT_INDIRECT );\n\tREQUIRES( isValidType( messageValue ) );\n\tREQUIRES( createInfo->cryptHandle == CRYPT_ERROR );\n\tREQUIRES( createInfo->cryptOwner == CRYPT_ERROR || \\\n\t\t\t  createInfo->cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( createInfo->cryptOwner ) );\n\t\n\t/* Find the appropriate ACL for this object create type */\n\tLOOP_MED( i = 0, i < createAclSize && \\\n\t\t\t\t\t createACL[ i ].type != messageValue && \n\t\t\t\t\t createACL[ i ].type != OBJECT_TYPE_NONE, i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < createAclSize );\n\tENSURES( createACL[ i ].type != OBJECT_TYPE_NONE );\n\tcreateACL = &createACL[ i ];\n\n\t/* Check whether this object subtype requires special handling and if it\n\t   does switch to an alternative ACL.  The default value for the entries \n\t   in the exceptions list is 0, but no valid exceptionally processed \n\t   sub-type has this value (which corresponds to CRYPT_something_NONE) \n\t   so we can never inadvertently match a valid type.  We do however have \n\t   to check for a nonzero subtype argument since for indirect object \n\t   creates the subtype arg.can be zero if type autodetection is being \n\t   used */\n\tif( createInfo->arg1 != 0 && createACL->exceptions[ 0 ] != 0 )\n\t\t{\n\t\tconst int objectSubType = createInfo->arg1;\n\n\t\t/* There are exception ACLs present, walk down the list of exception \n\t\t   ACLs checking whether there's one for this objet type */\n\t\tLOOP_SMALL( i = 0, createACL->exceptions[ i ] != OBJECT_TYPE_NONE, i++ )\n\t\t\t{\n\t\t\tif( objectSubType == createACL->exceptions[ i ] )\n\t\t\t\t{\n\t\t\t\tconst CREATE_ACL *exceptionACL = &createACL->exceptionACL[ i ];\n\t\t\t\tconst PARAM_ACL *paramACL = getParamACL( exceptionACL );\n\n\t\t\t\t/* If the object subtype that we're processing is the one \n\t\t\t\t   that's covered by this ACL then we're done */\n\t\t\t\tif( objectSubType >= paramACL->lowRange && \\\n\t\t\t\t\tobjectSubType <= paramACL->highRange )\n\t\t\t\t\t{\n\t\t\t\t\tcreateACL = exceptionACL;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Make sure that the subtype is valid for this object type */\n\tif( !checkParamNumeric( paramInfo( createACL, 0 ), createInfo->arg1 ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Make sure that any additional numeric arguments are valid */\n\tENSURES( checkParamNumeric( paramInfo( createACL, 1 ), \n\t\t\t\t\t\t\t\tcreateInfo->arg2 ) );\n\tENSURES( checkParamNumeric( paramInfo( createACL, 2 ), \n\t\t\t\t\t\t\t\tcreateInfo->arg3 ) );\n\n\t/* Make sure that any string arguments are valid */\n\tif( !checkParamString( paramInfo( createACL, 3 ), \n\t\t\t\t\t\t   createInfo->strArg1, createInfo->strArgLen1 ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( !checkParamString( paramInfo( createACL, 4 ), \n\t\t\t\t\t\t   createInfo->strArg2, createInfo->strArgLen2 ) )\n\t\treturn( CRYPT_ARGERROR_STR2 );\n\n\t/* If there's no object owner explicitly set, set the new object's owner \n\t   to the owner of the object that it's being created through.  If it's \n\t   being created through the system device object (which has no owner) \n\t   we set the owner to the default user object */\n\tif( createInfo->cryptOwner == CRYPT_ERROR )\n\t\t{\n\t\tif( objectHandle == SYSTEM_OBJECT_HANDLE )\n\t\t\tcreateInfo->cryptOwner = DEFAULTUSER_OBJECT_HANDLE;\n\t\telse\n\t\t\t{\n\t\t\tconst int ownerObject = objectTable[ objectHandle ].owner;\n\n\t\t\t/* Inner precondition: The owner is a valid user object */\n\t\t\tREQUIRES( isValidObject( ownerObject ) && \\\n\t\t\t\t\t  objectTable[ ownerObject ].type == OBJECT_TYPE_USER );\n\t\n\t\t\tcreateInfo->cryptOwner = ownerObject;\n\t\t\t}\n\t\t}\n\n\t/* Postcondition: The new object's owner will be the user object it's\n\t   being created through or the default user if it's being done via the\n\t   system object */\n\tENSURES( ( objectHandle == SYSTEM_OBJECT_HANDLE && \\\n\t\t\t   createInfo->cryptOwner == DEFAULTUSER_OBJECT_HANDLE ) || \\\n\t\t\t( objectHandle != SYSTEM_OBJECT_HANDLE && \\\n\t\t\t  createInfo->cryptOwner == objectTable[ objectHandle ].owner ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* It's a user management message, make sure that it's valid */\n\nCHECK_RETVAL \\\nint preDispatchCheckUserMgmtAccess( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_USERMGMT ) const int messageValue, \n\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\n\tREQUIRES( fullObjectCheck( objectHandle, message ) && \\\n\t\t\t  objectTable[ objectHandle ].type == OBJECT_TYPE_USER );\n\tREQUIRES( localMessage == MESSAGE_USER_USERMGMT );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_USERMGMT ) );\n\n\t/* At the moment with only minimal user management available it's \n\t   easiest to hardcode the checks */\n\tswitch( messageValue )\n\t\t{\n\t\tcase MESSAGE_USERMGMT_ZEROISE:\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* It's a trust management message, make sure that it's valid */\n\nCHECK_RETVAL \\\nint preDispatchCheckTrustMgmtAccess( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t const void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t STDC_UNUSED const int messageValue, \n\t\t\t\t\t\t\t\t\t STDC_UNUSED const void *dummy )\n\t{\n\tstatic const OBJECT_ACL objectTrustedCertificate = {\n\t\t\tST_CERT_CERT | ST_CERT_CERTCHAIN, ST_NONE, ST_NONE, \n\t\t\tACL_FLAG_HIGH_STATE | ACL_FLAG_ROUTE_TO_CERT };\n\tstatic const ATTRIBUTE_ACL trustMgmtPseudoACL[] = {\n\t\tMKACL_O(\n\t\t\t/* Since we're using an attribute-ACL check capability to handle\n\t\t\t   this, we set a dummy attribute type for the value that's \n\t\t\t   being checked */\n\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\tST_NONE, ST_NONE, ST_USER_ANY, ACCESS_INT_Rxx_xxx,\n\t\t\tROUTE( OBJECT_TYPE_USER ), &objectTrustedCertificate )\n\t\t};\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\n\tassert( ( messageValue == MESSAGE_TRUSTMGMT_GETISSUER && \\\n\t\t\t  isWritePtr( ( void * ) messageDataPtr, \\\n\t\t\t\t\t\t  sizeof( CRYPT_HANDLE ) ) ) || \\\n\t\t\t( isReadPtr( messageDataPtr, sizeof( CRYPT_HANDLE ) ) ) );\n\n\tREQUIRES( fullObjectCheck( objectHandle, message ) && \\\n\t\t\t  objectTable[ objectHandle ].type == OBJECT_TYPE_USER );\n\tREQUIRES( localMessage == MESSAGE_USER_TRUSTMGMT );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_TRUSTMGMT ) );\n\n\t/* The easiest way to handle this check is to use an ACL, treating the\n\t   trust management operation type as a pseudo-attribute type */\n\treturn( preDispatchCheckAttributeAccess( objectHandle,\n\t\t\t\t\t\t\tisInternalMessage( message ) ? \\\n\t\t\t\t\t\t\tIMESSAGE_GETATTRIBUTE : MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\tmessageDataPtr, CRYPT_CERTINFO_TRUSTED_IMPLICIT, \n\t\t\t\t\t\t\ttrustMgmtPseudoACL ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage Post-Dispatch Handlers\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If it's a destroy object message, adjust the reference counts of any\n   dependent devices.  We have to do this as a post-dispatch action since\n   the object that we're destroying often depends on the dependent device */\n\nCHECK_RETVAL \\\nint postDispatchSignalDependentDevices( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy4 )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tSTDC_UNUSED int status;\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( objectHandle ) && \\\n\t\t\t  objectHandle >= NO_SYSTEM_OBJECTS );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* An inability to change the reference counts of the dependent devices \n\t   doesn't affect the object itself so we can't report it as an error, \n\t   however we can at least warn about it in debug mode */\n\tif( isValidObject( objectInfoPtr->dependentDevice ) )\n\t\t{\n\t\t/* Velisurmaaja */\n\t\tstatus = decRefCount( objectInfoPtr->dependentDevice, 0, NULL, TRUE );\n\t\tassert( cryptStatusOK( status ) );\n\t\tobjectInfoPtr->dependentDevice = CRYPT_ERROR;\n\t\t}\n\n\t/* Postcondition: The dependent device is now disconnected from the \n\t   object */\n\tENSURES( !isValidObject( objectInfoPtr->dependentDevice ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* If we're fetching or creating an object, it won't be visible to an\n   outside caller.  If it's an external message, we have to make the object\n   externally visible before we return it */\n\nCHECK_RETVAL \\\nint postDispatchMakeObjectExternal( STDC_UNUSED const int dummy,\n\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\t\tconst void *auxInfo )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tconst BOOLEAN isInternalMessage = isInternalMessage( message ) ? \\\n\t\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tCRYPT_HANDLE objectHandle;\n\tint status;\n\n\t/* Preconditions */\n\tREQUIRES( localMessage == MESSAGE_GETATTRIBUTE || \\\n\t\t\t  localMessage == MESSAGE_DEV_CREATEOBJECT || \\\n\t\t\t  localMessage == MESSAGE_DEV_CREATEOBJECT_INDIRECT || \\\n\t\t\t  localMessage == MESSAGE_KEY_GETKEY || \\\n\t\t\t  localMessage == MESSAGE_KEY_GETNEXTCERT || \\\n\t\t\t  localMessage == MESSAGE_KEY_CERTMGMT );\n\tREQUIRES( messageDataPtr != NULL );\n\n\t/* If it's an internal message, there are no problems with object\n\t   visibility.  In addition most messages are internal, so performing\n\t   this check before anything else quickly weeds out the majority of\n\t   cases */\n\tif( isInternalMessage )\n\t\treturn( CRYPT_OK );\n\n\tswitch( localMessage )\n\t\t{\n\t\tcase MESSAGE_GETATTRIBUTE:\n\t\t\t{\n\t\t\tconst ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;\n\n\t\t\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\n\t\t\t/* Inner precondition: Since it's an external message, we must\n\t\t\t   be reading a standard attribute */\n\t\t\tREQUIRES( isAttribute( messageValue ) );\n\t\t\tassert( attributeACL->attribute == messageValue );\n\t\t\t\t\t/* Only in debug build, see comment in attr_acl.c */\n\n\t\t\t/* If it's not an object attribute read then we're done */\n\t\t\tif( attributeACL->valueType == ATTRIBUTE_VALUE_SPECIAL )\n\t\t\t\t{\n\t\t\t\tattributeACL = getSpecialRangeInfo( attributeACL );\n\t\t\t\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\t\t\t\tENSURES( attributeACL != NULL );\n\t\t\t\t}\n\t\t\tif( attributeACL->valueType != ATTRIBUTE_VALUE_OBJECT )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Inner precondition: We're reading an object attribute and\n\t\t\t   sending the response to an external caller */\n\t\t\tREQUIRES( attributeACL->valueType == ATTRIBUTE_VALUE_OBJECT );\n\t\t\tREQUIRES( isValidObject( *( ( int * ) messageDataPtr ) ) );\n\t\t\tREQUIRES( !isInternalMessage );\n\n\t\t\tobjectHandle = *( ( int * ) messageDataPtr );\n\n\t\t\t/* If the object has already been read (for example a \n\t\t\t   CRYPT_ENVINFO_SIGNATURE certificate from an envelope or a\n\t\t\t   CRYPT_SESSINFO_RESPONSE from a PKI session) then it'll \n\t\t\t   already be external, so all we have to do is convert an\n\t\t\t   additional internal reference to an external one */\n\t\t\tif( !isInternalObject( objectHandle ) && \\\n\t\t\t\t( messageValue == CRYPT_ENVINFO_SIGNATURE || \\\n\t\t\t\t  messageValue == CRYPT_ENVINFO_SIGNATURE_EXTRADATA || \\\n\t\t\t\t  messageValue == CRYPT_SESSINFO_RESPONSE || \\\n\t\t\t\t  messageValue == CRYPT_SESSINFO_CACERTIFICATE ) )\n\t\t\t\treturn( convertIntToExtRef( objectHandle ) );\n\n\t\t\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t\t\t isInternalObject( objectHandle ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase MESSAGE_DEV_CREATEOBJECT:\n\t\tcase MESSAGE_DEV_CREATEOBJECT_INDIRECT:\n\t\t\t{\n\t\t\tMESSAGE_CREATEOBJECT_INFO *createInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_CREATEOBJECT_INFO * ) messageDataPtr;\n\n\t\t\tassert( isReadPtr( createInfo, \\\n\t\t\t\t\t\t\t   sizeof( MESSAGE_CREATEOBJECT_INFO ) ) );\n\n\t\t\tobjectHandle = createInfo->cryptHandle;\n\n\t\t\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t\t\t isInternalObject( objectHandle ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase MESSAGE_KEY_GETKEY:\n\t\tcase MESSAGE_KEY_GETNEXTCERT:\n\t\t\t{\n\t\t\tMESSAGE_KEYMGMT_INFO *getkeyInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;\n\n\t\t\tassert( isReadPtr( getkeyInfo, \\\n\t\t\t\t\t\t\t   sizeof( MESSAGE_KEYMGMT_INFO ) ) );\n\n\t\t\tobjectHandle = getkeyInfo->cryptHandle;\n\n\t\t\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t\t\t isInternalObject( objectHandle ) && \\\n\t\t\t\t\t isInHighState( objectHandle ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase MESSAGE_KEY_CERTMGMT:\n\t\t\t{\n\t\t\tMESSAGE_CERTMGMT_INFO *certMgmtInfo = \\\n\t\t\t\t\t\t\t( MESSAGE_CERTMGMT_INFO * ) messageDataPtr;\n\n\t\t\tassert( isReadPtr( certMgmtInfo, \\\n\t\t\t\t\t\t\t   sizeof( MESSAGE_CERTMGMT_INFO ) ) );\n\n\t\t\t/* If it's not a certificate management action that can return \n\t\t\t   an object, there's no object to make visible */\n\t\t\tif( messageValue != CRYPT_CERTACTION_ISSUE_CERT && \\\n\t\t\t\tmessageValue != CRYPT_CERTACTION_CERT_CREATION && \\\n\t\t\t\tmessageValue != CRYPT_CERTACTION_ISSUE_CRL )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* If the caller has indicated that they're not interested in the\n\t\t\t   newly-created object, it won't be present so we can't make it\n\t\t\t   externally visible */\n\t\t\tif( certMgmtInfo->cryptCert == CRYPT_UNUSED )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Inner precondition: It's an action that can return an object,\n\t\t\t   and there's an object present */\n\t\t\tREQUIRES( messageValue == CRYPT_CERTACTION_ISSUE_CERT || \\\n\t\t\t\t\t  messageValue == CRYPT_CERTACTION_CERT_CREATION || \\\n\t\t\t\t\t  messageValue == CRYPT_CERTACTION_ISSUE_CRL );\n\t\t\tREQUIRES( certMgmtInfo->cryptCert != CRYPT_UNUSED );\n\n\t\t\tobjectHandle = certMgmtInfo->cryptCert;\n\n\t\t\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t\t\t isInternalObject( objectHandle ) && \\\n\t\t\t\t\t isInHighState( objectHandle ) );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make the object externally visible.  In theory we should make this\n\t   attribute read-only, but it's currently still needed in init.c (the\n\t   kernel self-test, which checks for internal vs. external\n\t   accessibility), keyex.c (to make PGP imported contexts visible),\n\t   sign.c (to make CMS signing attributes externally visible), and\n\t   cryptapi.c when creating objects (to make them externally visible)\n\t   and destroying objects (to make them appear destroyed if a dec-\n\t   refcount leaves it still active) */\n\tstatus = krnlSendMessage( objectHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INTERNAL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Postcondition: The object is now externally visible */\n\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t !isInternalObject( objectHandle ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* If there's a dependent object with a given relationship to the controlling\n   object, forward the message.  In practice the only dependencies are those\n   of PKC contexts paired with certificates, for which a message sent to one \n   (e.g. a check message such as \"is this suitable for signing?\") needs to be\n   forwarded to the other.  \n   \n   The certificate and CA capabilities are spread across certificates (the \n   certificate or certificate with CA flag set) and contexts (the PKC \n   capability), which requires a two-phase check.  First we check the \n   primary object and then we check the secondary one.  For a private key\n   the primary object is the private-key context and the secondary is the \n   certificate, for a public key the primary object is the certificate and\n   the secondary is the public-key context.\n\n   The possible combinaitions of objects and associated checks are:\n   \n\tType\t\t\t\tTarget\tObject\t\tDep.Obj.\tCheck\n\t----\t\t\t\t------\t------\t\t-------\t\t--------\n\tPrivkey + cert\t\tContext\tPKC-priv\tCert\t\tSIGN\n\tCert + pubkey\t\tCert\tCert\t\tPKC-pub\t\tSIGCHECK\n\n\tType\t\t\t\tTarget\tObject\t\tDep.Obj.\tCheck\n\t----\t\t\t\t------\t------\t\t-------\t\t--------\n\tPrivkey + CA cert\tContext\tPKC-priv\tCert\t\tSIGN_CA\n\tCA cert + pubkey\tCert\tCert\t\tPKC-pub\t\tSIGCHECK_CA\n\n   In theory for certificates we'd need to perform some sort of generic \n   sign-or-sigcheck check for the case where the certificate is the primary \n   object, but since the certificate + context combination can only occur \n   for public-key contexts it's safe to check for a sigcheck capability.  \n   Similarly, when the context is the primary object it's always a private \n   key, so we can check for a sign capability */\n\nCHECK_RETVAL \\\nint postDispatchForwardToDependentObject( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\t  IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy1,\n\t\t\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_CHECK ) const int messageValue,\n\t\t\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tconst int dependentObject = objectInfoPtr->dependentObject;\n\tconst OBJECT_TYPE objectType = objectInfoPtr->type;\n\tconst OBJECT_TYPE dependentType = isValidObject( dependentObject ) ? \\\n\t\t\t\t\t\t\tobjectTable[ dependentObject ].type : CRYPT_ERROR;\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMESSAGE_CHECK_TYPE localMessageValue = messageValue;\n\tint status;\n\n\t/* Precondition: It's an appropriate message type being forwarded to a\n\t   dependent object */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( ( message & MESSAGE_MASK ) == MESSAGE_CHECK );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_CHECK ) );\n\tREQUIRES( isValidObject( dependentObject ) || \\\n\t\t\t  dependentObject == CRYPT_ERROR );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* If there's no dependent object then there's nothing to forward the \n\t   message to */\n\tif( !isValidObject( dependentObject ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If there's no context : certificate relationship between the objects, \n\t   don't do anything.  This is a bit ugly since it hardcodes object \n\t   types into a kernel function, we could in theory encode the rule into\n\t   an ACL and apply it as simulation of a generic rule that happens to \n\t   do the same thing, but since there's only one check type that we can\n\t   apply we just leave it hardcoded here rather than faking generality\n\t   via an ACL */\n\tif( !( objectType == OBJECT_TYPE_CONTEXT && \\\n\t\t   dependentType == OBJECT_TYPE_CERTIFICATE ) && \\\n\t\t!( objectType == OBJECT_TYPE_CERTIFICATE && \\\n\t\t   dependentType == OBJECT_TYPE_CONTEXT ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Postcondition */\n\tENSURES( isValidObject( dependentObject ) );\n\tENSURES( isSameOwningObject( objectHandle, dependentObject ) );\n\n\t/* Forward the message to the dependent object.  We have to make the\n\t   message internal since the dependent object may be internal-only.\n\t   In addition we have to unlock the object table since the dependent\n\t   object may currently be owned by another thread */\n\tMUTEX_UNLOCK( objectTable );\n\tstatus = krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  localMessageValue );\n\tMUTEX_LOCK( objectTable );\n\treturn( status );\n\t}\n\n/* Some objects can only perform given number of actions before they self-\n   destruct, so if there's a usage count set we update it */\n\nCHECK_RETVAL \\\nint postDispatchUpdateUsageCount( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *dummy4 )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];\n\tORIGINAL_INT_VAR( usageCt, objectInfoPtr->usageCount );\n\n\t/* Precondition: It's a context with a nonzero usage count */\n\tREQUIRES( isValidObject( objectHandle ) && \\\n\t\t\t  objectInfoPtr->type == OBJECT_TYPE_CONTEXT );\n\tREQUIRES( objectInfoPtr->usageCount == CRYPT_UNUSED || \\\n\t\t\t  objectInfoPtr->usageCount > 0 );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* If there's an active usage count present, update it */\n\tif( objectInfoPtr->usageCount > 0 )\n\t\tobjectInfoPtr->usageCount--;\n\n\t/* Postcondition: If there was a usage count it's been decremented and\n\t   is >= 0 (the ground state) */\n\tENSURES( objectInfoPtr->usageCount == CRYPT_UNUSED || \\\n\t\t\t ( objectInfoPtr->usageCount == ORIGINAL_VALUE( usageCt ) - 1 && \\\n\t\t\t   objectInfoPtr->usageCount >= 0 ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Certain messages can trigger changes in the object state from the low to\n   the high state.  Once one of these messages is successfully processed, we\n   change the object's state so that further accesses are handled by the\n   kernel based on the new state established by the message having been\n   processed successfully.  Since the object is still marked as busy at this\n   stage, other messages arriving before the following state change can't\n   bypass the kernel checks since they won't be processed until the object\n   is marked as non-busy later on */\n\nCHECK_RETVAL \\\nint postDispatchChangeState( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t STDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t STDC_UNUSED const int dummy3,\n\t\t\t\t\t\t\t STDC_UNUSED const void *dummy4 )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\n\t/* Precondition: Object is in the low state so a state change message is\n\t   valid */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( !isInHighState( objectHandle ) );\n\n\t/* The state change message was successfully processed, the object is now\n\t   in the high state */\n\tSET_FLAG( objectTable[ objectHandle ].flags, OBJECT_FLAG_HIGH );\n\n\t/* Postcondition: Object is in the high state */\n\tENSURES( isInHighState( objectHandle ) );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint postDispatchChangeStateOpt( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const MESSAGE_TYPE dummy1,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t\tconst int messageValue,\n\t\t\t\t\t\t\t\tIN TYPECAST( ATTRIBUTE_ACL * ) const void *auxInfo )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tconst ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\tassert( isReadPtr( attributeACL, sizeof( ATTRIBUTE_ACL ) ) );\n\n\t/* Precondition.  If we're closing down then a background polling thread\n\t   may still be trying to send entropy data to the system object, so we\n\t   don't complain if this is the case */\n\tREQUIRES( ( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_THREADS && \\\n\t\t\t    objectHandle == SYSTEM_OBJECT_HANDLE && \\\n\t\t\t    messageValue == CRYPT_IATTRIBUTE_ENTROPY ) || \\\n\t\t\t  isValidObject( objectHandle ) );\n\n\t/* If it's an attribute that triggers a state change, change the state */\n\tif( attributeACL->flags & ATTRIBUTE_FLAG_TRIGGER )\n\t\t{\n\t\t/* Inner precondition: Object is in the low state so a state change\n\t\t   message is valid, or it's a retriggerable attribute that can be\n\t\t   added multiple times (in other words, it can be added in both\n\t\t   the low and high state, with the first add in the low state\n\t\t   triggering a transition into the high state and subsequent\n\t\t   additions augmenting the existing data) */\n\t\tREQUIRES( !isInHighState( objectHandle ) || \\\n\t\t\t\t  ( ( attributeACL->access & ACCESS_INT_xWx_xWx ) == \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tACCESS_INT_xWx_xWx ) );\n\n\t\tSET_FLAG( objectTable[ objectHandle ].flags, OBJECT_FLAG_HIGH );\n\n\t\t/* Postcondition: Object is in the high state */\n\t\tENSURES( isInHighState( objectHandle ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Postcondition: It wasn't a trigger message */\n\tENSURES( !( attributeACL->flags & ATTRIBUTE_FLAG_TRIGGER ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* It's a user management message, if it's a zeroise trigger a shutdown of\n   the kernel */\n\nCHECK_RETVAL \\\nint postDispatchHandleZeroise( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy2,\n\t\t\t\t\t\t\t   IN_ENUM( MESSAGE_USERMGMT ) const int messageValue,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *dummy3 )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst MESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\tREQUIRES( fullObjectCheck( objectHandle, message ) && \\\n\t\t\t  objectTable[ objectHandle ].type == OBJECT_TYPE_USER );\n\tREQUIRES( localMessage == MESSAGE_USER_USERMGMT );\n\tREQUIRES( isEnumRange( messageValue, MESSAGE_USERMGMT ) );\n\n\t/* The only currently defined message is zeroise */\n\tREQUIRES( messageValue == MESSAGE_USERMGMT_ZEROISE );\n\n\t/* We're about to shut down, give any threads a chance to bail out */\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_THREADS;\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/obj_acc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Alternative Access\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sending a message to an object only makes the one object which is the\n   target of the message available for use.  When we need simultaneous\n   access to two objects (for example when copying a collection of cert\n   extensions from one cert to another), we have to use the\n   krnlAcquireObject()/krnlReleaseObject() functions to obtain access to\n   the second object's internals.\n\n   There is a second situation in which we need access to an object's\n   internals, and that occurs when we need to export/import a key from/to\n   a context.  This is handled via the key extract functions at the end\n   of this module, see the comments there for further information */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* Optionally include the Intel Thread Checker API to control analysis of \n   the object mutexes */\n\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && 0\n  #include \"../../../Intel/VTune/tcheck/Include/libittnotify.h\"\n  #pragma comment( lib, \"C:/Program Files/Intel/VTune/Analyzer/Lib/libittnotify.lib\" )\n\n  #define THREAD_NOTIFY_PREPARE( id )\t__itt_notify_sync_prepare( ( void * ) id );\n  #define THREAD_NOTIFY_CANCELLED( id )\t__itt_notify_sync_prepare( ( void * ) id );\n  #define THREAD_NOTIFY_ACQUIRED( id )\t__itt_notify_sync_acquired( ( void * ) id );\n  #define THREAD_NOTIFY_RELEASED( id )\t__itt_notify_sync_releasing( ( void * ) id );\n#else\n  #define THREAD_NOTIFY_PREPARE( dummy )\n  #define THREAD_NOTIFY_CANCELLED( dummy )\n  #define THREAD_NOTIFY_ACQUIRED( dummy )\n  #define THREAD_NOTIFY_RELEASED( dummy )\n#endif /* VC++ 6.0 with Intel Thread Checker */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The type of checking that we perform for the object access.  The check \n   types are:\n\n\tCHECK_EXTACCESS\n\t\tKernel-external call with a cert or crypto device to allow access to\n\t\tobject-internal data.\n\n\tCHECK_KEYACCESS\n\t\tKernel-internal call with a context for key export/import.\n\n\tCHECK_SUSPEND\n\t\tKernel-external call with a user or system object to temporarily\n\t\tsuspend object use and allow others access, providing a (somewhat \n\t\tcrude) mechanism for making kernel calls interruptible */\n\ntypedef enum {\n\tACCESS_CHECK_NONE,\t\t/* No access check type */\n\tACCESS_CHECK_EXTACCESS,\t/* Generic external call: Cert or crypt.dev.*/\n\tACCESS_CHECK_KEYACCESS,\t/* Internal call: Context for key export */\n\tACCESS_CHECK_SUSPEND,\t/* Suspend object use: User or sys.obj.*/\n\tACCESS_CHECK_LAST\t\t/* Last access check type */\n\t} ACCESS_CHECK_TYPE;\n\n/* Check that this is an object for which direct access is valid.  We can \n   only access the following object types:\n\n\tCertificates: EXTACCESS, used when copying internal state such as cert \n\t\textensions or CRL info from one cert object to another.\n\n\tContexts: KEYACCESS, used when importing/exporting keys to/from contexts \n\t\tduring key wrap/unwrap operations.\n\n\tCrypto hardware devices other than the system object: EXTACCESS, used \n\t\twhen a context tied to a device needs to perform an operation using \n\t\tthe device.\n\n\tSystem object: ACCESS_CHECK_SUSPEND, used when performing a randomness \n\t\tdata read/write, which can take some time to complete.\n\n\tUser objects: ACCESS_CHECK_SUSPEND, used when committing config data to \n\t\tpersistent storage.  We don't actually use the object data but \n\t\tmerely unlock it to allow others access while performing the \n\t\tpotentially lengthy update.  Also used when performing the self-\n\t\ttest */\n\nCHECK_RETVAL \\\nstatic int checkAccessValid( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t IN_ENUM( ACCESS_CHECK ) \\\n\t\t\t\t\t\t\t\t\tconst ACCESS_CHECK_TYPE checkType,\n\t\t\t\t\t\t\t IN_ERROR const int errorCode )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable(), *objectInfoPtr;\n\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isEnumRange( checkType, ACCESS_CHECK ) );\n\tREQUIRES( cryptStatusError( errorCode ) );\n\n\t/* Perform similar access checks to the ones performed in\n\t   krnlSendMessage(): It's a valid object owned by the calling\n\t   thread */\n\tif( !isValidObject( objectHandle ) || \\\n\t\t!checkObjectOwnership( objectTable[ objectHandle ] ) )\n\t\treturn( errorCode );\n\n\t/* It's a valid object, get its info */\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\n\t/* Make sure that the object access is valid */\n\tswitch( objectInfoPtr->type )\n\t\t{\n\t\tcase OBJECT_TYPE_CONTEXT:\n\t\t\t/* Optionally used to allow direct calls to context functions \n\t\t\t   for real-time APi access */\n#ifdef CONFIG_DIRECT_API\n\t\t\tif( checkType == ACCESS_CHECK_EXTACCESS )\n\t\t\t\t{\n\t\t\t\tif( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_CONV ) && \\\n\t\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_HASH ) && \\\n\t\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_MAC ) )\n\t\t\t\t\treturn( errorCode );\n\t\t\t\t}\n\t\t\telse\n#endif /* CONFIG_DIRECT_API */\n\t\t\t{\n\t\t\t/* Used when exporting/importing keying info, valid for contexts \n\t\t\t   with keys when called from within the kernel */\n\t\t\tif( checkType != ACCESS_CHECK_KEYACCESS )\n\t\t\t\treturn( errorCode );\n\t\t\tif( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_CONV ) && \\\n\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_MAC ) && \\\n\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_PKC ) && \\\n\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_GENERIC ) )\n\t\t\t\treturn( errorCode );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_CERTIFICATE:\n\t\t\t/* Used when copying internal state such as cert extensions or\n\t\t\t   CRL info from one cert object to another.  This is valid for\n\t\t\t   all cert types */\n\t\t\tif( checkType != ACCESS_CHECK_EXTACCESS )\n\t\t\t\treturn( errorCode );\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_DEVICE:\n\t\t\t/* If it's an external access operation, it's used when a \n\t\t\t   context tied to a crypto hardware device needs to perform an \n\t\t\t   operation using the device.  This is valid for all devices \n\t\t\t   other than the system object */\n\t\t\tif( checkType == ACCESS_CHECK_EXTACCESS )\n\t\t\t\t{\n\t\t\t\tif( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_PKCS11 ) && \\\n\t\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_CRYPTOAPI ) && \\\n\t\t\t\t\t!isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_HARDWARE ) )\n\t\t\t\t\treturn( errorCode );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If it's a suspend operation, it's used to temporarily \n\t\t\t\t   allow access to the system object while other operations\n\t\t\t\t   are being performed */\n\t\t\t\tif( checkType != ACCESS_CHECK_SUSPEND )\n\t\t\t\t\treturn( errorCode );\n\t\t\t\tif( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_SYSTEM ) )\n\t\t\t\t\treturn( errorCode );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase OBJECT_TYPE_USER:\n\t\t\t/* Used when updating config data, which can take awhile.  The \n\t\t\t   default user is an SO user, which is why we check for this \n\t\t\t   user type */\n\t\t\tif( checkType != ACCESS_CHECK_SUSPEND )\n\t\t\t\treturn( errorCode );\n\t\t\tif( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_USER_SO ) )\n\t\t\t\treturn( errorCode );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Postcondition: The object is of the appropriate type for the access */\n#ifdef CONFIG_DIRECT_API\n\tENSURES( ( checkType == ACCESS_CHECK_EXTACCESS && \\\n\t\t\t   ( objectInfoPtr->type == OBJECT_TYPE_CONTEXT || \\\n\t\t\t     objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \\\n\t\t\t\t objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ) || \\\n\t\t\t ( checkType == ACCESS_CHECK_KEYACCESS && \\\n\t\t\t   objectInfoPtr->type == OBJECT_TYPE_CONTEXT ) || \\\n\t\t\t ( checkType == ACCESS_CHECK_SUSPEND && \\\n\t\t\t   ( objectInfoPtr->type == OBJECT_TYPE_DEVICE || \\\n\t\t\t\t objectInfoPtr->type == OBJECT_TYPE_USER ) ) );\n#else\n\tENSURES( ( checkType == ACCESS_CHECK_EXTACCESS && \\\n\t\t\t   ( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \\\n\t\t\t\t objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ) || \\\n\t\t\t ( checkType == ACCESS_CHECK_KEYACCESS && \\\n\t\t\t   objectInfoPtr->type == OBJECT_TYPE_CONTEXT ) || \\\n\t\t\t ( checkType == ACCESS_CHECK_SUSPEND && \\\n\t\t\t   ( objectInfoPtr->type == OBJECT_TYPE_DEVICE || \\\n\t\t\t\t objectInfoPtr->type == OBJECT_TYPE_USER ) ) );\n#endif /* CONFIG_DIRECT_API */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a pointer to an object's data from its handle */\n\nCHECK_RETVAL \\\nstatic int getObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t  IN_ENUM( OBJECT_TYPE ) const OBJECT_TYPE type,\n\t\t\t\t\t  IN_ENUM( ACCESS_CHECK ) const ACCESS_CHECK_TYPE checkType, \n\t\t\t\t\t  OUT_OPT_PTR_COND void **objectPtrPtr, \n\t\t\t\t\t  IN_INT_OPT const int refCount, \n\t\t\t\t\t  IN_ERROR const int errorCode )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable, *objectInfoPtr;\n\tint status;\n\n\tassert( ( ( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\tobjectHandle == DEFAULTUSER_OBJECT_HANDLE ) && \\\n\t\t\t  objectPtrPtr == NULL && refCount > 0 ) || \\\n\t\t\t( !( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\t objectHandle == DEFAULTUSER_OBJECT_HANDLE ) && \\\n\t\t\t  isWritePtr( objectPtrPtr, sizeof( void * ) ) && \\\n\t\t\t  refCount == CRYPT_UNUSED ) );\n\n\t/* Preconditions: It's a valid object */\n\tREQUIRES( isValidHandle( objectHandle ) );\n#ifndef CONFIG_FUZZ\t\t/* To directly inject data into objects */\n\tREQUIRES( isValidType( type ) && \\\n\t\t\t  ( type == OBJECT_TYPE_CONTEXT || \\\n\t\t\t\ttype == OBJECT_TYPE_CERTIFICATE || \\\n\t\t\t\ttype == OBJECT_TYPE_DEVICE || type == OBJECT_TYPE_USER ) );\n#endif /* CONFIG_FUZZ */\n\tREQUIRES( isEnumRange( checkType, ACCESS_CHECK ) );\n\tREQUIRES( ( ( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\t  objectHandle == DEFAULTUSER_OBJECT_HANDLE ) && \\\n\t\t\t\tobjectPtrPtr == NULL && refCount > 0 ) || \\\n\t\t\t  ( !( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\t   objectHandle == DEFAULTUSER_OBJECT_HANDLE ) && \\\n\t\t\t\tobjectPtrPtr != NULL && refCount == CRYPT_UNUSED ) );\n\n\t/* Clear the return value */\n\tif( objectPtrPtr != NULL )\n\t\t*objectPtrPtr = NULL;\n\n\tTHREAD_NOTIFY_PREPARE( objectHandle );\n\tMUTEX_LOCK( objectTable );\n\tobjectTable = getObjectTable();\n\n\t/* Perform similar access checks to the ones performed in\n\t   krnlSendMessage(), as well as situation-specific additional checks \n\t   for correct object types */\n#ifndef CONFIG_FUZZ\t\t/* To directly inject data into objects */\n\tstatus = checkAccessValid( objectHandle, checkType, errorCode );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tTHREAD_NOTIFY_CANCELLED( objectHandle );\n\t\tretIntError_Ext( status );\n\t\t}\n#endif /* CONFIG_FUZZ */\n\n\t/* Perform additional checks for correct object types */\n\tif( ( ( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\tobjectHandle == DEFAULTUSER_OBJECT_HANDLE ) && \\\n\t\t  objectPtrPtr != NULL ) || \\\n\t\tobjectTable[ objectHandle ].type != type )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tTHREAD_NOTIFY_CANCELLED( objectHandle );\n\t\tretIntError_Ext( errorCode );\n\t\t}\n\n\t/* It's a valid object, get its info */\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\tREQUIRES_MUTEX( sanityCheckObject( objectInfoPtr ), objectTable );\n\n\t/* Inner precondition: The object is of the requested type */\n#ifndef CONFIG_FUZZ\t\t/* To directly inject data into objects */\n\tREQUIRES_MUTEX( objectInfoPtr->type == type && \\\n\t\t\t\t\t( objectInfoPtr->type == OBJECT_TYPE_CONTEXT || \\\n\t\t\t\t\t   objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \\\n\t\t\t\t\t   objectInfoPtr->type == OBJECT_TYPE_DEVICE || \\\n\t\t\t\t\t   objectInfoPtr->type == OBJECT_TYPE_USER ), \n\t\t\t\t\tobjectTable );\n#endif /* CONFIG_FUZZ */\n\n\t/* If the object is busy, wait for it to become available */\n\tif( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) )\n\t\t{\n\t\tstatus = waitForObject( objectHandle, &objectInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\tTHREAD_NOTIFY_CANCELLED( objectHandle );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* If it's an external access to certificate/device info or an internal \n\t   access to access the object's keying data, increment the object's \n\t   reference count to reserve it for our exclusive use */\n\tif( checkType == ACCESS_CHECK_EXTACCESS || \\\n\t\tcheckType == ACCESS_CHECK_KEYACCESS )\n\t\tobjectInfoPtr->lockCount++;\n\telse\n\t\t{\n\t\t/* If we're resuming use of an object that we suspended to allow \n\t\t   others access, reset the reference count */\n\t\tREQUIRES_MUTEX( checkType == ACCESS_CHECK_SUSPEND, objectTable );\n\t\tREQUIRES_MUTEX( objectInfoPtr->lockCount == 0, objectTable );\n\t\tREQUIRES_MUTEX( refCount > 0 && refCount < 100, objectTable );\n\n\t\tobjectInfoPtr->lockCount = refCount;\n\t\t}\n#ifdef USE_THREADS\n\tobjectInfoPtr->lockOwner = THREAD_SELF();\n#endif /* USE_THREADS */\n\tif( objectPtrPtr != NULL )\n\t\t{\n\t\tvoid *objectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\n\t\tREQUIRES_MUTEX( objectPtr != NULL, objectTable );\n\n\t\t*objectPtrPtr = objectPtr;\n\t\t}\n\tMUTEX_UNLOCK( objectTable );\n\tTHREAD_NOTIFY_ACQUIRED( objectHandle );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Release an object that we previously acquired directly.  We don't require \n   that the return value of this function be checked by the caller since the \n   only time that we can get an error is if it's a 'can't-occur' internal \n   error and it's not obvious what they should do in that case (omnia iam \n   fient fieri quae posse negabam) */\n\nstatic int releaseObject( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t  IN_ENUM( ACCESS_CHECK ) const ACCESS_CHECK_TYPE checkType,\n\t\t\t\t\t\t  OUT_OPT_INT_Z int *refCount )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable, *objectInfoPtr;\n#ifndef CONFIG_FUZZ\n\tint status;\n#endif /* CONFIG_FUZZ */\n\tDECLARE_ORIGINAL_INT( lockCount );\n\n\tassert( ( ( checkType == ACCESS_CHECK_EXTACCESS || \\\n\t\t\t\tcheckType == ACCESS_CHECK_KEYACCESS ) && \\\n\t\t\t  refCount == NULL ) || \\\n\t\t\t( checkType == ACCESS_CHECK_SUSPEND && \\\n\t\t\t  isWritePtr( refCount, sizeof( int ) ) ) );\n\n\t/* Preconditions */\n\tREQUIRES( isEnumRange( checkType, ACCESS_CHECK ) );\n\tREQUIRES( ( ( checkType == ACCESS_CHECK_EXTACCESS || \\\n\t\t\t\t  checkType == ACCESS_CHECK_KEYACCESS ) && \\\n\t\t\t\trefCount == NULL ) || \\\n\t\t\t  ( checkType == ACCESS_CHECK_SUSPEND && \\\n\t\t\t\trefCount != NULL ) );\n\n\tTHREAD_NOTIFY_PREPARE( objectHandle );\n\tMUTEX_LOCK( objectTable );\n\tobjectTable = getObjectTable();\n\n\t/* Preconditions: It's a valid object in use by the caller.  Since these \n\t   checks require access to the object table we can only perform them \n\t   after we've locked it */\n\tREQUIRES_MUTEX( isValidObject( objectHandle ), objectTable );\n\tREQUIRES_MUTEX( isInUse( objectHandle ) && \\\n\t\t\t\t\tisObjectOwner( objectHandle ), objectTable );\n\n\t/* Perform similar access checks to the ones performed in\n\t   krnlSendMessage(), as well as situation-specific additional checks \n\t   for correct object types */\n#ifndef CONFIG_FUZZ\t\t/* To directly inject data into objects */\n\tstatus = checkAccessValid( objectHandle, checkType, \n\t\t\t\t\t\t\t   CRYPT_ERROR_PERMISSION );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tTHREAD_NOTIFY_CANCELLED( objectHandle );\n\t\tretIntError_Ext( status );\n\t\t}\n#endif /* CONFIG_FUZZ */\n\n\t/* Perform additional checks for correct object types.  The ownership \n\t   check in checkAccessValid() simply checks whether the current thread \n\t   is the overall object owner, isObjectOwner() checks whether the \n\t   current thread owns the lock on the object */\n\tif( !isInUse( objectHandle ) || !isObjectOwner( objectHandle ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tTHREAD_NOTIFY_CANCELLED( objectHandle );\n\t\tretIntError_Ext( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* It's a valid object, get its info */\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\tREQUIRES_MUTEX( sanityCheckObject( objectInfoPtr ), objectTable );\n\n\t/* If it was an external access to certificate/device info or an \n\t   internal access to the object's keying data, decrement the object's \n\t   reference count to allow others access again */\n\tif( checkType == ACCESS_CHECK_EXTACCESS || \\\n\t\tcheckType == ACCESS_CHECK_KEYACCESS )\n\t\t{\n\t\tSTORE_ORIGINAL_INT( lockCount, objectInfoPtr->lockCount );\n\n\t\tobjectInfoPtr->lockCount--;\n\n\t\t/* Postcondition: The object's lock count has been decremented and \n\t\t   is non-negative */\n\t\tENSURES_MUTEX( objectInfoPtr->lockCount == \\\n\t\t\t\t\t\t\tORIGINAL_VALUE( lockCount ) - 1, objectTable );\n\t\tENSURES_MUTEX( isIntegerRange( objectInfoPtr->lockCount ), \\\n\t\t\t\t\t   objectTable );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an external access to free the object for access by others, \n\t\t   clear the reference count */\n\t\tREQUIRES_MUTEX( checkType == ACCESS_CHECK_SUSPEND, objectTable );\n\n\t\t*refCount = objectInfoPtr->lockCount;\n\t\tobjectInfoPtr->lockCount = 0;\n\n\t\t/* Postcondition: The object has been completely released */\n\t\tENSURES_MUTEX( !isInUse( objectHandle ), objectTable );\n\t\t}\n\n\tMUTEX_UNLOCK( objectTable );\n\tTHREAD_NOTIFY_RELEASED( objectHandle );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL \\\nint initObjectAltAccess( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n\nvoid endObjectAltAccess( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDirect Object Access Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Acquire/release an object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint krnlAcquireObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t   IN_ENUM( OBJECT_TYPE ) const OBJECT_TYPE type,\n\t\t\t\t\t   OUT_PTR_COND void **objectPtr, \n\t\t\t\t\t   IN_ERROR const int errorCode )\n\t{\n\tREQUIRES( objectPtr != NULL );\t/* getObject() allows it to be NULL */\n\t\n\treturn( getObject( objectHandle, type, ACCESS_CHECK_EXTACCESS, \n\t\t\t\t\t   objectPtr, CRYPT_UNUSED, errorCode ) );\n\t}\n\nRETVAL \\\nint krnlReleaseObject( IN_HANDLE const int objectHandle )\n\t{\n\treturn( releaseObject( objectHandle, ACCESS_CHECK_EXTACCESS, NULL ) );\n\t}\n\n/* Temporarily suspend use of an object to allow other threads access, and\n   resume object use afterwards.  Note that PREfast will erroneously report \n   'attributes inconsistent with previous declaration' for these two \n   functions */\n\nRETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint krnlSuspendObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t   OUT_INT_Z int *refCount )\n\t{\n\treturn( releaseObject( objectHandle, ACCESS_CHECK_SUSPEND, refCount ) );\n\t}\n\nCHECK_RETVAL \\\nint krnlResumeObject( IN_HANDLE const int objectHandle, \n\t\t\t\t\t  IN_INT_Z const int refCount )\n\t{\n\treturn( getObject( objectHandle, \n\t\t\t\t\t   ( objectHandle == SYSTEM_OBJECT_HANDLE ) ? \\\n\t\t\t\t\t\t OBJECT_TYPE_DEVICE : OBJECT_TYPE_USER, \n\t\t\t\t\t   ACCESS_CHECK_SUSPEND, NULL, refCount, \n\t\t\t\t\t   CRYPT_ERROR_FAILED ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Extract Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The cryptlib equivalent of trusted downgraders in other security models:\n   Functions that extract a key from a context.  These functions need to\n   bypass the kernel's security checking in order to allow key export and\n   are the only ones that can do this.  This is an unavoidable requirement\n   in the complete-isolation model - some bypass mechanism needs to be\n   present in order to allow a key to be exported from an encryption action\n   object.  The three functions that perform the necessary operations are:\n\n\textractKeyData: Extract a session key from a conventional/MAC/generic-\n\t\t\t\t\tsecret context prior to encryption with a KEK.\n\texportPrivateKey: Write private key data to a stream prior to encryption\n\t\t\t\t\t  with a KEK.\n\timportPrivateKey: Read private key data from a stream after decryption\n\t\t\t\t\t  with a KEK.  We use this rather than a generic \n\t\t\t\t\t  external private key load to avoid having the key \n\t\t\t\t\t  marked as an untrusted user-set key, and also because\n\t\t\t\t\t  it's easier to read the key data directly into the\n\t\t\t\t\t  context's bignum storage rather than adding indirection\n\t\t\t\t\t  via a CRYPT_PKCINFO_xxx structure */\n\n#define PKC_CONTEXT\t\t/* Indicate that we're working with PKC context */\n#if defined( INC_ALL )\n  #include \"context.h\"\n  #include \"mech_int.h\"\n#else\n  #include \"context/context.h\"\n  #include \"mechs/mech_int.h\"\n#endif /* Compiler-specific includes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint extractKeyData( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t\tOUT_BUFFER_FIXED( keyDataLen ) void *keyData, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keyDataLen, \n\t\t\t\t\tIN_BUFFER( accessKeyLen ) const char *accessKey, \n\t\t\t\t\tIN_LENGTH_FIXED( 7 ) const int accessKeyLen )\n\t{\n\tCONTEXT_INFO *contextInfoPtr;\n\tint status;\n\n\tassert( isWritePtrDynamic( keyData, keyDataLen ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( keyDataLen >= MIN_KEYSIZE && keyDataLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( accessKeyLen == 7 );\n\n\t/* Clear return values */\n\tmemset( keyData, 0, keyDataLen );\n\n\t/* Make sure that we really intended to call this function */\n\tENSURES( accessKeyLen == 7 && !memcmp( accessKey, \"keydata\", 7 ) );\n\n\t/* Make sure that we've been given a conventional encryption, MAC, or\n\t   generic-secret context with a key loaded.  This has already been \n\t   checked at a higher level, but we perform a sanity check here to be \n\t   safe */\n\tstatus = getObject( iCryptContext, OBJECT_TYPE_CONTEXT,\n\t\t\t\t\t\tACCESS_CHECK_KEYACCESS,\n\t\t\t\t\t\t( void ** ) &contextInfoPtr, CRYPT_UNUSED, \n\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ( contextInfoPtr->type != CONTEXT_CONV && \\\n\t\t  contextInfoPtr->type != CONTEXT_MAC && \\\n\t\t  contextInfoPtr->type != CONTEXT_GENERIC ) || \\\n\t\t!TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET ) )\n\t\t{\n\t\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\t/* Export the key data from the context */\n\tswitch( contextInfoPtr->type )\n\t\t{\n\t\tcase CONTEXT_CONV:\n\t\t\tif( contextInfoPtr->ctxConv->userKeyLength < MIN_KEYSIZE || \\\n\t\t\t\tcontextInfoPtr->ctxConv->userKeyLength > keyDataLen )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Conventional-encryption key data is too long \"\n\t\t\t\t\t\t\t \"to export\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tREQUIRES( rangeCheck( contextInfoPtr->ctxConv->userKeyLength,\n\t\t\t\t\t\t\t\t\t  1, keyDataLen ) );\n\t\t\t\tmemcpy( keyData, contextInfoPtr->ctxConv->userKey,\n\t\t\t\t\t\tcontextInfoPtr->ctxConv->userKeyLength );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CONTEXT_MAC:\n\t\t\tif( contextInfoPtr->ctxMAC->userKeyLength < MIN_KEYSIZE || \\\n\t\t\t\tcontextInfoPtr->ctxMAC->userKeyLength > keyDataLen )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"MAC key data is too long to export\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tREQUIRES( rangeCheck( contextInfoPtr->ctxMAC->userKeyLength,\n\t\t\t\t\t\t\t\t\t  1, keyDataLen ) );\n\t\t\t\tmemcpy( keyData, contextInfoPtr->ctxMAC->userKey,\n\t\t\t\t\t\tcontextInfoPtr->ctxMAC->userKeyLength );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase CONTEXT_GENERIC:\n\t\t\tif( contextInfoPtr->ctxGeneric->genericSecretLength < MIN_KEYSIZE || \\\n\t\t\t\tcontextInfoPtr->ctxGeneric->genericSecretLength > keyDataLen )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Generic key data is too long to export\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tREQUIRES( rangeCheck( contextInfoPtr->ctxGeneric->genericSecretLength,\n\t\t\t\t\t\t\t\t\t  1, keyDataLen ) );\n\t\t\t\tmemcpy( keyData, contextInfoPtr->ctxGeneric->genericSecret,\n\t\t\t\t\t\tcontextInfoPtr->ctxGeneric->genericSecretLength );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 6 ) ) \\\nint exportPrivateKeyData( OUT_BUFFER_OPT( privKeyDataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t  *privKeyDataLength ) \\\n\t\t\t\t\t\t\tvoid *privKeyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int privKeyDataMaxLength,\n\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *privKeyDataLength,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t  IN_BUFFER( accessKeyLen ) const char *accessKey, \n\t\t\t\t\t\t  IN_LENGTH_FIXED( 11 ) const int accessKeyLen )\n\t{\n\tCONTEXT_INFO *contextInfoPtr;\n\tPKC_WRITEKEY_FUNCTION writePrivateKeyFunction;\n\tSTREAM stream;\n\tint status;\n\n\tassert( ( privKeyData == NULL && privKeyDataMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( privKeyData, privKeyDataMaxLength ) );\n\tassert( isWritePtr( privKeyDataLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( accessKey, accessKeyLen ) );\n\n\tREQUIRES( ( privKeyData == NULL && privKeyDataMaxLength == 0 ) || \\\n\t\t\t  ( privKeyData != NULL && \\\n\t\t\t\tprivKeyDataMaxLength >= 32 && \\\n\t\t\t\tprivKeyDataMaxLength < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\tREQUIRES( accessKeyLen == 11 );\n\n\t/* Clear return value */\n\t*privKeyDataLength = 0;\n\n\t/* Make sure that we really intended to call this function */\n\tENSURES( accessKeyLen == 11 && !memcmp( accessKey, \"private_key\", 11 ) );\n\n\t/* Make sure that we've been given a PKC context with a private key\n\t   loaded.  This has already been checked at a higher level, but we\n\t   perform a sanity check here to be safe */\n\tstatus = getObject( iCryptContext, OBJECT_TYPE_CONTEXT, \n\t\t\t\t\t\tACCESS_CHECK_KEYACCESS,\n\t\t\t\t\t\t( void ** ) &contextInfoPtr, CRYPT_UNUSED, \n\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( contextInfoPtr->type != CONTEXT_PKC || \\\n\t\t!TEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET ) || \\\n\t\tTEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY ) )\n\t\t{\n\t\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\twritePrivateKeyFunction = ( PKC_WRITEKEY_FUNCTION ) \\\n\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->writePrivateKeyFunction );\n\tif( writePrivateKeyFunction == NULL )\n\t\t{\n\t\t/* We have to use a bit of a nonstandard checking process here \n\t\t   because a standard throw-exception check won't release the\n\t\t   object, so we synthesize a \n\t\t   REQUIRES( writePrivateKeyFunction != NULL ) that also \n\t\t   releases the object */\n\t\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\t\tREQUIRES( writePrivateKeyFunction != NULL );\n\t\t}\n\n\t/* Export the key data from the context */\n\tif( privKeyData == NULL )\n\t\tsMemNullOpen( &stream );\n\telse\n\t\tsMemOpen( &stream, privKeyData, privKeyDataMaxLength );\n\tstatus = writePrivateKeyFunction( &stream, contextInfoPtr, formatType, \n\t\t\t\t\t\t\t\t\t  accessKey, accessKeyLen );\n\tif( cryptStatusOK( status ) )\n\t\t*privKeyDataLength = stell( &stream );\n\tif( privKeyData == NULL )\n\t\tsMemClose( &stream );\n\telse\n\t\tsMemDisconnect( &stream );\n\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importPrivateKeyData( IN_BUFFER( privKeyDataLen ) const void *privKeyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int privKeyDataLen,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType )\n\t{\n\tCONTEXT_INFO *contextInfoPtr;\n\tPKC_READKEY_FUNCTION readPrivateKeyFunction;\n\tCTX_LOADKEY_FUNCTION loadKeyFunction;\n\tPKC_CALCULATEKEYID_FUNCTION calculateKeyIDFunction;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtrDynamic( privKeyData, privKeyDataLen ) );\n\n\tREQUIRES( privKeyDataLen >= 32 && privKeyDataLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isEnumRange( formatType, KEYFORMAT ) );\n\n\t/* Make sure that we've been given a PKC context with no private key\n\t   loaded.  This has already been checked at a higher level, but we\n\t   perform a sanity check here to be safe */\n\tstatus = getObject( iCryptContext, OBJECT_TYPE_CONTEXT, \n\t\t\t\t\t\tACCESS_CHECK_KEYACCESS,\n\t\t\t\t\t\t( void ** ) &contextInfoPtr, CRYPT_UNUSED, \n\t\t\t\t\t\tCRYPT_ARGERROR_OBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( contextInfoPtr->type != CONTEXT_PKC || \\\n\t\tTEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET ) || \\\n\t\tTEST_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_ISPUBLICKEY ) )\n\t\t{\n\t\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\treadPrivateKeyFunction = ( PKC_READKEY_FUNCTION ) \\\n\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->readPrivateKeyFunction );\n\tloadKeyFunction = ( CTX_LOADKEY_FUNCTION ) \\\n\t\t\tFNPTR_GET( contextInfoPtr->loadKeyFunction );\n\tcalculateKeyIDFunction = ( PKC_CALCULATEKEYID_FUNCTION ) \\\n\t\t\tFNPTR_GET( contextInfoPtr->ctxPKC->calculateKeyIDFunction );\n\tif( readPrivateKeyFunction == NULL || loadKeyFunction == NULL || \\\n\t\tcalculateKeyIDFunction == NULL )\n\t\t{\n\t\t/* We can't use a standard REQUIRES() here because it won't release \n\t\t   the object, so we need to manually perform the equivalent */\n\t\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\t\tretIntError();\n\t\t}\n\n\t/* Import the key data into the context */\n\tsMemConnect( &stream, privKeyData, privKeyDataLen );\n\tstatus = readPrivateKeyFunction( &stream, contextInfoPtr, formatType, \n\t\t\t\t\t\t\t\t\t FALSE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* If everything went OK, perform an internal load that uses the\n\t\t   values already present in the context */\n\t\tstatus = loadKeyFunction( contextInfoPtr, NULL, 0 );\n\t\tif( cryptStatusOK( status ) && formatType == KEYFORMAT_PRIVATE_OLD )\n\t\t\t{\n\t\t\t/* This format is unusual in that it stores the public-key data \n\t\t\t   in encrypted form alongside the private-key data, so that the \n\t\t\t   public key is read as part of the private key rather than \n\t\t\t   being set as a CRYPT_IATTRIBUTE_KEY_xxx_PARTIAL attribute.  \n\t\t\t   Because of this it bypasses the standard keyID-calculation\n\t\t\t   process that occurs on public-key load, so we have to \n\t\t\t   explicitly calculate the keyID data here */\n\t\t\tstatus = calculateKeyIDFunction( contextInfoPtr );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && formatType == KEYFORMAT_PRIVATE )\n\t\t\t{\n\t\t\t/* The in-memory key components are now checksummed (via \n\t\t\t   loadKeyFunction()), if the format supports it verify that the \n\t\t\t   components correspond to the original key data.  This is done\n\t\t\t   by performing a dummy read of the key data that compares it\n\t\t\t   against what was previously read */\n\t\t\tsMemConnect( &stream, privKeyData, privKeyDataLen );\n\t\t\tstatus = readPrivateKeyFunction( &stream, contextInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t formatType, TRUE );\n\t\t\tsMemDisconnect( &stream );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tkrnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_INITIALISED );\n\t\t\tSET_FLAG( contextInfoPtr->flags, CONTEXT_FLAG_KEY_SET );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If the problem was indicated as a function argument error, \n\t\t\t   map it to a more appropriate code.  The most appropriate code \n\t\t\t   at this point is CRYPT_ERROR_INVALID since a bad-data error \n\t\t\t   will be returned as an explicit CRYPT_ERROR_BADDATA while a \n\t\t\t   parameter error indicates that one or more of the key \n\t\t\t   components failed a validity check */\n\t\t\tif( cryptArgError( status ) )\n\t\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t}\n\t\t}\n\treleaseObject( iCryptContext, ACCESS_CHECK_KEYACCESS, NULL );\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/objects.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKernel Object Management\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* Define the following to use fixed (deterministic) object handles.  This\n   orders object handles sequentially, making it easier to pin down \n   approximately where/when a leftover objects was created, as well as\n   ensuring that handles have consistent values across runs */\n\n/* #define USE_FIXED_OBJECTHANDLES */\n\n/* A template used to initialise object table entries.  Some of the entries\n   are either object handles that have to be set to CRYPT_ERROR or values\n   for which 0 is significant (so they're set to CRYPT_UNUSED), because of\n   this we can't just memset the entry to all zeroes */\n\nstatic const OBJECT_INFO OBJECT_INFO_TEMPLATE = {\n\tOBJECT_TYPE_NONE, SUBTYPE_NONE,\t/* Type, subtype */\n\tDATAPTR_INIT, 0,\t\t\t/* Object data and size */\n\tSAFE_FLAGS_INIT( OBJECT_FLAG_INTERNAL | OBJECT_FLAG_NOTINITED ),\t\n\t\t\t\t\t\t\t\t/* Flags */\n\t0,\t\t\t\t\t\t\t/* Action flags */\n\t1, 0, 0,\t\t\t\t\t/* Int.and ext. ref.counts, lock count */\n#ifdef USE_THREADS\n\tTHREAD_INITIALISER,\t\t\t/* Lock owner */\n#endif /* USE_THREADS */\n\t0,\t\t\t\t\t\t\t/* Unique ID */\n\tCRYPT_UNUSED, CRYPT_UNUSED,\t/* Forward count, usage count */\n#ifdef USE_THREADS\n\tTHREAD_INITIALISER,\t\t\t/* Owner */\n#endif /* USE_THREADS */\n\tFNPTR_INIT,\t\t\t\t\t/* Message function */\n\tCRYPT_ERROR,\t\t\t\t/* Owner */\n\tCRYPT_ERROR, CRYPT_ERROR\t/* Dependent object/device */\n\t};\n\n/* When we use the template to clear an object table entry we can't directly\n   assign the template to the position that we want to clear because there\n   may be padding bytes appended to the struct for alignment purposes.  What\n   this means is that saying:\n\n\tobjectTable[ index ] = OBJECT_INFO_TEMPLATE;\n\n   will leave the padding bytes at the end of the struct untouched.  \n   Technically this isn't really an issue because the bytes are effectively\n   invisible, but it's somewhat ugly so we define a macro to carry out the\n   assignment which uses a memcpy() of the sizeof struct, which includes the\n   padding bytes */\n\n#define CLEAR_TABLE_ENTRY( entry ) \\\n\t\tmemcpy( ( entry ), &OBJECT_INFO_TEMPLATE, sizeof( OBJECT_INFO ) )\n\n/* LFSR parameters for selcting the next object handle */\n\n#define LFSR_MASK\t\t\t\tMAX_NO_OBJECTS\n#if MAX_NO_OBJECTS == 128\n  #define LFSRPOLY\t\t\t\t0x83\n#elif MAX_NO_OBJECTS == 256\n  #define LFSRPOLY\t\t\t\t0x11D\n#elif MAX_NO_OBJECTS == 512\n  #define LFSRPOLY\t\t\t\t0x211\n#elif MAX_NO_OBJECTS == 1024\n  #define LFSRPOLY\t\t\t\t0x409\n#elif MAX_NO_OBJECTS == 2048\n  #define LFSRPOLY\t\t\t\t0x805\n#elif MAX_NO_OBJECTS == 4096\n  #define LFSRPOLY\t\t\t\t0x1053\n#elif MAX_NO_OBJECTS == 8192\n  #define LFSRPOLY\t\t\t\t0x201B\n#elif MAX_NO_OBJECTS == 16384\n  #define LFSRPOLY\t\t\t\t0x402B\n#elif MAX_NO_OBJECTS == 32768\n  #define LFSRPOLY\t\t\t\t0x8003L\n#elif MAX_NO_OBJECTS == 65536\n  #define LFSRPOLY\t\t\t\t0x1002DL\n  /* Further LFSR polynomials are 0x20009L, 0x40027L, 0x80027L, 0x100009L, \n     0x200005L, 0x400003L, ... */\n#endif /* LFSR polynomial for object table size */\n\n/* A template used to initialise the object allocation state data */\n\nstatic const OBJECT_STATE_INFO OBJECT_STATE_INFO_TEMPLATE = {\n\t-1\t\t\t\t\t\t\t/* Initial-1'th object handle */\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create and destroy the object table.  The destroy process is handled in\n   two stages, the first of which is called fairly early in the shutdown\n   process to destroy any remaining objects, and the second which is called\n   at the end of the shutdown when the kernel data is being deleted.  This\n   is because some of the objects are tied to things like external devices,\n   and deleting them at the end when everything else has been shut down\n   isn't possible */\n\nCHECK_RETVAL \\\nint initObjects( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tint i, status, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on various things that need to be set\n\t   up in a certain way for things to work properly */\n\tstatic_assert( MAX_NO_OBJECTS >= 64, \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.type == OBJECT_TYPE_NONE, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.subType == 0, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( DATAPTR_GET( OBJECT_INFO_TEMPLATE.objectPtr ) == NULL, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.objectSize == 0, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( CHECK_FLAGS( OBJECT_INFO_TEMPLATE.flags, \\\n\t\t\t\t\t\t\t\t\tOBJECT_FLAG_NONE, OBJECT_FLAG_MAX ), \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( GET_FLAGS( OBJECT_INFO_TEMPLATE.flags, OBJECT_FLAG_MAX ) == \\\n\t\t\t\t\t\t\t( OBJECT_FLAG_INTERNAL | OBJECT_FLAG_NOTINITED ), \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.actionFlags == 0, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.forwardCount == CRYPT_UNUSED, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.usageCount == CRYPT_UNUSED, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.owner == CRYPT_ERROR, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.dependentDevice == CRYPT_ERROR, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert_opt( OBJECT_INFO_TEMPLATE.dependentObject == CRYPT_ERROR, \\\n\t\t\t\t\t   \"Object table param\" );\n\tstatic_assert( SYSTEM_OBJECT_HANDLE == NO_SYSTEM_OBJECTS - 2, \\\n\t\t\t\t   \"Object table param\" );\n\tstatic_assert( DEFAULTUSER_OBJECT_HANDLE == NO_SYSTEM_OBJECTS - 1, \\\n\t\t\t\t   \"Object table param\" );\n\n\t/* Allocate and initialise the object table */\n\tLOOP_EXT( i = 0, i < MAX_NO_OBJECTS, i++, MAX_NO_OBJECTS + 1 )\n\t\t{\n\t\tCLEAR_TABLE_ENTRY( &objectTable[ i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tkrnlData->objectStateInfo = OBJECT_STATE_INFO_TEMPLATE;\n\n\t/* Initialise object-related information.  This isn't strictly part of\n\t   the object table but is used to assign unique ID values to objects\n\t   within the table, since table entries (object handles) may be reused\n\t   as objects are destroyed and new ones created in their place */\n\tkrnlData->objectUniqueID = 0;\n\n\t/* Initialize any data structures required to make the object table\n\t   thread-safe */\n\tMUTEX_CREATE( objectTable, status );\n\tif( cryptStatusError( status ) )\n\t\tretIntError();\n\n\t/* Postconditions */\n\tFORALL( i, 0, MAX_NO_OBJECTS, \\\n\t\t\t!memcmp( &objectTable[ i ], &OBJECT_INFO_TEMPLATE, \\\n\t\t\t\t\t sizeof( OBJECT_INFO ) ) );\n\tENSURES( krnlData->objectStateInfo.objectHandle == SYSTEM_OBJECT_HANDLE - 1 );\n\tENSURES( krnlData->objectUniqueID == 0 );\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid endObjects( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable();\n\n\t/* Hinc igitur effuge */\n\tMUTEX_LOCK( objectTable );\n\tzeroise( objectTable, MAX_NO_OBJECTS * sizeof( OBJECT_INFO ) );\n\tkrnlData->objectUniqueID = 0;\n\tMUTEX_UNLOCK( objectTable );\n\tMUTEX_DESTROY( objectTable );\n\tkrnlData = NULL;\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Table Management\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Destroy an object's instance data and object table entry */\n\nCHECK_RETVAL \\\nint destroyObjectData( IN_HANDLE const int objectHandle )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_INFO *objectInfoPtr;\n\tvoid *objectPtr;\n\tint status;\n\n\t/* Precondition: It's a valid object */\n\tREQUIRES( isValidObject( objectHandle ) );\n\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tobjectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\n\t/* Inner precondition: There's valid object data present */\n\tREQUIRES( objectPtr != NULL );\n\tREQUIRES( objectInfoPtr->objectSize > 0 && \\\n\t\t\t  objectInfoPtr->objectSize < MAX_BUFFER_SIZE );\n\n\t/* Destroy the object's data and clear the object table entry */\n\tif( TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_SECUREMALLOC ) )\n\t\t{\n\t\tstatus = krnlMemfree( &objectPtr );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\telse\n\t\t{\n\t\t/* Mors ultima linea rerum est */\n\t\tzeroise( objectPtr, objectInfoPtr->objectSize );\n\t\tif( !TEST_FLAG( objectInfoPtr->flags, OBJECT_FLAG_STATICALLOC ) ) \n\t\t\tclFree( \"destroyObjectData\", objectPtr );\n\t\t}\n\tCLEAR_TABLE_ENTRY( &objectTable[ objectHandle ] );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Destroy an object.  This is only called when cryptlib is shutting down,\n   normally objects are destroyed directly in response to messages */\n\nCHECK_RETVAL \\\nstatic int destroyObject( IN_HANDLE const int objectHandle )\n\t{\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr;\n\tMESSAGE_FUNCTION messageFunction;\n\n\t/* Precondition: It's a valid object */\n\tREQUIRES( isValidObject( objectHandle ) );\n\n\t/* Get the object info and message function.  We don't throw an \n\t   exception if there's a problem with recovering the message function\n\t   (although we do assert in debug mode) because there's not much that \n\t   we can do for error recovery at this point, we just skip the object-\n\t   specific cleanup and go straight to the object cleanup */\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tmessageFunction = ( MESSAGE_FUNCTION ) \\\n\t\t\t\t\t  FNPTR_GET( objectInfoPtr->messageFunction );\n\n\t/* If there's no object present at this position, just clear the entry \n\t   (it should be cleared anyway) */\n\tif( objectInfoPtr->type == OBJECT_TYPE_NONE )\n\t\t{\n\t\tCLEAR_TABLE_ENTRY( &objectTable[ objectHandle ] );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tassert( messageFunction != NULL );\n\n\t/* Destroy the object and its object table entry */\n\tif( messageFunction != NULL )\n\t\t{\n\t\tvoid *objectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\n\t\tENSURES( objectPtr != NULL );\n\n\t\tif( objectInfoPtr->type == OBJECT_TYPE_DEVICE )\n\t\t\t{\n\t\t\tMESSAGE_FUNCTION_EXTINFO messageExtInfo;\n\n\t\t\t/* Device objects are unlockable so we have to pass in extended \n\t\t\t   information to handle this */\n\t\t\tinitMessageExtInfo( &messageExtInfo, objectPtr );\n\t\t\tmessageFunction( &messageExtInfo, MESSAGE_DESTROY, NULL, 0 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tmessageFunction( objectPtr, MESSAGE_DESTROY, NULL, 0 );\n\t\t\t}\n\t\t}\n\treturn( destroyObjectData( objectHandle ) );\n\t}\n\n/* Destroy all objects at a given nesting level */\n\nCHECK_RETVAL \\\nstatic int destroySelectedObjects( IN_RANGE( 1, 3 ) const int currentDepth )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint objectHandle, status = CRYPT_OK, LOOP_ITERATOR;\n\n\t/* Preconditions: We're destroying objects at a fixed depth */\n\tREQUIRES( currentDepth >= 1 && currentDepth <= 3 );\n\n\tLOOP_EXT( objectHandle = NO_SYSTEM_OBJECTS,\n\t\t\t  objectHandle < MAX_NO_OBJECTS,\n\t\t\t  objectHandle++, MAX_NO_OBJECTS + 1 )\n\t\t{\n\t\tconst int dependentObject = \\\n\t\t\t\t\t\tobjectTable[ objectHandle ].dependentObject;\n\t\tint depth = 1;\n\n\t\t/* If there's nothing there, continue.  In this case we don't \n\t\t   perform a REQUIRES( DATAPTR_VALID() ) because we don't want a \n\t\t   single corrupted pointer to prevent the cleanup of the entire \n\t\t   object table */\n\t\tif( !DATAPTR_ISSET( objectTable[ objectHandle ].objectPtr ) )\n\t\t\tcontinue;\n\n\t\t/* There's an object still present, determine its nesting depth.\n\t\t   Dependent devices are terminal so we only follow the path down for\n\t\t   dependent objects */\n\t\tif( isValidObject( dependentObject ) )\n\t\t\t{\n\t\t\tif( isValidObject( objectTable[ dependentObject ].dependentObject ) )\n\t\t\t\tdepth = 3;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( isValidObject( objectTable[ dependentObject ].dependentDevice ) )\n\t\t\t\t\tdepth = 2;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( isValidObject( objectTable[ objectHandle ].dependentDevice ) )\n\t\t\t\tdepth = 2;\n\t\t\t}\n\n\t\t/* If the nesting level of the object matches the current level,\n\t\t   destroy it.  We unlock the object table around the access to\n\t\t   prevent remaining active objects from blocking the shutdown (the\n\t\t   activation of krnlIsExiting() takes care of any other messages \n\t\t   that may arrive during this process).\n\n\t\t   \"For death is come up into our windows, and it is entered into\n\t\t    our palaces, to cut off the children from the without\"\n\t\t\t-- Jeremiah 9:21 */\n\t\tif( depth >= currentDepth )\n\t\t\t{\n\t\t\tKERNEL_DATA *krnlData = getKrnlData();\n\n\t\t\tDEBUG_DIAG(( \"Destroying leftover %s\", \n\t\t\t\t\t\t getObjectDescriptionNT( objectHandle ) ));\n\t\t\tobjectTable = NULL;\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\tkrnlSendNotifier( objectHandle, IMESSAGE_DESTROY );\n\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\tMUTEX_LOCK( objectTable );\n\t\t\tobjectTable = getObjectTable();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( objectHandle <= MAX_NO_OBJECTS );\n\n\treturn( status );\n\t}\n\n/* Destroy all objects (homini necesse est mori) */\n\nCHECK_RETVAL \\\nint destroyObjects( void )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint depth, objectHandle, localStatus, status DUMMY_INIT, LOOP_ITERATOR;\n\n\t/* Preconditions: We either didn't complete the initialisation and are \n\t   shutting down during a krnlBeginInit(), or we've completed \n\t   initialisation and are shutting down after a krnlBeginShutdown() */\n\tREQUIRES( ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\tkrnlData->shutdownLevel == SHUTDOWN_LEVEL_NONE ) || \\\n\t\t\t  ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\tkrnlData->shutdownLevel == SHUTDOWN_LEVEL_THREADS ) );\n\n\t/* Indicate that we're shutting down the object handling.  From now on\n\t   all messages other than object-destruction ones will be rejected by\n\t   the kernel.  This is needed in order to have any remaining active\n\t   objects exit quickly, since we don't want them to block the shutdown.\n\t   Note that we do this before we lock the object table to encourage\n\t   anything that might have the table locked to exit quickly once we try\n\t   and lock the table */\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_MESSAGES;\n\n\t/* Lock the object table to ensure that other threads don't try to\n\t   access it */\n\tMUTEX_LOCK( objectTable );\n\n\t/* Destroy all system objects except the root system object (\"The death\n\t   of God left the angels in a strange position\" - Donald Barthelme, \"On\n\t   Angels\").  We have to do this before we destroy any unclaimed\n\t   leftover objects because some of them may depend on system objects,\n\t   if the system objects aren't destroyed they'll be erroneously flagged\n\t   as leftover objects.  The destruction is done explicitly by invoking\n\t   the object's message function directly because the message dispatcher\n\t   checks to make sure that they're never destroyed through a standard\n\t   message, which would indicate a programming error */\n\tLOOP_SMALL( objectHandle = SYSTEM_OBJECT_HANDLE + 1,\n\t\t\t\tobjectHandle < NO_SYSTEM_OBJECTS, objectHandle++ )\n\t\t{\n\t\t/* In the extremely unlikely event that we encounter an error during \n\t\t   the creation of the system object, no other objects will have been \n\t\t   created, so before we try and destroy an object we make sure that \n\t\t   it's actually been created */\n\t\tif( !isValidObject( objectHandle ) )\n\t\t\tcontinue;\n\n\t\tstatus = destroyObject( objectHandle );\n\t\tENSURES_MUTEX( cryptStatusOK( status ), objectTable );\n\t\t}\n\tENSURES_MUTEX( LOOP_BOUND_OK, objectTable );\n\n\t/* Postcondition: All system objects except the root system object have\n\t   been destroyed */\n\tFORALL( i, SYSTEM_OBJECT_HANDLE + 1, NO_SYSTEM_OBJECTS,\n\t\t\t!memcmp( &objectTable[ i ], &OBJECT_INFO_TEMPLATE, \\\n\t\t\t\t\t sizeof( OBJECT_INFO ) ) );\n\n\t/* Delete any unclaimed leftover objects.  This is rather more complex\n\t   than just rumbling through deleting each object we find since some\n\t   objects have dependent objects underneath them, and deleting the\n\t   lower-level object causes problems when we later delete their parents\n\t   (the code handles it cleanly, but we get a kernel trap warning us that\n\t   we're trying to delete a non-present object).  Because of this we have\n\t   to delete the objects in order of depth, first all three-level objects\n\t   (e.g. cert -> context -> device), then all two-level objects, and\n\t   finally all one-level objects.  This means that we can never delete\n\t   another object out from under a dependent object */\n\tLOOP_SMALL( depth = 3, depth > 0, depth-- )\n\t\t{\n\t\tlocalStatus = destroySelectedObjects( depth );\n\t\tif( cryptStatusError( localStatus ) )\n\t\t\tstatus = localStatus;\n\t\t}\n\tENSURES_MUTEX( LOOP_BOUND_OK, objectTable );\n\n\t/* Postcondition: All objects except the root system object have been\n\t   destroyed */\n\tFORALL( i, SYSTEM_OBJECT_HANDLE + 1, MAX_NO_OBJECTS, \\\n\t\t\t!memcmp( &objectTable[ i ], &OBJECT_INFO_TEMPLATE, \\\n\t\t\t\t\t sizeof( OBJECT_INFO ) ) );\n\n\t/* Finally, destroy the system root object.  We need to preserve the \n\t   possible error status from cleaning up any leftover objects so we use \n\t   a local status value to get the destroy-object results */\n\tlocalStatus = destroyObject( SYSTEM_OBJECT_HANDLE );\n\tENSURES_MUTEX( cryptStatusOK( localStatus ), objectTable );\n\n\t/* Unlock the object table to allow access by other threads */\n\tMUTEX_UNLOCK( objectTable );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tObject Creation/Destruction\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a new object.  This function has to be very careful about locking\n   to ensure that another thread can't manipulate the newly-created object\n   while it's in an indeterminate state.  To accomplish this it locks the\n   object table and tries to create the new object.  If this succeeds it sets\n   the OBJECT_FLAG_NOTINITED flag pending completion of the object's\n   initialisation by the caller, unlocks the object table, and returns\n   control to the caller.  While the object is in this state, the kernel\n   will allow it to process only two message types, either a notification\n   from the caller that the init stage is complete (which sets the object's\n   state to OK), or a destroy object message, which sets the\n   OBJECT_FLAG_SIGNALLED flag pending arrival of the init complete\n   notification, whereupon the object is immediately destroyed.  The state\n   diagram for this is:\n\t\t\t\t\t\t\t\t\t State\n\t\t\t\t\t\t  Notinited\t\t\tSignalled\n\t\t\t--------+-------------------+-----------------\n\t\t\t-> OK\t| state -> OK,\t\t| Msg -> Destroy\n\t\t\t\t\t| ret( OK )\t\t\t|\n\tMsg.\tDestroy\t| state -> Sig'd,\t| state -> Sig'd,\n\t\t\t\t\t| ret( OK )\t\t\t| ret( OK )\n\t\t\tCtrlMsg\t| process as usual\t| process as usual\n\t\t\tNonCtrl\t| ret( Notinited )\t| ret( Sig'd )\n\n   The initialisation process for an object is therefore:\n\n\tstatus = krnlCreateObject( ... );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t// Complete object-specific initialisation\n\tinitStatus = ...;\n\n\tstatus = krnlSendMessage( ..., state -> CRYPT_OK );\n\treturn( ( cryptStatusError( initStatus ) ? initStatus : status );\n\n   If the object is destroyed during the object-specific initialisation\n   (either by the init code when an error is encountered or due to an\n   external signal), the destroy is deferred until the change state message\n   at the end occurs.  If a destroy is pending, the change state is converted\n   to a destroy and the newly-created object is destroyed.\n\n   This mechanism ensures that the object table is only locked for a very\n   short time (typically for only a few lines of executed code in the create\n   object function) so that slow initialisation (for example of keyset\n   objects associated with network links) can't block other objects.\n\n   In addition to the locking, we need to be careful with how we create new\n   objects because if we just allocate handles sequentially and reuse handles\n   as soon as possible, an existing object could be signalled and a new one\n   created in its place without the caller or owning object realizing that\n   they're now working with a different object (although the kernel can tell\n   them apart because it maintains an internal unique ID for each object).\n   Unix systems handle this by always incrementing pids and assuming that\n   there won't be any problems when they wrap, we do the same thing but in\n   addition allocate handles in a non-sequential manner using an LFSR to\n   step through the object table.  There's no strong reason for this apart\n   from helping disabuse users of the notion that any cryptlib objects have\n   stdin/stdout-style fixed handles, but it only costs a few extra clocks so\n   we may as well do it.\n   \n   There is one case in which we can still get handle reuse and that's then \n   the object table is heavily loaded but not quite enough to trigger a \n   resize.  For example with a table of size 1024 if the caller creates 1023\n   objects and then repeatedly creates and destroys a final object it'll \n   always be reassigned the same handle if no other objects are destroyed in\n   the meantime.  This is rather unlikely unless the caller is using \n   individual low-level objects (all of the high-level objects create \n   object-table churn through their dependent objects) so it's not worth\n   adding special-case handling for it */\n\nCHECK_RETVAL_RANGE( NO_SYSTEM_OBJECTS, MAX_NO_OBJECTS ) \\\nstatic int findFreeObjectEntry( int value )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tBOOLEAN freeEntryAvailable = FALSE;\n\tint oldValue = value, iterations, LOOP_ITERATOR;\n\n\t/* Preconditions: We're starting with a valid object handle, and it's not\n\t   a system object */\n\tREQUIRES( isValidHandle( value ) );\n\tREQUIRES( value >= NO_SYSTEM_OBJECTS );\n\n\t/* Step through the entire table looking for a free entry */\n\tLOOP_EXT( iterations = 0, \n\t\t\t  isValidHandle( value ) && iterations < MAX_NO_OBJECTS, \n\t\t\t  iterations++, MAX_NO_OBJECTS + 1 )\n\t\t{\n\t\t/* Get the next value: Multiply by x and reduce by the polynomial */\n#ifdef USE_FIXED_OBJECTHANDLES\n\t\tvalue++;\n#else\n\t\tvalue <<= 1;\n\t\tif( value & LFSR_MASK )\n\t\t\tvalue ^= LFSRPOLY;\n#endif /* USE_FIXED_OBJECTHANDLES */\n\n\t\t/* Invariant: We're still within the object table */\n\t\tENSURES( isValidHandle( value ) );\n\n\t\t/* If we've found a free object or we've covered the entire table,\n\t\t   exit.  We do this check after we update the value rather than as\n\t\t   part of the loop test to ensure that we always progress to a new\n\t\t   object handle whenever we call this function.  If we did the\n\t\t   check as part of the loop test then deleting and creating an\n\t\t   object would result in the handle of the deleted object being\n\t\t   re-assigned to the new object */\n\t\tif( isFreeObject( value ) )\n\t\t\t{\n\t\t\t/* We've found a free entry, we're done */\n\t\t\tfreeEntryAvailable = TRUE;\n\t\t\tbreak;\n\t\t\t}\n\t\tif( value == oldValue )\n\t\t\t{\n\t\t\t/* We've covered the entire object table, there's no room for\n\t\t\t   further objects */\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( iterations < MAX_NO_OBJECTS )\n\n\t/* Postcondition: We're still within the object table */\n\tENSURES( isValidHandle( value ) );\n\n\t/* If we didn't find a free entry, tell the caller that the tank is \n\t   full */\n\tif( !freeEntryAvailable )\n\t\t{\n\t\t/* Postcondition: We tried all locations and there are no free slots\n\t\t   available (or, vastly less likely, an internal error has\n\t\t   occurred) */\n\t\tENSURES( iterations == MAX_NO_OBJECTS - 2 );\n\t\tFORALL( i, 0, MAX_NO_OBJECTS, \\\n\t\t\t\t!isFreeObject( i ) );\n\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* Postconditions: We found a handle to a free slot */\n\tENSURES( isFreeObject( value ) );\n\tENSURES( value >= NO_SYSTEM_OBJECTS );\n\n\treturn( value );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \\\nint krnlCreateObject( OUT_HANDLE_OPT int *objectHandle,\n\t\t\t\t\t  OUT_BUFFER_ALLOC_OPT( objectDataSize ) void **objectDataPtr, \n\t\t\t\t\t  IN_LENGTH_SHORT const int objectDataSize,\n\t\t\t\t\t  IN_ENUM( OBJECT_TYPE ) const OBJECT_TYPE type, \n\t\t\t\t\t  IN_ENUM( SUBTYPE ) const OBJECT_SUBTYPE subType,\n\t\t\t\t\t  IN_FLAGS_Z( CREATEOBJECT ) const int createObjectFlags, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_USER owner,\n\t\t\t\t\t  IN_FLAGS_Z( ACTION_PERM ) const int actionFlags,\n\t\t\t\t\t  IN MESSAGE_FUNCTION messageFunction )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable(), objectInfo;\n\tOBJECT_STATE_INFO *objectStateInfo = &krnlData->objectStateInfo;\n\tOBJECT_SUBTYPE bitCount;\n\tBOOLEAN isStaticAlloc = FALSE;\n\tint localObjectHandle, status = CRYPT_OK;\n\n\tassert( isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) );\n\tassert( isWritePtr( objectDataPtr, sizeof( void * ) ) );\n\n\t/* Preconditions (the subType check is just the standard hakmem bitcount\n\t   which ensures that we don't try and create multi-typed objects, the\n\t   sole exception to this rule is the default user object, which acts as\n\t   both a user and an SO object) */\n\tREQUIRES( objectDataSize > 16 && \\\n\t\t\t  ( ( !( type == OBJECT_TYPE_CONTEXT && subType == SUBTYPE_CTX_PKC ) && \\\n\t\t\t\tobjectDataSize < MAX_INTLENGTH_SHORT ) || \\\n\t\t\t  ( type == OBJECT_TYPE_CONTEXT && subType == SUBTYPE_CTX_PKC && \\\n\t\t\t\tobjectDataSize < MAX_INTLENGTH ) ) );\n\tREQUIRES( isValidType( type ) );\n\tREQUIRES( \\\n\t\t( bitCount = ( subType & ~SUBTYPE_CLASS_MASK ) - \\\n\t\t\t\t\t ( ( ( subType & ~SUBTYPE_CLASS_MASK ) >> 1 ) & 033333333333L ) - \\\n\t\t\t\t\t ( ( ( subType & ~SUBTYPE_CLASS_MASK ) >> 2 ) & 011111111111L ) ) != 0 );\n\tREQUIRES( ( ( bitCount + ( bitCount >> 3 ) ) & 030707070707L ) % 63 == 1 );\n\tREQUIRES( createObjectFlags >= CREATEOBJECT_FLAG_NONE && \\\n\t\t\t  createObjectFlags < CREATEOBJECT_FLAG_MAX );\n\tREQUIRES( !( createObjectFlags & \\\n\t\t\t\t ~( CREATEOBJECT_FLAG_SECUREMALLOC | CREATEOBJECT_FLAG_DUMMY | \\\n\t\t\t\t\tCREATEOBJECT_FLAG_PERSISTENT ) ) );\n\tREQUIRES( owner == CRYPT_UNUSED || isValidHandle( owner ) );\n\tREQUIRES( isFlagRangeZ( actionFlags, ACTION_PERM ) );\n\tREQUIRES( messageFunction != NULL );\n\n\t/* Clear return values */\n\t*objectHandle = CRYPT_ERROR;\n\t*objectDataPtr = NULL;\n\n\t/* If we haven't been initialised yet or we're in the middle of a\n\t   shutdown, we can't create any new objects */\n\tif( !isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) || \\\n\t\tkrnlData->initLevel <= INIT_LEVEL_NONE )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )\n\t\t{\n\t\tDEBUG_DIAG(( \"Can't create new objects during a shutdown\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Allocate memory for the object and set up as much as we can of the \n\t   object table entry (the remainder has to be set up inside the object-\n\t   table lock).  The object is always created as an internal object, \n\t   it's up to the caller to make it externally visible.\n\t   \n\t   The apparently redundant clearning of objectInfo before overwriting\n\t   it with the object-info template is due to yet another gcc bug, in\n\t   this case in the x64 debug (-o0) build, for which it doesn't memcpy()\n\t   the template across but sets each field individually, leaving \n\t   whatever padding bytes were present beforehand set to random values */\n\tif( objectStateInfo->objectHandle < NO_SYSTEM_OBJECTS - 1 )\n\t\t{\n\t\t/* This is either the system object or the default user object */\n\t\tREQUIRES( ( type == OBJECT_TYPE_DEVICE && \\\n\t\t\t\t\tsubType == SUBTYPE_DEV_SYSTEM ) || \\\n\t\t\t\t  ( type == OBJECT_TYPE_USER && \\\n\t\t\t\t    subType == SUBTYPE_USER_SO ) );\n\n\t\tif( type == OBJECT_TYPE_DEVICE )\n\t\t\t*objectDataPtr = getSystemDeviceStorage();\n\t\telse\n\t\t\t*objectDataPtr = getDefaultUserObjectStorage();\n\t\tisStaticAlloc = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tif( createObjectFlags & CREATEOBJECT_FLAG_SECUREMALLOC )\n\t\t\t{\n\t\t\tstatus = krnlMemalloc( objectDataPtr, objectDataSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( objectDataSize, 1, MAX_INTLENGTH ) );\n\t\t\tif( ( *objectDataPtr = clAlloc( \"krnlCreateObject\", \\\n\t\t\t\t\t\t\t\t\t\t\tobjectDataSize ) ) == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\t}\n\tassert( isWritePtrDynamic( *objectDataPtr, objectDataSize ) );\n\tmemset( *objectDataPtr, 0, objectDataSize );\n\tmemset( &objectInfo, 0, sizeof( OBJECT_INFO ) ); /* See comment above */\n\tobjectInfo = OBJECT_INFO_TEMPLATE;\n\tDATAPTR_SET( objectInfo.objectPtr, *objectDataPtr );\n\tobjectInfo.objectSize = objectDataSize;\n\tif( createObjectFlags & CREATEOBJECT_FLAG_SECUREMALLOC )\n\t\tSET_FLAG( objectInfo.flags, OBJECT_FLAG_SECUREMALLOC );\n\tif( isStaticAlloc )\n\t\tSET_FLAG( objectInfo.flags, OBJECT_FLAG_STATICALLOC );\n\tobjectInfo.owner = owner;\n\tobjectInfo.type = type;\n\tobjectInfo.subType = subType;\n\tobjectInfo.actionFlags = actionFlags;\n\tFNPTR_SET( objectInfo.messageFunction, messageFunction );\n\tENSURES( sanityCheckObject( &objectInfo ) );\n\n\t/* Make sure that the kernel has been initialised and lock the object\n\t   table for exclusive access */\n\tMUTEX_LOCK( initialisation );\n\tMUTEX_LOCK( objectTable );\n\tMUTEX_UNLOCK( initialisation );\n\n\t/* Finish setting up the object table entry with any remaining data */\n\tobjectInfo.uniqueID = krnlData->objectUniqueID;\n\n\t/* The first objects created are internal objects with predefined\n\t   handles (spes lucis aeternae).  As we create these objects we ratchet\n\t   up through the fixed handles until we reach the last fixed object,\n\t   whereupon we allocate handles normally */\n\tlocalObjectHandle = objectStateInfo->objectHandle;\n\tif( localObjectHandle < NO_SYSTEM_OBJECTS - 1 )\n\t\t{\n\t\tREQUIRES_MUTEX( ( localObjectHandle == SYSTEM_OBJECT_HANDLE - 1 && \\\n\t\t\t\t\t\t  owner == CRYPT_UNUSED && \\\n\t\t\t\t\t\t  type == OBJECT_TYPE_DEVICE && \\\n\t\t\t\t\t\t  subType == SUBTYPE_DEV_SYSTEM ) || \\\n\t\t\t\t\t\t( localObjectHandle == DEFAULTUSER_OBJECT_HANDLE - 1 && \\\n\t\t\t\t\t\t  owner == SYSTEM_OBJECT_HANDLE && \\\n\t\t\t\t\t\t  type == OBJECT_TYPE_USER && \\\n\t\t\t\t\t\t  subType == SUBTYPE_USER_SO ), \n\t\t\t\t\t\tobjectTable );\n\t\tlocalObjectHandle++;\n\t\tENSURES_MUTEX( isValidHandle( localObjectHandle ) && \\\n\t\t\t\t\t   localObjectHandle < NO_SYSTEM_OBJECTS && \\\n\t\t\t\t\t   localObjectHandle == objectStateInfo->objectHandle + 1, \\\n\t\t\t\t\t   objectTable );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES_MUTEX( isValidHandle( owner ), objectTable );\n\n\t\t/* Search the table for a free entry */\n\t\tstatus = localObjectHandle = findFreeObjectEntry( localObjectHandle );\n\t\t}\n\n\t/* If there's a problem with allocating a handle then it either means \n\t   that we've run out of entries in the object table or there's a more \n\t   general error */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tvoid *objectPtr = DATAPTR_GET( objectInfo.objectPtr );\n\n\t\tMUTEX_UNLOCK( objectTable );\n\n\t\tENSURES( objectPtr != NULL );\n\n\t\t/* Warn about the problem */\n\t\tDEBUG_DIAG_ERRMSG(( \"Error %s allocating new handle for %s object\", \n\t\t\t\t\t\t\tgetStatusName( status ), \n\t\t\t\t\t\t\tgetObjectTypeDescriptionNT( type, subType ) ));\n\t\tassert( DEBUG_WARN );\n\n\t\t/* Free the object instance data storage that we allocated earlier \n\t\t   and return the error status */\n\t\tif( TEST_FLAG( objectInfo.flags, OBJECT_FLAG_SECUREMALLOC ) )\n\t\t\t{\n\t\t\tint localStatus = krnlMemfree( &objectPtr );\n\t\t\tENSURES( cryptStatusOK( localStatus ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tzeroise( objectPtr, objectInfo.objectSize );\n\t\t\tif( !TEST_FLAG( objectInfo.flags, OBJECT_FLAG_STATICALLOC ) ) \n\t\t\t\tclFree( \"destroyObjectData\", objectPtr );\n\t\t\t}\n\t\tzeroise( &objectInfo, sizeof( OBJECT_INFO ) );\n\n\t\treturn( status );\n\t\t}\n\n\t/* Inner precondition: This object table slot is free */\n\tREQUIRES_MUTEX( isFreeObject( localObjectHandle ), objectTable );\n\n\t/* Set up the new object entry in the table and update the object table\n\t   state */\n\tobjectTable[ localObjectHandle ] = objectInfo;\n\tif( localObjectHandle == NO_SYSTEM_OBJECTS - 1 )\n\t\t{\n\t\ttime_t theTime;\n\t\t\n\t\t/* Get a non-constant seed to use for the initial object handle.  \n\t\t   See the comment in findFreeObjectEntry() for why this is done, \n\t\t   and why it only uses a relatively weak seed.  Since we may be \n\t\t   running on an embedded system with no reliable time source \n\t\t   available we use getApproxTime() rather than getTime(), the check \n\t\t   for correct functioning of the time source on non-embedded \n\t\t   systems has already been done in the init code */\n\t\ttheTime = getApproxTime();\n\n\t\t/* If this is the last system object, we've been allocating handles\n\t\t   sequentially up to this point.  From now on we start allocating\n\t\t   handles starting from a randomised location in the table */\n#ifndef USE_FIXED_OBJECTHANDLES\n\t\tobjectStateInfo->objectHandle = \\\n\t\t\t\t( int ) theTime & ( LFSR_MASK - 1 );\n#endif /* USE_FIXED_OBJECTHANDLES */\n\t\tif( objectStateInfo->objectHandle < NO_SYSTEM_OBJECTS )\n\t\t\t{\n\t\t\t/* Can occur with probability\n\t\t\t   NO_SYSTEM_OBJECTS / MAX_NO_OBJECTS */\n\t\t\tobjectStateInfo->objectHandle = NO_SYSTEM_OBJECTS + 42;\n\t\t\t}\n\t\t}\n\telse\n\t\tobjectStateInfo->objectHandle = localObjectHandle;\n\n\t/* Update the object unique ID value */\n\tif( krnlData->objectUniqueID < 0 || \\\n\t\tkrnlData->objectUniqueID >= INT_MAX - 1 )\n\t\tkrnlData->objectUniqueID = NO_SYSTEM_OBJECTS;\n\telse\n\t\tkrnlData->objectUniqueID++;\n\tENSURES_MUTEX( krnlData->objectUniqueID > 0 && \\\n\t\t\t\t   krnlData->objectUniqueID < INT_MAX, objectTable );\n\n\t/* Postconditions: It's a valid object that's been set up as required */\n\tENSURES_MUTEX( isValidObject( localObjectHandle ), objectTable );\n\tENSURES_MUTEX( DATAPTR_GET( objectInfo.objectPtr ) == *objectDataPtr, objectTable );\n\tENSURES_MUTEX( objectInfo.owner == owner, objectTable );\n\tENSURES_MUTEX( objectInfo.type == type, objectTable );\n\tENSURES_MUTEX( objectInfo.subType == subType, objectTable );\n\tENSURES_MUTEX( objectInfo.actionFlags == actionFlags, objectTable );\n\tENSURES_MUTEX( FNPTR_ISSET( objectInfo.messageFunction ), \n\t\t\t\t   objectTable );\n\n\tMUTEX_UNLOCK( objectTable );\n\n\t*objectHandle = localObjectHandle;\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/sec_mem.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSecure Memory Management\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* The minimum and maximum amount of secure memory that we can ever \n   allocate.  A more normal upper bound is 1K, however the SSL session cache \n   constitutes a single large chunk of secure memory that goes way over this \n   limit */\n\n#define MIN_ALLOC_SIZE\t\t\t8\n#define MAX_ALLOC_SIZE\t\t\t8192\n\n/* Memory block flags.  These are:\n\n\tFLAG_LOCKED: The memory block has been page-locked to prevent it from \n\t\t\tbeing swapped to disk and will need to be unlocked when it's \n\t\t\tfreed.\n\n\tFLAG_PROTECTED: The memory is read-only, enforced by running a checksum\n\t\t\tover it that's stored at the end of the user-visible block */\n\n#define MEM_FLAG_NONE\t\t\t0x00\t/* No memory flag */\n#define MEM_FLAG_LOCKED\t\t\t0x01\t/* Memory block is page-locked */\n#define MEM_FLAG_PROTECTED\t\t0x02\t/* Memory block can't be changed */\n#define MEM_FLAG_MAX\t\t\t0x03\t/* Maximum possible flag value */\n\n/* To support page locking and other administration tasks we need to store \n   some additional information with the memory block.  We do this by \n   reserving an extra memory block at the start of the allocated block and \n   saving the information there.\n\n   The information stored in the extra block is flags that control the use\n   of the memory block, the size of the block, and pointers to the next and \n   previous pointers in the list of allocated blocks (this is used by the \n   thread that walks the block list touching each one).  We also insert a \n   canary at the start and end of each allocated memory block to detect \n   memory overwrites and modification, which is just a checksum of the memory\n   header that doubles as a canary (which also makes it somewhat \n   unpredictable).\n\n   The resulting memory block looks as follows:\n\n\t\t\tExternal mem.ptr\n\t\t\t\t\t|\t\t\t\t\t\tCanary\n\t\t\t\t\tv\t\t\t\t\t\t  v\n\t\t+-------+---+-----------------------+---+\n\t\t| Hdr\t|###| Memory\t\t\t\t|###|\n\t\t+-------+---+-----------------------+---+\n\t\t^\t\t\t\t\t\t\t\t\t^\t|\n\t\t|<----------- memHdrPtr->size --------->|\n\t\t|\t\t\t\t\t\t\t\t\t|\n\tmemPtr (BYTE *)\t\t\t\t\t\t\t|\n\tmemHdrPtr (MEM_INFO_HDR *)\t\tmemTrlPtr (MEM_INFO_TRL *) */\n\ntypedef struct {\n\tSAFE_FLAGS flags;\t\t/* Flags for this memory block.  The memory \n\t\t\t\t\t\t\t   header is checksummed so we don't strictly\n\t\t\t\t\t\t\t   have to use safe flags, but we do it anyway\n\t\t\t\t\t\t\t   for appearances' sake */\n\tint size;\t\t\t\t/* Size of the block (including the size\n\t\t\t\t\t\t\t   of the header and trailer) */\n\tDATAPTR prev, next;\t\t/* Next, previous memory block */\n\tint checksum;\t\t\t/* Header checksum+canary for spotting overwrites */\n\t} MEM_INFO_HEADER;\n\ntypedef struct {\n\tint checksum;\t\t\t/* Memory block checksum or canary (= header chks) */\n\t} MEM_INFO_TRAILER;\n\n#if INT_MAX <= 32767\n  #define MEM_ROUNDSIZE\t\t4\n#elif INT_MAX <= 0xFFFFFFFFUL\n  #define MEM_ROUNDSIZE\t\t8\n#else\n  #define MEM_ROUNDSIZE\t\t16\n#endif /* 16/32/64-bit systems */\n#define MEM_INFO_HEADERSIZE\troundUp( sizeof( MEM_INFO_HEADER ), MEM_ROUNDSIZE )\n#define MEM_INFO_TRAILERSIZE sizeof( MEM_INFO_TRAILER )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOS-Specific Memory Locking\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Many OSes support locking pages in memory, the following helper functions \n   implement this locking */\n\n#if defined( __MAC__ )\n\n#include <Memory.h>\n\n/* The Mac has two functions for locking memory, HoldMemory() (which makes \n   the memory ineligible for paging) and LockMemory() (which makes it \n   ineligible for paging and also immovable).  We use HoldMemory() since \n   it's slightly more friendly, but really critical applications could use \n   LockMemory() */\n\nstatic void lockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n#if !defined( CALL_NOT_IN_CARBON ) || CALL_NOT_IN_CARBON\n\tif( HoldMemory( memPtr, memHdrPtr->size ) == noErr )\n\t\tSET_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED );\n#endif /* Non Mac OS X memory locking */\n\t}\n\nstatic void unlockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\t/* If the memory was locked, unlock it now */\n#if !defined( CALL_NOT_IN_CARBON ) || CALL_NOT_IN_CARBON\n\tif( TEST_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED ) )\n\t\tUnholdMemory( memPtr, memHdrPtr->size );\n#endif /* Non Mac OS X memory locking */\n\t}\n\n#elif defined( __MSDOS__ ) && defined( __DJGPP__ )\n\n#include <dpmi.h>\n#include <go32.h>\n\nstatic void lockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\t/* Under 32-bit MSDOS use the DPMI functions to lock memory */\n\tif( _go32_dpmi_lock_data( memPtr, memHdrPtr->size ) == 0)\n\t\tSET_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED );\n\t}\n\nstatic void unlockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\t/* Under 32-bit MSDOS we *could* use the DPMI functions to unlock\n\t   memory, but as many DPMI hosts implement page locking in a binary\n\t   form (no lock count maintained), it's better not to unlock anything\n\t   at all.  Note that this may lead to a shortage of virtual memory in\n\t   long-running applications */\n\t}\n\n#elif defined( __UNIX__ )\n\n/* Since the function prototypes for the SYSV/Posix mlock() call are stored\n   all over the place depending on the Unix version it's easier to prototype \n   it ourselves here rather than trying to guess its location */\n\n#if defined( __osf__ ) || defined( __alpha__ )\n  #include <sys/mman.h>\n#elif defined( sun )\n  #include <sys/mman.h>\n  #include <sys/types.h>\n#else\n  int mlock( void *address, size_t length );\n  int munlock( void *address, size_t length );\n#endif /* Unix-variant-specific includes */\n\n/* Under many Unix variants the SYSV/Posix mlock() call can be used, but \n   only by the superuser (with occasional OS-specific variants, for example \n   under some newer Linux variants the caller needs the specific \n   CAP_IPC_LOCK privilege rather than just generally being root).  \n   \n   OSF/1 has mlock(), but this is defined to the nonexistant memlk() so we \n   need to special-case it out.  \n   \n   QNX (depending on the version) either doesn't have mlock() at all or it's \n   a dummy that just returns -1, so we no-op it out.  \n   \n   Aches, A/UX, PHUX, Linux < 1.3.something, and Ultrix don't even pretend \n   to have mlock().\n   \n   Many systems also have plock(), but this is pretty crude since it locks \n   all data, and also has various other shortcomings.  \n   \n   Finally, PHUX has datalock(), which is just a plock() variant.\n   \n   Linux 2.6.32 has a kernel bug in which, under high disk-load conditions \n   (100% disk usge) and with multiple cryptlib threads performing memory \n   locking/unlocking the process can get stuck in the \"D\" state, a.k.a. \n   TASK_UNINTERRUPTIBLE, which is an uninterruptible disk I/O sleep state.  \n   If the process doesn't snap out of it when the I/O completes then it's \n   necessary to reboot the machine to clear the state.  To help find this \n   issue use:\n\n\tps -eo ppid,pid,user,stat,pcpu,comm,wchan:32\n\n   which shows D-state processes via the fourth column, the last column \n   will show the name of the kernel function in which the process is\n   currently sleeping (also check dmesg for kernel Oops'es) */\n\n#if defined( _AIX ) || defined( __alpha__ ) || defined( __aux ) || \\\n\tdefined( _CRAY ) || defined( __CYGWIN__ ) || defined( __hpux ) || \\\n\t( defined( __linux__ ) && OSVERSION < 2 ) || \\\n\tdefined( _M_XENIX ) || defined( __osf__ ) || \\\n\t( defined( __QNX__ ) && OSVERSION <= 6 ) || \\\n\tdefined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\tdefined( __ultrix )\n  #define mlock( a, b )\t\t1\n  #define munlock( a, b )\n#endif /* Unix OS-specific defines */\n\n/* In theory we could also tell the kernel to treat the memory specially if\n   this facility is available.  In practice this doesn't really work though \n   because madvise() works on a granularity of page boundaries, despite the\n   appearance of working on arbitrary memory regions.  This means that \n   unless the start address is page-aligned, it'll fail.  In addition it \n   functions at a much lower level than malloc(), so if we madvise() \n   malloc'd memory we'll end up messing with the heap in ways that will \n   break memory allocation.  For example MADV_WIPEONFORK will wipe the \n   entire page or page range containing the heap that the client gets, \n   corrupting the heap on fork.\n\n  What this means is that we'd need to mmap() memory in order to madvise() \n  on it, and then implement our own allocator on top of that.  Or, every \n  time we allocate anything, make it a full page, again via mmap().  The \n  chances of something going wrong when we do our own memory management are \n  probably a lot higher than the chances of something ending up in a core \n  dump when we don't:\n\n\t#if defined( __linux__ ) && defined( _BSD_SOURCE ) && 0\n\n\t// Tell the kernel to exclude this memory region from core dumps if \n\t// possible\n\n\t#ifdef MADV_DONTDUMP\n\n\t#include <sys/mman.h>\n\n\t( void ) madvise( void *addr, size_t length, MADV_DONTDUMP );\n\n\t#endif // MADV_DONTDUMP */\n\nstatic void lockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\tif( !mlock( ( void * ) memHdrPtr, memHdrPtr->size ) )\n\t\tSET_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED );\n\t}\n\nstatic void unlockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\t/* If the memory was locked, unlock it now */\n\tif( TEST_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED ) )\n\t\tmunlock( ( void * ) memHdrPtr, memHdrPtr->size );\n\t}\n\n#elif defined( __WIN32__ ) && !defined( NT_DRIVER )\n\n/* For the Win32 debug build we enable extra checking for heap corruption.\n   This isn't anywhere near as good as proper memory checkers like Bounds\n   Checker, but it can catch some errors */\n\n#if !defined( NDEBUG ) && !defined( NT_DRIVER ) && !defined( __BORLANDC__ )\n  #define USE_HEAP_CHECKING\n  #include <crtdbg.h>\n#endif /* Win32 debug version */\n\n/* Get the start address of a page and, given an address in a page and a \n   size, determine on which page the data ends.  These are used to determine \n   which pages a memory block covers */\n\n#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )\n  #define PTR_TYPE\tINT_PTR \n#else\n  #define PTR_TYPE\tlong\n#endif /* Newer versions of VC++ */\n\n#define getPageStartAddress( address ) \\\n\t\t\t( ( PTR_TYPE ) ( address ) & ~( pageSize - 1 ) )\n#define getPageEndAddress( address, size ) \\\n\t\t\tgetPageStartAddress( ( PTR_TYPE ) address + ( size ) - 1 )\n\n/* Under Win95/98/ME the VirtualLock() function was implemented as \n   'return( TRUE )' (\"Thank Microsoft kids\" - \"Thaaaanks Bill\"), but we \n   don't have to worry about those Windows versions any more.  Under Win32/\n   Win64 the function does actually work, but with a number of caveats.  The \n   main one is that it was originally intended that VirtualLock() only locks\n   memory into a processes' working set, in other words it guarantees that \n   the memory won't be paged while a thread in the process is running, and \n   when all threads are pre-empted the memory is still a target for paging.  \n   This would mean that on a loaded system a process that was idle for some \n   time could have the memory unlocked by the system and swapped out to disk \n   (actually with older Windows incarnations like NT, their somewhat strange \n   paging strategy meant that it could potentially get paged even on a \n   completely unloaded system.  Even on relatively recent systems the \n   gradual creeping takeover of free memory for disk buffers/cacheing can\n   cause problems, something that was still affecting Win64 systems during\n   the Windows 7 time frame.  Ironically the 1GB cache size limit on Win32\n   systems actually helped here because the cache couldn't grow beyond this\n   size and most systems had more than 1GB of RAM, while on Win64 systems \n   without this limit there was more scope for excessive reads and writes to \n   consume all available memory due to cacheing).\n   \n   The lock-into-working-set approach was the original intention, however \n   the memory manager developers never got around to implementing the \n   unlock-if-all-threads idle part.  The behaviour of VirtualLock() was \n   evaluated back under Win2K and XP by trying to force data to be paged \n   under various conditions, which were unsuccesful, so VirtualLock() under \n   these OSes seems to be fairly effective in keeping data off disk.  In \n   newer versions of Windows the contract for VirtualLock() was changed to \n   match the actual implemented behaviour, so that now \"pages are guaranteed \n   not to be written to the pagefile while they are locked\".\n\n   An additional concern is that although VirtualLock() takes arbitrary \n   memory pointers and a size parameter, the locking is done on a per-page \n   basis so that unlocking a region that shares a page with another locked \n   region means that both reqions are unlocked.  Since VirtualLock() doesn't \n   do reference counting (emulating the underlying MMU page locking even \n   though it seems to implement an intermediate layer above the MMU so it \n   could in theory do this), the only way around this is to walk the chain \n   of allocated blocks and not unlock a block if there's another block \n   allocated on the same page.  Ick.\n\n   For the NT kernel driver, the memory is always allocated from the non-\n   paged pool so there's no need for these gyrations.\n   \n   In addition to VirtualLock() we could also use VirtualAlloc(), however \n   this allocates in units of the allocation granularity, which is in theory\n   system-dependent and obtainable via the dwAllocationGranularity field in\n   the SYSTEM_INFO structure returned by GetSystemInfo() but in practice on\n   x86 systems is always 64K, this means the memory is nicely aligned for\n   efficient access but wastes 64K for every allocation */\n\nstatic void lockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\tif( VirtualLock( ( void * ) memHdrPtr, memHdrPtr->size ) )\n\t\tSET_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED );\n\t}\n\nstatic void unlockMemory( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMEM_INFO_HEADER *currentBlockPtr;\n\tPTR_TYPE block1PageAddress, block2PageAddress;\n\tconst int pageSize = getSysVar( SYSVAR_PAGESIZE );\n\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER ) ) );\n\n\t/* If the memory block isn't locked, there's nothing to do */\n\tif( !TEST_FLAG( memHdrPtr->flags, MEM_FLAG_LOCKED ) )\n\t\treturn;\n\n\t/* Because VirtualLock() works on a per-page basis, we can't unlock a\n\t   memory block if there's another locked block on the same page.  The\n\t   only way to manage this is to walk the block list checking to see\n\t   whether there's another block allocated on the same page.  Although in\n\t   theory this could make freeing memory rather slow, in practice there\n\t   are only a small number of allocated blocks to check so it's\n\t   relatively quick, especially compared to the overhead imposed by the\n\t   lethargic VC++ allocator.  The only real disadvantage is that the\n\t   allocation objects remain locked while we do the free, but this\n\t   isn't any worse than the overhead of touchAllocatedPages().  Note \n\t   that the following code assumes that an allocated block will never \n\t   cover more than two pages, which is always the case.\n\n\t   First we calculate the addresses of the page(s) in which the memory \n\t   block resides */\n\tblock1PageAddress = getPageStartAddress( memHdrPtr );\n\tblock2PageAddress = getPageEndAddress( memHdrPtr, memHdrPtr->size );\n\tif( block1PageAddress == block2PageAddress )\n\t\tblock2PageAddress = 0;\n\n\t/* Walk down the block list checking whether the page(s) contain another \n\t   locked block */\n\tfor( currentBlockPtr = DATAPTR_GET( krnlData->allocatedListHead ); \\\n\t\t currentBlockPtr != NULL; \n\t\t currentBlockPtr = DATAPTR_GET( currentBlockPtr->next ) )\n\t\t{\n\t\tconst PTR_TYPE currentPage1Address = \\\n\t\t\t\t\t\tgetPageStartAddress( currentBlockPtr );\n\t\tPTR_TYPE currentPage2Address = \\\n\t\t\t\t\t\tgetPageEndAddress( currentBlockPtr, currentBlockPtr->size );\n\n\t\tif( currentPage1Address == currentPage2Address )\n\t\t\tcurrentPage2Address = 0;\n\n\t\t/* If there's another block allocated on either of the pages, don't\n\t\t   unlock it */\n\t\tif( block1PageAddress == currentPage1Address || \\\n\t\t\tblock1PageAddress == currentPage2Address )\n\t\t\t{\n\t\t\tblock1PageAddress = 0;\n\t\t\tif( !block2PageAddress )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( block2PageAddress == currentPage1Address || \\\n\t\t\tblock2PageAddress == currentPage2Address )\n\t\t\t{\n\t\t\tblock2PageAddress = 0;\n\t\t\tif( !block1PageAddress )\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t/* Finally, if either page needs unlocking, do so.  The supplied size is \n\t   irrelevant since the entire page the memory is on is unlocked */\n\tif( block1PageAddress )\n\t\tVirtualUnlock( ( void * ) block1PageAddress, 16 );\n\tif( block2PageAddress )\n\t\tVirtualUnlock( ( void * ) block2PageAddress, 16 );\n\t}\n#else\n\n/* For everything else we no-op it out */\n\n#define lockMemory( memHdrPtr )\n#define unlockMemory( memHdrPtr )\n\n#endif /* OS-specific page-locking handling */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tOS-Specific Nonpageable Allocators\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some OSes handle page-locking by explicitly locking an already-allocated\n   address range, others require the use of a special allocate-nonpageable-\n   memory function.  For the latter class we redefine the standard \n   clAlloc()/clFree() macros to use the appropriate OS-specific allocators */\n\n#if defined( __BEOS__xxx )\t/* See comment below */\n\n/* BeOS' create_area(), like most of the low-level memory access functions \n   provided by different OSes, functions at the page level so we round the \n   size up to the page size.  We can mitigate the granularity somewhat by \n   specifying lazy locking, which means that the page isn't locked until it's \n   committed.\n\n   In pre-open-source BeOS, areas were bit of a security tradeoff because \n   they were globally visible(!!!) through the use of find_area(), so that \n   any other process in the system could find them.  An attacker could \n   always find the app's malloc() arena anyway because of this, but putting \n   data directly into areas made the attacker's task somewhat easier.  Open-\n   source BeOS fixed this, mostly because it would have taken extra work to \n   make areas explicitly globally visible and no-one could see a reason for \n   this, so it's somewhat safer there.\n\n   However, the implementation of create_area() in the open-source BeOS \n   seems to be rather flaky (simply creating an area and then immediately \n   destroying it again causes a segmentation violation) so it may be \n   necessary to turn it off for some BeOS releases.\n   \n   In more recent open-source BeOS releases create_area() simply maps to\n   mmap(), and that uses a function convert_area_protection_flags() to\n   convert the BeOS to Posix flags which simply discards everything but\n   AREA_READ, AREA_WRITE, and AREA_EXEC, so it appears that create_area()\n   can no longer allocate non-pageable memory.  If the original behaviour is \n   ever restored then the code will need to be amended to add the following\n   member to MEM_INFO_HEADER:\n\n\tarea_id areaID;\t\t\t\t// Needed for page locking under BeOS\n\n   and save the areaID after the create_area() call:\n\n\tmemHdrPtr->areaID = areaID; */\n\n#define clAlloc( string, size )\t\tbeosAlloc( size )\n#define clFree( string, memblock )\tbeosFree( memblock )\n\nstatic void *beosAlloc( const int size )\n\t{ \n\tvoid *memPtr = NULL; \n\tarea_id areaID; \n\n\tareaID = create_area( \"memory_block\", &memPtr, B_ANY_ADDRESS,\n\t\t\t\t\t\t  roundUp( size + MEM_INFO_HEADERSIZE, B_PAGE_SIZE ),\n\t\t\t\t\t\t  B_LAZY_LOCK, B_READ_AREA | B_WRITE_AREA );\n\tif( areaID < B_NO_ERROR )\n\t\treturn( NULL );\n\n\treturn( memPtr );\n\t}\n\nstatic void beosFree( void *memPtr )\n\t{\n\tMEM_INFO_HEADER *memHdrPtr = memPtr;\n\tarea_id areaID; \n\n\tareaID = memHdrPtr->areaID;\n\tzeroise( memPtr, memHdrPtr->size );\n\tdelete_area( areaID );\n\t}\n\n#elif defined( __CHORUS__ )\n\n/* ChorusOS is one of the very few embedded OSes with paging capabilities,\n   fortunately there's a way to allocate nonpageable memory if paging is\n   enabled */\n\n#include <mem/chMem.h>\n\n#define clAlloc( string, size )\t\tchorusAlloc( size )\n#define clFree( string, memblock )\tchorusFree( memblock )\n\nstatic void *chorusAlloc( const int size )\n\t{ \n\tKnRgnDesc rgnDesc = { K_ANYWHERE, size + MEM_INFO_HEADERSIZE, \\\n\t\t\t\t\t\t  K_WRITEABLE | K_NODEMAND };\n\n\tif( rgnAllocate( K_MYACTOR, &rgnDesc ) != K_OK )\n\t\treturn( NULL );\n\n\treturn( rgnDesc.startAddr );\n\t}\n\nstatic void chorusFree( void *memPtr )\n\t{\n\tMEM_INFO_HEADER *memHdrPtr = memPtr;\n\tKnRgnDesc rgnDesc = { K_ANYWHERE, 0, 0 };\n\n\trgnDesc.size = memHdrPtr->size;\n\trgnDesc.startAddr = memPtr;\n\tzeroise( memPtr, memHdrPtr->size );\n\trgnFree( K_MYACTOR, &rgnDesc );\n\t}\n#endif /* OS-specific nonpageable allocation handling */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate the checksum for a memory header block */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checksumMemHdr( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tconst int memHdrChecksum = memHdrPtr->checksum;\n\tint checksum;\n\n\tmemHdrPtr->checksum = 0;\n\tchecksum = checksumData( memHdrPtr, MEM_INFO_HEADERSIZE );\n\tmemHdrPtr->checksum = memHdrChecksum;\n\n\treturn( checksum );\n\t}\n\n/* Set the checksum for a block of memory */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void setMemChecksum( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tMEM_INFO_TRAILER *memTrlPtr;\n\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\n\tmemHdrPtr->checksum = 0;\t/* Set mutable members to zero */\n\tmemHdrPtr->checksum = checksumData( memHdrPtr, MEM_INFO_HEADERSIZE );\n\tmemTrlPtr = ( MEM_INFO_TRAILER * ) \\\n\t\t\t\t( ( BYTE * ) memHdrPtr + memHdrPtr->size - MEM_INFO_TRAILERSIZE );\n\tmemTrlPtr->checksum = memHdrPtr->checksum;\n\t}\n\n/* Check that a memory block is in order */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkMemBlockHdr( INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tconst MEM_INFO_TRAILER *memTrlPtr;\n\tint checksum;\n\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\n\t/* Make sure that the general header information is valid.  This is a \n\t   quick check for obviously-invalid blocks, as well as ensuring that a \n\t   corrupted size member doesn't result in us reading off into the \n\t   weeds */\n\tif( memHdrPtr->size < MEM_INFO_HEADERSIZE + MIN_ALLOC_SIZE + \\\n\t\t\t\t\t\t  MEM_INFO_TRAILERSIZE || \\\n\t\tmemHdrPtr->size > MEM_INFO_HEADERSIZE + MAX_ALLOC_SIZE + \\\n\t\t\t\t\t\t  MEM_INFO_TRAILERSIZE )\n\t\treturn( FALSE );\n\tif( !CHECK_FLAGS( memHdrPtr->flags, MEM_FLAG_NONE, \n\t\t\t\t\t  MEM_FLAG_MAX ) )\n\t\treturn( FALSE );\n\n\t/* Everything seems kosher so far, check that the header hasn't been \n\t   altered */\n\tchecksum = checksumMemHdr( memHdrPtr );\n\tif( checksum != memHdrPtr->checksum )\n\t\treturn( FALSE );\n\n\t/* Check that the trailer hasn't been altered */\n\tmemTrlPtr = ( MEM_INFO_TRAILER * ) \\\n\t\t\t\t( ( BYTE * ) memHdrPtr + memHdrPtr->size - MEM_INFO_TRAILERSIZE );\n\tif( memHdrPtr->checksum != memTrlPtr->checksum )\n\t\treturn( FALSE );\n\t\n\treturn( TRUE );\n\t}\n\n/* Insert and unlink a memory block from a list of memory blocks, with \n   appropriate updates of memory checksums and other information.  We keep \n   the code for this in distinct functions to make sure that an exception-\n   condition doesn't force an exit without the memory mutex unlocked */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int insertMemBlock( INOUT MEM_INFO_HEADER **allocatedListHeadPtr, \n\t\t\t\t\t\t   INOUT MEM_INFO_HEADER **allocatedListTailPtr, \n\t\t\t\t\t\t   INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tMEM_INFO_HEADER *allocatedListHead = *allocatedListHeadPtr;\n\tMEM_INFO_HEADER *allocatedListTail = *allocatedListTailPtr;\n\n\tassert( isWritePtr( allocatedListHeadPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\tassert( allocatedListHead == NULL || \\\n\t\t\tisWritePtr( allocatedListHead, sizeof( MEM_INFO_HEADER ) ) );\n\tassert( isWritePtr( allocatedListTailPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\tassert( allocatedListTail == NULL || \\\n\t\t\tisWritePtr( allocatedListTail, sizeof( MEM_INFO_HEADER ) ) );\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\n\t/* Precondition: The memory block list is empty, or there's at least a \n\t   one-entry list present */\n\tREQUIRES( ( allocatedListHead == NULL && allocatedListTail == NULL ) || \\\n\t\t\t  ( allocatedListHead != NULL && allocatedListTail != NULL ) );\n\n\t/* If it's a new list, set up the head and tail pointers and return */\n\tif( allocatedListHead == NULL )\n\t\t{\n\t\t/* In yet another of gcc's endless supply of compiler bugs, if the\n\t\t   following two lines of code are combined into a single line then\n\t\t   the write to the first value, *allocatedListHeadPtr, ends up \n\t\t   going to some arbitrary memory location and only the second\n\t\t   write goes to the correct location (completely different code is\n\t\t   generated for the two writes)  This leaves \n\t\t   krnlData->allocatedListHead as a NULL pointer, leading to an\n\t\t   exception being triggered the next time that it's accessed */\n#if defined( __GNUC__ ) && ( __GNUC__ == 4 )\n\t\t*allocatedListHeadPtr = memHdrPtr;\n\t\t*allocatedListTailPtr = memHdrPtr;\n#else\n\t\t*allocatedListHeadPtr = *allocatedListTailPtr = memHdrPtr;\n#endif /* gcc 4.x compiler bug */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's an existing list, add the new element to the end */\n\tREQUIRES( checkMemBlockHdr( allocatedListTail ) );\n\tDATAPTR_SET( allocatedListTail->next, memHdrPtr );\n\tsetMemChecksum( allocatedListTail );\n\tDATAPTR_SET( memHdrPtr->prev, allocatedListTail );\n\t*allocatedListTailPtr = memHdrPtr;\n\n\t/* Postcondition: The new block has been linked into the end of the \n\t   list */\n\tENSURES( DATAPTR_GET( allocatedListTail->next ) == memHdrPtr && \\\n\t\t\t DATAPTR_GET( memHdrPtr->prev ) == allocatedListTail && \\\n\t\t\t DATAPTR_ISNULL( memHdrPtr->next ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int unlinkMemBlock( INOUT MEM_INFO_HEADER **allocatedListHeadPtr, \n\t\t\t\t\t\t   INOUT MEM_INFO_HEADER **allocatedListTailPtr, \n\t\t\t\t\t\t   INOUT MEM_INFO_HEADER *memHdrPtr )\n\t{\n\tMEM_INFO_HEADER *allocatedListHead = *allocatedListHeadPtr;\n\tMEM_INFO_HEADER *allocatedListTail = *allocatedListTailPtr;\n\tMEM_INFO_HEADER *nextBlockPtr = DATAPTR_GET( memHdrPtr->next );\n\tMEM_INFO_HEADER *prevBlockPtr = DATAPTR_GET( memHdrPtr->prev );\n\n\tassert( isWritePtr( allocatedListHeadPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\tassert( allocatedListHead == NULL || \\\n\t\t\tisWritePtr( allocatedListHead, sizeof( MEM_INFO_HEADER ) ) );\n\tassert( isWritePtr( allocatedListTailPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\tassert( allocatedListTail == NULL || \\\n\t\t\tisWritePtr( allocatedListTail, sizeof( MEM_INFO_HEADER ) ) );\n\tassert( isWritePtr( memHdrPtr, sizeof( MEM_INFO_HEADER * ) ) );\n\n\tREQUIRES( DATAPTR_ISVALID( memHdrPtr->next ) );\n\tREQUIRES( DATAPTR_ISVALID( memHdrPtr->prev ) );\n\n\t/* If we're removing the block from the start of the list, make the\n\t   start the next block */\n\tif( memHdrPtr == allocatedListHead )\n\t\t{\n\t\tREQUIRES( prevBlockPtr == NULL );\n\n\t\t*allocatedListHeadPtr = nextBlockPtr;\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( prevBlockPtr != NULL && \\\n\t\t\t\t  DATAPTR_GET( prevBlockPtr->next ) == memHdrPtr );\n\n\t\t/* Delete from the middle or end of the list */\n\t\tREQUIRES( checkMemBlockHdr( prevBlockPtr ) );\n\t\tDATAPTR_SET( prevBlockPtr->next, nextBlockPtr );\n\t\tsetMemChecksum( prevBlockPtr );\n\t\t}\n\tif( nextBlockPtr != NULL )\n\t\t{\n\t\tREQUIRES( DATAPTR_GET( nextBlockPtr->prev ) == memHdrPtr );\n\n\t\tREQUIRES( checkMemBlockHdr( nextBlockPtr ) );\n\t\tDATAPTR_SET( nextBlockPtr->prev, prevBlockPtr );\n\t\tsetMemChecksum( nextBlockPtr );\n\t\t}\n\n\t/* If we've removed the last element, update the end pointer */\n\tif( memHdrPtr == allocatedListTail )\n\t\t{\n\t\tREQUIRES( nextBlockPtr == NULL );\n\n\t\t*allocatedListTailPtr = prevBlockPtr;\n\t\t}\n\n\t/* Clear the current block's pointers, just to be clean */\n\tDATAPTR_SET( memHdrPtr->next, NULL );\n\tDATAPTR_SET( memHdrPtr->prev, NULL );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\t/* Currently unused, in practice would be called from a worker thread\n\t\t   that periodically touches all secure-data pages */\n\n/* Walk the allocated block list touching each page.  In most cases we don't\n   need to explicitly touch the page since the allocated blocks are almost\n   always smaller than the MMU's page size and simply walking the list\n   touches them, but in some rare cases we need to explicitly touch each\n   page */\n\nstatic void touchAllocatedPages( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMEM_INFO_HEADER *memHdrPtr;\n\tconst int pageSize = getSysVar( SYSVAR_PAGESIZE );\n\n\t/* Lock the allocation object to ensure that other threads don't try to\n\t   access them */\n\tMUTEX_LOCK( allocation );\n\n\t/* Walk down the list (which implicitly touches each page).  If the\n\t   allocated region is larger than the page size, explicitly touch each \n\t   additional page */\n\tfor( memHdrPtr = krnlData->allocatedListHead; memHdrPtr != NULL;\n\t\t memHdrPtr = memHdrPtr->next )\n\t\t{\n\t\t/* If the allocated region has pages beyond the first one (which \n\t\t   we've already touched by accessing the header), explicitly\n\t\t   touch those pages as well */\n\t\tif( memHdrPtr->size > pageSize )\n\t\t\t{\n\t\t\tBYTE *memPtr = ( BYTE * ) memHdrPtr + pageSize;\n\t\t\tint memSize = memHdrPtr->size;\n\n\t\t\t/* Touch each page.  The rather convoluted expression in the loop\n\t\t\t   body is to try and stop it from being optimised away - it \n\t\t\t   always evaluates to true since we only get here if \n\t\t\t   allocatedListHead != NULL, but hopefully the compiler won't \n\t\t\t   be able to figure that out */\n\t\t\tLOOP_LARGE( memSize = memHdrPtr->size, memSize > pageSize, \n\t\t\t\t\t\tmemSize -= pageSize )\n\t\t\t\t{\n\t\t\t\tif( *memPtr || krnlData->allocatedListHead != NULL )\n\t\t\t\t\tmemPtr += pageSize;\n\t\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Unlock the allocation object to allow access by other threads */\n\tMUTEX_UNLOCK( allocation );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create and destroy the secure allocation information */\n\nCHECK_RETVAL \\\nint initAllocation( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint status;\n\n\tassert( isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) );\n\n\t/* Clear the allocated block list head and tail pointers */\n\tDATAPTR_SET( krnlData->allocatedListHead, NULL );\n\tDATAPTR_SET( krnlData->allocatedListTail, NULL );\n\n\t/* Initialize any data structures required to make the allocation thread-\n\t   safe */\n\tMUTEX_CREATE( allocation, status );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid endAllocation( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\t/* Destroy any data structures required to make the allocation thread-\n\t   safe */\n\tMUTEX_DESTROY( allocation );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSecure Memory Allocation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A safe malloc function that performs page locking if possible */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlMemalloc( OUT_BUFFER_ALLOC_OPT( size ) void **pointer, \n\t\t\t\t  IN_LENGTH int size )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMEM_INFO_HEADER *allocatedListHeadPtr, *allocatedListTailPtr; \n\tMEM_INFO_HEADER *memHdrPtr;\n\tBYTE *memPtr;\n\tconst int alignedSize = roundUp( size, MEM_ROUNDSIZE );\n\tconst int memSize = MEM_INFO_HEADERSIZE + alignedSize + \\\n\t\t\t\t\t\tMEM_INFO_TRAILERSIZE;\n\tint status;\n\n\tstatic_assert( MEM_INFO_HEADERSIZE >= sizeof( MEM_INFO_HEADER ), \\\n\t\t\t\t   \"Memlock header size\" );\n\n\t/* Make sure that the parameters are in order */\n\tif( !isWritePtr( pointer, sizeof( void * ) ) )\n\t\tretIntError();\n\t\n\tREQUIRES( size >= MIN_ALLOC_SIZE && size <= MAX_ALLOC_SIZE );\n\n\t/* Clear return values */\n\t*pointer = NULL;\n\n\t/* Allocate and clear the memory */\n\tREQUIRES( rangeCheck( memSize, 1, MAX_INTLENGTH ) );\n\tif( ( memPtr = clAlloc( \"krnlMemAlloc\", memSize ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( memPtr, 0, memSize );\n\n\t/* Set up the memory block header and trailer */\n\tmemHdrPtr = ( MEM_INFO_HEADER * ) memPtr;\n\tINIT_FLAGS( memHdrPtr->flags, MEM_FLAG_NONE );\n\tmemHdrPtr->size = memSize;\n\tDATAPTR_SET( memHdrPtr->next, NULL );\n\tDATAPTR_SET( memHdrPtr->prev, NULL );\n\n\t/* Try to lock the pages in memory */\n\tlockMemory( memHdrPtr );\n\n\t/* Lock the memory list */\n\tMUTEX_LOCK( allocation );\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( krnlData->allocatedListHead ) || \\\n\t\t!DATAPTR_ISVALID( krnlData->allocatedListTail ) )\n\t\t{\n\t\tMUTEX_UNLOCK( allocation );\n\t\tclFree( \"krnlMemAlloc\", memPtr );\n\t\tDEBUG_DIAG(( \"Kernel memory data corrupted\" ));\n\t\tretIntError();\n\t\t}\n\n\t/* Insert the new block into the list */\n\tallocatedListHeadPtr = DATAPTR_GET( krnlData->allocatedListHead );\n\tallocatedListTailPtr = DATAPTR_GET( krnlData->allocatedListTail );\n\tstatus = insertMemBlock( &allocatedListHeadPtr, &allocatedListTailPtr, \n\t\t\t\t\t\t\t memHdrPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( allocation );\n\t\tclFree( \"krnlMemAlloc\", memPtr );\n\t\tretIntError();\n\t\t}\n\tDATAPTR_SET( krnlData->allocatedListHead, allocatedListHeadPtr );\n\tDATAPTR_SET( krnlData->allocatedListTail, allocatedListTailPtr );\n\n\t/* Calculate the checksums for the memory block */\n\tsetMemChecksum( memHdrPtr );\n\n\t/* Perform heap sanity-checking if the functionality is available */\n#ifdef USE_HEAP_CHECKING\n\t/* Sanity check to detect memory chain corruption */\n\tassert( _CrtIsValidHeapPointer( memHdrPtr ) );\n\tassert( DATAPTR_ISNULL( memHdrPtr->next ) );\n\tassert( DATAPTR_GET( krnlData->allocatedListHead ) == \\\n\t\t\t\tDATAPTR_GET( krnlData->allocatedListTail ) || \\\n\t\t\t_CrtIsValidHeapPointer( DATAPTR_GET( memHdrPtr->prev ) ) );\n#endif /* USE_HEAP_CHECKING */\n\n\tMUTEX_UNLOCK( allocation );\n\n\t*pointer = memPtr + MEM_INFO_HEADERSIZE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* A safe free function that scrubs memory and zeroes the pointer.\n\n\t\"You will softly and suddenly vanish away\n\t And never be met with again\"\t- Lewis Carroll,\n\t\t\t\t\t\t\t\t\t  \"The Hunting of the Snark\" */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint krnlMemfree( INOUT_PTR void **pointer )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMEM_INFO_HEADER *allocatedListHeadPtr, *allocatedListTailPtr; \n\tMEM_INFO_HEADER *memHdrPtr;\n\tBYTE *memPtr;\n\tint status;\n\n\tassert( isReadPtr( pointer, sizeof( void * ) ) );\n\n\t/* Make sure that the parameters are in order */\n\tif( !isReadPtr( pointer, sizeof( void * ) ) || \\\n\t\t!isReadPtr( *pointer, MIN_ALLOC_SIZE ) )\n\t\tretIntError();\n\n\t/* Recover the actual allocated memory block data from the pointer */\n\tmemPtr = ( ( BYTE * ) *pointer ) - MEM_INFO_HEADERSIZE;\n\tif( !isReadPtr( memPtr, MEM_INFO_HEADERSIZE ) )\n\t\tretIntError();\n\tmemHdrPtr = ( MEM_INFO_HEADER * ) memPtr;\n\n\t/* Lock the memory list */\n\tMUTEX_LOCK( allocation );\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( krnlData->allocatedListHead ) || \\\n\t\t!DATAPTR_ISVALID( krnlData->allocatedListTail ) )\n\t\t{\n\t\tMUTEX_UNLOCK( allocation );\n\t\tDEBUG_DIAG(( \"Kernel memory data corrupted\" ));\n\t\tretIntError();\n\t\t}\n\n\t/* Make sure that the memory header information and canaries are \n\t   valid */\n\tif( !checkMemBlockHdr( memHdrPtr ) )\n\t\t{\n\t\tMUTEX_UNLOCK( allocation );\n\n\t\t/* The memory block doesn't look right, don't try and go any \n\t\t   further */\n\t\tDEBUG_DIAG(( \"Attempt to free invalid memory segment at %lX inside \"\n\t\t\t\t\t \"memory block at %lX\", *pointer, memHdrPtr ));\n\t\tretIntError();\n\t\t}\n\n\t/* Perform heap sanity-checking if the functionality is available */\n#ifdef USE_HEAP_CHECKING\n\t/* Sanity check to detect memory chain corruption */\n\tassert( _CrtIsValidHeapPointer( memHdrPtr ) );\n\tassert( DATAPTR_ISNULL( memHdrPtr->next ) || \\\n\t\t\t_CrtIsValidHeapPointer( DATAPTR_GET( memHdrPtr->next ) ) );\n\tassert( DATAPTR_ISNULL( memHdrPtr->prev ) || \\\n\t\t\t_CrtIsValidHeapPointer( DATAPTR_GET( memHdrPtr->prev ) ) );\n#endif /* USE_HEAP_CHECKING */\n\n\t/* Unlink the memory block from the list */\n\tallocatedListHeadPtr = DATAPTR_GET( krnlData->allocatedListHead );\n\tallocatedListTailPtr = DATAPTR_GET( krnlData->allocatedListTail );\n\tstatus = unlinkMemBlock( &allocatedListHeadPtr, &allocatedListTailPtr, \n\t\t\t\t\t\t\t memHdrPtr );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDATAPTR_SET( krnlData->allocatedListHead, allocatedListHeadPtr );\n\t\tDATAPTR_SET( krnlData->allocatedListTail, allocatedListTailPtr );\n\t\t}\n\n\tMUTEX_UNLOCK( allocation );\n\n\t/* Zeroise the memory (including the memlock info), free it, and zero\n\t   the pointer */\n\tzeroise( memPtr, memHdrPtr->size );\n\tunlockMemory( memHdrPtr );\n\tclFree( \"krnlMemFree\", memPtr );\n\t*pointer = NULL;\n\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/selftest.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Self-Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"capabil.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"device/capabil.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCorrectness/Safety Self-test Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Self-test code for the correctness/safety mechanisms.  Note that we have \n   to use a buffer of at least 256 bytes since that's the smallest that \n   safeBufferInit() will allow us to specify */\n\n#define SAFE_BUFFER_SIZE\t256\n\nstatic BOOLEAN testCFITrue( const ACCESS_TOKEN accessToken )\n\t{\n\treturn( CHECK_TOKEN( \"testCFITrue\" ) ? TRUE : FALSE );\n\t}\n\nstatic BOOLEAN testCFIFalse( const ACCESS_TOKEN accessToken )\n\t{\n\treturn( CHECK_TOKEN( \"testCFIFalse\" ) ? FALSE : TRUE );\n\t}\n\nstatic BOOLEAN testSafetyMechanisms( void )\n\t{\n\tDATAPTR testPtr;\n\tSAFE_FLAGS flags;\n\tSAFE_BOOLEAN testBool;\n\tBYTE buffer[ SAFE_BUFFER_SIZE + 16 + 8 ], *bufPtr, savedValue;\n\tint i, LOOP_ITERATOR, LOOP_ITERATOR_ALT;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\n\t/* Test the error-detecting BOOLEAN variable mechanisms */\n\tBOOL_SET( &testBool );\n\tif( !BOOL_ISSET( &testBool ) || BOOL_ISCLEAR( &testBool ) )\n\t\treturn( FALSE );\n\tBOOL_CLEAR( &testBool );\n\tif( BOOL_ISSET( &testBool ) || !BOOL_ISCLEAR( &testBool ) )\n\t\treturn( FALSE );\n\tBOOL_SET( &testBool );\n\ttestBool.value1 ^= 0x0800;\n\tif( BOOL_ISVALID( &testBool ) )\n\t\treturn( FALSE );\n\tBOOL_SET( &testBool );\n\ttestBool.value2 ^= 0x0800;\n\tif( BOOL_ISVALID( &testBool ) )\n\t\treturn( FALSE );\n\tBOOL_CLEAR( &testBool );\n\ttestBool.value1 ^= 0x0800;\n\tif( BOOL_ISVALID( &testBool ) )\n\t\treturn( FALSE );\n\tBOOL_CLEAR( &testBool );\n\ttestBool.value2 ^= 0x0800;\n\tif( BOOL_ISVALID( &testBool ) )\n\t\treturn( FALSE );\n\tCFI_CHECK_UPDATE( \"BOOLEAN\" ); \n\n\t/* Test the error-detecting bitflags variable mechanisms */\n\tINIT_FLAGS( flags, 0 );\n\tif( !CHECK_FLAGS( flags, 0x00, 0x80 ) )\n\t\treturn( FALSE );\n\tSET_FLAG( flags, 0x80 );\n\tif( !CHECK_FLAGS( flags, 0x00, 0x80 ) )\n\t\treturn( FALSE );\n\tif( !TEST_FLAG( flags, 0x80 ) )\n\t\treturn( FALSE );\n\tCLEAR_FLAG( flags, 0x80 );\n\tif( !CHECK_FLAGS( flags, 0x00, 0x80 ) )\n\t\treturn( FALSE );\n\tif( TEST_FLAG( flags, 0x80 ) )\n\t\treturn( FALSE );\n\tINIT_FLAGS( flags, 0 );\n\tSET_FLAG( flags, 0x100 );\n\tif( CHECK_FLAGS( flags, 0x00, 0x80 ) )\n\t\treturn( FALSE );\n\tINIT_FLAGS( flags, 0 );\n\tflags.flagValue |= 0x01;\n\tif( CHECK_FLAGS( flags, 0x00, 0x80 ) )\n\t\treturn( FALSE );\n\tCFI_CHECK_UPDATE( \"bitflags\" ); \n\n\t/* Test the error-detecting pointer mechanisms.  We only check data\n\t   pointers since function pointers are implemented identically */\n\tDATAPTR_SET( testPtr, &testBool );\n\tif( DATAPTR_GET( testPtr ) != &testBool )\n\t\treturn( FALSE );\n\ttestPtr.dataCheck ^= 0x0800;\t\t/* Hidden variable used to check testPtr */\n\tif( DATAPTR_ISVALID( testPtr ) || DATAPTR_ISSET( testPtr ) || \\\n\t\tDATAPTR_ISNULL( testPtr ) || DATAPTR_GET( testPtr ) != NULL )\n\t\treturn( FALSE );\n\tCFI_CHECK_UPDATE( \"pointers\" ); \n\n\t/* Test the function-call CFI protection mechanism */\n\tif( !testCFITrue( MK_TOKEN( \"testCFITrue\" ) ) || \\\n\t\t!testCFIFalse( MK_TOKEN( \"testCFITrue\" ) ) ) \n\t\treturn( FALSE );\n\tCFI_CHECK_UPDATE( \"CFI\" ); \n\n\t/* Test the bounded-loop mechanisms.  There are many variants of this, \n\t   we only check the basic forms */\n\tLOOP_SMALL( i = 0, i < 5, i++ );\n\tif( !LOOP_BOUND_OK )\n\t\treturn( FALSE );\n\tLOOP_SMALL( i = 0, i < 20, i++ );\n\tif( LOOP_BOUND_OK )\n\t\treturn( FALSE );\n\tLOOP_SMALL_ALT( i = 0, i < 5, i++ );\n\tif( !LOOP_BOUND_OK_ALT )\n\t\treturn( FALSE );\n\tLOOP_SMALL_ALT( i = 0, i < 20, i++ );\n\tif( LOOP_BOUND_OK_ALT )\n\t\treturn( FALSE );\n/*\tLOOP_SMALL_ALT2( i = 0, i < 20, i++ );\n\tif( LOOP_BOUND_OK_ALT2 )\n\t\treturn( FALSE ); - No LOOP_SMALL_ALT2 */\n\tCFI_CHECK_UPDATE( \"loops\" ); \n\n\t/* Test the buffer overrun protection */\n\tmemset( buffer, 0, SAFE_BUFFER_SIZE + 16 );\n\tbufPtr = SAFEBUFFER_PTR( buffer );\n\tsafeBufferInit( bufPtr, SAFE_BUFFER_SIZE );\n\tif( !safeBufferCheck( bufPtr, SAFE_BUFFER_SIZE ) )\n\t\treturn( FALSE );\t/* Basic check */\n\tsavedValue = bufPtr[ -1 ];\n\tbufPtr[ -1 ]++;\n\tif( safeBufferCheck( bufPtr, SAFE_BUFFER_SIZE ) )\n\t\treturn( FALSE );\t/* Corrupt buffer start */\n\tbufPtr[ -1 ] = savedValue;\n\tif( !safeBufferCheck( bufPtr, SAFE_BUFFER_SIZE ) )\n\t\treturn( FALSE );\t/* Redo basic check */\n\tbufPtr[ SAFE_BUFFER_SIZE + 2 ]++;\n\tif( safeBufferCheck( bufPtr, SAFE_BUFFER_SIZE ) )\n\t\treturn( FALSE );\t/* Corrupt buffer end */\n\tCFI_CHECK_UPDATE( \"buffers\" ); \n\n\t/* Test the sequence-point CFI mechanism */\n\tif( !CFI_CHECK_SEQUENCE_6( \"BOOLEAN\", \"bitflags\", \"pointers\", \"CFI\", \n\t\t\t\t\t\t\t   \"loops\", \"buffers\" ) )\n\t\treturn( FALSE );\n\tif( CFI_CHECK_SEQUENCE_6( \"BOOLEAN\", \"pointers\", \"bitflags\", \"CFI\", \n\t\t\t\t\t\t\t  \"loops\", \"buffers\" ) )\n\t\treturn( FALSE );\n\tif( CFI_CHECK_SEQUENCE_6( \"BOOLEAN\", \"bitflags\", \"loops\", \"buffers\", \n\t\t\t\t\t\t\t  \"pointers\", \"CFI\" ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAlgorithm Self-test Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Self-test code for several general crypto algorithms that are used\n   internally all over cryptlib: MD5, SHA-1, SHA-2, 3DES, and AES */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN testGeneralAlgorithms( void )\n\t{\n#ifndef CONFIG_NO_SELFTEST\n\tconst CAPABILITY_INFO *capabilityInfo;\n\tint status;\n\n#ifdef USE_MD5\n\t/* Test the MD5 functionality */\n\tcapabilityInfo = getMD5Capability();\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"MD5 self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_MD5 */\n\n\t/* Test the SHA-1 functionality */\n\tcapabilityInfo = getSHA1Capability();\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"SHA-1 self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test the SHA-2 functionality */\n\tcapabilityInfo = getSHA2Capability();\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"SHA-2 self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test the 3DES functionality */\n#ifdef USE_3DES\n\tcapabilityInfo = get3DESCapability();\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"3DES self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_3DES */\n\n\t/* Test the AES functionality */\n#ifdef USE_AES\n\tcapabilityInfo = getAESCapability();\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"AES self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_AES */\n#endif /* CONFIG_NO_SELFTEST */\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKernel Self-test Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Test the kernel mechanisms to make sure that everything's working as\n   expected.  This performs the following tests:\n\n   General:\n\n\tObject creation.\n\n   Access checks:\n\n\tInability to access internal object or attribute via external message.\n\tInability to perform an internal-only action externally, ability to\n\t\tperform an internal-only action internally\n\n   Attribute checks:\n\n\tAttribute range checking for numeric, string, boolean, and time\n\t\tattributes.\n\tInability to write a read-only attribute, read a write-only attribute,\n\t\tor delete a non-deletable attribute.\n\n   Object state checks:\n\n\tAbility to perform standard operation on object, ability to transition a\n\t\tstate = low object to state = high.\n\tInability to perform state = high operation on state = low object,\n\t\tinability to perform state = low operation on state = high object.\n\n   Object property checks:\n\n\tAbility to use an object with a finite usage count, inability to\n\t\tincrement the count, ability to decrement the count, inability to\n\t\texceed the usage count.\n\tAbility to lock an object, inability to change security parameters once\n\t\tit's locked */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkNumericRange( IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\n\t/* Verify kernel range checking of numeric values */\n\tvalue = -10;\t\t/* Below (negative) */\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = 0;\t\t\t/* Lower bound fencepost error */\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = 1;\t\t\t/* Lower bound */\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tvalue = MAX_KEYSETUP_ITERATIONS / 2;\t/* Mid-range */\n\tkrnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tvalue = MAX_KEYSETUP_ITERATIONS;\t\t/* Upper bound */\n\tkrnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tvalue = MAX_KEYSETUP_ITERATIONS + 1;\t/* Upper bound fencepost error */\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = MAX_KEYSETUP_ITERATIONS * 50;\t/* High */\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkStringRange( IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ CRYPT_MAX_HASHSIZE + 1 + 8 ];\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\n\t/* Verify kernel range checking of string values.  We have to disable \n\t   the more outrageous out-of-bounds values in the debug version since \n\t   they'll cause the debug kernel to throw an exception if it sees \n\t   them.  In addition for internal messages this results in an internal-\n\t   error status rather than a argument-error status since the values are\n\t   so far out of their allowed range that it's reported as a problem \n\t   with the caller rather than with the parameters used */\n\tmemset( buffer, '*', CRYPT_MAX_HASHSIZE + 1 );\n#ifdef NDEBUG\n\t/* Below (negative) */\n\tsetMessageData( &msgData, buffer, -10 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ERROR_INTERNAL )\n\t\treturn( FALSE );\n#endif /* NDEBUG */\n\t/* Lower bound fencepost error */\n\tsetMessageData( &msgData, buffer, 7 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\t/* Lower bound */\n\tsetMessageData( &msgData, buffer, 8 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )\n\t\treturn( FALSE );\n\t/* Mid-range */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE / 2 );\n\tkrnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )\n\t\treturn( FALSE );\n\t/* Upper bound */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );\n\tkrnlSendMessage( iCryptContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )\n\t\treturn( FALSE );\n\t/* Upper bound fencepost error */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE + 1 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n#ifdef NDEBUG\n\t/* High */\n\tsetMessageData( &msgData, buffer, 32767 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ERROR_INTERNAL )\n\t\treturn( FALSE );\n#endif /* NDEBUG */\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkUsageCount( IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tBYTE buffer[ 16 + 8 ];\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\n\t/* Verify the ability to use an object with a finite usage count, the\n\t   inability to increment the count, the ability to decrement the count,\n\t   and the inability to exceed the usage count */\n\tvalue = 10;\n\tmemset( buffer, 0, 16 );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_USAGECOUNT ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, 16 ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tvalue = 20;\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_USAGECOUNT ) != CRYPT_ERROR_PERMISSION )\n\t\treturn( FALSE );\n\tvalue = 1;\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_USAGECOUNT ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, 16 ) != CRYPT_OK || \\\n\t\tkrnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, 16 ) != CRYPT_ERROR_PERMISSION )\n\t\treturn( FALSE );\n\n\t/* Note that at this point the usage count is zero so no further \n\t   operations with the object are possible */\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkLocking( IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\n\t/* Verify the ability to lock an object and the inability to change\n\t   security parameters once it's locked */\n\tvalue = 5;\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_OK || \\\n\t\tkrnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t CRYPT_PROPERTY_HIGHSECURITY ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_LOCKED ) != CRYPT_OK || \\\n\t\tvalue != TRUE || \\\n\t\tkrnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_ERROR_PERMISSION )\n\t\t{\n\t\t/* Object should be locked, forwardcount should be inaccessible */\n\t\treturn( FALSE );\n\t\t}\n\tvalue = 1;\n\tif( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_ERROR_PERMISSION )\n\t\t{\n\t\t/* Security parameters shouldn't be writeable */\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n#ifdef USE_CERTIFICATES\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkBooleanRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )\n\t{\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptCertificate ) );\n\n\t/* Verify functioning of the kernel range checking, phase 3: Boolean\n\t   values.  Any value should be OK, with conversion to TRUE/FALSE */\n\tvalue = 0;\t\t/* FALSE */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \\\n\t\tvalue != FALSE )\n\t\treturn( FALSE );\n\tvalue = 1;\t\t/* TRUE */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \\\n\t\tvalue != TRUE )\n\t\treturn( FALSE );\n\tvalue = 10000;\t/* Positive true-equivalent */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \\\n\t\tvalue != TRUE )\n\t\treturn( FALSE );\n\tvalue = -1;\t\t/* Negative true-equivalent */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \\\n\t\tvalue != TRUE )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkTimeRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )\n\t{\n\tMESSAGE_DATA msgData;\n\ttime_t timeVal;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptCertificate ) );\n\n\t/* Verify kernel range checking of time values.  Any value above the \n\t   initial cutoff date should be OK */\n\tsetMessageData( &msgData, &timeVal, sizeof( time_t ) );\n\ttimeVal = 10;\t\t\t\t\t/* Below */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )\n\t\treturn( FALSE );\n\ttimeVal = MIN_TIME_VALUE;\t\t/* Lower bound fencepost error */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )\n\t\treturn( FALSE );\n\ttimeVal = MIN_TIME_VALUE + 1;\t/* Lower bound */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_OK )\n\t\treturn( FALSE );\n\ttimeVal = roundUp( timeVal, 0x10000000L );\t/* Mid-range */\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_OK )\n\t\treturn( FALSE );\n\ttimeVal = MAX_TIME_VALUE - 1;\t/* Upper bound */\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_OK )\n\t\treturn( FALSE );\n\ttimeVal = MAX_TIME_VALUE;\t\t/* Upper bound fencepost error */\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )\n\t\treturn( FALSE );\n\ttimeVal = MAX_TIME_VALUE + ( 365 * 86400 );\t/* Above */\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkAllowedValuesRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ 16 + 8 ];\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptCertificate ) );\n\n\t/* Verify kernel range checking of special-case allowed values.  Valid \n\t   values are either a 4-byte IPv4 address or a 16-byte IPv6 address */\n\tvalue = CRYPT_CERTINFO_SUBJECTALTNAME;\n\tmemset( buffer, 0, 16 );\n\tsetMessageData( &msgData, buffer, 3 );\t/* Below, allowed value 1 */\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tsetMessageData( &msgData, buffer, 4 );\t/* Equal, allowed value 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS );\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\n\tsetMessageData( &msgData, buffer, 5 );\t/* Above, allowed value 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tsetMessageData( &msgData, buffer, 15 );\t/* Below, allowed value 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tsetMessageData( &msgData, buffer, 16 );\t/* Equal, allowed value 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_OK )\n\t\treturn( FALSE );\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS );\n\tkrnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\n\tsetMessageData( &msgData, buffer, 17 );\t/* Above, allowed value 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CERTINFO_IPADDRESS ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkSubrangeRange( IN_HANDLE const CRYPT_CONTEXT iCryptCertificate )\n\t{\n\tint value;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptCertificate ) );\n\n\t/* Verify kernel range checking of special-case subranges.  Valid values \n\t   are either CRYPT_CURSOR_FIRST ... CRYPT_CURSOR_LAST or an extension \n\t   ID.  Since the cursor movement codes are negative values an out-of-\n\t   bounds value is MIN + 1 or MAX - 1, not the other way round */\n\tvalue = CRYPT_CURSOR_FIRST + 1;\t\t\t/* Below, subrange 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CURSOR_FIRST;\t\t\t\t/* Low bound, subrange 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ERROR_NOTFOUND )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CURSOR_LAST;\t\t\t\t/* High bound, subrange 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ERROR_NOTFOUND )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CURSOR_LAST - 1;\t\t\t/* Above, subrange 1 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CERTINFO_FIRST_EXTENSION - 1;\t/* Below, subrange 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CERTINFO_FIRST_EXTENSION;\t\t/* Low bound, subrange 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ERROR_NOTFOUND )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CERTINFO_LAST_EXTENSION;\t\t/* High bound, subrange 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ERROR_NOTFOUND )\n\t\treturn( FALSE );\n\tvalue = CRYPT_CERTINFO_LAST_EXTENSION + 1;\t/* Above, subrange 2 */\n\tif( krnlSendMessage( iCryptCertificate, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT_GROUP ) != CRYPT_ARGERROR_NUM1 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_CERTIFICATES */\n\nCHECK_RETVAL \\\nstatic BOOLEAN testKernelMechanisms( void )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tCRYPT_CONTEXT iCryptHandle;\n#ifdef DEFAULT_ALGO_AES\n\tstatic const BYTE key[] = \\\n\t\t{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n\t\t  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };\n\t/* AES FIPS test keys */\n\tstatic const BYTE iv[] = \\\n\t\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t\t  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n\tstatic const int blockSize = 16, keySize = 16;\n#else\n\tstatic const BYTE key[] = \\\n\t\t{ 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,\n\t\t  0x51, 0x07, 0xB0, 0x15, 0x19, 0x58, 0x01, 0x01,\n\t\t  0x19, 0x07, 0x92, 0x10, 0x98, 0x1A, 0x01, 0x01 };\n\t/* Single-DES keys pulled from NBS 500-20 Data Permutation\n\t   test vectors */\n\tstatic const BYTE iv[] = \\\n\t\t{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\n\tstatic const int blockSize = 8, keySize = 24;\n#endif /* DEFAULT_ALGO_AES */\n\tBYTE buffer[ 128 + 8 ];\n\tint value, status;\n\n\t/* CRYPT_ALGO_3DES is an enum and so isn't visible to the preprocessor,\n\t   so we have to hardcode in its actual value above, which we check\n\t   here */\n\tstatic_assert( CRYPT_ALGO_3DES  == 2, \"3DES algorithm ID\" );\n\n\t/* Verify object creation */\n\tsetMessageCreateObjectInfo( &createInfo, DEFAULT_CRYPT_ALGO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Object creation self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tiCryptHandle = createInfo.cryptHandle;\n\n\t/* Verify the inability to access an internal object or attribute using\n\t   an external message.  The attribute access will be stopped by the\n\t   object access check before it even gets to the attribute access check,\n\t   so we also re-do the check further on when the object is made\n\t   externally visible to verify the attribute-level checks as well */\n\tif( krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_ALGO ) != CRYPT_ARGERROR_OBJECT || \\\n\t\tkrnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_IATTRIBUTE_TYPE ) != CRYPT_ARGERROR_VALUE )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object internal/external self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the ability to perform standard operations and the inability\n\t   to perform a state = high operation on a state = low object */\n\tmemset( buffer, 0, 16 );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) iv, blockSize );\n\tif( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_IV ) != CRYPT_OK || \\\n\t\tkrnlSendMessage( iCryptHandle, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, blockSize ) != CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object low/high state self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the functioning of kernel range checking, phase 1: Numeric\n\t   values */\n\tif( !checkNumericRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel numeric range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the functioning of kernel range checking, phase 2: String\n\t   values */\n\tif( !checkStringRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel string range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the ability to transition a state = low object to state =\n\t   high */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) key, keySize );\n\tif( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEY ) != CRYPT_OK )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object state transition self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the inability to write a read-only attribute, read a write-\n\t   only attribute, or delete a non-deletable attribute */\n\tvalue = CRYPT_MODE_CBC;\n\tsetMessageData( &msgData, NULL, 0 );\n\tif( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CTXINFO_BLOCKSIZE ) != CRYPT_ERROR_PERMISSION || \\\n\t\tkrnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEY ) != CRYPT_ERROR_PERMISSION || \\\n\t\tkrnlSendMessage( iCryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t CRYPT_CTXINFO_MODE ) != CRYPT_ERROR_PERMISSION )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Attribute read/write self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the inability to perform state = low operations on a state =\n\t   high object */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) key, keySize );\n\tif( krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t CRYPT_CTXINFO_KEY ) != CRYPT_ERROR_PERMISSION || \\\n\t\tkrnlSendNotifier( iCryptHandle, \n\t\t\t\t\t\t  IMESSAGE_CTX_GENKEY ) != CRYPT_ERROR_PERMISSION )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object state access self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the inability to perform an internal-only action externally\n\t   but still perform it internally.  We also repeat the internal-only\n\t   attribute test from earlier on, this access is now stopped at the\n\t   attribute check level rather than the object-check level.\n\n\t   The object will become very briefly visible externally at this point,\n\t   but there's nothing that can be done with it because of the\n\t   permission settings, and it's destroyed as soon as the internal/\n\t   external tests are completed */\n\tvalue = \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );\n\tmemset( buffer, 0, 16 );\n\tkrnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, &value,\n\t\t\t\t\t CRYPT_IATTRIBUTE_ACTIONPERMS );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INTERNAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We couldn't make the object external (which can only really \n\t\t   happen due to an internal error), explicitly destroy it since \n\t\t   it's uncertain whether we should decrement an internal or \n\t\t   external reference */\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DESTROY );\n\t\tDEBUG_DIAG(( \"Object internal/external action self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( krnlSendMessage( iCryptHandle, MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, blockSize ) != CRYPT_ERROR_PERMISSION || \\\n\t\tkrnlSendMessage( iCryptHandle, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t buffer, blockSize ) != CRYPT_OK )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, MESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object internal/external action self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_IATTRIBUTE_TYPE ) != CRYPT_ARGERROR_VALUE )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, MESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object internal/external action self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The following checks modify object properties and, as a side-effect,\n\t   render them less and less usable as the checks progress.  For this\n\t   reason they have to be executed in a set order, the usage-count check\n\t   (which disables the ability to perform operations with the object)\n\t   as the second-to-last check, and the locking check, which disables\n\t   the ability to change object properties, as the last check.  Once \n\t   this check has completed, the object is locked down to a level where\n\t   it can't be used any more */\n\n\t/* Verify the ability to use an object with a finite usage count, the\n\t   inability to increment the count, the ability to decrement the count,\n\t   and the inability to exceed the usage count.\n\t   \n\t   After this check the usage count has dropped to zero so the object is\n\t   no longer usable for standard operations */\n\tif( !checkUsageCount( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, MESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object usage-count self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify the ability to lock an object and the inability to change\n\t   security parameters once it's locked.\n\t   \n\t   After this check any further changes on the security-relevant object \n\t   properties are no longer possible */\n\tif( !checkLocking( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, MESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Object locking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* We've finished with the object (and in any case it's locked down to \n\t   the point where it's no longer usable), destroy it */\n\tstatus = krnlSendNotifier( iCryptHandle, MESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Object destroy failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The following checks require that use of certificates be enabled in\n\t   order to perform them.  This is because these attribute types are\n\t   only valid for certificates (or, by extension, certificate-using\n\t   object types like envelopes and sessions).  So although these\n\t   attribute ACLs won't be tested if certificates aren't enabled, they\n\t   also won't be used if certificates aren't enabled */\n#ifdef USE_CERTIFICATES\n\n\t/* Create a cert object for the remaining kernel range checks */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Certificate object creation self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tiCryptHandle = createInfo.cryptHandle;\n\n\t/* Verify functioning of the kernel range checking, phase 3: Boolean\n\t   values */\n\tif( !checkBooleanRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel boolean range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify functioning of the kernel range checking, phase 4: Time\n\t   values */\n\tif( !checkTimeRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel time range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify functioning of kernel range-checking, phase 6: Special-case\n\t   checks, allowed values */\n\tif( !checkAllowedValuesRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel allowed-values range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Verify functioning of kernel range-checking, phase 6: Special-case\n\t   checks, subranges */\n\tif( !checkSubrangeRange( iCryptHandle ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tDEBUG_DIAG(( \"Kernel subranges range checking self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tkrnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );\n#endif /* USE_CERTIFICATES */\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGeneral Self-test Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Run internal-function self-tests.  There are two general tests that are \n   run, testFunctionality() which is an overall sanity-check of general\n   functionality before we try anything else, and testKernel(), which runs\n   much later and tests the kernel mechanisms */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntAPI( void );\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntString( void );\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntTime( void );\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntBN( void );\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN testInternalFunctions( void )\n\t{\n\tif( !testIntAPI() )\n\t\t{\n\t\tDEBUG_DIAG(( \"int_api.c self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !testIntString() )\n\t\t{\n\t\tDEBUG_DIAG(( \"int_string.c self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !testIntTime() )\n\t\t{\n\t\tDEBUG_DIAG(( \"int_time.c self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !testIntBN() )\n\t\t{\n\t\tDEBUG_DIAG(( \"ctx_bn.c self-test failed\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL \\\nint testFunctionality( void )\n\t{\n\tENSURES_NOFAULT( testSafetyMechanisms() );\n\tENSURES_NOFAULT( testGeneralAlgorithms() );\n\tENSURES_NOFAULT( testInternalFunctions() );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint testKernel( void )\n\t{\n\tENSURES_NOFAULT( testKernelMechanisms() );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n"
  },
  {
    "path": "deps/cl345/kernel/semaphore.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSemaphores and Mutexes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A template to initialise the semaphore table */\n\nstatic const SEMAPHORE_INFO SEMAPHORE_INFO_TEMPLATE = \\\n\t\t\t\t{ SEMAPHORE_STATE_UNINITED, 0, 0 };\n\n/* Create and destroy the semaphores and mutexes.  Since mutexes usually \n   aren't scalar values and are declared and accessed via macros that \n   manipulate various fields, we have to handle a pile of them individually \n   rather than using an array of mutexes */\n\nCHECK_RETVAL \\\nint initSemaphores( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint i, status, LOOP_ITERATOR;\n\n#ifdef USE_SESSIONS\n\tstatic_assert( MUTEX_LAST == 5, \"Mutex value\" );\n#else\n\tstatic_assert( MUTEX_LAST == 2, \"Mutex value\" );\n#endif /* USE_SESSIONS */\n\n\t/* Clear the semaphore table */\n\tLOOP_SMALL( i = 0, i < SEMAPHORE_LAST, i++ )\n\t\tkrnlData->semaphoreInfo[ i ] = SEMAPHORE_INFO_TEMPLATE;\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Initialize any data structures required to make the semaphore table\n\t   thread-safe */\n\tMUTEX_CREATE( semaphore, status );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Initialize the mutexes */\n\tMUTEX_CREATE( mutex1, status );\n\tENSURES( cryptStatusOK( status ) );\n#ifdef USE_SESSIONS\n\tMUTEX_CREATE( mutex2, status );\n\tENSURES( cryptStatusOK( status ) );\n\tMUTEX_CREATE( mutex3, status );\n\tENSURES( cryptStatusOK( status ) );\n\tMUTEX_CREATE( mutex4, status );\n\tENSURES( cryptStatusOK( status ) );\n#endif /* USE_SESSIONS */\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid endSemaphores( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\tREQUIRES_V( ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\t  krnlData->shutdownLevel == SHUTDOWN_LEVEL_NONE ) || \\\n\t\t\t\t( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \\\n\t\t\t\t  krnlData->shutdownLevel == SHUTDOWN_LEVEL_MESSAGES ) || \\\n\t\t\t\t( krnlData->initLevel == INIT_LEVEL_FULL && \\\n\t\t\t\t  krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES ) );\n\n\t/* Signal that kernel mechanisms are no longer available */\n\tkrnlData->shutdownLevel = SHUTDOWN_LEVEL_MUTEXES;\n\n\t/* Shut down the mutexes */\n#ifdef USE_SESSIONS\n\tMUTEX_DESTROY( mutex4 );\n\tMUTEX_DESTROY( mutex3 );\n\tMUTEX_DESTROY( mutex2 );\n#endif /* USE_SESSIONS */\n\tMUTEX_DESTROY( mutex1 );\n\n\t/* Destroy any data structures required to make the semaphore table\n\t   thread-safe */\n\tMUTEX_DESTROY( semaphore );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSemaphore Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_THREAD_FUNCTIONS\n\n/* Under multithreaded OSes, we often need to wait for certain events before\n   we can continue (for example when asynchronously accessing system\n   objects anything that depends on the object being available needs to\n   wait for the access to complete) or handle mutual exclusion when accessing\n   a shared resource.  The following functions abstract this handling,\n   providing a lightweight semaphore mechanism via mutexes, which is used \n   before checking a system synchronisation object (mutexes usually don't\n   require a kernel entry, while semaphores usually do).  The semaphore \n   function works a bit like the Win32 Enter/LeaveCriticalSection() \n   routines, which perform a quick check on a user-level lock and only call \n   the kernel-level handler if necessary (in most cases this isn't \n   necessary).  A useful side-effect is that since they work with \n   lightweight local locks instead of systemwide locking objects, they \n   aren't vulnerable to security problems where (for example) another \n   process can mess with a globally visible object handle.  This is \n   particularly problematic under Windows, where (for example) CreateMutex()\n   can return a handle to an already-existing object of the same name rather\n   than a newly-created object (there's no O_EXCL functionality).\n\n   Semaphores are one-shots, so that once set and cleared they can't be\n   reset.  This is handled by enforcing the following state transitions:\n\n\tUninited -> Set | Clear\n\tSet -> Set | Clear\n\tClear -> Clear\n\n   The handling is complicated somewhat by the fact that on some systems the\n   semaphore has to be explicitly deleted, but only the last thread to use it\n   can safely delete it.  In order to handle this, we reference-count the\n   semaphore and let the last thread out delete it.  This is handled by\n   introducing an additional state preClear, which indicates that while the\n   semaphore object is still present, the last thread out should delete it,\n   bringing it to the true clear state */\n\nvoid setSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore,\n\t\t\t\t   const MUTEX_HANDLE object )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tSEMAPHORE_INFO *semaphoreInfo;\n\n\tREQUIRES_V( isEnumRange( semaphore, SEMAPHORE ) );\n\n\t/* It's safe to get a pointer to this outside the lock, we just can't\n\t   access it yet */\n\tsemaphoreInfo = &krnlData->semaphoreInfo[ semaphore ];\n\n\t/* Lock the semaphore table, set the semaphore, and unlock it again */\n\tMUTEX_LOCK( semaphore );\n\tif( semaphoreInfo->state == SEMAPHORE_STATE_UNINITED )\n\t\t{\n\t\t/* The semaphore can only be set if it's currently in the uninited \n\t\t   state.  Since the semaphore handle may be a non-scalar type we\n\t\t   have to use a cast to make it non-const (semaphoreInfo->object\n\t\t   can be const if it's a pointer but has to be non-const if it's\n\t\t   a scalar) */\n\t\t*semaphoreInfo = SEMAPHORE_INFO_TEMPLATE;\n\t\tsemaphoreInfo->state = SEMAPHORE_STATE_SET;\n\t\tsemaphoreInfo->object = ( MUTEX_HANDLE ) object;\n\t\t}\n\tMUTEX_UNLOCK( semaphore );\n\t}\n\nvoid clearSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tSEMAPHORE_INFO *semaphoreInfo;\n\n\tREQUIRES_V( isEnumRange( semaphore, SEMAPHORE ) );\n\n\t/* It's safe to get a pointer to this outside the lock, we just can't\n\t   access it yet */\n\tsemaphoreInfo = &krnlData->semaphoreInfo[ semaphore ];\n\n\t/* Lock the semaphore table, clear the semaphore, and unlock it again */\n\tMUTEX_LOCK( semaphore );\n\tif( semaphoreInfo->state == SEMAPHORE_STATE_SET )\n\t\t{\n\t\t/* Precondition: The reference count is valid.  Note that we have to\n\t\t   make this an assert() rather than a REQUIRES() because the latter\n\t\t   would exit with the semaphore still held */\n#if !( defined( __WINCE__ ) && _WIN32_WCE < 400 )\n\t\tassert( semaphoreInfo[ semaphore ].refCount >= 0 );\n#endif /* Fix for bug in PocketPC 2002 emulator with eVC++ 3.0 */\n\n\t\t/* If there are threads waiting on this semaphore, tell the last\n\t\t   thread out to turn out the lights */\n\t\tif( semaphoreInfo->refCount > 0 )\n\t\t\tsemaphoreInfo->state = SEMAPHORE_STATE_PRECLEAR;\n\t\telse\n\t\t\t{\n\t\t\t/* No threads waiting on the semaphore, we can delete it */\n\t\t\tTHREAD_CLOSE( semaphoreInfo->object );\n\t\t\t*semaphoreInfo = SEMAPHORE_INFO_TEMPLATE;\n\t\t\t}\n\t\t}\n\tMUTEX_UNLOCK( semaphore );\n\t}\n\n/* Wait on a semaphore.  This occurs in two phases, first we extract the\n   information that we need from the semaphore table, then we unlock it and \n   wait on the semaphore if necessary.  This is necessary because the wait \n   can take an indeterminate amount of time and we don't want to tie up the \n   other semaphores while this occurs.  Note that this type of waiting on \n   local (rather than system) semaphores where possible greatly improves\n   performance, in some cases the wait on a signalled system semaphore can\n   take several seconds whereas waiting on the local semaphore only takes a\n   few ms.  Once the wait has completed, we update the semaphore state as\n   per the longer description above */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN krnlWaitSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tSEMAPHORE_INFO *semaphoreInfo;\n#ifdef NONSCALAR_HANDLES\n\tMUTEX_HANDLE *object DUMMY_INIT_PTR;\n#else\n\tMUTEX_HANDLE object DUMMY_INIT_MUTEX;\n#endif /* NONSCALAR_HANDLES */\n\tBOOLEAN semaphoreSet = FALSE;\n\tint status = CRYPT_OK;\n\n\tREQUIRES_B( isEnumRange( semaphore, SEMAPHORE ) );\n\n\t/* If we're in a shutdown and the semaphores have been destroyed, don't\n\t   try and acquire the semaphore mutex.  In this case anything that \n\t   they're protecting should be set to a shutdown state in which any \n\t   access fails, so this isn't a problem */\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MUTEXES )\n\t\treturn( FALSE );\n\n\t/* Lock the semaphore table, extract the information that we need, and \n\t   unlock it again */\n\tsemaphoreInfo = &krnlData->semaphoreInfo[ semaphore ];\n\tMUTEX_LOCK( semaphore );\n\tif( semaphoreInfo->state == SEMAPHORE_STATE_SET )\n\t\t{\n\t\t/* Precondition: The reference count is valid.  Note that we have to\n\t\t   make this an assert() rather than a REQUIRES() because the latter\n\t\t   would exit with the semaphore still held */\n\t\tassert( semaphoreInfo->refCount >= 0 );\n\n\t\t/* The semaphore is set and not in use, extract the information we\n\t\t   require and mark is as being in use */\n#ifdef NONSCALAR_HANDLES\n\t\tobject = &semaphoreInfo->object;\n#else\n\t\tobject = semaphoreInfo->object;\n#endif /* NONSCALAR_HANDLES */\n\t\tsemaphoreInfo->refCount++;\n\t\tsemaphoreSet = TRUE;\n\t\t}\n\tMUTEX_UNLOCK( semaphore );\n\n\t/* If the semaphore wasn't set or is in use, exit now */\n\tif( !semaphoreSet )\n\t\treturn( TRUE );\n\n\t/* Wait on the object */\n#ifdef NONSCALAR_HANDLES\n\tassert( memcmp( object, &SEMAPHORE_INFO_TEMPLATE.object,\n\t\t\t\t\tsizeof( MUTEX_HANDLE ) ) );\n#else\n\tassert( memcmp( &object, &SEMAPHORE_INFO_TEMPLATE.object,\n\t\t\t\t\tsizeof( MUTEX_HANDLE ) ) );\n#endif /* NONSCALAR_HANDLES */\n\tTHREAD_WAIT( object, status );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Wait on object failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Lock the semaphore table, update the information, and unlock it\n\t   again */\n\tMUTEX_LOCK( semaphore );\n\tif( semaphoreInfo->state == SEMAPHORE_STATE_SET || \\\n\t\tsemaphoreInfo->state == SEMAPHORE_STATE_PRECLEAR )\n\t\t{\n\t\t/* The semaphore is still set, update the reference count */\n\t\tsemaphoreInfo->refCount--;\n\n\t\t/* Inner precondition: The reference count is valid.  Note that we \n\t\t   have to make this an assert() rather than a REQUIRES() because \n\t\t   the latter would exit with the semaphore still held */\n\t\tassert( semaphoreInfo->refCount >= 0 );\n\n\t\t/* If the object owner has signalled that it's done with the object\n\t\t   and the reference count has reached zero, we can delete it */\n\t\tif( semaphoreInfo->state == SEMAPHORE_STATE_PRECLEAR || \\\n\t\t\tsemaphoreInfo->refCount <= 0 )\n\t\t\t{\n\t\t\t/* No threads waiting on the semaphore, we can delete it */\n\t\t\tTHREAD_CLOSE( object );\n\t\t\t*semaphoreInfo = SEMAPHORE_INFO_TEMPLATE;\n\t\t\t}\n\t\t}\n\tMUTEX_UNLOCK( semaphore );\n\t\n\treturn( TRUE );\n\t}\n#else\n\n/* krnlWaitSemaphore() is only used if threading functions are enabled, \n   however this is an externally-visible API so we need to provide a dummy\n   replacement for it as opposed to the kernel-internal setSemaphore()/\n   clearSemaphore() which can be relaced with a #define */ \n\nCHECK_RETVAL_BOOL \\\nBOOLEAN krnlWaitSemaphore( IN_ENUM( SEMAPHORE ) const SEMAPHORE_TYPE semaphore )\n\t{\n\treturn( TRUE );\n\t}\n#endif /* USE_THREAD_FUNCTIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMutex Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enter and exit a mutex */\n\nCHECK_RETVAL \\\nint krnlEnterMutex( IN_ENUM( MUTEX ) const MUTEX_TYPE mutex )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\tREQUIRES( isEnumRange( mutex, MUTEX ) );\n\n\t/* If we're in a shutdown and the mutexes have been destroyed, don't\n\t   try and acquire them.  In this case anything that they're protecting\n\t   should be set to a shutdown state in which any access fails, so this\n\t   isn't a problem */\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MUTEXES )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\tswitch( mutex )\n\t\t{\n\t\tcase MUTEX_RANDOM:\n\t\t\tMUTEX_LOCK( mutex1 );\n\t\t\tbreak;\n\n#ifdef USE_SESSIONS\n\t\tcase MUTEX_SCOREBOARD:\n\t\t\tMUTEX_LOCK( mutex2 );\n\t\t\tbreak;\n\n\t\tcase MUTEX_SOCKETPOOL:\n\t\t\tMUTEX_LOCK( mutex3 );\n\t\t\tbreak;\n\n\t\tcase MUTEX_CRYPTODELAY:\n\t\t\tMUTEX_LOCK( mutex4 );\n\t\t\tbreak;\n#endif /* USE_SESSIONS */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid krnlExitMutex( IN_ENUM( MUTEX ) const MUTEX_TYPE mutex )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\n\tREQUIRES_V( isEnumRange( mutex, MUTEX ) );\n\n\t/* If we're in a shutdown and the mutexes have been destroyed, don't\n\t   try and acquire them.  In this case anything that they're protecting\n\t   should be set to a shutdown state in which any access fails, so this\n\t   isn't a problem */\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MUTEXES )\n\t\treturn;\n\n\tswitch( mutex )\n\t\t{\n\t\tcase MUTEX_RANDOM:\n\t\t\tMUTEX_UNLOCK( mutex1 );\n\t\t\tbreak;\n\n#ifdef USE_SESSIONS\n\t\tcase MUTEX_SCOREBOARD:\n\t\t\tMUTEX_UNLOCK( mutex2 );\n\t\t\tbreak;\n\n\t\tcase MUTEX_SOCKETPOOL:\n\t\t\tMUTEX_UNLOCK( mutex3 );\n\t\t\tbreak;\n\n\t\tcase MUTEX_CRYPTODELAY:\n\t\t\tMUTEX_UNLOCK( mutex4 );\n\t\t\tbreak;\n#endif /* USE_SESSIONS */\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/sendmsg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKernel Message Dispatcher\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"acl.h\"\n  #include \"kernel.h\"\n#else\n  #include \"crypt.h\"\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n#endif /* Compiler-specific includes */\n\n/* The ACL used to check objects passed as message parameters, in this case\n   for certificate sign/sig-check messages */\n\nstatic const MESSAGE_ACL messageParamACLTbl[] = {\n\t/* Certificates can only be signed by (private-key) PKC contexts */\n\t{ MESSAGE_CRT_SIGN,\n\t  { ST_CTX_PKC,\n\t\tST_NONE, ST_NONE } },\n\n\t/* Signatures can be checked with a raw PKC context or a certificate/\n\t   certificate chain (but see the long discussion in certs/certschk.c \n\t   for details on this).  The object being checked can also be checked \n\t   against a CRL or CRL-equivalent like an RTCS or OCSP response, \n\t   against revocation data in a certificate store, or against an RTCS or \n\t   OCSP responder */\n\t{ MESSAGE_CRT_SIGCHECK,\n\t  { ST_CTX_PKC | MKTYPE_CERTIFICATES( ST_CERT_CERT ) | \\\n\t\t\tMKTYPE_CERTIFICATES( ST_CERT_CERTCHAIN ) | \\\n\t\t\tMKTYPE_CERTREV( ST_CERT_CRL ) | MKTYPE_CERTVAL( ST_CERT_RTCS_RESP ) | \\\n\t\t\tMKTYPE_CERTREV( ST_CERT_OCSP_RESP ),\n\t    MKTYPE_DBMS( ST_KEYSET_DBMS ) | MKTYPE_DBMS( ST_KEYSET_DBMS_STORE ),\n\t\tMKTYPE_RTCS( ST_SESS_RTCS ) | MKTYPE_OCSP( ST_SESS_OCSP ) } },\n\n\t/* End-of-ACL marker */\n\t{ MESSAGE_NONE, { ST_NONE, ST_NONE, ST_NONE } },\n\t{ MESSAGE_NONE, { ST_NONE, ST_NONE, ST_NONE } }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sometimes a message is explicitly non-routable (i.e. it has to be sent\n   directly to the appropriate target object).  The following function checks\n   that the target object is one of the required types */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint checkTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\t const long targets )\n\t{\n\tconst OBJECT_TYPE target = targets & 0xFF;\n\tconst OBJECT_TYPE altTarget = targets >> 8;\n\tOBJECT_INFO *objectTable = getObjectTable();\n\n\t/* Precondition: Source is a valid object, destination(s) are valid\n\t   target(s) */\n\tREQUIRES( isValidObject( originalObjectHandle ) );\n\tREQUIRES( isValidType( target ) );\n\tREQUIRES( altTarget == OBJECT_TYPE_NONE || isValidType( altTarget ) );\n\n\t/* Clear return value */\n\t*targetObjectHandle = CRYPT_ERROR;\n\n\t/* Check whether the object matches the required type.  We don't have to\n\t   check whether the alternative target has a value or not since the\n\t   object can never be a OBJECT_TYPE_NONE */\n\tif( !isValidObject( originalObjectHandle ) || \\\n\t\t( objectTable[ originalObjectHandle ].type != target && \\\n\t\t  objectTable[ originalObjectHandle ].type != altTarget ) )\n\t\treturn( CRYPT_ERROR );\n\n\t/* Postcondition */\n\tENSURES( objectTable[ originalObjectHandle ].type == target || \\\n\t\t\t objectTable[ originalObjectHandle ].type == altTarget );\n\n\t*targetObjectHandle = originalObjectHandle;\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the ACL for a parameter object */\n\nCHECK_RETVAL_PTR \\\nstatic const MESSAGE_ACL *findParamACL( IN_MESSAGE const MESSAGE_TYPE message )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Precondition: It's a message that takes an object parameter */\n\tREQUIRES_N( isParamMessage( message ) );\n\n\t/* Find the ACL entry for this message type.  There's no need to \n\t   explicitly handle the internal-error condition since any loop\n\t   exit is treated as an error */\n\tLOOP_MED( i = 0, messageParamACLTbl[ i ].type != MESSAGE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( messageParamACLTbl[ i ].type == message )\n\t\t\treturn( &messageParamACLTbl[ i ] );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\tretIntError_Null();\n\t}\n\n/* Wait for an object to become available so that we can use it, with a \n   timeout for blocked objects (dulcis et alta quies placidaeque similima \n   morti).  We spin for WAITCOUNT_SLEEP_THRESHOLD turns, then sleep (see\n   the comment in waitForObject() for more on this), and finally bail out\n   once MAX_WAITCOUNT is reached.  \n   \n   This is an internal function that's used when mapping an object handle to \n   object data, and is never called directly.  \n   \n   As an aid in identifying objects acting as bottlenecks, we provide a \n   function to warn about excessive waiting, along with information on the \n   object that was waited on, in debug mode.  A wait count threshold of \n   100 is generally high enough to avoid false positives caused by (for \n   example) network subsystem delays */\n\n#define WAITCOUNT_SLEEP_THRESHOLD\t\t100\n#define WAITCOUNT_WARN_THRESHOLD\t\t100\n#define MAX_WAITCOUNT\t\t\t\t\t1000\n\n#if defined( USE_ERRMSGS ) && !defined( NDEBUG )\n\n/* Get a text description of an object associated with a given object \n   handle */\n\nstatic const char *objectTypeNames[] = {\n\t\"none\", \"context\", \"keyset\", \"envelope\", \"certificate\", \"device\",\n\t\"session\", \"user\", \"none\", \"none\"\n\t};\n\nstatic const OBJECT_NAME_INFO objectNameInfo[] = {\n\t{ SUBTYPE_CTX_CONV, \"conventional encryption\" },\n\t{ SUBTYPE_CTX_PKC, \"public-key encryption\" },\n\t{ SUBTYPE_CTX_HASH, \"hash\" },\n\t{ SUBTYPE_CTX_MAC, \"MAC\" },\n\t{ SUBTYPE_CTX_GENERIC, \"generic\" },\n\t{ SUBTYPE_CERT_CERT, \"certificate\" },\n\t{ SUBTYPE_CERT_CERTREQ, \"PKCS #10 cert.request\" },\n\t{ SUBTYPE_CERT_REQ_CERT, \"CRMF cert.request\" },\n\t{ SUBTYPE_CERT_REQ_REV, \"CRMF rev.request\" },\n\t{ SUBTYPE_CERT_CERTCHAIN, \"cert.chain\" },\n\t{ SUBTYPE_CERT_ATTRCERT, \"attribute cert.\" },\n\t{ SUBTYPE_CERT_CRL, \"CRK\" },\n\t{ SUBTYPE_CERT_CMSATTR, \"CMS attributes\" },\n\t{ SUBTYPE_CERT_RTCS_REQ, \"RTCS request\" },\n\t{ SUBTYPE_CERT_RTCS_RESP, \"RTCS response\" },\n\t{ SUBTYPE_CERT_OCSP_REQ, \"OCSP request\" },\n\t{ SUBTYPE_CERT_OCSP_RESP, \"OCSP response\" },\n\t{ SUBTYPE_CERT_PKIUSER, \"PKI user\" },\n\t{ SUBTYPE_ENV_ENV, \"PKCS #7/CMS envelope\" },\n\t{ SUBTYPE_ENV_ENV_PGP, \"PGP envelope\" },\n\t{ SUBTYPE_ENV_DEENV, \"de-envelope\" },\n\t{ SUBTYPE_KEYSET_FILE, \"file\" },\n\t{ SUBTYPE_KEYSET_FILE_PARTIAL, \"file (partial)\" },\n\t{ SUBTYPE_KEYSET_FILE_READONLY, \"file (readonly)\" },\n\t{ SUBTYPE_KEYSET_DBMS, \"database\" },\n\t{ SUBTYPE_KEYSET_DBMS_STORE, \"database store\" },\n\t{ SUBTYPE_KEYSET_HTTP, \"HTTP\" },\n\t{ SUBTYPE_KEYSET_LDAP, \"LDAP\" },\n\t{ SUBTYPE_DEV_SYSTEM, \"system\" },\n\t{ SUBTYPE_DEV_PKCS11, \"PKCS #11\" },\n\t{ SUBTYPE_DEV_CRYPTOAPI, \"CryptoAPI\" },\n\t{ SUBTYPE_DEV_HARDWARE, \"hardware\" },\n\t{ SUBTYPE_SESSION_SSH, \"SSH\" },\n\t{ SUBTYPE_SESSION_SSH_SVR, \"SSH server\" },\n\t{ SUBTYPE_SESSION_SSL, \"SSL\" },\n\t{ SUBTYPE_SESSION_SSL_SVR, \"SSL server\" },\n\t{ SUBTYPE_SESSION_RTCS, \"RTCS\" },\n\t{ SUBTYPE_SESSION_RTCS_SVR, \"RTCS server\" },\n\t{ SUBTYPE_SESSION_OCSP, \"OCSP\" },\n\t{ SUBTYPE_SESSION_OCSP_SVR, \"OCSP server\" },\n\t{ SUBTYPE_SESSION_TSP, \"TSP\" },\n\t{ SUBTYPE_SESSION_TSP_SVR, \"TSP server\" },\n\t{ SUBTYPE_SESSION_CMP, \"CMP\" },\n\t{ SUBTYPE_SESSION_CMP_SVR, \"CMP server\" },\n\t{ SUBTYPE_SESSION_SCEP, \"SCEP\" },\n\t{ SUBTYPE_SESSION_SCEP_SVR, \"SCEP server\" },\n\t{ SUBTYPE_SESSION_CERT_SVR, \"cerificate store\" },\n\t{ SUBTYPE_USER_SO, \"SO user\" },\n\t{ SUBTYPE_USER_NORMAL, \"standard user\" },\n\t{ SUBTYPE_USER_CA, \"CA user\" },\n\t{ SUBTYPE_NONE, \"none\" }, { SUBTYPE_NONE, \"none\" },\n\t};\n\nSTDC_NONNULL_ARG( ( 2 ) ) \\\nstatic void getObjectDescription( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t  OUT char *description )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tconst OBJECT_INFO *objectInfoPtr;\n\tint offset;\n\n\tassert( isValidObject( objectHandle ) );\n\n\tREQUIRES_V( isValidHandle( objectHandle ) );\n\n\tobjectInfoPtr = &objectTable[ objectHandle ];\n\n\tREQUIRES_V( sanityCheckObject( objectInfoPtr ) );\n\tREQUIRES_V( isValidType( objectInfoPtr->type ) );\n\n\tif( objectHandle == SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\tstrlcpy_s( description, 128, \"system object\" );\n\t\treturn;\n\t\t}\n\tif( objectHandle == DEFAULTUSER_OBJECT_HANDLE )\n\t\t{\n\t\tstrlcpy_s( description, 128, \"default user object\" );\n\t\treturn;\n\t\t}\n\toffset = sprintf_s( description, 128, \"%sobject %d (%s/%s)\", \n\t\t\t\t\t\t( objectInfoPtr->extRefCount > 0 ) ? \"\" : \"internal \",\n\t\t\t\t\t\tobjectHandle, objectTypeNames[ objectInfoPtr->type ],\n\t\t\t\t\t\tgetObjectName( objectNameInfo,\n\t\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( objectNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   OBJECT_NAME_INFO ),\n\t\t\t\t\t\t\t\t\t   objectInfoPtr->subType ) );\n\tif( objectInfoPtr->owner < NO_SYSTEM_OBJECTS )\n\t\t{\n\t\toffset += sprintf_s( description + offset, 128 - offset, \n\t\t\t\t\t\t\t \" owned by %s\", \n\t\t\t\t\t( objectInfoPtr->owner == SYSTEM_OBJECT_HANDLE ) ? \\\n\t\t\t\t\t  \"system object\" : \"default user object\" );\n\t\t}\n\telse\n\t\t{\n\t\toffset += sprintf_s( description + offset, 128 - offset, \n\t\t\t\t\t\t\t \" owned by %d\", objectInfoPtr->owner );\n\t\t}\n\tif( objectInfoPtr->dependentObject != CRYPT_ERROR )\n\t\t{\n\t\toffset += sprintf_s( description + offset, 128 - offset, \n\t\t\t\t\t\t\t \", dependent object %d\", \n\t\t\t\t\t\t\t objectInfoPtr->dependentObject );\n\t\t}\n\tassert( offset < 128 );\n\t}\n\n/* Non thread-safe version of the above that can be used directly in\n   printf() statements.  This isn't really that bad, firstly it's mostly \n   only called for diagnostics during startup/shutdown where there's \n   guaranteed to be only one thread active, and secondly it uses TLS\n   where possible which means that it'll only really be non-thread-safe on\n   systems that don't have threading anyway (embedded systems that use\n   the tasking model where there's typically only one task) */\n\n#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 201112L )\n  #if defined( __GNUC__ ) && ( __GNUC__ < 5 )\n\t/* Versions of gcc before 5 don't actually support C11 TLS even though\n\t   they claim that they do */\n\t#define THREAD_STORAGE_STATIC\tstatic __thread\n  #else\n\t#define THREAD_STORAGE_STATIC\tstatic _Thread_local\n  #endif /* Broken gcc C11 support */\n#elif defined( __GNUC__ ) || defined( __clang__ ) || \\\n\t  defined( __SUNPRO_C ) \n  #define THREAD_STORAGE_STATIC\t\tstatic __thread\n#elif defined( _MSC_VER )\n  #define THREAD_STORAGE_STATIC\t\t__declspec( thread ) static\n#else\n  #define THREAD_STORAGE_STATIC\t\tstatic\n#endif /* Compiler-specific TLS */\n#if defined( __APPLE__ )\n  /* \"We don't support the thread_local implementation from the open-source \n      Clang because we believe we can provide a higher-performance \n\t  implementation for our platforms using various features in the dynamic \n\t  linker\" */\n  #undef THREAD_STORAGE_STATIC\n  #define THREAD_STORAGE_STATIC\t\tstatic\n#endif /* OS X */\n\nconst char *getObjectTypeDescriptionNT( IN_ENUM( OBJECT_TYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst OBJECT_TYPE type, \n\t\t\t\t\t\t\t\t\t\tIN_ENUM( SUBTYPE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst OBJECT_SUBTYPE subType )\n\t{\n\tTHREAD_STORAGE_STATIC char buffer[ 128 ];\n\n\tREQUIRES_EXT( isValidType( type ), \"unknown object type\" );\n\n\tsprintf_s( buffer, 128, \"%s/%s\", objectTypeNames[ type ], \n\t\t\t   getObjectName( objectNameInfo,\n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( objectNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  OBJECT_NAME_INFO ),\n\t\t\t\t\t\t\t  subType ) );\n\n\treturn( buffer );\n\t}\n\nconst char *getObjectDescriptionNT( IN_HANDLE const int objectHandle )\n\t{\n\tTHREAD_STORAGE_STATIC char buffer[ 128 ];\n\n\tREQUIRES_EXT( isValidHandle( objectHandle ), \"invalid object handle\" );\n\n\tmemset( buffer, 0, 128 );\n\tgetObjectDescription( objectHandle, buffer );\n\treturn( buffer );\n\t}\n\n/* Warn about an excessive wait for an object to become available */\n\nstatic void waitWarn( IN_HANDLE const int objectHandle, \n\t\t\t\t\t  IN_INT const int waitCount )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tchar description[ 128 + 8 ];\n\n\tassert( isValidObject( objectHandle ) );\n\tassert( waitCount > WAITCOUNT_WARN_THRESHOLD && \\\n\t\t\twaitCount <= MAX_WAITCOUNT );\n\n\tgetObjectDescription( objectHandle, description );\n\tDEBUG_DIAG(( \"\\nWarning: Thread %lX waited %d iteration%s for %s\",\n\t\t\t\t ( unsigned long ) THREAD_SELF(), waitCount, \n\t\t\t\t ( waitCount == 1 ) ? \"\" : \"s\", description ));\n\t}\n#endif /* Debug mode only */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint waitForObject( IN_HANDLE const int objectHandle, \n\t\t\t\t   OUT_PTR_COND OBJECT_INFO **objectInfoPtrPtr )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tconst int uniqueID = objectTable[ objectHandle ].uniqueID;\n\tint waitCount, LOOP_ITERATOR;\n\n\t/* Preconditions: The object is in use by another thread */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) );\n\n\t/* Clear return value */\n\t*objectInfoPtrPtr = NULL;\n\n\t/* While the object is busy, put the thread to sleep (Pauzele lungi si\n\t   dese; Cheia marilor succese).  This is the only really portable way\n\t   to wait on the resource, which gives up this thread's timeslice to\n\t   allow other threads (including the one using the object) to run.\n\t   Somewhat better methods methods such as mutexes with timers are\n\t   difficult to manage portably across different platforms.\n\n\t   Even this can cause problems in some circumstances.  The idea behind \n\t   the mechanism below is that by yielding the CPU, whichever thread \n\t   currently holds the object gets to finish with it and then the \n\t   current thread resumes.  However if there's a thundering-herd \n\t   situation where a dozen other threads are waiting on the lock and \n\t   they've voluntarily yielded the CPU and the scheduler prioritises \n\t   them above other threads because of this then they'll all fight for \n\t   the lock and so the thread that holds the object that they're waiting \n\t   on never gets to run.\n\t   \n\t   This seems somewhat unlikely, but it's cropped up on multicore \n\t   hyperthreaded Linux machines running large numbers of threads, \n\t   probably because of the thread-scheduling pecularities of HT CPUs\n\t   combined with the thread-scheduling peculiarities of Linux (it\n\t   doesn't occur on the same systems running Windows or other OSes).  \n\t   The problem seems to be that if a thread yields on a CPU other than\n\t   the one that holds the resource and no other threads are waiting to\n\t   run then it's immediately re-scheduled, because the yield only \n\t   applies to threads on the same CPU.\n\n\t   To deal with this we turn the basic thread-timeslice-yield into a \n\t   more aggressive thread-sleep (which really does yield the CPU, even\n\t   with the thread-scheduling described above) if \n\t   WAITCOUNT_SLEEP_THRESHOLD yields are exceeded */\n\tLOOP_EXT( waitCount = 0,\n\t\t\t  isValidObject( objectHandle ) && \\\n\t\t\t\tobjectTable[ objectHandle ].uniqueID == uniqueID && \\\n\t\t\t\tisInUse( objectHandle ) && waitCount < MAX_WAITCOUNT && \\\n\t\t\t\tkrnlData->shutdownLevel < SHUTDOWN_LEVEL_MESSAGES,\n\t\t\t  waitCount++, MAX_WAITCOUNT + 1 )\n\t\t{\n\t\tobjectTable = NULL;\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tTHREAD_YIELD();\n\t\tif( waitCount > WAITCOUNT_SLEEP_THRESHOLD )\n\t\t\t{\n\t\t\t/* We've waited for over WAITCOUNT_SLEEP_THRESHOLD thread\n\t\t\t   timeslices, explicitly put the thread to sleep rather than \n\t\t\t   just yielding its timeslice */\n\t\t\tTHREAD_SLEEP( 1 );\n\t\t\t}\n\t\tMUTEX_LOCK( objectTable );\n\t\tobjectTable = getObjectTable();\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n#if defined( USE_ERRMSGS ) && !defined( NDEBUG ) && !defined( __WIN16__ )\n\tif( waitCount > WAITCOUNT_WARN_THRESHOLD )\n\t\t{\n\t\t/* If we waited more than WAITCOUNT_WARN_THRESHOLD iterations for\n\t\t   something this could be a sign of a resource usage bottleneck\n\t\t   (typically caused by users who don't understand threading), warn\n\t\t   the user that there's a potential problem */\n\t\twaitWarn( objectHandle, waitCount );\n\t\t}\n#endif /* NDEBUG on systems with stdio */\n\n\t/* If cryptlib is shutting down, exit */\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* If we timed out waiting for the object, return a timeout error */\n\tif( waitCount >= MAX_WAITCOUNT )\n\t\t{\n\t\tDEBUG_DIAG(( \"Object wait exceeded %d iterations\", MAX_WAITCOUNT ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\t}\n\n\t/* Make sure that nothing happened to the object while we were waiting\n\t   on it */\n\tif( !isValidObject( objectHandle ) || \\\n\t\tobjectTable[ objectHandle ].uniqueID != uniqueID )\n\t\treturn( CRYPT_ERROR_SIGNALLED );\n\n\t/* Update the object info pointer in case the object table was updated\n\t   while we had yielded control */\n\t*objectInfoPtrPtr = &objectTable[ objectHandle ];\n\n\t/* Postconditions: The object is available for use */\n\tENSURES( isValidObject( objectHandle ) );\n\tENSURES( !isInUse( objectHandle ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tMessage Routing\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the ultimate target of an object attribute manipulation message by\n   walking down the chain of controlling -> dependent objects.  For example\n   a message targeted at a device and sent to a certificate would be routed\n   to the certificate's dependent object (which would typically be a \n   context).  The device message targeted at the context would in turn be \n   routed to the context's dependent device, which is its final destination */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint findTargetType( IN_HANDLE const CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\tconst long targets )\n\t{\n\tconst OBJECT_TYPE target = targets & 0xFF;\n\tconst OBJECT_TYPE altTarget1 = ( targets >> 8 ) & 0xFF;\n\tconst OBJECT_TYPE altTarget2 = ( targets >> 16 ) & 0xFF;\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_TYPE type = objectTable[ originalObjectHandle ].type;\n\tint objectHandle = originalObjectHandle, iterations, LOOP_ITERATOR;\n\n\t/* Preconditions: Source is a valid object, destination(s) are valid\n\t   target(s) */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidType( target ) );\n\tREQUIRES( altTarget1 == OBJECT_TYPE_NONE || isValidType( altTarget1 ) );\n\tREQUIRES( altTarget2 == OBJECT_TYPE_NONE || isValidType( altTarget2 ) );\n\n\t/* Clear return value */\n\t*targetObjectHandle = CRYPT_ERROR;\n\n\t/* Route the request through any dependent objects as required until we\n\t   reach the required target object type.  \"And thou shalt make\n\t   loops...\" -- Exodus 26:4 */\n\tLOOP_SMALL( iterations = 0, \\\n\t\t\t\titerations < 3 && isValidObject( objectHandle ) && \\\n\t\t\t\t!( target == type || \\\n\t\t\t\t   ( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \\\n\t\t\t\t   ( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ),\n\t\t\t\titerations++ )\n\t\t{\n\t\t/* Loop invariants.  \"Fifty loops thou shalt make\" -- Exodus 26:5\n\t\t   (some of the OT verses shouldn't be taken too literally,\n\t\t   apparently the 50 used here merely means \"many\" as in \"more than\n\t\t   one or two\" in the same way that \"40 days and nights\" is now\n\t\t   generally taken as meaning \"Lots, but that's as far as we're\n\t\t   prepared to count\") */\n\t\tENSURES( isValidObject( objectHandle ) );\n\t\tENSURES( iterations < 3 );\n\n\t\t/* Find the next potential target object */\n\t\tif( target == OBJECT_TYPE_DEVICE && \\\n\t\t\tobjectTable[ objectHandle ].dependentDevice != CRYPT_ERROR )\n\t\t\t{\n\t\t\tobjectHandle = objectTable[ objectHandle ].dependentDevice;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( target == OBJECT_TYPE_USER )\n\t\t\t\t{\n\t\t\t\t/* If we've reached the system object (the parent of all \n\t\t\t\t   other objects) we can't go any further */\n\t\t\t\tobjectHandle = ( objectHandle != SYSTEM_OBJECT_HANDLE ) ? \\\n\t\t\t\t\t\t\t   objectTable[ objectHandle ].owner : CRYPT_ERROR;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tobjectHandle = objectTable[ objectHandle ].dependentObject;\n\t\t\t}\n\t\tif( isValidObject( objectHandle ) )\n\t\t\ttype = objectTable[ objectHandle ].type;\n\n\t\t/* If we've got a new object, it has the same owner as the original\n\t\t   target candidate */\n\t\tENSURES( !isValidObject( objectHandle ) || \\\n\t\t\t\t isSameOwningObject( originalObjectHandle, objectHandle ) || \\\n\t\t\t\t objectTable[ originalObjectHandle ].owner == objectHandle );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( iterations < 3 );\n\tif( !isValidObject( objectHandle ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* Postcondition: We've reached the target object */\n\tENSURES( isValidObject( objectHandle ) && \\\n\t\t\t ( isSameOwningObject( originalObjectHandle, objectHandle ) || \\\n\t\t\t   objectTable[ originalObjectHandle ].owner == objectHandle ) && \\\n\t\t\t ( target == type || \\\n\t\t\t   ( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \\\n\t\t\t   ( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ) );\n\n\n\t*targetObjectHandle = objectHandle;\n\treturn( CRYPT_OK );\n\t}\n\n/* Find the ultimate target of a compare message by walking down the chain\n   of controlling -> dependent objects.  For example a message targeted at a\n   device and sent to a certificate would be routed to the certificate's \n   dependent object (which would typically be a context).  The device \n   message targeted at the context would be routed to the context's \n   dependent device, which is its final destination */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int routeCompareMessageTarget( IN_HANDLE const CRYPT_HANDLE originalObjectHandle, \n\t\t\t\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_HANDLE *targetObjectHandle,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( MESSAGE_COMPARE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst long messageValue )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tOBJECT_TYPE targetType = OBJECT_TYPE_NONE;\n\tint status;\n\n\t/* Preconditions */\n\tREQUIRES( isValidObject( originalObjectHandle ) );\n\tREQUIRES( messageValue == MESSAGE_COMPARE_HASH || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_ICV || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_KEYID || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_KEYID_PGP || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_KEYID_OPENPGP || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_SUBJECT || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_ISSUERANDSERIALNUMBER || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHA1 || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHA2 || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_FINGERPRINT_SHAng || \\\n\t\t\t  messageValue == MESSAGE_COMPARE_CERTOBJ );\n\n\t/* Clear return value */\n\t*targetObjectHandle = CRYPT_ERROR;\n\n\t/* Determine the ultimate target type for the message.  We don't check for\n\t   keysets, envelopes and sessions as dependent objects since this never\n\t   occurs */\n\tswitch( messageValue )\n\t\t{\n\t\tcase MESSAGE_COMPARE_HASH:\n\t\tcase MESSAGE_COMPARE_ICV:\n\t\tcase MESSAGE_COMPARE_KEYID:\n\t\tcase MESSAGE_COMPARE_KEYID_PGP:\n\t\tcase MESSAGE_COMPARE_KEYID_OPENPGP:\n\t\t\ttargetType = OBJECT_TYPE_CONTEXT;\n\t\t\tbreak;\n\n\t\tcase MESSAGE_COMPARE_SUBJECT:\n\t\tcase MESSAGE_COMPARE_ISSUERANDSERIALNUMBER:\n\t\tcase MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER:\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHA1:\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHA2:\n\t\tcase MESSAGE_COMPARE_FINGERPRINT_SHAng:\n\t\tcase MESSAGE_COMPARE_CERTOBJ:\n\t\t\ttargetType = OBJECT_TYPE_CERTIFICATE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Route the message through to the appropriate object */\n\tstatus = findTargetType( originalObjectHandle, targetObjectHandle, \n\t\t\t\t\t\t\t targetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\n\t/* Postcondition: We've found a valid target object */\n\tENSURES( isValidObject( *targetObjectHandle ) && \\\n\t\t\t isSameOwningObject( originalObjectHandle, \\\n\t\t\t\t\t\t\t\t *targetObjectHandle ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage Dispatch ACL\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Each message type has certain properties such as whether it's routable,\n   which object types it applies to, what checks are performed on it, whether\n   it's processed by the kernel or dispatched to an object, etc etc.  These\n   are all defined in the following table.\n\n   In addition to the usual checks, we also make various assertions about the\n   parameters we're passed.  Note that these don't check user data (that's\n   checked programmatically and an error code returned) but values passed by\n   cryptlib code */\n\ntypedef enum {\n\tPARAMTYPE_NONE_NONE,\t/* Data = 0, value = 0 */\n\t\tPARAMTYPE_NONE = PARAMTYPE_NONE_NONE,/* For code analyser */\n\tPARAMTYPE_NONE_ANY,\t\t/* Data = 0, value = any */\n\tPARAMTYPE_NONE_BOOLEAN,\t/* Data = 0, value = boolean */\n\tPARAMTYPE_NONE_CHECKTYPE,/* Data = 0, value = check type */\n\tPARAMTYPE_DATA_NONE,\t/* Data, value = 0 */\n\tPARAMTYPE_DATA_ANY,\t\t/* Data, value = any */\n\tPARAMTYPE_DATA_ATTRIBUTE,/* Data, value = attribute type */\n\tPARAMTYPE_DATA_LENGTH,\t/* Data, value >= 0 */\n\tPARAMTYPE_DATA_OBJTYPE,\t/* Data, value = object type */\n\tPARAMTYPE_DATA_MECHTYPE,/* Data, value = mechanism type */\n\tPARAMTYPE_DATA_ITEMTYPE,/* Data, value = keymgmt.item type */\n\tPARAMTYPE_DATA_FORMATTYPE,/* Data, value = cert format type */\n\tPARAMTYPE_DATA_COMPARETYPE,/* Data, value = compare type */\n\tPARAMTYPE_DATA_SETDEPTYPE,/* Data, value = setdep.option type */\n\tPARAMTYPE_DATA_CERTMGMTTYPE,/* Data, value = cert.mgmt.type */\n\tPARAMTYPE_ANY_USERMGMTTYPE,/* Data = any, value = user mgmt.type */\n\tPARAMTYPE_ANY_TRUSTMGMTTYPE,/* Data = any, value = trust mgmt.type */\n\tPARAMTYPE_LAST\t\t\t/* Last possible parameter check type */\n\t} PARAMCHECK_TYPE;\n\n/* Symbolic defines for message handling types, used to make it clearer\n   what's going on\n\n\tPRE_DISPATCH\t- Action before message is dispatched\n\tPOST_DISPATCH\t- Action after message is dispatched\n\tHANDLE_INTERNAL\t- Message handled by the kernel */\n\n#define PRE_DISPATCH( function )\tpreDispatch##function, NULL\n#define POST_DISPATCH( function )\tNULL, postDispatch##function\n#define PRE_POST_DISPATCH( preFunction, postFunction ) \\\n\t\tpreDispatch##preFunction, postDispatch##postFunction\n#define HANDLE_INTERNAL( function )\tNULL, NULL, MESSAGE_HANDLING_FLAG_INTERNAL, function\n\n/* Flags to indicate (potential) special-case handling for a message.  These\n   are:\n\n\tFLAG_INTERNAL: The message is handled internally by the kernel rather\n\t\t\tthan being sent to an external handler.\n\n\tFLAG_MAYUNLOCK: The message handler may unlock the object (via \n\t\t\tkrnlReleaseObject()) to allow other threads access.  In this \n\t\t\tcase the first parameter to the handler function should be a\n\t\t\tMESSAGE_FUNCTION_EXTINFO structure to contain unlocking\n\t\t\tinformation */\n\n#define MESSAGE_HANDLING_FLAG_NONE\t\t0\t/* No special handling */\n#define MESSAGE_HANDLING_FLAG_MAYUNLOCK\t1\t/* Handler may unlock object */\n#define MESSAGE_HANDLING_FLAG_INTERNAL\t2\t/* Message handle by kernel */\n\n/* The handling information, declared in the order in which it's applied */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\n\t\tint ( *PREDISPATCH_FUNCTION )( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t   const void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t   const int messageValue, const void *auxInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\n\t\tint ( *POSTDISPATCH_FUNCTION )( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t\t\t\tIN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t\t\tconst void *messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tconst int messageValue, const void *auxInfo );\ntypedef CHECK_RETVAL \\\n\t\tint ( *INTERNALHANDLER_FUNCTION )( IN_HANDLE const int objectHandle, \n\t\t\t\t\t\t\t\t\t\t   const int arg1, const void *arg2,\n\t\t\t\t\t\t\t\t\t\t   const BOOLEAN isInternal );\n\ntypedef struct {\n\t/* The message type, used for consistency checking */\n\tconst MESSAGE_TYPE messageType;\n\n\t/* Message routing information if the message is routable.  If the target\n\t   is implicitly determined via the message value, the routing target is\n\t   OBJECT_TYPE_NONE; if the target is explicitly determined, the routing\n\t   target is identified in the target.  If the routing function is null,\n\t   the message isn't routed */\n\tconst long routingTarget;\t\t\t/* Target type if routable */\n\tROUTING_FUNCTION routingFunction;\n\n\t/* Object type checking information: Object subtypes for which this\n\t   message is valid (for object-type-specific message) */\n\tconst OBJECT_SUBTYPE subTypeA, subTypeB, subTypeC;\n\t\t\t\t\t\t\t\t\t\t/* Object subtype for which msg.valid */\n\n\t/* Message type checking information used to assertion-check the function\n\t   preconditions */\n\tconst PARAMCHECK_TYPE paramCheck;\t/* Parameter check assertion type */\n\n\t/* Pre- and post-message-dispatch handlers.  These perform any additional\n\t   checking and processing that may be necessary before and after a\n\t   message is dispatched to an object */\n\tPREDISPATCH_FUNCTION preDispatchFunction;\n\tPOSTDISPATCH_FUNCTION postDispatchFunction;\n\n\t/* Flags to indicate (potential) special-case handling for this message, \n\t   and the (optional) internal handler function that's used if the \n\t   message is handled directly by the kernel */\n\tint flags;\t\t\t\t\t\t\t/* Special-case handling flags */\n\tINTERNALHANDLER_FUNCTION internalHandlerFunction;\n\t} MESSAGE_HANDLING_INFO;\n\nstatic const MESSAGE_HANDLING_INFO messageHandlingInfo[] = {\n\t{ MESSAGE_NONE, ROUTE_NONE, 0, 0, 0, PARAMTYPE_NONE_NONE },\n\n\t/* Control messages.  These messages aren't routed, are valid for all\n\t   object types and subtypes, take no (or minimal) parameters, and are\n\t   handled by the kernel */\n\t{ MESSAGE_DESTROY,\t\t\t\t/* Destroy the object */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_NONE_NONE,\n\t  PRE_POST_DISPATCH( SignalDependentObjects, SignalDependentDevices ) },\n\t{ MESSAGE_INCREFCOUNT,\t\t\t/* Increment object ref.count */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_NONE_NONE,\n\t  HANDLE_INTERNAL( incRefCount ) },\n\t{ MESSAGE_DECREFCOUNT,\t\t\t/* Decrement object ref.count */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_NONE_NONE,\n\t  HANDLE_INTERNAL( decRefCount ) },\n\t{ MESSAGE_GETDEPENDENT,\t\t\t/* Get dependent object */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_OBJTYPE,\n\t  HANDLE_INTERNAL( getDependentObject ) },\n\t{ MESSAGE_SETDEPENDENT,\t\t\t/* Set dependent object (e.g. ctx->dev) */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_SETDEPTYPE,\n\t  HANDLE_INTERNAL( setDependentObject ) },\n\t{ MESSAGE_CLONE,\t\t\t\t/* Clone the object (only valid for ctxs) */\n\t  ROUTE_FIXED( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_HASH, ST_NONE, ST_NONE, \n\t  PARAMTYPE_NONE_ANY,\n\t  HANDLE_INTERNAL( cloneObject ) },\n\n\t/* Attribute messages.  These messages are implicitly routed by attribute\n\t   type, more specific checking is performed using the attribute ACL's */\n\t{ MESSAGE_GETATTRIBUTE,\t\t\t/* Get numeric object attribute */\n\t  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_ATTRIBUTE,\n\t  PRE_POST_DISPATCH( CheckAttributeAccess, MakeObjectExternal ) },\n\t{ MESSAGE_GETATTRIBUTE_S,\t\t/* Get string object attribute */\n\t  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_ATTRIBUTE,\n\t  PRE_DISPATCH( CheckAttributeAccess ) },\n\t{ MESSAGE_SETATTRIBUTE,\t\t\t/* Set numeric object attribute */\n\t  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_ATTRIBUTE,\n\t  PRE_POST_DISPATCH( CheckAttributeAccess, ChangeStateOpt ) },\n\t{ MESSAGE_SETATTRIBUTE_S,\t\t/* Set string object attribute */\n\t  ROUTE_IMPLICIT, ST_ANY_A, ST_ANY_B, ST_ANY_C, \n\t  PARAMTYPE_DATA_ATTRIBUTE,\n\t  PRE_POST_DISPATCH( CheckAttributeAccess, ChangeStateOpt ) },\n\t{ MESSAGE_DELETEATTRIBUTE,\t\t/* Delete object attribute */\n\t  ROUTE_IMPLICIT, ST_CTX_ANY | ST_CERT_ANY, ST_NONE, ST_SESS_ANY | ST_USER_NORMAL | ST_USER_SO,\n\t  PARAMTYPE_NONE_ANY,\n\t  PRE_DISPATCH( CheckAttributeAccess ) },\n\n\t/* General messages to objects */\n\t{ MESSAGE_COMPARE,\t\t\t\t/* Compare objs.or obj.properties */\n\t  ROUTE_SPECIAL( CompareMessageTarget ), ST_CTX_ANY | ST_CERT_ANY, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_COMPARETYPE,\n\t  PRE_DISPATCH( CheckCompareParam ) },\n\t{ MESSAGE_CHECK,\t\t\t\t/* Check object info */\n\t  ROUTE_NONE, ST_ANY_A, ST_ANY_B, ST_ANY_C,\n\t  PARAMTYPE_NONE_CHECKTYPE,\n\t  PRE_POST_DISPATCH( CheckCheckParam, ForwardToDependentObject ) },\n\t{ MESSAGE_SELFTEST,\t\t\t\t/* Perform a self-test */\n\t  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_SYSTEM, ST_NONE, \n\t  PARAMTYPE_NONE_NONE,\n\t  NULL, NULL,\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\n\t/* Messages sent from the kernel to object message handlers.  These\n\t   messages are sent directly to the object from inside the kernel in\n\t   response to a control message, so we set the checking to disallow\n\t   everything to catch any that arrive from outside */\n\t{ MESSAGE_CHANGENOTIFY,\t\t\t/* Notification of obj.status chge.*/\n\t  ROUTE_NONE, ST_NONE, ST_NONE, ST_NONE, PARAMTYPE_NONE_NONE },\n\n\t/* Object-type-specific messages: Contexts */\n\t{ MESSAGE_CTX_ENCRYPT,\t\t\t/* Context: Action = encrypt */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_LENGTH,\n\t  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },\n\t{ MESSAGE_CTX_DECRYPT,\t\t\t/* Context: Action = decrypt */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_LENGTH,\n\t  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },\n\t{ MESSAGE_CTX_SIGN,\t\t\t\t/* Context: Action = sign */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_LENGTH,\n\t  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },\n\t{ MESSAGE_CTX_SIGCHECK,\t\t\t/* Context: Action = sigcheck */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_LENGTH,\n\t  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },\n\t{ MESSAGE_CTX_HASH,\t\t\t\t/* Context: Action = hash */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_HASH | ST_CTX_MAC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_LENGTH,\n\t  PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },\n\t{ MESSAGE_CTX_GENKEY,\t\t\t/* Context: Generate a key */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), \n\t\tST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC | ST_CTX_GENERIC, ST_NONE, ST_NONE, \n\t  PARAMTYPE_NONE_NONE,\n\t  PRE_POST_DISPATCH( CheckState, ChangeState ) },\n\t{ MESSAGE_CTX_GENIV,\t\t\t/* Context: Generate an IV */\n\t  ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV, ST_NONE, ST_NONE, \n\t  PARAMTYPE_NONE_NONE },\n\n\t/* Object-type-specific messages: Certificates */\n\t{ MESSAGE_CRT_SIGN,\t\t\t\t/* Cert: Action = sign certificate */\n\t  ROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\tST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t  PARAMTYPE_NONE_ANY,\n\t  PRE_POST_DISPATCH( CheckStateParamHandle, ChangeState ) },\n\t{ MESSAGE_CRT_SIGCHECK,\t\t\t/* Cert: Action = check/verify certificate */\n\t  ROUTE( OBJECT_TYPE_CERTIFICATE ),\n\t\tST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \\\n\t\tST_CERT_RTCS_RESP | ST_CERT_OCSP_RESP, ST_NONE, ST_NONE, \n\t  PARAMTYPE_NONE_ANY,\n\t  PRE_DISPATCH( CheckParamHandleOpt ) },\n\t{ MESSAGE_CRT_EXPORT,\t\t\t/* Cert: Export encoded certificate data */\n\t  ROUTE( OBJECT_TYPE_CERTIFICATE ), ST_CERT_ANY, ST_NONE, ST_NONE, \n\t  PARAMTYPE_DATA_FORMATTYPE,\n\t  PRE_DISPATCH( CheckExportAccess ) },\n\n\t/* Object-type-specific messages: Devices */\n\t{ MESSAGE_DEV_QUERYCAPABILITY,\t/* Device: Query capability */\n\t  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_ANY },\n\t{ MESSAGE_DEV_EXPORT,\t\t\t/* Device: Action = export key */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismWrapAccess ), \n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_IMPORT,\t\t\t/* Device: Action = import key */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismWrapAccess ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_SIGN,\t\t\t\t/* Device: Action = sign */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismSignAccess ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_SIGCHECK,\t\t\t/* Device: Action = sig.check */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismSignAccess ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_DERIVE,\t\t\t/* Device: Action = derive key */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismDeriveAccess ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_KDF,\t\t\t\t/* Device: Action = KDF key */\n\t  ROUTE( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_MECHTYPE,\n\t  PRE_DISPATCH( CheckMechanismKDFAccess ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_CREATEOBJECT,\t\t/* Device: Create object */\n\t  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_OBJTYPE,\n\t  PRE_POST_DISPATCH( CheckCreate, MakeObjectExternal ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\t{ MESSAGE_DEV_CREATEOBJECT_INDIRECT,/* Device: Create obj.from data */\n\t  ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_NONE, ST_DEV_ANY, ST_NONE, \n\t  PARAMTYPE_DATA_OBJTYPE,\n\t  PRE_POST_DISPATCH( CheckCreate, MakeObjectExternal ),\n\t  MESSAGE_HANDLING_FLAG_MAYUNLOCK },\n\n\t/* Object-type-specific messages: Envelopes */\n\t{ MESSAGE_ENV_PUSHDATA,\t\t\t/* Envelope: Push data */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),\n\t\tST_NONE, ST_ENV_ANY, ST_SESS_ANY_DATA,\n\t  PARAMTYPE_DATA_NONE,\n\t  PRE_DISPATCH( CheckData ) },\n\t{ MESSAGE_ENV_POPDATA,\t\t\t/* Envelope: Pop data */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),\n\t\tST_NONE, ST_ENV_ANY, ST_SESS_ANY_DATA,\n\t  PARAMTYPE_DATA_NONE,\n\t  PRE_DISPATCH( CheckData ) },\n\n\t/* Object-type-specific messages: Keysets */\n\t{ MESSAGE_KEY_GETKEY,\t\t\t/* Keyset: Instantiate ctx/certificate */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,\n\t  PARAMTYPE_DATA_ITEMTYPE,\n\t  PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },\n\t{ MESSAGE_KEY_SETKEY,\t\t\t/* Keyset: Add ctx/certificate */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,\n\t  PARAMTYPE_DATA_ITEMTYPE,\n\t  PRE_DISPATCH( CheckKeysetAccess ) },\n\t{ MESSAGE_KEY_DELETEKEY,\t\t/* Keyset: Delete key */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,\n\t  PARAMTYPE_DATA_ITEMTYPE,\n\t  PRE_DISPATCH( CheckKeysetAccess ) },\n\t{ MESSAGE_KEY_GETFIRSTCERT,\t\t/* Keyset: Get first cert in sequence */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,\n\t  PARAMTYPE_DATA_ITEMTYPE,\n\t  PRE_DISPATCH( CheckKeysetAccess ) },\n\t{ MESSAGE_KEY_GETNEXTCERT,\t\t/* Keyset: Get next cert in sequence */\n\t  ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),\n\t\tST_NONE, ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,\n\t  PARAMTYPE_DATA_ITEMTYPE,\n\t  PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },\n\t{ MESSAGE_KEY_CERTMGMT,\t\t\t/* Keyset: Certificate management */\n\t  ROUTE_FIXED( OBJECT_TYPE_KEYSET ),\n\t\tST_NONE, ST_KEYSET_DBMS_STORE, ST_NONE,\n\t  PARAMTYPE_DATA_CERTMGMTTYPE,\n\t  PRE_POST_DISPATCH( CheckCertMgmtAccess, MakeObjectExternal ) },\n\n\t/* Object-type-specific messages: Users */\n\t{ MESSAGE_USER_USERMGMT,\t\t/* User: User management */\n\t  ROUTE_FIXED( OBJECT_TYPE_USER ), ST_NONE, ST_NONE, ST_USER_SO, \n\t  PARAMTYPE_ANY_USERMGMTTYPE,\n\t  PRE_POST_DISPATCH( CheckUserMgmtAccess, HandleZeroise ) },\n\t{ MESSAGE_USER_TRUSTMGMT,\t\t/* User: Trust management */\n\t  ROUTE_FIXED( OBJECT_TYPE_USER ), ST_NONE, ST_NONE, ST_USER_SO, \n\t  PARAMTYPE_ANY_TRUSTMGMTTYPE,\n\t  PRE_DISPATCH( CheckTrustMgmtAccess ) },\n\n\t/* End-of-ACL marker */\n\t{ MESSAGE_NONE, ROUTE_NONE, 0, PARAMTYPE_NONE_NONE },\n\t{ MESSAGE_NONE, ROUTE_NONE, 0, PARAMTYPE_NONE_NONE }\n\t};\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Check the basic validity of message parameters.  Note that this only \n   checks for coding errors (krnlSendMessage() having been called \n   correctly), it doesn't perform parameter validation, which is the\n   job of the full ACL checks.\n   \n   Since the check for non-null pointers isn't very comprehensive, for \n   example it wont catch a call using &fooPtr->cryptHandle where fooPtr is \n   NULL, we also assert on the non-null pointer pointing to at least an \n   integer's worth of memory in the debug version */\n\nCHECK_RETVAL_BOOL\nstatic BOOLEAN checkParams( IN_ENUM( PARAMTYPE ) \\\n\t\t\t\t\t\t\t\tconst PARAMCHECK_TYPE paramCheck,\n\t\t\t\t\t\t\tconst void *messageDataPtr, \n\t\t\t\t\t\t\tconst int messageValue )\n\t{\n\tREQUIRES_B( paramCheck >= PARAMTYPE_NONE_NONE && \\\n\t\t\t\tparamCheck < PARAMTYPE_LAST );\n\n\tswitch( paramCheck )\n\t\t{\n\t\tcase PARAMTYPE_NONE_NONE:\n\t\t\treturn( ( messageDataPtr == NULL && messageValue == 0 ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_NONE_ANY:\n\t\t\treturn( ( messageDataPtr == NULL ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_NONE_BOOLEAN:\n\t\t\treturn( ( messageDataPtr == NULL && \\\n\t\t\t\t\t  ( messageValue == FALSE || messageValue == TRUE ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_NONE_CHECKTYPE:\n\t\t\treturn( ( messageDataPtr == NULL && \\\n\t\t\t\t\t  ( messageValue > MESSAGE_CHECK_NONE && \\\n\t\t\t\t\t\tmessageValue < MESSAGE_CHECK_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_NONE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && messageValue == 0 ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_ANY:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_ATTRIBUTE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( ( messageValue > CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\t  messageValue < CRYPT_ATTRIBUTE_LAST ) || \\\n\t\t\t\t\t\t( messageValue > CRYPT_IATTRIBUTE_FIRST && \\\n\t\t\t\t\t\t  messageValue < CRYPT_IATTRIBUTE_LAST ) ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_LENGTH:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && messageValue >= 0 ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_OBJTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( messageValue > OBJECT_TYPE_NONE && \\\n\t\t\t\t\t\tmessageValue < OBJECT_TYPE_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_MECHTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( messageValue > MECHANISM_NONE && \\\n\t\t\t\t\t\tmessageValue < MECHANISM_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_ITEMTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( messageValue > KEYMGMT_ITEM_NONE && \\\n\t\t\t\t\t\tmessageValue < KEYMGMT_ITEM_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_FORMATTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( messageValue > CRYPT_CERTFORMAT_NONE && \\\n\t\t\t\t\t\tmessageValue < CRYPT_CERTFORMAT_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_COMPARETYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  ( messageValue > MESSAGE_COMPARE_NONE && \\\n\t\t\t\t\t\tmessageValue < MESSAGE_COMPARE_LAST ) ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_SETDEPTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  messageValue > SETDEP_OPTION_NONE && \\\n\t\t\t\t\t  messageValue < SETDEP_OPTION_LAST ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_DATA_CERTMGMTTYPE:\n\t\t\tassert( isReadPtr( messageDataPtr, sizeof( int ) ) );\n\t\t\treturn( ( isValidPointer( messageDataPtr ) && \\\n\t\t\t\t\t  messageValue > CRYPT_CERTACTION_NONE && \\\n\t\t\t\t\t  messageValue < CRYPT_CERTACTION_LAST ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_ANY_USERMGMTTYPE:\n\t\t\treturn( ( messageValue > MESSAGE_USERMGMT_NONE && \\\n\t\t\t\t\t  messageValue < MESSAGE_USERMGMT_LAST ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tcase PARAMTYPE_ANY_TRUSTMGMTTYPE:\n\t\t\treturn( ( messageValue > MESSAGE_TRUSTMGMT_NONE && \\\n\t\t\t\t\t  messageValue < MESSAGE_TRUSTMGMT_LAST ) ? \\\n\t\t\t\t\tTRUE : FALSE );\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\tretIntError_Boolean();\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the message queue */\n\nstatic int initMessageQueue( void )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( krnlData, sizeof( KERNEL_DATA ) ) );\n\n\tLOOP_EXT( i = 0, i < MESSAGE_QUEUE_SIZE, i++, MESSAGE_QUEUE_SIZE + 1 )\n\t\t{\n\t\tDATAPTR_SET( messageQueue[ i ].handlingInfoPtr, NULL );\n\t\tDATAPTR_SET( messageQueue[ i ].messageDataPtr, NULL );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifndef CONFIG_NO_SELFTEST\n\nCHECK_RETVAL \\\nint initSendMessage( void )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Perform a consistency check on various things that need to be set\n\t   up in a certain way for things to work properly */\n\tstatic_assert( MESSAGE_CTX_DECRYPT == MESSAGE_CTX_ENCRYPT + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_CTX_SIGN == MESSAGE_CTX_DECRYPT + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_CTX_SIGCHECK == MESSAGE_CTX_SIGN + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_CTX_HASH == MESSAGE_CTX_SIGCHECK + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_CTX_GENKEY == MESSAGE_CTX_HASH + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_GETATTRIBUTE_S == MESSAGE_GETATTRIBUTE + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_SETATTRIBUTE == MESSAGE_GETATTRIBUTE_S + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_SETATTRIBUTE_S == MESSAGE_SETATTRIBUTE + 1, \\\n\t\t\t\t   \"Message value\" );\n\tstatic_assert( MESSAGE_DELETEATTRIBUTE == MESSAGE_SETATTRIBUTE_S + 1, \\\n\t\t\t\t   \"Message value\" );\n\n\t/* Perform a consistency check on various internal values and constants */\n\tassert( ACTION_PERM_COUNT == 6 );\n\n\t/* Perform a consistency check on the parameter ACL */\n\tLOOP_MED( i = 0, messageParamACLTbl[ i ].type != MESSAGE_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL ), \n\t\t\t  i++ )\n\t\t{\n\t\tconst MESSAGE_ACL *messageParamACL = &messageParamACLTbl[ i ];\n\n\t\tENSURES( isParamMessage( messageParamACL->type ) && \\\n\t\t\t\t !( messageParamACL->objectACL.subTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( messageParamACL->objectACL.subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( messageParamACL->objectACL.subTypeC & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSUBTYPE_CLASS_B ) ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( messageParamACLTbl, MESSAGE_ACL ) );\n\n\t/* Perform a consistency check on the message handling information */\n\tLOOP_MED( i = MESSAGE_NONE + 1, i < MESSAGE_LAST, i++ )\n\t\t{\n\t\tconst MESSAGE_HANDLING_INFO *messageInfo = &messageHandlingInfo[ i ];\n\n\t\tENSURES( messageInfo->messageType == i && \\\n\t\t\t\t messageInfo->paramCheck >= PARAMTYPE_NONE_NONE && \\\n\t\t\t\t messageInfo->paramCheck < PARAMTYPE_LAST );\n\t\tENSURES( ( messageInfo->messageType >= MESSAGE_ENV_PUSHDATA && \\\n\t\t\t\t   messageInfo->messageType <= MESSAGE_KEY_GETNEXTCERT ) || \\\n\t\t\t\t ( messageInfo->routingTarget >= OBJECT_TYPE_NONE && \\\n\t\t\t\t   messageInfo->routingTarget <= OBJECT_TYPE_LAST ) );\n\t\tENSURES( messageInfo->messageType == MESSAGE_CLONE || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_COMPARE || \\\n\t\t\t\t ( messageInfo->routingTarget == OBJECT_TYPE_NONE && \\\n\t\t\t\t   messageInfo->routingFunction == NULL ) || \\\n\t\t\t\t ( messageInfo->routingTarget != OBJECT_TYPE_NONE && \\\n\t\t\t\t   messageInfo->routingFunction != NULL ) );\n\t\tENSURES( !( messageInfo->subTypeA & ( SUBTYPE_CLASS_B | \\\n\t\t\t\t\t\t\t\t\t\t\t  SUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( messageInfo->subTypeB & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t  SUBTYPE_CLASS_C ) ) && \\\n\t\t\t\t !( messageInfo->subTypeC & ( SUBTYPE_CLASS_A | \\\n\t\t\t\t\t\t\t\t\t\t\t  SUBTYPE_CLASS_B ) ) );\n\t\tENSURES( ( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_SELFTEST || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_CHANGENOTIFY || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_CTX_GENIV || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_DEV_QUERYCAPABILITY || \\\n\t\t\t\t messageInfo->preDispatchFunction != NULL );\n\t\tENSURES( messageInfo->messageType == MESSAGE_SELFTEST || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_CHANGENOTIFY || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_CTX_GENIV || \\\n\t\t\t\t messageInfo->messageType == MESSAGE_DEV_QUERYCAPABILITY || \\\n\t\t\t\t ( messageInfo->preDispatchFunction != NULL || \\\n\t\t\t\t   messageInfo->postDispatchFunction != NULL || \\\n\t\t\t\t   messageInfo->internalHandlerFunction != NULL ) );\n\t\tENSURES( ( ( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) && \\\n\t\t\t\t\t messageInfo->internalHandlerFunction != NULL ) || \\\n\t\t\t\t ( !( messageInfo->flags & MESSAGE_HANDLING_FLAG_INTERNAL ) && \\\n\t\t\t\t\t  messageInfo->internalHandlerFunction == NULL ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( initMessageQueue() );\n\t}\n#else\n\nCHECK_RETVAL \\\nint initSendMessage( void )\n\t{\n\treturn( initMessageQueue() );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n\nvoid endSendMessage( void )\n\t{\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMessage Queue\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enqueue a message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int enqueueMessage( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t   const MESSAGE_HANDLING_INFO *handlingInfoPtr,\n\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t   IN_OPT const void *messageDataPtr,\n\t\t\t\t\t\t   const int messageValue )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;\n\tint queuePos, i, LOOP_ITERATOR;\n\tORIGINAL_INT_VAR( queueEnd, krnlData->queueEnd );\n\n\tassert( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );\n\n\t/* Precondition: It's a valid message being sent to a valid object */\n\tREQUIRES( isValidObject( objectHandle ) );\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\n\t/* Sanity-check the state/make sure that we don't overflow the queue \n\t   (this object is not responding to messages... now all we need is \n\t   GPF's).  We return a timeout error on overflow to indicate that there \n\t   are too many messages queued for this (or other) objects */\n\tif( krnlData->queueEnd < 0 || \\\n\t\tkrnlData->queueEnd >= MESSAGE_QUEUE_SIZE - 1 )\n\t\t{\n\t\tENSURES( krnlData->queueEnd >= 0 );\n\t\tDEBUG_DIAG(( \"Invalid kernel message queue state\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\t}\n\n\t/* Precondition: There's room to enqueue the message */\n\tREQUIRES( krnlData->queueEnd >= 0 && \\\n\t\t\t  krnlData->queueEnd < MESSAGE_QUEUE_SIZE - 1 );\n\n\t/* Check whether a message to this object is already present in the\n\t   queue */\n\tLOOP_EXT( queuePos = krnlData->queueEnd - 1, queuePos >= 0, queuePos--, \n\t\t\t  MESSAGE_QUEUE_SIZE + 1 )\n\t\t{\n\t\tif( messageQueue[ queuePos ].objectHandle == objectHandle )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Postcondition: queuePos = -1 if not present, position in queue if\n\t   present */\n\tENSURES( queuePos == -1 || \\\n\t\t\t ( queuePos >= 0 && queuePos < krnlData->queueEnd ) );\n\n\t/* Sanity-check the queue positioning */\n\tENSURES( queuePos >= -1 && queuePos < krnlData->queueEnd );\n\n\t/* Enqueue the message:\n\n\t\t+---------------+\t\t+---------------+\n\t\t|.|.|x|x|y|z|   |\t->\t|.|.|x|x|#|y|z| |\n\t\t+---------------+\t\t+---------------+\n\t\t\t   ^\t ^\t\t\t\t\t ^\t   ^\n\t\t\t  qPos\tqEnd\t\t\t\tqPos  qEnd */\n\tqueuePos++;\t\t/* Insert after current position */\n\tLOOP_EXT( i = krnlData->queueEnd - 1, i >= queuePos, i--, \n\t\t\t  MESSAGE_QUEUE_SIZE + 1 )\n\t\t{\n\t\tmessageQueue[ i + 1 ] = messageQueue[ i ];\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tmemset( &messageQueue[ queuePos ], 0, sizeof( MESSAGE_QUEUE_DATA ) );\n\tmessageQueue[ queuePos ].objectHandle = objectHandle;\n\tDATAPTR_SET( messageQueue[ queuePos ].handlingInfoPtr, \n\t\t\t\t ( void * ) handlingInfoPtr );\n\tmessageQueue[ queuePos ].message = message;\n\tDATAPTR_SET( messageQueue[ queuePos ].messageDataPtr, \n\t\t\t\t ( void * ) messageDataPtr );\n\tmessageQueue[ queuePos ].messageValue = messageValue;\n\tkrnlData->queueEnd++;\n\n\t/* Postcondition: The queue is within bounds and has grown by one \n\t   element */\n\tENSURES( krnlData->queueEnd > 0 && \\\n\t\t\t krnlData->queueEnd <= MESSAGE_QUEUE_SIZE - 1 );\n\tENSURES( krnlData->queueEnd == ORIGINAL_VALUE( queueEnd ) + 1 );\n\n\t/* If a message for this object is already present tell the caller to \n\t   defer processing */\n\tif( queuePos > 0 )\n\t\treturn( OK_SPECIAL );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Dequeue a message */\n\nCHECK_RETVAL \\\nstatic int dequeueMessage( IN_RANGE( 0, MESSAGE_QUEUE_SIZE ) \\\n\t\t\t\t\t\t\t\tconst int messagePosition )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;\n\tMESSAGE_QUEUE_DATA *messageQueuePtr;\n\tint i, LOOP_ITERATOR;\n\tORIGINAL_INT_VAR( queueEnd, krnlData->queueEnd );\n\n\t/* Precondition: We're deleting a valid queue position */\n\tREQUIRES( messagePosition >= 0 && \\\n\t\t\t  messagePosition < krnlData->queueEnd );\n\tREQUIRES( krnlData->queueEnd > 0 && \\\n\t\t\t  krnlData->queueEnd < MESSAGE_QUEUE_SIZE );\n\n\t/* Move the remaining messages down and clear the last entry */\n\tLOOP_EXT( i = messagePosition, i < krnlData->queueEnd - 1, i++,\n\t\t\t  MESSAGE_QUEUE_SIZE + 1 )\n\t\tmessageQueue[ i ] = messageQueue[ i + 1 ];\n\tENSURES( LOOP_BOUND_OK );\n\tmessageQueuePtr = &messageQueue[ krnlData->queueEnd - 1 ];\n\tzeroise( messageQueuePtr, sizeof( MESSAGE_QUEUE_DATA ) );\n\tDATAPTR_SET( messageQueuePtr->handlingInfoPtr, NULL );\n\tDATAPTR_SET( messageQueuePtr->messageDataPtr, NULL );\n\tkrnlData->queueEnd--;\n\n\t/* Postcondition: the queue is one element shorter, all queue entries \n\t   are valid, and all non-queue entries are empty */\n\tENSURES( krnlData->queueEnd == ORIGINAL_VALUE( queueEnd ) - 1 );\n\tENSURES( krnlData->queueEnd >= 0 && \\\n\t\t\t krnlData->queueEnd < MESSAGE_QUEUE_SIZE - 1 );\n\tFORALL( i, 0, krnlData->queueEnd,\n\t\t\tDATAPTR_ISSET( messageQueue[ i ].handlingInfoPtr ) );\n\tFORALL( i, krnlData->queueEnd, MESSAGE_QUEUE_SIZE,\n\t\t\tDATAPTR_ISNULL( messageQueue[ i ].handlingInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the next message in the queue */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN getNextMessage( IN_HANDLE const int objectHandle,\n\t\t\t\t\t\t\t   OUT_OPT MESSAGE_QUEUE_DATA *messageQueueInfo )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tMESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;\n\tint i, LOOP_ITERATOR;\n\n\tassert( messageQueueInfo == NULL || \\\n\t\t\tisWritePtr( messageQueueInfo, sizeof( MESSAGE_QUEUE_DATA ) ) );\n\n\t/* Preconditions: It's a valid object table entry.  It's not necessarily\n\t   a valid object since we may be de-queueing messages for it because \n\t   it's just been destroyed */\n\tREQUIRES_B( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\tobjectHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t\tisHandleRangeValid( objectHandle ) );\n\n\t/* Clear return value */\n\tif( messageQueueInfo != NULL )\n\t\tmemset( messageQueueInfo, 0, sizeof( MESSAGE_QUEUE_DATA ) );\n\n\t/* Sanity-check the state */\n\tREQUIRES_B( krnlData->queueEnd >= 0 && \\\n\t\t\t\tkrnlData->queueEnd < MESSAGE_QUEUE_SIZE );\n\n\t/* Find the next message for this object.  Since other messages can have\n\t   come and gone in the meantime, we have to scan from the start each\n\t   time */\n\tLOOP_EXT( i = 0, i < krnlData->queueEnd, i++, MESSAGE_QUEUE_SIZE + 1 )\n\t\t{\n\t\tif( messageQueue[ i ].objectHandle == objectHandle )\n\t\t\t{\n\t\t\tint status;\n\n\t\t\tif( messageQueueInfo != NULL )\n\t\t\t\t*messageQueueInfo = messageQueue[ i ];\n\t\t\tstatus = dequeueMessage( i );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Postcondition: There are no more messages for this object present in\n\t   the queue */\n\tFORALL( i, 0, krnlData->queueEnd,\n\t\t\tmessageQueue[ i ].objectHandle != objectHandle );\n\n\treturn( FALSE );\n\t}\n\n/* Dequeue all messages for an object in the queue */\n\nstatic void dequeueAllMessages( IN_HANDLE const int objectHandle )\n\t{\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tint LOOP_ITERATOR;\n\n\t/* Preconditions: It's a valid object table entry.  It's not necessarily\n\t   a valid object since we may be de-queueing messages for it because \n\t   it's just been destroyed */\n\tREQUIRES_V( objectHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\tobjectHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t\tisHandleRangeValid( objectHandle ) );\n\t\n\t/* Dequeue all messages for a given object */\n\tLOOP_EXT_CHECK( getNextMessage( objectHandle, NULL ), \n\t\t\t\t\tMESSAGE_QUEUE_SIZE + 1 );\n\tENSURES_V( LOOP_BOUND_OK );\n\n\t/* Postcondition: There are no more messages for this object present in\n\t   the queue */\n\tFORALL( i, 0, krnlData->queueEnd,\n\t\t\tkrnlData->messageQueue[ i ].objectHandle != objectHandle );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMessage Dispatcher\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a message that's handled internally by the kernel, for example \n   one that accesses an object's kernel attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int processInternalMessage( IN_HANDLE const int localObjectHandle,\n\t\t\t\t\t\t\t\t   const MESSAGE_HANDLING_INFO *handlingInfoPtr,\n\t\t\t\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t\t\t\t   IN_OPT void *messageDataPtr,\n\t\t\t\t\t\t\t\t   const int messageValue,\n\t\t\t\t\t\t\t\t   IN_OPT const void *aclPtr )\n\t{\n\tconst OBJECT_INFO *objectTable = getObjectTable();\n\tint status;\n\n\tassert( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );\n\n\t/* Precondition: It's a valid message being sent to a valid object */\n\tREQUIRES( isValidObject( localObjectHandle ) );\n\tREQUIRES( isValidMessage( message & MESSAGE_MASK ) );\n\n\t/* If there's a pre-dispatch handler, invoke it */\n\tif( handlingInfoPtr->preDispatchFunction != NULL )\n\t\t{\n\t\tstatus = handlingInfoPtr->preDispatchFunction( localObjectHandle,\n\t\t\t\t\t\t\t\t\tmessage, messageDataPtr, messageValue,\n\t\t\t\t\t\t\t\t\taclPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Inner precondition: Either the message as a whole is internally \n\t   handled or it's a property attribute */\n\tREQUIRES( handlingInfoPtr->internalHandlerFunction != NULL || \\\n\t\t\t  isAttributeMessage( message & MESSAGE_MASK ) );\n\n\t/* If it's an object property attribute (which is handled by the kernel), \n\t   get or set its value */\n\tif( handlingInfoPtr->internalHandlerFunction == NULL )\n\t\t{\n\t\t/* Precondition: Object properties are always numeric attributes, \n\t\t   and there's always a message value present */\n\t\tREQUIRES( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE || \\\n\t\t\t\t  handlingInfoPtr->messageType == MESSAGE_SETATTRIBUTE );\n\t\tREQUIRES( messageDataPtr != NULL );\n\n\t\tif( handlingInfoPtr->messageType == MESSAGE_GETATTRIBUTE )\n\t\t\t{\n\t\t\tstatus = getPropertyAttribute( localObjectHandle, messageValue, \n\t\t\t\t\t\t\t\t\t\t   messageDataPtr );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = setPropertyAttribute( localObjectHandle, messageValue, \n\t\t\t\t\t\t\t\t\t\t   messageDataPtr );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a kernel-handled message, process it */\n\t\tstatus = handlingInfoPtr->internalHandlerFunction( localObjectHandle, \n\t\t\t\t\t\t\t\t\t\t\t\tmessageValue, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tisInternalMessage( message ) ? \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Postcondition: It's a genuine error, or a special-case condition\n\t\t   such as the object creation being aborted, which produces an \n\t\t   OK_SPECIAL status to tell the caller to convert the message that\n\t\t   triggered this into a MESSAGE_DESTROY */\n\t\tENSURES( cryptStatusError( status ) || status == OK_SPECIAL );\n\n\t\treturn( status );\n\t\t}\n\n\t/* If there's a post-dispatch handler, invoke it */\n\tif( handlingInfoPtr->postDispatchFunction != NULL )\n\t\t{\n\t\tstatus = handlingInfoPtr->postDispatchFunction( localObjectHandle, \n\t\t\t\t\t\t\t\t\tmessage, messageDataPtr, messageValue, \n\t\t\t\t\t\t\t\t\taclPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Dispatch a message to an object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int dispatchMessage( IN_HANDLE const int localObjectHandle,\n\t\t\t\t\t\t\tconst MESSAGE_QUEUE_DATA *messageQueueData,\n\t\t\t\t\t\t\tINOUT OBJECT_INFO *objectInfoPtr,\n\t\t\t\t\t\t\tIN_OPT const void *aclPtr )\n\t{\n\tconst MESSAGE_HANDLING_INFO *handlingInfoPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( messageQueueData->handlingInfoPtr );\n\tconst MESSAGE_FUNCTION messageFunction = ( MESSAGE_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( objectInfoPtr->messageFunction );\n\tconst MESSAGE_TYPE localMessage = \\\n\t\t\t\t\t\tmessageQueueData->message & MESSAGE_MASK;\n\tconst void *messageDataPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( messageQueueData->messageDataPtr );\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable = getObjectTable();\n\tMESSAGE_FUNCTION_EXTINFO messageExtInfo;\n\tvoid *objectPtr = DATAPTR_GET( objectInfoPtr->objectPtr );\n\tBOOLEAN mayUnlock = FALSE;\n\tint status;\n\tORIGINAL_INT_VAR( lockCount, objectInfoPtr->lockCount );\n\n\tassert( isReadPtr( messageQueueData, sizeof( MESSAGE_QUEUE_DATA ) ) );\n\tassert( isWritePtr( objectInfoPtr, sizeof( OBJECT_INFO ) ) );\n\n\tREQUIRES( isValidObject( localObjectHandle ) );\n\tREQUIRES( !isInUse( localObjectHandle ) || \\\n\t\t\t  isObjectOwner( localObjectHandle ) );\n\tREQUIRES( sanityCheckObject( objectInfoPtr ) );\n\tREQUIRES( handlingInfoPtr != NULL );\n\tREQUIRES( messageFunction != NULL );\n\tREQUIRES( DATAPTR_ISVALID( messageQueueData->messageDataPtr ) );\n\t\t\t  /* messageDataPtr is NULL for a number of messages */\n\tREQUIRES( objectPtr != NULL );\n\n\t/* If there's a pre-dispatch handler present, apply it */\n\tif( handlingInfoPtr->preDispatchFunction != NULL )\n\t\t{\n\t\tstatus = handlingInfoPtr->preDispatchFunction( localObjectHandle,\n\t\t\t\t\t\t\t\t\tmessageQueueData->message, messageDataPtr,\n\t\t\t\t\t\t\t\t\tmessageQueueData->messageValue, aclPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Some objects (generally the system object and to a lesser extent other\n\t   devices and the default user object) may unlock themselves while \n\t   processing a message when they forward the message elsewhere or perform \n\t   non-object-specific processing.  If this may be the case then we pass \n\t   in an extended message structure to record this information */\n\tinitMessageExtInfo( &messageExtInfo, objectPtr );\n\tif( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) || \\\n\t\t( handlingInfoPtr->flags & MESSAGE_HANDLING_FLAG_MAYUNLOCK ) )\n\t\t{\n\t\tmayUnlock = TRUE;\n\t\tobjectPtr = &messageExtInfo;\n\t\t}\n\n\t/* Mark the object as busy so that we have it available for our\n\t   exclusive use and further messages to it will be enqueued, dispatch\n\t   the message with the object table unlocked, and mark the object as\n\t   non-busy again */\n\tobjectInfoPtr->lockCount++;\n#ifdef USE_THREADS\n\tobjectInfoPtr->lockOwner = THREAD_SELF();\n#endif /* USE_THREADS */\n\tMUTEX_UNLOCK( objectTable );\n\tstatus = messageFunction( objectPtr, localMessage,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) messageDataPtr,\n\t\t\t\t\t\t\t  messageQueueData->messageValue );\n\tMUTEX_LOCK( objectTable );\n\tobjectTable = getObjectTable();\n\tobjectInfoPtr = &objectTable[ localObjectHandle ];\n\tif( !isValidType( objectInfoPtr->type ) )\n\t\tretIntError();\t/* Something catastrophic happened while unlocked */\n\tif( !( mayUnlock && isMessageObjectUnlocked( &messageExtInfo ) ) )\n\t\tobjectInfoPtr->lockCount--;\n\n\t/* Postcondition: The lock count is non-negative and, if it's not the\n\t   system object, has been reset to its previous value */\n\tENSURES( objectInfoPtr->lockCount >= 0 && \\\n\t\t\t ( localObjectHandle == SYSTEM_OBJECT_HANDLE ||\n\t\t\t   objectInfoPtr->lockCount == ORIGINAL_VALUE( lockCount ) ) );\n\n\t/* If there's a post-dispatch handler present, apply it.  Since a\n\t   destroy object message always succeeds but can return an error code\n\t   (typically CRYPT_ERROR_INCOMPLETE), we don't treat an error return as\n\t   a real error status for the purposes of further processing */\n\tif( ( cryptStatusOK( status ) || localMessage == MESSAGE_DESTROY ) && \\\n\t\thandlingInfoPtr->postDispatchFunction != NULL )\n\t\t{\n\t\tconst BOOLEAN isIncomplete = ( localMessage == MESSAGE_DESTROY && \\\n\t\t\t\t\t\t\t\t\t   status == CRYPT_ERROR_INCOMPLETE ) ? \\\n\t\t\t\t\t\t\t\t\t TRUE : FALSE;\n\n\t\tstatus = handlingInfoPtr->postDispatchFunction( localObjectHandle,\n\t\t\t\t\t\t\t\t\t\tmessageQueueData->message, messageDataPtr,\n\t\t\t\t\t\t\t\t\t\tmessageQueueData->messageValue, aclPtr );\n\t\tif( isIncomplete )\n\t\t\t{\n\t\t\t/* Normally we don't call the post-dispatch handler on error, \n\t\t\t   however if it's a destroy message then we have to call it \n\t\t\t   in order to handle any additional cleanup operations since \n\t\t\t   the object is about to be destroyed, so if the destroy \n\t\t\t   message to the object returned an incomplete error a we \n\t\t\t   override any post-dispatch status with the original error\n\t\t\t   status */\n\t\t\tstatus = CRYPT_ERROR_INCOMPLETE;\n\t\t\t}\n\t\t}\n\treturn( status );\n\t}\n\n/* Send a message to an object */\n\nRETVAL \\\nPARAMCHECK_MESSAGE( MESSAGE_DESTROY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_INCREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DECREFCOUNT, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETDEPENDENT, OUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETDEPENDENT, IN, IN ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CLONE, PARAM_NULL, IN_HANDLE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE, OUT, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_GETATTRIBUTE_S, INOUT, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE, IN, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SETATTRIBUTE_S, IN, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DELETEATTRIBUTE, PARAM_NULL, IN_ATTRIBUTE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_COMPARE, IN, IN_ENUM( MESSAGE_COMPARE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CHECK, PARAM_NULL, IN_ENUM( MESSAGE_CHECK ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_SELFTEST, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CHANGENOTIFY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_ENCRYPT, INOUT, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_DECRYPT, INOUT, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_SIGN, IN, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_SIGCHECK, IN, IN_LENGTH ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_HASH, IN, IN_LENGTH_Z ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_GENKEY, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CTX_GENIV, PARAM_NULL, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_SIGN, PARAM_NULL, IN_HANDLE ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_SIGCHECK, PARAM_NULL, IN_HANDLE_OPT ) \\\nPARAMCHECK_MESSAGE( MESSAGE_CRT_EXPORT, INOUT, IN_ENUM( CRYPT_CERTFORMAT ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_QUERYCAPABILITY, OUT, IN_ALGO ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_EXPORT, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_IMPORT, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_SIGN, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_SIGCHECK, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_DERIVE, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_KDF, INOUT, IN_ENUM( MECHANISM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_DEV_CREATEOBJECT_INDIRECT, INOUT, IN_ENUM( OBJECT_TYPE ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_ENV_PUSHDATA, INOUT, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_ENV_POPDATA, INOUT, PARAM_IS( 0 ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_SETKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_DELETEKEY, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETFIRSTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_GETNEXTCERT, INOUT, IN_ENUM( KEYMGMT_ITEM ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_KEY_CERTMGMT, INOUT, IN_ENUM( CRYPT_CERTACTION ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_USER_USERMGMT, INOUT, IN_ENUM( MESSAGE_USERMGMT ) ) \\\nPARAMCHECK_MESSAGE( MESSAGE_USER_TRUSTMGMT, IN, IN_ENUM( MESSAGE_TRUSTMGMT ) ) \\\n\t\t\t\t\t/* Actually INOUT for MESSAGE_TRUSTMGMT_GETISSUER, but too \\\n\t\t\t\t\t   complex to annotate */ \\\nint krnlSendMessage( IN_HANDLE const int objectHandle, \n\t\t\t\t\t IN_MESSAGE const MESSAGE_TYPE message,\n\t\t\t\t\t void *messageDataPtr, const int messageValue )\n\t{\n\tconst ATTRIBUTE_ACL *attributeACL = NULL;\n\tconst MESSAGE_HANDLING_INFO *handlingInfoPtr;\n\tKERNEL_DATA *krnlData = getKrnlData();\n\tOBJECT_INFO *objectTable, *objectInfoPtr;\n\tMESSAGE_QUEUE_DATA enqueuedMessageData;\n\tconst BOOLEAN isInternalMessage = isInternalMessage( message ) ? \\\n\t\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tconst void *aclPtr = NULL;\n\tMESSAGE_TYPE localMessage = message & MESSAGE_MASK;\n\tint localObjectHandle = objectHandle;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\t/* Preconditions.  For external messages we don't provide any assertions\n\t   at this point since they're coming straight from the user and could\n\t   contain any values, and for internal messages we only trap on\n\t   programming errors (thus for example isValidHandle() vs.\n\t   isValidObject(), since this would trap if a message is sent to a\n\t   destroyed object) */\n\tREQUIRES( isValidMessage( localMessage ) );\n\tREQUIRES( !isInternalMessage || isValidHandle( objectHandle ) );\n\n\t/* Perform optional memory fault injection for every message sent */\n\tINJECT_MEMORY_FAULTS();\n\n\t/* Get the information that we need to handle this message */\n\thandlingInfoPtr = &messageHandlingInfo[ localMessage ];\n\n\t/* Inner preconditions now that we have the handling information: Message\n\t   parameters must be within the allowed range */\n\tREQUIRES( checkParams( handlingInfoPtr->paramCheck, messageDataPtr, \n\t\t\t\t\t\t   messageValue ) );\n\n\t/* If it's an object-manipulation message get the attribute's mandatory\n\t   ACL; if it's an object-parameter message get the parameter's mandatory\n\t   ACL.  Since these doesn't require access to any object information, we\n\t   can do it before we lock the object table */\n\tif( isAttributeMessage( localMessage ) )\n\t\t{\n\t\tattributeACL = findAttributeACL( messageValue, isInternalMessage );\n\t\tif( attributeACL == NULL )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\taclPtr = attributeACL;\n\n\t\t/* Because cryptlib can be called through a variety of different \n\t\t   language bindings it's not guaranteed that the values of TRUE and \n\t\t   FALSE (as supplied by the caller) will always be 1 and 0.  For\n\t\t   example Visual Basic uses the value -1 for TRUE because of \n\t\t   obscure backwards-compatibility and implementation issues with \n\t\t   16-bit versions of VB.  In order to avoid complaints from various\n\t\t   checks at lower levels of cryptlib, we replace any boolean values\n\t\t   with a setting other than FALSE with the explicit boolean value \n\t\t   TRUE.  This is a bit of an ugly kludge but it avoids having to\n\t\t   special-case these values at all sorts of other locations in the\n\t\t   code */\n\t\tif( localMessage == MESSAGE_SETATTRIBUTE && \\\n\t\t\tattributeACL->valueType == ATTRIBUTE_VALUE_BOOLEAN )\n\t\t\t{\n\t\t\tREQUIRES( messageDataPtr != NULL );\n\n\t\t\tif( *( ( BOOLEAN * ) messageDataPtr ) )\n\t\t\t\tmessageDataPtr = MESSAGE_VALUE_TRUE;\n\t\t\t}\n\t\t}\n\tif( isParamMessage( localMessage ) )\n\t\t{\n\t\taclPtr = findParamACL( localMessage );\n\t\tENSURES( aclPtr != NULL );\n\t\t}\n\n\t/* Inner precondition: If it's an attribute-manipulation message, we have\n\t   a valid ACL for the attribute present */\n\tREQUIRES( !isAttributeMessage( localMessage ) || attributeACL != NULL );\n\n\t/* If we're in the middle of a shutdown, don't allow any further\n\t   messages except ones related to object destruction (the status read\n\t   is needed for objects capable of performing async ops, since the\n\t   shutdown code needs to determine whether they're currently busy).\n\t   The check outside the object-table lock is done in order to have any\n\t   remaining active objects exit quickly without tying up the object\n\t   table, since we don't want them to block the shutdown.  In addition\n\t   if the thread is a leftover/long-running thread that's still active\n\t   after the shutdown has occurred, we can't access the object table\n\t   lock since it'll have been deleted */\n\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES && \\\n\t\t!( localMessage == MESSAGE_DESTROY || \\\n\t\t   localMessage == MESSAGE_DECREFCOUNT || \\\n\t\t   ( localMessage == MESSAGE_GETATTRIBUTE && \\\n\t\t\t messageValue == CRYPT_IATTRIBUTE_STATUS ) ) )\n\t\t{\n\t\t/* Exit without even trying to acquire the object table lock */\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* Lock the object table to ensure that other threads don't try to\n\t   access it */\n\tMUTEX_LOCK( objectTable );\n\tobjectTable = getObjectTable();\n\n\t/* The first line of defence: Make sure that the message is being sent\n\t   to a valid object and that the object is externally visible and\n\t   accessible to the caller if required by the message.  The checks\n\t   performed are:\n\n\t\tif( handle does not correspond to an object )\n\t\t\terror;\n\t\tif( message is external )\n\t\t\t{\n\t\t\tif( object is internal )\n\t\t\t\terror;\n\t\t\tif( object isn't owned by calling thread )\n\t\t\t\terror;\n\t\t\t}\n\n\t   This is equivalent to the shorter form fullObjectCheck() that used\n\t   elsewhere.  The error condition reported in all of these cases is\n\t   that the object handle isn't valid */\n\tif( !isValidObject( objectHandle ) )\n\t\tstatus = CRYPT_ARGERROR_OBJECT;\n\telse\n\t\t{\n\t\tif( !isInternalMessage && \\\n\t\t\t( isInternalObject( objectHandle ) || \\\n\t\t\t  !checkObjectOwnership( objectTable[ objectHandle ] ) ) )\n\t\t\tstatus = CRYPT_ARGERROR_OBJECT;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\treturn( status );\n\t\t}\n\n\t/* Inner precondition now that the outer check has been passed: It's a\n\t   valid, accessible object and not a system object that can never be\n\t   explicitly destroyed or have its refCount altered */\n\tREQUIRES_MUTEX( isValidObject( objectHandle ), objectTable );\n\tREQUIRES_MUTEX( isInternalMessage || ( !isInternalObject( objectHandle ) && \\\n\t\t\t\t\tcheckObjectOwnership( objectTable[ objectHandle ] ) ), \\\n\t\t\t\t\tobjectTable );\n\tREQUIRES_MUTEX( fullObjectCheck( objectHandle, message ), objectTable );\n\tREQUIRES_MUTEX( objectHandle >= NO_SYSTEM_OBJECTS || \\\n\t\t\t\t\t( localMessage != MESSAGE_DESTROY && \\\n\t\t\t\t\t  localMessage != MESSAGE_DECREFCOUNT && \\\n\t\t\t\t\t  localMessage != MESSAGE_INCREFCOUNT ), objectTable );\n\n\t/* If this message is routable, find its target object */\n\tif( handlingInfoPtr->routingFunction != NULL )\n\t\t{\n\t\t/* If it's implicitly routed, route it based on the attribute type */\n\t\tif( isImplicitRouting( handlingInfoPtr->routingTarget ) )\n\t\t\t{\n\t\t\tREQUIRES_MUTEX( attributeACL != NULL, objectTable );\n\n\t\t\tif( attributeACL->routingFunction != NULL )\n\t\t\t\t{\n\t\t\t\tstatus = attributeACL->routingFunction( objectHandle,\n\t\t\t\t\t\t\t\t\t\t\t&localObjectHandle,\n\t\t\t\t\t\t\t\t\t\t\tattributeACL->routingTarget );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's explicitly or directly routed, route it based on the\n\t\t\t   message type or fixed-target type */\n\t\t\tstatus = handlingInfoPtr->routingFunction( objectHandle,\n\t\t\t\t\t\t\t\t\t\t\t&localObjectHandle,\n\t\t\t\t\t\tisExplicitRouting( handlingInfoPtr->routingTarget ) ? \\\n\t\t\t\t\t\tmessageValue : handlingInfoPtr->routingTarget );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t\t}\n\t\t}\n\n\t/* Inner precodition: It's a valid destination object */\n\tREQUIRES_MUTEX( isValidObject( localObjectHandle ), objectTable );\n\n\t/* Sanity-check the message routing */\n\tif( !isValidObject( localObjectHandle ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tretIntError();\n\t\t}\n\n\t/* It's a valid object, get its info */\n\tobjectInfoPtr = &objectTable[ localObjectHandle ];\n\tREQUIRES_MUTEX( sanityCheckObject( objectInfoPtr ), objectTable );\n\n\t/* Now that the message has been routed to its intended target, make sure\n\t   that it's valid for the target object subtype */\n\tif( !isValidSubtype( handlingInfoPtr->subTypeA, objectInfoPtr->subType ) && \\\n\t\t!isValidSubtype( handlingInfoPtr->subTypeB, objectInfoPtr->subType ) && \\\n\t\t!isValidSubtype( handlingInfoPtr->subTypeC, objectInfoPtr->subType ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\treturn( CRYPT_ARGERROR_OBJECT );\n\t\t}\n\n\t/* Inner precondition: The message is valid for this object subtype */\n\tREQUIRES_MUTEX( isValidSubtype( handlingInfoPtr->subTypeA, \\\n\t\t\t\t\t\t\t\t\tobjectInfoPtr->subType ) || \\\n\t\t\t\t\tisValidSubtype( handlingInfoPtr->subTypeB, \\\n\t\t\t\t\t\t\t\t\tobjectInfoPtr->subType ) || \\\n\t\t\t\t\tisValidSubtype( handlingInfoPtr->subTypeC, \\\n\t\t\t\t\t\t\t\t\tobjectInfoPtr->subType ), \\\n\t\t\t\t\tobjectTable );\n\n\t/* If this message is processed internally, handle it now.  These\n\t   messages aren't affected by the object's state so they're always\n\t   processed */\n\tif( handlingInfoPtr->internalHandlerFunction != NULL || \\\n\t\t( attributeACL != NULL && \\\n\t\t  attributeACL->flags & ATTRIBUTE_FLAG_PROPERTY ) )\n\t\t{\n\t\tstatus = processInternalMessage( localObjectHandle, handlingInfoPtr, \n\t\t\t\t\t\t\t\t\t\t message, messageDataPtr, \n\t\t\t\t\t\t\t\t\t\t messageValue, aclPtr );\n\t\tif( status != OK_SPECIAL )\n\t\t\t{\n\t\t\t/* The message was processed normally, exit */\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* The object has entered an invalid state (for example it was\n\t\t   signalled while it was being initialised) and can't be used any\n\t\t   more, convert the (local copy of the) message into a destroy \n\t\t   object message */\n\t\tlocalMessage = MESSAGE_DESTROY;\n\t\tstatus = CRYPT_OK;\n\t\t}\n\n\t/* If the object isn't already processing a message and the message isn't\n\t   a special type such as MESSAGE_DESTROY, dispatch it immediately rather\n\t   than enqueueing it for later dispatch.  This scoreboard mechanism\n\t   greatly reduces the load on the queue */\n\tif( !isInUse( localObjectHandle ) && localMessage != MESSAGE_DESTROY )\n\t\t{\n\t\tMESSAGE_QUEUE_DATA messageQueueData;\n\n\t\t/* If the object isn't in a valid state, we can't do anything with it.\n\t\t   There are no messages that can be sent to it at this point, get/\n\t\t   set property messages have already been handled earlier and the\n\t\t   destroy message isn't handled here */\n\t\tif( isInvalidObjectState( localObjectHandle ) )\n\t\t\t{\n\t\t\tstatus = getObjectStatusValue( objectInfoPtr->flags );\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* In case a shutdown was signalled while we were performing other\n\t\t   processing, exit now before we try and do anything with the\n\t\t   object.  It's safe to perform the check at this point since no\n\t\t   message sent during shutdown will get here */\n\t\tif( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES )\n\t\t\t{\n\t\t\tMUTEX_UNLOCK( objectTable );\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\n\t\t/* Inner precondition: The object is in a valid state */\n\t\tREQUIRES_MUTEX( !isInvalidObjectState( localObjectHandle ), \\\n\t\t\t\t\t\tobjectTable );\n\n\t\t/* Dispatch the message to the object.  We can't use a constant \n\t\t   struct here (declared and initialised at the start of this code \n\t\t   block) because of the use of error-detecting pointers */\n\t\tmessageQueueData.objectHandle = localObjectHandle; \n\t\tDATAPTR_SET( messageQueueData.handlingInfoPtr, \n\t\t\t\t\t ( void * ) handlingInfoPtr ); \n\t\tmessageQueueData.message = message; \n\t\tDATAPTR_SET( messageQueueData.messageDataPtr, messageDataPtr ); \n\t\tmessageQueueData.messageValue = messageValue;\n\t\tstatus = dispatchMessage( localObjectHandle, &messageQueueData,\n\t\t\t\t\t\t\t\t  objectInfoPtr, aclPtr );\n\t\tMUTEX_UNLOCK( objectTable );\n\n\t\t/* If it's a zeroise, perform a kernel shutdown.  In theory we could \n\t\t   do this from the post-dispatch handler, but we need to make sure \n\t\t   that there are no further kernel actions to be taken before we \n\t\t   perform the shutdown, so we do it at this level instead */\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( messageQueueData.message & MESSAGE_MASK ) == MESSAGE_USER_USERMGMT && \\\n\t\t\tmessageQueueData.messageValue == MESSAGE_USERMGMT_ZEROISE )\n\t\t\t{\n\t\t\t/* Since it's a zeroise we return the status of the overall \n\t\t\t   zeroise operation rather than any possible non-OK status from\n\t\t\t   shutting down the kernel at the end of the zeroise */\n\t\t\t( void ) endCryptlib();\n\t\t\t}\n\n\t\t/* Postcondition: The return status is valid */\n\t\tENSURES( cryptStandardError( status ) || \\\n\t\t\t\t cryptArgError( status ) || status == OK_SPECIAL );\n\n\t\treturn( status );\n\t\t}\n\n\t/* Inner precondition: The object is in use or it's a destroy object\n\t   message, we have to enqueue it */\n\tREQUIRES_MUTEX( isInUse( localObjectHandle ) || \\\n\t\t\t\t\tlocalMessage == MESSAGE_DESTROY, \\\n\t\t\t\t\tobjectTable );\n\n\t/* If we're stuck in a loop processing recursive messages, bail out.\n\t   This would happen automatically anyway once we fill the message queue,\n\t   but this early-out mechanism prevents a single object from filling the\n\t   queue to the detriment of other objects */\n\tif( objectInfoPtr->lockCount > MESSAGE_QUEUE_SIZE / 2 )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\tDEBUG_DIAG(( \"Invalid kernel message queue state\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\t}\n\n\t/* If the object is in use by another thread, wait for it to become\n\t   available */\n\tif( isInUse( localObjectHandle ) && !isObjectOwner( localObjectHandle ) )\n\t\t{\n\t\tstatus = waitForObject( localObjectHandle, &objectInfoPtr );\n#if !defined( NDEBUG ) && defined( USE_THREADS )\n\t\tif( cryptStatusOK( status ) && isInUse( localObjectHandle ) )\n\t\t\t{\n\t\t\t/* dispatchMessage() expects us to be the lock owner if the\n\t\t\t   object is in use, however if the object has been */\n\t\t\tobjectInfoPtr->lockOwner = THREAD_SELF();\n\t\t\t}\n#endif /* !NDEBUG && USE_THREADS */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMUTEX_UNLOCK( objectTable );\n\t\treturn( status );\n\t\t}\n\tassert( !isInUse( localObjectHandle ) || \\\n\t\t\tisObjectOwner( localObjectHandle ) );\n\n\t/* Enqueue the message */\n\tif( ( message & MESSAGE_MASK ) != localMessage )\n\t\t{\n\t\t/* The message was converted during processing, this can only happen\n\t\t   when a message sent to an invalid-state object is converted into\n\t\t   a destroy-object message.  What we therefore enqueue is a\n\t\t   destroy-object message, but with the messageValue parameter set\n\t\t   to TRUE to indicate that it's a converted destroy message */\n\t\tREQUIRES_MUTEX( localMessage == MESSAGE_DESTROY, objectTable );\n\n\t\tstatus = enqueueMessage( localObjectHandle,\n\t\t\t\t\t\t\t\t &messageHandlingInfo[ MESSAGE_DESTROY ],\n\t\t\t\t\t\t\t\t MESSAGE_DESTROY, messageDataPtr, TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = enqueueMessage( localObjectHandle, handlingInfoPtr, message,\n\t\t\t\t\t\t\t\t messageDataPtr, messageValue );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* A message for this object is already present in the queue, defer\n\t\t   processing until later */\n\t\tMUTEX_UNLOCK( objectTable );\n\t\treturn( ( status == OK_SPECIAL ) ? CRYPT_OK : status );\n\t\t}\n\tassert( !isInUse( localObjectHandle ) || \\\n\t\t\tisObjectOwner( localObjectHandle ) );\n\n\t/* While there are more messages for this object present, dequeue them\n\t   and dispatch them.  Since messages will only be enqueued if\n\t   krnlSendMessage() is called recursively, we only dequeue messages for\n\t   the current object in this loop.  Queued messages for other objects\n\t   will be handled at a different level of recursion.\n\t   \n\t   Bounding this loop is a bit tricky because new messages can arrive as\n\t   the existing ones are dequeued, so that in theory the arrival rate\n\t   could match the dispatch rate.  However in practice a situation like\n\t   this would be extremely unusual, so we bound the loop at\n\t   FAILSAFE_ITERATIONS_LARGE */\n\tLOOP_LARGE_CHECK( getNextMessage( localObjectHandle, &enqueuedMessageData ) )\n\t\t{\n\t\tconst BOOLEAN isDestroy = \\\n\t\t\t( ( enqueuedMessageData.message & MESSAGE_MASK ) == MESSAGE_DESTROY ) ? \\\n\t\t\tTRUE : FALSE;\n\t\tconst BOOLEAN isZeroise = \\\n\t\t\t( ( enqueuedMessageData.message & MESSAGE_MASK ) == MESSAGE_USER_USERMGMT && \\\n\t\t\t  enqueuedMessageData.messageValue == MESSAGE_USERMGMT_ZEROISE ) ? \\\n\t\t\tTRUE : FALSE;\n\t\tconst BOOLEAN isConvertedDestroy = \\\n\t\t\t( isDestroy && ( enqueuedMessageData.messageValue == TRUE ) ) ? \\\n\t\t\tTRUE : FALSE;\n\n\t\t/* If there's a problem with the object, initiate special processing.\n\t\t   The exception to this is a destroy message that started out as a \n\t\t   different type of message (that is, it was converted into a \n\t\t   destroy object message due to the object being in an invalid \n\t\t   state, indicated by the messageValue parameter being set to TRUE\n\t\t   when it's normally zero for a destroy message), which is let \n\t\t   through */\n\t\tif( isInvalidObjectState( localObjectHandle ) && !isConvertedDestroy )\n\t\t\t{\n\t\t\t/* If it's a destroy object message being sent to an object in\n\t\t\t   the process of being created, set the state to signalled and\n\t\t\t   continue.  The object will be destroyed when the caller\n\t\t\t   notifies the kernel that the init is complete */\n\t\t\tif( isDestroy && TEST_FLAG( objectInfoPtr->flags, \n\t\t\t\t\t\t\t\t\t\tOBJECT_FLAG_NOTINITED ) )\n\t\t\t\t{\n\t\t\t\tSET_FLAG( objectInfoPtr->flags, OBJECT_FLAG_SIGNALLED );\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Remove all further messages for this object and return\n\t\t\t\t   to the caller */\n\t\t\t\tdequeueAllMessages( localObjectHandle );\n\t\t\t\tstatus = getObjectStatusValue( objectInfoPtr->flags );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\t\tassert( !isInUse( localObjectHandle ) || \\\n\t\t\t\tisObjectOwner( localObjectHandle ) );\n\n\t\t/* Inner precondition: The object is in a valid state or it's a\n\t\t   destroy message that was converted from a different message \n\t\t   type */\n\t\tREQUIRES_MUTEX( !isInvalidObjectState( localObjectHandle ) || \\\n\t\t\t\t\t\t( isDestroy && ( enqueuedMessageData.messageValue == TRUE ) ), \\\n\t\t\t\t\t\tobjectTable );\n\n\t\t/* Dispatch the message to the object.  Before we forward it on, if\n\t\t   this is a message that was converted to a destroy message we have \n\t\t   to reset the special-case message indicator to make it a standard\n\t\t   destroy message */\n\t\tif( isConvertedDestroy )\n\t\t\tenqueuedMessageData.messageValue = 0;\n\t\tstatus = dispatchMessage( localObjectHandle, &enqueuedMessageData,\n\t\t\t\t\t\t\t\t  objectInfoPtr, aclPtr );\n\n\t\t/* If the message is a destroy object message, we have to explicitly\n\t\t   remove it from the object table and dequeue all further messages\n\t\t   for it since the object's message handler can't do this itself.\n\t\t   Since a destroy object message always succeeds but can return an\n\t\t   error code (typically CRYPT_ERROR_INCOMPLETE), we don't treat an\n\t\t   error return as a real error status for the purposes of further\n\t\t   processing */\n\t\tif( isDestroy )\n\t\t\t{\n\t\t\tint destroyStatus;\t/* Preserve original status value */\n\n\t\t\tdestroyStatus = destroyObjectData( localObjectHandle );\n\t\t\tENSURES_MUTEX( cryptStatusOK( destroyStatus ), objectTable );\n\t\t\tdequeueAllMessages( localObjectHandle );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If we ran into a problem or this is a zeroise (i.e. a \n\t\t\t   localised shutdown), dequeue all further messages for this \n\t\t\t   object.  This causes getNextMessage() to fail and we drop out \n\t\t\t   of the loop */\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t( cryptStatusOK( status ) && isZeroise ) )\n\t\t\t\t{\n\t\t\t\tdequeueAllMessages( localObjectHandle );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES_MUTEX( LOOP_BOUND_OK, objectTable );\n\n\t/* Unlock the object table to allow access by other threads */\n\tMUTEX_UNLOCK( objectTable );\n\n\t/* If it's a zeroise, perform a kernel shutdown.  In theory we could do \n\t   this from the post-dispatch handler, but we need to make sure that \n\t   there are no further kernel actions to be taken before we perform the \n\t   shutdown, so we do it at this level instead */\n\tif( cryptStatusOK( status ) && localMessage == MESSAGE_USER_USERMGMT && \\\n\t\tmessageValue == MESSAGE_USERMGMT_ZEROISE )\n\t\t{\n\t\t/* Since it's a zeroise we return the status of the overall zeroise \n\t\t   operation rather than any possible non-OK status from shutting \n\t\t   down the kernel at the end of the zeroise */\n\t\t( void ) endCryptlib();\n\t\t}\n\n\t/* Postcondition: The return status is valid */\n\tENSURES( cryptStandardError( status ) || cryptArgError( status ) || \\\n\t\t\t status == OK_SPECIAL );\n\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/kernel/storage.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Storage\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef __STDC__\n  #include <stddef.h>\t\t/* For offsetof() */\n#endif /* __STDC__ */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #ifdef USE_CERTIFICATES\n\t#include \"trustmgr_int.h\"\n  #endif /* USE_CERTIFICATES */\n  #include \"device.h\"\n  #include \"acl.h\"\n  #ifdef USE_TCP\n\t#include \"tcp_int.h\"\n  #endif /* USE_TCP */\n  #include \"kernel.h\"\n  #include \"user.h\"\n  #include \"user_int.h\"\n  #include \"random_int.h\"\n  #ifdef USE_SSL\n\t#include \"scorebrd_int.h\"\n  #endif /* USE_SSL */\n#else\n  #include \"crypt.h\"\n  #ifdef USE_CERTIFICATES\n\t#include \"cert/trustmgr_int.h\"\n  #endif /* USE_CERTIFICATES */\n  #include \"device/device.h\"\n  #ifdef USE_TCP\n\t#include \"io/tcp_int.h\"\n  #endif /* USE_TCP */\n  #include \"kernel/acl.h\"\n  #include \"kernel/kernel.h\"\n  #include \"misc/user.h\"\n  #include \"misc/user_int.h\"\n  #include \"random/random_int.h\"\n  #ifdef USE_SSL\n\t#include \"session/scorebrd_int.h\"\n  #endif /* USE_SSL */\n#endif /* Compiler-specific includes */\n\n/* cryptlib uses a preset amount of fixed storage for kernel data structures\n   and built-in objects, which can be allocated statically at compile time\n   rather than dynamically.  The following structure contains this fixed \n   storage, consisting of the kernel data, the object table, the system and \n   default user object storage, and any other fixed storage blocks that \n   might be needed */\n\ntypedef struct {\n\t/* The kernel data */\n\tKERNEL_DATA krnlData;\n\n\t/* The object table */\n\tOBJECT_INFO objectTable[ MAX_NO_OBJECTS ];\n\n\t/* The system object and default user object.  Since each object has \n\t   subtype-specific storage following it, we also allocate a block of\n\t   storage for the device subtype following it which isn't accessed\n\t   directly but implicitly follows the object storage */\n\tDEVICE_INFO systemDevice;\n\tSYSTEMDEV_INFO systemDeviceStorage;\n\tUSER_INFO defaultUserObject;\n\n\t/* The randomness information.  This is normally allocated in non-\n\t   pageable memory, but for embedded systems it's part of the \n\t   statically-allocated system storage */\n#ifdef USE_EMBEDDED_OS\n\tRANDOM_INFO randomInfo;\n#endif /* USE_EMBEDDED_OS */\n\n\t/* The certificate trust information */\n#ifdef USE_CERTIFICATES\n\tTRUST_INFO_CONTAINER trustInfoContainer;\t\n#endif /* USE_CERTIFICATES */\n\n\t/* The network socket pool */\n#ifdef USE_TCP\n\tSOCKET_INFO socketInfo[ SOCKETPOOL_SIZE ];\n#endif /* USE_TCP */\n\n\t/* The session scoreboard */\n#ifdef USE_SSL\n\tSCOREBOARD_INDEX_INFO scoreboardIndexInfo;\n#endif /* USE_SSL */\n\n\t/* The config option information.  This has a size defined by a complex\n\t   preprocessor expression (it's not a fixed struct) so we allocate it\n\t   as a byte array and let the caller manage it */\n\tBYTE optionInfo[ OPTION_INFO_SIZE ];\n\t} STORAGE_STRUCT;\n\nstatic STORAGE_STRUCT systemStorage;\n\n/* Initialise and destroy the built-in storage info */\n\n#if defined( __WINDOWS__ )\n\ntypedef HRESULT ( WINAPI *WERREGISTEREXCLUDEDMEMORYBLOCK )( const void *address, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tDWORD size );\nstatic void excludeSystemStorage( void )\n\t{\n\tWERREGISTEREXCLUDEDMEMORYBLOCK pWerRegisterExcludedMemoryBlock;\n\tHANDLE hKernel32;\n\n\t/* Try and get WerRegisterExcludedMemoryBlock().  Since this is a \n\t   Windows 10 function, we need to dynamically link it */\n\tif( ( hKernel32 = GetModuleHandle( \"Kernel32.dll\" ) ) == NULL )\n\t\treturn;\n\tpWerRegisterExcludedMemoryBlock = ( WERREGISTEREXCLUDEDMEMORYBLOCK ) \\\n\t\t\t\tGetProcAddress( hKernel32, \"WerRegisterExcludedMemoryBlock\" );\n\tif( pWerRegisterExcludedMemoryBlock == NULL )\n\t\treturn;\n\n\t/* Exclude the system storage from being submitted in an error report */\n\t( void ) pWerRegisterExcludedMemoryBlock( &systemStorage, \n\t\t\t\t\t\t\t\t\t\t\t  sizeof( STORAGE_STRUCT ) );\n\t}\n#elif defined( __UNIX__ )\n\n  #ifdef __linux__ \n\t#include <sys/mman.h>\n  #endif /* Linux */\n\nstatic void excludeSystemStorage( void )\n\t{\n\t/* Exclude the system storage from core dumps.  MADV_DONTDUMP is only\n\t   available under Linux, which also requires that the address provided \n\t   be page-aligned which the system storage block almost certainly \n\t   isn't (we'd have to use mmap() to allocate it, which defeats the \n\t   point of using statically-allocated memory), but this is only best-\n\t   effort anyway until a more universal facility for excluding the \n\t   memory block from dumps appears */\n#ifdef MADV_DONTDUMP\n\t( void ) madvise( &systemStorage, sizeof( STORAGE_STRUCT ), \n\t\t\t\t\t  MADV_DONTDUMP );\n#endif /* MADV_DONTDUMP */\n\t}\n#else\n  #define excludeSystemStorage()\n#endif /* OS-specific exclusion from memory dumps */\n\nvoid initBuiltinStorage( void )\n\t{\n\tmemset( &systemStorage, 0, sizeof( STORAGE_STRUCT ) );\n\texcludeSystemStorage();\n\t}\n\nvoid destroyBuiltinStorage( void )\n\t{\n\tmemset( &systemStorage, 0, sizeof( STORAGE_STRUCT ) );\n\t}\n\n/* When we start up and shut down the kernel, we need to clear the kernel\n   data.  However, the init lock may have been set by an external management\n   function, so we can't clear that part of the kernel data.  In addition,\n   on shutdown the shutdown level value must stay set so that any threads\n   still running will be forced to exit at the earliest possible instance,\n   and remain set after the shutdown has completed.  To handle this, we use\n   the following macro to clear only the appropriate area of the kernel data\n   block */\n\nvoid clearKernelData( void )\n\t{\n\tKERNEL_DATA *krnlDataPtr = &systemStorage.krnlData;\n\n#ifdef __STDC__\n\tzeroise( ( BYTE * ) krnlDataPtr + offsetof( KERNEL_DATA, initLevel ), \n\t\t\t sizeof( KERNEL_DATA ) - offsetof( KERNEL_DATA, initLevel ) );\n#else\n\tassert( &krnlDataPtr->endMarker - &krnlDataPtr->initLevel < sizeof( KERNEL_DATA ) ); \n\tzeroise( ( void * ) &krnlDataPtr->initLevel, \n\t\t\t &krnlDataPtr->endMarker - &krnlDataPtr->initLevel );\n#endif /* C89 compilers */\n\t}\n\n/* Access functions for the built-in storage */\n\nCHECK_RETVAL_PTR_NONNULL \\\nKERNEL_DATA *getKrnlData( void )\n\t{\n\treturn( &systemStorage.krnlData );\n\t}\n\nCHECK_RETVAL_PTR_NONNULL \\\nOBJECT_INFO *getObjectTable( void )\n\t{\n\treturn( systemStorage.objectTable );\n\t}\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getSystemDeviceStorage( void )\n\t{\n\treturn( &systemStorage.systemDevice );\n\t}\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getDefaultUserObjectStorage( void )\n\t{\n\treturn( &systemStorage.defaultUserObject );\n\t}\n\n#ifdef USE_EMBEDDED_OS\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getRandomInfoStorage( void )\n\t{\n\treturn( &systemStorage.randomInfo );\n\t}\n#endif /* USE_EMBEDDED_OS */\n\n#ifdef USE_CERTIFICATES\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getTrustMgrStorage( void )\n\t{\n\treturn( &systemStorage.trustInfoContainer );\n\t}\n#endif /* USE_CERTIFICATES */\n\n#ifdef USE_TCP\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getSocketPoolStorage( void )\n\t{\n\treturn( &systemStorage.socketInfo );\n\t}\n#endif /* USE_TCP */\n\n#ifdef USE_SSL\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getScoreboardInfoStorage( void )\n\t{\n\treturn( &systemStorage.scoreboardIndexInfo );\n\t}\n#endif /* USE_SSL */\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getOptionInfoStorage( void )\n\t{\n\treturn( &systemStorage.optionInfo );\n\t}\n\n/* Helper functions used when debugging.  These return the sizes of the \n   various data structures for use with fault-injection testing */\n\n#ifndef NDEBUG\n\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getKrnlDataSize( void )\n\t{\n\treturn( sizeof( KERNEL_DATA ) );\n\t}\n\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getObjectTableSize( void )\n\t{\n\treturn( sizeof( OBJECT_INFO ) );\n\t}\n\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getSystemDeviceStorageSize( void )\n\t{\n\treturn( sizeof( DEVICE_INFO ) + sizeof( SYSTEMDEV_INFO ) );\n\t}\n\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getDefaultUserObjectStorageSize( void )\n\t{\n\treturn( sizeof( USER_INFO )  );\n\t}\n\n#ifdef USE_EMBEDDED_OS\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getRandomInfoStorageSize( void )\n\t{\n\treturn( sizeof( RANDOM_INFO ) );\n\t}\n#endif /* USE_EMBEDDED_OS */\n\n#ifdef USE_CERTIFICATES\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getTrustMgrStorageSize( void )\n\t{\n\treturn( sizeof( TRUST_INFO_CONTAINER ) );\n\t}\n#endif /* USE_CERTIFICATES */\n\n#ifdef USE_TCP\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getSocketPoolStorageSize( void )\n\t{\n\treturn( sizeof( SOCKET_INFO ) * SOCKETPOOL_SIZE );\n\t}\n#endif /* USE_TCP */\n\n#ifdef USE_SSL\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getScoreboardInfoStorageSize( void )\n\t{\n\treturn( sizeof( SCOREBOARD_INDEX_INFO ) );\n\t}\n#endif /* USE_SSL */\n\nCHECK_RETVAL_LENGTH_NOERROR \\\nint getOptionInfoStorageSize( void )\n\t{\n\treturn( OPTION_INFO_SIZE );\n\t}\n#endif /* !NDEBUG */\n"
  },
  {
    "path": "deps/cl345/kernel/thread.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Thread/Mutex Handling  \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _THREAD_DEFINED\n\n#define _THREAD_DEFINED\n\n/* In multithreaded environments we need to use mutexes to protect the\n   information inside cryptlib data structures from access by other threads\n   while we use it.  In most cases (mutexes not taken) mutexes are extremely\n   quick, being implemented using compare-and-swap on x86 or load/store\n   conditional on most RISC CPUs.\n\n   The types and macros that are needed to handle mutexes are:\n\n\tMUTEX_HANDLE\t\t\t-- Handle for mutexes/semaphores\n\n\tMUTEX_DECLARE_STORAGE\t-- Declare storage for mutex\n\tMUTEX_CREATE\t\t\t-- Initialise mutex\n\tMUTEX_DESTROY\t\t\t-- Delete mutex\n\tMUTEX_LOCK\t\t\t\t-- Acquire mutex\n\tMUTEX_UNLOCK\t\t\t-- Release mutex\n\n   Before deleting a mutex we lock and unlock it again to ensure that if\n   some other thread is holding it they'll release it before we delete it.\n\n   Many systems don't provide re-entrant semaphores/mutexes.  To handle this\n   we implement our own re-entrant mutexes on top of the OS ones.  Using\n   the Posix terminology, what we do is use mutex_trylock(), which doesn't\n   re-lock the mutex if it's already locked, and as a side-benefit can be up\n   to twice as fast as mutex_lock(), depending on the OS.  This works as\n   follows:\n\n\t// Try and lock the mutex\n\tif( mutex_trylock( mutex ) == error )\n\t\t{\n\t\t// The mutex is already locked, see who owns it\n\t\tif( thread_self() != mutex_owner )\n\t\t\t// Someone else has it locked, wait for it to become available\n\t\t\tmutex_lock( mutex );\n\t\telse\n\t\t\t// We have it locked, increment its lock count\n\t\t\tmutex_lockcount++;\n\t\t}\n\tmutex_owner = thread_self();\n\n\t// ....\n\n\t// Decrement the lock count and if we reach zero, unlock the mutex\n\tif( mutex_lockcount > 0 )\n\t\tmutex_lockcount--;\n\telse\n\t\t{\n\t\tmutex_owner = none;\n\t\tmutex_unlock( mutex );\n\t\t}\n\n   This is safe from race conditions via the following:\n\n\tif( mutex_trylock( mutex ) == error )\n\t\t{\t\t\t\t\t\t\t\t\t\t--> Unlock #1\n\t\tif( thread_self() != mutex_owner )\n\t\t\t\t\t\t\t\t\t\t\t\t--> Unlock #2\n\t\t\tmutex_lock( mutex );\n\t\telse\n\t\t\tmutex_lockcount++;\n\t\t}\n\n   If the mutex is unlocked after the trylock at one of the two given \n   points, we can get the following situations:\n\n\tUnlock #1, no relock: mutex owner = none -> we lock the mutex\n\tUnlock #1, relock by another thread: \n\t\t\t   mutex owner = other -> we wait on the mutex lock\n\n\tUnlock #2, no relock: mutex owner = none -> we lock the mutex\n\tUnlock #2, relock by another thread: \n\t\t\t   mutex owner = other -> we wait on the mutex lock\n\n   There's no race condition in the lock process since the only thing that \n   could cause a problem is if we unlock the mutex ourselves, which we can't \n   do.\n\n   For the unlock process, the only possibility for a race condition is in\n   conjunction with the lock process, if the owner field isn't reset on \n   unlock then thread #1 could unlock the mutex and thread #2 could lock it\n   but be pre-empted before it can (re-)set the owner field.  Then thread #1\n   could reacquire it thinking that it still owns the mutex because the \n   owner field hasn't been reset yet from its previous ownership.  For this\n   reason it's essential that the owner field be reset before the mutex is\n   unlocked.\n\n   Note that this implementation of re-entrant mutexes will cause some \n   static source analysers to give false-positive warnings about not \n   unlocking mutexes, since they don't understand the reference-counting \n   mechanism and assume that the mutex is always locked but not always \n   unlocked.\n\n   An additional benefit to performing our own OS object management is that \n   we can avoid OS-specific exposure issues arising from the use of global \n   objects.  For example under Windows if an object with a given name \n   already exists, CreateXYZ() opens the existing object, ignores the \n   security parameters and the object-held flag (!!), and returns a success \n   status.  The only way to tell that we didn't actually get what we asked \n   for is that GetLastError() will return ERROR_ALREADY_EXISTS.  Without \n   this check we could end up thinking we safely hold the object (via the \n   ignored object-held flag) when in fact we don't.  Under Unix it's no \n   better, since a semaphore set (for example) is disconnected from the \n   processes that use it (access requires an on-demand lookup by semid) it's \n   possible for a name-squatting process to create the set before we do, we \n   \"create\" (= open) it, and then the other process deletes it and recreates \n   it in a different (and totally unexpected) configuration.  To our process \n   the disconnected lookup makes it appear to be the same semaphore set.  By \n   synthesising any higher-level objects that we need from low-level \n   primitives that aren't visible outside our process, we avoid this type \n   of exposure.\n\n   The types and macros that need to be declared to handle threading are:\n\n\tTHREAD_HANDLE\t\t\t-- Handle for threads\n\n\tTHREADFUNC_DEFINE\t\t-- Define thread function\n\n\tTHREAD_CREATE\t\t\t-- Create thread\n\tTHREAD_EXIT\t\t\t\t-- Exit from thread\n\tTHREAD_INITIALISER\t\t-- Value to initialise thread handle\n\tTHREAD_SELF\t\t\t\t-- Get handle of current thread\n\tTHREAD_SAME\t\t\t\t-- Compare two thread handles\n\tTHREAD_SLEEP\t\t\t-- Sleep for n milliseconds\n\tTHREAD_YIELD\t\t\t-- Yield thread's timeslice\n\tTHREAD_WAIT\t\t\t\t-- Wait for thread to terminate\n\tTHREAD_CLOSE\t\t\t-- Clean up thread after THREAD_WAIT (only needed\n\t\t\t\t\t\t\t   in a small number of OSes)\n\n   Some systems allow a thread/task handle to be used as a synchronisation\n   object while others require a separate semaphore object for\n   synchronisation.  To handle this we create a synchronisation semaphore in\n   the non-signalled state when we create a thread/task, signal it when the\n   task exits, and wait on it in the calling thread/task:\n\n\tParent:\t\t\t\t\t\t\t\t\tChild:\n\n\tsyncSem = createSem( 1 );\n\tthread = createThread( syncSem );\n\t\t\t\t\t\t\t\t\t\t\tsignal( syncSem );\n\t\t\t\t\t\t\t\t\t\t\texit();\n\twait( syncSem );\n\tdestroySem( syncSem );\n\n   If the thread/task handle can be used as a synchronisation object, these\n   additional operations are turned into no-ops.\n\n   Several of the embedded OSes are extremely difficult to work with because\n   their kernels perform no memory (or, often, resource) management of their\n   own, assuming that all memory will be allocated by the caller.  In the\n   simplest case this means that the thread stack/workspace has to be user-\n   allocated, in the worst case every object handle variable that's normally\n   a simple scalar value in other OSes is a composite non-scalar type that\n   contains all of the object's data, requiring that the caller manually\n   allocate state data for threads, mutexes, and semaphores rather than\n   having the OS do it for them.\n\n   For things like mutex and semaphore 'handles', which have a fixed number\n   or location, this is manageable by statically allocating the storage in\n   advance.  However it significantly complicates things like thread\n   handling because the thread that dynamically creates a worker thread has\n   to be around later on to clean up after it when it terminates, and the\n   state data has to be maintained in external (non-thread) storage.  We\n   handle this in one of two ways, either by not using cryptlib-internal\n   threads (they're only used for initialisation and keygen, neither of\n   which will benefit much from the ability to run them in the background in\n   an embedded system), or by wrapping the threading functions in our own\n   ones which allocate memory as required and access the information via a\n   scalar handle.\n\n   To enable the use of thread wrappers, see the xxx_THREAD_WRAPPERS define\n   for each embedded OS type.\n\n   For the embedded OSes that require user-allocated stack space, we use\n   the following as the stack size.  The 8192 byte storage area provides \n   enough space for the task control block and about half a dozen levels of \n   function nesting (if no large on-stack arrays are used), this should be \n   enough for background init but probably won't be sufficient for the \n   infinitely-recursive OpenSSL bignum code, so the value may need to be \n   adjusted if background keygen is being used */\n\n#define EMBEDDED_STACK_SIZE\t\t8192\n\n/* Define the following to debug mutex lock/unlock operations (only enabled\n   under Windows at the moment) */\n\n/* #define MUTEX_DEBUG */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAMX\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __AMX__ )\n\n/* To use resource-management wrappers for the AMX thread functions,\n   undefine the following */\n\n/* #define AMX_THREAD_WRAPPERS */\n\n#include <cjzzz.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tCJ_ID\n#define MUTEX_HANDLE\t\t\tCJ_ID\n\n/* Mutex management functions.  AMX resource semaphores are re-entrant so we\n   don't have to jump through the hoops that are necessary with most other\n   OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( cjrmcreate( &krnlData->name##Mutex, NULL ) == CJ_EROK ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tcjrmrsv( krnlData->name##Mutex, threadPriority(), 0 ); \\\n\t\t\tcjrmrls( krnlData->name##Mutex ); \\\n\t\t\tcjrmdelete( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tcjrmrsv( krnlData->name##Mutex, x, 0 )\n#define MUTEX_UNLOCK( name ) \\\n\t\tcjrmrls( krnlData->name##Mutex )\n\n/* Thread management functions.  AMX threads require that the user allocate\n   the stack space for them, unlike virtually every other embedded OS, which\n   make this at most a rarely-used option.  To handle this, we use our own\n   wrappers which hide this mess.  A second problem with AMX threads is that\n   there's no obvious way to pass an argument to a thread.  In theory we\n   could convey the information by sending it via a mailbox, but this\n   requires first conveying the mailbox ID to the new task, which has the\n   same problem.\n\n   We create the thread with the same priority as the calling thread, AMX\n   threads are created in the suspended state so after we create the thread\n   we have to trigger it to start it running */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( cyg_addrword_t arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\t\\\n\t\t\tcjsmcreate( &syncHandle, NULL, CJ_SMBINARY ); \\\n\t\t\tif( cjtkcreate( &threadHandle, NULL, function, threadStack, \\\n\t\t\t\t\t\t\tEMBEDDED_STACK_SIZE, 0, threadPriority(), \\\n\t\t\t\t\t\t\t0 ) != CJ_EROK ) \\\n\t\t\t\t{ \\\n\t\t\t\tfree( threadStack ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tcjtktrigger( threadHandle ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tcjsmsignal( sync ); \\\n\t\t\t\t\t\t\t\treturn\n#define THREAD_INITIALISER\t\tCJ_IDNULL\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tcjtkid()\n#define THREAD_SLEEP( ms )\t\tcjtkdelay( cjtmconvert( ms ) )\n#define THREAD_YIELD()\t\t\tcjtkdelay( 1 )\n#define THREAD_WAIT( sync, status )\t\\\n\t\t\t\t\t\t\t\tif( cjsmwait( sync, threadPriority(), 0 ) != CJ_EROK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tcjsmdelete( sync )\n#define THREAD_CLOSE( sync )\n\n/* Because of the problems with resource management of AMX tasks and\n   related metadata, we no-op them out unless we're using wrappers by\n   ensuring that any attempt to spawn a thread inside cryptlib fails,\n   falling back to the non-threaded alternative.  Note that cryptlib itself\n   is still thread-safe, it just can't do its init in an internal background \n   thread */\n\n#ifndef AMX_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !AMX_THREAD_WRAPPERS */\n\n/* The AMX task-priority function returns the priority via a reference\n   parameter.  Because of this we have to provide a wrapper that returns\n   it as a return value */\n\nint threadPriority( void );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tARINC 653\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ARINC653__ )\n\n#include <apex.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tPROCESS_ID_TYPE\n#define MUTEX_HANDLE\t\t\tSEMAPHORE_ID_TYPE\n\n/* The ARINC 653 API returns status codes as a by-reference parameter, in \n   cases where we don't care about the return status we need to provide a\n   dummy value to take this */\n\nextern RETURN_CODE_TYPE dummyRetCode;\n\n/* Mutex management functions.  ARINC 653 mutexes are re-entrant so we don't \n   have to jump through the hoops that are necessary with most other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tRETURN_CODE_TYPE retCode; \\\n\t\t\t\\\n\t\t\tCREATE_SEMAPHORE( NULL, 0, 1, FIFO, &krnlData->name##Mutex, &retCode ); \\\n\t\t\tif( retCode == NO_ERROR ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tWAIT_SEMAPHORE( krnlData->name##Mutex, INFINITE_TIME_VALUE, &dummyRetCode ); \\\n\t\t\tSIGNAL_SEMAPHORE( krnlData->name##Mutex, &dummyRetCode ); \\\n\t\t\t/* ARINC 653 provides no way to delete a semaphore */ \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tWAIT_SEMAPHORE( krnlData->name##Mutex, INFINITE_TIME_VALUE, &dummyRetCode )\n#define MUTEX_UNLOCK( name ) \\\n\t\tSIGNAL_SEMAPHORE( krnlData->name##Mutex, &dummyRetCode )\n\n/* Thread management functions.  CREATE_PROCESS() creates the task in the \n   suspended (or at least DORMANT) state so we have to RESUME() it after\n   creation.  The process attributes are underdocumented and system-\n   dependent, and will need to be set on a case-by-case basis.  ARINC 653 \n   doesn't provide any way to end a process so the best that we can do is a \n   STOP_SELF().  A TIMED_WAIT() of 0 yields the CPU, otherwise it's the \n   sleep time in nanoseconds */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void const *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tPROCESS_ATTRIBUTE_TYPE attributes = \\\n\t\t\t\t{ \"\", ( SYSTEM_ADDRESS_TYPE ) function, 0, \\\n\t\t\t\t  MAX_PRIORITY_VALUE / 2, 0, 0, SOFT }; \\\n\t\t\tRETURN_CODE_TYPE retCode; \\\n\t\t\t\\\n\t\t\tCREATE_SEMAPHORE( NULL, 0, 1, FIFO, &syncHandle, &retCode ); \\\n\t\t\tCREATE_PROCESS( &attributes, &threadHandle, &retCode ); \\\n\t\t\tif( retCode != NO_ERROR ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tRESUME( threadHandle, &retCode ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tSTOP_SELF(); \\\n\t\t\t\t\t\t\t\tSIGNAL_SEMAPHORE( sync, &dummyRetCode ); \\\n\t\t\t\t\t\t\t\treturn\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#define THREAD_SLEEP( ms )\t\tTIMED_WAIT( ( ms ) * 1000000, &dummyRetCode )\n#define THREAD_YIELD()\t\t\tTIMED_WAIT( 0, &dummyRetCode )\n#define THREAD_WAIT( sync, status )\t\\\n\t\t\t\t\t\t\t\t{ \\\n\t\t\t\t\t\t\t\tRETURN_CODE_TYPE retCode; \\\n\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\tWAIT_SEMAPHORE( sync, INFINITE_TIME_VALUE, &retCode ); \\\n\t\t\t\t\t\t\t\tif( retCode != NO_ERROR ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\t/* ARINC 653 provides no way to delete a semaphore */ \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_CLOSE( sync )\n\n/* The ARINC 653 thread-self function returns the thread ID via a reference \n   parameter, because of this we have to provide a wrapper that returns it \n   as a return value */\n\nPROCESS_ID_TYPE threadSelf( void );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tBeOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __BEOS__ )\n\n#include <kernel/OS.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tthread_id\n#define MUTEX_HANDLE\t\t\tthread_id\n\n/* Mutex management functions */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tsem_id name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tthread_id name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( ( krnlData->name##Mutex = create_sem( 1, NULL ) ) < B_NO_ERROR ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tacquire_sem( krnlData->name##Mutex ); \\\n\t\t\trelease_sem( krnlData->name##Mutex ); \\\n\t\t\tdelete_sem( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( acquire_sem_etc( krnlData->name##Mutex, 1, \\\n\t\t\t\t\t\t\t B_RELATIVE_TIMEOUT, 0 ) == B_WOULD_BLOCK ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tacquire_sem( krnlData->name##Mutex ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\trelease_sem( krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  BeOS threads are created in the suspended\n   state, so after we create the thread we have to resume it to start it\n   running */\n\n#define THREADFUNC_DEFINE( name, arg )\tthread_id name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tthreadHandle = syncHandle = \\\n\t\t\t\tspawn_thread( ( function ), NULL, B_NORMAL_PRIORITY, \\\n\t\t\t\t\t\t\t  ( arg ) ); \\\n\t\t\tif( threadHandle < B_NO_ERROR ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\tresume_thread( threadHandle ); \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\texit_thread( 0 )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tfind_thread( NULL )\n#define THREAD_SLEEP( ms )\t\tsnooze( ms )\n#define THREAD_YIELD()\t\t\tsnooze( estimate_max_scheduling_latency( -1 ) + 1 )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\t{ \\\n\t\t\t\t\t\t\t\tstatus_t dummy; \\\n\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\tif( wait_for_thread( sync, &dummy ) != B_NO_ERROR ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tChorusOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __CHORUS__ )\n\n/* To use resource-management wrappers for the AMX thread functions,\n   undefine the following */\n\n/* #define AMX_THREAD_WRAPPERS */\n\n#include <chorus.h>\n#include <exec/chExec.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tKnThreadLid\n#define MUTEX_HANDLE\t\t\tKnMutex\n\n/* Mutex management functions.  ChorusOS provides no way to destroy a\n   mutex once it's initialised, presumably it gets cleaned up when the\n   owning actor terminates */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tKnThreadLid name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( mutexInit( &krnlData->name##Mutex ) == K_OK ) \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tmutexGet( &krnlData->name##Mutex ); \\\n\t\t\tmutexRel( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( mutexTry( &krnlData->name##Mutex ) == 0 ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tmutexGet( &krnlData->name##Mutex ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\tmutexRel( &krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  ChorusOS threads require that the user\n   allocate the stack space for them, unlike virtually every other embedded\n   OS, which make this at most a rarely-used option.  To handle this, we use\n   our own wrappers which hide this mess.  A second problem with ChorusOS\n   threads is that there's no easy way to pass an argument to a thread, so\n   we have to include it as a \"software register\" value that the thread then\n   obtains via threadLoadR().\n\n   ChorusOS provides no way to destroy a semaphore once it's initialised,\n   presumably it gets cleaned up when the owning actor terminates */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\tKnDefaultStartInfo startInfo = { \\\n\t\t\t\tK_START_INFO | K_START_INFO_SOFTREG, K_DEFAULT_STACK_SIZE, \\\n\t\t\t\tfunction, threadStack, K_USERTHREAD, arg }; \\\n\t\t\t\\\n\t\t\tsemInit( &syncHandle, 1 ); \\\n\t\t\tif( threadCreate( K_MYACTOR, &threadHandle, K_ACTIVE, NULL, \\\n\t\t\t\t\t\t\t  &startInfo ) != K_OK ) \\\n\t\t\t\t{ \\\n\t\t\t\tfree( threadStack ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tsemV( sync ); \\\n\t\t\t\t\t\t\t\tthreadDelete( K_MYACTOR, K_MYSELF )\n#define THREAD_INITIALISER\t\tNULL\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#define THREAD_SLEEP( ms )\t\t{ \\\n\t\t\t\t\t\t\t\tKnTimeVal timeVal; \\\n\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\tK_MILLI_TO_TIMEVAL( &timeVal, ms ); \\\n\t\t\t\t\t\t\t\tthreadDelay( &timeVal ); \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_YIELD()\t\t\tthreadDelay( K_NOBLOCK )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( semP( sync, K_NOTIMEOUT ) < 0 ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_CLOSE( sync )\n\n/* Because of the problems with resource management of Chorus thread stack\n   space, we no-op out threads unless we're using wrappers by ensuring that\n   any attempt to spawn a thread inside cryptlib fails, falling back to the\n   non-threaded alternative.  Note that cryptlib itself is still thread-\n   safe, it just can't do its init in an internal background thread */\n\n#ifndef CHORUS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !CHORUS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tCMSIS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __CMSIS__ )\n\n#include <cmsis_os.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tosThreadId\n#define MUTEX_HANDLE\t\t\tosMutexId\n\n/* Mutex management functions.  CMSIS mutexes are re-entrant so we don't \n   have to jump through the hoops that are necessary with most other OSes */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tosMutexDef( name ); \\\n\t\t\t\\\n\t\t\tkrnlData->name##Mutex = osMutexCreate( osMutex( name ) ); \\\n\t\t\tif( krnlData->name##Mutex != NULL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tosMutexWait( krnlData->name##Mutex, osWaitForever ); \\\n\t\t\tosMutexRelease( krnlData->name##Mutex ); \\\n\t\t\tosMutexDelete( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tosMutexWait( krnlData->name##Mutex, osWaitForever )\n#define MUTEX_UNLOCK( name ) \\\n\t\tosMutexRelease( krnlData->name##Mutex )\n\n/* Thread management functions */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void const *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tosMutexDef( mutexDef ); \\\n\t\t\tosThreadDef( function, osPriorityNormal, 1, 0 ); \\\n\t\t\t\\\n\t\t\tsyncHandle = osMutexCreate( osMutex( mutexDef ) ); \\\n\t\t\tthreadHandle = osThreadCreate( osThread( function ), NULL ); \\\n\t\t\tif( threadHandle == NULL ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tosMutexWait( syncHandle, osWaitForever ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tosThreadTerminate( osThreadGetId() ); \\\n\t\t\t\t\t\t\t\tosMutexRelease( sync ); \\\n\t\t\t\t\t\t\t\treturn\n#define THREAD_INITIALISER\t\tNULL\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tosThreadGetId()\n#define THREAD_SLEEP( ms )\t\tosDelay( ms )\n#define THREAD_YIELD()\t\t\tosThreadYield()\n#define THREAD_WAIT( sync, status )\t\\\n\t\t\t\t\t\t\t\tif( osMutexWait( sync, osWaitForever ) != osOK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tosMutexDelete( sync )\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\teCOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ECOS__ )\n\n/* To use resource-management wrappers for the eCOS thread functions,\n   undefine the following */\n\n/* #define ECOS_THREAD_WRAPPERS */\n\n#include <cyg/hal/hal_arch.h>\n#include <cyg/kernel/kapi.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tcyg_handle_t\n#define MUTEX_HANDLE\t\t\tcyg_sem_t\n\n/* Indicate that eCOS has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tcyg_mutex_t name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tcyg_handle_t name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK;\t/* Apparently never fails */ \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tcyg_mutex_init( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tcyg_mutex_lock( &krnlData->name##Mutex ); \\\n\t\t\tcyg_mutex_unlock( &krnlData->name##Mutex ); \\\n\t\t\tcyg_mutex_destroy( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( !cyg_mutex_trylock( &krnlData->name##Mutex ) ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tcyg_mutex_lock( &krnlData->name##Mutex ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\tcyg_mutex_unlock( &krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  eCOS threads require that the user allocate\n   the stack space for them, unlike virtually every other embedded OS, which\n   make this at most a rarely-used option.  To handle this, we use our own\n   wrappers, which hide this mess and provide access via a single scalar\n   variable.  For synchronisation we use semaphores, eCOS also provides\n   condition variables for this purpose but they require a user-managed\n   mutex to synchronise access to them, making them (at best) a primitive\n   DIY semaphore.\n\n   We create the thread with the same priority as the calling thread, note\n   that this precludes the use of the bitmap scheduler (but not the lottery\n   scheduler).  There doesn't seem to be any way to tell whether a thread\n   has been successfully created/started or not (!!), the best that we can\n   do is assume that if the thread handle is zero or negative then there's\n   been a problem.  eCOS threads are created in the suspended state, so\n   after we create the thread we have to resume it to start it running.\n\n   The CYGNUM_HAL_STACK_SIZE_TYPICAL provides enough stack space for about\n   half a dozen levels of function nesting (if no large on-stack arrays are\n   used), this should be enough for background init but probably won't be\n   sufficient for the infinitely-recursive OpenSSL bignum code, so the value\n   may need to be adjusted if background keygen is being used.\n\n   Thread sleep times are measured in implementation-specific ticks rather\n   than ms, but the default is 100Hz so we divide by 10 to convert ms to\n   ticks */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( cyg_addrword_t arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadData = clAlloc( sizeof( cyg_thread ) + \\\n\t\t\t\t\t\t\t\t\t    CYGNUM_HAL_STACK_SIZE_TYPICAL ); \\\n\t\t\t\\\n\t\t\tcyg_semaphore_init( &syncHandle, 0 ); \\\n\t\t\tcyg_thread_create( cyg_thread_get_priority( cyg_thread_self() ), \\\n\t\t\t\t\t\t\t   function, ( cyg_addrword_t ) arg, NULL, \\\n\t\t\t\t\t\t\t   threadData + sizeof( cyg_thread ), \\\n\t\t\t\t\t\t\t   CYGNUM_HAL_STACK_SIZE_TYPICAL, \\\n\t\t\t\t\t\t\t   &threadHandle, ( cyg_thread * ) threadData ); \\\n\t\t\tif( threadHandle <= 0 ) \\\n\t\t\t\t{ \\\n\t\t\t\tfree( threadData ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tcyg_thread_resume( threadHandle ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tcyg_semaphore_post( &sync ); \\\n\t\t\t\t\t\t\t\tcyg_thread_exit()\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tcyg_thread_self()\n#define THREAD_SLEEP( ms )\t\tcyg_thread_delay( ( ms ) / 10 )\n#define THREAD_YIELD()\t\t\tcyg_thread_yield()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( !cyg_semaphore_wait( &sync ) ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tcyg_semaphore_destroy( &sync )\n#define THREAD_CLOSE( sync )\tcyg_thread_delete( &sync )\n\n/* Because of the problems with resource management of eCOS threads and\n   related metadata, we no-op them out unless we're using wrappers by\n   ensuring that any attempt to spawn a thread inside cryptlib fails,\n   falling back to the non-threaded alternative.  Note that cryptlib itself\n   is still thread-safe, it just can't do its init in an internal background \n   thread */\n\n#ifndef ECOS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !ECOS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tembOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __embOS__ )\n\n/* To use resource-management wrappers for the embOS thread functions,\n   undefine the following */\n\n/* #define EMBOS_THREAD_WRAPPERS */\n\n#include <RTOS.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tOS_TASK *\n#define MUTEX_HANDLE\t\t\tOS_RSEMA\n\n/* Indicate that embOS has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions.  embOS mutexes are reentrant so we don't have \n   to hand-assemble reentrant mutexes as for many other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK;\t/* Apparently never fails */ \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tOS_CREATERSEMA( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tOS_Use( &krnlData->name##Mutex ); \\\n\t\t\tOS_Unuse( &krnlData->name##Mutex ); \\\n\t\t\tOS_DeleteRSema( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tOS_Use( &krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\tOS_Unuse( &krnlData->name##Mutex )\n\n/* Thread management functions.  embOS threads require that the user allocate\n   the stack space for them, unlike virtually every other embedded OS, which\n   make this at most a rarely-used option.  To handle this, we use our own\n   wrappers, which hide this mess and provide access via a single scalar\n   variable.\n\n   We create the thread with the same priority as the calling thread.  There \n   doesn't seem to be any way to tell whether a thread has been successfully \n   created/started or not (!!), nor is there any way of indicating how large\n   the stack is.\n   \n   The implementation of THREAD_SAME() is somewhat ugly in that since thread\n   data storage is handled by the caller rather than being allocated by the\n   OS we end up with a mixture of 'struct' (if we're referring to a block of\n   storage for the thread data) and 'struct *' (if we're referring to a thread\n   handle returned from a function like OS_GetTaskID()).  THREAD_SAME() takes\n   advantage of the fact that when it's used, the first argument is always a\n   'struct' and the second is always a 'struct *', which is rather ugly but the\n   only other way to do it would be to wrap the thread functions with our own\n   code that dynamically allocates thread data so that all handles are \n   'struct *'s */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\t\\\n\t\t\tif( threadStack == NULL ) \\\n\t\t\t\tstatus = CRYPT_ERROR_MEMORY; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tOS_CREATERSEMA( &syncHandle ); \\\n\t\t\t\tOS_CREATETASK_EX( threadHandle, NULL, function, \\\n\t\t\t\t\t\t\t\t  OS_GetPriority( NULL ), threadStack, arg ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tOS_Unuse( ( OS_RSEMA * ) &sync ); \\\n\t\t\t\t\t\t\t\tOS_Terminate( OS_GetTaskID() )\n#define THREAD_INITIALISER\t\t{ 0 }\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tOS_GetTaskID()\n#define THREAD_SLEEP( ms )\t\tOS_Delay( ms )\n#define THREAD_YIELD()\t\t\tOS_Yield()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tOS_Use( &sync ); \\\n\t\t\t\t\t\t\t\tOS_DeleteRSema( &sync ); \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_OK\n#define THREAD_CLOSE( sync )\n\n/* Because of the problems with resource management of embOS threads and\n   related metadata, we no-op them out unless we're using wrappers by\n   ensuring that any attempt to spawn a thread inside cryptlib fails,\n   falling back to the non-threaded alternative.  Note that cryptlib itself\n   is still thread-safe, it just can't do its init in an internal background \n   thread */\n\n#ifndef EMBOS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !EMBOS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFreeRTOS/OpenRTOS\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __FreeRTOS__ )\n\n#include <FreeRTOS.h>\n#include <task.h>\n#include <semphr.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\txTaskHandle \n#define MUTEX_HANDLE\t\t\txSemaphoreHandle \n\n/* Mutex management functions.  Mutexes aren't recursive but binary \n   semaphores are so we use those instead of mutexes.  In addition most of \n   the functions are implemented via macros rather than functions so we use \n   the handles directly instead of passing a reference.  Finally, there's no \n   way to destroy/clean up a mutex after it's been created because the kernel\n   and code are linked into a single monolithic blob that's running the \n   entire time, so we don't perform any explicit cleanup */\n\n#define MUTEX_WAIT_TIME\t\t( 5000 / portTICK_RATE_MS )\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tvSemaphoreCreateBinary( krnlData->name##Mutex ); \\\n\t\t\tif( krnlData->name##Mutex == NULL ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\txSemaphoreTakeRecursive( krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t\t MUTEX_WAIT_TIME ); \\\n\t\t\txSemaphoreGiveRecursive( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\txSemaphoreTakeRecursive( krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t MUTEX_WAIT_TIME )\n#define MUTEX_UNLOCK( name ) \\\n\t\txSemaphoreGiveRecursive( krnlData->name##Mutex )\n\n/* Thread management functions.  FreeRTOS threads are generally sensible and\n   don't require user management of stack space as with many other \n   minimalist embedded OSes, although they do have the peculiarity that the \n   stack size is given as a \"depth\" rather than an actual stack size, where \n   the total size is defined by \"depth\" x \"width\" (= machine word size) */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tportBASE_TYPE result; \\\n\t\t\t\\\n\t\t\tsyncHandle = xSemaphoreCreateMutex(); \\\n\t\t\txSemaphoreTake( syncHandle, MUTEX_WAIT_TIME ); \\\n\t\t\tresult = xTaskCreate( function, \"clibTask\", EMBEDDED_STACK_SIZE, \\\n\t\t\t\t\t\t\t\t  arg, tskIDLE_PRIORITY, &threadHandle ); \\\n\t\t\tif( result != pdPASS ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\txSemaphoreGive( ( xSemaphoreHandle  * ) &sync )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\txTaskGetCurrentTaskHandle()\n#define THREAD_SLEEP( ms )\t\tvTaskDelay( ( ms ) / portTICK_RATE_MS )\n#define THREAD_YIELD()\t\t\ttaskYIELD()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( xSemaphoreTake( sync, MUTEX_WAIT_TIME ) != pdTRUE ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_CLOSE( sync )\tvTaskDelete( &sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tIBM 4758\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __IBM4758__ )\n\n#include <cpqlib.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tlong\n#define MUTEX_HANDLE\t\t\tlong\n\n/* Mutex management functions */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Semaphore\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Semaphore; \\\n\t\tBOOLEAN name##SemaphoreInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##SemaphoreInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( CPCreateSerSem( NULL, 0, 0, \\\n\t\t\t\t\t\t\t\t&krnlData->name##Semaphore ) == 0 ) \\\n\t\t\t\tkrnlData->name##SemaphoreInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##SemaphoreInitialised ) \\\n\t\t\t{ \\\n\t\t\tCPSemClaim( krnlData->name##Semaphore, SVCWAITFOREVER ); \\\n\t\t\tCPSemRelease( krnlData->name##Semaphore ); \\\n\t\t\tCPDelete( krnlData->name##Semaphore, 0 ); \\\n\t\t\tkrnlData->name##SemaphoreInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tCPSemClaim( krnlData->name##Semaphore, SVCWAITFOREVER )\n#define MUTEX_UNLOCK( name ) \\\n\t\tCPSemRelease( krnlData->name##Semaphore )\n\n/* Thread management functions.  CP/Q doesn't use threads but only supports\n   CP/Q tasks.  These function in a somewhat peculiar manner, so this\n   facility isn't currently used */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tuITRON\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ITRON__ )\n\n/* In the following includes, kernel.h is the uITRON kernel.h, not the\n   cryptlib one */\n\n#include <itron.h>\n#include <kernel.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tID\n#define MUTEX_HANDLE\t\t\tID\n\n/* Mutex management functions.  We could use either semaphores or mutexes\n   for this, semaphores are supported under uITRON 3.0 but since we're\n   using automatic assignment of handles (which requires uITRON 4.0) we may\n   as well use mutexes */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tID name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tstatic const T_CMTX pk_cmtx = { TA_TFIFO, 0, 0 }; \\\n\t\t\t\\\n\t\t\tif( ( krnlData->name##Mutex = \\\n\t\t\t\t\t\tacre_mtx( ( T_CMTX  * ) &pk_cmtx ) ) < E_OK ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tloc_mtx( krnlData->name##Mutex ); \\\n\t\t\tunl_mtx( krnlData->name##Mutex ); \\\n\t\t\tdel_mtx( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( ploc_mtx( krnlData->name##Mutex ) == E_ILUSE ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tloc_mtx( krnlData->name##Mutex ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = threadSelf();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\tunl_mtx( krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  The attributes for task creation are:\n\n\tTA_HLNG | TA_ACT\t-- C interface, create task in the active rather\n\t\t\t\t\t\t   than suspended state (otherwise we'd have to use\n\t\t\t\t\t\t   act_tsk() to activate it a la BeOS).\n\targ\t\t\t\t\t-- Task extended info.\n\tfunction\t\t\t-- Task function.\n\tTPRI_SELF\t\t\t-- Same priority as invoking task.\n\tEMBEDDED_STACK_SIZE\t-- Stack size.\n\tNULL\t\t\t\t-- Auto-allocate stack.  This is given as 0 rather\n\t\t\t\t\t\t   than NULL since some uITRON headers define their\n\t\t\t\t\t\t   own NULL as 0, leading to compiler warnings.\n\n   uITRON status values are 8:8 bit pairs with the actual status in the\n   low 8 bits.  The sub-values can be extracted with the MERCD() and SERCD()\n   (main- and sub-error-code) macros, however simply using the MERCD()\n   result isn't safe because it could be the (negative) low 8 bits of a\n   (positive overall) return value.  When creating a task we therefore\n   consider a status < E_OK as being an error, without trying to pick apart\n   the overall value.\n\n   The handling of initialisers is a bit dodgy since TSK_NONE == TSK_SELF\n   (== 0) and it isn't even safe to use negative values since in some cases\n   these can be valid system task handles.  In general however uITRON\n   numbers IDs from 1...n, so using 0 as a non-value is safe.\n\n   Handling of task sleep is also somewhat dodgy, time is measured in clock\n   ticks of an implementation-specific duration, the best that we can do is\n   to assume that it's close enough to ms.\n\n   In theory we don't really need to use exd_tsk() since returning from a\n   task ends it, but we make it explicit to be neat */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( VP_INT *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tstatic const T_CSEM pk_csem = { TA_TFIFO, 1, 64 }; \\\n\t\t\tT_CTSK pk_ctsk = { TA_HLNG | TA_ACT, ( arg ), ( function ), \\\n\t\t\t\t\t\t\t   TPRI_SELF, EMBEDDED_STACK_SIZE, 0 }; \\\n\t\t\t\\\n\t\t\tsyncHandle = acre_sem( ( T_CSEM  * ) &pk_csem ); \\\n\t\t\tthreadHandle = acre_tsk( &pk_ctsk ); \\\n\t\t\tif( threadHandle < E_OK ) \\\n\t\t\t\t{ \\\n\t\t\t\tdel_sem( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tsig_sem( sync ); \\\n\t\t\t\t\t\t\t\texd_tsk()\n#define THREAD_INITIALISER\t\tTSK_NONE\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#define THREAD_SLEEP( ms )\t\tdly_tsk( ms )\n#define THREAD_YIELD()\t\t\tdly_tsk( 0 )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( wai_sem( sync ) != E_OK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tdel_sem( sync )\n#define THREAD_CLOSE( sync )\n\n/* The uITRON thread-self function returns the thread ID via a reference\n   parameter since uITRON IDs can be negative and there'd be no way to\n   differentiate a thread ID from an error code.  Because of this we have\n   to provide a wrapper that returns it as a return value */\n\nID threadSelf( void );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMongoose OS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MGOS__ )\n\n#include <mgos.h>\n\n/* Object handles.  Mongoose OS is built around an event loop (so \n   cooperative rather than preemptive multitasking), so there's no concept\n   of tasks or threads (which makes you wonder why there are mutexes...).\n   To deal with this we define a dummy type as the thread ID */\n\n#define THREAD_HANDLE\t\t\tint\n#define MUTEX_HANDLE\t\t\tstruct mgos_rlock_type *\n\n/* Indicate that MQX has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions.  Mongoose OS mutexes are reentrant, but also\n   dyamically allocated, so we have to handle them somewhat differently from\n   the usual user-allocates-storage mutexes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( ( krnlData->name##Mutex = mgos_rlock_create() ) != NULL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tmgos_rlock( krnlData->name##Mutex ); \\\n\t\t\tmgos_runlock( krnlData->name##Mutex ); \\\n\t\t\tmgos_rlock_destroy( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tmgos_rlock( krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\tmgos_runlock( krnlData->name##Mutex )\n\n/* Thread management functions.  See the comment at the start of this \n   section for the problems with this, which is why we no-op them out \n   later, leaving the following only as templates if threads/tasks get\n   added at some point */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( uint32_t /* = void* */ arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\t\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\t0\n#define THREAD_SLEEP( ms )\t\tmgos_msleep( ms )\n#define THREAD_YIELD()\t\t\t\n#define THREAD_WAIT( sync, status )\n#define THREAD_CLOSE( sync )\n\n#ifndef MGOS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !MGOS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tMQX\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MQXRTOS__ )\n\n#include <mqx.h>\n#include <mutex.h>\n\n/* MQX really likes redefining standard types, leading to the moronic \n   warning in mqx.h that \"redefining NULL may sometimes conflict [with\n   existing types] as most standard library files do not check for previous \n   definitions\".  By including C-level casts that can't be evaluated at the \n   preprocessor level we can't even check whether the redefinition of the \n   standard type has been done, and that aside from the fact that a non-\n   typed quantity now has a type that's vulnerable to type-conversion issues\n   (testiculos sobre un fuego grande...).\n\n   Because of this we have to assume that values that we use have been\n   redefined in strange ways, and define them back to what they should be */\n\n#undef TRUE\n#define TRUE\t0x0F3C569F\n#undef FALSE\n#define FALSE\t0\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\t_task_id\n#define MUTEX_HANDLE\t\t\tMUTEX_STRUCT\n\n/* Indicate that MQX has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions.  It's unclear whether MQX mutexes are \n   reentrant or not, if they aren't then the following macros would need\n   to be changed to hand-assemble reentrant mutexes as is done for many \n   other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( _mutex_init( &krnlData->name##Mutex, NULL ) == MQX_OK ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\t_mutex_lock( &krnlData->name##Mutex ); \\\n\t\t\t_mutex_unlock( &krnlData->name##Mutex ); \\\n\t\t\t_mutex_destroy( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\t_mutex_lock( &krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\t_mutex_unlock( &krnlData->name##Mutex )\n\n/* Thread management functions.  MQX's task creation is weird in that it \n   doesn't take task parameters like any other OS but requres an integer \n   that identifies an entry in a list of task templates that was specified at \n   compile time.  This is weird in that we can't simply start an arbitrary \n   task by specifying its function name but have to refer to it indirectly.\n   Fortunately the only time this capability is used is when we're performing\n   an async init, if it were used in other locations then it'd be necessary\n   to have THREAD_CREATE compare the 'function' value passed to it with a\n   built-in list and map that to an integer ID for _task_create(), which then \n   maps it back to a function name.\n\n   To deal with this strangeness you need to define an entry in your app's\n   TASK_TEMPLATE_STRUCT list something like the following:\n\n\t{ 0x100, threadedBind, EMBEDDED_STACK_SIZE, 15, NULL, 0, 0, 0 }\n\n   which creates a non-auto-start task with FIFO scheduling and a default \n   timeslice.  Unfortunately because of this bizarre way of specifying things\n   we can't set the priority in any sane way, normally we'd use  \n   _task_get_priority() with MQX_NULL_TASK_ID to get the current task's \n   priority but this doesn't work because the value has to be allocated at \n   compile time.  We give the task a mid-range priority value of 15 (from a \n   range of 0 = highest ... 31 = lowest), this is somewhat ugly but there\n   doesn't seem to be much else that we can do */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( uint32_t /* = void* */ arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\t_lwsem_create( &syncHandle, 1 ); \\\n\t\t\tthreadHandle = _task_create( 0, 0x100, ( uint32_t ) arg ); \\\n\t\t\tif( threadHandle == MQX_NULL_TASK_ID ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\t_lwsem_post( ( MUTEX_STRUCT * ) &sync ); \\\n\t\t\t\t\t\t\t\t_task_destroy( MQX_NULL_TASK_ID )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\t_task_get_id()\n#define THREAD_SLEEP( ms )\t\t_time_delay( ms )\n#define THREAD_YIELD()\t\t\t_sched_yield()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( _lwsem_wait( sync ) != MQX_OK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\t_lwsem_destroy( sync )\n#define THREAD_CLOSE( sync )\n\n/* Because of the problems with resource management of MQX threads, we no-op \n   them out unless we're using wrappers by ensuring that any attempt to \n   spawn a thread inside cryptlib fails, falling back to the non-threaded \n   alternative.  Note that cryptlib itself is still thread-safe, it just \n   can't do its init in an internal background thread */\n\n#ifndef MQX_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !MQX_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tNucleus\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Nucleus__ )\n\n#include <nucleus.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tNU_TASK *\n#define MUTEX_HANDLE\t\t\tNU_SEMAPHORE *\n\n/* Indicate that Nucleus has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions.  Nucleus doesn't have a mutex_trylock()-\n   equivalent so we have to perform the check by comparing the mutex\n   owner to the current task, which in turns means we have to explicitly\n   manage the mutex owner value at a level beyond what's necessary with\n   other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tNU_SEMAPHORE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tNU_TASK *name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( NU_Create_Semaphore( &krnlData->name##Mutex, \"CLIBSEMA\", 1, \\\n\t\t\t\t\t\t\t\t\t NU_PRIORITY ) == NU_SUCCESS ) \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexOwner = NULL; \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tNU_Delete_Semaphore( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( krnlData->name##MutexOwner == NU_Current_Task_Pointer() ) \\\n\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tNU_Obtain_Semaphore( &krnlData->name##Mutex, NU_SUSPEND ); \\\n\t\t\tkrnlData->name##MutexOwner = NU_Current_Task_Pointer(); \\\n\t\t\t}\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = NULL; \\\n\t\t\tNU_Release_Semaphore( &krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  The attributes for task creation are:\n\n\t\"CLIBTASK\"\t\t\t-- Task label.\n\tfunction\t\t\t-- Task function.\n\targc, argv\t\t\t-- Task arguments\n\tstackSpace\t\t\t-- Stack storage.\n\tEMBEDDED_STACK_SIZE\t-- Stack size.\n\t200\t\t\t\t\t-- Task priority 0...255.\n\t15\t\t\t\t\t-- Maximum task timeslice in ticks.\n\tNU_PREEMPT\t\t\t-- Task is preemptible.\n\tNU_START\t\t\t-- Auto-start the task.\n\n   Thread sleep times are measured in implementation-specific ticks rather\n   than ms, but the default is 100Hz so we divide by 10 to convert ms to\n   ticks */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( UNSIGNED argc, VOID *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *stackSpace = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\tSTATUS nu_status; \\\n\t\t\t\\\n\t\t\tnu_status = NU_Create_Task( &threadHandle, \"CLIBTASK\", function, \\\n\t\t\t\t\t\t\t\t\t\t1, arg, stackSpace, EMBEDDED_STACK_SIZE, \\\n\t\t\t\t\t\t\t\t\t\t200, 15, NU_PREEMPT, NU_START ); \\\n\t\t\tif( status != NU_SUCCESS ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tNU_Release_Semaphore( &sync ); \\\n\t\t\t\t\t\t\t\tNU_Terminate_Task( NU_Current_Task_Pointer() )\n#define THREAD_INITIALISER\t\t{ 0 }\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tNU_Current_Task_Pointer()\n#define THREAD_SLEEP( ms )\t\tNU_Sleep( ms / 10 )\n#define THREAD_YIELD()\t\t\tNU_Relinquish()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( NU_Obtain_Semaphore( sync, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t NU_SUSPEND ) != NU_SUCCESS ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tNU_Delete_Semaphore( sync )\n#define THREAD_CLOSE( sync )\tNU_Delete_Task( sync )\n\n/* Because of the problems with resource management of Nucleus threads, we \n   no-op them out unless we're using wrappers by ensuring that any attempt \n   to spawn a thread inside cryptlib fails, falling back to the non-\n   threaded alternative.  Note that cryptlib itself is still thread-safe, it \n   just can't do its init in an internal background thread */\n\n#ifndef NUCLEUS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !NUCLEUS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tOS/2\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __OS2__ )\n\n#define INCL_DOSSEMAPHORES\n#define INCL_DOSMISC\n#define INCL_DOSFILEMGR\n#define INCL_DOSMISC\n#define INCL_DOSDATETIME\n#define INCL_DOSPROCESS\n#define INCL_WINWINDOWMGR\n#define INCL_WINSYS\n#include <os2.h>\nULONG DosGetThreadID( void );\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tTID\n#define MUTEX_HANDLE\t\t\tHEV\n\n/* Mutex management functions */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tHMTX name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( DosCreateMutexSem( NULL, &krnlData->name##Mutex, 0L, \\\n\t\t\t\t\t\t\t\t   FALSE ) == NO_ERROR ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tDosRequestMutexSem( krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t( ULONG ) SEM_INDEFINITE_WAIT ); \\\n\t\t\tDosReleaseMutexSem( krnlData->name##Mutex ); \\\n\t\t\tDosCloseMutexSem( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tDosRequestMutexSem( krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t( ULONG ) SEM_INDEFINITE_WAIT )\n#define MUTEX_UNLOCK( name ) \\\n\t\tDosReleaseMutexSem( krnlData->name##Mutex )\n\n/* Thread management functions */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid _Optlink name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tthreadHandle = syncHandle = \\\n\t\t\t\t_beginthread( ( function ), NULL, 8192, ( arg ) ); \\\n\t\t\tstatus = ( threadHandle == -1 ) ? CRYPT_ERROR : CRYPT_OK ); \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\t_endthread()\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SELF()\t\t\tDosGetThreadID()\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SLEEP( ms )\t\tDosWait( ms )\n#define THREAD_YIELD()\t\t\tDosWait( 0 )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( DosWaitThread( sync, INFINITE ) != NO_ERROR ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tOSEK/VDX\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __OSEK__ )\n\n#include <os.h>\n\n/* Object handles.  See below for the use of MUTEX_HANDLE, which is just\n   a filler that's used because it's required in kernel data structures */\n\n#define THREAD_HANDLE\t\t\tTaskType \n#define MUTEX_HANDLE\t\t\tint\n\n/* Mutex management functions.  OSEK doesn't really have anything that works\n   as a conventional mutex, only \"resources\" and \"events\".  An event is a \n   bitmask that can be set, cleared, and waited on, but because it's a \n   bitmask there's a fixed maximum number of events that can be defined.  \n   The intent of events seems to be as a task-synchronisation mechanism in\n   which a single control task waits on events from multiple sub-tasks as\n   a form of select():\n\n\tWaitEvent( Event1 | Event2 | Event3 ); \n\tGetEvent( Task1, &WhichEvent ); \n\n   A resource is a crude form of mutex that supports only two operations,\n   GetResource() and ReleaseResource(), with resources initialised to the\n   not-held state.  As with most other things in OSEK, the resource values\n   are assigned at compile time, so there's no concept of a resource handle\n   since it's a static value \n   \n   In order for the statically-defined mutexes to work, the following \n   resource IDs (from kernel/kernel.h) need to be defined:\n\n\tinitialisationMutex, objectTableMutex, semaphoreMutex, \n\tmutex1Mutex, mutex2Mutex, mutex3Mutex, mutex4Mutex, allocationMutex */\n\n#if !defined( initialisationMutex ) || !defined( objectTableMutex ) || \\\n\t!defined( semaphoreMutex ) || !defined( mutex1Mutex ) || \\\n\t!defined( allocationMutex )\n  #error Need to define resource types for cryptlib kernel mutexes\n#endif /* Resource IDs for mutexes */\n#ifdef USE_SESSIONS\n  #if !defined( mutex2Mutex ) || !defined( mutex3Mutex ) || \\\n\t  !defined( mutex4Mutex ) \n\t#error Need to define resource types for cryptlib session mutexes\n  #endif /* Resource IDs for session mutexes */\n#endif /* USE_SESSIONS */\n\n#define MUTEX_LOCKNAME( name )\tname##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tGetResource( name##Mutex ); \\\n\t\t\tReleaseResource( name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tGetResource( name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\tReleaseResource( name##Mutex )\n\n/* Thread management functions.   OSEK has no way to sleep for a certain \n   amount of time short of constructing our own sleep function via alarms,\n   the best that we can do is yield our timeslice */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( uint32_t /* = void* */ arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tif( ActivateTask( threadHandle ) != E_OK ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tReleaseResource( sync ); \\\n\t\t\t\t\t\t\t\tTerminateTask()\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#define THREAD_SLEEP( ms )\t\tSchedule()\n#define THREAD_YIELD()\t\t\tSchedule()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tGetResource( sync ); \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_OK;\n#define THREAD_CLOSE( sync )\n\n/* Because of the problems with resource management of OSEK tasks, we no-op \n   them out unless we're using wrappers by ensuring that any attempt to \n   spawn a thread inside cryptlib fails, falling back to the non-threaded \n   alternative.  Note that cryptlib itself is still thread-safe, it just \n   can't do its init in an internal background thread */\n\n#ifndef OSEK_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !OSEK_THREAD_WRAPPERS */\n\n/* The OSEK thread-self function returns the thread ID via a reference \n   parameter, because of this we have to provide a wrapper that returns it \n   as a return value */\n\nTaskType threadSelf( void );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tPalmOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __PALMOS__ )\n\n#include <CmnErrors.h>\n#include <SysThread.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tSysHandle\n#define MUTEX_HANDLE\t\t\tSysHandle\n\n/* Mutex management functions.  These are just initialised in a slightly\n   odd manner, there isn't any function to explicitly initialise them but\n   instead they're statically initialised to a fixed value (NULL), when\n   the lock/unlock functions are passed this value they perform the\n   initialisation on-demand.  This means that if the underlying hardware\n   supports it they can be implemented using atomic operations directly\n   on the critical-section value without having to allocate memory for\n   a struct to contain the critical-section data */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tSysCriticalSectionType name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##Mutex = sysCriticalSectionInitializer; \\\n\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tSysCriticalSectionEnter( &krnlData->name##Mutex ); \\\n\t\t\tSysCriticalSectionExit( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##Mutex = sysCriticalSectionInitializer; \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tSysCriticalSectionEnter( &krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\tSysCriticalSectionExit( &krnlData->name##Mutex )\n\n/* Thread management functions.  PalmOS threads are created in the suspended\n   state, so after we create the thread we have to explicitly start it to\n   get it running.  The default stack size (via SysThreadCreateEZ()) is a\n   pathetic 4K for standard threads or 8K for UI threads, to avoid this we\n   have to use the full SysThreadCreate() and specify our own stack size */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tSysSemaphoreCreateEZ( 0, ( SysHandle * ) &syncHandle ); \\\n\t\t\tif( SysThreadCreate( sysThreadNoGroup, \"\", \\\n\t\t\t\t\t\t\t\t sysThreadPriorityNormal, 32768, function, \\\n\t\t\t\t\t\t\t\t arg, &threadHandle ) != errNone ) \\\n\t\t\t\t{ \\\n\t\t\t\tSysSemaphoreDestroy( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tSysThreadStart( threadHandle ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tSysSemaphoreSignal( sync ); \\\n\t\t\t\t\t\t\t\tSysThreadExit()\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tSysCurrentThread()\n#define THREAD_SLEEP( ms )\t\tSysThreadDelay( ( ms ) * 1000000L, P_ABSOLUTE_TIMEOUT )\n#define THREAD_YIELD()\t\t\tSysThreadDelay( 0, P_POLL )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( SysSemaphoreWait( sync, P_WAIT_FOREVER, 0 ) != errNone ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tSysSemaphoreDestroy( sync )\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tQuadros/RTXC\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Quadros__ )\n\n/* To use resource-management wrappers for the Quadros thread functions,\n   undefine the following */\n\n/* #define QUADROS_THREAD_WRAPPERS */\n\n#include <rtxcapi.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tTHREAD\n#define MUTEX_HANDLE\t\t\tMUTX\n\n/* Mutex management functions.  Quadros mutexes are reentrant so we don't \n   have to hand-assemble reentrant mutexes as for many other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( KS_OpenMutx( NULL, &krnlData->name##Mutex ) == RC_GOOD ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tKS_TestMutxW( krnlData->name##Mutex ); \\\n\t\t\tKS_ReleaseMutx( krnlData->name##Mutex ); \\\n\t\t\tKS_CloseMutx( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tKS_TestMutxW( krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name ) \\\n\t\tKS_ReleaseMutx( krnlData->name##Mutex )\n\n/* Thread management functions.  Quadros threads require that the user \n   allocate the stack space for them, unlike virtually every other embedded \n   OS, which make this at most a rarely-used option.  To handle this, we use \n   our own wrappers.\n   \n   A bigger problem with Quadros though is that it only supports statically-\n   defined threads, which means that there's no concept of creating, exiting, \n   or deleting a thread.  In addition there's no way to put a thread to \n   sleep.  Because of this we no-op these functions out further down */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void *arg, void *environment )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\t\\\n\t\t\tTS_DefThreadEntry( THREADA, function ); \\\n\t\t\tTS_DefThreadArg (THREADA, arg ); \\\n\t\t\tTS_ScheduleThread( THREADA ); \\\n\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tKS_ReleaseMutx( sync ); \\\n\t\t\t\t\t\t\t\tXXXX_EndThread( TS_GetThreadID() )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tTS_GetThreadID()\n#define THREAD_SLEEP( ms )\t\tXXXX_SleepThread( ( ms ) / 10 )\n#define THREAD_YIELD()\t\t\tTS_UnscheduleThread()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tKS_TestMutxW( sync ); \\\n\t\t\t\t\t\t\t\tKS_CloseMutx( sync )\n#define THREAD_CLOSE( sync )\tXXXX_DeleteThread( &sync )\n\n/* Because of the problems with resource management of Quadros threads and\n   related metadata we no-op them out unless we're using wrappers by \n   ensuring that any attempt to spawn a thread inside cryptlib fails,\n   falling back to the non-threaded alternative.  Note that cryptlib itself\n   is still thread-safe, it just can't do its init in an internal background \n   thread */\n\n#ifndef QUADROS_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !QUADROS_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tRTEMS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __RTEMS__ )\n\n#include <rtems.h>\n\n/* Object handles.  These are actually multi-component object IDs, but they\n   act like standard handles */\n\n#define THREAD_HANDLE\t\t\trtems_id\n#define MUTEX_HANDLE\t\t\trtems_id\n\n/* RTEMS objects have names, which aren't really names but 32-bit integer\n   tags (the term 'name' comes from the fact that they can be initialised\n   to four ASCII chars like original Mac resource IDs).  Since we don't\n   really care about names, we pass in a dummy name value for all of our\n   calls */\n\n#define NO_NAME\t\t\t\t\t0\n\n/* Mutex management functions.  RTEMS semaphores (or at least standard\n   counting semaphores, which is what we're using here) are re-entrant so\n   we don't have to jump through the hoops that are necessary with most\n   other OSes.\n\n   We specify the priority ceiling as zero since it's not used for the\n   semaphore type that we're creating */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( rtems_semaphore_create( NO_NAME, 1, RTEMS_DEFAULT_ATTRIBUTES, 0, \\\n\t\t\t\t\t\t\t\t\t\t&krnlData->name##Mutex ) == RTEMS_SUCCESSFUL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\trtems_semaphore_obtain( krnlData->name##Mutex, RTEMS_WAIT, 0 ); \\\n\t\t\trtems_semaphore_release( krnlData->name##Mutex ); \\\n\t\t\trtems_semaphore_delete( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\trtems_semaphore_obtain( krnlData->name##Mutex, RTEMS_WAIT, 0 );\n#define MUTEX_UNLOCK( name ) \\\n\t\trtems_semaphore_release( krnlData->name##Mutex );\n\n/* Thread management functions.  RTEMS tasks are created in the suspended\n   state, so after we create the task we have to resume it to start it\n   running.  The attributes for task creation are:\n\n\tNO_NAME\t\t\t\t\t-- Task name.\n\tRTEMS_CURRENT_PRIORITY\t-- Task priority.  The documentation is unclear\n\t\t\t\t\t\t\t   as to whether we can specify this directly as\n\t\t\t\t\t\t\t   the priority or have to obtain it via a call,\n\t\t\t\t\t\t\t   we use the call to be safe.\n\tRTEMS_STACK_SIZE\t\t-- Task stack size.  We use the default size for\n\t\t\t\t\t\t\t   RTEMS tasks.\n\tRTEMS_ASR | \\\t\t\t-- Task mode: Enable async signal processing\n\t\tRTEMS_INT_LEVEL(0) | \\ (default), all interrupts enabled (default),\n\t\tRTEMS_PREEMPT | \\\t   preemptive scheduling (default), timeslicing\n\t\tRTEMS_TIMESLICE\t\t   for tasks of the same priority.\n\tRTEMS_DEFAULT_ATTRIBUTES-- Task attributes: Local task, no FP regs.\n\n   Specifying the default values for the task mode is optional, but we do it\n   anyway to make the behaviour explicit.\n\n   We could make the synchronisation semaphore a binary semaphore, but\n   there's no indication that this is any more efficient than a counting\n   semaphore, and it saves having to create a long list of (non-default)\n   attributes to specify this.\n\n   Task sleep times are measured in implementation-specific ticks rather\n   than ms, but the default is 10ms so we divide by 10.  If necessary the\n   absolute value can be calculated from the microseconds_per_tick field in\n   the RTEMS configuration table or from CONFIGURE_MICROSECONDS_PER_TICK in\n   confdefs.h */\n\n#define TASK_MODE\t( RTEMS_ASR | RTEMS_INTERRUPT_LEVEL(0) | \\\n\t\t\t\t\t  RTEMS_PREEMPT | RTEMS_TIMESLICE )\n\n#define THREADFUNC_DEFINE( name, arg )\trtems_task name( rtems_task_argument arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\trtems_status_code rtemsStatus; \\\n\t\t\trtems_task_priority rtemsPriority; \\\n\t\t\t\\\n\t\t\trtems_task_set_priority( RTEMS_SELF, RTEMS_CURRENT_PRIORITY, \\\n\t\t\t\t\t\t\t\t\t &rtemsPriority ); \\\n\t\t\trtems_semaphore_create( NO_NAME, 1, RTEMS_DEFAULT_ATTRIBUTES, 0, \\\n\t\t\t\t\t\t\t\t\t&syncHandle ); \\\n\t\t\trtemsStatus = rtems_task_create( NO_NAME, rtemsPriority, \\\n\t\t\t\t\t\t\t\t\t\t\t RTEMS_STACK_SIZE, TASK_MODE, \\\n\t\t\t\t\t\t\t\t\t\t\t RTEMS_DEFAULT_ATTRIBUTES, \\\n\t\t\t\t\t\t\t\t\t\t\t &threadHandle ); \\\n\t\t\tif( rtemsStatus == RTEMS_SUCCESSFUL ) \\\n\t\t\t\trtemsStatus = rtems_task_start( threadHandle, function, \\\n\t\t\t\t\t\t\t\t\t\t\t\t( rtems_task_argument ) arg ); \\\n\t\t\tif( rtemsStatus == RTEMS_SUCCESSFUL ) \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\trtems_semaphore_delete( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\trtems_semaphore_release( sync ); \\\n\t\t\t\t\t\t\t\trtems_task_delete( RTEMS_SELF );\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#define THREAD_SLEEP( ms )\t\trtems_task_wake_after( ( ms ) / 10 )\n#define THREAD_YIELD()\t\t\trtems_task_wake_after( RTEMS_YIELD_PROCESSOR )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( rtems_semaphore_obtain( sync, RTEMS_WAIT, 0 ) != RTEMS_SUCCESSFUL ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\telse \\\n\t\t\t\t\t\t\t\t\trtems_semaphore_release( sync ); \\\n\t\t\t\t\t\t\t\trtems_semaphore_delete( sync )\n#define THREAD_CLOSE( sync )\n\n/* The RTEMS thread-self function returns the task ID via a reference\n   parameter, because of this we have to provide a wrapper that returns it\n   as a return value */\n\nrtems_id threadSelf( void );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSMX\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __SMX__ )\n\n/* SMX typedefs 'BOOLEAN', which clashes with our own BOOLEAN, so we \n   undefine it around the include of the SMX headers */\n\n#undef BOOLEAN\n#include <smx.h>\n#define BOOLEAN\t\t\tint\n\n/* SMX redefined it's API completely from 3.x to 4.x, changing the somewhat\n   chaotic namespace to a cleaner one with smx_ prefixes for all functions,\n   and so on.  In order to work with the 3.x headers we use macros to map\n   them to the 4.x namespace */\n\n#if SMX_VERSION < 0x0400\n  #define PRI_NORM\t\t\t\tNORM /* \"Women. Can't live with 'em... pass the beer nuts\" */\n  #define SMX_PRI_NOCHG\t\t\tPRI_NOCHG\n  #define smx_ConvSecToTicks\tSMX_SEC_TO_TICKS\n  #define smx_DelayMsec\t\t\tSMX_DELAY_MSEC\n  #define smx_MutexCreate( pi, ceiling, name ) \\\n\t\t\t\t\t\t\t\tcreate_mutex( pi, ceiling )\n  #define smx_MutexDelete\t\tdelete_mutex\n  #define smx_MutexGet\t\t\tget_mutex\n  #define smx_MutexRelease\t\trel_mutex\n  #define smx_TaskBump\t\t\tbump_task\n  #define smx_TaskCreate( code, pri, stack_size, flags, name ) \\\n\t\t\t\t\t\t\t\tcreate_task( code, pri, stack_size )\n  #define smx_TaskDelete\t\tdelete_task\n  #define smx_TaskStartPar\t\tstart_par\n#endif /* SMX old-style namespace */\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tTCB_PTR\n#define MUTEX_HANDLE\t\t\tMUCB_PTR\n\n/* Mutex management functions.  SMX resource semaphores are re-entrant so we\n   don't have to jump through the hoops that are necessary with most other\n   OSes */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( ( krnlData->name##Mutex = \\\n\t\t\t\t\t\tsmx_MutexCreate( 0, 0, NULL ) ) != NULL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tsmx_MutexGet( krnlData->name##Mutex, smx_ConvSecToTicks( 1 ) / 10 ); \\\n\t\t\tsmx_MutexRelease( krnlData->name##Mutex ); \\\n\t\t\tsmx_MutexDelete( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tsmx_MutexGet( krnlData->name##Mutex, smx_ConvSecToTicks( 1 ) / 10 )\n#define MUTEX_UNLOCK( name ) \\\n\t\tsmx_MutexRelease( krnlData->name##Mutex )\n\n/* SMX has an odd way of implementing its thread_self() functionality, it\n   stores the current task's ID (a pointer to the TCB) in the global \n   variable 'ct' (\"current task\"), so to get the current task ID we just\n   read the value of ct.  To make this a bit more obvious we define a macro\n   that makes it look like a standard SMX function */\n\n#define smx_GetCurrentTask()\tct\n\n/* Thread management functions.  We create the thread with the same priority \n   as the calling thread, SMX threads are created in the suspended state so \n   after we create the thread we have to trigger it to start it running.\n   \n   Exiting a task is a bit awkward, we need to call smx_TaskDelete() but\n   because of the odd way that thread_self() works we'd have to pass a\n   reference to the global current-task variable ct, which gets cleared by\n   smx_TaskDelete().  To deal with this we take a copy of ct and pass in\n   a reference to that */\n\ntypedef void ( *SMX_THREAD_FNTR )( uint arg );\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( /*INT_SZ_TYPE = uint*/ void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tsyncHandle = smx_MutexCreate( 0, 0, NULL ); \\\n\t\t\tif( ( threadHandle = smx_TaskCreate( ( CODE_PTR ) function, \\\n\t\t\t\t\t\t\tPRI_NORM, 0, SMX_FL_NONE, NULL ) ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\tsmx_MutexDelete( &( syncHandle ) ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tsmx_MutexGet( syncHandle, smx_ConvSecToTicks( 1 ) / 10 ); \\\n\t\t\t\tsmx_TaskStartPar( threadHandle, ( uint ) arg ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\t{ \\\n\t\t\t\t\t\t\t\tTCB_PTR ctCopy = ct; \\\n\t\t\t\t\t\t\t\tsmx_TaskDelete( &ctCopy ); \\\n\t\t\t\t\t\t\t\treturn; \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_INITIALISER\t\tNULL\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tsmx_GetCurrentTask()\n#define THREAD_SLEEP( ms )\t\tsmx_DelayMsec( ms )\n#define THREAD_YIELD()\t\t\tsmx_TaskBump( smx_GetCurrentTask(), SMX_PRI_NOCHG )\n#define THREAD_WAIT( sync, status )\t\\\n\t\t\t\t\t\t\t\tif( !smx_MutexGet( sync, smx_ConvSecToTicks( 1 ) / 10 ) ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tsmx_MutexDelete( &( sync ) )\n#define THREAD_CLOSE( sync )\tsmx_MutexRelease( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tTelit\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Telit__ )\n\n#include <m2m_type.h>\n#include <m2m_os_api.h>\n#include <m2m_os_lock_api.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tINT32\n#define MUTEX_HANDLE\t\t\tM2M_T_OS_MTX \n\n/* Mutex management functions.  It's unclear whether Telit mutexes are \n   reentrant or not (no mention is made in any documentation) but we assume\n   they are so we don't have to hand-assemble reentrant mutexes as for many \n   other OSes */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##Mutex = m2m_os_mtx_init( INHERITANCE_ENABLED ); \\\n\t\t\tif( krnlData->name##Mutex != NULL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tm2m_os_mtx_lock( krnlData->name##Mutex, NULL ); \\\n\t\t\tm2m_os_mtx_unlock( krnlData->name##Mutex ); \\\n\t\t\tm2m_os_mtx_destroy( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tm2m_os_mtx_lock( krnlData->name##Mutex, NULL )\n#define MUTEX_UNLOCK( name ) \\\n\t\tm2m_os_mtx_unlock( krnlData->name##Mutex )\n\n/* Thread management functions.  Stack space for these is really limited,\n   either M2M_OS_TASK_STACK_S = 2K, M2M_OS_TASK_STACK_M = 4K, \n   M2M_OS_TASK_STACK_L = 8K, or M2M_OS_TASK_STACK_XL = 16K.  None of these\n   are likely to work with anything that requires a fair amount of state\n   like sessions, but the best that we can do is M2M_OS_TASK_STACK_XL.\n\n   We give the thread a mid-range priority value (from a range of 1 = highest \n   ... 31 = lowest, so M2M_OS_TASK_PRIORITY_MIN / 2 is mid-range) */\n\n#define THREADFUNC_DEFINE( name, arg )\tINT32 name( INT32 type, INT32 arg, INT32 arg2 )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\t\\\n\t\t\tsyncHandle = m2m_os_mtx_init( INHERITANCE_ENABLED ); \\\n\t\t\tthreadHandle = m2m_os_create_task( M2M_OS_TASK_STACK_XL, \\\n\t\t\t\t\t\t\t\t\t\t\t   M2M_OS_TASK_PRIORITY_MIN / 2, \\\n\t\t\t\t\t\t\t\t\t\t\t   M2M_OS_TASK_MBOX_L, function ); \\\n\t\t\tif( threadHandle <= 0 ) \\\n\t\t\t\t{ \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tm2m_os_mtx_unlock( sync ); \\\n\t\t\t\t\t\t\t\tm2m_os_destroy_task( m2m_os_get_current_task_id() ); \\\n\t\t\t\t\t\t\t\treturn( 0 );\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tm2m_os_get_current_task_id()\n#define THREAD_SLEEP( ms )\t\tm2m_os_sleep_ms( ms )\n#define THREAD_YIELD()\t\t\tm2m_os_cooperate_task()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( m2m_os_mtx_lock( sync, NULL ) != M2M_API_RESULT_SUCCESS ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\telse \\\n\t\t\t\t\t\t\t\t\tm2m_os_mtx_unlock( sync ); \\\n\t\t\t\t\t\t\t\tm2m_os_mtx_destroy( sync )\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tThreadX\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ThreadX__ )\n\n/* To use resource-management wrappers for the ThreadX thread functions,\n   undefine the following */\n\n/* #define THREADX_THREAD_WRAPPERS */\n\n//#include <tx_api.h>\n#pragma message( \"ThreadX header path faked\" )\n#include <threadx_tx_api.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tTX_THREAD *\n#define MUTEX_HANDLE\t\t\tTX_MUTEX\n\n/* Indicate that ThreadX has non-scalar handles */\n\n#define NONSCALAR_HANDLES\n\n/* Mutex management functions.  ThreadX mutexes are reentrant so we don't \n   have to hand-assemble reentrant mutexes as for many other OSes.  All \n   ThreadX objects have names (presumably for debugging) but what the \n   requirements for these are aren't documented so we just use a dummy name \n   for everything.  Since we don't care whether the threads waiting on the \n   mutex get woken up in priority order, we use TX_NO_INHERIT to ignore \n   priority inheritance */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( tx_mutex_create( &krnlData->name##Mutex, \"name\", \\\n\t\t\t\t\t\t\t\t TX_NO_INHERIT ) == TX_SUCCESS ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\ttx_mutex_get( &krnlData->name##Mutex, TX_WAIT_FOREVER ); \\\n\t\t\ttx_mutex_put( &krnlData->name##Mutex ); \\\n\t\t\ttx_mutex_delete( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\ttx_mutex_get( &krnlData->name##Mutex, TX_WAIT_FOREVER )\n#define MUTEX_UNLOCK( name ) \\\n\t\ttx_mutex_put( &krnlData->name##Mutex )\n\n/* Thread management functions.  ThreadX threads require that the user \n   allocate the stack space for them, unlike virtually every other embedded \n   OS, which make this at most a rarely-used option.  To handle this, we use \n   our own wrappers.\n\n   The thread function's argument is a ULONG, since we use this as a pointer\n   to parameter data we declare it as a 'void *' since that's how it's\n   treated in practice.\n\n   We give the thread a mid-range priority value and preemption threshold of\n   15 (from a range of 0 = highest ... 31 = lowest) and a 50-tick timeslice.\n   The timeslice value is HAL-dependent so it's not really possible to tell \n   how much runtime this will actually give the thread, anyone using cryptlib\n   with ThreadX will need to set an appropriate value for their HAL.  The\n   same goes for the sleep time, the code assumes that 1 tick = 10ms so we\n   divide by 10 to convert ms to ticks */\n\n#define THREADFUNC_DEFINE( name, arg )\tVOID name( void * /*ULONG*/ arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tBYTE *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\t\\\n\t\t\ttx_mutex_create( &syncHandle, \"name\", TX_NO_INHERIT ); \\\n\t\t\tif( tx_thread_create( &threadHandle, \"name\", function, \\\n\t\t\t\t\t\t\t\t  ( ULONG ) arg, threadStack, EMBEDDED_STACK_SIZE, \\\n\t\t\t\t\t\t\t\t  15, 50, 15, TX_AUTO_START ) != TX_SUCCESS ) \\\n\t\t\t\t{ \\\n\t\t\t\tfree( threadStack ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\ttx_mutex_put( &sync ); \\\n\t\t\t\t\t\t\t\ttx_thread_terminate( tx_thread_identify() )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\ttx_thread_identify()\n#define THREAD_SLEEP( ms )\t\ttx_thread_sleep( ( ms ) / 10 )\n#define THREAD_YIELD()\t\t\ttx_thread_relinquish()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( !tx_mutex_get( &sync, TX_WAIT_FOREVER ) ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\ttx_mutex_delete( &sync )\n#define THREAD_CLOSE( sync )\ttx_thread_delete( &sync )\n\n/* Because of the problems with resource management of ThreadX threads and\n   related metadata we no-op them out unless we're using wrappers by \n   ensuring that any attempt to spawn a thread inside cryptlib fails,\n   falling back to the non-threaded alternative.  Note that cryptlib itself\n   is still thread-safe, it just can't do its init in an internal background \n   thread */\n\n#ifndef THREADX_THREAD_WRAPPERS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !THREADX_THREAD_WRAPPERS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tT-Kernel\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __TKernel__ )\n\n#include <tkernel.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tID\n#define MUTEX_HANDLE\t\t\tID\n\n/* Mutex management functions.  We could use either semaphores or mutexes\n   for this, semaphores are supported under uITRON 3.0 but since we're\n   using automatic assignment of handles (which requires uITRON 4.0) we may\n   as well use mutexes */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tID name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tstatic const T_CMTX pk_cmtx = { NULL, TA_TFIFO, 0 }; \\\n\t\t\t\\\n\t\t\tif( ( krnlData->name##Mutex = \\\n\t\t\t\t\t\ttk_cre_mtx( &pk_cmtx ) ) < E_OK ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\ttk_loc_mtx( krnlData->name##Mutex, TMO_FEVR ); \\\n\t\t\ttk_unl_mtx( krnlData->name##Mutex ); \\\n\t\t\ttk_del_mtx( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( tk_loc_mtx( krnlData->name##Mutex, TMO_POL ) == E_TMOUT ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\ttk_loc_mtx( krnlData->name##Mutex, TMO_FEVR ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\ttk_unl_mtx( krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  The attributes for task creation are:\n\n\targ\t\t\t\t\t-- Task argument.\n\tTA_HLNG\t\t\t\t-- C interface.\n\tfunction\t\t\t-- Task function.\n\tTPRI_SELF\t\t\t-- Same priority as invoking task.\n\tEMBEDDED_STACK_SIZE\t-- User stack size.\n\tOther\t\t\t\t-- Various parameters left at their default \n\t\t\t\t\t\t   settings.\n\n   The handling of initialisers is a bit dodgy since TSK_SELF == 0 and it \n   isn't even safe to use negative values since in some cases these can be \n   valid system task handles.  In general however T-Kernel numbers IDs from \n   1...n, so using 0 as a non-value is safe.\n\n   Dealing with the task's priority is a bit complicated since T-Kernel \n   provides no way of determining a task's current priority, for now we\n   use TPRI_INI = the priority of the task when it was started, if this \n   isn't appropriate then it'd be necessary to call td_ref_tsk() and read\n   the tskpri field from the rtsk data, however this may be just as bad \n   because it returns the priority at read time which may differ from the\n   usual priority.\n\n   T-Kernel status values are 8:8 bit pairs with the actual status in the\n   low 8 bits.  The sub-values can be extracted with the MERCD() and SERCD()\n   (main- and sub-error-code) macros, however simply using the MERCD()\n   result isn't safe because it could be the (negative) low 8 bits of a\n   (positive overall) return value.  When creating a task we therefore\n   consider a status < E_OK as being an error, without trying to pick apart\n   the overall value */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( INT stacd, VP arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tstatic const T_CSEM pk_csem = { NULL, TA_TFIFO, 1, 64 }; \\\n\t\t\tT_CTSK pk_ctsk = { ( arg ), TA_HLNG, ( function ), \\\n\t\t\t\t\t\t\t   TPRI_INI, EMBEDDED_STACK_SIZE, 0, 0, 0, 0, 0 }; \\\n\t\t\t\\\n\t\t\tsyncHandle = tk_cre_sem( &pk_csem ); \\\n\t\t\tthreadHandle = tk_cre_tsk( &pk_ctsk ); \\\n\t\t\tif( threadHandle < E_OK ) \\\n\t\t\t\t{ \\\n\t\t\t\ttk_del_sem( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\ttk_sta_tsk( threadHandle, 0 ); \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\ttk_sig_sem( sync, 1 ); \\\n\t\t\t\t\t\t\t\ttk_exd_tsk()\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\ttk_get_tid()\n#define THREAD_SLEEP( ms )\t\ttk_slp_tsk( ms )\n#define THREAD_YIELD()\t\t\ttk_slp_tsk( 0 )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( tk_wai_sem( sync, 1, TMO_FEVR ) != E_OK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\ttk_del_sem( sync )\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tuC/OS-II\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __UCOS__ )\n\n/* uC/OS-II has a pure priority-based scheduler (no round-robin scheduling)\n   and makes a task's priority do double duty as the task ID, which means\n   that it's unlikely it'll ever get round-robin scheduling without a\n   major overhaul of the API.  Because of this, a background task started\n   inside cryptlib for initialisation will either never run or always run \n   depending on the priority it's started with, thus making it equivalent to \n   performing the operation synchronously.  This means that there's no point \n   in using cryptlib-internal tasks, so they're disabled unless the \n   following is commented out.  Note that cryptlib is still thread-(task)-\n   safe, it just won't use internal tasks for asynchronous ops, because \n   uC/OS-II's scheduling will make the synchronous */\n\n/* #define UCOS_USE_TASKS */\n\n/* Most systems handle priority-inversion-avoidance automatically, however\n   for some reason in uC/OS-II this has to be managed manually by the user.\n   This is done by specifying the priority-inherit priority level that a\n   low-priority task is raised to when a high-priority task attempts to\n   acquire a mutex that the low-priority task is currently holding.  This\n   has to be higher than the priority of any of the tasks that will try\n   to acquire the mutex, as well as being different from the task ID/\n   priority of any task (another problem caused by the task ID == priority\n   issue).  The following is a sample value that'll need to be adjusted\n   based on usage by the calling application */\n\n#define UCOS_PIP\t\t10\n\n/* Because of the strict priority scheduling, we have to specify the task\n   priority (which then also becomes the task ID) when we create the task.\n   The following is a sample task ID, which must be less than UCOS_PIP */\n\n#define UCOS_TASKID\t\t20\n\n/* uC/OS-II typedefs 'BOOLEAN', which clashes with our own BOOLEAN, so we\n   undefine it around the include of the uC/OS-II headers */\n\n#undef BOOLEAN\n#include <ucos_ucos_ii.h>\n#define BOOLEAN\t\t\tint\n\n/* uC/OS-II defines 'BYTE' for backwards-compatibility with uC/OS-I but\n   never uses it, so we remove it again to make our definition visible */\n\n#undef BYTE\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tINT8U\n#define MUTEX_HANDLE\t\t\tOS_EVENT *\n\n/* Mutex management functions.  uC/OS-II mutexes aren't re-entrant (although\n   this is never mentioned explicitly in any documentation the description \n   of how mutexes work in App.Note 1002 makes it clear that they're not), we\n   use the standard trylock()-style mechanism to work around this */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tINT8U name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tINT8U err; \\\n\t\t\t\\\n\t\t\tkrnlData->name##Mutex = OSMutexCreate( UCOS_PIP, &err ); \\\n\t\t\tif( err == OS_ERR_NONE ) \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tINT8U err; \\\n\t\t\t\\\n\t\t\tOSMutexPend( krnlData->name##Mutex, 0, &err ); \\\n\t\t\tOSMutexPost( krnlData->name##Mutex ); \\\n\t\t\tOSMutexDel( krnlData->name##Mutex, OS_DEL_ALWAYS, &err ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\t{ \\\n\t\tINT8U err; \\\n\t\t\\\n\t\tif( OSMutexAccept( krnlData->name##Mutex, &err ) == 0 ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tOSMutexPend( krnlData->name##Mutex, 0, &err ); \\\n\t\t\telse \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF(); \\\n\t\t}\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\tOSMutexPost( krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Thread management functions.  Because of the strict priority-based\n   scheduling there's no way to perform a yield, the best that we can do\n   is sleep for 1ms, which is better than performing a busy wait.\n\n   Thread sleep times are measured in implementation-specific ticks rather\n   than ms, so we have to scale the time based on the OS_TICKS_PER_SEC\n   value */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tOS_STK *threadStack = clAlloc( EMBEDDED_STACK_SIZE ); \\\n\t\t\t\\\n\t\t\tsyncHandle = OSSemCreate( 0 ); \\\n\t\t\tif( OSTaskCreate( function, arg, \\\n\t\t\t\t\t\t\t  ( BYTE * ) threadStack + ( EMBEDDED_STACK_SIZE - 1 ), \\\n\t\t\t\t\t\t\t  UCOS_TASKID ) != OS_ERR_NONE ) \\\n\t\t\t\t{ \\\n\t\t\t\tfree( threadStack ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tOSSemPost( sync ); \\\n\t\t\t\t\t\t\t\tOSTaskDel( OS_PRIO_SELF )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tthreadSelf()\n#if OS_TICKS_PER_SEC >= 1000\n  #define THREAD_SLEEP( ms )\tOSTimeDly( ( OS_TICKS_PER_SEC / 1000 ) * ms )\n#else\n  #define THREAD_SLEEP( ms )\tOSTimeDly( max( ( ms * OS_TICKS_PER_SEC ) / 1000, 1 ) )\n#endif /* OS_TICKS_PER_SEC time scaling */\n#define THREAD_YIELD()\t\t\tTHREAD_SLEEP( 1 )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\t{ \\\n\t\t\t\t\t\t\t\tINT8U err; \\\n\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\tOSSemPend( sync, 0, &err ); \\\n\t\t\t\t\t\t\t\tif( err != OS_ERR_NONE ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\tOSSemDel( sync, OS_DEL_ALWAYS, &err ); \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_CLOSE( sync )\n\n/* uC/OS-II doesn't have a thread-self function, but allows general task\n   info to be queried.  Because of this we provide a wrapper that returns\n   the task ID as its return value */\n\nINT8U threadSelf( void );\n\n/* Because of the inability to do round-robin scheduling, we no-op out the\n   use of internal threads/tasks.  Note that cryptlib itself is still thread-\n   safe, it just can't do its init in an internal background thread */\n\n#ifndef UCOS_USE_TASKS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !UCOS_USE_TASKS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUnix/MVS/XMK\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif ( defined( __UNIX__ ) || defined( __XMK__ ) ) && defined( USE_THREADS )\n\n/* Under OSF/1 pthread.h includes c_asm.h which contains a declaration\n\n\tlong asm( const char *,...);\n\n   that conflicts with the gcc asm keyword.  This asm stuff is only used\n   when inline asm alternatives to the Posix threading functions are enabled,\n   which isn't done by default so in theory we could also fix this by\n   defining asm to something else before including pthread.h, but it's safer\n   to just disable inclusion of c_asm.h by pre-defining the guard define.\n   This will result in a more useful warning if for some reason inline\n   threading functions with asm are enabled */\n\n#if defined( __osf__ ) || defined( __alpha__ )\n  #define __C_ASM_H\n#endif /* Alpha */\n\n/* Linux threads are a particularly peculiar implementation, being based on\n   the Linux clone() system call, which clones an entire process and uses\n   a special \"manager thread\" to provide the appearance of a multithreaded\n   application.  This threads == processes model produces very strange\n   effects such as the appearance of a mass of (pseudo-)processes, each with\n   their own PID, that appear to consume more memory than is physically\n   present.  Another problem was that signals, which are done on a per-PID\n   basis and should have been consistent across all threads in the process,\n   were instead only delivered to one thread/pseudo-process and never got\n   any further.  The clone()-based hack results in non-conformance with the\n   pthreads spec as well as significant scalability and performance issues.\n\n   The problem was finally (mostly) fixed with Ingo Molnar's native Posix\n   thread library (NPTL) patches to the 2.5 development) kernel, which\n   still retains the strange clone()-based threading mechanism but provides\n   enough kludges to other parts of the kernel that it's not longer so\n   obvious.  For example the clone() call has been optimised to make it\n   more lightweight, Molnar's O(1) scheduler reduces the overhead of the\n   process-per-thread mechanism, fast userspace mutexes eliminate the need\n   for interthread signalling to implement locking, and most importantly the\n   kernel identification of all threads has been collapsed to a single PID,\n   eliminating the confusion caused by the cloned pseudo-processes */\n\n#include <pthread.h>\n#include <sys/time.h>\n#ifdef __XMK__\n  #include <sys/process.h>\n  #include <sys/timer.h>\n#endif /* Xilinx XMK */\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tpthread_t\n#define MUTEX_HANDLE\t\t\tpthread_t\n\n/* Mutex management functions.  Most Unix mutex implementations are non-\n   re-entrant, which means that re-locking a mutex leads to deadlock\n   (charming).  Some implementations can fix this by setting a mutex\n   attribute to ensure that it doesn't deadlock using:\n\n\tpthread_mutexattr_settype( attr, PTHREAD_MUTEX_RECURSIVE );\n\n   or:\n\n\tpthread_mutex_setrecursive();\n\n   but this isn't universal.  To fix the problem, we implement our own\n   re-entrant mutexes on top of the Posix ones.\n\n   Due to the complexity of the locking process using pthreads' (usually)\n   non-reentrant mutexes, we don't try and lock+unlock the mutex before we\n   destroy it.  This isn't a major issue since it's just a safety precaution,\n   the kernel should have forced any remaining threads to exit by the time\n   the shutdown occurs anyway */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tpthread_mutex_t name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised; \\\n\t\tpthread_t name##MutexOwner; \\\n\t\tint name##MutexLockcount\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( pthread_mutex_init( &krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t\tNULL ) == 0 ) \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount = 0; \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tpthread_mutex_destroy( &krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tif( pthread_mutex_trylock( &krnlData->name##Mutex ) ) \\\n\t\t\t{ \\\n\t\t\tif( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \\\n\t\t\t\tpthread_mutex_lock( &krnlData->name##Mutex ); \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexLockcount++; \\\n\t\t\t\tANALYSER_HINT_RECURSIVE_LOCK( krnlData->name##Mutex ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\tkrnlData->name##MutexOwner = THREAD_SELF();\n#define MUTEX_UNLOCK( name ) \\\n\t\tif( krnlData->name##MutexLockcount > 0 ) \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexLockcount--; \\\n\t\t\tANALYSER_HINT_RECURSIVE_UNLOCK( krnlData->name##Mutex ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tkrnlData->name##MutexOwner = THREAD_INITIALISER; \\\n\t\t\tpthread_mutex_unlock( &krnlData->name##Mutex ); \\\n\t\t\t}\n\n/* Instead of the DIY recursive mutexes above it's also possible to use OS\n   recursive mutexes if they're available.  Unfortunately there's no easy\n   way to reliably test for these (they're often provided as _NP variants,\n   or require obscure preprocessor trickery to enable them), and even if\n   they're present they may not be supported (pthread_mutexattr_settype()\n   returns an error), or the implementation may be flaky (some Linux \n   threading implementations).  Because of this the following use of \n   recursive mutexes needs to be manually enabled.  Note that on most \n   systems that use gcc it's necessary to define either _XOPEN_SOURCE=500 or \n   _GNU_SOURCE to get PTHREAD_MUTEX_RECURSIVE, otherwise only \n   PTHREAD_MUTEX_RECURSIVE_NP is defined, i.e. the standard behaviour of gcc \n   is to be nonstandard */\n\n#if 0\n\n#undef MUTEX_CREATE\n#undef MUTEX_LOCK\n#undef MUTEX_UNLOCK\n#define MUTEX_CREATE( name, status ) \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tpthread_mutexattr_t mutexAttr;\\\n\t\t\t\\\n\t\t\tpthread_mutexattr_init( &mutexAttr );\\\n\t\t\tpthread_mutexattr_settype( &mutexAttr, \\\n\t\t\t\t\t\t\t\t\t   PTHREAD_MUTEX_RECURSIVE ); \\\n\t\t\tif( pthread_mutex_init( &krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t\t&mutexAttr ) == 0 ) \\\n\t\t\t\t{ \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\tpthread_mutexattr_destroy ( &mutexAttr );\\\n\t\t\t}\n#define MUTEX_LOCK( name )\t\tpthread_mutex_lock( &krnlData->name##Mutex )\n#define MUTEX_UNLOCK( name )\tpthread_mutex_unlock( &krnlData->name##Mutex )\n\n#endif /* 0 */\n\n/* Putting a thread to sleep for a number of milliseconds can be done with\n   select() because it should be a thread-safe one in the presence of\n   pthreads.  In addition there are some system-specific quirks, these are\n   handled by re-defining the macros below in a system-specific manner\n   further on.\n\n   Yielding a thread's timeslice gets rather complex due to a confusion of\n   non-portable \"portable\" Posix functions.  Initially there was\n   pthread_yield() from draft 4 of the Posix thread standard in 1990,\n   popularised in the DCE threading code and picked up by a number of other\n   implementations.  At about that time the realtime (1003.1b) and thread\n   (1003.1c) standardisation was proceeding independently, with neither side\n   knowing which one would make it to standards status first.  As it turned\n   out this was 1003.1b with sched_yield().  When the 1003.1c folks were\n   looking for every place where the text said \"process\" but should say\n   \"thread\" once 1003.1c was in effect, they noticed that sched_yield() and\n   pthread_yield() were now identical.  Since sched_yield() was already in\n   the standard, there was no need for pthread_yield() so it was removed.\n   However, some older implementations still do pthread_yield() and some\n   (also older) implementations use sched_yield() to yield the processes'\n   timeslice rather than the thread's timeslice, further complicated by the\n   fact that some implementations like PHUX 10.x/11.x have buggy manpages\n   that claim sched_yield() is per-process when in fact it's per-thread\n   (PHUX 10.x still had pthread_yield() while 11.x only has sched_yield()).\n   The whole is further confused by the fact that in some implementations,\n   threads are processes (sort of, e.g. Linux's clone()'d threads and Sun\n   LWPs).  In addition Sun have their own thr_yield which is part of their\n   UI threads interface and that you have to fall back to occasionally.\n\n   Because of this mess, we try for pthread_yield() if possible (since that\n   definitely yields the thread's timeslice), fall back to sched_yield() if\n   necessary, and add a special workaround for Sun systems.\n\n   \"Posix is portable in the sense that you can use a forklift to move the\n    printed volumes around\" */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid *name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tstatus = pthread_create( &threadHandle, NULL, function, arg ) ? \\\n\t\t\t\t\t CRYPT_ERROR : CRYPT_OK; \\\n\t\t\tsyncHandle = threadHandle; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tpthread_exit( ( void * ) 0 )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SELF()\t\t\tpthread_self()\n#define THREAD_SAME( thread1, thread2 )\tpthread_equal( ( thread1 ), ( thread2 ) )\n#if defined( __osf__ ) || defined( __alpha__ ) || defined( __APPLE__ )\n  #define THREAD_YIELD()\t\tpthread_yield_np()\n#elif defined( __MVS__ )\n  #define THREAD_YIELD()\t\tpthread_yield( NULL )\n#elif defined( sun )\n  #if OSVERSION <= 6\n\t/* Older Slowaris gets a bit complex, SunOS 4.x always returns -1 and \n\t   sets errno to ENOSYS when sched_yield() is called, so we use this to \n\t   fall back to the UI interface if necessary */\n\t#define THREAD_YIELD()\t\t{ if( sched_yield() ) thr_yield(); }\n  #else\n\t#define THREAD_YIELD()\t\tsched_yield()\n  #endif /* Slowaris 5.7 / 7.x or newer */\n#elif defined( _AIX ) || defined( __Android__ ) || defined( __CYGWIN__ ) || \\\n\t  ( defined( __hpux ) && ( OSVERSION >= 11 ) ) || \\\n\t  defined( __NetBSD__ ) || defined( __QNX__ ) || defined( __UCLIBC__ )\n  #define THREAD_YIELD()\t\tsched_yield()\n#elif defined( __XMK__ )\n  /* The XMK underlying scheduling object is the process context, for which\n     the user-visible interface is the thread.  Therefore yielding the\n\t underlying process context should yield the associated thread */\n  #define THREAD_YIELD()\t\tyield()\n#else\n  #if defined( __linux__ )\n  #if ( OSVERSION > 3 )\n\t#include <sched.h>\n\t#define THREAD_YIELD() sched_yield()\n  #else\n\t#ifndef __USE_GNU\n\t  void pthread_yield( void );\n\t#endif / Present but not prototyped unless GNU extensions are enabled /\n\t#define THREAD_YIELD() pthread_yield()\n  #endif // Linux > 3.x /</sched.h>\n  #else\n    #define THREAD_YIELD() pthread_yield()\n  #endif\n\n#endif /* Not-very-portable Posix portability */\n#define THREAD_SLEEP( ms )\t\t{ \\\n\t\t\t\t\t\t\t\tstruct timeval tv = { 0 }; \\\n\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\ttv.tv_usec = ( ms ) * 1000; \\\n\t\t\t\t\t\t\t\tselect( 1, NULL, NULL, NULL, &tv ); \\\n\t\t\t\t\t\t\t\t}\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( pthread_join( sync, NULL ) < 0 ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_CLOSE( sync )\n\n/* OSF1 includes some ghastly kludgery to handle binary compatibility from\n   1003.4a to 1003.1c threading functions and inline asm functions with all\n   sorts of name mangling and translation of function names and types.\n   Unfortunately a straight vanilla compile leaves pthread_self() un-\n   prototyped, which means that it's then implicitly prototyped as returned\n   an int.  This generates hundreds of warnings of int <-> pointer casting\n   problems, so if pthread_self() isn't redefined into one of a dozen\n   different mangled versions we prototype it ourselves here */\n\n#if ( defined( __osf__ ) || defined( __alpha__ ) ) && \\\n\t!defined( pthread_self )\n  #ifdef _PTHREAD_USE_MANGLED_NAMES_\n\t#define pthread_self __pthread_self\n  #endif /* Name mangling */\n  extern pthread_t pthread_self( void );\n#endif /* OSF1 pthread_self function prototyping bug */\n\n/* The pthreads implementation on MP-RAS (NCR User Space Threads based on\n   CMA threads for DCE) doesn't accept NULL for several of the attribute\n   arguments so we have to supply pthread_mutexattr_default attributes */\n\n#ifdef _MPRAS\n  #undef MUTEX_CREATE\n  #define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( pthread_mutex_init( &krnlData->name##Mutex, \\\n\t\t\t\t\t\t\t\t\tpthread_mutexattr_default ) == 0 ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n\n  #undef THREAD_CREATE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tstatus = pthread_create( &threadHandle, pthread_attr_default, \\\n\t\t\t\t\t\t\t\t\t function, arg ) ? \\\n\t\t\t\t\t CRYPT_ERROR : CRYPT_OK ); \\\n\t\t\tsyncHandle = ( long ) threadHandle; \\\n\t\t\t}\n#endif /* _MPRAS */\n\n/* Some systems (notably MVS and MP-RAS) use non-scalar pthread_t's, so we\n   have to handle initialisation of these specially */\n\n#if defined( __MVS__ ) || defined( _MPRAS )\n  #define NONSCALAR_HANDLES\n  #undef THREAD_INITIALISER\n  #define THREAD_INITIALISER\t{ 0 }\n#endif /* Non-scalar pthread_t's */\n\n/* XMK doesn't have a select(), however it has a sleep() as part of the timer\n   package that performs the same function.  Note that there's a second\n   sleep() that takes an argument in seconds rather than ms and that sleeps\n   the overall process in the PPC BSP library, but presumably this won't be\n   used if the sleep() in the timer package is enabled */\n\n#ifdef __XMK__\n  #undef THREAD_SLEEP\n  #define THREAD_SLEEP( ms )\tsleep( ms )\n#endif /* Xilinx XMK */\n\n/* UnixWare/SCO creates threads with a ridiculously small default stack size\n   of a few KB or so, which means that the thread can't even start.  To work\n   around this we have to use a custom thread-creation function that sets\n   the stack size to something reasonable */\n\n#ifdef __SCO_VERSION__\n  #undef THREAD_CREATE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tpthread_attr_t attr; \\\n\t\t\t\\\n\t\t\tpthread_attr_init( &attr ); \\\n\t\t\tpthread_attr_setstacksize( &attr, 32768 ); \\\n\t\t\tstatus = pthread_create( &threadHandle, &attr, function, arg ); \\\n\t\t\tpthread_attr_destroy( &attr ); \\\n\t\t\tif( status ) \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t\tsyncHandle = ( long ) threadHandle; \\\n\t\t\t\t} \\\n\t\t\t}\n#endif /* UnixWare/SCO */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tVDK\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VDK__ )\n\n/* VDK has a rather unusual concept of error handling in which it assumes \n   that system calls rarely fail and if they do the error should be handled \n   as an exception by a thread's ErrorFunction (augmenting the standard\n   function return code), which is defined in the thread template alongside \n   various other things like the thread's Run function (see the discussion \n   on threads below for more on this).  Error handling via exceptions \n   depends on how the system is linked, if it's linked against the error-\n   checking libraries then general error conditions are checked and result\n   in an exception (e.g. waiting on an undefined semaphore), if the standard \n   libraries are used then only some critical errors such as timeout on a \n   semaphore result in an exception.\n\n   This dual-path error handling is made worse by the fact that the default \n   ErrorFunction handler invokes a kernel panic (!!!), making clean recovery \n   somewhat difficult */\n\n#include <VDK.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tVDK_ThreadID\n#define MUTEX_HANDLE\t\t\tVDK_SemaphoreID\n\n/* Mutex management functions.  VDK semaphores are re-entrant so we don't \n   have to jump through the hoops that are necessary with most other OSes.\n   \n   VDK uses one-size-fits all semaphores and also has the concept of a\n   \"periodic semaphore\" which is actually just a waitable timer triggering\n   every n clock ticks.  We disable this functionality and create a basic\n   binary semaphore with no (or at least near-infnite) timeout, in other \n   words a mutex */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( ( krnlData->name##Mutex = VDK_CreateSemaphore( 1, 1, 1, 0 ) ) != UINT_MAX ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tVDK_PendSemaphore( krnlData->name##Mutex, 1000000 ); \\\n\t\t\tVDK_PostSemaphore( krnlData->name##Mutex ); \\\n\t\t\tVDK_DestroySemaphore( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tVDK_PendSemaphore( krnlData->name##Mutex, 1000000 ); \\\n#define MUTEX_UNLOCK( name ) \\\n\t\tVDK_PostSemaphore( krnlData->name##Mutex );\n\n/* VDK has a somewhat strange concept of thread management in which a thread\n   isn't defined as a stream of execution on code but via a template whose \n   details are fixed at compile time, with each template identified by a \n   unique value in a header file.  So instead of starting a thread with\n   'CreatThread( threadFnPtr, threadFnParams, threadInfo )' VDK uses\n   'CreateThread( threadType )' and the scheduler looks up the details that\n   are normally pass in at runtime in a table mapping the thread type to the\n   parameters that it needs.\n\n   This is really awkward because it requires that all threads be defined in\n   a single location at system build time, which is problematic for a \n   library like cryptlib because the calling code has to be aware of \n   cryptlib-internal thread functions when it's built.  Because of this we\n   disable the use of cryptlib-internal threads, these are only used for\n   dynamic driver binding which isn't needed under VDK because there are\n   unlikely to be PKCS #11 or ODBC ports to it any time soon, or even\n   dynamic library support which would be needed before it was possible to\n   have loadable drivers.\n\n   VDK threads are exited using a standard 'return' rather than via any OS-\n   specific exit mechanism.\n\n   Task sleep times are measured in implementation-specific ticks rather\n   than ms, but we can get the duration using VDK_GetTickPeriod() */\n\n#define THREADFUNC_DEFINE( name, arg )\tthread_id name( void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tVDK_ThreadCreationBlock threadInfo; \\\n\t\t\t\\\n\t\t\tmemset( &threadInfo, 0, sizeof( VDK_ThreadCreationBlock ) ); \\\n\t\t\tthreadInfo.template_id = kDynamicThread; \\\n\t\t\tthreadInfo.user_data_ptr = arg; \\\n\t\t\tthreadInfo.pTemplate = /*<thread template, see above>*/; \\\n\t\t\t\\\n\t\t\tsyncHandle = VDK_CreateSemaphore( 1, 1, 1, 0 ); \\\n\t\t\tthreadHandle = VDK_CreateThreadEx( &threadInfo ); \\\n\t\t\tif( threadHandle == UINT_MAX ) \\\n\t\t\t\t{ \\\n\t\t\t\tVDK_DestroySemaphore( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tVDK_PostSemaphore( sync ); \\\n\t\t\t\t\t\t\t\treturn( 0 )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\tVDK_GetThreadID()\n#define THREAD_SLEEP( ms )\t\tVDK_Sleep( VDK_GetTickPeriod() * ms )\n#define THREAD_YIELD()\t\t\tVDK_Yield()\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( !VDK_PendSemaphore( sync, 1000000 ) ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\telse \\\n\t\t\t\t\t\t\t\t\tVDK_PostSemaphore( sync ); \\\n\t\t\t\t\t\t\t\tVDK_DestroySemaphore( sync )\n#define THREAD_CLOSE( sync )\n\n/* Because of the odd way in which thread management works we no-op out the\n   use of internal threads.  Note that cryptlib itself is still thread-safe, \n   it just can't do its init in an internal background thread */\n\n#ifndef VDK_USE_THREADS\n  #undef USE_THREAD_FUNCTIONS\n  #undef THREAD_CREATE\n  #undef THREAD_EXIT\n  #undef THREAD_CLOSE\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n  #define THREAD_EXIT( sync )\n  #define THREAD_CLOSE( sync )\n#endif /* !VDK_USE_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tVxWorks\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VxWorks__ )\n\n#include <vxWorks.h>\n#include <semLib.h>\n#include <taskLib.h>\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tint\n#define MUTEX_HANDLE\t\t\tSEM_ID\n\n/* Mutex management functions.  VxWorks mutual exclusion semaphores (and\n   only mutex semaphores) are re-entrant, so we don't have to jump through\n   the hoops that are necessary with most other OSes */\n\n#define MUTEX_LOCKNAME( name )\tkrnlData->name##Mutex\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tMUTEX_HANDLE name##Mutex; \\\n\t\tBOOLEAN name##MutexInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tif( ( krnlData->name##Mutex = semMCreate( SEM_Q_FIFO ) ) != NULL ) \\\n\t\t\t\tkrnlData->name##MutexInitialised = TRUE; \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##MutexInitialised ) \\\n\t\t\t{ \\\n\t\t\tsemTake( krnlData->name##Mutex, WAIT_FOREVER ); \\\n\t\t\tsemGive( krnlData->name##Mutex ); \\\n\t\t\tsemDelete( krnlData->name##Mutex ); \\\n\t\t\tkrnlData->name##MutexInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tsemTake( krnlData->name##Mutex, WAIT_FOREVER ); \n#define MUTEX_UNLOCK( name ) \\\n\t\tsemGive( krnlData->name##Mutex );\n\n/* Thread management functions.  Some PPC compilers use the FP registers for\n   non-FP operations such as working with long long data types (used for\n   example in PKC key generation), so if we're building for the PPC we\n   create tasks with FP register saving enabled */\n\n#ifdef __ppc__\n  #define TASK_ATTRIBUTES\tVX_FP_TASK\n#else\n  #define TASK_ATTRIBUTES\t0\n#endif /* PPC vs.non-PPC register saves */\n#ifndef T_PRIORITY\n  #define T_PRIORITY\t\t50\n#endif /* T_PRIORITY */\n\n/* VxWorks tasks are exited using the standard ANSI exit() function rather\n   than any OS-specific exit mechanism.\n\n   The argument to the thread function is actually ten long's, but all we\n   care about is the first one.  In addition since we're using it as a \n   pointer we cheat a bit and declare it as a 'void *' rather than a 'long'.\n\n   Task sleep times are measured in implementation-specific ticks rather\n   than ms, but it's usually close enough to allow us to treat them as being\n   identical.  If we need truly accurate timing we could call a helper\n   function that scales the time based on sysClkRateGet(), but at the moment\n   it's only used for general short delays rather than any fixed amount of\n   time so this isn't necessary */\n\n#define THREADFUNC_DEFINE( name, arg )\tvoid name( /*long*/ void *arg )\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t{ \\\n\t\t\tsyncHandle = semBCreate( SEM_Q_FIFO, SEM_EMPTY ); \\\n\t\t\tthreadHandle = taskSpawn( NULL, T_PRIORITY, TASK_ATTRIBUTES, \\\n\t\t\t\t\t\t\t\t\t  EMBEDDED_STACK_SIZE, ( FUNCPTR ) function, \\\n\t\t\t\t\t\t\t\t\t  ( int ) arg, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); \\\n\t\t\tif( threadHandle == ERROR ) \\\n\t\t\t\t{ \\\n\t\t\t\tsemDelete( syncHandle ); \\\n\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\tstatus = CRYPT_OK; \\\n\t\t\t}\n#define THREAD_EXIT( sync )\t\tsemGive( sync ); \\\n\t\t\t\t\t\t\t\texit( 0 )\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SELF()\t\t\ttaskIdSelf()\n#define THREAD_SLEEP( ms )\t\ttaskDelay( ms )\n#define THREAD_YIELD()\t\t\ttaskDelay( NO_WAIT )\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( semTake( sync, WAIT_FOREVER ) != OK ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR; \\\n\t\t\t\t\t\t\t\telse \\\n\t\t\t\t\t\t\t\t\tsemGive( sync ); \\\n\t\t\t\t\t\t\t\tsemDelete( sync )\n#define THREAD_CLOSE( sync )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tWin32/WinCE\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif ( defined( __WIN32__ ) && !defined( NT_DRIVER ) ) || \\\n\t  defined( __WINCE__ )\n\n#ifndef __WINCE__\n  #include <process.h>\n#endif /* __WINCE__ */\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\tDWORD\n#define MUTEX_HANDLE\t\t\tHANDLE\n\n/* Mutex management functions.  InitializeCriticalSection() doesn't return \n   an error code but can throw a STATUS_NO_MEMORY exception in certain low-\n   memory situations under Win2K/XP/2003 (it was fixed in Vista), however \n   this exception isn't raised in an exception-safe manner (the critical \n   section object is left in a corrupted state) so it can't be safely caught \n   and recovered from.  The result is that there's no point in trying to \n   catch it (this is a known design flaw in the function).\n\n   EnterCriticalSection() is a bit more problematic.  Apart from the\n   EXCEPTION_POSSIBLE_DEADLOCK exception (which is raised if the critical \n   section is corrupted, there's not much that can be done here), this can \n   also raise an out-of-memory exception due to on-demand allocation of the \n   event handle required by the critical section.  In Windows NT these were \n   always allocated by InitializeCriticalSection(), however in the Win2K \n   timeframe applications with hundreds of threads and hundreds or even \n   thousands of critical sections were starting to appear, many of which \n   were never user.  To avoid resource-exhaustion problems, Win2K was \n   changed to perform on-demand allocation of event handles in critical \n   sections, and even then only on the first contended acquire (rather than \n   the first time EnterCriticalSection() is called).  To avoid this problem, \n   InitializeCriticalSectionAndSpinCount() was kludged under Win2K to always \n   allocate the event handle if the high bit of the dwSpinCount value was \n   set, but this behaviour was disabled again in WinXP.\n\n   Because of this behaviour, there's no easy safe way to initialise a \n   critical section.  What we'd have to do is create a second thread to \n   force an initialisation by trying to enter the section while another \n   thread holds the lock, forcing the allocation of an event handle.  In \n   theory we could do this (since cryptlib only uses a handful of critical \n   sections), but in practice if the system is so short of resources that it \n   can't allocate event handles any more then the user has bigger things to \n   worry about.  If we were running exclusively under Vista we could use the \n   extremely useful slim reader/writer (SRW) locks, but it'll be awhile yet \n   before we can rely on these (they're also non-reentrant due to their \n   extreme slimness, which means that they have to be managed very \n   carefully).\n\n   Critical sections can lead to lock convoys, a variant of the thundering \n   herd problem that occurs due to an optimisation in lock management used \n   under Windows where a lock with another thread waiting would be handed \n   off to the waiting thread without ever being released.  In other words \n   the handoff consisted of handing ownership over to the waiting thread \n   (without unlocking the lock) instead of unlocking and re-locking with the \n   new thread. This was done to implement fair locking in which threads were \n   serviced in strictly FIFO order.\n\n   This leads to a problem because it extends the lock hold time by the \n   thread context switch latency.  Consider a lock for which a thread \n   arrives every 2000 cycles and executes inside the lock for 1000 cycles.  \n   With thread T0 holding the lock, a new thread T1 arrives 500 cycles into \n   the execution.  T0 releases the lock after 1000 cycles, and T1 takes \n   ownership.  However, the context switch time is 4000 cycles (up to 10K \n   cycles), so it can't actually start running inside the lock until cycle \n   5000, even if there are other threads ready to run immediately.  Windows \n   Vista fixed this by making locks slightly unfair, so that an active \n   thread can steal the lock from the one at the front of the wait queue if \n   the latter isn't scheduled to be run.\n\n   Finally, special handling of critical sections occurs during a process \n   shutdown.  Firstly, every thread but the one that initiated the shutdown \n   is killed in a fairly hostile manner.  Then, in order to avoid deadlocks, \n   the system effectively ignores calls to Enter/LeaveCriticalSection(), \n   since the lock may have been held by one of the killed threads.  What \n   this means is that if the thread left lock-protected data in an \n   inconsistent state when it was killed and the shutdown thread comes along \n   and tries to use it, it's going to run into problems.  This is a \n   difficult problem to solve (the MT CRT apparently has a number of \n   problems with this in internal code paths), but luckily is triggered \n   extremely rarely, if ever */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##CriticalSection\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tCRITICAL_SECTION name##CriticalSection; \\\n\t\tBOOLEAN name##CriticalSectionInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK;\t/* See note above */ \\\n\t\tif( !krnlData->name##CriticalSectionInitialised ) \\\n\t\t\t{ \\\n\t\t\tInitializeCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t\tkrnlData->name##CriticalSectionInitialised = TRUE; \\\n\t\t\t}\n#define MUTEX_DESTROY( name ) \\\n\t\tif( krnlData->name##CriticalSectionInitialised ) \\\n\t\t\t{ \\\n\t\t\tEnterCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t\tLeaveCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t\tDeleteCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t\tkrnlData->name##CriticalSectionInitialised = FALSE; \\\n\t\t\t}\n#define MUTEX_LOCK( name ) \\\n\t\tEnterCriticalSection( &krnlData->name##CriticalSection )\n#define MUTEX_UNLOCK( name ) \\\n\t\tLeaveCriticalSection( &krnlData->name##CriticalSection )\n\n/* Mutex debug support */\n\n#ifdef MUTEX_DEBUG\n\n/* A queue to record prior mutex operations */\n\ntypedef struct {\n\tTHREAD_HANDLE owner;\n\tint lockCount;\n\tint sequenceNo;\n\t} MUTEX_QUEUE_INFO;\n\n#define MUTEX_QUEUE_SIZE\t16\n\n/* Alternative debug versions of the mutex manipulation primitives.  These \n   just record the last MUTEX_QUEUE_SIZE mutex operations in a FIFO queue for\n   later analysis */\n\n#undef MUTEX_DECLARE_STORAGE\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tCRITICAL_SECTION name##CriticalSection; \\\n\t\tBOOLEAN name##CriticalSectionInitialised; \\\n\t\tMUTEX_QUEUE_INFO name##EntryQueue[ MUTEX_QUEUE_SIZE ]; \\\n\t\tMUTEX_QUEUE_INFO name##ExitQueue[ MUTEX_QUEUE_SIZE ]; \\\n\t\tint name##LockCount; \\\n\t\tint name##SequenceNo\n#undef MUTEX_CREATE\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK; \\\n\t\tif( !krnlData->name##CriticalSectionInitialised ) \\\n\t\t\t{ \\\n\t\t\tInitializeCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t\tmemset( &krnlData->name##EntryQueue, 0, \\\n\t\t\t\t\tsizeof( MUTEX_QUEUE_INFO ) * MUTEX_QUEUE_SIZE ); \\\n\t\t\tmemset( &krnlData->name##ExitQueue, 0, \\\n\t\t\t\t\tsizeof( MUTEX_QUEUE_INFO ) * MUTEX_QUEUE_SIZE ); \\\n\t\t\tkrnlData->name##LockCount = krnlData->name##SequenceNo = 0; \\\n\t\t\tkrnlData->name##CriticalSectionInitialised = TRUE; \\\n\t\t\t}\n#undef MUTEX_LOCK\n#undef MUTEX_UNLOCK\n#define MUTEX_LOCK( name ) \\\n\t\t{ \\\n\t\tint i; \\\n\t\t\\\n\t\tEnterCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\tfor( i = 1; i < MUTEX_QUEUE_SIZE; i++ ) \\\n\t\t\tkrnlData->name##EntryQueue[ i - 1 ] = \\\n\t\t\t\tkrnlData->name##EntryQueue[ i ]; \\\n\t\tkrnlData->name##EntryQueue[ MUTEX_QUEUE_SIZE - 1 ].owner = THREAD_SELF(); \\\n\t\tkrnlData->name##EntryQueue[ MUTEX_QUEUE_SIZE - 1 ].lockCount = krnlData->name##LockCount++; \\\n\t\tkrnlData->name##EntryQueue[ MUTEX_QUEUE_SIZE - 1 ].sequenceNo = krnlData->name##SequenceNo++; \\\n\t\t}\n#define MUTEX_UNLOCK( name ) \\\n\t\t{ \\\n\t\tint i; \\\n\t\t\\\n\t\tfor( i = 1; i < MUTEX_QUEUE_SIZE; i++ ) \\\n\t\t\tkrnlData->name##ExitQueue[ i - 1 ] = \\\n\t\t\t\tkrnlData->name##ExitQueue[ i ]; \\\n\t\tkrnlData->name##ExitQueue[ MUTEX_QUEUE_SIZE - 1 ].owner = THREAD_SELF(); \\\n\t\tkrnlData->name##ExitQueue[ MUTEX_QUEUE_SIZE - 1 ].lockCount = krnlData->name##LockCount--; \\\n\t\tkrnlData->name##ExitQueue[ MUTEX_QUEUE_SIZE - 1 ].sequenceNo = krnlData->name##SequenceNo++; \\\n\t\tLeaveCriticalSection( &krnlData->name##CriticalSection ); \\\n\t\t}\n#endif /* MUTEX_DEBUG */\n\n/* Thread management functions.  Win32 requires a C library-aware wrapper\n   around the OS native CreateThread()/ExitThread() calls, with WinCE\n   after 2.0 the C runtime is integrated into the OS so we can call them\n   directly.\n\n   There are two functions that we can call to get the current thread ID,\n   GetCurrentThread() and GetCurrentThreadId().  GetCurrentThread() merely\n   returns a constant value that's interpreted by various functions to\n   mean \"the current thread\".  GetCurrentThreadId() returns the thread ID,\n   however this isn't the same as the thread handle.\n   \n   After we wait for the thread, we need to close the handle.  This is\n   complicated by the fact that we can only close it once all threads have\n   exited the wait, which requires further calisthenics in the function that\n   uses it to ensure that the last thread out closes the handle. This also\n   means that we can't combine the close with the wait as for other OSes,\n   since we can only perform the close once all waits have exited */\n\n#if defined( __WIN32__ )\n  #define THREADFUNC_DEFINE( name, arg ) \\\n\t\t\t\tunsigned __stdcall name( void *arg )\n  #if defined( _MSC_VER ) && VC_GE_2005( _MSC_VER )\n\t#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t{ \\\n\t\t\t\tuintptr_t hThread; \\\n\t\t\t\t\\\n\t\t\t\thThread = _beginthreadex( NULL, 0, ( function ), ( arg ), 0, \\\n\t\t\t\t\t\t\t\t\t\t  &threadHandle ); \\\n\t\t\t\tsyncHandle = ( MUTEX_HANDLE ) hThread; \\\n\t\t\t\tstatus = ( hThread == 0 ) ? CRYPT_ERROR : CRYPT_OK; \\\n\t\t\t\t}\n  #else\n\t#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t{ \\\n\t\t\t\tunsigned long hThread; \\\n\t\t\t\t\\\n\t\t\t\thThread = _beginthreadex( NULL, 0, ( function ), ( arg ), 0, \\\n\t\t\t\t\t\t\t\t\t\t  &threadHandle ); \\\n\t\t\t\tsyncHandle = ( MUTEX_HANDLE ) hThread; \\\n\t\t\t\tstatus = ( hThread == 0 ) ? CRYPT_ERROR : CRYPT_OK; \\\n\t\t\t\t}\n  #endif /* Older vs. newer VC++ */\n  #define THREAD_EXIT( sync )\t_endthreadex( 0 ); return( 0 )\n#elif defined( __WINCE__ )\n  #define THREADFUNC_DEFINE( name, arg ) \\\n\t\t\t\tDWORD WINAPI name( void *arg )\n  #define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t{ \\\n\t\t\t\tHANDLE hThread; \\\n\t\t\t\t\\\n\t\t\t\thThread = CreateThread( NULL, 0, ( function ), ( arg ), 0, \\\n\t\t\t\t\t\t\t\t\t\t&threadHandle ); \\\n\t\t\t\tsyncHandle = hThread; \\\n\t\t\t\tstatus = ( hThread == NULL ) ? CRYPT_ERROR : CRYPT_OK; \\\n\t\t\t\t}\n  #define THREAD_EXIT( sync )\tExitThread( 0 ); return( 0 )\n#endif /* Win32 vs. WinCE */\n#define THREAD_INITIALISER\t\t0\n#define THREAD_SELF()\t\t\tGetCurrentThreadId()\n#define THREAD_SAME( thread1, thread2 )\t( ( thread1 ) == ( thread2 ) )\n#define THREAD_SLEEP( ms )\t\tSleep( ms )\n#if defined( __WIN32__ )\n  #define THREAD_YIELD()\t\tthreadYield()\n#else\n  #define THREAD_YIELD()\t\tSleep( 0 )\n#endif /* Win32 vs. WinCE */\n#define THREAD_WAIT( sync, status ) \\\n\t\t\t\t\t\t\t\tif( WaitForSingleObject( sync, INFINITE ) != WAIT_OBJECT_0 ) \\\n\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_CLOSE( sync )\tCloseHandle( sync )\n\n/* Yielding a thread on an SMP or HT system is a tricky process, so we have \n   to use a custom function to do this */\n\nvoid threadYield( void );\n\n#elif defined( __WIN32__ ) && defined( NT_DRIVER )\n\n/* Object handles */\n\n#define THREAD_HANDLE\t\t\t\tHANDLE\n#define MUTEX_HANDLE\t\t\t\tHANDLE\n\n/* Mutex management functions */\n\n#define MUTEX_LOCKNAME( name )\t&krnlData->name##CriticalSection\n#define MUTEX_DECLARE_STORAGE( name ) \\\n\t\tKMUTEX name##CriticalSection; \\\n\t\tBOOLEAN name##CriticalSectionInitialised\n#define MUTEX_CREATE( name, status ) \\\n\t\tstatus = CRYPT_OK;\t/* Apparently never fails */ \\\n\t\tif( !krnlData->name##CriticalSectionInitialised ) \\\n\t\t\t{ \\\n\t\t\tKeInitializeMutex( &krnlData->name##CriticalSection, 1 ); \\\n\t\t\tkrnlData->name##CriticalSectionInitialised = TRUE; \\\n\t\t\t}\n#define MUTEX_DESTROY( name )\n#define MUTEX_LOCK( name ) \\\n\t\tKeWaitForMutexObject( &krnlData->name##CriticalSection, Executive, \\\n\t\t\t\t\t\t\t  KernelMode, FALSE, NULL )\n#define MUTEX_UNLOCK( name ) \\\n\t\tKeReleaseMutex( &krnlData->name##CriticalSection, FALSE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tNon-threaded OSes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#else\n\n/* Generic or NOP versions of functions and types declared for those OSes\n   that don't support threading */\n\n#define THREAD_HANDLE\t\t\t\t\t\t\tint\n#define MUTEX_HANDLE\t\t\t\t\t\t\tint\n\n#define MUTEX_LOCKNAME( name )\n#define MUTEX_DECLARE_STORAGE( name )\n#define MUTEX_CREATE( name, status )\t\t\tstatus = CRYPT_OK\n#define MUTEX_DESTROY( name )\n#define MUTEX_LOCK( name )\n#define MUTEX_UNLOCK( name )\n\n#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tstatus = CRYPT_ERROR\n#define THREAD_EXIT( sync )\n#define THREAD_INITIALISER\t\t\t\t\t\t0\n#define THREAD_SAME( thread1, thread2 )\t\t\tTRUE\n#define THREAD_SELF()\t\t\t\t\t\t\t0\n#define THREAD_SLEEP( ms )\n#define THREAD_YIELD()\n#define THREAD_WAIT( sync, status )\n#define THREAD_CLOSE( sync )\n\n#endif /* Threading support macros */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGeneric Defines\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* To initialise thread/mutex handles we need our own version of DUMMY_INIT,\n   since this may be an OS-specific and/or non-scalar value we only define\n   it if it hasn't already been defined above */\n\n#ifdef NONSCALAR_HANDLES\n  #define DUMMY_INIT_MUTEX\t\t= { 0 }\n#else\n  #define DUMMY_INIT_MUTEX\t\t= ( MUTEX_HANDLE ) 0\n#endif /* Scalar vs. non-scalar thread handles */\n\n#endif /* _THREAD_DEFINED */\n"
  },
  {
    "path": "deps/cl345/keyset/ca_add.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib DBMS CA Certificate Add Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that the request that we've been passed is in order */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkRequest( IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action )\n\t{\n\tMESSAGE_DATA msgData;\n\tBOOLEAN_INT isInited, isSelfSigned;\n\tint certType, value, status;\n\n\tREQUIRES_B( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES_B( action == CRYPT_CERTACTION_CERT_CREATION || \\\n\t\t\t\taction == CRYPT_CERTACTION_ISSUE_CERT || \\\n\t\t\t\taction == CRYPT_CERTACTION_REVOKE_CERT || \\\n\t\t\t\taction == CRYPT_CERTACTION_NONE );\n\n\t/* Make sure that the request type is consistent with the operation\n\t   being performed */\n\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tswitch( action )\n\t\t{\n\t\tcase CRYPT_CERTACTION_CERT_CREATION:\n\t\tcase CRYPT_CERTACTION_ISSUE_CERT:\n\t\t\tif( certType != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\t\t\tcertType != CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTACTION_REVOKE_CERT:\n\t\t\tif( certType != CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTACTION_NONE:\n\t\t\t/* We're performing a straight add of a request to the store,\n\t\t\t   any request type is permitted */\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\t/* Make sure that the request is completed and valid.  We don't check\n\t   the signature on revocation requests since they aren't signed, and\n\t   have to be careful with CRMF requests which can be unsigned for\n\t   encryption-only keys */\n\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &isInited, CRYPT_CERTINFO_IMMUTABLE );\n\tif( cryptStatusError( status ) || !isInited )\n\t\treturn( FALSE );\n\tswitch( certType )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &isSelfSigned, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SELFSIGNED );\n\t\t\tif( cryptStatusOK( status ) && !isSelfSigned )\n\t\t\t\t{\n\t\t\t\t/* It's an unsigned CRMF request, make sure that it really \n\t\t\t\t   is an encryption-only key */\n\t\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_KEYUSAGE );\n\t\t\t\tif( cryptStatusOK( status ) && ( value & KEYUSAGE_SIGN ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_CRT_SIGCHECK,\n\t\t\t\t\t\t\t\t\t  NULL, CRYPT_UNUSED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\t/* Revocation requests are unsigned so we can't perform a \n\t\t\t   signature check on them */\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\t/* Check that required parameters are present.  This is necessary for\n\t   CRMF requests where every single parameter is optional, for our use\n\t   we require that a certificate request contains at least a subject DN \n\t   and public key and a revocation request contains at least an issuer \n\t   DN and serial number */\n\tswitch( certType )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTREQUEST:\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_SPKI );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_REVOCATION:\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( iCertRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Boolean();\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check that a revocation request is consistent with information held in the\n   certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRevRequest( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCertRequest )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, issuerIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\n\t/* Check that the certificate being referred to in the request is \n\t   present and active */\n\tstatus = getKeyID( issuerID, ENCODED_DBXKEYID_SIZE, &issuerIDlength, \n\t\t\t\t\t   iCertRequest, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, issuerID, issuerIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT certData FROM certificates WHERE issuerID = ?\",\n\t\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr,\n\t\t\t\t\t\t\tDBMS_CACHEDQUERY_ISSUERID, DBMS_QUERY_CHECK );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The certificate isn't an active certificate, it's either not present \n\t   or not active, return an appropriate error code.  If this request has \n\t   been entered into the certificate store log then it's a duplicate \n\t   request, otherwise it's a request to revoke a non-present certificate \n\t   (either that or something really obscure which is best reported as a \n\t   non-present certificate problem) */\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT certData FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr,\n\t\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );\n\t\t}\n\treturn( cryptStatusOK( status ) ? \\\n\t\t\tCRYPT_ERROR_DUPLICATE : CRYPT_ERROR_NOTFOUND );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Add Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a new PKI user to the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint caAddPKIUser( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iPkiUser,\n\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certDataLength, certIDlength DUMMY_INIT, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iPkiUser ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Extract the information that we need from the PKI user object.  In\n\t   addition to simply obtaining the information for logging purposes we\n\t   also need to perform this action to tell the certificate management \n\t   code to fill in the remainder of the (implicitly-added) user \n\t   information  before we start querying fields as we add it to the \n\t   certificate store.  Because of this we also need to place the certID \n\t   fetch after the object export since it's in an incomplete state \n\t   before this point */\n\tstatus = extractCertData( iPkiUser, CRYPT_ICERTFORMAT_DATA,\n\t\t\t\t\t\t\t  certData, MAX_CERT_SIZE, &certDataLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t\t   iPkiUser, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't extract PKI user data to add to certificate \"\n\t\t\t\t  \"store\" ) );\n\t\t}\n\n\t/* Update the certificate store */\n\tstatus = addCert( dbmsInfo, iPkiUser, CRYPT_CERTTYPE_PKIUSER,\n\t\t\t\t\t  CERTADD_NORMAL, DBMS_UPDATE_BEGIN, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateCertLog( dbmsInfo, CRYPT_CERTACTION_ADDUSER, \n\t\t\t\t\t\t\t\tcertID, certIDlength, NULL, 0, NULL, 0, \n\t\t\t\t\t\t\t\tcertData, certDataLength, \n\t\t\t\t\t\t\t\tDBMS_UPDATE_COMMIT );\n\t\t}\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"PKI user add operation failed: \" ) );\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Delete a PKI user from the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint caDeletePKIUser( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iPkiUser;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength DUMMY_INIT, dummy, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get information on the PKI user that we're about to delete */\n\tstatus = getItemData( dbmsInfo, &iPkiUser, &dummy, \n\t\t\t\t\t\t  KEYMGMT_ITEM_PKIUSER, keyIDtype, \n\t\t\t\t\t\t  keyID, keyIDlength, KEYMGMT_FLAG_NONE, \n\t\t\t\t\t\t  errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t\t   iPkiUser, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\tkrnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't get information on PKI user to be \"\n\t\t\t\t\t \"deleted: \" ) );\n\t\t}\n\n\t/* Delete the PKI user information and record the deletion */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM pkiUsers WHERE certID = ?\", \n\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_BEGIN );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = updateCertLog( dbmsInfo, CRYPT_CERTACTION_DELETEUSER, \n\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, certID, certIDlength, \n\t\t\t\t\t\t\t\tNULL, 0, DBMS_UPDATE_COMMIT );\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"PKI user delete operation failed: \" ) );\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Add a certificate issue or revocation request to the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint caAddCertRequest( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE requestType, \n\t\t\t\t\t  const BOOLEAN isRenewal, \n\t\t\t\t\t  const BOOLEAN isInitialOp,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ], *reqCertIDptr = reqCertID;\n\tint certIDlength, reqCertIDlength DUMMY_INIT;\n\tint certDataLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES( requestType == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t  requestType == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tREQUIRES( isRenewal == TRUE || isRenewal == FALSE );\n\tREQUIRES( isInitialOp == TRUE || isInitialOp == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Make sure that the request is OK and if it's a revocation request \n\t   make sure that it refers to a certificate which is both present in \n\t   the store and currently active */\n\tif( !checkRequest( iCertRequest, CRYPT_CERTACTION_NONE ) )\n\t\t{\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, errorInfo, \n\t\t\t\t\t \"Certificate request information \"\n\t\t\t\t\t \"inconsistent/invalid\" ) );\n\t\t}\n\tif( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tstatus = checkRevRequest( dbmsInfo, iCertRequest );\n\t\tif( cryptStatusError( status ) )\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Revocation request doesn't correspond to a currently \"\n\t\t\t\t\t  \"active certificate\" ) );\n\t\t}\n\n\t/* Extract the information that we need from the certificate request */\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = extractCertData( iCertRequest, \n\t\t\t\t\t\t\t\t  ( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_ICERTFORMAT_DATA : \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE,\n\t\t\t\t\t\t\t\t  certData, MAX_CERT_SIZE, &certDataLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength, \n\t\t\t\t\t\t   iCertRequest, CRYPT_IATTRIBUTE_AUTHCERTID );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If the request is being added directly by the user, there's no\n\t\t\t   authorising certificate/PKI user information present */\n\t\t\treqCertIDptr = NULL;\n\t\t\treqCertIDlength = 0;\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't extract certificate request data to add to \"\n\t\t\t\t  \"certificate store\" ) );\n\t\t}\n\n\t/* Check that the PKI user who authorised this certificate issue still \n\t   exists.  If the CA has deleted them all further requests for \n\t   certificates fail */\n\tif( reqCertIDptr != NULL )\n\t\t{\n\t\tCRYPT_CERTIFICATE iPkiUser;\n\n\t\tstatus = caGetIssuingUser( dbmsInfo, &iPkiUser, reqCertID, \n\t\t\t\t\t\t\t\t   reqCertIDlength, errorInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tkrnlSendNotifier( iPkiUser, IMESSAGE_DECREFCOUNT );\n\t\telse\n\t\t\t{\n\t\t\tupdateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,\n\t\t\t\t\t\t\t\t\"Certificate request submitted for \"\n\t\t\t\t\t\t\t\t\"nonexistent PKI user\", NULL, 0, \n\t\t\t\t\t\t\t\treqCertID, reqCertIDlength, NULL, 0, \n\t\t\t\t\t\t\t\tNULL, 0 );\n\t\t\tretExt( CRYPT_ERROR_PERMISSION, \n\t\t\t\t\t( CRYPT_ERROR_PERMISSION, errorInfo, \n\t\t\t\t\t  \"Certificate request submitted for nonexistent PKI \"\n\t\t\t\t\t  \"user\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If there's an authorising PKI user present make sure that it hasn't\n\t   already been used to authorise the issuance of a certificate.  This \n\t   is potentially vulnerable to the following race condition:\n\n\t\t1: check authCertID -> OK\n\t\t2: check authCertID -> OK\n\t\t1: add\n\t\t2: add\n\n\t   In theory we could detect this by requiring the reqCertID to be \n\t   unique, however a PKI user can be used to request both a certificate \n\t   and a revocation for the certificate and a signing certificate can \n\t   be used to request an update or revocation of both itself and one or \n\t   more associated encryption certificates.  We could probably handle \n\t   this via the ID-mangling used for certIDs but this makes tracing \n\t   events through the audit log complex since there'll now be different \n\t   effective IDs for the authorising certificate depending on what it \n\t   was authorising.  \n\t   \n\t   In addition it's not certain how many further operations a \n\t   certificate (rather than a PKI user) can authorise, in theory a \n\t   single signing certificate can authorise at least four further \n\t   operations, these being the update of itself, the update of an \n\t   associated encryption certificate, and the revocation of itself and \n\t   the encryption certificate.  In addition its possible that a signing \n\t   certificate could be used to authorise a series of short-duration \n\t   encryption certificates or a variety of other combinations of \n\t   operations.\n\n\t   Because of these issues we can't use a uniqueness constraint on the\n\t   reqCertID to enforce a single use of issuing authorisation by the\n\t   database ifself but have to do a manual check here, checking \n\t   specifically for the case where a PKI user authorises a certificate \n\t   issue.  In addition we can't even perform a general-purpose check \n\t   because as soon as a single issue has been authorised for a user \n\t   there'll be a request for that user logged so that all further \n\t   attempts to submit a request (for example for a renewal, or an \n\t   encryption certificate to go with a signing one) will fail.  Because \n\t   of this we only perform a check on the first attempt to issue a \n\t   certificate, indicated by the caller setting the isInitialOp flag */\n\tif( isInitialOp && reqCertIDptr != NULL )\n\t\t{\n\t\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT certID FROM certLog WHERE reqCertID = ? \"\n\t\t\t\"AND action = \" TEXT_CERTACTION_REQUEST_CERT,\n\t\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr, \n\t\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* This user has already authorised the issue of a certificate, \n\t\t\t   it can't be used to issue a second certificate */\n\t\t\tupdateCertErrorLog( dbmsInfo, CRYPT_ERROR_DUPLICATE,\n\t\t\t\t\t\t\t\t\"Attempt to authorise additional certificate \"\n\t\t\t\t\t\t\t\t\"issue when a certificate for this user has \"\n\t\t\t\t\t\t\t\t\"already been issued\", NULL, 0, \n\t\t\t\t\t\t\t\treqCertID, reqCertIDlength, NULL, 0, NULL, 0 );\n\t\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t\t( CRYPT_ERROR_DUPLICATE, errorInfo, \n\t\t\t\t\t  \"Attempt to authorise additional certificate issue \"\n\t\t\t\t\t  \"when a certificate for this user has already been \"\n\t\t\t\t\t  \"issued\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Update the certificate store.  Since a revocation request generally \n\t   won't have any fields of any significance set we have to use a \n\t   special cut-down insert statement that doesn't expect to find any \n\t   fields except the certificate ID */\n\tif( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t{\n\t\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\t\tchar encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];\n\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\tif( hasBinaryBlobs( dbmsInfo ) )\n\t\t\t{\n\t\t\tsetBoundDataBlob( boundDataPtr, 1, certData, certDataLength );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint encodedCertDataLength;\n\t\t\t\n\t\t\tstatus = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE, \n\t\t\t\t\t\t\t\t   &encodedCertDataLength, certData, \n\t\t\t\t\t\t\t\t   certDataLength, CRYPT_CERTTYPE_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Couldn't base64-encode data\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tsetBoundData( boundDataPtr, 1, encodedCertData, \n\t\t\t\t\t\t  encodedCertDataLength );\n\t\t\t}\n\t\tstatus = dbmsUpdate( \n\t\t\t\t\"INSERT INTO certRequests VALUES (\"\n\t\t\t\tTEXT_CERTTYPE_REQUEST_REVOCATION \", '', '', '', '', '', '', \"\n\t\t\t\t\"'', ?, ?)\", boundDataPtr, DBMS_UPDATE_BEGIN );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = addCert( dbmsInfo, iCertRequest, CRYPT_CERTTYPE_REQUEST_CERT,\n\t\t\t\t\t\t  CERTADD_NORMAL, DBMS_UPDATE_BEGIN, errorInfo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateCertLog( dbmsInfo,\n\t\t\t\t\t\t( requestType == CRYPT_CERTTYPE_REQUEST_REVOCATION ) ? \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_REVOCATION : \\\n\t\t\t\t\t\t( isRenewal ) ? \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_RENEWAL : \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_CERT,\n\t\t\t\t\t\tcertID, certIDlength, reqCertIDptr, reqCertIDlength, \n\t\t\t\t\t\tNULL, 0, certData, certDataLength, \n\t\t\t\t\t\tDBMS_UPDATE_COMMIT );\n\t\t}\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate request add operation failed: \" ) );\n\t\t}\n\n\treturn( status );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/ca_clean.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib DBMS CA Cleanup Interface\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n/* When we iterate through the entries in the certificate store we have to \n   protect ourselves against repeatedly fetching the same value over and \n   over again if there's a problem with the certificate store, which we do \n   by remembering data from the previous certificate that we fetched.  The \n   following value defines the amount of certificate data that we record \n   (since this doesn't protect against Byzantine failures, we also maintain\n   an iteration counter that bails out after a certain number of iterations\n   are exceeded) */\n\n#define MAX_PREVCERT_DATA\t128\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete a certificate request or partially-issued certificated if a \n   cleanup operation for it failed, recording the failure details in the \n   log */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int deleteIncompleteRequest( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( reqCertIDlength ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *reqCertID, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int reqCertIDlength, \n\t\t\t\t\t\t\t\t\tIN_ERROR const int errorStatus,\n\t\t\t\t\t\t\t\t\tIN_STRING const char *reasonMessage )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isReadPtrDynamic( reqCertID, reqCertIDlength ) );\n\n\tANALYSER_HINT_STRING( reasonMessage );\n\n\tREQUIRES( isShortIntegerRangeNZ( reqCertIDlength ) );\n\tREQUIRES( cryptStatusError( errorStatus ) );\n\n\t/* Delete the request and record the cause */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );\n\tstatus = dbmsUpdate( \n\t\t\t\t\"DELETE FROM certRequests WHERE certID = ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\tupdateCertErrorLog( dbmsInfo, errorStatus, reasonMessage, NULL, 0, \n\t\t\t\t\t\tNULL, 0, reqCertID, reqCertIDlength, NULL, 0 );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int deleteIncompleteCert( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t\t const BOOLEAN isRenewal,\n\t\t\t\t\t\t\t\t IN_ERROR const int errorStatus,\n\t\t\t\t\t\t\t\t IN_STRING const char *reasonMessage )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE certID[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tint certIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tANALYSER_HINT_STRING( reasonMessage );\n\n\tREQUIRES( isRenewal == TRUE || isRenewal == FALSE );\n\tREQUIRES( cryptStatusError( errorStatus ) );\n\n\t/* Get the certID for the incomplete certificate to delete */\n\tstatus = dbmsQuery( isRenewal ? \\\n\t\t\t\t\"SELECT certID FROM certificates WHERE keyID LIKE '\" KEYID_ESC2 \"%'\" : \\\n\t\t\t\t\"SELECT certID FROM certificates WHERE keyID LIKE '\" KEYID_ESC1 \"%'\",\n\t\t\t\t\t\tcertID, MAX_QUERY_RESULT_SIZE, &certIDlength, NULL, \n\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Delete the request and record the cause */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\tstatus = dbmsUpdate( \n\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\tupdateCertErrorLog( dbmsInfo, errorStatus, reasonMessage, NULL, 0, \n\t\t\t\t\t\tNULL, 0, certID, certIDlength, NULL, 0 );\n\treturn( status );\n\t}\n\n/* Get a partially-issued certificate.  We have to perform the import\n   ourselves since it's marked as an incompletely-issued certificate and so \n   is invisible to accesses performed via the standard certificate fetch \n   routines */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getNextPartialCert( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t   INOUT_BUFFER_FIXED( prevCertDataMaxLen ) \\\n\t\t\t\t\t\t\t\t\tBYTE *prevCertData, \n\t\t\t\t\t\t\t   IN_LENGTH_FIXED( MAX_PREVCERT_DATA ) \\\n\t\t\t\t\t\t\t\t\tconst int prevCertDataMaxLen, \n\t\t\t\t\t\t\t   const BOOLEAN isRenewal )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBYTE certificate[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tchar encodedCertData[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tvoid *certPtr = hasBinaryBlobs( dbmsInfo ) ? \\\n\t\t\t\t\t( void * ) certificate : encodedCertData;\n\tint certSize, status;\t\t\t/* Cast needed for gcc */\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtrDynamic( prevCertData, prevCertDataMaxLen ) );\n\n\tREQUIRES( prevCertDataMaxLen == MAX_PREVCERT_DATA );\n\tREQUIRES( isRenewal == TRUE || isRenewal == FALSE );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* Find the next certificate and import it.  Although this would appear \n\t   to be fetching the same certificate over and over again, the caller \n\t   will be deleting the currently-fetched certificate after we return it \n\t   to them so in practice it fetches a new certificate each time (we\n\t   also perform a loop check on the prevCertData once we've fetched the\n\t   next certificate so we'll detect any looping fairly quickly) */\n\tstatus = dbmsQuery( isRenewal ? \\\n\t\t\t\t\"SELECT certData FROM certificates WHERE keyID LIKE '\" KEYID_ESC2 \"%'\" : \\\n\t\t\t\t\"SELECT certData FROM certificates WHERE keyID LIKE '\" KEYID_ESC1 \"%'\",\n\t\t\t\t\t\tcertPtr, MAX_QUERY_RESULT_SIZE, &certSize, NULL, \n\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\n\t\t/* We've processed all of the entries, this isn't an error */\n\t\tresetErrorInfo( dbmsInfo );\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tif( !hasBinaryBlobs( dbmsInfo ) )\n\t\t{\n\t\tstatus = base64decode( certificate, MAX_CERT_SIZE, &certSize,\n\t\t\t\t\t\t\t   encodedCertData, certSize, \n\t\t\t\t\t\t\t   CRYPT_CERTFORMAT_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't base64-decode data\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( certSize > 0 && certSize <= MAX_CERT_SIZE );\n\n\t/* If we're stuck in a loop fetching the same value over and over, make\n\t   an emergency exit */\n\tif( !memcmp( prevCertData, certificate, \\\n\t\t\t\t min( certSize, prevCertDataMaxLen ) ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t}\n\tmemcpy( prevCertData, certificate, \n\t\t\tmin( certSize, prevCertDataMaxLen ) );\n\n\t/* Reset the first byte of the certificate data from the not-present \n\t   magic value to allow it to be imported and create a certificate from \n\t   it */\n\tcertificate[ 0 ] = BER_SEQUENCE;\n\tsetMessageCreateObjectIndirectInfo( &createInfo, certificate, certSize,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t*iCertificate = createInfo.cryptHandle;\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCA Cleanup Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a cleanup operation on the certificate store, removing \n   incomplete, expired, and otherwise leftover certificates.  Since we're \n   cleaning up the certificate store we try and continue even if an error \n   occurs, at least up to a limit.  In addition to protect against Byzantine\n   failures we include an iteration counter and bail out after a certain \n   number of iterations.  This is a tradeoff between DoS protection and\n   bailing out too early, using FAILSAFE_ITERATIONS_LARGE is a reasonable\n   compromise */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint caCleanup( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE prevCertData[ MAX_PREVCERT_DATA + 8 ];\n\tBYTE certID[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tconst time_t currentTime = getTime();\n\tint certIDlength, errorCount, noEntriesProcessed, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( action == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_CLEANUP );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* If the time is screwed up we can't perform time-based cleanup\n\t   actions */\n\tif( action == CRYPT_CERTACTION_EXPIRE_CERT && \\\n\t\tcurrentTime <= MIN_TIME_VALUE )\n\t\tretIntError();\n\n\t/* Rumble through the certificate store either deleting leftover \n\t   requests or expiring every certificate which is no longer current */\n\tmemset( prevCertData, 0, MAX_PREVCERT_DATA );\n\tLOOP_LARGE( ( status = CRYPT_OK, errorCount = 0, noEntriesProcessed = 0 ),\n\t\t\t\tstatus != CRYPT_ERROR_NOTFOUND && errorCount < 5 && \\\n\t\t\t\t\tnoEntriesProcessed < 500,\n\t\t\t\tnoEntriesProcessed++ )\n\t\t{\n\t\t/* Find the certificate ID of the next expired certificate or next \n\t\t   certificate request (revocation requests are handled later by \n\t\t   completing the revocation).  Note that the select requires that \n\t\t   the database glue code be capable of returning a single result \n\t\t   and then finishing the query, for some back-ends there may be a \n\t\t   need to explicitly cancel the query after the first result is \n\t\t   returned if the database returns an entire result set */\n\t\tif( action == CRYPT_CERTACTION_EXPIRE_CERT )\n\t\t\t{\n\t\t\tinitBoundData( boundDataPtr );\n\t\t\tsetBoundDataDate( boundDataPtr, 0, &currentTime );\n\t\t\tstatus = dbmsQuery(\n\t\t\t\t\t\t\"SELECT certID FROM certificates WHERE validTo < ?\",\n\t\t\t\t\t\t\t\tcertID, MAX_QUERY_RESULT_SIZE, &certIDlength, \n\t\t\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = dbmsQuery(\n\t\t\t\t\t\t\"SELECT certID FROM certRequests WHERE type = \"\n\t\t\t\t\t\t\tTEXT_CERTTYPE_REQUEST_CERT,\n\t\t\t\t\t\t\t\tcertID, MAX_QUERY_RESULT_SIZE, &certIDlength, \n\t\t\t\t\t\t\t\tNULL, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed all of the entries this isn't an error */\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\tresetErrorInfo( dbmsInfo );\n\t\t\telse\n\t\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( certIDlength > MAX_PREVCERT_DATA )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate ID data too large\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tcertIDlength = MAX_PREVCERT_DATA;\n\t\t\t}\n\t\tif( !memcmp( prevCertData, certID, certIDlength ) )\n\t\t\t{\n\t\t\t/* We're stuck in a loop fetching the same value over and over,\n\t\t\t   make an emergency exit */\n\t\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tbreak;\n\t\t\t}\n\t\tREQUIRES( rangeCheck( certIDlength, 1, MAX_PREVCERT_DATA ) );\n\t\tmemcpy( prevCertData, certID, certIDlength );\n\n\t\t/* Clean up/expire the certificate.  Since CRYPT_CERTACTION_CLEANUP \n\t\t   is a composite action that encompasses a whole series of \n\t\t   operations we replace it with a more specific action code */\n\t\tstatus = updateCertLog( dbmsInfo,\n\t\t\t\t\t\t\t\t( action == CRYPT_CERTACTION_CLEANUP ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTACTION_RESTART_CLEANUP : action,\n\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, certID, certIDlength, \n\t\t\t\t\t\t\t\tNULL, 0, DBMS_UPDATE_BEGIN );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tinitBoundData( boundDataPtr );\n\t\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\t\tstatus = dbmsUpdate( ( action == CRYPT_CERTACTION_EXPIRE_CERT ) ? \\\n\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\" : \\\n\t\t\t\t\"DELETE FROM certRequests WHERE certID = ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_COMMIT );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Something went wrong, abort the transaction */\n\t\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\t\terrorCount++;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( errorCount >= 5 || noEntriesProcessed >= 500 )\n\t\t{\n\t\t/* It's hard to tell what type of error an iterationCount-exceeded\n\t\t   situation really is, in theory it's a software error (either in\n\t\t   cryptlib's fetch logic or in the dabatase) but because we could be\n\t\t   cleaning up a large number of entries (for example if it's \n\t\t   cleaning up the result of an app going into and endless loop and\n\t\t   requesting a large number of certificates) it's entirely possible \n\t\t   that this is isn't an abnormal situation. Because of this we \n\t\t   don't flag it as an internal error but simply warn in the debug \n\t\t   build, although we do bail out after a fixed limit */\n\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n\n\t/* If we ran into a problem, perform a fallback general delete of\n\t   entries that caused the problem */\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tif( action == CRYPT_CERTACTION_EXPIRE_CERT )\n\t\t\t{\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Expire operation \"\n\t\t\t\t\t\t\t\t   \"failed, performing fallback straight \"\n\t\t\t\t\t\t\t\t   \"delete\" );\n\t\t\tinitBoundData( boundDataPtr );\n\t\t\tsetBoundDataDate( boundDataPtr, 0, &currentTime );\n\t\t\tstatus = dbmsUpdate(\n\t\t\t\t\t\t\"DELETE FROM certificates WHERE validTo < ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Certificate request \"\n\t\t\t\t\t\t\t\t   \"cleanup operation failed, performing \"\n\t\t\t\t\t\t\t\t   \"fallback straight delete\" );\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\t\t\t\"DELETE FROM certRequests WHERE type = \"\n\t\t\t\t\t\t\tTEXT_CERTTYPE_REQUEST_CERT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Fallback straight \"\n\t\t\t\t\t\t\t\t   \"delete failed\" );\n\t\t}\n\n\t/* If it's an expiry action we've done the expired certificates, now \n\t   remove any stale CRL entries and exit.  If there are no CRL entries \n\t   in the expiry period this isn't an error, so we remap the error code \n\t   if necessary */\n\tif( action == CRYPT_CERTACTION_EXPIRE_CERT )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundDataDate( boundDataPtr, 0, &currentTime );\n\t\tstatus = dbmsUpdate(\n\t\t\t\t\t\"DELETE FROM CRLs WHERE expiryDate < ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tresetErrorInfo( dbmsInfo );\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Couldn't delete stale CRL entries from \"\n\t\t\t\t\t\t \"certificate store: \" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a restart, process any incompletely-issued certificates in the\n\t   same manner as the expiry/cleanup is handled.  Since we don't know at\n\t   what stage the issue process was interrupted we have to make a worst-\n\t   case assumption and do a full reversal as a compensating transaction\n\t   for an aborted certificate issue */\n\tmemset( prevCertData, 0, MAX_PREVCERT_DATA );\n\tLOOP_LARGE( ( status = CRYPT_OK, errorCount = 0, noEntriesProcessed = 0 ),\n\t\t\t\tstatus != CRYPT_ERROR_NOTFOUND && errorCount < 5 && \\\n\t\t\t\t\tnoEntriesProcessed < 500,\n\t\t\t\tnoEntriesProcessed++ )\n\t\t{\n\t\tCRYPT_CERTIFICATE iCertificate;\n\n\t\t/* Get the next partially-issued certificate */\n\t\tstatus = getNextPartialCert( dbmsInfo, &iCertificate, \n\t\t\t\t\t\t\t\t\t prevCertData, MAX_PREVCERT_DATA, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed all of the entries, we're done */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\tbreak;\n\n\t\t\t/* If we're stuck in a loop fetching the same value over and \n\t\t\t   over, make an emergency exit */\n\t\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's some other type of problem, clear it and continue */\n\t\t\tstatus = deleteIncompleteCert( dbmsInfo, FALSE, status, \n\t\t\t\t\t\t\t\t\t\t   \"Couldn't get partially-issued \"\n\t\t\t\t\t\t\t\t\t\t   \"certificate to complete issue, \"\n\t\t\t\t\t\t\t\t\t\t   \"deleting and continuing\" );\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* We found a certificate to revoke, complete the revocation */\n\t\tstatus = revokeCertDirect( dbmsInfo, iCertificate,\n\t\t\t\t\t\t\t\t   CRYPT_CERTACTION_CERT_CREATION_REVERSE,\n\t\t\t\t\t\t\t\t   errorInfo );\n\t\tkrnlSendNotifier( iCertificate, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( errorCount >= 5 || noEntriesProcessed >= 500 )\n\t\t{\n\t\t/* See note with earlier code */\n\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n\n\t/* If we ran into a problem, perform a fallback general delete of\n\t   entries that caused the problem */\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Partially-issued \"\n\t\t\t\t\t\t\t   \"certificate cleanup operation failed, \"\n\t\t\t\t\t\t\t   \"performing fallback straight delete\" );\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"DELETE FROM certificates WHERE keyID LIKE '\" KEYID_ESC1 \"%'\" );\n\t\tif( cryptStatusError( status ) )\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Fallback straight \"\n\t\t\t\t\t\t\t\t   \"delete failed\" );\n\t\t}\n\n\t/* Now process any partially-completed renewals */\n\tmemset( prevCertData, 0, MAX_PREVCERT_DATA );\n\tLOOP_LARGE( ( status = CRYPT_OK, errorCount = 0, noEntriesProcessed = 0 ),\n\t\t\t\tstatus != CRYPT_ERROR_NOTFOUND && errorCount < 5 && \\\n\t\t\t\t\tnoEntriesProcessed < 500,\n\t\t\t\tnoEntriesProcessed++ )\n\t\t{\n\t\tCRYPT_CERTIFICATE iCertificate;\n\n\t\t/* Get the next partially-completed certificate */\n\t\tstatus = getNextPartialCert( dbmsInfo, &iCertificate, \n\t\t\t\t\t\t\t\t\t prevCertData, MAX_PREVCERT_DATA, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed all of the entries, we're done */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\tbreak;\n\n\t\t\t/* If we're stuck in a loop fetching the same value over and \n\t\t\t   over, make an emergency exit */\n\t\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's some other type of problem, clear it and continue */\n\t\t\tstatus = deleteIncompleteCert( dbmsInfo, TRUE, status, \n\t\t\t\t\t\t\t\t\t\t   \"Couldn't get partially-renewed \"\n\t\t\t\t\t\t\t\t\t\t   \"certificate to complete renewal, \"\n\t\t\t\t\t\t\t\t\t\t   \"deleting and continuing\" );\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* We found a partially-completed certificate, complete the renewal */\n\t\tstatus = completeCertRenewal( dbmsInfo, iCertificate, errorInfo );\n\t\tkrnlSendNotifier( iCertificate, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( errorCount >= 5 || noEntriesProcessed >= 500 )\n\t\t{\n\t\t/* See note with earlier code */\n\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n\n\t/* Finally, process any pending revocations */\n\tmemset( prevCertData, 0, MAX_PREVCERT_DATA );\n\tLOOP_LARGE( ( status = CRYPT_OK, errorCount = 0, noEntriesProcessed = 0 ),\n\t\t\t\tstatus != CRYPT_ERROR_NOTFOUND && errorCount < 5 && \\\n\t\t\t\t\tnoEntriesProcessed < 500,\n\t\t\t\tnoEntriesProcessed++ )\n\t\t{\n\t\tCRYPT_CERTIFICATE iCertRequest;\n\t\tint dummy;\n\n\t\t/* Find the next revocation request and import it.  This is slightly\n\t\t   ugly since we could grab it directly by fetching the data based on\n\t\t   the request type field, but there's no way to easily get to the\n\t\t   low-level import functions from here so we have to first fetch the\n\t\t   certificate ID and then pass that down to the lower-level \n\t\t   functions to fetch the actual request */\n\t\tstatus = dbmsQuery(\n\t\t\t\t\t\"SELECT certID FROM certRequests WHERE type = \"\n\t\t\t\t\t\tTEXT_CERTTYPE_REQUEST_REVOCATION,\n\t\t\t\t\t\t\tcertID, MAX_QUERY_RESULT_SIZE, &certIDlength, \n\t\t\t\t\t\t\tNULL, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed all of the entries this isn't an error */\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\tresetErrorInfo( dbmsInfo );\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( certIDlength > MAX_PREVCERT_DATA )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Certificate ID data too large\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tcertIDlength = MAX_PREVCERT_DATA;\n\t\t\t}\n\t\tif( !memcmp( prevCertData, certID, certIDlength ) )\n\t\t\t{\n\t\t\t/* We're stuck in a loop fetching the same value over and over,\n\t\t\t   make an emergency exit */\n\t\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tbreak;\n\t\t\t}\n\t\tREQUIRES( rangeCheck( certIDlength, 1, MAX_PREVCERT_DATA ) );\n\t\tmemcpy( prevCertData, certID, certIDlength );\n\t\tstatus = getItemData( dbmsInfo, &iCertRequest, &dummy, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_REVREQUEST, CRYPT_IKEYID_CERTID, \n\t\t\t\t\t\t\t  certID, certIDlength, KEYMGMT_FLAG_NONE, \n\t\t\t\t\t\t\t  errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tstatus = \\\n\t\t\t\tdeleteIncompleteRequest( dbmsInfo, certID, certIDlength, status, \n\t\t\t\t\t\t\t\t\t\t \"Couldn't instantiate revocation \"\n\t\t\t\t\t\t\t\t\t\t \"request from stored data, deleting \"\n\t\t\t\t\t\t\t\t\t\t \"request and continuing\" );\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Complete the revocation */\n\t\tstatus = caRevokeCert( dbmsInfo, iCertRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t   CRYPT_CERTACTION_RESTART_REVOKE_CERT,\n\t\t\t\t\t\t\t   errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we get a not-found error this is an allowable condition \n\t\t\t   since the certificate may have expired or been otherwise \n\t\t\t   removed after the revocation request was received, so we \n\t\t\t   just delete the entry */\n\t\t\tstatus = \\\n\t\t\t\tdeleteIncompleteRequest( dbmsInfo, certID, certIDlength, status, \n\t\t\t\t\t\t\t\t\t\t ( status == CRYPT_ERROR_NOTFOUND ) ? \\\n\t\t\t\t\t\t\t\t\t\t \"Deleted revocation request for \"\n\t\t\t\t\t\t\t\t\t\t \"non-present certificate\" : \\\n\t\t\t\t\t\t\t\t\t\t \"Couldn't revoke certificate from \"\n\t\t\t\t\t\t\t\t\t\t \"revocation request, deleting \"\n\t\t\t\t\t\t\t\t\t\t \"request and continuing\" );\n\t\t\t}\n\t\tkrnlSendNotifier( iCertRequest, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( errorCount >= 5 || noEntriesProcessed >= 500 )\n\t\t{\n\t\t/* See note with earlier code */\n\t\tDEBUG_DIAG(( \"Certificate-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n\n\t/* If we ran into a problem, perform a fallback general delete of\n\t   entries that caused the problem */\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Revocation request \"\n\t\t\t\t\t\t\t   \"cleanup operation failed, performing \"\n\t\t\t\t\t\t\t   \"fallback straight delete\" );\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\t\t\"DELETE FROM certRequests WHERE type = \"\n\t\t\t\t\t\tTEXT_CERTTYPE_REQUEST_REVOCATION );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Fallback straight \"\n\t\t\t\t\t\t\t\t   \"delete failed\" );\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Revocation request cleanup operation failed: \" ) );\n\t\t\t}\n\t\t}\n\n\treturn( resetErrorInfo( dbmsInfo ) );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/ca_issue.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib DBMS CA Certificate Issue Interface\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the issue type (new request, renewal, etc) for a particular \n   certificate request or certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getCertIssueType( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t\t\t OUT_ENUM_OPT( CERTADD ) CERTADD_TYPE *issueType,\n\t\t\t\t\t\t\t const BOOLEAN isCert )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE certData[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, length, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( issueType, sizeof( CERTADD_TYPE ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( isCert == TRUE || isCert == FALSE );\n\n\t/* Clear return value */\n\t*issueType = CERTADD_NONE;\n\n\t/* Get the certID of the request that resulted in the certificate \n\t   creation */\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) && isCert )\n\t\t{\n\t\t/* If it's a certificate we have to apply an extra level of \n\t\t   indirection to get the request that resulted in its creation */\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT reqCertID FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\t\tcertData, MAX_QUERY_RESULT_SIZE, &length, \n\t\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( length > ENCODED_DBXKEYID_SIZE )\n\t\t\t\tlength = ENCODED_DBXKEYID_SIZE;\n\t\t\tREQUIRES( rangeCheck( length, 1, ENCODED_DBXKEYID_SIZE ) );\n\t\t\tmemcpy( certID, certData, length );\n\t\t\tcertIDlength = length;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Find out whether this was a certificate update by checking whether it \n\t   was added as a standard or renewal request, then set the update type\n\t   appropriately.  The comparison for the action type is a bit odd since\n\t   some back-ends will return the action as text and some as a binary\n\t   numeric value, rather than relying on the back-end glue code to\n\t   perform the appropriate conversion we just check for either value\n\t   type.\n\t   \n\t   In addition to performing this basic check in order to figure out how\n\t   the replacement process should be handled we could in theory also \n\t   check that an update really is a pure update with all other portions\n\t   of the certificate being identical, however there are two problems\n\t   with this.  The first is that we don't know when we get the request \n\t   how much of what's in the final certificate will be added by the CA \n\t   (in other words we'd have to check that the request is a proper \n\t   subset of the certificate that it's supposedly updating, which isn't \n\t   easily feasible).  The second, more important one is that if a client \n\t   really wants to change the certificate details then they can just use \n\t   a CRYPT_CERTACTION_REQUEST_CERT in place of a \n\t   CRYPT_CERTACTION_REQUEST_RENEWAL and change whatever details they \n\t   want.  The distinction between the two is really just an artefact of \n\t   CMP's messaging, and as usual the CMP spec confuses the issue \n\t   completely, with varied discussions of updating a key vs. updating a \n\t   certificate vs. obtaining a certificate.  Because of this there \n\t   doesn't seem to be anything to be gained by performing whatever it is \n\t   that we could be checking for here */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\tstatus = dbmsQuery(\n\t\t\"SELECT action FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\tcertData, MAX_QUERY_RESULT_SIZE, &length, \n\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( certData[ 0 ] )\n\t\t{\n\t\tcase CRYPT_CERTACTION_REQUEST_CERT:\n\t\tcase TEXTCH_CERTACTION_REQUEST_CERT:\n\t\t\t*issueType = CERTADD_PARTIAL;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_CERTACTION_REQUEST_RENEWAL:\n\t\tcase TEXTCH_CERTACTION_REQUEST_RENEWAL:\n\t\t\t*issueType = CERTADD_PARTIAL_RENEWAL;\n\t\t\treturn( CRYPT_OK );\n\n\t\tdefault:\n\t\t\tDEBUG_DIAG(( \"Unknown certificate action type %d\", \n\t\t\t\t\t\t certData[ 0 ] ));\n\t\t\tassert( DEBUG_WARN );\n\t\t}\n\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/* Sanitise a new certificate of potentially dangerous attributes by \n   creating a template of the disallowed values and setting them as blocked \n   attributes.  For our use we clear all CA and CA-equivalent attributes to \n   prevent users from submitting requests that turn them into CAs */\n\nCHECK_RETVAL \\\nstatic int sanitiseCertAttributes( IN_HANDLE const CRYPT_CERTIFICATE iCertificate )\n\t{\n\tCRYPT_CERTIFICATE iTemplateCertificate;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiTemplateCertificate = createInfo.cryptHandle;\n\n\t/* Add as disallowed values the CA flag and and CA keyUsages, and any \n\t   CA-equivalent values, in this case the old Netscape usage flags which \n\t   (incredibly) are still used today by some CAs in place of the X.509 \n\t   keyUsage extension.  We can only do the latter if use of the obsolete \n\t   Netscape extensions is enabled, by default these are disabled so they \n\t   can still be sneaked in as blob attributes, but only if the user has\n\t   enabled the (disabled-by-default) \n\t   CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES option.\n\t   \n\t   The disabling of the CA flag isn't really necessary since the entire\n\t   basicConstraints extension is disallowed in certificate requests, \n\t   we only have it here for belt-and-suspenders security.\n\t   \n\t   Note that the blocked-attributes check currently assumes that the \n\t   value being checked for non-permitted values is a keyUsage-style \n\t   bitflag (since almost no attributes are allowed in certificate\n\t   requests for security purposes), if any other data types are blocked \n\t   then the checking will have to be extended to handle these */\n\tstatus = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_CERTINFO_CA );\n#ifdef USE_CERT_OBSOLETE\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatic const int value = CRYPT_NS_CERTTYPE_SSLCA | \\\n\t\t\t\t\t\t\t\t CRYPT_NS_CERTTYPE_SMIMECA | \\\n\t\t\t\t\t\t\t\t CRYPT_NS_CERTTYPE_OBJECTSIGNINGCA;\n\n\t\tstatus = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &value, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_NS_CERTTYPE );\n\t\t}\n#endif /* USE_CERT_OBSOLETE */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatic const int value = KEYUSAGE_CA;\n\n\t\tstatus = krnlSendMessage( iTemplateCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &value, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iTemplateCertificate,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_BLOCKEDATTRS );\n\t\t}\n\tif( status == CRYPT_ERROR_INVALID )\n\t\t{\n\t\t/* If the request would have resulted in the creation of an invalid \n\t\t   certificate, report it as an error with the request */\n\t\tstatus = CAMGMT_ARGERROR_REQUEST;\n\t\t}\n\tkrnlSendNotifier( iTemplateCertificate, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n\n/* Make sure that an about-to-be-issued certificate hasn't been added to the \n   certificate store yet.  In theory we wouldn't need to do this since the \n   keyID uniqueness constraint will catch duplicates, however duplicates are \n   allowed for updates and won't automatically be caught for partial adds \n   because the keyID has to be added in a special form to enable the \n   completion of the partial add to work.  What we therefore need to check \n   for is that a partial add (which will add the keyID in special form) \n   won't in the future clash with a keyID in standard form.  The checking \n   for a keyID clash in special form happens automagically through the \n   uniqueness constraint.\n\n   There are two special cases in which the issue can fail during the \n   completion rather than initial add phase, one is during an update (which \n   can't be avoided, since clashes are legal for this and we can't resolve \n   things until the completion phase) and the other is through a race \n   condition caused by the following sequence of updates:\n\n\t1: check keyID -> OK\n\t2: check keyID -> OK\n\t1: add as ESC1+keyID\n\t1: issue as keyID\n\t2: add as ESC1+keyID\n\t2: issue -> fails\n\n   This condition will be fairly rare.  Note that in neither case are the \n   integrity constraints of the certificate issuing process violated, the \n   only thing that happens is that a failure due to duplicates is detected \n   at a later stage than it normally would be */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDuplicateAdd( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iLocalCertificate, \n\t\t\t\t\t\t\t  IN_ENUM( CERTADD ) const CERTADD_TYPE issueType )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar keyID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint keyIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iLocalCertificate ) );\n\tREQUIRES( isEnumRange( issueType, CERTADD ) );\n\n\t/* If it's a normal certificate issue then there's no problem with the\n\t   potential presence of pseudo-duplicates */\n\tif( issueType != CERTADD_PARTIAL )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether a certificate with this keyID is already present in the \n\t   store */\n\tstatus = getCertKeyID( keyID, ENCODED_DBXKEYID_SIZE, &keyIDlength, \n\t\t\t\t\t\t   iLocalCertificate );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, keyID, keyIDlength );\n\tstatus = dbmsQuery( \\\n\t\t\t\t\"SELECT certData FROM certificates WHERE keyID = ?\",\n\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr, \n\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );\n\tresetErrorInfo( dbmsInfo );\n\treturn( cryptStatusOK( status ) ? CRYPT_ERROR_DUPLICATE : CRYPT_OK );\n\t}\n\n/* Replace one certificate (usually a partially-issued one) with another \n   (usually its completed form).  The types of operations and their \n   corresponding add-type values are:\n\n\tESC1 -> std\t\tCERTADD_PARTIAL\t\t\t\tCompletion of partial\n\tESC1 -> ESC2\tCERTADD_PARTIAL_RENEWAL\t\tFirst half of renewal\n\tESC2 -> std\t\tCERTADD_RENEWAL_COMPLETE\tSecond half of renewal */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completeCert( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t\t IN_ENUM( CERTADD ) const CERTADD_TYPE addType,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( addType == CERTADD_PARTIAL || \\\n\t\t\t  addType == CERTADD_PARTIAL_RENEWAL || \\\n\t\t\t  addType == CERTADD_RENEWAL_COMPLETE );\n\tREQUIRES( errorInfo != NULL );\n\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = addCert( dbmsInfo, iCertificate, CRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t  ( addType == CERTADD_PARTIAL_RENEWAL ) ? \\\n\t\t\t\t\t\tCERTADD_PARTIAL_RENEWAL : CERTADD_NORMAL,\n\t\t\t\t\t  DBMS_UPDATE_BEGIN, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tchar specialCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\n\t\t/* Turn the general certID into the form required for special-case\n\t\t   certificate data by overwriting the first two bytes with an out-\n\t\t   of-band value */\n\t\tREQUIRES( rangeCheck( certIDlength, 0, ENCODED_DBXKEYID_SIZE ) );\n\t\tmemcpy( specialCertID, ( addType == CERTADD_RENEWAL_COMPLETE ) ? \\\n\t\t\t\tKEYID_ESC2 : KEYID_ESC1, KEYID_ESC_SIZE );\n\t\tmemcpy( specialCertID + KEYID_ESC_SIZE, certID + KEYID_ESC_SIZE, \n\t\t\t\tcertIDlength - KEYID_ESC_SIZE );\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, specialCertID, certIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr,\n\t\t\t\t\t\t\t ( addType == CERTADD_PARTIAL_RENEWAL ) ? \\\n\t\t\t\t\t\t\t DBMS_UPDATE_COMMIT : DBMS_UPDATE_CONTINUE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( addType != CERTADD_PARTIAL_RENEWAL )\n\t\t\t{\n\t\t\tstatus = updateCertLog( dbmsInfo,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTACTION_CERT_CREATION_COMPLETE,\n\t\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, certID, certIDlength, \n\t\t\t\t\t\t\t\t\tNULL, 0, DBMS_UPDATE_COMMIT );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\t}\n\n\t/* If the operation failed, record the details */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tupdateCertErrorLog( dbmsInfo, status,\n\t\t\t\t\t\t\t\"Certificate creation - completion operation \"\n\t\t\t\t\t\t\t\"failed\", NULL, 0, NULL, 0, \n\t\t\t\t\t\t\tcertID, certIDlength, NULL, 0 );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate creation - completion operation \"\n\t\t\t\t\t \"failed: \" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Issue Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Complete a certificate renewal operation by revoking the certificate to \n   be replaced and replacing it with the newly-issued certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint completeCertRenewal( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iReplaceCertificate,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iOrigCertificate DUMMY_INIT;\n\tchar keyID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint keyIDlength, dummy, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iReplaceCertificate ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Extract the key ID from the new certificate and use it to fetch the \n\t   existing certificate issued for the same key */\n\tstatus = getCertKeyID( keyID, ENCODED_DBXKEYID_SIZE, &keyIDlength, \n\t\t\t\t\t\t   iReplaceCertificate );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getItemData( dbmsInfo, &iOrigCertificate, &dummy,\n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY, CRYPT_IKEYID_KEYID, \n\t\t\t\t\t\t\t  keyID, keyIDlength, KEYMGMT_FLAG_NONE, \n\t\t\t\t\t\t\t  errorInfo );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* If the original certificate fetch fails with a notfound error \n\t\t\t   this is OK since we may be resuming from a point where the \n\t\t\t   revocation has already occurred or the certificate may have \n\t\t\t   already expired or been otherwise replaced, so we just slide \n\t\t\t   in the new certificate */\n\t\t\treturn( completeCert( dbmsInfo, iReplaceCertificate,\n\t\t\t\t\t\t\t\t  CERTADD_RENEWAL_COMPLETE, errorInfo ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't get information for the certificate to be \"\n\t\t\t\t\t \"renewed: \" ) );\n\t\t}\n\n\t/* Replace the original certificate with the new one */\n\tstatus = revokeCertDirect( dbmsInfo, iOrigCertificate,\n\t\t\t\t\t\t\t   CRYPT_CERTACTION_REVOKE_CERT, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = completeCert( dbmsInfo, iReplaceCertificate,\n\t\t\t\t\t\t\t   CERTADD_RENEWAL_COMPLETE, errorInfo );\n\t\t}\n\tkrnlSendNotifier( iOrigCertificate, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n\n/* Issue a certificate from a certificate request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint caIssueCert( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE caKey,\n\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iLocalCertificate;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tCERTADD_TYPE addType = CERTADD_NORMAL, issueType;\n\tint certDataLength DUMMY_INIT, issuerIDlength, certIDlength;\n\tint reqCertIDlength DUMMY_INIT, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( iCertificate == NULL ) || \\\n\t\t\tisWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( isHandleRangeValid( caKey ) );\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES( action == CRYPT_CERTACTION_ISSUE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\tif( iCertificate != NULL )\n\t\t*iCertificate = CRYPT_ERROR;\n\n\t/* Extract the information that we need from the certificate request */\n\tstatus = getCertIssueType( dbmsInfo, iCertRequest, &issueType, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t   &reqCertIDlength, iCertRequest, \n\t\t\t\t\t\t   CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( cryptArgError( status ) )\n\t\t\tstatus = CAMGMT_ARGERROR_REQUEST;\n\t\tretExtArg( status, \n\t\t\t\t   ( status, errorInfo, \n\t\t\t\t\t \"Couldn't extract certificate request information \"\n\t\t\t\t\t \"needed to issue certificate\" ) );\n\t\t}\n\n\t/* We're ready to perform the certificate issue transaction.  First we \n\t   turn the request into a certificate */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalCertificate = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iLocalCertificate, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCertRequest,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTREQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't create certificate from certificate request \"\n\t\t\t\t  \"data\" ) );\n\t\t}\n\n\t/* Sanitise the new certificate of potentially dangerous attributes */\n\tstatus = sanitiseCertAttributes( iLocalCertificate );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tretExtArg( status, \n\t\t\t\t   ( status, errorInfo, \n\t\t\t\t\t \"Certificate request contains attributes that would \"\n\t\t\t\t\t \"result in the creation of a CA rather than a normal \"\n\t\t\t\t\t \"user certificate\" ) );\n\t\t}\n\n\t/* Finally, sign the certificate */\n\tstatus = krnlSendMessage( iLocalCertificate, IMESSAGE_CRT_SIGN, NULL,\n\t\t\t\t\t\t\t  caKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tif( status == CRYPT_ARGERROR_VALUE )\n\t\t\tstatus = CAMGMT_ARGERROR_CAKEY;\n\t\tretExtArg( status, \n\t\t\t\t   ( status, errorInfo, \n\t\t\t\t\t \"Couldn't sign certificate created from certificate \"\n\t\t\t\t\t \"request\" ) );\n\t\t}\n\n\t/* Extract the information that we need from the newly-created \n\t   certificate */\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iLocalCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getKeyID( issuerID, ENCODED_DBXKEYID_SIZE, &issuerIDlength, \n\t\t\t\t\t\t   iLocalCertificate,\n\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = extractCertData( iLocalCertificate, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, certData, \n\t\t\t\t\t\t\t\t  MAX_CERT_SIZE, &certDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't extract new certificate data to add to \"\n\t\t\t\t  \"certificate store\" ) );\n\t\t}\n\n\t/* If we're doing a partial certificate creation, handle the \n\t   complexities created by things like certificate renewals that create \n\t   pseudo-duplicates while the update is taking place */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION )\n\t\t{\n\t\tstatus = checkDuplicateAdd( dbmsInfo, iLocalCertificate, issueType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Certificate already exists in certificate store\" ) );\n\t\t\t}\n\n\t\t/* This is a partial add, make sure that the certificate is added in \n\t\t   the appropriate manner */\n\t\taddType = CERTADD_PARTIAL;\n\t\t}\n\n\t/* Update the certificate store */\n\tstatus = addCert( dbmsInfo, iLocalCertificate, CRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t  addType, DBMS_UPDATE_BEGIN, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateCertLog( dbmsInfo, action, certID, certIDlength, \n\t\t\t\t\t\t\t\treqCertID, reqCertIDlength, NULL, 0,\n\t\t\t\t\t\t\t\tcertData, certDataLength,\n\t\t\t\t\t\t\t\tDBMS_UPDATE_CONTINUE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM certRequests WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_COMMIT );\n\t\t}\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\t}\n\n\t/* If the operation failed, record the details */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tupdateCertErrorLog( dbmsInfo, status,\n\t\t\t\t\t\t\t( action == CRYPT_CERTACTION_ISSUE_CERT ) ? \\\n\t\t\t\t\t\t\t\t\"Certificate issue operation failed\" : \\\n\t\t\t\t\t\t\t\t\"Certificate creation operation failed\",\n\t\t\t\t\t\t\tNULL, 0, reqCertID, reqCertIDlength, NULL, 0, \n\t\t\t\t\t\t\tNULL, 0 );\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t ( action == CRYPT_CERTACTION_ISSUE_CERT ) ? \\\n\t\t\t\t\t\t\"Certificate issue operation failed: \" : \\\n\t\t\t\t\t\t\"Certificate creation operation failed: \" ) );\n\t\t}\n\n\t/* The certificate has been successfully issued, return it to the caller \n\t   if necessary */\n\tif( iCertificate != NULL )\n\t\t*iCertificate = iLocalCertificate;\n\telse\n\t\t{\n\t\t/* The caller isn't interested in the certificate, destroy it */\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete a previously-started certificate issue */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint caIssueCertComplete( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t\t IN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION_DROP || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Extract the information that we need from the certificate */\n\tstatus = getKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength, \n\t\t\t\t\t   iCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're completing the certificate issue process, replace the\n\t   incomplete certificate with the completed one and exit */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE )\n\t\t{\n\t\tCERTADD_TYPE issueType;\n\n\t\tstatus = getCertIssueType( dbmsInfo, iCertificate, &issueType, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't get original certificate issue type to \"\n\t\t\t\t\t  \"complete certificate issue operation: \" ) );\n\t\t\t}\n\t\tstatus = completeCert( dbmsInfo, iCertificate, issueType, errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If we're doing a certificate renewal, complete the multi-phase \n\t\t   update required to replace an existing certificate */\n\t\tif( issueType == CERTADD_PARTIAL_RENEWAL )\n\t\t\t{\n\t\t\treturn( completeCertRenewal( dbmsInfo, iCertificate, \n\t\t\t\t\t\t\t\t\t\t errorInfo ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're abandoning the certificate issue process, delete the\n\t   incomplete certificate and exit */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_DROP )\n\t\t{\n\t\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\t\tchar incompleteCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\n\t\t/* Turn the general certID into the form required for special-case\n\t\t   certificate data by overwriting the first two bytes with an out-\n\t\t   of-band value, then delete the object with that ID */\n\t\tREQUIRES( rangeCheck( certIDlength, 0, ENCODED_DBXKEYID_SIZE ) );\n\t\tmemcpy( incompleteCertID, KEYID_ESC1, KEYID_ESC_SIZE );\n\t\tmemcpy( incompleteCertID + KEYID_ESC_SIZE, certID + KEYID_ESC_SIZE, \n\t\t\t\tcertIDlength - KEYID_ESC_SIZE );\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, incompleteCertID, certIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_BEGIN );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = updateCertLog( dbmsInfo, action, NULL, 0, NULL, 0, \n\t\t\t\t\t\t\t\t\tcertID, certIDlength, NULL, 0, \n\t\t\t\t\t\t\t\t\tDBMS_UPDATE_COMMIT );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Something went wrong, abort the transaction */\n\t\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* The drop operation failed, record the details and fall back to a\n\t\t   straight delete */\n\t\tupdateCertErrorLog( dbmsInfo, status,\n\t\t\t\t\t\t\t\"Certificate creation - drop operation failed, \"\n\t\t\t\t\t\t\t\"performing straight delete\", NULL, 0, NULL, 0, \n\t\t\t\t\t\t\tcertID, certIDlength, NULL, 0 );\n\t\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, status, \"Fallback straight \"\n\t\t\t\t\t\t\t\t   \"delete failed\" );\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Certificate creation - drop operation failed: \" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We're reversing a certificate creation as a compensating transaction \n\t   for an aborted certificate issue, we need to explicitly revoke the \n\t   certificate rather than just deleting it */\n\tENSURES( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\n\treturn( revokeCertDirect( dbmsInfo, iCertificate,\n\t\t\t\t\t\t\t  CRYPT_CERTACTION_CERT_CREATION_REVERSE, \n\t\t\t\t\t\t\t  errorInfo ) );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/ca_misc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib DBMS CA Certificate Misc Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\t\t/* For snprintf() */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if 0\n\n/* Get the ultimate successor certificate for one that's been superseded */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getSuccessorCert( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t IN_BUFFER( initialCertIDlength ) \\\n\t\t\t\t\t\t\t\tconst char *initialCertID,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int initialCertIDlength )\n\t{\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint chainingLevel, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( *iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( initialCertID, initialCertIDlength ) );\n\n\t/* Walk through the chain of renewals in the certificate store log until \n\t   we find the ultimate successor certificate to the current one */\n\tREQUIRES( rangeCheck( initialCertIDlength, 1, ENCODED_DBXKEYID_SIZE ) );\n\tmemcpy( certID, initialCertID, initialCertIDlength );\n\tLOOP_MED( ( chainingLevel = 0, status = CRYPT_ERROR_NOTFOUND ),\n\t\t\t  status == CRYPT_ERROR_NOTFOUND && chainingLevel < 32,\n\t\t\t  chainingLevel++ )\n\t\t{\n\t\tBYTE keyCertID[ DBXKEYID_SIZE + 8 ];\n\t\tchar certData[ MAX_QUERY_RESULT_SIZE + 8 ];\n\t\tint certDataLength, length, dummy;\n\n\t\t/* Find the request to renew this certificate */\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT certID FROM certLog WHERE subjCertID = ? \"\n\t\t\t\"AND action = \" TEXT_CERTACTION_REQUEST_RENEWAL,\n\t\t\t\t\t\t\tcertData, &certDataLength, certID,\n\t\t\t\t\t\t\tstrlen( certID ), 0, DBMS_CACHEDQUERY_NONE,\n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Find the resulting certificate */\n\t\tmemcpy( certID, certData,\n\t\t\t\tmin( certDataLength, ENCODED_DBXKEYID_SIZE + 1 ) );\n\t\tcertID[ MAX_ENCODED_DBXKEYID_SIZE ] = '\\0';\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT certID FROM certLog WHERE reqCertID = ? \"\n\t\t\t\t\"AND action = \" TEXT_CERTACTION_CERT_CREATION,\n\t\t\t\t\t\t\tcertData, &certDataLength, certID,\n\t\t\t\t\t\t\tstrlen( certID ), 0, DBMS_CACHEDQUERY_NONE,\n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = length = \\\n\t\t\t\tbase64decode( keyCertID, certData,\n\t\t\t\t\t\t\t  min( certDataLength, ENCODED_DBXKEYID_SIZE ),\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_NONE );\n\t\t\tassert( !cryptStatusError( status ) );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Try and get the replacement certificate */\n\t\tstatus = getItemData( dbmsInfo, iCertificate, &dummy,\n\t\t\t\t\t\t\t  getKeyName( CRYPT_IKEYID_CERTID ),\n\t\t\t\t\t\t\t  keyCertID, length, KEYMGMT_ITEM_PUBLICKEY,\n\t\t\t\t\t\t\t  KEYMGMT_FLAG_NONE, errorInfo );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( chainingLevel >= 32 )\n\t\t{\n\t\t/* We've chained through too many entries, bail out */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\treturn( status );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tLogging Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add an entry to the CA log */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint updateCertLog( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action, \n\t\t\t\t   IN_BUFFER_OPT( certIDlength ) const char *certID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int certIDlength,\n\t\t\t\t   IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int reqCertIDlength,\n\t\t\t\t   IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int subjCertIDlength,\n\t\t\t\t   IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int dataLength, \n\t\t\t\t   IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];\n\tchar certIDbuffer[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];\n\tconst time_t boundDate = getApproxTime();\n\tint localCertIDlength = certIDlength, sqlOffset, sqlLength, boundDataIndex;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( certID, certIDlength ) );\n\tassert( ( reqCertID == NULL && reqCertIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( reqCertID, reqCertIDlength ) );\n\tassert( ( subjCertID == NULL && subjCertIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( subjCertID, subjCertIDlength ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\t\n\tREQUIRES( isEnumRange( action, CRYPT_CERTACTION ) );\n\tREQUIRES( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\t  ( certID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certIDlength ) ) );\n\tREQUIRES( ( reqCertID == NULL && reqCertIDlength == 0 ) || \\\n\t\t\t  ( reqCertID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( reqCertIDlength ) ) );\n\tREQUIRES( ( subjCertID == NULL && subjCertIDlength == 0 ) || \\\n\t\t\t  ( subjCertID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( subjCertIDlength ) ) );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( dataLength ) ) );\n\tREQUIRES( isEnumRange( updateType, DBMS_UPDATE ) );\n\n\t/* Build up the necessary SQL format string required to insert the log\n\t   entry.  This is complicated somewhat by the fact that some of the\n\t   values may be NULL so we have to insert them by naming the columns\n\t   (some databases allow the use of the DEFAULT keyword but this isn't\n\t   standardised enough to be safe) */\n\tstrlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE,\n\t\t\t  \"INSERT INTO certLog (action, actionTime, certID\" );\n\tif( reqCertID != NULL )\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \", reqCertID\" );\n\tif( subjCertID != NULL )\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \", subjCertID\" );\n\tif( data != NULL )\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \", certData\" );\n\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \") VALUES (\" );\n\tsqlOffset = strlen( sqlBuffer );\n\tsqlLength = MAX_SQL_QUERY_SIZE - sqlOffset;\n\tsprintf_s( sqlBuffer + sqlOffset, sqlLength, \"%d, ?, ?\", action );\n\tif( reqCertID != NULL )\n\t\tstrlcat_s( sqlBuffer + sqlOffset, sqlLength, \", ?\" );\n\tif( subjCertID != NULL )\n\t\tstrlcat_s( sqlBuffer + sqlOffset, sqlLength, \", ?\" );\n\tif( data != NULL )\n\t\tstrlcat_s( sqlBuffer + sqlOffset, sqlLength, \", ?\" );\n\tstrlcat_s( sqlBuffer + sqlOffset, sqlLength, \")\" );\n\n\t/* If we're not worried about the certID we just insert a nonce value\n\t   which is used to meet the constraints for a unique entry.  In order\n\t   to ensure that it doesn't clash with a real certID we set the first\n\t   four characters to an out-of-band value */\n\tif( certID == NULL )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE nonce[ KEYID_SIZE + 8 ];\n\t\tint status;\n\n\t\tsetMessageData( &msgData, nonce, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = base64encode( certIDbuffer, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t\t   &localCertIDlength, nonce, DBXKEYID_SIZE, \n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Normally this is a should-never-occur error, however if\n\t\t\t   cryptlib has been shut down from another thread the kernel\n\t\t\t   will fail all non shutdown-related calls with a permission\n\t\t\t   error.  To avoid false alarms, we mask out failures due to\n\t\t\t   permission errors */\n\t\t\tassert( ( status == CRYPT_ERROR_PERMISSION ) || DEBUG_WARN );\n\t\t\treturn( status );\n\t\t\t}\n\t\tmemset( certIDbuffer, '-', 4 );\n\t\tcertID = certIDbuffer;\n\t\t}\n\n\t/* Set up the parameter information and update the certificate store \n\t   log */\n\tinitBoundData( boundDataPtr );\n\tsetBoundDataDate( boundDataPtr, 0, &boundDate );\n\tsetBoundData( boundDataPtr, 1, certID, localCertIDlength );\n\tboundDataIndex = 2;\n\tif( reqCertID != NULL )\n\t\tsetBoundData( boundDataPtr, boundDataIndex++, reqCertID, \n\t\t\t\t\t  reqCertIDlength );\n\tif( subjCertID != NULL )\n\t\tsetBoundData( boundDataPtr, boundDataIndex++, subjCertID, \n\t\t\t\t\t  subjCertIDlength );\n\tif( data != NULL )\n\t\t{\n\t\tif( hasBinaryBlobs( dbmsInfo ) )\n\t\t\t{\n\t\t\tsetBoundDataBlob( boundDataPtr, boundDataIndex, \n\t\t\t\t\t\t\t  data, dataLength );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint encodedDataLength, status;\n\n\t\t\tstatus = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE,\n\t\t\t\t\t\t\t\t   &encodedDataLength, data, dataLength, \n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Couldn't base64-encode data\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tsetBoundData( boundDataPtr, boundDataIndex, \n\t\t\t\t\t\t  encodedCertData, encodedDataLength );\n\t\t\t}\n\t\t}\n\treturn( dbmsUpdate( sqlBuffer, boundDataPtr, updateType ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateCertErrorLog( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\tIN_ERROR const int errorStatus,\n\t\t\t\t\t\tIN_STRING const char *errorString, \n\t\t\t\t\t\tIN_BUFFER_OPT( certIDlength ) const char *certID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int reqCertIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int subjCertIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataLength )\n\t{\n\tSTREAM stream;\n\tBYTE errorData[ 64 + MAX_CERT_SIZE + 8 ];\n\tconst int errorStringLength = strlen( errorString );\n\tint errorDataLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( certID, certIDlength ) );\n\tassert( ( reqCertID == NULL && reqCertIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( reqCertID, reqCertIDlength ) );\n\tassert( ( subjCertID == NULL && subjCertIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( subjCertID, subjCertIDlength ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tANALYSER_HINT_STRING( errorString );\n\n\tREQUIRES( cryptStatusError( errorStatus ) );\n\tREQUIRES( errorString != NULL );\n\tREQUIRES( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\t  ( certID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( certIDlength ) ) );\n\tREQUIRES( ( reqCertID == NULL && reqCertIDlength == 0 ) || \\\n\t\t\t  ( reqCertID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( reqCertIDlength ) ) );\n\tREQUIRES( ( subjCertID == NULL && subjCertIDlength == 0 ) || \\\n\t\t\t  ( subjCertID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( subjCertIDlength ) ) );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( dataLength ) ) );\n\n\t/* Encode the error information:\n\n\t\tSEQUENCE {\n\t\t\terrorStatus\tINTEGER,\n\t\t\terrorString\tUTF8String,\n\t\t\tcertData\tANY OPTIONAL\n\t\t\t} \n\n\t   Note that the buffer we use is slightly larger than MAX_CERT_SIZE in \n\t   order to accomodate the error status information alongside the \n\t   largest possible certificate, in theory this means that if the database\n\t   back-end doesn't support binary blobs there won't be enough room in\n\t   the logging code to text-encode this worst-case scenario, but the use\n\t   of non-binary-blob capable database should be fairly rare so it's \n\t   easier to just rely on the logging code to catch this unlikely \n\t   scenario than to try and special-case around it */\n\tsMemOpen( &stream, errorData, 64 + MAX_CERT_SIZE );\n\twriteSequence( &stream, sizeofShortInteger( -errorStatus ) + \\\n\t\t\t\t\t\t\tsizeofShortObject( errorStringLength ) + \\\n\t\t\t\t\t\t\tdataLength );\n\twriteShortInteger( &stream, -errorStatus, DEFAULT_TAG );\n\tstatus = writeCharacterString( &stream, errorString, errorStringLength,\n\t\t\t\t\t\t\t\t   BER_STRING_UTF8 );\n\tif( dataLength > 0 )\n\t\tstatus = swrite( &stream, data, dataLength );\n\tif( cryptStatusOK( status ) )\n\t\terrorDataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemOpen( &stream, errorData, MAX_CERT_SIZE );\n\t\twriteSequence( &stream, sizeofObject( 1 ) + sizeofObject( 31 ) );\n\t\twriteShortInteger( &stream, -( CRYPT_ERROR_FAILED ), DEFAULT_TAG );\n\t\tstatus = writeCharacterString( &stream, \n\t\t\t\t\t\t\t\t\t   \"Error writing error information\", 31,\n\t\t\t\t\t\t\t\t\t   BER_STRING_UTF8 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\terrorDataLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Update the certificate store log with the error information as the \n\t   data value */\n\treturn( updateCertLog( dbmsInfo, CRYPT_CERTACTION_ERROR, \n\t\t\t\t\t\t   certID, certIDlength, reqCertID, reqCertIDlength, \n\t\t\t\t\t\t   subjCertID, subjCertIDlength, \n\t\t\t\t\t\t   errorData, errorDataLength, DBMS_UPDATE_NORMAL ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateCertErrorLogMsg( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t   IN_ERROR const int errorStatus,\n\t\t\t\t\t\t   IN_STRING const char *errorString )\n\t{\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\treturn( updateCertErrorLog( dbmsInfo, errorStatus, errorString,\n\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, NULL, 0, NULL, 0 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous CA Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the PKI user that originally authorised the issuance of a certificate.  \n   This can involve chaining back through multiple generations of \n   certificates, for example to check authorisation on a revocation request \n   we might have to go through:\n\n\trev_req:\tget reqCertID = update_req\n\tupdate_req:\tget reqCertID = cert_req\n\tcert_req:\tget reqCertID = init_req\n\tinit_req:\tget reqCertID = pki_user */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint caGetIssuingUser( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iPkiUser,\n\t\t\t\t\t  IN_BUFFER( initialCertIDlength ) const char *initialCertID, \n\t\t\t\t\t  IN_LENGTH_FIXED( ENCODED_DBXKEYID_SIZE ) \\\n\t\t\t\t\t\t\tconst int initialCertIDlength, \n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, chainingLevel, dummy, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( iPkiUser, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtr( initialCertID, ENCODED_DBXKEYID_SIZE ) );\n\n\tREQUIRES( initialCertIDlength == ENCODED_DBXKEYID_SIZE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\t*iPkiUser = CRYPT_ERROR;\n\n\t/* Walk through the chain of updates in the certificate store log until \n\t   we find the PKI user that authorised the first certificate issue */\n\tREQUIRES( rangeCheck( initialCertIDlength, 1, ENCODED_DBXKEYID_SIZE ) );\n\tmemcpy( certID, initialCertID, initialCertIDlength );\n\tcertIDlength = initialCertIDlength;\n\tLOOP_MED( chainingLevel = 0, chainingLevel < 32, chainingLevel++ )\n\t\t{\n\t\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ];\n\t\tBOUND_DATA *boundDataPtr = boundData;\n\t\tBYTE certData[ MAX_QUERY_RESULT_SIZE + 8 ];\n\t\tint certDataLength;\n\n\t\t/* Find out whether this is a PKI user.  The comparison for the\n\t\t   action type is a bit odd since some back-ends will return the\n\t\t   action as text and some as a binary numeric value.  Rather than\n\t\t   relying on the back-end glue code to perform the appropriate\n\t\t   conversion we just check for either value type */\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT action FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\t\tcertData, MAX_QUERY_RESULT_SIZE, &certDataLength, \n\t\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( certData[ 0 ] == CRYPT_CERTACTION_ADDUSER || \\\n\t\t\tcertData[ 0 ] == TEXTCH_CERTACTION_ADDUSER )\n\t\t\t{\n\t\t\t/* We've found the PKI user, we're done */\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Find the certificate that was issued, recorded either as a\n\t\t   CERTACTION_CERT_CREATION for a multi-phase CMP-based certificate\n\t\t   creation or a CERTACTION_ISSUE_CERT for a one-step creation */\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT reqCertID FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\t\tcertData, MAX_QUERY_RESULT_SIZE, &certDataLength, \n\t\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertIDlength = min( certDataLength, ENCODED_DBXKEYID_SIZE );\n\t\tREQUIRES( rangeCheck( certIDlength, 1, ENCODED_DBXKEYID_SIZE ) );\n\t\tmemcpy( certID, certData, certIDlength );\n\n\t\t/* Find the request to issue this certificate.  For a CMP-based issue\n\t\t   this will have an authorising object (found in the next iteration\n\t\t   through the loop), for a one-step issue it won't */\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, certID, certIDlength );\n\t\tstatus = dbmsQuery(\n\t\t\t\"SELECT reqCertID FROM certLog WHERE certID = ?\",\n\t\t\t\t\t\t\tcertData, MAX_QUERY_RESULT_SIZE, &certDataLength, \n\t\t\t\t\t\t\tboundDataPtr, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_NORMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertIDlength = min( certDataLength, ENCODED_DBXKEYID_SIZE );\n\t\tREQUIRES( rangeCheck( certIDlength, 1, ENCODED_DBXKEYID_SIZE ) );\n\t\tmemcpy( certID, certData, certIDlength );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( chainingLevel >= 32 )\n\t\t{\n\t\t/* We've chained through too many entries, bail out */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* We've found the original PKI user, get the user information */\n\treturn( getItemData( dbmsInfo, iPkiUser, &dummy, KEYMGMT_ITEM_PKIUSER,\n\t\t\t\t\t\t CRYPT_IKEYID_CERTID, certID, certIDlength, \n\t\t\t\t\t\t KEYMGMT_FLAG_NONE, errorInfo ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCA Certificate Management Interface\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a certificate management operation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int certMgmtFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CERTIFICATE caKey,\n\t\t\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CERTIFICATE request,\n\t\t\t\t\t\t\t IN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tchar reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint reqCertIDlength, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( ( iCertificate == NULL ) || \\\n\t\t\tisWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( ( action != CRYPT_CERTACTION_ISSUE_CRL && \n\t\t\t\taction != CRYPT_CERTACTION_CERT_CREATION ) || \\\n\t\t\t  ( ( action == CRYPT_CERTACTION_ISSUE_CRL || \\\n\t\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION ) && \\\n\t\t\t\tiCertificate != NULL ) );\n\t\t\t  /* An ISSUE_CERT can have iCertificate == NULL, which leaves\n\t\t\t     the issued certificate in the store without returning it\n\t\t\t\t to the caller */\n\tREQUIRES( ( caKey == CRYPT_UNUSED ) || isHandleRangeValid( caKey ) );\n\tREQUIRES( ( request == CRYPT_UNUSED ) || isHandleRangeValid( request ) );\n\tREQUIRES( isEnumRange( action, CRYPT_CERTACTION ) );\n\n\t/* In order for various SQL query strings to use the correct values the\n\t   type values have to match their text equivalents defined at the start\n\t   of this file.  Since we can't check this at compile time we have to\n\t   do it here via an assertion */\n\tstatic_assert_opt( TEXT_CERTTYPE_REQUEST_CERT[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTTYPE_REQUEST_REVOCATION[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_REVOCATION, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTACTION_CREATE[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_CREATE, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert( TEXTCH_CERTACTION_ADDUSER - '0' == \\\n\t\t\t\t\t\tCRYPT_CERTACTION_ADDUSER, \\\n\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTACTION_REQUEST_CERT[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_CERT, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert( TEXTCH_CERTACTION_REQUEST_CERT - '0' == \\\n\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_CERT, \\\n\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTACTION_REQUEST_RENEWAL[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_REQUEST_RENEWAL, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert( TEXTCH_CERTACTION_REQUEST_RENEWAL - '0' == \\\n\t\t\t\t   CRYPT_CERTACTION_REQUEST_RENEWAL, \\\n\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTACTION_CERT_CREATION[ 0 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_CERT_CREATION / 10, \\\n\t\t\t\t\t   \"SQL data type\" );\n\tstatic_assert_opt( TEXT_CERTACTION_CERT_CREATION[ 1 ] - '0' == \\\n\t\t\t\t\t\t\tCRYPT_CERTACTION_CERT_CREATION % 10, \\\n\t\t\t\t\t   \"SQL data type\" );\n\n\t/* Clear return value */\n\tif( iCertificate != NULL )\n\t\t*iCertificate = CRYPT_ERROR;\n\n\t/* If it's a simple certificate expire or cleanup, there are no \n\t   parameters to check so we can perform the action immediately */\n\tif( action == CRYPT_CERTACTION_EXPIRE_CERT || \\\n\t\taction == CRYPT_CERTACTION_CLEANUP )\n\t\t{\n\t\tREQUIRES( caKey == CRYPT_UNUSED );\n\t\tREQUIRES( request == CRYPT_UNUSED );\n\n\t\treturn( caCleanup( dbmsInfo, action, KEYSET_ERRINFO ) );\n\t\t}\n\n\t/* If it's the completion of a certificate creation, process it */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_COMPLETE || \\\n\t\taction == CRYPT_CERTACTION_CERT_CREATION_DROP || \\\n\t\taction == CRYPT_CERTACTION_CERT_CREATION_REVERSE )\n\t\t{\n\t\tREQUIRES( caKey == CRYPT_UNUSED );\n\t\tREQUIRES( isHandleRangeValid( request ) );\n\n\t\treturn( caIssueCertComplete( dbmsInfo, request, action, \n\t\t\t\t\t\t\t\t\t KEYSET_ERRINFO ) );\n\t\t}\n\n\t/* Check that the CA key that we've been passed is in order.  These\n\t   checks are performed automatically during the issue process by the\n\t   kernel when we try and convert the request into a certificate, \n\t   however we perform them explicitly here so that we can return a more \n\t   meaningful error message to the caller */\n\tif( action == CRYPT_CERTACTION_ISSUE_CRL )\n\t\t{\n\t\tint value;\n\n\t\tREQUIRES( isHandleRangeValid( caKey ) );\n\n\t\t/* If we're issuing a CRL, the key must be capable of CRL signing */\n\t\tstatus = krnlSendMessage( caKey, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\t!( value & CRYPT_KEYUSAGE_CRLSIGN ) )\n\t\t\t{\n\t\t\tretExtArg( CAMGMT_ARGERROR_CAKEY, \n\t\t\t\t\t   ( CAMGMT_ARGERROR_CAKEY, KEYSET_ERRINFO, \n\t\t\t\t\t\t \"CA certificate isn't valid for CRL signing\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* For anything other than a revocation action (which just updates \n\t\t   the certificate store without doing anything else) the key must \n\t\t   be a CA key */\n\t\tif( action != CRYPT_CERTACTION_REVOKE_CERT )\n\t\t\t{\n\t\t\tREQUIRES( isHandleRangeValid( caKey ) );\n\n\t\t\tif( !checkContextCapability( caKey, MESSAGE_CHECK_PKC_SIGN_CA ) )\n\t\t\t\t{\n\t\t\t\tretExtArg( CAMGMT_ARGERROR_CAKEY, \n\t\t\t\t\t\t   ( CAMGMT_ARGERROR_CAKEY, KEYSET_ERRINFO, \n\t\t\t\t\t\t\t \"CA certificate isn't valid for certificate \"\n\t\t\t\t\t\t\t \"signing\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If it's a CRL issue it's a read-only operation on the CRL store for \n\t   which we only need the CA certificate (there's no request involved) */\n\tif( action == CRYPT_CERTACTION_ISSUE_CRL )\n\t\t{\n\t\tREQUIRES( isHandleRangeValid( caKey ) );\n\t\tREQUIRES( request == CRYPT_UNUSED );\n\n\t\treturn( caIssueCRL( dbmsInfo, iCertificate, caKey, KEYSET_ERRINFO ) );\n\t\t}\n\n\t/* Beyond this point we need to be working with a valid request */\n\tREQUIRES( isHandleRangeValid( request ) );\n\n\t/* We're processing an action that requires an explicit certificate \n\t   request, perform further checks on the request */\n\tif( !checkRequest( request, action ) )\n\t\t{\n\t\tretExtArg( CAMGMT_ARGERROR_REQUEST, \n\t\t\t\t   ( CAMGMT_ARGERROR_REQUEST, KEYSET_ERRINFO, \n\t\t\t\t\t \"Certificate request information \"\n\t\t\t\t\t \"inconsistent/invalid\" ) );\n\t\t}\n\n\t/* Make sure that the request is present in the request table in order \n\t   to issue a certificate for it.  Again, this will be checked later but \n\t   we can return a more meaningful error here */\n\tstatus = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength, \n\t\t\t\t\t   request, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CAMGMT_ARGERROR_REQUEST );\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );\n\tstatus = dbmsQuery(\n\t\t\"SELECT certData FROM certRequests WHERE certID = ?\",\n\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr, \n\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"Certificate request doesn't correspond to any existing \"\n\t\t\t\t  \"request in the certificate store\" ) );\n\t\t}\n\n\t/* If it's a revocation request, process it */\n\tif( action == CRYPT_CERTACTION_REVOKE_CERT )\n\t\t{\n\t\tREQUIRES( caKey == CRYPT_UNUSED );\n\n\t\treturn( caRevokeCert( dbmsInfo, request, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTACTION_REVOKE_CERT, KEYSET_ERRINFO ) );\n\t\t}\n\n\t/* It's a certificate issue request, issue the certificate */\n\tREQUIRES( action == CRYPT_CERTACTION_ISSUE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION );\n\tREQUIRES( isHandleRangeValid( caKey ) );\n\n\treturn( caIssueCert( dbmsInfo, iCertificate, caKey, request, action, \n\t\t\t\t\t\t KEYSET_ERRINFO ) );\n\t}\n\n/* Set up the function pointers to the keyset methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSCA( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\n\tkeysetInfoPtr->keysetDBMS->certMgmtFunction = certMgmtFunction;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/ca_rev.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib DBMS CA Certificate Revocation Interface\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the certificate indicated in a revocation request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int getCertToRevoke( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCertRequest, \n\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tchar issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint dummy, issuerIDlength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\t*iCertificate = CRYPT_ERROR;\n\n\t/* Extract the certificate identity information from the request and try\n\t   and fetch it from the certificate store */\n\tstatus = getKeyID( issuerID, ENCODED_DBXKEYID_SIZE, &issuerIDlength, \n\t\t\t\t\t   iCertRequest, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( getItemData( dbmsInfo, iCertificate, &dummy, \n\t\t\t\t\t\t KEYMGMT_ITEM_PUBLICKEY, CRYPT_IKEYID_ISSUERID, \n\t\t\t\t\t\t issuerID, issuerIDlength, KEYMGMT_FLAG_NONE, \n\t\t\t\t\t\t errorInfo ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Revocation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle an indirect certificate revocation (one where we need to reverse a \n   certificate issue or otherwise remove the certificate without obtaining a \n   direct revocation request from the user).  The various revocation \n   situations are:\n\n\tComplete cert renewal\t\t\t\toriginal certificate supplied\n\t\tCERTACTION_REVOKE_CERT\t\t\treason = superseded\n\t\t\t\t\t\t\t\t\t\tfail -> straight delete\n\n\tReverse issue due to cancel in CMP\toriginal certificate supplied\n\t\tCERTACTION_CREATION_REVERSE\t\treason = neverValid\n\t\t\t\t\t\t\t\t\t\tdate = certificate issue date\n\t\t\t\t\t\t\t\t\t\tfail -> straight delete\n\n\tUndo issue after restart\t\t\toriginal certificate supplied\n\t\tCERTACTION_CREATION_REVERSE\t\treason = neverValid\n\t\t\t\t\t\t\t\t\t\tdate = certificate issue date\n\t\t\t\t\t\t\t\t\t\tfail -> straight delete\n\n\t( Standard revocation\t\t\t\toriginal certificate not supplied\n\t\tCERTACTION_REVOKE_CERT\t\t\treason = <in request>\n\t\t\t\t\t\t\t\t\t\tdelete request\n\t\t\t\t\t\t\t\t\t\tfail -> no action ) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint revokeCertDirect( INOUT DBMS_INFO *dbmsInfo,\n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t  IN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iLocalCRL;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\ttime_t certDate;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertificate ) );\n\tREQUIRES( action == CRYPT_CERTACTION_REVOKE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get any information needed for the revocation from the certificate */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, &certDate, sizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iCertificate, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDFROM );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Create a (single-entry) CRL to contain the revocation information for \n\t   the certificate and revoke it via the standard channels.  We go \n\t   directly to a CRL rather than doing it via a revocation request \n\t   because we need to add information that can only be added by a CA and \n\t   only to a CRL */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalCRL = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCertificate, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't create CRL entry from certificate to be \"\n\t\t\t\t  \"revoked\" ) );\n\t\t}\n\tif( action == CRYPT_CERTACTION_REVOKE_CERT )\n\t\t{\n\t\tstatic const int crlReason = CRYPT_CRLREASON_SUPERSEDED;\n\n\t\t/* We're revoking the certificate because we're about to replace it, \n\t\t   set the revocation reason to superseded */\n\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &crlReason, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CRLREASON );\n\t\t}\n\telse\n\t\t{\n\t\tstatic const int crlReason = CRYPT_CRLREASON_NEVERVALID;\n\t\tMESSAGE_DATA msgData;\n\n\t\t/* We're revoking a certificate issued in error, set the revocation \n\t\t   and invalidity dates to the same value (the time of certificate \n\t\t   issue) in the hope of ensuring that it's regarded as never being \n\t\t   valid.  This isn't too accurate but since X.509 makes the \n\t\t   assumption that all CAs are perfect and never make mistakes \n\t\t   there's no other way to indicate that a certificate was issued in \n\t\t   error.  In addition to this we set the extended reason to \n\t\t   neverValid, but not too many implementations will check this */\n\t\tsetMessageData( &msgData, &certDate, sizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_REVOCATIONDATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_INVALIDITYDATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t( MESSAGE_CAST ) &crlReason, \n\t\t\t\t\t\t\tCRYPT_CERTINFO_CRLREASON );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INITIALISED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't add revocation status information to CRL for \"\n\t\t\t\t  \"certificate revocation\" ) );\n\t\t}\n\tstatus = caRevokeCert( dbmsInfo, iLocalCRL, iCertificate, action, \n\t\t\t\t\t\t   errorInfo );\n\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/* Revoke a certificate from a revocation request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint caRevokeCert( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t  IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iLocalCertificate = iCertificate;\n\tCRYPT_CERTIFICATE iLocalCRL = iCertRequest;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar reqCertID[ ENCODED_DBXKEYID_SIZE + 8 ], *reqCertIDptr = reqCertID;\n\tchar subjCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar specialCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tconst BOOLEAN reqPresent = \\\n\t\t\t\t\t( action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \\\n\t\t\t\t\t  ( action == CRYPT_CERTACTION_REVOKE_CERT && \\\n\t\t\t\t\t\tiCertificate == CRYPT_UNUSED ) ) ? TRUE : FALSE;\n\tint certDataLength DUMMY_INIT, reqCertIDlength, subjCertIDlength;\n\tint specialCertIDlength DUMMY_INIT, status = CRYPT_OK;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES( iCertificate == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iCertificate ) );\n\tREQUIRES( action == CRYPT_CERTACTION_REVOKE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_RESTART_REVOKE_CERT || \\\n\t\t\t  action == CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* This function handles a number of operations as summarised in the \n\t   table below:\n\n\t\tOperation\t\t\tAction\t\t\t\tRequest\tOn disk\tCert\n\t\t---------\t\t\t------\t\t\t\t-------\t-------\t----\n\t\tComplete revocation\tRESTART_REVOKE_CERT\tRev.req\t  Yes\t --\n\t\ton restart\n\n\t\tStandard revocation\tREVOKE_CERT\t\t\tRev.req\t  Yes\t --\n\n\t\tComplete renewal\tREVOKE_CERT\t\t\tcrlEntry   --\tSupplied\n\n\t\tReverse issue (CMP\tCREATION_REVERSE\tcrlEntry   --\tSupplied\n\t\tor due to restart)\n\n\t   The following assertion checks that the certificate parameter is \n\t   correct.  Checking the request parameter isn't so easy since it \n\t   requires multiple function calls, and is done as part of the code */\n\tREQUIRES( ( action == CRYPT_CERTACTION_RESTART_REVOKE_CERT && \\\n\t\t\t\tiCertificate == CRYPT_UNUSED ) || \\\n\t\t\t  ( action == CRYPT_CERTACTION_REVOKE_CERT ) || \\\n\t\t\t  ( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE && \\\n\t\t\t\tisHandleRangeValid( iCertificate ) ) );\n\n\t/* If it's a standard revocation (rather than one done as part of an\n\t   internal certificate management operation, which passes in a single-\n\t   entry CRL) fetch the certificate that we're going to revoke and set \n\t   up a CRL object to contain the revocation information */\n\tif( iCertificate == CRYPT_UNUSED )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t/* Get the certificate being revoked via the revocation request */\n\t\tstatus = getKeyID( reqCertID, ENCODED_DBXKEYID_SIZE, &reqCertIDlength, \n\t\t\t\t\t\t   iCertRequest, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = getCertToRevoke( dbmsInfo, &iLocalCertificate,\n\t\t\t\t\t\t\t\t\t  iCertRequest, errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Couldn't find certificate to revoke in \"\n\t\t\t\t\t\t \"certificate store: \" ) );\n\t\t\t}\n\n\t\t/* Create the CRL to contain the revocation information */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* Fill in the CRL from the revocation request */\n\t\t\tiLocalCRL = createInfo.cryptHandle;\n\t\t\tstatus = krnlSendMessage( iLocalCRL, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCertRequest,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_REVREQUEST );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't create CRL from revocation request\" ) );\n\t\t\t}\n\n\t\t}\n\telse\n\t\t{\n\t\t/* This is a direct revocation done as part of an internal \n\t\t   certificate management operation, there's no explicit request \n\t\t   for the revocation present and the caller has passed us a CRL \n\t\t   ready to use */\n\t\treqCertIDptr = NULL;\n\t\treqCertIDlength = 0;\n\t\t}\n\tstatus = getKeyID( subjCertID, ENCODED_DBXKEYID_SIZE, &subjCertIDlength, \n\t\t\t\t\t   iLocalCertificate, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = extractCertData( iLocalCRL, CRYPT_IATTRIBUTE_CRLENTRY,\n\t\t\t\t\t\t\t\t  certData, MAX_CERT_SIZE, &certDataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we created the necessary objects locally rather than having\n\t\t   them passed in by the caller we have to clean them up again\n\t\t   before we exit */\n\t\tif( iCertificate == CRYPT_UNUSED )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\t\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't extract CRL data to add to certificate store\" ) );\n\t\t}\n\n\t/* If it's a certificate creation reversal operation then the \n\t   certificate will be stored under a special temporary-status ID so we \n\t   turn the general subject certID into the form required for \n\t   special-case certificate data */\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )\n\t\t{\n\t\t/* Turn the general certID into the form required for special-case\n\t\t   certificate data by overwriting the first two bytes with an out-\n\t\t   of-band value */\n\t\tREQUIRES( rangeCheck( subjCertIDlength, 0, ENCODED_DBXKEYID_SIZE ) );\n\t\tmemcpy( specialCertID, KEYID_ESC1, KEYID_ESC_SIZE );\n\t\tmemcpy( specialCertID + KEYID_ESC_SIZE, subjCertID + KEYID_ESC_SIZE, \n\t\t\t\tsubjCertIDlength - KEYID_ESC_SIZE );\n\t\tspecialCertIDlength = subjCertIDlength;\n\t\t}\n\n\t/* Update the certificate store.  This is the ugliest CA operation since \n\t   it touches every table, luckily it's performed only rarely.\n\t   \n\t   If this is a reversal operation or revocation of a certificate to be \n\t   replaced, which is a direct follow-on to a certificate creation, \n\t   there's no corresponding request present so we don't have to update \n\t   the requests table */\n\tstatus = addCRL( dbmsInfo, iLocalCRL, iLocalCertificate,\n\t\t\t\t\t DBMS_UPDATE_BEGIN, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateCertLog( dbmsInfo, action, NULL, 0, reqCertIDptr, \n\t\t\t\t\t\t\t\treqCertIDlength, subjCertID, \n\t\t\t\t\t\t\t\tsubjCertIDlength, certData, certDataLength, \n\t\t\t\t\t\t\t\tDBMS_UPDATE_CONTINUE );\n\t\t}\n\tif( cryptStatusOK( status ) && reqPresent )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, reqCertID, reqCertIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\"DELETE FROM certRequests WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_CONTINUE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tinitBoundData( boundDataPtr );\n\t\tif( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )\n\t\t\t{\n\t\t\tsetBoundData( boundDataPtr, 0, specialCertID, \n\t\t\t\t\t\t  specialCertIDlength );\n\t\t\tstatus = dbmsUpdate( \n\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_COMMIT );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsetBoundData( boundDataPtr, 0, subjCertID, subjCertIDlength );\n\t\t\tstatus = dbmsUpdate( \n\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_COMMIT );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Something went wrong, abort the transaction */\n\t\tdbmsUpdate( NULL, NULL, DBMS_UPDATE_ABORT );\n\t\t}\n\tif( iCertificate == CRYPT_UNUSED )\n\t\t{\n\t\t/* If we created the necessary objects locally rather than having \n\t\t   them passed in by the caller we have to clean them up again \n\t\t   before we exit */\n\t\tkrnlSendNotifier( iLocalCertificate, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iLocalCRL, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The operation failed, record the details */\n\tupdateCertErrorLog( dbmsInfo, status,\n\t\t\t\t\t\t( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE ) ? \\\n\t\t\t\t\t\t\"Certificate issue reversal operation failed, \"\n\t\t\t\t\t\t\t\"performing straight delete\" : \\\n\t\t\t\t\t\t( action == CRYPT_CERTACTION_REVOKE_CERT && \\\n\t\t\t\t\t\t  iCertificate != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\"Revocation of certificate to be replaced failed, \"\n\t\t\t\t\t\t\t\"performing straight delete\" :\n\t\t\t\t\t\t\"Certificate revocation operation failed\",\n\t\t\t\t\t\tNULL, 0, reqCertIDptr, reqCertIDlength, NULL, 0, \n\t\t\t\t\t\tNULL, 0 );\n\n\t/* If it was a user-initiated operation we can't try and clean up the \n\t   operation internally */\n\tif( reqPresent )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t ( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE ) ? \\\n\t\t\t\t\t\t\t\"Certificate issue reversal operation failed: \" : \\\n\t\t\t\t\t\t ( action == CRYPT_CERTACTION_REVOKE_CERT && \\\n\t\t\t\t\t\t   iCertificate != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\"Revocation of certificate to be replaced \"\n\t\t\t\t\t\t\t\t\"failed: \" :\n\t\t\t\t\t\t\t\"Certificate revocation operation failed: \" ) );\n\t\t}\n\n\tREQUIRES( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE || \\\n\t\t\t  action == CRYPT_CERTACTION_REVOKE_CERT );\n\n\t/* It was a direct revocation done invisibly as part of an internal \n\t   certificate management operation, try again with a straight delete.\n\t   \"Where I come from Sherpa Tenzing there's no such word as 'asambhav \n\t   chha'\" */\n\tinitBoundData( boundDataPtr );\n\tif( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE )\n\t\t{\n\t\tsetBoundData( boundDataPtr, 0, specialCertID, specialCertIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\t\t}\n\telse\n\t\t{\n\t\tsetBoundData( boundDataPtr, 0, subjCertID, subjCertIDlength );\n\t\tstatus = dbmsUpdate( \n\t\t\t\t\t\"DELETE FROM certificates WHERE certID = ?\",\n\t\t\t\t\t\t\t boundDataPtr, DBMS_UPDATE_NORMAL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fallback straight delete succeeded, exit with a warning */\n\t\tsetErrorString( errorInfo, \"Warning: Direct certificate revocation \"\n\t\t\t\t\t\t\"operation failed, revocation was handled via \"\n\t\t\t\t\t\t\"straight delete\", 99);\n\t\treturn( CRYPT_OK ); \n\t\t}\n\n\t/* The fallback failed as well, we've run out of options */\n\tupdateCertErrorLogMsg( dbmsInfo, status, \n\t\t\t\t\t\t   \"Fallback straight delete failed\" );\n\tretExtErr( status, \n\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t ( action == CRYPT_CERTACTION_CERT_CREATION_REVERSE ) ? \\\n\t\t\t\t\t\"Certificate issue reversal operation failed: \" : \\\n\t\t\t\t ( action == CRYPT_CERTACTION_REVOKE_CERT && \\\n\t\t\t\t   iCertificate != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\"Revocation of certificate to be replaced failed: \" :\n\t\t\t\t\t\"Certificate revocation operation failed: \" ) );\n\t}\n\n/* Create a CRL from revocation entries in the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint caIssueCRL( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCRL,\n\t\t\t\tIN_HANDLE const CRYPT_CONTEXT caKey, \n\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE crlEntry[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tBOOLEAN crlEntryAdded = FALSE;\n\tchar crlEntryBuffer[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tvoid *crlEntryPtr = hasBinaryBlobs( dbmsInfo ) ? \\\n\t\t\t\t\t\tcrlEntry : ( void * ) crlEntryBuffer;\n\t\t\t\t\t\t/* Cast needed for gcc */\n\tchar nameID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tchar *operationString = \"No error\";\n\tint operationStatus = CRYPT_OK, nameIDlength;\n\tint errorCount, noCrlEntries, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( iCryptCRL, sizeof( CRYPT_CERTIFICATE ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( caKey ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Extract the information that we need to build the CRL from the CA \n\t   certificate */\n\tstatus = getKeyID( nameID, ENCODED_DBXKEYID_SIZE, &nameIDlength, \n\t\t\t\t\t   caKey, CRYPT_IATTRIBUTE_SUBJECT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the CRL object to hold the entries */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CRL );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Submit a query to fetch every CRL entry for this CA.  We don't have\n\t   to do a date check since the presence of revocation entries for\n\t   expired certificates is controlled by whether the CA's policy \n\t   involves removing entries for expired certificates or not */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, nameID, nameIDlength );\n\tstatus = dbmsQuery(\n\t\t\"SELECT certData FROM CRLs WHERE nameID = ?\",\n\t\t\t\t\t\tNULL, 0, NULL, boundDataPtr, \n\t\t\t\t\t\tDBMS_CACHEDQUERY_NONE, DBMS_QUERY_START );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't initiate CRL data fetch from certificate \"\n\t\t\t\t\t \"store: \" ) );\n\t\t}\n\n\t/* Rumble through the certificate store fetching every entry and adding \n\t   it to the CRL.  We only stop once we've run out of entries or we hit \n\t   too many errors which ensures that some minor error at some point \n\t   won't prevent the CRL from being issued, however if there was a \n\t   problem somewhere we create a log entry to record it */\n\tLOOP_LARGE( ( errorCount = 0, noCrlEntries = 0 ),\n\t\t\t\tstatus != CRYPT_ERROR_COMPLETE && errorCount < 5 && \\\n\t\t\t\t\tnoCrlEntries < 500, \n\t\t\t\tnoCrlEntries++ )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tint crlEntryLength;\n\n\t\t/* Read the CRL entry data */\n\t\tstatus = dbmsQuery( NULL, crlEntryPtr, MAX_QUERY_RESULT_SIZE, \n\t\t\t\t\t\t\t&crlEntryLength, NULL, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\tDBMS_QUERY_CONTINUE );\n\t\tif( status == CRYPT_ERROR_COMPLETE )\n\t\t\t{\n\t\t\t/* We've got all the entries, complete the query and exit */\n\t\t\tdbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE,\n\t\t\t\t\t\t\t DBMS_QUERY_CANCEL );\n\t\t\tbreak;\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && !hasBinaryBlobs( dbmsInfo ) )\n\t\t\t{\n\t\t\tstatus = base64decode( crlEntry, MAX_CERT_SIZE, &crlEntryLength,\n\t\t\t\t\t\t\t\t   crlEntryBuffer, crlEntryLength,\n\t\t\t\t\t\t\t\t   CRYPT_CERTFORMAT_NONE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Remember the error details for later if necessary */\n\t\t\tif( cryptStatusOK( operationStatus ) )\n\t\t\t\t{\n\t\t\t\toperationStatus = status;\n\t\t\t\toperationString = \"Some CRL entries couldn't be read from \"\n\t\t\t\t\t\t\t\t  \"the certificate store\";\n\t\t\t\t}\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Add the entry to the CRL */\n\t\tsetMessageData( &msgData, crlEntry, crlEntryLength );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CRLENTRY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Remember the error details for later if necessary */\n\t\t\tif( cryptStatusOK( operationStatus ) )\n\t\t\t\t{\n\t\t\t\toperationStatus = status;\n\t\t\t\toperationString = \"Some CRL entries couldn't be added to \"\n\t\t\t\t\t\t\t\t  \"the CRL\";\n\t\t\t\t}\n\t\t\terrorCount++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tcrlEntryAdded = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( errorCount >= 5 || noCrlEntries >= 500 )\n\t\t{\n\t\t/* It's hard to tell what type of error an iterationCount-exceeded\n\t\t   situation really is, in theory it's a software error (either in\n\t\t   cryptlib's fetch logic or in the dabatase) but because of the\n\t\t   practice of creating mega-CRLs with thousands of entries it's\n\t\t   entirely possible that this is \"normal\", or at least \"normal\" in\n\t\t   the alternative reality of X.509.  Because of this we don't flag\n\t\t   it as an internal error but simply warn in the debug build, \n\t\t   although we do bail out rather than trying to construct some\n\t\t   monster CRL */\n\t\tDEBUG_DIAG(( \"CRL-entry-fetch loop detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\t}\n\tif( cryptStatusError( operationStatus ) )\n\t\t{\n\t\t/* If nothing could be added to the CRL something is wrong, don't \n\t\t   try and continue */\n\t\tif( !crlEntryAdded )\n\t\t\t{\n\t\t\tupdateCertErrorLogMsg( dbmsInfo, operationStatus, \n\t\t\t\t\t\t\t\t   \"No CRL entries could be added to the \"\n\t\t\t\t\t\t\t\t   \"CRL\" );\n\t\t\tretExt( operationStatus, \n\t\t\t\t\t( operationStatus, errorInfo, \n\t\t\t\t\t  \"No CRL entries could be added to the CRL\" ) );\n\t\t\t}\n\n\t\t/* At least some entries could be added to the CRL, record that there\n\t\t   was a problem but continue */\n\t\tupdateCertErrorLogMsg( dbmsInfo, operationStatus, operationString );\n\t\t}\n\n\t/* We've got all the CRL entries, sign the CRL and return it to the\n\t   caller */\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CRT_SIGN,\n\t\t\t\t\t\t\t  NULL, caKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ARGERROR_VALUE )\n\t\t\tstatus = CAMGMT_ARGERROR_CAKEY;\t/* Map to correct error code */\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tupdateCertErrorLogMsg( dbmsInfo, operationStatus,\n\t\t\t\t\t\t\t   \"CRL creation failed\" );\n\t\tretExtArg( status, \n\t\t\t\t   ( status, errorInfo, \n\t\t\t\t\t \"Couldn't sign CRL to be issued\" ) );\n\t\t}\n\t*iCryptCRL = createInfo.cryptHandle;\n\tupdateCertLog( dbmsInfo, CRYPT_CERTACTION_ISSUE_CRL, \n\t\t\t\t   NULL, 0, NULL, 0, NULL, 0, NULL, 0, DBMS_UPDATE_NORMAL );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/dbms.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib DBMS Backend Interface\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tBackend Database Access Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Dispatch functions for various database types.  ODBC is the native keyset\n   for Windows and (frequently) Unix, the rest are accessible via database \n   plugins */\n\n#ifdef USE_ODBC\n  int initDispatchODBC( DBMS_INFO *dbmsInfo );\n#else\n  #define initDispatchODBC( dbmsInfo )\t\tCRYPT_ERROR\n#endif /* USE_ODBC */\n#if defined( USE_DATABASE )\n  int initDispatchDatabase( DBMS_INFO *dbmsInfo );\n#else\n  #define initDispatchDatabase( dbmsInfo )\tCRYPT_ERROR\n#endif /* General database interface */\n\n/* Database access functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int openDatabase( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_BUFFER( nameLen ) const char *name,\n\t\t\t\t\t\t IN_LENGTH_NAME const int nameLen, \n\t\t\t\t\t\t IN const BOOLEAN isReadOnly, \n\t\t\t\t\t\t OUT_FLAGS_Z( DBMS_FEATURE ) int *featureFlags )\n\t{\n\tDBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLen ) );\n\tassert( isWritePtr( featureFlags, sizeof( int ) ) );\n\n\tREQUIRES( nameLen >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLen < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isReadOnly == TRUE || isReadOnly == FALSE );\n\n\t/* Clear return value */\n\t*featureFlags = DBMS_FEATURE_FLAG_NONE;\n\n\tstatus = dbmsInfo->openDatabaseBackend( dbmsStateInfo, name, nameLen, \n\t\t\t\t\t\t\t\t\t\t\tisReadOnly, featureFlags );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make long-term information returned as a back-end interface-specific\n\t   feature flags persistent if necessary */\n\tif( *featureFlags & DBMS_FEATURE_FLAG_BINARYBLOBS )\n\t\tSET_FLAG( dbmsInfo->flags, DBMS_FLAG_BINARYBLOBS );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void closeDatabase( INOUT DBMS_INFO *dbmsInfo )\n\t{\n\tDBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tdbmsInfo->closeDatabaseBackend( dbmsStateInfo );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performUpdate( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t  IN_STRING_OPT const char *command,\n\t\t\t\t\t\t  IN_ARRAY_OPT_C( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\tTYPECAST( BOUND_DATA ) const void *boundData,\n\t\t\t\t\t\t  IN_ENUM( DBMS_UPDATE ) \\\n\t\t\t\t\t\t\tconst DBMS_UPDATE_TYPE updateType )\n\t{\n\tDBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;\n\tconst int commandLength = ( command != NULL ) ? strlen( command ) : 0;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( command == NULL && commandLength == 0 && \\\n\t\t\t  updateType == DBMS_UPDATE_ABORT ) || \\\n\t\t\tisReadPtrDynamic( command, commandLength ) );\n\tassert( ( boundData == NULL ) || \\\n\t\t\tisReadPtr( boundData, \\\n\t\t\t\t\t   sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS ) );\n\n\tANALYSER_HINT_STRING( command );\n\n\tREQUIRES( ( updateType == DBMS_UPDATE_ABORT && \\\n\t\t\t\tcommand == NULL && commandLength == 0 ) || \\\n\t\t\t  ( updateType != DBMS_UPDATE_ABORT && \\\n\t\t\t\tcommand != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( commandLength ) ) );\n\tREQUIRES( isEnumRange( updateType, DBMS_UPDATE ) );\n\n\t/* If we're trying to abort a transaction that was never begun, don't\n\t   do anything */\n\tif( updateType == DBMS_UPDATE_ABORT && \\\n\t\t!TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_UPDATEACTIVE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Tried to roll back non-begun transaction.\" ));\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Process the update */\n\tstatus = dbmsInfo->performUpdateBackend( dbmsStateInfo, command,\n\t\t\t\t\t\t\t\t\t\t\t commandLength, boundData,\n\t\t\t\t\t\t\t\t\t\t\t updateType );\n\tif( cryptStatusOK( status ) && updateType == DBMS_UPDATE_BEGIN )\n\t\t{\n\t\t/* We've successfully started a transaction, record the update\n\t\t   state */\n\t\tSET_FLAG( dbmsInfo->flags, DBMS_FLAG_UPDATEACTIVE );\n\t\t}\n\tif( updateType == DBMS_UPDATE_COMMIT || \\\n\t\tupdateType == DBMS_UPDATE_ABORT )\n\t\t{\n\t\t/* Final commits or rollbacks always end a transaction, even if\n\t\t   they're performed as part of a failed transaction */\n\t\tCLEAR_FLAG( dbmsInfo->flags, DBMS_FLAG_UPDATEACTIVE );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int performStaticUpdate( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t\t\tIN_STRING const char *command )\n\t{\n\treturn( performUpdate( dbmsInfo, command, NULL, DBMS_UPDATE_NORMAL ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performQuery( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_STRING_OPT const char *command,\n\t\t\t\t\t\t OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t\t OUT_OPT_LENGTH_SHORT_Z int *dataLength, \n\t\t\t\t\t\t IN_ARRAY_OPT_C( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\tTYPECAST( BOUND_DATA ) const void *boundData,\n\t\t\t\t\t\t IN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t IN_ENUM( DBMS_QUERY ) const DBMS_QUERY_TYPE queryType )\n\t{\n\tDBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;\n\tconst int commandLength = ( command != NULL ) ? strlen( command ) : 0;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( command == NULL && commandLength == 0 && \\\n\t\t\t  ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\t\tqueryType == DBMS_QUERY_CANCEL ) ) || \\\n\t\t\tisReadPtrDynamic( command, commandLength ) );\n\tassert( ( data == NULL && dataLength == NULL ) || \\\n\t\t\tisWritePtr( data, MAX_QUERY_RESULT_SIZE ) );\n\tassert( ( boundData == NULL ) || \\\n\t\t\tisReadPtr( boundData, \\\n\t\t\t\t\t   sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS ) );\n\n\tANALYSER_HINT_STRING( command );\n\n\tREQUIRES( ( ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\t\t  queryType == DBMS_QUERY_CANCEL ) && \\\n\t\t\t\tcommand == NULL && commandLength == 0 ) || \\\n\t\t\t  ( ( queryType == DBMS_QUERY_START || \\\n\t\t\t\t  queryType == DBMS_QUERY_CHECK || \\\n\t\t\t\t  queryType == DBMS_QUERY_NORMAL ) && \\\n\t\t\t\tcommand != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( commandLength ) ) );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 && \\\n\t\t\t\tdataLength == NULL ) || \\\n\t\t\t  ( data != NULL && dataMaxLength >= 16 && \\\n\t\t\t\tdataMaxLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tdataLength != NULL ) );\n\tREQUIRES( isEnumRangeOpt( queryEntry, DBMS_CACHEDQUERY ) );\n\tREQUIRES( isEnumRange( queryType, DBMS_QUERY ) );\n\n\t/* Additional state checks: If we're starting a new query or performing\n\t   a point query there can't already be one active and if we're\n\t   continuing or cancelling an existing query there has to be one\n\t   already active */\n\tREQUIRES( ( ( queryType == DBMS_QUERY_START || \\\n\t\t\t\t  queryType == DBMS_QUERY_CHECK || \\\n\t\t\t\t  queryType == DBMS_QUERY_NORMAL ) && \\\n\t\t\t\t!TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) ) ||\n\t\t\t  ( ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\t\t  queryType == DBMS_QUERY_CANCEL ) && \\\n\t\t\t\tTEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) ) );\n\n\t/* Clear return value */\n\tif( data != NULL )\n\t\t{\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t\t*dataLength = 0;\n\t\t}\n\n\t/* Process the query */\n\tstatus = dbmsInfo->performQueryBackend( dbmsStateInfo, command, \n\t\t\t\t\t\t\t\t\t\t\tcommandLength, data, dataMaxLength, \n\t\t\t\t\t\t\t\t\t\t\tdataLength, boundData, \n\t\t\t\t\t\t\t\t\t\t\tqueryEntry, queryType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Sanity-check the result data from the back-end */\n\tif( dataLength != NULL && \\\n\t\t( *dataLength <= 0 || *dataLength > MAX_QUERY_RESULT_SIZE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Database backend return invalid data size\" ));\n\t\tassert( DEBUG_WARN );\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t\t*dataLength = 0;\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Update the state information based on the query that we've just \n\t   performed */\n\tif( queryType == DBMS_QUERY_START  )\n\t\tSET_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE );\n\tif( queryType == DBMS_QUERY_CANCEL )\n\t\tCLEAR_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performStaticQuery( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t\t   IN_STRING_OPT const char *command,\n\t\t\t\t\t\t\t   IN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t\t   IN_ENUM( DBMS_QUERY ) \\\n\t\t\t\t\t\t\t\tconst DBMS_QUERY_TYPE queryType )\n\t{\n\treturn( performQuery( dbmsInfo, command, NULL, 0, NULL, NULL, \n\t\t\t\t\t\t  queryEntry, queryType ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSQL Rewrite Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In order to allow general certificate database queries we have to be able \n   to process user-supplied query strings.  The cryptlib manual contains \n   strong warnings about the correct way to do this (if it's done at all), \n   the best that we can do is apply assorted safety checks of the query data \n   to try and reduce the chances of SQL injection.  Unfortunately this can \n   get arbitrarily complicated:\n\n\t';\tThe standard SQL-injection method, used with values like\n\t\t'foo; DROP TABLE bar', or '1=1' to return all entries in a table.\n\n\t--\tComment delimiter (other values also exist, e.g. MySQL's '#') to\n\t\ttruncate queries beyond the end of the injected SQL.\n\n\tchar(0xNN)\tBypass the first level of filtering, e.g. char(0x41)\n\t\tproduces the banned character '.\n\n   One additional check that we could do is to try and explicitly strip\n   SQL keywords from queries but this is somewhat problematic because apart \n   from the usual trickery (e.g. embedding one SQL keyword inside another so \n   that stripping SELECT from SELSELECTECT will still leave the outer \n   SELECT, requiring recursive stripping, or taking advantage of the fact \n   that VARBINARY values are implicitly cast to VARCHARS so that 0x42434445 \n   would turn into ABCD, or further escaping the encoding with values like \n   'sel'+'ect') there are also any number of backend-specific custom \n   keywords and ways of escaping keywords that we can't know about and \n   therefore can't easily strip */\n\n#define\tSQL_ESCAPE\t'\\''\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int copyChar( OUT_BUFFER( bufMaxLen, *bufPos ) char *buffer, \n\t\t\t\t\t IN_LENGTH_SHORT const int bufMaxLen, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxLen ) int *bufPos, \n\t\t\t\t\t IN_BYTE const int ch, \n\t\t\t\t\t const BOOLEAN escapeQuotes )\n\t{\n\tint position = 0;\n\n\tassert( isWritePtrDynamic( buffer, bufMaxLen ) );\n\tassert( isWritePtr( bufPos, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( bufMaxLen ) );\n\tREQUIRES( ch >= 0 && ch <= 0xFF );\n\tREQUIRES( escapeQuotes == TRUE || escapeQuotes == FALSE );\n\n\t/* Clear return value */\n\t*bufPos = 0;\n\n\t/* If it's a control character, skip it */\n\tif( ( ch & 0x7F ) < ' ' )\n\t\treturn( CRYPT_OK );\n\n\t/* Escape metacharacters that could be misused in queries.  We catch the \n\t   obvious ' and ; as well as the less obvious %, which could be used to \n\t   hide other metacharacters, and \\, used by some databases (e.g. MySQL)\n\t   as an escape.  Note that none of these characters are valid in base64, \n\t   which makes it safe to escape them in the few instances where they do \n\t   occur */\n\tif( ( ch == '\\'' && escapeQuotes ) || \\\n\t\tch == '\\\\' || ch == ';' || ch == '%' )\n\t\t{\n\t\t/* Escape the character */\n\t\tbuffer[ position++ ] = SQL_ESCAPE;\n\t\tif( position >= bufMaxLen )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* Bypass various dangerous SQL \"enhancements\".  For Windows ODBC (at\n\t   least for MS Jet 3.x, but not 4.x any more) the driver will execute \n\t   anything delimited by '|'s as an expression (an example being \n\t   '|shell(\"cmd /c echo \" & chr(124) & \" format c:\")|'), because of this \n\t   we strip gazintas.  Since ODBC uses '{' and '}' as escape delimiters \n\t   we also strip these */\n\tif( ch != '|' && ch != '{' && ch != '}' )\n\t\tbuffer[ position++ ] = intToByte( ch );\n\n\t/* Make sure that we haven't overflowed the output buffer.  This \n\t   overflowing can be done deliberately, for example by using large \n\t   numbers of escape chars (which are in turn escaped) to force \n\t   truncation of the query beyond the injected SQL if the processing \n\t   simply stops at a given point */\n\tif( position >= bufMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t*bufPos = position;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int copyStringArg( OUT_BUFFER( bufMaxLen, *bufPos ) char *buffer, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int bufMaxLen, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( bufMaxLen ) int *bufPos, \n\t\t\t\t\t\t  IN_BUFFER( stringLen ) const char *string,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int stringLen )\n\t{\n\tint index, position = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( buffer, bufMaxLen ) );\n\tassert( isWritePtr( bufPos, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( string, stringLen ) );\n\n\tREQUIRES( isShortIntegerRange( bufMaxLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( stringLen ) );\n\n\t/* Make sure that there's room for at least one more character of \n\t   output */\n\tif( bufMaxLen < 1 )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Copy the string to the output buffer with conversion of any special \n\t   characters that are used by SQL */\n\tLOOP_MAX( index = 0, index < stringLen, index++ )\n\t\t{\n\t\tint charsWritten, status;\n\n\t\tstatus = copyChar( buffer + position, bufMaxLen - position, \n\t\t\t\t\t\t   &charsWritten, byteToInt( string[ index ] ), \n\t\t\t\t\t\t   TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tposition += charsWritten;\n\t\tif( position > bufMaxLen )\n\t\t\t{\n\t\t\t/* Already checked in copyChar() but we double-check here to be \n\t\t\t   safe */\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t*bufPos = position;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Format input parameters into SQL queries, replacing meta-values with\n   actual column names, and null-terminate the resulting string so that\n   it can be fed to the database backend */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint dbmsFormatQuery( OUT_BUFFER( outMaxLength, *outLength ) char *output, \n\t\t\t\t\t IN_LENGTH_SHORT const int outMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( outMaxLength ) int *outLength,\n\t\t\t\t\t IN_BUFFER( inputLength ) const char *input, \n\t\t\t\t\t IN_LENGTH_SHORT const int inputLength )\n\t{\n\tint inPos, outPos = 0, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( output, outMaxLength ) );\n\tassert( isWritePtr( outLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( input, inputLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( outMaxLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( inputLength ) );\n\n\t/* Clear return values */\n\tmemset( output, 0, min( 16, outMaxLength ) );\n\t*outLength = 0;\n\n\tLOOP_MAX_INITCHECK( inPos = 0, inPos < inputLength )\n\t\t{\n\t\tint length;\n\n\t\tif( input[ inPos ] == '$' )\n\t\t\t{\n\t\t\ttypedef struct {\n\t\t\t\tBUFFER_FIXED( sourceLength ) \\\n\t\t\t\tchar *sourceName;\n\t\t\t\tint sourceLength;\n\t\t\t\tBUFFER_FIXED( destLength ) \\\n\t\t\t\tchar *destName;\n\t\t\t\tint destLength;\n\t\t\t\t} NAMEMAP_INFO;\n\t\t\tstatic const NAMEMAP_INFO nameMapTbl[] = {\n\t\t\t\t{ \"C\", 1, \"C\", 1 }, { \"SP\", 2, \"SP\", 2 },\n\t\t\t\t{ \"L\", 1, \"L\", 1 }, { \"O\", 1, \"O\", 1 },\n\t\t\t\t{ \"OU\", 2, \"OU\", 2 }, { \"CN\", 2, \"CN\", 2 },\n\t\t\t\t{ \"email\", 5, \"email\", 5 }, { \"uri\", 3, \"email\", 5 },\n\t\t\t\t{ \"date\", 4, \"validTo\", 7 }, \n\t\t\t\t{ NULL, 0, NULL, 0 }, { NULL, 0, NULL, 0 }\n\t\t\t\t};\n\t\t\tconst int fieldPos = inPos + 1;\n\t\t\tconst char *fieldName = input + fieldPos;\n\t\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t\tinPos++;\t/* Skip '$' */\n\n\t\t\t/* Extract the field name and translate it into the table\n\t\t\t   column name */\n\t\t\tLOOP_LARGE_CHECKINC_ALT( inPos < inputLength && \\\n\t\t\t\t\t\t\t\t\t isAlpha( input[ inPos ] ), inPos++ );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tlength = inPos - fieldPos;\n\t\t\tif( length <= 0 || length > 5 )\n\t\t\t\t{\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tLOOP_MED( i = 0, nameMapTbl[ i ].sourceName != NULL && \\\n\t\t\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( nameMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   NAMEMAP_INFO ), \n\t\t\t\t\t  i++ )\n\t\t\t\t{\n\t\t\t\tif( length == nameMapTbl[ i ].sourceLength && \\\n\t\t\t\t\t!strCompare( fieldName, nameMapTbl[ i ].sourceName, \\\n\t\t\t\t\t\t\t\t length ) )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tENSURES( i < FAILSAFE_ARRAYSIZE( nameMapTbl, NAMEMAP_INFO ) );\n\t\t\tif( nameMapTbl[ i ].sourceName == NULL )\n\t\t\t\t{\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Copy the translated name to the output buffer */\n\t\t\tstatus = copyStringArg( output + outPos, outMaxLength - outPos, \n\t\t\t\t\t\t\t\t\t&length, nameMapTbl[ i ].destName,\n\t\t\t\t\t\t\t\t\tnameMapTbl[ i ].destLength );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Just copy the character over, with a length check.  We don't \n\t\t\t   escape single quotes in this case because we use these \n\t\t\t   ourselves in SQL queries */\n\t\t\tstatus = copyChar( output + outPos, outMaxLength - outPos, \n\t\t\t\t\t\t\t   &length, input[ inPos++ ], FALSE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\toutPos += length;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\toutPos = 0;\n\toutput[ outPos ] = '\\0';\t/* Add der terminador */\n\t*outLength = outPos;\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBack-end Interface Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Parse a user-supplied database name into individual components, used by\n   the database back-end connect functions.  We don't do a syntax check\n   (since the exact syntax is database-specific) but merely break the single\n   string up into any recognisable components.  The database back-end can\n   determine whether the format is valid or not.  The general format that we\n   look for is:\n\n\t[generic name]\n\tuser:pass\n\tuser@server\n\tuser:pass@server\n\tuser:pass@server/name\n\n   One distinction that we make is that if there's something after an '@'\n   and there's no server/name separator present we treat it as a name rather \n   than a server.  In other words @foo results in name=foo while @foo/bar \n   results in server=foo, name=bar.  This is because the most common \n   situation that we have to handle is ODBC, which identifies the database \n   by name rather than by server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint dbmsParseName( OUT DBMS_NAME_INFO *nameInfo, \n\t\t\t\t   IN_BUFFER( nameLen ) const char *name, \n\t\t\t\t   IN_LENGTH_NAME const int nameLen )\n\t{\n\tint offset, offset2, length;\n\n\tassert( isWritePtr( nameInfo, sizeof( DBMS_NAME_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLen ) );\n\n\tREQUIRES( nameLen >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLen < MAX_ATTRIBUTE_SIZE );\n\n\t/* Clear return value */\n\tmemset( nameInfo, 0, sizeof( DBMS_NAME_INFO ) );\n\n\t/* Check for a complex database name */\n\tif( ( offset = strFindCh( name, nameLen, ':' ) ) < 0 && \\\n\t\t( offset = strFindCh( name, nameLen, '@' ) ) < 0 )\n\t\t{\n\t\t/* It's a straightforward name, use it directly */\n\t\tnameInfo->name = ( char * ) name;\n\t\tnameInfo->nameLen = nameLen;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Extract the user name */\n\tlength = min( offset, CRYPT_MAX_TEXTSIZE );\n\tif( length <= 0 )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( nameInfo->userBuffer, name, length );\n\tnameInfo->user = nameInfo->userBuffer;\n\tnameInfo->userLen = length;\n\n\t/* We're either at the server name or password, extract the password\n\t   if there is one */\n\tENSURES( name[ offset ] == ':' || name[ offset ] == '@' );\n\tif( name[ offset++ ] == ':' )\n\t\t{\n\t\toffset2 = strFindCh( name + offset, nameLen - offset, '@' );\n\t\tif( offset2 < 0 )\n\t\t\toffset2 = nameLen - offset;\t/* Password is rest of string */\n\t\tlength = min( offset2, CRYPT_MAX_TEXTSIZE );\n\t\tif( length <= 0 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( nameInfo->passwordBuffer, name + offset, length );\n\t\tnameInfo->password = nameInfo->passwordBuffer;\n\t\tnameInfo->passwordLen = length;\n\t\toffset += offset2 + 1;\n\t\tif( offset >= nameLen )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Separate the server and database name if necessary */\n\toffset2 = strFindCh( name + offset, nameLen - offset, '/' );\n\tif( offset2 >= 0 )\n\t\t{\n\t\t/* There's a distinction between the server name and database name,\n\t\t   extract the server name */\n\t\tlength = min( offset2, CRYPT_MAX_TEXTSIZE );\n\t\tif( length <= 0 )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( nameInfo->serverBuffer, name + offset, length );\n\t\tnameInfo->server = nameInfo->serverBuffer;\n\t\tnameInfo->serverLen = length;\n\t\toffset += offset2 + 1;\n\t\t}\n\n\t/* Extract the database name if there is one */\n\tif( offset < nameLen )\n\t\t{\n\t\tlength = nameLen - offset;\n\t\tif( length <= 0 || length > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ERROR_OPEN );\n\t\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( nameInfo->nameBuffer, name + offset, length );\n\t\tnameInfo->name = nameInfo->nameBuffer;\n\t\tnameInfo->nameLen = length;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and shut down a session with a database back-end */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDbxSession( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\tIN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE type )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tDBMS_STATE_INFO *dbmsStateInfo;\n\tint status = CRYPT_ERROR;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( isEnumRange( type, CRYPT_KEYSET ) );\n\n\t/* Initialise the DBMS information */\n\tmemset( dbmsInfo, 0, sizeof( DBMS_INFO ) );\n\tINIT_FLAGS( dbmsInfo->flags, DBMS_FLAG_NONE );\n\n\t/* Select the appropriate dispatch function for the keyset type */\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_KEYSET_ODBC:\n\t\tcase CRYPT_KEYSET_ODBC_STORE:\n\t\t\tstatus = initDispatchODBC( dbmsInfo );\n\t\t\tbreak;\n\n\t\tcase CRYPT_KEYSET_DATABASE:\n\t\tcase CRYPT_KEYSET_DATABASE_STORE:\n\t\t\tstatus = initDispatchDatabase( dbmsInfo );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Set up the remaining function pointers */\n\tdbmsInfo->openDatabaseFunction = openDatabase;\n\tdbmsInfo->closeDatabaseFunction = closeDatabase;\n\tdbmsInfo->performUpdateFunction = performUpdate;\n\tdbmsInfo->performStaticUpdateFunction = performStaticUpdate;\n\tdbmsInfo->performQueryFunction = performQuery;\n\tdbmsInfo->performStaticQueryFunction = performStaticQuery;\n\n\t/* Allocate the database session state information */\n\tif( ( dbmsStateInfo = clAlloc( \"initDbxSession\", \\\n\t\t\t\t\t\t\t\t   sizeof( DBMS_STATE_INFO ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( dbmsStateInfo, 0, sizeof( DBMS_STATE_INFO ) );\n\tDATAPTR_SET( keysetInfoPtr->keyData, dbmsStateInfo );\n\tkeysetInfoPtr->keyDataSize = sizeof( DBMS_STATE_INFO );\n\tdbmsInfo->stateInfo = dbmsStateInfo;\n\tif( type == CRYPT_KEYSET_ODBC_STORE || \\\n\t\ttype == CRYPT_KEYSET_DATABASE_STORE )\n\t\t{\n\t\tSET_FLAGS( dbmsInfo->flags, DBMS_FLAG_CERTSTORE | \\\n\t\t\t\t\t\t\t\t\tDBMS_FLAG_CERTSTORE_FIELDS );\n\t\t}\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint endDbxSession( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\n\t/* Free the database session state information if necessary */\n\tif( DATAPTR_ISSET( keysetInfoPtr->keyData ) )\n\t\t{\n\t\tDBMS_STATE_INFO *dbmsStateInfo = DATAPTR_GET( keysetInfoPtr->keyData );\n\n\t\tENSURES( dbmsStateInfo != NULL );\n\n\t\tmemset( dbmsStateInfo, 0, keysetInfoPtr->keyDataSize );\n\t\tclFree( \"endDbxSession\", dbmsStateInfo );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/dbms.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib DBMS Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _DBMS_DEFINED\n\n#define _DBMS_DEFINED\n\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Keyset Headers\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle ODBC support.  This gets rather complex, with all sorts of special-\n   case handling of headers and types required across different systems */\n\n#ifdef USE_ODBC\n\n/* As part of the ever-changing way of identifying Win32, Microsoft changed \n   the predefined constant from WIN32 to _WIN32 in VC++ 2.1.  However the \n   ODBC header files still expect to find WIN32 and if this isn't defined \n   will use the default (i.e. C) calling convention instead of the Pascal \n   convention which is actually used by the ODBC functions.  This means that \n   both the caller and the callee clean up the stack so that for each ODBC \n   call the stack creeps upwards by a few bytes until eventually the local \n   variables and/or return address get trashed.  This problem is usually \n   hidden by the fact that something else defines WIN32 so everything works \n   OK, but the October 1997 development platform upgrade changes this so \n   that compiling the code after this update is installed breaks things.  To \n   avoid this problem, we define WIN32 if it isn't defined, which ensures \n   that the ODBC header files work properly */\n#if defined( __WIN32__ ) && !defined( WIN32 )\n  #define WIN32\n#endif /* __WIN32__ && !WIN32 */\n\n#ifdef __WINDOWS__\n  /* UnixODBC defines its own version of various Windows types, if we're \n     building under Windows then we have to disable this.  The UnixODBC \n\t headers have a guard ALLREADY_HAVE_WINDOWS_TYPE (sic) but this is \n\t all-or-nothing, disabling the defining of Windows *and* SQL types.  \n\t Defining the guard value fixes most compile problems but in order to \n\t build it the commented-out typedefs also need to be defined.  These \n\t are already defined in the standard (Windows) sqltypes.h so their use \n\t needs to be manually enabled for UnixODBC under Windows, which is \n\t unlikely to occur given that it's a Unix-only driver */\n  #define ALLREADY_HAVE_WINDOWS_TYPE\n  #if 0\n\ttypedef signed short RETCODE;\n\ttypedef short int SWORD;\n\ttypedef long int SDWORD;\n\ttypedef signed char SQLSCHAR;\n\ttypedef HWND SQLHWND;\n  #endif /* 0 */\n\n  #pragma warning( push )\n  #pragma warning( disable : 4255 )\t/* Errors in recent sqlext.h versions */\n  #include <sql.h>\n  #include <sqlext.h>\n  #pragma warning( pop )\n\n  /* When Microsoft switched from 32- to 64-bit ODBC they changed some of \n     the types that were formerly SQLINTEGER to SQLLEN.  To deal with this \n\t we map SQLLEN to SQLINTEGER if required */\n  #ifndef __WIN64__\n\t#define SQLLEN\t\tSQLINTEGER\n\t#define SQLULEN\t\tSQLUINTEGER\n  #endif /* 32-bit environment */\n#else\n  #include <sql.h>\n  #include <sqlext.h>\n#endif /* Windows vs.everything else */\n\n#endif /* USE_ODBC */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Keyset Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of the ID fields, derived from the base64-encoded first 128 bits \n   of an SHA-1 hash.  The field size value is also given in text form for \n   use in SQL strings */\n\n#define DBXKEYID_SIZE\t\t\t16\t\t/* Full keyID = 128 bits */\n#define ENCODED_DBXKEYID_SIZE\t22\t\t/* base64-encoded key ID */\n#define TEXT_DBXKEYID_SIZE\t\t\"22\"\n\n/* The maximum SQL query size */\n\n#define MAX_SQL_QUERY_SIZE\t\t256\n\n/* When performing a query the database glue code limits the maximum returned\n   data size to a certain size, the following define allows us to declare a\n   fixed-size buffer that we know will always be big enough */\n\n#define MAX_QUERY_RESULT_SIZE\tMAX_ENCODED_CERT_SIZE\n\n/* Database status flags.  These are:\n\n\tFLAG_BINARYBLOBS: Database supports binary blobs.\n\n\tFLAG_CERTSTORE/FLAG_CERTSTORE_FIELDS: Certificate stores are designated \n\t\t\tby two flags, a main one for standard database/certificate store \n\t\t\tdifferentiation and a secondary one that indicates that it's a \n\t\t\tcertificate store opened as a standard database, for example \n\t\t\twhen it's being used for read-only access with a key server.  In \n\t\t\tthis case it's possible to perform extended queries on fields \n\t\t\tthat aren't present in standard databases so we set the \n\t\t\tsecondary flags to indicate that extended queries are possible \n\t\t\teven though certificate store functionality isn't present.\n\n\tFLAG_QUERYACTIVE: A query (returning a multiple-element result set) is\n\t\t\tcurrently in progress.\n\n\tFLAG_UPDATEACTIVE: An update is currently in progress.  This is required \n\t\t\tbecause we can sometimes run into a situation where an update \n\t\t\tfalls through to an abort without ever having been begun, this \n\t\t\thappens if there's a sequence of miscellaneous setup operations \n\t\t\ttaking place and one of them fails before we begin the update.  \n\t\t\tAlthough it'd be better if the caller handled this, in practice \n\t\t\tit'd mean passing extra status information (failed vs.failed but \n\t\t\tneed to abort a commenced update) across a number of different \n\t\t\tfunctions, to avoid this we record whether an update has begun \n\t\t\tand if not skip an abort operation if there's no update currently \n\t\t\tin progress */\n\n#define DBMS_FLAG_NONE\t\t\t0x00\t/* No DBMS flag */\n#define DBMS_FLAG_BINARYBLOBS\t0x01\t/* DBMS supports blobs */\n#define DBMS_FLAG_UPDATEACTIVE\t0x02\t/* Ongoing update in progress */\n#define DBMS_FLAG_QUERYACTIVE\t0x04\t/* Ongoing query in progress */\n#define DBMS_FLAG_CERTSTORE\t\t0x08\t/* Full certificate store */\n#define DBMS_FLAG_CERTSTORE_FIELDS 0x10\t/* Certificate store fields */\n#define DBMS_FLAG_MAX\t\t\t0x1F\t/* Maximum possible flag value */\n\n/* Database feature information returned when the keyset is opened */\n\n#define DBMS_FEATURE_FLAG_NONE\t0x00\t/* No DBMS features */\n#define DBMS_FEATURE_FLAG_BINARYBLOBS 0x01 /* DBMS supports binary blobs */\n#define DBMS_FEATURE_FLAG_READONLY 0x02\t/* DBMS doesn't allow write access */\n#define DBMS_FEATURE_FLAG_PRIVILEGES 0x04 /* DBMS supports GRANT/REVOKE */\n#define DBMS_FEATURE_FLAG_MAX\t0x07\t/* Maximum possible flag value */\n\n/* The certstore and binary blobs flags are checked often enough that we \n   define a macro for them */\n\n#define hasBinaryBlobs( dbmsInfo ) \\\n\t\tTEST_FLAG( ( dbmsInfo )->flags, DBMS_FLAG_BINARYBLOBS )\n#define isCertStore( dbmsInfo ) \\\n\t\tTEST_FLAG( ( dbmsInfo )->flags, DBMS_FLAG_CERTSTORE )\n\n/* When we perform a DBMS transaction there are several variations on the \n   basic operation type.  The following values tell performQuery() and\n   performUpdate() which type of operation to perform */\n\ntypedef enum {\n\tDBMS_QUERY_NONE,\t\t\t\t/* No DBMS query */\n\tDBMS_QUERY_NORMAL,\t\t\t\t/* Standard data fetch */\n\tDBMS_QUERY_CHECK,\t\t\t\t/* Check-type fetch, don't fetch data */\n\tDBMS_QUERY_START,\t\t\t\t/* Begin an ongoing query */\n\tDBMS_QUERY_CONTINUE,\t\t\t/* Continue an ongoing query */\n\tDBMS_QUERY_CANCEL,\t\t\t\t/* Cancel ongoing query */\n\tDBMS_QUERY_LAST\t\t\t\t\t/* Last valid DBMS query type */\n\t} DBMS_QUERY_TYPE;\n\ntypedef enum {\n\tDBMS_UPDATE_NONE,\t\t\t\t/* No DBMS update */\n\tDBMS_UPDATE_NORMAL,\t\t\t\t/* Standard update */\n\tDBMS_UPDATE_BEGIN,\t\t\t\t/* Begin a transaction */\n\tDBMS_UPDATE_CONTINUE,\t\t\t/* Continue an ongoing transaction */\n\tDBMS_UPDATE_COMMIT,\t\t\t\t/* Commit a transaction */\n\tDBMS_UPDATE_ABORT,\t\t\t\t/* Abort a transaction */\n\tDBMS_UPDATE_LAST\t\t\t\t/* Last valid DBMS update type */\n\t} DBMS_UPDATE_TYPE;\n\n/* To optimise database accesses we use prepared queries that are prepared\n   once and then re-used whenever a new result set is required.  The following\n   values are used to refer to the prepared query types */\n\ntypedef enum {\n\tDBMS_CACHEDQUERY_NONE,\t\t\t/* No cached query */\n\tDBMS_CACHEDQUERY_CERTID,\t\t/* Query on certificate ID */\n\tDBMS_CACHEDQUERY_ISSUERID,\t\t/* Query on issuer ID */\n\tDBMS_CACHEDQUERY_NAMEID,\t\t/* Query in name ID */\n\tDBMS_CACHEDQUERY_URI,\t\t\t/* Query on URI */\n\tDBMS_CACHEDQUERY_LAST\t\t\t/* Last valid cached query type */\n\t} DBMS_CACHEDQUERY_TYPE;\n\n#define NO_CACHED_QUERIES\t5\n\n/* When we add or read information to/from a table we sometimes have to\n   specify type information which is an integer value, however SQL requires\n   that things be set out as character strings so we use the following\n   defines to provide the string form of the value for insertion into an SQL\n   query.  Unfortunately we can't check this at compile time so we have to\n   check it via an assertion in the CA dispatch function */\n\n#define TEXT_CERTTYPE_REQUEST_CERT\t\t\t\"5\"\n#define TEXT_CERTTYPE_REQUEST_REVOCATION\t\"6\"\n\n#define TEXT_CERTACTION_CREATE\t\t\t\t\"1\"\n#define TEXTCH_CERTACTION_ADDUSER\t\t\t'5'\n#define TEXT_CERTACTION_REQUEST_CERT\t\t\"7\"\n#define TEXTCH_CERTACTION_REQUEST_CERT\t\t'7'\n#define TEXT_CERTACTION_REQUEST_RENEWAL\t\t\"8\"\n#define TEXTCH_CERTACTION_REQUEST_RENEWAL\t'8'\n#define TEXT_CERTACTION_CERT_CREATION\t\t\"10\"\n\n/* Special escape strings used in database keys to indicate that the value is\n   physically but not logically present.  This is used to handle (currently-)\n   incomplete certificate issues and similar events where intermediate state \n   information has to be stored in the database but the object in question \n   isn't ready for use yet */\n\n#define KEYID_ESC1\t\t\t\t\"--\"\n#define KEYID_ESC2\t\t\t\t\"##\"\n#define KEYID_ESC_SIZE\t\t\t2\n\n/* The ways in which we can add a certificate object to a table.  Normally \n   we just add the certificate as is, however if we're awaiting confirmation \n   from a user before we can complete the certificate issue process we \n   perform a partial add that marks the certificate as not quite ready for \n   use yet.  A variant of this is when we're renewing a certificate (i.e. \n   re-issuing it with the same key, which is really bad but required by some \n   certificate mismanagement protocols) in which case we have to process the \n   update as a multi-stage process because we're replacing an existing \n   certificate with one which is exactly the same as far as the uniqueness \n   constraints on the certificate store are concerned */\n\ntypedef enum {\n\tCERTADD_NONE,\t\t\t\t/* No certificate-add operation */\n\tCERTADD_NORMAL,\t\t\t\t/* Standard one-step add */\n\tCERTADD_PARTIAL,\t\t\t/* Partial add */\n\tCERTADD_PARTIAL_RENEWAL,\t/* Partial add with certificate replacement to follow */\n\tCERTADD_RENEWAL_COMPLETE,\t/* Completion of renewal */\n\tCERTADD_LAST\t\t\t\t/* Last valid certificate-add type */\n\t} CERTADD_TYPE;\n\n/* In order to make reporting of parameter errors in the multi-parameter \n   CA management function easier we provide symbolic defines mapping the \n   CA management-specific parameter type to its corresponding parameter \n   error type */\n\n#define CAMGMT_ARGERROR_CAKEY\t\tCRYPT_ARGERROR_NUM1\n#define CAMGMT_ARGERROR_REQUEST\t\tCRYPT_ARGERROR_NUM2\n#define CAMGMT_ARGERROR_ACTION\t\tCRYPT_ARGERROR_VALUE\n\n/* To avoid SQL injection attacks and speed up performance we make extensive \n   use of bound parameters.  The following structure is used to communicate \n   these parameters to the database back-end */\n\ntypedef enum {\n\tBOUND_DATA_NONE,\t\t/* No bound data type */\n\tBOUND_DATA_STRING,\t\t/* Character string */\n\tBOUND_DATA_BLOB,\t\t/* Binary string */\n\tBOUND_DATA_TIME,\t\t/* Date/time */\n\tBOUND_DATA_LAST\t\t\t/* Last bound data type */\n\t} BOUND_DATA_TYPE;\n\ntypedef struct {\n\tBOUND_DATA_TYPE type;\t/* Type of this data item */\n\tBUFFER_FIXED( dataLength ) \\\n\tconst void *data;\t\t/* Data and data length */\n#ifdef USE_ODBC\n\tSQLLEN dataLength;\n#else\n\tint dataLength;\n#endif /* USE_ODBC */\n\t} BOUND_DATA;\n\n#define BOUND_DATA_MAXITEMS\t\t16\n\n/* Macros to initialise the bound-data information.  When we're binding \n   standard data values (i.e. non-blob data) the buffer to contain the value \n   is always present but if there's no data in it then the length will be \n   zero, so we perform a check for a buffer with a length of zero and set \n   the buffer pointer to NULL if this is the case */\n\n#define initBoundData( boundData ) \\\n\t\tmemset( ( boundData ), 0, sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS )\n#define setBoundData( bdStorage, bdIndex, bdValue, bdValueLen ) \\\n\t\t{ \\\n\t\tconst int bdLocalIndex = ( bdIndex ); \\\n\t\t\\\n\t\t( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_STRING; \\\n\t\t( bdStorage )[ bdLocalIndex ].data = ( bdValueLen > 0 ) ? bdValue : NULL; \\\n\t\t( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \\\n\t\t}\n#define setBoundDataBlob( bdStorage, bdIndex, bdValue, bdValueLen ) \\\n\t\t{ \\\n\t\tconst int bdLocalIndex = ( bdIndex ); \\\n\t\t\\\n\t\t( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_BLOB; \\\n\t\t( bdStorage )[ bdLocalIndex ].data = bdValue; \\\n\t\t( bdStorage )[ bdLocalIndex ].dataLength = bdValueLen; \\\n\t\t}\n#define setBoundDataDate( bdStorage, bdIndex, bdValue ) \\\n\t\t{ \\\n\t\tconst int bdLocalIndex = ( bdIndex ); \\\n\t\t\\\n\t\t( bdStorage )[ bdLocalIndex ].type = BOUND_DATA_TIME; \\\n\t\t( bdStorage )[ bdLocalIndex ].data = bdValue; \\\n\t\t( bdStorage )[ bdLocalIndex ].dataLength = sizeof( time_t ); \\\n\t\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Keyset Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A structure to parse the database access information into so that it can \n   be used by backend-specific connect functions */\n\ntypedef struct {\n\tBUFFER( CRYPT_MAX_TEXTSIZE, userLen ) \\\n\tchar userBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER_OPT( CRYPT_MAX_TEXTSIZE, userLen ) \\\n\tchar *user;\n\tBUFFER( CRYPT_MAX_TEXTSIZE, passwordLen ) \\\n\tchar passwordBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER_OPT( CRYPT_MAX_TEXTSIZE, passwordLen ) \\\n\tchar *password;\n\tBUFFER( CRYPT_MAX_TEXTSIZE, serverLen ) \\\n\tchar serverBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER_OPT( CRYPT_MAX_TEXTSIZE, serverLen ) \\\n\tchar *server;\n\tBUFFER( CRYPT_MAX_TEXTSIZE, nameLen ) \\\n\tchar nameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER_OPT( CRYPT_MAX_TEXTSIZE, nameLen ) \\\n\tchar *name;\n\tint userLen, passwordLen, serverLen, nameLen;\n\t} DBMS_NAME_INFO;\n\n/* Database state information maintained by the database back-end specific \n   code */\n\ntypedef struct {\n\t/* DBMS status information */\n\tBOOLEAN needsUpdate;\t\t\t/* Whether data remains to be committed */\n\tBOOLEAN hasBinaryBlobs;\t\t\t/* Whether back-end supports binary blobs */\n\n\t/* Error information returned by the back-end.  This is copied over to \n\t   the keyset object as required */\n\tERROR_INFO errorInfo;\n\n\t/* Database-specific information */\n  #ifdef USE_ODBC\n\t/* ODBC access information */\n\tSQLHENV hEnv;\t\t\t\t\t/* Environment handle */\n\tSQLHDBC hDbc;\t\t\t\t\t/* Connection handle */\n\tBOOLEAN connectionOpen;\t\t\t/* Whether hDbc connection is active */\n\tARRAY_FIXED( NO_CACHED_QUERIES ) \\\n\tSQLHSTMT hStmt[ NO_CACHED_QUERIES + 8 ];/* Statement handles */\n\tARRAY_FIXED( NO_CACHED_QUERIES ) \\\n\tBOOLEAN hStmtPrepared[ NO_CACHED_QUERIES + 8 ];/* Whether stmt is prepared on handle */\n\tBOOLEAN transactIsDestructive;\t/* Whether commit/rollback destroys prep'd queries */\n\tSQLSMALLINT blobType;\t\t\t/* SQL type of blob data type */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, blobNameLength ) \\\n\tchar blobName[ CRYPT_MAX_TEXTSIZE + 8 ];/* Name of blob data type */\n\tint blobNameLength;\t\t\t\t/* Length of blob data type name */\n\tSQLULEN dateTimeNameColSize;\t/* Back-end specific size of datetime column */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, dateTimeNameLength ) \\\n\tchar dateTimeName[ CRYPT_MAX_TEXTSIZE + 8 ];/* Name of datetime data type */\n\tint dateTimeNameLength;\t\t\t/* Length of datetime data type name */\n\tBOOLEAN needLongLength;\t\t\t/* Back-end needs blob length at bind.time */\n\tint backendType;\t\t\t\t/* Back-end type if special handling is req'd */\n  #endif /* USE_ODBC */\n  #ifdef USE_DATABASE\n\t#error Need to add database backend-specific state variables\n  #endif /* USE_DATABASE */\n  #ifdef USE_TCP\n\tSTREAM stream;\t\t\t\t\t/* Network I/O stream */\n  #endif /* USE_TCP */\n\t} DBMS_STATE_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDBMS Access Macros\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Macros to make use of the DBMS access functions less painful.  These \n   assume the existence of a variable 'dbmsInfo' that contains DBMS access\n   state information */\n\n#define dbmsOpen( name, nameLen, isReadOnly, featureFlags ) \\\n\t\tdbmsInfo->openDatabaseFunction( dbmsInfo, name, nameLen, isReadOnly, featureFlags )\n#define dbmsClose() \\\n\t\tdbmsInfo->closeDatabaseFunction( dbmsInfo )\n#define dbmsStaticUpdate( command ) \\\n\t\tdbmsInfo->performStaticUpdateFunction( dbmsInfo, command )\n#define dbmsUpdate( command, updateBoundData, updateType ) \\\n\t\tdbmsInfo->performUpdateFunction( dbmsInfo, command, updateBoundData, \\\n\t\t\t\t\t\t\t\t\t\t updateType )\n#define dbmsStaticQuery( command, queryEntry, queryType ) \\\n\t\tdbmsInfo->performStaticQueryFunction( dbmsInfo, command, queryEntry, \\\n\t\t\t\t\t\t\t\t\t\t\t  queryType )\n#define dbmsQuery( command, data, dataMaxLength, dataLength, queryBoundData, queryEntry, queryType ) \\\n\t\tdbmsInfo->performQueryFunction( dbmsInfo, command, data, dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\tdataLength, queryBoundData, queryEntry, \\\n\t\t\t\t\t\t\t\t\t\tqueryType )\n\n#ifdef USE_RPCAPI\nint cmdClose( void *stateInfo, COMMAND_INFO *cmd );\nint cmdGetErrorInfo( void *stateInfo, COMMAND_INFO *cmd );\nint cmdOpen( void *stateInfo, COMMAND_INFO *cmd );\nint cmdQuery( void *stateInfo, COMMAND_INFO *cmd );\nint cmdUpdate( void *stateInfo, COMMAND_INFO *cmd );\n#endif /* USE_RPCAPI */\n\n/* In order to provide access to the backend-specific error information for\n   the cryptlib error message-formatting routines we need to dig down into \n   the DBMS state structure to extract the error information */\n\n#define getDbmsErrorInfo( dbmsInfo ) \\\n\t\t( &( ( ( DBMS_STATE_INFO * ) ( dbmsInfo )->stateInfo )->errorInfo ) )\n\n/* Other non-macro functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint dbmsFormatQuery( OUT_BUFFER( outMaxLength, *outLength ) char *output, \n\t\t\t\t\t IN_LENGTH_SHORT const int outMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( outMaxLength ) int *outLength,\n\t\t\t\t\t IN_BUFFER( inputLength ) const char *input, \n\t\t\t\t\t IN_LENGTH_SHORT const int inputLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint dbmsParseName( OUT DBMS_NAME_INFO *nameInfo, \n\t\t\t\t   IN_BUFFER( nameLen ) const char *name, \n\t\t\t\t   IN_LENGTH_NAME const int nameLen );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDBMS Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Forward declaration for argument to function pointers.  These structs are\n   declared in keyset.h, but that's included after dbms.h since the structs\n   in keyset.h depend on values in dbms.h */\n\nstruct DI;\nstruct KI;\n\n/* Prototypes for interface routines in DBMS modules */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDbxSession( INOUT struct KI *keysetInfoPtr, \n\t\t\t\t\tIN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE type );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint endDbxSession( INOUT struct KI *keysetInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSread( INOUT struct KI *keysetInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSwrite( INOUT struct KI *keysetInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSCA( INOUT struct KI *keysetInfoPtr );\n\n/* Prototypes for functions in dbx_rd.c/dbx_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \\\nint getItemData( INOUT struct DI *dbmsInfo, \n\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t OUT_OPT int *stateInfo, \n\t\t\t\t IN_ENUM_OPT( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t IN_ENUM_OPT( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype, \n\t\t\t\t IN_BUFFER_OPT( keyValueLength ) const char *keyValue, \n\t\t\t\t IN_LENGTH_KEYID_Z const int keyValueLength,\n\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options,\n\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint addCert( INOUT struct DI *dbmsInfo, \n\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE certType, \n\t\t\t IN_ENUM( CERTADD ) const CERTADD_TYPE addType,\n\t\t\t IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType, \n\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint addCRL( INOUT struct DI *dbmsInfo, \n\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCRL,\n\t\t\tIN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptRevokeCert,\n\t\t\tIN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType, \n\t\t\tINOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for routines in dbx_misc.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint makeKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t   IN_LENGTH_SHORT_MIN( ENCODED_DBXKEYID_SIZE ) \\\n\t\t\t\t\tconst int keyIdMaxLen,\n\t\t\t   OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE iDtype,\n\t\t\t   IN_BUFFER( idValueLength ) const void *idValue,\n\t\t\t   IN_LENGTH_SHORT const int idValueLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t  IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyIDtype );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getCertKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getPkiUserKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCryptCert );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint extractCertData( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert, \n\t\t\t\t\t IN_INT const int formatType,\n\t\t\t\t\t OUT_BUFFER( certDataMaxLength, *certDataLength ) \\\n\t\t\t\t\t\tvoid *certDataBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\tconst int certDataMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certDataMaxLength ) \\\n\t\t\t\t\t\tint *certDataLength );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint resetErrorInfo( INOUT struct DI *dbmsInfo );\nCHECK_RETVAL_PTR \\\nchar *getKeyName( IN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype );\n\n/* Prototypes for routines in ca_add.c */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkRequest( IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint caAddCertRequest( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE requestType, \n\t\t\t\t\t  const BOOLEAN isRenewal, const BOOLEAN isInitialOp,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint caAddPKIUser( INOUT struct DI *dbmsInfo, \n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iPkiUser,\n\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint caDeletePKIUser( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t IN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for routines in ca_clean.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint caCleanup( INOUT struct DI *dbmsInfo, \n\t\t\t   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t   INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for routines in ca_issue.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint completeCertRenewal( INOUT struct DI *dbmsInfo,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iReplaceCertificate,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint caIssueCert( INOUT struct DI *dbmsInfo, \n\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE caKey,\n\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint caIssueCertComplete( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t\t IN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for routines in ca_rev.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint revokeCertDirect( INOUT struct DI *dbmsInfo,\n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\t  IN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint caRevokeCert( INOUT struct DI *dbmsInfo, \n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t  IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action,\n\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint caIssueCRL( INOUT struct DI *dbmsInfo, \n\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCRL,\n\t\t\t\tIN_HANDLE const CRYPT_CONTEXT caKey, \n\t\t\t\tINOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for routines in ca_misc.c */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint updateCertLog( INOUT struct DI *dbmsInfo, \n\t\t\t\t   IN_ENUM( CRYPT_CERTACTION ) const CRYPT_CERTACTION_TYPE action, \n\t\t\t\t   IN_BUFFER_OPT( certIDlength ) const char *certID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int certIDlength,\n\t\t\t\t   IN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int reqCertIDlength,\n\t\t\t\t   IN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int subjCertIDlength,\n\t\t\t\t   IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int dataLength, \n\t\t\t\t   IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType );\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateCertErrorLog( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\tIN_ERROR const int errorStatus,\n\t\t\t\t\t\tIN_STRING const char *errorString, \n\t\t\t\t\t\tIN_BUFFER_OPT( certIDlength ) const char *certID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int certIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( reqCertIDlength ) const char *reqCertID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int reqCertIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( subjCertIDlength ) const char *subjCertID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int subjCertIDlength,\n\t\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataLength );\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateCertErrorLogMsg( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t   IN_ERROR const int errorStatus,\n\t\t\t\t\t\t   IN_STRING const char *errorString );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint caGetIssuingUser( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iPkiUser,\n\t\t\t\t\t  IN_BUFFER( initialCertIDlength ) const char *initialCertID, \n\t\t\t\t\t  IN_LENGTH_FIXED( ENCODED_DBXKEYID_SIZE ) \\\n\t\t\t\t\t\tconst int initialCertIDlength, \n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\n\n#endif /* _DBMS_DEFINED */\n\n"
  },
  {
    "path": "deps/cl345/keyset/dbx_misc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib DBMS Misc Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/* The table structure for the various DBMS tables is (# = indexed, \n   * = unique, + = certificate store only):\n\n\tcertificates:\n\t\tC, SP, L, O, OU, CN, email#, validTo, nameID#, issuerID#*, keyID#*, certID#*, certData\n\tCRLs:\n\t\texpiryDate+, nameID+, issuerID#*, certID#+, crl.certData\n\tpkiUsers+:\n\t\tC, SP, L, O, OU, CN, nameID#*, user.keyID#*, user.certID, user.certData\n\tcertRequests+:\n\t\ttype, C, SP, L, O, OU, CN, email, req.certID, req.certData\n\tcertLog+:\n\t\taction, date, certID#*, req.certID, subjCertID, log.certData\n\n   Note that in the CRL table the certID is the ID of the certificate being \n   revoked and not of the per-entry CRL data, and in the  PKIUsers table the \n   keyID isn't for a public key but a nonce used to identify the PKI user \n   and the nameID is used purely to ensure uniqueness of users.\n\n   The certificate store contains a table for logging certificate management \n   operations (e.g. when issued, when revoked, etc etc).  The operations are \n   tied together by the certID of the object that the log entry pertains to, \n   associated with this in the log are optional certIDs of the request that \n   caused the action to be taken and of the subject that was affected by the \n   request.  For example in the most complex case of a revocation operation\n   the certID would be of the CRL entry that was created, the req.certID\n   would be for the revocation request, and the subjCertID would be for the\n   certificate being revoked.  This allows a complete history of each item \n   to be built via the log.  The certLog has a UNIQUE INDEX on the certID \n   that detects attempts to add duplicates, although this unfortunately \n   requires the addition of dummy nonce certIDs to handle certain types of \n   actions that don't produce objects with certIDs (see the comment further \n   down on the use of constraints).\n\n   The handling for each type of CA management operation is:\n\n\tCERTACTION_REQUEST_CERT/CERTACTION_REQUEST_RENEWAL/\n\tCERTACTION_REQUEST_REVOCATION: Stores the incoming requests and \n\tgenerates a log entry.  Duplicate issue requests are detected by the \n\tcertLog.certID uniqueness constraint.  Available: request with certID: \n\n\t  INSERT INTO certRequests VALUES ( <type>, <DN components>, <certID>, <request> );\n\t  INSERT INTO certLog VALUES\n\t\t(ACTION_REQUEST_CERT/RENEWAL/REVOCATION, $date, <certID>, NULL, NULL,\n\t\t  <request>);\n\n\tCERTACTION_ISSUE_CERT/CERTACTION_CERT_CREATION: Add the certificate and  \n\tremove the issue request.  Duplicate certificate issuance is detected by  \n\tthe certLog.certID uniqueness constraint.  Available: request with \n\treq.certID, certificate with certID\n\n\t  INSERT INTO certificates VALUES (<DN components>, <IDs>, <cert>);\n\t  INSERT INTO certLog VALUES\n\t\t(ACTION_ISSUE_CERT/CERT_CREATION, $date, <certID>, <req.certID>, NULL,\n\t\t  <cert>);\n\t  DELETE FROM certRequests WHERE certID = <req.certID>;\n\n\tCERTACTION_ISSUE_CRL: Read each CRL entry with caCert.nameID and \n\tassemble the full CRL.  Requires an ongoing query:\n\n\t  SELECT FROM CRLs WHERE nameID = <caCert.nameID>\n\n\tCERTACTION_REVOKE_CERT: Add the CRL entry that causes the revocation, \n\tdelete the certificate and the request that caused the action.  \n\tAvailable: request with req.certID, certificate with cert.certID, CRL \n\tentry with certID\n\n\t  INSERT INTO CRLs VALUES (<IDs>, <crlData>);\n\t  INSERT INTO certLog VALUES\n\t\t(ACTION_REVOKE_CERT, $date, <nonce>, <req.certID>, <cert.certID>, <crlData>);\n\t  DELETE FROM certRequests WHERE certID = <req.certID>;\n\t  DELETE FROM certificates WHERE certID = <cert.certID>;\n\n\tCERTACTION_EXPIRE_CERT/CERTACTION_RESTART_CLEANUP: Delete each expired \n\tentry or clean up leftover certificate requests after a restart.  The \n\tlogging for these is a bit tricky, ideally we'd want to \"INSERT INTO \n\tcertLog VALUES (ACTION_CERT_EXPIRE, $date, SELECT certID FROM \n\tcertificates WHERE validTo <= $date)\" or the cleanup equivalent, however \n\tthis isn't possible both because it's not possible to mix static values \n\tand a select result in an INSERT and because the certID is already \n\tpresent from when the certificate/request was originally added.  We can \n\tfix the former by making the static values part of the select result, \n\ti.e. \"INSERT INTO certLog VALUES SELECT ACTION_CERT_EXPIRE, $date, \n\tcertID FROM certificates WHERE validTo <= $date\" but this still doesn't \n\tfix the problem with the duplicate IDs.  In fact there isn't really a \n\tcertID present since it's an implicit action, but we can't make the \n\tcertID column null since it's not possible to index nullable columns.  \n\tAs a result the only way that we can do it is to repetitively perform \n\t\"SELECT certID FROM certificates WHERE validTo <= $date\" (or the \n\tequivalent cleanup select) and for each time it succeeds follow it with:\n\n\t  INSERT INTO certLog VALUES\n\t\t(ACTION_EXPIRE_CERT, $date, <nonce>, NULL, <certID>);\n\t  DELETE FROM certificates WHERE certID = <certID>\n\n\tor\n\n\t  INSERT INTO certLog VALUES\n\t\t(ACTION_RESTART_CLEANUP, $date, <nonce>, NULL, <certID>);\n\t  DELETE FROM certRequests WHERE certID = <certID>\n\n\tThis has the unfortunate side-effect that the update isn't atomic, we \n\tcould enforce this with \"LOCK TABLE <name> IN EXCLUSIVE MODE\" but the MS \n\tdatabases don't support this and either require the use of baroque \n\tmechanisms such as a \"(TABLOCKX HOLDLOCK)\" as a locking hint after the \n\ttable name in the first statement after the transaction is begun or \n\tdon't support this type of locking at all.  Because of this it isn't \n\treally possible to make the update atomic, in particular for the cleanup \n\toperation we rely on the caller to perform it at startup before anyone \n\telse accesses the certificate store.  The fact that the update isn't \n\tquite atomic isn't really a major problem, at worst it'll result in \n\teither an expired certificate being visible or a leftover request \n\tblocking a new request for a split second longer than they should.\n\t\n\tAn additional feature that we could make use of for CA operations is the \n\tuse of foreign keys to ensure referential integrity, usually via entries \n\tin the certificate log.  \n\t\n\tIt's not clear though what the primary key (or keys in different tables) \n\tshould be.  We can't use certificates.certID as a foreign key for CRLs \n\tbecause a general-purpose certificate keyset (rather than specifically a \n\tCA certificate store) can store any CRLs and not just ones for \n\tcertificates in the keyset.  In addition we want to return the CRL entry \n\teven if the certificate is deleted (in fact the creation of the CRL \n\tentry implies the deletion of the corresponding certificate entry).  The \n\tcertificate store isn't something like a customer database where \n\teverything is tied to a unique customer ID but more a transactional \n\tsystem where an object appearing in one table requires the deletion of a \n\tcorresponding object in another table (e.g. certificate request -> \n\tcertificate, revocation request -> CRL + certificate deletion) which \n\tcan't be easily handled with something as simple as a foreign key but \n\thas to be done with transactions.\n\t\n\tWe could in theory require that all certificate requests be authorised \n\tby adding an authCertID column to the certReq table and constraining it \n\twith:\n\n\t\tFOREIGN KEY (authCertID) REFERENCES certLog.reqCertID\n\n\tbut even then (apart from the overhead of adding extra indexed columns \n\tjust to ensure referential integrity) the syntax for this varies \n\tsomewhat between vendors so that it'd require assorted rewriting by the \n\tback-end glue code to handle the different requirements for each \n\tdatabase type.  In addition since the foreign key constraint is \n\tspecified at table create time we could experience strange failures on \n\ttable creation requiring special-purpose workarounds where we remove the \n\tforeign-key constraint in the hope that the table create then succeeds.\n\n\tAn easier way to handle this is via manual references to entries in the \n\tcertificate log.  Since this is append-only, a manual presence check can \n\tnever return an incorrect result (an entry can't be removed between time \n\tof check and time of use) so this provides the same result as using \n\treferential integrity mechanisms.\n\n\tAnother database feature that we could use is database triggers as a \n\tbackup for the access control settings.  For example (using one \n\tparticular SQL dialect) we could say:\n\n\t\tCREATE TRIGGER checkLog ON certLog FOR UPDATE, DELETE AS\n\t\t\tBEGIN\n\t\t\t\tROLLBACK\n\t\t\tEND\n\n\tHowever as the \"dialect\" reference in the above comment implies this \n\tprocess is *extremely* back-end specific (far more so than access \n\tcontrols and the use of foreign keys) so we can't really do much here \n\twithout ending up having to set different triggers for each back-end \n\ttype and even back-end version.\n\n\tA final feature that we could in theory use is the ability to impose \n\tuniqueness constraints based on more than one column, for example the \n\tcertLog 'action' and 'certID' could be handled using a constraint of:\n\n\t\tUNIQUE (action, certID)\n\n\thowever this isn't desirable for all combinations of (action, certID) \n\tbut only some, so that just the certID by itself must be unique in most \n\tcases except for one or two where it's sufficient that (action, certID) \n\tbe unique.  Because of this, as with foreign keys, we need to enforce \n\tthe constraint via transactions, which gives us more control over how \n\tthings are handled */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up key ID information for a query.  There are two variations of\n   this, makeKeyID() encodes an existing keyID value and getKeyID() reads an\n   attribute from an object and encodes it using makeKeyID() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint makeKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t   IN_LENGTH_SHORT_MIN( ENCODED_DBXKEYID_SIZE ) \\\n\t\t\t\t\tconst int keyIdMaxLen,\n\t\t\t   OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE iDtype, \n\t\t\t   IN_BUFFER( idValueLength ) const void *idValue, \n\t\t\t   IN_LENGTH_SHORT const int idValueLength )\n\t{\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint idLength = idValueLength, status;\n\n\tassert( isWritePtrDynamic( keyID, keyIdMaxLen ) );\n\tassert( isWritePtr( keyIdLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( keyID, idValueLength ) );\n\n\tREQUIRES( keyIdMaxLen >= ENCODED_DBXKEYID_SIZE && \\\n\t\t\t  keyIdMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( iDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  iDtype == CRYPT_KEYID_URI || \\\n\t\t\t  iDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  iDtype == CRYPT_IKEYID_ISSUERID || \\\n\t\t\t  iDtype == CRYPT_IKEYID_CERTID );\n\tREQUIRES( isShortIntegerRangeNZ( idValueLength ) );\n\n\t/* Clear return values */\n\tmemset( keyID, 0, min( 16, keyIdMaxLen ) );\n\t*keyIdLen = 0;\n\n\t/* Name and email address are used as is */\n\tif( iDtype == CRYPT_KEYID_NAME || iDtype == CRYPT_KEYID_URI )\n\t\t{\n\t\tif( idLength > CRYPT_MAX_TEXTSIZE * 2 )\n\t\t\t{\n\t\t\t/* Truncate to the database column size */\n\t\t\tidLength = CRYPT_MAX_TEXTSIZE * 2;\n\t\t\t}\n\t\tif( idLength > keyIdMaxLen )\n\t\t\t{\n\t\t\t/* Truncate to the output buffer size */\n\t\t\tidLength = keyIdMaxLen;\n\t\t\t}\n\t\tREQUIRES( rangeCheck( idLength, 1, keyIdMaxLen ) );\n\t\tmemcpy( keyID, idValue, idLength );\n\t\tif( iDtype == CRYPT_KEYID_URI )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\t/* Force the search URI to lowercase to make case-insensitive \n\t\t\t   matching easier.  In most cases we could ask the back-end to \n\t\t\t   do this but this complicates indexing and there's no reason \n\t\t\t   why we can't do it here */\n\t\t\tLOOP_LARGE( i = 0, i < idLength, i++ )\n\t\t\t\tkeyID[ i ] = intToByte( toLower( keyID[ i ] ) );\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\t*keyIdLen = idLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* A keyID is just a subjectKeyIdentifier, which is already supposed to \n\t   be an SHA-1 hash but which in practice can be almost anything so we\n\t   always hash it to a fixed-length value */\n\tif( iDtype == CRYPT_IKEYID_KEYID )\n\t\t{\n\t\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\n\t\t/* Get the hash algorithm information and hash the keyID to get\n\t\t   the fixed-length keyID */\n\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t\t NULL );\n\t\thashFunctionAtomic( hashBuffer, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\t\tidValue, idValueLength );\n\t\tidValue = hashBuffer;\n\t\tidLength = DBXKEYID_SIZE;\n\t\t}\n\n\tENSURES( idLength >= DBXKEYID_SIZE && idLength <= keyIdMaxLen );\n\n\t/* base64-encode the key ID so that we can use it with database queries.\n\t   Since we only store 128 bits of a (usually 160 bit) ID to save space\n\t   (particularly where it's used in indices) and to speed lookups, this\n\t   encoding step has the side-effect of truncating the ID down to the\n\t   correct size */\n\tstatus = base64encode( keyID, keyIdMaxLen, keyIdLen, idValue, \n\t\t\t\t\t\t   DBXKEYID_SIZE, CRYPT_CERTTYPE_NONE );\n\tENSURES( cryptStatusOK( status ) );\n\tENSURES( *keyIdLen == ENCODED_DBXKEYID_SIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE keyIDtype )\n\t{\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtrDynamic( keyID, keyIdMaxLen ) );\n\tassert( isWritePtr( keyIdLen, sizeof( int ) ) );\n\n\tREQUIRES( keyIdMaxLen >= 16 && keyIdMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( ( keyIDtype == CRYPT_CERTINFO_FINGERPRINT_SHA1 || \\\n\t\t\t\tkeyIDtype == CRYPT_IATTRIBUTE_AUTHCERTID ) || \\\n\t\t\t  ( keyIDtype == CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER || \\\n\t\t\t\tkeyIDtype == CRYPT_IATTRIBUTE_ISSUER || \\\n\t\t\t\tkeyIDtype == CRYPT_IATTRIBUTE_SUBJECT || \\\n\t\t\t\tkeyIDtype == CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER || \\\n\t\t\t\tkeyIDtype == CRYPT_IATTRIBUTE_SPKI ) );\n\n\t/* Clear return values */\n\tmemset( keyID, 0, min( 16, keyIdMaxLen ) );\n\t*keyIdLen = 0;\n\n\t/* Get the attribute from the certificate and hash it, unless it's \n\t   already a hash */\n\tif( keyIDtype == CRYPT_CERTINFO_FINGERPRINT_SHA1 || \\\n\t\tkeyIDtype == CRYPT_IATTRIBUTE_AUTHCERTID )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, hashBuffer, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, keyIDtype );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES( msgData.length == KEYID_SIZE );\n\t\t}\n\telse\n\t\t{\n\t\tDYNBUF idDB;\n\t\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\t\tint hashSize;\n\n\t\t/* Get the attribute data and hash it to get the ID */\n\t\tstatus = dynCreate( &idDB, iCryptHandle, keyIDtype );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t\t &hashSize );\n\t\thashFunctionAtomic( hashBuffer, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\t\tdynData( idDB ), dynLength( idDB ) );\n\t\tENSURES( hashSize == KEYID_SIZE );\n\t\tdynDestroy( &idDB );\n\t\t\n\t\t/* If we're generating an identifier by reading (and hashing) the \n\t\t   SubjectPublicKeyInfo then we have to hash it a second time in\n\t\t   order to match a cryptlib-generated keyID.  This is required \n\t\t   because cryptlib's CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER is a hash \n\t\t   of the SubjectPublicKeyInfo, but this is then hashed again to \n\t\t   turn the potentially arbitrary-form value from a non-cryptlib \n\t\t   certificate into a fixed-length ID (see the comment in \n\t\t   getCertKeyID() for more details).  \n\t\t   \n\t\t   Because of this second hash that's applied to the \n\t\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER we have to hash the value \n\t\t   that we've generated ourselves from the raw SubjectPublicKeyInfo \n\t\t   a second time to get the same value.\n\t\t   \n\t\t   This normally only happens with the rare non-cryptlib \n\t\t   certificates that don't have a \n\t\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER present, but can also occur \n\t\t   if the user is running cryptlib at a reduced compliance level at\n\t\t   which the CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER isn't processed.  \n\t\t   The second level of hashing means that the explicitly-generated\n\t\t   keyID value is the same as the implicitly-generated one that's\n\t\t   been skipped at the reduced compliance level */\n\t\tif( keyIDtype == CRYPT_IATTRIBUTE_SPKI )\n\t\t\t{\n\t\t\thashFunctionAtomic( hashBuffer, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\t\t\thashBuffer, KEYID_SIZE );\n\t\t\t}\n\t\t}\n\n\t/* Turn the binary ID data into text form that can be added to/used to \n\t   search a database, see makeKeyID() for details */\n\tstatus = base64encode( keyID, keyIdMaxLen, keyIdLen, hashBuffer, \n\t\t\t\t\t\t   DBXKEYID_SIZE, CRYPT_CERTTYPE_NONE );\n\tENSURES( cryptStatusOK( status ) );\n\tENSURES( *keyIdLen == ENCODED_DBXKEYID_SIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get a keyID for a certificate or a pkiUser */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getCertKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tint status;\n\n\tassert( isWritePtrDynamic( keyID, keyIdMaxLen ) );\n\tassert( isWritePtr( keyIdLen, sizeof( int ) ) );\n\n\tREQUIRES( keyIdMaxLen >= 16 && keyIdMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* Clear return values */\n\tmemset( keyID, 0, min( 16, keyIdMaxLen ) );\n\t*keyIdLen = 0;\n\n\t/* Certificate keyID handling isn't quite as simple as just reading an\n\t   attribute from the certificate since the subjectKeyIdentifier (if\n\t   present) may not be the same as the keyID if the certificate has come \n\t   from a CA that does strange things with the sKID.  To resolve this we \n\t   first try and build the key ID from the sKID.  Since it's possible \n\t   to stuff anything in there the sKID may have a nonstandard length, \n\t   so getKeyID() hashes it to the standard size after reading it */\n\tstatus = getKeyID( keyID, keyIdMaxLen, keyIdLen, iCryptCert,\n\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\tif( cryptStatusOK( status ) )\n\t\treturn( status );\n\n\t/* There's no subjectKeyIdentifier, use the keyID.  We can't just read \n\t   the CRYPT_IATTRIBUTE_KEYID attribute directly since this may be a \n\t   data-only certificate (either a standalone certificate or one from \n\t   the middle of a chain) so we have to generate it indirectly by \n\t   hashing the SubjectPublicKeyInfo, which is equivalent to the keyID \n\t   and is always present in a certificate */\n\treturn( getKeyID( keyID, keyIdMaxLen, keyIdLen, iCryptCert, \n\t\t\t\t\t  CRYPT_IATTRIBUTE_SPKI ) );\n\t}\n\n#ifdef USE_PKIUSER\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getPkiUserKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( keyIdMaxLen ) int *keyIdLen,\n\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE binaryKeyID[ 64 + 8 ];\n\tchar encKeyID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint binaryKeyIDlength DUMMY_INIT, status;\n\n\tassert( isWritePtrDynamic( keyID, keyIdMaxLen ) );\n\tassert( isWritePtr( keyIdLen, sizeof( int ) ) );\n\n\tREQUIRES( keyIdMaxLen >= 16 && keyIdMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* Clear return values */\n\tmemset( keyID, 0, min( 16, keyIdMaxLen ) );\n\t*keyIdLen = 0;\n\n\t/* Get the keyID as the PKI user ID.  We can't read this directly since \n\t   it's returned in text form for use by end users so we have to read \n\t   the encoded form, decode it, and then turn the decoded binary value \n\t   into a key ID.  We identify the result as a keyID, \n\t   (== subjectKeyIdentifier, which it isn't really) but we need to use \n\t   this to ensure that it's hashed/expanded out to the correct size */\n\tsetMessageData( &msgData, encKeyID, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_PKIUSER_ID );\n\tif( cryptStatusOK( status ) )\n\t\tstatus =  decodePKIUserValue( binaryKeyID, 64, &binaryKeyIDlength, \n\t\t\t\t\t\t\t\t\t  encKeyID, msgData.length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( isShortIntegerRangeNZ( binaryKeyIDlength ) );\n\treturn( makeKeyID( keyID, keyIdMaxLen, keyIdLen, CRYPT_IKEYID_KEYID, \n\t\t\t\t\t   binaryKeyID, binaryKeyIDlength ) );\n\t}\n#endif /* USE_PKIUSER */\n\n/* Extract certificate data from a certificate object.  Note that the \n   formatType is given as an int rather than an enumerated type because\n   it can be either a CRYPT_CERTFORMAT_TYPE or a CRYPT_ATTRIBUTE_TYPE */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint extractCertData( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert, \n\t\t\t\t\t IN_INT const int formatType,\n\t\t\t\t\t OUT_BUFFER( certDataMaxLength, *certDataLength ) \\\n\t\t\t\t\t\tvoid *certDataBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\tconst int certDataMaxLength, \n\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certDataMaxLength ) \\\n\t\t\t\t\t\tint *certDataLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtrDynamic( certDataBuffer, certDataMaxLength ) );\n\tassert( isWritePtr( certDataLength, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( formatType == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\t\t  formatType == CRYPT_ICERTFORMAT_DATA || \\\n\t\t\t  formatType == CRYPT_IATTRIBUTE_CRLENTRY );\n\tREQUIRES( certDataMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  certDataMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Make sure that there's no collision in format type values (although \n\t   the switch() statement will also catch this by producing a compile \n\t   error */\n\tstatic_assert( CRYPT_CERTFORMAT_CERTIFICATE != CRYPT_ICERTFORMAT_DATA && \\\n\t\t\t\t   CRYPT_CERTFORMAT_CERTIFICATE != CRYPT_IATTRIBUTE_CRLENTRY, \\\n\t\t\t\t   \"Format type collision\" );\n\n\t/* Clear return values */\n\tmemset( certDataBuffer, 0, min( 16, certDataMaxLength ) );\n\t*certDataLength = 0;\n\n\t/* Extract the certificate object data */\n\tsetMessageData( &msgData, certDataBuffer, certDataMaxLength );\n\tswitch( formatType )\n\t\t{\n\t\tcase CRYPT_CERTFORMAT_CERTIFICATE:\n\t\tcase CRYPT_ICERTFORMAT_DATA:\n\t\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT,\n\t\t\t\t\t\t\t\t\t  &msgData, formatType );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IATTRIBUTE_CRLENTRY:\n\t\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t  &msgData, formatType );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*certDataLength = msgData.length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Some internal actions set extended error codes as a result of their \n   operation that the user shouldn't really see.  For example performing a \n   certificate cleanup will return a no-data-found error once the last \n   certificate is reached, which will be read by the user the next time that \n   they read the CRYPT_ATTRIBUTE_INT_ERRORCODE/CRYPT_ATTRIBUTE_INT_ERRORMESSAGE \n   even though the error came from a previous internal operation.  To avoid\n   this problem we clean up the error status information when it's been set \n   by an internal operation */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint resetErrorInfo( INOUT DBMS_INFO *dbmsInfo )\n\t{\n\tDBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;\n\tERROR_INFO *errorInfo = &dbmsStateInfo->errorInfo;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get names for various items */\n\nCHECK_RETVAL_PTR \\\nchar *getKeyName( IN_KEYID const CRYPT_KEYID_TYPE keyIDtype )\n\t{\n\tREQUIRES_N( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_NAME:\n\t\t\treturn( \"CN\" );\n\n\t\tcase CRYPT_KEYID_URI:\n\t\t\treturn( \"email\" );\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\treturn( \"keyID\" );\n\n\t\tcase CRYPT_IKEYID_SUBJECTID:\n\t\t\treturn( \"nameID\" );\n\n\t\tcase CRYPT_IKEYID_ISSUERID:\n\t\t\treturn( \"issuerID\" );\n\n\t\tcase CRYPT_IKEYID_CERTID:\n\t\t\treturn( \"certID\" );\n\t\t}\n\n\tretIntError_Null();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Access Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a new key database */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int createDatabase( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t\t\t   const BOOLEAN hasPermissions, \n\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tint updateProgress = 0, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( hasPermissions == TRUE || hasPermissions == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Create tables for certificates, CRLs, certificate requests, PKI \n\t   users, and CA logs.  We use CHAR rather than VARCHAR for the ID \n\t   fields since these always have a fixed length and CHAR is faster than \n\t   VARCHAR.  In addition we make as many columns as possible NOT NULL \n\t   since these fields should always be present and because this is  \n\t   faster for most databases.  The BLOB type is nonstandard, this is \n\t   rewritten by the database interface layer to the type which is \n\t   appropriate for the database */\n\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE certificates (\"\n\t\t\t\t\"C CHAR(2), \"\n\t\t\t\t\"SP VARCHAR(64), \"\n\t\t\t\t\"L VARCHAR(64), \"\n\t\t\t\t\"O VARCHAR(64), \"\n\t\t\t\t\"OU VARCHAR(64), \"\n\t\t\t\t\"CN VARCHAR(64), \"\n\t\t\t\t\"email VARCHAR(64), \"\n\t\t\t\t\"validTo DATETIME NOT NULL, \"\n\t\t\t\t\"nameID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"issuerID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"keyID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certData BLOB NOT NULL)\" );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't create certificate database: \" ) );\n\t\t}\n\tif( isCertStore( dbmsInfo ) )\n\t\t{\n\t\t/* The certificate store contains in addition to the other CRL \n\t\t   fields the certificate expiry time which is used to remove the \n\t\t   entry from the CRL table once the certificate has expired anyway, \n\t\t   the nameID which is used to force clustering of entries for each \n\t\t   CA, and the ID of the certificate being revoked, which isn't \n\t\t   available if we're creating it from a raw CRL */\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE CRLs (\"\n\t\t\t\t\"expiryDate DATETIME NOT NULL, \"\n\t\t\t\t\"nameID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"issuerID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL,\"\n\t\t\t\t\"certID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certData BLOB NOT NULL)\" );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tupdateProgress++;\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE pkiUsers (\"\n\t\t\t\t\"C CHAR(2), \"\n\t\t\t\t\"SP VARCHAR(64), \"\n\t\t\t\t\"L VARCHAR(64), \"\n\t\t\t\t\"O VARCHAR(64), \"\n\t\t\t\t\"OU VARCHAR(64), \"\n\t\t\t\t\"CN VARCHAR(64), \"\n\t\t\t\t\"nameID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"keyID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certData BLOB NOT NULL)\" );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tupdateProgress++;\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE certRequests (\"\n\t\t\t\t\"type SMALLINT NOT NULL, \"\n\t\t\t\t\"C CHAR(2), \"\n\t\t\t\t\"SP VARCHAR(64), \"\n\t\t\t\t\"L VARCHAR(64), \"\n\t\t\t\t\"O VARCHAR(64), \"\n\t\t\t\t\"OU VARCHAR(64), \"\n\t\t\t\t\"CN VARCHAR(64), \"\n\t\t\t\t\"email VARCHAR(64), \"\n\t\t\t\t\"certID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"certData BLOB NOT NULL)\" );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tupdateProgress++;\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE certLog (\"\n\t\t\t\t\"action SMALLINT NOT NULL, \"\n\t\t\t\t\"actionTime DATETIME NOT NULL, \"\n\t\t\t\t\"certID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL, \"\n\t\t\t\t\"reqCertID CHAR(\" TEXT_DBXKEYID_SIZE \"), \"\n\t\t\t\t\"subjCertID CHAR(\" TEXT_DBXKEYID_SIZE \"), \"\n\t\t\t\t\"certData BLOB)\" );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE TABLE CRLs (\"\n\t\t\t\t\"issuerID CHAR(\" TEXT_DBXKEYID_SIZE \") NOT NULL,\"\n\t\t\t\t\"certData BLOB NOT NULL)\" );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Undo the previous table creations */\n\t\tdbmsStaticUpdate( \"DROP TABLE certificates\" );\n\t\tif( updateProgress > 0 )\n\t\t\tdbmsStaticUpdate( \"DROP TABLE CRLs\" );\n\t\tif( updateProgress > 1 )\n\t\t\tdbmsStaticUpdate( \"DROP TABLE pkiUsers\" );\n\t\tif( updateProgress > 2 )\n\t\t\tdbmsStaticUpdate( \"DROP TABLE certRequests\" );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't create certificate%s database: \",\n\t\t\t\t\t isCertStore( dbmsInfo ) ? \" store\" : \"\" ) );\n\t\t}\n\n\t/* Create an index for the email address, nameID, issuerID, keyID, and\n\t   certID in the certificates table, the issuerID and certID in the CRLs\n\t   table (the CRL nameID isn't indexed since we only use it for linear\n\t   scans), the nameID and keyID in the PKI users table (the former isn't \n\t   used but is made a UNIQUE INDEX to ensure that the same entry can't \n\t   be added more than once) and the certID in the certificate log (this \n\t   also isn't used but is made a UNIQUE INDEX to ensure that the same \n\t   entry can't be added more than once).  In theory we could force the \n\t   UNIQUE constraint on the column rather than indirectly via an index \n\t   but some databases will quietly create a unique index anyway in order \n\t   to do that so we make the creation of the index explicit rather than \n\t   leaving it as a maybe/maybe not option for the database. + CRLF\n\t   \n\t   We have to give these unique names since some databases don't allow \n\t   two indexes to have the same name even if they're in a different \n\t   table.  Since most of the fields in the tables are supposed to be \n\t   unique we can specify this for the indexes that we're creating, \n\t   however we can't do it for the email address or the nameID in the \n\t   certificates table since there could be multiple certificates present \n\t   that differ only in key usage.  We don't index the other tables since \n\t   indexes consume space and we don't expect to access any of these \n\t   much */\n\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE INDEX emailIdx ON certificates(email)\" );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE INDEX nameIDIdx ON certificates(nameID)\" );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX issuerIDIdx ON certificates(issuerID)\" );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX keyIDIdx ON certificates(keyID)\" );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX certIDIdx ON certificates(certID)\" );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX crlIssuerIDIdx ON CRLs (issuerID)\" );\n\t\t}\n\tif( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )\n\t\t{\n\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX crlCertIDIdx ON CRLs (certID)\" );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX userKeyIDIdx ON pkiUsers (keyID)\" );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX userNameIDIdx ON pkiUsers (nameID)\" );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = dbmsStaticUpdate(\n\t\t\t\"CREATE UNIQUE INDEX logCertIDIdx ON certLog (certID)\" );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tchar dummyCertID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\t\t\tconst int dummyCertIDlength = ENCODED_DBXKEYID_SIZE;\n\n\t\t\t/* Create a special dummy certID with an out-of-band value to \n\t\t\t   mark the first entry in the log */\n\t\t\tmemset( dummyCertID, '-', ENCODED_DBXKEYID_SIZE );\n\n\t\t\t/* Add the initial log entry recording the creation of the \n\t\t\t   log */\n\t\t\tstatus = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CREATE,\n\t\t\t\t\t\t\t\t\tdummyCertID, dummyCertIDlength, \n\t\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, NULL, 0,\n\t\t\t\t\t\t\t\t\tDBMS_UPDATE_NORMAL );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Undo the creation of the various tables */\n\t\tdbmsStaticUpdate( \"DROP TABLE certificates\" );\n\t\tdbmsStaticUpdate( \"DROP TABLE CRLs\" );\n\t\tif( isCertStore( dbmsInfo ) )\n\t\t\t{\n\t\t\tdbmsStaticUpdate( \"DROP TABLE pkiUsers\" );\n\t\t\tdbmsStaticUpdate( \"DROP TABLE certRequests\" );\n\t\t\tdbmsStaticUpdate( \"DROP TABLE certLog\" );\n\t\t\t}\n\t\tretExtErr( CRYPT_ERROR_WRITE, \n\t\t\t\t   ( CRYPT_ERROR_WRITE, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Couldn't create indexes for certificate%s database: \",\n\t\t\t\t\t isCertStore( dbmsInfo ) ? \" store\" : \"\" ) );\n\t\t}\n\n\t/* If the back-end doesn't support access permissions (generally only \n\t   toy ones like Access and Paradox) or it's not a CA certificate \n\t   store, we're done */\n\tif( !hasPermissions || !isCertStore( dbmsInfo ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Set access controls for the certificate store tables:\n\n\t\t\t\t\t\tUsers\t\t\t\tCAs\n\t\tcertRequests:\t-\t\t\t\t\tINSERT,SELECT,DELETE\n\t\tcertificates:\tSELECT\t\t\t\tINSERT,SELECT,DELETE\n\t\tCRLs:\t\t\t-\t\t\t\t\tINSERT,SELECT,DELETE\n\t\tpkiUsers:\t\t-\t\t\t\t\tINSERT,SELECT,DELETE\n\t\tcertLog:\t\t-\t\t\t\t\tINSERT,SELECT\n\t\n\t   Once role-based access controls are enabled we can allow only the CA \n\t   user to update the certstore tables and allow others only read access \n\t   to the certificates table.  In addition the revocation should be \n\t   phrased as REVOKE ALL, GRANT <permitted> rather than revoking specific \n\t   privileges since each database vendor has their own nonstandard \n\t   additional privileges that a specific revoke won't cover.  \n\t   Unfortunately configuring this will be somewhat difficult since it\n\t   requires that cryptlib users create database user roles, which in turn\n\t   requires that they read the manual */\n#if 1\n\tdbmsStaticUpdate( \"REVOKE UPDATE ON certificates FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"REVOKE UPDATE ON CRLs FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"REVOKE UPDATE ON pkiUsers FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"REVOKE UPDATE ON certRequests FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"REVOKE DELETE,UPDATE ON certLog FROM PUBLIC\" );\n#else\n\tdbmsStaticUpdate( \"REVOKE ALL ON certificates FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"GRANT INSERT,SELECT,DELETE ON certificates TO ca\" );\n\tdbmsStaticUpdate( \"GRANT SELECT ON certificates TO PUBLIC\" );\n\tdbmsStaticUpdate( \"REVOKE ALL ON CRLs FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"GRANT INSERT,SELECT,DELETE ON CRLs TO ca\" );\n\tdbmsStaticUpdate( \"REVOKE ALL ON pkiUsers FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"GRANT INSERT,SELECT,DELETE ON pkiUsers TO ca\" );\n\tdbmsStaticUpdate( \"REVOKE ALL ON certRequests FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"GRANT INSERT,SELECT,DELETE ON certRequests TO ca\" );\n\tdbmsStaticUpdate( \"REVOKE ALL ON certLog FROM PUBLIC\" );\n\tdbmsStaticUpdate( \"GRANT INSERT,SELECT ON certLog TO ca\" );\n#endif /* 1 */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return status information for the keyset */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isBusyFunction( KEYSET_INFO *keysetInfoPtr )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_UPDATEACTIVE | \\\n\t\t\t\t\t\t\t\t\t\tDBMS_FLAG_QUERYACTIVE ) ? \\\n\t\t\t  TRUE : FALSE );\n\t}\n\n/* Open a connection to a database */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( nameLen ) const char *name,\n\t\t\t\t\t\t IN_LENGTH_NAME const int nameLen,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tDBMS_NAME_INFO nameInfo;\n\tconst BOOLEAN readOnly = \\\n\t\t\t\t\tTEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_READONLY ) ? \\\n\t\t\t\t\tTRUE : FALSE; \n\tint featureFlags, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLen ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( nameLen >= MIN_NAME_LENGTH && nameLen < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\n\t/* Parse the data source name.  The parsed form isn't needed at this \n\t   point but it allows us to return a more meaningful error response */\n\tstatus = dbmsParseName( &nameInfo, name, nameLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \"Invalid database name\" ) );\n\t\t}\n\n\t/* Perform a database back-end specific open */\n\tstatus = dbmsOpen( name, nameLen, readOnly, &featureFlags );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendDbxSession( keysetInfoPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* If the back-end is read-only (which would be extremely unusual, \n\t   usually related to misconfigured DBMS access permissions) and we're \n\t   not opening it in read-only mode, signal an error */\n\tif( ( featureFlags & DBMS_FEATURE_FLAG_READONLY ) && !readOnly )\n\t\t{\n\t\tendDbxSession( keysetInfoPtr );\n\t\tretExt( CRYPT_ERROR_PERMISSION, \n\t\t\t\t( CRYPT_ERROR_PERMISSION, KEYSET_ERRINFO, \n\t\t\t\t  \"Certificate database can only be accessed in read-only \"\n\t\t\t\t  \"mode\" ) );\n\t\t}\n\n\t/* If we're being asked to create a new database, create it and exit */\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\t{\n\t\tstatus = createDatabase( dbmsInfo, \n\t\t\t\t\t\t\t\t ( featureFlags & DBMS_FEATURE_FLAG_PRIVILEGES ) ? \\\n\t\t\t\t\t\t\t\t   TRUE : FALSE, KEYSET_ERRINFO );\n\t\tif( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )\n\t\t\t{\n\t\t\tstatus = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,\n\t\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, NULL, 0, NULL, 0,\n\t\t\t\t\t\t\t\t\tDBMS_UPDATE_NORMAL );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdbmsClose();\n\t\t\tendDbxSession( keysetInfoPtr );\n\n\t\t\t/* Since this function is called on object creation, if it fails \n\t\t\t   there's no object to get extended error information from so \n\t\t\t   we dump the error info as a diagnostic for debugging \n\t\t\t   purposes */\n#ifdef USE_ERRMSGS\n\t\t\tkeysetInfoPtr->errorInfo.errorString[ \\\n\t\t\t\t\tkeysetInfoPtr->errorInfo.errorStringLength ] = '\\0';\n#endif /* USE_ERRMSGS */\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* Check to see whether it's a certificate store.  We do this by \n\t   checking for the presence of the certificate store creation entry in \n\t   the log, this is always present with an action value of \n\t   CRYPT_CERTACTION_CREATE */\n\tstatus = dbmsStaticQuery(\n\t\t\t\"SELECT certData FROM certLog WHERE action = \"\n\t\t\t\tTEXT_CERTACTION_CREATE,\n\t\t\t\t\t\t\t  DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CHECK );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* It's a certificate store, if we're opening it as a non-certificate \n\t\t   store it has to be in read-only mode.  We return an error rather \n\t\t   than quietly changing the access mode to read-only both to make it \n\t\t   explicit to the user at open time that they can't make changes \n\t\t   and because we need to have the read-only flag set when we open \n\t\t   the database to optimise the buffering and locking strategy, \n\t\t   setting it at this point is too late */\n\t\tif( !isCertStore( dbmsInfo ) )\n\t\t\t{\n\t\t\tif( !readOnly )\n\t\t\t\t{\n\t\t\t\tdbmsClose();\n\t\t\t\tendDbxSession( keysetInfoPtr );\n\t\t\t\tretExt( CRYPT_ERROR_PERMISSION, \n\t\t\t\t\t\t( CRYPT_ERROR_PERMISSION, KEYSET_ERRINFO, \n\t\t\t\t\t\t  \"Certificate store can't be accessed as a normal \"\n\t\t\t\t\t\t  \"database except in read-only mode\" ) );\n\t\t\t\t}\n\n\t\t\t/* Remember that even though it's not functioning as a \n\t\t\t   certificate store we can still perform some extended queries \n\t\t\t   on it based on fields that are only present in certificate \n\t\t\t   stores */\n\t\t\tSET_FLAG( dbmsInfo->flags, DBMS_FLAG_CERTSTORE_FIELDS );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* If this isn't a read-only open, record a connection to the\n\t\t   store */\n\t\tif( !readOnly )\n\t\t\t{\n\t\t\tstatus = updateCertLog( dbmsInfo, CRYPT_CERTACTION_CONNECT,\n\t\t\t\t\t\t\t\t\tNULL, 0, NULL, 0, NULL, 0, NULL, 0,\n\t\t\t\t\t\t\t\t\tDBMS_UPDATE_NORMAL );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* This is a critical error, if we can't update the access \n\t\t\t\t   log at this point then it's not safe to use the \n\t\t\t\t   certificate store (if we fail during a general update \n\t\t\t\t   operation we give the caller the option of continuing \n\t\t\t\t   since the transaction itself will have been rolled back \n\t\t\t\t   so there's no permanent harm done) */\n\t\t\t\tif( status == CRYPT_ERROR_WRITE )\n\t\t\t\t\t{\n\t\t\t\t\t/* We'll usually fail at this point with a \n\t\t\t\t\t   CRYPT_ERROR_WRITE due to being unable to update the\n\t\t\t\t\t   cetificate store log, but this is rather confusing \n\t\t\t\t\t   for a keyset open so we convert it into a generic\n\t\t\t\t\t   CRYPT_ERROR_OPEN */\n\t\t\t\t\tstatus = CRYPT_ERROR_OPEN;\n\t\t\t\t\t}\n\t\t\t\tdbmsClose();\n\t\t\t\tendDbxSession( keysetInfoPtr );\n\t\t\t\tretExtArg( status, \n\t\t\t\t\t\t   ( status, KEYSET_ERRINFO, \n\t\t\t\t\t\t\t \"Couldn't update certificate store log\" ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's not a certificate store, if the DBMS information indicates that \n\t   we're expecting to open it as one tell the caller */\n\tif( isCertStore( dbmsInfo ) )\n\t\t{\n\t\tdbmsClose();\n\t\tendDbxSession( keysetInfoPtr );\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t \"Keyset isn't a certificate store\" ) );\n\t\t}\n\n\t/* Since the failure of the query above will set the extended error\n\t   information we have to explicitly clear it here to avoid making the\n\t   (invisible) query side-effects visible to the user */\n\tresetErrorInfo( dbmsInfo );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Close the connection to a database */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\t/* If it's a certificate store opened in read/write mode, record a \n\t   closed connection to the store */\n\tif( isCertStore( dbmsInfo ) && \\\n\t\t!TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_READONLY ) )\n\t\t{\n\t\tupdateCertLog( dbmsInfo, CRYPT_CERTACTION_DISCONNECT, \n\t\t\t\t\t   NULL, 0, NULL, 0, NULL, 0, NULL, 0, \n\t\t\t\t\t   DBMS_UPDATE_NORMAL );\n\t\t}\n\n\t/* If we're in the middle of a query, cancel it.  We always use \n\t   DBMS_CACHEDQUERY_NONE because this is the only query type that can\n\t   remain active outside the keyset object */\n\tif( TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) )\n\t\tdbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE, DBMS_QUERY_CANCEL );\n\n\tdbmsClose();\n\treturn( endDbxSession( keysetInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the function pointers to the keyset methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodDBMS( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYSET ) const CRYPT_KEYSET_TYPE type )\n\t{\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tstatic_assert( DBMS_CACHEDQUERY_LAST == NO_CACHED_QUERIES, \\\n\t\t\t\t   \"Cached query ID\" );\n\n\tREQUIRES( isEnumRange( type, CRYPT_KEYSET ) );\n\n\t/* Set up the lower-level interface functions */\n\tstatus = initDbxSession( keysetInfoPtr, type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tstatus = initDBMSread( keysetInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initDBMSwrite( keysetInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( type == CRYPT_KEYSET_ODBC_STORE || \\\n\t\ttype == CRYPT_KEYSET_DATABASE_STORE )\n\t\t{\n\t\tstatus = initDBMSCA( keysetInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tFNPTR_SET( keysetInfoPtr->isBusyFunction, isBusyFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/dbx_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib DBMS Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The most common query types can be performed using cached access plans \n   and query data.  The following function determines whether a particular\n   query can be performed using cached information, returning the cache \n   entry for the query if so */\n\nCHECK_RETVAL_ENUM( DBMS_CACHEDQUERY ) \\\nstatic DBMS_CACHEDQUERY_TYPE getCachedQueryType( IN_ENUM_OPT( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t\t\t\t\t IN_KEYID_OPT \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype )\n\t{\n\tREQUIRES_EXT( ( itemType == KEYMGMT_ITEM_NONE || \\\n\t\t\t\t\titemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t\t\titemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t\t\titemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\t\titemType == KEYMGMT_ITEM_REVOCATIONINFO ), \n\t\t\t\t  DBMS_CACHEDQUERY_NONE );\n\t\t\t\t  /* KEYMGMT_ITEM_NONE is for ongoing queries */\n\tREQUIRES_EXT( ( itemType == KEYMGMT_ITEM_NONE && \\\n\t\t\t\t\tkeyIDtype == CRYPT_KEYID_NONE ) || \\\n\t\t\t\t  ( keyIDtype > CRYPT_KEYID_NONE && \\\n\t\t\t\t\tkeyIDtype < CRYPT_KEYID_LAST ), DBMS_CACHEDQUERY_NONE );\n\t\t\t\t  /* { KEYMGMT_ITEM_NONE, CRYPT_KEYID_NONE } is for ongoing \n\t\t\t\t     queries */\n\n\t/* If we're not reading from the standard certificates table the query \n\t   won't be cached */\n\tif( itemType != KEYMGMT_ITEM_PUBLICKEY )\n\t\treturn( DBMS_CACHEDQUERY_NONE );\n\n\t/* Check whether we're querying on a cacheable key value type */\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_URI:\n\t\t\treturn( DBMS_CACHEDQUERY_URI );\n\n\t\tcase CRYPT_IKEYID_ISSUERID:\n\t\t\treturn( DBMS_CACHEDQUERY_ISSUERID );\n\n\t\tcase CRYPT_IKEYID_CERTID:\n\t\t\treturn( DBMS_CACHEDQUERY_CERTID );\n\n\t\tcase CRYPT_IKEYID_SUBJECTID:\n\t\t\treturn( DBMS_CACHEDQUERY_NAMEID );\n\t\t}\n\n\treturn( DBMS_CACHEDQUERY_NONE );\n\t}\n\n/* Get the SQL string to fetch data from a given table */\n\nCHECK_RETVAL_PTR \\\nstatic char *getSelectString( IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType )\n\t{\n\tREQUIRES_N( itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t\titemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t\titemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\titemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\n\tswitch( itemType )\n\t\t{\n\t\tcase KEYMGMT_ITEM_REQUEST:\n\t\tcase KEYMGMT_ITEM_REVREQUEST:\n\t\t\treturn( \"SELECT certData FROM certRequests WHERE \" );\n\n\t\tcase KEYMGMT_ITEM_PKIUSER:\n\t\t\treturn( \"SELECT certData FROM pkiUsers WHERE \" );\n\n\t\tcase KEYMGMT_ITEM_PUBLICKEY:\n\t\t\treturn( \"SELECT certData FROM certificates WHERE \" );\n\n\t\tcase KEYMGMT_ITEM_REVOCATIONINFO:\n\t\t\treturn( \"SELECT certData FROM CRLs WHERE \" );\n\t\t}\n\n\tretIntError_Null();\n\t}\n\n/* Check an encoded certificate for a matching key usage.  The semantics of \n   key usage flags are vague in the sense that the query \"Is this key valid \n   for X\" is easily resolved but the query \"Which key is appropriate for X\" \n   is NP-hard due to the potential existence of unbounded numbers of\n   certificates with usage semantics expressed in an arbitrary number of\n   ways.  For now we distinguish between signing and encryption keys (this,\n   at least, is feasible) by doing a quick check for keyUsage if we get\n   multiple certificates with the same DN and choosing the one with the \n   appropriate key usage.\n\n   Rather than performing a relatively expensive certificate import for each \n   certificate we find the keyUsage by doing an optimised search through the \n   certificate data for its encoded form.  The pattern that we look for is:\n\n\tOID\t\t\t\t06 03 55 1D 0F + SEQUENCE at n-2\n\tBOOLEAN\t\t\t(optional)\n\tOCTET STRING {\n\t\tBIT STRING\t(value)\n\n   Note that this function isn't security-critical because it doesn't perform\n   an actual usage check, all it needs to do is find the key that's most \n   likely to be usable for purpose X.  If it gets it wrong the certificate-\n   level checking will catch the problem */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkCertUsage( IN_BUFFER( certLength ) const BYTE *certificate, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\tconst int certLength,\n\t\t\t\t\t\t\t   IN_FLAGS( KEYMGMT ) const int requestedUsage )\n\t{\n\tconst int keyUsageMask = ( requestedUsage & KEYMGMT_FLAG_USAGE_CRYPT ) ? \\\n\t\t\t\t\t\t\t CRYPT_KEYUSAGE_KEYENCIPHERMENT : KEYUSAGE_SIGN;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( certificate, certLength ) );\n\t\n\tREQUIRES_B( certLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tcertLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_B( isFlagRange( requestedUsage, KEYMGMT ) );\n\tREQUIRES_B( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS );\n\n\t/* Scan the payload portion of the certificate for the keyUsage \n\t   extension.  The certificate is laid out approximately as:\n\n\t\t[ junk ][ DN ][ times ][ DN ][ pubKey ][ attrs ][ sig ]\n\n\t   so we know there's at least 128 + MIN_PKCSIZE bytes at the start and\n\t   MIN_PKCSIZE bytes at the end that we don't have to bother poking \n\t   around in */\n\tLOOP_MAX( i = 128 + MIN_PKCSIZE, i < certLength - MIN_PKCSIZE, i++ )\n\t\t{\n\t\tSTREAM stream;\n\t\tint keyUsage, status;\n\n\t\t/* Look for the OID.  This potentially skips two bytes at a time but \n\t\t   this is safe because the preceding bytes can never contain either \n\t\t   of these two values (they're 0x30 + 11...15) */\n\t\tif( certificate[ i++ ] != BER_OBJECT_IDENTIFIER || \\\n\t\t\tcertificate[ i++ ] != 3 )\n\t\t\tcontinue;\n\t\tif( certificate[ i - 4 ] != BER_SEQUENCE )\n\t\t\tcontinue;\n\t\tif( memcmp( certificate + i, \"\\x55\\x1D\\x0F\", 3 ) )\n\t\t\tcontinue;\n\t\ti += 3;\n\n\t\t/* We've found the OID (with 2.8e-14 error probability), skip\n\t\t   the critical flag if necessary */\n\t\tif( certificate[ i ] == BER_BOOLEAN )\n\t\t\ti += 3;\n\n\t\t/* Read the OCTET STRING wrapper and BIT STRING */\n\t\tsMemConnect( &stream, certificate + i, \n\t\t\t\t\t certLength - ( i + MIN_PKCSIZE ) );\n\t\treadOctetStringHole( &stream, NULL, 4, DEFAULT_TAG );\n\t\tstatus = readBitString( &stream, &keyUsage );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\n\n\t\t/* Check whether the requested usage is allowed */\n\t\treturn( ( keyUsage & keyUsageMask ) ? TRUE : FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* No key usage found, assume that any usage is OK */\n\treturn( TRUE );\n\t}\n\n/* Check that the object that we've fetched actually matches what we asked \n   for.  Obviously this should be the case, but if the underlying data store \n   can lie to us and the caller blindly accepts the certificate and uses it \n   they could end up trying to fetch a certificate belonging to A, being fed \n   one belonging to B, and \"verify\" information from B believing it to be \n   from A */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nstatic int checkObjectIDMatch( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t\t\t   IN_ENUM_OPT( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t\t\t\t   IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype, \n\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) \\\n\t\t\t\t\t\t\t\t\tconst void *keyID, \n\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tBYTE decodedID[ DBXKEYID_SIZE + 8 ];\n\tint length = keyIDlength, status;\n\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyID != NULL && \\\n\t\t\t  keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Fetching an item based on its keyID is somewhat complex because the\n\t   value, which can be of arbitrary length or form, is hashed to create\n\t   a fixed-size keyID.  Because of this we can't use iCryptVerifyID() \n\t   but have to extract the ID from the object in the form that it's used \n\t   by the underlying data store and compare that */\n\tif( ( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t  itemType == KEYMGMT_ITEM_PKIUSER ) && \\\n\t\tkeyIDtype == CRYPT_IKEYID_KEYID )\n\t\t{\n\t\tBYTE storedKeyID[ DBXKEYID_SIZE + 8 ];\n\t\tint storedKeyIDlength;\n\n\t\tREQUIRES( keyIDlength == ENCODED_DBXKEYID_SIZE );\n\n#ifdef USE_PKIUSER\n\t\tif( itemType == KEYMGMT_ITEM_PKIUSER )\n\t\t\t{\n\t\t\tstatus = getPkiUserKeyID( storedKeyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t\t\t  &storedKeyIDlength, iCryptCert );\n\t\t\t}\n\t\telse\n#endif /* USE_PKIUSER */\n\t\tstatus = getCertKeyID( storedKeyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t   &storedKeyIDlength, iCryptCert );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!memcmp( keyID, storedKeyID, DBXKEYID_SIZE ) )\n\t\t\treturn( CRYPT_OK );\n\n\t\tDEBUG_DIAG(( \"Fetched item's keyID doesn't match keyID used to fetch it\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* The internal key ID types are binary values and will be base64-\n\t   encoded in order to be usable with the database back-end, before we \n\t   can compare them we have to covert them back into their original \n\t   binary form */\n\tif( keyIDtype >= CRYPT_KEYID_LAST_EXTERNAL )\n\t\t{\n\t\tstatus = base64decode( decodedID, DBXKEYID_SIZE, &length, keyID, \n\t\t\t\t\t\t\t   keyIDlength, CRYPT_CERTFORMAT_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tkeyID = decodedID;\n\t\t}\n\n\t/* Make sure that the ID that we've been passed to fetch an object \n\t   matches the ID used in the fetched object */\n\treturn( iCryptVerifyID( iCryptCert, keyIDtype, keyID, length ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Fetch Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Fetch a sequence of certificates from a data source.  This is called in \n   one of two ways, either indirectly by the certificate code to fetch the \n   first and subsequent certificates in a chain or directly by the user \n   after submitting a query to the keyset (which doesn't return any data) \n   to read the results of the query.  The schema for calls is:\n\n\tstate = NULL:\t\tquery( NULL, &data, CONTINUE );\n\tstate, point query:\tquery( SQL, &data, NORMAL );\n\tstate, multi-cert:\tquery( SQL, &data, START );\n\t\t\t\t\t\t( followed by 'query( NULL, &data, CONTINUE )') */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 9 ) ) \\\nint getItemData( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t OUT_OPT int *stateInfo, \n\t\t\t\t IN_ENUM_OPT( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t IN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype, \n\t\t\t\t IN_BUFFER_OPT( keyValueLength ) const char *keyValue, \n\t\t\t\t IN_LENGTH_KEYID_Z const int keyValueLength,\n\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options,\n\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tconst DBMS_CACHEDQUERY_TYPE cachedQueryType = \\\n\t\t\t\t\t\t\t\tgetCachedQueryType( itemType, keyIDtype );\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tBYTE certificate[ MAX_CERT_SIZE + 8 ];\n\tchar sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];\n\tconst char *queryString;\n\tchar certDataBuffer[ MAX_QUERY_RESULT_SIZE + 8 ];\n\tvoid *certDataPtr = hasBinaryBlobs( dbmsInfo ) ? \\\n\t\t\t\t\t\tcertificate : ( void * ) certDataBuffer;\n\t\t\t\t\t\t/* Cast needed for gcc */\n\tDBMS_QUERY_TYPE queryType = DBMS_QUERY_NORMAL;\n\tBOOLEAN multiCertQuery = ( options & KEYMGMT_MASK_USAGEOPTIONS ) ? \\\n\t\t\t\t\t\t\t TRUE : FALSE;\n\tint certDataLength DUMMY_INIT, itemCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( ( stateInfo == NULL ) || \\\n\t\t\tisWritePtr( stateInfo, sizeof( int ) ) );\n\tassert( ( keyValueLength > MIN_NAME_LENGTH && \\\n\t\t\t  isReadPtrDynamic( keyValue, keyValueLength ) && \\\n\t\t\t  ( keyIDtype > CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyIDtype < CRYPT_KEYID_LAST ) ) || \\\n\t\t\t( keyValueLength == 0 && keyValue == NULL && \\\n\t\t\t  keyIDtype == CRYPT_KEYID_NONE ) );\n\n\tREQUIRES( ( itemType == KEYMGMT_ITEM_NONE && \\\n\t\t\t\tkeyIDtype == CRYPT_KEYID_NONE && keyValue == NULL && \\\n\t\t\t\tkeyValueLength == 0 && stateInfo == NULL ) ||\n\t\t\t  /* This variant is for ongoing queries, for which information \n\t\t\t     will have been submitted when the query was started */\n\t\t\t  ( itemType > KEYMGMT_ITEM_NONE && \\\n\t\t\t    itemType < KEYMGMT_ITEM_LAST && \\\n\t\t\t\tkeyIDtype > CRYPT_KEYID_NONE && \\\n\t\t\t\tkeyIDtype < CRYPT_KEYID_LAST && \\\n\t\t\t\tkeyValue != NULL && \\\n\t\t\t\tkeyValueLength >= MIN_NAME_LENGTH && \n\t\t\t\tkeyValueLength < MAX_ATTRIBUTE_SIZE && \\\n\t\t\t\tstateInfo != NULL ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_NONE || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\tif( stateInfo != NULL )\n\t\t*stateInfo = CRYPT_ERROR;\n\n\t/* Make sure that we can never explicitly fetch anything with an ID that\n\t   indicates that it's physically but not logically present, for example\n\t   certificates that have been created but not fully issued yet, \n\t   certificate items that are on hold, and similar items */\n\tif( keyValue != NULL && keyValueLength >= KEYID_ESC_SIZE && \\\n\t\t( !memcmp( keyValue, KEYID_ESC1, KEYID_ESC_SIZE ) || \\\n\t\t  !memcmp( keyValue, KEYID_ESC2, KEYID_ESC_SIZE ) ) )\n\t\t{\n\t\t/* Eheu, litteras istas reperire non possum */\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* Perform a slight optimisation to eliminate unnecessary multi-\n\t   certificate queries: If we're querying by certID or issuerID only one \n\t   certificate can ever match so there's no need to perform a multi-\n\t   certificate query even if key usage options are specified */\n\tif( keyIDtype == CRYPT_IKEYID_ISSUERID || \\\n\t\tkeyIDtype == CRYPT_IKEYID_CERTID )\n\t\tmultiCertQuery = FALSE;\n\n\t/* Set the query to begin the fetch */\n\tif( stateInfo != NULL )\n\t\t{\n\t\tconst char *keyName = getKeyName( keyIDtype );\n\t\tconst char *selectString = getSelectString( itemType );\n\n\t\tENSURES( keyName != NULL && selectString != NULL );\n\t\tstrlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, keyName );\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \" = ?\" );\n\t\tqueryString = sqlBuffer;\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, keyValue, keyValueLength );\n\t\tif( multiCertQuery )\n\t\t\t{\n\t\t\tqueryType = DBMS_QUERY_START;\n\t\t\tif( TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) )\n\t\t\t\t{\n\t\t\t\t/* There's already a query active */\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an ongoing query, just fetch the next set of results */\n\t\tqueryString = NULL;\n\t\tboundDataPtr = NULL;\n\t\tqueryType = DBMS_QUERY_CONTINUE;\n\t\tif( !TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) )\n\t\t\t{\n\t\t\t/* There's no query active to continue with */\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n\n\t/* Retrieve the results from the query */\n\tLOOP_MED( itemCount = 0, itemCount < 32, itemCount++ )\n\t\t{\n\t\t/* Retrieve the certificate data and base64-decode it if necessary */\n\t\tstatus = dbmsQuery( queryString, certDataPtr, \n\t\t\t\t\t\t\thasBinaryBlobs( dbmsInfo ) ? \\\n\t\t\t\t\t\t\t\tMAX_CERT_SIZE : MAX_SQL_QUERY_SIZE,\n\t\t\t\t\t\t\t&certDataLength, boundDataPtr, cachedQueryType, \n\t\t\t\t\t\t\tqueryType );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Convert the error code to a more appropriate value if\n\t\t\t   necessary */\n\t\t\treturn( ( multiCertQuery && ( status == CRYPT_ERROR_COMPLETE ) ) ? \\\n\t\t\t\t\tCRYPT_ERROR_NOTFOUND : status );\n\t\t\t}\n\t\tif( !hasBinaryBlobs( dbmsInfo ) )\n\t\t\t{\n\t\t\tstatus = base64decode( certificate, MAX_CERT_SIZE, \n\t\t\t\t\t\t\t\t   &certDataLength, certDataBuffer, \n\t\t\t\t\t\t\t\t   certDataLength, CRYPT_CERTFORMAT_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status, \n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Couldn't decode certificate from stored encoded \"\n\t\t\t\t\t\t  \"certificate data\" ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* We've started the fetch, from now on we're only fetching further\n\t\t   results */\n\t\tqueryString = NULL;\n\t\tboundDataPtr = NULL;\n\t\tif( queryType == DBMS_QUERY_START )\n\t\t\tqueryType = DBMS_QUERY_CONTINUE;\n\n\t\tENSURES( certDataLength >= 16 && certDataLength <= MAX_CERT_SIZE );\n\t\tENSURES( ( stateInfo != NULL && \\\n\t\t\t\t   ( queryType == DBMS_QUERY_NORMAL || \\\n\t\t\t\t\t queryType == DBMS_QUERY_CONTINUE ) ) || \\\n\t\t\t\t ( stateInfo == NULL && queryType == DBMS_QUERY_CONTINUE ) );\n\n\t\t/* If the first byte of the certificate data is 0xFF then this is an \n\t\t   item that's physically but not logically present (see the comment \n\t\t   above in the check for the keyValue), which means that we can't \n\t\t   explicitly fetch it (te audire non possum, musa sapientum fixa \n\t\t   est in aure) */\n\t\tif( certificate[ 0 ] == 0xFF )\n\t\t\t{\n\t\t\t/* If it's a multi-certificate query try again with the next \n\t\t\t   result */\n\t\t\tif( multiCertQuery )\n\t\t\t\tcontinue;\n\t\t\t\n\t\t\t/* It's a point query, we found something but it isn't there.\n\t\t\t   \"Can't you understand English you arse, we're not at home\"\n\t\t\t   -- Jeremy Black, \"The Boys from Brazil\" */\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\n\t\t/* If more than one certificate is present and the requested key \n\t\t   usage doesn't match the one indicated in the certificate, try \n\t\t   again */\n\t\tif( multiCertQuery && \\\n\t\t\t!checkCertUsage( certificate, certDataLength, options ) )\n\t\t\tcontinue;\n\n\t\t/* We got what we wanted, exit */\n\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( itemCount >= 32 )\n\t\t{\n\t\tretExt_IntError( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t\t\t ( CRYPT_ERROR_NOTFOUND, errorInfo, \n\t\t\t\t\t\t   \"Couldn't find matching certificate after \"\n\t\t\t\t\t\t   \"processing %d items\", 32 ) );\n\t\t}\n\n\t/* If we've been looking through multiple certificates, cancel the \n\t   outstanding query, which will still be in progress */\n\tif( multiCertQuery )\n\t\tdbmsStaticQuery( NULL, cachedQueryType, DBMS_QUERY_CANCEL );\n\n\t/* Create a certificate object from the encoded certificate data.  If \n\t   we're reading revocation information the data is a single CRL entry \n\t   so we have to tell the certificate import code to treat it as a \n\t   special case of a CRL.  If we're reading a certificate request it \n\t   could be either a PKCS #10 or CRMF request so we have to use auto-\n\t   detection rather than specifying an exact format */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, certificate, \n\t\t\t\t\t\t\t\t\t\tcertDataLength,\n\t\t( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t  itemType == KEYMGMT_ITEM_NONE ) ? CRYPT_CERTTYPE_CERTIFICATE : \\\n\t\t( itemType == KEYMGMT_ITEM_REQUEST ) ? CRYPT_CERTTYPE_NONE : \\\n\t\t( itemType == KEYMGMT_ITEM_REVREQUEST ) ? CRYPT_CERTTYPE_REQUEST_REVOCATION : \\\n\t\t( itemType == KEYMGMT_ITEM_PKIUSER ) ? CRYPT_CERTTYPE_PKIUSER : \\\n\t\t( itemType == KEYMGMT_ITEM_REVOCATIONINFO ) ? CRYPT_ICERTTYPE_REVINFO : \\\n\t\tCRYPT_CERTTYPE_NONE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we're running a general query then the caller could have \n\t\t   instructed us to fetch all manner of rubbish, so we provide a \n\t\t   more specific error message for this case */\n\t\tif( itemType == KEYMGMT_ITEM_NONE )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't recreate certificate from stored certificate \"\n\t\t\t\t\t  \"data, since this was a general database query what was \"\n\t\t\t\t\t  \"fetched may not have been a certificate\" ) );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't recreate certificate from stored certificate \"\n\t\t\t\t  \"data\" ) );\n\t\t}\n\tif( itemType != KEYMGMT_ITEM_NONE )\n\t\t{\n\t\t/* If we're doing a fetch based on some form of identifier, make \n\t\t   sure that the data source has really given us the item that we've \n\t\t   asked for */\n\t\tstatus = checkObjectIDMatch( createInfo.cryptHandle, itemType,\n\t\t\t\t\t\t\t\t\t keyIDtype, keyValue, keyValueLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Certificate fetched for ID type %s doesn't actually \"\n\t\t\t\t\t  \"correspond to the given ID\", \n\t\t\t\t\t  getKeyIDName( keyIDtype ) ) );\n\t\t\t}\n\t\t}\n\t*iCertificate = createInfo.cryptHandle;\n\n\t/* If this was a read with state held externally remember where we got\n\t   to so that we can fetch the next certificate in the sequence */\n\tif( stateInfo != NULL )\n\t\t*stateInfo = *iCertificate;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \\\nstatic int getFirstItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t OUT int *stateInfo,\n\t\t\t\t\t\t\t\t IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tchar encodedKeyID[ ( CRYPT_MAX_TEXTSIZE * 2 ) + 8 ];\n\tint encodedKeyIDlength, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( iCertificate == NULL || \\\n\t\t\tisWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( itemType == KEYMGMT_ITEM_NONE || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\tREQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\n\t/* Fetch the first data item */\n\tstatus = makeKeyID( encodedKeyID, CRYPT_MAX_TEXTSIZE * 2, \n\t\t\t\t\t\t&encodedKeyIDlength, keyIDtype, keyID, keyIDlength );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tstatus = getItemData( dbmsInfo, iCertificate, stateInfo, itemType, \n\t\t\t\t\t\t  keyIDtype, encodedKeyID, encodedKeyIDlength, \n\t\t\t\t\t\t  options, KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate read operation failed: \" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getNextItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tINOUT int *stateInfo, \n\t\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( ( stateInfo == NULL ) || \\\n\t\t\tisWritePtr( stateInfo, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\tREQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\n\t/* If we're fetching the next certificate in a sequence based on \n\t   externally-held state information, set the key ID to the nameID of \n\t   the previous certificate's issuer, identified using the general\n\t   cryptlib ID of CRYPT_IKEYID_SUBJECTID (the term \"nameID\" is used\n\t   only for database keysets) */\n\tif( stateInfo != NULL )\n\t\t{\n\t\tchar encodedKeyID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\t\tint encodedKeyIDlength;\n\n\t\tstatus = getKeyID( encodedKeyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t   &encodedKeyIDlength, *stateInfo, \n\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = getItemData( dbmsInfo, iCertificate, stateInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY, CRYPT_IKEYID_SUBJECTID, \n\t\t\t\t\t\t\t  encodedKeyID, encodedKeyIDlength, options, \n\t\t\t\t\t\t\t  KEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Certificate read operation failed: \" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Fetch the next data item in an ongoing query */\n\tstatus = getItemData( dbmsInfo, iCertificate, NULL, KEYMGMT_ITEM_NONE, \n\t\t\t\t\t\t  CRYPT_KEYID_NONE, NULL, 0, options, \n\t\t\t\t\t\t  KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate read operation failed: \" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Retrieve a certificate object from the database */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tSTDC_UNUSED void *auxInfo, \n\t\t\t\t\t\t\tSTDC_UNUSED int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\t\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( itemType == KEYMGMT_ITEM_NONE || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( auxInfo == NULL && *auxInfoLength == 0 );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( ( flags & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\n\t/* Clear return value */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* There are some query types that can only be satisfied by a \n\t   certificate store since a standard database doesn't contain the \n\t   necessary fields.  Before we do anything else we make sure that we \n\t   can resolve the query using the current database type */\n\tif( !TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_CERTSTORE_FIELDS ) )\n\t\t{\n\t\t/* A standard database doesn't contain a certificate ID in the \n\t\t   revocation information since the CRL that it's populated from \n\t\t   only contains an issuerAndSerialNumber, so we can't resolve \n\t\t   queries for revocation information using a certificate ID */\n\t\tif( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \\\n\t\t\tkeyIDtype == CRYPT_IKEYID_CERTID )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Operation is only valid for certificate stores\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If this is a CA management item fetch, fetch the data from the CA \n\t   certificate store */\n\tif( itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\titemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\titemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t( itemType == KEYMGMT_ITEM_REVOCATIONINFO && \\\n\t\t  !( flags & KEYMGMT_FLAG_CHECK_ONLY ) ) )\n\t\t{\n\t\tint dummy;\n\n\t\t/* If we're getting the issuing PKI user (which means that the key ID\n\t\t   that's being queried on is that of an issued certificate that the \n\t\t   PKI user owns rather than that of the PKI user themselves) fetch \n\t\t   the user information via a special function */\n\t\tif( itemType == KEYMGMT_ITEM_PKIUSER && \\\n\t\t\t( flags & KEYMGMT_FLAG_GETISSUER ) )\n\t\t\t{\n\t\t\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\t\t\tint certIDlength;\n\n\t\t\tREQUIRES( keyIDtype == CRYPT_IKEYID_CERTID );\n\n\t\t\t/* The information required to locate the PKI user from one of \n\t\t\t   their certificates is only present in a certificate store */\n\t\t\tif( !isCertStore( dbmsInfo ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t\t\t  \"Operation is only valid for certificate stores\" ) );\n\t\t\t\t}\n\n\t\t\t/* Get the PKI user based on the certificate */\n\t\t\tstatus = makeKeyID( certID, ENCODED_DBXKEYID_SIZE, &certIDlength,\n\t\t\t\t\t\t\t\tCRYPT_IKEYID_CERTID, keyID, keyIDlength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tstatus = caGetIssuingUser( dbmsInfo, iCryptHandle, certID, \n\t\t\t\t\t\t\t\t\t   certIDlength, KEYSET_ERRINFO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExtErr( status, \n\t\t\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t\t \"Certificate read operation failed: \" ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* This is just a standard read from a non-certificate table rather\n\t\t   than the certificate table so we call the get-first certificate \n\t\t   function directly rather than going via the indirect certificate-\n\t\t   import code.  Since it's a direct call we need to provide a dummy \n\t\t   return variable for the state information that's normally handled \n\t\t   by the indirect-import code */\n\t\treturn( getFirstItemFunction( keysetInfoPtr, iCryptHandle, &dummy,\n\t\t\t\t\t\t\t\t\t  itemType, keyIDtype, keyID, \n\t\t\t\t\t\t\t\t\t  keyIDlength, KEYMGMT_FLAG_NONE ) );\n\t\t}\n\n\t/* If we're doing a check only, just check whether the item is present\n\t   without fetching any data */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\t{\n\t\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\t\tchar sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];\n\t\tchar encodedKeyID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\t\tconst char *keyName = getKeyName( keyIDtype );\n\t\tconst char *selectString = getSelectString( itemType );\n\t\tint encodedKeyIDlength;\n\n\t\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\t\tREQUIRES( keyIDlength == KEYID_SIZE );\n\t\tREQUIRES( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID || \\\n\t\t\t\t  keyIDtype == CRYPT_IKEYID_CERTID );\n\t\tENSURES( keyName != NULL && selectString != NULL );\n\n\t\t/* Check whether this item is present.  We don't care about the \n\t\t   result data, all we want to know is whether it's there or not so \n\t\t   we just do a check rather than a fetch of any data */\n\t\tstatus = makeKeyID( encodedKeyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t&encodedKeyIDlength, keyIDtype, \n\t\t\t\t\t\t\tkeyID, KEYID_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\tstrlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, keyName );\n\t\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \" = ?\" );\n\t\tinitBoundData( boundDataPtr );\n\t\tsetBoundData( boundDataPtr, 0, encodedKeyID, encodedKeyIDlength );\n\t\tstatus = dbmsQuery( sqlBuffer, NULL, 0, NULL, boundDataPtr,\n\t\t\t\t\t\t\tgetCachedQueryType( itemType, keyIDtype ),\n\t\t\t\t\t\t\tDBMS_QUERY_CHECK );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Certificate presence-check operation failed: \" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Import the certificate by doing an indirect read, which fetches \n\t   either a single certificate or an entire chain if it's present */\n\treturn( iCryptImportCertIndirect( iCryptHandle, keysetInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  keyIDtype, keyID, keyIDlength,\n\t\t\t\t\t\t\t\t\t  flags & KEYMGMT_MASK_CERTOPTIONS ) );\n\t}\n\n/* Add special data to the database.  Technically this is a set-function but \n   because it initiates a query-fetch it's included with the get-functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int setSpecialItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tchar sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];\n\tconst KEYMGMT_ITEM_TYPE itemType = \\\n\t\t\t\t\t\t( dataType == CRYPT_KEYINFO_QUERY_REQUESTS ) ? \\\n\t\t\t\t\t\tKEYMGMT_ITEM_REQUEST : KEYMGMT_ITEM_PUBLICKEY;\n\tconst char *selectString = getSelectString( itemType );\n\tconst KEY_ISBUSY_FUNCTION isBusyFunction = ( KEY_ISBUSY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->isBusyFunction );\n\tint sqlLength, sqlQueryLength, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tENSURES( dataType == CRYPT_KEYINFO_QUERY || \\\n\t\t\t dataType == CRYPT_KEYINFO_QUERY_REQUESTS );\n\tENSURES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t itemType == KEYMGMT_ITEM_REQUEST );\n\tENSURES( selectString != NULL );\n\tREQUIRES( isBusyFunction != NULL );\n\n\t/* The kernel enforces a size range from 6...CRYPT_MAX_TEXTSIZE but we \n\t   perform an explicit check here against possible database-specific \n\t   values that may be more specific than the kernel's one-size-fits-all \n\t   values */\n\tif( dataLength < 6 || dataLength > MAX_SQL_QUERY_SIZE - 64 )\n\t\t{\n\t\tretExtArg( CRYPT_ARGERROR_STR1, \n\t\t\t\t   ( CRYPT_ARGERROR_STR1, KEYSET_ERRINFO, \n\t\t\t\t\t \"Invalid query length, should be from 6...%d \"\n\t\t\t\t\t \"characters\", MAX_SQL_QUERY_SIZE - 64 ) );\n\t\t}\n\n\t/* If we're cancelling an existing query, pass it on down */\n\tif( dataLength == 6 && !strCompare( data, \"cancel\", dataLength ) )\n\t\t{\n\t\t/* If the caller is trying to cancel a query without one being \n\t\t   active, we can't continue */\n\t\tif( !TEST_FLAG( dbmsInfo->flags, DBMS_FLAG_QUERYACTIVE ) )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\n\t\tstatus = dbmsStaticQuery( NULL, DBMS_CACHEDQUERY_NONE,\n\t\t\t\t\t\t\t\t  DBMS_QUERY_CANCEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t\t \"Certificate query cancel operation failed: \" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tENSURES( !isBusyFunction( keysetInfoPtr ) );\n\n\t/* Rewrite the user-supplied portion of the query using the actual \n\t   column names and append it to the SELECT statement.  This is a \n\t   special case free-format query where we can't use bound parameters \n\t   because the query data must be interpreted as SQL, unlike standard \n\t   queries where we definitely don't want it (mis-)interpreted as SQL.  \n\t   dbmsFormatQuery() tries to sanitise the query as much as it can but \n\t   in general we rely on developers reading the warnings in the \n\t   documentation about the appropriate use of this capability */\n\tstrlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, selectString );\n\tsqlLength = strlen( sqlBuffer );\n\tstatus = dbmsFormatQuery( sqlBuffer + sqlLength, \n\t\t\t\t\t\t\t ( MAX_SQL_QUERY_SIZE - 1 ) - sqlLength, \n\t\t\t\t\t\t\t &sqlQueryLength, data, dataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtArg( CRYPT_ARGERROR_STR1, \n\t\t\t\t   ( CRYPT_ARGERROR_STR1, KEYSET_ERRINFO, \n\t\t\t\t\t \"Invalid query format\" ) );\n\t\t}\n\tstatus = dbmsStaticQuery( sqlBuffer, DBMS_CACHEDQUERY_NONE, \n\t\t\t\t\t\t\t  DBMS_QUERY_START );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate query operation failed: \" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSread( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\tFNPTR_SET( keysetInfoPtr->getFirstItemFunction, getFirstItemFunction );\n\tFNPTR_SET( keysetInfoPtr->getNextItemFunction, getNextItemFunction );\n\tFNPTR_SET( keysetInfoPtr->setSpecialItemFunction, setSpecialItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/dbx_rpc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib Database RPC Interface\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This file isn't a standalone module but is meant to be #included into\n   whichever of the database client files that it's used with */\n\n#ifdef USE_RPCAPI\n\n/* Set up query data so it can be sent to the database back-end */\n\nstatic void extractQueryData( COMMAND_INFO *cmd, time_t *timeValuePtrPtr,\n\t\t\t\t\t\t\t  void **dataValuePtrPtr,\n\t\t\t\t\t\t\t  int *dataValueLengthPtr )\n\t{\n\t/* Clear return values */\n\t*timeValuePtrPtr = 0;\n\t*dataValuePtrPtr = NULL;\n\t*dataValueLengthPtr = 0;\n\n\t/* If there's only one string arg present (the command), we're done */\n\tif( cmd->noStrArgs < 2 )\n\t\treturn;\n\n\t/* If one of the string args is a bound date, convert it into a time_t */\n\tif( cmd->strArgLen[ 1 ] == 8 )\n\t\t{\n\t\tconst BYTE *timeValuePtr = cmd->strArg[ 1 ];\n\n\t\t/* Extract the time_t from the 64-bit time value */\n\t\t*timeValuePtrPtr = ( time_t ) timeValuePtr[ 4 ] << 24 | \\\n\t\t\t\t\t\t   ( time_t ) timeValuePtr[ 5 ] << 16 | \\\n\t\t\t\t\t\t   ( time_t ) timeValuePtr[ 6 ] << 8 | \\\n\t\t\t\t\t\t   ( time_t ) timeValuePtr[ 7 ];\n#ifdef SYSTEM_64BIT\n\t\t*timeValuePtrPtr |= ( time_t ) timeValuePtr[ 3 ] << 32;\n#endif /* SYSTEM_64BIT */\n\n\t\t/* Since the first arg is the date, the data (if any) will be in\n\t\t   the second arg */\n\t\tif( cmd->strArgLen[ 2 ] > 0 )\n\t\t\t{\n\t\t\t*dataValuePtrPtr = cmd->strArg[ 2 ];\n\t\t\t*dataValueLengthPtr = cmd->strArgLen[ 2 ];\n\t\t\t}\n\n\t\treturn;\n\t\t}\n\n\t/* There's only one string arg present, which is the data */\n\tif( cmd->strArgLen[ 1 ] > 0 )\n\t\t{\n\t\t*dataValuePtrPtr = cmd->strArg[ 1 ];\n\t\t*dataValueLengthPtr = cmd->strArgLen[ 1 ];\n\t\t}\n\t}\n\n/* Handlers for the various commands */\n\nint cmdClose( void *stateInfo, COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == DBX_COMMAND_CLOSE );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 0 );\n\tassert( cmd->noStrArgs == 0 );\n\n\tcloseDatabase( stateInfo );\n\treturn( CRYPT_OK );\n\t}\n\nint cmdGetErrorInfo( void *stateInfo, COMMAND_INFO *cmd )\n\t{\n\tassert( cmd->type == DBX_COMMAND_GETERRORINFO );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 0 );\n\tassert( cmd->noStrArgs == 1 );\n\n\tperformErrorQuery( stateInfo, &cmd->arg[ 0 ], cmd->strArg[ 0 ] );\n\tcmd->strArgLen[ 0 ] = strlen( cmd->strArg[ 0 ] );\n\treturn( CRYPT_OK );\n\t}\n\nint cmdOpen( void *stateInfo, COMMAND_INFO *cmd )\n\t{\n\tint hasBinaryBlobs, status;\n\n\tassert( cmd->type == DBX_COMMAND_OPEN );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->arg[ 0 ] >= CRYPT_KEYOPT_NONE && \\\n\t\t\tcmd->arg[ 0 ] < CRYPT_KEYOPT_LAST );\n\tassert( cmd->noStrArgs == 1 );\n\n\tstatus = openDatabase( stateInfo, cmd->strArg[ 0 ], cmd->arg[ 0 ],\n\t\t\t\t\t\t   &hasBinaryBlobs );\n\tif( cryptStatusOK( status ) )\n\t\tcmd->arg[ 0 ] = hasBinaryBlobs;\n\treturn( status );\n\t}\n\nint cmdQuery( void *stateInfo, COMMAND_INFO *cmd )\n\t{\n\tconst int argIndex = cmd->noStrArgs - 1;\n\tvoid *dataValue;\n\ttime_t timeValue;\n\tint dataValueLength, dataLength, status;\n\n\tassert( cmd->type == DBX_COMMAND_QUERY );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 2 );\n\tassert( cmd->arg[ 0 ] > DBMS_QUERY_NONE && \\\n\t\t\tcmd->arg[ 0 ] < DBMS_QUERY_LAST );\n\tassert( cmd->arg[ 1 ] >= DBMS_CACHEDQUERY_NONE && \\\n\t\t\tcmd->arg[ 1 ] < DBMS_CACHEDQUERY_LAST );\n\tassert( cmd->noStrArgs >= 2 && cmd->noStrArgs <= 4 );\n\n\textractQueryData( cmd, &timeValue, &dataValue, &dataValueLength );\n\tstatus = performQuery( stateInfo, cmd->strArg[ 0 ],\n\t\t\t\t\t\t   cmd->strArg[ argIndex ], &dataLength, dataValue,\n\t\t\t\t\t\t   dataValueLength, timeValue, cmd->arg[ 1 ],\n\t\t\t\t\t\t   cmd->arg[ 0 ] );\n\tif( cryptStatusOK( status ) )\n\t\tcmd->strArgLen[ argIndex ] = \\\n\t\t\t\t\t\t\t\t( cmd->arg[ 0 ] == DBMS_QUERY_NORMAL || \\\n\t\t\t\t\t\t\t\t  cmd->arg[ 0 ] == DBMS_QUERY_CONTINUE ) ? \\\n\t\t\t\t\t\t\t\tdataLength : 0;\n\treturn( status );\n\t}\n\nint cmdUpdate( void *stateInfo, COMMAND_INFO *cmd )\n\t{\n\tvoid *dataValue;\n\tint dataValueLength;\n\ttime_t timeValue;\n\n\tassert( cmd->type == DBX_COMMAND_UPDATE );\n\tassert( cmd->flags == COMMAND_FLAG_NONE );\n\tassert( cmd->noArgs == 1 );\n\tassert( cmd->noStrArgs >= 0 && cmd->noStrArgs <= 3 );\n\n\textractQueryData( cmd, &timeValue, &dataValue, &dataValueLength );\n\treturn( performUpdate( stateInfo, cmd->strArg[ 0 ],\n\t\t\t\t\t\t   dataValueLength > 0 ? dataValue : NULL,\n\t\t\t\t\t\t   dataValueLength, timeValue, cmd->arg[ 0 ] ) );\n\t}\n\n/* Process a command from the client and send it to the appropriate handler */\n\nstatic const COMMAND_HANDLER commandHandlers[] = {\n\tNULL, NULL, cmdOpen, cmdClose, cmdQuery, cmdUpdate, cmdGetErrorInfo };\n\nvoid processCommand( void *stateInfo, BYTE *buffer )\n\t{\n\tCOMMAND_INFO cmd = { 0 };\n\tBYTE header[ COMMAND_FIXED_DATA_SIZE ], *bufPtr;\n\tlong totalLength;\n\tint i, status;\n\n\t/* Read the client's message header */\n\tmemcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );\n\n\t/* Process the fixed message header and make sure it's valid */\n\tgetMessageType( header, cmd.type, cmd.flags, cmd.noArgs, cmd.noStrArgs );\n\ttotalLength = getMessageLength( header + COMMAND_WORDSIZE );\n\tif( !dbxCheckCommandInfo( &cmd, totalLength ) || \\\n\t\tcmd.type == COMMAND_RESULT )\n\t\t{\n\t\tassert( NOTREACHED );\n\n\t\t/* Return an invalid result message */\n\t\tputMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );\n\t\tputMessageLength( buffer + COMMAND_WORDSIZE, 0 );\n\t\treturn;\n\t\t}\n\n\t/* Read the rest of the clients message */\n\tbufPtr = buffer + COMMAND_FIXED_DATA_SIZE;\n\tfor( i = 0; i < cmd.noArgs; i++ )\n\t\t{\n\t\tcmd.arg[ i ] = getMessageWord( bufPtr );\n\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t}\n\tfor( i = 0; i < cmd.noStrArgs; i++ )\n\t\t{\n\t\tcmd.strArgLen[ i ] = getMessageWord( bufPtr );\n\t\tcmd.strArg[ i ] = bufPtr + COMMAND_WORDSIZE;\n\t\tbufPtr += COMMAND_WORDSIZE + cmd.strArgLen[ i ];\n\t\t}\n\tif( !dbxCheckCommandConsistency( &cmd, totalLength ) )\n\t\t{\n\t\tassert( NOTREACHED );\n\n\t\t/* Return an invalid result message */\n\t\tputMessageType( buffer, COMMAND_RESULT, 0, 0, 0 );\n\t\tputMessageLength( buffer + COMMAND_WORDSIZE, 0 );\n\t\treturn;\n\t\t}\n\n\t/* If it's a command which returns a string value, obtain the returned\n\t   data in the buffer.  Normally we limit the size to the maximum\n\t   attribute size, however encoded objects and data popped from\n\t   envelopes/sessions can be larger than this so we use the entire buffer\n\t   minus a safety margin */\n\tif( cmd.type == DBX_COMMAND_QUERY || \\\n\t\tcmd.type == DBX_COMMAND_GETERRORINFO )\n\t\t{\n\t\tcmd.strArg[ cmd.noStrArgs ] = bufPtr;\n\t\tcmd.strArgLen[ cmd.noStrArgs ] = ( cmd.type == DBX_COMMAND_QUERY ) ? \\\n\t\t\t\t\t\t\t\t\t\t MAX_ENCODED_CERT_SIZE : MAX_ERRMSG_SIZE;\n\t\tcmd.noStrArgs++;\n\t\t}\n\n\t/* Null-terminate the first string arg if there's one present, either the\n\t   database name or the SQL command.  If there's something following it\n\t   in the buffer this is redundant (but safe) because it'll already be\n\t   followed by the MSB of the next string arg's length, if there's\n\t   nothing following it it's safe as well */\n\tif( cmd.type == DBX_COMMAND_OPEN || \\\n\t\t( cmd.type == DBX_COMMAND_UPDATE && \\\n\t\t  cmd.arg[ 0 ] != DBMS_UPDATE_ABORT ) || \\\n\t\t( cmd.type == DBX_COMMAND_QUERY && \\\n\t\t  ( cmd.arg[ 0 ] == DBMS_QUERY_NORMAL || \\\n\t\t    cmd.arg[ 0 ] == DBMS_QUERY_CHECK || \\\n\t\t\tcmd.arg[ 0 ] == DBMS_QUERY_START ) ) )\n\t\t( ( char * ) cmd.strArg[ 0 ] )[ cmd.strArgLen[ 0 ] ] = '\\0';\n\n\t/* Process the command and copy any return information back to the\n\t   caller */\n\tstatus = commandHandlers[ cmd.type ]( stateInfo, &cmd );\n\tbufPtr = buffer;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The command failed, return a simple status value */\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, status );\n\t\treturn;\n\t\t}\n\tif( cmd.type == DBX_COMMAND_OPEN )\n\t\t{\n\t\t/* Return numeric value */\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 2, 0 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE * 2 );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );\n\t\treturn;\n\t\t}\n\tif( cmd.type == DBX_COMMAND_QUERY )\n\t\t{\n\t\tconst int argIndex = cmd.noStrArgs - 1;\n\t\tconst long dataLength = cmd.strArgLen[ argIndex ];\n\n\t\t/* Return data and length.  In some cases (during ongoing queries\n\t\t   with no submitted SQL data) we can be called without any incoming\n\t\t   args, there's no space at the start of the shared input/output\n\t\t   buffer so we have to move the returned string back in the buffer\n\t\t   to avoid overwriting it with the other information we're about to\n\t\t   return */\n\t\tif( dataLength )\n\t\t\t{\n\t\t\tmemmove( bufPtr + COMMAND_WORD3_OFFSET,\n\t\t\t\t\t cmd.strArg[ argIndex ], dataLength );\n\t\t\t}\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 1 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE,\n\t\t\t\t\t\t  ( COMMAND_WORDSIZE * 2 ) + cmd.strArgLen[ argIndex ] );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, dataLength );\n\t\treturn;\n\t\t}\n\tif( cmd.type == DBX_COMMAND_GETERRORINFO )\n\t\t{\n\t\tconst long dataLength = cmd.strArgLen[ 0 ];\n\n\t\t/* Return data and length.  Because we were called without any\n\t\t   incoming args, there's no space at the start of the shared input/\n\t\t   output buffer so we have to move the returned string back in the\n\t\t   buffer to avoid overwriting it with the other information we're\n\t\t   about to return */\n\t\tif( dataLength )\n\t\t\tmemmove( bufPtr + COMMAND_WORD4_OFFSET, cmd.strArg[ 0 ],\n\t\t\t\t\t dataLength );\n\t\tputMessageType( bufPtr, COMMAND_RESULT, 0, 2, 1 );\n\t\tputMessageLength( bufPtr + COMMAND_WORDSIZE,\n\t\t\t\t\t\t  ( COMMAND_WORDSIZE * 2 ) + cmd.strArgLen[ 0 ] );\n\t\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t\tputMessageWord( bufPtr + COMMAND_WORD2_OFFSET, cmd.arg[ 0 ] );\n\t\tputMessageWord( bufPtr + COMMAND_WORD3_OFFSET, dataLength );\n\t\treturn;\n\t\t}\n\tputMessageType( bufPtr, COMMAND_RESULT, 0, 1, 0 );\n\tputMessageLength( bufPtr + COMMAND_WORDSIZE, COMMAND_WORDSIZE );\n\tputMessageWord( bufPtr + COMMAND_WORD1_OFFSET, CRYPT_OK );\n\t}\n#endif /* USE_RPCAPI */\n"
  },
  {
    "path": "deps/cl345/keyset/dbx_rpcc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Database RPC Client Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2006\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"keyset.h\"\n  #include \"dbms.h\"\n  #include \"rpc.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/dbms.h\"\n  #include \"misc/rpc.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tNetwork Database Interface Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_DATABASE_PLUGIN\n\n#ifdef USE_RPCAPI\n\nstatic void netEncodeError( BYTE *buffer, const int status )\n\t{\n\tputMessageType( buffer, COMMAND_RESULT, 0, 1, 0 );\n\tputMessageLength( buffer + COMMAND_WORDSIZE, COMMAND_WORDSIZE );\n\tputMessageWord( buffer + COMMAND_WORD1_OFFSET, status );\n\t}\n\nvoid netProcessCommand( void *stateInfo, BYTE *buffer )\n\t{\n\tDBMS_STATE_INFO *dbmsInfo = ( DBMS_STATE_INFO * ) stateInfo;\n\tCOMMAND_INFO cmd;\n\tint length, status;\n\n\tmemset( &cmd, 0, sizeof( COMMAND_INFO ) );\n\n\t/* Get the messge information from the header */\n\tgetMessageType( buffer, cmd.type, cmd.flags,\n\t\t\t\t\tcmd.noArgs, cmd.noStrArgs );\n\tlength = getMessageLength( buffer + COMMAND_WORDSIZE );\n\tif( cmd.type == DBX_COMMAND_OPEN )\n\t\t{\n\t\tNET_CONNECT_INFO connectInfo;\n\t\tBYTE *bufPtr = buffer + COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE;\n\t\tint nameLen;\n\n\t\t/* Get the length of the server name and null-terminate it */\n\t\tnameLen = getMessageWord( bufPtr );\n\t\tbufPtr += COMMAND_WORDSIZE;\n\t\tbufPtr[ nameLen ] = '\\0';\n\n\t\t/* Connect to the plugin */\n\t\tinitNetConnectInfo( &connectInfo, DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\tCRYPT_ERROR, CRYPT_ERROR, NET_OPTION_HOSTNAME );\n\t\tconnectInfo.name = bufPtr;\n\t\tstatus = sNetConnect( &dbmsInfo->stream, STREAM_PROTOCOL_TCPIP,\n\t\t\t\t\t\t\t  &connectInfo, dbmsInfo->errorMessage,\n\t\t\t\t\t\t\t  &dbmsInfo->errorCode );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tnetEncodeError( buffer, status );\n\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t/* Send the command to the plugin and read back the response */\n\tstatus = swrite( &dbmsInfo->stream, buffer,\n\t\t\t\t\t COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE + length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sread( &dbmsInfo->stream, buffer, COMMAND_FIXED_DATA_SIZE );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\t/* Perform a consistency check on the returned data */\n\t\tgetMessageType( buffer, cmd.type, cmd.flags,\n\t\t\t\t\t\tcmd.noArgs, cmd.noStrArgs );\n\t\tlength = getMessageLength( buffer + COMMAND_WORDSIZE );\n\t\tif( !dbxCheckCommandInfo( &cmd, length ) || \\\n\t\t\tcmd.type != COMMAND_RESULT )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\t/* Read the rest of the message */\n\t\tstatus = sread( &dbmsInfo->stream, buffer + COMMAND_FIXED_DATA_SIZE,\n\t\t\t\t\t\tlength );\n\n\t/* If it's a close command, terminate the connection to the plugin.  We\n\t   don't do any error checking once we get this far since there's not\n\t   much that we can still do at this point */\n\tif( cmd.type == DBX_COMMAND_CLOSE )\n\t\tsNetDisconnect( &dbmsInfo->stream );\n\telse\n\t\tif( cryptStatusError( status ) )\n\t\t\tnetEncodeError( buffer, status );\n\t}\n#else\n\nint initDispatchNet( DBMS_INFO *dbmsInfo )\n\t{\n\treturn( CRYPT_ERROR );\n\t}\n#endif /* USE_RPCAPI */\n\n#endif /* USE_DATABASE_PLUGIN */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase RPC Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Dispatch functions for various database types.  ODBC is the native keyset\n   for Windows and (if possible) Unix, a cryptlib-native plugin is the\n   fallback for Unix, and the rest are only accessible via database network\n   plugins */\n\n#ifdef USE_ODBC\n  void odbcProcessCommand( void *stateInfo, BYTE *buffer );\n  #define initDispatchODBC( dbmsInfo ) \\\n\t\t  ( dbmsInfo->dispatchFunction = odbcProcessCommand ) != NULL\n#else\n  #define initDispatchODBC( dbmsInfo )\t\tCRYPT_ERROR\n#endif /* USE_ODBC */\n#if defined( USE_DATABASE )\n  void databaseProcessCommand( void *stateInfo, BYTE *buffer );\n  #define initDispatchDatabase( dbmsInfo ) \\\n\t\t  ( dbmsInfo->dispatchFunction = databaseProcessCommand ) != NULL\n#else\n  #define initDispatchDatabase( dbmsInfo )\tCRYPT_ERROR\n#endif /* General database interface */\n#ifdef USE_DATABASE_PLUGIN\n  int initDispatchNet( DBMS_INFO *dbmsInfo );\n#else\n  #define initDispatchNet( dbmsInfo )\t\tCRYPT_ERROR\n#endif /* USE_DATABASE_PLUGIN */\n\n/* Make sure that we can fit the largest possible SQL query into the RPC\n   buffer */\n\n#if MAX_SQL_QUERY_SIZE + 256 >= DBX_IO_BUFSIZE\n  #error Database RPC buffer size is too small, increase DBX_IO_BUFSIZE and rebuild\n#endif /* SQL query size larger than RPC buffer size */\n\n/* Dispatch data to the back-end */\n\nstatic int dispatchCommand( COMMAND_INFO *cmd, void *stateInfo,\n\t\t\t\t\t\t\tDISPATCH_FUNCTION dispatchFunction )\n\t{\n\tCOMMAND_INFO sentCmd = *cmd;\n\tBYTE buffer[ DBX_IO_BUFSIZE + 8 ], *bufPtr = buffer;\n\tBYTE header[ COMMAND_FIXED_DATA_SIZE + 8 ];\n\tconst int payloadLength = ( cmd->noArgs * COMMAND_WORDSIZE ) + \\\n\t\t\t\t\t\t\t  ( cmd->noStrArgs * COMMAND_WORDSIZE ) + \\\n\t\t\t\t\t\t\t  cmd->strArgLen[ 0 ] + cmd->strArgLen[ 1 ] + \\\n\t\t\t\t\t\t\t  cmd->strArgLen[ 2 ];\n\tlong resultLength;\n\tint i;\n\n\tassert( payloadLength + 32 < DBX_IO_BUFSIZE );\n\tassert( dispatchFunction != NULL );\n\n\t/* Clear the return value */\n\tmemset( cmd, 0, sizeof( COMMAND_INFO ) );\n\n\t/* Write the header and message fields to the buffer */\n\tputMessageType( bufPtr, sentCmd.type, sentCmd.flags,\n\t\t\t\t\tsentCmd.noArgs, sentCmd.noStrArgs );\n\tputMessageLength( bufPtr + COMMAND_WORDSIZE, payloadLength );\n\tbufPtr += COMMAND_FIXED_DATA_SIZE;\n\tfor( i = 0; i < sentCmd.noArgs; i++ )\n\t\t{\n\t\tputMessageWord( bufPtr, sentCmd.arg[ i ] );\n\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t}\n\tfor( i = 0; i < sentCmd.noStrArgs; i++ )\n\t\t{\n\t\tconst int argLength = sentCmd.strArgLen[ i ];\n\n\t\tputMessageWord( bufPtr, argLength );\n\t\tif( argLength > 0 )\n\t\t\t{\n\t\t\tmemcpy( bufPtr + COMMAND_WORDSIZE, sentCmd.strArg[ i ],\n\t\t\t\t\targLength );\n\t\t\t}\n\t\tbufPtr += COMMAND_WORDSIZE + argLength;\n\t\t}\n\n\t/* Send the command to the server and read back the server's message\n\t   header */\n\tdispatchFunction( stateInfo, buffer );\n\tmemcpy( header, buffer, COMMAND_FIXED_DATA_SIZE );\n\n\t/* Process the fixed message header and make sure that it's valid */\n\tgetMessageType( header, cmd->type, cmd->flags,\n\t\t\t\t\tcmd->noArgs, cmd->noStrArgs );\n\tresultLength = getMessageLength( header + COMMAND_WORDSIZE );\n\tif( !dbxCheckCommandInfo( cmd, resultLength ) || \\\n\t\tcmd->type != COMMAND_RESULT )\n\t\treturn( CRYPT_ERROR );\n\tif( ( cmd->noStrArgs && cmd->strArgLen[ 0 ] ) && \\\n\t\t( sentCmd.type != DBX_COMMAND_QUERY && \\\n\t\t  sentCmd.type != DBX_COMMAND_GETERRORINFO ) )\n\t\t/* Only these commands can return data */\n\t\treturn( CRYPT_ERROR );\n\n\t/* Read the rest of the server's message */\n\tbufPtr = buffer + COMMAND_FIXED_DATA_SIZE;\n\tfor( i = 0; i < cmd->noArgs; i++ )\n\t\t{\n\t\tcmd->arg[ i ] = getMessageWord( bufPtr );\n\t\tbufPtr += COMMAND_WORDSIZE;\n\t\t}\n\tfor( i = 0; i < cmd->noStrArgs; i++ )\n\t\t{\n\t\tcmd->strArgLen[ i ] = getMessageWord( bufPtr );\n\t\tcmd->strArg[ i ] = bufPtr + COMMAND_WORDSIZE;\n\t\tbufPtr += COMMAND_WORDSIZE + cmd->strArgLen[ i ];\n\t\t}\n\n\t/* The first value returned is the status code, if it's nonzero return\n\t   it to the caller, otherwise move the other values down */\n\tif( cryptStatusError( cmd->arg[ 0 ] ) )\n\t\treturn( cmd->arg[ 0 ] );\n\tassert( cryptStatusOK( cmd->arg[ 0 ] ) );\n\tfor( i = 1; i < cmd->noArgs; i++ )\n\t\tcmd->arg[ i - 1 ] = cmd->arg[ i ];\n\tcmd->arg[ i ] = 0;\n\tcmd->noArgs--;\n\n\t/* Copy any string arg data back to the caller */\n\tif( cmd->noStrArgs && cmd->strArgLen[ 0 ] )\n\t\t{\n\t\tconst int maxBufSize = ( sentCmd.type == DBX_COMMAND_QUERY ) ? \\\n\t\t\t\t\t\t\t   MAX_QUERY_RESULT_SIZE : MAX_ERRMSG_SIZE;\n\t\tconst int argIndex = sentCmd.noStrArgs;\n\n\t\tmemcpy( sentCmd.strArg[ argIndex ], cmd->strArg[ 0 ],\n\t\t\t\tmin( cmd->strArgLen[ 0 ], maxBufSize ) );\n\t\tcmd->strArg[ 0 ] = sentCmd.strArg[ argIndex ];\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise query data prior to sending it to the database back-end */\n\nstatic int initQueryData( COMMAND_INFO *cmd, const COMMAND_INFO *cmdTemplate,\n\t\t\t\t\t\t  BYTE *encodedDate, DBMS_INFO *dbmsInfo,\n\t\t\t\t\t\t  const char *command, const void *boundData,\n\t\t\t\t\t\t  const int boundDataLength, const time_t boundDate,\n\t\t\t\t\t\t  const int type )\n\t{\n\tint argIndex = 1;\n\n\tmemcpy( cmd, cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd->arg[ 0 ] = type;\n\tif( command != NULL )\n\t\t{\n\t\tcmd->strArg[ 0 ] = ( void * ) command;\n\t\tcmd->strArgLen[ 0 ] = strlen( command );\n\t\t}\n\tif( boundDate > 0 )\n\t\t{\n#ifndef SYSTEM_64BIT\n\t\tassert( sizeof( time_t ) <= 4 );\n#endif /* !SYSTEM_64BIT */\n\n\t\t/* Encode the date as a 64-bit value */\n\t\tmemset( encodedDate, 0, 8 );\n#ifdef SYSTEM_64BIT\n\t\tencodedDate[ 3 ] = ( BYTE )( ( boundDate >> 32 ) & 0xFF );\n#endif /* SYSTEM_64BIT */\n\t\tencodedDate[ 4 ] = ( BYTE )( ( boundDate >> 24 ) & 0xFF );\n\t\tencodedDate[ 5 ] = ( BYTE )( ( boundDate >> 16 ) & 0xFF );\n\t\tencodedDate[ 6 ] = ( BYTE )( ( boundDate >> 8 ) & 0xFF );\n\t\tencodedDate[ 7 ] = ( BYTE )( ( boundDate ) & 0xFF );\n\t\tcmd->noStrArgs++;\n\t\tcmd->strArg[ argIndex ] = encodedDate;\n\t\tcmd->strArgLen[ argIndex++ ] = 8;\n\t\t}\n\tif( boundData != NULL )\n\t\t{\n\t\t/* Copy the bound data into non-ephemeral storage where it'll be\n\t\t   accessible to the back-end */\n\t\tmemcpy( dbmsInfo->boundData, boundData, boundDataLength );\n\t\tcmd->noStrArgs++;\n\t\tcmd->strArg[ argIndex ] = dbmsInfo->boundData;\n\t\tcmd->strArgLen[ argIndex++ ] = boundDataLength;\n\t\t}\n\n\treturn( argIndex );\n\t}\n\n/* Database access functions */\n\nstatic int openDatabase( DBMS_INFO *dbmsInfo, const char *name,\n\t\t\t\t\t\t const int nameLength, const int options, \n\t\t\t\t\t\t int *featureFlags )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ DBX_COMMAND_OPEN, COMMAND_FLAG_NONE, 1, 1 };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.arg[ 0 ] = options;\n\tcmd.strArg[ 0 ] = ( void * ) name;\n\tcmd.strArgLen[ 0 ] = nameLength;\n\tstatus = DISPATCH_COMMAND_DBX( cmdOpen, cmd, dbmsInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\t( cmd.arg[ 0 ] & DBMS_HAS_BINARYBLOBS ) )\n\t\tdbmsInfo->flags |= DBMS_FLAG_BINARYBLOBS;\n\treturn( status );\n\t}\n\nstatic void closeDatabase( DBMS_INFO *dbmsInfo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ DBX_COMMAND_CLOSE, COMMAND_FLAG_NONE, 0, 0 };\n\tCOMMAND_INFO cmd;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tDISPATCH_COMMAND_DBX( cmdClose, cmd, dbmsInfo );\n\t}\n\nstatic void performErrorQuery( DBMS_INFO *dbmsInfo )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ DBX_COMMAND_GETERRORINFO, COMMAND_FLAG_NONE, 0, 1 };\n\tCOMMAND_INFO cmd;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\t/* Clear the return values */\n\tmemset( dbmsInfo->errorMessage, 0, MAX_ERRMSG_SIZE );\n\tdbmsInfo->errorCode = 0;\n\n\t/* Dispatch the command */\n\tmemcpy( &cmd, &cmdTemplate, sizeof( COMMAND_INFO ) );\n\tcmd.strArg[ 0 ] = dbmsInfo->errorMessage;\n\tcmd.strArgLen[ 0 ] = 0;\n\tstatus = DISPATCH_COMMAND_DBX( cmdGetErrorInfo, cmd, dbmsInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tdbmsInfo->errorCode = cmd.arg[ 0 ];\n\t\tdbmsInfo->errorMessage[ cmd.strArgLen[ 0 ] ] = '\\0';\n\t\t}\n\t}\n\nstatic int performUpdate( DBMS_INFO *dbmsInfo, const char *command,\n\t\t\t\t\t\t  const void *boundData, const int boundDataLength,\n\t\t\t\t\t\t  const time_t boundDate,\n\t\t\t\t\t\t  const DBMS_UPDATE_TYPE updateType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ DBX_COMMAND_UPDATE, COMMAND_FLAG_NONE, 1, 1 };\n\tCOMMAND_INFO cmd;\n\tBYTE encodedDate[ 8 + 8 ];\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( updateType > DBMS_UPDATE_NONE && \\\n\t\t\tupdateType < DBMS_UPDATE_LAST );\n\n\t/* If we're trying to abort a transaction that was never begun, don't\n\t   do anything */\n\tif( updateType == DBMS_UPDATE_ABORT && \\\n\t\t!( dbmsInfo->flags & DBMS_FLAG_UPDATEACTIVE ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Dispatch the command */\n\tinitQueryData( &cmd, &cmdTemplate, encodedDate, dbmsInfo, command,\n\t\t\t\t   boundData, boundDataLength, boundDate, updateType );\n\tstatus = DISPATCH_COMMAND_DBX( cmdUpdate, cmd, dbmsInfo );\n\tif( cryptStatusError( status ) )\n\t\tperformErrorQuery( dbmsInfo );\n\telse\n\t\t{\n\t\t/* If we're starting or ending an update, record the update state */\n\t\tif( updateType == DBMS_UPDATE_BEGIN )\n\t\t\tdbmsInfo->flags |= DBMS_FLAG_UPDATEACTIVE;\n\t\tif( updateType == DBMS_UPDATE_COMMIT || \\\n\t\t\tupdateType == DBMS_UPDATE_ABORT )\n\t\t\tdbmsInfo->flags &= ~DBMS_FLAG_UPDATEACTIVE;\n\t\t}\n\treturn( status );\n\t}\n\nstatic int performStaticUpdate( DBMS_INFO *dbmsInfo, const char *command )\n\t{\n\treturn( performUpdate( dbmsInfo, command, NULL, 0, 0,\n\t\t\t\t\t\t   DBMS_UPDATE_NORMAL ) );\n\t}\n\nstatic int performQuery( DBMS_INFO *dbmsInfo, const char *command,\n\t\t\t\t\t\t char *data, int *dataLength, const char *queryData,\n\t\t\t\t\t\t const int queryDataLength, const time_t queryDate,\n\t\t\t\t\t\t const DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t const DBMS_QUERY_TYPE queryType )\n\t{\n\tstatic const COMMAND_INFO cmdTemplate = \\\n\t\t{ DBX_COMMAND_QUERY, COMMAND_FLAG_NONE, 2, 1 };\n\tCOMMAND_INFO cmd;\n\tBYTE encodedDate[ 8 + 8 ];\n\tint argIndex, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\tassert( ( data == NULL && dataLength == NULL ) || \\\n\t\t\tisWritePtr( data, 16 ) );\n\tassert( ( queryData == NULL && queryDataLength == 0 ) || \\\n\t\t\t( queryDataLength > 0 && \\\n\t\t\t  isReadPtrDynamic( queryData, queryDataLength ) ) );\n\tassert( queryEntry >= DBMS_CACHEDQUERY_NONE && \\\n\t\t\tqueryEntry < DBMS_CACHEDQUERY_LAST );\n\tassert( queryType > DBMS_QUERY_NONE && queryType < DBMS_QUERY_LAST );\n\n\t/* Additional state checks: If we're starting a new query or performing\n\t   a point query there can't already be one active, and if we're\n\t   continuing or cancelling an existing query there has to be one\n\t   already active */\n\tif( ( ( queryType == DBMS_QUERY_START || \\\n\t\t\tqueryType == DBMS_QUERY_CHECK || \\\n\t\t\tqueryType == DBMS_QUERY_NORMAL ) && \\\n\t\t  ( dbmsInfo->flags & DBMS_FLAG_QUERYACTIVE ) ) ||\n\t\t( ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\tqueryType == DBMS_QUERY_CANCEL ) && \\\n\t\t  !( dbmsInfo->flags & DBMS_FLAG_QUERYACTIVE ) ) )\n\t\tretIntError();\n\n\t/* Clear return value */\n\tif( data != NULL )\n\t\t{\n\t\tmemset( data, 0, 16 );\n\t\t*dataLength = 0;\n\t\t}\n\n\t/* Dispatch the command */\n\targIndex = initQueryData( &cmd, &cmdTemplate, encodedDate, dbmsInfo,\n\t\t\t\t\t\t\t  command, queryData, queryDataLength,\n\t\t\t\t\t\t\t  queryDate, queryType );\n\tcmd.arg[ 1 ] = queryEntry;\n\tcmd.strArg[ argIndex ] = data;\n\tcmd.strArgLen[ argIndex ] = 0;\n\tcmd.noStrArgs = argIndex + 1;\n\tstatus = DISPATCH_COMMAND_DBX( cmdQuery, cmd, dbmsInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tperformErrorQuery( dbmsInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* Update the state information based on the query that we've just\n\t   performed */\n\tif( queryType == DBMS_QUERY_START  )\n\t\tdbmsInfo->flags |= DBMS_FLAG_QUERYACTIVE;\n\tif( queryType == DBMS_QUERY_CANCEL )\n\t\tdbmsInfo->flags &= ~DBMS_FLAG_QUERYACTIVE;\n\tif( dataLength != NULL )\n\t\t{\n\t\t*dataLength = cmd.strArgLen[ argIndex ];\n\t\tif( *dataLength <= 0 || *dataLength > MAX_QUERY_RESULT_SIZE )\n\t\t\t{\n\t\t\tassert( NOTREACHED );\n\t\t\tmemset( data, 0, 16 );\n\t\t\t*dataLength = 0;\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nstatic int performStaticQuery( DBMS_INFO *dbmsInfo, const char *command,\n\t\t\t\t\t\t\t   const DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t\t   const DBMS_QUERY_TYPE queryType )\n\t{\n\treturn( performQuery( dbmsInfo, command, NULL, NULL, NULL, 0, 0,\n\t\t\t\t\t\t  queryEntry, queryType ) );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/dbx_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib DBMS Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n/* A structure to store ID information extracted from a certificate before \n   it's added to the certificate store */\n\ntypedef struct {\n\t/* User identification data */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, Clength ) \\\n\tchar C[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, SPlength ) \\\n\tchar SP[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, Llength ) \\\n\tchar L[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, Olength ) \\\n\tchar O[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, OUlength ) \\\n\tchar OU[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, CNlength ) \\\n\tchar CN[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, uriLength ) \\\n\tchar uri[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint Clength, SPlength, Llength, Olength, OUlength, CNlength, uriLength;\n\n\t/* Certificate identification data */\n\tBUFFER( ENCODED_DBXKEYID_SIZE, certIDlength ) \\\n\tchar certID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tBUFFER( ENCODED_DBXKEYID_SIZE, nameIDlength ) \\\n\tchar nameID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tBUFFER( ENCODED_DBXKEYID_SIZE, issuerIDlength ) \\\n\tchar issuerID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tBUFFER( ENCODED_DBXKEYID_SIZE, keyIDlength ) \\\n\tchar keyID[ ENCODED_DBXKEYID_SIZE + 8 ];\n\tint certIDlength, nameIDlength, issuerIDlength, keyIDlength;\n\t} CERT_ID_DATA;\n\n#ifdef USE_DBMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the SQL string to delete data from a given table */\n\nCHECK_RETVAL_PTR \\\nstatic char *getDeleteString( IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType )\n\t{\n\tREQUIRES_N( itemType == KEYMGMT_ITEM_PKIUSER || \\\n\t\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY );\n\n\tswitch( itemType )\n\t\t{\n\t\tcase KEYMGMT_ITEM_PKIUSER:\n\t\t\treturn( \"DELETE FROM pkiUsers WHERE \" );\n\n\t\tcase KEYMGMT_ITEM_PUBLICKEY:\n\t\t\treturn( \"DELETE FROM certificates WHERE \" );\n\t\t}\n\n\tretIntError_Null();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tExtract ID Information\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Extract user identification data from a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int extractCertNameData( IN_HANDLE const CRYPT_CERTIFICATE iCryptHandle,\n\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t\t\t\tOUT CERT_ID_DATA *certIdData )\n\t{\n\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\tstatic const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( certIdData, sizeof( CERT_ID_DATA ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certType == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  certType == CRYPT_CERTTYPE_PKIUSER );\n\n\t/* Clear return value */\n\tmemset( certIdData, 0, sizeof( CERT_ID_DATA ) );\n\n\t/* Extract the DN and altName (URI) components.  This changes the \n\t   currently selected DN components but this is OK because we've got the \n\t   certificate locked and the prior state will be restored when we \n\t   unlock it */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &nameValue, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, certIdData->C, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_COUNTRYNAME );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Although the country code is supposed to be ISO 3166, \n\t\t   certificates can turn up with all kinds of random garbage in the\n\t\t   country code, including values that aren't two-letter codes, so\n\t\t   we truncate the field if required in order to fit it into the\n\t\t   underlying database column */\n\t\tcertIdData->Clength = min( msgData.length, 2 );\n\t\t}\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, certIdData->SP, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_STATEORPROVINCENAME );\n\tif( cryptStatusOK( status ) )\n\t\tcertIdData->SPlength = msgData.length;\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, certIdData->L, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_LOCALITYNAME );\n\tif( cryptStatusOK( status ) )\n\t\tcertIdData->Llength = msgData.length;\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, certIdData->O, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_ORGANIZATIONNAME );\n\tif( cryptStatusOK( status ) )\n\t\tcertIdData->Olength = msgData.length;\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, certIdData->OU, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );\n\tif( cryptStatusOK( status ) )\n\t\tcertIdData->OUlength = msgData.length;\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\n\t/* The CommonName component is the generic \"name\" associated with the \n\t   certificate, to make sure that there's always at least something \n\t   useful present to identify it we fetch the certificate holder name \n\t   rather than the specific common name */\n\tsetMessageData( &msgData, certIdData->CN, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_HOLDERNAME );\n\tif( cryptStatusOK( status ) )\n\t\tcertIdData->CNlength = msgData.length;\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\t\t}\n\n\t/* PKI user objects don't have URI information so if we're processing \n\t   one of these we're done */\n\tif( certType == CRYPT_CERTTYPE_PKIUSER )\n\t\treturn( CRYPT_OK );\n\n\t/* Get the URI for this certificate, in order of likelihood of \n\t   occurrence */\n\tsetMessageData( &msgData, certIdData->uri, CRYPT_MAX_TEXTSIZE );\n\tkrnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &altNameValue, \n\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_RFC822NAME );\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, certIdData->uri, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER );\n\t\t}\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, certIdData->uri, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_DNSNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Force the URI (as stored) to lowercase to make case-insensitive \n\t\t   matching easier.  In most cases we could ask the back-end to do \n\t\t   this but this complicates indexing and there's no reason why we \n\t\t   can't do it here */\n\t\tLOOP_LARGE( i = 0, i < msgData.length, i++ )\n\t\t\tcertIdData->uri[ i ] = intToByte( toLower( certIdData->uri[ i ] ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tcertIdData->uriLength = msgData.length;\n\t\t}\n\t\n\treturn( status );\n\t}\n\n/* Extract certificate identification data from a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int extractCertIdData( IN_HANDLE const CRYPT_CERTIFICATE iCryptHandle,\n\t\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t\t\t  INOUT CERT_ID_DATA *certIdData )\n\t{\n\tint status;\n\n\tassert( isWritePtr( certIdData, sizeof( CERT_ID_DATA ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certType == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  certType == CRYPT_CERTTYPE_PKIUSER );\n\n\t/* Get general ID information */\n\tstatus = getKeyID( certIdData->certID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t   &certIdData->certIDlength, iCryptHandle,\n\t\t\t\t\t   CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get object-specific ID information */\n\tif( certType == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\tstatus = getKeyID( certIdData->nameID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t   &certIdData->nameIDlength, iCryptHandle, \n\t\t\t\t\t\t   CRYPT_IATTRIBUTE_SUBJECT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getKeyID( certIdData->issuerID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t   &certIdData->issuerIDlength, iCryptHandle, \n\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getCertKeyID( certIdData->keyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t\t   &certIdData->keyIDlength, iCryptHandle );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n#ifdef USE_PKIUSER\n\tif( certType == CRYPT_CERTTYPE_PKIUSER )\n\t\t{\n\t\tstatus = getPkiUserKeyID( certIdData->keyID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t\t  &certIdData->keyIDlength, iCryptHandle );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getKeyID( certIdData->nameID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t\t   &certIdData->nameIDlength, iCryptHandle, \n\t\t\t\t\t\t\t   CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n#endif /* USE_PKIUSER */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Extract certificate identification data from a CRL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int extractCrlIdData( IN_HANDLE const CRYPT_CERTIFICATE iCryptCRL,\n\t\t\t\t\t\t\t IN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\tconst CRYPT_CERTIFICATE iCryptRevokeCert,\n\t\t\t\t\t\t\t OUT CERT_ID_DATA *crlIdData )\n\t{\n\tint status;\n\n\tassert( isWritePtr( crlIdData, sizeof( CERT_ID_DATA ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCRL ) );\n\tREQUIRES( iCryptRevokeCert == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iCryptRevokeCert ) );\n\n\t/* Clear return value */\n\tmemset( crlIdData, 0, sizeof( CERT_ID_DATA ) );\n\n\t/* Get general ID information */\n\tstatus = getKeyID( crlIdData->issuerID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t   &crlIdData->issuerIDlength, iCryptCRL, \n\t\t\t\t\t   CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there's no certificate being revoked present (i.e. we're just \n\t   adding a set of CRL entries), we're done */\n\tif( iCryptRevokeCert == CRYPT_UNUSED )\n\t\treturn( CRYPT_OK );\n\n\t/* Get the certificate ID and the name ID of the issuer from the \n\t   certificate being revoked */\n\tstatus = getKeyID( crlIdData->certID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t   &crlIdData->certIDlength, iCryptRevokeCert,\n\t\t\t\t\t   CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getKeyID( crlIdData->nameID, ENCODED_DBXKEYID_SIZE, \n\t\t\t\t\t\t   &crlIdData->nameIDlength, iCryptRevokeCert,\n\t\t\t\t\t\t   CRYPT_IATTRIBUTE_ISSUER );\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Add Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a certificate object (certificate, certificate request, PKI user) to \n   a certificate store.  Normally existing rows would be overwritten if we \n   added duplicate entries but the UNIQUE constraint on the indices will \n   catch this */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint addCert( INOUT DBMS_INFO *dbmsInfo, \n\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t IN_ENUM( CRYPT_CERTTYPE ) const CRYPT_CERTTYPE_TYPE certType, \n\t\t\t IN_ENUM( CERTADD ) const CERTADD_TYPE addType,\n\t\t\t IN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType, \n\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tCERT_ID_DATA certIdData;\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];\n\tconst char *sqlString;\n\ttime_t boundDate;\n\tint certDataLength DUMMY_INIT, boundDataIndex, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t\t  certType == CRYPT_CERTTYPE_REQUEST_CERT || \\\n\t\t\t  certType == CRYPT_CERTTYPE_PKIUSER );\n\tREQUIRES( isEnumRange( addType, CERTADD ) );\n\tREQUIRES( isEnumRange( updateType, DBMS_UPDATE ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Extract name-related information from the certificate.  We explicitly\n\t   initialise certIdData before calling extractCertNameData() because,\n\t   although it's initialised by extractCertNameData(), this can return\n\t   an error code implying that it wasn't initialised, which violates the\n\t   contract for the function */\n\tmemset( &certIdData, 0, sizeof( CERT_ID_DATA ) );\n\tstatus = extractCertNameData( iCryptHandle, certType, &certIdData );\n\tif( ( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND ) && \\\n\t\t( certType == CRYPT_CERTTYPE_CERTIFICATE ) )\n\t\t{\n\t\tsetMessageData( &msgData, &boundDate, sizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDTO );\n\t\t}\n\telse\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert any low-level certificate-specific error into something \n\t\t   generic that makes a bit more sense to the caller */\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, errorInfo, \n\t\t\t\t\t \"Couldn't extract user identification information \"\n\t\t\t\t\t \"from certificate\" ) );\n\t\t}\n\n\t/* Get the ID information and certificate data from the certificate */\n\tstatus = extractCertIdData( iCryptHandle, certType, &certIdData );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = extractCertData( iCryptHandle, \n\t\t\t\t\t\t\t\t  ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_ICERTFORMAT_DATA : \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE,\n\t\t\t\t\t\t\t\t  certData, MAX_CERT_SIZE, &certDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert any low-level certificate-specific error into something \n\t\t   generic that makes a bit more sense to the caller */\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, errorInfo, \n\t\t\t\t\t \"Couldn't extract certificate data from \"\n\t\t\t\t\t \"certificate\" ) );\n\t\t}\n\n\t/* If this is a partial add (in which we add a certificate item which is \n\t   in the initial stages of the creation process so that although the \n\t   item may be physically present in the store it can't be accessed \n\t   directly) we set the first byte to 0xFF to indicate this.  In \n\t   addition we set the first two bytes of the IDs that have uniqueness \n\t   constraints to an out-of-band value to prevent a clash with the \n\t   finished entry when we complete the issue process and replace the \n\t   partial version with the full version */\n\tif( addType == CERTADD_PARTIAL || addType == CERTADD_PARTIAL_RENEWAL )\n\t\t{\n\t\tconst char *escapeStr = ( addType == CERTADD_PARTIAL ) ? \\\n\t\t\t\t\t\t\t\tKEYID_ESC1 : KEYID_ESC2;\n\n\t\tcertData[ 0 ] = 0xFF;\n\t\tmemcpy( certIdData.issuerID, escapeStr, KEYID_ESC_SIZE );\n\t\tmemcpy( certIdData.keyID, escapeStr, KEYID_ESC_SIZE );\n\t\tmemcpy( certIdData.certID, escapeStr, KEYID_ESC_SIZE );\n\t\t}\n\n\t/* Set up the certificate object data to be written and send it to the\n\t   database */\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, certIdData.C, certIdData.Clength );\n\tsetBoundData( boundDataPtr, 1, certIdData.SP, certIdData.SPlength );\n\tsetBoundData( boundDataPtr, 2, certIdData.L, certIdData.Llength );\n\tsetBoundData( boundDataPtr, 3, certIdData.O, certIdData.Olength );\n\tsetBoundData( boundDataPtr, 4, certIdData.OU, certIdData.OUlength );\n\tsetBoundData( boundDataPtr, 5, certIdData.CN, certIdData.CNlength );\n\tswitch( certType )\n\t\t{\n\t\tcase CRYPT_CERTTYPE_CERTIFICATE:\n\t\t\tsetBoundData( boundDataPtr, 6, certIdData.uri, \n\t\t\t\t\t\t  certIdData.uriLength );\n\t\t\tsetBoundDataDate( boundDataPtr, 7, &boundDate );\n\t\t\tsetBoundData( boundDataPtr, 8, certIdData.nameID, \n\t\t\t\t\t\t  certIdData.nameIDlength );\n\t\t\tsetBoundData( boundDataPtr, 9, certIdData.issuerID, \n\t\t\t\t\t\t  certIdData.issuerIDlength );\n\t\t\tsetBoundData( boundDataPtr, 10, certIdData.keyID, \n\t\t\t\t\t\t  certIdData.keyIDlength );\n\t\t\tboundDataIndex = 11;\n\t\t\tsqlString = \\\n\t\t\t\"INSERT INTO certificates VALUES (?, ?, ?, ?, ?, ?, ?,\"\n\t\t\t\t\t\t\t\t\t\t\t \"?, ?, ?, ?, ?, ?)\";\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_REQUEST_CERT:\n\t\t\tsetBoundData( boundDataPtr, 6, certIdData.uri, \n\t\t\t\t\t\t  certIdData.uriLength );\n\t\t\tboundDataIndex = 7;\n\t\t\tsqlString = \\\n\t\t\t\"INSERT INTO certRequests VALUES ('\" TEXT_CERTTYPE_REQUEST_CERT \"', \"\n\t\t\t\t\t\t\t\t\t\t\t \"?, ?, ?, ?, ?, ?, ?, ?, ?)\";\n\t\t\tbreak;\n\n\t\tcase CRYPT_CERTTYPE_PKIUSER:\n\t\t\tsetBoundData( boundDataPtr, 6, certIdData.nameID, \n\t\t\t\t\t\t  certIdData.nameIDlength );\n\t\t\tsetBoundData( boundDataPtr, 7, certIdData.keyID, \n\t\t\t\t\t\t  certIdData.keyIDlength );\n\t\t\tboundDataIndex = 8;\n\t\t\tsqlString = \\\n\t\t\t\"INSERT INTO pkiUsers VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\";\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tsetBoundData( boundDataPtr, boundDataIndex++, certIdData.certID, \n\t\t\t\t  certIdData.certIDlength );\n\tif( hasBinaryBlobs( dbmsInfo ) )\n\t\t{\n\t\tsetBoundDataBlob( boundDataPtr, boundDataIndex, \n\t\t\t\t\t\t  certData, certDataLength );\n\t\t}\n\telse\n\t\t{\n\t\tint encodedCertDataLength;\n\n\t\tstatus = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE, \n\t\t\t\t\t\t\t   &encodedCertDataLength, certData, \n\t\t\t\t\t\t\t   certDataLength, CRYPT_CERTTYPE_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't base64-encode data\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tretIntError();\n\t\t\t}\n\t\tsetBoundData( boundDataPtr, boundDataIndex, encodedCertData, \n\t\t\t\t\t  encodedCertDataLength );\n\t\t}\n\tstatus = dbmsUpdate( sqlString, boundDataPtr, updateType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate add operation failed: \" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Add a CRL to a certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nint addCRL( INOUT DBMS_INFO *dbmsInfo, \n\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCRL,\n\t\t\tIN_HANDLE_OPT const CRYPT_CERTIFICATE iCryptRevokeCert,\n\t\t\tIN_ENUM( DBMS_UPDATE ) const DBMS_UPDATE_TYPE updateType, \n\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tCERT_ID_DATA crlIdData;\n\tBYTE certData[ MAX_CERT_SIZE + 8 ];\n\tchar encodedCertData[ MAX_ENCODED_CERT_SIZE + 8 ];\n\tconst char *sqlString;\n\ttime_t expiryDate = 0;\n\tint certDataLength DUMMY_INIT, boundDataIndex, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCRL ) );\n\tREQUIRES( ( isCertStore( dbmsInfo ) && \\\n\t\t\t\tisHandleRangeValid( iCryptRevokeCert ) ) || \\\n\t\t\t  ( !isCertStore( dbmsInfo ) && \\\n\t\t\t\tiCryptRevokeCert == CRYPT_UNUSED ) );\n\tREQUIRES( isEnumRange( updateType, DBMS_UPDATE ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get the ID information for the current CRL entry */\n\tstatus = extractCrlIdData( iCryptCRL, iCryptRevokeCert, &crlIdData );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = extractCertData( iCryptCRL, CRYPT_IATTRIBUTE_CRLENTRY,\n\t\t\t\t\t\t\t\t  certData, MAX_CERT_SIZE, &certDataLength );\n\tif( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, &expiryDate, sizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iCryptRevokeCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDTO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert any low-level certificate-specific error into something \n\t\t   generic that makes a bit more sense to the caller */\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, errorInfo, \n\t\t\t\t\t \"Couldn't extract CRL data from CRL\" ) );\n\t\t}\n\n\t/* Set up the certificate object data to be written and send it to the \n\t   database.  Certificate stores contain extra inforomation that's \n\t   needed to build a CRL so we have to vary the SQL string depending on \n\t   the keyset type */\n\tinitBoundData( boundDataPtr );\n\tif( isCertStore( dbmsInfo ) )\n\t\t{\n\t\tsetBoundDataDate( boundDataPtr, 0, &expiryDate );\n\t\tsetBoundData( boundDataPtr, 1, crlIdData.nameID, \n\t\t\t\t\t  crlIdData.nameIDlength );\n\t\tsetBoundData( boundDataPtr, 2, crlIdData.issuerID, \n\t\t\t\t\t  crlIdData.issuerIDlength );\n\t\tsetBoundData( boundDataPtr, 3, crlIdData.certID, \n\t\t\t\t\t  crlIdData.certIDlength );\n\t\tboundDataIndex = 4;\n\t\tsqlString = \"INSERT INTO CRLs VALUES (?, ?, ?, ?, ?)\";\n\n\t\t}\n\telse\n\t\t{\n\t\tsetBoundData( boundDataPtr, 0, crlIdData.issuerID, \n\t\t\t\t\t  crlIdData.issuerIDlength );\n\t\tboundDataIndex = 1;\n\t\tsqlString = \"INSERT INTO CRLs VALUES (?, ?)\";\n\t\t}\n\tif( hasBinaryBlobs( dbmsInfo ) )\n\t\t{\n\t\tsetBoundDataBlob( boundDataPtr, boundDataIndex, certData, \n\t\t\t\t\t\t  certDataLength );\n\t\t}\n\telse\n\t\t{\n\t\tint encodedCertDataLength;\n\t\t\n\t\tstatus = base64encode( encodedCertData, MAX_ENCODED_CERT_SIZE,\n\t\t\t\t\t\t\t   &encodedCertDataLength, certData, \n\t\t\t\t\t\t\t   certDataLength, CRYPT_CERTTYPE_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't base64-encode data\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tretIntError();\n\t\t\t}\n\t\tsetBoundData( boundDataPtr, boundDataIndex, encodedCertData, \n\t\t\t\t\t  encodedCertDataLength );\n\t\t}\n\tstatus = dbmsUpdate( sqlString, boundDataPtr, updateType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"CRL add operation failed: \" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add an item to the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tSTDC_UNUSED const char *password, \n\t\t\t\t\t\t\tSTDC_UNUSED const int passwordLength,\n\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int flags )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tBOOLEAN itemAdded = FALSE;\n\tint type, status, loopStatus, LOOP_ITERATOR;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVREQUEST || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER );\n\tREQUIRES( password == NULL && passwordLength == 0 );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\n\t/* Make sure that we've been given a certificate, certificate chain, or \n\t   CRL (or a PKI user if it's a CA certificate store).  We can't do any \n\t   more specific checking against the itemType because if it's coming \n\t   from outside cryptlib it'll just be passed in as a generic \n\t   certificate object with no distinction between object subtypes */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &type, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( isCertStore( dbmsInfo ) )\n\t\t{\n\t\t/* The only item that can be inserted directly into a CA certificate\n\t\t   store is a CA request or PKI user information */\n\t\tif( type != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\t\ttype != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\t\ttype != CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\t\ttype != CRYPT_CERTTYPE_PKIUSER )\n\t\t\t{\n\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t\t \"Invalid item type for CA certificate store\" ) );\n\t\t\t}\n\n\t\tif( itemType == KEYMGMT_ITEM_PKIUSER )\n\t\t\t{\n\t\t\tREQUIRES( type == CRYPT_CERTTYPE_PKIUSER );\n\t\t\treturn( caAddPKIUser( dbmsInfo, iCryptHandle, KEYSET_ERRINFO ) );\n\t\t\t}\n\n\t\t/* It's a certificate request being added to a CA certificate \n\t\t   store */\n\t\tREQUIRES( ( itemType == KEYMGMT_ITEM_REQUEST && \\\n\t\t\t\t\t( type == CRYPT_CERTTYPE_CERTREQUEST || \\\n\t\t\t\t\t  type == CRYPT_CERTTYPE_REQUEST_CERT ) ) || \\\n\t\t\t\t  ( itemType == KEYMGMT_ITEM_REVREQUEST && \\\n\t\t\t\t    type == CRYPT_CERTTYPE_REQUEST_REVOCATION ) );\n\t\treturn( caAddCertRequest( dbmsInfo, iCryptHandle, type,\n\t\t\t\t\t\t\t\t  ( flags & KEYMGMT_FLAG_UPDATE ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE, \n\t\t\t\t\t\t\t\t  ( flags & KEYMGMT_FLAG_INITIALOP ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE, KEYSET_ERRINFO ) );\n\t\t}\n\tif( type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\ttype != CRYPT_CERTTYPE_CERTCHAIN && \\\n\t\ttype != CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t \"Item being added must be a CRL or certificate\" ) );\n\t\t}\n\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_REVOCATIONINFO );\n\n\t/* Lock the certificate or CRL for our exclusive use and select the \n\t   first sub-item (certificate in a certificate chain, entry in a CRL), \n\t   update the keyset with the certificate(s)/CRL entries, and unlock it \n\t   to allow others access.\n\n\t   An item being added may already be present but we can't fail \n\t   immediately because what's being added may be a chain containing \n\t   further certificates or a CRL containing further entries so we keep \n\t   track of whether we've successfully added at least one item and clear \n\t   data duplicate errors */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t( void ) krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( status );\n\t\t}\n\tif( type == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tLOOP_LARGE( loopStatus = CRYPT_OK, cryptStatusOK( loopStatus ),\n\t\t\t\t\tloopStatus = krnlSendMessage( iCryptHandle, \n\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t\t{\n\t\t\t/* Add the next entry in the CRL */\n\t\t\tstatus = addCRL( dbmsInfo, iCryptHandle, CRYPT_UNUSED,\n\t\t\t\t\t\t\t DBMS_UPDATE_NORMAL, KEYSET_ERRINFO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t\t\tbreak;\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\titemAdded = TRUE;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tLOOP_MED( loopStatus = CRYPT_OK, cryptStatusOK( loopStatus ),\n\t\t\t\t  loopStatus = krnlSendMessage( iCryptHandle, \n\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t\t{\n\t\t\t/* Add the next certificate in the chain */\n\t\t\tstatus = addCert( dbmsInfo, iCryptHandle,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE, CERTADD_NORMAL,\n\t\t\t\t\t\t\t  DBMS_UPDATE_NORMAL, KEYSET_ERRINFO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t\t\tbreak;\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\titemAdded = TRUE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t( void ) krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !itemAdded )\n\t\t{\n\t\t/* We reached the end of the certificate chain/CRL without finding \n\t\t   anything that we could add, return a data duplicate error */\n\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO, \n\t\t\t\t  \"No new %s were found to add to the certificate store\",\n\t\t\t\t  ( type == CRYPT_CERTTYPE_CRL ) ? \\\n\t\t\t\t\t\"CRL entries\" : \"certificates\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete an item from the certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int deleteItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tDBMS_INFO *dbmsInfo = keysetInfoPtr->keysetDBMS;\n\tBOUND_DATA boundData[ BOUND_DATA_MAXITEMS ], *boundDataPtr = boundData;\n\tchar sqlBuffer[ MAX_SQL_QUERY_SIZE + 8 ];\n\tchar encodedKeyID[ ( CRYPT_MAX_TEXTSIZE * 2 ) + 8 ];\n\tconst char *keyName = getKeyName( keyIDtype );\n\tconst char *deleteString = getDeleteString( itemType );\n\tint encodedKeyIDlength, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PKIUSER );\n\tREQUIRES( ( !isCertStore( dbmsInfo ) && \\\n\t\t\t\titemType == KEYMGMT_ITEM_PUBLICKEY ) || \\\n\t\t\t  ( isCertStore( dbmsInfo ) && \\\n\t\t\t\titemType == KEYMGMT_ITEM_PKIUSER ) );\n\tREQUIRES( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Delete the item from the certificate store */\n\tstatus = makeKeyID( encodedKeyID, CRYPT_MAX_TEXTSIZE * 2, \n\t\t\t\t\t\t&encodedKeyIDlength, keyIDtype, keyID, keyIDlength );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tif( isCertStore( dbmsInfo ) )\n\t\t{\n\t\t/* The only item that can be deleted from a CA certificate store is \n\t\t   PKI user information */\n\t\tif( itemType != KEYMGMT_ITEM_PKIUSER )\n\t\t\t{\n\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t\t \"Invalid operation for CA certificate store\" ) );\n\t\t\t}\n\n\t\treturn( caDeletePKIUser( dbmsInfo, keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t\t\t KEYSET_ERRINFO ) );\n\t\t}\n\tENSURES( keyName != NULL && deleteString != NULL );\n\tstrlcpy_s( sqlBuffer, MAX_SQL_QUERY_SIZE, deleteString );\n\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, keyName );\n\tstrlcat_s( sqlBuffer, MAX_SQL_QUERY_SIZE, \" = ?\" );\n\tinitBoundData( boundDataPtr );\n\tsetBoundData( boundDataPtr, 0, encodedKeyID, encodedKeyIDlength );\n\tstatus = dbmsUpdate( sqlBuffer, boundDataPtr, DBMS_UPDATE_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, KEYSET_ERRINFO, getDbmsErrorInfo( dbmsInfo ),\n\t\t\t\t\t \"Certificate delete operation failed: \" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDatabase Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDBMSwrite( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\tFNPTR_SET( keysetInfoPtr->deleteItemFunction, deleteItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_DBMS */\n"
  },
  {
    "path": "deps/cl345/keyset/http_keys.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib HTTP Keyset Mapping Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_HTTP\n\n/* The default size of the HTTP read buffer.  This is adjusted dynamically if\n   the data being read won't fit (e.g. large CRLs).  The default size is \n   fine for certificates */\n\n#define HTTP_BUFFER_SIZE\tMIN_BUFFER_SIZE\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up key information for a query */\n\nCHECK_RETVAL_PTR \\\nstatic const char *getKeyName( IN_KEYID const CRYPT_KEYID_TYPE keyIDtype )\n\t{\n\tREQUIRES_N( isEnumRange( keyIDtype, CRYPT_KEYID ) );\n\n\tswitch( keyIDtype )\n\t\t{\n\t\tcase CRYPT_KEYID_NAME:\n\t\t\treturn( \"name\" );\n\n\t\tcase CRYPT_KEYID_URI:\n\t\t\treturn( \"uri\" );\n\n\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\treturn( \"sKIDHash\" );\n\n\t\tcase CRYPT_IKEYID_ISSUERID:\n\t\t\treturn( \"iAndSHash\" );\n\n\t\tcase CRYPT_IKEYID_CERTID:\n\t\t\treturn( \"certHash\" );\n\t\t}\n\n\tretIntError_Null();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tKeyset Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Retrieve a certificate/CRL from an HTTP server, either as a flat URL if \n   the key name is \"[none]\" or as a certificate store */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tSTDC_UNUSED void *auxInfo, \n\t\t\t\t\t\t\tSTDC_UNUSED int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tHTTP_INFO *httpInfo = keysetInfoPtr->keysetHTTP;\n\tHTTP_DATA_INFO httpDataInfo;\n\tHTTP_REQ_INFO httpReqInfo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBOOLEAN hasExplicitKeyID = FALSE;\n\tvoid *keyData;\n\tlong length;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_HTTP );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || keyIDtype == CRYPT_KEYID_URI );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( auxInfo == NULL && *auxInfoLength == 0 );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\n\t/* Set the keyID as the query portion of the URL if necessary */\n\tif( keyIDlength != 6 || strCompare( keyID, \"[none]\", 6 ) )\n\t\t{\n\t\t/* Make sure that the keyID is of an appropriate size */\n\t\tif( keyIDlength > CRYPT_MAX_TEXTSIZE )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\thasExplicitKeyID = TRUE;\n\t\t}\n\n\t/* If we haven't allocated a buffer for the data yet, do so now */\n\tif( !DATAPTR_ISSET( keysetInfoPtr->keyData ) )\n\t\t{\n\t\t/* Allocate the initial I/O buffer */\n\t\tkeyData = safeBufferAlloc( HTTP_BUFFER_SIZE );\n\t\tif( keyData == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, keyData );\n\t\tkeysetInfoPtr->keyDataSize = HTTP_BUFFER_SIZE;\n\t\t}\n\tkeyData = DATAPTR_GET( keysetInfoPtr->keyData );\n\tENSURES( keyData != NULL );\n\thttpInfo->bufPos = 0;\n\n\t/* Set up the HTTP request information and send it to the server */\n\tif( hasExplicitKeyID )\n\t\t{\n\t\tconst char *keyName = getKeyName( keyIDtype );\n\n\t\tENSURES( keyName != NULL );\n\t\tmemset( &httpReqInfo, 0, sizeof( HTTP_REQ_INFO ) );\n\t\thttpReqInfo.attribute = keyName;\n\t\thttpReqInfo.attributeLen = strlen( keyName );\n\t\thttpReqInfo.value = keyID;\n\t\thttpReqInfo.valueLen = keyIDlength;\n\t\tstatus = initHttpInfoReqEx( &httpDataInfo, &httpReqInfo );\n\t\t}\n\telse\n\t\tstatus = initHttpInfoReq( &httpDataInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = swrite( &httpInfo->stream, &httpDataInfo,\n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &httpInfo->stream, &keysetInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* Read back the response from the server.  Since we don't know the size \n\t   of the data being read in advance we have to tell the stream I/O code \n\t   to adjust the read buffer size if necessary */\n\tstatus = initHttpInfoRead( &httpDataInfo, keyData, \n\t\t\t\t\t\t\t   keysetInfoPtr->keyDataSize );\n\tENSURES( cryptStatusOK( status ) );\n\thttpDataInfo.bufferResize = TRUE;\n\tstatus = sread( &httpInfo->stream, &httpDataInfo,\n\t\t\t\t\tsizeof( HTTP_DATA_INFO ) );\n\tif( httpDataInfo.bufferResize )\n\t\t{\n\t\t/* The read buffer may have been adjusted even though an error code\n\t\t   was returned from a later operation so we process the resized \n\t\t   flag before we check for an error status */\n\t\tkeyData = httpDataInfo.buffer;\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, keyData );\n\t\tkeysetInfoPtr->keyDataSize = httpDataInfo.bufSize;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &httpInfo->stream, &keysetInfoPtr->errorInfo );\n\n\t\t/* If it's a not-found error this is non-fatal condition (it just\n\t\t   means that the requested certificate wasn't found but doesn't \n\t\t   prevent us from submitting further requests) so we clear the \n\t\t   stream status to allow further queries */\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\tsClearError( &httpInfo->stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Find out how much data we got and perform a general check that\n\t   everything is OK.  We rely on this rather than the read byte count\n\t   since checking the ASN.1, which is the data that will actually be\n\t   processed, avoids any vagaries of server implementation oddities,\n\t   which may send extra null bytes or CRLFs or do who knows what else */\n\tstatus = getLongObjectLength( keyData, httpDataInfo.bytesAvail, \n\t\t\t\t\t\t\t\t  &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create a certificate object from the returned data */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, keyData, length, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_NONE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = iCryptVerifyID( createInfo.cryptHandle, keyIDtype, keyID, \n\t\t\t\t\t\t\t keyIDlength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Certificate fetched for ID type %s doesn't actually \"\n\t\t\t\t  \"correspond to the given ID\", \n\t\t\t\t  getKeyIDName( keyIDtype ) ) );\n\t\t}\n\t*iCryptHandle = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Prepare to open a connection to an HTTP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( nameLength ) const char *name, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int nameLength,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )\n\t{\n\tHTTP_INFO *httpInfo = keysetInfoPtr->keysetHTTP;\n\tNET_CONNECT_INFO connectInfo;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_HTTP );\n\tREQUIRES( nameLength >= MIN_DNS_SIZE && nameLength < MAX_URL_SIZE );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE );\n\n\t/* Set up the HTTP connection */\n\tinitNetConnectInfo( &connectInfo, keysetInfoPtr->ownerHandle, CRYPT_ERROR, \n\t\t\t\t\t\tCRYPT_ERROR, NET_OPTION_HOSTNAME );\n\tconnectInfo.name = name;\n\tconnectInfo.nameLength = nameLength;\n\tconnectInfo.port = 80;\n\tstatus = sNetConnect( &httpInfo->stream, STREAM_PROTOCOL_HTTP, \n\t\t\t\t\t\t  &connectInfo, &keysetInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Since this isn't a general-purpose HTTP stream (of the kind used for \n\t   the HTTP-as-a-substrate PKI protocols) but is only being used for \n\t   HTTP 'GET' operations, we restrict the usage to just this operation */\n\tsioctlSet( &httpInfo->stream, STREAM_IOCTL_HTTPREQTYPES,  \n\t\t\t   STREAM_HTTPREQTYPE_GET );\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Close a previously-opened HTTP connection */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tHTTP_INFO *httpInfo = keysetInfoPtr->keysetHTTP;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_HTTP );\n\n\tsNetDisconnect( &httpInfo->stream );\n\tif( DATAPTR_ISSET( keysetInfoPtr->keyData ) )\n\t\t{\n\t\tvoid *keyData = DATAPTR_GET( keysetInfoPtr->keyData );\n\n\t\tENSURES( keyData != NULL );\n\n\t\tzeroise( keyData, keysetInfoPtr->keyDataSize );\n\t\tsafeBufferFree( keyData );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodHTTP( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_HTTP );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_HTTP */\n"
  },
  {
    "path": "deps/cl345/keyset/key_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Keyset Attribute Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"keyset.h\"\n#else\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( keysetInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( keysetInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, \n\t\t\t\t\t   CRYPT_ERROR_NOTFOUND ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorIncomplete( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( keysetInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT,\n\t\t\t\t\t   CRYPT_ERROR_INCOMPLETE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getKeysetAttribute( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\tOUT_INT_Z int *valuePtr, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Clear return value */\n\t*valuePtr = 0;\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_ERRORTYPE:\n\t\t\t*valuePtr = keysetInfoPtr->errorType;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORLOCUS:\n\t\t\t*valuePtr = keysetInfoPtr->errorLocus;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getKeysetAttributeS( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_ERRORMESSAGE:\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tERROR_INFO *errorInfo = &keysetInfoPtr->errorInfo;\n\n\t\t\tif( errorInfo->errorStringLength > 0 )\n\t\t\t\t{\n\t\t\t\treturn( attributeCopy( msgData, errorInfo->errorString,\n\t\t\t\t\t\t\t\t\t   errorInfo->errorStringLength ) );\n\t\t\t\t}\n#endif /* USE_ERRMSGS */\n\t\t\treturn( exitErrorNotFound( keysetInfoPtr,\n\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_ERRORMESSAGE ) );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_CONFIGDATA:\n\t\tcase CRYPT_IATTRIBUTE_USERINDEX:\n\t\tcase CRYPT_IATTRIBUTE_USERINFO:\n\t\tcase CRYPT_IATTRIBUTE_TRUSTEDCERT:\n\t\tcase CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT:\n\t\t\t{\n\t\t\tconst KEY_GETSPECIALITEM_FUNCTION getSpecialItemFunction = \\\n\t\t\t\t\t\t( KEY_GETSPECIALITEM_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->getSpecialItemFunction );\n\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\t\t\tREQUIRES( getSpecialItemFunction != NULL );\n\n\t\t\t/* It's encoded cryptlib-specific data, fetch it from to the\n\t\t\t   keyset */\n\t\t\treturn( getSpecialItemFunction( keysetInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\t\tmsgData->data, msgData->length, \n\t\t\t\t\t\t\t\t\t\t\t&msgData->length ) );\n\t\t\t}\n\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setKeysetAttribute( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\tIN_INT_Z const int value, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst KEY_SETSPECIALITEM_FUNCTION setSpecialItemFunction = \\\n\t\t\t\t( KEY_SETSPECIALITEM_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( keysetInfoPtr->setSpecialItemFunction );\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( setSpecialItemFunction != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_IATTRIBUTE_HWSTORAGE:\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\n\t\t\treturn( setSpecialItemFunction( keysetInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_HWSTORAGE, \n\t\t\t\t\t\t\t\t\t\t\t&value, sizeof( int ) ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setKeysetAttributeS( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t IN_LENGTH const int dataLength,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst KEY_SETSPECIALITEM_FUNCTION setSpecialItemFunction = \\\n\t\t\t\t( KEY_SETSPECIALITEM_FUNCTION ) \\\n\t\t\t\tFNPTR_GET( keysetInfoPtr->setSpecialItemFunction );\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( dataLength ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\tREQUIRES( setSpecialItemFunction != NULL );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_KEYINFO_QUERY:\n\t\tcase CRYPT_KEYINFO_QUERY_REQUESTS:\n\t\t\t{\n\t\t\tconst KEY_ISBUSY_FUNCTION isBusyFunction = \\\n\t\t\t\t\t\t( KEY_ISBUSY_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( keysetInfoPtr->isBusyFunction );\n\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_DBMS );\n\t\t\tREQUIRES( isBusyFunction != NULL );\n\n\t\t\t/* If we're in the middle of an existing query the user needs to\n\t\t\t   cancel it before starting another one */\n\t\t\tif( isBusyFunction( keysetInfoPtr ) && \\\n\t\t\t\t( dataLength != 6 || strCompare( data, \"cancel\", 6 ) ) )\n\t\t\t\treturn( exitErrorIncomplete( keysetInfoPtr, attribute ) );\n\n\t\t\t/* Send the query to the data source */\n\t\t\treturn( setSpecialItemFunction( keysetInfoPtr, attribute, data, \n\t\t\t\t\t\t\t\t\t\t\tdataLength ) );\n\t\t\t}\n\n\t\tcase CRYPT_IATTRIBUTE_CONFIGDATA:\n\t\tcase CRYPT_IATTRIBUTE_USERINDEX:\n\t\tcase CRYPT_IATTRIBUTE_USERID:\n\t\tcase CRYPT_IATTRIBUTE_USERINFO:\n\t\t\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\n\t\t\t/* It's encoded cryptlib-specific data, pass it through to the\n\t\t\t   keyset */\n\t\t\tstatus = setSpecialItemFunction( keysetInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\t\t data, dataLength );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\tattribute != CRYPT_IATTRIBUTE_USERID )\n\t\t\t\t{\n\t\t\t\t/* The update succeeded, remember that the data in the keyset\n\t\t\t\t   has changed unless it's a userID that just modifies \n\t\t\t\t   existing data */\n\t\t\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY );\n\t\t\t\tCLEAR_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/keyset/keyset.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Keyset Interface Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _KEYSET_DEFINED\n\n#define _KEYSET_DEFINED\n\n/* Various include files needed by the DBMS libraries */\n\n#include <time.h>\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Types and Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The maximum size of a certificate in binary and base64-encoded form.  For \n   the first fifteen years of use this was 2048 bytes, but given the \n   increasing tendency to shovel all manner of random junk into a \n   certificate, bringing some dangerously close to 2048 bytes (and even \n   larger in some rare cases for oddball certificates) it's now 4096 bytes.\n\n   (Another reason for allowing the increase is that an original motivation\n   for capping the value at 2048 bytes was to deal with databases that \n   didn't support BLOBs and/or didn't do VARCHARs (treating them as straight\n   CHARs), but both the massively-increased storage available to databases\n   since then and the high improbability of a PKI of any appreciable size \n   ever being widely deployed (beyond the existing databases of commercial\n   CAs), combined with the near-universal supportof BLOBs in databases, \n   means that we don't need to be so restrictive any more) */\n\n#define MAX_CERT_SIZE\t\t4096\n#define MAX_ENCODED_CERT_SIZE ( ( MAX_CERT_SIZE * 4 ) / 3 )\n\n/* Keyset information flags */\n\n#define KEYSET_FLAG_NONE\t\t0x00\t/* No keyset flag */\n#define KEYSET_FLAG_OPEN\t\t0x01\t/* Keyset is open */\n#define KEYSET_FLAG_EMPTY\t\t0x02\t/* Keyset is empty */\n#define KEYSET_FLAG_DIRTY\t\t0x04\t/* Keyset data has been changed */\n#define KEYSET_FLAG_READONLY\t0x08\t/* Keyset is read-only */\n#define KEYSET_FLAG_STREAM_OPEN\t0x10\t/* Underlying file stream is open */\n#define KEYSET_FLAG_MAX\t\t\t0x1F\t/* Maximum possible flag value */\n\n/* The precise type of the key file that we're working with.  This is used \n   for type checking to make sure we don't try to find private keys in a\n   collection of certificates or whatever */\n\ntypedef enum {\n\tKEYSET_SUBTYPE_NONE,\t\t\t\t/* Unknown */\n\tKEYSET_SUBTYPE_PGP_PUBLIC,\t\t\t/* PGP public keyring */\n\tKEYSET_SUBTYPE_PGP_PRIVATE,\t\t\t/* PGP private keyring */\n\tKEYSET_SUBTYPE_PKCS12,\t\t\t\t/* PKCS #12 key mess */\n\tKEYSET_SUBTYPE_PKCS15,\t\t\t\t/* PKCS #15 keys */\n\tKEYSET_SUBTYPE_LAST\t\t\t\t\t/* Last valid keyset subtype */\n\t} KEYSET_SUBTYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyset Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The internal fields in a keyset that hold data for the various keyset\n   types */\n\ntypedef enum { KEYSET_NONE, KEYSET_FILE, KEYSET_DBMS, KEYSET_LDAP,\n\t\t\t   KEYSET_HTTP, KEYSET_LAST } KEYSET_TYPE;\n\nstruct KI;\t/* Forward declaration for argument to function pointers */\n\n#ifdef _DBMS_DEFINED\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\n\t\tint ( *DBX_OPENDATABASEBACKEND_FUNCTION )( INOUT DBMS_STATE_INFO *dbmsStateInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_BUFFER( nameLen ) const char *name, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_NAME const int nameLen, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN const BOOLEAN isReadOnly, \n\t\t\t\t\t\t\t\t\t\t\t\t   OUT_FLAGS_Z( DBMS_FEATURE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tint *featureFlags );\ntypedef STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tvoid ( *DBX_CLOSEDATABASEBACKEND_FUNCTION )( INOUT DBMS_STATE_INFO *dbmsStateInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_PERFORMUPDATEBACKEND_FUNCTION )( INOUT DBMS_STATE_INFO *dbmsStateInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t\tIN_BUFFER_OPT( commandLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst char *command,\n\t\t\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst int commandLength, \n\t\t\t\t\t\t\t\t\t\t\t\t\tIN_ARRAY_OPT( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst void *boundData, \n\t\t\t\t\t\t\t\t\t\t\t\t\tIN_ENUM( DBMS_UPDATE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_UPDATE_TYPE updateType );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_PERFORMQUERYBACKEND_FUNCTION )( INOUT DBMS_STATE_INFO *dbmsStateInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_BUFFER_OPT( commandLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst char *command,\n\t\t\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int commandLength, \n\t\t\t\t\t\t\t\t\t\t\t\t   OUT_BUFFER_OPT( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  *dataLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int dataMaxLength,  \n\t\t\t\t\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_OPT const void *boundData, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t\t\t\t\t\t\t   IN_ENUM( DBMS_QUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_QUERY_TYPE queryType );\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\n\t\tint ( *DBX_OPENDATABASE_FUNCTION )( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t\t\t\t\t\tIN_BUFFER( nameLen ) const char *name, \n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_NAME const int nameLen, \n\t\t\t\t\t\t\t\t\t\t\tIN const BOOLEAN isReadOnly, \n\t\t\t\t\t\t\t\t\t\t\tOUT_FLAGS_Z( DBMS ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tint *featureFlags );\ntypedef STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tvoid ( *DBX_CLOSEDATABASE_FUNCTION )( INOUT struct DI *dbmsInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_PERFORMUPDATE_FUNCTION )( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t\t\t\t\t\t IN_STRING_OPT const char *command,\n\t\t\t\t\t\t\t\t\t\t\t IN_OPT const void *boundData, \n\t\t\t\t\t\t\t\t\t\t\t IN_ENUM( DBMS_UPDATE ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_UPDATE_TYPE updateType );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *DBX_PERFORMSTATICUPDATE_FUNCTION )( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t   IN_STRING const char *command );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_PERFORMQUERY_FUNCTION )( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t\t\t\t\t\tIN_STRING_OPT const char *command,\n\t\t\t\t\t\t\t\t\t\t\tOUT_BUFFER_OPT( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   *dataLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int dataMaxLength, \n\t\t\t\t\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t\t\t\t\t\tIN_OPT const void *boundData,\n\t\t\t\t\t\t\t\t\t\t\tIN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry, \n\t\t\t\t\t\t\t\t\t\t\tIN_ENUM( DBMS_QUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_QUERY_TYPE queryType );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_PERFORMSTATICQUERY_FUNCTION )( INOUT struct DI *dbmsInfo, \n\t\t\t\t\t\t\t\t\t\t\t\t  IN_STRING_OPT const char *command,\n\t\t\t\t\t\t\t\t\t\t\t\t  IN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry, \n\t\t\t\t\t\t\t\t\t\t\t\t  IN_ENUM( DBMS_QUERY ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst DBMS_QUERY_TYPE queryType );\n#endif /* _DBMS_DEFINED */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *DBX_CERTMGMT_FUNCTION )( INOUT struct KI *keysetInfo, \n\t\t\t\t\t\t\t\t\t\tOUT_OPT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t\t\t\tIN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTIFICATE caKey,\n\t\t\t\t\t\t\t\t\t\tIN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTIFICATE request,\n\t\t\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_CERTACTION ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CERTACTION_TYPE action );\n\ntypedef struct {\n\t/* The I/O stream and file name */\n\tSTREAM stream;\t\t\t\t\t/* I/O stream for key file */\n\tchar fileName[ MAX_PATH_LENGTH + 8 ];/* Name of key file */\n\n\t/* If this keyset is being used as a structured storage object for a \n\t   hardware device then we need to record the device handle so that we\n\t   can associate any items retrieved from the keyset with the \n\t   hardware */\n\tCRYPT_DEVICE iHardwareDevice;\n\t} FILE_INFO;\n\ntypedef struct DI {\n\t/* DBMS status information */\n\tSAFE_FLAGS flags;\t\t\t\t/* General status flags */\n\n\t/* For database types that can use binary blobs we need to bind the\n\t   locations of variables and use placeholders in the SQL text rather\n\t   than passing the data as part of the SQL command.  We can't leave this\n\t   on the stack since it can be referenced by the back-end an arbitrary \n\t   amount of time after we initiate the update, so we copy it to the\n\t   following staging area before we pass control to the database \n\t   back-end */\n\tchar boundData[ MAX_ENCODED_CERT_SIZE + 8 ];\n\n\t/* The data being sent to the back-end can be communicated over a variety\n\t   of channels.  If we're using the RPC API, there's a single dispatch \n\t   function through which all data is communicated via the RPC mechanism.  \n\t   If we're not using the RPC API, there are a set of function pointers,\n\t   one for each back-end access type.  In addition the state information \n\t   storage contains the state data needed for the communications \n\t   channel */\n#if defined( USE_RPCAPI )\n\tvoid ( *dispatchFunction )( void *stateInfo, BYTE *buffer );\n#elif defined( _DBMS_DEFINED )\n\tDBX_OPENDATABASEBACKEND_FUNCTION openDatabaseBackend;\n\tDBX_CLOSEDATABASEBACKEND_FUNCTION closeDatabaseBackend;\n\tDBX_PERFORMUPDATEBACKEND_FUNCTION performUpdateBackend;\n\tDBX_PERFORMQUERYBACKEND_FUNCTION performQueryBackend;\n#else\n\tint ( *openDatabaseBackend )( void );\n\tvoid ( *closeDatabaseBackend )( void );\n\tint ( *performUpdateBackend )( void );\n\tint ( *performQueryBackend )( void );\n#endif /* Backend function pointers */\n\tvoid *stateInfo;\n\n\t/* Database back-end access functions.  These use the dispatch function/\n\t   function pointers above to communicate with the back-end */\n#ifdef _DBMS_DEFINED\n\tDBX_OPENDATABASE_FUNCTION openDatabaseFunction;\n\tDBX_CLOSEDATABASE_FUNCTION closeDatabaseFunction;\n\tDBX_PERFORMUPDATE_FUNCTION performUpdateFunction;\n\tDBX_PERFORMSTATICUPDATE_FUNCTION performStaticUpdateFunction;\n\tDBX_PERFORMQUERY_FUNCTION performQueryFunction;\n\tDBX_PERFORMSTATICQUERY_FUNCTION performStaticQueryFunction;\n#else\n\tint ( *openDatabaseFunction )( void ); \n\tvoid ( *closeDatabaseFunction )( void );\n\tint ( *performUpdateFunction )( void );\n\tint ( *performStaticUpdateFunction )( void ); \n\tint ( *performQueryFunction )( void ); \n\tint ( *performStaticQueryFunction )( void ); \n#endif /* _DBMS_DEFINED */\n\n\t/* Pointers to database-specific keyset access methods */\n\tDBX_CERTMGMT_FUNCTION certMgmtFunction;\n\t} DBMS_INFO;\n\ntypedef struct {\n\t/* The I/O stream */\n\tSTREAM stream;\t\t\t\t\t/* I/O stream for HTTP read */\n\n\t/* An HTTP fetch differs from the other types of read in that it can\n\t   return data in multiple chunks depending on how much comes over the\n\t   net at once.  Because of this we need to track what's come in, and\n\t   also allocate more buffer space on demand if required.  The following\n\t   variables handle the on-demand re-allocation of buffer space */\n\tint bufPos;\t\t\t\t\t\t/* Current position in buffer */\n\t} HTTP_INFO;\n\ntypedef struct {\n\t/* LDAP access information */\n\tvoid *ld;\t\t\t\t\t\t/* LDAP connection information */\n\tvoid *result;\t\t\t\t\t/* State information for ongoing queries */\n\n\t/* The names of the object class and various attributes.  These are\n\t   stored as part of the keyset context since they may be user-defined */\n\tchar nameObjectClass[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Name of object class */\n\tchar nameFilter[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Name of query filter */\n\tchar nameCACert[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Name of CA certificate attribute */\n\tchar nameCert[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Name of certificate attribute */\n\tchar nameCRL[ CRYPT_MAX_TEXTSIZE + 8 ];\t\t/* Name of CRL attribute */\n\tchar nameEmail[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* Name of email addr.attr.*/\n\tCRYPT_CERTTYPE_TYPE objectType;\t\t\t\t/* Preferred obj.type to fetch */\n\n\t/* When storing a certificate we need the certificate DN, email address,\n\t   and certificate expiry date */\n\tchar C[ CRYPT_MAX_TEXTSIZE + 8 ], SP[ CRYPT_MAX_TEXTSIZE + 8 ],\n\t\t L[ CRYPT_MAX_TEXTSIZE + 8 ], O[ CRYPT_MAX_TEXTSIZE + 8 ],\n\t\t OU[ CRYPT_MAX_TEXTSIZE + 8 ], CN[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tchar email[ CRYPT_MAX_TEXTSIZE + 8 ];\n\ttime_t date;\n\t} LDAP_INFO;\n\n/* Defines to make access to the union fields less messy */\n\n#define keysetFile\t\tkeysetInfo.fileInfo\n#define keysetDBMS\t\tkeysetInfo.dbmsInfo\n#define keysetHTTP\t\tkeysetInfo.httpInfo\n#define keysetLDAP\t\tkeysetInfo.ldapInfo\n\n/* The structure that stores information on a keyset */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\tint ( *KEY_INIT_FUNCTION )( INOUT struct KI *keysetInfo, \n\t\t\t\t\t\t\t\tIN_BUFFER_OPT( nameLength ) const char *name, \n\t\t\t\t\t\t\t\tIN_LENGTH_NAME_Z const int nameLength,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_KEYOPT ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_KEYOPT_TYPE options );\ntypedef RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\tint ( *KEY_SHUTDOWN_FUNCTION )( INOUT struct KI *keysetInfo );\n#ifdef USE_LDAP\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tint ( *KEY_GETATTRIBUTE_FUNCTION )( INOUT struct KI *keysetInfo, \n\t\t\t\t\t\t\t\t\t\tOUT void *data,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tint ( *KEY_SETATTRIBUTE_FUNCTION )( INOUT struct KI *keysetInfo, \n\t\t\t\t\t\t\t\t\t\tconst void *data,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type );\n#endif /* USE_LDAP */\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\n\tint ( *KEY_GETITEM_FUNCTION )( INOUT struct KI *keysetInfo,\n\t\t\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t   IN_OPT void *auxInfo, \n\t\t\t\t\t\t\t\t   INOUT_OPT int *auxInfoLength, \n\t\t\t\t\t\t\t\t   IN_FLAGS_Z( KEYMGMT ) const int flags );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\n\tint ( *KEY_GETSPECIALITEM_FUNCTION )( INOUT struct KI *keysetInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t\t\t\t\t  OUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t *dataLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tvoid *data,\n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT \\\n\t\t\t\t\t\t\t\t\t\t\tconst int dataMaxLength,\n\t\t\t\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tint *dataLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\tint ( *KEY_SETITEM_FUNCTION )( INOUT struct KI *deviceInfo,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t   IN_BUFFER_OPT( passwordLength ) \\\n\t\t\t\t\t\t\t\t\tconst char *password, \n\t\t\t\t\t\t\t\t   IN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t\t\t   IN_FLAGS( KEYMGMT ) const int flags );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\tint ( *KEY_SETSPECIALITEM_FUNCTION )( INOUT struct KI *deviceInfo,\n\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\n\tint ( *KEY_DELETEITEM_FUNCTION )( INOUT struct KI *keysetInfo,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t\t  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_KEYID const int keyIDlength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \\\n\tint ( *KEY_GETFIRSTITEM_FUNCTION )( INOUT struct KI *keysetInfo,\n\t\t\t\t\t\t\t\t\t\tOUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t\t\tOUT int *stateInfo,\n\t\t\t\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t\t\tIN_KEYID \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *keyID, \n\t\t\t\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int options );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\n\tint ( *KEY_GETNEXTITEM_FUNCTION )( INOUT struct KI *keysetInfo,\n\t\t\t\t\t\t\t\t\t   OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t\t   INOUT_OPT int *stateInfo, \n\t\t\t\t\t\t\t\t\t\t/* May be absent for an ongoing query run as \n\t\t\t\t\t\t\t\t\t\t   { getItem, getNext, getNext, ... } */\n\t\t\t\t\t\t\t\t\t   IN_FLAGS_Z( KEYMGMT ) const int options );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\tBOOLEAN ( *KEY_ISBUSY_FUNCTION )( INOUT struct KI *keysetInfo );\n\ntypedef struct KI {\n\t/* General keyset information */\n\tKEYSET_TYPE type;\t\t\t\t/* Keyset type (file, DBMS, HTTP, etc) */\n\tKEYSET_SUBTYPE subType;\t\t\t/* File keyset subtype (PGP, P12, P15, etc) */\n\tSAFE_FLAGS flags;\t\t\t\t/* Keyset information flags */\n\n\t/* Keyset type-specific information */\n\tunion {\n\t\tFILE_INFO *fileInfo;\n#ifdef USE_DBMS\n\t\tDBMS_INFO *dbmsInfo;\n#endif /* USE_DBMS */\n#ifdef USE_HTTP\n\t\tHTTP_INFO *httpInfo;\n#endif /* USE_HTTP */\n#ifdef USE_LDAP\n\t\tLDAP_INFO *ldapInfo;\n#endif /* USE_LDAP */\n\t\t} keysetInfo;\n\n\t/* Pointers to keyset access methods */\n\tFNPTR initFunction, shutdownFunction;\n#ifdef USE_LDAP\n\tFNPTR getAttributeFunction, setAttributeFunction;\n#endif /* USE_LDAP */\n\tFNPTR getItemFunction, getSpecialItemFunction;\n\tFNPTR setItemFunction, setSpecialItemFunction;\n\tFNPTR deleteItemFunction, getFirstItemFunction, getNextItemFunction;\n\tFNPTR isBusyFunction;\n\n\t/* Some keysets require keyset-type-specific data storage, which is\n\t   managed via the following variables. keyDataSize denotes the total\n\t   size in bytes of the keyData buffer, and keyDataNoObjects is the \n\t   number of objects in the buffer if it's implemented as an array of \n\t   key data objects */\n\tDATAPTR keyData;\t\t\t\t/* Keyset data buffer */\n\tint keyDataSize;\t\t\t\t/* Buffer size */\n\tint keyDataNoObjects;\t\t\t/* No.of objects in key data buffer */\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* Low-level error information */\n\tERROR_INFO errorInfo;\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the\n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\n\t/* Variable-length storage for the type-specific data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} KEYSET_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyset Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Functions in cryptkey.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckKeyset( const KEYSET_INFO *keysetInfoPtr );\n\n/* Keyset attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getKeysetAttribute( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\tOUT_INT_Z int *valuePtr, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getKeysetAttributeS( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setKeysetAttribute( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\tIN_INT_Z const int value, \n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setKeysetAttributeS( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t IN_LENGTH const int dataLength,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\n\n/* Prototypes for keyset mapping functions */\n\n#ifdef USE_ODBC\n  CHECK_RETVAL \\\n  int dbxInitODBC( void );\n  void dbxEndODBC( void );\n#else\n  #define dbxInitODBC()\t\t\t\t\t\tCRYPT_OK\n  #define dbxEndODBC()\n#endif /* USE_ODBC */\n#ifdef USE_DBMS\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodDBMS( INOUT KEYSET_INFO *keysetInfo,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_KEYSET ) \\\n\t\t\t\t\t\t\tconst CRYPT_KEYSET_TYPE type );\n#else\n  #define setAccessMethodDBMS( x, y )\t\tCRYPT_ARGERROR_NUM1\n#endif /* USE_DBMS */\n#ifdef USE_HTTP\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodHTTP( INOUT KEYSET_INFO *keysetInfo );\n#else\n  #define setAccessMethodHTTP( x )\t\t\tCRYPT_ARGERROR_NUM1\n#endif /* USE_HTTP */\n#ifdef USE_LDAP\n  CHECK_RETVAL \\\n  int dbxInitLDAP( void );\n  void dbxEndLDAP( void );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodLDAP( INOUT KEYSET_INFO *keysetInfo );\n#else\n  #define dbxInitLDAP()\t\t\t\t\t\tCRYPT_OK\n  #define dbxEndLDAP()\n  #define setAccessMethodLDAP( x )\t\t\tCRYPT_ARGERROR_NUM1\n#endif /* USE_LDAP */\n#ifdef USE_PGPKEYS\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodPGPPublic( INOUT KEYSET_INFO *keysetInfo );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodPGPPrivate( INOUT KEYSET_INFO *keysetInfo );\n#else\n  #define setAccessMethodPGPPublic( x )\t\tCRYPT_ARGERROR_NUM1\n  #define setAccessMethodPGPPrivate( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_PGPKEYS */\n#ifdef USE_PKCS12\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodPKCS12( INOUT KEYSET_INFO *keysetInfo );\n#else\n  #define setAccessMethodPKCS12( x )\t\tCRYPT_ARGERROR_NUM1\n#endif /* PKCS #12 */\n#ifdef USE_PKCS15\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodPKCS15( INOUT KEYSET_INFO *keysetInfo );\n#else\n  #define setAccessMethodPKCS15( x )\t\tCRYPT_ARGERROR_NUM1\n#endif /* PKCS #15 */\n#if defined( USE_PGPKEYS ) && defined( USE_PKCS12_WRITE )\n  #define isWriteableFileKeyset( type ) \\\n\t\t  ( ( type ) == KEYSET_SUBTYPE_PGP_PUBLIC || \\\n\t\t\t( type ) == KEYSET_SUBTYPE_PKCS12 || \\\n\t\t\t( type ) == KEYSET_SUBTYPE_PKCS15 )\n#elif defined( USE_PGPKEYS ) \n  #define isWriteableFileKeyset( type ) \\\n\t\t  ( ( type ) == KEYSET_SUBTYPE_PGP_PUBLIC || \\\n\t\t\t( type ) == KEYSET_SUBTYPE_PKCS15 )\n#elif defined( USE_PKCS12_WRITE )\n  #define isWriteableFileKeyset( type ) \\\n\t\t  ( ( type ) == KEYSET_SUBTYPE_PKCS12 || \\\n\t\t\t( type ) == KEYSET_SUBTYPE_PKCS15 )\n#else\n  #define isWriteableFileKeyset( type ) \\\n\t\t  ( ( type ) == KEYSET_SUBTYPE_PKCS15 )\n#endif /* Writeable keyset subtypes */\n#endif /* _KEYSET_DEFINED */\n"
  },
  {
    "path": "deps/cl345/keyset/ldap.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib LDAP Mapping Routines\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2004\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following code can be built to use most of the various subtly \n   incompatible LDAP clients.  By default the Windows client is used under \n   Windows and the OpenLDAP client is used elsewhere, this can be overridden \n   by defining NETSCAPE_CLIENT which causes the Netscape client to be used \n   instead.  Old versions of the Windows client were considerably more buggy \n   than the Netscape one, so if you get data corruption and other problems \n   try switching to the Netscape client (see the comment next to ber_free() \n   for more details on some of these problems).  Note that there are at least\n   five incompatible LDAP APIs, the one defined in the RFCs, the older \n   OpenLDAP API, the newer OpenLDAP API, the Windows API, and the Netscape \n   API.  The following code tries to auto-adjust itself for all of the\n   different versions, but it may need some hand-tweaking.\n\n   A generalisation of this is that you shouldn't be using LDAP for\n   certificate storage at all unless you're absolutely forced to.  LDAP\n   is a truly awful mechanism for storing and retrieving certificates,\n   technical reasons for this may be found in the Godzilla crypto tutorial\n   and in any database text written within the last 20 years */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_LDAP\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with LDAP enabled.\" )\n#endif /* Warn with VC++ */\n\n/* LDAP requires us to set up complicated structures to handle DN's.  The\n   following values define the upper limit for DN string data and the\n   maximum number of attributes we write to a directory */\n\n#define MAX_DN_STRINGSIZE\t\t1024\n#define MAX_LDAP_ATTRIBUTES\t\t20\n\n/* These should really be taken from the system include directory but this\n   leads to too many complaints from people who don't read the LDAP\n   installation section of the manual */\n\n#if defined( __WINDOWS__ )\n  /* cryptlib.h includes a trap for inclusion of wincrypt.h before \n     cryptlib.h which results in a compiler error if both files are \n\t included.  To disable this, we need to undefine the CRYPT_MODE_ECB \n\t defined in cryptlib.h */\n  #undef CRYPT_MODE_ECB\n  #include <winldap.h>\n  #define LDAP_API\t\tLDAPAPI\t\t/* Windows LDAP API type */\n  #define timeval\t\tl_timeval\t/* Windows uses nonstandard name */\n#elif defined( NETSCAPE_CLIENT )\n  #include <ldap.h>\n  #define LDAP_API\t\tLDAP_CALL\t/* Netscape LDAP API type */\n  #define ber_free\t\tldap_ber_free\t/* Netscape uses nonstandard name */\n#else\n  #include <ldap.h>\n  #include <sys/time.h>\t\t\t\t/* For 'struct timeval' */\n  #ifdef LDAP_API\n\t/* Some OpenLDAP versions have their own LDAP_API macro which is \n\t   incompatible with the usage here, so we clear it before we define our\n\t   own */\n\t#undef LDAP_API\n  #endif /* LDAP_API */\n  #define LDAP_API\t\t\t\t\t/* OpenLDAP LDAP API type */\n#endif /* Different LDAP client types */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tWindows Init/Shutdown Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef DYNAMIC_LOAD\n\n/* Global function pointers.  These are necessary because the functions need\n   to be dynamically linked since older systems won't contain the necessary\n   DLL's.  Explicitly linking to them will make cryptlib unloadable on these \n   systems */\n\nstatic INSTANCE_HANDLE hLDAP = NULL_INSTANCE;\n\ntypedef void ( LDAP_API *BER_FREE )( BerElement *ber, int freebuf );\ntypedef int ( LDAP_API *LDAP_ADD_S )( LDAP *ld, const char *dn, LDAPMod **attrs );\ntypedef int ( LDAP_API *LDAP_DELETE_S )( LDAP *ld, const char *dn );\ntypedef char * ( LDAP_API *LDAP_ERR2STRING )( int err );\ntypedef char * ( LDAP_API *LDAP_FIRST_ATTRIBUTE )( LDAP *ld, LDAPMessage *entry,\n\t\t\t\t\t\t\t\t\t\t  BerElement **ber );\ntypedef LDAPMessage * ( LDAP_API *LDAP_FIRST_ENTRY )( LDAP *ld, LDAPMessage *result );\n#if defined( __WINDOWS__ )\n  typedef int ( LDAP_API *LDAP_GETLASTERROR )( void );\n#elif defined( NETSCAPE_CLIENT )\n  typedef int ( LDAP_API *LDAP_GET_LDERRNO )( LDAP *ld, char **m, char **s );\n#else\n  typedef int ( LDAP_API *LDAP_GET_OPTION )( LDAP *ld, int option, void *outvalue );\n#endif /* Different LDAP client types */\ntypedef struct berval ** ( LDAP_API *LDAP_GET_VALUES_LEN )( LDAP *ld, LDAPMessage *entry,\n\t\t\t\t\t\t\t\t\t\t\t\t   const char *attr );\ntypedef LDAP * ( LDAP_API *LDAP_INIT )( const char *host, int port );\ntypedef int ( LDAP_API *LDAP_IS_LDAP_URL )( char *url );\ntypedef void ( LDAP_API *LDAP_MEMFREE )( void *p );\ntypedef void ( LDAP_API *LDAP_MODSFREE )( LDAPMod **mods, int freemods );\ntypedef int ( LDAP_API *LDAP_MSGFREE )( LDAPMessage *lm );\ntypedef LDAPMessage * ( LDAP_API *LDAP_NEXT_ENTRY )( LDAP *ld, LDAPMessage *result );\ntypedef int ( LDAP_API *LDAP_SEARCH_ST )( LDAP *ld, const char *base, int scope,\n\t\t\t\t\t\t\t\tconst char *filter, char **attrs,\n\t\t\t\t\t\t\t\tint attrsonly, struct timeval *timeout,\n\t\t\t\t\t\t\t\tLDAPMessage **res );\ntypedef int ( LDAP_API *LDAP_SET_OPTION )( LDAP *ld, int option, void *optdata );\ntypedef int ( LDAP_API *LDAP_SIMPLE_BIND_S )( LDAP *ld, const char *who,\n\t\t\t\t\t\t\t\t\t const char *passwd );\ntypedef int ( LDAP_API *LDAP_UNBIND )( LDAP *ld );\ntypedef int ( LDAP_API *LDAP_URL_SEARCH_ST )( LDAP *ld, char *url, int attrsonly,\n\t\t\t\t\t\t\t\t\t\t\t  struct timeval *timeout,\n\t\t\t\t\t\t\t\t\t\t\t  LDAPMessage **res );\ntypedef void ( LDAP_API *LDAP_VALUE_FREE_LEN )( struct berval **vals );\n#if defined( __WINDOWS__ ) || defined( NETSCAPE_CLIENT )\n  static BER_FREE p_ber_free = NULL;\n#endif /* __WINDOWS__ || NETSCAPE_CLIENT */\nstatic LDAP_ADD_S p_ldap_add_s = NULL;\nstatic LDAP_DELETE_S p_ldap_delete_s = NULL;\nstatic LDAP_ERR2STRING p_ldap_err2string = NULL;\nstatic LDAP_FIRST_ATTRIBUTE p_ldap_first_attribute = NULL;\nstatic LDAP_FIRST_ENTRY p_ldap_first_entry = NULL;\n#if defined( __WINDOWS__ )\n  static LDAP_GETLASTERROR p_LdapGetLastError = NULL;\n#elif defined( NETSCAPE_CLIENT )\n  static LDAP_GET_LDERRNO p_ldap_get_lderrno = NULL;\n#else\n  static LDAP_GET_OPTION p_ldap_get_option = NULL;\n#endif /* Different LDAP client types */\nstatic LDAP_GET_VALUES_LEN p_ldap_get_values_len = NULL;\nstatic LDAP_INIT p_ldap_init = NULL;\nstatic LDAP_IS_LDAP_URL p_ldap_is_ldap_url = NULL;\nstatic LDAP_MEMFREE p_ldap_memfree = NULL;\nstatic LDAP_NEXT_ENTRY p_ldap_next_entry = NULL;\nstatic LDAP_MSGFREE p_ldap_msgfree = NULL;\nstatic LDAP_SEARCH_ST p_ldap_search_st = NULL;\nstatic LDAP_SET_OPTION p_ldap_set_option = NULL;\nstatic LDAP_SIMPLE_BIND_S p_ldap_simple_bind_s = NULL;\nstatic LDAP_UNBIND p_ldap_unbind = NULL;\nstatic LDAP_URL_SEARCH_ST p_ldap_url_search_st = NULL;\nstatic LDAP_VALUE_FREE_LEN p_ldap_value_free_len = NULL;\n\n/* The use of dynamically bound function pointers vs.statically linked\n   functions requires a bit of sleight of hand since we can't give the\n   pointers the same names as prototyped functions.  To get around this we\n   redefine the actual function names to the names of the pointers */\n\n#define ber_free\t\t\t\tp_ber_free\n#define ldap_add_s\t\t\t\tp_ldap_add_s\n#define ldap_delete_s\t\t\tp_ldap_delete_s\n#define ldap_err2string\t\t\tp_ldap_err2string\n#define ldap_first_attribute\tp_ldap_first_attribute\n#define ldap_first_entry\t\tp_ldap_first_entry\n#if defined( __WINDOWS__ )\n  #define LdapGetLastError\t\tp_LdapGetLastError\n#elif defined( NETSCAPE_CLIENT )\n  #define ldap_get_lderrno\t\tp_ldap_get_lderrno\n#else\n  #define ldap_get_option\t\tp_ldap_get_option\n#endif /* Different LDAP client types */\n#define ldap_get_values_len\t\tp_ldap_get_values_len\n#define ldap_init\t\t\t\tp_ldap_init\n#define ldap_is_ldap_url\t\tp_ldap_is_ldap_url\n#define ldap_memfree\t\t\tp_ldap_memfree\n#define ldap_msgfree\t\t\tp_ldap_msgfree\n#define ldap_next_entry\t\t\tp_ldap_next_entry\n#define ldap_search_st\t\t\tp_ldap_search_st\n#define ldap_set_option\t\t\tp_ldap_set_option\n#define ldap_simple_bind_s\t\tp_ldap_simple_bind_s\n#define ldap_unbind\t\t\t\tp_ldap_unbind\n#define ldap_url_search_st\t\tp_ldap_url_search_st\n#define ldap_value_free_len\t\tp_ldap_value_free_len\n\n/* The name of the LDAP driver, in this case the Netscape LDAPv3 driver */\n\n#ifdef __WIN16__\n  #define LDAP_LIBNAME\t\t\t\"NSLDSS16.DLL\"\n#elif defined( __WIN32__ )\n  #define LDAP_LIBNAME\t\t\t\"wldap32.dll\"\n#elif defined( __UNIX__ )\n  #if defined( __APPLE__ )\n\t/* OS X has built-in LDAP support via OpenLDAP */\n\t#define LDAP_LIBNAME\t\t\"libldap.dylib\"\n  #elif defined NETSCAPE_CLIENT\n\t#define LDAP_LIBNAME\t\t\"libldap50.so\"\n  #else\n\t#define LDAP_LIBNAME\t\t\"libldap.so\"\n  #endif /* NETSCAPE_CLIENT */\n#endif /* System-specific ODBC library names */\n\n/* Dynamically load and unload any necessary LDAP libraries */\n\nCHECK_RETVAL \\\nint dbxInitLDAP( void )\n\t{\n#ifdef __WIN16__\n\tUINT errorMode;\n#endif /* __WIN16__ */\n\n\t/* If the LDAP module is already linked in, don't do anything */\n\tif( hLDAP != NULL_INSTANCE )\n\t\treturn( CRYPT_OK );\n\n\t/* Obtain a handle to the module containing the LDAP functions */\n#ifdef __WIN16__\n\terrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );\n\thLDAP = LoadLibrary( LDAP_LIBNAME );\n\tSetErrorMode( errorMode );\n\tif( hLDAP < HINSTANCE_ERROR )\n\t\t{\n\t\thLDAP = NULL_INSTANCE;\n\t\treturn( CRYPT_ERROR );\n\t\t}\n#else\n\tif( ( hLDAP = DynamicLoad( LDAP_LIBNAME ) ) == NULL_INSTANCE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't load LDAP driver '%s'\", LDAP_LIBNAME ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n#endif /* __WIN32__ */\n\tDEBUG_DIAG(( \"Loaded LDAP driver '%s'\", LDAP_LIBNAME ));\n\n\t/* Now get pointers to the functions */\n#if defined( __WINDOWS__ )\n\tp_ber_free = ( BER_FREE ) DynamicBind( hLDAP, \"ber_free\" );\n#elif defined( NETSCAPE_CLIENT )\n\tp_ber_free = ( BER_FREE ) DynamicBind( hLDAP, \"ldap_ber_free\" );\n#endif /* __WINDOWS__ || NETSCAPE_CLIENT */\n\tp_ldap_add_s = ( LDAP_ADD_S ) DynamicBind( hLDAP, \"ldap_add_s\" );\n\tp_ldap_delete_s = ( LDAP_DELETE_S ) DynamicBind( hLDAP, \"ldap_delete_s\" );\n\tp_ldap_err2string = ( LDAP_ERR2STRING ) DynamicBind( hLDAP, \"ldap_err2string\" );\n\tp_ldap_first_attribute = ( LDAP_FIRST_ATTRIBUTE ) DynamicBind( hLDAP, \"ldap_first_attribute\" );\n\tp_ldap_first_entry = ( LDAP_FIRST_ENTRY ) DynamicBind( hLDAP, \"ldap_first_entry\" );\n#if defined( __WINDOWS__ )\n\tp_LdapGetLastError = ( LDAP_GETLASTERROR ) DynamicBind( hLDAP, \"LdapGetLastError\" );\n#elif defined( NETSCAPE_CLIENT )\n\tp_ldap_get_lderrno = ( LDAP_GET_LDERRNO ) DynamicBind( hLDAP, \"ldap_get_lderrno\" );\n#else\n\tp_ldap_get_option = ( LDAP_GET_OPTION ) DynamicBind( hLDAP, \"ldap_get_option\" );\n#endif /* Different LDAP client types */\n\tp_ldap_get_values_len = ( LDAP_GET_VALUES_LEN ) DynamicBind( hLDAP, \"ldap_get_values_len\" );\n\tp_ldap_init = ( LDAP_INIT ) DynamicBind( hLDAP, \"ldap_init\" );\n\tp_ldap_is_ldap_url = ( LDAP_IS_LDAP_URL ) DynamicBind( hLDAP, \"ldap_is_ldap_url\" );\n\tp_ldap_memfree = ( LDAP_MEMFREE ) DynamicBind( hLDAP, \"ldap_memfree\" );\n\tp_ldap_msgfree = ( LDAP_MSGFREE ) DynamicBind( hLDAP, \"ldap_msgfree\" );\n\tp_ldap_next_entry = ( LDAP_NEXT_ENTRY ) DynamicBind( hLDAP, \"ldap_next_entry\" );\n\tp_ldap_search_st = ( LDAP_SEARCH_ST ) DynamicBind( hLDAP, \"ldap_search_st\" );\n\tp_ldap_set_option = ( LDAP_SET_OPTION ) DynamicBind( hLDAP, \"ldap_set_option\" );\n\tp_ldap_simple_bind_s = ( LDAP_SIMPLE_BIND_S ) DynamicBind( hLDAP, \"ldap_simple_bind_s\" );\n\tp_ldap_unbind = ( LDAP_UNBIND ) DynamicBind( hLDAP, \"ldap_unbind\" );\n\tp_ldap_url_search_st = ( LDAP_URL_SEARCH_ST ) DynamicBind( hLDAP, \"ldap_url_search_st\" );\n\tp_ldap_value_free_len = ( LDAP_VALUE_FREE_LEN ) DynamicBind( hLDAP, \"ldap_value_free_len\" );\n\n\t/* Make sure that we got valid pointers for every LDAP function */\n\tif( p_ldap_add_s == NULL ||\n#ifdef NETSCAPE_CLIENT\n\t\tp_ber_free == NULL ||\n#endif /* NETSCAPE_CLIENT */\n\t\tp_ldap_delete_s == NULL || p_ldap_err2string == NULL || \\\n\t\tp_ldap_first_attribute == NULL || p_ldap_first_entry == NULL || \\\n\t\tp_ldap_init == NULL ||\n#if defined( __WINDOWS__ )\n\t\tp_LdapGetLastError == NULL ||\n#elif defined( NETSCAPE_CLIENT )\n\t\tp_ldap_get_lderrno == NULL || p_ldap_is_ldap_url == NULL ||\n\t\tp_ldap_url_search_st == NULL ||\n#else\n\t\tp_ldap_get_option == NULL ||\n#endif /* NETSCAPE_CLIENT */\n\t\tp_ldap_get_values_len == NULL || p_ldap_memfree == NULL || \\\n\t\tp_ldap_msgfree == NULL || p_ldap_next_entry == NULL || \\\n\t\tp_ldap_search_st == NULL || p_ldap_set_option == NULL || \\\n\t\tp_ldap_simple_bind_s == NULL || p_ldap_unbind == NULL || \\\n\t\tp_ldap_value_free_len == NULL )\n\t\t{\n\t\t/* Free the library reference and reset the handle */\n\t\tDynamicUnload( hLDAP );\n\t\thLDAP = NULL_INSTANCE;\n\t\tDEBUG_DIAG(( \"Couldn't bind to LDAP driver functions\" ));\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Some versions of OpenLDAP define ldap_is_ldap_url() but not \n\t   ldap_url_search_st() (which makes the former more or less useless), \n\t   so if the latter isn't defined we remove the former as well */\n\tif( p_ldap_url_search_st == NULL )\n\t\tp_ldap_is_ldap_url = NULL;\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid dbxEndLDAP( void )\n\t{\n\tif( hLDAP != NULL_INSTANCE )\n\t\tDynamicUnload( hLDAP );\n\thLDAP = NULL_INSTANCE;\n\t}\n#else\n\nCHECK_RETVAL \\\nint dbxInitLDAP( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n\nvoid dbxEndLDAP( void )\n\t{\n\t}\n#endif /* __WINDOWS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Assign a name for an LDAP object/attribute field */\n\nstatic void assignFieldName( const CRYPT_USER cryptOwner, char *buffer,\n\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_TYPE option )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( cryptOwner, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, option );\n\tassert( cryptStatusOK( status ) );\n\tbuffer[ msgData.length ] = '\\0';\n\t}\n\n/* Get information on an LDAP error */\n\nstatic void getErrorInfo( KEYSET_INFO *keysetInfoPtr, int ldapStatus )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &keysetInfoPtr->errorInfo;\n#endif /* USE_ERRMSGS */\n#ifndef __WINDOWS__ \n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n#endif /* !__WINDOWS__ */\n#ifdef __WINDOWS__\n\tint errorCode;\n#endif /* __WINDOWS__ */\n\tchar *errorMessage;\n\n#if defined( __WINDOWS__ )\n\terrorCode = LdapGetLastError();\n\tif( errorCode == LDAP_SUCCESS )\n\t\t{\n\t\t/* In true Microsoft fashion LdapGetLastError() can return\n\t\t   LDAP_SUCCESS with the error string set to \"Success.\" so if we\n\t\t   get this we use the status value returned by the original LDAP\n\t\t   function call instead */\n\t\terrorCode = ldapStatus;\n\t\t}\n\terrorMessage = ldap_err2string( errorCode );\n  #if 0\n\t/* The exact conditions under which ldap_err2string() does something\n\t   useful are somewhat undefined, it may be necessary to use the\n\t   following which works with general Windows error codes rather than\n\t   special-case LDAP function result codes */\n\terrorCode = GetLastError();\n\tFormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n\t\t\t\t   NULL, errorCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),\n\t\t\t\t   ldapInfo->errorMessage, MAX_ERRMSG_SIZE - 1, NULL );\n  #endif /* 0 */\n#elif defined( NETSCAPE_CLIENT )\n\tldap_get_lderrno( ldapInfo->ld, NULL, &errorMessage );\n#else\n\tldap_get_option( ldapInfo->ld, LDAP_OPT_ERROR_STRING, &errorMessage );\n#endif /* Different LDAP client types */\n\tif( errorMessage != NULL )\n\t\t{\n\t\tsetErrorString( errorInfo, errorMessage, strlen( errorMessage ) );\n\t\t}\n\telse\n\t\tclearErrorString( errorInfo );\n\t}\n\n/* Map an LDAP error to the corresponding cryptlib error.  The various LDAP\n   imlpementations differ slightly in their error codes, so we have to \n   adjust them as appropriate */\n\nstatic int mapLdapError( const int ldapError, const int defaultError )\n\t{\n\tswitch( ldapError )\n\t\t{\n\t\tcase LDAP_INAPPROPRIATE_AUTH:\n\t\tcase LDAP_INVALID_CREDENTIALS:\n\t\tcase LDAP_AUTH_UNKNOWN:\n#if defined( __WINDOWS__ )\n\t\tcase LDAP_INSUFFICIENT_RIGHTS:\n\t\tcase LDAP_AUTH_METHOD_NOT_SUPPORTED:\n#elif defined( NETSCAPE_CLIENT )\n\t\tcase LDAP_INSUFFICIENT_ACCESS:\n#else\n\t\tcase LDAP_INSUFFICIENT_ACCESS:\n\t\tcase LDAP_AUTH_METHOD_NOT_SUPPORTED:\n#endif /* Different client types */\n\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\n#if defined( __WINDOWS__ )\n\t\tcase LDAP_ATTRIBUTE_OR_VALUE_EXISTS:\n\t\tcase LDAP_ALREADY_EXISTS:\n#elif defined( NETSCAPE_CLIENT )\n\t\tcase LDAP_TYPE_OR_VALUE_EXISTS:\n#else\n\t\tcase LDAP_TYPE_OR_VALUE_EXISTS:\n\t\tcase LDAP_ALREADY_EXISTS:\n#endif /* Different client types */\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n#if defined( __WINDOWS__ )\n\t\tcase LDAP_CONFIDENTIALITY_REQUIRED:\n#elif defined( NETSCAPE_CLIENT )\n\t\t/* Nothing */\n#else\n\t\tcase LDAP_CONFIDENTIALITY_REQUIRED:\n\t\tcase LDAP_STRONG_AUTH_REQUIRED:\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n#endif /* Different client types */\n\n\t\tcase LDAP_INVALID_DN_SYNTAX:\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\n\t\tcase LDAP_TIMELIMIT_EXCEEDED:\n\t\tcase LDAP_TIMEOUT:\n\t\t\treturn( CRYPT_ERROR_TIMEOUT );\n\n#ifndef NETSCAPE_CLIENT\n\t\tcase LDAP_NO_RESULTS_RETURNED:\n#endif /* NETSCAPE_CLIENT */\n\t\tcase LDAP_NO_SUCH_ATTRIBUTE:\n\t\tcase LDAP_NO_SUCH_OBJECT:\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n#ifndef NETSCAPE_CLIENT\n\t\tcase LDAP_NOT_SUPPORTED:\n\t\tcase LDAP_UNAVAILABLE:\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#endif /* NETSCAPE_CLIENT */\n\n\t\tcase LDAP_SIZELIMIT_EXCEEDED:\n\t\tcase LDAP_RESULTS_TOO_LARGE:\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t\tcase LDAP_NO_MEMORY:\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\n\treturn( defaultError );\n\t}\n\n/* Copy attribute information into an LDAPMod structure so it can be written to\n   the directory */\n\nstatic LDAPMod *copyAttribute( const char *attributeName,\n\t\t\t\t\t\t\t   const void *attributeValue,\n\t\t\t\t\t\t\t   const int attributeLength )\n\t{\n\tLDAPMod *ldapModPtr;\n\n\t/* Allocate room for the LDAPMod structure */\n\tif( ( ldapModPtr = ( LDAPMod * ) clAlloc( \"copyAttribute\", \\\n\t\t\t\t\t\t\t\t\t\t\t  sizeof( LDAPMod ) ) ) == NULL )\n\t\treturn( NULL );\n\n\t/* Set up the pointers to the attribute information.  This differs\n\t   slightly depending on whether we're adding text or binary data */\n\tif( !attributeLength )\n\t\t{\n\t\tif( ( ldapModPtr->mod_values = \\\n\t\t\t\t\tclAlloc( \"copyAttribute\", \\\n\t\t\t\t\t\t\t 2 * sizeof( void * ) ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"copyAttribute\", ldapModPtr );\n\t\t\treturn( NULL );\n\t\t\t}\n\t\tldapModPtr->mod_op = LDAP_MOD_ADD;\n\t\tldapModPtr->mod_type = ( char * ) attributeName;\n\t\tldapModPtr->mod_values[ 0 ] = ( char * ) attributeValue;\n\t\tldapModPtr->mod_values[ 1 ] = NULL;\n\t\t}\n\telse\n\t\t{\n\t\tif( ( ldapModPtr->mod_bvalues = \\\n\t\t\t\t\tclAlloc( \"copyAttribute\", \\\n\t\t\t\t\t\t\t 2 * sizeof( struct berval ) ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"copyAttribute\", ldapModPtr );\n\t\t\treturn( NULL );\n\t\t\t}\n\t\tldapModPtr->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;\n\t\tldapModPtr->mod_type = ( char * ) attributeName;\n\t\tldapModPtr->mod_bvalues[ 0 ]->bv_len = attributeLength;\n\t\tldapModPtr->mod_bvalues[ 0 ]->bv_val = ( char * ) attributeValue;\n\t\tldapModPtr->mod_bvalues[ 1 ] = NULL;\n\t\t}\n\n\treturn( ldapModPtr );\n\t}\n\n/* Encode DN information in the RFC 1779 reversed format.  We don't have to\n   explicitly check for overflows (which will lead to truncation of the \n   resulting encoded DN) because the certificate management code limits the \n   size of each component to a small fraction of the total buffer size.  \n   Besides which, it's LDAP, anyone using this crap as a certificate store \n   is asking for it anyway */\n\nstatic void catComponent( char *dest, const int destLen, char *src )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\t/* Find the end of the existing destination string */\n\tLOOP_LARGE( i = 0, i < destLen && dest[ i ] != '\\0', i++ );\n\tENSURES_V( LOOP_BOUND_OK );\n\tif( i >= destLen )\n\t\tretIntError_Void();\n\n\t/* Append the source string, escaping special chars */\n\tLOOP_LARGE_CHECKINC( i < destLen - 1 && *src != '\\0', src++ )\n\t\t{\n\t\tconst char ch = *src;\n\n\t\tif( ch == ',' )\n\t\t\t{\n\t\t\tdest[ i++ ] = '\\\\';\n\t\t\tif( i >= destLen )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdest[ i++ ] = ch;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tdest[ i ] = '\\0';\n\t}\n\nstatic int encodeDN( char *dn, const int maxDnLen, char *C, char *SP, \n\t\t\t\t\t char *L, char *O, char *OU, char *CN )\n\t{\n\tstrlcpy_s( dn, maxDnLen, \"CN=\" );\n\tcatComponent( dn, maxDnLen, CN );\n\tif( *OU )\n\t\t{\n\t\tstrlcat_s( dn, maxDnLen, \",OU=\" );\n\t\tcatComponent( dn, maxDnLen, OU );\n\t\t}\n\tif( *O )\n\t\t{\n\t\tstrlcat_s( dn, maxDnLen, \",O=\" );\n\t\tcatComponent( dn, maxDnLen, O );\n\t\t}\n\tif( *L )\n\t\t{\n\t\tstrlcat_s( dn, maxDnLen, \",L=\" );\n\t\tcatComponent( dn, maxDnLen, L );\n\t\t}\n\tif( *SP )\n\t\t{\n\t\tstrlcat_s( dn, maxDnLen, \",ST=\" );\t/* Not to be confused with ST=street */\n\t\tcatComponent( dn, maxDnLen, SP );\n\t\t}\n\tstrlcat_s( dn, maxDnLen, \",C=\" );\n\tcatComponent( dn, maxDnLen, C );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDirectory Open/Close Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Close a previously-opened LDAP connection.  We have to have this before\n   the init function since it may be called by it if the open process fails.\n   This is necessary because the complex LDAP open may require a fairly\n   extensive cleanup afterwards */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\n\tldap_unbind( ldapInfo->ld );\n\tldapInfo->ld = NULL;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Open a connection to an LDAP directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( nameLength ) const char *name,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int nameLength,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )\n\t{\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\tURL_INFO urlInfo;\n\tconst char *ldapUser = NULL;\n\tchar ldapServer[ MAX_URL_SIZE + 8 ];\n\tint maxEntries = 2, timeout, ldapPort, ldapStatus = LDAP_OTHER, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\tREQUIRES( nameLength >= MIN_URL_SIZE && nameLength < MAX_URL_SIZE );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE );\n\n\t/* Check the URL.  The Netscape and OpenLDAP APIs provide the function\n\t   ldap_is_ldap_url() for this, but this requires a complete LDAP URL\n\t   rather than just a server name and port */\n\tif( nameLength > MAX_URL_SIZE - 1 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tstatus = sNetParseURL( &urlInfo, name, nameLength, URL_TYPE_LDAP );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tREQUIRES( rangeCheck( urlInfo.hostLen, 1, MAX_URL_SIZE ) );\n\tmemcpy( ldapServer, urlInfo.host, urlInfo.hostLen );\n\tldapServer[ urlInfo.hostLen ] = '\\0';\n\tldapPort = ( urlInfo.port > 0 ) ? urlInfo.port : LDAP_PORT;\n\tif( urlInfo.locationLen > 0 )\n\t\tldapUser = urlInfo.location;\n\n\t/* Open the connection to the server */\n\tif( ( ldapInfo->ld = ldap_init( ldapServer, ldapPort ) ) == NULL )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tif( ( ldapStatus = ldap_simple_bind_s( ldapInfo->ld, ldapUser, \n\t\t\t\t\t\t\t\t\t\t   NULL ) ) != LDAP_SUCCESS )\n\t\t{\n\t\tgetErrorInfo( keysetInfoPtr, ldapStatus );\n\t\tldap_unbind( ldapInfo->ld );\n\t\tldapInfo->ld = NULL;\n\t\treturn( mapLdapError( ldapStatus, CRYPT_ERROR_OPEN ) );\n\t\t}\n\n\t/* Set the search timeout and limit the maximum number of returned\n\t   entries to 2 (setting the search timeout is mostly redundant since we\n\t   use search_st anyway, however there may be other operations which also\n\t   require some sort of timeout which can't be explicitly specified */\n\tstatus = krnlSendMessage( keysetInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout, \n\t\t\t\t\t\t\t  CRYPT_OPTION_NET_READTIMEOUT );\n\tif( cryptStatusError( status ) || timeout < 15 )\n\t\t{\n\t\t/* Network I/O may be set to be nonblocking, so we make sure we try\n\t\t   for at least 15s before timing out */\n\t\ttimeout = 15;\n\t\t}\n\tldap_set_option( ldapInfo->ld, LDAP_OPT_TIMELIMIT, &timeout );\n\tldap_set_option( ldapInfo->ld, LDAP_OPT_SIZELIMIT, &maxEntries );\n\n\t/* Set up the names of the objects and attributes */\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameObjectClass,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS );\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameFilter,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_FILTER );\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameCACert,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_CACERTNAME );\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameCert,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_CERTNAME );\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameCRL,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_CRLNAME );\n\tassignFieldName( keysetInfoPtr->ownerHandle, ldapInfo->nameEmail,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_EMAILNAME );\n\tkrnlSendMessage( keysetInfoPtr->ownerHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t &ldapInfo->objectType,\n\t\t\t\t\t CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE );\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDirectory Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a query to an LDAP server */\n\nstatic int sendLdapQuery( LDAP_INFO *ldapInfo, LDAPMessage **resultPtr,\n\t\t\t\t\t\t  const CRYPT_HANDLE iOwnerHandle, const char *dn )\n\t{\n\tconst CRYPT_CERTTYPE_TYPE objectType = ldapInfo->objectType;\n\tconst char *certAttributes[] = { ldapInfo->nameCert, NULL };\n\tconst char *caCertAttributes[] = { ldapInfo->nameCACert, NULL };\n\tconst char *crlAttributes[] = { ldapInfo->nameCRL, NULL };\n\tstruct timeval ldapTimeout = { 0, 0 };\n\tint ldapStatus = LDAP_OTHER, timeout, status;\n\n\t/* Network I/O may be set to be nonblocking, so we make sure we try for \n\t   at least 15s before timing out */\n\tstatus = krnlSendMessage( iOwnerHandle, IMESSAGE_GETATTRIBUTE, &timeout, \n\t\t\t\t\t\t\t  CRYPT_OPTION_NET_READTIMEOUT );\n\tif( cryptStatusError( status ) || timeout < 15 )\n\t\tldapTimeout.tv_sec = 15;\n\telse\n\t\tldapTimeout.tv_sec = timeout;\n\n\t/* If the LDAP search-by-URL functions are available and the key ID is \n\t   an LDAP URL, perform a search by URL */\n\tif( ldap_is_ldap_url != NULL && ldap_is_ldap_url( ( char * ) dn ) )\n\t\t{\n\t\treturn( ldap_url_search_st( ldapInfo->ld, ( char * ) dn, FALSE, \n\t\t\t\t\t\t\t\t\t&ldapTimeout, resultPtr ) );\n\t\t}\n\n\t/* Try and retrieve the entry for this DN from the directory.  We use a \n\t   base specified by the DN, a chop of 0 (to return only the current \n\t   entry), any object class (to get around the problem of \n\t   implementations which stash certificates in whatever they feel like), \n\t   and look for a certificate attribute.  If the search fails for this \n\t   attribute, we try again but this time go for a CA certificate \n\t   attribute which unfortunately slows down the search somewhat when the \n\t   certificate isn't found but can't really be avoided since there's no \n\t   way to tell in advance whether a certificate will be an end entity or \n\t   a CA certificate.  To complicate things even further, we may also \n\t   need to check for a CRL in case this is what the user is after */\n\tif( objectType == CRYPT_CERTTYPE_NONE || \\\n\t\tobjectType == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\tldapStatus = ldap_search_st( ldapInfo->ld, dn, LDAP_SCOPE_BASE,\n\t\t\t\t\t\t\t\t\t ldapInfo->nameFilter,\n\t\t\t\t\t\t\t\t\t ( char ** ) certAttributes, 0,\n\t\t\t\t\t\t\t\t\t &ldapTimeout, resultPtr );\n\t\tif( ldapStatus == LDAP_SUCCESS )\n\t\t\treturn( ldapStatus );\n\t\t}\n\tif( objectType == CRYPT_CERTTYPE_NONE || \\\n\t\tobjectType == CRYPT_CERTTYPE_CERTIFICATE )\n\t\t{\n\t\tldapStatus = ldap_search_st( ldapInfo->ld, dn, LDAP_SCOPE_BASE,\n\t\t\t\t\t\t\t\t\t ldapInfo->nameFilter,\n\t\t\t\t\t\t\t\t\t ( char ** ) caCertAttributes, 0,\n\t\t\t\t\t\t\t\t\t &ldapTimeout, resultPtr );\n\t\tif( ldapStatus == LDAP_SUCCESS )\n\t\t\treturn( ldapStatus );\n\t\t}\n\tif( objectType == CRYPT_CERTTYPE_NONE || \\\n\t\tobjectType == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tldapStatus = ldap_search_st( ldapInfo->ld, dn, LDAP_SCOPE_BASE,\n\t\t\t\t\t\t\t\t\t ldapInfo->nameFilter,\n\t\t\t\t\t\t\t\t\t ( char ** ) crlAttributes, 0,\n\t\t\t\t\t\t\t\t\t &ldapTimeout, resultPtr );\n\t\tif( ldapStatus == LDAP_SUCCESS )\n\t\t\treturn( ldapStatus );\n\t\t}\n\n\treturn( ldapStatus );\n\t}\n\n/* Retrieve a key attribute from an LDAP directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tSTDC_UNUSED void *auxInfo, \n\t\t\t\t\t\t\tSTDC_UNUSED int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\tLDAPMessage *result DUMMY_INIT_PTR, *resultEntry;\n\tBerElement *ber;\n\tstruct berval **valuePtrs;\n\tchar dn[ MAX_DN_STRINGSIZE + 8 ];\n\tchar *attributePtr;\n\tint ldapStatus, status = CRYPT_OK;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( keyIDtype != CRYPT_KEYID_NONE || iCryptHandle != NULL );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( auxInfo == NULL && *auxInfoLength == 0 );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\n\t/* Clear return value */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* Convert the DN into a null-terminated form */\n\tif( keyIDlength > MAX_DN_STRINGSIZE - 1 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tREQUIRES( rangeCheck( keyIDlength, 1, MAX_DN_STRINGSIZE ) );\n\tmemcpy( dn, keyID, keyIDlength );\n\tdn[ keyIDlength ] = '\\0';\n\n\t/* Send the LDAP query to the server */\n\tldapStatus = sendLdapQuery( ldapInfo, &result, \n\t\t\t\t\t\t\t\tkeysetInfoPtr->ownerHandle, dn );\n\tif( ldapStatus != LDAP_SUCCESS )\n\t\t{\n\t\tgetErrorInfo( keysetInfoPtr, ldapStatus );\n\t\treturn( mapLdapError( ldapStatus, CRYPT_ERROR_READ ) );\n\t\t}\n\n\t/* We got something, start fetching the results */\n\tif( ( resultEntry = ldap_first_entry( ldapInfo->ld, result ) ) == NULL )\n\t\t{\n\t\tldap_msgfree( result );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* Copy out the certificate */\n\tif( ( attributePtr = ldap_first_attribute( ldapInfo->ld, resultEntry, \n\t\t\t\t\t\t\t\t\t\t\t   &ber ) ) == NULL )\n\t\t{\n\t\tldap_msgfree( result );\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tvaluePtrs = ldap_get_values_len( ldapInfo->ld, resultEntry, \n\t\t\t\t\t\t\t\t\t attributePtr );\n\tif( valuePtrs != NULL )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t/* Create a certificate object from the returned data */\n\t\tsetMessageCreateObjectIndirectInfo( &createInfo, valuePtrs[ 0 ]->bv_val,\n\t\t\t\t\t\t\t\t\t\t\tvaluePtrs[ 0 ]->bv_len,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_NONE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = iCryptVerifyID( createInfo.cryptHandle, keyIDtype, \n\t\t\t\t\t\t\t\t\t keyID, keyIDlength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t*iCryptHandle = createInfo.cryptHandle;\n\t\t\t}\n\t\tldap_value_free_len( valuePtrs );\n\t\t}\n\telse\n\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\n\t/* Clean up.  The ber_free() function is rather problematic because\n\t   Netscape uses the nonstandard ldap_ber_free() name (which can be fixed\n\t   with proprocessor trickery), Microsoft first omitted it entirely (up \n\t   to NT4 SP4) and then later added it as a stub (Win2K, rumour has it \n\t   that the only reason this function even exists is because the Netscape \n\t   client required it), and OpenLDAP doesn't use it at all.  Because it \n\t   may or may not exist in the MS client, we call it if we resolved its \n\t   address, otherwise we skip it.\n\n\t   The function is further complicated by the fact that LDAPv3 says the\n\t   second parameter should be 0, however the Netscape client docs used to\n\t   require it to be 1 and the MS client was supposed to ignore it so the\n\t   code passed in a 1.  Actually the way the MS implementation handles\n\t   the BER data is that the BerElement returned by ldap_first_attribute()\n\t   is (despite what the MSDN docs claim) just a data structure pointed to\n\t   by lm_ber in the LDAPMessage structure, all that\n\t   ldap_first_attribute() does is redirect the lm_ber pointer inside the\n\t   LDAPMessage, so actually freeing this wouldn't be a good idea.\n\n\t   Later, the Netscape docs were updated to require a 0, presumably to\n\t   align them with the LDAPv3 spec.  On some systems it makes no\n\t   difference whether you pass in a 0 or 1 to the call, but on others it\n\t   can cause an access violation.  Presumably eventually everyone will\n\t   move to something which implements the new rather than old Netscape-\n\t   documented behaviour, so we pass in 0 as the argument.\n\n\t   It gets worse than this though.  Calling ber_free() with newer\n\t   versions of the Windows LDAP client with any argument at all causes\n\t   internal data corruption which typically first results in a soft\n\t   failure (e.g. a data fetch fails) and then eventually a hard failure\n\t   such as an access violation after further calls are made.  The only\n\t   real way to fix this is to avoid calling it entirely, this doesn't\n\t   seem to leak any more memory than LDAP leaks anyway (that is, there \n\t   are a considerable number of memory and handle leaks, but the number \n\t   doesn't increase if ber_free() isn't called).\n\n\t   There have been reports that with some older versions of the Windows\n\t   LDAP client (e.g. the one in Win95) the ldap_msgfree() call generates\n\t   an exception in wldap.dll, if this is a problem you need to either\n\t   install a newer LDAP DLL or switch to the Netscape one.\n\n\t   The reason for some of the Windows problems are because the\n\t   wldap32.lib shipped with VC++ uses different ordinals than the\n\t   wldap32.dll which comes with the OS (see MSKB article Q283199), so\n\t   that simply using the out-of-the-box development tools with the out-\n\t   of-the-box OS can result in access violations and assorted other\n\t   problems */\n#ifdef NETSCAPE_CLIENT\n\tif( ber_free != NULL )\n\t\tber_free( ber, 0 );\n#endif /* NETSCAPE_CLIENT */\n\tldap_memfree( attributePtr );\n\tldap_msgfree( result );\n\n\treturn( status );\n\t}\n\n/* Add an entry/attribute to an LDAP directory.  The LDAP behaviour differs\n   somewhat from DAP in that assigning a value to a nonexistant attribute\n   implicitly creates the required attribute.  In addition deleting the last\n   value automatically deletes the entire attribute, the delete item code\n   assumes the user is requesting a superset of this behaviour and deletes\n   the entire entry */\n\nstatic int addCert( KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\tconst CRYPT_HANDLE iCryptHandle )\n\t{\n\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\tLDAPMod *ldapMod[ MAX_LDAP_ATTRIBUTES + 8 ];\n\tMESSAGE_DATA msgData;\n\tBYTE keyData[ MAX_CERT_SIZE + 8 ];\n\tchar dn[ MAX_DN_STRINGSIZE + 8 ];\n\tchar C[ CRYPT_MAX_TEXTSIZE + 1 + 8 ], SP[ CRYPT_MAX_TEXTSIZE + 1 + 8 ],\n\t\tL[ CRYPT_MAX_TEXTSIZE + 1 + 8 ], O[ CRYPT_MAX_TEXTSIZE + 1 + 8 ],\n\t\tOU[ CRYPT_MAX_TEXTSIZE + 1 + 8 ], CN[ CRYPT_MAX_TEXTSIZE + 1 + 8 ],\n\t\temail[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\tint keyDataLength, ldapModIndex = 1, status, LOOP_ITERATOR;\n\n\t*C = *SP = *L = *O = *OU = *CN = *email = '\\0';\n\n\t/* Extract the DN and altName components.  This changes the currently\n\t   selected DN components, but this is OK since we've got the \n\t   certificate locked and the prior state will be restored when we \n\t   unlock it */\n\tkrnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &nameValue, CRYPT_ATTRIBUTE_CURRENT );\n\tsetMessageData( &msgData, C, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_COUNTRYNAME );\n\tif( cryptStatusOK( status ) )\n\t\tC[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, SP, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_STATEORPROVINCENAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tSP[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, L, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_LOCALITYNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tL[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, O, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_ORGANIZATIONNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tO[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, OU, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tOU[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tsetMessageData( &msgData, CN, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_COMMONNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tCN[ msgData.length ] = '\\0';\n\tif( cryptStatusOK( status ) || status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* Get the string form of the DN */\n\t\tstatus = encodeDN( dn, MAX_DN_STRINGSIZE, C, SP, L, O, OU, CN );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, email, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_EMAIL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\temail[ msgData.length ] = '\\0';\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert any low-level certificate-specific error into something \n\t\t   generic which makes a bit more sense to the caller */\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Get the certificate data */\n\tsetMessageData( &msgData, keyData, MAX_CERT_SIZE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tkeyDataLength = msgData.length;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Convert any low-level certificate-specific error into something \n\t\t   generic which makes a bit more sense to the caller */\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Set up the fixed attributes and certificate data.  This currently\n\t   always adds a certificate as a standard certificate rather than a CA \n\t   certificate because of uncertainty over what other implementations\n\t   will try and look for, once enough other software uses the CA \n\t   certificate attribute this can be switched over */\n\tif( ( ldapMod[ 0 ] = copyAttribute( ldapInfo->nameObjectClass,\n\t\t\t\t\t\t\t\t\t\t\"certPerson\", 0 ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tif( ( ldapMod[ ldapModIndex++ ] = copyAttribute( ldapInfo->nameCert,\n\t\t\t\t\t\t\t\t\t\tkeyData, keyDataLength ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\n\t/* Set up the DN/identification information */\n\tif( cryptStatusOK( status ) && *email && \\\n\t\t( ldapMod[ ldapModIndex++ ] = \\\n\t\t\t\tcopyAttribute( ldapInfo->nameEmail, email, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *CN && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"CN\", CN, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *OU && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"OU\", OU, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *O && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"O\", O, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *L && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"L\", L, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *SP && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"SP\", SP, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tif( cryptStatusOK( status ) && *C && \\\n\t\t( ldapMod[ ldapModIndex++ ] = copyAttribute( \"C\", C, 0 ) ) == NULL )\n\t\tstatus = CRYPT_ERROR_MEMORY;\n\tldapMod[ ldapModIndex ] = NULL;\n\n\t/* Add the new attribute/entry */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint ldapStatus;\n\n\t\tif( ( ldapStatus = ldap_add_s( ldapInfo->ld, dn,\n\t\t\t\t\t\t\t\t\t   ldapMod ) ) != LDAP_SUCCESS )\n\t\t\t{\n\t\t\tgetErrorInfo( keysetInfoPtr, ldapStatus );\n\t\t\tstatus = mapLdapError( ldapStatus, CRYPT_ERROR_WRITE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up.  We do it the hard way rather than using\n\t   ldap_mods_free() here partially because the ldapMod[] array\n\t   isn't malloc()'d, but mostly because for the Netscape client\n\t   library ldap_mods_free() causes some sort of memory corruption,\n\t   possibly because it's trying to free the mod_values[] entries\n\t   which are statically allocated, and for the MS client the\n\t   function doesn't exist */\n\tLOOP_EXT( ldapModIndex = 0, \n\t\t\t  ldapModIndex < MAX_LDAP_ATTRIBUTES && \\\n\t\t\t\tldapMod[ ldapModIndex ] != NULL,\n\t\t\t  ldapModIndex++, MAX_LDAP_ATTRIBUTES + 1 )\n\t\t{\n\t\tif( ldapMod[ ldapModIndex ]->mod_op & LDAP_MOD_BVALUES )\n\t\t\tclFree( \"addCert\", ldapMod[ ldapModIndex ]->mod_bvalues );\n\t\telse\n\t\t\tclFree( \"addCert\", ldapMod[ ldapModIndex ]->mod_values );\n\t\tclFree( \"addCert\", ldapMod[ ldapModIndex ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( ldapModIndex >= MAX_LDAP_ATTRIBUTES )\n\t\tretIntError();\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tSTDC_UNUSED const char *password, \n\t\t\t\t\t\t\tSTDC_UNUSED const int passwordLength,\n\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int flags )\n\t{\n\tBOOLEAN seenNonDuplicate = FALSE;\n\tint type, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( password == NULL && passwordLength == 0 );\n\tREQUIRES( flags == KEYMGMT_FLAG_NONE );\n\n\t/* Make sure we've been given a certificate or certificate chain */\n\tstatus = krnlSendMessage( iCryptHandle, MESSAGE_GETATTRIBUTE, &type, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( type != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\ttype != CRYPT_CERTTYPE_CERTCHAIN )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* Lock the certificate for our exclusive use (in case it's a \n\t   certificate chain, we also select the first certificate in the \n\t   chain), update the keyset with the certificate(s), and unlock it to \n\t   allow others access */\n\tkrnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MED_CHECK( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Add the certificate */\n\t\tstatus = addCert( keysetInfoPtr, iCryptHandle );\n\n\t\t/* A certificate being added may already be present, however we \n\t\t   can't fail immediately because what's being added may be a chain \n\t\t   containing further certificates so we keep track of whether we've \n\t\t   successfully added at least one certificate and clear data \n\t\t   duplicate errors */\n\t\tif( status == CRYPT_OK )\n\t\t\tseenNonDuplicate = TRUE;\n\t\telse\n\t\t\t{\n\t\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\telse\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Move on to the next certificate */\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tkrnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusOK( status ) && !seenNonDuplicate )\n\t\t{\n\t\t/* We reached the end of the chain without finding anything we could\n\t\t   add, return a data duplicate error */\n\t\tstatus = CRYPT_ERROR_DUPLICATE;\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Delete an entry from an LDAP directory */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int deleteItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\tchar dn[ MAX_DN_STRINGSIZE + 8 ];\n\tint ldapStatus;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || keyIDtype == CRYPT_KEYID_URI );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Convert the DN into a null-terminated form */\n\tif( keyIDlength > MAX_DN_STRINGSIZE - 1 )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tREQUIRES( rangeCheck( keyIDlength, 1, MAX_DN_STRINGSIZE ) );\n\tmemcpy( dn, keyID, keyIDlength );\n\tdn[ keyIDlength ] = '\\0';\n\n\t/* Delete the entry */\n\tif( ( ldapStatus = ldap_delete_s( ldapInfo->ld, dn ) ) != LDAP_SUCCESS )\n\t\t{\n\t\tgetErrorInfo( keysetInfoPtr, ldapStatus );\n\t\treturn( mapLdapError( ldapStatus, CRYPT_ERROR_WRITE ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return status information for the keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isBusyFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES_B( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES_B( keysetInfoPtr->type == KEYSET_LDAP );\n\n\treturn( FALSE );\n\t}\n\n/* Get/set keyset attributes */\n\nstatic void *getAttributeDataPtr( KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t\t  const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tLDAP_INFO *ldapInfo = keysetInfoPtr->keysetLDAP;\n\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS:\n\t\t\treturn( ldapInfo->nameObjectClass );\n\n\t\tcase CRYPT_OPTION_KEYS_LDAP_FILTER:\n\t\t\treturn( ldapInfo->nameFilter );\n\n\t\tcase CRYPT_OPTION_KEYS_LDAP_CACERTNAME:\n\t\t\treturn( ldapInfo->nameCACert );\n\n\t\tcase CRYPT_OPTION_KEYS_LDAP_CERTNAME:\n\t\t\treturn( ldapInfo->nameCert );\n\n\t\tcase CRYPT_OPTION_KEYS_LDAP_CRLNAME:\n\t\t\treturn( ldapInfo->nameCRL );\n\n\t\tcase CRYPT_OPTION_KEYS_LDAP_EMAILNAME:\n\t\t\treturn( ldapInfo->nameEmail );\n\t\t}\n\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t\t INOUT void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst void *attributeDataPtr;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\n\tattributeDataPtr = getAttributeDataPtr( keysetInfoPtr, type );\n\tif( attributeDataPtr == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\treturn( attributeCopy( data, attributeDataPtr, \n\t\t\t\t\t\t   strlen( attributeDataPtr ) ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t\t const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) data;\n\tBYTE *attributeDataPtr;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\n\tattributeDataPtr = getAttributeDataPtr( keysetInfoPtr, type );\n\tif( attributeDataPtr == NULL )\n\t\treturn( CRYPT_ARGERROR_VALUE );\n\tif( msgData->length < 1 || msgData->length > CRYPT_MAX_TEXTSIZE )\n\t\treturn( CRYPT_ARGERROR_STR1 );\n\tREQUIRES( rangeCheck( msgData->length, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( attributeDataPtr, msgData->data, msgData->length );\n\tattributeDataPtr[ msgData->length ] = '\\0';\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodLDAP( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_LDAP );\n\n#ifdef DYNAMIC_LOAD\n\t/* Make sure that the LDAP driver is bound in */\n\tif( hLDAP == NULL_INSTANCE )\n\t\treturn( CRYPT_ERROR_OPEN );\n#endif /* DYNAMIC_LOAD */\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( keysetInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( keysetInfoPtr->setAttributeFunction, setAttributeFunction );\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\tFNPTR_SET( keysetInfoPtr->deleteItemFunction, deleteItemFunction );\n\tFNPTR_SET( keysetInfoPtr->isBusyFunction, isBusyFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_LDAP */\n"
  },
  {
    "path": "deps/cl345/keyset/odbc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib ODBC Mapping Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\t\t/* For sprintf() */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"dbms.h\"\n  #include \"keyset.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/dbms.h\"\n  #include \"keyset/keyset.h\"\n#endif /* Compiler-specific includes */\n\n/* ODBC functions can return either SQL_SUCCESS or SQL_SUCCESS_WITH_INFO to\n   indicate successful completion, to make them easier to work with we use\n   a general status-check macro along the lines of cryptStatusOK() */\n\n#define sqlStatusOK( status ) \\\n\t\t( ( status ) == SQL_SUCCESS || ( status ) == SQL_SUCCESS_WITH_INFO )\n\n/* DBMS back-ends that require special handling */\n\nenum { DBMS_NONE, DBMS_ACCESS, DBMS_INTERBASE, DBMS_MYSQL, DBMS_POSTGRES,\n\t   DBMS_SQLITE, DBMS_LAST };\n\n/* The level at which we want SQLDiagRec() to return error information to \n   us */\n\ntypedef enum { SQL_ERRLVL_NONE, SQL_ERRLVL_STMT, SQL_ERRLVL_DBC, \n\t\t\t   SQL_ERRLVL_ENV, SQL_ERRLVL_LAST } SQL_ERRLVL_TYPE;\n\n/* When rewriting an SQL query we have to provide a slightly larger buffer \n   to allow for possible expansion of some SQL strings */\n\n#define SQL_QUERY_BUFSIZE\t( MAX_SQL_QUERY_SIZE + 64 )\n\n/* Some ODBC functions take either pointers or small integer values cast to \n   pointers to indicate certain magic values.  This causes problems in \n   64-bit environments because the LLP64 model means that pointers are 64 \n   bits while ints and longs are 32 bits.  To deal with this we define the \n   following data-conversion macros for 32- and 64-bit environments */\n\n#ifdef __WIN64__\n  #define VALUE_TO_PTR\tULongToPtr\n#else\n  #define VALUE_TO_PTR\t( SQLPOINTER )\n#endif /* 32- vs. 64-bit environment */\n\n#ifdef USE_ODBC\n\n/* When processing bound data we need to store the state information used by \n   SQLBindParameter() until the SQL operation completes.  The following \n   structure provides the necessary state storage */\n\ntypedef struct {\n\tSQLLEN lengthStorage[ BOUND_DATA_MAXITEMS + 8 ];\n\tSQL_TIMESTAMP_STRUCT timestampStorage;\n\t} BOUND_DATA_STATE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tInit/Shutdown Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef DYNAMIC_LOAD\n\n/* Global function pointers.  These are necessary because the functions need\n   to be dynamically linked since not all systems contain the necessary\n   shared libraries.  Explicitly linking to them will make cryptlib \n   unloadable on some systems.\n\n   MSDN updates from late 2000 defined SQLROWCOUNT themselves (which could be\n   fixed by undefining it), however after late 2002 the value was typedef'd,\n   requring all sorts of extra trickery to handle the different cases.\n   Because of this issue, this particular function is typedef'd with a _FN \n   suffix.\n   \n   Several of the ODBC functions allow such a mess of parameters, with \n   options for pointers to be cast to integers indexing a table of data \n   values hidden under someone's bed and other peculiarities, that several \n   of the following markups are only approximations for the way the \n   functions are used here.  If markups are absent entirely (e.g. for the\n   SQLSetXXXAttr() functions) it's because the polymorphism of parameters \n   doesn't allow any coherent annotation to be given */\n\nstatic INSTANCE_HANDLE hODBC = NULL_INSTANCE;\n\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLALLOCHANDLE ) \\\n\t\t\t\t\t( SQLSMALLINT HandleType, IN_OPT SQLHANDLE InputHandle, \n\t\t\t\t\tOUT_PTR SQLHANDLE *OutputHandlePtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLBINDPARAMETER ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle, \n\t\t\t\t\tSQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType,\n\t\t\t\t\tSQLSMALLINT ValueType, SQLSMALLINT ParameterType,\n\t\t\t\t\tSQLULEN ColumnSize, SQLSMALLINT DecimalDigits,\n\t\t\t\t\tIN_BUFFER_OPT( BufferLength ) SQLPOINTER ParameterValuePtr, \n\t\t\t\t\tSQLLEN BufferLength, \n\t\t\t\t\tINOUT_OPT SQLLEN *StrLen_or_IndPtr );\ntypedef SQLRETURN ( SQL_API *SQLCLOSECURSOR )( IN SQLHSTMT StatementHandle );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLCONNECT ) \\\n\t\t\t\t\t( IN SQLHDBC ConnectionHandle,\n\t\t\t\t\tIN_BUFFER( NameLength1 ) SQLCHAR *ServerName, \n\t\t\t\t\tSQLSMALLINT NameLength1,\n\t\t\t\t\tIN_BUFFER( NameLength2 ) SQLCHAR *UserName, \n\t\t\t\t\tSQLSMALLINT NameLength2,\n\t\t\t\t\tIN_BUFFER( NameLength3 ) SQLCHAR *Authentication, \n\t\t\t\t\tSQLSMALLINT NameLength3 );\ntypedef SQLRETURN ( SQL_API *SQLDISCONNECT )( IN SQLHDBC ConnectionHandle );\ntypedef SQLRETURN ( SQL_API *SQLENDTRAN )( SQLSMALLINT HandleType,\n\t\t\t\t\tIN SQLHANDLE Handle, SQLSMALLINT CompletionType );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLEXECDIRECT ) \\\n\t\t\t\t\t( SQLHSTMT StatementHandle,\n\t\t\t\t\tIN_BUFFER( TextLength ) SQLCHAR *StatementText, \n\t\t\t\t\tSQLINTEGER TextLength );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLEXECUTE ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLFETCH ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle );\ntypedef SQLRETURN ( SQL_API *SQLFREEHANDLE )( SQLSMALLINT HandleType,\n\t\t\t\t\tIN SQLHANDLE Handle );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETDATA ) \\\n\t\t\t\t\t( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, \n\t\t\t\t\tSQLSMALLINT TargetType, \n\t\t\t\t\tOUT_BUFFER( BufferLength, *StrLen_or_IndPtr ) \\\n\t\t\t\t\t\tSQLPOINTER TargetValuePtr, \n\t\t\t\t\tSQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETDIAGREC ) \\\n\t\t\t\t\t( SQLSMALLINT HandleType,\n\t\t\t\t\tIN SQLHANDLE Handle, SQLSMALLINT RecNumber,\n\t\t\t\t\tOUT_BUFFER_FIXED( SQL_SQLSTATE_SIZE ) SQLCHAR *Sqlstate, \n\t\t\t\t\tOUT SQLINTEGER *NativeErrorPtr,\n\t\t\t\t\tOUT_BUFFER( BufferLength, *TextLengthPtr ) \\\n\t\t\t\t\t\tSQLCHAR *MessageText, \n\t\t\t\t\tSQLSMALLINT BufferLength, SQLSMALLINT *TextLengthPtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETINFO ) \\\n\t\t\t\t\t( IN SQLHDBC ConnectionHandle,\n\t\t\t\t\tSQLUSMALLINT InfoType, \n\t\t\t\t\tOUT_BUFFER( BufferLength, *StringLengthPtr ) \\\n\t\t\t\t\t\tSQLPOINTER InfoValuePtr, \n\t\t\t\t\tSQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETSTMTATTR ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle,\n\t\t\t\t\tSQLINTEGER Attribute, OUT SQLPOINTER ValuePtr,\n\t\t\t\t\tSQLINTEGER BufferLength, \n\t\t\t\t\tSTDC_UNUSED SQLINTEGER *StringLengthPtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLGETTYPEINFO ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle,\n\t\t\t\t\tSQLSMALLINT DataType );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLPREPARE ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle,\n\t\t\t\t\tIN_BUFFER( TextLength ) SQLCHAR *StatementText, \n\t\t\t\t\tSQLINTEGER TextLength );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLROWCOUNT_FN ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle,\n\t\t\t\t\tOUT SQLLEN *RowCountPtr );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETCONNECTATTR ) \\\n\t\t\t\t\t( IN SQLHDBC ConnectionHandle,\n\t\t\t\t\tSQLINTEGER Attribute, SQLPOINTER ValuePtr,\n\t\t\t\t\tSQLINTEGER StringLength );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETENVATTR ) \\\n\t\t\t\t\t( IN SQLHENV EnvironmentHandle,\n\t\t\t\t\tSQLINTEGER Attribute, SQLPOINTER ValuePtr,\n\t\t\t\t\tSQLINTEGER StringLength );\ntypedef CHECK_RETVAL SQLRETURN ( SQL_API *SQLSETSTMTATTR ) \\\n\t\t\t\t\t( IN SQLHSTMT StatementHandle,\n\t\t\t\t\tSQLINTEGER Attribute, SQLPOINTER ValuePtr,\n\t\t\t\t\tSQLINTEGER StringLength );\n\nstatic SQLALLOCHANDLE pSQLAllocHandle = NULL;\nstatic SQLBINDPARAMETER pSQLBindParameter = NULL;\nstatic SQLCLOSECURSOR pSQLCloseCursor = NULL;\nstatic SQLCONNECT pSQLConnect = NULL;\nstatic SQLDISCONNECT pSQLDisconnect = NULL;\nstatic SQLENDTRAN pSQLEndTran = NULL;\nstatic SQLEXECDIRECT pSQLExecDirect = NULL;\nstatic SQLEXECUTE pSQLExecute = NULL;\nstatic SQLFETCH pSQLFetch = NULL;\nstatic SQLFREEHANDLE pSQLFreeHandle = NULL;\nstatic SQLGETDATA pSQLGetData = NULL;\nstatic SQLGETDIAGREC pSQLGetDiagRec = NULL;\nstatic SQLGETINFO pSQLGetInfo = NULL;\nstatic SQLGETSTMTATTR pSQLGetStmtAttr = NULL;\nstatic SQLGETTYPEINFO pSQLGetTypeInfo = NULL;\nstatic SQLPREPARE pSQLPrepare = NULL;\nstatic SQLROWCOUNT_FN pSQLRowCount = NULL;\nstatic SQLSETCONNECTATTR pSQLSetConnectAttr = NULL;\nstatic SQLSETENVATTR pSQLSetEnvAttr = NULL;\nstatic SQLSETSTMTATTR pSQLSetStmtAttr = NULL;\n\n/* The use of dynamically bound function pointers vs. statically linked\n   functions requires a bit of sleight of hand since we can't give the\n   pointers the same names as prototyped functions.  To get around this we\n   redefine the actual function names to the names of the pointers */\n\n#define SQLAllocHandle\t\t\tpSQLAllocHandle\n#define SQLBindParameter\t\tpSQLBindParameter\n#define SQLCloseCursor\t\t\tpSQLCloseCursor\n#define SQLConnect\t\t\t\tpSQLConnect\n#define SQLDisconnect\t\t\tpSQLDisconnect\n#define SQLEndTran\t\t\t\tpSQLEndTran\n#define SQLExecDirect\t\t\tpSQLExecDirect\n#define SQLExecute\t\t\t\tpSQLExecute\n#define SQLFetch\t\t\t\tpSQLFetch\n#define SQLFreeHandle\t\t\tpSQLFreeHandle\n#define SQLGetData\t\t\t\tpSQLGetData\n#define SQLGetDiagRec\t\t\tpSQLGetDiagRec\n#define SQLGetInfo\t\t\t\tpSQLGetInfo\n#define SQLGetStmtAttr\t\t\tpSQLGetStmtAttr\n#define SQLGetTypeInfo\t\t\tpSQLGetTypeInfo\n#define SQLPrepare\t\t\t\tpSQLPrepare\n#define SQLRowCount\t\t\t\tpSQLRowCount\n#define SQLSetConnectAttr\t\tpSQLSetConnectAttr\n#define SQLSetEnvAttr\t\t\tpSQLSetEnvAttr\n#define SQLSetStmtAttr\t\t\tpSQLSetStmtAttr\n\n/* Depending on whether we're running under Win16, Win32, or Unix we load the\n   ODBC driver under a different name */\n\n#if defined( __WIN16__ )\n  #define ODBC_LIBNAME\t\t\t\"ODBC.DLL\"\n#elif defined( __WIN32__ )\n  #define ODBC_LIBNAME\t\t\t\"ODBC32.DLL\"\n#elif defined( __UNIX__ )\n  #if defined( __APPLE__ )\n\t/* OS X has built-in ODBC support via iODBC */\n\t#define ODBC_LIBNAME\t\t\"libiodbc.dylib\"\n  #else\n\t/* Currently we default to UnixODBC, which uses libodbc.so.  If this\n\t   fails, we fall back to the next-most-common one, iODBC.  If you're\n\t   using something else, you'll need to change the entry below to\n\t   specify your library name */\n\t#define ODBC_LIBNAME\t\t\"libodbc.so\"\n\t#define ODBC_ALT_LIBNAME\t\"libiodbc.so\"\n  #endif /* Mac OS X vs. other Unixen */\n#endif /* System-specific ODBC library names */\n\n/* Dynamically load and unload any necessary DBMS libraries */\n\nCHECK_RETVAL \\\nint dbxInitODBC( void )\n\t{\n#ifdef __WIN16__\n\tUINT errorMode;\n#endif /* __WIN16__ */\n\n\t/* If the ODBC module is already linked in, don't do anything */\n\tif( hODBC != NULL_INSTANCE )\n\t\treturn( CRYPT_OK );\n\n\t/* Obtain a handle to the module containing the ODBC functions */\n#if defined( __WIN16__ )\n\terrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );\n\thODBC = LoadLibrary( ODBC_LIBNAME );\n\tSetErrorMode( errorMode );\n\tif( hODBC < HINSTANCE_ERROR )\n\t\t{\n\t\thODBC = NULL_INSTANCE;\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n#elif defined( __UNIX__ ) && !defined( __APPLE__ )\n\tif( ( hODBC = DynamicLoad( ODBC_LIBNAME ) ) == NULL_INSTANCE && \\\n\t\t( hODBC = DynamicLoad( ODBC_ALT_LIBNAME ) ) == NULL_INSTANCE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't load ODBC driver '%s' or '%s'\",\n\t\t\t\t\t ODBC_LIBNAME, ODBC_ALT_LIBNAME ));\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n#else\n\tif( ( hODBC = DynamicLoad( ODBC_LIBNAME ) ) == NULL_INSTANCE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't load ODBC driver '%s'\", ODBC_LIBNAME ));\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n#endif /* __WIN32__ */\n\tDEBUG_DIAG(( \"Loaded ODBC driver '%s'\", ODBC_LIBNAME ));\n\n\t/* Now get pointers to the functions */\n\tpSQLAllocHandle = ( SQLALLOCHANDLE ) DynamicBind( hODBC, \"SQLAllocHandle\" );\n\tpSQLBindParameter = ( SQLBINDPARAMETER ) DynamicBind( hODBC, \"SQLBindParameter\" );\n\tpSQLCloseCursor = ( SQLCLOSECURSOR ) DynamicBind( hODBC, \"SQLCloseCursor\" );\n\tpSQLConnect = ( SQLCONNECT ) DynamicBind( hODBC, \"SQLConnect\" );\n\tpSQLDisconnect = ( SQLDISCONNECT ) DynamicBind( hODBC, \"SQLDisconnect\" );\n\tpSQLEndTran = ( SQLENDTRAN ) DynamicBind( hODBC, \"SQLEndTran\" );\n\tpSQLExecDirect = ( SQLEXECDIRECT ) DynamicBind( hODBC, \"SQLExecDirect\" );\n\tpSQLExecute = ( SQLEXECUTE ) DynamicBind( hODBC, \"SQLExecute\" );\n\tpSQLFetch = ( SQLFETCH ) DynamicBind( hODBC, \"SQLFetch\" );\n\tpSQLFreeHandle = ( SQLFREEHANDLE ) DynamicBind( hODBC, \"SQLFreeHandle\" );\n\tpSQLGetData = ( SQLGETDATA ) DynamicBind( hODBC, \"SQLGetData\" );\n\tpSQLGetDiagRec = ( SQLGETDIAGREC ) DynamicBind( hODBC, \"SQLGetDiagRec\" );\n\tpSQLGetInfo = ( SQLGETINFO ) DynamicBind( hODBC, \"SQLGetInfo\" );\n\tpSQLGetStmtAttr = ( SQLGETSTMTATTR ) DynamicBind( hODBC, \"SQLGetStmtAttr\" );\n\tpSQLGetTypeInfo = ( SQLGETTYPEINFO ) DynamicBind( hODBC, \"SQLGetTypeInfo\" );\n\tpSQLPrepare = ( SQLPREPARE ) DynamicBind( hODBC, \"SQLPrepare\" );\n\tpSQLRowCount = ( SQLROWCOUNT_FN ) DynamicBind( hODBC, \"SQLRowCount\" );\n\tpSQLSetConnectAttr = ( SQLSETCONNECTATTR ) DynamicBind( hODBC, \"SQLSetConnectAttr\" );\n\tpSQLSetEnvAttr = ( SQLSETENVATTR ) DynamicBind( hODBC, \"SQLSetEnvAttr\" );\n\tpSQLSetStmtAttr = ( SQLSETSTMTATTR ) DynamicBind( hODBC, \"SQLSetStmtAttr\" );\n\n\t/* Make sure that we got valid pointers for every ODBC function */\n\tif( pSQLAllocHandle == NULL || pSQLBindParameter == NULL ||\n\t\tpSQLCloseCursor == NULL || pSQLConnect == NULL ||\n\t\tpSQLDisconnect == NULL || pSQLEndTran == NULL ||\n\t\tpSQLExecDirect == NULL || pSQLExecute == NULL ||\n\t\tpSQLFetch == NULL || pSQLFreeHandle == NULL ||\n\t\tpSQLGetData == NULL || pSQLGetDiagRec == NULL ||\n\t\tpSQLGetInfo == NULL || pSQLGetStmtAttr == NULL ||\n\t\tpSQLGetTypeInfo == NULL || pSQLPrepare == NULL || \n\t\tpSQLSetConnectAttr == NULL || pSQLSetEnvAttr == NULL || \n\t\tpSQLSetStmtAttr == NULL )\n\t\t{\n\t\t/* Free the library reference and reset the handle */\n\t\tDynamicUnload( hODBC );\n\t\thODBC = NULL_INSTANCE;\n\t\tDEBUG_DIAG(( \"Couldn't bind to ODBC driver functions\" ));\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nvoid dbxEndODBC( void )\n\t{\n\tif( hODBC != NULL_INSTANCE )\n\t\tDynamicUnload( hODBC );\n\thODBC = NULL_INSTANCE;\n\t}\n#else\n\nCHECK_RETVAL \\\nint dbxInitODBC( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\n\nvoid dbxEndODBC( void )\n\t{\n\t}\n#endif /* DYNAMIC_LOAD */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get information on an ODBC error.  The statement handle is specified as a\n   distinct parameter because it may be an ephemeral handle not part of the\n   state information data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getErrorInfo( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_ENUM( SQL_ERRLVL ) const SQL_ERRLVL_TYPE errorLevel, \n\t\t\t\t\t\t const SQLHSTMT hStmt, \n\t\t\t\t\t\t IN_ERROR const int defaultStatus )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &dbmsInfo->errorInfo;\n#endif /* USE_ERRMSGS */\n\tSQLCHAR szSqlState[ SQL_SQLSTATE_SIZE + 8 ];\n\tSQLCHAR errorString[ MAX_ERRMSG_SIZE + 1 + 8 ];\n\tSQLHANDLE handle;\n\tSQLINTEGER dwNativeError = 0;\n\tSQLSMALLINT handleType, errorStringLength;\n\tSQLRETURN sqlStatus;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\t\n\tREQUIRES( errorLevel == SQL_ERRLVL_STMT || \\\n\t\t\t  errorLevel == SQL_ERRLVL_DBC || \\\n\t\t\t  errorLevel == SQL_ERRLVL_ENV );\n\tREQUIRES( ( errorLevel == SQL_ERRLVL_STMT && \\\n\t\t\t\thStmt != SQL_NULL_HSTMT ) || \\\n\t\t\t  ( errorLevel != SQL_ERRLVL_STMT && \\\n\t\t\t\thStmt == SQL_NULL_HSTMT ) );\n\tREQUIRES( cryptStatusError( defaultStatus ) );\n\n\t/* Set up the handle information for the diagnostic information that we \n\t   want to retrieve */\n\tswitch( errorLevel )\n\t\t{\n\t\tcase SQL_ERRLVL_STMT:\n\t\t\thandleType = SQL_HANDLE_STMT;\n\t\t\thandle = hStmt;\n\t\t\tbreak;\n\n\t\tcase SQL_ERRLVL_DBC:\n\t\t\thandleType = SQL_HANDLE_DBC;\n\t\t\thandle = dbmsInfo->hDbc;\n\t\t\tbreak;\n\n\t\tcase SQL_ERRLVL_ENV:\n\t\t\thandleType = SQL_HANDLE_ENV;\n\t\t\thandle = dbmsInfo->hEnv;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Get the ODBC error information at the most detailed level that we can \n\t   manage */\n\tsqlStatus = SQLGetDiagRec( handleType, handle, 1, szSqlState,\n\t\t\t\t\t\t\t   &dwNativeError, errorString, MAX_ERRMSG_SIZE, \n\t\t\t\t\t\t\t   &errorStringLength );\n\tif( !sqlStatusOK( sqlStatus ) && errorLevel == SQL_ERRLVL_STMT )\n\t\t{\n\t\t/* If we couldn't get information at the statement-handle level, try \n\t\t   again at the connection handle level */\n\t\tsqlStatus = SQLGetDiagRec( SQL_HANDLE_DBC, dbmsInfo->hDbc, 1,\n\t\t\t\t\t\t\t\t   szSqlState, &dwNativeError,\n\t\t\t\t\t\t\t\t   errorString, MAX_ERRMSG_SIZE, \n\t\t\t\t\t\t\t\t   &errorStringLength );\n\t\t}\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't read error information from database \"\n\t\t\t\t\t \"backend\" ));\n\t\tassert( DEBUG_WARN );\t/* Catch this if it ever occurs */\n\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t( CRYPT_ERROR_READ, errorInfo, \n\t\t\t\t  \"Couldn't get error information from database \"\n\t\t\t\t  \"backend\" ) );\n\t\t}\n\n\t/* In some (rare) cases SQLGetDiagRec() can return an empty error string\n\t   with only szSqlState set, in which case we clear the error string */\n\tif( errorStringLength > 0 )\n\t\t{\n\t\t/* Since the error string has come from the database source we \n\t\t   sanitise it before returning it to the caller.  The +1 is for\n\t\t   the '\\0' that sanitiseString() adds to the string */\n\t\tsanitiseString( errorString, errorStringLength + 1, \n\t\t\t\t\t\terrorStringLength );\n\t\tsetErrorString( errorInfo, errorString, errorStringLength );\n\t\t}\n\telse\n\t\tclearErrorString( errorInfo );\n\n\t/* Check for a not-found error status.  We can also get an sqlStatus of\n\t   SQL_NO_DATA with SQLSTATE set to \"00000\" and the error message string\n\t   empty in some cases, in which case we provide our own error string */\n\tif( !memcmp( szSqlState, \"S0002\", 5 ) ||\t/* ODBC 2.x */\n\t\t!memcmp( szSqlState, \"42S02\", 5 ) ||\t/* ODBC 3.x */\n\t\t( !memcmp( szSqlState, \"00000\", 5 ) && \\\n\t\t  sqlStatus == SQL_NO_DATA ) )\n\t\t{\n\t\t/* Make sure that the caller gets a sensible error message if they\n\t\t   try to examine the extended error information */\n\t\tif( errorStringLength <= 0 )\n\t\t\tsetErrorString( errorInfo, \"No data found\", 13 );\n\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* When we're trying to create a new keyset, there may already be one\n\t   present giving an S0001/42S01 (table already exists) or S0011/42S11 \n\t   (index already exists) error .  We could check for the table by doing \n\t   a dummy read, but it's easier to just try the update anyway and \n\t   convert the error code to the correct value here if there's a \n\t   problem */\n\tif( !memcmp( szSqlState, \"S0001\", 5 ) ||\n\t\t!memcmp( szSqlState, \"S0011\", 5 ) ||\t/* ODBC 2.x */\n\t\t!memcmp( szSqlState, \"42S01\", 5 ) ||\n\t\t!memcmp( szSqlState, \"42S11\", 5 ) )\t\t/* ODBX 3.x */\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t/* This one is a bit odd: An integrity constraint violation occurred,\n\t   which means (among other things) that an attempt was made to write a\n\t   duplicate value to a column constrained to contain unique values.  It\n\t   can also include things like writing a NULL value to a column\n\t   constrained to be NOT NULL, but this wouldn't normally happen so we\n\t   can convert this one to a duplicate data error */\n\tif( !memcmp( szSqlState, \"23000\", 5 ) )\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t/* SQLite returns almost all errors as a generic HY000 with an \n\t   accompanying text message describing the problem (dwNativeError is no\n\t   more useful, it's almost always 1 = SQLITE_ERROR), so we have to pick\n\t   apart the text message to see what we need to return.  This is a \n\t   really horrible, brittle way to do things, but there's no other way\n\t   to get a more specific error code */\n\tif( dbmsInfo->backendType == DBMS_SQLITE && \\\n\t\t!memcmp( szSqlState, \"HY000\", 5 ) )\n\t\t{\n\t\tif( strFindStr( errorString, errorStringLength, \n\t\t\t\t\t\t\"already exists\", 14 ) >= 0 )\n\t\t\t{\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\tif( strFindStr( errorString, errorStringLength,\n\t\t\t\t\t\t\"UNIQUE constraint\", 17 ) >= 0 )\n\t\t\t{\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t}\n\t\tif( strFindStr( errorString, errorStringLength,\n\t\t\t\t\t\t\"no such\", 7 ) >= 0 )\n\t\t\t{\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\tsqlStatus = 0;\n\t\t}\n\n\treturn( defaultStatus );\n\t}\n\n/* Dump debugging information on an ODBC error to the error log.  This is \n   used to record oddball errors during debugging that don't necessarily\n   affect overall operation but that should be fixed anyway */\n\n#if !defined( NDEBUG ) && defined( DEBUG_DIAGNOSTIC_ENABLE )\n\n#define DUMP_ODBCERROR\tdebugDiagOdbcError\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid debugDiagOdbcError( IN_STRING const char *functionName,\n\t\t\t\t\t\t INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_ENUM( SQL_ERRLVL ) const SQL_ERRLVL_TYPE errorLevel, \n\t\t\t\t\t\t const SQLHSTMT hStmt )\n\t{\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( isReadPtr( functionName, 8 ) );\n\tassert( errorLevel == SQL_ERRLVL_STMT || \\\n\t\t\terrorLevel == SQL_ERRLVL_DBC || \\\n\t\t\terrorLevel == SQL_ERRLVL_ENV );\n\tassert( ( errorLevel == SQL_ERRLVL_STMT && \\\n\t\t\thStmt != SQL_NULL_HSTMT ) || \\\n\t\t  ( errorLevel != SQL_ERRLVL_STMT && \\\n\t\t\thStmt == SQL_NULL_HSTMT ) );\n\n\t( void ) getErrorInfo( dbmsInfo, errorLevel, hStmt, \n\t\t\t\t\t\t   CRYPT_ERROR_INTERNAL );\n\tDEBUG_DIAG_ERRMSG(( \"%s reports:\\n  '%s'.\", functionName,\n\t\t\t\t\t\tgetErrorInfoString( &dbmsInfo->errorInfo ) ));\n\t}\n#else\n  #define DUMP_ODBCERROR( dbmsInfo, functionName, errorLevel, hStmt );\n#endif /* !NDEBUG */\n\n/* Rewrite the SQL query to handle the back-end specific blob and date type, \n   and to work around problems with some back-end types (and we're \n   specifically talking Access here) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nstatic int rewriteString( INOUT_BUFFER( stringMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t*stringLength ) char *string, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int stringMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \\\n\t\t\t\t\t\t\t\tint *stringLength, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int subStringLength, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int origStringLength, \n\t\t\t\t\t\t  IN_BUFFER( newSubStringLength ) \\\n\t\t\t\t\t\t\t\tconst char *newSubString, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int newSubStringLength )\n\t{\n\tconst int remainder = origStringLength - subStringLength;\n\tconst int newStringLength = newSubStringLength + remainder;\n\n\tassert( isWritePtrDynamic( string, stringMaxLength ) );\n\tassert( isReadPtrDynamic( newSubString, newSubStringLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( stringMaxLength ) );\n\tREQUIRES( subStringLength > 0 && \\\n\t\t\t  subStringLength < origStringLength && \\\n\t\t\t  subStringLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( origStringLength > 0 && \\\n\t\t\t  origStringLength <= stringMaxLength && \\\n\t\t\t  origStringLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( newSubStringLength ) );\n\n\t/* Clear return value */\n\t*stringLength = 0;\n\n\t/* Make sure that the parameters are in order and there's room to \n\t   rewrite the string */\n\tENSURES( remainder > 0 && newStringLength > 0 && \\\n\t\t\t newStringLength < stringMaxLength );\n\n\t/* Open/close up a gap and replace the existing substring with the new \n\t   one:\n\n\t\t\t\t\t\t\t\t\torigStringLength\n\t\t|<----------- string -------------->|\n\t\t+---------------+-------------------+-----------+\n\t\t|///////////////|...................|\t\t\t|\n\t\t+---------------+-------------------+-----------+\n\t\t|<- subString ->|\t\t\t\t\t\t\t\t|\n\t\t\t\t\t\t\t\t\t\t\t\tstringMaxLength */\n\tREQUIRES( boundsCheck( newSubStringLength, remainder, \n\t\t\t\t\t\t   stringMaxLength ) );\n\tmemmove( string + newSubStringLength, string + subStringLength, \n\t\t\t remainder );\n\tmemcpy( string, newSubString, newSubStringLength );\n\t*stringLength = newSubStringLength - subStringLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int convertQuery( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t OUT_BUFFER( queryMaxLen, *queryLength ) char *query,\n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) const int queryMaxLen, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( queryMaxLen ) \\\n\t\t\t\t\t\t\t\tint *queryLength,\n\t\t\t\t\t\t IN_BUFFER( commandLength ) const char *command,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int commandLength )\n\t{\n\tint currentLength = commandLength;\n\tint offset, length, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( isWritePtrDynamic( query, queryMaxLen ) );\n\tassert( isReadPtrDynamic( command, commandLength ) );\n\t\n\tREQUIRES( queryMaxLen >= 16 && queryMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( commandLength > 0 && commandLength < queryMaxLen && \\\n\t\t\t  commandLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\t*queryLength = 0;\n\n\t/* Copy the SQL command across to the query buffer */\n\tREQUIRES( rangeCheck( commandLength, 1, queryMaxLen ) );\n\tmemcpy( query, command, commandLength );\n\n\t/* If it's a CREATE TABLE command rewrite the blob and date types to the \n\t   appropriate values for the database back-end */\n\tif( !strCompare( command, \"CREATE TABLE\", 12 ) )\n\t\t{\n\t\toffset = strFindStr( query, currentLength, \" BLOB\", 5 );\n\t\tif( offset > 0 )\n\t\t\t{\n\t\t\toffset++;\t/* Skip space before blob name */\n\n\t\t\tstatus = rewriteString( query + offset, queryMaxLen - offset, \n\t\t\t\t\t\t\t\t\t&length, 4, currentLength - offset, \n\t\t\t\t\t\t\t\t\tdbmsInfo->blobName, \n\t\t\t\t\t\t\t\t\tdbmsInfo->blobNameLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcurrentLength += length;\n\t\t\t}\n\t\toffset = strFindStr( query, currentLength, \" DATETIME\", 9 );\n\t\tif( offset > 0 && \\\n\t\t\t!( dbmsInfo->dateTimeNameLength == 8 && \\\n\t\t\t   !strCompare( dbmsInfo->dateTimeName, \"DATETIME\", 8 ) ) )\n\t\t\t{\n\t\t\toffset++;\t/* Skip space before date/time name */\n\t\t\tstatus = rewriteString( query + offset, queryMaxLen - offset, \n\t\t\t\t\t\t\t\t\t&length, 8, currentLength - offset, \n\t\t\t\t\t\t\t\t\tdbmsInfo->dateTimeName, \n\t\t\t\t\t\t\t\t\tdbmsInfo->dateTimeNameLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcurrentLength += length;\n\t\t\t}\n\t\t}\n\n\t/* If it's not one of the back-ends that require special-case handling,  \n\t   we're done */\n\tswitch( dbmsInfo->backendType )\n\t\t{\n\t\tcase DBMS_ACCESS:\n\t\t\t/* If it's not a SELECT/DELETE with wildcards used, there's \n\t\t\t   nothing to do */\n\t\t\tif( ( strCompare( query, \"SELECT\", 6 ) && \\\n\t\t\t\t  strCompare( query, \"DELETE\", 6 ) ) || \\\n\t\t\t\t  strFindStr( query, currentLength, \" LIKE \", 6 ) <= 7 )\n\t\t\t\t{\n\t\t\t\t*queryLength = currentLength;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase DBMS_INTERBASE:\n\t\t\t/* If it's not a CREATE TABLE/INSERT/DELETE/SELECT with the \n\t\t\t   'type' column involved, there's nothing to do */\n\t\t\tif( strCompare( query, \"CREATE TABLE\", 12 ) && \\\n\t\t\t\tstrCompare( query, \"SELECT\", 6 ) && \\\n\t\t\t\tstrCompare( query, \"DELETE\", 6 ) && \\\n\t\t\t\tstrCompare( query, \"INSERT\", 6 ) )\n\t\t\t\t{\n\t\t\t\t*queryLength = currentLength;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tif( strFindStr( query, currentLength, \" type \", 6 ) <= 7 )\n\t\t\t\t{\n\t\t\t\t*queryLength = currentLength;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* Currently no other back-ends need special handling */\n\t\t\t*queryLength = currentLength;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Unlike everything else in the known universe Access uses * and ?\n\t   instead of the standard SQL wildcards so if we find a LIKE ... %\n\t   we rewrite the % as a * */\n\tif( ( dbmsInfo->backendType == DBMS_ACCESS ) && \\\n\t\t( offset = strFindStr( query, currentLength, \" LIKE \", 6 ) ) > 0 )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Search up to 6 characters ahead for a wildcard and replace it\n\t\t   with the one needed by Access if we find it.  We search 6 chars\n\t\t   ahead because the higher-level SQL code uses expressions like\n\t\t   \"SELECT .... WHERE foo LIKE '--%'\", which is 5 chars plus one as\n\t\t   a safety margin */\n\t\tLOOP_LARGE( i = offset + 7, i < offset + 11 && i < currentLength, \n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( query[ i ] == '%' )\n\t\t\t\tquery[ i ] = '*';\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Interbase treats TYPE as a reserved word so we can't use 'type' for a\n\t   column name */\n\tif( ( dbmsInfo->backendType == DBMS_INTERBASE ) && \\\n\t\t( offset = strFindStr( query, currentLength, \" type \", 6 ) ) > 0 )\n\t\t{\n\t\toffset++;\t/* Skip space before type name */\n\t\tstatus = rewriteString( query + offset, queryMaxLen - offset, \n\t\t\t\t\t\t\t\t&length, 4, currentLength - offset, \n\t\t\t\t\t\t\t\t\"ctype\", 5 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcurrentLength += length;\n\t\t}\n\n\t*queryLength = currentLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Bind parameters for a query/update.  The caller has to supply the bound\n   data storage since it still has to exist later on when the query is\n   executed */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nstatic int bindParameters( const SQLHSTMT hStmt, \n\t\t\t\t\t\t   IN_ARRAY_C( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\tconst BOUND_DATA *boundData,\n\t\t\t\t\t\t   OUT BOUND_DATA_STATE *boundDataState,\n\t\t\t\t\t\t   INOUT DBMS_STATE_INFO *dbmsInfo )\n\t{\n\tSQLUSMALLINT paramNo = 1;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( boundData, \\\n\t\t\t\t\t   sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS ) );\n\tassert( isWritePtr( boundDataState, sizeof( BOUND_DATA_STATE ) ) );\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\tmemset( boundDataState, 0, sizeof( BOUND_DATA_STATE ) );\n\n\t/* Bind in any necessary parameters to the hStmt */\n\tLOOP_EXT( i = 0, boundData[ i ].type != BOUND_DATA_NONE, i++,\n\t\t\t  BOUND_DATA_MAXITEMS + 1 )\n\t\t{\n\t\tconst BOUND_DATA *boundDataPtr = &boundData[ i ];\n\t\tSQLSMALLINT valueType, parameterType;\n\t\tSQLRETURN sqlStatus;\n\n\t\tif( boundDataPtr->type == BOUND_DATA_TIME )\n\t\t\t{\n\t\t\tSQL_TIMESTAMP_STRUCT *timestampStorage = \\\n\t\t\t\t\t\t\t\t &boundDataState->timestampStorage;\n\t\t\tstruct tm timeInfo, *timeInfoPtr = &timeInfo;\n\t\t\n\t\t\tREQUIRES( boundDataPtr->dataLength == sizeof( time_t ) );\n\n\t\t\t/* Sanity check the input parameters */\n\t\t\ttimeInfoPtr = gmTime_s( boundDataPtr->data, timeInfoPtr );\n\t\t\tif( timeInfoPtr == NULL )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t\t/* Bind in the date.  The handling of the ColumnSize parameter \n\t\t\t   is ugly, this value should be implicit in the underlying data \n\t\t\t   type but a small number of back-ends (e.g. ones derived from \n\t\t\t   the Sybase 4.2 code line, which includes the current Sybase \n\t\t\t   and SQL Server) may support multiple time representations and \n\t\t\t   require an explicit length indicator to decide which one they \n\t\t\t   should use.  This means that we have to provide an explicit \n\t\t\t   length value as a hint to the driver, see the comment in \n\t\t\t   getDatatypeInfo() for how this is obtained */\n\t\t\tmemset( timestampStorage, 0, sizeof( SQL_TIMESTAMP_STRUCT ) );\n\t\t\ttimestampStorage->year = ( SQLSMALLINT ) ( timeInfoPtr->tm_year + 1900 );\n\t\t\ttimestampStorage->month = ( SQLUSMALLINT ) ( timeInfoPtr->tm_mon + 1 );\n\t\t\ttimestampStorage->day = ( SQLUSMALLINT ) timeInfoPtr->tm_mday;\n\t\t\ttimestampStorage->hour = ( SQLUSMALLINT ) timeInfoPtr->tm_hour;\n\t\t\ttimestampStorage->minute = ( SQLUSMALLINT ) timeInfoPtr->tm_min;\n\t\t\ttimestampStorage->second = ( SQLUSMALLINT ) timeInfoPtr->tm_sec;\n\t\t\tsqlStatus = SQLBindParameter( hStmt, paramNo++, SQL_PARAM_INPUT,\n\t\t\t\t\t\t\t\t\t\t  SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP,\n\t\t\t\t\t\t\t\t\t\t  dbmsInfo->dateTimeNameColSize, 0,\n\t\t\t\t\t\t\t\t\t\t  timestampStorage, 0, NULL );\n\t\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tassert( ( boundDataPtr->dataLength == 0 ) || \\\n\t\t\t\tisReadPtrDynamic( boundDataPtr->data, \\\n\t\t\t\t\t\t\t\t  boundDataPtr->dataLength ) );\n\n\t\tREQUIRES( boundDataPtr->type == BOUND_DATA_STRING || \\\n\t\t\t\t  boundDataPtr->type == BOUND_DATA_BLOB );\n\t\tREQUIRES( dbmsInfo->hasBinaryBlobs || \\\n\t\t\t\t  boundDataPtr->type == BOUND_DATA_STRING );\n\t\tREQUIRES( ( boundDataPtr->data == NULL && \\\n\t\t\t\t\tboundDataPtr->dataLength == 0 ) || \\\n\t\t\t\t  ( boundDataPtr->data != NULL && \\\n\t\t\t\t\tisShortIntegerRangeNZ( boundDataPtr->dataLength ) ) );\n\t\t\t\t  /* Bound data of { NULL, 0 } denotes a null parameter */\n\n\t\t/* Null parameters have to be handled specially.  Note that we have \n\t\t   to set the ColumnSize parameter (no.6) to a nonzero value (even \n\t\t   though it's ignored, since this is a null parameter) otherwise \n\t\t   some drivers will complain about an \"Invalid precision value\" */\n\t\tif( boundDataPtr->dataLength <= 0 )\n\t\t\t{\n\t\t\tstatic const SQLLEN nullDataValue = SQL_NULL_DATA;\n\n\t\t\tsqlStatus = SQLBindParameter( hStmt, paramNo++, SQL_PARAM_INPUT,\n\t\t\t\t\t\t\t\t\t\t  SQL_C_CHAR, SQL_C_CHAR, 1, 0, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t  ( SQLLEN * ) &nullDataValue );\n\t\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Bind in the query data */\n\t\tif( boundDataPtr->type == BOUND_DATA_BLOB )\n\t\t\t{\n\t\t\tvalueType = SQL_C_BINARY;\n\t\t\tparameterType = dbmsInfo->blobType;\n\t\t\t}\n\t\telse\n\t\t\tvalueType = parameterType = SQL_C_CHAR;\n\t\tboundDataState->lengthStorage[ i ] = boundDataPtr->dataLength;\n\t\tsqlStatus = SQLBindParameter( hStmt, paramNo++, SQL_PARAM_INPUT,\n\t\t\t\t\t\t\t\t\t  valueType, parameterType,\n\t\t\t\t\t\t\t\t\t  boundDataPtr->dataLength, 0,\n\t\t\t\t\t\t\t\t\t  ( SQLPOINTER ) boundDataPtr->data, \n\t\t\t\t\t\t\t\t\t  boundDataPtr->dataLength, \n\t\t\t\t\t\t\t\t\t  &boundDataState->lengthStorage[ i ] );\n\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t{\n\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t  CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Get Database Back-end Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get data type information for this data source.  Since SQLGetTypeInfo() \n   returns a variable (and arbitrary) length result set we have to call\n   SQLCloseCursor() after each fetch before performing a new query */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int getBlobInfo( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\tconst SQLSMALLINT type,\n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *maxFieldSize )\n\t{\n\tconst SQLHSTMT hStmt = dbmsInfo->hStmt[ DBMS_CACHEDQUERY_NONE ];\n\tSQLRETURN sqlStatus;\n\tSQLINTEGER count;\n\tSQLLEN blobNameLength, dummy;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\t/* Clear return value */\n\t*maxFieldSize = 0;\n\n\t/* Check for support for the requested type and get the results of the \n\t   transaction.  If the database doesn't support this we'll get an \n\t   SQL_NO_DATA status */\n\tsqlStatus = SQLGetTypeInfo( hStmt, type );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\treturn( CRYPT_ERROR );\n\tsqlStatus = SQLFetch( hStmt );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tSQLCloseCursor( hStmt );\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\n\t/* Get the type name (result column 1) and column size (= maximum\n\t   possible field length, result column 3).  We only check the second\n\t   return code since they both apply to the same row */\n\tSQLGetData( hStmt, 1, SQL_C_CHAR, dbmsInfo->blobName,\n\t\t\t\tCRYPT_MAX_TEXTSIZE, &blobNameLength );\n\tsqlStatus = SQLGetData( hStmt, 3, SQL_C_SLONG, &count,\n\t\t\t\t\t\t\tsizeof( SQLINTEGER ), &dummy );\n\tSQLCloseCursor( hStmt );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\treturn( CRYPT_ERROR );\n\tif( dbmsInfo->backendType == DBMS_MYSQL && blobNameLength == 0 )\n\t\t{\n\t\t/* Some older versions of the MySQL ODBC driver don't return a \n\t\t   length value so we have to set it ourselves by taking the length \n\t\t   of the returned string.  The null-termination occurs as a side-\n\t\t   effect of the buffer being initialised to zeroes */\n\t\tblobNameLength = strlen( dbmsInfo->blobName );\n\t\t}\n\tREQUIRES( isIntegerRange( blobNameLength ) );\n\tdbmsInfo->blobNameLength = ( int ) blobNameLength;\n#ifdef __UNIX__\n\tif( dummy != sizeof( SQLLEN ) )\n\t\t{\n\t\tfprintf( stderr, \"\\ncryptlib: The ODBC driver is erroneously \"\n\t\t\t\t \"returning a %ld-byte integer value\\n          when a \"\n\t\t\t\t \"%d-byte SQLINTEGER value is requested, which will \"\n\t\t\t\t \"overwrite\\n          adjacent memory locations.  To fix \"\n\t\t\t\t \"this you need to recompile\\n          with whatever \"\n\t\t\t\t \"preprocessor options your ODBC header files require\\n\"\n\t\t\t\t \"          to force the use of 64-bit ODBC data types (and \"\n\t\t\t\t \"report this issue\\n          to the ODBC driver vendor so \"\n\t\t\t\t \"that they can sync the driver and\\n          headers).\"\n\t\t\t\t \"\\n\\n\", ( long ) dummy, ( int ) sizeof( SQLLEN ) );\n\t\t\t\t /* Cast is nec. because sizeof() can be 32 or 64 bits */\n\t\t}\n#endif /* __UNIX__ */\n\t*maxFieldSize = count;\n\n\t/* We've got the type information, remember the details.  Postgres has \n\t   problems handling blobs via ODBC (or even in general) since it uses \n\t   its own BYTEA (byte array) type that's not really usable as an SQL \n\t   blob type because of weird escaping requirements when \n\t   sending/receiving data.  In addition it requires other Postgres-\n\t   specific oddities like specifying 'ByteaAsLongVarBinary=1' in the \n\t   connect string.  So even though the back-end sort-of supports blobs \n\t   we can't actually use them */\n\tif( ( type == SQL_LONGVARBINARY ) && \\\n\t\t( dbmsInfo->backendType != DBMS_POSTGRES ) )\n\t\tdbmsInfo->hasBinaryBlobs = TRUE;\n\tdbmsInfo->blobType = type;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getDateTimeInfo( INOUT DBMS_STATE_INFO *dbmsInfo )\n\t{\n\tconst SQLHSTMT hStmt = dbmsInfo->hStmt[ DBMS_CACHEDQUERY_NONE ];\n\tSQLRETURN sqlStatus;\n\tSQLLEN dateTimeNameLength, columnSize, dummy;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\t/* The Postgres driver doesn't correctly detect the date/time type used\n\t   by the back-end so we have to hard-code in the actual value */\n\tif( dbmsInfo->backendType == DBMS_POSTGRES )\n\t\t{\n\t\tmemcpy( dbmsInfo->dateTimeName, \"TIMESTAMP\", 9 );\n\t\tdbmsInfo->dateTimeNameLength = 9;\n\t\tdbmsInfo->dateTimeNameColSize = 16;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get information on the back-end's date+time data type  This changed \n\t   from SQL_TIMESTAMP in ODBC 2.x to SQL_TYPE_TIMESTAMP in ODBC 3.x, \n\t   since 3.x is more common we try the 3.x version first and if that \n\t   fails fall back to the 2.x form */\n\tsqlStatus = SQLGetTypeInfo( hStmt, SQL_TYPE_TIMESTAMP );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Database backend uses pre-ODBC 3.0 data types\" ));\n\t\tassert( DEBUG_WARN );\t/* Warn of absence of ODBC 3.0 types */\n\t\tsqlStatus = SQLGetTypeInfo( hStmt, SQL_TIMESTAMP );\n\t\t}\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\treturn( CRYPT_ERROR );\n\n\t/* Fetch the results of the transaction and get the type name (result \n\t   column 1) and column size (result column 3) */\n\tsqlStatus = SQLFetch( hStmt );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tSQLCloseCursor( hStmt );\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\tsqlStatus = SQLGetData( hStmt, 1, SQL_C_CHAR, dbmsInfo->dateTimeName,\n\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, &dateTimeNameLength );\n\tif( sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tsqlStatus = SQLGetData( hStmt, 3, SQL_C_SLONG,\n\t\t\t\t\t\t\t\t&dbmsInfo->dateTimeNameColSize,\n\t\t\t\t\t\t\t\tsizeof( SQLINTEGER ), &dummy );\n\t\t}\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tSQLCloseCursor( hStmt );\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\tif( dbmsInfo->backendType == DBMS_MYSQL && dateTimeNameLength == 0 )\n\t\t{\n\t\t/* Some older versions of the MySQL ODBC driver don't return a \n\t\t   length value so we have to set it ourselves by taking the length \n\t\t   of the returned string.  The null-termination occurs as a side-\n\t\t   effect of the buffer being initialised to zeroes */\n\t\tdateTimeNameLength = strlen( dbmsInfo->dateTimeName );\n\t\t}\n\tREQUIRES( isIntegerRange( dateTimeNameLength ) );\n\tdbmsInfo->dateTimeNameLength = ( int ) dateTimeNameLength;\n\n\t/* The column size argument is quite problematic because although some \n\t   back-ends have a fixed size for this (and usually ignore the column-\n\t   size parameter) others allow multiple time representations and \n\t   require an explicit column-size indicator to decide which one they \n\t   should use.  The ODBC standard representation for example uses 19 \n\t   chars (yyyy-mm-dd hh:mm:ss) for the full date+time that we use here \n\t   but also allows a 16-char version without the seconds and a 20+n-char \n\t   version for n digits of fractional seconds.  The back-end however may \n\t   use a completely different value, for example Oracle encodes the full \n\t   date+time as 7 bytes (century, year, month, day, hour, minute, \n\t   second).  To get around this we get the first column-size value \n\t   (which is usually the only one available) and if this is the same as \n\t   the ODBC standard minimum-size column we try for more results to see \n\t   if the full date+time form is available, and use that if it is */\n\tif( dbmsInfo->dateTimeNameColSize != 16 )\n\t\t{\n\t\t/* This isn't a potentially problematic column size, we're done */\n\t\tSQLCloseCursor( hStmt );\n\t\treturn( CRYPT_OK );\n\t\t}\n\t\t\n\t/* If the back-end has reported the short (no-seconds) ODBC-default \n\t   format, see whether it'll support the longer (with seconds) format \n\t   instead */\n\tsqlStatus = SQLFetch( hStmt );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tSQLCloseCursor( hStmt );\n\t\treturn( CRYPT_ERROR );\n\t\t}\n\tsqlStatus = SQLGetData( hStmt, 3, SQL_C_SLONG, &columnSize, \n\t\t\t\t\t\t\tsizeof( SQLINTEGER ), &dummy );\n\tif( sqlStatusOK( sqlStatus ) && columnSize == 19 )\n\t\tdbmsInfo->dateTimeNameColSize = columnSize;\n\tSQLCloseCursor( hStmt );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getDatatypeInfo( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t\tOUT_FLAGS_Z( DBMS ) int *featureFlags )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &dbmsInfo->errorInfo;\n#endif /* USE_ERRMSGS */\n\tconst SQLHSTMT hStmt = dbmsInfo->hStmt[ DBMS_CACHEDQUERY_NONE ];\n\tSQLRETURN sqlStatus;\n\tSQLSMALLINT bufLen;\n\tSQLUSMALLINT transactBehaviour;\n\tSQLLEN attrLength;\n\tSQLUINTEGER privileges;\n\tchar buffer[ 8 + 8 ];\n\tint maxBlobSize, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( isWritePtr( featureFlags, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*featureFlags = DBMS_FEATURE_FLAG_NONE;\n\n\t/* First we see what the back-end's blob data type is.  Usually it'll\n\t   be binary blobs, if that doesn't work we try for char blobs */\n\tstatus = getBlobInfo( dbmsInfo, SQL_LONGVARBINARY, &maxBlobSize );\n\tif( cryptStatusError( status ) )\n\t\tstatus = getBlobInfo( dbmsInfo, SQL_LONGVARCHAR, &maxBlobSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t  CRYPT_ERROR_OPEN ) );\n\t\t}\n\tif( dbmsInfo->hasBinaryBlobs )\n\t\t*featureFlags |= DBMS_FEATURE_FLAG_BINARYBLOBS;\n\n\t/* If we couldn't get a blob type or the type is too short to use,\n\t   report it back as a database open failure */\n\tif( maxBlobSize < MAX_ENCODED_CERT_SIZE )\n\t\t{\n\t\tchar errorMessage[ 128 + 8 ];\n\t\tint errorMessageLength;\n\n\t\terrorMessageLength = \\\n\t\t\tsprintf_s( errorMessage, 128,\n\t\t\t\t\t   \"Database blob type can only store %d bytes, we need \"\n\t\t\t\t\t   \"at least %d\", maxBlobSize, MAX_ENCODED_CERT_SIZE );\n\t\tsetErrorString( errorInfo, errorMessage, errorMessageLength );\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\t/* Sanity check, make sure that the source can return the required\n\t   amount of data.  A number of data sources don't support this\n\t   attribute (it's mostly meant to be set by applications rather than\n\t   being read, and is intended to be used to reduce network traffic) and\n\t   in addition the maximum query size is pretty short (the longest is a \n\t   few hundred bytes for the table creation commands) so we don't worry \n\t   if it's not available.  In addition to the maximum-size check we also \n\t   have to perform a minimum-size check since a value of zero is used to \n\t   indicate no length limit */\n\tsqlStatus = SQLGetStmtAttr( hStmt, SQL_ATTR_MAX_LENGTH,\n\t\t\t\t\t\t\t\t( SQLPOINTER ) &attrLength, SQL_IS_INTEGER,\n\t\t\t\t\t\t\t\tNULL );\n\tif( sqlStatusOK( sqlStatus ) && \\\n\t\tattrLength > 0 && attrLength < MAX_SQL_QUERY_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t( CRYPT_ERROR_OPEN, errorInfo,\n\t\t\t\t  \"Database back-end can only transmit %d bytes per \"\n\t\t\t\t  \"message, we need at least %d\", ( int ) attrLength, \n\t\t\t\t  MAX_SQL_QUERY_SIZE ) );\n\t\t}\n\n\t/* Now do the same thing for the date+time data type */\n\tstatus = getDateTimeInfo( dbmsInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t  CRYPT_ERROR_OPEN ) );\n\t\t}\n\n\t/* Determine whether we can write to the database (result = 'Y') or not\n\t   (result = 'N') */\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_DATA_SOURCE_READ_ONLY,\n\t\t\t\t\t\t\tbuffer, 8, &bufLen );\n\tif( sqlStatusOK( sqlStatus ) && *buffer == 'Y' )\n\t\t*featureFlags |= DBMS_FEATURE_FLAG_READONLY;\n\n\t/* Determine whether GRANT/REVOKE capabilities are available.  This gets\n\t   a bit messy because it only specifies which extended GRANT/REVOKE\n\t   options are available rather than whether GRANT/REVOKE is available\n\t   at all.  To handle this we treat GRANT/REVOKE as being available if\n\t   any information is returned (SQL Server typically returns only\n\t   SQL_SG_WITH_GRANT_OPTION while other sources like DB2, Postgres, and\n\t   Sybase return the correct set of flags) and not available if nothing\n\t   is returned (Access, dBASE, Paradox, etc).  To make things especially\n\t   challenging, Informix returns nothing for SQL_SQL92_GRANT but does\n\t   return something for SQL_SQL92_REVOKE so we have to check both options \n\t   and allow GRANT/REVOKE if either test positive */\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_SQL92_GRANT,\n\t\t\t\t\t\t\t( SQLPOINTER ) &privileges,\n\t\t\t\t\t\t\tsizeof( SQLUINTEGER ), &bufLen );\n\tif( sqlStatusOK( sqlStatus ) && privileges )\n\t\t*featureFlags |= DBMS_FEATURE_FLAG_PRIVILEGES;\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_SQL92_REVOKE,\n\t\t\t\t\t\t\t( SQLPOINTER ) &privileges,\n\t\t\t\t\t\t\tsizeof( SQLUINTEGER ), &bufLen );\n\tif( sqlStatusOK( sqlStatus ) && privileges )\n\t\t*featureFlags |= DBMS_FEATURE_FLAG_PRIVILEGES;\n\n\t/* Check how the back-end reacts to commit/rollback operations.  If\n\t   transactions are destructive (that is, prepared statements are\n\t   cleared when a commit/rollback is performed) we have to clear the\n\t   hStmtPrepared[] array to indicate that all statements have to be\n\t   re-prepared.  Fortunately this is quite rare, both because most\n\t   back-ends don't do this (for virtually all ODBC-accessible data\n\t   sources (SQL Server, Access, dBASE, Paradox, etc etc) the behaviour\n\t   is SQL_CB_CLOSE, meaning that the currently active cursor is closed\n\t   but there's no need to call SQLPrepare() again) and because \n\t   transactions are used with CA certificate stores opened in read/write \n\t   mode */\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_CURSOR_COMMIT_BEHAVIOR,\n\t\t\t\t\t\t\t&transactBehaviour, sizeof( SQLUSMALLINT ),\n\t\t\t\t\t\t\t&bufLen );\n\tif( sqlStatusOK( sqlStatus ) && transactBehaviour == SQL_CB_DELETE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Database uses destructive transactions\" ));\n\t\tassert( DEBUG_WARN );\n\t\tdbmsInfo->transactIsDestructive = TRUE;\n\t\t}\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_CURSOR_ROLLBACK_BEHAVIOR,\n\t\t\t\t\t\t\t&transactBehaviour, sizeof( SQLUSMALLINT ),\n\t\t\t\t\t\t\t&bufLen );\n\tif( sqlStatusOK( sqlStatus ) && transactBehaviour == SQL_CB_DELETE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Database uses destructive transactions\" ));\n\t\tassert( DEBUG_WARN );\n\t\tdbmsInfo->transactIsDestructive = TRUE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get the back-end type for this data source, which allows us to work \n   around back-end-specific bugs and peculiarities */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getBackendInfo( INOUT DBMS_STATE_INFO *dbmsInfo )\n\t{\n\tSQLRETURN sqlStatus;\n\tSQLSMALLINT bufLen;\n\tchar buffer[ 128 + 8 ];\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\t/* Check for various back-ends that require special-case handling */\n\tsqlStatus = SQLGetInfo( dbmsInfo->hDbc, SQL_DBMS_NAME, buffer, 128 - 1,\n\t\t\t\t\t\t\t&bufLen );\n\tif( sqlStatusOK( sqlStatus ) && bufLen >= 5 )\n\t\t{\n\t\tbuffer[ bufLen ] = '\\0';\t/* Keep static source anal.tools happy */\n\t\tif( !strCompare( buffer, \"MySQL\", 5 ) )\n\t\t\tdbmsInfo->backendType = DBMS_MYSQL;\n\t\tif( bufLen >= 6 && !strCompare( buffer, \"Access\", 6 ) )\n\t\t\tdbmsInfo->backendType = DBMS_ACCESS;\n\t\tif( bufLen >= 6 && !strCompare( buffer, \"SQLite\", 6 ) )\n\t\t\tdbmsInfo->backendType = DBMS_SQLITE;\n\t\tif( bufLen >= 9 && !strCompare( buffer, \"Interbase\", 9 ) )\n\t\t\tdbmsInfo->backendType = DBMS_INTERBASE;\n\t\tif( bufLen >= 12 && !strCompare( buffer, \"PostgreSQL\", 10 ) )\n\t\t\tdbmsInfo->backendType = DBMS_POSTGRES;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDatabase Open/Close Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Close a previously-opened ODBC connection.  We have to have this before\n   openDatabase() since it may be called by openDatabase() if the open\n   process fails */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void closeDatabase( INOUT DBMS_STATE_INFO *dbmsInfo )\n\t{\n\tSQLRETURN sqlStatus;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\t/* Commit the transaction.  The default transaction mode is auto-commit\n\t   so the SQLEndTran() call isn't strictly necessary, but we play it\n\t   safe anyway */\n\tif( dbmsInfo->needsUpdate )\n\t\t{\n\t\tsqlStatus = SQLEndTran( SQL_HANDLE_DBC, dbmsInfo->hDbc, SQL_COMMIT );\n\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t{\n\t\t\tDUMP_ODBCERROR( \"SQLEndTran()\", dbmsInfo, SQL_ERRLVL_DBC, \n\t\t\t\t\t\t\tSQL_NULL_HSTMT );\n\t\t\tassert( DEBUG_WARN );\t/* Catch this if it ever occurs */\n\t\t\t}\n\t\tdbmsInfo->needsUpdate = FALSE;\n\t\t}\n\n\t/* Clean up */\n\tLOOP_EXT( i = 0, i < NO_CACHED_QUERIES, i++, NO_CACHED_QUERIES + 1 )\n\t\t{\n\t\tif( dbmsInfo->hStmt[ i ] != NULL )\n\t\t\t{\n\t\t\tsqlStatus = SQLFreeHandle( SQL_HANDLE_STMT, dbmsInfo->hStmt[ i ] );\n\t\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\tDUMP_ODBCERROR( \"SQLFreeHandle()\", dbmsInfo, \n\t\t\t\t\t\t\t\tSQL_ERRLVL_STMT, dbmsInfo->hStmt[ i ] );\n\t\t\t\tassert( DEBUG_WARN );\t/* Catch this if it ever occurs */\n\t\t\t\t}\n\t\t\tdbmsInfo->hStmtPrepared[ i ] = FALSE;\n\t\t\tdbmsInfo->hStmt[ i ] = NULL;\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tif( dbmsInfo->connectionOpen )\n\t\t{\n\t\tsqlStatus = SQLDisconnect( dbmsInfo->hDbc );\n\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t{\n\t\t\tDUMP_ODBCERROR( \"SQLDisconnect()\", dbmsInfo, SQL_ERRLVL_DBC, \n\t\t\t\t\t\t\tSQL_NULL_HSTMT );\n\t\t\tassert( DEBUG_WARN );\t/* Catch this if it ever occurs */\n\t\t\t}\n\t\tdbmsInfo->connectionOpen = FALSE;\n\t\t}\n\tsqlStatus = SQLFreeHandle( SQL_HANDLE_DBC, dbmsInfo->hDbc );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tDUMP_ODBCERROR( \"SQLFreeHandle()\", dbmsInfo, SQL_ERRLVL_DBC, \n\t\t\t\t\t\tSQL_NULL_HSTMT );\n\t\tassert( DEBUG_WARN );\t/* Catch this if it ever occurs */\n\t\t}\n\tsqlStatus = SQLFreeHandle( SQL_HANDLE_ENV, dbmsInfo->hEnv );\n\tassert( sqlStatusOK( sqlStatus ) );\t\t\t/* Warn of potential errors */\n\tdbmsInfo->hDbc = NULL;\n\tdbmsInfo->hEnv = NULL;\n\t}\n\n/* Open a connection to a data source.  We don't check the return codes for\n   many of the parameter-fiddling functions since the worst that can happen\n   if they fail is that performance will be somewhat suboptimal and it's not\n   worth abandoning the database open just because some obscure tweak isn't\n   supported.\n\n   In addition to the main hStmt handle we also allocate a number of \n   additional hStmts used to contain pre-prepared, cached instances of \n   frequently-executed queries.  This means that the expensive step of \n   parsing the SQL query, validating it against the system catalog, \n   preparing an access plan, and optimising the plan, are only performed \n   once on the first query rather than at every single access */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int openDatabase( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_BUFFER( nameLen ) const char *name,\n\t\t\t\t\t\t IN_LENGTH_NAME const int nameLen, \n\t\t\t\t\t\t IN const BOOLEAN isReadOnly, \n\t\t\t\t\t\t OUT_FLAGS_Z( DBMS ) int *featureFlags )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &dbmsInfo->errorInfo;\n#endif /* USE_ERRMSGS */\n\tDBMS_NAME_INFO nameInfo;\n\tSQLRETURN sqlStatus;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( isReadPtrDynamic( name, nameLen ) );\n\tassert( isWritePtr( featureFlags, sizeof( int ) ) );\n\n\tREQUIRES( nameLen >= MIN_NAME_LENGTH && \\\n\t\t\t  nameLen < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( isReadOnly == TRUE || isReadOnly == FALSE );\n\n\t/* Clear return values */\n\tmemset( dbmsInfo, 0, sizeof( DBMS_STATE_INFO ) );\n\t*featureFlags = DBMS_FEATURE_FLAG_NONE;\n\n#ifdef DYNAMIC_LOAD\n\t/* Make sure that the driver is bound in */\n\tif( hODBC == NULL_INSTANCE )\n\t\treturn( CRYPT_ERROR_OPEN );\n#endif /* DYNAMIC_LOAD */\n\n\t/* Parse the data source into its individual components */\n\tstatus = dbmsParseName( &nameInfo, name, nameLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Allocate environment and connection handles.  Before we do anything\n\t   with the environment handle we have to set the ODBC version to 3 or\n\t   any succeeding calls will fail with a function sequence error.  God\n\t   knows why they couldn't assume a default setting of ODBC 3.x for this\n\t   value when it requires an ODBC 3.x function call to get here in the\n\t   first place */\n\tsqlStatus = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE,\n\t\t\t\t\t\t\t\t&dbmsInfo->hEnv );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\t/* We can't get any error details without at least an environment\n\t\t   handle so all that we can do is return a generic allocation error\n\t\t   message.  If we get a failure at this point (and in particular\n\t\t   on the very first ODBC call) it's usually a sign of an incorrect\n\t\t   ODBC install or config (on non-Windows systems where it's not\n\t\t   part of the OS), since the ODBC driver can't initialise itself */\n#ifdef __WINDOWS__\n\t\tsetErrorString( errorInfo, \n\t\t\t\t\t\t\"Couldn't allocate database connection handle\", 44 );\n#else\n\t\tsetErrorString( errorInfo, \n\t\t\t\t\t\t\"Couldn't allocate database connection handle, this \"\n\t\t\t\t\t\t\"is probably due to an incorrect ODBC driver install \"\n\t\t\t\t\t\t\"or an invalid configuration\", 130 );\n#endif /* __WINDOWS__ */\n\t\tDEBUG_DIAG(( \"SQLAllocHandle() (environment handle) returned error \"\n\t\t\t\t\t \"%d\", sqlStatus ));\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\tsqlStatus = SQLSetEnvAttr( dbmsInfo->hEnv, SQL_ATTR_ODBC_VERSION,\n\t\t\t\t\t\t\t\tVALUE_TO_PTR( SQL_OV_ODBC3 ),\n\t\t\t\t\t\t\t\tSQL_IS_INTEGER );\n\tif( sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tsqlStatus = SQLAllocHandle( SQL_HANDLE_DBC, dbmsInfo->hEnv,\n\t\t\t\t\t\t\t\t\t&dbmsInfo->hDbc );\n\t\t}\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_ENV, SQL_NULL_HSTMT,\n\t\t\t\t\t\t\t   CRYPT_ERROR_OPEN );\n\t\tSQLFreeHandle( SQL_HANDLE_ENV, dbmsInfo->hEnv );\n\t\tDEBUG_DIAG_ERRMSG(( \"SQLAllocHandle() (connection handle) returned \"\n\t\t\t\t\t\t\t\"error code %d, error string:\\n  '%s'\", sqlStatus, \n\t\t\t\t\t\t\tgetErrorInfoString( &dbmsInfo->errorInfo ) ));\n\t\treturn( status );\n\t\t}\n\n\t/* Once everything is set up the way that we want it, try to connect to \n\t   a data source and allocate a statement handle.  If there's an error\n\t   we dump the information to the error log, since this is a create-\n\t   object function and so extended error information can't be read since\n\t   the object won't be created */\n\tsqlStatus = SQLConnect( dbmsInfo->hDbc,\n\t\t\t\t\t\t\t( SQLCHAR * ) nameInfo.name, \n\t\t\t\t\t\t\t( SQLSMALLINT ) nameInfo.nameLen,\n\t\t\t\t\t\t\t( SQLCHAR * ) nameInfo.user, \n\t\t\t\t\t\t\t( SQLSMALLINT ) nameInfo.userLen,\n\t\t\t\t\t\t\t( SQLCHAR * ) nameInfo.password, \n\t\t\t\t\t\t\t( SQLSMALLINT ) nameInfo.passwordLen );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_DBC, SQL_NULL_HSTMT,\n\t\t\t\t\t\t\t   CRYPT_ERROR_OPEN );\n\t\tDEBUG_DIAG_ERRMSG(( \"SQLConnect() returned error code %d, error \"\n\t\t\t\t\t\t\t\"string:\\n  '%s'\", sqlStatus, \n\t\t\t\t\t\t\tgetErrorInfoString( &dbmsInfo->errorInfo ) ));\n\t\tcloseDatabase( dbmsInfo );\n\t\treturn( status );\n\t\t}\n\tdbmsInfo->connectionOpen = TRUE;\n\n\t/* Now that the connection is open, allocate the statement handles */\n\tLOOP_EXT( i = 0, i < NO_CACHED_QUERIES && sqlStatusOK( sqlStatus ), i++,\n\t\t\t  NO_CACHED_QUERIES + 1 )\n\t\t{\n\t\tsqlStatus = SQLAllocHandle( SQL_HANDLE_STMT, dbmsInfo->hDbc,\n\t\t\t\t\t\t\t\t\t&dbmsInfo->hStmt[ i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_DBC, SQL_NULL_HSTMT,\n\t\t\t\t\t\t\t   CRYPT_ERROR_OPEN );\n\t\tDEBUG_DIAG_ERRMSG(( \"SQLAllocHandle() (statement handle) returned \"\n\t\t\t\t\t\t\t\"error code %d, error string:\\n  '%s'\", \n\t\t\t\t\t\t\tsqlStatus, \n\t\t\t\t\t\t\tgetErrorInfoString( &dbmsInfo->errorInfo ) ));\n\t\tcloseDatabase( dbmsInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* Set the access mode to read-only if we can.  The default is R/W, but\n\t   setting it to read-only optimises transaction management */\n\tif( isReadOnly )\n\t\t{\n\t\t( void ) SQLSetStmtAttr( dbmsInfo->hDbc, SQL_ATTR_ACCESS_MODE,\n\t\t\t\t\t\t\t\t VALUE_TO_PTR( SQL_MODE_READ_ONLY ), \n\t\t\t\t\t\t\t\t SQL_IS_INTEGER );\n\t\t}\n\n\t/* Set the cursor type to forward-only (which should be the default\n\t   anyway), concurrency to read-only if we're opening the database in\n\t   read-only mode (this again should be the default), and turn off\n\t   scanning for escape clauses in the SQL strings, which lets the driver\n\t   pass the string directly to the data source.  The latter improves\n\t   both performance and (to some extent) security by reducing the\n\t   chances of hostile SQL injection, or at least by requiring specially\n\t   crafted back-end specific SQL rather than generic ODBC SQL to\n\t   function */\n\tLOOP_EXT( i = 0, i < NO_CACHED_QUERIES, i++, NO_CACHED_QUERIES + 1 )\n\t\t{\n\t\t( void ) SQLSetStmtAttr( dbmsInfo->hStmt[ i ], SQL_ATTR_CURSOR_TYPE,\n\t\t\t\t\t\t\t\t VALUE_TO_PTR( SQL_CURSOR_FORWARD_ONLY ),\n\t\t\t\t\t\t\t\t SQL_IS_INTEGER );\n\t\tif( isReadOnly )\n\t\t\t{\n\t\t\t( void ) SQLSetStmtAttr( dbmsInfo->hStmt[ i ], \n\t\t\t\t\t\t\t\t\t SQL_ATTR_CONCURRENCY,\n\t\t\t\t\t\t\t\t\t VALUE_TO_PTR( SQL_CONCUR_READ_ONLY ),\n\t\t\t\t\t\t\t\t\t SQL_IS_INTEGER );\n\t\t\t}\n\t\t( void ) SQLSetStmtAttr( dbmsInfo->hStmt[ i ], SQL_ATTR_NOSCAN,\n\t\t\t\t\t\t\t\t VALUE_TO_PTR( SQL_NOSCAN_ON ), \n\t\t\t\t\t\t\t\t SQL_IS_INTEGER );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Get various driver and data source-specific information that we may\n\t   need later on */\n\tstatus = getDatatypeInfo( dbmsInfo, featureFlags );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getBackendInfo( dbmsInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcloseDatabase( dbmsInfo );\n\t\tDEBUG_DIAG_ERRMSG(( \"Fetch of database-specific information \"\n\t\t\t\t\t\t\t\"returned status %d, error string:\\n  '%s'\", \n\t\t\t\t\t\t\tstatus, \n\t\t\t\t\t\t\tgetErrorInfoString( &dbmsInfo->errorInfo ) ));\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDatabase Read Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Fetch data from a query */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 6 ) ) \\\nstatic int fetchData( const SQLHSTMT hStmt, \n\t\t\t\t\t  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\tchar *data,\n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *dataLength, \n\t\t\t\t\t  IN_ENUM( DBMS_QUERY ) const DBMS_QUERY_TYPE queryType,\n\t\t\t\t\t  INOUT DBMS_STATE_INFO *dbmsInfo )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &dbmsInfo->errorInfo;\n#endif /* USE_ERRMSGS */\n\tconst SQLSMALLINT dataType = ( SQLSMALLINT  ) \\\n\t\t\t\t\t\t\t\t ( ( dbmsInfo->hasBinaryBlobs ) ? \\\n\t\t\t\t\t\t\t\t   SQL_C_BINARY : SQL_C_CHAR );\n\tSQLRETURN sqlStatus;\n\tSQLLEN length;\n\n\tassert( ( queryType == DBMS_QUERY_CHECK && \\\n\t\t\t  data == NULL && dataMaxLength == 0 && dataLength == NULL ) || \\\n\t\t\t( queryType != DBMS_QUERY_CHECK && \\\n\t\t\t  isWritePtrDynamic( data, dataMaxLength ) && \\\n\t\t\t  isWritePtr( dataLength, sizeof( int ) ) ) );\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\n\tREQUIRES( ( queryType == DBMS_QUERY_CHECK && \\\n\t\t\t\tdata == NULL && dataMaxLength == 0 && \\\n\t\t\t\tdataLength == NULL ) || \\\n\t\t\t  ( queryType != DBMS_QUERY_CHECK && \\\n\t\t\t\tdata != NULL && dataMaxLength >= 16 && \\\n\t\t\t\tdataMaxLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tdataLength != NULL ) );\n\tREQUIRES( isEnumRange( queryType, DBMS_QUERY ) );\n\n\t/* Clear return value */\n\tif( data != NULL )\n\t\t{\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t\t*dataLength = 0;\n\t\t}\n\n\t/* Get the results of the transaction */\n\tsqlStatus = SQLFetch( hStmt );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\t/* If the fetch status is SQL_NO_DATA, indicating the end of the\n\t\t   result set, we handle it specially since some drivers only return\n\t\t   the basic error code and don't provide any further diagnostic\n\t\t   information to be fetched by SQLGetDiagRec() */\n\t\tif( sqlStatus == SQL_NO_DATA )\n\t\t\t{\n\t\t\tif( queryType == DBMS_QUERY_CONTINUE )\n\t\t\t\t{ \n\t\t\t\tsetErrorString( errorInfo, \"No more data found\", 18 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tsetErrorString( errorInfo, \"No data found\", 13 );\n\t\t\t\t}\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t  CRYPT_ERROR_READ ) );\n\t\t}\n\n\t/* If we're just doing a presence check we don't bother fetching data */\n\tif( queryType == DBMS_QUERY_CHECK )\n\t\treturn( CRYPT_OK );\n\n\t/* Read the data */\n\tsqlStatus = SQLGetData( hStmt, 1, dataType, data, \n\t\t\t\t\t\t\t( SQLLEN ) dataMaxLength, &length );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t  CRYPT_ERROR_READ ) );\n\t\t}\n\tREQUIRES( isIntegerRange( length ) );\n\t*dataLength = ( int ) length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a transaction that returns information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performQuery( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t IN_BUFFER_OPT( commandLength ) const char *command,\n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int commandLength, \n\t\t\t\t\t\t OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t IN_ARRAY_OPT_C( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\tTYPECAST( BOUND_DATA ) const void *boundData,\n\t\t\t\t\t\t IN_ENUM_OPT( DBMS_CACHEDQUERY ) \\\n\t\t\t\t\t\t\tconst DBMS_CACHEDQUERY_TYPE queryEntry,\n\t\t\t\t\t\t IN_ENUM( DBMS_QUERY ) const DBMS_QUERY_TYPE queryType )\n\t{\n\tconst SQLHSTMT hStmt = dbmsInfo->hStmt[ queryEntry ];\n\tBOUND_DATA_STATE boundDataState;\n\tSQLRETURN sqlStatus;\n\tint status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( ( command == NULL && commandLength == 0 && \\\n\t\t\t  ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\t\tqueryType == DBMS_QUERY_CANCEL ) ) || \\\n\t\t\tisReadPtrDynamic( command, commandLength ) );\n\tassert( ( data == NULL && dataMaxLength == 0 && dataLength == NULL ) || \\\n\t\t\t( isWritePtrDynamic( data, dataMaxLength ) && \\\n\t\t\t  isWritePtr( dataLength, sizeof( int ) ) ) );\n\tassert( ( boundData == NULL ) || \\\n\t\t\tisReadPtr( boundData, \\\n\t\t\t\t\t   sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS ) );\n\n\tREQUIRES( ( ( queryType == DBMS_QUERY_CONTINUE || \\\n\t\t\t\t  queryType == DBMS_QUERY_CANCEL ) && \\\n\t\t\t\tcommand == NULL && commandLength == 0 ) || \\\n\t\t\t  ( ( queryType == DBMS_QUERY_START || \\\n\t\t\t\t  queryType == DBMS_QUERY_CHECK || \\\n\t\t\t\t  queryType == DBMS_QUERY_NORMAL ) && \\\n\t\t\t\tcommand != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( commandLength ) ) );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 && \\\n\t\t\t\tdataLength == NULL ) || \\\n\t\t\t  ( data != NULL && dataMaxLength >= 16 && \\\n\t\t\t\tdataMaxLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\tdataLength != NULL ) );\n\tREQUIRES( isEnumRangeOpt( queryEntry, DBMS_CACHEDQUERY ) );\n\tREQUIRES( isEnumRange( queryType, DBMS_QUERY ) );\n\n\t/* Clear return value */\n\tif( dataLength != NULL )\n\t\t*dataLength = 0;\n\n\t/* If we're starting a new query, handle the query initialisation and\n\t   parameter binding */\n\tif( queryType == DBMS_QUERY_START || \\\n\t\tqueryType == DBMS_QUERY_CHECK || \\\n\t\tqueryType == DBMS_QUERY_NORMAL )\n\t\t{\n\t\t/* Prepare the query for execution if necessary.  The entry at \n\t\t   position DBMS_CACHEDQUERY_NONE is never cached so the following \n\t\t   code is always executed for this case */\n\t\tif( !dbmsInfo->hStmtPrepared[ queryEntry ] )\n\t\t\t{\n\t\t\tchar query[ SQL_QUERY_BUFSIZE + 8 ];\n\t\t\tint queryLength;\n\n\t\t\tstatus = convertQuery( dbmsInfo, query, SQL_QUERY_BUFSIZE, \n\t\t\t\t\t\t\t\t   &queryLength, command, commandLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsqlStatus = SQLPrepare( hStmt, ( SQLCHAR * ) query, \n\t\t\t\t\t\t\t\t\tqueryLength );\n\t\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_READ ) );\n\t\t\t\t}\n\t\t\tif( queryEntry != DBMS_CACHEDQUERY_NONE )\n\t\t\t\tdbmsInfo->hStmtPrepared[ queryEntry ] = TRUE;\n\t\t\t}\n\n\t\t/* Bind in any query parameters that may be required */\n\t\tif( boundData != NULL )\n\t\t\t{\n\t\t\tstatus = bindParameters( hStmt, boundData, &boundDataState, \n\t\t\t\t\t\t\t\t\t dbmsInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\tswitch( queryType )\n\t\t{\n\t\tcase DBMS_QUERY_START:\n\t\t\t/* Execute the query */\n\t\t\tsqlStatus = SQLExecute( hStmt );\n\t\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t  CRYPT_ERROR_READ ) );\n\t\t\t\t}\n\n\t\t\t/* If we're starting an ongoing query with results to be fetched\n\t\t\t   later, we're done */\n\t\t\tif( data == NULL )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Fall through to fetch the first set of results */\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase DBMS_QUERY_CONTINUE:\n\t\t\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\n\t\t\tREQUIRES( data != NULL && \\\n\t\t\t\t\t  dataMaxLength >= 16 && \\\n\t\t\t\t\t  dataMaxLength < MAX_INTLENGTH_SHORT );\n\n\t\t\t/* We're in the middle of a continuing query, fetch the next set\n\t\t\t   of results.  If we've run out of results (indicated by a not-\n\t\t\t   found status) we explicitly signal to the caller that the\n\t\t\t   query has completed */\n\t\t\tstatus = fetchData( dbmsInfo->hStmt[ queryEntry ], data,\n\t\t\t\t\t\t\t\tdataMaxLength, dataLength, \n\t\t\t\t\t\t\t\tDBMS_QUERY_CONTINUE, dbmsInfo );\n\t\t\treturn( cryptStatusOK( status ) ? CRYPT_OK : \\\n\t\t\t\t\t( status == CRYPT_ERROR_NOTFOUND ) ? \\\n\t\t\t\t\tCRYPT_ERROR_COMPLETE : status );\n\n\t\tcase DBMS_QUERY_CANCEL:\n\t\t\t/* Cancel any outstanding requests to clear the hStmt and make \n\t\t\t   it ready for re-use */\n\t\t\tSQLCloseCursor( dbmsInfo->hStmt[ queryEntry ] );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase DBMS_QUERY_CHECK:\n\t\tcase DBMS_QUERY_NORMAL:\n\t\t\t/* Only return a maximum of a single row in response to a point\n\t\t\t   query.  This is a simple optimisation to ensure that the\n\t\t\t   database client doesn't start sucking across huge amounts of\n\t\t\t   data when it's not necessary */\n\t\t\t( void ) SQLSetStmtAttr( hStmt, SQL_ATTR_MAX_ROWS, \n\t\t\t\t\t\t\t\t\t VALUE_TO_PTR( 1 ), SQL_IS_INTEGER );\n\n\t\t\t/* Execute the SQL statement and fetch the results */\n\t\t\tsqlStatus = SQLExecute( hStmt );\n\t\t\tif( sqlStatusOK( sqlStatus ) )\n\t\t\t\t{\n\t\t\t\tstatus = fetchData( hStmt, data, dataMaxLength, dataLength, \n\t\t\t\t\t\t\t\t\tqueryType, dbmsInfo );\n\t\t\t\tSQLCloseCursor( hStmt );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t   CRYPT_ERROR_READ );\n\t\t\t\t}\n\n\t\t\t/* Reset the statement handle's multi-row result handling */\n\t\t\t( void ) SQLSetStmtAttr( hStmt, SQL_ATTR_MAX_ROWS, \n\t\t\t\t\t\t\t\t\t VALUE_TO_PTR( 0 ), SQL_IS_INTEGER );\n\t\t\treturn( status );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t \tDatabase Write Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a transaction that updates the database without returning any\n   data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int performUpdate( INOUT DBMS_STATE_INFO *dbmsInfo, \n\t\t\t\t\t\t  IN_BUFFER_OPT( commandLength ) const char *command,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int commandLength, \n\t\t\t\t\t\t  IN_ARRAY_OPT_C( BOUND_DATA_MAXITEMS ) \\\n\t\t\t\t\t\t\tTYPECAST( BOUND_DATA ) const void *boundData,\n\t\t\t\t\t\t  IN_ENUM( DBMS_UPDATE ) \\\n\t\t\t\t\t\t\tconst DBMS_UPDATE_TYPE updateType )\n\t{\n\tconst SQLHSTMT hStmt = dbmsInfo->hStmt[ DBMS_CACHEDQUERY_NONE ];\n\tBOUND_DATA_STATE boundDataState;\n\tSQLRETURN sqlStatus;\n\tchar query[ SQL_QUERY_BUFSIZE + 8 ];\n\tint queryLength, status;\n\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_STATE_INFO ) ) );\n\tassert( ( command == NULL && commandLength == 0 && \\\n\t\t\t  updateType == DBMS_UPDATE_ABORT ) || \\\n\t\t\tisReadPtrDynamic( command, commandLength ) );\n\tassert( ( boundData == NULL ) || \\\n\t\t\tisReadPtr( boundData, \\\n\t\t\t\t\t   sizeof( BOUND_DATA ) * BOUND_DATA_MAXITEMS ) );\n\n\tREQUIRES( ( updateType == DBMS_UPDATE_ABORT && \\\n\t\t\t\tcommand == NULL && commandLength == 0 ) || \\\n\t\t\t  ( updateType != DBMS_UPDATE_ABORT && \\\n\t\t\t\tcommand != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( commandLength ) ) );\n\tREQUIRES( isEnumRange( updateType, DBMS_UPDATE ) );\n\n\t/* If we're aborting a transaction, roll it back, re-enable autocommit,\n\t   and clean up */\n\tif( updateType == DBMS_UPDATE_ABORT )\n\t\t{\n\t\tsqlStatus = SQLEndTran( SQL_HANDLE_DBC, dbmsInfo->hDbc, \n\t\t\t\t\t\t\t\tSQL_ROLLBACK );\n\t\t( void ) SQLSetConnectAttr( dbmsInfo->hDbc, SQL_ATTR_AUTOCOMMIT,\n\t\t\t\t\t\t\t\t\tVALUE_TO_PTR( SQL_AUTOCOMMIT_ON ),\n\t\t\t\t\t\t\t\t\tSQL_IS_UINTEGER );\n\t\tif( !sqlStatusOK( sqlStatus ) )\n\t\t\t{\n\t\t\treturn( getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t  CRYPT_ERROR_WRITE ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's the start of a transaction, turn autocommit off */\n\tif( updateType == DBMS_UPDATE_BEGIN )\n\t\t{\n\t\t( void ) SQLSetConnectAttr( dbmsInfo->hDbc, SQL_ATTR_AUTOCOMMIT,\n\t\t\t\t\t\t\t\t\tVALUE_TO_PTR( SQL_AUTOCOMMIT_OFF ),\n\t\t\t\t\t\t\t\t\tSQL_IS_UINTEGER );\n\t\t}\n\n\t/* Bind in any necessary parameters to the hStmt */\n\tif( boundData != NULL )\n\t\t{\n\t\tstatus = bindParameters( hStmt, boundData, &boundDataState,\n\t\t\t\t\t\t\t\t dbmsInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Execute the command */\n\tstatus = convertQuery( dbmsInfo, query, SQL_QUERY_BUFSIZE, &queryLength,\n\t\t\t\t\t\t   command, commandLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsqlStatus = SQLExecDirect( hStmt, ( SQLCHAR * ) query, queryLength );\n\tif( !sqlStatusOK( sqlStatus ) )\n\t\t{\n\t\t/* If we were supposed to begin a transaction but it failed, reset\n\t\t   the autocommit state.  This is necessary because the \n\t\t   DBMS_FLAG_UPDATEACTIVE flag won't be set if the transaction\n\t\t   isn't started and therefore the DBMS_UPDATE_COMMIT/\n\t\t   DBMS_UPDATE_ABORT action that has to eventually follow a \n\t\t   DBMS_UPDATE_BEGIN will never be performed */\n\t\tif( updateType == DBMS_UPDATE_BEGIN )\n\t\t\t{\n\t\t\t( void ) SQLSetConnectAttr( dbmsInfo->hDbc, SQL_ATTR_AUTOCOMMIT,\n\t\t\t\t\t\t\t\t\t\tVALUE_TO_PTR( SQL_AUTOCOMMIT_ON ),\n\t\t\t\t\t\t\t\t\t\tSQL_IS_UINTEGER );\n\t\t\t}\n\n\t\t/* The return status from a delete operation can be reported in\n\t\t   several ways at the whim of the driver.  Some drivers always\n\t\t   report success even though nothing was found to delete (more\n\t\t   common in ODBC 2.x drivers, see the code further on for the\n\t\t   handling for this), others report a failure to delete anything\n\t\t   with an SQL_NO_DATA status (more common in ODBC 3.x drivers).\n\t\t   For this case we convert the overall status to a\n\t\t   CRYPT_ERROR_NOTFOUND and update the sqlStatus as required if we\n\t\t   need to continue */\n\t\tif( sqlStatus == SQL_NO_DATA && \\\n\t\t\tcommand != NULL && commandLength >= 6 && \\\n\t\t\t!strCompare( command, \"DELETE\", 6 ) )\n\t\t\t{\n\t\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\t\t\tif( updateType != DBMS_UPDATE_COMMIT )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* SQLite erroneously reports the result of a CREATE TABLE/\n\t\t\t   CREATE INDEX command with SQL_NO_DATA instead of SQL_SUCCESS, \n\t\t\t   so we treat this as SQL_SUCCESS */\n\t\t\tif( sqlStatus == SQL_NO_DATA && \\\n\t\t\t\tdbmsInfo->backendType == DBMS_SQLITE && \\\n\t\t\t\tcommand != NULL && commandLength >= 13 && \\\n\t\t\t\t( !strCompare( command, \"CREATE TABLE \", 13 ) || \\\n\t\t\t\t  !strCompare( command, \"CREATE INDEX \", 13 ) || \\\n\t\t\t\t  !strCompare( command, \"CREATE UNIQUE\", 13 ) ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"SQLite reported result of '%s' as SQL_NO_DATA, \"\n\t\t\t\t\t\t\t \"assuming that this is really SQL_SUCCESS\",\n\t\t\t\t\t\t\t command ));\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If we hit an error at this point we can only exit if we're\n\t\t\t\t   not finishing a transaction.  If we are, the commit turns\n\t\t\t\t   into an abort further down */\n\t\t\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t\t   CRYPT_ERROR_WRITE );\n\t\t\t\tif( updateType != DBMS_UPDATE_COMMIT )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're performing a delete the operation will succeed even\n\t\t   though nothing was found to delete so we make sure that we\n\t\t   actually changed something */\n\t\tif( command != NULL && commandLength >= 6 && \\\n\t\t\t!strCompare( command, \"DELETE\", 6 ) )\n\t\t\t{\n\t\t\tSQLLEN rowCount;\n\n\t\t\tsqlStatus = SQLRowCount( hStmt, &rowCount );\n\t\t\tif( !sqlStatusOK( sqlStatus ) || rowCount <= 0 )\n\t\t\t\tstatus = CRYPT_ERROR_NOTFOUND;\n\t\t\t}\n\t\t}\n\n\t/* If it's the end of a transaction, commit the transaction and turn\n\t   autocommit on again */\n\tif( updateType == DBMS_UPDATE_COMMIT )\n\t\t{\n\t\t/* If we've had a failure before this point, abort, otherwise\n\t\t   commit.  The SQLSMALLINT cast is necessary (although spurious) in \n\t\t   some development environments */\n\t\tsqlStatus = SQLEndTran( SQL_HANDLE_DBC, dbmsInfo->hDbc,\n\t\t\t\t\t\t\t\t( SQLSMALLINT ) \\\n\t\t\t\t\t\t\t\t( cryptStatusError( status ) ? \\\n\t\t\t\t\t\t\t\t  SQL_ROLLBACK : SQL_COMMIT ) );\n\t\tif( dbmsInfo->transactIsDestructive )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\t/* If transactions are destructive for this back-end type, \n\t\t\t   invalidate all prepared statements */\n\t\t\tLOOP_EXT( i = 0, i < NO_CACHED_QUERIES, i++, \n\t\t\t\t\t  NO_CACHED_QUERIES + 1 )\n\t\t\t\t{\n\t\t\t\tdbmsInfo->hStmtPrepared[ i ] = FALSE;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\t( void ) SQLSetConnectAttr( dbmsInfo->hDbc, SQL_ATTR_AUTOCOMMIT,\n\t\t\t\t\t\t\t\t\tVALUE_TO_PTR( SQL_AUTOCOMMIT_ON ),\n\t\t\t\t\t\t\t\t\tSQL_IS_UINTEGER );\n\t\tif( cryptStatusOK( status ) && !sqlStatusOK( sqlStatus ) )\n\t\t\t{\n\t\t\tstatus = getErrorInfo( dbmsInfo, SQL_ERRLVL_STMT, hStmt,\n\t\t\t\t\t\t\t\t   CRYPT_ERROR_WRITE );\n\t\t\t}\n\t\t}\n\n\treturn( status );\n\t}\n\n#ifndef USE_RPCAPI\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDispatchODBC( INOUT DBMS_INFO *dbmsInfo )\n\t{\n\tassert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );\n\n\tdbmsInfo->openDatabaseBackend = openDatabase;\n\tdbmsInfo->closeDatabaseBackend = closeDatabase;\n\tdbmsInfo->performUpdateBackend = performUpdate;\n\tdbmsInfo->performQueryBackend = performQuery;\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\n/* Pull in the shared database RPC routines, renaming the generic dispatch\n   function to the ODBC-specific one which is called directly by the\n   marshalling code */\n\n#define processCommand( stateInfo, buffer ) \\\n\t\todbcProcessCommand( stateInfo, buffer )\n#include \"dbx_rpc.c\"\n\n#endif /* !USE_RPCAPI */\n\n#endif /* USE_ODBC */\n"
  },
  {
    "path": "deps/cl345/keyset/pgp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib PGP Keyset Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"keyset.h\"\n  #include \"pgp_key.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pgp_key.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGPKEYS\n\n/* A PGP private keyset can contain multiple key objects so before we do \n   anything with the keyset we scan it and build an in-memory index of \n   what's present.  When we perform an update we just flush the in-memory \n   information to disk.\n\n   Each keyset can contain information for multiple personalities (although \n   for private keys it's unlikely to contain more than a small number), we \n   allow a maximum of MAX_PGP_OBJECTS per keyset.  A setting of 16 objects \n   consumes ~4K of memory (16 x ~256) so we choose that as the limit */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define MAX_PGP_OBJECTS\t4\n#else\n  #define MAX_PGP_OBJECTS\t16\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* GPG 2.1 broke the standard keyring format, going from the RFC-standardised\n   format to storing private keys in an undocumented, homebrew format in a \n   directory \"private-keys.v1.d\" and public keys in an equally undocumented\n   homebrew \"keybox\" format \"pubring.kbx\", see\n   https://www.gnupg.org/faq/whats-new-in-2.1.html#nosecring and \n   https://www.gnupg.org/faq/whats-new-in-2.1.html#keybox.  This means that\n   GPG-sourced keys can only be used if they're first exported in the \n   standard RFC-compliant format */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the PGP information state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckPGP( const PGP_INFO *pgpInfoPtr )\n\t{\n\tassert( isReadPtr( pgpInfoPtr, sizeof( PGP_INFO ) ) );\n\n\t/* Check that the basic fields are in order */\n\tif( !isShortIntegerRange( pgpInfoPtr->keyDataLen ) || \\\n\t\tpgpInfoPtr->lastUserID < 0 || \\\n\t\tpgpInfoPtr->lastUserID > MAX_PGP_USERIDS || \\\n\t\t( pgpInfoPtr->isOpenPGP != FALSE && \\\n\t\t  pgpInfoPtr->isOpenPGP != TRUE ) || \\\n\t\t( pgpInfoPtr->isComplete != FALSE && \\\n\t\t  pgpInfoPtr->isComplete != TRUE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPGP: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\t\n\treturn( TRUE );\n\t}\n\n/* Free object entries */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pgpFreeEntry( INOUT PGP_INFO *pgpInfo )\n\t{\n\tassert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\n\tif( pgpInfo->keyData != NULL )\n\t\t{\n\t\tzeroise( pgpInfo->keyData, pgpInfo->keyDataLen );\n\t\tclFree( \"pgpFreeEntry\", pgpInfo->keyData );\n\t\tpgpInfo->keyData = NULL;\n\t\tpgpInfo->keyDataLen = 0;\n\t\t}\n\tzeroise( pgpInfo, sizeof( PGP_INFO  ) );\n\t}\n\n/* Create a decryption context for the private key from a user-supplied \n   password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int createDecryptionContext( OUT_HANDLE_OPT CRYPT_CONTEXT *iSessionKey,\n\t\t\t\t\t\t\t\t\tconst PGP_KEYINFO *keyInfo,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *password, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_NAME const int passwordLength )\n\t{\n\tCRYPT_CONTEXT iLocalContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tstatic const int mode = CRYPT_MODE_CFB;\t/* int vs.enum */\n\tint ivSize, status;\n\n\tassert( isWritePtr( iSessionKey, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Convert the user password into an encryption context */\n\tsetMessageCreateObjectInfo( &createInfo, keyInfo->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo,  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = pgpPasswordToKey( iLocalContext, \n\t\t\t\t\t\t\t\t   ( keyInfo->cryptAlgo == CRYPT_ALGO_AES && \\\n\t\t\t\t\t\t\t\t     keyInfo->cryptAlgoParam > 0 ) ? \\\n\t\t\t\t\t\t\t\t\tkeyInfo->cryptAlgoParam : CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t   password, passwordLength, \n\t\t\t\t\t\t\t\t   keyInfo->hashAlgo, \n\t\t\t\t\t\t\t\t   ( keyInfo->saltSize > 0 ) ? \\\n\t\t\t\t\t\t\t\t\tkeyInfo->salt : NULL, keyInfo->saltSize,\n\t\t\t\t\t\t\t\t   keyInfo->keySetupIterations );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the IV into the context */\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &ivSize, CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusOK( status ) && ivSize > keyInfo->ivSize )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyInfo->iv, \n\t\t\t\t\t\tkeyInfo->ivSize );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iSessionKey = iLocalContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tFind a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a cryptlib-style key ID for a PGP key and check it against the\n   given key ID.  This will really suck with large public keyrings since it\n   requires creating a context for each key that we check, but there's no \n   easy way around this and in any case it only occurs when using PGP keys \n   with non-PGP messages, which is fairly rare */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN matchKeyID( const PGP_KEYINFO *keyInfo, \n\t\t\t\t\t\t   IN_BUFFER( requiredIDlength ) const BYTE *requiredID,\n\t\t\t\t\t\t   IN_LENGTH_KEYID const int requiredIDlength,\n\t\t\t\t\t\t   const BOOLEAN isPGPkeyID )\n\t{\n\tCRYPT_CONTEXT iLocalContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ KEYID_SIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isReadPtrDynamic( requiredID, requiredIDlength ) );\n\n\tREQUIRES_B( requiredIDlength == PGP_KEYID_SIZE || \\\n\t\t\t\trequiredIDlength == KEYID_SIZE );\n\tREQUIRES_B( isPGPkeyID == TRUE || isPGPkeyID == FALSE );\n\n\t/* If it's a PGP key ID we can check it directly against the two PGP\n\t   key IDs.  We don't distinguish between the two ID types externally\n\t   because it's a pain for external code to have to know that there are\n\t   two ID types that look the same and are often used interchangeably \n\t   but of the two only the OpenPGP variant is valid for all keys (in \n\t   fact there are some broken PGP variants that use PGP 2.x IDs marked \n\t   as OpenPGP IDs, so checking both IDs is necessary for \n\t   interoperability).  The mixing of ID types is safe because the \n\t   chances of a collision are miniscule and the worst that can happen is \n\t   that a signature check will fail (encryption keys are chosen by user \n\t   ID and not key ID so accidentally using the wrong key to encrypt \n\t   isn't an issue) */\n\tif( isPGPkeyID )\n\t\t{\n\t\tENSURES_B( requiredIDlength == PGP_KEYID_SIZE );\n\n\t\tif( !memcmp( requiredID, keyInfo->openPGPkeyID, PGP_KEYID_SIZE ) )\n\t\t\treturn( TRUE );\n\t\treturn( ( keyInfo->pkcAlgo == CRYPT_ALGO_RSA ) && \\\n\t\t\t\t!memcmp( requiredID, keyInfo->pgp2KeyID, PGP_KEYID_SIZE ) );\n\t\t}\n\tENSURES_B( requiredIDlength == KEYID_SIZE );\n\n\t/* Generate the key ID via a context.  We have to set the OpenPGP key ID\n\t   before the key load to mark it as a PGP key otherwise the key check \n\t   will fail since it's not a full X9.42 key with DLP validation \n\t   parameters */\n\tsetMessageCreateObjectInfo( &createInfo, keyInfo->pkcAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't create PKC context to generate key ID\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( FALSE );\n\t\t}\n\tiLocalContext = createInfo.cryptHandle;\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyInfo->openPGPkeyID, \n\t\t\t\t\tPGP_KEYID_SIZE );\n\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyInfo->pubKeyData,\n\t\t\t\t\t\tkeyInfo->pubKeyDataLen );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_PGP );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyID, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\t}\n\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't initialise PKC context to generate key ID\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check if it's the same as the key ID that we're looking for */\n\treturn( !memcmp( requiredID, keyID, requiredIDlength ) ? TRUE : FALSE );\n\t}\n\n/* Check whether a key matches the required user ID */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN pgpCheckKeyMatch( const PGP_INFO *pgpInfo, \n\t\t\t\t\t\t  const PGP_KEYINFO *keyInfo, \n\t\t\t\t\t\t  const KEY_MATCH_INFO *keyMatchInfo )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\tassert( isReadPtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) );\n\n\t/* If there's an explicitly requested key usage type, make sure that the \n\t   key is suitable */\n\tif( ( keyMatchInfo->flags & KEYMGMT_MASK_USAGEOPTIONS ) && \\\n\t\t!( keyInfo->usageFlags & keyMatchInfo->flags ) )\n\t\treturn( FALSE );\n\n\t/* If we're searching by key ID, check whether this is the packet that \n\t   we want */\n\tif( keyMatchInfo->keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\tkeyMatchInfo->keyIDtype == CRYPT_IKEYID_PGPKEYID )\n\t\t{\n\t\treturn( matchKeyID( keyInfo, keyMatchInfo->keyID, \n\t\t\t\t\tkeyMatchInfo->keyIDlength,\n\t\t\t\t\t( keyMatchInfo->keyIDtype == CRYPT_IKEYID_PGPKEYID ) ? \\\n\t\t\t\t\t\tTRUE : FALSE ) );\n\t\t}\n\n\tREQUIRES_B( keyMatchInfo->keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t\tkeyMatchInfo->keyIDtype == CRYPT_KEYID_URI );\n\n\t/* If it's a wildcard match, return the first key */\n\tif( keyMatchInfo->keyID == NULL )\n\t\t{\n\t\tENSURES( keyMatchInfo->keyIDlength == 0 );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* We're searching by user ID, walk down the list of userIDs checking\n\t   for a match */\n\tLOOP_EXT( i = 0, i < pgpInfo->lastUserID, i++, MAX_PGP_USERIDS + 1 )\n\t\t{\n\t\t/* Check if it's the one that we want.  If it's a key with subkeys \n\t\t   and no usage type is explicitly specified this will always return \n\t\t   the main key.  This is the best solution since the main key is \n\t\t   always a signing key, which is more likely to be what the user \n\t\t   wants.  Encryption keys will typically only be accessed via \n\t\t   envelopes and the enveloping code can specify a preference of an \n\t\t   encryption-capable key, while signing keys will be read directly \n\t\t   and pushed into the envelope */\n\t\tif( strFindStr( pgpInfo->userID[ i ], pgpInfo->userIDlen[ i ],\n\t\t\t\t\t\t( char * ) keyMatchInfo->keyID, \n\t\t\t\t\t\tkeyMatchInfo->keyIDlength ) >= 0 )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Locate a key based on an ID.  This is complicated somewhat by the fact \n   that PGP groups multiple keys around the same textual ID so we have to \n   check both keys and subkeys for a possible match */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic PGP_INFO *findEntry( const PGP_INFO *pgpInfo,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int noPgpObjects,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int requestedUsage, \n\t\t\t\t\t\t\tOUT_OPT_PTR_COND PGP_KEYINFO **keyInfo )\n\t{\n\tCONST_INIT_STRUCT_4( KEY_MATCH_INFO keyMatchInfo, \\\n\t\t\t\t\t\t keyIDtype, keyID, keyIDlength, requestedUsage );\n\tint i, LOOP_ITERATOR;\n\n\tCONST_SET_STRUCT( keyMatchInfo.keyIDtype = keyIDtype; \\\n\t\t\t\t\t  keyMatchInfo.keyID = keyID; \\\n\t\t\t\t\t  keyMatchInfo.keyIDlength = keyIDlength; \\\n\t\t\t\t\t  keyMatchInfo.flags = requestedUsage );\n\n\tassert( isReadPtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\tassert( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( keyInfo == NULL || \\\n\t\t\tisWritePtr( keyInfo, sizeof( PGP_KEYINFO * ) ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( noPgpObjects ) );\n\tREQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t\tkeyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_PGPKEYID );\n\tREQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t\t( keyID != NULL && \\\n\t\t\t\t  keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES_N( isFlagRangeZ( requestedUsage, KEYMGMT ) );\n\tREQUIRES_N( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t\tKEYMGMT_MASK_USAGEOPTIONS );\n\n\t/* Clear return value */\n\tif( keyInfo != NULL )\n\t\t*keyInfo = NULL;\n\n\tLOOP_MED( i = 0, i < noPgpObjects, i++ )\n\t\t{\n\t\tconst PGP_INFO *pgpInfoPtr = &pgpInfo[ i ];\n\n\t\t/* If there's no entry at this position, continue */\n\t\tif( pgpInfoPtr->keyData == NULL )\n\t\t\tcontinue;\n\n\t\tENSURES_N( sanityCheckPGP( pgpInfoPtr ) );\n\n\t\tif( pgpCheckKeyMatch( pgpInfoPtr, &pgpInfoPtr->key,\n\t\t\t\t\t\t\t  &keyMatchInfo ) )\n\t\t\t{\n\t\t\tif( keyInfo != NULL )\n\t\t\t\t*keyInfo = ( PGP_KEYINFO * ) &pgpInfoPtr->key;\n\t\t\treturn( ( PGP_INFO * ) pgpInfoPtr );\n\t\t\t}\n\t\tif( pgpCheckKeyMatch( pgpInfoPtr, &pgpInfoPtr->subKey,\n\t\t\t\t\t\t\t  &keyMatchInfo ) )\n\t\t\t{\n\t\t\tif( keyInfo != NULL )\n\t\t\t\t*keyInfo = ( PGP_KEYINFO * ) &pgpInfoPtr->subKey;\n\t\t\treturn( ( PGP_INFO * ) pgpInfoPtr );\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tGet a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read key data from a PGP keyring */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tIN_OPT void *auxInfo, \n\t\t\t\t\t\t\tINOUT_OPT int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tCRYPT_CONTEXT iDecryptionKey DUMMY_INIT, iLocalContext;\n\tCRYPT_KEYID_TYPE localKeyIDtype = keyIDtype;\n\tPGP_INFO *pgpInfo = DATAPTR_GET( keysetInfoPtr->keyData ), *pgpInfoPtr;\n\tPGP_KEYINFO *keyInfo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE localKeyIDbuffer[ PGP_KEYID_SIZE + 8 ];\n\tconst void *localKeyID = keyID;\n\tconst int auxInfoMaxLength = *auxInfoLength;\n\tint localKeyIDlength = keyIDlength;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( auxInfo, auxInfoMaxLength ) );\n\t\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC || \n\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \\\n\t\t\t  ( auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( *auxInfoLength ) ) );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( pgpInfo != NULL );\n\n\t/* Clear return value */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* PGP keys are also identified by hex key IDs alongside standard \n\t   identifiers, of the form \"0x[16 digits]\".  To deal with these we try \n\t   and recognise a CRYPT_KEYID_NAME that's actually a keyID and convert \n\t   it to a CRYPT_IKEYID_PGPKEYID */\n\tif( ( keyIDtype == CRYPT_KEYID_NAME ) && \\\n\t\t( keyIDlength == 2 + ( 2 * PGP_KEYID_SIZE ) ) && \\\n\t\t!memcmp( keyID, \"0x\", 2 ) )\n\t\t{\n\t\tconst BYTE *keyIDptr = ( ( BYTE * ) keyID ) + 2;\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Read the PGP keyID a byte at a time */\n\t\tLOOP_EXT( i = 0, i < PGP_KEYID_SIZE, i++, PGP_KEYID_SIZE + 1 )\n\t\t\t{\n\t\t\tint ch;\n\n\t\t\tstatus = strGetHex( keyIDptr + ( i * 2 ), 2, &ch, 0x00, 0xFF );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ARGERROR_STR1, \n\t\t\t\t\t\t( CRYPT_ARGERROR_STR1, KEYSET_ERRINFO, \n\t\t\t\t\t\t  \"Invalid OpenPGP key ID\" ) );\n\t\t\t\t}\n\t\t\tlocalKeyIDbuffer[ i ] = intToByte( ch );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\n\t\t/* Mark the updated keyID as a PGP keyID */\n\t\tlocalKeyIDtype = CRYPT_IKEYID_PGPKEYID;\n\t\tlocalKeyID = localKeyIDbuffer;\n\t\tlocalKeyIDlength = PGP_KEYID_SIZE;\n\t\t}\n\n\t/* If we're matching on the special-case key ID \"[none]\", perform a \n\t   fetch of the first matching key */\n\tif( keyIDlength == 6 && !strCompare( keyID, \"[none]\", 6 ) )\n\t\t{\n\t\tlocalKeyIDtype = CRYPT_KEYID_NAME;\n\t\tlocalKeyID = NULL;\n\t\tlocalKeyIDlength = 0;\n\t\t}\n\n\t/* Find the requested item.  This is complicated somewhat by the fact\n\t   that private keys are held in memory while public keys (which can\n\t   be arbitrarily numerous) are held on disk.  This means that the former\n\t   (and also public keys read from a private-key keyring) are found with \n\t   a quick in-memory search while the latter require a scan of the \n\t   keyring on disk */\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE )\n\t\t{\n\t\t/* Try and locate the appropriate object in the PGP collection */\n\t\tpgpInfoPtr = findEntry( pgpInfo, MAX_PGP_OBJECTS, localKeyIDtype, \n\t\t\t\t\t\t\t\tlocalKeyID, localKeyIDlength, flags, \n\t\t\t\t\t\t\t\t&keyInfo );\n\t\tif( pgpInfoPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\telse\n\t\t{\n\t\tCONST_INIT_STRUCT_4( KEY_MATCH_INFO keyMatchInfo, \\\n\t\t\t\t\t\t\t localKeyIDtype, localKeyID, localKeyIDlength, \\\n\t\t\t\t\t\t\t flags );\n\n\t\tCONST_SET_STRUCT( keyMatchInfo.keyIDtype = localKeyIDtype; \\\n\t\t\t\t\t\t  keyMatchInfo.keyID = localKeyID; \\\n\t\t\t\t\t\t  keyMatchInfo.keyIDlength = localKeyIDlength; \\\n\t\t\t\t\t\t  keyMatchInfo.flags = flags );\n\n\t\t/* Try and find the required key in the keyset.  This function works \n\t\t   in a bit of a strange way, unlike pgpReadPrivKeyring() it doesn't\n\t\t   select a specific private-key entry from data held in pgpInfo[] \n\t\t   but instead scans through an arbitrary-length stream looking for \n\t\t   a particular matching key, which it returns in pgpInfo[ 0 ].  In\n\t\t   addition since the matching key can be any of the collection of\n\t\t   physical keys associated with a single logical key, we return\n\t\t   information on the particular subkey in keyInfo */\n\t\tsseek( &keysetInfoPtr->keysetFile->stream, 0 );\n\t\tstatus = pgpScanPubKeyring( &keysetInfoPtr->keysetFile->stream,\n\t\t\t\t\t\t\t\t\tpgpInfo, &keyMatchInfo, &keyInfo, \n\t\t\t\t\t\t\t\t\tKEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\tpgpInfoPtr = pgpInfo;\t/* Key data is returned in pgpInfo[ 0 ] */\n\t\t}\n\n\t/* If it's just a check or label read, we're done */\n\tif( flags & ( KEYMGMT_FLAG_CHECK_ONLY | KEYMGMT_FLAG_LABEL_ONLY ) )\n\t\t{\n\t\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t\t{\n\t\t\tconst int userIDsize = min( pgpInfoPtr->userIDlen[ 0 ],\n\t\t\t\t\t\t\t\t\t\tauxInfoMaxLength );\n\n\t\t\tREQUIRES( isShortIntegerRangeNZ( pgpInfoPtr->userIDlen[ 0 ] ) );\n\t\t\t\n\t\t\t*auxInfoLength = userIDsize;\n\t\t\tif( auxInfo != NULL )\n\t\t\t\tmemcpy( auxInfo, pgpInfo->userID[ 0 ], userIDsize );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Set up the key to decrypt the private-key fields if necessary */\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\t/* If no password is supplied let the caller know that they need a\n\t\t   password */\n\t\tif( auxInfo == NULL )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY, \n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Need a password to decrypt the private key\" ) );\n\t\t\t}\n\n\t\t/* If the key is stored as plaintext we can't do anything with it.  \n\t\t   This is just a safety check, we never get here anyway, see the \n\t\t   comment in readSecretKeyDecryptionInfo() for details */\n\t\tif( keyInfo->cryptAlgo == CRYPT_ALGO_NONE )\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t\t/* Create a decryption context to decrypt the private key */\n\t\tstatus = createDecryptionContext( &iDecryptionKey, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  auxInfo, auxInfoMaxLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't create decryption context for private key \"\n\t\t\t\t\t  \"from user password\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Load the key into the encryption context */\n\tsetMessageCreateObjectInfo( &createInfo, keyInfo->pkcAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t\tkrnlSendNotifier( iDecryptionKey, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tiLocalContext = createInfo.cryptHandle;\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\tREQUIRES( isShortIntegerRangeNZ( pgpInfoPtr->userIDlen[ 0 ] ) );\n\n\t\tsetMessageData( &msgData, pgpInfoPtr->userID[ 0 ],\n\t\t\t\t\t\tmin( pgpInfoPtr->userIDlen[ 0 ],\n\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE ) );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyInfo->openPGPkeyID, PGP_KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyInfo->pubKeyData,\n\t\t\t\t\t\tkeyInfo->pubKeyDataLen );\n\t\tstatus = krnlSendMessage( iLocalContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData,\n\t\t\t\t\t\t\t\t  ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_PGP_PARTIAL : \\\n\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_PGP );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't recreate key from stored %s key data\",\n\t\t\t\t  ( itemType == KEYMGMT_ITEM_PRIVATEKEY ) ? \\\n\t\t\t\t\t\"private\" : \"public\" ) );\n\t\t}\n\n\t/* If it's a public key, we're done */\n\tif( itemType != KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\t*iCryptHandle = iLocalContext;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Import the encrypted key into the PKC context */\n\tsetMechanismWrapInfo( &mechanismInfo, keyInfo->privKeyData,\n\t\t\t\t\t\t  keyInfo->privKeyDataLen, NULL, 0, iLocalContext,\n\t\t\t\t\t\t  iDecryptionKey );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT, \n\t\t\t\t\t\t\t  &mechanismInfo, pgpInfoPtr->isOpenPGP ? \\\n\t\t\t\t\t\t\t\t( keyInfo->hashedChecksum ?\n\t\t\t\t\t\t\t\t  MECHANISM_PRIVATEKEYWRAP_OPENPGP : \\\n\t\t\t\t\t\t\t\t  MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD ) : \\\n\t\t\t\t\t\t\t\tMECHANISM_PRIVATEKEYWRAP_PGP2 );\n\tclearMechanismInfo( &mechanismInfo );\n\tkrnlSendNotifier( iDecryptionKey, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't unwrap private key\" ) );\n\t\t}\n\t*iCryptHandle = iLocalContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAdd a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add an item to the PGP keyring */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int flags )\n\t{\n\tconst PGP_INFO *pgpInfo = DATAPTR_GET( keysetInfoPtr->keyData );\n\tPGP_INFO *pgpInfoPtr;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBOOLEAN encryptionOnlyKey = FALSE, privkeyPresent;\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint algorithm, keyIDsize DUMMY_INIT, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( ( itemType == KEYMGMT_ITEM_PUBLICKEY && \\\n\t\t\t  password == NULL && passwordLength == 0 ) || \\\n\t\t\t( itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t\t  isReadPtrDynamic( password, passwordLength ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC );\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( ( password == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( ( itemType == KEYMGMT_ITEM_PUBLICKEY && \\\n\t\t\t\tpassword == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t\t\tpassword != NULL && passwordLength != 0 ) );\n\tREQUIRES( flags == KEYMGMT_FLAG_NONE );\n\tREQUIRES( pgpInfo != NULL );\n\n\t/* Check the object and extract ID information from it */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tkeyIDsize = msgData.length;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( ( status == CRYPT_ARGERROR_OBJECT ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tif( findEntry( pgpInfo, 1, CRYPT_IKEYID_KEYID, keyID, keyIDsize, \n\t\t\t\t   KEYMGMT_FLAG_NONE, NULL ) != NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO, \n\t\t\t\t  \"Item is already present in keyset\" ) );\n\t\t}\n\n\t/* Find out what sort of key we're trying to store */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tswitch( algorithm )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tcase CRYPT_ALGO_ECDH:\n\t\t\t\t/* If it's an encryption-only algorithm then we can only \n\t\t\t\t   store the key data but can't sign metadata */\n\t\t\t\tencryptionOnlyKey = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstatus = CRYPT_ARGERROR_NUM1;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tprivkeyPresent = checkContextCapability( cryptHandle, \n\t\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_PRIVATE );\n\n\t/* If we're adding a private key make sure that there's a context and a\n\t   password present.  Conversely if we're adding a public key make sure \n\t   that there's no password present.  The password-check has already \n\t   been performed by the kernel but we perform a second check here just \n\t   to be safe.  The private-key check can't be performed by the kernel \n\t   since it doesn't know the difference between public- and private-key \n\t   contexts */\n\tswitch( itemType )\n\t\t{\n\t\tcase KEYMGMT_ITEM_PUBLICKEY:\n\t\t\tif( password != NULL )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tbreak;\n\n\t\tcase KEYMGMT_ITEM_PRIVATEKEY:\n\t\t\tif( !privkeyPresent )\n\t\t\t\t{\n\t\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t\t\t \"Item being added doesn't contain a private \"\n\t\t\t\t\t\t\t \"key\" ) );\n\t\t\t\t}\n\t\t\tif( password == NULL )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tbreak;\n\t\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Make sure that the label of what we're adding doesn't duplicate the \n\t   label of an existing object */\n\tif( privkeyPresent )\n\t\t{\n\t\tint labelLength;\n\n\t\tsetMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tlabelLength = msgData.length;\n\t\tif( findEntry( pgpInfo, 1, CRYPT_KEYID_NAME, label, labelLength, \n\t\t\t\t\t   KEYMGMT_FLAG_NONE, NULL ) != NULL )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t\t( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Item with label '%s' is already present\",\n\t\t\t\t\t  sanitiseString( label, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  labelLength ) ) );\n\t\t\t}\n\t\t}\n\n\t/* Storing PGP private keys is quite complicated and there's no good \n\t   reason to use this format instead of PKCS #15, so for now we don't\n\t   implement it */\n\tif( itemType == KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTAVAIL, \n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, KEYSET_ERRINFO, \n\t\t\t\t  \"Storing private keys in PGP format isn't supported\" ) );\n\t\t}\n\n\t/* Find out where we can add data and what needs to be added.  This is \n\t   quite problematic because of the way that PGP creates a single \n\t   logical key out of multiple physical keys, unless two keys being \n\t   added have the same label it's not possible to tell whether they're \n\t   meant to be part of the same logical key or not.\n\t   \n\t   To deal with this we only allow a single logical key (comprising one \n\t   or more physical keys) to be added, so instead of using findEntry() \n\t   to locate a possible match we always choose the first entry */\n#if 0\n\tpgpInfoPtr = findEntry( pgpInfo, 1, ... );\n\tif( pgpInfoPtr == NULL )\n\t\t{\n\t\tpgpInfoPtr = findFreeEntry( pgpInfo, 1 );\n\t\tif( pgpInfoPtr == NULL )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, KEYSET_ERRINFO, \n\t\t\t\t\t  \"No more room in keyset to add this item\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t...\n#endif /* 0 */\n\tpgpInfoPtr = DATAPTR_GET( keysetInfoPtr->keyData );\t/* Pointer to first entry */\n\tENSURES( pgpInfoPtr != NULL );\n\tif( pgpInfoPtr->isComplete )\n\t\t{\n\t\tretExt( CRYPT_ERROR_COMPLETE, \n\t\t\t\t( CRYPT_ERROR_COMPLETE, KEYSET_ERRINFO, \n\t\t\t\t  \"No further keys can be added for this entry\" ) );\n\t\t}\n\tif( encryptionOnlyKey && pgpInfoPtr->keyData != NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO, \n\t\t\t\t  \"This entry already contains an encryption key\" ) );\n\t\t}\n\n\t/* If it's an encryption-only key then we need to save the key data away \n\t    for later use, where it'll be signed using a signature key */\n\tif( encryptionOnlyKey )\n\t\t{\n\t\tvoid *keyData;\n\t\tint keyDataSize;\n\n\t\t/* Allocate storage for the key data, write the data to the storage, \n\t\t   and remember it for later */\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_PGP );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tkeyDataSize = msgData.length;\n\t\tREQUIRES( rangeCheck( keyDataSize, 1, MAX_INTLENGTH_SHORT ) );\n\t\tif( ( keyData = clAlloc( \"setItemFunction\", keyDataSize ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tsetMessageData( &msgData, keyData, keyDataSize );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_PGP );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"setItemFunction\", keyData ); \n\t\t\treturn( status );\n\t\t\t}\n\t\tpgpInfoPtr->keyData = keyData;\n\t\tpgpInfoPtr->keyDataLen = keyDataSize;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* In order to write the key data we need to be able to bind metadata to \n\t   the main key using signatures, so we need to have been passed a \n\t   private key in order to generate the signatures */\n\tif( !privkeyPresent )\n\t\t{\n\t\tretExt( CRYPT_ARGERROR_NUM1, \n\t\t\t\t( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t  \"Key must be a private key in order to sign public \"\n\t\t\t\t  \"keyring data\" ) );\n\t\t}\n\n\t/* Write the key data and associated metadata in PGP keyring format */\n\tstatus = pgpWritePubkey( pgpInfoPtr, cryptHandle );\n\tif( cryptStatusOK( status ) )\n\t\tpgpInfoPtr->isComplete = TRUE;\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Shutdown functions */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tPGP_INFO *pgpInfo;\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC || \n\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );\n\n\t/* If there's no PGP key information present, we're done */\n\tif( DATAPTR_ISNULL( keysetInfoPtr->keyData ) )\n\t\treturn( CRYPT_OK );\n\n\tpgpInfo = DATAPTR_GET( keysetInfoPtr->keyData );\n\tENSURES( pgpInfo != NULL );\n\n\t/* If the contents have been changed, commit the changes to disk */\n\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY ) )\n\t\t{\n\t\tSTREAM *stream = &keysetInfoPtr->keysetFile->stream;\n\t\tBYTE buffer[ SAFEBUFFER_SIZE( STREAM_BUFSIZE ) + 8 ] STACK_ALIGN_DATA;\n\n\t\tsseek( stream, 0 );\n\t\tmemset( buffer, 0, STREAM_BUFSIZE );\n\t\t\t\t/* Keep static analysers happy */\n\t\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tsioctlSetString( stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t\t SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tstatus = swrite( stream, pgpInfo->keyData, pgpInfo->keyDataLen );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sflush( stream );\n\t\tsioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );\n\t\t}\n\n\t/* Free the cached key information */\n\tif( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_EXT( i = 0, i < MAX_PGP_OBJECTS, i++, MAX_PGP_OBJECTS + 1 )\n\t\t\tpgpFreeEntry( &pgpInfo[ i ] );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\telse\n\t\tpgpFreeEntry( pgpInfo );\n\tclFree( \"shutdownFunction\", pgpInfo );\n\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\tkeysetInfoPtr->keyDataSize = 0;\n\n\treturn( status );\n\t}\n\n/* PGP public keyrings can be arbitrarily large so we don't try to do any\n   preprocessing, all we do at this point is allocate the key information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initPublicFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t   STDC_UNUSED const char *name,\n\t\t\t\t\t\t\t   STDC_UNUSED const int nameLength,\n\t\t\t\t\t\t\t   IN_ENUM( CRYPT_KEYOPT ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_KEYOPT_TYPE options )\n\t{\n\tPGP_INFO *pgpInfo;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC );\n\tREQUIRES( name == NULL && nameLength == 0 );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\n\t/* Allocate memory for the key information.  Since we're just scanning \n\t   the keyring for a single matching key or writing a single key, we \n\t   only need to allocate room for one entry.  If we're reading the \n\t   keyring we also need to allocate a read buffer */\n\tif( ( pgpInfo = clAlloc( \"initPublicFunction\", \\\n\t\t\t\t\t\t\t sizeof( PGP_INFO ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( pgpInfo, 0, sizeof( PGP_INFO ) );\n\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t{\n\t\tif( ( pgpInfo->keyData = clAlloc( \"initPublicFunction\", \\\n\t\t\t\t\t\t\t\t\t\t  KEYRING_BUFSIZE ) ) == NULL )\n\t\t\t{\n\t\t\tclFree( \"initPublicFunction\", pgpInfo );\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tpgpInfo->keyDataLen = KEYRING_BUFSIZE;\n\t\t}\n\tDATAPTR_SET( keysetInfoPtr->keyData, pgpInfo );\n\tkeysetInfoPtr->keyDataSize = sizeof( PGP_INFO );\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* A PGP private keyring can contain multiple keys and whatnot so when we\n   open it we scan it and record various pieces of information about it that \n   we can use later when we need to access it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initPrivateFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t\t\tSTDC_UNUSED const char *name,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const int nameLength,\n\t\t\t\t\t\t\t\tIN_ENUM( CRYPT_KEYOPT ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_KEYOPT_TYPE options )\n\t{\n\tPGP_INFO *pgpInfo;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE );\n\tREQUIRES( name == NULL && nameLength == 0 );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\n\t/* Allocate the PGP object information */\n\tif( ( pgpInfo = clAlloc( \"initPrivateFunction\", \\\n\t\t\t\t\t\t\t sizeof( PGP_INFO ) * MAX_PGP_OBJECTS ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( pgpInfo, 0, sizeof( PGP_INFO ) * MAX_PGP_OBJECTS );\n\tDATAPTR_SET( keysetInfoPtr->keyData, pgpInfo );\n\tkeysetInfoPtr->keyDataSize = sizeof( PGP_INFO ) * MAX_PGP_OBJECTS;\n\n\t/* If this is a newly-created keyset, there's nothing left to do */\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\treturn( CRYPT_OK );\n\n\t/* Read all of the keys in the keyring */\n\tstatus = pgpReadPrivKeyring( &keysetInfoPtr->keysetFile->stream, \n\t\t\t\t\t\t\t\t pgpInfo, MAX_PGP_OBJECTS, KEYSET_ERRINFO );\n\tif( status == OK_SPECIAL )\n\t\t{\n\t\t/* We couldn't process one or more packets, make the keyset read-\n\t\t   only to ensure that the incomplete key data isn't written to \n\t\t   disk */\n\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_READONLY );\n\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tshutdownFunction( keysetInfoPtr );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodPGPPublic( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC || \n\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initPublicFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodPGPPrivate( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  ( keysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PUBLIC || \n\t\t\t\tkeysetInfoPtr->subType == KEYSET_SUBTYPE_PGP_PRIVATE ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initPrivateFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGPKEYS */\n"
  },
  {
    "path": "deps/cl345/keyset/pgp_key.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPGP Keyset Definitions Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _PGPKEY_DEFINED\n\n#define _PGPKEY_DEFINED\n\n#ifndef _PGP_DEFINED\n  #if defined( INC_ALL )\n\t#include \"pgp.h\"\n  #else\n\t#include \"misc/pgp.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _PGP_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPGP Keyring Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Each PGP key can contain an arbitrary number of user IDs, we only track\n   the following maximum number.  Further IDs are read and stored, but not\n   indexed or searched on */\n\n#define MAX_PGP_USERIDS\t\t16\n\n/* When reading a PGP keyring we implement a sliding window that reads a\n   certain amount of data into a lookahead buffer and then tries to identify\n   a key packet group in the buffer.  The following value determines the size\n   of the lookahead.  Unfortunately we have to keep this above a certain\n   minimum size in order to handle PGP 8.x's inclusion of photo IDs in \n   keyrings, which means that the smallest size that we can safely use is \n   about 8kb */\n\n#define KEYRING_BUFSIZE\t\t8192\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPGP Keyring Types and Structures\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key-related information needed to create a cryptlib context from PGP key\n   data */\n\ntypedef struct {\n\t/* Key data information */\n\tCRYPT_ALGO_TYPE pkcAlgo;\t\t/* Key algorithm */\n\tCRYPT_ECCCURVE_TYPE curveType;\t/* Curve type for ECC */\n\tint usageFlags;\t\t\t\t\t/* Keymgmt flags permitted usage */\n\tBUFFER_FIXED( PGP_KEYID_SIZE ) \\\n\tBYTE pgp2KeyID[ PGP_KEYID_SIZE + 8 ];\n\tBUFFER_FIXED( PGP_KEYID_SIZE ) \\\n\tBYTE openPGPkeyID[ PGP_KEYID_SIZE + 8 ];\n\tBUFFER_FIXED( pubKeyDataLen ) \\\n\tvoid *pubKeyData;\n\tBUFFER_OPT_FIXED( privKeyDataLen ) \\\n\tvoid *privKeyData;\t/* Pointer to encoded pub/priv key data */\n\tint pubKeyDataLen, privKeyDataLen;\n\n\t/* Key data protection information */\n\tCRYPT_ALGO_TYPE cryptAlgo;\t\t/* Key wrap algorithm */\n\tint cryptAlgoParam;\t\t\t\t/* Optional parameter for key wrap algo */\n\tBUFFER( CRYPT_MAX_IVSIZE, ivSize ) \\\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];/* Key wrap IV */\n\tint ivSize;\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t/* Password hashing algo */\n\tint hashAlgoParam;\t\t\t\t/* Optional parameter for hash algo */\n\tBUFFER( PGP_SALTSIZE, saltSize ) \\\n\tBYTE salt[ PGP_SALTSIZE + 8 ];\t/* Password hashing salt */\n\tint saltSize;\n\tint keySetupIterations;\t\t\t/* Password hashing iterations */\n\tBOOLEAN hashedChecksum;\t\t\t/* Key checksum is SHA-1 hash */\n\t} PGP_KEYINFO;\n\n/* The following structure contains the the information for one personality,\n   which covers one or more of a private key, public key, and subkeys.  PGP\n   encodes keys in a complex manner by writing them as groups of (implicitly)\n   connected packets that require arbitrary amounts of lookahead to parse.  \n   To handle this we read the overall encoded key data as a single unit and\n   store it in a dynamically-allocated buffer, then set up pointers to\n   locations of relevant data (public and private keys and user IDs) within\n   the overall key data.  To further complicate matters, there can be a key\n   and subkey associated with the same information, so we have to maintain\n   two lots of physical keying information for each logical key.\n   \n   Writing keys is no easier, because a single logical key can consist of \n   one or more keys and subkeys we can potentially need to add data from \n   multiple contexts to produce a single logical key.  We restrict what can\n   be added to a single signature+encryption key or a signature key with an\n   encryption key as a subkey.  The isComplete flag records whether further\n   key data can be added or not */\n\ntypedef struct {\n\t/* Key and subkey data */\n\tBUFFER_FIXED( keyDataLen ) \\\n\tvoid *keyData;\t\t\t\t\t/* Encoded key data */\n\tint keyDataLen;\n\tPGP_KEYINFO key, subKey;\t\t/* Key and subkey information */\n\n\t/* User ID(s) */\n\tARRAY( MAX_PGP_USERIDS, lastUserID ) \\\n\tchar *userID[ MAX_PGP_USERIDS + 8 ];/* UserIDs */\n\tARRAY( MAX_PGP_USERIDS, lastUserID ) \\\n\tint userIDlen[ MAX_PGP_USERIDS + 8 ];\n\tint lastUserID;\t\t\t\t\t/* Last used userID */\n\n\t/* Miscellaneous data */\n\tBOOLEAN isOpenPGP;\t\t\t\t/* Whether data is PGP 2.x or OpenPGP */\n\tBOOLEAN isComplete;\t\t\t\t/* Whether all key information is present */\n\t} PGP_INFO;\n\n#define resetPGPInfo( pgpInfo ) \\\n\t\tmemset( &( pgpInfo )->key, 0, sizeof( PGP_KEYINFO ) ); \\\n\t\tmemset( &( pgpInfo )->subKey, 0, sizeof( PGP_KEYINFO ) ); \\\n\t\tmemset( ( pgpInfo )->userID, 0, sizeof( char * ) * MAX_PGP_USERIDS ); \\\n\t\tmemset( ( pgpInfo )->userIDlen, 0, sizeof( int ) * MAX_PGP_USERIDS ); \\\n\t\t( pgpInfo )->lastUserID = 0; \\\n\t\t( pgpInfo )->isOpenPGP = ( pgpInfo )->isComplete = FALSE\n\n/* When we're searching for a key, we need to compare each one against a\n   collection of match criteria.  The following structure contains the \n   information that we match against */\n\ntypedef struct {\n\tCONST_INIT CRYPT_KEYID_TYPE keyIDtype;/* Key ID type */\n\tBUFFER_FIXED( keyIDlength ) \\\n\tconst void *keyID;\n\tCONST_INIT int keyIDlength;\t\t/* Key ID */\n\tCONST_INIT int flags;\t\t\t/* Key usage flags */\n\t} KEY_MATCH_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Keyring Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Utility functions in pgp.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pgpFreeEntry( INOUT PGP_INFO *pgpInfo );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nBOOLEAN pgpCheckKeyMatch( const PGP_INFO *pgpInfo, \n\t\t\t\t\t\t  const PGP_KEYINFO *keyInfo, \n\t\t\t\t\t\t  const KEY_MATCH_INFO *keyMatchInfo );\n\n/* Prototypes for functions in pgp_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nint pgpScanPubKeyring( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT PGP_INFO *pgpInfo, \n\t\t\t\t\t   const KEY_MATCH_INFO *keyMatchInfo,\n\t\t\t\t\t   OUT_PTR_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,\n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint pgpReadPrivKeyring( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ARRAY( maxNoPgpObjects ) PGP_INFO *pgpInfo, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxNoPgpObjects,\n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pgp_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWritePubkey( INOUT PGP_INFO *pgpInfoPtr,\n\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle );\n\n#endif /* _PGPKEY_DEFINED */\n"
  },
  {
    "path": "deps/cl345/keyset/pgp_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib PGP Key Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"keyset.h\"\n  #include \"pgp_key.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pgp_key.h\"\n#endif /* Compiler-specific includes */\n\n/* Make sure that the maximum number of PGP userIDs that we record is less\n   than the failsafe bound on the loop that reads userIDs */\n\n#if MAX_PGP_USERIDS >= FAILSAFE_ITERATIONS_MED\n  #error MAX_PGP_USERIDS must be less than FAILSAFE_ITERATIONS_MED since this is used to bound loops\n#endif /* MAX_PGP_USERIDS >= FAILSAFE_ITERATIONS_MED */\n\n#ifdef USE_PGPKEYS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the size of an encoded MPI and skip the payload data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int getMPIsize( INOUT STREAM *stream, \n\t\t\t\t\t   IN_LENGTH_PKC const int minMpiSize, \n\t\t\t\t\t   IN_LENGTH_PKC const int maxMpiSize,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *length )\n\t{\n\tconst int position = stell( stream );\n\tint dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( minMpiSize > 0 && maxMpiSize > 0 && \\\n\t\t\t  minMpiSize <= maxMpiSize && maxMpiSize <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( !cryptStatusError( position ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\t\n\tstatus = readInteger16Ubits( stream, NULL, &dummy, minMpiSize, \n\t\t\t\t\t\t\t\t maxMpiSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*length = stell( stream ) - position;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Determine the minimum allowed packet size for a given packet type.  The \n   minimum-length packet that we can encounter is a single-byte trust \n   packet, then two bytes for a userID, and three bytes for a marker \n   packet.  Other than that all packets must be at least eight bytes in \n   length */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, 8 ) \\\nstatic int getMinPacketSize( IN_BYTE const int packetType )\n\t{\n\tENSURES_EXT( ( packetType >= 0 && \\\n\t\t\t\t   packetType <= 0xFF ), 0 );\n\t\t\t\t /* This could be any packet type including new values not\n\t\t\t\t    covered by the PGP_PACKET_TYPE range so we can't be too\n\t\t\t\t\tpicky about values */\n\n\treturn( ( packetType == PGP_PACKET_TRUST ) ? 1 : \\\n\t\t\t( packetType == PGP_PACKET_USERID ) ? 2 : \\\n\t\t\t( packetType == PGP_PACKET_MARKER ) ? 3 : 8 );\n\t}\n\n/* Scan a sequence of key packets to find the extent of the packet group */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int scanPacketGroup( INOUT STREAM *stream,\n\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( totalLength ) \\\n\t\t\t\t\t\t\t\tint *packetGroupLength,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int totalLength )\n\t{\n\tBOOLEAN firstPacket = TRUE;\n\tint endPos, noPackets, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetGroupLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( totalLength ) );\n\n\t/* Clear return value */\n\t*packetGroupLength = 0;\n\n\tLOOP_MED( ( endPos = 0, noPackets = 0 ), \n\t\t\t  endPos < totalLength && noPackets < 32, noPackets++ )\n\t\t{\n\t\tlong length;\n\t\tint ctb, type;\n\n\t\t/* Get the next CTB */\n\t\tstatus = ctb = sPeek( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !( pgpIsCTB( ctb ) ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t/* Check the packet type and make sure that it's valid.  This also\n\t\t   catches odd things like compressed-data packets, which aren't\n\t\t   indefinite-length but also don't really have a length so that we \n\t\t   can't skip them.  These shouldn't be present in keyrings anyway, \n\t\t   but can crop up due to data corruption */\n\t\ttype = pgpGetPacketType( ctb );\n\t\tif( type != PGP_PACKET_SIGNATURE && type != PGP_PACKET_SECKEY && \\\n\t\t\ttype != PGP_PACKET_PUBKEY && type != PGP_PACKET_SECKEY_SUB && \\\n\t\t\ttype != PGP_PACKET_MARKER && type != PGP_PACKET_TRUST && \\\n\t\t\ttype != PGP_PACKET_USERID && type != PGP_PACKET_PUBKEY_SUB && \\\n\t\t\ttype != PGP_PACKET_USERATTR )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Encountered invalid keyring packet type %d\", type ));\n\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tif( firstPacket )\n\t\t\t{\n\t\t\t/* Make sure that the packet group starts with the expected \n\t\t\t   packet type */\n\t\t\tif( type != PGP_PACKET_PUBKEY && type != PGP_PACKET_SECKEY )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tfirstPacket = FALSE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If we've found the start of a new packet group, we're done */\n\t\t\tif( type == PGP_PACKET_PUBKEY || type == PGP_PACKET_SECKEY )\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Skip the current packet in the buffer */\n\t\tstatus = pgpReadPacketHeader( stream, NULL, &length, \n\t\t\t\t\t\t\t\t\t  getMinPacketSize( type ),\n\t\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tendPos = stell( stream );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noPackets >= 32 )\n\t\t{\n\t\t/* If we've found this many packets in a row all supposedly \n\t\t   belonging to the same key then there's something wrong */\n\t\tDEBUG_DIAG(( \"Encountered more than %d packets for a single key\", \n\t\t\t\t\t noPackets ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Remember where the current packet group ends */\n\t*packetGroupLength = endPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tProcess Key Packet Components\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the information needed to decrypt a private key */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPrivateKeyDecryptionInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\t INOUT PGP_KEYINFO *keyInfo )\n\t{\n\tCRYPT_QUERY_INFO queryInfo;\n\tconst int ctb = sgetc( stream );\n\tint ivSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\n\t/* Clear return values */\n\tkeyInfo->cryptAlgo = keyInfo->hashAlgo = CRYPT_ALGO_NONE;\n\tkeyInfo->saltSize = keyInfo->keySetupIterations = 0;\n\n\t/* Before we go any further make sure that we were at least able to read \n\t   the CTB */\n\tif( cryptStatusError( ctb ) )\n\t\treturn( ctb );\n\n\t/* If no encryption is being used we mark the key as unusable.  This \n\t   isn't exactly the correct thing to do, but storing plaintext private \n\t   keys on disk is extremely dangerous and we probably shouldn't be\n\t   using them, and in any case an attempt to import an unencrypted key \n\t   will trigger so many security check failures in the key unwrap code \n\t   that it's not even worth trying */\n\tif( ctb == 0 )\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\n#ifdef USE_PGP2\n\t/* If it's a direct algorithm specifier then it's a PGP 2.x packet with \n\t   raw IDEA encryption */\n\tif( ctb == PGP_ALGO_IDEA )\n\t\t{\n\t\tkeyInfo->cryptAlgo = CRYPT_ALGO_IDEA;\n\t\tkeyInfo->hashAlgo = CRYPT_ALGO_MD5;\n\t\tstatus = sread( stream, keyInfo->iv, 8 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tkeyInfo->ivSize = 8;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_PGP2 */\n\n\t/* Must be an S2K specifier */\n\tif( ctb != PGP_S2K && ctb != PGP_S2K_HASHED )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Get the key wrap algorithm and S2K information */\n\tstatus = readPgpAlgo( stream, &keyInfo->cryptAlgo, \n\t\t\t\t\t\t  &keyInfo->cryptAlgoParam, PGP_ALGOCLASS_PWCRYPT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If it's an unknown algorithm type, skip this packet */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\treturn( OK_SPECIAL );\n\n\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,\n\t\t\t\t\t\t\t  keyInfo->cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tivSize = queryInfo.blockSize;\n\tstatus = readPgpS2K( stream, &keyInfo->hashAlgo, &keyInfo->hashAlgoParam, \n\t\t\t\t\t\t keyInfo->salt, PGP_SALTSIZE, &keyInfo->saltSize, \n\t\t\t\t\t\t &keyInfo->keySetupIterations );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If it's an unknown algorithm type, skip this packet */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\treturn( OK_SPECIAL );\n\n\t\treturn( status );\n\t\t}\n\tif( ctb == PGP_S2K_HASHED )\n\t\t{\n\t\t/* The legacy PGP 2.x key integrity protection format used a simple \n\t\t   16-bit additive checksum of the encrypted MPI payload, the newer \n\t\t   OpenPGP format uses a SHA-1 MDC.  There's also a halfway format \n\t\t   used in older OpenPGP versions that still uses the 16-bit \n\t\t   checksum but encrypts the entire MPI data block rather than just \n\t\t   the payload */\n\t\tkeyInfo->hashedChecksum = TRUE;\n\t\t}\n\tstatus = sread( stream, keyInfo->iv, ivSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tkeyInfo->ivSize = ivSize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read public-key components */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readRSAKeyComponents( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT PGP_KEYINFO *keyInfo,\n\t\t\t\t\t\t\t\t OUT_INT_Z int *pubKeyComponentLength )\n\t{\n\tint length, totalLength = 1, status;\n\t\t\t\t/* Initial length 1 is for the algorithm ID byte */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isWritePtr( pubKeyComponentLength, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*pubKeyComponentLength = 0;\n\n\t/* Read RSA n + e.  The LSBs of n serve as the PGP 2.x key ID so we copy \n\t   the data out if PGP 2.x support is enabled */\n\tstatus = getMPIsize( stream, MIN_PKCSIZE, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t &length );\t\t\t/* n */\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalLength += length;\n\t\n#ifdef USE_PGP2\n\t/* Move back and copy out the last PGP_KEYID_SIZE bytes of n as the PGP \n\t   2.x key ID */\n\tstatic_assert( PGP_KEYID_SIZE < MIN_PKCSIZE, \"PGP keyID size\" );\n\tstatus = sseek( stream, stell( stream ) - PGP_KEYID_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sread( stream, keyInfo->pgp2KeyID, PGP_KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#endif /* USE_PGP2 */\n\tstatus = getMPIsize( stream, 1, CRYPT_MAX_PKCSIZE, &length );\n\tif( cryptStatusError( status ) )\t\t/* e */\n\t\treturn( status );\n\t*pubKeyComponentLength = totalLength + length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readDLPKeyComponents( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT PGP_KEYINFO *keyInfo,\n\t\t\t\t\t\t\t\t OUT_INT_Z int *pubKeyComponentLength )\n\t{\n\tint length, totalLength = 1, status;\n\t\t\t\t/* Initial length 1 is for the algorithm ID byte */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isWritePtr( pubKeyComponentLength, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*pubKeyComponentLength = 0;\n\n\t/* DSA/Elgamal: p + g + y */\n\tstatus = getMPIsize( stream, MIN_PKCSIZE, CRYPT_MAX_PKCSIZE, &length );\t\n\tif( cryptStatusOK( status ) )\t\t\t\t/* p */\n\t\t{\n\t\ttotalLength += length;\n\t\tstatus = getMPIsize( stream, 1, CRYPT_MAX_PKCSIZE, &length );\n\t\t}\t\t\t\t\t\t\t\t\t\t/* g */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttotalLength += length;\n\t\tstatus = getMPIsize( stream, MIN_PKCSIZE, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t &length );\t\t\t/* y */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalLength += length;\n\tif( keyInfo->pkcAlgo ==  CRYPT_ALGO_DSA )\n\t\t{\n\t\t/* DSA has q as well */\n\t\tstatus = getMPIsize( stream, bitsToBytes( 155 ), CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t &length );\t\t\t/* q */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\ttotalLength += length;\n\t\t}\n\t*pubKeyComponentLength = totalLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readECCKeyComponents( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT PGP_KEYINFO *keyInfo,\n\t\t\t\t\t\t\t\t OUT_INT_Z int *pubKeyComponentLength )\n\t{\n\tint length, totalLength = 2, status;\n\t\t\t\t/* Initial len.2 is for the algorithm ID and OID len.byte */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isWritePtr( pubKeyComponentLength, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*pubKeyComponentLength = 0;\n\n\t/* Skip the ECC OID, which is preceded by a length byte */\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_OID_SIZE || length >= MAX_OID_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sSkip( stream, length, MAX_OID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalLength += length;\n\n\t/* ECC: qx/qy as an ECC point */\n\tstatus = getMPIsize( stream, MIN_PKCSIZE_ECCPOINT, \n\t\t\t\t\t\t CRYPT_MAX_PKCSIZE_ECC, &length );\t\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalLength += length;\n\n\t/* If we're reading an ECDSA key, we're done */\n\tif( keyInfo->pkcAlgo == CRYPT_ALGO_ECDSA )\n\t\t{\n\t\t*pubKeyComponentLength = totalLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* ECDH keys are followed by further data that has nothing to do with \n\t   ECDH but that's stuffed in with the key for no obvious reason */\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length != 3 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sSkip( stream, 3, 3 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*pubKeyComponentLength = totalLength + 1 + length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPublicKeyComponents( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT PGP_KEYINFO *keyInfo,\n\t\t\t\t\t\t\t\t\tOUT_INT_Z int *pubKeyComponentLength )\n\t{\n\tint pgpPkcAlgo, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyInfo, sizeof( PGP_KEYINFO ) ) );\n\tassert( isWritePtr( pubKeyComponentLength, sizeof( int ) ) );\n\n\t/* Clear return value */\n\t*pubKeyComponentLength = 0;\n\n\t/* Get the public-key algorithm type */\n\tstatus = pgpPkcAlgo = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the algorithm info and read the key components */\n\tswitch( pgpPkcAlgo )\n\t\t{\n\t\tcase PGP_ALGO_RSA:\n\t\tcase PGP_ALGO_RSA_ENCRYPT:\n\t\tcase PGP_ALGO_RSA_SIGN:\n\t\t\tkeyInfo->pkcAlgo = CRYPT_ALGO_RSA;\n\t\t\tif( pgpPkcAlgo != PGP_ALGO_RSA_SIGN )\n\t\t\t\tkeyInfo->usageFlags = KEYMGMT_FLAG_USAGE_CRYPT;\n\t\t\tif( pgpPkcAlgo != PGP_ALGO_RSA_ENCRYPT )\n\t\t\t\tkeyInfo->usageFlags |= KEYMGMT_FLAG_USAGE_SIGN;\n\t\t\treturn( readRSAKeyComponents( stream, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  pubKeyComponentLength ) );\n\n\t\tcase PGP_ALGO_DSA:\n\t\t\tkeyInfo->pkcAlgo = CRYPT_ALGO_DSA;\n\t\t\tkeyInfo->usageFlags = KEYMGMT_FLAG_USAGE_SIGN;\n\t\t\treturn( readDLPKeyComponents( stream, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  pubKeyComponentLength ) );\n\n\t\tcase PGP_ALGO_ELGAMAL:\n\t\t\tkeyInfo->pkcAlgo = CRYPT_ALGO_ELGAMAL;\n\t\t\tkeyInfo->usageFlags = KEYMGMT_FLAG_USAGE_CRYPT;\n\t\t\treturn( readDLPKeyComponents( stream, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  pubKeyComponentLength ) );\n\n\t\tcase PGP_ALGO_ECDH:\n\t\t\tkeyInfo->pkcAlgo = CRYPT_ALGO_ECDH;\n\t\t\tkeyInfo->usageFlags = KEYMGMT_FLAG_USAGE_CRYPT;\n\t\t\treturn( readECCKeyComponents( stream, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  pubKeyComponentLength ) );\n\n\t\tcase PGP_ALGO_ECDSA:\n\t\t\tkeyInfo->pkcAlgo = CRYPT_ALGO_ECDSA;\n\t\t\tkeyInfo->usageFlags = KEYMGMT_FLAG_USAGE_SIGN;\n\t\t\treturn( readECCKeyComponents( stream, keyInfo, \n\t\t\t\t\t\t\t\t\t\t  pubKeyComponentLength ) );\n\n\t\tdefault:\n\t\t\t/* It's an unknown algorithm, skip this key */\n\t\t\treturn( OK_SPECIAL );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Read a sequence of userID packets */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readUserID( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT_OPT PGP_INFO *pgpInfo )\n\t{\n\tlong packetLength;\n\tint ctb, packetType DUMMY_INIT, noPackets;\n\tint status DUMMY_INIT, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( pgpInfo == NULL || \\\n\t\t\tisWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\n\tENSURES( pgpInfo == NULL || \\\n\t\t\t ( pgpInfo->lastUserID >= 0 && \\\n\t\t\t   pgpInfo->lastUserID <= MAX_PGP_USERIDS ) );\n\n\t/* Skip keyring trust packets, signature packets, and any private \n\t   packets (GPG uses packet type 61, which might be a DSA self-\n\t   signature).\n\n\t   PGP has two ways of indicating key usage, either directly via the key \n\t   type (e.g. PGP_ALGO_RSA_ENCRYPT vs. PGP_ALGO_RSA_SIGN) or in a rather \n\t   schizophrenic manner in signature packets by allowing the signer to \n\t   specify an X.509-style key usage.  Since it can appear in both self-\n\t   sigs and certification signatures, the exact usage for a key is \n\t   somewhat complex to determine as a certification signer could \n\t   indicate that they trust the key when it's used for signing while a \n\t   self-signer could indicate that the key should be used for \n\t   encryption.  This appears to be a preference indication rather than a \n\t   hard limit like the X.509 keyUsage and also contains other odds and \n\t   ends as well such as key splitting indicators.  For now we don't make \n\t   use of these flags as it's a bit difficult to figure out what's what, \n\t   and in any case DSA vs. Elgamal doesn't need any further constraints \n\t   since there's only one usage possible */\n\tLOOP_MED( noPackets = 0, noPackets < 32, noPackets++ )\n\t\t{\n\t\t/* See what we've got.  If we've run out of input due to reading the \n\t\t   end of the packet group or it's a non-key-related packet, we're \n\t\t   done */\n\t\tstatus = ctb = sPeek( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tpacketType = pgpGetPacketType( ctb );\n\t\tif( packetType != PGP_PACKET_TRUST && \\\n\t\t\tpacketType != PGP_PACKET_SIGNATURE && \\\n\t\t\tpacketType != PGP_PACKET_USERATTR && \\\n\t\t\t!pgpIsReservedPacket( packetType ) )\n\t\t\tbreak;\n\n\t\t/* Skip the packet */\n\t\tstatus = pgpReadPacketHeader( stream, &ctb, &packetLength, \n\t\t\t\t\t\t\t\t\t  getMinPacketSize( packetType ),\n\t\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!isShortIntegerRangeNZ( packetLength ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sSkip( stream, packetLength, MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Running out of input due to reading the end of the packet group \n\t\t   is a valid condition so we don't return a fatal error code if \n\t\t   this occurss */\n\t\treturn( ( status == CRYPT_ERROR_UNDERFLOW ) ? OK_SPECIAL : status );\n\t\t}\n\tif( noPackets >= 32 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If we've reached the end of the current collection of key packets, \n\t   let the caller know that we're done */\n\tif( packetType != PGP_PACKET_USERID )\n\t\treturn( OK_SPECIAL );\n\n\t/* Record the userID (unless we're skipping the packet).  If there are \n\t   more userIDs than we can record then we silently ignore them.  This \n\t   handles keys with weird numbers of userIDs without rejecting them \n\t   just because they have, well, a weird number of userIDs */\n\tstatus = pgpReadPacketHeader( stream, &ctb, &packetLength, \n\t\t\t\t\t\t\t\t  getMinPacketSize( packetType ), 1024 );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( packetLength ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( pgpInfo != NULL && pgpInfo->lastUserID < MAX_PGP_USERIDS )\n\t\t{\n\t\tvoid *dataPtr;\n\n\t\tREQUIRES( isIntegerRange( packetLength ) );\n\t\tstatus = sMemGetDataBlock( stream, &dataPtr, packetLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpgpInfo->userID[ pgpInfo->lastUserID ] = dataPtr;\n\t\tpgpInfo->userIDlen[ pgpInfo->lastUserID++ ] = ( int ) packetLength;\n\t\t}\n\treturn( sSkip( stream, packetLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tRead a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a single key in a group of key packets.  A packet group consists of \n   a jumble of packets concatenated together following a primary key with \n   the jumble continuing until we encounter another primary key, which is \n   why we need the auxiliary scanPacketGroup() function to look ahead in the\n   data stream to determine when to stop.  A typical set of packets might be:\n\n\tDSA key\n\tUserID\n\tBinding signature of DSA key and UserID\n\tTrust rating\n\tElgamal subkey\n\tBinding signature of DSA key and Elgamal subkey\n\tTrust rating\n\n   but almost anything else is possible, there can be arbitrary further \n   userIDs, keys, and other data floating around, all glued together in \n   various locations with binding signatures (or possibly not, since the\n   signatures are optional).\n\n   All of this is read into memory in a PGP_INFO structure with the \n   encoded data retained as follows:\n\n\tpgpInfo[ index ]->keyData\t\t\t= entire packet group\n\t\t\t\t\t->key->pubKeyData\t= DSA/RSA pubkey payload\n\t\t\t\t\t->key->privKeyData\t= DSA/RSA privkey payload (without\n\t\t\t\t\t\t\t\t\t\t  decryption information, which is\n\t\t\t\t\t\t\t\t\t\t  stored separately)\n\t\t\t\t\t->subKey->pubKeyData= Elgamal pubkey payload\n\t\t\t\t\t->subKey->privKeyData=Elgamal privkey as before.\n\n   This tries to simplify things somewhat because in practice there can be a \n   more or less arbitrary number of subkeys present, not just the obvious \n   encryption subkeys signed with the primary signing key but also further\n   signing keys as subkeys, with a binding signature between the primary and\n   subkey made using the subkey instead of the primary key (although it can\n   also contain another binding signature from the primary key as well).\n\n   The more or less arbitrarily complex nature of all of these bits and \n   pieces is why PGP 5, which used a keying format that was still vastly\n   simpler than the current one, was split into two separate applications\n   of which the more complex one did nothing but key handling and the other,\n   simpler one did everything else in PGP.  It's also why we don't support\n   public keyring writes, it would require a complete keyring management\n   application just to deal with all of this complexity.\n\n   Even just to read all of this stuff we have to simplify the processing a\n   bit by recording the first primary key and subkey and skipping anything \n   else that may be present, the addition of arbitrary numbers of further\n   subkeys each potentially with their own per-subkey userIDs is too complex\n   to handle without again building a complete key management application, \n   and in any case such oddball keys are fairly rare and the basic greedy\n   algorithm for handling them seems to work fine */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readKey( INOUT STREAM *stream, \n\t\t\t\t\tINOUT PGP_INFO *pgpInfo, \n\t\t\t\t\tIN_INT_SHORT_Z const int keyGroupNo,\n\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tPGP_KEYINFO *keyInfo = &pgpInfo->key;\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ], packetHeader[ 16 + 8 ];\n\tBOOLEAN isPublicKey = TRUE;\n\tvoid *pubKeyPayload;\n\tlong packetLength;\n\tint pubKeyPos, pubKeyPayloadPos, endPos, pubKeyPayloadLen;\n\tint ctb, length, value, hashSize, noUserIDs, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRange( keyGroupNo ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Process the CTB and packet length */\n\tstatus = ctb = sPeek( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there was an error reading the CTB, which is the first byte of \n\t\t   the packet group, it means that we've run out of data so we \n\t\t   return the status as a not-found error rather than the actual\n\t\t   stream status */\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\tswitch( pgpGetPacketType( ctb ) )\n\t\t{\n\t\tcase PGP_PACKET_SECKEY_SUB:\n\t\t\tkeyInfo = &pgpInfo->subKey;\n\t\t\tisPublicKey = FALSE;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_SECKEY:\n\t\t\tisPublicKey = FALSE;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_PUBKEY_SUB:\n\t\t\tkeyInfo = &pgpInfo->subKey;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_PUBKEY:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid PGP CTB %02X for key packet group %d\", \n\t\t\t\t\t  ctb, keyGroupNo ) );\n\t\t}\n\tstatus = pgpReadPacketHeader( stream, NULL, &packetLength, 64, \n\t\t\t\t\t\t\t\t  MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PGP key packet header for key packet group %d\", \n\t\t\t\t  keyGroupNo ) );\n\t\t}\n\tif( packetLength < 64 || packetLength > sMemDataLeft( stream ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid PGP key packet length %ld for key packet group %d\", \n\t\t\t\t  packetLength, keyGroupNo ) );\n\t\t}\n\n\t/* Since there can (in theory) be arbitrary numbers of further subkeys \n\t   and other odds and ends attached to an existing key and the details \n\t   of what to do with these things gets a bit vague, we just skip any \n\t   additional subkeys that may be present.\n\t   \n\t   How to handle userIDs in this case is a bit unclear since there could\n\t   be different userIDs attached to a subkey, however stripping them \n\t   would make the main key invisible if searched for by one of the \n\t   subkey IDs, so we read them and treat them as if they belonged to the\n\t   main key (it's uncertain whether such an oddball configuration of key\n\t   packets even exists, or what to do with them if it does) */\n\tif( keyInfo->pkcAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = sSkip( stream, packetLength, MAX_INTLENGTH_SHORT );\n\t\tLOOP_MED( noUserIDs = 0, \n\t\t\t\t  cryptStatusOK( status ) && noUserIDs < 32, noUserIDs++ )\n\t\t\t{\n\t\t\tstatus = readUserID( stream, pgpInfo );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( cryptStatusOK( status ) && noUserIDs >= 32 )\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid additional PGP subkey information for key \"\n\t\t\t\t\t  \"packet group %d\", keyGroupNo ) );\n\t\t\t}\n\n\t\t/* We've skipped the current subkey, we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Determine which bits make up the public and the private key data.  The\n\t   public-key data starts at the version number and includes the date,\n\t   validity, and public-key components.  Since there's no length \n\t   information included for this data block we have to record bookmarks\n\t   and then later retroactively calculate the length based on how much\n\t   data we've read in the meantime:\n\n\t\tpubKeyPos pubKeyPayload\t\t\t privKey\t\t\t\t endPos\n\t\t\t|\t\t|\t\t\t\t\t\t|\t\t\t\t\t\t|\n\t\t\tv\t\tv\t\t\t\t\t\tv\t\t\t\t\t\tv\n\t\t+---+-------------------------------+-----------------------+\n\t\t|hdr|\t\t|\t\tPublic key\t\t|\t\tPrivate key\t\t|\n\t\t+---+-------------------------------+-----------------------+\n\t\t\t|\t\t|<--pubKeyPayloadLen--->|\t\t\t\t\t\t|\n\t\t\t|\t\t\t\t\t\t\t\t|\t\t\t\t\t\t|\n\t\t\t|<------- pubKeyDataLen ------->|<-- privKeyDataLen --->| \n\t\t\t|<----------------- packetLength ---------------------->| */\n\tpubKeyPos = stell( stream );\n\tendPos = pubKeyPos + packetLength;\n\tENSURES( endPos > pubKeyPos && endPos < MAX_BUFFER_SIZE );\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != PGP_VERSION_2 && value != PGP_VERSION_3 && \\\n\t\tvalue != PGP_VERSION_OPENPGP )\n\t\t{\n\t\t/* Unknown version number, skip this packet */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tpgpInfo->isOpenPGP = ( value == PGP_VERSION_OPENPGP ) ? TRUE : FALSE;\n\n\t/* Build the packet header, which is hashed along with the key components\n\t   to get the OpenPGP keyID.  This is generated anyway when the context\n\t   is created but we need to generate it here as well in order to locate\n\t   the key in the first place:\n\n\t\tbyte\t\tctb = 0x99\n\t\tbyte[2]\t\tlength\n\t\tbyte\t\tversion = 4\n\t\tbyte[4]\t\tkey generation time\n\t  [\tbyte[2]\t\tvalidity time - PGP 2.x only ]\n\t\tbyte[]\t\tkey data\n\n\t   We can't add the length or key data yet since we have to parse the\n\t   key data to know how long it is, so we can only build the static part\n\t   of the header at this point */\n\tpacketHeader[ 0 ] = 0x99;\n\tpacketHeader[ 3 ] = PGP_VERSION_OPENPGP;\n\n\t/* Read the timestamp and skip the validity period (for PGP 2.x keys) */\n\tstatus = sread( stream, packetHeader + 4, 4 );\n\tif( cryptStatusOK( status ) && !pgpInfo->isOpenPGP )\n\t\tstatus = sSkip( stream, 2, 2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the public key components */\n\tpubKeyPayloadPos = stell( stream );\n\tstatus = readPublicKeyComponents( stream, keyInfo, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the error status is OK_SPECIAL then the problem was an\n\t\t   unrecognised algorithm or something similar so we just skip the \n\t\t   packet */\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Encountered unrecognised algorithm while \"\n\t\t\t\t\t\t \"reading PGP key %d\", keyGroupNo ));\n\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PGP public-key components for key packet group %d\",\n\t\t\t\t  keyGroupNo ) );\n\t\t}\n\n\t/* Now that we know where the public key data starts and finishes, we \n\t   can set up references to it */\n\tkeyInfo->pubKeyDataLen = stell( stream ) - pubKeyPos;\n\tstatus = sMemGetDataBlockAbs( stream, pubKeyPos, &keyInfo->pubKeyData, \n\t\t\t\t\t\t\t\t  keyInfo->pubKeyDataLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\tpubKeyPayloadLen = stell( stream ) - pubKeyPayloadPos;\n\tstatus = sMemGetDataBlockAbs( stream, pubKeyPayloadPos, &pubKeyPayload, \n\t\t\t\t\t\t\t\t  pubKeyPayloadLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\n\t/* Complete the packet header that we read earlier on by adding the\n\t   length information */\n\tpacketHeader[ 1 ] = intToByte( ( ( 1 + 4 + length ) >> 8 ) & 0xFF );\n\tpacketHeader[ 2 ] = intToByte( ( 1 + 4 + length ) & 0xFF );\n\n\t/* Hash the data needed to generate the OpenPGP keyID */\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, &hashSize );\n\thashFunction( hashInfo, NULL, 0, packetHeader, 1 + 2 + 1 + 4, \n\t\t\t\t  HASH_STATE_START );\n\thashFunction( hashInfo, hash, CRYPT_MAX_HASHSIZE, \n\t\t\t\t  pubKeyPayload, pubKeyPayloadLen, HASH_STATE_END );\n\tmemcpy( keyInfo->openPGPkeyID, hash + hashSize - PGP_KEYID_SIZE,\n\t\t\tPGP_KEYID_SIZE );\n\n\t/* If it's a private keyring, process the private key components */\n\tif( !isPublicKey )\n\t\t{\n\t\t/* Handle decryption information for private-key components if \n\t\t   necessary */\n\t\tstatus = readPrivateKeyDecryptionInfo( stream, keyInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If the error status is OK_SPECIAL then the problem was an\n\t\t\t   unrecognised algorithm or something similar so we just skip\n\t\t\t   the packet */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Encountered unrecognised algorithm while \"\n\t\t\t\t\t\t\t \"reading PGP private key %d\", keyGroupNo ));\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t\treturn( OK_SPECIAL );\n\t\t\t\t}\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid PGP private-key decryption information for \"\n\t\t\t\t\t  \"key packet group %d\", keyGroupNo ) );\n\t\t\t}\n\n\t\t/* What's left is the private-key data */\n\t\tkeyInfo->privKeyDataLen = endPos - stell( stream );\n\t\tif( keyInfo->privKeyDataLen < 16 || \\\n\t\t\tkeyInfo->privKeyDataLen > MAX_INTLENGTH_SHORT )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tstatus = sMemGetDataBlock( stream, &keyInfo->privKeyData, \n\t\t\t\t\t\t\t\t   keyInfo->privKeyDataLen );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = sSkip( stream, keyInfo->privKeyDataLen, \n\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Read any associated subpacket(s), of which the only ones of real \n\t   interest are the userID packet(s).  readUserID() returns OK_SPECIAL\n\t   once it's run out of packets so this status isn't treated as an \n\t   error */\n\tLOOP_MED( noUserIDs = 0, cryptStatusOK( status ) && noUserIDs < 32, \n\t\t\t  noUserIDs++ )\n\t\t{\n\t\tstatus = readUserID( stream, pgpInfo );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) && noUserIDs >= 32 )\n\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PGP userID information for key packet group %d\",\n\t\t\t\t  keyGroupNo ) );\n\t\t}\n\n\t/* If there's no user ID present, set a generic label */\n\tif( pgpInfo->lastUserID <= 0 )\n\t\t{\n\t\tpgpInfo->userID[ 0 ] = \"PGP key (no user ID found)\";\n\t\tpgpInfo->userIDlen[ 0 ] = 26;\n\t\tpgpInfo->lastUserID = 1;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the information in the packet group */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \\\nstatic int processPacketGroup( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT PGP_INFO *pgpInfo,\n\t\t\t\t\t\t\t   IN_OPT const KEY_MATCH_INFO *keyMatchInfo,\n\t\t\t\t\t\t\t   INOUT_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,\n\t\t\t\t\t\t\t   IN_INT_SHORT_Z const int keyGroupNo,\n\t\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tint noPackets, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\tassert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \\\n\t\t\t( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) && \\\n\t\t\t  isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \\\n\t\t\t  ( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL && \\\n\t\t\t\tpgpInfo->keyData != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( pgpInfo->keyDataLen ) ) );\n\tREQUIRES( isShortIntegerRange( keyGroupNo ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tif( matchedKeyInfoPtrPtr != NULL )\n\t\t*matchedKeyInfoPtrPtr = NULL;\n\n\t/* Reset the index information before we read the current key(s), since \n\t   it may already have been initialised during a previous (incomplete) \n\t   key read */\n\tresetPGPInfo( pgpInfo );\n\n\t/* Read all the packets in this packet group */\n\tLOOP_MED( ( status = CRYPT_OK, noPackets = 0 ),\n\t\t\t  cryptStatusOK( status ) && sMemDataLeft( stream ) > 0 && \\\n\t\t\t\tnoPackets++ < 32,\n\t\t\t  noPackets++ )\n\t\t{\n\t\tstatus = readKey( stream, pgpInfo, keyGroupNo, errorInfo );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( noPackets >= 32 )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* If we're reading all keys, we're done */\n\tif( keyMatchInfo == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* We're searching for a particular key, see if this is the one */\n\tif( pgpCheckKeyMatch( pgpInfo, &pgpInfo->key, keyMatchInfo ) )\n\t\t{\n\t\t*matchedKeyInfoPtrPtr = &pgpInfo->key;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( pgpCheckKeyMatch( pgpInfo, &pgpInfo->subKey, keyMatchInfo ) )\n\t\t{\n\t\t*matchedKeyInfoPtrPtr = &pgpInfo->subKey;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* No match, tell the caller to keep looking */\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead a Keyring\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an entire keyring.  This function can be used in one of two ways, if \n   key match information is supplied then each packet will be checked \n   against it and the read will exit when a match is found (used for public \n   keyrings).  If no key match information is supplied then all keys will be \n   read into memory (used for private keyrings) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 8, 9 ) ) \\\nstatic int processKeyringPackets( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  IN_ARRAY( maxNoPgpObjects ) PGP_INFO *pgpInfo, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int maxNoPgpObjects,\n\t\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( bufSize ) BYTE *buffer, \n\t\t\t\t\t\t\t\t  IN_LENGTH_FIXED( KEYRING_BUFSIZE ) const int bufSize,\n\t\t\t\t\t\t\t\t  IN_OPT const KEY_MATCH_INFO *keyMatchInfo,\n\t\t\t\t\t\t\t\t  INOUT_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,\n\t\t\t\t\t\t\t\t  OUT BOOLEAN *unhandledDataPresent,\n\t\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tBOOLEAN moreData, insecureKeys = FALSE;\n\tlong filePos = 0;\n\tint bufEnd, keyGroupNo = 0, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( pgpInfo, \\\n\t\t\t\t\t\t\t   sizeof( PGP_INFO ) * maxNoPgpObjects ) );\n\tassert( isWritePtrDynamic( buffer, bufSize ) );\n\tassert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \\\n\t\t\t( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) && \\\n\t\t\t  isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) ) );\n\tassert( isWritePtr( unhandledDataPresent, sizeof( BOOLEAN ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPgpObjects ) );\n\tREQUIRES( bufSize == KEYRING_BUFSIZE );\n\tREQUIRES( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \\\n\t\t\t  ( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL && \\\n\t\t\t\tpgpInfo->keyData != NULL && \\\n\t\t\t\tpgpInfo->keyDataLen == KEYRING_BUFSIZE ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tif( matchedKeyInfoPtrPtr != NULL )\n\t\t*matchedKeyInfoPtrPtr = NULL;\n\t*unhandledDataPresent = FALSE;\n\n\t/* Scan all of the objects in the keyset.  This is implemented as a \n\t   sliding window that reads a certain amount of data into a lookahead \n\t   buffer and then tries to identify a packet group in the buffer.\n\n\t   Bounding the loop at FAILSAFE_ITERATIONS_MAX is safe since under \n\t   normal circumstances we'll hit the keyGroupNo bound long before we \n\t   encounter the hard bound */\n\tLOOP_MAX_INITCHECK( ( moreData = TRUE, bufEnd = 0 ),\n\t\t\t\t\t\tmoreData || bufEnd > 0 )\n\t\t{\n\t\tPGP_INFO *pgpInfoPtr = &pgpInfo[ keyGroupNo ];\n\t\tSTREAM keyStream;\n\t\tint length DUMMY_INIT;\t/* Init needed by gcc */\n\n\t\t/* Fill the lookahead buffer:\n\n\t\t\t buffer\t\t bufEnd\t\t\t bufSize\n\t\t\t\t|\t\t\t|\t\t\t\t|\n\t\t\t\tv\t\t\tv\t\t\t\tv\n\t\t\t\t+-----------+---------------+\n\t\t\t\t|///////////|\t\t\t\t|\n\t\t\t\t+-----------+---------------+ \n\t\t\t\t\t\t\t|\n\t\t\t\t\t\t\t+-- length --> */\n\t\tif( moreData )\n\t\t\t{\n\t\t\tREQUIRES( bufEnd >= 0 && bufEnd < bufSize );\n\n\t\t\tstatus = length = sread( stream, buffer + bufEnd,\n\t\t\t\t\t\t\t\t\t bufSize - bufEnd );\n\t\t\tif( cryptStatusError( status ) || length <= 0 )\n\t\t\t\t{\n\t\t\t\t/* If we read nothing and there's nothing left in the buffer,\n\t\t\t\t   we're done */\n\t\t\t\tif( bufEnd <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we've previously read at least one group of key \n\t\t\t\t\t   packets then we're OK */\n\t\t\t\t\tif( keyGroupNo > 0 )\n\t\t\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t\t\t/* There's no existing data still in the buffer and an\n\t\t\t\t\t   attempt to read more resulted in an error, we can't \n\t\t\t\t\t   go any further */\n\t\t\t\t\treturn( cryptStatusError( status ) ? status : \\\n\t\t\t\t\t\t\t( keyMatchInfo != NULL ) ? CRYPT_ERROR_NOTFOUND : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ERROR_UNDERFLOW );\n\t\t\t\t\t}\n\n\t\t\t\t/* There's still data in the buffer from a previous read, we \n\t\t\t\t   can continue until we drain it */\n\t\t\t\tlength = 0;\n\t\t\t\tmoreData = FALSE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If we didn't get as much as we requested then there's \n\t\t\t\t   nothing left to read */\n\t\t\t\tif( length < bufSize - bufEnd )\n\t\t\t\t\tmoreData = FALSE;\n\t\t\t\t}\n\t\t\tbufEnd += length;\n\n\t\t\tENSURES( bufEnd > 0 && bufEnd <= bufSize );\n\t\t\t}\n\n\t\t/* Determine the size of the group of key packets in the buffer */\n\t\tsMemConnect( &keyStream, buffer, bufEnd );\n\t\tstatus = scanPacketGroup( &keyStream, &length, bufEnd );\n\t\tsMemDisconnect( &keyStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't parse key packet group %d\", keyGroupNo ) );\n\t\t\t}\n\t\tENSURES( length > 0 && length <= bufEnd );\n\n\t\t/* Move the packet group from the keyring buffer to the key data */  \n\t\tif( keyMatchInfo == NULL )\n\t\t\t{\n\t\t\t/* It's a private-key read of all packets, allocate room for the \n\t\t\t   current packet group */\n\t\t\tREQUIRES( rangeCheck( length, 1, MAX_INTLENGTH ) );\n\t\t\tif( ( pgpInfoPtr->keyData = \\\n\t\t\t\t\t\tclAlloc( \"processKeyringPackets\", length ) ) == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\tmemcpy( pgpInfoPtr->keyData, buffer, length );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a public-key read and we're just scanning through the \n\t\t\t   packets looking for a match.  In this case pgpInfoPtr == \n\t\t\t   &pgpInfo[ 0 ], with pgpInfoPtr->keyData being a fixed buffer \n\t\t\t   of size KEYRING_BUFSIZE, with length <= KEYRING_BUFSIZE */\n\t\t\tREQUIRES( rangeCheck( length, 1, KEYRING_BUFSIZE ) );\n\t\t\tmemcpy( pgpInfoPtr->keyData, buffer, length );\n\t\t\t}\n\t\tpgpInfoPtr->keyDataLen = length;\n\n\t\t/* Remove the packet group from the read buffer:\n\n\t\t\t\t length\t  bufEnd\t\t\t  length\n\t\t\t\t\t|\t\t|\t\t\t\t\t|\n\t\t\t\t\tv\t\tv\t\t\t\t\tv\n\t\t\t+-------+-------+---+\t\t+-------+-----------+\n\t\t\t|///////|\\\\\\\\\\\\\\|\t| ---->\t|\\\\\\\\\\\\\\|\t\t\t|\n\t\t\t+-------+-------+---+\t\t+-------+-----------+\n\t\t\t   To\t   To\n\t\t\t remove\t  move */\n\t\tif( length < bufEnd )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( length, bufEnd - length, bufSize ) );\n\t\t\tmemmove( buffer, buffer + length, bufEnd - length );\n\t\t\t}\n\t\tbufEnd -= length;\n\t\tfilePos += length;\n\t\tENSURES( bufEnd >= 0 && bufEnd < bufSize );\n\n\t\t/* Process the current packet group */\n\t\tsMemConnect( &keyStream, pgpInfoPtr->keyData, \n\t\t\t\t\t pgpInfoPtr->keyDataLen );\n\t\tstatus = processPacketGroup( &keyStream, pgpInfoPtr, keyMatchInfo,\n\t\t\t\t\t\t\t\t\t matchedKeyInfoPtrPtr, keyGroupNo, \n\t\t\t\t\t\t\t\t\t errorInfo );\n\t\tsMemDisconnect( &keyStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we were looking for a match for a particular key and we\n\t\t\t   didn't find it, continue */\n\t\t\tif( keyMatchInfo != NULL && status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\tcontinue;\n\n\t\t\t/* If it's not a recoverable error, exit */\n\t\t\tif( status != OK_SPECIAL && status != CRYPT_ERROR_NOSECURE )\n\t\t\t\treturn( status );\n\n\t\t\t/* Remember that we hit something that we couldn't process, and\n\t\t\t   optionally an (unusable) unprotected key */\n\t\t\t*unhandledDataPresent = TRUE;\n\t\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t\tinsecureKeys = TRUE;\n\t\t\tif( keyMatchInfo == NULL )\n\t\t\t\t{\n\t\t\t\t/* Free the entry that we allocated earlier */\n\t\t\t\tpgpFreeEntry( pgpInfo );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If we're looking for a particular key, we've found it */\n\t\tif( keyMatchInfo != NULL )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* We're reading all keys, move on to the next empty slot.  Note \n\t\t   that we only get to this point if we've been able to do something \n\t\t   with the key, if not then the unhandledDataPresent flag will be \n\t\t   set without moving on to the next key group */\n\t\tkeyGroupNo++;\n\t\tif( keyGroupNo >= maxNoPgpObjects )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, errorInfo, \n\t\t\t\t\t  \"Maximum keyset object item count %d reached, no more \"\n\t\t\t\t\t  \"room to add further items\", maxNoPgpObjects ) );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If we were looking for a specific match, we haven't found it */\n\tif( keyMatchInfo != NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* If we haven't found any keys that we can use, let the caller know.  \n\t   The error code to return here is a bit complex because we can skip \n\t   keys either because there's something in the key data that we can't\n\t   process or because the keys aren't sufficiently protected for us to\n\t   trust them.  The most complex case is when both situations occur.  \n\t   To keep it simple, if there are any insecure keys then we report\n\t   CRYPT_ERROR_NOSECURE on the basis that if the keys had been \n\t   appropriately secured then we might have been able to process them \n\t   and return one */\n\tif( keyGroupNo <= 0 )\n\t\t{\n\t\treturn( insecureKeys ? CRYPT_ERROR_NOSECURE : \\\n\t\t\t\t\t\t\t   CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nint pgpScanPubKeyring( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT PGP_INFO *pgpInfo, \n\t\t\t\t\t   const KEY_MATCH_INFO *keyMatchInfo,\n\t\t\t\t\t   OUT_PTR_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,\n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tBYTE buffer[ KEYRING_BUFSIZE + 8 ];\n\tBYTE streamBuffer[ SAFEBUFFER_SIZE( STREAM_BUFSIZE ) + 8 ] STACK_ALIGN_DATA;\n\tBOOLEAN unhandledDataPresent;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );\n\tassert( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) );\n\tassert( isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( pgpInfo->keyData != NULL && \\\n\t\t\t  pgpInfo->keyDataLen == KEYRING_BUFSIZE );\n\tREQUIRES( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear the return value */\n\t*matchedKeyInfoPtrPtr = NULL;\n\n\t/* PGP keyrings just contain an arbitrary collection of packets \n\t   concatenated together so we can't tell in advance how much data we \n\t   should be reading.  Because of this we have to set the file stream to \n\t   allow partial reads without returning a read error */\n\tsioctlSet( stream, STREAM_IOCTL_PARTIALREAD, TRUE );\n\n\t/* Since we're scanning an arbitrarily-large collection of packets for a \n\t   match we need to allocate a stream buffer, since the stream for the \n\t   public keyring is merely an open file handle that can be scanned and \n\t   re-scanned as required to locate keys.  The somewhat awkward \n\t   buffering scheme is used because we need one buffer for the stream \n\t   and another to process keyring packets in, we can't use one for both.\n\t   \n\t   The processing works in a bit of a strange way, unlike \n\t   pgpReadPrivKeyring() it doesn't select a specific private-key entry \n\t   from data held in pgpInfo[] but instead scans through an arbitrary-\n\t   length stream looking for a particular matching key, which it returns \n\t   in pgpInfo[ 0 ].  \n\t   \n\t   Since the matching key can be any of the collection of physical keys \n\t   associated with a single logical key, we return information on the \n\t   particular subkey via the matchedKeyInfoPtr */\n\tsafeBufferInit( SAFEBUFFER_PTR( streamBuffer ), STREAM_BUFSIZE );\n\tsioctlSetString( stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t SAFEBUFFER_PTR( streamBuffer ), STREAM_BUFSIZE );\n\tstatus = processKeyringPackets( stream, pgpInfo, 1, buffer, \n\t\t\t\t\t\t\t\t\tKEYRING_BUFSIZE, keyMatchInfo, \n\t\t\t\t\t\t\t\t\tmatchedKeyInfoPtrPtr, \n\t\t\t\t\t\t\t\t\t&unhandledDataPresent, errorInfo );\n\tsioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we couldn't process one or more packets let the caller know that \n\t   not all keyring data is present in memory */\n\treturn( unhandledDataPresent ? OK_SPECIAL : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint pgpReadPrivKeyring( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ARRAY( maxNoPgpObjects ) PGP_INFO *pgpInfo, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxNoPgpObjects,\n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tBYTE buffer[ KEYRING_BUFSIZE + 8 ];\n\tBOOLEAN unhandledDataPresent;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( pgpInfo, \\\n\t\t\t\t\t\t\t   sizeof( PGP_INFO ) * maxNoPgpObjects ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPgpObjects ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* PGP keyrings just contain an arbitrary collection of packets \n\t   concatenated together so we can't tell in advance how much data we \n\t   should be reading.  Because of this we have to set the file stream to \n\t   allow partial reads without returning a read error */\n\tsioctlSet( stream, STREAM_IOCTL_PARTIALREAD, TRUE );\n\n\t/* Read all of the keyring packets into memory */\n\tstatus = processKeyringPackets( stream, pgpInfo, maxNoPgpObjects, \n\t\t\t\t\t\t\t\t\tbuffer, KEYRING_BUFSIZE, NULL, NULL, \n\t\t\t\t\t\t\t\t\t&unhandledDataPresent, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we couldn't process one or more packets let the caller know that \n\t   not all keyring data is present in memory */\n\treturn( unhandledDataPresent ? OK_SPECIAL : CRYPT_OK );\n\t}\n#endif /* USE_PGPKEYS */\n"
  },
  {
    "path": "deps/cl345/keyset/pgp_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib PGP Key Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"pgp_rw.h\"\n  #include \"keyset.h\"\n  #include \"pgp_key.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pgp_key.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGPKEYS\n\n/* Sizes of various buffers used to hold intermediate values before they're\n   encoded into PGP keyring format */\n\n#define KEYDATA_BUFFER_SIZE\t\t( ( CRYPT_MAX_PKCSIZE * 3 ) + 128 )\n\t\t\t\t\t\t\t\t/* DSA p + q + g + metadata */\n#define SIGDATA_BUFFER_SIZE\t\t( CRYPT_MAX_PKCSIZE + 256 )\t\n\t\t\t\t\t\t\t\t/* RSA sig + metadata */\n#define USERID_BUFFER_SIZE\t\t128\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash a key or userID in canonicalised form */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int hashKeyData( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\tIN_BUFFER( keyDataLength ) const BYTE *keyData,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) const int keyDataLength )\n\t{\n\tSTREAM stream;\n\tBYTE headerBuffer[ 8 + 8 ];\n\tint headerLength DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( keyDataLength >= 16 && keyDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Write the dummy header used to hash the key data.  We can't use \n\t   pgpWritePacketHeader() for this because we have to create a fixed-\n\t   format header rather than an optimally-encoded one */\n\tsMemOpen( &stream, headerBuffer, 8 );\n\tsputc( &stream, 0x99 );\t\t/* Pubkey CTB, 16-bit length */\n\tstatus = writeUint16( &stream, keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\theaderLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Hash the dummy header and the key data payload */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  headerBuffer, headerLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) keyData, keyDataLength );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int hashUserID( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t   IN_BUFFER( userIDlength ) const BYTE *userID,\n\t\t\t\t\t   IN_LENGTH_SHORT const int userIDlength )\n\t{\n\tSTREAM stream;\n\tBYTE headerBuffer[ 8 + 8 ];\n\tint headerLength DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( userID, userIDlength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( userIDlength ) );\n\n\t/* Write the dummy header used to hash the attributes and userID data.  \n\t   We can't use pgpWritePacketHeader() for this because we have to \n\t   create a fixed-format header rather than an optimally-encoded one */\n\tsMemOpen( &stream, headerBuffer, 8 );\n\tsputc( &stream, 0xB4 );\t\t/* UserID CTB, 32-bit length */\n\tstatus = writeUint32( &stream, userIDlength );\n\tif( cryptStatusOK( status ) )\n\t\theaderLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Hash the dummy header and the attributes and userID packet payload */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  headerBuffer, headerLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) userID, userIDlength );\n\treturn( status );\n\t}\n\n/* Build a PGP-style userID from the identifiers associated with a key.  \n   Ideally we use the more comprehensive information present in a\n   certificate, but if there's no certificate present then we have to fall \n   back to the key label */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nstatic int getUserID( IN_HANDLE const CRYPT_CONTEXT cryptHandle,\n\t\t\t\t\t  OUT_BUFFER( userIDmaxLength, \\\n\t\t\t\t\t\t\t\t  *userIDlength ) void *userID,\n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int userIDmaxLength,\n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( userIDmaxLength ) \\\n\t\t\t\t\t\t\tint *userIDlength )\n\t{\n\tCRYPT_CERTIFICATE iCryptCert;\n\tMESSAGE_DATA msgData DUMMY_INIT_STRUCT;\n\tSTREAM stream;\n\tBYTE nameBuffer[ USERID_BUFFER_SIZE + 8 ];\n\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\tstatic const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;\n\tint nameLength, value, status;\n\n\tassert( isWritePtrDynamic( userID, userIDmaxLength ) );\n\tassert( isWritePtr( userIDlength, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( userIDmaxLength >= 16 && \\\n\t\t\t  userIDmaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( userID, 0, min( 16, userIDmaxLength ) );\n\t*userIDlength = 0;\n\n\t/* Check whether we're dealing with a certificate */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) || \\\n\t\t( value != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t  value != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t{\n\t\t/* It's a straight context, the best that we can do in terms of a \n\t\t   userID is the label for the context */\n\t\tsetMessageData( &msgData, userID, userIDmaxLength );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*userIDlength = msgData.length;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the associated certificate object handle and lock it so that we \n\t   can mess around with internal cursors */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iCryptCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Fetch the certificate holder name, usually the common name but \n\t   possibly an alternative if there's no CN present */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &nameValue, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, nameBuffer, \n\t\t\t\t\t\tmin( userIDmaxLength, USERID_BUFFER_SIZE ) );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_HOLDERNAME );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( status );\n\t\t}\n\tnameLength = msgData.length;\n\tENSURES( nameLength > 0 && nameLength <= userIDmaxLength );\n\n\t/* Set the user ID to the holder name */\n\tREQUIRES( rangeCheck( nameLength, 1, userIDmaxLength ) );\n\tmemcpy( userID, nameBuffer, nameLength );\n\t*userIDlength = nameLength;\n\n\t/* Check whether the holder name is an email address, or at least of the \n\t   form \"...@...\".  If it is then we're done */\n\tif( strFindCh( nameBuffer, nameLength, '@' ) > 0 )\n\t\t{\n\t\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Fetch the email address if there's one present */\n\tsetMessageData( &msgData, nameBuffer, USERID_BUFFER_SIZE );\n\tkrnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &altNameValue, \n\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_RFC822NAME );\n\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t\n\t/* If there isn't room to append the email address to the name, in the\n\t   form \"name <email>\", then we're done */\n\tif( nameLength + 2 + msgData.length + 1 > userIDmaxLength )\n\t\treturn( CRYPT_OK );\n\n\t/* Construct the userID as name + \" <\" + email + \">\" */\n\tsMemOpen( &stream, ( BYTE * ) userID + nameLength, \n\t\t\t  userIDmaxLength - nameLength );\n\tswrite( &stream, \" <\", 2 );\n\tswrite( &stream, nameBuffer, msgData.length );\n\tstatus = swrite( &stream, \">\", 1 );\n\tif( cryptStatusOK( status ) )\n\t\t*userIDlength += stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSubpacket Signature Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create signed attributes.  In addition to the default information \n   (signing time and signing key ID), PGP keys can have all manner of \n   (mostly) noise attributes added to them, but it's not clear what purpose \n   any of them really serve apart from bloating up the public key data.  The \n   sender will choose its preferred default algorithms (e.g. AES, SHA-256) \n   anyway out of any list that we send so we don't need to specify them, and \n   in some cases the choices are tautologies, e.g. the ECC keys for which \n   only AES is allowed so there's no point in specifying anything.\n\n   The possible packets that we can add are:\n\n\t- Preferred symmetric algorithms.\n\t- Preferred hash algorithms.\n\t- Preferred compression algorithms.\n\t- Primary userID flag.\n\t- Features: MDC.\n\n   None of these really seem to serve any purpose if they're not set, but \n   since it seems to be a required fashion statement to have them present we\n   generate the relevant attributes and include them in the signed data*/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int createSignedAttributes( OUT_BUFFER( attributeMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t   *attributeLength ) void *attributes,\n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int attributeMaxLength,\n\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( attributeMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\tint *attributeLength )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 16 + 8 ];\n\tint bufPos, status;\n\n\tassert( isWritePtrDynamic( attributes, attributeMaxLength ) );\n\tassert( isWritePtr( attributeLength, sizeof( int ) ) );\n\n\tREQUIRES( attributeMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  attributeMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( attributes, 0, min( 16, attributeMaxLength ) );\n\t*attributeLength = 0;\n\n\tsMemOpen( &stream, attributes, attributeMaxLength );\n\n\t/* Preferred symmetric algorithms:\n\n\t\tbyte\tlength\n\t\tbyte\ttype = PGP_SUBPACKET_PREF_SYM\n\t\tbyte[]\talgorithms.\n\t\t\n\t   We don't advertise obsolete algorithms like IDEA and CAST even if \n\t   they're available because we don't want to encourage their use */\n\tbufPos = 0;\n\tif( algoAvailable( CRYPT_ALGO_AES ) )\n\t\t{\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_AES_128;\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_AES_256;\n\t\t}\n\tif( algoAvailable( CRYPT_ALGO_3DES ) )\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_3DES;\n\tif( bufPos > 0 )\n\t\t{\n\t\tsputc( &stream, 1 + bufPos );\n\t\tsputc( &stream, PGP_SUBPACKET_PREF_SYM );\n\t\tswrite( &stream, buffer, bufPos );\n\t\t}\n\n\t/* Preferred hash algorithms:\n\n\t\tbyte\tlength\n\t\tbyte\ttype = PGP_SUBPACKET_PREF_HASH\n\t\tbyte[]\talgorithms */\n\tbufPos = 0;\n\tif( algoAvailable( CRYPT_ALGO_SHAng ) )\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_SHAng;\n\tif( algoAvailable( CRYPT_ALGO_SHA2 ) )\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_SHA2_256;\n\tif( algoAvailable( CRYPT_ALGO_SHA1 ) )\n\t\tbuffer[ bufPos++ ] = PGP_ALGO_SHA;\n\tif( bufPos > 0 )\n\t\t{\n\t\tsputc( &stream, 1 + bufPos );\n\t\tsputc( &stream, PGP_SUBPACKET_PREF_HASH );\n\t\tswrite( &stream, buffer, bufPos );\n\t\t}\n\n\t/* Preferred compression algorithms:\n\n\t\tbyte\tlength\n\t\tbyte\ttype = PGP_SUBPACKET_PREF_COPR\n\t\tbyte[]\talgorithms */\n#ifdef USE_COMPRESSION\n\tsputc( &stream, 1 + 2 );\n\tsputc( &stream, PGP_SUBPACKET_PREF_COPR );\n\tsputc( &stream, PGP_ALGO_ZLIB );\n\tsputc( &stream, PGP_ALGO_ZIP );\n#else\n\tsputc( &stream, 1 + 1 );\n\tsputc( &stream, PGP_SUBPACKET_PREF_COPR );\n\tsputc( &stream, PGP_ALGO_NONE );\n#endif /* USE_COMPRESSION */\n\n\t/* Primary userID:\n\t\t\n\t\tbyte\tlength = 1 + 1\n\t\tbyte\ttype = PGP_SUBPACKET_PRIMARY_USERID\n\t\tbyte\tboolean = 1\n\n\t   This is somewhat redundant since there's only one userID anyway, but \n\t   we include it just in case something relies on it */\n\tsputc( &stream, 1 + 1 );\n\tsputc( &stream, PGP_SUBPACKET_PRIMARY_USERID );\n\tsputc( &stream, 1 );\n\n\t/* Features:\n\t\t\n\t\tbyte\tlength = 1 + 1\n\t\tbyte\ttype = PGP_SUBPACKET_FEATURES\n\t\tbyte\tflags = 0x1, MDC supported */\n\tsputc( &stream, 1 + 1 );\n\tsputc( &stream, PGP_SUBPACKET_FEATURES );\n\tstatus = sputc( &stream, 1 );\n\n\tif( cryptStatusOK( status ) )\n\t\t*attributeLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Create a subpacket signature to bind the subpacket to the main key \n   packet.  This simply signs the userID or key data with the primary key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nstatic int createSubpacketSignature( OUT_BUFFER( sigMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t *signatureLength ) void *signature,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int sigMaxLength,\n\t\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( sigMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\tint *signatureLength,\n\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSigContext,\n\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t\t\t\t IN_BUFFER( subPacketDataLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *subPacketData,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int subPacketDataLength,\n\t\t\t\t\t\t\t\t\t IN_BUFFER_OPT( sigAttributeLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *sigAttributes,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int sigAttributeLength,\n\t\t\t\t\t\t\t\t\t IN_RANGE( PGP_SIG_NONE + 1, PGP_SIG_LAST - 1 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int sigType )\n\t{\n\tCRYPT_CONTEXT iLocalHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSIGPARAMS sigParams;\n\tint status;\n\n\tassert( isWritePtrDynamic( signature, sigMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( subPacketData, subPacketDataLength ) );\n\tassert( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( sigAttributes, sigAttributeLength ) );\n\n\tREQUIRES( sigMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  sigMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iSigContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( subPacketDataLength ) );\n\tREQUIRES( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\t  ( sigAttributes != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( sigAttributeLength ) ) );\n\tREQUIRES( sigType == PGP_SIG_CERT0 || \\\n\t\t\t  sigType == PGP_SIG_SUBKEY );\n\n\t/* Clear return values */\n\tmemset( signature, 0, min( 16, sigMaxLength ) );\n\t*signatureLength = 0;\n\n\t/* Clone the primary key hash context so that we can continue hashing\n\t   the subpacket data */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalHashContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CLONE, NULL,\n\t\t\t\t\t\t\t  iLocalHashContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Hash the subpacket data */\n\tif( sigType == PGP_SIG_CERT0 )\n\t\t{\n\t\tstatus = hashUserID( iLocalHashContext, subPacketData, \n\t\t\t\t\t\t\t subPacketDataLength );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = hashKeyData( iLocalHashContext, subPacketData, \n\t\t\t\t\t\t\t  subPacketDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Finally, sign the hashed data */\n\tinitSigParamsPGP( &sigParams, sigType, sigAttributes, \n\t\t\t\t\t  sigAttributeLength );\n\tstatus = iCryptCreateSignature( signature, sigMaxLength,\n\t\t\t\t\t\t\t\t\tsignatureLength, CRYPT_FORMAT_PGP,\n\t\t\t\t\t\t\t\t\tiSigContext, iLocalHashContext,\n\t\t\t\t\t\t\t\t\t&sigParams );\n\n\t/* Clean up */\n\tkrnlSendNotifier( iLocalHashContext, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPGP Key Export Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export a PGP key.  There are two types of export that we can perform, an\n   RSA key, which exports a single key and is self-signed, and an \n   Elgamal/ECDH + (EC)DSA key, which exports both keys and uses the (EC)DSA \n   key to sign the Elgamal/ECDH key.\n   \n   The OpenPGP key format is a complex mess, for RSA keys we use:\n\n\tRSA key\n\t\tuser ID, RSA binding signature\n\n   For Elgamal/ECDH + (EC)DSA keys we use:\n\n\t(EC)DSA key\t\t\t\t\t\t\t\t\t\t-- Primary key\n\t\tuser ID, (EC)DSA binding signature\n\t\tElgamal/ECDH key, (EC)DSA binding signature\t-- Secondary key \n\n   The following code assumes that various checks and the storing of the\n   Elgamal/ECDH key data have already been performed by higher-level code,\n   and concerns itself purely with the generation of signatures and encoding\n   of key data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pgpWritePubkey( INOUT PGP_INFO *pgpInfoPtr,\n\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tCRYPT_CONTEXT iKeyHash;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE primaryKeyBuffer[ KEYDATA_BUFFER_SIZE + 8 ];\n\tBYTE secondaryKeySigBuffer[ SIGDATA_BUFFER_SIZE + 8 ];\n\tBYTE userIDsigBuffer[ SIGDATA_BUFFER_SIZE + 8 ];\n\tBYTE userIDbuffer[ USERID_BUFFER_SIZE + 8 ];\n\tBYTE sigAttributes[ 64 + 8 ];\n\tvoid *keyData;\n\tint primaryKeyDataLen, secondaryKeySigLen = 0;\n\tint userIDlen, userIDsigLen DUMMY_INIT, sigAttributeLen;\n\tint keyDataLength, altKeyDataLength = 0, status;\n\n\tassert( isWritePtr( pgpInfoPtr, sizeof( PGP_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\n\t/* Get the primary key and userID for the key */\n\tsetMessageData( &msgData, primaryKeyBuffer, KEYDATA_BUFFER_SIZE );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_PGP );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tprimaryKeyDataLen = msgData.length;\n\tstatus = getUserID( cryptHandle, userIDbuffer, USERID_BUFFER_SIZE, \n\t\t\t\t\t\t&userIDlen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the signed attributes for the user ID */\n\tstatus = createSignedAttributes( sigAttributes, 64, &sigAttributeLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Hash the primary key data in preparation for creating any subkey\n\t   signatures */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiKeyHash = createInfo.cryptHandle;\n\tstatus = hashKeyData( iKeyHash, primaryKeyBuffer, primaryKeyDataLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iKeyHash, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Sign the user ID */\n\tstatus = createSubpacketSignature( userIDsigBuffer, SIGDATA_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t   &userIDsigLen, cryptHandle, iKeyHash, \n\t\t\t\t\t\t\t\t\t   userIDbuffer, userIDlen, sigAttributes, \n\t\t\t\t\t\t\t\t\t   sigAttributeLen, PGP_SIG_CERT0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iKeyHash, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Sign the secondary (encryption) key if there's one present */\n\tif( pgpInfoPtr->keyData != NULL )\n\t\t{\n\t\tstatus = createSubpacketSignature( secondaryKeySigBuffer, SIGDATA_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t\t\t   &secondaryKeySigLen, cryptHandle, \n\t\t\t\t\t\t\t\t\t\t   iKeyHash, pgpInfoPtr->keyData, \n\t\t\t\t\t\t\t\t\t\t   pgpInfoPtr->keyDataLen, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t   PGP_SIG_SUBKEY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iKeyHash, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\taltKeyDataLength = 16 + pgpInfoPtr->keyDataLen + secondaryKeySigLen;\n\t\t}\n\tkrnlSendNotifier( iKeyHash, IMESSAGE_DECREFCOUNT );\n\n\t/* Allocate storage to write the keyring data */\n\tkeyDataLength = 16 + primaryKeyDataLen + 16 + userIDlen + \\\n\t\t\t\t\tuserIDsigLen + altKeyDataLength;\n\tREQUIRES( rangeCheck( keyDataLength, 1, MAX_INTLENGTH_SHORT ) );\n\tkeyData = clAlloc( \"pgpWritePubkey\", keyDataLength );\n\tif( keyData == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t/* Write the key(s), user ID, and signature data into the buffer:\n\n\t\tpubkey\n\t\t\tuserID, binding signature\n\t\t  [\tsecondary pubkey, binding signature ] */\n\tsMemOpen( &stream, keyData, keyDataLength );\n\tstatus = pgpWritePacketHeader( &stream, PGP_PACKET_PUBKEY, \n\t\t\t\t\t\t\t\t   primaryKeyDataLen );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tswrite( &stream, primaryKeyBuffer, primaryKeyDataLen );\n\t\tstatus = pgpWritePacketHeader( &stream, PGP_PACKET_USERID, \n\t\t\t\t\t\t\t\t\t   userIDlen );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tswrite( &stream, userIDbuffer, userIDlen );\n\t\tstatus = swrite( &stream, userIDsigBuffer, userIDsigLen );\n\t\t}\n\tif( cryptStatusOK( status ) && pgpInfoPtr->keyDataLen > 0 )\n\t\t{\n\t\tstatus = pgpWritePacketHeader( &stream, PGP_PACKET_PUBKEY_SUB, \n\t\t\t\t\t\t\t\t\t   pgpInfoPtr->keyDataLen );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tswrite( &stream, pgpInfoPtr->keyData, pgpInfoPtr->keyDataLen );\n\t\t\tstatus = swrite( &stream, secondaryKeySigBuffer, \n\t\t\t\t\t\t\t secondaryKeySigLen );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tkeyDataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Finally, rearrange the buffers containing key data as required */\n\tif( pgpInfoPtr->keyData != NULL )\n\t\tclFree( \"pgpWritePublicKey\", pgpInfoPtr->keyData );\n\tpgpInfoPtr->keyData = keyData;\n\tpgpInfoPtr->keyDataLen = keyDataLength;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGPKEYS */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs12.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib PKCS #12 Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2010\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs12.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs12.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS12\n\n/* OID information used to read the header of a PKCS #12 keyset */\n\nstatic const CMS_CONTENT_INFO oidInfoEncryptedData = { 0, 2 };\n\nstatic const OID_INFO dataOIDinfo[] = {\n    { OID_CMS_DATA, CRYPT_OK },\n    { NULL, 0 }, { NULL, 0 }\n    };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the PKCS #12 information state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckPKCS12( const PKCS12_INFO *pkcs12infoPtr )\n\t{\n\tconst PKCS12_OBJECT_INFO *objectInfoPtr;\n\n\tassert( isReadPtr( pkcs12infoPtr, sizeof( PKCS12_INFO ) ) );\n\n\t/* Check that the basic fields are in order.  Since all of the fields are\n\t   optional, either of them may not be present */\n\tif( pkcs12infoPtr->labelLength == 0 )\n\t\t{\n\t\t/* No label, there must be an ID present */\n\t\tif( pkcs12infoPtr->idLength < 0 || \\\n\t\t\tpkcs12infoPtr->idLength > CRYPT_MAX_HASHSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: ID\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There's a label, the ID is optional */\n\t\tif( pkcs12infoPtr->labelLength <= 0 || \\\n\t\t\tpkcs12infoPtr->labelLength > CRYPT_MAX_TEXTSIZE || \\\n\t\t\tpkcs12infoPtr->idLength < 0 || \\\n\t\t\tpkcs12infoPtr->idLength > CRYPT_MAX_HASHSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Label/ID\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check that the object-specific fields have reasonable values.  This \n\t   is a general check for reasonable values that's more targeted at\n\t   catching inadvertent memory corruption than a strict sanity check */\n\tobjectInfoPtr = &pkcs12infoPtr->keyInfo;\n\tif( objectInfoPtr->data != NULL )\n\t\t{\n\t\tif( !isShortIntegerRangeNZ( objectInfoPtr->dataSize ) || \\\n\t\t\tobjectInfoPtr->payloadOffset <= 0 || \\\n\t\t\tobjectInfoPtr->payloadOffset >= objectInfoPtr->dataSize || \\\n\t\t\tobjectInfoPtr->payloadSize <= 0 || \\\n\t\t\tobjectInfoPtr->payloadSize >= objectInfoPtr->dataSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Key data/payload\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( objectInfoPtr->dataSize != 0 || \\\n\t\t\tobjectInfoPtr->payloadOffset != 0 || \\\n\t\t\tobjectInfoPtr->payloadSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Spurious key data/payload\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( objectInfoPtr->keySize < 0 || \\\n\t\tobjectInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \\\n\t\tobjectInfoPtr->saltSize < 0 || \\\n\t\tobjectInfoPtr->saltSize > CRYPT_MAX_HASHSIZE || \\\n\t\tobjectInfoPtr->iterations < 0 || \\\n\t\tobjectInfoPtr->iterations > MAX_KEYSETUP_ITERATIONS )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Key salt/iterations\" ));\n\t\treturn( FALSE );\n\t\t}\n\tobjectInfoPtr = &pkcs12infoPtr->certInfo;\n\tif( objectInfoPtr->data != NULL )\n\t\t{\n\t\t/* Make sure that the payload is contained within the data.  The \n\t\t   payload may be the same as the data, so we can have a start offset\n\t\t   of 0 and a size equal to the payload size */\n\t\tif( !isShortIntegerRangeNZ( objectInfoPtr->dataSize ) || \\\n\t\t\tobjectInfoPtr->payloadOffset < 0 || \\\n\t\t\tobjectInfoPtr->payloadOffset >= objectInfoPtr->dataSize || \\\n\t\t\tobjectInfoPtr->payloadSize < 0 || \\\n\t\t\tobjectInfoPtr->payloadSize > objectInfoPtr->dataSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Cert data/payload\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( objectInfoPtr->dataSize != 0 || \\\n\t\t\tobjectInfoPtr->payloadOffset != 0 || \\\n\t\t\tobjectInfoPtr->payloadSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Spurious cert data/payload\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( objectInfoPtr->keySize < 0 || \\\n\t\tobjectInfoPtr->keySize > CRYPT_MAX_KEYSIZE || \\\n\t\tobjectInfoPtr->saltSize < 0 || \\\n\t\tobjectInfoPtr->saltSize > CRYPT_MAX_HASHSIZE || \\\n\t\tobjectInfoPtr->iterations < 0 || \\\n\t\tobjectInfoPtr->iterations > MAX_KEYSETUP_ITERATIONS )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: Cert salt/iterations\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check that the crypto-related fields are in order.  This is a general \n\t   check for reasonable values that's more targeted at catching \n\t   inadvertent memory corruption than a strict sanity check */\n\tif( !isShortIntegerRange( pkcs12infoPtr->macSaltSize ) || \\\n\t\t!isIntegerRange( pkcs12infoPtr->macIterations ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS12: MAC info\" ));\n\t\treturn( FALSE );\n\t\t}\n\t\n\treturn( TRUE );\n\t}\n\n/* Locate a PKCS #12 object based on an ID */\n\n#define matchID( src, srcLen, dest, destLen ) \\\n\t\t( ( srcLen ) > 0 && ( srcLen ) == ( destLen ) && \\\n\t\t  !memcmp( ( src ), ( dest ), ( destLen ) ) )\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS12_INFO *pkcs12FindEntry( IN_ARRAY( noPkcs12objects ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int noPkcs12objects,\n\t\t\t\t\t\t\t  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t  IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\t\t  const BOOLEAN isWildcardMatch )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs12info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS12_INFO ) * noPkcs12objects ) );\n\tassert( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( noPkcs12objects ) );\n\tREQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t\tkeyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_KEYID );\n\tREQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t\t( keyID != NULL && \\\n\t\t\t\t  keyIDlength > 0 && keyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES_N( isWildcardMatch == TRUE || isWildcardMatch == FALSE );\n\tREQUIRES_N( ( isWildcardMatch && keyID == NULL ) || !isWildcardMatch );\n\n\t/* Try and locate the appropriate object in the PKCS #12 collection */\n\tLOOP_MED( i = 0, i < noPkcs12objects, i++ )\n\t\t{\n\t\tconst PKCS12_INFO *pkcs12infoPtr = &pkcs12info[ i ];\n\n\t\t/* If there's no entry at this position, continue */\n\t\tif( pkcs12infoPtr->flags == PKCS12_FLAG_NONE )\n\t\t\tcontinue;\n\n\t\tENSURES_N( sanityCheckPKCS12( pkcs12infoPtr ) );\n\n\t\t/* If we're doing a wildcard matches, match the first private-key \n\t\t   entry.  This is required because PKCS #12 provides almost no \n\t\t   useful indexing information, and works because most keysets \n\t\t   contain only a single entry */\n\t\tif( isWildcardMatch )\n\t\t\t{\n\t\t\tif( pkcs12infoPtr->keyInfo.data == NULL )\n\t\t\t\tcontinue;\t/* No private-key data present, continue */\n\t\t\treturn( ( PKCS12_INFO * ) pkcs12infoPtr );\n\t\t\t}\n\n\t\t/* Check for a match based on the ID type */\n\t\tswitch( keyIDtype )\n\t\t\t{\n\t\t\tcase CRYPT_KEYID_NAME:\n\t\t\tcase CRYPT_KEYID_URI:\n\t\t\t\tif( matchID( pkcs12infoPtr->label, pkcs12infoPtr->labelLength,\n\t\t\t\t\t\t\t keyID, keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS12_INFO * ) pkcs12infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\t\tif( matchID( pkcs12infoPtr->id, pkcs12infoPtr->idLength,\n\t\t\t\t\t\t\t keyID, keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS12_INFO * ) pkcs12infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Null();\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/* Find a free PKCS #12 entry */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS12_INFO *pkcs12FindFreeEntry( IN_ARRAY( noPkcs12objects ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int noPkcs12objects, \n\t\t\t\t\t\t\t\t  OUT_OPT_INDEX( noPkcs12objects ) int *index )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs12info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS12_INFO ) * noPkcs12objects ) );\n\tassert( ( index == NULL ) || isWritePtr( index, sizeof( int ) ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( noPkcs12objects ) );\n\n\t/* Clear return value */\n\tif( index != NULL )\n\t\t*index = CRYPT_ERROR;\n\n\tLOOP_MED( i = 0, i < noPkcs12objects, i++ )\n\t\t{\n\t\tif( pkcs12info[ i ].flags == PKCS12_FLAG_NONE )\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tif( i >= noPkcs12objects )\n\t\treturn( NULL );\n\n\t/* Remember the index value (used for enumerating PKCS #12 entries) for \n\t   this entry if required */\n\tif( index != NULL )\n\t\t*index = i;\n\n\treturn( ( PKCS12_INFO * ) &pkcs12info[ i ] );\n\t}\n\n/* Free object entries */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12freeObjectEntry( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo )\n\t{\n\tvoid *dataPtr = ( void * ) pkcs12objectInfo->data;\n\t\t /* Although the data is declared 'const' since it can't be \n\t\t    modified, we still have to be able to zeroise it on free so \n\t\t\twe override the const for this */\n\n\tassert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\n\tzeroise( dataPtr, pkcs12objectInfo->dataSize );\n\tclFree( \"pkcs12freeObjectEntry\", dataPtr );\n\tzeroise( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12freeEntry( INOUT PKCS12_INFO *pkcs12info )\n\t{\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\n\tif( pkcs12info->macInitialised )\n\t\tkrnlSendNotifier( pkcs12info->iMacContext, IMESSAGE_DECREFCOUNT );\n\tif( pkcs12info->keyInfo.data != NULL )\n\t\tpkcs12freeObjectEntry( &pkcs12info->keyInfo );\n\tif( pkcs12info->certInfo.data != NULL )\n\t\tpkcs12freeObjectEntry( &pkcs12info->certInfo );\n\n\tzeroise( pkcs12info, sizeof( PKCS12_INFO ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12Free( INOUT_ARRAY( noPkcs12objects ) PKCS12_INFO *pkcs12info, \n\t\t\t\t IN_RANGE( 1, MAX_PKCS12_OBJECTS ) const int noPkcs12objects )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( pkcs12info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS12_INFO ) * noPkcs12objects ) );\n\n\tREQUIRES_V( noPkcs12objects >= 1 && \\\n\t\t\t\tnoPkcs12objects <= MAX_PKCS12_OBJECTS );\n\n\tLOOP_MED( i = 0, i < noPkcs12objects, i++ )\n\t\tpkcs12freeEntry( &pkcs12info[ i ] );\n\tENSURES_V( LOOP_BOUND_OK );\n\tzeroise( pkcs12info, sizeof( PKCS12_INFO ) * noPkcs12objects );\n\t}\n\n/* Read the header of a PKCS #12 keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPkcs12header( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_INT_Z int *endPosPtr,\n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tlong payloadLength DUMMY_INIT, version;\n\tint endPos, currentPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( endPosPtr, sizeof( long ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\t/* Clear return value */\n\t*endPosPtr = 0;\n\n\t/* Read the outer header and make sure that it's valid */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &version );\n\tif( cryptStatusOK( status ) && version != 3 )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readCMSheader( stream, dataOIDinfo, \n\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ),\n\t\t\t\t\t\t\t\tNULL, &payloadLength, \n\t\t\t\t\t\t\t\tREADCMS_FLAG_DEFINITELENGTH_OPT );\n\t\tif( cryptStatusOK( status ) && payloadLength > MAX_INTLENGTH_SHORT )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #12 keyset header\" ) );\n\t\t}\n\tREQUIRES( isIntegerRange( payloadLength ) );\n\tendPos = ( int ) payloadLength;\n\n\t/* PKCS #12 files created by the Norwegian Buypass CA use constructed \n\t   OCTET STRINGs with the inner, primitive OCTET STRING exactly filling \n\t   the outer constructed one, in effect creating one OCTET STRING nested\n\t   inside the other.  To deal with this, if we hit an OCTET STRING at \n\t   this point then it's the inner one so we skip it to get to the actual \n\t   content */\n\tif( peekTag( stream ) == BER_OCTETSTRING )\n\t\treadOctetStringHole( stream, &endPos, 4, DEFAULT_TAG );\n\n\t/* If we couldn't get the length from the CMS header, try again with the \n\t   next level of nested data */\n\tif( endPos == CRYPT_UNUSED )\n\t\t{\n\t\tint length;\n\n\t\tstatus = readSequence( stream, &length );\n\t\tif( cryptStatusOK( status ) && length == CRYPT_UNUSED )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Can't process indefinite-length PKCS #12 \"\n\t\t\t\t\t  \"content\" ) );\n\t\t\t}\n\t\tendPos = length;\t/* int -> long, readSequence() requires an int */\n\t\t}\n\telse\n\t\t{\n\t\tconst int startPos = stell( stream );\n\n\t\t/* Just skip the next level of nesting.  We don't rely on the value\n\t\t   returned from readSequence() in case it has an indefinite length,\n\t\t   since we've already got a definite length earlier */\n\t\tstatus = readSequence( stream, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tendPos -= ( stell( stream ) - startPos );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #12 keyset inner header\" ) );\n\t\t}\n\n\t/* Make sure that the length information is sensible */\n\tcurrentPos = stell( stream );\n\tif( endPos < 16 + MIN_OBJECT_SIZE || \\\n\t\tcurrentPos + endPos >= MAX_INTLENGTH_SHORT )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid PKCS #12 keyset length information\" ) );\n\t\t}\n\t*endPosPtr = currentPos + endPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCrypto Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the parameters used to derive a password for encryption/MACing */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5 ) ) \\\nstatic int initDeriveParams( IN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\t OUT_BUFFER( saltMaxLength, *saltLength ) \\\n\t\t\t\t\t\t\t\tvoid *salt,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( KEYWRAP_SALTSIZE ) \\\n\t\t\t\t\t\t\t\tconst int saltMaxLength,\n\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( saltMaxLength ) \\\n\t\t\t\t\t\t\t\tint *saltLength,\n\t\t\t\t\t\t\t OUT_INT_Z int *iterations )\n\t{\n\tMESSAGE_DATA msgData;\n\tint value, status;\n\n\tassert( isWritePtrDynamic( salt, saltMaxLength ) );\n\tassert( isWritePtr( saltLength, sizeof( int ) ) );\n\tassert( isWritePtr( iterations, sizeof( int ) ) );\n\n\tREQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptOwner ) );\n\tREQUIRES( saltMaxLength >= KEYWRAP_SALTSIZE && \\\n\t\t\t  saltMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( salt, 0, min( 16, saltMaxLength ) );\n\t*saltLength = 0;\n\t*iterations = 0;\n\n\t/* Generate the salt */\n\tsetMessageData( &msgData, salt, KEYWRAP_SALTSIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*saltLength = KEYWRAP_SALTSIZE;\n\n\t/* In the interests of luser-proofing we force the use of a safe minimum \n\t   number of iterations */\n\tstatus = krnlSendMessage( cryptOwner, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_OPTION_KEYING_ITERATIONS );\n\tif( cryptStatusError( status ) || value < MIN_KEYING_ITERATIONS )\n\t\tvalue = MIN_KEYING_ITERATIONS;\n\t*iterations = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Set up an encryption/MAC context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 6 ) ) \\\nstatic int initContext( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\tIN_LENGTH_KEY const int keySize,\n\t\t\t\t\t\tIN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength,\n\t\t\t\t\t\tIN_BUFFER( saltLength ) const void *salt,\n\t\t\t\t\t\tIN_LENGTH_SHORT const int saltLength,\n\t\t\t\t\t\tIN_INT const int iterations,\n\t\t\t\t\t\tconst BOOLEAN isCryptContext )\n\t{\n\tCRYPT_CONTEXT iLocalCryptContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMECHANISM_DERIVE_INFO deriveInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE key[ CRYPT_MAX_KEYSIZE + 8 ], iv[ CRYPT_MAX_IVSIZE + 8 ];\n\tBYTE saltData[ 1 + CRYPT_MAX_IVSIZE + 8 ];\n\tint ivSize DUMMY_INIT, localKeySize = keySize, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( ( isCryptContext && isConvAlgo( cryptAlgo ) ) || \\\n\t\t\t  ( !isCryptContext && isMacAlgo( cryptAlgo ) ) );\n\tREQUIRES( keySize >= bitsToBytes( 40 ) && keySize <= CRYPT_MAX_KEYSIZE );\n\t\t\t  /* 40 bits is a special case for certificates encrypted with\n\t\t\t     RC2-40 */\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( saltLength >= 1 && saltLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( isIntegerRangeNZ( iterations ) );\n\tREQUIRES( isCryptContext == TRUE || isCryptContext == FALSE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Create the encryption/MAC context and get any required parameter \n\t   information.  Note that this assumes that the encryption algorithm\n\t   is a block cipher, which always seems to be the case */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalCryptContext = createInfo.cryptHandle;\n\tif( isCryptContext )\n\t\t{\n\t\tstatus = krnlSendMessage( iLocalCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &ivSize, CRYPT_CTXINFO_IVSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Since the salt also includes a diversifier as its first byte we copy \n\t   it to a working buffer with room for the extra data byte */\n\tREQUIRES( boundsCheck( 1, saltLength, 1 + CRYPT_MAX_IVSIZE ) );\n\tmemcpy( saltData + 1, salt, saltLength );\n\n\t/* Derive the encryption/MAC key and optional IV from the password */\n\tif( isCryptContext )\n\t\tsaltData[ 0 ] = KEYWRAP_ID_WRAPKEY;\n\telse\n\t\tsaltData[ 0 ] = KEYWRAP_ID_MACKEY;\n\tsetMechanismDeriveInfo( &deriveInfo, key, keySize, password, \n\t\t\t\t\t\t\tpasswordLength, CRYPT_ALGO_SHA1, saltData, \n\t\t\t\t\t\t\tsaltLength + 1, iterations );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t  &deriveInfo, MECHANISM_DERIVE_PKCS12 );\n\tif( cryptStatusOK( status ) && isCryptContext )\n\t\t{\n\t\tsaltData[ 0 ] = KEYWRAP_ID_IV;\n\t\tsetMechanismDeriveInfo( &deriveInfo, iv, ivSize, password, \n\t\t\t\t\t\t\t\tpasswordLength, CRYPT_ALGO_SHA1, saltData, \n\t\t\t\t\t\t\t\tsaltLength + 1, iterations );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t  &deriveInfo, MECHANISM_DERIVE_PKCS12 );\n\t\t}\n\tclearMechanismInfo( &deriveInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( key, CRYPT_MAX_KEYSIZE );\n\t\tzeroise( iv, CRYPT_MAX_IVSIZE );\n\t\tkrnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* We need to add special-case processing for RC2-40, which is still \n\t   universally used by Windows and possibly other implementations as \n\t   well.  The kernel (and pretty much everything else) won't allow keys \n\t   of less then MIN_KEYSIZE bytes, to get around this we create a \n\t   pseudo-key consisting of two copies of the string \"PKCS#12\" followed \n\t   by the actual key, with a total length of 19 bytes / 152 bits.  The \n\t   RC2 code checks for this special string at the start of any key that \n\t   it loads and only uses the last 40 bits.  This is a horrible kludge, \n\t   but RC2 is disabled by default (unless USE_PKCS12 is defined) so the \n\t   only time that it'll ever be used anyway is as RC2-40 */\n\tif( cryptAlgo == CRYPT_ALGO_RC2 && keySize == bitsToBytes( 40 ) )\n\t\t{\n\t\tmemmove( key + 14, key, bitsToBytes( 40 ) );\n\t\tmemcpy( key, \"PKCS#12PKCS#12\", 14 );\n\t\tlocalKeySize = 14 + bitsToBytes( 40 );\n\t\t}\n\n\t/* Create an encryption/MAC context and load the key and IV into it */\n\tsetMessageData( &msgData, key, localKeySize );\n\tstatus = krnlSendMessage( iLocalCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\tif( cryptStatusOK( status ) && isCryptContext )\n\t\t{\n\t\tsetMessageData( &msgData, iv, ivSize );\n\t\tstatus = krnlSendMessage( iLocalCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\t\t}\n\tzeroise( key, CRYPT_MAX_KEYSIZE );\n\tzeroise( iv, CRYPT_MAX_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iCryptContext = iLocalCryptContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create key wrap and MAC contexts from a password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint createPkcs12KeyWrapContext( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\tconst BOOLEAN initParams )\n\t{\n\tint status;\n\n\tassert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptOwner ) );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( initParams == TRUE || initParams == FALSE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Set up the parameters for the encryption key and IV if required.\n\t   The only (useful) encryption algorithm that's available is 3DES, so\n\t   we hardcode that in */\n\tif( initParams )\n\t\t{\n\t\tpkcs12objectInfo->cryptAlgo = CRYPT_ALGO_3DES;\n\t\tpkcs12objectInfo->keySize = bitsToBytes( 192 );\n\t\tstatus = initDeriveParams( cryptOwner, pkcs12objectInfo->salt, \n\t\t\t\t\t\t\t\t   CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t   &pkcs12objectInfo->saltSize,\n\t\t\t\t\t\t\t\t   &pkcs12objectInfo->iterations );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Derive the encryption key and IV from the password */\n\treturn( initContext( iCryptContext, pkcs12objectInfo->cryptAlgo, \n\t\t\t\t\t\t pkcs12objectInfo->keySize, password, \n\t\t\t\t\t\t passwordLength, pkcs12objectInfo->salt,\n\t\t\t\t\t\t pkcs12objectInfo->saltSize, \n\t\t\t\t\t\t pkcs12objectInfo->iterations, TRUE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint createPkcs12MacContext( INOUT PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\tconst BOOLEAN initParams )\n\t{\n\tint status;\n\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptOwner ) );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( initParams == TRUE || initParams == FALSE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Set up the parameters used to derive the MAC key if required */\n\tif( initParams )\n\t\t{\n\t\tstatus = initDeriveParams( cryptOwner, pkcs12info->macSalt, \n\t\t\t\t\t\t\t\t   CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t   &pkcs12info->macSaltSize,\n\t\t\t\t\t\t\t\t   &pkcs12info->macIterations );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Derive the MAC key from the password.  PKCS #12 currently hardcodes\n\t   this to HMAC-SHA1 with a 160-bit key */\n\treturn( initContext( iCryptContext, CRYPT_ALGO_HMAC_SHA1, \n\t\t\t\t\t\t 20, password, passwordLength, pkcs12info->macSalt,\n\t\t\t\t\t\t pkcs12info->macSaltSize, \n\t\t\t\t\t\t pkcs12info->macIterations, FALSE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A PKCS #12 keyset can contain steaming mounds of keys and whatnot, so \n   when we open it we parse the contents into memory for later use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t STDC_UNUSED const char *name,\n\t\t\t\t\t\t STDC_UNUSED const int nameLength,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )\n\t{\n\tPKCS12_INFO *pkcs12info;\n\tSTREAM *stream = &keysetInfoPtr->keysetFile->stream;\n\tint endPos DUMMY_INIT, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\tREQUIRES( name == NULL && nameLength == 0 );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\n\t/* If we're opening an existing keyset skip the outer header.  We do \n\t   this before we perform any setup operations to weed out potential \n\t   problem keysets */\n\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t{\n\t\tstatus = readPkcs12header( stream, &endPos, KEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Allocate the PKCS #12 object information */\n\tif( ( pkcs12info = clAlloc( \"initFunction\", \\\n\t\t\t\t\t\t\t\tsizeof( PKCS12_INFO ) * \\\n\t\t\t\t\t\t\t\tMAX_PKCS12_OBJECTS ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( pkcs12info, 0, sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS );\n\tDATAPTR_SET( keysetInfoPtr->keyData, pkcs12info );\n\tkeysetInfoPtr->keyDataSize = sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS;\n\tkeysetInfoPtr->keyDataNoObjects = MAX_PKCS12_OBJECTS;\n\n\t/* If this is a newly-created keyset, there's nothing left to do */\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\treturn( CRYPT_OK );\n\n\t/* Read all of the keys in the keyset */\n\tstatus = pkcs12ReadKeyset( &keysetInfoPtr->keysetFile->stream, \n\t\t\t\t\t\t\t   pkcs12info, MAX_PKCS12_OBJECTS, endPos, \n\t\t\t\t\t\t\t   KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"initFunction\", pkcs12info );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t\t{\n\t\t\t/* Reset the stream position to account for the header \n\t\t\t   information that we've already read */\n\t\t\tsseek( stream, 0 ) ;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Shut down the PKCS #12 state, flushing information to disk if necessary */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tPKCS12_INFO *pkcs12info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\tREQUIRES( DATAPTR_ISVALID( keysetInfoPtr->keyData ) );\n\n\t/* If the contents have been changed, allocate a working I/O buffer for \n\t   the duration of the flush and commit the changes to disk */\n#ifdef USE_PKCS12_WRITE \n\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY ) )\n\t\t{\n\t\tSTREAM *stream = &keysetInfoPtr->keysetFile->stream;\n\t\tBYTE buffer[ SAFEBUFFER_SIZE( STREAM_BUFSIZE ) + 8 ] STACK_ALIGN_DATA;\n\n\t\tREQUIRES( pkcs12info != NULL );\n\n\t\tsseek( stream, 0 );\n\t\tmemset( buffer, 0, STREAM_BUFSIZE );\n\t\t\t\t/* Keep static analysers happy */\n\t\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tsioctlSetString( stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t\t SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tstatus = pkcs12Flush( stream, pkcs12info, \n\t\t\t\t\t\t\t  keysetInfoPtr->keyDataNoObjects );\n\t\tsioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n#endif /* USE_PKCS12_WRITE */\n\n\t/* Free the PKCS #12 object information */\n\tif( pkcs12info != NULL )\n\t\t{\n\t\tpkcs12Free( pkcs12info, MAX_PKCS12_OBJECTS );\n\t\tzeroise( pkcs12info, keysetInfoPtr->keyDataSize );\n\t\tclFree( \"shutdownFunction\", pkcs12info );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\t}\n\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't send PKCS #12 data to persistent storage\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodPKCS12( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tstatus = initPKCS12get( keysetInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initPKCS12set( keysetInfoPtr );\n\treturn( status );\n\t}\n#endif /* USE_PKCS12 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs12.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPKCS #12 Definitions Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _PKCS12_DEFINED\n\n#define _PKCS12_DEFINED\n\n#if defined( _MSC_VER )\n  #if defined( USE_PKCS12_WRITE )\n\t#pragma message( \"  Building with PKCS #12 read and write enabled.\" )\n  #elif defined( USE_PKCS12 )\n\t#pragma message( \"  Building with PKCS #12 enabled.\" )\n  #endif /* PKCS #12 options */\n#endif /* USE_PKCS12 with VC++ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKCS #12 Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A PKCS #12 file can in theory contain multiple key and certificate \n   objects, however no normal implementation seems to use this capability\n   (a few oddball ones do, generally storing additional unencrypted\n   certificates alongside the private key and associated certificate).\n\n   There are half a dozen different interpretations as to how multiple \n   entries are supposed to work, both in terms of how to interpret the format \n   and what to do with things like MACing, which can only use a single key \n   even if there are multiple different encryption keys used for the data.  \n   In addition because of the complete abscence of key indexing information \n   there's no easy way to sort out which key or other object is used for \n   what.\n   \n   The code is written to handle multiple personalities like PKCS #15 and \n   PGP, but treats the presence or more than one private key as an error (in \n   practice it's a bit more complicated than that because of various PKCS \n   #12 vagaries, see the code in pkcs12_rd.c for more details) */\n\n#define MAX_PKCS12_OBJECTS\t\t8\n\n/* The minimum number of keying iterations to use when deriving a key wrap\n   key from a password */\n\n#define MIN_KEYING_ITERATIONS\t1000\n\n/* The minimum size of an object in a keyset, used for sanity-checking when\n   reading a keyset */\n\n#define MIN_OBJECT_SIZE\t\t\t64\n\n/* Parameters for PKCS #12's homebrew password-derivation mechanism.  The ID\n   values function as diversifiers when generating the same keying material\n   from a given password and in effect function as an extension of the salt */\n\n#define KEYWRAP_ID_WRAPKEY\t\t1\n#define KEYWRAP_ID_IV\t\t\t2\n#define KEYWRAP_ID_MACKEY\t\t3\n\n#define KEYWRAP_SALTSIZE\t\t8\n\n/* Flags for PKCS #12 object types */\n\n#define PKCS12_FLAG_NONE\t\t0x00\n#define PKCS12_FLAG_CERT\t\t0x01\t/* Object is certificate */\n#define PKCS12_FLAG_ENCCERT\t\t0x02\t/* Object is encrypted cert. */\n#define PKCS12_FLAG_PRIVKEY\t\t0x04\t/* Object is encrypted priv.key */\n#define PKCS12_FLAG_MAX\t\t\t0x07\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKCS #12 Types and Structures\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following structure contains the information for a private key or\n   certificate object */\n\ntypedef struct {\n\t/* The overall object data and the location of the payload within it, \n\t   usually in the form of encrypted data */\n\tBUFFER_OPT_FIXED( dataSize ) \\\n\tconst void *data;\t\t\t\t/* Object data */\n\tint dataSize;\n\tint payloadOffset, payloadSize;\t/* Payload within object data */\n\n\t/* Encryption information needed to process the payload */\n\tCRYPT_ALGO_TYPE cryptAlgo;\t\t/* Encryption algorithm */\n\tint keySize;\t\t\t\t\t/* Key size in bytes */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltSize ) \\\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint saltSize;\t\t\t\t\t/* Password-derivation salt */\n\tint iterations;\t\t\t\t\t/* Password-derivation iterations */\n\t} PKCS12_OBJECT_INFO;\n\n/* The following structure contains the information for one personality, \n   which covers one or more of a private key and a certificate */\n\ntypedef struct {\n\t/* General information */\n\tint flags;\t\t\t\t\t\t/* Object type information flags */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, labelLength ) \\\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];/* PKCS #12 object label */\n\tint labelLength;\n\tBUFFER( CRYPT_MAX_HASHSIZE, idLength ) \\\n\tBYTE id[ CRYPT_MAX_HASHSIZE + 8 ];/* PKCS #12 object ID */\n\tint idLength;\n\n\t/* Key and certificate object information */\n\tPKCS12_OBJECT_INFO keyInfo, certInfo;\n\n\t/* Alongside the per-object security information, PKCS #12 files also \n\t   have a MAC for the keyset as a whole.  This is supposedly optional \n\t   but many apps will reject the keyset (or even crash) if it's not \n\t   present.\n\n\t   Since the same key is used for both the whole-keyset MAC and the \n\t   individual objects, we can really only have a single personality per \n\t   keyset.  For now we deal with this by storing the MAC security \n\t   information alongside the other object information */\n\tCRYPT_CONTEXT iMacContext;\t\t/* MAC context */\n\tBUFFER( CRYPT_MAX_HASHSIZE, macSaltSize ) \\\n\tBYTE macSalt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint macSaltSize;\t\t\t\t/* Salt for MAC key */\n\tint macIterations;\t\t\t\t/* Number of iters.to derive MAC key */\n\tBOOLEAN macInitialised;\t\t\t/* Whether MAC context has been set up */\n\t} PKCS12_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKCS #12 Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in pkcs12.c */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS12_INFO *pkcs12FindEntry( IN_ARRAY( noPkcs12objects ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int noPkcs12objects,\n\t\t\t\t\t\t\t  IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t  IN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\t\t  const BOOLEAN isWildcardMatch );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS12_INFO *pkcs12FindFreeEntry( IN_ARRAY( noPkcs12objects ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int noPkcs12objects, \n\t\t\t\t\t\t\t\t  OUT_OPT_INDEX( noPkcs12objects ) int *index );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12freeObjectEntry( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12freeEntry( INOUT PKCS12_INFO *pkcs12info );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs12Free( INOUT_ARRAY( noPkcs12objects ) PKCS12_INFO *pkcs12info, \n\t\t\t\t IN_RANGE( 1, MAX_PKCS12_OBJECTS ) const int noPkcs12objects );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint createPkcs12KeyWrapContext( INOUT PKCS12_OBJECT_INFO *pkcs12objectInfo,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\tconst BOOLEAN initParams );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint createPkcs12MacContext( INOUT PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_TEXT const int passwordLength,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\tconst BOOLEAN initParams );\n\n/* Prototypes for functions in pkcs12_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint pkcs12ReadKeyset( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_ARRAY( maxNoPkcs12objects ) PKCS12_INFO *pkcs12info, \n\t\t\t\t\t  IN_LENGTH_SHORT const int maxNoPkcs12objects, \n\t\t\t\t\t  IN_LENGTH const long endPos,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS12get( INOUT KEYSET_INFO *keysetInfoPtr );\n\n/* Prototypes for functions in pkcs12_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint pkcs12ReadObject( INOUT STREAM *stream, \n\t\t\t\t\t  OUT PKCS12_INFO *pkcs12info, \n\t\t\t\t\t  const BOOLEAN isEncryptedCert,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pkcs12_wr.c */\n\n#ifdef USE_PKCS12_WRITE\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS12set( INOUT KEYSET_INFO *keysetInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pkcs12Flush( INOUT STREAM *stream, \n\t\t\t\t IN_ARRAY( noPkcs12objects ) const PKCS12_INFO *pkcs12info, \n\t\t\t\t IN_LENGTH_SHORT const int noPkcs12objects );\n#else\n  #define initPKCS12set( keysetInfoPtr )\tCRYPT_OK\n#endif /* USE_PKCS12_WRITE */\n\n#endif /* _PKCS12_DEFINED */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs12_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #12 Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs12.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs12.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS12\n\n/* OID information used to read a PKCS #12 keyset */\n\nstatic const CMS_CONTENT_INFO oidInfoEncryptedData = { 0, 2 };\n\nstatic const OID_INFO keyDataOIDinfo[] = {\n\t{ OID_CMS_ENCRYPTEDDATA, TRUE, &oidInfoEncryptedData },\n\t{ OID_CMS_DATA, FALSE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* OID information used to read decrypted PKCS #12 objects */\n\nstatic const OID_INFO certBagOIDinfo[] = {\n\t{ OID_PKCS12_CERTBAG, 0 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\nstatic const OID_INFO certOIDinfo[] = {\n\t{ OID_PKCS9_X509CERTIFICATE, 0 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy PKCS #12 object information.  If there's already content present in \n   the destination information then we copy in additional information, for\n   example to augment existing private-key data with an associated \n   certificate or vice-versa */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void copyObjectInfo( INOUT PKCS12_INFO *destPkcs12Info, \n\t\t\t\t\t\t\tconst PKCS12_INFO *srcPkcs12Info,\n\t\t\t\t\t\t\tconst BOOLEAN isCertificate )\n\t{\n\tassert( isWritePtr( destPkcs12Info, sizeof( PKCS12_INFO ) ) );\n\tassert( isReadPtr( srcPkcs12Info, sizeof( PKCS12_INFO ) ) );\n\n\tREQUIRES_V( isCertificate == TRUE || isCertificate == FALSE );\n\n\tdestPkcs12Info->flags |= srcPkcs12Info->flags;\n\tif( isCertificate )\n\t\t{\n\t\tmemcpy( &destPkcs12Info->certInfo, &srcPkcs12Info->certInfo, \n\t\t\t\tsizeof( PKCS12_OBJECT_INFO ) );\n\t\t}\n\telse\n\t\t{\n\t\tmemcpy( &destPkcs12Info->keyInfo, &srcPkcs12Info->keyInfo, \n\t\t\t\tsizeof( PKCS12_OBJECT_INFO ) );\n\t\t}\n\tif( destPkcs12Info->labelLength <= 0 && \\\n\t\tsrcPkcs12Info->labelLength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( srcPkcs12Info->labelLength, 1, \n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( destPkcs12Info->label, srcPkcs12Info->label,\n\t\t\t\tsrcPkcs12Info->labelLength );\n\t\tdestPkcs12Info->labelLength = srcPkcs12Info->labelLength;\n\t\t}\n\tif( destPkcs12Info->idLength <= 0 && \\\n\t\tsrcPkcs12Info->idLength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( srcPkcs12Info->idLength, 1, \n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( destPkcs12Info->id, srcPkcs12Info->id,\n\t\t\t\tsrcPkcs12Info->idLength );\n\t\tdestPkcs12Info->idLength = srcPkcs12Info->idLength;\n\t\t}\n\t}\n\n/* PKCS #12's lack of useful indexing information makes it extremely \n   difficult to reliably track and match up object types like private keys\n   and certificates.  The PKCS #15 code simply does a findEntry() to find \n   the entry that matches a newly-read object and attaches it to whatever's \n   already present for an existing entry if required (so for example it'd \n   attach a certificate to a previously-read private key), however with PKCS \n   #12 there's no reliable way to do this since entries may or may not have \n   ID information attached, which makes it impossible to reliably attach \n   keys to certificates.\n\n   To deal with this as best we can, we apply the following strategy:\n\n\t1. For the first item read, we save it as is in the zero-th position\n\t   (the item may or may not have an ID attached, typically if it's an\n\t   encrypted certificate then it won't, if it's a private key then it\n\t   will).\n\n\t2. For subsequent items read, if there's no ID information present then \n\t   we assume that it's attached to the previously-read first entry \n\t   provided that it's compatible with it, for example an ID-less \n\t   encrypted certificate attached to an encrypted key.  The \"no ID\n\t   information present\" can mean either that the currently-read item has \n\t   no ID information or that the first item has no ID information.\n\n\t3. If there's ID information attached, we handle it as we would for a \n\t   PKCS #15 item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int findObjectEntryLocation( OUT_PTR_COND PKCS12_INFO **pkcs12infoPtrPtr, \n\t\t\t\t\t\t\t\t\tIN_ARRAY( maxNoPkcs12objects ) \\\n\t\t\t\t\t\t\t\t\t\tconst PKCS12_INFO *pkcs12info, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int maxNoPkcs12objects, \n\t\t\t\t\t\t\t\t\tIN_BUFFER_OPT( idLength ) const void *id, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_KEYID_Z const int idLength,\n\t\t\t\t\t\t\t\t\tIN_FLAGS( PKCS12 ) const int flags )\n\n\t{\n\tconst PKCS12_INFO *pkcs12firstItem = &pkcs12info[ 0 ];\n\tconst PKCS12_INFO *pkcs12infoPtr;\n\tint index;\n\n\tassert( isReadPtr( pkcs12infoPtrPtr, sizeof( PKCS12_INFO * ) ) );\n\tassert( isReadPtrDynamic( pkcs12info, sizeof( PKCS12_INFO ) * \\\n\t\t\t\t\t\t\t\t\t\t  maxNoPkcs12objects ) );\n\tassert( ( id == NULL && idLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( id, idLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPkcs12objects ) );\n\tREQUIRES( ( id == NULL && idLength == 0 ) || \\\n\t\t\t  ( id != NULL && \\\n\t\t\t\tidLength > 0 && idLength < MAX_ATTRIBUTE_SIZE ) );\n\n\t/* Clear return value */\n\t*pkcs12infoPtrPtr = NULL;\n\n\t/* If this is the first entry being added, just add it as is */\n\tif( pkcs12FindFreeEntry( pkcs12info, maxNoPkcs12objects, \\\n\t\t\t\t\t\t\t &index ) != NULL && index == 0 )\n\t\t{\n\t\t*pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12firstItem;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's no ID information present, try and find an appropriate \n\t   existing item to attach it to.  This can occur in two variations,\n\t   either the existing entry is EncryptedData containing a certificate \n\t   with no ID information and the newly-read item is a private key, or \n\t   the existing item is a private key with ID information and the newly-\n\t   read item is EncryptedData containing a certificate with no ID \n\t   information */\n\tif( ( pkcs12firstItem->labelLength == 0 && \\\n\t\t  pkcs12firstItem->idLength == 0 ) || id == NULL )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* If the combination of items isn't an encrypted certificate (which \n\t\t   has no ID data associated with it since it's EncryptedData) rather \n\t\t   than a non-encrypted certificate or a private key (which is Data \n\t\t   and should have ID data associated with it) then we can't process \n\t\t   it */\n\t\tif( !( ( pkcs12firstItem->flags == PKCS12_FLAG_ENCCERT && \\\n\t\t\t\t flags == PKCS12_FLAG_PRIVKEY ) || \\\n\t\t\t   ( pkcs12firstItem->flags == PKCS12_FLAG_PRIVKEY && \\\n\t\t\t\t flags == PKCS12_FLAG_ENCCERT ) ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\tpkcs12infoPtr = NULL;\n\t\tLOOP_MED( i = 0, i < maxNoPkcs12objects, i++ )\n\t\t\t{\n\t\t\t/* If this entry isn't in use, continue */\n\t\t\tif( pkcs12info[ i ].flags == PKCS12_FLAG_NONE )\n\t\t\t\tcontinue;\n\n\t\t\t/* If we've already found a matching entry then finding a second \n\t\t\t   one is ambiguous since we don't know know which one to \n\t\t\t   associate the newly-read no-ID entry with */\n\t\t\tif( pkcs12infoPtr != NULL )\n\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t\t\t/* We've found a potential location to add the ID-less entry */\n\t\t\tpkcs12infoPtr = &pkcs12info[ i ];\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( pkcs12infoPtr != NULL )\n\t\t\t\t /* There's always a zero-th entry present to act as the \n\t\t\t\t\tknown elephant in Cairo */\n\n\t\t*pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There's an ID present, try and find a matching existing entry for \n\t   it */\n\tpkcs12infoPtr = pkcs12FindEntry( pkcs12info, maxNoPkcs12objects, \n\t\t\t\t\t\t\t\t\t CRYPT_IKEYID_KEYID, id, idLength,\n\t\t\t\t\t\t\t\t\t FALSE );\n\tif( pkcs12infoPtr != NULL )\n\t\t{\n\t\t*pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* This personality isn't present yet, find out where we can add the \n\t   object data */\n\tpkcs12infoPtr = pkcs12FindFreeEntry( pkcs12info, maxNoPkcs12objects, \n\t\t\t\t\t\t\t\t\t\t NULL );\n\tif( pkcs12infoPtr == NULL )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t*pkcs12infoPtrPtr = ( PKCS12_INFO * ) pkcs12infoPtr;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tImport Keys/Certificates\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unwrap and import an encrypted certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 7 ) ) \\\nstatic int importCertificate( const PKCS12_OBJECT_INFO *certObjectInfo,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\t  IN_BUFFER( passwordLen ) const void *password,\n\t\t\t\t\t\t\t  IN_LENGTH_TEXT const int passwordLen,\n\t\t\t\t\t\t\t  INOUT_BUFFER_FIXED( certObjectDataLen ) \\\n\t\t\t\t\t\t\t\t\tvoid *certObjectData,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int certObjectDataLen,\n\t\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCert )\n\t{\n\tCRYPT_CONTEXT iWrapContext;\n\tSTREAM stream;\n\tlong length DUMMY_INIT;\n\tint certDataSize, status;\n\n\tassert( isReadPtr( certObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLen ) );\n\tassert( isWritePtrDynamic( certObjectData, certObjectDataLen ) );\n\tassert( isWritePtr( iDataCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptOwner ) );\n\tREQUIRES( passwordLen >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLen <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( certObjectDataLen > MIN_OBJECT_SIZE && \\\n\t\t\t  certObjectDataLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\t*iDataCert = CRYPT_ERROR;\n\n\t/* Create the wrap context used to decrypt the public certificate data */\n\tstatus = createPkcs12KeyWrapContext( ( PKCS12_OBJECT_INFO * ) certObjectInfo, \n\t\t\t\t\t\t\t\t\t\t cryptOwner, password, passwordLen, \n\t\t\t\t\t\t\t\t\t\t &iWrapContext, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Decrypt the certificate */\n\tstatus = krnlSendMessage( iWrapContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t  certObjectData, certObjectDataLen );\n\tkrnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the decryption succeeded.  We have to be a bit careful\n\t   here because there are so many garbled certificates used with the\n\t   equally-garbled PKCS #12 format that an invalid object doesn't\n\t   necessarily imply that an incorrect decryption key was used.  To \n\t   avoid false positives, if we get an invalid encoding we try and read \n\t   the outer layer of wrapping around the certificate object, and if \n\t   that succeeds then it's a valid decrypt of a garbled certificate \n\t   rather than an invalid key leading to an invalid certificate.\n\t   \n\t   In addition to this we can occasionally get a failed decrypt that\n\t   looks like a valid ASN.1 object, typically a single primitive-encoded\n\t   ASN.1 item like a text string.  To deal with this we make sure that \n\t   it's pretty close to the length of the decrypted object, \"close\" \n\t   meaning that the difference is less than any block cipher padding \n\t   that may be removed by the decryption */\n\tstatus = checkCertObjectEncodingLength( certObjectData, \n\t\t\t\t\t\t\t\t\t\t\tcertObjectDataLen, \n\t\t\t\t\t\t\t\t\t\t\t&certDataSize );\n\tif( cryptStatusError( status ) || \\\n\t\tcertDataSize < certObjectDataLen - CRYPT_MAX_IVSIZE )\n\t\t{\n\t\tint sequenceLength;\n\n\t\tsMemConnect( &stream, certObjectData, certObjectDataLen );\n\t\tstatus = readSequence( &stream, &sequenceLength );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( sequenceLength < MIN_OBJECT_SIZE || \\\n\t\t\t  sequenceLength > certObjectDataLen ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readSequence( &stream, &sequenceLength );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( sequenceLength < MIN_OBJECT_SIZE || \\\n\t\t\t  sequenceLength > certObjectDataLen ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The data is garbled so that it doesn't look anything like a\n\t\t\t   CMS-wrapped certificate, report it as a decryption problem */\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t\t}\n\t\t\n\t\t/* The data at least looks like a CMS-wrapped certificate, since we \n\t\t   couldn't get the length via the encoding check, we have to use \n\t\t   the overall object size as an approximation of the length.  This\n\t\t   won't be the exact length because of cipher block padding, but\n\t\t   the cert-import code won't read past the end of the certificate\n\t\t   data */\n\t\tcertDataSize = certObjectDataLen;\n\t\t}\n\n\t/* Import the certificate as a data-only certificate.  At this point we \n\t   have two redundant CMS headers, one within the other, with the nested \n\t   inner header of the outer CMS header being the start of the inner CMS \n\t   header.  To handle this we read the outer CMS header with the \n\t   READCMS_FLAG_WRAPPERONLY flag set to avoid reading the start of the\n\t   inner header, which is then read by the second readCMSheader() \n\t   call */\n\tsMemConnect( &stream, certObjectData, certDataSize );\n\treadSequence( &stream, NULL );\n\tstatus = readCMSheader( &stream, certBagOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( certBagOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\tNULL, NULL, READCMS_FLAG_WRAPPERONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readCMSheader( &stream, certOIDinfo, \n\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( certOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\t\tNULL, &length, READCMS_FLAG_INNERHEADER | \\\n\t\t\t\t\t\t\t\t\t\t\t   READCMS_FLAG_DEFINITELENGTH );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t( length < MIN_OBJECT_SIZE || length > certObjectDataLen ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tENSURES( isIntegerRange( length ) );\n\tstatus = importCertFromStream( &stream, iDataCert, cryptOwner,\n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t   ( int ) length, \n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_DATAONLY_CERT );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Import an encrypted private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 6 ) ) \\\nstatic int importPrivateKey( const PKCS12_OBJECT_INFO *keyObjectInfo,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_USER cryptOwner,\n\t\t\t\t\t\t\t IN_HANDLE CRYPT_CONTEXT iPrivKeyContext,\n\t\t\t\t\t\t\t IN_BUFFER( passwordLen ) const void *password,\n\t\t\t\t\t\t\t IN_LENGTH_TEXT const int passwordLen,\n\t\t\t\t\t\t\t IN_BUFFER( keyObjectDataLen ) const void *keyObjectData,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int keyObjectDataLen,\n\t\t\t\t\t\t\t IN_BUFFER_OPT( labelLength ) const void *label,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int labelLength )\n\t{\n\tCRYPT_CONTEXT iWrapContext;\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtr( keyObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLen ) );\n\tassert( isReadPtrDynamic( keyObjectData, keyObjectDataLen) );\n\tassert( ( label == NULL && labelLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( label, labelLength ) );\n\n\tREQUIRES( cryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptOwner ) );\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( passwordLen >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLen <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( keyObjectDataLen > MIN_OBJECT_SIZE && \\\n\t\t\t  keyObjectDataLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( label == NULL && labelLength == 0 ) || \\\n\t\t\t  ( label != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( labelLength ) ) );\n\n\t/* Create the wrap context used to unwrap the private key */\n\tstatus = createPkcs12KeyWrapContext( ( PKCS12_OBJECT_INFO * ) keyObjectInfo, \n\t\t\t\t\t\t\t\t\t\t cryptOwner, password, passwordLen, \n\t\t\t\t\t\t\t\t\t\t &iWrapContext, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set the key label.  We have to set the label before we load the key \n\t   or the key load will be blocked by the kernel */\n\tif( label != NULL )\n\t\t{ \n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) label, \\\n\t\t\t\t\t\tmin( labelLength, CRYPT_MAX_TEXTSIZE ) ); \n\t\t}\n\telse\n\t\t{ \n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) \"Dummy label\", 11 ); \n\t\t}\n\tstatus = krnlSendMessage( iPrivKeyContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Import the encrypted private key into the PKC context */\n\tsetMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST * ) keyObjectData, \n\t\t\t\t\t\t  keyObjectDataLen, NULL, 0, iPrivKeyContext, \n\t\t\t\t\t\t  iWrapContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT, \n\t\t\t\t\t\t\t  &mechanismInfo, \n\t\t\t\t\t\t\t  MECHANISM_PRIVATEKEYWRAP_PKCS8 );\n\tclearMechanismInfo( &mechanismInfo );\n\tkrnlSendNotifier( iWrapContext, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKCS #12 Keys\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a set of objects in a keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \\\nstatic int readObjects( INOUT STREAM *stream, \n\t\t\t\t\t\tINOUT_ARRAY( maxNoPkcs12objects ) PKCS12_INFO *pkcs12info, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int maxNoPkcs12objects, \n\t\t\t\t\t\tIN_LENGTH_MIN( 32 ) const long endPos,\n\t\t\t\t\t\tconst BOOLEAN isEncryptedCert,\n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) * \\\n\t\t\t\t\t\t\t\t\tmaxNoPkcs12objects ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPkcs12objects ) );\n\tREQUIRES( endPos >= 32 && endPos < MAX_BUFFER_SIZE );\n\tREQUIRES( isEncryptedCert == TRUE || isEncryptedCert == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Read each object in the current collection */\n\tLOOP_MED_CHECK( stell( stream ) < endPos )\n\t\t{\n\t\tPKCS12_INFO localPkcs12Info, *pkcs12infoPtr;\n\t\tPKCS12_OBJECT_INFO *pkcs12ObjectInfoPtr;\n\t\tBOOLEAN isCertificate = FALSE;\n\n\t\t/* Read one object */\n\t\tstatus = pkcs12ReadObject( stream, &localPkcs12Info, \n\t\t\t\t\t\t\t\t   isEncryptedCert, errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( localPkcs12Info.flags & ( PKCS12_FLAG_CERT | \\\n\t\t\t\t\t\t\t\t\t  PKCS12_FLAG_ENCCERT ) )\n\t\t\tisCertificate = TRUE;\n\n\t\t/* Find the location where we'll copy over the new object data */\n\t\tstatus = findObjectEntryLocation( &pkcs12infoPtr, pkcs12info, \n\t\t\t\t\t\t\t\t\t\t  maxNoPkcs12objects, \n\t\t\t\t\t\t\t\t\t\t  localPkcs12Info.idLength <= 0 ? \\\n\t\t\t\t\t\t\t\t\t\t\t\tNULL : localPkcs12Info.id,\n\t\t\t\t\t\t\t\t\t\t  localPkcs12Info.idLength,\n\t\t\t\t\t\t\t\t\t\t  localPkcs12Info.flags );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs12freeObjectEntry( isCertificate ? \\\n\t\t\t\t\t&localPkcs12Info.certInfo : &localPkcs12Info.keyInfo );\n\t\t\tif( status == CRYPT_ERROR_OVERFLOW )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, errorInfo, \n\t\t\t\t\t\t  \"No more room in keyset data to add further \"\n\t\t\t\t\t\t  \"PKCS #12 items\" ) );\n\t\t\t\t}\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't reconcile ID-less object with existing \"\n\t\t\t\t\t  \"PKCS #12 objects\" ) );\n\t\t\t}\n\n\t\t/* Copy the newly-read PKCS #12 object information into the PKCS #12\n\t\t   keyset info */\n\t\tpkcs12ObjectInfoPtr = isCertificate ? &pkcs12infoPtr->certInfo : \\\n\t\t\t\t\t\t\t\t\t\t\t  &pkcs12infoPtr->keyInfo;\n\t\tif( pkcs12ObjectInfoPtr->data != NULL )\n\t\t\t{\n\t\t\tpkcs12freeObjectEntry( isCertificate ? \\\n\t\t\t\t\t&localPkcs12Info.certInfo : &localPkcs12Info.keyInfo );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Multiple conflicting %s found in keyset\",\n\t\t\t\t\t  isCertificate ? \"certificates\" : \"keys\" ) );\n\t\t\t}\n\t\tcopyObjectInfo( pkcs12infoPtr, &localPkcs12Info, isCertificate );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an entire keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint pkcs12ReadKeyset( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_ARRAY( maxNoPkcs12objects ) PKCS12_INFO *pkcs12info, \n\t\t\t\t\t  IN_LENGTH_SHORT const int maxNoPkcs12objects, \n\t\t\t\t\t  IN_LENGTH const long endPos,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) * \\\n\t\t\t\t\t\t\t\t\tmaxNoPkcs12objects ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPkcs12objects ) );\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( pkcs12info, 0, sizeof( PKCS12_INFO ) * maxNoPkcs12objects );\n\n\t/* Scan all of the objects in the keyset.  This gets quite complicated\n\t   because there are multiple points at which we can have a SET/SEQUENCE\n\t   OF and depending on the implementation multiple objects may be stored\n\t   at any of these points, so we have to handle multiple nesting points\n\t   at which we can find more than one of an object */\n\tLOOP_MED_INITCHECK( status = CRYPT_OK, \n\t\t\t\t\t\tcryptStatusOK( status ) && stell( stream ) < endPos )\n\t\t{\n\t\tlong payloadLength;\n\t\tint length, innerEndPos = CRYPT_ERROR, isEncrypted, noEOCs = 0;\n\n\t\t/* Read the CMS header encapsulation for the object.  At this point \n\t\t   we get to more PKCS #12 stupidity, if we hit CMS EncryptedData \n\t\t   (isEncrypted == TRUE) then it's actually a certificate (that \n\t\t   doesn't need to be encrypted), and if we hit CMS Data \n\t\t   (isEncrypted == FALSE) then it's usually a private key wrapped \n\t\t   within a bizarre reinvention of CMS EncryptedData that's nested \n\t\t   within the CMS Data, although in some rare cases it may be a \n\t\t   SEQUENCE OF certificates and/or private key data that doesn't \n\t\t   correspond to either of the above.  The combinations are:\n\n\t\t\tData\n\t\t\t\tSEQUENCE OF\n\t\t\t\t\tShroundedKeyBag | CertBag\n\t\t\t\n\t\t\tEncryptedData\n\t\t\t\tData (= Certificate) \n\n\t\t   So if we find EncryptedData then we know that it's definitely a \n\t\t   certificate (so far nothing has tried to put private keys in\n\t\t   EncryptedData, although the spec allows it).  If we find Data \n\t\t   then it could be anything, and we have to keep looking at a lower\n\t\t   level */\n\t\tstatus = readCMSheader( stream, keyDataOIDinfo, \n\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( keyDataOIDinfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tOID_INFO ),\n\t\t\t\t\t\t\t\t&isEncrypted, &payloadLength, \n\t\t\t\t\t\t\t\tREADCMS_FLAG_NONE );\n\t\tif( cryptStatusOK( status ) && payloadLength > MAX_INTLENGTH_SHORT )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid PKCS #12 object header\" ) );\n\t\t\t}\n\t\tREQUIRES( isIntegerRange( payloadLength ) );\n\t\tlength = ( int ) payloadLength;\n\n\t\t/* Deal with constructed OCTET STRINGs, see the comment in \n\t\t   readPkcs12header() for details */\n\t\tif( peekTag( stream ) == BER_OCTETSTRING )\n\t\t\treadOctetStringHole( stream, &length, 4, DEFAULT_TAG );\n\n\t\t/* Find out where the collection of PKCS #12 objects in the current\n\t\t   set of objects ends.  There may be only one, or many, and they\n\t\t   may or may not be of the same type */\n\t\tif( length != CRYPT_UNUSED )\n\t\t\tinnerEndPos = stell( stream ) + length;\n\t\telse\n\t\t\t{\n\t\t\t/* In order to get to this point without finding a length we\n\t\t\t   need to have encountered three indefinite-length wrappers,\n\t\t\t   which means that we need to skip three EOCs at the end */\n\t\t\tnoEOCs = 3;\n\t\t\t}\n\t\tif( !isEncrypted )\n\t\t\t{\n\t\t\tint innerLength;\n\n\t\t\t/* Skip the SET OF PKCS12Bag encapsulation */\n\t\t\tstatus = readSequenceI( stream, &innerLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tif( length == CRYPT_UNUSED && innerLength != CRYPT_UNUSED )\n\t\t\t\tinnerEndPos = stell( stream ) + innerLength;\n\t\t\t}\n\t\tif( innerEndPos == CRYPT_ERROR )\n\t\t\t{\n\t\t\tint innerLength;\n\n\t\t\t/* We still haven't got any length information, at this point \n\t\t\t   the best that we can do is assume that there's a single \n\t\t\t   encapsulated object present (which, in the rare situations\n\t\t\t   where this case arises, always seems to be the case) and\n\t\t\t   explicitly find its length before we can continue */\n\t\t\tstatus = getStreamObjectLength( stream, &innerLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tinnerEndPos = stell( stream ) + innerLength;\n\n\t\t\t/* In practice it's not quite this simple.  Firstly, this\n\t\t\t   approach is somewhat risky because we're calling \n\t\t\t   getStreamObjectLength() on a stream that could in theory be \n\t\t\t   non-seekable (although in practice file streams are always \n\t\t\t   seekable so this is more a theoretical than an actual \n\t\t\t   problem).  In addition PKCS #12 files usually contain a\n\t\t\t   single object that fits easily within the stream buffer, \n\t\t\t   so even if the stream was non-seekable the call would \n\t\t\t   usually work.\n\n\t\t\t   Secondly, and more critically, readObjects() calls\n\t\t\t   pkcs12ReadObject() which calls readRawObjectAlloc(), which\n\t\t\t   needs a definite length, again because it's dealing with a \n\t\t\t   non-seekable stream (and in this case it really may be a non-\n\t\t\t   seekable stream).  Since we're dealing with an indefinite\n\t\t\t   length, readRawObjectAlloc() can't continue.\n\t\t\t   \n\t\t\t   A kludge workaround for this would be to pass the innerLength \n\t\t\t   value in to readObjects() as a length hint and to tell it to \n\t\t\t   bypass the call to readRawObjectAlloc() in favour of a direct\n\t\t\t   malloc() and fixed-length read, duplicating part of \n\t\t\t   readRawObjectAlloc().  For now we'll leave this until there's \n\t\t\t   an actual demand for it */\n\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Couldn't get PKCS #12 object length information\" ) );\n\n\t\t\t}\n\n\t\t/* Read the set of objects */\n\t\tstatus = readObjects( stream, pkcs12info, maxNoPkcs12objects,\n\t\t\t\t\t\t\t  innerEndPos, isEncrypted, errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Skip any EOCs that may be present.  In the simplest case where\n\t\t   the data was encoded using all indefinte-length encoding we know\n\t\t   how many EOCs are present and skip them all */\n\t\tif( noEOCs > 0 )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t\tLOOP_SMALL_ALT( i = 0, i < noEOCs, i++ )\n\t\t\t\t{\n\t\t\t\tconst int value = checkEOC( stream );\n\t\t\t\tif( cryptStatusError( value ) )\n\t\t\t\t\t{\n\t\t\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\t\t\treturn( value );\n\t\t\t\t\t}\n\t\t\t\tif( value == FALSE )\n\t\t\t\t\t{\n\t\t\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If the data was encoded using a mixture of definite and \n\t\t\t   indefinite encoding there may be EOC's present even though \n\t\t\t   the length is known so we skip them if necessary.  We have to \n\t\t\t   make the reads speculative since the indefinite-length values \n\t\t\t   were processed inside readCMSheader(), so we don't know how \n\t\t\t   many there were */\n\t\t\tif( ( status = checkEOC( stream ) ) == TRUE )\n\t\t\t\tstatus = checkEOC( stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tpkcs12Free( pkcs12info, maxNoPkcs12objects );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tstatus = CRYPT_OK;\t/* checkEOC() returns TRUE/FALSE */\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tGet a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if 0\t/* Crack an RC2-40 key.  Call as 'keyCrack( certData, certDataSize )'\n\t\t   before the 'importCertificate()' call.  A more efficient version\n\t\t   of this is in ctx_rc2.c, the following code is really only \n\t\t   present for testing the process with known-key data */\n\n#pragma message( \"#############################\" )\n#pragma message( \"Building PKCS #12 key-cracker\" )\n#pragma message( \"#############################\" )\n\nstatic int keyCrack( const void *encData, const int length )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE data[ 32 ], key[ 32 ], *keyPtr = key + 14;\n\tint i, status;\n\n\t/* Test file: IV =  17 17 F1 B0 94 E8 EE F8\t\tencData + 0\n\t\t\t\t  PT =\t06 0B 2A 86 48 86 F7 0D\n\t\t\t\t\t\t-----------------------\n\t\t\t\t  XOR:\t11 1C DB 36 DC 6E 19 F5 \n\n\t   So encr. above = CT block 2.\n\t\t\t\t\t  =\t9C 4E 66 8A C7 6B 97 F5\t\tencData + 8\n\n\t   Actual:    IV =  6F A0 7E A5 65 00 65 6C\t\tencData + 0\n\t\t\t\t  PT =\t06 0B 2A 86 48 86 F7 0D\n\t\t\t\t\t\t-----------------------\n\t\t\t\t  XOR:\t69 AB 54 23 2D 86 92 61 \n\n\t   So encr. above = CT block 2.\n\t\t\t\t\t  =\t34 AA F1 83 BD 9C C0 15\t\tencData + 8 */\n\t\n//\tmemcpy( data, \"\\x17\\x17\\xF1\\xB0\\x94\\xE8\\xEE\\xF8\", 8 );\n\tmemcpy( data, \"\\x6F\\xA0\\x7E\\xA5\\x65\\x00\\x65\\x6C\", 8 );\n\tfor( i = 0; i < 8; i++ )\n\t\tdata[ i ] ^= i[ \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\" ];\n\n\tmemcpy( key, \"PKCS#12PKCS#12\", 14 );\n\tmemset( key + 14, 0, 5 );\n\n//\tmemcpy( keyPtr, \"\\x13\\x25\\x0c\\x1a\\x60\", 5 );\t// Test PKCS #12 file, file #1.\n//\tmemcpy( keyPtr, \"\\x2C\\x28\\x14\\xC4\\x01\", 5 );\t// \"Tellus\" PKCS #12 file, file #2\n\n\tfor( i = 0; i < 256; i++ )\n\t\t{\n\t\tint keyIndex;\n\n\t\tprintf( \"Trying keys %02X xx.\\n\", i );\n\t\tfflush( stdout );\n\t\twhile( keyPtr[ 0 ] == i )\n\t\t\t{\n\t\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RC2 );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcryptContext = createInfo.cryptHandle;\n\t\t\tsetMessageData( &msgData, key, 19 );\n\t\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) encData, 8 );\n\t\t\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n#if 0\t/* For key-crack */\n\t\t\t\tmemcpy( data, ( const BYTE * ) encData + 8, 8 );\n\t\t\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t\t\t\t  data, 8 );\n#else\t/* For full decrypt */\n\t\t\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) \\\n\t\t\t\t\t\t\t\t\t\t\t( ( const BYTE * ) encData + 8 ), \n\t\t\t\t\t\t\t\t\t\t  length - 8 );\n\t\t\t\tDEBUG_DUMP( \"crack_result\", ( const BYTE * ) encData + 8,\n\t\t\t\t\t\t\tlength - 8 );\n#endif /* 0 */\n\t\t\t\t}\n\t\t\tkrnlSendNotifier( cryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( data[ 0 ] == 0x06 && \\\n\t\t\t\t!memcmp( data, \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\", 8 ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Found at %02X %02X %02X %02X %02X.\\n\",\n\t\t\t\t\t\tkeyPtr[ 0 ], keyPtr[ 1 ], keyPtr[ 2 ],\n\t\t\t\t\t\tkeyPtr[ 3 ], keyPtr[ 4 ] );\n\t\t\t\tfflush( stdout );\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tfor( keyIndex = 4; keyIndex >= 0; keyIndex++ )\n\t\t\t\t{\n\t\t\t\tkeyPtr[ keyIndex ]++;\n\t\t\t\tif( keyPtr[ keyIndex ] > 0 )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( keyIndex == 1 )\n\t\t\t\t{\n\t\t\t\tprintf( \"Trying keys %02X %02X.\\n\", \n\t\t\t\t\t\tkeyPtr[ 0 ], keyPtr[ 1 ] );\n\t\t\t\tfflush( stdout );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/* Import a certificate as a data-only certificate object to be attached to \n   the private key */\n\n#ifdef USE_CERTIFICATES\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5, 7 ) ) \\\nstatic int importDataOnlyCertificate( const PKCS12_INFO *pkcs12infoPtr,\t\n\t\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_USER iCryptUser,\n\t\t\t\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCert,\n\t\t\t\t\t\t\t\t\t  IN_BUFFER( certIDlength ) const void *certID, \n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int certIDlength,\n\t\t\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iCertificate;\n\tconst PKCS12_OBJECT_INFO *certObjectInfo = &pkcs12infoPtr->certInfo;\n\tconst int certDataSize = certObjectInfo->payloadSize;\n\tDYNBUF pubKeyDB;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtr( pkcs12infoPtr, sizeof( PKCS12_INFO ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iDataCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( certID, certIDlength ) );\n\n\tREQUIRES( iCryptUser == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptUser ) );\n\tREQUIRES( isShortIntegerRangeNZ( certIDlength ) );\n\n\t/* Clear return values */\n\t*iCryptContext = *iDataCert = CRYPT_ERROR;\n\n\t/* If it's an unencrypted certificate (they almost never are) then we \n\t   can import it directly */\n\tif( pkcs12infoPtr->flags & PKCS12_FLAG_CERT )\n\t\t{\n\t\tsMemConnect( &stream, ( BYTE * ) certObjectInfo->data + \\\n\t\t\t\t\t\t\t\t\t\t certObjectInfo->payloadOffset, \n\t\t\t\t\t certDataSize );\n\t\tstatus = importCertFromStream( &stream, &iCertificate, iCryptUser,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t   certDataSize, \n\t\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_DATAONLY_CERT );\n\t\tsMemDisconnect( &stream );\n\t\t}\n\telse\n\t\t{\n\t\tBYTE certDataBuffer[ 2048 + 8 ], *certData = certDataBuffer;\n\n\t\tREQUIRES( pkcs12infoPtr->flags & PKCS12_FLAG_ENCCERT );\n\n\t\t/* It's an encrypted certificate, we need to decrypt it before we \n\t\t   can import it.  First we set up a buffer to decrypt the \n\t\t   certificate data */\n\t\tif( certDataSize > 2048 )\n\t\t\t{\n\t\t\tif( certDataSize >= MAX_INTLENGTH_SHORT )\n\t\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\tREQUIRES( rangeCheck( certDataSize, 1, MAX_INTLENGTH_SHORT ) );\n\t\t\tif( ( certData = clAlloc( \"importDataOnlyCertificate\", \\\n\t\t\t\t\t\t\t\t\t  certDataSize ) ) == NULL )\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t}\n\t\tREQUIRES( boundsCheck( certObjectInfo->payloadOffset, certDataSize,\n\t\t\t\t\t\t\t   certObjectInfo->dataSize ) );\n\t\tmemcpy( certData, \n\t\t\t\t( BYTE * ) certObjectInfo->data + \\\n\t\t\t\t\t\t   certObjectInfo->payloadOffset, certDataSize );\n\n\t\t/* Decrypt and import the certificate */\n\t\tstatus = importCertificate( certObjectInfo, iCryptUser, \n\t\t\t\t\t\t\t\t\tcertID, certIDlength, certData, \n\t\t\t\t\t\t\t\t\tcertDataSize, &iCertificate );\n\t\tzeroise( certData, certDataSize );\n\t\tif( certData != certDataBuffer )\n\t\t\tclFree( \"importDataOnlyCertificate\", certData );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't recreate certificate from stored certificate \"\n\t\t\t\t  \"data\" ) );\n\t\t}\n\t\t\n\t/* We've got the certificate, now create the public part of the context \n\t   from the certificate's encoded public-key components */\n\tstatus = dynCreate( &pubKeyDB, iCertificate, CRYPT_IATTRIBUTE_SPKI );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, dynData( pubKeyDB ), dynLength( pubKeyDB ) );\n\tstatus = iCryptReadSubjectPublicKey( &stream, iCryptContext,\n\t\t\t\t\t\t\t\t\t\t SYSTEM_OBJECT_HANDLE, TRUE );\n\tsMemDisconnect( &stream );\n\tdynDestroy( &pubKeyDB );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCertificate, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't recreate public key from certificate\" ) );\n\t\t}\n\n\t*iDataCert = iCertificate;\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n\n/* Get a key from a PKCS #12 keyset.  This gets pretty ugly both because \n   PKCS #12 keysets contain no effective indexing information (making it \n   impossible to look up objects within them) and because in most cases all \n   data, including public keys and certificates, is encrypted.  To handle \n   this we only allow private-key reads, and treat whatever's in the keyset \n   as being a match for any request, since without indexing information \n   there's no way to tell whether it really is a match or not */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tIN_OPT void *auxInfo, \n\t\t\t\t\t\t\tINOUT_OPT int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n#ifdef USE_CERTIFICATES\n\tCRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;\n#endif /* USE_CERTIFICATES */\n\tCRYPT_CONTEXT iCryptContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tconst PKCS12_INFO *pkcs12info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tconst PKCS12_INFO *pkcs12infoPtr;\n\tconst int auxInfoMaxLength = *auxInfoLength;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( auxInfo, auxInfoMaxLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \\\n\t\t\t  ( auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( *auxInfoLength ) ) );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( pkcs12info != NULL );\n\n\t/* Clear return values */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* Only private-key reads are possible */\n\tif( itemType != KEYMGMT_ITEM_PRIVATEKEY )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"PKCS #12 keysets only support private-key reads\" ) );\n\t\t}\n\n\t/* PKCS #12 doesn't provide any useful indexing information that we\n\t   can use to look up a key apart from an optional label, so if we get \n\t   a key ID type that we can't do anything with or we're matching on\n\t   the special-case key ID \"[none]\" we perform a fetch of the first \n\t   matching private key on the basis that most PKCS #12 keysets only \n\t   contain a single key of interest */\n\tif( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\tkeyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\tkeyIDtype == CRYPT_IKEYID_ISSUERID || \\\n\t\t( keyIDlength == 6 && !strCompare( keyID, \"[none]\", 6 ) ) )\n\t\t{\n\t\tpkcs12infoPtr = pkcs12FindEntry( pkcs12info,\n\t\t\t\t\t\t\t\t\t\t keysetInfoPtr->keyDataNoObjects,\n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t TRUE );\n\t\t}\n\telse\n\t\t{\n\t\t/* Find a private-key entry */\n\t\tpkcs12infoPtr = pkcs12FindEntry( pkcs12info,\n\t\t\t\t\t\t\t\t\t\t keysetInfoPtr->keyDataNoObjects,\n\t\t\t\t\t\t\t\t\t\t keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t\t\t\t\t FALSE );\n\t\t}\n\tif( pkcs12infoPtr == NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No information present for this ID\" ) );\n\t\t}\n\tif( pkcs12infoPtr->keyInfo.data == NULL )\n\t\t{\n\t\t/* There's not enough information present to get a private key */\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No private key data present for this ID\" ) );\n\t\t}\n\n\t/* If we're just checking whether an object exists, return now.  If all\n\t   that we want is the key label, copy it back to the caller and exit */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\treturn( CRYPT_OK );\n\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t{\n\t\treturn( attributeCopyParams( auxInfo, auxInfoMaxLength, \n\t\t\t\t\t\t\t\t\t auxInfoLength, pkcs12infoPtr->label, \n\t\t\t\t\t\t\t\t\t pkcs12infoPtr->labelLength ) );\n\t\t}\n\n\t/* Make sure that the user has supplied a password */\n\tif( auxInfo == NULL )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t/* If there's a certificate present with the private key, import it as a \n\t   data-only certificate object to be attached to the private key */\n#ifdef USE_CERTIFICATES\n\tif( pkcs12infoPtr->certInfo.data != NULL )\n\t\t{\n\t\tstatus = importDataOnlyCertificate( pkcs12infoPtr, \n\t\t\t\t\t\t\t\t\t\t\tkeysetInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t\t\t&iCryptContext, &iDataCert,\n\t\t\t\t\t\t\t\t\t\t\tauxInfo, *auxInfoLength,\n\t\t\t\t\t\t\t\t\t\t\tKEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( iDataCert != CRYPT_ERROR )\n\t\t\t{\n\t\t\tstatus = iCryptVerifyID( iDataCert, keyIDtype, keyID, \n\t\t\t\t\t\t\t\t\t keyIDlength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\t\t\tretExt( status, \n\t\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t\t  \"Certificate fetched for ID type %s doesn't \"\n\t\t\t\t\t\t  \"actually correspond to the given ID\", \n\t\t\t\t\t\t  getKeyIDName( keyIDtype ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n#endif /* USE_CERTIFICATES */\n\t\t{\n\t\t/* Create the private-key object that we'll be importing the key \n\t\t   data into.  In yet another piece of design brilliance, the PKC \n\t\t   algorithm that's needed to create the public/private-key context \n\t\t   is stored inside the encrypted key data, so we can't create a \n\t\t   context to import the key data into until we've already imported \n\t\t   the key data.  To get around this we default to CRYPT_ALGO_RSA, \n\t\t   which is almost always the case */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiCryptContext = createInfo.cryptHandle;\n\t\t}\n\n\t/* Import the wrapped private key */\n\tstatus = importPrivateKey( &pkcs12infoPtr->keyInfo, \n\t\t\t\t\tkeysetInfoPtr->ownerHandle, iCryptContext,\n\t\t\t\t\tauxInfo, *auxInfoLength, \n\t\t\t\t\t( const BYTE * ) pkcs12infoPtr->keyInfo.data + \\\n\t\t\t\t\t\t\t\t\t pkcs12infoPtr->keyInfo.payloadOffset,\n\t\t\t\t\tpkcs12infoPtr->keyInfo.payloadSize, \n\t\t\t\t\t( pkcs12infoPtr->labelLength > 0 ) ? \\\n\t\t\t\t\t\tpkcs12infoPtr->label : NULL, \n\t\t\t\t\tpkcs12infoPtr->labelLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tif( iDataCert != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't unwrap and import private key\" ) );\n\t\t}\n\n#ifdef USE_CERTIFICATES\n\t/* Connect the data-only certificate object to the private-key context \n\t   if necessary.  This is an internal object used only by the context so \n\t   we tell the kernel to mark it as owned by the context only */\n\tif( iDataCert != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t  &iDataCert, SETDEP_OPTION_NOINCREF );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't attach certificate to key\" ) );\n\t\t\t}\n\t\t}\n#endif /* USE_CERTIFICATES */\n\t*iCryptHandle = iCryptContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS12get( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS12 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs12_rdo.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #12 Object-Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs12.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs12.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS12\n\n/* OID information used to read a PKCS #12 keyset */\n\nstatic const OID_INFO keyCertBagOIDinfo[] = {\n\t{ OID_PKCS12_SHROUDEDKEYBAG, TRUE },\n\t{ OID_PKCS12_CERTBAG, FALSE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* OID information used to read decrypted PKCS #12 objects */\n\nstatic const OID_INFO certBagOIDinfo[] = {\n\t{ OID_PKCS12_CERTBAG, 0 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\nstatic const OID_INFO certOIDinfo[] = {\n\t{ OID_PKCS9_X509CERTIFICATE, 0 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* Protection algorithms used for encrypted keys and certificates, and a \n   mapping from PKCS #12 to cryptlib equivalents.  Beyond these there are\n   also 40- and 128-bit RC4 and 128-bit RC2, but nothing seems to use\n   them.  40-bit RC2 is used by Windows to, uhh, \"protect\" public\n   certificates so we have to support it in order to be able to read\n   certificates (see the comment in keymgmt/pkcs12.c for details on how\n   the 40-bit RC2 key is handled) */\n\nenum { PKCS12_ALGO_NONE, PKCS12_ALGO_3DES_192, PKCS12_ALGO_3DES_128, \n\t   PKCS12_ALGO_RC2_40 };\n\ntypedef struct {\n\tconst CRYPT_ALGO_TYPE cryptAlgo;\n\tconst int keySize;\n\t} PKCS12_ALGO_MAP;\n\nstatic const PKCS12_ALGO_MAP algoMap3DES_192 = { CRYPT_ALGO_3DES, bitsToBytes( 192 ) };\nstatic const PKCS12_ALGO_MAP algoMap3DES_128 = { CRYPT_ALGO_3DES, bitsToBytes( 128 ) };\nstatic const PKCS12_ALGO_MAP algoMapRC2_40 = { CRYPT_ALGO_RC2, bitsToBytes( 40 ) };\n\nstatic const OID_INFO encryptionOIDinfo[] = {\n\t{ OID_PKCS12_PBEWITHSHAAND3KEYTRIPLEDESCBC, PKCS12_ALGO_3DES_192, \n\t  &algoMap3DES_192 },\n\t{ OID_PKCS12_PBEWITHSHAAND2KEYTRIPLEDESCBC, PKCS12_ALGO_3DES_128,\n\t  &algoMap3DES_128 },\n\t{ OID_PKCS12_PBEWITHSHAAND40BITRC2CBC, PKCS12_ALGO_RC2_40,\n\t  &algoMapRC2_40 },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* PKCS #12 attributes.  This is a subset of the full range that can be \n   used, we skip any that we don't care about using a wildcard OID match */\n\nenum { PKCS12_ATTRIBUTE_NONE, PKCS12_ATTRIBUTE_LABEL, PKCS12_ATTRIBUTE_ID };\n\nstatic const OID_INFO attributeOIDinfo[] = {\n\t{ OID_PKCS9_FRIENDLYNAME, PKCS12_ATTRIBUTE_LABEL },\n\t{ OID_PKCS9_LOCALKEYID, PKCS12_ATTRIBUTE_ID },\n\t{ WILDCARD_OID, PKCS12_ATTRIBUTE_NONE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read protection algorithm information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readProtAlgoInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t\t\t OUT_INT_SHORT_Z int *keySize )\n\t{\n\tconst OID_INFO *oidInfoPtr;\n\tconst PKCS12_ALGO_MAP *algoMapInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( keySize, sizeof( int ) ) );\n\n\t/* Clear return values */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\t*keySize = 0;\n\n\t/* Read the wrapper and the protection algorithm OID and extract the\n\t   protection information parameters for it */\n\treadSequence( stream, NULL );\n\tstatus = readOIDEx( stream, encryptionOIDinfo, \n\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( encryptionOIDinfo, OID_INFO ), \n\t\t\t\t\t\t&oidInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\talgoMapInfoPtr = oidInfoPtr->extraInfo;\n\t*cryptAlgo = algoMapInfoPtr->cryptAlgo;\n\t*keySize = algoMapInfoPtr->keySize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read key-derivation information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int readKeyDerivationInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  OUT_BUFFER( saltMaxLen, *saltLen ) void *salt,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int saltMaxLen,\n\t\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( saltMaxLen ) int *saltLen,\n\t\t\t\t\t\t\t\t  OUT_INT_SHORT_Z int *iterations )\n\t{\n\tlong intValue;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( salt, saltMaxLen ) );\n\tassert( isWritePtr( saltLen, sizeof( int ) ) );\n\tassert( isWritePtr( iterations, sizeof( int ) ) );\n\n\tREQUIRES( saltMaxLen >= 16 && saltMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( salt, 0, min( 16, saltMaxLen ) );\n\t*saltLen = *iterations = 0;\n\n\t/* Read the wrapper and salt value */\n\treadSequence( stream, NULL );\n\tstatus = readOctetString( stream, salt, saltLen, 1, saltMaxLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the iteration count and make sure that it's within a sensible\n\t   range */\n\tstatus = readShortInteger( stream, &intValue );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( intValue < 1 || intValue > MAX_KEYSETUP_ITERATIONS )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tENSURES( isIntegerRange( intValue ) );\n\t*iterations = ( int ) intValue;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead PKCS #12 Object Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an object's attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readObjectAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT PKCS12_INFO *pkcs12info )\n\t{\n\tint endPos, length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\n\t/* Determine how big the collection of attributes is */\n\tstatus = readSet( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\n\t/* Read the collection of attributes */\n\tLOOP_MED_CHECK( stell( stream ) < endPos )\n\t\t{\n\t\tBYTE stringBuffer[ ( CRYPT_MAX_TEXTSIZE * 2 ) + 8 ];\n\t\tint attributeType, stringLength, srcIndex, destIndex;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Read the outer wrapper and determine the attribute type based on\n\t\t   the OID */\n\t\treadSequence( stream, NULL );\n\t\tstatus = readOID( stream, attributeOIDinfo, \n\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( attributeOIDinfo, OID_INFO ), \n\t\t\t\t\t\t  &attributeType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Read the wrapper around the attribute payload */\n\t\tstatus = readSet( stream, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tswitch( attributeType )\n\t\t\t{\n\t\t\tcase PKCS12_ATTRIBUTE_NONE:\n\t\t\t\t/* It's a don't-care attribute, skip it */\n\t\t\t\tif( length > 0 )\n\t\t\t\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS12_ATTRIBUTE_LABEL:\n\t\t\t\t/* Read the label, translating it from Unicode.  We assume\n\t\t\t\t   that it's just widechar ASCII/latin-1 (which always seems\n\t\t\t\t   to be the case), which avoids OS-specific i18n \n\t\t\t\t   headaches */\n\t\t\t\tstatus = readCharacterString( stream, stringBuffer, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE * 2, &stringLength,\n\t\t\t\t\t\t\t\t\tBER_STRING_BMP );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\tbreak;\n\t\t\t\tLOOP_LARGE_ALT( srcIndex = destIndex = 0, \n\t\t\t\t\t\t\t\tsrcIndex < stringLength, \n\t\t\t\t\t\t\t\t( srcIndex +=2, destIndex++ ) )\n\t\t\t\t\t{\n\t\t\t\t\tpkcs12info->label[ destIndex ] = \\\n\t\t\t\t\t\t\t\tstringBuffer[ srcIndex + 1 ];\n\t\t\t\t\t}\n\t\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\t\tpkcs12info->labelLength = destIndex;\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS12_ATTRIBUTE_ID:\n\t\t\t\t/* It's a binary-blob ID value, usually a 32-bit little-\n\t\t\t\t   endian integer, remember it in case it's needed later \n\t\t\t\t   (this is the sole vaguely-useful ID that PKCS #12\n\t\t\t\t   provides, and can sometimes be used to match\n\t\t\t\t   certificates to their corresponding private keys) */\n\t\t\t\tstatus = readOctetString( stream, pkcs12info->id, \n\t\t\t\t\t\t\t\t\t\t  &pkcs12info->idLength, \n\t\t\t\t\t\t\t\t\t\t  1, CRYPT_MAX_HASHSIZE );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read object information.  The standard unencrypted object is always a\n   certificate, the encrypted object can be a certificate as well, or a \n   private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readObjectInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t   OUT PKCS12_OBJECT_INFO *pkcs12objectInfo,\n\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tlong length;\n\tint payloadOffset DUMMY_INIT;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tmemset( pkcs12objectInfo, 0, sizeof( PKCS12_OBJECT_INFO ) );\n\n\t/* Read the inner portion of the redundantly-nested object types and\n\t   remember the payload details within it */\n\tstatus = readCMSheader( stream, certOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( certOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\tNULL, &length, READCMS_FLAG_INNERHEADER | \\\n\t\t\t\t\t\t\t\t\t\t   READCMS_FLAG_DEFINITELENGTH );\n\tif( cryptStatusOK( status ) && \\\n\t\t( length < MIN_OBJECT_SIZE || length > MAX_INTLENGTH_SHORT ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tpayloadOffset = stell( stream );\n\t\tstatus = sSkip( stream, length, SSKIP_MAX );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid certificate payload data\" ) );\n\t\t}\n\tpkcs12objectInfo->payloadOffset = payloadOffset;\n\tpkcs12objectInfo->payloadSize = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isIncorrectNestedContent( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int contentLength )\n\t{\n\tSTREAM localStream;\n\tvoid *dataPtr;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( contentLength ) );\n\n\t/* The incorrect nested content is always an OCTET STRING, so if we\n\t   don't find that then there's nothing further to check */\n\tif( peekTag( stream ) != BER_OCTETSTRING )\n\t\t{\n\t\t/* Since we're reading encrypted data, we could encounter anything \n\t\t   at this point, including things that obviously aren't valid \n\t\t   ASN.1.  This means that the stream error state will be set, so\n\t\t   we have to explicitly clear the error state before we continue */\n\t\tsClearError( stream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* We've found what could be an OCTET STRING, check if it's a valid \n\t   encoding for one and whether it fits exactly inside the content */\n\tstatus = sMemGetDataBlock( stream, &dataPtr, 8 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tsMemConnect( &localStream, dataPtr, 8 );\n\tstatus = readOctetStringHole( &localStream, &length, MIN_OBJECT_SIZE, \n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tsMemDisconnect( &localStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( sizeofObject( length ) != contentLength )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readEncryptedObjectInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tOUT PKCS12_OBJECT_INFO *pkcs12objectInfo,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isEncryptedCert,\n\t\t\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n#ifdef USE_ERRMSGS\n\tconst char *objectName = isEncryptedCert ? \"encrypted certificate\" : \\\n\t\t\t\t\t\t\t\t\t\t\t   \"encrypted private key\";\n#endif /* USE_ERRMSGS */\n\tint payloadOffset DUMMY_INIT, payloadLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12objectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isEncryptedCert == TRUE || isEncryptedCert == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tmemset( pkcs12objectInfo, 0, sizeof( PKCS12_OBJECT_INFO ) );\n\n\t/* Read the encryption algorithm information */\n\tstatus = readProtAlgoInfo( stream, &pkcs12objectInfo->cryptAlgo,\n\t\t\t\t\t\t\t   &pkcs12objectInfo->keySize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid %s protection algorithm\", objectName ) );\n\t\t}\n\t\n\t/* Read the key-derivation parameters */\n\tstatus = readKeyDerivationInfo( stream, pkcs12objectInfo->salt,\n\t\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t\t&pkcs12objectInfo->saltSize,\n\t\t\t\t\t\t\t\t\t&pkcs12objectInfo->iterations );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid %s protection parameters\", objectName ) );\n\t\t}\n\n\t/* Read the start of the encrypted content.  This has a variety of \n\t   encapsulations depending on how its hidden inside the PKCS #12 \n\t   object so we read it as a generic object.  readGenericHole()\n\t   disallows indefinite-length encodings so we know that the returned \n\t   payload length will have a definite value */\n\tstatus = readGenericHole( stream, &payloadLength, MIN_OBJECT_SIZE, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusOK( status ) && isEncryptedCert && \\\n\t\t( payloadLength % 4 ) == 0 && \\\n\t\tisIncorrectNestedContent( stream, payloadLength ) )\n\t\t{\n\t\t/* Some CAs incorrectly interpret the content encoding as being\n\t\t   [0] EXPLICIT OCTET STRING instead of [0] IMPLICIT OCTET STRING.\n\t\t   This is tricky to detect since 1/256 encrypted data blocks will\n\t\t   look, to a peekTag(), like an OCTET STRING.  To detect this we\n\t\t   first take advantage of the fact that it only occurs for \n\t\t   encrypted certificates and that the length will be a multiple \n\t\t   of four bytes (either a cipher block size multiple of 8 or 16\n\t\t   bytes wrapped in a four-byte tag+length header), and if those\n\t\t   conditions are met check for an encapsulated OCTET STRING.  If\n\t\t   we find one, we dig one level further down into the data to get\n\t\t   the actual content */\n\t\tDEBUG_DIAG(( \"Compensating for invalid content encoding of \"\n\t\t\t\t\t \"OCTET STRING inside [0] data\" ));\n\t\tstatus = readOctetStringHole( stream, &payloadLength, \n\t\t\t\t\t\t\t\t\t  MIN_OBJECT_SIZE, DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tpayloadOffset = stell( stream );\n\t\tstatus = sSkip( stream, payloadLength, SSKIP_MAX );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid %s payload data\", objectName ) );\n\t\t}\n\tpkcs12objectInfo->payloadOffset = payloadOffset;\n\tpkcs12objectInfo->payloadSize = payloadLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKCS #12 Keys\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a single object in a keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint pkcs12ReadObject( INOUT STREAM *stream, \n\t\t\t\t\t  OUT PKCS12_INFO *pkcs12info, \n\t\t\t\t\t  const BOOLEAN isEncryptedCert,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tPKCS12_OBJECT_INFO localPkcs12ObjectInfo, *pkcs12ObjectInfoPtr;\n\tSTREAM objectStream;\n\tBOOLEAN isPrivateKey = FALSE;\n\tvoid *objectData;\n\tint objectLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\t\n\tREQUIRES( isEncryptedCert == TRUE || isEncryptedCert == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tmemset( pkcs12info, 0, sizeof( PKCS12_INFO ) );\n\n\t/* Read the current object's data */\n\tstatus = readRawObjectAlloc( stream, &objectData, &objectLength,\n\t\t\t\t\t\t\t\t MIN_OBJECT_SIZE, MAX_INTLENGTH_SHORT - 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't read PKCS #12 object data\" ) );\n\t\t}\n\tANALYSER_HINT( objectData != NULL );\n\n\t/* Read the object information from the in-memory object data.  First we \n\t   have to find out what it is that we're dealing with, caused by yet \n\t   more PKCS #12 braindamage in which the same object types can be \n\t   encapsulated in different ways in different locations.  The nesting \n\t   is:\n\n\t\t\tData\n\t\t\t\tSEQUENCE OF\n\t\t\t\t\tShroundedKeyBag | CertBag\t<- Current position\n\t\t\t\n\t\t\tEncryptedData\n\t\t\t\tData (= Certificate)\t\t\t<- Current position\n\n\t   with the current level being either the ShroundedKeyBag/CertBag or\n\t   Data.  If we're expecting Data (denoted by the isEncryptedCert flag\n\t   being set, the PKCS #12 braindamage leads to counterintuitive \n\t   control-flag naming) then we read it as is, if we're expecting some\n\t   other content-type then we have to analyse it to see what we've got */\n\tsMemConnect( &objectStream, objectData, objectLength );\n\tif( isEncryptedCert )\n\t\t{\n\t\t/* We're reading a public certificate held within CMS EncryptedData, \n\t\t   skip the encapsulation to get to the encryption information */\n\t\treadSequence( &objectStream, NULL );\n\t\tstatus = readFixedOID( &objectStream, OID_CMS_DATA, \n\t\t\t\t\t\t\t   sizeofOID( OID_CMS_DATA ) );\n\t\t}\n\telse\n\t\t{\n\t\tint isEncryptedPrivateKey;\n\n\t\t/* We're reading either a private key held within a ShroudedKeyBag \n\t\t   or a certificate within a CertBag, see what we've got.  As usual\n\t\t   with PKCS #12 there are complications, in this case because \n\t\t   certificates are stored within a redundantly nested \n\t\t   X509Certificate object within a CertBag object, so we have to \n\t\t   read the outer CMS header with the READCMS_FLAG_WRAPPERONLY flag \n\t\t   set to avoid reading the start of the inner header, which is then \n\t\t   read by the second readCMSheader() call.  Since this skips the\n\t\t   normal read of the inner header, we have to explicitly read it if\n\t\t   it's not a CertBag */\n\t\tstatus = readCMSheader( &objectStream, keyCertBagOIDinfo, \n\t\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( keyCertBagOIDinfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tOID_INFO ),\n\t\t\t\t\t\t\t\t&isEncryptedPrivateKey, NULL, \n\t\t\t\t\t\t\t\tREADCMS_FLAG_WRAPPERONLY );\n\t\tif( !cryptStatusError( status ) && isEncryptedPrivateKey )\n\t\t\t{\n\t\t\tisPrivateKey = TRUE;\n\t\t\tstatus = readSequence( &objectStream, NULL );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &objectStream );\n\t\tclFree( \"readObject\", objectData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #12 object header\" ) );\n\t\t}\n\n\t/* Read the object data, either as an encrypted object if it's a private \n\t   key or an encrypted certificate, or as plain data if it's a standard \n\t   certificate */\n\tif( isEncryptedCert || isPrivateKey )\n\t\t{\n\t\tstatus = readEncryptedObjectInfo( &objectStream, \n\t\t\t\t\t\t\t\t\t\t  &localPkcs12ObjectInfo, \n\t\t\t\t\t\t\t\t\t\t  isEncryptedCert, errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readObjectInfo( &objectStream, &localPkcs12ObjectInfo, \n\t\t\t\t\t\t\t\t errorInfo );\n\t\t}\n\tif( cryptStatusOK( status ) && stell( &objectStream ) < objectLength )\n\t\t{\n\t\t/* There are object attributes present, read these as well.  Note \n\t\t   that these apply to the overall set of objects, so we read them\n\t\t   into the general information rather than the per-object \n\t\t   information */\n\t\tstatus = readObjectAttributes( &objectStream, pkcs12info );\n\t\t}\n\tsMemDisconnect( &objectStream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"readObject\", objectData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \"Invalid %s information\",\n\t\t\t\t  isPrivateKey ? \"private key\" : \"certificate\" ) );\n\t\t}\n\n\t/* Remember the encoded object data */\n\tif( isEncryptedCert )\n\t\tpkcs12info->flags = PKCS12_FLAG_ENCCERT;\n\telse\n\t\t{\n\t\tif( isPrivateKey )\n\t\t\tpkcs12info->flags = PKCS12_FLAG_PRIVKEY;\n\t\telse\n\t\t\tpkcs12info->flags = PKCS12_FLAG_CERT;\n\t\t}\n\tpkcs12ObjectInfoPtr = isPrivateKey ? &pkcs12info->keyInfo : \\\n\t\t\t\t\t\t\t\t\t\t &pkcs12info->certInfo;\n\tmemcpy( pkcs12ObjectInfoPtr, &localPkcs12ObjectInfo, \n\t\t\tsizeof( PKCS12_OBJECT_INFO ) );\n\tpkcs12ObjectInfoPtr->data = objectData;\n\tpkcs12ObjectInfoPtr->dataSize = objectLength;\n\tENSURES( boundsCheck( pkcs12ObjectInfoPtr->payloadOffset, \n\t\t\t\t\t\t  pkcs12ObjectInfoPtr->payloadSize,\n\t\t\t\t\t\t  pkcs12ObjectInfoPtr->dataSize ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS12 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs12_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #12 Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2002\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This code is based on breakms.c, which breaks the encryption of several of\n   MS's extremely broken PKCS #12 implementations.  Because of the security\n   problems associated with key files produced by MS software and the fact\n   that this format is commonly used to spray private keys around without any\n   regard to their sensitivity, cryptlib doesn't support it as a writeable\n   format.  As one vendor who shall remain anonymous put it, \"We don't want \n   to put our keys anywhere where MS software can get to them\" */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs12.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs12.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS12_WRITE\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the garbled PKCS #12 version of a CMS wrapper */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeNonCMSheader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  IN_BUFFER( oidLength ) const BYTE *oid, \n\t\t\t\t\t\t\t  IN_RANGE( 1, MAX_OID_SIZE ) const int oidLength, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int length, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int attrDataLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( oid, oidLength ) );\n\n\tREQUIRES( oidLength >= MIN_OID_SIZE && oidLength <= MAX_OID_SIZE );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( isShortIntegerRangeNZ( attrDataLength ) );\n\n\twriteSequence( stream, sizeofOID( oid ) + \\\n\t\t\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( length ) ) + \\\n\t\t\t\t\t\t   sizeofShortObject( attrDataLength ) );\n\tswrite( stream, oid, oidLength );\n\twriteConstructed( stream, sizeofShortObject( length ), 0 );\n\treturn( writeSequence( stream, length ) );\n\t}\n\n/* Write the MAC data at the end of the keyset */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofMacData( const PKCS12_INFO *pkcs12info ) \n\t{\n\tassert( isReadPtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\n\treturn( sizeofShortObject( \\\n\t\t\t\tsizeofAlgoID( CRYPT_ALGO_SHA1 ) + \\\n\t\t\t\tsizeofObject( 20 ) ) + \\\n\t\t\t sizeofShortObject( pkcs12info->macSaltSize ) + \\\n\t\t\t sizeofShortInteger( pkcs12info->macIterations ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeMacData( INOUT STREAM *stream,\n\t\t\t\t\t\t const PKCS12_INFO *pkcs12info )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE macBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst int macDataSize = sizeofMacData( pkcs12info );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\n\tREQUIRES( macDataSize >= 32 && macDataSize < MAX_INTLENGTH_SHORT );\n\n\t/* Wrap up the MACing and get the MAC value */\n\tstatus = krnlSendMessage( pkcs12info->iMacContext, \n\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, macBuffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( pkcs12info->iMacContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the MAC data.  Despite the fact that the algorithm being used \n\t   is HMAC, the OID that we have to write is the one for plain SHA-1 */\n\twriteSequence( stream, macDataSize );\n\twriteSequence( stream, sizeofAlgoID( CRYPT_ALGO_SHA1 ) + \\\n\t\t\t\t\t\t   sizeofObject( 20 ) );\n\twriteAlgoID( stream, CRYPT_ALGO_SHA1 );\n\twriteOctetString( stream, macBuffer, msgData.length, DEFAULT_TAG );\n\twriteOctetString( stream, pkcs12info->macSalt, pkcs12info->macSaltSize,\n\t\t\t\t\t  DEFAULT_TAG );\n\treturn( writeShortInteger( stream, pkcs12info->macIterations, \n\t\t\t\t\t\t\t   DEFAULT_TAG ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite a Key/Certiifcate\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write an encrypted private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writePrivateKey( INOUT PKCS12_OBJECT_INFO *keyObjectInfo,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iPrivKeyContext,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iKeyWrapContext )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tSTREAM stream;\n\tvoid *privKeyData;\n\tint privKeyDataSize DUMMY_INIT, pbeInfoDataSize, headerSize, status;\n\n\tassert( isWritePtr( keyObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( isHandleRangeValid( iKeyWrapContext ) );\n\n\t/* Calculate the eventual encrypted key size and allocate storage for it */\n\tsetMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, iPrivKeyContext,\n\t\t\t\t\t\t  iKeyWrapContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, \n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP_PKCS8 );\n\tif( cryptStatusOK( status ) )\n\t\tprivKeyDataSize = mechanismInfo.wrappedDataLength;\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( rangeCheck( privKeyDataSize, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( keyObjectInfo->data = clAlloc( \"setItemFunction\", \\\n\t\t\t\t\t\t\t\t\t\t 64 + privKeyDataSize ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tkeyObjectInfo->dataSize = 64 + privKeyDataSize;\n\n\t/* Calculate the size of the key-derivation information */\n\tpbeInfoDataSize = sizeofShortObject( keyObjectInfo->saltSize ) + \\\n\t\t\t\t\t  sizeofShortInteger( keyObjectInfo->iterations );\n\n\t/* Write the key-derivation information */\n\tsMemOpen( &stream, ( void * ) keyObjectInfo->data, \n\t\t\t  keyObjectInfo->dataSize );\n\twriteSequence( &stream,\n\t\t\t\t   sizeofOID( OID_PKCS12_PBEWITHSHAAND3KEYTRIPLEDESCBC ) + \\\n\t\t\t\t   sizeofShortObject( pbeInfoDataSize ) );\n\twriteOID( &stream, OID_PKCS12_PBEWITHSHAAND3KEYTRIPLEDESCBC );\n\twriteSequence( &stream, pbeInfoDataSize );\n\twriteOctetString( &stream, keyObjectInfo->salt, keyObjectInfo->saltSize, \n\t\t\t\t\t  DEFAULT_TAG );\n\twriteShortInteger( &stream, keyObjectInfo->iterations, DEFAULT_TAG );\n\tstatus = writeOctetStringHole( &stream, privKeyDataSize, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\theaderSize = stell( &stream );\n\tENSURES( boundsCheck( headerSize, privKeyDataSize, \n\t\t\t\t\t\t  keyObjectInfo->dataSize ) );\n\n\t/* Insert the wrapped key into the stream buffer */\n\tstatus = sMemGetDataBlockRemaining( &stream, &privKeyData, \n\t\t\t\t\t\t\t\t\t\t&privKeyDataSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\tsetMechanismWrapInfo( &mechanismInfo, privKeyData, privKeyDataSize,\n\t\t\t\t\t\t  NULL, 0, iPrivKeyContext, iKeyWrapContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, \n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP_PKCS8 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tkeyObjectInfo->dataSize = headerSize + \\\n\t\t\t\t\t\t\t\t  mechanismInfo.wrappedDataLength;\n\t\tkeyObjectInfo->payloadOffset = headerSize;\n\t\tkeyObjectInfo->payloadSize = mechanismInfo.wrappedDataLength;\n\t\t}\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( keyObjectInfo->data, \n\t\t\t\t\t\t\t\t\t\t\t keyObjectInfo->dataSize ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write a certificate.  PKCS #12 generally only stores the individual \n   certificate that's associated with the private key rather than a complete \n   certificate chain, so we only add the leaf certificate rather than all of \n   the certificates in the chain (that is, in theory it's possible to stuff \n   all of the certificates in the chain into the keyset, but since PKCS #12 \n   has no way of identifying or indexing them there's not much that anything \n   can do with them even if they're present) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeCertificate( INOUT PKCS12_OBJECT_INFO *certObjectInfo,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( certObjectInfo, sizeof( PKCS12_OBJECT_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\n\t/* Select the leaf certificate */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Allocate storage for the encoded certificate data */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( rangeCheck( msgData.length, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( certObjectInfo->data = clAlloc( \"setItemFunction\", \\\n\t\t\t\t\t\t\t\t\t\t  msgData.length ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t/* Export the certificate */\n\tmsgData.data = ( void * ) certObjectInfo->data;\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"setItemFunction\", ( void * ) certObjectInfo->data );\n\t\tcertObjectInfo->data = NULL;\n\n\t\treturn( status );\n\t\t}\n\tcertObjectInfo->dataSize = msgData.length;\n\n\t/* Since we've just created the data object, the payload is identical to\n\t   the data */\n\tcertObjectInfo->payloadSize = certObjectInfo->dataSize;\n\tcertObjectInfo->payloadOffset = 0;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite a Keyset\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a PKCS #12 item (\"safeBag\").  We can't write this directly to the\n   output but have to buffer it via an intermediate stream so that we can \n   MAC it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeMacItem( INOUT STREAM *stream, \n\t\t\t\t\t\t const PKCS12_INFO *pkcs12info,\n\t\t\t\t\t\t const BOOLEAN isPrivateKey, \n\t\t\t\t\t\t const BOOLEAN macData )\n\t{\n\tconst PKCS12_OBJECT_INFO *pkcs12objectInfo = \\\n\t\t\tisPrivateKey ? &pkcs12info->keyInfo : &pkcs12info->certInfo;\n\tSTREAM memStream;\n\tBYTE objectHeaderBuffer[ 256 + 8 ], idBuffer[ 256 + 8 ];\n\tconst int idDataSize = sizeofOID( OID_PKCS9_LOCALKEYID ) + \\\n\t\t\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( 1 ) );\n\tconst int labelDataSize = sizeofOID( OID_PKCS9_FRIENDLYNAME ) + \\\n\t\t\t\t\t\t\t  sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofShortObject( pkcs12info->labelLength * 2 ) );\n\tconst int attrDataSize = sizeofShortObject( idDataSize ) + \\\n\t\t\t\t\t\t\t sizeofShortObject( labelDataSize );\n\tint objectHeaderSize DUMMY_INIT, idSize DUMMY_INIT, i;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( pkcs12info, sizeof( PKCS12_INFO ) ) );\n\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\tREQUIRES( macData == TRUE || macData == FALSE );\n\n\t/* Write the object header to a buffer where it can be MACed */\n\tsMemOpen( &memStream, objectHeaderBuffer, 256 );\n\tif( isPrivateKey )\n\t\t{\n\t\tstatus = writeNonCMSheader( &memStream, OID_PKCS12_SHROUDEDKEYBAG,\n\t\t\t\t\t\t\t\t\tsizeofOID( OID_PKCS12_SHROUDEDKEYBAG ),\n\t\t\t\t\t\t\t\t\tpkcs12objectInfo->dataSize, attrDataSize );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeNonCMSheader( &memStream, OID_PKCS12_CERTBAG,\n\t\t\t\t\t\t\tsizeofOID( OID_PKCS12_CERTBAG ), \n\t\t\t\t\t\t\tsizeofOID( OID_PKCS9_X509CERTIFICATE ) + \\\n\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\tsizeofShortObject( pkcs12objectInfo->dataSize ) ),\n\t\t\t\t\t\t\t attrDataSize );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\twriteOID( &memStream, OID_PKCS9_X509CERTIFICATE );\n\t\t\twriteConstructed( &memStream, \n\t\t\t\t\t\t\t  sizeofShortObject( pkcs12objectInfo->dataSize ), \n\t\t\t\t\t\t\t  0 );\n\t\t\tstatus = writeOctetStringHole( &memStream, \n\t\t\t\t\t\t\t\tpkcs12objectInfo->dataSize, DEFAULT_TAG );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tobjectHeaderSize = stell( &memStream );\n\tsMemDisconnect( &memStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the object header and data to the keyset */\n\tswrite( stream, objectHeaderBuffer, objectHeaderSize );\n\tstatus = swrite( stream, pkcs12objectInfo->data, \n\t\t\t\t\t pkcs12objectInfo->dataSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Mac the payload data if necessary (we don't have to perform the \n\t   MACing if we're performing a dummy write to a null stream) */\n\tif( macData )\n\t\t{\n\t\tstatus = krnlSendMessage( pkcs12info->iMacContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  objectHeaderBuffer, objectHeaderSize );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( pkcs12info->iMacContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) pkcs12objectInfo->data, \n\t\t\t\t\t\t\t\t\t  pkcs12objectInfo->dataSize );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the item's ID and label.  These are supposedly optional, but\n\t   some apps will break if they're not present.  We have to keep the ID\n\t   short (rather than using, say, a keyID) because some apps assume that \n\t   it's a 32-bit int or something similar.  In addition apps seem to \n\t   change this value at random (Windows changes it to a GUID, Mozilla/\n\t   NSS changes it to a SHA-1 hash) so it's pretty much meaningless \n\t   anyway */\n\tsMemOpen( &memStream, idBuffer, 256 );\n\twriteSet( &memStream, attrDataSize );\n\twriteSequence( &memStream, idDataSize );\n\twriteOID( &memStream, OID_PKCS9_LOCALKEYID );\n\twriteSet( &memStream, sizeofObject( 1 ) );\n\twriteOctetStringHole( &memStream, 1, DEFAULT_TAG );\n\tsputc( &memStream, 1 );\t\t/* ID, fixed at 0x01 for a single key */\n\twriteSequence( &memStream, labelDataSize );\n\twriteOID( &memStream, OID_PKCS9_FRIENDLYNAME );\n\twriteSet( &memStream, sizeofShortObject( pkcs12info->labelLength * 2 ) );\n\tstatus = writeGenericHole( &memStream, pkcs12info->labelLength * 2,\n\t\t\t\t\t\t\t   BER_STRING_BMP );\n\tLOOP_EXT( i = 0, i < pkcs12info->labelLength, i++, CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\t/* Convert the ASCII string into a BMP string */\n\t\tsputc( &memStream, 0 );\n\t\tstatus = sputc( &memStream, byteToInt( pkcs12info->label[ i ] ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) )\n\t\tidSize = stell( &memStream );\n\tsMemDisconnect( &memStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = swrite( stream, idBuffer, idSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Mac the attribute data if necessary (we don't have to perform the \n\t   MACing if we're performing a dummy write to a null stream) */\n\tif( macData )\n\t\t{\n\t\tstatus = krnlSendMessage( pkcs12info->iMacContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, idBuffer, idSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Flush a PKCS #12 collection to a stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pkcs12Flush( INOUT STREAM *stream, \n\t\t\t\t IN_ARRAY( noPkcs12objects ) const PKCS12_INFO *pkcs12info, \n\t\t\t\t IN_LENGTH_SHORT const int noPkcs12objects )\n\t{\n\tSTREAM memStream;\n\tBYTE objectHeaderBuffer[ 32 + 8 ];\n\tBOOLEAN privateKeyPresent = FALSE;\n\tconst int macDataSize = sizeofMacData( pkcs12info );\n\tint safeDataSize DUMMY_INIT, authSafeDataSize;\n\tint objectHeaderSize DUMMY_INIT, i, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( pkcs12info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS12_INFO ) * noPkcs12objects ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs12objects ) );\n\n\t/* Determine the overall size of the collection of objects */\n\tsMemNullOpen( &memStream );\n\tLOOP_MED( i = 0, i < noPkcs12objects, i++ )\n\t\t{\n\t\tif( pkcs12info[ i ].keyInfo.dataSize > 0 )\n\t\t\t{\n\t\t\tprivateKeyPresent = TRUE;\n\t\t\tstatus = writeMacItem( &memStream, pkcs12info, TRUE, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( pkcs12info[ i ].certInfo.dataSize > 0 )\n\t\t\t{\n\t\t\tstatus = writeMacItem( &memStream, pkcs12info, FALSE, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) )\n\t\tsafeDataSize = stell( &memStream );\n\tsMemClose( &memStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !privateKeyPresent )\n\t\t{\n\t\t/* If there's no data present, let the caller know that the keyset\n\t\t   is empty */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tauthSafeDataSize = sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofOID( OID_CMS_DATA ) + \\\n\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\t\tsizeofShortObject( safeDataSize ) ) ) ) );\n\n\t/* Write the outermost (authSafe) layer of cruft */\n\twriteSequence( stream, sizeofShortInteger( 3 ) + \\\n\t\t\t\t\t\t   sizeofShortObject( \\\n\t\t\t\t\t\t\t\tsizeofOID( OID_CMS_DATA ) + \\\n\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\tsizeofShortObject( authSafeDataSize ) ) ) + \\\n\t\t\t\t\t\t   sizeofShortObject( macDataSize ) );\n\twriteShortInteger( stream, 3, DEFAULT_TAG );\n\tstatus = writeCMSheader( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ),\n\t\t\t\t\t\t\t authSafeDataSize, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write and MAC the next layer (safe) of cruft.  We have to do this via\n\t   an intermediate memory stream so that we can MAC the data before we \n\t   write it to the keyset */\n\tsMemOpen( &memStream, objectHeaderBuffer, 32 );\n\twriteSequence( &memStream, sizeofShortObject( \\\n\t\t\t\t\t\t\t\t\tsizeofOID( OID_CMS_DATA ) + \\\n\t\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\t\t\t\t\tsizeofShortObject( safeDataSize ) ) ) ) );\n\tstatus = writeCMSheader( &memStream, OID_CMS_DATA, \n\t\t\t\t\t\t\t sizeofOID( OID_CMS_DATA ),\n\t\t\t\t\t\t\t sizeofShortObject( safeDataSize ), TRUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeSequence( &memStream, safeDataSize );\n\tif( cryptStatusOK( status ) )\n\t\tobjectHeaderSize = stell( &memStream );\n\tsMemDisconnect( &memStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswrite( stream, objectHeaderBuffer, objectHeaderSize );\n\tstatus = krnlSendMessage( pkcs12info->iMacContext, \n\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, objectHeaderBuffer, \n\t\t\t\t\t\t\t  objectHeaderSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the individual objects */\n\tLOOP_MED( i = 0, i < noPkcs12objects, i++ )\n\t\t{\n\t\tif( pkcs12info[ i ].keyInfo.dataSize > 0 )\n\t\t\t{\n\t\t\tstatus = writeMacItem( stream, pkcs12info, TRUE, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tif( pkcs12info[ i ].certInfo.dataSize > 0 )\n\t\t\t{\n\t\t\tstatus = writeMacItem( stream, pkcs12info, FALSE, TRUE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Write the MAC data at the end of the keyset */\n\tstatus = writeMacData( stream, pkcs12info );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( sflush( stream ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAdd a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add an item to the PKCS #12 keyset.  PKCS #12's braindamaged format \n   severly restricts what we can allow in terms of keyset updates.  Since \n   there's only a single KEK used for both the private-key wrap and the\n   overall MAC of the data, we can't store more than one private key.  In\n   addition because of the lack of any useful indexing information there's\n   no way to match anything to anything else, so we have to assume that\n   a certificate being added belongs with the already-present private key.\n   To handle all of these constraints we only store a single private key and\n   only allow a certificate to be added either alongside or after the \n   private key has been added */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int flags )\n\t{\n\tCRYPT_CONTEXT iKeyWrapContext;\n\tPKCS12_INFO *pkcs12info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tPKCS12_OBJECT_INFO *keyObjectInfo, *certObjectInfo;\n\tBOOLEAN certPresent = FALSE, contextPresent, pkcs12keyPresent;\n\tBOOLEAN wrapContextInitialised = FALSE;\n\tint value, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtrDynamic( pkcs12info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS12_INFO ) * \\\n\t\t\t\t\t\t\t\t\tkeysetInfoPtr->keyDataNoObjects ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( ( password == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( ( itemType == KEYMGMT_ITEM_PUBLICKEY && \\\n\t\t\t\tpassword == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( itemType == KEYMGMT_ITEM_PRIVATEKEY && \\\n\t\t\t\tpassword != NULL && passwordLength != 0 ) );\n\tREQUIRES( flags == KEYMGMT_FLAG_NONE );\n\tREQUIRES( pkcs12info != NULL );\n\n\t/* Set up PKCS #12 information state variables */\n\tkeyObjectInfo = &pkcs12info->keyInfo;\n\tcertObjectInfo = &pkcs12info->certInfo;\n\tpkcs12keyPresent = ( keyObjectInfo->dataSize > 0 ) ? TRUE : FALSE;\n\n\t/* If there's already a key and certificate present then we can't add \n\t   anything else.  This check also catches the (invalid) case of a \n\t   certificate being present without a corresponding private key */\n\tif( certObjectInfo->dataSize > 0 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t( CRYPT_ERROR_OVERFLOW, KEYSET_ERRINFO, \n\t\t\t\t  \"No more room in keyset to add this item\" ) );\n\t\t}\n\n\t/* Check the object and extract any information that we may need from \n\t   it */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint algorithm;\t/* int vs.enum */\n\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusOK( status ) && algorithm != CRYPT_ALGO_RSA )\n\t\t\t{\n\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t\t \"PKCS #12 keysets can only store RSA private keys \"\n\t\t\t\t\t\t \"and certificates\" ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( ( status == CRYPT_ARGERROR_OBJECT ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tcontextPresent = checkContextCapability( cryptHandle, \n\t\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_PRIVATE );\n\n\t/* If there's a certificate present, make sure that it's something that \n\t   can be stored.  We don't treat the wrong type as an error since we \n\t   can still store the public/private key components even if we don't \n\t   store the certificate */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusOK( status ) && \\\n\t\t( value == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t  value == CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t{\n\t\tBOOLEAN_INT isInited;\n\n\t\tcertPresent = TRUE;\n\n\t\t/* If the certificate isn't signed then we can't store it in this \n\t\t   state */\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &isInited, CRYPT_CERTINFO_IMMUTABLE );\n\t\tif( cryptStatusError( status ) || !isInited )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTINITED, \n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Certificate being added is incomplete (unsigned)\" ) );\n\t\t\t}\n\n\t\t/* If we're adding a standalone certificate then we can't add it \n\t\t   unless there's already key data present.  Since PKCS #12 doesn't \n\t\t   store any indexing information we have no idea whether the two \n\t\t   actually belong together, so we just have to hope for the best */\n\t\tif( !contextPresent && !pkcs12keyPresent )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTINITED, \n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, KEYSET_ERRINFO, \n\t\t\t\t\t  \"No key present that corresponds to the certificate \"\n\t\t\t\t\t  \"being added\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If we're trying to add a key and there's already one present then we \n\t   can't add another one */\n\tif( pkcs12keyPresent && contextPresent )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INITED, \n\t\t\t\t( CRYPT_ERROR_INITED, KEYSET_ERRINFO, \n\t\t\t\t  \"No more room in keyset to add this item\" ) );\n\t\t}\n\n\t/* PKCS #12 keysets can't store public keys, only private keys and \n\t   certificates */\n\tif( itemType == KEYMGMT_ITEM_PUBLICKEY && !certPresent )\n\t\t{\n\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t \"PKCS #12 keysets can only store private keys and \"\n\t\t\t\t\t \"certificates, not public keys\" ) );\n\t\t}\n\n\t/* At this point we're either storing a certificate or a private key \n\t   (with an optional certificate attached) */\n\tENSURES( ( itemType == KEYMGMT_ITEM_PUBLICKEY && certPresent ) || \\\n\t\t\t ( itemType == KEYMGMT_ITEM_PRIVATEKEY && contextPresent ) );\n\n\t/* If we're adding a private key, make sure that there's a password \n\t   present.  Conversely, if there's a password present make sure that \n\t   we're adding a private key */\n\tif( pkcs12keyPresent )\n\t\t{\n\t\t/* We're adding a certificate, there can't be a password present.  \n\t\t   Some PKCS #12 implementations encrypt public certificates for no\n\t\t   adequately explained reason, we always store them as plaintext\n\t\t   since they are, after all, *public* certificates */\n\t\tif( password != NULL )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\t/* We're adding a private key, there must be a password present */\n\t\tif( password == NULL )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\n\t/* Get what little index information PKCS #12 stores with a key */\n\tif( !pkcs12keyPresent && contextPresent )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, pkcs12info->label, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't read key label from private-key object\" ) );\n\t\t\t}\n\t\tpkcs12info->labelLength = msgData.length;\n\t\t}\n\n\t/* Write the certificate if necessary.  We do this one first because \n\t   it's the easiest to back out of */\n\tif( certPresent )\n\t\t{\n\t\t/* We're ready to go, lock the object for our exclusive use */\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tstatus = writeCertificate( certObjectInfo, cryptHandle );\n\t\t( void ) krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't extract certificate data from \"\n\t\t\t\t\t  \"certificate\" ) );\n\t\t\t}\n\t\tpkcs12info->flags |= PKCS12_FLAG_CERT;\n\n\t\t/* If there's already a key present, return now */\n\t\tif( pkcs12keyPresent )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Create the key wrap context and the MAC context (if necessary) from \n\t   the password */\n\tstatus = createPkcs12KeyWrapContext( keyObjectInfo, \n\t\t\t\t\t\t\t\t\t\t keysetInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t\t password, passwordLength,\n\t\t\t\t\t\t\t\t\t\t &iKeyWrapContext, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\twrapContextInitialised = TRUE;\n\t\tif( !pkcs12info->macInitialised )\n\t\t\t{\n\t\t\tstatus = createPkcs12MacContext( pkcs12info, \n\t\t\t\t\t\t\t\t\t\t\t keysetInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\t\t\t\t password, passwordLength, \n\t\t\t\t\t\t\t\t\t\t\t &pkcs12info->iMacContext, TRUE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tpkcs12freeEntry( pkcs12info );\n\t\tif( wrapContextInitialised )\n\t\t\tkrnlSendNotifier( iKeyWrapContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't create session/MAC key to secure private \"\n\t\t\t\t  \"key\" ) );\n\t\t}\n\tpkcs12info->macInitialised = TRUE;\n\n\t/* Write the encrypted and MACed private key */\n\tstatus = writePrivateKey( keyObjectInfo, cryptHandle, \n\t\t\t\t\t\t\t  iKeyWrapContext );\n\tkrnlSendNotifier( iKeyWrapContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tpkcs12freeEntry( pkcs12info );\n\n\t\t/* PKCS #12 requires the presence of RSA components that are never \n\t\t   used, if these aren't available then the private-key write code\n\t\t   can't write the key data.  If we get a CRYPT_ERROR_NOTAVAIL from\n\t\t   this then we return more informative error information about the\n\t\t   problem */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"RSA key doesn't contain unused components required \"\n\t\t\t\t\t  \"by PKCS #12, couldn't write key data\" ) );\n\t\t\t}\n\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't write wrapped private key data\" ) );\n\t\t}\n\tpkcs12info->flags |= PKCS12_FLAG_PRIVKEY;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS12set( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS12 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS12_WRITE */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib PKCS #15 Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/* OID information used to read the header of a PKCS #15 keyset.  Since the \n   PKCS #15 content can be further wrapped in CMS AuthData we have to check\n   for both types of content.  If we find AuthData we retry the read, this\n   time allowing only PKCS #15 content.  In addition since this is inner\n   content in an EncapsulatedContentInfo structure we don't specify any\n   version information because the additional OCTET STRING encapsulation \n   used with EncapsulatedContentInfo means that we need to dig down further \n   before we can find this field */\n\nstatic const CMS_CONTENT_INFO oidInfoPkcs15Data = { 0, 0 };\n\nstatic const OID_INFO keyFileOIDinfo[] = {\n\t{ OID_PKCS15_CONTENTTYPE, TRUE, &oidInfoPkcs15Data },\n\t{ OID_CMS_AUTHDATA, FALSE, &oidInfoPkcs15Data },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\nstatic const OID_INFO keyFilePKCS15OIDinfo[] = {\n\t{ OID_PKCS15_CONTENTTYPE, CRYPT_OK, NULL },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the PKCS #15 information state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckPKCS15( const PKCS15_INFO *pkcs15infoPtr )\n\t{\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\t/* Check that the basic fields are in order.  The label field can be \n\t   empty for standalone certificates or public keys, which don't \n\t   usually have a label associated with the key */\n\tif( !isEnumRange( pkcs15infoPtr->type, PKCS15_SUBTYPE ) || \\\n\t\t!isIntegerRange( pkcs15infoPtr->index ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( pkcs15infoPtr->labelLength < 0 || \\\n\t\tpkcs15infoPtr->labelLength > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Label\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( pkcs15infoPtr->type == PKCS15_SUBTYPE_SECRETKEY || \\\n\t\tpkcs15infoPtr->type == PKCS15_SUBTYPE_DATA )\n\t\t{\n\t\tif( pkcs15infoPtr->iDlength != 0 || \\\n\t\t\tpkcs15infoPtr->keyIDlength != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Spurious ID\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( pkcs15infoPtr->iDlength <= 0 || \\\n\t\t\tpkcs15infoPtr->iDlength > CRYPT_MAX_HASHSIZE || \\\n\t\t\tpkcs15infoPtr->keyIDlength <= 0 || \\\n\t\t\tpkcs15infoPtr->keyIDlength > CRYPT_MAX_HASHSIZE )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: IDs\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Check that the ID fields have reasonable values.  This is a general \n\t   check for reasonable values that's more targeted at catching \n\t   inadvertent memory corruption than a strict sanity check */\n\tif( pkcs15infoPtr->iAndSIDlength < 0 || \\\n\t\tpkcs15infoPtr->iAndSIDlength > KEYID_SIZE || \\\n\t\tpkcs15infoPtr->subjectNameIDlength < 0 || \\\n\t\tpkcs15infoPtr->subjectNameIDlength > KEYID_SIZE || \\\n\t\tpkcs15infoPtr->issuerNameIDlength < 0 || \\\n\t\tpkcs15infoPtr->issuerNameIDlength > KEYID_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Subject/issuer ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( pkcs15infoPtr->pgp2KeyIDlength < 0 || \\\n\t\tpkcs15infoPtr->pgp2KeyIDlength > PGP_KEYID_SIZE || \\\n\t\tpkcs15infoPtr->openPGPKeyIDlength < 0 || \\\n\t\tpkcs15infoPtr->openPGPKeyIDlength > PGP_KEYID_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: PGP ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check that the key/certificate data fields have reasonable values.  \n\t   This is a general check for reasonable values that's more targeted \n\t   at catching inadvertent memory corruption than a strict sanity \n\t   check */\n\tif( pkcs15infoPtr->pubKeyData != NULL )\n\t\t{\n\t\tif( !isShortIntegerRangeNZ( pkcs15infoPtr->pubKeyDataSize ) || \\\n\t\t\tpkcs15infoPtr->pubKeyOffset <= 0 || \\\n\t\t\tpkcs15infoPtr->pubKeyOffset >= pkcs15infoPtr->pubKeyDataSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Public key data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( pkcs15infoPtr->pubKeyDataSize != 0 || \\\n\t\t\tpkcs15infoPtr->pubKeyOffset != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Spurious public key data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( pkcs15infoPtr->privKeyData != NULL )\n\t\t{\n\t\tif( !isShortIntegerRangeNZ( pkcs15infoPtr->privKeyDataSize ) || \\\n\t\t\tpkcs15infoPtr->privKeyOffset <= 0 || \\\n\t\t\tpkcs15infoPtr->privKeyOffset >= pkcs15infoPtr->privKeyDataSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Private key data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( pkcs15infoPtr->privKeyDataSize != 0 || \\\n\t\t\tpkcs15infoPtr->privKeyOffset != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Spurious private key data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( pkcs15infoPtr->certData != NULL )\n\t\t{\n\t\tif( !isShortIntegerRangeNZ( pkcs15infoPtr->certDataSize ) || \\\n\t\t\tpkcs15infoPtr->certOffset <= 0 || \\\n\t\t\tpkcs15infoPtr->certOffset >= pkcs15infoPtr->certDataSize )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( pkcs15infoPtr->certDataSize != 0 || \\\n\t\t\tpkcs15infoPtr->certOffset != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckPKCS15: Spurious certificate data\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Get the hash of various certificate name fields */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint getCertID( IN_HANDLE const CRYPT_HANDLE iCryptHandle, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE nameType, \n\t\t\t   OUT_BUFFER( nameIdMaxLen, *nameIdLen ) BYTE *nameID, \n\t\t\t   IN_LENGTH_SHORT_MIN( KEYID_SIZE ) const int nameIdMaxLen,\n\t\t\t   OUT_LENGTH_BOUNDED_Z( nameIdMaxLen ) int *nameIdLen )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tDYNBUF idDB;\n\tint status;\n\n\tassert( isWritePtrDynamic( nameID, nameIdMaxLen ) );\n\tassert( isWritePtr( nameIdLen, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( nameType == CRYPT_IATTRIBUTE_SPKI || \\\n\t\t\t  nameType == CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER || \\\n\t\t\t  nameType == CRYPT_IATTRIBUTE_SUBJECT || \\\n\t\t\t  nameType == CRYPT_IATTRIBUTE_ISSUER );\n\tREQUIRES( nameIdMaxLen >= KEYID_SIZE && \\\n\t\t\t  nameIdMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\t*nameIdLen = 0;\n\n\t/* Get the attribute data and hash algorithm information and hash the \n\t   attribute to get the ID */\n\tstatus = dynCreate( &idDB, iCryptHandle, nameType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\thashFunctionAtomic( nameID, nameIdMaxLen, dynData( idDB ), \n\t\t\t\t\t\tdynLength( idDB ) );\n\tdynDestroy( &idDB );\n\t*nameIdLen = nameIdMaxLen;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Locate a PKCS #15 object based on an ID */\n\n#define matchID( src, srcLen, dest, destLen ) \\\n\t\t( ( srcLen ) > 0 && ( srcLen ) == ( destLen ) && \\\n\t\t  !memcmp( ( src ), ( dest ), ( destLen ) ) )\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS15_INFO *findEntry( IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t/* CRYPT_KEYIDEX_ID maps to CRYPT_KEYID_NONE */\n\t\t\t\t\t\tIN_BUFFER_OPT( keyIDlength ) const void *keyID, \n\t\t\t\t\t\tIN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int requestedUsage,\n\t\t\t\t\t\tconst BOOLEAN isWildcardMatch )\n\t{\n\tconst PKCS15_INFO *pkcs15infoWildcardMatch = NULL;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES_N( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t\tkeyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_SUBJECTID || \\\n\t\t\t\tkeyIDtype == CRYPT_IKEYID_ISSUERID || \\\n\t\t\t\tkeyIDtype == CRYPT_KEYIDEX_ID );\n\tREQUIRES_N( ( keyID == NULL && keyIDlength == 0 ) || \\\n\t\t\t\t( keyID != NULL && \\\n\t\t\t\t  keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES_N( isFlagRangeZ( requestedUsage, KEYMGMT ) );\n\tREQUIRES_N( ( requestedUsage & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t\tKEYMGMT_MASK_USAGEOPTIONS );\n\tREQUIRES_N( isWildcardMatch == TRUE || isWildcardMatch == FALSE );\n\tREQUIRES_N( ( isWildcardMatch && keyID == NULL ) || !isWildcardMatch );\n\n\t/* If there's no ID to search on and we're not performing a wildcard \n\t   match, don't try and do anything.  This can occur when we're trying \n\t   to build a chain and the necessary chaining data like an issuerID \n\t   isn't present in the keyset */\n\tif( ( keyID == NULL || keyIDlength <= 0 ) && !isWildcardMatch )\n\t\treturn( NULL );\n\n\t/* Try and locate the appropriate object in the PKCS #15 collection */\n\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t{\n\t\tconst PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];\n\t\tconst int compositeUsage = pkcs15infoPtr->pubKeyUsage | \\\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->privKeyUsage;\n\n\t\t/* If there's no entry at this position, continue */\n\t\tif( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )\n\t\t\tcontinue;\n\n\t\tENSURES_N( sanityCheckPKCS15( pkcs15infoPtr ) );\n\n\t\t/* If we've already got a wildcard match and we've found a second\n\t\t   potential match, there's an ambiguity over what we should be \n\t\t   returning */\n\t\tif( pkcs15infoWildcardMatch != NULL )\n\t\t\treturn( NULL );\n\n\t\t/* If there's an explicit usage requested, make sure that the key \n\t\t   usage matches this.  This can get slightly complex because the \n\t\t   advertised usage isn't necessarily the same as the usage \n\t\t   permitted by the associated certificate (PKCS #11 apps are \n\t\t   particularly good at setting bogus usage types) and the overall \n\t\t   result can be further influenced by trusted usage settings, so \n\t\t   all that we check for here is an indicated usage for the key \n\t\t   matching the requested usage */\n\t\tif( ( requestedUsage & KEYMGMT_FLAG_USAGE_CRYPT ) && \\\n\t\t\t!( compositeUsage & ENCR_USAGE_MASK ) )\n\t\t\tcontinue;\n\t\tif( ( requestedUsage & KEYMGMT_FLAG_USAGE_SIGN ) && \\\n\t\t\t!( compositeUsage & SIGN_USAGE_MASK ) )\n\t\t\tcontinue;\n\n\t\t/* If we're performing a wildcard match, return the first private-key \n\t\t   entry.  In theory this shouldn't be necessary since cryptlib-\n\t\t   generated keysets must have valid labels, but keysets from other \n\t\t   implementations may not have them, or may have machine-generated\n\t\t   labels that don't work well for human use, so we allow a wildcard\n\t\t   match as a generic \"get me whatever you can\" */\n\t\tif( isWildcardMatch )\n\t\t\t{\n\t\t\tif( pkcs15infoPtr->privKeyData == NULL )\n\t\t\t\tcontinue;\t/* No private-key data present, continue */\n\n\t\t\t/* We've found a potential wildcard match, remember it and \n\t\t\t   continue */\n\t\t\tpkcs15infoWildcardMatch = pkcs15infoPtr;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check for a match based on the ID type */\n\t\tswitch( keyIDtype )\n\t\t\t{\n\t\t\tcase CRYPT_KEYID_NAME:\n\t\t\tcase CRYPT_KEYID_URI:\n\t\t\t\tif( matchID( pkcs15infoPtr->label, pkcs15infoPtr->labelLength,\n\t\t\t\t\t\t\t keyID, keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_IKEYID_KEYID:\n\t\t\t\tif( matchID( pkcs15infoPtr->keyID, pkcs15infoPtr->keyIDlength,\n\t\t\t\t\t\t\t keyID, keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_IKEYID_PGPKEYID:\n\t\t\t\t/* For the PGP keyID we compare both IDs for the reasons \n\t\t\t\t   given in the PGP keyset read code */\n\t\t\t\tif( matchID( pkcs15infoPtr->pgp2KeyID,\n\t\t\t\t\t\t\t pkcs15infoPtr->pgp2KeyIDlength, keyID,\n\t\t\t\t\t\t\t keyIDlength ) || \\\n\t\t\t\t\tmatchID( pkcs15infoPtr->openPGPKeyID,\n\t\t\t\t\t\t\t pkcs15infoPtr->openPGPKeyIDlength, keyID,\n\t\t\t\t\t\t\t keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_IKEYID_SUBJECTID:\n\t\t\t\tif( matchID( pkcs15infoPtr->subjectNameID,\n\t\t\t\t\t\t\t pkcs15infoPtr->subjectNameIDlength, keyID,\n\t\t\t\t\t\t\t keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_IKEYID_ISSUERID:\n\t\t\t\tif( matchID( pkcs15infoPtr->iAndSID,\n\t\t\t\t\t\t\t pkcs15infoPtr->iAndSIDlength, keyID,\n\t\t\t\t\t\t\t keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_KEYIDEX_ID:\n\t\t\t\tif( matchID( pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,\n\t\t\t\t\t\t\t keyID, keyIDlength ) )\n\t\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Null();\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\t/* If we're looking for a wildcard match, return that */\n\tif( pkcs15infoWildcardMatch != NULL )\n\t\treturn( ( PKCS15_INFO * ) pkcs15infoWildcardMatch );\n\n\t/* If we're trying to match on the PGP key ID and didn't find anything,\n\t   retry it using the first PGP_KEYID_SIZE bytes of the object ID.  This\n\t   is necessary because calculation of the OpenPGP ID requires the\n\t   presence of data that may not be present in non-PGP keys so we can't\n\t   calculate a real OpenPGP ID but have to use the next-best thing \n\t   (sol lucet omnibus) */\n\tif( keyIDtype == CRYPT_IKEYID_PGPKEYID )\n\t\t{\n\t\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tconst PKCS15_INFO *pkcs15infoPtr = &pkcs15info[ i ];\n\n\t\t\tif( pkcs15infoPtr->type != PKCS15_SUBTYPE_NONE && \\\n\t\t\t\tpkcs15infoPtr->iDlength >= PGP_KEYID_SIZE && \\\n\t\t\t\t!memcmp( keyID, pkcs15infoPtr->iD, PGP_KEYID_SIZE ) )\n\t\t\t\t{\n\t\t\t\treturn( ( PKCS15_INFO * ) pkcs15infoPtr );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\t}\n\n\treturn( NULL );\n\t}\n\n/* Find a free PKCS #15 entry */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS15_INFO *findFreeEntry( IN_ARRAY( noPkcs15objects ) \\\n\t\t\t\t\t\t\t\tconst PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects, \n\t\t\t\t\t\t\tOUT_OPT_INDEX( noPkcs15objects ) int *index )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( ( index == NULL ) || isWritePtr( index, sizeof( int ) ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( noPkcs15objects ) );\n\n\t/* Clear return value */\n\tif( index != NULL )\n\t\t*index = CRYPT_ERROR;\n\n\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t{\n\t\tif( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tif( i >= noPkcs15objects )\n\t\treturn( NULL );\n\n\t/* Remember the index value (used for enumerating PKCS #15 entries) for \n\t   this entry if required */\n\tif( index != NULL )\n\t\t*index = i;\n\n\treturn( ( PKCS15_INFO * ) &pkcs15info[ i ] );\n\t}\n\n/* Free object entries */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs15freeEntry( INOUT PKCS15_INFO *pkcs15info )\n\t{\n\tassert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) ) );\n\n\tif( pkcs15info->pubKeyData != NULL )\n\t\t{\n\t\tzeroise( pkcs15info->pubKeyData, pkcs15info->pubKeyDataSize );\n\t\tclFree( \"pkcs15freeEntry\", pkcs15info->pubKeyData );\n\t\t}\n\tif( pkcs15info->privKeyData != NULL )\n\t\t{\n\t\tzeroise( pkcs15info->privKeyData, pkcs15info->privKeyDataSize );\n\t\tclFree( \"pkcs15freeEntry\", pkcs15info->privKeyData );\n\t\t}\n\tif( pkcs15info->certData != NULL )\n\t\t{\n\t\tzeroise( pkcs15info->certData, pkcs15info->certDataSize );\n\t\tclFree( \"pkcs15freeEntry\", pkcs15info->certData );\n\t\t}\n\tif( pkcs15info->dataData != NULL )\n\t\t{\n\t\tzeroise( pkcs15info->dataData, pkcs15info->dataDataSize );\n\t\tclFree( \"pkcs15freeEntry\", pkcs15info->dataData );\n\t\t}\n\tzeroise( pkcs15info, sizeof( PKCS15_INFO ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs15Free( INOUT_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t IN_RANGE( 1, MAX_PKCS15_OBJECTS ) const int noPkcs15objects )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES_V( noPkcs15objects >= 1 && \\\n\t\t\t\tnoPkcs15objects <= MAX_PKCS15_OBJECTS );\n\n\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\tpkcs15freeEntry( &pkcs15info[ i ] );\n\tENSURES_V( LOOP_BOUND_OK );\n\tzeroise( pkcs15info, sizeof( PKCS15_INFO ) * noPkcs15objects );\n\t}\n\n/* Get the PKCS #15 validity information from a certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getValidityInfo( INOUT PKCS15_INFO *pkcs15info,\n\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tMESSAGE_DATA msgData;\n\ttime_t validFrom, validTo;\n\tint status;\n\n\tassert( isWritePtr( pkcs15info, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\n\t/* Remember the validity information for later.  We always update the \n\t   validity (even if it's already set) since we may be replacing an \n\t   older certificate with a newer one */\n\tsetMessageData( &msgData, &validFrom, sizeof( time_t ) );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDFROM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, &validTo, sizeof( time_t ) );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDTO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( pkcs15info->validTo > validTo )\n\t\t{\n\t\t/* There's an existing, newer certificate already present, make sure \n\t\t   that we don't try and add the new one */\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t}\n\tpkcs15info->validFrom = validFrom;\n\tpkcs15info->validTo = validTo;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the header of a PKCS #15 keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPkcs15EncapsHeader( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   OUT long *endPosPtr )\n\t{\n\tlong length;\n\tint tag, innerLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( endPosPtr, sizeof( long ) ) );\n\n\t/* Clear return value */\n\t*endPosPtr = 0;\n\n\t/* The outer header was a CMS AuthData wrapper, try again for an inner \n\t   PKCS #15 header.  First we skip the AuthData SET OF RECIPIENTINFO, \n\t   macAlgorithm AlgorithmIdentifier, and optional digestAlgorithm \n\t   AlgorithmIdentifier */\n\treadUniversal( stream );\n\tstatus = readUniversal( stream );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We've made our way past the AuthData information, try again for\n\t   encapsulated PKCS #15 content */\n\tstatus = readCMSheader( stream, keyFilePKCS15OIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( keyFilePKCS15OIDinfo, OID_INFO ), \n\t\t\t\t\t\t\tNULL, &length, READCMS_FLAG_INNERHEADER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Since this is EncapsulatedContentInfo the version information doesn't \n\t   immediately follow the header but is encapsulated inside an OCTET \n\t   STRING, so we have to skip an additional layer of wrapping and \n\t   manually read the version information.  In addition the OCTET STRING\n\t   could be indefinite-length, in which case it acts as a constructed \n\t   value containing an inner OCTET STRING, so we have to skip the inner\n\t   OCTET STRING before we get to the actual content */\n\tif( length == CRYPT_UNUSED )\n\t\t{\n\t\t/* It's an indefinite-length OCTET STRING, skip the inner OCTET \n\t\t   STRING wrapper */\n\t\treadOctetStringHole( stream, NULL, 16, DEFAULT_TAG );\n\t\t}\n\tstatus = readSequence( stream, &innerLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tlong value;\n\n\t\t*endPosPtr = innerLength;\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusOK( status ) && value != 0 )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPkcs15header( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT_INT_Z long *endPosPtr,\n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tlong endPos, currentPos;\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( endPosPtr, sizeof( long ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\t/* Clear return value */\n\t*endPosPtr = 0;\n\n\t/* Read the outer header and make sure that the length information is \n\t   valid */\n\tstatus = readCMSheader( stream, keyFileOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( keyFileOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\t&value, &endPos, \n\t\t\t\t\t\t\tREADCMS_FLAG_DEFINITELENGTH_OPT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid PKCS #15 keyset header\" ) );\n\t\t}\n\tif( value == FALSE )\n\t\t{\n\t\t/* The outer header was a CMS AuthData wrapper, try again for an \n\t\t   inner PKCS #15 header */\n\t\tstatus = readPkcs15EncapsHeader( stream, &endPos );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid PKCS #15 content wrapped in AuthData\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If it's indefinite-length data, don't try and go any further (the \n\t   general length check below will also catch this, but we make the \n\t   check explicit here) */\n\tif( endPos == CRYPT_UNUSED )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Can't process indefinite-length PKCS #15 content\" ) );\n\t\t}\n\n\t/* Make sure that the length information is sensible.  readCMSheader() \n\t   reads the version number field at the start of the content so we have \n\t   to adjust the stream position for this when we calculate the data end \n\t   position */\n\tcurrentPos = stell( stream ) - sizeofShortInteger( 0 );\n\tif( endPos < 16 + MIN_OBJECT_SIZE || \\\n\t\tcurrentPos + endPos >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid PKCS #15 keyset length information\" ) );\n\t\t}\n\t*endPosPtr = currentPos + endPos;\n\n\t/* Skip the key management information if there is any and read the \n\t   inner wrapper */\n\tif( checkStatusPeekTag( stream, status, value ) && \\\n\t\tvalue == MAKE_CTAG( 0 ) )\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = readLongSequence( stream, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that, after skipping the key management data, there's still \n\t   some payload left */\n\tif( stell( stream ) >= endPos - MIN_OBJECT_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A PKCS #15 keyset can contain multiple keys and whatnot, so when we open\n   it we parse the contents into memory for later use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initFunction( INOUT KEYSET_INFO *keysetInfoPtr, \n\t\t\t\t\t\t STDC_UNUSED const char *name,\n\t\t\t\t\t\t STDC_UNUSED const int nameLength,\n\t\t\t\t\t\t IN_ENUM( CRYPT_KEYOPT ) const CRYPT_KEYOPT_TYPE options )\n\t{\n\tPKCS15_INFO *pkcs15info;\n\tSTREAM *stream = &keysetInfoPtr->keysetFile->stream;\n\tlong endPos DUMMY_INIT;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( name == NULL && nameLength == 0 );\n\tREQUIRES( options == CRYPT_KEYOPT_NONE || \\\n\t\t\t  options == CRYPT_KEYOPT_CREATE );\n\n\t/* If we're opening an existing keyset skip the outer header, optional\n\t   keyManagementInfo, and inner header.  We do this before we perform any\n\t   setup operations to weed out potential problem keysets */\n\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t{\n\t\tstatus = readPkcs15header( stream, &endPos, KEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Allocate the PKCS #15 object information */\n\tif( ( pkcs15info = clAlloc( \"initFunction\", \\\n\t\t\t\t\t\t\t\tsizeof( PKCS15_INFO ) * \\\n\t\t\t\t\t\t\t\tMAX_PKCS15_OBJECTS ) ) == NULL )\n\t\t{\n\t\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t\t{\n\t\t\t/* Reset the stream position to account for the header \n\t\t\t   information that we've already read */\n\t\t\tsseek( stream, 0 ) ;\n\t\t\t}\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\tmemset( pkcs15info, 0, sizeof( PKCS15_INFO ) * MAX_PKCS15_OBJECTS );\n\tDATAPTR_SET( keysetInfoPtr->keyData, pkcs15info );\n\tkeysetInfoPtr->keyDataSize = sizeof( PKCS15_INFO ) * MAX_PKCS15_OBJECTS;\n\tkeysetInfoPtr->keyDataNoObjects = MAX_PKCS15_OBJECTS;\n\n\t/* If this is a newly-created keyset, there's nothing left to do */\n\tif( options == CRYPT_KEYOPT_CREATE )\n\t\t{\n\t\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read all of the keys in the keyset */\n\tstatus = readPkcs15Keyset( &keysetInfoPtr->keysetFile->stream, \n\t\t\t\t\t\t\t   pkcs15info, MAX_PKCS15_OBJECTS, endPos, \n\t\t\t\t\t\t\t   KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"initFunction\", pkcs15info );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\tif( options != CRYPT_KEYOPT_CREATE )\n\t\t\t{\n\t\t\t/* Reset the stream position to account for the header \n\t\t\t   information that we've already read */\n\t\t\tsseek( stream, 0 ) ;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\tENSURES( sanityCheckKeyset( keysetInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Shut down the PKCS #15 state, flushing information to disk if necessary */\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int shutdownFunction( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tPKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tint status = CRYPT_OK;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( DATAPTR_ISVALID( keysetInfoPtr->keyData ) );\n\n\t/* If the contents have been changed, allocate a working I/O buffer for \n\t   the duration of the flush and commit the changes to disk */\n\tif( TEST_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_DIRTY ) )\n\t\t{\n\t\tSTREAM *stream = &keysetInfoPtr->keysetFile->stream;\n\t\tBYTE buffer[ SAFEBUFFER_SIZE( STREAM_BUFSIZE ) + 8 ] STACK_ALIGN_DATA;\n\n\t\tREQUIRES( pkcs15info != NULL );\n\n\t\tsseek( stream, 0 );\n\t\tmemset( buffer, 0, STREAM_BUFSIZE );\n\t\t\t\t/* Keep static analysers happy */\n\t\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tsioctlSetString( stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t\t SAFEBUFFER_PTR( buffer ), STREAM_BUFSIZE );\n\t\tstatus = pkcs15Flush( stream, pkcs15info, \n\t\t\t\t\t\t\t  keysetInfoPtr->keyDataNoObjects );\n\t\tsioctlSet( stream, STREAM_IOCTL_IOBUFFER, 0 );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\tSET_FLAG( keysetInfoPtr->flags, KEYSET_FLAG_EMPTY );\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\n\t/* Free the PKCS #15 object information */\n\tif( pkcs15info != NULL )\n\t\t{\n\t\tpkcs15Free( pkcs15info, keysetInfoPtr->keyDataNoObjects );\n\t\tzeroise( pkcs15info, keysetInfoPtr->keyDataSize );\n\t\tclFree( \"shutdownFunction\", pkcs15info );\n\t\tDATAPTR_SET( keysetInfoPtr->keyData, NULL );\n\t\tkeysetInfoPtr->keyDataSize = 0;\n\t\t}\n\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't send PKCS #15 data to persistent storage\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodPKCS15( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->initFunction, initFunction );\n\tFNPTR_SET( keysetInfoPtr->shutdownFunction, shutdownFunction );\n\tstatus = initPKCS15get( keysetInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = initPKCS15set( keysetInfoPtr );\n\treturn( status );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPKCS #15 Definitions Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _PKCS15_DEFINED\n\n#define _PKCS15_DEFINED\n\n/* The format used to protect the private key components is a standard\n   cryptlib envelope, however for various reasons the required enveloping\n   functionality (which in practice is just minimal code to process a\n   PasswordRecipientInfo at the start of the data) is duplicated here\n   because:\n\n\t1. It's somewhat inelegant to use the heavyweight enveloping routines to\n\t   wrap up 100 bytes of data.\n\n\t2. The enveloping code is enormous and complex, especially when extra\n\t   sections like zlib and PGP and S/MIME support are factored in.  This\n\t   makes it difficult to compile a stripped-down version of cryptlib,\n\t   since private key storage will require all of the enveloping code to \n\t   be included.\n\n\t3. Since the enveloping code is general-purpose, it doesn't allow very\n\t   precise control over the data being processed.  Specifically, it's\n\t   necessary to write the private key components to a buffer in plaintext\n\t   form, which isn't permitted by the cryptlib kernel.\n\n   For these reasons the PKCS #15 modules include the code to process minimal\n   (password-encrypted data) envelopes */\n\n/* Alongside per-key protection, PKCS #15 also allows for an entire keyset \n   to be integrity-protected, but the key management makes this more or less \n   impossible to deploy using a general-purpose API.  If only a single key \n   is present in the file then it's partly feasible, except that once a \n   keyset is cast in stone no further updates can be made without requiring \n   passwords at odd times.  For example a certificate update would require a \n   (private-key) password in order to recalculate the integrity-check value \n   once the certificate has been added.  In addition the password would need \n   to be supplied at file open, when the whole file is parsed, and then \n   again when the private key is read, which leads to a rather puzzling API \n   for anyone not in the know.\n\n   In the presence of multiple keys this becomes even more awkward since the \n   per-key password isn't necessarily the same as the per-file password, so \n   you'd need to provide a password to open the file and then possibly \n   another one to get the key, unless it was the same as the per-file \n   password.  If there was one per-file password and multiple per-key \n   passwords then you would't know which key or keys used the per-file \n   password unless you opportunistically tried on each per-key access, and \n   the chances of that successfully making it up into any UI that people \n   create seem slim.  In addition updates are even more problematic than for \n   the one file, one key case because whoever last added a key would end up \n   with their per-key password authenticating the whole file */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKCS #15 Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Each PKCS #15 keyset can contain information for multiple personalities \n   (although it's extremely unlikely to contain more than one or two), with\n   Each object consiting of a combination of { private key, public key, other \n   items } belonging to a single shared ID.  We allow at most maximum of \n   MAX_PKCS15_OBJECTS per keyset in order to discourage them from being used \n   as general-purpose public-key keysets, which they're not supposed to be.   \n   Ideally we want to set this as low as possible, but have to be careful to\n   not break things for users who genuinely need to store multiple private\n   keys in one keyset */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define MAX_PKCS15_OBJECTS\t4\n#else\n  #define MAX_PKCS15_OBJECTS\t8\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* Usually a PKCS #15 personality consists of a collection of related PKCS\n   #15 objects (typically a public and private key and a certificate), but \n   sometimes we have personalities that consist only of a certificate and \n   little other information (for example a trusted CA root certificate, \n   which contains no user-supplied information such as a label).  In \n   addition there's an unrecognised data-type for which we interpret the\n   metadata but can't perform any other operations with */\n\ntypedef enum {\n\tPKCS15_SUBTYPE_NONE,\t\t\t/* Non-personality */\n\tPKCS15_SUBTYPE_NORMAL,\t\t\t/* Standard personality, keys+optional cert */\n\tPKCS15_SUBTYPE_CERT,\t\t\t/* Standalone certificate */\n\tPKCS15_SUBTYPE_SECRETKEY,\t\t/* Secret key */\n\tPKCS15_SUBTYPE_DATA,\t\t\t/* Pre-encoded cryptlib-specific data */\n\tPKCS15_SUBTYPE_UNRECOGNISED,\t/* Unrecognised data type */\n\tPKCS15_SUBTYPE_LAST\n\t} PKCS15_SUBTYPE;\n\n/* The types of object that we can find in a PKCS #15 file */\n\ntypedef enum { PKCS15_OBJECT_NONE, PKCS15_OBJECT_PUBKEY, \n\t\t\t   PKCS15_OBJECT_PRIVKEY, PKCS15_OBJECT_CERT, \n\t\t\t   PKCS15_OBJECT_SECRETKEY, PKCS15_OBJECT_DATA, \n\t\t\t   PKCS15_OBJECT_UNRECOGNISED, PKCS15_OBJECT_LAST \n\t\t\t   } PKCS15_OBJECT_TYPE;\n\n/* The types of key identifiers that we can find attached to an object */\n\nenum { PKCS15_KEYID_NONE, PKCS15_KEYID_ISSUERANDSERIALNUMBER,\n\t   PKCS15_KEYID_SUBJECTKEYIDENTIFIER, PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH,\n\t   PKCS15_KEYID_SUBJECTKEYHASH, PKCS15_KEYID_ISSUERKEYHASH,\n\t   PKCS15_KEYID_ISSUERNAMEHASH, PKCS15_KEYID_SUBJECTNAMEHASH,\n\t   PKCS15_KEYID_PGP2, PKCS15_KEYID_OPENPGP, PKCS15_KEYID_LAST };\n\n/* PKCS #15 key usage flags, a complex mixture of PKCS #11 and some bits of\n   X.509 */\n\n#define PKCS15_USAGE_ENCRYPT\t\t0x0001\n#define PKCS15_USAGE_DECRYPT\t\t0x0002\n#define PKCS15_USAGE_SIGN\t\t\t0x0004\n#define PKCS15_USAGE_SIGNRECOVER\t0x0008\n#define PKCS15_USAGE_WRAP\t\t\t0x0010\n#define PKCS15_USAGE_UNWRAP\t\t\t0x0020\n#define PKCS15_USAGE_VERIFY\t\t\t0x0040\n#define PKCS15_USAGE_VERIFYRECOVER\t0x0080\n#define PKCS15_USAGE_DERIVE\t\t\t0x0100\n#define PKCS15_USAGE_NONREPUDIATION\t0x0200\n\n/* Symbolic values for range checking of the usage flags */\n\n#define PKCS15_USAGE_FLAG_NONE\t\t0x0000\n#define PKCS15_USAGE_FLAG_MAX\t\t0x03FF\n\n/* PKCS #15 flags that can't be set for public keys.  We use this as a mask\n   to derive public-key flags from private key ones */\n\n#define PUBKEY_USAGE_MASK\t~( PKCS15_USAGE_DECRYPT | PKCS15_USAGE_SIGN | \\\n\t\t\t\t\t\t\t   PKCS15_USAGE_SIGNRECOVER | PKCS15_USAGE_UNWRAP )\n\n/* PKCS #15 usage types for encryption and signature keys.  We use these when\n   looking specifically for signing or encryption keys */\n\n#define ENCR_USAGE_MASK\t\t( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_DECRYPT | \\\n\t\t\t\t\t\t\t  PKCS15_USAGE_WRAP | PKCS15_USAGE_UNWRAP )\n#define SIGN_USAGE_MASK\t\t( PKCS15_USAGE_SIGN | PKCS15_USAGE_SIGNRECOVER | \\\n\t\t\t\t\t\t\t  PKCS15_USAGE_VERIFY | PKCS15_USAGE_VERIFYRECOVER | \\\n\t\t\t\t\t\t\t  PKCS15_USAGE_NONREPUDIATION )\n\n/* The access flags for various types of key objects.  For a public key we\n   set 'extractable', for a private key we set 'sensitive',\n   'alwaysSensitive', and 'neverExtractable' */\n\n#define KEYATTR_ACCESS_PUBLIC\t0x02\t/* 00010b */\n#define KEYATTR_ACCESS_PRIVATE\t0x0D\t/* 01101b */\n\n/* When adding a public key and/or certificate to a PKCS #15 collection we \n   have to be able to cleanly handle the addition of arbitrary collections of \n   potentially overlapping objects.  Since a public key is a subset of the \n   data in a certificate, if we're adding a certificate + public key pair \n   the certificate data overrides the public key, which isn't added at all.  \n   This leads to some rather convoluted logic for deciding what needs \n   updating and under which conditions.  The actions taken are:\n\n\tkey only:\tif present\n\t\t\t\t\treturn( CRYPT_ERROR_DUPLICATE )\n\t\t\t\telse\n\t\t\t\t\tadd key;\n\tcert only:\tif present\n\t\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\telif( matching key present )\n\t\t\t\t\tadd, delete key data;\n\t\t\t\telif( trusted certificate )\n\t\t\t\t\tadd as trusted certificate;\n\t\t\t\telse\n\t\t\t\t\terror;\n\tkey+cert:\tif key present and certificate present\n\t\t\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\t\t\t\tdelete key;\n\t\t\t\tif certificate present -> don't add certificate;\n\n   The following values specify the action to be taken when adding a \n   certificate */\n\ntypedef enum {\n\tCERTADD_NONE,\t\t\t/* No certificate add action */\n\tCERTADD_UPDATE_EXISTING,/* Update existing key info with a certificate */\n\tCERTADD_NORMAL,\t\t\t/* Add a certificate for which no key info present */\n\tCERTADD_STANDALONE_CERT,/* Add a standalone certificate not assoc'd with a key */\n\tCERTADD_LAST\t\t\t/* Last valid certificate add action */\n\t} CERTADD_TYPE;\n\n/* Since PKCS #15 uses more key ID types than are used by the rest of\n   cryptlib, we extend the standard range with PKCS15-only types */\n\n#define CRYPT_KEYIDEX_ID\t\t\t\tCRYPT_KEYID_NONE\n\n/* The minimum size of an object in a keyset, used for sanity-checking when\n   reading a keyset */\n\n#define MIN_OBJECT_SIZE\t\t16\n\n/* When writing attributes it's useful to have a fixed-size buffer rather\n   than having to mess around with all sorts of variable-length structures,\n   the following value defines the maximum size of the attribute data that\n   we can write (that is, the I/O stream is opened with this size and\n   generates a CRYPT_ERROR_OVERFLOW if we go beyond this).  The maximum-\n   length buffer contents are two CRYPT_MAX_TEXTSIZE strings, about half a\n   dozen hashes (as IDs for subject, issuer, and so on), and a few odd bits \n   and pieces so this is plenty */\n\n#define KEYATTR_BUFFER_SIZE\t512\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKCS #15 Types and Structures\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following structure contains the the information for one personality,\n   which covers one or more of a private key, public key, and certificate */\n\ntypedef struct {\n\t/* General information on the personality: The subtype, a local unique\n\t   identifier which is easier to manage than the iD (this is used when\n\t   enumerating PKCS #15 items in a keyset, the last-read-item entry is \n\t   set to the index value), the PKCS #15 object label, and the PKCS #15 \n\t   object ID and key ID (which is usually the same as the object ID) */\n\tPKCS15_SUBTYPE type;\t\t\t/* Personality subtype */\n\tint index;\t\t\t\t\t\t/* Unique value for this personality */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, labelLength ) \\\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];/* PKCS #15 object label */\n\tint labelLength;\n\tBUFFER( CRYPT_MAX_HASHSIZE, iDlength ) \\\n\tBYTE iD[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_HASHSIZE, keyIDlength ) \\\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint iDlength, keyIDlength;\t\t/* PKCS #15 object ID and key ID */\n\n\t/* Certificate-related ID information: Hash of the issuer name, subject\n\t   name, and issuerAndSerialNumber, and PGP key IDs */\n\tBUFFER( KEYID_SIZE, iAndSIDlength ) \\\n\tBYTE iAndSID[ KEYID_SIZE + 8 ];\n\tBUFFER( KEYID_SIZE, subjectNameIDlength ) \\\n\tBYTE subjectNameID[ KEYID_SIZE + 8 ];\n\tBUFFER( KEYID_SIZE, issuerNameIDlength ) \\\n\tBYTE issuerNameID[ KEYID_SIZE + 8 ];\n\tBUFFER( KEYID_SIZE, pgp2KeyIDlength ) \\\n\tBYTE pgp2KeyID[ PGP_KEYID_SIZE + 8 ];\n\tBUFFER( KEYID_SIZE, openPGPKeyIDlength ) \\\n\tBYTE openPGPKeyID[ PGP_KEYID_SIZE + 8 ];\n\tint iAndSIDlength, subjectNameIDlength, issuerNameIDlength;\n\tint pgp2KeyIDlength, openPGPKeyIDlength;\n\n\t/* Key/certificate object data */\n\tBUFFER_OPT_FIXED( pubKeyDataSize ) \\\n\tvoid *pubKeyData;\n\tBUFFER_OPT_FIXED( privKeyDataSize ) \\\n\tvoid *privKeyData;\n\tBUFFER_OPT_FIXED( certDataSize ) \\\n\tvoid *certData;\t\t\t\t\t/* Encoded object data */\n\tint pubKeyDataSize, privKeyDataSize, certDataSize;\n\tint pubKeyOffset, privKeyOffset, certOffset;\n\t\t\t\t\t\t\t\t\t/* Offset of payload in data */\n\tint pubKeyUsage, privKeyUsage;\t/* Permitted usage for the key */\n\tint trustedUsage;\t\t\t\t/* Usage which key is trusted for */\n\tBOOLEAN implicitTrust;\t\t\t/* Whether certificate is implicitly trusted */\n\ttime_t validFrom, validTo;\t\t/* Key/certificate validity information */\n\n\t/* Secret-key object data */\n\tBUFFER_OPT_FIXED( secretKeyDataSize ) \\\n\tvoid *secretKeyData;\t\t\t/* Encoded object data */\n\tint secretKeyDataSize, secretKeyOffset;\n\n\t/* Data object data */\n\tCRYPT_ATTRIBUTE_TYPE dataType;\t/* Type of the encoded object data */\n\tBUFFER_OPT_FIXED( dataDataSize ) \\\n\tvoid *dataData;\t\t\t\t\t/* Encoded object data */\n\tint dataDataSize, dataOffset;\n\t} PKCS15_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKCS #15 ASN.1 Tags\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Context-specific tags for object types */\n\nenum { CTAG_PO_PRIVKEY, CTAG_PO_PUBKEY, CTAG_PO_TRUSTEDPUBKEY,\n\t   CTAG_PO_SECRETKEY, CTAG_PO_CERT, CTAG_PO_TRUSTEDCERT,\n\t   CTAG_PO_USEFULCERT, CTAG_PO_DATA, CTAG_PO_AUTH, CTAG_PO_LAST };\n\n/* Context-specific tags for the PublicKeyInfo record */\n\nenum { CTAG_PK_CERTIFICATE, CTAG_PK_CERTCHAIN, CTAG_PK_LAST };\n\n/* Context-specific tags for the object record */\n\nenum { CTAG_OB_SUBCLASSATTR, CTAG_OB_TYPEATTR, CTAG_OB_LAST };\n\n/* Context-specific tags for the object value record */\n\nenum { CTAG_OV_DIRECT, CTAG_OV_DUMMY, CTAG_OV_DIRECTPROTECTED, \n\t   CTAG_OV_DUMMY_DIRECTPROTECTED_EXT, CTAG_OV_DIRECTPROTECTED_EXT,\n\t   CTAG_OV_LAST };\n\n/* Context-specific tags for the class attributes record */\n\nenum { CTAG_KA_VALIDTO, CTAG_KA_LAST };\nenum { CTAG_CA_DUMMY, CTAG_CA_TRUSTED_USAGE, CTAG_CA_IDENTIFIERS,\n\t   CTAG_CA_TRUSTED_IMPLICIT, CTAG_CA_VALIDTO, CTAG_CA_LAST };\nenum { CTAG_PK_IDENTIFIERS };\n\n/* Context-specific tags for the public/private key objects record */\n\nenum { CTAG_PK_ECC, CTAG_PK_DH, CTAG_PK_DSA, CTAG_PK_KEA };\n\n/* Context-specific tags for the data objects record */\n\nenum { CTAG_DO_EXTERNALDO, CTAG_DO_OIDDO, CTAG_DO_LAST };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKCS #15 Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Utility functions in pkcs15.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint getCertID( IN_HANDLE const CRYPT_HANDLE iCryptHandle, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE nameType, \n\t\t\t   OUT_BUFFER( nameIdMaxLen, *nameIdLen ) BYTE *nameID, \n\t\t\t   IN_LENGTH_SHORT_MIN( KEYID_SIZE ) const int nameIdMaxLen,\n\t\t\t   OUT_LENGTH_BOUNDED_Z( nameIdMaxLen ) int *nameIdLen );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS15_INFO *findEntry( IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\tIN_KEYID_OPT const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t/* CRYPT_KEYIDEX_ID maps to CRYPT_KEYID_NONE */\n\t\t\t\t\t\tIN_BUFFER_OPT( keyIDlength ) const void *keyID,\n\t\t\t\t\t\tIN_LENGTH_KEYID_Z const int keyIDlength,\n\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int requestedUsage,\n\t\t\t\t\t\tconst BOOLEAN isWildcardMatch );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nPKCS15_INFO *findFreeEntry( IN_ARRAY( noPkcs15objects ) \\\n\t\t\t\t\t\t\t\tconst PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects, \n\t\t\t\t\t\t\tOUT_OPT_INDEX( noPkcs15objects ) int *index );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs15freeEntry( INOUT PKCS15_INFO *pkcs15info );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid pkcs15Free( INOUT_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t IN_RANGE( 1, MAX_PKCS15_OBJECTS ) const int noPkcs15objects );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getValidityInfo( INOUT PKCS15_INFO *pkcs15info,\n\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle );\n\n/* Prototypes for functions in pkcs15_add.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getKeyTypeTag( IN_HANDLE_OPT const CRYPT_CONTEXT cryptContext,\n\t\t\t\t   IN_ALGO_OPT const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t   OUT int *tag );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint addConfigData( IN_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t   IN_LENGTH_SHORT const int noPkcs15objects, \n\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t   IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t   IN_LENGTH_SHORT const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addSecretKey( IN_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t  IN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 11 ) ) \\\nint pkcs15AddKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t  IN_BUFFER_OPT( passwordLength ) const void *password, \n\t\t\t\t  IN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t  IN_HANDLE const CRYPT_USER iOwnerHandle, \n\t\t\t\t  const BOOLEAN privkeyPresent, const BOOLEAN certPresent, \n\t\t\t\t  const BOOLEAN doAddCert, const BOOLEAN pkcs15keyPresent,\n\t\t\t\t  const BOOLEAN isStorageObject, \n\t\t\t\t  INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pkcs15_adpb.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint pkcs15AddCert( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t   IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t   IN_BUFFER_OPT( privKeyAttributeSize ) \\\n\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int privKeyAttributeSize,\n\t\t\t\t   IN_ENUM( CERTADD ) const CERTADD_TYPE certAddType, \n\t\t\t\t   INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint pkcs15AddCertChain( INOUT PKCS15_INFO *pkcs15info, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCert, \n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 8 ) ) \\\nint pkcs15AddPublicKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptContext, \n\t\t\t\t\t\tIN_BUFFER( pubKeyAttributeSize ) \\\n\t\t\t\t\t\t\tconst void *pubKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int pubKeyAttributeSize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, \n\t\t\t\t\t\tIN_LENGTH_PKC const int modulusSize, \n\t\t\t\t\t\tconst BOOLEAN isStorageObject, \n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pkcs15_adpr.c.  The private-key attribute \n   functions have to be accessible externally because adding or changing a \n   certificate for a private key can update the private-key attributes */\n\nSTDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nvoid updatePrivKeyAttributes( INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tvoid *newPrivKeyData, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int newPrivKeyDataSize,\n\t\t\t\t\t\t\t  IN_BUFFER( privKeyAttributeSize ) \\\n\t\t\t\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int privKeyAttributeSize, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int privKeyInfoSize, \n\t\t\t\t\t\t\t  IN_TAG const int keyTypeTag );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint calculatePrivkeyStorage( OUT_BUFFER_ALLOC_OPT( *newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tvoid **newPrivKeyDataPtr, \n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *newPrivKeyDataSize, \n\t\t\t\t\t\t\t IN_BUFFER_OPT( origPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *origPrivKeyData,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int origPrivKeyDataSize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeySize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeyAttributeSize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int extraDataSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6, 11 ) ) \\\nint pkcs15AddPrivateKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iPrivKeyContext,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptOwner,\n\t\t\t\t\t\t IN_BUFFER_OPT( passwordLength ) const char *password, \n\t\t\t\t\t\t IN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t IN_BUFFER( privKeyAttributeSize ) \\\n\t\t\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeyAttributeSize,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, \n\t\t\t\t\t\t IN_LENGTH_PKC const int modulusSize, \n\t\t\t\t\t\t const BOOLEAN isStorageObject, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pkcs15_atrd.c/pkcs15_atwr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 7 ) ) \\\nint writeKeyAttributes( OUT_BUFFER( privKeyAttributeMaxLen, \\\n\t\t\t\t\t\t\t\t\t*privKeyAttributeSize ) \n\t\t\t\t\t\t\tvoid *privKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\tconst int privKeyAttributeMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( privKeyAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *privKeyAttributeSize, \n\t\t\t\t\t\tOUT_BUFFER( pubKeyAttributeMaxLen, \\\n\t\t\t\t\t\t\t\t\t*pubKeyAttributeSize ) \\\n\t\t\t\t\t\t\tvoid *pubKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\tconst int pubKeyAttributeMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( pubKeyAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *pubKeyAttributeSize, \n\t\t\t\t\t\tINOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\tconst BOOLEAN writeKeyIDs );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint writeCertAttributes( OUT_BUFFER( certAttributeMaxLen, *certAttributeSize ) \\\n\t\t\t\t\t\t\tvoid *certAttributes, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) const int certAttributeMaxLen,\n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *certAttributeSize, \n\t\t\t\t\t\t INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptCert );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readObjectAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t  IN_ENUM( PKCS15_OBJECT ) const PKCS15_OBJECT_TYPE type, \n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in pkcs15_get/set.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS15get( INOUT KEYSET_INFO *keysetInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS15set( INOUT KEYSET_INFO *keysetInfoPtr );\n\n/* Prototypes for functions in pkcs15_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pkcs15Flush( INOUT STREAM *stream, \n\t\t\t\t IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info, \n\t\t\t\t IN_LENGTH_SHORT const int noPkcs15objects );\n\n/* Prototypes for functions in pkcs15_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 8, 9, 10, 11, 12 ) ) \\\nint readPublicKeyComponents( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_KEYSET iCryptKeysetCallback,\n\t\t\t\t\t\t\t IN_ENUM( CRYPT_KEYID ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t const BOOLEAN publicComponentsOnly,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_DEVICE iDeviceObject, \n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContextPtr,\n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCertPtr,\n\t\t\t\t\t\t\t OUT_FLAGS_Z( ACTION_PERM ) int *pubkeyActionFlags, \n\t\t\t\t\t\t\t OUT_FLAGS_Z( ACTION_PERM ) int *privkeyActionFlags, \n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint readPrivateKeyComponents( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iPrivKeyContext,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( passwordLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *password, \n\t\t\t\t\t\t\t  IN_LENGTH_NAME_Z const int passwordLength, \n\t\t\t\t\t\t\t  const BOOLEAN isStorageObject, \n\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint readPkcs15Keyset( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_ARRAY( maxNoPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t\t  IN_LENGTH_SHORT const int maxNoPkcs15objects, \n\t\t\t\t\t  IN_LENGTH const long endPos,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\n\n#endif /* _PKCS15_DEFINED */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_add.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #15 Key Add Interface\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine the tag to use when encoding a given key type.  There isn't any\n   tag for Elgamal but the keys are the same as X9.42 DH keys and cryptlib\n   uses the OID rather than the tag to determine the key type so the\n   following sleight-of-hand works */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getKeyTypeTag( IN_HANDLE_OPT const CRYPT_CONTEXT cryptContext,\n\t\t\t\t   IN_ALGO_OPT const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t   OUT int *tag )\n\t{\n\tstatic const MAP_TABLE tagMapTbl[] = {\n\t\t{ CRYPT_ALGO_RSA, 100 },\n\t\t{ CRYPT_ALGO_DH, CTAG_PK_DH },\n\t\t{ CRYPT_ALGO_ELGAMAL, CTAG_PK_DH },\n\t\t{ CRYPT_ALGO_DSA, CTAG_PK_DSA },\n\t\t{ CRYPT_ALGO_ECDSA, CTAG_PK_ECC },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tint keyCryptAlgo, value, status;\n\n\tREQUIRES( ( isHandleRangeValid( cryptContext ) && \\\n\t\t\t\tcryptAlgo == CRYPT_ALGO_NONE ) || \\\n\t\t\t  ( cryptContext == CRYPT_UNUSED && \\\n\t\t\t\tisPkcAlgo( cryptAlgo ) ) );\n\n\t/* Clear return value */\n\t*tag = 0;\n\n\t/* If the caller hasn't already supplied the algorithm details, get them\n\t   from the context */\n\tif( cryptAlgo != CRYPT_ALGO_NONE )\n\t\tkeyCryptAlgo = cryptAlgo;\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &keyCryptAlgo, CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Map the algorithm to the corresponding tag.  We have to be a bit \n\t   careful with the tags because the out-of-band special-case value \n\t   DEFAULT_TAG looks like an error value, so we supply a dummy value\n\t   of '100' for this tag and map it back to DEFAULT_TAG when we return\n\t   it to the caller */\n\tstatus = mapValue( keyCryptAlgo, &value, tagMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( tagMapTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\t*tag = ( value == 100 ) ? DEFAULT_TAG : value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAdd Miscellaneous Items\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add configuration data to a PKCS #15 collection.  The different data\n   types are:\n\n\tIATTRIBUTE_USERID: ID for objects in user keysets.  All items in the \n\t\tkeyset (which will be the user object's private key and their \n\t\tconfiguration information) are given this value as their ID.\n\t\n\tIATTRIBUTE_CONFIGDATA: ASN.1-encoded cryptlib configuration options.\n\n\tIATTRIBUTE_USERINDEX: ASN.1-encoded table mapping userIDs and names to \n\t\ta unique index value that's used to locate the file or storage \n\t\tlocation for that user's configuration data.\n\n\tIATTRIBUTE_USERINFO: ASN.1-encoded user information containing their \n\t\trole, ID, name information, and any additional required information.\n\n   The lookup process for a given user's information is to read the \n   IATTRIBUTE_USERINDEX from the user index keyset (typically index.p15) to \n   find the user's index value, and then use that to read the \n   IATTRIBUTE_USERINFO from the user keyset (typically u<index>.p15).  The \n   cryptlib-wide IATTRIBUTE_CONFIGDATA is stored in the cryptlib default \n   initialisation keyset, typically cryptlib.p15.\n\n   If we're being sent empty data (corresponding to an empty SEQUENCE, so \n   dataLength < 8), it means that the caller wants to clear this entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint addConfigData( IN_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t   IN_LENGTH_SHORT const int noPkcs15objects, \n\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t   IN_BUFFER( dataLength ) const char *data, \n\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tPKCS15_INFO *pkcs15infoPtr = NULL;\n\tconst BOOLEAN isDataClear = ( dataLength < 8 ) ? TRUE : FALSE;\n\tvoid *newData;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINDEX || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERID || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINFO );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* If it's a user ID, set all object IDs to this value.  This is needed\n\t   for user keysets where there usually isn't any key ID present (there\n\t   is one for SO keysets that have public/private keys attached to them \n\t   but they're not identified by key ID so it's not much use).  In this \n\t   case the caller has to explicitly set an ID, which is the user ID */\n\tif( dataType == CRYPT_IATTRIBUTE_USERID )\n\t\t{\n\t\tconst int length = min( dataLength, CRYPT_MAX_HASHSIZE );\n\n\t\tREQUIRES( dataLength == KEYID_SIZE );\n\n\t\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_HASHSIZE ) );\n\t\t\tmemcpy( pkcs15info[ i ].iD, data, length );\n  \t\t\tpkcs15info[ i ].iDlength = length;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Find an entry that contains data identical to what we're adding now \n\t   (which we'll replace with the new data) or failing that, the first \n\t   free entry */\n\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t{\n\t\tif( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \\\n\t\t\tpkcs15info[ i ].dataType == dataType )\n\t\t\t{\n\t\t\tpkcs15infoPtr = &pkcs15info[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( pkcs15infoPtr == NULL )\n\t\t{\n\t\t/* If we're trying to delete an existing entry then not finding what\n\t\t   we want to delete is an error */\n\t\tENSURES( !isDataClear );\n\n\t\t/* We couldn't find an existing entry to update, add a new entry */\n\t\tpkcs15infoPtr = findFreeEntry( pkcs15info, noPkcs15objects, NULL );\n\t\t}\n\tif( pkcs15infoPtr == NULL )\n\t\t{\n\t\t/* The appropriate error value to return here is a \n\t\t   CRYPT_ERROR_OVERFLOW because we always try to add a new entry if\n\t\t   we can't find an existing one, so the final error status is \n\t\t   always an overflow */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* If we're clearing an existing entry, we're done */\n\tif( isDataClear )\n\t\t{\n\t\tpkcs15freeEntry( pkcs15infoPtr );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're adding new data and there's no existing storage available, \n\t   allocate storage for it */\n\tif( pkcs15infoPtr->dataData == NULL || \\\n\t\tdataLength > pkcs15infoPtr->dataDataSize )\n\t\t{\n\t\tREQUIRES( rangeCheck( dataLength, 1, MAX_BUFFER_SIZE ) );\n\t\tnewData = clAlloc( \"addConfigData\", dataLength );\n\t\tif( newData == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t\t/* If there's existing data present, clear and free it */\n\t\tif( pkcs15infoPtr->dataData != NULL )\n\t\t\t{\n\t\t\tzeroise( pkcs15infoPtr->dataData, pkcs15infoPtr->dataDataSize );\n\t\t\tclFree( \"addConfigData\", pkcs15infoPtr->dataData );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There's existing data present and the new data will fit into its\n\t\t   storage, re-use the existing storage */\n\t\tnewData = pkcs15infoPtr->dataData;\n\t\t}\n\n\t/* Remember the pre-encoded configuration data */\n\tpkcs15infoPtr->dataData = newData;\n\tmemcpy( pkcs15infoPtr->dataData, data, dataLength );\n\tpkcs15infoPtr->dataDataSize = dataLength;\n\n\t/* Set the type information for the data */\n\tpkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;\n\tpkcs15infoPtr->dataType = dataType;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add a secret key to a PKCS #15 collection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addSecretKey( IN_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t  IN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptContext )\n\t{\n\tPKCS15_INFO *pkcs15infoPtr = NULL;\n\tMESSAGE_DATA msgData;\n\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtrDynamic( pkcs15infoPtr, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Check the object and make sure that the label of what we're adding\n\t   doesn't duplicate the label of an existing object */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  MESSAGE_CHECK_CRYPT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( ( status == CRYPT_ARGERROR_OBJECT ) ? \\\n\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tsetMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( findEntry( pkcs15info, noPkcs15objects, CRYPT_KEYID_NAME, \n\t\t\t\t   msgData.data, msgData.length, \n\t\t\t\t   KEYMGMT_FLAG_NONE, FALSE ) != NULL )\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t/* Find out where we can add the new key data */\n\tpkcs15infoPtr = findFreeEntry( pkcs15info, noPkcs15objects, NULL );\n\tif( pkcs15infoPtr == NULL )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\tpkcs15infoPtr->type = PKCS15_SUBTYPE_SECRETKEY;\n\n\t/* This functionality is currently unused */\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tExternal Add-a-Key Interface\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a key to a PKCS #15 collection.  The strategy for adding items is:\n\n\t\t\t\t\t\t\t\t\t\tExisting\n\t\tNew\t\t|\tNone\t| Priv+Pub\t| Priv+Cert\t|\tCert\t|\n\t------------+-----------+-----------+-----------+-----------+\n\tPriv + Pub\t|\tAdd\t\t|\t----\t|\t----\t|\tAdd\t\t|\n\t\t\t\t|\t\t\t|\t\t\t|\t\t\t|\t\t\t|\n\tPriv + Cert\t|\tAdd\t\t| Repl.pubk\t| Add cert\t| Add cert\t|\n\t\t\t\t|\t\t\t| with cert\t| if newer\t| if newer\t|\n\tCert\t\t| If trusted|\tAdd\t\t| Add cert\t| Add cert\t|\n\t\t\t\t|\t\t\t|\t\t\t| if newer\t| if newer\t|\n\t------------+-----------+-----------+-----------+-----------+ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 11 ) ) \\\nint pkcs15AddKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t  IN_BUFFER_OPT( passwordLength ) const void *password, \n\t\t\t\t  IN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t  IN_HANDLE const CRYPT_USER iOwnerHandle, \n\t\t\t\t  const BOOLEAN privkeyPresent, const BOOLEAN certPresent, \n\t\t\t\t  const BOOLEAN doAddCert, const BOOLEAN pkcs15keyPresent,\n\t\t\t\t  const BOOLEAN isStorageObject, \n\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tBYTE pubKeyAttributes[ KEYATTR_BUFFER_SIZE + 8 ];\n\tBYTE privKeyAttributes[ KEYATTR_BUFFER_SIZE + 8 ];\n\tint pubKeyAttributeSize = 0, privKeyAttributeSize = 0;\n\tint modulusSize DUMMY_INIT, pkcCryptAlgo, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( ( privkeyPresent && \\\n\t\t\t  isReadPtrDynamic( password, passwordLength ) ) || \\\n\t\t\t( ( !privkeyPresent || isStorageObject ) && \\\n\t\t\t  password == NULL && passwordLength == 0 ) );\n\n\tREQUIRES( ( privkeyPresent && password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) || \\\n\t\t\t  ( ( !privkeyPresent || isStorageObject ) && \\\n\t\t\t\tpassword == NULL && passwordLength == 0 ) );\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iOwnerHandle ) );\n\tREQUIRES( privkeyPresent == TRUE || privkeyPresent == FALSE );\n\tREQUIRES( certPresent == TRUE || certPresent == FALSE );\n\tREQUIRES( doAddCert == TRUE || doAddCert == FALSE );\n\tREQUIRES( pkcs15keyPresent == TRUE || pkcs15keyPresent == FALSE );\n\tREQUIRES( isStorageObject == TRUE || isStorageObject == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get information from the context */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &pkcCryptAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &modulusSize, CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the attribute information.  We have to rewrite the key\n\t   information when we add a non-standalone certificate even if we don't \n\t   change the key because adding a certificate can affect key \n\t   attributes */\n\tif( ( certPresent && pkcs15keyPresent ) ||\t\t/* Updating existing */\n\t\t( privkeyPresent && !pkcs15keyPresent ) )\t/* Adding new */\n\t\t{\n\t\t/* If we're adding a raw private key then we have to write the\n\t\t   identifiers that are normally written for the certificate, for\n\t\t   the private key (specified by the last function parameter) */\n\t\tstatus = writeKeyAttributes( privKeyAttributes, KEYATTR_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t &privKeyAttributeSize,\n\t\t\t\t\t\t\t\t\t pubKeyAttributes, KEYATTR_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t &pubKeyAttributeSize, pkcs15infoPtr,\n\t\t\t\t\t\t\t\t\t iCryptHandle,\n\t\t\t\t\t\t\t\t\t !certPresent && privkeyPresent && \\\n\t\t\t\t\t\t\t\t\t\t!pkcs15keyPresent );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't write PKCS #15 key attributes\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Write the certificate if necessary.  We do this one first because \n\t   it's the easiest to back out of */\n\tif( certPresent && doAddCert )\n\t\t{\n\t\t/* Select the leaf certificate in case it's a certificate chain */\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Write the certificate information.  There may be further \n\t\t   certificates in the chain but we don't try and do anything with \n\t\t   these at this level, the addition of supplemental certificates is \n\t\t   handled by the caller */\n\t\tif( pkcs15keyPresent )\n\t\t\t{\n\t\t\tstatus = pkcs15AddCert( pkcs15infoPtr, iCryptHandle, \n\t\t\t\t\t\t\t\t\tprivKeyAttributes, privKeyAttributeSize, \n\t\t\t\t\t\t\t\t\tCERTADD_UPDATE_EXISTING, errorInfo );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = pkcs15AddCert( pkcs15infoPtr, iCryptHandle, NULL, 0,\n\t\t\t\t\t\t\t\t\t( privkeyPresent || isStorageObject ) ? \\\n\t\t\t\t\t\t\t\t\t\tCERTADD_NORMAL : \\\n\t\t\t\t\t\t\t\t\t\tCERTADD_STANDALONE_CERT, errorInfo );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If there's no public/private-key context to add, exit */\n\t\tif( !privkeyPresent || pkcs15keyPresent )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Add the public key information if the information hasn't already been \n\t   added via a certificate */\n\tif( !certPresent )\n\t\t{\n\t\tENSURES( privkeyPresent && !pkcs15keyPresent );\n\n\t\tstatus = pkcs15AddPublicKey( pkcs15infoPtr, iCryptHandle, \n\t\t\t\t\t\t\t\t\t pubKeyAttributes, pubKeyAttributeSize, \n\t\t\t\t\t\t\t\t\t pkcCryptAlgo, modulusSize, isStorageObject,\n\t\t\t\t\t\t\t\t\t errorInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Add the private key information */\n\treturn( pkcs15AddPrivateKey( pkcs15infoPtr, iCryptHandle, iOwnerHandle,\n\t\t\t\t\t\t\t\t password, passwordLength, privKeyAttributes,\n\t\t\t\t\t\t\t\t privKeyAttributeSize, pkcCryptAlgo,\n\t\t\t\t\t\t\t\t modulusSize, isStorageObject, errorInfo ) );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_adpb.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #15 Public-key Add Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/* Define the following to use the corrected PKCS #15 v1.2 form for \n   ObjectValue.direct tagging rather than the original erroneous v1.1\n   form.  Note that this will break backwards compatibility for cryptlib \n   versions before 3.4.0, however 3.4.0 also introduces AuthEncData so this \n   seems like a good time to make the changeover for the tagging as well */\n\n#define USE_PKCS15V12_FORM\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate the size of and if necessary allocate storage for public-key \n   and certificate data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int calculatePubkeyStorage( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t\t   INOUT_PTR void **newPubKeyDataPtr, \n\t\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *newPubKeyDataSize, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int pubKeySize,\n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int pubKeyAttributeSize,\n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extraDataSize )\n\t{\n\tvoid *newPubKeyData;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( newPubKeyDataPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( newPubKeyDataSize, sizeof( int ) ) ); \n\n\tREQUIRES( isShortIntegerRangeNZ( pubKeySize ) );\n\tREQUIRES( isShortIntegerRangeNZ( pubKeyAttributeSize ) );\n\tREQUIRES( isShortIntegerRange( extraDataSize ) );\n\n\t/* Calculate the new private-key data size */\n\t*newPubKeyDataSize = sizeofObject( \\\n\t\t\t\t\t\t\tpubKeyAttributeSize + \\\n\t\t\t\t\t\t\tsizeofObject( \\\n\t\t\t\t\t\t\t\tsizeofObject( \\\n\t\t\t\t\t\t\t\t\tsizeofObject( pubKeySize ) + \\\n\t\t\t\t\t\t\t\t\textraDataSize ) ) );\n\tENSURES( *newPubKeyDataSize > 0 && \\\n\t\t\t *newPubKeyDataSize < MAX_BUFFER_SIZE );\n\n\t/* If the new data will fit into the existing storage, we're done */\n\tif( *newPubKeyDataSize <= pkcs15infoPtr->pubKeyDataSize )\n\t\treturn( CRYPT_OK );\n\n\t/* Allocate storage for the new data */\n\tREQUIRES( rangeCheck( *newPubKeyDataSize, 1, MAX_BUFFER_SIZE ) );\n\tnewPubKeyData = clAlloc( \"calculatePubkeyStorage\", *newPubKeyDataSize );\n\tif( newPubKeyData == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t*newPubKeyDataPtr = newPubKeyData;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int calculateCertStorage( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t\t INOUT_PTR void **newCertDataPtr,\n\t\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *newCertDataSize,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int certAttributeSize,\n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int certSize )\n\t{\n\tvoid *newCertData;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( newCertDataPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( newCertDataSize, sizeof( int ) ) ); \n\n\tREQUIRES( isShortIntegerRangeNZ( certAttributeSize ) );\n\tREQUIRES( isShortIntegerRangeNZ( certSize ) );\n\n\t/* Calculate the new certificate data size */\n#ifdef USE_PKCS15V12_FORM\n\t*newCertDataSize = sizeofObject( certAttributeSize + \\\n\t\t\t\t\t\t\t\t\t sizeofObject( \\\n\t\t\t\t\t\t\t\t\t   sizeofObject( \\\n\t\t\t\t\t\t\t\t\t\t sizeofObject( certSize ) ) ) );\n#else\n\t*newCertDataSize = sizeofObject( certAttributeSize + \\\n\t\t\t\t\t\t\t\t\t sizeofObject( \\\n\t\t\t\t\t\t\t\t\t   sizeofObject( certSize ) ) );\n#endif /* USE_PKCS15V12_FORM */\n\tENSURES( *newCertDataSize > 0 && *newCertDataSize < MAX_BUFFER_SIZE );\n\n\t/* If the new data will fit into the existing storage, we're done */\n\tif( *newCertDataSize <= pkcs15infoPtr->certDataSize )\n\t\treturn( CRYPT_OK );\n\n\t/* Allocate storage for the new data */\n\tREQUIRES( rangeCheck( *newCertDataSize, 1, MAX_BUFFER_SIZE ) );\n\tnewCertData = clAlloc( \"calculateCertStorage\", *newCertDataSize );\n\tif( newCertData == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t*newCertDataPtr = newCertData;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Delete the public-key entry for a personality, used when we're replacing\n   the pubkey with a certificate */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void deletePubKey( INOUT PKCS15_INFO *pkcs15infoPtr )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tzeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );\n\tclFree( \"deletePubKey\", pkcs15infoPtr->pubKeyData );\n\tpkcs15infoPtr->pubKeyData = NULL;\n\tpkcs15infoPtr->pubKeyDataSize = pkcs15infoPtr->pubKeyOffset = 0;\n\t}\n\n/* Replace existing public-key or certificate data with updated \n   information */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void replacePubkeyData( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t   IN_BUFFER( newPubKeyDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *newPubKeyData, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int newPubKeyDataSize,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int newPubKeyOffset )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( newPubKeyData, newPubKeyDataSize ) );\n\n\tREQUIRES_V( newPubKeyDataSize >= 16 && \\\n\t\t\t\tnewPubKeyDataSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( newPubKeyOffset > 0 && \\\n\t\t\t\tnewPubKeyOffset < newPubKeyDataSize && \\\n\t\t\t\tnewPubKeyOffset < MAX_INTLENGTH_SHORT );\n\n\t/* If we've allocated new storage for the data rather than directly \n\t   replacing the existing entry, free the existing entry and replace it \n\t   with the new one */\n\tif( newPubKeyData != pkcs15infoPtr->pubKeyData )\n\t\t{\n\t\tif( pkcs15infoPtr->pubKeyData != NULL )\n\t\t\t{\n\t\t\tzeroise( pkcs15infoPtr->pubKeyData, \n\t\t\t\t\t pkcs15infoPtr->pubKeyDataSize );\n\t\t\tclFree( \"replacePubkeyData\", pkcs15infoPtr->pubKeyData );\n\t\t\t}\n\t\tpkcs15infoPtr->pubKeyData = ( void * ) newPubKeyData;\n\t\t}\n\n\t/* Update the size information */\n\tpkcs15infoPtr->pubKeyDataSize = newPubKeyDataSize;\n\tpkcs15infoPtr->pubKeyOffset = newPubKeyOffset;\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void replaceCertData( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t IN_BUFFER( newCertDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *newCertData, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int newCertDataSize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int newCertOffset )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( newCertData, newCertDataSize ) );\n\n\tREQUIRES_V( newCertDataSize >= 16 && \\\n\t\t\t\tnewCertDataSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( newCertOffset > 0 && \\\n\t\t\t\tnewCertOffset < newCertDataSize && \\\n\t\t\t\tnewCertOffset < MAX_INTLENGTH_SHORT );\n\n\t/* If we've allocated new storage for the data rather than directly \n\t   replacing the existing entry, free the existing entry and replace it \n\t   with the new one */\n\tif( newCertData != pkcs15infoPtr->certData )\n\t\t{\n\t\tif( pkcs15infoPtr->certData != NULL )\n\t\t\t{\n\t\t\tzeroise( pkcs15infoPtr->certData, pkcs15infoPtr->certDataSize );\n\t\t\tclFree( \"replaceCertData\", pkcs15infoPtr->certData );\n\t\t\t}\n\t\tpkcs15infoPtr->certData = ( void * ) newCertData;\n\t\t}\n\n\t/* Update the size information */\n\tpkcs15infoPtr->certDataSize = newCertDataSize;\n\tpkcs15infoPtr->certOffset = newCertOffset;\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd a Certificate\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a certificate to a PKCS #15 collection, updating affected public and\n   private key attributes as required */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint pkcs15AddCert( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t   IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t   IN_BUFFER_OPT( privKeyAttributeSize ) \\\n\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int privKeyAttributeSize,\n\t\t\t\t   IN_ENUM( CERTADD ) const CERTADD_TYPE certAddType, \n\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE certAttributes[ KEYATTR_BUFFER_SIZE + 8 ];\n\tvoid *newCertData = pkcs15infoPtr->certData;\n\tvoid *newPrivKeyData = pkcs15infoPtr->privKeyData;\n\tint newCertDataSize DUMMY_INIT, certInfoSize DUMMY_INIT;\n\tint newPrivKeyDataSize DUMMY_INIT, privKeyInfoSize DUMMY_INIT;\n\tint newCertOffset DUMMY_INIT, certAttributeSize;\n\tint subType = PKCS15_SUBTYPE_NORMAL, keyTypeTag, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( ( certAddType == CERTADD_UPDATE_EXISTING && \\\n\t\t\t  isReadPtrDynamic( privKeyAttributes, \\\n\t\t\t\t\t\t\t\tprivKeyAttributeSize ) ) || \\\n\t\t\t( ( certAddType == CERTADD_NORMAL || \\\n\t\t\t\tcertAddType == CERTADD_STANDALONE_CERT ) && \\\n\t\t\t  privKeyAttributes == NULL && privKeyAttributeSize == 0 ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( ( certAddType == CERTADD_UPDATE_EXISTING && \\\n\t\t\t\tprivKeyAttributes != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( privKeyAttributeSize ) ) || \\\n\t\t\t  ( ( certAddType == CERTADD_NORMAL || \\\n\t\t\t\t  certAddType == CERTADD_STANDALONE_CERT ) && \\\n\t\t\t\tprivKeyAttributes == NULL && privKeyAttributeSize == 0 ) );\n\tREQUIRES( isEnumRange( certAddType, CERTADD ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get the tag for encoding the key data */\n\tstatus = getKeyTypeTag( iCryptCert, CRYPT_ALGO_NONE, &keyTypeTag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we've been passed a standalone certificate it has to be \n\t   implicitly trusted in order to be added.  We don't perform this check \n\t   if this is a storage object for a hardware device, which acts as a \n\t   generic information store with no restrictions on what can be \n\t   stored */\n\tif( certAddType == CERTADD_STANDALONE_CERT )\n\t\t{\n\t\tBOOLEAN_INT trustedImplicit;\n\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &trustedImplicit, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_TRUSTED_IMPLICIT );\n\t\tif( cryptStatusError( status ) || !trustedImplicit )\n\t\t\t{\n\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, errorInfo, \n\t\t\t\t\t\t \"Only a trusted certificate can be added as a \"\n\t\t\t\t\t\t \"standalone certificate\" ) );\n\t\t\t}\n\n\t\t/* Set the personality type to certificate-only */\n\t\tsubType = PKCS15_SUBTYPE_CERT;\n\t\t}\n\n\t/* Write the certificate attributes */\n\tstatus = writeCertAttributes( certAttributes, KEYATTR_BUFFER_SIZE, \n\t\t\t\t\t\t\t\t  &certAttributeSize, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t  iCryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write certificate attributes\" ) );\n\t\t}\n\n\t/* Find out how big the PKCS #15 data will be and allocate room for it.\n\t   Since adding the certificate will affect the key attributes we need \n\t   to rewrite the key information once we've added the certificate */\n\tif( certAddType == CERTADD_UPDATE_EXISTING )\n\t\t{\n\t\t/* Since we're re-using pre-encoded private key data the extra \n\t\t   information is already present in encoded form so we set the \n\t\t   extraDataSize parameter to zero */\n\t\tprivKeyInfoSize = pkcs15infoPtr->privKeyDataSize - \\\n\t\t\t\t\t\t  pkcs15infoPtr->privKeyOffset;\n\t\tstatus = calculatePrivkeyStorage( &newPrivKeyData, &newPrivKeyDataSize, \n\t\t\t\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyData,\n\t\t\t\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyDataSize,\n\t\t\t\t\t\t\t\t\t\t  privKeyInfoSize,\n\t\t\t\t\t\t\t\t\t\t  privKeyAttributeSize, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertInfoSize = msgData.length;\n\t\tstatus = calculateCertStorage( pkcs15infoPtr, &newCertData,\n\t\t\t\t\t\t\t\t\t   &newCertDataSize, certAttributeSize,\n\t\t\t\t\t\t\t\t\t   certInfoSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( newPrivKeyData != pkcs15infoPtr->privKeyData )\n\t\t\tclFree( \"addCert\", newPrivKeyData );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( newPrivKeyData != NULL );\n\tANALYSER_HINT( newCertData != NULL );\n\n\t/* Write the PKCS #15 certificate data */\n\tsMemOpen( &stream, newCertData, newCertDataSize );\n#ifdef USE_PKCS15V12_FORM\n\twriteSequence( &stream, certAttributeSize + \\\n\t\t\t\t\t\t\tsizeofObject( \\\n\t\t\t\t\t\t\t  sizeofObject( \\\n\t\t\t\t\t\t\t\tsizeofObject( certInfoSize ) ) ) );\n\tswrite( &stream, certAttributes, certAttributeSize );\n\twriteConstructed( &stream, sizeofObject( \\\n\t\t\t\t\t\t\t\t sizeofObject( certInfoSize ) ), \n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\twriteSequence( &stream, sizeofObject( certInfoSize ) );\n\tstatus = writeConstructed( &stream, certInfoSize, CTAG_OV_DIRECT );\n#else\n\twriteSequence( &stream, certAttributeSize + \\\n\t\t\t\t\t\t\tsizeofObject( sizeofObject( certInfoSize ) ) );\n\tswrite( &stream, certAttributes, certAttributeSize );\n\twriteConstructed( &stream, sizeofObject( certInfoSize ), \n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\tstatus = writeSequence( &stream, certInfoSize );\n#endif /* USE_PKCS15V12_FORM */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tnewCertOffset = stell( &stream );\n\t\tstatus = exportCertToStream( &stream, iCryptCert, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Undo what we've done so far without changing the existing PKCS #15\n\t\t   data */\n\t\tDEBUG_DIAG(( \"Failed to set up/write certificate data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tif( newPrivKeyData != pkcs15infoPtr->privKeyData )\n\t\t\tclFree( \"addCert\", newPrivKeyData );\n\t\tif( newCertData != pkcs15infoPtr->certData )\n\t\t\tclFree( \"addCert\", newCertData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write PKCS #15 certificate data\" ) );\n\t\t}\n\tENSURES( cryptStatusOK( \\\n\t\t\t\tcheckCertObjectEncoding( newCertData, \n\t\t\t\t\t\t\t\t\t\t newCertDataSize ) ) );\n\n\t/* Replace the old certificate (if there is one) with the new one.  If \n\t   it's a certificate associated with a private key we also have to \n\t   update the private-key attributes, which can be affected by \n\t   certificate information */\n\tpkcs15infoPtr->type = subType;\n\treplaceCertData( pkcs15infoPtr, newCertData, newCertDataSize, \n\t\t\t\t\t newCertOffset );\n\tif( certAddType == CERTADD_UPDATE_EXISTING )\n\t\t{\n\t\tupdatePrivKeyAttributes( pkcs15infoPtr, \n\t\t\t\t\t\t\t\t newPrivKeyData, newPrivKeyDataSize, \n\t\t\t\t\t\t\t\t privKeyAttributes, privKeyAttributeSize, \n\t\t\t\t\t\t\t\t privKeyInfoSize, keyTypeTag );\n\t\t}\n\n\t/* The public-key data is redundant now that we've performed the update,\n\t   delete it */\n\tif( pkcs15infoPtr->pubKeyData != NULL )\n\t\tdeletePubKey( pkcs15infoPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add a complete certificate chain to a PKCS #15 collection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint pkcs15AddCertChain( INOUT PKCS15_INFO *pkcs15info, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCert, \n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tBOOLEAN itemAdded = FALSE;\n\tint status, loopStatus, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* See if there are certificates in the chain beyond the first one, \n\t   which we've already added.  Getting a data not found error is OK \n\t   since it just means that there are no more certificates present */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );\n\n\t/* Walk up the chain checking each certificate to see whether we need to \n\t   add it */\n\tLOOP_MED( loopStatus = CRYPT_OK, cryptStatusOK( loopStatus ),\n\t\t\t  loopStatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t{\n\t\tPKCS15_INFO *pkcs15infoPtr;\n\t\tBYTE iAndSID[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tint iAndSIDlength, index;\n\n\t\t/* Check whether this certificate is present.  If the door's locked, \n\t\t   move on to the next one */\n\t\tstatus = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\t\tiAndSID, KEYID_SIZE, &iAndSIDlength );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tfindEntry( pkcs15info, noPkcs15objects, CRYPT_IKEYID_ISSUERID, \n\t\t\t\t\t   iAndSID, iAndSIDlength, KEYMGMT_FLAG_NONE, FALSE ) != NULL )\n\t\t\tcontinue;\n\n\t\t/* We've found a certificate that isn't present yet, try and add \n\t\t   it */\n\t\tpkcs15infoPtr = findFreeEntry( pkcs15info, noPkcs15objects, &index );\n\t\tif( pkcs15infoPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tstatus = pkcs15AddCert( pkcs15infoPtr, iCryptCert, NULL, 0, \n\t\t\t\t\t\t\t\tCERTADD_NORMAL, errorInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tpkcs15infoPtr->index = index;\n\t\t\titemAdded = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* A certificate being added may already be present, however we \n\t\t\t   can't fail immediately because there may be further \n\t\t\t   certificates in the chain that can be added so we clear data \n\t\t\t   duplicate errors */\n\t\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t\tbreak;\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !itemAdded )\n\t\t{\n\t\t/* We reached the end of the chain without finding anything that we \n\t\t   could add, return a data duplicate error */\n\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t( CRYPT_ERROR_DUPLICATE, errorInfo, \n\t\t\t\t  \"Couldn't find any new certificates to add\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd a Public Key\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a public key to a PKCS #15 collection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 8 ) ) \\\nint pkcs15AddPublicKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptContext, \n\t\t\t\t\t\tIN_BUFFER( pubKeyAttributeSize ) \\\n\t\t\t\t\t\t\tconst void *pubKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int pubKeyAttributeSize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, \n\t\t\t\t\t\tIN_LENGTH_PKC const int modulusSize, \n\t\t\t\t\t\tconst BOOLEAN isStorageObject, \n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tconst CRYPT_ATTRIBUTE_TYPE keyDataType = isStorageObject ? \\\n\t\t\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : CRYPT_IATTRIBUTE_KEY_SPKI;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tvoid *newPubKeyData = pkcs15infoPtr->pubKeyData;\n\tint newPubKeyDataSize, newPubKeyOffset DUMMY_INIT, pubKeySize;\n\tint extraDataSize = 0, keyTypeTag, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( pubKeyAttributes, pubKeyAttributeSize ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( pubKeyAttributeSize ) );\n\tREQUIRES( isPkcAlgo( pkcCryptAlgo ) );\n\tREQUIRES( ( isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isStorageObject == TRUE || isStorageObject == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get the tag for encoding the key data */\n\tstatus = getKeyTypeTag( CRYPT_UNUSED, pkcCryptAlgo, &keyTypeTag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Find out how big the PKCS #15 data will be and allocate room for it.\n\t   If it's a key metadata object then we have to read the information\n\t   using CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL since it's not necessarily\n\t   in the high state as required by CRYPT_IATTRIBUTE_KEY_SPKI because\n\t   the hardware may not be ready yet, but we can still fetch the stored\n\t   public-key data from it */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, keyDataType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpubKeySize = msgData.length;\n\tif( pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* RSA keys have an extra element for PKCS #11 compatibility */\n\t\textraDataSize = sizeofShortInteger( modulusSize );\n\t\t}\n\tstatus = calculatePubkeyStorage( pkcs15infoPtr, &newPubKeyData, \n\t\t\t\t\t\t\t\t\t &newPubKeyDataSize, pubKeySize, \n\t\t\t\t\t\t\t\t\t pubKeyAttributeSize, extraDataSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the public key data */\n\tsMemOpen( &stream, newPubKeyData, newPubKeyDataSize );\n\twriteConstructed( &stream, pubKeyAttributeSize + \\\n\t\t\t\t\t\t\t   sizeofObject( \\\n\t\t\t\t\t\t\t\t sizeofObject( \\\n\t\t\t\t\t\t\t\t   sizeofObject( pubKeySize ) + \\\n\t\t\t\t\t\t\t\t   extraDataSize ) ),\n\t\t\t\t\t  keyTypeTag );\n\tswrite( &stream, pubKeyAttributes, pubKeyAttributeSize );\n\twriteConstructed( &stream, sizeofObject( \\\n\t\t\t\t\t\t\t\tsizeofObject( pubKeySize ) + \\\n\t\t\t\t\t\t\t\textraDataSize ),\n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\twriteSequence( &stream, sizeofObject( pubKeySize ) + extraDataSize );\n\tstatus = writeConstructed( &stream, pubKeySize, CTAG_OV_DIRECT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tnewPubKeyOffset = stell( &stream );\n\t\tstatus = exportAttributeToStream( &stream, iCryptContext,\n\t\t\t\t\t\t\t\t\t\t  keyDataType );\n\t\t}\n\tif( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* When using the SPKI option for storing key components the RSA\n\t\t   components require a [1] tag since the basic (non-SPKI) option is\n\t\t   also a SEQUENCE, so if it's an RSA key we modify the tag.  This is\n\t\t   easier than passing the tag requirement down through the kernel\n\t\t   call to the context.  In addition RSA keys have an extra element\n\t\t   for PKCS #11 compatibility */\n\t\t( ( BYTE * ) newPubKeyData )[ newPubKeyOffset ] = MAKE_CTAG( 1 );\n\t\tstatus = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );\n\t\t}\n\tassert( stell( &stream ) == newPubKeyDataSize );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Failed to set up/write public key data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tif( newPubKeyData != pkcs15infoPtr->pubKeyData )\n\t\t\tclFree( \"addPublicKey\", newPubKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write PKCS #15 public-key data\" ) );\n\t\t}\n\tENSURES( cryptStatusOK( checkCertObjectEncoding( newPubKeyData, \n\t\t\t\t\t\t\t\t\t\t\t\t\t newPubKeyDataSize ) ) );\n\n\t/* Replace the old data with the newly-written data */\n\treplacePubkeyData( pkcs15infoPtr, newPubKeyData, newPubKeyDataSize,\n\t\t\t\t\t   newPubKeyOffset );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_adpr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #15 Private-key Add Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/* Define the following to write the pre-PKCS #15 v1.2 exponent-size value\n   for RSA private keys */\n\n/* #define USE_RSA_EXTRAPARAM */\n\n/* The minimum number of keying iterations to use when deriving a key wrap\n   key from a password.  We have to be careful here not to exceed the kernel-\n   enforced MAX_KEYSETUP_ITERATIONS, or any attempt to use that many \n   iterations will be blocked by the kernel */\n\n#if defined( CONFIG_SLOW_CPU )\n  #define MIN_KEYING_ITERATIONS\t1000\n#elif defined( CONFIG_FAST_CPU )\n  #define MIN_KEYING_ITERATIONS\t50000\n#else\n  #define MIN_KEYING_ITERATIONS\t10000\n#endif /* CONFIG_SLOW_CPU */\n#if MIN_KEYING_ITERATIONS > MAX_KEYSETUP_ITERATIONS\n  #error MIN_KEYING_ITERATIONS exceeds MAX_KEYSETUP_ITERATIONS\n#endif /* Sanity chechk of keying iterations */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Replace existing private-key data with updated information */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void replacePrivkeyData( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t\tIN_BUFFER( newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\t\tconst void *newPrivKeyData, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\tconst int newPrivKeyDataSize,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int newPrivKeyOffset )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( newPrivKeyData, newPrivKeyDataSize ) );\n\n\tREQUIRES_V( newPrivKeyDataSize >= 16 && \\\n\t\t\t\tnewPrivKeyDataSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( newPrivKeyOffset > 0 && \\\n\t\t\t\tnewPrivKeyOffset < newPrivKeyDataSize && \\\n\t\t\t\tnewPrivKeyOffset < MAX_INTLENGTH_SHORT );\n\n\t/* If we've allocated new storage for the data rather than directly \n\t   replacing the existing entry, free the existing one and replace it\n\t   with the new one */\n\tif( newPrivKeyData != pkcs15infoPtr->privKeyData )\n\t\t{\n\t\tif( pkcs15infoPtr->privKeyData != NULL )\n\t\t\t{\n\t\t\tzeroise( pkcs15infoPtr->privKeyData, \n\t\t\t\t\t pkcs15infoPtr->privKeyDataSize );\n\t\t\tclFree( \"replacePrivkeyData\", pkcs15infoPtr->privKeyData );\n\t\t\t}\n\t\tpkcs15infoPtr->privKeyData = ( void * ) newPrivKeyData;\n\t\t}\n\n\t/* Update the size information */\n\tpkcs15infoPtr->privKeyDataSize = newPrivKeyDataSize;\n\tpkcs15infoPtr->privKeyOffset = newPrivKeyOffset;\n\t}\n\n/* Calculate the size of and if necessary allocate storage for private-key \n   data.  This function has to be accessible externally because adding or \n   changing a certificate for a private key can change the private-key \n   attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint calculatePrivkeyStorage( OUT_BUFFER_ALLOC_OPT( *newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tvoid **newPrivKeyDataPtr, \n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *newPrivKeyDataSize, \n\t\t\t\t\t\t\t IN_BUFFER_OPT( origPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *origPrivKeyData,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int origPrivKeyDataSize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeySize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeyAttributeSize,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int extraDataSize )\n\t{\n\tvoid *newPrivKeyData;\n\n\tassert( isWritePtr( newPrivKeyDataPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( newPrivKeyDataSize, sizeof( int ) ) ); \n\tassert( ( origPrivKeyData == NULL && origPrivKeyDataSize == 0 ) || \\\n\t\t\tisReadPtrDynamic( origPrivKeyData, origPrivKeyDataSize ) );\n\n\tREQUIRES( ( origPrivKeyData == NULL && origPrivKeyDataSize == 0 ) || \\\n\t\t\t  ( origPrivKeyData != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( origPrivKeyDataSize ) ) );\n\tREQUIRES( isShortIntegerRangeNZ( privKeySize ) );\n\tREQUIRES( isShortIntegerRangeNZ( privKeyAttributeSize ) );\n\tREQUIRES( isShortIntegerRange( extraDataSize ) );\n\n\t/* Clear return values */\n\t*newPrivKeyDataPtr = NULL;\n\t*newPrivKeyDataSize = 0;\n\n\t/* Calculate the new private-key data size */\n\t*newPrivKeyDataSize = sizeofObject( privKeyAttributeSize + \\\n\t\t\t\t\t\t\t\t\t\tsizeofObject( \\\n\t\t\t\t\t\t\t\t\t\t\tsizeofObject( privKeySize ) + \\\n\t\t\t\t\t\t\t\t\t\t\textraDataSize ) );\n\tENSURES( *newPrivKeyDataSize > 0 && \\\n\t\t\t *newPrivKeyDataSize < MAX_BUFFER_SIZE );\n\n\t/* If the new data will fit into the existing storage, we're done */\n\tif( *newPrivKeyDataSize <= origPrivKeyDataSize )\n\t\t{\n\t\t*newPrivKeyDataPtr = ( void * ) origPrivKeyData;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Allocate storage for the new data */\n\tREQUIRES( rangeCheck( *newPrivKeyDataSize, 1, MAX_BUFFER_SIZE ) );\n\tnewPrivKeyData = clAlloc( \"calculatePrivkeyStorage\", *newPrivKeyDataSize );\n\tif( newPrivKeyData == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\t*newPrivKeyDataPtr = newPrivKeyData;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Update the private-key attributes while leaving the private key itself\n   untouched.  This is necessary after updating a certificate associated \n   with a private key, which can affect the key's attributes */\n\nSTDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nvoid updatePrivKeyAttributes( INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tvoid *newPrivKeyData, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int newPrivKeyDataSize,\n\t\t\t\t\t\t\t  IN_BUFFER( privKeyAttributeSize ) \\\n\t\t\t\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int privKeyAttributeSize, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int privKeyInfoSize, \n\t\t\t\t\t\t\t  IN_TAG const int keyTypeTag )\n\t{\n\tSTREAM stream;\n\tBYTE keyBuffer[ MAX_PRIVATE_KEYSIZE + 8 ];\n\tint newPrivKeyOffset DUMMY_INIT, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtrDynamic( newPrivKeyData, newPrivKeyDataSize ) );\n\tassert( isReadPtrDynamic( privKeyAttributes, privKeyAttributeSize ) );\n\n\tREQUIRES_V( newPrivKeyDataSize >= 16 && \\\n\t\t\t\tnewPrivKeyDataSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( isShortIntegerRangeNZ( privKeyAttributeSize ) );\n\tREQUIRES_V( privKeyInfoSize > 0 && \\\n\t\t\t\tprivKeyInfoSize < MAX_PRIVATE_KEYSIZE );\n\tREQUIRES_V( keyTypeTag == DEFAULT_TAG || \\\n\t\t\t\t( keyTypeTag >= 0 && keyTypeTag < MAX_TAG_VALUE ) );\n\n\t/* Since we may be doing an in-place update of the private-key \n\t   information we copy the wrapped key data out to a temporary buffer \n\t   while we make the changes */\n\tREQUIRES_V( boundsCheck( pkcs15infoPtr->privKeyOffset, privKeyInfoSize,\n\t\t\t\t\t\t     pkcs15infoPtr->privKeyDataSize ) );\n\tmemcpy( keyBuffer, ( BYTE * ) pkcs15infoPtr->privKeyData +\n\t\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyOffset,\n\t\t\tprivKeyInfoSize );\n\n\t/* The corresponding key is already present, we need to update the key\n\t   attributes since adding the certificate may have changed them.  The\n\t   key data itself is unchanged so we just memcpy() it across verbatim */\n\tsMemOpen( &stream, newPrivKeyData, newPrivKeyDataSize );\n\twriteConstructed( &stream, privKeyAttributeSize + \\\n\t\t\t\t\t\t\t   sizeofObject( \\\n\t\t\t\t\t\t\t\t\tsizeofObject( privKeyInfoSize ) ), \n\t\t\t\t\t  keyTypeTag );\n\tswrite( &stream, privKeyAttributes, privKeyAttributeSize );\n\twriteConstructed( &stream, sizeofShortObject( privKeyInfoSize ),\n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\tstatus = writeSequence( &stream, privKeyInfoSize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tnewPrivKeyOffset = stell( &stream );\n\t\tstatus = swrite( &stream, keyBuffer, privKeyInfoSize );\n\t\t}\n\tsMemDisconnect( &stream );\n\tzeroise( keyBuffer, MAX_PRIVATE_KEYSIZE );\n\tENSURES_V( cryptStatusOK( status ) && \\\n\t\t\t   cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( newPrivKeyData, \n\t\t\t\t\t\t\t\t\t\t\t newPrivKeyDataSize ) ) );\n\n\t/* Replace the old data with the newly-written data */\n\treplacePrivkeyData( pkcs15infoPtr, newPrivKeyData, newPrivKeyDataSize, \n\t\t\t\t\t\tnewPrivKeyOffset );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEncryption Context Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a strong encryption/MAC context to protect a private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createStrongAlgorithmContext( OUT_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t\t\t\t\t IN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iMasterKeyContext,\n\t\t\t\t\t\t\t\t\t\t const BOOLEAN isCryptContext )\n\t{\n\tCRYPT_CONTEXT iLocalContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMECHANISM_KDF_INFO mechanismInfo;\n\tint algorithm, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( iMasterKeyContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iMasterKeyContext ) );\n\tREQUIRES( isCryptContext == TRUE || isCryptContext == FALSE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* In the interests of luser-proofing we're rather paranoid and force\n\t   the use of non-weak algorithms and modes of operation.  In addition\n\t   since OIDs are only defined for a limited subset of algorithms we \n\t   also default to a guaranteed available algorithm if no OID is defined\n\t   for the algorithm that was requested */\n\tif( isCryptContext )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &algorithm, CRYPT_OPTION_ENCR_ALGO );\n\t\tif( cryptStatusError( status ) || isWeakCryptAlgo( algorithm ) || \\\n\t\t\tcryptStatusError( sizeofAlgoIDex( algorithm, CRYPT_MODE_CBC ) ) )\n\t\t\t{\n\t\t\talgorithm = DEFAULT_CRYPT_ALGO;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &algorithm, CRYPT_OPTION_ENCR_MAC );\n\t\tif( cryptStatusError( status ) || isWeakMacAlgo( algorithm ) || \\\n\t\t\tcryptStatusError( sizeofAlgoID( algorithm ) ) )\n\t\t\t{\n\t\t\talgorithm = CRYPT_ALGO_HMAC_SHA1;\n\t\t\t}\n\t\t}\n\n\t/* Create the context */\n\tsetMessageCreateObjectInfo( &createInfo, algorithm );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalContext = createInfo.cryptHandle;\n\n\t/* Perform any additional initialisation that may be required.  In \n\t   particular we need to generate an IV at this point so that it can be \n\t   copied to the generic-secret context */\n\tif( isCryptContext )\n\t\t{\n\t\tstatus = krnlSendNotifier( iLocalContext, IMESSAGE_CTX_GENIV );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* If we're using standard encryption, we're done */\n\tif( iMasterKeyContext == CRYPT_UNUSED )\n\t\t{\n\t\t*iCryptContext = iLocalContext;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Derive the key for the context from the generic-secret context */\n\tif( isCryptContext )\n\t\t{\n\t\tsetMechanismKDFInfo( &mechanismInfo, iLocalContext, \n\t\t\t\t\t\t\t iMasterKeyContext, CRYPT_ALGO_HMAC_SHA1, \n\t\t\t\t\t\t\t \"encryption\", 10 );\n\t\t}\n\telse\n\t\t{\n\t\tsetMechanismKDFInfo( &mechanismInfo, iLocalContext, \n\t\t\t\t\t\t\t iMasterKeyContext, CRYPT_ALGO_HMAC_SHA1, \n\t\t\t\t\t\t\t \"authentication\", 14 );\n\t\t}\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iCryptContext = iLocalContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Send algorithm parameters from the encryption or MAC context to the\n   generic-secret context */\n\nCHECK_RETVAL \\\nstatic int setAlgoParams( IN_HANDLE const CRYPT_CONTEXT iGenericSecret,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE algorithmParamData[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint algorithmParamDataSize DUMMY_INIT, status;\n\n\tREQUIRES( isHandleRangeValid( iGenericSecret ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( attribute == CRYPT_IATTRIBUTE_ENCPARAMS || \\\n\t\t\t  attribute == CRYPT_IATTRIBUTE_MACPARAMS );\n\n\t/* Get the algorithm parameter data from the encryption or MAC\n\t   context */\n\tsMemOpen( &stream, algorithmParamData, CRYPT_MAX_TEXTSIZE );\n\tif( attribute == CRYPT_IATTRIBUTE_ENCPARAMS )\n\t\tstatus = writeCryptContextAlgoID( &stream, iCryptContext );\n\telse\n\t\tstatus = writeContextAlgoID( &stream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\talgorithmParamDataSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the encoded parameter information to the generic-secret \n\t   context */\n\tsetMessageData( &msgData, algorithmParamData, algorithmParamDataSize );\n\treturn( krnlSendMessage( iGenericSecret, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, attribute ) );\n\t}\n\n/* Create encryption contexts to protect the private key data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int createContexts( OUT_HANDLE_OPT CRYPT_CONTEXT *iGenericSecret,\n\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_CONTEXT *iMacContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iCryptOwner )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( iGenericSecret, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iMacContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\n\t/* Clear return values */\n\t*iGenericSecret = *iCryptContext = *iMacContext = CRYPT_ERROR;\n\n\t/* Create the generic-secret context from which the encryption and MAC\n\t   keys will be derived and generate a key into it */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_IALGO_GENERIC_SECRET );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*iGenericSecret = createInfo.cryptHandle;\n\tstatus = krnlSendNotifier( *iGenericSecret, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( *iGenericSecret, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Create the encryption and MAC contexts and derive the keys for them \n\t   from the generic-secret context */\n\tstatus = createStrongAlgorithmContext( iCryptContext, iCryptOwner,\n\t\t\t\t\t\t\t\t\t\t   *iGenericSecret, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( *iGenericSecret, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tstatus = createStrongAlgorithmContext( iMacContext, iCryptOwner,\n\t\t\t\t\t\t\t\t\t\t   *iGenericSecret, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( *iGenericSecret, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Send the algorithm parameters for the encryption and MAC contexts to\n\t   the generic-secret context */\n\tstatus = setAlgoParams( *iGenericSecret, *iCryptContext,\n\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_ENCPARAMS );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = setAlgoParams( *iGenericSecret, *iMacContext,\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_MACPARAMS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( *iGenericSecret, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( *iMacContext, IMESSAGE_DECREFCOUNT );\n\t\t}\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPrivate-key Wrap Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a wrapped content-protection key in the form \n   SET OF { [ 0 ] (EncryptedKey) } */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int writeWrappedSessionKey( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   IN_HANDLE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t\t\t   IN_BUFFER( passwordLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst char *password,\n\t\t\t\t\t\t\t\t   IN_LENGTH_NAME const int passwordLength )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tint iterations, exportedKeySize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* In the interests of luser-proofing we force the use of a safe minimum \n\t   number of iterations */\n\tstatus = krnlSendMessage( iCryptOwner, IMESSAGE_GETATTRIBUTE, &iterations,\n\t\t\t\t\t\t\t  CRYPT_OPTION_KEYING_ITERATIONS );\n\tif( cryptStatusError( status ) || iterations < MIN_KEYING_ITERATIONS )\n\t\titerations = MIN_KEYING_ITERATIONS;\n\n\t/* Create an encryption context and derive the user password into it */\n\tstatus = createStrongAlgorithmContext( &iCryptContext, iCryptOwner, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_UNUSED, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &iterations, CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, \n\t\t\t\t\t\tpasswordLength );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_VALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Determine the size of the exported key and write the encrypted data\n\t   content field */\n\tstatus = iCryptExportKey( NULL, 0, &exportedKeySize, CRYPT_FORMAT_CMS, \n\t\t\t\t\t\t\t  iSessionKeyContext, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *dataPtr;\n\t\tint length;\n\n\t\twriteSet( stream, exportedKeySize );\n\t\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = iCryptExportKey( dataPtr, length, &exportedKeySize,\n\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CMS, iSessionKeyContext, \n\t\t\t\t\t\t\t\t\t  iCryptContext );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sSkip( stream, exportedKeySize, MAX_INTLENGTH_SHORT );\n\t\t}\n\n\t/* Clean up */\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/* Write the private key wrapped using the session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeWrappedPrivateKey( OUT_BUFFER( wrappedKeyMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t   *wrappedKeyLength ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *wrappedKey, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int wrappedKeyMaxLength,\n\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( wrappedKeyMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\tint *wrappedKeyLength,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iPrivKeyContext,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_CONTEXT iMacContext,\n\t\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE pkcAlgo )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tSTREAM encDataStream;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtrDynamic( wrappedKey, wrappedKeyMaxLength ) );\n\tassert( isWritePtr( wrappedKeyLength, sizeof( int ) ) );\n\n\tREQUIRES( wrappedKeyMaxLength >= 16 && \\\n\t\t\t  wrappedKeyMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( iMacContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iMacContext ) );\n\tREQUIRES( isPkcAlgo( pkcAlgo ) );\n\n\t/* Clear return values */\n\tmemset( wrappedKey, 0, min( 16, wrappedKeyMaxLength ) );\n\t*wrappedKeyLength = 0;\n\n\t/* Export the wrapped private key */\n\tsetMechanismWrapInfo( &mechanismInfo, wrappedKey, wrappedKeyMaxLength, \n\t\t\t\t\t\t  NULL, 0, iPrivKeyContext, iCryptContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );\n\tif( cryptStatusOK( status ) )\n\t\tlength = mechanismInfo.wrappedDataLength;\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*wrappedKeyLength = length;\n\n\t/* MAC the wrapped key data if necessary */\n\tif( iMacContext != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t  wrappedKey, length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Try and check that the wrapped key data no longer contains \n\t   identifiable structured data.  We can only do this for RSA keys \n\t   because the amount of information present for DLP keys (a single \n\t   short integer) is too small to reliably check.  This check is \n\t   performed in addition to checks already performed by the encryption \n\t   code and the key wrap code */\n\tif( pkcAlgo != CRYPT_ALGO_RSA )\n\t\treturn( CRYPT_OK );\n\n\t/* For RSA keys the data would be:\n\n\t\tSEQUENCE {\n\t\t\t[3] INTEGER,\n\t\t\t...\n\t\t\t}\n\n\t   99.9% of all wrapped keys will fail the initial valid-SEQUENCE check \n\t   so we provide an early-out for it */\n\tsMemConnect( &encDataStream, wrappedKey, *wrappedKeyLength );\n\tstatus = readSequence( &encDataStream, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &encDataStream );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The data must contain at least p and q, or at most all key \n\t   components */\n\tif( length < MIN_PKCSIZE * 2 || length > MAX_PRIVATE_KEYSIZE )\n\t\t{\n\t\tsMemDisconnect( &encDataStream );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The first key component is p, encoded as '[3] INTEGER' */\n\tstatus = readIntegerTag( &encDataStream, NULL, CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t &length, 3 );\n\tif( cryptStatusOK( status ) && \\\n\t\t( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE ) )\n\t\tstatus = CRYPT_ERROR;\n\tsMemDisconnect( &encDataStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* We appear to have plaintext data still present in the buffer, clear \n\t   it and warn the user */\n\tzeroise( wrappedKey, wrappedKeyMaxLength );\n\tDEBUG_DIAG(( \"Private key data wasn't encrypted\" ));\n\tassert( DEBUG_WARN );\n\treturn( CRYPT_ERROR_FAILED );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd a Private Key\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A structure to store various parameters needed when writing a private \n   key */\n\ntypedef struct {\n\t/* Encryption contexts used to secure the private key */\n\tCRYPT_CONTEXT iGenericContext, iCryptContext, iMacContext;\n\n\t/* The encoded private-key attributes */\n\tBUFFER_FIXED( privKeyAttributeSize ) \\\n\tconst void *privKeyAttributes; \n\tint privKeyAttributeSize;\n\n\t/* Miscellaneous information */\n\tCRYPT_ALGO_TYPE pkcCryptAlgo;\t/* Private-key algorithm */\n#ifdef USE_RSA_EXTRAPARAM\n\tint modulusSize;\t\t\t\t/* Optional parameter for RSA keys */\n#endif /* USE_RSA_EXTRAPARAM */\n\tint keyTypeTag;\t\t\t\t\t/* ASN.1 tag for encoding key data */\n\t} PRIVKEY_WRITE_PARAMS;\n\n#define initPrivKeyParams( params, genericCtx, cryptCtx, macCtx, keyAttr, keyAttrSize, pkcAlgo, modSize, keyTag ) \\\n\t\tmemset( params, 0, sizeof( PRIVKEY_WRITE_PARAMS ) ); \\\n\t\t( params )->iGenericContext = genericCtx; \\\n\t\t( params )->iCryptContext = cryptCtx; \\\n\t\t( params )->iMacContext = macCtx; \\\n\t\t( params )->privKeyAttributes = keyAttr; \\\n\t\t( params )->privKeyAttributeSize = keyAttrSize; \\\n\t\t( params )->pkcCryptAlgo = pkcAlgo; \\\n\t\t( params )->keyTypeTag = keyTag;\n#ifdef USE_RSA_EXTRAPARAM\n\t\t( params )->modulusSize = modSize;\n#endif /* USE_RSA_EXTRAPARAM */\n\n/* Add private-key metadata to a PKCS #15 storage object using a simplified \n   version if the code in the standard writePrivateKey() to store just the \n   attributes and the external storage reference */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int addPrivateKeyMetadata( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t\t\t  const PRIVKEY_WRITE_PARAMS *privKeyParams )\n\t{\n\tSTREAM stream;\n\tMESSAGE_DATA msgData;\n\tBYTE storageID[ KEYID_SIZE + 8 ];\n\tvoid *newPrivKeyData = pkcs15infoPtr->privKeyData;\n\tconst int privKeySize = sizeofObject( KEYID_SIZE );\n\tint newPrivKeyDataSize, newPrivKeyOffset DUMMY_INIT;\n\tint extraDataSize = 0;\n\tint status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtr( privKeyParams, sizeof( PRIVKEY_WRITE_PARAMS ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\tREQUIRES( privKeyParams->iGenericContext == CRYPT_UNUSED && \\\n\t\t\t  privKeyParams->iCryptContext == CRYPT_UNUSED && \\\n\t\t\t  privKeyParams->iMacContext == CRYPT_UNUSED );\n\tREQUIRES( isShortIntegerRangeNZ( privKeyParams->privKeyAttributeSize ) );\n\tREQUIRES( isPkcAlgo( privKeyParams->pkcCryptAlgo ) );\n#ifdef USE_RSA_EXTRAPARAM\n\tREQUIRES( ( isEccAlgo( privKeyParams->pkcCryptAlgo ) && \\\n\t\t\t\tprivKeyParams->modulusSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t\tprivKeyParams->modulusSize <= CRYPT_MAX_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( privKeyParams->pkcCryptAlgo ) && \\\n\t\t\t\tprivKeyParams->modulusSize >= MIN_PKCSIZE && \\\n\t\t\t\tprivKeyParams->modulusSize <= CRYPT_MAX_PKCSIZE ) );\n#endif /* USE_RSA_EXTRAPARAM */\n\tREQUIRES( privKeyParams->keyTypeTag == DEFAULT_TAG || \\\n\t\t\t  ( privKeyParams->keyTypeTag >= 0 && \\\n\t\t\t\tprivKeyParams->keyTypeTag < MAX_TAG_VALUE ) );\n\n\t/* Get the storage ID used to link the metadata to the actual keying \n\t   data held in external hardware */\n\tsetMessageData( &msgData, storageID, KEYID_SIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate the private-key storage size */\n#ifdef USE_RSA_EXTRAPARAM\n\tif( privKeyParams->pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* RSA keys have an extra element for PKCS #11 compatibility */\n\t\textraDataSize = sizeofShortInteger( \\\n\t\t\t\t\t\t\tbytesToBits( privKeyParams->modulusSize ) );\n\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\tstatus = calculatePrivkeyStorage( &newPrivKeyData, &newPrivKeyDataSize, \n\t\t\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyData,\n\t\t\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyDataSize,\n\t\t\t\t\t\t\t\t\t  sizeofObject( privKeySize ),\n\t\t\t\t\t\t\t\t\t  privKeyParams->privKeyAttributeSize, \n\t\t\t\t\t\t\t\t\t  extraDataSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tsMemOpen( &stream, newPrivKeyData, newPrivKeyDataSize );\n\n\t/* Write the outer header, attributes, and storage reference */\n\twriteConstructed( &stream, privKeyParams->privKeyAttributeSize + \\\n\t\t\t\t\t\t\t   sizeofObject( \\\n\t\t\t\t\t\t\t\t\tsizeofObject( \\\n\t\t\t\t\t\t\t\t\t\tsizeofObject( privKeySize ) + \\\n\t\t\t\t\t\t\t\t\t\textraDataSize ) ),\n\t\t\t\t\t  privKeyParams->keyTypeTag );\n\tswrite( &stream, privKeyParams->privKeyAttributes, \n\t\t\tprivKeyParams->privKeyAttributeSize );\n\twriteConstructed( &stream, \n\t\t\t\t\t  sizeofObject( \\\n\t\t\t\t\t\t\tsizeofObject( privKeySize + extraDataSize ) ), \n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\tstatus = writeSequence( &stream, \n\t\t\t\t\t\t\tsizeofObject( privKeySize + extraDataSize ) );\n\tif( cryptStatusOK( status ) )\n\t\tnewPrivKeyOffset = stell( &stream );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\twriteSequence( &stream, privKeySize );\n\t\tstatus = writeOctetString( &stream, storageID, KEYID_SIZE, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n#ifdef USE_RSA_EXTRAPARAM\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tprivKeyParams->pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t\t{\n\t\t\t/* RSA keys have an extra element for PKCS #11 compability that \n\t\t\t   we need to kludge onto the end of the private-key data */\n\t\t\tstatus = writeShortInteger( &stream, \n\t\t\t\t\t\t\t\tbytesToBits( privKeyParams->modulusSize ), \n\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\t\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\tassert( newPrivKeyDataSize == stell( &stream ) );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( newPrivKeyData, \n\t\t\t\t\t\t\t\t\t\t\t newPrivKeyDataSize ) ) );\n\n\t/* Replace the old data with the newly-written data */\n\treplacePrivkeyData( pkcs15infoPtr, newPrivKeyData, \n\t\t\t\t\t\tnewPrivKeyDataSize, newPrivKeyOffset );\n\treturn( CRYPT_OK );\n\t}\n\n/* Write an encrypted and MACd private key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 8, 9, 10, 11 ) ) \\\nstatic int writePrivateKey( IN_HANDLE const CRYPT_HANDLE iPrivKeyContext,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptOwner,\n\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_NAME const int passwordLength,\n\t\t\t\t\t\t\tconst PRIVKEY_WRITE_PARAMS *privKeyParams,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( origPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *origPrivKeyData,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int origPrivKeyDataSize,\n\t\t\t\t\t\t\tOUT_BUFFER_ALLOC_OPT( *newPrivKeyDataSize ) \\\n\t\t\t\t\t\t\t\tvoid **newPrivKeyData,\n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *newPrivKeyDataSize,\n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *newPrivKeyOffset, \n\t\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE envelopeHeaderBuffer[ 256 + 8 ], macValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tvoid *encryptedKeyDataPtr, *macDataPtr DUMMY_INIT_PTR;\n\tint privKeySize DUMMY_INIT, extraDataSize = 0, macSize;\n\tint envelopeHeaderSize, envelopeContentSize;\n\tint macDataOffset DUMMY_INIT, macDataLength DUMMY_INIT;\n\tint encryptedKeyDataLength, status;\n\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isReadPtr( privKeyParams, sizeof( PRIVKEY_WRITE_PARAMS ) ) );\n\tassert( ( origPrivKeyData == NULL && origPrivKeyDataSize == 0 ) || \\\n\t\t\tisReadPtrDynamic( origPrivKeyData, origPrivKeyDataSize ) );\n\tassert( isWritePtr( newPrivKeyData, sizeof( void * ) ) );\n\tassert( isWritePtr( newPrivKeyDataSize, sizeof( int ) ) );\n\tassert( isWritePtr( newPrivKeyOffset, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( origPrivKeyData == NULL && origPrivKeyDataSize == 0 ) || \\\n\t\t\t  ( origPrivKeyData != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( origPrivKeyDataSize ) ) );\n\n\tREQUIRES( isHandleRangeValid( privKeyParams->iGenericContext ) );\n\tREQUIRES( isHandleRangeValid( privKeyParams->iCryptContext ) );\n\tREQUIRES( isHandleRangeValid( privKeyParams->iMacContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( privKeyParams->privKeyAttributeSize ) );\n\tREQUIRES( isPkcAlgo( privKeyParams->pkcCryptAlgo ) );\n#ifdef USE_RSA_EXTRAPARAM\n\tREQUIRES( ( isEccAlgo( privKeyParams->pkcCryptAlgo ) && \\\n\t\t\t\tprivKeyParams->modulusSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t\tprivKeyParams->modulusSize <= CRYPT_MAX_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( privKeyParams->pkcCryptAlgo ) && \\\n\t\t\t\tprivKeyParams->modulusSize >= MIN_PKCSIZE && \\\n\t\t\t\tprivKeyParams->modulusSize <= CRYPT_MAX_PKCSIZE ) );\n#endif /* USE_RSA_EXTRAPARAM */\n\tREQUIRES( privKeyParams->keyTypeTag == DEFAULT_TAG || \\\n\t\t\t  ( privKeyParams->keyTypeTag >= 0 && \\\n\t\t\t\tprivKeyParams->keyTypeTag < MAX_TAG_VALUE ) );\n\n\t/* Clear return values */\n\t*newPrivKeyData = NULL;\n\t*newPrivKeyDataSize = *newPrivKeyOffset = 0;\n\n\t/* Calculate the eventual encrypted key size */\n\tsetMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, iPrivKeyContext,\n\t\t\t\t\t\t  privKeyParams->iCryptContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );\n\tif( cryptStatusOK( status ) )\n\t\tprivKeySize = mechanismInfo.wrappedDataLength;\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( privKeySize >= 16 && privKeySize <= 256 + MAX_PRIVATE_KEYSIZE );\n\n\t/* Determine the size of the MAC value */\n\tstatus = krnlSendMessage( privKeyParams->iMacContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &macSize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmacSize = sizeofObject( macSize );\n\n\t/* Write the CMS envelope header for the wrapped private key except for \n\t   the outermost wrapper, which we have to defer writing until later \n\t   because we won't know the size of the encryption context information \n\t   or inner CMS header until we've written them.  Since we're using \n\t   KEKRecipientInfo we use a version of 2 rather than 0 */\n\tsMemOpen( &stream, envelopeHeaderBuffer, 256 );\n\twriteShortInteger( &stream, 2, DEFAULT_TAG );\n\tstatus = writeWrappedSessionKey( &stream, privKeyParams->iGenericContext, \n\t\t\t\t\t\t\t\t\t iCryptOwner, password, passwordLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmacDataOffset = stell( &stream );\n\t\tstatus = writeCMSencrHeader( &stream, OID_CMS_DATA, \n\t\t\t\t\t\t\t\t\t sizeofOID( OID_CMS_DATA ), privKeySize,\n\t\t\t\t\t\t\t\t\t privKeyParams->iGenericContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write envelope header for wrapping private \"\n\t\t\t\t  \"key\" ) );\n\t\t}\n\tenvelopeHeaderSize = stell( &stream );\n\tenvelopeContentSize = envelopeHeaderSize + privKeySize + macSize;\n\tsMemDisconnect( &stream );\n\n\t/* Since we haven't been able to write the outer CMS envelope wrapper \n\t   yet we need to adjust the overall size for the additional level of\n\t   encapsulation */\n\tprivKeySize = sizeofShortObject( envelopeContentSize );\n\n\t/* Calculate the private-key storage size */\n#ifdef USE_RSA_EXTRAPARAM\n\tif( privKeyParams->pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* RSA keys have an extra element for PKCS #11 compatibility */\n\t\textraDataSize = sizeofShortInteger( privKeyParams->modulusSize );\n\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\tstatus = calculatePrivkeyStorage( newPrivKeyData, newPrivKeyDataSize, \n\t\t\t\t\t\t\t\t\t  origPrivKeyData, origPrivKeyDataSize,\n\t\t\t\t\t\t\t\t\t  privKeySize, \n\t\t\t\t\t\t\t\t\t  privKeyParams->privKeyAttributeSize, \n\t\t\t\t\t\t\t\t\t  extraDataSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* MAC the EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier \n\t   information alongside the payload data to prevent an attacker from \n\t   manipulating the algorithm parameters to cause corruption that won't \n\t   be detected by the MAC on the payload data */\n\tsMemConnect( &stream, envelopeHeaderBuffer + macDataOffset, \n\t\t\t\t envelopeHeaderSize - macDataOffset );\n\treadSequenceI( &stream, NULL );\t\t/* Outer encapsulation */\n\tstatus = readUniversal( &stream );\t/* Content-type OID */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getStreamObjectLength( &stream, &macDataLength );\n\tif( cryptStatusOK( status ) )\t\t/* AlgoID */\n\t\t{\n\t\tstatus = sMemGetDataBlock( &stream, &macDataPtr, \n\t\t\t\t\t\t\t\t   macDataLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( privKeyParams->iMacContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, macDataPtr, \n\t\t\t\t\t\t\t\t  macDataLength );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( newPrivKeyData != origPrivKeyData )\n\t\t\tclFree( \"writePrivateKey\", *newPrivKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't MAC encryption attributes\" ) );\n\t\t}\n\n\tsMemOpen( &stream, *newPrivKeyData, *newPrivKeyDataSize );\n\n\t/* Write the outer header and attributes */\n\twriteConstructed( &stream, privKeyParams->privKeyAttributeSize + \\\n\t\t\t\t\t\t\t   sizeofObject( sizeofObject( privKeySize ) + \\\n\t\t\t\t\t\t\t\t\t\t\t extraDataSize ),\n\t\t\t\t\t  privKeyParams->keyTypeTag );\n\tswrite( &stream, privKeyParams->privKeyAttributes, \n\t\t\tprivKeyParams->privKeyAttributeSize );\n\twriteConstructed( &stream, \n\t\t\t\t\t  sizeofObject( privKeySize + extraDataSize ), \n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\tstatus = writeSequence( &stream, privKeySize + extraDataSize );\n\tif( cryptStatusOK( status ) )\n\t\t*newPrivKeyOffset = stell( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tif( newPrivKeyData != origPrivKeyData )\n\t\t\tclFree( \"writePrivateKey\", *newPrivKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write private key attributes\" ) );\n\t\t}\n\n\t/* Write the previously-encoded CMS envelope header and key exchange \n\t   information.  Since we now know the size of the envelope header \n\t   (which we couldn't write earlier) we can add this too */\n\twriteConstructed( &stream, envelopeContentSize, \n\t\t\t\t\t  CTAG_OV_DIRECTPROTECTED_EXT );\n\tstatus = swrite( &stream, envelopeHeaderBuffer, envelopeHeaderSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t\n\t/* Write the encrypted private key by exporting it directly into the \n\t   stream buffer */\n\tstatus = sMemGetDataBlockRemaining( &stream, &encryptedKeyDataPtr, \n\t\t\t\t\t\t\t\t\t\t&encryptedKeyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeWrappedPrivateKey( encryptedKeyDataPtr, \n\t\t\t\t\t\t\t\t\t\t encryptedKeyDataLength, &privKeySize, \n\t\t\t\t\t\t\t\t\t\t iPrivKeyContext, \n\t\t\t\t\t\t\t\t\t\t privKeyParams->iCryptContext, \n\t\t\t\t\t\t\t\t\t\t privKeyParams->iMacContext, \n\t\t\t\t\t\t\t\t\t\t privKeyParams->pkcCryptAlgo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( &stream, privKeySize, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tif( newPrivKeyData != origPrivKeyData )\n\t\t\tclFree( \"writePrivateKey\", *newPrivKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write wrapped private key\" ) );\n\t\t}\n\n\t/* Get the MAC value and write it */\n\tsetMessageData( &msgData, macValue, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( privKeyParams->iMacContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeOctetString( &stream, macValue, msgData.length, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tif( newPrivKeyData != origPrivKeyData )\n\t\t\tclFree( \"writePrivateKey\", *newPrivKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write integrity check value for wrapped private \"\n\t\t\t\t  \"key\" ) );\n\t\t}\n\n#ifdef USE_RSA_EXTRAPARAM\n\t/* RSA keys have an extra element for PKCS #11 compability that we need \n\t   to kludge onto the end of the private-key data */\n\tif( privKeyParams->pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\tstatus = writeShortInteger( &stream, privKeyParams->modulusSize, \n\t\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemClose( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\tassert( *newPrivKeyDataSize == stell( &stream ) );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( *newPrivKeyData, \n\t\t\t\t\t\t\t\t\t\t\t *newPrivKeyDataSize ) ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add a private key to a PKCS #15 collection */\n\n#if 1\t/* New (3.4.0+) code to write the private key as AuthEnvData */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6, 11 ) ) \\\nint pkcs15AddPrivateKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iPrivKeyContext,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptOwner,\n\t\t\t\t\t\t IN_BUFFER_OPT( passwordLength ) const char *password, \n\t\t\t\t\t\t IN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t IN_BUFFER( privKeyAttributeSize ) \\\n\t\t\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeyAttributeSize,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, \n\t\t\t\t\t\t IN_LENGTH_PKC const int modulusSize, \n\t\t\t\t\t\t const BOOLEAN isStorageObject, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iGenericContext, iCryptContext, iMacContext;\n\tPRIVKEY_WRITE_PARAMS privKeyParams;\n\tvoid *newPrivKeyData;\n\tint newPrivKeyDataSize, newPrivKeyOffset, keyTypeTag, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( ( isStorageObject && password == NULL && passwordLength == 0 ) || \\\n\t\t\t( !isStorageObject && isReadPtrDynamic( password, passwordLength ) ) );\n\tassert( isReadPtrDynamic( privKeyAttributes, privKeyAttributeSize ) );\n\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( ( isStorageObject && password == NULL && \\\n\t\t\t\tpasswordLength == 0 ) || \\\n\t\t\t  ( !isStorageObject && password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isShortIntegerRangeNZ( privKeyAttributeSize ) );\n\tREQUIRES( isPkcAlgo( pkcCryptAlgo ) );\n\tREQUIRES( ( isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isStorageObject == TRUE || isStorageObject == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get the tag for encoding the key data */\n\tstatus = getKeyTypeTag( CRYPT_UNUSED, pkcCryptAlgo, &keyTypeTag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If this is a dummy object (in other words object metadata) being \n\t   stored in a PKCS #15 object store then there's nothing present except\n\t   key attributes and a reference to the key held in external hardware,\n\t   in which case we use a simplified version of the key-write code */\n\tif( isStorageObject )\n\t\t{\n\t\tinitPrivKeyParams( &privKeyParams, CRYPT_UNUSED, CRYPT_UNUSED, \n\t\t\t\t\t\t   CRYPT_UNUSED, privKeyAttributes, \n\t\t\t\t\t\t   privKeyAttributeSize, pkcCryptAlgo, modulusSize,\n\t\t\t\t\t\t   keyTypeTag );\n\t\tstatus = addPrivateKeyMetadata( pkcs15infoPtr, iPrivKeyContext, \n\t\t\t\t\t\t\t\t\t\t&privKeyParams );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't write private key metadata\" ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Create the contexts needed to protect the private-key data */\n\tstatus = createContexts( &iGenericContext, &iCryptContext, &iMacContext,\n\t\t\t\t\t\t\t iCryptOwner );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't create encryption contexts to protect the \"\n\t\t\t\t  \"private key\" ) );\n\t\t}\n\n\t/* Write the encrypted and MACd private key */\n\tinitPrivKeyParams( &privKeyParams, iGenericContext, iCryptContext, \n\t\t\t\t\t   iMacContext, privKeyAttributes, \n\t\t\t\t\t   privKeyAttributeSize, pkcCryptAlgo, modulusSize,\n\t\t\t\t\t   keyTypeTag );\n\tstatus = writePrivateKey( iPrivKeyContext, iCryptOwner, password, \n\t\t\t\t\t\t\t  passwordLength, &privKeyParams,\n\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyData,\n\t\t\t\t\t\t\t  pkcs15infoPtr->privKeyDataSize,\n\t\t\t\t\t\t\t  &newPrivKeyData, &newPrivKeyDataSize,\n\t\t\t\t\t\t\t  &newPrivKeyOffset, errorInfo );\n\tkrnlSendNotifier( iGenericContext, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( iMacContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( newPrivKeyData != NULL );\n\n\t/* Replace the old data with the newly-written data */\n\treplacePrivkeyData( pkcs15infoPtr, newPrivKeyData, \n\t\t\t\t\t\tnewPrivKeyDataSize, newPrivKeyOffset );\n\treturn( CRYPT_OK );\n\t}\n\n#else\t/* Old (pre-3.4.0) code to write the encrypted private key as\n\t\t   EnvelopedData rather than AuthEnv'd data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 6, 11 ) ) \\\nint pkcs15AddPrivateKey( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptOwner,\n\t\t\t\t\t\t IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t IN_LENGTH_NAME const int passwordLength,\n\t\t\t\t\t\t IN_BUFFER( privKeyAttributeSize ) \\\n\t\t\t\t\t\t\tconst void *privKeyAttributes, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int privKeyAttributeSize,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, \n\t\t\t\t\t\t IN_LENGTH_PKC const int modulusSize, \n\t\t\t\t\t\t const BOOLEAN isStorageObject, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iSessionKeyContext;\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tSTREAM stream;\n\tBYTE envelopeHeaderBuffer[ 256 + 8 ];\n\tvoid *newPrivKeyData = pkcs15infoPtr->privKeyData;\n\tint newPrivKeyDataSize, newPrivKeyOffset DUMMY_INIT;\n\tint privKeySize DUMMY_INIT, extraDataSize = 0;\n\tint keyTypeTag, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( ( isStorageObject && password == NULL && passwordLength == 0 ) || \\\n\t\t\t( !isStorageObject && isReadPtrDynamic( password, passwordLength ) ) );\n\tassert( isReadPtrDynamic( privKeyAttributes, privKeyAttributeSize ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( ( isStorageObject && password == NULL && \\\n\t\t\t\tpasswordLength == 0 ) || \\\n\t\t\t  ( !isStorageObject && password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isShortIntegerRangeNZ( privKeyAttributeSize ) );\n\tREQUIRES( isPkcAlgo( pkcCryptAlgo ) );\n\tREQUIRES( ( isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE_ECC && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( pkcCryptAlgo ) && \\\n\t\t\t\tmodulusSize >= MIN_PKCSIZE && \\\n\t\t\t\tmodulusSize <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isStorageObject == TRUE || isStorageObject == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Get the tag for encoding the key data */\n\tstatus = getKeyTypeTag( CRYPT_UNUSED, pkcCryptAlgo, &keyTypeTag );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If this is a dummy object (in other words object metadata) being \n\t   stored in a PKCS #15 object store then there's nothing present except\n\t   key attributes and a reference to the key held in external hardware,\n\t   in which case we use a simplified version if the code that follows */\n\tif( isStorageObject )\n\t\t{\n\t\tstatus = addPrivateKeyMetadata( pkcs15infoPtr, iCryptContext, \n\t\t\t\t\t\t\t\t\t\tprivKeyAttributes, privKeyAttributeSize,\n\t\t\t\t\t\t\t\t\t\tpkcCryptAlgo, modulusSize, keyTypeTag );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't write private key metadata\" ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Create a session key context and generate a key and IV into it.  The \n\t   IV would be generated automatically later on when we encrypt data for \n\t   the first time but we do it explicitly here to catch any possible \n\t   errors at a point where recovery is easier */\n\tstatus = createStrongEncryptionContext( &iSessionKeyContext, iCryptOwner );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendNotifier( iSessionKeyContext, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendNotifier( iSessionKeyContext, IMESSAGE_CTX_GENIV );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't create session key to wrap private key\" ) );\n\t\t}\n\n\t/* Calculate the eventual encrypted key size */\n\tsetMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, iCryptContext,\n\t\t\t\t\t\t  iSessionKeyContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );\n\tif( cryptStatusOK( status ) )\n\t\tprivKeySize = mechanismInfo.wrappedDataLength;\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tENSURES( privKeySize <= 256 + MAX_PRIVATE_KEYSIZE );\n\n\t/* Write the CMS envelope header for the wrapped private key except for \n\t   the outermost wrapper, which we have to defer writing until later \n\t   since we won't know the wrapped session key or inner CMS header size \n\t   until we've written them.  Since we're using KEKRecipientInfo we use \n\t   a version of 2 rather than 0 */\n\tsMemOpen( &stream, envelopeHeaderBuffer, 256 );\n\twriteShortInteger( &stream, 2, DEFAULT_TAG );\n\tstatus = writeWrappedSessionKey( &stream, iSessionKeyContext,\n\t\t\t\t\t\t\t\t\t iCryptOwner, password, passwordLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeCMSencrHeader( &stream, OID_CMS_DATA, \n\t\t\t\t\t\t\t\t\t sizeofOID( OID_CMS_DATA ), privKeySize,\n\t\t\t\t\t\t\t\t\t iSessionKeyContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write envelope header for wrapping private \"\n\t\t\t\t  \"key\" ) );\n\t\t}\n\tenvelopeHeaderSize = stell( &stream );\n\tenvelopeContentSize = envelopeHeaderSize + privKeySize;\n\tsMemDisconnect( &stream );\n\n\t/* Since we haven't been able to write the outer CMS envelope wrapper \n\t   yet we need to adjust the overall size for the additional level of\n\t   encapsulation */\n\tprivKeySize = sizeofShortObject( privKeySize + envelopeHeaderSize );\n\n\t/* Calculate the private-key storage size */\n#ifdef USE_RSA_EXTRAPARAM\n\tif( pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* RSA keys have an extra element for PKCS #11 compatibility */\n\t\textraDataSize = sizeofShortInteger( modulusSize );\n\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\tstatus = calculatePrivkeyStorage( pkcs15infoPtr, &newPrivKeyData,\n\t\t\t\t\t\t\t\t\t  &newPrivKeyDataSize, privKeySize, \n\t\t\t\t\t\t\t\t\t  privKeyAttributeSize, \n\t\t\t\t\t\t\t\t\t  extraDataSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\tsMemOpen( &stream, newPrivKeyData, newPrivKeyDataSize );\n\n\t/* Write the outer header and attributes */\n\twriteConstructed( &stream, privKeyAttributeSize + \\\n\t\t\t\t\t\t\t   sizeofObject( sizeofObject( privKeySize ) + \\\n\t\t\t\t\t\t\t\t\t\t\t extraDataSize ),\n\t\t\t\t\t  keyTypeTag );\n\tswrite( &stream, privKeyAttributes, privKeyAttributeSize );\n\twriteConstructed( &stream, sizeofObject( privKeySize + extraDataSize ), \n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\tstatus = writeSequence( &stream, privKeySize + extraDataSize );\n\tif( cryptStatusOK( status ) )\n\t\tnewPrivKeyOffset = stell( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\t\tif( newPrivKeyData != pkcs15infoPtr->privKeyData )\n\t\t\tclFree( \"addPrivateKey\", newPrivKeyData );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't write private key attributes\" ) );\n\t\t}\n\n\t/* Write the previously-encoded CMS envelope header and key exchange\n\t   information and follow it with the encrypted private key.  Since we\n\t   now know the size of the envelope header (which we couldn't write\n\t   earlier) we can add this now too */\n\twriteConstructed( &stream, envelopeContentSize, CTAG_OV_DIRECTPROTECTED );\n\tstatus = swrite( &stream, envelopeHeaderBuffer, envelopeHeaderSize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *dataPtr;\n\t\tint length;\n\n\t\tstatus = sMemGetDataBlockRemaining( &stream, &dataPtr, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = writeWrappedPrivateKey( dataPtr, length, &privKeySize, \n\t\t\t\t\t\t\t\t\t\t\t iCryptContext, iSessionKeyContext, \n\t\t\t\t\t\t\t\t\t\t\t pkcCryptAlgo );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( &stream, privKeySize, MAX_INTLENGTH_SHORT );\n#ifdef USE_RSA_EXTRAPARAM\n\tif( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* RSA keys have an extra element for PKCS #11 compability that we\n\t\t   need to kludge onto the end of the private-key data */\n\t\tstatus = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );\n\t\t}\n#endif /* USE_RSA_EXTRAPARAM */\n\tkrnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't wrap private key using session key\" ) );\n\t\t}\n\tassert( newPrivKeyDataSize == stell( &stream ) );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( newPrivKeyData, \n\t\t\t\t\t\t\t\t\t\t\t newPrivKeyDataSize ) ) );\n\n\t/* Replace the old data with the newly-written data */\n\treplacePrivkeyData( pkcs15infoPtr, newPrivKeyData, \n\t\t\t\t\t\tnewPrivKeyDataSize, newPrivKeyOffset );\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_atrd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #15 Attribute Read Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/* OID information used to read a PKCS #15 keyset */\n\nstatic const OID_INFO dataObjectOIDinfo[] = {\n\t{ OID_CRYPTLIB_CONTENTTYPE, TRUE },\n\t{ WILDCARD_OID, FALSE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\nstatic const OID_INFO cryptlibDataOIDinfo[] = {\n\t{ OID_CRYPTLIB_CONFIGDATA, CRYPT_IATTRIBUTE_CONFIGDATA },\n\t{ OID_CRYPTLIB_USERINDEX, CRYPT_IATTRIBUTE_USERINDEX },\n\t{ OID_CRYPTLIB_USERINFO, CRYPT_IATTRIBUTE_USERINFO },\n\t{ WILDCARD_OID, CRYPT_ATTRIBUTE_NONE },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* Permitted object subtypes.  PKCS #15 uses context-specific tagging to \n   identify the subtypes within an object type so we store a list of\n   permitted tags for each object type */\n\ntypedef struct {\n\tPKCS15_OBJECT_TYPE type;\t/* Object type */\n\tint subTypes[ 7 ];\t\t\t/* Subtype tags */\n\t} ALLOWED_ATTRIBUTE_TYPES;\n\nstatic const ALLOWED_ATTRIBUTE_TYPES allowedTypesTbl[] = {\n\t{ PKCS15_OBJECT_PUBKEY,\n\t  { BER_SEQUENCE, MAKE_CTAG( CTAG_PK_ECC ), MAKE_CTAG( CTAG_PK_DH ), \n\t    MAKE_CTAG( CTAG_PK_DSA ), \n\t\tCRYPT_ERROR, CRYPT_ERROR } },\n\t{ PKCS15_OBJECT_PRIVKEY,\n\t  { BER_SEQUENCE, MAKE_CTAG( CTAG_PK_ECC ), MAKE_CTAG( CTAG_PK_DH ), \n\t    MAKE_CTAG( CTAG_PK_DSA ), \n\t\tCRYPT_ERROR, CRYPT_ERROR } },\n\t{ PKCS15_OBJECT_CERT,\n\t  { BER_SEQUENCE, CRYPT_ERROR, CRYPT_ERROR } },\n\t{ PKCS15_OBJECT_SECRETKEY,\n\t  { CRYPT_ERROR, CRYPT_ERROR } },\n\t{ PKCS15_OBJECT_DATA, \n\t  { MAKE_CTAG( CTAG_DO_OIDDO ), CRYPT_ERROR, CRYPT_ERROR } },\n\t{ PKCS15_OBJECT_NONE, { CRYPT_ERROR, CRYPT_ERROR } },\n\t\t{ PKCS15_OBJECT_NONE, { CRYPT_ERROR, CRYPT_ERROR } }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a sequence of PKCS #15 key identifiers */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readKeyIdentifiers( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t   IN_LENGTH const int endPos )\n\t{\n\tint identifierCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\t\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\n\tLOOP_MED( ( status = CRYPT_OK, identifierCount = 0 ),\n\t\t\t  cryptStatusOK( status ) && stell( stream ) < endPos && \\\n\t\t\t\tidentifierCount < 32, identifierCount++ )\n\t\t{\n\t\tlong value;\n\t\tint payloadLength;\n\n\t\t/* Read each identifier type and copy the useful ones into the PKCS\n\t\t   #15 information */\n\t\treadSequence( stream, &payloadLength );\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tswitch( value )\n\t\t\t{\n\t\t\tcase PKCS15_KEYID_ISSUERANDSERIALNUMBER:\n\t\t\t\t{\n\t\t\t\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\t\t\t\tvoid *iAndSPtr DUMMY_INIT_PTR;\n\t\t\t\tint iAndSLength, hashSize;\n\n\t\t\t\t/* If we've already got the iAndSID, use that version \n\t\t\t\t   instead */\n\t\t\t\tif( pkcs15infoPtr->iAndSIDlength > 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = readUniversal( stream );\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t/* Hash the full issuerAndSerialNumber to get an iAndSID */\n\t\t\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0,\n\t\t\t\t\t\t\t\t\t\t &hashFunctionAtomic, &hashSize );\n\t\t\t\tstatus = getStreamObjectLength( stream, &iAndSLength );\n\t\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t\t!isShortIntegerRangeNZ( iAndSLength ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = sMemGetDataBlock( stream, &iAndSPtr, \n\t\t\t\t\t\t\t\t\t\t\t   iAndSLength );\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = sSkip( stream, iAndSLength, \n\t\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\thashFunctionAtomic( pkcs15infoPtr->iAndSID, KEYID_SIZE, \n\t\t\t\t\t\t\t\t\tiAndSPtr, iAndSLength );\n\t\t\t\tpkcs15infoPtr->iAndSIDlength = hashSize;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase PKCS15_KEYID_SUBJECTKEYIDENTIFIER:\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->keyID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->keyIDlength, \n\t\t\t\t\t\t\t\t\t\t  8, CRYPT_MAX_HASHSIZE );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH:\n\t\t\t\t/* If we've already got the iAndSID by hashing the\n\t\t\t\t   issuerAndSerialNumber, use that version instead */\n\t\t\t\tif( pkcs15infoPtr->iAndSIDlength > 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = readUniversal( stream );\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->iAndSID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->iAndSIDlength, \n\t\t\t\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_KEYID_ISSUERNAMEHASH:\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->issuerNameID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->issuerNameIDlength, \n\t\t\t\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_KEYID_SUBJECTNAMEHASH:\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->subjectNameID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->subjectNameIDlength, \n\t\t\t\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_KEYID_PGP2:\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->pgp2KeyID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->pgp2KeyIDlength, \n\t\t\t\t\t\t\t\t\t\t  PGP_KEYID_SIZE, PGP_KEYID_SIZE );\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_KEYID_OPENPGP:\n\t\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->openPGPKeyID,\n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->openPGPKeyIDlength, \n\t\t\t\t\t\t\t\t\t\t  PGP_KEYID_SIZE, PGP_KEYID_SIZE );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( identifierCount >= 32 )\n\t\t{\n\t\t/* This could be either an internal error or some seriously \n\t\t   malformed data, since we can't tell without human intervention\n\t\t   we throw a debug exception but otherwise treat it as bad data */\n\t\tDEBUG_DIAG(( \"Encountered more than %d key IDs\", \n\t\t\t\t\t FAILSAFE_ITERATIONS_MED ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead PKCS #15 Attributes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read public/private key attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPubkeyAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t\t IN_LENGTH const int endPos, \n\t\t\t\t\t\t\t\t const BOOLEAN isPubKeyObject )\n\t{\n\tint usageFlags, tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\tREQUIRES( isPubKeyObject == TRUE || isPubKeyObject == FALSE );\n\n\tstatus = readBitString( stream, &usageFlags );\t\t\t/* Usage flags */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_BOOLEAN )\t\t\t\t\t\t\t\t/* Native flag */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_BITSTRING )\t\t\t\t\t\t\t\t/* Access flags */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_INTEGER )\t\t\t\t\t\t\t\t/* Key reference */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_TIME_GENERALIZED )\t\t\t\t\t\t/* Start date */\n\t\t{\n\t\tstatus = readGeneralizedTime( stream, &pkcs15infoPtr->validFrom );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_KA_VALIDTO ) )\t\t\t\t/* End date */\n\t\t{\n\t\tstatus = readGeneralizedTimeTag( stream, &pkcs15infoPtr->validTo, \n\t\t\t\t\t\t\t\t\t\t CTAG_KA_VALIDTO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isPubKeyObject )\n\t\tpkcs15infoPtr->pubKeyUsage = usageFlags;\n\telse\n\t\tpkcs15infoPtr->privKeyUsage = usageFlags;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read certificate attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCertAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t   IN_LENGTH const int endPos )\n\t{\n\tint tag, length, status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_BOOLEAN )\t\t\t\t\t\t\t\t/* Authority flag */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_SEQUENCE )\t\t\t\t\t\t\t\t/* Identifier */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CA_DUMMY ) )\t\t\t\t\t/* Thumbprint */\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CA_TRUSTED_USAGE ) )\t\t\t/* Trusted usage */\n\t\t{\n\t\treadConstructed( stream, NULL, CTAG_CA_TRUSTED_USAGE );\n\t\tstatus = readBitString( stream, &pkcs15infoPtr->trustedUsage );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CA_IDENTIFIERS ) )\t\t\t/* Identifiers */\n\t\t{\n\t\tstatus = readConstructed( stream, &length, CTAG_CA_IDENTIFIERS );\n\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t{\n\t\t\tstatus = readKeyIdentifiers( stream, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t\t\t stell( stream ) + length );\n\t\t\t}\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) )\n\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\t/* Implicitly trusted */\n\t\tstatus = readBooleanTag( stream, &pkcs15infoPtr->implicitTrust,\n\t\t\t\t\t\t\t\t CTAG_CA_TRUSTED_IMPLICIT );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_CA_VALIDTO ) )\t\t\t\t/* Validity */\n\t\t{\n\t\t/* Due to miscommunication between PKCS #15 and 7816-15 there are \n\t\t   two ways to encode the validity information for certificates, one \n\t\t   based on the format used elsewhere in PKCS #15 (for PKCS #15) and \n\t\t   the other based on the format used in certificates (for 7816-15).  \n\t\t   Luckily they can be distinguished by the tagging type */\n\t\treadConstructed( stream, NULL, CTAG_CA_VALIDTO );\n\t\treadUTCTime( stream, &pkcs15infoPtr->validFrom );\n\t\tstatus = readUTCTime( stream, &pkcs15infoPtr->validTo );\n\t\t}\n\telse\n\t\t{\n\t\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\t\ttag == BER_TIME_GENERALIZED )\t\t\t\t\t/* Start date */\n\t\t\t{\n\t\t\tstatus = readGeneralizedTime( stream, \n\t\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->validFrom );\n\t\t\t}\n\t\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\t\ttag == MAKE_CTAG_PRIMITIVE( CTAG_CA_VALIDTO ) )\t/* End date */\n\t\t\t{\n\t\t\tstatus = readGeneralizedTimeTag( stream, &pkcs15infoPtr->validTo,\n\t\t\t\t\t\t\t\t\t\t\t CTAG_CA_VALIDTO );\n\t\t\t}\n\t\t}\n\n\treturn( cryptStatusError( status ) ? status : CRYPT_OK );\n\t}\t\t/* checkStatusLimitsPeekTag() can return tag as status */\n\n/* Read an object's attributes */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readClassAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tINOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t\tIN_ENUM( PKCS15_OBJECT ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS15_OBJECT_TYPE type )\n\t{\n\tBOOLEAN isCryptlibObject = FALSE;\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\n\t/* Read the attribute wrapper.  Since there may be no attributes present,\n\t   we use readSequenceZ() */\n\tstatus = readSequenceZ( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\t/* Secret-key objects have no attributes of interest, data objects \n\t\t   have only optional attributes, so a zero length is OK */\n\t\tif( type == PKCS15_OBJECT_SECRETKEY || type == PKCS15_OBJECT_DATA )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* For anything else, a zero length is an error */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tendPos = stell( stream ) + length;\n\n\t/* Process per-object-type attributes */\n\tswitch( type )\n\t\t{\n\t\tcase PKCS15_OBJECT_PUBKEY:\n\t\tcase PKCS15_OBJECT_PRIVKEY:\n\t\t\t/* It's a public/private-key object, read the ID and assorted \n\t\t\t   flags */\n\t\t\tif( length < sizeofObject( MIN_NAME_LENGTH ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->iD,\n\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->iDlength, \n\t\t\t\t\t\t\t\t\t  MIN_NAME_LENGTH, CRYPT_MAX_HASHSIZE );\n\t\t\tif( cryptStatusOK( status ) && stell( stream ) < endPos )\n\t\t\t\t{\n\t\t\t\tstatus = readPubkeyAttributes( stream, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t\t\t\tendPos,\n\t\t\t\t\t\t\t\t\t\t\t( type == PKCS15_OBJECT_PUBKEY ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_CERT:\n\t\t\t/* It's a certificate object, read the ID and assorted flags */\n\t\t\tif( length < sizeofObject( MIN_NAME_LENGTH ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tstatus = readOctetString( stream, pkcs15infoPtr->iD,\n\t\t\t\t\t\t\t\t\t  &pkcs15infoPtr->iDlength, \n\t\t\t\t\t\t\t\t\t  MIN_NAME_LENGTH, CRYPT_MAX_HASHSIZE );\n\t\t\tif( cryptStatusOK( status ) && stell( stream ) < endPos )\n\t\t\t\t{\n\t\t\t\tstatus = readCertAttributes( stream, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t\t\t\t endPos );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_SECRETKEY:\n\t\t\t/* It's a secret-key object, there are no attributes of interest \n\t\t\t   present */\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_DATA:\n\t\t\t/* If it's a cryptlib data object then it'll be identified via \n\t\t\t   the cryptlib OID */\n\t\t\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\t\ttag == BER_STRING_UTF8 )\n\t\t\t\t{\n\t\t\t\t/* Skip application name */\n\t\t\t\tstatus = readUniversal( stream );\n\t\t\t\t}\n\t\t\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\t\t\ttag == BER_OBJECT_IDENTIFIER )\n\t\t\t\t{\n\t\t\t\tint value;\n\n\t\t\t\tstatus = readOID( stream, dataObjectOIDinfo, \n\t\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( dataObjectOIDinfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t  OID_INFO ), &value );\n\t\t\t\tif( cryptStatusOK( status ) && value == TRUE )\n\t\t\t\t\tisCryptlibObject = TRUE;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_UNRECOGNISED:\n\t\t\t/* It's an unrecognised object type, we don't know what to do \n\t\t\t   with any attributes that may be present */\n\t\t\tbreak;\n\t\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip any additional attribute information that may be present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = sseek( stream, endPos );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( isCryptlibObject ? OK_SPECIAL : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSubclassAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t\t   IN_ENUM( PKCS15_OBJECT ) \\\n\t\t\t\t\t\t\t\t\t\tconst PKCS15_OBJECT_TYPE type )\n\t{\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\n\t/* Read the attribute wrapper */\n\treadConstructed( stream, NULL, CTAG_OB_SUBCLASSATTR );\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tswitch( type )\n\t\t{\n\t\tcase PKCS15_OBJECT_PRIVKEY:\n\t\t\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\t\ttag == BER_SEQUENCE )\t\t\t\t\t\t/* Name */\n\t\t\t\t{\n\t\t\t\tstatus = readUniversal( stream );\n\t\t\t\t}\n\t\t\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\t\t\ttag == MAKE_CTAG( CTAG_PK_IDENTIFIERS ) )\t/* KeyIDs */\n\t\t\t\t{\n\t\t\t\tstatus = readConstructed( stream, &length, \n\t\t\t\t\t\t\t\t\t\t  CTAG_PK_IDENTIFIERS );\n\t\t\t\tif( cryptStatusOK( status ) && length > 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = readKeyIdentifiers( stream, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t stell( stream ) + length );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_PUBKEY:\n\t\tcase PKCS15_OBJECT_CERT:\n\t\tcase PKCS15_OBJECT_SECRETKEY:\n\t\tcase PKCS15_OBJECT_DATA:\n\t\t\t/* These object types don't have subclass attributes */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_UNRECOGNISED:\n\t\t\t/* It's an unrecognised object type, we don't know what to do \n\t\t\t   with any attributes that may be present */\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip any additional attribute information that may be present */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = sseek( stream, endPos );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readTypeAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t   IN_ENUM( PKCS15_OBJECT ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS15_OBJECT_TYPE type,\n\t\t\t\t\t\t\t   const BOOLEAN unrecognisedAttribute,\n\t\t\t\t\t\t\t   const BOOLEAN isCryptlibData )\n\t{\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\tREQUIRES( unrecognisedAttribute == TRUE || unrecognisedAttribute == FALSE );\n\tREQUIRES( isCryptlibData == TRUE || isCryptlibData == FALSE );\n\n\t/* Read the attribute wrapper */\t\n\treadConstructed( stream, NULL, CTAG_OB_TYPEATTR );\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tif( unrecognisedAttribute )\n\t\t{\n\t\t/* It's a non-recognised object subtype, skip it */\n\t\treturn( ( stell( stream ) < endPos ) ? \\\n\t\t\t\tsseek( stream, endPos ) : CRYPT_OK );\n\t\t}\n\n\t/* Parameterised types have special tagging requirements when using \n\t   context-specific tags and the declaration is a \"Tag Type\" (for \n\t   example for the \"direct\" choice for the ObjectValue type) and the \n\t   \"Type\" in the \"Tag Type\" is a \"DummyReference\".  In this case the \n\t   context tag is encoded as an EXPLICIT rather than IMPLCIIT tag (see \n\t   section F.2 of PKCS #15 v1.2 and newer).  The only case where this \n\t   occurs is for the ObjectValue.direct option.\n\t\t   \n\t   This is complicated by the fact that versions of PKCS #15 before v1.2 \n\t   erroneously stated that all context-specific tags in parameterised \n\t   types should use EXPLICIT tagging, however no (known) implementation \n\t   ever did this.\n\t\t   \n\t   What this double error means is that existing implementations get \n\t   things almost right, the exception being ObjectValue.direct, which \n\t   does require an EXPLICIT tag.  To deal with this, we check for the \n\t   presence of the optional tag and skip it if it's present */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_OV_DIRECT ) )\n\t\t{\n\t\tstatus = readConstructed( stream, &length, CTAG_OV_DIRECT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the payload data, which just consists of remembering where the \n\t   payload starts */\n\tswitch( type )\n\t\t{\n\t\tcase PKCS15_OBJECT_PUBKEY:\n\t\t\tpkcs15infoPtr->pubKeyOffset = stell( stream );\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_PRIVKEY:\n\t\t\tpkcs15infoPtr->privKeyOffset = stell( stream );\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_CERT:\n\t\t\tpkcs15infoPtr->certOffset = stell( stream );\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_SECRETKEY:\n\t\t\tpkcs15infoPtr->secretKeyOffset = stell( stream );\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_DATA:\n\t\t\t{\n\t\t\tint value;\n\n\t\t\t/* If it's not cryptlib data, we can't do much with it */\n\t\t\tif( !isCryptlibData )\n\t\t\t\tbreak;\n\n\t\t\t/* It's a cryptlib data object, extract the contents */\n\t\t\tstatus = readOID( stream, cryptlibDataOIDinfo, \n\t\t\t\t\t\t\t  FAILSAFE_ARRAYSIZE( cryptlibDataOIDinfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  OID_INFO ), \n\t\t\t\t\t\t\t  &value );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( value == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t\tvalue == CRYPT_IATTRIBUTE_USERINDEX )\n\t\t\t\t{\n\t\t\t\t/* The configuration data and user index are SEQUENCEs of \n\t\t\t\t   objects */\n\t\t\t\tstatus = readSequence( stream, NULL );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tif( value == CRYPT_ATTRIBUTE_NONE )\n\t\t\t\t{\n\t\t\t\t/* It's a non-recognised cryptlib data subtype, skip it */\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tpkcs15infoPtr->dataOffset = stell( stream );\n\t\t\tpkcs15infoPtr->dataType = value;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip the data payload */\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = sseek( stream, endPos );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readObjectAttributes( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t  IN_ENUM( PKCS15_OBJECT ) \\\n\t\t\t\t\t\t\t\tconst PKCS15_OBJECT_TYPE type, \n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst ALLOWED_ATTRIBUTE_TYPES *allowedTypeInfo;\n\tBOOLEAN skipDataRead = TRUE, isCryptlibData = FALSE;\n\tint tag, length, outerLength, lastTag = CRYPT_ERROR, i;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear the return value */\n\tmemset( pkcs15infoPtr, 0, sizeof( PKCS15_INFO ) );\n\n\t/* Find the allowed-subtype information for this object type */\n\tLOOP_SMALL( i = 0,\n\t\t\t\tallowedTypesTbl[ i ].type != type && \\\n\t\t\t\t\tallowedTypesTbl[ i ].type != PKCS15_OBJECT_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( allowedTypesTbl, \\\n\t\t\t\t\t\t\t\t\t\t\tALLOWED_ATTRIBUTE_TYPES ), \n\t\t\t\ti++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( allowedTypesTbl, ALLOWED_ATTRIBUTE_TYPES ) );\n\tallowedTypeInfo = &allowedTypesTbl[ i ];\n\n\t/* Make sure that this is a subtype that we can handle */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readGenericHole( stream, &outerLength, MIN_OBJECT_SIZE, \n\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_MED( i = 0, allowedTypeInfo->subTypes[ i ] != CRYPT_ERROR, i++ )\n\t\t{\n\t\t/* If this is a recognised subtype, process the attribute data */\n\t\tif( allowedTypeInfo->subTypes[ i ] == tag )\n\t\t\t{\n\t\t\tskipDataRead = FALSE;\n\t\t\tbreak;\n\t\t\t}\n\t\tlastTag = allowedTypeInfo->subTypes[ i ];\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If this is an unrecognised subtype, make sure that it's at least \n\t   vaguely valid.  Tags are in the range { BER_SEQUENCE, [0]...[n] }, \n\t   we interpret \"vaguely valid\" to mean within a short distance of the \n\t   last tag [n] that we recognise as valid */\n\tif( skipDataRead && ( tag != BER_SEQUENCE ) && \\\n\t\t( tag < MAKE_CTAG( 0 ) || tag > lastTag + 10 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Process the PKCS15CommonObjectAttributes.  These may have zero length \n\t   so we use readSequenceZ() */\n\tstatus = readSequenceZ( stream, &length );\n\tif( cryptStatusOK( status ) && length > 0 )\n\t\t{\n\t\tconst int endPos = stell( stream ) + length;\n\n\t\t/* Read the label if it's present and skip anything else */\n\t\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\t\ttag == BER_STRING_UTF8 )\n\t\t\t{\n\t\t\tstatus = readCharacterString( stream,\n\t\t\t\t\t\tpkcs15infoPtr->label, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t&pkcs15infoPtr->labelLength, BER_STRING_UTF8 );\n\t\t\t}\n\t\tif( !cryptStatusError( status ) && stell( stream ) < endPos )\n\t\t\tstatus = sseek( stream, endPos );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #15 common object attributes\" ) );\n\t\t}\n\n\t/* Process the class attributes */\n\tstatus = readClassAttributes( stream, pkcs15infoPtr, type );\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #15 %s attributes\",\n\t\t\t\t  ( type == PKCS15_OBJECT_PUBKEY ) ? \"public key\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_PRIVKEY ) ? \"private key\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_CERT ) ? \"certificate\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_DATA ) ? \"data object\" : \\\n\t\t\t\t\t\t\t\t\t\t\t\t   \"class\" ) );\n\t\t}\n\tif( status == OK_SPECIAL )\n\t\tisCryptlibData = TRUE;\n\n\t/* We have to have at least an ID present for any standard object \n\t   types */\n\tENSURES( ( type == PKCS15_OBJECT_SECRETKEY || \\\n\t\t\t   type == PKCS15_OBJECT_DATA || \\\n\t\t\t   type == PKCS15_OBJECT_UNRECOGNISED ) || \\\n\t\t\t pkcs15infoPtr->iDlength > 0 );\n\n\t/* If there's no keyID present then we use the iD as the keyID */\n\tif( pkcs15infoPtr->keyIDlength <= 0 && pkcs15infoPtr->iDlength > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( pkcs15infoPtr->iDlength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( pkcs15infoPtr->keyID, pkcs15infoPtr->iD, \n\t\t\t\tpkcs15infoPtr->iDlength );\n\t\tpkcs15infoPtr->keyIDlength = pkcs15infoPtr->iDlength;\n\t\t}\n\n\t/* Skip the subclass attributes if present */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_OB_SUBCLASSATTR ) )\n\t\t{\n\t\tstatus = readSubclassAttributes( stream, pkcs15infoPtr, type );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid PKCS #15 %s attributes\",\n\t\t\t\t\t  ( type == PKCS15_OBJECT_PRIVKEY ) ? \"private key\" : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  \"subclass\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Process the type attributes */\n\tstatus = readTypeAttributes( stream, pkcs15infoPtr, type, \n\t\t\t\t\t\t\t\t skipDataRead, isCryptlibData );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid PKCS #15 %s payload data\",\n\t\t\t\t  ( type == PKCS15_OBJECT_PUBKEY ) ? \"public key\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_PRIVKEY ) ? \"private key\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_CERT ) ? \"certificate\" : \\\n\t\t\t\t  ( type == PKCS15_OBJECT_DATA ) ? \"data object\" : \\\n\t\t\t\t\t\t\t\t\t\t\t\t   \"class\" ) );\n\t\t}\n\n\treturn( skipDataRead ? OK_SPECIAL : CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_atwr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #15 Attribute Write Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get assorted ID information from a context or certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getKeyIDs( INOUT PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCryptContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE sKIDbuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Get various pieces of information from the object.  The information\n\t   may already have been set up earlier on so we only set it if this is\n\t   a newly-added key.  We use a guard for the existence of both a label\n\t   and an ID since there may be a pre-set user ID (which isn't the same\n\t   as the key ID) present for implicitly created keys in user keysets */\n\tif( pkcs15infoPtr->labelLength <= 0 )\n\t\t{\n\t\tsetMessageData( &msgData, pkcs15infoPtr->label, CRYPT_MAX_TEXTSIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpkcs15infoPtr->labelLength = msgData.length;\n\t\tsetMessageData( &msgData, pkcs15infoPtr->keyID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpkcs15infoPtr->keyIDlength = msgData.length;\n\t\t}\n\tif( pkcs15infoPtr->iDlength <= 0 && pkcs15infoPtr->keyIDlength > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( pkcs15infoPtr->keyIDlength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( pkcs15infoPtr->iD, pkcs15infoPtr->keyID, \n\t\t\t\tpkcs15infoPtr->keyIDlength );\n\t\tpkcs15infoPtr->iDlength = pkcs15infoPtr->keyIDlength;\n\t\t}\n\tif( pkcs15infoPtr->pgp2KeyIDlength <= 0 )\n\t\t{\n\t\tsetMessageData( &msgData, pkcs15infoPtr->pgp2KeyID, PGP_KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_PGP2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* Not present for all key types so an error isn't fatal */\n\t\t\tpkcs15infoPtr->pgp2KeyIDlength = msgData.length;\n\t\t\t}\n\t\t}\n\tif( pkcs15infoPtr->openPGPKeyIDlength <= 0 )\n\t\t{\n\t\tsetMessageData( &msgData, pkcs15infoPtr->openPGPKeyID, PGP_KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* Not present for all key types so an error isn't fatal */\n\t\t\tpkcs15infoPtr->openPGPKeyIDlength = msgData.length;\n\t\t\t}\n\t\t}\n\n\t/* The subjectKeyIdentifier, if present, may not be the same as the \n\t   keyID if the certificate that it's in has come from a CA that does \n\t   strange things with the sKID so we try and read this value and if \n\t   it's present override the implicit sKID (== keyID) value with the \n\t   actual sKID */\n\tsetMessageData( &msgData, sKIDbuffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tREQUIRES( rangeCheck( msgData.length, 1, CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( pkcs15infoPtr->keyID, sKIDbuffer, msgData.length );\n\t\tpkcs15infoPtr->keyIDlength = msgData.length;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 5 ) ) \\\nstatic int getCertIDs( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iCryptCert, \n\t\t\t\t\t   OUT BOOLEAN *isCA, \n\t\t\t\t\t   OUT BOOLEAN *trustedImplicit, \n\t\t\t\t\t   OUT int *trustedUsage )\n\t{\n\tint value, status;\n\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( isCA, sizeof( BOOLEAN ) ) );\n\tassert( isWritePtr( trustedImplicit, sizeof( BOOLEAN ) ) );\n\tassert( isWritePtr( trustedUsage, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* Clear return values */\n\t*isCA = *trustedImplicit = FALSE;\n\t*trustedUsage = CRYPT_UNUSED;\n\n\t/* Get various pieces of status information from the certificate */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CA );\n\tif( cryptStatusOK( status ) )\n\t\t*isCA = value;\t/* BOOLEAN vs. int */\n\telse\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t*isCA = FALSE;\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  trustedUsage, CRYPT_CERTINFO_TRUSTED_USAGE );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* If there's no trusted usage defined, don't store a trust\n\t\t\t   setting */\n\t\t\t*trustedUsage = CRYPT_UNUSED;\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_TRUSTED_IMPLICIT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*trustedImplicit = value;\t/* BOOLEAN vs. int */\n\t\telse\n\t\t\t{\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\t/* If it's not implicitly trusted, don't store a trust setting */\n\t\t\t\t*trustedImplicit = FALSE;\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getValidityInfo( pkcs15infoPtr, iCryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're adding a standalone certificate then the iD and keyID won't \n\t   have been set up yet so we need to set these up as well.  Since the \n\t   certificate could be a data-only one we create the iD ourselves from \n\t   the encoded public key components rather than trying to read an \n\t   associated context's keyID attribute.  For similar reasons we \n\t   specifically don't try and read the PGP ID information since for a \n\t   certificate chain it'll come from the context of the leaf certificate \n\t   rather than the current certificate (in any case they're not \n\t   necessary since none of the certificates in the chain will be PGP \n\t   keys) */\n\tif( pkcs15infoPtr->iDlength <= 0 )\n\t\t{\n\t\tstatus = getCertID( iCryptCert, CRYPT_IATTRIBUTE_SPKI,\n\t\t\t\t\t\t\tpkcs15infoPtr->iD, KEYID_SIZE, \n\t\t\t\t\t\t\t&pkcs15infoPtr->iDlength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( pkcs15infoPtr->keyIDlength <= 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, pkcs15infoPtr->keyID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tpkcs15infoPtr->keyIDlength = msgData.length;\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( pkcs15infoPtr->iDlength, 1, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\t\tmemcpy( pkcs15infoPtr->keyID, pkcs15infoPtr->iD, \n\t\t\t\t\tpkcs15infoPtr->iDlength );\n\t\t\tpkcs15infoPtr->keyIDlength = pkcs15infoPtr->iDlength;\n\t\t\t}\n\t\t}\n\n\t/* Get the various other IDs for the certificate */\n\tstatus = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,\n\t\t\t\t\t\tpkcs15infoPtr->iAndSID, KEYID_SIZE,\n\t\t\t\t\t\t&pkcs15infoPtr->iAndSIDlength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getCertID( iCryptCert, CRYPT_IATTRIBUTE_SUBJECT,\n\t\t\t\t\t\t\tpkcs15infoPtr->subjectNameID, KEYID_SIZE,\n\t\t\t\t\t\t\t&pkcs15infoPtr->subjectNameIDlength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUER,\n\t\t\t\t\t\t\tpkcs15infoPtr->issuerNameID, KEYID_SIZE,\n\t\t\t\t\t\t\t&pkcs15infoPtr->issuerNameIDlength );\n\treturn( status );\n\t}\n\n/* Get the PKCS #15 key usage flags for a context */\n\nCHECK_RETVAL_RANGE( PKCS15_USAGE_FLAG_NONE, PKCS15_USAGE_FLAG_MAX ) \\\nstatic int getKeyUsageFlags( IN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\t\t IN_FLAGS( PKCS15_USAGE ) const int privKeyUsage )\n\t{\n\tMESSAGE_DATA msgData;\n\tint keyUsage = PKCS15_USAGE_FLAG_NONE, value, status;\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isFlagRangeZ( privKeyUsage, PKCS15_USAGE ) );\n\n\t/* There's one special-case situation in which there won't be any usage\n\t   information available and that's when we've been passed a dummy \n\t   context that's used to contain key metadata for a crypto device.  If \n\t   this is the case, we allow any usage that the algorithm allows, it's\n\t   up to the device (which we don't have any control over) to set more \n\t   specific restrictions */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint pkcAlgo;\n\t\t\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &pkcAlgo, CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tswitch( pkcAlgo )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_DH:\n\t\t\t\treturn( PKCS15_USAGE_DERIVE );\n\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\treturn( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_DECRYPT | \\\n\t\t\t\t\t\tPKCS15_USAGE_SIGN | PKCS15_USAGE_VERIFY );\n\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\treturn( PKCS15_USAGE_SIGN | PKCS15_USAGE_VERIFY );\n\n\t\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\t\treturn( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_DECRYPT );\n\t\t\t}\n\t\tretIntError();\n\t\t}\n\n\t/* Obtaining the usage flags gets a bit complicated because they're a \n\t   mixture of parts of X.509 and PKCS #11 flags (and the X.509 -> PKCS \n\t   #15 mapping isn't perfect, see for example key agreement) so we have \n\t   to build them up from bits and pieces pulled in from all over the \n\t   place */\n\tif( checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\tkeyUsage = PKCS15_USAGE_ENCRYPT;\n\tif( checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_DECRYPT ) )\n\t\tkeyUsage |= PKCS15_USAGE_DECRYPT;\n\tif( checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_SIGN ) || \\\n\t\tcheckContextCapability( iCryptContext, MESSAGE_CHECK_PKC_SIGN_CA ) )\n\t\tkeyUsage |= PKCS15_USAGE_SIGN;\n\tif( checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_SIGCHECK ) || \\\n\t\tcheckContextCapability( iCryptContext, MESSAGE_CHECK_PKC_SIGCHECK_CA ) )\n\t\tkeyUsage |= PKCS15_USAGE_VERIFY;\n\tif( checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_KA_EXPORT ) || \\\n\t\tcheckContextCapability( iCryptContext, MESSAGE_CHECK_PKC_KA_IMPORT ) )\n\t\tkeyUsage |= PKCS15_USAGE_DERIVE;\t/* I don't think so Tim */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\tif( cryptStatusOK( status ) && \\\n\t\t( value & CRYPT_KEYUSAGE_NONREPUDIATION ) )\n\t\t{\n\t\t/* This may be a raw key or a certificate with no keyUsage present \n\t\t   so a failure to read the usage attribute isn't a problem */\n\t\tkeyUsage |= PKCS15_USAGE_NONREPUDIATION;\n\t\t}\n\n\t/* If the key ends up being unusable, tell the caller */\n\tif( keyUsage <= PKCS15_USAGE_FLAG_NONE )\n\t\treturn( PKCS15_USAGE_FLAG_NONE );\n\n\t/* If this is a public-key object which is updating a private-key one\n\t   then the only key usages that we'll have found are public-key ones.  \n\t   To ensure that we don't disable use of the private-key object we copy \n\t   across private-key usages where corresponding public-key ones are \n\t   enabled.  This is used, for example, when updating an unrestricted-\n\t   usage raw private key with a restricted-usage public key, e.g. from a\n\t   certificate */\n\tif( !checkContextCapability( iCryptContext, MESSAGE_CHECK_PKC_PRIVATE ) )\n\t\t{\n\t\tif( keyUsage & PKCS15_USAGE_ENCRYPT )\n\t\t\tkeyUsage |= privKeyUsage & PKCS15_USAGE_DECRYPT;\n\t\tif( keyUsage & PKCS15_USAGE_VERIFY )\n\t\t\tkeyUsage |= privKeyUsage & PKCS15_USAGE_SIGN;\n\t\t}\n\n\treturn( keyUsage );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite PKCS #15 Attributes\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write PKCS #15 identifier values */\n\nCHECK_RETVAL_RANGE_NOERROR( 1, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sizeofObjectIDs( const PKCS15_INFO *pkcs15infoPtr )\n\t{\n\tint identifierSize;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tidentifierSize = \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->keyIDlength ) );\n\tif( pkcs15infoPtr->iAndSIDlength > 0 )\n\t\t{\n\t\tidentifierSize += \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->iAndSIDlength ) );\n\t\t}\n\tif( pkcs15infoPtr->issuerNameIDlength > 0 )\n\t\t{\n\t\tidentifierSize += \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->issuerNameIDlength ) );\n\t\t}\n\tif( pkcs15infoPtr->subjectNameIDlength > 0 )\n\t\t{\n\t\tidentifierSize += \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_SUBJECTNAMEHASH ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->subjectNameIDlength ) );\n\t\t}\n\tif( pkcs15infoPtr->pgp2KeyIDlength > 0 )\n\t\t{\n\t\tidentifierSize += \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_PGP2 ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->pgp2KeyIDlength ) );\n\t\t}\n\tif( pkcs15infoPtr->openPGPKeyIDlength > 0 )\n\t\t{\n\t\tidentifierSize += \\\n\t\t\tsizeofShortObject( \\\n\t\t\t\tsizeofShortInteger( PKCS15_KEYID_OPENPGP ) + \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->openPGPKeyIDlength ) );\n\t\t}\n\n\treturn( identifierSize );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeObjectIDs( INOUT STREAM *stream, \n\t\t\t\t\t\t   const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_OBJECT_SIZE ) const int length, \n\t\t\t\t\t\t   IN_TAG const int tag )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\t\n\tREQUIRES( length >= MIN_OBJECT_SIZE && length < MAX_INTLENGTH_SHORT );\n\tREQUIRES( tag >= 0 && tag < MAX_TAG_VALUE );\n\n\twriteConstructed( stream, length, tag );\n\twriteSequence( stream,\n\t\t\t\t   sizeofShortInteger( PKCS15_KEYID_SUBJECTKEYIDENTIFIER ) + \\\n\t\t\t\t   sizeofShortObject( pkcs15infoPtr->keyIDlength ) );\n\twriteShortInteger( stream, PKCS15_KEYID_SUBJECTKEYIDENTIFIER,\n\t\t\t\t\t   DEFAULT_TAG );\n\tstatus = writeOctetString( stream, pkcs15infoPtr->keyID,\n\t\t\t\t\t\t\t   pkcs15infoPtr->keyIDlength, DEFAULT_TAG );\n\tif( pkcs15infoPtr->iAndSIDlength > 0 )\n\t\t{\n\t\twriteSequence( stream,\n\t\t\t\t\t   sizeofShortInteger( PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH ) + \\\n\t\t\t\t\t   sizeofShortObject( pkcs15infoPtr->iAndSIDlength ) );\n\t\twriteShortInteger( stream, PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH,\n\t\t\t\t\t\t   DEFAULT_TAG );\n\t\tstatus = writeOctetString( stream, pkcs15infoPtr->iAndSID,\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->iAndSIDlength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( pkcs15infoPtr->issuerNameIDlength > 0 )\n\t\t{\n\t\twriteSequence( stream,\n\t\t\t\t\t   sizeofShortInteger( PKCS15_KEYID_ISSUERNAMEHASH ) + \\\n\t\t\t\t\t   sizeofShortObject( pkcs15infoPtr->issuerNameIDlength ) );\n\t\twriteShortInteger( stream, PKCS15_KEYID_ISSUERNAMEHASH, DEFAULT_TAG );\n\t\tstatus = writeOctetString( stream, pkcs15infoPtr->issuerNameID,\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->issuerNameIDlength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( pkcs15infoPtr->subjectNameIDlength > 0 )\n\t\t{\n\t\twriteSequence( stream,\n\t\t\t\t\t   sizeofShortInteger( PKCS15_KEYID_SUBJECTNAMEHASH ) + \\\n\t\t\t\t\t   sizeofShortObject( pkcs15infoPtr->subjectNameIDlength ) );\n\t\twriteShortInteger( stream, PKCS15_KEYID_SUBJECTNAMEHASH, DEFAULT_TAG );\n\t\tstatus = writeOctetString( stream, pkcs15infoPtr->subjectNameID,\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->subjectNameIDlength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( pkcs15infoPtr->pgp2KeyIDlength > 0 )\n\t\t{\n\t\twriteSequence( stream, sizeofShortInteger( PKCS15_KEYID_PGP2 ) + \\\n\t\t\t\t\t\t\t   sizeofShortObject( pkcs15infoPtr->pgp2KeyIDlength ) );\n\t\twriteShortInteger( stream, PKCS15_KEYID_PGP2, DEFAULT_TAG );\n\t\tstatus = writeOctetString( stream, pkcs15infoPtr->pgp2KeyID,\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->pgp2KeyIDlength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\tif( pkcs15infoPtr->openPGPKeyIDlength > 0 )\n\t\t{\n\t\twriteSequence( stream, sizeofShortInteger( PKCS15_KEYID_OPENPGP ) + \\\n\t\t\t\t\t\t\t   sizeofShortObject( pkcs15infoPtr->openPGPKeyIDlength ) );\n\t\twriteShortInteger( stream, PKCS15_KEYID_OPENPGP, DEFAULT_TAG );\n\t\tstatus = writeOctetString( stream, pkcs15infoPtr->openPGPKeyID,\n\t\t\t\t\t\t\t\t   pkcs15infoPtr->openPGPKeyIDlength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Write atributes to a buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 7 ) ) \\\nint writeKeyAttributes( OUT_BUFFER( privKeyAttributeMaxLen, \\\n\t\t\t\t\t\t\t\t\t*privKeyAttributeSize ) \n\t\t\t\t\t\t\tvoid *privKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\tconst int privKeyAttributeMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( privKeyAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *privKeyAttributeSize, \n\t\t\t\t\t\tOUT_BUFFER( pubKeyAttributeMaxLen, \\\n\t\t\t\t\t\t\t\t\t*pubKeyAttributeSize ) \\\n\t\t\t\t\t\t\tvoid *pubKeyAttributes, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\tconst int pubKeyAttributeMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( pubKeyAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *pubKeyAttributeSize, \n\t\t\t\t\t\tINOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE iCryptContext,\n\t\t\t\t\t\tconst BOOLEAN writeKeyIDs )\n\t{\n\tSTREAM stream;\n\tint commonAttributeSize, commonKeyAttributeSize;\n\tint keyIdentifierDataSize DUMMY_INIT, keyUsage, status;\n\n\tassert( isWritePtrDynamic( privKeyAttributes, privKeyAttributeMaxLen ) );\n\tassert( isWritePtr( privKeyAttributeSize, sizeof( int ) ) );\n\tassert( isWritePtrDynamic( pubKeyAttributes, pubKeyAttributeMaxLen ) );\n\tassert( isWritePtr( pubKeyAttributeSize, sizeof( int ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( privKeyAttributeMaxLen >= 16 && \\\n\t\t\t  privKeyAttributeMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( pubKeyAttributeMaxLen >= 16 && \\\n\t\t\t  pubKeyAttributeMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Clear return values */\n\tmemset( privKeyAttributes, 0, min( 16, privKeyAttributeMaxLen ) );\n\tmemset( pubKeyAttributes, 0, min( 16, pubKeyAttributeMaxLen ) );\n\t*privKeyAttributeSize = *pubKeyAttributeSize = 0;\n\n\t/* Get ID information from the context */\n\tstatus = getKeyIDs( pkcs15infoPtr, iCryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Try and get the validity information.  This isn't used at this point\n\t   but may be needed before it's set in the certificate write code, for\n\t   example when adding two certificates that differ only in validity \n\t   period to a keyset.  Since we could be adding a raw key we ignore any \n\t   return code */\n\t( void ) getValidityInfo( pkcs15infoPtr, iCryptContext );\n\n\t/* Figure out the PKCS #15 key usage flags.  The action flags for an \n\t   object can change over time under the influence of another object.  \n\t   For example when a raw private key is initially written and unless \n\t   something else has told it otherwise it'll have all permissible \n\t   actions enabled.  When a certificate for the key is later added the \n\t   permissible actions for the key may be constrained by the certificate \n\t   so the private key flags will change when the object is re-written to \n\t   the keyset */\n\tkeyUsage = getKeyUsageFlags( iCryptContext, \n\t\t\t\t\t\t\t\t pkcs15infoPtr->privKeyUsage );\n\tif( keyUsage <= 0 )\n\t\treturn( CRYPT_ERROR_PERMISSION );\t/* No easy way to report this one */\n\n\t/* Determine how big the private key attribute collections will be */\n\tcommonAttributeSize = ( int) sizeofObject( pkcs15infoPtr->labelLength );\n\tcommonKeyAttributeSize = sizeofShortObject( pkcs15infoPtr->iDlength ) + \\\n\t\t\t\t\t\t\t sizeofBitString( keyUsage ) + \\\n\t\t\t\t\t\t\t sizeofBitString( KEYATTR_ACCESS_PRIVATE );\n\tif( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )\n\t\tcommonKeyAttributeSize += sizeofGeneralizedTime();\n\tif( pkcs15infoPtr->validTo > MIN_TIME_VALUE )\n\t\tcommonKeyAttributeSize += sizeofGeneralizedTime();\n\tif( writeKeyIDs )\n\t\tkeyIdentifierDataSize = sizeofObjectIDs( pkcs15infoPtr );\n\n\t/* Write the private key attributes */\n\tsMemOpen( &stream, privKeyAttributes, privKeyAttributeMaxLen );\n\twriteSequence( &stream, commonAttributeSize );\n\twriteCharacterString( &stream, ( BYTE * ) pkcs15infoPtr->label,\n\t\t\t\t\t\t  pkcs15infoPtr->labelLength, BER_STRING_UTF8 );\n\twriteSequence( &stream, commonKeyAttributeSize );\n\twriteOctetString( &stream, pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,\n\t\t\t\t\t  DEFAULT_TAG );\n\twriteBitString( &stream, keyUsage, DEFAULT_TAG );\n\tstatus = writeBitString( &stream, KEYATTR_ACCESS_PRIVATE, DEFAULT_TAG );\n\tif( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )\n\t\tstatus = writeGeneralizedTime( &stream, pkcs15infoPtr->validFrom, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( pkcs15infoPtr->validTo > MIN_TIME_VALUE )\n\t\tstatus = writeGeneralizedTime( &stream, pkcs15infoPtr->validTo, \n\t\t\t\t\t\t\t\t\t   CTAG_KA_VALIDTO );\n\tif( writeKeyIDs )\n\t\t{\n\t\t/* Writing the keyIDs gets rather messy because the identifiers are \n\t\t   present as standard certificate attributes (written in \n\t\t   writeCertAttributes()), but only as subclass attributes for \n\t\t   private keys, and not at all for public keys.  Because of this we\n\t\t   can only write them for private keys */\n\t\twriteConstructed( &stream, sizeofObject( \\\n\t\t\t\t\t\t\t\t\tsizeofObject( keyIdentifierDataSize ) ), \n\t\t\t\t\t\t  CTAG_OB_SUBCLASSATTR );\n\t\twriteSequence( &stream, sizeofObject( keyIdentifierDataSize ) );\n\t\tstatus = writeObjectIDs( &stream, pkcs15infoPtr, \n\t\t\t\t\t\t\t\t keyIdentifierDataSize, \n\t\t\t\t\t\t\t\t CTAG_PK_IDENTIFIERS );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*privKeyAttributeSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\tpkcs15infoPtr->privKeyUsage = keyUsage;\t/* Update stored usage information */\n\n\t/* Determine how big the public key attribute collections will be */\n\tkeyUsage &= PUBKEY_USAGE_MASK;\n\tcommonKeyAttributeSize = sizeofShortObject( pkcs15infoPtr->iDlength ) + \\\n\t\t\t\t\t\t\t sizeofBitString( keyUsage ) + \\\n\t\t\t\t\t\t\t sizeofBitString( KEYATTR_ACCESS_PUBLIC );\n\tif( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )\n\t\tcommonKeyAttributeSize += sizeofGeneralizedTime();\n\tif( pkcs15infoPtr->validTo > MIN_TIME_VALUE )\n\t\tcommonKeyAttributeSize += sizeofGeneralizedTime();\n\n\t/* Write the public key attributes */\n\tsMemOpen( &stream, pubKeyAttributes, pubKeyAttributeMaxLen );\n\twriteSequence( &stream, commonAttributeSize );\n\twriteCharacterString( &stream, ( BYTE * ) pkcs15infoPtr->label,\n\t\t\t\t\t\t  pkcs15infoPtr->labelLength, BER_STRING_UTF8 );\n\twriteSequence( &stream, commonKeyAttributeSize );\n\twriteOctetString( &stream, pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,\n\t\t\t\t\t  DEFAULT_TAG );\n\twriteBitString( &stream, keyUsage, DEFAULT_TAG );\n\tstatus = writeBitString( &stream, KEYATTR_ACCESS_PUBLIC, DEFAULT_TAG );\n\tif( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )\n\t\tstatus = writeGeneralizedTime( &stream, pkcs15infoPtr->validFrom, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\tif( pkcs15infoPtr->validTo > MIN_TIME_VALUE )\n\t\tstatus = writeGeneralizedTime( &stream, pkcs15infoPtr->validTo, \n\t\t\t\t\t\t\t\t\t   CTAG_KA_VALIDTO );\n\tif( cryptStatusOK( status ) )\n\t\t*pubKeyAttributeSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\tpkcs15infoPtr->pubKeyUsage = keyUsage;\t/* Update stored usage information */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint writeCertAttributes( OUT_BUFFER( certAttributeMaxLen, *certAttributeSize ) \\\n\t\t\t\t\t\t\tvoid *certAttributes, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\tconst int certAttributeMaxLen,\n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( certAttributeMaxLen ) \\\n\t\t\t\t\t\t\tint *certAttributeSize, \n\t\t\t\t\t\t INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptCert )\n\t{\n\tSTREAM stream;\n\tBOOLEAN trustedImplicit;\n\tint commonAttributeSize, commonCertAttributeSize;\n\tint keyIdentifierDataSize, trustedUsageSize;\n\tint isCA, trustedUsage, status;\n\n\tassert( isWritePtrDynamic( certAttributes, certAttributeMaxLen ) );\n\tassert( isWritePtr( certAttributeSize, sizeof( int ) ) );\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( certAttributeMaxLen >= 16 && \\\n\t\t\t  certAttributeMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* Clear return values */\n\tmemset( certAttributes, 0, min( 16, certAttributeMaxLen ) );\n\t*certAttributeSize = 0;\n\n\t/* Get ID information from the certificate */\n\tstatus = getCertIDs( pkcs15infoPtr, iCryptCert, &isCA, \n\t\t\t\t\t\t &trustedImplicit, &trustedUsage );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* At this point we could create a pseudo-label by reading the \n\t   CRYPT_IATTRIBUTE_HOLDERNAME attribute, however label-less items will \n\t   only occur when adding a standalone (i.e. trusted, implicitly-\n\t   handled) certificate.  If we were to set labels for these then the \n\t   keyset would end up acting as a general-purpose certificate store \n\t   which it isn't meant to be, so we always leave implicitly handled \n\t   certificates label-less */\n\n\t/* Determine how big the attribute collection will be */\n\ttrustedUsageSize = ( trustedUsage != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t   sizeofBitString( trustedUsage ) : 0;\n\tkeyIdentifierDataSize = sizeofObjectIDs( pkcs15infoPtr );\n\tcommonAttributeSize = ( pkcs15infoPtr->labelLength > 0 ) ? \\\n\t\t\t\t\t\t  sizeofShortObject( pkcs15infoPtr->labelLength ) : 0;\n\tcommonCertAttributeSize = \\\n\t\t\t\t\t\tsizeofShortObject( pkcs15infoPtr->iDlength ) + \\\n\t\t\t\t\t\t( isCA ? sizeofBoolean() : 0 ) + \\\n\t\t\t\t\t\t( ( trustedUsage != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t  sizeofShortObject( trustedUsageSize ) : 0 ) + \\\n\t\t\t\t\t\tsizeofShortObject( keyIdentifierDataSize ) + \\\n\t\t\t\t\t\t( trustedImplicit ? sizeofBoolean() : 0 ) + \\\n\t\t\t\t\t\tsizeofGeneralizedTime() + sizeofGeneralizedTime();\n\n\t/* Write the certificate attributes */\n\tsMemOpen( &stream, certAttributes, certAttributeMaxLen );\n\twriteSequence( &stream, commonAttributeSize );\n\tif( commonAttributeSize > 0 )\n\t\twriteCharacterString( &stream, pkcs15infoPtr->label,\n\t\t\t\t\t\t\t  pkcs15infoPtr->labelLength, BER_STRING_UTF8 );\n\twriteSequence( &stream, commonCertAttributeSize );\n\twriteOctetString( &stream, pkcs15infoPtr->iD, pkcs15infoPtr->iDlength,\n\t\t\t\t\t  DEFAULT_TAG );\n\tif( isCA )\n\t\twriteBoolean( &stream, TRUE, DEFAULT_TAG );\n\tif( trustedUsage != CRYPT_UNUSED )\n\t\t{\n\t\twriteConstructed( &stream, trustedUsageSize, CTAG_CA_TRUSTED_USAGE );\n\t\twriteBitString( &stream, trustedUsage, DEFAULT_TAG );\n\t\t}\n\tstatus = writeObjectIDs( &stream, pkcs15infoPtr, keyIdentifierDataSize,\n\t\t\t\t\t\t\t CTAG_CA_IDENTIFIERS );\n\tENSURES( cryptStatusOK( status ) );\n\tif( trustedImplicit )\n\t\twriteBoolean( &stream, TRUE, CTAG_CA_TRUSTED_IMPLICIT );\n\twriteGeneralizedTime( &stream, pkcs15infoPtr->validFrom, DEFAULT_TAG );\n\tstatus = writeGeneralizedTime( &stream, pkcs15infoPtr->validTo,\n\t\t\t\t\t\t\t\t   CTAG_CA_VALIDTO );\n\tif( cryptStatusOK( status ) )\n\t\t*certAttributeSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_get.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t   cryptlib PKCS #15 Get-item Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set any optional attributes that may be associated with a key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int setKeyAttributes( IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\t INOUT const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t IN_FLAGS_Z( ACTION_PERM ) const int actionFlags )\n\t{\n\tint status;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( isFlagRangeZ( actionFlags, ACTION_PERM ) );\n\t\t\t  /* This check is a bit odd because normally an action flag \n\t\t\t     value of ACTION_PERM_FLAG_NONE would indicate that the \n\t\t\t\t object can't be used, but setting it to CRYPT_UNUSED would \n\t\t\t\t create a value outside the normal allowed range so we use \n\t\t\t\t _NONE to indicate a don't-care value */\n\n\tif( actionFlags != 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &actionFlags,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( pkcs15infoPtr->openPGPKeyIDlength > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) pkcs15infoPtr->openPGPKeyID,\n\t\t\t\t\t\tpkcs15infoPtr->openPGPKeyIDlength );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t/* 18/3/18 We can't safely set this as the PGP date because the OpenPGP \n\t\t\t   keyID hashes it into the implicitly-generated ID value, which \n\t\t\t   means that the key ID changes at random depending on the date \n\t\t\t   value.  For keys from non-PGP sources cryptlib always sets \n\t\t\t   the date to zero in order to get a fixed value for the ID */\n#if 0\n\tif( pkcs15infoPtr->validFrom > MIN_TIME_VALUE )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\t/* This isn't really used for anything but is required to generate\n\t\t   the OpenPGP keyID, which includes the key creation time in the\n\t\t   ID-generation process */\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) &pkcs15infoPtr->validFrom,\n\t\t\t\t\t\tsizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* 0 */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get an encoded trusted certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int getTrustedCert( IN_ARRAY( noPkcs15objects ) \\\n\t\t\t\t\t\t\tconst PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\t   OUT_BUFFER( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int dataMaxLength, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t   const BOOLEAN resetCertIndex )\n\t{\n\tstatic int trustedCertIndex;\n\tconst PKCS15_INFO *pkcs15infoPtr;\n\tint certStartOffset, certDataTotalSize, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( resetCertIndex == TRUE || resetCertIndex == FALSE );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* If this is the first certificate, reset the index value.  This is \n\t   pretty ugly since this sort of state-information value should be \n\t   stored with the caller, however there's no way to pass this back and \n\t   forth in a MESSAGE_DATA without resorting to an even uglier hack and \n\t   it's safe since this attribute is only ever read by the init thread \n\t   when it reads the configuration data at startup */\n\tif( resetCertIndex )\n\t\ttrustedCertIndex = 0;\n\telse\n\t\t{\n\t\t/* Move on to the next certificate */\n\t\tif( trustedCertIndex >= noPkcs15objects - 1 )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\ttrustedCertIndex++;\t\n\t\t}\n\n\t/* Find the next trusted certificate */\n\tLOOP_MED( pkcs15infoPtr = NULL, trustedCertIndex < noPkcs15objects, \n\t\t\t  trustedCertIndex++ )\n\t\t{\n\t\tif( pkcs15info[ trustedCertIndex ].implicitTrust )\n\t\t\t{\n\t\t\tpkcs15infoPtr = &pkcs15info[ trustedCertIndex ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( pkcs15infoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tcertStartOffset = pkcs15infoPtr->certOffset;\n\tcertDataTotalSize = pkcs15infoPtr->certDataSize;\n\n\t/* Return the data to the caller */\n\tREQUIRES( boundsCheck( certStartOffset, \n\t\t\t\t\t\t   certDataTotalSize - certStartOffset,\n\t\t\t\t\t\t   certDataTotalSize ) );\n\treturn( attributeCopyParams( data, dataMaxLength, dataLength,\n\t\t\t\t\t( BYTE * ) pkcs15infoPtr->certData + certStartOffset,\n\t\t\t\t\tcertDataTotalSize - certStartOffset ) );\n\t}\n\n/* Get an encoded configuration item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int getConfigItem( IN_ARRAY( noPkcs15objects ) \\\n\t\t\t\t\t\t\tconst PKCS15_INFO *pkcs15info,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int noPkcs15objects,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *dataLength )\n\t{\n\tconst PKCS15_INFO *pkcs15infoPtr;\n\tint dataStartOffset, dataTotalSize, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINDEX || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINFO );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataMaxLength >= 16 && \\\n\t\t\t\tdataMaxLength < MAX_INTLENGTH_SHORT ) );\n\n\t/* Clear return values */\n\t*dataLength = 0;\n\tif( data != NULL )\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\n\t/* Find the particular data type that we're looking for */\n\tLOOP_MED( ( pkcs15infoPtr = NULL, i = 0 ), i < noPkcs15objects, i++ )\n\t\t{\n\t\tif( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_DATA && \\\n\t\t\t  pkcs15info[ i ].dataType == dataType ) )\n\t\t\t{\n\t\t\tpkcs15infoPtr = &pkcs15info[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( pkcs15infoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tdataStartOffset = pkcs15infoPtr->dataOffset;\n\tdataTotalSize = pkcs15infoPtr->dataDataSize;\n\n\t/* If it's just a length check, we're done */\n\tif( data == NULL )\n\t\t{\n\t\t*dataLength = dataTotalSize - dataStartOffset;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Return the data to the caller */\n\tREQUIRES( boundsCheck( dataStartOffset, \n\t\t\t\t\t\t   dataTotalSize - dataStartOffset,\n\t\t\t\t\t\t   dataTotalSize ) );\n\treturn( attributeCopyParams( data, dataMaxLength, dataLength,\n\t\t\t\t\t( BYTE * ) pkcs15infoPtr->dataData + dataStartOffset,\n\t\t\t\t\tdataTotalSize - dataStartOffset ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tGet a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read key data from a PKCS #15 collection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int getItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_HANDLE *iCryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\tIN_OPT void *auxInfo, \n\t\t\t\t\t\t\tINOUT_OPT int *auxInfoLength,\n\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int flags )\n\t{\n\tCRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;\n\tCRYPT_KEYID_TYPE localKeyIDtype = keyIDtype;\n\tCRYPT_CONTEXT iCryptContext;\n\tconst PKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tconst PKCS15_INFO *pkcs15infoPtr;\n\tMESSAGE_DATA msgData;\n\tconst void *localKeyID = keyID;\n\tconst BOOLEAN publicComponentsOnly = \\\n\t\t\t\t\t( itemType != KEYMGMT_ITEM_PRIVATEKEY ) ? TRUE : FALSE;\n\tconst BOOLEAN isStorageObject = \\\n\t\t\t( keysetInfoPtr->keysetFile->iHardwareDevice != CRYPT_UNUSED ) ? \\\n\t\t\tTRUE : FALSE;\n\tconst int auxInfoMaxLength = *auxInfoLength;\n\tint localKeyIDlength = keyIDlength;\n\tint pubkeyActionFlags = 0, privkeyActionFlags = 0, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCryptHandle, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( ( auxInfo == NULL && auxInfoMaxLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( auxInfo, auxInfoMaxLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( ( auxInfo == NULL && *auxInfoLength == 0 ) || \\\n\t\t\t  ( auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( *auxInfoLength ) ) );\n\tREQUIRES( isFlagRangeZ( flags, KEYMGMT ) );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Clear return values */\n\t*iCryptHandle = CRYPT_ERROR;\n\n\t/* Locate the appropriate object in the PKCS #15 collection and make \n\t   sure that the components that we need are present: Either a public \n\t   key or a certificate for any type of read, and a private key as well \n\t   for a private-key read */\n\tif( keyIDlength == 6 && !strCompare( keyID, \"[none]\", 6 ) )\n\t\t{\n\t\t/* It's a wildcard read, locate the first private-key object */\n\t\tpkcs15infoPtr = findEntry( pkcs15info, \n\t\t\t\t\t\t\t\t   keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t\t\t   keyIDtype, NULL, 0, flags, TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tpkcs15infoPtr = findEntry( pkcs15info, \n\t\t\t\t\t\t\t\t   keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t\t\t   keyIDtype, keyID, keyIDlength, flags, FALSE );\n\t\tif( pkcs15infoPtr == NULL && keyIDtype == CRYPT_IKEYID_PGPKEYID )\n\t\t\t{\n\t\t\t/* If we don't find a match for an OpenPGP ID, try again with a \n\t\t\t   wildcard match.  This somewhat suboptimal strategy is \n\t\t\t   dictated by the annoying way in which OpenPGP keyIDs are \n\t\t\t   generated, they hash a timestamp into the ID value and \n\t\t\t   generate it implicitly on the fly without storing it, so \n\t\t\t   without access to the original PGP-format keyring that \n\t\t\t   contains the key there's no way to determine a matching ID \n\t\t\t   value.  Matching the first key is somewhat suboptimal since \n\t\t\t   it can lead to false positives, but it provides at least some \n\t\t\t   functionality in cases where this problem crops up, and if it \n\t\t\t   really is the wrong key it'll be caught later on when an \n\t\t\t   attempt to decrypt with it fails.\n\n\t\t\t   Once we've matched the first key, we have to change the key \n\t\t\t   ID to a tautological one since an import of the public key \n\t\t\t   components using the OpenPGP ID will fail in the same way as \n\t\t\t   the overall match on the OpenPGP ID */\n\t\t\tpkcs15infoPtr = findEntry( pkcs15info, \n\t\t\t\t\t\t\t\t\t   keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t\t\t\t   keyIDtype, NULL, 0, flags, TRUE );\n\t\t\tif( pkcs15infoPtr != NULL )\n\t\t\t\t{\n\t\t\t\tlocalKeyIDtype = CRYPT_IKEYID_KEYID;\n\t\t\t\tlocalKeyID = pkcs15infoPtr->keyID;\n\t\t\t\tlocalKeyIDlength = pkcs15infoPtr->keyIDlength;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( pkcs15infoPtr == NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No information present for this ID\" ) );\n\t\t}\n\tif( pkcs15infoPtr->pubKeyData == NULL && \\\n\t\tpkcs15infoPtr->certData == NULL )\n\t\t{\n\t\t/* There's not enough information present to get a public key or the\n\t\t   public portions of a private key */\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No public key or certificate data present for this ID\" ) );\n\t\t}\n\tif( !publicComponentsOnly && pkcs15infoPtr->privKeyData == NULL )\n\t\t{\n\t\t/* There's not enough information present to get a private key */\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No private key data present for this ID\" ) );\n\t\t}\n\n\t/* If we're just checking whether an object exists, return now.  If all\n\t   that we want is the key label, copy it back to the caller and exit */\n\tif( flags & KEYMGMT_FLAG_CHECK_ONLY )\n\t\treturn( CRYPT_OK );\n\tif( flags & KEYMGMT_FLAG_LABEL_ONLY )\n\t\t{\n\t\treturn( attributeCopyParams( auxInfo, auxInfoMaxLength, \n\t\t\t\t\t\t\t\t\t auxInfoLength, pkcs15infoPtr->label, \n\t\t\t\t\t\t\t\t\t pkcs15infoPtr->labelLength ) );\n\t\t}\n\n\t/* If we're reading the private key and this isn't a PKCS #15 object \n\t   store (which only contains metadata for private keys), make sure that \n\t   the user has supplied a password.  This is checked by the kernel but \n\t   we perform another check here just to be safe*/\n\tif( !publicComponentsOnly && !isStorageObject && auxInfo == NULL )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t/* Read the public components */\n\tstatus = readPublicKeyComponents( pkcs15infoPtr, keysetInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  localKeyIDtype, localKeyID, \n\t\t\t\t\t\t\t\t\t  localKeyIDlength, publicComponentsOnly,\n\t\t\t\t\t\t\t\t\t  isStorageObject ? \\\n\t\t\t\t\t\t\t\t\t\tkeysetInfoPtr->keysetFile->iHardwareDevice : \\\n\t\t\t\t\t\t\t\t\t\tSYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  &iCryptContext, &iDataCert,\n\t\t\t\t\t\t\t\t\t  &pubkeyActionFlags, \n\t\t\t\t\t\t\t\t\t  &privkeyActionFlags, KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're only interested in the public components, set the key\n\t   permissions and exit */\n\tif( publicComponentsOnly )\n\t\t{\n\t\tstatus = setKeyAttributes( iCryptContext, pkcs15infoPtr,\n\t\t\t\t\t\t\t\t   ( pkcs15infoPtr->pubKeyData != NULL ) ? \\\n\t\t\t\t\t\t\t\t\t pubkeyActionFlags : 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't set PKCS #15 permitted action flags for \"\n\t\t\t\t\t  \"the key\" ) );\n\t\t\t}\n\t\t*iCryptHandle = iCryptContext;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tREQUIRES( ( pkcs15infoPtr->pubKeyData != NULL || \\\n\t\t\t\tpkcs15infoPtr->certData != NULL ) && \\\n\t\t\t  pkcs15infoPtr->privKeyData != NULL );\n\n\t/* Set the key label and read the private key components.  We have to \n\t   set the label before we load the key or the key load will be blocked \n\t   by the kernel.  In addition if this keyset is a device object store\n\t   we have to set the label as a CRYPT_IATTRIBUTE_EXISTINGLABEL \n\t   otherwise the existing item's label will be erroneously reported as\n\t   a duplicate */\n\tif( pkcs15infoPtr->labelLength > 0 )\n\t\t{ \n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) pkcs15infoPtr->label,\n\t\t\t\t\t\tmin( pkcs15infoPtr->labelLength, \\\n\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE ) ); \n\t\t}\n\telse\n\t\t{ \n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) \"Dummy label\", 11 ); \n\t\t}\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, isStorageObject ? \\\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_EXISTINGLABEL : \\\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_LABEL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readPrivateKeyComponents( pkcs15infoPtr, iCryptContext, \n\t\t\t\t\t\t\t\tauxInfo, *auxInfoLength, isStorageObject,\n\t\t\t\t\t\t\t\tKEYSET_ERRINFO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tif( iDataCert != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Connect the data-only certificate object to the context if it exists.\n\t   This is an internal object used only by the context so we tell the\n\t   kernel to mark it as owned by the context only */\n\tif( iDataCert != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t  &iDataCert, SETDEP_OPTION_NOINCREF );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Couldn't attach certificate to key\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Set the permitted action flags */\n\tstatus = setKeyAttributes( iCryptContext, pkcs15infoPtr,\n\t\t\t\t\t\t\t   privkeyActionFlags );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, MESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, KEYSET_ERRINFO, \n\t\t\t\t  \"Couldn't set PKCS #15 permitted action flags for the \"\n\t\t\t\t  \"key\" ) );\n\t\t}\n\n\t*iCryptHandle = iCryptContext;\n\treturn( CRYPT_OK );\n\t}\n\n/* Read special data from a PKCS #15 collection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \\\nstatic int getSpecialItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t\t\t   OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *data,\n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int dataMaxLength,\n\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\tint *dataLength )\n\t{\n\tconst PKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\n\tassert( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINDEX || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINFO || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t    dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( ( dataType != CRYPT_IATTRIBUTE_TRUSTEDCERT && \\\n\t\t\t\tdataType != CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT ) || \\\n\t\t\t  data != NULL );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Clear return values */\n\tif( data != NULL )\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* If we're being asked for pre-encoded trusted certificate data, return \n\t   it to the caller */\n\tif( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \\\n\t\tdataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT )\n\t\t{\n\t\treturn( getTrustedCert( pkcs15info, keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t\t\tdata, dataMaxLength, dataLength,\n\t\t\t\t\t\t\t\t( dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE ) );\n\t\t}\n\n\t/* Return a configuration data item */\n\treturn( getConfigItem( pkcs15info, keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t   dataType, data, dataMaxLength, dataLength ) );\n\t}\n\n#ifdef USE_CERTIFICATES\n\n/* Fetch a sequence of certificates.  These functions are called indirectly \n   by the certificate code to fetch the first and subsequent certificates in \n   a certificate chain.  The 'stateInfo' value is handled as an OUT parameter\n   rather than the more obvious INOUT since the state is managed explicitly \n   by the caller, who uses it to pass in a next-key-ID reference instead of \n   a current-key-ID one */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 10 ) ) \\\nstatic int getItem( INOUT_ARRAY( noPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t\tIN_LENGTH_SHORT const int noPkcs15objects, \n\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate, \n\t\t\t\t\tOUT int *stateInfo, \n\t\t\t\t\tIN_KEYID const CRYPT_KEYID_TYPE keyIDtype, \n\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\tIN_LENGTH_KEYID const int keyIDlength, \n\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) const KEYMGMT_ITEM_TYPE itemType, \n\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options, \n\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tconst PKCS15_INFO *pkcs15infoPtr;\n\tBYTE *certDataPtr;\n\tint certStartOffset, certDataTotalSize, tag, status;\n\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtr( stateInfo, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_SUBJECTID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\tREQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\n\t/* Find the appropriate entry based on the ID */\n\tif( keyIDtype != CRYPT_IKEYID_SUBJECTID && \\\n\t\tkeyIDlength == 6 && !strCompare( keyID, \"[none]\", 6 ) )\n\t\t{\n\t\t/* It's a findFirst() called (findNext() always uses \n\t\t   CRYPT_IKEYID_SUBJECTID as the ID) and it's a wildcard read, \n\t\t   locate the first object associated with a private key */\n\t\tpkcs15infoPtr = findEntry( pkcs15info, noPkcs15objects, keyIDtype, \n\t\t\t\t\t\t\t\t   NULL, 0, options, TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tpkcs15infoPtr = findEntry( pkcs15info, noPkcs15objects, keyIDtype, \n\t\t\t\t\t\t\t\t   keyID, keyIDlength, options, FALSE );\n\t\t}\n\tif( pkcs15infoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t*stateInfo = pkcs15infoPtr->index;\n\n\t/* When we get called it's via a callback from iCryptImportCertIndirect()\n\t   that's called as part of a private-key read, and that only gets called\n\t   if there's certificate data present, the following check ensures that \n\t   this is the case */\n\tENSURES( pkcs15infoPtr->certData != NULL );\n\n\t/* Import the certificate.  This gets somewhat ugly because early drafts \n\t   of PKCS #15 wrote the certificate as is while the final version \n\t   wrapped it up in a [0] IMPLICIT tag so we can run into both the \n\t   original untagged SEQUENCE form and the newer [0] IMPLICIT SEQUENCE.  \n\t   To handle this we dynamically replace the tag with the standard \n\t   SEQUENCE tag and reinstate the original afterwards, this is easier \n\t   than trying to pass the special-case decoding requirement down \n\t   through the kernel call */\n\tcertDataPtr = ( BYTE * ) pkcs15infoPtr->certData + \\\n\t\t\t\t  pkcs15infoPtr->certOffset;\n\tcertStartOffset = pkcs15infoPtr->certOffset;\n\tcertDataTotalSize = pkcs15infoPtr->certDataSize;\n\ttag = *certDataPtr;\n\t*certDataPtr = BER_SEQUENCE;\n\tREQUIRES( boundsCheck( certStartOffset, \n\t\t\t\t\t\t   certDataTotalSize - certStartOffset,\n\t\t\t\t\t\t   certDataTotalSize ) );\n\tsetMessageCreateObjectIndirectInfoEx( &createInfo, certDataPtr,\n\t\t\t\t\t\t\tcertDataTotalSize - certStartOffset,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t\t\t( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT : \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t*certDataPtr = intToByte( tag );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't create certificate from stored certificate \"\n\t\t\t\t  \"data\" ) );\n\t\t}\n\tif( !( ( ( keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t   keyIDtype == CRYPT_IKEYID_PGPKEYID ) && \\\n\t\t\t ( options & KEYMGMT_FLAG_DATAONLY_CERT ) ) ) )\n\t\t{\n\t\t/* Make sure that the certificate that we got back is what we \n\t\t   actually asked for.  We can't do this for key IDs with data-only \n\t\t   certificates since the IDs aren't present in the certificate\n\t\t   but are generated dynamically in the associated context */\n\t\tstatus = iCryptVerifyID( createInfo.cryptHandle, keyIDtype, keyID, \n\t\t\t\t\t\t\t\t keyIDlength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Certificate fetched for ID type %s doesn't actually \"\n\t\t\t\t\t  \"correspond to the given ID\", \n\t\t\t\t\t  getKeyIDName( keyIDtype ) ) );\n\t\t\t}\n\t\t}\n\t*iCertificate = createInfo.cryptHandle;\n\tif( pkcs15infoPtr->validFrom <= MIN_TIME_VALUE )\n\t\t{\n\t\t/* Perform an opportunistic update of the validity information if \n\t\t   this hasn't already been set.  Since this is a purely \n\t\t   opportunistic update we ignore any return value */\n\t\t( void ) getValidityInfo( pkcs15info, createInfo.cryptHandle );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \\\nstatic int getFirstItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t OUT int *stateInfo,\n\t\t\t\t\t\t\t\t IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tPKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tconst int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtr( stateInfo, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) );\n\tREQUIRES( ( options & KEYMGMT_MASK_USAGEOPTIONS ) != \\\n\t\t\t  KEYMGMT_MASK_USAGEOPTIONS );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\n\treturn( getItem( pkcs15info, noPkcs15objects, iCertificate, stateInfo,\n\t\t\t\t\t keyIDtype, keyID, keyIDlength, itemType, options,\n\t\t\t\t\t KEYSET_ERRINFO ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getNextItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tINOUT int *stateInfo, \n\t\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tPKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tconst int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;\n\tconst int lastEntry = *stateInfo;\n\tint status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( stateInfo, sizeof( int ) ) );\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_MASK_CERTOPTIONS ) == 0 );\n\tREQUIRES( ( lastEntry >= 0 && lastEntry < noPkcs15objects ) || \\\n\t\t\t  lastEntry == CRYPT_ERROR );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Clear return values */\n\t*iCertificate = CRYPT_ERROR;\n\t*stateInfo = CRYPT_ERROR;\n\n\t/* If the previous certificate was the last one, there's nothing left to \n\t   fetch */\n\tif( lastEntry == CRYPT_ERROR )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No more items present\" ) );\n\t\t}\n\tENSURES( lastEntry >= 0 && lastEntry < noPkcs15objects );\n\n\t/* If there's no index information present to locate other certificates, \n\t   we can't go any further */\n\tif( pkcs15info[ lastEntry ].issuerNameIDlength <= 0 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No index information available to locate other \"\n\t\t\t\t  \"certificates\" ) );\n\t\t}\n\n\t/* Find the certificate for which the subjectNameID matches this \n\t   certificate's issuerNameID */\n\tstatus = getItem( pkcs15info, noPkcs15objects, iCertificate, stateInfo,\n\t\t\t\t\t  CRYPT_IKEYID_SUBJECTID, \n\t\t\t\t\t  pkcs15info[ lastEntry ].issuerNameID,\n\t\t\t\t\t  pkcs15info[ lastEntry ].issuerNameIDlength,\n\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY, options, KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( lastEntry != *stateInfo );\t\t/* Loop detection */\n\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \\\nstatic int getFirstItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\t OUT int *stateInfo,\n\t\t\t\t\t\t\t\t IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int getNextItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t\tINOUT int *stateInfo, \n\t\t\t\t\t\t\t\tIN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\treturn( CRYPT_ERROR_NOTFOUND );\n\t}\n#endif /* USE_CERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS15get( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->getItemFunction, getItemFunction );\n\tFNPTR_SET( keysetInfoPtr->getSpecialItemFunction, getSpecialItemFunction );\n\tFNPTR_SET( keysetInfoPtr->getFirstItemFunction, getFirstItemFunction );\n\tFNPTR_SET( keysetInfoPtr->getNextItemFunction, getNextItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_getp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib PKCS #15 Get Public/Private Key\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n/* Define the following to enable a workaround for a MAC keysize bug in\n   authEnc private key data in cryptlib 3.4.0 */\n\n#define MAC_KEYSIZE_BUG\n\n#ifdef USE_PKCS15\n\n/* OID information used to read a PKCS #15 keyset */\n\nstatic const OID_INFO dataOIDinfo[] = {\n\t{ OID_CMS_DATA, CRYPT_OK },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Translate the PKCS #15 usage flags into cryptlib permitted actions.  The\n   PKCS #11 use of the 'derive' flag to mean 'allow key agreement' is a bit\n   of a kludge, we map it to allowing key-agreement export and import if \n   it's a key-agreement algorithm, if there are further constraints then \n   they'll be handled by the attached certificate.  The PKCS #15 \n   nonRepudiation flag doesn't have any definition so we can't do anything \n   with it, although we may need to translate it to allowing signing and/or \n   verification if implementations appear that expect it to be used this \n   way */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getPermittedActions( IN_FLAGS( PKCS15_USAGE ) const int usageFlags,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\tOUT_FLAGS_Z( ACTION_PERM ) int *usage )\n\t{\n\tint actionFlags = ACTION_PERM_NONE_ALL;\n\n\tREQUIRES( isFlagRangeZ( usageFlags, PKCS15_USAGE ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\n\t/* Clear return value */\n\t*usage = ACTION_PERM_NONE;\n\n\tif( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP ) )\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );\n\tif( usageFlags & ( PKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) )\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );\n\tif( usageFlags & PKCS15_USAGE_SIGN )\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );\n\tif( usageFlags & PKCS15_USAGE_VERIFY )\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );\n\tif( isKeyxAlgo( cryptAlgo ) && ( usageFlags & PKCS15_USAGE_DERIVE ) )\n\t\tactionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL ) | \\\n\t\t\t\t\t   MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\t/* If there are any restrictions on the key usage then we have to \n\t\t   make it internal-only because of RSA's signature/encryption \n\t\t   duality */\n\t\tif( !( ( usageFlags & ( PKCS15_USAGE_ENCRYPT | PKCS15_USAGE_WRAP | \\\n\t\t\t\t\t\t\t\tPKCS15_USAGE_DECRYPT | PKCS15_USAGE_UNWRAP ) ) && \\\n\t\t\t   ( usageFlags & ( PKCS15_USAGE_SIGN | PKCS15_USAGE_VERIFY ) ) ) )\n\t\t\tactionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );\n\t\t}\n\telse\n\t\t{\n\t\t/* Because of the special-case data formatting requirements for DLP\n\t\t   algorithms we make the usage internal-only */\n\t\tactionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );\n\t\t}\n\tif( actionFlags <= ACTION_PERM_NONE_ALL )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t*usage = actionFlags;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead Public Key Components\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read public-key components from a PKCS #15 object entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 8, 9, 10, 11, 12 ) ) \\\nint readPublicKeyComponents( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_KEYSET iCryptKeysetCallback,\n\t\t\t\t\t\t\t IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t IN_LENGTH_KEYID const int keyIDlength,\n\t\t\t\t\t\t\t const BOOLEAN publicComponentsOnly,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_DEVICE iDeviceObject, \n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContextPtr,\n\t\t\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CERTIFICATE *iDataCertPtr,\n\t\t\t\t\t\t\t OUT_FLAGS_Z( ACTION_PERM ) int *pubkeyActionFlags, \n\t\t\t\t\t\t\t OUT_FLAGS_Z( ACTION_PERM ) int *privkeyActionFlags, \n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tCRYPT_CERTIFICATE iDataCert = CRYPT_ERROR;\n\tSTREAM stream;\n\tint pkcAlgo, status;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\tassert( isWritePtr( iCryptContextPtr, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iDataCertPtr, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( pubkeyActionFlags, sizeof( int ) ) );\n\tassert( isWritePtr( privkeyActionFlags, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptKeysetCallback ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_PGPKEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( publicComponentsOnly == TRUE || publicComponentsOnly == FALSE );\n\tREQUIRES( iDeviceObject == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iDeviceObject ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\t*iCryptContextPtr = CRYPT_ERROR;\n\t*iDataCertPtr = CRYPT_ERROR;\n\t*pubkeyActionFlags = *privkeyActionFlags = ACTION_PERM_NONE;\n\n\t/* If we're creating a public-key context we create the certificate or \n\t   PKC context normally, if we're creating a private-key context we \n\t   create a data-only certificate (if there's certificate information \n\t   present) and a partial PKC context ready to accept the private key \n\t   components.  If there's a certificate present then we take all of the \n\t   information that we need from the certificate, otherwise we use the \n\t   public-key data */\n#ifdef USE_CERTIFICATES\n\tif( pkcs15infoPtr->certData != NULL )\n\t\t{\n\t\t/* There's a certificate present, import it and reconstruct the\n\t\t   public-key information from it if we're creating a partial PKC \n\t\t   context */\n\t\tstatus = iCryptImportCertIndirect( &iCryptContext,\n\t\t\t\t\t\t\t\tiCryptKeysetCallback, keyIDtype, keyID,\n\t\t\t\t\t\t\t\tkeyIDlength, publicComponentsOnly ? \\\n\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_NONE : \\\n\t\t\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't recreate certificate from stored \"\n\t\t\t\t\t  \"certificate data\" ) );\n\t\t\t}\n\t\tif( !publicComponentsOnly )\n\t\t\t{\n\t\t\tDYNBUF pubKeyDB;\n\n\t\t\t/* We got the certificate, now create the public part of the \n\t\t\t   context from the certificate's encoded public-key \n\t\t\t   components */\n\t\t\tiDataCert = iCryptContext;\n\t\t\tstatus = dynCreate( &pubKeyDB, iDataCert, \n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_SPKI );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsMemConnect( &stream, dynData( pubKeyDB ),\n\t\t\t\t\t\t dynLength( pubKeyDB ) );\n\t\t\tstatus = iCryptReadSubjectPublicKey( &stream, &iCryptContext,\n\t\t\t\t\t\t\t\t\t\t\t\t iDeviceObject, TRUE );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tdynDestroy( &pubKeyDB );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\t\t\tretExt( status, \n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Couldn't recreate public key from \"\n\t\t\t\t\t\t  \"certificate\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n#endif /* USE_CERTIFICATES */\n\t\t{\n\t\tconst int pubKeyStartOffset = pkcs15infoPtr->pubKeyOffset;\n\t\tconst int pubKeyTotalSize = pkcs15infoPtr->pubKeyDataSize;\n\n\t\t/* There's no certificate present, create the public-key context\n\t\t   directly */\n\t\tREQUIRES( boundsCheck( pubKeyStartOffset, \n\t\t\t\t\t\t\t   pubKeyTotalSize - pubKeyStartOffset,\n\t\t\t\t\t\t\t   pubKeyTotalSize ) );\n\t\tsMemConnect( &stream, \n\t\t\t\t\t ( BYTE * ) pkcs15infoPtr->pubKeyData + pubKeyStartOffset,\n\t\t\t\t\t pubKeyTotalSize - pubKeyStartOffset );\n\t\tstatus = iCryptReadSubjectPublicKey( &stream, &iCryptContext,\n\t\t\t\t\t\t\t\t\t\t\t iDeviceObject, \n\t\t\t\t\t\t\t\t\t\t\t publicComponentsOnly ? \\\n\t\t\t\t\t\t\t\t\t\t\t\tFALSE : TRUE );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't recreate public key from stored public key \"\n\t\t\t\t\t  \"data\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Get the permitted usage flags for each object type that we'll be\n\t   instantiating.  If there's a public key present we apply its usage\n\t   flags to whichever PKC context we create, even if it's done indirectly\n\t   via the certificate import.  Since the private key can also perform \n\t   the actions of the public key we set its action flags to the union of \n\t   the two */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &pkcAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && pkcs15infoPtr->pubKeyData != NULL )\n\t\t{\n\t\tstatus = getPermittedActions( pkcs15infoPtr->pubKeyUsage, pkcAlgo,\n\t\t\t\t\t\t\t\t\t  pubkeyActionFlags );\n\t\t}\n\tif( cryptStatusOK( status ) && !publicComponentsOnly )\n\t\t{\n\t\tstatus = getPermittedActions( pkcs15infoPtr->privKeyUsage, pkcAlgo,\n\t\t\t\t\t\t\t\t\t  privkeyActionFlags );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tif( iDataCert != CRYPT_ERROR )\n\t\t\tkrnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Public/private key usage flags don't allow any type of \"\n\t\t\t\t  \"key usage\" ) );\n\t\t}\n\n\t/* Return the newly-created objects to the caller */\n\t*iCryptContextPtr = iCryptContext;\n\t*iDataCertPtr = iDataCert;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Private Key Components\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import the session key (either a direct session key or a generic-secret\n   key used to derive the decryption and MAC contexts) using the supplied\n   password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 6 ) ) \\\nstatic int importSessionKey( IN_HANDLE const CRYPT_CONTEXT iSessionKey,\n\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyDataSize ) \\\n\t\t\t\t\t\t\t\tconst void *encryptedKeyData,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int encryptedKeyDataSize,\n\t\t\t\t\t\t\t IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t\t\t\t IN_LENGTH_NAME const int passwordLength,\n\t\t\t\t\t\t\t const QUERY_INFO *queryInfo )\n\t{\n\tCRYPT_CONTEXT iKeyWrapContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tint mode, status;\n\n\tassert( isReadPtrDynamic( encryptedKeyData, encryptedKeyDataSize ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSessionKey ) );\n\tREQUIRES( encryptedKeyDataSize >= 16 && \\\n\t\t\t  encryptedKeyDataSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Create the context used to import the session key and derive the user\n\t   password into it */\n\tsetMessageCreateObjectInfo( &createInfo, queryInfo->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiKeyWrapContext = createInfo.cryptHandle;\n\tmode = queryInfo->cryptMode;\t/* int vs.enum */\n\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusOK( status ) && \\\n\t\tqueryInfo->keySetupAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tconst int algorithm = queryInfo->keySetupAlgo;\t/* int vs.enum */\n\t\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &algorithm, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ALGO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &queryInfo->keySetupIterations,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ITERATIONS );\n\t\t}\n\tif( cryptStatusOK( status ) && queryInfo->keySize > 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &queryInfo->keySize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) queryInfo->salt, \n\t\t\t\t\t\tqueryInfo->saltLength );\n\t\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_SALT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, passwordLength );\n\t\tstatus = krnlSendMessage( iKeyWrapContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_VALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iKeyWrapContext, IMESSAGE_DECREFCOUNT );\n\n\t\t/* If there's an error in the parameters supplied via the query \n\t\t   information (which were stored with the exported key) we'll get \n\t\t   an argument or attribute error when we try to set the attribute \n\t\t   so we translate it into an error code which is appropriate for \n\t\t   the situation */\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t\t}\n\n\t/* Import the session key, either an actual session key context for PKCS \n\t   #15 v1.1 using direct-protected content or a generic-secret context\n\t   for PKCS #15 v1.2 using direct-protected-ext content */\n\tstatus = iCryptImportKey( encryptedKeyData, encryptedKeyDataSize, \n\t\t\t\t\t\t\t  CRYPT_FORMAT_CRYPTLIB, iKeyWrapContext,\n\t\t\t\t\t\t\t  iSessionKey, NULL );\n\tkrnlSendNotifier( iKeyWrapContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Translate any arg/attribute errors as before */\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise decryption and MAC contexts and keys from a generic-secret \n   context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) \\\nstatic int initKeys( IN_HANDLE const CRYPT_CONTEXT iGenericContext,\n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iMacContext,\n\t\t\t\t\t OUT_HANDLE_OPT CRYPT_CONTEXT *iMacAltContext,\n\t\t\t\t\t const QUERY_INFO *queryInfo )\n\t{\n\tCRYPT_CONTEXT iAuthEncCryptContext, iAuthEncMacContext;\n#ifdef MAC_KEYSIZE_BUG\n\tCRYPT_CONTEXT iAuthEncMacAltContext DUMMY_INIT;\n#endif /* MAC_KEYSIZE_BUG */\n\tCRYPT_ALGO_TYPE kdfAlgo DUMMY_INIT;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMECHANISM_KDF_INFO mechanismInfo;\n\tSTREAM stream;\n\tint kdfAlgoParam DUMMY_INIT, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iMacContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( iMacAltContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iGenericContext ) );\n\n\t/* Clear return values */\n\t*iCryptContext = *iMacContext = *iMacAltContext = CRYPT_ERROR;\n\n\t/* Recover the KDF information if it's present.  Early implementations\n\t   erroneously omitted the PBKDF2 AlgorithmIdentifier so we allow for\n\t   versions with or without this value.  Since the entries are skipped \n\t   it just means that there's two more values to skip:\n\n\t\tKdfParams ::= [ 0 ] SEQUENCE {\t\t\t-- 3.4.3 - 3.4.4.1\n\t\t\tsalt\t\t\tOCTET STRING SIZE(0),\n\t\t\titerationCount\tINTEGER (1),\n\t\t\tprf\t\t\t\tAlgorithmIdentifier\n\t\t\t} \n\n\t\tKdfParams ::= [ 0 ] SEQUENCE {\t\t\t-- Present if HMAC != SHA1\n\t\t\tpbkdf2\t\t\tOBJECT IDENTIFIER,\n\t\t\tSEQUENCE {\n\t\t\t\tsalt\t\tOCTET STRING SIZE(0),\n\t\t\t\titerationCount INTEGER (1),\n\t\t\t\tprf\t\t\tAlgorithmIdentifier\t-- HMAC-SHA2, etc\n\t\t\t\t}\n\t\t\t} */\n\tif( queryInfo->kdfParamLength > 0 )\n\t\t{\n\t\tsMemConnect( &stream, \n\t\t\t\t\t queryInfo->authEncParamData + queryInfo->kdfParamStart, \n\t\t\t\t\t queryInfo->kdfParamLength );\n\t\treadConstructed( &stream, NULL, 0 );\n\t\tif( peekTag( &stream ) == BER_OBJECT_IDENTIFIER )\n\t\t\t{\n\t\t\treadUniversal( &stream );\t\t/* OID */\n\t\t\treadSequence( &stream, NULL );\n\t\t\t}\n\t\treadUniversal( &stream );\t\t\t/* Salt */\n\t\tstatus = readShortInteger( &stream, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readAlgoIDex( &stream, &kdfAlgo, NULL,\n\t\t\t\t\t\t\t\t   &kdfAlgoParam, ALGOID_CLASS_HASH );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* The PBKDF2 default KDF is HMAC-SHA1 */\n\t\tkdfAlgo = CRYPT_ALGO_HMAC_SHA1;\n\t\tkdfAlgoParam = 0;\n\t\t}\n\n\t/* Recreate the encryption and MAC contexts used for the authenticated \n\t   encryption from the algorithm parameter data that was stored \n\t   alongside the generic-secret context parameter data */\n\tsMemConnect( &stream, \n\t\t\t\t queryInfo->authEncParamData + queryInfo->encParamStart,\n\t\t\t\t queryInfo->encParamLength );\n\tstatus = readContextAlgoID( &stream, &iAuthEncCryptContext, NULL, \n\t\t\t\t\t\t\t\tDEFAULT_TAG, ALGOID_CLASS_CRYPT );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, \n\t\t\t\t queryInfo->authEncParamData + queryInfo->macParamStart,\n\t\t\t\t queryInfo->macParamLength );\n\tstatus = readContextAlgoID( &stream, &iAuthEncMacContext, NULL, \n\t\t\t\t\t\t\t\tDEFAULT_TAG, ALGOID_CLASS_HASH );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Derive the encryption and MAC keys from the generic-secret key */\n\tsetMechanismKDFInfo( &mechanismInfo, iAuthEncCryptContext, \n\t\t\t\t\t\t iGenericContext, kdfAlgo, \"encryption\", 10 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMechanismKDFInfo( &mechanismInfo, iAuthEncMacContext, \n\t\t\t\t\t\t\t iGenericContext, kdfAlgo, \"authentication\", 14 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* MAC the EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier \n\t   information alongside the payload data to prevent an attacker from \n\t   manipulating the algorithm parameters to cause corruption that won't \n\t   be detected by the MAC on the payload data */\n\tstatus = krnlSendMessage( iAuthEncMacContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) queryInfo->authEncParamData,\n\t\t\t\t\t\t\t  queryInfo->authEncParamLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n#ifdef MAC_KEYSIZE_BUG\n\t/* Because of an error in setting the key size for the 3.4.0 cryptlib\n\t   release, private-key files created by this version use a 128-bit \n\t   HMAC-SHA1 key instead of a 160-bit one.  To work around this we \n\t   create a second MAC context with a 128-bit key and try that if the\n\t   initial check with the 160-bit key fails.\n\n\t   In addition the RFC draft that 3.4.0 was based on didn't MAC the\n\t   EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier, so we skip\n\t   MAC'ing that part of the data as well */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\tstatic const int macKeySize = bitsToBytes( 128 );\n\n\t\tiAuthEncMacAltContext = createInfo.cryptHandle;\n\t\tstatus = krnlSendMessage( iAuthEncMacAltContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &macKeySize, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMechanismKDFInfo( &mechanismInfo, iAuthEncMacAltContext, \n\t\t\t\t\t\t\t iGenericContext, CRYPT_ALGO_HMAC_SHA1, \n\t\t\t\t\t\t\t \"authentication\", 14 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_KDF,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PBKDF2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iAuthEncCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacContext, IMESSAGE_DECREFCOUNT );\n\t\tkrnlSendNotifier( iAuthEncMacAltContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iMacAltContext = iAuthEncMacAltContext;\n#endif /* MAC_KEYSIZE_BUG */\n\n\t*iCryptContext = iAuthEncCryptContext;\n\t*iMacContext = iAuthEncMacContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Verify the integrity of the encrypted key components and derive the final \n   decryption context from the generic intermediate context that's used to \n   derive the MAC and final decryption contexts.  This replaces the \n   intermediate context with the final decryption context */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 4, 6, 7 ) ) \\\nstatic int verifyEncKey( INOUT_HANDLE CRYPT_CONTEXT *iCryptContext,\n\t\t\t\t\t\t IN_BUFFER( encryptedContentLength ) \\\n\t\t\t\t\t\t\tconst void *encryptedContent, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int encryptedContentLength, \n\t\t\t\t\t\t IN_BUFFER( macValueLength ) \\\n\t\t\t\t\t\t\tconst void *macValue, \n\t\t\t\t\t\t IN_LENGTH_HASH const int macValueLength, \n\t\t\t\t\t\t const QUERY_INFO *queryInfo,\n\t\t\t\t\t\t OUT ERROR_INFO *errorInfo )\n\t{\n\tconst CRYPT_CONTEXT iOriginalCryptContext = *iCryptContext;\n\tCRYPT_CONTEXT iDerivedCryptContext, iMacContext, iMacAltContext;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( encryptedContent, encryptedContentLength ) );\n\tassert( isReadPtrDynamic( macValue, macValueLength ) );\n\tassert( isReadPtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iOriginalCryptContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( encryptedContentLength ) );\n\tREQUIRES( macValueLength >= MIN_HASHSIZE && \\\n\t\t\t  macValueLength <= CRYPT_MAX_HASHSIZE );\n\n\t/* Clear return value */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* We're using authenticated encryption so we have to apply an \n\t   intermediate step that transforms the generic-secret context into \n\t   distinct decryption and MAC contexts.  This also MACs the encryption \n\t   metadata that precedes the data payload */\n\tstatus = initKeys( iOriginalCryptContext, &iDerivedCryptContext, \n\t\t\t\t\t   &iMacContext, &iMacAltContext, queryInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't recreate encryption and MAC keys needed to \"\n\t\t\t\t  \"unwrap the private key\" ) );\n\t\t}\n\n\t/* Verify the integrity of the encrypted private key before trying to \n\t   process it */\n\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) encryptedContent, \n\t\t\t\t\t\t\t  encryptedContentLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) macValue, \n\t\t\t\t\t\tmacValueLength );\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_HASH );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* A failed MAC check is reported as a CRYPT_ERROR comparison \n\t\t\t   result so we have to convert it to a more appropriate status \n\t\t\t   code */\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t}\n\t\t}\n#ifdef MAC_KEYSIZE_BUG\n\tif( status == CRYPT_ERROR_SIGNATURE )\n\t\t{\n\t\t/* If we got a failed MAC check, try again with a MAC context with a \n\t\t   128-bit MAC key, a bug in cryptlib version 3.4.0 */\n\t\tstatus = krnlSendMessage( iMacAltContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) encryptedContent, \n\t\t\t\t\t\t\t\t  encryptedContentLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( iMacAltContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) macValue, \n\t\t\t\t\t\t\tmacValueLength );\n\t\t\tstatus = krnlSendMessage( iMacAltContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_HASH );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* A failed MAC check is reported as a CRYPT_ERROR \n\t\t\t\t   comparison result so we have to convert it to a more \n\t\t\t\t   appropriate status code */\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tkrnlSendNotifier( iMacAltContext, IMESSAGE_DECREFCOUNT );\n#endif /* MAC_KEYSIZE_BUG */\n\tkrnlSendNotifier( iMacContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We convert any failure status encountered at this point into a \n\t\t   generic signature-check failure, which makes explicit what's \n\t\t   going on */\n\t\tretExt( CRYPT_ERROR_SIGNATURE, \n\t\t\t\t( CRYPT_ERROR_SIGNATURE, errorInfo, \n\t\t\t\t  \"Private-key integrity check failed\" ) );\n\t\t}\n\n\t/* Replace the original encryption context with the derived one */\n\tkrnlSendNotifier( iOriginalCryptContext, IMESSAGE_DECREFCOUNT );\n\t*iCryptContext = iDerivedCryptContext;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read private-key components from a PKCS #15 object entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nint readPrivateKeyComponents( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iPrivKeyContext,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( passwordLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *password, \n\t\t\t\t\t\t\t  IN_LENGTH_NAME_Z const int passwordLength, \n\t\t\t\t\t\t\t  const BOOLEAN isStorageObject, \n\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iCryptContext;\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tQUERY_INFO queryInfo DUMMY_INIT_STRUCT, contentQueryInfo;\n\tSTREAM stream;\n\tBYTE macValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBOOLEAN isAuthEnc = FALSE;\n\tconst int privKeyStartOffset = pkcs15infoPtr->privKeyOffset;\n\tconst int privKeyTotalSize = pkcs15infoPtr->privKeyDataSize;\n\tvoid *encryptedKey, *encryptedContent DUMMY_INIT_PTR;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint encryptedContentLength DUMMY_INIT, macValueLength DUMMY_INIT;\n\tint checksum, tag, status;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( ( isStorageObject && \\\n\t\t\t  password == NULL && passwordLength == 0 ) || \\\n\t\t\t( !isStorageObject && \\\n\t\t\t  isReadPtrDynamic( password, passwordLength ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iPrivKeyContext ) );\n\tREQUIRES( ( isStorageObject && \\\n\t\t\t\tpassword == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( !isStorageObject && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( isStorageObject == TRUE || isStorageObject == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Skip the outer wrapper, version number, and header for the SET OF \n\t   EncryptionInfo, and query the exported key information to determine \n\t   the parameters required to reconstruct the decryption key */\n\tREQUIRES( boundsCheck( privKeyStartOffset, \n\t\t\t\t\t\t   privKeyTotalSize - privKeyStartOffset,\n\t\t\t\t\t\t   privKeyTotalSize ) );\n\tsMemConnect( &stream,\n\t\t\t\t ( BYTE * ) pkcs15infoPtr->privKeyData + privKeyStartOffset,\n\t\t\t\t privKeyTotalSize - privKeyStartOffset );\n\tstatus = tag = peekTag( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isStorageObject )\n\t\t{\n\t\tBYTE storageID[ KEYID_SIZE + 8 ];\n\t\tint length;\n\n\t\t/* If this is a PKCS #15 storage object then it'll contain only \n\t\t   private-key metadata with the content being merely a reference\n\t\t   to external hardware, so we just read the storage object\n\t\t   reference and save it to the dummy context */\n\t\tif( tag != BER_SEQUENCE )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Expected device storage ID, not item type %02X\",\n\t\t\t\t\t  tag ) );\n\t\t\t}\n\t\treadSequence( &stream, NULL );\n\t\tstatus = readOctetString( &stream, storageID, &length, \n\t\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsetMessageData( &msgData, storageID, KEYID_SIZE );\n\t\treturn( krnlSendMessage( iPrivKeyContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_DEVICESTORAGEID ) );\n\t\t}\n\tif( tag == MAKE_CTAG( CTAG_OV_DIRECTPROTECTED_EXT ) )\n\t\tisAuthEnc = TRUE;\n\telse\n\t\t{\n\t\tif( tag != MAKE_CTAG( CTAG_OV_DIRECTPROTECTED ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTAVAIL, \n\t\t\t\t\t( CRYPT_ERROR_NOTAVAIL, errorInfo, \n\t\t\t\t\t  \"Unrecognised private-key protection type %02X\", \n\t\t\t\t\t  tag ) );\n\t\t\t}\n\t\t}\n\treadConstructed( &stream, NULL, \n\t\t\t\t\t isAuthEnc ? CTAG_OV_DIRECTPROTECTED_EXT : \\\n\t\t\t\t\t\t\t\t CTAG_OV_DIRECTPROTECTED );\n\treadShortInteger( &stream, NULL );\n\tstatus = readSet( &stream, NULL );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = queryAsn1Object( &stream, &queryInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\tqueryInfo.type != CRYPT_OBJECT_ENCRYPTED_KEY )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid encrypted private key data header\" ) );\n\t\t}\n\tstatus = sMemGetDataBlock( &stream, &encryptedKey, queryInfo.size );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readUniversal( &stream );\t/* Skip the exported key */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"queryAsn1Object\" );\n\n\t/* Read the header for the encrypted key and make sure that all of the\n\t   encrypted key data (and the trailing MAC value if we're using \n\t   authenticated encryption) is present in the stream */\n\tstatus = readCMSencrHeader( &stream, dataOIDinfo, \n\t\t\t\tFAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ), NULL,\n\t\t\t\t&iCryptContext, &contentQueryInfo, isAuthEnc ? \\\n\t\t\t\t\tREADCMS_FLAG_AUTHENC | READCMS_FLAG_DEFINITELENGTH : \\\n\t\t\t\t\tREADCMS_FLAG_DEFINITELENGTH );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tencryptedContentLength = contentQueryInfo.size;\n\t\tif( !isShortIntegerRangeNZ( encryptedContentLength ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = sMemGetDataBlock( &stream, &encryptedContent, \n\t\t\t\t\t\t\t\t\t   encryptedContentLength );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = sSkip( &stream, encryptedContentLength, \n\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( encryptedContentLength < MIN_OBJECT_SIZE || \\\n\t\t\t  encryptedContentLength > MAX_INTLENGTH_SHORT ) )\n\t\t\t{\n\t\t\t/* Too-small object */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && isAuthEnc )\n\t\t{\n\t\t/* If we're using authenticated encryption then the encrypted key \n\t\t   data is followed by a MAC value */\n\t\tstatus = readOctetString( &stream, macValue, &macValueLength, \n\t\t\t\t\t\t\t\t  MIN_HASHSIZE, CRYPT_MAX_HASHSIZE );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\tzeroise( &contentQueryInfo, sizeof( QUERY_INFO ) );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid encrypted private key data\" ) );\n\t\t}\n\tANALYSER_HINT( encryptedContent != NULL );\n\tchecksum = checksumData( encryptedContent, encryptedContentLength );\n\tCFI_CHECK_UPDATE( \"readCMSencrHeader\" );\n\n\t/* Import the session key using the user password */\n\tstatus = importSessionKey( iCryptContext, encryptedKey, queryInfo.size, \n\t\t\t\t\t\t\t   password, passwordLength, &queryInfo );\n\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tzeroise( &contentQueryInfo, sizeof( QUERY_INFO ) );\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't import the session key used to protect the \"\n\t\t\t\t  \"private key\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"importSessionKey\" );\n\n\t/* If we're using authenticated encryption then we have to use an \n\t   intermediate step that transforms the generic-secret context into \n\t   distinct decryption and MAC contexts.  This also MACs the \n\t   encryption metadata that precedes the data payload */\n\tif( isAuthEnc )\n\t\t{\n\t\tstatus = verifyEncKey( &iCryptContext, encryptedContent, \n\t\t\t\t\t\t\t   encryptedContentLength, macValue, \n\t\t\t\t\t\t\t   macValueLength, &contentQueryInfo, \n\t\t\t\t\t\t\t   errorInfo );\n\t\tzeroise( &contentQueryInfo, sizeof( QUERY_INFO ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\tzeroise( &contentQueryInfo, sizeof( QUERY_INFO ) );\n\tCFI_CHECK_UPDATE( \"verifyEncKey\" );\n\n\t/* Import the encrypted key into the PKC context */\n\tsetMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST ) encryptedContent,\n\t\t\t\t\t\t  encryptedContentLength, NULL, 0, iPrivKeyContext,\n\t\t\t\t\t\t  iCryptContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );\n\tclearMechanismInfo( &mechanismInfo );\n\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We can end up here due to a whole range of possible low-level \n\t\t   problems, to make things easier on the caller we provide a \n\t\t   somewhat more detailed breakdown of possible causes */\n\t\tswitch( status )\n\t\t\t{\n\t\t\tcase CRYPT_ERROR_WRONGKEY:\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Couldn't unwrap private key, probably due to \"\n\t\t\t\t\t\t  \"incorrect decryption key being used\" ) );\n\n\t\t\tcase CRYPT_ERROR_BADDATA:\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Private key data corrupted or invalid\" ) );\n\n\t\t\tcase CRYPT_ERROR_INVALID:\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Private key components failed validity check\" ) );\n\n\t\t\tdefault:\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t\t  \"Couldn't unwrap/import private key\" ) );\n\t\t\t}\n\t\t}\n\tif( checksumData( encryptedContent, \n\t\t\t\t\t  encryptedContentLength ) != checksum )\n\t\t{\n\t\t/* The encrypted private-key data was corrupted between the MAC \n\t\t   check and when it was decrypted and loaded into the context, we \n\t\t   can't trust the key */\n\t\tDEBUG_DIAG(( \"Encrypted private-key data memory corruption detected\" ));\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_IMPORT\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"queryAsn1Object\", \"readCMSencrHeader\", \n\t\t\t\t\t\t\t\t\t\"importSessionKey\", \"verifyEncKey\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_IMPORT\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #15 Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Copy any new object ID information that we've just read across to the \n   object information */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void copyObjectIdInfo( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t  const PKCS15_INFO *pkcs15objectInfo )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );\n\n\t/* If any new ID information has become available, copy it over.  The \n\t   keyID defaults to the iD so we only copy the newly-read keyID over if \n\t   it's something other than the existing iD */\n\tif( pkcs15objectInfo->keyIDlength > 0 && \\\n\t\t( pkcs15infoPtr->iDlength != pkcs15objectInfo->keyIDlength || \\\n\t\t  memcmp( pkcs15infoPtr->iD, pkcs15objectInfo->keyID,\n\t\t\t\t  pkcs15objectInfo->keyIDlength ) ) )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->keyIDlength, 1, \n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( pkcs15infoPtr->keyID, pkcs15objectInfo->keyID,\n\t\t\t\tpkcs15objectInfo->keyIDlength );\n\t\tpkcs15infoPtr->keyIDlength = pkcs15objectInfo->keyIDlength;\n\t\t}\n\tif( pkcs15objectInfo->iAndSIDlength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->iAndSIDlength, 1, \n\t\t\t\t\t\t\t\tKEYID_SIZE ) );\n\t\tmemcpy( pkcs15infoPtr->iAndSID, pkcs15objectInfo->iAndSID,\n\t\t\t\tpkcs15objectInfo->iAndSIDlength );\n\t\tpkcs15infoPtr->iAndSIDlength = pkcs15objectInfo->iAndSIDlength;\n\t\t}\n\tif( pkcs15objectInfo->subjectNameIDlength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->subjectNameIDlength, 1, \n\t\t\t\t\t\t\t\tKEYID_SIZE ) );\n\t\tmemcpy( pkcs15infoPtr->subjectNameID, pkcs15objectInfo->subjectNameID,\n\t\t\t\tpkcs15objectInfo->subjectNameIDlength );\n\t\tpkcs15infoPtr->subjectNameIDlength = pkcs15objectInfo->subjectNameIDlength;\n\t\t}\n\tif( pkcs15objectInfo->issuerNameIDlength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->issuerNameIDlength, 1, \n\t\t\t\t\t\t\t\tKEYID_SIZE ) );\n\t\tmemcpy( pkcs15infoPtr->issuerNameID, pkcs15objectInfo->issuerNameID,\n\t\t\t\tpkcs15objectInfo->issuerNameIDlength );\n\t\tpkcs15infoPtr->issuerNameIDlength = pkcs15objectInfo->issuerNameIDlength;\n\t\t}\n\tif( pkcs15objectInfo->pgp2KeyIDlength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->pgp2KeyIDlength, 1, \n\t\t\t\t\t\t\t\tPGP_KEYID_SIZE ) );\n\t\tmemcpy( pkcs15infoPtr->pgp2KeyID, pkcs15objectInfo->pgp2KeyID,\n\t\t\t\tpkcs15objectInfo->pgp2KeyIDlength );\n\t\tpkcs15infoPtr->pgp2KeyIDlength = pkcs15objectInfo->pgp2KeyIDlength;\n\t\t}\n\tif( pkcs15objectInfo->openPGPKeyIDlength > 0 )\n\t\t{\n\t\tREQUIRES_V( rangeCheck( pkcs15objectInfo->openPGPKeyIDlength, 1, \n\t\t\t\t\t\t\t\tPGP_KEYID_SIZE ) );\n\t\tmemcpy( pkcs15infoPtr->openPGPKeyID, pkcs15objectInfo->openPGPKeyID,\n\t\t\t\tpkcs15objectInfo->openPGPKeyIDlength );\n\t\tpkcs15infoPtr->openPGPKeyIDlength = pkcs15objectInfo->openPGPKeyIDlength;\n\t\t}\n\t}\n\n/* Copy any new object payload information that we've just read across to \n   the object information */\n\nSTDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int copyObjectPayloadInfo( INOUT PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t\t\t  const PKCS15_INFO *pkcs15objectInfo,\n\t\t\t\t\t\t\t\t  IN_BUFFER( objectLength ) const void *object, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int objectLength,\n\t\t\t\t\t\t\t\t  IN_ENUM( PKCS15_OBJECT ) \\\n\t\t\t\t\t\t\t\t\tconst PKCS15_OBJECT_TYPE type )\n\t{\n\tassert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );\n\tassert( isReadPtrDynamic( object, objectLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( objectLength ) );\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\n\tswitch( type )\n\t\t{\n\t\tcase PKCS15_OBJECT_PUBKEY:\n\t\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;\n\t\t\tpkcs15infoPtr->pubKeyData = ( void * ) object;\n\t\t\tpkcs15infoPtr->pubKeyDataSize = objectLength;\n\t\t\tpkcs15infoPtr->pubKeyOffset = pkcs15objectInfo->pubKeyOffset;\n\t\t\tpkcs15infoPtr->pubKeyUsage = pkcs15objectInfo->pubKeyUsage;\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_PRIVKEY:\n\t\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;\n\t\t\tpkcs15infoPtr->privKeyData = ( void * ) object;\n\t\t\tpkcs15infoPtr->privKeyDataSize = objectLength;\n\t\t\tpkcs15infoPtr->privKeyOffset = pkcs15objectInfo->privKeyOffset;\n\t\t\tpkcs15infoPtr->privKeyUsage = pkcs15objectInfo->privKeyUsage;\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_CERT:\n\t\t\tif( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )\n\t\t\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;\n\t\t\tpkcs15infoPtr->certData = ( void * ) object;\n\t\t\tpkcs15infoPtr->certDataSize = objectLength;\n\t\t\tpkcs15infoPtr->certOffset = pkcs15objectInfo->certOffset;\n\t\t\tpkcs15infoPtr->trustedUsage = pkcs15objectInfo->trustedUsage;\n\t\t\tpkcs15infoPtr->implicitTrust = pkcs15objectInfo->implicitTrust;\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_SECRETKEY:\n\t\t\t/* We don't try and return an error for this, it's not something\n\t\t\t   that we can make use of but if it's ever reached it just ends \n\t\t\t   up as an empty (non-useful) object entry */\n\t\t\tDEBUG_DIAG(( \"Found secret-key object\" ));\n\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_DATA:\n\t\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;\n\t\t\tpkcs15infoPtr->dataType = pkcs15objectInfo->dataType;\n\t\t\tpkcs15infoPtr->dataData = ( void * ) object;\n\t\t\tpkcs15infoPtr->dataDataSize = objectLength;\n\t\t\tpkcs15infoPtr->dataOffset = pkcs15objectInfo->dataOffset;\n\t\t\tbreak;\n\n\t\tcase PKCS15_OBJECT_UNRECOGNISED:\n\t\t\t/* This is a placeholder for an unrecognised object subtype such\n\t\t\t   as a certificate object whose subtype is SPKI or WTLS or \n\t\t\t   X9.68, we record it as such and remember the data contents but \n\t\t\t   leave it as an empty (non-useful) object entry */\n\t\t\tDEBUG_DIAG(( \"Found unrecognised object subtype\" ));\n\t\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_UNRECOGNISED;\n\t\t\tpkcs15infoPtr->dataType = CRYPT_ATTRIBUTE_NONE;\n\t\t\tpkcs15infoPtr->dataData = ( void * ) object;\n\t\t\tpkcs15infoPtr->dataDataSize = objectLength;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* We don't try and return an error for this, it's not something\n\t\t\t   that we can make use of but if it's ever reached it just ends \n\t\t\t   up as an empty (non-useful) object entry */\n\t\t\tDEBUG_DIAG(( \"Found unknown object type %d\", type ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tbreak;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead a Keyset\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a single object in a keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \\\nstatic int readObject( INOUT STREAM *stream, \n\t\t\t\t\t   OUT PKCS15_INFO *pkcs15objectInfo, \n\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( *objectLengthPtr ) void **objectPtrPtr, \n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *objectLengthPtr,\n\t\t\t\t\t   IN_ENUM( PKCS15_OBJECT ) const PKCS15_OBJECT_TYPE type, \n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tSTREAM objectStream;\n\tvoid *objectData;\n\tint objectLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( pkcs15objectInfo, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( objectPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( objectLengthPtr, sizeof( int ) ) );\n\t\n\tREQUIRES( isEnumRange( type, PKCS15_OBJECT ) );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return values */\n\tmemset( pkcs15objectInfo, 0, sizeof( PKCS15_INFO ) );\n\t*objectPtrPtr = NULL;\n\t*objectLengthPtr = 0;\n\n\t/* Read the current object's data */\n\tstatus = readRawObjectAlloc( stream, &objectData, &objectLength,\n\t\t\t\t\t\t\t\t MIN_OBJECT_SIZE, MAX_INTLENGTH_SHORT - 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't read PKCS #15 object data\" ) );\n\t\t}\n\tANALYSER_HINT( objectData != NULL );\n\n\t/* Read the object attributes from the in-memory object data */\n\tsMemConnect( &objectStream, objectData, objectLength );\n\tstatus = readObjectAttributes( &objectStream, pkcs15objectInfo, type, \n\t\t\t\t\t\t\t\t   errorInfo );\n\tsMemDisconnect( &objectStream );\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t{\n\t\tclFree( \"readObject\", objectData );\n\t\treturn( status );\n\t\t}\n\n\t/* Remember the encoded object data */\n\t*objectPtrPtr = objectData;\n\t*objectLengthPtr = objectLength;\n\n\treturn( status );\n\t}\n\n/* Read an entire keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nint readPkcs15Keyset( INOUT STREAM *stream, \n\t\t\t\t\t  OUT_ARRAY( maxNoPkcs15objects ) PKCS15_INFO *pkcs15info, \n\t\t\t\t\t  IN_LENGTH_SHORT const int maxNoPkcs15objects, \n\t\t\t\t\t  IN_LENGTH const long endPos,\n\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * \\\n\t\t\t\t\t\t\t\t\tmaxNoPkcs15objects ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( maxNoPkcs15objects ) );\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( pkcs15info, 0, sizeof( PKCS15_INFO ) * maxNoPkcs15objects );\n\n\t/* Scan all of the objects in the keyset */\n\tLOOP_MED_INITCHECK( status = CRYPT_OK, \n\t\t\t\t\t\tcryptStatusOK( status ) && stell( stream ) < endPos )\n\t\t{\n\t\tstatic const MAP_TABLE tagToTypeTbl[] = {\n\t\t\t{ CTAG_PO_PRIVKEY, PKCS15_OBJECT_PRIVKEY },\n\t\t\t{ CTAG_PO_PUBKEY, PKCS15_OBJECT_PUBKEY },\n\t\t\t{ CTAG_PO_TRUSTEDPUBKEY, PKCS15_OBJECT_PUBKEY },\n\t\t\t{ CTAG_PO_SECRETKEY, PKCS15_OBJECT_SECRETKEY },\n\t\t\t{ CTAG_PO_CERT, PKCS15_OBJECT_CERT },\n\t\t\t{ CTAG_PO_TRUSTEDCERT, PKCS15_OBJECT_CERT },\n\t\t\t{ CTAG_PO_USEFULCERT, PKCS15_OBJECT_CERT },\n\t\t\t{ CTAG_PO_DATA, PKCS15_OBJECT_DATA },\n\t\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t\t};\n\t\tPKCS15_OBJECT_TYPE type = PKCS15_OBJECT_NONE;\n\t\tint tag, value DUMMY_INIT, innerEndPos, LOOP_ITERATOR_ALT;\n\n\t\t/* Map the object tag to a PKCS #15 object type */\n\t\tstatus = tag = peekTag( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\treturn( status );\n\t\t\t}\n\t\ttag = EXTRACT_CTAG( tag );\n\t\tif( tag < CTAG_PO_PRIVKEY || tag >= CTAG_PO_LAST )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\telse\n\t\t\t{\n\t\t\tstatus = mapValue( tag, &value, tagToTypeTbl,\n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( tagToTypeTbl, MAP_TABLE ) );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid PKCS #15 object type %02X\", tag ) );\n\t\t\t}\n\t\ttype = value;\n\n\t\t/* Read the [n] [0] wrapper to find out what we're dealing with.  \n\t\t   Note that we set the upper limit at MAX_BUFFER_SIZE rather than\n\t\t   MAX_INTLENGTH_SHORT because some keysets with many large objects \n\t\t   may have a combined group-of-objects length larger than \n\t\t   MAX_INTLENGTH_SHORT */\n\t\treadConstructed( stream, NULL, tag );\n\t\tstatus = readConstructed( stream, &innerEndPos, CTAG_OV_DIRECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( innerEndPos < MIN_OBJECT_SIZE || innerEndPos >= MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid PKCS #15 object data size %d\", \n\t\t\t\t\t  innerEndPos ) );\n\t\t\t}\n\t\tinnerEndPos += stell( stream );\n\n\t\t/* Scan all objects of this type */\n\t\tLOOP_LARGE_CHECK_ALT( stell( stream ) < innerEndPos )\n\t\t\t{\n\t\t\tPKCS15_INFO pkcs15objectInfo, *pkcs15infoPtr = NULL;\n\t\t\tvoid *object;\n\t\t\tint objectLength;\n\n\t\t\t/* Read the object */\n\t\t\tstatus = readObject( stream, &pkcs15objectInfo, &object,\n\t\t\t\t\t\t\t\t &objectLength, type, errorInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status != OK_SPECIAL )\n\t\t\t\t\t{\n\t\t\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n\n\t\t\t\t/* We read an object that we don't know what to do with, \n\t\t\t\t   change the effective type to a placeholder */\n\t\t\t\ttype = PKCS15_OBJECT_UNRECOGNISED;\n\t\t\t\t}\n\t\t\tANALYSER_HINT( object != NULL );\n\n\t\t\t/* If we read an object with associated ID information, find out \n\t\t\t   where to add the object data */\n\t\t\tif( pkcs15objectInfo.iDlength > 0 )\n\t\t\t\t{\n\t\t\t\tpkcs15infoPtr = findEntry( pkcs15info, maxNoPkcs15objects, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_KEYIDEX_ID, \n\t\t\t\t\t\t\t\t\t\t   pkcs15objectInfo.iD,\n\t\t\t\t\t\t\t\t\t\t   pkcs15objectInfo.iDlength,\n\t\t\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_NONE, FALSE );\n\t\t\t\t}\n\t\t\tif( pkcs15infoPtr == NULL )\n\t\t\t\t{\n\t\t\t\tint index;\n\n\t\t\t\t/* This personality isn't present yet, find out where we can \n\t\t\t\t   add the object data and copy the fixed object information \n\t\t\t\t   over */\n\t\t\t\tpkcs15infoPtr = findFreeEntry( pkcs15info, \n\t\t\t\t\t\t\t\t\t\t\t   maxNoPkcs15objects, &index );\n\t\t\t\tif( pkcs15infoPtr == NULL )\n\t\t\t\t\t{\n\t\t\t\t\tclFree( \"readKeyset\", object );\n\t\t\t\t\tpkcs15Free( pkcs15info, maxNoPkcs15objects );\n\t\t\t\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, errorInfo, \n\t\t\t\t\t\t\t  \"No more room in keyset to add further items\" ) );\n\t\t\t\t\t}\n\t\t\t\tmemcpy( pkcs15infoPtr, &pkcs15objectInfo, \n\t\t\t\t\t\tsizeof( PKCS15_INFO ) );\n\t\t\t\tpkcs15infoPtr->index = index;\n\t\t\t\t}\n\n\t\t\t/* Copy over any ID information */\n\t\t\tcopyObjectIdInfo( pkcs15infoPtr, &pkcs15objectInfo );\n\n\t\t\t/* Copy over any other new information that may have become\n\t\t\t   available.  The semantics when multiple date ranges are \n\t\t\t   present (for example one for a key and one for a certificate) \n\t\t\t   are a bit uncertain, we use the most recent date available on \n\t\t\t   the assumption that this reflects the newest information */\n\t\t\tif( pkcs15objectInfo.validFrom > pkcs15infoPtr->validFrom )\n\t\t\t\tpkcs15infoPtr->validFrom = pkcs15objectInfo.validFrom;\n\t\t\tif( pkcs15objectInfo.validTo > pkcs15infoPtr->validTo )\n\t\t\t\tpkcs15infoPtr->validTo = pkcs15objectInfo.validTo;\n\n\t\t\t/* Copy the payload over */\n\t\t\tcopyObjectPayloadInfo( pkcs15infoPtr, &pkcs15objectInfo,\n\t\t\t\t\t\t\t\t   object, objectLength, type );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_set.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t   cryptlib PKCS #15 Set-item Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether we can add anything to a PKCS #15 personality */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 8, 9 ) ) \\\nstatic int checkAddInfo( const PKCS15_INFO *pkcs15infoPtr,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t const BOOLEAN isCertChain, \n\t\t\t\t\t\t const BOOLEAN privkeyPresent,\n\t\t\t\t\t\t const BOOLEAN certPresent,\n\t\t\t\t\t\t const BOOLEAN pkcs15keyPresent,\n\t\t\t\t\t\t const BOOLEAN pkcs15certPresent,\n\t\t\t\t\t\t OUT BOOLEAN *isCertUpdate, \n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tBOOLEAN unneededCert, unneededKey;\n\tint status;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( isCertUpdate, sizeof( BOOLEAN ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( isCertChain == TRUE || isCertChain == FALSE );\n\tREQUIRES( privkeyPresent == TRUE || privkeyPresent == FALSE );\n\tREQUIRES( certPresent == TRUE || certPresent == FALSE );\n\tREQUIRES( pkcs15keyPresent == TRUE || pkcs15keyPresent == FALSE );\n\tREQUIRES( pkcs15certPresent == TRUE || pkcs15certPresent == FALSE );\n\tREQUIRES( errorInfo != NULL );\n\n\t/* Clear return value */\n\t*isCertUpdate = FALSE;\n\n\t/* Check what we can update (if anything) */\n\tunneededKey = privkeyPresent & pkcs15keyPresent;\n\tunneededCert = certPresent & pkcs15certPresent;\n\tif( ( ( unneededCert && !privkeyPresent ) || \\\n\t\t  ( unneededKey && unneededCert ) ) && \\\n\t\tpkcs15infoPtr->validTo > MIN_TIME_VALUE )\n\t\t{\n\t\ttime_t validTo;\n\n\t\t/* The certificate would be a duplicate, see if it's more recent \n\t\t   than the existing one.  We only perform this check if there's a \n\t\t   validTo time stored for the certificate since without this \n\t\t   restriction any certificate without a stored time could be \n\t\t   overwritten */\n\t\tsetMessageData( &msgData, &validTo, sizeof( time_t ) );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDTO );\n\t\tif( cryptStatusOK( status ) && validTo > pkcs15infoPtr->validTo )\n\t\t\t{\n\t\t\ttime_t validFrom;\n\n\t\t\t/* It's a newer certificate, don't treat it as a duplicate.  \n\t\t\t   This check is effectively impossible to perform automatically \n\t\t\t   since there are an infinite number of variations that have to \n\t\t\t   be taken into account, for example a certificate for the same \n\t\t\t   key issued by a different CA, same CA but it's changed the \n\t\t\t   bits it sets in the keyUsage (digitalSignature vs.\n\t\t\t   nonRepudiation), slightly different issuer DN (Thawte \n\t\t\t   certificates with a date encoded in the DN), and so on and so \n\t\t\t   on.  Because this really requires manual processing by a \n\t\t\t   human we don't even try and sort it all out but just allow a \n\t\t\t   certificate for a given key (checked by the ID match) to be \n\t\t\t   replaced by a newer certificate for the same key.  This is \n\t\t\t   restrictive enough to prevent most obviously-wrong \n\t\t\t   replacements while being permissive enough to allow most \n\t\t\t   probably-OK replacements */\n\t\t\tunneededCert = FALSE;\n\t\t\t*isCertUpdate = TRUE;\n\n\t\t\t/* There's one special-case situation in which odd things can \n\t\t\t   happen when updating certificates and that's when adding a \n\t\t\t   future-dated certificate, which would result in the \n\t\t\t   certificate being replaced with one that can't be used yet.  \n\t\t\t   There's no clean way to handle this because in order to know \n\t\t\t   what to do we'd have to be able to guess the intent of the \n\t\t\t   user, however for anything but signature certificates it's \n\t\t\t   likely that the hit-and-miss certificate checking performed \n\t\t\t   by most software won't even notice a future-dated \n\t\t\t   certificate, and for signature certificates the semantics of \n\t\t\t   signing data now using a certificate that isn't valid yet are \n\t\t\t   somewhat uncertain.  Since in most cases no-one will even \n\t\t\t   notice the problem, we throw an exception in the debug build \n\t\t\t   but don't do anything in release builds.  This is probably \n\t\t\t   less annoying to users than having the code reject an \n\t\t\t   otherwise-valid future-dated certificate.  If anyone ever\n\t\t\t   complains about this then we can ask the users at that time\n\t\t\t   what sort of behaviour they're prefer */\n\t\t\tsetMessageData( &msgData, &validFrom, sizeof( time_t ) );\n\t\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_VALIDFROM );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\tvalidFrom > getApproxTime() + 86400L )\n\t\t\t\t{\n\t\t\t\tDEBUG_DIAG(( \"Attempt to replace certificate with \"\n\t\t\t\t\t\t\t \"future-dated certificate\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Make sure that we can update at least one of the objects in the PKCS \n\t   #15 personality */\n\tif( ( unneededKey && !certPresent ) ||\t\t/* Key only, duplicate */\n\t\t( unneededCert && !privkeyPresent ) ||\t/* Certificate only, duplicate */\n\t\t( unneededKey && unneededCert ) )\t\t/* Key+certificate, duplicate */\n\t\t{\n\t\t/* If it's anything other than a certificate chain, we can't add \n\t\t   anything */\n\t\tif( !isCertChain )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t\t( CRYPT_ERROR_DUPLICATE, errorInfo, \n\t\t\t\t\t  \"No new data to add\" ) );\n\t\t\t}\n\n\t\t/* Tell the caller that it's an opportunistic certificate-chain \n\t\t   update */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAdd a Key\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add an item to the PKCS #15 keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int setItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\tIN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\tIN_BUFFER_OPT( passwordLength ) const char *password, \n\t\t\t\t\t\t\tIN_LENGTH_NAME_Z const int passwordLength,\n\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int flags )\n\t{\n\tCRYPT_CERTIFICATE iCryptCert DUMMY_INIT;\n\tPKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tPKCS15_INFO *pkcs15infoPtr;\n\tMESSAGE_DATA msgData;\n\tBYTE iD[ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst BOOLEAN isStorageObject = \\\n\t\t\t( keysetInfoPtr->keysetFile->iHardwareDevice != CRYPT_UNUSED ) ? \\\n\t\t\tTRUE : FALSE;\n\tBOOLEAN certPresent = FALSE, privkeyPresent = FALSE;\n\tBOOLEAN pkcs15certPresent = FALSE, pkcs15keyPresent = FALSE;\n\tBOOLEAN isCertChain = FALSE, isCertUpdate = FALSE;\n\tconst int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;\n\tint pkcs15index = CRYPT_ERROR, iDsize, value, status;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY || \\\n\t\t\t  itemType == KEYMGMT_ITEM_KEYMETADATA );\n\tREQUIRES( ( password == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( password != NULL && \\\n\t\t\t\tpasswordLength >= MIN_NAME_LENGTH && \\\n\t\t\t\tpasswordLength < MAX_ATTRIBUTE_SIZE ) );\n\tREQUIRES( ( ( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\t  itemType == KEYMGMT_ITEM_KEYMETADATA ) && \\\n\t\t\t\tpassword == NULL && passwordLength == 0 ) || \\\n\t\t\t  ( ( itemType == KEYMGMT_ITEM_PRIVATEKEY || \\\n\t\t\t\t  itemType == KEYMGMT_ITEM_SECRETKEY ) && \\\n\t\t\t\tpassword != NULL && passwordLength != 0 ) );\n\tREQUIRES( ( isStorageObject && \\\n\t\t\t\t( itemType == KEYMGMT_ITEM_PUBLICKEY || \\\n\t\t\t\t  itemType == KEYMGMT_ITEM_KEYMETADATA ) ) || \\\n\t\t\t   ( !isStorageObject && \\\n\t\t\t     itemType != KEYMGMT_ITEM_KEYMETADATA ) );\n\tREQUIRES( flags == KEYMGMT_FLAG_NONE );\n\tENSURES( pkcs15info != NULL );\n\n\t/* If we're being sent a secret key, add it to the PKCS #15 keyset and \n\t   exit */\n\tif( itemType == KEYMGMT_ITEM_SECRETKEY )\n\t\treturn( addSecretKey( pkcs15info, noPkcs15objects, cryptHandle ) );\n\n\t/* Check the object, extract ID information from it, and determine\n\t   whether it's a standalone certificate (which produces a PKCS #15 \n\t   certificate object) or a private-key context (which produces a PKCS \n\t   #15 private key object and either a PKCS #15 public-key object (if \n\t   there's no certificate present) or a certificate object (if there's \n\t   a certificate present)).  If it's a dummy context being used to\n\t   store key metadata then it won't necessarily be usable for encryption\n\t   operations so we skip the initial check in this case, the kernel will\n\t   already have performed the basic type check.\n\n\t   Note that we don't allow the addition of standalone public keys\n\t   (without corresponding private keys) since these keysets are private-\n\t   key keysets and not general-purpose public key exchange mechanisms.\n\t   Without this safeguard some users would use them as a general public-\n\t   key store in place of database keysets or (more rarely) as a type of \n\t   unsigned certificate for exchanging public keys.\n\t   \n\t   In addition allowing the storage of standalone public keys is rather \n\t   problematic since they need to have a label attached in order to be \n\t   identified so performing a public-key add with a private-key context \n\t   would work but performing one with a public-key context would fail.  \n\t   A certificate update on this public-key-only item would result in the \n\t   presence a private-key-labelled certificate, which is even more \n\t   strange for users to comprehend.  To keep things sensible we \n\t   therefore disallow the addition of standalone public keys */\n\tif( itemType != KEYMGMT_ITEM_KEYMETADATA )\n\t\t{\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\t\tprivkeyPresent = checkContextCapability( cryptHandle, \n\t\t\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_PRIVATE );\n\t\t}\n\telse\n\t\t{\n\t\t/* Private-key metadata implicitly has a private key present even\n\t\t   if it's not explicitly present in the dummy context */\n\t\tprivkeyPresent = TRUE;\n\t\t}\n\tsetMessageData( &msgData, iD, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiDsize = msgData.length;\n\n\t/* If the object being added isn't a generic public key/certificate and \n\t   is bound to crypto hardware, make sure that this keyset is PKCS #15 \n\t   object store */\n\tif( itemType != KEYMGMT_ITEM_PUBLICKEY )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_DEVICESTORAGEID );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* A hardware-bound object can't be added to a general-purpose \n\t\t\t   keyset because there's no way to access the key components \n\t\t\t   that are required to be stored */\n\t\t\tif( !isStorageObject )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( isStorageObject )\n\t\t\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\t\t}\n\n\t/* If we're adding a private key make sure that there's a context and a\n\t   password present.  Conversely if we're adding a public key make sure \n\t   that there's no password present.  The password-check has already \n\t   been performed by the kernel but we perform a second check here just \n\t   to be safe.  The private-key check can't be performed by the kernel \n\t   since it doesn't know the difference between public- and private-key \n\t   contexts */\n\tswitch( itemType )\n\t\t{\n\t\tcase KEYMGMT_ITEM_PUBLICKEY:\n\t\tcase KEYMGMT_ITEM_KEYMETADATA:\n\t\t\tif( password != NULL )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tbreak;\n\n\t\tcase KEYMGMT_ITEM_PRIVATEKEY:\n\t\t\tif( !privkeyPresent )\n\t\t\t\t{\n\t\t\t\tretExtArg( CRYPT_ARGERROR_NUM1, \n\t\t\t\t\t\t   ( CRYPT_ARGERROR_NUM1, KEYSET_ERRINFO, \n\t\t\t\t\t\t\t \"Item being added doesn't contain a private \"\n\t\t\t\t\t\t\t \"key\" ) );\n\t\t\t\t}\n\t\t\tif( password == NULL )\n\t\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\tbreak;\n\t\t\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* If there's a certificate present make sure that it's something that \n\t   can be stored.  We don't treat the wrong type as an error since we \n\t   can still store the public/private key components even if we don't \n\t   store the certificate */\n\tif( cryptStatusOK( \\\n\t\tkrnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t CRYPT_CERTINFO_CERTTYPE ) ) && \\\n\t\t( value == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\t  value == CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t{\n\t\tBOOLEAN_INT isInited;\n\n\t\t/* If it's a certificate chain, remember this for later since we may\n\t\t   need to store multiple certificates */\n\t\tif( value == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\tisCertChain = TRUE;\n\n\t\t/* If the certificate isn't signed then we can't store it in this \n\t\t   state */\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &isInited, CRYPT_CERTINFO_IMMUTABLE );\n\t\tif( cryptStatusError( status ) || !isInited )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTINITED, \n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, KEYSET_ERRINFO, \n\t\t\t\t\t  \"Certificate being added is incomplete (unsigned)\" ) );\n\t\t\t}\n\t\t\n\t\t/* Get a reference to the certificate that's associated with the\n\t\t   context.  We have to do this in order to lock it so that we can\n\t\t   store it since the lock operation is only valid for certificates \n\t\t   and not contexts */\n\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t\t  &iCryptCert, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcertPresent = TRUE;\n\t\t}\n\n\t/* Find out where we can add data and what needs to be added.  The \n\t   strategy for adding items is:\n\n\t\t\t\t\t\t\t\t\t\tExisting\n\t\t\tNew\t\t|\tNone\t| Priv+Pub\t| Priv+Cert\t|\tCert\t|\n\t\t------------+-----------+-----------+-----------+-----------+\n\t\tPriv + Pub\t|\tAdd\t\t|\t----\t|\t----\t|\tAdd\t\t|\n\t\t\t\t\t|\t\t\t|\t\t\t|\t\t\t|\t\t\t|\n\t\tPriv + Cert\t|\tAdd\t\t| Repl.pubk\t| Add cert\t| Add cert\t|\n\t\t\t\t\t|\t\t\t| with cert\t| if newer\t| if newer\t|\n\t\tCert\t\t| If trusted|\tAdd\t\t| Add cert\t| Add cert\t|\n\t\t\t\t\t|\t\t\t|\t\t\t| if newer\t| if newer\t|\n\t\t------------+-----------+-----------+-----------+-----------+\n\n\t   We don't check for the addition of a trusted certificate at this \n\t   point since it could be buried in the middle of a certificate chain \n\t   so we leave the checking to addCertChain() */\n\tpkcs15infoPtr = findEntry( pkcs15info, noPkcs15objects, CRYPT_KEYIDEX_ID,\n\t\t\t\t\t\t\t   iD, iDsize, KEYMGMT_FLAG_NONE, FALSE );\n\tif( pkcs15infoPtr != NULL )\n\t\t{\n\t\t/* Determine what actually needs to be added */\n\t\tif( pkcs15infoPtr->privKeyData != NULL )\n\t\t\tpkcs15keyPresent = TRUE;\n\t\tif( pkcs15infoPtr->certData != NULL )\n\t\t\tpkcs15certPresent = TRUE;\n\n\t\t/* See what we can add */\n\t\tstatus = checkAddInfo( pkcs15infoPtr, cryptHandle, isCertChain, \n\t\t\t\t\t\t\t   privkeyPresent, certPresent, \n\t\t\t\t\t\t\t   pkcs15keyPresent, pkcs15certPresent,\n\t\t\t\t\t\t\t   &isCertUpdate, KEYSET_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If it's not an OK_SPECIAL status telling us that we can still \n\t\t\t   try for an opportunistic certificate chain add, exit */\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\t\n\t\t\t/* In theory we can't add anything, however since we've been \n\t\t\t   given a certificate chain there may be new certificates \n\t\t\t   present that we can try and add opportunistically */\n\t\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = pkcs15AddCertChain( pkcs15infoPtr, noPkcs15objects, \n\t\t\t\t\t\t\t\t\t\t cryptHandle, KEYSET_ERRINFO );\n\t\t\t( void ) krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* This key/certificate isn't already present, make sure that the \n\t\t   label of what we're adding doesn't duplicate the label of an \n\t\t   existing object */\n\t\tif( privkeyPresent )\n\t\t\t{\n\t\t\tchar label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\t\tint labelLength;\n\n\t\t\tsetMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );\n\t\t\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tlabelLength = msgData.length;\n\t\t\tif( findEntry( pkcs15info, noPkcs15objects, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t   label, labelLength, KEYMGMT_FLAG_NONE, \n\t\t\t\t\t\t   FALSE ) != NULL )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_DUPLICATE, \n\t\t\t\t\t\t( CRYPT_ERROR_DUPLICATE, KEYSET_ERRINFO, \n\t\t\t\t\t\t  \"Item with label '%s' is already present\",\n\t\t\t\t\t\t  sanitiseString( label, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t\t  labelLength ) ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Find out where we can add the new key data */\n\t\tpkcs15infoPtr = findFreeEntry( pkcs15info, noPkcs15objects, \n\t\t\t\t\t\t\t\t\t   &pkcs15index );\n\t\tif( pkcs15infoPtr == NULL )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_OVERFLOW, \n\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, KEYSET_ERRINFO, \n\t\t\t\t\t  \"No more room in keyset to add this item\" ) );\n\t\t\t}\n\t\t}\n\n\t/* We're ready to go, lock the object for our exclusive use */\n\tif( certPresent )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Add the key data.  This will add the public/private key and any \n\t   certificate data associated with the key as required */\n\tstatus = pkcs15AddKey( pkcs15infoPtr, cryptHandle, password, \n\t\t\t\t\t\t   passwordLength, keysetInfoPtr->ownerHandle, \n\t\t\t\t\t\t   privkeyPresent, certPresent, \n\t\t\t\t\t\t   ( isCertUpdate || !pkcs15certPresent ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE, \n\t\t\t\t\t\t   pkcs15keyPresent, isStorageObject,\n\t\t\t\t\t\t   KEYSET_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( certPresent )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* The update was successful, update the type and index information if \n\t   this was a newly-created entry */\n\tif( pkcs15index != CRYPT_ERROR )\n\t\t{\n\t\tpkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;\n\t\tpkcs15infoPtr->index = pkcs15index;\n\t\t}\n\n\t/* If we've been given a certificate chain, try and opportunistically \n\t   add any further certificates that may be present in it.  Error \n\t   handling once we get this far gets a bit tricky, since this is an\n\t   opportunistic add then one or more of the certificates may already\n\t   be present so a CRYPT_ERROR_DUPLICATE isn't a problem.\n\n\t   Alternatively, we can also get an error at this point if the \n\t   certificate chain update fails even if the main certificate add \n\t   succeeded, however it's uncertain whether we should still report an \n\t   error when the main intended update (of the private key and public \n\t   key or certificate) succeeded.\n\t   \n\t   Since the primary items to be added are the keys and a corresponding \n\t   certificate (as handled in addKey()) we don't report an error if \n\t   adding one of the coincidental certificates fails, since the primary \n\t   items were added successfully */\n\tif( isCertChain )\n\t\t{\n\t\t( void ) pkcs15AddCertChain( pkcs15info, noPkcs15objects, \n\t\t\t\t\t\t\t\t\t cryptHandle, KEYSET_ERRINFO );\n\t\t}\n\n\t/* Clean up */\n\tif( certPresent )\n\t\t{\n\t\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\treturn( status );\n\t}\n\n/* Add special data to the PKCS #15 keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int setSpecialItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE dataType,\n\t\t\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tPKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tconst int noPkcs15objects = keysetInfoPtr->keyDataNoObjects;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isWritePtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t   sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINDEX || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERID || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_USERINFO || \\\n\t\t\t  dataType == CRYPT_IATTRIBUTE_HWSTORAGE );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Some hardware devices use PKCS #15 as their storage format for \n\t   structured data, in which case this is a notification that some rules\n\t   about what can be added to a PKCS #15 keyset can be relaxed */\n\tif( dataType == CRYPT_IATTRIBUTE_HWSTORAGE )\n\t\t{\n\t\tkeysetInfoPtr->keysetFile->iHardwareDevice = \\\n\t\t\t\t\t\t\t\t\t\t*( ( CRYPT_HANDLE * ) data );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\treturn( addConfigData( pkcs15info, noPkcs15objects, dataType,\n\t\t\t\t\t\t   data, dataLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tDelete a Key\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int deleteItemFunction( INOUT KEYSET_INFO *keysetInfoPtr,\n\t\t\t\t\t\t\t   IN_ENUM( KEYMGMT_ITEM ) \\\n\t\t\t\t\t\t\t\tconst KEYMGMT_ITEM_TYPE itemType,\n\t\t\t\t\t\t\t   IN_KEYID const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t   IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t   IN_LENGTH_KEYID const int keyIDlength )\n\t{\n\tconst PKCS15_INFO *pkcs15info = DATAPTR_GET( keysetInfoPtr->keyData );\n\tPKCS15_INFO *pkcs15infoPtr;\n\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\tassert( isReadPtrDynamic( keyID, keyIDlength ) );\n\n\tREQUIRES( sanityCheckKeyset( keysetInfoPtr ) );\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\tREQUIRES( isEnumRange( itemType, KEYMGMT_ITEM ) );\n\tREQUIRES( keyIDtype == CRYPT_KEYID_NAME || \\\n\t\t\t  keyIDtype == CRYPT_KEYID_URI || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_KEYID || \\\n\t\t\t  keyIDtype == CRYPT_IKEYID_ISSUERID );\n\tREQUIRES( keyIDlength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyIDlength < MAX_ATTRIBUTE_SIZE );\n\tREQUIRES( pkcs15info != NULL );\n\n\t/* Locate the appropriate object in the PKCS #15 collection.  Note that\n\t   we don't allow wildcard deletes, since this is a bit too risky */\n\tpkcs15infoPtr = findEntry( pkcs15info, keysetInfoPtr->keyDataNoObjects, \n\t\t\t\t\t\t\t   keyIDtype, keyID, keyIDlength, \n\t\t\t\t\t\t\t   KEYMGMT_FLAG_NONE, FALSE );\n\tif( pkcs15infoPtr == NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTFOUND, \n\t\t\t\t( CRYPT_ERROR_NOTFOUND, KEYSET_ERRINFO, \n\t\t\t\t  \"No information present for this ID\" ) );\n\t\t}\n\n\t/* Clear this entry */\n\tpkcs15freeEntry( pkcs15infoPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKeyset Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initPKCS15set( INOUT KEYSET_INFO *keysetInfoPtr )\n\t{\n\tassert( isWritePtr( keysetInfoPtr, sizeof( KEYSET_INFO ) ) );\n\n\tREQUIRES( keysetInfoPtr->type == KEYSET_FILE && \\\n\t\t\t  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( keysetInfoPtr->setItemFunction, setItemFunction );\n\tFNPTR_SET( keysetInfoPtr->setSpecialItemFunction, setSpecialItemFunction );\n\tFNPTR_SET( keysetInfoPtr->deleteItemFunction, deleteItemFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/keyset/pkcs15_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib PKCS #15 Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"keyset.h\"\n  #include \"pkcs15.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"keyset/keyset.h\"\n  #include \"keyset/pkcs15.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PKCS15\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite PKCS #15 Objects\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the wrapping needed for individual objects */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeObjectWrapper( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t   IN_TAG const int tag )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( tag >= 0 && tag < MAX_TAG_VALUE );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\twriteConstructed( stream, sizeofObject( length ), tag );\n\treturn( writeConstructed( stream, length, CTAG_OV_DIRECT ) );\n\t}\n\n/* Write a data item */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sizeofDataItem( const PKCS15_INFO *pkcs15infoPtr, \n\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *length )\n\t{\n\tconst int dataSize = \\\n\t\t\t( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO ) ? \\\n\t\t\t\tpkcs15infoPtr->dataDataSize : \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->dataDataSize );\n\tconst int labelSize = \\\n\t\t\t( pkcs15infoPtr->labelLength > 0 ) ? \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->labelLength ) : 0;\n\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRange( labelSize ) );\n\tREQUIRES( isShortIntegerRangeNZ( dataSize ) );\n\n\t*length = sizeofShortObject( \\\n\t\t\t\t\tsizeofShortObject( labelSize ) + \\\n\t\t\t\t\tsizeofShortObject( sizeofOID( OID_CRYPTLIB_CONTENTTYPE ) ) + \\\n\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofOID( OID_CRYPTLIB_CONFIGDATA ) + dataSize ) ) );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeDataItem( INOUT STREAM *stream, \n\t\t\t\t\t\t  const PKCS15_INFO *pkcs15infoPtr )\n\t{\n\tconst BYTE *oid = \\\n\t\t\t( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_CONFIGDATA ) ? \\\n\t\t\t\tOID_CRYPTLIB_CONFIGDATA : \\\n\t\t\t( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINDEX ) ? \\\n\t\t\t\tOID_CRYPTLIB_USERINDEX : OID_CRYPTLIB_USERINFO;\n\tconst int labelSize = \\\n\t\t\t( pkcs15infoPtr->labelLength > 0 ) ? \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->labelLength ) : 0;\n\tconst int contentSize = sizeofOID( oid ) + \\\n\t\t\t( ( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO ) ? \\\n\t\t\t\tpkcs15infoPtr->dataDataSize : \\\n\t\t\t\tsizeofShortObject( pkcs15infoPtr->dataDataSize ) );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );\n\n\tREQUIRES( pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \\\n\t\t\t  pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINDEX || \\\n\t\t\t  pkcs15infoPtr->dataType == CRYPT_IATTRIBUTE_USERINFO );\n\tREQUIRES( isShortIntegerRange( labelSize ) );\n\tREQUIRES( isShortIntegerRangeNZ( contentSize ) );\n\n\twriteConstructed( stream, \n\t\t\t\t\t  sizeofShortObject( labelSize ) + \\\n\t\t\t\t\t  sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofOID( OID_CRYPTLIB_CONTENTTYPE ) ) + \\\n\t\t\t\t\t  sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofObject( contentSize ) ),\n\t\t\t\t\t  CTAG_DO_OIDDO );\n\twriteSequence( stream, labelSize );\n\tif( labelSize > 0 )\n\t\t{\n\t\twriteCharacterString( stream, ( BYTE * ) pkcs15infoPtr->label,\n\t\t\t\t\t\t\t  pkcs15infoPtr->labelLength, BER_STRING_UTF8 );\n\t\t}\n\twriteSequence( stream, sizeofOID( OID_CRYPTLIB_CONTENTTYPE ) );\n\twriteOID( stream, OID_CRYPTLIB_CONTENTTYPE );\n\twriteConstructed( stream, sizeofShortObject( contentSize ),\n\t\t\t\t\t  CTAG_OB_TYPEATTR );\n\twriteSequence( stream, contentSize );\n\twriteOID( stream, oid );\n\tif( pkcs15infoPtr->dataType != CRYPT_IATTRIBUTE_USERINFO )\n\t\t{\n\t\t/* UserInfo is a straight object, the others are SEQUENCEs of\n\t\t   objects */\n\t\twriteSequence( stream, pkcs15infoPtr->dataDataSize );\n\t\t}\n\treturn( swrite( stream, pkcs15infoPtr->dataData, \\\n\t\t\t\t\tpkcs15infoPtr->dataDataSize ) );\n\t}\n\n/* Flush a PKCS #15 collection to a stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint pkcs15Flush( INOUT STREAM *stream, \n\t\t\t\t IN_ARRAY( noPkcs15objects ) const PKCS15_INFO *pkcs15info, \n\t\t\t\t IN_LENGTH_SHORT const int noPkcs15objects )\n\t{\n\tint pubKeySize = 0, privKeySize = 0, certSize = 0, dataSize = 0;\n\tint objectsSize = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( pkcs15info, \\\n\t\t\t\t\t\t\t  sizeof( PKCS15_INFO ) * noPkcs15objects ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( noPkcs15objects ) );\n\n\t/* Determine the overall size of the objects */\n\tLOOP_MED( i = 0, i < noPkcs15objects, i++ )\n\t\t{\n\t\tswitch( pkcs15info[ i ].type )\n\t\t\t{\n\t\t\tcase PKCS15_SUBTYPE_NONE:\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_SUBTYPE_NORMAL:\n\t\t\t\tpubKeySize += pkcs15info[ i ].pubKeyDataSize;\n\t\t\t\tprivKeySize += pkcs15info[ i ].privKeyDataSize;\n\t\t\t\tSTDC_FALLTHROUGH;\n\n\t\t\tcase PKCS15_SUBTYPE_CERT:\n\t\t\t\tcertSize += pkcs15info[ i ].certDataSize;\n\t\t\t\tbreak;\n\n\t\t\tcase PKCS15_SUBTYPE_SECRETKEY:\n\t\t\t\tretIntError();\n\n\t\t\tcase PKCS15_SUBTYPE_DATA:\n\t\t\t\t{\n\t\t\t\tint length;\n\n\t\t\t\tstatus = sizeofDataItem( &pkcs15info[ i ], &length );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tdataSize += length;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Determine how much data there is to write.  If there's no data\n\t   present, let the caller know that the keyset is empty */\n\tif( pubKeySize > 0 )\n\t\tobjectsSize += sizeofObject( sizeofObject( pubKeySize ) );\n\tif( privKeySize > 0 )\n\t\tobjectsSize += sizeofObject( sizeofObject( privKeySize ) );\n\tif( certSize > 0 )\n\t\tobjectsSize += sizeofObject( sizeofObject( certSize ) );\n\tif( dataSize > 0 )\n\t\tobjectsSize += sizeofObject( sizeofObject( dataSize ) );\n\tif( objectsSize <= 0 )\n\t\treturn( OK_SPECIAL );\t/* Keyset is empty */\n\n\t/* Write the header information and each public key, private key, and\n\t   certificate */\n\tstatus = writeCMSheader( stream, OID_PKCS15_CONTENTTYPE, \n\t\t\t\t\t\t\t sizeofOID( OID_PKCS15_CONTENTTYPE ),\n\t\t\t\t\t\t\t sizeofShortInteger( 0 ) + \\\n\t\t\t\t\t\t\t\tsizeofObject( objectsSize ), FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\tstatus = writeSequence( stream, objectsSize );\n\tif( cryptStatusOK( status ) && privKeySize > 0 )\n\t\t{\n\t\tstatus = writeObjectWrapper( stream, privKeySize, CTAG_PO_PRIVKEY );\n\t\tLOOP_MED( i = 0, cryptStatusOK( status ) && i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tif( pkcs15info[ i ].privKeyDataSize > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = swrite( stream, pkcs15info[ i ].privKeyData,\n\t\t\t\t\t\t\t\t pkcs15info[ i ].privKeyDataSize );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( cryptStatusOK( status ) && pubKeySize > 0 )\n\t\t{\n\t\tstatus = writeObjectWrapper( stream, pubKeySize, CTAG_PO_PUBKEY );\n\t\tLOOP_MED( i = 0, cryptStatusOK( status ) && i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tif( pkcs15info[ i ].pubKeyDataSize > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = swrite( stream, pkcs15info[ i ].pubKeyData,\n\t\t\t\t\t\t\t\t pkcs15info[ i ].pubKeyDataSize );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( cryptStatusOK( status ) && certSize > 0 )\n\t\t{\n\t\tstatus = writeObjectWrapper( stream, certSize, CTAG_PO_CERT );\n\t\tLOOP_MED( i = 0, cryptStatusOK( status ) && i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tif( ( pkcs15info[ i ].type == PKCS15_SUBTYPE_NORMAL && \\\n\t\t\t\t  pkcs15info[ i ].certDataSize > 0 ) || \\\n\t\t\t\t( pkcs15info[ i ].type == PKCS15_SUBTYPE_CERT ) )\n\t\t\t\t{\n\t\t\t\tstatus = swrite( stream, pkcs15info[ i ].certData,\n\t\t\t\t\t\t\t\t pkcs15info[ i ].certDataSize );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tif( cryptStatusOK( status ) && dataSize > 0 )\n\t\t{\n\t\tstatus = writeObjectWrapper( stream, dataSize, CTAG_PO_DATA );\n\t\tLOOP_MED( i = 0, cryptStatusOK( status ) && i < noPkcs15objects, i++ )\n\t\t\t{\n\t\t\tif( pkcs15info[ i ].dataDataSize > 0 )\n\t\t\t\tstatus = writeDataItem( stream, &pkcs15info[ i ] );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( sflush( stream ) );\n\t}\n#endif /* USE_PKCS15 */\n"
  },
  {
    "path": "deps/cl345/makefile",
    "content": "#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\tMakefile for cryptlib 3.4.x\t\t\t\t\t\t*\n#*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2018\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# This makefile contains extensive amounts of business logic which, alongside \n# further logic in the build scripts in the ./tools directory and the \n# cryptlib OS-specific header files, ensures that cryptlib auto-configures \n# itself and builds out of the box on most systems.  Before you ask about \n# redoing the makefile using autoconf, have a look at what it would take to \n# move all of this logic across to another build mechanism.\n#\n# \"The makefile is looking really perverse.  You're getting the hang of it\"\n#\t\t\t\t\t\t\t\t\t\t\t\t\t\t- Chris Wedgwood.\n# At least it doesn't pipe itself through sed yet.\n#\n# (Note that as of 3.1 beta 3 it does pipe itself through sed on non-Unix\n#  systems to retarget Unix-specific files to OS-specific ones and perform\n#  various other operations that aren't easily possible by adding another\n#  level of recursion).\n#\n# The self-test program pulls in parts of cryptlib to ensure that the self-\n# configuration works.  Because this is handled by the makefile, you can't\n# just 'make testlib' after making changes, you need to use 'make; make\n# testlib'.\n\n# Naming information: Major and minor version numbers and project and library\n# names (static lib, shared lib, and OS X dylib).  The patch level is always\n# zero because patches imply bugs and my code is perfect (although sometimes\n# reality isn't).\n#\n# Note that when updating these values it'll also be necessary to update the\n# equivalents in tools/buildall.sh.\n\nMAJ\t\t= 3\nMIN\t\t= 4\nPLV\t\t= 5\nPROJ\t= cl\nLIBNAME\t= lib$(PROJ).a\nSLIBNAME = lib$(PROJ).so.$(MAJ).$(MIN).$(PLV)\nDYLIBNAME = lib$(PROJ).$(MAJ).$(MIN).dylib\n\n# Compiler options.  By default this builds the release version of the code,\n# to build the debug version (which is useful for finding compiler bugs and\n# system-specific peculiarities), use one of the alternative CFLAGS options\n# below.  Many problems will now trigger an assertion at the point of failure \n# rather than returning an error status from 100 levels down in the code, \n# although as of 3.3.2 many of the earlier assertions have been turned into \n# REQUIRES/ENSURES predicates that are applied even in the release version.\n#\n# Note that the gcc build on x86 uses -fomit-frame-pointer to free up an \n# extra register (which desperately needs it), this may screw up some\n# versions of gdb if you try and debug a version (compile with '-g')\n# compiled with this option.  -fomit-frame-pointer isn't explicitly\n# specified for other architectures because it's implied by -O, being\n# enabled for -O, -O2, -O3, and -Os.\n#\n# As a general comment, the -fno-omit-frame-pointer is required in x86-64 \n# and ARM because the ABI specifies that no frame pointer is used, so for \n# debugging we have to explicitly enable it to provide better diagnostics.\n# Alternatively, use the debug target \"make debug\".  This assumes a certain \n# amount of gnu-ishness in the debug environment (which seems to be the \n# universal default), if you're using something else then you'll have to \n# modify CFLAGS_DEBUG below.  In addition it's probably a good idea to remove \n# -fomit-frame-pointer if it's explicitly set for the target environment.\n#\n# If the OS supports it, the multithreaded version of cryptlib will be built.\n# To specifically disable this add -DNO_THREADS.\n#\n# If you're building the 64-bit version on a system that defaults to 32-bit\n# binaries then you can get the 64-bit version by adding \"-m64\" to CFLAGS\n# and LDFLAGS, at least for gcc.\n#\n# The Gnu coverage-analysis tools are at about the level that cavemen used to\n# debug fire, you need to enable CFLAGS_COVERAGE and LDLAGS_COVERAGE below,\n# then run ./testlib, then manually run gcov on each source file, which at\n# best can be done with:\n#\tgcov -o static-obj/ session/*.c\n# which dumps the resulting gcov files in the current directory.  This then\n# needs further processing with lcov:\n#\tlcov --directory . --capture --output-file testlib.info\n# to produce output that needs even more processing with genhtml:\n#\tgenhtml --output-directory testlib_html testlib.info\n# that can finally be viewed with a web browser.  The resulting summary info\n# is graphical, but the per-file information is in crude ASCII-art form.\n# Overall it's not worth it, just turn on profiling in Visual Studio.\n#\n# Further cc flags are gathered dynamically at runtime via the ccopts.sh\n# script.\n\nCFLAGS\t\t\t= -c -D__UNIX__ -DNDEBUG -I.\nCFLAGS_DEBUG\t= -c -D__UNIX__ -I. -g -O1\nCFLAGS_DEBUGGCC\t= -c -D__UNIX__ -I. -ggdb3 -fno-omit-frame-pointer -O1\nCFLAGS_ANALYSE\t= -c -D__UNIX__ -I.\nCFLAGS_COVERAGE\t= -c -D__UNIX__ -I. -ggdb3 -fno-omit-frame-pointer -O1 --coverage -fprofile-arcs -ftest-coverage\nCFLAGS_FUZZ\t\t= -c -D__UNIX__ -I. -ggdb3 -fno-omit-frame-pointer -funwind-tables -fsanitize=address -O1 -DCONFIG_FUZZ\nCFLAGS_LIBFUZZER = -c -D__UNIX__ -I. -g -fno-omit-frame-pointer -fsanitize=fuzzer,address,undefined -O1 -DCONFIG_FUZZ -DCONFIG_LIBFUZZER\nCFLAGS_HONGGFUZZ = -c -D__UNIX__ -I. -g -fno-omit-frame-pointer -O1 -DCONFIG_FUZZ -DCONFIG_LIBFUZZER\nCFLAGS_UBSAN\t= -c -D__UNIX__ -I. -ggdb3 -fno-omit-frame-pointer -funwind-tables -fsanitize=undefined -fsanitize-blacklist=ubsan_blacklist.txt -O1\nCFLAGS_VALGRIND\t= -c -D__UNIX__ -I. -ggdb3 -fno-omit-frame-pointer -O1\n\n# Paths and command names.  We have to be careful with comments attached to\n# path defines because some makes don't strip trailing spaces.\n#\n# The reason for the almost-identical defines for path and dir is because of\n# the braindamaged BSDI mkdir (and rmdir) that break if the path ends in a\n# '/', it's easier to have separate defines than to drop a '/' into every\n# path.\n\nSTATIC_OBJ_DIR = ./static-obj\nSHARED_OBJ_DIR = ./shared-obj\nSTATIC_OBJ_PATH = $(STATIC_OBJ_DIR)/\nSHARED_OBJ_PATH = $(SHARED_OBJ_DIR)/\nCPP\t\t\t= $(CC) -E\nLD\t\t\t= $(CC)\nMAKE\t\t= make\nAR\t\t\t= ar\nSTRIP\t\t= strip\nSHELL\t\t= /bin/sh\nOSNAME\t\t= `uname`\nLINKFILE\t= link.tmp\n\n# Default target and obj file path.  This is changed depending on whether\n# we're building the static or shared library, the default is to build the\n# static library.\n\nTARGET\t\t= $(LIBNAME)\nOBJPATH\t\t= $(STATIC_OBJ_PATH)\n\n# By default we're not cross-compiling\n\nCROSSCOMPILE = 0\n\n# Some makes don't pass defines down when they recursively invoke make, so we\n# need to manually pass them along.  The following macro contains all defines\n# that we want to pass to recursive calls to make.\n\nDEFINES\t\t= $(TARGET) OBJPATH=$(OBJPATH) OSNAME=$(OSNAME)\n\n# Cross-compilation/non-Unix options, which are just the standard ones with\n# Unix-specific entries (-D__UNIX__, use of uname to identify the system)\n# removed.  The actual values are explicitly given in the rules for each non-\n# Unix target.\n\nXCFLAGS\t\t\t= -c -DNDEBUG -I.\nXCFLAGS_DEBUG\t= -c -I. -g -O0\nXDEFINES\t\t= $(TARGET) OBJPATH=$(OBJPATH) CROSSCOMPILE=1\nXLDFLAGS\t\t= CROSSCOMPILE=1\n\nXSCFLAGS\t\t= -c -DNDEBUG -I.\nXSCFLAGS_DEBUG\t= -c -I. -g -O0\nXSDEFINES\t\t= $(SLIBNAME) OBJPATH=$(SHARED_OBJ_PATH) CROSSCOMPILE=1\nXSLDFLAGS\t\t= CROSSCOMPILE=1\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\tCommon Dependencies\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# The object files that make up cryptlib.\n\nBNOBJS\t\t= $(OBJPATH)bn_asm.o $(OBJPATH)bn_exp.o $(OBJPATH)bn_exp2.o \\\n\t\t\t  $(OBJPATH)bn_gcd.o $(OBJPATH)bn_mul.o $(OBJPATH)bn_recp.o \\\n\t\t\t  $(OBJPATH)ec_lib.o $(OBJPATH)ecp_mont.o $(OBJPATH)ecp_smpl.o \\\n\t\t\t  $(OBJPATH)ec_mult.o\n\nCERTOBJS\t= $(OBJPATH)certrev.o $(OBJPATH)certschk.o $(OBJPATH)certsign.o \\\n\t\t\t  $(OBJPATH)certval.o $(OBJPATH)chain.o $(OBJPATH)chk_cert.o \\\n\t\t\t  $(OBJPATH)chk_chn.o $(OBJPATH)chk_san.o $(OBJPATH)chk_use.o \\\n\t\t\t  $(OBJPATH)comp_cert.o $(OBJPATH)comp_curs.o $(OBJPATH)comp_del.o \\\n\t\t\t  $(OBJPATH)comp_get.o $(OBJPATH)comp_gets.o \\\n\t\t\t  $(OBJPATH)comp_pkiu.o $(OBJPATH)comp_set.o $(OBJPATH)dn.o \\\n\t\t\t  $(OBJPATH)dn_rw.o $(OBJPATH)dn_rws.o $(OBJPATH)dn_string.o \\\n\t\t\t  $(OBJPATH)ext.o $(OBJPATH)ext_add.o $(OBJPATH)ext_chk.o \\\n\t\t\t  $(OBJPATH)ext_copy.o $(OBJPATH)ext_def.o $(OBJPATH)ext_rd.o \\\n\t\t\t  $(OBJPATH)ext_wr.o $(OBJPATH)imp_chk.o $(OBJPATH)imp_exp.o \\\n\t\t\t  $(OBJPATH)read.o $(OBJPATH)trustmgr.o $(OBJPATH)write.o \\\n\t\t\t  $(OBJPATH)write_pre.o\n\nCRYPTOBJS\t= $(OBJPATH)aes_modes.o $(OBJPATH)aes_ni.o $(OBJPATH)aescrypt.o \\\n\t\t\t  $(OBJPATH)aeskey.o $(OBJPATH)aestab.o $(OBJPATH)castecb.o \\\n\t\t\t  $(OBJPATH)castenc.o $(OBJPATH)castskey.o $(OBJPATH)descbc.o \\\n\t\t\t  $(OBJPATH)desecb.o $(OBJPATH)desecb3.o $(OBJPATH)desenc.o \\\n\t\t\t  $(OBJPATH)desskey.o $(OBJPATH)gcm.o $(OBJPATH)gf128mul.o \\\n\t\t\t  $(OBJPATH)icbc.o $(OBJPATH)iecb.o $(OBJPATH)iskey.o \\\n\t\t\t  $(OBJPATH)rc2cbc.o $(OBJPATH)rc2ecb.o $(OBJPATH)rc2skey.o \\\n\t\t\t  $(OBJPATH)rc4enc.o $(OBJPATH)rc4skey.o \n\nCONTEXTOBJS\t= $(OBJPATH)ctx_3des.o $(OBJPATH)ctx_aes.o $(OBJPATH)ctx_attr.o \\\n\t\t\t  $(OBJPATH)ctx_bn.o $(OBJPATH)ctx_bnmath.o $(OBJPATH)ctx_bnpkc.o \\\n\t\t\t  $(OBJPATH)ctx_bnprime.o $(OBJPATH)ctx_bnrw.o $(OBJPATH)ctx_bnsieve.o \\\n\t\t\t  $(OBJPATH)ctx_bntest.o $(OBJPATH)ctx_cast.o $(OBJPATH)ctx_des.o \\\n\t\t\t  $(OBJPATH)ctx_dh.o $(OBJPATH)ctx_dsa.o $(OBJPATH)ctx_ecdh.o \\\n\t\t\t  $(OBJPATH)ctx_ecdsa.o $(OBJPATH)ctx_elg.o $(OBJPATH)ctx_encr.o \\\n\t\t\t  $(OBJPATH)ctx_generic.o $(OBJPATH)ctx_hsha.o $(OBJPATH)ctx_hsha2.o \\\n\t\t\t  $(OBJPATH)ctx_idea.o $(OBJPATH)ctx_md5.o $(OBJPATH)ctx_misc.o \\\n\t\t\t  $(OBJPATH)ctx_rc2.o $(OBJPATH)ctx_rc4.o $(OBJPATH)ctx_rsa.o \\\n\t\t\t  $(OBJPATH)ctx_sha.o $(OBJPATH)ctx_sha2.o $(OBJPATH)kg_dlp.o \\\n\t\t\t  $(OBJPATH)kg_ecc.o $(OBJPATH)kg_prime.o $(OBJPATH)kg_rsa.o \\\n\t\t\t  $(OBJPATH)keyload.o $(OBJPATH)key_id.o $(OBJPATH)key_rdpri.o \\\n\t\t\t  $(OBJPATH)key_rdpub.o $(OBJPATH)key_wr.o\n\nDEVICEOBJS\t= $(OBJPATH)dev_attr.o $(OBJPATH)hardware.o $(OBJPATH)hw_dummy.o \\\n\t\t\t  $(OBJPATH)pkcs11.o $(OBJPATH)pkcs11_init.o $(OBJPATH)pkcs11_pkc.o \\\n\t\t\t  $(OBJPATH)pkcs11_rd.o $(OBJPATH)pkcs11_wr.o $(OBJPATH)system.o\n\nENCDECOBJS\t= $(OBJPATH)asn1_algid.o $(OBJPATH)asn1_chk.o $(OBJPATH)asn1_rd.o \\\n\t\t\t  $(OBJPATH)asn1_wr.o $(OBJPATH)asn1_ext.o $(OBJPATH)base64.o \\\n\t\t\t  $(OBJPATH)base64_id.o $(OBJPATH)misc_rw.o $(OBJPATH)pgp_rw.o\n\nENVOBJS\t\t= $(OBJPATH)cms_denv.o $(OBJPATH)cms_env.o $(OBJPATH)cms_envpre.o \\\n\t\t\t  $(OBJPATH)decode.o $(OBJPATH)encode.o $(OBJPATH)env_attr.o \\\n\t\t\t  $(OBJPATH)pgp_denv.o $(OBJPATH)pgp_env.o $(OBJPATH)res_actn.o \\\n\t\t\t  $(OBJPATH)res_denv.o $(OBJPATH)res_env.o\n\nHASHOBJS\t= $(OBJPATH)md5dgst.o $(OBJPATH)sha1dgst.o $(OBJPATH)sha2.o\n\nIOOBJS\t\t= $(OBJPATH)dns.o $(OBJPATH)dns_srv.o $(OBJPATH)file.o \\\n\t\t\t  $(OBJPATH)http.o $(OBJPATH)http_rd.o $(OBJPATH)http_parse.o \\\n\t\t\t  $(OBJPATH)http_wr.o $(OBJPATH)memory.o $(OBJPATH)net.o \\\n\t\t\t  $(OBJPATH)net_proxy.o $(OBJPATH)net_trans.o \\\n\t\t\t  $(OBJPATH)net_url.o $(OBJPATH)stream.o $(OBJPATH)tcp.o \\\n\t\t\t  $(OBJPATH)tcp_conn.o $(OBJPATH)tcp_err.o $(OBJPATH)tcp_rw.o\n\nKERNELOBJS\t= $(OBJPATH)attr_acl.o $(OBJPATH)certm_acl.o $(OBJPATH)init.o \\\n\t\t\t  $(OBJPATH)int_msg.o $(OBJPATH)key_acl.o $(OBJPATH)mech_acl.o \\\n\t\t\t  $(OBJPATH)msg_acl.o $(OBJPATH)obj_acc.o $(OBJPATH)objects.o \\\n\t\t\t  $(OBJPATH)sec_mem.o $(OBJPATH)selftest.o $(OBJPATH)semaphore.o \\\n\t\t\t  $(OBJPATH)sendmsg.o $(OBJPATH)storage.o\n\nKEYSETOBJS\t= $(OBJPATH)dbms.o $(OBJPATH)ca_add.o $(OBJPATH)ca_clean.o \\\n\t\t\t  $(OBJPATH)ca_issue.o $(OBJPATH)ca_misc.o $(OBJPATH)ca_rev.o \\\n\t\t\t  $(OBJPATH)dbx_misc.o $(OBJPATH)dbx_rd.o $(OBJPATH)dbx_wr.o \\\n\t\t\t  $(OBJPATH)http_keys.o $(OBJPATH)key_attr.o $(OBJPATH)ldap.o \\\n\t\t\t  $(OBJPATH)odbc.o $(OBJPATH)pgp.o $(OBJPATH)pgp_rd.o \\\n\t\t\t  $(OBJPATH)pgp_wr.o $(OBJPATH)pkcs12.o $(OBJPATH)pkcs12_rd.o \\\n\t\t\t  $(OBJPATH)pkcs12_rdo.o $(OBJPATH)pkcs12_wr.o $(OBJPATH)pkcs15.o \\\n\t\t\t  $(OBJPATH)pkcs15_add.o $(OBJPATH)pkcs15_adpb.o \\\n\t\t\t  $(OBJPATH)pkcs15_adpr.o $(OBJPATH)pkcs15_atrd.o \\\n\t\t\t  $(OBJPATH)pkcs15_atwr.o $(OBJPATH)pkcs15_get.o \\\n\t\t\t  $(OBJPATH)pkcs15_getp.o $(OBJPATH)pkcs15_rd.o \\\n\t\t\t  $(OBJPATH)pkcs15_set.o $(OBJPATH)pkcs15_wr.o\n\nLIBOBJS\t\t= $(OBJPATH)cryptapi.o $(OBJPATH)cryptcrt.o $(OBJPATH)cryptctx.o \\\n\t\t\t  $(OBJPATH)cryptdev.o $(OBJPATH)cryptenv.o $(OBJPATH)cryptkey.o \\\n\t\t\t  $(OBJPATH)cryptlib.o $(OBJPATH)cryptses.o $(OBJPATH)cryptusr.o\n\nMECHOBJS\t= $(OBJPATH)keyex.o $(OBJPATH)keyex_int.o $(OBJPATH)keyex_rw.o \\\n\t\t\t  $(OBJPATH)mech_cwrap.o $(OBJPATH)mech_drv.o $(OBJPATH)mech_int.o \\\n\t\t\t  $(OBJPATH)mech_pkwrap.o $(OBJPATH)mech_privk.o \\\n\t\t\t  $(OBJPATH)mech_sig.o $(OBJPATH)obj_qry.o $(OBJPATH)sign.o \\\n\t\t\t  $(OBJPATH)sign_cms.o $(OBJPATH)sign_int.o $(OBJPATH)sign_pgp.o \\\n\t\t\t  $(OBJPATH)sign_rw.o $(OBJPATH)sign_x509.o\n\nMISCOBJS\t= $(OBJPATH)int_api.o $(OBJPATH)int_attr.o $(OBJPATH)int_debug.o \\\n\t\t\t  $(OBJPATH)int_env.o $(OBJPATH)int_err.o $(OBJPATH)int_mem.o \\\n\t\t\t  $(OBJPATH)int_string.o $(OBJPATH)int_time.o $(OBJPATH)java_jni.o \\\n\t\t\t  $(OBJPATH)os_spec.o $(OBJPATH)pgp_misc.o $(OBJPATH)random.o \\\n\t\t\t  $(OBJPATH)rand_x917.o $(OBJPATH)unix.o $(OBJPATH)user.o \\\n\t\t\t  $(OBJPATH)user_attr.o $(OBJPATH)user_cfg.o $(OBJPATH)user_rw.o\n\nSESSIONOBJS\t= $(OBJPATH)certstore.o $(OBJPATH)cmp.o $(OBJPATH)cmp_cli.o \\\n\t\t\t  $(OBJPATH)cmp_crypt.o $(OBJPATH)cmp_err.o $(OBJPATH)cmp_rd.o \\\n\t\t\t  $(OBJPATH)cmp_rdmsg.o $(OBJPATH)cmp_svr.o $(OBJPATH)cmp_wr.o \\\n\t\t\t  $(OBJPATH)cmp_wrmsg.o $(OBJPATH)ocsp.o $(OBJPATH)pnppki.o \\\n\t\t\t  $(OBJPATH)rtcs.o $(OBJPATH)scep.o $(OBJPATH)scep_cli.o \\\n\t\t\t  $(OBJPATH)scep_svr.o $(OBJPATH)scorebrd.o $(OBJPATH)sess_attr.o \\\n\t\t\t  $(OBJPATH)sess_iattr.o $(OBJPATH)sess_rd.o $(OBJPATH)sess_wr.o \\\n\t\t\t  $(OBJPATH)sess_ws.o $(OBJPATH)session.o $(OBJPATH)ssh.o \\\n\t\t\t  $(OBJPATH)ssh2.o $(OBJPATH)ssh2_authc.o $(OBJPATH)ssh2_auths.o \\\n\t\t\t  $(OBJPATH)ssh2_chn.o $(OBJPATH)ssh2_cli.o $(OBJPATH)ssh2_crypt.o \\\n\t\t\t  $(OBJPATH)ssh2_msg.o $(OBJPATH)ssh2_msgc.o $(OBJPATH)ssh2_msgs.o \\\n\t\t\t  $(OBJPATH)ssh2_rd.o $(OBJPATH)ssh2_svr.o $(OBJPATH)ssh2_wr.o \\\n\t\t\t  $(OBJPATH)ssl.o $(OBJPATH)ssl_cli.o $(OBJPATH)ssl_crypt.o \\\n\t\t\t  $(OBJPATH)ssl_ext.o $(OBJPATH)ssl_hs.o $(OBJPATH)ssl_hsc.o \\\n\t\t\t  $(OBJPATH)ssl_kmgmt.o $(OBJPATH)ssl_rd.o $(OBJPATH)ssl_suites.o \\\n\t\t\t  $(OBJPATH)ssl_svr.o $(OBJPATH)ssl_wr.o $(OBJPATH)tsp.o\n\nZLIBOBJS\t= $(OBJPATH)adler32.o $(OBJPATH)deflate.o $(OBJPATH)inffast.o \\\n\t\t\t  $(OBJPATH)inflate.o $(OBJPATH)inftrees.o $(OBJPATH)trees.o \\\n\t\t\t  $(OBJPATH)zutil.o\n\nOBJS\t\t= $(BNOBJS) $(CERTOBJS) $(CRYPTOBJS) $(CONTEXTOBJS) $(DEVICEOBJS) \\\n\t\t\t  $(ENCDECOBJS) $(ENVOBJS) $(HASHOBJS) $(IOOBJS) $(KEYSETOBJS) \\\n\t\t\t  $(KERNELOBJS) $(LIBOBJS) $(MECHOBJS) $(MISCOBJS) $(SESSIONOBJS) \\\n\t\t\t  $(ZLIBOBJS) $(OSOBJS)\n\n# Object files for the self-test code\n\nTESTOBJS\t= certimp.o certproc.o certs.o devices.o envelope.o highlvl.o \\\n\t\t\t  keydbx.o keyfile.o loadkey.o lowlvl.o s_cmp.o s_scep.o sreqresp.o \\\n\t\t\t  ssh.o ssl.o stress.o suiteb.o testfunc.o testlib.o utils.o\n\n# Various functions all make use of certain headers so we define the\n# dependencies once here\n\nIO_DEP = io/stream.h enc_dec/misc_rw.h enc_dec/pgp_rw.h\n\nIO_DEP_INT = $(IO_DEP) io/file.h io/http.h io/stream_int.h io/tcp.h \\\n\t\t\t io/tcp_int.h \n\nASN1_DEP = io/stream.h enc_dec/asn1.h enc_dec/asn1_ext.h\n\nCERT_DEP = cert/cert.h cert/certfn.h\n\nCRYPT_DEP\t= cryptlib.h crypt.h cryptkrn.h misc/config.h misc/consts.h \\\n\t\t\t  misc/debug.h misc/fault.h misc/int_api.h misc/list.h \\\n\t\t\t  misc/os_spec.h misc/safety.h \n\nKERNEL_DEP\t= kernel/acl.h kernel/acl_perm.h kernel/kernel.h kernel/thread.h\n\nZLIB_DEP = zlib/zconf.h zlib/zlib.h zlib/zutil.h\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\tDefault and High-level Targets\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# Find the system type and use a conditional make depending on that.\n#\n# Slowaris doesn't ship with a compiler by default, so Sun had to provide\n# something that pretends to be one for things that look for a cc.  This\n# makes it really hard to figure out what's really going on.  The default cc,\n# /usr/ucb/cc, is a script that looks for a real compiler elsewhere.  If the\n# Sun compiler is installed, this will be via a link /usr/ccs/bin/ucbcc,\n# which in turn points to /opt/SUNWspro.  If it's not installed, or installed\n# incorrectly, it will bail out with a \"package not installed\" error.  We\n# check for this bogus compiler and if we get the error message fall back to\n# gcc, which is how most people just fix this mess.\n#\n# The MVS USS c89 compiler has a strict ordering of options.  That ordering\n# can be relaxed with the _C89_CCMODE environment variable to accept options\n# and file names in any order, so we check to make sure that this is set.\n#\n# The Cray uname reports the machine serial number instead of the machine\n# type by default, so we have to explicitly check for Cray systems and\n# modify the machine-detection mechanism to handle this.\n#\n# The '-' to disable error-checking in several cases below is necessary for\n# the braindamaged QNX make, which bails out as soon as one of the tests\n# fails, whether this would affect the make or not.\n#\n# We have to special-case the situation where the OS name is an alias for\n# uname rather than being predefined (this occurs when cross-compiling),\n# because the resulting expansion would contain two levels of `` escapes.  To\n# handle this, we leave a predefined OS name in place, but replace a call to\n# uname with instructions to the osversion.sh script to figure it out for\n# itself.\n#\n# The build flow for a standard invocation via 'make' is:\n#\n#\tmake -> (default rule) -> buildall.sh, get compiler options via \n#\tccopts.sh -> make $osname -> make $libname\n#\n# The build flow for a cross-compile, via 'make crosscompile-target' is:\n#\n#\tmake crosscompile-target -> make $libname \n#\t\tusing 'CFLAGS=ccopts-crosscompile.sh CROSSCOMPILE=1'\n#\n# The build flow for creating the final library is to invoke buildlib.sh \n# or buildsharedlib.sh, where buildsharedlib.sh invokes getlibs.sh to\n# determine which libraries to use.\n\ndefault:\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh $(MAKE) $(CC) $(OSNAME) $(CFLAGS)\n\nshared:\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh shared $(MAKE) $(CC) $(OSNAME) $(CFLAGS)\n\ndebug:\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh $(MAKE) $(CC) $(OSNAME) $(CFLAGS_DEBUG)\n\n# Special-case targets.  The \"analyse\" target isn't used directly but is \n# invoked as part of the clang static analyser build process.\n\nanalyse:\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh analyse $(MAKE) $(CC) $(OSNAME) $(CFLAGS_ANALYSE)\n\ntestlib-special:\n\t@echo $(TESTOBJS) > $(LINKFILE)\n\t$(LD) $(LDFLAGS) -o testlib `cat $(LINKFILE)` $(LDEXTRA) -L. -l$(PROJ) \\\n\t\t`./tools/getlibs.sh special $(LD) $(OSNAME)`\n\t@rm -f $(LINKFILE)\n\nfuzz:\n\t@$(MAKE) check-clang\n\t@$(MAKE) common-tasks\n\t@export AFL_HARDEN=1 ; export AFL_USE_ASAN=1 ; \\\n\t\t./tools/buildall.sh special $(MAKE) ~/afl-2*/afl-clang-fast \\\n\t\t$(OSNAME) $(CFLAGS_FUZZ)\n\t@rm -f $(LINKFILE)\n\tmake testlib-special LD=~/afl-2*/afl-clang-fast LDFLAGS=\"-fsanitize=address\" \\\n\t\tLDEXTRA=\"~/afl-2*/afl-llvm-rt.o\" OSNAME=$(OSNAME)\n\t@mv ./testlib ./fuzz-clib\n\nfuzz-gcc:\n\t@$(MAKE) check-clang\n\t@$(MAKE) common-tasks\n\t@export export AFL_USE_ASAN=1 ; \\\n\t\t./tools/buildall.sh special $(MAKE) ~/afl-2*/afl-gcc $(OSNAME) $(CFLAGS_FUZZ)\n\t@rm -f $(LINKFILE)\n\tmake testlib-special LD=~/afl-2*/afl-gcc LDFLAGS=\"-fsanitize=address\" \\\n\t\tOSNAME=$(OSNAME)\n\t@mv ./testlib ./fuzz-clib\n\nhonggfuzz:\n\t@$(MAKE) check-clang\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh special $(MAKE) ~/HONGGFUZZ/hfuzz_cc/hfuzz-clang $(OSNAME) \\\n\t\t$(CFLAGS_HONGGFUZZ)\n\t~/HONGGFUZZ/hfuzz_cc/hfuzz-clang -L. -l$(PROJ) \\\n\t\t`./tools/getlibs.sh special ~/HONGGFUZZ/hfuzz_cc/hfuzz-clang $(OSNAME)`\n\t@mv ./a.out ./fuzz-clib\n\nlibfuzzer:\n\t@$(MAKE) check-clang\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh special $(MAKE) clang $(OSNAME) $(CFLAGS_LIBFUZZER)\n\tclang -fsanitize=fuzzer,address,undefined -L. -l$(PROJ) \\\n\t\t`./tools/getlibs.sh special clang $(OSNAME)`\n\t@mv ./a.out ./fuzz-clib\n\nvalgrind:\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh special $(MAKE) $(CC) $(OSNAME) $(CFLAGS_VALGRIND)\n\t@rm -f $(LINKFILE)\n\tmake testlib-special LD=cc LDFLAGS=\"\" OSNAME=$(OSNAME)\n\nubsan:\n\t@$(MAKE) check-clang\n\t@$(MAKE) common-tasks\n\t@./tools/buildall.sh special $(MAKE) clang $(OSNAME) $(CFLAGS_UBSAN)\n\t@rm -f $(LINKFILE)\n\tmake testlib-special LD=clang LDFLAGS=\"-fsanitize=undefined\" \\\n\t\tOSNAME=$(OSNAME)\n\n# Tasks involved in the build process.  The \"touch\" target is used to \n# correct file timestamps when they've come from a system in a different \n# time zone.\n\ncheck-clang:\n\t@if [ ! `which clang` ] ; then \\\n\t\techo \"LLVM isn't present in \\$$PATH.\" >&2 ; \\\n\t\texit 1 ; \\\n\tfi\n\ntouch:\n\ttouch ./makefile\n\tfind ./ | xargs touch\n\ncommon-tasks:\n\t@$(MAKE) directories\n\t@$(MAKE) toolscripts\n\t@- if [ $(OSNAME) = 'OS/390' -a \"$(_C89_CCMODE)\" != \"1\" ] ; then \\\n\t\techo \"The c89 environment variable _C89_CCMODE must be set to 1.\" >&2 ; \\\n\t\texit 1 ; \\\n\tfi\n\ndirectories:\n\t@- if [ ! -d $(STATIC_OBJ_PATH) ] ; then \\\n\t\tmkdir $(STATIC_OBJ_DIR) ; \\\n\tfi\n\t@- if [ ! -d $(SHARED_OBJ_PATH) ] ; then \\\n\t\tmkdir $(SHARED_OBJ_DIR) ; \\\n\tfi\n\ntoolscripts:\n\t@for file in ./tools/*.sh ; do \\\n\t\tif [ ! -x $$file ] ; then chmod +x $$file ; fi \\\n\tdone\n\n# Install the library and include file.  PREFIX and DESTDIR are two (usually)\n# predefined variables, see e.g.:\n# https://www.freebsd.org/doc/en/books/porters-handbook/porting-prefix.html\n# https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html\n# DESTDIR is used to deal with things like jails, with the system mounted\n# somewhere other than '/'.\n\nPREFIX=/usr/local\nPATH_LIB=$(PREFIX)/lib\nPATH_INCLUDE=$(PREFIX)/include\n\ninstall-dirs:\n\t@if [ ! -d \"$(DESTDIR)$(PATH_LIB)\" ] ; then \\\n\t\tmkdir -p \"$(DESTDIR)$(PATH_LIB)\" ; \\\n\t\tchmod 755 \"$(DESTDIR)$(PATH_LIB)\" ; \\\n\tfi\n\t@if [ ! -d \"$(DESTDIR)$(PATH_INCLUDE)\" ] ; then \\\n\t\tmkdir -p \"$(DESTDIR)$(PATH_INCLUDE)\" ; \\\n\t\tchmod 755 \"$(DESTDIR)$(PATH_INCLUDE)\" ; \\\n\tfi\n\ninstall:\n\t@$(MAKE) install-dirs\n\tif [ -f \"$(LIBNAME)\" ] ; then \\\n\t\tcp \"$(LIBNAME)\" \"$(DESTDIR)$(PATH_LIB)\" ; \\\n\t\tchmod 644 \"$(DESTDIR)$(PATH_LIB)/$(LIBNAME)\" ; \\\n\tfi\n\tif [ -f \"$(SLIBNAME)\" ] ; then \\\n\t\tcp \"$(SLIBNAME)\" \"$(DESTDIR)$(PATH_LIB)\" ; \\\n\t\tchmod 755 \"$(DESTDIR)$(PATH_LIB)/$(SLIBNAME)\" ; \\\n\t\tln -s \"$(SLIBNAME)\" \"$(DESTDIR)$(PATH_LIB)/lib$(PROJ).so.$(MAJ)\" ; \\\n\t\tln -s \"$(SLIBNAME)\" \"$(DESTDIR)$(PATH_LIB)/lib$(PROJ).so\" ; \\\n\tfi\n\tif [ -f \"$(DYLIBNAME)\" ] ; then \\\n\t\tcp \"$(DYLIBNAME)\" \"$(DESTDIR)$(PATH_LIB)\" ; \\\n\t\tchmod 755 \"$(DESTDIR)$(PATH_LIB)/$(DYLIBNAME)\" ; \\\n\tfi\n\tcp cryptlib.h \"$(DESTDIR)$(PATH_INCLUDE)\"\n\tchmod 644 \"$(DESTDIR)$(PATH_INCLUDE)/cryptlib.h\"\n\n# Frohe Ostern.\n\nbabies:\n\t@echo \"Good grief, what do you think I am?  Unix is capable, but not that capable.\"\n\ncookies:\n\t@echo \"Mix 250g flour, 150g sugar, 125g butter, an egg, a few drops of vanilla\"\n\t@echo \"essence, and 1 tsp baking powder into a dough, cut cookies from rolls of\"\n\t@echo \"dough, bake for about 15 minutes at 180C until they turn very light brown\"\n\t@echo \"at the edges.\"\n\nlove:\n\t@echo \"Nicht wahr?\"\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\tC Module Targets\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# Main directory\n\n$(OBJPATH)cryptapi.o:\t$(CRYPT_DEP) cryptapi.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptapi.o cryptapi.c\n\n$(OBJPATH)cryptcrt.o:\t$(CRYPT_DEP) $(CERT_DEP) cryptcrt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptcrt.o cryptcrt.c\n\n$(OBJPATH)cryptctx.o:\t$(CRYPT_DEP) context/context.h cryptctx.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptctx.o cryptctx.c\n\n$(OBJPATH)cryptdev.o:\t$(CRYPT_DEP) device/device.h cryptdev.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptdev.o cryptdev.c\n\n$(OBJPATH)cryptenv.o:\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tcryptenv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptenv.o cryptenv.c\n\n$(OBJPATH)cryptkey.o:\t$(CRYPT_DEP) keyset/keyset.h cryptkey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptkey.o cryptkey.c\n\n$(OBJPATH)cryptlib.o:\t$(CRYPT_DEP) cryptlib.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptlib.o cryptlib.c\n\n$(OBJPATH)cryptses.o:\t$(CRYPT_DEP) session/session.h cryptses.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptses.o cryptses.c\n\n$(OBJPATH)cryptusr.o:\t$(CRYPT_DEP) misc/user.h cryptusr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cryptusr.o cryptusr.c\n\n# Additional modules whose use needs to be explicitly enabled by the user.\n\n$(OBJPATH)java_jni.o:\t$(CRYPT_DEP) bindings/java_jni.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)java_jni.o bindings/java_jni.c\n\n# bn subdirectory\n\n$(OBJPATH)bn_asm.o:\t\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_asm.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_asm.o bn/bn_asm.c\n\n$(OBJPATH)bn_exp.o:\t\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_exp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_exp.o bn/bn_exp.c\n\n$(OBJPATH)bn_exp2.o:\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_exp2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_exp2.o bn/bn_exp2.c\n\n$(OBJPATH)bn_gcd.o:\t\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_gcd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_gcd.o bn/bn_gcd.c\n\n$(OBJPATH)bn_mul.o:\t\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_mul.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_mul.o bn/bn_mul.c\n\n$(OBJPATH)bn_recp.o:\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/bn_recp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)bn_recp.o bn/bn_recp.c\n\n$(OBJPATH)ec_lib.o:\t\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/ec.h bn/ec_lib.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ec_lib.o bn/ec_lib.c\n\n$(OBJPATH)ecp_mont.o:\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/ec.h bn/ecp_mont.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ecp_mont.o bn/ecp_mont.c\n\n$(OBJPATH)ecp_smpl.o:\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/ec.h bn/ecp_smpl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ecp_smpl.o bn/ecp_smpl.c\n\n$(OBJPATH)ec_mult.o:\tcrypt/osconfig.h bn/bn.h bn/bn_lcl.h bn/ec.h bn/ec_mult.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ec_mult.o bn/ec_mult.c\n\n# cert subdirectory\n\n$(OBJPATH)certrev.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certrev.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certrev.o cert/certrev.c\n\n$(OBJPATH)certschk.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certschk.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certschk.o cert/certschk.c\n\n$(OBJPATH)certsign.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certsign.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certsign.o cert/certsign.c\n\n$(OBJPATH)certval.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certval.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certval.o cert/certval.c\n\n$(OBJPATH)chain.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/chain.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)chain.o cert/chain.c\n\n$(OBJPATH)chk_cert.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/chk_cert.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)chk_cert.o cert/chk_cert.c\n\n$(OBJPATH)chk_chn.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/chk_chn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)chk_chn.o cert/chk_chn.c\n\n$(OBJPATH)chk_san.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/chk_san.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)chk_san.o cert/chk_san.c\n\n$(OBJPATH)chk_use.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/chk_use.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)chk_use.o cert/chk_use.c\n\n$(OBJPATH)comp_cert.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_cert.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_cert.o cert/comp_cert.c\n\n$(OBJPATH)comp_curs.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_curs.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_curs.o cert/comp_curs.c\n\n$(OBJPATH)comp_del.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_del.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_del.o cert/comp_del.c\n\n$(OBJPATH)comp_get.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_get.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_get.o cert/comp_get.c\n\n$(OBJPATH)comp_gets.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_gets.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_gets.o cert/comp_gets.c\n\n$(OBJPATH)comp_pkiu.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_pkiu.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_pkiu.o cert/comp_pkiu.c\n\n$(OBJPATH)comp_set.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/comp_set.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)comp_set.o cert/comp_set.c\n\n$(OBJPATH)dn.o:\t\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/dn.h cert/dn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dn.o cert/dn.c\n\n$(OBJPATH)dn_rw.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/dn.h cert/dn_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dn_rw.o cert/dn_rw.c\n\n$(OBJPATH)dn_rws.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/dn.h cert/dn_rws.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dn_rws.o cert/dn_rws.c\n\n$(OBJPATH)dn_string.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/dn.h cert/dn_string.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dn_string.o cert/dn_string.c\n\n$(OBJPATH)ext.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext.o cert/ext.c\n\n$(OBJPATH)ext_add.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_add.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_add.o cert/ext_add.c\n\n$(OBJPATH)ext_chk.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_chk.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_chk.o cert/ext_chk.c\n\n$(OBJPATH)ext_copy.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_copy.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_copy.o cert/ext_copy.c\n\n$(OBJPATH)ext_def.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_def.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_def.o cert/ext_def.c\n\n$(OBJPATH)ext_rd.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_rd.o cert/ext_rd.c\n\n$(OBJPATH)ext_wr.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/certattr.h cert/ext_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ext_wr.o cert/ext_wr.c\n\n$(OBJPATH)imp_chk.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/imp_chk.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)imp_chk.o cert/imp_chk.c\n\n$(OBJPATH)imp_exp.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/imp_exp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)imp_exp.o cert/imp_exp.c\n\n$(OBJPATH)read.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/read.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)read.o cert/read.c\n\n$(OBJPATH)trustmgr.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/trustmgr.h cert/trustmgr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)trustmgr.o cert/trustmgr.c\n\n$(OBJPATH)write.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/write.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)write.o cert/write.c\n\n$(OBJPATH)write_pre.o:\t$(CRYPT_DEP) $(ASN1_DEP) $(CERT_DEP) cert/write_pre.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)write_pre.o cert/write_pre.c\n\n# context subdirectory\n\n$(OBJPATH)ctx_3des.o:\t$(CRYPT_DEP) context/context.h crypt/des.h context/ctx_3des.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_3des.o context/ctx_3des.c\n\n$(OBJPATH)ctx_aes.o:\t$(CRYPT_DEP) context/context.h crypt/aes.h crypt/aes_ni.h \\\n\t\t\t\t\t\tcrypt/aes_via_ace.h crypt/aesopt.h context/ctx_aes.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_aes.o context/ctx_aes.c\n\n$(OBJPATH)ctx_attr.o:\t$(CRYPT_DEP) context/context.h context/ctx_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_attr.o context/ctx_attr.c\n\n$(OBJPATH)ctx_bn.o:\t\t$(CRYPT_DEP) context/context.h context/ctx_bn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bn.o context/ctx_bn.c\n\n$(OBJPATH)ctx_bnmath.o:\t$(CRYPT_DEP) context/context.h context/ctx_bnmath.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bnmath.o context/ctx_bnmath.c\n\n$(OBJPATH)ctx_bnpkc.o:\t$(CRYPT_DEP) context/context.h context/ctx_bnpkc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bnpkc.o context/ctx_bnpkc.c\n\n$(OBJPATH)ctx_bnprime.o:\t$(CRYPT_DEP) context/context.h context/ctx_bnprime.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bnprime.o context/ctx_bnprime.c\n\n$(OBJPATH)ctx_bnrw.o:\t$(CRYPT_DEP) context/context.h context/ctx_bnrw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bnrw.o context/ctx_bnrw.c\n\n$(OBJPATH)ctx_bnsieve.o:\t$(CRYPT_DEP) context/context.h context/ctx_bnsieve.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bnsieve.o context/ctx_bnsieve.c\n\n$(OBJPATH)ctx_bntest.o:\t$(CRYPT_DEP) context/context.h context/ctx_bntest.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_bntest.o context/ctx_bntest.c\n\n$(OBJPATH)ctx_cast.o:\t$(CRYPT_DEP) context/context.h crypt/cast.h context/ctx_cast.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_cast.o context/ctx_cast.c\n\n$(OBJPATH)ctx_des.o:\t$(CRYPT_DEP) context/context.h crypt/testdes.h crypt/des.h \\\n\t\t\t\t\t\tcontext/ctx_des.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_des.o context/ctx_des.c\n\n$(OBJPATH)ctx_dh.o:\t\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_dh.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_dh.o context/ctx_dh.c\n\n$(OBJPATH)ctx_dsa.o:\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_dsa.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_dsa.o context/ctx_dsa.c\n\n$(OBJPATH)ctx_ecdh.o:\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_ecdh.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_ecdh.o context/ctx_ecdh.c\n\n$(OBJPATH)ctx_ecdsa.o:\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_ecdsa.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_ecdsa.o context/ctx_ecdsa.c\n\n$(OBJPATH)ctx_elg.o:\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_elg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_elg.o context/ctx_elg.c\n\n$(OBJPATH)ctx_encr.o:\t$(CRYPT_DEP) context/context.h context/ctx_encr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_encr.o context/ctx_encr.c\n\n$(OBJPATH)ctx_generic.o: $(CRYPT_DEP) context/context.h context/ctx_generic.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_generic.o context/ctx_generic.c\n\n$(OBJPATH)ctx_hsha.o:\t$(CRYPT_DEP) context/context.h crypt/sha.h context/ctx_hsha.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_hsha.o context/ctx_hsha.c\n\n$(OBJPATH)ctx_hsha2.o:\t$(CRYPT_DEP) context/context.h crypt/sha2.h context/ctx_hsha2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_hsha2.o context/ctx_hsha2.c\n\n$(OBJPATH)ctx_idea.o:\t$(CRYPT_DEP) context/context.h crypt/idea.h context/ctx_idea.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_idea.o context/ctx_idea.c\n\n$(OBJPATH)ctx_md5.o:\t$(CRYPT_DEP) context/context.h crypt/md5.h context/ctx_md5.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_md5.o context/ctx_md5.c\n\n$(OBJPATH)ctx_misc.o:\t$(CRYPT_DEP) context/context.h context/ctx_misc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_misc.o context/ctx_misc.c\n\n$(OBJPATH)ctx_rc2.o:\t$(CRYPT_DEP) context/context.h crypt/rc2.h context/ctx_rc2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_rc2.o context/ctx_rc2.c\n\n$(OBJPATH)ctx_rc4.o:\t$(CRYPT_DEP) context/context.h crypt/rc4.h context/ctx_rc4.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_rc4.o context/ctx_rc4.c\n\n$(OBJPATH)ctx_rsa.o:\t$(CRYPT_DEP) context/context.h bn/bn.h context/ctx_rsa.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_rsa.o context/ctx_rsa.c\n\n$(OBJPATH)ctx_sha.o:\t$(CRYPT_DEP) context/context.h crypt/sha.h context/ctx_sha.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_sha.o context/ctx_sha.c\n\n$(OBJPATH)ctx_sha2.o:\t$(CRYPT_DEP) context/context.h crypt/sha2.h context/ctx_sha2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ctx_sha2.o context/ctx_sha2.c\n\n$(OBJPATH)kg_dlp.o:\t\t$(CRYPT_DEP) context/context.h context/kg_dlp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)kg_dlp.o context/kg_dlp.c\n\n$(OBJPATH)kg_ecc.o:\t\t$(CRYPT_DEP) context/context.h context/kg_ecc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)kg_ecc.o context/kg_ecc.c\n\n$(OBJPATH)kg_prime.o:\t$(CRYPT_DEP) context/context.h context/kg_prime.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)kg_prime.o context/kg_prime.c\n\n$(OBJPATH)kg_rsa.o:\t\t$(CRYPT_DEP) context/context.h context/kg_rsa.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)kg_rsa.o context/kg_rsa.c\n\n$(OBJPATH)keyload.o:\t$(CRYPT_DEP) context/context.h context/keyload.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)keyload.o context/keyload.c\n\n$(OBJPATH)key_id.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) context/key_id.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_id.o context/key_id.c\n\n$(OBJPATH)key_rdpri.o:\t$(CRYPT_DEP) $(ASN1_DEP) context/key_rdpri.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_rdpri.o context/key_rdpri.c\n\n$(OBJPATH)key_rdpub.o:\t$(CRYPT_DEP) $(ASN1_DEP) context/key_rdpub.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_rdpub.o context/key_rdpub.c\n\n$(OBJPATH)key_wr.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) context/key_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_wr.o context/key_wr.c\n\n# crypt subdirectory - crypt algos\n\n$(OBJPATH)aes_modes.o:\t$(CRYPT_DEP) crypt/aes.h crypt/aes_ni.h crypt/aes_via_ace.h \\\n\t\t\t\t\t\tcrypt/aesopt.h crypt/aes_modes.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)aes_modes.o crypt/aes_modes.c\n\n$(OBJPATH)aes_ni.o:\t\t$(CRYPT_DEP) crypt/aes.h crypt/aes_ni.h crypt/aes_via_ace.h \\\n\t\t\t\t\t\tcrypt/aes_ni.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)aes_ni.o crypt/aes_ni.c\n\n$(OBJPATH)aescrypt.o:\t$(CRYPT_DEP) crypt/aes.h crypt/aes_ni.h crypt/aes_via_ace.h \\\n\t\t\t\t\t\tcrypt/aescrypt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)aescrypt.o crypt/aescrypt.c\n\n$(OBJPATH)aeskey.o:\t\t$(CRYPT_DEP) crypt/aes.h crypt/aes_ni.h crypt/aes_via_ace.h \\\n\t\t\t\t\t\tcrypt/aeskey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)aeskey.o crypt/aeskey.c\n\n$(OBJPATH)aestab.o:\t\t$(CRYPT_DEP) crypt/aes.h crypt/aes_ni.h crypt/aes_via_ace.h \\\n\t\t\t\t\t\tcrypt/aestab.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)aestab.o crypt/aestab.c\n\n$(OBJPATH)castecb.o:\tcrypt/osconfig.h crypt/cast.h crypt/castlcl.h crypt/castecb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)castecb.o crypt/castecb.c\n\n$(OBJPATH)castenc.o:\tcrypt/osconfig.h crypt/cast.h crypt/castlcl.h crypt/castenc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)castenc.o crypt/castenc.c\n\n$(OBJPATH)castskey.o:\tcrypt/osconfig.h crypt/cast.h crypt/castlcl.h crypt/castsbox.h \\\n\t\t\t\t\t\tcrypt/castskey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)castskey.o crypt/castskey.c\n\n$(OBJPATH)descbc.o:\t\tcrypt/osconfig.h crypt/des.h crypt/deslocl.h crypt/descbc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)descbc.o crypt/descbc.c\n\n$(OBJPATH)desecb.o:\t\tcrypt/osconfig.h crypt/des.h crypt/deslocl.h crypt/desecb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)desecb.o crypt/desecb.c\n\n$(OBJPATH)desecb3.o:\tcrypt/osconfig.h crypt/des.h crypt/deslocl.h crypt/desecb3.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)desecb3.o crypt/desecb3.c\n\n$(OBJPATH)desenc.o:\t\tcrypt/osconfig.h crypt/des.h crypt/deslocl.h crypt/desenc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)desenc.o crypt/desenc.c\n\n$(OBJPATH)desskey.o:\tcrypt/osconfig.h crypt/des.h crypt/deslocl.h crypt/desskey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)desskey.o crypt/desskey.c\n\n$(OBJPATH)gcm.o:\t\t$(CRYPT_DEP) crypt/gf128mul.h crypt/gcm.h crypt/mode_hdr.h \\\n\t\t\t\t\t\tcrypt/gcm.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)gcm.o crypt/gcm.c\n\n$(OBJPATH)gf128mul.o:\t$(CRYPT_DEP) crypt/gf128mul.h crypt/mode_hdr.h \\\n\t\t\t\t\t\tcrypt/gf_mul_lo.h crypt/gf128mul.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)gf128mul.o crypt/gf128mul.c\n\n$(OBJPATH)icbc.o:\t\t$(CRYPT_DEP) crypt/idea.h crypt/idealocl.h crypt/icbc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)icbc.o crypt/icbc.c\n\n$(OBJPATH)iecb.o:\t\t$(CRYPT_DEP) crypt/idea.h crypt/idealocl.h crypt/iecb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)iecb.o crypt/iecb.c\n\n$(OBJPATH)iskey.o:\t\t$(CRYPT_DEP) crypt/idea.h crypt/idealocl.h crypt/iskey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)iskey.o crypt/iskey.c\n\n$(OBJPATH)rc2cbc.o:\t\tcrypt/osconfig.h crypt/rc2.h crypt/rc2locl.h crypt/rc2cbc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rc2cbc.o crypt/rc2cbc.c\n\n$(OBJPATH)rc2ecb.o:\t\tcrypt/osconfig.h crypt/rc2.h crypt/rc2locl.h crypt/rc2ecb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rc2ecb.o crypt/rc2ecb.c\n\n$(OBJPATH)rc2skey.o:\tcrypt/osconfig.h crypt/rc2.h crypt/rc2locl.h crypt/rc2skey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rc2skey.o crypt/rc2skey.c\n\n$(OBJPATH)rc4enc.o:\t\tcrypt/osconfig.h crypt/rc4.h crypt/rc4locl.h crypt/rc4enc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rc4enc.o crypt/rc4enc.c\n\n$(OBJPATH)rc4skey.o:\tcrypt/osconfig.h crypt/rc4.h crypt/rc4locl.h crypt/rc4skey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rc4skey.o crypt/rc4skey.c\n\n# crypt subdirectory - hash algos\n\n$(OBJPATH)md5dgst.o:\tcrypt/osconfig.h crypt/md5.h crypt/md5locl.h \\\n\t\t\t\t\t\tcrypt/md32com.h crypt/md5dgst.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)md5dgst.o crypt/md5dgst.c\n\n$(OBJPATH)sha1dgst.o:\tcrypt/osconfig.h crypt/sha.h crypt/sha1locl.h \\\n\t\t\t\t\t\tcrypt/md32com.h crypt/sha1dgst.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sha1dgst.o crypt/sha1dgst.c\n\n$(OBJPATH)sha2.o:\t\tcrypt/osconfig.h crypt/sha.h crypt/sha1locl.h crypt/sha2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sha2.o crypt/sha2.c\n\n# device subdirectory\n\n$(OBJPATH)dev_attr.o:\t$(CRYPT_DEP) device/device.h device/dev_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dev_attr.o device/dev_attr.c\n\n$(OBJPATH)hardware.o:\t$(CRYPT_DEP) device/device.h device/hardware.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)hardware.o device/hardware.c\n\n$(OBJPATH)hw_dummy.o:\t$(CRYPT_DEP) device/device.h device/hw_dummy.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)hw_dummy.o device/hw_dummy.c\n\n$(OBJPATH)pkcs11.o:\t\t$(CRYPT_DEP) device/device.h device/pkcs11_api.h device/pkcs11.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs11.o device/pkcs11.c\n\n$(OBJPATH)pkcs11_init.o: $(CRYPT_DEP) device/device.h device/pkcs11_api.h \\\n\t\t\t\t\t\tdevice/pkcs11_init.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs11_init.o device/pkcs11_init.c\n\n$(OBJPATH)pkcs11_pkc.o:\t$(CRYPT_DEP) device/device.h device/pkcs11_api.h \\\n\t\t\t\t\t\tdevice/pkcs11_pkc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs11_pkc.o device/pkcs11_pkc.c\n\n$(OBJPATH)pkcs11_rd.o:\t$(CRYPT_DEP) device/device.h device/pkcs11_api.h \\\n\t\t\t\t\t\tdevice/pkcs11_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs11_rd.o device/pkcs11_rd.c\n\n$(OBJPATH)pkcs11_wr.o:\t$(CRYPT_DEP) device/device.h device/pkcs11_api.h \\\n\t\t\t\t\t\tdevice/pkcs11_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs11_wr.o device/pkcs11_wr.c\n\n$(OBJPATH)system.o:\t\t$(CRYPT_DEP) device/device.h device/capabil.h device/system.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)system.o device/system.c\n\n# enc_dec subdirectory\n\n$(OBJPATH)asn1_algid.o:\t$(CRYPT_DEP) $(ASN1_DEP) enc_dec/asn1_algid.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)asn1_algid.o enc_dec/asn1_algid.c\n\n$(OBJPATH)asn1_chk.o:\t$(CRYPT_DEP) $(ASN1_DEP) enc_dec/asn1_chk.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)asn1_chk.o enc_dec/asn1_chk.c\n\n$(OBJPATH)asn1_ext.o:\t$(CRYPT_DEP) $(ASN1_DEP) enc_dec/asn1_oids.h enc_dec/asn1_ext.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)asn1_ext.o enc_dec/asn1_ext.c\n\n$(OBJPATH)asn1_rd.o:\t$(CRYPT_DEP) $(ASN1_DEP) enc_dec/asn1_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)asn1_rd.o enc_dec/asn1_rd.c\n\n$(OBJPATH)asn1_wr.o:\t$(CRYPT_DEP) $(ASN1_DEP) enc_dec/asn1_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)asn1_wr.o enc_dec/asn1_wr.c\n\n$(OBJPATH)base64.o:\t\t$(CRYPT_DEP) enc_dec/base64.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)base64.o enc_dec/base64.c\n\n$(OBJPATH)base64_id.o:\t$(CRYPT_DEP) enc_dec/base64_id.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)base64_id.o enc_dec/base64_id.c\n\n$(OBJPATH)misc_rw.o:\t$(CRYPT_DEP) $(IO_DEP) enc_dec/misc_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)misc_rw.o enc_dec/misc_rw.c\n\n$(OBJPATH)pgp_rw.o:\t\t$(CRYPT_DEP) $(IO_DEP) enc_dec/pgp_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_rw.o enc_dec/pgp_rw.c\n\n# envelope subdirectory\n\n$(OBJPATH)cms_denv.o:\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tenvelope/cms_denv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cms_denv.o envelope/cms_denv.c\n\n$(OBJPATH)cms_env.o:\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tenvelope/cms_env.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cms_env.o envelope/cms_env.c\n\n$(OBJPATH)cms_envpre.o:\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tenvelope/cms_envpre.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cms_envpre.o envelope/cms_envpre.c\n\n$(OBJPATH)decode.o:\t\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tenvelope/decode.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)decode.o envelope/decode.c\n\n$(OBJPATH)encode.o:\t\t$(CRYPT_DEP) envelope/envelope.h $(ASN1_DEP) \\\n\t\t\t\t\t\tenvelope/encode.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)encode.o envelope/encode.c\n\n$(OBJPATH)env_attr.o:\t$(CRYPT_DEP) envelope/envelope.h envelope/env_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)env_attr.o envelope/env_attr.c\n\n$(OBJPATH)pgp_denv.o:\t$(CRYPT_DEP) $(IO_DEP) misc/pgp.h envelope/pgp_denv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_denv.o envelope/pgp_denv.c\n\n$(OBJPATH)pgp_env.o:\t$(CRYPT_DEP) $(IO_DEP) misc/pgp.h envelope/pgp_env.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_env.o envelope/pgp_env.c\n\n$(OBJPATH)res_actn.o:\t$(CRYPT_DEP) envelope/envelope.h envelope/res_actn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)res_actn.o envelope/res_actn.c\n\n$(OBJPATH)res_denv.o:\t$(CRYPT_DEP) envelope/envelope.h envelope/res_denv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)res_denv.o envelope/res_denv.c\n\n$(OBJPATH)res_env.o:\t$(CRYPT_DEP) envelope/envelope.h envelope/res_env.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)res_env.o envelope/res_env.c\n\n# io subdirectory\n\n$(OBJPATH)dns.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/dns.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dns.o io/dns.c\n\n$(OBJPATH)dns_srv.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/dns_srv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dns_srv.o io/dns_srv.c\n\n$(OBJPATH)file.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/file.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)file.o io/file.c\n\n$(OBJPATH)http.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/http.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)http.o io/http.c\n\n$(OBJPATH)http_rd.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/http_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)http_rd.o io/http_rd.c\n\n$(OBJPATH)http_parse.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/http_parse.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)http_parse.o io/http_parse.c\n\n$(OBJPATH)http_wr.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/http_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)http_wr.o io/http_wr.c\n\n$(OBJPATH)memory.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/memory.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)memory.o io/memory.c\n\n$(OBJPATH)net.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/net.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)net.o io/net.c\n\n$(OBJPATH)net_proxy.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/net_proxy.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)net_proxy.o io/net_proxy.c\n\n$(OBJPATH)net_trans.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/net_trans.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)net_trans.o io/net_trans.c\n\n$(OBJPATH)net_url.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/net_url.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)net_url.o io/net_url.c\n\n$(OBJPATH)stream.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/stream.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)stream.o io/stream.c\n\n$(OBJPATH)tcp.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/tcp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)tcp.o io/tcp.c\n\n$(OBJPATH)tcp_conn.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/tcp_conn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)tcp_conn.o io/tcp_conn.c\n\n$(OBJPATH)tcp_err.o:\t$(CRYPT_DEP) $(IO_DEP_INT) io/tcp_err.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)tcp_err.o io/tcp_err.c\n\n$(OBJPATH)tcp_rw.o:\t\t$(CRYPT_DEP) $(IO_DEP_INT) io/tcp_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)tcp_rw.o io/tcp_rw.c\n\n# kernel subdirectory\n\n$(OBJPATH)attr_acl.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/attr_acl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)attr_acl.o kernel/attr_acl.c\n\n$(OBJPATH)certm_acl.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/certm_acl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certm_acl.o kernel/certm_acl.c\n\n$(OBJPATH)init.o:\t\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/init.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)init.o kernel/init.c\n\n$(OBJPATH)int_msg.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/int_msg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_msg.o kernel/int_msg.c\n\n$(OBJPATH)key_acl.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/key_acl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_acl.o kernel/key_acl.c\n\n$(OBJPATH)mech_acl.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/mech_acl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_acl.o kernel/mech_acl.c\n\n$(OBJPATH)msg_acl.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/msg_acl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)msg_acl.o kernel/msg_acl.c\n\n$(OBJPATH)obj_acc.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/obj_acc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)obj_acc.o kernel/obj_acc.c\n\n$(OBJPATH)objects.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/objects.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)objects.o kernel/objects.c\n\n$(OBJPATH)sec_mem.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/sec_mem.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sec_mem.o kernel/sec_mem.c\n\n$(OBJPATH)selftest.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/selftest.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)selftest.o kernel/selftest.c\n\n$(OBJPATH)semaphore.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/semaphore.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)semaphore.o kernel/semaphore.c\n\n$(OBJPATH)sendmsg.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/sendmsg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sendmsg.o kernel/sendmsg.c\n\n$(OBJPATH)storage.o:\t$(CRYPT_DEP) $(KERNEL_DEP) kernel/storage.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)storage.o kernel/storage.c\n\n# keyset subdirectory\n\n$(OBJPATH)dbms.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/dbms.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dbms.o keyset/dbms.c\n\n$(OBJPATH)ca_add.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/ca_add.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ca_add.o keyset/ca_add.c\n\n$(OBJPATH)ca_clean.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/ca_clean.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ca_clean.o keyset/ca_clean.c\n\n$(OBJPATH)ca_issue.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/ca_issue.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ca_issue.o keyset/ca_issue.c\n\n$(OBJPATH)ca_misc.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/ca_misc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ca_misc.o keyset/ca_misc.c\n\n$(OBJPATH)ca_rev.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/ca_rev.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ca_rev.o keyset/ca_rev.c\n\n$(OBJPATH)dbx_misc.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/dbx_misc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dbx_misc.o keyset/dbx_misc.c\n\n$(OBJPATH)dbx_rd.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/dbx_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dbx_rd.o keyset/dbx_rd.c\n\n$(OBJPATH)dbx_wr.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/dbx_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)dbx_wr.o keyset/dbx_wr.c\n\n$(OBJPATH)http_keys.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/http_keys.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)http_keys.o keyset/http_keys.c\n\n$(OBJPATH)key_attr.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/key_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)key_attr.o keyset/key_attr.c\n\n$(OBJPATH)ldap.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/ldap.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ldap.o keyset/ldap.c\n\n$(OBJPATH)odbc.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/odbc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)odbc.o keyset/odbc.c\n\n$(OBJPATH)pgp.o:\t\t$(CRYPT_DEP) misc/pgp.h keyset/pgp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp.o keyset/pgp.c\n\n$(OBJPATH)pgp_rd.o:\t\t$(CRYPT_DEP) misc/pgp.h keyset/pgp_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_rd.o keyset/pgp_rd.c\n\n$(OBJPATH)pgp_wr.o:\t\t$(CRYPT_DEP) misc/pgp.h keyset/pgp_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_wr.o keyset/pgp_wr.c\n\n$(OBJPATH)pkcs12.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs12.h keyset/pkcs12.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs12.o keyset/pkcs12.c\n\n$(OBJPATH)pkcs12_rd.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs12.h keyset/pkcs12_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs12_rd.o keyset/pkcs12_rd.c\n\n$(OBJPATH)pkcs12_rdo.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs12.h keyset/pkcs12_rdo.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs12_rdo.o keyset/pkcs12_rdo.c\n\n$(OBJPATH)pkcs12_wr.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs12.h keyset/pkcs12_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs12_wr.o keyset/pkcs12_wr.c\n\n$(OBJPATH)pkcs15.o:\t\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15.o keyset/pkcs15.c\n\n$(OBJPATH)pkcs15_add.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_add.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_add.o keyset/pkcs15_add.c\n\n$(OBJPATH)pkcs15_adpb.o: $(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_adpb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_adpb.o keyset/pkcs15_adpb.c\n\n$(OBJPATH)pkcs15_adpr.o: $(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_adpr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_adpr.o keyset/pkcs15_adpr.c\n\n$(OBJPATH)pkcs15_atrd.o: $(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_atrd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_atrd.o keyset/pkcs15_atrd.c\n\n$(OBJPATH)pkcs15_atwr.o: $(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_atwr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_atwr.o keyset/pkcs15_atwr.c\n\n$(OBJPATH)pkcs15_get.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_get.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_get.o keyset/pkcs15_get.c\n\n$(OBJPATH)pkcs15_getp.o: $(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_getp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_getp.o keyset/pkcs15_getp.c\n\n$(OBJPATH)pkcs15_rd.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_rd.o keyset/pkcs15_rd.c\n\n$(OBJPATH)pkcs15_set.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_set.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_set.o keyset/pkcs15_set.c\n\n$(OBJPATH)pkcs15_wr.o:\t$(CRYPT_DEP) keyset/keyset.h keyset/pkcs15.h keyset/pkcs15_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pkcs15_wr.o keyset/pkcs15_wr.c\n\n# mechanism subdirectory\n\n$(OBJPATH)keyex.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/keyex.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)keyex.o mechs/keyex.c\n\n$(OBJPATH)keyex_int.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/keyex_int.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)keyex_int.o mechs/keyex_int.c\n\n$(OBJPATH)keyex_rw.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/keyex_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)keyex_rw.o mechs/keyex_rw.c\n\n$(OBJPATH)mech_cwrap.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_cwrap.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_cwrap.o mechs/mech_cwrap.c\n\n$(OBJPATH)mech_drv.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_drv.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_drv.o mechs/mech_drv.c\n\n$(OBJPATH)mech_int.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_int.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_int.o mechs/mech_int.c\n\n$(OBJPATH)mech_pkwrap.o: $(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_pkwrap.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_pkwrap.o mechs/mech_pkwrap.c\n\n$(OBJPATH)mech_privk.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_privk.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_privk.o mechs/mech_privk.c\n\n$(OBJPATH)mech_sig.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/mech_sig.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)mech_sig.o mechs/mech_sig.c\n\n$(OBJPATH)obj_qry.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/obj_qry.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)obj_qry.o mechs/obj_qry.c\n\n$(OBJPATH)sign.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign.o mechs/sign.c\n\n$(OBJPATH)sign_cms.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign_cms.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign_cms.o mechs/sign_cms.c\n\n$(OBJPATH)sign_int.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign_int.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign_int.o mechs/sign_int.c\n\n$(OBJPATH)sign_pgp.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign_pgp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign_pgp.o mechs/sign_pgp.c\n\n$(OBJPATH)sign_rw.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign_rw.o mechs/sign_rw.c\n\n$(OBJPATH)sign_x509.o:\t$(CRYPT_DEP) $(ASN1_DEP) mechs/mech.h mechs/sign_x509.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sign_x509.o mechs/sign_x509.c\n\n# misc subdirectory\n\n$(OBJPATH)int_api.o:\t$(CRYPT_DEP) misc/int_api.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_api.o misc/int_api.c\n\n$(OBJPATH)int_attr.o:\t$(CRYPT_DEP) misc/int_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_attr.o misc/int_attr.c\n\n$(OBJPATH)int_debug.o:\t$(CRYPT_DEP) misc/int_debug.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_debug.o misc/int_debug.c\n\n$(OBJPATH)int_env.o:\t$(CRYPT_DEP) misc/int_env.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_env.o misc/int_env.c\n\n$(OBJPATH)int_err.o:\t$(CRYPT_DEP) misc/int_err.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_err.o misc/int_err.c\n\n$(OBJPATH)int_mem.o:\t$(CRYPT_DEP) misc/int_mem.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_mem.o misc/int_mem.c\n\n$(OBJPATH)int_string.o:\t$(CRYPT_DEP) misc/int_string.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_string.o misc/int_string.c\n\n$(OBJPATH)int_time.o:\t$(CRYPT_DEP) misc/int_time.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)int_time.o misc/int_time.c\n\n$(OBJPATH)os_spec.o: \t$(CRYPT_DEP) misc/os_spec.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)os_spec.o misc/os_spec.c\n\n$(OBJPATH)pgp_misc.o:\t$(CRYPT_DEP) $(IO_DEP) misc/pgp.h misc/pgp_misc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pgp_misc.o misc/pgp_misc.c\n\n$(OBJPATH)random.o:\t\t$(CRYPT_DEP) random/random.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)random.o random/random.c\n\n$(OBJPATH)rand_x917.o:\t$(CRYPT_DEP) random/rand_x917.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rand_x917.o random/rand_x917.c\n\n$(OBJPATH)unix.o:\t\t$(CRYPT_DEP) random/unix.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)unix.o random/unix.c\n\n$(OBJPATH)user.o:\t\t$(CRYPT_DEP) misc/user.h misc/user.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)user.o misc/user.c\n\n$(OBJPATH)user_attr.o:\t$(CRYPT_DEP) misc/user.h misc/user_int.h misc/user_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)user_attr.o misc/user_attr.c\n\n$(OBJPATH)user_cfg.o:\t$(CRYPT_DEP) misc/user.h misc/user_int.h misc/user_cfg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)user_cfg.o misc/user_cfg.c\n\n$(OBJPATH)user_rw.o:\t$(CRYPT_DEP) misc/user.h misc/user_int.h misc/user_rw.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)user_rw.o misc/user_rw.c\n\n# session subdirectory\n\n$(OBJPATH)certstore.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/certstore.h \\\n\t\t\t\t\t\tsession/certstore.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)certstore.o session/certstore.c\n\n$(OBJPATH)cmp.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp.o session/cmp.c\n\n$(OBJPATH)cmp_cli.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_cli.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_cli.o session/cmp_cli.c\n\n$(OBJPATH)cmp_crypt.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_crypt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_crypt.o session/cmp_crypt.c\n\n$(OBJPATH)cmp_err.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_err.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_err.o session/cmp_err.c\n\n$(OBJPATH)cmp_rd.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_rd.o session/cmp_rd.c\n\n$(OBJPATH)cmp_rdmsg.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_rdmsg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_rdmsg.o session/cmp_rdmsg.c\n\n$(OBJPATH)cmp_svr.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_svr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_svr.o session/cmp_svr.c\n\n$(OBJPATH)cmp_wr.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_wr.o session/cmp_wr.c\n\n$(OBJPATH)cmp_wrmsg.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/cmp_wrmsg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)cmp_wrmsg.o session/cmp_wrmsg.c\n\n$(OBJPATH)ocsp.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/ocsp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ocsp.o session/ocsp.c\n\n$(OBJPATH)pnppki.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/cmp.h \\\n\t\t\t\t\t\tsession/pnppki.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)pnppki.o session/pnppki.c\n\n$(OBJPATH)rtcs.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/rtcs.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)rtcs.o session/rtcs.c\n\n$(OBJPATH)scep.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/scep.h \\\n\t\t\t\t\t\tsession/scep.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)scep.o session/scep.c\n\n$(OBJPATH)scep_cli.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/scep.h \\\n\t\t\t\t\t\tsession/scep_cli.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)scep_cli.o session/scep_cli.c\n\n$(OBJPATH)scep_svr.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/certstore.h \\\n\t\t\t\t\t\tsession/scep.h session/scep_svr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)scep_svr.o session/scep_svr.c\n\n$(OBJPATH)scorebrd.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/scorebrd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)scorebrd.o session/scorebrd.c\n\n$(OBJPATH)sess_attr.o:\t$(CRYPT_DEP) session/session.h session/sess_attr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sess_attr.o session/sess_attr.c\n\n$(OBJPATH)sess_iattr.o:\t$(CRYPT_DEP) session/session.h session/sess_iattr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sess_iattr.o session/sess_iattr.c\n\n$(OBJPATH)sess_rd.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/sess_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sess_rd.o session/sess_rd.c\n\n$(OBJPATH)sess_wr.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/sess_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sess_wr.o session/sess_wr.c\n\n$(OBJPATH)sess_ws.o:\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/sess_ws.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)sess_ws.o session/sess_ws.c\n\n$(OBJPATH)session.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/session.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)session.o session/session.c\n\n$(OBJPATH)ssh.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh.o session/ssh.c\n\n$(OBJPATH)ssh2.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2.o session/ssh2.c\n\n$(OBJPATH)ssh2_authc.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_authc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_authc.o session/ssh2_authc.c\n\n$(OBJPATH)ssh2_auths.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_auths.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_auths.o session/ssh2_auths.c\n\n$(OBJPATH)ssh2_chn.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_chn.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_chn.o session/ssh2_chn.c\n\n$(OBJPATH)ssh2_cli.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_cli.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_cli.o session/ssh2_cli.c\n\n$(OBJPATH)ssh2_crypt.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_crypt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_crypt.o session/ssh2_crypt.c\n\n$(OBJPATH)ssh2_msg.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_msg.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_msg.o session/ssh2_msg.c\n\n$(OBJPATH)ssh2_msgc.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_msgc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_msgc.o session/ssh2_msgc.c\n\n$(OBJPATH)ssh2_msgs.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_msgs.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_msgs.o session/ssh2_msgs.c\n\n$(OBJPATH)ssh2_rd.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_rd.o session/ssh2_rd.c\n\n$(OBJPATH)ssh2_svr.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_svr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_svr.o session/ssh2_svr.c\n\n$(OBJPATH)ssh2_wr.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssh.h \\\n\t\t\t\t\t\tsession/ssh2_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssh2_wr.o session/ssh2_wr.c\n\n$(OBJPATH)ssl.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl.o session/ssl.c\n\n$(OBJPATH)ssl_cli.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_cli.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_cli.o session/ssl_cli.c\n\n$(OBJPATH)ssl_crypt.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_crypt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_crypt.o session/ssl_crypt.c\n\n$(OBJPATH)ssl_ext.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_ext.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_ext.o session/ssl_ext.c\n\n$(OBJPATH)ssl_hs.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_hs.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_hs.o session/ssl_hs.c\n\n$(OBJPATH)ssl_hsc.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_hsc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_hsc.o session/ssl_hsc.c\n\n$(OBJPATH)ssl_kmgmt.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_kmgmt.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_kmgmt.o session/ssl_kmgmt.c\n\n$(OBJPATH)ssl_rd.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_rd.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_rd.o session/ssl_rd.c\n\n$(OBJPATH)ssl_suites.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_suites.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_suites.o session/ssl_suites.c\n\n$(OBJPATH)ssl_svr.o:\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_svr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_svr.o session/ssl_svr.c\n\n$(OBJPATH)ssl_wr.o:\t\t$(CRYPT_DEP) $(IO_DEP) session/session.h session/ssl.h \\\n\t\t\t\t\t\tsession/ssl_wr.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)ssl_wr.o session/ssl_wr.c\n\n$(OBJPATH)tsp.o:\t\t$(CRYPT_DEP) $(ASN1_DEP) session/session.h session/tsp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)tsp.o session/tsp.c\n\n# zlib subdirectory\n\n$(OBJPATH)adler32.o:\t$(ZLIB_DEP) zlib/adler32.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)adler32.o zlib/adler32.c\n\n$(OBJPATH)deflate.o:\t$(ZLIB_DEP) zlib/deflate.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)deflate.o zlib/deflate.c\n\n$(OBJPATH)inffast.o:\t$(ZLIB_DEP) zlib/inffast.h zlib/inffixed.h \\\n\t\t\t\t\t\tzlib/inftrees.h zlib/inffast.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)inffast.o zlib/inffast.c\n\n$(OBJPATH)inflate.o:\t$(ZLIB_DEP) zlib/inflate.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)inflate.o zlib/inflate.c\n\n$(OBJPATH)inftrees.o:\t$(ZLIB_DEP) zlib/inftrees.h zlib/inftrees.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)inftrees.o zlib/inftrees.c\n\n$(OBJPATH)trees.o:\t\t$(ZLIB_DEP) zlib/trees.h zlib/trees.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)trees.o zlib/trees.c\n\n$(OBJPATH)zutil.o:\t\t$(ZLIB_DEP) zlib/zutil.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) -o $(OBJPATH)zutil.o zlib/zutil.c\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\tTest Code Targets\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# The test code\n\nutils.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/utils.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/utils.c\n\ncertimp.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/certimp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/certimp.c\n\ncertproc.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/certproc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/certproc.c\n\ncerts.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/certs.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/certs.c\n\ndevices.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/devices.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/devices.c\n\nenvelope.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/envelope.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/envelope.c\n\nhighlvl.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/highlvl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/highlvl.c\n\nkeydbx.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/keydbx.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/keydbx.c\n\nkeyfile.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/keyfile.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/keyfile.c\n\nloadkey.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/loadkey.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/loadkey.c\n\nlowlvl.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/lowlvl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/lowlvl.c\n\ns_cmp.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/s_cmp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/s_cmp.c\n\ns_scep.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/s_scep.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/s_scep.c\n\nsreqresp.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/sreqresp.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/sreqresp.c\n\nssh.o:\t\t\t\t\tcryptlib.h crypt.h test/test.h test/ssh.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/ssh.c\n\nssl.o:\t\t\t\t\tcryptlib.h crypt.h test/test.h test/ssl.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/ssl.c\n\nstress.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/stress.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/stress.c\n\nsuiteb.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/suiteb.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/suiteb.c\n\ntestfunc.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/testfunc.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/testfunc.c\n\ntestlib.o:\t\t\t\tcryptlib.h crypt.h test/test.h test/testlib.c\n\t\t\t\t\t\t$(CC) $(CFLAGS) test/testlib.c\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\tLink Targets\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# Create the static and shared libraries.  The main test program is also\n# listed as a dependency since we need to use OS-specific compiler options\n# for it that a simple 'make testlib' won't give us (the test program checks\n# whether the compiler options were set correctly when building the library,\n# so it needs to include a few library-specific files that wouldn't be used\n# in a normal program).\n#\n# When cross-compiling, we have to use the hosted tools and libraries rather\n# than the system tools and libraries for the build, so we special-case this\n# step based on the $(OSNAME) setting supplied to the build script.\n\n$(LIBNAME):\t\t$(OBJS) $(EXTRAOBJS) $(TESTOBJS)\n\t\t\t\t@./tools/buildlib.sh $(LIBNAME) $(OSNAME) $(AR) \\\n\t\t\t\t\t$(OBJS) $(EXTRAOBJS)\n\n$(SLIBNAME):\t$(OBJS) $(EXTRAOBJS) $(TESTOBJS)\n\t\t\t\t@if [ $(CROSSCOMPILE) = '1' ] ; then \\\n\t\t\t\t\t./tools/buildsharedlib.sh crosscompile $(SLIBNAME) $(OSNAME) \\\n\t\t\t\t\t\t$(LD) $(STRIP) $(MAJ).$(MIN) $(OBJS) $(EXTRAOBJS) ; \\\n\t\t\t\telse \\\n\t\t\t\t\t./tools/buildsharedlib.sh $(SLIBNAME) $(OSNAME) \\\n\t\t\t\t\t\t$(LD) $(STRIP) $(MAJ).$(MIN) $(OBJS) $(EXTRAOBJS) ; \\\n\t\t\t\tfi\n\n$(DYLIBNAME):\t$(OBJS) $(EXTRAOBJS) $(TESTOBJS)\n\t\t\t\t@$(LD) -dynamiclib -compatibility_version $(MAJ).$(MIN) \\\n\t\t\t\t\t-current_version $(MAJ).$(MIN).$(PLV) \\\n\t\t\t\t\t`./tools/getlibs.sh $(LD) $(OSNAME)` \\\n\t\t\t\t\t-o $(DYLIBNAME) $(OBJS) $(EXTRAOBJS)\n\n# If installing cryptlib as a systemwide lib, run ldconfig (which normally\n# reads /etc/ld.so.conf, sets up the appropriate symbolic links in the\n# shared lib directory, and writes a cache file /etc/ld.so.cache for use by\n# other programs). The loader the consults /etc/ld.so.cache to find the\n# libraries it needs.  This is why ldconfig has to be run when a new lib is\n# added or removed.\n#\n#\tldconfig -n <cryptlib .so directory path>\n#\n# A temporary workaround for testing is to set LD_LIBRARY_PATH to the\n# directory containing the cryptlib shared lib.  This (colon-separated) list\n# of directories is searched before the standard library directories.  This\n# may have system-specific variations, e.g. under PHUX it's called\n# SHLIB_PATH and under Aches it's LIBPATH.  BeOS uses LIBRARY_PATH, and\n# needs to have it pointed to . to find the shared lib, otherwise it fails\n# with a \"Missing library\" error without indicating which library is missing.\n#\n# To run stestlib with a one-off lib path change, use either the universal:\n#\n#\tenv LD_LIBRARY_PATH=. ./stestlib\n#\n# or the shell-specific (csh/tcsh):\n#\n#\tsetenv LD_LIBRARY_PATH .\n#\t./stestlib\n#\n# or (sh/bash):\n#\n#\tLD_LIBRARY_PATH=. ; export LD_LIBRARY_PATH\n#\t./stestlib\n#\n# (for OS X, use DYLD_LIBRARY_PATH instead of LD_LIBRARY_PATH).\n#\n# Finally:\n#\n#\tldd ./stestlib \n#\n# will print out shared lib dependencies.\n#\n# We don't give the library $(SLIBNAME) as a dependency since the user has \n# to make this explicitly rather than implicitly, otherwise the auto-config \n# mechanism is bypassed and what gets built is a mix of static and shared\n# binaries, for example due to OBJPATH still being set to the static rather\n# than the shared object path.  \n#\n# Since OS X uses special dylibs instead of normal shared libs, we detect \n# this and build the appropriate lib type.\n#\n# Finally, the kludging of versions is normally handled under Unix through a\n# mess of symlinks from different truncated version numbers of the shared \n# library to the actual version (e.g. libfoo.so -> libfoo.so.1 -> \n# libfoo.so.1.2 etc).  This is normally done by the install script, if we're\n# building stestlib for testing in the current directory (but only ofr that,\n# not as a general build of SLIBNAME) we also make the fixslibname target \n# which creates the appropriate link so the loader can find it.\n\nlinkcmd:\t\t\n\t\t\t\t`./tools/getcompiler.sh $(CC) $(OSNAME)` -o $(PROGNAME) $(LDFLAGS) \\\n\t\t\t\t\t`cat $(LINKFILE)` -L. $(LIBNAME) \\\n\t\t\t\t\t`./tools/getlibs.sh $(CC) $(OSNAME)`\n\nfixslibname:\t\n\t\t\t\tif [ ! -f $(SHORTSLIBNAME) ] ; then \\\n\t\t\t\t\tln -s \"$(SLIBNAME)\" \"$(SHORTSLIBNAME)\" ; \\\n\t\t\t\tfi\n\ntestlib:\t\t$(TESTOBJS) $(LIBNAME)\n\t\t\t\t@rm -f $(LINKFILE)\n\t\t\t\t@echo $(TESTOBJS) > $(LINKFILE)\n\t\t\t\t@make linkcmd OSNAME=$(OSNAME) PROGNAME=testlib LIBNAME=-l$(PROJ)\n\t\t\t\t@rm -f $(LINKFILE)\n\nstestlib:\t\t$(TESTOBJS) \n\t\t\t\t@rm -f $(LINKFILE)\n\t\t\t\t@echo $(TESTOBJS) > $(LINKFILE)\n\t\t\t\t@if [ $(OSNAME) = 'AIX' ] ; then \\\n\t\t\t\t\tmake linkcmd OSNAME=$(OSNAME) PROGNAME=stestlib LIBNAME=$(SLIBNAME).a ; \\\n\t\t\t\telif [ $(OSNAME) = 'Darwin' ] ; then \\\n\t\t\t\t\tmake linkcmd OSNAME=$(OSNAME) PROGNAME=stestlib LIBNAME=$(DYLIBNAME) ; \\\n\t\t\t\telif [ $(OSNAME) = 'HP-UX' ] ; then \\\n\t\t\t\t\tmake linkcmd OSNAME=$(OSNAME) PROGNAME=stestlib LIBNAME=lib$(PROJ).sl ; \\\n\t\t\t\telse \\\n\t\t\t\t\tmake linkcmd OSNAME=$(OSNAME) PROGNAME=stestlib LIBNAME=$(SLIBNAME) ; \\\n\t\t\t\t\tmake fixslibname SHORTSLIBNAME=\"lib$(PROJ).so.$(MAJ).$(MIN)\" ; \\\n\t\t\t\tfi\n\t\t\t\t@rm -f $(LINKFILE)\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\tUnix OS Targets\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# Aches: A vaguely Unix-compatible OS designed by IBM.  The maxmem option\n#\t\t is to give the optimizer more headroom, it's not really needed\n#\t\t but avoids millions of informational messages telling you to\n#\t\t increase it from the default 2048.  The roconst puts const data\n#\t\t into read-only memory (this may happen anyway on some versions of\n#\t\t the compiler).  The -O3 is what other compilers call -O2, the IBM\n#\t\t compiler doesn't have a -O1.  The qnolist is to turn off generation\n#\t\t of listing files, this is supposed to be off by default but xlc\n#\t\t isn't aware of this.  Note though that even when qnolist is \n#\t\t specified, some versions still generate .lst files for each source\n#\t\t file, containing a two-line entry that's identical across each file.\n\nAIX:\n\t@if [ $(CC) = \"gcc\" ] ; then \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -D_REENTRANT\" ; \\\n\telse \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -qnolist -qmaxmem=-1 -qroconst -D_REENTRANT\" ; \\\n\tfi\n\n# Millions of Intel BSD's (many are really BSE's, with incredibly archaic\n#\t\t\tdevelopment tools and libs, although it's slowly getting better):\n#\t\t\tcc is gcc except when it isn't.  Most are still using a.out,\n#\t\t\talthough some are slowly going to ELF, which we can autodetect by\n#\t\t\tchecking whether the compiler defines __ELF__.  If the compiler\n#\t\t\tcheck doesn't work then [ `uname -r | cut -f 1 -d '.'` -ge 4 ]\n#\t\t\t(for FreeBSD) and -ge 2 (for OpenBSD) should usually work.\n#\n#\t\t\tNetBSD for many years (up until around 1999-2000) used an\n#\t\t\tincredibly old version of as that didn't handle 486 opcodes (!!),\n#\t\t\tso the asm code was disabled by default.  In addition it used an\n#\t\t\tequally archaic version of gcc, requiring manual fiddling with\n#\t\t\tthe compiler type and options.  If you're still using one of\n#\t\t\tthese ancient versions, you'll have to change the entry below to\n#\t\t\thandle it.  In addition the rule is currently hardwired to assume\n#\t\t\tx86 due to lack of access to a non-x86 box, if you're building on\n#\t\t\ta different architecture you'll have to change the entry slightly\n#\t\t\tto detect x86 vs. whatever you're currently using, see the Linux\n#\t\t\tentry for an example.\n#\n#\t\t\tFor the newer BSDs, the optimisation level is set via the\n#\t\t\tccopts.sh script.\n\nBSD386:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer -O3\"\niBSD:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer -O3\"\nBSD/OS:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer -O3\"\n\nFreeBSD:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer -pthread\"\n\nNetBSD:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer -pthread\" \n\nOpenBSD:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer\" \n\n# Cray Unicos: The Cray compiler complains about char * vs. unsigned char\n#\t\t\t   passed to functions, there's no way to disable this directly\n#\t\t\t   so the best that we can do is disable warnings:\n#\t\t\t\tcc-256 Function call argument or assignment has incompatible type\n#\t\t\t\tcc-265 Function call argument has incompatible type\n\nCRAY:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -h nomessage=256:265 -O2\"\n\n# Cygwin: cc is gcc.\n\nCYGWIN_NT-5.1:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -D__CYGWIN__ -I/usr/local/include\"\n\nCYGWIN_NT-6.1:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -D__CYGWIN__ -I/usr/local/include\"\n\n# PHUX: A SYSVR2 layer with a SYSVR3 glaze on top of an adapted BSD 4.2\n#\t\tkernel.  Use cc, the exact incantation varies somewhat depending on\n#\t\twhich version of PHUX you're running.  For 9.x you need to use\n#\t\t'-Aa -D_HPUX_SOURCE' to get the compiler into ANSI mode, in 10.x this\n#\t\tchanged to just '-Ae', and after 10.30 -Ae was the default mode.\n#\t\tWith PA-RISC 2 you should probably also define +DD64 to compile in\n#\t\t64-bit mode under PHUX 11.x, under even newer versions this becomes\n#\t\t+DA2.0w (note that building 64-bit versions of anything will probably\n#\t\tcause various build problems arising from the compiler and linker\n#\t\tbecause although the CPU may be 64 bit the software development tools\n#\t\treally, really want to give you 32-bit versions of everything and it\n#\t\ttakes quite some cajoling to actually get them to spit out a 64-bit\n#\t\tresult).  In addition the PHUX compilers don't recognise -On like the\n#\t\trest of the universe but use +On instead so we adjust things based\n#\t\ton the compiler we're using.  In addition we only build the asm code\n#\t\tunder 11 since it doesn't like 10.x and earlier systems.\n#\n#\t\tNewer compilers can use +Oall to apply all optimisations (even the\n#\t\tdodgy ones).  Typically going from +O2 -> +O3 -> +O4 gives a ~10-15%\n#\t\timprovement at each step.  Finally, when making the shared lib you\n#\t\tcan only use +O2, not +O3, because it gives the compiler the speed\n#\t\twobbles.  In theory we could also use +ESlit to force const data\n#\t\tinto a read-only segment, but this is defeated by a compiler bug\n#\t\tthat doesn't initialise non-explicitly-initialised struct elements\n#\t\tto zero any more when this option is enabled (this is a double-bug\n#\t\tthat violates two C rules because if there are insufficient\n#\t\tinitialisers the remaining elements should be set to zero, and for\n#\t\tstatic objects they should be set to zero even if there are no\n#\t\tinitialisers).\n#\n#\t\tNote that the PHUX compilers (especially the earlier ones) are\n#\t\thorribly broken and will produce all sorts of of bogus warnings of\n#\t\tnon-problems, eg:\n#\n#\t\t\t/usr/ccs/bin/ld: (Warning) Quadrant change in relocatable\n#\t\t\t\t\t\t\t expression in subspace $CODE$\n#\n#\t\t(translation: Klingons off the starboard bow!).  The code contains\n#\t\tworkarounds for non-errors (for example applying a cast to anything\n#\t\tmagically turns it into an rvalue), but it's not worth fixing the\n#\t\twarnings for an OS as broken as this.  In addition most of the HP\n#\t\tcompilers are incapable of handling whitespace before a preprocessor\n#\t\tdirective, so you need to either (a) get a non-broken compiler or\n#\t\t(b) run each file through sed to strip the whitespace, something like:\n#\n#\t\t#! /bin/csh -f\n#\t\tforeach file (*.h *.c)\n#\t\t  sed -e 's/  #/#/g' -e 's/\t#/#/g' -e 's/\t  #/#/g' $file > tmp\n#\t\t  mv tmp $file\n#\t\tend\n#\n#\t\tAgain, it isn't worth changing every single source file just to\n#\t\taccomodate this piece of compiler braindamage.\n#\n#\t\tThe asm bignum asm code is for PA-RISC 2.0, so we have to make sure\n#\t\tthat we're building a PA-RISC 2.0 version if we use the asm code.\n#\t\tThis can be detected with \"getconf CPU_VERSION\", if the result is >=\n#\t\t532 (equal to the symbolic define CPU_PA_RISC2_0) it's PA-RISC 2.0.\n#\t\tWe need to explicitly check the architecture rather than the OS\n#\t\tsince although PHUX 10.20 first supported PA-RISC 2.0, it wasn't\n#\t\tuntil PHUX 11.00 that the 64-bit capabilities were first supported\n#\t\t(previously it was treated as PA-RISC 1.x, 32-bit, or a 1.x/2.0\n#\t\thybrid).  Because of the not-quite PA-RISC 2.0 support in PHUX 10.x,\n#\t\twe'd need to check the kernel with \"file /stand/vmunix\" for that,\n#\t\twhich will report \"ELF-64 executable object file - PA-RISC 2.0\n#\t\t(LP64)\" for PA-RISC 2.0.\n#\n#\t\tEven then, this may not necessarily work, depending on the phase of\n#\t\tthe moon and a few other variables.  If testlib dumps core right at\n#\t\tthe start (in the internal self-test), disable the use of the asm\n#\t\tcode and rebuild.\n#\n#\t\tIn addition pa_risc2.s is written using the HP as syntax rather than\n#\t\tgas syntax, so we can only build it if we're using the PHUX native\n#\t\tdevelopment tools.\n#\n#\t\tThe HP compilers emit bogus warnings about (signed) char <->\n#\t\tunsigned char conversion, to get rid of these we use +W 563,604\n#\t\tto disable warning 563 (Argument is not the correct type) and 604\n#\t\t(Pointers are not assignment-compatible).\n#\n#\t\tFinally, the default PHUX system ships with a non-C compiler (C++)\n#\t\twith most of the above bugs, but that can't process standard C code\n#\t\teither.  To detect this we feed it a C-compiler option and check for\n#\t\ta non-C-compiler error message, in this case +O3 which yields \"The\n#\t\t+O3 option is available only with the C/ANSI C product; ignored\".\n#\n#\t\tThe PHUX compiler bugs comment is really starting to give the SCO\n#\t\tone a run for its money.\n\nHP-UX:\n\t@if [ `$(CC) +O3 ./tools/endian.c -o /dev/null 2>&1 | grep -c \"ANSI C product\"` = '1' ] ; then \\\n\t\techo \"Warning: This system appears to be running the HP bundled C++ compiler as\" ; \\\n\t\techo \"         its cc.  You need to install a proper C compiler to build cryptlib.\" ; \\\n\t\techo \"\" ; \\\n\t\tfi\n\t@rm -f a.out\n\t@case `./tools/osversion.sh HP-UX` in \\\n\t\t8|9) \\\n\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -Aa -D_HPUX_SOURCE +O3\" ;; \\\n\t\t10) \\\n\t\t\tif [ $(CC) = \"gcc\" ] ; then \\\n\t\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3\" ; \\\n\t\t\telse \\\n\t\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -Ae +O3\" ; \\\n\t\t\tfi ;; \\\n\t\t11) \\\n\t\t\tif [ $(CC) = \"gcc\" ] ; then \\\n\t\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -D_REENTRANT\" ; \\\n\t\t\telse \\\n\t\t\t\tif [ `getconf CPU_VERSION` -ge 532 ] ; then \\\n\t\t\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) +O3 +ESlit +DA2.0 +DS2.0 -Ae +W 563,604 -D_REENTRANT\" ; \\\n\t\t\t\telse \\\n\t\t\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) +O3 +ESlit -Ae +W 563,604 -D_REENTRANT\" ; \\\n\t\t\t\tfi ; \\\n\t\t\tfi ;; \\\n\tesac\n\n# Irix: Use cc.\n\nIRIX:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3\"\nIRIX64:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3\"\n\n# Linux: cc is usually gcc, although with some luck it'll eventually be killed by\n#\t\t LLVM. \n\nLinux:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O3 -fomit-frame-pointer -D_REENTRANT\" \n\n# Mac OS X: BSD variant.  Optimisation level is set via the ccopts.sh script.\n#\t\t\tIf you want to build a universal binary you can use a command a\n#\t\t\tbit like the following (with the path to your SDK install\n#\t\t\tsubstituted for the one in the command-lines below):\n#\n# make LDFLAGS='-isysroot /Developer/SDKs/MacOSX10.5.sdk' CFLAGS='-c -isysroot \\\n# /Developer/SDKs/MacOSX10.5.sdk -Os -mmacosx-version-min=10.5 -arch ppc -arch \\\n# ppc64 -arch i386 -arch x86_64 -DOSX_UNIVERSAL_BINARY -D__UNIX__ -DNDEBUG -I.'\n#\n# make LDFLAGS='-arch i386 -arch x86_64' CFLAGS='-c -O2 -mmacosx-version-min=10.5 \\\n# -arch i386 -arch x86_64 -D__UNIX__ -DNDEBUG -I.'\n#\n#\t\t\tThis will also require adding $(LDFLAGS) to the dylib build rule.\n#\n#\t\t\tThis build method is rather trouble-prone because the low-level\n#\t\t\tcrypto code has to configure itself for CPU endianness and word\n#\t\t\tsize for the algorithms that require low-level bit fiddling, and\n#\t\t\tuses different code strategies depending on the CPU architecture\n#\t\t\tand bit width.  This single-pass build for multiple architectures\n#\t\t\toften causes problems, and you're more or less on your own if you\n#\t\t\tdecide to try it.\n\nDarwin:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -fomit-frame-pointer\"\n\n# MinGW: cc is gcc.  Note that we have to use the cross-compile flags\n# XCFLAGS rather than CFLAGS because the latter implies a native Unix\n# build, and we also need to execute the target-init rule in order to\n# reconfigure ourselves to use the Win32 randomness-polling\n# system rather than the Unix one, and we need to use the pre-built\n# Win32 COFF object files because the assembler included with MinGW\n# is a rather minimal one that seems to be intended mostly as a back-\n# end for MinGW's gcc.\n\nMINGW32_NT-5.1:\n\t$(MAKE) OSNAME=win32 target-init\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(XCFLAGS) -O2\"\n\nMINGW32_NT-6.1:\n\t$(MAKE) OSNAME=win32 target-init\n\t$(MAKE) $(DEFINES) EXTRAOBJS=\"$(WIN32ASMOBJS)\" \\\n\t\tCFLAGS=\"$(XCFLAGS) -O2 -Wl,--subsystem,windows,--output-def,cl32.def\"\n\n# NCR MP-RAS: Use the NCR cc.  The \"-DNCR_UST\" is needed to enable threading\n#\t\t\t  (User-Space Threads).\n\nUNIX_SV:\n\t$(MAKE) $(DEFINES) ARMETHOD=rcs CFLAGS=\"$(CFLAGS) -D_MPRAS -DNCR_UST \\\n\t\t-O2 -Xa -Hnocopyr -K xpg42 -K catchnull '-Hpragma=Offwarn(39)' \\\n\t\t'-Hpragma=Offwarn(73)'\"\n\n# QNX: Older versions of QNX (4.x) use braindamaged old 16-bit MSDOS-era\n#\t   Watcom tools that can't handle Unix-style code (or behaviour).\n#\t   The handling of compiler flags is particularly painful, in order to\n#\t   save space under DOS the compiler uses variable-size enums, in theory\n#\t   there's a compiler option -ei to make them the same size as an int\n#\t   but because the system 'cc' is just a wrapper for the DOS-style wcc386\n#\t   compiler we need to first use '-Wc' to tell the wrapper that an option\n#\t   for the compiler follows and then '-ei' for the compiler option itself.\n#\t   In addition to these problems the tools can't handle either ELF or\n#\t   a.out asm formats so we can't use the asm code unless we're building\n#\t   with gcc.\n\nQNX:\n\t@if gcc -v > /dev/null 2>&1 ; then \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O2 -D_REENTRANT\"; \\\n\telse \\\n\t\tif [ `./tools/osversion.sh QNX` = '4' ] ; then \\\n\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O4 -Wc,-ei -zc\" ; \\\n\t\telse \\\n\t\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O4 -ei -zc\" ; \\\n\t\tfi ; \\\n\tfi\n\n# SCO: Unlike the entire rest of the world, SCO doesn't use -On, although it\n#\t   does recognise -O3 to mean \"turn off pass 3 optimization\".  The SCO cc\n#\t   is in fact a mutant version of Microsoft C 6.0, so we use the usual\n#\t   MSC optimization options except for the unsafe ones.  -Olx is\n#\t   equivalent to -Oegilt.  Unless SCO rewrote half the compiler when\n#\t   no-one was looking, you won't be getting much optimization for your\n#\t   -O.\n#\n#\t   Actually it turns out that the only thing you get with -Olx is\n#\t   compiler bugs, so we only use -O, and even with that you get internal\n#\t   compiler faults that it traps and forces a compiler restart on,\n#\t   presumably with optimisations disabled.\n#\n#\t   SCO is basically too braindamaged to support any of the asm builds.\n#\t   as won't take input from stdin and dumps core on the crypto .S files,\n#\t   and cc/as barf on bni80386.s.  Even compiling the straight C code\n#\t   gives a whole slew of internal compiler errors/failed assertions.\n#\n#\t   For another taste of the wonderful SCO compiler, take the trivial lex\n#\t   example from the dragon book, lex it, and compile it.  Either the\n#\t   compiler will core dump from a SIGSEGV or the resulting program will\n#\t   from a SIGILL, depending on what level of optimization you use (a\n#\t   compiler that'll produce illegal code as output is pretty impressive).\n#\n#\t   In addition the SCO cc ignores the path for output files and dumps the\n#\t   whole mess in the same directory as the source files.  This means you\n#\t   need to set STATIC_OBJ_PATH = . in order for the library to be built,\n#\t   however the following rule does this for you by forwarding down the\n#\t   $(TARGET) define rather than $(DEFINES), which also includes the\n#\t   output path.\n#\n#\t   If you're building the shared version after building the static one\n#\t   you need to manually remove all the object files before trying to\n#\t   build it.\n#\n#\t   The SCO/UnixWare sockets libraries are extraordinarily buggy, make\n#\t   sure that you've got the latest patches installed if you plan to use\n#\t   cryptlib's secure session interface.  Note that some bugs reappear in\n#\t   later patches, so you should make sure that you really do have the\n#\t   very latest patch installed (\"SCO - Where Quality is Job #9\" -\n#\t   unofficial company motto following a SCO employee survey).\n#\n#\t   In terms of straight compiling of code, UnixWare (SCO 7.x) is only\n#\t   marginally better.  as now finally accepts input from stdin if '-' is\n#\t   specified as a command-line arg, but it doesn't recognise 486\n#\t   instructions yet (they've only been with us for over a decade for\n#\t   crying out loud), even using the BSDI-format kludge doesn't quite\n#\t   work since as just terminates with an internal error.\n#\n#\t   The compiler breaks when processing the aestab.c file, if you want to\n#\t   use the SCO cc to build cryptlib you'll have to do without AES (or\n#\t   use gcc, see below).\n#\n#\t   UnixWare also finally supports threads, but it may not be possible to\n#\t   build cryptlib with threading support under older versions because of\n#\t   a compiler bug in which the preprocessor sprays random spaces around\n#\t   any code in which token-pasting is used.  Although having foo##->mutex\n#\t   turn into \"certInfo -> mutex\" is OK, foo##.mutex turns into\n#\t   \"certInfo. mutex\" which the compiler chokes on (the appearances of\n#\t   spaces in different places doesn't seem to follow any pattern, the\n#\t   quoted strings above are exactly as output by the preprocessor).\n#\n#\t   To avoid this mess, you can build the code using the SCO-modified gcc\n#\t   which has been hacked to work with cc-produced libraries (the code\n#\t   below tries this by default, falling back to the SCO compiler only if\n#\t   it can't find gcc).\n#\n#\t   Cool, the SCO comment is now longer than the comments for all the\n#\t   other Unix variants put together.\n\nSCO:\n\t@if gcc -v > /dev/null 2>&1 ; then \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O2 -D_REENTRANT\"; \\\n\telse \\\n\t\techo \"Please read the entry for SCO in the makefile before continuing.\" ; \\\n\t\t$(MAKE) $(TARGET) CFLAGS=\"$(CFLAGS) -O\" ; \\\n\tfi\n\nUnixWare:\n\t@if gcc -v > /dev/null 2>&1 ; then \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O2 -D_REENTRANT\"; \\\n\telse \\\n\t\techo \"Please read the entry for UnixWare in the makefile before continuing.\" ; \\\n\t\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -O -Xa -Khost -Kthread\" ; \\\n\tfi\n\nitgoaway:\n\t@echo \"You poor bastard.\"\n\n# Sun/Slowaris: An OS named after the 1972 Andrei Tarkovsky film about a space\n#\t\t\t\tstation that drives people who work there mad.  Use gcc, but\n#\t\t\t\tfall back to the SUNSwspro compiler if necessary (in the c\n#\t\t\t\tchecks below, the '-' is necessary because one of the checks\n#\t\t\t\treturns a nonzero status somewhere that causes make to bail\n#\t\t\t\tout, and the error suppression is necessary to avoid dozens of\n#\t\t\t\tbogus warnings about signed vs.unsigned chars).\n#\n#\t\t\t\tIn addition we can only safely use -O2 (-xO2 in SUNwspro-\n#\t\t\t\tspeak) because -O3 introduces too many problems due to\n#\t\t\t\toptimiser bugs, while it's possible to (eventually) eliminate\n#\t\t\t\tthem through the judicious sprinkling of 'asm(\"\");' in\n#\t\t\t\tappropriate locations to disable optimisation within that\n#\t\t\t\tcode block it becomes a pain having to track them down\n#\t\t\t\twhenever the code changes, and -O2 isn't really much\n#\t\t\t\tdifferent than -O3 anyway.\n#\n#\t\t\t\tWe only build the asm code if we're doing a 32-bit build,\n#\t\t\t\tsince it's 32-bit only.\n\nSunOS:\n\t@if [ $(CC) = \"gcc\" ] ; then \\\n\t\t$(MAKE) SunOS-gcc $(DEFINES) CFLAGS=\"$(CFLAGS)\" ; \\\n\telse \\\n\t\t$(MAKE) SunOS-SunPro $(DEFINES) CFLAGS=\"$(CFLAGS)\" ; \\\n\tfi\n\nSunOS-gcc:\n\t$(MAKE) $(DEFINES) CC=gcc CFLAGS=\"$(CFLAGS) -O2 -D_REENTRANT\" \n\nSunOS-SunPro:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -xO2 -D_REENTRANT\" \n\n# Ultrix: Use vcc or gcc.\n\nULTRIX:\n\t$(MAKE) $(DEFINES) CC=gcc CFLAGS=\"$(CFLAGS) -O2\"\n\n# Amdahl UTS 4:\n\nUTS4:\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -Xc -O4\"\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\tOther OS Targets\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# BeOS: By default we use the newer BeOS development environment, which uses\n#\t\tgcc.  Since BeOS doesn't use the default Unix environment, we use\n#\t\tXCFLAGS and insert __BEOS__ as the OS.\n#\n#\t\tThe older BeOS development environment can still be used with:\n#\n#\t$(MAKE) $(DEFINES) CC=mwcc AR=\"mwcc -xml -o\" LD=\"mwcc -xms -f crypt.exp\"\n\nBeOS:\n\t@if grep \"unix\\.o\" makefile > /dev/null ; then \\\n\t\tsed s/unix\\.o/beos\\.o/g makefile | sed s/unix\\.c/beos\\.c/g > makefile.tmp || exit 1 ; \\\n\t\tmv -f makefile.tmp makefile || exit 1 ; \\\n\tfi\n\t$(MAKE) $(DEFINES) CFLAGS=\"$(CFLAGS) -U__UNIX__ -D__BEOS__ -O2 -D_REENTRANT\" ; \\\n\tfi\n\n# Haiku: Clone of BeOS so we pretend it's BeOS.\n\nHaiku:\n\t@if grep \"unix\\.o\" makefile > /dev/null ; then \\\n\t\tsed s/unix\\.o/beos\\.o/g makefile | sed s/unix\\.c/beos\\.c/g > makefile.tmp || exit 1 ; \\\n\t\tmv -f makefile.tmp makefile || exit 1 ; \\\n\tfi\n\tmake $(DEFINES) CFLAGS=\"$(CFLAGS) -U__UNIX__ -D__BEOS__ -O2 -D_REENTRANT\" ; \\\n\tfi\n\n# EPOC: Cross-compilation requires custom code paths to build using the\n#\t\tSymbian SDK rather than the native compiler.  The following defines\n#\t\tare for Symbian OS 7.x as the SDK and ARM as the architecture.  A\n#\t\tcross-compile config for a more modern toolset (Carbide) is given\n#\t\tfurther down.\n#\n# EPOC\t\t= /usr/local/symbian/7.0\n# CXX\t\t= ${EPOC}/bin/arm-epoc-pe-g++\n# CC\t\t= ${EPOC}/bin/arm-epoc-pe-gcc\n# AR\t\t= ${EPOC}/bin/arm-epoc-pe-ar\n# LD\t\t= ${EPOC}/bin/arm-epoc-pe-ld\n# CPP\t\t= ${EPOC}/bin/arm-epoc-pe-cpp\n# RANLIB\t= ${EPOC}/bin/arm-epoc-pe-ranlib\n# STRIP\t\t= ${EPOC}/bin/arm-epoc-pe-strip\n# INCS\t\t= -I$(EPOC)/include/libc\n\nEPOC:\n\t$(MAKE) CFLAGS=\"$(XCFLAGS) -D__EPOC__\" $(DEFINES)\n\n# IBM MVS (a.k.a.OS/390, z/OS): File naming behaviour is controlled by the\n#\t\t\t\t\t\t\t\tDDNAME_IO define.\n#\n#\tDDNAME_IO defined: Use ddnames for all I/O.  User options will be saved\n#\t\tin dynamically allocated datasets userid.CRYPTLIB.filename.\n#\n#\tDDNAME_IO not defined: Use HFS for all I/O.  User options will be saved\n#\t\tin directory $HOME/.cryptlib.\n#\n# The options are: \n#\n#\tLANGLVL: C99 with IBM extensions (superset of LANGLVL(EXTENDED)).\n#\tCSECT: CSECTS are named, needed for some modules, see #pragma csect in\n#\t\t   the code.\n#\tRENT: Generate reentrant code.\n#\tROC: Force constants into read-only memory.\n#\tROS: Force string literals into read-only memory.\n#\tENUM: Force enums to fixed-size 4-byte values.\n#\tCONVLIT: Use ISO 8859-1 internally.\n#\n# The compiler also produces a pile of noise warnings that we disable:\n#\n#\tCCN3068: void * <-> struct foo *.\n#\tCCN3280: const void * <-> void *.\n#\tCCN4332: Compiler breakage, 'A function with return type \"unsigned char*\"'\n#\t\t\t 'may not return a value of type \"const unsigned char*\"', but the\n#\t\t\t function is declared 'static const BYTE *'.\n\n$(OBJPATH)mvsent.o:\t\trandom/mvsent.s \n\t\t\t\t\t\tas -o $(OBJPATH)mvsent.o random/mvsent.s \n\nOS/390:\n\t@if grep \"unix\\.o\" makefile > /dev/null ; then \\\n\t\tsed s/unix\\.o/mvs\\.o/g makefile | sed s/unix\\.c/mvs\\.c/g > makefile.tmp || exit 1 ; \\\n\t\tmv -f makefile.tmp makefile || exit 1 ; \\\n\tfi\n\t$(MAKE) $(DEFINES) EXTRAOBJS=\"$(OBJPATH)mvsent.o\" CFLAGS=\"$(XCFLAGS) -O2 \\\n\t\t-W c,'LANGLVL(EXTC99) CSECT RENT ROC ROS TARG(CURRENT) ENUM(4)' \\\n\t\t-W c,'CONVLIT(ISO8859-1)' -W c,'SUPPRESS(CCN3068,CCN3280,CCN4332)' \\\n\t\t-D_OPEN_THREADS -D_XOPEN_SOURCE_EXTENDED=1\"\n\n# Tandem NSK/OSS: Use c89.  There are two variants of the OS here, OSS\n#\t\t\t\t  (Posix-like layer over NSK) and NSK hosted on OSS (many\n#\t\t\t\t  of the Posix functions aren't available).  The following\n#\t\t\t\t  builds for the OSS target (the default), to build for\n#\t\t\t\t  NSK use \"-Wsystype=guardian\".  For optimisation there's\n#\t\t\t\t  only -O, which is equivalent to the Tandem-specific\n#\t\t\t\t  -Woptimize=2 setting.  We need to enable extensions with\n#\t\t\t\t  -Wextensions for the networking code or many of the\n#\t\t\t\t  networking header data types are NOP'ed out.\n#\n#\t\t\t\t  The compiler is pretty picky, we turn off warnings for:\n#\n#\t\t\t\t\tNested comments (106)\n#\t\t\t\t\tUnreachable code (203, usually for failsafe defaults\n#\t\t\t\t\t\tafter a case statement)\n#\t\t\t\t\tUnsigned char vs. char (232)\n#\t\t\t\t\tChar vs. unsigned char (252)\n#\t\t\t\t\tInt vs. static int functions (257, the STATIC_FN\n#\t\t\t\t\t\tissue)\n#\t\t\t\t\tMixing enum and int (272)\n#\t\t\t\t\tChar vs. unsigned char (611),\n#\t\t\t\t\tVariable initialised but never used (770, mostly in\n#\t\t\t\t\t\tOpenSSL code)\n#\t\t\t\t\tInt vs. unsigned int (1506)\n\nNONSTOP_KERNEL:\n\t@if grep \"unix\\.o\" makefile > /dev/null ; then \\\n\t\tsed s/unix\\.o/tandem\\.o/g makefile | sed s/unix\\.c/tandem\\.c/g > makefile.tmp || exit 1 ; \\\n\t\tmv -f makefile.tmp makefile || exit 1 ; \\\n\tfi\n\t$(MAKE) $(DEFINES) CC=c89 CFLAGS=\"$(CFLAGS) -O -Wextensions -Wnowarn=106,203,232,252,257,272,611,770,1506\"\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\tCross-Compilation Targets\t\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# Generic entry for cross-compilation.  You need to provide at least the\n# following:\n#\n#\t-DCONFIG_DATA_LITTLEENDIAN/-DCONFIG_DATA_BIGENDIAN\n#\t\tOverride endianness auto-detection.\n#\n#\t-DOSVERSION=major_version\n#\t\tOS major version number.\n#\n#\t$(OSNAME)\n#\t\tThe target OS name, to select the appropriate compiler/link\n#\t\toptions further down.\n#\n# For further options, see the cryptlib manual.  A general template for an\n# entry is:\n#\n# target-X:\n#\t$(MAKE) OSNAME=target-X target-init\n#\t$(MAKE) $(DEFINES) OSNAME=target-X CC=target-cc CFLAGS=\"$(XCFLAGS) \\\n#\t\t-DCONFIG_DATA_xxxENDIAN -DOSVERSION=major_version -O2 -D_REENTRANT\" \\\n#\t\tLDFLAGS=\"$(XLDFLAGS)\"\n#\n# Since we're cross-compiling here, we use $(XCFLAGS) and $(XDEFINES) instead\n# if the usual $(CFLAGS) and $(DEFINES), which assume that the target is a\n# Unix system.\n\ntarget-init:\n\t@$(MAKE) directories\n\t@$(MAKE) toolscripts\n\t@if grep \"unix\\.o\" makefile > /dev/null ; then \\\n\t\tsed s/unix\\.o/$(OSNAME)\\.o/g makefile | sed s/unix\\.c/$(OSNAME)\\.c/g > makefile.tmp || exit 1 ; \\\n\t\tmv -f makefile.tmp makefile || exit 1 ; \\\n\tfi\n\ntarget-init-unix:\n\t@$(MAKE) directories\n\t@$(MAKE) toolscripts\n\nembedded-comments:\n\t@echo \"\"\n\t@echo \"The build for $(OSNAME) targets an embedded system with no native entropy\"\n\t@echo \"(randomness) source for key generation.  This means that you need to provide\"\n\t@echo \"an entropy seed file, see 'Random Data Sources' in the manual for details.\"\n\t@echo \"\"\n\nlinux-target-comments:\n\t@echo \"\"\n\t@echo \"Building for a Linux target environment that doesn't match the host\"\n\t@echo \"environment, some manual adjustment of header file and library usage via\"\n\t@echo \"tools/ccopts.sh and tools/getlibs.sh may be required.\"\n\t@echo \"\"\n\n# (Kadak) AMX: Gnu toolchain under Unix or Cygwin or ARM cc for ARM CPUs.\n\ntarget-amx-arm:\n\t@$(MAKE) OSNAME=amx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=AMX CC=armcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__AMX__ -O2\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=AMX embedded-comments\n\ntarget-amx-mips:\n\t@$(MAKE) OSNAME=amx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=AMX CC=mips-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__AMX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=AMX embedded-comments\n\ntarget-amx-ppc:\n\t@$(MAKE) OSNAME=amx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=AMX CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__AMX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=AMX embedded-comments\n\ntarget-amx-x86:\n\t@$(MAKE) OSNAME=amx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=AMX CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__AMX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=AMX embedded-comments\n\n# Android: Android NDK with GNU toolchain, usually hosted under Unix.  This\n# requires quite extensive configuration of target platform-specific\n# cross-compile options, the following hardcoded values will need tuning for\n# each target platform.\n\nANDROID_8D_NDK_PATH = $(HOME)/adt-bundle-linux-x86_64/android-ndk-r8d\nANDROID_8D_TOOLCHAIN_PATH = $(ANDROID_8D_NDK_PATH)/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/\nANDROID_8D_INCLUDE_SOURCES_PATH = $(ANDROID_8D_NDK_PATH)/sources/cxx-stl/gnu-libstdc++/4.6/\nANDROID_8D_INCLUDE_PLATFORM_PATH = $(ANDROID_8D_NDK_PATH)/platforms/android-9\n\ntarget-android8-arm:\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XDEFINES) OSNAME=Android \\\n\t\tCC=$(ANDROID_8D_TOOLCHAIN_PATH)/bin/arm-linux-androideabi-gcc \\\n\t\tCFLAGS=\"$(XCFLAGS) -DCONFIG_DATA_LITTLEENDIAN -O2 -D__Android__ \\\n\t\t-D_REENTRANT -MMD -MP -MF -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ \\\n\t\t-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -march=armv7-a -mtune=xscale \\\n\t\t-msoft-float -mthumb -g -DNDEBUG -no-canonical-prefixes \\\n\t\t-fno-strict-aliasing -finline-limit=64 \\\n\t\t-I$(ANDROID_8D_INCLUDE_SOURCES_PATH)/include \\\n\t\t-I$(ANDROID_8D_INCLUDE_SOURCES_PATH)/libs/armeabi-v7a/include \\\n\t\t-I$(ANDROID_8D_INCLUDE_PLATFORM_PATH)/arch-arm/usr/include\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\nANDROID_9_NDK_PATH = /Applications/android-ndk-r9\nANDROID_9_TOOLCHAIN_PATH = $(ANDROID_9_NDK_PATH)/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64\nANDROID_9_INCLUDE_PATH = $(ANDROID_9_NDK_PATH)/sources/cxx-stl/gnu-libstdc++/4.6\nANDROID_9_PLATFORM_PATH = $(ANDROID_9_NDK_PATH)/platforms/android-9\nANDROID_9_PLATFORM_ARM_PATH = $(ANDROID_9_PLATFORM_PATH)/arch-arm/usr\n\ntarget-android9-arm:\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XDEFINES) OSNAME=Android \\\n\t\tCC=$(ANDROID_9_TOOLCHAIN_PATH)/bin/arm-linux-androideabi-gcc \\\n\t\tCFLAGS=\"$(XSCFLAGS) -DCONFIG_DATA_LITTLEENDIAN -O2 -D__Android__ \\\n\t\t-D_REENTRANT -MMD -MP -MF -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ \\\n\t\t-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -march=armv7-a -mtune=xscale \\\n\t\t-msoft-float -mthumb -g -DNDEBUG -no-canonical-prefixes \\\n\t\t-fno-strict-aliasing -finline-limit=64 \\\n\t\t-I$(ANDROID_9_INCLUDE_PATH)/include \\\n\t\t-I$(ANDROID_9_INCLUDE_PATH)/libs/armeabi-v7a/include \\\n\t\t-I$(ANDROID_9_PLATFORM_ARM_PATH)/include\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-android9-arm-shared:\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XSDEFINES) OSNAME=Android \\\n\t\tCC=$(ANDROID_9_TOOLCHAIN_PATH)/bin/arm-linux-androideabi-gcc \\\n\t\tCFLAGS=\"$(XSCFLAGS) -DCONFIG_DATA_LITTLEENDIAN -O2 -D__Android__ \\\n\t\t-D_REENTRANT -MMD -MP -MF -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ \\\n\t\t-D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -march=armv7-a -mtune=xscale \\\n\t\t-msoft-float -mthumb -Os -g -DNDEBUG -no-canonical-prefixes \\\n\t\t-fno-strict-aliasing -finline-limit=64 \\\n\t\t-I$(ANDROID_9_INCLUDE_PATH)/include \\\n\t\t-I$(ANDROID_9_INCLUDE_PATH)/libs/armeabi-v7a/include \\\n\t\t-I$(ANDROID_9_PLATFORM_ARM_PATH)/include\" \\\n\t\tLD=$(ANDROID_9_TOOLCHAIN_PATH)/bin/arm-linux-androideabi-ld \\\n\t\tLDFLAGS=\"$(XLDFLAGS) -L$(ANDROID_9_PLATFORM_ARM_PATH)/lib\" \\\n\t\tSTRIP=$(ANDROID_9_TOOLCHAIN_PATH)/bin/arm-linux-androideabi-strip\n\n# Atmel ARM7 TDMI: Little-endian, no OS, maximum restrictions on resource\n# usage since it's running on the bare metal.\n\ntarget-atmel:\n\t@$(MAKE) OSNAME=atmel target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Atmel CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_NO_STDIO -DCONFIG_CONSERVE_MEMORY \\\n\t\t-DCONFIG_NO_DYNALLOC -DCONFIG_RANDSEED -O2\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=Atmel embedded-comments\n\n# ChorusOS: Generic toolchain for various architectures.\n\ntarget-chorus:\n\t@$(MAKE) OSNAME=chorus target-init\n\t$(MAKE) $(XDEFINES) OSNAME=CHORUS CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -D__CHORUS__ -O3\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\n# eCOS: Gnu toolchain under Unix.  For a standard install you also need\n# to change the XCFLAGS define at the start of this makefile to\n# XCFLAGS = -c -DNDEBUG -I. -I$(ECOS_INSTALL_DIR)/include.\n\ntarget-ecos-arm:\n\t@$(MAKE) OSNAME=ecos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=eCOS CC=arm-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -D__ECOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-ecos-ppc:\n\t@$(MAKE) OSNAME=ecos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=eCOS CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -D__ECOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-ecos-sh:\n\t@$(MAKE) OSNAME=ecos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=eCOS CC=sh-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -D__ECOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-ecos-x86:\n\t@$(MAKE) OSNAME=ecos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=eCOS CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -D__ECOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\n# Segger embOS: Gnu toolchain under Unix.\n\ntarget-embos:\n\t@$(MAKE) OSNAME=embos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=embOS CC=arm-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -D__embOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\n# FreeRTOS/OpenRTOS: Gnu toolchain under Cygwin.\n\ntarget-freertos-arm:\n\t@$(MAKE) OSNAME=X target-init\n\t$(MAKE) $(XDEFINES) OSNAME=FreeRTOS CC=arm-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__FREERTOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=FreeRTOS embedded-comments\n\ntarget-freertos-mb:\n\t@$(MAKE) OSNAME=X target-init\n\t$(MAKE) $(XDEFINES) OSNAME=FreeRTOS CC=mb-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__FREERTOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=FreeRTOS embedded-comments\n\ntarget-freertos-ppc:\n\t@$(MAKE) OSNAME=X target-init\n\t$(MAKE) $(XDEFINES) OSNAME=FreeRTOS CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__FREERTOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=FreeRTOS embedded-comments\n\n# Apple iOS hosted on OS X.  The paths changed for different versions of iOS \n# so we define different targets for iOS 5 and iOS > 5.  In addition Apple\n# keep changing the SDK paths and option names based on which version is in \n# use and there's no direct way to determine what to use, so we rely on a \n# helper script tools/xcode.sh that reports whatever Apple currently thinks \n# is the appropriate path or name for things.\n\nIOS5_SDK_PATH=/Developer/Platforms/iPhoneOS.platform/Developer\nIOS5_TOOLS_PATH=$(IOS5_SDK_PATH)/usr/bin\nIOS5_CCOPTS=-Wno-switch -Wno-pointer-sign\n\ntarget-ios5:\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XDEFINES) OSNAME=iOS CC=$(IOS5_TOOLS_PATH)/cc LD=$(IOS5_TOOLS_PATH)/ld \\\n\t\tAR=$(IOS5_TOOLS_PATH)/ar STRIP=$(IOS5_TOOLS_PATH)/strip \\\n\t\tCFLAGS=\"$(XCFLAGS) $(IOS5_CCOPTS) -DCONFIG_DATA_LITTLEENDIAN \\\n\t\t-D__UNIX__ -O2 -D_REENTRANT -arch armv7 \\\n\t\t-isysroot $(IOS5_SDK_PATH)/SDKs/iPhoneOS5.0.sdk\" LDFLAGS=\"-arch armv7\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\nIOS_PLATFORM=iphoneos\nIOS_ARCH=arm64\n\ntarget-ios:\n\t@if [ ! `which xcrun` ] ; then \\\n\t\techo \"Error: Xcode development tools not found, exiting...\" ; \\\n\t\texit 1 ; \\\n\tfi\n\t@echo \"Building for $(IOS_PLATFORM) SDK version `./tools/xcode.sh sdkversion $(IOS_PLATFORM)` on arch $(IOS_ARCH)\"\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XDEFINES) OSNAME=iOS CC=`./tools/xcode.sh cc $(IOS_PLATFORM)` \\\n\t\tLD=`./tools/xcode.sh ld $(IOS_PLATFORM)` \\\n\t\tAR=`./tools/xcode.sh ar $(IOS_PLATFORM)` STRIP=`./tools/xcode.sh cc \\\n\t\t$(IOS_PLATFORM)` CFLAGS=\"$(XCFLAGS) -DCONFIG_DATA_LITTLEENDIAN \\\n\t\t-D__UNIX__ -O2 -D_REENTRANT -DOSVERSION=`./tools/xcode.sh osversion \\\n\t\t$(IOS_PLATFORM)` -arch $(IOS_ARCH) -Wno-switch -Wno-pointer-sign \\\n\t\t`./tools/xcode.sh bitcode-arg $(IOS_PLATFORM)` \\\n\t\t-miphoneos-version-min=`./tools/xcode.sh sdkversion $(IOS_PLATFORM)` \\\n\t\t-isysroot `./tools/xcode.sh sysroot $(IOS_PLATFORM)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\nIOS_DEVELOPER=`xcode-select -print-path`\nIOS_ARCHS_SH=\"armv7 armv7s arm64\"\nIOS_ARCHS_CSH=arm64 x86_64\nIOS_SDKVER=`xcrun -sdk iphoneos --show-sdk-version`\nIOS_CURRENTPATH=`pwd`\nIOS_LIBS += $(foreach N,$(IOS_ARCHS_CSH),$(IOS_CURRENTPATH)/libcl_$N.a$(IOS_LIBS$N) )\n\ntarget-ios-universal:\n\t@if [ ! `which xcode-select` ] ; then \\\n\t\techo \"Error: Xcode development tools not found, exiting...\" ; \\\n\t\texit 1 ; \\\n\tfi\n\t@if [ ! -d \"${IOS_DEVELOPER}\" ] ; then \\\n\t\techo \"Error: Xcode path is not set correctly, '${IOS_DEVELOPER}' does not exist,\" ; \\\n\t\techo \"  most likely because of Xcode > 4.3.  To fix this, run\" ; \\\n\t\techo \"    sudo xcode-select -switch <xcode path>\" ; \\\n\t\techo \"  For the default installation this is\" ; \\\n\t\techo \"    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer\" ; \\\n\t\texit 1 ; \\\n\tfi\n\t@case ${IOS_DEVELOPER} in \\\n\t\t*\\ * ) \\\n\t\t\techo \"Your Xcode path contains whitespaces, which is not supported.\" ; \\\n\t\t\texit 1 ;; \\\n\tesac\n\t@for IOS_ARCH in ${IOS_ARCHS_CSH} ; do \\\n\t\tif [ \"$$IOS_ARCH\" = \"i386\" -o \"$$IOS_ARCH\" = \"x86_64\" ] ; then \\\n\t\t\tIOS_PLATFORM=\"iPhoneSimulator\" ; \\\n\t\telse \\\n\t\t\tIOS_PLATFORM=\"iPhoneOS\" ; \\\n\t\tfi ; \\\n\t\techo \"Building cryptlib for $$IOS_PLATFORM ${IOS_SDKVER} $$IOS_ARCH\" ; \\\n\t\t$(MAKE) clean ; \\\n\t\trm -f ${IOS_CURRENTPATH}/libcl_$$IOS_ARCH.a ; \\\n\t\t$(MAKE) target-ios IOS_ARCH=$$IOS_ARCH IOS_PLATFORM=$$IOS_PLATFORM ; \\\n\t\tmv ${IOS_CURRENTPATH}/libcl.a ${IOS_CURRENTPATH}/libcl_$$IOS_ARCH.a ; \\\n\tdone\n\t@echo \"Assembling universal library... ${IOS_LIBS}\"\n\t@lipo -create ${IOS_LIBS} -output ${IOS_CURRENTPATH}/libcl.a\n\t@echo \"Done.\"\n\n# Embedded Linux via cross-compilation on a source Linux system.\n\ntarget-linux-arm:\n\t@$(MAKE) target-init-unix\n\t@$(MAKE) linux-target-comments\n\t$(MAKE) $(XDEFINES) OSNAME=Linux CC=arm-linux-gnueabi-gcc \\\n\t\tAR=arm-linux-gnueabi-ar LD=arm-linux-gnueabi-ld \\\n\t\tSTRIP=arm-linux-gnueabi-strip \\\n\t\tCFLAGS=\"$(XCFLAGS) -D__UNIX__ \\\n\t\t\t`./tools/ccopts-crosscompile.sh $(CC)` \\\n\t\t\t-DCONFIG_DATA_LITTLEENDIAN -O2 -D_REENTRANT\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-linux-sh4:\n\t@$(MAKE) target-init-unix\n\t@$(MAKE) linux-target-comments\n\t$(MAKE) $(XDEFINES) OSNAME=Linux CC=sh4-linux-gnu-gcc \\\n\t\tAR=sh4-linux-gnu-ar LD=sh4-linux-gnu-ld \\\n\t\tSTRIP=sh4-linux-gnu-strip \\\n\t\tCFLAGS=\"$(XCFLAGS) -D__UNIX__ \\\n\t\t\t`./tools/ccopts-crosscompile.sh $(CC)` \\\n\t\t\t-DCONFIG_DATA_LITTLEENDIAN -O2 -D_REENTRANT\"\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-linux-ppc:\n\t@$(MAKE) target-init-unix\n\t@$(MAKE) linux-target-comments\n\t$(MAKE) $(XDEFINES) OSNAME=Linux CC=powerpc-eabi-gcc \\\n\t\tAR=powerpc-eabi-ar LD=powerpc-eabi-ld \\\n\t\tSTRIP=powerpc-eabi-strip \\\n\t\tCFLAGS=\"$(XCFLAGS) -D__UNIX__ \\\n\t\t\t`./tools/ccopts-crosscompile.sh $(CC)` \\\n\t\t\t-DCONFIG_DATA_BIGENDIAN -O2 -D_REENTRANT\"\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\n\t# For testing the crosscompile build process\ntarget-linux-x86:\n\t@$(MAKE) target-init-unix\n\t@$(MAKE) linux-target-comments\n\t$(MAKE) $(XDEFINES) OSNAME=Linux CC=gcc AR=ar LD=ld STRIP=strip \\\n\t\tCFLAGS=\"$(XCFLAGS) -D__UNIX__ \\\n\t\t\t`./tools/ccopts-crosscompile.sh $(CC)` \\\n\t\t\t-DCONFIG_DATA_LITTLEENDIAN -O2 -D_REENTRANT\" \n\ntarget-linux-x86-shared:\n\t@$(MAKE) target-init-unix\n\t@$(MAKE) linux-target-comments\n\t$(MAKE) $(XSDEFINES) OSNAME=Linux CC=gcc LD=ld \\\n\t\tCFLAGS=\"$(XCFLAGS) -D__UNIX__ \\\n\t\t\t`./tools/ccopts-crosscompile.sh $(CC)` \\\n\t\t\t-DCONFIG_DATA_LITTLEENDIAN -O2 -D_REENTRANT\" \n\n# mbed/CMSIS RTOS: Gnu toolchain.\n\ntarget-mbed:\n\t@$(MAKE) OSNAME=mbed target-init\n\t$(MAKE) $(XDEFINES) OSNAME=CMSIS CC=arm-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__CMSIS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=mbed embedded-comments\n\n# Mongoose OS: gcc under Windows or Unix.\n\ntarget-mgos:\n\t@$(MAKE) OSNAME=mgos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Mongoose CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__MGOS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=Mongoose embedded-comments\n\n\n# MQX: IAR compiler under Windows or Unix.  The MQX headers define __MQX__\n# (as well as a pile of other stuff like NULL, TRUE, FALSE, and most stdio \n# function names) so we can't use it to denote the OS but have to use the \n# somewhat awkward __MQXRTOS__.\n\ntarget-mqx:\n\t@$(MAKE) OSNAME=mqx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=MQX CC=iar-cc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__MQXRTOS__ -e -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=MQX embedded-comments\n\n# Nucleus: IAR compiler under Windows or Unix.\n\ntarget-nucleus:\n\t@$(MAKE) OSNAME=nucleus target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Nucleus CC=iar-cc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__Nucleus__ -e -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=Nucleus embedded-comments\n\n# OSEK/VDX/AUTOSAR: IAR compiler under Windows or Unix.  OSEK is a generic\n# RTOS specification so there are a large range of build environments\n# available, the IAR one seems to be the most popular so we make it the\n# default for target-osek, others can be added as target-osek-compilername.\n\ntarget-osek:\n\t@$(MAKE) OSNAME=osek target-init\n\t$(MAKE) $(XDEFINES) OSNAME=OSEK CC=iar-cc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__OSEK__ -e -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=OSEK embedded-comments\n\n# PalmOS on ARM: Little-endian.  The first target is for the Palm tools, the\n# second for the PRC tools package.  The latter needs to have assorted extra\n# defines that are automatically set by the Palm tools set manually.  The\n# optimisation level for the Palm compiler is left at the default -O, which is\n# equivalent to -O3.  -O4 and -O5 are somewhat flaky.\n#\n# The toolchains can require a bit of tweaking to get running due to problems\n# with finding include directories.  The PRC tools using gcc expect to find\n# standard ARM headers as a fallback from the PalmOS ones, using\n# #include_next to pull in the next headers.  For a standard install this\n# requires specifying the additional include file paths with\n# \"-idirafter /usr/lib/gcc-lib/arm-palmos/...\".  The Palm tools under Cygwin\n# are even more problematic, and may require manual instruction on where to\n# find their include files for both the Palm and ANSI/ISO C standard headers.\n#\n# The PalmOS compiler sets an idiotic -wall by default, requiring that we\n# manually turn off a pile of the more annoying warnings, although the worst\n# one (used before initialised) can't be turned off.  For the warnings that\n# we can turn off:\n#\n#\t112 = unreachable code\n#\t187 = comparison of unsigned type for < 0\n#\t189 = enumerated type mixed with another type (== int)\n#\n# The Palm SDK under Cygwin only understands heavily-escaped absolute MSDOS \n# pathnames, so it's necessary to specify (for example)\n# -I\"c:/Program\\\\\\ Files/PalmSource/Palm\\\\\\ OS\\\\\\ Developer\\\\\\ Suite/sdk-6/\"\n# as the SDK path.  In practice it's easier to dump all the files in their\n# own partition, which is what the Palm SDK target assumes.  Note that if \n# you change this you'll also have to change the path value in\n# tools/buildlib.sh.\n\nPALMSDK_PATH\t= \"d:/Palm\\\\\\ SDK/sdk-6\"\n\npalm-sld:\t\tcryptlib.sld\n\tpslib -inDef cryptlib.sld -outObjStartup $(OBJPATH)cryptsld.o \\\n\t-outObjStub palmcl.obj -outEntryNums palmcl.h\n\ntarget-palmos:\n\t@$(MAKE) OSNAME=palmos target-init\n\t@$(MAKE) palm-sld\n\t$(MAKE) $(XDEFINES) OSNAME=PalmOS CC=pacc CFLAGS=\"$(XCFLAGS) \\\n\t\t-I$(PALMSDK_PATH)/headers/ \\\n\t\t-I$(PALMSDK_PATH)/headers/posix/ \\\n\t\t-nologo -D__PALMOS_KERNEL__ -DBUILD_TYPE=BUILD_TYPE_RELEASE \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -O -wd112 -wd187 -wd189\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-palmos-prc:\n\t@$(MAKE) OSNAME=palmos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=PalmOS-PRC CC=arm-palmos-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-idirafter /usr/lib/gcc-lib/arm-palmos/3.2.2/include/ \\\n\t\t-D__PALMOS_KERNEL__ -D__PALMSOURCE__ -DBUILD_TYPE=BUILD_TYPE_RELEASE \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -O2 `./tools/ccopts-crosscompile.sh $(CC)`\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\n# RTEMS: Gnu toolchain under Cygwin.\n\ntarget-rtems-arm:\n\t@$(MAKE) OSNAME=rtems target-init\n\t$(MAKE) $(XDEFINES) OSNAME=RTEMS CC=arm-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__RTEMS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=RTEMS embedded-comments\n\ntarget-rtems-mips:\n\t@$(MAKE) OSNAME=rtems target-init\n\t$(MAKE) $(XDEFINES) OSNAME=RTEMS CC=mips-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__RTEMS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=RTEMS embedded-comments\n\ntarget-rtems-ppc:\n\t@$(MAKE) OSNAME=rtems target-init\n\t$(MAKE) $(XDEFINES) OSNAME=RTEMS CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__RTEMS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=RTEMS embedded-comments\n\ntarget-rtems-x86:\n\t@$(MAKE) OSNAME=rtems target-init\n\t$(MAKE) $(XDEFINES) OSNAME=RTEMS CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__RTEMS__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=RTEMS embedded-comments\n\n# Quadros: IAR compiler under Windows or Unix.\n\ntarget-quadros:\n\t@$(MAKE) OSNAME=quadros target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Quadros CC=iar-cc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__Quadros__ -e -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=Quadros embedded-comments\n\n# SMX: IAR compiler under Windows or Unix.\n\ntarget-smx:\n\t@$(MAKE) OSNAME=smx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=SMX CC=iar-cc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__SMX__ -e -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=SMX embedded-comments\n\n# Symbian: Carbide toolchain under Windows or Unix.  This builds either for\n# the ARM target or for the x86 Symbian emulator, strictly speaking the\n# latter isn't really a cross-compile but we have to treat it as such\n# because we're building for an OS other than the native one.\n#\n# The handling of this is a bit of a mess, the emulator build is done using\n# the ex-Metrowerks CodeWarrior compiler (restricted to only produce x86\n# output) and the ARM builds are done using either gcc or the ARM compiler.\n# Since the only preprocessor indicator that the emulator compiler defines\n# is __EMU_SYMBIAN_OS__ (as well as __INTEL__, a Metrowerks define that's\n# hardcoded on because none of the other Metrowerks target types are\n# available any more) we have to manually define __SYMBIAN32__ ourselves\n# for the emulator build.\n\nCARBIDE_PATH\t\t\t= \"C:\\Carbide.c++ v2.3\"\nCARBIDE_INCLUDE_PATH\t= \"$(CARBIDE_PATH)\\x86Build\\Symbian_Support\\MSL\\MSL_C\\MSL_Common\\Include\\\"\n\ntarget-symbian:\n\t@$(MAKE) OSNAME=symbian target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Symbian CC=arm-none-symbianelf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-O2 -I$(CARBIDE_INCLUDE_PATH)\" LDFLAGS=\"$(XLDFLAGS)\"\n\ntarget-symbian-emulator:\n\t@$(MAKE) OSNAME=Symbian target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Symbian CC=mwccsym2 CFLAGS=\"$(XCFLAGS) \\\n\t\t-D__SYMBIAN32__ -O2 -I$(CARBIDE_INCLUDE_PATH)\" LDFLAGS=\"$(XLDFLAGS)\"\n\n# Telit: Gnu toolchain under Cygwin.\n\ntarget-telit:\n\t@$(MAKE) OSNAME=telit target-init\n\t$(MAKE) $(XDEFINES) OSNAME=Telit CC=armcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=Telit embedded-comments\n\n# ThreadX: Usually the Gnu toolchain under Cygwin or Unix (with occasional\n# exceptions for vendor-specific compilers, in the rules below the ones that\n# invoke ccopts-crosscompile.sh are for the Gnu toolchain).  The front-end\n# when gcc is used is usually Eclipse, but it's not really needed for\n# building cryptlib.\n\nTHREADX_IAR_PATH = \"C:/Program Files (x86)/IAR Systems/Embedded Workbench 6.4\"\nTHREADX_INCLUDE_PATH = \"../../../uk_smets_integ_01_crypto/projects/threadx\"\n\ntarget-threadx-arm:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=armcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\ntarget-threadx-mb:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=mb-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\ntarget-threadx-mips:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=mips-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\ntarget-threadx-ppc:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\ntarget-threadx-rx:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=iccrx CFLAGS=\"$(XCFLAGS) \\\n\t\t-D__ThreadX__ -e -DDEBUG_DIAGNOSTIC_ENABLE -DCONFIG_DEBUG_MALLOC \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -DOPENSSL_NO_FP_API \\\n\t\t-DCONFIG_NO_STDIO -Ohs --core RX610 -r -I $(THREADX_INCLUDE_PATH) \\\n\t\t--dlib_config '$(THREADX_IAR_PATH)/rx/LIB/dlrxfllf.h'\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\ntarget-threadx-x86:\n\t@$(MAKE) OSNAME=threadx target-init\n\t$(MAKE) $(XDEFINES) OSNAME=ThreadX CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__ThreadX__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=ThreadX embedded-comments\n\n# uC/OS-II: Generic toolchain for various architectures.\n\ntarget-ucos-arm:\n\t@$(MAKE) OSNAME=ucos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=UCOS CC=armcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__UCOS__ -O3\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=uC/OS-II embedded-comments\n\ntarget-ucos-ppc:\n\t@$(MAKE) OSNAME=ucos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=UCOS CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__UCOS__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=uC/OS-II embedded-comments\n\ntarget-ucos-x86:\n\t@$(MAKE) OSNAME=ucos target-init\n\t$(MAKE) $(XDEFINES) OSNAME=UCOS CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__UCOS__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=uC/OS-II embedded-comments\n\n# ucLinux on ARM: Little-endian.  Note that we use $(CFLAGS) rather than\n# $(XCFLAGS) since this is a Unix system, just not the same as the source\n# one (in particular we need __UNIX__ defined for the build).\n\ntarget-uclinux:\n\t@$(MAKE) target-init-unix\n\t$(MAKE) $(XDEFINES) OSNAME=Linux CC=arm-elf-gcc CFLAGS=\"$(CFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_CONSERVE_MEMORY \\\n\t\t-O2 `./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\n# VDK: AD-provided toolchain under Windows.\n\ntarget-vdk:\n\t@$(MAKE) OSNAME=vdk target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VDK CC=blackfin-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__VDK__ -O2 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VDK embedded-comments\n\n# VxWorks: VxWorks toolchain under Windows or Unix.  The configurations for \n# these is highly situation-specific, and if it's not running under Cygwin \n# (when using Windows) can't use the .sh build script, so we have to \n# hardcode on all sorts of custom build options.  \n#\n# Since the facilities for entropy-polling under VxWorks are practically \n# nonexistent (see the comment in random/vxworks.c) we enable \n# -DCONFIG_RANDSEED by default.\n\nVXWORKS_ARM_1_ARCH_DEFS\t= -D__arm__ -t7 -mfpu=vfp -mfloat-abi=softfp \\\n\t\t\t\t\t\t  -DCPU=_VX_ARMARCH7 -DARMEL -DCPU_CORTEXA8 \\\n\t\t\t\t\t\t  -DARMMMU=ARMMMU_CORTEXA8 -DARMCACHE=ARMCACHE_CORTEXA8 \\\n\t\t\t\t\t\t  -DARM_USE_VFP\nVXWORKS_ARM_1_DEFS\t= $(VXWORKS_ARM_1_ARCH_DEFS) -DRW_MULTI_THREAD \\\n\t\t\t\t\t  -D_REENTRANT=1 -D_POSIX_THREADS -D__VXWORKS_6_2__ \\\n\t\t\t\t\t  -DTOOL_FAMILY=gnu -DTOOL=gnu -D_WRS_KERNEL \\\n\t\t\t\t\t  -DRW_MULTI_THREAD\nVXWORKS_ARM_PATH\t= $(WIND_BASE)/target/h\n\ntarget-vxworks-arm-1:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=ccarm AR=ararm CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t-I$(VXWORKS_ARM_PATH) -I$(VXWORKS_ARM_PATH)/wrn/coreip \\\n\t\t-I$(VXWORKS_ARM_PATH)/types -I$(VXWORKS_ARM_PATH)/wrn/coreip/netinet \\\n\t\t-I$(VXWORKS_ARM_PATH)/tool/gnu $(VXWORKS_ARM_1_DEFS)\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\nVXWORKS_ARM_2_ARCH_DEFS\t= -g -D__arm__ -t7 -mfpu=vfp -mfloat-abi=softfp  \\\n\t\t\t\t\t\t  -fno-zero-initialized-in-bss -MD -MP\n                                                 \nVXWORKS_ARM_2_DEFS\t\t= $(VXWORKS_ARM_2_ARCH_DEFS) -DCPU=_VX_ARMARCH7 \\\n\t\t\t\t\t\t  -DTOOL_FAMILY=gnu -DTOOL=gnu -D_WRS_KERNEL \\\n\t\t\t\t\t\t  -D_WRS_VX_SMP -D_WRS_CONFIG_SMP -DARMEL -DARM_USE_VFP \\\n\t\t\t\t\t\t  -D__VXWORKS_6_9__ -D__VXWORKS \n       \ntarget-vxworks-arm-2:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=ccarm AR=ararm CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t-I$(WIND_BASE)/target/h -I$(WIND_BASE)/target/h/wrn/coreip \\\n\t\t-I$(PRJ_ROOT_DIR)/../../../../../platform/dpws/dpwscore/platform/gnu/vxworks_6.9/include \\\n\t\t$(VXWORKS_ARM_2_DEFS)\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\ntarget-vxworks-mb:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=mb-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\ntarget-vxworks-mips:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=mips-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\ntarget-vxworks-ppc:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\nVXWORKS_GCC_PPC_1_ARCH_DEFS\t= -D__ppc__ -mhard-float -mstrict-align \\\n\t\t\t\t\t\t\t  -mno-implicit-fp -DPPC32_fp60x -DCPU=PPC32\nVXWORKS_GCC_PPC_1_DEFS\t= $(VXWORKS_GCC_ARCH_DEFS) -DRW_MULTI_THREAD \\\n\t\t\t\t\t\t  -D_REENTRANT=1 -D_POSIX_THREADS -D__VXWORKS_6_2__ \\\n\t\t\t\t\t\t  -DWITH_SOAPDEFS_H -DNDEBUG=1 -DTOOL_FAMILY=gnu \\\n\t\t\t\t\t\t  -DTOOL=gnu -D_WRS_KERNEL -DWITH_NONAMESPACES \\\n\t\t\t\t\t\t  -DRW_MULTI_THREAD -DCONFIG_RANDSEED\nVXWORKS_GCC_PATH\t= $(WIND_BASE)/target/h\n\ntarget-vxworks-ppc-gnu-1:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=ccppc AR=arppc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t-I$(VXWORKS_GCC_PATH) -I$(VXWORKS_GCC_PATH)/wrn/coreip \\\n\t\t-I$(VXWORKS_GCC_PATH)/types -I$(VXWORKS_GCC_PATH)/wrn/coreip/netinet \\\n\t\t-I$(VXWORKS_GCC_PATH)/tool/gnu $(VXWORKS_GCC_PPC_1_DEFS)\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\nVXWORKS_GCC_PPC_2_ARCH_DEFS = -mcpu=603 -mhard-float -mstrict-align \\\n\t\t\t\t\t\t\t  -fno-implicit-fp -fno-zero-initialized-in-bss \\\n\t\t\t\t\t\t\t  -nostdinc -fvolatile -fno-builtin \\\n\t\t\t\t\t\t\t  -Wsystem-headers -MD -MP -G8 -DPPC32_fp60x\nVXWORKS_GCC_PPC_2_DEFS = $(VXWORKS_GCC_PPC_2_ARCH_DEFS) -DCPU=_VX_PPC32 \\\n\t\t\t\t\t\t -D_VX_CPU=_VX_PPC32 -D_WRS_VX_SMP -D_WRS_CONFIG_SMP \\\n\t\t\t\t\t\t -DWITH_NONAMESPACES -DPPC32_fp60x -DTOOL_FAMILY=gnu \\\n\t\t\t\t\t\t -DTOOL=gnu -DCPU_VARIANT=_ppc603_83xx -D__VXWORKS_6_9__ \\\n\t\t\t\t\t\t -D__VXWORKS__ -D_REENTRANT -D_POSIX_THREADS -DNDEBUG=1 \\\n\t\t\t\t\t\t -D__powerpc__ -DCONFIG_DATA_BIGENDIAN\n\ntarget-vxworks-ppc-gnu-2:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=ccppc AR=arppc CFLAGS=\"$(XCFLAGS)\n\t\t$(VXWORKS_GCC_PPC_2_DEFS) -O3 -I$(VXWORKS_GCC_PATH)/h \\\n\t\t-I$(VXWORKS_GCC_PATH)/h/wrn/coreip -I$(VXWORKS_GCC_PATH)/h/types \\\n\t\t-I$(VXWORKS_GCC_PATH)/h/wrn/coreip/netinet -I$(VXWORKS_GCC_PATH)/usr \\\n\t\t-I$(VXWORKS_GCC_PATH)/usr/h -I$(VXWORKS_GCC_PATH)/lib/h/config \\\n\t\t-I$(VXWORKS_GCC_PATH)/h/tool/gnu -I$(VXWORKS_GCC_PATH)/usr/h \\\n\t\t-I$(WIND_HOME)/gnu/4.3.3-vxworks-6.9/lib/gcc/powerpc-wrs-vxworks/4.3.3/include \\\n\t\t-I./ -I../ \\\n\t\t-I$(PRJ_ROOT_DIR)/../../../../../platform/dpws/dpwscore/platform/gnu/vxworks_6.9/include\" \\\n\t\tLDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\ntarget-vxworks-x86:\n\t@$(MAKE) OSNAME=vxworks target-init\n\t$(MAKE) $(XDEFINES) OSNAME=VxWorks CC=i386-elf-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__VxWorks__ -O3 \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=VxWorks embedded-comments\n\n# Xilinx XMK: Gnu toolchain under Unix or Cygwin.  There are two possible\n# compilers, gcc for MicroBlaze (Xilinx custom RISC core) or for PPC.  The\n# MB gcc doesn't predefine any symbols allowing us to autoconfigure\n# ourselves so we manually define __mb__.  It may also be necessary to use\n# the MicroBlaze-specific mb-ar instead of the standard ar.\n#\n# Note that the MB cores are highly reconfigurable and may have all sorts\n# of capabilities enabled or disabled.  You'll need to edit the 'xl'\n# options below based on your config.\n\ntarget-xmk-mb:\n\t@$(MAKE) OSNAME=xmk target-init\n\t@echo \"See the comments by the MicroBlaze entry in the makefile before\"\n\t@echo \"building for this core.\"\n\t$(MAKE) $(XDEFINES) OSNAME=XMK CC=mb-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_CONSERVE_MEMORY -DCONFIG_RANDSEED \\\n\t\t-D__XMK__ -D__mb__ -mno-xl-soft-mul -mxl-barrel-shift \\\n\t\t-mno-xl-soft-div -O2 -I../microblaze_0/include \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=XMK embedded-comments\n\ntarget-xmk-ppc:\n\t@$(MAKE) OSNAME=xmk target-init\n\t$(MAKE) $(XDEFINES) OSNAME=XMK CC=powerpc-eabi-gcc CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_LITTLEENDIAN -DCONFIG_RANDSEED -D__XMK__ \\\n\t\t-O2 `./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=XMK embedded-comments\n\n# Non-OS target or proprietary OS.  This will trigger #errors at various\n# locations in the code where you need to fill in the blanks for whatever\n# your OS (or non-OS) requires.\n\ntarget-generic:\n\t@$(MAKE) OSNAME=generic target-init\n\t$(MAKE) $(XDEFINES) OSNAME=generic CC=cc.exe CFLAGS=\"$(XCFLAGS) \\\n\t\t-DCONFIG_DATA_BIGENDIAN -DCONFIG_RANDSEED \\\n\t\t`./tools/ccopts-crosscompile.sh $(CC)`\" LDFLAGS=\"$(XLDFLAGS)\"\n\t@$(MAKE) OSNAME=generic embedded-comments\n\n#****************************************************************************\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#*\t\t\t\t\t\tClean up after make has finished\t\t\t\t\t*\n#*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n#****************************************************************************\n\n# The removal of the files and directories is silenced since they may not \n# exist and we don't want unnecessary error messages arising from trying to \n# remove them.\n#\n# Some build systems create additional files in the build directories, we\n# explicitly check for these before removing them rather than just removing\n# \"*\" since the latter can be risky if, for example, the path variable ends\n# up undefined.  The special files are:\n#\n# VxWorks: *.d dependency files.\n# gcov: *.gcno coverage-analysis files.\n# LLVM tools: *.ll IR files.\n# STACK analyser: *.ll.out processed LLVM IR files.\n# xlc: *.lst files dumped into the cryptlib root directory, a compiler bug.  \n#\t   See the comment for the AIX rule for more on this.\n#\n# The way this is done is a bit ugly, the standard -f <filename> check\n# doesn't work with wildcards and while it's possible to do an equivalent\n# check, it requires lots of ugly shell- and environment-specific hackery.\n# To avoid this we use a for loop (which is pretty universal) that then \n# does a wildcard delete, so that if any files match they're all deleted\n# and the loop exits.\n\nclean:\n\trm -f *.o core testlib stestlib tools/endian $(LIBNAME) $(SLIBNAME)\n\t@if [ -d $(STATIC_OBJ_DIR) ] ; then \\\n\t\tfor f in $(STATIC_OBJ_PATH)*.d ] ; do \\\n\t\t\trm -f $(STATIC_OBJ_PATH)*.d ; \\\n\t\tdone ; \\\n\t\tfor f in $(STATIC_OBJ_PATH)*.gcno ] ; do \\\n\t\t\trm -f $(STATIC_OBJ_PATH)*.gcno ; \\\n\t\tdone ; \\\n\t\tfor f in $(STATIC_OBJ_PATH)*.ll ] ; do \\\n\t\t\trm -f $(STATIC_OBJ_PATH)*.ll ; \\\n\t\tdone ; \\\n\t\tfor f in $(STATIC_OBJ_PATH)*.ll.out ] ; do \\\n\t\t\trm -f $(STATIC_OBJ_PATH)*.ll.out ; \\\n\t\tdone ; \\\n\t\trm -f $(STATIC_OBJ_PATH)*.o ; \\\n\t\trmdir $(STATIC_OBJ_DIR) ; \\\n\tfi\n\t@if [ -d $(SHARED_OBJ_DIR) ] ; then \\\n\t\trm -f $(SHARED_OBJ_PATH)*.o ; \\\n\t\trmdir $(SHARED_OBJ_DIR) ; \\\n\tfi\n\t@if [ -d ./clang_output ] ; then \\\n\t\trm -r ./clang_output/* ; \\\n\t\trmdir clang_output ; \\\n\tfi\n\t@if [ `uname -s` = 'AIX' ] ; then rm *.lst ; fi\n\t@if [ `uname -s` = 'CYGWIN_NT-5.0' ] ; then rm -f *.exe ; fi\n\t@if [ `uname -s` = 'HP-UX' ] ; then rm -f lib$(PROJ).sl ; fi\n"
  },
  {
    "path": "deps/cl345/mechs/dev_mech.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Device Mechanism Header File \t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2009\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for crypto mechanism functions supported by various devices.  \n   These are cryptlib-native mechanisms, some devices override these with \n   device-specific implementations */\n\n#ifndef _DEVMECH_DEFINED\n\n#define _DEVMECH_DEFINED\n\n/* Key derivation mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePBKDF2( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePKCS12( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveSSL( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveTLS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveTLS12( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveCMP( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePGP( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_DERIVE_INFO *mechanismInfo );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint kdfPBKDF2( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_KDF_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint kdfSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_DERIVE_INFO *mechanismInfo );\n\n/* Signature mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signPKCS1( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_SIGN_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint sigcheckPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t   INOUT MECHANISM_SIGN_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signSSL( STDC_UNUSED void *dummy, \n\t\t\t INOUT MECHANISM_SIGN_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint sigcheckSSL( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_SIGN_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_SIGN_INFO *mechanismInfo );\n\n/* Public-key key wrap mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPKCS1PGP( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPKCS1PGP( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportOAEP( STDC_UNUSED void *dummy, \n\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importOAEP( STDC_UNUSED void *dummy, \n\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint pkcWrapSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo );\n\n/* Symmetric key wrap mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportCMS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importCMS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo );\n\n/* Private key export mechanisms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPrivateKey( STDC_UNUSED void *dummy, \n\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKey( STDC_UNUSED void *dummy, \n\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPrivateKeyPKCS8( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyPKCS8( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyPGP2( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyOpenPGPOld( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyOpenPGP( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo );\n\n/* A data structure for mapping mechanisms to the functions that implement \n   them.  The device info pointer is optional and used for mechanisms that \n   are tied to particular devices */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\n\t\tint ( *MECHANISM_FUNCTION )( IN_OPT void *deviceInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT void *mechanismInfo );\ntypedef struct {\n\tconst MESSAGE_TYPE action;\n\tconst MECHANISM_TYPE mechanism;\n\tconst MECHANISM_FUNCTION function;\n\t} MECHANISM_FUNCTION_INFO;\n#endif /* _DEVMECH_DEFINED */\n"
  },
  {
    "path": "deps/cl345/mechs/keyex.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Exchange Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and determine the format of the encrypted data */\n\nCHECK_RETVAL_ENUM( CRYPT_FORMAT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic CRYPT_FORMAT_TYPE getFormatType( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int dataLength )\n\t{\n\tSTREAM stream;\n\tlong value;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES_EXT( dataLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\t  dataLength < MAX_BUFFER_SIZE, CRYPT_FORMAT_NONE );\n\n\tsMemConnect( &stream, data, min( 16, dataLength ) );\n\n\t/* Figure out what we've got.  PKCS #7/CMS/SMIME keyTrans begins:\n\n\t\tkeyTransRecipientInfo ::= SEQUENCE {\n\t\t\tversion\t\tINTEGER (0|2),\n\n\t   while a kek begins:\n\n\t\tkekRecipientInfo ::= [3] IMPLICIT SEQUENCE {\n\t\t\tversion\t\tINTEGER (0),\n\n\t   which allows us to determine which type of object we have.  Note that \n\t   we use sPeek() rather than peekTag() because we want to continue\n\t   processing (or at least checking for) PGP data if it's no ASN.1 */\n\tif( sPeek( &stream ) == BER_SEQUENCE )\n\t\t{\n\t\tCRYPT_FORMAT_TYPE formatType;\n\n\t\treadSequence( &stream, NULL );\n\t\tstatus = readShortInteger( &stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_FORMAT_NONE );\n\t\t\t}\n\t\tswitch( value )\n\t\t\t{\n\t\t\tcase KEYTRANS_VERSION:\n\t\t\t\tformatType = CRYPT_FORMAT_CMS;\n\t\t\t\tbreak;\n\n\t\t\tcase KEYTRANS_EX_VERSION:\n\t\t\t\tformatType = CRYPT_FORMAT_CRYPTLIB;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tformatType = CRYPT_FORMAT_NONE;\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( formatType );\n\t\t}\n\tif( sPeek( &stream ) == MAKE_CTAG( CTAG_RI_PWRI ) )\n\t\t{\n\t\treadConstructed( &stream, NULL, CTAG_RI_PWRI );\n\t\tstatus = readShortInteger( &stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_FORMAT_NONE );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( ( value == PWRI_VERSION ) ? \\\n\t\t\t\tCRYPT_FORMAT_CRYPTLIB : CRYPT_FORMAT_NONE );\n\t\t}\n\n#ifdef USE_PGP\n\t/* It's not ASN.1 data, check for PGP data */\n\tstatus = pgpReadPacketHeader( &stream, NULL, &value, 30, 8192 );\n\tif( cryptStatusOK( status ) && value > 30 && value < 8192 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_FORMAT_PGP );\n\t\t}\n#endif /* USE_PGP */\n\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_FORMAT_NONE );\n\t}\n\n/* Check the key wrap key being used to import/export a session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int checkWrapKey( IN_HANDLE int importKey, \n\t\t\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t\t const BOOLEAN isImport )\n\t{\n\tint localCryptAlgo, status;\n\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\n\tREQUIRES( isHandleRangeValid( importKey ) );\n\tREQUIRES( isImport == TRUE || isImport == FALSE );\n\n\t/* Clear return value */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\n\t/* Make sure that the context is valid and get the algorithm being \n\t   used */\n\tstatus = krnlSendMessage( importKey, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &localCryptAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isPkcAlgo( localCryptAlgo ) )\n\t\t{\n\t\t/* The DLP algorithms have specialised data-formatting requirements\n\t\t   and can't normally be directly accessed via external messages,\n\t\t   and PKC operations in general may be restricted to internal access\n\t\t   only if they have certificates that restrict their use associated\n\t\t   with them.  However if we're performing a high-level key import \n\t\t   (rather than a low-level raw context operation) this is OK since \n\t\t   the low-level operation is being performed via these higher-level\n\t\t   routines which handle the formatting requirements.  Doing the \n\t\t   check via an internal message is safe at this point since we've \n\t\t   already checked the context's external accessibility when we got \n\t\t   the algorithm info */\n\t\tstatus = krnlSendMessage( importKey, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t  isImport ? MESSAGE_CHECK_PKC_DECRYPT : \\\n\t\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_ENCRYPT );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( importKey, MESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t  MESSAGE_CHECK_CRYPT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*cryptAlgo = localCryptAlgo;\n\treturn( CRYPT_OK );\n\t}\n\n/* Check that the context data is encodable using the chosen format */\n\nCHECK_RETVAL \\\nstatic int checkContextsEncodable( IN_HANDLE const CRYPT_HANDLE exportKey,\n\t\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE exportAlgo,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT sessionKeyContext,\n\t\t\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tconst BOOLEAN exportIsPKC = isPkcAlgo( exportAlgo ) ? TRUE : FALSE;\n\tBOOLEAN sessionIsMAC = FALSE;\n\tint sessionKeyAlgo, sessionKeyMode DUMMY_INIT, status;\n\n\tREQUIRES( isHandleRangeValid( exportKey ) );\n\tREQUIRES( isEnumRange( exportAlgo, CRYPT_ALGO ) );\n\tREQUIRES( isHandleRangeValid( sessionKeyContext ) );\n\tREQUIRES( formatType > CRYPT_FORMAT_NONE && \\\n\t\t\t  formatType < CRYPT_FORMAT_LAST_EXTERNAL );\n\n\t/* Get any required context information */\n\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &sessionKeyAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( isMacAlgo( sessionKeyAlgo ) )\n\t\tsessionIsMAC = TRUE;\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &sessionKeyMode, CRYPT_CTXINFO_MODE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t}\n\n\tswitch( formatType )\n\t\t{\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\tcase CRYPT_FORMAT_CMS:\n\t\tcase CRYPT_FORMAT_SMIME:\n\t\t\t/* Check that the export algorithm is encodable */\n\t\t\tif( exportIsPKC )\n\t\t\t\t{\n\t\t\t\tif( cryptStatusError( sizeofAlgoID( exportAlgo ) ) )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tint exportMode;\t/* int vs.enum */\n\n\t\t\t\t/* If it's a conventional key export, the key wrap mechanism \n\t\t\t\t   requires the use of CBC mode for the wrapping */\n\t\t\t\tstatus = krnlSendMessage( exportKey, MESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\t  &exportMode, CRYPT_CTXINFO_MODE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t\t\tif( exportMode != CRYPT_MODE_CBC || \\\n\t\t\t\t\tcryptStatusError( sizeofAlgoIDex( exportAlgo, exportMode ) ) )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t\t\t}\n\n\t\t\t/* Check that the session-key algorithm is encodable */\n\t\t\tif( sessionIsMAC )\n\t\t\t\tstatus = sizeofAlgoID( sessionKeyAlgo );\n\t\t\telse\n\t\t\t\tstatus = checkAlgoID( sessionKeyAlgo, sessionKeyMode );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\n\t\t\treturn( CRYPT_OK );\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\t{\n\t\t\tint dummy;\n\n\t\t\t/* Check that the export algorithm is encodable */\n\t\t\tif( cryptStatusError( \\\n\t\t\t\t\tcryptlibToPgpAlgo( exportAlgo, &dummy ) ) )\n\t\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\n\t\t\t/* Check that the session-key algorithm is encodable */\n\t\t\tif( exportIsPKC )\n\t\t\t\t{\n\t\t\t\tif( cryptStatusError( \\\n\t\t\t\t\t\tcryptlibToPgpAlgo( sessionKeyAlgo, &dummy ) ) )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t\t\tif( sessionKeyMode != CRYPT_MODE_CFB )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tint exportMode;\t/* int vs.enum */\n\n\t\t\t\t/* If it's a conventional key export there's no key wrap as \n\t\t\t\t   in CMS (the session-key context isn't used), so the \n\t\t\t\t   \"export context\" mode must be CFB */\n\t\t\t\tstatus = krnlSendMessage( exportKey, MESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\t  &exportMode, CRYPT_CTXINFO_MODE );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\texportMode != CRYPT_MODE_CFB )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n#endif /* USE_PGP */\n\t\t}\n\t\n\t/* It's an invalid/unknown format, we can't check the encodability of \n\t   the context data */\n\treturn( CRYPT_ERROR_PARAM4 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tImport a Session Key\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import an extended encrypted key, either a cryptlib key or a CMS key */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext,\n\t\t\t\t\t\tC_OUT_OPT CRYPT_CONTEXT C_PTR returnedContext )\n\t{\n\tCRYPT_CONTEXT iReturnedContext DUMMY_INIT;\n\tCRYPT_FORMAT_TYPE formatType;\n\tCRYPT_ALGO_TYPE importAlgo;\n\tint owner = CRYPT_ERROR, originalOwner = CRYPT_ERROR, status;\n\n\t/* Perform basic error checking */\n\tif( encryptedKeyLength <= MIN_CRYPT_OBJECTSIZE || \\\n\t\tencryptedKeyLength >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtrDynamic( encryptedKey, encryptedKeyLength ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( ( formatType = \\\n\t\t\tgetFormatType( encryptedKey, encryptedKeyLength ) ) == CRYPT_FORMAT_NONE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( !isHandleRangeValid( importKey ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tif( sessionKeyContext != CRYPT_UNUSED && \\\n\t\t!isHandleRangeValid( sessionKeyContext ) )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\n\t/* Check the importing key */\n\tstatus = checkWrapKey( importKey, &importAlgo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM3 : status );\n\n\t/* Check the session key */\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\t/* PGP stores the session key information with the encrypted key\n\t\t   data, so the user can't provide a context */\n\t\tif( sessionKeyContext != CRYPT_UNUSED )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tif( !isWritePtr( returnedContext, sizeof( CRYPT_CONTEXT ) ) )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t*returnedContext = CRYPT_ERROR;\n\t\t}\n\telse\n\t\t{\n\t\tint sessionKeyAlgo;\t/* int vs.enum */\n\n\t\tif( !isHandleRangeValid( sessionKeyContext ) )\n\t\t\treturn( CRYPT_ERROR_PARAM4 );\n\t\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &sessionKeyAlgo, CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t\t  isMacAlgo( sessionKeyAlgo ) ? \\\n\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_MAC_READY : \\\n\t\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_CRYPT_READY );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM4 : status );\n\t\tif( returnedContext != NULL )\n\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* If the importing key is owned, bind the session key context to the same\n\t   owner before we load a key into it.  We also need to save the original\n\t   owner so that we can undo the binding later if things fail */\n\tstatus = krnlSendMessage( importKey, MESSAGE_GETATTRIBUTE, &owner,\n\t\t\t\t\t\t\t  CRYPT_PROPERTY_OWNER );\n\tif( cryptStatusOK( status ) && sessionKeyContext != CRYPT_UNUSED )\n\t\t{\n\t\t/* The importing key is owned, set the imported key's owner */\n\t\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &originalOwner, CRYPT_PROPERTY_OWNER );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  &owner, CRYPT_PROPERTY_OWNER );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Don't try and reset the session key ownership on error */\n\t\t\toriginalOwner = CRYPT_ERROR;\n\t\t\t}\n\t\t}\n\n\t/* Import it as appropriate */\n\tstatus = iCryptImportKey( encryptedKey, encryptedKeyLength, formatType,\n\t\t\t\t\t\t\t  importKey, sessionKeyContext, \n\t\t\t\t\t\t\t  ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\t&iReturnedContext : NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The import failed, return the session key context to its\n\t\t   original owner.  If this fails there's not much that we can do\n\t\t   to recover so we don't do anything with the return value */\n\t\tif( originalOwner != CRYPT_ERROR )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( sessionKeyContext, \n\t\t\t\t\t\t\t\t\t  MESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &originalOwner, CRYPT_PROPERTY_OWNER );\n\t\t\t}\n\t\tif( cryptArgError( status ) )\n\t\t\t{\n\t\t\t/* If we get an argument error from the lower-level code, map the\n\t\t\t   parameter number to the function argument number */\n\t\t\tstatus = ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t\t CRYPT_ERROR_PARAM4 : CRYPT_ERROR_PARAM3;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n#ifdef USE_PGP\n\t/* If it's a PGP key import then the session key was recreated from \n\t   information stored with the wrapped key so we have to make it \n\t   externally visible before it can be used by the caller */\n\tif( formatType == CRYPT_FORMAT_PGP && isPkcAlgo( importAlgo ) )\n\t\t{\n\t\t/* If the importing key is owned, set the imported key's owner */\n\t\tif( owner != CRYPT_ERROR )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iReturnedContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  &owner, CRYPT_PROPERTY_OWNER );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( iReturnedContext, IMESSAGE_DECREFCOUNT );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Make the newly-created context externally visible */\n\t\tstatus = krnlSendMessage( iReturnedContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INTERNAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iReturnedContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t*returnedContext = iReturnedContext;\n\t\t}\n#endif /* USE_PGP */\n\t\n\treturn( CRYPT_OK );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptImportKey( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\treturn( cryptImportKeyEx( encryptedKey, encryptedKeyLength, importKey,\n\t\t\t\t\t\t\t  sessionKeyContext, NULL ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tExport a Session Key\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export an extended encrypted key, either a cryptlib key or a CMS key */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptExportKeyEx( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyMaxLength,\n\t\t\t\t\t\tC_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\tC_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\tCRYPT_ALGO_TYPE exportAlgo;\n\tint sessionKeyAlgo, status;\t/* int vs.enum */\n\n\t/* Perform basic error checking */\n\tif( encryptedKey != NULL )\n\t\t{\n\t\tif( encryptedKeyMaxLength <= MIN_CRYPT_OBJECTSIZE || \\\n\t\t\tencryptedKeyMaxLength >= MAX_BUFFER_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\tif( !isWritePtrDynamic( encryptedKey, encryptedKeyMaxLength ) )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\tmemset( encryptedKey, 0, MIN_CRYPT_OBJECTSIZE );\n\t\t}\n\telse\n\t\t{\n\t\tif( encryptedKeyMaxLength != 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\t}\n\tif( !isWritePtr( encryptedKeyLength, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t*encryptedKeyLength = 0;\n\tif( formatType != CRYPT_FORMAT_CRYPTLIB && \\\n\t\tformatType != CRYPT_FORMAT_CMS && \\\n\t\tformatType != CRYPT_FORMAT_SMIME && \\\n\t\tformatType != CRYPT_FORMAT_PGP )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tif( !isHandleRangeValid( exportKey ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\tif( !isHandleRangeValid( sessionKeyContext ) )\n\t\treturn( CRYPT_ERROR_PARAM6 );\n\n\t/* Check the exporting key */\n\tstatus = checkWrapKey( exportKey, &exportAlgo, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );\n\tstatus = checkContextsEncodable( exportKey, exportAlgo, \n\t\t\t\t\t\t\t\t\t sessionKeyContext, formatType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( ( status == CRYPT_ERROR_PARAM1 ) ? CRYPT_ERROR_PARAM5 : \\\n\t\t\t\t( status == CRYPT_ERROR_PARAM3 ) ? CRYPT_ERROR_PARAM6 : \\\n\t\t\t\tCRYPT_ERROR_PARAM4 );\n\t\t}\n\n\t/* Check the exported key */\n\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &sessionKeyAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM6 );\n\tstatus = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  isMacAlgo( sessionKeyAlgo ) ? \\\n\t\t\t\t\t\t\t\tMESSAGE_CHECK_MAC : MESSAGE_CHECK_CRYPT );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM6 : status );\n\n\t/* Export the key via the shared export function */\n\tstatus = iCryptExportKey( encryptedKey, encryptedKeyMaxLength, \n\t\t\t\t\t\t\t  encryptedKeyLength, formatType,\n\t\t\t\t\t\t\t  sessionKeyContext, exportKey );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* If we get an argument error from the lower-level code, map the\n\t\t   parameter number to the function argument number */\n\t\tstatus = ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t CRYPT_ERROR_PARAM6 : CRYPT_ERROR_PARAM5;\n\t\t}\n\treturn( status );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptExportKey( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyMaxLength,\n\t\t\t\t\t  C_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\tint status;\n\n\tstatus = cryptExportKeyEx( encryptedKey, encryptedKeyMaxLength,\n\t\t\t\t\t\t\t   encryptedKeyLength, CRYPT_FORMAT_CRYPTLIB,\n\t\t\t\t\t\t\t   exportKey, sessionKeyContext );\n\treturn( ( status == CRYPT_ERROR_PARAM5 ) ? CRYPT_ERROR_PARAM4 : \\\n\t\t\t( status == CRYPT_ERROR_PARAM6 ) ? CRYPT_ERROR_PARAM5 : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal Import/Export Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Internal versions of the above.  These skip a lot of the explicit \n   checking done by the external versions (e.g. \"Is this value really a \n   handle to a valid PKC context?\") since they're only called by cryptlib \n   internal functions rather than being passed untrusted user data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint iCryptImportKey( IN_BUFFER( encryptedKeyLength ) const void *encryptedKey, \n\t\t\t\t\t IN_LENGTH_SHORT const int encryptedKeyLength,\n\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iImportKey,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iReturnedContext )\n\t{\n\tconst KEYEX_TYPE keyexType = \\\n\t\t\t( formatType == CRYPT_FORMAT_AUTO || \\\n\t\t\t  formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \\\n\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;\n\tint importAlgo,\tstatus;\t/* int vs.enum */\n\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\tassert( ( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t  isWritePtr( iReturnedContext, sizeof( CRYPT_CONTEXT ) ) ) || \\\n\t\t\t( formatType != CRYPT_FORMAT_PGP && \\\n\t\t\t  iReturnedContext == NULL ) );\n\n\tREQUIRES( encryptedKeyLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( isHandleRangeValid( iImportKey ) );\n\tREQUIRES( ( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\tiSessionKeyContext == CRYPT_UNUSED ) || \\\n\t\t\t  ( formatType != CRYPT_FORMAT_PGP && \\\n\t\t\t\tisHandleRangeValid( iSessionKeyContext ) ) );\n\tREQUIRES( ( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\tiReturnedContext != NULL ) || \\\n\t\t\t  ( formatType != CRYPT_FORMAT_PGP && \\\n\t\t\t\tiReturnedContext == NULL ) );\n\n\t/* Clear return values */\n\tif( iReturnedContext != NULL )\n\t\t*iReturnedContext = CRYPT_ERROR;\n\n\t/* Import it as appropriate.  We don't handle key agreement at this\n\t   level since it's a protocol-specific mechanism used by SSH and SSL,\n\t   which are internal-only formats */\n\tstatus = krnlSendMessage( iImportKey, IMESSAGE_GETATTRIBUTE, &importAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isConvAlgo( importAlgo ) )\n\t\t{\n\t\tif( !isHandleRangeValid( iSessionKeyContext ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM2 );\n\t\treturn( importConventionalKey( encryptedKey, encryptedKeyLength,\n\t\t\t\t\t\t\t\t\t   iSessionKeyContext, iImportKey,\n\t\t\t\t\t\t\t\t\t   keyexType ) );\n\t\t}\n\treturn( importPublicKey( encryptedKey, encryptedKeyLength,\n\t\t\t\t\t\t\t iSessionKeyContext, iImportKey,\n\t\t\t\t\t\t\t iReturnedContext, keyexType ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptExportKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \\\n\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iExportKey )\n\t{\n\tconst KEYEX_TYPE keyexType = \\\n\t\t\t( formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \\\n\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;\n\tDYNBUF auxDB;\n\tconst int encKeyMaxLength = ( encryptedKey == NULL ) ? \\\n\t\t\t\t\t\t\t\t0 : encryptedKeyMaxLength;\n\tint exportAlgo, status;\t/* int vs.enum */\n\n\tassert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\t( encryptedKeyMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  isWritePtrDynamic( encryptedKey, encryptedKeyMaxLength ) ) );\n\tassert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );\n\n\tREQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\t  ( encryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tencryptedKeyMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( ( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\t\tiSessionKeyContext == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( iSessionKeyContext ) );\n\tREQUIRES( isHandleRangeValid( iExportKey ) );\n\n\tANALYSER_HINT( encryptedKeyLength != NULL );\n\n\t/* Clear return value */\n\t*encryptedKeyLength = 0;\n\n\t/* Perform simplified error checking */\n\tstatus = krnlSendMessage( iExportKey, IMESSAGE_GETATTRIBUTE, &exportAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\n\t/* If it's a non-PKC export, pass the call down to the low-level export\n\t   function */\n\tif( !isPkcAlgo( exportAlgo ) )\n\t\t{\n\t\treturn( exportConventionalKey( encryptedKey, encKeyMaxLength, \n\t\t\t\t\t\t\t\t\t   encryptedKeyLength, iSessionKeyContext, \n\t\t\t\t\t\t\t\t\t   iExportKey, keyexType ) );\n\t\t}\n\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\n\t/* If it's a non-CMS/SMIME PKC export, pass the call down to the low-\n\t   level export function */\n\tif( formatType != CRYPT_FORMAT_CMS && formatType != CRYPT_FORMAT_SMIME )\n\t\t{\n\t\treturn( exportPublicKey( encryptedKey, encKeyMaxLength, \n\t\t\t\t\t\t\t\t encryptedKeyLength, iSessionKeyContext, \n\t\t\t\t\t\t\t\t iExportKey, NULL, 0, keyexType ) );\n\t\t}\n\n\tREQUIRES( keyexType == KEYEX_CMS );\n\n\t/* We're exporting a key in CMS format we need to obtain recipient \n\t   information from the certificate associated with the export context.\n\t   First we lock the certificate for our exclusive use and in case it's \n\t   a certificate chain select the first certificate in the chain */\n\tstatus = krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\tstatus = krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Unlock the chain before we exit.  If this fails there's not much \n\t\t   that we can do to recover so we don't do anything with the return \n\t\t   value */\n\t\t( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* Next we get the recipient information from the certificate into a \n\t   dynbuf */\n\tstatus = dynCreate( &auxDB, iExportKey,\n\t\t\t\t\t\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t}\n\n\t/* We're ready to export the key alongside the key ID as auxiliary \n\t   data */\n\tstatus = exportPublicKey( encryptedKey, encKeyMaxLength, \n\t\t\t\t\t\t\t  encryptedKeyLength, iSessionKeyContext, \n\t\t\t\t\t\t\t  iExportKey, dynData( auxDB ), \n\t\t\t\t\t\t\t  dynLength( auxDB ), keyexType );\n\n\t/* Clean up.  If the unlock fails there's not much that we can do to \n\t   recover so we don't do anything with the return value */\n\t( void ) krnlSendMessage( iExportKey, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tdynDestroy( &auxDB );\n\n\treturn( status );\n\t}\n\n#else\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tStub Functions for non-CMS/PGP Use\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nC_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext,\n\t\t\t\t\t\tC_OUT CRYPT_CONTEXT C_PTR returnedContext )\n\t{\n\tUNUSED_ARG( encryptedKey );\n\tUNUSED_ARG( returnedContext );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptImportKey( C_IN void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT importKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\tUNUSED_ARG( encryptedKey );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptExportKeyEx( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t\tC_IN int encryptedKeyMaxLength,\n\t\t\t\t\t\tC_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t\tC_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\tC_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\tUNUSED_ARG( encryptedKey );\n\tUNUSED_ARG( encryptedKeyLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptExportKey( C_OUT_OPT void C_PTR encryptedKey,\n\t\t\t\t\t  C_IN int encryptedKeyMaxLength,\n\t\t\t\t\t  C_OUT int C_PTR encryptedKeyLength,\n\t\t\t\t\t  C_IN CRYPT_HANDLE exportKey,\n\t\t\t\t\t  C_IN CRYPT_CONTEXT sessionKeyContext )\n\t{\n\tUNUSED_ARG( encryptedKey );\n\tUNUSED_ARG( encryptedKeyLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/keyex_int.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal Key Exchange Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"mech.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"mechs/mech.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tLow-level Key Export Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export a conventionally encrypted session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint exportConventionalKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \\\n\t\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t\t   IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iExportContext,\n\t\t\t\t\t\t   IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tconst WRITEKEK_FUNCTION writeKeyexFunction = getWriteKekFunction( keyexType );\n\tBYTE buffer[ CRYPT_MAX_KEYSIZE + 16 + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint keySize, ivSize, status;\n\n\tassert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( encryptedKey, encryptedKeyMaxLength ) );\n\tassert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );\n\n\tREQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\t  ( encryptedKey != NULL && \\\n\t\t\t\tencryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tencryptedKeyMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( ( keyexType == KEYEX_PGP && \\\n\t\t\t\tiSessionKeyContext == CRYPT_UNUSED ) || \\\n\t\t\t  ( keyexType != KEYEX_PGP && \\\n\t\t\t\tisHandleRangeValid( iSessionKeyContext ) ) );\n\tREQUIRES( isHandleRangeValid( iExportContext ) );\n\tREQUIRES( isEnumRange( keyexType, KEYEX ) );\n\n\t/* Clear return value */\n\t*encryptedKeyLength = 0;\n\n\t/* Make sure that the requested key exchange format is available */\n\tif( writeKeyexFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n#ifdef USE_PGP\n\t/* PGP doesn't actually wrap up a key but derives the session key\n\t   directly from the password.  Because of this there isn't any key\n\t   wrapping to be done so we just write the key derivation parameters\n\t   and exit */\n\tif( keyexType == KEYEX_PGP )\n\t\t{\n\t\tSTREAM stream;\n\n\t\tsMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );\n\t\tstatus = writeKeyexFunction( &stream, iExportContext, NULL, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*encryptedKeyLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( status );\n\t\t}\n#endif /* USE_PGP */\n\n\t/* Get the export parameters */\n\tstatus = krnlSendMessage( iSessionKeyContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &keySize, CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\tif( cryptStatusError( krnlSendMessage( iExportContext,\n\t\t\t\t\t\t\t\t\t\t   IMESSAGE_GETATTRIBUTE, &ivSize,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_IVSIZE ) ) )\n\t\tivSize = 0;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Load an IV into the exporting context.  This is somewhat nasty in that\n\t   a side-effect of exporting a key is to load an IV, which isn't really \n\t   part of the function's job description.  The alternative would be to \n\t   require the user to explicitly load an IV before exporting the key, \n\t   but this is equally nasty because they'll never remember.  The lesser \n\t   of the two evils is to load the IV here and assume that anyone \n\t   loading the IV themselves will read the docs, which warn about the \n\t   side-effects of exporting a key.\n\n\t   Note that we always load a new IV when we export a key because the\n\t   caller may be using the context to exchange multiple keys.  Since each\n\t   exported key requires its own IV we perform an unconditional reload.\n\t   In addition because we don't want another thread coming along and\n\t   changing the IV while we're in the process of encrypting with it, we\n\t   lock the exporting key object until the encryption has completed and\n\t   the IV is written to the output */\n\tstatus = krnlSendMessage( iExportContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ivSize > 0 )\n\t\t{\n\t\tstatus = krnlSendNotifier( iExportContext, IMESSAGE_CTX_GENIV );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_GENIV\" );\n\n\t/* Encrypt the session key and write the result to the output stream */\n\tif( encryptedKey == NULL )\n\t\t{\n\t\tsetMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, \n\t\t\t\t\t\t\t  iSessionKeyContext, iExportContext );\n\t\t}\n\telse\n\t\t{\n\t\tsetMechanismWrapInfo( &mechanismInfo, buffer, CRYPT_MAX_KEYSIZE + 16, \n\t\t\t\t\t\t\t  NULL, 0, iSessionKeyContext, iExportContext );\n\t\t}\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_CMS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tSTREAM stream;\n\n\t\t/* If we're perfoming a dummy export for a length check, set up a \n\t\t   dummy value to write */\n\t\tif( encryptedKey == NULL )\n\t\t\tmemset( buffer, 0x01, mechanismInfo.wrappedDataLength );\n\n\t\tINJECT_FAULT( MECH_CORRUPT_KEY, MECH_CORRUPT_KEY_1 );\n\t\tsMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );\n\t\tstatus = writeKeyexFunction( &stream, iExportContext,\n\t\t\t\t\t\t\t\t\t ( encryptedKey != NULL ) ? \\\n\t\t\t\t\t\t\t\t\t\tmechanismInfo.wrappedData : buffer,\n\t\t\t\t\t\t\t\t\t mechanismInfo.wrappedDataLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*encryptedKeyLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tINJECT_FAULT( MECH_CORRUPT_SALT, MECH_CORRUPT_SALT_1 );\n\t\tINJECT_FAULT( MECH_CORRUPT_ITERATIONS, MECH_CORRUPT_ITERATIONS_1 );\n\t\tINJECT_FAULT( MECH_CORRUPT_PRFALGO, MECH_CORRUPT_PRFALGO_1 );\n\t\tCFI_CHECK_UPDATE( \"writeKeyexFunction\" );\n\t\t}\n\t( void ) krnlSendMessage( iExportContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tclearMechanismInfo( &mechanismInfo );\n\tzeroise( buffer, CRYPT_MAX_KEYSIZE + 16 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \"IMESSAGE_CTX_GENIV\",\n\t\t\t\t\t\t\t\t\t\"writeKeyexFunction\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Export a public-key encrypted session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint exportPublicKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \\\n\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iExportContext,\n\t\t\t\t\t IN_BUFFER_OPT( auxInfoLength ) const void *auxInfo, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int auxInfoLength,\n\t\t\t\t\t IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tconst WRITEKEYTRANS_FUNCTION writeKeytransFunction = getWriteKeytransFunction( keyexType );\n\tconst BOOLEAN requiresSizeFixup = \\\n\t\t\t\t( ( keyexType == KEYEX_CMS || keyexType == KEYEX_CRYPTLIB ) && \\\n\t\t\t\t  ( encryptedKey != NULL ) ) ? TRUE : FALSE;\n\tBYTE buffer[ MAX_PKCENCRYPTED_SIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint exportKeySize DUMMY_INIT, status;\n\n\tassert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( encryptedKey, encryptedKeyMaxLength ) );\n\tassert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );\n\tassert( ( auxInfo == NULL && auxInfoLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( auxInfo, auxInfoLength ) );\n\t\n\tREQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \\\n\t\t\t  ( encryptedKey != NULL && \\\n\t\t\t\tencryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tencryptedKeyMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\tREQUIRES( isHandleRangeValid( iExportContext ) );\n\tREQUIRES( ( auxInfo == NULL && auxInfoLength == 0 ) || \\\n\t\t\t  ( auxInfo != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( auxInfoLength ) ) );\n\tREQUIRES( isEnumRange( keyexType, KEYEX ) );\n\n\t/* Clear return value */\n\t*encryptedKeyLength = 0;\n\n\t/* Make sure that the requested key exchange format is available */\n\tif( writeKeytransFunction  == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Get the export parameters */\n\tif( requiresSizeFixup )\n\t\t{\n\t\tstatus = krnlSendMessage( iExportContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &exportKeySize, CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\t\tif( exportKeySize > encryptedKeyMaxLength )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Encrypt the session key and write the result to the output stream */\n\tif( encryptedKey == NULL )\n\t\t{\n\t\tsetMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, \n\t\t\t\t\t\t\t  iSessionKeyContext, iExportContext );\n\t\t}\n\telse\n\t\t{\n\t\tsetMechanismWrapInfo( &mechanismInfo, buffer, MAX_PKCENCRYPTED_SIZE, \n\t\t\t\t\t\t\t  NULL, 0, iSessionKeyContext, iExportContext );\n\t\t}\n\tif( keyexType == KEYEX_CMS_OAEP )\n\t\t{\n\t\t/* OAEP requires an additional parameter, the hash algorithm to use.\n\t\t   Actually it requires numerous additional parameters because in \n\t\t   OAEP absolutely everything is parameterised, but at the moment the\n\t\t   only one that's really used is SHA-1, which is also the default\n\t\t   algorithm ID for the various parameters and so doesn't require \n\t\t   extensive additional encoding.  Because of this we always use \n\t\t   SHA-1 */\n\t\tmechanismInfo.auxInfo = CRYPT_ALGO_SHA1;\n\t\t}\n\tstatus = krnlSendMessage( iExportContext, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, \n\t\t\t\t\t\t\t  ( keyexType == KEYEX_PGP ) ? \\\n\t\t\t\t\t\t\t\tMECHANISM_ENC_PKCS1_PGP : \\\n\t\t\t\t\t\t\t  ( keyexType == KEYEX_CMS_OAEP ) ? \\\n\t\t\t\t\t\t\t\tMECHANISM_ENC_OAEP : MECHANISM_ENC_PKCS1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tSTREAM stream;\n\n\t\t/* If we're perfoming a dummy export for a length check, set up a \n\t\t   dummy value to write */\n\t\tif( encryptedKey == NULL )\n\t\t\t{\n\t\t\tmemset( buffer, 0x01, mechanismInfo.wrappedDataLength );\n\t\t\tmechanismInfo.wrappedData = buffer;\n\t\t\t}\n\n\t\t/* If we're using the CMS data format then we need to fix up the \n\t\t   size of the wrapped key data to match the exporting key size.  \n\t\t   This is necessary because the higher-level ASN.1 wrappers at the \n\t\t   CMS envelope level won't reflect the fact that the size has \n\t\t   changed at the CMS keyex level, so we need to adjust the data \n\t\t   size to ensure that the amount of data we output matches what\n\t\t   was promised in the size check */\n\t\tif( requiresSizeFixup && mechanismInfo.wrappedDataLength < exportKeySize )\n\t\t\t{\n\t\t\tconst int delta = exportKeySize - mechanismInfo.wrappedDataLength;\n\n\t\t\tREQUIRES( boundsCheck( delta, mechanismInfo.wrappedDataLength, \n\t\t\t\t\t\t\t\t   MAX_PKCENCRYPTED_SIZE ) );\n\t\t\tmemmove( ( BYTE * ) mechanismInfo.wrappedData + delta, \n\t\t\t\t\t mechanismInfo.wrappedData, \n\t\t\t\t\t mechanismInfo.wrappedDataLength );\n\t\t\tmemset( mechanismInfo.wrappedData, 0, delta );\n\t\t\tmechanismInfo.wrappedDataLength = exportKeySize;\n\t\t\t}\n\n\t\tINJECT_FAULT( MECH_CORRUPT_KEY, MECH_CORRUPT_KEY_1 );\n\t\tsMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );\n\t\tstatus = writeKeytransFunction ( &stream, iExportContext, \n\t\t\t\t\t\t\t\t\t\t mechanismInfo.wrappedData,\n\t\t\t\t\t\t\t\t\t\t mechanismInfo.wrappedDataLength,\n\t\t\t\t\t\t\t\t\t\t auxInfo, auxInfoLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*encryptedKeyLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tCFI_CHECK_UPDATE( \"writeKeytransFunction\" );\n\t\t}\n\tclearMechanismInfo( &mechanismInfo );\n\n\t/* Clean up */\n\tzeroise( buffer, MAX_PKCENCRYPTED_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"IMESSAGE_GETATTRIBUTE\",\n\t\t\t\t\t\t\t\t\t\"writeKeytransFunction\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tLow-level Key Import Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import a conventionally encrypted session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importConventionalKey( IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\tconst void *encryptedKey, \n\t\t\t\t\t\t   IN_DATALENGTH const int encryptedKeyLength,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t\t   IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tconst READKEK_FUNCTION readKeyexFunction = getReadKekFunction( keyexType );\n\tQUERY_INFO queryInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tint importAlgo, importMode DUMMY_INIT, status;\t/* int vs.enum */\n\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\n\tREQUIRES( encryptedKeyLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( iSessionKeyContext ) );\n\tREQUIRES( isHandleRangeValid( iImportContext ) );\n\tREQUIRES( isEnumRange( keyexType, KEYEX ) );\n\n\t/* Make sure that the requested key exchange format is available */\n\tif( readKeyexFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Get the import parameters */\n\tstatus = krnlSendMessage( iImportContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &importAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &importMode, CRYPT_CTXINFO_MODE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\n\t/* Read and check the encrypted key record and make sure that we'll be \n\t   using the correct type of encryption context to decrypt it */\n\tsMemConnect( &stream, encryptedKey, encryptedKeyLength );\n\tstatus = readKeyexFunction( &stream, &queryInfo );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) && \\\n\t\t( importAlgo != queryInfo.cryptAlgo || \\\n\t\t  importMode != queryInfo.cryptMode ) )\n\t\tstatus = CRYPT_ARGERROR_NUM1;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Extract the encrypted key from the buffer and decrypt it.  Since we\n\t   don't want another thread changing the IV while we're using the import\n\t   context, we lock it for the duration */\n\tstatus = krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tif( needsIV( importMode ) && importAlgo != CRYPT_ALGO_RC4 )\n\t\t{\n\t\tsetMessageData( &msgData, queryInfo.iv, queryInfo.ivLength );\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( boundsCheck( queryInfo.dataStart, queryInfo.dataLength,\n\t\t\t\t\t\t  encryptedKeyLength ) );\n\tsetMechanismWrapInfo( &mechanismInfo,\n\t\t\t\t\t\t  ( BYTE * ) encryptedKey + queryInfo.dataStart, \n\t\t\t\t\t\t  queryInfo.dataLength, NULL, 0, \n\t\t\t\t\t\t  iSessionKeyContext, iImportContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_CMS );\n\t( void ) krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\tclearMechanismInfo( &mechanismInfo );\n\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\n\treturn( status );\n\t}\n\n/* Import a public-key encrypted session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importPublicKey( IN_BUFFER( encryptedKeyLength ) const void *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH const int encryptedKeyLength,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iReturnedContext, \n\t\t\t\t\t IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tconst READKEYTRANS_FUNCTION readKeytransFunction = getReadKeytransFunction( keyexType );\n\tQUERY_INFO queryInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tint compareType, status;\n\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\tassert( ( keyexType == KEYEX_PGP && \\\n\t\t\t  isWritePtr( iReturnedContext, sizeof( CRYPT_CONTEXT ) ) ) || \\\n\t\t\t( keyexType != KEYEX_PGP && iReturnedContext == NULL ) );\n\n\tREQUIRES( encryptedKeyLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( keyexType == KEYEX_PGP && \\\n\t\t\t\tiSessionKeyContext == CRYPT_UNUSED ) || \\\n\t\t\t  ( keyexType != KEYEX_PGP && \\\n\t\t\t\tisHandleRangeValid( iSessionKeyContext ) ) );\n\tREQUIRES( isHandleRangeValid( iImportContext ) );\n\tREQUIRES( ( keyexType == KEYEX_PGP && iReturnedContext != NULL ) || \\\n\t\t\t  ( keyexType != KEYEX_PGP && iReturnedContext == NULL ) );\n\tREQUIRES( isEnumRange( keyexType, KEYEX ) );\n\n\t/* Clear return value */\n\tif( iReturnedContext != NULL )\n\t\t*iReturnedContext = CRYPT_ERROR;\n\n\t/* Make sure that the requested key exchange format is available */\n\tif( readKeytransFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Read and check the encrypted key record */\n\tsMemConnect( &stream, encryptedKey, encryptedKeyLength );\n\tstatus = readKeytransFunction( &stream, &queryInfo );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that we've been given the correct key */\n\tsetMessageData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );\n\tswitch( keyexType )\n\t\t{\n\t\tcase KEYEX_CMS:\n\t\t\tsetMessageData( &msgData, \\\n\t\t\t\t\t( BYTE * ) encryptedKey + queryInfo.iAndSStart, \\\n\t\t\t\t\tqueryInfo.iAndSLength );\n\t\t\tcompareType = MESSAGE_COMPARE_ISSUERANDSERIALNUMBER;\n\t\t\tbreak;\n\n\t\tcase KEYEX_CRYPTLIB:\n\t\t\tcompareType = MESSAGE_COMPARE_KEYID;\n\t\t\tbreak;\n\n\t\tcase KEYEX_PGP:\n\t\t\tcompareType = ( queryInfo.version == PGP_VERSION_2 ) ? \\\n\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID_PGP : \\\n\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID_OPENPGP;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tstatus = krnlSendMessage( iImportContext, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t  compareType );\n\tif( cryptStatusError( status ) && \\\n\t\tcompareType == MESSAGE_COMPARE_KEYID )\n\t\t{\n\t\t/* Checking for the keyID gets a bit complicated, in theory it's the \n\t\t   subjectKeyIdentifier from a certificate but in practice this form \n\t\t   is mostly used for certificateless public keys.  Because of this we \n\t\t   check for the keyID first and if that fails fall back to the \n\t\t   sKID */\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER );\n\t\t}\n\tif( cryptStatusError( status ) && \\\n\t\tcompareType == MESSAGE_COMPARE_KEYID_OPENPGP )\n\t\t{\n\t\t/* Some broken PGP implementations put PGP 2.x IDs in packets marked \n\t\t   as OpenPGP packets so if we were doing a check for an OpenPGP ID \n\t\t   and it failed, fall back to a PGP 2.x one */\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_KEYID_PGP );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* A failed comparison is reported as a generic CRYPT_ERROR, convert \n\t\t   it into a wrong-key error */\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t}\n\n\t/* Decrypt the encrypted key and load it into the context */\n\tif( keyexType != KEYEX_PGP )\n\t\t{\n\t\tconst BOOLEAN isOAEP = \\\n\t\t\t\t( queryInfo.cryptAlgoEncoding == ALGOID_ENCODING_OAEP ) ? \\\n\t\t\t\tTRUE : FALSE;\n\n\t\tsetMechanismWrapInfo( &mechanismInfo,\n\t\t\t\t\t\t\t  ( BYTE * ) encryptedKey + queryInfo.dataStart, \n\t\t\t\t\t\t\t  queryInfo.dataLength, NULL, 0, \n\t\t\t\t\t\t\t  iSessionKeyContext, iImportContext );\n\t\tif( isOAEP )\n\t\t\t{\n\t\t\t/* See the comment in exportPublicKey() on the hardcoding of \n\t\t\t   SHA-1 */\n\t\t\tmechanismInfo.auxInfo = CRYPT_ALGO_SHA1;\n\t\t\t}\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t\t  &mechanismInfo, isOAEP ? \\\n\t\t\t\t\t\t\t\t\tMECHANISM_ENC_OAEP : \\\n\t\t\t\t\t\t\t\t\tMECHANISM_ENC_PKCS1 );\n\t\t}\n\telse\n\t\t{\n\t\t/* PGP doesn't provide separate session key information with the\n\t\t   encrypted data but wraps it up alongside the encrypted key, so we\n\t\t   can't import the wrapped key into a context via the standard key\n\t\t   import functions but instead have to create the context as part\n\t\t   of the unwrap process */\n\t\tsetMechanismWrapInfo( &mechanismInfo, \n\t\t\t\t\t\t\t  ( BYTE * ) encryptedKey + queryInfo.dataStart,\n\t\t\t\t\t\t\t  queryInfo.dataLength, NULL, 0, \n\t\t\t\t\t\t\t  CRYPT_UNUSED, iImportContext );\n\t\tstatus = krnlSendMessage( iImportContext, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_PKCS1_PGP );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*iReturnedContext = mechanismInfo.keyContext;\n\t\t}\n\tclearMechanismInfo( &mechanismInfo );\n\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\n\treturn( status );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/keyex_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tKey Exchange Read/Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n/* Context-specific tags for the KEK record */\n\nenum { CTAG_KK_DA };\n\n/* Context-specific tags for the KeyTrans record */\n\nenum { CTAG_KT_SKI };\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a CMS key identifier.  This gets a bit complicated because in theory \n   we're supposed to use the sKID from a certificate but it we're using a \n   raw public key then there's no sKID present.  To deal with this we try \n   for an sKID if the object that we've been passed is a certificate, if \n   that fails or if it's a raw context then we use the keyID */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint getCmsKeyIdentifier( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t OUT_BUFFER( keyIDMaxLength, *keyIDlength ) \\\n\t\t\t\t\t\t\tBYTE *keyID, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) const int keyIDMaxLength,\n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( keyIDMaxLength ) \\\n\t\t\t\t\t\t\tint *keyIDlength )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtrDynamic( keyID, keyIDMaxLength ) );\n\tassert( isWritePtr( keyIDlength, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( keyIDMaxLength >= 32 && keyIDMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( keyID, 0, min( 16, keyIDMaxLength ) );\n\t*keyIDlength = 0;\n\n\t/* If it's a certificate, try for an sKID */\n\tsetMessageData( &msgData, keyID, keyIDMaxLength );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t*keyIDlength = msgData.length;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Use the keyID */\n\tsetMessageData( &msgData, keyID, keyIDMaxLength );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*keyIDlength = msgData.length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tConventionally-Encrypted Key Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The OID for the PKCS #5 v2.0 key derivation function and the parameterised\n   PWRI key wrap algorithm */\n\n#define OID_PBKDF2\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x05\\x0C\" )\n#define OID_PWRIKEK\tMKOID( \"\\x06\\x0B\\x2A\\x86\\x48\\x86\\xF7\\x0D\\x01\\x09\\x10\\x03\\x09\" )\n\n/* Read/write a PBKDF2 key derivation record:\n\n\tSEQUENCE {\n\t\talgorithm\t\t\t\t\tAlgorithmIdentifier (pkcs-5 12),\n\t\tparams SEQUENCE {\n\t\t\tsalt\t\t\t\t\tOCTET STRING,\n\t\t\titerationCount\t\t\tINTEGER (1..MAX),\n\t\t\tkeyLength\t\t\t\tINTEGER OPTIONAL,\n\t\t\tprf\t\t\t\t\t\tAlgorithmIdentifier DEFAULT hmacWithSHA1\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readKeyDerivationInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  OUT QUERY_INFO *queryInfo )\n\t{\n\tlong endPos, value;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the outer wrapper and key derivation algorithm OID */\n\treadConstructed( stream, NULL, CTAG_KK_DA );\n\tstatus = readFixedOID( stream, OID_PBKDF2, sizeofOID( OID_PBKDF2 ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the PBKDF2 parameters, limiting the salt and iteration count to\n\t   sane values */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\treadOctetString( stream, queryInfo->salt, &queryInfo->saltLength, \n\t\t\t\t\t 2, CRYPT_MAX_HASHSIZE );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value < 1 || value > MAX_KEYSETUP_ITERATIONS )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tENSURES( isIntegerRange( value ) );\n\tqueryInfo->keySetupIterations = ( int ) value;\n\tqueryInfo->keySetupAlgo = CRYPT_ALGO_HMAC_SHA1;\n\tif( stell( stream ) < endPos && \\\n\t\tsPeek( stream ) == BER_INTEGER )\n\t\t{\n\t\t/* There's an optional key length that may override the default \n\t\t   key size present, read it.  Note that we compare the upper\n\t\t   bound to MAX_WORKING_KEYSIZE rather than CRYPT_MAX_KEYSIZE,\n\t\t   since this is a key used directly with an encryption algorithm\n\t\t   rather than a generic keying value that may be hashed down to \n\t\t   size */\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( value < MIN_KEYSIZE || value > MAX_WORKING_KEYSIZE )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tENSURES( isIntegerRange( value ) );\n\t\tqueryInfo->keySize = ( int ) value;\n\t\t}\n\tif( stell( stream ) < endPos )\n\t\t{\n\t\tCRYPT_ALGO_TYPE prfAlgo;\n\t\tint prfAlgoParam;\n\t\n\t\t/* There's a non-default hash algorithm ID present, read it */\n\t\tstatus = readAlgoIDex( stream, &prfAlgo, NULL, &prfAlgoParam, \n\t\t\t\t\t\t\t   ALGOID_CLASS_HASH );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->keySetupAlgo = prfAlgo;\n\t\tqueryInfo->keySetupAlgoParam = prfAlgoParam;\n\t\t}\n\n\t/* Make sure that we've read everything present */\n\tif( stell( stream ) != endPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeKeyDerivationInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iCryptContext )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint saltLength, keySetupIterations, prfAlgo DUMMY_INIT;\n\tint derivationInfoSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\n\t/* Get the key derivation information */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &keySetupIterations,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &prfAlgo, CRYPT_CTXINFO_KEYING_ALGO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, salt, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_SALT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsaltLength = msgData.length;\n\tderivationInfoSize = sizeofShortObject( saltLength ) + \\\n\t\t\t\t\t\t sizeofShortInteger( keySetupIterations );\n\tif( prfAlgo != CRYPT_ALGO_HMAC_SHA1 )\n\t\t{\n\t\tint prfAlgoIDsize;\n\n\t\tstatus = prfAlgoIDsize = sizeofAlgoID( prfAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tderivationInfoSize += prfAlgoIDsize;\n\t\t}\n\n\t/* Write the PBKDF2 information */\n\twriteConstructed( stream, sizeofOID( OID_PBKDF2 ) + \\\n\t\t\t\t\t\t\t  sizeofShortObject( derivationInfoSize ), \n\t\t\t\t\t  CTAG_KK_DA );\n\twriteOID( stream, OID_PBKDF2 );\n\twriteSequence( stream, derivationInfoSize );\n\twriteOctetString( stream, salt, saltLength, DEFAULT_TAG );\n\tstatus = writeShortInteger( stream, keySetupIterations, DEFAULT_TAG );\n\tif( prfAlgo != CRYPT_ALGO_HMAC_SHA1 )\n\t\tstatus = writeAlgoID( stream, prfAlgo );\n\tzeroise( salt, CRYPT_MAX_HASHSIZE );\n\treturn( status );\n\t}\n\n/* Read/write CMS KEK data.  This is the weird Spyrus key wrap that was \n   slipped into CMS, nothing seems to support this so we don't either */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCmsKek( INOUT STREAM *stream, \n\t\t\t\t\t   OUT QUERY_INFO *queryInfo )\n\t{\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the header */\n\treadConstructed( stream, NULL, CTAG_RI_KEKRI );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != KEK_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n#if 0\t/* 21/4/06 Disabled since it was never used */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeCmsKek( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\tIN_BUFFER( encryptedKeyLength ) const BYTE *encryptedKey, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) \\\n\t\t\t\t\t\t\tconst int encryptedKeyLength )\n\t{\n\tSTREAM localStream;\n\tMESSAGE_DATA msgData;\n\tBYTE kekInfo[ 128 + 8 ], label[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tconst int algoIdInfoSize = \\\n\t\t\t\tsizeofContextAlgoID( iCryptContext, ALGOID_ENCODING_NONE );\n\tint kekInfoSize, labelSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_KEYSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\n\tif( cryptStatusError( algoIdInfoSize ) )\n\t\treturn( algoIdInfoSize  );\n\n\t/* Get the label */\n\tsetMessageData( &msgData, label, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlabelSize = msgData.length;\n\n\t/* Determine the size of the KEK info.  To save evaluating it twice in a\n\t   row and because it's short, we just write it to local buffers */\n\tsMemOpen( &localStream, kekInfo, 128 );\n\twriteSequence( &localStream, sizeofOID( OID_PWRIKEK ) + algoIdInfoSize );\n\twriteOID( &localStream, OID_PWRIKEK );\n\tstatus = writeContextCryptAlgoID( &localStream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\tkekInfoSize = stell( &localStream );\n\tsMemDisconnect( &localStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the algorithm identifiers and encrypted key */\n\twriteConstructed( stream, sizeofShortInteger( KEK_VERSION ) + \\\n\t\t\t\t\t  sizeofShortObject( \\\n\t\t\t\t\t\t\tsizeofShortObject( labelSize ) ) + \\\n\t\t\t\t\t  kekInfoSize + sizeofShortObject( encryptedKeyLength ),\n\t\t\t\t\t  CTAG_RI_KEKRI );\n\twriteShortInteger( stream, KEK_VERSION, DEFAULT_TAG );\n\twriteSequence( stream, sizeofShortObject( labelSize ) );\n\twriteOctetString( stream, label, labelSize, DEFAULT_TAG );\n\tswrite( stream, kekInfo, kekInfoSize );\n\treturn( writeOctetString( stream, encryptedKey, encryptedKeyLength,\n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n#endif /* 0 */\n\n/* Read/write cryptlib KEK data:\n\n\t[3] SEQUENCE {\n\t\tversion\t\t\t\t\t\tINTEGER (0),\n\t\tkeyDerivationAlgorithm\t[0]\tAlgorithmIdentifier OPTIONAL,\n\t\tkeyEncryptionAlgorithm\t\tAlgorithmIdentifier,\n\t\tencryptedKey\t\t\t\tOCTET STRING\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCryptlibKek( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT QUERY_INFO *queryInfo )\n\t{\n\tQUERY_INFO keyDerivationQueryInfo DUMMY_INIT_STRUCT;\n\tconst int startPos = stell( stream );\n\tBOOLEAN hasDerivationInfo = FALSE;\n\tlong value;\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* If it's a CMS KEK, read it as such */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == CTAG_RI_KEKRI )\n\t\treturn( readCmsKek( stream, queryInfo ) );\n\n\t/* Read the header */\n\treadConstructed( stream, NULL, CTAG_RI_PWRI );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != PWRI_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the optional KEK derivation info and KEK algorithm info */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == MAKE_CTAG( CTAG_KK_DA ) )\n\t\t{\n\t\tstatus = readKeyDerivationInfo( stream, &keyDerivationQueryInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thasDerivationInfo = TRUE;\n\t\t}\n\treadSequence( stream, NULL );\n\tstatus = readFixedOID( stream, OID_PWRIKEK, sizeofOID( OID_PWRIKEK ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readContextAlgoID( stream, NULL, queryInfo, DEFAULT_TAG,\n\t\t\t\t\t\t\t\t\tALGOID_CLASS_CRYPT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there's key-derivation information available, copy it across to \n\t   the overall query information */\n\tif( hasDerivationInfo )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyDerivationQueryInfo.saltLength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( queryInfo->salt, keyDerivationQueryInfo.salt,\n\t\t\t\tkeyDerivationQueryInfo.saltLength );\n\t\tqueryInfo->saltLength = keyDerivationQueryInfo.saltLength;\n\t\tqueryInfo->keySetupIterations = \\\n\t\t\t\t\t\tkeyDerivationQueryInfo.keySetupIterations;\n\t\tqueryInfo->keySetupAlgo = keyDerivationQueryInfo.keySetupAlgo;\n\t\tqueryInfo->keySetupAlgoParam = \\\n\t\t\t\t\t\tkeyDerivationQueryInfo.keySetupAlgoParam;\n\t\tif( keyDerivationQueryInfo.keySize > 0 )\n\t\t\t{\n\t\t\t/* How to handle the optional keysize value from the key-\n\t\t\t   derivation information is a bit unclear, for example what \n\t\t\t   should we do if the encryption algorithm is AES-256 but the \n\t\t\t   keysize is 128 bits?  At the moment this problem is resolved\n\t\t\t   by the fact that nothing seems to use the keysize value */\n\t\t\tqueryInfo->keySize = keyDerivationQueryInfo.keySize;\n\t\t\t}\n\t\t}\n\n\t/* Finally, read the start of the encrypted key */\n\tstatus = readOctetStringHole( stream, &queryInfo->dataLength, \n\t\t\t\t\t\t\t\t  MIN_KEYSIZE, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining key data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeCryptlibKek( STREAM *stream, \n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) \\\n\t\t\t\t\t\t\t\tconst int encryptedKeyLength )\n\t{\n\tSTREAM localStream;\n\tBYTE derivationInfo[ CRYPT_MAX_HASHSIZE + 32 + 8 ], kekInfo[ 128 + 8 ];\n\tBOOLEAN hasKeyDerivationInfo = TRUE;\n\tconst int algoIdInfoSize = sizeofCryptContextAlgoID( iCryptContext );\n\tint derivationInfoSize = 0, kekInfoSize DUMMY_INIT, value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_KEYSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\n\tif( cryptStatusError( algoIdInfoSize ) )\n\t\treturn( algoIdInfoSize  );\n\n\t/* If it's a non-password-derived key and there's a label attached,\n\t   write it as a KEKRI with a PWRI algorithm identifier as the key\n\t   encryption algorithm */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( status == CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\thasKeyDerivationInfo = FALSE;\n\n#if 0\t/* 21/4/06 Disabled since it was never used */\n\t\tMESSAGE_DATA msgData;\n\n\t\t/* There's no password-derivation information present, see if there's\n\t\t   a label present */\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* There's a label present, write it as a PWRI within a KEKRI */\n\t\t\treturn( writeCmsKek( stream, iCryptContext, encryptedKey,\n\t\t\t\t\t\t\t\t encryptedKeyLength ) );\n\t\t\t}\n#endif /* 0 */\n\t\t}\n\n\t/* Determine the size of the derivation info and KEK info.  To save\n\t   evaluating it twice in a row and because it's short, we just write\n\t   it to local buffers */\n\tif( hasKeyDerivationInfo )\n\t\t{\n\t\tsMemOpen( &localStream, derivationInfo, CRYPT_MAX_HASHSIZE + 32 );\n\t\tstatus = writeKeyDerivationInfo( &localStream, iCryptContext );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tderivationInfoSize = stell( &localStream );\n\t\tsMemDisconnect( &localStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsMemOpen( &localStream, kekInfo, 128 );\n\twriteSequence( &localStream, sizeofOID( OID_PWRIKEK ) + algoIdInfoSize );\n\twriteOID( &localStream, OID_PWRIKEK );\n\tstatus = writeCryptContextAlgoID( &localStream, iCryptContext );\n\tif( cryptStatusOK( status ) )\n\t\tkekInfoSize = stell( &localStream );\n\tsMemDisconnect( &localStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the algorithm identifiers and encrypted key */\n\twriteConstructed( stream, sizeofShortInteger( PWRI_VERSION ) + \\\n\t\t\t\t\t\t\t  derivationInfoSize + kekInfoSize + \\\n\t\t\t\t\t\t\t  sizeofShortObject( encryptedKeyLength ),\n\t\t\t\t\t  CTAG_RI_PWRI );\n\twriteShortInteger( stream, PWRI_VERSION, DEFAULT_TAG );\n\tif( derivationInfoSize > 0 )\n\t\tswrite( stream, derivationInfo, derivationInfoSize );\n\tswrite( stream, kekInfo, kekInfoSize );\n\treturn( writeOctetString( stream, encryptedKey, encryptedKeyLength,\n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\n#ifdef USE_PGP\n\n/* Read/write PGP KEK data.\n\n\tSKE:\n\t\tbyte\tctb = PGP_PACKET_SKE\n\t\tbyte[]\tlength\n\t\tbyte\tversion = PGP_VERSION_OPENPGP\n\t\tbyte\tcryptAlgo\n\t\tbyte\tstringToKey specifier, 0, 1, or 3\n\t\tbyte[]\tstringToKey data\n\t\t\t\t0x00: byte\t\thashAlgo\n\t\t\t\t0x01: byte[8]\tsalt\n\t\t\t\t0x03: byte\t\titerations */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpKek( INOUT STREAM *stream, \n\t\t\t\t\t   OUT QUERY_INFO *queryInfo )\n\t{\n\tint dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Make sure that the packet header is in order and check the packet\n\t   version.  This is an OpenPGP-only packet */\n\tstatus = getPgpPacketInfo( stream, queryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sgetc( stream ) != PGP_VERSION_OPENPGP )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->version = PGP_VERSION_OPENPGP;\n\n\t/* Get the encryption algorithm.  In theory we should also store the\n\t   algorithm parater (indicating the key size), but that's communicated\n\t   explicitly by the size of the wrapped key */\n\tstatus = readPgpAlgo( stream, &queryInfo->cryptAlgo, &dummy,\n\t\t\t\t\t\t  PGP_ALGOCLASS_PWCRYPT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the S2K information */\n\treturn( readPgpS2K( stream, &queryInfo->keySetupAlgo, \n\t\t\t\t\t\t&queryInfo->keySetupAlgoParam, queryInfo->salt,  \n\t\t\t\t\t\tPGP_SALTSIZE, &queryInfo->saltLength,\n\t\t\t\t\t\t&queryInfo->keySetupIterations ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writePgpKek( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\tSTDC_UNUSED const BYTE *encryptedKey, \n\t\t\t\t\t\tSTDC_UNUSED const int encryptedKeyLength )\n\t{\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashAlgo DUMMY_INIT, kekCryptAlgo DUMMY_INIT;\t/* int vs.enum */\n\tint pgpKekCryptAlgo, pgpHashAlgo DUMMY_INIT, keySetupIterations;\n\tint count, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKey == NULL && encryptedKeyLength == 0 );\n\n\t/* Get the key derivation information */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &keySetupIterations, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ITERATIONS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_KEYING_ALGO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &kekCryptAlgo, CRYPT_CTXINFO_ALGO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, salt, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_SALT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptlibToPgpAlgo( kekCryptAlgo, &pgpKekCryptAlgo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptlibToPgpAlgo( hashAlgo, &pgpHashAlgo );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Calculate the PGP \"iteration count\" from the value used to derive\n\t   the key.  The \"iteration count\" is actually a count of how many bytes\n\t   are hashed, this is because the \"iterated hashing\" treats the salt +\n\t   password as an infinitely-repeated sequence of values and hashes the\n\t   resulting string for PGP-iteration-count bytes worth.  Instead of\n\t   being written directly the count is encoded in a complex manner that\n\t   saves a whole byte, so before we can write it we have to encode it\n\t   into the base + exponent form expected by PGP.  This has a default\n\t   base of 16 + the user-supplied base value, we can set this to zero\n\t   since the iteration count used by cryptlib is always a multiple of\n\t   16, the remainder is just log2 of what's left of the iteration\n\t   count */\n\tREQUIRES( keySetupIterations % 16 == 0 );\n\tkeySetupIterations /= 32;\t/* Remove fixed offset before log2 op.*/\n\tLOOP_MED( count = 0, keySetupIterations > 0,\n\t\t\t  ( count++, keySetupIterations >>= 1 ) );\n\tENSURES( LOOP_BOUND_OK );\n\tcount <<= 4;\t\t\t\t/* Exponent comes first */\n\tENSURES( count >= 0 && count <= 0xFF );\n\n\t/* Write the SKE packet */\n\tpgpWritePacketHeader( stream, PGP_PACKET_SKE, \n\t\t\t\t\t\t  PGP_VERSION_SIZE + PGP_ALGOID_SIZE + 1 + \\\n\t\t\t\t\t\t\tPGP_ALGOID_SIZE + PGP_SALTSIZE + 1 );\n\tsputc( stream, PGP_VERSION_OPENPGP );\n\tsputc( stream, pgpKekCryptAlgo );\n\tsputc( stream, 3 );\t\t/* S2K = salted, iterated hash */\n\tsputc( stream, pgpHashAlgo );\n\tswrite( stream, salt, PGP_SALTSIZE );\n\treturn( sputc( stream, count ) );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPublic-key Encrypted Key Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write CMS key transport data:\n\n\tSEQUENCE {\n\t\tversion\t\t\t\t\t\tINTEGER (0),\n\t\tissuerAndSerial\t\t\t\tIssuerAndSerialNumber,\n\t\talgorithm\t\t\t\t\tAlgorithmIdentifier,\n\t\tencryptedKey\t\t\t\tOCTET STRING\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCmsKeytrans( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tlong value;\n\tint length, encoding DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the header and version number */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != KEYTRANS_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the key ID and PKC algorithm information.  Since we're recording \n\t   the position of the issuerAndSerialNumber as a blob we have to use\n\t   getStreamObjectLength() to get the overall blob data size */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->iAndSStart = stell( stream ) - startPos;\n\tqueryInfo->iAndSLength = length;\n\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDex( stream, &queryInfo->cryptAlgo, NULL,\n\t\t\t\t\t\t\t   &encoding, ALGOID_CLASS_PKC );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( encoding != ALGOID_ENCODING_NONE )\n\t\tqueryInfo->cryptAlgoEncoding = encoding;\n\n\t/* Finally, read the start of the encrypted key */\n\tstatus = readOctetStringHole( stream, &queryInfo->dataLength, \n\t\t\t\t\t\t\t\t  MIN_PKCSIZE, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining key data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int writeCmsKeytrans( INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\tconst int encryptedKeyLength,\n\t\t\t\t\t\t\t IN_BUFFER( auxInfoLength ) const void *auxInfo, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int auxInfoLength )\n\t{\n\tconst int algoIdInfoSize = \\\n\t\t\t\tsizeofContextAlgoID( iCryptContext, ALGOID_ENCODING_PKCS1 );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\tassert( isReadPtrDynamic( auxInfo, auxInfoLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( auxInfoLength ) );\n\n\tif( cryptStatusError( algoIdInfoSize ) )\n\t\treturn( algoIdInfoSize  );\n\n\twriteSequence( stream, sizeofShortInteger( KEYTRANS_VERSION ) + \\\n\t\t\t\t\t\t   auxInfoLength + algoIdInfoSize + \\\n\t\t\t\t\t\t   sizeofShortObject( encryptedKeyLength ) );\n\twriteShortInteger( stream, KEYTRANS_VERSION, DEFAULT_TAG );\n\tswrite( stream, auxInfo, auxInfoLength );\n\twriteContextAlgoIDex( stream, iCryptContext, ALGOID_ENCODING_PKCS1 );\n\treturn( writeOctetString( stream, encryptedKey, encryptedKeyLength, \n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\n#ifdef USE_OAEP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int writeCmsKeytransOAEP( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int encryptedKeyLength,\n\t\t\t\t\t\t\t\t IN_BUFFER( auxInfoLength ) const void *auxInfo, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int auxInfoLength )\n\t{\n\tconst int algoIdInfoSize = \\\n\t\t\t\tsizeofContextAlgoID( iCryptContext, ALGOID_ENCODING_OAEP );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\tassert( isReadPtrDynamic( auxInfo, auxInfoLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( auxInfoLength ) );\n\n\tif( cryptStatusError( algoIdInfoSize ) )\n\t\treturn( algoIdInfoSize  );\n\n\twriteSequence( stream, sizeofShortInteger( KEYTRANS_VERSION ) + \\\n\t\t\t\t\t\t   auxInfoLength + algoIdInfoSize + \\\n\t\t\t\t\t\t   sizeofShortObject( encryptedKeyLength ) );\n\twriteShortInteger( stream, KEYTRANS_VERSION, DEFAULT_TAG );\n\tswrite( stream, auxInfo, auxInfoLength );\n\twriteContextAlgoIDex( stream, iCryptContext, ALGOID_ENCODING_OAEP );\n\treturn( writeOctetString( stream, encryptedKey, encryptedKeyLength, \n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n#endif /* USE_OAEP */\n\n/* Read/write cryptlib key transport data:\n\n\tSEQUENCE {\n\t\tversion\t\t\t\t\t\tINTEGER (2),\n\t\tkeyID\t\t\t\t\t[0]\tSubjectKeyIdentifier,\n\t\talgorithm\t\t\t\t\tAlgorithmIdentifier,\n\t\tencryptedKey\t\t\t\tOCTET STRING\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCryptlibKeytrans( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tlong value;\n\tint encoding DUMMY_INIT, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the header and version number */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != KEYTRANS_EX_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the key ID and PKC algorithm information */\n\tstatus = readOctetStringTag( stream, queryInfo->keyID, \n\t\t\t\t\t\t\t\t &queryInfo->keyIDlength, 8, \n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, CTAG_KT_SKI );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDex( stream, &queryInfo->cryptAlgo, NULL,\n\t\t\t\t\t\t\t   &encoding, ALGOID_CLASS_PKC );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( encoding != ALGOID_ENCODING_NONE )\n\t\tqueryInfo->cryptAlgoEncoding = encoding;\n\n\t/* Finally, read the start of the encrypted key */\n\tstatus = readOctetStringHole( stream, &queryInfo->dataLength, \n\t\t\t\t\t\t\t\t  MIN_KEYSIZE, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining key data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeCryptlibKeytrans( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t  IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int encryptedKeyLength,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const void *auxInfo,\n\t\t\t\t\t\t\t\t  STDC_UNUSED const int auxInfoLength )\n\t{\n\tBYTE keyID[ 128 + 8 ];\n\tconst int algoIdInfoSize = \\\n\t\t\t\tsizeofContextAlgoID( iCryptContext, ALGOID_ENCODING_PKCS1 );\n\tint keyIDlength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( auxInfo == NULL && auxInfoLength == 0 );\n\n\tif( cryptStatusError( algoIdInfoSize ) )\n\t\treturn( algoIdInfoSize  );\n\n\tstatus = getCmsKeyIdentifier( iCryptContext, keyID, 128, &keyIDlength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteSequence( stream, sizeofShortInteger( KEYTRANS_EX_VERSION ) + \\\n\t\t\t\t\t\t   sizeofShortObject( keyIDlength ) + algoIdInfoSize + \\\n\t\t\t\t\t\t   sizeofShortObject( encryptedKeyLength ) );\n\twriteShortInteger( stream, KEYTRANS_EX_VERSION, DEFAULT_TAG );\n\twriteOctetString( stream, keyID, keyIDlength, CTAG_KT_SKI );\n\twriteContextAlgoIDex( stream, iCryptContext, ALGOID_ENCODING_PKCS1 );\n\treturn( writeOctetString( stream, encryptedKey, encryptedKeyLength, \n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\n#ifdef USE_PGP\n\n/* Read/write PGP key transport data:\n\n\tPKE:\n\t\tbyte\tctb = PGP_PACKET_PKE\n\t\tbyte[]\tlength\n\t\tbyte\tversion = PGP_VERSION_PGP2 or 3 (= OpenPGP, not the expected PGP3)\n\t\tbyte[8]\tkeyID\n\t\tbyte\tPKC algo\n\t\tmpi(s)\tencrypted session key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpKeytrans( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Make sure that the packet header is in order and check the packet\n\t   version.  For this packet type a version number of 3 denotes OpenPGP\n\t   whereas for signatures it denotes PGP 2.x, so we translate the value\n\t   that we return to the caller */\n\tstatus = getPgpPacketInfo( stream, queryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tvalue = sgetc( stream );\n\tif( value != PGP_VERSION_2 && value != 3 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->version = ( value == PGP_VERSION_2 ) ? \\\n\t\t\t\t\t\t PGP_VERSION_2 : PGP_VERSION_OPENPGP;\n\n\t/* Get the PGP key ID and algorithm */\n\tstatus = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->keyIDlength = PGP_KEYID_SIZE;\n\tstatus = readPgpAlgo( stream, &queryInfo->cryptAlgo, NULL, \n\t\t\t\t\t\t  PGP_ALGOCLASS_PKCCRYPT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the RSA-encrypted key, recording the position and length of the \n\t   raw RSA-encrypted integer value.  We have to be careful how we handle \n\t   this because readInteger16Ubits() returns the canonicalised form of\n\t   the values (with leading zeroes truncated) so an stell() before the \n\t   read doesn't necessarily represent the start of the payload:\n\n\t\tstartPos\tdataStart\t\t stell()\n\t\t\t|\t\t\t|\t\t\t\t|\n\t\t\tv\t\t\tv <-- length -->v\n\t\t+---+-----------+---------------+\n\t\t|\t|\t\t\t|///////////////| Stream\n\t\t+---+-----------+---------------+ */\n\tif( queryInfo->cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\tstatus = readInteger16Ubits( stream, NULL, &queryInfo->dataLength,\n\t\t\t\t\t\t\t\t\t MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->dataStart = ( stell( stream ) - startPos ) - \\\n\t\t\t\t\t\t\t   queryInfo->dataLength;\n\t\t}\n\telse\n\t\t{\n\t\tconst int dataStartPos = stell( stream );\n\t\tint dummy;\n\n\t\tREQUIRES( dataStartPos >= 0 && dataStartPos < MAX_BUFFER_SIZE );\n\t\tREQUIRES( queryInfo->cryptAlgo == CRYPT_ALGO_ELGAMAL );\n\n\t\t/* Read the Elgamal-encrypted key, recording the position and\n\t\t   combined lengths of the MPI pair.  Again, we can't use the length\n\t\t   returned by readInteger16Ubits() to determine the overall size \n\t\t   but have to calculate it from the position in the stream */\n\t\tstatus = readInteger16Ubits( stream, NULL, &dummy, MIN_PKCSIZE,\n\t\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readInteger16Ubits( stream, NULL, &dummy, MIN_PKCSIZE,\n\t\t\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->dataStart = dataStartPos - startPos;\n\t\tqueryInfo->dataLength = stell( stream ) - dataStartPos;\n\t\t}\n\n\t/* Make sure that we've read the entire object.  This check is necessary \n\t   to detect corrupted length values, which can result in reading past \n\t   the end of the object */\n\tif( ( stell( stream ) - startPos ) != queryInfo->size )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writePgpKeytrans( INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\tconst int encryptedKeyLength,\n\t\t\t\t\t\t\t STDC_UNUSED const void *auxInfo, \n\t\t\t\t\t\t\t STDC_UNUSED const int auxInfoLength )\n\t{\n\tBYTE keyID[ PGP_KEYID_SIZE + 8 ];\n\tint algorithm, pgpAlgo, status;\t/* int vs.enum */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( encryptedKey, encryptedKeyLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( encryptedKeyLength >= MIN_PKCSIZE && \\\n\t\t\t  encryptedKeyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( auxInfo == NULL && auxInfoLength == 0 );\n\n\t/* Get the key information */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, keyID, PGP_KEYID_SIZE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptlibToPgpAlgo( algorithm, &pgpAlgo );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Write the PKE packet */\n\tpgpWritePacketHeader( stream, PGP_PACKET_PKE,\n\t\t\t\t\t\t  PGP_VERSION_SIZE + PGP_KEYID_SIZE + PGP_ALGOID_SIZE + \\\n\t\t\t\t\t\t  ( ( algorithm == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t\t\t\tsizeofInteger16U( encryptedKeyLength ) : \\\n\t\t\t\t\t\t\tencryptedKeyLength ) );\n\tsputc( stream, 3 );\t\t/* Version = 3 (OpenPGP) */\n\tswrite( stream, keyID, PGP_KEYID_SIZE );\n\tsputc( stream, pgpAlgo );\n\treturn( ( algorithm == CRYPT_ALGO_RSA ) ? \\\n\t\t\twriteInteger16Ubits( stream, encryptedKey, encryptedKeyLength ) :\n\t\t\tswrite( stream, encryptedKey, encryptedKeyLength ) );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tKey Exchange Read/Write Access Function\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst KEYEX_TYPE type;\n\tconst READKEYTRANS_FUNCTION function;\n\t} KEYTRANS_READ_INFO;\nstatic const KEYTRANS_READ_INFO keytransReadTable[] = {\n\t{ KEYEX_CMS, readCmsKeytrans },\n\t{ KEYEX_CRYPTLIB, readCryptlibKeytrans },\n#ifdef USE_PGP\n\t{ KEYEX_PGP, readPgpKeytrans },\n#endif /* USE_PGP */\n\t{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }\n\t};\n\ntypedef struct {\n\tconst KEYEX_TYPE type;\n\tconst WRITEKEYTRANS_FUNCTION function;\n\t} KEYTRANS_WRITE_INFO;\nstatic const KEYTRANS_WRITE_INFO keytransWriteTable[] = {\n\t{ KEYEX_CMS, writeCmsKeytrans },\n#ifdef USE_OAEP\n\t{ KEYEX_CMS_OAEP, writeCmsKeytransOAEP },\n#endif /* USE_OAEP */\n\t{ KEYEX_CRYPTLIB, writeCryptlibKeytrans },\n#ifdef USE_PGP\n\t{ KEYEX_PGP, writePgpKeytrans },\n#endif /* USE_PGP */\n\t{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }\n\t};\n\ntypedef struct {\n\tconst KEYEX_TYPE type;\n\tconst READKEK_FUNCTION function;\n\t} KEK_READ_INFO;\nstatic const KEK_READ_INFO kekReadTable[] = {\n\t{ KEYEX_CMS, readCryptlibKek },\n\t{ KEYEX_CRYPTLIB, readCryptlibKek },\n#ifdef USE_PGP\n\t{ KEYEX_PGP, readPgpKek },\n#endif /* USE_PGP */\n\t{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }\n\t};\n\ntypedef struct {\n\tconst KEYEX_TYPE type;\n\tconst WRITEKEK_FUNCTION function;\n\t} KEK_WRITE_INFO;\nstatic const KEK_WRITE_INFO kekWriteTable[] = {\n\t{ KEYEX_CMS, writeCryptlibKek },\n\t{ KEYEX_CRYPTLIB, writeCryptlibKek },\n#ifdef USE_PGP\n\t{ KEYEX_PGP, writePgpKek },\n#endif /* USE_PGP */\n\t{ KEYEX_NONE, NULL }, { KEYEX_NONE, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nREADKEYTRANS_FUNCTION getReadKeytransFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( keyexType, KEYEX ) );\n\n\tLOOP_SMALL( i = 0, \n\t\t\t\tkeytransReadTable[ i ].type != KEYEX_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( keytransReadTable, \\\n\t\t\t\t\t\t\t\t\t\t\tKEYTRANS_READ_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( keytransReadTable[ i ].type == keyexType )\n\t\t\treturn( keytransReadTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( keytransReadTable, KEYTRANS_READ_INFO ) );\n\n\treturn( NULL );\n\t}\nCHECK_RETVAL_PTR \\\nWRITEKEYTRANS_FUNCTION getWriteKeytransFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( keyexType, KEYEX ) );\n\n\tLOOP_SMALL( i = 0, \n\t\t\t\tkeytransWriteTable[ i ].type != KEYEX_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( keytransWriteTable, \\\n\t\t\t\t\t\t\t\t\t\t\tKEYTRANS_WRITE_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tif( keytransWriteTable[ i ].type == keyexType )\n\t\t\treturn( keytransWriteTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( keytransWriteTable, KEYTRANS_WRITE_INFO ) );\n\n\treturn( NULL );\n\t}\nCHECK_RETVAL_PTR \\\nREADKEK_FUNCTION getReadKekFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( keyexType, KEYEX ) );\n\n\tLOOP_SMALL( i = 0, \n\t\t\t\tkekReadTable[ i ].type != KEYEX_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( kekReadTable, \\\n\t\t\t\t\t\t\t\t\t\t\tKEK_READ_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( kekReadTable[ i ].type == keyexType )\n\t\t\treturn( kekReadTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( kekReadTable, KEK_READ_INFO ) );\n\t\t\n\treturn( NULL );\n\t}\nCHECK_RETVAL_PTR \\\nWRITEKEK_FUNCTION getWriteKekFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( keyexType, KEYEX ) );\n\n\tLOOP_SMALL( i = 0, \n\t\t\t\tkekWriteTable[ i ].type != KEYEX_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( kekWriteTable, \\\n\t\t\t\t\t\t\t\t\t\t\tKEK_WRITE_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tif( kekWriteTable[ i ].type == keyexType )\n\t\t\treturn( kekWriteTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( kekWriteTable, KEK_WRITE_INFO ) );\n\n\treturn( NULL );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/mech.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  Signature/Keyex Mechanism Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _MECHANISM_DEFINED\n\n#define _MECHANISM_DEFINED\n\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tASN.1 Constants and Macros\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMS version numbers for various objects.  They're monotonically increasing\n   because it was thought that this was enough to distinguish the record\n   types (see the note about CMS misdesign above).  This was eventually fixed\n   but the odd version numbers remain, except for PWRI which was done right */\n\nenum { KEYTRANS_VERSION, SIGNATURE_VERSION, KEYTRANS_EX_VERSION,\n\t   SIGNATURE_EX_VERSION, KEK_VERSION, PWRI_VERSION = 0 };\n\n/* Context-specific tags for the RecipientInfo record.  KeyTrans has no tag\n   (actually it has an implied 0 tag because of CMS misdesign, so the other\n   tags start at 1).  To allow for addition of new RI types we permit (but\n   ignore) objects tagged up to CTAG_RI_MAX */\n\nenum { CTAG_RI_KEYAGREE = 1, CTAG_RI_KEKRI, CTAG_RI_PWRI, CTAG_RI_MAX = 9 };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMechanism Function Prototypes\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The data formats for key exchange/transport and signature types.  These\n   are an extension of the externally-visible cryptlib formats and are needed\n   for things like X.509 signatures and various secure session protocols\n   that wrap stuff other than straight keys up using a KEK.  Note the non-\n   orthogonal handling of reading/writing CMS signatures, this is needed\n   because creating a CMS signature involves adding assorted additional data\n   like iAndS and signed attributes that present too much information to\n   pass into a basic writeSignature() call */\n\ntypedef enum {\n\tKEYEX_NONE,\t\t\t/* No recipient type */\n\tKEYEX_CMS,\t\t\t/* iAndS + algoID + OCTET STRING */\n\tKEYEX_CMS_OAEP,\t\t/* As CMS but using OAEP not PKCS #1 */\n\tKEYEX_CRYPTLIB,\t\t/* keyID + algoID + OCTET STRING */\n\tKEYEX_PGP,\t\t\t/* PGP keyID + MPI */\n\tKEYEX_LAST\t\t\t/* Last possible recipient type */\n\t} KEYEX_TYPE;\n\ntypedef enum {\n\tSIGNATURE_NONE,\t\t/* No signature type */\n\tSIGNATURE_RAW,\t\t/* BIT STRING */\n\tSIGNATURE_X509,\t\t/* algoID + BIT STRING */\n\tSIGNATURE_CMS,\t\t/* sigAlgoID + OCTET STRING (write) */\n\t\t\t\t\t\t/* iAndS + hAlgoID + sAlgoID + OCTET STRING (read) */\n\tSIGNATURE_CRYPTLIB,\t/* keyID + hashAlgoID + sigAlgoID + OCTET STRING */\n\tSIGNATURE_PGP,\t\t/* PGP MPIs */\n\tSIGNATURE_SSH,\t\t/* SSHv2 sig.record */\n\tSIGNATURE_SSL,\t\t/* Raw signature data (no encapsulation) with dual hash */\n\tSIGNATURE_TLS12,\t/* As SSL but with PKCS #1 format */\n\tSIGNATURE_LAST\t\t/* Last possible signature type */\n\t} SIGNATURE_TYPE;\n\n/* Signature read/write methods for the different format types.  Specifying\n   input ranges gets a bit complicated because the functions are polymorphic \n   so we have to provide the lowest common denominator of all functions */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *READSIG_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   OUT QUERY_INFO *queryInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\n\t\tint ( *WRITESIG_FUNCTION )( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\tIN_HANDLE_OPT \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ALGO ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParam,\n\t\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ALGO ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( signatureLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst BYTE *signature,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 40 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int signatureLength );\n\nCHECK_RETVAL_PTR \\\nREADSIG_FUNCTION getReadSigFunction( IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE sigType );\nCHECK_RETVAL_PTR \\\nWRITESIG_FUNCTION getWriteSigFunction( IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE sigType );\n\n/* Key exchange read/write methods for the different format types.  Specifying\n   input ranges gets a bit complicated because the functions are polymorphic \n   so we have to provide the lowest common denominator of all functions */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *READKEYTRANS_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\tOUT QUERY_INFO *queryInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\n\t\tint ( *WRITEKEYTRANS_FUNCTION )( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int encryptedKeyLength,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER_OPT( auxInfoLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst void *auxInfo,\n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\t\tconst int auxInfoLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *READKEK_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t   OUT QUERY_INFO *queryInfo );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *WRITEKEK_FUNCTION )( STREAM *stream,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\t\tIN_BUFFER_OPT( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst BYTE *encryptedKey, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\tconst int encryptedKeyLength );\n\nCHECK_RETVAL_PTR \\\nREADKEYTRANS_FUNCTION getReadKeytransFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType );\nCHECK_RETVAL_PTR \\\nWRITEKEYTRANS_FUNCTION getWriteKeytransFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType );\nCHECK_RETVAL_PTR \\\nREADKEK_FUNCTION getReadKekFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType );\nCHECK_RETVAL_PTR \\\nWRITEKEK_FUNCTION getWriteKekFunction( IN_ENUM( KEYEX ) \\\n\t\t\t\t\t\t\t\t\t\tconst KEYEX_TYPE keyexType );\n\n/* Prototypes for keyex functions in keyex_int.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint exportConventionalKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t   *encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t\t   IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iExportContext,\n\t\t\t\t\t\t   IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint exportPublicKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, \\\n\t\t\t\t\t\t\t\t\t *encryptedKeyLength ) \\\n\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iExportContext,\n\t\t\t\t\t IN_BUFFER_OPT( auxInfoLength ) \\\n\t\t\t\t\t\tconst void *auxInfo, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int auxInfoLength,\n\t\t\t\t\t IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importConventionalKey( IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\t\t\tconst void *encryptedKey, \n\t\t\t\t\t\t   IN_DATALENGTH const int encryptedKeyLength,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t\t   IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importPublicKey( IN_BUFFER( encryptedKeyLength ) \\\n\t\t\t\t\t\tconst void *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH const int encryptedKeyLength,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iReturnedContext, \n\t\t\t\t\t IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType );\n\n/* Prototypes for signature functions in sign_cms.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignatureCMS( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *signatureLength,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT signContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\tconst BOOLEAN useDefaultAuthAttr,\n\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CERTIFICATE iAuthAttr,\n\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_SESSION iTspSession,\n\t\t\t\t\t\tIN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignatureCMS( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_DATALENGTH const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iExtraData,\n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iSigCheckKey );\n\n/* Prototypes for signature functions in sign_pgp.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignaturePGP( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *signatureLength, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\tIN_BUFFER_OPT( sigAttributeLength ) \\\n\t\t\t\t\t\t\tconst void *sigAttributes,\n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int sigAttributeLength,\n\t\t\t\t\t\tIN_RANGE( PGP_SIG_NONE, PGP_SIG_LAST - 1 ) \\\n\t\t\t\t\t\t\tconst int sigType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignaturePGP( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_DATALENGTH const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext );\n\n/* Prototypes for common low-level signature functions in sign_int.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignature( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t IN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *signatureLength, \n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iHashContext2,\n\t\t\t\t\t IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\tconst SIGNATURE_TYPE signatureType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\tIN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iHashContext2,\n\t\t\t\t\tIN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\tconst SIGNATURE_TYPE signatureType );\n\n/* Prototypes for functions in keyex_rw.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint getCmsKeyIdentifier( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t OUT_BUFFER( keyIDMaxLength, *keyIDlength ) \\\n\t\t\t\t\t\t\tBYTE *keyID, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 32 ) \\\n\t\t\t\t\t\t\tconst int keyIDMaxLength,\n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( keyIDMaxLength ) \\\n\t\t\t\t\t\t\tint *keyIDlength );\n\n/* Prototypes for functions in sign_rw.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPgpOnepassSigPacket( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT QUERY_INFO *queryInfo );\n\n/* Prototypes for functions in obj_qry.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getPgpPacketInfo( INOUT STREAM *stream, OUT QUERY_INFO *queryInfo );\n\n#endif /* _MECHANISM_DEFINED */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_cwrap.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Conventional Key Wrap Mechanism Routines\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2008\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"mech_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"mechs/mech_int.h\"\n#endif /* Compiler-specific includes */\n\n/* The size of the key block header, an 8-bit length followed by a 24-bit \n   check value */\n\n#define CMS_KEYBLOCK_HEADERSIZE\t\t4\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMS Wrap/Unwrap Mechanisms\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Determine how many padding bytes are required for a CMS conventional key \n   wrap */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getPadSize( IN_HANDLE const CRYPT_CONTEXT iExportContext,\n\t\t\t\t\t   IN_RANGE( MIN_KEYSIZE, CRYPT_MAX_KEYSIZE ) \\\n\t\t\t\t\t\tconst int payloadSize, \n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *padSize )\n\t{\n\tint blockSize, totalSize, status;\n\n\tassert( isWritePtr( padSize, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iExportContext ) );\n\tREQUIRES( payloadSize >= MIN_KEYSIZE && \\\n\t\t\t  payloadSize <= CRYPT_MAX_KEYSIZE );\n\n\t/* Clear return value */\n\t*padSize = 0;\n\n\tstatus = krnlSendMessage( iExportContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine the padding size, which is the amount of padding required to\n\t   bring the total data size up to a multiple of the block size with a\n\t   minimum size of two blocks.  Unlike PKCS #5 padding, the total may be \n\t   zero */\n\ttotalSize = roundUp( payloadSize, blockSize );\n\tif( totalSize < blockSize * 2 )\n\t\ttotalSize = blockSize * 2;\n\tENSURES( !( totalSize & ( blockSize - 1 ) ) );\n\t*padSize = totalSize - payloadSize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMS Wrap/Unwrap Mechanisms\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform CMS data wrapping */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportCMS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE *keyBlockPtr = ( BYTE * ) mechanismInfo->wrappedData;\n\tBYTE dataSample[ 16 + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint keySize, padSize, status = CRYPT_OK;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Clear the return value */\n\tif( mechanismInfo->wrappedData != NULL )\n\t\t{\n\t\tmemset( mechanismInfo->wrappedData, 0,\n\t\t\t\tmechanismInfo->wrappedDataLength );\n\t\t}\n\n\t/* Get the key payload details from the key contexts */\n\tstatus = krnlSendMessage( mechanismInfo->keyContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = getPadSize( mechanismInfo->wrapContext, \n\t\t\t\t\t\t CMS_KEYBLOCK_HEADERSIZE + keySize, &padSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( padSize >= 0 && padSize <= CRYPT_MAX_IVSIZE );\n\tCFI_CHECK_UPDATE( \"getPadSize\" );\n\n\t/* If this is just a length check, we're done */\n\tif( mechanismInfo->wrappedData == NULL )\n\t\t{\n\t\tmechanismInfo->wrappedDataLength = \\\n\t\t\t\t\t\t\tCMS_KEYBLOCK_HEADERSIZE + keySize + padSize;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tANALYSER_HINT( mechanismInfo->wrappedDataLength > ( 2 * 8 ) && \\\n\t\t\t\t   mechanismInfo->wrappedDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Make sure that the wrapped key data fits in the output */\n\tif( CMS_KEYBLOCK_HEADERSIZE + \\\n\t\t\t\t\tkeySize + padSize > mechanismInfo->wrappedDataLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Pad the payload out with a random nonce if required */\n\tif( padSize > 0 )\n\t\t{\n\t\tsetMessageData( &msgData, \n\t\t\t\t\t\tkeyBlockPtr + CMS_KEYBLOCK_HEADERSIZE + keySize, \n\t\t\t\t\t\tpadSize );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Format the key block:\n\n\t\t|<--- C_K_HDRSIZE + keySize --->|<- padSz ->|\n\t\t+-------+-----------+-----------+-----------+\n\t\t| length| chk.value\t|\tkey\t\t|  padding\t|\n\t\t+-------+-----------+-----------+-----------+\n\t\t|<-\t1 ->|<--- 3 --->|\n\t\t\n\t   then copy the payload in at the last possible moment and perform two \n\t   passes of encryption, retaining the IV from the first pass for the \n\t   second pass */\n\tkeyBlockPtr[ 0 ] = intToByte( keySize );\n\tstatus = extractKeyData( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t keyBlockPtr + CMS_KEYBLOCK_HEADERSIZE,\n\t\t\t\t\t\t\t keySize, \"keydata\", 7 );\n\tkeyBlockPtr[ 1 ] = intToByte( keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE ] ^ 0xFF );\n\tkeyBlockPtr[ 2 ] = intToByte( keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE + 1 ] ^ 0xFF );\n\tkeyBlockPtr[ 3 ] = intToByte( keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE + 2 ] ^ 0xFF );\n\tmemcpy( dataSample, keyBlockPtr, 16 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedData,\n\t\t\t\t\t\t\t\t  CMS_KEYBLOCK_HEADERSIZE + keySize + \\\n\t\t\t\t\t\t\t\t\tpadSize );\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT1\" );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedData,\n\t\t\t\t\t\t\t\t  CMS_KEYBLOCK_HEADERSIZE + keySize + \\\n\t\t\t\t\t\t\t\t\tpadSize );\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT2\" );\n\t\t}\n\tif( cryptStatusOK( status ) && !memcmp( dataSample, keyBlockPtr, 16 ) )\n\t\t{\n\t\t/* The data to wrap is unchanged, there's been a catastrophic \n\t\t   failure of the encryption.  We don't do a retIntError() at this\n\t\t   point because we want to at least continue and zeroise the data\n\t\t   first */\n\t\tassert( FALSE );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tzeroise( dataSample, 16 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->wrappedData,\n\t\t\t\t mechanismInfo->wrappedDataLength );\n\t\treturn( status );\n\t\t}\n\tmechanismInfo->wrappedDataLength = CMS_KEYBLOCK_HEADERSIZE + \\\n\t\t\t\t\t\t\t\t\t   keySize + padSize;\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"getPadSize\", \"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_ENCRYPT1\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_ENCRYPT2\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform CMS data unwrapping */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importCMS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE + 8 ];\n\tBYTE ivBuffer[ CRYPT_MAX_IVSIZE + 8 ];\n\tBYTE *dataEndPtr = buffer + mechanismInfo->wrappedDataLength;\n\tint blockSize, value, status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Make sure that the data is a multiple of the cipher block size and \n\t   contains at least two encrypted blocks */\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &blockSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( mechanismInfo->wrappedDataLength & ( blockSize - 1 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( mechanismInfo->wrappedDataLength < 2 * blockSize )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\tif( mechanismInfo->wrappedDataLength > CRYPT_MAX_KEYSIZE + blockSize )\n\t\t{\n\t\t/* This has already been checked in general via a kernel ACL but we \n\t\t   can perform a more specific check here because we now know the \n\t\t   encryption block size */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\tANALYSER_HINT( mechanismInfo->wrappedDataLength >= 8 && \\\n\t\t\t\t   mechanismInfo->wrappedDataLength < CRYPT_MAX_KEYSIZE + 16 );\n\n\t/* Save the current IV for the inner decryption */\n\tsetMessageData( &msgData, ivBuffer, CRYPT_MAX_IVSIZE );\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Decrypt the n'th block using the n-1'th ciphertext block as the new \n\t   IV.  Then decrypt the remainder of the ciphertext blocks using the \n\t   decrypted n'th ciphertext block as the IV.  Technically some of the \n\t   checks of the return value aren't necessary because the CBC-MAC that \n\t   we're performing at the end will detect any failure to set a \n\t   parameter but we perform them anyway just to be sure */\n\tREQUIRES( rangeCheck( mechanismInfo->wrappedDataLength, 1, \n\t\t\t\t\t\t  CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE ) );\n\tmemcpy( buffer, mechanismInfo->wrappedData,\n\t\t\tmechanismInfo->wrappedDataLength );\n\tsetMessageData( &msgData, dataEndPtr - ( 2 * blockSize ), blockSize );\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t\t  dataEndPtr - blockSize, blockSize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, dataEndPtr - blockSize, blockSize );\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, buffer,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedDataLength - blockSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( buffer, CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Decrypt the inner data using the original IV */\n\tsetMessageData( &msgData, ivBuffer, blockSize );\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, buffer,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( buffer, CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that everything is in order and load the decrypted keying \n\t   information into the session key context.  This uses a somewhat\n\t   odd checking mechanism in order to avoid timing attacks (although it's\n\t   not really certain what an attacker would gain by an ability to do \n\t   this).  The checks being performed are:\n\n\t\tif( buffer[ 0 ] < MIN_KEYSIZE || \\\n\t\t\tbuffer[ 0 ] > MAX_WORKING_KEYSIZE || \\\n\t\t\tbuffer[ 0 ] > mechanismInfo->wrappedDataLength - \\\n\t\t\t\t\t\t  CMS_KEYBLOCK_HEADERSIZE || \\\n\t\t\tbuffer[ 1 ] != ( buffer[ CMS_KEYBLOCK_HEADERSIZE ] ^ 0xFF ) || \\\n\t\t\tbuffer[ 2 ] != ( buffer[ CMS_KEYBLOCK_HEADERSIZE + 1 ] ^ 0xFF ) || \\\n\t\t\tbuffer[ 3 ] != ( buffer[ CMS_KEYBLOCK_HEADERSIZE + 2 ] ^ 0xFF ) )\n\t\t\terror; \n\n\t   If this check fails then it could be due to corruption of the wrapped\n\t   data but is far more likely to be because the incorrect unwrap key was\n\t   used, so we return a CRYPT_ERROR_WRONGKEY instead of a \n\t   CRYPT_ERROR_BADDATA */\n\tvalue = ( buffer[ 0 ] < MIN_KEYSIZE ) | \\\n\t\t\t( buffer[ 0 ] > MAX_WORKING_KEYSIZE ) | \\\n\t\t\t( buffer[ 0 ] > mechanismInfo->wrappedDataLength - \\\n\t\t\t\t\t\t\tCMS_KEYBLOCK_HEADERSIZE );\n\tvalue |= buffer[ 1 ] ^ ( buffer[ CMS_KEYBLOCK_HEADERSIZE ] ^ 0xFF );\n\tvalue |= buffer[ 2 ] ^ ( buffer[ CMS_KEYBLOCK_HEADERSIZE + 1 ] ^ 0xFF );\n\tvalue |= buffer[ 3 ] ^ ( buffer[ CMS_KEYBLOCK_HEADERSIZE + 2 ] ^ 0xFF );\n\tif( value != 0 )\n\t\t{\n\t\tzeroise( buffer, CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE );\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t}\n\n\t/* Load the recovered key into the session key context */\n\tsetMessageData( &msgData, buffer + CMS_KEYBLOCK_HEADERSIZE, buffer[ 0 ] );\n\tstatus = krnlSendMessage( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* If there was an error with the key value or size, convert the\n\t\t   return value into something more appropriate */\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tzeroise( buffer, CRYPT_MAX_KEYSIZE + CRYPT_MAX_IVSIZE );\n\n\treturn( status );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_drv.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Key Derivation Mechanism Routines\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1992-2009\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"mech_int.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"mechs/mech_int.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPRF Building Blocks\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* HMAC-based PRF used for PBKDF2 / PKCS #5v2 and TLS */\n\n#define HMAC_DATASIZE\t\t64\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 7, 8 ) ) \\\nstatic int prfInit( IN const HASH_FUNCTION hashFunction, \n\t\t\t\t\tIN const HASH_FUNCTION_ATOMIC hashFunctionAtomic,\n\t\t\t\t\tOUT TYPECAST( HASHINFO ) void *hashState, \n\t\t\t\t\tIN_LENGTH_HASH const int hashSize, \n\t\t\t\t\tOUT_BUFFER( processedKeyMaxLength, *processedKeyLength ) \\\n\t\t\t\t\t\tvoid *processedKey, \n\t\t\t\t\tIN_LENGTH_FIXED( HMAC_DATASIZE ) \\\n\t\t\t\t\t\tconst int processedKeyMaxLength,\n\t\t\t\t\tOUT_RANGE( 0, HMAC_DATASIZE ) int *processedKeyLength, \n\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyLength )\n\t{\n\tBYTE hashBuffer[ HMAC_DATASIZE + 8 ], *keyPtr = processedKey;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( hashState, sizeof( HASHINFO ) ) );\n\tassert( isWritePtrDynamic( processedKey, processedKeyMaxLength ) );\n\tassert( isWritePtr( processedKeyLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\n\tREQUIRES( hashFunction != NULL && hashFunctionAtomic != NULL );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( processedKeyMaxLength == HMAC_DATASIZE );\n\tREQUIRES( isShortIntegerRangeNZ( keyLength ) );\n\n\t/* Clear return values */\n\tmemset( processedKey, 0, min( 16, processedKeyMaxLength ) );\n\t*processedKeyLength = 0;\n\n\t/* If the key size is larger than the hash data size reduce it to the \n\t   hash size before processing it (yuck.  You're required to do this\n\t   though) */\n\tif( keyLength > HMAC_DATASIZE )\n\t\t{\n\t\t/* Hash the user key down to the hash size and use the hashed form of\n\t\t   the key */\n\t\thashFunctionAtomic( processedKey, processedKeyMaxLength, key, \n\t\t\t\t\t\t\tkeyLength );\n\t\t*processedKeyLength = hashSize;\n\t\t}\n\telse\n\t\t{\n\t\t/* Copy the key to internal storage.  Note that this has the \n\t\t   potential to leak a tiny amount of timing information about the\n\t\t   key length, but given the mass of operations that follow this is\n\t\t   unlikely to be significant */\n\t\tREQUIRES( rangeCheck( keyLength, 1, processedKeyMaxLength ) );\n\t\tmemcpy( processedKey, key, keyLength );\n\t\t*processedKeyLength = keyLength;\n\t\t}\n\n\t/* Perform the start of the inner hash using the zero-padded key XORed\n\t   with the ipad value.  This could be done slightly more efficiently, \n\t   but the following sequence of operations minimises timing channels \n\t   leaking the key length */\n\tREQUIRES( rangeCheck( *processedKeyLength, 1, HMAC_DATASIZE ) );\n\tmemcpy( hashBuffer, keyPtr, *processedKeyLength );\n\tif( *processedKeyLength < HMAC_DATASIZE )\n\t\t{\n\t\tmemset( hashBuffer + *processedKeyLength, 0, \n\t\t\t\tHMAC_DATASIZE - *processedKeyLength );\n\t\t}\n\tLOOP_EXT( i = 0, i < HMAC_DATASIZE, i++, HMAC_DATASIZE + 1 )\n\t\thashBuffer[ i ] ^= HMAC_IPAD;\n\tENSURES( LOOP_BOUND_OK );\n\thashFunction( hashState, NULL, 0, hashBuffer, HMAC_DATASIZE, \n\t\t\t\t  HASH_STATE_START );\n\tzeroise( hashBuffer, HMAC_DATASIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nstatic int prfEnd( IN const HASH_FUNCTION hashFunction, \n\t\t\t\t   INOUT TYPECAST( HASHINFO ) void *hashState,\n\t\t\t\t   IN_LENGTH_HASH const int hashSize, \n\t\t\t\t   OUT_BUFFER_FIXED( hashMaxSize ) void *hash, \n\t\t\t\t   IN_LENGTH_HASH const int hashMaxSize, \n\t\t\t\t   IN_BUFFER( processedKeyLength ) const void *processedKey, \n\t\t\t\t   IN_RANGE( 1, HMAC_DATASIZE ) const int processedKeyLength )\n\t{\n\tBYTE hashBuffer[ HMAC_DATASIZE + 8 ];\n\tBYTE digestBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( hashState, sizeof( HASHINFO ) ) );\n\tassert( isWritePtrDynamic( hash, hashMaxSize ) );\n\tassert( isReadPtrDynamic( processedKey, processedKeyLength ) );\n\n\tREQUIRES( hashFunction != NULL );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( hashMaxSize >= MIN_HASHSIZE && \\\n\t\t\t  hashMaxSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( processedKeyLength >= 1 && \\\n\t\t\t  processedKeyLength <= HMAC_DATASIZE );\n\n\t/* Complete the inner hash and extract the digest */\n\thashFunction( hashState, digestBuffer, CRYPT_MAX_HASHSIZE, NULL, 0, \n\t\t\t\t  HASH_STATE_END );\n\n\t/* Perform the outer hash using the zero-padded key XORed with the opad\n\t   value followed by the digest from the inner hash.  As with the init\n\t   function this could be done slightly more efficiently, but the \n\t   following sequence of operations minimises timing channels leaking \n\t   the key length */\n\tREQUIRES( rangeCheck( processedKeyLength, 1, HMAC_DATASIZE ) );\n\tmemcpy( hashBuffer, processedKey, processedKeyLength );\n\tif( processedKeyLength < HMAC_DATASIZE )\n\t\t{\n\t\tmemset( hashBuffer + processedKeyLength, 0, \n\t\t\t\tHMAC_DATASIZE - processedKeyLength );\n\t\t}\n\tLOOP_EXT( i = 0, i < HMAC_DATASIZE, i++, HMAC_DATASIZE + 1 )\n\t\thashBuffer[ i ] ^= HMAC_OPAD;\n\tENSURES( LOOP_BOUND_OK );\n\thashFunction( hashState, NULL, 0, hashBuffer, HMAC_DATASIZE, \n\t\t\t\t  HASH_STATE_START );\n\tzeroise( hashBuffer, HMAC_DATASIZE );\n\thashFunction( hashState, hash, hashMaxSize, digestBuffer, hashSize, \n\t\t\t\t  HASH_STATE_END );\n\tzeroise( digestBuffer, CRYPT_MAX_HASHSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKCS #5v2 Key Derivation \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Implement one round of the PKCS #5v2 PRF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 8 ) ) \\\nstatic int pbkdf2Hash( OUT_BUFFER_FIXED( outLength ) BYTE *out, \n\t\t\t\t\t   IN_RANGE( 1, CRYPT_MAX_HASHSIZE ) const int outLength, \n\t\t\t\t\t   IN const HASH_FUNCTION hashFunction, \n\t\t\t\t\t   INOUT TYPECAST( HASHINFO ) void *initialHashState,\n\t\t\t\t\t   IN_LENGTH_HASH const int hashSize, \n\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t   IN_RANGE( 1, HMAC_DATASIZE ) const int keyLength,\n\t\t\t\t\t   IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t\t   IN_RANGE( 4, 512 ) const int saltLength,\n\t\t\t\t\t   IN_INT const int iterations, \n\t\t\t\t\t   IN_RANGE( 1, 1000 ) const int blockCount )\n\t{\n\tHASHINFO hashInfo;\n\tBYTE block[ CRYPT_MAX_HASHSIZE + 8 ], countBuffer[ 4 + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( out, outLength ) );\n\tassert( isWritePtr( initialHashState, sizeof( HASHINFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( hashFunction != NULL );\n\tREQUIRES( outLength > 0 && outLength <= hashSize && \\\n\t\t\t  outLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( keyLength >= 1 && keyLength <= HMAC_DATASIZE );\n\tREQUIRES( saltLength >= 4 && saltLength <= 512 );\n\tREQUIRES( isIntegerRangeNZ( iterations ) );\n\tREQUIRES( blockCount > 0 && blockCount <= 1000 );\n\n\t/* Clear return value */\n\tmemset( out, 0, outLength );\n\n\t/* Set up the block counter buffer.  This will never have more than the\n\t   last few bits set (8 bits = 5100 bytes of key) so we only change the\n\t   last byte */\n\tmemset( countBuffer, 0, 4 );\n\tcountBuffer[ 3 ] = ( BYTE ) blockCount;\n\n\t/* Calculate HMAC( salt || counter ) */\n\tmemcpy( hashInfo, initialHashState, sizeof( HASHINFO ) );\n\thashFunction( hashInfo, NULL, 0, salt, saltLength, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, NULL, 0, countBuffer, 4, HASH_STATE_CONTINUE );\n\tstatus = prfEnd( hashFunction, hashInfo, hashSize, block, \n\t\t\t\t\t CRYPT_MAX_HASHSIZE, key, keyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\t\treturn( status );\n\t\t}\n\tmemcpy( out, block, outLength );\n\n\t/* Calculate HMAC( T1 ) ^ HMAC( T2 ) ^ ... HMAC( Tc ) */\n\tLOOP_MAX( i = 0, i < iterations - 1, i++ )\n\t\t{\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\t/* Generate the PRF output for the current iteration */\n\t\tmemcpy( hashInfo, initialHashState, sizeof( HASHINFO ) );\n\t\thashFunction( hashInfo, NULL, 0, block, hashSize, HASH_STATE_CONTINUE );\n\t\tstatus = prfEnd( hashFunction, hashInfo, hashSize, block, \n\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, key, keyLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\t\t\tzeroise( block, CRYPT_MAX_HASHSIZE );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* XOR the new PRF output into the existing PRF output */\n\t\tLOOP_EXT_ALT( j = 0, j < outLength, j++, CRYPT_MAX_HASHSIZE + 1 )\n\t\t\tout[ j ] ^= block[ j ];\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\tzeroise( block, CRYPT_MAX_HASHSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform PBKDF2 / PKCS #5v2 derivation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePBKDF2( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tCRYPT_ALGO_TYPE hashAlgo;\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO initialHashInfo;\n\tBYTE processedKey[ HMAC_DATASIZE + 8 ];\n\tBYTE *dataOutPtr = mechanismInfo->dataOut;\n\tstatic const MAP_TABLE mapTbl[] = {\n\t\t{ CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_SHA1 },\n\t\t{ CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_SHA2 },\n\t\t{ CRYPT_ALGO_HMAC_SHAng, CRYPT_ALGO_SHAng },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tint hashSize, keyIndex, processedKeyLength, blockCount = 1;\n\tint value, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\t/* Convert the HMAC algorithm into the equivalent hash algorithm for use \n\t   with the PRF */\n\tstatus = mapValue( mechanismInfo->hashAlgo, &value, mapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( mapTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashAlgo = value;\n\tif( !algoAvailable( hashAlgo ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Initialise the HMAC information with the user key.  Although the user\n\t   has specified the algorithm in terms of an HMAC we're synthesising it \n\t   from the underlying hash algorithm since this allows us to perform the\n\t   PRF setup once and reuse the initial value for any future hashing */\n\tgetHashAtomicParameters( hashAlgo, mechanismInfo->hashParam, \n\t\t\t\t\t\t\t &hashFunctionAtomic, &hashSize );\n\tgetHashParameters( hashAlgo, mechanismInfo->hashParam, &hashFunction, \n\t\t\t\t\t   NULL );\n\tstatus = prfInit( hashFunction, hashFunctionAtomic, initialHashInfo, \n\t\t\t\t\t  hashSize, processedKey, HMAC_DATASIZE, \n\t\t\t\t\t  &processedKeyLength, mechanismInfo->dataIn, \n\t\t\t\t\t  mechanismInfo->dataInLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Produce enough blocks of output to fill the key (nil sine magno \n\t   labore) */\n\tLOOP_MED( keyIndex = 0, keyIndex < mechanismInfo->dataOutLength,\n\t\t\t  ( keyIndex += hashSize, dataOutPtr += hashSize ) )\n\t\t{\n\t\tconst int noKeyBytes = \\\n\t\t\t( mechanismInfo->dataOutLength - keyIndex > hashSize ) ? \\\n\t\t\thashSize : mechanismInfo->dataOutLength - keyIndex;\n\n\t\tstatus = pbkdf2Hash( dataOutPtr, noKeyBytes, \n\t\t\t\t\t\t\t hashFunction, initialHashInfo, hashSize,\n\t\t\t\t\t\t\t processedKey, processedKeyLength,\n\t\t\t\t\t\t\t mechanismInfo->salt, mechanismInfo->saltLength,\n\t\t\t\t\t\t\t mechanismInfo->iterations, blockCount++ );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( initialHashInfo, sizeof( HASHINFO ) );\n\tzeroise( processedKey, HMAC_DATASIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->dataOut, mechanismInfo->dataOutLength );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Apply PBKDF2 / PKCS #5v2 as a pure (single-round) KDF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint kdfPBKDF2( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_KDF_INFO *mechanismInfo )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismDeriveInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE masterSecretBuffer[ CRYPT_MAX_KEYSIZE + 8 ];\n\tBYTE keyBuffer[ CRYPT_MAX_KEYSIZE + 8 ];\n\tint masterSecretSize, keySize DUMMY_INIT, status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Get the key payload details from the key contexts */\n\tstatus = krnlSendMessage( mechanismInfo->masterKeyContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &masterSecretSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->keyContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( masterSecretSize > 0 && \\\n\t\t\t masterSecretSize <= CRYPT_MAX_KEYSIZE );\n\n\t/* Extract the master secret value from the generic-secret context and \n\t   derive the key from it using PBKDF2 as the KDF */\n\tstatus = extractKeyData( mechanismInfo->masterKeyContext,\n\t\t\t\t\t\t\t masterSecretBuffer, CRYPT_MAX_KEYSIZE, \n\t\t\t\t\t\t\t \"keydata\", 7 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMechanismDeriveInfo( &mechanismDeriveInfo, keyBuffer, keySize,\n\t\t\t\t\t\t\tmasterSecretBuffer, masterSecretSize,\n\t\t\t\t\t\t\tmechanismInfo->hashAlgo, mechanismInfo->salt,\n\t\t\t\t\t\t\tmechanismInfo->saltLength, 1 );\n\tmechanismDeriveInfo.hashParam = mechanismInfo->hashParam;\n\tstatus = derivePBKDF2( NULL, &mechanismDeriveInfo );\n\tzeroise( masterSecretBuffer, CRYPT_MAX_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( keyBuffer, CRYPT_MAX_KEYSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the derived key into the context */\n\tsetMessageData( &msgData, keyBuffer, keySize );\n\tstatus = krnlSendMessage( mechanismInfo->keyContext, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\tzeroise( keyBuffer, CRYPT_MAX_KEYSIZE );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKCS #12 Key Derivation \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PKCS12\n\n/* The nominal block size for PKCS #12 derivation, based on the MD5/SHA-1 \n   input size of 512 bits */\n\n#define P12_BLOCKSIZE\t\t64\n\n/* The maximum size of the expanded diversifier, salt, and password (DSP),\n   one block for the expanded diversifier, one block for the expanded salt,\n   and up to three blocks for the password converted to Unicode with a\n   terminating \\x00 appended, which for a maximum password length of\n   CRYPT_MAX_TEXTSIZE can be ( 64 + 1 ) * 2, rounded up to a multiple of\n   P12_BLOCKSIZE */\n\n#define P12_DSPSIZE\t\t\t( P12_BLOCKSIZE + P12_BLOCKSIZE + \\\n\t\t\t\t\t\t\t  ( P12_BLOCKSIZE * 3 ) )\n\n/* Add two P12_BLOCKSIZE-byte blocks as 64-byte big-endian values:\n\n\tdest = (dest + src + 1) mod 2^P12_BLOCKSIZE */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int add64( INOUT_BUFFER_FIXED( destLen ) BYTE *dest,\n\t\t\t\t  IN_LENGTH_FIXED( P12_BLOCKSIZE ) const int destLen,\n\t\t\t\t  IN_BUFFER( srcLen ) const BYTE *src,\n\t\t\t\t  IN_LENGTH_FIXED( P12_BLOCKSIZE ) const int srcLen )\n\t{\n\tint destIndex, srcIndex, carry = 1, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destLen ) );\n\tassert( isReadPtrDynamic( src, srcLen ) );\n\n\tREQUIRES( destLen == P12_BLOCKSIZE );\n\tREQUIRES( srcLen == P12_BLOCKSIZE );\n\n\t/* dest = (dest + src + 1) mod 2^P12_BLOCKSIZE */\n\tLOOP_EXT( ( destIndex = P12_BLOCKSIZE - 1, srcIndex = P12_BLOCKSIZE - 1 ),\n\t\t\t  destIndex >= 0, ( destIndex--, srcIndex-- ), P12_BLOCKSIZE + 1 )\n\t\t{\n\t\tconst int value = dest[ destIndex ] + src[ srcIndex ] + carry;\n\t\tdest[ destIndex ] = intToByte( value & 0xFF );\n\t\tcarry = value >> 8;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Concantenate enough copies of the input data together to fill an output \n   buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int expandData( OUT_BUFFER_FIXED( destLen ) BYTE *dest, \n\t\t\t\t\t   IN_LENGTH_SHORT const int destLen, \n\t\t\t\t\t   IN_BUFFER( srcLen ) const BYTE *src, \n\t\t\t\t\t   IN_LENGTH_SHORT const int srcLen )\n\t{\n\tint index, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destLen ) );\n\tassert( isReadPtrDynamic( src, srcLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( destLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( srcLen ) );\n\n\t/* Clear return value */\n\tmemset( dest, 0, min( 16, destLen ) );\n\n\tLOOP_MED_INITCHECK( index = 0, index < destLen )\n\t\t{\n\t\tconst int bytesToCopy = min( srcLen, destLen - index );\n\n\t\tREQUIRES( boundsCheckZ( index, bytesToCopy, destLen ) );\n\t\tmemcpy( dest, src, bytesToCopy );\n\t\tdest += bytesToCopy;\n\t\tindex += bytesToCopy;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Build the diversifier/salt/password (DSP) string to use as the initial \n   input to the hash function:\n\n\t<---- 64 bytes ----><------- 64 bytes -------><-- Mult.64 bytes ->\n\t[ ID | ID | ID ... ][ salt | salt | salt ... ][ pw | pw | pw ... ] */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6 ) ) \\\nstatic int initDSP( OUT_BUFFER( dspMaxLen, *dspLen ) BYTE *dsp,\n\t\t\t\t\tIN_RANGE( P12_DSPSIZE, 512 ) const int dspMaxLen,\n\t\t\t\t\tOUT_RANGE( 0, 512 ) int *dspLen,\n\t\t\t\t\tIN_BUFFER( keyLength ) const BYTE *key,\n\t\t\t\t\tIN_LENGTH_TEXT const int keyLength,\n\t\t\t\t\tIN_BUFFER( saltLength ) const BYTE *salt,\n\t\t\t\t\tIN_RANGE( 1, P12_BLOCKSIZE ) const int saltLength,\n\t\t\t\t\tIN_RANGE( 1, 3 ) const int diversifier )\n\t{\n\tBYTE bmpString[ ( ( CRYPT_MAX_TEXTSIZE + 1 ) * 2 ) + 8 ];\n\tBYTE *dspPtr = dsp;\n\tint keyIndex, bmpIndex, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dsp, dspMaxLen ) );\n\tassert( isWritePtr( dspLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( dspMaxLen >= P12_DSPSIZE && dspMaxLen <= 512 );\n\tREQUIRES( diversifier >= 1 && diversifier <= 3 );\n\tREQUIRES( saltLength >= 1 && saltLength <= P12_BLOCKSIZE );\n\tREQUIRES( keyLength >= MIN_NAME_LENGTH && \\\n\t\t\t  keyLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Clear return values */\n\tmemset( dsp, 0, min( 16, dspMaxLen ) );\n\t*dspLen = 0;\n\n\t/* Set up the diversifier in the first P12_BLOCKSIZE bytes */\n\tLOOP_EXT( i = 0, i < P12_BLOCKSIZE, i++, P12_BLOCKSIZE + 1 )\n\t\tdsp[ i ] = intToByte( diversifier );\n\tENSURES( LOOP_BOUND_OK );\n\tdspPtr += P12_BLOCKSIZE;\n\n\t/* Set up the salt in the next P12_BLOCKSIZE bytes */\n\tstatus = expandData( dspPtr, P12_BLOCKSIZE, salt, saltLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdspPtr += P12_BLOCKSIZE;\n\n\t/* Convert the password to a null-terminated Unicode string, a Microsoft\n\t   bug that was made part of the standard */\n\tLOOP_EXT( ( keyIndex = 0, bmpIndex = 0 ), keyIndex < keyLength, \n\t\t\t  ( keyIndex++, bmpIndex += 2 ), CRYPT_MAX_TEXTSIZE + 1 )\n\t\t{\n\t\tbmpString[ bmpIndex ] = '\\0';\n\t\tbmpString[ bmpIndex + 1 ] = key[ keyIndex ];\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tbmpString[ bmpIndex++ ] = '\\0';\n\tbmpString[ bmpIndex++ ] = '\\0';\n\tENSURES( dspMaxLen >= P12_BLOCKSIZE + P12_BLOCKSIZE + \\\n\t\t\t\t\t\t  roundUp( bmpIndex, P12_BLOCKSIZE ) );\n\n\t/* Set up the Unicode password string as the remaining bytes */\n\tstatus = expandData( dspPtr, roundUp( bmpIndex, P12_BLOCKSIZE ),\n\t\t\t\t\t\t bmpString, bmpIndex );\n\tzeroise( bmpString, ( CRYPT_MAX_TEXTSIZE + 1 ) * 2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( dsp, dspMaxLen );\n\t\treturn( status );\n\t\t}\n\t*dspLen = P12_BLOCKSIZE + P12_BLOCKSIZE + \\\n\t\t\t  roundUp( bmpIndex, P12_BLOCKSIZE );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform PKCS #12 derivation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePKCS12( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE p12_DSP[ P12_DSPSIZE + 8 ];\n\tBYTE p12_Ai[ CRYPT_MAX_HASHSIZE + 8 ], p12_B[ P12_BLOCKSIZE + 8 ];\n\tBYTE *dataOutPtr = mechanismInfo->dataOut;\n\tconst BYTE *saltPtr = mechanismInfo->salt;\n\tint dspLen, hashSize, keyIndex, i, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\tgetHashAtomicParameters( mechanismInfo->hashAlgo, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\n\t/* Set up the diversifier/salt/password (DSP) string.  The first byte of \n\t   the PKCS #12 salt acts as a diversifier so we separate this out from \n\t   the rest of the salt data */\n\tstatus = initDSP( p12_DSP, P12_DSPSIZE, &dspLen, mechanismInfo->dataIn,\n\t\t\t\t\t  mechanismInfo->dataInLength, saltPtr + 1,\n\t\t\t\t\t  mechanismInfo->saltLength - 1, byteToInt( *saltPtr ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Produce enough blocks of output to fill the key */\n\tLOOP_MED( keyIndex = 0, keyIndex < mechanismInfo->dataOutLength, \n\t\t\t  keyIndex += hashSize )\n\t\t{\n\t\tconst int noKeyBytes = \\\n\t\t\t( mechanismInfo->dataOutLength - keyIndex > hashSize ) ? \\\n\t\t\thashSize : mechanismInfo->dataOutLength - keyIndex;\n\t\tint dspIndex, LOOP_ITERATOR_ALT;\n\n\t\t/* Hash the keying material the required number of times to obtain the\n\t\t   output value */\n\t\thashFunctionAtomic( p12_Ai, CRYPT_MAX_HASHSIZE, p12_DSP, dspLen );\n\t\tLOOP_MAX_ALT( i = 1, i < mechanismInfo->iterations, i++ )\n\t\t\t{\n\t\t\thashFunctionAtomic( p12_Ai, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\tp12_Ai, hashSize );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tREQUIRES( boundsCheckZ( keyIndex, noKeyBytes, \n\t\t\t\t\t\t\t    mechanismInfo->dataOutLength ) );\n\t\tmemcpy( dataOutPtr + keyIndex, p12_Ai, noKeyBytes );\n\n\t\t/* Update the input keying material for the next iteration by \n\t\t   adding the output value expanded to P12_BLOCKSIZE, to \n\t\t   P12_BLOCKSIZE-sized blocks of the salt/password portion of the \n\t\t   DSP string */\n\t\tstatus = expandData( p12_B, P12_BLOCKSIZE, p12_Ai, hashSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tLOOP_LARGE_ALT( dspIndex = P12_BLOCKSIZE, dspIndex < dspLen, \n\t\t\t\t\t\tdspIndex += P12_BLOCKSIZE )\n\t\t\t{\n\t\t\tstatus = add64( p12_DSP + dspIndex, P12_BLOCKSIZE,\n\t\t\t\t\t\t\tp12_B, P12_BLOCKSIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( p12_DSP, P12_DSPSIZE );\n\tzeroise( p12_Ai, CRYPT_MAX_HASHSIZE );\n\tzeroise( p12_B, P12_BLOCKSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->dataOut, mechanismInfo->dataOutLength );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PKCS12 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSSL/TLS Key Derivation \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSL\n\n/* Structure used to store TLS PRF state information */\n\ntypedef struct {\n\t/* The hash functions and hash info */\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tHASH_FUNCTION hashFunction;\n\tint hashSize;\n\n\t/* The initial hash state from prfInit() and the current hash state */\n\tHASHINFO initialHashInfo, hashInfo;\n\n\t/* The HMAC processed key and intermediate data value */\n\tBUFFER( HMAC_DATASIZE, processedKeyLength ) \\\n\tBYTE processedKey[ HMAC_DATASIZE + 8 ];\n\tBUFFER( HMAC_DATASIZE, hashSize ) \\\n\tBYTE hashA[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint processedKeyLength;\n\t} TLS_PRF_INFO;\n\n/* Perform SSL key derivation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveSSL( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tHASH_FUNCTION md5HashFunction, shaHashFunction;\n\tHASHINFO hashInfo;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ], counterData[ 16 + 8 ];\n\tBYTE *dataOutPtr = mechanismInfo->dataOut;\n\tint md5HashSize, shaHashSize, counter = 0, keyIndex;\n\tint LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\tgetHashParameters( CRYPT_ALGO_MD5, 0, &md5HashFunction, &md5HashSize );\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &shaHashFunction, &shaHashSize );\n\n\t/* Produce enough blocks of output to fill the key */\n\tLOOP_MED( keyIndex = 0, keyIndex < mechanismInfo->dataOutLength, \n\t\t\t  keyIndex += md5HashSize )\n\t\t{\n\t\tconst int noKeyBytes = \\\n\t\t\t( mechanismInfo->dataOutLength - keyIndex > md5HashSize ) ? \\\n\t\t\tmd5HashSize : mechanismInfo->dataOutLength - keyIndex;\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Set up the counter data */\n\t\tLOOP_EXT_ALT( i = 0, i <= counter, i++, 16 + 1 )\n\t\t\tcounterData[ i ] = intToByte( 'A' + counter );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tcounter++;\n\n\t\t/* Calculate SHA1( 'A'/'BB'/'CCC'/... || keyData || salt ) */\n\t\tshaHashFunction( hashInfo, NULL, 0, counterData, counter, \n\t\t\t\t\t\t HASH_STATE_START );\n\t\tshaHashFunction( hashInfo, NULL, 0, mechanismInfo->dataIn,\n\t\t\t\t\t\t mechanismInfo->dataInLength, HASH_STATE_CONTINUE );\n\t\tshaHashFunction( hashInfo, hash, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t mechanismInfo->salt, mechanismInfo->saltLength, \n\t\t\t\t\t\t HASH_STATE_END );\n\n\t\t/* Calculate MD5( keyData || SHA1-hash ) */\n\t\tmd5HashFunction( hashInfo, NULL, 0, mechanismInfo->dataIn,\n\t\t\t\t\t\t mechanismInfo->dataInLength, HASH_STATE_START );\n\t\tmd5HashFunction( hashInfo, hash, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\t hash, shaHashSize, HASH_STATE_END );\n\n\t\t/* Copy the result to the output */\n\t\tREQUIRES( boundsCheckZ( keyIndex, noKeyBytes, \n\t\t\t\t\t\t\t\tmechanismInfo->dataOutLength ) );\n\t\tmemcpy( dataOutPtr + keyIndex, hash, noKeyBytes );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\tzeroise( hash, CRYPT_MAX_HASHSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise the TLS PRF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int tlsPrfInit( INOUT TLS_PRF_INFO *prfInfo, \n\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t   IN_LENGTH_SHORT const int keyLength,\n\t\t\t\t\t   IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t\t   IN_LENGTH_SHORT const int saltLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( prfInfo, sizeof( TLS_PRF_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( keyLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( saltLength ) );\n\n\t/* Initialise the hash information with the keying info.  This is\n\t   reused for any future hashing since it's constant */\n\tstatus = prfInit( prfInfo->hashFunction, prfInfo->hashFunctionAtomic, \n\t\t\t\t\t  prfInfo->initialHashInfo, prfInfo->hashSize, \n\t\t\t\t\t  prfInfo->processedKey, HMAC_DATASIZE, \n\t\t\t\t\t  &prfInfo->processedKeyLength, key, keyLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Calculate A1 = HMAC( salt ) */\n\tmemcpy( prfInfo->hashInfo, prfInfo->initialHashInfo, sizeof( HASHINFO ) );\n\tprfInfo->hashFunction( prfInfo->hashInfo, NULL, 0, salt, saltLength, \n\t\t\t\t\t\t  HASH_STATE_CONTINUE );\n\treturn( prfEnd( prfInfo->hashFunction, prfInfo->hashInfo, \n\t\t\t\t\tprfInfo->hashSize, prfInfo->hashA,\n\t\t\t\t\tCRYPT_MAX_HASHSIZE, prfInfo->processedKey, \n\t\t\t\t\tprfInfo->processedKeyLength ) );\n\t}\n\n/* Implement one round of the TLS PRF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int tlsPrfHash( INOUT_BUFFER_FIXED( outLength ) BYTE *out, \n\t\t\t\t\t   IN_LENGTH_SHORT const int outLength, \n\t\t\t\t\t   INOUT TLS_PRF_INFO *prfInfo, \n\t\t\t\t\t   IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t\t   IN_LENGTH_SHORT const int saltLength )\n\t{\n\tHASHINFO hashInfo, AnHashInfo;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( out, outLength ) );\n\tassert( isWritePtr( prfInfo, sizeof( TLS_PRF_INFO ) ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( outLength > 0 && outLength <= prfInfo->hashSize && \\\n\t\t\t  outLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( saltLength >= 13 && saltLength <= 512 );\n\n\t/* The result of the hashing is XORd to the output so we don't clear the \n\t   return value like usual */\n\n\t/* Calculate HMAC( An || salt ) */\n\tmemcpy( hashInfo, prfInfo->initialHashInfo, sizeof( HASHINFO ) );\n\tprfInfo->hashFunction( hashInfo, NULL, 0, prfInfo->hashA, \n\t\t\t\t\t\t   prfInfo->hashSize, HASH_STATE_CONTINUE );\n\tmemcpy( AnHashInfo, hashInfo, sizeof( HASHINFO ) );\n\tprfInfo->hashFunction( hashInfo, NULL, 0, salt, saltLength, \n\t\t\t\t\t\t   HASH_STATE_CONTINUE );\n\tstatus = prfEnd( prfInfo->hashFunction, hashInfo, prfInfo->hashSize, \n\t\t\t\t\t hash, CRYPT_MAX_HASHSIZE, prfInfo->processedKey, \n\t\t\t\t\t prfInfo->processedKeyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( AnHashInfo, sizeof( HASHINFO ) );\n\t\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\t\tzeroise( hash, CRYPT_MAX_HASHSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Calculate An+1 = HMAC( An ) */\n\tmemcpy( hashInfo, AnHashInfo, sizeof( HASHINFO ) );\n\tstatus = prfEnd( prfInfo->hashFunction, hashInfo, prfInfo->hashSize, \n\t\t\t\t\t prfInfo->hashA, prfInfo->hashSize, \n\t\t\t\t\t prfInfo->processedKey, prfInfo->processedKeyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( AnHashInfo, sizeof( HASHINFO ) );\n\t\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\t\tzeroise( hash, CRYPT_MAX_HASHSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Copy the result to the output */\n\tLOOP_EXT( i = 0, i < outLength, i++, CRYPT_MAX_HASHSIZE + 1 )\n\t\tout[ i ] ^= hash[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\tzeroise( AnHashInfo, sizeof( HASHINFO ) );\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\tzeroise( hash, CRYPT_MAX_HASHSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform TLS key derivation.  This implements the function described as \n   'PRF()' in the TLS spec */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveTLS( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tTLS_PRF_INFO md5Info, shaInfo;\n\tBYTE *dataOutPtr = mechanismInfo->dataOut;\n\tconst void *s1, *s2;\n\tconst int dataOutLength = mechanismInfo->dataOutLength;\n\tconst int sLen = ( mechanismInfo->dataInLength + 1 ) / 2;\n\tint md5Index, shaIndex, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\tmemset( &md5Info, 0, sizeof( TLS_PRF_INFO ) );\n\tgetHashAtomicParameters( CRYPT_ALGO_MD5, 0, &md5Info.hashFunctionAtomic, \n\t\t\t\t\t\t\t &md5Info.hashSize );\n\tgetHashParameters( CRYPT_ALGO_MD5, 0, &md5Info.hashFunction, NULL );\n\tmemset( &shaInfo, 0, sizeof( TLS_PRF_INFO ) );\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &shaInfo.hashFunctionAtomic, \n\t\t\t\t\t\t\t &shaInfo.hashSize );\n\tgetHashParameters( CRYPT_ALGO_SHA1, 0, &shaInfo.hashFunction, NULL );\n\n\t/* Find the start of the two halves of the keying info used for the\n\t   HMACing.  The size of each half is given by ceil( dataInLength / 2 ) \n\t   so there's a one-byte overlap if the input is an odd number of bytes \n\t   long */\n\ts1 = mechanismInfo->dataIn;\n\ts2 = ( BYTE * ) mechanismInfo->dataIn + \\\n\t\t ( mechanismInfo->dataInLength - sLen );\n\n\t/* The two hash functions have different block sizes that would require\n\t   complex buffering to handle leftover bytes from SHA-1, a simpler\n\t   method is to zero the output data block and XOR in the values from\n\t   each hash mechanism using separate output location indices for MD5 and\n\t   SHA-1 */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\t/* Initialise the TLS PRF and calculate A1 = HMAC( salt ) */\n\tstatus = tlsPrfInit( &md5Info, s1, sLen, mechanismInfo->salt,\n\t\t\t\t\t\t mechanismInfo->saltLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = tlsPrfInit( &shaInfo, s2, sLen, mechanismInfo->salt,\n\t\t\t\t\t\t\t mechanismInfo->saltLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &md5Info, sizeof( TLS_PRF_INFO ) );\n\t\tzeroise( &shaInfo, sizeof( TLS_PRF_INFO ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Produce enough blocks of output to fill the key.  We use the MD5 hash\n\t   size as the loop increment since this produces the smaller output\n\t   block */\n\tLOOP_MED_INITCHECK( md5Index = shaIndex = 0, md5Index < dataOutLength )\n\t\t{\n\t\tconst int md5NoKeyBytes = min( dataOutLength - md5Index, \\\n\t\t\t\t\t\t\t\t\t   md5Info.hashSize );\n\t\tconst int shaNoKeyBytes = min( dataOutLength - shaIndex, \\\n\t\t\t\t\t\t\t\t\t   shaInfo.hashSize );\n\n\t\tstatus = tlsPrfHash( dataOutPtr + md5Index, md5NoKeyBytes, \n\t\t\t\t\t\t\t &md5Info, mechanismInfo->salt, \n\t\t\t\t\t\t\t mechanismInfo->saltLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tif( shaNoKeyBytes > 0 )\n\t\t\t{\n\t\t\t/* Since the SHA-1 counter advances faster than the MD5 one we\n\t\t\t   can end up with zero bytes left to process for SHA-1 when MD5 \n\t\t\t   is processing it's last block */\n\t\t\tstatus = tlsPrfHash( dataOutPtr + shaIndex, shaNoKeyBytes, \n\t\t\t\t\t\t\t\t &shaInfo, mechanismInfo->salt, \n\t\t\t\t\t\t\t\t mechanismInfo->saltLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tmd5Index += md5NoKeyBytes;\n\t\tshaIndex += shaNoKeyBytes;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( &md5Info, sizeof( TLS_PRF_INFO ) );\n\tzeroise( &shaInfo, sizeof( TLS_PRF_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->dataOut, mechanismInfo->dataOutLength );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform TLS 1.2 key derivation using a gratuitously incompatible PRF \n   invented for TLS 1.2 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveTLS12( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tTLS_PRF_INFO shaInfo;\n\tBYTE *dataOutPtr = mechanismInfo->dataOut;\n\tconst int dataOutLength = mechanismInfo->dataOutLength;\n\tint keyIndex, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\tmemset( &shaInfo, 0, sizeof( TLS_PRF_INFO ) );\n\tgetHashAtomicParameters( mechanismInfo->hashAlgo, \n\t\t\t\t\t\t\t mechanismInfo->hashParam,\n\t\t\t\t\t\t\t &shaInfo.hashFunctionAtomic, \n\t\t\t\t\t\t\t &shaInfo.hashSize );\n\tgetHashParameters( mechanismInfo->hashAlgo, mechanismInfo->hashParam,\n\t\t\t\t\t   &shaInfo.hashFunction, NULL );\n\n\t/* Initialise the TLS PRF and calculate A1 = HMAC( salt ) */\n\tstatus = tlsPrfInit( &shaInfo, mechanismInfo->dataIn, \n\t\t\t\t\t\t mechanismInfo->dataInLength, mechanismInfo->salt,\n\t\t\t\t\t\t mechanismInfo->saltLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &shaInfo, sizeof( TLS_PRF_INFO ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Produce enough blocks of output to fill the key */\n\tLOOP_MED( keyIndex = 0, keyIndex < dataOutLength, \n\t\t\t  keyIndex += shaInfo.hashSize )\n\t\t{\n\t\tconst int noKeyBytes = min( dataOutLength - keyIndex, \\\n\t\t\t\t\t\t\t\t\tshaInfo.hashSize );\n\n\t\tstatus = tlsPrfHash( dataOutPtr + keyIndex, noKeyBytes, &shaInfo, \n\t\t\t\t\t\t\t mechanismInfo->salt, mechanismInfo->saltLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( &shaInfo, sizeof( TLS_PRF_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->dataOut, mechanismInfo->dataOutLength );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Key Derivation \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\n/* Implement one round of the OpenPGP PRF */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4, 6, 8, 10 ) ) \\\nstatic int pgpPrfHash( OUT_BUFFER_FIXED( outLength ) BYTE *out, \n\t\t\t\t\t   IN_LENGTH_HASH const int outLength, \n\t\t\t\t\t   IN const HASH_FUNCTION hashFunction, \n\t\t\t\t\t   INOUT TYPECAST( HASHINFO ) void *hashInfo,\n\t\t\t\t\t   IN_LENGTH_HASH const int hashSize, \n\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 2 ) const int keyLength,\n\t\t\t\t\t   IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t\t   IN_LENGTH_FIXED( PGP_SALTSIZE ) const int saltLength,\n\t\t\t\t\t   INOUT_LENGTH_Z long *byteCount, \n\t\t\t\t\t   IN_RANGE( CRYPT_UNUSED, 1 ) const int preloadLength )\n\t{\n\tlong count = *byteCount;\n\n\tassert( isWritePtrDynamic( out, outLength ) );\n\tassert( isWritePtr( hashInfo, sizeof( HASHINFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\tassert( isWritePtr( byteCount, sizeof( int ) ) );\n\n\tREQUIRES( hashFunction != NULL );\n\tREQUIRES( outLength == hashSize );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( keyLength >= 2 && keyLength <= MAX_INTLENGTH_SHORT );\n\tREQUIRES( saltLength == PGP_SALTSIZE );\n\tREQUIRES( preloadLength == CRYPT_UNUSED || \\\n\t\t\t  ( preloadLength >= 0 && preloadLength <= 1 ) );\n\tREQUIRES( isIntegerRangeNZ( count ) );\n\n\t/* Clear return value */\n\tmemset( out, 0, outLength );\n\n\t/* If it's a subsequent round of hashing, preload the hash with zero \n\t   bytes.  If it's the first round (preloadLength == 0) it's handled\n\t   specially below */\n\tif( preloadLength > 0 )\n\t\t{\n\t\thashFunction( hashInfo, NULL, 0, ( const BYTE * ) \"\\x00\\x00\\x00\\x00\", \n\t\t\t\t\t  preloadLength, HASH_STATE_START );\n\t\t}\n\n\t/* Hash the next round of salt || password.  Since we're being asked to \n\t   stop once we've processed 'count' input bytes we implement an early-\n\t   out mechanism that exits if the length of the item being hashed is \n\t   sufficient to reach 'count' */\n\tif( count <= saltLength )\n\t\t{\n\t\thashFunction( hashInfo, out, outLength, salt, count, \n\t\t\t\t\t  HASH_STATE_END );\n\t\t*byteCount = 0;\n\t\t\n\t\treturn( CRYPT_OK );\n\t\t}\n\thashFunction( hashInfo, NULL, 0, salt, saltLength, \n\t\t\t\t  ( preloadLength == 0 ) ? HASH_STATE_START : \\\n\t\t\t\t\t\t\t\t\t\t   HASH_STATE_CONTINUE );\n\tcount -= saltLength;\n\tif( count <= keyLength )\n\t\t{\n\t\thashFunction( hashInfo, out, outLength, key, count, HASH_STATE_END );\n\t\t*byteCount = 0;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\thashFunction( hashInfo, NULL, 0, key, keyLength, HASH_STATE_CONTINUE );\n\tcount -= keyLength;\n\tENSURES( isIntegerRangeNZ( count ) );\n\n\t*byteCount = count;\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform OpenPGP S2K key derivation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint derivePGP( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tlong byteCount = ( long ) mechanismInfo->iterations << 6;\n\tlong secondByteCount = 0;\n\tint hashSize, i, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\tREQUIRES( mechanismInfo->iterations >= 0 && \\\n\t\t\t  mechanismInfo->iterations <= MAX_KEYSETUP_HASHSPECIFIER );\n\tREQUIRES( byteCount >= 0 && byteCount < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\t/* Set up the hash parameters */\n\tgetHashParameters( mechanismInfo->hashAlgo, 0, &hashFunction, \n\t\t\t\t\t   &hashSize );\n\tmemset( hashInfo, 0, sizeof( HASHINFO ) );\n\n\tREQUIRES( mechanismInfo->dataOutLength < 2 * hashSize );\n\n\t/* If it's a non-iterated hash or the count won't allow even a single\n\t   pass over the 8-byte salt and password, adjust it to make sure that \n\t   we run at least one full iteration */\n\tif( byteCount < PGP_SALTSIZE + mechanismInfo->dataInLength )\n\t\tbyteCount = PGP_SALTSIZE + mechanismInfo->dataInLength;\n\n\t/* If the hash output size is less than the required key size we run a \n\t   second round of hashing after the first one to provide the total \n\t   required amount of keying material */\n\tif( hashSize < mechanismInfo->dataOutLength )\n\t\tsecondByteCount = byteCount;\n\n\t/* Repeatedly hash the salt and password until we've met the byte count.  \n\t   In effect this hashes:\n\n\t\tsalt || password || salt || password || ...\n\n\t   until we've processed 'byteCount' bytes of data.\n\n\t   This processing is complicated by the ridiculous number of iterations\n\t   of processing specified by some versions of GPG (see the long comment\n\t   in misc/consts.h), so that we can no longer employ the standard\n\t   FAILSAFE_ITERATIONS_MAX as a failsafe value but have to use a \n\t   multiple of that.  There's no clean way to do this, the following\n\t   hardcodes an upper bound that'll have to be varied based on what\n\t   MAX_KEYSETUP_HASHSPECIFIER is set to */\n\t#define GPG_FAILSAFE_ITERATIONS_MAX\t\t( MAX_KEYSETUP_HASHSPECIFIER * ( 64 / 16 ) )\n\tLOOP_EXT( i = 0, byteCount > 0 && cryptStatusOK( status ), i++, \n\t\t\t  GPG_FAILSAFE_ITERATIONS_MAX )\n\t\t{\n\t\tstatus = pgpPrfHash( mechanismInfo->dataOut, \n\t\t\t\t\t\t\t hashSize, hashFunction, hashInfo, hashSize, \n\t\t\t\t\t\t\t mechanismInfo->dataIn,\n\t\t\t\t\t\t\t mechanismInfo->dataInLength,\n\t\t\t\t\t\t\t mechanismInfo->salt, \n\t\t\t\t\t\t\t mechanismInfo->saltLength, &byteCount, \n\t\t\t\t\t\t\t ( i <= 0 ) ? 0 : CRYPT_UNUSED );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) && secondByteCount > 0 )\n\t\t{\n\t\tLOOP_EXT( i = 0, secondByteCount > 0 && cryptStatusOK( status ), i++,\n\t\t\t\t  GPG_FAILSAFE_ITERATIONS_MAX )\n\t\t\t{\n\t\t\tstatus = pgpPrfHash( ( BYTE * ) mechanismInfo->dataOut + hashSize, \n\t\t\t\t\t\t\t\t hashSize, hashFunction, hashInfo, hashSize, \n\t\t\t\t\t\t\t\t mechanismInfo->dataIn, \n\t\t\t\t\t\t\t\t mechanismInfo->dataInLength,\n\t\t\t\t\t\t\t\t mechanismInfo->salt, \n\t\t\t\t\t\t\t\t mechanismInfo->saltLength, &secondByteCount, \n\t\t\t\t\t\t\t\t ( i <= 0 ) ? 1 : CRYPT_UNUSED );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->dataOut, mechanismInfo->dataOutLength );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP || USE_PGPKEYS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc Key Derivation \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CMP\n\n/* Perform CMP/Entrust key derivation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveCMP( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tint hashSize, iterations, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );\n\n\t/* Calculate SHA1( password || salt ) */\n\tgetHashAtomicParameters( mechanismInfo->hashAlgo, 0, \n\t\t\t\t\t\t\t &hashFunctionAtomic, &hashSize );\n\tgetHashParameters( mechanismInfo->hashAlgo, 0, &hashFunction, NULL );\n\thashFunction( hashInfo, NULL, 0, mechanismInfo->dataIn,\n\t\t\t\t  mechanismInfo->dataInLength, HASH_STATE_START );\n\thashFunction( hashInfo, mechanismInfo->dataOut, \n\t\t\t\t  mechanismInfo->dataOutLength, mechanismInfo->salt,\n\t\t\t\t  mechanismInfo->saltLength, HASH_STATE_END );\n\n\t/* Iterate the hashing the remaining number of times.  We start the \n\t   count at one since the first iteration has already been performed */\n\tLOOP_MAX( iterations = 1, iterations < mechanismInfo->iterations, \n\t\t\t  iterations++ )\n\t\t{\n\t\thashFunctionAtomic( mechanismInfo->dataOut, \n\t\t\t\t\t\t\tmechanismInfo->dataOutLength, \n\t\t\t\t\t\t\tmechanismInfo->dataOut, hashSize );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDerivation Self-test Functions \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test key derivation mechanisms.  The externally-defined \n   MECHANISM_FUNCTION_INFO.function uses 'void *mechanismInfo' for the \n   second parameter because it could be one of several types while here we \n   use the specific 'MECHANISM_DERIVE_INFO *mechanismInfo', this leads to\n   warnings from some compilers about assigning incompatible pointer types\n   so we explicitly cast the function type via the FUNCTION_CAST below */\n\n#define FUNCTION_CAST\t\tconst MECHANISM_FUNCTION\n\ntypedef struct {\n\tMECHANISM_FUNCTION_INFO mechanismFunctionInfo;\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\t} MECHANISM_TEST_INFO;\n\n#define MECHANISM_OUTPUT_SIZE\t\t32\n#define MECHANISM_INPUT_SIZE\t\t32\n#define MECHANISM_SALT_SIZE\t\t\t16\n\n#define MECHANISM_OUTPUT_SIZE_SSL\t48\n#define MECHANISM_INPUT_SIZE_SSL\t48\n#define MECHANISM_SALT_SIZE_SSL\t\t64\n\nstatic const BYTE inputValue[] = {\n\t/* More than a single hash block size for SHA-1 */\n\t0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, \n\t0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,\n\t0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, \n\t0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,\n\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, \n\t0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF\n\t};\nstatic const BYTE saltValue[] = {\n\t/* At least 64 bytes for SSL/TLS PRF */\n\t0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, \n\t0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,\n\t0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F, \n\t0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,\n\t0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, \n\t0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,\n\t0x80, 0x91, 0xA2, 0xB3, 0xC4, 0xD5, 0xE6, 0xF7, \n\t0x08, 0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F\n\t};\n#ifdef USE_PKCS12\nstatic const BYTE pkcs12saltValue[] = {\n\t/* PKCS #12 has a single-byte diversifier at the start of the salt */\n\t0x01,\n\t0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, \n\t0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF\n\t};\n#endif /* USE_PKCS12 */\n\nstatic const MECHANISM_TEST_INFO deriveMechanismTestInfo[] = {\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PBKDF2, ( FUNCTION_CAST ) derivePBKDF2 },\n\t  { MKDATA( \"\\x73\\xF7\\x8A\\xBE\\x3C\\x9C\\x65\\x80\\x97\\x60\\x56\\xDE\\x04\\x2A\\x0C\\x97\"\n\t\t\t\t\"\\x99\\xF5\\x06\\x0F\\x43\\x06\\xA5\\xD0\\x74\\xC9\\xD5\\xC5\\xA5\\x05\\xB5\\x7F\" ), MECHANISM_OUTPUT_SIZE,\n\t\tinputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_HMAC_SHA1, 0,\n\t\tsaltValue, MECHANISM_SALT_SIZE, 10 } },\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( FUNCTION_CAST ) derivePGP },\n\t  { MKDATA( \"\\x4A\\x4B\\x90\\x09\\x27\\xF8\\xD0\\x93\\x56\\x16\\xEA\\xC1\\x45\\xCD\\xEE\\x05\"\n\t\t\t\t\"\\x67\\xE1\\x09\\x38\\x66\\xEB\\xB2\\xB2\\xB9\\x1F\\xD3\\xF7\\x48\\x2B\\xDC\\xCA\" ), MECHANISM_OUTPUT_SIZE,\n\t\tinputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1, 0,\n\t\tsaltValue, 8, 10 } },\n#endif /* USE_PGP || USE_PGPKEYS */\n#ifdef USE_SSL\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( FUNCTION_CAST ) deriveSSL },\n\t  { MKDATA( \"\\x87\\x46\\xDD\\x7D\\xAD\\x5F\\x48\\xB6\\xFC\\x8D\\x92\\xC4\\xDB\\x38\\x79\\x9A\"\n\t\t\t\t\"\\x3D\\xEA\\x22\\xFA\\xCD\\x7E\\x86\\xD5\\x23\\x6E\\x10\\x4C\\xBD\\x84\\x89\\xDF\"\n\t\t\t\t\"\\x1C\\x87\\x60\\xBF\\xFA\\x2B\\xCA\\xFE\\xFE\\x65\\xC7\\xA2\\xCF\\x04\\xFF\\xEB\" ), MECHANISM_OUTPUT_SIZE_SSL,\n\t\tinputValue, MECHANISM_INPUT_SIZE_SSL, ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, 0,\n\t\tsaltValue, MECHANISM_SALT_SIZE_SSL, 1 } },\t\t\t\t  /* Both MD5 and SHA1 */\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( FUNCTION_CAST ) deriveTLS },\n\t  { MKDATA( \"\\xD3\\xD4\\x2F\\xD6\\xE3\\x7D\\xC0\\x3C\\xA6\\x9F\\x92\\xDF\\x3E\\x40\\x0A\\x64\"\n\t\t\t\t\"\\x49\\xB4\\x0E\\xC4\\x14\\x04\\x2F\\xC8\\xDD\\x27\\xD5\\x1C\\x62\\xD2\\x2C\\x97\"\n\t\t\t\t\"\\x90\\xAE\\x08\\x4B\\xEE\\xF4\\x8D\\x22\\xF0\\x2A\\x1E\\x38\\x2D\\x31\\xCB\\x68\" ), MECHANISM_OUTPUT_SIZE_SSL,\n\t\tinputValue, MECHANISM_INPUT_SIZE_SSL, ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, 0,\n\t\tsaltValue, MECHANISM_SALT_SIZE_SSL, 1 } },\t\t\t\t  /* Both MD5 and SHA1 */\n#endif /* USE_SSL */\n#ifdef USE_CMP\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( FUNCTION_CAST ) deriveCMP },\n\t  { MKDATA( \"\\x80\\x0B\\x95\\x73\\x74\\x3B\\xC1\\x63\\x6B\\x28\\x2B\\x04\\x47\\xFD\\xF0\\x04\"\n\t\t\t\t\"\\x80\\x40\\x31\\xB1\" ), 20,\n\t\tinputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1, 0,\n\t\tsaltValue, MECHANISM_SALT_SIZE, 10 } },\n#endif /* USE_CMP */\n#ifdef USE_PKCS12\n  #if 0\t\t/* Additional check value from OpenSSL, this only uses 1 iteration */\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( FUNCTION_CAST ) derivePKCS12 },\n\t  { MKDATA( \"\\x8A\\xAA\\xE6\\x29\\x7B\\x6C\\xB0\\x46\\x42\\xAB\\x5B\\x07\\x78\\x51\\x28\\x4E\"\n\t\t\t\t\"\\xB7\\x12\\x8F\\x1A\\x2A\\x7F\\xBC\\xA3\" ), 24,\n\t\tMKDATA( \"smeg\" ), 4, CRYPT_ALGO_SHA1, 0,\n\t\tMKDATA( \"\\x01\\x0A\\x58\\xCF\\x64\\x53\\x0D\\x82\\x3F\" ), 1 + 8, 1 } },\n  #endif /* 0 */\n  #if 0\t\t/* Additional check value from OpenSSL, now with 1,000 iterations */\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( FUNCTION_CAST ) derivePKCS12 },\n\t  { MKDATA( \"\\xED\\x20\\x34\\xE3\\x63\\x28\\x83\\x0F\\xF0\\x9D\\xF1\\xE1\\xA0\\x7D\\xD3\\x57\"\n\t\t\t\t\"\\x18\\x5D\\xAC\\x0D\\x4F\\x9E\\xB3\\xD4\" ), 24,\n\t\tMKDATA( \"queeg\" ), 5, CRYPT_ALGO_SHA1, 0,\n\t\tMKDATA( \"\\x01\\x05\\xDE\\xC9\\x59\\xAC\\xFF\\x72\\xF7\" ), 1 + 8, 1000 } },\n  #endif /* 0 */\n\t{ { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( FUNCTION_CAST ) derivePKCS12 },\n\t  { MKDATA( \"\\x8B\\xFB\\x1D\\x77\\xFE\\x78\\xFF\\xE8\\xE9\\x69\\x76\\xE0\\xC5\\x0A\\xB6\\xD2\"\n\t\t\t\t\"\\x64\\xEC\\xA3\\x01\\xE9\\xD2\\xE0\\xC0\\xBC\\x60\\x3D\\x63\\xB2\\x4A\\xB2\\x63\" ), MECHANISM_OUTPUT_SIZE,\n\t\tinputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1, 0,\n\t\tpkcs12saltValue, 1 + MECHANISM_SALT_SIZE, 10 } },\n#endif /* USE_PKCS12 */\n\t{ { MESSAGE_NONE } }, { { MESSAGE_NONE } }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint deriveSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tBYTE buffer[ MECHANISM_OUTPUT_SIZE_SSL + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\tLOOP_LARGE( i = 0, \n\t\t\t\tderiveMechanismTestInfo[ i ].mechanismFunctionInfo.action != MESSAGE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( deriveMechanismTestInfo, \\\n\t\t\t\t\t\t\t\t\t\t\tMECHANISM_TEST_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tconst MECHANISM_FUNCTION_INFO *mechanismFunctionInfo = \\\n\t\t\t\t\t&deriveMechanismTestInfo[ i ].mechanismFunctionInfo;\n\t\tconst MECHANISM_TEST_INFO *mechanismTestInfoPtr = \\\n\t\t\t\t\t\t\t\t\t\t\t&deriveMechanismTestInfo[ i ];\n\t\tMECHANISM_DERIVE_INFO testMechanismInfo;\n\n\t\tmemcpy( &testMechanismInfo, &mechanismTestInfoPtr->mechanismInfo, \n\t\t\t\tsizeof( MECHANISM_DERIVE_INFO ) );\n\t\ttestMechanismInfo.dataOut = buffer;\n\t\tstatus = mechanismFunctionInfo->function( NULL, &testMechanismInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( memcmp( mechanismTestInfoPtr->mechanismInfo.dataOut, buffer, \n\t\t\t\t\tmechanismTestInfoPtr->mechanismInfo.dataOutLength ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"Mechanism self-test #%d for mechanism %d failed.\\n\", \n\t\t\t\t\t\t  i, mechanismFunctionInfo->mechanism ));\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( deriveMechanismTestInfo, \\\n\t\t\t\t\t\t\t\t\t MECHANISM_TEST_INFO ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Test KDF mechanisms */\n\nstatic const MECHANISM_TEST_INFO kdfMechanismTestInfo[] = {\n\t/* For the PBKDF2 test we call derivePBKDF2() rather than kdfPBKDF2() \n\t   since the latter works directly on encryption contexts, and in any \n\t   case is just a wrapper for derivePBKDF2() with the iteration count\n\t   hardcoded to 1 */\n\t{ { MESSAGE_DEV_KDF, MECHANISM_DERIVE_PBKDF2, ( FUNCTION_CAST ) derivePBKDF2 },\n\t  { \"\\x46\\x9D\\x41\\x22\\x45\\x10\\x28\\x4A\\xF9\\x80\\x62\\xCF\\xD6\\x4F\\x4D\\x66\"\n\t\t\"\\x4B\\x76\\xEC\\x7E\\xF0\\x48\\x7A\\xC3\\x9A\\xDB\\x2E\\xAE\\x56\\x94\\x65\\x01\", MECHANISM_OUTPUT_SIZE,\n\t\tinputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_HMAC_SHA2, 0,\n\t\tsaltValue, MECHANISM_SALT_SIZE, 1 } },\n\t{ { MESSAGE_NONE, MECHANISM_NONE, NULL } }, \n\t\t\t{ { MESSAGE_NONE, MECHANISM_NONE, NULL } }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint kdfSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_DERIVE_INFO *mechanismInfo )\n\t{\n\tBYTE buffer[ MECHANISM_OUTPUT_SIZE_SSL + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_DERIVE_INFO ) ) );\n\n\tLOOP_LARGE( i = 0, \n\t\t\t\tkdfMechanismTestInfo[ i ].mechanismFunctionInfo.mechanism != MECHANISM_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( kdfMechanismTestInfo, \\\n\t\t\t\t\t\t\t\t\t\t\tMECHANISM_TEST_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tconst MECHANISM_FUNCTION_INFO *mechanismFunctionInfo = \\\n\t\t\t\t\t&kdfMechanismTestInfo[ i ].mechanismFunctionInfo;\n\t\tconst MECHANISM_TEST_INFO *mechanismTestInfoPtr = \\\n\t\t\t\t\t\t\t\t\t\t\t&kdfMechanismTestInfo[ i ];\n\t\tMECHANISM_DERIVE_INFO testMechanismInfo;\n\n\t\tmemcpy( &testMechanismInfo, &mechanismTestInfoPtr->mechanismInfo, \n\t\t\t\tsizeof( MECHANISM_DERIVE_INFO ) );\n\t\ttestMechanismInfo.dataOut = buffer;\n\t\tstatus = mechanismFunctionInfo->function( NULL, &testMechanismInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( memcmp( mechanismTestInfoPtr->mechanismInfo.dataOut, buffer, \n\t\t\t\t\tmechanismTestInfoPtr->mechanismInfo.dataOutLength ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"Mechanism self-test #%d for mechanism %d failed.\\n\", \n\t\t\t\t\t\t  i, mechanismFunctionInfo->mechanism ));\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( kdfMechanismTestInfo, \\\n\t\t\t\t\t\t\t\t\t MECHANISM_TEST_INFO ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_int.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Internal Mechanism Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2008\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"mech_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"mechs/mech_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tPKC Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The length of the input data for PKCS #1 transformations is usually\n   determined by the key size but sometimes we can be passed data that has \n   been zero-padded (for example data coming from an ASN.1 INTEGER in which \n   the high bit is a sign bit) making it longer than the key size, or that \n   has leading zero byte(s) making it shorter than the key size.  The best \n   place to handle this is somewhat uncertain, it's an encoding issue so it \n   probably shouldn't be visible to the raw crypto routines but putting it \n   at the mechanism layer removes the algorithm-independence of that layer \n   and putting it at the mid-level sign/key-exchange routine layer both \n   removes the algorithm-independence and requires duplication of the code \n   for signatures and encryption.  The best place to put it seems to be at \n   the mechanism layer since an encoding issue really shouldn't be visible \n   at the crypto layer and because it would require duplicating the handling \n   every time a new PKC implementation is plugged in.\n\n   The intent of the size adjustment is to make the data size match the key\n   length.  If it's longer we try to strip leading zero bytes.  If it's \n   shorter we pad it with zero bytes to match the key size.  The result is\n   either the data adjusted to match the key size or CRYPT_ERROR_BADDATA if\n   this isn't possible */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint adjustPKCS1Data( OUT_BUFFER_FIXED( outDataMaxLen ) BYTE *outData, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( CRYPT_MAX_PKCSIZE ) \\\n\t\t\t\t\t\tconst int outDataMaxLen, \n\t\t\t\t\t IN_BUFFER( inLen ) const BYTE *inData, \n\t\t\t\t\t IN_LENGTH_SHORT const int inLen, \n\t\t\t\t\t IN_LENGTH_SHORT const int keySize )\n\t{\n\tint length = inLen, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( outData, outDataMaxLen ) );\n\tassert( isReadPtrDynamic( inData, inLen ) );\n\n\tREQUIRES( outDataMaxLen >= CRYPT_MAX_PKCSIZE && \\\n\t\t\t  outDataMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( inLen > 0 && inLen <= outDataMaxLen && \\\n\t\t\t  inLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( keySize >= MIN_PKCSIZE && keySize <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( outData != inData );\n\n\t/* Make sure that the result will fit in the output buffer.  This has \n\t   already been checked by the kernel mechanism ACL and by the \n\t   REQUIRES() predicate above but we make the check explicit here */\n\tif( keySize > outDataMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Find the start of the data payload.  If it's suspiciously short, \n\t   don't try and process it */\n\tLOOP_EXT( length = inLen, length >= MIN_PKCSIZE - 8 && *inData == 0,\n\t\t\t  ( length--, inData++ ), CRYPT_MAX_PKCSIZE );\n\tENSURES( LOOP_BOUND_OK );\n\tif( length < MIN_PKCSIZE - 8 || length > keySize )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If it's of the correct size, exit */\n\tif( length == keySize )\n\t\t{\n\t\tREQUIRES( rangeCheck( keySize, 1, outDataMaxLen ) );\n\t\tmemcpy( outData, inData, keySize );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( length < keySize );\n\n\t/* We've adjusted the size to account for zero-padding during encoding,\n\t   now we have to move the data into a fixed-length format to match the\n\t   key size.  To do this we copy the payload into the output buffer with\n\t   enough leading-zero bytes to bring the total size up to the key size */\n\tREQUIRES( boundsCheck( keySize - length, length, outDataMaxLen ) );\n\tmemset( outData, 0, keySize );\n\tmemcpy( outData + ( keySize - length ), inData, length );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get PKC algorithm parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getPkcAlgoParams( IN_HANDLE const CRYPT_CONTEXT pkcContext,\n\t\t\t\t\t  OUT_OPT_ALGO_Z CRYPT_ALGO_TYPE *pkcAlgo, \n\t\t\t\t\t  OUT_LENGTH_PKC_Z int *pkcKeySize )\n\t{\n\tassert( ( pkcAlgo == NULL ) || \\\n\t\t\tisWritePtr( pkcAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( pkcKeySize, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( pkcContext ) );\n\n\t/* Clear return values */\n\tif( pkcAlgo != NULL )\n\t\t*pkcAlgo = CRYPT_ALGO_NONE;\n\t*pkcKeySize = 0;\n\n\t/* Get various PKC algorithm parameters */\n\tif( pkcAlgo != NULL )\n\t\t{\n\t\tint algorithm, status;\n\n\t\tstatus = krnlSendMessage( pkcContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*pkcAlgo = algorithm;\t/* int vs.enum */\n\t\t}\n\treturn( krnlSendMessage( pkcContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t pkcKeySize, CRYPT_CTXINFO_KEYSIZE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tHash Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get hash algorithm parameters */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getHashAlgoParams( IN_HANDLE const CRYPT_CONTEXT hashContext,\n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo, \n\t\t\t\t\t   OUT_OPT_LENGTH_HASH_Z int *hashSize )\n\t{\n\tint status;\n\n\tassert( isWritePtr( hashAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( ( hashSize == NULL ) || \\\n\t\t\tisWritePtr( hashSize, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( hashContext ) );\n\n\t/* Clear return values */\n\t*hashAlgo = CRYPT_ALGO_NONE;\n\tif( hashSize != NULL )\n\t\t*hashSize = 0;\n\n\t/* Get various PKC algorithm parameters */\n\tif( hashSize != NULL )\n\t\t{\n\t\tstatus = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  hashSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\treturn( krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t hashAlgo, CRYPT_CTXINFO_ALGO ) );\n\t}\n\n"
  },
  {
    "path": "deps/cl345/mechs/mech_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Internal Mechanism Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _MECH_INT_DEFINED\n\n#define _MECH_INT_DEFINED\n\n#ifndef _DEVMECH_DEFINED\n  #if defined( INC_ALL )\n\t#include \"dev_mech.h\"\n  #else\n\t#include \"mechs/dev_mech.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _DEVMECH_DEFINED */\n\n/* Prototypes for functions in mech_int.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint adjustPKCS1Data( OUT_BUFFER_FIXED( outDataMaxLen ) BYTE *outData, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( CRYPT_MAX_PKCSIZE ) \\\n\t\t\t\t\t\tconst int outDataMaxLen, \n\t\t\t\t\t IN_BUFFER( inLen ) const BYTE *inData, \n\t\t\t\t\t IN_LENGTH_SHORT const int inLen, \n\t\t\t\t\t IN_LENGTH_SHORT const int keySize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getPkcAlgoParams( IN_HANDLE const CRYPT_CONTEXT pkcContext,\n\t\t\t\t\t  OUT_OPT_ALGO_Z CRYPT_ALGO_TYPE *pkcAlgo, \n\t\t\t\t\t  OUT_LENGTH_PKC_Z int *pkcKeySize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint getHashAlgoParams( IN_HANDLE const CRYPT_CONTEXT hashContext,\n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo, \n\t\t\t\t\t   OUT_OPT_LENGTH_HASH_Z int *hashSize );\n\n/* Prototypes for kernel-internal access functions.  This is a bit of an odd \n   place to have them but we need to have a prototype visible to both the\n   mechanism code where they're called and the kernel code */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint extractKeyData( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t\tOUT_BUFFER_FIXED( keyDataLen ) void *keyData, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int keyDataLen, \n\t\t\t\t\tIN_BUFFER( accessKeyLen ) const char *accessKey, \n\t\t\t\t\tIN_LENGTH_FIXED( 7 ) const int accessKeyLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint importPrivateKeyData( IN_BUFFER( privKeyDataLen ) const void *privKeyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int privKeyDataLen,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 6 ) ) \\\nint exportPrivateKeyData( OUT_BUFFER_OPT( privKeyDataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t  *privKeyDataLength ) \\\n\t\t\t\t\t\t\tvoid *privKeyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int privKeyDataMaxLength,\n\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *privKeyDataLength,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t  IN_ENUM( KEYFORMAT ) \\\n\t\t\t\t\t\t\tconst KEYFORMAT_TYPE formatType,\n\t\t\t\t\t\t  IN_BUFFER( accessKeyLen ) const char *accessKey, \n\t\t\t\t\t\t  IN_LENGTH_FIXED( 11 ) const int accessKeyLen );\n\n#endif /* _MECH_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_pkwrap.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib PKC Key Wrap Mechanism Routines\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"mech_int.h\"\n  #include \"pgp.h\"\n  #include \"asn1.h\"\n  #include \"misc_rw.h\"\n#else\n  #include \"crypt.h\"\n  #include \"mechs/mech_int.h\"\n  #include \"misc/pgp.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/misc_rw.h\"\n#endif /* Compiler-specific includes */\n\n/* Macros to implement constant-time operations */\n\n#define MSB_SHIFT_AMOUNT\t( ( sizeof( int ) * 8 ) - 1 )\n\n#define MAKE_BOOLEAN( x )\t( ( unsigned ) -( x ) >> MSB_SHIFT_AMOUNT )\n#define SELECT( bFlag, a, b ) \\\n\t\t\t\t\t\t\t( ~( ( bFlag ) - 1 ) & ( a ) ) | ( ( ( bFlag ) - 1 ) & ( b ) )\n\n/* Fixed-format maximum-length padding string that works for both PKCS #1 \n   and OAEP (meaning that the start looks valid but the padding check\n   will fail).  This is used as a dummy value to allow processing to \n   continue in case the decrypt operation fails, reducing the scope for \n   timing attacks */\n\n#if CRYPT_MAX_PKCSIZE > 512\n  #error Need to adjust dummy PKCS #1/OAEP data value to match CRYPT_MAX_PKCSIZE\n#endif /* CRYPT_MAX_PKCSIZE size check */\n\nstatic const BYTE fixedFormattedValue[] = {\n\t/* 128 bytes / 1024 bits */\n\t0x00, 0x02, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t/* 256 bytes / 2048 bits */\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n#if CRYPT_MAX_PKCSIZE > 256\n\t/* 384 bytes / 3072 bits */\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t/* 512 bytes / 4096 bits */\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,\n\t0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55\n#endif /* CRYPT_MAX_PKCSIZE > 256 */\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_PGP ) \n\n/* PGP checksums the PKCS #1 wrapped data even though this doesn't really\n   serve any purpose since any decryption error will corrupt the PKCS #1\n   padding.  The following routine calculates this checksum and either \n   appends it to the data or checks it against the stored value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int pgpGenerateChecksum( INOUT_BUFFER_FIXED( dataLength ) void *data, \n\t\t\t\t\t\t\t\tIN_RANGE( 1, CRYPT_MAX_PKCSIZE + UINT16_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int dataLength,\n\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int keyDataLength )\n\t{\n\tSTREAM stream;\n\tBYTE *dataPtr = data;\n\tint checksum = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength > 0 && \\\n\t\t\t  dataLength <= CRYPT_MAX_PKCSIZE + UINT16_SIZE );\n\tREQUIRES( keyDataLength == dataLength - UINT16_SIZE );\n\n\t/* Calculate the checksum for the MPI */\n\tLOOP_MAX( i = 0, i < keyDataLength, i++ )\n\t\tchecksum += byteToInt( dataPtr[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Append the checksum to the MPI data */\n\tsMemOpen( &stream, dataPtr + keyDataLength, dataLength - keyDataLength );\n\tstatus = writeUint16( &stream, checksum & 0xFFFF );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN pgpVerifyChecksum( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t  IN_RANGE( 1, CRYPT_MAX_PKCSIZE + UINT16_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int dataLength )\n\t{\n\tSTREAM stream;\n\tint checksum = 0, storedChecksum, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES_B( dataLength > UINT16_SIZE && \\\n\t\t\t\tdataLength <= CRYPT_MAX_PKCSIZE + UINT16_SIZE );\n\n\t/* Calculate the checksum for the MPI and compare it to the appended \n\t   checksum */\n\tsMemConnect( &stream, data, dataLength );\n\tLOOP_MAX( i = 0, i < dataLength - UINT16_SIZE, i++ )\n\t\t{\n\t\tconst int ch = sgetc( &stream );\n\t\tif( cryptStatusError( ch ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tchecksum += ch;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tstoredChecksum = readUint16( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( storedChecksum == checksum );\n\t}\n\n/* PGP includes the session key information alongside the encrypted key so\n   it's not really possible to import the key into a context in the\n   conventional sense.  Instead, the import code has to create the context\n   as part of the import process and return it to the caller.  This is ugly,\n   but less ugly than doing a raw import and handling the key directly in\n   the calling code */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int pgpExtractKey( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t\t  IN_LENGTH_PKC const int dataLength )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tstatic const int mode = CRYPT_MODE_CFB;\t/* int vs.enum */\n\tint algoParam, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength >= MIN_KEYSIZE && dataLength <= CRYPT_MAX_PKCSIZE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* Get the session key algorithm.  We delay checking the algorithm ID\n\t   return status until after the checksum calculation to reduce the \n\t   chance of being used as an oracle */\n\tstatus = pgpToCryptlibAlgo( data[ 0 ], PGP_ALGOCLASS_CRYPT, &cryptAlgo,\n\t\t\t\t\t\t\t\t&algoParam );\n\n\t/* Checksum the session key, skipping the algorithm ID at the start and\n\t   the checksum at the end.  This is actually superfluous since any\n\t   decryption error will be caught by corrupted PKCS #1 padding with\n\t   vastly higher probability than this simple checksum, but we do it\n\t   anyway because other PGP implementations do it too */\n\tif( !pgpVerifyChecksum( data + 1, dataLength - 1 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Make sure that the algorithm ID is valid.  We only perform the check \n\t   at this point because this returns a different error code than the \n\t   usual bad-data, we want to be absolutely sure that the problem really \n\t   is an unknown algorithm and not the result of scrambled decrypted \n\t   data */\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Create the context ready to have the key loaded into it */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( algoParam != 0 )\n\t\t{\n\t\t/* Some algorithms have variable-size keys, if this is one of them \n\t\t   then indicate the key size that we want to use */\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &algoParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode, CRYPT_CTXINFO_MODE );\n\tif( cryptStatusError( status ) )\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\telse\n\t\t*iCryptContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tLow-level Data Wrap/Unwrap Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wrap/unwrap data using a public/private-key context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int pkcWrapData( INOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t\tINOUT_BUFFER_FIXED( wrappedDataLength ) BYTE *wrappedData, \n\t\t\t\t\t\tIN_LENGTH_PKC const int wrappedDataLength,\n\t\t\t\t\t\tconst BOOLEAN usePgpWrap, \n\t\t\t\t\t\tconst BOOLEAN isDlpAlgo )\n\t{\n\tBYTE dataSample[ 16 + 8 ];\n\tconst void *samplePtr = wrappedData + ( wrappedDataLength / 2 );\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\tassert( isWritePtrDynamic( wrappedData, wrappedDataLength ) );\n\n\tREQUIRES( wrappedDataLength >= MIN_PKCSIZE && \\\n\t\t\t  wrappedDataLength <= CRYPT_MAX_PKCSIZE );\n#ifdef USE_OAEP\n\tREQUIRES( wrappedData[ 0 ] == 0x00 );\n#else\n\tREQUIRES( wrappedData[ 0 ] == 0x00 && \\\n\t\t\t  ( wrappedData[ 1 ] == 0x01 || wrappedData[ 1 ] == 0x02 ) );\n#endif /* USE_OAEP */\n\tREQUIRES( usePgpWrap == TRUE || usePgpWrap == FALSE );\n\tREQUIRES( isDlpAlgo == TRUE || isDlpAlgo == FALSE );\n\n\t/* Take a sample of the input for comparison with the output */\n\tmemcpy( dataSample, samplePtr, 16 );\n\n\tif( isDlpAlgo )\n\t\t{\n\t\tDLP_PARAMS dlpParams;\n\n\t\t/* For DLP-based PKC's the output length isn't the same as the key\n\t\t   size so we adjust the return length as required */\n\t\tsetDLPParams( &dlpParams, wrappedData, wrappedDataLength, \n\t\t\t\t\t  wrappedData, mechanismInfo->wrappedDataLength );\n\t\tif( usePgpWrap )\n\t\t\tdlpParams.formatType = CRYPT_FORMAT_PGP;\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, &dlpParams,\n\t\t\t\t\t\t\t\t  sizeof( DLP_PARAMS ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmechanismInfo->wrappedDataLength = dlpParams.outLen;\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT\" );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, wrappedData, \n\t\t\t\t\t\t\t\t  wrappedDataLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst BYTE *dataPtr = mechanismInfo->wrappedData;\n\t\t\tint dataLength = wrappedDataLength, LOOP_ITERATOR;\n\n\t\t\t/* The PKC wrap functions take a fixed-length input and produce \n\t\t\t   a fixed-length output but some of this can be leading-zero \n\t\t\t   padding, so we strip the padding if there's any present */\n\t\t\tif( *dataPtr == 0 )\n\t\t\t\t{\n\t\t\t\tLOOP_MED_CHECKINC( *dataPtr == 0 && dataLength > 16,\n\t\t\t\t\t\t\t\t   ( dataPtr++, dataLength-- ) );\n\t\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t\tREQUIRES( rangeCheck( dataLength, 16, wrappedDataLength ) );\n\t\t\t\tmemmove( mechanismInfo->wrappedData, dataPtr, \n\t\t\t\t\t\t dataLength );\n\t\t\t\tmemset( ( BYTE * ) mechanismInfo->wrappedData + dataLength, \n\t\t\t\t\t\t0, wrappedDataLength - dataLength );\n\t\t\t\t}\n\t\t\tmechanismInfo->wrappedDataLength = dataLength;\n\t\t\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT\" );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && !memcmp( dataSample, samplePtr, 16 ) )\n\t\t{\n\t\t/* The data to wrap is unchanged, there's been a catastrophic \n\t\t   failure of the encryption.  We don't do a retIntError() at this\n\t\t   point because we want to at least continue and zeroise the data\n\t\t   first */\n\t\tassert( FALSE );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tzeroise( dataSample, 16 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem with the wrapping, clear the output value */\n\t\tzeroise( wrappedData, wrappedDataLength );\n\t\treturn( status );\n\t\t}\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_1( \"IMESSAGE_CTX_ENCRYPT\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int pkcUnwrapData( MECHANISM_WRAP_INFO *mechanismInfo, \n\t\t\t\t\t\t  OUT_BUFFER( dataMaxLength, *dataOutLength ) \\\n\t\t\t\t\t\t\t\tBYTE *data, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\tconst int dataMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *dataOutLength, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\tconst int dataInLength, \n\t\t\t\t\t\t  const BOOLEAN usePgpWrap, \n\t\t\t\t\t\t  const BOOLEAN isDlpAlgo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataOutLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength >= MIN_PKCSIZE && \\\n\t\t\t  dataMaxLength <= MAX_INTLENGTH_SHORT );\n\tREQUIRES( dataInLength >= MIN_PKCSIZE && \\\n\t\t\t  dataInLength <= dataMaxLength && \\\n\t\t\t  dataInLength <= MAX_INTLENGTH_SHORT );\n\tREQUIRES( usePgpWrap == TRUE || usePgpWrap == FALSE );\n\tREQUIRES( isDlpAlgo == TRUE || isDlpAlgo == FALSE );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataOutLength = 0;\n\n\tif( isDlpAlgo )\n\t\t{\n\t\tDLP_PARAMS dlpParams;\n\n\t\tsetDLPParams( &dlpParams, mechanismInfo->wrappedData,\n\t\t\t\t\t  mechanismInfo->wrappedDataLength, data, \n\t\t\t\t\t  dataMaxLength );\n\t\tif( usePgpWrap )\n\t\t\tdlpParams.formatType = CRYPT_FORMAT_PGP;\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, &dlpParams,\n\t\t\t\t\t\t\t\t  sizeof( DLP_PARAMS ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t*dataOutLength = dlpParams.outLen;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = adjustPKCS1Data( data, dataMaxLength,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedData,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedDataLength, \n\t\t\t\t\t\t\t\t  dataInLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, data,\n\t\t\t\t\t\t\t\t\t  dataInLength );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t*dataOutLength = dataInLength;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\t/* There was a problem with the wrapping, clear the output value */\n\tzeroise( data, dataMaxLength );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKCS #1 Wrap/Unwrap Mechanisms\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* When we're recovering a PKCS #1 data block, we check that the payload\n   contents are of a valid length.  Usually this is MAX_WORKING_KEYSIZE,\n   however for SSL what's wrapped is a 48-byte premaster secret, not an \n   actual key, so the length value that we check for is somewhat longer */\n\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n  #define MAX_PAYLOAD_SIZE\t\t48\n#else\n  #define MAX_PAYLOAD_SIZE\t\tMAX_WORKING_KEYSIZE\n#endif /* SSL vs. standard wrapped data */\n\n/* Generate/recover a PKCS #1 data block */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int generatePkcs1DataBlock( INOUT_BUFFER( dataMaxLen, *dataLength ) \\\n\t\t\t\t\t\t\t\t\t\tBYTE *data, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int dataMaxLen, \n\t\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataMaxLen ) \\\n\t\t\t\t\t\t\t\t\t\tint *dataLength, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int messageLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tconst int pkcs1PadSize = dataMaxLen - ( messageLen + 3 );\n\tint status;\n\n\tassert( isWritePtrDynamic( data, dataMaxLen ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLen >= MIN_PKCSIZE && dataMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( messageLen >= MIN_KEYSIZE && messageLen < dataMaxLen && \\\n\t\t\t  messageLen < MAX_INTLENGTH_SHORT );\n\t\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLen ) );\n\t*dataLength = 0;\n\n\t/* Determine PKCS #1 padding parameters and make sure that the key is \n\t   long enough to encrypt the payload.  PKCS #1 requires that the \n\t   maximum payload size be 11 bytes less than the length to give a \n\t   minimum of 8 bytes of random padding */\n\tif( messageLen > dataMaxLen - 11 )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\tENSURES( pkcs1PadSize >= 8 && \\\n\t\t\t 2 + pkcs1PadSize + 1 + messageLen <= dataMaxLen );\n\n\t/* Encode the payload using the PKCS #1 format:\n\t   \n\t\t[ 0 ][ 2 ][ nonzero random padding ][ 0 ][ payload ]\n\n\t   Note that the random padding is a nice place for a subliminal channel,\n\t   especially with the larger public key sizes where you can communicate \n\t   more information in the padding than you can in the payload */\n\tdata[ 0 ] = 0;\n\tdata[ 1 ] = 2;\n\tsetMessageData( &msgData, data + 2, pkcs1PadSize );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NZ );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( data, dataMaxLen );\n\t\treturn( status );\n\t\t}\n\tdata[ 2 + pkcs1PadSize ] = 0;\n\t*dataLength = 2 + pkcs1PadSize + 1;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int recoverPkcs1DataBlock( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int dataLength, \n\t\t\t\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *pkcs1PadSize )\n\t{\n\tint ch, ch0pos = 0, index, length, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( pkcs1PadSize, sizeof( int ) ) );\n\n\tREQUIRES( dataLength >= MIN_PKCSIZE && dataLength <= CRYPT_MAX_PKCSIZE );\n\n\t/* Clear return value */\n\t*pkcs1PadSize = 0;\n\n\t/* Undo the PKCS #1 padding:\n\n\t\t[ 0 ][ 2 ][ random nonzero padding ][ 0 ][ payload ]\n\t\n\t   with a minimum of 8 bytes padding (so 11 bytes including the constant\n\t   values).  However, with our MIN_PKCSIZE values we'll never get a \n\t   payload that comes close to MIN_PKCSIZE (in other words\n\t   ( MIN_PKCSIZE - payloadSize ) >>> 8) so we use \n\t   MIN_PKCSIZE - ( MAX_PAYLOAD_SIZE + 8 ) as our minimum allowed\n\t   padding value.  We also check that the payload size is at least\n\t   MIN_KEYSIZE in length.\n\t   \n\t   Note that some implementations may have bignum code that zero-\n\t   truncates the result which will produce a CRYPT_ERROR_BADDATA error \n\t   when we undo the padding, it's the responsibility of the lower-level \n\t   crypto layer to reformat the data to return a correctly-formatted \n\t   result if necessary.\n\n\t   In theory we can be used as a decryption timing oracle, in which\n\t   case the alternative code below, which runs in close to constant \n\t   time, can be used.  However, timing measurements for situations where \n\t   we could be an oracle, in this case TLS and some PKI protocols, \n\t   indicate that an attacker can't really gain any useful information\n\t   from the minute differences that occur at this level.\n\t   \n\t   The simple measure of bundling all of the formatting checks into a \n\t   single location and making the code as simple and quick as possible \n\t   seems to be enough to defeat any timing measurements, and also makes \n\t   the code much easier to understand and verify */\n\tif( dataLength < 11 + MIN_KEYSIZE )\n\t\t{\n\t\t/* PKCS #1 padding requires at least 11 (2 + 8 + 1) bytes of \n\t\t   padding data, if there isn't this much present then what we've \n\t\t   got can't be a valid payload.  \n\t\t   \n\t\t   Note that this code is never executed since \n\t\t   MIN_PKCSIZE >> MIN_KEYSIZE, it's present here merely to document \n\t\t   that the PKCS #1 conditions are being checked */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n#if 0\t/* Alternative constant-time version */\n\t{\n\tint result;\n\n\tresult = data[ 0 ] | ( data[ 1 ] ^ 0x02 );\t/* data[ 0 ] == 0, data[ 1 ] == 2 */\n\tfor( index = 1; index < dataLength; index++ )\n\t\t{\n\t\tint ch0select;\n\n\t\tch = byteToInt( data[ index ] );\n\t\tch = MAKE_BOOLEAN( ch ) ^ 1;\t\t\t/* 0 -> 1, !0 -> 0 */\n\t\tch0select = MAKE_BOOLEAN( ch0pos ) ^ 1;\t/* 0 -> 1, !0 -> 0 */\n\t\tch0pos = SELECT( ch0select & ch, index, ch0pos );\n\t\t}\n\tresult |= ch0pos < MIN_PKCSIZE - ( MAX_PAYLOAD_SIZE + 8 );\n\t}\t\t\t\t\t\t\t\t\t\t\t/* Not constant-time */\n#else\n\tif( data[ 0 ] != 0x00 || data[ 1 ] != 0x02 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tLOOP_LARGE( index = 1, index < dataLength, index++ )\n\t\t{\n\t\tch = byteToInt( data[ index ] );\n\t\tif( !( ch0pos | ch ) )\n\t\t\tch0pos = index;\t\t/* Set ch0pos on first zero byte */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( ch0pos < MIN_PKCSIZE - ( MAX_PAYLOAD_SIZE + 8 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( dataLength - ( ch0pos + 1 ) < MIN_KEYSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n#endif\n\tlength = ch0pos + 1;\t\t/* Skip the final 0x00 */\n\n\t/* Sanity check to make sure that the padding data looks OK (this will \n\t   also catch some cases of an attacker trying to use us as an oracle by\n\t   sending fixed-format padding).  We only do this in debug mode since \n\t   it's a probabilistic test and we don't want to bail out due to a \n\t   false positive in production code */\n\tassert( checkEntropy( data + 2, length - 1 ) );\n\n\t*pkcs1PadSize = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform PKCS #1 wrapping/unwrapping.  There are several variations of\n   this that are handled through common PKCS #1 mechanism functions */\n\ntypedef enum { \n\tPKCS1_WRAP_NONE,\t\t/* No PKCS #1 wrap type */\n\tPKCS1_WRAP_NORMAL,\t\t/* Standard PKCS #1 wrapping */\n#ifdef USE_SSL\n\tPKCS1_WRAP_RAW,\t\t\t/* SSL premaster secret in PKCS #1 */\n#endif /* USE_SSL */\n#ifdef USE_PGP\n\tPKCS1_WRAP_PGP,\t\t\t/* Checksummed PGP-format key data */\n#endif /* USE_PGP */\n\tPKCS1_WRAP_LAST\t\t\t/* Last possible PKCS #1 wrap type */\n\t} PKCS1_WRAP_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int pkcs1Wrap( INOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t  IN_ENUM( PKCS1_WRAP ) const PKCS1_WRAP_TYPE type )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tBYTE *wrappedData = mechanismInfo->wrappedData, *dataPtr;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint payloadSize, length, pkcs1PadSize, status;\n#ifdef USE_PGP\n\tint pgpAlgoID DUMMY_INIT;\n#endif /* USE_PGP */\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS1_WRAP ) );\n\n\t/* Clear return value */\n\tif( mechanismInfo->wrappedData != NULL )\n\t\t{\n\t\tmemset( mechanismInfo->wrappedData, 0,\n\t\t\t\tmechanismInfo->wrappedDataLength );\n\t\t}\n\n\t/* Get various algorithm parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo, \n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\tCFI_CHECK_UPDATE( \"getPkcAlgoParams\" );\n\n\t/* If this is just a length check, we're done */\n\tif( mechanismInfo->wrappedData == NULL )\n\t\t{\n\t\t/* Determine how long the encrypted value will be.  In the case of\n\t\t   Elgamal it's just an estimate since it can change by up to two\n\t\t   bytes depending on whether the values have the high bit set or\n\t\t   not, which requires zero-padding of the ASN.1-encoded integers.\n\t\t   This is rather nasty because it means that we can't tell how \n\t\t   large an encrypted value will be without actually creating it.  \n\t\t   The 10-byte length at the start is for the ASN.1 SEQUENCE (= 4) \n\t\t   and 2 * INTEGER (= 2*3) encoding */\n\t\tmechanismInfo->wrappedDataLength = \\\n\t\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \\\n\t\t\t\t\t\t\t10 + ( 2 * ( length + 1 ) ) : length;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that there's enough room for the wrapped key data */\n\tif( length > mechanismInfo->wrappedDataLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Get the payload details, either as data passed in by the caller or\n\t   from the key context */\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\tif( type == PKCS1_WRAP_RAW )\n\t\tpayloadSize = mechanismInfo->keyDataLength;\n\telse\n#endif /* USE_SSL && USE_RSA_SUITES */\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &payloadSize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#ifdef USE_PGP\n\tif( type == PKCS1_WRAP_PGP )\n\t\t{\n\t\tint sessionKeyAlgo;\t/* int vs.enum */\n\n\t\t/* PGP includes an additional algorithm specifier and checksum with\n\t\t   the wrapped key so we adjust the length to take this into\n\t\t   account */\n\t\tstatus = krnlSendMessage( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &sessionKeyAlgo,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptlibToPgpAlgo( sessionKeyAlgo, &pgpAlgoID );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tpayloadSize += 3;\t/* 1-byte algo ID + 2-byte checksum */\n\t\t}\n#endif /* USE_PGP */\n\tCFI_CHECK_UPDATE( \"payloadSize\" );\n\n\t/* Perform a preliminary check for an excessively long payload to make\n\t   it explicit, however generatePkcs1DataBlock() will also perform a \n\t   more precise check when it performs the data formatting */\n\tif( payloadSize >= length )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Generate the PKCS #1 data block with room for the payload at the end */\n\tstatus = generatePkcs1DataBlock( wrappedData, length, &pkcs1PadSize, \n\t\t\t\t\t\t\t\t\t payloadSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( wrappedData, length );\n\t\treturn( status );\n\t\t}\n\tENSURES( pkcs1PadSize + payloadSize == length );\n\tCFI_CHECK_UPDATE( \"generatePkcs1DataBlock\" );\n\n\t/* Copy the payload in at the last possible moment, then encrypt it */\n\tdataPtr = wrappedData + pkcs1PadSize;\n\tswitch( type )\n\t\t{\n\t\tcase PKCS1_WRAP_NORMAL:\n\t\t\tstatus = extractKeyData( mechanismInfo->keyContext, dataPtr,\n\t\t\t\t\t\t\t\t\t payloadSize, \"keydata\", 7 );\n\t\t\tCFI_CHECK_UPDATE( \"extractKeyData\" );\n\t\t\tbreak;\n\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t\tcase PKCS1_WRAP_RAW:\n\t\t\tREQUIRES( boundsCheck( pkcs1PadSize, payloadSize, \n\t\t\t\t\t\t\t\t   mechanismInfo->wrappedDataLength ) );\n\t\t\tmemcpy( dataPtr, mechanismInfo->keyData, payloadSize );\n\t\t\tCFI_CHECK_UPDATE( \"extractKeyData\" );\n\t\t\tbreak;\n#endif /* USE_SSL && USE_RSA_SUITES */\n\n#ifdef USE_PGP\n\t\tcase PKCS1_WRAP_PGP:\n\t\t\t*dataPtr++ = intToByte( pgpAlgoID );\n\t\t\tstatus = extractKeyData( mechanismInfo->keyContext, dataPtr,\n\t\t\t\t\t\t\t\t\t payloadSize - 3, \"keydata\", 7 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = pgpGenerateChecksum( dataPtr, payloadSize - 1,\n\t\t\t\t\t\t\t\t\tpayloadSize - ( 1 + UINT16_SIZE ) );\n\t\t\t\t}\n\t\t\tCFI_CHECK_UPDATE( \"extractKeyData\" );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( wrappedData, length );\n\t\treturn( status );\n\t\t}\n\n\t/* Wrap the encoded data using the public key */\n\tstatus = pkcWrapData( mechanismInfo, wrappedData, length,\n#ifdef USE_PGP\n\t\t\t\t\t\t  ( type == PKCS1_WRAP_PGP ) ? TRUE : FALSE,\n#else\n\t\t\t\t\t\t  FALSE,\n#endif /* USE_PGP */\n\t\t\t\t\t\t  ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem with the wrapping, clear the output value */\n\t\tzeroise( wrappedData, length );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"pkcWrapData\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"getPkcAlgoParams\", \"payloadSize\", \n\t\t\t\t\t\t\t\t\t\"generatePkcs1DataBlock\", \"extractKeyData\", \n\t\t\t\t\t\t\t\t\t\"pkcWrapData\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int pkcs1Unwrap( INOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t\tIN_ENUM( PKCS1_WRAP ) const PKCS1_WRAP_TYPE type )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tMESSAGE_DATA msgData;\n\tBYTE decryptedData[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE *decryptedDataPtr = decryptedData;\n\tconst BYTE *payloadPtr;\n\tconst int maxPayloadLength = \n#ifdef USE_SSL\n\t\t\t\t\t\t\t\t ( type == PKCS1_WRAP_RAW ) ? \\\n\t\t\t\t\t\t\t\t mechanismInfo->keyDataLength : \n#endif /* USE_SSL */\n#ifdef USE_PGP\n\t\t\t\t\t\t\t\t ( type == PKCS1_WRAP_PGP ) ? \\\n\t\t\t\t\t\t\t\t MAX_WORKING_KEYSIZE + 3 : \n#endif /* USE_PGP */\n\t\t\t\t\t\t\t\t MAX_WORKING_KEYSIZE;\n\tint length, pkcs1PadSize, unwrapStatus = CRYPT_OK, status;\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PKCS1_WRAP ) );\n\n\t/* Clear the return value if we're returning raw data */\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\tif( type == PKCS1_WRAP_RAW )\n\t\tmemset( mechanismInfo->keyData, 0, mechanismInfo->keyDataLength );\n#endif /* USE_SSL && USE_RSA_SUITES */\n\n\t/* Get various algorithm parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo, \n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\t/* Decrypt the data */\n\tstatus = pkcUnwrapData( mechanismInfo, decryptedData, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\t\t\t&length, length, \n#ifdef USE_PGP\n\t\t\t\t\t\t\t( type == PKCS1_WRAP_PGP ) ? TRUE : FALSE,\n#else\n\t\t\t\t\t\t\tFALSE,\n#endif /* USE_PGP */\n\t\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem with the decryption operation, continue with \n\t\t   dummy PKCS #1-formatted data.  It's uncertain what it would take \n\t\t   to actually encounter this situation since there's no obvious way \n\t\t   to cause it by manipulating the input data (at least in a manner \n\t\t   that causes the decryption to fail in the middle of the \n\t\t   operation rather than just rejecting the input data without even \n\t\t   trying to decrypt it, for example by making it larger than the \n\t\t   modulus for RSA), but it could be possible to achieve through a \n\t\t   memory-corruption attack, causing processing to bail out before \n\t\t   the key-validity check at the end catches the corruption.  On the \n\t\t   other hand skipping half the decrypt will cause a much larger \n\t\t   timing difference than the padding check, so we're probably not \n\t\t   achieving that much here.  Since it doesn't cost anything, we \n\t\t   defend against it anyway */\n\t\tdecryptedDataPtr = ( BYTE * ) fixedFormattedValue;\n\t\tunwrapStatus = status;\n\t\t}\n\n\t/* Recover the PKCS #1 data block, with the payload at the end */\n\tstatus = recoverPkcs1DataBlock( decryptedDataPtr, length, \n\t\t\t\t\t\t\t\t\t&pkcs1PadSize );\n\tif( cryptStatusError( unwrapStatus ) )\n\t\t{\n\t\t/* If there was an error at the decrypt stage, propagate that rather \n\t\t   than returning the generic CRYPT_ERROR_BADDATA that we'd get from\n\t\t   the padding check of the dummy data */\n\t\tstatus = unwrapStatus;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( decryptedData, CRYPT_MAX_PKCSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Evaluate the location and length of the payload after the PKCS #1 \n\t   padding and make sure that it can (plausibly) hold a key.  See the\n\t   analysis in recoverPkcs1DataBlock() about using this as a timing \n\t   oracle */\n\tlength -= pkcs1PadSize;\n\tif( length < MIN_KEYSIZE || length > maxPayloadLength )\n\t\t{\n\t\tzeroise( decryptedData, CRYPT_MAX_PKCSIZE );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tpayloadPtr = decryptedData + pkcs1PadSize;\n\n\t/* Return the result to the caller or load it into a context as a key */\n\tswitch( type )\n\t\t{\n#ifdef USE_PGP\n\t\tcase PKCS1_WRAP_PGP:\n\t\t\t/* PGP includes extra wrapping around the key so we have to\n\t\t\t   process that before we can load it */\n\t\t\tstatus = pgpExtractKey( &mechanismInfo->keyContext, payloadPtr, \n\t\t\t\t\t\t\t\t\tlength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tpayloadPtr++;\t\t/* Skip algorithm ID */\n\t\t\tlength -= 3;\t\t/* Subtract extra wrapping length */\n\t\t\tif( length < MIN_KEYSIZE )\n\t\t\t\t{\n\t\t\t\tzeroise( decryptedData, CRYPT_MAX_PKCSIZE );\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n#endif /* USE_PGP */\n\n\t\tcase PKCS1_WRAP_NORMAL:\n\t\t\t/* Load the decrypted keying information into the session key\n\t\t\t   context */\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) payloadPtr, length );\n\t\t\tstatus = krnlSendMessage( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\t\t\tif( cryptArgError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If there was an error with the key value or size convert \n\t\t\t\t   the return value into something more appropriate */\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\tbreak;\n\n#if defined( USE_SSL ) && defined( USE_RSA_SUITES )\n\t\tcase PKCS1_WRAP_RAW:\n\t\t\t/* Return the result to the caller.  This mechanism is used to \n\t\t\t   wrap the SSL premaster secret so the recovered data length \n\t\t\t   has to match the output length */\n\t\t\tif( length != mechanismInfo->keyDataLength )\n\t\t\t\t{\n\t\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tREQUIRES( rangeCheck( length, 1, mechanismInfo->keyDataLength ) );\n\t\t\tmemcpy( mechanismInfo->keyData, payloadPtr, length );\n\t\t\tmechanismInfo->keyDataLength = length;\n\t\t\tbreak;\n#endif /* USE_SSL && USE_RSA_SUITES */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tzeroise( decryptedData, CRYPT_MAX_PKCSIZE );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( pkcs1Wrap( mechanismInfo,\n#ifdef USE_SSL\n\t\t\t\t\t   ( mechanismInfo->keyContext == CRYPT_UNUSED ) ? \\\n\t\t\t\t\t   PKCS1_WRAP_RAW : \n#endif /* USE_SSL */\t\t\t\t\t   \n\t\t\t\t\t   PKCS1_WRAP_NORMAL ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( pkcs1Unwrap( mechanismInfo,\n#ifdef USE_SSL\n\t\t\t\t\t\t ( mechanismInfo->keyData != NULL ) ? \\\n\t\t\t\t\t\t PKCS1_WRAP_RAW : \n#endif /* USE_SSL */\t\t\t\t\t\t \n\t\t\t\t\t\t PKCS1_WRAP_NORMAL ) );\n\t}\n\n#ifdef USE_PGP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPKCS1PGP( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( pkcs1Wrap( mechanismInfo, PKCS1_WRAP_PGP ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPKCS1PGP( STDC_UNUSED void *dummy, \n\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( pkcs1Unwrap( mechanismInfo, PKCS1_WRAP_PGP ) );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOAEP Key Wrap/Unwrap Mechanisms\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_OAEP\n\n/* Get the lHash value used for OAEP.  In theory this should be a hash of a \n   label applied to the OAEP operation but this is never used so what ends\n   up being used is a fixed hash of an empty string.  Since this is \n   constant we can use a pre-calculated value for each hash algorithm */\n\ntypedef struct {\n\tconst CRYPT_ALGO_TYPE hashAlgo;\n\tBUFFER_FIXED( lHashSize ) \\\n\tconst BYTE *lHash;\n\tconst int lHashSize;\n\t} LHASH_INFO;\n\nstatic const LHASH_INFO lHashInfo[] = {\n\t{ CRYPT_ALGO_SHA1, ( const BYTE * )\t\t/* For pedantic compilers */\n\t  \"\\xDA\\x39\\xA3\\xEE\\x5E\\x6B\\x4B\\x0D\\x32\\x55\\xBF\\xEF\\x95\\x60\\x18\\x90\"\n\t  \"\\xAF\\xD8\\x07\\x09\", 20 },\n\t{ CRYPT_ALGO_SHA2, ( const BYTE * )\t\t/* For pedantic compilers */\n\t  \"\\xE3\\xB0\\xC4\\x42\\x98\\xFC\\x1C\\x14\\x9A\\xFB\\xF4\\xC8\\x99\\x6F\\xB9\\x24\"\n\t  \"\\x27\\xAE\\x41\\xE4\\x64\\x9B\\x93\\x4C\\xA4\\x95\\x99\\x1B\\x78\\x52\\xB8\\x55\", 32 },\n#ifdef USE_SHA2_EXT\n\t/* SHA2-384 and SHA2-512 are only available on systems with 64-bit data \n\t   type support */\n\t{ CRYPT_ALGO_SHA2, ( const BYTE * )\t\t/* For pedantic compilers */\n\t  \"\\x38\\xB0\\x60\\xA7\\x51\\xAC\\x96\\x38\\x4C\\xD9\\x32\\x7E\\xB1\\xB1\\xE3\\x6A\"\n\t  \"\\x21\\xFD\\xB7\\x11\\x14\\xBE\\x07\\x43\\x4C\\x0C\\xC7\\xBF\\x63\\xF6\\xE1\\xDA\"\n\t  \"\\x27\\x4E\\xDE\\xBF\\xE7\\x6F\\x65\\xFB\\xD5\\x1A\\xD2\\xF1\\x48\\x98\\xB9\\x5B\", 48 },\n\t{ CRYPT_ALGO_SHA2, ( const BYTE * )\t\t/* For pedantic compilers */\n\t  \"\\xCF\\x83\\xE1\\x35\\x7E\\xEF\\xB8\\xBD\\xF1\\x54\\x28\\x50\\xD6\\x6D\\x80\\x07\"\n\t  \"\\xD6\\x20\\xE4\\x05\\x0B\\x57\\x15\\xDC\\x83\\xF4\\xA9\\x21\\xD3\\x6C\\xE9\\xCE\"\n\t  \"\\x47\\xD0\\xD1\\x3C\\x5D\\x85\\xF2\\xB0\\xFF\\x83\\x18\\xD2\\x87\\x7E\\xEC\\x2F\"\n\t  \"\\x63\\xB9\\x31\\xBD\\x47\\x41\\x7A\\x81\\xA5\\x38\\x32\\x7A\\xF9\\x27\\xDA\\x3E\", 64 },\n#endif /* USE_SHA2_EXT */\n\t{ CRYPT_ALGO_NONE, NULL, 0 }, { CRYPT_ALGO_NONE, NULL, 0 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int getOaepHash( OUT_BUFFER_OPT( lHashMaxLen, *lHashLen ) \\\n\t\t\t\t\t\t\tvoid *lHash, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int lHashMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_SHORT_Z( lHashMaxLen ) \\\n\t\t\t\t\t\t\tint *lHashLen,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParam )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( ( lHash == NULL && lHashMaxLen == 0 ) || \\\n\t\t\tisWritePtrDynamic( lHash, lHashMaxLen ) );\n\t\n\tREQUIRES( ( lHash == NULL && lHashMaxLen == 0 ) || \\\n\t\t\t  ( lHash != NULL && \\\n\t\t\t\tlHashMaxLen >= CRYPT_MAX_HASHSIZE && \\\n\t\t\t\tlHashMaxLen < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashParam == 0 || \\\n\t\t\t  ( hashParam >= MIN_HASHSIZE && \\\n\t\t\t\thashParam <= CRYPT_MAX_HASHSIZE ) );\n\n\t/* Clear return values */\n\tif( lHash != NULL )\n\t\tzeroise( lHash, min( 16, lHashMaxLen ) );\n\t*lHashLen = 0;\n\n\t/* Find the matching hash data for this algorithm and hash size */\n\tLOOP_SMALL( i = 0, lHashInfo[ i ].hashAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( lHashInfo, LHASH_INFO ), i++ )\n\t\t{\n\t\tif( lHashInfo[ i ].hashAlgo != hashAlgo )\n\t\t\tcontinue;\n\t\tif( hashParam != 0 && lHashInfo[ i ].lHashSize != hashParam )\n\t\t\tcontinue;\n\t\tif( lHash != NULL )\n\t\t\t{\n\t\t\tREQUIRES( rangeCheck( lHashInfo[ i ].lHashSize, 1, \n\t\t\t\t\t\t\t\t  lHashMaxLen ) );\n\t\t\tmemcpy( lHash, lHashInfo[ i ].lHash, lHashInfo[ i ].lHashSize );\n\t\t\t}\n\t\t*lHashLen = lHashInfo[ i ].lHashSize;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( lHashInfo, LHASH_INFO ) );\n\tif( lHash != NULL )\n\t\tzeroise( lHash, lHashMaxLen );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n#define getOaepHashSize( hashLen, hashAlgo, hashParam ) \\\n\t\tgetOaepHash( NULL, 0, hashLen, hashAlgo, hashParam )\n\n/* OAEP mask generation function MGF1 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int mgf1( OUT_BUFFER_FIXED( maskLen ) void *mask, \n\t\t\t\t IN_LENGTH_PKC const int maskLen, \n\t\t\t\t IN_BUFFER( seedLen ) const void *seed, \n\t\t\t\t IN_LENGTH_PKC const int seedLen,\n\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t IN_INT_SHORT_Z const int hashParam )\n\t{\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO hashInfo;\n\tBYTE countBuffer[ 4 + 8 ], maskBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE *maskOutPtr = mask;\n\tint hashSize, maskIndex, blockCount = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( mask, maskLen ) );\n\tassert( isReadPtrDynamic( seed, seedLen ) );\n\n\tREQUIRES( maskLen >= 20 && maskLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( seedLen >= 20 && seedLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( isShortIntegerRange( hashParam ) );\n\n\tgetHashParameters( hashAlgo, hashParam, &hashFunction, &hashSize );\n\n\t/* Set up the block counter buffer.  This will never have more than the\n\t   last few bits set (8 bits = 5120 bytes of mask for the smallest hash,\n\t   SHA-1) so we only change the last byte */\n\tmemset( countBuffer, 0, 4 );\n\n\t/* Produce enough blocks of output to fill the mask */\n\tLOOP_MED( maskIndex = 0, maskIndex < maskLen, \n\t\t\t  ( maskIndex += hashSize, maskOutPtr += hashSize ) )\n\t\t{\n\t\tconst int noMaskBytes = min( hashSize, maskLen - maskIndex );\n\n\t\t/* Calculate hash( seed || counter ) */\n\t\tcountBuffer[ 3 ] = ( BYTE ) blockCount++;\n\t\thashFunction( hashInfo, NULL, 0, seed, seedLen, HASH_STATE_START );\n\t\thashFunction( hashInfo, maskBuffer, hashSize, countBuffer, 4, \n\t\t\t\t\t  HASH_STATE_END );\n\t\tREQUIRES( boundsCheckZ( maskIndex, noMaskBytes, maskLen ) );\n\t\tmemcpy( maskOutPtr, maskBuffer, noMaskBytes );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\tzeroise( maskBuffer, CRYPT_MAX_HASHSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Generate/recover an OAEP data block:\n\n\t\t\t\t\t\t\t +----------+---------+-------+\n\t\t\t\t\t\tDB = |  lHash   |    PS   |   M   |\n\t\t\t\t\t\t\t +----------+---------+-------+\n\t\t\t\t\t\t\t\t\t\t\t|\n\t\t\t\t  +----------+\t\t\t\tV\n\t\t\t\t  |   seed   |--> MGF ---> xor\n\t\t\t\t  +----------+\t\t\t\t|\n\t\t\t\t\t\t|\t\t\t\t\t|\n\t\t\t   +--+\t\tV\t\t\t\t\t|\n\t\t\t   |00|\t   xor <----- MGF <-----|\n\t\t\t   +--+\t\t|\t\t\t\t\t|\n\t\t\t\t |\t\t|\t\t\t\t\t|\n\t\t\t\t V\t\tV\t\t\t\t\tV\n\t\t\t   +--+----------+----------------------------+\n\t\t EM =  |00|maskedSeed|          maskedDB          |\n\t\t\t   +--+----------+----------------------------+ \n\t\t\t\t\t\t|\t\t\t\t\t|\n\t\t\t\t\t\tV\t\t\t\t\tV\n\t\t\t\t\t   xor <----- MGF <-----|\n\t\t\t\t\t\t|\t\t\t\t\t|\n\t\t\t\t\t\tV\t\t\t\t\t|\n\t\t\t\t  +----------+\t\t\t\tV\n\t\t\t\t  |   seed   |--> MGF ---> xor\n\t\t\t\t  +----------+\t\t\t\t|\n\t\t\t\t\t\t\t\t\t\t\tV\n\t\t\t\t\t\t\t +----------+---------+-------+\n\t\t\t\t\t\tDB = |  lHash   |    PS   |   M   |\n\t\t\t\t\t\t\t +----------+---------+-------+ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int generateOaepDataBlock( OUT_BUFFER_FIXED( dataMaxLen ) BYTE *data, \n\t\t\t\t\t\t\t\t  IN_LENGTH_PKC const int dataMaxLen, \n\t\t\t\t\t\t\t\t  IN_BUFFER( messageLen ) const void *message, \n\t\t\t\t\t\t\t\t  IN_RANGE( MIN_KEYSIZE, CRYPT_MAX_KEYSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int messageLen,\n\t\t\t\t\t\t\t\t  IN_BUFFER( seedLen ) const void *seed, \n\t\t\t\t\t\t\t\t  IN_LENGTH_PKC const int seedLen,\n\t\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\t  IN_INT_SHORT_Z const int hashParam )\n\t{\n\tBYTE dbMask[ CRYPT_MAX_PKCSIZE + 8 ], seedMask[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE *maskedSeed, *db;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint dbLen, i, length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( data, dataMaxLen ) );\n\tassert( isReadPtrDynamic( message, messageLen ) );\n\tassert( isReadPtrDynamic( seed, seedLen ) );\n\n\tREQUIRES( dataMaxLen >= MIN_PKCSIZE && dataMaxLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( messageLen >= MIN_KEYSIZE && messageLen <= dataMaxLen && \\\n\t\t\t  messageLen <= CRYPT_MAX_KEYSIZE );\n\tREQUIRES( seedLen >= 20 && seedLen <= dataMaxLen && \\\n\t\t\t  seedLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( cryptStatusOK( \\\n\t\t\t\tgetOaepHashSize( &i, hashAlgo, hashParam ) ) && seedLen == i );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( isShortIntegerRange( hashParam ) );\n\n\t/* Make sure that the payload fits:\n\n\t\t<------------ dataMaxLen ----------->\n\t\t+--+------+-------+----+--+---------+\n\t\t|00| seed | lhash | PS |01| message |\n\t\t+--+------+-------+----+--+---------+\n\t\t  1\t sLen\t sLen\t 1\t 1\t msgLen\n\n\t   Although PS may have a length of zero bytes we require at least one\n\t   padding byte.  The only case where we can run into problems is if we \n\t   try and use SHA2-512 in combination with a 1024-bit key */\n\tif( 1 + seedLen + seedLen + 1 + 1 + messageLen > dataMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Calculate the size and position of the various data quantities:\n\n\t\t<---------- dataMaxLen --------->\n\t\t+--+------------+---------------+\n\t\t|00|\tseed\t|\t\tdb\t\t|\n\t\t+--+------------+---------------+\n\t\t|  |<-seedLen ->|<--- dbLen --->|\n\t  data |\t\t\t|\n\t\tmaskedSeed\t   db */\n\tmaskedSeed = data + 1;\n\tdb = maskedSeed + seedLen;\n\tdbLen = dataMaxLen - ( 1 + seedLen );\n\n\tENSURES( dbLen >= 20 && dbLen >= messageLen + 1 && \\\n\t\t\t 1 + seedLen + dbLen <= dataMaxLen );\n\n\t/* db = lHash || zeroes || 0x01 || message */\n\tREQUIRES( boundsCheck( 1 + seedLen, dbLen, dataMaxLen ) );\n\tmemset( db, 0, dbLen );\n\tstatus = getOaepHash( db, dbLen, &length, hashAlgo, hashParam );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdb[ dbLen - messageLen - 1 ] = 0x01;\n\tREQUIRES( boundsCheck( 1 + seedLen + dbLen - messageLen, messageLen,\n\t\t\t\t\t\t   dataMaxLen ) );\n\tmemcpy( db + dbLen - messageLen, message, messageLen );\n\tCFI_CHECK_UPDATE( \"getOaepHash\" );\n\n\tENSURES( length == seedLen );\n\n\t/* dbMask = MGF1( seed, dbLen ) */\n\tstatus = mgf1( dbMask, dbLen, seed, seedLen, hashAlgo, hashParam );\n\tENSURES( cryptStatusOK( status ) );\n\tCFI_CHECK_UPDATE( \"dbMask\" );\n\n\t/* maskedDB = db ^ dbMask */\n\tLOOP_EXT( i = 0, i < dbLen, i++, CRYPT_MAX_PKCSIZE + 1 )\n\t\tdb[ i ] ^= dbMask[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* seedMask = MGF1( maskedDB, seedLen ) */\n\tstatus = mgf1( seedMask, seedLen, db, dbLen, hashAlgo, hashParam );\n\tENSURES( cryptStatusOK( status ) );\n\tCFI_CHECK_UPDATE( \"seedMask\" );\n\n\t/* maskedSeed = seed ^ seedMask */\n\tLOOP_EXT( i = 0, i < seedLen, i++, CRYPT_MAX_PKCSIZE + 1 )\n\t\t{\n\t\tmaskedSeed[ i ] = \\\n\t\t\tintToByte( ( ( const BYTE * ) seed )[ i ] ^ seedMask[ i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"maskedSeed\" );\n\n\t/* data = 0x00 || maskedSeed || maskedDB */\n\tdata[ 0 ] = 0x00;\n\n\tzeroise( dbMask, CRYPT_MAX_PKCSIZE );\n\tzeroise( seedMask, CRYPT_MAX_HASHSIZE );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"getOaepHash\", \"dbMask\", \"seedMask\", \n\t\t\t\t\t\t\t\t\t\"maskedSeed\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int recoverOaepDataBlock( OUT_BUFFER( messageMaxLen, *messageLen ) \\\n\t\t\t\t\t\t\t\t\tBYTE *message, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int messageMaxLen, \n\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( messageMaxLen ) \\\n\t\t\t\t\t\t\t\t\tint *messageLen, \n\t\t\t\t\t\t\t\t IN_BUFFER( dataLen ) const void *data, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int dataLen, \n\t\t\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\t IN_INT_SHORT_Z const int hashParam )\n\t{\n\tBYTE dbMask[ CRYPT_MAX_PKCSIZE + 8 ], seedMask[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE dataBuffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE *seed, *db;\n\tint seedLen, dbLen, length, i, dummy, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( message, messageMaxLen ) );\n\tassert( isWritePtr( messageLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( data, dataLen ) );\n\n\tREQUIRES( messageMaxLen >= MIN_PKCSIZE && \\\n\t\t\t  messageMaxLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( dataLen >= MIN_PKCSIZE && dataLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( isShortIntegerRange( hashParam ) );\n\n\t/* Clear return value */\n\tmemset( message, 0, min( 16, messageMaxLen ) );\n\t*messageLen = 0;\n\n\t/* Make sure that the MGF requirements are met.  Note that this check \n\t   has already been performed by the caller to avoid this being used as \n\t   a timing oracle, this is merely here to make the fact that the check \n\t   has been done explicit */\n\tstatus = getOaepHashSize( &seedLen, hashAlgo, hashParam );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Take a local copy of the input data, since we're about to operate on \n\t   it */\n\tREQUIRES( rangeCheck( dataLen, 1, CRYPT_MAX_PKCSIZE ) );\n\tmemcpy( dataBuffer, data, dataLen );\n\n\t/* Calculate the size and position of the various data quantities */\n\tseed = dataBuffer + 1;\n\tdb = seed + seedLen;\n\tdbLen = dataLen - ( 1 + seedLen );\n\n\tENSURES( dbLen >= 16 && 1 + seedLen + dbLen <= dataLen );\n\n\t/* seedMask = MGF1( maskedDB, seedLen ) */\n\tstatus = mgf1( seedMask, seedLen, db, dbLen, hashAlgo, hashParam );\n\tENSURES( cryptStatusOK( status ) );\t/* Can only be an internal error */\n\n\t/* seed = maskedSeed ^ seedMask */\n\tLOOP_EXT( i = 0, i < seedLen, i++, CRYPT_MAX_PKCSIZE + 1 )\n\t\tseed[ i ] ^= seedMask[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* dbMask = MGF1( seed, dbLen ) */\n\tstatus = mgf1( dbMask, dbLen, seed, seedLen, hashAlgo, hashParam );\n\tENSURES( cryptStatusOK( status ) );\t/* Can only be an internal error */\n\n\t/* db = maskedDB ^ dbMask */\n\tLOOP_EXT( i = 0, i < dbLen, i++, CRYPT_MAX_PKCSIZE + 1 )\n\t\tdb[ i ] ^= dbMask[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Get the (constant) lHash value */\n\tstatus = getOaepHash( dbMask, dbLen, &dummy, hashAlgo, hashParam );\n\tENSURES( cryptStatusOK( status ) );\t\n\t\t\t /* This can only be an internal error since we've already \n\t\t\t    called this function a few lines further up */\n\n\t/* Verify that:\n\n\t\tdata = 0x00 || [seed] || db \n\t\t\t = 0x00 || [seed] || lHash || zeroes || 0x01 || message\n\n\t   We need to be careful with the order of the checks, for example we \n\t   could check for the leading 0x00 before performing the OAEP \n\t   processing but this might allow an attacker to mount a timing attack,\n\t   see \"A chosen ciphertext attack on RSA optimal asymmetric encryption \n\t   padding (OAEP)\" by James Manger, Proceedings of Crypto'01, LNCS \n\t   No.2139, p.230.  To make this as hard as possible we cluster all of \n\t   the format checks as close together as we can to try and produce a \n\t   near-constant-time accept/reject decision.  \n\t   \n\t   Unfortunately the complex processing required by OAEP makes it more \n\t   or less impossible to perform in a timing-independent manner, so the \n\t   best that we can do is make it as hard as possible to get timing \n\t   data, but in any case see the comment in the PKCS #1 processing code \n\t   for the low probability of this occurring.  Not to mention the fact \n\t   that the OAEP code isn't used anywhere in cryptlib */\n\tif( 1 + seedLen + seedLen + 1 + 1 + MIN_KEYSIZE > dataLen )\n\t\t{\n\t\t/* Make sure that at least a minimum-length payload fits:\n\n\t\t\t<------------ dataMaxLen ----------->\n\t\t\t+--+------+-------+----+--+---------+\n\t\t\t|00| seed | lhash | PS |01| message |\n\t\t\t+--+------+-------+----+--+---------+\n\t\t\t  1\t sLen\t sLen\t 1\t 1\t msgLen\n\t\t\n\t\t   Again, we perform this check after all formatting operations have\n\t\t   completed to try and avoid a timing attack */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( dataBuffer[ 0 ] != 0x00 || \\\n\t\t!compareDataConstTime( db, dbMask, seedLen ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tLOOP_EXT( i = seedLen, i < dbLen && db[ i ] == 0x00, i++, \n\t\t\t  CRYPT_MAX_PKCSIZE + 1 );\n\tENSURES( LOOP_BOUND_OK );\n\tif( i <= seedLen || i >= dbLen || db[ i++ ] != 0x01 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tlength = dbLen - i;\n\tif( length < MIN_KEYSIZE )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\tif( length > messageMaxLen )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Return the recovered message to the caller */\n\tREQUIRES( boundsCheck( i, length, dbLen ) );\n\tREQUIRES( rangeCheck( length, 0, messageMaxLen ) );\n\tmemcpy( message, db + i, length );\n\t*messageLen = length;\n\n\tzeroise( dbMask, CRYPT_MAX_PKCSIZE );\n\tzeroise( seedMask, CRYPT_MAX_HASHSIZE );\n\tzeroise( dataBuffer, CRYPT_MAX_PKCSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform OAEP wrapping/unwrapping */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportOAEP( STDC_UNUSED void *dummy, \n\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tBYTE payload[ CRYPT_MAX_KEYSIZE + 8 ], seed[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint seedLen, payloadSize, length, status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Clear return value */\n\tif( mechanismInfo->wrappedData != NULL )\n\t\t{\n\t\tmemset( mechanismInfo->wrappedData, 0,\n\t\t\t\tmechanismInfo->wrappedDataLength );\n\t\t}\n\n\t/* Make sure that the OAEP auxiliary algorithm requirements are met */\n\tstatus = getOaepHashSize( &seedLen, mechanismInfo->auxInfo, \n\t\t\t\t\t\t\t  /* mechanismInfo->auxInfoParam */ 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"getOaepHashSize\" );\n\n\t/* Get various algorithm parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo, \n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\tCFI_CHECK_UPDATE( \"getPkcAlgoParams\" );\n\n\t/* If this is just a length check, we're done */\n\tif( mechanismInfo->wrappedData == NULL )\n\t\t{\n\t\t/* Determine how long the encrypted value will be.  In the case of\n\t\t   Elgamal it's just an estimate since it can change by up to two\n\t\t   bytes depending on whether the values have the high bit set or\n\t\t   not, which requires zero-padding of the ASN.1-encoded integers.\n\t\t   This is rather nasty because it means that we can't tell how \n\t\t   large an encrypted value will be without actually creating it.  \n\t\t   The 10-byte length at the start is for the ASN.1 SEQUENCE (= 4) \n\t\t   and 2 * INTEGER (= 2*3) encoding */\n\t\tmechanismInfo->wrappedDataLength = \\\n\t\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \\\n\t\t\t\t\t\t\t10 + ( 2 * ( length + 1 ) ) : length;\n\t\t\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the payload details from the key context and generate the OAEP \n\t   random seed value */\n\tstatus = krnlSendMessage( mechanismInfo->keyContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &payloadSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, seed, seedLen );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Extract the key data and process it into an OAEP data block */\n\tstatus = extractKeyData( mechanismInfo->keyContext, payload, payloadSize,\n\t\t\t\t\t\t\t \"keydata\", 7 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = generateOaepDataBlock( mechanismInfo->wrappedData, length, \n\t\t\t\t\t\t\t\t\t\tpayload, payloadSize, seed, seedLen,\n\t\t\t\t\t\t\t\t\t\tmechanismInfo->auxInfo, \n\t\t\t\t\t\t\t\t\t\t/* mechanismInfo->auxInfoParam */ 0 );\n\t\t}\n\tzeroise( payload, bitsToBytes( CRYPT_MAX_KEYSIZE ) );\n\tzeroise( seed, CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"generateOaepDataBlock\" );\n\n\t/* Wrap the encoded data using the public key */\n\tstatus = pkcWrapData( mechanismInfo, mechanismInfo->wrappedData, length, \n\t\t\t\t\t\t  FALSE, ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \\\n\t\t\t\t\t\t\t\t TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem with the wrapping, clear the output value */\n\t\tzeroise( mechanismInfo->wrappedData, length );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"pkcWrapData\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"getOaepHashSize\", \"getPkcAlgoParams\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\"generateOaepDataBlock\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importOAEP( STDC_UNUSED void *dummy, \n\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tMESSAGE_DATA msgData;\n\tBYTE decryptedData[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE *decryptedDataPtr = decryptedData;\n\tBYTE message[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint length, messageLen, unwrapStatus = CRYPT_OK, status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\t/* Make sure that the MGF requirements are met.  This check isn't \n\t   actually needed until the recoverOaepDataBlock() call but we perform \n\t   it here before the decrypt to avoid being used as a timing oracle \n\t   since feeding in a non-usable hash function that causes the \n\t   processing to bail out right after the decrypt provides a reasonably \n\t   precise timer for the decryption */\n\tstatus = getOaepHashSize( &length, mechanismInfo->auxInfo, \n\t\t\t\t\t\t\t  /* mechanismInfo->auxInfoParam */ 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get various algorithm parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->wrapContext, &cryptAlgo, \n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\t/* Decrypt the data */\n\tstatus = pkcUnwrapData( mechanismInfo, decryptedData, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\t\t\t&length, length, FALSE,\n\t\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* See the long comment in pkcs1Unwrap() for the background on what \n\t\t   we're doing here */\n\t\tdecryptedDataPtr = ( BYTE * ) fixedFormattedValue;\n\t\tunwrapStatus = status;\n\t\t}\n\n\t/* Recover the payload from the OAEP data block */\n\tstatus = recoverOaepDataBlock( message, CRYPT_MAX_PKCSIZE, &messageLen, \n\t\t\t\t\t\t\t\t   decryptedDataPtr, length, \n\t\t\t\t\t\t\t\t   mechanismInfo->auxInfo, \n\t\t\t\t\t\t\t\t   /* mechanismInfo->auxInfoParam */ 0 );\n\tzeroise( decryptedData, CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusError( unwrapStatus ) )\n\t\t{\n\t\t/* If there was an error at the decrypt stage, propagate that rather \n\t\t   than returning the generic CRYPT_ERROR_BADDATA that we'd get from\n\t\t   the padding check of the dummy data */\n\t\tstatus = unwrapStatus;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( message, CRYPT_MAX_PKCSIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the decrypted keying information into the session key context */\n\tsetMessageData( &msgData, message, messageLen );\n\tstatus = krnlSendMessage( mechanismInfo->keyContext, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* If there was an error with the key value or size, convert the \n\t\t   return value into something more appropriate */\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tzeroise( message, CRYPT_MAX_PKCSIZE );\n\n\treturn( status );\n\t}\n#endif /* USE_OAEP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKC Key Wrap Self-test Functions \t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test PKC key wrap mechanisms */\n\ntypedef enum {\n\tTEST_NONE,\t\t\t\t/* No data block manipulation type */\n\tTEST_NORMAL,\t\t\t/* Standard test */\n\tTEST_CORRUPT_START,\t\t/* Corrupt starting byte */\n\tTEST_CORRUPT_BLOCKTYPE,\t/* Corrupt block type */\n\tTEST_CORRUPT_PADDING,\t/* Corrupt padding data */\n\tTEST_CORRUPT_END,\t\t/* Corrupt ending byte */\n\tTEST_LAST\t\t\t\t/* Last possible manipulation type */\n\t} TEST_TYPE;\n\nstatic void manipulateDataBlock( INOUT_BUFFER_FIXED( length ) BYTE *buffer,\n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int length,\n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int payloadStart,\n\t\t\t\t\t\t\t\t IN_ENUM( TEST ) const TEST_TYPE testType )\n\t{\n\tassert( isWritePtr( buffer, length ) );\n\n\tREQUIRES_V( length > 0 && length <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_V( payloadStart > 0 && payloadStart < length );\n\tREQUIRES_V( isEnumRange( testType, TEST ) );\n\n\tswitch( testType )\n\t\t{\n\t\tcase TEST_NORMAL:\n\t\t\t/* Standard test */\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_START:\n\t\t\t/* Corrupt the PKCS #1 leading zero */\n\t\t\tbuffer[ 0 ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_BLOCKTYPE:\n\t\t\t/* Corrupt the PKCS #1 block type */\n\t\t\tbuffer[ 1 ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_PADDING:\n\t\t\t/* Corrupt the PKCS #1 padding */\n\t\t\tbuffer[ 30 ] = 0;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_END:\n\t\t\t/* Corrupt the PKCS #1 trailing zero */\n\t\t\tbuffer[ payloadStart - 1 ]++;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nCHECK_RETVAL \\\nstatic int testPKCS1( IN_ENUM( TEST ) const TEST_TYPE testType )\n\t{\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ], *payloadPtrIn, *payloadPtrOut;\n\tint length = 256, padSizeIn, padSizeOut;\n\tint payloadSizeIn = 16, payloadSizeOut = length, status;\n\n\tREQUIRES( isEnumRange( testType, TEST ) );\n\n\t/* Create the PKCS #1 data block and remember its parameters */\n\tstatus = generatePkcs1DataBlock( buffer, length, &padSizeIn, \n\t\t\t\t\t\t\t\t\t payloadSizeIn );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( padSizeIn + payloadSizeIn == length );\n\tpayloadPtrIn = buffer + padSizeIn;\n\tmemset( payloadPtrIn, '*', payloadSizeIn );\n\n\t/* Manipulate the data as required */\n\tmanipulateDataBlock( buffer, length, padSizeIn, testType );\n\n\t/* Verify the data block and make sure that we got back what we put \n\t   in */\n\tstatus = recoverPkcs1DataBlock( buffer, length, &padSizeOut );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpayloadSizeOut -= padSizeOut;\n\tpayloadPtrOut = buffer + padSizeOut;\n\tif( padSizeOut != padSizeIn || payloadPtrOut != payloadPtrIn || \\\n\t\tpayloadSizeOut != payloadSizeIn || payloadPtrOut[ 0 ] != '*' || \\\n\t\tpayloadPtrOut[ payloadSizeOut - 1 ] != '*' )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_OAEP\n\nCHECK_RETVAL \\\nstatic int testOAEP( IN_ENUM( TEST ) const TEST_TYPE testType )\n\t{\n\t#define OAEP_BUFSIZE\t256\n\tstatic const BYTE seed[] = \\\n\t\t\t{ 0xAA, 0xFD, 0x12, 0xF6, 0x59, 0xCA, 0xE6, 0x34, \n\t\t\t  0x89, 0xB4, 0x79, 0xE5, 0x07, 0x6D, 0xDE, 0xC2,\n\t\t\t  0xF0, 0x6C, 0xB5, 0x8F };\n\tstatic const BYTE message[] = \\\n\t\t\t{ 0xD4, 0x36, 0xE9, 0x95, 0x69, 0xFD, 0x32, 0xA7,\n\t\t\t  0xC8, 0xA0, 0x5B, 0xBC, 0x90, 0xD3, 0x2C, 0x49 };\n\tBYTE buffer[ OAEP_BUFSIZE + 8 ], outMessage[ 128 + 8 ];\n\tint seedLen, outLen DUMMY_INIT, status;\n\n\tREQUIRES( isEnumRange( testType, TEST ) );\n\n\t/* SHA-1 */\n\tstatus = getOaepHashSize( &seedLen, CRYPT_ALGO_SHA1, 0 );\n\tREQUIRES( cryptStatusOK( status ) );\n\tmemset( buffer, '*', OAEP_BUFSIZE );\n\tstatus = generateOaepDataBlock( buffer, OAEP_BUFSIZE, message, 16, \n\t\t\t\t\t\t\t\t\tseed, seedLen, CRYPT_ALGO_SHA1, 20 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmanipulateDataBlock( buffer, OAEP_BUFSIZE, OAEP_BUFSIZE - 8, \n\t\t\t\t\t\t\t testType );\n\t\tstatus = recoverOaepDataBlock( outMessage, 128, &outLen, \n\t\t\t\t\t\t\t\t\t   buffer, OAEP_BUFSIZE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_SHA1, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( outLen != 16 || memcmp( message, outMessage, outLen ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* SHA-2 */\n\tstatus = getOaepHashSize( &seedLen, CRYPT_ALGO_SHA2, 0 );\n\tREQUIRES( cryptStatusOK( status ) );\n\tmemset( buffer, '*', OAEP_BUFSIZE );\n\tstatus = generateOaepDataBlock( buffer, OAEP_BUFSIZE, message, 16, \n\t\t\t\t\t\t\t\t\tseed, seedLen, CRYPT_ALGO_SHA2, 32 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmanipulateDataBlock( buffer, OAEP_BUFSIZE, OAEP_BUFSIZE - 8, \n\t\t\t\t\t\t\t testType );\n\t\tstatus = recoverOaepDataBlock( outMessage, 128, &outLen, \n\t\t\t\t\t\t\t\t\t   buffer, OAEP_BUFSIZE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_SHA2, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( outLen != 16 || memcmp( message, outMessage, outLen ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* SHA-2 512-bit */\n#ifdef USE_SHA2_EXT\n\tstatus = getOaepHashSize( &seedLen, CRYPT_ALGO_SHA2, 64 );\n\tREQUIRES( cryptStatusOK( status ) );\n\tmemset( buffer, '*', OAEP_BUFSIZE );\n\tstatus = generateOaepDataBlock( buffer, OAEP_BUFSIZE, message, 16, \n\t\t\t\t\t\t\t\t\tseed, seedLen, CRYPT_ALGO_SHA2, 64 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmanipulateDataBlock( buffer, OAEP_BUFSIZE, OAEP_BUFSIZE - 8, \n\t\t\t\t\t\t\t testType );\n\t\tstatus = recoverOaepDataBlock( outMessage, 128, &outLen, \n\t\t\t\t\t\t\t\t\t   buffer, OAEP_BUFSIZE, \n\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_SHA2, 64 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( outLen != 16 || memcmp( message, outMessage, outLen ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n#endif /* USE_SHA2_EXT */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_OAEP */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint pkcWrapSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tint status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\tstatus = testPKCS1( TEST_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_PRINT(( \"Mechanism self-test for PKCS1 wrap/unwrap mechanism \"\n\t\t\t\t\t  \"failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n\tstatus = testPKCS1( TEST_CORRUPT_START );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_BLOCKTYPE );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_PADDING );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_END );\n\tif( status != CRYPT_ERROR_BADDATA )\n\t\t{\n\t\tDEBUG_PRINT(( \"Data corruption self-test for PKCS1 wrap/unwrap \"\n\t\t\t\t\t  \"mechanism failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n#ifdef USE_OAEP\n\tstatus = testOAEP( TEST_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_PRINT(( \"Mechanism self-test for OAEP wrap/unwrap mechanism \"\n\t\t\t\t\t  \"failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n\tstatus = testOAEP( TEST_CORRUPT_START );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testOAEP( TEST_CORRUPT_PADDING );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testOAEP( TEST_CORRUPT_END );\n\tif( status != CRYPT_ERROR_BADDATA )\n\t\t{\n\t\tDEBUG_PRINT(( \"Data corruption self-test for OAEP wrap/unwrap \"\n\t\t\t\t\t  \"mechanism failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n#endif /* USE_OAEP */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_privk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Private-Key Wrap Mechanism Routines\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"misc_rw.h\"\n  #include \"stream.h\"\n  #include \"mech_int.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"io/stream.h\"\n  #include \"mechs/mech_int.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\n/* Decrypt a PGP MPI */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int pgpReadDecryptMPI( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t\t\t\t  IN_LENGTH_PKC const int maxLength )\n\t{\n\tvoid *mpiDataPtr DUMMY_INIT_PTR;\n\tconst long mpiDataStartPos = stell( stream ) + UINT16_SIZE;\n\tint mpiLength, dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( minLength >= bitsToBytes( 155 ) && \\\n\t\t\t  minLength <= maxLength && \\\n\t\t\t  maxLength <= CRYPT_MAX_PKCSIZE );\n\n\t/* Get the MPI length and decrypt the payload data.  We have to be \n\t   careful how we handle this because readInteger16Ubits() returns the \n\t   canonicalised form of the values (with leading zeroes truncated) so \n\t   the returned length value doesn't necessarily represent the amount\n\t   of data that we need to decrypt:\n\n\t\tstartPos\tdataStart\t\t stell()\n\t\t\t|\t\t\t|\t\t\t\t|\n\t\t\tv\t\t\tv <-- length -->v\n\t\t+---+-----------+---------------+\n\t\t|\t|\t\t\t|///////////////| Stream\n\t\t+---+-----------+---------------+ */\n\tstatus = readInteger16Ubits( stream, NULL, &dummy, minLength, \n\t\t\t\t\t\t\t\t maxLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmpiLength = stell( stream ) - mpiDataStartPos;\n\tstatus = sMemGetDataBlockAbs( stream, mpiDataStartPos, &mpiDataPtr, \n\t\t\t\t\t\t\t\t  mpiLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t  mpiDataPtr, mpiLength );\n\t\t}\n\treturn( status );\n\t}\n\n/* The PGP 2.x key wrap encrypts only the MPI payload data rather than the \n   entire private key record so we have to read and then decrypt each \n   component separately.  This is a horrible way to handle things because we \n   have to repeatedly process the MPI data, first in the PGP keyring code to\n   find out how much key data is present, then again during decryption to \n   find the MPI payload that needs to be decrypted, and finally again after\n   decryption to find the MPI payload that needs to be checksummed (although\n   we can shortcut the latter, see the comment in checkPgp2KeyIntegrity().\n   \n   Unfortunately we can't use the xxxPARAM_MIN_x / xxxPARAM_MAX_x values to\n   perform range checking since they're only visible to the context-\n   manipulation code, so we have to use approximations here (the actual\n   values will be checked by the keyload code anyway, it just means that we\n   can't perform very precise pre-filtering here) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int pgp2DecryptKey( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) const int dataLength, \n\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( dataLength ) \\\n\t\t\t\t\t\t\t\tint *bytesToChecksum, \n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t   const BOOLEAN isDlpAlgo )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( bytesToChecksum, sizeof( int ) ) );\n\t\n\tREQUIRES( dataLength >= 16 && \\\n\t\t\t  dataLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isDlpAlgo == TRUE || isDlpAlgo == FALSE );\n\n\t/* Clear return value */\n\t*bytesToChecksum = 0;\n\n\tsMemConnect( &stream, data, dataLength );\n\tstatus = pgpReadDecryptMPI( &stream, iCryptContext,\t\t\t/* d or x */\n\t\t\t\t\t\t\t\tbitsToBytes( 155 ), CRYPT_MAX_PKCSIZE );\n\tif( isDlpAlgo )\n\t\t{\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*bytesToChecksum = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = pgpReadDecryptMPI( &stream, iCryptContext,\t\t/* p */\n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE / 2, CRYPT_MAX_PKCSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = pgpReadDecryptMPI( &stream, iCryptContext,\t\t/* q */\n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE / 2, CRYPT_MAX_PKCSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = pgpReadDecryptMPI( &stream, iCryptContext,\t\t/* u */\n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE / 2, CRYPT_MAX_PKCSIZE  );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*bytesToChecksum = stell( &stream );\n\tsMemDisconnect( &stream );\n\treturn( status );\n\t}\n#endif /* USE_PGP || USE_PGPKEYS */\n\n/* Check that the unwrapped data hasn't been corrupted */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkKeyIntegrity( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_PRIVATE_KEYSIZE ) \\\n\t\t\t\t\t\t\t\tconst int dataLength,\n\t\t\t\t\t\t\t  IN_LENGTH_IV const int blockSize )\n\t{\n\tconst BYTE *padPtr;\n\tint length, padSize, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength >= MIN_PRIVATE_KEYSIZE && \\\n\t\t\t  dataLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( blockSize >= MIN_IVSIZE && blockSize <= CRYPT_MAX_IVSIZE );\n\n\t/* Get the length of the encapsulated ASN.1 object */\n\tstatus = getObjectLength( data, dataLength, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( ( status == CRYPT_ERROR_BADDATA ) ? \\\n\t\t\t\tCRYPT_ERROR_WRONGKEY : status );\n\t\t}\n\n\t/* Check that the PKCS #5 padding is as expected.  Performing the check \n\t   this way is the reverse of the way that it's usually done because we \n\t   already know the payload size from the ASN.1 and can use this to \n\t   determine the expected padding value and thus check that the end of \n\t   the encrypted data hasn't been subject to a bit-flipping attack.  For \n\t   example for RSA private keys the end of the data is:\n\n\t\t[ INTEGER u ][ INTEGER keySize ][ padding ]\n\n\t   where the keySize is encoded as a 4-byte value and the padding is 1-8 \n\t   bytes.  If the low bits of u are flipped there's a 5/8 chance that \n\t   either the keySize value (checked in the RSA read code) or padding \n\t   will be messed up, both of which will be detected (in addition the \n\t   RSA key load checks try and verify u when the key is loaded).  For \n\t   DLP keys the end of the data is:\n\n\t\t[ INTEGER x ][ padding ]\n\n\t   for which bit flipping is rather harder to detect since 7/8 of the \n\t   time the following block won't be affected, however the DLP key load \n\t   checks also verify x when the key is loaded.  The padding checking is \n\t   effectively free and helps make Klima-Rosa type attacks harder */\n\tpadPtr = ( const BYTE * ) data + length;\n\tpadSize = blockSize - ( length & ( blockSize - 1 ) );\n\tif( padSize < 1 || padSize > CRYPT_MAX_IVSIZE || \\\n\t\tlength + padSize > dataLength )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tLOOP_EXT( i = 0, i < padSize, i++, CRYPT_MAX_IVSIZE + 1 )\n\t\t{\n\t\tif( padPtr[ i ] != padSize )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkPgp2KeyIntegrity( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int dataLength, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int keyDataLength )\n\t{\n\tSTREAM stream;\n\tconst BYTE *keyData = data;\n\tint checksum = 0, storedChecksum, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength >= 16 && dataLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( keyDataLength >= 16 && \\\n\t\t\t  keyDataLength + UINT16_SIZE <= dataLength && \\\n\t\t\t  keyDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Calculate the checksum for the MPIs.  In theory we'd have to process\n\t   them all over again but the checksumming procedure is inconsistent\n\t   with the encryption in that only the MPI data is encrypted but the\n\t   overall length and data are checksummed.  Since these data blocks are\n\t   stored consecutively in memory we can checksum all MPI data as one\n\t   continuous block */\n\tLOOP_MAX( i = 0, i < keyDataLength, i++ )\n\t\tchecksum += keyData[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\tchecksum &= 0xFFFF;\t\t/* MPI checksum is a 16-bit value */\n\n\t/* Recover the stored checksum that follows the MPI data and compare it \n\t   to the calculated checksum */\n\tsMemConnect( &stream, keyData + keyDataLength, \n\t\t\t\t dataLength - keyDataLength );\n\tstatus = storedChecksum = readUint16( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) || checksum != storedChecksum )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkOpenPgpKeyIntegrity( IN_BUFFER( dataLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *data, \n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int dataLength )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hashValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tconst BYTE *hashValuePtr;\n\tint hashSize;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength >= 16 && dataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Get the hash algorithm info and make sure that there's room for \n\t   minimal-length data and the checksum */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\tif( dataLength < bitsToBytes( 155 ) + hashSize )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\thashValuePtr = ( const BYTE * ) data + dataLength - hashSize; \n\n\t/* Hash the data and make sure that it matches the stored MDC */\n\thashFunctionAtomic( hashValue, CRYPT_MAX_HASHSIZE, data, \n\t\t\t\t\t\tdataLength - hashSize );\n\tif( !compareDataConstTime( hashValue, hashValuePtr, hashSize ) )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP || USE_PGPKEYS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tPKCS #15 Private Key Wrap/Unwrap Mechanisms\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform private key wrapping/unwrapping.  There are several variations of\n   this that are handled through common private key wrap mechanism\n   functions.\n\n   In order to protect against use of a possibly corrupted private key, \n   cryptlib performs a series of chained checks that follow the general \n   pattern:\n\n\tverify integrity of key data in form X;\n\ttransform key data into form Y;\n\tcalculate checksum of form Y;\n\tverify integrity of key data in form X;\n\n   Once the data has been checksummed, and therefore protected, in form Y, \n   the check on form X that it came from is repeated to ensure that what was \n   converted into form Y is unchanged.\n\n   In the case of a private key load, the chained checks are as follows.  \n   For privateKeyUnwrap(), the procedure is:\n\n\tchecksumData( keyData );\n\timportPrivateKeyData( keyData );\n\t\treadPrivateKeyFunction( keyData, LOAD );\n\t\tloadKeyFunction( keyData );\n\t\t\tinitCheckDLPkey( keyData );\n\t\t\tchecksumContextData( keyData );\n\t\treadPrivateKeyFunction( keyData, CHECK );\n\tchecksumData( keyData );\n\n   The checksumData() checks that the key data wasn't corrupted around the \n   importPrivateKeyData() call, and the readPrivateKeyFunction( LOAD/CHECK ) \n   checks that the data loaded before the loadKeyFunction() is the same as \n   the data present afterwards.  Finally, loadKeyFunction() calls\n   checksumContextData() which protects the loaded key from corruption */\n\ntypedef enum { PRIVATEKEY_WRAP_NONE, PRIVATEKEY_WRAP_NORMAL,\n\t\t\t   PRIVATEKEY_WRAP_OLD, PRIVATEKEY_WRAP_LAST } PRIVATEKEY_WRAP_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int privateKeyWrap( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t\t   IN_ENUM( PRIVATEKEY_WRAP ) \\\n\t\t\t\t\t\t\tconst PRIVATEKEY_WRAP_TYPE type )\n\t{\n\tconst KEYFORMAT_TYPE formatType = ( type == PRIVATEKEY_WRAP_NORMAL ) ? \\\n\t\t\t\t\t\t\t\tKEYFORMAT_PRIVATE : KEYFORMAT_PRIVATE_OLD;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint payloadSize, blockSize, padSize, status, LOOP_ITERATOR;\n\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PRIVATEKEY_WRAP ) );\n\n\t/* Clear return value */\n\tif( mechanismInfo->wrappedData != NULL )\n\t\t{\n\t\tmemset( mechanismInfo->wrappedData, 0,\n\t\t\t\tmechanismInfo->wrappedDataLength );\n\t\t}\n\n\t/* Get the payload details */\n\tstatus = exportPrivateKeyData( NULL, 0, &payloadSize, \n\t\t\t\t\t\t\t\t   mechanismInfo->keyContext, formatType, \n\t\t\t\t\t\t\t\t   \"private_key\", 11 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"exportPrivateKeyData\" );\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &blockSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpadSize = roundUp( payloadSize + 1, blockSize ) - payloadSize;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\t\n\tENSURES( !( ( payloadSize + padSize ) & ( blockSize - 1 ) ) );\n\tENSURES( padSize >= 1 && padSize <= CRYPT_MAX_IVSIZE );\n\n\t/* If this is just a length check, we're done */\n\tif( mechanismInfo->wrappedData == NULL )\n\t\t{\n\t\tmechanismInfo->wrappedDataLength = payloadSize + padSize;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tANALYSER_HINT( mechanismInfo->wrappedDataLength > MIN_PKCSIZE && \\\n\t\t\t\t   mechanismInfo->wrappedDataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Make sure that the wrapped key fits in the output buffer */\n\tif( payloadSize + padSize > mechanismInfo->wrappedDataLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Write the private key data, PKCS #5-pad it, and encrypt it */\n\tstatus = exportPrivateKeyData( mechanismInfo->wrappedData, \n\t\t\t\t\t\t\t\t   mechanismInfo->wrappedDataLength, \n\t\t\t\t\t\t\t\t   &payloadSize, mechanismInfo->keyContext,\n\t\t\t\t\t\t\t\t   formatType, \"private_key\", 11 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tBYTE startSample[ 8 + 8 ], endSample[ 8 + 8 ];\n\t\tBYTE *dataPtr = mechanismInfo->wrappedData;\n\t\tconst void *dataEndPtr = dataPtr + payloadSize + padSize - 8;\n\t\tint i;\n\n\t\t/* Sample the first and last 8 bytes of data so that we can check\n\t\t   that they really have been encrypted */\n\t\tmemcpy( startSample, dataPtr, 8 );\n\t\tmemcpy( endSample, dataEndPtr, 8 );\n\n\t\t/* Add the PKCS #5 padding and encrypt the data */\n\t\tLOOP_EXT( i = 0, i < padSize, i++, CRYPT_MAX_IVSIZE + 1 )\n\t\t\tdataPtr[ payloadSize + i ] = intToByte( padSize );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedData,\n\t\t\t\t\t\t\t\t  payloadSize + padSize );\n\n\t\t/* Make sure that the original data samples differ from the final\n\t\t   data.  We don't perform a retIntError() exit at this point because\n\t\t   we need to continue and zeroise the data that we're working with */\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( !memcmp( startSample, dataPtr, 8 ) || \\\n\t\t\t  !memcmp( endSample, dataEndPtr, 8 ) ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Failed to encrypt private-key data\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t}\n\t\tzeroise( startSample, 8 );\n\t\tzeroise( endSample, 8 );\n\t\tCFI_CHECK_UPDATE( \"exportPrivateKeyData\" );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->wrappedData,\n\t\t\t\t mechanismInfo->wrappedDataLength );\n\t\treturn( status );\n\t\t}\n\tmechanismInfo->wrappedDataLength = payloadSize + padSize;\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"exportPrivateKeyData\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\"exportPrivateKeyData\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int privateKeyUnwrap( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t\t\t IN_ENUM( PRIVATEKEY_WRAP ) \\\n\t\t\t\t\t\t\t\tconst PRIVATEKEY_WRAP_TYPE type )\n\t{\n\tconst KEYFORMAT_TYPE formatType = ( type == PRIVATEKEY_WRAP_NORMAL ) ? \\\n\t\t\t\t\t\t\t\tKEYFORMAT_PRIVATE : KEYFORMAT_PRIVATE_OLD;\n\tvoid *buffer;\n\tint blockSize, checksum DUMMY_INIT, status, altStatus;\n\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\t\n\tREQUIRES( isEnumRange( type, PRIVATEKEY_WRAP ) );\n\n\t/* Make sure that the data has a sane length and is a multiple of the\n\t   cipher block size.  Since we force the use of CBC mode we know that \n\t   it has to have this property.  Any required length checks have \n\t   already been enforced by the kernel ACLs */\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &blockSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_IVSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( mechanismInfo->wrappedDataLength & ( blockSize - 1 ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Copy the encrypted private key data to a temporary pagelocked buffer, \n\t   decrypt it, and read it into the context */\n\tif( ( status = krnlMemalloc( &buffer, \\\n\t\t\t\t\t\t\tmechanismInfo->wrappedDataLength ) ) != CRYPT_OK )\n\t\treturn( status );\n\tmemcpy( buffer, mechanismInfo->wrappedData,\n\t\t\tmechanismInfo->wrappedDataLength );\n\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, buffer,\n\t\t\t\t\t\t\t  mechanismInfo->wrappedDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tchecksum = checksumData( buffer, mechanismInfo->wrappedDataLength );\n\t\tstatus = checkKeyIntegrity( buffer, \n\t\t\t\t\t\t\t\t\tmechanismInfo->wrappedDataLength, \n\t\t\t\t\t\t\t\t\tblockSize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importPrivateKeyData( buffer, \n\t\t\t\t\t\t\tmechanismInfo->wrappedDataLength, \n\t\t\t\t\t\t\tmechanismInfo->keyContext, formatType );\n\t\tif( checksumData( buffer, \n\t\t\t\t\t\t  mechanismInfo->wrappedDataLength ) != checksum )\n\t\t\t{\n\t\t\t/* The private-key data was corrupted between the decrypt and \n\t\t\t   when it was loaded into the context, we can't trust the \n\t\t\t   key */\n\t\t\tDEBUG_DIAG(( \"Decrypted private-key data memory corruption detected\" ));\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t}\n\t\t}\n\tzeroise( buffer, mechanismInfo->wrappedDataLength );\n\taltStatus = krnlMemfree( &buffer );\n\tENSURES( cryptStatusOK( altStatus ) );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPrivateKey( STDC_UNUSED void *dummy, \n\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKey( STDC_UNUSED void *dummy, \n\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint exportPrivateKeyPKCS8( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyPKCS8( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t   INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPGP Private Key Wrap/Unwrap Mechanisms\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PGPKEYS\n\n/* Perform PGP private key wrapping/unwrapping.  There are several variations\n   of this that are handled through common private key wrap mechanism\n   functions.  The variations are:\n\n\tPGP2: mpi_enc( d ), mpi_enc( p ), mpi_enc( q ), mpi_enc( u ),\n\t\t  uint16 checksum\n\t\n\tOpenPGP_Old: enc( mpi [...], \n\t\t\t\t\t  uint16 checksum )\n\t\n\tOpenPGP: enc( mpi [...], \n\t\t\t\t  byte[20] mdc ) */\n\ntypedef enum { PRIVATEKEYPGP_WRAP_NONE, PRIVATEKEYPGP_WRAP_PGP2, \n\t\t\t   PRIVATEKEYPGP_WRAP_OPENPGP_OLD,\n\t\t\t   PRIVATEKEYPGP_WRAP_OPENPGP, \n\t\t\t   PRIVATEKEYPGP_WRAP_LAST } PRIVATEKEYPGP_WRAP_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int privateKeyUnwrapPGP( STDC_UNUSED void *dummy,\n\t\t\t\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo,\n\t\t\t\t\t\t\t\tIN_ENUM( PRIVATEKEYPGP_WRAP ) \\\n\t\t\t\t\t\t\t\t\tconst PRIVATEKEYPGP_WRAP_TYPE type )\n\t{\n\tvoid *buffer;\n\tint pkcAlgorithm, bytesToChecksum DUMMY_INIT, status, altStatus;\n\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, PRIVATEKEYPGP_WRAP ) );\n\n\t/* Get various algorithm parameters */\n\tstatus = krnlSendMessage( mechanismInfo->keyContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgorithm,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy the encrypted private key data to a temporary buffer and decrypt \n\t   it */\n\tif( ( status = krnlMemalloc( &buffer, \\\n\t\t\t\t\t\tmechanismInfo->wrappedDataLength ) ) != CRYPT_OK )\n\t\treturn( status );\n\tmemcpy( buffer, mechanismInfo->wrappedData,\n\t\t\tmechanismInfo->wrappedDataLength );\n\tif( type == PRIVATEKEYPGP_WRAP_PGP2 )\n\t\t{\n\t\tstatus = pgp2DecryptKey( buffer, mechanismInfo->wrappedDataLength,\n\t\t\t\t\t\t\t\t &bytesToChecksum, mechanismInfo->wrapContext, \n\t\t\t\t\t\t\t\t ( pkcAlgorithm != CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->wrapContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, buffer,\n\t\t\t\t\t\t\t\t  mechanismInfo->wrappedDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( buffer, mechanismInfo->wrappedDataLength );\n\t\taltStatus = krnlMemfree( &buffer );\n\t\tENSURES( cryptStatusOK( altStatus ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Perform one of PGP's assorted key checksumming operations and read \n\t   the key data into the context */\n\tif( type == PRIVATEKEYPGP_WRAP_PGP2 || \\\n\t\ttype == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )\n\t\t{\n\t\t/* Before the use of MDCs for private-key data there was a mutant \n\t\t   halfway stage that used the PGP 2.x checksum but encrypted all of \n\t\t   the key data in the OpenPGP manner.  If we're using this halfway \n\t\t   variant then the amount of data to checksum is the total amount\n\t\t   minus the size of the checksum */\n\t\tif( type == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )\n\t\t\tbytesToChecksum = mechanismInfo->wrappedDataLength - UINT16_SIZE;\n\t\tstatus = checkPgp2KeyIntegrity( buffer, mechanismInfo->wrappedDataLength,\n\t\t\t\t\t\t\t\t\t\tbytesToChecksum );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = checkOpenPgpKeyIntegrity( buffer, \n\t\t\t\t\t\t\t\t\t\t   mechanismInfo->wrappedDataLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importPrivateKeyData( buffer, \n\t\t\t\t\t\t\tmechanismInfo->wrappedDataLength, \n\t\t\t\t\t\t\tmechanismInfo->keyContext, KEYFORMAT_PGP );\n\t\tif( status == CRYPT_ERROR_BADDATA )\n\t\t\tstatus = CRYPT_ERROR_WRONGKEY;\n\t\t}\n\tzeroise( buffer, mechanismInfo->wrappedDataLength );\n\taltStatus = krnlMemfree( &buffer );\n\tENSURES( cryptStatusOK( altStatus ) );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyPGP2( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t  INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyUnwrapPGP( dummy, mechanismInfo,\n\t\t\t\t\t\t\t\t PRIVATEKEYPGP_WRAP_PGP2 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyOpenPGPOld( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t\t\tINOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyUnwrapPGP( dummy, mechanismInfo,\n\t\t\t\t\t\t\t\t PRIVATEKEYPGP_WRAP_OPENPGP_OLD ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint importPrivateKeyOpenPGP( STDC_UNUSED void *dummy, \n\t\t\t\t\t\t\t INOUT MECHANISM_WRAP_INFO *mechanismInfo )\n\t{\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );\n\n\treturn( privateKeyUnwrapPGP( dummy, mechanismInfo,\n\t\t\t\t\t\t\t\t PRIVATEKEYPGP_WRAP_OPENPGP ) );\n\t}\n#endif /* USE_PGPKEYS */\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/mechs/mech_sig.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Signature Mechanism Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef INC_ALL\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"mech_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"mechs/mech_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tUtility Routines - ASN.1 Replacement\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're building cryptlib without ASN.1 support then we still need some\n   minimal ASN.1 functionality in order to encode and decode MessageDigest\n   records in signatures.  The following bare-bones functions provide this\n   support, these are extremely cut-down versions of code normally found in \n   asn1_rd.c and asn1_ext.c */\n\n#ifndef USE_INT_ASN1\n\n#define readTag\t\t\t\t\tsgetc\n#define writeTag\t\t\t\tsputc\n#define sizeofShortObject( length )\t( 1 + 1 + ( length ) )\n#define BER_OCTETSTRING\t\t\t0x04\n#define BER_NULL\t\t\t\t0x05\n#define BER_SEQUENCE\t\t\t0x30\n#define MKOID( value )\t\t\t( ( const BYTE * ) value )\n#define sizeofOID( oid )\t\t( 1 + 1 + ( int ) oid[ 1 ] )\n#define sizeofNull()\t\t\t( 1 + 1 )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int readRawObject( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_BUFFER( bufferMaxLength, *bufferLength ) \\\n\t\t\t\t\t\t\t\tBYTE *buffer,\n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\tconst int bufferMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \\\n\t\t\t\t\t\t\t\tint *bufferLength, \n\t\t\t\t\t\t  IN_TAG_ENCODED const int tag )\n\t{\n\tint objectTag, length, offset = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( buffer, bufferMaxLength ) );\n\tassert( isWritePtr( bufferLength, sizeof( int ) ) );\n\n\tREQUIRES_S( bufferMaxLength > 16 && \\\n\t\t\t\tbufferMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_S( tag == BER_SEQUENCE );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, bufferMaxLength ) );\n\t*bufferLength = 0;\n\n\t/* Read the identifier field and length.  We need to remember each byte \n\t   as it's read so we can't just call readLengthValue() for the length, \n\t   but since we only need to handle lengths that can be encoded in one \n\t   byte this isn't a problem */\n\tstatus = objectTag = readTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( objectTag != BER_SEQUENCE )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tbuffer[ offset++ ] = intToByte( objectTag );\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 || length > 0x7F )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\tbuffer[ offset++ ] = intToByte( length );\n\tif( offset + length > bufferMaxLength )\n\t\treturn( sSetError( stream, CRYPT_ERROR_OVERFLOW ) );\n\n\t/* Read in the rest of the data */\n\t*bufferLength = offset + length;\n\treturn( sread( stream, buffer + offset, length ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeHeader( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_TAG_ENCODED const int tag,\n\t\t\t\t\t\tIN_LENGTH_SHORT const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES_S( tag >= BER_OCTETSTRING && tag <= BER_SEQUENCE );\n\tREQUIRES_S( length >= 0 && length <= 255 );\n\n\twriteTag( stream, tag );\n\treturn( sputc( stream, length ) );\n\t}\n\nCHECK_RETVAL_PTR \\\nstatic const BYTE *getOID( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t   IN_LENGTH_HASH const int hashSize )\n\t{\n\tREQUIRES_N( isHashAlgo( hashAlgo ) );\n\tREQUIRES_N( hashSize == 0 || \\\n\t\t\t\t( hashSize >= MIN_HASHSIZE && \\\n\t\t\t\t  hashSize <= CRYPT_MAX_HASHSIZE ) );\n\n\tif( hashAlgo == CRYPT_ALGO_SHA1 )\n\t\treturn( MKOID( \"\\x06\\x05\\x2B\\x0E\\x03\\x02\\x1A\" ) );\n\tif( hashAlgo != CRYPT_ALGO_SHA2 )\n\t\tretIntError_Null();\n\n\tswitch( hashSize )\n\t\t{\n\t\tcase 0:\n\t\tcase 32:\n\t\t\treturn( MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x01\" ) );\n\n#ifdef USE_SHA2_EXT\n\t\tcase 48:\n\t\t\treturn( MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x02\" ) );\n\n\t\tcase 64:\n\t\t\treturn( MKOID( \"\\x06\\x09\\x60\\x86\\x48\\x01\\x65\\x03\\x04\\x02\\x03\" ) );\n#endif /* USE_SHA2_EXT */\n\n\t\tdefault:\n\t\t\tretIntError_Null();\n\t\t}\n\n\tretIntError_Null();\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nstatic int sizeofAlgoIDex( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t   IN_RANGE( 0, 999 ) const int subAlgo )\n\t{\n\tconst BYTE *oid = getOID( hashAlgo, subAlgo );\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( subAlgo == 0 || \\\n\t\t\t  ( subAlgo >= MIN_HASHSIZE && subAlgo <= CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( oid != NULL );\n\n\treturn( sizeofShortObject( sizeofOID( oid ) + sizeofNull() ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT \\\nstatic int sizeofMessageDigest( IN_ALGO const CRYPT_ALGO_TYPE hashAlgo, \n\t\t\t\t\t\t\t\tIN_LENGTH_HASH const int hashSize )\n\t{\n\tint algoInfoSize, hashInfoSize;\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\n\talgoInfoSize = sizeofAlgoIDex( hashAlgo, hashSize );\n\thashInfoSize = sizeofShortObject( hashSize );\n\tENSURES( algoInfoSize > 8 && algoInfoSize < MAX_INTLENGTH_SHORT );\n\tENSURES( hashInfoSize > hashSize && hashInfoSize < MAX_INTLENGTH_SHORT );\n\n\treturn( sizeofShortObject( algoInfoSize + hashInfoSize ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeMessageDigest( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t   IN_BUFFER( hashSize ) const void *hash, \n\t\t\t\t\t\t\t   IN_LENGTH_HASH const int hashSize )\n\t{\n\tconst BYTE *oid = getOID( hashAlgo, hashSize );\n\t\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( hash, hashSize ) );\n\n\tREQUIRES_S( isHashAlgo( hashAlgo ) );\n\tREQUIRES_S( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\n\t/* writeSequence() */\n\twriteHeader( stream, BER_SEQUENCE, \n\t\t\t\t sizeofAlgoIDex( hashAlgo, hashSize ) + \\\n\t\t\t\t\tsizeofShortObject( hashSize ) );\n\n\t/* writeAlgoIDex() */\n\twriteHeader( stream, BER_SEQUENCE, sizeofOID( oid ) + sizeofNull() );\n\tswrite( stream, oid, sizeofOID( oid ) );\n\twriteHeader( stream, BER_NULL, 0 );\n\n\t/* writeOctetString() */\n\twriteHeader( stream, BER_OCTETSTRING, hashSize );\n\treturn( swrite( stream, hash, hashSize ) );\n\t}\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike PKCS #1 encryption there isn't any minimum-height requirement for \n   the PKCS #1 signature padding, however we require a set minimum number of \n   bytes of 0xFF padding because if they're not present then there's \n   something funny going on.  For a given key size we require that all but\n   ( 3 bytes PKCS #1 formatting + ( 2 + 15 + 2 ) bytes ASN.1 wrapper + \n     CRYPT_MAX_HASHSIZE bytes hash ) be 0xFF padding */\n\n#define getMinPadBytes( length ) \\\n\t\t( ( length ) - ( 3 + 19 + CRYPT_MAX_HASHSIZE ) )\n\n/* Encode/decode PKCS #1 signature formatting */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int encodePKCS1( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\tIN_BUFFER( hashSize ) const void *hash, \n\t\t\t\t\t\tIN_LENGTH_HASH const int hashSize,\n\t\t\t\t\t\tIN_LENGTH_PKC const int length )\n\t{\n\tint payloadSize, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( hash, hashSize ) );\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( length >= MIN_PKCSIZE && length < CRYPT_MAX_PKCSIZE );\n\n\t/* Encode the signature payload using the PKCS #1 format:\n\n\t\t[ 0 ][ 1 ][ 0xFF padding ][ 0 ][ payload ] */\n\tstatus = payloadSize = sizeofMessageDigest( hashAlgo, hashSize );\n\tENSURES( !cryptStatusError( status ) );\n\tsputc( stream, 0 );\n\tsputc( stream, 1 );\n\tLOOP_EXT( i = 0, i < length - ( payloadSize + 3 ), i++,\n\t\t\t  CRYPT_MAX_PKCSIZE )\n\t\t{\n\t\tsputc( stream, 0xFF );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsputc( stream, 0 );\n\n\treturn( writeMessageDigest( stream, hashAlgo, hash, hashSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int decodePKCS1( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_LENGTH_PKC const int length )\n\t{\n\tint ch, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( length >= MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\n\t/* Decode the payload using the PKCS #1 format:\n\n\t\t[ 0 ][ 1 ][ 0xFF padding ][ 0 ][ payload ]\n\n\t   Note that some implementations may have bignum code that zero-\n\t   truncates the RSA data, which would remove the leading zero from the \n\t   PKCS #1 padding and produce a CRYPT_ERROR_BADDATA error.  It's the \n\t   responsibility of the lower-level crypto layer to reformat the data \n\t   to return a correctly-formatted result if necessary */\n\tif( sgetc( stream ) != 0 || sgetc( stream ) != 1 )\n\t\t{\n\t\t/* No [ 0 ][ 1 ] at start */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tLOOP_EXT( ( i = 2, ch = 0xFF ), \n\t\t\t  ( i < length - MIN_HASHSIZE ) && ( ch == 0xFF ), i++, \n\t\t\t  CRYPT_MAX_PKCSIZE + 1 )\n\t\t{\n\t\tch = sgetc( stream );\n\t\tif( cryptStatusError( ch ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( ch != 0 || i < getMinPadBytes( length ) || \\\n\t\ti >= length - MIN_HASHSIZE )\n\t\t{\n\t\t/* No [ 0 ] at end or insufficient/excessive 0xFF padding */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Compare the ASN.1-encoded hash value in the signature with the hash \n   information that we've been given.  We have to be very careful how we \n   handle this because we don't want to allow an attacker to inject random \n   data into gaps in the encoding, which would allow for signature forgery \n   if small exponents are used (although cryptlib disallows any exponents \n   that make this easy).  The obvious approach of using \n   checkObjectEncoding() doesn't work because an attacker can still encode \n   the signature in a form that's syntactically valid ASN.1, just not the \n   correct ASN.1 for a MessageDigest record.  To avoid having to have every \n   function that handles reading the hash value be anal-retentive about \n   every data element that it reads, we take the hash value that we've been \n   given and encode it correctly as a MessageDigest record and then do a \n   straight memcmp() of the encoded form rather than trying to validity-\n   check the externally-supplied value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int compareHashInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\tIN_BUFFER( hashSize ) const void *hash, \n\t\t\t\t\t\t\tIN_LENGTH_HASH const int hashSize )\n\t{\n\tCRYPT_ALGO_TYPE dummyHashAlgo;\n\tSTREAM mdStream;\n\tBYTE encodedMD[ 32 + CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE recreatedMD[ 32 + CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE dummyHashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint encodedMdLength, recreatedMdLength DUMMY_INIT;\n\tint dummyHashSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( hash, hashSize ) );\n\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashSize >= MIN_HASHSIZE && hashSize <= CRYPT_MAX_HASHSIZE );\n\n\t/* Read the encoded hash data as a blob and make sure that that's all\n\t   of the data */\n\tstatus = readRawObject( stream, encodedMD, 32 + CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t&encodedMdLength, BER_SEQUENCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sMemDataLeft( stream ) != 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Write the supplied hash information into an encoded blob */\n\tsMemOpen( &mdStream, recreatedMD, 32 + CRYPT_MAX_HASHSIZE );\n\tstatus = writeMessageDigest( &mdStream, hashAlgo, hash, hashSize );\n\tif( cryptStatusOK( status ) )\n\t\trecreatedMdLength = stell( &mdStream );\n\tsMemDisconnect( &mdStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Compare the two encoded blobs.  What to return in this case is a bit\n\t   complex because if the data that precedes the hash value is corrupted \n\t   then we should really return a CRYPT_ERROR_BADDATA, but because we're \n\t   doing an encode-and-compare rather than a read/decode, everything \n\t   gets converted into the same error code, namely a \n\t   CRYPT_ERROR_SIGNATURE.  \n\t   \n\t   To deal with this we first perform a redundant read of the encoded \n\t   ASN.1 portion, allowing us to return a CRYPT_ERROR_BADDATA in most \n\t   cases where the problem is a corrupted/invalid encoding rather than \n\t   a generic CRYPT_ERROR_SIGNATURE */\n\tsMemConnect( &mdStream, encodedMD, encodedMdLength );\n\tstatus = readMessageDigest( &mdStream, &dummyHashAlgo, dummyHashBuffer, \n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE, &dummyHashSize );\n\tsMemDisconnect( &mdStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( encodedMdLength != recreatedMdLength || \\\n\t\t!compareDataConstTime( encodedMD, recreatedMD, encodedMdLength ) )\n\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\n\tzeroise( encodedMD, 32 + CRYPT_MAX_HASHSIZE );\n\tzeroise( recreatedMD, 32 + CRYPT_MAX_HASHSIZE );\n\n\treturn( status );\n\t}\n\n/* Make sure that the recovered signature data matches the data that we \n   originally signed.  The rationale behind this operation is covered (in \n   great detail) in ctx_rsa.c */\n\nstatic int checkRecoveredSignature( IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( sigDataLen ) const void *sigData,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int sigDataLen,\n\t\t\t\t\t\t\t\t\tIN_BUFFER( sigLen ) const void *signature,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_PKC const int sigLen )\n\t{\n\tBYTE recoveredSignature[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( sigData, sigDataLen ) );\n\tassert( isReadPtrDynamic( signature, sigLen ) );\n\n\tREQUIRES( sigDataLen >= MIN_PKCSIZE && sigDataLen <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES( sigLen >= MIN_PKCSIZE && sigLen <= CRYPT_MAX_PKCSIZE );\n\n\t/* Recover the original signature data, unless we're in the unlikely \n\t   situation that the key isn't valid for signature checking */\n\tREQUIRES( rangeCheck( sigLen, 1, CRYPT_MAX_PKCSIZE ) );\n\tmemcpy( recoveredSignature, signature, sigLen );\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_CTX_SIGCHECK, \n\t\t\t\t\t\t\t  recoveredSignature, sigLen );\n\tif( status == CRYPT_ERROR_PERMISSION || status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* The key can't be used for signature checking, there's not much \n\t\t   that we can do */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\t/* Make sure that the recovered data matches the original data */\n\tif( sigDataLen != sigLen || \\\n\t\t!compareDataConstTime( sigData, recoveredSignature, sigLen ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Signature consistency check failed\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tzeroise( recoveredSignature, CRYPT_MAX_PKCSIZE );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSignature Mechanisms \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform signing.  There are several variations of this that are handled \n   through common signature mechanism functions */\n\ntypedef enum { SIGN_NONE, SIGN_PKCS1, SIGN_SSL, SIGN_LAST } SIGN_TYPE;\n\n/* Perform PKCS #1 signing/sig.checking */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sign( INOUT MECHANISM_SIGN_INFO *mechanismInfo, \n\t\t\t\t IN_ENUM( SIGN ) const SIGN_TYPE type )\n\t{\n\tCRYPT_ALGO_TYPE hashAlgo DUMMY_INIT;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n#ifdef USE_SSL\n\tBYTE hash2[ CRYPT_MAX_HASHSIZE + 8 ];\n#endif /* USE_SSL */\n\tBYTE preSigData[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBOOLEAN_INT sideChannelProtectionLevel DUMMY_INIT;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint hashSize, length, status;\n#ifdef USE_SSL\n\tint hashSize2 DUMMY_INIT, i, LOOP_ITERATOR; \n#endif /* USE_SSL */\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\tREQUIRES( isEnumRange( type, SIGN ) );\n\n\t/* Clear return value */\n\tif( mechanismInfo->signature != NULL )\n\t\t{\n\t\tmemset( mechanismInfo->signature, 0,\n\t\t\t\tmechanismInfo->signatureLength );\n\t\t}\n\n\t/* Get various algorithm and config parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->signContext, NULL,\n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getHashAlgoParams( mechanismInfo->hashContext,\n\t\t\t\t\t\t\t\t\t&hashAlgo, NULL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( mechanismInfo->signContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &sideChannelProtectionLevel,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_MISC_SIDECHANNELPROTECTION );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\tCFI_CHECK_UPDATE( \"getPkcAlgoParams\" );\n\n\t/* If this is just a length check, we're done */\n\tif( mechanismInfo->signature == NULL )\n\t\t{\n\t\tmechanismInfo->signatureLength = length;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Get the hash data and determine the encoded payload size */\n\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( mechanismInfo->hashContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashSize = msgData.length;\n#ifdef USE_SSL\n\tif( type == SIGN_SSL )\n\t\t{\n\t\tsetMessageData( &msgData, hash2, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( mechanismInfo->hashContext2,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thashSize2 = msgData.length;\n\t\t}\n#endif /* USE_SSL */\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Encode the payload as required */\n\tsMemOpen( &stream, mechanismInfo->signature, length );\n\tswitch( type )\n\t\t{\n\t\tcase SIGN_PKCS1:\n\t\t\tstatus = encodePKCS1( &stream, hashAlgo, hash, hashSize, \n\t\t\t\t\t\t\t\t  length );\n\t\t\tCFI_CHECK_UPDATE( \"encodePKCS1\" );\n\t\t\tbreak;\n\n#ifdef USE_SSL\n\t\tcase SIGN_SSL:\n\t\t\tREQUIRES( hashAlgo == CRYPT_ALGO_MD5 );\n\n\t\t\t/* Encode the payload using the PKCS #1 SSL format:\n\n\t\t\t\t[ 0 ][ 1 ][ 0xFF padding ][ 0 ][ MD5 hash ][ SHA1 hash ] */\n\t\t\tsputc( &stream, 0 );\n\t\t\tsputc( &stream, 1 );\n\t\t\tLOOP_EXT( i = 0, i < length - ( hashSize + hashSize2 + 3 ), i++,\n\t\t\t\t\t  CRYPT_MAX_PKCSIZE )\n\t\t\t\tsputc( &stream, 0xFF );\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tsputc( &stream, 0 );\n\t\t\tswrite( &stream, hash, hashSize );\n\t\t\tstatus = swrite( &stream, hash2, hashSize2 );\n\t\t\tCFI_CHECK_UPDATE( \"encodePKCS1\" );\n\t\t\tbreak;\n#endif /* USE_SSL */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tENSURES( cryptStatusError( status ) || stell( &stream ) == length );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->signature, mechanismInfo->signatureLength );\n\t\treturn( status );\n\t\t}\n\n\t/* If we're using side-channel protection remember a copy of the \n\t   signature data for later so that we can check it against the \n\t   recovered signature data */\n\tif( sideChannelProtectionLevel > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( length, 1, CRYPT_MAX_PKCSIZE ) );\n\t\tmemcpy( preSigData, mechanismInfo->signature, length );\n\t\t}\n\n\t/* Sign the data */\n\tstatus = krnlSendMessage( mechanismInfo->signContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_SIGN, mechanismInfo->signature,\n\t\t\t\t\t\t\t  length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( mechanismInfo->signature, mechanismInfo->signatureLength );\n\t\treturn( status );\n\t\t}\n\tmechanismInfo->signatureLength = length;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_SIGN\" );\n\n\t/* If we're using side-channel protection check that the signature \n\t   verifies */\n\tif( sideChannelProtectionLevel > 0 )\n\t\t{\n\t\tstatus = checkRecoveredSignature( mechanismInfo->signContext, \n\t\t\t\t\t\t\t\t\t\t  preSigData, length,\n\t\t\t\t\t\t\t\t\t\t  mechanismInfo->signature, length );\n\t\tzeroise( preSigData, CRYPT_MAX_PKCSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( mechanismInfo->signature, length );\n\t\t\tmechanismInfo->signatureLength = 0;\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkRecoveredSignature\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"getPkcAlgoParams\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE_S\", \"encodePKCS1\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_SIGN\", \n\t\t\t\t\t\t\t\t\t\"checkRecoveredSignature\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sigcheck( INOUT MECHANISM_SIGN_INFO *mechanismInfo, \n\t\t\t\t\t IN_ENUM( SIGN ) const SIGN_TYPE type )\n\t{\n\tCRYPT_ALGO_TYPE contextHashAlgo DUMMY_INIT;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE decryptedSignature[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, hashSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\t\n\tREQUIRES( isEnumRange( type, SIGN ) );\n\n\t/* Get various algorithm parameters */\n\tstatus = getPkcAlgoParams( mechanismInfo->signContext, NULL,\n\t\t\t\t\t\t\t   &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getHashAlgoParams( mechanismInfo->hashContext,\n\t\t\t\t\t\t\t\t\t&contextHashAlgo, NULL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( mechanismInfo->hashContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\thashSize = msgData.length;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length > MIN_PKCSIZE && length <= CRYPT_MAX_PKCSIZE );\n\tCFI_CHECK_UPDATE( \"getPkcAlgoParams\" );\n\n\t/* Format the input data as required for the signatue check to work */\n\tstatus = adjustPKCS1Data( decryptedSignature, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\tmechanismInfo->signature, mechanismInfo->signatureLength,\n\t\t\t\t\tlength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"adjustPKCS1Data\" );\n\n\t/* Recover the signed data */\n\tstatus = krnlSendMessage( mechanismInfo->signContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_SIGCHECK, decryptedSignature,\n\t\t\t\t\t\t\t  length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_SIGCHECK\" );\n\n\t/* Decode the payload as required */\n\tsMemConnect( &stream, decryptedSignature, length );\n\tswitch( type )\n\t\t{\n\t\tcase SIGN_PKCS1:\n\t\t\t/* The payload is an ASN.1-encoded hash, process it very \n\t\t\t   carefully */\n\t\t\tstatus = decodePKCS1( &stream, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tstatus = compareHashInfo( &stream, contextHashAlgo, hash, \n\t\t\t\t\t\t\t\t\t  hashSize );\n\t\t\tCFI_CHECK_UPDATE( \"compareHashInfo\" );\n\t\t\tbreak;\n\n#ifdef USE_SSL\n\t\tcase SIGN_SSL:\n\t\t\t{\n\t\t\tBYTE hash2[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t\tREQUIRES( contextHashAlgo == CRYPT_ALGO_MD5 );\n\n\t\t\t/* The payload is [ MD5 hash ][ SHA1 hash ] */\n\t\t\tstatus = decodePKCS1( &stream, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\tstatus = sread( &stream, hash, 16 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = sread( &stream, hash2, 20 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\n\t\t\t/* Make sure that the two hash values match */\n\t\t\tsetMessageData( &msgData, hash, 16 );\n\t\t\tstatus = krnlSendMessage( mechanismInfo->hashContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_HASH );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tsetMessageData( &msgData, hash2, 20 );\n\t\t\t\tstatus = krnlSendMessage( mechanismInfo->hashContext2, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_HASH );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* The compare-hash operations return a generic CRYPT_OK/\n\t\t\t\t   CRYPT_ERROR, convert it to a more specific error code for \n\t\t\t\t   the operation that we're performing */\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( sMemDataLeft( &stream ) != 0 )\n\t\t\t\t\t{\n\t\t\t\t\t/* Make sure that's all that there is.  This is checked \n\t\t\t\t\t   in compareHashInfo() for standard signatures but we \n\t\t\t\t\t   have to perform the check explicitly for SSL-style \n\t\t\t\t\t   signatures */\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* Clean up */\n\t\t\tzeroise( hash2, CRYPT_MAX_HASHSIZE );\n\t\t\tCFI_CHECK_UPDATE( \"compareHashInfo\" );\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_SSL */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tsMemDisconnect( &stream );\n\n\t/* Clean up */\n\tzeroise( decryptedSignature, CRYPT_MAX_PKCSIZE );\n\tzeroise( hash, CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"getPkcAlgoParams\", \n\t\t\t\t\t\t\t\t\t\"adjustPKCS1Data\", \"IMESSAGE_CTX_SIGCHECK\", \n\t\t\t\t\t\t\t\t\t\"compareHashInfo\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signPKCS1( STDC_UNUSED void *dummy, \n\t\t\t   INOUT MECHANISM_SIGN_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\treturn( sign( mechanismInfo, SIGN_PKCS1 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint sigcheckPKCS1( STDC_UNUSED void *dummy, \n\t\t\t\t   INOUT MECHANISM_SIGN_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\treturn( sigcheck( mechanismInfo, SIGN_PKCS1 ) );\n\t}\n\n#ifdef USE_SSL\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signSSL( STDC_UNUSED void *dummy, \n\t\t\t INOUT MECHANISM_SIGN_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\treturn( sign( mechanismInfo, SIGN_SSL ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint sigcheckSSL( STDC_UNUSED void *dummy, \n\t\t\t\t INOUT MECHANISM_SIGN_INFO *mechanismInfo )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\treturn( sigcheck( mechanismInfo, SIGN_SSL ) );\n\t}\n#endif /* USE_SSL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSignature Self-test Functions \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* Test signature mechanisms */\n\ntypedef enum {\n\tTEST_NONE,\t\t\t\t/* No data block manipulation type */\n\tTEST_NORMAL,\t\t\t/* Standard test */\n\tTEST_CORRUPT_START,\t\t/* Corrupt starting byte */\n\tTEST_CORRUPT_BLOCKTYPE,\t/* Corrupt block type */\n\tTEST_CORRUPT_PADDING,\t/* Corrupt padding data */\n\tTEST_CORRUPT_END,\t\t/* Corrupt ending byte */\n\tTEST_CORRUPT_OID,\t\t/* Corrupt encoded OID data */\n\tTEST_CORRUPT_HASH,\t\t/* Corrupt hash value */\n\tTEST_LAST\t\t\t\t/* Last possible manipulation type */\n\t} TEST_TYPE;\n\nstatic void manipulateDataBlock( INOUT_BUFFER_FIXED( length ) BYTE *buffer,\n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int length,\n\t\t\t\t\t\t\t\t IN_LENGTH_PKC const int payloadStart,\n\t\t\t\t\t\t\t\t IN_ENUM( TEST ) const TEST_TYPE testType )\n\t{\n\tassert( isWritePtr( buffer, length ) );\n\n\tREQUIRES_V( length > 0 && length <= CRYPT_MAX_PKCSIZE );\n\tREQUIRES_V( payloadStart >= 20 && payloadStart < length );\n\tREQUIRES_V( isEnumRange( testType, TEST ) );\n\n\tswitch( testType )\n\t\t{\n\t\tcase TEST_NORMAL:\n\t\t\t/* Standard test */\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_START:\n\t\t\t/* Corrupt the PKCS #1 leading zero */\n\t\t\tbuffer[ 0 ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_BLOCKTYPE:\n\t\t\t/* Corrupt the PKCS #1 block type */\n\t\t\tbuffer[ 1 ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_PADDING:\n\t\t\t/* Corrupt the PKCS #1 padding.  This is already at 0xFF so we \n\t\t\t   decrement rather than increment the value */\n\t\t\tbuffer[ 30 ]--;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_END:\n\t\t\t/* Corrupt the PKCS #1 trailing zero.  The location is a bit \n\t\t\t   complex to evaluate since the hash value is preceded by a\n\t\t\t   variable-length OID, the following is the value for SHA-1 */\n\t\t\tassert( buffer[ payloadStart - ( 15 + 1 ) ] == 0 );\n\t\t\tbuffer[ payloadStart - ( 15 + 1 ) ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_OID:\n\t\t\t/* Corrupt the OID/ASN.1 data that precedes the hash value, see \n\t\t\t   above for the magic value used */\n\t\t\tbuffer[ payloadStart - 10 ]++;\n\t\t\tbreak;\n\n\t\tcase TEST_CORRUPT_HASH:\n\t\t\t/* Corrupt the hash value */\n\t\t\tbuffer[ payloadStart + 8 ]++;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError_Void();\n\t\t}\n\t}\n\nCHECK_RETVAL \\\nstatic int testPKCS1( IN_ENUM( TEST ) const TEST_TYPE testType )\n\t{\n\tconst BYTE hash[] = \\\n\t\t{ 0x54, 0xC8, 0x85, 0x09, 0x78, 0x7D, 0xF6, 0x50, \n\t\t  0x23, 0x7C, 0x94, 0xD0, 0x19, 0x47, 0x06, 0xE0,\n\t\t  0xCD, 0x24, 0xD5, 0x80 };\n \tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tSTREAM stream;\n\tint length = 256, status;\n\n\tREQUIRES( isEnumRange( testType, TEST ) );\n\n\t/* Create the PKCS #1 signature block */\n\tsMemOpen( &stream, buffer, length );\n\tstatus = encodePKCS1( &stream, CRYPT_ALGO_SHA1, hash, 20, length );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Manipulate the data as required */\n\tmanipulateDataBlock( buffer, length, length - 20, testType );\n\n\t/* Verify the signature block and make sure that we got back what we \n\t   put in */\n\tsMemConnect( &stream, buffer, length );\n\tstatus = decodePKCS1( &stream, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( compareHashInfo( &stream, CRYPT_ALGO_SHA1, hash, 20 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint signSelftest( STDC_UNUSED void *dummy, \n\t\t\t\t  INOUT MECHANISM_SIGN_INFO *mechanismInfo )\n\t{\n\tint status;\n\n\tUNUSED_ARG( dummy );\n\tassert( isWritePtr( mechanismInfo, sizeof( MECHANISM_SIGN_INFO ) ) );\n\n\tstatus = testPKCS1( TEST_NORMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_PRINT(( \"Mechanism self-test for PKCS1 sig/sigcheck \"\n\t\t\t\t\t  \"mechanism failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n\tstatus = testPKCS1( TEST_CORRUPT_START );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_BLOCKTYPE );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_PADDING );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_END );\n\tif( status == CRYPT_ERROR_BADDATA )\n\t\tstatus = testPKCS1( TEST_CORRUPT_OID );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\tstatus = testPKCS1( TEST_CORRUPT_HASH );\n\tif( status != CRYPT_ERROR_SIGNATURE )\n\t\t{\n\t\tDEBUG_PRINT(( \"Data corruption self-test for PKCS1 sig/sigcheck \"\n\t\t\t\t\t  \"mechanism failed.\\n\" ));\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n"
  },
  {
    "path": "deps/cl345/mechs/obj_qry.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEncoded Object Query Routines\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2008\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_CMS\n\n/* Get information on an ASN.1 object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getObjectInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT QUERY_INFO *queryInfo )\n\t{\n\tconst long startPos = stell( stream );\n\tlong value;\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* We always need at least MIN_CRYPT_OBJECTSIZE more bytes to do\n\t   anything */\n\tif( sMemDataLeft( stream ) < MIN_CRYPT_OBJECTSIZE )\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\n\t/* Get the object's length and make sure that its encoding is valid, \n\t   which also checks that all of the object's data is present */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *objectPtr;\n\t\n\t\tstatus = sMemGetDataBlockAbs( stream, startPos, &objectPtr, length );\n#ifndef CONFIG_FUZZ\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = checkObjectEncoding( objectPtr, length );\n#endif /* CONFIG_FUZZ */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get the type and version information */\n\tqueryInfo->formatType = CRYPT_FORMAT_CRYPTLIB;\n\tqueryInfo->size = length;\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treadGenericHole( stream, NULL, 16, tag );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isIntegerRange( value ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->version = ( int ) value;\n\tswitch( tag )\n\t\t{\n\t\tcase BER_SEQUENCE:\n\t\t\t/* This could be a signature or a PKC-encrypted key, see what\n\t\t\t   follows */\n\t\t\tswitch( value )\n\t\t\t\t{\n\t\t\t\tcase KEYTRANS_VERSION:\n\t\t\t\tcase KEYTRANS_EX_VERSION:\n\t\t\t\t\tqueryInfo->type = CRYPT_OBJECT_PKCENCRYPTED_KEY;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase SIGNATURE_VERSION:\n\t\t\t\tcase SIGNATURE_EX_VERSION:\n\t\t\t\t\tqueryInfo->type = CRYPT_OBJECT_SIGNATURE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\t}\n\t\t\tif( value == KEYTRANS_VERSION || value == SIGNATURE_VERSION )\n\t\t\t\tqueryInfo->formatType = CRYPT_FORMAT_CMS;\n\t\t\tbreak;\n\n\t\tcase MAKE_CTAG( CTAG_RI_KEYAGREE ):\n\t\t\t/* It's CMS' wierd X9.42-inspired key agreement mechanism, we\n\t\t\t   can't do much with this (mind you neither can anyone else)\n\t\t\t   so we should probably really treat it as a \n\t\t\t   CRYPT_ERROR_BADDATA if we encounter it rather than just \n\t\t\t   ignoring it */\n\t\t\tqueryInfo->type = CRYPT_OBJECT_NONE;\n\t\t\tDEBUG_DIAG(( \"Found keyAgreeRecipientInfo\" ));\n\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\tbreak;\n\n\t\tcase MAKE_CTAG( CTAG_RI_PWRI ):\n\t\t\tqueryInfo->type = CRYPT_OBJECT_ENCRYPTED_KEY;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tqueryInfo->type = CRYPT_OBJECT_NONE;\n\t\t\tif( tag > MAKE_CTAG( CTAG_RI_PWRI ) && \\\n\t\t\t\ttag <= MAKE_CTAG( CTAG_RI_MAX ) )\n\t\t\t\t{\n\t\t\t\t/* This is probably a new RecipientInfo type, skip it */\n\t\t\t\tDEBUG_DIAG(( \"Found unknown RecipientInfo %X\", tag ));\n\t\t\t\tassert_nofuzz( DEBUG_WARN );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Reset the stream for the caller before we exit */\n\tsseek( stream, startPos );\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_CMS */\n\n#ifdef USE_PGP\n\n/* Get information on a PGP data object.  This doesn't reset the stream like\n   the ASN.1 equivalent because the PGP header is complex enough that it\n   can't be read inline like the ASN.1 header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getPgpPacketInfo( INOUT STREAM *stream, \n\t\t\t\t\t  OUT QUERY_INFO *queryInfo )\n\t{\n\tconst long startPos = stell( stream );\n\tlong offset, length;\n\tint ctb, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the packet header and extract information from the CTB.  Note\n\t   that the assignment of version numbers is speculative only because\n\t   it's possible to use PGP 2.x packet headers to wrap up OpenPGP\n\t   packets */\n\tstatus = pgpReadPacketHeader( stream, &ctb, &length, 8, \n\t\t\t\t\t\t\t\t  MAX_INTLENGTH - 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->formatType = CRYPT_FORMAT_PGP;\n\tqueryInfo->version = pgpGetPacketVersion( ctb );\n\tstatus = offset = stell( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->size = ( offset - startPos ) + length;\n\tswitch( pgpGetPacketType( ctb ) )\n\t\t{\n\t\tcase PGP_PACKET_SKE:\n\t\t\tqueryInfo->type = CRYPT_OBJECT_ENCRYPTED_KEY;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_PKE:\n\t\t\tqueryInfo->type = CRYPT_OBJECT_PKCENCRYPTED_KEY;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_SIGNATURE:\n\t\t\tqueryInfo->type = CRYPT_OBJECT_SIGNATURE;\n\t\t\tbreak;\n\n\t\tcase PGP_PACKET_SIGNATURE_ONEPASS:\n\t\t\t/* First half of a one-pass signature, this is given a special\n\t\t\t   type of 'none' since it's not a normal packet */\n\t\t\tqueryInfo->type = CRYPT_OBJECT_NONE;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tDEBUG_DIAG(( \"Found unrecognised ctb %X\", ctb ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Make sure that all of the data is present without resetting the \n\t   stream */\n\treturn( ( sMemDataLeft( stream ) < length ) ? \\\n\t\t\tCRYPT_ERROR_UNDERFLOW : CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tObject Query Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_CMS\n\n/* Low-level object query functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint queryAsn1Object( INOUT void *streamPtr, OUT QUERY_INFO *queryInfo )\n\t{\n\tQUERY_INFO basicQueryInfo;\n\tSTREAM *stream = streamPtr;\n\tconst long startPos = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Determine basic object information.  This also verifies that all of \n\t   the object data is present in the stream */\n\tstatus = getObjectInfo( stream, &basicQueryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Call the appropriate routine to find out more about the object */\n\tswitch( basicQueryInfo.type )\n\t\t{\n\t\tcase CRYPT_OBJECT_ENCRYPTED_KEY:\n\t\t\t{\n\t\t\tconst READKEK_FUNCTION readKekFunction = \\\n\t\t\t\t\t\t\t\t\tgetReadKekFunction( KEYEX_CMS );\n\n\t\t\tif( readKekFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readKekFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_PKCENCRYPTED_KEY:\n\t\t\t{\n\t\t\tconst READKEYTRANS_FUNCTION readKeytransFunction = \\\n\t\t\t\tgetReadKeytransFunction( ( basicQueryInfo.formatType == CRYPT_FORMAT_CMS ) ? \\\n\t\t\t\t\t\t\t\t\t\t KEYEX_CMS : KEYEX_CRYPTLIB );\n\n\t\t\tif( readKeytransFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readKeytransFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_SIGNATURE:\n\t\t\t{\n\t\t\tconst READSIG_FUNCTION readSigFunction = \\\n\t\t\t\tgetReadSigFunction( ( basicQueryInfo.formatType == CRYPT_FORMAT_CMS ) ? \\\n\t\t\t\t\t\t\t\t\tSIGNATURE_CMS : SIGNATURE_CRYPTLIB );\n\n\t\t\tif( readSigFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readSigFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_NONE:\n\t\t\t/* New, unrecognised RecipientInfo type */\n\t\t\tstatus = readUniversal( stream );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tstartPos + basicQueryInfo.size != stell( stream ) )\n\t\t{\n\t\t/* Make sure that the given size of the object matches what we've \n\t\t   actually processed */\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tsseek( stream, startPos );\n\n\t/* Augment the per-object query information with the basic query \n\t   information that we got earlier */\n\tqueryInfo->formatType = basicQueryInfo.formatType;\n\tqueryInfo->type = basicQueryInfo.type;\n\tqueryInfo->size = basicQueryInfo.size;\n\tqueryInfo->version = basicQueryInfo.version;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_CMS */\n\n#ifdef USE_PGP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint queryPgpObject( INOUT void *streamPtr, OUT QUERY_INFO *queryInfo )\n\t{\n\tQUERY_INFO basicQueryInfo;\n\tSTREAM *stream = streamPtr;\n\tconst long startPos = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Determine basic object information.  This also verifies that all of \n\t   the object data is present in the stream */\n\tstatus = getPgpPacketInfo( stream, &basicQueryInfo );\n\tsseek( stream, startPos );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Call the appropriate routine to find out more about the object */\n\tswitch( basicQueryInfo.type )\n\t\t{\n\t\tcase CRYPT_OBJECT_ENCRYPTED_KEY:\n\t\t\t{\n\t\t\tconst READKEK_FUNCTION readKekFunction = \\\n\t\t\t\t\t\t\t\t\tgetReadKekFunction( KEYEX_PGP );\n\n\t\t\tif( readKekFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readKekFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_PKCENCRYPTED_KEY:\n\t\t\t{\n\t\t\tconst READKEYTRANS_FUNCTION readKeytransFunction = \\\n\t\t\t\t\t\t\t\t\tgetReadKeytransFunction( KEYEX_PGP );\n\n\t\t\tif( readKeytransFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readKeytransFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_SIGNATURE:\n\t\t\t{\n\t\t\tconst READSIG_FUNCTION readSigFunction = \\\n\t\t\t\t\t\t\t\t\tgetReadSigFunction( SIGNATURE_PGP );\n\n\t\t\tif( readSigFunction == NULL )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tstatus = readSigFunction( stream, queryInfo );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_OBJECT_NONE:\n\t\t\t/* First half of a one-pass signature */\n\t\t\tstatus = readPgpOnepassSigPacket( stream, queryInfo );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tstartPos + basicQueryInfo.size != stell( stream ) )\n\t\t{\n\t\t/* Make sure that the given size of the object matches what we've \n\t\t   actually processed */\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tsseek( stream, startPos );\n\n\t/* Augment the per-object query information with the basic query \n\t   information that we got earlier */\n\tqueryInfo->formatType = basicQueryInfo.formatType;\n\tif( queryInfo->type == CRYPT_OBJECT_NONE )\n\t\t{\n\t\t/* The non-type CRYPT_OBJECT_NONE denotes the first half of a one-\n\t\t   pass signature packet, in which case the actual type is given in\n\t\t   the packet data */\n\t\tqueryInfo->type = basicQueryInfo.type;\n\t\t}\n\tqueryInfo->size = basicQueryInfo.size;\n\tif( queryInfo->version == 0 )\n\t\t{\n\t\t/* PGP has multiple packet version numbers sprayed all over the\n\t\t   place, and just because an outer version is X doesn't mean that\n\t\t   a subsequent inner version can't be Y.  The information is really\n\t\t   only used to control the formatting of what gets read, so we\n\t\t   just report the first version that we encounter */\n\t\tqueryInfo->version = basicQueryInfo.version;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tExternal Object Query Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_INT_CMS ) || defined( USE_PGP )\n\n/* Query an object.  This is just a wrapper that provides an external\n   interface for the lower-level object-query routines */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1, 3 ) ) \\\nC_RET cryptQueryObject( C_IN void C_PTR objectData,\n\t\t\t\t\t\tC_IN int objectDataLength,\n\t\t\t\t\t\tC_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo )\n\t{\n\tQUERY_INFO queryInfo DUMMY_INIT_STRUCT;\t/* If USE_PGP undef'd */\n\tSTREAM stream;\n\tint value, length = objectDataLength, status;\n\n\t/* Perform basic error checking and clear the return value */\n\tif( objectDataLength <= MIN_CRYPT_OBJECTSIZE || \\\n\t\tobjectDataLength >= MAX_BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtrDynamic( objectData, objectDataLength ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( !isWritePtr( cryptObjectInfo, sizeof( CRYPT_OBJECT_INFO ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\tmemset( cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );\n\n\t/* Query the object.  This is just a wrapper for the lower-level object-\n\t   query functions.  Note that we use sPeek() rather than peekTag() \n\t   because we want to continue processing (or at least checking for) PGP \n\t   data if it's no ASN.1 */\n\tsMemConnect( &stream, ( void * ) objectData, length );\n\tstatus = value = sPeek( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tif( value == BER_SEQUENCE || value == MAKE_CTAG( CTAG_RI_PWRI ) )\n\t\tstatus = queryAsn1Object( &stream, &queryInfo );\n\telse\n\t\t{\n#ifdef USE_PGP\n\t\tstatus = queryPgpObject( &stream, &queryInfo );\n#else\n\t\tstatus = CRYPT_ERROR_BADDATA;\n#endif /* USE_PGP */\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Copy the externally-visible fields across */\n\tcryptObjectInfo->objectType = queryInfo.type;\n\tcryptObjectInfo->cryptAlgo = queryInfo.cryptAlgo;\n\tcryptObjectInfo->cryptMode = queryInfo.cryptMode;\n\tif( queryInfo.type == CRYPT_OBJECT_SIGNATURE )\n\t\tcryptObjectInfo->hashAlgo = queryInfo.hashAlgo;\n\tif( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY && \\\n\t\tqueryInfo.saltLength > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( queryInfo.saltLength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( cryptObjectInfo->salt, queryInfo.salt, \n\t\t\t\tqueryInfo.saltLength );\n\t\tcryptObjectInfo->saltSize = queryInfo.saltLength;\n\t\tcryptObjectInfo->iterations = queryInfo.keySetupIterations;\n\t\tif( queryInfo.keySetupAlgo != CRYPT_ALGO_NONE )\n\t\t\tcryptObjectInfo->hashAlgo = queryInfo.keySetupAlgo;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tStub Functions for non-CMS/PGP Use\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nC_RET cryptQueryObject( C_IN void C_PTR objectData,\n\t\t\t\t\t\tC_IN int objectDataLength,\n\t\t\t\t\t\tC_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo )\n\t{\n\tUNUSED_ARG( objectData );\n\tUNUSED_ARG( cryptObjectInfo );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* USE_INT_CMS || USE_PGP */\n"
  },
  {
    "path": "deps/cl345/mechs/sign.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSignature Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and determine the format of the signed data */\n\nCHECK_RETVAL_ENUM( CRYPT_FORMAT ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic CRYPT_FORMAT_TYPE getFormatType( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int dataLength )\n\t{\n\tSTREAM stream;\n\tlong value;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\t\n\tREQUIRES_EXT( dataLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\t  dataLength < MAX_BUFFER_SIZE, CRYPT_FORMAT_NONE );\n\n\tsMemConnect( &stream, data, min( 16, dataLength ) );\n\n\t/* Figure out what we've got.  A PKCS #7/CMS/SMIME signature begins:\n\n\t\tcryptlibSignature ::= SEQUENCE {\n\t\t\tversion\t\tINTEGER (3),\n\t\t\tkeyID [ 0 ]\tOCTET STRING\n\n\t   while a CMS signature begins:\n\n\t\tcmsSignature ::= SEQUENCE {\n\t\t\tversion\t\tINTEGER (1),\n\t\t\tdigestAlgo\tSET OF {\n\n\t   which allows us to determine which type of object we have.  Note that \n\t   we use sPeek() rather than peekTag() because we want to continue\n\t   processing (or at least checking for) PGP data if it's no ASN.1 */\n\tif( sPeek( &stream ) == BER_SEQUENCE )\n\t\t{\n\t\tCRYPT_FORMAT_TYPE formatType;\n\n\t\treadSequence( &stream, NULL );\n\t\tstatus = readShortInteger( &stream, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( CRYPT_FORMAT_NONE );\n\t\t\t}\n\t\tswitch( value )\n\t\t\t{\n\t\t\tcase SIGNATURE_VERSION:\n\t\t\t\tformatType = CRYPT_FORMAT_CMS;\n\t\t\t\tbreak;\n\n\t\t\tcase SIGNATURE_EX_VERSION:\n\t\t\t\tformatType = CRYPT_FORMAT_CRYPTLIB;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tformatType = CRYPT_FORMAT_NONE;\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\n\t\treturn( formatType );\n\t\t}\n\n#ifdef USE_PGP\n\t/* It's not ASN.1 data, check for PGP data */\n\tstatus = pgpReadPacketHeader( &stream, NULL, &value, 30, 8192 );\n\tif( cryptStatusOK( status ) && value > 30 && value < 8192 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( CRYPT_FORMAT_PGP );\n\t\t}\n#endif /* USE_PGP */\n\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_FORMAT_NONE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate a Signature \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create an extended signature type */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptCreateSignatureEx( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\t  C_IN int signatureMaxLength,\n\t\t\t\t\t\t\t  C_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\t  C_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_HANDLE extraData )\n\t{\n\tSIGPARAMS sigParams;\n\tBOOLEAN hasSigParams = FALSE;\n\tint value, status;\n\n\t/* Perform basic error checking.  We have to use an internal message to\n\t   check for signing capability because the DLP algorithms have\n\t   specialised data-formatting requirements that can't normally be\n\t   directly accessed via external messages, and even the non-DLP\n\t   algorithms may be internal-use-only if there's a certificate attached \n\t   to the context.  To make sure that the context is OK we first check \n\t   its external accessibility by performing a dummy attribute read.  \n\t   Note that we can't safely use the certificate-type read performed \n\t   later on for this check because some error conditions (e.g. \"not a \n\t   certificate\") are valid in this case, but we don't want to have mess \n\t   with trying to distinguish OK-in-this-instance vs.not-OK error \n\t   conditions */\n\tif( signature != NULL )\n\t\t{\n\t\tif( signatureMaxLength <= MIN_CRYPT_OBJECTSIZE || \\\n\t\t\tsignatureMaxLength >= MAX_BUFFER_SIZE )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\tif( !isWritePtrDynamic( signature, signatureMaxLength ) )\n\t\t\treturn( CRYPT_ERROR_PARAM1 );\n\t\tmemset( signature, 0, MIN_CRYPT_OBJECTSIZE );\n\t\t}\n\telse\n\t\t{\n\t\tif( signatureMaxLength != 0 )\n\t\t\treturn( CRYPT_ERROR_PARAM2 );\n\t\t}\n\tif( !isWritePtr( signatureLength, sizeof( int ) ) )\n\t\treturn( CRYPT_ERROR_PARAM3 );\n\t*signatureLength = 0;\n\tif( formatType <= CRYPT_FORMAT_NONE || \\\n\t\tformatType >= CRYPT_FORMAT_LAST_EXTERNAL )\n\t\treturn( CRYPT_ERROR_PARAM4 );\n\tstatus = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &value, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );\n\tstatus = krnlSendMessage( signContext, IMESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  MESSAGE_CHECK_PKC_SIGN );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );\n\tstatus = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t  MESSAGE_CHECK_HASH );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_PARAM6 : status );\n\n\t/* Perform any required format-specific checking */\n\tswitch( formatType )\n\t\t{\n\t\tcase CRYPT_FORMAT_AUTO:\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\t/* If it's a cryptlib-format signature there can't be any extra\n\t\t\t   signing attributes present */\n\t\t\tif( extraData != CRYPT_UNUSED )\n\t\t\t\treturn( CRYPT_ERROR_PARAM7 );\n\t\t\tbreak;\n\n\t\tcase CRYPT_FORMAT_CMS:\n\t\tcase CRYPT_FORMAT_SMIME:\n\t\t\t{\n\t\t\tint certType;\t/* int vs.enum */\n\n\t\t\t/* Make sure that the signing context has a certificate attached \n\t\t\t   to it */\n\t\t\tstatus = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t( certType != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\t  certType != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\n\t\t\t/* Make sure that the extra data object is in order */\n\t\t\tif( extraData != CRYPT_USE_DEFAULT )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( extraData, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\tcertType != CRYPT_CERTTYPE_CMS_ATTRIBUTES )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM7 );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\t/* There's nothing specific to check for PGP signatures */\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Set up any optional signing parameters if required */\n\tif( extraData != CRYPT_UNUSED )\n\t\t{\n\t\tinitSigParams( &sigParams );\n\t\tif( extraData == CRYPT_USE_DEFAULT )\n\t\t\tsigParams.useDefaultAuthAttr = TRUE;\n\t\telse\n\t\t\tsigParams.iAuthAttr = extraData;\n\t\thasSigParams = TRUE;\n\t\t}\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\tinitSigParamsPGP( &sigParams, PGP_SIG_DATA, NULL, 0 );\n\t\thasSigParams = TRUE;\n\t\t}\n\n\t/* Call the low-level signature create function to create the\n\t   signature */\n\tstatus = iCryptCreateSignature( signature, signatureMaxLength,\n\t\t\t\t\tsignatureLength, formatType, signContext, hashContext, \n\t\t\t\t\thasSigParams ? &sigParams : NULL );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* Remap the error code to refer to the correct parameter */\n\t\tstatus = ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t CRYPT_ERROR_PARAM5 : CRYPT_ERROR_PARAM6;\n\t\t}\n\treturn( status );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\nC_RET cryptCreateSignature( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\tC_IN int signatureMaxLength,\n\t\t\t\t\t\t\tC_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT hashContext )\n\t{\n\tint status;\n\n\tstatus = cryptCreateSignatureEx( signature, signatureMaxLength,\n\t\t\t\t\t\t\t\t\t signatureLength, CRYPT_FORMAT_CRYPTLIB,\n\t\t\t\t\t\t\t\t\t signContext, hashContext,\n\t\t\t\t\t\t\t\t\t CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Remap parameter errors to the correct position */\n\t\tif( status == CRYPT_ERROR_PARAM5 )\n\t\t\tstatus = CRYPT_ERROR_PARAM4;\n\t\tif( status == CRYPT_ERROR_PARAM6 )\n\t\t\tstatus = CRYPT_ERROR_PARAM5;\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCheck a Signature \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check an extended signature type */\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCheckSignatureEx( C_IN void C_PTR signature,\n\t\t\t\t\t\t\t C_IN int signatureLength,\n\t\t\t\t\t\t\t C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t C_OUT_OPT CRYPT_HANDLE C_PTR extraData )\n\t{\n\tCRYPT_FORMAT_TYPE formatType;\n\tCRYPT_CERTIFICATE iExtraData DUMMY_INIT;\n\tCRYPT_CONTEXT sigCheckContext;\n\tint status;\n\n\t/* Perform basic error checking */\n\tif( signatureLength <= MIN_CRYPT_OBJECTSIZE || \\\n\t\tsignatureLength >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_PARAM2 );\n\tif( !isReadPtrDynamic( signature, signatureLength ) )\n\t\treturn( CRYPT_ERROR_PARAM1 );\n\tif( ( formatType = getFormatType( signature, \\\n\t\t\t\t\t\t\t\t\t  signatureLength ) ) == CRYPT_FORMAT_NONE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Clear return values */\n\tif( extraData != NULL )\n\t\t*extraData = CRYPT_UNUSED;\n\n\t/* Perform extended error checking */\n\tstatus = krnlSendMessage( sigCheckKey, MESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t  &sigCheckContext, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( sigCheckContext, IMESSAGE_CHECK,\n\t\t\t\t\t\t\t\t  NULL, MESSAGE_CHECK_PKC_SIGCHECK );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,\n\t\t\t\t\t\t\t\t  MESSAGE_CHECK_HASH );\n\t\tif( cryptArgError( status ) )\n\t\t\tstatus = CRYPT_ERROR_PARAM4;\n\t\t}\n\telse\n\t\t{\n\t\tif( cryptArgError( status ) )\n\t\t\tstatus = CRYPT_ERROR_PARAM3;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( formatType == CRYPT_FORMAT_CMS || \\\n\t\tformatType == CRYPT_FORMAT_SMIME )\n\t\t{\n\t\tint certType;\t/* int vs.enum */\n\n\t\t/* Make sure that the sig check key includes a certificate */\n\t\tstatus = krnlSendMessage( sigCheckKey, MESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\t\tif( cryptStatusError( status ) ||\n\t\t\t( certType != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t  certType != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\treturn( CRYPT_ERROR_PARAM3 );\n\t\t}\n\n\t/* Perform any required format-specific checking */\n\tswitch( formatType )\n\t\t{\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\t/* If it's a cryptlib-format signature there can't be any extra\n\t\t\t   signing attributes present */\n\t\t\tif( extraData != NULL )\n\t\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t\tbreak;\n\n\t\tcase CRYPT_FORMAT_CMS:\n\t\tcase CRYPT_FORMAT_SMIME:\n\t\t\tif( extraData != NULL )\n\t\t\t\t{\n\t\t\t\tif( !isWritePtr( extraData, sizeof( int ) ) )\n\t\t\t\t\treturn( CRYPT_ERROR_PARAM6 );\n\t\t\t\t*extraData = CRYPT_ERROR;\n\t\t\t\t}\n\t\t\tbreak;\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\t/* PGP doesn't have signing attributes */\n\t\t\tif( extraData != NULL )\n\t\t\t\treturn( CRYPT_ERROR_PARAM5 );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Call the low-level signature create function to check the signature */\n\tstatus = iCryptCheckSignature( signature, signatureLength, formatType, \n\t\t\t\t\t\tsigCheckKey, hashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t( extraData != NULL ) ? &iExtraData : NULL );\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* Remap the error code to refer to the correct parameter */\n\t\tstatus = ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t CRYPT_ERROR_PARAM3 : CRYPT_ERROR_PARAM4;\n\t\t}\n\tif( extraData == NULL )\n\t\treturn( status );\n\t\n\t/* The caller has requested to see the the recovered signing attributes, \n\t   make them externally visible.  Bailing out if this operation fails \n\t   may be a bit excessive in that the signature has already verified so \n\t   failing the whole operation just because we can't make auxiliary \n\t   attributes visible could be seen as overkill, however since the \n\t   caller has indicated an interest in the attributes it can be argued \n\t   that an inability to return them is as serious as a general sig.check \n\t   failure */\n\tstatus = krnlSendMessage( iExtraData, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_INTERNAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iExtraData, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*extraData = iExtraData;\n\n\treturn( CRYPT_OK );\n\t}\n\nC_CHECK_RETVAL C_NONNULL_ARG( ( 1 ) ) \\\nC_RET cryptCheckSignature( C_IN void C_PTR signature,\n\t\t\t\t\t\t   C_IN int signatureLength,\n\t\t\t\t\t\t   C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t   C_IN CRYPT_CONTEXT hashContext )\n\t{\n\treturn( cryptCheckSignatureEx( signature, signatureLength, sigCheckKey,\n\t\t\t\t\t\t\t\t   hashContext, NULL ) );\n\t}\n#endif /* USE_INT_CMS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal Import/Export Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Internal versions of the above.  These skip a lot of the explicit \n   checking done by the external versions (e.g. \"Is this value really a \n   handle to a valid PKC context?\") since they're only called by cryptlib \n   internal functions rather than being passed untrusted user data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptCreateSignature( OUT_BUFFER_OPT( signatureMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\t   IN_DATALENGTH_Z const int signatureMaxLength,\n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *signatureLength,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t   IN_OPT const SIGPARAMS *sigParams )\n\t{\n\tint certType, status;\t/* int vs.enum */\n\n\tassert( signature == NULL || \\\n\t\t\tisWritePtrDynamic( signature, signatureMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\tassert( sigParams == NULL || isReadPtr( sigParams, sizeof( SIGPARAMS ) ) );\n\n\tREQUIRES( ( signature == NULL && signatureMaxLength == 0 ) || \\\n\t\t\t  ( signature != NULL && \\\n\t\t\t\tsignatureMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tsignatureMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( ( formatType == CRYPT_FORMAT_CRYPTLIB || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_SSH || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_TLS12 ) && \\\n\t\t\t\tsigParams == NULL ) || \n\t\t\t  ( ( formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t\t  formatType == CRYPT_FORMAT_SMIME || \\\n\t\t\t\t  formatType == CRYPT_FORMAT_PGP || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_SSL ) && \\\n\t\t\t\tsigParams != NULL ) );\n\t\t\t  /* The sigParams structure is too complex to check fully here\n\t\t\t     so we check it in the switch statement below */\n\n\tANALYSER_HINT( signatureLength != NULL );\n\n\t/* Clear return value */\n\t*signatureLength = 0;\n\n\t/* If the signing context has a certificate chain attached then the \n\t   currently-selected certificate may not be the leaf certificate.  To \n\t   ensure that we use the correct certificate we lock the chain (which \n\t   both protects us from having the user select a different certificate \n\t   while we're using it and saves the selection state for when we later \n\t   unlock it) and explicitly select the leaf certificate.  Certificates \n\t   are used for formats other than the obvious CRYPT_FORMAT_CMS/\n\t   CRYPT_FORMAT_SMIME so we perform this operation unconditionally \n\t   rather than only for those two formats */\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &certType, CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There's no certificate of the required type attached */\n\t\tcertType = CRYPT_CERTTYPE_NONE;\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's a certificate chain, lock it and select the leaf \n\t\t   certificate */\n\t\tif( certType == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Call the low-level signature create function to create the signature */\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_CMS\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\tstatus = createSignature( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t  signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t  iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t  SIGNATURE_CRYPTLIB );\n\t\t\tbreak;\n\n\t\tcase CRYPT_FORMAT_CMS:\n\t\tcase CRYPT_FORMAT_SMIME:\n\t\t\t{\n\t\t\tREQUIRES( ( sigParams->iAuthAttr == CRYPT_ERROR && \\\n\t\t\t\t\t\tsigParams->useDefaultAuthAttr == FALSE ) || \\\n\t\t\t\t\t  ( sigParams->iAuthAttr == CRYPT_ERROR && \\\n\t\t\t\t\t\tsigParams->useDefaultAuthAttr == TRUE ) || \\\n\t\t\t\t\t  ( isHandleRangeValid( sigParams->iAuthAttr ) && \\\n\t\t\t\t\t    sigParams->useDefaultAuthAttr == FALSE ) );\n\t\t\tREQUIRES( sigParams->iTspSession == CRYPT_ERROR || \\\n\t\t\t\t\t  isHandleRangeValid( sigParams->iTspSession ) );\n\n\t\t\tstatus = createSignatureCMS( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t\t signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t\t iHashContext, \n\t\t\t\t\t\t\t\t\t\t sigParams->useDefaultAuthAttr, \n\t\t\t\t\t\t\t\t\t\t ( sigParams->iAuthAttr == CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED : sigParams->iAuthAttr,\n\t\t\t\t\t\t\t\t\t\t ( sigParams->iTspSession == CRYPT_ERROR ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED : sigParams->iTspSession, \n\t\t\t\t\t\t\t\t\t\t formatType );\n\t\t\t}\n\t\t\tbreak;\n#endif /* USE_INT_CMS */\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\tREQUIRES( sigParams->useDefaultAuthAttr == FALSE && \\\n\t\t\t\t\t  sigParams->iAuthAttr == CRYPT_ERROR && \\\n\t\t\t\t\t  sigParams->iTspSession == CRYPT_ERROR && \\\n\t\t\t\t\t  ( sigParams->sigType >= PGP_SIG_NONE && \\\n\t\t\t\t\t    sigParams->sigType < PGP_SIG_LAST ) && \\\n\t\t\t\t\t  sigParams->iSecondHash == CRYPT_ERROR );\n\n\t\t\tstatus = createSignaturePGP( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t\t signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t\t iHashContext, sigParams->sigAttributes,\n\t\t\t\t\t\t\t\t\t\t sigParams->sigAttributeSize,\n\t\t\t\t\t\t\t\t\t\t sigParams->sigType );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n#ifdef USE_SSL\n\t\tcase CRYPT_IFORMAT_SSL:\n\t\t\tREQUIRES( sigParams->useDefaultAuthAttr == FALSE && \\\n\t\t\t\t\t  sigParams->iAuthAttr == CRYPT_ERROR && \\\n\t\t\t\t\t  sigParams->iTspSession == CRYPT_ERROR && \\\n\t\t\t\t\t  sigParams->sigType == PGP_SIG_NONE && \\\n\t\t\t\t\t  isHandleRangeValid( sigParams->iSecondHash ) );\n\n\t\t\tstatus = createSignature( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t  signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t  iHashContext, sigParams->iSecondHash,\n\t\t\t\t\t\t\t\t\t  SIGNATURE_SSL );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IFORMAT_TLS12:\n\t\t\tREQUIRES( sigParams == NULL );\n\n\t\t\tstatus = createSignature( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t  signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t  iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t  SIGNATURE_TLS12 );\n\t\t\tbreak;\n#endif /* USE_SSL */\n\n#ifdef USE_SSH\n\t\tcase CRYPT_IFORMAT_SSH:\n\t\t\tstatus = createSignature( signature, signatureMaxLength, \n\t\t\t\t\t\t\t\t\t  signatureLength, iSignContext,\n\t\t\t\t\t\t\t\t\t  iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t  SIGNATURE_SSH );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* Catch any parameter errors that slip through */\n\t\tDEBUG_DIAG(( \"Signature creation return argError status\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( certType == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\t/* We're signing with a certificate chain, restore its state and \n\t\t   unlock it to allow others access.  If this fails there's not much \n\t\t   that we can do to recover so we don't do anything with the return \n\t\t   value */\n\t\t( void ) krnlSendMessage( iSignContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint iCryptCheckSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iSigCheckKey,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iHash2Context,\n\t\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_HANDLE *extraData )\n\t{\n\tCRYPT_CONTEXT sigCheckContext;\n\tint status;\n\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\n\tREQUIRES( signatureLength > 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isEnumRange( formatType, CRYPT_FORMAT ) );\n\tREQUIRES( isHandleRangeValid( iSigCheckKey ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( formatType == CRYPT_IFORMAT_SSL && \\\n\t\t\t\tisHandleRangeValid( iHash2Context ) && extraData == NULL ) || \\\n\t\t\t  ( ( formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t\t  formatType == CRYPT_FORMAT_SMIME || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_TLS12 ) && \\\n\t\t\t\tiHash2Context == CRYPT_UNUSED ) || \\\n\t\t\t  ( ( formatType == CRYPT_FORMAT_CRYPTLIB || \\\n\t\t\t\t  formatType == CRYPT_FORMAT_PGP || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_TLS12 || \\\n\t\t\t\t  formatType == CRYPT_IFORMAT_SSH ) && \\\n\t\t\t\tiHash2Context == CRYPT_UNUSED && extraData == NULL ) );\n\n\t/* Clear return value */\n\tif( extraData != NULL )\n\t\t*extraData = CRYPT_ERROR;\n\n\t/* Perform basic error checking */\n\tstatus = krnlSendMessage( iSigCheckKey, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t  &sigCheckContext, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Call the low-level signature check function to check the signature */\n\tswitch( formatType )\n\t\t{\n#ifdef USE_INT_CMS\n\t\tcase CRYPT_FORMAT_CRYPTLIB:\n\t\t\t/* For this call we have to pass in the original handle (which \n\t\t\t   may be a certificate with an attached public-key context) \n\t\t\t   rather than the raw context because the signature format uses \n\t\t\t   the subjectKeyIdentifier to identify the key, and that's only \n\t\t\t   available via the certificate */\n\t\t\tstatus = checkSignature( signature, signatureLength,\n\t\t\t\t\t\t\t\t\t iSigCheckKey, iHashContext,\n\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, SIGNATURE_CRYPTLIB );\n\t\t\tbreak;\n\n\t\tcase CRYPT_FORMAT_CMS:\n\t\tcase CRYPT_FORMAT_SMIME:\n\t\t\tif( extraData != NULL )\n\t\t\t\t*extraData = CRYPT_ERROR;\n\t\t\tstatus = checkSignatureCMS( signature, signatureLength, \n\t\t\t\t\t\t\t\t\t\tsigCheckContext, iHashContext, \n\t\t\t\t\t\t\t\t\t\textraData, iSigCheckKey );\n\t\t\tbreak;\n#endif /* USE_INT_CMS */\n\n#ifdef USE_PGP\n\t\tcase CRYPT_FORMAT_PGP:\n\t\t\tstatus = checkSignaturePGP( signature, signatureLength,\n\t\t\t\t\t\t\t\t\t\tsigCheckContext, iHashContext );\n\t\t\tbreak;\n#endif /* USE_PGP */\n\n#ifdef USE_SSL\n\t\tcase CRYPT_IFORMAT_SSL:\n\t\t\tstatus = checkSignature( signature, signatureLength,\n\t\t\t\t\t\t\t\t\t sigCheckContext, iHashContext,\n\t\t\t\t\t\t\t\t\t iHash2Context, SIGNATURE_SSL );\n\t\t\tbreak;\n\n\t\tcase CRYPT_IFORMAT_TLS12:\n\t\t\tstatus = checkSignature( signature, signatureLength,\n\t\t\t\t\t\t\t\t\t sigCheckContext, iHashContext,\n\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, SIGNATURE_TLS12 );\n\t\t\tbreak;\n#endif /* USE_SSL */\n\n#ifdef USE_SSH\n\t\tcase CRYPT_IFORMAT_SSH:\n\t\t\tstatus = checkSignature( signature, signatureLength,\n\t\t\t\t\t\t\t\t\t sigCheckContext, iHashContext,\n\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, SIGNATURE_SSH );\n\t\t\tbreak;\n#endif /* USE_SSH */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( cryptArgError( status ) )\n\t\t{\n\t\t/* Catch any parameter errors that slip through */\n\t\tDEBUG_DIAG(( \"Signature creation returned argError status\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tStub Functions for non-CMS/PGP Use\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef USE_INT_CMS \n\nC_RET cryptCreateSignatureEx( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\t  C_IN int signatureMaxLength,\n\t\t\t\t\t\t\t  C_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\t  C_IN CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t  C_IN CRYPT_HANDLE extraData )\n\t{\n\tUNUSED_ARG( signature );\n\tUNUSED_ARG( signatureLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCreateSignature( C_OUT_OPT void C_PTR signature,\n\t\t\t\t\t\t\tC_IN int signatureMaxLength,\n\t\t\t\t\t\t\tC_OUT int C_PTR signatureLength,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\t\tC_IN CRYPT_CONTEXT hashContext )\n\t{\n\tUNUSED_ARG( signature );\n\tUNUSED_ARG( signatureLength );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCheckSignatureEx( C_IN void C_PTR signature,\n\t\t\t\t\t\t\t C_IN int signatureLength,\n\t\t\t\t\t\t\t C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t\t C_IN CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t C_OUT_OPT CRYPT_HANDLE C_PTR extraData )\n\t{\n\tUNUSED_ARG( signature );\n\tUNUSED_ARG( extraData );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\nC_RET cryptCheckSignature( C_IN void C_PTR signature,\n\t\t\t\t\t\t   C_IN int signatureLength,\n\t\t\t\t\t\t   C_IN CRYPT_HANDLE sigCheckKey,\n\t\t\t\t\t\t   C_IN CRYPT_CONTEXT hashContext )\n\t{\n\tUNUSED_ARG( signature );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/sign_cms.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMS Signature Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n/* CMS version */\n\n#define CMS_VERSION\t\t1\n\n/* The maximum size for the encoded CMS signed attributes */\n\n#define ENCODED_ATTRIBUTE_SIZE\t512\n\n/* In standard PKIX/CMS form, the ESSCertID isn't just a hash but a complex \n   composite field.  To deal with this we use a fixed SEQUENCE { OCTET \n   STRING ... } header before the SHA-2 hash value */\n\n#define ESSCERTID_HEADER\t\t\"\\x30\\x22\\x04\\x20\"\n#define ESSCERTID_HEADER_SIZE\t4\n\n/* A structure to store CMS attribute information */\n\ntypedef struct {\n\t/* The format of the signature: Basic CMS or full S/MIME */\n\tCRYPT_FORMAT_TYPE formatType;\n\n\t/* Objects needed to create the attributes.  The time source is a device\n\t   associated with the signing key (usually the system device, but can\n\t   be a crypto device) used to obtain the signing time.  The TSP session\n\t   is an optional session that's used to timestamp the signature */\n\tBOOLEAN useDefaultAttributes;\t\t/* Whether we provide default attrs.*/\n\tCRYPT_CERTIFICATE iCmsAttributes;\t/* CMS attributes */\n\tCRYPT_CONTEXT iMessageHash;\t\t\t/* Hash for MessageDigest */\n\tCRYPT_HANDLE iTimeSource;\t\t\t/* Time source for signing time */\n\tCRYPT_SESSION iTspSession;\t\t\t/* Optional TSP session */\n\n\t/* The encoded attributes.  The encodedAttributes pointer is null if \n\t   there are no attributes present, or points to the buffer containing \n\t   the encoded attributes */\n\tBYTE attributeBuffer[ ENCODED_ATTRIBUTE_SIZE + 8 ];\n\tBUFFER_OPT( maxEncodedAttributeSize, encodedAttributeSize ) \\\n\tBYTE *encodedAttributes;\n\tint maxEncodedAttributeSize;\n\n\t/* Returned data: The size of the encoded attribute information in the\n\t   buffer */\n\tint encodedAttributeSize;\n\t} CMS_ATTRIBUTE_INFO;\n\n#define initCmsAttributeInfo( attributeInfo, format, useDefault, cmsAttributes, messageHash, timeSource, tspSession ) \\\n\t\tmemset( attributeInfo, 0, sizeof( CMS_ATTRIBUTE_INFO ) ); \\\n\t\t( attributeInfo )->formatType = format; \\\n\t\t( attributeInfo )->useDefaultAttributes = useDefault; \\\n\t\t( attributeInfo )->iCmsAttributes = cmsAttributes; \\\n\t\t( attributeInfo )->iMessageHash = messageHash; \\\n\t\t( attributeInfo )->iTimeSource = timeSource; \\\n\t\t( attributeInfo )->iTspSession = tspSession; \\\n\t\t( attributeInfo )->maxEncodedAttributeSize = ENCODED_ATTRIBUTE_SIZE;\n\n#ifdef USE_INT_CMS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write CMS signer information:\n\n\tSignerInfo ::= SEQUENCE {\n\t\tversion\t\t\t\t\tINTEGER (1),\n\t\tissuerAndSerialNumber\tIssuerAndSerialNumber,\n\t\tdigestAlgorithm\t\t\tAlgorithmIdentifier,\n\t\tsignedAttrs\t\t  [ 0 ]\tIMPLICIT SET OF Attribute OPTIONAL,\n\t\tsignatureAlgorithm\t\tAlgorithmIdentifier,\n\t\tsignature\t\t\t\tOCTET STRING,\n\t\tunsignedAttrs\t  [ 1 ]\tIMPLICIT SET OF Attribute OPTIONAL\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 7 ) ) \\\nstatic int writeCmsSignerInfo( INOUT STREAM *stream,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t   IN_RANGE( 0, CRYPT_MAX_HASHSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int hashAlgoParam,\n\t\t\t\t\t\t\t   IN_BUFFER_OPT( attributeSize ) \\\n\t\t\t\t\t\t\t\t\tconst void *attributes, \n\t\t\t\t\t\t\t   IN_DATALENGTH_Z const int attributeSize,\n\t\t\t\t\t\t\t   IN_BUFFER( signatureSize ) const void *signature, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int signatureSize,\n\t\t\t\t\t\t\t   IN_HANDLE_OPT const CRYPT_HANDLE unsignedAttrObject )\n\t{\n\tMESSAGE_DATA msgData;\n\tDYNBUF iAndSDB;\n\tint sizeofHashAlgoID, timeStampSize DUMMY_INIT;\n\tint unsignedAttributeSize = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( attributes == NULL && attributeSize == 0 ) || \\\n\t\t\tisReadPtrDynamic( attributes, attributeSize ) );\n\tassert( isReadPtrDynamic( signature, signatureSize ) );\n\n\tREQUIRES( isHandleRangeValid( certificate ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashAlgoParam == 0 || \\\n\t\t\t  ( hashAlgoParam >= MIN_HASHSIZE && \\\n\t\t\t\thashAlgoParam <= CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( ( attributes == NULL && attributeSize == 0 ) || \\\n\t\t\t  ( attributes != NULL && \\\n\t\t\t\tattributeSize > 0 && attributeSize < MAX_BUFFER_SIZE ) );\n\tREQUIRES( signatureSize > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  signatureSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( unsignedAttrObject == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( unsignedAttrObject ) );\n\n\t/* Determine the size of the hash algorithm information */\n\tif( hashAlgoParam == 0 )\n\t\tsizeofHashAlgoID = sizeofAlgoID( hashAlgo );\n\telse\n\t\tsizeofHashAlgoID = sizeofAlgoIDex( hashAlgo, hashAlgoParam );\n\tif( cryptStatusError( sizeofHashAlgoID ) )\n\t\treturn( sizeofHashAlgoID );\n\n\t/* Get the signerInfo information */\n\tif( unsignedAttrObject != CRYPT_UNUSED )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( unsignedAttrObject, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENC_TIMESTAMP );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\ttimeStampSize = msgData.length;\n\t\tunsignedAttributeSize = \\\n\t\t\t\t\tsizeofShortObject( sizeofOID( OID_TSP_TSTOKEN ) + \\\n\t\t\t\t\t\t\t\t\t   sizeofShortObject( timeStampSize ) );\n\t\t}\n\tstatus = dynCreate( &iAndSDB, certificate,\n\t\t\t\t\t\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the outer SEQUENCE wrapper and version number */\n\twriteSequence( stream, sizeofShortInteger( CMS_VERSION ) + \\\n\t\t\t\t\t\t   dynLength( iAndSDB ) + sizeofHashAlgoID + \\\n\t\t\t\t\t\t   attributeSize + signatureSize + \\\n\t\t\t\t\t\t   ( ( unsignedAttributeSize > 0 ) ? \\\n\t\t\t\t\t\t\t sizeofShortObject( unsignedAttributeSize ) : 0 ) );\n\twriteShortInteger( stream, CMS_VERSION, DEFAULT_TAG );\n\n\t/* Write the issuerAndSerialNumber, digest algorithm identifier,\n\t   attributes (if there are any) and signature */\n\tswrite( stream, dynData( iAndSDB ), dynLength( iAndSDB ) );\n\twriteAlgoIDex( stream, hashAlgo, hashAlgoParam, 0 );\n\tif( attributeSize > 0 )\n\t\tswrite( stream, attributes, attributeSize );\n\tstatus = swrite( stream, signature, signatureSize );\n\tdynDestroy( &iAndSDB );\n\tif( cryptStatusError( status ) || unsignedAttributeSize <= 0 )\n\t\treturn( status );\n\n\t/* Write the unsigned attributes.  Note that the only unsigned attribute\n\t   in use at this time is a (not-quite) countersignature containing a\n\t   timestamp, so the following code always assumes that the attribute is\n\t   a timestamp.  First we write the [1] IMPLICT SET OF attribute\n\t   wrapper */\n\twriteConstructed( stream, unsignedAttributeSize, 1 );\n\twriteSequence( stream, sizeofOID( OID_TSP_TSTOKEN ) + \\\n\t\t\t\t\t\t   sizeofObject( timeStampSize ) );\n\twriteOID( stream, OID_TSP_TSTOKEN );\n\tstatus = writeSet( stream, timeStampSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Then we copy the timestamp data directly into the stream */\n\treturn( exportAttributeToStream( stream, unsignedAttrObject,\n\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ENC_TIMESTAMP ) );\n\t}\n\n/* Create a CMS countersignature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createCmsCountersignature( IN_BUFFER( dataSignatureSize ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *dataSignature,\n\t\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int dataSignatureSize,\n\t\t\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\t\t  IN_RANGE( 0, CRYPT_MAX_HASHSIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int hashAlgoParam,\n\t\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_SESSION iTspSession )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tint length, status;\n\n\tassert( isReadPtrDynamic( dataSignature, dataSignatureSize ) );\n\n\tREQUIRES( dataSignatureSize > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  dataSignatureSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashAlgoParam == 0 || \\\n\t\t\t  ( hashAlgoParam >= MIN_HASHSIZE && \\\n\t\t\t\thashAlgoParam <= CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( isHandleRangeValid( iTspSession ) );\n\n\t/* Hash the signature data to create the hash value to countersign.\n\t   The CMS spec requires that the signature is calculated on the\n\t   contents octets (in other words the V of the TLV) of the signature,\n\t   so we have to skip the signature algorithm and OCTET STRING wrapper */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &hashAlgoParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tiHashContext = createInfo.cryptHandle;\n#if 1\t/* Standard CMS countersignature */\n\tsMemConnect( &stream, dataSignature, dataSignatureSize );\n\treadUniversal( &stream );\n\tstatus = readOctetStringHole( &stream, &length, MIN_HASHSIZE, \n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *dataPtr;\n\n\t\tstatus = sMemGetDataBlock( &stream, &dataPtr, length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t  dataPtr, length );\n\t\t\t}\n\t\t}\n\tsMemDisconnect( &stream );\n#else\t/* Broken TSP not-quite-countersignature */\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t ( MESSAGE_CAST ) dataSignature, dataSignatureSize );\n#endif /* 1 */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iTspSession, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &iHashContext,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_TSP_MSGIMPRINT );\n\t\t}\n\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the result to the TSA for countersigning */\n\treturn( krnlSendMessage( iTspSession, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t MESSAGE_VALUE_TRUE, CRYPT_SESSINFO_ACTIVE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate CMS Attributes \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add signingTime to a CMS attribute object */\n\nCHECK_RETVAL \\\nstatic int addSigningTime( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_DEVICE iTimeSource )\n\t{\n\tMESSAGE_DATA msgData;\n\tconst time_t currentTime = getReliableTime( iTimeSource );\n\n\tREQUIRES( isHandleRangeValid( iCmsAttributes ) );\n\n\tif( currentTime < MIN_TIME_VALUE )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) &currentTime,\n\t\t\t\t\tsizeof( time_t ) );\n\treturn( krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t &msgData, CRYPT_CERTINFO_CMS_SIGNINGTIME ) );\n\t}\n\n/* Add cmsNonce to a CMS attribute object to make sure that we don't sign \n   the same message twice.  This is highly unlikely in the presence of the\n   signing time, but in theory possible if we create two signed messages in \n   quick succession from the same data.  Since this isn't critical, we \n   don't report an error if it fails */\n\nstatic void addCmsNonce( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE nonceBuffer[ 8 + 8 ];\n\tint status;\n\n\tREQUIRES_V( isHandleRangeValid( iCmsAttributes ) );\n\n\tsetMessageData( &msgData, nonceBuffer, 8 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t( void ) krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_NONCE );\n\t\t}\n\t}\n\n/* Add/check the signingCertificate identifier in a CMS attribute object, \n   with the same error handling as addCmsNonce() */\n\nstatic void addSigningCertificate( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CERTIFICATE iSignContext )\n\t{\n\tCRYPT_CERTIFICATE iCryptCert;\n\tMESSAGE_DATA msgData DUMMY_INIT_STRUCT;\n\tBYTE essCertIDv2[ ESSCERTID_HEADER_SIZE + CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tREQUIRES_V( isHandleRangeValid( iCmsAttributes ) );\n\tREQUIRES_V( isHandleRangeValid( iSignContext ) );\n\n\t/* Lock the certificate for our exclusive use, select the first \n\t   certificate in the chain, add the ESSCertID for the signing \n\t   certificate, and unlock it again to allow others access.\n\n\t   In theory we could switch from SHA-2/ESSCertIDv2 to SHA1/ESSCertID \n\t   based on which hash algorithm we're using, but in practice the\n\t   signingCertificate capability is so rarely used or checked by \n\t   anything other than cryptlib that we can just default to the stronger\n\t   hash for all cases */\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iCryptCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn;\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* In standard PKIX/CMS form, the ESSCertID isn't just a hash but a \n\t\t   complex composite field.  To deal with this we copy in a fixed\n\t\t   ESSCERTID header before the hash value */\n\t\tmemcpy( essCertIDv2, ESSCERTID_HEADER, ESSCERTID_HEADER_SIZE );\n\t\tsetMessageData( &msgData, essCertIDv2 + ESSCERTID_HEADER_SIZE, \n\t\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA2 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, essCertIDv2, \n\t\t\t\t\t\tESSCERTID_HEADER_SIZE + msgData.length );\n\t\t( void ) krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2 );\n\t\t}\n\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\t}\n\nstatic int checkSigningCertificate( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iSignContext )\n\t{\n\tCRYPT_CERTIFICATE iCryptCert;\n\tMESSAGE_DATA msgData DUMMY_INIT_STRUCT;\n\tBYTE essCertIDv2[ ESSCERTID_HEADER_SIZE + CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE hashValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize DUMMY_INIT, status;\n\n\tREQUIRES( isHandleRangeValid( iCmsAttributes ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\n\t/* Get the signingCertificate identifier and make sure that we can \n\t   process it.  If we can't get the identifier or it's in some complex\n\t   form that we don't know what to do with, we skip it */\n\tsetMessageData( &msgData, essCertIDv2, \n\t\t\t\t\tESSCERTID_HEADER_SIZE + CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SIGNINGCERTV2_ESSCERTIDV2 );\n\tif( cryptStatusError( status ) || \\\n\t\tmemcmp( essCertIDv2, ESSCERTID_HEADER, ESSCERTID_HEADER_SIZE ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Lock the certificate for our exclusive use, select the first \n\t   certificate in the chain, get its cert hash, and unlock it again to \n\t   allow others access */\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iCryptCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, hashValue, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\thashSize = msgData.length;\n\t\t}\n\t( void ) krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* We've now got a copy of the required certificate hash and the actual\n\t   certificate hash, make sure that they match up.  If they don't we\n\t   report the problem as a signature error, which it technically isn't\n\t   but it's an obscure-enough failure condition that a signature-error \n\t   report is the best that we can do */\n\tif( memcmp( hashValue, essCertIDv2 + ESSCERTID_HEADER_SIZE, hashSize ) )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add sMimeCapabilities to a CMS attribute object */\n\nstatic void addSmimeCapabilities( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes )\n\t{\n\ttypedef struct { \n\t\tCRYPT_ALGO_TYPE algorithm;\n\t\tCRYPT_ALGO_TYPE secondaryAlgorithm;\n\t\tCRYPT_ATTRIBUTE_TYPE smimeCapability;\n\t\t} SMIMECAP_INFO;\n\tstatic const SMIMECAP_INFO smimeCapInfo[] = {\n#ifdef USE_3DES\n\t\t{ CRYPT_ALGO_3DES, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_3DES },\n#endif /* USE_3DES */\n#ifdef USE_AES\n\t\t{ CRYPT_ALGO_AES, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_AES },\n#endif /* USE_AES */\n#ifdef USE_SHAng\n\t\t{ CRYPT_ALGO_SHAng, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_SHAng },\n#endif /* USE_SHAng */\n\t\t{ CRYPT_ALGO_SHA2, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_SHA2 },\n\t\t{ CRYPT_ALGO_SHA1, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_SHA1 },\n#ifdef USE_SHAng\n\t\t{ CRYPT_ALGO_HMAC_SHAng, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHAng },\n#endif /* USE_SHAng */\n\t\t{ CRYPT_ALGO_HMAC_SHA2, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA2 },\n\t\t{ CRYPT_ALGO_HMAC_SHA1, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_HMAC_SHA1 },\n\t\t{ CRYPT_IALGO_GENERIC_SECRET, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC256 },\n\t\t{ CRYPT_IALGO_GENERIC_SECRET, CRYPT_ALGO_NONE, \n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_AUTHENC128 },\n#ifdef USE_SHAng\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHAng,\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHAng },\n#endif /* USE_SHAng */\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2,\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA2 },\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_NONE,\t/* 'None' since always avail. */\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_RSA_SHA1 },\n#ifdef USE_DSA\n\t\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_NONE,\t/* 'None' since always avail. */\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_DSA_SHA1 },\n#endif /* USE_DSA */\n#ifdef USE_ECDSA\n  #ifdef USE_SHAng\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHAng,\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHAng },\n  #endif /* USE_SHAng */\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2,\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA2 },\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_NONE,\t/* 'None' since always avail. */\n\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_ECDSA_SHA1 },\n#endif /* USE_ECDSA */\n\t\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ATTRIBUTE_NONE },\n\t\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ATTRIBUTE_NONE },\n\t\t};\n\tCRYPT_ALGO_TYPE prevAlgo = CRYPT_ALGO_NONE;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_V( isHandleRangeValid( iCmsAttributes ) );\n\n\t/* Add an sMIMECapability for each supported algorithm or algorithm \n\t   combination.  Since these are no-value attributes it's not worth \n\t   aborting the signature generation if the attempt to add them fails \n\t   so we don't bother checking the return value */\n\tLOOP_MED( i = 0, smimeCapInfo[ i ].algorithm != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( smimeCapInfo, SMIMECAP_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tconst CRYPT_ALGO_TYPE algorithm = smimeCapInfo[ i ].algorithm;\n\n\t\t/* Make sure that the primary algorithm is available */\n\t\tif( prevAlgo != algorithm && !algoAvailable( algorithm ) )\n\t\t\t{\n\t\t\tprevAlgo = algorithm;\n\t\t\tcontinue;\n\t\t\t}\n\t\tprevAlgo = algorithm;\n\n\t\t/* If there's a secondary algorithm, make sure that it's available */\n\t\tif( smimeCapInfo[ i ].secondaryAlgorithm != CRYPT_ALGO_NONE && \\\n\t\t\t!algoAvailable( smimeCapInfo[ i ].secondaryAlgorithm ) )\n\t\t\tcontinue;\n\n\t\t/* List this algorithm or algorithm combination as an available \n\t\t   capability */\n\t\t( void ) krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED, \n\t\t\t\t\t\t\t\t  smimeCapInfo[ i ].smimeCapability );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( i < FAILSAFE_ARRAYSIZE( smimeCapInfo, SMIMECAP_INFO ) );\n\n\t/* Add any futher non-algorithm-related sMIMECapabilities */\n\t( void ) krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SMIMECAP_PREFERBINARYINSIDE );\n\t}\n\n/* Finalise processing of and hash the CMS attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int hashCmsAttributes( INOUT CMS_ATTRIBUTE_INFO *cmsAttributeInfo,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iAttributeHash,\n\t\t\t\t\t\t\t  const BOOLEAN lengthCheckOnly )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE temp, hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( cmsAttributeInfo, sizeof( CMS_ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtrDynamic( cmsAttributeInfo->encodedAttributes, \\\n\t\t\t\t\t\t\t   cmsAttributeInfo->maxEncodedAttributeSize ) );\n\n\tREQUIRES( isHandleRangeValid( cmsAttributeInfo->iCmsAttributes ) );\n\tREQUIRES( isHandleRangeValid( cmsAttributeInfo->iMessageHash ) );\n\tREQUIRES( isHandleRangeValid( iAttributeHash ) );\n\tREQUIRES( lengthCheckOnly == TRUE || lengthCheckOnly == FALSE );\n\n\t/* Extract the message hash information and add it as a messageDigest\n\t   attribute, replacing any existing value if necessary (we don't bother\n\t   checking the return value because the attribute may or may not be \n\t   present, and a failure to delete it will be detected immediately\n\t   afterwards when we try and set it).  If we're doing a call just to \n\t   get the length of the exported data we use a dummy hash value since \n\t   the hashing may not have completed yet */\n\t( void ) krnlSendMessage( cmsAttributeInfo->iCmsAttributes, \n\t\t\t\t\t\t\t  IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_MESSAGEDIGEST );\n\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\tif( lengthCheckOnly )\n\t\t{\n\t\tmemset( hash, 0, CRYPT_MAX_HASHSIZE );\t/* Keep mem.checkers happy */\n\t\tstatus = krnlSendMessage( cmsAttributeInfo->iMessageHash, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &msgData.length, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = krnlSendMessage( cmsAttributeInfo->iMessageHash, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( cmsAttributeInfo->iCmsAttributes, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_MESSAGEDIGEST );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Export the attributes into an encoded signedAttributes data block */\n\tif( lengthCheckOnly )\n\t\t{ setMessageData( &msgData, NULL, 0 ); }\n\telse\n\t\t{ \n\t\tsetMessageData( &msgData, cmsAttributeInfo->encodedAttributes,\n\t\t\t\t\t\tcmsAttributeInfo->maxEncodedAttributeSize );\n\t\t}\n\tstatus = krnlSendMessage( cmsAttributeInfo->iCmsAttributes, \n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcmsAttributeInfo->encodedAttributeSize = msgData.length;\n\n\t/* If it's a length check, just generate a dummy hash value and exit */\n\tif( lengthCheckOnly )\n\t\treturn( krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, \"\", 0 ) );\n\n\t/* Replace the IMPLICIT [ 0 ] tag at the start with a SET OF tag to \n\t   allow the attributes to be hashed, hash them into the attribute hash \n\t   context, and replace the original tag */\n\ttemp = cmsAttributeInfo->encodedAttributes[ 0 ];\n\tcmsAttributeInfo->encodedAttributes[ 0 ] = BER_SET;\n\tstatus = krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  cmsAttributeInfo->encodedAttributes,\n\t\t\t\t\t\t\t  cmsAttributeInfo->encodedAttributeSize );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, \"\", 0 );\n\tcmsAttributeInfo->encodedAttributes[ 0 ] = temp;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createCmsAttributes( INOUT CMS_ATTRIBUTE_INFO *cmsAttributeInfo,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iCmsHashContext,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\tIN_RANGE( 0, CRYPT_MAX_HASHSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int hashAlgoParam,\n\t\t\t\t\t\t\t\tconst BOOLEAN lengthCheckOnly )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBOOLEAN createdHashContext = FALSE;\n\ttime_t timeValue;\n\tint value, status;\n\n\tassert( isWritePtr( cmsAttributeInfo, sizeof( CMS_ATTRIBUTE_INFO ) ) );\n\tassert( isWritePtrDynamic( cmsAttributeInfo->attributeBuffer, \\\n\t\t\t\t\t\t\t   cmsAttributeInfo->maxEncodedAttributeSize ) );\n\tassert( isWritePtr( iCmsHashContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( cmsAttributeInfo->formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t  cmsAttributeInfo->formatType == CRYPT_FORMAT_SMIME );\n\tREQUIRES( ( cmsAttributeInfo->iCmsAttributes == CRYPT_UNUSED && \\\n\t\t\t\tcmsAttributeInfo->useDefaultAttributes == FALSE ) || \\\n\t\t\t  ( cmsAttributeInfo->iCmsAttributes == CRYPT_UNUSED && \\\n\t\t\t\tcmsAttributeInfo->useDefaultAttributes == TRUE ) || \\\n\t\t\t  ( isHandleRangeValid( cmsAttributeInfo->iCmsAttributes ) && \\\n\t\t\t    cmsAttributeInfo->useDefaultAttributes == FALSE ) );\n\tREQUIRES( isHandleRangeValid( cmsAttributeInfo->iMessageHash ) );\n\tREQUIRES( isHandleRangeValid( cmsAttributeInfo->iTimeSource ) );\n\tREQUIRES( ( cmsAttributeInfo->iTspSession == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( cmsAttributeInfo->iTspSession ) );\n\tREQUIRES( cmsAttributeInfo->encodedAttributes == NULL && \\\n\t\t\t  cmsAttributeInfo->encodedAttributeSize == 0 );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashAlgoParam == 0 || \\\n\t\t\t  ( hashAlgoParam >= MIN_HASHSIZE && \\\n\t\t\t\thashAlgoParam <= CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( lengthCheckOnly == TRUE || lengthCheckOnly == FALSE );\n\n\t/* Clear return value */\n\t*iCmsHashContext = CRYPT_ERROR;\n\n\t/* Set up the attribute buffer */\n\tcmsAttributeInfo->encodedAttributes = cmsAttributeInfo->attributeBuffer;\n\n\t/* If the user hasn't supplied the attributes, generate them ourselves */\n\tif( cmsAttributeInfo->useDefaultAttributes )\n\t\t{\n\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tcmsAttributeInfo->iCmsAttributes = createInfo.cryptHandle;\n\t\t}\n\tENSURES( isHandleRangeValid( cmsAttributeInfo->iCmsAttributes ) );\n\tiCmsAttributes = cmsAttributeInfo->iCmsAttributes;\n\n\t/* Add the default attributes, contentType, signingTime, and cmsNonce */\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_CONTENTTYPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatic const int contentType = CRYPT_CONTENT_DATA;\n\n\t\t/* There's no content type present, treat it as straight data (which\n\t\t   means that this is signedData) */\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &contentType, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_CONTENTTYPE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, &timeValue, sizeof( time_t ) );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_SIGNINGTIME );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = addSigningTime( iCmsAttributes,\n\t\t\t\t\t\t\t\t cmsAttributeInfo->iTimeSource );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_NONCE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The nonce is a non-critical attribute so we don't abort the \n\t\t   signature generation if we can't add it */\n\t\taddCmsNonce( iCmsAttributes );\n\t\t}\n\tif( cmsAttributeInfo->formatType == CRYPT_FORMAT_SMIME )\n\t\t{\n\t\t/* It's an S/MIME (vs.pure CMS) signature, add the \n\t\t   signingCertificate identifier and the sMIMECapabilities to \n\t\t   further bloat things up.  Since these are optional attributes \n\t\t   it's not worth aborting the signature generation if the attempt \n\t\t   to add them fails so we don't bother checking a return value */\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t( void ) addSigningCertificate( iCmsAttributes, iSignContext );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SMIMECAPABILITIES );\n\t\tif( cryptStatusError( status ) )\n\t\t\t( void ) addSmimeCapabilities( iCmsAttributes );\n\t\t}\n\n\t/* Generate the attributes and hash them into the CMS hash context */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &hashAlgoParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcreatedHashContext = TRUE;\n\t\tstatus = hashCmsAttributes( cmsAttributeInfo, createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\tlengthCheckOnly );\n\t\t}\n\tif( cmsAttributeInfo->useDefaultAttributes )\n\t\t{\n\t\tkrnlSendNotifier( cmsAttributeInfo->iCmsAttributes, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tcmsAttributeInfo->iCmsAttributes = CRYPT_UNUSED;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( createdHashContext )\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Return the hash of the attributes to the caller */\n\t*iCmsHashContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate/Check a CMS Signature \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a CMS signature.  The use of authenticated attributes is a three-\n   way choice:\n\n\tuseDefaultAuthAttr = FALSE,\t\tNo attributes.\n\tiAuthAttr = CRYPT_UNUSED\n\n\tuseDefaultAuthAttr = TRUE,\t\tWe supply default attributes.\n\tiAuthAttr = CRYPT_UNUSED\n\n\tuseDefaultAuthAttr = FALSE,\t\tCaller has supplied attributes\n\tiAuthAttr = validhandle */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignatureCMS( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *signatureLength,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT signContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\tconst BOOLEAN useDefaultAuthAttr,\n\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CERTIFICATE iAuthAttr,\n\t\t\t\t\t\tIN_HANDLE_OPT const CRYPT_SESSION iTspSession,\n\t\t\t\t\t\tIN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_CONTEXT iCmsHashContext = iHashContext;\n\tCRYPT_CERTIFICATE iSigningCert;\n\tSTREAM stream;\n\tCMS_ATTRIBUTE_INFO cmsAttributeInfo;\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 128 + 8 ];\n\tBYTE *bufPtr = ( signature == NULL ) ? NULL : buffer;\n\tconst int bufSize = ( signature == NULL ) ? 0 : CRYPT_MAX_PKCSIZE + 128;\n\tint hashAlgo, hashAlgoParam = 0;\n\tint dataSignatureSize, length DUMMY_INIT, status;\n\n\tassert( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( signature, sigMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\n\tREQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\t  ( signature != NULL && \\\n\t\t\t    sigMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tsigMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isHandleRangeValid( signContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( useDefaultAuthAttr == TRUE || useDefaultAuthAttr == FALSE );\n\tREQUIRES( ( iAuthAttr == CRYPT_UNUSED && \\\n\t\t\t\tuseDefaultAuthAttr == FALSE ) || \\\n\t\t\t  ( iAuthAttr == CRYPT_UNUSED && \\\n\t\t\t\tuseDefaultAuthAttr == TRUE ) || \\\n\t\t\t  ( isHandleRangeValid( iAuthAttr ) && \\\n\t\t\t    useDefaultAuthAttr == FALSE ) );\n\tREQUIRES( ( iTspSession == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( iTspSession ) );\n\tREQUIRES( formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t  formatType == CRYPT_FORMAT_SMIME );\n\n\t/* Clear return value */\n\t*signatureLength = 0;\n\n\tinitCmsAttributeInfo( &cmsAttributeInfo, formatType, \n\t\t\t\t\t\t  useDefaultAuthAttr, iAuthAttr, iHashContext, \n\t\t\t\t\t\t  signContext, iTspSession );\n\n\t/* Get the message hash algo and signing certificate */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgoParam, CRYPT_CTXINFO_BLOCKSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\tstatus = krnlSendMessage( signContext, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t  &iSigningCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\n\t/* If we're using signed attributes, set them up to be added to the\n\t   signature info */\n\tif( useDefaultAuthAttr || iAuthAttr != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = createCmsAttributes( &cmsAttributeInfo, &iCmsHashContext, \n\t\t\t\t\t\t\t\t\t  signContext, hashAlgo, hashAlgoParam,\n\t\t\t\t\t\t\t\t\t  ( signature == NULL ) ? TRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Create the signature */\n\tstatus = createSignature( bufPtr, bufSize, &dataSignatureSize, \n\t\t\t\t\t\t\t  signContext, iCmsHashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t  SIGNATURE_CMS );\n\tif( iCmsHashContext != iHashContext )\n\t\tkrnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're countersigning the signature (typically done via a\n\t   timestamp), create the countersignature */\n\tif( iTspSession != CRYPT_UNUSED && signature != NULL )\n\t\t{\n\t\tstatus = createCmsCountersignature( buffer, dataSignatureSize,\n\t\t\t\t\t\t\t\t\t\t\thashAlgo, hashAlgoParam,\n\t\t\t\t\t\t\t\t\t\t\tiTspSession );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the signerInfo record */\n\tINJECT_FAULT( ENVELOPE_CORRUPT_AUTHATTR, \n\t\t\t\t  ENVELOPE_CORRUPT_AUTHATTR_CMS_1 );\n\tsMemOpenOpt( &stream, signature, ( signature == NULL ) ? 0 : sigMaxLength );\n\tstatus = writeCmsSignerInfo( &stream, iSigningCert, hashAlgo, hashAlgoParam,\n\t\t\t\t\t\t\t\t cmsAttributeInfo.encodedAttributes, \n\t\t\t\t\t\t\t\t cmsAttributeInfo.encodedAttributeSize,\n\t\t\t\t\t\t\t\t buffer, dataSignatureSize,\n\t\t\t\t\t\t\t\t ( signature == NULL ) ? CRYPT_UNUSED : iTspSession );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( iTspSession != CRYPT_UNUSED && signature == NULL )\n\t\t{\n\t\t/* If we're countersigning the signature with a timestamp and doing \n\t\t   a length check only then we run into problems because we can't \n\t\t   report how big the final size will be without contacting the TSA \n\t\t   for a timestamp.  In theory we could report some hopefully-OK\n\t\t   large-enough size, but at the moment we take advantage of the \n\t\t   fact that we're only going to be called from the enveloping code \n\t\t   because a timestamp only makes sense as a countersignature on CMS \n\t\t   data.  It's somewhat ugly because it asumes internal knowledge of \n\t\t   the envelope abstraction but there isn't really any clean way to \n\t\t   handle this because we can't tell in advance how much data the \n\t\t   TSA will send us.\n\n\t\t   In theory the code doesn't even need to return an estimate \n\t\t   because, without knowing the exact length of the \n\t\t   countersignature, the enveloping code has to fall back to using\n\t\t   indefinite-length encoding (see envelope/cms_envpre.c), so the\n\t\t   length value that we return here is ignored */\n\t\tlength += MIN_BUFFER_SIZE;\n\t\t}\n\t*signatureLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check a CMS signature.  The reason why there are apparently two \n   signature-checking objects present in the function arguments is that\n   sigCheckContext is the raw public-key context while iSigCheckKey is the \n   overall signature-checking object, which may include attached \n   certificates and other information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignatureCMS( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_DATALENGTH const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t   OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iExtraData,\n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iSigCheckKey )\n\t{\n\tCRYPT_CERTIFICATE iLocalExtraData;\n\tCRYPT_CONTEXT iCmsHashContext = iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tQUERY_INFO queryInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tstatic const BYTE setTag[] = { BER_SET };\n\tBYTE hashValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint hashAlgo, hashAlgoParam = 0, value, status;\t/* int vs.enum */\n\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\tassert( ( iExtraData == NULL ) || \\\n\t\t\tisWritePtr( iExtraData, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( signatureLength > 40 && signatureLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( sigCheckContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isHandleRangeValid( iSigCheckKey ) );\n\n\tif( iExtraData != NULL )\n\t\t*iExtraData = CRYPT_ERROR;\n\n\t/* Get the message hash algo */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgoParam, CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Unpack the SignerInfo record and make sure that the supplied key is\n\t   the correct one for the sig.check and the supplied hash context\n\t   matches the algorithm used in the signature */\n\tsMemConnect( &stream, signature, signatureLength );\n\tstatus = queryAsn1Object( &stream, &queryInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\t( queryInfo.formatType != CRYPT_FORMAT_CMS && \\\n\t\t  queryInfo.formatType != CRYPT_FORMAT_SMIME ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tREQUIRES( boundsCheck( queryInfo.iAndSStart, queryInfo.iAndSLength,\n\t\t\t\t\t\t   queryInfo.size ) );\n\tsetMessageData( &msgData, \\\n\t\t\t\t\t( BYTE * ) signature + queryInfo.iAndSStart, \\\n\t\t\t\t\tqueryInfo.iAndSLength );\n\tstatus = krnlSendMessage( iSigCheckKey, IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t  MESSAGE_COMPARE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* A failed comparison is reported as a generic CRYPT_ERROR,\n\t\t   convert it into a wrong-key error if necessary */\n\t\treturn( ( status == CRYPT_ERROR ) ? \\\n\t\t\t\tCRYPT_ERROR_WRONGKEY : status );\n\t\t}\n\tif( queryInfo.hashAlgo != hashAlgo || \\\n\t\tqueryInfo.hashAlgoParam != hashAlgoParam )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tCFI_CHECK_UPDATE( \"queryAsn1Object\" );\n\n\t/* If there are no signed attributes present, just check the signature \n\t   and exit */\n\tif( queryInfo.attributeStart <= 0 )\n\t\t{\n\t\tstatus = checkSignature( signature, signatureLength, sigCheckContext,\n\t\t\t\t\t\t\t\t iCmsHashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t SIGNATURE_CMS );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkSignature\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \"queryAsn1Object\", \n\t\t\t\t\t\t\t\t\t\t\"checkSignature\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There are signedAttributes present, hash the data, substituting a SET \n\t   OF tag for the IMPLICIT [ 0 ] tag at the start */\n\tREQUIRES( boundsCheck( queryInfo.attributeStart, \n\t\t\t\t\t\t   queryInfo.attributeLength, queryInfo.size ) );\n\tsetMessageCreateObjectInfo( &createInfo, queryInfo.hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isHashMacExtAlgo( queryInfo.hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &queryInfo.hashAlgoParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tiCmsHashContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  ( BYTE * ) setTag, sizeof( BYTE ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t( BYTE * ) signature + queryInfo.attributeStart + 1,\n\t\t\t\t\t\tqueryInfo.attributeLength - 1 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_HASH\" );\n\n\t/* Check the signature */\n\tstatus = checkSignature( signature, signatureLength, sigCheckContext,\n\t\t\t\t\t\t\t iCmsHashContext, CRYPT_UNUSED, SIGNATURE_CMS );\n\tkrnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkSignature\" );\n\n\t/* Import the attributes and make sure that the data hash value given in\n\t   the signed attributes matches the user-supplied hash */\n\tREQUIRES( boundsCheck( queryInfo.attributeStart, \n\t\t\t\t\t\t   queryInfo.attributeLength, queryInfo.size ) );\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t( BYTE * ) signature + queryInfo.attributeStart,\n\t\t\t\t\t\tqueryInfo.attributeLength,\n\t\t\t\t\t\tCRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiLocalExtraData = createInfo.cryptHandle;\n\tsetMessageData( &msgData, hashValue, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iLocalExtraData, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_MESSAGEDIGEST );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_HASH );\n\t\tif( cryptStatusError( status ) )\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalExtraData, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_COMPARE\" );\n\n\t/* If there's a signingCertificate identifier present, make sure that it\n\t   matches the certificate that we're using */\n\tstatus = krnlSendMessage( iLocalExtraData, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CMS_SIGNINGCERTIFICATEV2 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = checkSigningCertificate( iLocalExtraData, sigCheckContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalExtraData, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\t\n\tCFI_CHECK_UPDATE( \"checkSigningCertificate\" );\n\n\t/* If the user wants to look at the authenticated attributes, make them\n\t   externally visible, otherwise delete them */\n\tif( iExtraData != NULL )\n\t\t*iExtraData = iLocalExtraData;\n\telse\n\t\tkrnlSendNotifier( iLocalExtraData, IMESSAGE_DECREFCOUNT );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"IMESSAGE_GETATTRIBUTE\", \"queryAsn1Object\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_HASH\", \"checkSignature\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_COMPARE\", \n\t\t\t\t\t\t\t\t\t\"checkSigningCertificate\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_CMS */\n"
  },
  {
    "path": "deps/cl345/mechs/sign_int.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInternal Signature Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"mech.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"mechs/mech.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDLP Signature Handling\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a DLP signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int createDlpSignature( OUT_BUFFER_OPT( bufSize, *length ) \\\n\t\t\t\t\t\t\t\t\tvoid *buffer,\n\t\t\t\t\t\t\t   IN_RANGE( 0, CRYPT_MAX_PKCSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int bufSize, \n\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( bufSize ) int *length, \n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t\t   IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE signatureType,\n\t\t\t\t\t\t\t   const BOOLEAN isECC )\n\t{\n\tDLP_PARAMS dlpParams;\n\tMESSAGE_DATA msgData;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint hashSize, status;\n\n\tassert( ( buffer == NULL && bufSize == 0 ) || \\\n\t\t\tisWritePtrDynamic( buffer, bufSize ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( ( buffer == NULL && bufSize == 0 ) || \\\n\t\t\t  ( buffer != NULL && \\\n\t\t\t    bufSize > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tbufSize <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isEnumRange( signatureType, SIGNATURE ) );\n\tREQUIRES( isECC == TRUE || isECC == FALSE );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Extract the hash value from the context.  If we're doing a length \n\t   check then there's no hash value present yet, so we just fill in the \n\t   hash length value from the blocksize attribute */\n\tif( buffer == NULL )\n\t\t{\n\t\tmemset( hash, 0, CRYPT_MAX_HASHSIZE );\t/* Keep mem.checkers happy */\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &msgData.length, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashSize = msgData.length;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* SSH hardcodes SHA-1 (or at least two fixed-length values of 20 bytes)\n\t   into its signature format, so we can't create an SSH signature unless\n\t   we're using a 20-byte hash */\n\tif( !isECC && signatureType == SIGNATURE_SSH && hashSize != 20 )\n\t\t{\n\t\t/* The error reporting here is a bit complex, see the comment in \n\t\t   createSignature() for how this works */\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* If we're doing a length check and the signature is being written in \n\t   cryptlib format the length is just an estimate since it can change by \n\t   several bytes depending on whether the signature values have the high \n\t   bit set or not (which requires zero-padding of the ASN.1-encoded \n\t   integers) or have the high bytes set to zero(es).  We use a worst-\n\t   case estimate here and assume that both integers will be of the \n\t   maximum size and need padding, which is rather nasty because it means \n\t   that we can't tell how large a signature will be without actually \n\t   creating it */\n\tif( buffer == NULL )\n\t\t{\n\t\tint sigComponentSize = hashSize;\n\n\t\tif( isECC )\n\t\t\t{\n\t\t\t/* For ECC signatures the reduction is done mod n, which is\n\t\t\t   variable-length, but for standard curves is the same as the\n\t\t\t   key size */\n\t\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &sigComponentSize, \n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tswitch( signatureType )\n\t\t\t{\n#ifdef USE_PGP\n\t\t\tcase SIGNATURE_PGP:\n\t\t\t\t*length = 2 * ( 2 + sigComponentSize );\n\t\t\t\tbreak;\n#endif /* USE_PGP */\n\n#ifdef USE_SSH\n\t\t\tcase SIGNATURE_SSH:\n\t\t\t\t*length = 2 * sigComponentSize;\n\t\t\t\tbreak;\n#endif /* USE_SSH */\n\n#ifdef USE_INT_ASN1\n\t\t\tdefault:\n\t\t\t\t*length = sizeofObject( \\\n\t\t\t\t\t\t\t\t( 2 * sizeofObject( \\\n\t\t\t\t\t\t\t\t\t\tsigComponentSize + 1 ) ) );\n\t\t\t\tbreak;\n#else\n\t\t\tdefault:\n\t\t\t\tretIntError();\n#endif /* USE_INT_ASN1 */\n\t\t\t}\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Sign the data */\n\tsetDLPParams( &dlpParams, hash, hashSize, buffer, bufSize );\n\tif( signatureType == SIGNATURE_PGP )\n\t\tdlpParams.formatType = CRYPT_FORMAT_PGP;\n\tif( signatureType == SIGNATURE_SSH )\n\t\tdlpParams.formatType = CRYPT_IFORMAT_SSH;\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_CTX_SIGN, \n\t\t\t\t\t\t\t  &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*length = dlpParams.outLen;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_SIGN\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_SIGN\" ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Check a DLP signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkDlpSignature( IN_BUFFER( signatureDataLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *signatureData, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int signatureDataLength,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t\t  IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE signatureType )\n\t{\n\tDLP_PARAMS dlpParams;\n\tMESSAGE_DATA msgData;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint hashSize, status;\n\n\tREQUIRES( ( signatureType == SIGNATURE_SSH && \\\n\t\t\t\tsignatureDataLength == 40 ) || \\\n\t\t\t  ( signatureDataLength > 40 && \\\n\t\t\t\tsignatureDataLength < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isHandleRangeValid( iSigCheckContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isEnumRange( signatureType, SIGNATURE ) );\n\n\t/* Extract the hash value from the context */\n\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashSize = msgData.length;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Check the signature validity using the encoded signature data and \n\t   hash */\n\tsetDLPParams( &dlpParams, hash, hashSize, NULL, 0 );\n\tdlpParams.inParam2 = signatureData;\n\tdlpParams.inLen2 = signatureDataLength;\n\tif( signatureType == SIGNATURE_PGP )\n\t\tdlpParams.formatType = CRYPT_FORMAT_PGP;\n\tif( signatureType == SIGNATURE_SSH )\n\t\tdlpParams.formatType = CRYPT_IFORMAT_SSH;\n\tstatus = krnlSendMessage( iSigCheckContext, IMESSAGE_CTX_SIGCHECK,\n\t\t\t\t\t\t\t  &dlpParams, sizeof( DLP_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_SIGCHECK\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_SIGCHECK\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCreate a Signature\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Common signature-creation routine, used by other sign_xxx.c modules */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignature( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t IN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *signatureLength, \n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iHashContext2,\n\t\t\t\t\t IN_ENUM( SIGNATURE ) const SIGNATURE_TYPE signatureType )\n\t{\n\tSTREAM stream;\n\tconst WRITESIG_FUNCTION writeSigFunction = getWriteSigFunction( signatureType );\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBYTE *bufPtr = ( signature == NULL ) ? NULL : buffer;\n\tconst BOOLEAN isSSLsig = ( signatureType == SIGNATURE_SSL ) ? TRUE : FALSE;\n\tconst int bufSize = ( signature == NULL ) ? 0 : CRYPT_MAX_PKCSIZE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint signAlgo, hashAlgo, length DUMMY_INIT, hashParam = 0, status;\n\n\tassert( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( signature, sigMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\n\tREQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\t  ( signature != NULL && \\\n\t\t\t    sigMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tsigMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( signatureType == SIGNATURE_SSL && \\\n\t\t\t\tisHandleRangeValid( iHashContext2 ) ) || \\\n\t\t\t  ( ( signatureType == SIGNATURE_CMS || \\\n\t\t\t\t  signatureType == SIGNATURE_CRYPTLIB || \\\n\t\t\t\t  signatureType == SIGNATURE_PGP || \\\n\t\t\t\t  signatureType == SIGNATURE_RAW || \\\n\t\t\t\t  signatureType == SIGNATURE_SSH || \\\n\t\t\t\t  signatureType == SIGNATURE_TLS12 || \\\n\t\t\t\t  signatureType == SIGNATURE_X509 ) && \\\n\t\t\t\tiHashContext2 == CRYPT_UNUSED ) );\n\n\t/* Clear return value */\n\tif( signature != NULL )\n\t\tmemset( signature, 0, min( 16, sigMaxLength ) );\n\t*signatureLength = 0;\n\n\t/* Make sure that the requested signature format is available */\n\tif( writeSigFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Extract general information */\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, &signAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashParam, CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* DLP and ECDLP signatures are handled somewhat specially */\n\tINJECT_FAULT( MECH_CORRUPT_HASH, MECH_CORRUPT_HASH_1 );\n\tif( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )\n\t\t{\n\t\t/* In addition to the special-case processing for DLP/ECDLP \n\t\t   signatures, we have to provide even further special handling for \n\t\t   SSL signatures, which normally sign a dual hash of MD5 and SHA-1 \n\t\t   but for DLP only sign the second SHA-1 hash */\n\t\tstatus = createDlpSignature( bufPtr, bufSize, &length, iSignContext, \n\t\t\t\t\t\t\t\t\t isSSLsig ? iHashContext2 : iHashContext, \n\t\t\t\t\t\t\t\t\t signatureType, \n\t\t\t\t\t\t\t\t\t isEccAlgo( signAlgo ) ? TRUE : FALSE );\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_SIGN\" );\n\t\t}\n\telse\n\t\t{\n\t\tMECHANISM_SIGN_INFO mechanismInfo;\n\n\t\t/* It's a standard signature, process it as normal */\n\t\tsetMechanismSignInfo( &mechanismInfo, bufPtr, bufSize, iHashContext, \n\t\t\t\t\t\t\t  iHashContext2, iSignContext );\n\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_DEV_SIGN, &mechanismInfo,\n\t\t\t\t\t\t\t\t  isSSLsig ? MECHANISM_SIG_SSL : \\\n\t\t\t\t\t\t\t\t\t\t\t MECHANISM_SIG_PKCS1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlength = mechanismInfo.signatureLength;\n\t\tclearMechanismInfo( &mechanismInfo );\n\t\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_SIGN\" );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The mechanism messages place the acted-on object (in this case the\n\t\t   hash context) first while the higher-level functions place the\n\t\t   signature context next to the signature data, in other words\n\t\t   before the hash context.  Because of this we have to reverse\n\t\t   parameter error values when translating from the mechanism to the\n\t\t   signature function level */\n\t\tif( bufPtr != NULL )\n\t\t\tzeroise( bufPtr, CRYPT_MAX_PKCSIZE );\n\t\treturn( ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t\tCRYPT_ARGERROR_NUM2 : \\\n\t\t\t\t( status == CRYPT_ARGERROR_NUM2 ) ? \\\n\t\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tINJECT_FAULT( MECH_CORRUPT_SIG, MECH_CORRUPT_SIG_1 );\n\n\t/* If we're perfoming a dummy sign for a length check, set up a dummy \n\t   value to write */\n\tif( signature == NULL )\n\t\tmemset( buffer, 0x01, length );\n\n\t/* Write the signature record to the output */\n\tsMemOpenOpt( &stream, signature, sigMaxLength );\n\tstatus = writeSigFunction( &stream, iSignContext, hashAlgo, hashParam, \n\t\t\t\t\t\t\t   signAlgo, buffer, length );\n\tif( cryptStatusOK( status ) )\n\t\t*signatureLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tCFI_CHECK_UPDATE( \"writeSigFunction\" );\n\n\t/* Clean up */\n\tzeroise( buffer, CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_SIGN\", \"writeSigFunction\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck a Signature\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Common signature-checking routine, used by other sign_xxx.c modules */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\tIN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iHashContext2,\n\t\t\t\t\tIN_ENUM( SIGNATURE ) const SIGNATURE_TYPE signatureType )\n\t{\n\tMECHANISM_SIGN_INFO mechanismInfo;\n\tconst READSIG_FUNCTION readSigFunction = getReadSigFunction( signatureType );\n\tQUERY_INFO queryInfo;\n\tSTREAM stream;\n\tvoid *signatureData;\n\tconst BOOLEAN isSSLsig = ( signatureType == SIGNATURE_SSL ) ? TRUE : FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint signAlgo, hashAlgo, hashAlgoParam = 0;\n\tint signatureDataLength, compareType = MESSAGE_COMPARE_NONE, status;\n\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\n\tREQUIRES( signatureLength > 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iSigCheckContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( signatureType == SIGNATURE_SSL && \\\n\t\t\t\tisHandleRangeValid( iHashContext2 ) ) || \\\n\t\t\t  ( ( signatureType == SIGNATURE_CMS || \\\n\t\t\t\t  signatureType == SIGNATURE_CRYPTLIB || \\\n\t\t\t\t  signatureType == SIGNATURE_PGP || \\\n\t\t\t\t  signatureType == SIGNATURE_RAW || \\\n\t\t\t\t  signatureType == SIGNATURE_SSH || \\\n\t\t\t\t  signatureType == SIGNATURE_TLS12 || \\\n\t\t\t\t  signatureType == SIGNATURE_X509 ) && \\\n\t\t\t\tiHashContext2 == CRYPT_UNUSED ) );\n\n\t/* Make sure that the requested signature format is available */\n\tif( readSigFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Extract general information */\n\tstatus = krnlSendMessage( iSigCheckContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &signAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) && isHashMacExtAlgo( hashAlgo ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashAlgoParam, CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Read and check the signature record */\n\tsMemConnect( &stream, signature, signatureLength );\n\tstatus = readSigFunction( &stream, &queryInfo );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readSigFunction\" );\n\n\t/* Make sure that we've been given the correct algorithms */\n\tif( signatureType != SIGNATURE_RAW && signatureType != SIGNATURE_SSL )\n\t\t{\n\t\tif( signAlgo != queryInfo.cryptAlgo || \\\n\t\t\thashAlgo != queryInfo.hashAlgo )\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\tif( signatureType != SIGNATURE_SSH )\n\t\t\t{\n\t\t\t/* SSH requires complex string-parsing to determine the optional\n\t\t\t   parameters, so the check is done elsewhere */\n\t\t\tif( isHashMacExtAlgo( hashAlgo ) && \\\n\t\t\t\thashAlgoParam != queryInfo.hashAlgoParam )\n\t\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that we've been given the correct key if the signature\n\t   format supports this type of check */\n\tswitch( signatureType )\n\t\t{\n\t\tcase SIGNATURE_CMS:\n\t\t\t/* This format supports a check with \n\t\t\t   MESSAGE_COMPARE_ISSUERANDSERIALNUMBER but this has already \n\t\t\t   been done while procesing the other CMS data before we were \n\t\t\t   called so we don't need to do it again */\n\t\t\t/* compareType = MESSAGE_COMPARE_ISSUERANDSERIALNUMBER; */\n\t\t\tbreak;\n\n\t\tcase SIGNATURE_CRYPTLIB:\n\t\t\tcompareType = MESSAGE_COMPARE_KEYID;\n\t\t\tbreak;\n\n\t\tcase SIGNATURE_PGP:\n\t\t\tcompareType = ( queryInfo.version == PGP_VERSION_2 ) ? \\\n\t\t\t\t\t\t\tMESSAGE_COMPARE_KEYID_PGP : \\\n\t\t\t\t\t\t\tMESSAGE_COMPARE_KEYID_OPENPGP;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* Other format types don't include identification information\n\t\t\t   with the signature */\n\t\t\tbreak;\n\t\t}\n\tif( compareType != MESSAGE_COMPARE_NONE )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );\n\t\tstatus = krnlSendMessage( iSigCheckContext, IMESSAGE_COMPARE,\n\t\t\t\t\t\t\t\t  &msgData, compareType );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\tcompareType == MESSAGE_COMPARE_KEYID )\n\t\t\t{\n\t\t\t/* Checking for the keyID gets a bit complicated, in theory it's \n\t\t\t   the subjectKeyIdentifier from a certificate but in practice \n\t\t\t   this form is mostly used for certificateless public keys.  \n\t\t\t   Because of this we check for the keyID first and if that \n\t\t\t   fails fall back to the sKID */\n\t\t\tstatus = krnlSendMessage( iSigCheckContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_SUBJECTKEYIDENTIFIER );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* A failed comparison is reported as a generic CRYPT_ERROR,\n\t\t\t   convert it into a wrong-key error */\n\t\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t\t}\n\t\t}\n\tREQUIRES( boundsCheck( queryInfo.dataStart, queryInfo.dataLength,\n\t\t\t\t\t\t   signatureLength ) );\n\tsignatureData = ( BYTE * ) signature + queryInfo.dataStart;\n\tsignatureDataLength = queryInfo.dataLength;\n\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_COMPARE\" );\n\n\t/* DLP and ECDLP signatures are handled somewhat specially */\n\tif( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )\n\t\t{\n\t\t/* In addition to the special-case processing for DLP/ECDLP \n\t\t   signatures, we have to provide even further special handling for \n\t\t   SSL signatures, which normally sign a dual hash of MD5 and SHA-1 \n\t\t   but for DLP only sign the second SHA-1 hash */\n\t\tstatus = checkDlpSignature( signatureData, signatureDataLength, \n\t\t\t\t\t\t\t\t\tiSigCheckContext, \n\t\t\t\t\t\t\t\t\tisSSLsig ? iHashContext2 : iHashContext,\n\t\t\t\t\t\t\t\t\tsignatureType );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"checkDlpSignature\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\t\"readSigFunction\", \"IMESSAGE_COMPARE\", \n\t\t\t\t\t\t\t\t\t\t\"checkDlpSignature\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a standard signature, process it as normal */\n\tsetMechanismSignInfo( &mechanismInfo, signatureData, signatureDataLength, \n\t\t\t\t\t\t  iHashContext, iHashContext2, iSigCheckContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_SIGCHECK, \n\t\t\t\t\t\t\t  &mechanismInfo, isSSLsig ? MECHANISM_SIG_SSL : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t MECHANISM_SIG_PKCS1 );\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The mechanism messages place the acted-on object (in this case the \n\t\t   hash context) first while the higher-level functions place the \n\t\t   signature context next to the signature data, in other words \n\t\t   before the hash context.  Because of this we have to reverse \n\t\t   parameter error values when translating from the mechanism to the \n\t\t   signature function level */\n\t\treturn( ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t\tCRYPT_ARGERROR_NUM2 : \\\n\t\t\t\t( status == CRYPT_ARGERROR_NUM2 ) ? \\\n\t\t\t\t\tCRYPT_ARGERROR_NUM1 : status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_SIGCHECK\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \"readSigFunction\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_COMPARE\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_SIGCHECK\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n"
  },
  {
    "path": "deps/cl345/mechs/sign_pgp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Signature Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_PGP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a PGP signature packet header:\n\n\t\t-- Start of hashed data --\n\t\tbyte\tversion = 4\n\t\tbyte\tsigType\n\t\tbyte\tsigAlgo\n\t\tbyte\thashAlgo\n\t\tuint16\tlength of auth.attributes\n\t\tbyte[]\tauthenticated attributes\n\t\t-- End of hashed data --\n\t\tuint16\tlength of unauth.attributes = 0\n\t  [\tbyte[2]\thash check ]\n\t  [\tmpi(s)\tsignature  ]\n\n   See the comment in createSignaturePGP() for the use of this function */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int writePgpSigPacketHeader( OUT_BUFFER_OPT( dataMaxLen, *dataLen ) \\\n\t\t\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataMaxLen,\n\t\t\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( dataMaxLen ) \\\n\t\t\t\t\t\t\t\t\t\tint *dataLen,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t\t\t\tIN_BUFFER_OPT( sigAttributeLength ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *sigAttributes,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z \\\n\t\t\t\t\t\t\t\t\t\tconst int sigAttributeLength,\n\t\t\t\t\t\t\t\t\tIN_RANGE( PGP_SIG_NONE, PGP_SIG_LAST - 1 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int sigType,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int iAndSlength )\n\t{\n\tSTREAM stream;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ PGP_KEYID_SIZE + 8 ];\n\tBYTE iAndSHeader[ 64 + 8 ];\n\tconst time_t currentTime = getApproxTime();\n\tint hashAlgo, signAlgo, pgpHashAlgo, pgpSignAlgo;\t/* int vs.enum */\n\tint iAndSHeaderLength = 0, length, status;\n\n\tassert( ( data == NULL && dataMaxLen == 0 ) || \\\n\t\t\tisWritePtrDynamic( data, dataMaxLen ) );\n\tassert( isWritePtr( dataLen, sizeof( int ) ) );\n\tassert( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( sigAttributes, sigAttributeLength ) );\n\n\tREQUIRES( ( data == NULL && dataMaxLen == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataMaxLen > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tdataMaxLen < MAX_INTLENGTH_SHORT ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\t  ( sigAttributes != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( sigAttributeLength ) ) );\n\tREQUIRES( isEnumRangeOpt( sigType, PGP_SIG ) );\n\tREQUIRES( isShortIntegerRange( iAndSlength ) );\n\n\t/* Clear return value */\n\t*dataLen = 0;\n\n\t/* Get the signature information */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );\n\tif( cryptStatusError( cryptlibToPgpAlgo( hashAlgo, &pgpHashAlgo ) ) )\n\t\treturn( CRYPT_ARGERROR_NUM2 );\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &signAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\tif( cryptStatusError( cryptlibToPgpAlgo( signAlgo, &pgpSignAlgo ) ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tsetMessageData( &msgData, keyID, PGP_KEYID_SIZE );\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );\n\tif( cryptStatusError( status ) )\n\t\treturn( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );\n\tINJECT_FAULT( CORRUPT_ID, CORRUPT_ID_PGP_1 );\n\n\t/* Write the issuerAndSerialNumber packet header if necessary.  Since\n\t   this is a variable-length packet we need to pre-encode it before we\n\t   can write the main packet data:\n\n\t\tbyte[]\t\tlength\n\t\tbyte\t\tsubpacketType\n\t\tuint32\t\tflags = 0\n\t\tuint16\t\ttypeLength\n\t\tuint16\t\tvalueLength\n\t\tbyte[]\t\ttype\n\t\tbyte[]\t\tvalue */\n\tif( iAndSlength > 0 )\n\t\t{\n\t\tSTREAM headerStream;\n\n\t\tsMemOpen( &headerStream, iAndSHeader, 64 );\n\t\tpgpWriteLength( &headerStream, \\\n\t\t\t\t\t\t1 + UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + \\\n\t\t\t\t\t\t21 + iAndSlength );\n\t\tsputc( &headerStream, PGP_SUBPACKET_TYPEANDVALUE );\n\t\twriteUint32( &headerStream, 0 );\n\t\twriteUint16( &headerStream, 21 );\n\t\twriteUint16( &headerStream, iAndSlength );\n\t\tstatus = swrite( &headerStream, \"issuerAndSerialNumber\", 21 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tiAndSHeaderLength = stell( &headerStream );\n\t\tsMemDisconnect( &headerStream );\n\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\n\t/* Write the general header information */\n\tsMemOpenOpt( &stream, data, dataMaxLen );\n\tsputc( &stream, PGP_VERSION_OPENPGP );\n\tsputc( &stream, sigType );\n\tsputc( &stream, pgpSignAlgo );\n\tstatus = sputc( &stream, pgpHashAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the authenticated attributes:\n\n\t\tuint16\t\tauthAttrLength\n\t\tbyte\t\tsubpacketLength = 1 + UINT32_SIZE\n\t\tbyte\t\tID = PGP_SUBPACKET_TIME\n\t\tuint32\t\ttime\n\t\tbyte\t\tsubpacketLength = 1 + PGP_KEYID_SIZE\n\t\tbyte\t\tID = PGP_SUBPACKET_KEYID\n\t\tbyte[8]\t\tsignerID\n\t  [ byte[]\t\tsigned attributes ]\n\t  [\tbyte[]\t\ttypeAndValue packet for iAndS ]\n\t\n\t   The signer ID is optional, but if we omit it GPG fails the signature \n\t   check so we always include it */\n\tlength = ( 1 + 1 + UINT32_SIZE ) + ( 1 + 1 + PGP_KEYID_SIZE ) + \\\n\t\t\t sigAttributeLength;\n\tif( iAndSlength > 0 )\n\t\tlength += iAndSHeaderLength + iAndSlength;\n\twriteUint16( &stream, length );\n\tsputc( &stream, 1 + UINT32_SIZE );\t\t/* Time */\n\tsputc( &stream, PGP_SUBPACKET_TIME );\n\twriteUint32Time( &stream, currentTime );\n\tsputc( &stream, 1 + PGP_KEYID_SIZE );\t/* Signer ID */\n\tsputc( &stream, PGP_SUBPACKET_KEYID );\n\tstatus = swrite( &stream, keyID, PGP_KEYID_SIZE );\n\tif( cryptStatusOK( status ) && sigAttributeLength > 0 )\n\t\tstatus = swrite( &stream, sigAttributes, sigAttributeLength );\n\tif( cryptStatusOK( status ) && iAndSlength > 0 )\n\t\t{\t\t\t\t\t\t\t\t\t/* TypeAndValue */\n\t\tstatus = swrite( &stream, iAndSHeader, iAndSHeaderLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = exportAttributeToStream( &stream, iSignContext,\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the unauthenticated attributes:\n\n\t\tuint16\t\tunauthAttrLength = 0 */\n\tstatus = writeUint16( &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t*dataLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCreate/Check a PGP Signature\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a PGP signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createSignaturePGP( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_DATALENGTH_Z const int sigMaxLength, \n\t\t\t\t\t\tOUT_DATALENGTH_Z int *signatureLength, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\tIN_BUFFER_OPT( sigAttributeLength ) \\\n\t\t\t\t\t\t\tconst void *sigAttributes,\n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int sigAttributeLength,\n\t\t\t\t\t\tIN_RANGE( PGP_SIG_NONE, PGP_SIG_LAST - 1 ) \\\n\t\t\t\t\t\t\tconst int sigType )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE signatureData[ CRYPT_MAX_PKCSIZE + 128 + 8 ];\n\tBYTE extraData[ 1024 + 8 ], *extraDataPtr = extraData;\n\tBYTE extraTrailer[ 8 + 8 ];\n\tint extraDataLength = 1024, extraTrailerLength DUMMY_INIT;\n\tint signatureDataLength, iAndSlength = 0, totalLength DUMMY_INIT;\n\tint status;\n\n\tassert( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( signature, sigMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\tassert( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( sigAttributes, sigAttributeLength ) );\n\n\tREQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \\\n\t\t\t  ( signature != NULL && \\\n\t\t\t\tsigMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t\tsigMaxLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( ( sigAttributes == NULL && sigAttributeLength == 0 ) || \\\n\t\t\t  ( sigAttributes != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( sigAttributeLength ) ) );\n\tREQUIRES( isEnumRangeOpt( sigType, PGP_SIG ) );\n\n\t/* Check whether there's an issuerAndSerialNumber present */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );\n\tif( cryptStatusOK( status ) )\n\t\tiAndSlength = msgData.length;\n\n\t/* If it's a length check only, determine how large the signature data\n\t   will be and exit */\n\tif( signature == NULL )\n\t\t{\n\t\tstatus = writePgpSigPacketHeader( NULL, 0, &extraDataLength, \n\t\t\t\t\t\t\t\t\t\t  iSignContext, iHashContext, \n\t\t\t\t\t\t\t\t\t\t  sigAttributes, sigAttributeLength,\n\t\t\t\t\t\t\t\t\t\t  sigType, iAndSlength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = createSignature( NULL, 0, &signatureDataLength, \n\t\t\t\t\t\t\t\t  iSignContext, iHashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  SIGNATURE_PGP );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*signatureLength = 1 + pgpSizeofLength( extraDataLength + 2 + \\\n\t\t\t\t\t\t\t\t\t\t\t\tsignatureDataLength ) + \\\n\t\t\t\t\t\t   extraDataLength + 2 + signatureDataLength;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's an issuerAndSerialNumber present, allocate a larger buffer \n\t   for it if necessary (this virtually never occurs, the iAndS would need\n\t   to be over 1kB long.  Note that we can't use a dynBuf for this \n\t   because we're allocating a buffer larger than the attribute, not the \n\t   same size as the attribute */\n\tif( iAndSlength > extraDataLength - 128 )\n\t\t{\n\t\textraDataLength = 128 + iAndSlength;\n\t\tif( ( extraDataPtr = clDynAlloc( \"createSignaturePGP\", \\\n\t\t\t\t\t\t\t\t\t\t extraDataLength ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t}\n\n\t/* Complete the hashing and create the signature.  In theory this could\n\t   get ugly because there could be multiple one-pass signature packets\n\t   present, however PGP handles multiple signatures by nesting them so\n\t   this isn't a problem.\n\n\t   PGP processes the authenticated attributes in an odd way, first\n\t   hashing part of the packet from the version number to the end of the\n\t   authenticated attributes, then hashing some more (out-of-band) stuff, \n\t   and finally signing the result of the overall hashing.  Because of \n\t   this complex way of handling things we can't write the signature \n\t   packet in one go but instead have to write the part that we can \n\t   create now, hash the portion that's hashed (all but the last 16 bits, \n\t   the length of the unathenticated attributes), and then go back and \n\t   assemble the whole thing including the length and signature later on \n\t   from the pre-hashed data and the length, hash check, and signature */\n\tstatus = writePgpSigPacketHeader( extraData, extraDataLength, \n\t\t\t\t\t\t\t\t\t  &extraDataLength, iSignContext,\n\t\t\t\t\t\t\t\t\t  iHashContext, sigAttributes, \n\t\t\t\t\t\t\t\t\t  sigAttributeLength, sigType, \n\t\t\t\t\t\t\t\t\t  iAndSlength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  extraData, extraDataLength - UINT16_SIZE );\n\t\tif( status == CRYPT_ERROR_COMPLETE )\n\t\t\t{\n\t\t\t/* Unlike standard signatures PGP requires that the hashing not \n\t\t\t   be wrapped up before the signature is generated because it \n\t\t\t   needs to hash in further data before it can generate the \n\t\t\t   signature.  Since completing the hashing is likely to be a \n\t\t\t   common error we specifically check for this and return an\n\t\t\t   appropriate error code */\n\t\t\tstatus = CRYPT_ARGERROR_NUM2;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( extraDataPtr, extraDataLength );\n\t\tif( extraDataPtr != extraData )\n\t\t\tclFree( \"createSignaturePGP\", extraDataPtr );\n\t\treturn( status );\n\t\t}\n\tINJECT_FAULT( ENVELOPE_CORRUPT_AUTHATTR, \n\t\t\t\t  ENVELOPE_CORRUPT_AUTHATTR_PGP_1 );\n\n\t/* Hash in even more stuff at the end.  This is a complex jumble of \n\t   items comprising a version number, an 0xFF, and another length.  \n\t   This was motivated by a concern that something that meant one thing \n\t   in a version n sig could mean something different when interpreted as \n\t   a version n+1 sig.  For this reason a hash-convention version (v4) \n\t   was added, along with a disambiguator 0xFF that will never be found \n\t   at that position in older (v3) hash-convention sigs (the 0x04 is in \n\t   fact redundant but may be needed at some point if the hash \n\t   convention moves to a v5 format).  The length has something to do \n\t   with parsing the packet from the end, so that out-of-band data \n\t   doesn't run into payload data, but no-one can quite remember why \n\t   it's actually there */\n\tsMemOpen( &stream, extraTrailer, 8 );\n\tsputc( &stream, 0x04 );\n\tsputc( &stream, 0xFF );\n\tstatus = writeUint32( &stream, extraDataLength - UINT16_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\textraTrailerLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t  extraTrailer, extraTrailerLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( extraDataPtr, extraDataLength );\n\t\tif( extraDataPtr != extraData )\n\t\t\tclFree( \"createSignaturePGP\", extraDataPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* We've finally finished with all the hashing, create the signature */\n\tstatus = createSignature( signatureData, CRYPT_MAX_PKCSIZE + 128, \n\t\t\t\t\t\t\t  &signatureDataLength, iSignContext, \n\t\t\t\t\t\t\t  iHashContext, CRYPT_UNUSED, SIGNATURE_PGP );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttotalLength = 1 + \\\n\t\t\t\t\t  pgpSizeofLength( extraDataLength + 2 + \\\n\t\t\t\t\t\t\t\t\t   signatureDataLength ) + \\\n\t\t\t\t\t  extraDataLength + 2 + signatureDataLength;\n\t\tif( totalLength + 64 > sigMaxLength )\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( extraDataPtr, extraDataLength );\n\t\tif( extraDataPtr != extraData )\n\t\t\tclFree( \"createSignaturePGP\", extraDataPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the signature packet:\n\n\t  [\tsignature packet header ]\n\t\tbyte[2]\thash check\n\t\tmpi\t\tsignature\n\n\t  Since we've already had to write half the packet earlier on in order\n\t  to hash it we copy this pre-encoded information across and add the \n\t  header and trailer around it */\n\tsMemOpen( &stream, signature, totalLength + 64 );\n\tpgpWritePacketHeader( &stream, PGP_PACKET_SIGNATURE,\n\t\t\t\t\t\t  extraDataLength + 2 + signatureDataLength );\n\tswrite( &stream, extraData, extraDataLength );\n\tswrite( &stream, hash, 2 );\t\t\t/* Hash check */\n\tstatus = swrite( &stream, signatureData, signatureDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t*signatureLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tzeroise( extraDataPtr, extraDataLength );\n\tzeroise( signatureData, CRYPT_MAX_PKCSIZE + 128 );\n\tif( extraDataPtr != extraData )\n\t\tclFree( \"createSignaturePGP\", extraDataPtr );\n\n\treturn( status );\n\t}\n\n/* Check a PGP signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkSignaturePGP( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_DATALENGTH const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext )\n\t{\n\tconst READSIG_FUNCTION readSigFunction = getReadSigFunction( SIGNATURE_PGP );\n\tQUERY_INFO queryInfo;\n\tSTREAM stream;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\n\tREQUIRES( signatureLength > 40 && signatureLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( sigCheckContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\n\t/* Make sure that the requested signature format is available */\n\tif( readSigFunction == NULL )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Determine whether there are any authenticated attributes attached to\n\t   the signature */\n\tsMemConnect( &stream, signature, signatureLength );\n\tstatus = readSigFunction( &stream, &queryInfo );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readSigFunction\" );\n\n\t/* After hashing the content, PGP also hashes in extra authenticated\n\t   attributes, see the earlier comment in createSignaturePGP() */\n\tREQUIRES( boundsCheck( queryInfo.attributeStart, \n\t\t\t\t\t\t   queryInfo.attributeLength, queryInfo.size ) );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  ( BYTE * ) signature + queryInfo.attributeStart,\n\t\t\t\t\t\t\t  queryInfo.attributeLength );\n\tif( cryptStatusOK( status ) && queryInfo.attributeLength != 5 )\n\t\t{\n\t\tBYTE buffer[ 8 + 8 ];\n\t\tint length DUMMY_INIT;\n\n\t\t/* In addition to the standard authenticated attributes OpenPGP\n\t\t   hashes in even more stuff at the end (see the comments for \n\t\t   createSignaturePGP() for more on this) */\n\t\tsMemOpen( &stream, buffer, 8 );\n\t\tsputc( &stream, 0x04 );\n\t\tsputc( &stream, 0xFF );\n\t\tstatus = writeUint32( &stream, queryInfo.attributeLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t\t  buffer, length );\n\t\t\t}\n\t\t}\n\tzeroise( &queryInfo, sizeof( QUERY_INFO ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_HASH\" );\n\n\t/* Check the signature */\n\tstatus = checkSignature( signature, signatureLength, sigCheckContext,\n\t\t\t\t\t\t\t iHashContext, CRYPT_UNUSED, SIGNATURE_PGP );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkSignature\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"readSigFunction\", \"IMESSAGE_CTX_HASH\", \n\t\t\t\t\t\t\t\t\t\"checkSignature\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP */\n"
  },
  {
    "path": "deps/cl345/mechs/sign_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Signature Read/Write Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"enc_dec/pgp_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n/* Context-specific tags for the SignerInfo record */\n\nenum { CTAG_SI_SKI };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tX.509 Signature Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Read/write raw signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readRawSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the start of the signature */\n\tstatus = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,\n\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeRawSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t  STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t  IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( signatureLength >= 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\t/* Write the BIT STRING wrapper and signature */\n\twriteBitStringHole( stream, signatureLength, DEFAULT_TAG );\n\treturn( writeRawObject( stream, signature, signatureLength ) );\n\t}\n\n/* Read/write X.509 signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readX509Signature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the signature/hash algorithm information followed by the start\n\t   of the signature */\n\tstatus = readAlgoIDex( stream, &queryInfo->cryptAlgo,\n\t\t\t\t\t\t   &queryInfo->hashAlgo, &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t   ALGOID_CLASS_PKCSIG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,\n\t\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeX509Signature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t   STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t   IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( signatureLength >= 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\t/* Write the hash+signature algorithm identifier followed by the BIT\n\t   STRING wrapper and signature */\n\twriteContextAlgoIDex( stream, iSignContext, hashAlgo );\n\twriteBitStringHole( stream, signatureLength, DEFAULT_TAG );\n\treturn( writeRawObject( stream, signature, signatureLength ) );\n\t}\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMS Signature Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_CMS\n\n/* Read/write PKCS #7/CMS (issuerAndSerialNumber) signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCmsSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tlong value, endPos;\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = startPos + length;\n\n\t/* Read the header */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != SIGNATURE_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the issuer and serial number and hash algorithm ID.  Since we're \n\t   recording the position of the issuerAndSerialNumber as a blob we have \n\t   to use getStreamObjectLength() to get the overall blob data size */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->iAndSStart = stell( stream ) - startPos;\n\tqueryInfo->iAndSLength = length;\n\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDex( stream, &queryInfo->hashAlgo, NULL, \n\t\t\t\t\t\t\t   &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t\t   ALGOID_CLASS_HASH );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the authenticated attributes if there are any present */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\tstatus = getStreamObjectLength( stream, &length );\n\t\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->attributeStart = stell( stream ) - startPos;\n\t\tqueryInfo->attributeLength = length;\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the CMS/cryptlib signature algorithm and the start of the \n\t   signature.  CMS separates the signature algorithm from the hash \n\t   algorithm so we read it as ALGOID_CLASS_PKC and not \n\t   ALGOID_CLASS_PKCSIG.  Unfortunately some buggy implementations get \n\t   this wrong and write an algorithm+hash algoID, to get around this the\n\t   decoding table contains an alternative interpretation of the\n\t   ALGOID_CLASS_PKCSIG information pretending to be an \n\t   ALGOID_CLASS_PKC.  This broken behaviour was codified in RFC 5652\n\t   (section 10.1.2, \"SignatureAlgorithmIdentifier\") so it's now part\n\t   of the standard */\n\tstatus = readAlgoID( stream, &queryInfo->cryptAlgo, \n\t\t\t\t\t\t ALGOID_CLASS_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readOctetStringHole( stream, &queryInfo->dataLength, \n\t\t\t\t\t\t\t\t\t  18 + 18, DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tqueryInfo->dataStart = stell( stream ) - startPos;\n\t\tstatus = sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the unauthenticated attributes if there are any present */\n\tif( stell( stream ) < endPos && \\\n\t\tcheckStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\t{\n\t\tstatus = getStreamObjectLength( stream, &length );\n\t\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->unauthAttributeStart = stell( stream ) - startPos;\n\t\tqueryInfo->unauthAttributeLength = length;\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* Make sure that we've read everything present */\n\tif( stell( stream ) != endPos )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeCmsSignature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t  STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t  IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( signatureLength >= 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\t/* Write the signature algorithm identifier and signature data.  The\n\t   handling of CMS signatures is non-orthogonal to readCmsSignature()\n\t   because creating a CMS signature involves adding assorted additional\n\t   data like iAndS and signed attributes that present too much\n\t   information to pass into a basic writeSignature() call */\n\twriteContextAlgoID( stream, iSignContext );\n\treturn( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );\n\t}\n\n/* Read/write cryptlib/CMS (keyID) signatures */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readCryptlibSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tlong value;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the header */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != SIGNATURE_EX_VERSION )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the key ID and hash algorithm identifier */\n\tstatus = readOctetStringTag( stream, queryInfo->keyID, \n\t\t\t\t\t\t\t\t &queryInfo->keyIDlength, 8, \n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, CTAG_SI_SKI );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoIDex( stream, &queryInfo->hashAlgo, NULL,\n\t\t\t\t\t\t\t   &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t\t   ALGOID_CLASS_HASH );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the CMS/cryptlib signature algorithm and the start of the \n\t   signature.  CMS separates the signature algorithm from the hash\n\t   algorithm so we we use ALGOID_CLASS_PKC rather than \n\t   ALGOID_CLASS_PKCSIG */\n\tstatus = readAlgoID( stream, &queryInfo->cryptAlgo, ALGOID_CLASS_PKC );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readOctetStringHole( stream, &queryInfo->dataLength, \n\t\t\t\t\t\t\t\t\t  18 + 18, DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, queryInfo->dataLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeCryptlibSignature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\t   STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t\t   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t\t   IN_BUFFER( signatureLength ) \\\n\t\t\t\t\t\t\t\t\tconst BYTE *signature,\n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 40 ) \\\n\t\t\t\t\t\t\t\t\tconst int signatureLength )\n\t{\n\tBYTE keyID[ 128 + 8 ];\n\tconst int signAlgoIdSize = sizeofContextAlgoID( iSignContext, 0 );\n\tconst int hashAlgoIdSize = sizeofAlgoID( hashAlgo );\n\tint keyIDlength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( signatureLength >= 40 && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\tif( cryptStatusError( signAlgoIdSize ) )\n\t\treturn( signAlgoIdSize );\n\tif( cryptStatusError( hashAlgoIdSize ) )\n\t\treturn( hashAlgoIdSize );\n\n\t/* Get the key ID */\n\tstatus = getCmsKeyIdentifier( iSignContext, keyID, 128, &keyIDlength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the header */\n\twriteSequence( stream, sizeofShortInteger( SIGNATURE_EX_VERSION ) + \\\n\t\t\t\t   sizeofObject( keyIDlength ) + \\\n\t\t\t\t   signAlgoIdSize + hashAlgoIdSize + \\\n\t\t\t\t   sizeofObject( signatureLength ) );\n\n\t/* Write the version, key ID and algorithm identifier */\n\twriteShortInteger( stream, SIGNATURE_EX_VERSION, DEFAULT_TAG );\n\twriteOctetString( stream, keyID, keyIDlength, CTAG_SI_SKI );\n\twriteAlgoID( stream, hashAlgo );\n\twriteContextAlgoID( stream, iSignContext );\n\treturn( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );\n\t}\n#endif /* USE_INT_CMS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Signature Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_PGP\n\n/* Read a PGP type-and-value packet and check whether it's one of ours */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readTypeAndValue( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t IN_LENGTH_Z const int startPos )\n\t{\n\tBYTE nameBuffer[ 32 + 8 ];\n\tstatic const char *nameString = \"issuerAndSerialNumber\";\n\tint nameLength, valueLength, status;\t/* length = 21 */\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\tREQUIRES( startPos < stell( stream ) );\n\n\t/* Skip the flags */\n\tstatus = sSkip( stream, UINT32_SIZE, UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the attribute length information and make sure that it looks \n\t   valid */\n\tnameLength = readUint16( stream );\n\tstatus = valueLength = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( nameLength < 1 || nameLength > 255 || \\\n\t\t!isShortIntegerRangeNZ( valueLength ) )\n\t\t{\n\t\t/* The RFC is, as usual, silent on what's a sane size for a type-\n\t\t   and-value pair, so we define our own, hopefully sensible, \n\t\t   limits */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( nameLength != 21 || valueLength < 16 || valueLength > 2048 )\n\t\t{\n\t\t/* This is a somewhat different check to the above one in that out-\n\t\t   of-range (but plausible) sizes are skipped rather than being \n\t\t   counted as an error */\n\t\treturn( sSkip( stream, nameLength + valueLength, \n\t\t\t\t\t   MAX_INTLENGTH_SHORT ) );\n\t\t}\n\n\t/* Read the name and check whether it's one that we recognise */\n\tstatus = sread( stream, nameBuffer, nameLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !memcmp( nameBuffer, nameString, nameLength ) )\n\t\t{\n\t\t/* It's an issuerAndSerialNumber, remember it for later */\n\t\tqueryInfo->iAndSStart = stell( stream ) - startPos;\n\t\tqueryInfo->iAndSLength = valueLength;\n\t\t}\n\treturn( sSkip( stream, valueLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\n/* Read signature subpackets.  In theory we could do something with the \n   isAuthenticated flag but at the moment we don't rely on any attributes \n   that require authentication.  The most that an attacker can do by \n   changing the keyID/iAndS field is cause the signature check to fail, \n   which they can do just as easily by flipping a bit */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSignatureSubpackets( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tINOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int length, \n\t\t\t\t\t\t\t\t\tIN_DATALENGTH const int startPos,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isAuthenticated )\n\t{\n\tBOOLEAN seenTimestamp = FALSE;\n\tconst int endPos = stell( stream ) + length;\n\tint noSubpackets, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\tREQUIRES( startPos < stell( stream ) );\n\tREQUIRES( isAuthenticated == TRUE || isAuthenticated == FALSE );\n\tREQUIRES( endPos > 0 && endPos < MAX_BUFFER_SIZE );\n\n\tLOOP_MED( noSubpackets = 0, \n\t\t\t  stell( stream ) < endPos && noSubpackets < 30,\n\t\t\t  noSubpackets++ )\n\t\t{\n\t\tint subpacketLength, type DUMMY_INIT, status;\n\n\t\t/* Read the subpacket length and type */\n\t\tstatus = pgpReadShortLength( stream, &subpacketLength, \n\t\t\t\t\t\t\t\t\t PGP_CTB_OPENPGP );\n\t\tif( cryptStatusOK( status ) && subpacketLength < 1 )\n\t\t\t{\n\t\t\t/* We must have at least a packet-type indicator present */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = type = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If it's an unrecognised subpacket with the critical flag set,\n\t\t   reject the signature.  The range check isn't complete since there\n\t\t   are a few holes in the range, but since the holes presumably exist\n\t\t   because of deprecated subpacket types any new packets will be \n\t\t   added at the end so it's safe to use */\n\t\tif( ( type & 0x80 ) && ( ( type & 0x7F ) > PGP_SUBPACKET_LAST ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\tswitch( type )\n\t\t\t{\n\t\t\tcase PGP_SUBPACKET_TIME:\n\t\t\t\tstatus = sSkip( stream, UINT32_SIZE, UINT32_SIZE );\n\n\t\t\t\t/* Remember that we've seen the (mandatory) timestamp \n\t\t\t\t   packet */\n\t\t\t\tseenTimestamp = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase PGP_SUBPACKET_KEYID:\n\t\t\t\t/* Make sure that the length is valid */\n\t\t\t\tif( subpacketLength != PGP_KEYID_SIZE + 1 )\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t\t\t\t/* If it's a key ID and we haven't already set this from a \n\t\t\t\t   preceding one-pass signature packet (which can happen \n\t\t\t\t   with detached sigs), set it now */\n\t\t\t\tif( queryInfo->keyIDlength <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );\n\t\t\t\t\tqueryInfo->keyIDlength = PGP_KEYID_SIZE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t/* We've already got the ID, skip it and continue.  The \n\t\t\t\t\t   -1 is for the packet type, which we've already read */\n\t\t\t\t\tstatus = sSkip( stream, subpacketLength - 1, \n\t\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase PGP_SUBPACKET_TYPEANDVALUE:\n\t\t\t\t/* It's a type-and-value packet, check whether it's one of \n\t\t\t\t   ours */\n\t\t\t\tstatus = readTypeAndValue( stream, queryInfo, startPos );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\t/* It's something else, skip it and continue.  The -1 is for \n\t\t\t\t   the packet type, which we've already read */\n\t\t\t\tif( subpacketLength > 1 )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = sSkip( stream, subpacketLength - 1, \n\t\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noSubpackets >= 30 )\n\t\t{\n\t\t/* If we've found this many packets in a row all supposedly \n\t\t   belonging to the same signature then there's something wrong */\n\t\tDEBUG_DIAG(( \"Encountered more than %d subpackets for a single \"\n\t\t\t\t\t \"signature\", noSubpackets ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Make sure that the mandatory fields are present in the subpacket \n\t   data.  We also need to check for the presence of the keyID but this\n\t   can be in either the authenticated or unauthenticated attributes, so\n\t   it has to be checked by the calling function */\n\tif( isAuthenticated && !seenTimestamp )\n\t\treturn( CRYPT_ERROR_INVALID );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Signature info:\n\n\tbyte\tctb = PGP_PACKET_SIGNATURE_ONEPASS\n\tbyte[]\tlength\n\tbyte\tversion = 3 (= OpenPGP, not the expected PGP3)\n\tbyte\tsigType\n\tbyte\thashAlgo\n\tbyte\tsigAlgo\n\tbyte[8]\tkeyID\n\tbyte\t1 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPgpOnepassSigPacket( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT QUERY_INFO *queryInfo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\t/* Make sure that the packet header is in order and check the packet\n\t   version.  This is an OpenPGP-only packet */\n\tstatus = getPgpPacketInfo( stream, queryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sgetc( stream ) != 3 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->version = PGP_VERSION_OPENPGP;\n\n\t/* Skip the sig.type and get the hash algorithm and signature \n\t   algorithms */\n\tstatus = sgetc( stream );\t/* Skip signature type */\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = readPgpAlgo( stream, &queryInfo->hashAlgo, \n\t\t\t\t\t\t\t  &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t\t  PGP_ALGOCLASS_HASH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readPgpAlgo( stream, &queryInfo->cryptAlgo, \n\t\t\t\t\t\t\t  &queryInfo->cryptAlgoParam, \n\t\t\t\t\t\t\t  PGP_ALGOCLASS_SIGN );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->type = CRYPT_OBJECT_SIGNATURE;\n\n\t/* Get the PGP key ID and make sure that this isn't a nested signature */\n\tstatus = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->keyIDlength = PGP_KEYID_SIZE;\n\treturn( ( sgetc( stream ) != 1 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );\n\t}\n\n/* Read/write PGP signatures.\n\n\t\tbyte\tctb = PGP_PACKET_SIGNATURE\n\t\tbyte[]\tlength\n\tv3:\tbyte\tversion = PGP_2,3\tv4: byte\tversion = PGP_VERSION_OPENPGP\n\t\tbyte\tinfoLen = 5\t\t\t\tbyte\tsigType\n\t\t\tbyte\tsigType\t\t\t\tbyte\tsigAlgo\n\t\t\tbyte[4]\tsig.time\t\t\tbyte\thashAlgo\n\t\tbyte[8]\tkeyID\t\t\t\t\tuint16\tlength of auth.attributes\n\t\tbyte\tsigAlgo\t\t\t\t\tbyte[]\tauthenticated attributes\n\t\tbyte\thashAlgo\t\t\t\tuint16\tlength of unauth.attributes\n\t\tbyte[2]\thash check\t\t\t\tbyte[]\tunauthenticated attributes\n\t\tmpi(s)\tsignature\t\t\t\t\t\t\t-- Contains keyID\n\t\t\t\t\t\t\t\t\t\tbyte[2]\thash check\n\t\t\t\t\t\t\t\t\t\tmpi(s)\tsignature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgp2SigInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int startPos )\n\t{\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\tREQUIRES( startPos < stell( stream ) );\n\n\t/* Read PGP 2.x additional signature information */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != 5 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->attributeStart = stell( stream ) - startPos;\n\tqueryInfo->attributeLength = 5;\n\tstatus = sSkip( stream, 5, 5 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the signer keyID and signature and hash algorithms */\n\tstatus = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->keyIDlength = PGP_KEYID_SIZE;\n\tstatus = readPgpAlgo( stream, &queryInfo->cryptAlgo, \n\t\t\t\t\t\t  &queryInfo->cryptAlgoParam, PGP_ALGOCLASS_SIGN );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readPgpAlgo( stream, &queryInfo->hashAlgo, \n\t\t\t\t\t\t\t  &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t\t  PGP_ALGOCLASS_HASH );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readOpenPgpSigInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT QUERY_INFO *queryInfo,\n\t\t\t\t\t\t\t   IN_DATALENGTH_Z const int startPos )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\tREQUIRES( startPos < stell( stream ) );\n\n\t/* Remember the extra data to be hashed and read the signature and hash \n\t   algorithms.  Since the extra data starts at the version byte that \n\t   we've already read, we add a -1 offset to the start position, as well\n\t   as including it in the overall length calculation */\n\tqueryInfo->attributeStart = ( stell( stream ) - 1 ) - startPos;\n\tqueryInfo->attributeLength = PGP_VERSION_SIZE + 1 + \\\n\t\t\t\t\t\t\t\t PGP_ALGOID_SIZE + PGP_ALGOID_SIZE;\n\tstatus = sgetc( stream );\t/* Skip signature type */\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = readPgpAlgo( stream, &queryInfo->cryptAlgo, \n\t\t\t\t\t\t\t  &queryInfo->cryptAlgoParam, \n\t\t\t\t\t\t\t  PGP_ALGOCLASS_SIGN );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readPgpAlgo( stream, &queryInfo->hashAlgo, \n\t\t\t\t\t\t\t  &queryInfo->hashAlgoParam, \n\t\t\t\t\t\t\t  PGP_ALGOCLASS_HASH );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Process the authenticated attributes */\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < 0 || length > 2048 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->attributeLength += UINT16_SIZE + length;\n\tif( length > 0 )\n\t\t{\n\t\tstatus = readSignatureSubpackets( stream, queryInfo, length,\n\t\t\t\t\t\t\t\t\t\t  startPos, TRUE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Process the unauthenticated attributes */\n\tqueryInfo->unauthAttributeStart = stell( stream ) - startPos;\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < 0 || length > 2048 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->unauthAttributeLength = UINT16_SIZE + length;\n\tif( length > 0 )\n\t\t{\n\t\tstatus = readSignatureSubpackets( stream, queryInfo, length, \n\t\t\t\t\t\t\t\t\t\t  startPos, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Check the the presence of required attributes.  The mandatory ones \n\t   per the RFC are checked when the authenticated attributes are being\n\t   read, however the keyID, which is required to check the signature,\n\t   can be present in either the authenticated or unauthenticated\n\t   attributes depending on the mood of the implementer, so we have to\n\t   check for it outside the attribute-read code */\n\tif( queryInfo->keyIDlength <= 0 )\n\t\treturn( CRYPT_ERROR_INVALID );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPgpSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Make sure that the packet header is in order and check the packet\n\t   version.  For this packet type a version number of 3 denotes PGP 2.x\n\t   whereas for key transport it denotes OpenPGP */\n\tstatus = getPgpPacketInfo( stream, queryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != PGP_VERSION_2 && value != PGP_VERSION_3 && \\\n\t\tvalue != PGP_VERSION_OPENPGP )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->type = CRYPT_OBJECT_SIGNATURE;\n\tqueryInfo->version = ( value == PGP_VERSION_OPENPGP ) ? \\\n\t\t\t\t\t\t PGP_VERSION_OPENPGP : PGP_VERSION_2;\n\n\t/* Read the signing attributes and skip the hash check */\n\tif( value != PGP_VERSION_OPENPGP )\n\t\tstatus = readPgp2SigInfo( stream, queryInfo, startPos );\n\telse\n\t\tstatus = readOpenPgpSigInfo( stream, queryInfo, startPos );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, 2, 2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the signature, recording the position and length of the raw RSA \n\t   signature data.  We have to be careful how we handle this because \n\t   readInteger16Ubits() returns the canonicalised form of the values \n\t   (with leading zeroes truncated) so an stell() before the read doesn't \n\t   necessarily represent the start of the payload:\n\n\t\tstartPos\tdataStart\t\t stell()\n\t\t\t|\t\t\t|\t\t\t\t|\n\t\t\tv\t\t\tv <-- length -->v\n\t\t+---+-----------+---------------+\n\t\t|\t|\t\t\t|///////////////| Stream\n\t\t+---+-----------+---------------+ */\n\tif( queryInfo->cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\tstatus = readInteger16Ubits( stream, NULL, &queryInfo->dataLength,\n\t\t\t\t\t\t\t\t\t MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->dataStart = ( stell( stream ) - startPos ) - \\\n\t\t\t\t\t\t\t   queryInfo->dataLength;\n\t\t}\n\telse\n\t\t{\n\t\tconst int dataStartPos = stell( stream );\n\t\tint dummy;\n\n\t\tREQUIRES( dataStartPos >= 0 && dataStartPos < MAX_BUFFER_SIZE );\n\t\tREQUIRES( queryInfo->cryptAlgo == CRYPT_ALGO_DSA );\n\n\t\t/* Read the DSA signature, recording the position and combined \n\t\t   lengths of the MPI pair.  Again, we can't use the length returned \n\t\t   by readInteger16Ubits() to determine the overall size but have to \n\t\t   calculate it from the position in the stream */\n\t\tstatus = readInteger16Ubits( stream, NULL, &dummy, 16, 20 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readInteger16Ubits( stream, NULL, &dummy, 16, 20 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tqueryInfo->dataStart = dataStartPos - startPos;\n\t\tqueryInfo->dataLength = stell( stream ) - dataStartPos;\n\t\t}\n\n\t/* Make sure that we've read the entire object.  This check is necessary \n\t   to detect corrupted length values, which can result in reading past \n\t   the end of the object */\n\tif( ( stell( stream ) - startPos ) != queryInfo->size )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writePgpSignature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t  STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t  IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \\\n\t\t\t\t\t\t\t\tconst int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( isPkcAlgo( signAlgo ) );\n\tREQUIRES( signatureLength > ( 18 + 18 ) && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\t/* If it's a DLP/ECDLP algorithm then we've already specified the low-\n\t   level signature routines' output format as PGP so there's no need for \n\t   further processing.  The handling of PGP signatures is non-orthogonal \n\t   to readPgpSignature() because creating a PGP signature involves \n\t   adding assorted additional data like key IDs and authenticated \n\t   attributes, which present too much information to pass into a basic \n\t   writeSignature() call */\n\tif( isDlpAlgo( signAlgo ) || isEccAlgo( signAlgo ) )\n\t\treturn( swrite( stream, signature, signatureLength ) );\n\n\t/* Write the signature as a PGP MPI */\n\treturn( writeInteger16Ubits( stream, signature, signatureLength ) );\n\t}\n#endif /* USE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMiscellaneous Signature Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSH\n\n/* Read/write SSH signatures.  SSH signature data is treated as a blob\n   encoded as an SSH string rather than properly-formatted data so we don't\n   encode/decode it as SSH MPIs */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSshSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tBYTE buffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the signature record size and algorithm information */\n\treadUint32( stream );\n\tstatus = readString32( stream, buffer, CRYPT_MAX_TEXTSIZE, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length == 7 )\n\t\t{\n\t\t/* If it's a string of length 7 it's a conventional signature \n\t\t   algorithm */\n\t\tif( !memcmp( buffer, \"ssh-rsa\", 7 ) )\n\t\t\tqueryInfo->cryptAlgo = CRYPT_ALGO_RSA;\n\t\telse\n\t\t\t{\n\t\t\tif( !memcmp( buffer, \"ssh-dss\", 7 ) )\n\t\t\t\tqueryInfo->cryptAlgo = CRYPT_ALGO_DSA;\n\t\t\telse\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tqueryInfo->hashAlgo = CRYPT_ALGO_SHA1;\n\t\t}\n\telse\n\t\t{\n\t\tif( length == 12 )\n\t\t\t{\n\t\t\tif( memcmp( buffer, \"rsa-sha2-256\", 12 ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tqueryInfo->cryptAlgo = CRYPT_ALGO_RSA;\n\t\t\tqueryInfo->hashAlgo = CRYPT_ALGO_SHA2;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's probably an ECC signature algorithm.  We don't bother \n\t\t\t   checking the exact type since this is implicitly specified by \n\t\t\t   the signature-check key */\n\t\t\tif( length < 19 )\t\t/* \"ecdsa-sha2-nistXXXX\" */\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tif( memcmp( buffer, \"ecdsa-sha2-\", 11 ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tqueryInfo->cryptAlgo = CRYPT_ALGO_ECDSA;\n\t\t\tqueryInfo->hashAlgo = CRYPT_ALGO_SHA2;\n\t\t\t}\n\t\t}\n\n\t/* Read the start of the signature */\n\tstatus = length = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( queryInfo->cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tif( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tif( length != ( 20 + 20 ) )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbreak;\n\t\t\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tif( length < MIN_PKCSIZE_ECCPOINT || \\\n\t\t\t\tlength > MAX_PKCSIZE_ECCPOINT )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\tqueryInfo->dataLength = length;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeSshSignature( INOUT STREAM *stream,\n#ifdef USE_ECDSA\n\t\t\t\t\t\t\t  const CRYPT_CONTEXT iSignContext,\n#else\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_CONTEXT iSignContext,\n#endif /* !USE_ECDSA */\n\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t  STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t  IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( hashAlgo == CRYPT_ALGO_SHA1 || hashAlgo == CRYPT_ALGO_SHA2 );\n\tREQUIRES( signAlgo == CRYPT_ALGO_RSA || signAlgo == CRYPT_ALGO_DSA || \\\n\t\t\t  signAlgo == CRYPT_ALGO_ECDSA );\n\tREQUIRES( signatureLength >= ( 20 + 20 ) && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n#ifdef USE_ECDSA\n\t/* ECC signatures require all sorts of calisthenics that aren't \n\t   necessary for standard signatures, specifically we have to encode the\n\t   curve type in the algorithm name.  See the long comment in \n\t   session/ssh.c on the possible problems that the following can run \n\t   into */\n\tif( signAlgo == CRYPT_ALGO_ECDSA )\n\t\t{\n\t\tconst char *algoName;\n\t\tint keySize, algoNameLen, status;\n\n\t\tstatus = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &keySize, CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tswitch( keySize )\n\t\t\t{\n\t\t\tcase bitsToBytes( 256 ):\n\t\t\t\talgoName = \"ecdsa-sha2-nistp256\";\n\t\t\t\talgoNameLen = 19;\n\t\t\t\tbreak;\n\n\t\t\tcase bitsToBytes( 384 ):\n\t\t\t\talgoName = \"ecdsa-sha2-nistp384\";\n\t\t\t\talgoNameLen = 19;\n\t\t\t\tbreak;\n\n\t\t\tcase bitsToBytes( 521 ):\n\t\t\t\talgoName = \"ecdsa-sha2-nistp521\";\n\t\t\t\talgoNameLen = 19;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\n\t\twriteUint32( stream, sizeofString32( algoNameLen ) + \\\n\t\t\t\t\t\t\t sizeofString32( signatureLength ) );\n\t\twriteString32( stream, algoName, algoNameLen );\n\t\treturn( writeString32( stream, signature, signatureLength ) );\n\t\t}\n#endif /* USE_ECDSA */\n\n\t/* Write a non-ECC signature */\n\tif( hashAlgo == CRYPT_ALGO_SHA1 )\n\t\t{\n\t\twriteUint32( stream, sizeofString32( 7 ) + \\\n\t\t\t\t\t\t\t sizeofString32( signatureLength ) );\n\t\twriteString32( stream, ( signAlgo == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t\t\t\t   \"ssh-rsa\" : \"ssh-dss\", 7 );\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( signAlgo == CRYPT_ALGO_RSA && \\\n\t\t\t\t  hashAlgo == CRYPT_ALGO_SHA2 );\n\n\t\twriteUint32( stream, sizeofString32( 12 ) + \\\n\t\t\t\t\t\t\t sizeofString32( signatureLength ) );\n\t\twriteString32( stream, \"rsa-sha2-256\", 12 );\n\t\t}\n\treturn( writeString32( stream, signature, signatureLength ) );\n\t}\n#endif /* USE_SSH */\n\n#ifdef USE_SSL\n\n/* Read/write SSL signatures.  This is just a raw signature without any\n   encapsulation */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readSslSignature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t OUT QUERY_INFO *queryInfo )\n\t{\n\tconst int startPos = stell( stream );\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the start of the signature */\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < min( MIN_PKCSIZE, MIN_PKCSIZE_ECCPOINT ) || \\\n\t\tlength > CRYPT_MAX_PKCSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\tqueryInfo->dataLength = length;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeSslSignature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t  STDC_UNUSED const int hashParam,\n\t\t\t\t\t\t\t  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t  IN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \\\n\t\t\t\t\t\t\t\tconst int signatureLength )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( signatureLength > ( 18 + 18 ) && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\twriteUint16( stream, signatureLength );\n\treturn( swrite( stream, signature, signatureLength ) );\n\t}\n\n/* Read/write TLS 1.2 signatures, which specify a hash algorithm before the \n   signature and use PKCS #1 formatting instead of SSL's raw dual-hash */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readTls12Signature( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   OUT QUERY_INFO *queryInfo )\n\t{\n\tstatic const MAP_TABLE hashAlgoIDTbl[] = {\n\t\t{ /* TLS_HASHALGO_MD5 */ 1, CRYPT_ALGO_MD5 },\n\t\t{ /* TLS_HASHALGO_SHA1 */ 2, CRYPT_ALGO_SHA1 },\n\t\t{ /* TLS_HASHALGO_SHA2 */ 4, CRYPT_ALGO_SHA2 },\n\t\t{ /* TLS_HASHALGO_SHA384 */ 5, CRYPT_ALGO_SHA2 },\n\t\t{ /* TLS_HASHALGO_SHA512 */ 6, CRYPT_ALGO_SHA2 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tstatic const MAP_TABLE sigAlgoIDTbl[] = {\n\t\t{ /* TLS_SIGALGO_RSA */ 1, CRYPT_ALGO_RSA },\n\t\t{ /* TLS_SIGALGO_DSA */ 2, CRYPT_ALGO_DSA },\n\t\t{ /* TLS_SIGALGO_ECDSA */ 3, CRYPT_ALGO_ECDSA },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tconst int startPos = stell( stream );\n\tint hashAlgoID, sigAlgoID, value, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );\n\n\tREQUIRES( startPos >= 0 && startPos < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\tmemset( queryInfo, 0, sizeof( QUERY_INFO ) );\n\n\t/* Read the hash and signature algorithm data */\n\thashAlgoID = sgetc( stream );\n\tstatus = sigAlgoID = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hashAlgoID <= 0 || hashAlgoID >= 7 || \\\n\t\tsigAlgoID <= 0 || sigAlgoID >= 4 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = mapValue( hashAlgoID, &value, hashAlgoIDTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tqueryInfo->hashAlgo = value;\t/* int vs.enum */\n\tif( isHashMacExtAlgo( value ) )\n\t\t{\n\t\t/* If it's a parameterised algorithm then we have to return extra\n\t\t   information to indicate the sub-algorithm type */\n\t\tswitch( hashAlgoID )\n\t\t\t{\n\t\t\tcase 4:\n\t\t\t\tqueryInfo->hashAlgoParam = bitsToBytes( 256 );\n\t\t\t\tbreak;\n\n#ifdef USE_SHA2_EXT\n\t\t\tcase 5:\n\t\t\t\tqueryInfo->hashAlgoParam = bitsToBytes( 384 );\n\t\t\t\tbreak;\n\n\t\t\tcase 6:\n\t\t\t\tqueryInfo->hashAlgoParam = bitsToBytes( 512 );\n\t\t\t\tbreak;\n#endif /* USE_SHA2_EXT */\n\n\t\t\tdefault:\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\t} \n\tstatus = mapValue( sigAlgoID, &value, sigAlgoIDTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( sigAlgoIDTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status ); \n\tqueryInfo->cryptAlgo = value;\t/* int vs.enum */\n\n\t/* Read the start of the signature */\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < min( MIN_PKCSIZE, MIN_PKCSIZE_ECCPOINT ) || \\\n\t\tlength > CRYPT_MAX_PKCSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tqueryInfo->dataStart = stell( stream ) - startPos;\n\tqueryInfo->dataLength = length;\n\n\t/* Make sure that the remaining signature data is present */\n\treturn( sSkip( stream, length, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \\\nstatic int writeTls12Signature( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\tSTDC_UNUSED const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParam,\n\t\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE signAlgo,\n\t\t\t\t\t\t\t\tIN_BUFFER( signatureLength ) const BYTE *signature,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 18 + 18 + 1 ) \\\n\t\t\t\t\t\t\t\t\tconst int signatureLength )\n\t{\n\tstatic const MAP_TABLE hashAlgoIDTbl[] = {\n\t\t{ CRYPT_ALGO_MD5, /* TLS_HASHALGO_MD5 */ 1 },\n\t\t{ CRYPT_ALGO_SHA1, /* TLS_HASHALGO_SHA1 */ 2 },\n\t\t{ CRYPT_ALGO_SHA2, /* TLS_HASHALGO_SHA2 */ 4 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tstatic const MAP_TABLE sigAlgoIDTbl[] = {\n\t\t{ CRYPT_ALGO_RSA, /* TLS_SIGALGO_RSA */ 1 },\n\t\t{ CRYPT_ALGO_DSA, /* TLS_SIGALGO_DSA */ 2 },\n\t\t{ CRYPT_ALGO_ECDSA, /* TLS_SIGALGO_ECDSA */ 3 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tint hashAlgoID, sigAlgoID, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\t\t\t/* Other parameters aren't used for this format */\n\n\tREQUIRES( hashAlgo == CRYPT_ALGO_SHA1 || hashAlgo == CRYPT_ALGO_SHA2 );\n\tREQUIRES( isShortIntegerRange( hashParam ) );\n\tREQUIRES( signatureLength > ( 18 + 18 ) && \\\n\t\t\t  signatureLength < MAX_INTLENGTH_SHORT );\n\n\t/* Write the hash and siagnature algorithm data */\n\tstatus = mapValue( hashAlgo, &hashAlgoID, hashAlgoIDTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n#ifdef USE_SHA2_EXT\n\tif( hashAlgo == CRYPT_ALGO_SHA2 && hashParam == bitsToBytes( 384 ) )\n\t\thashAlgoID = 5;\t/* SHA-384 */\n#endif /* USE_SHA2_EXT */\n\tstatus = mapValue( signAlgo, &sigAlgoID, sigAlgoIDTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( sigAlgoIDTbl, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsputc( stream, hashAlgoID );\n\tsputc( stream, sigAlgoID );\n\n\t/* Write the signature itself */\n\twriteUint16( stream, signatureLength );\n\treturn( swrite( stream, signature, signatureLength ) );\n\t}\n#endif /* USE_SSL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSignature Read/Write Access Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst SIGNATURE_TYPE type;\n\tconst READSIG_FUNCTION function;\n\t} SIG_READ_INFO;\nstatic const SIG_READ_INFO sigReadTable[] = {\n#ifdef USE_INT_ASN1\n\t{ SIGNATURE_RAW, readRawSignature },\n\t{ SIGNATURE_X509, readX509Signature },\n#endif /* USE_INT_ASN1 */\n#ifdef USE_INT_CMS \n\t{ SIGNATURE_CMS, readCmsSignature },\n\t{ SIGNATURE_CRYPTLIB, readCryptlibSignature },\n#endif /* USE_INT_CMS */\n#ifdef USE_PGP\n\t{ SIGNATURE_PGP, readPgpSignature },\n#endif /* USE_PGP */\n#ifdef USE_SSH\n\t{ SIGNATURE_SSH, readSshSignature },\n#endif /* USE_SSH */\n#ifdef USE_SSL\n\t{ SIGNATURE_SSL, readSslSignature },\n\t{ SIGNATURE_TLS12, readTls12Signature },\n#endif /* USE_SSL */\n\t{ SIGNATURE_NONE, NULL }, { SIGNATURE_NONE, NULL }\n\t};\n\ntypedef struct {\n\tconst SIGNATURE_TYPE type;\n\tconst WRITESIG_FUNCTION function;\n\t} SIG_WRITE_INFO;\nstatic const SIG_WRITE_INFO sigWriteTable[] = {\n#ifdef USE_INT_ASN1\n\t{ SIGNATURE_RAW, writeRawSignature },\n\t{ SIGNATURE_X509, writeX509Signature },\n#endif /* USE_INT_ASN1 */\n#ifdef USE_INT_CMS \n\t{ SIGNATURE_CMS, writeCmsSignature },\n\t{ SIGNATURE_CRYPTLIB, writeCryptlibSignature },\n#endif /* USE_INT_CMS */\n#ifdef USE_PGP\n\t{ SIGNATURE_PGP, writePgpSignature },\n#endif /* USE_PGP */\n#ifdef USE_SSH\n\t{ SIGNATURE_SSH, writeSshSignature },\n#endif /* USE_SSH */\n#ifdef USE_SSL\n\t{ SIGNATURE_SSL, writeSslSignature },\n\t{ SIGNATURE_TLS12, writeTls12Signature },\n#endif /* USE_SSH */\n\t{ SIGNATURE_NONE, NULL }, { SIGNATURE_NONE, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nREADSIG_FUNCTION getReadSigFunction( IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE sigType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( sigType, SIGNATURE ) );\n\n\tLOOP_SMALL( i = 0,\n\t\t\t\tsigReadTable[ i ].type != SIGNATURE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( sigReadTable, SIG_READ_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tif( sigReadTable[ i ].type == sigType )\n\t\t\treturn( sigReadTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( sigReadTable, SIG_READ_INFO ) );\n\n\treturn( NULL );\n\t}\nCHECK_RETVAL_PTR \\\nWRITESIG_FUNCTION getWriteSigFunction( IN_ENUM( SIGNATURE ) \\\n\t\t\t\t\t\t\t\t\t\tconst SIGNATURE_TYPE sigType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( sigType, SIGNATURE ) );\n\n\tLOOP_SMALL( i = 0, \n\t\t\t\tsigWriteTable[ i ].type != SIGNATURE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( sigWriteTable, SIG_WRITE_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( sigWriteTable[ i ].type == sigType )\n\t\t\treturn( sigWriteTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( sigWriteTable, SIG_WRITE_INFO ) );\n\n\treturn( NULL );\n\t}\n"
  },
  {
    "path": "deps/cl345/mechs/sign_x509.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tX.509/PKI Signature Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1993-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"misc_rw.h\"\n  #include \"mech.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"mechs/mech.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CERTIFICATES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tX.509-style Signature Functions \t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create/check an X.509-style signature.  These work with objects of the\n   form:\n\n\tsignedObject ::= SEQUENCE {\n\t\tobject\t\t\t\tANY,\n\t\tsignatureAlgorithm\tAlgorithmIdentifier,\n\t\tsignature\t\t\tBIT STRING\n\t\t}\n\n   This is complicated by a variety of b0rken PKI protocols that couldn't\n   quite manage a cut & paste of two lines of text, adding all sorts of\n   unnecessary extra tagging and wrappers to the signature.  These odds and\n   ends are specified in the formatInfo structure */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint createX509signature( OUT_BUFFER( signedObjectMaxLength, \\\n\t\t\t\t\t\t\t\t\t *signedObjectLength ) \\\n\t\t\t\t\t\t\tvoid *signedObject, \n\t\t\t\t\t\t IN_DATALENGTH_Z const int signedObjectMaxLength, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *signedObjectLength,\n\t\t\t\t\t\t IN_BUFFER( objectLength ) const void *object, \n\t\t\t\t\t\t IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t IN_OPT const X509SIG_FORMATINFO *formatInfo )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tBYTE dataSignature[ CRYPT_MAX_PKCSIZE + 128 + 8 ];\n\tint signatureLength, totalSigLength, status;\n\n\tassert( isWritePtrDynamic( signedObject, signedObjectMaxLength ) );\n\tassert( isWritePtr( signedObjectLength, sizeof( int ) ) );\n\tassert( isReadPtr( object, objectLength ) && \\\n\t\t\tcryptStatusOK( checkCertObjectEncoding( object, objectLength ) ) );\n\tassert( formatInfo == NULL || \\\n\t\t\tisReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );\n\n\tREQUIRES( signedObjectMaxLength > MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  signedObjectMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( objectLength > 0 && objectLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( formatInfo == NULL || \\\n\t\t\t  ( ( formatInfo->tag >= 0 && \\\n\t\t\t\t  formatInfo->tag < MAX_CTAG_VALUE ) && \\\n\t\t\t\tisShortIntegerRange( formatInfo->extraLength ) ) );\n\n\t/* Clear return values */\n\tmemset( signedObject, 0, min( 16, signedObjectMaxLength ) );\n\t*signedObjectLength = 0;\n\n\t/* Hash the data to be signed */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiHashContext = createInfo.cryptHandle;\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) object, objectLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the signature and calculate the overall length of the payload, \n\t   optional signature wrapper, and signature data */\n\tstatus = createSignature( dataSignature, CRYPT_MAX_PKCSIZE + 128, \n\t\t\t\t\t\t\t  &signatureLength, iSignContext, \n\t\t\t\t\t\t\t  createInfo.cryptHandle, CRYPT_UNUSED, \n\t\t\t\t\t\t\t  SIGNATURE_X509 );\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( formatInfo == NULL )\n\t\ttotalSigLength = signatureLength;\n\telse\n\t\t{\n\t\t/* It's a nonstandard format, figure out the size due to the \n\t\t   additional signature wrapper and other odds and ends */\n\t\ttotalSigLength = \\\n\t\t\t\tsizeofShortObject( signatureLength + formatInfo->extraLength );\n\t\tif( formatInfo->isExplicit )\n\t\t\ttotalSigLength = sizeofShortObject( totalSigLength );\n\t\t}\n\tENSURES( totalSigLength > 40 && totalSigLength < MAX_BUFFER_SIZE );\n\n\t/* Make sure that there's enough room for the signed object in the \n\t   output buffer.  This will be checked by the stream handling anyway \n\t   but we make it explicit here */\n\tif( sizeofObject( objectLength + totalSigLength ) > signedObjectMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Write the outer SEQUENCE wrapper and copy the payload into place \n\t   behind it */\n\tsMemOpen( &stream, signedObject, signedObjectMaxLength );\n\twriteSequence( &stream, objectLength + totalSigLength );\n\tswrite( &stream, object, objectLength );\n\n\t/* If it's a nonstandard (b0rken PKI protocol) signature we have to \n\t   kludge in a variety of additional wrappers and other junk around the \n\t   signature */\n\tif( formatInfo != NULL )\n\t\t{\n\t\tif( formatInfo->isExplicit )\n\t\t\t{\n\t\t\twriteConstructed( &stream, \n\t\t\t\t\t\t\t  sizeofObject( signatureLength + \\\n\t\t\t\t\t\t\t\t\t\t\tformatInfo->extraLength ),\n\t\t\t\t\t\t\t  formatInfo->tag );\n\t\t\twriteSequence( &stream, \n\t\t\t\t\t\t   signatureLength + formatInfo->extraLength );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\twriteConstructed( &stream, \n\t\t\t\t\t\t\t  signatureLength + formatInfo->extraLength,\n\t\t\t\t\t\t\t  formatInfo->tag );\n\t\t\t}\n\t\t}\n\n\t/* Finally, append the signature */\n\tstatus = swrite( &stream, dataSignature, signatureLength );\n\tif( cryptStatusOK( status ) )\n\t\t*signedObjectLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tassert( ( formatInfo != NULL && formatInfo->extraLength > 0 ) || \\\n\t\t\tcryptStatusOK( checkCertObjectEncoding( signedObject, \n\t\t\t\t\t\t\t\t\t\t\t\t\t*signedObjectLength ) ) );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkX509signature( IN_BUFFER( signedObjectLength ) const void *signedObject, \n\t\t\t\t\t\tIN_DATALENGTH const int signedObjectLength,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\t\tIN_OPT const X509SIG_FORMATINFO *formatInfo )\n\t{\n\tCRYPT_ALGO_TYPE signAlgo, hashAlgo;\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tvoid *objectPtr DUMMY_INIT_PTR, *sigPtr;\n\tlong length;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint sigCheckAlgo, sigLength, hashParam, status;\t/* int vs.enum */\n\n\tassert( isReadPtrDynamic( signedObject, signedObjectLength ) );\n\tassert( formatInfo == NULL || \\\n\t\t\tisReadPtr( formatInfo, sizeof( X509SIG_FORMATINFO ) ) );\n\n\tREQUIRES( signedObjectLength > 0 && \\\n\t\t\t  signedObjectLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isHandleRangeValid( iSigCheckContext ) );\n\tREQUIRES( formatInfo == NULL || \\\n\t\t\t  ( ( formatInfo->tag >= 0 && \\\n\t\t\t\t  formatInfo->tag < MAX_CTAG_VALUE ) && \\\n\t\t\t\tisShortIntegerRange( formatInfo->extraLength ) ) );\n\n\t/* Make sure that the signing parameters are in order */\n\tstatus = krnlSendMessage( iSigCheckContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &sigCheckAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE\" );\n\n\t/* Check the start of the object and record the start and size of the\n\t   encapsulated signed object.  We have to use the long-length form of\n\t   the length functions to handle mega-CRLs */\n\tsMemConnect( &stream, signedObject, signedObjectLength );\n\treadLongSequence( &stream, NULL );\n\tstatus = getLongStreamObjectLength( &stream, &length );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( &stream, &objectPtr, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( &stream, length, SSKIP_MAX );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"getLongStreamObjectLength\" );\n\n\t/* If it's a broken signature, process the extra encapsulation */\n\tif( formatInfo != NULL )\n\t\t{\n\t\tif( formatInfo->isExplicit )\n\t\t\t{\n\t\t\treadConstructed( &stream, NULL, formatInfo->tag );\n\t\t\tstatus = readSequence( &stream, NULL );\n\t\t\t}\n\t\telse\n\t\t\tstatus = readConstructed( &stream, NULL, formatInfo->tag );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Remember the location and size of the signature data */\n\tstatus = sMemGetDataBlockRemaining( &stream, &sigPtr, &sigLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tstatus = readAlgoIDex( &stream, &signAlgo, &hashAlgo, &hashParam,\n\t\t\t\t\t\t   ALGOID_CLASS_PKCSIG );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( sigPtr != NULL );\n\tCFI_CHECK_UPDATE( \"readAlgoIDex\" );\n\n\t/* If the signature algorithm isn't what we expected the best that we \n\t   can do is report a signature error */\n\tif( sigCheckAlgo != signAlgo )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\t/* Create a hash context from the algorithm identifier of the\n\t   signature */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiHashContext = createInfo.cryptHandle;\n\tif( hashParam != 0 )\n\t\t{\n\t\t/* Some hash algorithms have variable output size, in which case \n\t\t   we need to explicitly tell the context which one we're working \n\t\t   with */\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &hashParam, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Hash the signed data and check the signature on the object */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t  objectPtr, length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t  \"\", 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = checkSignature( sigPtr, sigLength, iSigCheckContext,\n\t\t\t\t\t\t\t\t iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t SIGNATURE_X509 );\n\t\t}\n\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkSignature\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"IMESSAGE_GETATTRIBUTE\", \n\t\t\t\t\t\t\t\t\t\"getLongStreamObjectLength\", \"readAlgoIDex\", \n\t\t\t\t\t\t\t\t\t\"checkSignature\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPKI Protocol Signature Functions \t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The various PKIX certificate management protocols are built using the \n   twin design guidelines that nothing should use a standard style of \n   signature and no two protocols should use the same nonstandard format, \n   the only way to handle these (without creating dozens of new signature \n   types, each with their own special-case handling) is to process most of \n   the signature information at the protocol level and just check the raw \n   signature here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint createRawSignature( OUT_BUFFER( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\tconst int sigMaxLength, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( sigMaxLength ) \\\n\t\t\t\t\t\t\tint *signatureLength, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext )\n\t{\n\tassert( isWritePtrDynamic( signature, sigMaxLength ) );\n\tassert( isWritePtr( signatureLength, sizeof( int ) ) );\n\n\tREQUIRES( sigMaxLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  sigMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\n\treturn( createSignature( signature, sigMaxLength, signatureLength, \n\t\t\t\t\t\t\t iSignContext, iHashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t SIGNATURE_RAW ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkRawSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext )\n\t{\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( signatureLength ) );\n\tREQUIRES( isHandleRangeValid( iSigCheckContext ) );\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\n\treturn( checkSignature( signature, signatureLength, iSigCheckContext,\n\t\t\t\t\t\t\tiHashContext, CRYPT_UNUSED, SIGNATURE_RAW ) );\n\t}\n#endif /* USE_CERTIFICATES */\n"
  },
  {
    "path": "deps/cl345/misc/analyse.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Source Analysis Header File \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _ANALYSE_DEFINED\n\n#define _ANALYSE_DEFINED\n\n/* A symbolic define for the maximum possible error value when we're \n   checking ranges for status codes */\n\n#define MAX_ERROR\t\tCRYPT_ARGERROR_NUM2\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPREfast Analysis Support\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( _MSC_VER ) && defined( _PREFAST_ ) \n\n/* Enable strict checking of PREfast annotations.  This gets a bit ugly \n   because if a standard header that's included before us already \n   includes sal.h then we'll have __SPECSTRINGS_STRICT_LEVEL already\n   defined (the default is level 1, minimal warnings), so we undefine it\n   if necessary before setting it to the maximum warning level */\n\n#ifdef __SPECSTRINGS_STRICT_LEVEL\n  #undef __SPECSTRINGS_STRICT_LEVEL\n#endif /* __SPECSTRINGS_STRICT_LEVEL */\n#define __SPECSTRINGS_STRICT_LEVEL\t3\n\n/* Include the PREfast code analysis header.  Microsoft changed the notation \n   used from declspec SAL to attribute SAL some time between VC++ 2005 and \n   VC++ 2008, and then from attribute SAL 1.0 to attribute SAL 2.0 some time \n   between VC++ 2010 and VC++ 2013.  This is complicated somewhat by the \n   fixer-upper nature of the SAL material, many of the annotations aren't \n   documented in MSDN, some are only available in MS-internal versions of \n   PREfast, and some are defined to no-ops.  Because of this we have to\n   try and kludge some annotations together ourselves from low-level \n   primitives */\n\n#include <sal.h>\n\n/* Microsoft document an annotation _Deref_inout_range_(), however this \n   doesn't exist in any version of sal.h up to at least VS 2015.  To get\n   around this problem, we define it ourselves as best we can */\n\n#ifndef _Deref_inout_range_\n  #define _Deref_pre_range_( lb, ub )\t\t_Deref_in_range_impl_( lb, ub )\n  #define _Deref_post_range_( lb, ub )\t\t_Deref_out_range_impl_( lb, ub )\n\n  #define _Deref_prepost_range_( lb, ub )                 \\\n\t\t  _SAL1_1_Source_( _Deref_prepost_range_, ( lb, ub ), \\\n\t\t\t\t\t\t   _Deref_pre_range_( lb, ub ) _Deref_post_range_( lb, ub ) )\n\n  #define _Deref_inout_range_( min, max )\t_Deref_prepost_range_( min, max )\n#endif /* !_Deref_inout_range_ */\n\n/* There's no _Deref_opt_out_range_(), this is an attempt to construct it \n   from existing primtiives */\n\n#define _Deref_opt_out_range_( lb, ub ) \\\n\t\t_SAL2_Source_( _Deref_out_range_, ( lb, ub ), \\\n\t\t\t\t\t   _Out_opt_impl_ _Deref_out_range_impl_( lb, ub ) )\n\n/* Function return value information.  RETVAL_xxx annotations simply indicate\n   what the function returns, CHECK_RETVAL_xxx indicates that the caller must\n   check the return value:\n\n\tRETVAL\t\t\tFunction returns a standard cryptlib status code.\n\tRETVAL_BOOL\t\tAs CHECK_RETVAL but result is a boolean value.  This is \n\t\t\t\t\tused for 'pure' boolean functions that simply return a \n\t\t\t\t\tyes-or-no response about their input, for which there's \n\t\t\t\t\tno specific failure or success code.\n\tRETVAL_DATAPTR\tAs CHECK_RETVAL but returns a DATAPTR, on error a \n\t\t\t\t\tDATAPTR_NULL.\n\tRETVAL_ENUM\t\tAs CHECK_RETVAL but result is an enum following the \n\t\t\t\t\trules for IN_ENUM further down.\n\tRETVAL_LENGTH\tAs CHECK_RETVAL but result is a LENGTH following the \n\t\t\t\t\trules for IN_LENGTH further down.\n\tRETVAL_PTR\t\tAs CHECK_RETVAL but result is a pointer, non-null on\n\t\t\t\t\tsuccess.\n\tRETVAL_PTR_NONNULL As CHECK_RETVAL but result is a pointer that's\n\t\t\t\t\tguaranteed to never be NULL.\n\tRETVAL_RANGE\tAs CHECK_RETVAL but result must be in the range \n\t\t\t\t\t{ low...high } inclusive.\n\tRETVAL_SPECIAL\tAs RETVAL but OK_SPECIAL is treated as CRYPT_OK.\n\tRETVAL_STRINGOP\tFunction returns either an error code or a string \n\t\t\t\t\tposition/index, used for the strXYZ() functions.\n\n   The ranged variants of RETVAL (RETVAL_LENGTH, RETVAL_RANGE, \n   RETVAL_STRINGOP) require an additional annotation because there are \n   actually two ranges that need to be specified, the overall range of \n   values that can be returned and the range that gets returned on success, \n   which is a subset of the full set of values.  For example a function that \n   returns a length returns 0...MAX_LENGTH on success but MAX_ERROR...\n   MAX_LENGTH in general.\n\n   Alongside the standard RETVAL_xxxx there's also a RETVAL_xxxx_NOERROR\n   to indicate that any returned value is valid, for example when \n   calculating a checksum value.\n\n   The form for some of the RETVALs is a bit odd, they should be \n   '== CRYPT_OK' or '== TRUE' but when given in that form PREfast doesn't \n   recognise cryptStatusError() or '!' as a check for failure and warns \n   about uninitialised values being used after the cryptStatusError()/\n   boolean check has confirmed that all was OK.\n\n   CHECK_RETVAL_ENUM doesn't have a _Success_ specifier because all enum \n   values are valid return values, typically one is assigned to indicate\n   an error status but its interpretation is up to the caller.  In some\n   cases all but one are an error status, for example when a function \n   evaluates the CRYPT_ERRTYPE_TYPE to return for a failed operation.\n\n   This is additionally complicated by the fact that attribute SAL doesn't \n   allow RETVAL in typedefs and function pointers (since they're not valid\n   as attributes there) so we have to use a special-case typedef/function-\n   pointer version that's no-oped out */\n\n#define CHECK_RETVAL\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= CRYPT_OK ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, CRYPT_OK )\n#define CHECK_RETVAL_BOOL\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return != FALSE ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( FALSE, TRUE )\n#define CHECK_RETVAL_DATAPTR\t_Check_return_ \n#define CHECK_RETVAL_ENUM( name ) \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_range_( name##_NONE, name##_LAST )\n#define CHECK_RETVAL_LENGTH\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= 0 && return <= MAX_INTLENGTH - 1 ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, MAX_INTLENGTH - 1 ) \n#define CHECK_RETVAL_LENGTH_NOERROR \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_range_( 0, MAX_INTLENGTH - 1 ) \n#define CHECK_RETVAL_LENGTH_SHORT \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= 0 && return <= MAX_INTLENGTH_SHORT - 1 ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, MAX_INTLENGTH_SHORT - 1 ) \n#define CHECK_RETVAL_LENGTH_SHORT_NOERROR \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_range_( 0, MAX_INTLENGTH_SHORT - 1 ) \n#define CHECK_RETVAL_PTR\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_maybenull_ \\\n\t\t\t\t\t\t\t\t_Success_( return != NULL )\n#define CHECK_RETVAL_PTR_NONNULL \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_notnull_\n#define CHECK_RETVAL_RANGE( low, high ) \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= ( low ) && return <= ( high ) ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, high ) \n#define CHECK_RETVAL_RANGE_NOERROR( low, high ) \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Ret_range_( low, high ) \n#define CHECK_RETVAL_SPECIAL\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= CRYPT_OK || return == OK_SPECIAL ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( OK_SPECIAL, CRYPT_OK )\n#define CHECK_RETVAL_STRINGOP \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= 0 && return <= strLen ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( -1, strLen ) \n\n#define RETVAL\t\t\t\t\t_Success_( return >= CRYPT_OK ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, CRYPT_OK )\n#define RETVAL_BOOL\t\t\t\t_Success_( return != FALSE ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( FALSE, TRUE )\n#define RETVAL_LENGTH_NOERROR\t_Ret_range_( 0, MAX_INTLENGTH - 1 ) \n#define RETVAL_LENGTH_SHORT_NOERROR\t\\\n\t\t\t\t\t\t\t\t_Ret_range_( 0, MAX_INTLENGTH_SHORT - 1 ) \n#define RETVAL_RANGE( low, high ) \\\n\t\t\t\t\t\t\t\t_Success_( return >= ( low ) && return <= ( high ) ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( MAX_ERROR, high ) \n#define RETVAL_RANGE_NOERROR( low, high ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( low, high ) \n#define RETVAL_SPECIAL\t\t\t_Success_( return >= CRYPT_OK || return == OK_SPECIAL ) \\\n\t\t\t\t\t\t\t\t_Ret_range_( OK_SPECIAL, CRYPT_OK )\n\n/* The standard RETVAL is MAX_ERROR ... CRYPT_OK, RETVAL_SPECIAL lies \n   outside this range for a total range OK_SPECIAL ... CRYPTO_OK.  The\n   following check ensures that this is the case, the comparison is\n   reversed because the values are negative */\n\n#if OK_SPECIAL > MAX_ERROR\n  #error OK_SPECIAL must have a larger (negative) magnitude than MAX_ERROR\n#endif /* Check for OK_SPECIAL outside the range of MAX_ERROR */\n\n/* When we return from an error handler, returning an error status means \n   that the function succeeded, since it's forwarding a status that it was\n   given rather than reporting its own status.  In this case returning an\n   error code indicates success */\n\n#define CHECK_RETVAL_ERROR\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return < CRYPT_OK - 1 )\n\n/* Some functions acquire and release mutexes as part of their operation.\n   These require additional annotations to cover the operation of the \n   mutex */\n\n#define CHECK_RETVAL_ACQUIRELOCK( lockName ) \\\n\t\t\t\t\t\t\t\t_Check_return_ \\\n\t\t\t\t\t\t\t\t_Success_( return >= CRYPT_OK, _Acquires_lock_( lockName ) )\n\n#define RETVAL_RELEASELOCK( lockName ) \\\n\t\t\t\t\t\t\t\t_Requires_lock_held_( lockName ) \\\n\t\t\t\t\t\t\t\t_Success_( return >= CRYPT_OK, _Releases_lock_( lockName ) )\n#define RELEASELOCK( lockName ) _Requires_lock_held_( lockName ) \\\n\t\t\t\t\t\t\t\t_Releases_lock_( lockName )\n\n/* Numeric parameter checking:\n\n\tINT\t\t\tValue must be between 1 and MAX_INTLENGTH - 1\n\tINT_SHORT\tAs INT but upper bound is MAX_INTLENGTH_SHORT - 1 rather \n\t\t\t\tthan MAX_INTLENGTH - 1.\n\n   In addition to these we allow the OPT specifier to indicate that the \n   value may be NULL for OUT parameters, the OPT suffix to indicate that the \n   value may be CRYPT_UNUSED, and the Z suffix to indicate that the lower \n   bound may be zero.  This is used for two cases, either when the lower\n   bound is explicitly zero or when it's set on error to xyz_NONE, which \n   would normally be an invalid value for the non-_Z parameter */\n\n#define IN_BYTE\t\t\t\t\t_In_range_( 0, 255 )\n#define IN_INT\t\t\t\t\t_In_range_( 1, MAX_INTLENGTH - 1 ) \n#define IN_INT_OPT\t\t\t\t_In_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 ) \n#define IN_INT_Z\t\t\t\t_In_range_( 0, MAX_INTLENGTH - 1 ) \n#define IN_INT_SHORT\t\t\t_In_range_( 1, MAX_INTLENGTH_SHORT - 1 ) \n#define IN_INT_SHORT_Z\t\t\t_In_range_( 0, MAX_INTLENGTH_SHORT - 1 ) \n\n#define OUT_INT\t\t\t\t\t_Deref_out_range_( 1, MAX_INTLENGTH - 1 ) \n#define OUT_INT_Z\t\t\t\t_Deref_out_range_( 0, MAX_INTLENGTH - 1 ) \n#define OUT_INT_SHORT_Z\t\t\t_Deref_out_range_( 0, MAX_INTLENGTH_SHORT - 1 ) \n#define OUT_OPT_INT_Z\t\t\t_Deref_out_range_( 0, MAX_INTLENGTH - 1 ) \n\n#define INOUT_INT_Z\t\t\t\t_Deref_inout_range_( 0, MAX_INTLENGTH - 1 )\n\n/* Special-case parameter checking:\n\n\tALGO\t\tValue must be a cryptlib encryption algorithm.\n\tATTRIBUTE\tValue must be a cryptlib attribute.\n\tBOOL\t\tValue must be boolean.\n\tBYTE\t\tValue must be a single-byte value.\n\tCHAR\t\tValue must be a 7-bit ASCII character.\n\tERROR\t\tValue must be a cryptlib error status code.\n\tHANDLE\t\tValue must be a cryptlib handle.\n\tINDEX\t\tLike RANGE but can output CRYPT_ERROR on error.  This is \n\t\t\t\tused when returning an index into an array, for which the\n\t\t\t\tdefault not-initialised value of 0 is actually a valid \n\t\t\t\tresult.\n\tMESSAGE\t\tValue must be a cryptlib message type.\n\tMODE\t\tValue must be a cryptlib encryption mode.\n\tPORT\t\tValue must be a network port.\n\tRANGE\t\tUser-specified range check.\n\tSTATUS\t\tValue must be cryptlib status code\n\n   In addition to these we allow the OPT specifier to indicate that the \n   value may be NULL for OUT parameters.  Note that for the OUT versions \n   there's no _opt_ version of _Deref_out_range_ so the best that we can do\n   is use a straight _Deref_out_range_.\n   \n   We also allow an OPT suffix to indicate the use of don't-care values, \n   typically CRYPT_UNUSED */\n\n#define IN_ALGO\t\t\t\t\t_In_range_( CRYPT_ALGO_NONE + 1, CRYPT_ALGO_LAST - 1 )\n#define IN_ALGO_OPT\t\t\t\t_In_range_( CRYPT_ALGO_NONE, CRYPT_ALGO_LAST - 1 )\n#define IN_ATTRIBUTE\t\t\t_In_range_( CRYPT_ATTRIBUTE_NONE + 1, CRYPT_IATTRIBUTE_LAST - 1 )\n#define IN_ATTRIBUTE_OPT\t\t_In_range_( CRYPT_ATTRIBUTE_NONE, CRYPT_IATTRIBUTE_LAST - 1 )\n#define IN_BYTE\t\t\t\t\t_In_range_( 0, 0xFF )\n#define IN_CHAR\t\t\t\t\t_In_range_( 0, 0x7F )\n#define IN_ERROR\t\t\t\t_In_range_( MAX_ERROR, -1 )\n#define IN_HANDLE\t\t\t\t_In_range_( SYSTEM_OBJECT_HANDLE, MAX_NO_OBJECTS - 1 )\n#define IN_HANDLE_OPT\t\t\t_In_range_( CRYPT_UNUSED, MAX_NO_OBJECTS - 1 )\n#define IN_KEYID\t\t\t\t_In_range_( CRYPT_KEYID_NONE + 1, CRYPT_KEYID_LAST - 1 )\n#define IN_KEYID_OPT\t\t\t_In_range_( CRYPT_KEYID_NONE, CRYPT_KEYID_LAST - 1 )\n#define IN_MESSAGE\t\t\t\t_In_range_( MESSAGE_NONE + 1, IMESSAGE_LAST - 1 )\n#define IN_MODE\t\t\t\t\t_In_range_( CRYPT_MODE_NONE + 1, CRYPT_MODE_LAST - 1 )\n#define IN_MODE_OPT\t\t\t\t_In_range_( CRYPT_MODE_NONE, CRYPT_MODE_LAST - 1 )\n#define IN_PORT\t\t\t\t\t_In_range_( 22, 65535L )\n#define IN_PORT_OPT\t\t\t\t_In_range_( CRYPT_UNUSED, 65535L )\n#define IN_RANGE( min, max )\t_In_range_( ( min ), ( max ) )\n#define IN_RANGE_FIXED( value )\t_In_range_( ( value ), ( value ) )\n#define IN_STATUS\t\t\t\t_In_range_( MAX_ERROR, CRYPT_OK )\n\n#define INOUT_HANDLE\t\t\t_Deref_inout_range_( SYSTEM_OBJECT_HANDLE, MAX_NO_OBJECTS - 1 )\n#define INOUT_RANGE( min, max )\t_Deref_inout_range_( ( min ), ( max ) )\n\n#define OUT_ALGO_Z\t\t\t\t_Deref_out_range_( CRYPT_ALGO_NONE, CRYPT_ALGO_LAST - 1 )\n#define OUT_OPT_ALGO_Z\t\t\t_Deref_out_range_( CRYPT_ALGO_NONE, CRYPT_ALGO_LAST - 1 )\n#define OUT_ATTRIBUTE_Z\t\t\t_Deref_out_range_( CRYPT_ATTRIBUTE_NONE, CRYPT_IATTRIBUTE_LAST - 1 )\n#define OUT_OPT_ATTRIBUTE_Z\t\t_Deref_out_range_( CRYPT_ATTRIBUTE_NONE, CRYPT_IATTRIBUTE_LAST - 1 )\n#define OUT_BOOL\t\t\t\t_Deref_out_range_( FALSE, TRUE )\n#define OUT_OPT_BOOL\t\t\t_Deref_out_range_( FALSE, TRUE )\n#define OUT_OPT_BYTE\t\t\t_Deref_out_range_( 0, 0xFF )\n#define OUT_ERROR\t\t\t\t_Deref_out_range_( MAX_ERROR, -1 )\n#define OUT_HANDLE_OPT\t\t\t_Deref_out_range_( -1, MAX_NO_OBJECTS - 1 )\n#define OUT_OPT_HANDLE_OPT\t\t_Deref_out_range_( -1, MAX_NO_OBJECTS - 1 )\n\t\t\t\t\t\t\t\t/* There's no _opt_ version of this \n\t\t\t\t\t\t\t\t   annotation, or for any of the _Deref_\n\t\t\t\t\t\t\t\t   variants for that matter, this is the \n\t\t\t\t\t\t\t\t   best that we can do */\n#define OUT_INDEX( max )\t\t_Deref_out_range_( CRYPT_ERROR, ( max ) )\n#define OUT_OPT_INDEX( max )\t_Deref_out_range_( CRYPT_ERROR, ( max ) )\n\t\t\t\t\t\t\t\t/* See note for OUT_OPT_HANDLE_OPT */\n#define OUT_PORT_Z\t\t\t\t_Deref_out_range_( 0, 65535L )\n#define OUT_RANGE( min, max )\t_Deref_out_range_( ( min ), ( max ) )\n#define OUT_OPT_RANGE( min, max ) _Deref_out_range_( ( min ), ( max ) )\n#define OUT_STATUS\t\t\t\t_Deref_out_range_( MAX_ERROR, CRYPT_OK )\n\n/* Length parameter checking:\n\n\tLENGTH\t\t\tValue must be between 1 and MAX_INTLENGTH - 1.\n\tLENGTH_FIXED\tValue must be a single fixed length, used for polymorphic\n\t\t\t\t\tfunctions of which this specific instance takes a fixed-\n\t\t\t\t\tsize parameter, or otherwise in cases where a length \n\t\t\t\t\tparameter is supplied mostly just to allow bounds \n\t\t\t\t\tchecking.\n\tLENGTH_MIN\t\tAs LENGTH but lower bound is user-specified.\n\tLENGTH_Z\t\tAs LENGTH but lower bound may be zero.\n\n\tDATALENGTH\t\tValue must be between 1 and MAX_BUFFER_SIZE - 1\n\tDATALENGTH_Z\tAs DATALENGTH but lower bound may be zero.\n\n\tLENGTH_SHORT\tAs LENGTH but upper bound is MAX_INTLENGTH_SHORT - 1 \n\t\t\t\t\trather than MAX_INTLENGTH - 1.\n\tLENGTH_SHORT_MIN As LENGTH_SHORT but lower bound is user-specified.\n\tLENGTH_SHORT_Z\tAs LENGTH_SHORT but lower bound may be zero.\n\n   In addition to these we allow the OPT specifier and OPT and Z suffixes as\n   before */\n\n#define IN_LENGTH\t\t\t\t_In_range_( 1, MAX_INTLENGTH - 1 )\n#define IN_LENGTH_OPT\t\t\t_In_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 )\n#define IN_LENGTH_FIXED( size )\t_In_range_( ( size ), ( size ) )\n#define IN_LENGTH_MIN( min )\t_In_range_( ( min ), MAX_INTLENGTH - 1 )\n#define IN_LENGTH_Z\t\t\t\t_In_range_( 0, MAX_INTLENGTH - 1 )\n\n#define IN_DATALENGTH\t\t\t_In_range_( 1, MAX_BUFFER_SIZE - 1 )\n#define IN_DATALENGTH_OPT\t\t_In_range_( CRYPT_UNUSED, MAX_BUFFER_SIZE - 1 )\n#define IN_DATALENGTH_MIN( min ) _In_range_( ( min ), MAX_BUFFER_SIZE - 1 )\n#define IN_DATALENGTH_Z\t\t\t_In_range_( 0, MAX_BUFFER_SIZE - 1 )\n\n#define IN_LENGTH_SHORT\t\t\t_In_range_( 1, MAX_INTLENGTH_SHORT - 1 )\n#define IN_LENGTH_SHORT_OPT\t\t_In_range_( CRYPT_UNUSED, MAX_INTLENGTH_SHORT - 1 )\n\t\t\t\t\t\t\t\t/* This really is a _OPT and not a _INDEF in \n\t\t\t\t\t\t\t\t   the one place where it's used */\n#define IN_LENGTH_SHORT_MIN( min ) _In_range_( ( min ) , MAX_INTLENGTH_SHORT - 1 )\n#define IN_LENGTH_SHORT_Z\t\t_In_range_( 0, MAX_INTLENGTH_SHORT - 1 )\n\n#define INOUT_LENGTH_Z\t\t\t_Deref_inout_range_( 0, MAX_INTLENGTH - 1 )\n#define INOUT_LENGTH_SHORT_Z\t_Deref_inout_range_( 0, MAX_INTLENGTH_SHORT - 1 )\n\n#define OUT_LENGTH\t\t\t\t_Deref_out_range_( 1, MAX_INTLENGTH - 1 )\n#define OUT_LENGTH_MIN( min )\t_Deref_out_range_( ( min ), MAX_INTLENGTH - 1 )\n#define OUT_OPT_LENGTH_MIN( min ) _Deref_out_range_( ( min ), MAX_INTLENGTH - 1 )\n#define OUT_LENGTH_Z\t\t\t_Deref_out_range_( 0, MAX_INTLENGTH - 1 )\n#define OUT_OPT_LENGTH_Z\t\t_Deref_out_range_( 0, MAX_INTLENGTH - 1 )\n\n#define OUT_DATALENGTH\t\t\t_Deref_out_range_( 1, MAX_BUFFER_SIZE - 1 )\n#define OUT_DATALENGTH_Z\t\t_Deref_out_range_( 0, MAX_BUFFER_SIZE - 1 )\n#define OUT_OPT_DATALENGTH_Z\t_Deref_out_range_( 0, MAX_BUFFER_SIZE - 1 )\n\n#define OUT_LENGTH_SHORT\t\t_Deref_out_range_( 1, MAX_INTLENGTH_SHORT - 1 )\n#define OUT_LENGTH_SHORT_Z\t\t_Deref_out_range_( 0, MAX_INTLENGTH_SHORT - 1 )\n#define OUT_OPT_LENGTH_SHORT\t_Deref_out_range_( 1, MAX_INTLENGTH_SHORT - 1 )\n#define OUT_OPT_LENGTH_SHORT_MIN( min )\t_Deref_out_range_( ( min ), MAX_INTLENGTH_SHORT - 1 )\n#define OUT_OPT_LENGTH_SHORT_Z\t_Deref_out_range_( 0, MAX_INTLENGTH_SHORT - 1 )\n\n/* Sometimes a length value is given in terms of another length, typically \n   for the pattern { buffer, maxLength, *outLength } where *outLength is\n   bounded by maxLength.  The following annotations deal with this\n   bounded-length condition.\n\n   Note that using this annotation doesn't work when \n   { buffer, maxLength, *outLength } can be given as { NULL, 0, *outLength }\n   for performing a length check.  In this case we still use a pseudo-\n   annotation that begins OUT_LENGTH_BOUNDED, but end it as a normal length\n   annotation such as OUT_LENGTH_BOUNDED_PKC.  This functions the same as\n   OUT_LENGTH_PKC, but may be modified in the future if SAL supports more\n   complex conditional annotations.\n   \n   There's no _Deref_out_opt_range_ so we can't do the same for the\n   OUT_OPT_LENGTH_xxx variants */\n\n#define OUT_LENGTH_BOUNDED( length ) \\\n\t\t\t\t\t\t\t\t_Deref_out_range_( 1, length )\n#define OUT_LENGTH_BOUNDED_Z( length ) \\\n\t\t\t\t\t\t\t\t_Deref_out_range_( 0, length )\n\n#define OUT_LENGTH_BOUNDED_SHORT_Z( length ) \\\n\t\t\t\t\t\t\t\tOUT_LENGTH_SHORT_Z\n#define OUT_LENGTH_BOUNDED_PKC_Z( length ) \\\n\t\t\t\t\t\t\t\tOUT_LENGTH_PKC_Z\n\n/* Special-case length checking:\n\n\tLENGTH_ATTRIBUTE Value must be a valid length for an attribute.\n\tLENGTH_DNS\t\tValue must be a valid length for DNS data or a URL.\n\tLENGTH_DNS_Z\tValue must be a valid length for DNS data or a URL,\n\t\t\t\t\tincluding zero-length output, which is returned on error.\n\tLENGTH_ERRORMESSAGE\tValue must be a valid length for an extended error \n\t\t\t\t\tstring.\n\tLENGTH_HASH\t\tValue must be a valid length for a hash.\n\tLENGTH_INDEF\tAs LENGTH but may also be CRYPT_UNUSED for indefinite-\n\t\t\t\t\tlength encoded data.\n\tLENGTH_IV\t\tValue must be a valid length for a cipher block.  \n\t\t\t\t\tTechnically this isn't always an IV, but this is about\n\t\t\t\t\tthe best name to give it.\n\tLENGTH_KEY\t\tValue must be a valid length for a conventional \n\t\t\t\t\tencryption key.\n\tLENGTH_KEYID\tValue must be a valid length for a key ID lookup.\n\tLENGTH_NAME\t\tValue must be a valid length for an object name or\n\t\t\t\t\tsimilar type of string, e.g. a database name or a \n\t\t\t\t\tpassword (this is a bit of a catch-all value for\n\t\t\t\t\tstrings, unfortunately there's no easily descriptive\n\t\t\t\t\tname for the function it performs).\n\tLENGTH_OID\t\tValue must be a valid length for an OID.\n\tLENGTH_PKC\t\tValue must be a valid length for PKC data.\n\tLENGTH_PKC_Z\tValue must be a valid length for PKC data, including \n\t\t\t\t\tzero-length output, which is returned on error.\n\tLENGTH_TEXT\t\tValue must be a valid length for a text string (length\n\t\t\t\t\tup to CRYPT_MAX_TEXTSIZE).\n\n   In addition to these we allow the OPT specifier and Z suffix as before.\n   \n   For the OUT_OPT variants there's no SAL 2.0 annotation that we can map\n   this to so for now it's the same as a standard DEREF */\n\n#define IN_LENGTH_ATTRIBUTE\t\t_In_range_( 1, MAX_ATTRIBUTE_SIZE )\n#define IN_LENGTH_DNS\t\t\t_In_range_( 1, MAX_DNS_SIZE )\n#define IN_LENGTH_DNS_Z\t\t\t_In_range_( 0, MAX_DNS_SIZE )\n#define IN_LENGTH_ERRORMESSAGE\t_In_range_( 1, MAX_ERRMSG_SIZE )\n#define IN_LENGTH_HASH\t\t\t_In_range_( 16, CRYPT_MAX_HASHSIZE )\n#define IN_LENGTH_HASH_Z\t\t_In_range_( 0, CRYPT_MAX_HASHSIZE )\n#define IN_LENGTH_INDEF\t\t\t_In_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 )\n#define IN_LENGTH_IV\t\t\t_In_range_( MIN_IVSIZE, CRYPT_MAX_IVSIZE )\n#define IN_LENGTH_IV_Z\t\t\t_In_range_( 0, CRYPT_MAX_IVSIZE )\n#define IN_LENGTH_KEY\t\t\t_In_range_( MIN_KEYSIZE, CRYPT_MAX_KEYSIZE )\n#define IN_LENGTH_KEYID\t\t\t_In_range_( MIN_NAME_LENGTH, MAX_ATTRIBUTE_SIZE )\n#define IN_LENGTH_KEYID_Z\t\t_In_range_( 0, MAX_ATTRIBUTE_SIZE )\n#define IN_LENGTH_NAME\t\t\t_In_range_( MIN_NAME_LENGTH, MAX_ATTRIBUTE_SIZE )\n#define IN_LENGTH_NAME_Z\t\t_In_range_( 0, MAX_ATTRIBUTE_SIZE )\n#define IN_LENGTH_OID\t\t\t_In_range_( 7, MAX_OID_SIZE )\n#define IN_LENGTH_PKC\t\t\t_In_range_( 1, CRYPT_MAX_PKCSIZE )\n#define IN_LENGTH_PKC_BITS\t\t_In_range_( 1, bytesToBits( CRYPT_MAX_PKCSIZE ) )\n#define IN_LENGTH_PKC_Z\t\t\t_In_range_( 0, CRYPT_MAX_PKCSIZE )\n#define IN_LENGTH_TEXT\t\t\t_In_range_( 1, CRYPT_MAX_TEXTSIZE )\n#define IN_LENGTH_TEXT_Z\t\t_In_range_( 0, CRYPT_MAX_TEXTSIZE )\n\n#define OUT_LENGTH_HASH_Z\t\t_Deref_out_range_( 0, CRYPT_MAX_HASHSIZE )\n#define OUT_LENGTH_DNS_Z\t\t_Deref_out_range_( 0, MAX_DNS_SIZE )\n#define OUT_OPT_LENGTH_HASH_Z\t_Deref_out_range_( 0, CRYPT_MAX_HASHSIZE )\n#define OUT_LENGTH_PKC_Z\t\t_Deref_out_range_( 0, CRYPT_MAX_PKCSIZE )\n#define OUT_LENGTH_INDEF\t\t_Deref_out_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 )\n#define OUT_OPT_LENGTH_INDEF\t_Deref_out_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 )\n#define OUT_OPT_LENGTH_SHORT_INDEF\t_Deref_out_range_( CRYPT_UNUSED, MAX_INTLENGTH - 1 )\n\n/* ASN.1 parameter checking, enabled if ANALYSE_ASN1 is defined:\n\n\tTAG\t\t\t\tValue must be a valid tag or DEFAULT_TAG.  Note that \n\t\t\t\t\tthis is the raw tag value before any DER encoding, \n\t\t\t\t\te.g. '0' rather than 'MAKE_CTAG( 0 )'.\n\tTAG_EXT\t\t\tAs IN_TAG but may also be ANY_TAG, is used internally \n\t\t\t\t\tby the ASN.1 code to indicate a don't-care tag value.\n\tTAG_ENCODED\t\tValue must be a valid DER-encoded tag value \n\n   In addition to these we allow the EXT specifier to indicate that the \n   value may also be ANY_TAG (a don't-care value) or the hidden NO_TAG used \n   to handle reading of data when the tag has already been processed */\n\n#define IN_TAG\t\t\t\t\t_In_range_( DEFAULT_TAG, MAX_TAG_VALUE - 1 )\n#define IN_TAG_EXT\t\t\t\t_In_range_( ANY_TAG, MAX_TAG_VALUE - 1 )\n#define IN_TAG_ENCODED\t\t\t_In_range_( NO_TAG, MAX_TAG - 1 )\n#define IN_TAG_ENCODED_EXT\t\t_In_range_( ANY_TAG, MAX_TAG - 1 )\n\n#define OUT_TAG_Z\t\t\t\t_Deref_out_range_( 0, MAX_TAG_VALUE - 1 )\n#define OUT_TAG_ENCODED_Z\t\t_Deref_out_range_( 0, MAX_TAG - 1 )\n\n/* Enumerated type checking.  Due to the duality of 'int' and 'enum' under C\n   these can normally be mixed freely until it comes back to bite on systems\n   where the compiler doesn't treat them quite the same.  The following \n   provides more strict type checking of enums than the compiler would \n   normally provide and relies on the enum being bracketed by xxx_NONE and\n   xxx_LAST.\n\n   We also allow an OPT suffix to indicate the use of don't-care values, \n   denoted by xxx_NONE */\n\n#define IN_ENUM( name )\t\t\t_In_range_( name##_NONE + 1, name##_LAST - 1 )\n#define IN_ENUM_OPT( name )\t\t_In_range_( name##_NONE, name##_LAST - 1 )\n\n#define INOUT_ENUM( name )\t\t_Deref_inout_range_( name##_NONE + 1, name##_LAST - 1 )\n#define INOUT_ENUM_OPT( name )\t_Deref_inout_range_( name##_NONE, name##_LAST - 1 )\n\n#define OUT_ENUM( name )\t\t_Deref_out_range_( name##_NONE + 1, name##_LAST - 1 )\n#define OUT_ENUM_OPT( name )\t_Deref_out_range_( name##_NONE, name##_LAST - 1 )\n#define OUT_OPT_ENUM( name )\t_Deref_opt_out_range_( name##_NONE + 1, name##_LAST - 1 )\n\n/* Binary flag checking.  This works as for enumerated type checking and \n   relies on the flag definition being bracketed by xxx_FLAG_NONE and \n   xxx_FLAG_MAX */\n\n#define IN_FLAGS( name )\t\t_In_range_( 1, name##_FLAG_MAX )\n#define IN_FLAGS_Z( name )\t\t_In_range_( name##_FLAG_NONE, name##_FLAG_MAX )\n\n#define INOUT_FLAGS( name )\t\t_Deref_inout_range_( name##_FLAG_NONE, name##_FLAG_MAX )\n\n#define OUT_FLAGS_Z( name )\t\t_Deref_out_range_( name##_FLAG_NONE, name##_FLAG_MAX )\n\n/* Buffer parameter checking:\n\n\tIN_BUFFER\t\tFor { buffer, length } values.\n\tINOUT_BUFFER\tFor in-place processing of { buffer, maxLength, *length } \n\t\t\t\t\tvalues, e.g. decryption with padding removal.\n\tOUT_BUFFER\t\tFor filling of { buffer, maxLength, *length } values.\n\n\tINOUT_BUFFER_FIXED For in-place processing of { buffer, length } values, \n\t\t\t\t\te.g. filtering control chars in a string.\n\tOUT_BUFFER_FIXED For filling of { buffer, length } values.\n\n   In addition to these we allow the OPT specifier as before */\n\n#define IN_BUFFER( count )\t\t\t\t_In_reads_bytes_( count )\n#define IN_BUFFER_C( count )\t\t\t_In_reads_bytes_( count )\n#define IN_BUFFER_OPT( count )\t\t\t_In_reads_bytes_opt_( count )\n#define IN_BUFFER_OPT_C( count )\t\t_In_reads_bytes_opt_( count )\n\n#define INOUT_BUFFER( max, count )\t\t_Inout_updates_bytes_to_( max, count )\n#define INOUT_BUFFER_C( max, count )\t_Inout_updates_bytes_to_( max, count )\n#define INOUT_BUFFER_FIXED( count )\t\t_Inout_updates_bytes_all_( count )\n#define INOUT_BUFFER_OPT( max, count )\t_Inout_updates_bytes_to_opt_( max, count )\n\n#define OUT_BUFFER( max, count )\t\t_Out_writes_bytes_to_( max, count ) \n#define OUT_BUFFER_C( max, count )\t\t_Out_writes_bytes_to_( max, count ) \n#define OUT_BUFFER_OPT( max, count )\t_Out_writes_bytes_to_opt_( max, count ) \n#define OUT_BUFFER_OPT_C( max, count )\t_Out_writes_bytes_to_opt_( max, count ) \n#define OUT_BUFFER_FIXED( count )\t\t_Out_writes_bytes_all_( count )\n#define OUT_BUFFER_FIXED_C( count )\t\t_Out_writes_bytes_all_( count )\n#define OUT_BUFFER_OPT_FIXED( count )\t_Out_writes_bytes_all_opt_( count )\n\n/* A special-case annotation for a situation in which a block of memory is\n   passed around as a working buffer to save allocating local buffers up\n   and down a call hierarchy.  This is a bit of an awkward situation since\n   it isn't really an IN or OUT parameter, and doesn't have to be \n   initialised by either the caller or callee.  Its only function is that\n   the callee pollutes it, but not in any annotation-relevant manner.\n\n   To deal with this, we make it an OUT parameter, making it callee-\n   initialised seems to be the closest to the required semantics */\n\n#define WORKING_BUFFER\t\t\t\t\tOUT_BUFFER_FIXED\n\n/* Array parameter checking:\n\n\tARRAY\t\t\tFor { fooType foo[], int fooCount } values */\n\n#define IN_ARRAY( count )\t\t_In_reads_( count )\n#define IN_ARRAY_C( count )\t\t_In_reads_( count )\n#define IN_ARRAY_OPT( count )\t_In_reads_opt_( count )\n#define IN_ARRAY_OPT_C( count )\t_In_reads_opt_( count )\n\n#define INOUT_ARRAY( count )\t_Inout_updates_( count )\n#define INOUT_ARRAY_C( count )\t_Inout_updates_( count )\n\n#define OUT_ARRAY( count )\t\t_Out_writes_( count )\n#define OUT_ARRAY_C( count )\t_Out_writes_( count )\n#define OUT_ARRAY_OPT( count )\t_Out_writes_opt_( count )\n#define OUT_ARRAY_OPT_C( count ) _Out_writes_opt_( count )\n\n/* Conditional modifiers on parameters.  These are used when one parameter's\n   behaviour depends on another, for example:\n\n\tIN_WHEN( condition == STATE_WRITE ) \\\n\tOUT_WHEN( condition == STATE_READ ) \\\n\tINOUT_WHEN( condition == STATE_READWRITE )\n\n  specifies the behaviour of a buffer value when an associated operation \n  code is read/write/readwrite */\n\n#define OUT_WHEN( cond )\t_When_( ( cond ), _Out_ )\n#define INOUT_WHEN( cond )\t_When_( ( cond ), _Inout_ )\n\n/* Parameter checking that goes beyond the basic operations provided above.  \n   This uses somewhat complex conditionals on annotations to handle \n   situations where one parameter controls the behaviour of one or more\n   others and that can't be handled more directly using the IN_WHEN/OUT_WHEN\n   operations.  Because of the complexity of these annotations, we provide \n   several custom forms that are used in specific situations:\n\n\tPARAMCHECK\t\t\tGeneral-purpose, specifies the condition, the \n\t\t\t\t\t\tparameter that's affected, and the behaviour of the \n\t\t\t\t\t\tparameter, e.g. { operation == READ, buffer, OUT }\n\t\t\t\t\t\t(although something that simple would be handled with\n\t\t\t\t\t\tIN_WHEN/OUT_WHEN/etc). \n\n\tPARAMCHECK_MESSAGE\tFor krnlSendMessage(), specifies the message type \n\t\t\t\t\t\tand the behaviour of the pointer and integer \n\t\t\t\t\t\tparameters passed to the call */\n\n#define PARAM_NULL\t\t\t\t_Pre_null_\n#define PARAM_IS( value )\t\t_Pre_equal_to_( value )\n\n#define PARAMCHECK( condition, param, type ) \\\n\t\t\t\t\t\t\t\t_When_( ( condition ), _At_( param, type ) )\n\n#define PARAMCHECK_MESSAGE( msgType, msgDataType, msgValType ) \\\n\t\t\t\t\t\t\t\t_When_( ( message & MESSAGE_MASK ) == ( msgType ), \\\n\t\t\t\t\t\t\t\t\t\t_At_( messageDataPtr, msgDataType ) ) \\\n\t\t\t\t\t\t\t\t_When_( ( message & MESSAGE_MASK ) == ( msgType ), \\\n\t\t\t\t\t\t\t\t\t\t_At_( messageValue, msgValType ) )\n\n/* Structures that encapsulate data-handling operations:\n\n\tVALUE\t\t\tInteger value constrained to a subrange, e.g. 0...10.\n\tARRAY\t\t\tArray of total allocated size 'max', currently filled\n\t\t\t\t\tto 'count' elements.\n\tBUFFER\t\t\tBuffer of total allocated size 'max', currently filled \n\t\t\t\t\tto 'count' bytes.\n\tBUFFER_FIXED\tBuffer of total allocated and filled size 'max'.\n\n   In addition to these we allow the OPT specifier as before, and the \n   UNSPECIFIED specifier to indicate that the fill state of the buffer \n   isn't specified or at least is too complex to describe to PREfast, for \n   example an I/O buffer that acts as BUFFER on read but BUFFER_FIXED on \n   write.\n   \n   The VALUE_xxx annotations don't appear to be implemented in current \n   versions of PREfast.  For example the annotation of the handle ranges for \n   MESSAGE_CREATEOBJECT_INFO in cryptkrn.h has no effect, producing a \n   warning that the handle value is potentially out of range every time that \n   it's used.  At the moment this is kludged with an ANALYSER_HINT() for\n   the setMessageCreateObjectInfo() macro, which silences the hundreds of\n   warnings that would otherwise be produced */\n\n#define VALUE( min, max )\t\t_Field_range_( ( min ), ( max ) )\n#define VALUE_HANDLE\t\t\t_Field_range_( SYSTEM_OBJECT_HANDLE, MAX_NO_OBJECTS - 1 )\n#define VALUE_HANDLE_OPT\t\t_Field_range_( CRYPT_UNUSED, MAX_NO_OBJECTS - 1 )\n#define VALUE_INT\t\t\t\t_Field_range_( 0, MAX_INTLENGTH ) \n#define VALUE_INT_SHORT\t\t\t_Field_range_( 0, MAX_INTLENGTH_SHORT ) \n#define ARRAY( max, count )\t\t_Field_size_part_( ( max ), ( count ) )\n#define ARRAY_FIXED( max )\t\t_Field_size_( max )\n#define BUFFER( max, count )\t_Field_size_bytes_part_( ( max ), ( count ) )\n#define BUFFER_OPT( max, count ) _Field_size_bytes_part_opt_( ( max ), ( count ) )\n#define BUFFER_FIXED( max )\t\t_Field_size_bytes_( max )\n#define BUFFER_OPT_FIXED( max )\t_Field_size_bytes_opt_( max )\n#define BUFFER_UNSPECIFIED( max ) _Field_size_bytes_( max )\n\n/* Memory-allocation functions that allocate and return a block of \n   initialised memory:\n\n\tALLOC\t\t\tPointer can't be NULL, *pointer set to NULL on failure.\n\tALLOC_OPT\t\tPointer may be NULL, *pointer set to NULL on failure  */\n\n#define OUT_BUFFER_ALLOC( length )\t\t_Outptr_result_nullonfailure_ \\\n\t\t\t\t\t\t\t\t\t\t_Outptr_result_bytebuffer_( length )\n#define OUT_BUFFER_ALLOC_OPT( length )\t_Outptr_opt_result_nullonfailure_ \\\n\t\t\t\t\t\t\t\t\t\t_Outptr_opt_result_bytebuffer_( length )\n\n/* Pointer annotations for parameter DATAPTR.  This is just a plain \n   IN/OUT/etc, but we make it a separate annotation in case future versions \n   of PREfast allow additional checking */\n\n#define IN_DATAPTR\t\t\t\tIN\n#define IN_DATAPTR_OPT\t\t\tIN\n#define OUT_DATAPTR\t\t\t\tOUT\n#define OUT_DATAPTR_COND\t\tOUT\n#define OUT_DATAPTR_xCOND\t\tOUT\n\n/* Typeless annotations used in situations where the size or type is \n   implicit, e.g. a pointer to a structure.  The annotation 'IN' is \n   implied by 'const' so we wouldn't normally use it, but it can be useful \n   when we're re-prototyping a non-cryptlib function that doesn't use \n   'const's,\n   \n   OUT_ALWAYS is a special-case annotation where we always set the annotated\n   parameter but also return a status value to indicate additional\n   information.  Examples of this occur in some of the error-handling \n   functions, which set ERROR_INFO structures but also return an error\n   status that represents value to pass back to the caller rather than the\n   success status of the error handler  */\n\n#ifdef IN\t\t/* Defined to no-ops in some versions of windef.h */\n  #undef IN\n  #undef OUT\n#endif\n\n#define IN\t\t\t\t\t\t_In_\n#define IN_OPT\t\t\t\t\t_In_opt_\n#define INOUT\t\t\t\t\t_Inout_\n#define INOUT_OPT\t\t\t\t_Inout_opt_\n#define OUT\t\t\t\t\t\t_Out_\n#define OUT_OPT\t\t\t\t\t_Out_opt_\n#define OUT_ALWAYS\t\t\t\t_Always_( _Out_ )\n\n/* Pointer annotations for parameter **result:\n\n\tOUT_PTR\t\t\t\tresult non-NULL, *result non-NULL.\n\tOUT_PTR_COND\t\tresult non-NULL, *result non-NULL on success.\n\tOUT_PTR_xCOND\t\tresult non-NULL, *result non-NULL on failure.\n\t\t\t\t\t\tUsed for functions that return pointer to error info.\n\tOUT_PTR_OPT\t\t\tresult non-NULL, *result may be NULL or non-NULL.\n\t\t\t\t\t\tUsed for caller-cleanup functions (create \n\t\t\t\t\t\tcert/ctx/key/etc object), or for functions that \n\t\t\t\t\t\treturn a pointer to a mismatch point \n\t\t\t\t\t\t(findRevocationEntry()).\n\tOUT_OPT_PTR\t\t\tresult may be NULL, *result non-NULL.\n\tOUT_OPT_PTR_COND\tresult may be NULL, *result non-NULL on success */\n\n#define INOUT_PTR\t\t\t\t_Inout_\n\t\t\t\t\t\t\t\t/* There's no \n\t\t\t\t\t\t\t\t   _Inoutptr_result_nullonfailure_, the \n\t\t\t\t\t\t\t\t   _Inout_ seems to work though */\n#define OUT_PTR\t\t\t\t\t_Outptr_\n#define OUT_PTR_COND\t\t\t_Outptr_result_nullonfailure_\n#define OUT_PTR_OPT\t\t\t\t_Outptr_result_maybenull_\n#define OUT_OPT_PTR\t\t\t\t_Outptr_opt_\n#define OUT_OPT_PTR_COND\t\t_Outptr_opt_result_nullonfailure_\n\n/* There's no way to say OUT_PTR_xCOND and OUT_OPT_PTR_xCOND in SAL, the \n   following is a guess at what might be required, or at least a guess\n   tempered by something that doesn't produce compile errors */\n\n#define OUT_PTR_xCOND \\\n\t\t_SAL2_Source_(_Outptr_result_nonnullonfailure_, (), \\\n\t\t\t\t\t\t_Outptr_ _On_failure_( _Notref_impl_ _Deref_impl_ ) )\n#define OUT_OPT_PTR_xCOND \\\n\t\t_SAL2_Source_(_Outptr_result_nonnullonfailure_, (), \\\n\t\t\t\t\t\t_Outptr_opt_ _On_failure_( _Notref_impl_ _Deref_impl_ ) )\n\n/* Other annotations:\n\n\tFORMAT_STRING\tArgument is a printf-style format string.\n\tIN_STRING\t\tArgument is a null-terminated string.\n\tTYPECAST\t\tType cast, e.g. from void * to struct foo * */\n\n#define ANALYSER_HINT( expr )\t__analysis_assume( expr )\n#define ANALYSER_HINT_V( expr )\t__analysis_assume( expr )\n\t\t\t\t\t\t\t\t/* Attribute SAL has no equivalent for this, \n\t\t\t\t\t\t\t\t   but __analysis_assume() still works */\n#define FORMAT_STRING\t\t\t_Printf_format_string_\n#define IN_STRING\t\t\t\t_In_z_\n#define IN_STRING_OPT\t\t\t_In_opt_z_\n#define TYPECAST( type )\t\t/* No equivalent in attribute SAL */\n\n#endif /* PREfast */\n\n/* Handling of C'0x analysis */\n\n#if defined( _MSC_VER ) && !VC_16BIT( _MSC_VER )\n\n#define STDC_NONNULL_ARG( argIndex )\n#define STDC_PRINTF_FN( formatIndex, argIndex )\n#define STDC_PURE\t\t\t__declspec( noalias )\n#if defined( _MSC_VER ) && defined( _PREFAST_ ) \n  #define STDC_FALLTHROUGH\t__fallthrough\n  #define STDC_UNUSED\t\t_Reserved_\n#else\n  #define STDC_FALLTHROUGH\n  #define STDC_UNUSED\n#endif /* VC++ with/without PREfast */\n\n#endif /* VC++ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tgcc/C'0x Analysis Support \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if ( defined( __GNUC__ ) && ( __GNUC__ >= 4 ) ) || defined( __clang__ )\n\n/* Future versions of the C standard will support the ability to annotate \n   functions to allow the compiler to perform extra checking and assist with\n   code generation.  Currently clang and gcc support this annotation, in \n   gcc's case in a highly gcc-specific (meaning broken-by-design) manner, see \n   below.  In order to handle this we define macros for the proposed \n   C-standard annotation, which defines attributes of the form \"stdc_<name>\", \n   although how they'll be applied is still undecided.\n\n   Unfortunately neither gcc's STDC_NONNULL_ARG nor its CHECK_RETVAL \n   checking work properly.  CHECK_RETVAL is the least broken since it merely \n   fails to report a return value being unchecked in many cases while\n   reporting unnecessary false positives in others, but STDC_NONNULL_ARG is \n   downright dangerous since it'll break correctly functioning code.\n   \n   The problem with CHECK_RETVAL is that it regards any \"use\" of the return \n   value of a function, for example assigning it to a variable that's never \n   used, as fulfilling the conditions for \"use\", and therefore issues no \n   warning.  On the other hand the standard \"(void)\" cast that's been used \n   to indicate that you genuinely want to ignore the return value of a \n   function since circa 1979 with lint is ignored, resulting in warnings \n   where there shouldn't be any.\n\n   STDC_NONNULL_ARG on the other hand is far more broken since the warnings\n   are issued by the front-end before data flow analysis occurs (so many\n   cases of NULL pointer use are missed) but then the optimiser takes the\n   annotation to mean that that value can never be NULL and *removes any\n   code that might check for a NULL pointer*!  This is made even worse by\n   the awkward way that the annotation works, requiring hand-counting the\n   parameters and providing an index into the parameter list instead of\n   placing it next to the parameter as for STDC_UNUSED (clang supports the\n   latter form, but since gcc doesn't we have to use the awkward gcc form).\n\n   clang's nonnull attribute is bug-compatible with the gcc braindamage,\n   however it has a _Nonnull type qualifier that can be inserted next to\n   the parameter like STDC_UNUSED, which we could use in various IN_xxx/\n   INOUT_xxx/OUT_xxx annotations.\n\n   The NULL-pointer problem may be controllable through \n   -fno-delete-null-pointer-checks, but this is actually present in order to \n   address a different issue, that code like \n   'b = a->b; if( a == NULL ) return -1', which will segfault on most \n   architectures but not ones that don't have memory protection (e.g. ARM7)\n   will never get to the NULL check so it can be deleted (as above, gcc\n   generates code that it knows will segfault instead of warning that \n   there's a problem).  Since -fno-delete-null-pointer-checks doesn't\n   necessarily apply to STDC_NONNULL_ARG, it's not safe to rely on it, and\n   in any case we want the compiler to warn of erroneous use, not knowingly\n   generate code that segfaults when it's encountered.\n\n   For both of these issues the gcc maintainers' response was \"not our \n   problem/it's behaving as intended\".\n   \n   This isn't the only time that gcc maintainers have introduced faults \n   and/or security flaws into gcc-generated code.  When they changed gcc to \n   optimise away integer-overflow checks like 'a*b/b != a' (see \"IntPatch: \n   Automatically Fix Integer-Overflow-to-Buffer-Overflow Vulnerability at \n   Compile Time\", Zhang et al, ESORICS'10) or 'a + 100 > 0' they spent a 55-\n   message thread arguing over why it was OK to do this (see \n   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475) rather than actually \n   fixing it (although in this case the lack of tact of the bug submitter \n   can't have helped either).\n   \n   Another case is the totally braindamaged behaviour of -Wshadow, which \n   took a complaint from no less then Linus Torvalds to get fixed (see \n   \"[PATCH] Don't compare unsigned variable for <0 in sys_prctl()\", \n   http://lkml.org/lkml/2006/11/28/239, and even then it took them six\n   years to fix the problem) */\n\n#define STDC_NONNULL_ARG( argIndex ) \\\n\t\t\t__attribute__(( nonnull argIndex ))\n#define STDC_PRINTF_FN( formatIndex, argIndex ) \\\n\t\t\t__attribute__(( format( printf, formatIndex, argIndex ) ))\n#define STDC_PURE\t\t\t__attribute__(( pure ))\n#if defined( __clang__ ) && ( __clang_major__ >= 5 ) && !defined( __APPLE_CC__ )\n  /* The distinct double guard is necessary here because gcc chokes if it \n\t sees __has_attribute() on the same line as #if defined ... \n\t \n\t We need to specifically exclude Apple's mutant clang fork, which has\n\t a __has_attribute( fallthrough ) reporting that it's available even\n\t though it isn't, resulting in \"declaration does not declare anything\" \n\t warnings on compile.  However, this may be a large clang issue since\n\t clang 4.x also has a __has_attribute( fallthrough ) even though it's\n\t not supported, so we guard it with a check for version >= 5 */\n  #if __has_attribute( fallthrough )\n\t#define STDC_FALLTHROUGH __attribute__(( fallthrough ))\n  #else\n\t#define STDC_FALLTHROUGH\n  #endif /* LLVM attributes */\n#elif defined( __GNUC__ ) && ( __GNUC__ >= 7 )\n  #define STDC_FALLTHROUGH\t__attribute__(( fallthrough ))\n#else\n  #define STDC_FALLTHROUGH\n#endif /* Compiler-specific fallthrough-annotation support */\n#define STDC_UNUSED\t\t\t__attribute__(( unused ))\n\n/* The return-value-checking annotation should really be \n   STDC_WARN_UNUSED_RESULT but since the PREfast attributes are defined and \n   widely used within cryptlib while the C standard ones don't even \n   officially exist yet, we allow the PREfast naming to take precedence */\n\n#define CHECK_RETVAL \\\n\t\t\t__attribute__(( warn_unused_result ))\n#define CHECK_RETVAL_BOOL\t\t\t\tCHECK_RETVAL\n#define CHECK_RETVAL_DATAPTR\t\t\tCHECK_RETVAL\n#define CHECK_RETVAL_ENUM( name )\t\tCHECK_RETVAL\n#define CHECK_RETVAL_LENGTH\t\t\t\tCHECK_RETVAL\n#define CHECK_RETVAL_LENGTH_NOERROR\t\tCHECK_RETVAL\n#define CHECK_RETVAL_LENGTH_SHORT\t\tCHECK_RETVAL\n#define CHECK_RETVAL_LENGTH_SHORT_NOERROR CHECK_RETVAL\n#define CHECK_RETVAL_PTR\t\t\t\tCHECK_RETVAL\n#define CHECK_RETVAL_PTR_NONNULL\t\tCHECK_RETVAL\n#define CHECK_RETVAL_RANGE( low, high )\tCHECK_RETVAL\n#define CHECK_RETVAL_RANGE_NOERROR( low, high ) CHECK_RETVAL\n#define CHECK_RETVAL_SPECIAL\t\t\tCHECK_RETVAL\n#define CHECK_RETVAL_STRINGOP\t\t\tCHECK_RETVAL\n\n#define CHECK_RETVAL_ERROR\t\t\t\tCHECK_RETVAL\n\n#define CHECK_RETVAL_ACQUIRELOCK( lockName ) \\\n\t\t\t\t\t\t\t\t\t\tCHECK_RETVAL\n\n/* gcc's handling of both warn_unused_result and nonnull is just too broken\n   to safely use it in any production code, because of this we require the \n   use to be explicitly enabled.  Since clang/LLVM share the gcc front-end\n   and do actually get things right, we don't disable them if we're using\n   clang */\n\n#if !( defined( USE_GCC_ATTRIBUTES ) || defined( __clang_analyzer__ ) )\n  #undef STDC_NONNULL_ARG\n  #define STDC_NONNULL_ARG( argIndex )\n  #undef CHECK_RETVAL\n  #define CHECK_RETVAL\n#endif /* gcc with use of dangerous attributes disabled */\n\n/* clang/LLVM uses gcc as a front-end so we can also end up in the gcc case \n   if we're using clang.  The following defines are for clang with gcc as a\n   front-end */\n\n#ifdef __clang_analyzer__\n\n/* Since clang, unlike gcc, gets CHECK_RETVAL and STDC_NONNULL_ARG right, we \n   can enable it not only for cryptlib functions but also for C library \n   ones.  To do this we override at-risk functions with our own ones whose \n   prototypes allow for extended checking with clang */\n\nCHECK_RETVAL \\\n\tvoid *_checked_malloc( size_t size );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\n\tvoid _checked_free( void *ptr );\n\n#define malloc( x )\t\t\t_checked_malloc( x )\n#define free( x )\t\t\t_checked_free( x )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tint _checked_memcmp( const void *ptr1, const void *ptr2, size_t num );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tvoid *_checked_memcpy( void *dest, const void *src, size_t num );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tvoid *_checked_memmove( void *dest, const void *src, size_t num );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\n\tvoid *_checked_memset( void *ptr, int value, size_t num );\n\n#define memcmp( x, y, z )\t_checked_memcmp( x, y, z )\n#define memcpy( x, y, z )\t_checked_memcpy( x, y, z )\n#define memmove( x, y, z )\t_checked_memmove( x, y, z )\n#define memset( x, y, z )\t_checked_memset( x, y, z )\n\n/* Unfortunately clang doesn't provide any real means of guiding the \n   analyser, the best that we can do is use an ENSURES() */\n\n#define ANALYSER_HINT( expr )\tENSURES( expr )\n#define ANALYSER_HINT_V( expr )\tENSURES_V( expr )\n\n#endif /* clang/LLVM */\n\n/* gcc can also provide approximate guessing at buffer overflows.  This is \n   sufficiently hit-and-miss, and subject to platform-specific false \n   positives and other glitches, that we only enable it for the test build \n   in case it catches something there.  clang does a much better job at \n   finding issues without all of the accompanying problems */\n\n#ifdef USE_GCC_ATTRIBUTES\n\n#define bos( x ) __builtin_object_size( x, 0 )\n\n#undef memcpy\n#define memcpy( dest, src, count ) \\\n\t\t__builtin___memcpy_chk( dest, src, count, bos( dest ) )\n#undef memmove\n#define memmove( dest, src, count ) \\\n\t\t__builtin___memmove_chk( dest, src, count, bos( dest ) )\n#undef memset\n#define memset( ptr, value, count ) \\\n\t\t__builtin___memset_chk( ptr, value, count, bos( ptr ) )\n#undef strcpy\n#define strcpy( dest, src ) \\\n\t\t__builtin___strcpy_chk( dest, src, bos( dest ) )\n#undef strncpy\n#define strncpy( dest, src, size ) \\\n\t\t__builtin___strncpy_chk( dest, src, size, bos( dest ) )\n#undef strcat\n#define strcat( dest, src ) \\\n\t\t__builtin___strcat_chk( dest, src, bos( dest ) )\n\n#endif /* gcc on the test platform */\n\n#endif /* gcc/C'0x */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCoverity Analysis Support \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef __COVERITY__\n\n/* Coverity's annotations differ from everyone else's in that they're not\n   attributes applied to variables but explicit macros, so instead of:\n\n\tfoo( IN_STRING char *string )\n\n   they're given as:\n\n\tfoo( char *string )\n\t\t{\n\t\tANALYSER_HINT_STRING( string );\n\n   The annotations are documented in Help | Check Reference | Models and \n   annotations | Primitives for custom models, the ones that we use are:\n\n\tANALYSER_HINT_FORMAT_STRING: The string is a printf-style format string.\n\n\tANALYSER_HINT_STRING: The string must be a null-terminated string.\n\n\tANALYSER_HINT_RECURSIVE_LOCK/UNLOCK: The lock is recursively locked/\n\t\tunlocked.  This is required when cryptlib synthesises recursive \n\t\tmutexes from Posix non-recursive ones */\n\n#define ANALYSER_HINT_FORMAT_STRING( string )\t__coverity_format_string_sink__( string );\n#define ANALYSER_HINT_STRING( string )\t\t\t__coverity_string_null_sink__( string );\n#define ANALYSER_HINT_RECURSIVE_LOCK( lock )\t__coverity_recursive_lock_acquire__( lock );\n#define ANALYSER_HINT_RECURSIVE_UNLOCK( lock )\t__coverity_recursive_lock_release__( lock );\n\n#endif /* Coverity */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tNo Analysis \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CHECK_RETVAL\n\n#define CHECK_RETVAL\n#define CHECK_RETVAL_BOOL\n#define CHECK_RETVAL_DATAPTR\n#define CHECK_RETVAL_ENUM( name )\n#define CHECK_RETVAL_LENGTH\n#define CHECK_RETVAL_LENGTH_NOERROR\n#define CHECK_RETVAL_LENGTH_SHORT\n#define CHECK_RETVAL_LENGTH_SHORT_NOERROR\n#define CHECK_RETVAL_PTR\n#define CHECK_RETVAL_PTR_NONNULL\n#define CHECK_RETVAL_RANGE( low, high )\n#define CHECK_RETVAL_RANGE_NOERROR( low, high )\n#define CHECK_RETVAL_SPECIAL\n#define CHECK_RETVAL_STRINGOP\n\n#define CHECK_RETVAL_ERROR\n\n#define CHECK_RETVAL_ACQUIRELOCK( lockName )\n\n#endif /* No basic analysis support */\n\n#ifndef RETVAL\n\n#define RETVAL\n#define RETVAL_BOOL\n#define RETVAL_LENGTH_NOERROR\n#define RETVAL_LENGTH_SHORT_NOERROR\n#define RETVAL_RANGE( low, high )\n#define RETVAL_RANGE_NOERROR( low, high )\n\n#define RETVAL_RELEASELOCK( lockName )\n#define RELEASELOCK( lockName )\n\n#define IN_INT\n#define IN_INT_OPT\n#define IN_INT_Z\n#define IN_INT_SHORT\n#define IN_INT_SHORT_Z\n#define OUT_INT_Z\n#define OUT_INT_SHORT_Z\n#define OUT_OPT_INT_Z\n#define INOUT_INT_Z\n\n#define IN_ALGO\n#define IN_ALGO_OPT\n#define IN_ATTRIBUTE\n#define IN_ATTRIBUTE_OPT\n#define IN_BYTE\n#define IN_CHAR\n#define IN_ERROR\n#define IN_HANDLE\n#define IN_HANDLE_OPT\n#define IN_KEYID\n#define IN_KEYID_OPT\n#define IN_MESSAGE\n#define IN_MODE\n#define IN_MODE_OPT\n#define IN_PORT\n#define IN_PORT_OPT\n#define IN_RANGE( min, max )\n#define IN_RANGE_FIXED( value )\n#define IN_STATUS\n#define INOUT_HANDLE\n#define INOUT_RANGE( min, max )\n#define OUT_ALGO_Z\n#define OUT_OPT_ALGO_Z\n#define OUT_ATTRIBUTE_Z\n#define OUT_OPT_ATTRIBUTE_Z\n#define OUT_BOOL\n#define OUT_OPT_BOOL\n#define OUT_OPT_BYTE\n#define OUT_ERROR\n#define OUT_HANDLE_OPT\n#define OUT_OPT_HANDLE_OPT\n#define OUT_INDEX( max )\n#define OUT_OPT_INDEX( max )\n#define OUT_PORT_Z\n#define OUT_RANGE( min, max )\n#define OUT_OPT_RANGE( min, max )\n#define OUT_STATUS\n\n#define IN_LENGTH\n#define IN_LENGTH_OPT\n#define IN_LENGTH_FIXED( size )\n#define IN_LENGTH_MIN( min )\n#define IN_LENGTH_Z\n#define IN_DATALENGTH\n#define IN_DATALENGTH_OPT\n#define IN_DATALENGTH_MIN( min )\n#define IN_DATALENGTH_Z\n#define IN_LENGTH_SHORT\n#define IN_LENGTH_SHORT_MIN( min )\n#define IN_LENGTH_SHORT_OPT\n#define IN_LENGTH_SHORT_Z\n#define INOUT_LENGTH_Z\n#define INOUT_LENGTH_SHORT_Z\n#define OUT_LENGTH\n#define OUT_LENGTH_Z\n#define OUT_OPT_LENGTH_Z\n#define OUT_DATALENGTH\n#define OUT_DATALENGTH_Z\n#define OUT_OPT_DATALENGTH_Z\n#define OUT_LENGTH_SHORT\n#define OUT_OPT_LENGTH_SHORT\n#define OUT_OPT_LENGTH_SHORT_MIN( min )\n#define OUT_OPT_LENGTH_SHORT_Z\n#define OUT_LENGTH_SHORT_Z\n\n#define OUT_LENGTH_BOUNDED( length )\n#define OUT_LENGTH_BOUNDED_Z( length )\n#define OUT_LENGTH_BOUNDED_SHORT_Z( length )\n#define OUT_LENGTH_BOUNDED_PKC_Z( length )\n\n#define IN_LENGTH_ATTRIBUTE\n#define IN_LENGTH_DNS\n#define IN_LENGTH_DNS_Z\n#define IN_LENGTH_ERRORMESSAGE\n#define IN_LENGTH_HASH\n#define IN_LENGTH_HASH_Z\n#define IN_LENGTH_INDEF\n#define IN_LENGTH_IV\n#define IN_LENGTH_IV_Z\n#define IN_LENGTH_KEY\n#define IN_LENGTH_KEYID\n#define IN_LENGTH_KEYID_Z\n#define IN_LENGTH_NAME\n#define IN_LENGTH_NAME_Z\n#define IN_LENGTH_OID\n#define IN_LENGTH_PKC\n#define IN_LENGTH_PKC_BITS\n#define IN_LENGTH_PKC_Z\n#define IN_LENGTH_TEXT\n#define IN_LENGTH_TEXT_Z\n#define OUT_LENGTH_HASH_Z\n#define OUT_LENGTH_DNS_Z\n#define OUT_OPT_LENGTH_HASH_Z\n#define OUT_LENGTH_PKC_Z\n#define OUT_LENGTH_INDEF\n#define OUT_OPT_LENGTH_INDEF\n#define OUT_OPT_LENGTH_SHORT_INDEF\n\n#define IN_TAG\n#define IN_TAG_EXT\n#define IN_TAG_ENCODED\n#define IN_TAG_ENCODED_EXT\n#define OUT_TAG_Z\n#define OUT_TAG_ENCODED_Z\n\n#define IN_ENUM( name )\n#define IN_ENUM_OPT( name )\n#define INOUT_ENUM( name )\n#define INOUT_ENUM_OPT( name )\n#define OUT_ENUM( name )\n#define OUT_ENUM_OPT( name )\n#define OUT_OPT_ENUM( name )\n\n#define IN_FLAGS( name )\n#define IN_FLAGS_Z( name )\n#define OUT_FLAGS_Z( name )\n\n#define IN_BUFFER( size )\n#define IN_BUFFER_C( size )\n#define IN_BUFFER_OPT( size )\n#define IN_BUFFER_OPT_C( count )\n#define INOUT_BUFFER( max, size )\n#define INOUT_BUFFER_C( max, size )\n#define INOUT_BUFFER_FIXED( size )\n#define INOUT_BUFFER_OPT( max, count )\n#define OUT_BUFFER( max, size )\n#define OUT_BUFFER_C( max, size )\n#define OUT_BUFFER_FIXED( max )\n#define OUT_BUFFER_FIXED_C( count )\n#define OUT_BUFFER_OPT( max, size )\n#define OUT_BUFFER_OPT_C( max, size )\n#define OUT_BUFFER_OPT_FIXED( max )\n#define WORKING_BUFFER( max )\n\n#define IN_ARRAY( count )\n#define IN_ARRAY_C( count )\n#define IN_ARRAY_OPT( count )\n#define IN_ARRAY_OPT_C( count )\n#define INOUT_ARRAY( count )\n#define INOUT_ARRAY_C( count )\n#define OUT_ARRAY( count )\n#define OUT_ARRAY_C( count )\n#define OUT_ARRAY_OPT( count )\n#define OUT_ARRAY_OPT_C( count )\n\n#define OUT_WHEN( cond )\n#define INOUT_WHEN( cond )\n\n#define PARAM_NULL\n#define PARAM_IS( value )\n#define PARAMCHECK( condition, param, type )\n#define PARAMCHECK_MESSAGE( msgType, msgDataType, msgValType )\n\n#define VALUE( min, max )\n#define VALUE_HANDLE\n#define VALUE_HANDLE_OPT\n#define VALUE_INT\n#define VALUE_INT_SHORT\n#define ARRAY( max, count )\n#define ARRAY_FIXED( max )\n#define BUFFER( max, count )\n#define BUFFER_OPT( max, count )\n#define BUFFER_FIXED( max )\n#define BUFFER_OPT_FIXED( max )\n#define BUFFER_UNSPECIFIED( max )\n\n#define OUT_BUFFER_ALLOC( length )\n#define OUT_BUFFER_ALLOC_OPT( length )\n\n#define IN\n#define IN_OPT\n#define INOUT\n#define INOUT_OPT\n#define OUT\n#define OUT_OPT\n#define OUT_ALWAYS\n\n#define INOUT_PTR\n#define OUT_PTR\n#define OUT_PTR_COND\n#define OUT_PTR_xCOND\n#define OUT_PTR_OPT\n#define OUT_OPT_PTR\n#define OUT_OPT_PTR_COND\n#define OUT_OPT_PTR_xCOND\n\n#define IN_DATAPTR\n#define IN_DATAPTR_OPT\n#define OUT_DATAPTR\n#define OUT_DATAPTR_COND\n#define OUT_DATAPTR_xCOND\n\n#ifndef ANALYSER_HINT\n  #define ANALYSER_HINT( expr )\n  #define ANALYSER_HINT_V( expr )\n#endif /* ANALYSER_HINT */\n#define FORMAT_STRING\n#define IN_STRING\n#define IN_STRING_OPT\n#define TYPECAST( ctype )\n#ifndef ANALYSER_HINT_FORMAT_STRING\n  #define ANALYSER_HINT_FORMAT_STRING( string )\n  #define ANALYSER_HINT_STRING( string )\n  #define ANALYSER_HINT_RECURSIVE_LOCK( lock )\n  #define ANALYSER_HINT_RECURSIVE_UNLOCK( lock )\n#endif /* ANALYSER_HINT_FORMAT_STRING */\n#endif /* No extended analysis support */\n\n#ifndef STDC_NONNULL_ARG\n\n#define STDC_NONNULL_ARG( argIndex )\n#define STDC_PRINTF_FN( formatIndex, argIndex )\n#define STDC_PURE \n#define STDC_FALLTHROUGH\n#define STDC_UNUSED\n\n#endif /* No C'0x attribute support */\n\n#endif /* _ANALYSE_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/config.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Configuration Settings  \t\t\t\t\t*\n*\t\t\t\t\t   Copyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CONFIG_DEFINED\n\n#define _CONFIG_DEFINED\n#define USE_PROBLEMATIC_ALGORITHMS\n#define USE_SSH_EXTENDED\n#define USE_CERTLEVEL_STANDARD\n#define USE_SSH_CTR\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCustom Configuration Profiles\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*********************************3*******************************************/\n\n/* The following defines can be used to enable specific specific cryptlib \n   profiles that only enable the functionality needed for one particular\n   application:\n\n\t#define CONFIG_PROFILE_SMIME\n\t#define CONFIG_PROFILE_PGP\n\t#define CONFIG_PROFILE_SSL\n\t#define CONFIG_PROFILE_SSH\n\n   The configuration is set up in the section \"Application Profiles\" at the\n   end of this file.  Note that this sort of thing would normally be done by \n   the build command (e.g. in a makefile), the following is mostly intended \n   for debugging */\n\n\n\n\n#if 0\n  #define CONFIG_NO_CERTIFICATES\n  #define CONFIG_NO_DEVICES\n  #define CONFIG_NO_ENVELOPES\n  #define CONFIG_NO_KEYSETS\n  #define CONFIG_NO_SESSIONS\n  #if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 )\n\t#define NO_OBSCURE_FEATURES\n  #endif /* Exception for testing rarely-used facilities under VC++ 6.0 */\n#endif /* 0 */\n\n/* The following configuration options can be used for custom builds of\n   cryptlib to fit constrained environments.  Note that these builds \n   severely constrain the options available for cryptlib use, for example \n   removing certificate support and using CONFIG_USE_PSEUDOCERTIFICATES in \n   combination with CONFIG_PROFILE_SSL requires using a pre-encoded SSL/TLS \n   certificate chain with cryptCreateAttachedCert() to create the server's \n   key, since no certificate import or export capabilities are present */\n\n#if 0\t/* Embedded SSH client/server */\n#define CONFIG_PROFILE_SSH\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define CONFIG_CONSERVE_MEMORY\n#endif /* CONFIG_CONSERVE_MEMORY */\n#define CONFIG_NO_KEYSETS\t\t/* CONFIG_NO_xxx implied by CONFIG_PROFILE_xxx */\n#define CONFIG_NO_CERTIFICATES\n#define CONFIG_NO_DEVICES \n#define CONFIG_NO_ENVELOPES\n#define CONFIG_NO_SELFTEST\n#endif /* 0 */\n\n#if 0\t/* Embedded TLS client/server */\n#define CONFIG_PROFILE_SSL\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define CONFIG_CONSERVE_MEMORY\n#endif /* CONFIG_CONSERVE_MEMORY */\n#define CONFIG_NO_KEYSETS\t\t/* CONFIG_NO_xxx implied by CONFIG_PROFILE_xxx */\n#define CONFIG_NO_CERTIFICATES\n#define CONFIG_NO_DEVICES \n#define CONFIG_NO_ENVELOPES\n#define CONFIG_USE_PSEUDOCERTIFICATES\n#define CONFIG_NO_SELFTEST\n#endif /* 0 */\n\n#if 0\t/* Embedded TLS client/server with SCEP */\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define CONFIG_CONSERVE_MEMORY\n#endif /* CONFIG_CONSERVE_MEMORY */\n#define CONFIG_NO_CONTEXTS\t\t/* Only a few algorithms */\n#define USE_DH\n#define USE_MD5\n#define USE_RSA\n#define USE_PKC\n#define CONFIG_NO_CERTIFICATES\t/* Only basic certificates */\n#define USE_CERTIFICATES \n#define USE_CERTLEVEL_STANDARD\n#define USE_INT_ASN1\n#define CONFIG_NO_DEVICES \n#define CONFIG_NO_ENVELOPES\t\t/* Only CMS envelopes */\n#define USE_ENVELOPES\n#define USE_CMS\n#define USE_INT_CMS\n#define CONFIG_NO_KEYSETS\t\t/* Only PKCS #15 keysets */\n//#define USE_KEYSETS\n//#define USE_PKCS15\n//#define USE_FILES\n#define CONFIG_NO_SESSIONS\t\t/* Only SCEP sessions */\n#define USE_SESSIONS\n#define USE_SSL\n#define USE_SCEP\n#define CONFIG_NO_SELFTEST\n#endif /* 0 */\n\n/* The blanket low-memory configuration option changes other configuration \n   settings as well */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #ifndef CONFIG_NUM_OBJECTS\n\t#define CONFIG_NUM_OBJECTS\t\t128\n  #endif /* CONFIG_NUM_OBJECTS */\n  #ifndef CONFIG_PKC_ALLOCSIZE\n\t#define CONFIG_PKC_ALLOCSIZE\t256\n  #endif /* CONFIG_PKC_ALLOCSIZE */\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* Some standard cryptlib settings can be overridden by user-set \n   configuration options */\n\n#ifdef CONFIG_PKC_ALLOCSIZE\n  #if CONFIG_PKC_ALLOCSIZE < 128 || CONFIG_PKC_ALLOCSIZE > 512\n\t#error CONFIG_PKC_ALLOCSIZE must be between 128 and 512 (1024 to 4096 bits).\n  #endif /* CONFIG_PKC_ALLOCSIZE range check */\n  #undef CRYPT_MAX_PKCSIZE\n  #define CRYPT_MAX_PKCSIZE\t\t\tCONFIG_PKC_ALLOCSIZE\n#endif /* CONFIG_PKC_ALLOCSIZE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGeneral Capabilities\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* General capabilities that affect further config options */\n\n#if defined( __BEOS__ ) || defined( __CHORUS__ ) || \\\n\t( defined( __ECOS__ ) && defined( CYGPKG_NET ) ) || \\\n\tdefined( __embOS__ ) || defined( __FreeRTOS__ ) || \\\n\tdefined( __MGOS__ ) || defined( __MQXRTOS__ ) || \\\n\tdefined( __MVS__ ) || defined( __Nucleus__ ) || \\\n\tdefined( __PALMOS__ ) || defined( __Quadros__ ) || \\\n\tdefined( __RTEMS__ ) || defined( __SYMBIAN32__ ) || \\\n\tdefined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\tdefined( __Telit__ ) || defined( __ThreadX__ ) || \\\n\tdefined( __TKernel__ ) || defined( __UCOS__ ) || \\\n\tdefined( __UNIX__ ) || defined( __VxWorks__ ) || \\\n\tdefined( __WIN32__ ) || defined( __WIN64__ ) || \\\n\tdefined( __WINCE__ )\n  #define USE_TCP\n#endif /* Systems with TCP/IP networking available */\n\n/* Whether to use the RPC API or not.  This provides total isolation of\n   input and output data, at the expense of some additional overhead due\n   to marshalling and unmarshalling */\n\n/* #define USE_RPCAPI */\n\n/* Whether to use FIPS 140 ACLs or not.  Enabling this setting disables\n   all plaintext key loads.  Note that this will cause several of the\n   self-tests, which assume that they can load keys directly, to fail */\n\n/* #define USE_FIPS140 */\n\n/* Whether to build the Java/JNI interface or not */\n\n/* #define USE_JAVA */\n\n/* Whether to provide descriptive text messages for errors or not.\n   Disabling these can reduce code size, at the expense of making error\n   diagnosis reliant solely on error codes */\n\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define USE_ERRMSGS\n#endif /* Low-memory builds */\n\n/* When certificates are disabled in order to reduce code size it may still\n   be necessary to be able to at least send out certificates in things like \n   SSL/TLS handshakes.  The following define enables support for pseudo-\n   certificate objects, objects that support just enough of the required\n   certificate functionality to act as storage containers for encoded\n   certificate data that can be attached to messages */\n\n#ifdef CONFIG_USE_PSEUDOCERTIFICATES\n  #define USE_PSEUDOCERTIFICATES\n#endif /* CONFIG_USE_PSEUDOCERTIFICATES */\n\n/* If we're running a custom configuration we turn off some capabilities\n   that aren't relevant */\n\n#ifdef CONFIG_FUZZ\n  #define CONFIG_NO_SELFTEST\t/* Not needed / slows down fuzzing */\n#endif /* CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tContexts\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_CONTEXTS\n\n/* The umbrella define USE_DEPRECATED_ALGORITHMS can be used to drop \n   deprecated (obsolete or weak) algorithms, and USE_OBSCURE_ALGORITHMS can \n   be used to drop little-used algorithms.  Technically MD5 is also \n   deprecated but it's still so widely used that it's not really possible \n   to drop it */\n\n#if 0\n  #define USE_DEPRECATED_ALGORITHMS\n#endif /* 0 */\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define USE_PATENTED_ALGORITHMS\n  #define USE_OBSCURE_ALGORITHMS\n#endif /* Low-memory builds */\n\n/* Obsolete and/or weak algorithms, disabled by default */\n\n#ifdef USE_DEPRECATED_ALGORITHMS\n  #define USE_DES\n  #define USE_RC2\n  #define USE_RC4\n#endif /* Obsolete and/or weak algorithms */\n\n/* Obscure algorithms */\n\n#ifdef USE_OBSCURE_ALGORITHMS\n  #define USE_ELGAMAL\n  #define USE_IDEA\n#endif /* Obscure algorithms */\n\n/* Problematic algorithms that can cause issues due to memory/code size (for\n   example AES-GCM uses eight times as much memory as straight AES, and \n   that's for the variant with the small lookup tables, and the ECC \n   algorithms have a sizeable code and memory footprint) or because the \n   cryptosystems are brittle and problematic (the ECC algorithms and GCM\n   again) */\n\n#ifdef USE_PROBLEMATIC_ALGORITHMS\n  #define USE_ECDH\n  #define USE_ECDSA\n  #define USE_GCM\n#endif /* Problematic algorithms */\n\n/* Other algorithms.  Note SHA-1 and SHA-2 are always enabled as they're \n   used internally by cryptlib and used by virtually all cryptlib protocols/\n   mechanisms.  In addition at least one of 3DES or AES must be enabled, \n   since they're similarly used internally and by all protocols */\n\n#define USE_3DES\n#define USE_AES\n#define USE_DH\n#define USE_DSA\n#define USE_MD5\n#define USE_RSA\n\n#if !defined( USE_3DES ) && !defined( USE_AES ) \n  #error Either 3DES or AES must be enabled\n#endif /* !USE_3DES && !USE_AES ) */\n\n/* As part of the SHA-1 deprecation in 2016, a number of CAs and sites\n   skipped the obvious SHA-256 and went to SHA-384 or even SHA-512\n   because they wanted hash functions that go to 11 or even 12.  In order\n   to support this nonsense we unfortunately have to enable the extended\n   SHA-2's by default, however we don't enable it in limited-memory \n   environments because the bigger the hash, the larger the code size\n   and constant tables needed to implement it */\n\n#ifndef CONFIG_CONSERVE_MEMORY\n  #define USE_SHA2_EXT\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* General PKC context usage */\n\n#if defined( USE_DH ) || defined( USE_DSA ) || defined( USE_ELGAMAL ) || \\\n\tdefined( USE_RSA ) || defined( USE_ECDH ) || defined( USE_ECDSA )\n  #define USE_PKC\n#endif /* PKC types */\n\n#endif /* CONFIG_NO_CONTEXTS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tCertificates\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_CERTIFICATES\n\n/* The certificate-processing code is so deeply intertwingled (almost all of \n   the code to manipulate certificate attributes is shared, with only a few \n   certificate type-specific routines) that it's quite difficult to separate \n   out individual sections so all that we can provide is the ability to \n   enable/disable general classes of certificate object */\n\n#define USE_CERTIFICATES\n#define USE_ATTRCERT\t\t/* Attribute certificates */\n#define USE_CERTREV\t\t\t/* CRL, OCSP */\n#define USE_CERTVAL\t\t\t/* RTCS */\n#define USE_CERTREQ\t\t\t/* PKCS #10, CRMF */\n#define USE_CMSATTR\t\t\t/* CMS attributes */\n#define USE_PKIUSER\t\t\t/* pkiUser */\n\n/* Another side-effect of the complexity of the certificate-handling code is\n   that it carries around a large amount of code that's required in order to \n   support processing of bizarro attributes that no-one ever uses and whose\n   sole effect is to weaken the overall code by vastly increasing its attack\n   surface.  The following defines can be used to control the maximum level \n   of compliance in the certificate-handling code.  To enable use at \n   compliance level n it's necessary to have the values for level 0...n-1 \n   defined as well, this makes checking in the code cleaner.  Compliance\n   levels _OBLIVIOUS, _REDUCED, and _STANDARD are assumed by default, levels\n   _PKIX_PARTIAL and _PKIX_FULL need to be explicitly enabled.  _PKIX_PARTIAL\n   enables a few extra attributes and extra checking that are skipped in\n   _STANDARD, in most cases there'll be no noticeable difference between\n   _STANDARD and _PKIX_PARTIAL so unless you specifically need it you can\n   disable it to save space and code complexity.  _PKIX_FULL on the other \n   hand enables a large number of additional attributes and checks, \n   including ones that enforce downright bizarre requirements set by the \n   standards.  Unless you understand the implications of this (or you need \n   to pass some sort of external compliance test) you shouldn't enable this \n   level of processing since all it does is increase the code size and \n   attack surface, complicate processing, and (if triggered) produce results\n   that can be quite counterintuitive unless you really understand the\n   peculiarities in the standards */\n\n#if !defined( USE_CERTLEVEL_PKIX_FULL ) && \\\n\t!defined( USE_CERTLEVEL_PKIX_PARTIAL ) && \\\n\t!defined( USE_CERTLEVEL_STANDARD )\n  #define USE_CERTLEVEL_PKIX_PARTIAL\t/* Default level is PKIX_PARTIAL */\n#endif /* PKIX compliance level */\n#if defined( USE_CERTLEVEL_PKIX_FULL ) && !defined( USE_CERTLEVEL_PKIX_PARTIAL )\n  /* USE_CERTLEVEL_PKIX_FULL implies USE_CERTLEVEL_PKIX_PARTIAL */\n  #define USE_CERTLEVEL_PKIX_PARTIAL\n#endif /* USE_CERTLEVEL_PKIX_FULL && !USE_CERTLEVEL_PKIX_PARTIAL */\n\n/* Certificates can be given to us in base64-encoded form, so we need to \n   enable base64 decoding to deal with them.  In addition PKI user support \n   requires the ability to encode/decode PKI userIDs */\n\n#define USE_BASE64\n#ifdef USE_PKIUSER\n  #define USE_BASE64ID\n#endif /* USE_PKIUSER */\n\n/* Certificates need ASN.1 support */\n\n#if defined( USE_CERTIFICATES ) && !defined( USE_INT_ASN1 )\n  #define USE_INT_ASN1\n#endif /* USE_CERTIFICATES && !USE_INT_ASN1 */\n\n/* If we're using pseudo-certificates then we can't also use full \n   certificates */\n\n#if defined( USE_PSEUDOCERTIFICATES ) && defined( USE_CERTIFICATES )\n  #error Cant use both full certificates and pseudocertificates at the same time\n#endif /* USE_PSEUDOCERTIFICATES && USE_CERTIFICATES */\n\n/* The following are used to control handling of obscure certificate and CMS \n   attributes like qualified certificates, SigG certificates, CMS receipts, \n   security labels, and AuthentiCode, and completely obsolete certificate \n   attributes like the old Thawte and Netscape certificate extensions.  These\n   are disabled by default */\n\n#if 0\n  #define USE_CERT_OBSCURE\n  #define USE_CMSATTR_OBSCURE\n  #define USE_CERT_OBSOLETE\n#endif /* 0 */\n\n/* Finally, we provide the ability to disable various complex and therefore\n   error-prone mechanisms that aren't likely to see much use.  By default \n   these are disabled */\n\n#if 0\n  #define USE_CERT_DNSTRING\n#endif /* 0 */\n\n#if ( defined( USE_CERTIFICATES ) || defined( USE_PSEUDOCERTIFICATES ) ) && \\\n\t!defined( USE_PKC )\n  #error Use of certificates requires use of PKC algorithms to be enabled\n#endif /* USE_CERTIFICATES && !USE_PKC */\n\n#endif /* CONFIG_NO_CERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tDevices\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_DEVICES\n\n/* Device types.  PKCS #11 and TPMs can also be enabled under Unix by the \n   auto-config mechanism, which sets HAS_PKCS11 and HAS_TPM if PKCS #11 and\n   TPM support are available */\n\n#if defined( __WIN32__ )\n  #define USE_PKCS11\n  #if !defined( NDEBUG )\n\t#define USE_HARDWARE\n  #endif /* Windows debug mode only */\n#endif /* __WIN32__ */\n#ifdef HAS_PKCS11\n  #define USE_PKCS11\n#endif /* PKCS #11 under Unix autoconfig */\n#ifdef HAS_TPM\n  #define USE_TPM\n#endif /* TPM under Unix autoconfig */\n#if defined( USE_PKCS11 ) || defined( USE_CRYPTOAPI )\n  #define USE_DEVICES\n#endif /* Device types */\n\n#endif /* CONFIG_NO_DEVICES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tEnveloping\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_ENVELOPES\n\n#define USE_CMS\n#define USE_PGP\n\n#if defined( USE_CMS ) || defined( USE_PGP )\n  #define USE_ENVELOPES\n#endif /* Enveloping types */\n\n/* CMS envelopes require CMS data formats and compression support */\n\n#if defined( USE_CMS ) && !defined( USE_INT_CMS )\n  /* CMS enveloping requires CMS data format support */\n  #define USE_INT_CMS\n//#define USE_COMPRESSION\n#endif /* USE_CMS */\n\n/* PGP envelopes require Elgamal, CAST, CFB mode, and compression support.  \n   Note that we don't force USE_IDEA for PGP (even though the patents have \n   expired and it's freely usable) since this should now hopefully be \n   extinct */\n\n#if defined( USE_PGP )\n  #ifndef USE_ELGAMAL\n\t/* OpenPGP requires ElGamal */\n\t#define USE_ELGAMAL\n  #endif /* !USE_ELGAMAL */\n  #ifndef USE_CAST\n\t/* Some OpenPGP implementations still (!!) default to CAST5 */\n\t#define USE_CAST\n  #endif /* !USE_CAST */\n  #ifndef USE_CFB\n\t/* OpenPGP is possibly the last remaining user of CFB mode */\n    #define USE_CFB\n  #endif /* USE_CFB */\n  #ifndef USE_COMPRESSION\n\t/* Decoding PGP messages from other implementations requires \n\t   compression support */\n//\t#define USE_COMPRESSION\n  #endif /* !USE_COMPRESSION */\n#endif /* OpenPGP-specific algorithms */\n\n/* Envelopes require PKC algorithms (they can be done with symmetric \n   algorithms only, but it's rather unikely that anyone will be doing \n   this) */\n\n#if defined( USE_ENVELOPES ) && !defined( USE_PKC )\n  #error Use of envelopes requires use of PKC algorithms to be enabled\n#endif /* USE_ENVELOPES && !USE_PKC */\n\n#endif /* CONFIG_NO_ENVELOPES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKeysets\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_KEYSETS\n\n/* File keysets */\n\n/* By uncommenting the following PKCS #12 define or enabling equivalent\n   functionality in any other manner you acknowledge that you are disabling\n   safety features in the code and take full responbility for any\n   consequences arising from this action.  You also indemnify the cryptlib\n   authors against all actions, claims, losses, costs, and expenses that\n   may be suffered or incurred and that may have arisen directly or\n   indirectly as a result of any use of cryptlib with this change made.  If\n   you receive the code with the safety features already disabled, you must\n   immediately obtain and use an original, unmodified version */\n/* #define USE_PKCS12 */\n/* Going beyond the PKCS #12 read capability which exists solely to allow \n   the import of keys supplied in that format by third parties, cryptlib has\n   a PKCS #12 write capability.  This exists purely to allow the export of\n   a single key with attached certificate for situations in which this is\n   required.  This is not a general-purpose key storage facility because \n   the PKCS #12 format encrypts all public and private components, including\n   certificates, and doesn't provide any indexing information to identify\n   which keys or certificates are present inside the encrypted blob.  This \n   means that there's no way to manage or update keys stored inside a PKCS \n   #12 file, and no way to store more than a single key.  By enabling this \n   additional define, you acknowledge all of the above conditions for the \n   PKCS #12 read capability, as well as the fact that PKCS #12 write is an \n   unsupported facility with special-case usage restrictions that doesn't \n   work like any normal keyset */\n/* #define USE_PKCS12_WRITE */\n\n#define USE_PKCS15\n#define USE_PGPKEYS\n\n#if defined( USE_PKCS15 ) && !defined( USE_INT_CMS )\n  /* PKCS #15 needs CMS support for iCryptImport/ExportKey() */\n  #define USE_INT_CMS\n#endif /* USE_PKCS15 && !USE_INT_CMS */\n#if defined( USE_PGPKEYS ) \n  #ifndef USE_CAST\n\t/* Some OpenPGP implementations still (!!) default to CAST5 */\n\t#define USE_CAST\n  #endif /* !USE_CAST */\n  #ifndef USE_CFB\n\t/* OpenPGP is possibly the last remaining user of CFB mode */\n    #define USE_CFB\n  #endif /* USE_CFB */\n#endif /* USE_PGPKEYS */\n#ifdef USE_PKCS12\n  /* If we use PKCS #12 then we have to enable RC2 in order to handle \n\t Microsoft's continuing use of RC2-40 */\n  #define USE_RC2\n#endif /* USE_PKCS12 */\n#if ( defined( USE_PKCS15 ) || defined( USE_PGPKEYS ) ) && \\\n\t!defined( USE_FILES )\n  /* PKCS #15/PGP keysets need file I/O support */\n  #define USE_FILES\n#endif /* ( USE_PKCS15 || USE_PGPKEYS ) && !USE_FILES */\n\n#if defined( USE_PGPKEYS ) || defined( USE_PKCS15 )\n  #ifndef USE_PKC\n\t#error Use of PGP/PKCS #15 keysets requires use of PKC algorithms to be enabled\n  #endif /* USE_PKC */\n#endif /* USE_PGPKEYS || USE_PKCS15 */\n\n/* Database keysets.  ODBC can also be enabled under Unix by the auto-config \n   mechanism, which sets HAS_ODBC if ODBC support is available */\n\n#if defined( __WIN32__ ) && !defined( NT_DRIVER )\n  #if !( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 ) )\n\t#define USE_ODBC\n  #endif /* Old Borland C++ */\n#endif /* Windows */\n#ifdef HAS_ODBC\n  #define USE_ODBC\n#endif /* ODBC under Unix autoconfig */\n#if defined( USE_ODBC ) || defined( USE_DATABASE ) || \\\n\t\t\t\t\t\t   defined( USE_DATABASE_PLUGIN )\n  #define USE_DBMS\n#endif /* RDBMS types */\n\n/* If we're using a database keyset then we need to be able to encode binary\n   identifiers as text, which requires the use of base64 encoding */\n\n#if defined( USE_DBMS )\n  #define USE_BASE64\n#endif /* USE_BASE64 */\n\n/* Network keysets.  LDAP can also be enabled under Unix by the auto-config \n   mechanism, which sets HAS_LDAP if LDAP support is available.\n\n   Note that LDAP is disabled by default because of its very large attack \n   surface, you should only enable this if it's absolutely essential.  Your \n   security guarantee is void when you do this */\n\n#if defined( __WIN32__ ) && \\\n\t!( defined( NT_DRIVER ) || defined( WIN_DDK ) || \\\n\t   defined( __BORLANDC__ ) ) && 0\n  #define USE_LDAP\n#endif /* Windows */\n#if defined( HAS_LDAP ) && 0\n  #define USE_LDAP\n#endif /* LDAP under Unix autoconfig */\n#ifdef USE_TCP\n  #define USE_HTTP\n#endif /* TCP/IP networking */\n\n/* General keyset usage */\n\n#if defined( USE_DBMS ) || defined( USE_HTTP ) || defined( USE_LDAP ) || \\\n\tdefined( USE_PGPKEYS ) || defined( USE_PKCS12 ) || defined( USE_PKCS15 )\n  #define USE_KEYSETS\n#endif /* Keyset types */\n\n#endif /* CONFIG_NO_KEYSETS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSessions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SESSIONS\n\n#define USE_CERTSTORE\n#define USE_CMP\n#define USE_RTCS\n#define USE_OCSP\n#define USE_SCEP\n#define USE_SSH\n#define USE_SSL\n#define USE_TSP\n\n#if defined( USE_CERTSTORE ) || defined( USE_CMP ) || defined( USE_RTCS ) || \\\n\tdefined( USE_OCSP ) || defined( USE_SCEP ) || defined( USE_SSH ) || \\\n\tdefined( USE_SSL ) || defined( USE_TSP )\n  #define USE_SESSIONS\n#endif /* Session types */\n\n/* We can't use secure sessions if there's no networking available.  We make\n   this check conditional on osspec.h being included, because config.h is \n   also used in files that have nothing to do with networking */\n\n#if defined( _OSSPEC_DEFINED ) && !defined( USE_TCP )\n  #error Use of secure sessions requires the use of TCP/IP\n#endif /* !USE_TCP */\n\n/* Make sure that prerequisites are met for sessions that require \n   certificate components.  We can only check these if there's no specific\n   session-based profile defined, because a profile for (for example) SSH\n   enables sessions, but only the SSH session and not any others, which\n   means that the dependency checks will produce false positives */\n\n#if !defined( CONFIG_PROFILE_SSH ) && !defined( CONFIG_PROFILE_SSL )\n  #if defined( USE_CERTSTORE ) && !defined( USE_CERTIFICATES )\n\t#error Use of a certificate store requires use of certificates to be enabled\n  #endif /* USE_CERTSTORE && !USE_CERTIFICATES */\n  #if defined( USE_CMP ) && !( defined( USE_CERTREQ ) && defined( USE_PKIUSER ) )\n\t#error Use of CMP requires use of certificate requests and PKI users to be enabled\n  #endif /* USE_CMP && !USE_CERTREQ */\n  #if defined( USE_OCSP ) && !defined( USE_CERTREV )\n\t#error Use of OCSP requires use of certificate revocation to be enabled\n  #endif /* USE_OCSP && !USE_CERTREV */\n  #if defined( USE_RTCS ) && !( defined( USE_CERTVAL ) && defined( USE_CMSATTR ) )\n\t/* RTCS needs CRYPT_CERTINFO_CMS_NONCE */\n\t#error Use of RTCS requires use of certificate validation and CMS attributes to be enabled\n  #endif /* USE_RTCS && !( USE_CERTVAL && USE_CMSATTR ) */\n  #if defined( USE_SCEP ) && !( defined( USE_CERTREQ ) && defined( USE_CMSATTR ) && defined( USE_PKIUSER ) )\n\t/* SCEP needs CRYPT_CERTINFO_CHALLENGEPASSWORD for PKCS #10 requests and \n\t   CRYPT_CERTINFO_SCEP_xyz for CMS attributes */\n\t#error Use of SCEP requires use of certificate requests, CMS attributes, and PKI users to be enabled\n  #endif /* USE_SCEP && !( USE_CERTREQ && USE_CMSATTR ) */\n  #if defined( USE_SSL ) && !defined( USE_CERTIFICATES )\n\t#error Use of SSL requires use of certificates to be enabled\n  #endif /* USE_SSL && !USE_CERTIFICATES */\n  #if defined( USE_TSP ) && !defined( USE_CMSATTR )\n\t/* TSP requires CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID */\n\t#error Use of TSP requires use of CMS attributes to be enabled\n  #endif /* USE_TSP && !USE_CERTIFICATES */\n#endif /* !CONFIG_PROFILE_SSH && !CONFIG_PROFILE_SSL */\n\n/* General session usage */\n\n#if defined( USE_SESSIONS ) && !defined( USE_PKC )\n  #error Use of secure sessions requires use of PKC algorithms to be enabled\n#endif /* USE_SESSIONS && !USE_PKC */\n\n/* If we're using SCEP then we need to deal with broken servers that require \n   the use of a POST disguised as a GET, for which we need to base64-encode \n   the binary data that we're sending.  If we're using SSL then we need to\n   enable PKI userIDs, which are used for PSK identities */\n\n#if defined( USE_SCEP ) && !defined( USE_BASE64 )\n  #define USE_BASE64\n#endif /* USE_SCEP && !USE_BASE64 */\n#if defined( USE_SSL ) && !defined( USE_BASE64ID )\n  #define USE_BASE64ID \n#endif /* USE_SSL && !USE_BASE64ID */\n\n/* The pure RSA suites are prone to assorted side-channel attacks that don't\n   affect the DH ones so we try and deprecate these as much as possible.  \n   Unfortunately in the embedded world they're probably still needed due to\n   the slow pace of change there, so at the moment we only disable them for \n   64-bit systems, which by definition are going to be fairly recent */\n\n#ifndef SYSTEM_64BIT\n  #define USE_RSA_SUITES \n#endif /* SYSTEM_64BIT */\n\n/* This now leads to a second problem, as of 2018 many public web servers \n   only support either the unsafe RSA-only suites or ECDH + RSA and will \n   fail the handshake if DH + RSA are specified.  To work around this, we \n   enable ECDH if RSA suites are disabled, which allows for the use of \n   ECDH + RSA without enabling the full ECC dogpile */\n\n#if defined( USE_SSL )&& !defined( USE_RSA_SUITES ) && !defined( USE_ECDH ) \n  #define USE_ECDH\n#endif /* USE_SSL && !USE_RSA_SUITES && !USE_ECDH */\n\n/* Finally, we provide the ability to disable optional, or complex and \n   therefore error-prone, mechanisms that aren't likely to see much use.  By \n   default these are disabled */\n\n#if 0\n  #define USE_EAP\n  #define USE_WEBSOCKETS\n  #define USE_SSH_EXTENDED\n#endif /* 0 */\n\n#endif /* CONFIG_NO_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOS Services and Resources\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Threads, meaning that we make operations thread-safe using mutexes */\n\n#if defined( __AMX__  ) || defined( __ARINC653__ ) || defined( __BEOS__ ) || \\\n\tdefined( __CHORUS__ ) || defined( __CMSIS__ ) || defined( __ECOS__ ) || \\\n\tdefined( __embOS__ ) || defined( __FreeRTOS__ ) || defined( __ITRON__ ) || \\\n\tdefined( __MGOS__ ) || defined( __MQXRTOS__ ) || defined( __Nucleus__ ) || \\\n\tdefined( __OS2__ ) || defined( __OSEK__ ) || defined( __Quadros__ ) || \\\n\tdefined( __PALMOS__ ) || defined( __RTEMS__ ) || defined( __SMX__ ) || \\\n\tdefined( __Telit__ ) || defined( __ThreadX__ ) || \\\n\tdefined( __TKernel__ ) || defined( __UCOS__ ) || defined( __VDK__ ) || \\\n\tdefined( __VxWorks__ ) || defined( __WIN32__ ) || defined( __WINCE__ ) || \\\n\tdefined( __XMK__ ) \n  #define USE_THREADS\n#endif /* Non-Unix systems with threads */\n\n#ifdef __UNIX__\n  #if !( ( defined( __QNX__ ) && ( OSVERSION <= 4 ) ) || \\\n\t\t ( defined( sun ) && ( OSVERSION <= 4 ) ) || defined( __TANDEM ) )\n\t#define USE_THREADS\n  #endif\n#endif /* Unix systems with threads */\n\n/* Alongside making functions thread-safe, we can also run our own threaded\n   functions to handle things like driver binding at startup */\n\n#if defined( USE_THREADS )\n  #define USE_THREAD_FUNCTIONS\n#endif /* USE_THREADS */\n\n#ifdef CONFIG_NO_THREADS\n  /* Allow thread use to be overridden by the user if required */\n  #undef USE_THREADS\n  #undef USE_THREAD_FUNCTIONS\n#endif /* CONFIG_NO_THREADS */\n\n/* Widechars */\n\n#if defined( __Android__ ) || defined( __BEOS__ ) || defined( __ECOS__ ) || \\\n\tdefined( __IAR_SYSTEMS_ICC__ ) || defined( __MSDOS32__ ) || \\\n\tdefined( __OS2__ ) || defined( __RTEMS__ ) || \\\n\tdefined( __TI_COMPILER_VERSION__ ) || \\\n\t( ( defined( __WIN32__ ) || defined( __WINCE__ ) ) && \\\n\t  !( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x500 ) ) ) || \\\n\tdefined( __XMK__ )\n  #define USE_WIDECHARS\n#endif /* Non-Unix systems with widechars */\n\n#ifdef __UNIX__\n  #if !( ( defined( __APPLE__ ) && OSVERSION < 7 ) || \\\n\t\t defined( __bsdi__ ) || \\\n\t\t ( defined( __OpenBSD__ ) && OSVERSION < 5 ) || \\\n\t\t ( defined( __SCO_VERSION__ ) && OSVERSION < 5 ) || \\\n\t\t ( defined( sun ) && OSVERSION < 5 ) || \\\n\t\t defined( __SYMBIAN32__ ) )\n\t#define USE_WIDECHARS\n  #endif\n#endif /* Unix systems with widechars */\n\n/* Embedded OSes are a bit of a special case in that they're usually cross-\n   compiled, which means that we can't just pick up the native defines and \n   headers and go with those.  To help handle things like conditional \n   includes we define a special symbol used to indicate a non-native cross-\n   compile.  Note that this is distinct from specific embedded  OSes like \n   WinCE and PalmOS which are treated as OSes in their own right, while all \n   USE_EMBEDDED_OS OSes are a single amorphous blob */\n\n#if defined( __AMX__ ) || defined( __Android__ ) || defined( __ARINC653__ ) || \\\n\tdefined( __CHORUS__ ) || defined( __CMSIS__ ) || defined( __ECOS__ ) || \\\n\tdefined( __embOS__ ) || defined( __FreeRTOS__ ) || defined( __ITRON__ ) || \\\n\tdefined( __MGOS__ ) || defined( __MQXRTOS__ ) || defined( __OSEK__ ) || \\\n\tdefined( __Quadros__ ) || defined( __RTEMS__ ) || defined( __Telit__ ) || \\\n\tdefined( __ThreadX__ ) || defined( __TKernel__ ) || defined( __UCOS__ ) || \\\n\tdefined( __VDK__ ) || defined( __VxWorks__ ) || defined( __XMK__ )\n  #define USE_EMBEDDED_OS\n#endif /* Embedded OSes */\n\n/* If it's an embededd OS there probably won't be much in the way of entropy\n   sources available so we enable the use of the random seed file by \n   default.  Since this requires at least file I/O support, we also need to\n   enable that if it's been disabled by disabling keysets */\n\n#if defined( USE_EMBEDDED_OS ) && !defined( CONFIG_RANDSEED )\n  #define CONFIG_RANDSEED\n#endif /* USE_EMBEDDED_OS && !CONFIG_RANDSEED */\n#ifdef CONFIG_RANDSEED\n  #ifndef USE_FILES\n\t#define USE_FILES\n  #endif /* USE_FILES */\n#endif /* CONFIG_RANDSEED */\n\n/* Networking.  DNS SRV is very rarely used and somewhat risky to leave \n   enabled by default because the high level of complexity of DNS packet \n   parsing combined with the primitiveness of some of the APIs (specifically\n   the Unix ones) make it a bit risky to leave enabled by default, so we\n   disabled it by default for attack surface reduction */\n\n#if defined( USE_TCP ) && \\\n\t( defined( __WINDOWS__ ) || defined( __UNIX__ ) ) && 0\n  #define USE_DNSSRV\n#endif /* Windows || Unix */\n\n/* If we're on a particularly slow or fast CPU we disable or enable certain \n   processor-intensive operations.  In the absence of any easy compile-time \n   metric we define the following:\n\n\tSlow: All 16-bit CPUs.\n\n\tFast: All 64-bit CPUs.  Windows PCs.  Arm A-series CPUs.\n\t\t  Servers: High-end MIPS, Sparc, PowerPC (these are ones not already\n\t\t\t\t   handled as 64-bit systems, of which there are likely few \n\t\t\t\t   if any left).\n\n   This isn't perfect, but is a reasonable approximation */\n\n#if defined( SYSTEM_16BIT )\n  #define CONFIG_SLOW_CPU\n#elif defined( SYSTEM_64BIT ) || defined( __WINDOWS__ ) || \\\n\t  defined( __ARM_ARCH_8A__ ) || defined( _MIPS_ISA_MIPS4 ) || \\\n\t  defined( __POWERPC__ ) || defined( __sparc_v9__ )\n  #define CONFIG_FAST_CPU\n#endif /* Approximation of CPU speeds */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tInternal/Low-level Formats\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The CMS data format requires the use of ASN.1 */\n\n#if defined( USE_INT_CMS ) && !defined( USE_INT_ASN1 )\n  #define USE_INT_ASN1\n#endif /* USE_INT_CMS && !USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tApplication Profiles\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following profiles can be used to enable specific functionality for\n   applications like SSL, SSH, and S/MIME */\n\n#if defined( CONFIG_PROFILE_SMIME ) || defined( CONFIG_PROFILE_PGP ) || \\\n\tdefined( CONFIG_PROFILE_SSH ) || defined( CONFIG_PROFILE_SSL )\n\t/* Contexts */\n\t#undef USE_CAST\n\t#undef USE_DES\n\t#undef USE_ELGAMAL\n\t#undef USE_IDEA\n\t#undef USE_RC2\n\t#undef USE_RC4\n\n\t/* Certificates */\n\t#undef USE_CERTREV\n\t#undef USE_CERTVAL\n\t#undef USE_CERTREQ\n\t#undef USE_PKIUSER\n\n\t/* Devices */\n\t#undef USE_CRYPTOAPI\n\t#undef USE_HARDWARE\n\t#undef USE_PKCS11\n\t#undef USE_DEVICES\n\n\t/* Keysets */\n\t#undef USE_DBMS\n\t#undef USE_HTTP\n\t#undef USE_LDAP\n\t#undef USE_ODBC\n\n\t/* Misc */\n\t#undef USE_BASE64\n\n\t/* Sessions */\n\t#undef USE_CERTSTORE\n\t#undef USE_CMP\n\t#undef USE_OCSP\n\t#undef USE_RTCS\n\t#undef USE_SCEP\n\t#undef USE_TSP\n\t#undef USE_DNSSRV\n#endif /* Application-specific profiles */\n\n#ifdef CONFIG_PROFILE_SSL\n\t/* Contexts */\n\t#undef USE_DSA\n\n\t/* Certificates */\n\t#undef USE_CMSATTR\n\n\t/* Envelopes */\n\t#undef USE_ENVELOPES\n\t#undef USE_CMS\n\t#undef USE_PGP\n\t#undef USE_COMPRESSION\n\n\t/* Keysets */\n\t#undef USE_PGPKEYS\n\n\t/* Sessions */\n\t#undef USE_SSH\n\n\t/* Internal data formats */\n\t#ifndef USE_PKCS15\n\t  #undef USE_INT_CMS\n\t#endif /* USE_PKCS15 */\n#endif /* CONFIG_PROFILE_SSL */\n\n#ifdef CONFIG_PROFILE_SSH\n\t/* Contexts */\n\t#undef USE_DSA\n\t#undef USE_MD5\n\n\t/* Certificates */\n\t#undef USE_CERTIFICATES\n\t#undef USE_CMSATTR\n\n\t/* Envelopes */\n\t#undef USE_ENVELOPES\n\t#undef USE_CMS\n\t#undef USE_PGP\n\t#undef USE_COMPRESSION\n\n\t/* Keysets */\n\t#undef USE_PGPKEYS\n\n\t/* Sessions */\n\t#undef USE_SSL\n#endif /* CONFIG_PROFILE_SSH */\n\n#ifdef CONFIG_PROFILE_SMIME\n\t/* Contexts */\n\t#undef USE_DH\n\t#undef USE_DSA\n\t#undef USE_MD5\n\n\t/* Envelopes */\n\t#undef USE_PGP\n\n\t/* Keysets */\n\t#undef USE_PGPKEYS\n\n\t/* Sessions */\n\t#undef USE_SSH\n\t#undef USE_SSL\n\t#undef USE_TCP\n\t#undef USE_SESSIONS\n#endif /* CONFIG_PROFILE_SMIME */\n\n#ifdef CONFIG_PROFILE_PGP\n\t/* Contexts */\n\t#undef USE_DH\n\t#undef USE_MD5\n\t#define USE_ELGAMAL\t/* Re-enable algorithms that nothing else uses */\n\t#define USE_CAST\n\n\t/* Certificates */\n\t#undef USE_CERTIFICATES\n\n\t/* Envelopes */\n\t#undef USE_CMS\n\n\t/* Sessions */\n\t#undef USE_SSH\n\t#undef USE_SSL\n\t#undef USE_TCP\n\t#undef USE_SESSIONS\n\n\t/* Internal data formats */\n\t#ifndef USE_PKCS15\n\t  #undef USE_INT_CMS\n\t  #undef USE_INT_ASN1\n\t#endif /* USE_PKCS15 */\n#endif /* CONFIG_PROFILE_PGP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFixups for Build Dependencies\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some of the high-level configuration options above retroactively affect \n   the availability of low-level options.  For example USE_SESSIONS can't be \n   enabled unless USE_TCP is already defined, but then if USE_SESSIONS \n   isn't defined then there's no need for USE_TCP any more.  The following\n   fixups handle situations like this */\n\n/* If use of ASN.1 isn't enabled then we can't use the DLP signature \n   algorithms, which need ASN.1 support to write the signature format.\n   Technically this isn't quite true since we could be writing the signature\n   in SSL/TLS or SSH format, but the self-test uses the ASN.1 format, and we\n   assume that a build that includes SSL/TLS or SSH will also include the\n   ASN.1 capabilities for things like private key storage */\n\n#ifndef USE_INT_ASN1\n  #ifdef USE_DSA\n\t#undef USE_DSA\n  #endif /* USE_DSA */\n  #ifdef USE_ELGAMAL\n\t#undef USE_ELGAMAL\n  #endif /* USE_ELGAMAL */\n  #ifdef USE_ECDSA\n\t#undef USE_ECDSA\n  #endif /* USE_ECDSA */\n#endif /* USE_INT_ASN1 */\n\n/* If sessions or HTTP keysets aren't being used then there's no need for \n   TCP networking */\n\n#if !defined( USE_SESSIONS ) && !( defined( USE_KEYSETS ) && defined( USE_HTTP ) )\n  #ifdef USE_TCP\n\t#undef USE_TCP\n  #endif /* USE_TCP */\n#endif /* USE_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDefines for Testing and Custom Builds\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unsafe or obsolete facilities that are disabled by default, except in the \n   Win32 debug build under VC++ 6.0 or the Win64 debug build under VS 2015.  \n   We have to be careful with the preprocessor checks because the high-level \n   feature-checking defines and macros are only available if osspec.h is \n   included, which it won't be at this level */\n\n#if defined( _WIN32 ) && !defined( NDEBUG ) && defined( _MSC_VER ) && \\\n\t( ( _MSC_VER == 1200 ) || ( _MSC_VER == 1900 && defined( _M_X64 ) ) ) && \\\n\t!defined( NO_OBSCURE_FEATURES ) && \\\n\t!( defined( __WINCE__ ) || defined( CONFIG_PROFILE_SMIME ) || \\\n\t   defined( CONFIG_PROFILE_PGP ) || defined( CONFIG_PROFILE_SSH ) || \\\n\t   defined( CONFIG_PROFILE_SSL ) )\n  #define USE_CERT_DNSTRING\n  #if _MSC_VER == 1200\n\t#define USE_CERTLEVEL_PKIX_FULL\n  #endif /* VC++ 6 debug build only */\n  #define USE_CRYPTOAPI\n  #define USE_CFB\n  #define USE_DES\n  #define USE_ECDH\n  #define USE_ECDSA\n  #define USE_GCM\n  #define USE_SHA2_EXT\n  #define USE_LDAP\n  #define USE_OAEP\n  #define USE_PKCS12\n  #define USE_PKCS12_WRITE \n  #define USE_RC2\t\t/* Needed for PKCS #12 */\n  #define USE_RC4\n  #ifdef USE_TCP\n\t#define USE_SSL3\n\t#define USE_RSA_SUITES \n\t#define USE_SSH_EXTENDED\n\t#define USE_SSH_CTR\n\t#define USE_WEBSOCKETS\n\t#define USE_EAP\n\t#if VC_GE_2005( _MSC_VER )\n\t  #define USE_DNSSRV\n\t#endif /* VS 2005 and newer */\n  #endif /* USE_TCP */\n  #define USE_PGP2\n#endif /* Win32 debug build */\n\n/* If we're using a static analyser then we also enable some additional \n   functionality to allow the analyser to check it */\n\n#if ( defined( _MSC_VER ) && defined( _PREFAST_ ) ) || \\\n\tdefined( __clang_analyzer__ ) || defined( __COVERITY__ ) || \\\n\tdefined( USE_ANALYSER )\n  #define USE_CERT_DNSTRING\n  #define USE_DES\n  #define USE_DNSSRV\n  #define USE_ECDH\n  #define USE_ECDSA\n  #define USE_GCM\n  #define USE_SHA2_EXT\n  #if defined( _PREFAST_ ) || defined( __clang_analyzer__ )\n\t#define USE_LDAP\n  #endif /* Analysers on development machines */\n  #define USE_OAEP\n  #define USE_PKCS12\n  #define USE_PKCS12_WRITE \n  #define USE_RC2\n  #define USE_RC4\n  #define USE_SSL3\n  #define USE_RSA_SUITES \n  #define USE_SSH_EXTENDED\n  #define USE_SSH_CTR\n  #define USE_DNSSRV\n  #define USE_PGP2\n#endif /* Static analyser builds */\n\n/* If we're using Suite B we have to explicitly enable certain algorithms, \n   including extended forms of SHA-2 */\n\n#if defined( CONFIG_SUITEB_TESTS ) && !defined( CONFIG_SUITEB )\n  #define CONFIG_SUITEB \n#endif /* CONFIG_SUITEB_TESTS && !CONFIG_SUITEB */\n#if defined( CONFIG_SUITEB )\n  #define USE_ECDH\n  #define USE_ECDSA\n  #define USE_GCM\n  #define USE_SHA2_EXT\n#endif /* Suite B */\n\n/* Rather than making everything even more complex and conditional than it\n   already is, it's easier to undefine the features that we don't want in\n   one place rather than trying to conditionally enable them */\n\n#if 0\t/* Devices */\n  #undef USE_PKCS11\n  #undef USE_CRYPTOAPI\n#endif /* 0 */\n#if 0\t/* Heavyweight keysets */\n  #undef USE_HTTP\n  #undef USE_LDAP\n  #undef USE_ODBC\n  #undef USE_DBMS\n#endif /* 0 */\n#if 0\t/* Networking */\n  #undef USE_CERTSTORE\n  #undef USE_TCP\n  #undef USE_CMP\n  #undef USE_HTTP\n  #undef USE_RTCS\n  #undef USE_OCSP\n  #undef USE_SCEP\n  #undef USE_SSH\n  #undef USE_SSL\n  #undef USE_TSP\n  #undef USE_SESSIONS\n#endif /* 0 */\n#if 0\t/* Verbose error messages */\n  #undef USE_ERRMSGS\n#endif /* 0 */\n\n\t#undef USE_COMPRESSION\n\n#endif /* _CONFIG_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/consts.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Data Size and Crypto-related Constants \t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CONSTS_DEFINED\n\n#define _CONSTS_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCrypto Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of a cryptlib key ID, a SHA-1 hash of the SubjectPublicKeyInfo,\n   and the PGP key ID */\n\n#define KEYID_SIZE\t\t\t\t20\n#define\tPGP_KEYID_SIZE\t\t\t8\n\n/* The minimum and maximum private key data size.  This is used when \n   buffering the encrypted private key from a keyset during decryption and \n   is equal to the overall size of the total number of possible PKC \n   parameters in an encryption context, plus a little extra for encoding and \n   encryption */\n\n#define MIN_PRIVATE_KEYSIZE\t\t18\t/* For DLP keys */\n#define MAX_PRIVATE_KEYSIZE\t\t( ( CRYPT_MAX_PKCSIZE * 8 ) + 256 )\n\n/* The minimum and maximum working conventional key size.  In order to avoid \n   problems with space inside PKC-encrypted blocks when MIN_PKCSIZE is less \n   than 1024 bits, we limit the total keysize to 256 bits, which is adequate \n   for all purposes - the limiting factor is AES-256 */\n\n#define MIN_KEYSIZE\t\t\t\tbitsToBytes( 64 )\n#define MAX_WORKING_KEYSIZE\t\tbitsToBytes( 256 )\n\n/* The minimum IV size */\n\n#define MIN_IVSIZE\t\t\t\tbitsToBytes( 64 )\n\n/* The minimum public key size (c.f. CRYPT_MAX_PKCSIZE).  This is a bit less \n   than the actual size because keygen specifics can lead to keys that are \n   slightly shorter than the nominal size, and signatures and wrapped keys\n   can also be shorter (1/256 will be one byte shorter, 1/64K will be two\n   bytes shorter, and so on).  In addition we have to have a special value \n   for ECC keys, for which key sizes work differently that conventional \n   PKCs */\n\n#define MIN_PKCSIZE\t\t\t\t( bitsToBytes( 1024 ) - 2 )\n#define MIN_PKCSIZE_ECC\t\t\t( bitsToBytes( 256 ) - 2 )\n\n/* When we read a public key, a value that's too short to be even vaguely\n   sensible is reported as CRYPT_ERROR_BADDATA, but if it's at least \n   vaguely sensible but too short to be secure it's reported as \n   CRYPT_ERROR_NOSECURE.  The following value defines the cutoff point \n   between \"obviously invalid\" and \"theoretically valid but not secure\",\n   so that 0...MIN_PKCSIZE_THRESHOLD - 1 is rejected with \n   CRYPT_ERROR_BADDATA, MIN_PKCSIZE_THRESHOLD... MIN_PKCSIZE - 1 is rejected \n   with CRYPT_ERROR_NOSECURE, and MIN_PKCSIZE...CRYPT_MAX_PKCSIZE is \n   accepted */\n\n#define MIN_PKCSIZE_THRESHOLD\t( bitsToBytes( 504 ) )\n#define MIN_PKCSIZE_ECC_THRESHOLD ( bitsToBytes( 120 ) )\n\n/* ECC points present special problems of their own since they're encoded\n   by stuffing them into byte strings with a type indicator at the start \n   which leads to a length that bears no relation to the actual key size */\n\n#define MIN_PKCSIZE_ECCPOINT\t( 1 + ( MIN_PKCSIZE_ECC * 2 ) )\n#define MIN_PKCSIZE_ECCPOINT_THRESHOLD \\\n\t\t\t\t\t\t\t\t( 1 + ( MIN_PKCSIZE_ECC_THRESHOLD * 2 ) )\n#define MAX_PKCSIZE_ECCPOINT\t( 1 + ( CRYPT_MAX_PKCSIZE_ECC * 2 ) )\n\n/* The minimum hash/MAC size */\n\n#define MIN_HASHSIZE\t\t\t16\n\n/* The size of the largest public-key wrapped value, corresponding to an\n   ASN.1-encoded Elgamal-encrypted key.  If we're not using Elgamal it's\n   the same as CRYPT_MAX_PKCSIZE */\n\n#ifdef USE_ELGAMAL\n  #define MAX_PKCENCRYPTED_SIZE\t( 16 + ( CRYPT_MAX_PKCSIZE * 2 ) )\n#else\n  #define MAX_PKCENCRYPTED_SIZE\tCRYPT_MAX_PKCSIZE\n#endif /* USE_ELGAMAL */\n\n/* The maximum public-key object size.  This is used to allocate temporary\n   buffers when working with signatures and PKC-encrypted keys.  The size\n   estimate is somewhat crude and involves a fair safety margin, it usually\n   contains a single PKC object (signature or encrypted key) along with\n   algorithm and key ID information */\n\n#define MAX_PKC_OBJECTSIZE\t\t( CRYPT_MAX_PKCSIZE * 2 )\n\n/* The minimum size of an encoded signature or exported key object.  This is\n   used by the pointer-check macros (for the OSes that support this) to\n   check that the pointers to objects that are passed to functions point to\n   the minimal amount of valid memory required for an object, and also to\n   zero the buffer for the object to ensure that the caller gets invalid\n   data if the function fails */\n\n#define MIN_CRYPT_OBJECTSIZE\t64\n\n/* The maximum number of iterations that we allow for an iterated key setup\n   such as a hashed password.  This is used to prevent DoS attacks from data\n   containing excessive iteration counts */\n\n#define MAX_KEYSETUP_ITERATIONS\tmin( INT_MAX - 256, 50000L )\n\n/* PGP's S2K uses a bizarre processing-complexity specifier that specifies,\n   in a very roundabout manner, the number of bytes hashed rather than the \n   iteration count.  In addition a number of PGP implementations specify\n   ridiculous levels of hashing that make them more akin to a DoS attack \n   than any legitimate security measure.  In theory we could recalculate the \n   above define for an assumption of an 8-byte hash salt and and 8-byte \n   password to get a value of ( ( MAX_KEYSETUP_ITERATIONS * 16 ) / 64 ),\n   with the '/ 64' term being present because what's specified is the value \n   without an additional * 64 multiplier that's added by the S2K mechanism \n   code, so we divide by 64 to account for this later scaling.  \n   \n   However in 2011 GPG raised its default hash specifier count from 64K to \n   over 2M (while still defaulting to the 15-year-old CAST5 for its block \n   cipher, so it may use an obsolete 64-bit crypto algorithm but at least it \n   iterates the password hashing enough to perform a DoS on anyone with an \n   older machine) and some configurations go even further and set it at \n   3,407,872.  Then at some point in 2017 the Kleopatra GPG front-end raised\n   the stakes even further with a value of 3,932,160, and then some time \n   early in 2018 to 6,815,744 (all of these values appear to be arbitrary, \n   with or without the * 64 multiplier they have no obvious significance).\n\n   In addition to GPG's constantly-changing behaviour, PGP Desktop 9 \n   (apparently) in its default config uses values up to 4M, and there's a \n   mutant GPG build used with loop-AES that uses 8M setup iterations for PGP \n   private keys.  Why this is used and why it writes PGP keys with this \n   setting is uncertain.\n\t\t   \n   It's unclear at which point we should draw the line here, on the one hand \n   we want to be able to handle the ridiculous iteration counts set by some \n   applications but we also want some protection against DoS attacks due to \n   such ridiculously high iteration counts.  In particular using any kind of \n   anti-DoS check would prevent us from reading newer GPG or GPG-derived \n   keyrings, so instead of trying to use a sane value as the upper limit we \n   hardcode in the smallest value that'll still allow us to read these \n   keyrings, 8MB of hashed data.\n\n   Unfortunately the ludicrous-speed limit on iterations is far higher\n   than 8M, the limit is defined in the RFC with the formula:\n   \n\tcount = (16 + (c & 15)) << ((c >> 4) + EXPBIAS);\n\n   where c is an 8-bit value and EXPBIAS is 6.  This then evaluates to:\n\n\t= (16 + (0x0F)) << ((0xF0 >> 4) + EXPBIAS);\n\t= 31 << (15 + EXPBIAS);\n\t= 31 << 21\n\t= 65,011,712\n\n   So in the future we could potentially see counts close to 2^25.  It's\n   because of this that we try and limit the count to a lower, safer \n   value */\n\n#define MAX_KEYSETUP_HASHSPECIFIER\tmin( INT_MAX - 256, ( 8388608L / 64 ) )\n\n/* The HMAC input and output padding values.  These are defined here rather\n   than in context.h because they're needed by some PRF mechanisms that \n   synthesise HMAC operations from low-level hash operations */\n\n#define HMAC_IPAD\t\t\t\t0x36\n#define HMAC_OPAD\t\t\t\t0x5C\n\n/* The default encryption algorithm, representing an always-available\n   algorithm type.  This is used when we just need to generically encrypt \n   something for internal use without caring about its external \n   representation.\n   \n   Alongside the algorithm type define, we also need to define symbolic\n   values that indicate which option is in use, since the preprocessor\n   can't evaluate the enums used to identify the algorithm type */\n\n#if defined( USE_AES )\n  #define DEFAULT_CRYPT_ALGO\tCRYPT_ALGO_AES\n  #define DEFAULT_ALGO_AES\n#elif defined( USE_3DES )\n  #define DEFAULT_CRYPT_ALGO\tCRYPT_ALGO_3DES\n  #define DEFAULT_ALGO_3DES\n#else\n  #error Either 3DES or AES must be enabled as the default encryption algorithm\n#endif /* Default encryption algorithm */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Size Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The maximum length that can be safely handled using an integer.  We don't\n   quite allow the maximum possible length since most data/message formats\n   impose some extra overhead themselves.\n   \n   In addition to the maximum-possible length we also define a shorter\n   length defined as a generally sensible upper bound for values that \n   shouldn't require arbitrary-length data quantities */\n\n#ifdef SYSTEM_16BIT\n  #define MAX_INTLENGTH_DELTA\t8192\n#else\n  #define MAX_INTLENGTH_DELTA\t1048576\n#endif /* 16- vs. 32/64-bit systems */\n#define MAX_INTLENGTH\t\t\t( INT_MAX - MAX_INTLENGTH_DELTA )\n#define MAX_INTLENGTH_SHORT\t\t16384\n\n/* The minimum size of a certificate.  This is used by the pointer-check\n   macros (for the OSes that support this) to check that the pointers being\n   passed to these functions point to the minimal amount of valid memory\n   required for an object */\n\n#define MIN_CERTSIZE\t\t\t256\n\n/* The maximum size of an object attribute.  In theory this can be any size,\n   but in practice we limit it to the following maximum to stop people\n   creating things like certs containing MPEGs of themselves playing with\n   their cat */\n\n#define MAX_ATTRIBUTE_SIZE\t\t1024\n\n/* Some objects contain internal buffers used to process data whose size can \n   be specified by the user, the following is the minimum and maximum size \n   allowed for these buffers.  We don't use MAX_INTLENGTH for this both \n   because it's a peculiarly high value (using all addressable memory as a \n   buffer is a bit odd) and because using a fraction of the full INT_MAX\n   range makes it safe to perform range-based comparisons, 'value1 + \n   value2 < value3', without the risk of integer overflow */\n\n#define MIN_BUFFER_SIZE\t\t\t8192\n#define MAX_BUFFER_SIZE\t\t\t( INT_MAX / 8 )\n\n/* The minimum allowed length for (typically human-readable) object names \n   (keysets, devices, users, etc).  In theory this could be a single \n   character, but by default we make it 2 chars to make things more \n   resistant to off-by-one errors in lengths, particularly since it applies \n   to external objects outside cryptlib's control.  Alongside this we also \n   define a minimum length for generic binary IDs */\n\n#ifdef UNICODE_CHARS\n  #define MIN_NAME_LENGTH\t\t( 2 * sizeof( wchar_t ) )\n#else\n  #define MIN_NAME_LENGTH\t\t2\n#endif /* Unicode vs. ASCII environments */\n#define MIN_ID_LENGTH\t\t\t2\n\n/* The minimum and maximum size of various Internet-related values, used for\n   range checking */\n\n#define MIN_DNS_SIZE\t\t\t4\t\t\t/* x.com */\n#define MAX_DNS_SIZE\t\t\t255\t\t\t/* Max hostname size */\n#define MIN_RFC822_SIZE\t\t\t7\t\t\t/* x@yy.zz */\n#define MAX_RFC822_SIZE\t\t\t255\n#define MIN_URL_SIZE\t\t\t12\t\t\t/* http://x.com */\n#define MAX_URL_SIZE\t\t\tMAX_DNS_SIZE\n\n/* Some object types interact with exteral services that can return detailed\n   error messages when problems occur, the following is the maximum length\n   error string that we store.  Anything beyond this size is truncated */\n\n#define MAX_ERRMSG_SIZE\t\t\t512\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Constants\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Various time values:\n\n\tMIN_TIME_VALUE: The minimum time value that's regarded as being a valid \n\t\ttime.  We have to allow dates slightly before the current time \n\t\tbecause of things like backdated certificate revocations, as a rule \n\t\tof thumb we allow a date up to two years in the past.\n\t\n\tMIN_STORED_TIME_VALUE: A somewhat more relaxed minimum time value used \n\t\twhen reading stored data like private keys, which can contain \n\t\tassociated certificates that have been hanging around for years.\n\n\tMAX_TIME_VALUE: The maximum time value that we can safely use while\n\t\tavoiding the Y2038 problem.\n\n\tCURRENT_TIME_VALUE: An approximation of the current time with the \n\t\tconstraint that it's not after the current date.  Unfortunately we \n\t\tcan't use any preprocessor macros for this since __DATE__ and \n\t\t__TIME__ are text strings rather than timestamps, so we have to\n\t\tbuild it the hard way from the __DATE__ value, which ANSI defines as \n\t\t\"Mmm dd yyyy\" with a space inserted if dd is less than 10.  The year \n\t\tis relatively straightforward, the month is more complicated.  We \n\t\tperform a match on the third letter of the month name, which has the \n\t\tleast collisions, and then disambiguate between Jan/Jun and Mar/Apr \n\t\tto select the month days from a cumulative count of 31, 28, 31, 30, \n\t\t31, 30, 31, 31, 30, 31, 30, 31, which is 0, 31, 59, 90, 120, 151, \n\t\t181, 212, 243, 273, 304, 334, (365).  We ignore leap years since \n\t\tit's only a single day and all we need is an approximate date, and \n\t\twe backate the calculated date by one month to deal with leap-year\n\t\trounding errors.\n\t\t\n\t\tNote that some compilers aren't tough enough to evaluate this at\n\t\tcompile time so we whitelist the compilers that can handle it and\n\t\tfor all others use an approximation.  Also, it's typically done by \n\t\tthe compiler rather than the preprocessor, so having it in the code \n\t\tworks but using it in a preprocessor expression, \n\t\t\"#if CURRENT_TIME_VALUE < xxx\", doesn't */\n\n#define DATE_YEAR \\\n\t\t( ( __DATE__[ 7 ] == '?' ? ( 2019 - 1970 ) : \\\n\t\t\t( ( ( __DATE__[  7 ] - '0' ) * 1000 ) + \\\n\t\t\t  ( ( __DATE__[  8 ] - '0' ) * 100 ) + \\\n\t\t\t  ( ( __DATE__[  9 ] - '0' ) * 10 ) + \\\n\t\t\t\t( __DATE__[ 10 ] - '0' ) ) - 1970 ) * 365 )\n\n#define DATE_MONTH \\\n\t\t( __DATE__[ 2 ] == \"Jan\"[ 2 ] ? \\\n\t\t  \t( __DATE__[ 1 ] == \"Jan\"[ 1 ] ? 0 : 151 ) : \\\n\t\t  __DATE__[ 2 ] == \"Feb\"[ 2 ] ? 31 : \\\n\t\t  __DATE__[ 2 ] == \"Mar\"[ 2 ] ? \\\n\t\t  \t( __DATE__[ 1 ] == \"Mar\"[ 1 ] ? 59 : 90 ) : \\\n\t\t  __DATE__[ 2 ] == \"May\"[ 2 ] ? 120 : \\\n\t\t  __DATE__[ 2 ] == \"Jul\"[ 2 ] ? 181 : \\\n\t\t  __DATE__[ 2 ] == \"Aug\"[ 2 ] ? 212 : \\\n\t\t  __DATE__[ 2 ] == \"Sep\"[ 2 ] ? 243 : \\\n\t\t  __DATE__[ 2 ] == \"Oct\"[ 2 ] ? 273 : \\\n\t\t  __DATE__[ 2 ] == \"Nov\"[ 2 ] ? 304 : \\\n\t\t  __DATE__[ 2 ] == \"Dec\"[ 2 ] ? 334 : 0 )\n\n#define DATE_DAY \\\n\t\t( __DATE__[ 4 ] == '?' ? 0 : \\\n\t\t  ( ( __DATE__[ 4 ] == ' ' ) ? \\\n\t\t  \t( __DATE__[ 5 ] - '0' ) : \\\n\t\t  \t( ( ( __DATE__[ 4 ] - '0' ) * 10 ) + __DATE__[ 5 ] - '0' ) ) )\n\n#define YEARS_TO_SECONDS( years ) ( ( years ) * 365 * 86400L )\n\n#define MIN_TIME_VALUE\t\t\t( CURRENT_TIME_VALUE - YEARS_TO_SECONDS( 2 ) )\n#define MIN_STORED_TIME_VALUE\t( YEARS_TO_SECONDS( 1995 - 1970 ) )\n#define MAX_TIME_VALUE\t\t\t( YEARS_TO_SECONDS( 2036 - 1970 ) )\n\n#if ( defined( __clang__ ) && ( __clang_major__ > 5 ) ) || \\\n\t( defined( __GNUC__ ) && ( __GNUC__ > 6 ) )\n  #define CURRENT_TIME_VALUE\t( ( DATE_YEAR + DATE_MONTH + DATE_DAY - 30 ) * 86400 )\n#else\n  #define CURRENT_TIME_VALUE\t( YEARS_TO_SECONDS( 2019 - 1970 ) )\n#endif /* Compilers that aren't tough enough for the above */\n\n/* The minimum and maximum network port numbers.  Note that we allow ports \n   down to 21 (= FTP) rather than the more obvious 22 (= SSH) provided by \n   cryptlib sessions because the URL-handling code is also used for general-\n   purpose URI parsing for which the lowest-numbered one that we'd normally \n   run into is FTP.  We set the upper bound at the end of the non-ephemeral \n   port range, 49152-65535 is for ephemeral ports that are only valid for \n   the duration of a TCP session */\n\n#define MIN_PORT_NUMBER\t\t\t21\n#define MAX_PORT_NUMBER\t\t\t49151L\n\n/* The maximum certificate compliance level */\n\n#if defined( USE_CERTLEVEL_PKIX_FULL )\n  #define MAX_COMPLIANCE_LEVEL\tCRYPT_COMPLIANCELEVEL_PKIX_FULL\n#elif defined( USE_CERTLEVEL_PKIX_PARTIAL )\n  #define MAX_COMPLIANCE_LEVEL\tCRYPT_COMPLIANCELEVEL_PKIX_PARTIAL\n#else\n  #define MAX_COMPLIANCE_LEVEL\tCRYPT_COMPLIANCELEVEL_STANDARD\n#endif /* Maximum compliance level */\n\n/* The maximum network read/write timeout, in seconds */\n\n#define MAX_NETWORK_TIMEOUT\t\t300\n\n/* Generic error return code/invalid value code */\n\n#define CRYPT_ERROR\t\t\t\t-1\n\n/* Sometimes compilers get confused about whether a variable has been \n   initialised or not and report a used-before-initialised error when there\n   isn't one.  This happens most frequently when the variable is initialised\n   as part of a conditional expression where the developer knows the control\n   flow will result in an initialisation but the compiler doesn't.  To get\n   around this we perform a dummy initialisation of the variable with a \n   symbolic value to get rid of the false positive */\n\n#define DUMMY_INIT\t\t\t\t= 0\n#define DUMMY_INIT_PTR\t\t\t= NULL\n#define DUMMY_INIT_STRUCT\t\t= { 0 }\n\n/* A special return code to indicate that everything went OK but there's\n   some special action to perform.  This is generally used when a lower-level\n   routine wants to return a CRYPT_OK with some condition attached, typically\n   that the calling routine not update state information since it's already\n   been done by the returning routine or because the returning routine has\n   more work to do on a later call.  The parentheses are to catch potential\n   erroneous use in an expression */\n\n#define OK_SPECIAL\t\t\t\t( -123 )\n\n/* When parameters get passed in messages, their mapping to parameters passed\n   to the calling function gets lost.  The following error codes are used to\n   denote errors in message parameters that are mapped to function parameter\n   error codes by the caller.  For a message call:\n\n\tkrnlSendMessage( object, {args}, MESSAGE_TYPE, value );\n\n   we have the following possible error codes.  The parentheses are to catch\n   potential erroneous use in an expression */\n\n#define CRYPT_ARGERROR_OBJECT\t( -100 )\t/* Error in object being sent msg.*/\n#define CRYPT_ARGERROR_VALUE\t( -101 )\t/* Error in message value */\n#define CRYPT_ARGERROR_STR1\t\t( -102 )\t/* Error in first string arg */\n#define CRYPT_ARGERROR_STR2\t\t( -103 )\t/* Error in second string arg */\n#define CRYPT_ARGERROR_NUM1\t\t( -104 )\t/* Error in first numeric arg */\n#define CRYPT_ARGERROR_NUM2\t\t( -105 )\t/* Error in second numeric arg */\n\n#define cryptArgError( status )\t\\\n\t\t( ( status ) >= CRYPT_ARGERROR_NUM2 && ( status ) <= CRYPT_ARGERROR_OBJECT )\n#define cryptStandardError( status ) \\\n\t\t( ( status ) >= CRYPT_ENVELOPE_RESOURCE && ( status ) <= CRYPT_OK )\n\n/* Network I/O is government by all sorts of timeouts.  The following are \n   the default timeout values used for network I/O, unless overridden by the\n   user */\n\n#define\tNET_TIMEOUT_CONNECT\t\t30\n#define NET_TIMEOUT_READ\t\t15\n#define NET_TIMEOUT_WRITE\t\t5\n\n/* The data formats for reading/writing public keys */\n\ntypedef enum {\n\tKEYFORMAT_NONE,\t\t/* No key format */\n\tKEYFORMAT_CERT,\t\t/* X.509 SubjectPublicKeyInfo */\n\tKEYFORMAT_SSH,\t\t/* SSHv2 public key */\n\tKEYFORMAT_SSL,\t\t/* SSL public key */\n\tKEYFORMAT_SSL_EXT,\t/* TLS extended public key */\n\tKEYFORMAT_PGP,\t\t/* PGP public key */\n\tKEYFORMAT_PRIVATE,\t/* Private key */\n\tKEYFORMAT_PRIVATE_OLD,\t/* Older format for backwards-compatibility */\n\tKEYFORMAT_LAST\t\t/* Last possible key format type */\n\t} KEYFORMAT_TYPE;\n\n/* The different types of actions that can be signalled to the management\n   function for each object class.  This instructs the management function\n   to initialise or shut down any object-class-specific information that it\n   may maintain */\n\ntypedef enum {\n\tMANAGEMENT_ACTION_NONE,\t\t\t\t/* No management action */\n\tMANAGEMENT_ACTION_PRE_INIT,\t\t\t/* Pre-initialisation */\n\tMANAGEMENT_ACTION_INIT,\t\t\t\t/* Initialisation */\n\tMANAGEMENT_ACTION_PRE_SHUTDOWN,\t\t/* Pre-shutdown */\n\tMANAGEMENT_ACTION_SHUTDOWN,\t\t\t/* Shutdown */\n\tMANAGEMENT_ACTION_LAST\t\t\t\t/* Last possible management action */\n\t} MANAGEMENT_ACTION_TYPE;\n\n/* Certificate key usage types.  SIGN is for data signing and CA is for \n   certificate signing.  we don't include CRYPT_KEYUSAGE_DATAENCIPHERMENT in \n   KEYUSAGE_CRYPT since this is more or less never what's actually meant */\n\n#define KEYUSAGE_SIGN\t\t\t( CRYPT_KEYUSAGE_DIGITALSIGNATURE | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_NONREPUDIATION )\n#define KEYUSAGE_CA\t\t\t\t( CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_CRLSIGN )\n#define KEYUSAGE_CRYPT\t\t\t( CRYPT_KEYUSAGE_KEYENCIPHERMENT )\n#define KEYUSAGE_KEYAGREEMENT\t( CRYPT_KEYUSAGE_KEYAGREEMENT | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_ENCIPHERONLY | \\\n\t\t\t\t\t\t\t\t  CRYPT_KEYUSAGE_DECIPHERONLY )\n\n#endif /* _CONSTS_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/debug.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Debug Header File \t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _DEBUG_DEFINED\n\n#define _DEBUG_DEFINED\n\n/* There are some diagnostics that we may want to enable even in non-debug\n   mode, which can be done by defining DEBUG_DIAGNOSTIC_ENABLE.  In debug\n   mode, this is enabled by default */\n\n#if !defined( NDEBUG )\n  #define DEBUG_DIAGNOSTIC_ENABLE\n#endif /* !NDEBUG */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tassert() Handling\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Older WinCE environments don't support assert() because there's no \n   console and no other support for it in the runtime (the documentation\n   claims there's at least an _ASSERT/_ASSERTE available, but this isn't \n   present in many systems such as PocketPC), so we use it if it's available \n   and otherwise kludge it using NKDbgPrintfW().\n\n   Note that (in theory) the version check isn't reliable since we should be \n   checking for the development environment version rather than the target \n   OS version, however in practice compiler/SDK version == OS version unless \n   you seriously enjoy pain, and in any case it's not really possible to \n   differentiate between eVC++ 3.0 and 4.0 - the SHx, MIPS, and ARM compilers \n   at least report 120{1|2} for 3.0 and 1200 for 3.0, but the x86 compiler \n   reports 1200 for both 3.0 and 4.0 even though it's a different build, \n   0.8168 vs. 0.8807 */\n\n#if defined( __WINCE__ ) && _WIN32_WCE < 400\n  #if 0\t/* Too nonportable, see comment above */\n\t#ifndef _ASSERTE\n\t  #ifdef NDEBUG\n\t\t#define _ASSERTE( x )\n\t  #else\n\t\t#define _ASSERTE( expr ) \\\n\t\t\t\t( void )( ( expr ) || ( NKDbgPrintfW( #expr ) ) )\n\t  #endif /* Debug vs. non-debug builds */\n\t#endif /* _ASSERTE available */\n\t#define assert( expr )\t_ASSERTE( expr )\n  #else\n\t#ifdef NDEBUG\n\t  #define assert( x )\n\t#else\n\t  #define assert( x ) \\\n\t\t\t  DEBUGMSG( !( x ), ( TEXT( \"Assert failed in %s line %d: %s\" ), TEXT( __FILE__ ), __LINE__, TEXT( #x ) ) )\n\t#endif /* Debug vs. non-debug builds */\n  #endif /* 0 */\n#else\n  #if defined( __MVS__ )\n\t/* MVS implements assert() using stdio functions but forgets to include\n\t   stdio.h when doing so, so we need to explicitly include it here */\n\t#include <stdio.h>\n  #endif /* __MVS__ */\n  #include <assert.h>\n#endif /* Systems without assert() */\n\n/* Assertions can't be used to detect post-preprocessing compile-time \n   problems, typically using expressions involving sizeof().  Newer versions\n   of the C standard added static_assert() to deal with this, since only\n   recent compilers support this we have to enable it as required, in some\n   cases using preprocessor kludges.\n   \n   In addition to the standard static_assert() we also define an alternative,\n   static_assert_opt(), for cases where the compiler isn't tough enough to\n   handle the standard static_assert().  This occurs with expressions like\n   \"foo\"[ 1 ] == 'o' */\n\n#define ASSERT_CONCAT_( a, b )\ta##b\n#define ASSERT_CONCAT( a, b )\tASSERT_CONCAT_( a, b )\n#ifndef __COUNTER__\n  /* We need a unique name for each static assertion, ideally we'd like to \n\t use a unique value for this but if it's not available (it's supported \n\t in the major platforms VC++ and gcc) then we use the next-best thing */\n  #define __COUNTER__\t\t\t__LINE__\n#endif /* __COUNTER__ */\n#if defined( _MSC_VER ) \n  #if VC_GE_2010( _MSC_VER )\t\n\t/* Built into VC++ 2010 and up.  This is supposedly partially supported \n\t   in VS 2008 as '_STATIC_ASSERT( expr )' but the support isn't complete \n\t   enough to rely on it so we only enable it for VS 2010 and up, for \n\t   which it's definitely present */\n  #else\n\t#define static_assert( expr, string ) \\\n\t\t\t{ enum { ASSERT_CONCAT( static_assert_, __COUNTER__ ) = 1 / ( !!( expr ) ) }; }\n  #endif /* VC++ versions */\n  #define static_assert_opt( expr, string ) \\\n\t\t  assert( expr )\n#elif defined( __GNUC__ ) && \\\n\t  ( ( __GNUC__ == 4 && __GNUC_MINOR__ >= 7 && defined( static_assert ) ) || \\\n\t\t( __GNUC__ >= 5 ) ) \n  /* Supposedly built into gcc 4.5 and above (as usual for new gcc features\n\t this isn't really documented, but web comments indicate that it should \n\t be present in 4.5 and above), however trying this with 4.5 produces\n\t assorted errors indicating that it isn't actually supported.  The GNU\n\t standards-support docs indicate its presence in an even earlier version,\n\t 4.3, which doesn't have it either.  It is present in the <assert.h> for \n\t gcc 4.9 and has an effect there, and sometimes works in 4.7 and 4.8 as \n\t well.  To protect ourselves, we assume that it's present in 4.7 and \n\t above but also check for static_assert being defined (which maps the\n\t C11 keyword _Static_assert to the C++-style static_assert()), which \n\t indicates that it really is present.  For 5.x and above we just assume \n\t that it's present.\n\t \n\t gcc 8.x started producing \"ISO C90 forbids mixed declarations and code\"\n\t warnings when static_assert() is used and -Wdeclaration-after-statement \n\t is enabled.  This occurs because, technically, static_assert() is a \n\t declaration and therefore should only be used in places where \n\t declarations are allowed.  No compiler actually seems to care about \n\t this, and gcc only warns when this specific warning is enabled, so we\n\t leave it for now */\n  #define static_assert_opt( expr, string ) \\\n\t\t  assert( expr )\n#elif defined( __clang__ )\n  /* Supported in LLVM/clang, however it's present using the C11 \n     _Static_assert name rather than the C++11 static_assert one.  Some \n\t assert.h's will map static_assert to _Static_assert, but since this \n\t depends on which assert.h is used we optionally do it ourselves here */\n  #ifndef static_assert\n\t#define static_assert\t_Static_assert\n  #endif /* static_assert */\n  #define static_assert_opt( expr, string ) \\\n\t\t  assert( expr )\n#elif ( defined( __xlc__ ) || defined( __IBMC__ ) ) && defined( _ALL_SOURCE )\n  /* Enabled by default in newer compilers, indicated by _ALL_SOURCE being \n     defined */\n  #define static_assert_opt( expr, string ) \\\n\t\t  assert( expr )\n#else\n  #define static_assert( expr, string ) \\\n\t\t  { enum { ASSERT_CONCAT( static_assert_, __COUNTER__ ) = 1 / ( !!( expr ) ) }; }\n  #define static_assert_opt( expr, string ) \\\n\t\t  assert( expr )\n#endif /* VC++ vs. other compilers */\n\n/* Force an assertion failure via assert( DEBUG_WARN ) */\n\n#define DEBUG_WARN\t\t\t\t0\n\n/* Under VC++ 6 assert() can randomly stop working so that only the abort() \n   portion still functions, making it impossible to find out what went wrong. \n   To deal with this we redefine the assert() macro to call our own \n   assertion handler */\n\n#if defined( __WIN32__ ) && !defined( NDEBUG ) && VC_LE_VC6( _MSC_VER )\n\nvoid vc6assert( const char *exprString, const char *fileName, \n\t\t\t\tconst int lineNo );\n\n#undef assert\n#define assert( expr ) \\\n\t\t( void )( ( expr ) || ( vc6assert( #expr, __FILE__, __LINE__ ), 0 ) )\n\n#endif /* VC++ 6.0 Debug */\n\n/* On EBCDIC systems assert() is problematic because we use ASCII strings \n   internally, which when displayed with assert() produces garbage.\n   To deal with this we redefine the assert() macro to use the built-in\n   diagnostic debugging routines.  Note the use of the nonstandard string-\n   type specified 'e' to denote an EBCDIC string, since __func__ is a \n   compiler intrinsic rather than a preprocessor symbol so it always\n   present as EBCDIC */\n\n#if ( defined( __MVS__ ) || defined( __VMCMS__ ) || \\\n\t  defined( __ILEC400__ ) ) && !defined( NDEBUG ) \n\n#undef assert\n#define assert( expr ) \\\n\t\t( void )( ( expr ) || ( DEBUG_PRINT(( \"%s:%e:%d:'%s'.\\n\", __FILE__, __func__, __LINE__, #expr )), 0 ) )\n\n#endif /* EBCDIC systems debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDebugging Diagnostic Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Debugging printf() that sends its output to the debug output */\n\n#if defined( NDEBUG ) || !defined( USE_ERRMSGS ) || \\\n\t( defined( CONFIG_FUZZ ) && !defined( __WINDOWS__ ) )\n  /* Debugging diagnostics are disabled for release builds, for builds\n     without verbose error messages enabled, and for fuzzing builds on\n\t the test (rather than fault-diagnose) system, which don't do anything \n\t with output and for which lots of spew just slows things down \n\t unnecessarily */\n  #define DEBUG_PUTS( x )\n  #define DEBUG_PRINT( x )\n  #define DEBUG_PRINT_COND( x, y )\n#else\n  int debugPrintf( const char *format, ... );\n\n  #define DEBUG_PUTS( x )\t\t\tdebugPrintf( \"%s\\n\", x )\n  #define DEBUG_PRINT( x )\t\t\tdebugPrintf x\n  #define DEBUG_PRINT_COND( c, x )\tif( c ) debugPrintf x\n#endif /* !DEBUG_PRINT */\n\n/* Sometimes we need to add additional debugging code that's needed only in \n   the debug version, the following macro allows debug-only operations to be \n   inserted */\n\n#if defined( NDEBUG )\n  #define DEBUG_OP( x )\n#else\n  #define DEBUG_OP( x )\t\t\tx\n#endif /* Debug vs. non-debug builds */\n\n/* Output an I-am-here to the debugging outout (see above), useful when \n   tracing errors in code without debug symbols available.  Because \n   __func__ is a predefined string literal rather than a predefined \n   macro/preprocessor symbol, it's a native-charset string on non-ASCII \n   systems so we have to use a custom format specifier to make sure that \n   it's displayed properly */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __ILEC400__ )\n  #define NATIVE_STR_FORMAT\t\t\"%e\"\n#else\n  #define NATIVE_STR_FORMAT\t\t\"%s\"\n#endif /* ASCII vs. EBCDIC strings */\n\n#define DEBUG_ENTER()\tDEBUG_PRINT(( \"Enter %s:\" NATIVE_STR_FORMAT \":%d.\\n\", __FILE__, __func__, __LINE__ ))\n#define DEBUG_IN()\t\tDEBUG_PRINT(( \"In    %s:\" NATIVE_STR_FORMAT \":%d.\\n\", __FILE__, __func__, __LINE__ ))\n#define DEBUG_EXIT()\tDEBUG_PRINT(( \"Exit  %s:\" NATIVE_STR_FORMAT \":%d, status %d.\\n\", __FILE__, __func__, __LINE__, status ))\n#define DEBUG_EXIT_NONE()\t\\\n\t\t\t\t\t\tDEBUG_PRINT(( \"Exit  %s:\" NATIVE_STR_FORMAT \":%d.\\n\", __FILE__, __func__, __LINE__ ))\n\n#define DEBUG_DIAG( x ) \\\n\t\t\t\t\t\tDEBUG_PRINT(( \"%s:\" NATIVE_STR_FORMAT \":%d: \", __FILE__, __func__, __LINE__ )); \\\n\t\t\t\t\t\tDEBUG_PRINT( x ); \\\n\t\t\t\t\t\tDEBUG_PRINT(( \".\\n\" ))\n\n/* Alongside the standard DEBUG_DIAG() there's also a version that relies on \n   the existence of extended error message information, which enables both \n   functions that print string-form versions of numeric values and a function \n   that returns the contents of an ERROR_INFO structure as a text string.  If\n   these aren't available then the DEBUG_DIAG_ERRMSG() variant of \n   DEBUG_DIAG() is turned into a no-op */\n\n#ifdef USE_ERRMSGS\n  #define DEBUG_DIAG_ERRMSG\t\t\tDEBUG_DIAG\n#else\n  #define DEBUG_DIAG_ERRMSG( displayString )\n#endif /* USE_ERRMSGS */\n\n/* Dump a PDU to disk or screen.  The debug functions do the following:\n\n\tDEBUG_DUMP_FILE: Writes a block of memory to a file in $TMP, suffix \n\t\t\".der\".\n\n\tDEBUG_DUMP_FILE_OPT: As DEBUG_DUMP_FILE, but only tries to dump the \n\t\tcontents if the length is non-zero.  This can happen if we get a\n\t\tzero-length from a client or server, for example what's being\n\t\tcommunicated is an error status and there's no content such as\n\t\tas a certificate to dump.\n\n\tDEBUG_DUMP_CERT: Writes a certificate object to a file, details as for\n\t\tDEBUG_DUMP_FILE().\n\n\tDEBUG_DUMP_HEX: Creates a hex + text dump of a block of memory along \n\t\twith a length and checksum of the entire buffer, prepended with a \n\t\tsupplied text string.\n\n\tDEBUG_DUMP_DATA: Creates a hex + text dump of a block of memory, to be \n\t\tused in conjunction with DEBUG_PRINT() for free-format text.\n\n\tDEBUG_DUMP_STREAM: As DEBUG_DUMP_DATA() but taking its input from a \n\t\tstream.\n\n\tDEBUG_GET_STREAMBYTE: Support function for DEBUG_DUMP_STREAM() that \n\t\tpulls data bytes, typically containing type information, out of a \n\t\tstream for display */\n\n#if defined( NDEBUG ) && !defined( DEBUG_DIAGNOSTIC_ENABLE )\n  #define DEBUG_DUMP_FILE( name, data, length )\n  #define DEBUG_DUMP_FILE_OPT( name, data, length )\n  #define DEBUG_DUMP_CERT( name, cert )\n  #define DEBUG_DUMP_HEX( dumpPrefix, dumpBuf, dumpLen )\n  #define DEBUG_DUMP_DATA( dumpBuf, dumpLen )\n  #define DEBUG_DUMP_STREAM( stream, position, length )\n  #define DEBUG_DUMP_STACKTRACE()\n  #define DEBUG_GET_STREAMBYTE( stream, position )\t\t0\n#else\n  #define DEBUG_DUMP_FILE\tdebugDumpFile\n  #define DEBUG_DUMP_FILE_OPT( name, data, length ) \\\n\t\t\tif( ( length ) != 0 ) \\\n\t\t\t\tdebugDumpFile( ( name ), ( data ), ( length ) )\n  #define DEBUG_DUMP_CERT\tdebugDumpFileCert\n  #define DEBUG_DUMP_HEX\tdebugDumpHex\n  #define DEBUG_DUMP_DATA\tdebugDumpData\n  #define DEBUG_DUMP_STREAM\tdebugDumpStream\n  #if defined( __WIN32__ )\n\t#define DEBUG_DUMP_STACKTRACE\tdisplayBacktrace\n\tvoid displayBacktrace( void );\n  #elif defined( __UNIX__ ) && \\\n\t\t( defined( __APPLE__ ) || defined( __linux__ ) || defined( __sun ) )\n\t#define DEBUG_DUMP_STACKTRACE\tdisplayBacktrace\n\tvoid displayBacktrace( void );\n  #else\n\t#define DEBUG_DUMP_STACKTRACE()\n  #endif /* OS-specific stack trace display routines */\n  #define DEBUG_GET_STREAMBYTE debugGetStreamByte\n  STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n  void debugDumpFile( IN_STRING const char *fileName, \n\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void debugDumpFileCert( IN_STRING const char *fileName, \n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert );\n  STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n  void debugDumpHex( IN_STRING const char *prefixString, \n\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t IN_LENGTH_SHORT const int dataLength );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void debugDumpData( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void debugDumpStream( INOUT /*STREAM*/ void *streamPtr, \n\t\t\t\t\t\tIN_LENGTH const int position, \n\t\t\t\t\t\tIN_LENGTH const int length );\n  RETVAL_RANGE_NOERROR( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\n  int debugGetStreamByte( INOUT /*STREAM*/ void *streamPtr, \n\t\t\t\t\t\t  IN_LENGTH const int position );\n#endif /* Win32 debug */\n\n/* Support functions that may be needed by the general debug functions */\n\n#if !defined( NDEBUG ) && defined( USE_ERRMSGS ) && \\\n\tdefined( DEBUG_DIAGNOSTIC_ENABLE )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst char *getErrorInfoString( const ERROR_INFO *errorInfo );\n\n#endif /* Debug && USE_ERRMSGS && DEBUG_DIAGNOSTIC_ENABLE */\n\n/* When building the debug version of the code we can include text strings\n   describing the what's being processed when decoding tables are applied, \n   this makes it easier to track down problems */\n\n#ifndef NDEBUG\n  #define DESCRIPTION( text )\t\ttext,\n#else\n  #define DESCRIPTION( text )\n#endif /* Debug vs. non-debug builds */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMemory Debugging Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In order to debug memory usage, we can define CONFIG_DEBUG_MALLOC to dump\n   memory usage diagnostics to stdout (this would usually be done in the\n   makefile).  Without this, the debug malloc just becomes a standard malloc.\n   Note that crypt/osconfig.h contains its own debug-malloc() handling for\n   the OpenSSL-derived code enabled via USE_BN_DEBUG_MALLOC in osconfig.h,\n   and zlib also has its own allocation code (which isn't instrumented for\n   diagnostic purposes).  In addition the default mapping to malloc()/free()\n   may be overridden in os_spec.h/os_spec.c for embedded systems that don't\n   use standard malloc/free, so we only set up the mappings if clAlloc() \n   isn't already defined.\n\n   In addition in order to control on-demand allocation of buffers for\n   larger-than-normal data items, we can define CONFIG_NO_DYNALLOC to\n   disable this allocation.  This is useful in memory-constrained\n   environments where we can't afford to grab chunks of memory at random */\n\n#if defined( CONFIG_DEBUG_MALLOC )\n  #undef clAlloc\n  #undef clFree\n  #define clAlloc( string, size ) \\\n\t\t  clAllocFn( __FILE__, ( string ), __LINE__, ( size ) )\n  #define clFree( string, memblock ) \\\n\t\t  clFreeFn( __FILE__, ( string ), __LINE__, ( memblock ) )\n  void *clAllocFn( const char *fileName, const char *fnName,\n\t\t\t\t   const int lineNo, size_t size );\n  void clFreeFn( const char *fileName, const char *fnName,\n\t\t\t\t const int lineNo, void *memblock );\n#elif !defined( clAlloc )\n  #define clAlloc( string, size )\t\tmalloc( size )\n  #define clFree( string, memblock )\tfree( memblock )\n#endif /* !CONFIG_DEBUG_MALLOC */\n#ifdef CONFIG_NO_DYNALLOC\n  #define clDynAlloc( string, size )\tNULL\n#else\n  #define clDynAlloc( string, size )\tclAlloc( string, size )\n#endif /* CONFIG_NO_DYNALLOC */\n\n/* To provide fault-injection testing capabilities we can have memory \n   allocations fail after a given count, thus exercising a large number of \n   failure code paths that are normally never taken.  The following \n   configuration define enables this fault-malloc(), with the first call \n   setting the allocation call at which failure occurs */\n\n#ifdef CONFIG_FAULT_MALLOC\n  #undef clAlloc\n  #undef clFree\n  #define clAlloc( string, size ) \\\n\t\t  clFaultAllocFn( __FILE__, ( string ), __LINE__, ( size ) )\n  #define clFree( string, memblock )\tfree( memblock )\n  void *clFaultAllocFn( const char *fileName, const char *fnName, \n\t\t\t\t\t\tconst int lineNo, size_t size );\n  void clFaultAllocSetCount( const int number );\n\n  /* Some of the should-neven-fail functions like the kernel self-tests\n\t include assertions to ensure that any failure raises an immediate \n\t alert.  Since we're explicitly forcing a failure, we don't want to \n\t be alerted to these conditions so we no-op out the assert if we're\n\t doing memory fault injection */\n  #define assertNoFault( x )\n  #define ENSURES_NOFAULT( x )\tif( !( x ) ) return( CRYPT_ERROR_MEMORY )\n#else\n  #define assertNoFault\t\t\tassert\n  #define ENSURES_NOFAULT\t\tENSURES\n#endif /* CONFIG_FAULT_MALLOC */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTiming Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __WINDOWS__ ) || defined( __UNIX__ )\n\n/* High-resolution timing functionality, used to diagnose performance \n   issues */\n\n#if defined( _MSC_VER )\n  typedef __int64 HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%lld\"\n#elif defined( __GNUC__ )\n  typedef long long HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%lld\"\n#else\n  typedef unsigned long HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%ld\"\n  #if ( ( LONG_MAX >> 16 ) > 0xFFFF )\n\t#define HIRES_TIME_64BIT\n  #endif /* 64-bit HIRES_TIME */\n#endif /* 32/64-bit time values */\n\n/* Timing support functions.  Call as:\n\n\tHIRES_TIME timeVal;\n\n\ttimeVal = timeDiff( 0 );\n\tfunction_to_time();\n\tresult = ( int ) timeDiff( timeVal ); */\n\nHIRES_TIME debugTimeDiff( HIRES_TIME startTime );\nint debugTimeDisplay( HIRES_TIME time );\n\n#endif /* __WINDOWS__ || __UNIX__ */\n#endif /* _DEBUG_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/fault.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Fault-Injection Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _FAULT_DEFINED\n\n#define _FAULT_DEFINED\n\n/* In the debug build, the code includes additional functionality to inject \n   faults that verify that possible conditions such as invalid signatures \n   are correctly detected.  The following values are check types that\n   can be performed for the higher-level envelope and session objects */\n\n#ifndef NDEBUG\n\n#ifdef CONFIG_FAULTS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFault Types and Handling\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The various fault types that we can inject */\n\ntypedef enum {\n\tFAULT_NONE,\t\t\t\t\t/* No fault type */\n\n\t/* Generic faults */\n\tFAULT_BADSIG_HASH,\t\t\t/* Sig.check failure - bad hash/MAC */\n\tFAULT_BADSIG_DATA,\t\t\t/* Sig.check failure - bad data */\n\tFAULT_BADSIG_SIG,\t\t\t/* Sig.check failure - bad signature */\n\tFAULT_CORRUPT_ID,\t\t\t/* Corrupt ID/username */\n\tFAULT_CORRUPT_AUTHENTICATOR, /* Corrupt password/auth.token */\n\n\t/* Low-level mechanism faults.  These are distinct from the generic \n\t   faults like FAULT_BADSIG_HASH since that injects the fault at a \n\t   higher level like an envelope or session, while these inject the\n\t   fault at the crypto mechanism level */\n\tFAULT_MECH_CORRUPT_HASH,\t/* Corrupt hash value in signature */\n\tFAULT_MECH_CORRUPT_SIG,\t\t/* Corrupt signature value */\n\tFAULT_MECH_CORRUPT_KEY,\t\t/* Corrupt encrypted key */\n\tFAULT_MECH_CORRUPT_SALT,\t/* Corrupt salt in PRF */\n\tFAULT_MECH_CORRUPT_ITERATIONS,\t/* Corrupt PRF iteration count */\n\tFAULT_MECH_CORRUPT_PRFALGO,\t/* Corrupt PRF algorithm */\n\n\t/* Envelope faults */\n\tFAULT_ENVELOPE_CORRUPT_AUTHATTR, /* Corruption of auth.attributes */\n\n\t/* CMS protocol-specific faults */\n\tFAULT_ENVELOPE_CMS_CORRUPT_AUTH_DATA, /* Corruption of authData data */\n\tFAULT_ENVELOPE_CMS_CORRUPT_AUTH_MAC, /* Corruption of authData MAC */\n\n\t/* PGP protocol-specific faults */\n\tFAULT_ENVELOPE_PGP_CORRUPT_ONEPASS_ID,\t/* Corruption of onepass keyID */\n\n\t/* Session faults.  The different between CORRUPT_DATA/MAC and \n\t   BADSIG_DATA/MAC is that the former is for session payload data in SSL\n\t   and SSH sessions while the latter is for handshake/protocol data,\n\t   MACs, and signatures, for example in the SSH handshake or CMP \n\t   exchange */\n\tFAULT_SESSION_CORRUPT_HANDSHAKE, /* Corruption of handshake messages */\n\tFAULT_SESSION_CORRUPT_NONCE,/* Corruption of sender/recipient nonce */\n\tFAULT_SESSION_CORRUPT_KEYEX_CLIENT, /* Corruption of client keyex value */\n\tFAULT_SESSION_CORRUPT_KEYEX_SERVER, /* Corruption of server keyex value */\n\tFAULT_SESSION_CORRUPT_DATA,\t/* Corruption/manip.of session data */\n\tFAULT_SESSION_CORRUPT_MAC,\t/* Corruption of session data MAC value */\n\tFAULT_SESSION_WRONGCERT,\t/* Wrong cert.for URL/email address */\n\n\t/* SSH protocol-specific faults */\n\tFAULT_SESSION_SSH_CORRUPT_EXCHANGE_HASH, /* Corruption of exchange hash */\n\tFAULT_SESSION_SSH_CORRUPT_CHANNEL_OPEN,\t/* Corruption of channel no. on open */\n\tFAULT_SESSION_SSH_CORRUPT_CHANNEL_DATA,\t/* Corruption of channel no. on data */\n\tFAULT_SESSION_SSH_CORRUPT_CHANNEL_CLOSE, /* Corruption of channel no. on close */\n\tFAULT_SESSION_SSH_CORRUPT_CHANNEL_REQUEST, /* Corruption of channel no. on req. */\n\n\t/* SSL protocol-specific faults */\n\tFAULT_SESSION_SSL_CORRUPT_FINISHED,\t/* Corruption of finished MAC */\n\tFAULT_SESSION_SSL_CORRUPT_IV,\t/* Corruption of data IV */\n\n\t/* SCEP protocol-specific faults */\n\tFAULT_SESSION_SCEP_CORRUPT_MESSAGETYPE,\t/* Corruption of message type */\n\tFAULT_SESSION_SCEP_CORRUPT_TRANSIDVALUE,/* Corruption of transID checksum */\n\n\tFAULT_LAST\t\t\t\t\t/* Last possible fault type */\n\t} FAULT_TYPE;\n\n/* The handler for injecting faults.  This would be called as:\n\n\tINJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_1 ); */\n\n#define INJECT_FAULT( type, action ) \\\n\t\tif( faultType == ( FAULT_##type ) ) \\\n\t\t\t{ \\\n\t\t\tFAULTACTION_##action; \\\n\t\t\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMechanism Faults\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Corrupt the hash and signature values */\n\n#define FAULTACTION_MECH_CORRUPT_HASH_1 \\\n\t\tif( signature != NULL ) \\\n\t\t\t{ \\\n\t\t\tkrnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL, \\\n\t\t\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE ); \\\n\t\t\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"1234\", 4 ); \\\n\t\t\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 ); \\\n\t\t\t}\n#define FAULTACTION_MECH_CORRUPT_SIG_1 \\\n\t\tif( signature != NULL ) \\\n\t\t\tbuffer[ 8 ]++\n\n/* Corrupt wrapped keys */\n\n#define FAULTACTION_MECH_CORRUPT_KEY_1 \\\n\t\tif( encryptedKey != NULL ) \\\n\t\t\t( ( BYTE * ) mechanismInfo.wrappedData )[ 8 ]++\n\n/* Corrupt the encoded PRF salt, iteration count, and PRF algorithm.  The \n   algorithm is changed from ... 9 == SHA256 to ... 7 == SHA1.  An \n   alternative option is to corrupt to ... 11 == SHA512, but this isn't\n   detected at the external-API level because there's no way to change the \n   hash size of SHA2 from the default SHA-256 to SHA-512 via the external\n   API, so what's reported as SHA512 is processed as SHA256 */\n\n#define FAULTACTION_MECH_CORRUPT_SALT_1 \\\n\t\tif( encryptedKey != NULL ) \\\n\t\t\t{ \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 20 ] == 0x04 ); \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 21 ] == 0x08 ); \\\n\t\t\t( ( BYTE * ) encryptedKey )[ 24 ]++; \\\n\t\t\t}\n#define FAULTACTION_MECH_CORRUPT_ITERATIONS_1 \\\n\t\tif( encryptedKey != NULL ) \\\n\t\t\t{ \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 30 ] == 0x02 ); \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 31 ] == 0x03 ); \\\n\t\t\t( ( BYTE * ) encryptedKey )[ 34 ]--; \\\n\t\t\t}\n#define FAULTACTION_MECH_CORRUPT_PRFALGO_1 \\\n\t\tif( encryptedKey != NULL ) \\\n\t\t\t{ \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 37 ] == 0x06 ); \\\n\t\t\tassert( ( ( BYTE * ) encryptedKey )[ 38 ] == 0x08 ); \\\n\t\t\t( ( BYTE * ) encryptedKey )[ 46 ] = 0x07; \\\n\t\t\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEnvelope Faults\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMS enveloping fault types */\n\n/* Corrupt the payload data or payload hash added to the signedAttrs for \n   signed data */\n\n#define FAULTACTION_BADSIG_DATA_CMS_1 \\\n\t\tenvelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos - 4 ]++\n#define FAULTACTION_BADSIG_HASH_CMS_1 \\\n\t\t{ \\\n\t\tACTION_LIST *actionListPtr = DATAPTR_GET( envelopeInfoPtr->actionList ); \\\n\t\t\\\n\t\tkrnlSendMessage( actionListPtr->iCryptHandle, IMESSAGE_CTX_HASH, \"1234\", 4 ); \\\n\t\t}\n\n/* Corrupt the payload data or MAC for authData and authEncData (the same\n   corruption is used for both enveloping types) */\n\n#define FAULTACTION_ENVELOPE_CMS_CORRUPT_AUTH_DATA_1 \\\n\t\tenvelopeInfoPtr->buffer[ envelopeInfoPtr->bufPos - 8 ]++\n#define FAULTACTION_ENVELOPE_CMS_CORRUPT_AUTH_MAC_1 \\\n\t\thash[ 4 ]++\n\n/* Corrupt the authenticated attributes */\n\n#define FAULTACTION_ENVELOPE_CORRUPT_AUTHATTR_CMS_1 \\\n\t\tif( signature != NULL ) \\\n\t\t\t{ \\\n\t\t\tassert( cmsAttributeInfo.encodedAttributes[ 46 ] == 0x04 ); \\\n\t\t\tassert( cmsAttributeInfo.encodedAttributes[ 47 ] == 0x08 ); \\\n\t\t\tcmsAttributeInfo.encodedAttributes[ 48 ]++; \\\n\t\t\t}\n\n/* PGP enveloping fault types */\n\n/* Corrupt the keyID/one-pass signature packet keyID */\n\n#define FAULTACTION_CORRUPT_ID_PGP_1 \\\n\t\tkeyID[ 4 ]++\n#define FAULTACTION_ENVELOPE_PGP_CORRUPT_ONEPASS_ID_1 \\\n\t\tkeyID[ 4 ]++\n\n/* Corrupt the payload data after the MDC is calculated or corrupt the MDC */\n\n#define FAULTACTION_ENVELOPE_BADSIG_DATA_PGP_1 \\\n\t\tkrnlSendMessage( iMdcContext, IMESSAGE_CTX_HASH, \"1234\", 4 )\n#define FAULTACTION_ENVELOPE_BADSIG_HASH_PGP_1 \\\n\t\tmdcBuffer[ 4 ]++\n\n/* Corrupt the authenticated attributes */\n\n#define FAULTACTION_ENVELOPE_CORRUPT_AUTHATTR_PGP_1 \\\n\t\textraData[ 10 ]++\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSession Faults\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* SSH session fault types */\n\n/* Corrupt the server hello */\n\n#define FAULTACTION_SESSION_CORRUPT_HANDSHAKE_SSH_1 \\\n\t\tif( cryptStatusOK( status ) ) \\\n\t\t\t( ( BYTE * ) serverHelloPtr )[ serverHelloLength - 1 ]++ \n#define FAULTACTION_SESSION_CORRUPT_HANDSHAKE_SSH_2 \\\n\t\t( ( BYTE * ) serverHelloPtr )[ serverHelloLength - 1 ]--\n\n/* Corrupt the payload data and MAC */\n\n#define FAULTACTION_SESSION_CORRUPT_DATA_SSH_1 \\\n\t\tif( isServer( sessionInfoPtr ) ) \\\n\t\t\t{ \\\n\t\t\tsessionInfoPtr->sendBuffer[ SSH2_HEADER_SIZE + \\\n\t\t\t\t\t\t\t\t\t\tSSH2_PAYLOAD_HEADER_SIZE + 4 ]++; \\\n\t\t\t}\n#define FAULTACTION_SESSION_CORRUPT_MAC_SSH_1 \\\n\t\tmac[ 4 ]++\n\n/* Swap the server key for a different one */\n\n#define FAULTACTION_SESSION_WRONGCERT_SSH_1 \\\n\t\tfaultParam1 = sessionInfoPtr->privateKey; \\\n\t\tstatus = getSubstituteKey( &sessionInfoPtr->privateKey ); \\\n\t\tif( cryptStatusError( status ) ) \\\n\t\t\tretIntError()\n#define FAULTACTION_SESSION_WRONGCERT_SSH_2 \\\n\t\tkrnlSendNotifier( sessionInfoPtr->privateKey, IMESSAGE_DESTROY ); \\\n\t\tsessionInfoPtr->privateKey = faultParam1\n\n/* Corrupt the keyex hash that's signed and sent to the client */\n\n#define FAULTACTION_SESSION_BADSIG_HASH_SSH_1 \\\n\t\tif( isServer ) \\\n\t\t\t{ \\\n\t\t\tkrnlSendMessage( handshakeInfo->iExchangeHashContext, \\\n\t\t\t\t\t\t\t IMESSAGE_CTX_HASH, \"x\", 1 ); \\\n\t\t\t}\n\n/* Corrupt the signature value that's sent to the client */\n\n#define FAULTACTION_SESSION_BADSIG_SIG_SSH_1 \\\n\t\t( ( BYTE * ) dataPtr )[ sigLength - 4 ]++\n\n/* Corrupt the username and password.  These checks can't be used because \n   the server-side code merely reports what's received to the caller so it\n   doesn't care what the value actually is since the check is performed by\n   the caller */\n\n#define FAULTACTION_SESSION_CORRUPT_ID_SSH_1 \\\n\t\tuserNameBuffer[ 0 ]++\n#define FAULTACTION_SESSION_CORRUPT_AUTHENTICATOR_SSH_1 \\\n\t\tif( cryptStatusOK( status ) ) \\\n\t\t\tstringBuffer[ 0 ]++\n\n/* Corrupt the client keyex value that's sent to the server and server keyex \n   value that's sent to the client */\n\n#define FAULTACTION_SESSION_CORRUPT_KEYEX_CLIENT_SSH_1 \\\n\t\tkeyAgreeParams.publicValue[ 8 ]++\n#define FAULTACTION_SESSION_CORRUPT_KEYEX_CLIENT_SSH_2 \\\n\t\tkeyAgreeParams.publicValue[ 8 ]--\n#define FAULTACTION_SESSION_CORRUPT_KEYEX_SERVER_SSH_1 \\\n\t\thandshakeInfo->serverKeyexValue[ 8 ]++\n#define FAULTACTION_SESSION_CORRUPT_KEYEX_SERVER_SSH_2 \\\n\t\thandshakeInfo->serverKeyexValue[ 8 ]--\n\n/* Corrupt the server's exchange hash */\n\n#define FAULTACTION_SESSION_SSH_CORRUPT_EXCHANGE_HASH_1 \\\n\t\tif( isServer ) \\\n\t\t\thandshakeInfo->sessionID[ handshakeInfo->sessionIDlength - 1 ]++\n\n/* Corrupt the server's channel number that it sends to the client.  Note \n   that two of the fault checks can't be used:\n   \n   The channel close fault check can't be used because, while it's detected \n   on the server side, the overall self-test status comes from the client \n   side, and that's closing down the session so it doesn't perform any \n   further communications with the server that would show up the problem.  \n   The result is an error message printed by the server-side test code, but \n   no overall error from the test as a whole.\n   \n   The channel request fault check can't be used because cryptlib always\n   sets want_reply to false on these requests, so there's no message to\n   corrupt returned */\n\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_OPEN_1 \\\n\t\tchannelNo += 0x100\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_OPEN_2 \\\n\t\tchannelNo -= 0x100\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_DATA_1 \\\n\t\tsseek( &stream, stell( &stream ) - UINT32_SIZE ); \\\n\t\twriteUint32( &stream, \\\n\t\t\t\t\t getCurrentChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t  CHANNEL_WRITE ) + 0x100 )\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_CLOSE_1 \\\n\t\t{ \\\n\t\tlong *channelPtr = ( long * ) &channelNo; \\\n\t\t( *channelPtr ) += 0x100; \\\n\t\t}\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_CLOSE_2 \\\n\t\t{ \\\n\t\tlong *channelPtr = ( long * ) &channelNo; \\\n\t\t( *channelPtr ) -= 0x100; \\\n\t\t}\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_REQUEST_1 \\\n\t\t{ \\\n\t\tlong *channelPtr = ( long * ) &prevChannelNo; \\\n\t\t( *channelPtr ) += 0x100; \\\n\t\t}\n#define FAULTACTION_SESSION_SSH_CORRUPT_CHANNEL_REQUEST_2 \\\n\t\t{ \\\n\t\tlong *channelPtr = ( long * ) &prevChannelNo; \\\n\t\t( *channelPtr ) -= 0x100; \\\n\t\t}\n\n/* SSL session fault types */\n\n/* Corrupt the session ID (this actually gets detected by us first since the \n   client sends its Finished before we do, and the MAC in the Finished \n   doesn't match what we're expecting).  The session ID is arbitrary and not \n   used in any crypto calculations, which makes it safe to corrupt since it \n   has to be detected entirely by a MAC failure */\n\n#define FAULTACTION_SESSION_CORRUPT_HANDSHAKE_SSL_1 \\\n\t\tfaultParam1 = ( stell( stream ) - handshakeInfo->sessionIDlength ) + 4; \\\n\t\tsessionInfoPtr->sendBuffer[ faultParam1 ]++\n#define FAULTACTION_SESSION_CORRUPT_HANDSHAKE_SSL_2 \\\n\t\tif( cryptStatusOK( status ) ) \\\n\t\t\tsessionInfoPtr->sendBuffer[ faultParam1 ]--\n\n/* Corrupt the payload data and MAC */\n\n#define FAULTACTION_SESSION_CORRUPT_DATA_SSL_1 \\\n\t\tif( !cryptStatusError( status ) ) \\\n\t\t\tsessionInfoPtr->sendBuffer[ SSL_HEADER_SIZE + 4 ]++\n#define FAULTACTION_SESSION_CORRUPT_MAC_SSL_1 \\\n\t\t( ( BYTE * ) data )[ payloadLength + 2 ]++\n\n/* Swap the server certificate for a different one */\n\n#define FAULTACTION_SESSION_WRONGCERT_SSL_1 \\\n\t\tfaultParam1 = sessionInfoPtr->privateKey; \\\n\t\tstatus = getSubstituteKey( &sessionInfoPtr->privateKey ); \\\n\t\tif( cryptStatusError( status ) ) \\\n\t\t\tretIntError()\n#define FAULTACTION_SESSION_WRONGCERT_SSL_2 \\\n\t\tkrnlSendNotifier( sessionInfoPtr->privateKey, IMESSAGE_DESTROY ); \\\n\t\tsessionInfoPtr->privateKey = faultParam1\n\n/* Corrupt the finished MAC value */\n\n#define FAULTACTION_SESSION_SSL_CORRUPT_FINISHED_1 \\\n\t\t( ( BYTE * ) hashValues )[ 4 ]++\n#define FAULTACTION_SESSION_SSL_CORRUPT_FINISHED_2 \\\n\t\t( ( BYTE * ) hashValues )[ 4 ]--\n\n/* Corrupt the hash value */\n\n#define FAULTACTION_SESSION_BADSIG_HASH_SSL_1 \\\n\t\tkrnlSendMessage( shaContext, IMESSAGE_DELETEATTRIBUTE, NULL, \\\n\t\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE ); \\\n\t\tstatus = krnlSendMessage( shaContext, IMESSAGE_CTX_HASH, \\\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) keyData, keyDataLength ); \\\n\t\tif( cryptStatusOK( status ) ) \\\n\t\t\tstatus = krnlSendMessage( shaContext, IMESSAGE_CTX_HASH, \"\", 0 ); \\\n\t\tif( cryptStatusError( status ) ) \\\n\t\t\tretIntError()\n\n/* Corrupt the server keyex value */\n\n#define FAULTACTION_SESSION_BADSIG_DATA_SSL_1 \\\n\t\t( ( BYTE * ) keyData )[ 16 ]++\n#define FAULTACTION_SESSION_BADSIG_DATA_SSL_2 \\\n\t\t( ( BYTE * ) keyData )[ 16 ]--\n\n/* Corrupt the server keyex signature */\n\n#define FAULTACTION_SESSION_BADSIG_SIG_SSL_1 \\\n\t\t( ( BYTE * ) dataPtr )[ 16 ]++\n\n/* Corrupt the IV */\n\n#define FAULTACTION_SESSION_SSL_CORRUPT_IV_1 \\\n\t\tiv[ 2 ]++\n\n/* CMP session fault types */\n\n/* Corrupt the transactionID */\n\n#define FAULTACTION_SESSION_CORRUPT_ID_CMP_1 \\\n\t\tprotocolInfo.transID[ 4 ]++\n\n/* Corrupt the sender nonce.  This isn't currently used because it's one of \n   the many unnecessary fields that CMP includes in messages, the same \n   function is served by the transactionID (checked for with \n   FAULT_SESSION_CORRUPT_ID) so cryptlib never uses nonces.  Sine there's no\n   nonce present, there's nothing to check for corruption */\n\n#define FAULTACTION_SESSION_CORRUPT_NONCE_CMP_1 \\\n\t\tprotocolInfo.senderNonce[ 4 ]++\n\n/* Corrupt the CMP request data (offset 25 = part of the DN), MAC, or \n   signature */\n\n#define FAULTACTION_SESSION_BADSIG_DATA_CMP_1 \\\n\t\tif( !isServer( sessionInfoPtr ) ) \\\n\t\t\tsessionInfoPtr->receiveBuffer[ 25 ]++\n#define FAULTACTION_SESSION_BADSIG_HASH_CMP_1 \\\n\t\tif( !isServer( sessionInfoPtr ) ) \\\n\t\t\tsessionInfoPtr->receiveBuffer[ 16 ]++\n#define FAULTACTION_SESSION_BADSIG_HASH_CMP_2 \\\n\t\tif( !isServer( sessionInfoPtr ) ) \\\n\t\t\tsessionInfoPtr->receiveBuffer[ 16 ]--\n#define FAULTACTION_SESSION_BADSIG_SIG_CMP_1 \\\n\t\tif( cryptStatusOK( status ) && !isServer( sessionInfoPtr ) ) \\\n\t\t\tsessionInfoPtr->receiveBuffer[ stell( &stream ) - 16 ]++\n\n/* SCEP session fault types */\n\n/* Corrupt the transactionID and nonce returned from the server to the \n   client.  The transactionID is checksummed so there are two types of\n   corruption possible, one where a new valid transactionID is substituted\n   for the old one and one where the transactionID data is corrupted so that\n   the checksum no longer validates.  The FAULT_SESSION_CORRUPT_ID \n   substitutes an incorrect (but valid) transactionID for the expected one,\n   so we need to use a different type of corruption, \n   FAULT_SESSION_SCEP_CORRUPT_TRANSIDVALUE, to exercise the checksum test */\n\n#define FAULTACTION_SESSION_CORRUPT_TRANSACTIONID_SCEP_1 \\\n\t\tif( isServer( sessionInfoPtr ) ) \\\n\t\t\t{ \\\n\t\t\tBYTE buffer[ CRYPT_MAX_HASHSIZE ]; \\\n\t\t\tint length; \\\n\t\t\t\\\n\t\t\tstatus = decodePKIUserValue( buffer, CRYPT_MAX_HASHSIZE, \\\n\t\t\t\t\t\t\t\t\t\t &length, userNamePtr->value, \\\n\t\t\t\t\t\t\t\t\t\t userNamePtr->valueLength ); \\\n\t\t\tassert( cryptStatusOK( status ) ); \\\n\t\t\tbuffer[ 4 ]++; \\\n\t\t\tstatus = encodePKIUserValue( userNamePtr->value, 64, \\\n\t\t\t\t\t\t\t\t\t\t ( int * ) &userNamePtr->valueLength, \\\n\t\t\t\t\t\t\t\t\t\t buffer, length, 3 ); \\\n\t\t\tassert( cryptStatusOK( status ) ); \\\n\t\t\t}\n#define FAULTACTION_SESSION_SCEP_CORRUPT_TRANSIDVALUE_1 \\\n\t\tprotocolInfo->transID[ 4 ]++\n#define FAULTACTION_SESSION_CORRUPT_NONCE_SCEP_1 \\\n\t\tprotocolInfo->nonce[ 4 ]++\n\n/* Corrupt the user password sent to the server */\n\n#define FAULTACTION_SESSION_CORRUPT_AUTHENTICATOR_SCEP_1 \\\n\t\t( ( BYTE * ) attributeListPtr->value )[ 4 ]++\n#define FAULTACTION_SESSION_CORRUPT_AUTHENTICATOR_SCEP_2 \\\n\t\t( ( BYTE * ) attributeListPtr->value )[ 4 ]--\n\n/* Corrypt the message type sent from the client to the server */\n\n#define FAULTACTION_SESSION_SCEP_CORRUPT_MESSAGETYPE_1 \\\n\t\tif( !strcmp( messageType, MESSAGETYPE_PKCSREQ ) ) \\\n\t\t\tmessageType = \"99\";\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tFault-Injection Variables and Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The global value that records the fault type to inject.  In addition to\n   this we may need to store parameter information relating to the fault,\n   the faultParam values provide for this storage */\n\nextern FAULT_TYPE faultType;\nextern int faultParam1;\n\n/* Get a substitute key to replace the actual one, used to check for \n   detection of use of the wrong key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSubstituteKey( OUT_HANDLE_OPT CRYPT_CONTEXT *iPrivateKey );\n\n/* Inject faults into a block of memory.  This is called on every call to \n   krnlSendMsg() to simulate SEUs, but is currently disabled */\n\n#define INJECT_MEMORY_FAULTS\t\tinjectMemoryFaults\n\nvoid injectMemoryFaults( void );\n\n#undef INJECT_MEMORY_FAULTS\n#define INJECT_MEMORY_FAULTS()\n\n#else\n\n/* Fault injection is disabled unless CONFIG_FAULTS is defined */\n\n#define INJECT_MEMORY_FAULTS()\n#define INJECT_FAULT( type, action )\n\n#endif /* CONFIG_FAULTS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFuzzing Handling\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef CONFIG_FUZZ\n\n/* Bail out from a block of code when we're fuzzing, needed because we can\n   only get to a certain point with static data before we can't go any\n   further.  The exit code is an error status rather than CRYPT_OK to make\n   sure that we exit immediately, which ensures that we don't have to \n   propagate FUZZ_EXIT()s all the way to the top */\n\n#define FUZZ_EXIT()\t\t\treturn( CRYPT_ERROR_NOTAVAIL )\n\n/* Skip a block of code when we're fuzzing, needed because request/response\n   protocols don't have a request to send out before reading back the \n   (static) response */\n\n#define FUZZ_SKIP()\t\t\treturn( CRYPT_OK )\n\n/* Sometimes we need to set up additional values that are normally handled\n   by skipped code.  This is handled with the following macro */\n\n#define FUZZ_SET( a, b )\t( a ) = ( b )\n\n/* If we're fuzzing then some asserts, which exist to draw attention to \n   unusual input data that needs human attention, shouldn't be triggered,\n   in which case we no-op them out */\n\n#define assert_nofuzz( x )\n\n#else\n\n#define FUZZ_EXIT()\n#define FUZZ_SKIP()\n#define FUZZ_SET( a, b )\n#define assert_nofuzz\tassert\n\n#endif /* CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRemoves Fault Injection for non-Debug\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#else\n\n#ifndef CONFIG_FAULTS\n  #define INJECT_FAULT( type, action )\n  #define INJECT_MEMORY_FAULTS()\n#endif /* CONFIG_FAULTS */\n\n#ifndef CONFIG_FUZZ\n  #define FUZZ_EXIT()\n  #define FUZZ_SKIP()\n  #define FUZZ_SET( a, b )\n  #define assert_nofuzz\tassert\n#endif /* CONFIG_FUZZ */\n\n#endif /* !NDEBUG */\n#endif /* _FAULT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/int_api.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Internal API\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* A generic module that implements a rug under which all problems not\n   solved elsewhere are swept */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"stream.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n/* Perform the FIPS-140 statistical checks that are feasible on a byte\n   string.  The full suite of tests assumes that an infinite source of\n   values (and time) is available, the following is a scaled-down version\n   used to sanity-check keys and other short random data blocks.  Note that\n   this check requires at least 64 bits of data in order to produce useful\n   results */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checkNontrivialKey( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) \\\n\t\t\t\t\t\t\t\t\t\tconst int dataLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_B( dataLength >= MIN_KEYSIZE && \\\n\t\t\t\tdataLength < MAX_INTLENGTH_SHORT );\n\n\tLOOP_LARGE( i = 0, i < dataLength, i++\t)\n\t\t{\n\t\tif( !isAlnum( data[ i ] ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( i >= dataLength )\n\t\treturn( FALSE );\n\n\tLOOP_LARGE( i = 0, i < dataLength - 1, i++ )\n\t\t{\n\t\tconst int delta = abs( data[ i ] - data[ i + 1 ] );\n\n\t\tif( delta > 8 )\n\t\t\tbreak;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tif( i >= dataLength - 1 )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkEntropy( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int dataLength )\n\t{\n\tconst int delta = ( dataLength < 16 ) ? 1 : 0;\n\tint bitCount[ 8 + 8 ], noOnes, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\t\n\tREQUIRES_B( dataLength >= MIN_KEYSIZE && dataLength < MAX_INTLENGTH_SHORT );\n\n\t/* Make sure that we haven't been given an obviously non-random key */\n\tif( !checkNontrivialKey( data, dataLength ) )\n\t\treturn( FALSE );\n\n\tmemset( bitCount, 0, sizeof( int ) * 9 );\n\tLOOP_LARGE( i = 0, i < dataLength, i++ )\n\t\t{\n\t\tconst int value = byteToInt( data[ i ] );\n\n\t\tbitCount[ value & 3 ]++;\n\t\tbitCount[ ( value >> 2 ) & 3 ]++;\n\t\tbitCount[ ( value >> 4 ) & 3 ]++;\n\t\tbitCount[ ( value >> 6 ) & 3 ]++;\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\t/* Monobit test: Make sure that at least 1/4 of the bits are ones and 1/4\n\t   are zeroes */\n\tnoOnes = bitCount[ 1 ] + bitCount[ 2 ] + ( 2 * bitCount[ 3 ] );\n\tif( noOnes < dataLength * 2 || noOnes > dataLength * 6 )\n\t\t{\n\t\tzeroise( bitCount, 8 * sizeof( int ) );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Poker test (almost): Make sure that each bit pair is present at least\n\t   1/16 of the time.  The FIPS 140 version uses 4-bit values but the\n\t   numer of samples available from the keys is far too small for this so\n\t   we can only use 2-bit values.\n\n\t   This isn't precisely 1/16, for short samples (< 128 bits) we adjust\n\t   the count by one because of the small sample size and for odd-length\n\t   data we're getting four more samples so the actual figure is slightly\n\t   less than 1/16 */\n\tif( ( bitCount[ 0 ] + delta < dataLength / 2 ) || \\\n\t\t( bitCount[ 1 ] + delta < dataLength / 2 ) || \\\n\t\t( bitCount[ 2 ] + delta < dataLength / 2 ) || \\\n\t\t( bitCount[ 3 ] + delta < dataLength / 2 ) )\n\t\t{\n\t\tzeroise( bitCount, 8 * sizeof( int ) );\n\t\treturn( FALSE );\n\t\t}\n\n\tzeroise( bitCount, 8 * sizeof( int ) );\n\treturn( TRUE );\n\t}\n\n/* Check whether a block of 64 bits of data is all-zeroes, typically used \n   for sanity-check functions that check contexts for validity.  \n   \n   Note that the length value provided to this function isn't the length of\n   the data being provided, which is fixed at 8 bytes, but the length value\n   that the caller has for the data.  If it's nonzero then we don't check\n   the data contents, only if it's zero do we go on to check whether the\n   data is also zero */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isEmptyData( IN_BUFFER_C( 8 ) const BYTE data[ 8 ],\n\t\t\t\t\t IN_LENGTH_SHORT_Z const int dataLengthValue )\n\t{\n\tassert( isReadPtr( data, 8 ) );\n\n\tREQUIRES_B( isShortIntegerRange( dataLengthValue ) );\n\n\t/* Perform a quick-reject check before calling the more expensive\n\t   memcmp() */\n\tif( dataLengthValue != 0 || data[ 0 ] != 0x00 )\n\t\treturn( FALSE );\n\n\t/* Check whether the first 64 bits are zero */\n\treturn( memcmp( data, \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 8 ) ? \\\n\t\t\tFALSE : TRUE );\n\t}\n\n/* Perform a bounds check on pointers to blocks of memory, verifying that an\n   inner block of memory is contained entirely within an outer block of \n   memory */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN pointerBoundsCheck( IN_OPT const void *data,\n\t\t\t\t\t\t\tIN_LENGTH_Z const int dataLength,\n\t\t\t\t\t\t\tIN_OPT const void *innerData,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int innerDataLength )\n\t{\n\tREQUIRES_B( isIntegerRange( dataLength ) );\n\tREQUIRES_B( isShortIntegerRange( innerDataLength ) );\n\n\t/* Check for general problems with the parameters */\n\tif( ( data != NULL && dataLength <= 0 ) || \\\n\t\t( data == NULL && dataLength > 0 ) )\n\t\treturn( FALSE );\n\tif( ( innerData != NULL && innerDataLength <= 0 ) || \\\n\t\t( innerData == NULL && innerDataLength > 0 ) )\n\t\treturn( FALSE );\n\n\tassert( data == NULL || isReadPtrDynamic( data, dataLength ) );\n\tassert( innerData == NULL || \\\n\t\t\tisReadPtrDynamic( innerData, innerDataLength ) );\n\t\n\t/* If there's no data present then there's nothing to check, although \n\t   we do have to make sure that there's then no inner data present \n\t   either */\n\tif( data == NULL )\n\t\t{\n\t\tif( innerData != NULL || innerDataLength != 0 )\n\t\t\treturn( FALSE );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If there's no inner data present then there's nothing to check */\n\tif( innerData == NULL )\n\t\t{\n\t\t/* This is already checked in the general parameter check above, but\n\t\t   we make it explicit here as well */\n\t\tREQUIRES_B( innerDataLength == 0 );\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Make sure that the inner data is contained within the outer data */\n\tif( innerData < data || \\\n\t\t( ( BYTE * ) innerData + innerDataLength > \\\n\t\t\t\t\t\t\t\t\t\t( BYTE * ) data + dataLength ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/* Helper function used to check that a sequence of CFI tokens have been \n   processed in order.  This is used both to ensure that inline macros to\n   perform the CFI checking don't get too complex and to reduce the chances\n   of a compiler being able to turn the CFI check into a compile-time \n   constant expression.\n   \n   This function isn't decorated with attributes because it both takes and \n   produces arbitrary-range integers */\n\nCFI_CHECK_TYPE cfiCheckSequence( const CFI_CHECK_TYPE initValue, \n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label1Value,\n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label2Value, \n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label3Value )\n\t{\n\tCFI_CHECK_TYPE cfiCheckValue = initValue;\n\n\tcfiCheckValue = ( cfiCheckValue << 5 ) + label1Value;\n\tif( label2Value != ( CFI_CHECK_TYPE ) -1 )\n\t\tcfiCheckValue = ( cfiCheckValue << 5 ) + label2Value;\n\tif( label3Value != ( CFI_CHECK_TYPE ) -1 )\n\t\tcfiCheckValue = ( cfiCheckValue << 5 ) + label3Value;\n\n\treturn( cfiCheckValue );\n\t}\n\n/* Copy a string attribute to external storage, with various range checks\n   to follow the cryptlib semantics (these will already have been done by\n   the caller, this is just a backup check).  There are two forms for this\n   function, one that takes a MESSAGE_DATA parameter containing all of the \n   result parameters in one place and the other that takes distinct result\n   parameters, typically because they've been passed down through several\n   levels of function call beyond the point where they were in a \n   MESSAGE_DATA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint attributeCopyParams( OUT_BUFFER_OPT( destMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *destLength ) void *dest, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int destMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_SHORT_Z( destMaxLength ) \\\n\t\t\t\t\t\t\tint *destLength, \n\t\t\t\t\t\t IN_BUFFER_OPT( sourceLength ) const void *source, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int sourceLength )\n\t{\n\tassert( ( dest == NULL && destMaxLength == 0 ) || \\\n\t\t\t( isWritePtrDynamic( dest, destMaxLength ) ) );\n\tassert( isWritePtr( destLength, sizeof( int ) ) );\n\tassert( ( source == NULL && sourceLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( source, sourceLength ) );\n\n\tREQUIRES( ( dest == NULL && destMaxLength == 0 ) || \\\n\t\t\t  ( dest != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( destMaxLength ) ) );\n\tREQUIRES( ( source == NULL && sourceLength == 0 ) || \\\n\t\t\t  ( source != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( sourceLength ) ) );\n\n\t/* Clear return value */\n\t*destLength = 0;\n\n\tif( sourceLength <= 0 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( dest != NULL )\n\t\t{\n\t\tassert( isReadPtrDynamic( source, sourceLength ) );\n\n\t\tif( sourceLength > destMaxLength || \\\n\t\t\t!isWritePtrDynamic( dest, sourceLength ) )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tREQUIRES( rangeCheck( sourceLength, 1, destMaxLength ) );\n\t\tmemcpy( dest, source, sourceLength );\n\t\t}\n\t*destLength = sourceLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint attributeCopy( INOUT MESSAGE_DATA *msgData, \n\t\t\t\t   IN_BUFFER( attributeLength ) const void *attribute, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int attributeLength )\n\t{\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\tassert( attributeLength == 0 || \\\n\t\t\tisReadPtrDynamic( attribute, attributeLength ) );\n\n\tREQUIRES( isShortIntegerRange( attributeLength ) );\n\n\treturn( attributeCopyParams( msgData->data, msgData->length, \n\t\t\t\t\t\t\t\t &msgData->length, attribute, \n\t\t\t\t\t\t\t\t attributeLength ) );\n\t}\n\n/* Check whether a given algorithm is available */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN algoAvailable( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_QUERY_INFO queryInfo;\n\n\tREQUIRES_B( isEnumRange( cryptAlgo, CRYPT_ALGO ) );\n\n\t/* Short-circuit check for always-available algorithms.  The kernel \n\t   won't initialise without the symmetric and hash algorithms being \n\t   present (and SHA-x implies HMAC-SHAx) so it's safe to hardcode them \n\t   in here */\n\tif( cryptAlgo == CRYPT_ALGO_AES || \\\n\t\tcryptAlgo == CRYPT_ALGO_SHA1 || \\\n\t\tcryptAlgo == CRYPT_ALGO_HMAC_SHA1 || \\\n\t\tcryptAlgo == CRYPT_ALGO_SHA2 || \\\n\t\tcryptAlgo == CRYPT_ALGO_HMAC_SHA2 || \\\n\t\tcryptAlgo == CRYPT_ALGO_RSA )\n\t\treturn( TRUE );\n#ifdef USE_3DES\n\tif( cryptAlgo == CRYPT_ALGO_3DES )\n\t\treturn( TRUE );\n#endif /* USE_3DES */\n\t\t\n\treturn( cryptStatusOK( krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\tIMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,\n\t\t\t\t\t\t\t\t\tcryptAlgo ) ) ? TRUE : FALSE );\n\t}\n\n/* For a given hash algorithm pair, check whether the first is stronger than \n   the second.  The order is:\n\n\tSNAng > SHA2 > SHA-1 > all others */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isStrongerHash( IN_ALGO const CRYPT_ALGO_TYPE algorithm1,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE algorithm2 )\n\t{\n\tstatic const CRYPT_ALGO_TYPE algoPrecedence[] = {\n\t\tCRYPT_ALGO_SHAng, CRYPT_ALGO_SHA2, CRYPT_ALGO_SHA1, \n\t\tCRYPT_ALGO_NONE, CRYPT_ALGO_NONE };\n\tint algo1index, algo2index, LOOP_ITERATOR;\n\n\tREQUIRES_B( isHashAlgo( algorithm1 ) );\n\tREQUIRES_B( isHashAlgo( algorithm2 ) );\n\n\t/* Find the relative positions on the scale of the two algorithms */\n\tLOOP_SMALL( algo1index = 0, \n\t\t\t\talgoPrecedence[ algo1index ] != algorithm1 && \\\n\t\t\t\t\talgo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_TYPE ),\n\t\t\t\talgo1index++ )\n\t\t{\n\t\t/* If we've reached an unrated algorithm, it can't be stronger than \n\t\t   the other one */\n\t\tif( algoPrecedence[ algo1index ] == CRYPT_ALGO_NONE )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( algo1index < FAILSAFE_ARRAYSIZE( algoPrecedence, \\\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ALGO_TYPE ) );\n\tLOOP_SMALL( algo2index = 0, \n\t\t\t\talgoPrecedence[ algo2index ] != algorithm2 && \\\n\t\t\t\t\talgo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_TYPE ),\n\t\t\t\talgo2index++ )\n\t\t{\n\t\t/* If we've reached an unrated algorithm, it's weaker than the other \n\t\t   one */\n\t\tif( algoPrecedence[ algo2index ] == CRYPT_ALGO_NONE )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( algo2index < FAILSAFE_ARRAYSIZE( algoPrecedence, \\\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ALGO_TYPE ) );\n\n\t/* If the first algorithm has a smaller index than the second, it's a\n\t   stronger algorithm */\n\treturn( ( algo1index < algo2index ) ? TRUE : FALSE );\n\t}\n\n/* Return a random small positive integer.  This is used to perform \n   lightweight randomisation of various algorithms in order to make DoS \n   attacks harder.  Because of this the values don't have to be \n   cryptographically strong, so all that we do is cache the data from \n   CRYPT_IATTRIBUTE_RANDOM_NONCE and pull out a small integer's worth on \n   each call.  For the same reason, we don't care that the function isn't\n   thread-safe */\n\n#define RANDOM_BUFFER_SIZE\t64\n\nCHECK_RETVAL_RANGE_NOERROR( 0, 32767 ) \\\nint getRandomInteger( void )\n\t{\n\tstatic BYTE nonceData[ RANDOM_BUFFER_SIZE + 8 ];\n\tstatic int nonceIndex = 0;\n\tint returnValue, status;\n\n\tREQUIRES_EXT( !( nonceIndex & 1 ), 0 );\n\n\t/* Initialise/reinitialise the nonce data if necessary.  See the long \n\t   coment for getNonce() in system.c for the reason why we don't bail \n\t   out on error but continue with a lower-quality generator */\n\tif( nonceIndex <= 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, nonceData, RANDOM_BUFFER_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( ( int ) getTime() & 0x7FFF );\n\t\t}\n\n\t/* Extract the next random integer value from the buffered data */\n\treturnValue = ( byteToInt( nonceData[ nonceIndex ] ) << 8 ) | \\\n\t\t\t\t\tbyteToInt( nonceData[ nonceIndex + 1 ] );\n\tnonceIndex = ( nonceIndex + 2 ) % RANDOM_BUFFER_SIZE;\n\tENSURES_EXT( nonceIndex >= 0 && nonceIndex < RANDOM_BUFFER_SIZE, 0 );\n\n\t/* Return the value constrained to lie within the range 0...32767 */\n\treturn( returnValue & 0x7FFF );\n\t}\n\n/* Map one value to another, used to map values from one representation \n   (e.g. PGP algorithms or HMAC algorithms) to another (cryptlib algorithms\n   or the underlying hash used for the HMAC algorithm) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint mapValue( IN_INT_SHORT_Z const int srcValue,\n\t\t\t  OUT_INT_SHORT_Z int *destValue,\n\t\t\t  IN_ARRAY( mapTblSize ) const MAP_TABLE *mapTbl,\n\t\t\t  IN_RANGE( 1, 100 ) const int mapTblSize )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( destValue, sizeof( int ) ) );\n\tassert( isReadPtr( mapTbl, mapTblSize * sizeof( MAP_TABLE ) ) );\n\n\tREQUIRES( isShortIntegerRange( srcValue ) );\n\tREQUIRES( mapTblSize > 0 && mapTblSize < 100 );\n\tREQUIRES( mapTbl[ mapTblSize ].source == CRYPT_ERROR );\n\n\t/* Clear return value */\n\t*destValue = 0;\n\n\t/* Convert the hash algorithm into the equivalent HMAC algorithm */\n\tLOOP_LARGE( i = 0, \n\t\t\t\ti < mapTblSize && mapTbl[ i ].source != CRYPT_ERROR, \n\t\t\t\ti++ )\n\t\t{\n\t\tif( mapTbl[ i ].source == srcValue )\n\t\t\t{\n\t\t\t*destValue = mapTbl[ i ].destination;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < mapTblSize );\n\n\treturn( CRYPT_ERROR_NOTAVAIL );\n\t}\n\n#ifdef USE_ERRMSGS\n\n/* Map an object type to a string description of the type, used for printing\n   diagnostic messages */\n\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst char *getObjectName( IN_ARRAY( objectNameInfoSize ) \\\n\t\t\t\t\t\t\t\tconst OBJECT_NAME_INFO *objectNameInfo,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int objectNameInfoSize,\n\t\t\t\t\t\t   const int objectType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( objectNameInfo, \n\t\t\t\t\t   sizeof( OBJECT_NAME_INFO ) * objectNameInfoSize ) );\n\n\tREQUIRES_EXT( isShortIntegerRange( objectNameInfoSize ),\n\t\t\t\t  \"<Internal error>\" );\n\n\tLOOP_LARGE( i = 0,\n\t\t\t\tobjectNameInfo[ i ].objectType != objectType && \\\n\t\t\t\t\tobjectNameInfo[ i ].objectType != CRYPT_ERROR && \\\n\t\t\t\t\ti < objectNameInfoSize, \n\t\t\t\ti++ );\n\tENSURES_EXT( LOOP_BOUND_OK, \"<Internal error>\" );\n\tENSURES_EXT( i < objectNameInfoSize, \"<Internal error>\" );\n\n\treturn( objectNameInfo[ i ].objectName );\n\t}\n#endif /* USE_ERRMSGS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTime Dithering Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delay by small random amounts, used to both dither the results of online-\n   visible crypto operations to make timing attacks harder and for failed \n   crypto operations to stall probing attacks alongside the dithering by \n   adding much longer delays.  In effect this creates the inverse of fuzzy \n   time/fuzzy I/O from Wei-Ming Hu's \"Reducing Timing Channels with Fuzzy \n   Time\", Journal of Computer Security, 1992, more usually implemented as \n   spread-spectrum clocking to deal with EMI, by keeping the clock constant \n   but fuzzing the execution time of what's being measured.\n   \n   As with anything involving randomness, there's been a lot of smoke and \n   not much light generated over the use of random delays to address timing \n   attacks.  The generic answer is that it doesn't help so there's no point \n   in doing it and everyone should just write constant-time code, another \n   prime example of le mieux est l'ennemi du bien.\n\n   If the arguments ever get beyond abstract theory (theoretical constant-\n   time code is better than theoretical random delays), the argument given \n   is usually that we're measuring timing differences in us or ns while the \n   delay functions are typically in ms.  Another argument is that all an \n   attacker has to do is repeat the measurements in order to filter out the \n   delays.\n\n   To give a concrete example, a sleep function with a ms granularity being \n   used with a 2GHz CPU means that there are 2M clock cycles between each \n   timer tick.  The sleep function doesn't guarantee to return after exactly \n   x ms but after at least x ms have elapsed which helps a bit, but we still \n   need a finer-grained delay, which insertCryptoDelay() further down \n   provides.\n\n   A counterargument for the high-precision measurement claim is that if \n   you've got an attacker sitting on your local LAN segment making ns-scale \n   timing measurements on your crypto then you've got bigger things to worry \n   about than side-channel attacks (over more distant connections, you can \n   at best get tens to hundreds of us using thousands of measurements, see \n   e.g. \"Opportunities and Limits of Remote Timing Attacks\" by Crosby, Reid, \n   and Wallach, which also required multiple days of data-gathering \n   beforehand to characterise the network).  \n   \n   In addition in cryptlib's case since all operations go via the kernel, \n   you don't have direct (timing) access to the low-level crypto ops but \n   only get strongly dithered results at that level (this actually makes the\n   effectiveness of the dithering countermeasures somewhat difficult to\n   evaluate since the kernel already provides a good measure of dithering).\n\n   As a result, while you can still use repeated measurements to eventually\n   filter out the dithering, it's now made the attacker's job much, much \n   harder.  Since the failure-related dithering is essentially free (it's \n   only invoked if an operation fails), it makes sense to add the delay.  \n   In addition, on top of the sleep delay, we add the fine-grained delay \n   mentioned earlier to dither exact timings.\n   \n   Another issue is how long to make the delay.  Obviously the longer the \n   better since it slows down attacks, however if we make it too long then \n   it can end up looking like a different problem, e.g. a networking issue \n   rather than a crypto defence, which will be a pain to diagnose for \n   users.  3s seems to be a good tradeoff between dithering operations and \n   slowing down an attacker while not adding an excessive delay that looks \n   like it's caused by something else */\n\n/* Implement an extremely slow busy-wait loop via the world's worst hash\n   function.  We use the slowest and most unpredictable data-manipulation\n   instructions available, combined with endless data dependencies and \n   pipeline stalls.  Multiplies, while they often have a single-cycle \n   throughput, typically have a multiple-cycle latency, which we enforce \n   with data dependencies.  The magic instruction for poor performance \n   though is the divide, which is typically microcoded and with a huge, \n   data-dependent, latency */\n\n#ifdef SYSTEM_64BIT\n  #define CONST1\t0x6A09E667BB67AE85\t/* SHA2, h0 || h1 */\n  #define CONST2\t0x3C6EF372A54FF53A\t/* SHA2, h2 || h3 */\n  #define CONST3\t0x510E527F9B05688C\t/* SHA2, h4 || h5 */\n  #define CONST4\t0x1F83D9AB5BE0CD19\t/* SHA2, h6 || h7 */\n#else\n  #define CONST1\t0xCA62C1D6\t\t\t/* SHA1, sqrt10 */\n  #define CONST2\t0x8F1BBCDC\t\t\t/* SHA1, sqrt5 */\n  #define CONST3\t0x6ED9EBA1\t\t\t/* SHA1, sqrt3 */\n  #define CONST4\t0x5A827999\t\t\t/* SHA1, sqrt2 */\n#endif /* 32- vs. 64-bit systems */\n\n#if defined( __WIN64__ )\n  typedef DWORD64\t\t\tMACHINE_WORD;\n#elif defined( __WIN32__ )\n  typedef DWORD\t\t\t\tMACHINE_WORD;\n#else\n  typedef unsigned long\t\tMACHINE_WORD;\n#endif /* System-specific machine word data types */\n\n#ifdef _MSC_VER\n  #ifdef SYSTEM_64BIT\n\t#define ROTL( x, r )\t_rotl64( x, r )\n  #else\n\t#define ROTL( x, r )\t_rotl( x, r )\n  #endif /* 32- vs. 64-bit systems */\n#else\n  /* Most compilers have rotate-recognisers, this is the form that will \n     produce a native rotate instruction */\n  #define WORD_SIZE\t\t\t( sizeof( MACHINE_WORD ) * 8 )\n  #define ROTL( x, r )\t\t( ( ( x ) << ( r ) ) | ( ( x ) >> ( WORD_SIZE - ( r ) ) ) )\n#endif /* _MSC_VER */\n\nstatic int merdeMerdeHash( const int value1, const int value2 )\n\t{\n\tMACHINE_WORD l = value1, r = value2;\n\tint fineDelay, i;\n\n\t/* Create the initial coarse-grained delay via the world's worst hash \n\t   function, full of data dependencies and pipeline stalls */\n\tfor( i = 0; i < value1; i++ )\n\t\t{\n\t\t/* Fill up both l and r with bits */\n\t\tl *= r + CONST1;\n\t\tr *= l + CONST2;\n\n\t\t/* Since we're about to divide by r, make sure that it's not zero, \n\t\t   as well as adding a number of unpredictable branches to the code \n\t\t   flow */\n\t\twhile( !( r & 0x800 ) )\n\t\t\tr += CONST3;\n\n\t\t/* Perform a slow divide.  We actually apply it as a mod operation \n\t\t   (still done via a divide instruction, only the remainder is \n\t\t   what's preserved) since a divide would reduce l to a small \n\t\t   integer value, and zero with 50% probability.  However we also \n\t\t   have to be careful with the mod operation for the same reason as \n\t\t   the problem with divides, at least half the time it'll be a \n\t\t   no-op, so we shift it four bits to increase the chances of it \n\t\t   doing something.  Finally, once we've done the divide, we refill \n\t\t   l since the mod by a smaller amount has decreased its magnitude */\n\t\tl %= r >> 4;\n\t\tl += ROTL( r, 13 );\n\n\t\t/* As before, this time with r and l */\n\t\twhile( !( l & 0x800 ) )\n\t\t\tl += CONST4;\n\t\tr %= l >> 4;\n\t\tr += ROTL( l, 13 );\n\t\t}\n\n\t/* Finish off with a fine-grained delay */\n\tfineDelay = ( int ) ( l & 0x7FFF );\n\tfor( i = 0; i < fineDelay; i++ )\n\t\t{\n\t\tl += ROTL( r, 23 );\n\t\tr += ROTL( l, 23 );\n\t\t}\n\n\treturn( ( r + l ) & 0x7FFF );\n\t}\n\n/* Delay by a large amount by suspending the current thread for a preset \n   time.  The external form delayRandom() is called in response to generic\n   failures in secure sessions rather than crypto failures.  Crypto failures \n   are handled via registerCryptoFailure() */\n\nstatic void randomDelay( IN_RANGE( 0, 10 ) const int baseDelaySeconds, \n\t\t\t\t\t\t IN_RANGE( 100, 5000 ) const int maxDelayMS )\n\t{\n\tint delayTime = getRandomInteger();\n\n\tREQUIRES_V( baseDelaySeconds >= 0 && baseDelaySeconds <= 10 );\n\tENSURES_V( maxDelayMS >= 100 && maxDelayMS <= 5000 );\n\n#ifdef CONFIG_FUZZ\n\t/* When fuzzing, make sure that we don't insert delays once we bail out \n\t   at the end of the fuzzed data */\n\treturn;\n#endif /* CONFIG_FUZZ */\n\n\t/* Use a delay from 0.01s to maxDelayMS.  getRandomInteger() can return \n\t   zero for a shouldn't-occur error condition, this is converted into a \n\t   small nonzero wait alongside an actual zero value */\n\tdelayTime %= ( maxDelayMS + 1 );\n\tif( delayTime < 5 )\n\t\tdelayTime = 5;\n\tENSURES_V( delayTime >= 5 && delayTime <= 5000 );\n\n\t/* Add the base delay amount */\n\tdelayTime += baseDelaySeconds * 1000;\n\n\t/* Wait for the given number of milliseconds */\n\t( void ) krnlWait( delayTime );\n\t}\n\nint delayRandom( void )\n\t{\n\trandomDelay( 0, 3000 );\n\treturn( insertCryptoDelay() );\n\t}\n\n/* Respond to repeated crypto failures, an indication that someone is trying \n   to use us as an oracle.  This tracks how many failures have occurred \n   recently and inserts a delay proportional to the number of failures, \n   acting as a rate-limiting mechanism for attacker queries.  We keep a \n   single count across all crypto failure types to avoid allowing an \n   attacker to bypass the rate-limiting by spreading their queries across\n   multiple mechanisms and protocols */ \n\n#ifdef USE_SESSIONS\n\nint registerCryptoFailure( void )\n\t{\n\tstatic time_t intervalStartTime = CURRENT_TIME_VALUE;\n\tstatic int failures = 0;\n\tconst time_t currentTime = getTime();\n\tint status;\n\n\t/* If there's no reliable time source available, there's not much that \n\t   we can do apart from inserting a tradeoff delay that's long enough \n\t   to slow down attacks but not long enough to DoS ourselves */\n\tif( currentTime <= MIN_TIME_VALUE )\n\t\t{\n\t\trandomDelay( 0, 500 );\n\t\tinsertCryptoDelay();\n\t\treturn( 0 );\n\t\t}\n\n\t/* Since the crypto failure state can be accessed by multiple threads, \n\t   we need to wrap the accesses in a mutex */\n\tstatus = krnlEnterMutex( MUTEX_CRYPTODELAY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* As before */\n\t\trandomDelay( 0, 500 );\n\t\tinsertCryptoDelay();\n\t\treturn( 0 );\n\t\t}\n\n\t/* If there hasn't been a crypto failure within the last five minutes,\n\t   decay the failure count and reset the interval start time */\n\tif( currentTime >= intervalStartTime + ( 5 * 60 ) )\n\t\t{\n\t\tconst int intervals = ( int ) \\\n\t\t\t\t\t\t( ( currentTime - intervalStartTime ) / ( 5 * 60 ) );\n\n\t\tif( intervals < 20 )\n\t\t\tfailures >>= intervals;\n\t\telse\n\t\t\tfailures = 0;\n\t\tintervalStartTime = currentTime;\n\t\t}\n\telse\n\t\t{\n\t\t/* There have been multiple failures within a short time period, if\n\t\t   the current one is very recent reset the time window */\n\t\tif( currentTime <= intervalStartTime + ( 2 * 60 ) )\n\t\t\tintervalStartTime = currentTime;\n\t\t}\n\n\t/* Increment the failure count, capping the total at a reasonable \n\t   value */ \n\tif( failures < 50000 )\n\t\tfailures++;\n\n\tkrnlExitMutex( MUTEX_CRYPTODELAY );\n\n\t/* Insert a delay proportionate to the number of recent crypto failures.  \n\t   The threshold for the various delays is rather imprecuse, we don't \n\t   want to respond disproportionately to a small number of legitimate \n\t   failures but do want to do so for an actual attack.  On the other \n\t   hand the process is somewhat self-limiting in that once a response is\n\t   triggered the attack rate will be severely throttled unless the code \n\t   is being run with a large number of threads, each of which can be \n\t   parked in randomDelay() while the next thread is attacked */\n\tif( failures < 10 )\n\t\trandomDelay( 0, 500 );\t\t/* 0..0.5s */\n\telse\n\tif( failures < 50 )\n\t\trandomDelay( 0, 1000 );\t\t/* 0..1s */\n\telse\n\tif( failures < 100 )\n\t\trandomDelay( 1, 2000 );\t\t/* 1..3s */\n\telse\n\tif( failures < 500 )\n\t\trandomDelay( 3, 2000 );\t\t/* 3..5s */\n\telse\n\t\trandomDelay( 5, 5000 );\t\t/* 5...10s */\n\t\n\treturn( insertCryptoDelay() );\n\t}\n\n/* Insert a small random delay to make timing attacks on crypto operations\n   harder.  This is a bit of a pain because the delays follow crypto \n   operations that have been tuned to be as fast and efficient as possible,\n   while what we're doing here is slowing them down again, however fast\n   crypto typically won't get noticed while side-channel vulnerable crypto\n   will.\n   \n   An alternative to trying to make the crypto constant-time is to bracket \n   the operation with clock ticks, so we wait for a clock tick to start the\n   operation and wait for another clock tick to finish it.  This is \n   typically even worse than inserting a random delay because it inserts two \n   largeish delays instead, even if it's done via a sleep call rather than a \n   busy-wait\n   \n   Another option, getting increasingly esoteric, would be possible on a \n   very busy server by batching crypto operations, so that n crypto \n   operations are run back-to-back and the result only returned when the \n   final one has completed, however this again leads to long delays as well\n   as being horribly complex to implement */\n\nint insertCryptoDelay( void )\n\t{\n\tstatic int seed = 1;\n\n\t/* Insert a short delay.  Since getRandomInteger() returns a short-\n\t   integer value (which we make explicit here, although the operation\n\t   is redundant), we have to call the hash function twice to get a long \n\t   enough delay.\n\n\t   The delay is chosen so that it adds about 1% to the execution time of\n\t   a 2Kbit private-key op.  This is actually 1/5 of the SD of the \n\t   private-key op time, so there's plenty of dithering there anyway...\n\n\t   The first value is the iteration count, the second is a a seed value\n\t   that's fed back to the input to ensure that a compiler can't inline/\n\t   optimise away the expression if it detects that the result isn't \n\t   being used */ \n\tseed = merdeMerdeHash( getRandomInteger() % 32768, seed );\n\treturn( merdeMerdeHash( getRandomInteger() % 32768, seed ) );\n\t}\n#endif /* USE_SESSIONS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChecksum/Hash Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Calculate a 16-bit Fletcher-like checksum for a block of data.  This \n   isn't a true Fletcher checksum but this isn't a big deal since all we \n   need is consistent results for identical data, the value itself is never \n   communicated externally.  In cases where it's used in critical checks \n   it's merely used as a quick pre-check for a full hash-based check, so it \n   doesn't have to be perfect.  In addition it's not in any way \n   cryptographically secure for the same reason, there's no particular need \n   for it to be secure.  If a requirement for at least some sort of \n   unpredictability did arise then something like Pearson hashing could be \n   substituted transparently */\n\nRETVAL_RANGE( MAX_ERROR, 0x7FFFFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint checksumData( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t  IN_DATALENGTH const int dataLength )\n\t{\n\tconst BYTE *dataPtr = data;\n\tint sum1 = 1, sum2 = 0, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( data != NULL );\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE )\n\n\tLOOP_MAX( i = 0, i < dataLength, i++ )\n\t\t{\n\t\tsum1 += dataPtr[ i ];\n\t\tsum2 += sum1;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n#if defined( SYSTEM_16BIT )\n\treturn( sum2 & 0x7FFF );\n#else\n\treturn( ( ( sum2 & 0x7FFF ) << 16 ) | ( sum1 & 0xFFFF ) );\n#endif /* 16- vs. 32-bit systems */\n\t}\n\n/* Calculate the hash of a block of data.  We use SHA-1 because it's the \n   built-in default, but any algorithm will do since we're only using it\n   to transform a variable-length value to a fixed-length one for easy\n   comparison purposes */\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid hashData( OUT_BUFFER_FIXED( hashMaxLength ) BYTE *hash, \n\t\t\t   IN_LENGTH_HASH const int hashMaxLength, \n\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t   IN_DATALENGTH const int dataLength )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize;\n\n\tassert( isWritePtrDynamic( hash, hashMaxLength ) );\n\tassert( hashMaxLength >= MIN_HASHSIZE && \\\n\t\t\thashMaxLength <= CRYPT_MAX_HASHSIZE );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\tassert( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\n\t/* Get the hash algorithm information if necessary */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\n\t/* Error handling: If there's a problem, return a zero hash.  We use \n\t   this strategy since this is a void function and so the usual \n\t   REQUIRES() predicate won't be effective.  Note that this can lead to \n\t   a false-positive match if we're called multiple times with invalid \n\t   input, in theory we could fill the return buffer with nonce data to \n\t   ensure that we never get a false-positive match but since this is a \n\t   should-never-occur condition anyway it's not certain whether forcing \n\t   a match or forcing a non-match is the preferred behaviour */\n\tif( data == NULL || dataLength <= 0 || dataLength >= MAX_BUFFER_SIZE || \\\n\t\thashMaxLength < MIN_HASHSIZE || hashMaxLength > hashSize || \\\n\t\thashMaxLength > CRYPT_MAX_HASHSIZE || hashFunctionAtomic == NULL )\n\t\t{\n\t\tmemset( hash, 0, hashMaxLength );\n\t\tretIntError_Void();\n\t\t}\n\n\t/* Hash the data and copy as many bytes as the caller has requested to\n\t   the output.  Typically they'll require only a subset of the full \n\t   amount since all that we're doing is transforming a variable-length\n\t   value to a fixed-length value for easy comparison purposes */\n\thashFunctionAtomic( hashBuffer, hashSize, data, dataLength );\n\tREQUIRES_V( rangeCheck( hashMaxLength, 1, hashSize ) );\n\tmemcpy( hash, hashBuffer, hashMaxLength );\n\tzeroise( hashBuffer, hashSize );\n\t}\n\n/* Compare two blocks of memory in a time-independent manner.  This is used \n   to avoid potential timing attacks on memcmp(), which bails out as soon as\n   it finds a mismatch */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN compareDataConstTime( IN_BUFFER( length ) const void *src,\n\t\t\t\t\t\t\t  IN_BUFFER( length ) const void *dest,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int length )\n\t{\n\tconst BYTE *srcPtr = src, *destPtr = dest;\n\tint value = 0, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isReadPtrDynamic( dest, length ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( length ) );\n\n\t/* Compare the two values in a time-independent manner */\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\tvalue |= srcPtr[ i ] ^ destPtr[ i ];\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( !value );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tStream Export/Import Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Export attribute or certificate data to a stream.  In theory we would\n   have to export this via a dynbuf and then write it to the stream but we \n   can save some overhead by writing it directly to the stream's buffer.\n   \n   Some attributes have a user-defined size (e.g. \n   CRYPT_IATTRIBUTE_RANDOM_NONCE) so we allow the caller to specify an \n   optional length parameter indicating how much of the attribute should be \n   exported */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exportAttr( INOUT STREAM *stream, \n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t   IN_LENGTH_INDEF const int length )\n\t\t\t\t\t\t\t/* Declared as LENGTH_INDEF because SHORT_INDEF\n\t\t\t\t\t\t\t   doesn't make sense */\n\t{\n\tMESSAGE_DATA msgData;\n\tvoid *dataPtr = NULL;\n\tint attrLength = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( sStatusOK( stream ) );\n\n\tREQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( isAttribute( attributeType ) || \\\n\t\t\t  isInternalAttribute( attributeType ) );\n\tREQUIRES( ( length == CRYPT_UNUSED ) || \\\n\t\t\t  ( length >= 8 && length < MAX_INTLENGTH_SHORT ) );\n\n\t/* Get access to the stream buffer if required */\n\tif( !sIsNullStream( stream ) )\n\t\t{\n\t\tif( length != CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* It's an explicit-length attribute, make sure that there's \n\t\t\t   enough room left in the stream for it */\n\t\t\tattrLength = length;\n\t\t\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's an implicit-length attribute whose maximum length is \n\t\t\t   defined by the stream size */\n\t\t\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, \n\t\t\t\t\t\t\t\t\t\t\t\t&attrLength );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Export the attribute directly into the stream buffer */\n\tsetMessageData( &msgData, dataPtr, attrLength );\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, attributeType );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, msgData.length, SSKIP_MAX );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr, \n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType )\n\t{\n\tassert( isWritePtr( streamPtr, sizeof( STREAM ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( isAttribute( attributeType ) || \\\n\t\t\t  isInternalAttribute( attributeType ) );\n\n\treturn( exportAttr( streamPtr, cryptHandle, attributeType, \\\n\t\t\t\t\t\tCRYPT_UNUSED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportVarsizeAttributeToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_FIXED( CRYPT_IATTRIBUTE_RANDOM_NONCE ) \\\n\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\tIN_RANGE( 8, 1024 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int attributeDataLength )\n\t{\n\tassert( isWritePtr( streamPtr, sizeof( STREAM ) ) );\n\n\tREQUIRES( cryptHandle == SYSTEM_OBJECT_HANDLE );\n\tREQUIRES( attributeType == CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tREQUIRES( attributeDataLength >= 8 && \\\n\t\t\t  attributeDataLength <= MAX_ATTRIBUTE_SIZE );\n\n\treturn( exportAttr( streamPtr, cryptHandle, attributeType, \n\t\t\t\t\t\tattributeDataLength ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportCertToStream( INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE cryptCertificate,\n\t\t\t\t\t\tIN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM *stream = streamPtr;\n\tvoid *dataPtr = NULL;\n\tint length = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( sStatusOK( stream ) );\n\n\tREQUIRES( isHandleRangeValid( cryptCertificate ) );\n\tREQUIRES( isEnumRange( certFormatType, CRYPT_CERTFORMAT ) );\n\n\t/* Get access to the stream buffer if required */\n\tif( !sIsNullStream( stream ) )\n\t\t{\n\t\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Export the certificate directly into the stream buffer */\n\tsetMessageData( &msgData, dataPtr, length );\n\tstatus = krnlSendMessage( cryptCertificate, IMESSAGE_CRT_EXPORT,\n\t\t\t\t\t\t\t  &msgData, certFormatType );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, msgData.length, SSKIP_MAX );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint importCertFromStream( INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *cryptCertificate,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\tconst int certDataLength,\n\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM *stream = streamPtr;\n\tvoid *dataPtr;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( sStatusOK( stream ) );\n\tassert( isWritePtr( cryptCertificate, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptOwner ) );\n\tREQUIRES( isEnumRange( certType, CRYPT_CERTTYPE ) );\n\tREQUIRES( certDataLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  certDataLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isFlagRangeZ( options, KEYMGMT ) && \\\n\t\t\t  ( options & ~KEYMGMT_FLAG_DATAONLY_CERT ) == 0 );\n\n\t/* Clear return value */\n\t*cryptCertificate = CRYPT_ERROR;\n\n\t/* Get access to the stream buffer and skip over the certificate data */\n\tstatus = sMemGetDataBlock( stream, &dataPtr, certDataLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, certDataLength, SSKIP_MAX );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Import the certificate directly from the stream buffer */\n\tsetMessageCreateObjectIndirectInfoEx( &createInfo, dataPtr, \n\t\t\t\t\t\tcertDataLength, certType,\n\t\t\t\t\t\t( options & KEYMGMT_FLAG_DATAONLY_CERT ) ? \\\n\t\t\t\t\t\t\tKEYMGMT_FLAG_DATAONLY_CERT : KEYMGMT_FLAG_NONE );\n\tcreateInfo.cryptOwner = iCryptOwner;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*cryptCertificate = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPublic-key Import Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_INT_ASN1\n\n/* Read a public key from an X.509 SubjectPublicKeyInfo record, creating the\n   context necessary to contain it in the process.  This is used by a variety\n   of modules including certificate-management, keysets, and crypto devices */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkKeyLength( INOUT STREAM *stream,\n\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t   const BOOLEAN hasAlgoParameters )\n\t{\n\tconst long startPos = stell( stream );\n\tint keyLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\tREQUIRES( hasAlgoParameters == TRUE || hasAlgoParameters == FALSE );\n\n\t/* ECC algorithms are a complete mess to handle because of the arbitrary\n\t   manner in which the algorithm parameters can be represented.  To deal\n\t   with this we skip the parameters and read the public key value, which \n\t   is a point on a curve stuffed in a variety of creative ways into an \n\t   BIT STRING.  Since this contains two values (the x and y coordinates) \n\t   we divide the lengths used by two to get an approximation of the \n\t   nominal key size */\n\tif( isEccAlgo( cryptAlgo ) )\n\t\t{\n\t\treadUniversal( stream );\t/* Skip algorithm parameters */\n\t\tstatus = readBitStringHole( stream, &keyLength, \n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE_ECCPOINT_THRESHOLD, \n\t\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\t\tif( cryptStatusOK( status ) && isShortECCKey( keyLength / 2 ) )\n\t\t\tstatus = CRYPT_ERROR_NOSECURE;\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\treturn( sseek( stream, startPos ) );\n\t\t}\n\n\t/* Read the key component that defines the nominal key size, either the \n\t   first algorithm parameter or the first public-key component */\n\tif( hasAlgoParameters )\n\t\t{\n\t\treadSequence( stream, NULL );\n\t\tstatus = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t\t  BER_INTEGER );\n\t\t}\n\telse\n\t\t{\n\t\treadBitStringHole( stream, NULL, MIN_PKCSIZE_THRESHOLD, DEFAULT_TAG );\n\t\treadSequence( stream, NULL );\n\t\tstatus = readGenericHole( stream, &keyLength, MIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t\t  BER_INTEGER );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check whether the nominal keysize is within the range defined as \n\t   being a weak key */\n\tif( isShortPKCKey( keyLength ) )\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\n\treturn( sseek( stream, startPos ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint iCryptReadSubjectPublicKey( INOUT TYPECAST( STREAM * ) void *streamPtr, \n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iPubkeyContext,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_DEVICE iCreatorHandle, \n\t\t\t\t\t\t\t\tconst BOOLEAN deferredLoad )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tCRYPT_CONTEXT iCryptContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM *stream = streamPtr;\n\tvoid *spkiPtr DUMMY_INIT_PTR;\n\tint spkiLength, length, status;\n\n\tassert( isReadPtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( iPubkeyContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( iCreatorHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCreatorHandle ) );\n\tREQUIRES( deferredLoad == TRUE || deferredLoad == FALSE );\n\n\t/* Clear return value */\n\t*iPubkeyContext = CRYPT_ERROR;\n\n\t/* Pre-parse the SubjectPublicKeyInfo, both to ensure that it's (at \n\t   least generally) valid before we go to the extent of creating an \n\t   encryption context to contain it and to get access to the \n\t   SubjectPublicKeyInfo data and algorithm information.  Because all \n\t   sorts of bizarre tagging exist due to things like CRMF we read the \n\t   wrapper as a generic hole rather than the more obvious SEQUENCE */\n\tstatus = getStreamObjectLength( stream, &spkiLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( stream, &spkiPtr, spkiLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readGenericHole( stream, NULL, \n\t\t\t\t\t\t\t\t  MIN_PKCSIZE_ECCPOINT_THRESHOLD, \n\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readAlgoIDparam( stream, &cryptAlgo, &length, \n\t\t\t\t\t\t\t  ALGOID_CLASS_PKC );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Perform minimal key-length checking.  We need to do this at this \n\t   point (rather than having it done implicitly in the \n\t   SubjectPublicKeyInfo read code) because a too-short key (or at least \n\t   too-short key data) will result in the kernel rejecting the \n\t   SubjectPublicKeyInfo before it can be processed, leading to a rather \n\t   misleading CRYPT_ERROR_BADDATA return status rather than the correct \n\t   CRYPT_ERROR_NOSECURE */\n\tstatus = checkKeyLength( stream, cryptAlgo,\n\t\t\t\t\t\t\t ( length > 0 ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Skip the remainder of the key components in the stream, first the\n\t   algorithm parameters (if there are any) and then the public-key \n\t   data */\n\tif( length > 0 )\n\t\treadUniversal( stream );\n\tstatus = readUniversal( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the public-key context and send the key data to it */\n\tsetMessageCreateObjectInfo( &createInfo, cryptAlgo );\n\tstatus = krnlSendMessage( iCreatorHandle, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCryptContext = createInfo.cryptHandle;\n\tsetMessageData( &msgData, spkiPtr, spkiLength );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, deferredLoad ? \\\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL : \\\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SPKI );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );\n\t\tif( status == CRYPT_ARGERROR_STR1 || \\\n\t\t\tstatus == CRYPT_ARGERROR_NUM1 )\n\t\t\t{\n\t\t\t/* If the key data was rejected by the kernel before it got to \n\t\t\t   the SubjectPublicKeyInfo read code (see the comment above) \n\t\t\t   then it'll be rejected with an argument-error code, which we\n\t\t\t   have to convert to a bad-data error before returning it to \n\t\t\t   the caller */\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t}\n\t\tif( cryptArgError( status ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Public-key load returned argError status %d\",\n\t\t\t\t\t\t status ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\t*iPubkeyContext = iCryptContext;\n\tassert( !checkContextCapability( iCryptContext, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_PRIVATE ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_INT_ASN1 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSafe Text-line Read Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )\n\n/* Read a line of text data ending in an EOL.  If we get more data than will \n   fit into the read buffer we discard it until we find an EOL.  As a \n   secondary concern we want to strip leading, trailing, and repeated \n   whitespace.  Leading whitespace is handled by setting the seen-whitespace \n   flag to true initially, this treats any whitespace at the start of the \n   line as superfluous and strips it.  Stripping of repeated whitespace is \n   also handled by the seenWhitespace flag, and stripping of trailing \n   whitespace is handled by walking back through any final whitespace once we \n   see the EOL. \n   \n   We optionally handle continued lines denoted by the MIME convention of a \n   semicolon as the last non-whitespace character by setting the \n   seenContinuation flag if we see a semicolon as the last non-whitespace \n   character.\n\n   Finally, we also need to handle generic DoS attacks.  If we see more than\n   MAX_LINE_LENGTH characters in a line we bail out */\n\n#define MAX_LINE_LENGTH\t\t4096\n\n/* The extra level of indirection provided by this function is necessary \n   because the the extended error information isn't accessible from outside \n   the stream code so we can't set it in formatTextLineError() in the usual \n   manner via a retExt().  Instead we call retExtFn() directly and then pass \n   the result down to the stream layer via an ioctl */\n\nCHECK_RETVAL_ERROR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int exitTextLineError( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  FORMAT_STRING const char *format, \n\t\t\t\t\t\t\t  const int value1, const int value2,\n\t\t\t\t\t\t\t  OUT_OPT_BOOL BOOLEAN *localError,\n\t\t\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tERROR_INFO errorInfo;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\tassert( localError == NULL || \\\n\t\t\tisReadPtr( localError, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* If the stream doesn't support extended error information, we're \n\t   done */\n\tif( localError == NULL )\n\t\treturn( status );\n\n\t/* The CRYPT_ERROR_BADDATA is a dummy code used in order to be able to \n\t   call retExtFn() to format the error string */\n\t*localError = TRUE;\n#ifdef USE_ERRMSGS\n\t( void ) retExtFn( CRYPT_ERROR_BADDATA, &errorInfo, format, \n\t\t\t\t\t   value1, value2 );\n#else\n\tmemset( &errorInfo, 0, sizeof( ERROR_INFO ) );\n#endif /* USE_ERRMSGS */\n\tsioctlSetString( stream, STREAM_IOCTL_ERRORINFO, &errorInfo, \n\t\t\t\t\t sizeof( ERROR_INFO ) );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readTextLine( READCHAR_FUNCTION readCharFunction, \n\t\t\t\t  INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t  OUT_BUFFER( lineBufferMaxLen, *lineBufferSize ) \\\n\t\t\t\t\t\tchar *lineBuffer,\n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int lineBufferMaxLen, \n\t\t\t\t  OUT_RANGE( 0, lineBufferMaxLen ) int *lineBufferSize, \n\t\t\t\t  OUT_OPT_BOOL BOOLEAN *localError,\n\t\t\t\t  const BOOLEAN allowContinuation )\n\t{\n\tBOOLEAN seenWhitespace, seenContinuation = FALSE;\n\tint totalChars, bufPos = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtr( streamPtr, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( lineBuffer, lineBufferMaxLen ) );\n\tassert( isWritePtr( lineBufferSize, sizeof( int ) ) );\n\tassert( localError == NULL || \\\n\t\t\tisWritePtr( localError, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( readCharFunction != NULL );\n\tREQUIRES( lineBufferMaxLen >= 16 && \\\n\t\t\t  lineBufferMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( allowContinuation == TRUE || allowContinuation == FALSE );\n\n\t/* Clear return values */\n\tmemset( lineBuffer, 0, min( 16, lineBufferMaxLen ) );\n\t*lineBufferSize = 0;\n\tif( localError != NULL )\n\t\t*localError = FALSE;\n\n\t/* Set the seen-whitespace flag initially to strip leading whitespace */\n\tseenWhitespace = TRUE;\n\n\t/* Read up to MAX_LINE_LENGTH chars.  Anything longer than this is \n\t   probably a DoS */\n\tLOOP_MAX( totalChars = 0, totalChars < MAX_LINE_LENGTH, totalChars++ )\n\t\t{\n\t\tint ch, status, LOOP_ITERATOR_ALT;\n\n\t\t/* Get the next input character */\n\t\tstatus = ch = readCharFunction( streamPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If it's an EOL or a continuation marker, strip trailing \n\t\t   whitespace */\n\t\tif( ch == '\\n' || ( allowContinuation && ch == ';' ) )\n\t\t\t{\n\t\t\t/* Strip trailing whitespace.  At this point it's all been\n\t\t\t   canonicalised so we don't need to check for anything other \n\t\t\t   than spaces */\n\t\t\tLOOP_LARGE_CHECKINC_ALT( bufPos > 0 && \\\n\t\t\t\t\t\t\t\t\t\tlineBuffer[ bufPos - 1 ] == ' ',\n\t\t\t\t\t\t\t\t\t bufPos-- );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\t}\n\n\t\t/* Process EOL */\n\t\tif( ch == '\\n' )\n\t\t\t{\n\t\t\t/* If we've seen a continuation marker, the line continues on \n\t\t\t   the next one */\n\t\t\tif( seenContinuation )\n\t\t\t\t{\n\t\t\t\tseenContinuation = FALSE;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* We're done */\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Ignore any additional decoration that may accompany EOLs */\n\t\tif( ch == '\\r' )\n\t\t\tcontinue;\n\n\t\t/* If we're over the maximum buffer size discard any further input\n\t\t   until we either hit EOL or exceed the DoS threshold at\n\t\t   MAX_LINE_LENGTH */\n\t\tif( bufPos >= lineBufferMaxLen )\n\t\t\t{\n\t\t\t/* If we've run off into the weeds (for example we're reading \n\t\t\t   binary data following the text header), bail out */\n\t\t\tif( !isValidTextChar( ch ) )\n\t\t\t\t{\n\t\t\t\treturn( exitTextLineError( streamPtr, \"Invalid character \"\n\t\t\t\t\t\t\t\t\t\t   \"0x%02X at position %d\", ch, \n\t\t\t\t\t\t\t\t\t\t   totalChars, localError,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ERROR_BADDATA ) );\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Process whitespace.  We can't use isspace() for this because it\n\t\t   includes all sorts of extra control characters that we don't want\n\t\t   to allow */\n\t\tif( ch == ' ' || ch == '\\t' )\n\t\t\t{\n\t\t\tif( seenWhitespace )\n\t\t\t\t{\n\t\t\t\t/* Ignore leading and repeated whitespace */\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\tch = ' ';\t/* Canonicalise whitespace */\n\t\t\t}\n\n\t\t/* Process any remaining chars */\n\t\tif( !isValidTextChar( ch ) )\n\t\t\t{\n\t\t\treturn( exitTextLineError( streamPtr, \"Invalid character \"\n\t\t\t\t\t\t\t\t\t   \"0x%02X at position %d\", ch, \n\t\t\t\t\t\t\t\t\t   totalChars, localError,\n\t\t\t\t\t\t\t\t\t   CRYPT_ERROR_BADDATA ) );\n\t\t\t}\n\t\tlineBuffer[ bufPos++ ] = intToByte( ch );\n\t\tENSURES( bufPos > 0 && bufPos <= totalChars + 1 );\n\t\t\t\t /* The 'totalChars + 1' is because totalChars is the loop\n\t\t\t\t    iterator and won't have been incremented yet at this \n\t\t\t\t\tpoint */\n\n\t\t/* Update the state variables.  If the character that we've just \n\t\t   processed was whitespace or if we've seen a continuation \n\t\t   character or we're processing whitespace after having seen a \n\t\t   continuation character (which makes it effectively leading \n\t\t   whitespace to be stripped), remember this */\n\t\tseenWhitespace = ( ch == ' ' ) ? TRUE : FALSE;\n\t\tseenContinuation = allowContinuation && \\\n\t\t\t\t\t\t   ( ch == ';' || \\\n\t\t\t\t\t\t     ( seenContinuation && seenWhitespace ) ) ? \\\n\t\t\t\t\t\t   TRUE : FALSE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( totalChars >= MAX_LINE_LENGTH )\n\t\t{\n\t\treturn( exitTextLineError( streamPtr, \"Text line too long, more \"\n\t\t\t\t\t\t\t\t   \"than %d characters\", MAX_LINE_LENGTH, 0, \n\t\t\t\t\t\t\t\t   localError, CRYPT_ERROR_OVERFLOW ) );\n\t\t}\n\t*lineBufferSize = bufPos;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_HTTP || USE_BASE64 || USE_SSH */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test code for the above functions */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )\n\n#include \"io/stream.h\"\n\nCHECK_RETVAL_RANGE( 0, 255 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE ch;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sread( stream, &ch, 1 );\n\treturn( cryptStatusError( status ) ? status : byteToInt( ch ) );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic BOOLEAN testReadLine( IN_BUFFER( dataInLength ) char *dataIn,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int dataInLength, \n\t\t\t\t\t\t\t IN_BUFFER( dataOutLength ) char *dataOut,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 1 ) const int dataOutLength,\n\t\t\t\t\t\t\t const BOOLEAN allowContinuation )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 16 + 8 ];\n\tint length, status;\n\n\tassert( isReadPtrDynamic( dataIn, dataInLength ) );\n\tassert( isReadPtrDynamic( dataOut, dataOutLength ) );\n\n\tREQUIRES_B( dataInLength >= 8 && dataInLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES_B( isShortIntegerRangeNZ( dataOutLength ) );\n\tREQUIRES_B( allowContinuation == TRUE || allowContinuation == FALSE );\n\n\tsMemPseudoConnect( &stream, dataIn, dataInLength );\n\tstatus = readTextLine( readCharFunction, &stream, buffer, 16, \n\t\t\t\t\t\t   &length, NULL, allowContinuation );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( length != dataOutLength || memcmp( buffer, dataOut, dataOutLength ) )\n\t\treturn( FALSE );\n\tsMemDisconnect( &stream );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_HTTP || USE_BASE64 || USE_SSH */\n\n#if defined( USE_BASE64 ) \n\nstatic BOOLEAN testBase64( void )\n\t{\n\tconst char *base64string = \"aaaaaaaaaaaaaaaaaaaaaaaa\";\n\tBYTE buffer[ 20 + 8 ];\n\tint inLength, outLength, decodedOutLength, status, LOOP_ITERATOR;\n\n\tLOOP_MED( inLength = 10, inLength < 24, inLength++ )\n\t\t{\n\t\t/* Skip non-decodable lengths */\n\t\tif( inLength == 13 || inLength == 17 || inLength == 21 )\n\t\t\tcontinue;\n\n\t\t/* Verify that the calculated decoded-length value matches the \n\t\t   actual decoded length */\n\t\tstatus = base64decodeLen( base64string, inLength, \n\t\t\t\t\t\t\t\t  &decodedOutLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = base64decode( buffer, 20, &outLength, base64string, \n\t\t\t\t\t\t\t   inLength, CRYPT_CERTFORMAT_NONE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( outLength != decodedOutLength )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B(  LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_BASE64 */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntAPI( void )\n\t{\n\t/* Test the non-trivial key check code */\n\tif( !checkNontrivialKey( \"\\x2E\\x19\\x76\\x57\\xDB\\x30\\xE6\\x26\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\x14\\xF3\\x3C\\x5A\\xB8\\x63\\x13\\xFB\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\x7B\\xE0\\xE4\\x14\\x5C\\x7C\\x2C\\x07\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\xD3\\x9C\\x16\\x37\\xAD\\x12\\x19\\xA2\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\x7F\\x6B\\x30\\xAD\\x02\\x83\\x96\\xF9\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\x79\\x92\\xF9\\xD1\\x75\\x43\\x56\\x87\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\x62\\xAF\\x14\\xCF\\x1F\\x5F\\xA7\\xC6\", 8 ) || \\\n\t\t!checkNontrivialKey( \"\\xAE\\x57\\xF3\\x63\\x45\\x03\\x2E\\x6B\", 8 ) )\n\t\treturn( FALSE );\n\tif( checkNontrivialKey( \"abcdefgh\", 8 ) || \\\n\t\tcheckNontrivialKey( \"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\", 8 ) )\n\t\treturn( FALSE );\n\n\t/* Test the entropy-check code */\n\tif( !checkEntropy( \"\\x2E\\x19\\x76\\x57\\xDB\\x30\\xE6\\x26\", 8 ) || \\\n\t\t!checkEntropy( \"\\x14\\xF3\\x3C\\x5A\\xB8\\x63\\x13\\xFB\", 8 ) || \\\n\t\t!checkEntropy( \"\\x7B\\xE0\\xE4\\x14\\x5C\\x7C\\x2C\\x07\", 8 ) || \\\n\t\t!checkEntropy( \"\\xD3\\x9C\\x16\\x37\\xAD\\x12\\x19\\xA2\", 8 ) || \\\n\t\t!checkEntropy( \"\\x7F\\x6B\\x30\\xAD\\x02\\x83\\x96\\xF9\", 8 ) || \\\n\t\t!checkEntropy( \"\\x79\\x92\\xF9\\xD1\\x75\\x43\\x56\\x87\", 8 ) || \\\n\t\t!checkEntropy( \"\\x62\\xAF\\x14\\xCF\\x1F\\x5F\\xA7\\xC6\", 8 ) || \\\n\t\t!checkEntropy( \"\\xAE\\x57\\xF3\\x63\\x45\\x03\\x2E\\x6B\", 8 ) )\n\t\treturn( FALSE );\n\tif( checkEntropy( \"\\xA5\\x5A\\xA5\\x5A\\xA5\\x5A\\xA5\\x5A\", 8 ) )\n\t\treturn( FALSE );\n\n\t/* Test the hash algorithm-strength code */\n\tif( isStrongerHash( CRYPT_ALGO_SHA1, CRYPT_ALGO_SHA2 ) || \\\n\t\t!isStrongerHash( CRYPT_ALGO_SHA2, CRYPT_ALGO_SHA1 ) || \\\n\t\tisStrongerHash( CRYPT_ALGO_MD5, CRYPT_ALGO_SHA2 ) || \\\n\t\t!isStrongerHash( CRYPT_ALGO_SHA2, CRYPT_ALGO_MD5 ) )\n\t\treturn( FALSE );\n\n\t/* Test the checksumming code */\n\tif( checksumData( \"12345678\", 8 ) != checksumData( \"12345678\", 8 ) || \\\n\t\tchecksumData( \"12345678\", 8 ) == checksumData( \"12345778\", 8 ) || \\\n\t\tchecksumData( \"12345678\", 8 ) == checksumData( \"12345\\xB7\" \"78\", 8 ) || \\\n\t\tchecksumData( \"12345678\", 8 ) == checksumData( \"12345\\x00\" \"78\", 8 ) )\n\t\treturn( FALSE );\n\n\t/* Test the base64 code */\n#if defined( USE_BASE64 ) \n\tif( !testBase64() )\n\t\treturn( FALSE );\n#endif /* USE_BASE64 */\n\n\t/* Test the text-line read code */\n#if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )\n\tif( !testReadLine( \"abcdefgh\\n\", 9, \"abcdefgh\", 8, FALSE ) || \\\n\t\t!testReadLine( \"abcdefghijklmnopq\\n\", 18, \n\t\t\t\t\t   \"abcdefghijklmnop\", 16, FALSE ) || \\\n\t\t!testReadLine( \" abcdefgh\\n\", 10, \"abcdefgh\", 8, FALSE ) || \\\n\t\t!testReadLine( \"abcdefgh \\n\", 10, \"abcdefgh\", 8, FALSE ) || \\\n\t\t!testReadLine( \" ab cdefgh \\n\", 12, \"ab cdefgh\", 9, FALSE ) || \\\n\t\t!testReadLine( \"   ab   cdefgh   \\n\", 18, \"ab cdefgh\", 9, FALSE ) )\n\t\treturn( FALSE );\n\tif( !testReadLine( \"abcdefgh\\r\\n\", 10, \"abcdefgh\", 8, FALSE ) || \\\n\t\t!testReadLine( \"abcdefgh\\r\\r\\n\", 11, \"abcdefgh\", 8, FALSE ) )\n\t\treturn( FALSE );\n\tif( testReadLine( \"   \\t   \\n\", 8, \"\", 1, FALSE ) || \\\n\t\ttestReadLine( \"abc\\x12\" \"efgh\\n\", 9, \"\", 1, FALSE ) )\n\t\treturn( FALSE );\n\tif( !testReadLine( \"abcdefgh;\\nabc\\n\", 14, \n\t\t\t\t\t   \"abcdefgh;\", 9, FALSE ) || \\\n\t\t!testReadLine( \"abcdefgh;\\nabc\\n\", 14, \n\t\t\t\t\t   \"abcdefgh;abc\", 12, TRUE ) || \\\n\t\t!testReadLine( \"abcdefgh; \\n abc\\n\", 16, \n\t\t\t\t\t   \"abcdefgh;abc\", 12, TRUE ) || \\\n\t\t!testReadLine( \"abcdefgh ; \\n abc\\n\", 17, \n\t\t\t\t\t   \"abcdefgh;abc\", 12, TRUE ) || \\\n\t\t!testReadLine( \"abcdefgh;abc\\nabc\\n\", 17, \n\t\t\t\t\t   \"abcdefgh;abc\", 12, TRUE ) )\n\t\treturn( FALSE );\n\tif( testReadLine( \"abcdefgh;\\n\", 10, \"\", 1, TRUE ) || \\\n\t\ttestReadLine( \"abcdefgh;\\n\\n\", 11, \"\", 1, TRUE ) || \\\n\t\ttestReadLine( \"abcdefgh;\\n \\n\", 12, \"\", 1, TRUE ) )\n\t\treturn( FALSE );\n#endif /* USE_HTTP || USE_BASE64 || USE_SSH */\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n"
  },
  {
    "path": "deps/cl345/misc/int_api.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Internal API Header File \t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _INTAPI_DEFINED\n\n#define _INTAPI_DEFINED\n\n/* Copy a string attribute to external storage, with various range checks\n   to follow the cryptlib external API semantics.  There are two variants\n   of this function depending on whether the result parameters are passed\n   in as discrete values or packed into a MESSAGE_DATA struct */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint attributeCopy( INOUT MESSAGE_DATA *msgData, \n\t\t\t\t   IN_BUFFER( attributeLength ) const void *attribute, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int attributeLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint attributeCopyParams( OUT_BUFFER_OPT( destMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t *destLength ) void *dest, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int destMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_SHORT_Z( destMaxLength ) \\\n\t\t\t\t\t\t\tint *destLength, \n\t\t\t\t\t\t IN_BUFFER_OPT( sourceLength ) const void *source, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int sourceLength );\n\n/* Check whether a password is valid or not.  Currently this just checks that\n   it contains at least one character, but stronger checking can be\n   substituted if required */\n\n#ifdef UNICODE_CHARS\n  #define isBadPassword( password ) \\\n\t\t  ( !isReadPtr( password, sizeof( wchar_t ) ) || \\\n\t\t    ( wcslen( password ) < 1 ) )\n#else\n  #define isBadPassword( password ) \\\n\t\t  ( !isReadPtr( password, 1 ) || \\\n\t\t    ( strlen( password ) < 1 ) )\n#endif /* Unicode vs. ASCII environments */\n\n/* Check whether a given algorithm is available for use.  This is performed\n   frequently enough that we have a special krnlSendMessage() wrapper\n   function for it rather than having to explicitly query the system\n   object */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN algoAvailable( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\n\n/* For a given algorithm pair, check whether the first is stronger than the\n   second */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN isStrongerHash( IN_ALGO const CRYPT_ALGO_TYPE algorithm1,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE algorithm2 );\n\n/* Check that a string has at least a minimal amount of entropy.  This is\n   used as a sanity-check on (supposedly) random keys before we load them */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkEntropy( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_KEYSIZE ) const int dataLength );\n\n/* Check whether a block of 64 bits of data is all-zeroes, typically used \n   for sanity-check functions that check contexts for validity */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isEmptyData( IN_BUFFER_C( 8 ) const BYTE data[ 8 ],\n\t\t\t\t\t IN_LENGTH_SHORT_Z const int dataLengthValue );\n\n/* Return a random small integer, used to perform lightweight randomisation \n   of various algorithms in order to make DoS attacks harder */\n\nCHECK_RETVAL_RANGE_NOERROR( 0, 32767 ) \\\nint getRandomInteger( void );\n\n/* Delay by a (relatively) large random amount of time, used to dither the \n   results of (failed) crypto operations to make timing attacks harder, \n   register a crypto failure (as well as inserting a random delay) in order \n   to catch possible crypto fault attacks, and insert a small random delay\n   to mask the exact timing of crypto operations */\n\nint delayRandom( void );\nint registerCryptoFailure( void );\nint insertCryptoDelay( void );\n\n/* Map one value to another, used to map values from one representation \n   (e.g. PGP algorithms or HMAC algorithms) to another (cryptlib algorithms\n   or the underlying hash used for the HMAC algorithm) */\n\ntypedef struct {\n\tint source, destination;\n\t} MAP_TABLE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nint mapValue( IN_INT_SHORT_Z const int srcValue,\n\t\t\t  OUT_INT_SHORT_Z int *destValue,\n\t\t\t  IN_ARRAY( mapTblSize ) const MAP_TABLE *mapTbl,\n\t\t\t  IN_RANGE( 1, 100 ) const int mapTblSize );\n\n/* Read a line of text from a stream.  The caller passes in a character-read\n   function callback that returns the next character from a supplied input\n   stream, and readTextLine() uses it to fetch the next line of input up to\n   an EOL.  The localError flag is set when the returned error code was\n   generated by readTextLine() itself, rather than being passed up from the\n   character-read function.  This allows the caller to report the errors\n   differently, for example a data-formatting error vs. a network I/O error.\n   \n   It would be nice if we could declare READCHARFUNCTION as taking a \n   STREAM * but this header gets included long before the stream header does\n   so the STREAM structure isn't visible at this point */\n\n#if defined( USE_HTTP ) || defined( USE_BASE64 ) || defined( USE_SSH )\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *READCHAR_FUNCTION )( INOUT void *streamPtr );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readTextLine( READCHAR_FUNCTION readCharFunction, \n\t\t\t\t  INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t  OUT_BUFFER( lineBufferMaxLen, *lineBufferSize ) \\\n\t\t\t\t\t\tchar *lineBuffer,\n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int lineBufferMaxLen, \n\t\t\t\t  OUT_RANGE( 0, lineBufferMaxLen ) int *lineBufferSize, \n\t\t\t\t  OUT_OPT_BOOL BOOLEAN *localError,\n\t\t\t\t  const BOOLEAN allowContinuation );\n#endif /* USE_HTTP || USE_BASE64 || USE_SSH */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tOS-specific Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get OS-specific values */\n\n#if defined( __WIN32__ ) || defined( __WINCE__ )\ntypedef enum { \n\tSYSVAR_NONE,\t\t\t/* No system variable */\n#if VC_LT_2005( _MSC_VER )\n\tSYSVAR_OSMAJOR,\t\t\t/* OS major version number */\n\tSYSVAR_OSMINOR,\t\t\t/* OS minor version number */\n#endif /* VC++ < 2005 */\n\tSYSVAR_HWINTRINS,\t\t/* Hardware crypto intrinsics */\n\tSYSVAR_PAGESIZE,\t\t/* System page size */\n\tSYSVAR_LAST\t\t\t\t/* Last valid system variable type */\n\t} SYSVAR_TYPE;\n#elif defined( __UNIX__ )\ntypedef enum { \n\tSYSVAR_NONE,\t\t\t/* No system variable */\n\tSYSVAR_HWINTRINS,\t\t/* Hardware crypto intrinsics */\n\tSYSVAR_HWCRYPT,\t\t\t/* Hardware crypto drivers */\n\tSYSVAR_PAGESIZE,\t\t/* System page size */\n\tSYSVAR_LAST\t\t\t\t/* Last valid system variable type */\n\t} SYSVAR_TYPE;\n#else\ntypedef enum { \n\tSYSVAR_NONE,\t\t\t/* No system variable */\n\tSYSVAR_HWINTRINS,\t\t/* Hardware crypto intrinsics */\n\tSYSVAR_LAST\t\t\t\t/* Last valid system variable type */\n\t} SYSVAR_TYPE;\n#endif /* OS-specific system variable types */\n\nCHECK_RETVAL \\\nint initSysVars( void );\nCHECK_RETVAL \\\nint getSysVar( IN_ENUM( SYSVAR ) const SYSVAR_TYPE type );\n\n/* Flags for SYSVAR_HWINTRINS capabilities */\n\n#define HWINTRINS_FLAG_NONE\t\t\t0x000\t/* No special HW capabilities */\n#define HWINTRINS_FLAG_RDTSC\t\t0x001\t/* x86 RDTSC instruction support */\n#define HWINTRINS_FLAG_XSTORE\t\t0x002\t/* VIA XSTORE instruction support */\n#define HWINTRINS_FLAG_XCRYPT\t\t0x004\t/* VIA XCRYPT instruction support */\n#define HWINTRINS_FLAG_XSHA\t\t\t0x008\t/* VIA XSHA instruction support */\n#define HWINTRINS_FLAG_MONTMUL\t\t0x010\t/* VIA bignum instruction support */\n#define HWINTRINS_FLAG_TRNG\t\t\t0x020\t/* AMD Geode LX TRNG MSR support */\n#define HWINTRINS_FLAG_AES\t\t\t0x040\t/* Intel AES instruction support */\n#define HWINTRINS_FLAG_RDRAND\t\t0x080\t/* Intel RDRAND instruction support */\n#define HWINTRINS_FLAG_RDSEED\t\t0x100\t/* Intel RDSEED instruction support */\n#define HWINTRINS_FLAG_MAX\t\t\t0x1FF\t/* Maximum possible flag value */\n\n/* Flags for SYSVAR_HWCRYPT capabilities */\n\n#define HWCRYPT_FLAG_NONE\t\t\t0x00\t/* No hardware crypto capability */\n#define HWCRYPT_FLAG_CRYPTDEV_3DES\t0x01\t/* BSD/Linux CryptoDev 3DES-CBC */\n#define HWCRYPT_FLAG_CRYPTDEV_AES\t0x02\t/* BSD/Linux CryptoDev AES-CBC */\n#define HWCRYPT_FLAG_CRYPTDEV_SHA1\t0x04\t/* BSD/Linux CryptoDev SHA-1 */\n#define HWCRYPT_FLAG_CRYPTDEV_SHA2\t0x08\t/* BSD/Linux CryptoDev SHA-2 */\n#define HWCRYPT_FLAG_LAST\t\t\t0x0F\t/* Maximum possible flag value */\n\n/* cryptlib-specific feature flags used in the keyFeatures extension in\n   certificates */\n\n#define KEYFEATURE_FLAG_NONE\t\t0x00\t/* No special key features */\n#define KEYFEATURE_FLAG_RESERVED\t0x01\t/* Reserved for backwards-compat.*/\n#define KEYFEATURE_FLAG_RAISSUED\t0x02\t/* Cert.was issued via an RA */\n#define KEYFEATURE_FLAG_MAX\t\t\t0x03\t/* Maximum possible flag value */\n\n/* Windows helper functions */\n\n#ifdef __WINDOWS__\n  /* Most versions of Windows support ACL-based access control mechanisms \n     for system objects, so when we create objects such as files and threads \n\t we give them an ACL that allows only the creator access.  The following \n\t functions return the security info needed when creating objects */\n  #ifdef __WIN32__\n\tCHECK_RETVAL_PTR \\\n\tvoid *initACLInfo( const int access );\n\tvoid *getACLInfo( INOUT_OPT void *securityInfoPtr );\n\tSTDC_NONNULL_ARG( ( 1 ) ) \\\n\tvoid freeACLInfo( IN void *securityInfoPtr );\n  #else\n\t#define initACLInfo( x )\tNULL\n\t#define getACLInfo( x )\t\tNULL\n\t#define freeACLInfo( x )\n  #endif /* __WIN32__ */\n\n  /* Safely load a DLL while avoid, if possible, malicious path-specific \n     trickery */\n  HMODULE WINAPI SafeLoadLibrary( IN_STRING LPCTSTR lpFileName );\n#endif /* __WINDOWS__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tString Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a value is a valid text character or not.  In almost all \n   cases for standard ASCII the isprint() restricts the input range to\n   0x20 ... 0x7E, we perform the explicit range check beforehand mostly to \n   ensure that the input range to isprint() isn't exceeded in cases where\n   it's implemented as a straight unchecked table lookup */\n\n#define isValidTextChar( value )\t( value >= 0x08 && value <= 0x7E && \\\n\t\t\t\t\t\t\t\t\t  isPrint( value ) )\n\n/* Compare two strings in a case-insensitive manner for those systems that\n   don't have this function.  These are then mapped to the abstract \n   functions strCompare() (with length) and strCompareZ() (zero-\n   terminated) */\n\n#if defined( __UNIX__ ) && !( defined( __CYGWIN__ ) )\n  #include <strings.h>\n  #define strnicmp\tstrncasecmp\n  #define stricmp\tstrcasecmp\n#elif defined( __WINCE__ )\n  #define strnicmp\t_strnicmp\n  #define stricmp\t_stricmp\n#elif defined( _MSC_VER ) \n  /* VC++ 8 and up warn about these being deprecated Posix functions and\n     require the ANSI/ISO-conformant _strXcmp */\n  #if _MSC_VER >= 1300 \n\t#define strnicmp _strnicmp\n\t#define stricmp\t_stricmp\n  #endif /* VC++ >= 8 */\n#elif defined( __ECOS__ ) || defined( __iOS__ )\n  #define strnicmp\tstrncasecmp\n  #define stricmp\tstrcasecmp\n#elif defined __PALMOS__\n  /* PalmOS has strcasecmp()/strncasecmp() but these aren't i18n-aware so we\n     have to use a system function instead */\n  #include <StringMgr.h>\n\n  #define strnicmp\tStrNCaselessCompare\n  #define stricmp\tStrCaselessCompare\n#elif defined( __TI_COMPILER_VERSION__ )\n  #include <strings.h>\n  #define strnicmp\tstrncasecmp\n  #define stricmp\tstrcasecmp\n#elif defined( __BEOS__ ) || defined( __IAR_SYSTEMS_ICC__ ) || \\\n\t  defined( __SMX__ ) || defined( __SYMBIAN32__ ) || \\\n\t  defined( __VxWorks___ )\n  int strnicmp( const char *src, const char *dest, const int length );\n  int stricmp( const char *src, const char *dest );\n\n  /* Make sure that we provide our own versions of the functions */\n  #define NO_NATIVE_STRICMP\n#endif /* OS-specific case-insensitive string compares */\n\n/* Sanitise a string before passing it back to the user.  This is used to\n   clear potential problem characters (for example control characters)\n   from strings passed back from untrusted sources.  The function returns a \n   pointer to the string to allow it to be used in the form \n   printf( \"..%s..\", sanitiseString( string, strLen ) ).  In addition it\n   formats the data to fit a fixed-length buffer.  If the string is longer \n   than the indicated buffer size it appends a '[...]' at the end of the \n   buffer to indicate that further data was truncated.\n   \n   To avoid lots of problems with compilers and static analysers, the input\n   argument is specified as a 'void *' rather than a 'BYTE *' because the\n   fact that it converts a 'BYTE *' into a 'char *' gives these tools\n   headaches */\n\t\t\t\t\t\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nchar *sanitiseString( INOUT_BUFFER( strMaxLen, strLen ) void *string, \n\t\t\t\t\t  IN_LENGTH_SHORT const int strMaxLen, \n\t\t\t\t\t  IN_LENGTH_SHORT const int strLen );\n\n/* Perform various string-processing operations */\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strFindCh( IN_BUFFER( strLen ) const char *str, \n\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t   IN_CHAR const int findCh );\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint strFindStr( IN_BUFFER( strLen ) const char *str, \n\t\t\t\tIN_LENGTH_SHORT const int strLen, \n\t\t\t\tIN_BUFFER( findStrLen ) const char *findStr, \n\t\t\t\tIN_LENGTH_SHORT const int findStrLen );\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strSkipWhitespace( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t\t   IN_LENGTH_SHORT const int strLen );\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strSkipNonWhitespace( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int strLen );\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strStripWhitespace( OUT_PTR_COND const char **newStringPtr, \n\t\t\t\t\t\tIN_BUFFER( strLen ) const char *string, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int strLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strExtract( OUT_PTR_COND const char **newStringPtr, \n\t\t\t\tIN_BUFFER( strLen ) const char *string, \n\t\t\t\tIN_LENGTH_SHORT_Z const int startOffset,\n\t\t\t\tIN_LENGTH_SHORT const int strLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint strGetNumeric( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t\t   OUT_INT_Z int *numericValue, \n\t\t\t\t   IN_RANGE( 0, 100 ) const int minValue, \n\t\t\t\t   IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint strGetHex( IN_BUFFER( strLen ) const char *str, \n\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t   OUT_INT_Z int *numericValue, \n\t\t\t   IN_RANGE( 0, 100 ) const int minValue, \n\t\t\t   IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN strIsPrintable( IN_BUFFER( strLen ) const void *str, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int strLen );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tError-handling Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle internal errors.  These follow a fixed pattern of \"throw an \n   exception, return an internal-error code\" (with a few exceptions for\n   functions that return a pointer or void).  There's also a \n   retExt_IntError() define in int_api.h for handling extended error \n   returns */\n\n#define INTERNAL_ERROR\t0\t/* Symbolic define for assertion failure */\n#define retIntError() \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( CRYPT_ERROR_INTERNAL ); \\\n\t\t}\n#define retIntError_Null() \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( NULL ); \\\n\t\t}\n#define retIntError_Boolean() \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( FALSE ); \\\n\t\t}\n#define retIntError_Void() \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn; \\\n\t\t}\n#define retIntError_Ext( value ) \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( value ); \\\n\t\t}\n#define retIntError_Dataptr() \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( DATAPTR_NULL ); \\\n\t\t}\n#define retIntError_Stream( stream ) \\\n\t\t{ \\\n\t\tDEBUG_DUMP_STACKTRACE(); \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( sSetError( stream, CRYPT_ERROR_INTERNAL ) ); \\\n\t\t}\n\n/* Check for an internal error.  This is required in situations where \n   supplementary information is returned as a by-reference parameter but\n   we can't rely on the value of the by-reference parameter because it\n   isn't reset to its default value until the internal-error checks have\n   been performed.  For example if we have a function:\n\n\tCHECK_RETVAL int foo( IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t  OUT_INT_OPT int *errorInfo )\n\t\t{\n\t\tREQUIRES( isValidHandle( cryptHandle ) );\n\n\t\t// Clear return value\n\t\t*errorInfo = CRYPT_OK;\n\n\t\t//...\n\t\t}\n\n   which is called as:\n\n\tstatus = foo( cryptHandle, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tswitch( errorInfo )\n\t\t\t{\n\t\t\t// ...\n\t\t\t}\n\t\t}\n\n   then we can't act on errorInfo if the returned status is \n   CRYPT_ERROR_INTERNAL because the exception may have been triggered \n   before the return value was cleared.\n\n   An alternative option to this explicit check would be to switch the order \n   of the exception-throwing checks and the clearing of return values, but \n   this both doesn't work in the case of wrapper functions where the check \n   is performed in the wrapper but the return value isn't cleared until the \n   actual function, and creates nasty catch-22's where we can't check the \n   validity of the by-reference parameter until it's already been written \n   to:\n\n\t// Clear return value\n\t*errorInfo = CRYPT_OK;\n\n\tREQUIRES( errorInfo != NULL );\n\n   Both options are ugly and error-prone, but having a requirement for the \n   caller to check for isInternalError() is relatively rare so it's the\n   one that we use here */\n\n#define isInternalError( status )\t( ( status ) == CRYPT_ERROR_INTERNAL )\n\n/* A struct to store extended error information.  This provides error info\n   above and beyond that provided by cryptlib error codes.  Since this \n   consumes a fair amount of memory, we make it conditional on USE_ERRMSGS\n   being defined and provide an alternative errorcode-only version if this\n   isn't enabled */\n\n#ifdef USE_ERRMSGS\n\ntypedef struct {\n\tBUFFER( MAX_ERRMSG_SIZE, errorStringLength ) \\\n\tchar errorString[ MAX_ERRMSG_SIZE + 8 ];\n\tint errorStringLength;\t\t\t/* Error message */\n\t} ERROR_INFO;\n\n/* When we're printing diagnostic messages we try and display a textual \n   description of an object rather than a numeric ID.  The following \n   function maps an ID to its name for display:\n\n\tgetObjectName( objectNameInfo,\n\t\t\t\t   FAILSAFE_ARRAYSIZE( objectNameInfo, OBJECT_NAME_INFO ),\n\t\t\t\t   objectID ); */\n\ntypedef struct {\n\tconst int objectType;\n\tconst char *objectName;\n\t} OBJECT_NAME_INFO;\n\nCHECK_RETVAL_PTR_NONNULL STDC_NONNULL_ARG( ( 1 ) ) \\\nconst char *getObjectName( IN_ARRAY( objectNameInfoSize ) \\\n\t\t\t\t\t\t\t\tconst OBJECT_NAME_INFO *objectNameInfo,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int objectNameInfoSize,\n\t\t\t\t\t\t   const int objectType );\n#else\n\ntypedef struct {\n\tint errorCode;\t\t\t\t\t/* Low-level error code */\n\t} ERROR_INFO;\n\n#endif /* USE_ERRMSGS */\n\n/* Prototypes for various extended error-handling functions.  retExt() \n   returns after setting extended error information for the object.  \n   \n   In addition to the standard retExt() we also have several extended-form \n   versions of the function that take additional error info parameters:\n\n\tretExtArgFn() is identical to ertExtFn() but passes through \n\t\tCRYPT_ARGERROR_xxx values, which are normally only present as leaked\n\t\tstatus codes from lower-level calls (and even then they should only\n\t\tever occur in 'can't-occur' error situations).\n\n\tretExtObj() takes a handle to an object that may provide additional \n\t\terror information, used when (for example) an operation references \n\t\ta keyset, where the keyset also contains extended error information.\n\n\tretExtStr() takes an additional error string pointer and is used in the\n\t\tsame way as retExtErr().\n\n\tretExtErr() takes a pointer to existing error info, used when (for\n\t\texample) a lower-level function has provided very low-level error \n\t\tinformation but the higher-level function that calls it needs to \n\t\tprovide its own more general error information on top of it.  This \n\t\tfunction is typically used when the caller wants to convert \n\t\tsomething like \"Low-level error string\" into \"High-level error \n\t\tstring: Low-level error string\".  errorInfoPtr and \n\t\texistingErrorInfoPtr can point to the same location.\n\tretExtErrAlt() is a variation of the above that appends the additional\n\t\terror information rather than prepending it */\n\n#ifdef USE_ERRMSGS\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid formatFingerprint( OUT_BUFFER_FIXED( fingerprintTextMaxLen ) \\\n\t\t\t\t\t\t\tchar *fingerprintText, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 32 ) const int fingerprintTextMaxLen,\n\t\t\t\t\t\tIN_BUFFER( fingerprintLen ) const BYTE *fingerprint,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int fingerprintLen );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid clearErrorString( OUT ERROR_INFO *errorInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint readErrorInfo( OUT ERROR_INFO *errorInfo, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE objectHandle );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid setErrorString( OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t\t IN_BUFFER( stringLength ) const char *string, \n\t\t\t\t\t IN_LENGTH_ERRORMESSAGE const int stringLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtFn( IN_ERROR const int status, \n\t\t\t  OUT ERROR_INFO *errorInfoPtr, \n\t\t\t  FORMAT_STRING const char *format, ... );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtArgFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t FORMAT_STRING const char *format, ... );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) STDC_PRINTF_FN( 4, 5 ) \\\nint retExtObjFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t IN_HANDLE const CRYPT_HANDLE extErrorObject, \n\t\t\t\t FORMAT_STRING const char *format, ... );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 5 ) ) STDC_PRINTF_FN( 5, 6 ) \\\nint retExtStrFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t IN_BUFFER( extErrorStringLength ) const char *extErrorString, \n\t\t\t\t IN_LENGTH_ERRORMESSAGE const int extErrorStringLength,\n\t\t\t\t FORMAT_STRING const char *format, ... );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) STDC_PRINTF_FN( 4, 5 ) \\\nint retExtErrFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t const ERROR_INFO *existingErrorInfoPtr, \n\t\t\t\t FORMAT_STRING const char *format, ... );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtErrAltFn( IN_ERROR const int status, \n\t\t\t\t\tINOUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t\tFORMAT_STRING const char *format, ... );\n#else\n  #define formatFingerprint( fingerprintText, fingerprintTextMaxLen, \\\n\t\t\t\t\t\t\t fingerprint, fingerprintLen );\n  #define clearErrorString( errorInfoPtr )\n  #define readErrorInfo( errorInfoPtr, objectHandle )\n  #define setErrorString( errorInfoPtr, string, stringLength );\n#endif /* USE_ERRMSGS */\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid copyErrorInfo( OUT ERROR_INFO *destErrorInfoPtr, \n\t\t\t\t\tconst ERROR_INFO *srcErrorInfoPtr );\n\n#ifdef USE_ERRMSGS\n  #define retExt( status, extStatus )\t\treturn retExtFn extStatus\n  #define retExtArg( status, extStatus )\treturn retExtArgFn extStatus\n  #define retExtObj( status, extStatus )\treturn retExtObjFn extStatus\n  #define retExtStr( status, extStatus )\treturn retExtStrFn extStatus \n  #define retExtErr( status, extStatus )\treturn retExtErrFn extStatus \n  #define retExtErrAlt( status, extStatus )\treturn retExtErrAltFn extStatus \n  #define retExt_IntError( status, extStatus ) \\\n\t\t{ \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn retExtFn extStatus; \\\n\t\t}\n#else\n  /* We're not using extended error information, just return the basic \n     status code */\n  #define retExt( status, extStatus )\t\treturn status\n  #define retExtArg( status, extStatus )\treturn status\n  #define retExtObj( status, extStatus )\treturn status\n  #define retExtStr( status, extStatus )\treturn status\n  #define retExtErr( status, extStatus )\treturn status\n  #define retExtErrAlt( status, extStatus )\treturn status\n  #define retExt_IntError( status, extStatus ) \\\n\t\t{ \\\n\t\tassert( INTERNAL_ERROR ); \\\n\t\treturn( status ); \\\n\t\t}\n#endif /* USE_ERRMSGS */\n\n/* Since this function works for all object types, we have to extract the\n   error info pointer from the object-specific data.  The following defines\n   do this for each object type */\n\n#define ENVELOPE_ERRINFO\t&envelopeInfoPtr->errorInfo\n#define KEYSET_ERRINFO\t\t&keysetInfoPtr->errorInfo\n#define SESSION_ERRINFO\t\t&sessionInfoPtr->errorInfo\n#define STREAM_ERRINFO\t\tstream->errorInfo\n#define NETSTREAM_ERRINFO\t&netStream->errorInfo\n\n/* Additional helper functions used to provide extended information for\n   error messages.  These are used both for long-form error messages and\n   debug diagnostics, so we need to enable them for both */\n\n#if defined( USE_ERRMSGS )\nCHECK_RETVAL \\\nconst char *getStatusName( IN_STATUS const int errorStatus );\nCHECK_RETVAL \\\nconst char *getAlgoName( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\nCHECK_RETVAL \\\nconst char *getKeyIDName( IN_KEYID const CRYPT_KEYID_TYPE keyID );\n#endif /* USE_ERRMSGS || debug mode */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tData Encode/Decode Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Special-case certificate function that works somewhat like the import \n   cert messages but reads certs by sending get_next_cert messages to the \n   message source and provides extended control over the format of the \n   imported object.  This isn't strictly speaking a certificate function but \n   the best (meaning least inappropriate) place to put it is with the cert-\n   management code */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint iCryptImportCertIndirect( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertificate,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iCertSource, \n\t\t\t\t\t\t\t  IN_ENUM( CRYPT_KEYID ) \\\n\t\t\t\t\t\t\t\tconst CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\t\t\t  IN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyIDlength,\n\t\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) const int options );\n\n/* Read a public key from an X.509 SubjectPublicKeyInfo record, creating the\n   context necessary to contain it in the process.  This is used by a variety\n   of modules including certificate-management, keyset, and crypto device. \n\n   The use of the void * instead of STREAM * is necessary because the STREAM\n   type isn't visible at the global level */\n\n#ifdef USE_INT_ASN1\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint iCryptReadSubjectPublicKey( INOUT TYPECAST( STREAM * ) void *streamPtr, \n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iPubkeyContext,\n\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_DEVICE iCreatorHandle, \n\t\t\t\t\t\t\t\tconst BOOLEAN deferredLoad );\n#endif /* USE_INT_ASN1 */\n\n/* Get information on encoded object data.  The first parameter for this\n   function is actually a STREAM *, but we can't use this here since\n   STREAM * hasn't been defined yet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint queryAsn1Object( INOUT void *streamPtr, OUT QUERY_INFO *queryInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint queryPgpObject( INOUT void *streamPtr, OUT QUERY_INFO *queryInfo );\n\n/* Export/import data to/from a stream without the overhead of going via a\n   dynbuf.  The first parameter for these functions is actually a STREAM *,\n   but we can't use this here since STREAM * hasn't been defined yet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportAttributeToStream( INOUT void *streamPtr, \n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportVarsizeAttributeToStream( INOUT void *streamPtr,\n\t\t\t\t\t\t\t\t\tIN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_FIXED( CRYPT_IATTRIBUTE_RANDOM_NONCE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeType,\n\t\t\t\t\t\t\t\t\tIN_RANGE( 8, 1024 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int attributeDataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint exportCertToStream( INOUT void *streamPtr,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE cryptCertificate,\n\t\t\t\t\t\tIN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE certFormatType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint importCertFromStream( INOUT TYPECAST( STREAM * ) void *streamPtr,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *cryptCertificate,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_USER iCryptOwner,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\tconst int certDataLength,\n\t\t\t\t\t\t  IN_FLAGS_Z( KEYMGMT ) const int options );\n\n/* base64/SMIME-en/decode routines */\n\n#ifdef USE_BASE64\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint base64checkHeader( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t   IN_DATALENGTH_MIN( MIN_CERTSIZE ) \\\n\t\t\t\t\t\t\tconst int dataLength,\n\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\t\t\tCRYPT_CERTFORMAT_TYPE *format,\n\t\t\t\t\t   OUT_DATALENGTH_Z int *startPos );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint base64encodeLen( IN_DATALENGTH_MIN( 10 ) const int dataLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encodedLength,\n\t\t\t\t\t IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint base64encode( OUT_BUFFER( destMaxLen, *destLen ) char *dest, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int destMaxLen,\n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( destMaxLen ) int *destLen,\n\t\t\t\t  IN_BUFFER( srcLen ) const void *src, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int srcLen,\n\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTTYPE ) \\\n\t\t\t\t\tconst CRYPT_CERTTYPE_TYPE certType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint base64decodeLen( IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t\t IN_DATALENGTH_MIN( 10 ) const int dataLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *decodedLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint base64decode( OUT_BUFFER( destMaxLen, *destLen ) void *dest, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int destMaxLen,\n\t\t\t\t  OUT_DATALENGTH_Z int *destLen,\n\t\t\t\t  IN_BUFFER( srcLen ) const BYTE *src, \n\t\t\t\t  IN_DATALENGTH_MIN( 10 ) const int srcLen,\n\t\t\t\t  IN_ENUM_OPT( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE format );\n#endif /* USE_BASE64 */\n\n/* User data en/decode routines */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isPKIUserValue( IN_BUFFER( encValLength ) const char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int encValLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint encodePKIUserValue( OUT_BUFFER( encValMaxLen, *encValLen ) char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int encValMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( encValMaxLen ) int *encValLen,\n\t\t\t\t\t\tIN_BUFFER( valueLen ) const BYTE *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int valueLen, \n\t\t\t\t\t\tIN_RANGE( 3, 4 ) const int noCodeGroups );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint decodePKIUserValue( OUT_BUFFER( valueMaxLen, *valueLen ) BYTE *value, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 10 ) const int valueMaxLen, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen,\n\t\t\t\t\t\tIN_BUFFER( encValLength ) const char *encVal, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int encValLength );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute List Manipulation Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In order to work with attribute lists of different types, we need a\n   means of accessing the type-specific previous and next pointers and the\n   attribute ID information.  The following callback function is passed to\n   all attribute-list manipulation functions and provides external access\n   to the required internal fields */\n\ntypedef enum {\n\tATTR_NONE,\t\t\t/* No attribute get type */\n\tATTR_CURRENT,\t\t/* Get details for current attribute */\n\tATTR_PREV,\t\t\t/* Get details for previous attribute */\n\tATTR_NEXT,\t\t\t/* Get details for next attribute */\n\tATTR_LAST\t\t\t/* Last valid attribute get type */\n\t} ATTR_TYPE;\n\ntypedef CHECK_RETVAL_PTR \\\n\t\tconst void * ( *GETATTR_FUNCTION ) \\\n\t\t\t\t\t\t\t( IN_OPT const void *attributePtr,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *groupID,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *attributeID,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *instanceID,\n\t\t\t\t\t\t\t  IN_ENUM( ATTR ) const ATTR_TYPE attrGetType );\ntypedef CHECK_RETVAL \\\n\t\tCONST_RETURN DATAPTR ( *DATAPTR_GETATTR_FUNCTION ) \\\n\t\t\t\t\t\t\t( IN_OPT const DATAPTR attributePtr,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *groupID,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *attributeID,\n\t\t\t\t\t\t\t  OUT_OPT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *instanceID,\n\t\t\t\t\t\t\t  IN_ENUM( ATTR ) const ATTR_TYPE attrGetType );\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindStart( IN_OPT const void *attributePtr,\n\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindEnd( IN_OPT const void *attributePtr,\n\t\t\t\t\t\tIN GETATTR_FUNCTION getAttrFunction );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFind( IN_OPT const void *attributePtr,\n\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindEx( IN_OPT const void *attributePtr,\n\t\t\t\t\t   IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE groupID,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE instanceID );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindNextInstance( IN_OPT const void *attributePtr,\n\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nconst void *attributeMoveCursor( IN_OPT const void *currentCursor,\n\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeMoveType,\n\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\tconst int cursorMoveType );\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFind( IN_OPT const DATAPTR attributePtr,\n\t\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID );\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFindEx( IN_OPT const DATAPTR attributePtr,\n\t\t\t\t\t\t\t\tIN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE groupID,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE instanceID );\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFindNextInstance( IN_OPT DATAPTR attributePtr,\n\t\t\t\t\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction );\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nCONST_RETURN DATAPTR dataptrAttributeMoveCursor( IN_OPT const DATAPTR currentCursor,\n\t\t\t\t\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeMoveType,\n\t\t\t\t\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int cursorMoveType );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTime Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In exceptional circumstances an attempt to read the time can fail,\n   returning either a garbage value (unsigned time_t) or -1 (signed time_t).\n   This can be problematic because many crypto protocols and operations use\n   the time at some point.  In order to protect against this, we provide a\n   safe time-read function that returns either a sane time value or zero,\n   and for situations where the absolute time isn't critical an approximate\n   current-time function that returns either a sane time value or an\n   approximate value hardcoded in at compile time.  Finally, we provide a\n   reliable time function used for operations such as signing certs and\n   timestamping that tries to get the time from a hardware time source if\n   one is available */\n\n#include <time.h>\n\ntime_t getTime( void );\ntime_t getApproxTime( void );\ntime_t getReliableTime( IN_HANDLE const CRYPT_HANDLE cryptHandle );\n\n/* Monotonic timer interface that protect against the system clock being \n   changed during a timing operation.  Even without deliberate fiddling\n   with the system clock, a timeout during a DST switch can cause something\n   like a 5s wait to turn into a 1hr 5s wait, so we have to abstract the\n   standard time API into a monotonic time API.  Since these functions are\n   purely peripheral to other operations (for example handling timeouts for\n   network I/O), they never fail but simply return good-enough results if\n   there's a problem (although they assert in debug mode).  This is because \n   we don't want to abort a network session just because we've detected \n   some trivial clock irregularity */\n\ntypedef struct {\n\ttime_t endTime, origTimeout, timeRemaining;\n\t} MONOTIMER_INFO;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setMonoTimer( OUT MONOTIMER_INFO *timerInfo, \n\t\t\t\t  IN_INT_Z const int duration );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid extendMonoTimer( INOUT MONOTIMER_INFO *timerInfo, \n\t\t\t\t\t  IN_INT const int duration );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkMonoTimerExpired( INOUT MONOTIMER_INFO *timerInfo );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkMonoTimerExpiryImminent( INOUT MONOTIMER_INFO *timerInfo,\n\t\t\t\t\t\t\t\t\t  IN_INT_Z const int timeLeft );\n\n/* Hardware timer read routine used for performance evaluation */\n\nCHECK_RETVAL_RANGE( 0, INT_MAX ) \\\nlong getTickCount( long startTime );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDynamic Memory Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Dynamic buffer management functions.  When reading variable-length\n   object data we can usually fit the data into a small fixed-length buffer, \n   but occasionally we have to cope with larger data amounts that require a \n   dynamically-allocated buffer.  The following routines manage this \n   process, dynamically allocating and freeing a larger buffer if required */\n\n#define DYNBUF_SIZE\t\t1024\n\ntypedef struct {\n\tBUFFER_FIXED( length ) \\\n\tvoid *data;\t\t\t\t\t\t/* Pointer to data */\n\tint length;\n\tBUFFER( DYNBUF_SIZE, length ) \\\n\tBYTE dataBuffer[ DYNBUF_SIZE + 8 ];\t/* Data buf.if size <= DYNBUF_SIZE */\n\t} DYNBUF;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dynCreate( OUT DYNBUF *dynBuf, \n\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dynCreateCert( OUT DYNBUF *dynBuf, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t   IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE formatType );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid dynDestroy( INOUT DYNBUF *dynBuf );\n\n#define dynLength( dynBuf )\t\t( dynBuf ).length\n#define dynData( dynBuf )\t\t( dynBuf ).data\n\n/* When allocating many little blocks of memory, especially in resource-\n   constrained systems, it's better if we pre-allocate a small memory pool\n   ourselves and grab chunks of it as required, falling back to dynamically\n   allocating memory later on if we exhaust the pool.  To use a custom\n   memory pool, the caller declares a state variable of type MEMPOOL_STATE,\n   calls initMemPool() to initialise the pool, and then calls getMemPool()\n   and freeMemPool() to allocate and free memory blocks.  The state pointer\n   is declared as a void * because to the caller it's an opaque memory block\n   while to the memPool routines it's structured storage */\n\ntypedef BYTE MEMPOOL_STATE[ 32 ];\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initMemPool( OUT void *statePtr, \n\t\t\t\t IN_BUFFER( memPoolSize ) void *memPool, \n\t\t\t\t IN_LENGTH_SHORT_MIN( 64 ) const int memPoolSize );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nvoid *getMemPool( INOUT void *statePtr, IN_LENGTH_SHORT const int size );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid freeMemPool( INOUT void *statePtr, IN void *memblock );\n\n/* Almost all objects require object-subtype-specific amounts of memory to\n   store object information.  In addition some objects such as certificates\n   contain arbitrary numbers of arbitrary-sized bits and pieces, most of\n   which are quite small.  To avoid having to allocate worst-case sized\n   blocks of memory for objects (a problem in embedded environments) or \n   large numbers of tiny little blocks of memory for certificate attributes, \n   we use variable-length structures in which the payload is stored after \n   the structure, with a pointer 'valueName' inside the structure pointing \n   into the payload storage (a convenient side-effect of this is that it \n   provides good spatial coherence when processing long lists of attributes).  \n   To make this easier to handle, we use macros to set up and tear down the \n   necessary variables.\n   \n   The use of 'storage[ 1 ]' means that the only element that's guaranteed \n   to be valid is 'storage[ 0 ]' under strict C99 definitions, however \n   declaring it as an unsized array leads to warnings of use of a zero-sized \n   array from many compilers so we leave it as 'storage[ 1 ]'.\n   \n   We have to insert an additional dummy value before the storage \n   declaration to ensure the correct alignment for the storage itself, in\n   particular on 64-bit platforms with the LLP64/LP64 memory model (which \n   means most current systems) the storage block may end up 32-bit aligned \n   if the compiler aligns to, at most, the nearest 32-bit integer value.  We \n   can't declare the storage as a long since under LLP64 it's only 32 bits \n   while a pointer is still 64 bits */\n\n#define DECLARE_VARSTRUCT_VARS \\\n\t\tint storageSize; \\\n\t\tvoid *_align_value; \\\n\t\tBUFFER_FIXED( storageSize ) \\\n\t\tBYTE storage[ 1 ]\n\n#define initVarStruct( structure, structureType, size, valueName ) \\\n\t\tmemset( structure, 0, sizeof( structureType ) ); \\\n\t\tstructure->valueName = structure->storage; \\\n\t\tstructure->storageSize = size\n\n#define copyVarStruct( destStructure, srcStructure, structureType, valueName ) \\\n\t\tmemcpy( destStructure, srcStructure, \\\n\t\t\t\tsizeof( structureType ) + srcStructure->storageSize ); \\\n\t\tif( destStructure->storageSize > 0 ) \\\n\t\t\tdestStructure->valueName = destStructure->storage;\n\n#define endVarStruct( structure, structureType ) \\\n\t\tzeroise( structure, sizeof( structureType ) + structure->storageSize )\n\n#define sizeofVarStruct( structure, structureType ) \\\n\t\t( sizeof( structureType ) + structure->storageSize )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChecksum/Hash Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash state information.  We can call the hash function with HASH_START,\n   HASH_CONTINUE, or HASH_END as required to process the input in parts */\n\ntypedef enum {\n\tHASH_STATE_NONE,\t\t\t\t/* No hash state */\n\tHASH_STATE_START,\t\t\t\t/* Begin hashing */\n\tHASH_STATE_CONTINUE,\t\t\t/* Continue existing hashing */\n\tHASH_STATE_END,\t\t\t\t\t/* Complete existing hashing */\n\tHASH_STATE_LAST\t\t\t\t\t/* Last valid hash option */\n\t} HASH_STATE_TYPE;\n\n/* The hash functions are used quite a bit so we provide an internal API for\n   them to avoid the overhead of having to set up an encryption context\n   every time they're needed.  These take a block of input data and hash it,\n   leaving the result in the output buffer.\n   \n   In addition to the hash-step operation, we provide a one-step atomic hash\n   function that processes a single data quantity and returns its hash.\n   \n   The data block is defined in terms of a long[] rather than a BYTE[] in\n   order to deal with alignment issues */\n\n#if defined( USE_SHA2_EXT ) \n  /* SHA2-384/512: ( 2 + 8 + 16 + 1 ) * sizeof( long long ) = 27 * 8 */\n  typedef long HASHINFO[ ( 27 * 2 ) + 2 ];\t/* ( 27 * 8 ) + 8 */\n#else\n  /* SHA-256: ( 2 + 8 + 16 + 1 ) * sizeof( long ) = 27 * 4 */\n  typedef long HASHINFO[ 27 + 2 ];\t\t\t/* ( 27 * 4 ) + 8 */\n#endif /* SYSTEM_64BIT */\n\ntypedef void ( *HASH_FUNCTION )( OUT_WHEN( hashState == HASH_STATE_START ) \\\n\t\t\t\t\t\t\t\t INOUT_WHEN( hashState != HASH_STATE_START ) \\\n\t\t\t\t\t\t\t\t\tHASHINFO hashInfo, \n\t\t\t\t\t\t\t\t OUT_BUFFER_OPT_FIXED( outBufMaxLength ) \\\n\t\t\t\t\t\t\t\t\tBYTE *outBuffer, \n\t\t\t\t\t\t\t\t IN_LENGTH_HASH_Z const int outBufMaxLength,\n\t\t\t\t\t\t\t\t IN_BUFFER_OPT( inLength ) const void *inBuffer, \n\t\t\t\t\t\t\t\t IN_LENGTH_Z const int inLength,\n\t\t\t\t\t\t\t\t IN_ENUM( HASH_STATE ) \\\n\t\t\t\t\t\t\t\t\tconst HASH_STATE_TYPE hashState );\ntypedef STDC_NONNULL_ARG( ( 1, 3 ) ) \\\n\t\tvoid ( *HASH_FUNCTION_ATOMIC )( OUT_BUFFER_FIXED( outBufMaxLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tBYTE *outBuffer, \n\t\t\t\t\t\t\t\t\t\tIN_LENGTH_HASH const int outBufMaxLength,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER( inLength ) const void *inBuffer, \n\t\t\t\t\t\t\t\t\t\tIN_LENGTH const int inLength );\n\nSTDC_NONNULL_ARG( ( 3 ) ) \\\nvoid getHashParameters( IN_ALGO const CRYPT_ALGO_TYPE hashAlgorithm,\n\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParams,\n\t\t\t\t\t\tOUT_PTR HASH_FUNCTION *hashFunction, \n\t\t\t\t\t\tOUT_OPT_LENGTH_SHORT_Z int *hashOutputSize );\nSTDC_NONNULL_ARG( ( 3 ) ) \\\nvoid getHashAtomicParameters( IN_ALGO const CRYPT_ALGO_TYPE hashAlgorithm,\n\t\t\t\t\t\t\t  IN_INT_SHORT_Z const int hashParams,\n\t\t\t\t\t\t\t  OUT_PTR HASH_FUNCTION_ATOMIC *hashFunctionAtomic, \n\t\t\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *hashOutputSize );\n\n/* Sometimes all that we need is a quick-reject check, usually performed to \n   lighten the load before we do a full hash check.  The following function \n   returns an integer checksum that can be used to weed out non-matches.  If \n   the checksum matches, we use the more heavyweight full hash of the data */\n\n#define HASH_DATA_SIZE\t16\n\nRETVAL_RANGE( MAX_ERROR, 0x7FFFFFFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint checksumData( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t  IN_DATALENGTH const int dataLength );\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid hashData( OUT_BUFFER_FIXED( hashMaxLength ) BYTE *hash, \n\t\t\t   IN_LENGTH_HASH const int hashMaxLength, \n\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t   IN_DATALENGTH const int dataLength );\n\n/* When we're comparing two cryptographic values, for example two MAC \n   values, and the developer's been careful to implement things really \n   badly, it may be possible to use a timing attack to guess a MAC value a\n   byte at a time by using a high-resolution timer to check at which byte\n   the memcmp() exits, thus guessing the MAC value a byte at a time in the\n   same way that the old TENEX password-guessing bug worked.  This seems\n   highly unlikely given that cryptlib implementations of protocols won't\n   allow themselves to be used as an oracle in this manner and for someone\n   using cryptlib to implement their own protocol the overhead of a trip\n   through the kernel will mask out a few clock cycles of difference in\n   the memcmp() at the end, but we defend against it anyway because no doubt\n   someone will eventually publish a CERT advisory on it being a problem in\n   some app somewhere */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN compareDataConstTime( IN_BUFFER( length ) const void *src,\n\t\t\t\t\t\t\t  IN_BUFFER( length ) const void *dest,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int length );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSigning/Key Wrap Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Signatures can have all manner of additional odds and ends associated \n   with them, the following structure contains these additional optional\n   values */\n\ntypedef struct {\n\t/* CMS additional signature information */\n\tBOOLEAN useDefaultAuthAttr;\t\t/* Use built-in default auth.attr */\n\tCRYPT_CERTIFICATE iAuthAttr;\t/* User-supplied auth.attributes */\n\tCRYPT_SESSION iTspSession;\t\t/* TSP session for timestamping */\n\n\t/* PGP additional signature information */\n\tint sigType;\t\t\t\t\t/* Signature type */\n\tBUFFER_OPT_FIXED( sigAttributeSize ) \\\n\tconst void *sigAttributes;\t\t/* Additional signature attributes */\n\tint sigAttributeSize;\n\n\t/* SSL/TLS additional signature information */\n\tCRYPT_CONTEXT iSecondHash;\t\t/* Second hash for dual sig.*/\n\t} SIGPARAMS;\n\n#define initSigParams( sigParams ) \\\n\t{ \\\n\tmemset( ( sigParams ), 0, sizeof( SIGPARAMS ) ); \\\n\t( sigParams )->iAuthAttr = ( sigParams )->iTspSession = \\\n\t\t( sigParams )->iSecondHash = CRYPT_ERROR; \\\n\t}\n\n#define initSigParamsPGP( sigParams, pgpSigType, pgpAttrs, pgpAttrSize ) \\\n\t{ \\\n\tmemset( ( sigParams ), 0, sizeof( SIGPARAMS ) ); \\\n\t( sigParams )->iAuthAttr = ( sigParams )->iTspSession = \\\n\t( sigParams )->iSecondHash = CRYPT_ERROR; \\\n\t( sigParams )->sigType = pgpSigType; \\\n\t( sigParams )->sigAttributes = pgpAttrs; \\\n\t( sigParams )->sigAttributeSize = pgpAttrSize; \\\n\t}\n\n/* Internal forms of various external functions.  These work with internal\n   resources that are marked as being inaccessible to the corresponding\n   external functions, and don't perform all the checking that their\n   external equivalents perform, since the parameters have already been\n   checked by cryptlib */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptCreateSignature( OUT_BUFFER_OPT( signatureMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\t   IN_DATALENGTH_Z const int signatureMaxLength,\n\t\t\t\t\t\t   OUT_DATALENGTH_Z int *signatureLength,\n\t\t\t\t\t\t   IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t   IN_OPT const SIGPARAMS *sigParams );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint iCryptCheckSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_HANDLE iSigCheckKey,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iHash2Context,\n\t\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_HANDLE *extraData );\n#ifdef USE_INT_CMS\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint iCryptImportKey( IN_BUFFER( encryptedKeyLength ) const void *encryptedKey, \n\t\t\t\t\t IN_LENGTH_SHORT const int encryptedKeyLength,\n\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iImportKey,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t OUT_OPT_HANDLE_OPT CRYPT_CONTEXT *iReturnedContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptExportKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \\\n\t\t\t\t\t\tvoid *encryptedKey, \n\t\t\t\t\t IN_DATALENGTH_Z const int encryptedKeyMaxLength,\n\t\t\t\t\t OUT_DATALENGTH_Z int *encryptedKeyLength,\n\t\t\t\t\t IN_ENUM( CRYPT_FORMAT ) \\\n\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,\n\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iExportKey );\n#endif /* USE_INT_CMS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnvelope Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_ENVELOPES\n\n/* General-purpose enveloping functions, used by various high-level\n   protocols */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 11 ) ) \\\nint envelopeWrap( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int inDataLength, \n\t\t\t\t  OUT_BUFFER( outDataMaxLength, *outDataLength ) void *outData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t  IN_ENUM_OPT( CRYPT_CONTENT ) const CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_HANDLE iPublicKey,\n\t\t\t\t  IN_BUFFER_OPT( passwordLength ) const void *password,\n\t\t\t\t  IN_LENGTH_SHORT_Z const int passwordLength,\n\t\t\t\t  OUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 9 ) ) \\\nint envelopeUnwrap( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t\tIN_DATALENGTH_MIN( 16 ) const int inDataLength,\n\t\t\t\t\tOUT_BUFFER( outDataMaxLength, *outDataLength ) void *outData, \n\t\t\t\t\tIN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t\tOUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iPrivKey,\n\t\t\t\t\tIN_BUFFER_OPT( passwordLength ) const void *password,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int passwordLength,\n\t\t\t\t\tOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint envelopeSign( IN_BUFFER_OPT( inDataLength ) const void *inData, \n\t\t\t\t  IN_DATALENGTH_Z const int inDataLength,\n\t\t\t\t  OUT_BUFFER( outDataMaxLength, *outDataLength ) void *outData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t  IN_ENUM_OPT( CRYPT_CONTENT ) const CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iSigKey,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t  OUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 7 ) ) \\\nint envelopeSigCheck( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int inDataLength,\n\t\t\t\t\t  OUT_BUFFER( outDataMaxLength, *outDataLength ) void *outData, \n\t\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iSigCheckKey,\n\t\t\t\t\t  OUT_STATUS int *sigResult, \n\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iSigningCert,\n\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCmsAttributes,\n\t\t\t\t\t  OUT ERROR_INFO *errorInfo );\n#endif /* USE_ENVELOPES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tBignum Manipulation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in context/ctx_bnrw.c, used in the ASN.1/misc \n   read/write routines */\n\ntypedef enum {\n\tKEYSIZE_CHECK_NONE,\t\t/* Don't check for short key sizes */\n\t\tKEYSIZE_CHECK_SPECIAL_NONE = KEYSIZE_CHECK_NONE,\n\tKEYSIZE_CHECK_PKC,\t\t/* Check for a short PKC key */\n\tKEYSIZE_CHECK_ECC,\t\t/* Check for a short ECC key */\n\t\tKEYSIZE_CHECK_LAST = KEYSIZE_CHECK_ECC + 1,\n\t\t\t\t\t\t\t/* Last valid normal check type */\n\tKEYSIZE_CHECK_SPECIAL,\t/* Allow slightly oversize keys for DLP */\n\tKEYSIZE_CHECK_SPECIAL_LAST\t/* Last valid check type */\n\t} KEYSIZE_CHECK_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint importBignum( INOUT TYPECAST( BIGNUM * ) void *bignumPtr, \n\t\t\t\t  IN_BUFFER( length ) const void *buffer, \n\t\t\t\t  IN_LENGTH_SHORT const int length,\n\t\t\t\t  IN_LENGTH_PKC const int minLength, \n\t\t\t\t  IN_RANGE( 1, CRYPT_MAX_PKCSIZE + 8 ) \\\n\t\t\t\t\tconst int maxLength,\t\n\t\t\t\t\t/* See DLP_OVERFLOW_SIZE = 8 in context.h */\n\t\t\t\t  IN_OPT TYPECAST( BIGNUM * ) const void *maxRangePtr,\n\t\t\t\t  IN_ENUM_OPT( KEYSIZE_CHECK_SPECIAL ) \\\n\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint exportBignum( OUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength, \n\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) int *dataLength,\n\t\t\t\t  IN TYPECAST( BIGNUM * ) const void *bignumPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nBOOLEAN verifyBignumImport( TYPECAST( const BIGNUM * ) const void *bignumPtr, \n\t\t\t\t\t\t\tIN_BUFFER( length ) const void *buffer, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int length );\n#if defined( USE_ECDH ) || defined( USE_ECDSA ) \nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint importECCPoint( INOUT void *bignumPtr1, \n\t\t\t\t\tINOUT void *bignumPtr2, \n\t\t\t\t    IN_BUFFER( length ) const void *buffer, \n\t\t\t\t    IN_LENGTH_SHORT const int length,\n\t\t\t\t\tIN_LENGTH_PKC const int minLength, \n\t\t\t\t\tIN_LENGTH_PKC const int maxLength, \n\t\t\t\t\tIN_LENGTH_PKC const int fieldSize,\n\t\t\t\t\tIN_OPT const void *maxRangePtr,\n\t\t\t\t\tIN_ENUM( KEYSIZE_CHECK ) \\\n\t\t\t\t\t\tconst KEYSIZE_CHECK_TYPE checkType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 4, 5 ) ) \\\nint exportECCPoint( OUT_BUFFER_OPT( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\tOUT_LENGTH_BOUNDED_PKC_Z( dataMaxLength ) int *dataLength,\n\t\t\t\t\tIN const void *bignumPtr1, \n\t\t\t\t\tIN const void *bignumPtr2,\n\t\t\t\t\tIN_LENGTH_PKC const int fieldSize );\n#endif /* USE_ECDH || USE_ECDSA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSignature Creation/Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in mechs/sign_x509.c, used by certificates and\n   sessions.  In the standard PKIX tradition there are a whole range of \n   b0rken PKI protocols that couldn't quite manage a cut & paste of two \n   lines of text, adding all sorts of unnecessary extra tagging and wrappers \n   to the signature.  \n   \n   The encoding of these odds and ends is handled via the X509SIG_FORMATINFO.  \n   The basic form allows a user-supplied tag and an indication of whether \n   it's explicitly or implicitly tagged.  If the explicitTag flag is clear \n   the tag is encoded as [n] { ... }.  If it's set, it's encoded as \n   [n] { SEQUENCE { ... }}.  \n   \n   In addition the extraLength field allows for the optional insertion of \n   extra data by the caller, with the wrapper length being written to \n   include the extraLength, whose payload can then be appended by the \n   caller */\n\ntypedef struct {\n\tint tag;\t\t\t\t/* Tag for signature */\n\tBOOLEAN isExplicit;\t\t/* Whether tag is expicit */\n\tint extraLength;\t\t/* Optional length for further data */\n\t} X509SIG_FORMATINFO;\n\n#define setX509FormatInfo( formatInfo, formatTag, formatIsExplicit ) \\\n\t\tmemset( formatInfo, 0, sizeof( X509SIG_FORMATINFO ) ); \\\n\t\t( formatInfo )->tag = ( formatTag ); \\\n\t\t( formatInfo )->isExplicit = ( formatIsExplicit )\n\n/* Create and verify an X.509-style signature, with optional extra odds and\n   ends as specified in various PKI protocols */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint createX509signature( OUT_BUFFER( signedObjectMaxLength, \\\n\t\t\t\t\t\t\t\t\t *signedObjectLength ) \\\n\t\t\t\t\t\t\tvoid *signedObject, \n\t\t\t\t\t\t IN_DATALENGTH_Z const int signedObjectMaxLength, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *signedObjectLength,\n\t\t\t\t\t\t IN_BUFFER( objectLength ) const void *object, \n\t\t\t\t\t\t IN_DATALENGTH const int objectLength,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t IN_OPT const X509SIG_FORMATINFO *formatInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkX509signature( IN_BUFFER( signedObjectLength ) const void *signedObject, \n\t\t\t\t\t\tIN_DATALENGTH const int signedObjectLength,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\t\tIN_OPT const X509SIG_FORMATINFO *formatInfo );\n\n/* Create and verify a raw signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint createRawSignature( OUT_BUFFER( sigMaxLength, *signatureLength ) \\\n\t\t\t\t\t\t\tvoid *signature, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\t\tconst int sigMaxLength, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( sigMaxLength ) \\\n\t\t\t\t\t\t\tint *signatureLength, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iHashContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint checkRawSignature( IN_BUFFER( signatureLength ) const void *signature, \n\t\t\t\t\t   IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iSigCheckContext,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iHashContext );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Miscellaneous functions that need to be prototyped here (or at least in \n   some globally-visible header) in order for them to be visible in the \n   external modules that reference them */ \n\n/* Prototypes for functions in context/key_wr.c, used by devices */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 6 ) ) \\\nint writeFlatPublicKey( OUT_BUFFER_OPT( bufMaxSize, *bufSize ) void *buffer, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int bufMaxSize, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( bufMaxSize ) int *bufSize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t\tIN_RANGE( 0, 100 ) const int intParam,\n\t\t\t\t\t\tIN_BUFFER( component1Length ) const void *component1, \n\t\t\t\t\t\tIN_LENGTH_PKC const int component1Length,\n\t\t\t\t\t\tIN_BUFFER( component2Length ) const void *component2, \n\t\t\t\t\t\tIN_LENGTH_PKC const int component2Length,\n\t\t\t\t\t\tIN_BUFFER_OPT( component3Length ) const void *component3, \n\t\t\t\t\t\tIN_LENGTH_PKC_Z const int component3Length,\n\t\t\t\t\t\tIN_BUFFER_OPT( component4Length ) const void *component4, \n\t\t\t\t\t\tIN_LENGTH_PKC_Z const int component4Length );\n\n/* Prototypes for functions in cryptctx.c, used in numerous other modules */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkContextCapability( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\tIN_ENUM( MESSAGE_CHECK ) \\\n\t\t\t\t\t\t\t\t\tconst MESSAGE_CHECK_TYPE checkType );\n\n/* Prototypes for functions in cryptcrt.c, used by devices, and a generic \n   one used by anything that fetches a certificate */\n\n#if defined( USE_CERTIFICATES ) || defined( USE_PSEUDOCERTIFICATES )\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createCertificateIndirect( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,\n\t\t\t\t\t\t\t   STDC_UNUSED const void *auxDataPtr, \n\t\t\t\t\t\t\t   STDC_UNUSED const int auxValue );\n#endif /* USE_CERTIFICATES || USE_PSEUDOCERTIFICATES */\n\n#ifdef USE_CERTIFICATES\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint iCryptVerifyID( IN_HANDLE const CRYPT_CERTIFICATE iCertificate,\n\t\t\t\t\tIN_ENUM( CRYPT_KEYID ) const CRYPT_KEYID_TYPE keyIDtype,\n\t\t\t\t\tIN_BUFFER( keyIDlength ) const void *keyID, \n\t\t\t\t\tIN_LENGTH_SHORT const int keyIDlength );\n#endif /* USE_CERTIFICATES */\n#endif /* _INTAPI_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/int_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Internal Attribute-list Manipulation API\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n/* The minimum size of an attribute-list element (in this case for \n   sessions), used for error checking in debug mode.  The values are various \n   ints and pointers, and the 'previous' and 'next' pointer for the list \n   itself */\n\n#define MIN_ATTRLIST_SIZE\t( ( 7 * sizeof( int ) ) + \\\n\t\t\t\t\t\t\t  ( 2 * sizeof( void * ) ) )\n\n/* Movement codes for the attribute cursor */\n\ntypedef enum {\n\tCURSOR_MOVE_NONE,\t\t/* No movement type */\n\tCURSOR_MOVE_START,\t\t/* Move to first attribute */\n\tCURSOR_MOVE_PREV,\t\t/* Move to previous attribute */\n\tCURSOR_MOVE_NEXT,\t\t/* Move to next attribute */\n\tCURSOR_MOVE_END,\t\t/* Move to last attribute */\n\tCURSOR_MOVE_LAST\t\t/* Last possible move type */\n\t} CURSOR_MOVE_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Location Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the start and end of an attribute group from an attribute within\n   the group */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindStart( IN_OPT const void *attributePtr,\n\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE groupID;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( attributePtr == NULL || \\\n\t\t\tisReadPtr( attributePtr, MIN_ATTRLIST_SIZE ) );\n\t\n\tREQUIRES_N( getAttrFunction != NULL );\n\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Move backwards until we find the start of the attribute */\n\tif( getAttrFunction( attributePtr, &groupID, NULL, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( groupID != CRYPT_ATTRIBUTE_NONE );\n\tLOOP_MAX( iterationCount = 0, iterationCount < FAILSAFE_ITERATIONS_MAX, \n\t\t\t  iterationCount++ )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE prevGroupID;\n\t\tconst void *prevPtr;\n\n\t\tprevPtr = getAttrFunction( attributePtr, &prevGroupID, NULL, NULL,\n\t\t\t\t\t\t\t\t   ATTR_PREV );\n\t\tif( prevPtr == NULL || prevGroupID != groupID )\n\t\t\t{\n\t\t\t/* We've reached the start of the list or a different attribute\n\t\t\t   group, this is the start of the current group */\n\t\t\tbreak;\n\t\t\t}\n\t\tattributePtr = prevPtr;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\treturn( ( void * ) attributePtr );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindEnd( IN_OPT const void *attributePtr,\n\t\t\t\t\t\tIN GETATTR_FUNCTION getAttrFunction )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE groupID;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( attributePtr == NULL || \\\n\t\t\tisReadPtr( attributePtr, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Move forwards until we're just before the start of the next\n\t   attribute */\n\tif( getAttrFunction( attributePtr, &groupID, NULL, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( groupID != CRYPT_ATTRIBUTE_NONE );\n\tLOOP_MAX( iterationCount = 0, iterationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE nextGroupID;\n\t\tconst void *nextPtr;\n\n\t\tnextPtr = getAttrFunction( attributePtr, &nextGroupID, NULL, NULL,\n\t\t\t\t\t\t\t\t   ATTR_NEXT );\n\t\tif( nextPtr == NULL || nextGroupID != groupID )\n\t\t\t{\n\t\t\t/* We've reached the end of the list or a different attribute\n\t\t\t   group, this is the end of the current group */\n\t\t\tbreak;\n\t\t\t}\n\t\tattributePtr = nextPtr;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\treturn( ( void * ) attributePtr );\n\t}\n\n/* Find an attribute in a list of attributes */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFind( IN_OPT const void *attributePtr,\n\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE currAttributeID;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( attributePtr == NULL || \\\n\t\t\tisReadPtr( attributePtr, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( isAttribute( attributeID ) || \\\n\t\t\t\tisInternalAttribute( attributeID ) );\n\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Find the attribute in the list */\n\tif( getAttrFunction( attributePtr, NULL, &currAttributeID, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( currAttributeID != CRYPT_ATTRIBUTE_NONE );\n\tLOOP_MAX( iterationCount = 0, \n\t\t\t  attributePtr != NULL && currAttributeID != attributeID && \\\n\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\tattributePtr = getAttrFunction( attributePtr, NULL,\n\t\t\t\t\t\t\t\t\t\t&currAttributeID, NULL,\n\t\t\t\t\t\t\t\t\t\tATTR_NEXT );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\treturn( ( void * ) attributePtr );\n\t}\n\n/* An extended form of the standard find-attribute function that searches \n   either by attribute group or by attribute + attribute-instance (the\n   case of search-by-attribute is handled through findAttribute(), and the\n   other combinations aren't valid) */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindEx( IN_OPT const void *attributePtr,\n\t\t\t\t\t   IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE groupID,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE instanceID )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE currAttributeID, currInstanceID;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( attributePtr == NULL || \\\n\t\t\tisReadPtr( attributePtr, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( groupID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t\tisAttribute( groupID ) || \\\n\t\t\t\tisInternalAttribute( groupID ) );\n\tREQUIRES_N( attributeID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t\tisAttribute( attributeID ) || \\\n\t\t\t\tisInternalAttribute( attributeID ) );\n\tREQUIRES_N( instanceID == CRYPT_ATTRIBUTE_NONE || \\\n\t\t\t\tisAttribute( instanceID ) || \\\n\t\t\t\tisInternalAttribute( instanceID ) );\n\tREQUIRES_N( ( groupID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t  attributeID == CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t  instanceID == CRYPT_ATTRIBUTE_NONE ) || \\\n\t\t\t\t( groupID == CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t  attributeID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t  instanceID != CRYPT_ATTRIBUTE_NONE ) );\n\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Find the attribute group if required */\n\tif( groupID != CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE currGroupID;\n\n\t\tif( getAttrFunction( attributePtr, &currGroupID, NULL, NULL, \n\t\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\t\treturn( NULL );\n\t\tENSURES_N( currGroupID != CRYPT_ATTRIBUTE_NONE );\n\t\tLOOP_MAX( iterationCount = 0, \n\t\t\t\t  attributePtr != NULL && currGroupID != groupID && \\\n\t\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t\t  iterationCount++ )\n\t\t\t{\n\t\t\tattributePtr = getAttrFunction( attributePtr, &currGroupID, \n\t\t\t\t\t\t\t\t\t\t\tNULL, NULL, ATTR_NEXT );\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\t\treturn( ( void * ) attributePtr );\n\t\t}\n\n\t/* Find the attribute */\n\tif( getAttrFunction( attributePtr, NULL, &currAttributeID, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( currAttributeID != CRYPT_ATTRIBUTE_NONE );\n\tLOOP_MAX( iterationCount = 0, \n\t\t\t  attributePtr != NULL && currAttributeID != attributeID && \\\n\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\tattributePtr = getAttrFunction( attributePtr, NULL,\n\t\t\t\t\t\t\t\t\t\t&currAttributeID, NULL,\n\t\t\t\t\t\t\t\t\t\tATTR_NEXT );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Find the attribute instance */\n\tif( getAttrFunction( attributePtr, NULL, &currAttributeID, \n\t\t\t\t\t\t &currInstanceID, ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( currAttributeID != CRYPT_ATTRIBUTE_NONE );\n\tLOOP_MAX( iterationCount = 0, \n\t\t\t  attributePtr != NULL && currAttributeID == attributeID && \\\n\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX, \n\t\t\t  iterationCount++ )\n\t\t{\n\t\tif( currInstanceID == instanceID )\n\t\t\treturn( ( void * ) attributePtr );\n\t\tattributePtr = getAttrFunction( attributePtr, NULL,\n\t\t\t\t\t\t\t\t\t\t&currAttributeID, &currInstanceID,\n\t\t\t\t\t\t\t\t\t\tATTR_NEXT );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\treturn( NULL );\n\t}\n\n/* Find the next instance of an attribute in an attribute group.  This is\n   used to step through multiple instances of an attribute, for example in\n   a cert extension containing a SEQUENCE OF <attribute> */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) ) \\\nvoid *attributeFindNextInstance( IN_OPT const void *attributePtr,\n\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE groupID, attributeID;\n\tCRYPT_ATTRIBUTE_TYPE currGroupID, currAttributeID;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( attributePtr == NULL || \\\n\t\t\tisReadPtr( attributePtr, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\n\tif( attributePtr == NULL )\n\t\treturn( NULL );\n\n\t/* Skip the current field */\n\tif( getAttrFunction( attributePtr, &groupID, &attributeID, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( groupID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t   attributeID != CRYPT_ATTRIBUTE_NONE );\n\tattributePtr = getAttrFunction( attributePtr, &currGroupID, \n\t\t\t\t\t\t\t\t\t&currAttributeID, NULL, ATTR_NEXT );\n\tif( attributePtr == NULL )\n\t\t{\n\t\t/* No next attribute, we're done */\n\t\treturn( NULL );\n\t\t}\n\tENSURES_N( currGroupID != CRYPT_ATTRIBUTE_NONE );\n\n\t/* Step through the remaining attributes in the group looking for\n\t   another occurrence of the current attribute */\n\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t  attributePtr != NULL && currGroupID == groupID && \\\n\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\tif( currAttributeID == attributeID )\n\t\t\treturn( ( void * ) attributePtr );\n\t\tattributePtr = getAttrFunction( attributePtr, &currGroupID,\n\t\t\t\t\t\t\t\t\t\t&currAttributeID, NULL,\n\t\t\t\t\t\t\t\t\t\tATTR_NEXT );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\n\t/* We couldn't find another instance of the attribute in this group */\n\treturn( NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tAttribute Cursor Movement Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Moving the cursor by attribute group is a bit more complex than just \n   stepping forwards or backwards along the attribute list.  First we have \n   to find the start or end of the current group.  Then we move to the start \n   of the previous (via ATTR_PREV and attributeFindStart()), or start of the\n   next (via ATTR_NEXT) group beyond that.  This has the effect of moving us \n   from anywhere in the current group to the start of the preceding or \n   following group.  Finally, we repeat this as required */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic const void *moveCursorByGroup( const void *currentCursor,\n\t\t\t\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t\t  IN_ENUM( CURSOR_MOVE ) \\\n\t\t\t\t\t\t\t\t\t\tconst CURSOR_MOVE_TYPE cursorMoveType, \n\t\t\t\t\t\t\t\t\t  IN_INT int count, \n\t\t\t\t\t\t\t\t\t  const BOOLEAN absMove )\n\t{\n\tconst void *newCursor = currentCursor, *lastCursor = NULL;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( isReadPtr( currentCursor, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( isEnumRange( cursorMoveType, CURSOR_MOVE ) );\n\tREQUIRES_N( isIntegerRangeNZ( count ) );\n\tREQUIRES_N( absMove == TRUE || absMove == FALSE );\n\n\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t  count-- > 0 && newCursor != NULL && \\\n\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t  iterationCount++ )\n\t\t{\n\t\tlastCursor = newCursor;\n\t\tif( cursorMoveType == CURSOR_MOVE_START || \\\n\t\t\tcursorMoveType == CURSOR_MOVE_PREV )\n\t\t\t{\n\t\t\t/* Move from the start of the current group to the start of the\n\t\t\t   preceding group */\n\t\t\tnewCursor = attributeFindStart( newCursor, getAttrFunction );\n\t\t\tif( newCursor != NULL )\n\t\t\t\tnewCursor = getAttrFunction( newCursor, NULL, NULL, NULL,\n\t\t\t\t\t\t\t\t\t\t\t ATTR_PREV );\n\t\t\tif( newCursor != NULL )\n\t\t\t\tnewCursor = attributeFindStart( newCursor, getAttrFunction );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES_N( cursorMoveType == CURSOR_MOVE_NEXT || \\\n\t\t\t\t\t\tcursorMoveType == CURSOR_MOVE_END );\n\n\t\t\t/* Move from the end of the current group to the start of the\n\t\t\t   next group */\n\t\t\tnewCursor = attributeFindEnd( newCursor, getAttrFunction );\n\t\t\tif( newCursor != NULL )\n\t\t\t\tnewCursor = getAttrFunction( newCursor, NULL, NULL, NULL,\n\t\t\t\t\t\t\t\t\t\t\t ATTR_NEXT );\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\tENSURES_N( lastCursor != NULL );\t/* We went through the loop at least once */\n\n\t/* If the new cursor is NULL, we've reached the start or end of the\n\t   attribute list */\n\tif( newCursor == NULL )\n\t\t{\n\t\t/* If it's an absolute move we've reached our destination, otherwise\n\t\t   there's nowhere left to move to.  We move to the start of the\n\t\t   first or last attribute that we got to before we ran out of\n\t\t   attributes to make sure that we don't fall off the start/end of\n\t\t   the list */\n\t\treturn( absMove ? \\\n\t\t\t\tattributeFindStart( lastCursor, getAttrFunction ) : NULL );\n\t\t}\n\n\t/* We've found what we were looking for */\n\treturn( newCursor );\n\t}\n\n/* Moving by attribute or attribute instance is rather simpler than moving by\n   group.  For attributes we move backwards or forwards until we either run \n   out of attributes or the next attribute belongs to a different group.  For \n   attribute instances we move similarly, except that we stop when we reach \n   an attribute whose group type, attribute type, and instance type don't \n   match the current one.  We have to explicitly keep track of whether the \n   cursor was successfully moved rather than checking that its value has \n   changed because some object types implement composite attributes that \n   maintain an attribute-internal virtual cursor, which can return the same \n   attribute pointer multiple times if the move is internal to the \n   (composite) attribute */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic const void *moveCursorByAttribute( const void *currentCursor,\n\t\t\t\t\t\t\t\t\t\t  GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t  IN_ENUM( CURSOR_MOVE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CURSOR_MOVE_TYPE cursorMoveType, \n\t\t\t\t\t\t\t\t\t\t  IN_INT int count, \n\t\t\t\t\t\t\t\t\t\t  const BOOLEAN absMove )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE groupID;\n\tBOOLEAN cursorMoved = FALSE;\n\tconst void *newCursor = currentCursor;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( isReadPtr( currentCursor, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( isEnumRange( cursorMoveType, CURSOR_MOVE ) );\n\tREQUIRES_N( isIntegerRangeNZ( count ) );\n\tREQUIRES_N( absMove == TRUE || absMove == FALSE );\n\n\tif( getAttrFunction( currentCursor, &groupID, NULL, NULL, \n\t\t\t\t\t\t ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( groupID != CRYPT_ATTRIBUTE_NONE );\n\tif( cursorMoveType == CURSOR_MOVE_START || \\\n\t\tcursorMoveType == CURSOR_MOVE_PREV )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE prevGroupID;\n\t\tconst void *prevCursor;\n\n\t\tprevCursor = getAttrFunction( newCursor, &prevGroupID, NULL, \n\t\t\t\t\t\t\t\t\t  NULL, ATTR_PREV );\n\t\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t\t  count-- > 0 && prevCursor != NULL && \\\n\t\t\t\t\tprevGroupID == groupID && \\\n\t\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t\t  iterationCount++ )\n\t\t\t{\n\t\t\tnewCursor = prevCursor;\n\t\t\tprevCursor = getAttrFunction( newCursor, &prevGroupID, NULL, \n\t\t\t\t\t\t\t\t\t\t  NULL, ATTR_PREV );\n\t\t\tcursorMoved = TRUE;\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE nextGroupID;\n\t\tconst void *nextCursor;\n\n\t\tREQUIRES_N( cursorMoveType == CURSOR_MOVE_NEXT || \\\n\t\t\t\t\tcursorMoveType == CURSOR_MOVE_END );\n\n\t\tnextCursor = getAttrFunction( newCursor, &nextGroupID, NULL,\n\t\t\t\t\t\t\t\t\t  NULL, ATTR_NEXT );\n\t\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t\t  count-- > 0 && nextCursor != NULL && \\\n\t\t\t\t\tnextGroupID == groupID && \\\n\t\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t\t  iterationCount++ )\n\t\t\t{\n\t\t\tnewCursor = nextCursor;\n\t\t\tnextCursor = getAttrFunction( newCursor, &nextGroupID, NULL,\n\t\t\t\t\t\t\t\t\t\t  NULL, ATTR_NEXT );\n\t\t\tcursorMoved = TRUE;\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\t\t}\n\n\tif( !absMove && !cursorMoved )\n\t\treturn( NULL );\n\treturn( newCursor );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic const void *moveCursorByInstance( const void *currentCursor,\n\t\t\t\t\t\t\t\t\t\t GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t IN_ENUM( CURSOR_MOVE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CURSOR_MOVE_TYPE cursorMoveType, \n\t\t\t\t\t\t\t\t\t\t IN_INT int count, \n\t\t\t\t\t\t\t\t\t\t const BOOLEAN absMove )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE groupID, attributeID, instanceID;\n\tBOOLEAN cursorMoved = FALSE;\n\tconst void *newCursor = currentCursor;\n\tint iterationCount, LOOP_ITERATOR;\n\n\tassert( isReadPtr( currentCursor, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( isEnumRange( cursorMoveType, CURSOR_MOVE ) );\n\tREQUIRES_N( isIntegerRangeNZ( count ) );\n\tREQUIRES_N( absMove == TRUE || absMove == FALSE );\n\n\tif( getAttrFunction( currentCursor, &groupID, &attributeID, \n\t\t\t\t\t\t &instanceID, ATTR_CURRENT ) == NULL )\n\t\treturn( NULL );\n\tENSURES_N( groupID != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t   attributeID != CRYPT_ATTRIBUTE_NONE );\n\tif( cursorMoveType == CURSOR_MOVE_START || \\\n\t\tcursorMoveType == CURSOR_MOVE_PREV )\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE prevGroupID, prevAttrID, prevInstID;\n\t\tconst void *prevCursor;\n\n\t\tprevCursor = getAttrFunction( newCursor, &prevGroupID,\n\t\t\t\t\t\t\t\t\t  &prevAttrID, &prevInstID,\n\t\t\t\t\t\t\t\t\t  ATTR_PREV );\n\t\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t\t  count-- > 0 && prevCursor != NULL && \\\n\t\t\t\t\tprevGroupID == groupID && \\\n\t\t\t\t\tprevAttrID == attributeID && \\\n\t\t\t\t\tprevInstID == instanceID && \\\n\t\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t\t  iterationCount++ )\n\t\t\t{\n\t\t\tnewCursor = prevCursor;\n\t\t\tprevCursor = getAttrFunction( newCursor, &prevGroupID,\n\t\t\t\t\t\t\t\t\t\t  &prevAttrID, &prevInstID,\n\t\t\t\t\t\t\t\t\t\t  ATTR_PREV );\n\t\t\tcursorMoved = TRUE;\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_ATTRIBUTE_TYPE nextGroupID, nextAttrID, nextInstID;\n\t\tconst void *nextCursor;\n\n\t\tREQUIRES_N( cursorMoveType == CURSOR_MOVE_NEXT || \\\n\t\t\t\t\tcursorMoveType == CURSOR_MOVE_END );\n\n\t\tnextCursor = getAttrFunction( newCursor, &nextGroupID,\n\t\t\t\t\t\t\t\t\t  &nextAttrID, &nextInstID,\n\t\t\t\t\t\t\t\t\t  ATTR_NEXT );\n\t\tLOOP_MAX( iterationCount = 0, \\\n\t\t\t\t  count-- > 0 && nextCursor != NULL && \\\n\t\t\t\t\tnextGroupID == groupID && \\\n\t\t\t\t\tnextAttrID == attributeID && \\\n\t\t\t\t\tnextInstID == instanceID && \\\n\t\t\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX,\n\t\t\t\t  iterationCount++ )\n\t\t\t{\n\t\t\tnewCursor = nextCursor;\n\t\t\tnextCursor = getAttrFunction( newCursor, &nextGroupID,\n\t\t\t\t\t\t\t\t\t\t  &nextAttrID, &nextInstID,\n\t\t\t\t\t\t\t\t\t\t  ATTR_NEXT );\n\t\t\tcursorMoved = TRUE;\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\t\t}\n\n\tif( !absMove && !cursorMoved )\n\t\treturn( NULL );\n\treturn( newCursor );\n\t}\n\n/* Move the attribute cursor relative to the current cursor position */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 2 ) )\\\nconst void *attributeMoveCursor( IN_OPT const void *currentCursor,\n\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeMoveType,\n\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\tconst int cursorMoveType )\n\t{\n\ttypedef struct {\n\t\tconst int moveCode;\n\t\tconst CURSOR_MOVE_TYPE cursorMoveType;\n\t\t} MOVECODE_MAP_INFO;\n\tstatic const MOVECODE_MAP_INFO moveCodeMap[] = {\n\t\t{ CRYPT_CURSOR_FIRST, CURSOR_MOVE_START },\n\t\t{ CRYPT_CURSOR_PREVIOUS, CURSOR_MOVE_PREV },\n\t\t{ CRYPT_CURSOR_NEXT, CURSOR_MOVE_NEXT },\n\t\t{ CRYPT_CURSOR_LAST, CURSOR_MOVE_END },\n\t\t{ 0, CURSOR_MOVE_NONE }, { 0, CURSOR_MOVE_NONE }\n\t\t};\n\tconst BOOLEAN absMove = ( cursorMoveType == CRYPT_CURSOR_FIRST || \\\n\t\t\t\t\t\t\t  cursorMoveType == CRYPT_CURSOR_LAST ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE;\n\tCURSOR_MOVE_TYPE moveType;\n\tint count, i, LOOP_ITERATOR;\n\n\tassert( currentCursor == NULL || \\\n\t\t\tisReadPtr( currentCursor, MIN_ATTRLIST_SIZE ) );\n\n\tREQUIRES_N( getAttrFunction != NULL );\n\tREQUIRES_N( attributeMoveType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t\tattributeMoveType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t\tattributeMoveType == CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\tREQUIRES_N( cursorMoveType >= CRYPT_CURSOR_LAST && \\\n\t\t\t\tcursorMoveType <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\n\t/* Positioning in null attribute lists is always unsuccessful */\n\tif( currentCursor == NULL )\n\t\treturn( NULL );\n\n\t/* Convert the move type into a more logical cursor move code.  We can't\n\t   use mapValue() for this because the move-type values overlap with the \n\t   end-of-table marker value expected by mapValue() */\n\tLOOP_SMALL( i = 0, \n\t\t\t\tmoveCodeMap[ i ].moveCode != cursorMoveType && \\\n\t\t\t\t\tmoveCodeMap[ i ].moveCode != 0 && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( moveCodeMap, \\\n\t\t\t\t\t\t\t\t\t\t\tMOVECODE_MAP_INFO ),\n\t\t\t\ti++ );\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( moveCodeMap, MOVECODE_MAP_INFO ) );\n\tENSURES_N( moveCodeMap[ i ].moveCode != 0 );\n\tmoveType = moveCodeMap[ i ].cursorMoveType;\n\n\t/* Set the amount that we want to move by based on the position code.\n\t   This means that we can handle the movement in a simple while loop\n\t   instead of having to special-case it for moves by one item */\n\tcount = absMove ? MAX_INTLENGTH - 1 : 1;\n\n\t/* Perform the appropriate attribute move type */\n\tswitch( attributeMoveType )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\t\treturn( moveCursorByGroup( currentCursor, getAttrFunction, \n\t\t\t\t\t\t\t\t\t   moveType, count, absMove ) );\n\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\t\treturn( moveCursorByAttribute( currentCursor, getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t   moveType, count, absMove ) );\n\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_INSTANCE:\n\t\t\treturn( moveCursorByInstance( currentCursor, getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t  moveType, count, absMove ) );\n\t\t}\n\n\t/* Everything else is an error */\n\tretIntError_Null();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSafe-pointer Attribute Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Safe pointer versions of the above.  These are just wrappers for the \n   standard functions */\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFind( IN_OPT const DATAPTR attributePtr,\n\t\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID )\n\t{\n\tDATAPTR attributeData;\n\tconst void *attributeListPtr;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tif( attributeListPtr == NULL )\n\t\treturn( DATAPTR_NULL );\n\tattributeListPtr = attributeFind( attributeListPtr, getAttrFunction, attributeID );\n\tDATAPTR_SET( attributeData, ( void * ) attributeListPtr );\n\n\treturn( attributeData );\n\t}\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFindEx( IN_OPT const DATAPTR attributePtr,\n\t\t\t\t\t\t\t\tIN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE groupID,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE instanceID )\n\t{\n\tDATAPTR attributeData;\n\tconst void *attributeListPtr;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tif( attributeListPtr == NULL )\n\t\treturn( DATAPTR_NULL );\n\tattributeListPtr = attributeFindEx( attributeListPtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t\tgroupID, attributeID, instanceID );\n\tDATAPTR_SET( attributeData, ( void * ) attributeListPtr );\n\n\treturn( attributeData );\n\t}\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nDATAPTR dataptrAttributeFindNextInstance( IN_OPT DATAPTR attributePtr,\n\t\t\t\t\t\t\t\t\t\t  IN GETATTR_FUNCTION getAttrFunction )\n\t{\n\tDATAPTR attributeData;\n\tconst void *attributeListPtr;\n\n\tREQUIRES_D( DATAPTR_ISVALID( attributePtr ) );\n\tattributeListPtr = DATAPTR_GET( attributePtr );\n\tif( attributeListPtr == NULL )\n\t\treturn( DATAPTR_NULL );\n\tattributeListPtr = attributeFindNextInstance( attributeListPtr, getAttrFunction );\n\tDATAPTR_SET( attributeData, ( void * ) attributeListPtr );\n\n\treturn( attributeData );\n\t}\n\nCHECK_RETVAL_DATAPTR STDC_NONNULL_ARG( ( 2 ) ) \\\nCONST_RETURN DATAPTR dataptrAttributeMoveCursor( IN_OPT const DATAPTR currentCursor,\n\t\t\t\t\t\t\t\t\t\t\t\t IN GETATTR_FUNCTION getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeMoveType,\n\t\t\t\t\t\t\t\t\t\t\t\t IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int cursorMoveType )\n\t{\n\tDATAPTR attributeCursorData;\n\tconst void *attributeListCursor;\n\n\tREQUIRES_D( DATAPTR_ISVALID( currentCursor ) );\n\tattributeListCursor = DATAPTR_GET( currentCursor );\n\tif( attributeListCursor == NULL )\n\t\treturn( DATAPTR_NULL );\n\tattributeListCursor = attributeMoveCursor( attributeListCursor, \n\t\t\t\t\t\t\t\t\t\t\t   getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t\t   attributeMoveType, \n\t\t\t\t\t\t\t\t\t\t\t   cursorMoveType );\n\tDATAPTR_SET( attributeCursorData, ( void * ) attributeListCursor );\n\n\treturn( attributeCursorData );\n\t}\n"
  },
  {
    "path": "deps/cl345/misc/int_debug.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Internal Debugging API\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"stream.h\"\n#else\n  #include \"crypt.h\"\n  #include \"io/stream.h\"\n#endif /* Compiler-specific includes */\n\n/* The following functions are intended purely for diagnostic purposes \n   during development.  They perform minimal checking (for example using \n   assertions rather than returning error codes, since the calling code \n   can't hardwire in tests for their return status), and should only\n   be used with a debugger */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDiagnostic-dump Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if !defined( NDEBUG ) || defined( DEBUG_DIAGNOSTIC_ENABLE ) \n\n/* Older versions of the WinCE runtime don't provide complete stdio\n   support so we have to emulate it using wrappers for native \n   functions */\n\n#if defined( __WINCE__ ) && _WIN32_WCE < 500\n\nint remove( const char *pathname )\n\t{\n\twchar_t wcBuffer[ _MAX_PATH + 1 ];\n\n\tmbstowcs( wcBuffer, pathname, strlen( pathname ) + 1 );\n\tDeleteFile( wcBuffer );\n\n\treturn( 0 );\n\t}\n#endif /* WinCE < 5.x doesn't have remove() */\n\n/* Output text to the debug console or whatever the OS'es nearest equivalent\n   is.  If possible this is normally done via a macro in a debug.h that \n   remaps the debug-output macros to the appropriate function but Windows \n   only provides a puts()-equivalent and not a printf()-equivalent and under \n   Unix we need to send the output to stderr which can't easily be done in a \n   macro */\n   \n#if defined( __WIN32__ ) || defined( __WINCE__ )\n\n/* OutputDebugString() under Windows isn't very reliable, it's implemented \n   using a 4kB chunk of shared memory DBWIN_BUFFER controlled by a mutex \n   DBWinMutex and two events DBWIN_BUFFER_READY and DBWIN_DATA_READY.  \n   OutputDebugString() waits for exclusive access to DBWinMutex, maps in \n   DBWIN_BUFFER, waits for DBWIN_BUFFER_READY to be signalled, copies in up \n   to 4K of data, fires DBWIN_DATA_READY, and releases the mutex.  If any of \n   these operations fail, the call to OutputDebugString() is treated as a \n   no-op and we never see the output.  On the receiving side the debugger \n   performs the obvious actions to receive the data.  \n   \n   Beyond this Rube-Goldberg message-passing mechanism there are also \n   problems with permissions on the mutex and the way the DACL for it has \n   been tweaked in almost every OS release.  The end result of this is that \n   data sent to OutputDebugString() may be randomly lost if other threads \n   are also sending data to it (e.g. Visual Studio as part of its normal \n   chattiness about modules and threads being loaded/started/unloaded/\n   stopped/etc).  \n   \n   The only way to avoid this is to step through the code that uses\n   OutputDebugString() so that enough delay is inserted to allow other \n   callers and the code being debugged to get out of each others' hair */\n\nint debugPrintf( const char *format, ... )\n\t{\n\tva_list argPtr;\n\tchar buffer[ 1024 + 8 ];\n\tint length;\n\n\tva_start( argPtr, format );\n#if VC_GE_2005( _MSC_VER )\n\tlength = vsnprintf_s( buffer, 1024, _TRUNCATE, format, argPtr );\n#else\n\tlength = vsprintf( buffer, format, argPtr );\n#endif /* VC++ 2005 or newer */\n\tva_end( argPtr );\n#if defined( __WIN32__ ) \n\tOutputDebugString( buffer );\n#else\n\tNKDbgPrintfW( L\"%s\", buffer )\n#endif /* __WIN32__ */\n\n\treturn( length );\n\t}\n\n#elif defined( __UNIX__ )\n\n#include <stdarg.h>\t\t\t/* Needed for va_list */\n\nint debugPrintf( const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vfprintf( stderr, format, argPtr );\n\tva_end( argPtr );\n\tfflush( stderr );\t/* Just in case it gets stuck in a buffer */\n\n\treturn( length );\n\t}\n\n#elif defined( __MVS__ ) || defined( __VMCMS__ ) || defined( __ILEC400__ )\n\n/* Implementing debugPrintf() on EBCDIC systems is problematic because all\n   internal strings are ASCII, so that both the format specifiers and any\n   string arguments that they're being used with won't work with functions\n   that expect EBCDIC strings.  To get around this we use the internal \n   vsPrintf_s() that handles all of the format types that cryptlib uses, \n   and then convert the result to EBCDIC */\n\nint debugPrintf( const char *format, ... )\n\t{\n\tva_list argPtr;\n\tchar buffer[ 1024 + 8 ];\n\tint length;\n\n\t/* Format the arguments as an ASCII string */\n\tva_start( argPtr, format );\n\tlength = vsPrintf_s( buffer, 1024, format, argPtr );\n\tva_end( argPtr );\n\n\t/* Convert it to EBCDIC and display it */\n\tbufferToEbcdic( buffer, buffer );\n#pragma convlit( suspend )\n\tprintf( \"%s\", buffer );\n#pragma convlit( resume )\n\tfflush( stdout );\t/* Just in case it gets stuck in a buffer */\n\n\treturn( length );\n\t}\n#else\n\n#include <stdarg.h>\t\t\t/* Needed for va_list */\n\nint debugPrintf( const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vprintf( format, argPtr );\n\tva_end( argPtr );\n\n\treturn( length );\n\t}\n#endif /* OS-specific debug output functions */\n\n/* Dump a PDU to disk */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void buildFilePath( IN_STRING const char *fileName,\n\t\t\t\t\t\t   OUT_BUFFER_FIXED_C( 1024 ) char *filenameBuffer )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\tassert( isWritePtr( filenameBuffer, 1024 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\t/* Check whether the filename appears to be an absolute path */\n\tLOOP_MAX( i = 0, fileName[ i ] != '\\0', i++ )\n\t\t{\n\t\tif( fileName[ i ] == ':' || fileName[ i ] == '/' )\n\t\t\tbreak;\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tif( fileName[ i ] == '\\0' )\n\t\t{\n\t\t/* It's a relative path, put the file in the temp directory */\n\t\tstrlcpy_s( filenameBuffer, 1024, \"/tmp/\" );\n\t\tstrlcat_s( filenameBuffer, 1024, fileName );\n\t\t}\n\telse\n\t\tstrlcpy_s( filenameBuffer, 1024, fileName );\n\tstrlcat_s( filenameBuffer, 1024, \".der\" );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic FILE *openFile( IN_STRING const char *fileName,\n\t\t\t\t\t   INOUT char *filenameBuffer )\n\t{\n\tFILE *filePtr;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tbuildFilePath( fileName, filenameBuffer );\n#if defined( EBCDIC_CHARS )\n\tbufferToEbcdic( filenameBuffer, filenameBuffer );\n  #pragma convlit( suspend )\t\n\tfilePtr = fopen( filenameBuffer, \"wb\" );\n  #pragma convlit( resume )\t\n#elif defined( __STDC_LIB_EXT1__ )\n\tif( fopen_s( &filePtr, filenameBuffer, \"wb\" ) != 0 )\n\t\tfilePtr = NULL;\n#else\n\tfilePtr = fopen( filenameBuffer, \"wb\" );\n#endif /* __STDC_LIB_EXT1__ */\n\n\treturn( filePtr );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid debugDumpFile( IN_STRING const char *fileName, \n\t\t\t\t\tIN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\tIN_LENGTH_SHORT const int dataLength )\n\t{\n\tFILE *filePtr;\n\tchar filenameBuffer[ 1024 + 8 ];\n\tint count DUMMY_INIT;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tfilePtr = openFile( fileName, filenameBuffer );\n\tassert( filePtr != NULL );\n\tif( filePtr == NULL )\n\t\treturn;\n\tif( dataLength > 0 )\n\t\t{\n#ifdef __MQXRTOS__\n\t\t/* MQX gets fwrite() args wrong */\n\t\tcount = fwrite( ( void * ) data, 1, dataLength, filePtr );\n#else\n\t\tcount = fwrite( data, 1, dataLength, filePtr );\n#endif /* __MQXRTOS__ */\n\t\tassert( count == dataLength );\n\t\t}\n\tfclose( filePtr );\n\tif( dataLength > 0 && count < dataLength )\n\t\t( void ) remove( filenameBuffer );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid debugDumpFileCert( IN_STRING const char *fileName, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCryptCert )\n\t{\n\tMESSAGE_DATA msgData DUMMY_INIT_STRUCT;\n\tFILE *filePtr;\n\tBYTE certData[ 2048 + 8 ];\n\tchar filenameBuffer[ 1024 + 8 ];\n\tint certType, count DUMMY_INIT, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\tassert( isHandleRangeValid( iCryptCert ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tfilePtr = openFile( fileName, filenameBuffer );\n\tassert( filePtr != NULL );\n\tif( filePtr == NULL )\n\t\treturn;\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &certType,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, certData, 2048 );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t\t  ( certType == CRYPT_CERTTYPE_PKIUSER ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_ICERTFORMAT_DATA : \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcount = fwrite( certData, 1, msgData.length, filePtr );\n\t\tassert( count == msgData.length );\n\t\t}\n\tfclose( filePtr );\n\tif( cryptStatusError( status ) || count < msgData.length )\n\t\t( void ) remove( filenameBuffer );\n\t}\n\n/* Create a hex dump of the first n bytes of a buffer along with the length \n   and a checksum of the entire buffer, used to output a block of hex data \n   along with checksums for debugging things like client/server sessions \n   where it can be used to detect data corruption.  The use of a memory \n   buffer is to allow the hex dump to be performed from multiple threads \n   without them fighting over stdout */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid debugDumpHex( IN_STRING const char *prefixString, \n\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tchar dumpBuffer[ 128 + 1 + 8 ];\n\tint offset, i, j, LOOP_ITERATOR;\n\n\tANALYSER_HINT_STRING( prefixString );\n\n\toffset = sprintf_s( dumpBuffer, 128, \"%3s %4d %04X \", \n\t\t\t\t\t\tprefixString, dataLength, \n\t\t\t\t\t\tchecksumData( data, dataLength ) & 0xFFFF );\n\tLOOP_MAX( i = 0, i < dataLength, i += 16 )\n\t\t{\n\t\tconst int innerLen = min( dataLength - i, 16 );\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\tif( i > 0 )\n\t\t\t{\n\t\t\toffset = sprintf_s( dumpBuffer, 128, \"%3s           \",\n\t\t\t\t\t\t\t\tprefixString );\n\t\t\t}\n\t\tfor( j = 0; j < innerLen; j++ )\n\t\t\t{\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"%02X \",\n\t\t\t\t\t\t\t\t ( ( BYTE * ) data )[ i + j ] );\n\t\t\t}\n\t\tLOOP_MAX_CHECKINC_ALT( j < 16, j++ )\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"   \" );\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\tLOOP_MAX_ALT( j = 0, j < innerLen, j++ )\n\t\t\t{\n\t\t\tconst BYTE ch = ( ( BYTE * ) data )[ i + j ];\n\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"%c\",\n\t\t\t\t\t\t\t\t isPrint( ch ) ? ch : '.' );\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\tDEBUG_PUTS(( dumpBuffer ));\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n#if !( defined( __WIN32__ ) || defined( __WINCE__ ) || defined( __ECOS__ ) || \\\n\t   ( defined( __MQXRTOS__ ) && defined( MQX_SUPPRESS_STDIO_MACROS ) ) )\n\tfflush( stdout );\n#endif /* Systems where output doesn't to go stdout */\n\t}\n\n/* Variants of debugDumpHex() that only output the raw hex data, for use in\n   conjunction with DEBUG_PRINT() to output other information about the \n   data */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid debugDumpData( IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\tIN_LENGTH_SHORT const int dataLength )\n\t{\n\tchar dumpBuffer[ 128 + 1 + 8 ];\n\tint offset, i, LOOP_ITERATOR;\n\n\tLOOP_MAX( i = 0, i < dataLength, i += 16 )\n\t\t{\n\t\tconst int innerLen = min( dataLength - i, 16 );\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\toffset = sprintf_s( dumpBuffer, 128, \"%04d: \", i );\n\t\tLOOP_MAX_ALT( j = 0, j < innerLen, j++ )\n\t\t\t{\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"%02X \",\n\t\t\t\t\t\t\t\t ( ( BYTE * ) data )[ i + j ] );\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\tLOOP_MAX_CHECKINC_ALT( j < 16, j++ )\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"   \" );\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\tLOOP_MAX_ALT( j = 0, j < innerLen, j++ )\n\t\t\t{\n\t\t\tconst BYTE ch = ( ( BYTE * ) data )[ i + j ];\n\n\t\t\toffset += sprintf_s( dumpBuffer + offset, 128 - offset, \"%c\",\n\t\t\t\t\t\t\t\t isPrint( ch ) ? ch : '.' );\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\tDEBUG_PUTS(( dumpBuffer ));\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n#if !( defined( __WIN32__ ) || defined( __WINCE__ ) || defined( __ECOS__ ) || \\\n\t   ( defined( __MQXRTOS__ ) && defined( MQX_SUPPRESS_STDIO_MACROS ) ) )\n\tfflush( stdout );\n#endif /* Systems where output doesn't to go stdout */\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid debugDumpStream( INOUT /*STREAM*/ void *streamPtr, \n\t\t\t\t\t  IN_LENGTH const int position,\n\t\t\t\t\t  IN_LENGTH const int length )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE *dataPtr; \n\tint status; \n\n\t/* In some cases we may be asked to dump zero-length packets, since \n\t   we're being called unconditionally (the caller can't put conditional\n\t   code into a debug macro) we just turn the call into a no-op */\n\tif( length <= 0 )\n\t\treturn;\n\n\tstatus = sMemGetDataBlockAbs( stream, position, ( void ** ) &dataPtr, \n\t\t\t\t\t\t\t\t  length );\n\tif( cryptStatusError( status ) )\n\t\treturn;\n\tANALYSER_HINT_V( dataPtr != NULL );\n\tdebugDumpData( dataPtr, length );\n\t}\n\n/* Dump a stack trace.  Note that under Unix this may require linking with \n   -rdynamic (to force the addition of all symbols, not just public ones, so \n   for example ones for static functions) in order for backtrace_symbols() \n   to be able to display all symbols */\n\n#if defined( __WIN32__ )\n\n#if VC_GE_2005( _MSC_VER )\n\n#include <dbghelp.h>\n#pragma comment( lib, \"dbghelp.lib\" )\n\n#ifdef _WIN64 \n  #define BINARIES_PATH\t\"debug64_vs10;binaries64_vs10\" \n#else\n  #define BINARIES_PATH\t\"debug32_vs10;binaries32_vs10\"\n#endif /* Win32 vs. Win64 */\n\nvoid displayBacktrace( void )\n\t{\n\tHANDLE process;\n\tSYMBOL_INFO *symbolInfo;\n\tIMAGEHLP_LINE lineInfo;\n\tBYTE buffer[ sizeof( SYMBOL_INFO ) + ( MAX_SYM_NAME * sizeof( TCHAR ) ) ];\n\tvoid *stack[ 64 ];\n\tint noFrames, i, LOOP_ITERATOR;\n\n\t/* Load debugging symbols for the current process */\n\tDEBUG_PUTS(( \"Stack trace:\" ));\n\tprocess = GetCurrentProcess();\n\tSymSetOptions( SYMOPT_LOAD_LINES );\n\tif( !SymInitialize( process, BINARIES_PATH, TRUE ) )\n\t\t{\n\t\tconst DWORD error = GetLastError();\n\t\t\n\t\tDEBUG_PRINT(( \"Couldn't load symbols, error = %d.\\n\", error ));\n\t\treturn;\t\t\n\t\t}\n\n\t/* Get the stack backtrace.  Frame 0 is the current function so we start at\n\t   1, and we don't display the last four frames since they're system \n\t   functions */\n\tnoFrames = CaptureStackBackTrace( 1, 64, stack, NULL );\n\tif( noFrames < 4 )\n\t\t{\n\t\tconst DWORD error = GetLastError();\n\t\t\n\t\tDEBUG_PRINT(( \"Couldn't capture stack backtrace, error = %d.\\n\", error ));\n\t\treturn;\t\t\n\t\t}\n\n\t/* Set up the SYMBOL_INFO and LINE_INFO structures */\n\tsymbolInfo = ( SYMBOL_INFO * ) buffer;\n\tmemset( symbolInfo, 0, sizeof( SYMBOL_INFO ) );\n\tsymbolInfo->MaxNameLen = MAX_SYM_NAME;\n\tsymbolInfo->SizeOfStruct = sizeof( SYMBOL_INFO );\n\tmemset( &lineInfo, 0, sizeof( IMAGEHLP_LINE ) );\n\tlineInfo.SizeOfStruct = sizeof( IMAGEHLP_LINE );\n\n\t/* Walk the stack printing addresses and symbols if we can get them */\n\tLOOP_LARGE( i = 0, i < noFrames - 4, i++ ) \n\t\t{\n\t\tconst DWORD_PTR address = ( DWORD_PTR ) stack[ i ];\n\t\tDWORD dwDisplacement;\n\n\t\tif( !SymFromAddr( process, address, 0, symbolInfo ) )\n\t\t\t{\n\t\t\tconst DWORD error = GetLastError();\n\t\t\tDEBUG_PRINT(( \"<Unknown - %d> - 0x%I64x\\n\", error, address ));\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( SymGetLineFromAddr( process, address, &dwDisplacement, \n\t\t\t\t\t\t\t\t&lineInfo ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"%s:%d - 0x%I64x\\n\", symbolInfo->Name, \n\t\t\t\t\t\t  lineInfo.LineNumber, symbolInfo->Address ));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"%s - 0x%I64x\\n\", symbolInfo->Name, \n\t\t\t\t\t\t  symbolInfo->Address ));\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n#else\n\n/* Older versions of VC++ don't have dbghelp.h/dbghelp.lib, which contains \n   CaptureStackBackTrace(), so we'd either need to dynamically load it or \n   just use alternate code that walks the stack manually from the current \n   EBP */\n\n#include <ImageHlp.h>\n#pragma comment( lib, \"imagehlp.lib\" )\n\n#define BINARIES_PATH\t\"debug32_vc6;binaries32_vc6\"\n\nvoid displayBacktrace( void )\n\t{\n\tHANDLE process;\n\tIMAGEHLP_SYMBOL *symbolInfo;\n\tIMAGEHLP_LINE lineInfo;\n\tBYTE buffer[ sizeof( IMAGEHLP_SYMBOL ) + 1024 ];\n\tunsigned long prevAddress, address = 1;\n\tint i, LOOP_ITERATOR;\n\n\t/* Horribly nonportable way of walking the stack due to lack of access\n\t   to CaptureStackBackTrace() */\n\t__asm { mov prevAddress, ebp };\n\n\t/* Load debugging symbols for the current process */\n\tDEBUG_PUTS(( \"Stack trace:\" ));\n\tprocess = GetCurrentProcess();\n\tSymSetOptions( SYMOPT_LOAD_LINES );\n\tif( !SymInitialize( process, BINARIES_PATH, TRUE ) )\n\t\t{\n\t\tDEBUG_OP( const DWORD error = GetLastError() );\n\t\t\n\t\tDEBUG_PRINT(( \"Couldn't load symbols, error = %d.\\n\", error ));\n\t\treturn;\t\t\n\t\t}\n\n\t/* Set up the SYMBOL_INFO and LINE_INFO structures */\n\tsymbolInfo = ( IMAGEHLP_SYMBOL * ) buffer;\n\tmemset( symbolInfo, 0, sizeof( IMAGEHLP_SYMBOL ) );\n\tsymbolInfo->SizeOfStruct = sizeof( IMAGEHLP_SYMBOL );\n\tsymbolInfo->MaxNameLength = 512;\n\tmemset( &lineInfo, 0, sizeof( IMAGEHLP_LINE ) );\n\tlineInfo.SizeOfStruct = sizeof( IMAGEHLP_LINE );\n\n\t/* Walk the stack printing addresses and symbols if we can get them */\n\tLOOP_LARGE( i = 0, i < 50, i++ ) \n\t\t{ \n\t\tDWORD dwDisplacement;\n\n\t\taddress = ( ( unsigned long * ) prevAddress )[ 1 ]; \n\t\tprevAddress = ( ( unsigned long * ) prevAddress )[ 0 ]; \n\t\tif( address == 0 )\n\t\t\tbreak;\n\t\tif( !SymGetSymFromAddr( process, address, 0, symbolInfo ) )\n\t\t\t{\n\t\t\tDEBUG_OP( const DWORD error = GetLastError() );\n\n\t\t\tDEBUG_PRINT(( \"<Unknown - %d> - 0x%0lX\\n\", error, address ));\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( SymGetLineFromAddr( process, address, &dwDisplacement, \n\t\t\t\t\t\t\t\t&lineInfo ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"%s:%d - 0x%lX\\n\", symbolInfo->Name, \n\t\t\t\t\t\t  lineInfo.LineNumber, symbolInfo->Address ));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"%s - 0x%0X\\n\", symbolInfo->Name, \n\t\t\t\t\t\t  symbolInfo->Address ));\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\tSymCleanup( process );\n\t}\n#endif /* Win32 vs. Win64 */\n\n#elif defined( __UNIX__ ) && \\\n\t  ( defined( __APPLE__ ) || defined( __linux__ ) || defined( __sun ) )\n\n#include <execinfo.h>\n\n#ifdef __GNUC__\n  /* Needed with -finstrument */\n  void __cyg_profile_func_enter( void *func, void *caller ) \\\n\t   __attribute__(( no_instrument_function ));\n  void __cyg_profile_func_enter( void *func, void *caller ) { }\t\n  void __cyg_profile_func_exit( void *func, void *caller ) \\\n\t   __attribute__(( no_instrument_function ));\n  void __cyg_profile_func_exit( void *func, void *caller ) { }\n#endif /* __GNUC__ */\n\nvoid displayBacktrace( void )\n\t{\n\tvoid *stackInfo[ 100 + 8 ];\n\tchar **stackInfoStrings;\n\tint i, stackInfoSize, LOOP_ITERATOR;\n \n\tDEBUG_PUTS(( \"Stack trace:\" ));\n\tstackInfoSize = backtrace( stackInfo, 100 );\n\tif( stackInfoSize <= 2 )\n\t\t{\n\t\t/* See also the comment about -rdynamic at the start of this code \n\t\t   section */\n\t\tDEBUG_PUTS(( \"Only one level of backtrace available, if this is an \"\n\t\t\t\t\t \"architecture without\\nframe pointers like ARM or MIPS \"\n\t\t\t\t\t \"then you need to rebuild with\\n-finstrument-functions \"\n\t\t\t\t\t \"and/or -fexceptions\" ));\n\t\t}\n\tstackInfoStrings = backtrace_symbols( stackInfo, stackInfoSize );\n \n\t/* We start at position 1, since the 0-th entry is the current function,\n\t   i.e. displayBacktrace().  We also stop one before the last entry, \n\t   which is typically main() or something similar */\n\tLOOP_LARGE( i = 1, i < stackInfoSize - 1, i++ ) \n\t\t{\n\t\tDEBUG_PRINT(( \"%p : %s\\n\", stackInfo[ i ], stackInfoStrings[ i ] ));\n\t\t}\n \tENSURES_V( LOOP_BOUND_OK );\n\n\tfree( stackInfoStrings );\n\t}\n#endif /* OS-specific backtrace printing */\n\n/* Support function used to access the text string data from an ERROR_INFO\n   structure.  Note that this function isn't thread-safe, but that should be\n   OK since it's only used for debugging */\n\n#if !defined( NDEBUG ) && defined( USE_ERRMSGS )\n\nconst char *getErrorInfoString( const ERROR_INFO *errorInfo )\n\t{\n\tstatic char errorInfoString[ MAX_ERRMSG_SIZE + 8 ];\n\tconst int errorStringLength = \\\n\t\t\t\tmin( errorInfo->errorStringLength, MAX_ERRMSG_SIZE - 1 );\n\n\t/* If there's no extended error information available, return an \n\t   indicator of this */\n\tif( errorStringLength <= 0 )\n\t\treturn( \"<<<No further information available>>>\" );\n\n\tmemcpy( errorInfoString, errorInfo->errorString, errorStringLength );\n\terrorInfoString[ errorStringLength ] = '\\0';\n\n\treturn( errorInfoString );\n\t}\n#endif /* !NDEBUG && USE_ERRMSGS */\n\n/* Support function used with streams to pull data bytes out of the stream,\n   allowing type and content data to be dumped with DEBUG_PRINT() */\n\nRETVAL_RANGE_NOERROR( 0, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint debugGetStreamByte( INOUT /*STREAM*/ void *streamPtr, \n\t\t\t\t\t\tIN_LENGTH const int position )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE *dataPtr; \n\tint status; \n\n\tstatus = sMemGetDataBlockAbs( stream, position, ( void ** ) &dataPtr, 1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( 0 );\n\treturn( byteToInt( *dataPtr ) );\n\t}\n#endif /* Debug || DEBUG_DIAGNOSTIC_ENABLE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tFault-injection Support Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\n#define PARAM_ACL\tint\t\t/* Fake out unneeded types */\n#include \"kernel/kernel.h\"\n\n/* Variables used for fault-injection tests */\n\nFAULT_TYPE faultType;\nint faultParam1;\n\n/* Get a substitute key to replace the actual one, used to check for \n   detection of use of the wrong key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSubstituteKey( OUT_HANDLE_OPT CRYPT_CONTEXT *iPrivateKey )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tint status;\n\n\t/* Clear return value */\n\t*iPrivateKey = CRYPT_ERROR;\n\n\t/* Try and read the certificate chain from the keyset */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );\n\tcreateInfo.arg2 = CRYPT_KEYOPT_READONLY;\n\tcreateInfo.strArg1 = \"test/keys/server2.p15\";\n\tcreateInfo.strArgLen1 = strlen( createInfo.strArg1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_KEYSET );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_NAME, \"Test user key\", 13,\n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_USAGE_SIGN );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DESTROY );\n\tif( cryptStatusOK( status ) )\n\t\t*iPrivateKey = getkeyInfo.cryptHandle;\n\n\treturn( status );\n\t}\n\n/* Corrupt a random bit in a block of memory */\n\nCHECK_RETVAL \\\nstatic int getDeterministicRandomInt( void )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunction;\n\tstatic BYTE hashBuffer[ CRYPT_MAX_HASHSIZE ] = { 0 };\n\tBYTE *hashBufPtr = hashBuffer;\n\tint hashSize, retVal;\n\n\t/* Step the RNG and extract an integer's-worth of data from it.  We go\n\t   via the intermediate value retVal because mgetLong() is a macro that\n\t   doesn't work as part of a return statement */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunction, &hashSize );\n\thashFunction( hashBuffer, hashSize, hashBuffer, hashSize );\n\tretVal = mgetLong( hashBufPtr );\n\n\treturn( retVal );\n\t}\n\nvoid injectMemoryFault( void )\n\t{\n\tconst int value = getDeterministicRandomInt();\n\tconst BYTE bitMask = intToByte( 1 << ( value & 3 ) );\n\tconst int bytePos = value >> 3;\n\tBYTE *dataPtr = ( BYTE * ) getKrnlData();\n\tconst int dataSize = getKrnlDataSize();\n\n\tdataPtr[ bytePos % dataSize ] ^= bitMask;\n\t}\n#endif /* CONFIG_FAULTS && Debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTiming Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if !defined( NDEBUG ) && ( defined( __WINDOWS__ ) || defined( __UNIX__ ) )\n\n#ifdef __UNIX__ \n  #include <sys/time.h>\t\t/* For gettimeofday() */\n#endif /* __UNIX__  */\n\n/* Get/update high-resolution timer value */\n\nHIRES_TIME debugTimeDiff( HIRES_TIME startTime )\n\t{\n\tHIRES_TIME timeValue;\n#ifdef __WINDOWS__\n\tLARGE_INTEGER performanceCount;\n\n\t/* Sensitive to context switches */\n\tQueryPerformanceCounter( &performanceCount );\n\ttimeValue = performanceCount.QuadPart;\n#else\n\tstruct timeval tv;\n\n\t/* Only accurate to about 1us */\n\tgettimeofday( &tv, NULL );\n  #ifdef HIRES_TIME_64BIT\n\ttimeValue = ( ( ( HIRES_TIME ) tv.tv_sec ) << 32 ) | tv.tv_usec;\n  #else\n\ttimeValue = tv.tv_usec;\n  #endif /* HIRES_TIME_64BIT */\n#endif /* Windows vs.Unix high-res timing */\n\n\tif( !startTime )\n\t\treturn( timeValue );\n\treturn( timeValue - startTime );\n\t}\n\n/* Display high-resulution time value */\n\nint debugTimeDisplay( HIRES_TIME timeValue )\n\t{\n\tHIRES_TIME timeMS, ticksPerSec;\n\n\t/* Try and get the clock frequency */\n#ifdef __WINDOWS__\n\tLARGE_INTEGER performanceCount;\n\n\tQueryPerformanceFrequency( &performanceCount );\n\tticksPerSec = performanceCount.QuadPart;\n#else\n\tticksPerSec = 1000000L;\n#endif /* __WINDOWS__ */\t\n\n\ttimeMS = ( timeValue * 1000 ) / ticksPerSec;\n\tassert( timeMS < INT_MAX );\n\tif( timeMS <= 0 )\n\t\tprintf( \"< 1\" );\n\telse\n\t\tprintf( HIRES_FORMAT_SPECIFIER, timeMS );\n\n\treturn( ( timeMS <= 0 ) ? 1 : ( int ) timeMS );\n\t}\n#endif /* Debug && ( __WINDOWS__ || __UNIX__ ) */\n"
  },
  {
    "path": "deps/cl345/misc/int_env.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Internal Enveloping API\t\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1992-2011\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ENVELOPES\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tData Wrap/Unwrap Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* General-purpose enveloping functions, used by various high-level\n   protocols */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 11 ) ) \\\nint envelopeWrap( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int inDataLength, \n\t\t\t\t  OUT_BUFFER( outDataMaxLength, \\\n\t\t\t\t\t\t\t  *outDataLength ) void *outData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t  IN_ENUM( CRYPT_FORMAT ) const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t  IN_ENUM_OPT( CRYPT_CONTENT ) \\\n\t\t\t\t\tconst CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_HANDLE iPublicKey,\n\t\t\t\t  IN_BUFFER_OPT( passwordLength ) const void *password,\n\t\t\t\t  IN_LENGTH_SHORT_Z const int passwordLength,\n\t\t\t\t  OUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ENVELOPE iCryptEnvelope;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength + 512 );\n\tint status;\n\n\tassert( isReadPtrDynamic( inData, inDataLength ) );\n\tassert( isWritePtrDynamic( outData, outDataMaxLength ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( password == NULL || \\\n\t\t\tisReadPtrDynamic( password, passwordLength ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( inDataLength > 16 && inDataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( outDataMaxLength > 16 && \\\n\t\t\t  outDataMaxLength >= inDataLength + 512 && \\\n\t\t\t  outDataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( formatType == CRYPT_FORMAT_CRYPTLIB || \\\n\t\t\t  formatType == CRYPT_FORMAT_CMS );\n\tREQUIRES( isEnumRangeOpt( contentType, CRYPT_CONTENT ) );\n\tREQUIRES( ( iPublicKey == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( iPublicKey ) );\n\tREQUIRES( ( password == NULL && passwordLength == 0 ) ||\n\t\t\t  ( password != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( passwordLength ) ) );\n\tREQUIRES( iPublicKey == CRYPT_UNUSED || password == NULL );\n\n\t/* Clear return values.  Note that we can't clear the output buffer \n\t   at this point since this function is frequently used for in-place \n\t   processing, so we clear it after we've pushed the input data */\n\t*outDataLength = 0;\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Create an envelope to wrap the data, add the encryption key if\n\t   necessary, and pop the wrapped result */\n\tsetMessageCreateObjectInfo( &createInfo, formatType );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\t\treturn( status );\n\t\t}\n\tiCryptEnvelope = createInfo.cryptHandle;\n\t( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &minBufferSize, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &inDataLength,\n\t\t\t\t\t\t\t  CRYPT_ENVINFO_DATASIZE );\n\tif( cryptStatusOK( status ) && contentType != CRYPT_CONTENT_NONE )\n\t\t{\n\t\tconst int value = contentType;\t/* int vs.enum */\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &value,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_CONTENTTYPE );\n\t\t}\n\tif( cryptStatusOK( status ) && iPublicKey != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iPublicKey,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PUBLICKEY );\n\t\t}\n\tif( cryptStatusOK( status ) && password != NULL )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, \n\t\t\t\t\t\tpasswordLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_ENVINFO_PASSWORD );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) inData, inDataLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tENSURES( msgData.length >= inDataLength );\n\t\t\t}\n\t\t}\n\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, outData, outDataMaxLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tENSURES( msgData.length > inDataLength && \\\n\t\t\t\t\t msgData.length < outDataMaxLength );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*outDataLength = msgData.length;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Fetch any addition error information that may be available */\n\t\treadErrorInfo( errorInfo, iCryptEnvelope );\n\t\t}\n\tkrnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );\n\n\tENSURES( cryptStatusError( status ) || \\\n\t\t\t cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( outData, *outDataLength ) ) );\n\tassert( !cryptArgError( status ) );\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 9 ) ) \\\nint envelopeUnwrap( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t\tIN_DATALENGTH_MIN( 16 ) const int inDataLength,\n\t\t\t\t\tOUT_BUFFER( outDataMaxLength, \\\n\t\t\t\t\t\t\t\t*outDataLength ) void *outData, \n\t\t\t\t\tIN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t\tOUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t\tIN_HANDLE_OPT const CRYPT_CONTEXT iPrivKey,\n\t\t\t\t\tIN_BUFFER_OPT( passwordLength ) const void *password,\n\t\t\t\t\tIN_LENGTH_SHORT_Z const int passwordLength,\n\t\t\t\t\tOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ENVELOPE iCryptEnvelope;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength );\n\tint status;\n\n\tassert( isReadPtrDynamic( inData, inDataLength ) );\n\tassert( isWritePtrDynamic( outData, outDataMaxLength ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( password == NULL || \\\n\t\t\tisReadPtrDynamic( password, passwordLength ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( inDataLength > 16 && inDataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( outDataMaxLength > 16 && \\\n\t\t\t  outDataMaxLength >= inDataLength && \\\n\t\t\t  outDataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( iPrivKey == CRYPT_UNUSED ) || \\\n\t\t\t  isHandleRangeValid( iPrivKey ) );\n\tREQUIRES( ( password == NULL && passwordLength == 0 ) ||\n\t\t\t  ( password != NULL && \\\n\t\t\t    isShortIntegerRangeNZ( passwordLength ) ) );\n\tREQUIRES( iPrivKey == CRYPT_UNUSED || password == NULL );\n\n\t/* Clear return values.  Note that we can't clear the output buffer \n\t   at this point since this function is frequently used for in-place \n\t   processing, so we clear it after we've pushed the input data */\n\t*outDataLength = 0;\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Create an envelope to unwrap the data, add the decryption key if\n\t   necessary, and pop the unwrapped result.  In theory we could use \n\t   checkASN1() here to perform a safety check of the envelope data\n\t   prior to processing but this has already been done by the calling\n\t   code when the datagram containing the enveloped data was read so\n\t   we don't need to repeat the (rather heavyweight) operation here */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\t\treturn( status );\n\t\t}\n\tiCryptEnvelope = createInfo.cryptHandle;\n\t( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &minBufferSize, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) inData, inDataLength );\n\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t  &msgData, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tENSURES( msgData.length >= inDataLength );\n\t\t}\n\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tif( iPrivKey != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iPrivKey,\n\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PRIVATEKEY );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( password != NULL )\n\t\t\t\t{\n\t\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) password, \n\t\t\t\t\t\t\t\tpasswordLength );\n\t\t\t\tstatus = krnlSendMessage( iCryptEnvelope, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_PASSWORD );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* The caller wasn't expecting encrypted data, let them \n\t\t\t\t   know */\n\t\t\t\tstatus = CRYPT_ERROR_WRONGKEY;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, outData, outDataMaxLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tENSURES( msgData.length < inDataLength && \\\n\t\t\t\t\t msgData.length < outDataMaxLength );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Fetch any addition error information that may be available */\n\t\treadErrorInfo( errorInfo, iCryptEnvelope );\n\t\t}\n\tkrnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusOK( status ) )\n\t\t*outDataLength = msgData.length;\n\n\tassert( !cryptArgError( status ) );\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tData Sign/Verify Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nint envelopeSign( IN_BUFFER_OPT( inDataLength ) const void *inData, \n\t\t\t\t  IN_DATALENGTH_Z const int inDataLength,\n\t\t\t\t  OUT_BUFFER( outDataMaxLength, \\\n\t\t\t\t\t\t\t  *outDataLength ) void *outData, \n\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t  IN_ENUM_OPT( CRYPT_CONTENT ) \\\n\t\t\t\t\tconst CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iSigKey,\n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t  OUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ENVELOPE iCryptEnvelope;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength + 1024 );\n\tint status;\n\n\tassert( ( inData == NULL && inDataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( inData, inDataLength ) );\n\tassert( isWritePtrDynamic( outData, outDataMaxLength ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( ( inData != NULL && \\\n\t\t\t\tinDataLength > 16 && inDataLength < MAX_BUFFER_SIZE ) || \\\n\t\t\t  ( inData == NULL && inDataLength == 0 && \\\n\t\t\t\tcontentType == CRYPT_CONTENT_NONE && \\\n\t\t\t\tisHandleRangeValid( iCmsAttributes ) ) );\n\tREQUIRES( outDataMaxLength > 16 && \\\n\t\t\t  outDataMaxLength >= inDataLength + 512 && \\\n\t\t\t  outDataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( contentType, CRYPT_CONTENT ) );\n\tREQUIRES( isHandleRangeValid( iSigKey ) );\n\tREQUIRES( iCmsAttributes == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iCmsAttributes ) );\n\n\t/* Clear return values.  Note that we can't clear the output buffer \n\t   at this point since this function is frequently used for in-place \n\t   processing, so we clear it after we've pushed the input data */\n\t*outDataLength = 0;\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Create an envelope to sign the data, add the signature key and\n\t   optional signing attributes, and pop the signed result */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_CMS );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\t\treturn( status );\n\t\t}\n\tiCryptEnvelope = createInfo.cryptHandle;\n\t( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &minBufferSize, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &inDataLength,\n\t\t\t\t\t\t\t  CRYPT_ENVINFO_DATASIZE );\n\tif( cryptStatusOK( status ) && contentType != CRYPT_CONTENT_NONE )\n\t\t{\n\t\tconst int value = contentType;\t/* int vs.enum */\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &value,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_CONTENTTYPE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iSigKey,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SIGNATURE );\n\t\t}\n\tif( cryptStatusOK( status ) && iCmsAttributes != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iCmsAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SIGNATURE_EXTRADATA );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* If there's no data supplied it's an attributes-only message\n\t\t   containing only authenticated attributes */\n\t\tif( inDataLength <= 0 )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ATTRONLY );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) inData, inDataLength );\n\t\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tENSURES( msgData.length >= inDataLength );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, outData, outDataMaxLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tENSURES( msgData.length > inDataLength && \\\n\t\t\t\t\t msgData.length < outDataMaxLength );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t*outDataLength = msgData.length;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Fetch any addition error information that may be available */\n\t\treadErrorInfo( errorInfo, iCryptEnvelope );\n\t\t}\n\tkrnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );\n\n\tENSURES( cryptStatusError( status ) || \\\n\t\t\t cryptStatusOK( \\\n\t\t\t\t\tcheckCertObjectEncoding( outData, *outDataLength ) ) );\n\tassert( !cryptArgError( status ) );\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 7 ) ) \\\nint envelopeSigCheck( IN_BUFFER( inDataLength ) const void *inData, \n\t\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int inDataLength,\n\t\t\t\t\t  OUT_BUFFER( outDataMaxLength, \\\n\t\t\t\t\t\t\t\t  *outDataLength ) void *outData, \n\t\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iSigCheckKey,\n\t\t\t\t\t  OUT_STATUS int *sigResult, \n\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iSigningCert,\n\t\t\t\t\t  OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iCmsAttributes,\n\t\t\t\t\t  OUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ENVELOPE iCryptEnvelope;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData DUMMY_INIT_STRUCT;\n\tconst int minBufferSize = max( MIN_BUFFER_SIZE, inDataLength );\n\tint status;\n\n\tassert( isReadPtrDynamic( inData, inDataLength ) );\n\tassert( isWritePtrDynamic( outData, outDataMaxLength ) );\n\tassert( isWritePtr( outDataLength, sizeof( int ) ) );\n\tassert( isWritePtr( sigResult, sizeof( int ) ) );\n\tassert( iSigningCert == NULL || \\\n\t\t\tisWritePtr( iSigningCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( iCmsAttributes == NULL || \\\n\t\t\tisWritePtr( iCmsAttributes, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( inDataLength > 16 && inDataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( outDataMaxLength > 16 && \\\n\t\t\t  outDataMaxLength >= inDataLength && \\\n\t\t\t  outDataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( iSigCheckKey == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSigCheckKey ) );\n\n\t/* Clear return values.  Note that we can't clear the output buffer \n\t   at this point since this function is frequently used for in-place \n\t   processing, so we clear it after we've pushed the input data */\n\t*outDataLength = 0;\n\t*sigResult = CRYPT_ERROR;\n\tif( iSigningCert != NULL )\n\t\t*iSigningCert = CRYPT_ERROR;\n\tif( iCmsAttributes != NULL )\n\t\t*iCmsAttributes = CRYPT_ERROR;\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Create an envelope to sig.check the data, push in the signed data and\n\t   sig.check key, and pop the result.  We also speculatively set the\n\t   attributes-only flag to let the enveloping code know that a signed\n\t   message with no content is a zero-data-length message rather than a\n\t   detached signature, which is what this type of message would normally\n\t   be.  In theory we could use checkASN1() here to perform a safety \n\t   check of the envelope data prior to processing, but this has already \n\t   been done by the calling code when the datagram containing the \n\t   enveloped data was read so we don't need to repeat the (rather \n\t   heavyweight) operation here */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\t\treturn( status );\n\t\t}\n\tiCryptEnvelope = createInfo.cryptHandle;\n\t( void ) krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &minBufferSize, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ATTRONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) inData, inDataLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tENSURES( msgData.length >= inDataLength );\n\t\t}\n\tmemset( outData, 0, min( 16, outDataMaxLength ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) && iSigCheckKey != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iSigCheckKey,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SIGNATURE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  sigResult, CRYPT_ENVINFO_SIGNATURE_RESULT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, outData, outDataMaxLength );\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_ENV_POPDATA,\n\t\t\t\t\t\t\t\t  &msgData, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tENSURES( msgData.length < inDataLength && \\\n\t\t\t\t\t msgData.length < outDataMaxLength );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && iSigningCert != NULL )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  iSigningCert,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SIGNATURE );\n\t\t}\n\tif( cryptStatusOK( status ) && iCmsAttributes != NULL )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptEnvelope, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  iCmsAttributes,\n\t\t\t\t\t\t\t\t  CRYPT_ENVINFO_SIGNATURE_EXTRADATA );\n\t\tif( cryptStatusError( status ) && iSigningCert != NULL )\n\t\t\t{\n\t\t\tkrnlSendNotifier( *iSigningCert, IMESSAGE_DECREFCOUNT );\n\t\t\t*iSigningCert = CRYPT_ERROR;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Fetch any addition error information that may be available */\n\t\treadErrorInfo( errorInfo, iCryptEnvelope );\n\t\t}\n\tkrnlSendNotifier( iCryptEnvelope, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusOK( status ) )\n\t\t*outDataLength = msgData.length;\n\n\tassert( !cryptArgError( status ) );\n\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t}\n#endif /* USE_ENVELOPES */\n"
  },
  {
    "path": "deps/cl345/misc/int_err.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Internal Error Reporting API\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdarg.h>\n#include <stdio.h>\t/* Needed on some systems for macro-mapped *printf()'s */\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_ERRMSGS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the error status and, if it's a leaked status code from a lower-\n   level call, convert it to a generic CRYPT_ERROR_FAILED.  These status \n   codes should only ever occur in 'can't-occur' error situations so we only \n   warn in debug mode */\n\nCHECK_RETVAL_ERROR \\\nstatic int convertErrorStatus( IN_ERROR const int status )\n\t{\n\tREQUIRES( cryptStatusError( status ) );\n\n\tif( cryptArgError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Error exit was passed argError status %d\", status ));\n\t\tDEBUG_DUMP_STACKTRACE();\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Format a printf-style error string.  The ERROR_INFO is annotated as\n   OUT_ALWAYS because it's initalised unconditionally, the return status \n   exists only to signal to the caller that, in the case where further \n   information is added to the error information, that it's OK to add this\n   further information.\n\n   In the following we can't make the third arg a NONNULL_ARG because in the \n   Arm ABI it's a scalar value */\n\nRETVAL_BOOL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic BOOLEAN formatErrorString( OUT_ALWAYS ERROR_INFO *errorInfoPtr, \n\t\t\t\t\t\t\t\t  IN_STRING const char *format, \n\t\t\t\t\t\t\t\t  IN va_list argPtr )\n\t{\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tANALYSER_HINT_STRING( format );\n\tANALYSER_HINT_FORMAT_STRING( format );\n\n\tREQUIRES_B( verifyVAList( argPtr ) );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\t/* This function is a bit tricky to deal with because of the \n\t   braindamaged behaviour of some of the underlying functions that it \n\t   may be mapped to.  Specifically, (v)snprintf() returns the number of \n\t   bytes it *could* have written had it felt like it rather than how \n\t   many it actually wrote on non-Windows systems and an error indicator \n\t   with no guarantee of null-termination on Windows systems.  The latter \n\t   isn't a problem because we both catch the error and don't require \n\t   null termination, the former is more problematic because it can lead \n\t   to a length indication that's larger than the actual buffer.  To \n\t   handle this we explicitly check for an overflow as well as an \n\t   error/underflow */\n\terrorInfoPtr->errorStringLength = \\\n\t\t\t\tvsprintf_s( errorInfoPtr->errorString, MAX_ERRMSG_SIZE, \n\t\t\t\t\t\t\tformat, argPtr ); \n\tif( errorInfoPtr->errorStringLength <= 0 || \\\n\t\terrorInfoPtr->errorStringLength > MAX_ERRMSG_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid error string data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tsetErrorString( errorInfoPtr, \n\t\t\t\t\t\t\"(Couldn't record error information)\", 35 );\n\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Append a second error string containing further explanatory information \n   to an existing one.  There's no failure/success return value for this \n   function since there's not much that we can do in the case of a failure, \n   we rely on the existing primary error string to convey as much \n   information as possible */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void appendErrorString( INOUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t\t\t\t   IN_BUFFER( extErrorStringLength ) \\\n\t\t\t\t\t\t\t\t\tconst char *extErrorString, \n\t\t\t\t\t\t\t   IN_LENGTH_ERRORMESSAGE \\\n\t\t\t\t\t\t\t\t\tconst int extErrorStringLength )\n\t{\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtrDynamic( extErrorString, extErrorStringLength ) );\n\n\tREQUIRES_V( errorInfoPtr->errorStringLength > 0 && \\\n\t\t\t\terrorInfoPtr->errorStringLength <= MAX_ERRMSG_SIZE );\n\tREQUIRES_V( extErrorStringLength > 0 && \\\n\t\t\t\textErrorStringLength <= MAX_ERRMSG_SIZE );\n\n\t/* If there's no room to store the combined strings, don't try and \n\t   append the second string */\n\tif( errorInfoPtr->errorStringLength + \\\n\t\t\t\t\t\t\textErrorStringLength >= MAX_ERRMSG_SIZE - 8 )\n\t\treturn;\n\n\tREQUIRES_V( boundsCheck( errorInfoPtr->errorStringLength,\n\t\t\t\t\t\t\t extErrorStringLength, MAX_ERRMSG_SIZE ) );\n\tmemcpy( errorInfoPtr->errorString + errorInfoPtr->errorStringLength,\n\t\t\textErrorString, extErrorStringLength );\n\terrorInfoPtr->errorStringLength += extErrorStringLength;\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClear/Set/Copy Error Strings\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a fixed string as the error message.  This is used to set a \n   predefined error string from something like a table of error messages */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid clearErrorString( OUT ERROR_INFO *errorInfoPtr )\n\t{\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid setErrorString( OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t\t IN_BUFFER( stringLength ) const char *string, \n\t\t\t\t\t IN_LENGTH_ERRORMESSAGE const int stringLength )\n\t{\n\tint length = stringLength;\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtrDynamic( string, stringLength ) );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\t/* Since we're already in an error-handling function we don't use the \n\t   REQUIRES() predicate (which would result in an infinite page fault)\n\t   but make the sanity-checking of parameters explicit */\n\tif( stringLength <= 0 || stringLength > MAX_ERRMSG_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid error string data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tstring = \"(Couldn't record error information)\";\n\t\tlength = 35;\n\t\t}\n\t\n\tREQUIRES_V( rangeCheck( length, 1, MAX_ERRMSG_SIZE ) );\n\tmemcpy( errorInfoPtr->errorString, string, length );\n\terrorInfoPtr->errorStringLength = length;\n\t}\n\n/* Copy error information from a low-level state structure (for example a \n   stream) to a high-level one (for example a session or envelope) */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid copyErrorInfo( OUT ERROR_INFO *destErrorInfoPtr, \n\t\t\t\t\tconst ERROR_INFO *srcErrorInfoPtr )\n\t{\n\tassert( isWritePtr( destErrorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( srcErrorInfoPtr, sizeof( ERROR_INFO ) ) );\n\n\tmemset( destErrorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\tif( srcErrorInfoPtr->errorStringLength > 0 )\n\t\t{\n\t\tsetErrorString( destErrorInfoPtr, srcErrorInfoPtr->errorString, \n\t\t\t\t\t\tsrcErrorInfoPtr->errorStringLength );\n\t\t}\n\t}\n\n/* Read error information from an object into an error-info structure */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint readErrorInfo( OUT ERROR_INFO *errorInfo, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE objectHandle )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( objectHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( objectHandle ) );\n\n\t/* Clear return value */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Read any additional error information that may be available */\n\tsetMessageData( &msgData, errorInfo->errorString, MAX_ERRMSG_SIZE );\n\tstatus = krnlSendMessage( objectHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_ATTRIBUTE_ERRORMESSAGE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\terrorInfo->errorStringLength = msgData.length;\n\tENSURES( errorInfo->errorStringLength > 0 && \\\n\t\t\t errorInfo->errorStringLength < MAX_ERRMSG_SIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tReturn Extended Error Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after recording a detailed error message.  This is used by lower-\n   level code to provide more information to the caller than a basic error \n   code.  Felix qui potuit rerum cognoscere causas.\n\n   Since we're already in an error-handling function when we call these \n   functions we don't use the REQUIRES() predicate (which would result in an \n   infinite page fault) but make the sanity-checking of parameters \n   explicit */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtFn( IN_ERROR const int status, \n\t\t\t  OUT ERROR_INFO *errorInfoPtr, \n\t\t\t  FORMAT_STRING const char *format, ... )\n\t{\n\tva_list argPtr;\n\tconst int localStatus = convertErrorStatus( status );\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\tva_start( argPtr, format );\n\tformatErrorString( errorInfoPtr, format, argPtr );\n\tva_end( argPtr );\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( localStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtArgFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t FORMAT_STRING const char *format, ... )\n\t{\n\tva_list argPtr;\n\n\t/* This function is identical to retExtFn() except that it doesn't trap\n\t   CRYPT_ARGERROR_xxx values, since they're valid return values in some\n\t   cases */\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\tva_start( argPtr, format );\n\tformatErrorString( errorInfoPtr, format, argPtr );\n\tva_end( argPtr );\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) STDC_PRINTF_FN( 4, 5 ) \\\nint retExtObjFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t IN_HANDLE const CRYPT_HANDLE extErrorObject, \n\t\t\t\t FORMAT_STRING const char *format, ... )\n\t{\n\tERROR_INFO extErrorInfo;\n\tva_list argPtr;\n\tconst int localStatus = convertErrorStatus( status );\n\tBOOLEAN errorStringOK;\n\tint errorStringLength, extErrorStatus;\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\tREQUIRES( extErrorObject == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( extErrorObject ) );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\t/* Format the basic error string */\n\tva_start( argPtr, format );\n\terrorStringOK = formatErrorString( errorInfoPtr, format, argPtr );\n\tva_end( argPtr );\n\tif( !errorStringOK )\n\t\t{\n\t\t/* If we couldn't format the basic error string then there's no \n\t\t   point in continuing.  formatErrorString() throws a debug \n\t\t   exception if there's a problem so there's no need to throw one \n\t\t   here */\n\t\treturn( localStatus );\n\t\t}\n\terrorStringLength = errorInfoPtr->errorStringLength;\n\tENSURES( errorStringLength > 0 && errorStringLength < MAX_ERRMSG_SIZE );\n\n\t/* Check whether there's any additional error information available */\n\textErrorStatus = readErrorInfo( &extErrorInfo, extErrorObject );\n\tif( cryptStatusError( extErrorStatus ) )\n\t\t{\n\t\t/* Nothing further to report, exit */\n\t\treturn( localStatus );\n\t\t}\n\n\t/* There's additional information present via the additional object, \n\t   fetch it and append it to the higher-level error message */\n\tif( errorStringLength + \\\n\t\t\textErrorInfo.errorStringLength < MAX_ERRMSG_SIZE - 32 )\n\t\t{\n\t\tREQUIRES( boundsCheck( errorStringLength + 26, \n\t\t\t\t\t\t\t   extErrorInfo.errorStringLength,\n\t\t\t\t\t\t\t   MAX_ERRMSG_SIZE ) );\n\t\tappendErrorString( errorInfoPtr, \". Additional information: \", 26 );\n\t\tappendErrorString( errorInfoPtr, extErrorInfo.errorString, \n\t\t\t\t\t\t   extErrorInfo.errorStringLength );\n\t\t}\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( localStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 5 ) ) STDC_PRINTF_FN( 5, 6 ) \\\nint retExtStrFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t IN_BUFFER( extErrorStringLength ) const char *extErrorString, \n\t\t\t\t IN_LENGTH_ERRORMESSAGE const int extErrorStringLength,\n\t\t\t\t FORMAT_STRING const char *format, ... )\n\t{\n\tva_list argPtr;\n\tconst int localStatus = convertErrorStatus( status );\n\tBOOLEAN errorStringOK;\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtrDynamic( extErrorString, extErrorStringLength ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\tREQUIRES( extErrorStringLength > 0 && \\\n\t\t\t  extErrorStringLength < MAX_ERRMSG_SIZE );\n\n\t/* Clear return value */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\n\t/* Format the basic error string */\n\tva_start( argPtr, format );\n\terrorStringOK = formatErrorString( errorInfoPtr, format, argPtr );\n\tva_end( argPtr );\n\tif( !errorStringOK )\n\t\t{\n\t\t/* If we couldn't format the basic error string then there's no \n\t\t   point in continuing.  formatErrorString() throws a debug \n\t\t   exception if there's a problem so there's no need to throw one \n\t\t   here */\n\t\treturn( localStatus );\n\t\t}\n\n\t/* Append the additional status string */\n\tappendErrorString( errorInfoPtr, extErrorString, extErrorStringLength );\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( localStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3, 4 ) ) STDC_PRINTF_FN( 4, 5 ) \\\nint retExtErrFn( IN_ERROR const int status, \n\t\t\t\t OUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t const ERROR_INFO *existingErrorInfoPtr, \n\t\t\t\t FORMAT_STRING const char *format, ... )\n\t{\n\tva_list argPtr;\n\tconst int localStatus = convertErrorStatus( status );\n\tchar extErrorString[ MAX_ERRMSG_SIZE + 8 ];\n\tBOOLEAN errorStringOK;\n\tint extErrorStringLength;\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( existingErrorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\t/* We can't clear the return value at this point because errorInfoPtr\n\t   could be the same as existingErrorInfoPtr */\n\n\t/* This function is typically used when the caller wants to convert \n\t   something like \"Low-level error string\" into \"High-level error \n\t   string: Low-level error string\".  Since the low-level error string \n\t   may already be held in the errorInfo buffer where the high-level \n\t   error string needs to go, we copy the string into a temporary buffer \n\t   from where it can be appended back onto the string in the errorInfo \n\t   buffer */\n\tif( existingErrorInfoPtr->errorStringLength > 0 && \\\n\t\texistingErrorInfoPtr->errorStringLength <= MAX_ERRMSG_SIZE )\n\t\t{\n\t\tREQUIRES( rangeCheck( existingErrorInfoPtr->errorStringLength, 1, \n\t\t\t\t\t\t\t  MAX_ERRMSG_SIZE ) );\n\t\tmemcpy( extErrorString, existingErrorInfoPtr->errorString,\n\t\t\t\texistingErrorInfoPtr->errorStringLength );\n\t\textErrorStringLength = existingErrorInfoPtr->errorStringLength;\n\t\t}\n\telse\n\t\t{\n\t\tmemcpy( extErrorString, \"(No additional information)\", 27 );\n\t\textErrorStringLength = 27;\n\t\t}\n\tENSURES( extErrorStringLength > 0 && \\\n\t\t\t extErrorStringLength <= MAX_ERRMSG_SIZE );\n\n\t/* Format the basic error string */\n\tmemset( errorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\tva_start( argPtr, format );\n\terrorStringOK = formatErrorString( errorInfoPtr, format, argPtr );\n\tva_end( argPtr );\n\tif( !errorStringOK )\n\t\t{\n\t\t/* If we couldn't format the basic error string then there's no \n\t\t   point in continuing.  formatErrorString() throws a debug \n\t\t   exception if there's a problem so there's no need to throw one \n\t\t   here */\n\t\treturn( localStatus );\n\t\t}\n\n\t/* Append the additional status string */\n\tappendErrorString( errorInfoPtr, extErrorString, extErrorStringLength );\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( localStatus );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) STDC_PRINTF_FN( 3, 4 ) \\\nint retExtErrAltFn( IN_ERROR const int status, \n\t\t\t\t\tINOUT ERROR_INFO *errorInfoPtr, \n\t\t\t\t\tFORMAT_STRING const char *format, ... )\n\t{\n\tva_list argPtr;\n\tconst int localStatus = convertErrorStatus( status );\n\tchar extErrorString[ MAX_ERRMSG_SIZE + 8 ];\n\tint extErrorStringLength;\n\n\tassert( isWritePtr( errorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( format, 4 ) );\n\n\t/* This function is typically used when the caller wants to convert \n\t   something like \"Low-level error string\" into \"Low-level error string,\n\t   additional comments\".  \n\t   \n\t   First we need to check that there's actually a base error string \n\t   present.  This situation can occur when a low-level function returns \n\t   a cryptlib-level error status without getting/setting any extended \n\t   error information, which then percolates up to a point where it's \n\t   returned via a retExt() */\n\tif( errorInfoPtr->errorStringLength <= 0 || \\\n\t\terrorInfoPtr->errorStringLength > MAX_ERRMSG_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid error string data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tsetErrorString( errorInfoPtr, \n\t\t\t\t\t\t\"(Couldn't record error information)\", 35 );\n\t\t}\n\n\t/* Format the additional-comments string prior appending it to the base\n\t   error string */\n\tva_start( argPtr, format );\n\textErrorStringLength = vsprintf_s( extErrorString, MAX_ERRMSG_SIZE, \n\t\t\t\t\t\t\t\t\t   format, argPtr ); \n\tva_end( argPtr );\n\tif( extErrorStringLength <= 0 || extErrorStringLength > MAX_ERRMSG_SIZE )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid error string data\" ));\n\t\tassert( DEBUG_WARN );\n\t\tsetErrorString( errorInfoPtr, \n\t\t\t\t\t\t\"(Couldn't record error information)\", 35 );\n\t\treturn( localStatus );\n\t\t}\n\n\t/* Append the additional status string */\n\tappendErrorString( errorInfoPtr, extErrorString, extErrorStringLength );\n\n\tDEBUG_PUTS( errorInfoPtr->errorString );\n\treturn( localStatus );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tHelper Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Additional helper functions used to provide extended information for\n   error messages.  The first set of functions provides names for error\n   status values, algorithms, and key IDs */\n\ntypedef struct {\n\tconst int value;\n\tconst char *description;\n\t} DESCRIPTION_MAP;\n\nCHECK_RETVAL \\\nconst char *getStatusName( IN_STATUS const int errorStatus )\n\t{\n\tstatic const DESCRIPTION_MAP descriptionMap[] = {\n\t\t{ CRYPT_ERROR_PARAM1, \"CRYPT_ERROR_PARAM1\" },\n\t\t{ CRYPT_ERROR_PARAM2, \"CRYPT_ERROR_PARAM2\" },\n\t\t{ CRYPT_ERROR_PARAM3, \"CRYPT_ERROR_PARAM3\" },\n\t\t{ CRYPT_ERROR_PARAM4, \"CRYPT_ERROR_PARAM4\" },\n\t\t{ CRYPT_ERROR_PARAM5, \"CRYPT_ERROR_PARAM5\" },\n\t\t{ CRYPT_ERROR_PARAM6, \"CRYPT_ERROR_PARAM6\" },\n\t\t{ CRYPT_ERROR_PARAM7, \"CRYPT_ERROR_PARAM7\" },\n\t\t{ CRYPT_ERROR_MEMORY, \"CRYPT_ERROR_MEMORY\" },\n\t\t{ CRYPT_ERROR_NOTINITED, \"CRYPT_ERROR_NOTINITED\" },\n\t\t{ CRYPT_ERROR_INITED, \"CRYPT_ERROR_INITED\" },\n\t\t{ CRYPT_ERROR_NOSECURE, \"CRYPT_ERROR_NOSECURE\" },\n\t\t{ CRYPT_ERROR_RANDOM, \"CRYPT_ERROR_RANDOM\" },\n\t\t{ CRYPT_ERROR_FAILED, \"CRYPT_ERROR_FAILED\" },\n\t\t{ CRYPT_ERROR_INTERNAL, \"CRYPT_ERROR_INTERNAL\" },\n\t\t{ CRYPT_ERROR_NOTAVAIL, \"CRYPT_ERROR_NOTAVAIL\" },\n\t\t{ CRYPT_ERROR_PERMISSION, \"CRYPT_ERROR_PERMISSION\" },\n\t\t{ CRYPT_ERROR_WRONGKEY, \"CRYPT_ERROR_WRONGKEY\" },\n\t\t{ CRYPT_ERROR_INCOMPLETE, \"CRYPT_ERROR_INCOMPLETE\" },\n\t\t{ CRYPT_ERROR_COMPLETE, \"CRYPT_ERROR_COMPLETE\" },\n\t\t{ CRYPT_ERROR_TIMEOUT, \"CRYPT_ERROR_TIMEOUT\" },\n\t\t{ CRYPT_ERROR_INVALID, \"CRYPT_ERROR_INVALID\" },\n\t\t{ CRYPT_ERROR_SIGNALLED, \"CRYPT_ERROR_SIGNALLED\" },\n\t\t{ CRYPT_ERROR_OVERFLOW, \"CRYPT_ERROR_OVERFLOW\" },\n\t\t{ CRYPT_ERROR_UNDERFLOW, \"CRYPT_ERROR_UNDERFLOW\" },\n\t\t{ CRYPT_ERROR_BADDATA, \"CRYPT_ERROR_BADDATA\" },\n\t\t{ CRYPT_ERROR_SIGNATURE, \"CRYPT_ERROR_SIGNATURE\" },\n\t\t{ CRYPT_ERROR_OPEN, \"CRYPT_ERROR_OPEN\" },\n\t\t{ CRYPT_ERROR_READ, \"CRYPT_ERROR_READ\" },\n\t\t{ CRYPT_ERROR_WRITE, \"CRYPT_ERROR_WRITE\" },\n\t\t{ CRYPT_ERROR_NOTFOUND, \"CRYPT_ERROR_NOTFOUND\" },\n\t\t{ CRYPT_ERROR_DUPLICATE, \"CRYPT_ERROR_DUPLICATE\" },\n\t\t{ CRYPT_ENVELOPE_RESOURCE, \"CRYPT_ENVELOPE_RESOURCE\" },\n\t\t{ CRYPT_OK, \"<<<Unknown>>>\" }, { CRYPT_OK, \"<<<Unknown>>>\" },\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_EXT( cryptStatusError( errorStatus ), \"<<<Unknown>>>\" );\n\n\tLOOP_MED( i = 0, descriptionMap[ i ].value != CRYPT_OK && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( descriptionMap, \\\n\t\t\t\t\t\t\t\t\t\t\t DESCRIPTION_MAP ), i++ )\n\t\t{\n\t\tif( descriptionMap[ i ].value == errorStatus )\n\t\t\treturn( descriptionMap[ i ].description );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, \"<<<Unknown>>>\" );\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( descriptionMap, DESCRIPTION_MAP ),\n\t\t\t\t \"<<<Unknown>>>\" );\n\n\tretIntError_Ext( \"<<<Unknown>>>\" );\n\t}\n\nCHECK_RETVAL \\\nconst char *getAlgoName( IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tstatic const DESCRIPTION_MAP descriptionMap[] = {\n\t\t/* Conventional algorithms */\n\t\t{ CRYPT_ALGO_DES, \"DES\" },\n\t\t{ CRYPT_ALGO_3DES, \"3DES\" },\n\t\t{ CRYPT_ALGO_IDEA, \"IDEA\" },\n\t\t{ CRYPT_ALGO_CAST, \"CAST-128\" },\n\t\t{ CRYPT_ALGO_RC2, \"RC2\" },\n\t\t{ CRYPT_ALGO_RC4, \"RC4\" },\n\t\t{ CRYPT_ALGO_AES, \"AES\" },\n\t\t/* PKC algorithms */\n\t\t{ CRYPT_ALGO_DH, \"DH\" },\n\t\t{ CRYPT_ALGO_RSA, \"RSA\" },\n\t\t{ CRYPT_ALGO_DSA, \"DSA\" },\n\t\t{ CRYPT_ALGO_ELGAMAL, \"ElGamal\" },\n\t\t{ CRYPT_ALGO_ECDSA,\t\"ECDSA\" },\n\t\t{ CRYPT_ALGO_ECDH, \"ECDH\" },\n\t\t/* Hash algorithms */\n\t\t{ CRYPT_ALGO_MD5, \"MD5\" },\n\t\t{ CRYPT_ALGO_SHA1, \"SHA1\" },\n\t\t{ CRYPT_ALGO_SHA2, \"SHA2\" },\n\t\t{ CRYPT_ALGO_SHAng,\t\"SHAng\" },\n\t\t/* Generic secret algorithm.  This is a bit of an odd one because \n\t\t   it's only visible internally, but we need to have some \n\t\t   description available for it in case an attempt to create a \n\t\t   context with it fails */\n\t\t{ CRYPT_IALGO_GENERIC_SECRET, \"Generic Secret\" },\n\t\t{ CRYPT_ALGO_NONE, \"NONE\" }, { CRYPT_ALGO_NONE, \"NONE\" },\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_EXT( isConvAlgo( cryptAlgo ) || isPkcAlgo( cryptAlgo ) || \\\n\t\t\t\t  isHashAlgo( cryptAlgo ) || isSpecialAlgo( cryptAlgo ), \n\t\t\t\t  \"<<<Unknown>>>\" );\n\n\tLOOP_MED( i = 0, descriptionMap[ i ].value != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( descriptionMap, \\\n\t\t\t\t\t\t\t\t\t\t\t DESCRIPTION_MAP ), i++ )\n\t\t{\n\t\tif( descriptionMap[ i ].value == cryptAlgo )\n\t\t\treturn( descriptionMap[ i ].description );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, \"<<<Unknown>>>\" );\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( descriptionMap, DESCRIPTION_MAP ),\n\t\t\t\t \"<<<Unknown>>>\" );\n\n\tretIntError_Ext( \"<<<Unknown>>>\" );\n\t}\n\nCHECK_RETVAL \\\nconst char *getKeyIDName( IN_KEYID const CRYPT_KEYID_TYPE keyIDtype )\n\t{\n\tstatic const DESCRIPTION_MAP descriptionMap[] = {\n\t\t{ CRYPT_KEYID_NAME, \"CRYPT_KEYID_NAME\" },\n\t\t{ CRYPT_KEYID_URI, \"CRYPT_KEYID_URI\" },\n\t\t{ CRYPT_IKEYID_KEYID, \"CRYPT_IKEYID_KEYID\" },\n\t\t{ CRYPT_IKEYID_PGPKEYID, \"CRYPT_IKEYID_PGPKEYID\" },\n\t\t{ CRYPT_IKEYID_CERTID, \"CRYPT_IKEYID_CERTID\" },\n\t\t{ CRYPT_IKEYID_SUBJECTID, \"CRYPT_IKEYID_SUBJECTID\" },\n\t\t{ CRYPT_IKEYID_ISSUERID, \"CRYPT_IKEYID_ISSUERID\" },\n\t\t{ CRYPT_IKEYID_ISSUERANDSERIALNUMBER, \"CRYPT_IKEYID_ISSUERANDSERIALNUMBER\" },\n\t\t{ CRYPT_KEYID_NONE, \"NONE\" }, { CRYPT_KEYID_NONE, \"NONE\" },\n\t\t};\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_EXT( isEnumRange( keyIDtype, CRYPT_KEYID ), \"<<<Unknown>>>\" );\n\n\tLOOP_MED( i = 0, descriptionMap[ i ].value != CRYPT_KEYID_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( descriptionMap, \\\n\t\t\t\t\t\t\t\t\t\t\t DESCRIPTION_MAP ), i++ )\n\t\t{\n\t\tif( descriptionMap[ i ].value == keyIDtype )\n\t\t\treturn( descriptionMap[ i ].description );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, \"<<<Unknown>>>\" );\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( descriptionMap, DESCRIPTION_MAP ),\n\t\t\t\t \"<<<Unknown>>>\" );\n\n\tretIntError_Ext( \"<<<Unknown>>>\" );\n\t}\n\n/* Format a fingerprint (hash value) for display in an error message */\n\nSTDC_NONNULL_ARG( ( 1, 3 ) ) \\\nvoid formatFingerprint( OUT_BUFFER_FIXED( fingerprintTextMaxLen ) \\\n\t\t\t\t\t\t\tchar *fingerprintText, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 32 ) const int fingerprintTextMaxLen,\n\t\t\t\t\t\tIN_BUFFER( fingerprintLen ) const BYTE *fingerprint,\n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int fingerprintLen )\n\t{\n\tassert( isWritePtr( fingerprintText, fingerprintTextMaxLen ) );\n\tassert( isReadPtr( fingerprint, fingerprintLen ) );\n\n\tREQUIRES_V( fingerprintTextMaxLen >= 32 && \\\n\t\t\t\tfingerprintTextMaxLen <= MAX_INTLENGTH_SHORT );\n\tREQUIRES_V( fingerprintLen >= 8 && \\\n\t\t\t\tfingerprintLen <= MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\tmemset( fingerprintText, 0, fingerprintTextMaxLen );\n\n\t/* Format the fingerprint as ACII hex data.  The potential expansion \n\t   factor is ( fingerprintLen * 3 ) + 1 (+3 for the ellipses, but -2 for \n\t   the absent spaces at the start and end of the string).  Since we \n\t   currently limit the output to 8 bytes we never output more than 25 \n\t   characters of text which is well under the 32-byte minimum buffer \n\t   size */\n\tsprintf_s( fingerprintText, fingerprintTextMaxLen, \n\t\t\t   \"%02X %02X %02X %02X...%02X %02X %02X %02X\",\n\t\t\t   fingerprint[ 0 ], fingerprint[ 1 ], \n\t\t\t   fingerprint[ 2 ], fingerprint[ 3 ],\n\t\t\t   fingerprint[ fingerprintLen - 4 ], \n\t\t\t   fingerprint[ fingerprintLen - 3 ],\n\t\t\t   fingerprint[ fingerprintLen - 2 ], \n\t\t\t   fingerprint[ fingerprintLen - 1 ] );\n\t}\n#else\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMinimal Error Reporting Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Even if we're not using extended error reporting there is one minimal \n   facility that we still need to support, which is the copying of an integer \n   error code from source to destination */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid copyErrorInfo( OUT ERROR_INFO *destErrorInfoPtr, \n\t\t\t\t\tconst ERROR_INFO *srcErrorInfoPtr )\n\t{\n\tassert( isWritePtr( destErrorInfoPtr, sizeof( ERROR_INFO ) ) );\n\tassert( isReadPtr( srcErrorInfoPtr, sizeof( ERROR_INFO ) ) );\n\n\tmemset( destErrorInfoPtr, 0, sizeof( ERROR_INFO ) );\n\tdestErrorInfoPtr->errorCode = srcErrorInfoPtr->errorCode;\n\t}\n#endif /* USE_ERRMSGS */\n"
  },
  {
    "path": "deps/cl345/misc/int_mem.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Internal Memory Management API\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdarg.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tChecked Buffer Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add cookies around a buffer, used to check for overwrites.  This converts\n   a memory buffer:\n\n\t| bufPtr\n\tv\n\t+---------------+\n\t|\tBuffer\t\t|\n\t+---------------+\n\t|<-- bufSize -->|\n\n   into:\n\n\t\t\t| bufPtr\n\t\t\tv\n\t+-------+---------------+-------+\n\t|Cookie |\tBuffer\t\t|Cookie\t|\n\t+-------+---------------+-------+\n\t\t\t|<-- bufSize -->|\n\n   To do this we need to convert an allocation of of bufSize bytes into one\n   of COOKIE_SIZE + bufSize + COOKIE_SIZE bytes, and then return a pointer \n   to the actual buffer data inside the cookie'd buffer */\n\n/* A buffer cookie, used as a canary to check for overwrites */\n\n#ifdef FIXED_SEED\n  #define SAFEBUFFER_COOKIE\t\t( ( uintptr_t ) FIXED_SEED )\n#else\n  #define SAFEBUFFER_COOKIE\t\t0xAAFFAAFF\n#endif /* FIXED_SEED */\n\n/* Initialise a safe buffer with canaries and check that the canaries \n   are still valid.  The annotations here aren't quite correct since \n   we're accessing memory just outside the buffer, but there's no way to \n   correctly annotate what's going on */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid safeBufferInit( INOUT_BUFFER_FIXED( bufSize ) void *buffer, \n\t\t\t\t\t IN_DATALENGTH const int bufSize )\n\t{\n\tBYTE *bufPtr = ( ( BYTE * ) buffer ) - SAFEBUFFER_COOKIE_SIZE;\n\tconst uintptr_t startCookie = ( uintptr_t ) buffer ^ SAFEBUFFER_COOKIE;\n\tconst uintptr_t endCookie = \\\n\t\t\t\t\t\t( ( uintptr_t ) bufPtr + SAFEBUFFER_COOKIE_SIZE + \\\n\t\t\t\t\t\t\t\t\t\tbufSize ) ^ SAFEBUFFER_COOKIE;\n\n\tREQUIRES_V( bufSize >= 256 && bufSize < MAX_BUFFER_SIZE );\n\n\t/* Insert the cookies, which correspond to the address at which they're\n\t   stored XOR'd with a fixed magic value */\n\t*( ( uintptr_t * ) bufPtr ) = startCookie;\n\t*( ( uintptr_t * ) ( bufPtr + SAFEBUFFER_COOKIE_SIZE + bufSize ) ) = endCookie;\n\t}\n\nCHECK_RETVAL_PTR \\\nvoid *safeBufferAlloc( IN_DATALENGTH const int bufSize )\n\t{\n\tvoid *bufPtr;\n\t\n\tREQUIRES_N( bufSize >= MIN_BUFFER_SIZE && bufSize < MAX_BUFFER_SIZE );\n\t\n\t/* Allocate the buffer, with extra space for the cookies and overflow \n\t   data.  The overflow amount is added implicitly here because the \n\t   caller only records the buffer size as being the base size without \n\t   the overflow amount, which means that when we perform the cookie \n\t   check on { buffer, bufSize } there's additional overflow space \n\t   between the purported end of the buffer and the cookie */\n\tbufPtr = clAlloc( \"safeBufferAlloc\", SAFEBUFFER_SIZE( bufSize ) + 8 );\n\tif( bufPtr == NULL )\n\t\treturn( NULL );\n\tsafeBufferInit( SAFEBUFFER_PTR( bufPtr ), bufSize );\n\n\treturn( SAFEBUFFER_PTR( bufPtr ) );\n\t}\n\nvoid safeBufferFree( const void *buffer )\n\t{\n\tvoid *bufPtr = ( ( BYTE * ) buffer ) - SAFEBUFFER_COOKIE_SIZE;\n\n\t/* We can't check the overall buffer state since we don't know its size, \n\t   but we can check at least the start cookie for validity */\n\tif( *( ( uintptr_t * ) bufPtr ) != ( ( uintptr_t ) buffer ^ SAFEBUFFER_COOKIE ) )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\n\tclFree( \"safeBufferFree\", bufPtr );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN safeBufferCheck( IN_BUFFER( bufSize ) const void *buffer, \n\t\t\t\t\t\t IN_DATALENGTH const int bufSize )\n\t{\n\tconst BYTE *bufPtr = ( ( const BYTE * ) buffer ) - SAFEBUFFER_COOKIE_SIZE;\n\n\tREQUIRES_B( bufSize > 4 && bufSize < MAX_BUFFER_SIZE );\n\n\t/* Check that the cookies haven't been disturbed */\n\tif( *( ( uintptr_t * ) bufPtr ) != ( ( uintptr_t ) buffer ^ SAFEBUFFER_COOKIE ) )\n\t\treturn( FALSE );\n\tif( *( ( uintptr_t * ) ( bufPtr + SAFEBUFFER_COOKIE_SIZE + bufSize ) ) != \\\n\t\t( ( ( uintptr_t ) bufPtr + SAFEBUFFER_COOKIE_SIZE + bufSize ) ^ SAFEBUFFER_COOKIE ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDynamic Buffer Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Dynamic buffer management functions.  When reading variable-length\n   object data we can usually fit the data into a small fixed-length buffer \n   but occasionally we have to cope with larger data amounts that require a \n   dynamically-allocated buffer.  The following routines manage this \n   process, dynamically allocating and freeing a larger buffer if required */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getDynData( OUT DYNBUF *dynBuf, \n\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   IN_MESSAGE const MESSAGE_TYPE message, \n\t\t\t\t\t   IN_INT const int messageParam )\n\t{\n\tMESSAGE_DATA msgData;\n\tvoid *dataPtr = NULL;\n\tint status;\n\n\tassert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( ( message == IMESSAGE_GETATTRIBUTE_S && \\\n\t\t\t\t( isAttribute( messageParam ) || \\\n\t\t\t\t  isInternalAttribute( messageParam ) ) ) || \\\n\t\t\t  ( message == IMESSAGE_CRT_EXPORT && \\\n\t\t \t\t( messageParam == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\t\t\t  messageParam == CRYPT_CERTFORMAT_CERTCHAIN ) ) );\n\n\t/* Clear return values.  Note that we don't use the usual memset() to \n\t   clear the value since the structure contains the storage for the \n\t   fixed-size portion of the buffer appended to it, and using memset() \n\t   to clear that is just unnecessary overhead */\n\tdynBuf->data = dynBuf->dataBuffer;\n\tdynBuf->length = 0;\n\n\t/* Get the data from the object */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( cryptHandle, message, &msgData, messageParam );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( msgData.length > DYNBUF_SIZE )\n\t\t{\n\t\t/* The data is larger than the built-in buffer size, dynamically\n\t\t   allocate a larger buffer */\n\t\tif( ( dataPtr = clDynAlloc( \"getDynData\", msgData.length ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tmsgData.data = dataPtr;\n\t\tstatus = krnlSendMessage( cryptHandle, message, &msgData,\n\t\t\t\t\t\t\t\t  messageParam );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tclFree( \"getDynData\", dataPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\tdynBuf->data = dataPtr;\n\t\t}\n\telse\n\t\t{\n\t\t/* The data will fit into the built-in buffer, read it directly into\n\t\t   the buffer */\n\t\tmsgData.data = dynBuf->data;\n\t\tstatus = krnlSendMessage( cryptHandle, message, &msgData,\n\t\t\t\t\t\t\t\t  messageParam );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tdynBuf->length = msgData.length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dynCreate( OUT DYNBUF *dynBuf, \n\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType )\n\t{\n\tassert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( isAttribute( attributeType ) || \\\n\t\t\t  isInternalAttribute( attributeType ) );\n\n\treturn( getDynData( dynBuf, cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\tattributeType ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint dynCreateCert( OUT DYNBUF *dynBuf, \n\t\t\t\t   IN_HANDLE const CRYPT_HANDLE cryptHandle,\n\t\t\t\t   IN_ENUM( CRYPT_CERTFORMAT ) \\\n\t\t\t\t   const CRYPT_CERTFORMAT_TYPE formatType )\n\t{\n\tassert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) );\n\n\tREQUIRES( isHandleRangeValid( cryptHandle ) );\n\tREQUIRES( formatType == CRYPT_CERTFORMAT_CERTIFICATE || \\\n\t\t\t  formatType == CRYPT_CERTFORMAT_CERTCHAIN );\n\n\treturn( getDynData( dynBuf, cryptHandle, IMESSAGE_CRT_EXPORT, \n\t\t\t\t\t\tformatType ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid dynDestroy( INOUT DYNBUF *dynBuf )\n\t{\n\tassert( isWritePtr( dynBuf, sizeof( DYNBUF ) ) );\n\tassert( isWritePtrDynamic( dynBuf->data, dynBuf->length ) );\n\n\tREQUIRES_V( dynBuf->data != NULL );\n\tREQUIRES_V( dynBuf->length > 0 && dynBuf->length < MAX_BUFFER_SIZE );\n\n\tzeroise( dynBuf->data, dynBuf->length );\n\tif( dynBuf->data != dynBuf->dataBuffer )\n\t\tclFree( \"dynDestroy\", dynBuf->data );\n\tdynBuf->data = NULL;\n\tdynBuf->length = 0;\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMemory Pool Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Memory pool management functions.  When allocating many small blocks of\n   memory, especially in resource-constrained systems, it's better if we pre-\n   allocate a small memory pool ourselves and grab chunks of it as required,\n   falling back to dynamically allocating memory later on if we exhaust the\n   pool.  The following functions implement the custom memory pool\n   management.  Usage is:\n\n\tinitMemPool( &memPoolState, storage, storageSize );\n\tnewItem = getMemPool( &memPoolState, newItemSize ) */\n\ntypedef struct {\n\tBUFFER( storageSize, storagePos ) \n\tvoid *storage;\t\t\t\t\t/* Memory pool */\n\tint storageSize, storagePos;\t/* Current usage and total size of pool */\n\t} MEMPOOL_INFO;\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckMempool( const MEMPOOL_INFO *state )\n\t{\n\t/* Make sure that the overall pool size information is in order */\n\tif( state->storageSize < 64 || \\\n\t\tstate->storageSize >= MAX_INTLENGTH_SHORT )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckMempool: Storage size\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the pool allocation information is in order */\n\tif( state->storagePos < 0 || \\\n\t\tstate->storagePos >= MAX_INTLENGTH_SHORT || \\\n\t\tstate->storagePos > state->storageSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckMempool: Storage position\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initMemPool( OUT void *statePtr, \n\t\t\t\t  IN_BUFFER( memPoolSize ) void *memPool, \n\t\t\t\t  IN_LENGTH_SHORT_MIN( 64 ) const int memPoolSize )\n\t{\n\tMEMPOOL_INFO *state = ( MEMPOOL_INFO * ) statePtr;\n\n\tassert( isWritePtr( state, sizeof( MEMPOOL_INFO ) ) );\n\tassert( isWritePtrDynamic( memPool, memPoolSize ) );\n\n#if defined( __WIN32__ ) && defined( _MSC_VER )\n\t#pragma warning( disable: 4127 )\t/* Needed for sizeof() in check */\n#endif /* VC++ */\n\tREQUIRES( sizeof( MEMPOOL_STATE ) >= sizeof( MEMPOOL_INFO ) );\n\tREQUIRES( memPoolSize >= 64 && memPoolSize < MAX_INTLENGTH_SHORT );\n#if defined( __WIN32__ ) && defined( _MSC_VER )\n\t#pragma warning( 4: 4127 )\n#endif /* VC++ */\n\n\tmemset( state, 0, sizeof( MEMPOOL_INFO ) );\n\tstate->storage = memPool;\n\tstate->storageSize = memPoolSize;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nvoid *getMemPool( INOUT void *statePtr, IN_LENGTH_SHORT const int size )\n\t{\n\tMEMPOOL_INFO *state = ( MEMPOOL_INFO * ) statePtr;\n\tBYTE *allocPtr;\n\tconst int allocSize = roundUp( size, sizeof( int ) );\n\n\tassert( isWritePtr( state, sizeof( MEMPOOL_INFO ) ) );\n\tassert( isWritePtrDynamic( state->storage, state->storageSize ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( size ) );\n\tREQUIRES_N( allocSize >= sizeof( int ) && \\\n\t\t\t\tallocSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES_N( sanityCheckMempool( state ) );\n\n\t/* If we can't satisfy the request from the memory pool we have to\n\t   allocate the memory block dynamically */\n\tif( state->storagePos + allocSize > state->storageSize )\n\t\treturn( clDynAlloc( \"getMemPool\", size ) );\n\n\t/* We can satisfy the request from the pool:\n\n\t memPool\n\t\t|\n\t\tv\t\t <- size -->\n\t\t+-------+-----------+-------+\n\t\t|\t\t|\t\t\t|\t\t|\n\t\t+-------+-----------+-------+\n\t\t\t\t^\t\t\t^\n\t\t\t\t|\t\t\t|\n\t\t\tstoragePos\tstoragePos' */\n\tallocPtr = ( BYTE * ) state->storage + state->storagePos;\n\tstate->storagePos += allocSize;\n\tENSURES_N( sanityCheckMempool( state ) );\n\n\treturn( allocPtr );\n\t}\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid freeMemPool( INOUT void *statePtr, IN void *memblock )\n\t{\n\tMEMPOOL_INFO *state = ( MEMPOOL_INFO * ) statePtr;\n\n\tassert( isWritePtr( state, sizeof( MEMPOOL_INFO ) ) );\n\tassert( isWritePtrDynamic( state->storage, state->storageSize ) );\n\n\tREQUIRES_V( sanityCheckMempool( state ) );\n\n\t/* If the memory block to free lies within the pool, there's nothing to \n\t   do */\n\tif( memblock >= state->storage && \\\n\t\tmemblock < ( void * ) ( ( BYTE * ) state->storage + \\\n\t\t\t\t\t\t\t\t\t\t   state->storageSize ) )\n\t\treturn;\n\n\t/* It's outside the pool and therefore dynamically allocated, free it */\n\tclFree( \"freeMemPool\", memblock );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDebugging Malloc Support\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Debugging malloc() that dumps memory usage diagnostics to stdout.  Note\n   that these functions are only intended to be used during interactive \n   debugging sessions since they throw exceptions under error conditions \n   rather than returning an error status (the fact that they dump \n   diagnostics to stdout during operation should be a clue as to their\n   intended status and usage) */\n\n#ifdef CONFIG_DEBUG_MALLOC\n\n#ifdef __WIN32__\n  #include <direct.h>\n#endif /* __WIN32__ */\n\n#ifdef __WINCE__\n\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH_STRING ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int wcPrintf( FORMAT_STRING const char *format, ... )\n\t{\n\twchar_t wcBuffer[ 1024 + 8 ];\n\tchar buffer[ 1024 + 8 ];\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vsprintf_s( buffer, 1024, format, argPtr );\n\tva_end( argPtr );\n\tif( length < 1 )\n\t\treturn( length );\n\tmbstowcs( wcBuffer, buffer, length + 1 );\n\tNKDbgPrintfW( wcBuffer );\n\n\treturn( length );\n\t}\n\n#define printf\t\twcPrintf\n\n#endif /* __WINCE__ */\n\nstatic int clAllocIndex = 0;\n\nvoid *clAllocFn( const char *fileName, const char *fnName,\n\t\t\t\t const int lineNo, size_t size )\n\t{\n#ifdef CONFIG_MALLOCTEST\n\tstatic int mallocCount = 0, mallocFailCount = 0;\n#endif /* CONFIG_MALLOCTEST */\n#if defined( __WIN32__ ) || defined( __UNIX__ )\n\tchar buffer[ 512 + 8 ];\n#endif /* __WIN32__ || __UNIX__ */\n\tBYTE *memPtr;\n\tint length;\n\n\tassert( fileName != NULL );\n\tassert( fnName != NULL );\n\tassert( lineNo > 0 );\n\tassert( isIntegerRangeNZ( size ) );\n\n\t/* Strip off the leading path components if we can to reduce the amount\n\t   of noise in the output */\n#if defined( __WIN32__ ) || defined( __UNIX__ )\n\tif( getcwd( buffer, 512 ) != NULL )\n\t\t{\n\t\tconst int pathLen = strlen( buffer ) + 1;\t/* Leading path + '/' */\n\n\t\tassert( pathLen < strlen( fileName ) );\n\t\tfileName += pathLen;\n\t\t}\n#endif /* __WIN32__ || __UNIX__ */\n\n\tlength = DEBUG_PRINT(( \"ALLOC: %s:%s:%d\", fileName, fnName, lineNo ));\n\twhile( length < 46 )\n\t\t{\n\t\tDEBUG_PRINT(( \" \" ));\n\t\tlength++;\n\t\t}\n\tDEBUG_PRINT(( \" %4d - %d bytes.\\n\", clAllocIndex, size ));\n#ifdef CONFIG_MALLOCTEST\n\t/* If we've exceeded the allocation count, make the next attempt to \n\t   allocate memory fail */\n\tif( mallocCount >= mallocFailCount )\n\t\t{\n\t\tmallocCount = 0;\n\t\tmallocFailCount++;\n\n\t\treturn( NULL );\n\t\t}\n\tmallocCount++;\n#endif /* CONFIG_MALLOCTEST */\n\tif( ( memPtr = malloc( size + sizeof( LONG ) ) ) == NULL )\n\t\treturn( NULL );\n\tmputLong( memPtr, clAllocIndex );\t/* Implicit memPtr += sizeof( LONG ) */\n\tclAllocIndex++;\n\treturn( memPtr );\n\t}\n\nvoid clFreeFn( const char *fileName, const char *fnName,\n\t\t\t   const int lineNo, void *memblock )\n\t{\n#if defined( __WIN32__ ) || defined( __UNIX__ )\n\tchar buffer[ 512 + 8 ];\n#endif /* __WIN32__ || __UNIX__ */\n\tBYTE *memPtr = ( BYTE * ) memblock - sizeof( LONG );\n\tint index, length;\n\n\tassert( fileName != NULL );\n\tassert( fnName != NULL );\n\tassert( lineNo > 0 );\n\n\t/* Strip off the leading path components if we can to reduce the amount\n\t   of noise in the output */\n#if defined( __WIN32__ ) || defined( __UNIX__ )\n\tif( getcwd( buffer, 512 ) != NULL )\n\t\t{\n\t\tconst int pathLen = strlen( buffer ) + 1;\t/* Leading path + '/' */\n\n\t\tassert( pathLen < strlen( fileName ) );\n\t\tfileName += pathLen;\n\t\t}\n#endif /* __WIN32__ || __UNIX__ */\n\n\tindex = mgetLong( memPtr );\n\tmemPtr -= sizeof( LONG );\t\t/* mgetLong() changes memPtr */\n\tlength = DEBUG_PRINT(( \"FREE : %s:%s:%d\", fileName, fnName, lineNo ));\n\twhile( length < 46 )\n\t\t{\n\t\tDEBUG_PRINT(( \" \" ));\n\t\tlength++;\n\t\t}\n\tDEBUG_PRINT(( \" %4d.\\n\", index ));\n\tfree( memPtr );\n\t}\n#endif /* CONFIG_DEBUG_MALLOC */\n\n/* Fault-testing malloc() that fails after a given number of allocations */\n\n#ifdef CONFIG_FAULT_MALLOC\n\nstatic int currentAllocCount = 0, failAllocCount = 0;\nstatic BOOLEAN allocFailed = FALSE;\n\nvoid clFaultAllocSetCount( const int number )\n\t{\n\tcurrentAllocCount = 0;\n\tfailAllocCount = number;\n\tallocFailed = FALSE;\n\t}\n\nvoid *clFaultAllocFn( const char *fileName, const char *fnName, \n\t\t\t\t\t  const int lineNo, size_t size )\n\t{\n\t/* If we've failed an allocation we probably shouldn't get here again,\n\t   however if we're running a multithreaded init then the second thread \n\t   could try and allocate memory after the first one has failed */\n\tif( allocFailed )\n\t\t{\n#ifdef __WIN32__\n\t\tDEBUG_PRINT(( \"\\n<<< Further allocation call from thread %X after \"\n\t\t\t\t\t  \"previous call failed, called from %s line %d in \"\n\t\t\t\t\t  \"%s.>>>\\n\", GetCurrentThreadId(), fnName, lineNo, \n\t\t\t\t\t  fileName ));\n#else\n\t\tDEBUG_PRINT(( \"\\n<<< Further allocation call after previous call \"\n\t\t\t\t\t  \"failed, called from %s line %d in %s.>>>\\n\", fnName, \n\t\t\t\t\t  lineNo, fileName ));\n#endif /* __WIN32__  */\n\t\tif( failAllocCount < 15 )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"<<<  (This could be because of a multithreaded \"\n\t\t\t\t\t\t  \"init).>>>\\n\" ));\n\t\t\tDEBUG_PRINT(( \"\\n\" ));\n\t\t\t}\n\t\treturn( NULL );\n\t\t}\n\n\t/* If we haven't reached the failure allocation count, return normally */\n\tif( currentAllocCount < failAllocCount )\n\t\t{\n\t\tcurrentAllocCount++;\n\t\treturn( malloc( size ) );\n\t\t}\n\n\t/* We've reached the failure count, fail the allocation */\n#ifdef __WIN32__\n\tDEBUG_PRINT(( \"\\n<<< Failing allocation call #%d for thread %X, called \"\n\t\t\t\t  \"from %s line %d in %s.>>>\\n\\n\", failAllocCount + 1, \n\t\t\t\t  GetCurrentThreadId(), fnName, lineNo, fileName ));\n#else\n\tDEBUG_PRINT(( \"\\n<<< Failing at allocation call #%d, called from %s line \"\n\t\t\t\t  \"%d in %s.>>>\\n\\n\", failAllocCount + 1, fnName, lineNo, \n\t\t\t\t  fileName ));\n#endif /* __WIN32__  */\n\tallocFailed = TRUE;\n\treturn( NULL );\n\t}\n#endif /* CONFIG_FAULT_MALLOC */\n"
  },
  {
    "path": "deps/cl345/misc/int_string.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Internal String API\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tGeneral-purpose String Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform various string-processing operations */\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strFindCh( IN_BUFFER( strLen ) const char *str, \n\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t   IN_CHAR const int findCh )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\tREQUIRES( findCh >= 0 && findCh <= 0x7F );\n\n\tLOOP_MAX( i = 0, i < strLen, i++ )\n\t\t{\n\t\tif( str[ i ] == findCh )\n\t\t\treturn( i );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\n\treturn( -1 );\n\t}\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint strFindStr( IN_BUFFER( strLen ) const char *str, \n\t\t\t\tIN_LENGTH_SHORT const int strLen, \n\t\t\t\tIN_BUFFER( findStrLen ) const char *findStr, \n\t\t\t\tIN_LENGTH_SHORT const int findStrLen )\n\t{\n\tconst int findCh = toUpper( findStr[ 0 ] );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\tassert( isReadPtrDynamic( findStr, findStrLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\tREQUIRES( isShortIntegerRangeNZ( findStrLen ) );\n\tREQUIRES( findCh >= 0 && findCh <= 0x7F );\n\n\tLOOP_MAX( i = 0, i <= strLen - findStrLen, i++ )\n\t\t{\n\t\tif( toUpper( str[ i ] ) == findCh && \\\n\t\t\t!strCompare( str + i, findStr, findStrLen ) )\n\t\t\treturn( i );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\n\treturn( -1 );\n\t}\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strSkipWhitespace( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t\t   IN_LENGTH_SHORT const int strLen )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\n\tLOOP_MAX( i = 0, \n\t\t\t  i < strLen && ( str[ i ] == ' ' || str[ i ] == '\\t' ), \n\t\t\t  i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\treturn( ( i < strLen ) ? i : -1 );\n\t}\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \\\nint strSkipNonWhitespace( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int strLen )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\n\t/* This differs slightly from strSkipWhitespace() in that EOL is also \n\t   counted as whitespace so there's never an error condition unless\n\t   we don't find anything at all */\n\tLOOP_MAX( i = 0, \n\t\t\t  i < strLen && str[ i ] != ' ' && str[ i ] != '\\t', \n\t\t\t  i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\treturn( i > 0 ? i : -1 );\n\t}\n\nCHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strStripWhitespace( OUT_PTR_COND const char **newStringPtr, \n\t\t\t\t\t\tIN_BUFFER( strLen ) const char *string, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int strLen )\n\t{\n\tint startPos, endPos, LOOP_ITERATOR;\n\n\tassert( isReadPtr( newStringPtr, sizeof( char * ) ) );\n\tassert( isReadPtrDynamic( string, strLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\n\t/* Clear return value */\n\t*newStringPtr = NULL;\n\n\t/* Skip leading and trailing whitespace.  We also count nulls as \n\t   trailing \"whitespace\" because some lower-level drivers and libraries \n\t   that we talk to may pad out buffers with nulls on the assumption \n\t   that the caller is using strlen() to find the end of the string in\n\t   them */\n\tLOOP_MAX( startPos = 0,\n\t\t\t  startPos < strLen && \\\n\t\t\t\t( string[ startPos ] == ' ' || string[ startPos ] == '\\t' ),\n\t\t\t  startPos++ );\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\tif( startPos >= strLen )\n\t\treturn( -1 );\n\t*newStringPtr = string + startPos;\n\tLOOP_MAX( endPos = strLen,\n\t\t\t  endPos > startPos && \\\n\t\t\t\t( string[ endPos - 1 ] == ' ' || \\\n\t\t\t\t  string[ endPos - 1 ] == '\\t' || \\\n\t\t\t\t  string[ endPos - 1 ] == '\\0' ),\n\t\t\t  endPos-- );\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\tENSURES( endPos - startPos > 0 );\n\treturn( endPos - startPos );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSpecial-purpose String Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Extract a substring from a string.  This converts:\n\n\t string\t\t\t\tstartOffset\t\t\t\t\t\t\t strLen\n\t\t|\t\t\t\t\t|\t\t\t\t\t\t\t\t\t|\n\t\tv\t\t\t\t\tv\t\t\t\t\t\t\t\t\tv\n\t\t+-------------------+---------------+-------------------+\n\t\t|\tProcessed data\t|\tWhitespace\t|\tRemaining data\t|\n\t\t+-------------------+---------------+-------------------+\n\n   into:\n\n\t newStr\t\t\t\t length\n\t\t|\t\t\t\t\t|\n\t\tv\t\t\t\t\tv\n\t\t+-------------------+\n\t\t|\tRemaining data\t|\n\t\t+-------------------+ \n\n   The order of the parameters is a bit unusual, normally we'd use \n   { str, strLen } but this makes things a bit confusing for the caller, for\n   whom it's more logical to group the parameters based on the overall\n   operation being performed, which to extract a substring beginning at\n   startOffset is { str, startOffset, strLen } */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strExtract( OUT_PTR_COND const char **newStringPtr, \n\t\t\t\tIN_BUFFER( strLen ) const char *string,\n\t\t\t\tIN_LENGTH_SHORT_Z const int startOffset,\n\t\t\t\tIN_LENGTH_SHORT const int strLen )\n\t{\n\tconst int newLen = strLen - startOffset;\n\n\tassert( isReadPtr( newStringPtr, sizeof( char * ) ) );\n\tassert( isReadPtrDynamic( string, strLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\tREQUIRES( startOffset >= 0 && startOffset <= strLen && \\\n\t\t\t  startOffset < MAX_INTLENGTH_SHORT );\n\t\t\t  /* May be zero if we're extracting from the start of the \n\t\t\t     string; may be equal to strLen if it's the entire\n\t\t\t\t remaining string */\n\n\t/* Clear return value */\n\t*newStringPtr = NULL;\n\n\tif( newLen < 1 || newLen > strLen || newLen >= MAX_INTLENGTH_SHORT )\n\t\treturn( -1 );\n\treturn( strStripWhitespace( newStringPtr, string + startOffset, newLen ) );\n\t}\n\n/* Parse a numeric or hex string into an integer value.  Safe conversion of a \n   numeric string gets a bit problematic because atoi() can't really \n   indicate an error except by returning 0, which is indistinguishable from \n   a zero numeric value.  To handle this we have to perform the conversion \n   ourselves */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint strGetNumeric( IN_BUFFER( strLen ) const char *str, \n\t\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t\t   OUT_INT_Z int *numericValue, \n\t\t\t\t   IN_RANGE( 0, 100 ) const int minValue, \n\t\t\t\t   IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue )\n\t{\n\tint i, value, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\tassert( isWritePtr( numericValue, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\tREQUIRES( minValue >= 0 && minValue < maxValue && \\\n\t\t\t  maxValue <= MAX_INTLENGTH );\n\n\t/* Clear return value */\n\t*numericValue = 0;\n\n\t/* Make sure that the value is within the range 'n' ... 'nnnnnnn' */\n\tif( strLen < 1 || strLen > 7 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Process the numeric string.  Note that the redundant 'value < 0' \n\t   check is necessary in order to prevent gcc from detecting what it \n\t   thinks is Undefined Behaviour (UB) and removing further checks from \n\t   the code.  In addition the second check for MAX_INTLENGTH - ch isn't\n\t   really necessary because we know that value < MAX_INTLENGTH / 10,\n\t   which means that value <= MAX_INTLENGTH / 10 - 1, so \n\t   value * 10 <= MAX_INTLENGTH - 10, therefore \n\t   value * 10 < MAX_INTLENGTH - 9, so value * 10 < MAX_INTLENGTH - ch,\n\t   however we leave it in to make the condition explicit */\n\tLOOP_MAX( ( value = 0, i = 0 ), i < strLen, i++ )\n\t\t{\n\t\tconst int ch = byteToInt( str[ i ] ) - '0';\n\n\t\tif( ch < 0 || ch > 9 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tif( value < 0 || value >= MAX_INTLENGTH / 10 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tvalue *= 10;\n\t\tif( value >= MAX_INTLENGTH - ch )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tvalue += ch;\n\t\tENSURES( isIntegerRange( value ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Make sure that the final value is within the specified range */\n\tif( value < minValue || value > maxValue )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t*numericValue = value;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint strGetHex( IN_BUFFER( strLen ) const char *str, \n\t\t\t   IN_LENGTH_SHORT const int strLen, \n\t\t\t   OUT_INT_Z int *numericValue, \n\t\t\t   IN_RANGE( 0, 100 ) const int minValue, \n\t\t\t   IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue )\n\t{\n#ifdef SYSTEM_16BIT\n\tconst int strMaxLen = ( maxValue > 0xFFF ) ? 4 : \\\n\t\t\t\t\t\t  ( maxValue > 0xFF ) ? 3 : \\\n\t\t\t\t\t\t  ( maxValue > 0xF ) ? 2 : 1;\n#else\n\tconst int strMaxLen = ( maxValue > 0xFFFF ) ? 5 : \\\n\t\t\t\t\t\t  ( maxValue > 0xFFF ) ? 4 : \\\n\t\t\t\t\t\t  ( maxValue > 0xFF ) ? 3 : \\\n\t\t\t\t\t\t  ( maxValue > 0xF ) ? 2 : 1;\n#endif /* SYSTEM_16BIT */\n\tint i, value = 0, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\tassert( isWritePtr( numericValue, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( strLen ) );\n\tREQUIRES( minValue >= 0 && minValue < maxValue && \\\n\t\t\t  maxValue <= MAX_INTLENGTH );\n\n\t/* Clear return value */\n\t*numericValue = 0;\n\n\t/* Make sure that the length is sensible for the value that we're \n\t   reading */\n\tif( strLen < 1 || strLen > strMaxLen )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Process the numeric string.  We don't have to perform the same level \n\t   of overflow checking as we do in strGetNumeric() because the maximum\n\t   value is capped to fit into an int */\n\tLOOP_MAX( i = 0, i < strLen, i++ )\n\t\t{\n\t\tconst int ch = toLower( str[ i ] );\n\t\n\t\tif( !isXDigit( ch ) )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tvalue = ( value << 4 ) | \\\n\t\t\t\t( ( ch <= '9' ) ? ch - '0' : ch - ( 'a' - 10 ) );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( value < minValue || value > maxValue )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t*numericValue = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Determine whether a string is printable or not, used when checking whether\n   it should be displayed to the caller as a text string or a hex dump */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN strIsPrintable( IN_BUFFER( strLen ) const void *str, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int strLen )\n\t{\n\tconst BYTE *strPtr = str;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( str, strLen ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( strLen ) );\n\n\tLOOP_MAX( i = 0, i < strLen, i++ )\n\t\t{\n\t\tconst int ch = byteToInt( strPtr[ i ] );\n\n\t\tif( !isValidTextChar( ch ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\n\treturn( TRUE );\n\t}\n\n/* Sanitise a string before passing it back to the user.  This is used to\n   clear potential problem characters (for example control characters)\n   from strings passed back from untrusted sources (nec verbum verbo \n   curabis reddere fidus interpres - Horace).\n   \n   This function assumes that the string is in ASCII form rather than some\n   exotic character set, since this is used for processing text error\n   messages sent to us by remote systems we can reasonably assume that \n   they should be be, well, text error messages so that we're within our\n   rights to filter out non-text data.\n   \n   The function returns a pointer to the string to allow it to be used in \n   the form printf( \"..%s..\", sanitiseString( string, strLen ) ).  In \n   addition it formats the data to fit a fixed-length buffer, if the string \n   is longer than the indicated buffer size then it appends a '[...]' at the \n   end of the buffer to indicate that further data was truncated.   The \n   transformation applied is as follows:\n\n\t  buffer\t\t\t\t\tstrMaxLen\n\t\t|\t\t\t\t\t\t\t|\n\t\tv\t\t\t\t\t\t\tv\n\t\t+---------------------------+\t\t.\t\t\t\t\t\t\t\t.\n\t\t|\t\t\t\t\t\t\t|  ==>\t.\t\t\t\t\t\t\t\t.\n\t\t+---------------------------+\t\t.\t\t\t\t\t\t\t\t.\n\t\t.\t\t\t\t\t\t\t.\t\t.\t\t\t\t\t\t\t\t.\n\t\t|---------------|\t\t\t.\t\t|---------------|\\0|\t\t\t.\n\t\t.\t\t\t\t^\t\t\t.\t\t.\t\t\t\t\t\t\t\t.\n\t\t|--------------------------------|\t|-----------------------|[...]\\0|\n\t\t\t\t\t\t|\t\t\t\t ^\n\t\t\t\t\t\t+---- strLen ----+\n\n   so \"Error string of arbitrary length...\" with a buffer size of 20 would \n   become \"Error string [...]\" */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nchar *sanitiseString( INOUT_BUFFER( strMaxLen, strLen ) void *string, \n\t\t\t\t\t  IN_LENGTH_SHORT const int strMaxLen, \n\t\t\t\t\t  IN_LENGTH_SHORT const int strLen )\n\t{\n\tBYTE *strPtr = string;\t/* See comment below */\n\tconst int strDataLen = min( strLen, strMaxLen );\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( string, strMaxLen ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( strLen ), \"(Internal error)\" );\n\tREQUIRES_EXT( isShortIntegerRangeNZ( strMaxLen ), \"(Internal error)\" );\n\n\t/* Remove any potentially unsafe characters from the string, effectively\n\t   converting it from a 'BYTE *' to a 'char *'.  This is also the reason\n\t   why the function prototype declares it as a 'void *', if it's declared\n\t   as a 'BYTE *' then the conversion process gives compilers and static\n\t   analysers headaches */\n\tLOOP_MAX( i = 0, i < strDataLen, i++ )\n\t\t{\n\t\tconst int ch = byteToInt( strPtr[ i ] );\n\n\t\tif( !isValidTextChar( ch ) )\n\t\t\tstrPtr[ i ] = '.';\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, \"(Internal error)\" );\n\n\t/* If there was more input than we could fit into the buffer and \n\t   there's room for a continuation indicator, add this to the output \n\t   string */\n\tif( ( strLen >= strMaxLen ) && ( strMaxLen > 8 ) )\n\t\t{\n\t\tREQUIRES_EXT( boundsCheck( strMaxLen - 6, 5, strMaxLen ),\n\t\t\t\t\t  \"(Internal error)\" );\n\t\tmemcpy( strPtr + strMaxLen - 6, \"[...]\", 5 );\t/* Extra -1 for '\\0' */\n\t\t}\n\n\t/* Terminate the string to allow it to be used in printf()-style\n\t   functions */\n\tif( strLen < strMaxLen )\n\t\tstrPtr[ strLen ] = '\\0';\n\telse\n\t\tstrPtr[ strMaxLen - 1 ] = '\\0';\n\n\t/* We've converted the string from BYTE * to char * so it can be \n\t   returned as a standard text string */\n\treturn( ( char * ) strPtr );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tTR 24731 Safe stdlib Extensions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef __STDC_LIB_EXT1__\n\n/* Minimal wrappers for the TR 24731 functions to map them to older stdlib \n   equivalents.  Because of potential issues when comparing a (signed)\n   literal value -1 to the unsigned size_t we explicitly check for both\n   '( size_t ) -1' as well as a general check for a negative return value */\n\nRETVAL_RANGE( -1, 0 ) \\\nint mbstowcs_s( OUT size_t *retval, \n\t\t\t\tOUT_BUFFER_FIXED( dstmax ) wchar_t *dst, \n\t\t\t\tIN_LENGTH_SHORT size_t dstmax, \n\t\t\t\tIN_BUFFER( len ) const char *src, \n\t\t\t\tIN_LENGTH_SHORT size_t len )\n\t{\n\tsize_t bytesCopied;\n\n\tassert( isWritePtr( retval, sizeof( size_t ) ) );\n\tassert( isWritePtrDynamic( dst, dstmax ) );\n\tassert( isReadPtrDynamic( src, len ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( dstmax ), -1 );\n\tREQUIRES_EXT( ( len > 0 && len <= dstmax && \\\n\t\t\t\t\tlen < MAX_INTLENGTH_SHORT ), -1 );\n\n\t/* Clear return value */\n\t*retval = 0;\n\n\tbytesCopied = mbstowcs( dst, src, len );\n\tif( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )\n\t\treturn( -1 );\n\t*retval = bytesCopied;\n\treturn( 0 );\n\t}\n\nRETVAL_RANGE( -1, 0 ) \\\nint wcstombs_s( OUT size_t *retval, \n\t\t\t\tOUT_BUFFER_FIXED( dstmax ) char *dst, \n\t\t\t\tIN_LENGTH_SHORT size_t dstmax, \n\t\t\t\tIN_BUFFER( len) const wchar_t *src, \n\t\t\t\tIN_LENGTH_SHORT size_t len )\n\t{\n\tsize_t bytesCopied;\n\n\tassert( isWritePtr( retval, sizeof( size_t ) ) );\n\tassert( isWritePtrDynamic( dst, dstmax ) );\n\tassert( isReadPtrDynamic( src, len ) );\n\n\tREQUIRES_EXT( isShortIntegerRangeNZ( dstmax ), -1 );\n\tREQUIRES_EXT( ( len > 0 && len <= dstmax && \\\n\t\t\t\t\tlen < MAX_INTLENGTH_SHORT ), -1 );\n\n\t/* Clear return value */\n\t*retval = 0;\n\n\tbytesCopied = wcstombs( dst, src, len );\n\tif( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )\n\t\treturn( -1 );\n\t*retval = bytesCopied;\n\treturn( 0 );\n\t}\n#endif /* !__STDC_LIB_EXT1__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test code for the above functions */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntString( void )\n\t{\n\tBYTE buffer[ 16 + 8 ];\n\tconst char *stringPtr;\n\tint stringLen, value;\n\n\t/* Test strFindCh() */\n\tif( strFindCh( \"abcdefgh\", 8, 'a' ) != 0 || \\\n\t\tstrFindCh( \"abcdefgh\", 8, 'd' ) != 3 || \\\n\t\tstrFindCh( \"abcdefgh\", 8, 'h' ) != 7 || \\\n\t\tstrFindCh( \"abcdefgh\", 8, 'x' ) != -1 )\n\t\treturn( FALSE );\n\n\t/* Test strFindStr() */\n\tif( strFindStr( \"abcdefgh\", 8, \"abc\", 3 ) != 0 || \\\n\t\tstrFindStr( \"abcdefgh\", 8, \"fgh\", 3 ) != 5 || \\\n\t\tstrFindStr( \"abcdefgh\", 8, \"ghi\", 3 ) != -1 || \\\n\t\tstrFindStr( \"abcdefgh\", 8, \"abcdefghi\", 9 ) != -1 )\n\t\treturn( FALSE );\n\n\t/* Test strSkipWhitespace() */\n\tif( strSkipWhitespace( \"abcdefgh\", 8 ) != 0 || \\\n\t\tstrSkipWhitespace( \" abcdefgh\", 9 ) != 1 || \\\n\t\tstrSkipWhitespace( \" \\t abcdefgh\", 11 ) != 3 || \\\n\t\tstrSkipWhitespace( \" x abcdefgh\", 11 ) != 1 || \\\n\t\tstrSkipWhitespace( \"  \\t \", 4 ) != -1 )\n\t\treturn( FALSE );\n\n\t/* Test strSkipNonWhitespace() */\n\tif( strSkipNonWhitespace( \"abcdefgh\", 8 ) != 8 || \\\n\t\tstrSkipNonWhitespace( \" abcdefgh\", 9 ) != -1 || \\\n\t\tstrSkipNonWhitespace( \"abcdefgh \", 9 ) != 8 || \\\n\t\tstrSkipNonWhitespace( \"abcdefgh x \", 11 ) != 8 )\n\t\treturn( FALSE );\n\n\t/* Test strStripWhitespace() */\n\tstringLen = strStripWhitespace( &stringPtr, \"abcdefgh\", 8 );\n\tif( stringLen != 8 || memcmp( stringPtr, \"abcdefgh\", 8 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \" abcdefgh\", 9 );\n\tif( stringLen != 8 || memcmp( stringPtr, \"abcdefgh\", 8 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \"abcdefgh \", 9 );\n\tif( stringLen != 8 || memcmp( stringPtr, \"abcdefgh\", 8 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \" abcdefgh \", 10 );\n\tif( stringLen != 8 || memcmp( stringPtr, \"abcdefgh\", 8 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \" x abcdefgh \", 12 );\n\tif( stringLen != 10 || memcmp( stringPtr, \"x abcdefgh\", 10 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \" abcdefgh x \", 12 );\n\tif( stringLen != 10 || memcmp( stringPtr, \"abcdefgh x\", 10 ) )\n\t\treturn( FALSE );\n\tstringLen = strStripWhitespace( &stringPtr, \"  \\t \", 4 );\n\tif( stringLen != -1 || stringPtr != NULL )\n\t\treturn( FALSE );\n\n\t/* Test strExtract() */\n\tstringLen = strExtract( &stringPtr, \"abcdefgh\", 4, 8 );\n\tif( stringLen != 4 || memcmp( stringPtr, \"efgh\", 4 ) )\n\t\treturn( FALSE );\n\tstringLen = strExtract( &stringPtr, \"abcd  efgh\", 4, 10 );\n\tif( stringLen != 4 || memcmp( stringPtr, \"efgh\", 4 ) )\n\t\treturn( FALSE );\n\tstringLen = strExtract( &stringPtr, \"abcd  efgh  \", 4, 12 );\n\tif( stringLen != 4 || memcmp( stringPtr, \"efgh\", 4 ) )\n\t\treturn( FALSE );\n\tstringLen = strExtract( &stringPtr, \"abcd  efgh  ij  \", 4, 16 );\n\tif( stringLen != 8 || memcmp( stringPtr, \"efgh  ij\", 8 ) )\n\t\treturn( FALSE );\n\n\t/* Test strGetNumeric() */\n\tif( strGetNumeric( \"0\", 1, &value, 0, 10 ) != CRYPT_OK || value != 0 || \\\n\t\tstrGetNumeric( \"00\", 2, &value, 0, 10 ) != CRYPT_OK || value != 0 || \\\n\t\tstrGetNumeric( \"1234\", 4, &value, 0, 2000 ) != CRYPT_OK || value != 1234 || \\\n\t\tstrGetNumeric( \"1234x\", 5, &value, 0, 2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \\\n\t\tstrGetNumeric( \"x1234\", 5, &value, 0, 2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \\\n\t\tstrGetNumeric( \"1000\", 4, &value, 0, 1000 ) != CRYPT_OK || value != 1000 || \\\n\t\tstrGetNumeric( \"1001\", 4, &value, 0, 1000 ) != CRYPT_ERROR_BADDATA || value != 0 )\n\t\treturn( FALSE );\n\n\t/* Test strGetHex() */\n\tif( strGetHex( \"0\", 1, &value, 0, 1000 ) != CRYPT_OK || value != 0 || \\\n\t\tstrGetHex( \"1234\", 4, &value, 0, 0x2000 ) != CRYPT_OK || value != 0x1234 || \\\n\t\tstrGetHex( \"1234x\", 5, &value, 0, 0x2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \\\n\t\tstrGetHex( \"x1234\", 5, &value, 0, 0x2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \\\n\t\tstrGetHex( \"12EE\", 4, &value, 0, 0x12EE ) != CRYPT_OK || value != 0x12EE || \\\n\t\tstrGetHex( \"12EF\", 4, &value, 0, 0x12EE ) != CRYPT_ERROR_BADDATA || value != 0 )\n\t\treturn( FALSE );\n\n\t/* Test sanitiseString() */\n\tmemcpy( buffer, \"abcdefgh\", 8 );\n\tstringPtr = sanitiseString( buffer, 16, 8 );\n\tif( memcmp( stringPtr, \"abcdefgh\", 9 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abc\\x12\" \"efgh\", 8 );\n\tstringPtr = sanitiseString( buffer, 16, 8 );\n\tif( memcmp( stringPtr, \"abc.efgh\", 9 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abcdefgh\", 8 );\n\tstringPtr = sanitiseString( buffer, 7, 8 );\n\tif( memcmp( stringPtr, \"abcdef\", 7 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abcdefgh\", 8 );\n\tstringPtr = sanitiseString( buffer, 8, 8 );\n\tif( memcmp( stringPtr, \"abcdefg\", 8 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abcdefghij\", 10 );\n\tstringPtr = sanitiseString( buffer, 9, 10 );\n\tif( memcmp( stringPtr, \"abc[...]\", 9 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abcdefghij\", 10 );\n\tstringPtr = sanitiseString( buffer, 10, 10 );\n\tif( memcmp( stringPtr, \"abcd[...]\", 10 ) )\n\t\treturn( FALSE );\n\tmemcpy( buffer, \"abcdefghij\", 10 );\n\tstringPtr = sanitiseString( buffer, 11, 10 );\n\tif( memcmp( stringPtr, \"abcdefghij\", 11 ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n"
  },
  {
    "path": "deps/cl345/misc/int_time.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Internal Time/Timer API\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTime Functions \t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the system time safely.  The first function implements hard failures,\n   converting invalid time values to zero, which yield a warning date of\n   1/1/1970 rather than an out-of-bounds or garbage value.  The second\n   function implements soft failures, returning an estimate of the\n   approximate current date.  The third function is used for operations such\n   as signing certs and timestamping and tries to get the time from a\n   hardware time source if one is available.\n   \n   Because of the implementation-dependent behaviour of the time_t type we \n   perform an explicit check against '( time_t ) -1' as well as a general \n   range check to avoid being caught by conversion problems if time_t is a \n   type too far removed from int */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\nstatic time_t testTimeValue = 0;\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\ntime_t getTime( void )\n\t{\n\tconst time_t theTime = time( NULL );\n\n\tif( ( theTime == ( time_t ) -1 ) || \\\n\t\t( theTime <= MIN_TIME_VALUE ) || \\\n\t\t( theTime >= MAX_TIME_VALUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"No time source available\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n\t\t}\n\treturn( theTime );\n\t}\n\ntime_t getApproxTime( void )\n\t{\n\tconst time_t theTime = time( NULL );\n\n\t/* If we're running a self-test with externally-controlled time, return\n\t   the pre-set time value */\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\tif( testTimeValue != 0 )\n\t\treturn( testTimeValue );\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n\tif( ( theTime == ( time_t ) -1 ) || \\\n\t\t( theTime <= MIN_TIME_VALUE ) || \\\n\t\t( theTime >= MAX_TIME_VALUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"No time source available\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CURRENT_TIME_VALUE );\n\t\t}\n\treturn( theTime );\n\t}\n\ntime_t getReliableTime( IN_HANDLE const CRYPT_HANDLE cryptHandle )\n\t{\n\tCRYPT_DEVICE cryptDevice;\n\tMESSAGE_DATA msgData;\n\ttime_t theTime;\n\tint status;\n\n\tREQUIRES_EXT( ( cryptHandle == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t\t\tisHandleRangeValid( cryptHandle ) ), 0 );\n\n\t/* Get the dependent device for the object that needs the time.  This\n\t   is typically a private key being used for signing something that \n\t   needs a timestamp, so what we're doing here is finding a time source\n\t   associated with that key, for example the HSM that the key is stored\n\t   in */\n\tstatus = krnlSendMessage( cryptHandle, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t  &cryptDevice, OBJECT_TYPE_DEVICE );\n\tif( cryptStatusError( status ) )\n\t\tcryptDevice = SYSTEM_OBJECT_HANDLE;\n\n\t/* Try and get the time from the device */\n\tsetMessageData( &msgData, &theTime, sizeof( time_t ) );\n\tstatus = krnlSendMessage( cryptDevice, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_TIME );\n\tif( cryptStatusError( status ) && cryptDevice != SYSTEM_OBJECT_HANDLE )\n\t\t{\n\t\t/* We couldn't get the time from a crypto token, fall back to the\n\t\t   system device */\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_TIME );\n\t\t}\n\tif( cryptStatusError( status ) || \\\n\t\t( theTime == ( time_t ) -1 ) || \\\n\t\t( theTime <= MIN_TIME_VALUE ) || \\\n\t\t( theTime >= MAX_TIME_VALUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Error: No time source available\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( 0 );\n\t\t}\n\treturn( theTime );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTimer Functions \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Monotonic timer interface that protects against the system clock being \n   changed during a timed operation like network I/O, so we have to abstract \n   the standard time API into a monotonic time API.  Since these functions \n   are purely peripheral to other operations (for example handling timeouts \n   for network I/O) they never fail but simply return good-enough results if \n   there's a problem (although they assert in debug mode).  This is because \n   we don't want to abort a network session just because we've detected some \n   trivial clock irregularity.\n\n   The way this works is that we record the following information for each\n   timing interval:\n\n\t\t\t(endTime - \\\n\t\t\t\ttimeRemaining)\t\t\t endTime\n\t................+-----------------------+...............\n\t\t^\t\t\t|\t\t\t\t\t\t|\t\t^\n\tcurrentTime\t\t|<--- timeRemaining --->|\tcurrentTime'\n\t\t  ....<------- origTimeout -------->|\n\n   When currentTime falls outside the timeRemaining interval we know that a \n   clock change has occurred and can try and correct it.  Moving forwards\n   by an unexpected amount is a bit more tricky than moving back because \n   it's hard to define \"unexpected\", so we use an estimation method that \n   detects the typical reasons for a clock leap (an attempt to handle a DST \n   adjust by changing the clock) without yielding false positives */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckMonotimer( const MONOTIMER_INFO *timerInfo )\n\t{\n\tassert( isReadPtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\n\t/* Make sure that the basic timer values are within bounds.  We can't\n\t   check endTime for a maximum range value since it's a time_t */\n\tif( !isIntegerRange( timerInfo->origTimeout ) || \\\n\t\t!isIntegerRange( timerInfo->timeRemaining ) || \\\n\t\ttimerInfo->endTime < 0 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckMonotimer: General info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that time ranges are withing bounds.  This can generally \n\t   only happen when a time_t over/underflow has occurred */\n\tif( timerInfo->endTime < timerInfo->timeRemaining || \\\n\t\ttimerInfo->origTimeout < timerInfo->timeRemaining )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckMonotimer: Time range\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void handleTimeOutOfBounds( INOUT MONOTIMER_INFO *timerInfo )\n\t{\n\tassert( isWritePtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\n\tDEBUG_DIAG(( \"time_t underflow/overflow has occurred\" ));\n\tassert( DEBUG_WARN );\n\n\t/* We've run into an overflow condition in the calculations that we've\n\t   performed on a time_t, this is a bit tricky to handle because we \n\t   can't just give up on (say) performing network I/O just because we \n\t   can't reliably set a timeout.  The best that we can do is warn in \n\t   debug mode and set a zero timeout so that at least one lot of I/O \n\t   will still take place */\n\ttimerInfo->origTimeout = timerInfo->timeRemaining = 0;\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN correctMonoTimer( INOUT MONOTIMER_INFO *timerInfo,\n\t\t\t\t\t\t\t\t const time_t currentTime )\n\t{\n\tBOOLEAN needsCorrection = FALSE;\n\n\tassert( isWritePtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\n\t/* If a time_t over/underflow has occurred, make a best-effort attempt \n\t   to recover */\n\tif( !sanityCheckMonotimer( timerInfo ) )\n\t\t{\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If the clock has been rolled back to before the start time, we need \n\t   to correct this.  The range check for endTime vs. timeRemaining has\n\t   already been done as part of the sanity check */\n\tif( currentTime < timerInfo->endTime - timerInfo->timeRemaining )\n\t\tneedsCorrection = TRUE;\n\telse\n\t\t{\n\t\t/* If we're past the timer end time, check to see whether it's \n\t\t   jumped by a suspicious amount.  If we're more than 30 minutes \n\t\t   past the timeout (which will catch things like attempted DST \n\t\t   corrections) and the initial timeout was less than the change (to \n\t\t   avoid a false positive if we've been waiting > 30 minutes for a \n\t\t   legitimate timeout), we need to correct this.  This can still \n\t\t   fail if (for example) we have a relatively short timeout and \n\t\t   we're being run in a VM that gets suspended for more than 30 \n\t\t   minutes and then restarted, but by then any peer communicating \n\t\t   with us should have long since given up waiting for a response \n\t\t   and timed out the connection.  In any case someone fiddling with \n\t\t   suspending processes in this manner, which will cause problems \n\t\t   for anything doing network I/O, should be prepared to handle any \n\t\t   problems that arise, for example by ensuring that current network \n\t\t   I/O has completed before suspending the process */\n\t\tif( currentTime > timerInfo->endTime )\n\t\t\t{\n\t\t\tconst time_t delta = currentTime - timerInfo->endTime;\n\n\t\t\tif( ( delta < 0 || delta > ( 30 * 60 ) ) && \\\n\t\t\t\ttimerInfo->origTimeout < delta )\n\t\t\t\tneedsCorrection = TRUE;\n\t\t\t}\n\t\t}\n\tif( !needsCorrection )\n\t\treturn( TRUE );\n\n\t/* The time information has been changed, correct the recorded time \n\t   information for the new time.\n\t   \n\t   The checking for overflow in time_t is impossible to perform when the\n\t   compiler uses gcc's braindamaged interpretation of the C standard.\n\t   A compiler like MSVC knows that a time_t is an int or long and \n\t   produces the expected code from the following, a compiler like gcc \n\t   also knows that a time_t is an int or a long but assumes that it \n\t   could also be a GUID or a variant record or anonymous union or packed \n\t   bitfield and therefore removes the checks in the code, because trying \n\t   to perform the check on a time_t is undefined behaviour (UB).  There \n\t   is no way to work around this issue apart from switching to a less \n\t   braindamaged compiler, so we leave the code there for sane compilers\n\t   under the acknowledgement that there's no way to address this with \n\t   gcc */\n\tif( currentTime >= ( MAX_INTLENGTH - timerInfo->timeRemaining ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid monoTimer time correction period\" ));\n\t\tassert( DEBUG_WARN );\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn( FALSE );\n\t\t}\n\ttimerInfo->endTime = currentTime + timerInfo->timeRemaining;\n\tif( timerInfo->endTime < currentTime || \\\n\t\ttimerInfo->endTime < currentTime + max( timerInfo->timeRemaining,\n\t\t\t\t\t\t\t\t\t\t\t\ttimerInfo->origTimeout ) )\n\t\t{\n\t\t/* There's a problem with the time calculations, handle the overflow\n\t\t   condition and tell the caller not to try anything further */\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setMonoTimer( OUT MONOTIMER_INFO *timerInfo, \n\t\t\t\t  IN_INT_Z const int duration )\n\t{\n\tconst time_t currentTime = getApproxTime();\n\tBOOLEAN initOK;\n\n\tassert( isWritePtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\t\n\tREQUIRES( isIntegerRange( duration ) );\n\n\tmemset( timerInfo, 0, sizeof( MONOTIMER_INFO ) );\n\tif( currentTime >= ( MAX_INTLENGTH - duration ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid monoTimer time period\" ));\n\t\tassert( DEBUG_WARN );\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn( CRYPT_OK );\n\t\t}\n\ttimerInfo->endTime = currentTime + duration;\n\ttimerInfo->timeRemaining = timerInfo->origTimeout = duration;\n\tinitOK = correctMonoTimer( timerInfo, currentTime );\n\tENSURES( initOK );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid extendMonoTimer( INOUT MONOTIMER_INFO *timerInfo, \n\t\t\t\t\t  IN_INT const int duration )\n\t{\n\tconst time_t currentTime = getApproxTime();\n\n\tassert( isWritePtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\t\n\tREQUIRES_V( isIntegerRange( duration ) );\n\n\t/* Correct the timer for clock skew if required */\n\tif( !correctMonoTimer( timerInfo, currentTime ) )\n\t\treturn;\n\n\t/* Extend the monotonic timer's timeout interval to allow for further\n\t   data to be processed */\n\tif( timerInfo->origTimeout >= ( MAX_INTLENGTH - duration ) || \\\n\t\ttimerInfo->endTime >= ( MAX_INTLENGTH - duration ) || \\\n\t\ttimerInfo->endTime < currentTime )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid monoTimer time period extension\" ));\n\t\tassert( DEBUG_WARN );\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn;\n\t\t}\n\ttimerInfo->origTimeout += duration;\n\ttimerInfo->endTime += duration;\n\ttimerInfo->timeRemaining = timerInfo->endTime - currentTime;\n\n\t/* Re-correct the timer in case overflow occurred */\n\t( void ) correctMonoTimer( timerInfo, currentTime );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkMonoTimerExpiryImminent( INOUT MONOTIMER_INFO *timerInfo,\n\t\t\t\t\t\t\t\t\t  IN_INT_Z const int timeLeft )\n\t{\n\tconst time_t currentTime = getApproxTime();\n\ttime_t timeRemaining;\n\n\tassert( isWritePtr( timerInfo, sizeof( MONOTIMER_INFO ) ) );\n\n\tREQUIRES_B( isIntegerRange( timeLeft ) );\n\n\t/* If the timeout has expired, don't try doing anything else */\n\tif( timerInfo->timeRemaining <= 0 )\n\t\treturn( TRUE );\n\n\t/* Correct the monotonic timer for clock skew if required */\n\tif( !correctMonoTimer( timerInfo, currentTime ) )\n\t\treturn( TRUE );\n\n\t/* Check whether the time will expire within timeLeft seconds */\n\tif( timerInfo->endTime < currentTime )\n\t\t{\n\t\tDEBUG_DIAG(( \"Invalid monoTimer expiry time period\" ));\n\t\tassert( DEBUG_WARN );\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\treturn( TRUE );\n\t\t}\n\ttimeRemaining = timerInfo->endTime - currentTime;\n\tif( timeRemaining > timerInfo->timeRemaining )\n\t\t{\n\t\thandleTimeOutOfBounds( timerInfo );\n\t\ttimeRemaining = 0;\n\t\t}\n\ttimerInfo->timeRemaining = timeRemaining;\n\treturn( ( timerInfo->timeRemaining <= timeLeft ) ? TRUE : FALSE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkMonoTimerExpired( INOUT MONOTIMER_INFO *timerInfo )\n\t{\n\treturn( checkMonoTimerExpiryImminent( timerInfo, 0 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSelf-test Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test code for the above functions */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\nstatic void setTestTime( const time_t value )\n\t{\n\ttestTimeValue = MIN_TIME_VALUE + value;\n\t}\n\nstatic void clearTestTime( void )\n\t{\n\ttestTimeValue = 0;\n\t}\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN testIntTime( void )\n\t{\n\tMONOTIMER_INFO timerInfo;\n\tint status;\n\n\t/* Test basic timer functions */\n\tsetTestTime( 1000 );\n\tstatus = setMonoTimer( &timerInfo, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( !checkMonoTimerExpiryImminent( &timerInfo, 1 ) )\n\t\treturn( FALSE );\n\tstatus = setMonoTimer( &timerInfo, 10 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( checkMonoTimerExpiryImminent( &timerInfo, 0 ) || \\\n\t\tcheckMonoTimerExpiryImminent( &timerInfo, 9 ) )\n\t\treturn( FALSE );\n\tif( !checkMonoTimerExpiryImminent( &timerInfo, 10 ) )\n\t\treturn( FALSE );\n\n\t/* Check timer period extension functionality */\n\tsetTestTime( 1000 );\n\tstatus = setMonoTimer( &timerInfo, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\textendMonoTimer( &timerInfo, 10 );\n\tif( checkMonoTimerExpiryImminent( &timerInfo, 0 ) || \\\n\t\tcheckMonoTimerExpiryImminent( &timerInfo, 9 ) || \\\n\t\t!checkMonoTimerExpiryImminent( &timerInfo, 10 ) )\n\t\treturn( FALSE );\n\n\t/* Check clock going forwards normally */\n\tsetTestTime( 1000 );\n\tstatus = setMonoTimer( &timerInfo, 10 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tsetTestTime( 1009 );\n\tif( checkMonoTimerExpiryImminent( &timerInfo, 0 ) || \\\n\t\t!checkMonoTimerExpiryImminent( &timerInfo, 1 ) )\n\t\treturn( FALSE );\n\n\t/* Check clock going backwards.  This recovers by correcting to allow \n\t   the original timeout */\n\tsetTestTime( 1000 );\n\tstatus = setMonoTimer( &timerInfo, 10 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tsetTestTime( 999 );\n\tif( checkMonoTimerExpiryImminent( &timerInfo, 0 ) || \\\n\t\tcheckMonoTimerExpiryImminent( &timerInfo, 9 ) || \\\n\t\t!checkMonoTimerExpiryImminent( &timerInfo, 10 ) )\n\t\treturn( FALSE );\n\n\t/* Check clock going forwards too far.  This recovers from a time jump \n\t   of > 30 minutes by correcting to allow the original timeout period on \n\t   the assumption that the problem is with the time source rather than \n\t   that we've waited for over half an hour for a network packet to \n\t   arrive */\n\tsetTestTime( 1000 );\n\tstatus = setMonoTimer( &timerInfo, 10 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tsetTestTime( 1000 + ( 45 * 60 ) );\n\tif( checkMonoTimerExpiryImminent( &timerInfo, 0 ) || \\\n\t\tcheckMonoTimerExpiryImminent( &timerInfo, 9 ) || \\\n\t\t!checkMonoTimerExpiryImminent( &timerInfo, 10 ) )\n\t\treturn( FALSE );\n\n\tclearTestTime();\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n"
  },
  {
    "path": "deps/cl345/misc/list.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib List Manipulation Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following functions handle the insertion and deletion of elements to \n   and from singly-linked and doubly-linked lists.  This is the sort of \n   thing that we'd really need templates for, but in their absence we have \n   to use unfortunately rather complex macros.  Where possible these macros \n   are invoked through wrapper functions, limiting the macro code expansion \n   to a small number of locations */\n\n#ifndef _LIST_DEFINED\n\n#define _LIST_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSafe-pointer Single-linked List Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Insert and delete elements to/from a single-linked list with safe \n   pointers */\n\n#define insertSingleListElement( listHead, insertPoint, newElement, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( listHead ); \\\n\t\t\\\n\t\t/* Make sure that the element being added is consistent */ \\\n\t\tREQUIRES( newElement != NULL ); \\\n\t\tREQUIRES( DATAPTR_GET( ( newElement )->next ) == NULL ); \\\n\t\t\\\n\t\tif( _listHeadPtr == NULL ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( ( insertPoint ) == NULL ); \\\n\t\t\t\\\n\t\t\t/* It's an empty list, make this the new list */ \\\n\t\t\tDATAPTR_SET( listHead, ( newElement ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tif( ( insertPoint ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\t/* We're inserting at the start of the list, make this the \\\n\t\t\t\t   new first element */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, _listHeadPtr ); \\\n\t\t\t\tDATAPTR_SET( listHead, ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tELEMENT_TYPE *insertPointNext = DATAPTR_GET( ( insertPoint )->next ); \\\n\t\t\t\t\\\n\t\t\t\t/* Insert the element in the middle or the end of the list */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, insertPointNext ); \\\n\t\t\t\tDATAPTR_SET( ( insertPoint )->next, ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\t}\n\n#define deleteSingleListElement( listHead, listPrev, element, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( listHead ); \\\n\t\t\\\n\t\t/* Make sure that the preconditions for safe delection are met */ \\\n\t\tREQUIRES( _listHeadPtr != NULL && element != NULL ); \\\n\t\tREQUIRES( element == _listHeadPtr || listPrev != NULL ); \\\n\t\t\\\n\t\tif( element == _listHeadPtr ) \\\n\t\t\t{ \\\n\t\t\t/* Special case for the first item */ \\\n\t\t\tDATAPTR_SET( listHead, DATAPTR_GET( element->next ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tANALYSER_HINT( listPrev != NULL ); \\\n\t\t\t\\\n\t\t\t/* Delete from middle or end of the list */ \\\n\t\t\tDATAPTR_SET( listPrev->next, DATAPTR_GET( element->next ) ); \\\n\t\t\t} \\\n\t\tDATAPTR_SET( ( element )->next, NULL ); \\\n\t\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tSafe-pointer Double-linked List Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Insert and delete elements to/from a double-linked list with safe \n   pointers */\n\n/*\t\t\t\t\t\t\t\t DATAPTR\t\t\tELEMENT_TYPE ELEMENT_TYPE */\n#define insertDoubleListElement( listHeadReference, insertPoint, newElement, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tDATAPTR _listHead = *( listHeadReference ); \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( _listHead ); \\\n\t\t\\\n\t\t/* Make sure that the elements being added are consistent */ \\\n\t\tREQUIRES( insertPoint != newElement ); \\\n\t\tREQUIRES( DATAPTR_GET( ( newElement )->prev ) == NULL && \\\n\t\t\t\t  DATAPTR_GET( ( newElement )->next ) == NULL ); \\\n\t\t\\\n\t\tif( _listHeadPtr == NULL ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( ( insertPoint ) == NULL ); \\\n\t\t\t\\\n\t\t\t/* It's an empty list, make this the new list */ \\\n\t\t\tDATAPTR_SET_PTR( ( listHeadReference ), ( newElement ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tif( ( insertPoint ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\t/* We're inserting at the start of the list, make this the \\\n\t\t\t\t   new first element */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, _listHeadPtr ); \\\n\t\t\t\tDATAPTR_SET( _listHeadPtr->prev, ( newElement ) ); \\\n\t\t\t\tDATAPTR_SET_PTR( ( listHeadReference ), ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tELEMENT_TYPE *insertPointNext = DATAPTR_GET( ( insertPoint )->next ); \\\n\t\t\t\t\\\n\t\t\t\t/* Make sure that the links are consistent */ \\\n\t\t\t\tENSURES( insertPointNext == NULL || \\\n\t\t\t\t\t\t DATAPTR_GET( insertPointNext->prev ) == ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Insert the element in the middle or the end of the list */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, insertPointNext ); \\\n\t\t\t\tDATAPTR_SET( ( newElement )->prev, ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Update the links for the next and previous elements */ \\\n\t\t\t\tif( insertPointNext != NULL ) \\\n\t\t\t\t\tDATAPTR_SET( insertPointNext->prev, ( newElement ) ); \\\n\t\t\t\tDATAPTR_SET( ( insertPoint )->next, ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\t}\n\n/*\t\t\t\t\t\t\t\t  DATAPTR\t\t\t ELEMENT_TYPE ELEMENT_TYPE */\n#define insertDoubleListElements( listHeadReference, insertPoint, newStartElement, newEndElement, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tDATAPTR _listHead = *( listHeadReference ); \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( _listHead ); \\\n\t\t\\\n\t\t/* Make sure that the elements being added are consistent */ \\\n\t\tREQUIRES( newStartElement != NULL && newEndElement != NULL ); \\\n\t\tREQUIRES( insertPoint != newStartElement && insertPoint != newEndElement ); \\\n\t\tREQUIRES( DATAPTR_GET( ( newStartElement )->prev ) == NULL && \\\n\t\t\t\t  DATAPTR_GET( ( newEndElement )->next ) == NULL ); \\\n\t\t\\\n\t\tif( _listHeadPtr == NULL ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( ( insertPoint ) == NULL ); \\\n\t\t\t\\\n\t\t\t/* It's an empty list, make this the new list */ \\\n\t\t\tDATAPTR_SET_PTR( ( listHeadReference ), ( newStartElement ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tif( ( insertPoint ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\t/* We're inserting at the start of the list, make this the \\\n\t\t\t\t   new first element */ \\\n\t\t\t\tDATAPTR_SET( ( newEndElement )->next, _listHeadPtr ); \\\n\t\t\t\tDATAPTR_SET( _listHeadPtr->prev, ( newEndElement ) ); \\\n\t\t\t\tDATAPTR_SET_PTR( ( listHeadReference ), ( newStartElement ) ); \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tELEMENT_TYPE *insertPointNext = DATAPTR_GET( ( insertPoint )->next ); \\\n\t\t\t\t\\\n\t\t\t\t/* Make sure that the links are consistent */ \\\n\t\t\t\tENSURES( insertPointNext == NULL || \\\n\t\t\t\t\t\t DATAPTR_GET( insertPointNext->prev ) == ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Insert the element in the middle or the end of the list */ \\\n\t\t\t\tDATAPTR_SET( ( newEndElement )->next, insertPointNext ); \\\n\t\t\t\tDATAPTR_SET( ( newStartElement )->prev, ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Update the links for the next and previous elements */ \\\n\t\t\t\tif( insertPointNext != NULL ) \\\n\t\t\t\t\tDATAPTR_SET( insertPointNext->prev, ( newEndElement ) ); \\\n\t\t\t\tDATAPTR_SET( ( insertPoint )->next, ( newStartElement ) ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\t}\n\n/*\t\t\t\t\t\t\t\t DATAPTR\t\t\tELEMENT_TYPE */\n#define deleteDoubleListElement( listHeadReference, element, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tDATAPTR _listHead = *( listHeadReference ); \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( _listHead ); \\\n\t\tELEMENT_TYPE *_elementPrev, *_elementNext; \\\n\t\t\\\n\t\t/* Make sure that the preconditions for safe delection are met */ \\\n\t\tREQUIRES( _listHeadPtr != NULL && element != NULL ); \\\n\t\t\\\n\t\t_elementPrev = DATAPTR_GET( element->prev ); \\\n\t\t_elementNext = DATAPTR_GET( element->next ); \\\n\t\t\\\n\t\t/* Make sure that the links are consistent */ \\\n\t\tREQUIRES( _elementNext == NULL || \\\n\t\t\t\t  DATAPTR_GET( _elementNext->prev ) == ( element ) ); \\\n\t\tREQUIRES( _elementPrev == NULL || \\\n\t\t\t\t  DATAPTR_GET( _elementPrev->next ) == ( element ) ); \\\n\t\t\\\n\t\t/* Unlink the element from the list */ \\\n\t\tif( element == _listHeadPtr ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( _elementPrev == NULL ); \\\n\t\t\t\\\n\t\t\t/* Special case for the first item */ \\\n\t\t\tDATAPTR_SET_PTR( ( listHeadReference ), _elementNext ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( _elementPrev != NULL ); \\\n\t\t\t\\\n\t\t\t/* Delete from the middle or the end of the list */ \\\n\t\t\tDATAPTR_SET( _elementPrev->next, _elementNext ); \\\n\t\t\t} \\\n\t\tif( _elementNext != NULL ) \\\n\t\t\tDATAPTR_SET( _elementNext->prev, _elementPrev ); \\\n\t\tDATAPTR_SET( element->prev, NULL ); \\\n\t\tDATAPTR_SET( element->next, NULL ); \\\n\t\t}\n\n#if 0\n\n#define insertDoubleListElement( listHead, insertPoint, newElement, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( listHead ); \\\n\t\t\\\n\t\t/* Make sure that the elements being added are consistent */ \\\n\t\tREQUIRES( insertPoint != newElement ); \\\n\t\tREQUIRES( DATAPTR_GET( ( newElement )->prev ) == NULL && \\\n\t\t\t\t  DATAPTR_GET( ( newElement )->next ) == NULL ); \\\n\t\t\\\n\t\tif( _listHeadPtr == NULL ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( ( insertPoint ) == NULL ); \\\n\t\t\t\\\n\t\t\t/* If it's an empty list, make this the new list */ \\\n\t\t\tDATAPTR_SET( listHead, ( newElement ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tif( ( insertPoint ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\t/* We're inserting at the start of the list, make this the \\\n\t\t\t\t   new first element */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, _listHeadPtr ); \\\n\t\t\t\tDATAPTR_SET( _listHeadPtr->prev, ( newElement ) ); \\\n\t\t\t\tDATAPTR_SET( listHead, ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tELEMENT_TYPE *insertPointNext = DATAPTR_GET( ( insertPoint )->next ); \\\n\t\t\t\t\\\n\t\t\t\t/* Make sure that the links are consistent */ \\\n\t\t\t\tENSURES( insertPointNext == NULL || \\\n\t\t\t\t\t\t DATAPTR_GET( insertPointNext->prev ) == ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Insert the element in the middle or the end of the list */ \\\n\t\t\t\tDATAPTR_SET( ( newElement )->next, insertPointNext ); \\\n\t\t\t\tDATAPTR_SET( ( newElement )->prev, ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Update the links for the next and previous elements */ \\\n\t\t\t\tif( insertPointNext != NULL ) \\\n\t\t\t\t\tDATAPTR_SET( insertPointNext->prev, ( newElement ) ); \\\n\t\t\t\tDATAPTR_SET( ( insertPoint )->next, ( newElement ) ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\t}\n\n#define insertDoubleListElements( listHead, insertPoint, newStartElement, newEndElement, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( listHead ); \\\n\t\t\\\n\t\t/* Make sure that the elements being added are consistent */ \\\n\t\tREQUIRES( newStartElement != NULL && newEndElement != NULL ); \\\n\t\tREQUIRES( insertPoint != newStartElement && insertPoint != newEndElement ); \\\n\t\tREQUIRES( DATAPTR_GET( ( newStartElement )->prev ) == NULL && \\\n\t\t\t\t  DATAPTR_GET( ( newEndElement )->next ) == NULL ); \\\n\t\t\\\n\t\tif( _listHeadPtr == NULL ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( ( insertPoint ) == NULL ); \\\n\t\t\t\\\n\t\t\t/* If it's an empty list, make this the new list */ \\\n\t\t\tDATAPTR_SET( listHead, ( newStartElement ) ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\tif( ( insertPoint ) == NULL ) \\\n\t\t\t\t{ \\\n\t\t\t\t/* We're inserting at the start of the list, make this the \\\n\t\t\t\t   new first element */ \\\n\t\t\t\tDATAPTR_SET( ( newEndElement )->next, _listHeadPtr ); \\\n\t\t\t\tDATAPTR_SET( _listHeadPtr->prev, ( newEndElement ) ); \\\n\t\t\t\tDATAPTR_SET( listHead, ( newStartElement ) ); \\\n\t\t\t\t} \\\n\t\t\telse \\\n\t\t\t\t{ \\\n\t\t\t\tELEMENT_TYPE *insertPointNext = DATAPTR_GET( ( insertPoint )->next ); \\\n\t\t\t\t\\\n\t\t\t\t/* Make sure that the links are consistent */ \\\n\t\t\t\tENSURES( insertPointNext == NULL || \\\n\t\t\t\t\t\t DATAPTR_GET( insertPointNext->prev ) == ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Insert the element in the middle or the end of the list */ \\\n\t\t\t\tDATAPTR_SET( ( newEndElement )->next, insertPointNext ); \\\n\t\t\t\tDATAPTR_SET( ( newStartElement )->prev, ( insertPoint ) ); \\\n\t\t\t\t\\\n\t\t\t\t/* Update the links for the next and previous elements */ \\\n\t\t\t\tif( insertPointNext != NULL ) \\\n\t\t\t\t\tDATAPTR_SET( insertPointNext->prev, ( newEndElement ) ); \\\n\t\t\t\tDATAPTR_SET( ( insertPoint )->next, ( newStartElement ) ); \\\n\t\t\t\t} \\\n\t\t\t} \\\n\t\t}\n\n#define deleteDoubleListElement( listHead, element, ELEMENT_TYPE ) \\\n\t\t{ \\\n\t\tELEMENT_TYPE *_listHeadPtr = DATAPTR_GET( listHead ); \\\n\t\tELEMENT_TYPE *_elementPrev, *_elementNext; \\\n\t\t\\\n\t\t/* Make sure that the preconditions for safe delection are met */ \\\n\t\tREQUIRES( _listHeadPtr != NULL && element != NULL ); \\\n\t\t\\\n\t\t_elementPrev = DATAPTR_GET( element->prev ); \\\n\t\t_elementNext = DATAPTR_GET( element->next ); \\\n\t\t\\\n\t\t/* Make sure that the links are consistent */ \\\n\t\tREQUIRES( _elementNext == NULL || \\\n\t\t\t\t  DATAPTR_GET( _elementNext->prev ) == ( element ) ); \\\n\t\tREQUIRES( _elementPrev == NULL || \\\n\t\t\t\t  DATAPTR_GET( _elementPrev->next ) == ( element ) ); \\\n\t\t\\\n\t\t/* Unlink the element from the list */ \\\n\t\tif( element == _listHeadPtr ) \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( _elementPrev == NULL ); \\\n\t\t\t\\\n\t\t\t/* Special case for the first item */ \\\n\t\t\tDATAPTR_SET( listHead, _elementNext ); \\\n\t\t\t} \\\n\t\telse \\\n\t\t\t{ \\\n\t\t\t/* Further consistency check */ \\\n\t\t\tREQUIRES( _elementPrev != NULL ); \\\n\t\t\t\\\n\t\t\t/* Delete from the middle or the end of the list */ \\\n\t\t\tDATAPTR_SET( _elementPrev->next, _elementNext ); \\\n\t\t\t} \\\n\t\tif( _elementNext != NULL ) \\\n\t\t\tDATAPTR_SET( _elementNext->prev, _elementPrev ); \\\n\t\tDATAPTR_SET( element->prev, NULL ); \\\n\t\tDATAPTR_SET( element->next, NULL ); \\\n\t\t}\n#endif /* 0 */\n\n#endif /* _LIST_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/os_detect.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib OS-Specific Config/Detection Header File \t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _OSDETECT_DEFINED\n\n#define _OSDETECT_DEFINED\n\n/* os_detect.h performs OS and compiler detection that's used by config.h, so\n   this file must be applied before config.h */\n\n#ifdef _CONFIG_DEFINED\n  #error \"os_detect.h must be included before config.h\"\n#endif /* _CONFIG_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tOS Detection\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Try and figure out if we're running under Windows and Win16/Win32/WinCE.\n   We have to jump through all sorts of hoops later on, not helped by the\n   fact that the method of detecting Windows at compile time changes with\n   different versions of Visual C (it's different for each of VC 2.0, 2.1,\n   4.0, and 4.1.  It actually remains the same after 4.1) */\n\n#ifndef __WINDOWS__\n  #if defined( _Windows ) || defined( _WINDOWS )\n\t#define __WINDOWS__\n  #endif /* Older Windows compilers */\n  #ifdef __MINGW32__\n\t#define __WINDOWS__\n  #endif /* MinGW */\n#endif /* Windows */\n#if !defined( __WIN32__ ) && ( defined( WIN32 ) || defined( _WIN32 ) )\n  #ifndef __WINDOWS__\n\t#define __WINDOWS__\t\t/* Win32 or WinCE */\n  #endif /* __WINDOWS__ */\n  #ifdef _WIN32_WCE\n\t#define __WINCE__\n  #else\n\t#define __WIN32__\n  #endif /* WinCE vs. Win32 */\n  #if defined( _M_X64 )\n\t#define __WIN64__\n  #endif /* Win64 */\n#endif /* Win32 or WinCE */\n#if defined( __WINDOWS__ ) && \\\n\t!( defined( __WIN32__ ) || defined( __WINCE__ ) )\n  #define __WIN16__\n#endif /* Windows without Win32 or WinCE */\n\n/* If we're using a DOS compiler and it's not a 32-bit one, record this.\n   __MSDOS__ is predefined by a number of compilers, so we use __MSDOS16__\n   for stuff that's 16-bit DOS specific, and __MSDOS32__ for stuff that's\n   32-bit DOS specific */\n\n#if defined( __MSDOS__ ) && !defined( __MSDOS32__ )\n  #define __MSDOS16__\n#endif /* 16-bit DOS */\n#if defined( __WATCOMC__ ) && defined( __DOS__ )\n  #ifndef __MSDOS__\n\t#define __MSDOS__\n  #endif /* 16- or 32-bit DOS */\n  #if defined( __386__ ) && !defined( __MSDOS32__ )\n\t#define __MSDOS32__\n  #endif /* 32-bit DOS */\n#endif /* Watcom C under DOS */\n\n/* Make the defines for various OSes look a bit more like the usual ANSI \n  defines that are used to identify the other OS types */\n\n#ifdef __TANDEM\n  #if defined( _OSS_TARGET )\n\t#define __TANDEM_OSS__\n  #elif defined( _GUARDIAN_TARGET )\n\t#define __TANDEM_NSK__\n  #else\n\t#error \"Can't determine Tandem OS target type (NSK or OSS)\"\n  #endif /* Tandem OSS vs. NSK */\n#endif /* Tandem */\n\n#if defined( __MWERKS__ ) || defined( SYMANTEC_C ) || defined( __MRC__ )\n  #define __MAC__\n#endif /* Macintosh */\n\n#if defined( __OS400__ ) || defined( __ILEC400__ )\n  #define __AS400__\n#endif /* AS/400 */\n\n#ifdef __PALMSOURCE__\n  #define __PALMOS__\n#endif /* Palm OS */\n\n#ifdef __VMS\n  #define __VMS__\n#endif /* VMS */\n\n#if defined( __APPLE__ )\n  /* Apple provides an environment-specific file that provides detailed\n\t information about the target enviroment, defining TARGET_OS_xxx to 1\n\t for a given target environment */\n  #include <TargetConditionals.h>\n  #if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR\n\t#define __iOS__\n  #elif TARGET_OS_WATCH\n\t/* It's a bit unclear what the OS for Apple's watch will eventually end \n\t   up as, for now we treat it as iOS since we're only accessing the low-\n\t   level functionality */\n\t#define __iOS__\n  #endif /* iOS aliases */\n#endif /* __APPLE__ */\n\n/* In some cases we're using a Windows system as an emulated cross-\n   development platform, in which case we are we add extra defines to turn \n   off some Windows-specific features.  The override for BOOLEAN is required \n   because once __WIN32__ is turned off we try and typedef BOOLEAN, but \n   under Windows it's already typedef'd which leads to error messages */\n\n#if defined( __WIN32__ ) && ( _MSC_VER == 1200 ) && defined( CROSSCOMPILE )\n  /* Embedded OS variant.  Remember to change Project | Settings | C/C++ |\n\t Preprocessor | Additional include directories as per the code \n\t comments, and add the new OS to the USE_THREADS and USE_EMBEDDED_OS \n\t defines in config.h */\n//\t#define __ARINC653__\t/* Extra include: ./,./embedded/arinc653 */\n//\t#define __CMSIS__\t\t/* Extra include: ./,./embedded/cmsis */\n//\t#define __embOS__\t\t/* Extra include: ./,./embedded/embos */\n//\t#define __FreeRTOS__\t/* Extra include: ./,./embedded/freertos */\n//\t#define __ITRON__\t\t/* Extra include: ./,./embedded/itron */\n\t#define __MGOS__\t\t/* Extra include: ./,./embedded/mgos,./embedded */\n//\t#define __MQXRTOS__\t\t/* Extra include: ./,./embedded/mqx */\n//\t#define __Nucleus__\t\t/* Extra include: ./,./embedded/nucleus */\n//\t#define __OSEK__\t\t/* Extra include: ./,./embedded/osek */\n//\t#define __Quadros__\t\t/* Extra include: ./,./embedded/quadros */\n//\t#define __RTEMS__\t\t/* Extra include: ./,./embedded/rtems */\n//\t#define __SMX__\t\t\t/* Extra include: ./,./embedded/smx/xsmx,./embedded/smx/xfs */\n//\t#define __Telit__\t\t/* Extra include: ./,./embedded/telit */\n//\t#define __ThreadX__\t\t/* Extra include: ./,./embedded/threadx */\n//\t#define __TKernel__\t\t/* Extra include: ./,./embedded/tk */\n//  #define __UCOS__\t\t/* Extra include: ./,./embedded/ucos */\n//\t#define __VxWorks__\t\t/* Extra include: ./,./embedded/vxworks/,./embedded/vxworks/wrn/coreip/ */\n\n  /* Embedded OS additions (filesystems, networking).  Include directory \n     changes as before */\n  #if defined( __MGOS__ )\n\t#define USE_LWIP\t\t/* Extra include: ...,./embedded */\n\t\t\t\t\t\t\t/* LWIP uses absolute paths, so the 'lwip' in \n\t\t\t\t\t\t\t   the path is part of the #include */\n  #endif /* OSes that support LWIP */\n\n  /* If we're using an embedded OS without support for a particular feature,\n     disable it */\n  #if defined( __ARINC653__ ) || defined( __ITRON__ ) || defined( __OSEK__ ) \n\t#define CONFIG_NO_SESSIONS\n  #endif /* Embedded OSes without built-in networking support */\n\n  /* Undo Windows defines */\n  #undef __WINDOWS__\n  #undef __WIN32__\n  #if !defined( __Nucleus__ ) && !defined( __SMX__ ) && !defined( __UCOS__ )\n\t#define BOOLEAN\t\t\tFNORDIAN\n  #endif /* Systems that typedef BOOLEAN */\n  #ifdef __Nucleus__\n\t#undef FAR\n  #endif /* Systems that define FAR */\n\n  /* Embedded SDK-specific additional defines */\n  #if defined( __VxWorks__ ) && !defined( _WRS_KERNEL )\n\t#define _WRS_KERNEL\t\t1\n  #endif /* SDK-specific defines */\n  #if defined( __OSEK__ )\n\t/* OSEK uses statically-defined mutex IDs, these are normally set via \n\t   the config tool but aren't available for cross-compile builds */\n\t#define initialisationMutex\t\t0x01\n\t#define objectTableMutex\t\t0x02\n\t#define semaphoreMutex\t\t\t0x03\n\t#define mutex1Mutex\t\t\t\t0x04\n\t#define mutex2Mutex\t\t\t\t0x05\n\t#define mutex3Mutex\t\t\t\t0x06\n\t#define allocationMutex\t\t\t0x07\n  #endif /* __OSEK__ */\n\n  /* In addition '__i386__' (assuming gcc with an x86 target) needs to be \n     defined globally via Project Settings | C/C++ | Preprocessor.  This\n\t is already defined for the 'Crosscompile' build configuration */\n#endif /* Windows emulated cross-compile environment */\n\n#ifdef _SCCTK\n  #define __IBM4758__\n#endif /* IBM 4758 cross-compiled under Windows */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCompiler Detection and Configuration\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Visual C++ capabilities have changed somewhat over the years, the \n   following defines make explicit what we're testing for in a check of \n   _MSC_VER.\n\n\tVisual C++ 1.5 _MSC_VER = 800\n\tVisual C++ 2.0 _MSC_VER = 900\n\tVisual C++ 4.0 _MSC_VER = 1000\n\tVisual C++ 5.0 _MSC_VER = 1100\n\tVisual C++ 6.0 _MSC_VER = 1200\n\tVisual C++ 7.0 (VC++.NET/2002) _MSC_VER = 1300\n\tVisual C++ 7.1 (VC++.NET/2003) _MSC_VER = 1310\n\tVisual C++ 8.0 (VS2005) _MSC_VER = 1400 \n\tVisual C++ 9.0 (VS2008) _MSC_VER = 1500\n\tVisual C++ 10.0 (VS2010) _MSC_VER = 1600 \n\tVisual C++ 11.0 (VS2012) _MSC_VER = 1700\n\tVisual C++ 12.0 (VS2013) _MSC_VER = 1800 \n\tVisual C++ 14.0 (VS2015) _MSC_VER = 1900\n\tVisual C++ 14.1x (VS2017) _MSC_VER = 191x\n\n   Starting with VS2017 and in line with the mainline Windows 10 update \n   cretinism, the version number is incremented from 1900 for every minor \n   update, starting at 1910 for Visual C++ 14.1 (VS2017) */\n\n#ifdef _MSC_VER\n  #define VC_16BIT( version )\t\t( version <= 800 )\n  #define VC_LE_VC6( version )\t\t( version <= 1200 )\n  #define VC_GE_2002( version )\t\t( version >= 1300 )\n  #define VC_LT_2005( version )\t\t( version < 1400 )\n  #define VC_GE_2005( version )\t\t( version >= 1400 )\n  #define VC_GE_2008( version )\t\t( version >= 1500 )\n  #define VC_LT_2010( version )\t\t( version < 1600 )\n  #define VC_GE_2010( version )\t\t( version >= 1600 )\n  #define VC_GE_2012( version )\t\t( version >= 1700 )\n  #define VC_GE_2013( version )\t\t( version >= 1800 )\n  #define VC_GE_2015( version )\t\t( version >= 1900 )\n  #define VC_LT_2017( version )\t\t( version < 1910 )\n  #define VC_GE_2017( version )\t\t( version >= 1910 )\n#else\n  /* These aren't specifically required on non-VC++ systems, but some \n     preprocessors get confused if they aren't defined */\n  #define VC_16BIT( version )\t\t0\n  #define VC_LE_VC6( version )\t\t0\n  #define VC_GE_2002( version )\t\t0\n  #define VC_LT_2005( version )\t\t0\n  #define VC_GE_2005( version )\t\t0\n  #define VC_GE_2008( version )\t\t0\n  #define VC_GE_2010( version )\t\t0\n  #define VC_GE_2012( version )\t\t0\n  #define VC_GE_2013( version )\t\t0\n  #define VC_GE_2015( version )\t\t0\n  #define VC_LT_2017( version )\t\t0\n  #define VC_GE_2017( version )\t\t0\n#endif /* Visual C++ */\n\n/* If we're compiling under VC++ with the maximum level of warnings, turn\n   off some of the more irritating warnings */\n\n#if defined( _MSC_VER )\n  #if VC_16BIT( _MSC_VER )\n\t#pragma warning( disable: 4135 )/* Conversion bet.diff.integral types */\n\t#pragma warning( disable: 4761 )/* Integral size mismatch in argument */\n  #endif /* 16-bit VC++ */\n\n  /* Warning level 3:\n  \n\t 4018: Comparing signed <-> unsigned value.  The compiler has to convert \n\t\t   the signed value to unsigned to perform the comparison.  This \n\t\t   leads to around 25 false-positive warnings.  Note that this is\n\t\t   a variant of the VC++ 2005-only warning 4267, this one warns\n\t\t   about comparing the result of a sizeof() operation to an int and\n\t\t   4267 warns about size_t types in general */\n  #pragma warning( disable: 4018 )\t/* Comparing signed <-> unsigned value */\n\n  /* Warning level 4:\n\n\t 4054, 4055: Cast from function pointer -> generic (data) pointer, cast \n\t\t   from generic (data) pointer -> function pointer.  These are \n\t\t   orthogonal and impossible to disable as they override the \n\t\t   universal 'void *' pointer type.\n\n\t 4057: Different types via indirection.  An annoying dual-purpose \n\t\t   warning that leads to huge numbers of false positives for \n\t\t   'char *' vs. 'unsigned char *' (for example due to a PKCS #11 \n\t\t   token label, declared as 'unsigned char *', being passed to a \n\t\t   string function, these are pretty much un-fixable as 'char'\n\t\t   vs. 'unsigned char's percolate up and down the code tree), \n\t\t   but that also provides useful warnings of potential problems \n\t\t   (for example 'int *' passed to function expecting 'long *').\n\n\t 4204, 4221: Struct initialised with non-const value, struct initialised \n\t\t   with address of automatic variable.  Standards extensions that \n\t\t   the struct STATIC_INIT macros manage for us.\n\n\t 4206: Empty C module due to #ifdef'd out code.  Annoying noise caused \n\t\t   by empty modules due to disabled functionality.\n\n\t The only useful ones are 4057, which can be turned off on a one-off \n\t basis to identify new true-positive issues before being disabled again \n\t to avoid all of the false-positives, currently 100 for 4057 */\n  #pragma warning( disable: 4054 )\t/* Cast from fn.ptr -> generic (data) ptr.*/\n  #pragma warning( disable: 4055 )\t/* Cast from generic (data) ptr. -> fn.ptr.*/\n  #pragma warning( disable: 4057 )\t/* Different types via indirection */\n  #pragma warning( disable: 4204 )\t/* Struct initialised with non-const value */\n  #pragma warning( disable: 4206 )\t/* Empty C module due to #ifdef'd out code */\n  #pragma warning( disable: 4221 )\t/* Struct initialised with addr.of auto.var */\n  #if VC_GE_2005( _MSC_VER )\n\t#pragma warning( disable: 4267 )/* int <-> size_t */\n  #endif /* VC++ 2005 or newer */\n\n  /* Different versions of VC++ generates extra warnings at level 4 due to \n\t problems in VC++/Platform SDK headers */\n  #pragma warning( disable: 4201 )/* Nameless struct/union in SQL/networking hdrs*/\n  #if VC_GE_2005( _MSC_VER )\n\t#pragma warning( disable: 4214 )/* bit field types other than int */\n  #endif /* VC++ 2005 or newer */\n\n  /* Code analysis generates even more warnings.  C6011 is particularly \n\t problematic, it's issued whenever a pointer is derefenced without first\n\t checking that it's not NULL, which makes it more or less unusable */\n  #if defined( _MSC_VER ) && defined( _PREFAST_ ) \n\t#pragma warning( disable: 6011 )/* Deferencing NULL pointer */\n  #endif /* VC++ with source analysis enabled */\n\n  /* Windows DDK free builds treat warnings as errors and the DDK headers \n\t have some problems so we have to disable additional warnings */\n  #ifdef WIN_DDK\n\t#pragma warning( disable: 4242 )/* MS-only bit field type used */\n\t#pragma warning( disable: 4731 )/* Frame pointer modified by inline asm */\n  #endif /* WIN_DDK */\n\n  /* gcc -wall type warnings.  The highest warning level generates large\n\t numbers of spurious warnings (including ones in VC++ headers), so it's\n\t best to only enable them for one-off test builds requiring manual\n\t checking for real errors */\n  #pragma warning( disable: 4100 )\t/* Unreferenced parameter */\n#endif /* Visual C++ */\n\n/* Under VC++/VS a number of warnings are disabled by default, including \n   some potentially useful ones, so we re-enable them.  The warnings are\n   listed as \"Compiler Warnings That Are Off by Default\", currently at\n   https://msdn.microsoft.com/en-us/library/23k5d385.aspx.\n\n\tC4242 'identifier': conversion from 'type1' to 'type2', possible loss of \n\t\t  data.\n\tC4255 'function': no function prototype given: converting '()' to \n\t\t  '(void)'.\n\tC4287 'operator': unsigned/negative constant mismatch.\n\tC4296 'operator': expression is always false.\n\tC4302 'conversion' : truncation from 'type 1' to 'type 2'.\n\tC4311 'variable' : pointer truncation from 'type' to 'type'.\n\tC4312 'operation' : conversion from 'type1' to 'type2' of greater size,\n\t\t  assigning a 32-bit type to a 64-bit pointer.\n\tC4431 missing type specifier - int assumed.\n\tC4545 expression before comma evaluates to a function which is missing \n\t\t  an argument list.\n\tC4546 function call before comma missing argument list.\n\tC4547 'operator' : operator before comma has no effect; expected \n\t\t  operator with side-effect.\n\tC4548 expression before comma has no effect; expected expression with \n\t\t  side-effect.\n\tC4549 'operator' : operator before comma has no effect; did you intend \n\t\t  'operator'?\n\tC4555 expression has no effect; expected expression with side-effect.\n\tC4557 '__assume' contains effect 'effect'.\n\tC4574 'identifier' is defined to be '0': did you mean to use '#if \n\t\t  identifier'?\n\tC4619 #pragma warning : there is no warning number 'number'.\n\tC4628 digraphs not supported with -Ze. Character sequence 'digraph' \n\t\t  not interpreted as alternate token for 'char'.\n\tC4668 'symbol' is not defined as a preprocessor macro, replacing with \n\t\t  '0' for 'directives'.  \n\t\t  Note that enabling this check causes warnings in Windows header \n\t\t  files.\n\tC4826 Conversion from 'type1 ' to 'type2' is sign-extended.\n\tC4837 trigraph detected: '??%c' replaced by '%c'.\n\n   These are all defined only for newer versions of VC++ (2005 and up) so \n   they need a recent compiler in order to be evaluated.\n\n   These versions also have the potentially useful warning 'C4390 empty \n   controlled statement found' (e.g. 'if( i );'), on by default for W3 and \n   above, however this warning has no effect in either VS 2005 or VS 2010,\n   it seems to be triggered by random misplaced semicolons rather than the\n   presence of empty controlled statements, e.g. 'if( foo; )' */\n\n#if defined( _MSC_VER )\n  #pragma warning( 3: 4242 )\n  #pragma warning( 3: 4255 )\n  #pragma warning( 3: 4287 )\n  #pragma warning( 3: 4296 )\n  #pragma warning( 3: 4302 )\n  #pragma warning( 3: 4311 )\n  #pragma warning( 3: 4312 )\n  #pragma warning( 3: 4431 )\n  #pragma warning( 3: 4545 )\n  #pragma warning( 3: 4546 )\n  #pragma warning( 3: 4547 )\n  #pragma warning( 3: 4548 )\n  #pragma warning( 3: 4549 )\n  #pragma warning( 3: 4555 )\n  #pragma warning( 3: 4557 )\n  #pragma warning( 3: 4574 )\n  #pragma warning( 3: 4619 )\n  #pragma warning( 3: 4628 )\n  #pragma warning( 3: 4668 )\n  #pragma warning( 3: 4826 )\n  #pragma warning( 3: 4837 )\n#endif /* Visual C++ */\n\n/* VC++ 2005 implements the TR 24731 security extensions but doesn't yet \n   define __STDC_LIB_EXT1__, so if we detect this version of the compiler we \n   define it ourselves */\n\n#if defined( _MSC_VER ) && VC_GE_2005( _MSC_VER ) && \\\n\t!defined( __STDC_LIB_EXT1__ )\n  #define __STDC_LIB_EXT1__\n#endif /* VC++ 2005 without __STDC_LIB_EXT1__ defined */\n\n/* The ability to modify warnings via the project file in BC++ 5.0x is\n   completely broken, the only way to do this is via pragmas in the source\n   code */\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n  /* Spurious warnings to disable */\n  #pragma warn -aus\t\t\t\t\t\t/* Assigned but never used.  This is\n\t\t\t\t\t\t\t\t\t\t   frequently misreported even when\n\t\t\t\t\t\t\t\t\t\t   the value is quite obviously used */\n  #pragma warn -csu\t\t\t\t\t\t/* Comparing signed/unsigned value */\n  #pragma warn -par\t\t\t\t\t\t/* Parameter is never used\t*/\n  #pragma warn -sig\t\t\t\t\t\t/* Conversion may lose significant digits */\n  #pragma warn -ucp\t\t\t\t\t\t/* Signed/unsigned char assignment */\n\n  /* Useful warnings to enable */\n  #pragma warn +amb\t\t\t\t\t\t/* Ambiguous operators need parentheses */\n  #pragma warn +amp\t\t\t\t\t\t/* Superfluous & with function */\n  #pragma warn +asm\t\t\t\t\t\t/* Unknown assembler instruction */\n  #pragma warn +ccc\t\t\t\t\t\t/* Condition is always true/false */\n  #pragma warn +cln\t\t\t\t\t\t/* Constant is long */\n  #pragma warn +def\t\t\t\t\t\t/* Use of ident before definition */\n  #pragma warn +stv\t\t\t\t\t\t/* Structure passed by value */\n#endif /* Broken BC++ 5.0x warning handling */\n\n/* The TI compiler needs to have a few annoying warnings disabled */\n\n#if defined( __TI_COMPILER_VERSION__ )\n  #pragma diag_suppress 190\t\t\t\t/* enum vs. int */\n#endif /* TI compiler */\n\n/* The IAR compiler warns about all manner of pointless stuff that seems to\n   be motivated more by the compiler developers' desire to show off how \n   smart they are than any real help it provides with code development.  \n   This includes things that don't have any effect on compiling (e.g. CRLF \n   vs. LF line endings) or are a mandatory part of the C standard (type 1 \n   promoted to type 2).  As an added benefit it includes warnings that can \n   never be disabled even if it seems that they can.  \n   \n   We try and disable the more annoying and pointless ones here, but the \n   fact that there's a diag_suppress for a particular warning doesn't mean \n   that it'll actually get suppressed */\n\n#ifdef __IAR_SYSTEMS_ICC__\n  #pragma diag_suppress=Pa050\t\t\t/* LF vs. CRLF line endings */\n  #pragma diag_suppress=Pa084\t\t\t/* Result of comparison always true */\n  #pragma diag_suppress=Pa118\t\t\t/* Mixing bool.and non-bool in a comparison */\n  #pragma diag_suppress=Pe167\t\t\t/* char * vs. unsigned char * */\n  #pragma diag_suppress=Pe186\t\t\t/* Compare unsigned using '>= 0' */\n  #pragma diag_suppress=Pe188\t\t\t/* int vs. enum */\n#endif /* IAR */\n\n/* All Windows CE functions are Unicode-only, this was an attempt to clean\n   up the ASCII vs. Unicode kludges in Win32 but unfortunately was made just\n   before UTF8 took off.  Because UTF8 allows everyone to keep using their\n   old ASCII stuff while being nominally Unicode-aware, it's unlikely that\n   any new Unicode-only systems will appear in the future, leaving WinCE's\n   Unicode-only API an orphan.  The easiest way to handle this is to convert\n   all strings to ASCII/8 bit as they come in from the external cryptlib API\n   and convert them back to Unicode as required when they're passed to WinCE\n   OS functions.  In other words Unicode is treated just like EBCDIC and\n   pushed out to the edges of cryptlib.  This requires the minimum amount of\n   conversion and special-case handling internally */\n\n#ifdef __WINCE__\n  #define UNICODE_CHARS\n#endif /* WinCE */\n\n/* Symbian has rather inconsistent defines depending in which toolchain \n   we're using, with the original ARM tools the define was __SYMBIAN32__\n   with __MARM__ for the ARM architecture, with the ex-Metrowerks Nokia\n   compiler the define is __EMU_SYMBIAN_OS__ for the emulated environment\n   and who knows what for the gcc toolchain.  To make checking easier we\n   require __SYMBIAN32__ for all environments, with __MARM__ vs.\n   __EMU_SYMBIAN_OS__ distinguishing between ARM and x86 emulator */\n\n#if defined( __EMU_SYMBIAN_OS__ ) && !defined( __SYMBIAN32__ )\n  #error Need to define '__SYMBIAN32__' for the Symbian build\n#endif /* __EMU_SYMBIAN_OS__ && !__SYMBIAN32__ */\n#if defined( __SYMBIAN32__ ) && \\\n\t!( defined( __MARM__ ) || defined( __EMU_SYMBIAN_OS__ ) )\n  #error Need to define a Symbian target architecture type, e.g. ARM or x86\n#endif /* __SYMBIAN32__ && !( __MARM__ || __EMU_SYMBIAN_OS__ ) */\n\n/* Some systems (typically 16-bit or embedded ones) have rather limited\n   amounts of memory available, if we're building on one of these we limit\n   the size of some of the buffers that we use and the size of the object\n   table */\n\n#if defined( __MSDOS16__ ) || defined( __uClinux__ )\n  #define CONFIG_CONSERVE_MEMORY\n  #define CONFIG_NUM_OBJECTS\t\t128\n#endif /* Memory-starved systems */\n\n/* Since the Win32 randomness-gathering uses a background randomness polling\n   thread, we can't build a Win32 version with NO_THREADS */\n\n#if defined( __WIN32__ ) && defined( NO_THREADS )\n  #error The Win32 version of cryptlib must have threading enabled\n#endif /* Win32 without threading */\n\n/* Enable use of assembly-language alternatives to C functions if possible.\n   Note that the following asm defines are duplicated in crypt/osconfig.h,\n   because the OpenSSL headers are non-orthogonal to the cryptlib ones.  Any \n   changes made here need to be reflected in osconfig.h */\n\n#if defined( __WIN32__ ) && \\\n\t!( defined( __WIN64__ ) || defined( __BORLANDC__ ) || defined( NO_ASM ) )\n  /* Enable use of the AES ASM code */\n  #define AES_ASM\n#endif /* Win32 */\n\n/* Alongside the general crypto asm code there's also inline asm to handle \n   things like CPU hardware features, if we're running under Win64 we have \n   to disable this as well */\n\n#if defined( __WIN64__ )\n  #define NO_ASM\n#endif /* Win64 */\n\n/* On systems that support dynamic loading, we bind various drivers and\n   libraries at runtime rather than at compile time.  Under Windows this is\n   fairly easy but under Unix it's supported somewhat selectively and may be\n   buggy or platform-specific */\n\n#if defined( __WINDOWS__ ) || \\\n\t( defined( __UNIX__ ) && \\\n\t  ( ( defined( sun ) && OSVERSION > 4 ) || defined( __linux__ ) || \\\n\t\tdefined( _AIX ) || ( defined( __APPLE__ ) && !defined( __MAC__ ) ) ) ) || \\\n\tdefined( __ANDROID__ )\n  #define DYNAMIC_LOAD\n#endif /* Systems that support dynamic loading */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tEndianness Defines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If the endianness isn't predefined and the compiler can tell us what\n   endianness we've got, use this in preference to all other methods.  This\n   is only really necessary on non-Unix systems since the makefile runtime\n   test will tell us the endianness under Unix */\n\n#ifdef __GNUC__\n  /* Apple and NetBSD do it differently to everyone else in the universe */\n  #if defined( __APPLE__ )\n\t#include <machine/endian.h>\n  #elif defined( __NetBSD__ )\n\t#include <sys/endian.h>\n  #else\n\t#include <endian.h>\n  #endif /* Apple vs. everyone else */\n#endif /* GCC */\n\n#if defined( CONFIG_DATA_LITTLEENDIAN ) || defined( CONFIG_DATA_BIGENDIAN )\n  /* If we're cross-compiling for another system, the endianness auto-\n\t detection will have been overridden.  In this case we force it to be\n\t what the user has specified rather than what we've auto-detected */\n  #undef DATA_LITTLEENDIAN\n  #undef DATA_BIGENDIAN\n  #ifdef CONFIG_DATA_LITTLEENDIAN\n\t#define DATA_LITTLEENDIAN\n  #else\n\t#define DATA_BIGENDIAN\n  #endif /* CONFIG_DATA_LITTLEENDIAN */\n#endif /* Forced big vs.little-endian */\n\n#if !defined( DATA_LITTLEENDIAN ) && !defined( DATA_BIGENDIAN )\n  #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) && defined( BYTE_ORDER )\n\t/* Some systems define both BIG_ENDIAN and LITTLE_ENDIAN, then define\n\t   BYTE_ORDER to the appropriate one, so we check this and define the\n\t   appropriate value */\n\t#if ( BYTE_ORDER == BIG_ENDIAN ) && !defined( DATA_BIGENDIAN )\n\t  #define DATA_BIGENDIAN\n\t#elif ( BYTE_ORDER == LITTLE_ENDIAN ) && !defined( DATA_LITTLEENDIAN )\n\t  #define DATA_LITTLEENDIAN\n\t#else\n\t  #error BYTE_ORDER is neither BIG_ENDIAN nor LITTLE_ENDIAN\n\t#endif /* BYTE_ORDER-specific define */\n  #elif defined( __BYTE_ORDER__ ) && \\\n\t\t( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )\n\t#define DATA_BIGENDIAN\n  #elif defined( __BYTE_ORDER__ ) && \\\n\t\t( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )\n\t#define DATA_LITTLEENDIAN\n  #elif defined( __LITTLE_ENDIAN__ )\n\t#if __LITTLE_ENDIAN__ == 1\n\t  #define DATA_LITTLEENDIAN\n\t#else\n\t  #define DATA_BIGENDIAN\n\t#endif /* __LITTLE_ENDIAN__ */\n  #elif defined( __i386 ) || defined( __i386__ ) || defined( __i486__ ) || \\\n\t\tdefined( __i586__ ) || defined( __i686__ ) || defined( _M_I86 ) || \\\n\t\tdefined( _M_IX86 ) || defined( _M_X64 ) || defined( __amd64__ ) || \\\n\t\tdefined( __x86_64__ ) || defined( _M_AMD64 ) || \\\n\t\tdefined( __TURBOC__ ) || defined( __OS2__ )\n\t#define DATA_LITTLEENDIAN\t/* Intel architecture always little-endian */\n  #elif defined( __WINCE__ )\n\t/* For WinCE it can get a bit complicated, however because of x86 cargo\n\t   cult programming WinCE systems always tend to be set up in little-\n\t   endian mode */\n\t#define DATA_LITTLEENDIAN\t/* Intel architecture always little-endian */\n  #elif defined( __sparc ) || defined( __sparc__ ) \n\t#define DATA_BIGENDIAN\t\t/* Sparc always big-endian */\n  #elif defined( _ARCH_PPC ) || defined( _ARCH_PPC64 ) || \\\n\t\tdefined( __powerpc ) || defined( __powerpc__ ) || \\\n\t\tdefined( __ppc__ )\n\t#define DATA_BIGENDIAN\t\t/* PowerPC always big-endian */\n  #elif defined( __AARCH64EB__ ) || defined( __ARMEB__ ) || \\\n\t\tdefined( __MIPSEB ) || defined( __MIPSEB__ ) || \\\n\t\tdefined( _MIPSEB ) || defined( __THUMBEB__ )\n\t#define DATA_BIGENDIAN\t\t/* ARM/MIPS explicit big-endian */\n  #elif defined( __AARCH64EL__ ) || defined( __ARMEL__ ) || \\\n\t\tdefined( __MIPSEL ) || defined( __MIPSEL__ ) || \\\n\t\tdefined( _MIPSEL ) || defined( __THUMBEL__ )\n\t#define DATA_LITTLEENDIAN\t/* ARM/MPIS explicit little-endian */\n  #elif defined( AMIGA ) || defined( __MWERKS__ ) || defined( SYMANTEC_C ) || \\\n\t\tdefined( THINK_C ) || defined( applec ) || defined( __MRC__ )\n\t#define DATA_BIGENDIAN\t\t/* Motorola architecture always big-endian */\n  #elif defined( VMS ) || defined( __VMS )\n\t#define DATA_LITTLEENDIAN\t/* VAX architecture always little-endian */\n  #elif defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n\t#define DATA_BIGENDIAN\t\t/* Tandem architecture always big-endian */\n  #elif defined( __AS400__ ) || defined( __VMCMS__ ) || defined( __MVS__ )\n\t#define DATA_BIGENDIAN\t\t/* IBM big iron always big-endian */\n  #elif defined( __SYMBIAN32__ ) && \\\n\t\t( defined( __MARM__ ) || defined( __EMU_SYMBIAN_OS__ ) )\n\t#define DATA_LITTLEENDIAN\t/* Symbian on ARM/x86 always little-endian */\n  #elif defined( __Nucleus__ ) && defined( __RVCT2_1__ )\n\t#if defined( __BIG_ENDIAN )\t/* Realview for Nucleus */\n\t  #define DATA_BIGENDIAN\n\t#else\n\t  #define DATA_LITTLEENDIAN\n\t#endif /* Big vs.little-endian */\n  #elif defined( __m68k__  )\n\t#define DATA_BIGENDIAN\t\t/* 68K always big-endian */\n  #elif defined( __TI_COMPILER_VERSION__ )\n\t/* The TI compiler can masquerade as gcc so we need to check for it \n\t   before we check for Gnu indicators */\n\t#if CPU_BYTE_ORDER == LOW_BYTE_FIRST\n\t  #define DATA_LITTLEENDIAN\n\t#elif CPU_BYTE_ORDER == HIGH_BYTE_FIRST\n\t  #define DATA_BIGENDIAN\n\t#else\n\t  #error Couldnt get endianness from CPU_BYTE_ORDER\n\t#endif /* TI compiler endianness detection */\n  #elif defined __GNUC__\n\t#ifdef BYTES_BIG_ENDIAN\n\t  #define DATA_BIGENDIAN\t/* Big-endian byte order */\n\t#else\n\t  #define DATA_LITTLEENDIAN\t/* Undefined = little-endian byte order */\n\t#endif /* __GNUC__ */\n  #endif /* Compiler-specific endianness checks */\n#endif /* !( DATA_LITTLEENDIAN || DATA_BIGENDIAN ) */\n\n/* The last-resort method.  Thanks to Shawn Clifford\n   <sysop@robot.nuceng.ufl.edu> for this trick.\n\n   NB: A number of compilers aren't tough enough for this test */\n\n#if !defined( DATA_LITTLEENDIAN ) && !defined( DATA_BIGENDIAN )\n  #if ( ( ( unsigned short ) ( 'AB' ) >> 8 ) == 'B' )\n\t#define DATA_LITTLEENDIAN\n  #elif ( ( ( unsigned short ) ( 'AB' ) >> 8 ) == 'A' )\n\t#define DATA_BIGENDIAN\n  #else\n\t#error \"Cannot determine processor endianness.  Edit misc/os_spec.h and recompile\"\n  #endif /* Endianness test */\n#endif /* !( DATA_LITTLEENDIAN || DATA_BIGENDIAN ) */\n\n/* Sanity check to catch both values being defined */\n\n#if defined( DATA_LITTLEENDIAN ) && defined( DATA_BIGENDIAN )\n  #error Both DATA_LITTLEENDIAN and DATA_BIGENDIAN are defined\n#endif /* DATA_LITTLEENDIAN && DATA_BIGENDIAN */\n\n#endif /* _OSDETECT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/os_spec.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib OS-specific Support Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1992-2007\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* IBM mainframe builds need extra functions for EBCDIC printf() */\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #define _OPEN_SYS_ITOA_EXT\n#endif /* IBM big iron debug build */\n\n#include <ctype.h>\n#include <stddef.h>\t\t/* For ptrdiff_t */\n#include <stdio.h>\n#include <time.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAMX\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __AMX__ )\n\n#include <cjzzz.h>\n\n/* The AMX task-priority function returns the priority via a reference\n   parameter.  Because of this we have to provide a wrapper that returns\n   it as a return value */\n\nint threadPriority( void )\n\t{\n\tint priority = 0;\n\n\tcjtkpradjust( cjtkid(), &priority );\n\treturn( priority );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tARINC 653\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ARINC653__ )\n\n#include <apex.h>\n\n/* The ARINC 653 API returns status codes as a by-reference parameter, in \n   cases where we don't care about the return status we need to provide a\n   dummy value to take this */\n\nRETURN_CODE_TYPE dummyRetCode;\n\n/* The ARINC 653 thread-self function returns the thread ID via a reference \n   parameter, because of this we have to provide a wrapper that returns it \n   as a return value */\n\nPROCESS_ID_TYPE threadSelf( void )\n\t{\n\tPROCESS_ID_TYPE processID;\n\tRETURN_CODE_TYPE retCode; \n\n\tGET_MY_ID( &processID, &retCode );\n\treturn( processID );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tuC/OS-II\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __UCOS__ )\n\n#undef BOOLEAN\t\t\t\t\t/* See comment in kernel/thread.h */\n#include <ucos_ii.h>\n#define BOOLEAN\t\t\tint\n\n/* uC/OS-II doesn't have a thread-self function, but allows general task\n   info to be queried.  Because of this we provide a wrapper that returns\n   the task ID as its return value */\n\nINT8U threadSelf( void )\n\t{\n\tOS_TCB osTCB;\n\n\tOSTaskQuery( OS_PRIO_SELF, &osTCB );\n\treturn( osTCB.OSTCBPrio );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tuITRON\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __ITRON__ )\n\n#include <itron.h>\n\n/* The uITRON thread-self function returns the thread ID via a reference\n   parameter since uITRON IDs can be negative and there'd be no way to\n   differentiate a thread ID from an error code.  Because of this we have\n   to provide a wrapper that returns it as a return value */\n\nID threadSelf( void )\n\t{\n\tID tskid;\n\n\tget_tid( &tskid );\n\treturn( tskid );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tIBM Mainframe\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* VM/CMS, MVS, and AS/400 systems need to convert characters from ASCII <->\n   EBCDIC before/after they're read/written to external formats, the\n   following functions perform the necessary conversion using the latin-1\n   code tables for systems that don't have etoa/atoe */\n\n#elif defined( EBCDIC_CHARS )\n\n#ifndef USE_ETOA\n\n/* ISO 8859-1 to IBM Latin-1 Code Page 01047 (EBCDIC) */\n\nstatic const BYTE asciiToEbcdicTbl[] = {\n\t0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,\t/* 00 - 07 */\n\t0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\t/* 08 - 0F */\n\t0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,\t/* 10 - 17 */\n\t0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,\t/* 18 - 1F */\n\t0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,\t/* 20 - 27 */\n\t0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,\t/* 28 - 2F */\n\t0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,\t/* 30 - 37 */\n\t0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,\t/* 38 - 3F */\n\t0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,\t/* 40 - 47 */\n\t0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,\t/* 48 - 4F */\n\t0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,\t/* 50 - 57 */\n\t0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,\t/* 58 - 5F */\n\t0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,\t/* 60 - 67 */\n\t0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,\t/* 68 - 6F */\n\t0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,\t/* 70 - 77 */\n\t0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,\t/* 78 - 7F */\n\t0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,\t/* 80 - 87 */\n\t0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,\t/* 88 - 8F */\n\t0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,\t/* 90 - 97 */\n\t0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,\t/* 98 - 9F */\n\t0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,\t/* A0 - A7 */\n\t0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,\t/* A8 - AF */\n\t0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,\t/* B0 - B7 */\n\t0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,\t/* B8 - BF */\n\t0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,\t/* C0 - C7 */\n\t0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,\t/* C8 - CF */\n\t0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,\t/* D0 - D7 */\n\t0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,\t/* D8 - DF */\n\t0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,\t/* E0 - E7 */\n\t0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,\t/* E8 - EF */\n\t0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,\t/* F0 - F7 */\n\t0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF\t/* F8 - FF */\n\t};\n\n/* IBM Latin-1 Code Page 01047 (EBCDIC) to ISO 8859-1 */\n\nstatic const BYTE ebcdicToAsciiTbl[] = {\n\t0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,\t/* 00 - 07 */\n\t0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\t/* 08 - 0F */\n\t0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87,\t/* 10 - 17 */\n\t0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,\t/* 18 - 1F */\n\t0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B,\t/* 20 - 27 */\n\t0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,\t/* 28 - 2F */\n\t0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,\t/* 30 - 37 */\n\t0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,\t/* 38 - 3F */\n\t0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,\t/* 40 - 47 */\n\t0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,\t/* 48 - 4F */\n\t0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,\t/* 50 - 57 */\n\t0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,\t/* 58 - 5F */\n\t0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,\t/* 60 - 67 */\n\t0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,\t/* 68 - 6F */\n\t0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,\t/* 70 - 77 */\n\t0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,\t/* 78 - 7F */\n\t0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,\t/* 80 - 87 */\n\t0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,\t/* 88 - 8F */\n\t0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,\t/* 90 - 97 */\n\t0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,\t/* 98 - 9F */\n\t0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,\t/* A0 - A7 */\n\t0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,\t/* A8 - AF */\n\t0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,\t/* B0 - B7 */\n\t0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,\t/* B8 - BF */\n\t0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,\t/* C0 - C7 */\n\t0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,\t/* C8 - CF */\n\t0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,\t/* D0 - D7 */\n\t0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,\t/* D8 - DF */\n\t0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,\t/* E0 - E7 */\n\t0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,\t/* E8 - EF */\n\t0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\t/* F0 - F7 */\n\t0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F\t/* F8 - FF */\n\t};\n\n/* Convert a string to/from EBCDIC */\n\nint asciiToEbcdic( char *dest, const char *src, const int length )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, length ) );\n\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\tdest[ i ] = asciiToEbcdicTbl[ ( unsigned int ) src[ i ] ];\n\tENSURES( LOOP_BOUND_OK );\n\treturn( CRYPT_OK );\n\t}\n\nint ebcdicToAscii( char *dest, const char *src, const int length )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, length ) );\n\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\tdest[ i ] = ebcdicToAsciiTbl[ ( unsigned int ) src[ i ] ];\n\tENSURES( LOOP_BOUND_OK );\n\treturn( CRYPT_OK );\n\t}\n#else\n\nint asciiToEbcdic( char *dest, const char *src, const int length )\n\t{\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, length ) );\n\n\tif( dest != src )\n\t\tmemcpy( dest, src, length );\n\treturn( __atoe_l( dest, length ) < 0 ? \\\n\t\t\tCRYPT_ERROR_BADDATA : CRYPT_OK );\n\t}\n\nint ebcdicToAscii( char *dest, const char *src, const int length )\n\t{\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, length ) );\n\n\tif( dest != src )\n\t\tmemcpy( dest, src, length );\n\treturn( __etoa_l( dest, length ) < 0 ? \\\n\t\t\tCRYPT_ERROR_BADDATA : CRYPT_OK );\n\t}\n#endif /* USE_ETOA */\n\n/* Convert a string to/from EBCDIC via a temporary buffer, used when passing \n   an ASCII string to a system function that requires EBCDIC and vice versa */\n\nchar *bufferToEbcdic( char *buffer, const char *string )\n\t{\n\tstrcpy( buffer, string );\n\tasciiToEbcdic( buffer, buffer, strlen( string ) );\n\treturn( buffer );\n\t}\n\nchar *bufferToAscii( char *buffer, const char *string )\n\t{\n\tstrcpy( buffer, string );\n\tebcdicToAscii( buffer, buffer, strlen( string ) );\n\treturn( buffer );\n\t}\n\n/* Table for ctype functions that explicitly use the ASCII character set */\n\n#define A\tASCII_ALPHA\n#define L\tASCII_LOWER\n#define N\tASCII_NUMERIC\n#define S\tASCII_SPACE\n#define U\tASCII_UPPER\n#define X\tASCII_HEX\n#define AL\t( A | L )\n#define AU\t( A | U )\n#define ANX\t( A | N | X )\n#define ALX\t( A | L | X )\n#define AUX\t( A | U | X )\n\nconst BYTE asciiCtypeTbl[ 256 ] = {\n\t/* 00\t   01\t   02\t   03\t   04\t   05\t   06\t   07  */\n\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\n\t/* 08\t   09\t   0A\t   0B\t   0C\t   0D\t   0E\t   0F */\n\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\n\t/* 10\t   11\t   12\t   13\t   14\t   15\t   16\t   17 */\n\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\n\t/* 18\t   19\t   1A\t   1B\t   1C\t   1D\t   1E\t   1F */\n\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\t\t0,\n\t/*\t\t\t!\t\t\"\t\t#\t\t$\t\t%\t\t&\t\t' */\n\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\n\t/* \t(\t\t)\t\t*\t\t+\t\t,\t\t-\t\t.\t\t/ */\n\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\n\t/*\t0\t\t1\t\t2\t\t3\t\t4\t\t5\t\t6\t\t7 */\n\t   ANX,\t   ANX,\t   ANX,\t   ANX,\t   ANX,\t   ANX,\t   ANX,\t   ANX,\n\t/*\t8\t\t9\t\t:\t\t;\t\t<\t\t=\t\t>\t\t? */\n\t   ANX,\t   ANX,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\n\t/*\t@\t\tA\t\tB\t\tC\t\tD\t\tE\t\tF\t\tG */\n\t\tA,\t   AUX,\t   AUX,\t   AUX,\t   AUX,\t   AUX,\t   AUX,\t   AU,\n\t/*\tH\t\tI\t\tJ\t\tK\t\tL\t\tM\t\tN\t\tO */\n\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\n\t/*\tP\t\tQ\t\tR\t\tS\t\tT\t\tU\t\tV\t\tW */\n\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\t   AU,\n\t/*\tX\t\tY\t\tZ\t\t[\t\t\\\t\t]\t\t^\t\t_ */\n\t   AU,\t   AU,\t   AU,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\n\t/*\t`\t\ta\t\tb\t\tc\t\td\t\te\t\tf\t\tg */\n\t\tA,\t   ALX,\t   ALX,\t   ALX,\t   ALX,\t   ALX,\t   ALX,\t   AL,\n\t/*\th\t\ti\t\tj\t\tk\t\tl\t\tm\t\tn\t\to */\n\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\n\t/*\tp\t\tq\t\tr\t\ts\t\tt\t\tu\t\tv\t\tw */\n\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\t   AL,\n\t/*\tx\t\ty\t\tz\t\t{\t\t|\t\t}\t\t~\t   DL */\n\t   AL,\t   AL,\t   AL,\t\tA,\t\tA,\t\tA,\t\tA,\t\tA,\n\t/* High-bit-set characters */\n\t0\n\t};\n\n/* stricmp()/strnicmp() versions that explicitly use the ASCII character\n   set.  In order for collation to be handled properly, we have to convert\n   to EBCDIC and use the local stricmp()/strnicmp() */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strCompare( IN_STRING const char *src, IN_STRING const char *dest, \n\t\t\t\tIN_LENGTH_SHORT const int length )\n\t{\n\tBYTE buffer1[ MAX_ATTRIBUTE_SIZE + 8 ];\n\tBYTE buffer2[ MAX_ATTRIBUTE_SIZE + 8 ];\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isReadPtrDynamic( dest, 1 ) );\n\n\tif( length <= 0 || length > MAX_ATTRIBUTE_SIZE )\n\t\treturn( 1 );\t/* Invalid length */\n\n\t/* Virtually all strings are 7-bit ASCII, the following optimisation\n\t   speeds up checking, particularly in cases where we're walking down a\n\t   list of keywords looking for a match */\n\tif( *src < 0x80 && *dest < 0x80 && \\\n\t\ttoLower( *src ) != toLower( *dest ) )\n\t\treturn( 1 );\t/* Not equal */\n\n\t/* Convert the strings to EBCDIC and use a native compare */\n\tsrc = bufferToEbcdic( buffer1, src );\n\tdest = bufferToEbcdic( buffer2, dest );\n\treturn( strncasecmp( src, dest, length ) );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint strCompareZ( IN_STRING const char *src, IN_STRING const char *dest )\n\t{\n\tconst int length = strlen( src );\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isReadPtrDynamic( dest, 1 ) );\n\n\tif( length != strlen( dest ) )\n\t\treturn( 1 );\t/* Lengths differ */\n\treturn( strCompare( src, dest, length ) );\n\t}\n\n/* sprintf_s() and vsprintf_s() that take ASCII format strings.  In addition \n   to the standard format specifiers, we also allow the nonstandard '%e' to \n   format an EBCDIC string.  This assumes that the format string is well-\n   formed, which it should be since the source is a cryptlib-internal fixed\n   string */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint vsPrintf_s( INOUT_BUFFER_FIXED( bufSize ) char *buffer, \n\t\t\t\tIN_LENGTH_SHORT const int bufSize, \n\t\t\t\tIN_STRING const char *format, \n\t\t\t\tva_list argPtr )\n\t{\n\tBYTE ch;\n\tint bufPos = 0, index, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( buffer, bufSize ) );\n\tassert( isReadPtrDynamic( format, 2 ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( bufSize ) );\n\n\tLOOP_LARGE( index = 0, \\\n\t\t\t\tbufPos < bufSize && ( ch = format[ index ] ) && ( ch != 0 ), \n\t\t\t\tindex++ )\n\t\t{\n\t\tBYTE formatBuffer[ MAX_ATTRIBUTE_SIZE + 1 + 8 ];\n\t\tBOOLEAN needsConversion = FALSE, needsUppercase = FALSE;\n\t\tBOOLEAN zeroPad = FALSE;\n\t\tint formatBufPos, padCount = 0, count, i;\n\n\t\t/* If it's not a formatting character, output it as is */\n\t\tif( ch != '%' )\n\t\t\t{\n\t\t\tbuffer[ bufPos++ ] = ch;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Process a format specifier */\n\t\tch = format[ ++index ];\n\t\tif( ch == '0' )\n\t\t\t{\n\t\t\tzeroPad = TRUE;\n\t\t\tch = format[ ++index ];\n\t\t\t}\n\t\tif( ch >= '1' && ch <= '9' )\n\t\t\t{\n\t\t\t/* Process padding requirements */\n\t\t\tpadCount = ch - '0';\n\t\t\tch = format[ ++index ];\n\t\t\t}\n\t\tswitch( ch )\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\tbreak;\n\n\t\t\tcase 'c' :\n\t\t\t\tformatBuffer[ 0 ] = ( char )( va_arg( argPtr, char ) );\n\t\t\t\tformatBuffer[ 1 ] = '\\0';\n\t\t\t\tbreak;\n\n\t\t\tcase 'd':\n\t\t\t\titoa( va_arg( argPtr, int ), formatBuffer, 10 );\n\t\t\t\tneedsConversion = TRUE;\n\t\t\t\tbreak;\n\t\n\t\t\tcase 'l':\n\t\t\t\tch = format[ ++index ];\n\t\t\t\tif( ch == 0 )\n\t\t\t\t\tbreak;\n\t\t\t\tltoa( va_arg( argPtr, long ), formatBuffer, ( ch == 'X' ) ? 16 : 10 );\n\t\t\t\tif( ch == 'X' )\n\t\t\t\t\tneedsUppercase = TRUE;\n\t\t\t\tneedsConversion = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase 's':\n\t\t\tcase 'e':\t/* For EBCDIC strings */ \n\t\t\t\t{\n\t\t\t\tconst char *bufPtr = va_arg( argPtr, char * );\n\t\t\t\tconst int bufStrLen = strlen( bufPtr );\n\n\t\t\t\tREQUIRES( isShortIntegerRange( bufStrLen ) );\n\n\t\t\t\t/* If we've been given an empty string, which can happen \n\t\t\t\t   when using the function as puts( \"\" ) -> printf( \"%s\\n\" )\n\t\t\t\t   to print a CRLF, there's nothing more to do */\n\t\t\t\tif( bufStrLen <= 0 )\n\t\t\t\t\tcontinue;\n\n\t\t\t\t/* Copy the string into a local buffer and convert it from \n\t\t\t\t   EBCDIC if necessary */\n\t\t\t\tif( bufStrLen > MAX_ATTRIBUTE_SIZE )\n\t\t\t\t\tstrcpy( formatBuffer, \"<<<String too long>>>\" );\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tstrcpy( formatBuffer, bufPtr );\n\t\t\t\t\tif( ch == 'e' )\n\t\t\t\t\t\tneedsConversion = TRUE;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n#if 0\t\t/* Not currently used */\n\t\t\tcase 'u':\n\t\t\t\tutoa( va_arg( argPtr, unsigned int ), formatBuffer, 10 );\n\t\t\t\tneedsConversion = TRUE;\n\t\t\t\tbreak;\n#endif /* 0 */\n\n\t\t\tcase 'x':\n\t\t\tcase 'X':\n\t\t\t\tutoa( va_arg( argPtr, unsigned int ), formatBuffer, 16 );\n\t\t\t\tif( ch == 'X' )\n\t\t\t\t\tneedsUppercase = TRUE;\n\t\t\t\tneedsConversion = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tformatBuffer[ 0 ] = ch;\n\t\t\t\tformatBuffer[ 1 ] = '\\0';\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( ch == 0 )\n\t\t\tbreak;\n\t\tif( needsConversion )\n\t\t\tbufferToAscii( formatBuffer, formatBuffer );\n\t\tformatBufPos = strlen( formatBuffer );\n\t\tif( needsUppercase )\n\t\t\t{\n\t\t\tLOOP_LARGE( i = 0, i < formatBufPos, i++ )\n\t\t\t\tformatBuffer[ i ] = toUpper( formatBuffer[ i ] );\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\tif( padCount > formatBufPos )\n\t\t\t{\n\t\t\tLOOP_SMALL( count = padCount - formatBufPos, \n\t\t\t\t\t\tcount > 0 && bufPos < bufSize, count-- )\n\t\t\t\tbuffer[ bufPos++ ] = zeroPad ? '0' : ' ';\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tif( bufPos >= bufSize )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tLOOP_LARGE( i = 0, i < formatBufPos && bufPos < bufSize, i++ )\n\t\t\tbuffer[ bufPos++ ] = formatBuffer[ i ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( bufPos >= bufSize )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tbuffer[ bufPos ] = '\\0';\n\n\treturn( bufPos );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint sPrintf_s( char *buffer, const int bufSize, const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vsPrintf_s( buffer, bufSize, format, argPtr );\n\tva_end( argPtr );\n\n\treturn( length );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tMQX\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In line with its mania for redefining standard C types in broken ways,\n   MQX redefines struct tm in a broken manner, giving its tm_mday a range\n   of 0...30 instead of the C standard 1...31, see \n   https://community.nxp.com/thread/437013.  What's more, the MQX docs\n   indicate that the function doesn't do much, if any, range checking (\"If \n   you violate the ranges, undefined behavior results\") so it'll probably \n   produce garbage results rather than rejecting a value that it considers \n   invalid.\n\n   To deal with this we define our own mktime() and gmtime_r() (there's no\n   gmtime(), only a gmtime_r()) that change the struct tm fields to get them \n   into the incorrect range that MQX uses */\n\n#elif defined( __MQXRTOS__ )\n\n#undef mktime\t\n#undef gmtime_r\t\t/* Restore the standard mktime() and gmtime_r() */\n\n#ifdef __IAR_SYSTEMS_ICC__\n  /* The IAR libraries don't provide any time functions, and since \n     gmtime_r() is a non-ANSI function there's no prototype for it in the\n\t IAR headers, although it is in the MQX headers but the IAR comiler can't\n\t seem to see it.  Because of this we have to provide it ourselves, \n\t matching the MQX prototype */\n  struct tm *gmtime_r( const time_t *timep, struct tm *result );\n#endif /* IAR compiler */\n\ntime_t my_mktime( struct tm *timeptr )\n\t{\n\tstruct tm mqxTime;\n\n\tmqxTime = *timeptr;\n\tif( mqxTime.tm_mday > 0 )\n\t\tmqxTime.tm_mday--;\t\t/* 1...31 -> 0...30 */\n\treturn( mktime( &mqxTime ) );\n\t}\n\nstruct tm *my_gmtime_r( const time_t *timep, struct tm *result )\n\t{\n\tstruct tm *resultPtr;\n\n\tresultPtr = gmtime_r( timep, result );\n\tif( resultPtr == NULL )\n\t\treturn( NULL );\n\tif( result->tm_mday < 31 )\n\t\tresult->tm_mday++;\t/* 0...30 -> 1...31 */\n\treturn( result );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tOSEK/VDX\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The OSEK thread-self function returns the thread ID via a reference \n   parameter, because of this we have to provide a wrapper that returns it \n   as a return value */\n\nTaskType threadSelf( void )\n\t{\n\tTaskType taskID;\n\n\tGetTaskID( &taskID );\n\treturn( taskID );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tPalmOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __Nucleus__ )\n\n#include <nucleus.h>\n\n/* Wrappers for the Nucleus OS-level memory allocation functions */\n\nextern NU_MEMORY_POOL Application_Memory;\n\nvoid *clAllocFn( size_t size )\n\t{\n\tSTATUS Rc;\n\tvoid *ptr;\n\n\tRc = NU_Allocate_Memory( &Application_Memory, &ptr, size, \n\t\t\t\t\t\t\t NU_NO_SUSPEND );\n\tif( Rc != NU_SUCCESS || ptr == NULL )\n\t\treturn( NULL );\n\treturn( ptr );\n\t}\n\nvoid clFreeFn( void *memblock )\n\t{\n\tNU_Deallocate_Memory( memblock );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tPalmOS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __PALMOS__ )\n\n#include <CmnErrors.h>\n#include <CmnLaunchCodes.h>\n\n/* The cryptlib entry point, defined in cryptlib.sld */\n\nuint32_t cryptlibMain( uint16_t cmd, void *cmdPBP, uint16_t launchFlags )\n\t{\n\tUNUSED_ARG( cmdPBP );\n\tUNUSED_ARG( launchFlags );\n\n\tswitch( cmd )\n\t\t{\n\t\tcase sysLaunchCmdInitialize:\n\t\t\t/* Set up the initialisation lock in the kernel */\n\t\t\tpreInit();\n\t\t\tbreak;\n\n\t\tcase sysLaunchCmdFinalize:\n\t\t\t/* Delete the initialisation lock in the kernel */\n\t\t\tpostShutdown();\n\t\t\tbreak;\n\t\t}\n\n\treturn( errNone );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tRTEMS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __RTEMS__ )\n\n/* The RTEMS thread-self function returns the task ID via a reference\n   parameter, because of this we have to provide a wrapper that returns it\n   as a return value.  We use RTEMS_SEARCH_ALL_NODES because there isn't\n   any other way to specify the local node, this option always searches the\n   local node first so it has the desired effect */\n\n#include <rtems.h>\n\nrtems_id threadSelf( void )\n\t{\n\trtems_id taskID;\n\n\trtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &taskID );\n\treturn( taskID );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tTandem\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The Tandem mktime() is broken and can't convert dates beyond 2023, if\n   mktime() fails and the year is between then and the epoch try again with\n   a time that it can convert */\n\n#elif defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n\n#undef mktime\t/* Restore the standard mktime() */\n\ntime_t my_mktime( struct tm *timeptr )\n\t{\n\ttime_t theTime;\n\n\ttheTime = mktime( timeptr );\n\tif( theTime < 0 && timeptr->tm_year > 122 && timeptr->tm_year <= 138 )\n\t\t{\n\t\ttimeptr->tm_year = 122;\t/* Try again with a safe year of 2022 */\n\t\ttheTime = mktime( timeptr );\n\t\t}\n\treturn( theTime );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tUnix\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __UNIX__ ) && \\\n\t  !( defined( __MVS__ ) || defined( __TANDEM_NSK__ ) || \\\n\t\t defined( __TANDEM_OSS__ ) )\n\n#include <sys/time.h>\n\n/* For performance evaluation purposes we provide the following function,\n   which returns ticks of the 1us timer */\n\nlong getTickCount( long startTime )\n\t{\n\tstruct timeval tv;\n\tlong timeLSB, timeDifference;\n\n\t/* Only accurate to about 1us */\n\tgettimeofday( &tv, NULL );\n\ttimeLSB = tv.tv_usec;\n\n\t/* If we're getting an initial time, return an absolute value */\n\tif( startTime <= 0 )\n\t\treturn( timeLSB );\n\n\t/* We're getting a time difference */\n\tif( startTime < timeLSB )\n\t\ttimeDifference = timeLSB - startTime;\n\telse\n\t\t{\n\t\t/* gettimeofday() rolls over at 1M us */\n\t\ttimeDifference = ( 1000000L - startTime ) + timeLSB;\n\t\t}\n\tif( timeDifference <= 0 )\n\t\t{\n\t\tprintf( \"Error: Time difference = %lX, startTime = %lX, \"\n\t\t\t\t\"endTime = %lX.\\n\", timeDifference, startTime, timeLSB );\n\t\treturn( 1 );\n\t\t}\n\treturn( timeDifference );\n\t}\n\n/* SunOS and older Slowaris have broken sprintf() handling.  In SunOS 4.x\n   this was documented as returning a pointer to the output data as per the\n   Berkeley original.  Under Slowaris the manpage was changed so that it\n   looks like any other sprintf(), but it still returns the pointer to the\n   output buffer in some versions so we use a wrapper that checks at\n   runtime to see what we've got and adjusts its behaviour accordingly.  In\n   fact it's much easier to fix than that, since we have to use vsprintf()\n   anyway and this doesn't have the sprintf() problem, this fixes itself\n   simply from the use of the wrapper (unfortunately we can't use \n   vsnprintf() because these older OS versions don't include it yet) */\n\n#if defined( sun ) && ( OSVERSION <= 5 )\n\n#include <stdarg.h>\n\nint fixedSprintf( char *buffer, const int bufSize, const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vsprintf( buffer, format, argPtr );\n\tva_end( argPtr );\n\n\treturn( length );\n\t}\n#endif /* Old SunOS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tWindows\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __WIN32__ )\n\n/* Yielding a thread on an SMP or HT system is a tricky process,\n   particularly on an HT system.  On an HT CPU the OS (or at least apps\n   running under the OS) think that there are two independent CPUs present,\n   but it's really just one CPU with partitioning of pipeline slots.  So\n   when one thread yields, the only effect is that all of its pipeline slots\n   get marked as available.  Since the other thread can't utilise those\n   slots, the first thread immediately reclaims them and continues to run.\n   In addition thread scheduling varies across OS versions, the WinXP\n   scheduler was changed to preferentially schedule threads on idle physical\n   processors rather than an idle logical processor on a physical processor\n   whose other logical processor is (potentially) busy.\n\n   There isn't really any easy way to fix this since it'd require a sleep \n   that works across all CPUs, however one solution is to make the thread \n   sleep for a nonzero time limit iff it's running on a multi-CPU system.  \n   There's a second problem though, which relates to thread priorities.  If \n   we're at a higher priority than the other thread then we can call \n   Sleep( 0 ) as much as we like, but the scheduler will never allow the \n   other thread to run since we're a higher-priority runnable thread.  As a \n   result, as soon as we release our timeslice the scheduler will restart us \n   again (the Windows scheduler implements a starvation-prevention mechanism \n   via the balance set manager, but this varies across scheduler versions \n   and isn't something that we want to rely on).  In theory we could do:\n\n\t\tx = GetThreadPriority( GetCurrentThread() );\n\t\tSetThreadPriority( GetCurrentThread(), x - 5 );\n\t\tSleep( 0 );\t\t// Needed to effect priority change\n\t\t<wait loop>\n\t\tSetThreadPriority( GetCurrentThread(), x );\n\t\tSleep( 0 );\n\n   however this is somewhat problematic if the caller is also messing with \n   priorities at the same time.  In fact it can get downright nasty because \n   the balance set manager will, if a thread has been starved for ~3-4 \n   seconds, give it its own priority boost to priority 15 (time-critical) to \n   ensure that it'll be scheduled, with the priority slowly decaying back to \n   the normal level each time that it's scheduled.  In addition it'll have \n   its scheduling quantum boosted to 2x the normal duration for a client OS \n   or 4x the normal duration for a server OS.\n\n   To solve this, we always force our thread to go to sleep (to allow a \n   potentially lower-priority thread to leap in and get some work done) even \n   on a single-processor system, but use a slightly longer wait on an \n   HT/multi-processor system.\n\n   (Actually this simplified view isn't quite accurate since on a HT system \n   the scheduler executes the top *two* threads on the two logical \n   processors and on a dual-CPU system they're executed on a physical \n   processor.  In addition on a HT system a lower-priority thread on one \n   logical processor can compete with a higher-priority thread on the other\n   logical processor since the hardware isn't aware of thread priorities) */\n\nvoid threadYield( void )\n\t{\n\tstatic int sleepTime = -1;\n\n\t/* If the sleep time hasn't been determined yet, get it now */\n\tif( sleepTime < 0 )\n\t\t{\n\t\tSYSTEM_INFO systemInfo;\n\n\t\tGetSystemInfo( &systemInfo );\n\t\tsleepTime = ( systemInfo.dwNumberOfProcessors > 1 ) ? 10 : 1;\n\t\t}\n\n\t/* Yield the CPU for this thread */\n\tSleep( sleepTime );\n\t}\n\n#ifndef NDEBUG\n\n/* For performance evaluation purposes we provide the following function,\n   which returns ticks of the 3.579545 MHz hardware timer (see the long\n   comment in rndwin32.c for more details on Win32 timing issues) */\n\nCHECK_RETVAL_RANGE( 0, INT_MAX ) \\\nlong getTickCount( long startTime )\n\t{\n\tlong timeLSB, timeDifference;\n\n#ifndef __BORLANDC__\n\tLARGE_INTEGER performanceCount;\n\n\t/* Sensitive to context switches */\n\tQueryPerformanceCounter( &performanceCount );\n\ttimeLSB = performanceCount.LowPart;\n#else\n\tFILETIME dummyTime, kernelTime, userTime;\n\n\t/* Only accurate to 10ms, returns constant values in VC++ debugger */\n\tGetThreadTimes( GetCurrentThread(), &dummyTime, &dummyTime,\n\t\t\t\t\t&kernelTime, &userTime );\n\ttimeLSB = userTime.dwLowDateTime;\n#endif /* BC++ vs. everything else */\n\n\t/* If we're getting an initial time, return an absolute value */\n\tif( startTime <= 0 )\n\t\treturn( timeLSB );\n\n\t/* We're getting a time difference */\n\tif( startTime < timeLSB )\n\t\ttimeDifference = timeLSB - startTime;\n\telse\n\t\t{\n\t\t/* Windows rolls over at INT_MAX */\n\t\ttimeDifference = ( 0xFFFFFFFFUL - startTime ) + 1 + timeLSB;\n\t\t}\n\tif( timeDifference <= 0 )\n\t\t{\n\t\tprintf( \"Error: Time difference = %lX, startTime = %lX, \"\n\t\t\t\t\"endTime = %lX.\\n\", timeDifference, startTime, timeLSB );\n\t\treturn( 1 );\n\t\t}\n\treturn( timeDifference );\n\t}\n#endif /* Debug version */\n\n/* Borland C++ before 5.50 doesn't have snprintf() so we fake it using\n   sprintf().  Unfortunately these are all va_args functions so we can't \n   just map them using macros but have to provide an explicit wrapper to get \n   rid of the size argument */\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0550 )\n\nint bcSnprintf( char *buffer, const int bufSize, const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tva_start( argPtr, format );\n\tlength = vsprintf( buffer, format, argPtr );\n\tva_end( argPtr );\n\n\treturn( length );\n\t}\n\nint bcVsnprintf( char *buffer, const int bufSize, const char *format, va_list argPtr )\n\t{\n\treturn( vsprintf( buffer, format, argPtr ) );\n\t}\n#endif /* BC++ before 5.50 */\n\n/* Safely load a DLL.  This gets quite complicated because different \n   versions of Windows have changed how they search for DLLs to load, and \n   the behaviour of a specific version of Windows can be changed based on\n   registry keys and SetDllDirectory().  Traditionally Windows searched\n   the app directory, the current directory, the system directory, the\n   Windows directory, and the directories in $PATH.  Windows XP SP2 added\n   the SafeDllSearchMode registry key, which changes the search order so\n   the current directory is searched towards the end rather than towards\n   the start, however it's (apparently) only set on new installs, on a\n   pre-SP2 install that's been upgraded it's not set.  Windows Vista and\n   newer enabled this safe behaviour by default, but even there \n   SetDefaultDllDirectories() can be used to explicitly re-enable unsafe\n   behaviour, and AddDllDirectory() can be used to add a path to the set of \n   DLL search paths and SetDllDirectory() can be used to add a new directory \n   to the start of the search order.\n\n   None of these options are terribly useful if we want a DLL to either\n   be loaded from the system directory or not at all.  To handle this we\n   build an absolute load path and prepend it to the name of the DLL\n   being loaded */\n\n#if 0\t/* Older code using SHGetFolderPath() */\n\n/* The documented behaviour for the handling of the system directory under \n   Win64 seems to be more or less random:\n\n\thttp://msdn.microsoft.com/en-us/library/bb762584%28VS.85%29.aspx: \n\t\tCSIDL_SYSTEM = %windir%/System32, CSIDL_SYSTEMX86 = %windir%/System32.\n\thttp://social.technet.microsoft.com/Forums/en/appvgeneralsequencing/thread/c58f7d64-6a23-46f0-998f-0a964c1eff2a:\n\t\tCSIDL_SYSTEM = %windir%/Syswow64.\n\thttp://msdn.microsoft.com/en-us/library/windows/desktop/ms538044%28v=vs.85%29.aspx:\n\t\tCSIDL_SYSTEM = %windir%/System32, CSIDL_SYSTEMX86 = %windir%/Syswow64.\n\thttp://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/f9a54564-1006-42f9-b4d1-b225f370c60c:\n\t\tGetSystemDirectory() = %windir%/Syswow64.\n\thttp://msdn.microsoft.com/en-us/library/windows/desktop/dd378457%28v=vs.85%29.aspx:\n\t\tCSIDL_SYSTEM = %windir%/System32, \n\t\tCSIDL_SYSTEMX86 = %windir%/System32 for Win32, %windir%/Syswow64 for Win64.\n\n   The current use of CSIDL_SYSTEM to get whatever-the-system-directory-is-\n   meant-to-be seems to work, so we'll leave it as is */\n\n#ifndef CSIDL_SYSTEM\n  #define CSIDL_SYSTEM\t\t0x25\t/* 'Windows/System32' */\n#endif /* !CSIDL_SYSTEM */\n#ifndef SHGFP_TYPE_CURRENT\n  #define SHGFP_TYPE_CURRENT\t0\n#endif /* !SHGFP_TYPE_CURRENT */\n\nstatic HMODULE WINAPI loadExistingLibrary( IN_STRING LPCTSTR lpFileName )\n\t{\n\tHANDLE hFile;\n\n\tassert( isReadPtr( lpFileName, 2 ) );\n\n\tANALYSER_HINT_STRING( lpFileName );\n\n\t/* Determine whether the DLL is present and accessible */\n\thFile = CreateFile( lpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,\n\t\t\t\t\t\tFILE_ATTRIBUTE_NORMAL, NULL );\n\tif( hFile == INVALID_HANDLE_VALUE )\n\t\treturn( NULL );\n\tCloseHandle( hFile );\n\n\treturn( LoadLibrary( lpFileName ) );\n\t}\n\nstatic HMODULE WINAPI loadFromSystemDirectory( IN_BUFFER( fileNameLength ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst char *fileName,\n\t\t\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 1 ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst int fileNameLength )\n\t{\n\tchar path[ MAX_PATH + 8 ];\n\tint pathLength;\n\n\tENSURES_N( fileNameLength >= 1 && fileNameLength + 8 < MAX_PATH );\n\n\tassert( isReadPtrDynamic( fileName, fileNameLength ) );\n\n\t/* Get the path to a DLL in the system directory */\n\tpathLength = \\\n\t\tGetSystemDirectory( path, MAX_PATH - ( fileNameLength + 8 ) );\n\tif( pathLength < 3 || pathLength + fileNameLength > MAX_PATH - 8 )\n\t\treturn( NULL );\n\tpath[ pathLength++ ] = '\\\\';\n\tREQUIRES_N( boundsCheck( pathLength, fileNameLength, MAX_PATH ) );\n\tmemcpy( path + pathLength, fileName, fileNameLength );\n\tpath[ pathLength + fileNameLength ] = '\\0';\n\n\treturn( loadExistingLibrary( path ) );\n\t}\n\nHMODULE WINAPI SafeLoadLibrary( IN_STRING LPCTSTR lpFileName )\n\t{\n\ttypedef HRESULT ( WINAPI *SHGETFOLDERPATH )( HWND hwndOwner,\n\t\t\t\t\t\t\t\t\t\tint nFolder, HANDLE hToken,\n\t\t\t\t\t\t\t\t\t\tDWORD dwFlags, LPTSTR lpszPath );\n\ttypedef struct {\n\t\tconst char *dllName; const int dllNameLen; \n\t\t} DLL_NAME_INFO;\n\tstatic const DLL_NAME_INFO dllNameInfoTbl[] = {\n\t\t{ \"Crypt32.dll\", 11 }, { \"ComCtl32.dll\", 12 },\n\t\t{ \"dnsapi.dll\", 10 }, { \"Mpr.dll\", 7 },\n\t\t{ \"NetAPI32.dll\", 12 }, { \"ODBC32.dll\", 10 },\n\t\t{ \"SetupAPI.dll\", 12 }, { \"SHFolder.dll\", 12 },\n\t\t{ \"Shell32.dll\", 11 }, { \"WinHTTP.dll\", 11 },\n\t\t{ \"wldap32.dll\", 11 }, { \"ws2_32.dll\", 10 },\n\t\t{ \"wsock32.dll\", 11 }, \n\t\t{ NULL, 0 }, { NULL, 0 }\n\t\t};\n\tSHGETFOLDERPATH pSHGetFolderPath;\n\tHINSTANCE hShell32;\n\tchar path[ MAX_PATH + 8 ];\n\tconst int fileNameLength = strlen( lpFileName );\n\tint pathLength, i, LOOP_ITERATOR;\n\tBOOLEAN gotPath = FALSE;\n\n\tANALYSER_HINT_STRING( lpFileName );\n\n\tREQUIRES_EXT( fileNameLength >= 1 && fileNameLength < MAX_PATH, \\\n\t\t\t\t  NULL );\n\n\tassert( isReadPtr( lpFileName, 2 ) );\n\n\t/* If it's Win98 or NT4, just call LoadLibrary directly.  In theory\n\t   we could try a few further workarounds (see io/file.c) but in \n\t   practice bending over backwards to fix search path issues under\n\t   Win98, which doesn't have ACLs to protect the files in the system\n\t   directory anyway, isn't going to achieve much, and in any case both\n\t   of these OSes should be long dead by now */\n\tif( getSysVar( SYSVAR_OSMAJOR ) <= 4 )\n\t\treturn( LoadLibrary( lpFileName ) );\n\n\t/* If it's already an absolute path, don't try and override it */\n\tif( lpFileName[ 0 ] == '/' || \\\n\t\t( fileNameLength >= 3 && isAlpha( lpFileName[ 0 ] ) && \\\n\t\t  lpFileName[ 1 ] == ':' && lpFileName[ 2 ] == '/' ) )\n\t\t{\n\t\treturn( loadExistingLibrary( lpFileName ) );\n\t\t}\n\n\t/* If it's a well-known DLL, load it from the system directory */\n\tLOOP_MED( i = 0, \n\t\t\t  dllNameInfoTbl[ i ].dllName != NULL && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( dllNameInfoTbl, DLL_NAME_INFO ),\n\t\t\t  i++ )\n\t\t{\n\t\tif( dllNameInfoTbl[ i ].dllNameLen == fileNameLength && \\\n\t\t\t!strCompare( dllNameInfoTbl[ i ].dllName, lpFileName, \n\t\t\t\t\t\t fileNameLength ) )\n\t\t\t{\n\t\t\t/* It's a standard system DLL, load it from the system \n\t\t\t   directory */\n\t\t\treturn( loadFromSystemDirectory( lpFileName, fileNameLength ) );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( dllNameInfoTbl, DLL_NAME_INFO ) );\n\n\t/* It's a system new enough to support SHGetFolderPath(), get the path\n\t   to the system directory.  Unfortunately at this point we're in a \n\t   catch-22, in order to resolve SHGetFolderPath() we need to call\n\t   Shell32.dll and if an attacker uses that as the injection point then\n\t   they can give us a SHGetFolderPath() that'll do whatever they want.  \n\t   There's no real way to fix this because we have to load Shell32 at\n\t   some point, either explicitly here or on program load, and since we\n\t   can't control the load path at either point we can't control what's\n\t   actually being loaded.  In addition DLLs typically recursively load\n\t   more DLLs so even if we can control the path of the DLL that we load \n\t   directly we can't influence the paths over which further DLLs get \n\t   loaded.  So unfortunately the best that we can do is make the \n\t   attacker work a little harder rather than providing a full fix */\n\thShell32 = loadFromSystemDirectory( \"Shell32.dll\", 11 );\n\tif( hShell32 != NULL )\n\t\t{\n\t\tpSHGetFolderPath = ( SHGETFOLDERPATH ) \\\n\t\t\t\t\t\t   GetProcAddress( hShell32, \"SHGetFolderPathA\" );\n\t\tif( pSHGetFolderPath != NULL && \\\n\t\t\tpSHGetFolderPath( NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, \n\t\t\t\t\t\t\t  path ) == S_OK )\n\t\t\tgotPath = TRUE;\n\t\tFreeLibrary( hShell32 );\n\t\t}\n\tif( !gotPath )\n\t\t{\n\t\t/* If for some reason we couldn't get the path to the Windows system\n\t\t   directory this means that there's something drastically wrong,\n\t\t   don't try and go any further */\n\t\treturn( NULL );\n\t\t}\n\tpathLength = strlen( path );\n\tif( pathLength < 3 || pathLength + fileNameLength > MAX_PATH - 8 )\n\t\t{\n\t\t/* Under WinNT and Win2K the LocalSystem account doesn't have its \n\t\t   own profile so SHGetFolderPath() will report success but return a \n\t\t   zero-length path if we're running as a service.  To detect this \n\t\t   we have to check for a valid-looking path as well as performing a \n\t\t   general check on the return status.\n\t\t   \n\t\t   In effect prepending a zero-length path to the DLL name just \n\t\t   turns the call into a standard LoadLibrary() call, but we make \n\t\t   the action explicit here.  Unfortunately this reintroduces the\n\t\t   security hole that we were trying to fix, and what's worse it's\n\t\t   for the LocalSystem account (sigh). */\n\t\treturn( LoadLibrary( lpFileName ) );\n\t\t}\n\tpath[ pathLength++ ] = '\\\\';\n\tREQUIRES_N( boundsCheck( pathLength, fileNameLength, MAX_PATH ) );\n\tmemcpy( path + pathLength, lpFileName, fileNameLength );\n\tpath[ pathLength + fileNameLength ] = '\\0';\n\n\treturn( loadExistingLibrary( path ) );\n\t}\n#else\t/* Newer code that does the same thing */\n\n#if VC_GE_2005( _MSC_VER )\n  #pragma warning( push )\n  #pragma warning( disable : 4255 )\t/* Errors in VersionHelpers.h */\n  #include <VersionHelpers.h>\n  #pragma warning( pop )\n#endif /* VC++ >= 2005 */\n\nHMODULE WINAPI SafeLoadLibrary( IN_STRING LPCTSTR lpFileName )\n\t{\n\tchar path[ MAX_PATH + 8 ];\n\tconst int fileNameLength = strlen( lpFileName );\n\tint pathLength;\n\n\tREQUIRES_EXT( fileNameLength >= 1 && fileNameLength < MAX_PATH, \\\n\t\t\t\t  NULL );\n\n\tassert( isReadPtr( lpFileName, 2 ) );\n\n\tANALYSER_HINT_STRING( lpFileName );\n\n\t/* If it's Win98 or NT4, just call LoadLibrary directly.  In theory\n\t   we could try a few further workarounds (see io/file.c) but in \n\t   practice bending over backwards to fix search path issues under\n\t   Win98, which doesn't have ACLs to protect the files in the system\n\t   directory anyway, isn't going to achieve much, and in any case both\n\t   of these OSes should be long dead by now */\n#if VC_LT_2010( _MSC_VER )\n\tif( getSysVar( SYSVAR_OSMAJOR ) <= 4 )\n\t\treturn( LoadLibrary( lpFileName ) );\n#else\n\tif( !IsWindowsXPOrGreater() )\n\t\treturn( LoadLibrary( lpFileName ) );\n#endif /* VC++ < 2010 */\n\n\t/* If it's already an absolute path, don't try and override it */\n\tif( lpFileName[ 0 ] == '/' || \\\n\t\tlpFileName[ 0 ] == '\\\\' || \\\n\t\t( fileNameLength >= 3 && isAlpha( lpFileName[ 0 ] ) && \\\n\t\t  lpFileName[ 1 ] == ':' && \\\n\t\t  ( lpFileName[ 2 ] == '/' || lpFileName[ 2 ] == '\\\\' ) ) )\n\t\t{\n\t\treturn( LoadLibrary( lpFileName ) );\n\t\t}\n\n\t/* Load the DLL from the system directory */\n\tpathLength = \\\n\t\tGetSystemDirectory( path, MAX_PATH - ( fileNameLength + 8 ) );\n\tif( pathLength < 3 || pathLength + fileNameLength > MAX_PATH - 8 )\n\t\treturn( NULL );\n\tpath[ pathLength++ ] = '\\\\';\n\tREQUIRES_N( boundsCheck( pathLength, fileNameLength, MAX_PATH ) );\n\tmemcpy( path + pathLength, lpFileName, fileNameLength );\n\tpath[ pathLength + fileNameLength ] = '\\0';\n\n\treturn( LoadLibrary( path ) );\n\t}\n#endif /* Old/New SafeLoadLibrary() */\n\n/* Windows NT-derived systems support ACL-based access control mechanisms \n   for system objects so when we create objects such as files and threads \n   we give them an ACL that allows only the creator access.  The following \n   functions return the security info needed when creating objects.  The \n   interface for this has changed in every major OS release, although it \n   never got any better, just differently ugly.  The following code uses the \n   original NT 3.1 interface, which works for all OS versions */\n\n/* The size of the buffer for ACLs and the user token */\n\n#define ACL_BUFFER_SIZE\t\t1024\n#define TOKEN_BUFFER_SIZE\t256\n\n/* A composite structure to contain the various ACL structures.  This is\n   required because ACL handling is a complex, multistage operation that\n   requires first creating an ACL and security descriptor to contain it,\n   adding an access control entry (ACE) to the ACL, adding the ACL as the\n   DACL of the security descriptor, and finally, wrapping the security\n   descriptor up in a security attributes structure that can be passed to\n   an object-creation function.\n\n   The handling of the TOKEN_INFO is extraordinarily ugly because although\n   the TOKEN_USER struct as defined is only 8 bytes long, Windoze allocates\n   an extra 24 bytes after the end of the struct into which it stuffs data\n   that the SID pointer in the TOKEN_USER struct points to.  This means that\n   we can't statically allocate memory of the size of the TOKEN_USER struct\n   but have to make it a pointer into a larger buffer that can contain the\n   additional invisible data tacked onto the end */\n\ntypedef struct {\n\tSECURITY_ATTRIBUTES sa;\n\tSECURITY_DESCRIPTOR pSecurityDescriptor;\n\tPACL pAcl;\n\tPTOKEN_USER pTokenUser;\n\tBYTE aclBuffer[ ACL_BUFFER_SIZE + 8 ];\n\tBYTE tokenBuffer[ TOKEN_BUFFER_SIZE + 8 ];\n\t} SECURITY_INFO;\n\n/* Initialise an ACL allowing only the creator access and return it to the\n   caller as an opaque value */\n\nCHECK_RETVAL_PTR \\\nvoid *initACLInfo( const int access )\n\t{\n\tSECURITY_INFO *securityInfo;\n\tHANDLE hToken = INVALID_HANDLE_VALUE;\t/* See comment below */\n\tBOOLEAN tokenOK = FALSE;\n\n\tREQUIRES_N( access > 0 );\n\n\t/* Allocate and initialise the composite security info structure */\n\tif( ( securityInfo = \\\n\t\t\t\tclAlloc( \"initACLInfo\", sizeof( SECURITY_INFO ) ) ) == NULL )\n\t\treturn( NULL );\n\tmemset( securityInfo, 0, sizeof( SECURITY_INFO ) );\n\tsecurityInfo->pAcl = ( PACL ) securityInfo->aclBuffer;\n\tsecurityInfo->pTokenUser = ( PTOKEN_USER ) securityInfo->tokenBuffer;\n\n\t/* Get the security token for this thread.  First we try for the thread\n\t   token (which it typically only has when impersonating), if we don't\n\t   get that we use the token associated with the process.  We also\n\t   initialise the hToken (above) even though it shouldn't be necessary\n\t   because Windows tries to read its contents, which indicates there\n\t   might be problems if it happens to start out with the wrong value */\n\tif( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken ) || \\\n\t\tOpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )\n\t\t{\n\t\tDWORD cbTokenUser;\n\n\t\ttokenOK = GetTokenInformation( hToken, TokenUser,\n\t\t\t\t\t\t\t\t\t   securityInfo->pTokenUser,\n\t\t\t\t\t\t\t\t\t   TOKEN_BUFFER_SIZE, &cbTokenUser );\n\t\tCloseHandle( hToken );\n\t\t}\n\tif( !tokenOK )\n\t\t{\n\t\tclFree( \"initACLInfo\", securityInfo );\n\t\treturn( NULL );\n\t\t}\n\n\t/* Set a security descriptor owned by the current user */\n\tif( !InitializeSecurityDescriptor( &securityInfo->pSecurityDescriptor,\n\t\t\t\t\t\t\t\t\t   SECURITY_DESCRIPTOR_REVISION ) || \\\n\t\t!SetSecurityDescriptorOwner( &securityInfo->pSecurityDescriptor,\n\t\t\t\t\t\t\t\t\t securityInfo->pTokenUser->User.Sid,\n\t\t\t\t\t\t\t\t\t FALSE ) )\n\t\t{\n\t\tclFree( \"initACLInfo\", securityInfo );\n\t\treturn( NULL );\n\t\t}\n\n\t/* Set up the discretionary access control list (DACL) with one access\n\t   control entry (ACE) for the current user */\n\tif( !InitializeAcl( securityInfo->pAcl, ACL_BUFFER_SIZE,\n\t\t\t\t\t\tACL_REVISION ) || \\\n\t\t!AddAccessAllowedAce( securityInfo->pAcl, ACL_REVISION, access,\n\t\t\t\t\t\t\t  securityInfo->pTokenUser->User.Sid ) )\n\t\t{\n\t\tclFree( \"initACLInfo\", securityInfo );\n\t\treturn( NULL );\n\t\t}\n\n\t/* Bind the DACL to the security descriptor */\n\tif( !SetSecurityDescriptorDacl( &securityInfo->pSecurityDescriptor, TRUE,\n\t\t\t\t\t\t\t\t\tsecurityInfo->pAcl, FALSE ) )\n\t\t{\n\t\tclFree( \"initACLInfo\", securityInfo );\n\t\treturn( NULL );\n\t\t}\n\n\tassert( IsValidSecurityDescriptor( &securityInfo->pSecurityDescriptor ) );\n\n\t/* Finally, set up the security attributes structure */\n\tsecurityInfo->sa.nLength = sizeof( SECURITY_ATTRIBUTES );\n\tsecurityInfo->sa.bInheritHandle = FALSE;\n\tsecurityInfo->sa.lpSecurityDescriptor = &securityInfo->pSecurityDescriptor;\n\n\treturn( securityInfo );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid freeACLInfo( IN TYPECAST( SECURITY_INFO * ) void *securityInfoPtr )\n\t{\n\tSECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;\n\n\tassert( securityInfoPtr == NULL || \\\n\t\t\tisWritePtr( securityInfoPtr, sizeof( SECURITY_INFO ) ) );\n\n\tif( securityInfo == NULL )\n\t\treturn;\n\tclFree( \"freeACLInfo\", securityInfo );\n\t}\n\n/* Extract the security info needed in Win32 API calls from the collection of\n   security data that we set up earlier */\n\nvoid *getACLInfo( INOUT_OPT TYPECAST( SECURITY_INFO * ) void *securityInfoPtr )\n\t{\n\tSECURITY_INFO *securityInfo = ( SECURITY_INFO * ) securityInfoPtr;\n\n\tassert( securityInfo == NULL || \\\n\t\t\tisWritePtr( securityInfo, sizeof( SECURITY_INFO ) ) );\n\n\treturn( ( securityInfo == NULL ) ? NULL : &securityInfo->sa );\n\t}\n\n/* The DLL entry point.  In theory we could also call:\n \n\tHeapSetInformation( GetProcessHeap(), \n\t\t\t\t\t\tHeapEnableTerminationOnCorruption, NULL, 0 ); \n\n   but this would have to be dynamically linked since it's only available \n   for Vista and newer OSes, and it could also cause problems when cryptlib \n   is linked with buggy applications that rely on the resilience of the heap \n   manager in order to function since running the app with cryptlib will \n   cause it to crash through no fault of cryptlib's.  Since cryptlib is \n   checked with Bounds Checker, Purify, and Valgrind, which are far more \n   rigorous than the checking performed by the heap manager, there doesn't \n   seem to be much advantage in doing this, but significant disadvantages \n   if users' application bugs are caught by it */\n\n#if !( defined( NT_DRIVER ) || defined( STATIC_LIB ) )\n\nBOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )\n\t{\n\tUNUSED_ARG( hinstDLL );\n\tUNUSED_ARG( lpvReserved );\n\n\tswitch( fdwReason )\n\t\t{\n\t\tcase DLL_PROCESS_ATTACH:\n\t\t\t/* Disable thread-attach notifications, which we don't do\n\t\t\t   anything with and therefore don't need */\n\t\t\tDisableThreadLibraryCalls( hinstDLL );\n\n\t\t\t/* Set up the initialisation lock in the kernel */\n\t\t\tpreInit();\n\t\t\tbreak;\n\n\t\tcase DLL_PROCESS_DETACH:\n\t\t\t/* Delete the initialisation lock in the kernel */\n\t\t\tpostShutdown();\n\t\t\tbreak;\n\n\t\tcase DLL_THREAD_ATTACH:\n\t\tcase DLL_THREAD_DETACH:\n\t\t\tbreak;\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Idiot-proofing.  Yes, there really are people who'll try and register a\n   straight DLL */\n\n#ifndef MB_OK\n  #define MB_OK\t\t\t\t\t0x00000000L\n  #define MB_ICONQUESTION\t\t0x00000020L\n  #define MB_ICONEXCLAMATION\t0x00000030L\n#endif /* MB_OK */\n\nint WINAPI MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption,\n\t\t\t\t\t\tUINT uType );\n\n#ifndef _WIN64\n  #pragma comment( linker, \"/export:DllRegisterServer=_DllRegisterServer@0,PRIVATE\" )\n#endif /* Win64 */\n#if defined( __MINGW32__ ) && !defined( STDAPI )\n  #define STDAPI\tHRESULT __stdcall\n#endif /* MinGW without STDAPI defined */\n\nSTDAPI DllRegisterServer( void )\n\t{\n\tMessageBoxA( NULL, \"Why are you trying to register the cryptlib DLL?\\n\"\n\t\t\t\t \"It's just a standard Windows DLL, there's nothing\\nto be \"\n\t\t\t\t \"registered.\", \"ESO Error\",\n\t\t\t\t MB_ICONQUESTION | MB_OK );\n\treturn( E_NOINTERFACE );\n\t}\n#endif /* !( NT_DRIVER || STATIC_LIB ) */\n\n#if VC_LE_VC6( _MSC_VER )\n\n/* Under VC++ 6 assert() can randomly stop working so that only the abort() \n   portion still functions, making it impossible to find out what went wrong.\n   To deal with this, os_spec.h redefines the assert() macro to call the \n   following function, which emulates what a correctly-functioning assert()\n   would do */\n\n#ifndef MB_OKCANCEL\n  #define MB_OKCANCEL\t\t\t0x00000001L\n#endif /* MB_OKCANCEL */\n#ifndef MB_YESNOCANCEL\n  #define MB_YESNOCANCEL\t\t0x00000003L\n#endif /* MB_YESNOCANCEL */\n#ifndef MB_ICONEXCLAMATION\n  #define MB_ICONEXCLAMATION\t0x00000030L\n#endif /* MB_ICONEXCLAMATION */\n\nvoid vc6assert( const char *exprString, const char *fileName, \n\t\t\t\tconst int lineNo )\n\t{\n\tconst char *cleanFileName;\n\tchar string[ 1024 ], title[ 1024 ];\n\tint result;\n\n\t/* Clean up the pathname */\n\tcleanFileName = strstr( fileName, \"cryptlib\" );\n\tif( cleanFileName != NULL )\n\t\tcleanFileName += 9;\t/* Skip \"cryptlib/\" */\n\telse\n\t\t{\n\t\tint i, slashCount = 0, LOOP_ITERATOR;\n\n\t\t/* We may be running off some nonstandard path, get as close as we\n\t\t   can to the minimal path */\n\t\tLOOP_LARGE( i = strlen( fileName ), i > 0, i-- )\n\t\t\t{\n\t\t\tif( fileName[ i ] == '\\\\' )\n\t\t\t\t{\n\t\t\t\tslashCount++;\n\t\t\t\tif( slashCount >= 2 )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK );\n\t\tcleanFileName = fileName + i;\n\t\t}\n\n\t/* Log the output to the debug console */\n\tsprintf( string, \"%s:%d:'%s'.\\n\", fileName, lineNo, exprString );\n\tOutputDebugString( string );\n\n\t/* Emulate the standard assert() functionality.  Note that the spurious \n\t   spaces in the last line of the message are to ensure that the title\n\t   text doesn't get truncated, since the message box width is determined \n\t   by the text in the dialog rather than the title length */\n\tsprintf( string, \"File %s, line %d:\\n\\n  '%s'.\\n\\n\"\n\t\t\t\"Yes to debug, no to continue, cancel to exit.                  \", \n\t\t\tcleanFileName, lineNo, exprString );\n\tsprintf( title, \"Assertion failed, file %s, line %d\", cleanFileName, \n\t\t\t lineNo );\n\tresult = MessageBoxA( NULL, string, title, \n\t\t\t\t\t\t  MB_ICONEXCLAMATION | MB_YESNOCANCEL );\n\tif( result == IDCANCEL )\n\t\tabort();\n\tif( result == IDYES )\n\t\tDebugBreak();\n\t}\n#endif /* VC++ 6.0 */\n\n/* Borland's archaic compilers don't recognise DllMain() but still use the\n   OS/2-era DllEntryPoint(), so we have to alias it to DllMain() in order\n   for things to be initialised properly */\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n\nBOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, DWORD fdwReason, \n\t\t\t\t\t\t   LPVOID lpvReserved )\n\t{\n\treturn( DllMain( hinstDLL, fdwReason, lpvReserved ) );\n\t}\n#endif /* BC++ */\n\n#elif defined( __WIN16__ )\n\n/* WinMain() and WEP() under Win16 are intended for DLL initialisation,\n   however it isn't possible to reliably do anything terribly useful in these\n   routines.  The reason for this is that the WinMain/WEP functions are\n   called by the windows module loader, which has a very limited workspace\n   and can cause peculiar behaviour for some functions (allocating/freeing\n   memory and loading other modules from these routines is unreliable), the\n   order in which WinMain() and WEP() will be called for a set of DLL's is\n   unpredictable (sometimes WEP doesn't seem to be called at all), and they\n   can't be tracked by a standard debugger.  This is why MS have\n   xxxRegisterxxx() and xxxUnregisterxxx() functions in their DLL's.\n\n   Under Win16 on a Win32 system this isn't a problem because the module\n   loader has been rewritten to work properly, but it isn't possible to get\n   reliable performance under pure Win16, so the DLL entry/exit routines here\n   do almost nothing, with the real work being done in cryptInit()/\n   cryptEnd() */\n\nHWND hInst;\n\nint CALLBACK LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, \n\t\t\t\t\t  LPSTR lpszCmdLine )\n\t{\n\t/* Remember the proc instance for later */\n\thInst = hInstance;\n\n\treturn( TRUE );\n\t}\n\nint CALLBACK WEP( int nSystemExit )\n\t{\n\tswitch( nSystemExit )\n\t\t{\n\t\tcase WEP_SYSTEM_EXIT:\n\t\t\t/* System is shutting down */\n\t\t\tbreak;\n\n\t\tcase WEP_FREE_DLL:\n\t\t\t/* DLL reference count = 0, DLL-only shutdown */\n\t\t\tbreak;\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check whether we're running inside a VM, which is a potential risk for\n   cryptovariables.  It gets quite tricky to detect the various VMs so for\n   now the only one that we detect is the most widespread one, VMware */\n\n#if defined( __WIN32__ ) && !defined( NO_ASM )\n\nBOOLEAN isRunningInVM( void )\n\t{\n\tunsigned int magicValue, version;\n\n\t__try {\n\t__asm {\n\t\tpush eax\n\t\tpush ebx\n\t\tpush ecx\n\t\tpush edx\n\n\t\t/* Check for VMware via the VMware guest-to-host communications \n\t\t   channel */\n\t\tmov eax, 'VMXh'\t\t/* VMware magic value 0x564D5868 */\n\t\txor ebx, ebx\t\t/* Clear parameters register */\n\t\tmov ecx, 0Ah\t\t/* Get-version command */\n\t\tmov dx, 'VX'\t\t/* VMware I/O port 0x5658 */\n\t\tin eax, dx\t\t\t/* Perform VMware call */\n\t\tmov magicValue, ebx\t/* VMware magic value */\n\t\tmov version, ecx\t/* VMware version */\n\n\t\tpop edx\n\t\tpop ecx\n\t\tpop ebx\n\t\tpop eax\n\t\t}\n\t} __except (EXCEPTION_EXECUTE_HANDLER) {}\n\n\treturn( magicValue == 'VMXh' ) ? TRUE : FALSE );\n\t}\n#else\n\nBOOLEAN isRunningInVM( void )\n\t{\n\treturn( FALSE );\n\t}\n#endif /* __WIN32__ && !NO_ASM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tWindows CE\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __WINCE__ )\n\n/* Windows CE doesn't provide ANSI standard time functions (although it'd be\n   relatively easy to do so, and they are in fact provided in MFC), so we\n   have to provide our own */\n\nCHECK_RETVAL \\\nstatic LARGE_INTEGER *getTimeOffset( void )\n\t{\n\tstatic LARGE_INTEGER timeOffset = { 0 };\n\n\t/* Get the difference between the ANSI/ISO C time epoch and the Windows\n\t   time epoch if we haven't already done so (we could also hardcode this\n\t   in as 116444736000000000LL) */\n\tif( timeOffset.QuadPart == 0 )\n\t\t{\n\t\tSYSTEMTIME ofsSystemTime;\n\t\tFILETIME ofsFileTime;\n\n\t\tmemset( &ofsSystemTime, 0, sizeof( SYSTEMTIME ) );\n\t\tofsSystemTime.wYear = 1970;\n\t\tofsSystemTime.wMonth = 1;\n\t\tofsSystemTime.wDay = 1;\n\t\tSystemTimeToFileTime( &ofsSystemTime, &ofsFileTime );\n\t\ttimeOffset.HighPart = ofsFileTime.dwHighDateTime;\n\t\ttimeOffset.LowPart = ofsFileTime.dwLowDateTime;\n\t\t}\n\n\treturn( &timeOffset );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic time_t fileTimeToTimeT( const FILETIME *fileTime )\n\t{\n\tconst LARGE_INTEGER *timeOffset = getTimeOffset();\n\tLARGE_INTEGER largeInteger;\n\n\t/* Convert a Windows FILETIME to a time_t by dividing by\n\t   10,000,000 (to go from 100ns ticks to 1s ticks) */\n\tlargeInteger.HighPart = fileTime->dwHighDateTime;\n\tlargeInteger.LowPart = fileTime->dwLowDateTime;\n\tlargeInteger.QuadPart = ( largeInteger.QuadPart - \\\n\t\t\t\t\t\t\t  timeOffset->QuadPart ) / 10000000L;\n\tif( sizeof( time_t ) == 4 && \\\n\t\tlargeInteger.QuadPart > 0x80000000UL )\n\t\t{\n\t\t/* time_t is 32 bits but the converted time is larger than a 32-bit\n\t\t   signed value, indicate that we couldn't convert it.  In theory\n\t\t   we could check for largeInteger.HighPart == 0 and perform a\n\t\t   second check to see if time_t is unsigned, but it's unlikely that\n\t\t   this change would be made to the VC++ runtime time_t since it'd\n\t\t   break too many existing apps */\n\t\treturn( -1 );\n\t\t}\n\treturn( ( time_t ) largeInteger.QuadPart );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void timeTToFileTime( FILETIME *fileTime, const time_t timeT )\n\t{\n\tconst LARGE_INTEGER *timeOffset = getTimeOffset();\n\tLARGE_INTEGER largeInteger = { timeT };\n\n\t/* Convert a time_t to a Windows FILETIME by multiplying by\n\t   10,000,000 (to go from 1s ticks to 100ns ticks) */\n\tlargeInteger.QuadPart = ( largeInteger.QuadPart * 10000000L ) + \\\n\t\t\t\t\t\t\ttimeOffset->QuadPart;\n\tfileTime->dwHighDateTime = largeInteger.HighPart;\n\tfileTime->dwLowDateTime = largeInteger.LowPart;\n\t}\n\ntime_t time( time_t *timePtr )\n\t{\n\tFILETIME fileTime;\n#ifdef __WINCE__\n\tSYSTEMTIME systemTime;\n#endif /* __WINCE__ */\n\n\tassert( timePtr == NULL );\n\n\t/* Get the time via GetSystemTimeAsFileTime().  Windows CE doesn't have\n\t   the unified call so we have to assemble it from discrete calls */\n#ifdef __WINCE__\n\tGetSystemTime( &systemTime );\n\tSystemTimeToFileTime( &systemTime, &fileTime );\n#else\n\tGetSystemTimeAsFileTime( &fileTime );\n#endif /* Win32 vs. WinCE */\n\n\treturn( fileTimeToTimeT( &fileTime ) );\n\t}\n\ntime_t mktime( struct tm *tmStruct )\n\t{\n\tSYSTEMTIME systemTime;\n\tFILETIME fileTime;\n\n\tassert( isWritePtr( tmStruct, sizeof( struct tm ) ) );\n\n\t/* Use SystemTimeToFileTime() as a mktime() substitute.  The input time\n\t   seems to be treated as local time, so we have to convert it to GMT\n\t   before we return it */\n\tmemset( &systemTime, 0, sizeof( SYSTEMTIME ) );\n\tsystemTime.wYear = tmStruct->tm_year + 1900;\n\tsystemTime.wMonth = tmStruct->tm_mon + 1;\n\tsystemTime.wDay = tmStruct->tm_mday;\n\tsystemTime.wHour = tmStruct->tm_hour;\n\tsystemTime.wMinute = tmStruct->tm_min;\n\tsystemTime.wSecond = tmStruct->tm_sec;\n\tSystemTimeToFileTime( &systemTime, &fileTime );\n\tLocalFileTimeToFileTime( &fileTime, &fileTime );\n\n\treturn( fileTimeToTimeT( &fileTime ) );\n\t}\n\nstruct tm *gmtime( const time_t *timePtr )\n\t{\n\tstatic struct tm tmStruct;\n\tSYSTEMTIME systemTime;\n\tFILETIME fileTime;\n\n\tassert( isReadPtr( timePtr, sizeof( time_t ) ) );\n\n\t/* Use FileTimeToSystemTime() as a gmtime() substitute.  Note that this\n\t   function, like its original ANSI/ISO C counterpart, is not thread-\n\t   safe */\n\ttimeTToFileTime( &fileTime, *timePtr );\n\tFileTimeToSystemTime( &fileTime, &systemTime );\n\tmemset( &tmStruct, 0, sizeof( struct tm ) );\n\ttmStruct.tm_year = systemTime.wYear - 1900;\n\ttmStruct.tm_mon = systemTime.wMonth - 1;\n\ttmStruct.tm_mday = systemTime.wDay;\n\ttmStruct.tm_hour = systemTime.wHour;\n\ttmStruct.tm_min = systemTime.wMinute;\n\ttmStruct.tm_sec = systemTime.wSecond;\n\n\treturn( &tmStruct );\n\t}\n\n/* When running in debug mode we provide a debugging printf() that sends its \n   output to the debug console.  This is normally done via a macro in a \n   header file that remaps the debug-output macros to the appropriate \n   function, but WinCE's NKDbgPrintfW() requires widechar strings that \n   complicate the macros so we provide a function that performs the \n   conversion before outputting the text */\n\n#if !defined( NDEBUG )\n\nint debugPrintf( const char *format, ... )\n\t{\n\tva_list argPtr;\n\tchar buffer[ 1024 ];\n\twchar_t wcBuffer[ 1024 ];\n\tint length, status;\n\n\tva_start( argPtr, format );\n\tlength = vsprintf( buffer, format, argPtr );\n\tva_end( argPtr );\n\tstatus = asciiToUnicode( wcBuffer, 1024, buffer, length );\n\tif( cryptStatusOK( status ) )\n\t\tNKDbgPrintfW( L\"%s\", wcBuffer );\n\treturn( length );\n\t}\n#endif /* Debug build */\n\n/* Windows CE systems need to convert characters from ASCII <-> Unicode\n   before/after they're read/written to external formats, the following\n   functions perform the necessary conversion.\n\n   winnls.h was already included via the global include of windows.h, however\n   it isn't needed for any other part of cryptlib so it was disabled via\n   NONLS.  Since winnls.h is now locked out, we have to un-define the guards\n   used earlier to get it included */\n\n#undef _WINNLS_\n#undef NONLS\n#include <winnls.h>\n\nint asciiToUnicode( wchar_t *dest, const int destMaxLen, \n\t\t\t\t\tconst char *src, const int length )\n\t{\n\tint status;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\n\t/* Note that this function doens't terminate the string if the output is \n\t   filled, so it's essential that the caller check the return value to \n\t   ensure that they're getting a well-formed string */\n\tstatus = MultiByteToWideChar( GetACP(), 0, src, destMaxLen, dest, \n\t\t\t\t\t\t\t\t  length );\n\treturn( status <= 0 ? CRYPT_ERROR_BADDATA : status * sizeof( wchar_t ) );\n\t}\n\nint unicodeToAscii( char *dest, const int destMaxLen, \n\t\t\t\t\tconst wchar_t *src, const int length )\n\t{\n\tsize_t destLen;\n\tint status;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\tassert( isWritePtrDynamic( dest, destMaxLen ) );\n\n\t/* Convert the string, overriding the system default char '?', which\n\t   causes problems if the output is used as a filename.  This function\n\t   has stupid semantics in that instead of returning the number of bytes\n\t   written to the output it returns the number of bytes specified as\n\t   available in the output buffer, zero-filling the rest (in addition as \n\t   for MultiByteToWideChar() it won't terminate the string if the output \n\t   is filled).  Because there's no way to tell how long the resulting \n\t   string actually is we have to use wcstombs() instead, which is \n\t   unfortunate because there's nothing that we can do with the maxLength \n\t   parameter */\n#if 0\n\tstatus = WideCharToMultiByte( GetACP(), 0, src, length, dest,\n\t\t\t\t\t\t\t\t  length * sizeof( wchar_t ), \"_\", NULL );\n\treturn( ( status <= 0 ) ? CRYPT_ERROR_BADDATA : wcslen( dest ) );\n#else\n\tstatus = wcstombs_s( &destLen, dest, destMaxLen, src, \n\t\t\t\t\t\t length * sizeof( wchar_t ) );\n\treturn( ( status <= 0 ) ? CRYPT_ERROR_BADDATA : status );\n#endif\n\t}\n\nBOOL WINAPI DllMain( HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved )\n\t{\n\tUNUSED_ARG( hinstDLL );\n\tUNUSED_ARG( lpvReserved );\n\n\tswitch( dwReason )\n\t\t{\n\t\tcase DLL_PROCESS_ATTACH:\n\t\t\t/* Disable thread-attach notifications, which we don't do\n\t\t\t   anything with and therefore don't need */\n\t\t\tDisableThreadLibraryCalls( hinstDLL );\n\n\t\t\t/* Set up the initialisation lock in the kernel */\n\t\t\tpreInit();\n\t\t\tbreak;\n\n\t\tcase DLL_PROCESS_DETACH:\n\t\t\t/* Delete the initialisation lock in the kernel */\n\t\t\tpostShutdown();\n\t\t\tbreak;\n\n\t\tcase DLL_THREAD_ATTACH:\n\t\tcase DLL_THREAD_DETACH:\n\t\t\tbreak;\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* OS-specific support */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tString Function Support\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Match a given substring against a string in a case-insensitive manner.\n   If possible we use native calls to handle this since they deal with\n   charset-specific issues such as collating sequences, however a few OSes\n   don't provide this functionality so we have to do it ourselves.\n   \n   The length argument to strnicmp() should be const, but we make it non-\n   const for compatibility with everyone else's strnicmp() */\n\n#ifdef NO_NATIVE_STRICMP\n\nint strnicmp( const char *src, const char *dest, /* const */ int length )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( src, length ) );\n\n\tLOOP_MAX( i = 0, i < length, i++ )\n\t\t{\n\t\tconst int srcCh = toUpper( *src );\n\t\tconst int destCh = toUpper( *dest );\n\n\t\t/* Need to be careful calling toupper() with side-effects */\n\t\tsrc++, dest++;\n\n\t\tif( srcCh != destCh )\n\t\t\treturn( srcCh - destCh );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, -1 );\n\n\treturn( 0 );\n\t}\n\nint stricmp( const char *src, const char *dest )\n\t{\n\tconst int length = strlen( src );\n\n\tif( length != strlen( dest ) )\n\t\treturn( 1 );\t/* Lengths differ */\n\treturn( strnicmp( src, dest, length ) );\n\t}\n#endif /* NO_NATIVE_STRICMP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMinimal Safe String Function Support\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef NO_NATIVE_STRLCPY\n\n/* Copy and concatenate a string, truncating it if necessary to fit the \n   destination buffer.  Unfortunately the TR 24731 functions don't do this,\n   while the OpenBSD safe-string functions do (but don't implement any of\n   the rest of the TR 24731 functionality).  Because the idiot maintainer\n   of glibc objects to these functions (even Microsoft recognise their\n   utility with the _TRUNCATE semantics for strcpy_s/strcat_s), everyone has \n   to manually implement them in their code, as we do here.\n   \n   Note that these aren't completely identical to the OpenBSD functions, in \n   order to fit the TR 24731 pattern we make the length the second paramter, \n   and give them a TR 24731-like _s suffix to make them distinct from the \n   standard OpenBSD ones (a macro in os_spec.h is sufficient to map this to \n   the proper functions where they're available in libc).\n   \n   In addition they always return 1, since the length value isn't checked\n   anywhere in the code  */\n\nint strlcpy_s( char *dest, const int destLen, const char *src )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destLen ) );\n\tassert( isShortIntegerRangeNZ( destLen ) );\n\tassert( isReadPtr( src, 1 ) );\n\n\t/* Copy as much as we can of the source string onto the end of the \n\t   destination string */\n\tLOOP_MAX( i = 0, i < destLen - 1 && *src != '\\0', i++ )\n\t\tdest[ i ] = *src++;\n\tENSURES_EXT( LOOP_BOUND_OK, 1 );\n\tdest[ i ] = '\\0';\n\n\treturn( 1 );\n\t}\n\nint strlcat_s( char *dest, const int destLen, const char *src )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( dest, destLen ) );\n\tassert( isShortIntegerRangeNZ( destLen ) );\n\tassert( isReadPtr( src, 1 ) );\n\n\t/* See how long the existing destination string is */\n\tLOOP_MAX( i = 0, i < destLen && dest[ i ] != '\\0', i++ );\n\tENSURES_EXT( LOOP_BOUND_OK, 1 );\n\tif( i >= destLen )\n\t\t{\n\t\tDEBUG_DIAG(( \"Overflow in strlcat_s\" ));\n\t\tassert( DEBUG_WARN );\n\t\tdest[ destLen - 1 ] = '\\0';\n\n\t\treturn( 1 );\n\t\t}\n\n\t/* Copy as much as we can of the source string onto the end of the \n\t   destination string */\n\tLOOP_MAX_CHECKINC( i < destLen - 1 && *src != '\\0', i++ )\n\t\tdest[ i ] = *src++;\n\tENSURES_EXT( LOOP_BOUND_OK, 1 );\n\tdest[ i ] = '\\0';\n\n\treturn( 1 );\n\t}\n#endif /* NO_NATIVE_STRLCPY */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSysVars Support\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __WIN32__ )  && \\\n\t!( defined( _M_X64 ) || defined( __MINGW32__ ) || defined( NO_ASM ) )\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\tchar vendorID[ 12 + 8 ];\n\tunsigned long processorID, featureFlags, featureFlags2;\n\tint hasAdvFeatures = 0, sysCaps = 0;\n\n\t/* Check whether the CPU supports extended features like CPUID and \n\t   RDTSC, and get any info that we need related to this.  There is an \n\t   IsProcessorFeaturePresent() function, but all that this provides is \n\t   an indication of the availability of rdtsc (alongside some stuff that \n\t   we don't care about, like MMX and 3DNow).  Since we still need to \n\t   check for the presence of other features, we do the whole thing \n\t   ourselves */\n\t__asm {\n\t\t/* Detect the CPU type */\n\t\tpushfd\n\t\tpop eax\t\t\t\t/* Get EFLAGS in eax */\n\t\tmov ebx, eax\t\t/* Save a copy for later */\n\t\txor eax, 0x200000\t/* Toggle the CPUID bit */\n\t\tpush eax\n\t\tpopfd\t\t\t\t/* Update EFLAGS */\n\t\tpushfd\n\t\tpop eax\t\t\t\t/* Get updated EFLAGS back in eax */\n\t\tpush ebx\n\t\tpopfd\t\t\t\t/* Restore original EFLAGS */\n\t\txor eax, ebx\t\t/* Check if we could toggle CPUID bit */\n\t\tjz noCPUID\t\t\t/* Nope, we can't do anything further */\n\t\tmov [hasAdvFeatures], 1\t/* Remember that we have CPUID */\n\t\tmov [sysCaps], HWINTRINS_FLAG_RDTSC\t/* Remember that we have RDTSC */\n\n\t\t/* We have CPUID, see what we've got */\n\t\txor ecx, ecx\n\t\txor edx, edx\t\t/* Tell VC++ that ECX, EDX will be trashed */\n\t\txor eax, eax\t\t/* CPUID function 0: Get vendor ID */\n\t\tcpuid\n\t\tmov dword ptr [vendorID], ebx\n\t\tmov dword ptr [vendorID+4], edx\n\t\tmov dword ptr [vendorID+8], ecx\t/* Save vendor ID string */\n\t\tmov eax, 1\t\t\t/* CPUID function 1: Get processor info */\n\t\tcpuid\n\t\tmov [processorID], eax\t/* Save processor ID */\n\t\tmov [featureFlags], ecx\t/* Save processor feature info */\n\t\tmov [featureFlags2], ebx/* Save extended feature info */\n\tnoCPUID:\n\t\t}\n\n\t/* If there's no CPUID support, there are no special HW capabilities\n\t   available */\n\tif( !hasAdvFeatures )\n\t\treturn( HWINTRINS_FLAG_NONE );\n\n\t/* If there's a vendor ID present, check for vendor-specific special\n\t   features */\n\tif( !memcmp( vendorID, \"CentaurHauls\", 12 ) )\n\t\t{\n\t__asm {\n\t\txor ebx, ebx\n\t\txor ecx, ecx\t\t/* Tell VC++ that EBX, ECX will be trashed */\n\t\tmov eax, 0xC0000000\t/* Centaur extended CPUID info */\n\t\tcpuid\n\t\tcmp eax, 0xC0000001\t/* Need at least release 2 ext.feature set */\n\t\tjb endCheck\t\t\t/* No extended info available */\n\t\tmov eax, 0xC0000001\t/* Centaur extended feature flags */\n\t\tcpuid\n\t\tmov eax, edx\t\t/* Work with saved copy of feature flags */\n\t\tand eax, 01100b\n\t\tcmp eax, 01100b\t\t/* Check for RNG present + enabled flags */\n\t\tjz noRNG\t\t\t/* No, RNG not present or enabled */\n\t\tor [sysCaps], HWINTRINS_FLAG_XSTORE\t/* Remember that we have a HW RNG */\n\tnoRNG:\n\t\tmov eax, edx\n\t\tand eax, 011000000b\n\t\tcmp eax, 011000000b\t/* Check for ACE present + enabled flags */\n\t\tjz noACE\t\t\t/* No, ACE not present or enabled */\n\t\tor [sysCaps], HWINTRINS_FLAG_XCRYPT\t/* Remember that we have HW AES */\n\tnoACE:\n\t\tmov eax, edx\n\t\tand eax, 0110000000000b\n\t\tcmp eax, 0110000000000b\t/* Check for PHE present + enabled flags */\n\t\tjz noPHE\t\t\t/* No, PHE not present or enabled */\n\t\tor [sysCaps], HWINTRINS_FLAG_XSHA\t/* Remember that we have HW SHA-1/SHA-2 */\n\tnoPHE:\n\t\tmov eax, edx\n\t\tand eax, 011000000000000b\n\t\tcmp eax, 011000000000000b /* Check for PMM present + enabled flags */\n\t\tjz endCheck\t\t\t/* No, PMM not present or enabled */\n\t\tor [sysCaps], HWINTRINS_FLAG_MONTMUL\t/* Remember that we have HW bignum */\n\tendCheck:\n\t\t}\n\t\t}\n\tif( !memcmp( vendorID, \"AuthenticAMD\", 12 ) )\n\t\t{\n\t\t/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */\n\t\tif( ( processorID & 0x0FF0 ) == 0x05A0 )\n\t\t\tsysCaps |= HWINTRINS_FLAG_TRNG;\n\n\t\t/* Check for the presence of a hardware RNG */\n\t\tif( featureFlags & ( 1 << 30 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDRAND;\n\t\t}\n\tif( !memcmp( vendorID, \"GenuineIntel\", 12 ) )\n\t\t{\n\t\t/* Check for hardware AES support */\n\t\tif( featureFlags & ( 1 << 25 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_AES;\n\n\t\t/* Check for the presence of a hardware RNG */\n\t\tif( featureFlags & ( 1 << 30 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDRAND;\n\t\tif( featureFlags2 & ( 1 << 18 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDSEED;\n\t\t}\n\n\treturn( sysCaps );\n\t}\n\n#elif defined( __WIN32__ )  && defined( _M_X64 )\n\n/* 64-bit VC++ doesn't allow inline asm, but does provide the __cpuid() \n   builtin to perform the operation above.  We don't guard this with the \n   NO_ASM check because it's not (technically) done with inline asm, \n   although it's a bit unclear whether an intrinsic qualifies as asm or\n   C */\n\n#pragma intrinsic( __cpuid )\n\ntypedef struct { unsigned int eax, ebx, ecx, edx; } CPUID_INFO;\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void cpuID( OUT CPUID_INFO *result, const int type )\n\t{\n\tint intResult[ 4 ];\t/* That's what the function prototype says */\n\n\t/* Clear return value */\n\tmemset( result, 0, sizeof( CPUID_INFO ) );\n\n\t/* Get the CPUID data and copy it back to the caller.  We clear it \n\t   before calling the __cpuid intrinsic because some analysers don't \n\t   know about it and will warn about use of uninitialised memory */\n\tmemset( intResult, 0, sizeof( int ) * 4 );\n\t__cpuid( intResult, type );\n\tresult->eax = intResult[ 0 ];\n\tresult->ebx = intResult[ 1 ];\n\tresult->ecx = intResult[ 2 ];\n\tresult->edx = intResult[ 3 ];\n\t}\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\tCPUID_INFO cpuidInfo;\n\tchar vendorID[ 12 + 8 ];\n\tint *vendorIDptr = ( int * ) vendorID;\n\tunsigned long processorID, featureFlags, featureFlags2;\n\tint sysCaps = HWINTRINS_FLAG_RDTSC;\t/* x86-64 always has RDTSC */\n\n\t/* Get any CPU info that we need.  There is an \n\t   IsProcessorFeaturePresent() function, but all that this provides is \n\t   an indication of the availability of rdtsc (alongside some stuff that \n\t   we don't care about, like MMX and 3DNow).  Since we still need to \n\t   check for the presence of other features, we do the whole thing \n\t   ourselves */\n\tcpuID( &cpuidInfo, 0 );\n\tvendorIDptr[ 0 ] = cpuidInfo.ebx;\n\tvendorIDptr[ 1 ] = cpuidInfo.edx;\n\tvendorIDptr[ 2 ] = cpuidInfo.ecx;\n\tcpuID( &cpuidInfo, 1 );\n\tprocessorID = cpuidInfo.eax;\n\tfeatureFlags = cpuidInfo.ecx;\n\tfeatureFlags2 = cpuidInfo.ebx;\n\n\t/* Check for vendor-specific special features */\n\tif( !memcmp( vendorID, \"CentaurHauls\", 12 ) )\n\t\t{\n\t\t/* Get the Centaur extended CPUID info and check whether the feature-\n\t\t   flags read capability is present.  VIA only announced their 64-\n\t\t   bit CPUs in mid-2010 and availability is limited so it's \n\t\t   uncertain whether this code will ever be exercised, but we provide \n\t\t   it anyway for compatibility with the 32-bit equivalent */\n\t\tcpuID( &cpuidInfo, 0xC0000000 );\n\t\tif( cpuidInfo.eax >= 0xC0000001 )\n\t\t\t{\n\t\t\t/* Get the Centaur extended feature flags */\n\t\t\tcpuID( &cpuidInfo, 0xC0000000 );\n\t\t\tif( ( cpuidInfo.edx & 0x000C ) == 0x000C )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XSTORE;\n\t\t\tif( ( cpuidInfo.edx & 0x00C0 ) == 0x00C0 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XCRYPT;\n\t\t\tif( ( cpuidInfo.edx & 0x0C00 ) == 0x0C00 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XSHA;\n\t\t\tif( ( cpuidInfo.edx & 0x3000 ) == 0x3000 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_MONTMUL;\n\t\t\t}\n\t\t}\n\tif( !memcmp( vendorID, \"AuthenticAMD\", 12 ) )\n\t\t{\n\t\t/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */\n\t\tif( ( processorID & 0x0FF0 ) == 0x05A0 )\n\t\t\tsysCaps |= HWINTRINS_FLAG_TRNG;\n\t\t}\n\tif( !memcmp( vendorID, \"GenuineIntel\", 12 ) )\n\t\t{\n\t\t/* Check for hardware AES support */\n\t\tif( featureFlags & ( 1 << 25 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_AES;\n\n\t\t/* Check for the return of a hardware RNG */\n\t\tif( featureFlags & ( 1 << 30 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDRAND;\n\t\tif( featureFlags2 & ( 1 << 18 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDSEED;\n\t\t}\n\n\treturn( sysCaps );\n\t}\n\n#elif defined( __GNUC__ ) && \\\n\t  ( ( __GNUC__ > 4 ) || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) ) && \\\n\t  ( defined( __i386__ ) || defined( __x86_64__ ) )\n\n/* Newer versions of gcc have cpuid as an intrinsic */\n\n#if HWINTRINS_FLAG_RDTSC != 0x01\n  #error Need to sync HWINTRINS_FLAG_RDTSC with equivalent asm definition\n#endif /* HWINTRINS_FLAG_RDTSC */\n\n#include <cpuid.h>\n\ntypedef struct { unsigned int eax, ebx, ecx, edx; } CPUID_INFO;\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN cpuID( OUT CPUID_INFO *result, const int type )\n\t{\n\tint a, b, c, d;\t\t/* That's what the function prototype says */\n\tint retVal;\n\n\tassert( isWritePtr( result, sizeof( CPUID_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( result, 0, sizeof( CPUID_INFO ) );\n\n\t/* Get the CPUID data and copy it back to the caller */\n\tretVal = __get_cpuid( type, &a, &b, &c, &d );\n\tif( retVal <= 0 )\n\t\treturn( FALSE );\n\tresult->eax = a;\n\tresult->ebx = b;\n\tresult->ecx = c;\n\tresult->edx = d;\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\tCPUID_INFO cpuidInfo;\n\tchar vendorID[ 12 + 8 ];\n\tint *vendorIDptr = ( int * ) vendorID;\n\tunsigned long processorID, featureFlags, featureFlags2;\n\tint sysCaps = 0;\n\n\t/* Get any CPU info that we need */\n\tif( !cpuID( &cpuidInfo, 0 ) )\t/* CPUID function 0: Get vendor ID */\n\t\treturn( HWINTRINS_FLAG_NONE );\n\tvendorIDptr[ 0 ] = cpuidInfo.ebx;\n\tvendorIDptr[ 1 ] = cpuidInfo.edx;\n\tvendorIDptr[ 2 ] = cpuidInfo.ecx;\n\tif( !cpuID( &cpuidInfo, 1 ) )\t/* CPUID function 1: Get processor info */\n\t\treturn( HWINTRINS_FLAG_NONE );\n\tprocessorID = cpuidInfo.eax;\n\tfeatureFlags = cpuidInfo.ecx;\n\tfeatureFlags2 = cpuidInfo.ebx;\n\n\t/* Check for vendor-specific special features */\n\tif( !memcmp( vendorID, \"CentaurHauls\", 12 ) )\n\t\t{\n\t\tint retVal;\n\n\t\t/* Get the Centaur extended CPUID info and check whether the feature-\n\t\t   flags read capability is present.  VIA only announced their 64-\n\t\t   bit CPUs in mid-2010 and availability is limited so it's \n\t\t   uncertain whether this code will ever be exercised, but we provide \n\t\t   it anyway for compatibility with the 32-bit equivalent */\n\t\tretVal = cpuID( &cpuidInfo, 0xC0000000 );\n\t\tif( retVal && cpuidInfo.eax >= 0xC0000001 )\n\t\t\t{\n\t\t\t/* Get the Centaur extended feature flags */\n\t\t\t( void ) cpuID( &cpuidInfo, 0xC0000000 );\n\t\t\tif( ( cpuidInfo.edx & 0x000C ) == 0x000C )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XSTORE;\n\t\t\tif( ( cpuidInfo.edx & 0x00C0 ) == 0x00C0 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XCRYPT;\n\t\t\tif( ( cpuidInfo.edx & 0x0C00 ) == 0x0C00 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_XSHA;\n\t\t\tif( ( cpuidInfo.edx & 0x3000 ) == 0x3000 )\n\t\t\t\tsysCaps |= HWINTRINS_FLAG_MONTMUL;\n\t\t\t}\n\t\t}\n\tif( !memcmp( vendorID, \"AuthenticAMD\", 12 ) )\n\t\t{\n\t\t/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */\n\t\tif( ( processorID & 0x0FF0 ) == 0x05A0 )\n\t\t\tsysCaps |= HWINTRINS_FLAG_TRNG;\n\t\t}\n\tif( !memcmp( vendorID, \"GenuineIntel\", 12 ) )\n\t\t{\n\t\t/* Check for hardware AES support */\n\t\tif( featureFlags & ( 1 << 25 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_AES;\n\n\t\t/* Check for the return of a hardware RNG */\n\t\tif( featureFlags & ( 1 << 30 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDRAND;\n\t\tif( featureFlags2 & ( 1 << 18 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDSEED;\n\t\t}\n\n\treturn( sysCaps );\n\t}\n\n#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) && \\\n\t  defined( __i386__ ) && !defined( NO_ASM )\n\n/* Fallback inline asm cpuid support */\n\n#if HWINTRINS_FLAG_RDTSC != 0x01\n  #error Need to sync HWINTRINS_FLAG_RDTSC with equivalent asm definition\n#endif /* HWINTRINS_FLAG_RDTSC */\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\tchar vendorID[ 12 + 8 ];\n\tunsigned long processorID, featureFlags, featureFlags2;\n\tint hasAdvFeatures = 0, sysCaps = 0;\n\n\t/* Check whether the CPU supports extended features like CPUID and \n\t   RDTSC, and get any info that we need related to this.  The use of ebx \n\t   is a bit problematic because gcc (via the IA32 ABI) uses ebx to store \n\t   the address of the global offset table and gets rather upset if it \n\t   gets changed, so we have to save/restore it around the cpuid call.  \n\t   We have to be particularly careful here because ebx is used \n\t   implicitly in references to sysCaps (which is a static int), so we \n\t   save it as close to the cpuid instruction as possible and restore it \n\t   immediately afterwards, away from any memory-referencing instructions \n\t   that implicitly use ebx */\n\tasm volatile( \"pushf\\n\\t\"\n\t\t\"popl %%eax\\n\\t\"\n\t\t\"movl %%eax, %%ecx\\n\\t\"\n\t\t\"xorl $0x200000, %%eax\\n\\t\"\n\t\t\"pushl %%eax\\n\\t\"\n\t\t\"popf\\n\\t\"\n\t\t\"pushf\\n\\t\"\n\t\t\"popl %%eax\\n\\t\"\n\t\t\"pushl %%ecx\\n\\t\"\n\t\t\"popf\\n\\t\"\n\t\t\"xorl %%ecx, %%eax\\n\\t\"\n\t\t\"jz noCPUID\\n\\t\"\n\t\t\"movl $1, %[hasAdvFeatures]\\n\\t\"/* hasAdvFeatures = TRUE */\n\t\t\"movl %[HW_FLAG_RDTSC], %[sysCaps]\\n\\t\"\t\t/* sysCaps = HWINTRINS_FLAG_RDTSC */\n\t\t\"pushl %%ebx\\n\\t\"\t/* Save PIC register */\n\t\t\"xorl %%eax, %%eax\\n\\t\"\t/* CPUID function 0: Get vendor ID */\n\t\t\"cpuid\\n\\t\"\n\t\t\"leal %2, %%eax\\n\\t\"\n\t\t\"movl %%ebx, (%%eax)\\n\\t\"\n\t\t\"movl %%edx, 4(%%eax)\\n\\t\"\n\t\t\"movl %%ecx, 8(%%eax)\\n\\t\"\n\t\t\"movl $1, %%eax\\n\\t\"\t/* CPUID function 1: Get processor info */\n\t\t\"cpuid\\n\\t\"\n\t\t\"leal %3, %%edx\\n\\t\"\n\t\t\"movl %%eax, (%%edx)\\n\\t\"\t/* processorID */\n\t\t\"leal %4, %%edx\\n\\t\"\n\t\t\"movl %%ecx, (%%edx)\\n\\t\"\t/* featureFlags */\n\t\t\"leal %5, %%edx\\n\\t\"\n\t\t\"movl %%ebx, (%%edx)\\n\\t\"\t/* featureFlags2 */\n\t\t\"popl %%ebx\\n\"\t\t/* Restore PIC register */\n\t\"noCPUID:\\n\\n\"\n#if 0\t/* See comment in tools/ccopts.sh for why this is disabled */\n\t\t\".section .note.GNU-stack, \\\"\\\", @progbits; .previous\\n\"\n\t\t\t\t\t\t\t/* Mark the stack as non-executable.  This is\n\t\t\t\t\t\t\t   undocumented outside of mailing-list postings\n\t\t\t\t\t\t\t   and a bit hit-and-miss, but having at least\n\t\t\t\t\t\t\t   one of these in included asm code doesn't\n\t\t\t\t\t\t\t   hurt */\n#endif /* 0 */\n\t\t: [hasAdvFeatures] \"=m\"(hasAdvFeatures),/* Output */\n\t\t\t[sysCaps] \"=m\"(sysCaps),\n\t\t\t[vendorID] \"=m\"(vendorID), \n\t\t\t[processorID] \"=m\"(processorID),\n\t\t\t[featureFlags] \"=m\"(featureFlags),\n\t\t\t[featureFlags2] \"=m\"(featureFlags2)\n\t\t: [HW_FLAG_RDTSC] \"i\"(HWINTRINS_FLAG_RDTSC)/* Input */\n\t\t: \"%eax\", \"%ecx\", \"%edx\"\t\t\t\t/* Registers clobbered */\n\t\t);\n\n\t/* If there's no CPUID support, there are no special HW capabilities\n\t   available */\n\tif( !hasAdvFeatures )\n\t\treturn( HWINTRINS_FLAG_NONE );\n\n\t/* If there's a vendor ID present, check for vendor-specific special\n\t   features.  Again, we have to be extremely careful with ebx */\n\tif( !memcmp( vendorID, \"CentaurHauls\", 12 ) )\n\t\t{\n\tasm volatile( \"pushl %%ebx\\n\\t\"\t/* Save PIC register */\n\t\t\"movl $0xC0000000, %%eax\\n\\t\"\n\t\t\"cpuid\\n\\t\"\n\t\t\"popl %%ebx\\n\\t\"\t\t\t/* Restore PIC register */\n\t\t\"cmpl $0xC0000001, %%eax\\n\\t\"\n\t\t\"jb endCheck\\n\\t\"\n\t\t\"pushl %%ebx\\n\\t\"\t\t\t/* Re-save PIC register */\n\t\t\"movl $0xC0000001, %%eax\\n\\t\"\n\t\t\"cpuid\\n\\t\"\n\t\t\"popl %%ebx\\n\\t\"\t\t\t/* Re-restore PIC register */\n\t\t\"movl %%edx, %%eax\\n\\t\"\n\t\t\"andl $0xC, %%edx\\n\\t\"\n\t\t\"cmpl $0xC, %%edx\\n\\t\"\n\t\t\"jz noRNG\\n\\t\"\n\t\t\"orl %[HW_FLAG_XSTORE], %[sysCaps]\\n\"\t/* HWINTRINS_FLAG_XSTORE */\n\t\"noRNG:\\n\\t\"\n\t\t\"movl %%edx, %%eax\\n\\t\"\n\t\t\"andl $0xC0, %%eax\\n\\t\"\n\t\t\"cmpl $0xC0, %%eax\\n\\t\"\n\t\t\"jz noACE\\n\\t\"\n\t\t\"orl %[HW_FLAG_XCRYPT], %[sysCaps]\\n\"\t/* HWINTRINS_FLAG_XCRYPT */\n\t\"noACE:\\n\\t\"\n\t\t\"movl %%edx, %%eax\\n\\t\"\n\t\t\"andl $0xC00, %%eax\\n\\t\"\n\t\t\"cmpl $0xC00, %%eax\\n\\t\"\n\t\t\"jz noPHE\\n\\t\"\n\t\t\"orl %[HW_FLAG_XSHA], %[sysCaps]\\n\"\t\t/* HWINTRINS_FLAG_XSHA */\n\t\"noPHE:\\n\\t\"\n\t\t\"movl %%edx, %%eax\\n\\t\"\n\t\t\"andl $0x3000, %%eax\\n\\t\"\n\t\t\"cmpl $0x3000, %%eax\\n\\t\"\n\t\t\"jz endCheck\\n\\t\"\n\t\t\"orl %[HW_FLAG_MONTMUL], %[sysCaps]\\n\"\t/* HWINTRINS_FLAG_MONTMUL */\n\t\"endCheck:\\n\\n\"\n\t\t : [sysCaps] \"=m\"(sysCaps)\t/* Output */\n\t\t : [HW_FLAG_XSTORE] \"i\"(HWINTRINS_FLAG_XSTORE),/* Input */\n\t\t\t[HW_FLAG_XCRYPT] \"i\"(HWINTRINS_FLAG_XCRYPT),\n\t\t\t[HW_FLAG_XSHA] \"i\"(HWINTRINS_FLAG_XSHA),\n\t\t\t[HW_FLAG_MONTMUL] \"i\"(HWINTRINS_FLAG_MONTMUL)\n\t\t : \"%eax\", \"%ecx\", \"%edx\"\t/* Registers clobbered */\n\t\t);\n\t\t}\n\tif( !memcmp( vendorID, \"AuthenticAMD\", 12 ) )\n\t\t{\n\t\t/* Check for AMD Geode LX, family 0x5 = Geode, model 0xA = LX */\n\t\tif( ( processorID & 0x0FF0 ) == 0x05A0 )\n\t\t\tsysCaps |= HWINTRINS_FLAG_TRNG;\n\t\t}\n\tif( !memcmp( vendorID, \"GenuineIntel\", 12 ) )\n\t\t{\n\t\t/* Check for hardware AES support */\n\t\tif( featureFlags & ( 1 << 25 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_AES;\n\n\t\t/* Check for the return of a hardware RNG */\n\t\tif( featureFlags & ( 1 << 30 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDRAND;\n\t\tif( featureFlags2 & ( 1 << 18 ) )\n\t\t\tsysCaps |= HWINTRINS_FLAG_RDSEED;\n\t\t}\n\n\treturn( sysCaps );\n\t}\n\n#elif defined( __GNUC__ ) && ( defined( __arm ) || defined( __arm__ ) ) && \\\n\t  !defined( NO_ASM ) && 0\t\t/* See comment below */\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\tint processorID;\n\n\t/* Get the ARM CPU type information.  Unfortunately this instruction \n\t   (and indeed virtually all of the very useful CP15 registers) are \n\t   inaccessible from user mode so it's not safe to perform any of these \n\t   operations.  If you're running an embedded OS that runs natively in \n\t   supervisor mode then you can try enabling this function to check \n\t   whether you have access to the other CP15 registers and their \n\t   information about hardware capabilities */\n\tasm volatile (\n\t\t\"mrc p15, 0, r0, c0, c0, 0\\n\\t\"\n\t\t\"str r0, %0\\n\"\n\t\t: \"=m\"(processorID)\n\t\t:\n\t\t: \"cc\", \"r0\");\n\n\treturn( HWINTRINS_FLAG_NONE );\n\t}\n#else\n\nCHECK_RETVAL_ENUM( HWINTRINS_FLAG ) \\\nstatic int getHWIntrins( void )\n\t{\n\treturn( HWINTRINS_FLAG_NONE );\n\t}\n#endif /* OS-specific support */\n\n/* Initialise OS-specific constants.  This is a bit ugly because the values \n   are often specific to one cryptlib module but there's no (clean) way to\n   perform any complex per-module initialisation so we have to know about \n   all of the module-specific sysVar requirements here */\n\n#define MAX_SYSVARS\t\t8\n\nstatic int sysVars[ MAX_SYSVARS ];\n\n#if ( defined( __WIN32__ ) || defined( __WINCE__ ) )\n\nCHECK_RETVAL \\\nint initSysVars( void )\n\t{\n#if VC_LT_2010( _MSC_VER )\n\tOSVERSIONINFO osvi = { sizeof(OSVERSIONINFO) };\n#endif /* VC++ < 2010 */\n\tSYSTEM_INFO systemInfo;\n\n\tstatic_assert( SYSVAR_LAST < MAX_SYSVARS, \"System variable value\" );\n\n\t/* Reset the system variable information */\n\tmemset( sysVars, 0, sizeof( int ) * MAX_SYSVARS );\n\n#if VC_LT_2010( _MSC_VER )\n\t/* Figure out which version of Windows we're running under */\n\tif( !GetVersionEx( &osvi ) )\n\t\t{\n\t\t/* If for any reason the call fails, just use the most likely \n\t\t   values */\n\t\tosvi.dwMajorVersion = 5;\t/* Win2K and higher */\n\t\tosvi.dwPlatformId = VER_PLATFORM_WIN32_NT;\n\t\t}\n\tsysVars[ SYSVAR_OSMAJOR ] = osvi.dwMajorVersion;\n\tsysVars[ SYSVAR_OSMINOR ] = osvi.dwMinorVersion;\n\n\t/* Check for Win32s and Win95/98/ME just in case someone ever digs up \n\t   one of these systems and tries to load cryptlib under them */\n\tif( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || \\\n\t\tosvi.dwPlatformId == VER_PLATFORM_WIN32s )\n\t\t{\n\t\tDEBUG_DIAG(( \"Win32s detected\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n#endif /* VC++ < 2010 */\n\n\t/* Get the system page size */\n\tGetSystemInfo( &systemInfo );\n\tsysVars[ SYSVAR_PAGESIZE ] = systemInfo.dwPageSize;\n\n\t/* Get system hardware capabilities */\n\tsysVars[ SYSVAR_HWINTRINS ] = getHWIntrins();\n\n\treturn( CRYPT_OK );\n\t}\n\n#elif defined( __UNIX__ )\n\n#include <unistd.h>\n#ifdef HAS_DEVCRYPTO\n  #include <fcntl.h>\n  #include <crypto/cryptodev.h>\n  #include <sys/ioctl.h>\n#endif /* HAS_DEVCRYPTO */\n\n#ifdef HAS_DEVCRYPTO\n\n/* Check for the presence of crypto hardware support.  This is something of \n   an exercise in futility because the crypto hardware is anything from \n   slightly slower (very large data blocks) to much, much slower (more \n   standard small data blocks) than software due to the overhead of getting\n   the data to and from the cryptologic and the cryptologic overhead. \n   However, people really want to see the fancy crypto hardware used even if\n   it yields a net loss in performance so we try and enable it if possible\n   unless it really is pointless, a slow software emulation of a slow \n   hardware interface */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN testCryptoAvail( const int cryptoFD,\n\t\t\t\t\t\t\t\tIN_RANGE( CRYPTO_DES_CBC, \\\n\t\t\t\t\t\t\t\t\t\t  CRYPTO_ALGORITHM_MAX ) \\\n\t\t\t\t\t\t\t\t\tconst int cryptoType )\n\t{\n\tstruct session_info_op sessionInfo;\n\tstruct session_op session;\n\tconst BOOLEAN isCipher = \\\n\t\t\t( cryptoType == CRYPTO_3DES_CBC || \\\n\t\t\t  cryptoType == CRYPTO_AES_CBC ) ? TRUE : FALSE;\n\n\tREQUIRES_B( cryptoType >= CRYPTO_DES_CBC && \\\n\t\t\t\tcryptoType < CRYPTO_ALGORITHM_MAX );\n\n\t/* Check whether the requested mechanism is available, and in what \n\t   form */\n\tmemset( &session, 0, sizeof( struct session_op ) );\n\tif( isCipher )\n\t\t{\n\t\tsession.cipher = cryptoType;\n\t\tsession.key = \"0123456789ABCDEF\";\n\t\tsession.keylen = 16;\n\t\t}\n\telse\n\t\tsession.mac = cryptoType;\n\tif( ioctl( cryptoFD, CIOCGSESSION, &session ) )\n\t\treturn( FALSE );\n\tmemset( &sessionInfo, 0, sizeof( struct session_info_op ) );\n\tsessionInfo.ses = session.ses;\n\tif( ioctl( cryptoFD, CIOCGSESSINFO, &sessionInfo ) )\n\t\t{\n\t\tioctl( cryptoFD, CIOCFSESSION, &session.ses );\n\t\treturn( FALSE );\n\t\t}\n\tioctl( cryptoFD, CIOCFSESSION, &session.ses );\n\tif( !( sessionInfo.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY ) )\n\t\t{\n\t\t/* The sole flag supported by CryptoDev, \n\t\t   SIOP_FLAG_KERNEL_DRIVER_ONLY, is rather confusing since it's\n\t\t   documented as meaning that the algorithm uses a driver only \n\t\t   available in-kernel, but whether this means that it's only \n\t\t   available from within the kernel or that it's hardware supported\n\t\t   by a kernel driver (as opposed to a software-only implementation) \n\t\t   is unclear.  Code comments and testing on various systems indicates\n\t\t   that if it's not set then it's software-only, so if we don't see it \n\t\t   set then we don't use this interface */\n\t\tDEBUG_PRINT(( \"Crypto %s is available but a software-only \"\n\t\t\t\t\t  \"implementation, skipping...\\n\", isCipher ? \\\n\t\t\t\t\t\tsessionInfo.cipher_info.cra_driver_name : \\\n\t\t\t\t\t\tsessionInfo.hash_info.cra_driver_name ));\n\t\treturn( FALSE );\n\t\t}\n\n\tDEBUG_PRINT(( \"Enabling crypto hardware support for %s.\\n\",\n\t\t\t\t  isCipher ? sessionInfo.cipher_info.cra_driver_name : \\\n\t\t\t\t\t\t\t sessionInfo.hash_info.cra_driver_name ));\n\n\treturn( TRUE );\n\t}\n\n#ifdef CIOCCPHASH\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkCopyAvail( const int cryptoFD )\n\t{\n\tstruct session_op session1, session2;\n\tstruct crypt_op cryptOpInfo;\n\tBOOLEAN returnValue = FALSE;\n\n\t/* Create two SHA-1 sessions */\n\tmemset( &session1, 0, sizeof( struct session_op ) );\n\tsession1.mac = CRYPTO_SHA1;\n\tif( ioctl( cryptoFD, CIOCGSESSION, &session1 ) )\n\t\treturn( FALSE );\n\tmemset( &session2, 0, sizeof( struct session_op ) );\n\tsession2.mac = CRYPTO_SHA1;\n\tif( ioctl( cryptoFD, CIOCGSESSION, &session2 ) )\n\t\t{\n\t\t( void ) ioctl( cryptoFD, CIOCFSESSION, session1 );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Hash some data using the first session, then copy it to the second \n\t   session */\n\tmemset( &cryptOpInfo, 0, sizeof( struct crypt_op ) );\n\tcryptOpInfo.ses = session1.ses;\n\tcryptOpInfo.op = COP_ENCRYPT;\n\tcryptOpInfo.flags = COP_FLAG_RESET | COP_FLAG_UPDATE;\n\tcryptOpInfo.src = \"12345678\";\n\tcryptOpInfo.len = 8;\n\tif( ioctl( cryptoFD, CIOCCRYPT, &cryptOpInfo ) == 0 )\n\t\t{\n\t\tstruct cphash_op copyInfo;\n\n\t\tmemset( &copyInfo, 0, sizeof( struct cphash_op ) );\n\t\tcopyInfo.src_ses = session1.ses;\n\t\tcopyInfo.dst_ses = session2.ses;\n\t\tif( ioctl( cryptoFD, CIOCCPHASH, &copyInfo ) == 0 )\n\t\t\treturnValue = TRUE;\n\t\t}\n\n\t/* Clean up */\n\t( void ) ioctl( cryptoFD, CIOCFSESSION, session1 );\n\t( void ) ioctl( cryptoFD, CIOCFSESSION, session2 );\n\n\treturn( returnValue );\n\t}\n#else\n  #define checkCopyAvail( cryptoFD, sessionID )\t\tFALSE\n#endif /* CIOCCPHASH */\n\nCHECK_RETVAL_ENUM( HWCRYPT_FLAG ) \\\nstatic int getHWCrypt( void )\n\t{\n\tstatic const MAP_TABLE hwCryptInfo[] = {\n\t\t{ CRYPTO_3DES_CBC, HWCRYPT_FLAG_CRYPTDEV_3DES },\n\t\t{ CRYPTO_AES_CBC, HWCRYPT_FLAG_CRYPTDEV_AES },\n\t\t{ CRYPTO_SHA1, HWCRYPT_FLAG_CRYPTDEV_SHA1 },\n\t\t{ CRYPTO_SHA2_256, HWCRYPT_FLAG_CRYPTDEV_SHA2 },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR },\n\t\t\t{ CRYPT_ERROR, CRYPT_ERROR }\n\t\t};\n\tstruct session_op session;\n\tint cryptoFD, hwCryptFlags = HWCRYPT_FLAG_NONE, i, LOOP_ITERATOR;\n\n\t/* Open the crypto device and make sure that we can talk to it.  We use\n\t   SHA-1 as our generic test algorithm both because it should be \n\t   supported everywhere and because it doesn't require any extra data \n\t   like a key in order to perform the query */\n\tcryptoFD = open( \"/dev/crypto\", O_RDWR, 0 );\n\tif( cryptoFD < 0 )\n\t\treturn( HWCRYPT_FLAG_NONE );\n\tfcntl( cryptoFD, F_SETFD, FD_CLOEXEC );\n\tmemset( &session, 0, sizeof( struct session_op ) );\n\tsession.mac = CRYPTO_SHA1;\n\tif( ioctl( cryptoFD, CIOCGSESSION, &session ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"CryptoDev SHA-1 access failed\" ));\n\t\tclose( cryptoFD );\n\n\t\treturn( HWCRYPT_FLAG_NONE );\n\t\t}\n\tioctl( cryptoFD, CIOCFSESSION, &session.ses );\n\n\t/* Check whether CIOCCPHASH is supported.  This is required for cloned \n\t   hash contexts */\n\tif( !checkCopyAvail( cryptoFD ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"CryptoDev CIOCCPHASH not supported, using default \"\n\t\t\t\t\t \"crypto provider\" ));\n\t\tclose( cryptoFD );\n\n\t\treturn( HWCRYPT_FLAG_NONE );\n\t\t}\n\n\t/* Find out which hardware crypto capabilities are available */\n\tLOOP_SMALL( i = 0, hwCryptInfo[ i ].source != CRYPT_ERROR && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( hwCryptInfo, MAP_TABLE ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( testCryptoAvail( cryptoFD, hwCryptInfo[ i ].source ) )\n\t\t\thwCryptFlags |= hwCryptInfo[ i ].destination;\n\t\t}\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( hwCryptInfo, MAP_TABLE ), \n\t\t\t\t HWCRYPT_FLAG_NONE );\n\tclose( cryptoFD );\n\n\treturn( hwCryptFlags );\n\t}\n#else\n\nCHECK_RETVAL_ENUM( HWCRYPT_FLAG ) \\\nstatic int getHWCrypt( void )\n\t{\n\treturn( HWCRYPT_FLAG_NONE );\n\t}\n#endif /* HAS_DEVCRYPTO */\n\nCHECK_RETVAL \\\nint initSysVars( void )\n\t{\n\tstatic_assert( SYSVAR_LAST < MAX_SYSVARS, \"System variable value\" );\n\n\t/* Reset the system variable information */\n\tmemset( sysVars, 0, sizeof( int ) * MAX_SYSVARS );\n\n\t/* Get the system page size.  We try for the sysconf() option first \n\t   because the original getpagesize() has been deprecated by Posix and,\n\t   while still present, typically requires system-specific preprocessor\n\t   defines to enable */\n#if defined( _SC_PAGESIZE )\n\tsysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGESIZE );\n#elif defined( _SC_PAGE_SIZE )\n\tsysVars[ SYSVAR_PAGESIZE ] = sysconf( _SC_PAGE_SIZE );\n#elif defined( _CRAY )\n\tsysVars[ SYSVAR_PAGESIZE ] = 4096;\t/* Close enough for most systems */\n#else\n\tsysVars[ SYSVAR_PAGESIZE ] = getpagesize();\n#endif /* Unix variant-specific brokenness */\n\tif( sysVars[ SYSVAR_PAGESIZE ] < 1024 )\n\t\t{\n\t\tDEBUG_DIAG(( \"System reports page size < 1024\" ));\n\t\tassert( DEBUG_WARN );\n\n\t\t/* Suspiciously small reported page size, just assume a sensible \n\t\t   value */\n\t\tsysVars[ SYSVAR_PAGESIZE ] = 4096;\n\t\t}\n\n\t/* Get system hardware capabilities */\n\tsysVars[ SYSVAR_HWINTRINS ] = getHWIntrins();\n\tsysVars[ SYSVAR_HWCRYPT ] = getHWCrypt();\n\n#if defined( __IBMC__ ) || defined( __IBMCPP__ )\n\t/* VisualAge C++ doesn't set the TZ correctly */\n\ttzset();\n#endif /* VisualAge C++ */\n\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\nCHECK_RETVAL \\\nint initSysVars( void )\n\t{\n\t/* Reset the system variable information */\n\tmemset( sysVars, 0, sizeof( int ) * MAX_SYSVARS );\n\n\t/* Get system hardware capabilities */\n\tsysVars[ SYSVAR_HWINTRINS ] = getHWIntrins();\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* OS-specific support */\n\nCHECK_RETVAL \\\nint getSysVar( IN_ENUM( SYSVAR ) const SYSVAR_TYPE type )\n\t{\n\tREQUIRES( isEnumRange( type, SYSVAR ) );\n\n\treturn( sysVars[ type ] );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous System-specific Support Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Align a pointer to a given boundary.  This gets quite complicated because\n   the only pointer arithmetic that's normally allowed is addition and \n   subtraction, but to align to a boundary we need to be able to perform \n   bitwise operations.  First we convert the pointer to a char pointer so\n   that we can perform normal maths on it, and then we round in the usual\n   manner used by roundUp().  Because we have to do pointer-casting we can't \n   use roundUp() directly but have to build our own version here */\n\nvoid *ptr_align( const void *ptr, const int units )\n\t{\n\tassert( isReadPtr( ptr, 1 ) );\n\tassert( isShortIntegerRangeNZ( units ) );\n\n\treturn( ( void * ) ( ( char * ) ptr + ( -( ( intptr_t )( ptr ) ) & ( units - 1 ) ) ) );\n\t}\n\n/* Determine the difference between two pointers, with some sanity \n   checking.  This assumes the pointers are fairly close in location,\n   used to determine whether pointers that were potentially relocated \n   at some point via ptr_align() have moved */\n\nint ptr_diff( const void *ptr1, const void *ptr2 )\n\t{\n\tptrdiff_t diff;\n\n\tassert( isReadPtr( ptr1, 1 ) );\n\tassert( isReadPtr( ptr2, 1 ) );\n\tassert( ptr1 >= ptr2 );\n\n\tdiff = ( const BYTE * ) ptr1 - ( const BYTE * ) ptr2;\n\tif( diff < 0 )\n\t\tdiff = -diff;\n\tif( diff >= MAX_INTLENGTH )\n\t\treturn( -1 );\n\n\treturn( ( int ) diff );\n\t}\n"
  },
  {
    "path": "deps/cl345/misc/os_spec.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib OS-Specific Interface Header File \t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _OSSPEC_DEFINED\n\n#define _OSSPEC_DEFINED\n\n/* To build the static .LIB under Win32, uncomment the following define (this\n   it not recommended since the init/shutdown is no longer completely thread-\n   safe).  In theory it should be possible to detect the build of a DLL vs.a\n   LIB with the _DLL define which is set when the /MD (multithreaded DLL)\n   option is used, however VC++ only defines _DLL when /MD is used *and*\n   it's linked with the MT DLL runtime.  If it's linked with the statically\n   linked runtime, _DLL isn't defined, which would result in the unsafe LIB\n   version being built as a DLL */\n\n/* #define STATIC_LIB */\n\n/* os_spec.h uses settings from config.h, so this file must be applied after \n   config.h */\n\n#ifndef _CONFIG_DEFINED\n  #error \"os_spec.h must be included after config.h\"\n#endif /* _CONFIG_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tOS-Specific Compiler Configuration\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Include stdint.h if it's available, since this greatly simplifies the\n   handling of data types in a portable manner */\n\n#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) \n  /* stdint.h via C99 compatibility */\n  #include <stdint.h>\n#elif defined( __GNUC__ ) && ( __GNUC__ > 3 ) \n  #if defined( __VxWorks__ ) && \\\n\t  ( ( _WRS_VXWORKS_MAJOR < 6 ) || \\\n\t\t( _WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR < 6 ) )\n\t/* Older versions of Wind River's toolchain don't include stdint.h, it \n\t   was added somewhere around VxWorks 6.6 */\n\ttypedef unsigned int\t\tuintptr_t;\n\ttypedef int\t\t\t\t\tintptr_t;\n  #else\n\t/* stdint.h via GNU headers */\n\t#include <stdint.h>\n  #endif /* Nonstandard gcc environments */\n#elif defined( __SUNPRO_C )\n  /* Older versions of Slowaris, which won't be caught by the STDC check \n     above, use inttypes.h */\n  #include <inttypes.h>\n#elif defined( __HAIKU__ )\n  /* Ancient gcc but with stdint.h */\n  #include <stdint.h>\n#elif defined( _MSC_VER ) && VC_GE_2015( _MSC_VER )\n  /* stdint.h via Visual Studio */\n  #include <stdint.h>\n#elif defined( _MSC_VER )\n  typedef INT_PTR\t\t\t\tintptr_t;\n  typedef UINT_PTR\t\t\t\tuintptr_t;\n#else\n  #if ULONG_MAX > 0xFFFFFFFFUL\n\ttypedef long long\t\t\tintptr_t;\n\ttypedef unsigned long long\tuintptr_t;\n  #else\n\ttypedef long\t\t\t\tintptr_t;\n\ttypedef unsigned long\t\tuintptr_t;\n  #endif /* 64- vs 32-bit systems */\n#endif /* Various stdint.h options */\n\n/* Try and figure out how to get the current function name.  Pre-C99 used\n   __FUNCTION__ instead of __func__ and treated it like the other \n   preprocessor macros __FILE__, __TIME__, etc, so if we find that we map\n   it to the C99 __func__.  In addition because __func__ is a predefined \n   string literal rather than a predefined macro/preprocessor symbol, we\n   can't check for #ifdef __func__ because it's usually not visible to\n   the preprocessor */\n\n#if defined( __FUNCTION__ ) && \\\n\t!( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) )\n  #define __func__\t\t__FUNCTION__\n#endif /* Map old-style __FUNCTION__ to C99 equivalent */\n#if defined( __arm__ ) || defined( __ghs__ )\n  #define __func__\t\t__FUNCTION__\n#endif /* Compilers with __FUNCTION__ but not __func__, and as a predefined \n\t\t  string literal not a predefined macro, Arm cc and Green Hills cc */\n\n#if ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) || \\\n\tdefined( __func__ ) || \\\n\tdefined( __GNUC__ ) || defined( __clang__ ) || defined( __arm__ ) || \\\n\tdefined( __IAR_SYSTEMS_ICC__ ) || defined( __INTEL_COMPILER ) || \\\n\tdefined( __SUNPRO_C ) \n  /* The compilers above have __func__, or __FUNCTION__ mapped to __func__.  \n     For all others we generate a compile error to allow explicit fixup of \n\t the appropriate macro or identifier, unless the compilers are excluded\n\t below */\n  #define HAS_FUNC\n#endif /* Compilers with __func__ support */\n#if !defined( HAS_FUNC ) && \\\n\t( defined( _MSC_VER ) && VC_LT_2005( _MSC_VER ) )\n  #define __func__\t\t\t\t\"(unknown)\"\n#endif /* HAS_FUNC */\n\n/* If we're compiling on the AS/400, make enums a fixed size rather than\n   using the variable-length values that IBM compilers default to, and force\n   strings into a read-only segment (by default they're writeable) */\n\n#ifdef __AS400__\n  #pragma enumsize( 4 )\n  #pragma strings( readonly )\n  #define EBCDIC_CHARS\n#endif /* AS/400 */\n\n/* If we're compiling under MVS or VM/CMS, make enums a fixed size rather\n   than using the variable-length values that IBM compilers default to */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma enum( 4 )\n  #define USE_ETOA\t\t/* Use built-in ASCII <-> EBCDIC conversion */\n  #define EBCDIC_CHARS\n#endif /* __MVS__ */\n\n/* If we're compiling under QNX, make enums a fixed size rather than using\n   the variable-length values that the Watcom compiler defaults to */\n\n#if defined( __QNX__ ) && defined( __WATCOMC__ )\n  #pragma enum int\n#endif /* QNX and Watcom C */\n\n/* A few rare operations are word-size-dependant.  This isn't as simple as \n   checking LONG_MAX because it won't work correctly with LLP64 systems, \n   luckily this is only Win64 which we can check for explicitly */\n\n#if INT_MAX <= 32768L\n  #define SYSTEM_16BIT\n#elif ( ULONG_MAX > 0xFFFFFFFFUL ) || defined( __WIN64__ )\n  #define SYSTEM_64BIT\n#else\n  #define SYSTEM_32BIT\n#endif /* 16- vs.32- vs.64-bit system */\n\n/* Useful data types.  Newer compilers provide a 'bool' datatype via \n   stdbool.h, but in a fit of braindamage generally make this a char instead \n   of an int.  While Microsoft's use of char for BOOLEAN in the early 1980s \n   with 8/16-bit 8086s and 128K of RAM makes sense, it's a pretty stupid \n   choice for 32- or 64-bit CPUs because alignment issues mean that it'll \n   generally still require 32 or 64 bits of storage (except for special \n   cases like an array of bool), but then the difficulty or even inability \n   of many CPUs and/or architectures to perform byte-level accesses means \n   that in order to update a boolean the system has to fetch a full machine \n   word, mask out the byte data, or/and in the value, and write the word \n   back out.  So 'bool' = 'char' combines most of the worst features of both \n   char and int.\n   \n   It also leads to really hard-to-find implementation bugs due to the fact \n   that '(bool) int = true' produces different results to \n   '*(bool *) intptr = true', something that was resolved years ago in enums \n   without causing such breakage.  \n   \n   Quite apart from those issues, the fact that we use fault-immune values\n   for booleans (see misc/safety.h) means that we can't use a bool because \n   it's only defined for the values 0 and 1, a single fault away from each \n   other.\n\n   Because of this we avoid the use of bool and just define it to int */\n\ntypedef unsigned char\t\tBYTE;\n#if defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) && 0\n  #include <stdbool.h>\n  typedef bool              BOOLEAN;\n#elif defined( __WIN32__ ) || defined( __WINCE__ )\n  /* VC++ typedefs BOOLEAN so we need to use the preprocessor to override it */\n  #define BOOLEAN\t\t\tint\n#elif defined( __UCOS__ ) || defined( __SMX__ )\n  /* Some OSes typedef BOOLEAN themselves so we set it as a #define, which \n\t means that we can then work around the typedef by undefining and\n\t redefining it around the include of the OS-specific headers:\n\n\t\t#undef BOOLEAN\n\t\t#include <smx.h>\n\t\t#define BOOLEAN int */\n  #if defined( __SMX__ ) && !defined( _MSC_VER )\n\ttypedef int\t\t\t\tBOOLEAN;\n  #else\n\t#define BOOLEAN\t\t\tint\n  #endif /* OS-specific BOOLEAN juggling */\n#elif defined( __Nucleus__ )\n  /* Nucleus defines BOOLEAN as 'unsigned char' so we override it to be an\n     int */\n  #undef  BOOLEAN\n  #define BOOLEAN\t\t\tint\n#else\n  typedef int\t\t\t\tBOOLEAN;\n#endif /* Boolean data type on different platforms */\n\n/* Sometimes we need to pass a BOOLEAN by reference to a function that \n   treats its parameter as a generic integer value.  In order to make \n   explicit that this is still a BOOLEAN even though it's of type int,\n   we define a symbolic BOOLEAN_INT */\n\ntypedef int\t\t\t\t\tBOOLEAN_INT;\n\n/* If we're building the Windows kernel driver version, include the DDK\n   headers */\n\n#if defined( __WIN32__ ) && defined( NT_DRIVER )\n  #include <ntddk.h>\n#endif /* NT kernel driver */\n\n/* If we're using eCOS, include the system config file that tells us which \n   parts of the eCOS kernel are available */\n\n#ifdef __ECOS__\n  #include <pkgconf/system.h>\n#endif /* __ECOS__ */\n\n/* The VxWorks SDK defines the value 'SH' (to indicate the use of the SuperH \n   CPU family) in vxCpu.h which conflicts with the 'struct SH' in ssh.h. \n   To fix this we undefine it, this shouldn't be a problem since the define \n   SH32 is set to the same value as SH and presumably no-one will be using \n   the basic 20-year-old SuperH any more.\n\n   VxWorks also uses some global symbols that clash with cryptlib's ones, \n   to resolve this we redefine the cryptlib ones to have a 'cl_' prefix */\n\n#ifdef __VxWorks__\n  /* Correct the use of the VxWorks preprocessor define 'SH' overriding \n     'struct SH' in ssh.h */\n  #if defined( SH )\n\t#undef SH\n  #endif /* SH */\n\n  /* Correct clashing global symbols in VxWorks */\n  #define setSerialNumber\t\tcl_setSerialNumber\n  #define inflate\t\t\t\tcl_inflate\n  #define addAction\t\t\t\tcl_addAction\n  #define inflate_copyright\t\tcl_inflate_copyright\n  #define zlibVersion\t\t\tcl_zlibVersion\n#endif /* __VxWorks__ */\n\n/* Some versions of the WinCE SDK define 'interface' as part of a complex \n   series of kludges for OLE support, made even more amusing by the fact \n   that 'interface' is an optional keyword in eVC++ which may or may not \n   be recognised as such by the compiler.  To avoid conflicts we undefine \n   it if it's defined since we're not using any OLE functionality */\n\n#if defined( __WINCE__ ) && defined( interface )\n  #undef interface\n#endif /* WinCE SDK */\n\n/* cryptlib contains a few locations that require forward declarations for\n   static data:\n\n\textern const int foo[];\n\n\tfoo[ i ] = bar;\n\n\tstatic const int foo[] = { ... };\n\n   Compiler opinions on how to handle this vary.  Some compile it as is\n   (i.e. 'static const ...'), some don't allow the 'static', some allow both\n   variants, and some produce warnings with both but allow them anyway\n   (there are probably more variants with further compilers).  To get around\n   this, we use the following define and then vary it for broken compilers\n   (the following is the minimum required to get it to compile, other broken\n   compilers will still produce warnings) */\n\n#if ( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 ) ) || \\\n\tdefined( __VMCMS__ ) || defined( __MVS__ ) || defined( __MRC__ ) || \\\n\tdefined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\t( defined( __UNIX__ ) && ( defined( __HP_cc ) || defined( __HP_aCC ) ) ) || \\\n\t( defined( __UNIX__ ) && defined( _MPRAS ) )\n  #define STATIC_DATA\n#else\n  #define STATIC_DATA\tstatic\n#endif /* Fn.prototyping workarounds for borken compilers */\n\n/* When implementing safe pointers, cryptlib returns structs that contain \n   fat pointers, some of which are const.  A few compilers don't like a\n   const struct as a returned value, so we no-op it out */\n\n#if defined( __xlc__ ) || defined( __IBMC__ )\n  #define CONST_RETURN \n#else\n  #define CONST_RETURN\tconst\n#endif /* IBM mainframe compilers */\n\n/* A few compilers won't allow initialisation of a struct at runtime, so\n   we have to kludge the init with macros.  This is rather ugly since\n   instead of saying \"struct = { a, b, c }\" we have to set each field\n   individually by name.  The real reason for doing this though is that\n   if the compiler can initialise the struct directly, we can make the\n   fields const for better usage checking by the compiler.\n\n   There are two forms of this, one for simple structs and one for arrays\n   of structs.  At the moment the only use for the array-init is for the\n   situation where the array represents a sequence of search options with\n   the last one being a terminator entry, so we provide a simplified form\n   that only sets the required fields.\n   \n   The value of __SUNPRO_C bears no relation whatsoever to the actual \n   version number of the compiler and even Sun's docs give different values \n   in different places for the same compiler version, but 0x570 seems to \n   work */\n\n#if ( defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 ) ) || \\\n\tdefined( _CRAY ) || \\\n\t( defined( __hpux ) && !defined( __GNUC__ ) ) || \\\n\t( defined( __QNX__ ) && ( OSVERSION <= 4 ) ) || \\\n\tdefined( __RVCT2_1__ ) || \\\n\t( defined( __SUNPRO_C ) && ( __SUNPRO_C <= 0x570 ) ) || \\\n\tdefined( __SCO_VERSION__ ) || defined(  __TANDEM )\n  #define CONST_INIT\n  #define CONST_INIT_STRUCT_3( decl, init1, init2, init3 ) \\\n\t\t  decl\n  #define CONST_INIT_STRUCT_4( decl, init1, init2, init3, init4 ) \\\n\t\t  decl\n  #define CONST_INIT_STRUCT_5( decl, init1, init2, init3, init4, init5 ) \\\n\t\t  decl\n  #define CONST_SET_STRUCT( init ) \\\n\t\t  init\n\n  #define CONST_INIT_STRUCT_A2( decl, init1, init2 ) \\\n\t\t  decl\n  #define CONST_SET_STRUCT_A( init ) \\\n\t\t  init\n#else\n  #define CONST_INIT\tconst\n  #define CONST_INIT_STRUCT_3( decl, init1, init2, init3 ) \\\n\t\t  decl = { init1, init2, init3 }\n  #define CONST_INIT_STRUCT_4( decl, init1, init2, init3, init4 ) \\\n\t\t  decl = { init1, init2, init3, init4 }\n  #define CONST_INIT_STRUCT_5( decl, init1, init2, init3, init4, init5 ) \\\n\t\t  decl = { init1, init2, init3, init4, init5 }\n  #define CONST_SET_STRUCT( init )\n\n  #define CONST_INIT_STRUCT_A2( decl, init1, init2 ) \\\n\t\t  const decl = { { init1, 0 }, { init2, 0 } }\n  #define CONST_SET_STRUCT_A( init )\n#endif /* Watcom C || SunPro C || SCO C */\n\n/* The Tandem mktime() is broken and can't convert dates beyond 2023, so we\n   replace it with our own version which can */\n\n#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n  #define mktime( timeptr )\t\tmy_mktime( timeptr )\n#endif /* __TANDEM_NSK__ || __TANDEM_OSS__ */\n\n/* MQX is even worse, its struct tm is broken so we need to override both\n   mktime() and gmtime() to allow fixups for the struct tm fields */\n\n#if defined( __MQXRTOS__ )\n  #define mktime( timeptr )\t\t\t\tmy_mktime( timeptr )\n  #define gmtime_r( time, result )\t\tmy_gmtime_r( time, result )\n#endif /* __MQXRTOS__ */\n\n/* In some environments va_list is a scalar, so it can't be compared with \n   NULL in order to verify its validity.  This was particularly problematic \n   with the ARM ABI, which changed the type in late 2009 to \n   'struct __va_list { void *__ap; }', breaking compatibility with all \n   existing code.  We can detect this by taking advantage of the fact that \n   support for the change was added in gcc 4.4, so any newer version with \n   ARM_EABI defined will have a scalar va_list.\n\n   The Arm64 ABI gets even more complicated, with a va_list being \n   struct __va_list { void *__stack; void *__gr_top; void *__vr_top; \n   int __gr_offs; int __vr_offs; } so we no-op it out there as well.\n   \n   Super-H variants also have scalar va_lists, the Super-H varargs header \n   va-sh.h uses a complex structure to handle va_lists for all SH3 and SH4 \n   variants, this presumably extends to SH5 as well so we treat va_lists on \n   Super-H as scalars */\n\n#if defined( __GNUC__ )\n  #if( defined( __ARM_EABI__ ) && \\\n\t   ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) || ( __GNUC__ > 4 ) )\n\t/* In theory we could check __ap but in practice it's too risky to rely \n\t   on the type and state of hidden internal fields, and in any case it's \n\t   only a sanity check, not a hard requirement, so we just no-op the \n\t   check out */\n\t#define verifyVAList( x ) TRUE\n  #elif defined( __aarch64__ ) || defined( __arm64 )\n\t#define verifyVAList( x ) TRUE\n  #elif defined( __sh__ )\n\t#define verifyVAList( x ) TRUE\n  #endif /* Architecture-specific scalar va_lists */\n#elif defined( __RVCT2_1__ ) || defined( __IAR_SYSTEMS_ICC__ )\n  /* The RealView and IAR compilers have the same issue */\n  #define verifyVAList( x ) TRUE\n#endif /* Nonstandard va_list types */\n#ifndef verifyVAList\n  #define verifyVAList( x ) ( ( x ) != NULL )\n#endif /* Verify function for vector arg lists */\n\n/* cryptlib has many code sequences of the form:\n\n\tstatus = foo();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = bar();\n\tif( cryptStatusOK( status ) )\n\t\tstatus = baz();\n\tif( cryptStatusOK( status ) )\n\t\t...\n\n   These can be made more efficient when the compiler can assume that the\n   majority case has 'status == CRYPT_OK'.  gcc provides a means of doing \n   this via __builtin_expect().  As usual for gcc the documentation for this \n   is quite confusing:\n\n     \"if( __builtin_expect( x, 0 ) ) foo (); would indicate that we do not \n\t expect to call foo, since we expect x to be zero\"\n\n   In this case the test is actually the expression 'x', which is evaluated\n   as 'x != 0', with the second parameter only taking values 0 (to mean 'not\n   likely') or 1 (to mean 'likely').  So the appropriate usage is \n   \"__builtin_expect( expr, 0 )\" to mean that we don't expect something and \n   \"__builtin_expect( expr, 1 )\" to mean that we do expect it.  The \n   following forms of cryptStatusError() and cryptStatusOK() assume that in \n   the majority of situations we won't encounter the error case */\n\n#if defined( __GNUC__ ) && ( __GNUC__ >= 3 )\n  #undef cryptStatusError\n  #undef cryptStatusOK\n  #define cryptStatusError( status ) \\\n\t\t  __builtin_expect( ( status ) < CRYPT_OK, 0 )\n  #define cryptStatusOK( status ) \\\n\t\t  __builtin_expect( ( status ) == CRYPT_OK, 1 )\n#endif /* gcc 3.x and newer */\n\n/* Nucleus has it's own functions for allocating and freeing memory, so\n   we provide wrappers for them that override the default clAlloc()/clFree()\n   mappings */\n\n#ifdef __Nucleus__ \n  #define clAlloc( string, size )\t\tclAllocFn( size )\n  #define clFree( string, memblock )\tclFreeFn( memblock )\n  void *clAllocFn( size_t size );\n  void clFreeFn( void *memblock );\n#endif /* __Nucleus__ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDynamic Loading Support\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* On systems that support dynamic loading, we bind various drivers and\n   libraries at runtime rather than at compile time.  Under Windows this is\n   fairly easy but under Unix it's supported somewhat selectively and may be\n   buggy or platform-specific */\n\n#ifdef DYNAMIC_LOAD\n  /* Macros to map OS-specific dynamic-load values to generic ones */\n  #if defined( __WINDOWS__ )\n\t#define INSTANCE_HANDLE\t\tHINSTANCE\n\t#define NULL_INSTANCE\t\t( HINSTANCE ) NULL\n\t#ifdef __WINCE__\n\t  #define DynamicLoad( name ) LoadLibrary( name )\n\t#else\n\t  #define DynamicLoad( name ) SafeLoadLibrary( name )\n\t#endif /* Win32 vs. WinCE */\n\t#define DynamicUnload\t\tFreeLibrary\n\t#define DynamicBind\t\t\tGetProcAddress\n  #elif defined( __UNIX__ ) || defined( __ANDROID__ )\n    /* Older versions of OS X didn't have dlopen() support but required\n\t   the use of the rather painful low-level dyld() interface.  If you're\n\t   running an older version of OS X and don't have the dlcompat wrapper\n\t   installed, get Peter O'Gorman's dlopen() implementation, which wraps\n\t   the dyld() interface */\n\t#include <dlfcn.h>\n\t#define INSTANCE_HANDLE\t\tvoid *\n\t#define NULL_INSTANCE\t\tNULL\n\t#define DynamicLoad( name )\tdlopen( name, RTLD_LAZY )\n\t#define DynamicUnload\t\tdlclose\n\t#define DynamicBind\t\t\tdlsym\n  #elif defined __VMCMS__\n\t#include <dll.h>\n\n\t#define INSTANCE_HANDLE\t\tdllhandle *\n\t#define NULL_INSTANCE\t\tNULL\n\t#define DynamicLoad( name )\tdllload( name, RTLD_LAZY )\n\t#define DynamicUnload\t\tdllfree\n\t#define DynamicBind\t\t\tdlqueryfn\n  #endif /* OS-specific instance handles */\n#endif /* DYNAMIC_LOAD */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tCharset Support\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Widechar handling.  Most systems now support this, the only support that\n   we require is the wchar_t type define */\n\n#ifdef USE_WIDECHARS\n  #if !( defined( __ECOS__ ) || \\\n\t\t ( defined( __QNX__ ) && ( OSVERSION <= 4 ) ) || \\\n\t\t ( defined( __WIN32__ ) && defined( __BORLANDC__ ) ) || \\\n\t\t ( defined( __WINCE__ ) && _WIN32_WCE < 400 ) || \\\n\t\t defined( __XMK__ ) )\n\t#include <wchar.h>\n  #endif /* Systems with widechar support in stdlib.h */\n#else\n  /* No native widechar support, define the necesary types ourselves unless\n\t we're running under older OS X (Darwin 6.x), which defines wchar_t in\n\t stdlib.h even though there's no wchar support present, or PalmOS, which\n\t defines it in wchar.h but then defines it differently in stddef.h, and\n\t in any case has no wchar support present */\n  #if !( defined( __APPLE__ ) || defined( __MVS__ ) || \\\n\t\t defined( __OpenBSD__ ) || defined( __PALMOS__ ) || \\\n\t\t defined( __SMX__ ) )\n\ttypedef unsigned short int wchar_t;\n  #endif /* __APPLE__ */\n#endif /* USE_WIDECHARS */\n#define WCSIZE\t\t\t\t\t( sizeof( wchar_t ) )\n#ifndef WCHAR_MAX\n  #define WCHAR_MAX\t\t\t\t( ( wchar_t ) -1 )\n#endif /* !WCHAR_MAX */\n\n/* The EOL convention used when outputting text.  Technically speaking \n   Nucleus, SMX, and XMK don't use any particular EOL convention, but since \n   the typical development environment is debug output sent to a Windows \n   terminal emulator, we use CRLF */\n\n#if defined( __MSDOS16__ ) || defined( __MSDOS32__ ) || \\\n\tdefined( __Nucleus__ ) || defined( __OS2__ ) || \\\n\tdefined( __SMX__ ) || defined( __SYMBIAN32__ ) || \\\n\tdefined( __WINDOWS__ ) || defined( __XMK__ )\n  #define EOL\t\t\t\t\t\"\\r\\n\"\n  #define EOL_LEN\t\t\t\t2\n#elif ( defined( __APPLE__ ) && !defined( __MAC__ ) ) || \\\n\t  defined( __BEOS__ ) || defined( __IBM4758__ ) || \\\n\t  defined( __MVS__ ) || defined( __PALMOS__ ) || \\\n\t  defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ ) || \\\n\t  defined( __UNIX__ ) || defined( __VMCMS__ )\n  #define EOL\t\t\t\t\t\"\\n\"\n  #define EOL_LEN\t\t\t\t1\n#elif defined( __MAC__ )\n  #define EOL\t\t\t\t\t\"\\r\"\n  #define EOL_LEN\t\t\t\t1\n#elif defined( USE_EMBEDDED_OS )\n  /* For embedded OSes we assume a generic Unix-like text environment, these \n\t aren't exactly used for interactive operations like text editing so \n\t there's usually no fixed text format, and many will handle both CRLF \n\t and LF-only text, with the lowest common denominator being the Unix-\n\t style LF-only */\n  #define EOL\t\t\t\t\t\"\\n\"\n  #define EOL_LEN\t\t\t\t1\n#else\n  #error \"You need to add the OS-specific define to enable end-of-line handling\"\n#endif /* OS-specific EOL markers */\n\n/* If we're compiling on IBM mainframes, enable EBCDIC <-> ASCII string\n   conversion.  Since cryptlib uses ASCII internally for all strings, we\n   need to check to make sure it's been built with ASCII strings enabled\n   before we go any further */\n\n#ifdef EBCDIC_CHARS\n  #if 'A' != 0x41\n\t#error cryptlib must be compiled with ASCII literals\n  #endif /* Check for use of ASCII */\n\n  int asciiToEbcdic( char *dest, const char *src, const int length );\n  int ebcdicToAscii( char *dest, const char *src, const int length );\n  char *bufferToEbcdic( char *buffer, const char *string );\n  char *bufferToAscii( char *buffer, const char *string );\n#endif /* IBM mainframes */\n\n/* If we're compiling on Windows CE, enable Unicode <-> ASCII string\n   conversion */\n\n#ifdef UNICODE_CHARS\n  int asciiToUnicode( wchar_t *dest, const int destMaxLen, \n\t\t\t\t\t  const char *src, const int length );\n  int unicodeToAscii( char *dest, const int destMaxLen, \n\t\t\t\t\t  const wchar_t *src, const int length );\n#endif /* Windows CE */\n\n/* Since cryptlib uses ASCII internally, we have to force the use of\n   ASCII-compatible versions of system library functions if the system\n   uses EBCDIC */\n\n#ifdef EBCDIC_CHARS\n  #include <stdarg.h>\n\n  #define ASCII_ALPHA\t\t\t0x01\n  #define ASCII_LOWER\t\t\t0x02\n  #define ASCII_NUMERIC\t\t\t0x04\n  #define ASCII_SPACE\t\t\t0x08\n  #define ASCII_UPPER\t\t\t0x10\n  #define ASCII_HEX\t\t\t\t0x20\n  extern const BYTE asciiCtypeTbl[];\n\n  #define isAlnum( ch ) \\\n\t\t  ( asciiCtypeTbl[ byteToInt( ch ) ] & ( ASCII_ALPHA | ASCII_NUMERIC ) )\n  #define isAlpha( ch ) \\\n\t\t  ( asciiCtypeTbl[ byteToInt( ch ) ] & ASCII_ALPHA )\n  #define isDigit( ch ) \\\n\t\t  ( asciiCtypeTbl[ byteToInt( ch ) ] & ASCII_NUMERIC )\n  #define isPrint( ch ) \\\n\t\t  ( ( byteToInt( ch ) ) >= 0x20 && ( byteToInt( ch ) ) <= 0x7E )\n  #define isXDigit( ch ) \\\n\t\t  ( asciiCtypeTbl[ byteToInt( ch ) ] & ASCII_HEX )\n  #define toLower( ch ) \\\n\t\t  ( ( asciiCtypeTbl[ byteToInt( ch ) ] & ASCII_UPPER ) ? \\\n\t\t\t( byteToInt( ch ) ) + 32 : ( byteToInt( ch ) ) )\n  #define toUpper( ch ) \\\n\t\t  ( ( asciiCtypeTbl[ byteToInt( ch ) ] & ASCII_LOWER ) ? \\\n\t\t\t( byteToInt( ch ) ) - 32 : ( byteToInt( ch ) ) )\n\n  /* We can't annotate these functions because os_spec.h is pulled in before\n     analyse.h, so the required annotations don't exist yet */\n  int strCompare( const char *src, const char *dest, const int length );\n  int strCompareZ( const char *src, const char *dest );\n  int sPrintf_s( char *buffer, const int bufSize, const char *format, ... );\n  int vsPrintf_s( char *buffer, const int bufSize, const char *format, \n\t\t\t\t  va_list argPtr );\n  #define sprintf_s\t\t\t\tsPrintf_s\n  #define vsprintf_s\t\t\tvsPrintf_s\n#else\n  #if defined( __Nucleus__ )\n\t#include <nu_ctype.h>\n\t#include <nu_string.h>\n  #else\n\t#include <ctype.h>\n  #endif /* OS-specific includes */\n\n  #define isAlnum( ch )\t\t\tisalnum( byteToInt( ch ) )\n  #define isAlpha( ch )\t\t\tisalpha( byteToInt( ch ) )\n  #define isDigit( ch )\t\t\tisdigit( byteToInt( ch ) )\n  #define isPrint( ch )\t\t\tisprint( byteToInt( ch ) )\n  #define isXDigit( ch )\t\tisxdigit( byteToInt( ch ) )\n  #define toLower( ch )\t\t\ttolower( byteToInt( ch ) )\n  #define toUpper( ch )\t\t\ttoupper( byteToInt( ch ) )\n  #define strCompareZ( str1, str2 )\t\\\n\t\t\t\t\t\t\t\tstricmp( str1, str2 )\n  #define strCompare( str1, str2, len )\t\\\n\t\t\t\t\t\t\t\tstrnicmp( str1, str2, len )\n#endif /* EBCDIC_CHARS */\n\n/* SunOS and older Slowaris have broken sprintf() handling.  In SunOS 4.x\n   this was documented as returning a pointer to the output data as per the\n   Berkeley original.  Under Slowaris the manpage was changed so that it\n   looks like any other sprintf(), but it still returns the pointer to the\n   output buffer in some versions so we use a wrapper that checks at\n   runtime to see what we've got and adjusts its behaviour accordingly */\n\n#if defined( sun ) && ( OSVERSION <= 5 )\n  int fixedSprintf( char *buffer, const int bufSize,\n\t\t\t\t\tconst char *format, ... );\n\n  #undef sPrintf_s\n  #define sPrintf_s\t\t\t\tfixedSprintf\n#endif /* Old SunOS */\n\n/* Borland C++ before 5.50 doesn't have snprintf() or vsnprintf() */\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n  #include <stdarg.h>\n\n  int bcSnprintf( char *buffer, const int bufSize,\n\t\t\t\t  const char *format, ... );\n  int bcVsnprintf( char *buffer, const int bufSize,\n\t\t\t\t   const char *format, va_list argPtr );\n#endif /* BC++ before 5.50 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tTR 24731 Safe stdlib Extensions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* ISO/IEC TR 24731 defines alternative stdlib functions designed to perform\n   additional parameter checking and avoid some types of common buffer\n   overflows.  We use these if possible, if they're not available we map\n   them down to the traditional stdlib equivalents, via the preprocessor if\n   possible or using wrapper functions if not.  In addition we use the \n   OpenBSD et al strlcpy()/strlcat() functions, whose truncation semantics \n   make them more useful than the TR 24731 equivalents (for example \n   strcpy_s() does nothing on overflow while the equivalent strlcpy() copies\n   with truncation).  Microsoft recognise this as well, implementing them in\n   TR 24731 by allowing the caller to specify _TRUNCATE semantics */\n\n#ifdef __STDC_LIB_EXT1__\n  #if defined( _MSC_VER ) && VC_GE_2005( _MSC_VER )\n\t/* The VC++ implementation of TR 24731 is based on preliminary versions \n\t   of the design for the spec, and in some cases needs re-mapping onto \n\t   the final versions.  Instances of this are:\n   \n\t\tTR 24731: struct tm *gmtime_s( const time_t *timer, struct tm *result );\n\t\tVC++: errno_t gmtime_s( struct tm *result, const time_t timer );\n\n\t   Because this could potentially result in a circular definition, we \n\t   have to kludge in an intermediate layer by renaming the call to \n\t   gmTime_s(), which we then remap to the VC++ gmtime_s() */\n\t#define gmTime_s( timer, result )\t\\\n\t\t\t( ( gmtime_s( result, timer ) == 0 ) ? result : NULL )\n\n\t/* Complicating things further, the Windows DDK doesn't have gmtime_s(),\n\t   although it does have all of the other TR 24731 functions.  To handle\n\t   this, we use the same workaround as for the non-TR 24731 libcs */\n\t#ifdef WIN_DDK\n\t  #undef gmTime_s\n\t  #define gmTime_s( timer, result )\tgmtime( timer )\n\t#endif /* WIN_DDK */\n\n\t/* MS implements strlcpy/strlcat-equivalents via the TR 24731 \n\t   functions */\n\t#define strlcpy_s( s1, s1max, s2 )\tstrncpy_s( s1, s1max, s2, _TRUNCATE )\n\t#define strlcat_s( s1, s1max, s2 )\tstrncat_s( s1, s1max, s2, _TRUNCATE )\n  #else\n\t#define gmTime_s\t\t\t\t\tgmtime_s\n  #endif /* VC++ >= 2005 */\n#else\n  /* String functions.  The OpenBSD strlcpy()/strlcat() functions with their\n     truncation semantics are quite useful so we use these as well, \n\t overlaying them with a macro that make them match the TR 24731 look \n\t and feel */\n  #define strcpy_s( s1, s1max, s2 )\t\tstrcpy( s1, s2 )\n  #if defined( __UNIX__ ) && \\\n\t  ( defined( __APPLE__ ) || defined( __FreeBSD__ ) || \\\n\t\tdefined( __NetBSD__ ) || defined( __OpenBSD__ ) || \\\n\t\t( defined( sun ) && OSVERSION >= 7 ) )\n\t/* Despite the glibc maintainer's pigheaded opposition to these \n\t   functions, some Unix OSes support them via custom libc patches */\n\t#define strlcpy_s( s1, s1max, s2 )\tstrlcpy( s1, s2, s1max )\t\n\t#define strlcat_s( s1, s1max, s2 )\tstrlcat( s1, s2, s1max )\n  #else\n\tint strlcpy_s( char *dest, const int destLen, const char *src );\n\tint strlcat_s( char *dest, const int destLen, const char *src );\n\t#define NO_NATIVE_STRLCPY\n  #endif /* OpenBSD safe string functions */\n\n  /* Widechar functions */\n  int mbstowcs_s( size_t *retval, wchar_t *dst, size_t dstmax, \n\t\t\t\t  const char *src, size_t len );\n  int wcstombs_s( size_t *retval, char *dst, size_t dstmax, \n\t\t\t\t  const wchar_t *src, size_t len );\n  #if defined( USE_EMBEDDED_OS )\n    /* Support for the thread-safe mbtowc() is practially nonexistent in\n\t   embedded OSes, but in any case is unlikely to be necessary since\n\t   there'll likely only be a single task dealing with crypto */\n\t#define mbstate_t\t\tint\n\t#define mbrtowc( wideChar, char, size, state ) \\\n\t\t\tmbtowc( wideChar, char, size )\n  #elif defined( _MSC_VER ) && VC_LE_VC6( _MSC_VER ) \n\t/* VC++ 6.0 has mbrtowc() in wchar.h but not in libc, it's present in\n\t   the deprecated libcp/msvcp libraries but it's better to just map\n\t   it to mbtowc() since this is thread-safe under Windows anyway */\n\t#define mbrtowc( wideChar, char, size, state ) \\\n\t\t\tmbtowc( wideChar, char, size )\n  #endif /* Compiler-specific thread-safe mbtowc() support */\n\n  /* printf() */\n  #if defined( _MSC_VER ) && VC_LT_2005( _MSC_VER )\n    #include <stdio.h>\n\n\t#define sprintf_s\t\t\t\t\t_snprintf\n\t#define vsprintf_s\t\t\t\t\t_vsnprintf\n  #elif defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n\t#define sprintf_s\t\t\t\t\tbcSnprintf\n\t#define vsprintf_s\t\t\t\t\tbcVsnprintf\n  #elif defined( __QNX__ ) && ( OSVERSION <= 4 )\n\t/* snprintf() exists under QNX 4.x but causes a SIGSEGV when called */\n\t#define sprintf_s\t\t\t\t\t_bprintf\n\t#define vsnprintf\t\t\t\t\t_vbprintf\n  #elif defined( EBCDIC_CHARS )\n\t/* We provide our own replacements for these functions which handle \n\t   output in ASCII (rather than EBCDIC) form */\n  #else\n    #include <stdio.h>\n\n\t#define sprintf_s\t\t\t\t\tsnprintf\n\t#define vsprintf_s\t\t\t\t\tvsnprintf\n  #endif /* Compiler-specific safe printf() support */\n\n  /* Misc.functions.  gmtime() is an ugly non-thread-safe function that runs \n     into the same problems as gethostbyname() (see the long comment in \n\t io/tcp.h), to deal with this as best we can we map it to the reentrant \n\t gmtime_r() if it's available.  In addition some OSes use TLS for the\n\t result value so it's handled automatically, see again the comments in \n\t io/tcp.h for more on this */\n  #if defined( USE_THREADS ) && defined( __GLIBC__ ) && ( __GLIBC__ >= 2 ) \n\t#define gmTime_s\t\t\t\t\tgmtime_r\n  #elif defined( __MQXRTOS__ )\n\t#define gmTime_s\t\t\t\t\tgmtime_r\n  #else\n\t#define gmTime_s( timer, result )\tgmtime( timer )\n  #endif /* USE_THREADS and libraries that provide gmtime_r() */\n#endif /* TR 24731 safe stdlib extensions */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tMiscellaneous System-specific Support Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform various operations on pointers */\n\nvoid *ptr_align( const void *ptr, const int units );\nint ptr_diff( const void *ptr1, const void *ptr2 );\n\n/* Check whether a pointer is aligned to a particular value, used by some\n   low-level functions that check for potentially unaligned accesses and \n   clean them up if possible.  This is mostly a hygiene check in that if it\n   can't be easily implemented we continue anyway but with the possible \n   overhead of an unaligned-access fixup, thus the _OPT qualifier.\n   \n   The apparently redundant cast to void * before the uintptr_t is necessary \n   because the conversion is only guaranteed for a void *, so if it's some \n   other type of pointer then we have to cast it to a void * first */\n\n#if ( defined( __STDC_VERSION__ ) && ( __STDC_VERSION__ >= 199901L ) ) || \\\n\t( defined( _MSC_VER ) && VC_GE_2005( _MSC_VER ) )\n  #define IS_ALIGNED_OPT( pointer, value ) \\\n\t\t  ( ( ( uintptr_t )( const void * )( pointer ) ) % ( value ) == 0 )\n#else\n  #define IS_ALIGNED_OPT( pointer, value )\tTRUE\n#endif /* C99 check */\n\n/* Align a piece of data on a given boundary.  This is needed on some \n   architectures that fault on unaligned accesses if the fault handler \n   doesn't fix up the access.  This is only used in a handful of locations\n   where we're adding cookies to buffers, which in most cases are aligned\n   anyway due to the additional data surrounding them, the code doesn't \n   depend on it */\n\n#if defined( __GNUC__ ) || defined( __clang__ )\n  #ifdef SYSTEM_64BIT\n\t#define STACK_ALIGN_DATA\t__attribute__(( aligned( 8 ) ))\n  #else\n\t#define STACK_ALIGN_DATA\t__attribute__(( aligned( 4 ) ))\n  #endif /* 32- vs. 64-bit alignment */\n#else\n  #define STACK_ALIGN_DATA\n#endif /* Data-alignment defines */\n\n#endif /* _OSSPEC_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/pgp.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPGP Definitions Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _PGP_DEFINED\n\n#define _PGP_DEFINED\n\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n\n/* PGP packet types, encoded into the CTB */\n\ntypedef enum {\n\tPGP_PACKET_NONE,\t\t\t/* No packet type */\n\tPGP_PACKET_PKE,\t\t\t\t/* PKC-encrypted session key */\n\tPGP_PACKET_SIGNATURE,\t\t/* Signature */\n\tPGP_PACKET_SKE,\t\t\t\t/* Secret-key-encrypted session key */\n\tPGP_PACKET_SIGNATURE_ONEPASS,/* One-pass signature */\n\tPGP_PACKET_SECKEY,\t\t\t/* Secret key */\n\tPGP_PACKET_PUBKEY,\t\t\t/* Public key */\n\tPGP_PACKET_SECKEY_SUB,\t\t/* Secret key subkey */\n\tPGP_PACKET_COPR,\t\t\t/* Compressed data */\n\tPGP_PACKET_ENCR,\t\t\t/* Encrypted data */\n\tPGP_PACKET_MARKER,\t\t\t/* Obsolete marker packet */\n\tPGP_PACKET_DATA,\t\t\t/* Raw data */\n\tPGP_PACKET_TRUST,\t\t\t/* Trust information */\n\tPGP_PACKET_USERID,\t\t\t/* Userid */\n\tPGP_PACKET_PUBKEY_SUB,\t\t/* Public key subkey */\n\tPGP_PACKET_DUMMY1, PGP_PACKET_DUMMY2,\t/* 15, 16 unused */\n\tPGP_PACKET_USERATTR,\t\t/* User attributes */\n\tPGP_PACKET_ENCR_MDC,\t\t/* Encrypted data with MDC */\n\tPGP_PACKET_MDC,\t\t\t\t/* MDC */\n\tPGP_PACKET_LAST\t\t\t\t/* Last possible PGP packet type */\n\t} PGP_PACKET_TYPE;\n\n/* PGP signature subpacket types */\n\ntypedef enum {\n\tPGP_SUBPACKET_RESERVED_0,\t/* Reserved */\n\tPGP_SUBPACKET_RESERVED_1,\t/* Reserved */\n\tPGP_SUBPACKET_TIME,\t\t\t/* Signing time */\n\tPGP_SUBPACKET_EXPIRY_TIME,\t/* Signature expiry time */\n\tPGP_SUBPACKET_EXP_CERT,\t\t/* Exportable certification */\n\tPGP_SUBPACKET_TRUST_SIG,\t/* Trust signature */\n\tPGP_SUBPACKET_REGEX,\t\t/* Regular expression */\n\tPGP_SUBPACKET_REVOCABLE,\t/* Revocable */\n\tPGP_SUBPACKET_RESERVED_8,\t/* Reserved */\n\tPGP_SUBPACKET_KEY_EXP,\t\t/* Key expiration time */\n\tPGP_SUBPACKET_PLACEHOLDER,\t/* Placeholder */\n\tPGP_SUBPACKET_PREF_SYM,\t\t/* Preferred symmetric algorithms */\n\tPGP_SUBPACKET_REV_KEY,\t\t/* Revocation key  */\n\tPGP_SUBPACKET_RESERVED_13,\t/* Reserved */\n\tPGP_SUBPACKET_RESERVED_14,\t/* Reserved */\n\tPGP_SUBPACKET_RESERVED_15,\t/* Reserved */\n\tPGP_SUBPACKET_KEYID,\t\t/* Issuer key ID */\n\tPGP_SUBPACKET_RESERVED_17,\t/* Reserved */\n\tPGP_SUBPACKET_RESERVED_18,\t/* Reserved */\n\tPGP_SUBPACKET_RESERVED_19,\t/* Reserved */\n\tPGP_SUBPACKET_TYPEANDVALUE,\t/* Type-and-value pairs */\n\tPGP_SUBPACKET_PREF_HASH,\t/* Preferred hash algorithms */\n\tPGP_SUBPACKET_PREF_COPR,\t/* Preferred compression algorithms */\n\tPGP_SUBPACKET_KEYSVR_PREF,\t/* Key server preferences */\n\tPGP_SUBPACKET_PREF_KEY_SVR,\t/* Preferred key server */\n\tPGP_SUBPACKET_PRIMARY_USERID, /* Primary userID */\n\tPGP_SUBPACKET_POLICY_URI,\t/* Policy URI */\n\tPGP_SUBPACKET_KEY_FLAGS,\t/* Key flags */\n\tPGP_SUBPACKET_SIGNER_USERID, /* Signer's userID  */\n\tPGP_SUBPACKET_REV_REASON,\t/* Reason for revocation */\n\tPGP_SUBPACKET_FEATURES,\t\t/* Features */\n\tPGP_SUBPACKET_SIG_TARGET,\t/* Signature target */\n\tPGP_SUBPACKET_EMBED_SIGNATURE, /* Embedded signature */\n\tPGP_SUBPACKET_LAST\t\t\t/* Last valid subpacket type */\n\t} PGP_SUBPACKET_TYPE;\n\n/* A special-case packet type that denotes a signature that follows on from \n   a one-pass signature packet.  When generating a signature of this type PGP\n   splits the information in the normal signature packet across the one-pass\n   signature packet and the signature packet itself, so we have to read the \n   data on two parts, with half the information in the one-pass packet and \n   the other half in the signature packet */\n\n#define PGP_PACKET_SIGNATURE_SPECIAL\t1000\n\n/* The PGP packet format (via the CTB) is:\n\n\t+---------------+\n\t|7 6 5 4 3 2 1 0|\n\t+---------------+\n\n\tBit 7: Always one\n\tBit 6: OpenPGP (new) format if set\n\n\t\tPGP 2.x:\t\t\t\t\t\tOpenPGP:\n\tBits 5-2: Packet type\t\tBits 5-0: Packet type\n\tBits 1-0: Length type\n\n   All CTBs have the MSB set, and OpenPGP CTBs have the next-to-MSB set.  We \n   also have a special-case CTB that's used for indefinite-length compressed \n   data */\n\n#define PGP_CTB\t\t\t\t0x80\t/* PGP 2.x CTB template */\n#define PGP_CTB_OPENPGP\t\t0xC0\t/* OpenPGP CTB template */\n#define PGP_CTB_COMPRESSED\t0xA3\t/* Compressed indef-length data */\n\n/* Macros to extract packet information from the CTB */\n\n#define pgpIsCTB( ctb )\t\t\t\t( ( ctb ) & PGP_CTB )\n#define pgpGetPacketVersion( ctb ) \\\n\t\t( ( ( ( ctb ) & PGP_CTB_OPENPGP ) == PGP_CTB_OPENPGP ) ? \\\n\t\t  PGP_VERSION_OPENPGP : PGP_VERSION_2 )\n#define pgpGetPacketType( ctb ) \\\n\t\t( ( ( ( ctb ) & PGP_CTB_OPENPGP ) == PGP_CTB_OPENPGP ) ? \\\n\t\t\t( ( ctb ) & 0x3F ) : ( ( ( ctb ) >> 2 ) & 0x0F ) )\n#define pgpIsReservedPacket( type )\t( ( type ) >= 60 && ( type ) <= 63 )\n\n/* Version information */\n\n#define PGP_VERSION_2\t\t2\t\t/* Version number byte for PGP 2.0 */\n#define PGP_VERSION_3\t\t3\t\t/* Version number byte for legal-kludged PGP 2.0 */\n#define PGP_VERSION_OPENPGP\t4\t\t/* Version number for OpenPGP */\n\n/* Public-key algorithms */\n\n#define PGP_ALGO_RSA\t\t1\t\t/* RSA */\n#define PGP_ALGO_RSA_ENCRYPT 2\t\t/* RSA encrypt-only */\n#define PGP_ALGO_RSA_SIGN\t3\t\t/* RSA sign-only */\n#define PGP_ALGO_ELGAMAL\t16\t\t/* ElGamal */\n#define PGP_ALGO_DSA\t\t17\t\t/* DSA */\n#define PGP_ALGO_ECDH\t\t18\t\t/* RFC 4880: Rsvd.for \"ECC\", RFC 6637: ECDH */\n#define PGP_ALGO_ECDSA\t\t19\t\t/* RFC 4880: Rsvd.for ECDSA, RFC 6637: ECDSA */\n#define PGP_ALGO_PKC_RES1\t20\t\t/* Reserved, formerly Elgamal sign */\n#define PGP_ALGO_PKC_RES2\t21\t\t/* Reserved for \"X9.42\" */\n\n/* Conventional encryption algorithms */\n\n#define PGP_ALGO_NONE\t\t0\t\t/* No CKE algorithm */\n#define PGP_ALGO_IDEA\t\t1\t\t/* IDEA */\n#define PGP_ALGO_3DES\t\t2\t\t/* Triple DES */\n#define PGP_ALGO_CAST5\t\t3\t\t/* CAST-128 */\n#define PGP_ALGO_BLOWFISH\t4\t\t/* Blowfish */\n#define PGP_ALGO_ENC_RES1\t5\t\t/* Reserved, formerly Safer-SK */\n#define PGP_ALGO_ENC_RES2\t6\t\t/* Reserved */\n#define PGP_ALGO_AES_128\t7\t\t/* AES with 128-bit key */\n#define PGP_ALGO_AES_192\t8\t\t/* AES with 192-bit key */\n#define PGP_ALGO_AES_256\t9\t\t/* AES with 256-bit key */\n#define PGP_ALGO_TWOFISH\t10\t\t/* Twofish */\n\n/* Hash algorithms */\n\n#define PGP_ALGO_MD5\t\t1\t\t/* MD5 */\n#define PGP_ALGO_SHA\t\t2\t\t/* SHA-1 */\n#define PGP_ALGO_RIPEMD160\t3\t\t/* RIPEMD-160 */\n#define PGP_ALGO_HASH_RES1\t4\t\t/* Reserved */\n#define PGP_ALGO_HASH_RES2\t5\t\t/* Reserved, formerly MD2 */\n#define PGP_ALGO_HASH_RES3\t6\t\t/* Reserved, formerly Tiger/192 */\n#define PGP_ALGO_HASH_RES4\t7\t\t/* Reserved, formerly Haval */\n#define PGP_ALGO_SHA2_256\t8\t\t/* SHA-2 256bit */\n#define PGP_ALGO_SHA2_384\t9\t\t/* SHA-2 384bit */\n#define PGP_ALGO_SHA2_512\t10\t\t/* SHA-2 512bit */\n#define PGP_ALGO_SHA2_224\t11\t\t/* SHA-2 224bit */\n#define PGP_ALGO_SHAng\t\t99\t\t/* Future SHA-nextgen standard */\n\n/* Compression algorithms */\n\n#define PGP_ALGO_ZIP\t\t1\t\t/* ZIP compression */\n#define PGP_ALGO_ZLIB\t\t2\t\t/* zlib compression */\n#define PGP_ALGO_BZIP2\t\t3\t\t/* Bzip2 compression */\n\n/* Highest possible algorithm value used by cryptlib, for range checking */\n\n#define PGP_ALGO_LAST\t\tPGP_ALGO_ECDSA\n\n/* S2K specifier */\n\n#define PGP_S2K\t\t\t\t0xFF\t/* Standard S2K */\n#define PGP_S2K_HASHED\t\t0xFE\t/* S2K with hashed key */\n\n/* Signature types */\n\n#define PGP_SIG_NONE\t\t0x00\t/* Same as PGP_SIG_DATA, for range chk.*/\n#define PGP_SIG_DATA\t\t0x00\t/* Binary data */\n#define PGP_SIG_TEXT\t\t0x01\t/* Canonicalised text data */\n#define PGP_SIG_STANDALONE\t0x02\t/* Unknown purpose, from RFC 4880 */\n#define\tPGP_SIG_CERT0\t\t0x10\t/* Key certificate, unknown assurance */\n#define\tPGP_SIG_CERT1\t\t0x11\t/* Key certificate, no assurance */\n#define\tPGP_SIG_CERT2\t\t0x12\t/* Key certificate, casual assurance */\n#define\tPGP_SIG_CERT3\t\t0x13\t/* Key certificate, strong assurance */\n#define PGP_SIG_SUBKEY\t\t0x18\t/* Subkey binding signature */\n#define PGP_SIG_PRIMKEY\t\t0x19\t/* Primary key binding signature */\n#define PGP_SIG_DIRECTKEY\t0x1F\t/* Key self-signature */\n#define PGP_SIG_KEYREV\t\t0x20\t/* Key revocation */\n#define PGP_SIG_SUBKEYREV\t0x28\t/* Subkey revocation */\n#define PGP_SIG_CRL\t\t\t0x30\t/* Certificate revocation */\n#define\tPGP_SIG_TS\t\t\t0x40\t/* Timestamp signature */\n#define\tPGP_SIG_COUNTERSIG\t0x50\t/* Third-party countersignature */\n#define PGP_SIG_LAST\t\t0x51\t/* Last possible signature type */\n\n/* The size of the PGP version ID and algorithm ID */\n\n#define PGP_VERSION_SIZE\t1\n#define PGP_ALGOID_SIZE\t\t1\n\n/* The maximum size of a PGP user ID.  Note that this is larger than the\n   cryptlib-wide maximum user ID size */\n\n#define PGP_MAX_USERIDSIZE\t256\n\n/* The size of the salt used for password hashing and the number of \n   setup \"iterations\".  This isn't a true iteration count but the number of \n   salt+password bytes hashed, and in fact it isn't even that but the\n   actual count scaled by dividing it by 64, which is how PGP encodes the\n   count in the data packet */\n\n#define PGP_SALTSIZE\t\t8\n#define PGP_ITERATIONS\t\t1024\n\n/* Various PGP packet header sizes, used to estimate how much data we still \n   need to process */\n\n#define PGP_MIN_HEADER_SIZE\t2\t\t/* CTB + length */\n#define PGP_MAX_HEADER_SIZE\t6\t\t/* CTB + 0xFF + 4-byte length */\n#define PGP_DATA_HEADER\t\t\"b\\x00\\x00\\x00\\x00\\x00\"\n#define PGP_DATA_HEADER_SIZE ( 1 + 1 + 4 )\n#define PGP_MDC_PACKET_SIZE\t( 1 + 1 + 20 )\t/* Size of MDC packet */\n\n/* Since PGP only provides a subset of cryptlib's algorithm types and uses\n   different identifiers, we have to both check that there's a mapping\n   possible and map from one to the other.  When going from PGP -> cryptlib\n   we specify both the algorithm ID and the algorithm class we expect to \n   find it in to allow type checking */\n\ntypedef enum {\n\tPGP_ALGOCLASS_NONE,\t\t/* No algorithm class */\n\tPGP_ALGOCLASS_CRYPT,\t/* Conventional encryption algorithms */\n\tPGP_ALGOCLASS_PWCRYPT,\t/* Password-based encryption algorithms */\n\tPGP_ALGOCLASS_PKCCRYPT,\t/* PKC algorithms */\n\tPGP_ALGOCLASS_SIGN,\t\t/* Signature algorithms */\n\tPGP_ALGOCLASS_HASH,\t\t/* Hash algorithms */\n\tPGP_ALGOCLASS_LAST\t\t/* Last possible algorithm class */\n\t} PGP_ALGOCLASS_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint pgpToCryptlibAlgo( IN_RANGE( PGP_ALGO_NONE, 0xFF ) const int pgpAlgo, \n\t\t\t\t\t   IN_ENUM( PGP_ALGOCLASS ) \\\n\t\t\t\t\t\t\tconst PGP_ALGOCLASS_TYPE pgpAlgoClass,\n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t   OUT_OPT_INT_Z int *cryptAlgoParam );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint cryptlibToPgpAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptlibAlgo,\n\t\t\t\t\t   OUT_RANGE( PGP_ALGO_NONE, PGP_ALGO_LAST ) \\\n\t\t\t\t\t\t\tint *pgpAlgo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPgpAlgo( INOUT STREAM *stream, \n\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo, \n\t\t\t\t OUT_OPT_INT_Z int *cryptAlgoParam,\n\t\t\t\t IN_ENUM( PGP_ALGOCLASS ) \\\n\t\t\t\t\t\tconst PGP_ALGOCLASS_TYPE pgpAlgoClass );\n\n/* Prototypes for functions in pgp_misc.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint pgpPasswordToKey( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int optKeyLength,\n\t\t\t\t\t  IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t  IN_DATALENGTH const int passwordLength, \n\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo, \n\t\t\t\t\t  IN_BUFFER_OPT( saltSize ) const BYTE *salt, \n\t\t\t\t\t  IN_RANGE( 0, CRYPT_MAX_HASHSIZE ) const int saltSize,\n\t\t\t\t\t  IN_INT const int iterations );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint pgpProcessIV( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t  INOUT_BUFFER_FIXED( ivInfoSize ) BYTE *ivInfo, \n\t\t\t\t  IN_RANGE( 8 + 2, CRYPT_MAX_IVSIZE + 2 ) \\\n\t\t\t\t\t\tconst int ivInfoSize, \n\t\t\t\t  IN_LENGTH_IV const int ivDataSize, \n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iMdcContext,\n\t\t\t\t  const BOOLEAN isEncrypt );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \\\nint readPgpS2K( INOUT STREAM *stream, \n\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,\n\t\t\t\tOUT_INT_Z int *hashAlgoParam,\n\t\t\t\tOUT_BUFFER( saltMaxLen, *saltLen ) BYTE *salt, \n\t\t\t\tIN_LENGTH_SHORT_MIN( PGP_SALTSIZE ) const int saltMaxLen, \n\t\t\t\tOUT_LENGTH_BOUNDED_Z( saltMaxLen ) int *saltLen,\n\t\t\t\tOUT_INT_SHORT_Z int *iterations );\n\n#endif /* _PGP_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/pgp_misc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t  PGP Support Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1992-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"pgp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"misc/pgp.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_PGP ) || defined( USE_PGPKEYS )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPGP <-> Cryptlib Algorithm Conversion\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert algorithm IDs from cryptlib to PGP and back */\n\ntypedef struct {\n\tconst int pgpAlgo;\n\tconst PGP_ALGOCLASS_TYPE pgpAlgoClass;\n\tconst CRYPT_ALGO_TYPE cryptlibAlgo;\n\tconst int cryptlibAlgoParam;\n\t} PGP_ALGOMAP_INFO;\nstatic const PGP_ALGOMAP_INFO pgpAlgoMap[] = {\n\t/* Encryption algos */\n#ifdef USE_3DES\n\t{ PGP_ALGO_3DES, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_3DES },\n#endif /* USE_3DES */\n#ifdef USE_CAST\n\t{ PGP_ALGO_CAST5, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_CAST },\n#endif /* USE_CAST */\n#ifdef USE_IDEA\n\t{ PGP_ALGO_IDEA, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_IDEA },\n#endif /* USE_IDEA */\n\t{ PGP_ALGO_AES_128, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_AES },\n\t{ PGP_ALGO_AES_192, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_AES },\n\t{ PGP_ALGO_AES_256, PGP_ALGOCLASS_CRYPT, CRYPT_ALGO_AES },\n\n\t/* Password-based encryption algos */\n#ifdef USE_3DES\n\t{ PGP_ALGO_3DES, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_3DES },\n#endif /* USE_3DES */\n#ifdef USE_CAST\n\t{ PGP_ALGO_CAST5, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_CAST },\n#endif /* USE_CAST */\n#ifdef USE_IDEA\n\t{ PGP_ALGO_IDEA, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_IDEA },\n#endif /* USE_IDEA */\n\t{ PGP_ALGO_AES_128, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_AES, 16 },\n\t{ PGP_ALGO_AES_192, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_AES, 24 },\n\t{ PGP_ALGO_AES_256, PGP_ALGOCLASS_PWCRYPT, CRYPT_ALGO_AES, 32 },\n\n\t/* PKC encryption algos */\n\t{ PGP_ALGO_RSA, PGP_ALGOCLASS_PKCCRYPT, CRYPT_ALGO_RSA },\n\t{ PGP_ALGO_RSA_ENCRYPT, PGP_ALGOCLASS_PKCCRYPT, CRYPT_ALGO_RSA },\n#ifdef USE_ELGAMAL\n\t{ PGP_ALGO_ELGAMAL, PGP_ALGOCLASS_PKCCRYPT, CRYPT_ALGO_ELGAMAL },\n#endif /* USE_ELGAMAL */\n\n\t/* PKC sig algos */\n\t{ PGP_ALGO_RSA, PGP_ALGOCLASS_SIGN, CRYPT_ALGO_RSA },\n\t{ PGP_ALGO_RSA_SIGN, PGP_ALGOCLASS_SIGN, CRYPT_ALGO_RSA },\n#ifdef USE_DSA\n\t{ PGP_ALGO_DSA, PGP_ALGOCLASS_SIGN, CRYPT_ALGO_DSA },\n#endif /* USE_DSA */\n\n\t/* Hash algos */\n#ifdef USE_MD5\n\t{ PGP_ALGO_MD5, PGP_ALGOCLASS_HASH, CRYPT_ALGO_MD5 },\n#endif /* USE_MD5 */\n\t{ PGP_ALGO_SHA, PGP_ALGOCLASS_HASH, CRYPT_ALGO_SHA1 },\n\t{ PGP_ALGO_SHA2_256, PGP_ALGOCLASS_HASH, CRYPT_ALGO_SHA2, 32 },\n\n\t{ PGP_ALGO_NONE, 0, CRYPT_ALGO_NONE },\n\t{ PGP_ALGO_NONE, 0, CRYPT_ALGO_NONE }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint pgpToCryptlibAlgo( IN_RANGE( PGP_ALGO_NONE, 0xFF ) const int pgpAlgo, \n\t\t\t\t\t   IN_ENUM( PGP_ALGOCLASS ) \\\n\t\t\t\t\t\t\tconst PGP_ALGOCLASS_TYPE pgpAlgoClass,\n\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo,\n\t\t\t\t\t   OUT_OPT_INT_Z int *cryptAlgoParam )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( cryptAlgoParam == NULL || \\\n\t\t\tisWritePtr( cryptAlgoParam, sizeof( int ) ) );\n\n\tREQUIRES( pgpAlgo >= 0 && pgpAlgo <= 0xFF );\n\tREQUIRES( isEnumRange( pgpAlgoClass, PGP_ALGOCLASS ) );\n\n\t/* Clear return values */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\tif( cryptAlgoParam != NULL )\n\t\t*cryptAlgoParam = 0;\n\n\tLOOP_MED( i = 0,\n\t\t\t  ( pgpAlgoMap[ i ].pgpAlgo != pgpAlgo || \\\n\t\t\t\tpgpAlgoMap[ i ].pgpAlgoClass != pgpAlgoClass ) && \\\n\t\t\t  pgpAlgoMap[ i ].pgpAlgo != PGP_ALGO_NONE && \\\n\t\t\t  i < FAILSAFE_ARRAYSIZE( pgpAlgoMap, PGP_ALGOMAP_INFO ), \n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( pgpAlgoMap, PGP_ALGOMAP_INFO ) );\n\tif( pgpAlgoMap[ i ].cryptlibAlgo == PGP_ALGO_NONE )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t*cryptAlgo = pgpAlgoMap[ i ].cryptlibAlgo;\n\tif( cryptAlgoParam != NULL )\n\t\t*cryptAlgoParam = pgpAlgoMap[ i ].cryptlibAlgoParam;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint cryptlibToPgpAlgo( IN_ALGO const CRYPT_ALGO_TYPE cryptlibAlgo,\n\t\t\t\t\t   OUT_RANGE( PGP_ALGO_NONE, PGP_ALGO_LAST ) \\\n\t\t\t\t\t\t\tint *pgpAlgo )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( pgpAlgo, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( cryptlibAlgo, CRYPT_ALGO ) );\n\n\t/* Clear return value */\n\t*pgpAlgo = PGP_ALGO_NONE;\n\n\tLOOP_MED( i = 0, \n\t\t\t  pgpAlgoMap[ i ].cryptlibAlgo != cryptlibAlgo && \\\n\t\t\t  pgpAlgoMap[ i ].cryptlibAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t  i < FAILSAFE_ARRAYSIZE( pgpAlgoMap, PGP_ALGOMAP_INFO ), \n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( pgpAlgoMap, PGP_ALGOMAP_INFO ) );\n\tif( pgpAlgoMap[ i ].cryptlibAlgo == CRYPT_ALGO_NONE )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t*pgpAlgo = pgpAlgoMap[ i ].pgpAlgo;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPgpAlgo( INOUT STREAM *stream, \n\t\t\t\t OUT_ALGO_Z CRYPT_ALGO_TYPE *cryptAlgo, \n\t\t\t\t OUT_OPT_INT_Z int *cryptAlgoParam,\n\t\t\t\t IN_ENUM( PGP_ALGOCLASS ) \\\n\t\t\t\t\t\tconst PGP_ALGOCLASS_TYPE pgpAlgoClass )\n\t{\n\tint value;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( cryptAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( cryptAlgoParam == NULL || \\\n\t\t\tisWritePtr( cryptAlgoParam, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( pgpAlgoClass, PGP_ALGOCLASS ) );\n\n\t/* Clear return values */\n\t*cryptAlgo = CRYPT_ALGO_NONE;\n\tif( cryptAlgoParam != NULL )\n\t\t*cryptAlgoParam = 0;\n\n\tvalue = sgetc( stream );\n\tif( cryptStatusError( value ) )\n\t\treturn( value );\n\treturn( pgpToCryptlibAlgo( value, pgpAlgoClass, cryptAlgo, \n\t\t\t\t\t\t\t   cryptAlgoParam ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMisc. PGP-related Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create an encryption key from a password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint pgpPasswordToKey( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int optKeyLength,\n\t\t\t\t\t  IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t  IN_DATALENGTH const int passwordLength, \n\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo, \n\t\t\t\t\t  IN_BUFFER_OPT( saltSize ) const BYTE *salt, \n\t\t\t\t\t  IN_RANGE( 0, CRYPT_MAX_HASHSIZE ) const int saltSize,\n\t\t\t\t\t  IN_INT const int iterations )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE hashedKey[ CRYPT_MAX_KEYSIZE + 8 ];\n\tint algorithm, keySize DUMMY_INIT, status;\t/* int vs.enum */\n\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( ( salt == NULL && saltSize == 0 ) || \\\n\t\t\tisReadPtrDynamic( salt, saltSize ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( passwordLength > 0 && passwordLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( optKeyLength == CRYPT_UNUSED ) || \\\n\t\t\t  ( optKeyLength >= MIN_KEYSIZE && \\\n\t\t\t\toptKeyLength <= CRYPT_MAX_KEYSIZE ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( ( salt == NULL && saltSize == 0 ) || \\\n\t\t\t  ( saltSize > 0 && saltSize <= CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( isIntegerRange( iterations ) );\n\n\t/* Get various parameters needed to process the password */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &keySize, CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( algorithm == CRYPT_ALGO_AES && optKeyLength != CRYPT_UNUSED )\n\t\t{\n\t\t/* PGP allows various AES key sizes and then encodes the size in the\n\t\t   algorithm ID (ugh), to handle this we allow the caller to specify\n\t\t   the actual size */\n\t\tkeySize = optKeyLength;\n\t\t}\n\tENSURES( keySize >= MIN_KEYSIZE && keySize <= CRYPT_MAX_KEYSIZE );\n\n\t/* Hash the password */\n\tif( salt != NULL )\n\t\t{\n\t\tMECHANISM_DERIVE_INFO mechanismInfo;\n\n\t\t/* Turn the user key into an encryption context key */\n\t\tsetMechanismDeriveInfo( &mechanismInfo, hashedKey, keySize,\n\t\t\t\t\t\t\t\tpassword, passwordLength, hashAlgo,\n\t\t\t\t\t\t\t\tsalt, saltSize, iterations );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_PGP );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Save the derivation info with the context */\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) salt, saltSize );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEYING_SALT );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\titerations > 0 && iterations <= MAX_KEYSETUP_ITERATIONS )\n\t\t\t{\n\t\t\t/* The number of key setup iterations may be zero for non-\n\t\t\t   iterated hashing, and may be some ridiculous value for \n\t\t\t   passwords used to protect private keys created by newer \n\t\t\t   versions of GPG.  In the former case we leave the iteration \n\t\t\t   count at zero, in the latter case we don't have to set the \n\t\t\t   iteration count (or indeed any of the key setup values) \n\t\t\t   because for private-key decryption keys they're never used \n\t\t\t   once the user key has been converted into the decryption\n\t\t\t   key */\n\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &iterations, \n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ITERATIONS );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst int value = hashAlgo;\t/* int vs.enum */\n\t\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &value, \n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_ALGO );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( hashedKey, CRYPT_MAX_KEYSIZE );\n\t\t\treturn( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\n\t\tgetHashAtomicParameters( hashAlgo, 0, &hashFunctionAtomic, NULL );\n\t\thashFunctionAtomic( hashedKey, CRYPT_MAX_HASHSIZE, password, \n\t\t\t\t\t\t\tpasswordLength );\n\t\t}\n\n\t/* Load the key into the context */\n\tsetMessageData( &msgData, hashedKey, keySize );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\tzeroise( hashedKey, CRYPT_MAX_KEYSIZE );\n\n\treturn( status );\n\t}\n\n/* Process a PGP-style IV.  This isn't a standard IV but contains an extra\n   two bytes of check value, which is why it's denoted as 'ivInfo' rather\n   than a pure 'iv' */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint pgpProcessIV( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t  INOUT_BUFFER_FIXED( ivInfoSize ) BYTE *ivInfo, \n\t\t\t\t  IN_RANGE( MIN_IVSIZE + 2, CRYPT_MAX_IVSIZE + 2 ) const int ivInfoSize, \n\t\t\t\t  IN_LENGTH_IV const int ivDataSize, \n\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iMdcContext,\n\t\t\t\t  const BOOLEAN isEncrypt )\n\t{\n\tstatic const BYTE zeroIV[ CRYPT_MAX_IVSIZE ] = { 0 };\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtrDynamic( ivInfo, ivInfoSize ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( ivDataSize >= MIN_IVSIZE && ivDataSize <= CRYPT_MAX_IVSIZE );\n\tREQUIRES( ivInfoSize == ivDataSize + 2 );\n\tREQUIRES( iMdcContext == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isEncrypt == TRUE || isEncrypt == FALSE );\n\n\t/* PGP uses a bizarre way of handling IVs that resyncs the data on some \n\t   boundaries and doesn't actually use an IV but instead prefixes the \n\t   data with ivSize bytes of random information (which is effectively \n\t   the IV) followed by two bytes of key check value after which there's a\n\t   resync boundary that requires reloading the IV from the last ivSize\n\t   bytes of ciphertext.  Two exceptions are the encrypted private key,\n\t   which does use an IV (although this can also be regarded as an\n\t   ivSize-byte prefix) without a key check or resync, and an encrypted \n\t   packet with MDC, which doesn't do the resync (if it weren't for that \n\t   it would be trivial to roll an MDC packet back to a non-MDC packet, \n\t   only the non-resync prevents this since the first bytes of the\n\t   encapsulated data packet will be corrupted).\n\t   \n\t   First, we load the all-zero IV */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) zeroIV, ivDataSize );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Then we encrypt or decrypt the IV info, which consists of the actual \n\t   IV data plus two bytes of check value */\n\tif( isEncrypt )\n\t\t{\n\t\t/* Get some random data to serve as the IV and duplicate the last \n\t\t   two bytes to create the check value */\n\t\tsetMessageData( &msgData, ivInfo, ivDataSize );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tmemcpy( ivInfo + ivDataSize, ivInfo + ivDataSize - 2, 2 );\n\n\t\t/* If the caller is using an MDC then the plaintext IV data has to \n\t\t   be hashed into the MDC value, effectively turning the straight \n\t\t   hash into a basic secret-prefix MAC */\n\t\tif( iMdcContext != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iMdcContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t\t  ivInfo, ivInfoSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Encrypt the IV and check value */\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  ivInfo, ivInfoSize );\n\t\t}\n\telse\n\t\t{\n\t\tBYTE ivInfoBuffer[ CRYPT_MAX_IVSIZE + 2 + 8 ];\n\n\t\t/* Decrypt the first ivSize bytes (the IV data) and the following 2-\n\t\t   byte check value.  There's a potential problem here in which an \n\t\t   attacker that convinces us to act as an oracle for the valid/not\n\t\t   valid status of the checksum can determine the contents of 16\n\t\t   bits of the encrypted data in 2^15 queries on average.  This is\n\t\t   incredibly unlikely (which implementation would auto-respond to\n\t\t   32,000 reqpeated queries on a block of data and return the \n\t\t   results to an external agent?), however if it's a concern then \n\t\t   one ameliorating change would be to not perform the check for \n\t\t   keys that were PKC-encrypted, because the PKC decryption process\n\t\t   would check the key for us */\n\t\tREQUIRES( rangeCheck( ivInfoSize, 1, CRYPT_MAX_IVSIZE + 2 ) );\n\t\tmemcpy( ivInfoBuffer, ivInfo, ivInfoSize );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t  ivInfoBuffer, ivInfoSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( ivInfoBuffer[ ivDataSize - 2 ] != ivInfoBuffer[ ivDataSize + 0 ] || \\\n\t\t\tivInfoBuffer[ ivDataSize - 1 ] != ivInfoBuffer[ ivDataSize + 1 ] )\n\t\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t\t/* If the caller is using an MDC then the plaintext IV data has to \n\t\t   be hashed into the MDC value, effectively turning the straight \n\t\t   hash into a basic secret-prefix MAC */\n\t\tif( iMdcContext != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iMdcContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t\t  ivInfoBuffer, ivInfoSize );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* The IV-resync is only done if traditional PGP encryption is used, the \n\t   processing was changed when MDC handling was added to skip this step, \n\t   so we only perform the resync if we're using non-MDC encryption */\n\tif( iMdcContext != CRYPT_UNUSED )\n\t\treturn( CRYPT_OK );\n\n\t/* Finally we've got the data the way that we want it, resync the IV by\n\t   setting it to the last ivSize bytes of data processed */\n\tsetMessageData( &msgData, ivInfo + 2, ivDataSize );\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_CTXINFO_IV ) );\n\t}\n\n/* Read PGP S2K information:\n\n\tbyte\tstringToKey specifier, 0, 1, or 3\n\tbyte[]\tstringToKey data\n\t\t\t0x00: byte\t\thashAlgo\t-- S2K = 0, 1, 3\n\t\t\t0x01: byte[8]\tsalt\t\t-- S2K = 1, 3\n\t\t\t0x03: byte\t\titerations\t-- S2K = 3 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \\\nint readPgpS2K( INOUT STREAM *stream, \n\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *hashAlgo,\n\t\t\t\tOUT_INT_Z int *hashAlgoParam,\n\t\t\t\tOUT_BUFFER( saltMaxLen, *saltLen ) BYTE *salt, \n\t\t\t\tIN_LENGTH_SHORT_MIN( PGP_SALTSIZE ) const int saltMaxLen, \n\t\t\t\tOUT_LENGTH_BOUNDED_Z( saltMaxLen ) int *saltLen,\n\t\t\t\tOUT_INT_SHORT_Z int *iterations )\n\t{\n\tlong hashSpecifier;\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( hashAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtrDynamic( salt, saltMaxLen ) );\n\tassert( isWritePtr( saltLen, sizeof( int ) ) );\n\tassert( isWritePtr( iterations, sizeof( int ) ) );\n\n\tREQUIRES( saltMaxLen >= PGP_SALTSIZE && \\\n\t\t\t  saltMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*hashAlgo = CRYPT_ALGO_NONE;\n\t*hashAlgoParam = 0;\n\tmemset( salt, 0, min( 16, saltMaxLen ) );\n\t*saltLen = 0;\n\t*iterations = 0;\n\n\t/* Read the S2K information */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != 0 && value != 1 && value != 3 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = readPgpAlgo( stream, hashAlgo, hashAlgoParam, \n\t\t\t\t\t\t  PGP_ALGOCLASS_HASH );\n\tif( cryptStatusError( status ) )\n\t\t return( status );\n\n\t/* If it's a straight hash, we're done */\n\tif( value <= 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* It's a salted hash, read the salt */\n\tstatus = sread( stream, salt, saltMaxLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*saltLen = PGP_SALTSIZE;\n\n\t/* If it's a non-iterated hash, we're done */\n\tif( value < 3 )\n\t\treturn( CRYPT_OK );\n\n\t/* It's a salted iterated hash, get the iteration count from the bizarre \n\t   fixed-point encoded value, limited to a sane value:\n\n\t\tcount = ( ( Int32 ) 16 + ( c & 15 ) ) << ( ( c >> 4 ) + 6 )\n\t   \n\t   The \"iteration count\" is actually a count of how many bytes are \n\t   hashed, this is because the \"iterated hashing\" treats the salt + \n\t   password as an infinitely-repeated sequence of values and hashes the \n\t   resulting string for PGP-iteration-count bytes worth.  The value that \n\t   we calculate here (to prevent overflow on 16-bit machines) is the \n\t   count without the base * 64 scaling, this also puts the range within \n\t   the value of the standard sanity check.  When we do the range check \n\t   we knock a further four bits off the maximum allowed length to avoid \n\t   performing calculations too close to INT_MAX in the S2K code.\n\n\t   See the long comment for MAX_KEYSETUP_HASHSPECIFIER in misc/consts.h\n\t   for more on the checking performed here */\n\tvalue = sgetc( stream );\n\tif( cryptStatusError( value ) )\n\t\treturn( value );\n\thashSpecifier = ( 16 + ( ( long ) value & 0x0F ) ) << ( value >> 4 );\n\tif( hashSpecifier <= 0 || \\\n\t\thashSpecifier >= ( MAX_INTLENGTH >> 4 ) / 64 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tif( hashSpecifier > MAX_KEYSETUP_HASHSPECIFIER )\n\t\t{\n\t\t/* The key requires hashing a ridiculous amount of data, this is \n\t\t   more likely a DoS than a genuine hash count */\n\t\tDEBUG_DIAG(( \"Encountered key with an S2K hash count parameter \"\n\t\t\t\t\t \"of %ld, max.allowed is %ld\", hashSpecifier * 64,\n\t\t\t\t\t MAX_KEYSETUP_HASHSPECIFIER * 64 ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tENSURES( isIntegerRange( hashSpecifier ) );\n\t*iterations = ( int ) hashSpecifier;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_PGP || USE_PGPKEYS */\n"
  },
  {
    "path": "deps/cl345/misc/rpc.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib RPC Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2001\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _RPC_DEFINED\n\n#define _RPC_DEFINED\n\n/* Each message when encoded looks as follows:\n\n\ttype\t\t\t: 8\n\tflags\t\t\t: 8\n\tnoArgs\t\t\t: 8\n\tnoStringArgs\t: 8\n\tlength\t\t\t: 32\n\targ * 0..n\t\t: 32 * n\n\tstringArg * 0..n: 32 + data * n\n\n   The fixed header consists of a 32-bit type+format information value and\n   length (to allow the entire message to be read using only two read calls)\n   followed by 1 - MAX_ARGS integer args and 0 - MAX_STRING_ARGS variable-\n   length data args.  The protocol is completely stateless, the client sends\n   COMMAND_xxx requests to the server and the server responds with\n   COMMAND_RESULT messages */\n\n/* cryptlib API commands */\n\ntypedef enum {\n\tCOMMAND_NONE,\t\t\t\t/* No command type */\n\tCOMMAND_RESULT,\t\t\t\t/* Result from server */\n\tCOMMAND_SERVERQUERY,\t\t/* Get info on server */\n\tCOMMAND_CREATEOBJECT,\t\t/* Create an object */\n\tCOMMAND_CREATEOBJECT_INDIRECT,\t/* Create an object indirectly */\n\tCOMMAND_EXPORTOBJECT,\t\t/* Export object in encoded form */\n\tCOMMAND_DESTROYOBJECT,\t\t/* Destroy an object */\n\tCOMMAND_QUERYCAPABILITY,\t/* Query capabilities */\n\tCOMMAND_GENKEY,\t\t\t\t/* Generate key */\n\tCOMMAND_ENCRYPT,\t\t\t/* Encrypt/sign/hash */\n\tCOMMAND_DECRYPT,\t\t\t/* Decrypt/sig check/hash */\n\tCOMMAND_GETATTRIBUTE,\t\t/* Get/set/delete attribute */\n\tCOMMAND_SETATTRIBUTE,\n\tCOMMAND_DELETEATTRIBUTE,\n\tCOMMAND_GETKEY,\t\t\t\t/* Get/set/delete key */\n\tCOMMAND_SETKEY,\n\tCOMMAND_DELETEKEY,\n\tCOMMAND_PUSHDATA,\n\tCOMMAND_POPDATA,\n\tCOMMAND_FLUSHDATA,\t\t\t/* Push/pop/flush data */\n\tCOMMAND_CERTSIGN,\t\t\t/* Sign certificate */\n\tCOMMAND_CERTCHECK,\t\t\t/* Check signature on certificate */\n\tCOMMAND_CERTMGMT,\t\t\t/* CA cert management operation */\n\tCOMMAND_LAST\t\t\t\t/* Last command type */\n\t} COMMAND_TYPE;\n\n/* Database shim commands */\n\ntypedef enum {\n\tDBX_COMMAND_NONE,\t\t\t/* No command type */\n\tDBX_COMMAND_RESULT,\t\t\t/* Result from server (== COMAND_RESULT) */\n\tDBX_COMMAND_OPEN,\t\t\t/* Open session with database */\n\tDBX_COMMAND_CLOSE,\t\t\t/* Close session with database */\n\tDBX_COMMAND_QUERY,\t\t\t/* Perform data fetch/check */\n\tDBX_COMMAND_UPDATE,\t\t\t/* Perform data update */\n\tDBX_COMMAND_GETERRORINFO,\t/* Sent if another command fails */\n\tDBX_COMMAND_LAST\t\t\t/* Last command type */\n\t} DBX_COMMAND_TYPE;\n\n/* The command formats are as follows (arguments in square brackets are\n   implied arguments whose values are supplied at the C function level but\n   that aren't passed over the wire, this is used to handle reads of string\n   values):\n\n\tCOMMAND_SERVERQUERY\n\t\t<none>\t\t\t\t\t\tword: status\n\t\t\t\t\t\t\t\t\tword: protocol version\n\t\t\t\t\t\t\t\t\tword: max.fragment size\n\tCOMMAND_CREATEOBJECT\n\t\tword: handle\t\t\t\tword: status\n\t\tword: object type\t\t\tword: new handle\n\t\tword(s) | str(s): params\n\tCOMMAND_CREATEOBJECT_INDIRECT\n\t\tword: handle\t\t\t\tword: status\n\t\tword: object type\t\t\tword: new handle\n\t\tstr : encoded object data\n\tCOMMAND_EXPORTOBJECT\n\t\tword: handle\t\t\t\tword: status\n\t\tword(s): params\t\t\t\tword: str_length | str: data\n\tCOMMAND_DESTROYOBJECT\n\t\tword: handle\t\t\t\tword: status\n\tCOMMAND_QUERYCAPABILITY\n\t\tword: handle\t\t\t\tword: status\n\t\tword: algo\t\t\t\t\tword: str_length | str : data\n\t\tword: mode\n\t\t[str: return buffer]\n\tCOMMAND_GENKEY\n\t\tword: handle\t\t\t\tword: status\n\t\tword: is_async (optional)\n\tCOMMAND_ENCRYPT\n\t\tword: handle\t\t\t\tword: status\n\t\tstr : data\t\t\t\t\tstr : data\n\tCOMMAND_DECRYPT\n\t\tword: handle\t\t\t\tword: status\n\t\tstr : data\t\t\t\t\tstr : data\n\tCOMMAND_GETATTRIBUTE\n\t\tword: handle\t\t\t\tword: status\n\t\tword: attribute type\t\tword: value | word: str_length | str: data\n\t\tword: get_str_data (optional)\n\t\t[str: return buffer for str_data]\n\tCOMMAND_SETATTRIBUTE\n\t\tword: handle\t\t\t\tword: status\n\t\tword: attribute type\n\t\tword: value | str : value\n\tCOMMAND_DELETEATTRIBUTE\n\t\tword: handle\t\t\t\tword: status\n\t\tword: attribute type\n\tCOMMAND_GETKEY\n\t\tword: handle\t\t\t\tword: status\n\t\tword: itemType\t\t\t\tword: handle\n\t\tword: key ID type\t\n\t\tstr : key ID (optional)\n\t\tstr : password (optional)\n\tCOMMAND_SETKEY\n\t\tword: handle\t\t\t\tword: status\n\t\tword: key handle\n\t\tword: caItemType (optional)\n\t\tstr : password (optional)\n\tCOMMAND_DELETEKEY\n\t\tword: handle\t\t\t\tword: status\n\t\tword: key ID type\n\t\tword: caItemType (optional)\n\t\tstr : key ID\n\tCOMMAND_PUSHDATA\n\t\tword: handle\t\t\t\tword: status\n\t\tstr : data\t\t\t\t\tword: length\n\tCOMMAND_POPDATA\n\t\tword: handle\t\t\t\tword: status\n\t\tword: length\t\t\t\tstr : data\n\t\t[str: return buffer]\n\tCOMMAND_CERTSIGN\n\t\tword: handle\t\t\t\tword: status\n\t\tword: sig.key handle\n\tCOMMAND_CERTCHECK\n\t\tword: handle\t\t\t\tword: status\n\t\tword: check key handle\n\tCOMMAND_CERTMGMT\n\t\tword: handle\t\t\t\tword: status\n\t\tword: caKey\t\t\t\t\tword: new cert (optional)\n\t\tword: certRequest\n\n\tDBX_COMMAND_OPEN:\n\t\tword: options\t\t\t\tword: status\n\t\tstr : name\t\t\t\t\tword: featureFlags\n\tDBX_COMMAND_CLOSE\n\t\t<none>\n\tDBX_COMMAND_UPDATE:\n\t\tword: type\t\t\t\t\tword: status\n\t\tstr : command\n\t\tstr : date (optional)\n\t\tstr : data (optional)\n\tDBX_COMMAND_QUERY:\n\t\tword: type\t\t\t\t\tword: status\n\t\tword: query entry (opt.)\tstr : data\n\t\tstr : command\t\t\t\n\t\tstr : date (optional)\n\t\tstr : data (optional)\n\t\t[str: return buffer]\n\tDBX_COMMAND_GETERRORINFO\n\t\t<none>\t\t\t\t\t\tword: errorCode\n\t\t\t\t\t\t\t\t\tstr : errorMessage */\n\n/* The maximum number of integer and string args, and the amount of space to\n   allocate in the COMMAND_INFO to store all possible args */\n\n#define MAX_ARGS\t\t\t\t4\n#define MAX_STRING_ARGS\t\t\t2\n#define DBX_MAX_ARGS\t\t\t2\n#define DBX_MAX_STRING_ARGS\t\t3\n#define ALLOC_MAX_ARGS\t\t\tMAX_ARGS\n#define ALLOC_MAX_STRING_ARGS\tDBX_MAX_STRING_ARGS\n\n/* The possible command flags */\n\n#define COMMAND_FLAG_NONE\t\t0x00\t/* No command flag */\n#define COMMAND_FLAG_RET_NONE\t0x01\t/* Don't return any data */\n#define COMMAND_FLAG_RET_LENGTH\t0x02\t/* Return only length of string arg */\n\n/* The size of an integer as encoded in a message, the size of the fixed-\n   length fields, and the offsets of the data fields in the message */\n\n#define COMMAND_WORDSIZE\t\t4\n#define COMMAND_FIXED_DATA_SIZE\t( COMMAND_WORDSIZE * 2 )\n#define COMMAND_WORD1_OFFSET\tCOMMAND_FIXED_DATA_SIZE\n#define COMMAND_WORD2_OFFSET\t( COMMAND_FIXED_DATA_SIZE + COMMAND_WORDSIZE )\n#define COMMAND_WORD3_OFFSET\t( COMMAND_FIXED_DATA_SIZE + ( COMMAND_WORDSIZE * 2 ) )\n#define COMMAND_WORD4_OFFSET\t( COMMAND_FIXED_DATA_SIZE + ( COMMAND_WORDSIZE * 3 ) )\n\n/* Macros to encode/decode a message type value */\n\n#define putMessageType( buffer, type, flags, noInt, noString ) \\\n\t\t{ \\\n\t\tbuffer[ 0 ] = ( BYTE ) ( type & 0xFF ); \\\n\t\tbuffer[ 1 ] = ( BYTE ) ( flags & 0xFF ); \\\n\t\tbuffer[ 2 ] = noInt; \\\n\t\tbuffer[ 3 ] = noString; \\\n\t\t}\n#define getMessageType( buffer, type, flags, noInt, noString ) \\\n\t\ttype = buffer[ 0 ]; flags = buffer[ 1 ]; \\\n\t\tnoInt = buffer[ 2 ]; noString = buffer[ 3 ]\n\n/* Macros to encode/decode an integer value and a length */\n\n#define putMessageWord( buffer, word ) \\\n\t\t{ \\\n\t\t( buffer )[ 0 ] = ( BYTE ) ( ( ( word ) >> 24 ) & 0xFF ); \\\n\t\t( buffer )[ 1 ] = ( BYTE ) ( ( ( word ) >> 16 ) & 0xFF ); \\\n\t\t( buffer )[ 2 ] = ( BYTE ) ( ( ( word ) >> 8 ) & 0xFF ); \\\n\t\t( buffer )[ 3 ] = ( BYTE ) ( ( word ) & 0xFF ); \\\n\t\t}\n#define getMessageWord( buffer ) \\\n\t\t( ( ( ( long ) ( buffer )[ 0 ] ) << 24 ) | \\\n\t\t  ( ( ( long ) ( buffer )[ 1 ] ) << 16 ) | \\\n\t\t  ( ( ( long ) ( buffer )[ 2 ] ) << 8 ) | \\\n\t\t\t  ( long ) ( buffer )[ 3 ] )\n\n#define getMessageLength\tgetMessageWord\n#define putMessageLength\tputMessageWord\n\n/* A structure to contain the command elements */\n\ntypedef struct {\n\tCOMMAND_TYPE type;\t\t\t\t\t/* Command type */\n\tint flags;\t\t\t\t\t\t\t/* Command flags */\n\tint noArgs, noStrArgs;\t\t\t\t/* Number of int, string args */\n\tint arg[ ALLOC_MAX_ARGS ];\t\t\t/* Integer arguments */\n\tvoid *strArg[ ALLOC_MAX_STRING_ARGS ];\t/* String args */\n\tint strArgLen[ ALLOC_MAX_STRING_ARGS ];\n\t} COMMAND_INFO;\n\n/* Function pointers for a generic dispatch function that dispatches the\n   marshalled data to a receiver, and command handlers that process each\n   command type */\n\ntypedef void ( *DISPATCH_FUNCTION )( void *stateInfo, BYTE *buffer );\ntypedef int ( *COMMAND_HANDLER )( void *stateInfo, COMMAND_INFO *cmd );\n\n/* The full RPC interface (with marshalling and everything) provides complete\n   isolation of input and output, however it resuls in a slight performance\n   decrease due to copying, and can't handle large objects atomically due to\n   limits on message size (this specifically applies to mega-CRLs).  Because \n   of this, we also allow a direct interface that just forwards the data \n   without marshalling/unmarshalling.\n   \n   Because of the change in arg handling for returned data in RPC vs. direct \n   calls (the RPC returns the data in the return message, the direct call \n   requires an extra parameter to specify the location of the returned data) \n   we also need a macro RETURN_VALUE() to no-op out the extra parameter in \n   case we're using the RPC form */\n\n#ifdef USE_RPCAPI\n  #define DISPATCH_COMMAND( function, command ) \\\n\t\t  dispatchCommand( &command )\n  #define DISPATCH_COMMAND_DBX( function, command, dbmsInfo ) \\\n\t\t  dispatchCommand( &command, ( dbmsInfo )->stateInfo, ( dbmsInfo )->dispatchFunction )\n  #define RETURN_VALUE( value )\t\t0\n#else\n  #define DISPATCH_COMMAND( function, command ) \\\n\t\t  function( &command )\n  #define DISPATCH_COMMAND_DBX( function, command, dbmsInfo ) \\\n\t\t  function( ( dbmsInfo )->stateInfo, &command )\n  #define RETURN_VALUE( value )\t\tvalue\n#endif /* USE_RPCAPI */\n\n/* Check whether a decoded command header contains valid data for the\n   different RPC types */\n\n#define checkCommandInfo( cmd, length ) \\\n\t\t( ( cmd )->type > COMMAND_NONE && \\\n\t\t  ( cmd )->type < COMMAND_LAST && \\\n\t\t  ( ( cmd )->flags == COMMAND_FLAG_NONE || \\\n\t\t    ( cmd )->flags == COMMAND_FLAG_RET_NONE || \\\n\t\t\t( cmd )->flags == COMMAND_FLAG_RET_LENGTH ) && \\\n\t\t  ( cmd )->noArgs >= 1 && ( cmd )->noArgs <= MAX_ARGS && \\\n\t\t  ( cmd )->noStrArgs >= 0 && ( cmd )->noStrArgs <= MAX_STRING_ARGS && \\\n\t\t  ( cmd )->strArgLen[ 0 ] >= 0 && \\\n\t\t  ( cmd )->strArgLen[ 1 ] >= 0 && \\\n\t\t  ( length ) >= 0 && ( length ) <= RPC_IO_BUFSIZE )\n\n#define checkCommandConsistency( cmd, length ) \\\n\t\t( ( ( cmd )->strArgLen[ 0 ] + ( cmd )->strArgLen[ 1 ] ) == \\\n\t\t\t( length - ( COMMAND_WORDSIZE * ( ( cmd )->noArgs + ( cmd )->noStrArgs ) ) ) )\n\n#define dbxCheckCommandInfo( cmd, length ) \\\n\t\t( ( cmd )->type > DBX_COMMAND_NONE && \\\n\t\t  ( cmd )->type < DBX_COMMAND_LAST && \\\n\t\t  ( cmd )->flags == COMMAND_FLAG_NONE && \\\n\t\t  ( cmd )->noArgs >= 0 && ( cmd )->noArgs <= DBX_MAX_ARGS && \\\n\t\t  ( cmd )->noStrArgs >= 0 && ( cmd )->noStrArgs <= DBX_MAX_STRING_ARGS && \\\n\t\t  ( cmd )->strArgLen[ 0 ] >= 0 && \\\n\t\t  ( cmd )->strArgLen[ 1 ] >= 0 && \\\n\t\t  ( cmd )->strArgLen[ 2 ] >= 0 && \\\n\t\t  ( length ) >= 0 && ( length ) <= DBX_IO_BUFSIZE )\n\n#define dbxCheckCommandConsistency( cmd, length ) \\\n\t\t( ( ( cmd )->strArgLen[ 0 ] + ( cmd )->strArgLen[ 1 ] + ( cmd )->strArgLen[ 2 ] ) == \\\n\t\t\t( length - ( COMMAND_WORDSIZE * ( ( cmd )->noArgs + ( cmd )->noStrArgs ) ) ) )\n\n/* The maximum size of a message fragment.  Messages containing more data\n   than this are broken up into fragments.  On systems with very restricted\n   amounts of memory we make the size rather small to limit the size of\n   the intermediate buffers used */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define MAX_FRAGMENT_SIZE\t\t8192\n#else\n  #define MAX_FRAGMENT_SIZE\t\t32768\n#endif /* CONSERVER_MEMORY */\n\n/* The size of the I/O buffer used to assemble messages.  This is equal to\n   the maximum fragment size plus the maximum header size for commands that\n   require fragmentation (COMMAND_ENCRYPT/COMMAND_DECRYPT and\n   COMMAND_PUSHDATA/COMMAND_POPDATA).  We define a separate version for \n   database RPC since this uses much smaller buffers */\n\n#define RPC_IO_BUFSIZE\t\t\tMAX_FRAGMENT_SIZE + 32\n#define DBX_IO_BUFSIZE\t\t\t4096\n\n#endif /* _RPC_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/safety.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Correctness/Safety Header File \t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1994-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SAFETY_DEFINED\n\n#define _SAFETY_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDesign-by-Contract Predicates\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Symbolic defines to handle design-by-contract predicates.  If we're \n   really short of code space, we can save a little extra by turning the \n   predicates into no-ops */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#define REQUIRES( x )\t\tif( !( x ) ) retIntError()\n#define REQUIRES_N( x )\t\tif( !( x ) ) retIntError_Null()\n#define REQUIRES_B( x )\t\tif( !( x ) ) retIntError_Boolean()\n#define REQUIRES_V( x )\t\tif( !( x ) ) retIntError_Void()\n#define REQUIRES_EXT( x, y )\tif( !( x ) ) retIntError_Ext( y )\n#define REQUIRES_D( x )\t\tif( !( x ) ) retIntError_Dataptr()\n#define REQUIRES_S( x )\t\tif( !( x ) ) retIntError_Stream( stream )\n\n#else\n\n#define REQUIRES( x )\n#define REQUIRES_N( x )\n#define REQUIRES_B( x )\n#define REQUIRES_V( x )\n#define REQUIRES_EXT( x, y )\n#define REQUIRES_D( x )\n#define REQUIRES_S( x )\n\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\n#define ENSURES\t\t\t\tREQUIRES\n#define ENSURES_N\t\t\tREQUIRES_N\n#define ENSURES_B\t\t\tREQUIRES_B\n#define ENSURES_V\t\t\tREQUIRES_V\n#define ENSURES_EXT\t\t\tREQUIRES_EXT\n#define ENSURES_D\t\t\tREQUIRES_D\n#define ENSURES_S\t\t\tREQUIRES_S\n\n/* A special-case form of the REQUIRES() predicate that's used in functions \n   that acquire a mutex.  There are two versions of this, one for cryptlib\n   kernel mutexes, denoted by KRNLMUTEX, and one for native mutexes that are\n   only visible inside the kernel, denoted by MUTEX */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#define REQUIRES_KRNLMUTEX( x, mutex ) \\\n\t\tif( !( x ) ) \\\n\t\t\t{ \\\n\t\t\tkrnlExitMutex( mutex ); \\\n\t\t\tretIntError(); \\\n\t\t\t}\n#define REQUIRES_KRNLMUTEX_V( x, mutex ) \\\n\t\tif( !( x ) ) \\\n\t\t\t{ \\\n\t\t\tkrnlExitMutex( mutex ); \\\n\t\t\tretIntError_Void(); \\\n\t\t\t}\n\n#define REQUIRES_MUTEX( x, mutex ) \\\n\t\tif( !( x ) ) \\\n\t\t\t{ \\\n\t\t\tMUTEX_UNLOCK( mutex ); \\\n\t\t\tretIntError(); \\\n\t\t\t}\n#else\n\n#define REQUIRES_KRNLMUTEX( x, mutex )\n#define REQUIRES_KRNLMUTEX_V( x, mutex )\n#define REQUIRES_MUTEX( x, mutex )\n\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\n#define ENSURES_KRNLMUTEX\tREQUIRES_KRNLMUTEX\n#define ENSURES_KRNLMUTEX_V\tREQUIRES_KRNLMUTEX_V\n\n#define ENSURES_MUTEX\t\tREQUIRES_MUTEX\n\n/* Another variant of REQUIRES() that releases an object on exit */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n#define REQUIRES_OBJECT( x, object ) \\\n\t\tif( !( x ) ) \\\n\t\t\t{ \\\n\t\t\tkrnlReleaseObject( object ); \\\n\t\t\tretIntError(); \\\n\t\t\t}\n#else\n\n#define REQUIRES_OBJECT( x, object )\n\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\n#define ENSURES_OBJECT\t\tREQUIRES_OBJECT\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRange/Bounds Checks\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether an integer value is within range */\n\n#define isIntegerRange( value )\t\\\n\t\t( ( value ) >= 0 && ( value ) < MAX_INTLENGTH )\n#define isIntegerRangeNZ( value ) \\\n\t\t( ( value ) >= 1 && ( value ) < MAX_INTLENGTH )\n#define isShortIntegerRange( value ) \\\n\t\t( ( value ) >= 0 && ( value ) < MAX_INTLENGTH_SHORT )\n#define isShortIntegerRangeNZ( value ) \\\n\t\t( ( value ) >= 1 && ( value ) < MAX_INTLENGTH_SHORT )\n\n/* Alongside the integer range check macros we also define one for enum \n   and flag range checks */\n\n#define isEnumRange( value, name ) \\\n\t\t( ( value ) > name##_NONE && ( value ) < name##_LAST )\n#define isEnumRangeOpt( value, name ) \\\n\t\t( ( value ) >= name##_NONE && ( value ) < name##_LAST )\n#define isFlagRange( value, name ) \\\n\t\t( ( value ) > name##_FLAG_NONE && ( value ) <= name##_FLAG_MAX )\n#define isFlagRangeZ( value, name ) \\\n\t\t( ( value ) >= name##_FLAG_NONE && ( value ) <= name##_FLAG_MAX )\n\n/* Perform a range check, verifying that { value } falls within \n   { start, end } */\n\n#define rangeCheck( value, start, end ) \\\n\t\t( ( ( value ) < ( start ) || ( value ) > ( end ) ) ? FALSE : TRUE )\n\n/* Perform a bounds check on indexes into a block of memory, verifying that \n   { start, length } falls within { 0, totalLength }.  There are two \n   versions of this, the default which requires a nonzero start offset and \n   the special-case variant which also allows a zero start offset.  The\n   latter is used for situations like optionally MIME-wrapped data which \n   have a nonzero offset if there's a MIME header to be skipped but a zero \n   offset if it's unencapsulated data */\n\n#define boundsCheck( start, length, totalLength ) \\\n\t\t( ( ( start ) <= 0 || ( length ) < 1 || \\\n\t\t\t( start ) + ( length ) > ( totalLength ) ) ? FALSE : TRUE )\n#define boundsCheckZ( start, length, totalLength ) \\\n\t\t( ( ( start ) < 0 || ( length ) < 1 || \\\n\t\t\t( start ) + ( length ) > ( totalLength ) ) ? FALSE : TRUE )\n\n/* Perform a bounds check on pointers to blocks of memory, verifying that an\n   inner block of memory is contained entirely within an outer block of \n   memory:\n\n\t\t\tinnerPtr\n\t\t\t\tv ----- innerLength ---->\n\t\t+-------+-----------------------+-------+\n\t\t|\t\t|\t\t\t\t\t\t|\t\t|\n\t\t+-------+-----------------------+-------+\n\t\t^ ------------- dataLength ------------->\n\tdataPtr\n\n   This is used for pointers to specific objects within a large encoded data\n   block.  Since it's a fairly complex set of checks, it's implemented as a\n   function in int_api.c */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN pointerBoundsCheck( IN_OPT const void *data,\n\t\t\t\t\t\t\tIN_LENGTH_Z const int dataLength,\n\t\t\t\t\t\t\tIN_OPT const void *innerData,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int innerDataLength );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPointer Validity Checks\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the validity of a pointer passed to a cryptlib function.  Usually\n   the best that we can do is check that it's not NULL, but some OSes allow\n   for better checking than this, for example that it points to a block of\n   readable or writeable memory.  Under Windows IsBadReadPtr() will always\n   succeed if the size is 0, so we have to add a separate check to make sure\n   that it's non-NULL.\n\n   For any OS, we check not just for the specific value NULL but for anything\n   that appears to be pointing into an unlikely memory range.  This is used\n   to catch invalid pointers to elements inside structures, for example:\n\n\tstruct foo_struct *fooPtr; \n\t\n\tfunction( &fooPtr->element ); \n\t\n   where fooPtr is NULL, which will pass in a small integer value as the \n   pointer.  While it won't catch most invalid pointers, it's at least a bit \n   more useful than just checking for NULL.\n\n   There are additional caveats with the use of the Windows memory-checking\n   functions.  In theory these would be implemented via VirtualQuery(),\n   however this is quite slow, requiring a kernel transition and poking\n   around with the page protection mechanisms.  Instead, they try and read\n   or write the memory with an exception handler wrapped around the access.\n   If the exception is thrown, they fail.  The problem with this way of\n   doing things is that if the memory address is a stack guard page used to\n   grow the stack (when the system-level exception handler sees an access to\n   the bottom-of-stack guard page, it knows that it has to grow the stack)\n   *and* the guard page is owned by another thread, IsBadXxxPtr() will catch \n   the exception and the system will never see it, so it can't grow the \n   stack past the current limit (note that this only occurs if the guard \n   page that we hit is owned by a different thread; if we own in then the\n   kernel will catch the STATUS_GUARD_PAGE_VIOLATION exception and grow the\n   stack as required).  In addition if it's the last guard page then instead \n   of getting an \"out of stack\" exception, it's turned into a no-op.  The \n   second time the last guard page is hit, the application is terminated by \n   the system, since it's passed its first-chance exception.\n\n   A variation of this is that the calling app could be deliberately passing\n   a pointer to a guard page and catching the guard page exception in order\n   to dynamically generate the data that would fill the page (this can \n   happen for example when simulating a large address space with pointer \n   swizzling), but this is a pretty weird programming technique that's \n   unlikely to be used with a crypto library.\n\n   A lesser problem is that there's a race condition in the checking in \n   which the memory can be unmapped between the IsBadXxxPtr() check and the \n   actual access, but you'd pretty much have to be trying to actively \n   subvert the checks to do something like this.\n\n   For these reasons we use these functions mostly for debugging, wrapping\n   them up in assert()s in most cases where they're used.  Under Windows \n   Vista and newer they've actually been turned into no-ops because of the \n   above problems, although it's probable that they'll be replaced by code \n   to check for NULL pointers, since some of Microsoft's docs indicate that \n   this much checking will still be done.  In addition the type of checking \n   seems to be a function of the Visual C++ libraries used rather than the \n   OS, since VC++ 6 applications still perform the full readability check \n   even under Windows 7 and 8.\n   \n   If necessary we could also replace the no-op'd out versions with the \n   equivalent code:\n\n\tinline BOOL IsBadReadPtr( const VOID *lp, UINT_PTR ucb )\n\t\t{\n\t\t__try { memcmp( p, p, cb ); }\n\t\t__except( EXCEPTION_EXECUTE_HANDLER ) { return( FALSE ); }\n\t\treturn( TRUE );\n\t\t}\n\n\tinline BOOL IsBadWritePtr( LPVOID lp, UINT_PTR ucb )\n\t\t{\n\t\t__try { memset( p, 0, cb ); }\n\t\t__except( EXCEPTION_EXECUTE_HANDLER ) { return( FALSE ); }\n\t\treturn( TRUE );\n\t\t} \n\n   In a number of cases the code is called as \n   isXXXPtr( ptr, sizeof( ptrObject ) ), which causes warnings about \n   constant expressions, to avoid this we define a separate version \n   isXXXPtrConst() that avoids the size check.\n   \n   Under Unix we could in theory check against _etext but this is too \n   unreliable to use, with shared libraries the single shared image can be \n   mapped pretty much anywhere into the process' address space and there can \n   be multiple _etext's present, one per shared library, it fails with \n   SELinux (which is something you'd expect to see used in combination with \n   code that's been carefully written to do things like perform pointer \n   checking), and who knows what it'll do in combination with different \n   approaches to ASLR.  Because of its high level of nonportability (even on \n   the same system it can break depending on whether something like SELinux \n   is enabled or not) it's too dangerous to enable its use */\n\n#define isValidPointer( ptr )\t( ( uintptr_t ) ( ptr ) > 0x0FFFF )\n\n#if defined( __WIN32__ ) || defined( __WINCE__ )\n  /* The use of code analysis complicates the pointer-checking macros\n\t because they read memory that's uninitialised at that point.  This is\n\t fine because we're only checking for readability/writeability, but the\n\t analyser doesn't know this and flags it as an error.  To avoid this,\n\t we remove the read/write calls when running the analyser */\n  #ifdef _PREFAST_\n\t#define isReadPtr( ptr, size )\t( isValidPointer( ptr ) )\n\t#define isWritePtr( ptr, size )\t( isValidPointer( ptr ) )\n\t#define isReadPtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 )\n\t#define isWritePtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 )\n  #else\n\t#define isReadPtr( ptr, size )\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  !IsBadReadPtr( ( ptr ), ( size ) ) )\n\t#define isWritePtr( ptr, size )\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  !IsBadWritePtr( ( ptr ), ( size ) ) )\n\t#define isReadPtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 && \\\n\t\t\t\t\t\t\t\t\t  !IsBadReadPtr( ( ptr ), ( size ) ) )\n\t#define isWritePtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 && \\\n\t\t\t\t\t\t\t\t\t  !IsBadWritePtr( ( ptr ), ( size ) ) )\n  #endif /* _PREFAST_ */\n#elif defined( __UNIX__ ) && 0\t\t/* See comment above */\n  extern int _etext;\n\n  #define isReadPtr( ptr, size )\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  ( void * ) ( ptr ) > ( void * ) &_etext )\n  #define isWritePtr( ptr, size )\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  ( void * ) ( ptr ) > ( void * ) &_etext )\n  #define isReadPtrDynamic( ptr, size )\t\\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  ( void * ) ( ptr ) > ( void * ) &_etext && \\\n\t\t\t\t\t\t\t\t\t  ( size ) > 0 )\n  #define isWritePtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && \\\n\t\t\t\t\t\t\t\t\t  ( void * ) ( ptr ) > ( void * ) &_etext && \\\n\t\t\t\t\t\t\t\t\t  ( size ) > 0 )\n#else\n  #define isReadPtr( ptr, type )\t( isValidPointer( ptr ) )\n  #define isWritePtr( ptr, type )\t( isValidPointer( ptr ) )\n  #define isReadPtrDynamic( ptr, size )\t\\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 )\n  #define isWritePtrDynamic( ptr, size ) \\\n\t\t\t\t\t\t\t\t\t( isValidPointer( ptr ) && ( size ) > 0 )\n#endif /* Pointer check macros */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSafe Buffer Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of the canary inserted into a buffer, and a macros to work with\n   overall buffer sizes.  SAFEBUFFER_SIZE() takes the data size and \n   calculates the overall buffer size, SAFEBUFFER_DATASIZE() takes the \n   overall buffer size and calculates the data size.  These macros assumes \n   that the size parameter will never even get close to a value where \n   overflow is an issue, which is always the case since we only use it with \n   buffers under MAX_BUFSIZE */\n\n#define SAFEBUFFER_COOKIE_SIZE\t( sizeof( uintptr_t ) )\n\n#define SAFEBUFFER_SIZE( size )\t( SAFEBUFFER_COOKIE_SIZE + ( size ) + \\\n\t\t\t\t\t\t\t\t  SAFEBUFFER_COOKIE_SIZE )\n#define SAFEBUFFER_DATASIZE( bufSize ) \\\n\t\t\t\t\t\t\t\t( ( bufSize ) - ( SAFEBUFFER_COOKIE_SIZE + \\\n\t\t\t\t\t\t\t\t\t\t\t\t  SAFEBUFFER_COOKIE_SIZE ) )\n#define SAFEBUFFER_PTR( bufPtr ) \\\n\t\t\t\t\t\t\t\t( ( ( BYTE * ) bufPtr ) + SAFEBUFFER_COOKIE_SIZE )\n\n/* Manage canaried buffers that check for writes outside the bounds of the\n   buffer.  For a statically allocated buffer this is used as:\n   \n\tBYTE buffer[ SAFEBUFFER_SIZE( 1024 ) ]; \n\t\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), 1024 );\n\tsread( stream, SAFEBUFFER_PTR( buffer ), 1024 ); \n\t\n   For a dynamically allocated buffer this is used as:\n\n\tBYTE bufPtr = malloc( SAFEBUFFER_SIZE( 1024 ) );\n\n\tstruct->buffer = SAFEBUFFER_PTR( bufPtr );\n\tstruct->bufSize = 1024;\n\tsafeBufferInit( struct->buffer, struct->bufSize ); \n\n   A combined allocate + init function is:\n\n\tbuffer = safeBufferAlloc( 1024 ); */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid safeBufferInit( INOUT_BUFFER_FIXED( bufSize ) void *buffer, \n\t\t\t\t\t IN_DATALENGTH const int bufSize );\nCHECK_RETVAL_PTR \\\nvoid *safeBufferAlloc( IN_DATALENGTH const int size );\nvoid safeBufferFree( const void *buffer );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN safeBufferCheck( IN_BUFFER( bufSize ) const void *buffer, \n\t\t\t\t\t\t IN_DATALENGTH const int bufSize );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tControl Flow Integrity Checks\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Turn a string into an access token, used to maintain control-flow \n   integrity (CFI).  In it's simplest form it's used as an acess token for a\n   function call to ensure that the function really was called as intended:\n\n\tfunctionName( MK_TOKEN( \"functionName\", 12 ), ..... );\n\n\tint functionName( const ACCESS_TOKEN accessToken, ... )\n\t\t{\n\t\tREQUIRES( CHECK_TOKEN( \"functionName\", 12 ) );\n\n\t\t...\n\t\t}\n\n    To work with access tokens we need a means of converting a string into \n\tan integer value, which we do by hashing it using the preprocessor (on\n\tcompilers with any level of optimisation, so essentially anything where\n\t-O0 isn't specified).  The hash function is the standard djb hash, \n\t'hash = hash * 33 + c' where the initial seed is 5381, with the property \n\tthat it's good on ASCII strings, which is what we're using it for.  In\n\tparticular it'll hash 6-character lowercase strings into 32 bits with no\n\tcollisions, this isn't something we specifically need since we just need \n\ta fairly low probability of collision, but it's a specific property of\n\tthe function that's worth pointing out.  Source of the magic values: \n\tSomething djb thought up */\n\n#define DJB_SEED\t\t\t\t5381\n#define DJB_HASH( hash, ch )\t( ( ( unsigned int ) ( hash ) * 33 ) + ( BYTE ) ch )\n\n#define DJB_LEN( str )\t\t\t( sizeof( str ) - 1 )\n#define DJB_HASH_1( str )\t\tDJB_HASH( DJB_SEED, str[ 0 ] )\n#define DJB_HASH_2( str )\t\tDJB_HASH( DJB_HASH_1( str ), str[ 1 ] )\n#define DJB_HASH_3( str )\t\tDJB_HASH( DJB_HASH_2( str ), str[ 2 ] )\n#define DJB_HASH_4( str )\t\tDJB_HASH( DJB_HASH_3( str ), str[ 3 ] )\n#define DJB_HASH_025( str )\t\tDJB_HASH( DJB_HASH_4( str ), str[ DJB_LEN( str ) / 4 ] )\n#define DJB_HASH_050( str )\t\tDJB_HASH( DJB_HASH_025( str ), str[ DJB_LEN( str ) / 2 ] )\n#define DJB_HASH_075( str )\t\tDJB_HASH( DJB_HASH_050( str ), str[ ( DJB_LEN( str ) * 3 ) / 4 ] )\n#define DJB_HASH_100( str )\t\tDJB_HASH( DJB_HASH_075( str ), str[ DJB_LEN( str ) - 1 ] )\n\n#define MK_TOKEN( key )\t\t\tDJB_HASH_100( key ) \n#define CHECK_TOKEN( key )\t\t( DJB_HASH_100( key ) == ( accessToken ) )\n\ntypedef unsigned int ACCESS_TOKEN;\n\n/* Access tokens are also used to enforce CFI within functions.  The way \n   this works is that an ongoing record of sequence points visited is kept \n   by an accumulator, and at the end of the function the accumulator value \n   is compared to the expected value.  This means that there are two \n   expressions of the control flow, one implicitly coded into the function \n   and a second explicitly stated at the end of the function.  If the final \n   values don't match, there's a problem with the control flow.\n\n   CFI checking is performed as follows:\n\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\t\n\tcode;\n\tCFI_CHECK_UPDATE( sequencePoint1Name ); \n\tcode;\n\tCFI_CHECK_UPDATE( sequencePoint2Name ); \n\tcode;\n\tCFI_CHECK_UPDATE( sequencePoint3Name ); \n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( functionName, sequencePoint1Name, \n\t\t\t  \t\t\t\t\t\tsequencePoint2Name, sequencePoint3Name ) );\n\n   Although the result looks rather ugly, most of the work is being done by \n   the preprocessor and not in generated code.  Hopefully no compiler will \n   be smart enough to optimise everything before the CFI_CHECK_SEQUENCE() \n   into a single fixed integer value, but then it's only a probabilistic \n   check in any case.\n   \n   Without reliable access to variadic macros, we have to hardcode the \n   number of arguments into the macro name.  In order to avoid passing large\n   numbers of dummy parameters as padding when not all parameters are used,\n   we use a helper function cfiCheckSequence() and nest calls to it where\n   more parameters need to be handled.  Another reason for using this helper\n   function is that it prevents excessively clever compilers from optimising\n   away the entire sequence of calculations and the resulting compare of two\n   fixed values (in theory a compiler that inlines cfiCheckSequence() could\n   still do this, but curently no compiler seems to be able to do this) */\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\ntypedef unsigned int CFI_CHECK_TYPE;\n#define CFI_CHECK_VALUE\t\t\t\tcfiCheckValue\n#ifdef __SUNPRO_C\n  /* SunPro C can't do sizeof( __func__ ) (or __FUNCTION__, as an \n\t alternative), a bug that's been present for at least a decade so is \n\t unlikely to ever get fixed.  The best that we can do is substitute\n\t __FILE__, which isn't as granular but close enough in most cases\n\t since CFI is only used for critical functions */\n  #define CFI_FUNCTION_NAME\t\t\tMK_TOKEN( __FILE__ )\n#else\n  #define CFI_FUNCTION_NAME\t\t\tMK_TOKEN( __func__ )\n#endif /* Sun braindamage */\n#define CFI_CHECK_INIT\t\t\t\tCFI_FUNCTION_NAME\n#define CFI_CHECK_UPDATE( label ) \\\n\t\tcfiCheckValue = ( cfiCheckValue << 5 ) + MK_TOKEN( label )\n#define CFI_CHECK_SEQUENCE_1( label1 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1, ( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_2( label1, label2 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label2 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_3( label1, label2, label3 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label2 ), MK_TOKEN( label3 ) ) )\n#define CFI_CHECK_SEQUENCE_4( label1, label2, label3, label4 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label4 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1, ( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_5( label1, label2, label3, label4, label5 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_6( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label6 ) ) )\n#define CFI_CHECK_SEQUENCE_7( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label7 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1, ( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_8( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7, label8 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n/* The following are only required for certificate-related functions, which\n   have high levels of complexity */\n#define CFI_CHECK_SEQUENCE_9( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7, label8, label9 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label9 ) ) )\n#define CFI_CHECK_SEQUENCE_10( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label10 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1, ( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_11( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label10 ), MK_TOKEN( label11 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_12( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\tcfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label10 ), MK_TOKEN( label11 ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label12 ) ) )\n#define CFI_CHECK_SEQUENCE_13( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\t  cfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label10 ), MK_TOKEN( label11 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label12 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label13 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1, ( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_14( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13, label14 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\t  cfiCheckSequence( \\\n\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label10 ), MK_TOKEN( label11 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label12 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label13 ), MK_TOKEN( label14 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n#define CFI_CHECK_SEQUENCE_17( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13, label14, label15, \\\n\t\t\t\t\t\t\t   label16, label17 ) \\\n\t\t( cfiCheckValue == \\\n\t\t  cfiCheckSequence( \\\n\t\t\t  cfiCheckSequence( \\\n\t\t\t\t  cfiCheckSequence( \\\n\t\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\t\tcfiCheckSequence( \\\n\t\t\t\t\t\t\tcfiCheckSequence( CFI_FUNCTION_NAME, MK_TOKEN( label1 ), \\\n\t\t\t\t\t\t\t\t\t\t\t  MK_TOKEN( label2 ), MK_TOKEN( label3 ) ), \\\n\t\t\t\t\t\t\t\t\t\t  MK_TOKEN( label4 ), MK_TOKEN( label5 ), \\\n\t\t\t\t\t\t\t\t\t\t  MK_TOKEN( label6 ) ), \\\n\t\t\t\t\t\t\t\t\t\tMK_TOKEN( label7 ), MK_TOKEN( label8 ), \\\n\t\t\t\t\t\t\t\t\t\tMK_TOKEN( label9 ) ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label10 ), MK_TOKEN( label11 ), \\\n\t\t\t\t\t\t\t\t\tMK_TOKEN( label12 ) ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label13 ), MK_TOKEN( label14 ), \\\n\t\t\t\t\t\t\t\tMK_TOKEN( label15 ) ), \\\n\t\t\t\t\t\t\tMK_TOKEN( label16 ), MK_TOKEN( label17 ), \\\n\t\t\t\t\t\t\t( CFI_CHECK_TYPE ) -1 ) )\n#else\n\n#define CFI_CHECK_VALUE\t\t\t\t\t\t\t\t\t\t\tcfiCheckValue\n#define CFI_CHECK_INIT\t\t\t\t\t\t\t\t\t\t\t0\n#define CFI_CHECK_UPDATE( label )\n#define CFI_CHECK_SEQUENCE_1( label1 )\t\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_2( label1, label2 )\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_3( label1, label2, label3 )\t\t\t0\n#define CFI_CHECK_SEQUENCE_4( label1, label2, label3, label4 )\t0\n#define CFI_CHECK_SEQUENCE_5( label1, label2, label3, label4, \\\n\t\t\t\t\t\t\t  label5 )\t\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_6( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6 )\t\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_7( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7 )\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_8( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7, label8 )\t\t\t0\n#define CFI_CHECK_SEQUENCE_9( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t  label6, label7, label8, label9 )\t0\n#define CFI_CHECK_SEQUENCE_10( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, \\\n\t\t\t\t\t\t\t   label10 )\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_11( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11 )\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_12( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12 )\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_13( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13 )\t\t0\n#define CFI_CHECK_SEQUENCE_14( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13, \\\n\t\t\t\t\t\t\t   label14 )\t\t\t\t\t\t0\n#define CFI_CHECK_SEQUENCE_17( label1, label2, label3, label4, label5, \\\n\t\t\t\t\t\t\t   label6, label7, label8, label9, label10, \\\n\t\t\t\t\t\t\t   label11, label12, label13, label14, \\\n\t\t\t\t\t\t\t   label15, label16, label17 )\t\t0\n\n#endif /* CONFIG_CONSERVE_MEMORY_EXTRA */\n\nCFI_CHECK_TYPE cfiCheckSequence( const CFI_CHECK_TYPE initValue, \n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label1Value,\n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label2Value, \n\t\t\t\t\t\t\t\t const CFI_CHECK_TYPE label3Value );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tLoop Bounds Checks\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Loop bounds used when a more specific constant upper bound isn't \n   available.  The following bounds on loop iterations apply:\n\n\tFAILSAFE_SMALL: Expect 1 but can have a few more.\n\tFAILSAFE_MED: Expect 10-20 but can have a few more.\n\tFAILSAFE_LARGE: Expect many, but not too many.\n\n  In addition to these values there's a special value \n  FAILSAFE_ITERATIONS_MAX which is equivalent to the ASN.1 (1...MAX) \n  construct in setting an upper bound on loop iterations without necessarily \n  setting any specific limit:\n\n\tFAILSAFE_MAX: A value that's unlikely to be reached during normal \n\t\t\t\t  operation, but that also won't result in an excessive \n\t\t\t\t  stall if it's exceeded */\n\n#define FAILSAFE_ITERATIONS_SMALL\t10\n#define FAILSAFE_ITERATIONS_MED\t\t50\n#define FAILSAFE_ITERATIONS_LARGE\t1000\n#define FAILSAFE_ITERATIONS_MAX\t\tmin( 100000L, INT_MAX )\n\n/* Pseudo-constants used for array bounds-checking.  These provide a more\n   precise limit than the FAILSAFE_ITERATIONS_xxx values above.  We subtract\n   one from the total count because static arrays are always overallocated \n   with two extra dummy elements at the end */\n\n#define FAILSAFE_ARRAYSIZE( array, elementType ) \\\n\t\t( ( sizeof( array ) / sizeof( elementType ) ) - 1 )\n\n/* In order to provide its availability guarantees, all loops in cryptlib \n   are statically bounded and double-indexed in case of a fault in the\n   primary loop index.  In addition the loops are indexed in opposite\n   directions to prevent compilers from combining the two loop index \n   variables into one.  So instead of:\n\n\tfor( i = 0; i < max; i++ )\n\n   the loop construct used is:\n\n\tfor( i = 0,\t\t_iterationCount = FAILSAFE_ITERATIONS_MED;\n\t\t i < max && _iterationCount > 0;\n\t\t i++,\t\t_iterationCount-- )\n\n   (in practice the static bounds check is performed before the dynamic one).\n\n   In order to hide the resulting complexity and to ensure consistent\n   implementation, the overall construct is mangled through macros so that\n   the above becomes:\n\n\tLOOP_MED( i = 0, i < max, i++ )\n\t\t{\n\t\t<loop body>;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n   First we define the loop variables and conditions that we need.  Since we\n   can have nested loops, we also define alternative values for a total of \n   up to three levels of nesting */\n\n#define LOOP_ITERATOR\t\t\t\t_iterationCount\n#define LOOP_BOUND_INIT( value )\t_iterationCount = ( value )\n#define LOOP_BOUND_CHECK\t\t\t( _iterationCount > 0 )\n#define LOOP_BOUND_INC\t\t\t\t_iterationCount--\n#define LOOP_BOUND_OK\t\t\t\tLOOP_BOUND_CHECK\n\n#define LOOP_ITERATOR_ALT\t\t\t_innerIterationCount\n#define LOOP_BOUND_INIT_ALT( value ) _innerIterationCount = ( value )\n#define LOOP_BOUND_CHECK_ALT\t\t( _innerIterationCount > 0 )\n#define LOOP_BOUND_INC_ALT\t\t\t_innerIterationCount--\n#define LOOP_BOUND_OK_ALT\t\t\tLOOP_BOUND_CHECK_ALT\n\n#define LOOP_ITERATOR_ALT2\t\t\t_innerInnerIterationCount\n#define LOOP_BOUND_INIT_ALT2( value ) _innerInnerIterationCount = ( value )\n#define LOOP_BOUND_CHECK_ALT2\t\t( _innerInnerIterationCount > 0 )\n#define LOOP_BOUND_INC_ALT2\t\t\t_innerInnerIterationCount--\n#define LOOP_BOUND_OK_ALT2\t\t\tLOOP_BOUND_CHECK_ALT2\n\n/* With the above we can now create the building blocks for the loops, the\n   basic universal form and then more specific forms built on top of that */\n\n#define LOOP_EXT( a, b, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK && ( b ); \\\n\t\t\t LOOP_BOUND_INC, ( c ) )\n#define LOOP_EXT_ALT( a, b, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT_ALT( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK_ALT && ( b ); \\\n\t\t\t LOOP_BOUND_INC_ALT, ( c ) )\n#define LOOP_EXT_ALT2( a, b, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT_ALT2( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK_ALT2 && ( b ); \\\n\t\t\t LOOP_BOUND_INC_ALT2, ( c ) )\n\n#define LOOP_SMALL( a, b, c )\tLOOP_EXT( a, b, c, FAILSAFE_ITERATIONS_SMALL )\n#define LOOP_MED( a, b, c )\t\tLOOP_EXT( a, b, c, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE( a, b, c )\tLOOP_EXT( a, b, c, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX( a, b, c )\t\tLOOP_EXT( a, b, c, FAILSAFE_ITERATIONS_MAX )\n\n#define LOOP_SMALL_ALT( a, b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_ALT( a, b, c, FAILSAFE_ITERATIONS_SMALL )\n#define LOOP_MED_ALT( a, b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_ALT( a, b, c, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE_ALT( a, b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_ALT( a, b, c, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX_ALT( a, b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_ALT( a, b, c, FAILSAFE_ITERATIONS_MAX )\n\n#define LOOP_LARGE_ALT2( a, b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_ALT2( a, b, c, FAILSAFE_ITERATIONS_LARGE )\n\n/* Finally, we need a few specialised subtypes to handle constructs like:\n\n\tfor( ; i < max ; i++ )\n\n   or even:\n\n\tfor( ; i < max ; )\n\n   (used when the loop variable is initialised dynamically and the increment\n   is part of a conditional in the loop body) */\n\n#define LOOP_EXT_INITCHECK( a, b, bound ) \\\n\t\tfor( LOOP_BOUND_INIT( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK && ( b ); \\\n\t\t\t LOOP_BOUND_INC )\n#define LOOP_EXT_INITINC( a, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK; \\\n\t\t\t LOOP_BOUND_INC, ( c ) )\n#define LOOP_EXT_CHECK( b, bound ) \\\n\t\tfor( LOOP_BOUND_INIT( bound ); \\\n\t\t\t LOOP_BOUND_CHECK && ( b ); \\\n\t\t\t LOOP_BOUND_INC )\n#define LOOP_EXT_CHECKINC( b, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT( bound ); \\\n\t\t\t LOOP_BOUND_CHECK && ( b ); \\\n\t\t\t LOOP_BOUND_INC, ( c ) )\n\n#define LOOP_EXT_INITCHECK_ALT( a, b, bound ) \\\n\t\tfor( LOOP_BOUND_INIT_ALT( bound ), ( a ); \\\n\t\t\t LOOP_BOUND_CHECK_ALT && ( b ); \\\n\t\t\t LOOP_BOUND_INC_ALT )\n#define LOOP_EXT_CHECK_ALT( b, bound ) \\\n\t\tfor( LOOP_BOUND_INIT_ALT( bound ); \\\n\t\t\t LOOP_BOUND_CHECK_ALT && ( b ); \\\n\t\t\t LOOP_BOUND_INC_ALT )\n#define LOOP_EXT_CHECKINC_ALT( b, c, bound ) \\\n\t\tfor( LOOP_BOUND_INIT_ALT( bound ); \\\n\t\t\t LOOP_BOUND_CHECK_ALT && ( b ); \\\n\t\t\t LOOP_BOUND_INC_ALT, ( c ) )\n\n#define LOOP_SMALL_INITCHECK( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK( a, b, FAILSAFE_ITERATIONS_SMALL ) \n#define LOOP_MED_INITCHECK( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK( a, b, FAILSAFE_ITERATIONS_MED ) \n#define LOOP_LARGE_INITCHECK( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK( a, b, FAILSAFE_ITERATIONS_LARGE ) \n#define LOOP_MAX_INITCHECK( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK( a, b, FAILSAFE_ITERATIONS_MAX ) \n\n#define LOOP_MED_INITINC( a, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITINC( a, c, FAILSAFE_ITERATIONS_MED )\n\n#define LOOP_SMALL_CHECK( b )\tLOOP_EXT_CHECK( b, FAILSAFE_ITERATIONS_SMALL )\n#define LOOP_MED_CHECK( b )\t\tLOOP_EXT_CHECK( b, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE_CHECK( b )\tLOOP_EXT_CHECK( b, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX_CHECK( b )\t\tLOOP_EXT_CHECK( b, FAILSAFE_ITERATIONS_MAX )\n\n#define LOOP_SMALL_CHECKINC( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC( b, c, FAILSAFE_ITERATIONS_SMALL )\n#define LOOP_MED_CHECKINC( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC( b, c, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE_CHECKINC( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC( b, c, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX_CHECKINC( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC( b, c, FAILSAFE_ITERATIONS_MAX )\n\n#define LOOP_MED_CHECK_ALT( b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECK_ALT( b, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE_CHECK_ALT( b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECK_ALT( b, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX_CHECK_ALT( b )\tLOOP_EXT_CHECK_ALT( b, FAILSAFE_ITERATIONS_MAX )\n\n#define LOOP_MED_INITCHECK_ALT( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK_ALT( a, b, FAILSAFE_ITERATIONS_MED ) \n#define LOOP_MAX_INITCHECK_ALT( a, b ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_INITCHECK_ALT( a, b, FAILSAFE_ITERATIONS_LARGE ) \n\n#define LOOP_MED_CHECKINC_ALT( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC_ALT( b, c, FAILSAFE_ITERATIONS_MED )\n#define LOOP_LARGE_CHECKINC_ALT( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC_ALT( b, c, FAILSAFE_ITERATIONS_LARGE )\n#define LOOP_MAX_CHECKINC_ALT( b, c ) \\\n\t\t\t\t\t\t\t\tLOOP_EXT_CHECKINC_ALT( b, c, FAILSAFE_ITERATIONS_MAX )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSafe Pointers\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Error-detecting function and data pointers.  We store two copies of the \n   pointer, the value itself and its bitwise inverse.  If on retrieving them \n   their XOR isn't all-ones then one of the values has been corrupted and \n   the pointer isn't safe to dereference.  \n\n   A linked list of items using safe pointers looks as follows:\n\n\tDATAPTR --> listItem {\n\t\t\t\t\t...\n\t\t\t\t\tDATAPTR --> listItem {\n\t\t\t\t\t...\t\t\t\t...\n\t\t\t\t\t}\t\t\t\tDATAPTR --> listItem {\n\t\t\t\t\t\t\t\t\t}\t\t\t\t...\n\t\t\t\t\t\t\t\t\t\t\t\t\tDATAPTR --> NULL\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n   Walking down a list of safe pointers works as follows:\n\n\tLOOP_LARGE( listPtr = DATAPTR_GET( listHead ),\n\t\t\t\tlistPtr != NULL,\n\t\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) )\n\n   When traversing a list (meaning walking from one link to the next looking\n   for a particular entry), the access pattern is as above.  When processing\n   entries (meaning working with the elements of listPtr), the pattern \n   becomes:\n\n\tLOOP_LARGE( listPtr = DATAPTR_GET( listHead ),\n\t\t\t\tlistPtr != NULL,\n\t\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tREQUIRES( sanityCheckListEntry( listPtr ) );\n\n\t\tbody;\n\t\t}\n\n   Sometimes we need to have both a LIST_ITEM and the DATAPTR that refers \n   to it available.  This occurs when we're working with a mixture of \n   internal-access (LIST_ITEM) and external-access (DATAPTR) functions.  \n   The following loop structure allows for this dual access:\n\n\tLOOP_LARGE( ( listCursor = listHead,\n\t\t\t\t  listPtr = DATAPTR_GET( listHead ) ),\n\t\t\t\tlistPtr != NULL,\n\t\t\t\t( listCursor = listPtr->next,\n\t\t\t\t  listPtr = DATAPTR_GET( listPtr->next ) ) )\n\n   Dealing with some types of loops is now especially difficult because a \n   pointer can become NULL even after it's been checked for being non-NULL.  \n   To see how this can happen, consider a loop to find the end of a linked \n   list:\n\n\tLOOP( listPtr = DATAPTR_GET( list ),\n\t\t  DATAPTR_ISSET( listPtr->next ),\n\t\t  listPtr = DATAPTR_GET( listPtr->next ) )\n\n   Since DATAPTR_GET() can return NULL on a fault, the DATAPTR_ISSET() check\n   works as a loop condition check but doesn't guarantee that listPtr is \n   non-NULL in the loop body.  To see how this happens, consider the C loop \n   structure:\n\n\tfor( init; check; increment )\n\t\tbody\n\n   This is evaluated as:\n\n\tinit;\n\twhile( check )\n\t\t{\n\t\tbody;\n\tcontinue_label:\n\t\tincrement;\n\t\t}\n\n  So the above loop will be evaluated as:\n\n\tlistPtr = DATAPTR_GET( list ),\n\twhile( DATAPTR_ISSET( listPtr->next ) )\n\t\t{\n\t\tbody;\n\t\tlistPtr = DATAPTR_GET( listPtr->next );\n\t\t}\n\n   If the DATAPTR_GET() in the increment returns NULL then the check\n   DATAPTR_ISSET() will dereference a NULL pointer.\n\n   The workaround for this is to rewrite the loop as:\n\n\tLOOP( listPtr = DATAPTR_GET( list ),\n\t\t  listPtr != NULL && DATAPTR_ISSET( listPtr->next ),\n\t\t  listPtr = DATAPTR_GET( listPtr->next ) )\n\t\t{\n\t\tbody;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( listPtr != NULL && DATAPTR_ISNULL( listPtr->next ) );\n\n   An alternative workaround, using a temporary variable, is:\n\n\tLOOP( ( prevElementPtr = NULL, listPtr = DATAPTR_GET( list ) ), \n\t\t  listPtr != NULL,\n\t\t  ( prevElementPtr = listPtr,\n\t\t\tlistPtr = DATAPTR_GET( listPtr->next ) ) )\n\t\t{\n\t\tbody;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n   The pattern for fetching an attribute from a function that returns a \n   pointer to the attribute is:\n\n\tattributeListPtr = findAttribute( attributeListHead, attributeType );\n\tENSURES( attributeListPtr != NULL );\n\tREQUIRES( sanityCheckAttribute( attributeListPtr ) ); */\n\n/* First we need to define the safe pointer type, a primary copy consisting \n   of a pointer and the alternative copy as an equivalent-sized integer.  We \n   could alternately store two copies of the same value but that wouldn't \n   detect identical corruption on both values.  We could also mask the value \n   with a secret seed generated at runtime, but that's more useful for \n   preventing pointer-overwriting attacks than detecting corruption, and \n   it's not clear whether that's a real threat.  Finally, we could actually \n   store a triple modular-redundant copy, but if we're trying to deal with \n   that level of corruption then there are likely to be all sorts of other \n   problems as well that we'd need to handle.\n   \n   Function pointers get a bit more difficult because there's no equivalent \n   to the 'void *' universal data pointer.  The ostensible reason for this\n   is that function and data pointers may not be of the same size, an example\n   being IA64, which as part of its \"totally idiotic calling conventions\"\n   (Linus) turns pointers into handles.  Since sizeof( data_ptr ) may not be\n   the same as sizeof( fn_ptr ), it follows logically (if you're a compiler\n   author, who run on their own very special type of logic) that we can't \n   have a 'void *' equivalent for function pointers.  Because of this, we \n   have to declare a generic void-ish function, typedef'd as \n   FNPTR_FUNCTION_TYPE, and then cast every assignment to/from it to avoid \n   compiler warnings.\n   \n   An additional complication with function pointers is that for the \n   aforementioned idiotic implementations there's no equivalent to a \n   uintptr_t.  However, this doesn't really affect us because we're not \n   storing a function pointer in a uintptr_t, just using it as a check\n   value.  In this case the worst that can happen is that a few bits of a\n   not-quite-a-pointer implementation of a function pointer don't get\n   checked, but on any sane architecture we'll be OK */\n\n#define FNPTR_TYPE\t\t\t\tuintptr_t\n#define DATAPTR_TYPE\t\t\tuintptr_t\n\ntypedef void ( *FNPTR_FUNCTION_TYPE )( void );\n\ntypedef struct { \n\tvoid *dataPtr; \n\tuintptr_t dataCheck; \n\t} DATAPTR;\ntypedef struct { \n\tFNPTR_FUNCTION_TYPE fnPtr;\n\tuintptr_t fnCheck; \n\t} FNPTR;\n\n/* Initialisers for the safe pointer data.  This is now a scalar so we need \n   both a means of setting it to NULL and a NULL-equivalent value that we\n   can use in places where we'd normally use the constant NULL */\n\n#define FNPTR_INIT\t\t\t\t{ NULL, ( FNPTR_TYPE ) ~0 }\n#define DATAPTR_INIT\t\t\t{ NULL, ( DATAPTR_TYPE ) ~0 }\n\nextern const DATAPTR DATAPTR_NULL;\nextern const FNPTR FNPTR_NULL;\n\n/* Check safe pointers.  There are now three checks that can be performed \n   rather than the usual two NULL/non-NULL ones, since there's a third \n   possibility, \"not valid\".  The latter is required because pointers are \n   now tri-state, valid and non-NULL, valid and NULL, and invalid, which is \n   reported as NULL by FN/DATAPTR_GET() and so would be indistinguishable \n   from valid and NULL */\n\n#define FNPTR_ISVALID( name ) \\\n\t\t( ( ( ( FNPTR_TYPE ) ( name.fnPtr ) ) ^ ( name.fnCheck ) ) == ~0 )\n#define DATAPTR_ISVALID( name ) \\\n\t\t( ( ( ( DATAPTR_TYPE ) ( name.dataPtr ) ) ^ ( name.dataCheck ) ) == ~0 )\n#define DATAPTR_ISVALID_PTR( name ) \\\n\t\t( ( ( ( DATAPTR_TYPE ) ( name->dataPtr ) ) ^ ( name->dataCheck ) ) == ~0 )\n\n#define FNPTR_ISSET( name ) \\\n\t\t( FNPTR_ISVALID( name ) && ( name.fnPtr ) != NULL )\n#define DATAPTR_ISSET( name ) \\\n\t\t( DATAPTR_ISVALID( name ) && ( name.dataPtr ) != NULL )\n#define DATAPTR_ISSET_PTR( name ) \\\n\t\t( DATAPTR_ISVALID_PTR( name ) && ( name->dataPtr ) != NULL )\n\n#define FNPTR_ISNULL( name ) \\\n\t\t( FNPTR_ISVALID( name ) && ( name.fnPtr ) == NULL )\n#define DATAPTR_ISNULL( name ) \\\n\t\t( DATAPTR_ISVALID( name ) && ( name.dataPtr ) == NULL )\n#define DATAPTR_ISNULL_PTR( name ) \\\n\t\t( DATAPTR_ISVALID_PTR( name ) && ( name->dataPtr ) == NULL )\n\n/* Set and get safe pointers.  The macros are used as:\n\n\tDATAPTR ptrStorage;\n\n\tFNPTR_SET( ptrStorage, functionAddress );\n\tDATAPTR_SET( ptrStorage, dataAddress );\n\n\tconst PTR_TYPE functionPtr = FNPTR_GET( ptrStorage );\n\tREQUIRES( functionPtr != NULL );\n\tPTR_TYPE dataPtr = DATAPTR_GET( ptrStorage );\n\tREQUIRES( dataPtr != NULL ); */\n\n#define FNPTR_GET( name ) \\\n\t\t( FNPTR_ISVALID( name ) ? ( name.fnPtr ) : NULL )\n#define DATAPTR_GET( name ) \\\n\t\t( DATAPTR_ISVALID( name ) ? ( name.dataPtr ) : NULL )\n#define DATAPTR_GET_PTR( name ) \\\n\t\t( DATAPTR_ISVALID_PTR( name ) ? ( name->dataPtr ) : NULL )\n\n#define FNPTR_SET( name, value ) \\\n\t\t\t{ \\\n\t\t\tname.fnPtr = ( FNPTR_FUNCTION_TYPE ) value; \\\n\t\t\tname.fnCheck = ( ( FNPTR_TYPE ) ( value ) ) ^ ~0; \\\n\t\t\t}\n#define DATAPTR_SET( name, value ) \\\n\t\t\t{ \\\n\t\t\tname.dataPtr = value; \\\n\t\t\tname.dataCheck = ( ( DATAPTR_TYPE ) ( value ) ) ^ ~0; \\\n\t\t\t}\n#define DATAPTR_SET_PTR( namePtr, value ) \\\n\t\t\t{ \\\n\t\t\tnamePtr->dataPtr = value; \\\n\t\t\tnamePtr->dataCheck = ( ( DATAPTR_TYPE ) ( value ) ) ^ ~0; \\\n\t\t\t}\n\n/* Finally, since DATAPTRs are now scalar values rather than pointers, we \n   have to replace some operations that work on pointers with macros that\n   deal with the use of scalars */\n\n#define DATAPTR_SAME( name1, name2 ) \\\n\t\t( ( ( name1 ).dataPtr ) == ( ( name2 ).dataPtr ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSafe Bitflags\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Safe bitflags.  These are particularly critical because some of them have\n   a considerable influence over how objects are used, for example \n   CONTEXT_FLAG_DUMMY (software vs. external hardware context), \n   DEVICE_FLAG_ACTIVE (device has been unlocked via PIN/password and is \n   ready for use), ENVELOPE_FLAG_ISDEENVELOPE (whether the envelope is used \n   for enveloping or de-enveloping) and so on.  In addition since the flags\n   are all packed into a single integer value, corruption of that value will\n   upset a large range of flags.\n\n   Because of this critical nature we protect flags by making them safe\n   objects, in the same way that pointers are protected.  The macros are used \n   as:\n\n\tSAFE_FLAGS flags;\n\t\n\tINIT_FLAGS( flags, XXX_FLAG_NONE );\n\tCHECK_FLAGS( flags, XXX_FLAG_NONE, XXX_FLAG_MAX );\n\t\n\tSET_FLAG( flags, XXX_FLAG_YYY );\n\tif( TEST_FLAG( flags, XXX_FLAG_YYY )\n\t\tdo_something;\n\tCLEAR_FLAG( flags, XXX_FLAG_YYY ); */\n\ntypedef struct {\n\tint flagValue, flagCheckValue;\n\t} SAFE_FLAGS;\n\n/* Initialisers for the safe flags.  We need both static and dynamic \n   initialision mechanisms */\n\n#define SAFE_FLAGS_INIT( value )\t\t{ ( value ), ~( value ) }\n#define INIT_FLAGS( flags, value ) \\\n\t\t( flags ).flagValue = ( value ), ( flags ).flagCheckValue = ~( value )\n\n/* Check safe flags.  The check doubles as a sanity-check, so it both \n   verifies that the flags are valid in the sense of not having been \n   corrupted and that they've been set to an allowed value */\n\n#define CHECK_FLAGS( flags, minRange, maxRange ) \\\n\t\t( ( ( flags ).flagValue ^ ( flags ).flagCheckValue ) == ~0 && \\\n\t\t  ( ( flags ).flagValue >= ( minRange ) && \\\n\t\t\t( flags ).flagValue <= ( maxRange ) ) )\n\n/* Get, set, and clear flags.  The XXX_FLAG() and XXX_FLAGS() operations do \n   the same thing, so one is aliased to the other */\n\n#define GET_FLAG( flags, value ) \\\n\t\t( ( flags ).flagValue & ( value ) )\n#define SET_FLAG( flags, value ) \\\n\t\t( flags ).flagValue |= ( value ), ( flags ).flagCheckValue &= ~( value )\n#define CLEAR_FLAG( flags, value ) \\\n\t\t( flags ).flagValue &= ~( value ), ( flags ).flagCheckValue |= ( value )\n#define GET_FLAGS\t\tGET_FLAG\n#define SET_FLAGS\t\tSET_FLAG\n#define CLEAR_FLAGS\t\tCLEAR_FLAG\n\n/* Test a flag.  Unlike the other macros there are two distinct versions of \n   this, TEST_FLAG() checks that a single flag value (or one of a set of \n   values) is set, TEST_FLAGS() checks that all specified flags are set */\n\n#define TEST_FLAG\t\tGET_FLAG\n#define TEST_FLAGS( flags, mask, reqFlags ) \\\n\t\t( GET_FLAG( flags, mask ) == ( reqFlags ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSafe Booleans\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Boolean constants.  Since the traditional TRUE = 1, FALSE = 0 only has a \n   single-bit difference between the two and it's going to be used to decide\n   things like \"access authorised\" or \"cryptographic verification succeeded\",\n   we define our own value for TRUE that minimises the chances of a simple\n   fault converting one value to another.  In addition we explicitly check\n   for equality to TRUE rather than just \"is non-zero\".\n\n   Contrast this with things like the NXP LPC devices, which use four magic\n   values, 0x12345678, 0x87654321, 0x43218765, and 0x4E697370 ('Nisp'), to\n   indicate that security is in effect, and the other 4 billion values to\n   indicate that no security is in effect (see \"Breaking Code Read \n   Protection on the NXP LPC-family Microcontrollers\" from RECON BRX 2017),\n   or STM's barely-better 16-bit { 0xAA, 0x55 } = no security, { 0xCC, \n   0x33 } = high security, and the remaining 64K-2 values = medium/low \n   security (\"Shedding too much Light on a Microcontrollers Firmware \n   Protection\" from WOOT 2017).\n\n   The bit pattern in the TRUE value is chosen to minimise the chances of an\n   SEU or similar fault flipping the value into something else that looks \n   valid.  The bit pattern is:\n\n\t0000 0000 1111 1111 0011 0011 1100 1100 || \\\n\t  0\t   0\tF\t F\t  3\t   3\tC\t C\n\n\t0000 1111 0011 1100 0101 0110 1001 1111\n\t  0\t   F\t3\t C\t  5\t   6\t9\t F\n\n   with the more important patterns at the LSB end, so we use the best\n   subset of patterns no matter what the word size is */\n\n#ifdef TRUE\n  #undef TRUE\n#endif /* TRUE */\n#if INT_MAX > 0xFFFFFFFFL\n  #define TRUE\t\t\t0x00FF33CC0F3C569F\n#elif INT_MAX > 0xFFFF\n  #define TRUE\t\t\t0x0F3C569F\n#else\n  #define TRUE\t\t\t0x569F\n#endif /* System-specific word size */\n#if defined( _MSC_VER ) && VC_GE_2010( _MSC_VER )\n  /* VC warns about #if FALSE vs. #ifdef FALSE, since FALSE == 0 */\n  #pragma warning( push )\n  #pragma warning( disable : 4574 )\n#endif /* VS 2010 and above */\n#ifdef FALSE\n  #if FALSE != 0\n\t#error Value of FALSE is nonzero, this isnt a boolean FALSE value.\n  #endif /* FALSE sanity check */\n#else\n  #define FALSE\t\t\t0\n#endif /* FALSE */\n#if defined( _MSC_VER ) && VC_GE_2010( _MSC_VER )\n  #pragma warning( pop )\n#endif /* VS 2010 and above */\n\n/* The fault-detecting value of TRUE is OK for internal use, but for \n   external use we still have to use TRUE = 1, for which we define an\n   alternative constant to make it explicit that this is the external-\n   use TRUE */\n\n#define TRUE_ALT\t\t1\n\n/* Error-detecting boolean variables, used for critical values where we \n   don't want to risk a single bit-flip converting a value from one to the\n   other.  In this case we also define SAFE_BOOL_FALSE to an SEU-immune data \n   value rather than allowing it to be all zeroes.\n   \n   We also mix in an additional value, currently just set to the constant\n   SAFE_BOOL_CONST, to deal with data-injection attacks in which an attacker \n   tries to set a boolean flag to a particular value.   In practice this \n   should be some unpredictable value set at runtime, but for now it's just \n   a no-op placeholder.\n   \n   The usage is:\n\n\tSAFE_BOOLEAN safeBool;\n\n\tBOOL_SET( &safeBool );\n\tBOOL_ISVALID( &safeBool );\n\n\tif( BOOL_ISSET( &safeBool ) )\n\t\tdo_something();\n\tBOOL_CLEAR( &safeBool ); */\n\n#define SAFE_BOOL_TRUE\t\tTRUE\n#if INT_MAX > 0xFFFFFFFFL\n  #define SAFE_BOOL_FALSE\t0x3300CCFF0FC3F596\n#elif INT_MAX > 0xFFFF\n  #define SAFE_BOOL_FALSE\t0x0FC3F596\n#else\n  #define SAFE_BOOL_FALSE\t0xF596\n#endif /* System-specific word size */\n#define SAFE_BOOL_CONST\t\t0\n\ntypedef struct {\n\t\tint value1, value2;\n\t\t} SAFE_BOOLEAN;\n\n#define BOOL_SET( name ) \\\n\t\t{ \\\n\t\t( name )->value1 = SAFE_BOOL_TRUE; \\\n\t\t( name )->value2 = SAFE_BOOL_TRUE ^ SAFE_BOOL_CONST; \\\n\t\t}\n#define BOOL_CLEAR( name ) \\\n\t\t{ \\\n\t\t( name )->value1 = SAFE_BOOL_FALSE; \\\n\t\t( name )->value2 = ~SAFE_BOOL_FALSE ^ SAFE_BOOL_CONST; \\\n\t\t}\n\n#define BOOL_ISSET( name )\t\t( ( ( name )->value1 ^ \\\n\t\t\t\t\t\t\t\t\t( name )->value2 ^ SAFE_BOOL_CONST ) == 0 )\n#define BOOL_ISCLEAR( name )\t( ( ( name )->value1 ^ \\\n\t\t\t\t\t\t\t\t\t( name )->value2 ^ SAFE_BOOL_CONST ) == ~0 )\n#define BOOL_ISVALID( name )\t( BOOL_ISSET( name ) || BOOL_ISCLEAR( name ) )\n\n#endif /* _SAFETY_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/user.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib User Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\t\t/* For snprintf_s() */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"asn1.h\"\n  #include \"user.h\"\n#else\n  #include \"enc_dec/asn1.h\"\n  #include \"misc/user.h\"\n#endif /* Compiler-specific includes */\n\n/* The different types of userID that we can use to look up users in the \n   index */\n\ntypedef enum {\n\tUSERID_NONE,\t\t/* No userID type */\n\tUSERID_USERID,\t\t/* User's userID */\n\tUSERID_CREATORID,\t/* Creating SO's userID */\n\tUSERID_NAME,\t\t/* User's name */\n\tUSERID_LAST\t\t\t/* Last possible userID type */\n\t} USERID_TYPE;\n\n/* cryptlib can work with multiple users (although it's extremely unlikely \n   that there'll ever be more than one or two), we allow a maximum of \n   MAX_USER_OBJECTS in order to discourage them from being used as a\n   substitute for OS user management.  A setting of 32 objects consumes \n   ~4K of memory (32 x ~128), so we choose that as the limit */\n\n#ifdef CONFIG_CONSERVE_MEMORY\n  #define MAX_USER_OBJECTS\t\t4\n#else\n  #define MAX_USER_OBJECTS\t\t32\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* The size of the default buffer used to read data from a keyset.  If\n   the data is larger than this, the buffer is allocated dynamically */\n\n#define USERDATA_BUFFERSIZE\t\t1024\n\n/* The maximum size of the encoded index data */\n\n#define MAX_USERINDEX_SIZE\t( ( 16 + ( KEYID_SIZE * 2 ) + \\\n\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE + 8 ) * MAX_USER_OBJECTS )\n\n/* The structure that stores the user index in the default user object */\n\ntypedef struct {\n\tUSER_FILE_INFO userIndex[ MAX_USER_OBJECTS ];\t/* User index */\n\tint lastEntry;\t\t\t\t\t/* Last entry in user index */\n\t} USER_INDEX_INFO;\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPrimary SO User Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Primary SO user info */\n\nstatic const USER_FILE_INFO primarySOInfo = {\n\tCRYPT_USER_SO,\t\t\t\t\t/* SO user */\n\tUSER_STATE_SOINITED,\t\t\t/* SO initialised, not ready for use */\n\t\"Security officer\", 16,\t\t\t/* Pre-set user name */\n\t\"<<<PRIMARYSO_USER>>>\", \"<<<TETRAGRAMMATON>>>\",\n\t-1\t\t\t/* No user file when starting from zeroised state */\n\t};\n\n/* The primary SO password after zeroisation */\n\n#define PRIMARYSO_PASSWORD\t\t\"zeroised\"\n#define PRIMARYSO_ALTPASSWORD\t\"zeroized\"\n#define PRIMARYSO_PASSWORD_LENGTH 8\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open a user or index keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int openKeyset( OUT_HANDLE_OPT CRYPT_KEYSET *iKeyset, \n\t\t\t\t\t   IN_BUFFER( fileNameLen ) const char *fileName, \n\t\t\t\t\t   IN_LENGTH_SHORT const int fileNameLen, \n\t\t\t\t\t   IN_ENUM_OPT( CRYPT_KEYOPT ) const int options )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tchar userFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint userFilePathLen, status;\n\n\tassert( isWritePtr( iKeyset, sizeof( CRYPT_KEYSET ) ) );\n\tassert( isReadPtrDynamic( fileName, fileNameLen ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( fileNameLen ) );\n\tREQUIRES( isEnumRangeOpt( options, CRYPT_KEYOPT ) );\n\n\t/* Clear return value */\n\t*iKeyset = CRYPT_ERROR;\n\n\t/* Open the given keyset */\n\tstatus = fileBuildCryptlibPath( userFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&userFilePathLen, fileName, fileNameLen, \n\t\t\t\t\t\t\t\t\t( options == CRYPT_KEYOPT_CREATE ) ? \\\n\t\t\t\t\t\t\t\t\tBUILDPATH_CREATEPATH : BUILDPATH_GETPATH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Map the lower-level filesystem-specific error into a more \n\t\t   meaningful generic error */\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );\n\tcreateInfo.arg2 = options;\n\tcreateInfo.strArg1 = userFilePath;\n\tcreateInfo.strArgLen1 = userFilePathLen;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_KEYSET );\n\tif( cryptStatusOK( status ) )\n\t\t*iKeyset = createInfo.cryptHandle;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int openUserKeyset( OUT_HANDLE_OPT CRYPT_KEYSET *iUserKeyset, \n\t\t\t\t\t\t   IN_INT_SHORT_Z const int fileRef, \n\t\t\t\t\t\t   IN_ENUM_OPT( CRYPT_KEYOPT ) const int options )\n\t{\n\tchar userFileName[ 16 + 8 ];\n\tint userFileNameLen;\n\n\tassert( isWritePtr( iUserKeyset, sizeof( CRYPT_KEYSET ) ) );\n\n\tREQUIRES( isShortIntegerRange( fileRef ) );\n\tREQUIRES( isEnumRangeOpt( options, CRYPT_KEYOPT ) );\n\n\tuserFileNameLen = sprintf_s( userFileName, 16, \"u%06x\", fileRef );\n\tENSURES( userFileNameLen > 0 && userFileNameLen < 16 );\n\treturn( openKeyset( iUserKeyset, userFileName, userFileNameLen, \n\t\t\t\t\t\toptions ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int openIndexKeyset( OUT CRYPT_KEYSET *iIndexKeyset, \n\t\t\t\t\t\t\tIN_ENUM_OPT( CRYPT_KEYOPT ) const int options )\n\t{\n\tassert( isWritePtr( iIndexKeyset, sizeof( CRYPT_KEYSET ) ) );\n\n\tREQUIRES( isEnumRange( options, CRYPT_KEYOPT ) );\n\n\treturn( openKeyset( iIndexKeyset, \"index\", 5, options ) );\n\t}\n\n/* Add a user key to the keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \\\nstatic int addKey( IN_HANDLE const CRYPT_KEYSET iUserKeyset, \n\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t   IN_BUFFER( userIdLength ) const void *userID, \n\t\t\t\t   IN_LENGTH_SHORT const int userIdLength,\n\t\t\t\t   IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t   IN_LENGTH_SHORT const int passwordLength,\n\t\t\t\t   const BOOLEAN isPrivateKey )\n\t{\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtrDynamic( userID, userIdLength ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isHandleRangeValid( iUserKeyset ) );\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( userIdLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\tREQUIRES( isPrivateKey == TRUE || isPrivateKey == FALSE );\n\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) userID, userIdLength );\n\tstatus = krnlSendMessage( iUserKeyset, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_USERID );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t   ( MESSAGE_CAST ) password, passwordLength,\n\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = iCryptContext;\n\tstatus = krnlSendMessage( iUserKeyset, IMESSAGE_KEY_SETKEY,\n\t\t\t\t\t\t\t  &setkeyInfo, isPrivateKey ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_ITEM_PRIVATEKEY : \\\n\t\t\t\t\t\t\t\tKEYMGMT_ITEM_SECRETKEY );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tManage User Index\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find a user in the user index.  Note that this search implements a flat\n   namespace rather than allowing duplicate names created by different SOs\n   because when we're looking up a user we don't know which SO they belong\n   to until after we've looked them up */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic const USER_FILE_INFO *findUser( IN_ARRAY( noUserIndexEntries ) \\\n\t\t\t\t\t\t\t\t\t\tconst USER_FILE_INFO *userIndex,\n\t\t\t\t\t\t\t\t\t   IN_RANGE( 1, MAX_USER_OBJECTS ) \\\n\t\t\t\t\t\t\t\t\t\tconst int noUserIndexEntries, \n\t\t\t\t\t\t\t\t\t   IN_ENUM( USERID ) const USERID_TYPE idType, \n\t\t\t\t\t\t\t\t\t   IN_BUFFER( idLength ) const BYTE *id, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int idLength )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( userIndex, \\\n\t\t\t\t\t\t\t  sizeof( USER_FILE_INFO ) * noUserIndexEntries ) );\n\tassert( isReadPtrDynamic( id, idLength ) );\n\n\tREQUIRES_N( noUserIndexEntries > 0 && \\\n\t\t\t\tnoUserIndexEntries <= MAX_USER_OBJECTS );\n\tREQUIRES_N( isEnumRange( idType, USERID ) );\n\tREQUIRES_N( isShortIntegerRangeNZ( idLength ) );\n\n\tLOOP_LARGE( i = 0, i < noUserIndexEntries, i++ )\n\t\t{\n\t\tconst USER_FILE_INFO *userIndexPtr = &userIndex[ i ];\n\n\t\tswitch( idType )\n\t\t\t{\n\t\t\tcase USERID_USERID:\n\t\t\t\tif( idLength == KEYID_SIZE && \\\n\t\t\t\t\t!memcmp( userIndexPtr->userID, id, idLength ) )\n\t\t\t\t\treturn( userIndexPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase USERID_CREATORID:\n\t\t\t\tif( idLength == KEYID_SIZE && \\\n\t\t\t\t\t!memcmp( userIndexPtr->creatorID, id, idLength ) )\n\t\t\t\t\treturn( userIndexPtr );\n\t\t\t\tbreak;\n\n\t\t\tcase USERID_NAME:\n\t\t\t\tif( idLength == userIndexPtr->userNameLength && \\\n\t\t\t\t\t!memcmp( userIndexPtr->userName, id, idLength ) )\n\t\t\t\t\treturn( userIndexPtr );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Null();\n\t\t\t}\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/* Find a free user entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic USER_FILE_INFO *findFreeEntry( IN_ARRAY( noUserIndexEntries ) \\\n\t\t\t\t\t\t\t\t\t\tUSER_FILE_INFO *userIndex,\n\t\t\t\t\t\t\t\t\t  IN_RANGE( 1, MAX_USER_OBJECTS ) \\\n\t\t\t\t\t\t\t\t\t\tconst int noUserIndexEntries,\n\t\t\t\t\t\t\t\t\t  OUT int *fileRef )\n\t{\n\tUSER_FILE_INFO *userIndexPtr;\n\tint newFileRef, i, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( userIndex, \\\n\t\t\t\t\t\t\t   sizeof( USER_FILE_INFO ) * noUserIndexEntries ) );\n\tassert( isWritePtr( fileRef, sizeof( int ) ) );\n\n\tREQUIRES_N( noUserIndexEntries > 0 && \\\n\t\t\t\tnoUserIndexEntries <= MAX_USER_OBJECTS );\n\n\t/* Clear return value */\n\t*fileRef = CRYPT_ERROR;\n\n\t/* Look for an available free entry */\n\tLOOP_LARGE( i = 0, i < noUserIndexEntries, i++ )\n\t\t{\n\t\tif( userIndex[ i ].state == USER_STATE_NONE )\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tif( i >= noUserIndexEntries )\n\t\t{\n\t\t/* No more available entries */\n\t\t*fileRef = CRYPT_ERROR;\n\t\treturn( NULL );\n\t\t}\n\n\t/* Remember where we found our match */\n\tuserIndexPtr = &userIndex[ i ];\n\n\t/* We've found a free entry, now look for an unused fileRef.  There are \n\t   two possible strategies for this, the first is to make it generational\n\t   and always allocate a new fileRef, the second is to use the smallest\n\t   available value, i.e. to re-use values.  The former has problems with\n\t   overflow (although it'd have to be a pretty funny situation to cause \n\t   this), the latter has potential problems with user confusion when one\n\t   ref #3 user file is replaced by another ref #3 file that belongs to\n\t   a completely different user.  However, even the generational approach\n\t   has problems (unless we can make the last-used fileRef persistent)\n\t   because deleting the highest-numbered ref. and then creating a new one\n\t   will result in the fileRef being re-allocated to the newly-created\n\t   file.\n\n\t   Since this is all highly speculative (it's not certain under what \n\t   conditions we could run into these problems because users aren't \n\t   expected to be bypassing cryptlib to directly access the user files),\n\t   we take the simplest approach and use the lowest-value free fileRef.\n\t   This is somewhat ugly because it's potentially an O( n^2 ) operation,\n\t   but the actualy impact is insignificant because the number of users\n\t   is tiny and new user creation is extremely rare, so it's not worth\n\t   switching to the complexity of a more sophisticated algorithm */\n\tLOOP_MED( newFileRef = 0, newFileRef < MAX_USER_OBJECTS, newFileRef++ )\n\t\t{\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Check whether this fileRef is already in use.  If not, we're\n\t\t   done */\n\t\tLOOP_MED_ALT( i = 0, i < noUserIndexEntries, i++ )\n\t\t\t{\n\t\t\tif( userIndex[ i ].fileRef == newFileRef )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK_ALT );\n\t\tif( i >= MAX_USER_OBJECTS )\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( newFileRef < MAX_USER_OBJECTS );\n\t*fileRef = newFileRef;\n\n\treturn( userIndexPtr );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int createUserEntry( OUT_PTR_COND USER_FILE_INFO **userIndexPtrPtr,\n\t\t\t\t\t\t\tIN_ARRAY( noUserIndexEntries ) \\\n\t\t\t\t\t\t\t\tUSER_FILE_INFO *userIndex, \n\t\t\t\t\t\t\tIN_RANGE_FIXED( MAX_USER_OBJECTS ) \\\n\t\t\t\t\t\t\t\tconst int noUserIndexEntries,\n\t\t\t\t\t\t\tINOUT USER_FILE_INFO *userFileInfo )\n\t{\n\tUSER_FILE_INFO *userIndexPtr;\n\tint fileRef, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( userIndexPtrPtr, sizeof( USER_FILE_INFO * ) ) );\n\tassert( isWritePtrDynamic( userIndex, \\\n\t\t\t\t\t\t\t   sizeof( USER_FILE_INFO ) * noUserIndexEntries ) );\n\tassert( isWritePtr( userFileInfo, sizeof( USER_FILE_INFO ) ) );\n\n\tREQUIRES( noUserIndexEntries > 0 && \\\n\t\t\t  noUserIndexEntries <= MAX_USER_OBJECTS );\n\n\t/* Clear return value */\n\t*userIndexPtrPtr = NULL;\n\n\t/* Check whether this user is already present in the index */\n\tif( findUser( userIndex, noUserIndexEntries, USERID_NAME, \n\t\t\t\t  userFileInfo->userName, userFileInfo->userNameLength ) != NULL )\n\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t/* Make sure that the userID that we're using is unique.  This is a \n\t   pretty straightforward operation, we just keep generating new random \n\t   IDs until we get one that's not already present */\n\tLOOP_MED_INITCHECK( status = CRYPT_OK, cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\t/* If this userID isn't present, we're done */\n\t\tif( findUser( userIndex, noUserIndexEntries, USERID_USERID, \n\t\t\t\t\t  userFileInfo->userID, KEYID_SIZE ) == NULL )\n\t\t\tbreak;\n\n\t\t/* The userID is already present, generate a new one */\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) userFileInfo->userID, \n\t\t\t\t\t\tKEYID_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Locate a new unused entry that we can use */\n\tuserIndexPtr = findFreeEntry( userIndex, MAX_USER_OBJECTS, &fileRef );\n\tif( userIndexPtr == NULL )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tuserFileInfo->fileRef = fileRef;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the user index file:\n\n\tUserIndexEntry ::= SEQUENCE {\n\t\tiD\t\t\t\t\tOCTET STRING SIZE(16),\t-- User ID\n\t\tcreatorID\t\t\tOCTET STRING SIZE(16),\t-- Creating SO's ID\n\t\tname\t\t\t\tUTF8String,\t\t\t\t-- User name\n\t\tfileReference\t\tINTEGER\t\t\t\t\t-- Reference to user file\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readIndexEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT USER_FILE_INFO *userIndexPtr )\n\t{\n\tUSER_FILE_INFO userIndexEntry;\n\tlong value;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( userIndexPtr, sizeof( USER_FILE_INFO ) ) );\n\n\t/* Clear return value */\n\tmemset( userIndexPtr, 0, sizeof( USER_FILE_INFO ) );\n\n\t/* Read the user index data */\n\tmemset( &userIndexEntry, 0, sizeof( USER_FILE_INFO ) );\n\treadSequence( stream, NULL );\n\treadOctetString( stream, userIndexEntry.userID, &length, KEYID_SIZE, \n\t\t\t\t\t KEYID_SIZE );\n\treadOctetString( stream, userIndexEntry.creatorID, &length, KEYID_SIZE, \n\t\t\t\t\t KEYID_SIZE );\n\treadCharacterString( stream, userIndexEntry.userName, \n\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE, &userIndexEntry.userNameLength, \n\t\t\t\t\t\t BER_STRING_UTF8 );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isIntegerRange( value ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tuserIndexEntry.fileRef = value;\n\n\t/* Return the result to the caller */\n\tmemcpy( userIndexPtr, &userIndexEntry, sizeof( USER_FILE_INFO ) );\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_RANGE( 0, maxUserObjects ) STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int readIndex( IN_HANDLE const CRYPT_KEYSET iIndexKeyset, \n\t\t\t\t\t  IN_ARRAY( maxUserObjects ) USER_FILE_INFO *userIndex, \n\t\t\t\t\t  IN_RANGE( 1, MAX_USER_OBJECTS ) const int maxUserObjects )\n\t{\n\tSTREAM stream;\n\tDYNBUF userIndexDB;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( userIndex, \\\n\t\t\t\t\t\t\t   maxUserObjects * sizeof( USER_FILE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iIndexKeyset ) );\n\tREQUIRES( maxUserObjects > 0 && maxUserObjects <= MAX_USER_OBJECTS );\n\n\t/* Read the user index file into memory */\n\tstatus = dynCreate( &userIndexDB, iIndexKeyset, \n\t\t\t\t\t\tCRYPT_IATTRIBUTE_USERINDEX );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, dynData( userIndexDB ), dynLength( userIndexDB ) );\n\tLOOP_LARGE( i = 0,  \n\t\t\t\tcryptStatusOK( status ) && \\\n\t\t\t\t\tstell( &stream ) < dynLength( userIndexDB ) && \\\n\t\t\t\t\ti < maxUserObjects,\n\t\t\t\ti++ )\n\t\t{\n\t\tstatus = readIndexEntry( &stream, &userIndex[ i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\tdynDestroy( &userIndexDB );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( i > maxUserObjects )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\treturn( i );\n\t}\n\n/* Write the user index file */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeUserIndexEntry( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tconst USER_FILE_INFO *userIndexPtr )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( userIndexPtr, sizeof( USER_FILE_INFO ) ) );\n\n\twriteSequence( stream, 2 * sizeofObject( KEYID_SIZE ) + \\\n\t\t\t\t   sizeofObject( userIndexPtr->userNameLength ) + \\\n\t\t\t\t   sizeofShortInteger( userIndexPtr->fileRef) );\n\twriteOctetString( stream, userIndexPtr->userID, KEYID_SIZE, DEFAULT_TAG );\n\twriteOctetString( stream, userIndexPtr->creatorID, KEYID_SIZE, DEFAULT_TAG );\n\twriteCharacterString( stream, userIndexPtr->userName,\n\t\t\t\t\t\t  userIndexPtr->userNameLength, BER_STRING_UTF8 );\n\treturn( writeShortInteger( stream, userIndexPtr->fileRef, DEFAULT_TAG ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int writeUserIndex( IN_HANDLE const CRYPT_KEYSET iIndexKeyset,\n\t\t\t\t\t\t   IN_ARRAY( noUserIndexEntries ) \\\n\t\t\t\t\t\t\tUSER_FILE_INFO *userIndex, \n\t\t\t\t\t\t   IN_RANGE( 1, MAX_USER_OBJECTS ) \\\n\t\t\t\t\t\t\tconst int noUserIndexEntries )\n\t{\n\tSTREAM stream;\n\tMESSAGE_DATA msgData;\n\tBYTE userIndexData[ MAX_USERINDEX_SIZE + 8 ];\n\tint userIndexDataLength, i;\n\tint status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( userIndex, \\\n\t\t\t\t\t\t\t   noUserIndexEntries * sizeof( USER_FILE_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iIndexKeyset ) );\n\tREQUIRES( noUserIndexEntries > 0 && \\\n\t\t\t  noUserIndexEntries <= MAX_USER_OBJECTS );\n\n\t/* Write the user index data to a buffer so that we can send it to the \n\t   index keyset */\n\tsMemOpen( &stream, userIndexData, MAX_USERINDEX_SIZE );\n\tLOOP_LARGE( i = 0,  \n\t\t\t\ti < noUserIndexEntries && cryptStatusOK( status ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( userIndex[ i ].state != USER_STATE_NONE )\n\t\t\tstatus = writeUserIndexEntry( &stream, &userIndex[ i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tuserIndexDataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the user index data to the keyset */\n\tsetMessageData( &msgData, userIndexData, userIndexDataLength );\n\treturn( krnlSendMessage( iIndexKeyset, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_USERINDEX ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/Write User Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write user data:\n\n\tUserInfo ::= SEQUENCE {\n\t\trole\t\t\t\tENUMERATED,\t\t\t\t-- SO/user/CA\n\t\tiD\t\t\t\t\tOCTET STRING SIZE(16),\t-- User ID\n\t\tcreatorID\t\t\tOCTET STRING SIZE(16),\t-- Creating SO's ID\n\t\tname\t\t\t\tUTF8String,\t\t\t\t-- User name\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readUserData( INOUT USER_FILE_INFO *userFileInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( userDataLength ) const void *userData, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int userDataLength )\n\t{\n\tSTREAM stream;\n\tint enumValue, length, status;\n\n\tassert( isWritePtr( userFileInfoPtr, sizeof( USER_FILE_INFO ) ) );\n\tassert( isReadPtrDynamic( userData, userDataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( userDataLength ) );\n\n\t/* Clear return value */\n\tmemset( userFileInfoPtr, 0, sizeof( USER_FILE_INFO ) );\n\n\t/* Read the user info */\n\tsMemConnect( &stream, userData, userDataLength );\n\treadSequence( &stream, NULL );\n\treadEnumerated( &stream, &enumValue );\n\tuserFileInfoPtr->type = enumValue;\n\treadOctetString( &stream, userFileInfoPtr->userID, &length, \n\t\t\t\t\t KEYID_SIZE, KEYID_SIZE );\n\treadOctetString( &stream, userFileInfoPtr->creatorID, &length, \n\t\t\t\t\t KEYID_SIZE, KEYID_SIZE );\n\tstatus = readCharacterString( &stream, userFileInfoPtr->userName,\n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  &userFileInfoPtr->userNameLength,\n\t\t\t\t\t\t\t\t  BER_STRING_UTF8 );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int writeUserData( OUT_BUFFER( userDataMaxLength, \\\n\t\t\t\t\t\t\t\t\t  *userDataLength ) void *userData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int userDataMaxLength,\n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( userDataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *userDataLength, \n\t\t\t\t\t\t  const USER_INFO *userInfoPtr )\n\t{\n\tconst USER_FILE_INFO *userFileInfo = &userInfoPtr->userFileInfo;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtrDynamic( userData, userDataMaxLength ) );\n\tassert( isWritePtr( userDataLength, sizeof( int ) ) );\n\tassert( isReadPtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( userDataMaxLength ) );\n\n\t/* Clear return values */\n\tmemset( userData, 0, min( 16, userDataMaxLength ) );\n\t*userDataLength = 0;\n\n\t/* Write the user information to a memory buffer */\n\tsMemOpen( &stream, userData, userDataMaxLength );\n\twriteSequence( &stream, sizeofShortInteger( userFileInfo->type ) + \\\n\t\t\t\t   2 * sizeofObject( KEYID_SIZE ) + \\\n\t\t\t\t   sizeofObject( userFileInfo->userNameLength ) );\n\twriteEnumerated( &stream, userFileInfo->type, DEFAULT_TAG );\n\twriteOctetString( &stream, userFileInfo->userID, KEYID_SIZE, \n\t\t\t\t\t  DEFAULT_TAG );\n\twriteOctetString( &stream, userFileInfo->creatorID, KEYID_SIZE, \n\t\t\t\t\t  DEFAULT_TAG );\n\tstatus = writeCharacterString( &stream, userFileInfo->userName,\n\t\t\t\t\t\t\t\t   userFileInfo->userNameLength, \n\t\t\t\t\t\t\t\t   BER_STRING_UTF8 );\n\tif( cryptStatusOK( status ) )\n\t\t*userDataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Send user data to a user keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int commitUserData( IN_HANDLE const CRYPT_KEYSET iUserKeyset, \n\t\t\t\t\t\t   const USER_INFO *userInfoPtr, \n\t\t\t\t\t\t   IN_BUFFER( userDataLength ) const void *userData, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int userDataLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( userData, userDataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iUserKeyset ) );\n\tREQUIRES( isShortIntegerRangeNZ( userDataLength ) );\n\n\t/* Add the user ID and SO-signed user info to the keyset */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) userData, userDataLength );\n\tstatus = krnlSendMessage( iUserKeyset, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_USERINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, \n\t\t\t\t\t\t( MESSAGE_CAST ) userInfoPtr->userFileInfo.userID,\n\t\t\t\t\t\tKEYID_SIZE );\n\t\tstatus = krnlSendMessage( iUserKeyset, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_USERID );\n\t\t}\n\treturn( status );\n\t}\n\n/* Read a user's info from a user keyset and verify it using the creating\n   SO's key */\n\n#if 0\t/*!!!!!!!!!!!!!!! Needs a serious overhaul !!!!!!!!!!!!!!!!!!!!!*/\n\t\t/*!!!!!!!!!!!!! Should also do recursive walk !!!!!!!!!!!!!!!!!!*/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getCheckUserInfo( INOUT USER_FILE_INFO *userFileInfoPtr, \n\t\t\t\t\t\t\t IN_INT_SHORT_Z const int fileRef )\n\t{\n\tCRYPT_ALGO_TYPE hashAlgo;\n\tCRYPT_CONTEXT iHashContext;\n\tCRYPT_KEYSET iUserKeyset;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tSTREAM stream;\n\tDYNBUF userDataDB;\n\tvoid *hashDataPtr, *signaturePtr;\n\tint soFileRef, hashDataLength, signatureLength, status;\n\n\tassert( isWritePtr( userFileInfoPtr, sizeof( USER_FILE_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRange( fileRef ) );\n\n\t/* Clear return values */\n\tmemset( userFileInfoPtr, 0, sizeof( USER_FILE_INFO ) );\n\n\t/* Open the user keyset and read the user data from it */\n\tstatus = openUserKeyset( &iUserKeyset, fileRef, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = dynCreate( &userDataDB, iUserKeyset, \n\t\t\t\t\t\tCRYPT_IATTRIBUTE_USERINFO );\n\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Burrow into the user info to get the information we need.  We do it\n\t   this way rather than using envelopes because we don't need the full\n\t   generality of the enveloping process (we know exactly what data to\n\t   expect) and to avoid the overhead of de-enveloping data every time a\n\t   user logs in */\n\tsMemConnect( &stream, dynData( userDataDB ), dynLength( userDataDB ) );\n\treadSequence( &stream, NULL );\t\t\t/* Outer wrapper */\n\treadUniversal( &stream );\t\t\t\t/* ContentType OID */\n\treadConstructed( &stream, NULL, 0 );\t/* Content */\n\treadSequence( &stream, NULL );\n\treadUniversal( &stream );\t\t\t\t/* Version */\n\tstatus = readSet( &stream, NULL );\t\t/* DigestAlgorithms */\n\tif( cryptSatusOK( status ) )\n\t\treadAlgoID( &stream, &hashAlgo );\n\treadSequence( &stream, NULL );\t\t\t/* EncapContentInfo */\n\treadUniversal( &stream );\t\t\t\t/* ContentType OID */\n\treadConstructed( &stream, NULL, 0 );\t/* Content type wrapper */\n\tstatus = readGenericHole( &stream, &hashDataLength, 16, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tdynDestroy( &userDataDB );\n\t\treturn( status );\n\t\t}\n\thashDataPtr = sMemBufPtr( &stream );\n\n\t/* Read the user info */\n\tstatus = readUserData( userFileInfoPtr, hashDataPtr, hashDataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tdynDestroy( &userDataDB );\n\t\treturn( status );\n\t\t}\n\n\t/* Hash the signed data and verify the signature using the SO key */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdynDestroy( &userDataDB );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tiHashContext = createInfo.cryptHandle;\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, hashDataPtr, \n\t\t\t\t\t hashDataLength );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tdynDestroy( &userDataDB );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Read the signature */\n\tstatus = readSet( &stream, &signatureLength );\n\tsignaturePtr = sMemBufPtr( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Open the SO keyset and read the SO public key from it */\n\tstatus = soFileRef = \\\n\t\tfindUserIndexEntry( USERID_USERID, userFileInfoPtr->creatorID, \n\t\t\t\t\t\t\tKEYID_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = openUserKeyset( &iUserKeyset, soFileRef, \n\t\t\t\t\t\t\t\t CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,\n\t\t\t\t\t\t   userFileInfoPtr->creatorID, KEYID_SIZE, NULL, 0,\n\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( iUserKeyset, IMESSAGE_KEY_GETKEY,\n\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Verify the signature using the SO key */\n\tstatus = iCryptCheckSignatureEx( signaturePtr, signatureLength,\n\t\t\t\t\t\t\t\t\t CRYPT_FORMAT_CRYPTLIB,\n\t\t\t\t\t\t\t\t\t getkeyInfo.cryptHandle, iHashContext, \n\t\t\t\t\t\t\t\t\t NULL );\n\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\t/* MAC (???) using password - needs PKCS #15 changes */\n\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n\treturn( status );\n\t}\n#endif /*!!!!!!!!!!!!!!! Needs a serious overhaul !!!!!!!!!!!!!!!!!!!!!*/\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSO Management Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return the primary SO user info.  This is used as a template to create \n   the primary SO user after a zeroise */\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst USER_FILE_INFO *getPrimarySoUserInfo( void )\n\t{\n\treturn( &primarySOInfo );\n\t}\n\n#ifdef USE_ENVELOPES\n\n/* Sign the user info and write it to the user keyset */\n\nCHECK_RETVAL \\\nstatic int signUserData( IN_HANDLE const CRYPT_KEYSET iUserKeyset,\n\t\t\t\t\t\t IN_HANDLE const CRYPT_CONTEXT iSignContext )\n\t{\n\tERROR_INFO errorInfo;\n\tBYTE userInfoBuffer[ USERDATA_BUFFERSIZE + 8 ];\n\tint userInfoLength, status;\n\n\tREQUIRES( isHandleRangeValid( iUserKeyset ) );\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\n\t/* Set dummy user data */\n\tmemset( userInfoBuffer, '*', 16 );\n\tuserInfoLength = 16;\n\n\t/* Sign the data via an envelope.  This is kind of heavyweight, but it's \n\t   OK because we rarely create new users and it saves having to hand-\n\t   assemble the data like the PKCS #15 code does */\n\tstatus = envelopeSign( userInfoBuffer, userInfoLength, \n\t\t\t\t\t\t   userInfoBuffer, USERDATA_BUFFERSIZE, \n\t\t\t\t\t\t   &userInfoLength, CRYPT_CONTENT_DATA, \n\t\t\t\t\t\t   iSignContext, CRYPT_UNUSED, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( CRYPT_ERROR_SIGNATURE );\n\t}\n\nCHECK_RETVAL \\\nstatic int sigCheckUserData( void )\n\t{\n\treturn( CRYPT_ERROR_SIGNATURE );\n\t}\n#endif /* USE_ENVELOPES */\n\n/* Create an SO private key and write it to the user keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int createSOKey( IN_HANDLE const CRYPT_KEYSET iUserKeyset,\n\t\t\t\t\t\tINOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int passwordLength )\n\t{\n\tconst USER_FILE_INFO *userFileInfo = &userInfoPtr->userFileInfo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int actionPerms = MK_ACTION_PERM( MESSAGE_CTX_SIGN,\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK,\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL );\n\tint status;\n\n\tassert( isReadPtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isHandleRangeValid( iUserKeyset ) );\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\n\t/* Create the SO private key, making it internal and signature-only */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) userFileInfo->userName,\n\t\t\t\t\tmin( userFileInfo->userNameLength, CRYPT_MAX_TEXTSIZE ) );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\tstatus = krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( int * ) &actionPerms,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add the SO private key to the keyset */\n\tstatus = addKey( iUserKeyset, createInfo.cryptHandle, \n\t\t\t\t\t userFileInfo->userID, KEYID_SIZE, password, \n\t\t\t\t\t passwordLength, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\tuserInfoPtr->iCryptContext = createInfo.cryptHandle;\n\treturn( CRYPT_OK );\n\t}\n\n#if 0\t/* Currently unused, for future use for CA users */\n\n/* Create a CA secret key and write it to the user keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \\\nstatic int createCAKey( IN_HANDLE const CRYPT_KEYSET iUserKeyset,\n\t\t\t\t\t\tINOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int passwordLength )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int actionPerms = MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL ) | \\\n\t\t\t\t\t\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t\t\t\tACTION_PERM_NONE_EXTERNAL );\n\tint status;\n\n\tassert( isReadPtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isHandleRangeValid( iUserKeyset ) );\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\n\t/* Create the CA secret key, making it internal-only */\n\tsetMessageCreateObjectInfo( &createInfo, DEFAULT_CRYPT_ALGO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, userInfoPtr->userID, KEYID_SIZE );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_CTXINFO_LABEL );\n\tstatus = krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( int * ) &actionPerms,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add the CA secret key to the keyset */\n\tstatus = addKey( iUserKeyset, createInfo.cryptHandle, \n\t\t\t\t\t userInfoPtr->userID, KEYID_SIZE, password, \n\t\t\t\t\t passwordLength, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/* Create a primary SO user.  This can only occur when we're in the zeroised \n   state */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createPrimarySoUser( INOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\t\t\tIN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int passwordLength )\n\t{\n\tCRYPT_KEYSET iIndexKeyset, iUserKeyset;\n\tUSER_FILE_INFO userIndex;\n\tBYTE userData[ USERDATA_BUFFERSIZE + 8 ];\n\tint userDataLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\n\t/* Create the user index file and user file for the primary SO user */\n\tstatus = openIndexKeyset( &iIndexKeyset, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = openUserKeyset( &iUserKeyset, 0, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Update the index file */\n\tmemcpy( &userIndex, &userInfoPtr->userFileInfo, \n\t\t\tsizeof( USER_FILE_INFO ) );\n\tuserIndex.fileRef = 0;\n\tstatus = writeUserIndex( iIndexKeyset, &userIndex, 1 );\n\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We couldn't update the index file, delete the newly-created user\n\t\t   keyset. Since we haven't written anything to it, it's zero-length\n\t\t   so it's deleted automatically on close */\n\t\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tuserInfoPtr->iKeyset = iUserKeyset;\n\n\t/* Create the SO key and the user keyset file */\n\tstatus = createSOKey( iUserKeyset, userInfoPtr, password, \n\t\t\t\t\t\t  passwordLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeUserData( userData, USERDATA_BUFFERSIZE, \n\t\t\t\t\t\t\t\t&userDataLength, userInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = commitUserData( iUserKeyset, userInfoPtr, userData, \n\t\t\t\t\t\t\t\t userDataLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The primary SO create failed, return to the zeroised state.  \n\t\t   Since we're already in an exception state here there's not\n\t\t   much that we can do if the zeroise fails */\n\t\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\t\t( void ) zeroiseUsers( userInfoPtr );\n\t\treturn( status );\n\t\t}\n\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n/*status = createCAKey( iUserKeyset, userInfoPtr, password, passwordLength );*/\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUser Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a supplied password is the zeroise password */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isZeroisePassword( IN_BUFFER( passwordLen ) const char *password,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int passwordLen )\n\t{\n\tassert( isReadPtrDynamic( password, passwordLen ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( passwordLen ) );\n\n\tif( passwordLen != PRIMARYSO_PASSWORD_LENGTH )\n\t\treturn( FALSE );\n\treturn( !memcmp( password, PRIMARYSO_PASSWORD, \n\t\t\t\t\t PRIMARYSO_PASSWORD_LENGTH ) || \\\n\t\t\t!memcmp( password, PRIMARYSO_ALTPASSWORD,\n\t\t\t\t\t PRIMARYSO_PASSWORD_LENGTH ) ? \\\n\t\t\tTRUE : FALSE );\n\t}\n\n/* Perform a zeroise */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint zeroiseUsers( INOUT USER_INFO *userInfoPtr )\n\t{\n\tUSER_INDEX_INFO *userIndexInfo = userInfoPtr->userIndexPtr;\n\tUSER_FILE_INFO *userIndex = userIndexInfo->userIndex;\n\tchar userFilePath[ MAX_PATH_LENGTH + 1 + 8 ];\n\tint userFilePathLen, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\t/* Read the user index and step through each entry clearing the user \n\t   info for it */\n\tLOOP_LARGE( i = 0, i < userIndexInfo->lastEntry, i++ )\n\t\t{\n\t\tchar userFileName[ 16 + 8 ];\n\n\t\t/* Erase the given user keyset */\n\t\tsprintf_s( userFileName, 16, \"u%06x\",  userIndex[ i ].fileRef );\n\t\tstatus = fileBuildCryptlibPath( userFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t\t&userFilePathLen, userFileName, \n\t\t\t\t\t\t\t\t\t\tstrlen( userFileName ), \n\t\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tuserFilePath[ userFilePathLen ] = '\\0';\n\t\t\tfileErase( userFilePath );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Erase the index file */\n\tstatus = fileBuildCryptlibPath( userFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&userFilePathLen, \"index\", 5, \n\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tuserFilePath[ userFilePathLen ] = '\\0';\n\t\tfileErase( userFilePath );\n\t\t}\n\treturn( status );\n\t}\n\n/* Create a user keyset */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createUserKeyset( INOUT USER_INFO *defaultUserInfoPtr,\n\t\t\t\t\t\t\t INOUT USER_INFO *newUserInfoPtr )\n\t{\n\tCRYPT_KEYSET iIndexKeyset, iUserKeyset;\n\tUSER_FILE_INFO *userFileInfo = &newUserInfoPtr->userFileInfo;\n\tUSER_FILE_INFO *userIndexPtr;\n\tint status;\n\n\tassert( isReadPtr( defaultUserInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtr( newUserInfoPtr, sizeof( USER_INFO ) ) );\n\n\t/* Try and open the index file */\n\tstatus = openIndexKeyset( &iIndexKeyset, CRYPT_IKEYOPT_EXCLUSIVEACCESS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the index entry for the new user */\n\tstatus = createUserEntry( &userIndexPtr, \n\t\t\t\t\t\t\t  defaultUserInfoPtr->userIndexPtr, \n\t\t\t\t\t\t\t  MAX_USER_OBJECTS, userFileInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( userIndexPtr != NULL );\n\n\t/* Create the user keyset */\n\tstatus = openUserKeyset( &iUserKeyset, userFileInfo->fileRef, \n\t\t\t\t\t\t\t CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* We've got the user keyset and info created, update the in-memory \n\t   index and index file */\n\tmemcpy( userIndexPtr, userFileInfo, sizeof( USER_FILE_INFO ) );\n\tstatus = writeUserIndex( iIndexKeyset, defaultUserInfoPtr->userIndexPtr, \n\t\t\t\t\t\t\t MAX_USER_OBJECTS );\n\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We couldn't update the index file, delete the newly-created user\n\t\t   keyset (since we haven't written anything to it, it's zero-length\n\t\t   so it's deleted automatically on close) */\n\t\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\n\t/* Clean up */\n\treturn( status );\n\t}\n\n/* Set/change the password for a user object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setUserPassword( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t IN_LENGTH_SHORT const int passwordLength )\n\t{\n\tCRYPT_KEYSET iUserKeyset;\n\tUSER_FILE_INFO *userFileInfo = &userInfoPtr->userFileInfo;\n\tint status;\n\n\tassert( isReadPtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n/*!!!!!! Dummy references to keep the compiler happy !!!!!*/\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n{\nUSER_FILE_INFO dummyUserInfo = { 0 }, *userFileInfoPtr = &dummyUserInfo;\nUSER_INFO userInfo;\n\n( void ) readUserData( userFileInfoPtr, \"\", 1 );\n#ifdef USE_ENVELOPES\nmemset( &userInfo, 0, sizeof( USER_INFO ) );\n( void ) signUserData( 0, 0 );\n( void ) sigCheckUserData();\n#endif /* USE_ENVELOPES */\n( void ) createSOKey( 0, &userInfo, \"\", 1 );\n( void ) createUserKeyset( &userInfo, &userInfo );\n}\n/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n\t/* No-one can ever directly set the default SO password */\n\tif( passwordLength == PRIMARYSO_PASSWORD_LENGTH && \\\n\t\t( !memcmp( password, PRIMARYSO_PASSWORD,\n\t\t\t\t   PRIMARYSO_PASSWORD_LENGTH ) || \\\n\t\t  !memcmp( password, PRIMARYSO_ALTPASSWORD,\n\t\t\t\t   PRIMARYSO_PASSWORD_LENGTH ) ) )\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\n\t/* If we're setting the password for the primary SO in the zeroised\n\t   state, create a new user keyset and SO authentication key and write\n\t   the details to the keyset */\n\tif( userFileInfo->fileRef == -1 )\n\t\t{\n\t\tstatus = createPrimarySoUser( userInfoPtr, password, \n\t\t\t\t\t\t\t\t\t  passwordLength );\n\t\t\n\t\treturn( status );\n\t\t}\n\n\t/* Open an existing user keyset */\n\tstatus = openUserKeyset( &iUserKeyset, userFileInfo->fileRef, \n\t\t\t\t\t\t\t CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\t/* set state = USER_INITED */\n\t/* write MAC( ??? ) to user file - needs PKCS #15 changes */\n\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n\t/* Close the keyset and commit the changes */\n\tkrnlSendNotifier( iUserKeyset, IMESSAGE_DECREFCOUNT );\n\n\t/* The password has been set, we're now in the user inited state */\n\tuserFileInfo->state = USER_STATE_USERINITED;\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise the user index in the default user object from the index file,\n   and clean up after we're done with it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initUserIndex( OUT_PTR_OPT void **userIndexPtrPtr )\n\t{\n\tCRYPT_KEYSET iIndexKeyset;\n\tUSER_INDEX_INFO *userIndexInfo;\n\tint noEntries, status;\n\n\tassert( isWritePtr( userIndexPtrPtr, sizeof( void * ) ) );\n\n\t/* Clear return value */\n\t*userIndexPtrPtr = NULL;\n\n\t/* Open the index file and read the index entries from it.  We open it\n\t   in exclusive mode since nothing else should be accessing it at this\n\t   point.\n\n\t   What to do if this fails is a bit tricky (see the comment in\n\t   createDefaultUserObject() for the config file read), however for the \n\t   index keyset it's a bit more clear-cut, we shouldn't fail if the\n\t   access fails so we just skip it and continue, making it look as if\n\t   we're in the zeroised state */\n\tstatus = openIndexKeyset( &iIndexKeyset, CRYPT_IKEYOPT_EXCLUSIVEACCESS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there's no index file present, we're already in the zeroised\n\t\t   state */\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* If keysets are disabled, we fall back to the hardwired \n\t\t   configuration parameters */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Warn the user (in debug mode) that something went wrong */\n \t\tDEBUG_DIAG_ERRMSG(( \"User index read failed with status %s, \"\n\t\t\t\t\t\t\t\"assuming zeroised state\", \n\t\t\t\t\t\t\tgetStatusName( status ) ));\n\t\tassert( DEBUG_WARN );\n\n#if 0\t/* Another problematic choice, should we potentially destroy a \n\t\t   damaged index or leave it for the user to fix up?  Since this \n\t\t   situation would never normally occur we leave it as a user-to-fix\n\t\t   for now */\n\t\t/* If there's something there but it's damaged, delete it so that we \n\t\t   can start again */\n\t\tif( status == CRYPT_ERROR_BADDATA )\n\t\t\t{\n\t\t\tchar userFilePath[ MAX_PATH_LENGTH + 1 + 8 ];\n\t\t\tint userFilePathLen;\n\n\t\t\tstatus = fileBuildCryptlibPath( userFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t\t\t&userFilePathLen, \"index\", 5,\n\t\t\t\t\t\t\t\t\t\t\tBUILDPATH_GETPATH );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tuserFilePath[ userFilePathLen ] = '\\0';\n\t\t\t\tfileErase( userFilePath );\n\t\t\t\t}\n\t\t\t}\n#endif /* 0 */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Allocate room for the user index and read it into the default user \n\t   object */\n\tif( ( userIndexInfo = clAlloc( \"initUserIndex\", \\\n\t\t\t\t\t\t\t\t   sizeof( USER_INDEX_INFO ) ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemset( userIndexInfo, 0, sizeof( USER_INDEX_INFO ) );\n\tstatus = noEntries = readIndex( iIndexKeyset, userIndexInfo->userIndex,\n\t\t\t\t\t\t\t\t\tMAX_USER_OBJECTS );\n\tkrnlSendNotifier( iIndexKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"initUserIndex\", userIndexInfo );\n\t\treturn( status );\n\t\t}\n\tuserIndexInfo->lastEntry = noEntries;\n\t*userIndexPtrPtr = userIndexInfo;\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endUserIndex( IN void *userIndexPtr )\n\t{\n\tassert( isWritePtr( userIndexPtr, sizeof( USER_INDEX_INFO ) ) );\n\n\tzeroise( userIndexPtr, sizeof( USER_INDEX_INFO ) );\n\tclFree( \"endUserIndex\", userIndexPtr );\n\t}\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/misc/user.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUser Routines Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1999-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _USER_DEFINED\n\n#define _USER_DEFINED\n\n/* Initialisation states for the user object */\n\ntypedef enum {\n\tUSER_STATE_NONE,\t\t\t\t/* No initialisation state */\n\tUSER_STATE_SOINITED,\t\t\t/* SSO inited, not usable */\n\tUSER_STATE_USERINITED,\t\t\t/* User inited, usable */\n\tUSER_STATE_LOCKED,\t\t\t\t/* Disabled, not usable */\n\tUSER_STATE_LAST\t\t\t\t\t/* Last possible state */\n\t} USER_STATE_TYPE;\n\n/* User information flags.  These are:\n\n\tFLAG_ZEROISE: Zeroise in progress, further messages (except destroy) are \n\t\t\tbounced, and all files are deleted on destroy */\n\n#define USER_FLAG_NONE\t\t\t0x00\t/* No flag */\n#define USER_FLAG_ZEROISE\t\t0x01\t/* Zeroise in progress */\n#define USER_FLAG_MAX\t\t\t0x01\t/* Maximum possible flag value */\n\n/* Content disposition when writing configuration data */\n\ntypedef enum {\n\tCONFIG_DISPOSITION_NONE,\t\t/* No disposition type */\n\tCONFIG_DISPOSITION_NO_CHANGE,\t/* No change in data and certificates */\n\tCONFIG_DISPOSITION_EMPTY_CONFIG_FILE,\t/* No data/certs present, empty file */\n\tCONFIG_DISPOSITION_TRUSTED_CERTS_ONLY,\t/* Only trusted certs present */\n\tCONFIG_DISPOSITION_DATA_ONLY,\t/* Only configuratin data present */\n\tCONFIG_DISPOSITION_BOTH,\t\t/* Both data and certificates present */\n\tCONFIG_DISPOSITION_LAST\t\t\t/* Last possible disposition type */\n\t} CONFIG_DISPOSITION_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* User information as stored in the user info file */\n\ntypedef struct {\n\tCRYPT_USER_TYPE type;\t\t\t/* User type */\n\tUSER_STATE_TYPE state;\t\t\t/* User state */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, userNameLength ) \\\n\tBYTE userName[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint userNameLength;\t\t\t\t/* User name */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE userID[ KEYID_SIZE + 8 ];\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE creatorID[ KEYID_SIZE + 8 ];/* ID of user and creator of this user */\n\tint fileRef;\t\t\t\t\t/* User info file reference */\n\t} USER_FILE_INFO;\n\n/* The structure that stores the information on a user */\n\ntypedef struct UI {\n\t/* Control and status information */\n\tSAFE_FLAGS flags;\t\t\t\t/* User flags */\n\tUSER_FILE_INFO userFileInfo;\t/* General user info */\n\n\t/* User index information for the default user */\n\tvoid *userIndexPtr;\n\n\t/* Configuration options for this user.  These are managed through the \n\t   user config code, so they're just treated as a dynamically-allocated \n\t   blob within the user object */\n\tvoid *configOptions;\n\tint configOptionsCount;\n\n\t/* Certificate trust information for this user, and a flag indicating\n\t   whether the trust info has changed and potentially needs to be\n\t   committed to disk.  This requires access to cert-internal details\n\t   so it's handled externally via the cert code, the user object just\n\t   sees the info as an opaque blob */\n\tDATAPTR trustInfo;\n\tBOOLEAN trustInfoChanged;\n\n\t/* The user object contains an associated keyset which is used to store\n\t   user information to disk.  In addition for SOs and CAs it also \n\t   contains an associated encryption context, either a private key (for \n\t   an SO) or a conventional key (for a CA) */\n\tCRYPT_KEYSET iKeyset;\t\t\t/* Keyset */\n\tCRYPT_CONTEXT iCryptContext;\t/* Private/secret key */\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* The object's handle, used when sending messages to the object when\n\t   only the xxx_INFO is available */\n\tCRYPT_HANDLE objectHandle;\n\t} USER_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInternal API Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* User attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t  OUT_INT_Z int *valuePtr, \n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getUserAttributeS( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t   INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t  IN_INT_Z const int value, \n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setUserAttributeS( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t   IN_DATALENGTH const int dataLength,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\n\n/* Prototypes for functions in user.c */\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst USER_FILE_INFO *getPrimarySoUserInfo( void );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN isZeroisePassword( IN_BUFFER( passwordLen ) const char *password,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int passwordLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint zeroiseUsers( INOUT USER_INFO *userInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setUserPassword( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t IN_LENGTH_SHORT const int passwordLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initUserIndex( OUT_PTR_OPT void **userIndexPtrPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endUserIndex( IN void *userIndexPtr );\n\n/* Prototypes for functions in user_cfg.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initOptions( OUT_PTR_COND void **configOptionsPtr, \n\t\t\t\t OUT_INT_SHORT_Z int *configOptionsCount );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endOptions( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tvoid *configOptions, \n\t\t\t\t IN_INT_SHORT const int configOptionsCount );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tvoid *configOptions, \n\t\t\t   IN_INT_SHORT const int configOptionsCount, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t   IN_INT const int value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setOptionSpecial( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t  IN_RANGE_FIXED( CRYPT_OPTION_SELFTESTOK ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t  IN_INT_Z const int value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint setOptionString( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t IN_BUFFER( valueLength ) const char *value, \n\t\t\t\t\t IN_LENGTH_SHORT const int valueLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint getOption( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tconst void *configOptions, \n\t\t\t   IN_INT_SHORT const int configOptionsCount, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t   OUT_INT_Z int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint getOptionString( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tconst void *configOptions,\n\t\t\t\t\t IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t OUT_PTR_COND const void **strPtrPtr, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *strLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option );\n\n/* Prototypes for functions in user_rw.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint readConfig( IN_HANDLE const CRYPT_USER iCryptUser, \n\t\t\t\tIN_STRING const char *fileName, \n\t\t\t\tINOUT DATAPTR trustInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint getConfigDisposition( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \t\n\t\t\t\t\t\t  IN const DATAPTR trustInfo, \n\t\t\t\t\t\t  OUT_ENUM( CONFIG_DISPOSITION ) \\\n\t\t\t\t\t\t\tCONFIG_DISPOSITION_TYPE *disposition );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint prepareConfigData( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t   IN_INT_SHORT const int configOptionsCount, \t\n\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t   OUT_DATALENGTH_Z int *dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint commitConfigData( IN_STRING const char *fileName,\n\t\t\t\t\t  IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t  IN_DATALENGTH_Z const int dataLength,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_USER iTrustedCertUserObject );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteConfig( IN_STRING const char *fileName );\n\n#endif /* _USER_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/user_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib User Attribute Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2007\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\t\t/* For snprintf_s() */\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"trustmgr.h\"\n  #include \"user.h\"\n#else\n  #include \"cert/trustmgr.h\"\n  #include \"misc/user.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( userInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorInited( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( userInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT, \n\t\t\t\t\t   CRYPT_ERROR_INITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( userInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT, \n\t\t\t\t\t   CRYPT_ERROR_NOTFOUND ) );\n\t}\n\n#ifdef USE_KEYSETS\n\n/* Process a set-attribute operation that initiates an operation that's \n   performed in two phases.  The reason for the split is that the second \n   phase doesn't require the use of the user object data any more and can be \n   a somewhat lengthy process due to disk accesses or lengthy crypto \n   operations.  Because of this we unlock the user object between the two \n   phases to ensure that the second phase doesn't stall all other operations \n   that require this user object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int twoPhaseConfigUpdate( INOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\t\t\t IN_INT_Z const int value )\n\t{\n\tCRYPT_USER iTrustedCertUserObject = CRYPT_UNUSED;\n\tCONFIG_DISPOSITION_TYPE disposition;\n\tchar userFileName[ 16 + 8 ];\n\tvoid *data = NULL;\n\tint length = 0, commitStatus, refCount, status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( value == FALSE );\n\n\t/* Set up the filename that we want to access */\n\tif( userInfoPtr->userFileInfo.fileRef == CRYPT_UNUSED )\n\t\tstrlcpy_s( userFileName, 16, \"cryptlib\" );\n\telse\n\t\t{\n\t\tsprintf_s( userFileName, 16, \"u%06x\", \n\t\t\t\t   userInfoPtr->userFileInfo.fileRef );\n\t\t}\n\n\t/* Determine what we have to do with the configuation information */\n\tstatus = getConfigDisposition( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t\t   userInfoPtr->configOptionsCount, \n\t\t\t\t\t\t\t\t   userInfoPtr->trustInfo, \n\t\t\t\t\t\t\t\t   &disposition );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( disposition )\n\t\t{\n\t\tcase CONFIG_DISPOSITION_NO_CHANGE:\n\t\t\t/* There's nothing to do, we're done */\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CONFIG_DISPOSITION_EMPTY_CONFIG_FILE:\n\t\t\t/* There's nothing to write, delete the configuration file */\n\t\t\treturn( deleteConfig( userFileName ) );\n\n\t\tcase CONFIG_DISPOSITION_TRUSTED_CERTS_ONLY:\n\t\t\t/* There are only trusted certificates present, if they're \n\t\t\t   unchanged from earlier then there's nothing to do */\n\t\t\tif( !userInfoPtr->trustInfoChanged )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Remember where the trusted certificates are coming from */\n\t\t\tiTrustedCertUserObject = userInfoPtr->objectHandle;\n\t\t\tbreak;\n\n\t\tcase CONFIG_DISPOSITION_DATA_ONLY:\n\t\tcase CONFIG_DISPOSITION_BOTH:\n\t\t\t/* There's configuration data to write, prepare it */\n\t\t\tstatus = prepareConfigData( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t\t\t\tuserInfoPtr->configOptionsCount, \n\t\t\t\t\t\t\t\t\t\t&data, &length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( disposition == CONFIG_DISPOSITION_BOTH )\n\t\t\t\t{\n\t\t\t\t/* There are certificates present as well, remember where \n\t\t\t\t   they're coming from */\n\t\t\t\tiTrustedCertUserObject = userInfoPtr->objectHandle;\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* We've got the configuration data (if there is any) in a memory \n\t   buffer, we can unlock the user object to allow external access while \n\t   we commit the in-memory data to disk.  This also sends any trusted\n\t   certificates in the user object to the configuration file alongside\n\t   the data */\n\tstatus = krnlSuspendObject( userInfoPtr->objectHandle, &refCount );\n\tENSURES( cryptStatusOK( status ) );\n\tcommitStatus = commitConfigData( userFileName, data, length, \n\t\t\t\t\t\t\t\t\t iTrustedCertUserObject );\n\tif( disposition == CONFIG_DISPOSITION_DATA_ONLY || \\\n\t\tdisposition == CONFIG_DISPOSITION_BOTH )\n\t\tclFree( \"userMessageFunction\", data );\n\tstatus = krnlResumeObject( userInfoPtr->objectHandle, refCount );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Handling errors at this point is rather tricky because an error \n\t\t   response from krnlResumeObject() is a can't-occur condition.  In \n\t\t   particular this will mean that we return to the kernel with the \n\t\t   user object released, which will cause it to throw an exception \n\t\t   due to the inconsistent object state.  On the other hand we can \n\t\t   only get to this point because of an exception condition anyway \n\t\t   so it's just going to propagate the exception back */\n\t\tretIntError();\n\t\t}\n\tif( cryptStatusOK( commitStatus ) )\n\t\tuserInfoPtr->trustInfoChanged = FALSE;\n\n\treturn( commitStatus );\n\t}\n#endif /* USE_KEYSETS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int twoPhaseSelftest( INOUT USER_INFO *userInfoPtr, \n\t\t\t\t\t\t\t IN_INT_Z const int value )\n\t{\n\tconst CRYPT_USER iCryptUser = userInfoPtr->objectHandle;\n\tint refCount, selfTestStatus, status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( value == TRUE );\n\n\t/* It's a self-test, forward the message to the system object with \n\t   the user object unlocked, tell the system object to perform its self-\n\t   test, and then re-lock the user object and set the self-test result \n\t   value.  Since the self-test configuration setting will be marked as \n\t   in-use at this point (to avoid having another thread update it while \n\t   the user object was unlocked) it can't be written to directly so we \n\t   have to update it via setOptionSpecial().  In addition since this is \n\t   now an action message we forward it as a MESSAGE_SELFTEST since the \n\t   CRYPT_OPTION_SELFTESTOK attribute only applies to the user object.\n\t   \n\t   An alternative way to handle this would be implement an advisory-\n\t   locking mechanism for configuration options, but this adds a great \n\t   deal of complexity just to handle this one single case so until \n\t   there's a wider need for general-purpose configuration option locking \n\t   the current approach will do */\n\tstatus = krnlSuspendObject( iCryptUser, &refCount );\n\tENSURES( cryptStatusOK( status ) );\n\tselfTestStatus = krnlSendNotifier( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t   IMESSAGE_SELFTEST );\n\tstatus = krnlResumeObject( iCryptUser, refCount );\n\t\t\t /* See comment above on krnlResumeObject() error handling */\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( setOptionSpecial( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t  userInfoPtr->configOptionsCount,\n\t\t\t\t\t\t\t  CRYPT_OPTION_SELFTESTOK,\n\t\t\t\t\t\t\t  cryptStatusOK( selfTestStatus ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t  OUT_INT_Z int *valuePtr, \n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tint status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Clear return value */\n\t*valuePtr = 0;\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_USERINFO_CAKEY_CERTSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_CRLSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_OCSPSIGN:\n\t\t\t{\n\t\t\tCRYPT_CERTIFICATE caCert;\n\n\t\t\t/* Make sure that the key type that we're after is present in \n\t\t\t   the object */\n\t\t\tif( userInfoPtr->iCryptContext == CRYPT_UNUSED )\n\t\t\t\treturn( exitErrorNotFound( userInfoPtr, attribute ) );\n\n\t\t\t/* Since the CA signing key tied to the user object is meant to \n\t\t\t   be used only through cryptlib-internal means we shouldn't \n\t\t\t   really be returning it to the caller.  We can return the \n\t\t\t   ssociated CA cert, but this may be an internal-only object \n\t\t\t   that the caller can't do anything with.  To avoid this \n\t\t\t   problem we isolate the cert by returning a copy of the\n\t\t\t   associated certificate object */\n\t\t\tstatus = krnlSendMessage( userInfoPtr->iCryptContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &caCert,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTCOPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t*valuePtr = caCert;\n\t\t\treturn( status );\n\t\t\t}\n\n#ifdef USE_CERTIFICATES\n\t\tcase CRYPT_IATTRIBUTE_CTL:\n\t\t\t{\n\t\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\t\t/* Check whether there are actually trusted certs present */\n\t\t\tif( !trustedCertsPresent( userInfoPtr->trustInfo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t\t/* Create a cert chain meta-object to hold the overall set of\n\t\t\t   certs */\n\t\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTCHAIN );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Assemble the trusted certs into the cert chain */\n\t\t\tstatus = enumTrustedCerts( userInfoPtr->trustInfo,\n\t\t\t\t\t\t\t\t\t   createInfo.cryptHandle, CRYPT_UNUSED );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t*valuePtr = createInfo.cryptHandle;\n\t\t\telse\n\t\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n#endif /* USE_CERTIFICATES */\n\t\t}\n\n\t/* Anything else has to be a configuration option */\n\tREQUIRES( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t  attribute < CRYPT_OPTION_LAST );\n\n\t/* A numeric-value get can never fail because we always have default \n\t   values present */\n\treturn( getOption( userInfoPtr->configOptions, \n\t\t\t\t\t   userInfoPtr->configOptionsCount, attribute, \n\t\t\t\t\t   valuePtr ) );\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getUserAttributeS( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t   INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst void *string;\n\tint stringLen, status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* This can only be a configuration option */\n\tREQUIRES( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t  attribute < CRYPT_OPTION_LAST );\n\n\t/* Check whether there's a configuration value of this type present */\n\tstatus = getOptionString( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t  userInfoPtr->configOptionsCount, attribute, \n\t\t\t\t\t\t\t  &string, &stringLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( attributeCopy( msgData, string, stringLen ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t  IN_INT_Z const int value, \n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tint status;\n\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( ( attribute == CRYPT_IATTRUBUTE_CERTKEYSET && \\\n\t\t\t\tvalue == CRYPT_UNUSED ) || \\\n\t\t\t  isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_USERINFO_CAKEY_CERTSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_CRLSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_OCSPSIGN:\n\t\t\t{\n\t\t\tconst int requiredKeyUsage = \\\n\t\t\t\t( attribute == CRYPT_USERINFO_CAKEY_CERTSIGN ) ? \\\n\t\t\t\t\tCRYPT_KEYUSAGE_KEYCERTSIGN : \\\n\t\t\t\t( attribute == CRYPT_USERINFO_CAKEY_CRLSIGN ) ? \\\n\t\t\t\t\tCRYPT_KEYUSAGE_CRLSIGN : KEYUSAGE_SIGN;\n\t\t\tBOOLEAN_INT isImmutable;\n\t\t\tint attributeValue;\n\n\t\t\t/* Make sure that this key type isn't already present in the \n\t\t\t   object */\n\t\t\tif( userInfoPtr->iCryptContext != CRYPT_UNUSED )\n\t\t\t\treturn( exitErrorInited( userInfoPtr, attribute ) );\n\n\t\t\t/* Make sure that we've been given a signing key */\n\t\t\tif( !checkContextCapability( value, MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Make sure that the object has an initialised cert of the\n\t\t\t   correct type associated with it */\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &isImmutable, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_IMMUTABLE );\n\t\t\tif( cryptStatusError( status ) || !isImmutable )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &attributeValue, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\t\t\tif( cryptStatusError( status ) ||\n\t\t\t\t( attributeValue != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t\t  attributeValue != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* Make sure that the key usage required for this action is\n\t\t\t   permitted.  OCSP is a bit difficult since the key may or may\n\t\t\t   not have an OCSP extended usage (depending on whether the CA\n\t\t\t   bothers to set it or not, even if they do they may delegate\n\t\t\t   the functionality to a short-term generic signing key) and the\n\t\t\t   signing ability may be indicated by either a digital signature\n\t\t\t   flag or a nonrepudiation flag depending on whether the CA\n\t\t\t   considers an OCSP signature to be short or long-term, so we\n\t\t\t   just check for a generic signing ability */\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  &attributeValue, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t!( attributeValue & requiredKeyUsage ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\t\t\t/* Save key in the keyset at some point.  Also handle get */\n\t\t\t/* (gets public key) and delete (removes key), this */\n\t\t\t/* functionality is only needed for CA users so is left for */\n\t\t\t/* the full implementation of user roles */\n\t\t\t/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/\n\n\t\t\treturn( status );\n\t\t\t}\n\n#ifdef USE_CERTIFICATES\n\t\tcase CRYPT_IATTRUBUTE_CERTKEYSET:\n\t\t\t/* If it's a presence check, handle it specially */\n\t\t\tif( value == CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\treturn( trustedCertsPresent( userInfoPtr->trustInfo ) ? \\\n\t\t\t\t\t\tCRYPT_OK : CRYPT_ERROR_NOTFOUND );\n\t\t\t\t}\n\n\t\t\t/* Send all trusted certs to the keyset */\n\t\t\treturn( enumTrustedCerts( userInfoPtr->trustInfo, \n\t\t\t\t\t\t\t\t\t  CRYPT_UNUSED, value ) );\n\n\t\tcase CRYPT_IATTRIBUTE_CTL:\n\t\t\t/* Add the certs via the trust list */\n\t\t\tstatus = addTrustEntry( userInfoPtr->trustInfo,\n\t\t\t\t\t\t\t\t\tvalue, NULL, 0, FALSE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tuserInfoPtr->trustInfoChanged = TRUE;\n\t\t\treturn( status );\n#endif /* USE_CERTIFICATES */\n\t\t}\n\n\t/* Anything else has to be a configuration option */\n\tREQUIRES( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t  attribute < CRYPT_OPTION_LAST );\n\n\t/* Set the option.  If it's not one of the two special options with \n\t   side-effects, we're done */\n\tstatus = setOption( userInfoPtr->configOptions, \n\t\t\t\t\t\tuserInfoPtr->configOptionsCount, attribute, value );\n\tif( attribute != CRYPT_OPTION_CONFIGCHANGED && \\\n\t\tattribute != CRYPT_OPTION_SELFTESTOK )\n\t\treturn( status );\n\n\t/* If there was a problem setting a side-effects option, don't go any \n\t   further */\n\tif( status != OK_SPECIAL )\n\t\treturn( status );\n\n\t/* Complete the processing of the special options */\n#ifdef USE_KEYSETS\n\tif( attribute == CRYPT_OPTION_CONFIGCHANGED )\n\t\treturn( twoPhaseConfigUpdate( userInfoPtr, value ) );\n#endif /* USE_KEYSETS */\n\treturn( twoPhaseSelftest( userInfoPtr, value ) );\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setUserAttributeS( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t   IN_DATALENGTH const int dataLength,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n#ifdef USE_KEYSETS\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_USERINFO_PASSWORD:\n\t\t\treturn( setUserPassword( userInfoPtr, data, dataLength ) );\n\t\t}\n#endif /* USE_KEYSETS */\n\n\t/* Anything else has to be a configuration option */\n\tREQUIRES( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t  attribute < CRYPT_OPTION_LAST );\n\treturn( setOptionString( userInfoPtr->configOptions, \n\t\t\t\t\t\t\t userInfoPtr->configOptionsCount, attribute, \n\t\t\t\t\t\t\t data, dataLength ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete Attributes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteUserAttribute( INOUT USER_INFO *userInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( userInfoPtr, sizeof( USER_INFO ) ) );\n\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_USERINFO_CAKEY_CERTSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_CRLSIGN:\n\t\tcase CRYPT_USERINFO_CAKEY_OCSPSIGN:\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\n\t/* Anything else has to be a configuration option */\n\tREQUIRES( attribute > CRYPT_OPTION_FIRST && \\\n\t\t\t  attribute < CRYPT_OPTION_LAST );\n\n\treturn( deleteOption( userInfoPtr->configOptions, \n\t\t\t\t\t\t  userInfoPtr->configOptionsCount, attribute ) );\n\t}\n"
  },
  {
    "path": "deps/cl345/misc/user_cfg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib Configuration Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1994-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"user_int.h\"\n  #include \"user.h\"\n#else\n  #include \"misc/user_int.h\"\n  #include \"misc/user.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tConfiguration Options\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Built-in default configuration options */\n\n#define MK_OPTION( option, value, index ) \\\n\t{ option, OPTION_NUMERIC, index, NULL, value }\n#define MK_OPTION_B( option, value, index ) \\\n\t{ option, OPTION_BOOLEAN, index, NULL, value }\n#define MK_OPTION_S( option, value, length, index ) \\\n\t{ option, OPTION_STRING, index, value, length }\n#define MK_OPTION_NONE() \\\n\t{ CRYPT_ATTRIBUTE_NONE, OPTION_NONE, CRYPT_UNUSED, NULL, 0 }\n\nstatic const BUILTIN_OPTION_INFO builtinOptionInfo[] = {\n\t/* cryptlib information (read-only) */\n#ifdef NDEBUG\n\tMK_OPTION_S( CRYPT_OPTION_INFO_DESCRIPTION, \"cryptlib security toolkit\", 25, CRYPT_UNUSED ),\n#else\n\tMK_OPTION_S( CRYPT_OPTION_INFO_DESCRIPTION, \"cryptlib security toolkit (debug build)\", 39, CRYPT_UNUSED ),\n#endif /* NDEBUG */\n\tMK_OPTION_S( CRYPT_OPTION_INFO_COPYRIGHT, \"Copyright Peter Gutmann, Eric Young, OpenSSL, 1994-2019\", 55, CRYPT_UNUSED ),\n\tMK_OPTION( CRYPT_OPTION_INFO_MAJORVERSION, 3, CRYPT_UNUSED ),\n\tMK_OPTION( CRYPT_OPTION_INFO_MINORVERSION, 4, CRYPT_UNUSED ),\n\tMK_OPTION( CRYPT_OPTION_INFO_STEPPING, 5, CRYPT_UNUSED ),\n\n\t/* Context options, base = 0 */\n\t/* Algorithm = Conventional encryption/hash/MAC options */\n\tMK_OPTION( CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_AES, 0 ),\n\tMK_OPTION( CRYPT_OPTION_ENCR_HASH, CRYPT_ALGO_SHA2, 1 ),\n\tMK_OPTION( CRYPT_OPTION_ENCR_MAC, CRYPT_ALGO_HMAC_SHA2, 2 ),\n\n\t/* Algorithm = PKC options */\n\tMK_OPTION( CRYPT_OPTION_PKC_ALGO, CRYPT_ALGO_RSA, 3 ),\n\tMK_OPTION( CRYPT_OPTION_PKC_KEYSIZE, bitsToBytes( 1536 ), 4 ),\n\n\t/* Placeholder for obsolete options */\n\tMK_OPTION( CRYPT_OPTION_DUMMY1, 0, 5 ),\n\tMK_OPTION( CRYPT_OPTION_DUMMY2, 0, 6 ),\n\n\t/* Algorithm = Key derivation options.  On a slower CPU we use a \n\t   lower number of iterations.  Conversely, on a fast CPU we use\n\t   a larger number */\n\tMK_OPTION( CRYPT_OPTION_KEYING_ALGO, CRYPT_ALGO_HMAC_SHA2, 7 ),\n#if defined( CONFIG_SLOW_CPU )\n\tMK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, 1000, 8 ),\n#elif defined( CONFIG_FAST_CPU )\n\tMK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, min( 50000, MAX_KEYSETUP_ITERATIONS ), 8 ),\n#else\n\tMK_OPTION( CRYPT_OPTION_KEYING_ITERATIONS, 10000, 8 ),\n#endif /* Options based on CPU speed */\n\n\t/* Certificate options, base = 100 */\n\tMK_OPTION_B( CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, FALSE, 100 ),\n\tMK_OPTION( CRYPT_OPTION_CERT_VALIDITY, 365, 101 ),\n\tMK_OPTION( CRYPT_OPTION_CERT_UPDATEINTERVAL, 90, 102 ),\n\tMK_OPTION( CRYPT_OPTION_CERT_COMPLIANCELEVEL, CRYPT_COMPLIANCELEVEL_STANDARD, 103 ),\n\tMK_OPTION_B( CRYPT_OPTION_CERT_REQUIREPOLICY, TRUE, 104 ),\n\n\t/* CMS options */\n\tMK_OPTION_B( CRYPT_OPTION_CMS_DEFAULTATTRIBUTES, TRUE, 105 ),\n\n\t/* Keyset options, base = 200 */\n\t/* Keyset = LDAP options */\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS, \"inetOrgPerson\", 13, 200 ),\n\tMK_OPTION( CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE, CRYPT_CERTTYPE_NONE, 201 ),\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_FILTER, \"(objectclass=*)\", 15, 202 ),\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CACERTNAME, \"cACertificate;binary\", 20, 203 ),\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CERTNAME, \"userCertificate;binary\", 32, 204 ),\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_CRLNAME, \"certificateRevocationList;binary\", 22, 205 ),\n\tMK_OPTION_S( CRYPT_OPTION_KEYS_LDAP_EMAILNAME, \"mail\", 4, 206 ),\n\n\t/* Device options, base = 300 */\n\t/* Device = PKCS #11 token options */\n\tMK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR01, NULL, 0, 300 ),\n\tMK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR02, NULL, 0, 301 ),\n\tMK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR03, NULL, 0, 302 ),\n\tMK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR04, NULL, 0, 303 ),\n\tMK_OPTION_S( CRYPT_OPTION_DEVICE_PKCS11_DVR05, NULL, 0, 304 ),\n\tMK_OPTION_B( CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY, FALSE, 305 ),\n\n\t/* Session options, base = 400 */\n\n\t/* Miscellaneous options, base = 500.  The network options are mostly \n\t   used by sessions but also apply to other object types like network \n\t   keysets so they're classed as miscellaneous options. \n\t   \n\t   Side-channel protection is usually disabled by default because a\n\t   survey of users found that a total of 0% indicated that they wanted\n\t   side-channel protection in exchange for a performance drop \n\t   (particularly in embedded systems where PKC ops already consume about \n\t   150% of the available CPU budget), however on fast systems we enable \n\t   it by default because they should be fast enough that no-one will \n\t   notice */\n\tMK_OPTION_S( CRYPT_OPTION_NET_SOCKS_SERVER, NULL, 0, 500 ),\n\tMK_OPTION_S( CRYPT_OPTION_NET_SOCKS_USERNAME, NULL, 0, 501 ),\n\tMK_OPTION_S( CRYPT_OPTION_NET_HTTP_PROXY, NULL, 0, 502 ),\n\tMK_OPTION( CRYPT_OPTION_NET_CONNECTTIMEOUT, NET_TIMEOUT_CONNECT, 503 ),\n\tMK_OPTION( CRYPT_OPTION_NET_READTIMEOUT, NET_TIMEOUT_READ, 504 ),\n\tMK_OPTION( CRYPT_OPTION_NET_WRITETIMEOUT, NET_TIMEOUT_WRITE, 505 ),\n\tMK_OPTION_B( CRYPT_OPTION_MISC_ASYNCINIT, TRUE, 506 ),\n#if defined( CONFIG_FAST_CPU )\n\tMK_OPTION( CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, 1, 507 ),\n#else\n\tMK_OPTION( CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, 0, 507 ),\n#endif /* Options based on CPU speed */\n\n\t/* All options beyond this point are ephemeral and aren't stored to disk. \n\t   Remember to update the LAST_STORED_OPTION define in user_int.h when \n\t   adding new options here */\n\n\t/* cryptlib state information.  These are special-case options that\n\t   record state information rather than a static configuration value.  \n\t   The configuration-option-changed status value is updated dynamically, \n\t   being set to TRUE if any configuration option is changed.  Writing it \n\t   to FALSE commits the changes to disk.  The self-test status value is \n\t   initially set to FALSE, writing it to TRUE triggers a self-test for \n\t   which the value remains at TRUE if the test succeeds */\n\tMK_OPTION_B( CRYPT_OPTION_CONFIGCHANGED, FALSE, CRYPT_UNUSED ),\n\tMK_OPTION( CRYPT_OPTION_SELFTESTOK, FALSE, CRYPT_UNUSED ),\n\n\t/* End-of-list marker */\n\tMK_OPTION_NONE(), MK_OPTION_NONE()\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Locate an entry in the built-in configuration options by looking up the \n   option code that identifies it when it's written to disk */\n\nCHECK_RETVAL_PTR \\\nconst BUILTIN_OPTION_INFO *getBuiltinOptionInfoByCode( IN_RANGE( 0, LAST_OPTION_INDEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst int optionCode )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( optionCode >= 0 && optionCode <= LAST_OPTION_INDEX );\n\n\tLOOP_LARGE( i = 0, \n\t\t\t\tbuiltinOptionInfo[ i ].option <= LAST_STORED_OPTION && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( builtinOptionInfo, \\\n\t\t\t\t\t\t\t\t\t\tBUILTIN_OPTION_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tif( builtinOptionInfo[ i ].index == optionCode )\n\t\t\treturn( &builtinOptionInfo[ i ] );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );\n\n\t/* Failing to find a match isn't an internal error since we're looking \n\t   up the options based on configuration data stored in an external \n\t   file */\n\treturn( NULL );\n\t}\n\n/* Locate an entry in the current configuration options */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic const OPTION_INFO *getOptionInfo( IN_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst OPTION_INFO *optionList,\n\t\t\t\t\t\t\t\t\t\t IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE option )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( optionList, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES_N( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\n\tLOOP_LARGE( i = 0, \n\t\t\t\ti < configOptionsCount && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo != NULL && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo->option != CRYPT_ATTRIBUTE_NONE, \n\t\t\t\ti++ )\n\t\t{\n\t\tif( optionList[ i ].builtinOptionInfo->option == option )\n\t\t\treturn( &optionList[ i ] );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < configOptionsCount );\n\n\tretIntError_Null();\n\t}\n\n/* Record the fact that one of the configuration options has been changed */\n\nstatic void setConfigChanged( INOUT_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\t\tOPTION_INFO *optionList,\n\t\t\t\t\t\t\t  IN_INT_SHORT const int configOptionsCount )\n\t{\n\tOPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( optionList, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES_V( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\toptionInfoPtr = ( OPTION_INFO * ) \\\n\t\t\t\t\tgetOptionInfo( optionList, configOptionsCount,\n\t\t\t\t\t\t\t\t   CRYPT_OPTION_CONFIGCHANGED );\n\tENSURES_V( optionInfoPtr != NULL );\n\toptionInfoPtr->intValue = TRUE;\n\t}\n\n/* Check whether a configuration option has been changed */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkConfigChanged( IN_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\tconst OPTION_INFO *optionList,\n\t\t\t\t\t\t\tIN_INT_SHORT const int configOptionsCount )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( optionList, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES_B( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\tLOOP_LARGE( i = 0, \n\t\t\t\ti < configOptionsCount && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo != NULL && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo->option <= LAST_STORED_OPTION, \n\t\t\t\ti++ )\n\t\t{\n\t\tif( optionList[ i ].dirty )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tENSURES_B( i < configOptionsCount );\n\n\treturn( FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet Configuration Options\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Query the value of a numeric or string option */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint getOption( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tconst void *configOptions, \n\t\t\t   IN_INT_SHORT const int configOptionsCount, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t   OUT_INT_Z int *value )\n\t{\n\tconst OPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\toptionInfoPtr = getOptionInfo( configOptions, configOptionsCount, \n\t\t\t\t\t\t\t\t   option );\n\tENSURES( optionInfoPtr != NULL && \\\n\t\t\t ( optionInfoPtr->builtinOptionInfo->type == OPTION_NUMERIC || \\\n\t\t\t   optionInfoPtr->builtinOptionInfo->type == OPTION_BOOLEAN ) );\n\t*value = optionInfoPtr->intValue;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \\\nint getOptionString( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tconst void *configOptions,\n\t\t\t\t\t IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t OUT_PTR_COND const void **strPtrPtr, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *strLen )\n\t{\n\tconst OPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isReadPtr( strPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( strLen, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\n\t/* Clear return values */\n\t*strPtrPtr = NULL;\n\t*strLen = 0;\n\n\toptionInfoPtr = getOptionInfo( configOptions, configOptionsCount, \n\t\t\t\t\t\t\t\t   option );\n\tENSURES( optionInfoPtr != NULL && \\\n\t\t\t optionInfoPtr->builtinOptionInfo->type == OPTION_STRING );\n\tif( optionInfoPtr->intValue <= 0 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t*strPtrPtr = optionInfoPtr->strValue;\n\t*strLen = optionInfoPtr->intValue;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSet Configuration Options\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set the value of a numeric or string option */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tvoid *configOptions, \n\t\t\t   IN_INT_SHORT const int configOptionsCount, \n\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t   IN_INT const int value )\n\t{\n\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr;\n\tOPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\tREQUIRES( isIntegerRange( value ) );\n\n\t/* Get a pointer to the option information and make sure that everything\n\t   is OK */\n\toptionInfoPtr = ( OPTION_INFO * ) \\\n\t\t\t\t\tgetOptionInfo( configOptions, configOptionsCount, \n\t\t\t\t\t\t\t\t   option );\n\tENSURES( optionInfoPtr != NULL );\n\tbuiltinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;\n\tENSURES( builtinOptionInfoPtr != NULL && \\\n\t\t\t ( builtinOptionInfoPtr->type == OPTION_NUMERIC || \\\n\t\t\t   builtinOptionInfoPtr->type == OPTION_BOOLEAN ) );\n\n\t/* If the stored value is the same as the new one, there's nothing to \n\t   do */\n\tif( optionInfoPtr->intValue == value )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're forcing a commit by returning the configuration-changed flag \n\t   to its ground state, write any changed options to backing store */\n\tif( option == CRYPT_OPTION_CONFIGCHANGED )\n\t\t{\n\t\t/* When a non-configuration option (for example a certificate trust \n\t\t   option) is changed then we need to write the updated \n\t\t   configuration data to backing store, but there's no way to tell \n\t\t   that this is required because the configuration options are \n\t\t   unchanged.  To allow the caller to signal this change they can \n\t\t   explicitly set the configuration-changed setting to TRUE \n\t\t   (normally this is done implicitly by when another configuration \n\t\t   setting is changed).  This explicit setting can only be done by \n\t\t   the higher-level configuration-update code because the kernel \n\t\t   blocks any attempts to set it to a value other than FALSE */\n\t\tif( value )\n\t\t\t{\n\t\t\toptionInfoPtr->intValue = TRUE;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Make sure that there's something to write.  We do this to avoid\n\t\t   problems with programs that always try to update the \n\t\t   configuration whether it's necessary or not, which can cause \n\t\t   problems with media with limited writeability */\n\t\tif( !optionInfoPtr->intValue )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* We don't do anything to write the configuration data at this \n\t\t   level since we currently have the user object locked and don't \n\t\t   want to stall all operations that depend on it while we're \n\t\t   updating the data, so all that we do is signal the user object \n\t\t   to perform the necessary operations */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* If we're forcing a self-test by changing the value of the self-test\n\t   status, perform an algorithm test */\n\tif( option == CRYPT_OPTION_SELFTESTOK )\n\t\t{\n\t\t/* The self-test can take some time to complete.  While it's running\n\t\t   we don't want to leave the user object locked since this will\n\t\t   block most other threads, which all eventually read some sort of\n\t\t   configuration option.  To get around this problem we set the \n\t\t   result value to an undefined status and unlock the user object \n\t\t   around the call, then re-lock it and set its actual value via \n\t\t   setOptionSpecial() once the self-test is done */\n\t\tif( optionInfoPtr->intValue == CRYPT_ERROR )\n\t\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\toptionInfoPtr->intValue = CRYPT_ERROR;\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* Set the value and remember that the configuration options have been \n\t   changed */\n\tif( builtinOptionInfoPtr->type == OPTION_BOOLEAN )\n\t\t{\n\t\t/* Turn a generic zero/nonzero boolean into TRUE or FALSE */\n\t\toptionInfoPtr->intValue = ( value ) ? TRUE : FALSE;\n\t\t}\n\telse\n\t\toptionInfoPtr->intValue = value;\n\toptionInfoPtr->dirty = TRUE;\n\tsetConfigChanged( configOptions, configOptionsCount );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setOptionSpecial( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t  IN_RANGE_FIXED( CRYPT_OPTION_SELFTESTOK ) \\\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t  IN_INT_Z const int value )\n\t{\n\tOPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* The update of the self-test status is performed in two phases.  When \n\t   we begin the self-test, triggered by the user setting the \n\t   CRYPT_OPTION_SELFTESTOK, it's set to an undefined value via \n\t   setOption().  In other words the user can only ever set this to the \n\t   self-test-in-progress state.  Once the self-test completes it's set \n\t   to the test result value via setOptionSpecial(), which can only be \n\t   accessed from inside the user object */\n\tREQUIRES( option == CRYPT_OPTION_SELFTESTOK );\n\n\t/* Get a pointer to the option information and make sure that everything\n\t   is OK */\n\toptionInfoPtr = ( OPTION_INFO * ) \\\n\t\t\t\t\tgetOptionInfo( configOptions, configOptionsCount, \n\t\t\t\t\t\t\t\t   option );\n\tENSURES( optionInfoPtr != NULL && \\\n\t\t\t optionInfoPtr->intValue == CRYPT_ERROR );\n\n\toptionInfoPtr->intValue = value;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint setOptionString( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option,\n\t\t\t\t\t IN_BUFFER( valueLength ) const char *value, \n\t\t\t\t\t IN_LENGTH_SHORT const int valueLength )\n\t{\n\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr;\n\tOPTION_INFO *optionInfoPtr;\n\tchar *valuePtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\n\t/* Get a pointer to the option information and make sure that everything\n\t   is OK */\n\toptionInfoPtr = ( OPTION_INFO * ) \\\n\t\t\t\t\tgetOptionInfo( configOptions, configOptionsCount, \n\t\t\t\t\t\t\t\t   option );\n\tENSURES( optionInfoPtr != NULL );\n\tbuiltinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;\n\tENSURES( builtinOptionInfoPtr != NULL && \\\n\t\t\t builtinOptionInfoPtr->type == OPTION_STRING );\n\n\t/* If the value is the same as the current one, there's nothing to do */\n\tif( optionInfoPtr->strValue != NULL && \\\n\t\toptionInfoPtr->intValue == valueLength && \\\n\t\t!memcmp( optionInfoPtr->strValue, value, valueLength ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're resetting a value to its default setting, just reset the\n\t   string pointers rather than storing the value */\n\tif( builtinOptionInfoPtr->strDefault != NULL && \\\n\t\tbuiltinOptionInfoPtr->intDefault == valueLength && \\\n\t\t!memcmp( builtinOptionInfoPtr->strDefault, value, valueLength ) )\n\t\t{\n\t\tif( optionInfoPtr->strValue != NULL && \\\n\t\t\toptionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )\n\t\t\t{\n\t\t\tzeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );\n\t\t\tclFree( \"setOptionString\", optionInfoPtr->strValue );\n\t\t\t}\n\t\toptionInfoPtr->strValue = ( char * ) builtinOptionInfoPtr->strDefault;\n\t\toptionInfoPtr->dirty = TRUE;\n\t\tsetConfigChanged( configOptions, configOptionsCount );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Try and allocate room for the new option */\n\tREQUIRES( rangeCheck( valueLength, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( valuePtr = clAlloc( \"setOptionString\", valueLength ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tmemcpy( valuePtr, value, valueLength );\n\n\t/* If the string value that's currently set isn't the default setting,\n\t   clear and free it */\n\tif( optionInfoPtr->strValue != NULL && \\\n\t\toptionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )\n\t\t{\n\t\tzeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );\n\t\tclFree( \"setOptionString\", optionInfoPtr->strValue );\n\t\t}\n\n\t/* Set the value and remember that the configuration options have been \n\t   changed */\n\toptionInfoPtr->strValue = valuePtr;\n\toptionInfoPtr->intValue = valueLength;\n\toptionInfoPtr->dirty = TRUE;\n\tsetConfigChanged( configOptions, configOptionsCount );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMisc.Configuration Options Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an option */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteOption( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \n\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE option )\n\t{\n\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr;\n\tOPTION_INFO *optionInfoPtr;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\tREQUIRES( option > CRYPT_OPTION_FIRST && option < CRYPT_OPTION_LAST );\n\n\t/* Get a pointer to the option information and make sure that everything\n\t   is OK */\n\toptionInfoPtr = ( OPTION_INFO * ) \\\n\t\t\t\t\tgetOptionInfo( configOptions, configOptionsCount, option );\n\tENSURES( optionInfoPtr != NULL );\n\tbuiltinOptionInfoPtr = optionInfoPtr->builtinOptionInfo;\n\tENSURES( builtinOptionInfoPtr != NULL && \\\n\t\t\t builtinOptionInfoPtr->type == OPTION_STRING );\n\n\t/* If we're deleting an option it can only be a string option without a\n\t   built-in default to fall back on (enforced by the kernel).  Since \n\t   these options don't have default values we check for a setting of \n\t   NULL rather than equivalence to a default string value.  In addition\n\t   since they contain a mixture of fixed and user-definable fields we\n\t   have to clear the fields explicitly rather than using a memset() */\n\tENSURES( builtinOptionInfoPtr->strDefault == NULL );\n\tif( optionInfoPtr->strValue == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tzeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );\n\tclFree( \"setOptionString\", optionInfoPtr->strValue );\n\toptionInfoPtr->strValue = NULL;\n\toptionInfoPtr->intValue = 0;\n\toptionInfoPtr->dirty = TRUE;\n\tsetConfigChanged( configOptions, configOptionsCount );\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise/shut down the configuration option handling */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initOptions( OUT_PTR_COND void **configOptionsPtr, \n\t\t\t\t OUT_INT_SHORT_Z int *configOptionsCount )\n\t{\n\tOPTION_INFO *optionList;\n\tint i, LOOP_ITERATOR;\n\n\t/* Clear return values */\n\t*configOptionsPtr = NULL;\n\t*configOptionsCount = 0;\n\n\t/* Perform a consistency check on the options */\n#ifndef CONFIG_FUZZ\n\tFORALL( i, 0, CRYPT_OPTION_LAST - CRYPT_OPTION_FIRST - 1,\n\t\t\tbuiltinOptionInfo[ i ].option == i + CRYPT_OPTION_FIRST + 1 );\n#endif /* !CONFIG_FUZZ */\n\n\t/* Allocate storage for the variable configuration data */\n\toptionList = getOptionInfoStorage();\n\tmemset( optionList, 0, OPTION_INFO_SIZE );\n\n\t/* Walk through the configuration option list setting up each option to \n\t   contain its default value */\n\tLOOP_LARGE( i = 0,\n\t\t\t\tbuiltinOptionInfo[ i ].option != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( builtinOptionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\tBUILTIN_OPTION_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr = &builtinOptionInfo[ i ];\n\t\tOPTION_INFO *optionInfoPtr = &optionList[ i ];\n\n\t\tif( builtinOptionInfoPtr->type == OPTION_STRING )\n\t\t\toptionInfoPtr->strValue = ( char * ) builtinOptionInfoPtr->strDefault;\n\t\toptionInfoPtr->intValue = builtinOptionInfoPtr->intDefault;\n\t\toptionInfoPtr->builtinOptionInfo = builtinOptionInfoPtr;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );\n\t*configOptionsPtr = optionList;\n\t*configOptionsCount = FAILSAFE_ARRAYSIZE( builtinOptionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t  BUILTIN_OPTION_INFO );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endOptions( IN_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\tvoid *configOptions, \n\t\t\t\t IN_INT_SHORT const int configOptionsCount )\n\t{\n\tOPTION_INFO *optionList = configOptions;\n\tint i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES_V( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* Walk through the configuration option list clearing and freeing each \n\t   option */\n\tLOOP_LARGE( i = 0, \n\t\t\t\tbuiltinOptionInfo[ i ].option != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( builtinOptionInfo, \\\n\t\t\t\t\t\t\t\t\t\t\tBUILTIN_OPTION_INFO ), \n\t\t\t\ti++ )\n\t\t{\n\t\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr = &builtinOptionInfo[ i ];\n\t\tOPTION_INFO *optionInfoPtr = &optionList[ i ];\n\n\t\tif( builtinOptionInfoPtr->type == OPTION_STRING )\n\t\t\t{\n\t\t\t/* If the string value that's currently set isn't the default\n\t\t\t   setting, clear and free it */\n\t\t\tif( optionInfoPtr->strValue != builtinOptionInfoPtr->strDefault )\n\t\t\t\t{\n\t\t\t\tzeroise( optionInfoPtr->strValue, optionInfoPtr->intValue );\n\t\t\t\tclFree( \"endOptions\", optionInfoPtr->strValue );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tENSURES_V( i < FAILSAFE_ARRAYSIZE( builtinOptionInfo, BUILTIN_OPTION_INFO ) );\n\tENSURES_V( i == configOptionsCount - 1 );\n\n\t/* Clear and free the configuration option list */\n\tmemset( optionList, 0, sizeof( OPTION_INFO ) * configOptionsCount );\n\t}\n"
  },
  {
    "path": "deps/cl345/misc/user_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Interal User Header File\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1999-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _USER_INT_DEFINED\n\n#define _USER_INT_DEFINED\n\n/* Configuration option types */\n\ntypedef enum {\n\tOPTION_NONE,\t\t\t\t\t/* Non-option */\n\tOPTION_STRING,\t\t\t\t\t/* Literal string */\n\tOPTION_NUMERIC,\t\t\t\t\t/* Numeric value */\n\tOPTION_BOOLEAN\t\t\t\t\t/* Boolean flag */\n\t} OPTION_TYPE;\n\n/* The configuration options.  Alongside the CRYPT_ATTRIBUTE_TYPE we store a \n   persistent index value for the option that always stays the same even if \n   the attribute type changes.  This avoids the need to change the config \n   file every time that an attribute is added or deleted.  Some options \n   can't be made persistent, for these the index value is set to \n   CRYPT_UNUSED */\n\ntypedef struct {\n\tconst CRYPT_ATTRIBUTE_TYPE option;/* Attribute ID */\n\tconst OPTION_TYPE type;\t\t\t/* Option type */\n\tconst int index;\t\t\t\t/* Index value for this option */\n\tBUFFER_OPT_FIXED( intDefault ) \\\n\tconst char *strDefault;\t\t\t/* Default if it's a string option */\n\tconst int intDefault;\t\t\t/* Default if it's a numeric/boolean\n\t\t\t\t\t\t\t\t\t   or length if it's a string */\n\t} BUILTIN_OPTION_INFO;\n\ntypedef struct {\n\tBUFFER_OPT_FIXED( intValue ) \\\n\tchar *strValue;\t\t\t\t\t/* Value if it's a string option */\n\tint intValue;\t\t\t\t\t/* Value if it's a numeric/boolean\n\t\t\t\t\t\t\t\t\t   or length if it's a string */\n\tconst BUILTIN_OPTION_INFO *builtinOptionInfo;\n\t\t\t\t\t\t\t\t\t/* Pointer to corresponding built-in \n\t\t\t\t\t\t\t\t\t   option info */\n\tBOOLEAN dirty;\t\t\t\t\t/* Whether option has been changed */\n\t} OPTION_INFO;\n\n/* The size of the variable-length configuration data, used when we allocate\n   storage for it and initialise it from the builtinOptionInfo template */\n\n#define OPTION_INFO_SIZE\t( sizeof( OPTION_INFO ) * \\\n\t\t\t\t\t\t\t  CRYPT_OPTION_CONFIGCHANGED - CRYPT_OPTION_FIRST )\n\n/* The attribute ID of the last option that's written to disk, and an upper \n   bound on the corresponding persistent index value used for range checking.  \n   Further options beyond this one are ephemeral and are never written to \n   disk */\n\n#define LAST_STORED_OPTION\t\t\tCRYPT_OPTION_MISC_SIDECHANNELPROTECTION\n#define LAST_OPTION_INDEX\t\t\t1000\n\n/* Get storage for the config option information */\n\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getOptionInfoStorage( void );\n\n/* Prototypes for functions in user_cfg.c */\n\nCHECK_RETVAL_PTR \\\nconst BUILTIN_OPTION_INFO *getBuiltinOptionInfoByCode( IN_RANGE( 0, LAST_OPTION_INDEX ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst int optionCode );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkConfigChanged( IN_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\tconst OPTION_INFO *optionList,\n\t\t\t\t\t\t\tIN_INT_SHORT const int configOptionsCount );\n\n#endif /* _USER_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/misc/user_rw.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t cryptlib Configuration Read/Write Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1994-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"trustmgr.h\"\n  #include \"asn1.h\"\n  #include \"user_int.h\"\n  #include \"user.h\"\n#else\n  #include \"cert/trustmgr.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"misc/user_int.h\"\n  #include \"misc/user.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_KEYSETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read an individual configuration option */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readConfigOption( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_HANDLE CRYPT_USER iCryptUser )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE attributeType;\n\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr;\n\tMESSAGE_DATA msgData;\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tlong optionCode;\n\tint value, tag, length, status;\n\n\t/* Read the wrapper and option index and map it to the actual option.  \n\t   If we find an unknown index or one that shouldn't be writeable to \n\t   persistent storage, we skip it and continue.  This is done to handle \n\t   new options that may have been added after this version of cryptlib \n\t   was built (for unknown indices) and because the stored configuration \n\t   options are an untrusted source so we have to check for attempts to \n\t   feed in bogus values (for non-writeable options) */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &optionCode );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( optionCode < 0 || optionCode > LAST_OPTION_INDEX )\n\t\t{\n\t\t/* Unknown option, ignore it */\n\t\treturn( readUniversal( stream ) );\n\t\t}\n\tbuiltinOptionInfoPtr = getBuiltinOptionInfoByCode( optionCode );\n\tif( builtinOptionInfoPtr == NULL || \\\n\t\tbuiltinOptionInfoPtr->index < 0 || \\\n\t\tbuiltinOptionInfoPtr->index > LAST_OPTION_INDEX || \\\n\t\tbuiltinOptionInfoPtr->index == CRYPT_UNUSED )\n\t\t{\n\t\t/* Unknown option, ignore it */\n\t\treturn( readUniversal( stream ) );\n\t\t}\n\tattributeType = builtinOptionInfoPtr->option;\n\n\t/* Read the option value and set the option.  We don't treat a failure \n\t   to set the option as a problem since the user probably doesn't want \n\t   the entire system to fail because of a bad configuration option, and \n\t   in any case we'll fall back to a safe default value */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( tag == BER_BOOLEAN || tag == BER_INTEGER )\n\t\t{\n\t\t/* It's a numeric value, read the appropriate type and try and set \n\t\t   the option */\n\t\tif( tag == BER_BOOLEAN )\n\t\t\tstatus = readBoolean( stream, &value );\n\t\telse\n\t\t\t{\n\t\t\tlong integer;\n\n\t\t\tstatus = readShortInteger( stream, &integer );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tif( !isIntegerRange( integer ) )\n\t\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\t\tvalue = ( int ) integer;\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t( void ) krnlSendMessage( iCryptUser, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, attributeType );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a string value, set the option straight from the encoded data */\n\tstatus = readGenericHole( stream, &length, 1, BER_STRING_UTF8 );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, length, SSKIP_MAX );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, dataPtr, length );\n\t( void ) krnlSendMessage( iCryptUser, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, attributeType );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Rumble through the configuration options to determine the total encoded \n   length of the ones that don't match the default setting.  We can't just \n   check the isDirty flag because if a value is reset to its default setting \n   the encoded size will be zero even though the isDirty flag is set */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int sizeofConfigData( IN_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\tconst OPTION_INFO *optionList, \n\t\t\t\t\t\t\t IN_INT_SHORT const int configOptionsCount,\n\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *length )\n\t{\n\tint dataLength = 0, i, LOOP_ITERATOR;\n\n\tassert( isReadPtrDynamic( optionList, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* Clear return value */\n\t*length = 0;\n\n\t/* Check each option to see whether it needs to be written to disk.  If \n\t   it does, determine its length */\n\tLOOP_LARGE( i = 0, \n\t\t\t\ti < configOptionsCount && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo != NULL && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo->option <= LAST_STORED_OPTION, \n\t\t\t\ti++ )\n\t\t{\n\t\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr = \\\n\t\t\t\t\t\t\t\t\toptionList[ i ].builtinOptionInfo;\n\t\tconst OPTION_INFO *optionInfoPtr = &optionList[ i ];\n\t\tint lengthValue;\n\n\t\t/* If it's an option that can't be written to disk, skip it */\n\t\tif( builtinOptionInfoPtr->index == CRYPT_UNUSED )\n\t\t\tcontinue;\n\n\t\tif( builtinOptionInfoPtr->type == OPTION_STRING )\n\t\t\t{\n\t\t\t/* If the string value is the same as the default, there's\n\t\t\t   nothing to do */\n\t\t\tif( optionInfoPtr->strValue == NULL || \\\n\t\t\t\toptionInfoPtr->strValue == builtinOptionInfoPtr->strDefault )\n\t\t\t\tcontinue;\n\t\t\tlengthValue = \\\n\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\tsizeofShortInteger( builtinOptionInfoPtr->index ) + \\\n\t\t\t\t\t\tsizeofShortObject( optionInfoPtr->intValue ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If the integer/boolean value that's currently set isn't the\n\t\t\t   default setting, update it */\n\t\t\tif( optionInfoPtr->intValue == builtinOptionInfoPtr->intDefault )\n\t\t\t\tcontinue;\n\t\t\tlengthValue = \\\n\t\t\t\t\tsizeofShortObject( \\\n\t\t\t\t\t\tsizeofShortInteger( builtinOptionInfoPtr->index ) + \\\n\t\t\t\t\t\t( builtinOptionInfoPtr->type == OPTION_NUMERIC ? \\\n\t\t\t\t\t\t  sizeofShortInteger( optionInfoPtr->intValue ) : \\\n\t\t\t\t\t\t  sizeofBoolean() ) );\n\t\t\t}\n\t\tENSURES( isShortIntegerRangeNZ( lengthValue ) );\n\t\tdataLength += lengthValue;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < configOptionsCount );\n\tENSURES( dataLength >= 0 && dataLength < MAX_BUFFER_SIZE );\n\n\t*length = dataLength;\n\treturn( CRYPT_OK );\n\t}\n\n/* Write the configuration data to a stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeConfigData( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_ARRAY( configOptionsCount ) \\\n\t\t\t\t\t\t\t\tconst OPTION_INFO *optionList,\n\t\t\t\t\t\t\tIN_INT_SHORT const int configOptionsCount )\n\t{\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( optionList, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* Write each option that needs to be written to the stream */\n\tLOOP_LARGE( i = 0, \n\t\t\t\ti < configOptionsCount && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo != NULL && \\\n\t\t\t\t\toptionList[ i ].builtinOptionInfo->option <= LAST_STORED_OPTION, \n\t\t\t\ti++ )\n\t\t{\n\t\tconst BUILTIN_OPTION_INFO *builtinOptionInfoPtr = \\\n\t\t\t\t\t\t\t\t\toptionList[ i ].builtinOptionInfo;\n\t\tconst OPTION_INFO *optionInfoPtr = &optionList[ i ];\n\n\t\t/* If it's an option that can't be written to disk, skip it */\n\t\tif( builtinOptionInfoPtr->index == CRYPT_UNUSED )\n\t\t\tcontinue;\n\n\t\tif( builtinOptionInfoPtr->type == OPTION_STRING )\n\t\t\t{\n\t\t\tif( optionInfoPtr->strValue == NULL || \\\n\t\t\t\toptionInfoPtr->strValue == builtinOptionInfoPtr->strDefault )\n\t\t\t\tcontinue;\n\t\t\twriteSequence( stream,\n\t\t\t\t\t\t   sizeofShortInteger( builtinOptionInfoPtr->index ) + \\\n\t\t\t\t\t\t   sizeofObject( optionInfoPtr->intValue ) );\n\t\t\twriteShortInteger( stream, builtinOptionInfoPtr->index,\n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\tstatus = writeCharacterString( stream, optionInfoPtr->strValue,\n\t\t\t\t\t\t\t\t\t\t   optionInfoPtr->intValue,\n\t\t\t\t\t\t\t\t\t\t   BER_STRING_UTF8 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tif( optionInfoPtr->intValue == builtinOptionInfoPtr->intDefault )\n\t\t\tcontinue;\n\t\tif( builtinOptionInfoPtr->type == OPTION_NUMERIC )\n\t\t\t{\n\t\t\twriteSequence( stream,\n\t\t\t\t\t\t   sizeofShortInteger( builtinOptionInfoPtr->index ) + \\\n\t\t\t\t\t\t   sizeofShortInteger( optionInfoPtr->intValue ) );\n\t\t\twriteShortInteger( stream, builtinOptionInfoPtr->index,\n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\tstatus = writeShortInteger( stream, optionInfoPtr->intValue,\n\t\t\t\t\t\t\t\t\t\tDEFAULT_TAG );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\twriteSequence( stream,\n\t\t\t\t\t\t   sizeofShortInteger( builtinOptionInfoPtr->index ) + \\\n\t\t\t\t\t\t   sizeofBoolean() );\n\t\t\twriteShortInteger( stream, builtinOptionInfoPtr->index,\n\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\tstatus = writeBoolean( stream, optionInfoPtr->intValue, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < configOptionsCount );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead Configuration Options \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read any user-defined configuration options.  Since the configuration \n   file is an untrusted source we set the values in it via external messages \n   rather than manipulating the configuration info directly, which means \n   that everything read is subject to the usual ACL checks */\n\n#ifdef USE_CERTIFICATES\n\nCHECK_RETVAL \\\nstatic int readTrustedCerts( IN_HANDLE const CRYPT_KEYSET iCryptKeyset,\n\t\t\t\t\t\t\t IN const DATAPTR trustInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ CRYPT_MAX_PKCSIZE + 1536 + 8 ];\n\tint status, LOOP_ITERATOR;\n\n\tREQUIRES( isHandleRangeValid( iCryptKeyset ) );\n\tREQUIRES( DATAPTR_ISSET( trustInfo ) );\n\n\t/* Read each trusted certificate from the keyset */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_PKCSIZE + 1536 );\n\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_TRUSTEDCERT );\n\tLOOP_LARGE_CHECK( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Add the certificate data as a trusted certificate item and look \n\t\t   for the next one */\n\t\tstatus = addTrustEntry( trustInfo, CRYPT_UNUSED, msgData.data,\n\t\t\t\t\t\t\t\tmsgData.length, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetMessageData( &msgData, buffer, CRYPT_MAX_PKCSIZE + 1536 );\n\t\t\tstatus = krnlSendMessage( iCryptKeyset, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );\n\t}\n#endif /* USE_CERTIFICATES */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint readConfig( IN_HANDLE const CRYPT_USER iCryptUser, \n\t\t\t\tIN_STRING const char *fileName, \n\t\t\t\tINOUT DATAPTR trustInfo )\n\t{\n\tCRYPT_KEYSET iCryptKeyset;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tDYNBUF configDB;\n\tchar configFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint configFilePathLen, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( iCryptUser == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptUser ) );\n\n\t/* Try and open the configuration file.  If we can't open it it merely \n\t   means that the file doesn't exist, which isn't an error, we'll go \n\t   with the built-in defaults */\n\tstatus = fileBuildCryptlibPath( configFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&configFilePathLen, fileName, \n\t\t\t\t\t\t\t\t\tstrlen( fileName ), BUILDPATH_GETPATH );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\t\t/* Can't build configuration path */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );\n\tcreateInfo.arg2 = CRYPT_KEYOPT_READONLY;\n\tcreateInfo.strArg1 = configFilePath;\n\tcreateInfo.strArgLen1 = configFilePathLen;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_KEYSET );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_OK );\t\t/* No configuration data present */\n\tiCryptKeyset = createInfo.cryptHandle;\n\n\t/* Get the configuration information from the keyset.  We fetch the \n\t   overall configuration information into a dynbuf and then optionally\n\t   read the trust information (trusted certificates) if certificate use\n\t   is enabled, after which we close the keyset and read the \n\t   configuration data from the dynbuf */\n\tstatus = dynCreate( &configDB, iCryptKeyset,\n\t\t\t\t\t\tCRYPT_IATTRIBUTE_CONFIGDATA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If there were no configuration options present there may still be \n\t\t   trusted certificates so we try and read those before exiting */\n#ifdef USE_CERTIFICATES\n\t\tif( status == CRYPT_ERROR_NOTFOUND && \\\n\t\t\tDATAPTR_ISSET( trustInfo ) )\n\t\t\t{\n\t\t\tstatus = readTrustedCerts( iCryptKeyset, trustInfo );\n\t\t\t}\n#endif /* USE_CERTIFICATES */\n\t\tkrnlSendNotifier( iCryptKeyset, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n#ifdef USE_CERTIFICATES\n\tif( DATAPTR_ISSET( trustInfo ) )\n\t\t{\n\t\tstatus = readTrustedCerts( iCryptKeyset, trustInfo );\n\t\t}\n#endif /* USE_CERTIFICATES */\n\tkrnlSendNotifier( iCryptKeyset, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdynDestroy( &configDB );\n\t\treturn( status );\n\t\t}\n\n\t/* Read each configuration option */\n\tsMemConnect( &stream, dynData( configDB ), dynLength( configDB ) );\n\tLOOP_LARGE_CHECK( cryptStatusOK( status ) && \\\n\t\t\t\t\t  stell( &stream ) < dynLength( configDB ) )\n\t\t{\n\t\tstatus = readConfigOption( &stream, iCryptUser );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tsMemDisconnect( &stream );\n\n\t/* Clean up */\n\tdynDestroy( &configDB );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite Configuration Options \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write any user-defined configuration options.  This is performed in two \n   phases, a first phase that encodes the configuration data and a second \n   phase that writes the data to disk.  The reason for the split is that the \n   second phase doesn't require the use of the user object data any more \n   and can be a somewhat lengthy process due to disk accesses and other bits \n   and pieces, because of this the caller is expected to unlock the user \n   object between the two phases to ensure that the second phase doesn't \n   stall all other operations that require it.\n   \n   The prepare phase is further subdivided into two sub-phases, necessitated \n   by the fact that we can have configuration data, trusted certificates, or \n   both, present to write.  First we determine what's present using \n   getConfigDisposition(), if there's configuration data present then we \n   prepare it using prepareConfigData(), and finally we write the \n   configuration data and/or trusted certificates using commitConfigData() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint getConfigDisposition( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t\t  IN_INT_SHORT const int configOptionsCount, \t\n\t\t\t\t\t\t  IN const DATAPTR trustInfo, \n\t\t\t\t\t\t  OUT_ENUM( CONFIG_DISPOSITION ) \\\n\t\t\t\t\t\t\tCONFIG_DISPOSITION_TYPE *disposition )\n\t{\n#ifdef USE_CERTIFICATES\n\tconst BOOLEAN hasTrustedCerts = trustedCertsPresent( trustInfo );\n#else\n\tconst BOOLEAN hasTrustedCerts = FALSE;\n#endif /* USE_CERTIFICATES */\n\tint length, status;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isWritePtr( disposition, sizeof( CONFIG_DISPOSITION_TYPE ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* Clear return value */\n\t*disposition = CONFIG_DISPOSITION_NONE;\n\n\t/* If neither the configuration options nor any certificate trust \n\t   settings have changed, there's nothing to do */\n\tif( !checkConfigChanged( configOptions, configOptionsCount ) && \\\n\t\t!hasTrustedCerts )\n\t\t{\n\t\t*disposition = CONFIG_DISPOSITION_NO_CHANGE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Determine the total encoded length of the configuration options */\n\tstatus = sizeofConfigData( configOptions, configOptionsCount, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\t/* There's no configuration data present, if there are trusted \n\t\t   certificates present then we need to write those, otherwise the\n\t\t   configuration file will be empty and the caller can delete it */\n\t\t*disposition = hasTrustedCerts ? \\\n\t\t\t\t\t\t\tCONFIG_DISPOSITION_TRUSTED_CERTS_ONLY : \\\n\t\t\t\t\t\t\tCONFIG_DISPOSITION_EMPTY_CONFIG_FILE;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* There's configuration data present, report whether there are trusted\n\t   certificates present as well */\n\t*disposition = hasTrustedCerts ? CONFIG_DISPOSITION_BOTH : \\\n\t\t\t\t\t\t\t\t\t CONFIG_DISPOSITION_DATA_ONLY;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint prepareConfigData( INOUT_ARRAY( configOptionsCount ) TYPECAST( OPTION_INFO * ) \\\n\t\t\t\t\t\t\tvoid *configOptions, \n\t\t\t\t\t   IN_INT_SHORT const int configOptionsCount, \t\n\t\t\t\t\t   OUT_BUFFER_ALLOC_OPT( *dataLength ) void **dataPtrPtr, \n\t\t\t\t\t   OUT_DATALENGTH_Z int *dataLength )\n\t{\n\tSTREAM stream;\n\tvoid *dataPtr;\n\tint length, status;\n\n\tassert( isReadPtrDynamic( configOptions, \n\t\t\t\t\t\t\t  sizeof( OPTION_INFO ) * configOptionsCount ) );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( configOptionsCount ) );\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\t*dataLength = 0;\n\n\t/* Determine the total encoded length of the configuration options */\n\tstatus = sizeofConfigData( configOptions, configOptionsCount, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\t/* Allocate a buffer to hold the encoded values */\n\tREQUIRES( rangeCheck( length, 1, MAX_BUFFER_SIZE ) );\n\tif( ( dataPtr = clAlloc( \"prepareConfigData\", length ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\n\t/* Write the configuration options */\n\tsMemOpen( &stream, dataPtr, length );\n\tstatus = writeConfigData( &stream, configOptions, configOptionsCount );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclFree( \"prepareConfigData\", dataPtr );\n\t\tDEBUG_DIAG(( \"Couldn't prepare config data for write\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\t*dataPtrPtr = dataPtr;\n\t*dataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint commitConfigData( IN_STRING const char *fileName,\n\t\t\t\t\t  IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t  IN_DATALENGTH_Z const int dataLength,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_USER iTrustedCertUserObject )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tchar configFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint configFilePathLen, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tREQUIRES( iTrustedCertUserObject == CRYPT_UNUSED || \\\n\t\t\t  ( iTrustedCertUserObject == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t\tisHandleRangeValid( iTrustedCertUserObject ) ) );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( dataLength > 0 && dataLength < MAX_BUFFER_SIZE ) );\n\n\t/* Build the path to the configuration file and try and create it */\n\tstatus = fileBuildCryptlibPath( configFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&configFilePathLen, fileName, \n\t\t\t\t\t\t\t\t\tstrlen( fileName ), \n\t\t\t\t\t\t\t\t\tBUILDPATH_CREATEPATH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Map the lower-level filesystem-specific error into a more \n\t\t   meaningful generic error */\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_KEYSET_FILE );\n\tcreateInfo.arg2 = CRYPT_KEYOPT_CREATE;\n\tcreateInfo.strArg1 = configFilePath;\n\tcreateInfo.strArgLen1 = configFilePathLen;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_KEYSET );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Map the lower-level keyset-specific error into a more meaningful\n\t\t   generic error */\n\t\treturn( CRYPT_ERROR_OPEN );\n\t\t}\n\n\t/* Send the configuration data (if there is any) and any trusted \n\t   certificates to the keyset.  { data, dataLength } can be empty if \n\t   there are only trusted certificates to write */\n\tif( dataLength > 0 )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) data, dataLength );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CONFIGDATA );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tiTrustedCertUserObject != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( iTrustedCertUserObject, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRUBUTE_CERTKEYSET );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfileErase( configFilePath );\n\t\treturn( CRYPT_ERROR_WRITE );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDelete Configuration Options \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete the configuration file.  This always returns an OK status even if\n   the delete fails since it's not certain what we should do in this case */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteConfig( IN_STRING const char *fileName )\n\t{\n\tchar configFilePath[ MAX_PATH_LENGTH + 1 + 8 ];\n\tint configFilePathLen, status;\n\n\tassert( isReadPtr( fileName, 2 ) );\n\n\tANALYSER_HINT_STRING( fileName );\n\n\tstatus = fileBuildCryptlibPath( configFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&configFilePathLen, fileName, \n\t\t\t\t\t\t\t\t\tstrlen( fileName ), BUILDPATH_GETPATH );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconfigFilePath[ configFilePathLen ] = '\\0';\n\t\tfileErase( configFilePath );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_KEYSETS */\n"
  },
  {
    "path": "deps/cl345/random/4758.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t IBM 4758 Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1998-2002\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include <time.h>\n#include \"../crypt.h\"\n\n/* OS-specific includes */\n\n#include \"scc_int.h\"\n\n/* The size of the returned random data and the number of calls we make for\n   a slow poll.  Since the 4758 uses a hardware RNG, it doesn't matter if we\n   call it several times in succession */\n\n#define SCC_RANDOM_SIZE\t\t8\t\t/* 64 bits */\n#define SCC_NO_CALLS\t\t4\t\t/* 256 bits total */\n\nvoid fastPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ SCC_RANDOM_SIZE ];\n\n\tsccGetRandomNumber( buffer, RANDOM_RANDOM );\n\tsetResourceData( &msgData, buffer, SCC_RANDOM_SIZE );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, SCC_RANDOM_SIZE );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ SCC_RANDOM_SIZE * SCC_NO_CALLS ];\n\tint quality = 100, i;\n\n\tfor( i = 0; i < SCC_NO_CALLS; i++ )\n\t\tsccGetRandomNumber( buffer + ( i * SCC_RANDOM_SIZE ), RANDOM_RANDOM );\n\n\t/* Add the data to the randomness pool */\n\tsetResourceData( &msgData, buffer, SCC_RANDOM_SIZE * SCC_NO_CALLS );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, SCC_RANDOM_SIZE * SCC_NO_CALLS );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t &quality, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/amx.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAMX Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an external source.  In its\n   current form it does not provide any usable entropy and should not be\n   used as an entropy source */\n\n/* General includes */\n\n#include <cjzzz.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\taddRandomLong( randomState, cjtmtick() );\n\tendRandomData( randomState, 1 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\treturn;\n\t}\n"
  },
  {
    "path": "deps/cl345/random/beos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  BeOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\tCopyright Peter Gutmann and Osma Ahvenlampi 1996-2003\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* These get defined by the Be headers */\n\n#undef min\n#undef max\n\n/* OS-specific includes */\n\n#include <fcntl.h>\n#include <sys/time.h>\n#include <kernel/fs_info.h>\n#include <kernel/OS.h>\n#include <kernel/image.h>\n\n/* The following is defined in <interface/InterfaceDefs.h>, however we\n   can't include that header because it uses some C++ keywords and so won't\n   compile when used with C code.\n\n   Unfortunately the C++-isms go further than that, extending to the\n   interface kit functions like idle_time(), modifiers(), and get_key_info(),\n   which are only present in libraries in C++ name-mangled form and can't\n   safely be called from a C-only module */\n\ntypedef struct {\n\tuint32  modifiers;\n\tuint8   key_states[16];\n\t} key_info;\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tstruct timeval tv;\n\tsystem_info info;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\tgettimeofday( &tv, NULL );\n\taddRandomValue( randomState, tv.tv_sec );\n\taddRandomValue( randomState, tv.tv_usec );\n\n\t/* Get the number of microseconds since the user last provided any input\n\t   to any part of the system, the state of keyboard shift keys */\n#if 0\t/* See comment at start */\n\tbigtime_t idleTime;\n\tuint32 value;\n\n\tidleTime = idle_time();\n\taddRandomData( randomState, &idleTime, sizeof( bigtime_t ) );\n\tvalue = modifiers();\n\taddRandomValue( randomState, value );\n#endif /* 0 */\n\n\t/* Get various fixed values (the 64-bit machine ID, CPU count and type(s),\n\t   clock speed, platform type, etc) and variable resources (number of in-\n\t   use pages, semaphores, ports, threads, teams, number of page faults,\n\t   and number of microseconds the CPU has been active) */\n\tget_system_info( &info );\n\taddRandomData( randomState, &info, sizeof( info ) );\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 5 );\n\t}\n\n#define DEVRANDOM_BITS\t\t4096\n#define DEVRANDOM_BYTES\t\t( min( DEVRANDOM_BITS / 8 ), RANDOM_BUFSIZE )\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tteam_info teami;\n\tthread_info threadi;\n\tarea_info areai;\n\tport_info porti;\n\tsem_info semi;\n\timage_info imagei;\n\tdouble temperature;\n\tint32 devID, cookie;\n\tint fd, value;\n\n\tif( ( fd = open( \"/dev/urandom\", O_RDONLY ) ) >= 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tstatic const int quality = 100;\n\n\t\t/* Read data from /dev/urandom, which won't block (although the\n\t\t   quality of the noise is lesser). */\n\t\tread( fd, buffer, DEVRANDOM_BYTES );\n\t\tsetMessageData( &msgData, buffer, DEVRANDOM_BYTES );\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\tzeroise( buffer, DEVRANDOM_BYTES );\n\t\tclose( fd );\n\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\treturn;\n\t\t}\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get the state of all keys on the keyboard and various other\n\t   system states */\n#if 0\t/* See comment at start */\n\tkey_info keyInfo;\n\n\tif( get_key_info( &keyInfo ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &keyInfo, sizeof( key_info ) );\n#endif /* 0 */\n\tvalue = is_computer_on();\t/* Returns 1 if computer is on */\n\taddRandomValue( randomState, value );\n\ttemperature = is_computer_on_fire();\t/* MB temp.if on fire */\n\taddRandomData( randomState, &temperature, sizeof( double ) );\n\n\t/* Get information on all running teams (thread groups, ie applications).\n\t   This returns the team ID, number of threads, images, and areas,\n\t   debugger port and thread ID, program args, and uid and gid */\n\tcookie = 0;\n\twhile( get_next_team_info( &cookie, &teami ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &teami, sizeof( teami ) );\n\n\t/* Get information on all running threads.  This returns the thread ID,\n\t   team ID, thread name and state (eg running, suspended, asleep,\n\t   blocked), the thread priority, elapsed user and kernel time, and\n\t   thread stack information */\n\tcookie = 0;\n\twhile( get_next_thread_info( 0, &cookie, &threadi ) == B_NO_ERROR )\n\t\t{\n\t\taddRandomValue( randomState, has_data( threadi.thread ) );\n\t\taddRandomData( randomState, &threadi, sizeof( threadi ) );\n\t\t}\n\n\t/* Get information on all memory areas (chunks of virtual memory).  This\n\t   returns the area ID, name, size, locking scheme and protection bits,\n\t   ID of the owning team, start address, number of resident bytes, copy-\n\t   on-write count, an number of pages swapped in and out */\n\tcookie = 0;\n\twhile( get_next_area_info( 0, &cookie, &areai ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &areai, sizeof( areai ) );\n\n\t/* Get information on all message ports.  This returns the port ID, ID of\n\t   the owning team, message queue length, number of messages in the\n\t   queue, and total number of messages processed */\n\tcookie = 0;\n\twhile( get_next_port_info( 0, &cookie, &porti ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &porti, sizeof( porti ) );\n\n\t/* Get information on all semaphores.  This returns the semaphore and\n\t   owning team ID, the name, thread count, and the ID of the last thread\n\t   which acquired the semaphore */\n\tcookie = 0;\n\twhile( get_next_sem_info( 0, &cookie, &semi ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &semi, sizeof( semi ) );\n\n\t/* Get information on all images (code blocks, eg applications, shared\n\t   libraries, and add-on images (DLL's on steroids).  This returns the\n\t   image ID and type (app, library, or add-on), the order in which the\n\t   image was loaded compared to other images, the address of the init\n\t   and shutdown routines, the device and node where the image lives,\n\t   and the image text and data sizes) */\n\tcookie = 0;\n\twhile( get_next_image_info( 0, &cookie, &imagei ) == B_NO_ERROR )\n\t\taddRandomData( randomState, &imagei, sizeof( imagei ) );\n\n\t/* Get information on all storage devices.  This returns the device\n\t   number, root inode, various device parameters such as I/O block size,\n\t   and the number of free and used blocks and inodes */\n\tdevID = 0;\n\twhile( next_dev( &devID ) >= 0 )\n\t\t{\n\t\tfs_info fsInfo;\n\n\t\tif( fs_stat_dev( devID, &fsInfo ) == B_NO_ERROR )\n\t\t\taddRandomData( randomState, &fsInfo, sizeof( fs_info ) );\n\t\t}\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 100 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/chorus.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tChorusOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an external source.  In its\n   current form it does not provide any usable entropy and should not be\n   used as an entropy source */\n\n/* General includes */\n\n#include <chorus.h>\n#include <afexec.h>\n#include <exec/chTime.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tKnTimeVal timeVal;\n\n\t/* The sysTime() ns timer seems to be quantised to ms rather than\n\t   being true ns timer output.  Other (supposedly) high-speed timers\n\t   like sysBench() are no better, on x86 hardware this is quantised\n\t   to 5ms intervals */\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tsysTime( &timeVal );\n\taddRandomData( randomState, &timeVal, sizeof( KnTimeVal ) );\n\tendRandomData( randomState, 1 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\taddRandomValue( randomState, agetId() );\n\tendRandomData( randomState, 1 );\n\n\t/* ChorusOS provides the MkStat family of calls (equivalent to Sun's\n\t   kstats), but these can only be called in supervisor mode */\n\treturn;\n\t}\n"
  },
  {
    "path": "deps/cl345/random/dos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  MSDOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2002\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide OS-specific randomness.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n\n/* OS-specific includes */\n\n#include <fcntl.h>\n#include <io.h>\n#include <time.h>\n\nvoid fastPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\ttime_t timeStamp = time( NULL );\n\n\t/* There's not much we can do under DOS, we rely entirely on the\n\t   /dev/random read for information */\n\tsetMessageData( &msgData, &timeStamp, sizeof( time_t ) );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ 128 ];\n\tint quality = 100, fd, count, total;\n\n\t/* Read 128 bytes from /dev/random and add it to the buffer.  Since DOS\n\t   doesn't swap we don't need to be as careful about copying data to\n\t   temporary buffers as we usually are.  We also have to use unbuffered\n\t   I/O, since the high-level functions will read BUFSIZ bytes at once\n\t   from the input, comletely draining the driver of any randomness */\n\tif( ( fd = open( \"/dev/random$\", O_RDONLY | O_BINARY) ) == -1 && \\\n\t\t( fd = open( \"/dev/random\", O_RDONLY | O_BINARY) ) == -1 )\n\t\treturn;\n\tfor( total = 0; total < sizeof( buffer ); )\n\t\t{\n\t\tcount = read( fd, buffer + total, sizeof( buffer ) - total );\n\t\tif( count <= 0 )\n\t\t\tbreak;\n\t\ttotal += count;\n\t\t}\n\tclose( fd );\n\tsetMessageData( &msgData, buffer, total );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, sizeof( buffer ) );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t &quality, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/ecos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\teCOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   eCos provides very few entropy sources, the code below provides very \n   little usable entropy and should not be relied upon as the sole entropy \n   source for the system but should be augmented with randomness from \n   external hardware sources */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <cyg/hal/hal_arch.h>\n#include <cyg/kernel/kapi.h>\n#ifdef CYGPKG_POWER\n  #include <cyg/power/power.h>\n#endif /* CYGPKG_POWER */\n#ifdef CYGPKG_IO_PCI\n  #include <cyg/io/pci.h>\n#endif /* CYGPKG_IO_PCI */\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tcyg_handle_t hThread = 0;\n\tcyg_uint16 threadID = 0;\n#ifdef CYGPKG_IO_PCI\n\tcyg_pci_device_id pciDeviceID;\n#endif /* CYGPKG_IO_PCI */\n#ifdef CYGPKG_POWER\n\tPowerController *powerControllerInfo;\n#endif /* CYGPKG_POWER */\n\tint itemsAdded = 0, iterationCount;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get the thread handle, ID, state, priority, and stack usage for \n\t   every thread in the system */\n\tfor( iterationCount = 0;\n\t\t cyg_thread_get_next( &hThread, &threadID ) && \\\n\t\t\titerationCount < FAILSAFE_ITERATIONS_MED;\n\t\t iterationCount++ )\n\t\t{\n\t\tcyg_thread_info threadInfo;\n\n\t\tif( !cyg_thread_get_info( hThread, threadID, &threadInfo ) )\n\t\t\tcontinue;\n\t\taddRandomData( randomState, &threadInfo, sizeof( cyg_thread_info ) );\n\t\titemsAdded++;\n\t\t}\n\n\t/* Walk the power-management info getting the power-management state for \n\t   each device.  This works a bit strangely, the power controller \n\t   information is a static table created at system build time so all that \n\t   we're doing is walking down an array getting one entry after another */\n#ifdef CYGPKG_POWER\n\tfor( powerControllerInfo = &( __POWER__[ 0 ] ), iterationCount = 0;\n\t\t powerControllerInfo != &( __POWER_END__ ) && \\\n\t\t\titerationCount < FAILSAFE_ITERATIONS_MED;\n\t\t powerControllerInfo++, iterationCount++ )\n\t\t{\n\t\tconst PowerMode mode = \\\n\t\t\tpower_get_controller_mode( powerControllerInfo );\n\n\t\taddRandomValue( randomState, mode );\n\t\t}\n#endif /* CYGPKG_POWER */\n\n\t/* Add PCI device information if there's PCI support present */\n#ifdef CYGPKG_IO_PCI\n\tif( cyg_pci_find_next( CYG_PCI_NULL_DEVID, &pciDeviceID ) )\n\t\t{\n\t\titerationCount = 0;\n\t\tdo\n\t\t\t{\n\t\t\tcyg_pci_device pciDeviceInfo;\n\n\t\t\tcyg_pci_get_device_info( pciDeviceID, &pciDeviceInfo );\n\t\t\taddRandomValue( randomState, PowerMode );\n\t\t\taddRandomData( randomState, &pciDeviceInfo, \n\t\t\t\t\t\t   sizeof( cyg_pci_device ) );\n\t\t\titemsAdded++;\n\t\t\t}\n\t\twhile( cyg_pci_find_next( pciDeviceID, &pciDeviceID ) && \\\n\t\t\t   iterationCount++ < FAILSAFE_ITERATIONS_MED );\n\t\t}\n#endif /* CYGPKG_IO_PCI */\n\n\t/* eCOS also has a CPU load-monitoring facility that we could in theory \n\t   use as a source of entropy but this is really meant for performance-\n\t   monitoring and isn't very suitable for use as an entropy source.  The \n\t   way this works is that you first call a calibration function \n\t   cyg_cpuload_calibrate() and then when it you want to get load \n\t   statistics call cyg_cpuload_create()/cyg_cpuload_get()/\n\t   cyg_cpuload_delete(), with get() returning the load over a 0.1s, 1s, \n\t   and 10s interval.  The only one of these capabilities that's even \n\t   potentially usable is cyg_cpuload_calibrate() and even that's rather \n\t   dubious for general use since it runs a thread at the highest priority \n\t   level for 0.1s for calibration purposes and measures the elapsed tick \n\t   count, which will hardly endear us to other threads in the system.  \n\t   It's really meant for development-mode load measurements and can't \n\t   safely be used as an entropy source */\n\n\t/* Flush any remaining data through and produce an estimate of its\n\t   value.  Unlike its use in standard OSes this isn't really a true \n\t   estimate since virtually all of the entropy is coming from the seed\n\t   file, all this does is complete the seed-file quality estimate to\n\t   make sure that we don't fail the entropy test */\n\tendRandomData( randomState, ( itemsAdded > 5 ) ? 20 : 0 );\n\t}\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tcyg_uint32 clockTicks;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\thal_clock_read( &clockTicks );\n\n\tendRandomData( randomState, 1 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/embos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  embOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an external source.  In its\n   current form it does not provide any usable entropy and should not be\n   used as an entropy source */\n\n/* General includes */\n\n#include <RTOS.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n#ifdef USE_TCP\n  #include <IP.h>\n#endif /* USE_TCP */\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Add the current time in microseconds */\n\taddRandomLong( randomState, OS_GetTime_us() );\n\n\t/* Add the task control block containing the current tasks's state \n\t   information, and a mask of signalled task events */\n\taddRandomData( randomState, OS_GetTaskID(), sizeof( OS_TASK ) );\n\taddRandomLong( randomState, OS_GetEventsOccurred( NULL ) );\n\n\tendRandomData( randomState, 20 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tstatic BOOLEAN addedStaticData = FALSE;\n#ifdef USE_TCP\n\tint interface;\n#endif /* USE_TCP */\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get static system information */\n\tif( !addedStaticData )\n\t\t{\n\t\tconst char *string;\n\n\t\tstring = OS_GetCPU();\n\t\taddRandomData( randomState, string, strlen( string ) );\n\t\tstring = OS_GetLibMode();\n\t \taddRandomData( randomState, string, strlen( string ) );\n\t\tstring = OS_GetModel();\n\t\taddRandomData( randomState, string, strlen( string ) );\n\t\tstring = OS_GetLibName();\n\t\taddRandomData( randomState, string, strlen( string ) );\n\t\taddRandomLong( randomState, OS_GetVersion() );\n#ifdef USE_TCP\n\t\taddRandomLong( randomState, IP_GetVersion() );\n#endif /* USE_TCP */\n\n\t\taddedStaticData = TRUE;\n\t\t}\n\n\t/* Get a bit mask of active devices */\n\taddRandomLong( randomState, OS_POWER_GetMask() );\n\n\t/* Get the task, system, and interrupt stack address, total size, and \n\t   unused space */\n \taddRandomData( randomState, OS_GetStackBase( NULL ), \n\t\t\t\t   sizeof( void * ) );\n\taddRandomLong( randomState, OS_GetStackSize( NULL ) );\n\taddRandomLong( randomState, OS_GetStackSpace( NULL ) );\n \taddRandomData( randomState, OS_GetSysStackBase(), \n\t\t\t\t   sizeof( void * ) );\n\taddRandomLong( randomState, OS_GetSysStackSize() );\n\taddRandomLong( randomState, OS_GetSysStackSpace() );\n \taddRandomData( randomState, OS_GetIntStackBase(), \n\t\t\t\t   sizeof( void * ) );\n\taddRandomLong( randomState, OS_GetIntStackSize() );\n\taddRandomLong( randomState, OS_GetIntStackSpace() );\n\n\t/* Add networking-related data */\n#ifdef USE_TCP\n\tinterface = IP_GetPrimaryIFace();\n\taddRandomLong( randomState, IP_GetCurrentLinkSpeed() );\n\taddRandomLong( randomState, IP_GetGWAddr( ( BYTE ) interface ) );\n\taddRandomLong( randomState, IP_GetIPAddr( ( BYTE ) interface ) );\n\taddRandomLong( randomState, IP_DNS_GetServer() );\n\taddRandomLong( randomState, IP_TCP_GetMTU( ( BYTE ) interface ) );\n#endif /* USE_TCP */\n\n\tendRandomData( randomState, 20 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/mac.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMacintosh Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\tCopyright Peter Gutmann and Matthijs van Duin 1997-2002\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* Mac threads are cooperatively scheduled (so they're what Win32 calls\n   fibers rather than true threads) and there isn't any real equivalent of a\n   mutex (only critical sections which prevent any other thread from being\n   scheduled, which defeats the point of multithreading), so we don't support\n   this pseudo-threading for randomness polling.  If proper threading were\n   available, we'd use NewThread()/DisposeThread() to create/destroy the\n   background randomness-polling thread */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n/* Filled in by Matthijs van Duin */\n\n#include <Power.h>\n#include <Sound.h>\n#include <Threads.h>\n#include <Events.h>\n#include <Scrap.h>\n#include <MacTypes.h>\n#include <Serial.h>\n#include <Processes.h>\n#include <Devices.h>\n#include <Disks.h>\n#include <OSUtils.h>\n#include <Start.h>\n#include <AppleTalk.h>\n#include <DeskBus.h>\n#include <Retrace.h>\n#include <SCSI.h>\n#include <SpeechSynthesis.h>\n#include <Resources.h>\n#include <Script.h>\n\n#if defined __MWERKS__\n  #pragma mpwc_relax off\n  #pragma extended_errorcheck on\n#endif\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n/*\tBatteryTimeRec batteryTimeInfo; */\n\tSMStatus soundStatus;\n\tThreadID threadID;\n\tThreadState threadState;\n\tEventRecord eventRecord;\n\tPoint point;\n\tWindowPtr windowPtr;\n\tPScrapStuff scrapInfo;\n/*\tBYTE dataBuffer[ 2 + 8 ]; */\n/*\tshort driverRefNum; */\n\tUInt32 dateTime;\n/*\tint count, dummy; */\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get the status of the last alert, how much battery time is remaining\n\t   and the voltage from all batteries, the internal battery status, the\n\t   current date and time and time since system startup in ticks, the\n\t   application heap limit and current and heap zone, free memory in the\n\t   current and system heap, microseconds since system startup, whether\n\t   QuickDraw has finished drawing, modem status, SCSI status\n\t   information, maximum block allocatable without compacting, available\n\t   stack space, the last QuickDraw error code */\n/*\taddRandomValue( randomState, GetAlertStage() );\n\tcount = BatteryCount();\n\twhile( count-- > 0 )\n\t\t{\n\t\taddRandomValue( randomState,\n\t\t\t\t   GetBatteryVoltage( count ) );\n\t\tGetBatteryTimes( count, &batteryTimeInfo );\n\t\taddRandomData( randomState, &batteryTimeInfo,\n\t\t\t\t\t   sizeof( BatteryTimeRec ) );\n\t\t}\n\tif( !BatteryStatus( buffer, dataBuffer + 1 ) )\n\t\taddRandomValue( randomState, dataBuffer );\n*/\tGetDateTime( &dateTime );\n\taddRandomValue( randomState, dateTime );\n\taddRandomValue( randomState, TickCount() );\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\taddRandomValue( randomState, GetApplLimit() );\n\taddRandomValue( randomState, GetZone() );\n\taddRandomValue( randomState, SystemZone() );\n\taddRandomValue( randomState, FreeMem() );\n\taddRandomValue( randomState, FreeMemSys() );\n#endif\n/*\tUnsignedWide usSinceStartup;\n\n\tMicroSeconds( &usSinceStartup );\n\taddRandomData( randomState, &usSinceStartup, sizeof( UnsignedWide ) ); */\n\taddRandomValue( randomState, QDDone( NULL ) );\n/*\tModemStatus( dataBuffer );\n\taddRandomValue( randomState, dataBuffer[ 0 ] ); */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\taddRandomValue( randomState, SCSIStat() );\n#endif\n\taddRandomValue( randomState, MaxBlock() );\n\taddRandomValue( randomState, StackSpace() );\n\taddRandomValue( randomState, QDError() );\n\n\t/* Get the event code and message, time, and mouse location for the next\n\t   event in the event queue and the OS event queue */\n\tif( EventAvail( everyEvent, &eventRecord ) )\n\t\taddRandomData( randomState, &eventRecord, sizeof( EventRecord ) );\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\tif( OSEventAvail( everyEvent, &eventRecord ) )\n\t\taddRandomData( randomState, &eventRecord, sizeof( EventRecord ) );\n#endif\n\n\t/* Get all sorts of information such as device-specific info, grafport\n\t   information, visible and clipping region, pattern, pen, text, and\n\t   colour information, and other details, on the topmost window.  Also\n\t   get the window variant.  If there's a colour table record, add the\n\t   colour table as well */\n\tif( ( windowPtr = FrontWindow() ) != NULL )\n\t\t{\n/*\t\tCTabHandle colourHandle; */\n\n#if !defined OPAQUE_TOOLBOX_STRUCTS || !OPAQUE_TOOLBOX_STRUCTS\n\t\taddRandomData( randomState, windowPtr, sizeof( GrafPort ) );\n#endif\n\t\taddRandomValue( randomState, GetWVariant( windowPtr ) );\n/*\t\tif( GetAuxWin( windowPtr, colourHandle ) )\n\t\t\t{\n\t\t\tCTabPtr colourPtr;\n\n\t\t\tHLock( colourHandle );\n\t\t\tcolourPtr = *colourHandle;\n\t\t\taddRandomData( randomState, colourPtr, sizeof( ColorTable ) );\n\t\t\tHUnlock( colourHandle );\n\t\t\t} */\n\t\t}\n\n\t/* Get mouse-related such as the mouse button status and mouse position,\n\t   information on the window underneath the mouse */\n\taddRandomValue( randomState, Button() );\n\tGetMouse( &point );\n\taddRandomData( randomState, &point, sizeof( Point ) );\n\tFindWindow( point, &windowPtr );\n#if !defined OPAQUE_TOOLBOX_STRUCTS || !OPAQUE_TOOLBOX_STRUCTS\n\tif( windowPtr != NULL )\n\t\taddRandomData( randomState, windowPtr, sizeof( GrafPort ) );\n#endif\n\n\t/* Get the size, handle, and location of the desk scrap/clipboard */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\tscrapInfo = InfoScrap();\n\taddRandomData( randomState, scrapInfo, sizeof( ScrapStuff ) );\n#endif\n\n\t/* Get information on the current thread */\n\tthreadID = kCurrentThreadID; /*GetThreadID( &threadID ); */\n\tGetThreadState( threadID, &threadState );\n\taddRandomData( randomState, &threadState, sizeof( ThreadState ) );\n\n\t/* Get the sound mananger status.  This gets the number of allocated\n\t   sound channels and the current CPU load from these channels */\n\tSndManagerStatus( sizeof( SMStatus ), &soundStatus );\n\taddRandomData( randomState, &soundStatus, sizeof( SMStatus ) );\n\n\t/* Get the speech manager version and status */\n/*\tNumVersion version;\n\n\tversion = SpeechManagerVersion();\n\taddRandomData( randomState, &version, sizeof( NumVersion ) );\n\taddRandomValue( randomState, SpeechBusy() );\n*/\n\t/* Get the status of the serial port.  This gets information on recent\n\t   errors, read and write pending status, and flow control values */\n/*\tif( !OpenDriver( \"\\p.AIn\", &driverRefNum ) )\n\t\t{\n\t\tSerStaRec serialStatus;\n\n\t\tSetStatus( driverRefNum, &serialStatus );\n\t\taddRandomData( randomState, &serialStatus, sizeof( SerStaRec ) );\n\t\t}\n\tif( !OpenDriver( \"\\p.AOut\", &driverRefNum ) )\n\t\t{\n\t\tSerStaRec serialStatus;\n\n\t\tSetStatus( driverRefNum, &serialStatus );\n\t\taddRandomData( randomState, &serialStatus, sizeof( SerStaRec ) );\n\t\t} */\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 10 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tProcessSerialNumber psn;\n\tGDHandle deviceHandle;\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\tQElemPtr queuePtr;\n#endif\n\tQHdrPtr queueHdr;\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Walk through the list of graphics devices adding information about\n\t   a device (IM VI 21-21) */\n\tdeviceHandle = GetDeviceList();\n\twhile( deviceHandle != NULL )\n\t\t{\n\t\tGDHandle currentHandle = deviceHandle;\n\t\tGDPtr devicePtr;\n\n\t\tHLock( ( Handle ) currentHandle );\n\t\tdevicePtr = *currentHandle;\n\t\tdeviceHandle = devicePtr->gdNextGD;\n\t\taddRandomData( randomState, devicePtr, sizeof( GDevice ) );\n\t\tHUnlock( ( Handle ) currentHandle );\n\t\t}\n\n\t/* Walk through the list of processes adding information about each\n\t   process, including the name and serial number of the process, file and\n\t   resource information, memory usage information, the name of the\n\t   launching process, launch time, and accumulated CPU time (IM VI 29-17) */\n\tpsn.highLongOfPSN = 0;\n\tpsn.lowLongOfPSN = kNoProcess;\n\twhile( !GetNextProcess( &psn ) )\n\t\t{\n\t\tProcessInfoRec infoRec;\n\t\tGetProcessInformation( &psn, &infoRec );\n\t\taddRandomData( randomState, &infoRec, sizeof( ProcessInfoRec ) );\n\t\t}\n\n\t/* Get the command type, trap address, and parameters for all commands in\n\t   the file I/O queue.  The parameters are quite complex and are listed\n\t   on page 117 of IM IV, and include reference numbers, attributes, time\n\t   stamps, length and file allocation information, finder info, and large\n\t   amounts of other volume and filesystem-related data */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\tif( ( queueHdr = GetFSQHdr() ) != NULL )\n\t\tqueuePtr = queueHdr->qHead;\n\t\twhile( queuePtr != NULL )\n\t\t\t{\n\t\t\t/* The queue entries are variant records of variable length so we\n\t\t\t   need to adjust the length parameter depending on the record\n\t\t\t   type */\n\t\t\taddRandomData( randomState, queuePtr, 32 ); /* dunno how big.. */\n\t\t\tqueuePtr = queuePtr->qLink;\n\t\t\t}\n#endif\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\tStr255 volName;\n\t\tGDHandle deviceHandle;\n\t\tDrvSts driveStatus;\n\t\tMachineLocation machineLocation;\n\t\tQHdrPtr vblQueue;\n\t\tSysEnvRec sysEnvirons;\n\t\tSysPPtr pramPtr;\n\t\tDefStartRec startupInfo;\n\t\tDefVideoRec videoInfo;\n\t\tDefOSRec osInfo;\n\t\tXPPParamBlock appleTalkParams;\n\t\tunsigned char *driverNames[] = {\n\t\t\t\"\\p.AIn\", \"\\p.AOut\", \"\\p.AppleCD\", \"\\p.ATP\", \"\\p.BIn\", \"\\p.BOut\", \"\\p.MPP\",\n\t\t\t\"\\p.Print\", \"\\p.Sony\", \"\\p.Sound\", \"\\p.XPP\", NULL\n\t\t\t};\n\t\tSInt16 count, node, net, vRefNum, script;\n\t\tSInt32 lcount, volume;\n\n\t\t/* Get the current font family ID, node ID of the local AppleMumble\n\t\t   router, caret blink delay, CPU speed, double-click delay, sound\n\t\t   volume, application and system heap zone, the number of resource\n\t\t   types in the application, the number of sounds voices available,\n\t\t   the FRef of the current resource file, volume of the sysbeep,\n\t\t   primary line direction, computer SCSI disk mode ID, timeout before\n\t\t   the screen is dimmed and before the computer is put to sleep,\n\t\t   number of available threads in the thread pool, whether hard drive\n\t\t   spin-down is disabled, the handle to the i18n resources, timeout\n\t\t   time for the internal HDD, */\n\t\taddRandomValue( randomState, GetAppFont() );\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\taddRandomValue( randomState, GetBridgeAddress() );\n#endif\n\t\taddRandomValue( randomState, GetCaretTime() );\n/*\t\taddRandomValue( randomState, GetCPUSpeed() ); */\n\t\taddRandomValue( randomState, GetDblTime() );\n\t\tGetSysBeepVolume( &volume );\n\t\taddRandomValue( randomState, volume );\n\t\tGetDefaultOutputVolume( &volume );\n\t\taddRandomValue( randomState, volume );\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\taddRandomValue( randomState, ApplicationZone() );\n\t\taddRandomValue( randomState, SystemZone() );\n#endif\n\t\taddRandomValue( randomState, CountTypes() );\n/*\t\tCountVoices( &count ); ** seems to crash\n\t\taddRandomValue( randomState, count ); */\n\t\taddRandomValue( randomState, CurResFile() );\n\t\tGetSysBeepVolume( &lcount );\n\t\taddRandomValue( randomState, lcount );\n\t\taddRandomValue( randomState, GetSysDirection() );\n/*\t\taddRandomValue( randomState, GetSCSIDiskModeAddress() );\n\t\taddRandomValue( randomState, GetDimmingTimeout() );\n\t\taddRandomValue( randomState, GetSleepTimeout() ); */\n\t\tGetFreeThreadCount( kCooperativeThread, &count );\n\t\taddRandomValue( randomState, count );\n/*\t\taddRandomValue( randomState, IsSpindownDisabled() ); */\n\t\taddRandomValue( randomState, GetIntlResource( 0 ) );\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tGetTimeout( &count );\n\t\taddRandomValue( randomState, count );\n#endif\n\n\t\t/* Get the number of documents/files which were selected when the app\n\t\t   started and for each document get the vRefNum, name, type, and\n\t\t   version -- OBSOLETE\n\t\tSInt16 dummy;\n\n\t\tCountAppFiles( &dummy, &count );\n\t\taddRandomValue( randomState, count );\n\t\twhile( count > 0 )\n\t\t\t{\n\t\t\tAppFile theFile;\n\t\t\tGetAppFiles( count, &theFile );\n\t\t\taddRandomData( randomState, &theFile, sizeof( AppFile ) );\n\t\t\tcount--;\n\t\t\t} */\n\n\t\t/* Get the app's name, resource file reference number, and handle to\n\t\t   the finder information -- OBSOLETE\n\t\tStr255 appName;\n\t\tHandle appHandle;\n\t\t\n\t\tGetAppParams( appName, appHandle, &count );\n\t\taddRandomData( randomState, appName, sizeof( Str255 ) );\n\t\taddRandomValue( randomState, appHandle );\n\t\taddRandomValue( randomState, count ); */\n\n\t\t/* Get all sorts of statistics such as physical information, disk and\n\t\t   write-protect present status, error status, and handler queue\n\t\t   information, on floppy drives attached to the system.  Also get\n\t\t   the volume name, volume reference number and number of bytes free,\n\t\t   for the volume in the drive */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( !DriveStatus( 1, &driveStatus ) )\n\t\t\taddRandomData( randomState, &driveStatus, sizeof (DrvSts) );\n#endif\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( !GetVInfo( 1, volName, &vRefNum, &lcount ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, volName, sizeof( Str255 ) );\n\t\t\taddRandomValue( randomState, vRefNum );\n\t\t\taddRandomValue( randomState, lcount );\n\t\t\t}\n#endif\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( !DriveStatus( 2, &driveStatus ) )\n\t\t\taddRandomData( randomState, &driveStatus, sizeof (DrvSts) );\n#endif\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( !GetVInfo( 2, volName, &vRefNum, &lcount ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, volName, sizeof( Str255 ) );\n\t\t\taddRandomValue( randomState, vRefNum );\n\t\t\taddRandomValue( randomState, lcount );\n\t\t\t}\n#endif\n\t\t/* Get information on the head and tail of the vertical retrace\n\t\t   queue */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( ( vblQueue = GetVBLQHdr() ) != NULL )\n\t\t\taddRandomData( randomState, vblQueue, sizeof( QHdr ) );\n#endif\n\t\t/* Get the parameter RAM settings */\n\t\tpramPtr = GetSysPPtr();\n\t\taddRandomData( randomState, pramPtr, sizeof( SysParmType ) );\n\n\t\t/* Get information about the machines geographic location */\n\t\tReadLocation( &machineLocation );\n\t\taddRandomData( randomState, &machineLocation,\n\t\t\t\t\t   sizeof( MachineLocation ) );\n\n\t\t/* Get information on current graphics devices including device\n\t\t   information such as dimensions and cursor information, and a\n\t\t   number of handles to device-related data blocks and functions, and\n\t\t   information about the dimentions and contents of the devices pixel\n\t\t   image as well as the images resolution, storage format, depth, and\n\t\t   colour usage */\n\t\tdeviceHandle = GetDeviceList();\n\t\tdo\n\t\t\t{\n\t\t\tGDPtr gdPtr;\n\n\t\t\taddRandomValue( randomState, deviceHandle );\n\t\t\tHLock( ( Handle ) deviceHandle );\n\t\t\tgdPtr = ( GDPtr ) *deviceHandle;\n\t\t\taddRandomData( randomState, gdPtr, sizeof( GDevice ) );\n\t\t\taddRandomData( randomState, gdPtr->gdPMap, sizeof( PixMap ) );\n\t\t\tHUnlock( ( Handle ) deviceHandle );\n\t\t\t}\n\t\twhile( ( deviceHandle = GetNextDevice( deviceHandle ) ) != NULL );\n\n\t\t/* Get the current system environment, including the machine and\n\t\t   system software type, the keyboard type, where there's a colour\n\t\t   display attached, the AppleTalk driver version, and the VRefNum of\n\t\t   the system folder */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tSysEnvirons( curSysEnvVers, &sysEnvirons );\n\t\taddRandomData( randomState, &sysEnvirons, sizeof( SysEnvRec ) );\n#endif\n\n\t\t/* Get the AppleTalk node ID and network number for this machine */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( GetNodeAddress( &node, &net ) )\n\t\t\t{\n\t\t\taddRandomValue( randomState, node );\n\t\t\taddRandomValue( randomState, net );\n\t\t\t}\n#endif\n\t\t/* Get information on each device connected to the ADB including the\n\t\t   device handler ID, the devices ADB address, and the address of the\n\t\t   devices handler and storage area */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tcount = CountADBs();\n\t\twhile( count-- > 0 )\n\t\t\t{\n\t\t\tADBDataBlock adbInfo;\n\n\t\t\tGetIndADB( &adbInfo, count );\n\t\t\taddRandomData( randomState, &adbInfo, sizeof( ADBDataBlock ) );\n\t\t\t}\n#endif\n\t\t/* Open the most common device types and get the general device\n\t\t   status information and (if possible) device-specific status.  The\n\t\t   general device information contains the device handle and flags,\n\t\t   I/O queue information, event information, and other driver-related\n\t\t   details */\n\n/* Try something like this again.. and ur a dead man, Peter ;-)\n      -xmath */\n\n/*\t\tfor( count = 0; driverNames[ count ] != NULL; count++ )\n\t\t\t{\n\t\t\tAuxDCEHandle dceHandle;\n\t\t\tshort driverRefNum;\n\n\t\t\t** Try and open the driver **\n\t\t\tif( OpenDriver( driverNames[ count ], &driverRefNum ) )\n\t\t\t\tcontinue;\n\n\t\t\t** Get a handle to the driver control information (this could\n\t\t\t   also be done with GetDCtlHandle()) **\n\t\t\tStatus( driverRefNum, 1, &dceHandle );\n\t\t\tHLock( dceHandle );\n\t\t\taddRandomData( randomState, *dceHandle,\n\t\t\t\t\t\t\t sizeof( AuxDCE ) );\n\t\t\tHUnlock( dceHandle );\n\t\t\tCloseDriver( driverRefNum );\n\t\t\t} */\n\n\t\t/* Get the name and volume reference number for the current volume */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tGetVol( volName, &vRefNum );\n\t\taddRandomData( randomState, volName, sizeof( Str255 ) );\n\t\taddRandomValue( randomState, vRefNum );\n#endif\n\t\t/* Get the time information, attributes, directory information and\n\t\t   bitmap, volume allocation information, volume and drive\n\t\t   information, pointers to various pieces of volume-related\n\t\t   information, and details on path and directory caches, for each\n\t\t   volume */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( ( queueHdr = GetVCBQHdr() ) != NULL )\n\t\t\tqueuePtr = queueHdr->qHead;\n\t\t\twhile ( queuePtr != NULL )\n\t\t\t\t{\n\t\t\t\taddRandomData( randomState, queuePtr, sizeof( VCB ) );\n\t\t\t\tqueuePtr = queuePtr->qLink;\n\t\t\t\t}\n#endif\n\n\t\t/* Get the driver reference number, FS type, and media size for each\n\t\t   drive */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tif( ( queueHdr = GetDrvQHdr() ) != NULL )\n\t\t\tqueuePtr = queueHdr->qHead;\n\t\t\twhile ( queuePtr != NULL )\n\t\t\t\t{\n\t\t\t\taddRandomData( randomState, queuePtr, sizeof( DrvQEl ) );\n\t\t\t\tqueuePtr = queuePtr->qLink;\n\t\t\t\t}\n#endif\n\t\t/* Get global script manager variables and vectors, including the\n\t\t   globals changed count, font, script, and i18n flags, various\n\t\t   script types, and cache information */\n\t\tfor( count = 0; count < 30; count++ )\n\t\t\taddRandomValue( randomState, GetScriptManagerVariable( count ) );\n\n\t\t/* Get the script code for the font script the i18n script, and for\n\t\t   each one add the changed count, font, script, i18n, and display\n\t\t   flags, resource ID's, and script file information */\n\t\tscript = FontScript();\n\t\taddRandomValue( randomState, script );\n\t\tfor( count = 0; count < 30; count++ )\n\t\t\taddRandomValue( randomState, GetScriptVariable( script, count ) );\n\t\tscript = IntlScript();\n\t\taddRandomValue( randomState, script );\n\t\tfor( count = 0; count < 30; count++ )\n\t\t\taddRandomValue( randomState, GetScriptVariable( script, count ) );\n\n\t\t/* Get the device ID, partition, slot number, resource ID, and driver\n\t\t   reference number for the default startup device */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tGetDefaultStartup( &startupInfo );\n\t\taddRandomData( randomState, &startupInfo, sizeof( DefStartRec ) );\n#endif\n\t\t/* Get the slot number and resource ID for the default video device */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tGetVideoDefault( &videoInfo );\n\t\taddRandomData( randomState, &videoInfo, sizeof( DefVideoRec ) );\n#endif\n\t\t/* Get the default OS type */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tGetOSDefault( &osInfo );\n\t\taddRandomData( randomState, &osInfo, sizeof( DefOSRec ) );\n#endif\n\t\t/* Get the AppleTalk command block and data size and number of\n\t\t   sessions */\n#if !defined CALL_NOT_IN_CARBON || CALL_NOT_IN_CARBON\n\t\tASPGetParms( &appleTalkParams, FALSE );\n\t\taddRandomData( randomState, &appleTalkParams,\n\t\t\t\t\t   sizeof( XPPParamBlock ) );\n#endif\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 100 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/mgos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMongoose OS Randomness-Gathering Code\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an external source.  In its\n   current form it does not provide any usable entropy and should not be\n   used as an entropy source */\n\n/* General includes */\n\n#include <mgos.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tstruct mgos_uart_stats *uartStats;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\taddRandomLong( randomState, mgos_uptime() );\n\taddRandomLong( randomState, mgos_get_free_heap_size() );\n\taddRandomLong( randomState, mgos_get_fs_memory_usage() );\n\taddRandomLong( randomState, mgos_wifi_sta_get_rssi() );\n\taddRandomLong( randomState, mgos_mqtt_num_unsent_bytes() );\n\taddRandomLong( randomState, mgos_uart_read_avail() );\n\taddRandomLong( randomState, mgos_uart_write_avail() );\n\tif( ( uartStats = mgos_uart_get_stats() ) != NULL )\n\t\taddRandomData( randomState, uartStats, sizeof( uartStats ) );\n\tendRandomData( randomState, 2 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tconst char *strPtr;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\taddRandomLong( randomState, mgos_get_free_fs_size() );\n\taddRandomLong( randomState, mgos_get_cpu_freq() );\n\taddRandomLong( randomState, mgos_wifi_get_status() );\n\tif( ( strPtr = mgos_wifi_get_connected_ssid() ) != NULL )\n\t\t{\n\t\taddRandomData( randomState, strPtr, strlen( strPtr ) );\n\t\tfree( strPtr );\n\t\t}\n\tif( ( strPtr = mgos_wifi_get_sta_default_dns() ) != NULL )\n\t\t{\n\t\taddRandomData( randomState, strPtr, strlen( strPtr ) );\n\t\tfree( strPtr );\n\t\t}\n\tendRandomData( randomState, 5 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/mqx.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMQX Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#ifdef __IAR_SYSTEMS_ICC__ \n  #include <time.h>\t\t\t/* IAR and MQX time definitions conflict */\n#endif /* IAR compiler */\n#include <mqx.h>\n#undef FALSE\t\t\t\t/* MQX has its own broken definition */\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Add the number of elapsed hardware ticks and the number of \n\t   microseconds and nanoseconds since the last interrupt */\n\taddRandomLong( randomState, _time_get_hwticks() );\n\taddRandomLong( randomState, _time_get_microseconds() );\n\taddRandomLong( randomState, _time_get_nanoseconds() );\n\tendRandomData( randomState, 10 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\tfastPoll();\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Add some sort of supposedly unique number, possibly a CPUID, the\n\t   task ID of the system task, available scheduling priorities, the\n\t   current task's creator, the task error code, ID, and creation\n\t   parameter */\n\taddRandomLong( randomState, _mqx_get_counter() );\n\taddRandomLong( randomState, _mqx_get_system_task_id() );\n\taddRandomLong( randomState, _sched_get_max_priority( 0 ) );\n\taddRandomLong( randomState, _sched_get_min_priority( 0 ) );\n\taddRandomLong( randomState, _task_get_creator() );\n\taddRandomLong( randomState, _task_get_error() );\n\taddRandomLong( randomState, _task_get_id() );\n\taddRandomLong( randomState, _task_get_parameter() );\n\tendRandomData( randomState, 5 );\n\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/mvs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tMVS Randomness-Gathering Code\t\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1999-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#define _OPEN_SYS\t\t1\n#define _OPEN_SYS_EXT\t1\n#include <sys/ps.h>\n#include <sys/times.h>\n#include <sys/resource.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* Define the MVS assembler module used to gather random data */\n\n#pragma linkage( MVSENT, OS )\n#pragma map( readRandom, \"MVSENT\" )\nint readRandom( int length, unsigned char *buffer );\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t512\n\n/* Slow and fast polling routines.  There really isn't much that we can\n   get under MVS, and we have to be careful how much we do with readRandom()\n   since it can become quite resource-intensive on some systems (where\n   \"resource-intensive\" means \"bring down a parallel sysplex in its earlier\n   form before additional safeguards were added\") so we can't call it from \n   fastPoll() and only get a small amount of data with a slow poll */\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\threport_t heapReport;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* There really isn't much available under MVS, it would be nice if we\n\t   could get output from DISPLAY but this requires a level of plumbing\n\t   that isn't easily managed from C */\n\taddRandomLong( randomState, clock() );\n\tif( __heaprpt( &heapReport ) != -1 )\n\t\taddRandomData( randomState, &heapReport, sizeof( hreport_t ) );\n\n\tendRandomData( randomState, 2 );\n\t}\n\nstatic void getProcInfo( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tW_PSPROC wProcInfo;\n\tint token, entryCount;\n\n\t/* Initialise the W_PSPROC structure.  This requires dynamically-\n\t   allocated internal fields set up by the caller, so we have to go \n\t   through a complex malloc() dance to allocate them all */\n\tmemset( &wProcInfo, 0, sizeof( W_PSPROC ) );\n\twProcInfo.ps_conttylen = PS_CONTTYBLEN;\n\tif( ( wProcInfo.ps_conttyptr = malloc( wProcInfo.ps_conttylen ) ) == NULL )\n\t\treturn;\n\twProcInfo.ps_pathlen = PS_PATHBLEN;\n\tif( ( wProcInfo.ps_pathptr = malloc( wProcInfo.ps_pathlen ) ) == NULL )\n\t\t{\n\t\tfree( wProcInfo.ps_conttyptr );\n\t\treturn;\n\t\t}\n\twProcInfo.ps_cmdlen = PS_CMDBLEN_LONG;\n\tif( ( wProcInfo.ps_cmdptr = malloc( wProcInfo.ps_cmdlen ) ) == NULL )\n\t\t{\n\t\tfree( wProcInfo.ps_conttyptr );\n\t\tfree( wProcInfo.ps_pathptr );\n\t\treturn;\n\t\t}\n\n\t/* Walk through the process table getting information on each process */\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n    token = w_getpsent( 0, &wProcInfo, sizeof( W_PSPROC ) );\n\tfor( entryCount = 0; token > 0 && entryCount < 256; entryCount++ )\n\t\t{\n\t\taddRandomData( randomState, &wProcInfo, sizeof( W_PSPROC ) );\n\t    token = w_getpsent( token, &wProcInfo, sizeof( W_PSPROC ) );\n\t\t}\n\tendRandomData( randomState, min( entryCount, 45 ) );\n\n\t/* Clean up */\n\tfree( wProcInfo.ps_conttyptr );\n\tfree( wProcInfo.ps_pathptr );\n\tfree( wProcInfo.ps_cmdptr );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tMESSAGE_DATA msgData;\n\tstruct _Optn *sysOptions;\n\tBYTE buffer[ RANDOM_BUFSIZE ], cpuidBuffer[ 16 ];\n\tint quality = 95, status;\n\n\t/* Get static system information.  The system options are a catalogue of\n\t   about two hundred configuration options and settings for the current\n\t   system */\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\t__get_cpuid( cpuidBuffer );\n\taddRandomData( randomState, cpuidBuffer, 11 );\n\tendRandomData( randomState, 2 );\n\tsysOptions = __get_system_settings();\n\tif( sysOptions != NULL )\n\t\t{\n\t\tstatic const int optionsQuality = 10;\n\n\t\tsetMessageData( &msgData, sysOptions, sizeof( struct _Optn ) );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t ( MESSAGE_CAST ) &optionsQuality, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\t}\n\n\t/* Get information on all processes in the system */\n\tgetProcInfo();\n\n\t/* Get entropy from the low-level polling code in mvsent.s */\n\tstatus = readRandom( RANDOM_BUFSIZE, buffer );\n\tif( status != 0 )\n\t\t{\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\tsetMessageData( &msgData, buffer, RANDOM_BUFSIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t &quality, CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t}\n\tzeroise( buffer, sizeof( buffer ) );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/mvsent.s",
    "content": "**********************************************************************\n*\n* DESCRIPTION\n* -----------\n*   THIS MODULE GATHERS DATA TO PROVIDE ENTROPY FOR THE CRYPTLIB\n*   RNDMVS.C MODULE.\n*\n*   ENTROPY IS GATHERED BY OBTAINING THE TOD VALUE INTERMIXED WITH\n*   TASKS THAT PASS CONTROL BACK TO MVS TO PROCESS.  ENTROPY IS\n*   INTRODUCED FROM THE FACT THAT THE AMOUNT OF TIME MVS TAKES TO\n*   PROCESS THE REQUESTS IS UNKNOWN AND DEPENDENT ON FACTORS NOT IN\n*   OUR CONTROL.\n*\n*   NEWER VERSIONS OF THE ARCHITECTURE PROVIDE THE PPNO-SHA-512-DRNG,\n*   BUT THIS IS MERELY THE NIST DETERMINISTIC HASH-BASED GENERTOR,\n*   AND PROVIDES NO ENTROPY.  SINCE WE ALREADY HAVE A DETERMINISTIC\n*   GENERATOR PRESENT, THERE'S NO POINT TO USING PPNO-SHA-512-DRNG.\n*\n* INPUT\n* -----\n*   R1 = PARM ADDRESS\n*        +0 = LENGTH OF INPUT BUFFER.  MUST BE IN THE RANGE OF 1 TO\n*             2,000,000\n*        +4 = ADDRESS OF BUFFER TO PLACE THE RANDOM DATA.\n*\n* OUTPUT\n* ------\n*   R15 = RETURN CODE\n*         0 = SUCCESSFUL\n*         1 = PARAMETER LIST ERROR\n*         2 = O/S MACRO ERROR\n*\n* ENVIRONMENT\n* -----------\n*   ENVIRONMENT:       LANGUAGE ENVIRONMENT\n*   AUTHORIZATION:     PROBLEM STATE\n*   CROSS MEMORY MODE: PASN=HASN=SASN\n*   AMODE:             31\n*   RMODE:             31\n*   INTERUPT STATUS:   EXTERNAL INTERUPTS\n*   LOCKS:             NONE\n*\n**********************************************************************\nMVSENT   CEEENTRY MAIN=NO,AUTO=LDSSZ\n         USING LDS,CEEDSA\n**********************************************************************\n*\n* LOAD INPUT PARAMETERS.\n*\n**********************************************************************\n         L     R3,0(,R1)               LOAD LENGTH\n         LTR   R3,R3                   ZERO?\n         BNH   EXIT01                  YES\n         C     R3,=F'2000000'          MORE THAN MAX BYTES ?\n         BH    EXIT01                  YES, IS ERROR\n         ST    R3,BUFLEN               SAVE BUFFER LENGTH\n*\n         ICM   R3,B'1111',4(R1)        LOAD ADR OF BUFFER\n         BZ    EXIT01                  IMPROPER PARAMETER LIST\n         ST    R3,BUFADR               SAVE BUFFER ADDRESS\n**********************************************************************\n*\n* MAIN FUNCTION.\n*\n* OBTAIN THE TOD VALUE INTERMIXED WITH TASKS THAT PASS CONTROL\n* BACK TO MVS TO PROCESS.  ENTROPY IS INTRODUCED FROM THE FACT THAT\n* THE AMOUNT OF TIME MVS TAKES TO PROCESS THE REQUESTS IS UNKNOWN\n* AND DEPENDENT ON FACTORS NOT IN OUR CONTROL.\n**********************************************************************\n*\n* EACH LOOP GATHERS 8 BYTES OF DATA.\n*\nENLOOP   DS    0H\n         LA    R2,WBUF                 LOAD ADR OF WORKING BUFFER\n*\n         MVC   PLIST(#ATTACH),$ATTACH  INIT PARM LIST\n         LA    R4,0                    LOAD NULL\n         ST    R4,STECB                ZERO ECB\n         LA    R4,STECB                LOAD A(ECB)\n         ATTACH ECB=(R4),                                              +\n               SF=(E,PLIST)\n         LTR   R15,R15                 SUCCESSFUL?\n         BNZ   EXIT02                  FAILED\n         ST    R1,STTCB                SAVE ADR OF TCB\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         WAIT  ECB=(R4)                WAIT FOR TASK TO COMPLETE\n         LA    R4,STTCB                LOAD A TCB\n         DETACH (R4)                   DETACK TASK\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         GETMAIN RC,LV=50000,LOC=(31,31)\n         LTR   R15,R15                 SUCCESSFUL?\n         BNZ   EXIT02                  NO, EXIT\n         LR    R4,R1\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         MVC   PLIST(#GQSCAN),$GQSCAN  INIT PARM LIST\n         GQSCAN AREA=((R4),50000),                                     +\n               MF=(E,PLIST)\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         FREEMAIN RU,LV=50000,A=(R4)\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         LOAD  EP=A@#$#@Z,ERRET=NOTFND\nNOTFND   DS    0H\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         MVC   PLIST(#ENQ),$ENQ        INIT PARM LIST\n         ENQ   MF=(E,PLIST)\n         MVC   PLIST(#DEQ),$DEQ        INIT PARM LIST\n         DEQ   MF=(E,PLIST)\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n         MVC   PLIST(#STIMERM),$STIMERM INIT PARM LIST\n         LA    R4,TIMERID              LOAD ADR OF TIME ID FIELD\n         XC    TIMEECB,TIMEECB         CLEAR ECB\n         LA    R1,TIMEECB\n         ST    R1,TIMEECB@             SAVE ADR ECB PARM\n         STIMERM SET,                                                  +\n               WAIT=NO,                                                +\n               EXIT=TIMEEXIT,                                          +\n               PARM=TIMEECB@,                                          +\n               TUINTVL=WAITTIME,                                       +\n               ID=(R4),                                                +\n               MF=(E,PLIST)\n         LTR   R15,R15                 SUCCESSFUL?\n         BNZ   EXIT02                  NO, EXIT\n         LA    R4,TIMEECB              LOAD ADR OF ECB\n         WAIT  ECB=(R4)                WAIT FOR TIMER TO COMPLETE\n*\n         STCK  TOD                     OBTAIN TOD VALUE\n         MVC   0(1,R2),TODB7           SAVE BYTE 7\n         LA    R2,1(,R2)               INCR ADR\n*\n*        COPY THE DATA TO THE USER BUFFER.\n*\n         LA    R1,WBUF                 LOAD ADR OF BUFFER\n         SR    R2,R1                   CALC LEN OF DATA\n         L     R3,BUFLEN               LOAD REMAINING BUF LEN\n         CR    R2,R3                   HOW MUCH ROOM LEFT?\n         BL    COPYDATA                ITS ENOUGH ROOM\n         LR    R2,R3                   SET LEN TO REMAINING ROOM\n*\nCOPYDATA DS    0H\n         L     R4,BUFADR               LOAD ADR OF CALLER'S BUF\n         LR    R5,R2                   LOAD LEN OF DATA\n         LA    R6,WBUF                 LOAD ADR OF DATA\n         LR    R7,R5                   LOAD LEN OF DATA\n         MVCL  R4,R6\n*\n         ST    R4,BUFADR               SAVE OFFSET INTO BUF\n         L     R3,BUFLEN               LOAD REMAINING LEN OF BUF\n         SR    R3,R2                   CALC NEW REMAINING LEN\n         ST    R3,BUFLEN               SAVE NEW REMAINING LEN\n*\n         LTR   R3,R3                   END OF BUF\n         BH    ENLOOP                  NO, CONTINUE\n*\n         B     EXIT00                  EXIT\n*\n**********************************************************************\n*\n* RETURN TO CALLER.\n*\n**********************************************************************\nEXIT01   DS    0H\n         LA    R15,1\n         B     EXIT\nEXIT02   DS    0H\n         LA    R15,2\n         B     EXIT\nEXIT00   DS    0H\n         LA    R15,0\nEXIT     DS    0H\n         CEETERM RC=(R15)\n**********************************************************************\n*\n*  CONSTANTS\n*\n**********************************************************************\nPPA      CEEPPA ,\n*\nWAITTIME DC    F'2'                         ~(2*26) MICROSECONDS\nQNAME    DC    C'CRYPTLIB'                  ENQ QNAME\nRNAME    DC    C'RANDOM'                    ENQ RNAME\n*\n$ATTACH  ATTACH EP=IEFBR14,                                            +\n               DPMOD=-255,                                             +\n               SF=L\n#ATTACH  EQU   *-$ATTACH\n*\n$GQSCAN  GQSCAN SCOPE=ALL,                                             +\n               XSYS=YES,                                               +\n               MF=L\n#GQSCAN  EQU   *-$GQSCAN\n*\n$ENQ     ENQ   (QNAME,RNAME,S,,SYSTEMS),MF=L\n#ENQ     EQU   *-$ENQ\n*\n$DEQ     DEQ   (QNAME,RNAME,,SYSTEMS),MF=L\n#DEQ     EQU   *-$ENQ\n*\n$STIMERM STIMERM SET,MF=L\n#STIMERM EQU   *-$STIMERM\n*\n         LTORG ,\n         YREGS ,\n*\n**********************************************************************\n*\n*  STIMERM ASYNC EXIT\n*\n**********************************************************************\n         DROP\nTIMEEXIT DS    0H\n         USING TIMEEXIT,R15\n         L     R2,4(,R1)               LOAD ADR OF ECB\n         POST  (R2)                    POST ECB\n         BR    R14                     RETURN TO CALLER\n         DROP  R15\n*\n**********************************************************************\n*\n*  DYNAMIC STORAGE AREA\n*\n**********************************************************************\nLDS      DSECT ,\n         DS    XL(CEEDSASZ)                 DSA STORAGE\n*\nBUFADR   DS    A                            CALLER'S BUFFER ADR\nBUFLEN   DS    H                            CALLER'S BUFFER LEN\n*\nTOD      DS    0D                           TIME-OF-DAY VALUE\nTODB1    DS    B\nTODB2    DS    B\nTODB3    DS    B\nTODB4    DS    B\nTODB5    DS    B\nTODB6    DS    B\nTODB7    DS    B\nTODB8    DS    B\n*\nSTECB    DS    F                            SUBTASK ECB\nSTTCB    DS    A                            SUBTASK ADR\nTIMERID  DS    F                            STIMERM TIMER ID\nTIMEECB  DS    F                            STIMERM ECB\nTIMEECB@ DS    A                            ADR OF STIMERM ECB\nPLIST    DS    XL256                        GENERAL PARM LIST\nWBUF     DS    CL100                        WORKING BUFFER\n*\n         DS    0D                           END LDS ON DOUBLE WORD\nLDSSZ    EQU   *-LDS\n*\n**********************************************************************\n*\n*  MAPPING DSECTS\n*\n**********************************************************************\n         CEECAA ,                      LE COMMON ANCHOR AREA\n         CEEDSA ,                      LE DYNAMIC STORAGE AREA\n*\n         END    MVSENT\n"
  },
  {
    "path": "deps/cl345/random/os2.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOS/2 Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\tCopyright Peter Gutmann and Stuart Woolford 1996-2001\t\t\t*\n*\t\t\t\t\t\t\tUpdated by Mario Korva 1998\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include \"crypt.h\"\n\n#define INCL_DOSMISC\n#define INCL_DOSDATETIME\n#define INCL_DOSPROCESS\n#define INCL_WINWINDOWMGR\n#define INCL_WINSYS\n#include <os2.h>\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n\n/* DosQProcStatus() = DOSCALLS.154 */\n\n#if defined(__32BIT__)\n  #define PTR(ptr, ofs)  ((void *) ((char *) (ptr) + (ofs)))\n#else\n  #define DosQueryModuleName DosGetModName\n  #define APIENTRY16 APIENTRY\n  #if defined(M_I86SM) || defined(M_I86MM)\n    #define PTR(ptr, ofs)  ((void *) ((char *) (ptr) + (ofs)))\n  #else\n    #define PTR(ptr, ofs)  ((void *) ((char *) (((ULONG) procstat & 0xFFFF0000) | (USHORT) (ptr)) + (ofs)))\n    /* kludge to transform 0:32 into 16:16 pointer in this special case */\n  #endif\n#endif\n\n#ifdef __EMX__\n\nUSHORT _THUNK_FUNCTION(DosQProcStatus) (PVOID pBuf, USHORT cbBuf);\nUSHORT _THUNK_FUNCTION(DosGetPrty) (USHORT usScope, PUSHORT pusPriority, USHORT pid);\n\nUSHORT _DosQProcStatus(PVOID pBuf, USHORT cbBuf)\n{\n  _THUNK_PROLOG(4+2);\n  _THUNK_FAR16(_emx_32to16(pBuf));       /* PVOID  pBuf  = 4 bytes */\n  _THUNK_SHORT(cbBuf);                   /* USHORT cbBuf = 2 bytes */\n  return (USHORT) _THUNK_CALL(DosQProcStatus);\n}\n\n#define DosQProcStatus _DosQProcStatus\n\n#else\n\nUSHORT APIENTRY16 DosQProcStatus(PVOID pBuf, USHORT cbBuf);\n\n#endif\n\n/* DosQProcStatus()\n   Query Process Status Info API used by PSTAT system utility.\n   To use this undocumented function add following to DEF file:\nIMPORTS\n  DOSQPROCSTATUS = DOSCALLS.154\n\n\n   The DosQProcStatus API is a 16 bit API that returns information that\n   summarizes the system resources that are in use of an OS/2 2.0 system.\n   DosQProcStatus reports on the following classes of OS/2 2.0 system resources:\n\n   Processes and Threads\n   Dynamic Link Library Modules\n   16 bit System Semaphores\n   Named Shared Memory Segments\n\n   DosQProcStatus returns a buffer that is filled with a series of sections\n   of resource information:\n\n   1. Pointer section\n   2. Global data section\n   3. Section with Process and Thread records - one Process record for each process\n      immediately followed by a set of Thread records - one Thread record for each\n      thread within the process\n   4. Section consisting of 16 Bit System Semaphore records\n   5. Section consisting of Executable Module records\n   6. Section consisting of Shared Memory Segment records\n\n   Definition of system records returned by DosQProcStatus()\n   from IBM document entitled:\n\n   DosQProcStatus API for IBM OS/2 Version 2.0\n   May 11, 1992 */\n\ntypedef struct qsGrec_s {             /* Global record */\n        ULONG         cThrds;         /* number of threads in use */\n        ULONG         Reserved1;\n        ULONG         Reserved2;\n}qsGrec_t;\n\ntypedef struct qsTrec_s {             /* Thread record */\n        ULONG         RecType;        /* Record Type */\n                                      /* Thread rectype = 100 */\n        USHORT        tid;            /* thread ID */\n        USHORT        slot;           /* \"unique\" thread slot number */\n        ULONG         sleepid;        /* sleep id thread is sleeping on */\n        ULONG         priority;       /* thread priority */\n        ULONG         systime;        /* thread system time */\n        ULONG         usertime;       /* thread user time */\n        UCHAR         state;          /* thread state */\n        UCHAR         padchar;        /* ? */\n        USHORT        padshort;       /* ? */\n} qsTrec_t;\n\ntypedef struct qsPrec_s {             /* Process record */\n        ULONG         RecType;        /* type of record being processed */\n                                      /* process rectype = 1            */\n        qsTrec_t  FAR *pThrdRec;      /* ptr to 1st thread rec for this prc*/\n        USHORT        pid;            /* process ID */\n        USHORT        ppid;           /* parent process ID */\n        ULONG         type;           /* process type */\n        ULONG         stat;           /* process status */\n        ULONG         sgid;           /* process screen group */\n        USHORT        hMte;           /* program module handle for process */\n        USHORT        cTCB;           /* # of TCBs in use in process */\n        ULONG         Reserved1;\n        void    FAR   *Reserved2;\n        USHORT        c16Sem;         /*# of 16 bit system sems in use by proc*/\n        USHORT        cLib;           /* number of runtime linked libraries */\n        USHORT        cShrMem;        /* number of shared memory handles */\n        USHORT        Reserved3;\n        USHORT  FAR   *p16SemRec;     /*ptr to head of 16 bit sem inf for proc*/\n        USHORT  FAR   *pLibRec;       /*ptr to list of runtime lib in use by  */\n                                      /*process*/\n        USHORT  FAR   *pShrMemRec;    /*ptr to list of shared mem handles in  */\n                                      /*use by process*/\n        USHORT  FAR   *Reserved4;\n} qsPrec_t;\n\ntypedef struct qsS16Headrec_s {       /* 16 Bit System Semaphore record */\n        ULONG         SRecType;       /* semaphore rectype = 3 */\n        ULONG         Reserved1;      /* overlays NextRec of 1st qsS16rec_t*/\n        ULONG         Reserved2;\n        ULONG         S16TblOff;      /* index of first semaphore,SEE PSTAT OUTPUT*/\n                                      /* System Semaphore Information Section     */\n} qsS16Headrec_t;\n\ntypedef struct qsMrec_s {             /* Shared Memory Segment record */\n        ULONG         MemNextRec;     /* offset to next record in buffer */\n        USHORT        hmem;           /* handle for shared memory */\n        USHORT        sel;            /* shared memory selector */\n        USHORT        refcnt;         /* reference count */\n        CHAR          Memname;        /* start of shared memory name string */\n} qsMrec_t;\n\ntypedef struct qsLrec_s {             /* Executable Module record */\n        void  FAR       *pNextRec;    /* pointer to next record in buffer */\n        USHORT        hmte;           /* handle for this mte */\n        USHORT        Reserved1;      /* Reserved */\n        ULONG         ctImpMod;       /* # of imported modules in table */\n        ULONG         Reserved2;      /* Reserved */\n        ULONG         Reserved3;      /* Reserved */\n        UCHAR     FAR *pName;         /* ptr to name string following stru */\n} qsLrec_t;\n\ntypedef struct qsPtrRec_s {             /* Pointer record */\n        qsGrec_t        *pGlobalRec;    /* ptr to the global data section   */\n        qsPrec_t        *pProcRec;      /* ptr to process record section    */\n        qsS16Headrec_t  *p16SemRec;     /* ptr to 16 bit sem section        */\n        qsMrec_t        *pShrMemRec;    /* ptr to shared mem section        */\n        qsLrec_t        *pLibRec;       /* ptr to exe module record section */\n} qsPtrRec_t;\n\nvoid fastPoll( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tDATETIME dt;\n\tULONG querybuffer[ 26 + 8 ];\n\tPTIB ptib = NULL;\n\tPPIB ppib = NULL;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get various (fairly constant) pieces of machine information and\n\t   timestamps, date and time, the thread information block and process\n\t   information block. The DosQuerySysInfo() call returns more or less\n\t   static information with a single 32-bit counter which is incremented\n\t   roughly every 31ms */\n\tDosQuerySysInfo( 1, 26, ( PVOID ) querybuffer, sizeof( querybuffer ) );\n\taddRandomData( randomState, querybuffer, sizeof( querybuffer ) );\n\tDosGetDateTime( &dt );\n\taddRandomData( randomState, &dt, sizeof( DATETIME ) );\n\n\t/* Process and Thread information */\n\tDosGetInfoBlocks( &ptib, &ppib );\n\taddRandom( randomState, ptib );\n\taddRandom( randomState, ppib );\n\taddRandomData( randomState, ptib, sizeof( TIB ) );  /* TIB */\n\taddRandomData( randomState, ppib, sizeof( PIB ) );  /* PIB */\n\taddRandomData( randomState, ptib->tib_ptib2, sizeof( TIB2 ) ); /* TIB2 */\n\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\t/* Command line and environment strings */\n\t\taddRandomData( randomState, ppib->pib_pchcmd,\n\t\t\t\t\t   strlen( ppib->pib_pchcmd ) );\n\t\taddRandomData( randomState, ppib->pib_pchenv,\n\t\t\t\t\t   strlen( ppib->pib_pchenv ) );\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* Running time information of all system threads */\n\t{\n    #define PTR(ptr, ofs)  ((void *) ((char *) (ptr) + (ofs)))\n    qsPtrRec_t *procstat;\n    qsPrec_t *proc;\n    qsTrec_t *thread;\n    USHORT rc,i;\n    UCHAR x;\n\n    /* Get information about system and user time of all threads.\n       This information is changing all the time.  */\n\n    procstat = malloc (0x8000); /* Large buffer for process information */\n    rc = DosQProcStatus ( (PVOID) procstat, 0x8000);    /* Query process info */\n    if (!rc) {\n        addRandom( randomState, procstat );\n        addRandomData( randomState, procstat, sizeof( qsPtrRec_t ) );\n    }\n    for ( proc = PTR( procstat->pProcRec, 0 );\n          proc -> RecType == 1;\n          proc = PTR( proc->pThrdRec, proc->cTCB * sizeof( qsTrec_t ) ) ) {\n        for ( i = 0, thread = PTR( proc->pThrdRec, 0 );\n              i < proc->cTCB;\n              i++, thread++ ) {\n            /* use low byte of (systime+usertime) */\n            x = (thread->systime + thread->usertime) & 0xFF;\n            /* but only if nonzero */\n            if( x )\n              addRandom( randomState, x );\n        }\n    }\n    free (procstat);\n\t}\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 10 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tHWND hwndParent;\n\tHWND hwndNext;\n\tHENUM henum;\n\tPID pib;\n\tTID tib;\n\tRECTL rcl;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Enumerate all PM windows */\n\thwndParent = HWND_DESKTOP;\n\thenum = WinBeginEnumWindows( hwndParent );\n\twhile( ( hwndNext = WinGetNextWindow( henum ) ) != NULLHANDLE )\n\t\t{\n\t\taddRandom( randomState, hwndNext );\n\n\t\tWinQueryWindowProcess( hwndNext, &pib, &tib );\n\t\taddRandomData( randomState, &tib, sizeof( TIB ) );\n\t\taddRandomData( randomState, &pib, sizeof( PIB ) );\n\t\tWinQueryWindowRect( hwndNext, &rcl );\n\t\taddRandomData( randomState, &rcl, sizeof( RECTL ) );\n\t\t}\n\tWinEndEnumWindows( henum );\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 50 );\n\t}\n\n/* Get current thread ID */\n\nULONG DosGetThreadID( void )\n\t{\n\tPTIB ptib = NULL;\n\tPPIB ppib = NULL;\n\n\t/* Process and Thread information */\n\tDosGetInfoBlocks( &ptib, &ppib );\n\treturn ppib->pib_ulpid;\n\t}\n"
  },
  {
    "path": "deps/cl345/random/osek.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  OSEK Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an external source.  In its\n   current form it does not provide any usable entropy and should not be\n   used as an entropy source */\n\n/* General includes */\n\n#include <os.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\n\t/* Get the core that we're currently running on */\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\taddRandomValue( randomState, GetCoreID() );\n\tendRandomData( randomState, 1 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tstatic BOOLEAN addedStaticData = FALSE;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get static system information */\n\tif( !addedStaticData )\n\t\t{\n\t\t/* The application ID is fixed at compile time, the current \n\t\t   application ID is almost always the same thing */ \n\t\taddRandomValue( randomState, GetApplicationID() );\n\t\taddRandomValue( randomState, GetCurrentApplicationID() );\n\t\taddRandomValue( randomState, GetNumberOfActivatedCores() );\n\n\t\taddedStaticData = TRUE;\n\t\t}\n\n\tendRandomData( randomState, 1 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/palmos.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPalmOS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2003-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include <sys/time.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <AppMgr.h>\n#include <Event.h>\n#include <FeatureMgr.h>\n#include <Font.h>\n#include <Form.h>\n#include <Menu.h>\n#include <MemoryMgr.h>\n#include <SystemMgr.h>\n#include <SysThread.h>\n#include <TimeMgr.h>\n#include <VFSMgr.h>\n#include <Window.h>\n\n/* The size of the intermediate buffer used to accumulate polled data.  We\n   make this somewhat smaller than the default 4K used for other entropy-\n   polling modules because the default PalmOS thread stack size is a\n   somewhat pathetic 4K, and we don't want to use all of it just on the\n   entropy buffer */\n\n#define RANDOM_BUFSIZE\t1024\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tWinHandle winHandle;\n\tCoord xCoord, yCoord;\n\tBoolean flag;\n\tuint64_t ticks;\n\tnsecs_t nsTime;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get the event-available and low-level event-available flag, current\n\t   pen status, and handle of the window with the input focus */\n\tflag = EvtEventAvail();\n\taddRandomValue( randomState, flag );\n\tflag = EvtSysEventAvail( TRUE );\n\taddRandomValue( randomState, flag );\n\tEvtGetPen( &xCoord, &yCoord, &flag );\n\taddRandomValue( randomState, xCoord );\n\taddRandomValue( randomState, yCoord );\n\twinHandle = EvtGetFocusWindow();\n\taddRandomValue( randomState, winHandle );\n\n\t/* Get the number of ticks of the (software) millisecond clock used\n\t   by the scheduler, and the length of time in nanoseconds since the\n\t   last reset */\n\tticks = TimGetTicks();\n\taddRandomData( randomState, &ticks, sizeof( uint64_t ) );\n\tnsTime = SysGetRunTime();\n\taddRandomData( randomState, &nsTime, sizeof( nsecs_t ) );\n\n\t/* Get the value of the real-time and runtime clocks in nanoseconds.\n\t   One of these may just be a wrapper for SysGetRunTime(), in addition\n\t   it's likely that they're hardware-specific, being CPU-level cycle\n\t   counters of some kind */\n\tnsTime = system_real_time();\n\taddRandomData( randomState, &nsTime, sizeof( nsecs_t ) );\n\tnsTime = system_time();\n\taddRandomData( randomState, &nsTime, sizeof( nsecs_t ) );\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 5 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tstruct batteryInfoType {\n\t\tuint16_t warnThreshold;\t\t/* Percent left for warn */\n\t\tuint16_t criticalThreshold;\t/* Percent left for critical warn */\n\t\tuint16_t shutdownThreshold;\t/* Percent left for shutdown */\n\t\tuint32_t timeout;\t\t\t/* Battery timeout */\n\t\tSysBatteryKind type;\t\t/* Battery type */\n\t\tBoolean pluggedIn;\t\t\t/* Whether battery plugged in */\n\t\tuint8_t powerLevel;\t\t\t/* Percent power remaining */\n\t\t} batteryInfo;\n\tconst FontType *fontPtr;\n\tMenuBarType *menuPtr;\n\tvoid *stackStart, *stackEnd;\n\tMemHeapInfoType memInfo;\n\tRectangleType rectangleInfo;\n\tEvtQueueHandle evtQueueHandle;\n\tDatabaseID databaseID;\n\tFontID fontID;\n\tWinHandle winHandle;\n\tWinFlagsType winFlags;\n\tPatternType pattern;\n\tuint32_t version;\n\tuint16_t formID;\n\tuint8_t value;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get the handle of the current thread's event queue, current resource\n\t   database ID, start and end of the current thread's stack, ID and\n\t   pointer to the current font, ID and pointer to the currently active\n\t   form, and pointer to the currently active menu */\n\tevtQueueHandle = EvtGetThreadEventQueue();\n\taddRandomValue( randomState, evtQueueHandle );\n\tSysCurAppDatabase( &databaseID );\n\taddRandomValue( randomState, databaseID );\n\tSysGetStackInfo( &stackStart, &stackEnd );\n\taddRandomData( randomState, &stackStart, sizeof( void * ) );\n\taddRandomData( randomState, &stackEnd, sizeof( void * ) );\n\tfontID = FntGetFont();\n\taddRandomValue( randomState, fontID );\n\tfontPtr = FntGetFontPtr();\n\taddRandomData( randomState, &fontPtr, sizeof( FontType * ) );\n\tformID = FrmGetActiveFormID();\n\taddRandomValue( randomState, formID );\n\tif( formID > 0 )\n\t\t{\n\t\tFormType *formPtr;\n\n\t\tformPtr = FrmGetFormPtr( formID );\n\t\taddRandomData( randomState, &formPtr, sizeof( FormType * ) );\n\t\t}\n\tmenuPtr = MenuGetActiveMenu();\n\taddRandomData( randomState, &menuPtr, sizeof( MenuBarType * ) );\n\n\t/* Get system memory info: heap base address, total memory, memory in\n\t   use, number of chunks allocated/free and chunk memory used/free,\n\t   available memory block info */\n\tMemDynHeapGetInfo( &memInfo );\n\taddRandomData( randomState, &memInfo, sizeof( MemHeapInfoType ) );\n\n\t/* Get the handle, creation flags, and size of the active window, the\n\t   screen window created at startup, and the current draw window, the\n\t   size and clipping rectangle of the draw window, the current pattern\n\t   type, and the current scaling mode */\n\twinHandle = WinGetActiveWindow();\n\taddRandomValue( randomState, winHandle );\n\twinFlags = WinGetWindowFlags( winHandle );\n\taddRandomValue( randomState, winFlags );\n\tWinGetWindowFrameRect( winHandle, &rectangleInfo );\n\taddRandomData( randomState, &rectangleInfo, sizeof( RectangleType ) );\n\twinHandle = WinGetDisplayWindow();\n\taddRandomValue( randomState, winHandle );\n\twinHandle = WinGetDrawWindow();\n\taddRandomValue( randomState, winHandle );\n\twinFlags = WinGetWindowFlags( winHandle );\n\taddRandomValue( randomState, winFlags );\n\tWinGetDrawWindowBounds( &rectangleInfo );\n\taddRandomData( randomState, &rectangleInfo, sizeof( RectangleType ) );\n\tWinGetClip( &rectangleInfo );\n\taddRandomData( randomState, &rectangleInfo, sizeof( RectangleType ) );\n\tpattern = WinGetPatternType();\n\taddRandomValue( randomState, pattern );\n\tif( FtrGet( sysFtrCreator, sysFtrNumWinVersion, &version ) == errNone && \\\n\t\tversion >= 5 )\n\t\t{\n\t\tuint32_t scaleType;\n\n\t\t/* Not implemented before PalmOS 5.3, requires the 1.5x Display\n\t\t   Feature Set to avoid generating a fatal alert */\n\t\tscaleType = WinGetScalingMode();\n\t\taddRandomValue( randomState, scaleType );\n\t\t}\n\n\t/* Get expansiode card info (capability flags, manufacturer, product,\n\t   and device info including unique serial number if available), and\n\t   media info (disk space, partition info, pseudo-HDD metrics) for all\n\t   expansion slots */\n\tif( FtrGet( sysFileCExpansionMgr,expFtrIDVersion, &version ) == errNone )\n\t\t{\n\t\tuint32_t slotIterator = expIteratorStart;\n\t\tuint16_t slotRefNum;\n\n\t\twhile( slotIterator != expIteratorStop && \\\n\t\t\t   ExpSlotEnumerate( &slotRefNum, &slotIterator ) == errNone )\n\t\t\t{\n\t\t\tExpCardInfoType cardInfo;\n\t\t\tCardMetricsType cardMetrics;\n\n\t\t\taddRandomValue( randomState, slotRefNum );\n\t\t\tExpCardInfo( slotRefNum, &cardInfo );\n\t\t\taddRandomData( randomState, &cardInfo, sizeof( ExpCardInfoType ) );\n\t\t\t\tExpCardMetrics( slotRefNum, &cardMetrics );\n\t\t\taddRandomData( randomState, &cardMetrics, sizeof( CardMetricsType ) );\n\t\t\t}\n\t\t}\n\n\t/* Get attributes, filesystem type, mount info, media type, space used,\n\t   and total space for all mounted volumes */\n\tif( FtrGet( sysFileCVFSMgr, vfsFtrIDVersion, &version ) == errNone )\n\t\t{\n\t\tuint32_t volIterator = vfsIteratorStart;\n\t\tuint16_t volRefNum;\n\n\t\twhile( volIterator != vfsIteratorStop && \\\n\t\t\t   VFSVolumeEnumerate( &volRefNum, &volIterator ) == errNone )\n\t\t\t{\n\t\t\tVolumeInfoType volInfo;\n\t\t\tuint32_t volUsed, volTotal;\n\n\t\t\taddRandomValue( randomState, volRefNum );\n\t\t\tVFSVolumeInfo( volRefNum, &volInfo );\n\t\t\taddRandomData( randomState, &volInfo, sizeof( VolumeInfoType ) );\n\t\t\tVFSVolumeSize( volRefNum, &volUsed, &volTotal );\n\t\t\taddRandomValue( randomState, volUsed );\n\t\t\taddRandomValue( randomState, volTotal );\n\t\t\t}\n\t\t}\n\n\t/* Get battery state info */\n\tif( SysBatteryInfo( FALSE, &batteryInfo.warnThreshold,\n\t\t\t\t\t\t&batteryInfo.criticalThreshold,\n\t\t\t\t\t\t&batteryInfo.shutdownThreshold,\n\t\t\t\t\t\t&batteryInfo.timeout, &batteryInfo.type,\n\t\t\t\t\t\t&batteryInfo.pluggedIn,\n\t\t\t\t\t\t&batteryInfo.powerLevel ) == errNone )\n\t\taddRandomData( randomState, &batteryInfo,\n\t\t\t\t\t   sizeof( struct batteryInfoType ) );\n\n\t/* Get the LCD brightness and contrast level */\n\tvalue = SysLCDBrightness( FALSE, 0 );\n\taddRandomValue( randomState, value );\n\tvalue = SysLCDContrast( FALSE, 0 );\n\taddRandomValue( randomState, value );\n\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\tstruct ftrInfoType {\n\t\t\tuint32_t creator;\t/* Feature creator */\n\t\t\tuint16_t number;\t/* Feature number */\n\t\t\tuint32_t value;\t\t/* Feature value */\n\t\t\t} ftrInfo;\n\t\tuint16_t ftrIterator, romTokenSize;\n\t\tuint8_t *romToken;\n\n\t\t/* Get system features.  This includes a large amount of\n\t\t   information ranging from fairly static (extensive hardware\n\t\t   capability info, OS version/configuration data) through to\n\t\t   variable (default font, locale, etc) */\n\t\tfor( ftrIterator = 0; \\\n\t\t\t FtrGetByIndex( ftrIterator, FALSE, &ftrInfo.creator, \\\n\t\t\t\t\t\t\t&ftrInfo.number, &ftrInfo.value ) == errNone; \\\n\t\t\t ftrIterator++ )\n\t\t\taddRandomData( randomState, &ftrInfo, sizeof( struct ftrInfoType ) );\n\n\t\t/* Get the ROM serial number.  This is somewhat complex, for it to\n\t\t   be valid the function call has to succeed and the returned\n\t\t   pointer has to be non-null and the first byte of the returned\n\t\t   data can't be 0xFF */\n\t\tif( SysGetROMToken( sysROMTokenSnum, &romToken, \\\n\t\t\t\t\t\t\t&romTokenSize ) == errNone && \\\n\t\t\tromToken != NULL && *romToken != 0xFF )\n\t\t\taddRandomData( randomState, &romToken, romTokenSize );\n\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 100 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/rand_x917.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib X9.17 Generator Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"random_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"random/random_int.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Sanity-check the X9.17 randomness state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckRandom( const RANDOM_INFO *randomInfo )\n\t{\n\tconst BYTE *keyDataPtr;\n\n\tassert( isReadPtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISSET( randomInfo->x917Key ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check that the keying data is aligned to the requirements of any \n\t   underlying hardware implementation */\n\tkeyDataPtr = DATAPTR_GET( randomInfo->x917Key );\n\tif( keyDataPtr != ptr_align( keyDataPtr, 16 ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: X.917 key alignment\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the X9.17 generator accounting information is within\n\t   bounds.  See the comment in generateX917() for the high-range check */\n\tif( randomInfo->x917Count < 0 || \\\n\t\trandomInfo->x917Count > X917_MAX_CYCLES + \\\n\t\t\t\t\t\t\t\t( MAX_RANDOM_BYTES / X917_POOLSIZE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: X9.17 count\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tANSI X9.17 Generator\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The ANSI X9.17 Annex C generator has a number of problems (besides just\n   being slow) including a tiny internal state, use of fixed keys, no\n   entropy update, revealing the internal state to an attacker whenever it\n   generates output, and a horrible vulnerability to state compromise.  For\n   FIPS 140 compliance however we need to use an approved generator (even\n   though Annex C is informative rather than normative and contains only \"an\n   example of a pseudorandom key and IV generator\" so that it could be argued\n   that any generator based on X9.17 3DES is permitted), which is why this\n   generator appears here.\n\n   In order to minimise the potential for damage we employ it as a post-\n   processor for the pool (since X9.17 produces a 1-1 mapping it can never\n   make the output any worse), using as our timestamp input the main RNG\n   output.  This is perfectly valid since X9.17 requires the use of DT, \"a\n   date/time vector which is updated on each key generation\", a requirement\n   which is met by the fastPoll() which is performed before the main pool is\n   mixed.  The cryptlib representation of the date and time vector is as a\n   hash of assorted incidental data and the date and time.  The fact that\n   99.9999% of the value of the generator is coming from the, uhh, timestamp\n   is as coincidental as the side effect of the engine cooling fan in the\n   Brabham ground effect cars.\n\n   Some eval labs may not like this use of DT, in which case it's also\n   possible to inject the extra seed material into the generator by using\n   the X9.31 interpretation of X9.17, which makes the V value an externally-\n   modifiable value.  In this interpretation the \"generator\" has degenerated \n   to little more than a 3DES encryption of V, which can hardly have been \n   the intent of the X9.17 designers.  In other words the X9.17 operation:\n\n\tout = Enc( Enc( in ) ^ V(n) );\n\tV(n+1) = Enc( Enc( in ) ^ out );\n\n   degenerates to:\n\n\tout = Enc( Enc( DT ) ^ in );\n\n   since V is overwritten on each iteration.  If the eval lab requires this\n   interpretation rather than the more sensible DT one then this can be\n   enabled by supplying a dateTime value to setKeyX917(), although we don't \n   do it by default since it's so far removed from the real X9.17 \n   generator */\n\n#ifdef USE_3DES_X917\n\n/* A macro to make what's being done by the generator easier to follow */\n\n#define rngEncrypt( data, key ) \\\n\t\tdes_ecb3_encrypt( ( C_Block * ) ( data ), ( C_Block * ) ( data ), \\\n\t\t\t\t\t\t  ( key )->desKey1, ( key )->desKey2, \\\n\t\t\t\t\t\t  ( key )->desKey3, DES_ENCRYPT )\n\n/* Set the X9.17 generator key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint setKeyX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\tIN_BUFFER_C( X917_KEYSIZE ) const BYTE *key,\n\t\t\t\tIN_BUFFER_C( X917_POOLSIZE ) const BYTE *state,\n\t\t\t\tIN_BUFFER_OPT_C( X917_POOLSIZE ) const BYTE *dateTime )\n\t{\n\tX917_KEY *des3Key = &randomInfo->x917Key;\n\tint desStatus;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isReadPtr( key, X917_KEYSIZE ) );\n\tassert( isReadPtr( state, X917_KEYSIZE ) );\n\tassert( dateTime == NULL || isReadPtr( dateTime, X917_KEYSIZE ) );\n\n\t/* Precondition: the key and seed aren't being taken from the same \n\t   location */\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\tREQUIRES( memcmp( key, state, X917_POOLSIZE ) );\n\n\t/* Remember that we're about to reset the generator state */\n\trandomInfo->x917Inited = FALSE;\n\n\t/* Schedule the DES keys.  Rather than performing the third key schedule\n\t   we just copy the first scheduled key into the third one, since it's \n\t   the same key in EDE mode */\n\tdes_set_odd_parity( ( C_Block * ) key );\n\tdes_set_odd_parity( ( C_Block * ) ( key + bitsToBytes( 64 ) ) );\n\tdesStatus = des_key_sched( ( des_cblock * ) key, des3Key->desKey1 );\n\tif( desStatus == 0 )\n\t\t{\n\t\tdesStatus = des_key_sched( ( des_cblock * ) \\\n\t\t\t\t\t\t\t\t   ( key + bitsToBytes( 64 ) ),\n\t\t\t\t\t\t\t\t   des3Key->desKey2 );\n\t\t}\n\tmemcpy( des3Key->desKey3, des3Key->desKey1, DES_KEYSIZE );\n\tif( desStatus )\n\t\t{\n\t\t/* There was a problem initialising the keys, don't try and go any\n\t\t   further */\n\t\tENSURES( randomInfo->x917Inited == FALSE );\n\t\treturn( CRYPT_ERROR_RANDOM );\n\t\t}\n\n\t/* Set up the generator state value V(0) and DT if we're using the X9.31\n\t   interpretation */\n\tmemcpy( randomInfo->x917Pool, state, X917_POOLSIZE );\n\tif( dateTime != NULL )\n\t\t{\n\t\tmemcpy( randomInfo->x917DT, dateTime, X917_POOLSIZE );\n\t\trandomInfo->useX931 = TRUE;\n\t\t}\n\n\t/* We've initialised the generator and reset the cryptovariables, we're\n\t   ready to go */\n\trandomInfo->x917Inited = TRUE;\n\trandomInfo->x917Count = 0;\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#else\n\n/* Macros to make what's being done by the generator easier to follow */\n\n#define AES_KEY\t\taes_encrypt_ctx\n#define rngEncrypt( data, key ) \\\n\t\taes_ecb_encrypt( ( data ), ( data ), X917_BLOCKSIZE, ( key ) )\n\n/* Set the X9.17 generator key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint setKeyX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\tIN_BUFFER_C( X917_KEYSIZE ) const BYTE *key,\n\t\t\t\tIN_BUFFER_C( X917_POOLSIZE ) const BYTE *state,\n\t\t\t\tIN_BUFFER_OPT_C( X917_POOLSIZE ) const BYTE *dateTime )\n\t{\n\tAES_KEY *aesKey = DATAPTR_GET( randomInfo->x917Key );\n\tint aesStatus;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isReadPtr( key, X917_KEYSIZE ) );\n\tassert( isReadPtr( state, X917_KEYSIZE ) );\n\tassert( dateTime == NULL || isReadPtr( dateTime, X917_KEYSIZE ) );\n\n\t/* Precondition: the key and seed aren't being taken from the same \n\t   location */\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\tREQUIRES( memcmp( key, state, X917_POOLSIZE ) );\n\n\t/* Remember that we're about to reset the generator state */\n\trandomInfo->x917Inited = FALSE;\n\n\t/* Schedule the AES key */\n\taesStatus = aes_encrypt_key128( key, aesKey );\n\tif( aesStatus != EXIT_SUCCESS )\n\t\t{\n\t\t/* There was a problem initialising the keys, don't try and go any\n\t\t   further */\n\t\tENSURES( randomInfo->x917Inited == FALSE );\n\t\treturn( CRYPT_ERROR_RANDOM );\n\t\t}\n\n\t/* Set up the generator state value V(0) and DT if we're using the X9.31\n\t   interpretation */\n\tmemcpy( randomInfo->x917Pool, state, X917_POOLSIZE );\n\tif( dateTime != NULL )\n\t\t{\n\t\tmemcpy( randomInfo->x917DT, dateTime, X917_POOLSIZE );\n\t\trandomInfo->useX931 = TRUE;\n\t\t}\n\n\t/* We've initialised the generator and reset the cryptovariables, we're\n\t   ready to go */\n\trandomInfo->x917Inited = TRUE;\n\trandomInfo->x917Count = 0;\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_3DES_X917 */\n\n/* Run the X9.17 generator over a block of data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generateX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\t  INOUT_BUFFER_FIXED( length ) BYTE *data, \n\t\t\t\t  IN_RANGE( 1, MAX_RANDOM_BYTES ) const int length )\n\t{\n\tAES_KEY *aesKey = DATAPTR_GET( randomInfo->x917Key );\n\tBYTE encTime[ X917_POOLSIZE + 8 ], *dataPtr = data;\n\tint dataBlockPos, LOOP_ITERATOR;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isReadPtrDynamic( data, length ) );\n\n\t/* Precondition: The generator has been initialised, we're not asking \n\t   for more data than the maximum that should be needed, and the\n\t   cryptovariables aren't past their use-by date */\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\tREQUIRES( randomInfo->x917Inited == TRUE );\n\tREQUIRES( length > 0 && length <= MAX_RANDOM_BYTES );\n\tREQUIRES( randomInfo->x917Count >= 0 && \\\n\t\t\t  randomInfo->x917Count < X917_MAX_CYCLES );\n\n\t/* Process as many blocks of output as needed.  We can't check the\n\t   return value of the encryption call because there isn't one, however\n\t   the encryption code has gone through a self-test when the randomness\n\t   subsystem was initialised.  This can run the generator for slightly \n\t   more than X917_MAX_CYCLES if we're already close to the limit before \n\t   we start, but this isn't a big problem, it's only an approximate \n\t   reset-count measure anyway */\n\tLOOP_LARGE( dataBlockPos = 0, dataBlockPos < length,\n\t\t\t\tdataBlockPos += X917_POOLSIZE )\n\t\t{\n\t\tconst int bytesToCopy = min( length - dataBlockPos, X917_POOLSIZE );\n\t\tint i, LOOP_ITERATOR_ALT;\n\t\tORIGINAL_INT_VAR( x917Count, randomInfo->x917Count );\n\n\t\t/* Precondition: We're processing from 1...X917_POOLSIZE bytes of\n\t\t   data */\n\t\tREQUIRES( bytesToCopy >= 1 && bytesToCopy <= X917_POOLSIZE );\n\n\t\t/* Set the seed from the user-supplied data.  This varies depending\n\t\t   on whether we're using the X9.17 or X9.31 interpretation of\n\t\t   seeding */\n\t\tif( randomInfo->useX931 )\n\t\t\t{\n\t\t\t/* It's the X9.31 interpretation, there's no further user seed\n\t\t\t   input apart from the V and DT that we set initially */\n\t\t\tmemcpy( encTime, randomInfo->x917DT, X917_POOLSIZE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's the X9.17 seed-via-DT interpretation, the user input is\n\t\t\t   DT.  Copy in as much timestamp (+ other assorted data) as we\n\t\t\t   can into the DT value */\n\t\t\tREQUIRES( rangeCheck( bytesToCopy, 1, X917_POOLSIZE ) );\n\t\t\tmemcpy( encTime, dataPtr, bytesToCopy );\n\n\t\t\t/* Inner precondition: The DT buffer contains the input data */\n\t\t\tFORALL( k, 0, bytesToCopy,\n\t\t\t\t\tencTime[ k ] == data[ dataBlockPos + k ] );\n\t\t\t}\n\n\t\t/* out = Enc( Enc( DT ) ^ V(n) ); */\n\t\trngEncrypt( encTime, aesKey );\n\t\tLOOP_EXT_ALT( i = 0, i < X917_POOLSIZE, i++, X917_POOLSIZE + 1 )\n\t\t\trandomInfo->x917Pool[ i ] ^= encTime[ i ];\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\trngEncrypt( randomInfo->x917Pool, aesKey );\n\t\tREQUIRES( boundsCheckZ( dataBlockPos, bytesToCopy, length ) );\n\t\tmemcpy( dataPtr, randomInfo->x917Pool, bytesToCopy );\n\n\t\t/* Postcondition: The internal state has been copied to the output\n\t\t   (ick) */\n\t\tFORALL( k, 0, bytesToCopy, \\\n\t\t\t\tdata[ dataBlockPos + k ] == randomInfo->x917Pool[ k ] );\n\n\t\t/* V(n+1) = Enc( Enc( DT ) ^ out ); */\n\t\tLOOP_EXT_ALT( i = 0, i < X917_POOLSIZE, i++, X917_POOLSIZE + 1 )\n\t\t\trandomInfo->x917Pool[ i ] ^= encTime[ i ];\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\trngEncrypt( randomInfo->x917Pool, aesKey );\n\n\t\t/* If we're using the X9.31 interpretation, update DT to meet the\n\t\t   monotonically increasing time value requirement.  Although the\n\t\t   spec doesn't explicitly state this, the published test vectors\n\t\t   increment the rightmost byte so the value is treated as big-\n\t\t   endian */\n\t\tif( randomInfo->useX931 )\n\t\t\t{\n\t\t\tORIGINAL_INT_VAR( lsb1, randomInfo->x917DT[ X917_POOLSIZE - 1 ] );\n\t\t\tORIGINAL_INT_VAR( lsb2, randomInfo->x917DT[ X917_POOLSIZE - 2 ] );\n\t\t\tORIGINAL_INT_VAR( lsb3, randomInfo->x917DT[ X917_POOLSIZE - 3 ] );\n\n\t\t\tLOOP_EXT_ALT( i = X917_POOLSIZE - 1, i >= 0, i--, X917_POOLSIZE )\n\t\t\t\t{\n\t\t\t\trandomInfo->x917DT[ i ]++;\n\t\t\t\tif( randomInfo->x917DT[ i ] != 0 )\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\n\t\t\t/* Postcondition: The value has been incremented by one */\n\t\t\tENSURES( ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == \\\n\t\t\t\t\t\t\tORIGINAL_VALUE( lsb1 ) + 1 ) || \\\n\t\t\t\t\t ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == 0 && \\\n\t\t\t\t\t   randomInfo->x917DT[ X917_POOLSIZE - 2 ] == \\\n\t\t\t\t\t\t\tORIGINAL_VALUE( lsb2 ) + 1 ) || \\\n\t\t\t\t\t ( randomInfo->x917DT[ X917_POOLSIZE - 1 ] == 0 && \\\n\t\t\t\t\t   randomInfo->x917DT[ X917_POOLSIZE - 2 ] == 0 && \\\n\t\t\t\t\t   randomInfo->x917DT[ X917_POOLSIZE - 3 ] == \\\n\t\t\t\t\t\t\tORIGINAL_VALUE( lsb3 ) + 1 ) );\n\t\t\t}\n\n\t\t/* Move on to the next block */\n\t\tdataPtr += bytesToCopy;\n\t\trandomInfo->x917Count++;\n\n\t\t/* Postcondition: We've processed one more block of data */\n\t\tENSURES( dataPtr == data + dataBlockPos + bytesToCopy );\n\t\tENSURES( randomInfo->x917Count == ORIGINAL_VALUE( x917Count ) + 1 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Postcondition: We processed all of the data */\n\tENSURES( dataPtr == data + length );\n\n\tzeroise( encTime, X917_POOLSIZE );\n\n\t/* Postcondition: Nulla vestigia retrorsum */\n\tFORALL( i, 0, X917_POOLSIZE,\n\t\t\tencTime[ i ] == 0 );\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise the X9.17 generator */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initX917( INOUT RANDOM_INFO *randomInfo )\n\t{\n\tvoid *keyDataPtr = &randomInfo->x917KeyData;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* The X9.17 RNG calls down into low-level internal code at a level\n\t   that bypasses the usual encryption context management.  Since the\n\t   underlying hardware implementation may impose alignment constraints\n\t   on the key storage, we have to manually align it here.  The alignment\n\t   value that we use is 16 bytes, required by some AES hardware */\n#ifdef USE_3DES_X917\n\tstatic_assert( sizeof( X917_KEYDATA ) >= ( 3 * DES_KEYSIZE ) + 16,\n\t\t\t\t   \"X.917 key storage\" );\n#else\n\tstatic_assert( sizeof( X917_KEYDATA ) >= AES_KEYSIZE + 16,\n\t\t\t\t   \"X.917 key storage\" );\n#endif /* USE_3DES_X917 */\n\tkeyDataPtr = ( void * ) roundUp( ( uintptr_t ) keyDataPtr, 16 );\n\tDATAPTR_SET( randomInfo->x917Key, keyDataPtr );\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tX9.17 Generator Self-test Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_NO_SELFTEST\n\n/* X9.17/X9.31 generator test vectors.  The first set of values used are\n   from the NIST publication \"The Random Number Generator Validation System\n   (RNGVS)\" (unfortunately the MCT values for this are wrong so they can't\n   be used), the second set are from test data used by an eval lab, and the\n   third set are the values used for cryptlib's FIPS evaluation */\n\n#define RNG_TEST_3DES_NIST\t0\n#define RNG_TEST_INFOGARD\t1\n#define RNG_TEST_FIPSEVAL\t2\n#define RNG_TEST_AES_NIST\t3\n\n#ifdef USE_3DES_X917\n  #define RNG_TEST_VALUES\tRNG_TEST_INFOGARD\n#else\n  #define RNG_TEST_VALUES\tRNG_TEST_AES_NIST\n#endif /* USE_3DES_X917 */\n\n#if ( RNG_TEST_VALUES == RNG_TEST_3DES_NIST )\n  #define VST_ITERATIONS\t5\n#elif ( RNG_TEST_VALUES == RNG_TEST_INFOGARD )\n  #define VST_ITERATIONS\t64\n#elif ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n  #define VST_ITERATIONS\t64\n#elif ( RNG_TEST_VALUES == RNG_TEST_AES_NIST )\n  #define VST_ITERATIONS\t64\n#endif /* VST iterations */\n\ntypedef struct {\n\t/* The values are declared with an extra byte of storage since they're\n\t   initialised from strings, which have an implicit '\\0' at the end */\n\tconst BYTE key[ X917_KEYSIZE + 1 ];\n\tconst BYTE DT[ X917_BLOCKSIZE + 1 ], V[ X917_BLOCKSIZE + 1 ];\n\tconst BYTE R[ X917_BLOCKSIZE + 1 ];\n\t} X917_MCT_TESTDATA;\n\ntypedef struct {\n\tconst BYTE key[ X917_KEYSIZE + 1 ];\n\tconst BYTE initDT[ X917_BLOCKSIZE + 1 ], initV[ X917_BLOCKSIZE + 1 ];\n\tconst BYTE R[ VST_ITERATIONS ][ X917_BLOCKSIZE + 1 ];\n\t} X917_VST_TESTDATA;\n\nstatic const X917_MCT_TESTDATA x917MCTdata = {\t/* Monte Carlo Test */\n#if ( RNG_TEST_VALUES == RNG_TEST_3DES_NIST )\t/* These values are wrong */\n\t/* Key1 = 75C71AE5A11A232C\n\t   Key2 = 40256DCD94F767B0\n\t   DT = C89A1D888ED12F3C\n\t   V = D5538F9CF450F53C\n\t   R = 77C695C33E51C8C0 */\n\t\"\\x75\\xC7\\x1A\\xE5\\xA1\\x1A\\x23\\x2C\\x40\\x25\\x6D\\xCD\\x94\\xF7\\x67\\xB0\",\n\t\"\\xC8\\x9A\\x1D\\x88\\x8E\\xD1\\x2F\\x3C\",\n\t\"\\xD5\\x53\\x8F\\x9C\\xF4\\x50\\xF5\\x3C\",\n\t\"\\x77\\xC6\\x95\\xC3\\x3E\\x51\\xC8\\xC0\"\n#elif ( RNG_TEST_VALUES == RNG_TEST_INFOGARD )\n\t/* Key1 = 625BB5131A45F492\n\t   Key2 = 70971C9E0D4C9792\n\t   DT = 5F328264B787B098\n\t   V = A24F6E0EE43204CD\n\t   R = C7AC1E8F100CC30A */\n\t\"\\x62\\x5B\\xB5\\x13\\x1A\\x45\\xF4\\x92\\x70\\x97\\x1C\\x9E\\x0D\\x4C\\x97\\x92\",\n\t\"\\x5F\\x32\\x82\\x64\\xB7\\x87\\xB0\\x98\",\n\t\"\\xA2\\x4F\\x6E\\x0E\\xE4\\x32\\x04\\xCD\",\n\t\"\\xC7\\xAC\\x1E\\x8F\\x10\\x0C\\xC3\\x0A\"\n#elif ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\t/* Key1 = A45BF2E50D153710\n\t   Key2 = 79832F38A89B2AB0\n\t   DT = 8219E01B2A6958BB\n\t   V = 283176BA23FA3181\n\t   R = ? */\n\t\"\\xA4\\x5B\\xF2\\xE5\\x0D\\x15\\x37\\x10\\x79\\x83\\x2F\\x38\\xA8\\x9B\\x2A\\xB0\",\n\t\"\\x82\\x19\\xE0\\x1B\\x2A\\x69\\x58\\xBB\",\n\t\"\\x28\\x31\\x76\\xBA\\x23\\xFA\\x31\\x81\",\n\t0\n#elif ( RNG_TEST_VALUES == RNG_TEST_AES_NIST )\n\t/* Key = F7D36762B9915F1ED585EB8E91700EB2\n\t   DT = 259E67249288597A4D61E7C0E690AFAE\n\t   V = 35CC0EA481FC8A4F5F05C7D4667233B2\n\t   R = 26A6B3D33B8E7E68B75D9630EC036314 */\n\t\"\\xF7\\xD3\\x67\\x62\\xB9\\x91\\x5F\\x1E\\xD5\\x85\\xEB\\x8E\\x91\\x70\\x0E\\xB2\",\n\t\"\\x25\\x9E\\x67\\x24\\x92\\x88\\x59\\x7A\\x4D\\x61\\xE7\\xC0\\xE6\\x90\\xAF\\xAE\",\n\t\"\\x35\\xCC\\x0E\\xA4\\x81\\xFC\\x8A\\x4F\\x5F\\x05\\xC7\\xD4\\x66\\x72\\x33\\xB2\",\n\t\"\\x26\\xA6\\xB3\\xD3\\x3B\\x8E\\x7E\\x68\\xB7\\x5D\\x96\\x30\\xEC\\x03\\x63\\x14\"\n#endif /* Different test vectors */\n\t};\n\nstatic const X917_VST_TESTDATA x917VSTdata = {\t/* Variable Seed Test (VST) */\n#if ( RNG_TEST_VALUES == RNG_TEST_3DES_NIST )\n\t/* Count = 0\n\t   Key1 = 75C71AE5A11A232C\n\t   Key2 = 40256DCD94F767B0\n\t   DT = C89A1D888ED12F3C\n\t   V = 80000000000000000 */\n\t\"\\x75\\xC7\\x1A\\xE5\\xA1\\x1A\\x23\\x2C\\x40\\x25\\x6D\\xCD\\x94\\xF7\\x67\\xB0\",\n\t\"\\xC8\\x9A\\x1D\\x88\\x8E\\xD1\\x2F\\x3C\",\n\t\"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",\n\t  /* Count = 0, V = 8000000000000000, R = 944DC7210D6D7FD7 */\n\t{ \"\\x94\\x4D\\xC7\\x21\\x0D\\x6D\\x7F\\xD7\",\n\t  /* Count = 1, V = C000000000000000, R = AF1A648591BB7C2C */\n\t  \"\\xAF\\x1A\\x64\\x85\\x91\\xBB\\x7C\\x2C\",\n\t  /* Count = 2, V = E000000000000000, R = 221839B07451E423 */\n\t  \"\\x22\\x18\\x39\\xB0\\x74\\x51\\xE4\\x23\",\n\t  /* Count = 3, V = F000000000000000, R = EBA9271E04043712 */\n\t  \"\\xEB\\xA9\\x27\\x1E\\x04\\x04\\x37\\x12\",\n\t  /* Count = 4, V = F800000000000000, R = 02433C9417A3326F */\n\t  \"\\x02\\x43\\x3C\\x94\\x17\\xA3\\x32\\x6F\" }\n#elif ( RNG_TEST_VALUES == RNG_TEST_INFOGARD )\n\t/* Count = 0\n\t   Key1 = 3164916EA2C87AAE\n\t   Key2 = 2ABC323EFB9802E3\n\t   DT = 65B9108277AC0582\n\t   V = 80000000000000000 */\n\t\"\\x31\\x64\\x91\\x6E\\xA2\\xC8\\x7A\\xAE\\x2A\\xBC\\x32\\x3E\\xFB\\x98\\x02\\xE3\",\n\t\"\\x65\\xB9\\x10\\x82\\x77\\xAC\\x05\\x82\",\n\t\"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",\n\t  /* Count = 0, V = 8000000000000000, R = D8015B966ADE69BA */\n\t{ \"\\xD8\\x01\\x5B\\x96\\x6A\\xDE\\x69\\xBA\",\n\t  /* Count = 1, V = C000000000000000, R = E737E18734365F43 */\n\t  \"\\xE7\\x37\\xE1\\x87\\x34\\x36\\x5F\\x43\",\n\t  /* Count = 2, V = E000000000000000, R = CA8F00C1DF28FCFF */\n\t  \"\\xCA\\x8F\\x00\\xC1\\xDF\\x28\\xFC\\xFF\",\n\t  /* Count = 3, V = F000000000000000, R = 9FF307027622FA2A */\n\t  \"\\x9F\\xF3\\x07\\x02\\x76\\x22\\xFA\\x2A\",\n\t  /* Count = 4, V = F800000000000000, R = 0A4BB2E54842648E */\n\t  \"\\x0A\\x4B\\xB2\\xE5\\x48\\x42\\x64\\x8E\",\n\t  /* Count = 5, V = FC00000000000000, R = FFAD84A57EE0DE37 */\n\t  \"\\xFF\\xAD\\x84\\xA5\\x7E\\xE0\\xDE\\x37\",\n\t  /* Count = 6, V = FE00000000000000, R = 0CF064313A7889FD */\n\t  \"\\x0C\\xF0\\x64\\x31\\x3A\\x78\\x89\\xFD\",\n\t  /* Count = 7, V = FF00000000000000, R = 97B6854447D95A01 */\n\t  \"\\x97\\xB6\\x85\\x44\\x47\\xD9\\x5A\\x01\",\n\t  /* Count = 8, V = ff80000000000000, R = 55272f900ae13948 */\n\t  \"\\x55\\x27\\x2F\\x90\\x0A\\xE1\\x39\\x48\",\n\t  /* Count = 9, V = ffc0000000000000, R = dbd731bdf9875a04 */\n\t  \"\\xDB\\xD7\\x31\\xBD\\xF9\\x87\\x5A\\x04\",\n\t  /* Count = 10, V = ffe0000000000000, R = b19589a371d4942d */\n\t  \"\\xB1\\x95\\x89\\xA3\\x71\\xD4\\x94\\x2D\",\n\t  /* Count = 11, V = fff0000000000000, R = 8da8f8e8c59fc497 */\n\t  \"\\x8D\\xA8\\xF8\\xE8\\xC5\\x9F\\xC4\\x97\",\n\t  /* Count = 12, V = fff8000000000000, R = ddfbf3f319bcda42 */\n\t  \"\\xDD\\xFB\\xF3\\xF3\\x19\\xBC\\xDA\\x42\",\n\t  /* Count = 13, V = fffc000000000000, R = a72ddd98d1744844 */\n\t  \"\\xA7\\x2D\\xDD\\x98\\xD1\\x74\\x48\\x44\",\n\t  /* Count = 14, V = fffe000000000000, R = de0835034456629e */\n\t  \"\\xDE\\x08\\x35\\x03\\x44\\x56\\x62\\x9E\",\n\t  /* Count = 15, V = ffff000000000000, R = e977daafef7aa5e0 */\n\t  \"\\xE9\\x77\\xDA\\xAF\\xEF\\x7A\\xA5\\xE0\",\n\t  /* Count = 16, V = ffff800000000000, R = 019c3edc5ae93ab8 */\n\t  \"\\x01\\x9C\\x3E\\xDC\\x5A\\xE9\\x3A\\xB8\",\n\t  /* Count = 17, V = ffffc00000000000, R = 163c3dbe31ffd91b */\n\t  \"\\x16\\x3C\\x3D\\xBE\\x31\\xFF\\xD9\\x1B\",\n\t  /* Count = 18, V = ffffe00000000000, R = f2045893945b4774 */\n\t  \"\\xF2\\x04\\x58\\x93\\x94\\x5B\\x47\\x74\",\n\t  /* Count = 19, V = fffff00000000000, R = 50c88799fc1ec55d */\n\t  \"\\x50\\xC8\\x87\\x99\\xFC\\x1E\\xC5\\x5D\",\n\t  /* Count = 20, V = fffff80000000000, R = 1545f463986e1511 */\n\t  \"\\x15\\x45\\xF4\\x63\\x98\\x6E\\x15\\x11\",\n\t  /* Count = 21, V = fffffc0000000000, R = 55f999624fe045a6 */\n\t  \"\\x55\\xF9\\x99\\x62\\x4F\\xE0\\x45\\xA6\",\n\t  /* Count = 22, V = fffffe0000000000, R = e3e0db844bca7505 */\n\t  \"\\xE3\\xE0\\xDB\\x84\\x4B\\xCA\\x75\\x05\",\n\t  /* Count = 23, V = ffffff0000000000, R = 8fb4b76d808562d7 */\n\t  \"\\x8F\\xB4\\xB7\\x6D\\x80\\x85\\x62\\xD7\",\n\t  /* Count = 24, V = ffffff8000000000, R = 9d5457baaeb496e4 */\n\t  \"\\x9D\\x54\\x57\\xBA\\xAE\\xB4\\x96\\xE4\",\n\t  /* Count = 25, V = ffffffc000000000, R = 2b8abff2bdc82366 */\n\t  \"\\x2B\\x8A\\xBF\\xF2\\xBD\\xC8\\x23\\x66\",\n\t  /* Count = 26, V = ffffffe000000000, R = 3936c324d09465af */\n\t  \"\\x39\\x36\\xC3\\x24\\xD0\\x94\\x65\\xAF\",\n\t  /* Count = 27, V = fffffff000000000, R = 1983dd227e55240e */\n\t  \"\\x19\\x83\\xDD\\x22\\x7E\\x55\\x24\\x0E\",\n\t  /* Count = 28, V = fffffff800000000, R = 866cf6e6dc3d03fb */\n\t  \"\\x86\\x6C\\xF6\\xE6\\xDC\\x3D\\x03\\xFB\",\n\t  /* Count = 29, V = fffffffc00000000, R = 03d10b0f17b04b59 */\n\t  \"\\x03\\xD1\\x0B\\x0F\\x17\\xB0\\x4B\\x59\",\n\t  /* Count = 30, V = fffffffe00000000, R = 3eeb1cd0248e25a6 */\n\t  \"\\x3E\\xEB\\x1C\\xD0\\x24\\x8E\\x25\\xA6\",\n\t  /* Count = 31, V = ffffffff00000000, R = 9d8bd4b8c3e425dc */\n\t  \"\\x9D\\x8B\\xD4\\xB8\\xC3\\xE4\\x25\\xDC\",\n\t  /* Count = 32, V = ffffffff80000000, R = bc515d3a0a719be1 */\n\t  \"\\xBC\\x51\\x5D\\x3A\\x0A\\x71\\x9B\\xE1\",\n\t  /* Count = 33, V = ffffffffc0000000, R = 1b35fb4aca4ac47c */\n\t  \"\\x1B\\x35\\xFB\\x4A\\xCA\\x4A\\xC4\\x7C\",\n\t  /* Count = 34, V = ffffffffe0000000, R = f8338668b6ead493 */\n\t  \"\\xF8\\x33\\x86\\x68\\xB6\\xEA\\xD4\\x93\",\n\t  /* Count = 35, V = fffffffff0000000, R = cdfa8e5ffa2deb17 */\n\t  \"\\xCD\\xFA\\x8E\\x5F\\xFA\\x2D\\xEB\\x17\",\n\t  /* Count = 36, V = fffffffff8000000, R = c965a35109044ca3 */\n\t  \"\\xC9\\x65\\xA3\\x51\\x09\\x04\\x4C\\xA3\",\n\t  /* Count = 37, V = fffffffffc000000, R = 8da70c88167b2746 */\n\t  \"\\x8D\\xA7\\x0C\\x88\\x16\\x7B\\x27\\x46\",\n\t  /* Count = 38, V = fffffffffe000000, R = 22ba92a21a74eb5b */\n\t  \"\\x22\\xBA\\x92\\xA2\\x1A\\x74\\xEB\\x5B\",\n\t  /* Count = 39, V = ffffffffff000000, R = 1fba0fab823a85e7 */\n\t  \"\\x1F\\xBA\\x0F\\xAB\\x82\\x3A\\x85\\xE7\",\n\t  /* Count = 40, V = ffffffffff800000, R = 656f4fc91245073d */\n\t  \"\\x65\\x6F\\x4F\\xC9\\x12\\x45\\x07\\x3D\",\n\t  /* Count = 41, V = ffffffffffc00000, R = a803441fb939f09c */\n\t  \"\\xA8\\x03\\x44\\x1F\\xB9\\x39\\xF0\\x9C\",\n\t  /* Count = 42, V = ffffffffffe00000, R = e3f30bb6aed64331 */\n\t  \"\\xE3\\xF3\\x0B\\xB6\\xAE\\xD6\\x43\\x31\",\n\t  /* Count = 43, V = fffffffffff00000, R = 6a75588b5e6f5ea4 */\n\t  \"\\x6A\\x75\\x58\\x8B\\x5E\\x6F\\x5E\\xA4\",\n\t  /* Count = 44, V = fffffffffff80000, R = ec95ad55ac684e93 */\n\t  \"\\xEC\\x95\\xAD\\x55\\xAC\\x68\\x4E\\x93\",\n\t  /* Count = 45, V = fffffffffffc0000, R = b2a79a0ebfb96c4e */\n\t  \"\\xB2\\xA7\\x9A\\x0E\\xBF\\xB9\\x6C\\x4E\",\n\t  /* Count = 46, V = fffffffffffe0000, R = 480263bb6146006f */\n\t  \"\\x48\\x02\\x63\\xBB\\x61\\x46\\x00\\x6F\",\n\t  /* Count = 47, V = ffffffffffff0000, R = c0d8b711395b290f */\n\t  \"\\xC0\\xD8\\xB7\\x11\\x39\\x5B\\x29\\x0F\",\n\t  /* Count = 48, V = ffffffffffff8000, R = a3f39193fe3d526d */\n\t  \"\\xA3\\xF3\\x91\\x93\\xFE\\x3D\\x52\\x6D\",\n\t  /* Count = 49, V = ffffffffffffc000, R = 6f50ba964d94d153 */\n\t  \"\\x6F\\x50\\xBA\\x96\\x4D\\x94\\xD1\\x53\",\n\t  /* Count = 50, V = ffffffffffffe000, R = ff8240a77c67bb8d */\n\t  \"\\xFF\\x82\\x40\\xA7\\x7C\\x67\\xBB\\x8D\",\n\t  /* Count = 51, V = fffffffffffff000, R = 7f95c72fd9b38ff6 */\n\t  \"\\x7F\\x95\\xC7\\x2F\\xD9\\xB3\\x8F\\xF6\",\n\t  /* Count = 52, V = fffffffffffff800, R = 7fbdf1428f44aac1 */\n\t  \"\\x7F\\xBD\\xF1\\x42\\x8F\\x44\\xAA\\xC1\",\n\t  /* Count = 53, V = fffffffffffffc00, R = 04cec286480ab97b */\n\t  \"\\x04\\xCE\\xC2\\x86\\x48\\x0A\\xB9\\x7B\",\n\t  /* Count = 54, V = fffffffffffffe00, R = 86562948c1cf8ec0 */\n\t  \"\\x86\\x56\\x29\\x48\\xC1\\xCF\\x8E\\xC0\",\n\t  /* Count = 55, V = ffffffffffffff00, R = b1a1c0f20c71b267 */\n\t  \"\\xB1\\xA1\\xC0\\xF2\\x0C\\x71\\xB2\\x67\",\n\t  /* Count = 56, V = ffffffffffffff80, R = f357a25c7dacbca8 */\n\t  \"\\xF3\\x57\\xA2\\x5C\\x7D\\xAC\\xBC\\xA8\",\n\t  /* Count = 57, V = ffffffffffffffc0, R = 8f8f4e0e348bf185 */\n\t  \"\\x8F\\x8F\\x4E\\x0E\\x34\\x8B\\xF1\\x85\",\n\t  /* Count = 58, V = ffffffffffffffe0, R = 52a21df35fa70190 */\n\t  \"\\x52\\xA2\\x1D\\xF3\\x5F\\xA7\\x01\\x90\",\n\t  /* Count = 59, V = fffffffffffffff0, R = 8be78733594af616 */\n\t  \"\\x8B\\xE7\\x87\\x33\\x59\\x4A\\xF6\\x16\",\n\t  /* Count = 60, V = fffffffffffffff8, R = e03a051b4ca826e5 */\n\t  \"\\xE0\\x3A\\x05\\x1B\\x4C\\xA8\\x26\\xE5\",\n\t  /* Count = 61, V = fffffffffffffffc, R = 5c4b73bb5901c3cf */\n\t  \"\\x5C\\x4B\\x73\\xBB\\x59\\x01\\xC3\\xCF\",\n\t  /* Count = 62, V = fffffffffffffffe, R = e5d7fc8415bfb0f0 */\n\t  \"\\xE5\\xD7\\xFC\\x84\\x15\\xBF\\xB0\\xF0\",\n\t  /* Count = 63, V = ffffffffffffffff, R = 9417d7247eaa5159 */\n\t  \"\\x94\\x17\\xD7\\x24\\x7E\\xAA\\x51\\x59\" }\n#elif ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\t/* COUNT = 0\n\t   Key1 = 3D3D0289DAEC867A\n\t   Key2 = 29B3F2C7F12C40E5\n\t   DT = 6FC8AE5CA678E042\n\t   V = 80000000000000000 */\n\t\"\\x3D\\x3D\\x02\\x89\\xDA\\xEC\\x86\\x7A\\x29\\xB3\\xF2\\xC7\\xF1\\x2C\\x40\\xE5\",\n\t\"\\x6F\\xC8\\xAE\\x5C\\xA6\\x78\\xE0\\x42\",\n\t\"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",\n\t{ 0 }\n#elif ( RNG_TEST_VALUES == RNG_TEST_AES_NIST )\n\t/* Key = 7213395B28586FE64026056638110B3C\n\t   DT = 947529F603EDB0CF6927F65EDBBBC593\n\t   V = 80000000000000000000000000000000 */\n\t\"\\x72\\x13\\x39\\x5B\\x28\\x58\\x6F\\xE6\\x40\\x26\\x05\\x66\\x38\\x11\\x0B\\x3C\",\n\t\"\\x94\\x75\\x29\\xF6\\x03\\xED\\xB0\\xCF\\x69\\x27\\xF6\\x5E\\xDB\\xBB\\xC5\\x93\",\n\t\"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",\n\t  /* Count = 0, V = 80000000000000000000000000000000, \n\t\t\t\t\tR = 339CEF70DA546707B2944591890394A3 */\n\t{ \"\\x33\\x9C\\xEF\\x70\\xDA\\x54\\x67\\x07\\xB2\\x94\\x45\\x91\\x89\\x03\\x94\\xA3\",\n\t  /* Count = 1, V = C0000000000000000000000000000000\n\t\t\t\t\tR = CC96309772E727E71BAF70C361E626AE */\n\t  \"\\xCC\\x96\\x30\\x97\\x72\\xE7\\x27\\xE7\\x1B\\xAF\\x70\\xC3\\x61\\xE6\\x26\\xAE\",\n\t  /* Count = 2, V = E0000000000000000000000000000000\n\t\t\t\t\tR = 793B0B004CE8543B24D26BC76EF84C19 */\n\t  \"\\x79\\x3B\\x0B\\x00\\x4C\\xE8\\x54\\x3B\\x24\\xD2\\x6B\\xC7\\x6E\\xF8\\x4C\\x19\",\n\t  /* Count = 3, V = F0000000000000000000000000000000\n\t\t\t\t\tR = 00A6100F3AC3C0AFC7194D75863BB97D */\n\t  \"\\x00\\xA6\\x10\\x0F\\x3A\\xC3\\xC0\\xAF\\xC7\\x19\\x4D\\x75\\x86\\x3B\\xB9\\x7D\",\n\t  /* Count = 4, V = F8000000000000000000000000000000\n\t\t\t\t\tR = DB6DCD4CDAFFD704E4AC9BA46448771A */\n\t  \"\\xDB\\x6D\\xCD\\x4C\\xDA\\xFF\\xD7\\x04\\xE4\\xAC\\x9B\\xA4\\x64\\x48\\x77\\x1A\",\n\t  /* Count = 5, V = FC000000000000000000000000000000\n\t\t\t\t\tR = 29BB29E1CA7EFFE2807C674628AE97FF */\n\t  \"\\x29\\xBB\\x29\\xE1\\xCA\\x7E\\xFF\\xE2\\x80\\x7C\\x67\\x46\\x28\\xAE\\x97\\xFF\",\n\t  /* Count = 6, V = FE000000000000000000000000000000\n\t\t\t\t\tR = 67290EA5D230E13E73E9223929078BD9 */\n\t  \"\\x67\\x29\\x0E\\xA5\\xD2\\x30\\xE1\\x3E\\x73\\xE9\\x22\\x39\\x29\\x07\\x8B\\xD9\",\n\t  /* Count = 7, V = FF000000000000000000000000000000\n\t\t\t\t\tR = 00A4362875F0FF7E2E58C616CA22A961 */\n\t  \"\\x00\\xA4\\x36\\x28\\x75\\xF0\\xFF\\x7E\\x2E\\x58\\xC6\\x16\\xCA\\x22\\xA9\\x61\",\n\t  /* Count = 8, V = FF800000000000000000000000000000\n\t\t\t\t\tR = 1C689C09F84BEAA4785F7507CE99D909 */\n\t  \"\\x1C\\x68\\x9C\\x09\\xF8\\x4B\\xEA\\xA4\\x78\\x5F\\x75\\x07\\xCE\\x99\\xD9\\x09\",\n\t  /* Count = 9, V = FFC00000000000000000000000000000\n\t\t\t\t\tR = 5C83858DA3C8D53EBCE32FA44764A2C9 */\n\t  \"\\x5C\\x83\\x85\\x8D\\xA3\\xC8\\xD5\\x3E\\xBC\\xE3\\x2F\\xA4\\x47\\x64\\xA2\\xC9\",\n\t  /* Count = 10, V = FFE00000000000000000000000000000\n\t\t\t\t\t R = 5E4F68F6D5BEB7C7855518B34E2BA2F6 */\n\t  \"\\x5E\\x4F\\x68\\xF6\\xD5\\xBE\\xB7\\xC7\\x85\\x55\\x18\\xB3\\x4E\\x2B\\xA2\\xF6\",\n\t  /* Count = 11, V = FFF00000000000000000000000000000\n\t\t\t\t\t R = ED7FE3B42B8724CE68C070E61588D11A */\n\t  \"\\xED\\x7F\\xE3\\xB4\\x2B\\x87\\x24\\xCE\\x68\\xC0\\x70\\xE6\\x15\\x88\\xD1\\x1A\",\n\t  /* Count = 12, V = FFF80000000000000000000000000000\n\t\t\t\t\t R = FFA4846475CB9F83261F0A04FD11368E */\n\t  \"\\xFF\\xA4\\x84\\x64\\x75\\xCB\\x9F\\x83\\x26\\x1F\\x0A\\x04\\xFD\\x11\\x36\\x8E\",\n\t  /* Count = 13, V = FFFC0000000000000000000000000000\n\t\t\t\t\t R = 3125F56CE4C048A5B33803C8020C8E6C */\n\t  \"\\x31\\x25\\xF5\\x6C\\xE4\\xC0\\x48\\xA5\\xB3\\x38\\x03\\xC8\\x02\\x0C\\x8E\\x6C\",\n\t  /* Count = 14, V = FFFE0000000000000000000000000000\n\t\t\t\t\t R = 7CC527BAA5B2B3ADD8E2198B326B8555 */\n\t  \"\\x7C\\xC5\\x27\\xBA\\xA5\\xB2\\xB3\\xAD\\xD8\\xE2\\x19\\x8B\\x32\\x6B\\x85\\x55\",\n\t  /* Count = 15, V = FFFF0000000000000000000000000000\n\t\t\t\t\t R = 95810F62AEE87ACCE306B4FAFE30831B */\n\t  \"\\x95\\x81\\x0F\\x62\\xAE\\xE8\\x7A\\xCC\\xE3\\x06\\xB4\\xFA\\xFE\\x30\\x83\\x1B\",\n\t  /* Count = 16, V = FFFF8000000000000000000000000000\n\t\t\t\t\t R = 69C8E966EE3EDAA1F78022D65F23D21A */\n\t  \"\\x69\\xC8\\xE9\\x66\\xEE\\x3E\\xDA\\xA1\\xF7\\x80\\x22\\xD6\\x5F\\x23\\xD2\\x1A\",\n\t  /* Count = 17, V = FFFFC000000000000000000000000000\n\t\t\t\t\t R = 5B5A4B89F521B3BA43B2F1FB226DA412 */\n\t  \"\\x5B\\x5A\\x4B\\x89\\xF5\\x21\\xB3\\xBA\\x43\\xB2\\xF1\\xFB\\x22\\x6D\\xA4\\x12\",\n\t  /* Count = 18, V = FFFFE000000000000000000000000000\n\t\t\t\t\t R = 669763CDAC9C776108BB0A3AC9E8717B */\n\t  \"\\x66\\x97\\x63\\xCD\\xAC\\x9C\\x77\\x61\\x08\\xBB\\x0A\\x3A\\xC9\\xE8\\x71\\x7B\",\n\t  /* Count = 19, V = FFFFF000000000000000000000000000\n\t\t\t\t\t R = 7420DFD43C1E1CDDE2E97EDC02C1C88A */\n\t  \"\\x74\\x20\\xDF\\xD4\\x3C\\x1E\\x1C\\xDD\\xE2\\xE9\\x7E\\xDC\\x02\\xC1\\xC8\\x8A\",\n\t  /* Count = 20, V = FFFFF800000000000000000000000000\n\t\t\t\t\t R = 0C1D2142B51720BDCFF11FF41CB573CD */\n\t  \"\\x0C\\x1D\\x21\\x42\\xB5\\x17\\x20\\xBD\\xCF\\xF1\\x1F\\xF4\\x1C\\xB5\\x73\\xCD\",\n\t  /* Count = 21, V = FFFFFC00000000000000000000000000\n\t\t\t\t\t R = 05B089E217EFE8A06F25D8226F7075F8 */\n\t  \"\\x05\\xB0\\x89\\xE2\\x17\\xEF\\xE8\\xA0\\x6F\\x25\\xD8\\x22\\x6F\\x70\\x75\\xF8\",\n\t  /* Count = 22, V = FFFFFE00000000000000000000000000\n\t\t\t\t\t R = 12F408B060A676019A430173E9236802 */\n\t  \"\\x12\\xF4\\x08\\xB0\\x60\\xA6\\x76\\x01\\x9A\\x43\\x01\\x73\\xE9\\x23\\x68\\x02\",\n\t  /* Count = 23, V = FFFFFF00000000000000000000000000\n\t\t\t\t\t R = 84DECCB0A2E30E1DF4601F1EAB0A5498 */\n\t  \"\\x84\\xDE\\xCC\\xB0\\xA2\\xE3\\x0E\\x1D\\xF4\\x60\\x1F\\x1E\\xAB\\x0A\\x54\\x98\",\n\t  /* Count = 24, V = FFFFFF80000000000000000000000000\n\t\t\t\t\t R = 4AF9217A6587BB66C72093F9FA52DFEF */\n\t  \"\\x4A\\xF9\\x21\\x7A\\x65\\x87\\xBB\\x66\\xC7\\x20\\x93\\xF9\\xFA\\x52\\xDF\\xEF\",\n\t  /* Count = 25, V = FFFFFFC0000000000000000000000000\n\t\t\t\t\t R = 6C552CD4E79B887C7F8A82A204BB5BC3 */\n\t  \"\\x6C\\x55\\x2C\\xD4\\xE7\\x9B\\x88\\x7C\\x7F\\x8A\\x82\\xA2\\x04\\xBB\\x5B\\xC3\",\n\t  /* Count = 26, V = FFFFFFE0000000000000000000000000\n\t\t\t\t\t R = 835E991A3FEF8A735574B3C8D6C18EE3 */\n\t  \"\\x83\\x5E\\x99\\x1A\\x3F\\xEF\\x8A\\x73\\x55\\x74\\xB3\\xC8\\xD6\\xC1\\x8E\\xE3\",\n\t  /* Count = 27, V = FFFFFFF0000000000000000000000000\n\t\t\t\t\t R = 7D4A1BAD6049ED9F6105B54081E0A47B */\n\t  \"\\x7D\\x4A\\x1B\\xAD\\x60\\x49\\xED\\x9F\\x61\\x05\\xB5\\x40\\x81\\xE0\\xA4\\x7B\",\n\t  /* Count = 28, V = FFFFFFF8000000000000000000000000\n\t\t\t\t\t R = E4B2E5FD7C6AE9C7009B358DBFBBC40E */\n\t  \"\\xE4\\xB2\\xE5\\xFD\\x7C\\x6A\\xE9\\xC7\\x00\\x9B\\x35\\x8D\\xBF\\xBB\\xC4\\x0E\",\n\t  /* Count = 29, V = FFFFFFFC000000000000000000000000\n\t\t\t\t\t R = 601ED99FA91B1EE1E7B12E1B55CBBF39 */\n\t  \"\\x60\\x1E\\xD9\\x9F\\xA9\\x1B\\x1E\\xE1\\xE7\\xB1\\x2E\\x1B\\x55\\xCB\\xBF\\x39\",\n\t  /* Count = 30, V = FFFFFFFE000000000000000000000000\n\t\t\t\t\t R = 8C9E1F94FE91B8BC3BF62CA875595199 */\n\t  \"\\x8C\\x9E\\x1F\\x94\\xFE\\x91\\xB8\\xBC\\x3B\\xF6\\x2C\\xA8\\x75\\x59\\x51\\x99\",\n\t  /* Count = 31, V = FFFFFFFF000000000000000000000000\n\t\t\t\t\t R = BC7F2371D7ACE178EC967D3FD85FAB35 */\n\t  \"\\xBC\\x7F\\x23\\x71\\xD7\\xAC\\xE1\\x78\\xEC\\x96\\x7D\\x3F\\xD8\\x5F\\xAB\\x35\",\n\t  /* Count = 32, V = FFFFFFFF800000000000000000000000\n\t\t\t\t\t R = 9E909514330BC5898CB6CE6C3A72798B */\n\t  \"\\x9E\\x90\\x95\\x14\\x33\\x0B\\xC5\\x89\\x8C\\xB6\\xCE\\x6C\\x3A\\x72\\x79\\x8B\",\n\t  /* Count = 33, V = FFFFFFFFC00000000000000000000000\n\t\t\t\t\t R = 9E8D2E53EA2B457941A6344B01B9E623 */\n\t  \"\\x9E\\x8D\\x2E\\x53\\xEA\\x2B\\x45\\x79\\x41\\xA6\\x34\\x4B\\x01\\xB9\\xE6\\x23\",\n\t  /* Count = 34, V = FFFFFFFFE00000000000000000000000\n\t\t\t\t\t R = 9FD7CF92C009BD7823AA4B098245FE07 */\n\t  \"\\x9F\\xD7\\xCF\\x92\\xC0\\x09\\xBD\\x78\\x23\\xAA\\x4B\\x09\\x82\\x45\\xFE\\x07\",\n\t  /* Count = 35, V = FFFFFFFFF00000000000000000000000\n\t\t\t\t\t R = F9D462B9FC073EF766623ACC9E813D79 */\n\t  \"\\xF9\\xD4\\x62\\xB9\\xFC\\x07\\x3E\\xF7\\x66\\x62\\x3A\\xCC\\x9E\\x81\\x3D\\x79\",\n \t  /* Count = 36, V = FFFFFFFFF80000000000000000000000\n\t\t\t\t\t R = BC8B053176EF602EAB420C4C71C94B7D */\n\t  \"\\xBC\\x8B\\x05\\x31\\x76\\xEF\\x60\\x2E\\xAB\\x42\\x0C\\x4C\\x71\\xC9\\x4B\\x7D\",\n\t  /* Count = 37, V = FFFFFFFFFC0000000000000000000000\n\t\t\t\t\t R = D914FF8866033081BE23C7A6357E88A1 */\n\t  \"\\xD9\\x14\\xFF\\x88\\x66\\x03\\x30\\x81\\xBE\\x23\\xC7\\xA6\\x35\\x7E\\x88\\xA1\",\n\t  /* Count = 38, V = FFFFFFFFFE0000000000000000000000\n\t\t\t\t\t R = 056D2D88CECCF5EB1E14F6950E4F98CA */\n\t  \"\\x05\\x6D\\x2D\\x88\\xCE\\xCC\\xF5\\xEB\\x1E\\x14\\xF6\\x95\\x0E\\x4F\\x98\\xCA\",\n\t  /* Count = 39, V = FFFFFFFFFF0000000000000000000000\n\t\t\t\t\t R = 580F8E925DCB03206A0832E3CF956D44 */\n\t  \"\\x58\\x0F\\x8E\\x92\\x5D\\xCB\\x03\\x20\\x6A\\x08\\x32\\xE3\\xCF\\x95\\x6D\\x44\",\n\t  /* Count = 40, V = FFFFFFFFFF8000000000000000000000\n\t\t\t\t\t R = 1F6CB3420F701353B16464869FD9777B */\n\t  \"\\x1F\\x6C\\xB3\\x42\\x0F\\x70\\x13\\x53\\xB1\\x64\\x64\\x86\\x9F\\xD9\\x77\\x7B\",\n\t  /* Count = 41, V = FFFFFFFFFFC000000000000000000000\n\t\t\t\t\t R = 003130793596F2B1E2D5BDE2B48AE312 */\n\t  \"\\x00\\x31\\x30\\x79\\x35\\x96\\xF2\\xB1\\xE2\\xD5\\xBD\\xE2\\xB4\\x8A\\xE3\\x12\",\n\t  /* Count = 42, V = FFFFFFFFFFE000000000000000000000\n\t\t\t\t\t R = 267B9B7EF90A732F836DE5B95DC3C5AB */\n\t  \"\\x26\\x7B\\x9B\\x7E\\xF9\\x0A\\x73\\x2F\\x83\\x6D\\xE5\\xB9\\x5D\\xC3\\xC5\\xAB\",\n\t  /* Count = 43, V = FFFFFFFFFFF000000000000000000000\n\t\t\t\t\t R = F41155BEE8AF3EE58E9DAE215F8CD565 */\n\t  \"\\xF4\\x11\\x55\\xBE\\xE8\\xAF\\x3E\\xE5\\x8E\\x9D\\xAE\\x21\\x5F\\x8C\\xD5\\x65\",\n\t  /* Count = 44, V = FFFFFFFFFFF800000000000000000000\n\t\t\t\t\t R = E5EAC38320CE55F8A2AA8BA80D2A1814 */\n\t  \"\\xE5\\xEA\\xC3\\x83\\x20\\xCE\\x55\\xF8\\xA2\\xAA\\x8B\\xA8\\x0D\\x2A\\x18\\x14\",\n\t  /* Count = 45, V = FFFFFFFFFFFC00000000000000000000\n\t\t\t\t\t R = 762D7889797C3DE5CC043E7A523D4355 */\n\t  \"\\x76\\x2D\\x78\\x89\\x79\\x7C\\x3D\\xE5\\xCC\\x04\\x3E\\x7A\\x52\\x3D\\x43\\x55\",\n\t  /* Count = 46, V = FFFFFFFFFFFE00000000000000000000\n\t\t\t\t\t R = 07EABC9D857245EB77703C4C8A37A07A */\n\t  \"\\x07\\xEA\\xBC\\x9D\\x85\\x72\\x45\\xEB\\x77\\x70\\x3C\\x4C\\x8A\\x37\\xA0\\x7A\",\n\t  /* Count = 47, V = FFFFFFFFFFFF00000000000000000000\n\t\t\t\t\t R = EE442D216C2BCA9056F2841A302BC7DB */\n\t  \"\\xEE\\x44\\x2D\\x21\\x6C\\x2B\\xCA\\x90\\x56\\xF2\\x84\\x1A\\x30\\x2B\\xC7\\xDB\",\n\t  /* Count = 48, V = FFFFFFFFFFFF80000000000000000000\n\t\t\t\t\t R = 8C6D73BD41AF6120D542E0B96262C090 */\n\t  \"\\x8C\\x6D\\x73\\xBD\\x41\\xAF\\x61\\x20\\xD5\\x42\\xE0\\xB9\\x62\\x62\\xC0\\x90\",\n\t  /* Count = 49, V = FFFFFFFFFFFFC0000000000000000000\n\t\t\t\t\t R = 6D6E205A2525666E46AE794096FF27E0 */\n\t  \"\\x6D\\x6E\\x20\\x5A\\x25\\x25\\x66\\x6E\\x46\\xAE\\x79\\x40\\x96\\xFF\\x27\\xE0\",\n\t  /* Count = 50, V = FFFFFFFFFFFFE0000000000000000000\n\t\t\t\t\t R = EAF9559B192A779CD5381802A07BE6E9 */\n\t  \"\\xEA\\xF9\\x55\\x9B\\x19\\x2A\\x77\\x9C\\xD5\\x38\\x18\\x02\\xA0\\x7B\\xE6\\xE9\",\n\t  /* Count = 51, V = FFFFFFFFFFFFF0000000000000000000\n\t\t\t\t\t R = 8C611A402887C46010E3CD979708B225 */\n\t  \"\\x8C\\x61\\x1A\\x40\\x28\\x87\\xC4\\x60\\x10\\xE3\\xCD\\x97\\x97\\x08\\xB2\\x25\",\n\t  /* Count = 52, V = FFFFFFFFFFFFF8000000000000000000\n\t\t\t\t\t R = A83310B018994CBC81C7BC021F4D4258 */\n\t  \"\\xA8\\x33\\x10\\xB0\\x18\\x99\\x4C\\xBC\\x81\\xC7\\xBC\\x02\\x1F\\x4D\\x42\\x58\",\n\t  /* Count = 53, V = FFFFFFFFFFFFFC000000000000000000\n\t\t\t\t\t R = 2BB0F59C40204AC4538B9857F90F89FB */\n\t  \"\\x2B\\xB0\\xF5\\x9C\\x40\\x20\\x4A\\xC4\\x53\\x8B\\x98\\x57\\xF9\\x0F\\x89\\xFB\",\n\t  /* Count = 54, V = FFFFFFFFFFFFFE000000000000000000\n\t\t\t\t\t R = 1FD58C060D2AC2A47A054D9E61CEFE23 */\n\t  \"\\x1F\\xD5\\x8C\\x06\\x0D\\x2A\\xC2\\xA4\\x7A\\x05\\x4D\\x9E\\x61\\xCE\\xFE\\x23\",\n\t  /* Count = 55, V = FFFFFFFFFFFFFF000000000000000000\n\t\t\t\t\t R = 8C609188F847C46AE07212FB7F72B237 */\n\t  \"\\x8C\\x60\\x91\\x88\\xF8\\x47\\xC4\\x6A\\xE0\\x72\\x12\\xFB\\x7F\\x72\\xB2\\x37\",\n\t  /* Count = 56, V = FFFFFFFFFFFFFF800000000000000000\n\t\t\t\t\t R = 9C8377288804E9C72487A23CCA4F1847 */\n\t  \"\\x9C\\x83\\x77\\x28\\x88\\x04\\xE9\\xC7\\x24\\x87\\xA2\\x3C\\xCA\\x4F\\x18\\x47\",\n\t  /* Count = 57, V = FFFFFFFFFFFFFFC00000000000000000\n\t\t\t\t\t R = 2CA0336293178A7B1E3EECB073722FD9 */\n\t  \"\\x2C\\xA0\\x33\\x62\\x93\\x17\\x8A\\x7B\\x1E\\x3E\\xEC\\xB0\\x73\\x72\\x2F\\xD9\",\n\t  /* Count = 58, V = FFFFFFFFFFFFFFE00000000000000000\n\t\t\t\t\t R = 522FA2D0681B68C0409F14A7BBC10F35 */\n\t  \"\\x52\\x2F\\xA2\\xD0\\x68\\x1B\\x68\\xC0\\x40\\x9F\\x14\\xA7\\xBB\\xC1\\x0F\\x35\",\n\t  /* Count = 59, V = FFFFFFFFFFFFFFF00000000000000000\n\t\t\t\t\t R = 68BD7966A4B327BA5CD7454B71473441 */\n\t  \"\\x68\\xBD\\x79\\x66\\xA4\\xB3\\x27\\xBA\\x5C\\xD7\\x45\\x4B\\x71\\x47\\x34\\x41\",\n\t  /* Count = 60, V = FFFFFFFFFFFFFFF80000000000000000\n\t\t\t\t\t R = 67B5ED9CCC8849E20ED1339CF527CF31 */\n\t  \"\\x67\\xB5\\xED\\x9C\\xCC\\x88\\x49\\xE2\\x0E\\xD1\\x33\\x9C\\xF5\\x27\\xCF\\x31\",\n\t  /* Count = 61, V = FFFFFFFFFFFFFFFC0000000000000000\n\t\t\t\t\t R = A58EA39069A3F84D5F5F30B3D42269F1 */\n\t  \"\\xA5\\x8E\\xA3\\x90\\x69\\xA3\\xF8\\x4D\\x5F\\x5F\\x30\\xB3\\xD4\\x22\\x69\\xF1\",\n\t  /* Count = 62, V = FFFFFFFFFFFFFFFE0000000000000000\n\t\t\t\t\t R = 11EE2C950E9B942D5A2D6BF9A0CCE85C */\n\t  \"\\x11\\xEE\\x2C\\x95\\x0E\\x9B\\x94\\x2D\\x5A\\x2D\\x6B\\xF9\\xA0\\xCC\\xE8\\x5C\",\n\t  /* Count = 63, V = FFFFFFFFFFFFFFFF0000000000000000\n\t\t\t\t\t R = A704BA2BD785A1D3F9E97F58E93D6A53 */\n\t  \"\\xA7\\x04\\xBA\\x2B\\xD7\\x85\\xA1\\xD3\\xF9\\xE9\\x7F\\x58\\xE9\\x3D\\x6A\\x53\"\n\t  /* The test vectors continue for another 64 values to cover all 128\n\t     bits of V, there's no obvious benefit to running through them all \n\t\t (just the first two values are enough, one to cover the RNG itself \n\t\t and the second to make sure the V update is working) so we stop at \n\t\t 64 values */\n\t}\n#endif /* Different test vectors */\n\t};\n\n/* Helper functions to output the test data in the format required for the\n   FIPS eval */\n\n#if ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\nstatic void printVector( const char *description, const BYTE *data )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tprintf( \"%s = \", description );\n\tLOOP_SMALL( i = 0, i < 8, i++ )\n\t\tprintf( \"%02x\", data[ i ] );\n\tENSURES( LOOP_BOUND_OK );\n\tputchar( '\\n' );\n\t}\n\nstatic void printVectors( const BYTE *key, const BYTE *dt, const BYTE *v,\n\t\t\t\t\t\t  const BYTE *r, const int count )\n\t{\n\tprintf( \"COUNT = %d\\n\", count );\n\tprintVector( \"Key1\", key );\n\tprintVector( \"Key2\", key + 8 );\n\tprintVector( \"DT\", dt );\n\tprintVector( \"V\", v );\n\tprintVector( \"R\", r );\n\t}\n#endif /* FIPS eval data output */\n\n/* Self-test code for the two crypto algorithms that are used for random\n   number generation.  The self-test of these two algorithms is performed\n   every time the randomness subsystem is initialised.  Note that the same\n   tests have already been performed as part of the startup self-test but\n   we perform them again here for the benefit of the randomness subsystem,\n   which doesn't necessarily trust (or even know about) the startup self-\n   test */\n\n#if defined( INC_ALL )\n  #include \"capabil.h\"\n#else\n  #include \"device/capabil.h\"\n#endif /* Compiler-specific includes */\n\nCHECK_RETVAL \\\nint randomAlgorithmSelfTest( void )\n\t{\n\tconst CAPABILITY_INFO *capabilityInfo;\n\tint status;\n\n\t/* Test the hash algorithm functionality */\n#ifdef USE_SHA1_PRNG\n\tcapabilityInfo = getSHA1Capability();\n#else\n\tcapabilityInfo = getSHA2Capability();\n#endif /* USE_SHA1_PRNG */\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Test the encryption algorithm functionality */\n#ifdef USE_3DES_X917\n\tcapabilityInfo = get3DESCapability();\n#else\n\tcapabilityInfo = getAESCapability();\n#endif /* USE_3DES_X917 */\n\tstatus = capabilityInfo->selfTestFunction();\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Test the X9.17 generator */\n\n#if defined( USE_SHA1_PRNG )\t/* SHA-1 + 3DES */\n  #define PRNG_OUTPUT_STEP1\t\"\\xF0\\x8D\\xD4\\xDE\\xFA\\x2C\\x80\\x11\"\n  #define PRNG_OUTPUT_STEP2\t\"\\xA0\\xA9\\x4E\\xEC\\xCD\\xD9\\x28\\x7F\"\n  #define PRNG_OUTPUT_STEP3\t\"\\x70\\x82\\x64\\xED\\x83\\x88\\x40\\xE4\"\n#elif defined( USE_3DES_X917 )\t/* SHA-2 + 3DES */\n  #define PRNG_OUTPUT_STEP1\t\"\\x7F\\x93\\x4E\\x84\\x3B\\x79\\xB3\\x96\"\n  #define PRNG_OUTPUT_STEP2\t\"\\x43\\xD5\\x6A\\x6D\\x97\\x71\\xA8\\x12\"\n  #define PRNG_OUTPUT_STEP3\t\"\\xAE\\xEF\\x82\\x6F\\xC1\\x5B\\x44\\xAF\"\n#else\t\t\t\t\t\t\t/* SHA-2 + AES */\n  #define PRNG_OUTPUT_STEP1\t\"\\x8A\\xB2\\x91\\x01\\x94\\x33\\x5C\\x51\\xB6\\x44\\x15\\x42\\xA7\\x4B\\x1D\\xFE\"\n  #define PRNG_OUTPUT_STEP2\t\"\\xDB\\x5B\\xB2\\xA0\\xEE\\xCB\\xA6\\x4B\\xEE\\x85\\x8C\\xEA\\xF7\\xCA\\x13\\x74\"\n  #define PRNG_OUTPUT_STEP3\t\"\\x02\\x86\\x91\\x4C\\xB8\\x61\\x2C\\xA5\\xA7\\xEB\\xD7\\x34\\x5F\\x3C\\x17\\x38\"\n#endif /* SHA-1 vs. SHA-2 PRNG */\n\nCHECK_RETVAL \\\nint selfTestX917( INOUT RANDOM_INFO *testRandomInfo, \n\t\t\t\t  IN_BUFFER_C( X917_KEYSIZE ) const BYTE *key )\n\t{\n\tBYTE buffer[ X917_BLOCKSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( testRandomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isReadPtr( key, X917_KEYSIZE ) );\n\n\t/* Check that the ANSI X9.17 PRNG is working correctly */\n\tmemset( buffer, 0, 16 );\n\tstatus = setKeyX917( testRandomInfo, key, key + X917_KEYSIZE, NULL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = generateX917( testRandomInfo, buffer, X917_BLOCKSIZE );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( buffer, PRNG_OUTPUT_STEP1, X917_BLOCKSIZE ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = generateX917( testRandomInfo, buffer, X917_BLOCKSIZE );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( buffer, PRNG_OUTPUT_STEP2, X917_BLOCKSIZE ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = generateX917( testRandomInfo, buffer, X917_BLOCKSIZE );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( buffer, PRNG_OUTPUT_STEP3, X917_BLOCKSIZE ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\n\treturn( status );\n\t}\n\n#if !defined( CONFIG_SLOW_CPU )\n\nCHECK_RETVAL \\\nstatic int fipsTest( INOUT RANDOM_INFO *testRandomInfo,\n\t\t\t\t\t const BOOLEAN isX931 )\n\t{\n\tBYTE keyBuffer[ X917_KEYSIZE + 8 ],  buffer[ X917_BLOCKSIZE + 8 ];\n\tBYTE V[ X917_BLOCKSIZE + 8 ], DT[ X917_BLOCKSIZE + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( testRandomInfo, sizeof( RANDOM_INFO ) ) );\n\n\tREQUIRES( isX931 == TRUE || isX931 == FALSE );\n\n\t/* Run through the tests twice, once using the X9.17 interpretation and \n\t   a second time using the X9.31 interpretation */\n\tmemcpy( V, x917VSTdata.initV, X917_BLOCKSIZE );\n\tmemcpy( DT, x917VSTdata.initDT, X917_BLOCKSIZE );\n\tLOOP_EXT( i = 0, i < VST_ITERATIONS, i++, VST_ITERATIONS + 1 )\n\t\t{\n\t\tint j, LOOP_ITERATOR_ALT;\n\n\t\tinitRandomPool( testRandomInfo );\n\t\tmemcpy( keyBuffer, x917VSTdata.key, X917_KEYSIZE );\n\t\tmemcpy( buffer, DT, X917_BLOCKSIZE );\n\t\tstatus = setKeyX917( testRandomInfo, keyBuffer, V, \\\n\t\t\t\t\t\t\t isX931 ? DT : NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = generateX917( testRandomInfo, buffer, X917_BLOCKSIZE );\n#if ( RNG_TEST_VALUES != RNG_TEST_FIPSEVAL )\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tmemcmp( buffer, x917VSTdata.R[ i ], X917_BLOCKSIZE ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n#endif /* FIPS eval data output */\n\t\tendRandomPool( testRandomInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\tretIntError();\n#if ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\t\tif( isX931 )\n\t\t\t{\n\t\t\tprintVectors( x917VSTdata.key, DT, V, buffer, i );\n\t\t\tputchar( '\\n' );\n\t\t\t}\n#endif /* FIPS eval data output */\n\n\t\t/* V = V >> 1, shifting in 1 bits; DT = DT + 1 */\n\t\tLOOP_EXT_ALT( j = X917_BLOCKSIZE - 1, j > 0, j--, \n\t\t\t\t\t   X917_BLOCKSIZE )\n\t\t\t{\n\t\t\tif( V[ j - 1 ] & 1 )\n\t\t\t\tV[ j ] = intToByte( ( V[ j ] >> 1 ) | 0x80 );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tV[ 0 ] = intToByte( ( V[ 0 ] >> 1 ) | 0x80 );\n\t\tLOOP_EXT_ALT( j = X917_BLOCKSIZE - 1, j >= 0, j--, \n\t\t\t\t\t  X917_BLOCKSIZE )\n\t\t\t{\n\t\t\tDT[ j ]++;\n\t\t\tif( DT[ j ] != 0 )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* Slower CPUs */\n\nCHECK_RETVAL \\\nint fipsTestX917( INOUT RANDOM_INFO *testRandomInfo )\n\t{\n\t/* The following tests can take quite some time on slower CPUs because\n\t   they're iterated tests so we only run them if we can assume that \n\t   there's a reasonably fast CPU present */\n#if !defined( CONFIG_SLOW_CPU )\n\tBYTE keyBuffer[ X917_KEYSIZE + 8 ];\n\tBYTE buffer[ X917_BLOCKSIZE + 8 ];\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( testRandomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* Check the ANSI X9.17 PRNG again, this time using X9.31 test vectors.\n\t   These aren't test vectors from X9.31 but vectors used to certify an \n\t   X9.17 generator when run in X9.31 mode (we actually run the test \n\t   twice, once in X9.17 seed-via-DT mode and once in X9.31 seed-via-V \n\t   mode).  We have to do this after the above test since they're run as \n\t   a linked series of tests going from the lowest-level cryptlib and \n\t   ANSI PRNGs to the top-level overall random number generation system.  \n\t   Inserting this test in the middle would upset the final result \n\t   values */\n\tinitRandomPool( testRandomInfo );\n\tmemcpy( keyBuffer, x917MCTdata.key, X917_KEYSIZE );\n\tmemset( buffer, 0, X917_BLOCKSIZE );\n\tstatus = setKeyX917( testRandomInfo, keyBuffer, x917MCTdata.V,\n\t\t\t\t\t\t x917MCTdata.DT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tLOOP_EXT( i = 0, cryptStatusOK( status ) && i < 10000, i++, 10001 )\n\t\t\t{\n\t\t\ttestRandomInfo->x917Count = 0;\n\t\t\tstatus = generateX917( testRandomInfo, buffer, X917_BLOCKSIZE );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n#if ( RNG_TEST_VALUES != RNG_TEST_FIPSEVAL )\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( buffer, x917MCTdata.R, X917_BLOCKSIZE ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n#endif /* FIPS eval data output */\n\tif( cryptStatusError( status ) )\n\t\tretIntError();\n\tendRandomPool( testRandomInfo );\n#if ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\tprintf( \"[X9.31]\\n[2-Key TDES]\\n\\n\" );\n\tprintVectors( x917MCTdata.key, x917MCTdata.DT, x917MCTdata.V, buffer, 0 );\n\tprintf( \"\\n\\n[X9.31]\\n[2-Key TDES]\\n\\n\" );\n#endif /* FIPS eval data output */\n\tstatus = fipsTest( testRandomInfo, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = fipsTest( testRandomInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#if ( RNG_TEST_VALUES == RNG_TEST_FIPSEVAL )\n\t/* Since this is run as a background thread we need to flush the output \n\t   before the thread terminates, otherwise it'll be discarded */\n\tfflush( stdout );\n#endif /* FIPS eval data output */\n#endif /* Slower CPUs */\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_NO_SELFTEST */\n"
  },
  {
    "path": "deps/cl345/random/random.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Randomness Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The random pool handling code in this module and the other modules in the\n   /random subdirectory represent the cryptlib continuously seeded\n   pseudorandom number generator (CSPRNG) as described in my 1998 Usenix\n   Security Symposium paper \"The generation of practically strong random\n   numbers\".\n\n   The CSPRNG code is copyright Peter Gutmann (and various others) 1995-2004\n   all rights reserved.  Redistribution of the CSPRNG modules and use in\n   source and binary forms, with or without modification, are permitted\n   provided that the following BSD-style license conditions are met:\n\n   1. Redistributions of source code must retain the above copyright notice\n\t  and this permission notice in its entirety.\n\n   2. Redistributions in binary form must reproduce the copyright notice in\n\t  the documentation and/or other materials provided with the distribution.\n\n   3. A copy of any bugfixes or enhancements made must be provided to the\n\t  author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the\n\t  baseline version of the code.\n\n   ALTERNATIVELY, the code may be distributed under the terms of the GNU\n   General Public License, version 2 or any later version published by the\n   Free Software Foundation, in which case the provisions of the GNU GPL are\n   required INSTEAD OF the above restrictions.\n\n   ALTERNATIVELY ALTERNATIVELY, the code may be distributed under the terms \n   of the GNU Library/Lesser General Public License, version 2 or any later \n   version published by the Free Software Foundation, in which case the \n   provisions of the GNU LGPL are required INSTEAD OF the above restrictions.\n\n   Although not required under the terms of the GPL or LGPL, it would still \n   be nice if you could make any changes available to the author to allow a\n   consistent code base to be maintained */\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #ifdef CONFIG_RANDSEED\n\t#include \"stream.h\"\n  #endif /* CONFIG_RANDSEED */\n  #include \"random_int.h\"\n#else\n  #include \"crypt.h\"\n  #ifdef CONFIG_RANDSEED\n\t#include \"io/stream.h\"\n  #endif /* CONFIG_RANDSEED */\n  #include \"random/random_int.h\"\n#endif /* Compiler-specific includes */\n\n/* If we don't have a defined randomness interface, complain */\n\n#if !( defined( __Android__ ) || defined( __BEOS__ ) || \\\n\t   defined( __ECOS__ ) || defined( __embOS__ ) || \\\n\t   defined( __IBM4758__ ) || defined( __iOS__ ) || \\\n\t   defined( __MAC__ ) || defined( __MGOS__ ) || \\\n\t   defined( __MSDOS__ ) || defined( __MQXRTOS__ ) || \\\n\t   defined( __MVS__ ) || defined( __Nucleus__ ) || \\\n\t   defined( __OS2__ ) || defined( __OSEK__ ) || \\\n\t   defined( __PALMOS__ ) || defined( __Quadros__ ) || \\\n\t   defined( __SMX__ ) || defined( __TANDEM_NSK__ ) || \\\n\t   defined( __TANDEM_OSS__ ) || defined( __Telit__ ) || \\\n\t   defined( __ThreadX__ ) || defined( __UNIX__ ) || \\\n\t   defined( __VMCMS__ ) || defined( __VxWorks__ ) || \\\n\t   defined( __WIN16__ ) || defined( __WIN32__ ) || \\\n\t   defined( __WINCE__ ) || defined( __XMK__ ) )\n  #error You need to create OS-specific randomness-gathering functions in random/<os-name>.c\n#endif /* Various OS-specific defines */\n\n/* If we're using stored seed data, make sure that the seed quality setting\n   is in order */\n\n#ifdef CONFIG_RANDSEED\n  #ifndef CONFIG_RANDSEED_QUALITY\n\t/* If the user hasn't provided a quality estimate, default to 95.  This\n\t   isn't necessarily because the quality is that good, but because many\n\t   embedded systems provide so little entropy that setting it to \n\t   anything less then 95 would result in us never reaching the required \n\t   entropy level.  This isn't as arbitrary as it seems because the seed-\n\t   file entropy is in theory 100 since it's meant to be produced from a\n\t   cryptographically strong source, the use of a non-100 value is just\n\t   to force an entropy poll if the user hasn't performed one */\n\t#define CONFIG_RANDSEED_QUALITY\t\t95\n  #endif /* !CONFIG_RANDSEED_QUALITY */\n  #if ( CONFIG_RANDSEED_QUALITY < 10 ) || ( CONFIG_RANDSEED_QUALITY > 100 )\n\t#error CONFIG_RANDSEED_QUALITY must be between 10 and 100\n  #endif /* CONFIG_RANDSEED_QUALITY check */\n\n  /* Forward declaration for the add-data function */\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  static void addStoredSeedData( INOUT RANDOM_INFO *randomInfo );\n#endif /* CONFIG_RANDSEED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRandomness Interface Definitions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* In order to avoid the pool startup problem (where initial pool data may\n   consist of minimally-mixed entropy samples) we require that the pool be\n   mixed at least the following number of times before we can draw data from\n   it.  This usually happens automatically because a slow poll adds enough\n   data to cause many mixing iterations, however if this doesn't happen we\n   manually mix it the appropriate number of times to get it up to the\n   correct level */\n\n#define RANDOMPOOL_MIXES\t\t10\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the randomness state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckRandom( const RANDOM_INFO *randomInfo )\n\t{\n\tassert( isReadPtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* Check the pool index information.  The pool index can briefly become \n\t   the same as RANDOMPOOL_SIZE if we've filled the pool and we've about \n\t   to mix it */\n\tif( randomInfo->randomPoolPos < 0 || \\\n\t\trandomInfo->randomPoolPos > RANDOMPOOL_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: Pool position\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check the pool accounting information */\n\tif( randomInfo->randomQuality < 0 || randomInfo->randomQuality > 100 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: Quality\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( randomInfo->randomPoolMixes < 0 || \\\n\t\trandomInfo->randomPoolMixes > RANDOMPOOL_MIXES )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckRandom: Mix count\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Checksum the randomness state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN checksumRandomPool( INOUT RANDOM_INFO *randomInfo )\n\t{\n\tconst int oldChecksum = randomInfo->checksum;\n\tint newChecksum;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\trandomInfo->checksum = 0;\n\tnewChecksum = checksumData( randomInfo, sizeof( RANDOM_INFO ) );\n\trandomInfo->checksum = newChecksum;\n\n\treturn( ( oldChecksum == newChecksum ) ? TRUE : FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRandom Pool Management Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and shut down the random pool */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initRandomPool( OUT RANDOM_INFO *randomInfo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\tmemset( randomInfo, 0, sizeof( RANDOM_INFO ) );\n\tstatus = initX917( randomInfo );\n\tREQUIRES_V( cryptStatusOK( status ) );\n\t( void ) checksumRandomPool( randomInfo );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endRandomPool( INOUT RANDOM_INFO *randomInfo )\n\t{\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\tzeroise( randomInfo, sizeof( RANDOM_INFO ) );\n\t}\n\n/* Stir up the data in the random pool.  Given a circular buffer of length n\n   bytes, a buffer position p, and a hash output size of h bytes, we hash\n   bytes from p - h...p - 1 (to provide chaining across previous hashes) and\n   p...p + 64 (to have as much surrounding data as possible affect the\n   current data).  Then we move on to the next h bytes until all n bytes have\n   been mixed.  See \"Cryptographic Security Architecture Design and \n   Implementation\" for the full details of the PRNG design */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int mixRandomPool( INOUT RANDOM_INFO *randomInfo )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE dataBuffer[ CRYPT_MAX_HASHSIZE + 64 + 8 ];\n\tint hashSize, hashIndex, LOOP_ITERATOR;\n\tORIGINAL_INT_VAR( randomPoolMixes, randomInfo->randomPoolMixes );\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\n\tgetHashAtomicParameters( PRNG_ALGO, 0, &hashFunctionAtomic, &hashSize );\n\n\t/* Stir up the entire pool.  We can't check the return value of the\n\t   hashing call because there isn't one, however the hashing code has \n\t   gone through a self-test when the randomness subsystem was \n\t   initialised */\n\tLOOP_MED( hashIndex = 0, hashIndex < RANDOMPOOL_SIZE, hashIndex += hashSize )\n\t\t{\n\t\tint dataBufIndex, poolIndex, LOOP_ITERATOR_ALT;\n\n\t\t/* Precondition: We're processing hashSize bytes at a time */\n\t\tREQUIRES( hashIndex % hashSize == 0 );\n\n\t\t/* If we're at the start of the pool then the first block that we hash\n\t\t   is at the end of the pool, otherwise it's the block immediately\n\t\t   preceding the current one */\n\t\tpoolIndex = ( hashIndex >= hashSize ) ? \\\n\t\t\t\t\thashIndex - hashSize : RANDOMPOOL_SIZE - hashSize;\n\t\tENSURES( poolIndex >= 0 && poolIndex <= RANDOMPOOL_SIZE - hashSize );\n\n\t\t/* Copy data from position p - hashSize... p + 64 in the circular \n\t\t   pool into the hash data buffer:\n\n\t\t\t\tpoolIndex\n\t\t\t\t\t| hashIndex\n\t\t\t\t\tv\tv\n\t\t\t--------+---+-----------------------+---------\n\t\t\t\t\t| hS|\t\t\t64\t\t\t|\t\t\tPool\n\t\t\t--------+---+-----------------------+---------\n\t\t\t\t\t|\t\t\t\t\t\t\t|\n\t\t\t\t\t+---------------------------+\n\t\t\t\t\t|\t\t\t\t\t\t\t|\t\t\tBuffer\n\t\t\t\t\t+---------------------------+\n\t\t\t\t\t \\\t\t\t\t\t\t\t/\n\t\t\t\t\t  \\\tHash  ------------------\t\n\t\t\t\t\t   \\\t /\n\t\t\t------------+---+-----------------------------\n\t\t\t\t\t\t| hS|\t\t\t\t\t\t\t\tPool'\n\t\t\t------------+---+----------------------------- \n\t\t\t\t\t^\t^\t\t\t\t\t\t^\n\t\t\t\t\t|\t|\t\t\t\t\t\t|\n\t\t\t\t   p-h\tp\t\t\t\t\t  p+64 */\n\t\tLOOP_EXT_ALT( dataBufIndex = 0, dataBufIndex < hashSize + 64,\n\t\t\t\t\t  dataBufIndex++, CRYPT_MAX_HASHSIZE + 64 + 1 )\n\t\t\t{\n\t\t\tdataBuffer[ dataBufIndex ] = randomInfo->randomPool[ poolIndex ];\n\t\t\tpoolIndex = ( poolIndex + 1 ) % RANDOMPOOL_SIZE;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\n\t\t/* Postconditions for the state data copy: We got hashSize + 64 bytes \n\t\t   surrounding the current pool position */\n\t\tENSURES( dataBufIndex == hashSize + 64 );\n\n\t\t/* Hash the data in the circular pool, depositing the result at position \n\t\t   p...p + hashSize */\n\t\thashFunctionAtomic( randomInfo->randomPool + hashIndex,\n\t\t\t\t\t\t\tRANDOMPOOL_ALLOCSIZE - hashIndex, \n\t\t\t\t\t\t\tdataBuffer, dataBufIndex );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tzeroise( dataBuffer, CRYPT_MAX_HASHSIZE + 64 );\n\n\t/* Postconditions for the pool mixing: The entire pool was mixed and\n\t   temporary storage was cleared */\n\tENSURES( hashIndex >= RANDOMPOOL_SIZE );\n\tFORALL( i, 0, CRYPT_MAX_HASHSIZE + 64,\n\t\t\tdataBuffer[ i ] == 0 );\n\n\t/* Increment the mix count and move the write position back to the start\n\t   of the pool */\n\tif( randomInfo->randomPoolMixes < RANDOMPOOL_MIXES )\n\t\trandomInfo->randomPoolMixes++;\n\trandomInfo->randomPoolPos = 0;\n\n\t/* Postconditions for the status update: We mixed the pool at least\n\t   once, and we're back at the start of the pool */\n\tENSURES( randomInfo->randomPoolMixes == RANDOMPOOL_MIXES || \\\n\t\t\t randomInfo->randomPoolMixes == \\\n\t\t\t\t\t\t\tORIGINAL_VALUE( randomPoolMixes ) + 1 );\n\tENSURES( randomInfo->randomPoolPos == 0 );\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Random Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a block of random data from the randomness pool in such a way that\n   compromise of the data doesn't compromise the pool and vice versa.  This \n   is done by performing the (one-way) pool mixing operation on the pool and\n   on a transformed version of the pool that becomes the key.  This \n   corresponds to the Barak-Halevi construction:\n\n\tr || s' = next( s );\n\ts' = refresh( s ^ new_state );\n\n   where 'r' is the generator output and 's' is the generator state.  The RNG\n   design here predates Barak-Halevi by about 10 years but the principle is\n   the same.\n   \n   The transformed version of the pool from which the output data will be \n   drawn is then further processed by running each 64-bit block through the \n   X9.17 generator.  As an additional precaution the output data is folded \n   in half to ensure that not even a hashed or encrypted form of the \n   previous contents is available.  No pool data ever leaves the pool.\n\n   This function performs a more paranoid version of the FIPS 140 continuous\n   tests on both the main pool contents and the X9.17 generator output to\n   detect stuck-at faults and short cycles in the output.  In addition the\n   higher-level message handler applies FIPS 140-like statistical tests to\n   the output and will retry the fetch if the output fails the tests.  This\n   additional step is performed at a higher level because it's then applied\n   to all randomness sources used by cryptlib and not just the built-in one.\n\n   Because the pool output is folded to mask the PRNG output, the output from \n   each round of mixing is only half the pool size, as defined below */\n\n#define RANDOM_OUTPUTSIZE\t( RANDOMPOOL_SIZE / 2 )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int tryGetRandomOutput( INOUT RANDOM_INFO *randomInfo,\n\t\t\t\t\t\t\t   INOUT RANDOM_INFO *exportedRandomInfo )\n\t{\n\tconst BYTE *samplePtr = randomInfo->randomPool;\n\tconst BYTE *x917SamplePtr = exportedRandomInfo->randomPool;\n\tunsigned long sample;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isWritePtr( exportedRandomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* Precondition: The pool is ready to go.  This check isn't so much to\n\t   confirm that this really is the case (it's already been checked\n\t   elsewhere) but to ensure that the two pool parameters haven't been\n\t   reversed.  The use of generic pools for all types of random output is\n\t   useful in terms of providing a nice abstraction, but less useful for\n\t   type safety */\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\tREQUIRES( randomInfo->randomQuality >= 100 && \\\n\t\t\t  randomInfo->randomPoolMixes >= RANDOMPOOL_MIXES && \\\n\t\t\t  randomInfo->x917Inited == TRUE );\n\tREQUIRES( exportedRandomInfo->randomQuality == 0 && \\\n\t\t\t  exportedRandomInfo->randomPoolMixes == 0 && \\\n\t\t\t  exportedRandomInfo->x917Inited == FALSE );\n\n\t/* Copy the contents of the main pool across to the export pool,\n\t   transforming it as we go by flipping all of the bits */\n\tLOOP_EXT( i = 0, i < RANDOMPOOL_ALLOCSIZE, i++, RANDOMPOOL_ALLOCSIZE + 1 )\n\t\t{\n\t\texportedRandomInfo->randomPool[ i ] = \\\n\t\t\t\t\tintToByte( randomInfo->randomPool[ i ] ^ 0xFF );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"copyPool\" );\n\n\t/* Postcondition for the bit-flipping: The two pools differ, and the\n\t   difference is in the flipped bits */\n\tENSURES( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,\n\t\t\t\t\t RANDOMPOOL_ALLOCSIZE ) );\n\tFORALL( i, 0, RANDOMPOOL_ALLOCSIZE, \\\n\t\t\trandomInfo->randomPool[ i ] == \\\n\t\t\t\t\t\t\t( exportedRandomInfo->randomPool[ i ] ^ 0xFF ) );\n\n\t/* Mix the original and export pools so that neither can be recovered\n\t   from the other */\n\tstatus = mixRandomPool( randomInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = mixRandomPool( exportedRandomInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendRandomPool( exportedRandomInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"mixRandomPool\" );\n\n\t/* Postcondition for the mixing: The two pools differ, and the difference\n\t   is more than just the bit flipping (this has a ~1e-14 chance of a false\n\t   positive, which should be safe) */\n\tENSURES( memcmp( randomInfo->randomPool, exportedRandomInfo->randomPool,\n\t\t\t\t\t RANDOMPOOL_ALLOCSIZE ) );\n\tENSURES( randomInfo->randomPool[ 0 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 0 ] ^ 0xFF ) ||\n\t\t\t randomInfo->randomPool[ 8 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 8 ] ^ 0xFF ) ||\n\t\t\t randomInfo->randomPool[ 16 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 16 ] ^ 0xFF ) ||\n\t\t\t randomInfo->randomPool[ 24 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 24 ] ^ 0xFF ) ||\n\t\t\t randomInfo->randomPool[ 32 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 32 ] ^ 0xFF ) ||\n\t\t\t randomInfo->randomPool[ 40 ] != \\\n\t\t\t\t\t( exportedRandomInfo->randomPool[ 40 ] ^ 0xFF ) );\n\n\t/* Precondition for sampling the output: It's a sample from the start of\n\t   the pool */\n\tENSURES( samplePtr == randomInfo->randomPool && \\\n\t\t\t x917SamplePtr == exportedRandomInfo->randomPool );\n\n\t/* Check for stuck-at faults by comparing a short sample from the current\n\t   output with samples from the previous RANDOMPOOL_SAMPLES outputs */\n\tsample = mgetLong( samplePtr );\n\tLOOP_EXT( i = 0, i < RANDOMPOOL_SAMPLES, i++, RANDOMPOOL_SAMPLES + 1 )\n\t\t{\n\t\tif( randomInfo->prevOutput[ i ] == sample )\n\t\t\t{\n\t\t\t/* We're repeating previous output, tell the caller to try\n\t\t\t   again */\n\t\t\tendRandomPool( exportedRandomInfo );\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"samplePool\" );\n\n\t/* Postcondition: There are no values seen during a previous run present\n\t   in the output */\n\tFORALL( i, 0, RANDOMPOOL_SAMPLES, \\\n\t\t\trandomInfo->prevOutput[ i ] != sample );\n\n\t/* Process the exported pool with the X9.17 generator */\n\tstatus = generateX917( randomInfo, exportedRandomInfo->randomPool,\n\t\t\t\t\t\t   RANDOMPOOL_ALLOCSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendRandomPool( exportedRandomInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"generateX917\" );\n\n\t/* Check for stuck-at faults in the X9.17 generator by comparing a short\n\t   sample from the current output with samples from the previous\n\t   RANDOMPOOL_SAMPLES outputs.  If it's the most recent sample then FIPS\n\t   140 requires an absolute failure if there's a duplicate rather than\n\t   simply signalling a problem and letting the higher layer handle it.\n\t   Because this will lead to false positives even for a perfect \n\t   generator we provide a custom check in which if we get a match in the \n\t   first 32 bits then we perform a backup check on the full \n\t   RANDOMPOOL_SAMPLE_SIZE bytes and return a hard failure if all of the \n\t   bits match.\n\n\t   There's an implied additional requirement in the sampling process in \n\t   which the zero'th iteration of the X9.17 generator doesn't have a \n\t   previous sample to compare to and therefore can't meet the \n\t   requirements for previous-sample checking, however this is handled by\n\t   having the generator cranked twice on init/reinit in \n\t   getRandomOutput(), which provides the necessary zero'th sample */\n\tsample = mgetLong( x917SamplePtr );\n\tLOOP_EXT( i = 0, i < RANDOMPOOL_SAMPLES, i++, RANDOMPOOL_SAMPLES + 1 )\n\t\t{\n\t\tif( randomInfo->x917PrevOutput[ i ] == sample )\n\t\t\t{\n\t\t\t/* If we've failed on the first sample and the full match also\n\t\t\t   fails, return a hard error */\n\t\t\tif( i == 0 && \\\n\t\t\t\t!memcmp( randomInfo->x917OuputSample,\n\t\t\t\t\t\t exportedRandomInfo->randomPool,\n\t\t\t\t\t\t RANDOMPOOL_SAMPLE_SIZE ) )\n\t\t\t\t{\n\t\t\t\tendRandomPool( exportedRandomInfo );\n\t\t\t\tretIntError();\n\t\t\t\t}\n\n\t\t\t/* We're repeating previous output, tell the caller to try\n\t\t\t   again */\n\t\t\tendRandomPool( exportedRandomInfo );\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"sampleX917\" );\n\n\t/* Postcondition: There are no values seen during a previous run present\n\t   in the output */\n\tFORALL( i, 0, RANDOMPOOL_SAMPLES, \\\n\t\t\trandomInfo->x917PrevOutput[ i ] != sample );\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"copyPool\", \"mixRandomPool\", \"samplePool\", \n\t\t\t\t\t\t\t\t\t\"generateX917\", \"sampleX917\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getRandomOutput( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\t\t\t\tOUT_BUFFER_FIXED( length ) BYTE *buffer, \n\t\t\t\t\t\t\tIN_RANGE( 1, RANDOM_OUTPUTSIZE ) const int length )\n\t{\n\tRANDOM_INFO exportedRandomInfo;\n\tBYTE *samplePtr;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint noRandomRetries, i, status, LOOP_ITERATOR;\n\tORIGINAL_INT_VAR( prevOutputIndex, randomInfo->prevOutputIndex );\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\tstatic_assert( RANDOM_OUTPUTSIZE == RANDOMPOOL_SIZE / 2, \\\n\t\t\t\t   \"Random pool size\" );\n\n\t/* Precondition for output quantity: We're being asked for a valid output\n\t   length and we're not trying to use more than half the pool contents.\n\t   Note that we've already checked that RANDOM_OUTPUTSIZE == \n\t   RANDOMPOOL_SIZE / 2 so we only check RANDOM_OUTPUTSIZE in the \n\t   REQUIRES() */\n\tREQUIRES( sanityCheckRandom( randomInfo ) );\n\tREQUIRES( length > 0 && length <= RANDOM_OUTPUTSIZE );\n\n\t/* If the X9.17 generator cryptovariables haven't been initialised yet\n\t   or have reached their use-by date, set the generator key and seed from\n\t   the pool contents, then mix the pool and crank the generator twice to\n\t   obscure the data that was used.  This also provides the zero'th sample\n\t   of output required by the FIPS 140 tests */\n\tif( !randomInfo->x917Inited || \\\n\t\trandomInfo->x917Count >= X917_MAX_CYCLES )\n\t\t{\n\t\tstatus = mixRandomPool( randomInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = setKeyX917( randomInfo, randomInfo->randomPool,\n\t\t\t\t\t\t\t\t randomInfo->randomPool + X917_KEYSIZE, \n\t\t\t\t\t\t\t\t NULL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = mixRandomPool( randomInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = generateX917( randomInfo, randomInfo->randomPool,\n\t\t\t\t\t\t\t\t   RANDOMPOOL_ALLOCSIZE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = mixRandomPool( randomInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = generateX917( randomInfo, randomInfo->randomPool,\n\t\t\t\t\t\t\t\t   RANDOMPOOL_ALLOCSIZE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tmemcpy( randomInfo->x917OuputSample, randomInfo->randomPool,\n\t\t\t\tRANDOMPOOL_SAMPLE_SIZE );\t/* Save zero'th output sample */\n\t\t}\n\tCFI_CHECK_UPDATE( \"generateX917\" );\n\n\t/* Precondition for drawing output from the generator: The pool is\n\t   sufficiently mixed, there's enough entropy present, and the X9.17\n\t   post-processor is ready for use */\n\tREQUIRES( randomInfo->randomPoolMixes == RANDOMPOOL_MIXES && \\\n\t\t\t  randomInfo->randomQuality >= 100 && randomInfo->x917Inited );\n\n\t/* Initialise the pool to contain the exported random data */\n\tinitRandomPool( &exportedRandomInfo );\n\tCFI_CHECK_UPDATE( \"initRandomPool\" );\n\n\t/* Try to obtain random data from the pool.  If the initial attempt to \n\t   get entropy fails, retry a fixed number of times */\n\tstatus = tryGetRandomOutput( randomInfo, &exportedRandomInfo );\n\tLOOP_EXT( noRandomRetries = 1, \n\t\t\t  status == OK_SPECIAL && \\\n\t\t\t\tnoRandomRetries < RANDOMPOOL_RETRIES, \n\t\t\t  noRandomRetries++, RANDOMPOOL_RETRIES + 1 )\n\t\t{\n\t\t/* Reset the random pool before we retry */\n\t\tinitRandomPool( &exportedRandomInfo );\n\t\tstatus = tryGetRandomOutput( randomInfo, &exportedRandomInfo );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We ran out of retries so that we're repeating the same output\n\t\t   data or there was some other type of error, fail */\n\t\tendRandomPool( &exportedRandomInfo );\n\n\t\t/* Postcondition: Nulla vestigia retrorsum */\n\t\tFORALL( i, 0, RANDOMPOOL_ALLOCSIZE, \\\n\t\t\t\texportedRandomInfo.randomPool[ i ] == 0 );\n\n\t\t/* We can't trust the pool data any more so we set its content\n\t\t   value to zero.  Ideally we should flash lights and sound\n\t\t   klaxons as well, this is a catastrophic failure */\n\t\trandomInfo->randomQuality = randomInfo->randomPoolMixes = 0;\n\t\trandomInfo->x917Inited = FALSE;\n\t\tretIntError();\n\t\t}\n\tCFI_CHECK_UPDATE( \"tryGetRandomOutput\" );\n\n\t/* Save a short sample from the current output for future checks */\n\tREQUIRES( randomInfo->prevOutputIndex >= 0 && \\\n\t\t\t  randomInfo->prevOutputIndex < RANDOMPOOL_SAMPLES );\n\tsamplePtr = randomInfo->randomPool;\n\trandomInfo->prevOutput[ randomInfo->prevOutputIndex ] = mgetLong( samplePtr );\n\tsamplePtr = exportedRandomInfo.randomPool;\n\trandomInfo->x917PrevOutput[ randomInfo->prevOutputIndex ] = mgetLong( samplePtr );\n\trandomInfo->prevOutputIndex = ( randomInfo->prevOutputIndex + 1 ) % \\\n\t\t\t\t\t\t\t\t  RANDOMPOOL_SAMPLES;\n\tmemcpy( randomInfo->x917OuputSample, exportedRandomInfo.randomPool,\n\t\t\tRANDOMPOOL_SAMPLE_SIZE );\n\tENSURES( randomInfo->prevOutputIndex != ORIGINAL_VALUE( prevOutputIndex ) );\n\tENSURES( randomInfo->prevOutputIndex == 0 || \\\n\t\t\t randomInfo->prevOutputIndex == ORIGINAL_VALUE( prevOutputIndex ) + 1 );\n\tENSURES( randomInfo->prevOutputIndex >= 0 && \\\n\t\t\t randomInfo->prevOutputIndex < RANDOMPOOL_SAMPLES );\n\tCFI_CHECK_UPDATE( \"samples\" );\n\n\t/* Copy the transformed data to the output buffer, folding it in half as\n\t   we go to mask the original content */\n\tLOOP_EXT( i = 0, i < length, i++, RANDOM_OUTPUTSIZE + 1 )\n\t\t{\n\t\tbuffer[ i ] = intToByte( exportedRandomInfo.randomPool[ i ] ^ \\\n\t\t\t\t\t\t\t\t exportedRandomInfo.randomPool[ RANDOM_OUTPUTSIZE + i ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tCFI_CHECK_UPDATE( \"copyPool\" );\n\n\t/* Postcondition: We drew at most half of the transformed output from the\n\t   export pool, and the output came from the export pool and not the main\n\t   pool */\n\tENSURES( i <= RANDOMPOOL_SIZE / 2 );\n\tEXISTS( i, 0, RANDOMPOOL_SIZE / 2, \\\n\t\t\tbuffer[ i ] != ( randomInfo->randomPool[ i ] ^ \\\n\t\t\t\t\t\t\t randomInfo->randomPool[ RANDOM_OUTPUTSIZE + i ] ) );\n\n\t/* Clean up */\n\tendRandomPool( &exportedRandomInfo );\n\tCFI_CHECK_UPDATE( \"endRandomPool\" );\n\n\t/* Postcondition: Nulla vestigia retrorsum */\n\tFORALL( i, 0, RANDOMPOOL_ALLOCSIZE, \\\n\t\t\texportedRandomInfo.randomPool[ i ] == 0 );\n\n\tENSURES( sanityCheckRandom( randomInfo ) );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"generateX917\", \"initRandomPool\", \n\t\t\t\t\t\t\t\t\t\"tryGetRandomOutput\", \"samples\", \n\t\t\t\t\t\t\t\t\t\"copyPool\", \"endRandomPool\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getRandomData( INOUT TYPECAST( RANDOM_INFO * ) void *randomInfoPtr, \n\t\t\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t\t   IN_RANGE( 1, MAX_RANDOM_BYTES ) const int length )\n\t{\n\tRANDOM_INFO *randomInfo = ( RANDOM_INFO * ) randomInfoPtr;\n\tBYTE *bufPtr = buffer;\n\tBOOLEAN randomInfoOK = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint randomQuality, count, retryCount = 0, iterationCount;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, length ) );\n\n\t/* Precondition: We're not asking for more data than the maximum that\n\t   should be needed */\n\tREQUIRES( length > 0 && length <= MAX_RANDOM_BYTES );\n\n\t/* Clear the return value and by extension make sure that we fail the\n\t   FIPS 140-like entropy tests on the output if there's a problem */\n\tzeroise( buffer, length );\n\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the random information is in order */\n\tif( sanityCheckRandom( randomInfo ) && checksumRandomPool( randomInfo ) )\n\t\trandomInfoOK = TRUE;\n\n\t/* If we're using a stored random seed, add it to the entropy pool if\n\t   necessary and update the random information checksum since the seed\n\t   update changes the pool state.  Note that we add the seed here rather \n\t   than when we initialise the randomness subsystem both because at that \n\t   point the stream subsystem may not be ready for use yet and because \n\t   there may be a requirement to periodically re-read the seed data if \n\t   it's changed by another process/task */\n#ifdef CONFIG_RANDSEED\n\tif( randomInfoOK && !randomInfo->seedProcessed )\n\t\t{\n\t\taddStoredSeedData( randomInfo );\n\t\t( void ) checksumRandomPool( randomInfo );\n\t\t}\n#endif /* CONFIG_RANDSEED */\n\n\t/* Get the randomness quality before we release the randomness info\n\t   again */\n\trandomQuality = randomInfo->randomQuality;\n\n\tkrnlExitMutex( MUTEX_RANDOM );\n\tCFI_CHECK_UPDATE( \"sanityCheckRandom\" );\n\n\t/* If there's a problem with the randomness information, don't try and\n\t   go any further */\n\tif( randomInfoOK != TRUE )\n\t\tretIntError();\n\n\t/* Perform a failsafe check to make sure that there's data available.\n\t   This should only ever be called once per application because after \n\t   the first blocking poll that occurs because the user has tried to\n\t   generate keying material without having first seeded the generator\n\t   the programmer of the calling application will make sure that \n\t   there's a slow poll done earlier on */\n\tif( randomQuality < 100 )\n\t\tslowPoll();\n\tCFI_CHECK_UPDATE( \"slowPoll\" );\n\n\t/* Make sure that any background randomness-gathering process has\n\t   finished */\n\tstatus = waitforRandomCompletion( FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"waitforRandomCompletion\" );\n\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Re-check the random information */\n\tif( !sanityCheckRandom( randomInfo ) || !checksumRandomPool( randomInfo ) )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\tretIntError();\n\t\t}\n\tCFI_CHECK_UPDATE( \"sanityCheckRandom\" );\n\n\t/* If we still can't get any random information, let the user know */\n\tif( randomInfo->randomQuality < 100 )\n\t\t{\n\t\tDEBUG_DIAG(( \"Insufficient random data available, only got %d out \"\n\t\t\t\t\t \"of 100\", randomInfo->randomQuality ));\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_RANDOM );\n\t\t}\n\n\t/* If the process has forked then we need to restart the generator \n\t   output process but we can't determine this until after we've already \n\t   produced the output.  If we do need to restart, we do it from this \n\t   point.\n\n\t   There is one variant of this problem that we can't work around and \n\t   that's where we're running inside a VM with rollback support.  Some \n\t   VMs can take periodic snapshots of the system state to allow rollback \n\t   to a known-good state if an error occurs.  Since the VM's rollback is \n\t   transparent to the OS there's no way to detect that this has \n\t   occcurred (although getSysVars() can detect the presence of some \n\t   common VMs it can't detect whether a rollback has occurred).  In this \n\t   case we'd roll back to a previous state of the RNG and continue from \n\t   there.  \n\t   \n\t   It's hard however to identify a situation in which this would pose a \n\t   serious threat.  Consider for example SSL/TLS or SSH session key \n\t   setup/generation: If we haven't committed the data to the remote \n\t   system yet it's no problem and if we have then we're now out of sync \n\t   with the remote system and the handshake will fail.  Similarly, if \n\t   we're generating a DSA signature then we'll end up generating the \n\t   same signature again but since it's over the same data there's no \n\t   threat involved.  Being able to cause a change in the data being \n\t   signed after the random DSA k value is generated would be a problem, \n\t   but k is only generated after the data has already been hashed and \n\t   the signature is about to be generated.\n\n\t   In general this type of attack would require cooperation between the \n\t   VM and a hostile external party to, for example, ignore the fact \n\t   that the VM has rolled back to an earlier point in the protocol so a \n\t   repeat of a previous handshake message will be seen.  In other words \n\t   it more or less requires control over the VM by an external party, and \n\t   anyone faced with this level of attack has bigger things to worry \n\t   about than RNG state rollback */\n\t( void ) forkCheck( FALSE );\nrestartPoint:\n\n\t/* Prepare to get data from the randomness pool.  Before we do this we\n\t   perform a final quick poll of the system to get any last bit of\n\t   entropy, and mix the entire pool.  If the pool hasn't been sufficiently\n\t   mixed, we iterate until we've reached the minimum mix count */\n\tLOOP_MAX( iterationCount = 0, \n\t\t\t  iterationCount < FAILSAFE_ITERATIONS_LARGE, \n\t\t\t  iterationCount++ )\n\t\t{\n\t\tDECLARE_ORIGINAL_INT( randomPoolMixes );\n\n\t\tfastPoll();\n\n\t\t/* Mix the pool after the fast poll.  The poll itself can result in \n\t\t   multiple sets of mixing, this final mix ensures that there's no\n\t\t   unmixed data left */\n\t\tSTORE_ORIGINAL_INT( randomPoolMixes, randomInfo->randomPoolMixes );\n\t\tstatus = mixRandomPool( randomInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) checksumRandomPool( randomInfo );\n\t\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES_KRNLMUTEX( randomInfo->randomPoolMixes == RANDOMPOOL_MIXES || \\\n\t\t\t\t\t\t   randomInfo->randomPoolMixes == \\\n\t\t\t\t\t\t\t\t\tORIGINAL_VALUE( randomPoolMixes ) + 1, \\\n\t\t\t\t\t\t   MUTEX_RANDOM );\n\n\t\t/* If the pool is sufficiently mixed, we're done */\n\t\tif( randomInfo->randomPoolMixes >= RANDOMPOOL_MIXES )\n\t\t\tbreak;\n\n\t\t/* Since the mixRandomPool() has changed the state of the pool, we \n\t\t   need to recalculate the checksum on the pool information before\n\t\t   the next call to fastPoll().  This is a bit of an unusual \n\t\t   situation because the fastPoll() is called from the current \n\t\t   thread with the pool mutex already held so there's no explicit\n\t\t   unlock/relock with an accompanying recalculation of the pool\n\t\t   checksum.  Because of this we have to explicitly recalculate it \n\t\t   here otherwise the next fastPoll() will detect apparent pool \n\t\t   corruption caused by the mixing */\n\t\t( void ) checksumRandomPool( randomInfo );\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_RANDOM );\n\tENSURES_KRNLMUTEX( iterationCount < FAILSAFE_ITERATIONS_LARGE, \\\n\t\t\t\t\t   MUTEX_RANDOM );\n\tCFI_CHECK_UPDATE( \"mixRandomPool\" );\n\n\t/* Keep producing RANDOMPOOL_OUTPUTSIZE bytes of output until the request\n\t   is satisfied */\n\tLOOP_MED( count = 0, count < length, count += RANDOM_OUTPUTSIZE )\n\t\t{\n\t\tconst int outputBytes = min( length - count, RANDOM_OUTPUTSIZE );\n\t\tORIGINAL_PTR( bufPtr );\n\n\t\t/* Precondition for output quantity: Either we're on the last output\n\t\t   block or we're producing the maximum-size output quantity, and\n\t\t   we're never trying to use more than half the pool contents */\n\t\tREQUIRES_KRNLMUTEX( length - count < RANDOM_OUTPUTSIZE || \\\n\t\t\t\t\t\t\toutputBytes == RANDOM_OUTPUTSIZE, MUTEX_RANDOM );\n\t\tREQUIRES_KRNLMUTEX( outputBytes <= RANDOMPOOL_SIZE / 2, \\\n\t\t\t\t\t\t\tMUTEX_RANDOM );\n\n\t\tstatus = getRandomOutput( randomInfo, bufPtr, outputBytes );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) checksumRandomPool( randomInfo );\n\t\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\t\treturn( status );\n\t\t\t}\n\t\tbufPtr += outputBytes;\n\n\t\t/* Postcondition: We're filling the output buffer and we wrote the\n\t\t   output to the correct portion of the output buffer */\n\t\tENSURES_KRNLMUTEX( ( bufPtr > ( BYTE * ) buffer ) && \\\n\t\t\t\t\t\t   ( bufPtr <= ( BYTE * ) buffer + length ),\n\t\t\t\t\t\t   MUTEX_RANDOM );\n\t\tENSURES_KRNLMUTEX( bufPtr == ORIGINAL_VALUE( bufPtr ) + outputBytes, \\\n\t\t\t\t\t\t   MUTEX_RANDOM );\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_RANDOM );\n\tCFI_CHECK_UPDATE( \"getRandomOutput\" );\n\n\t/* Postcondition: We filled the output buffer with the required amount\n\t   of output */\n\tENSURES_KRNLMUTEX( bufPtr == ( BYTE * ) buffer + length, MUTEX_RANDOM );\n\n\t/* Check whether the process forked while we were generating output.  If\n\t   it did, force a complete remix of the pool and restart the output\n\t   generation process (the fast poll will ensure that the pools in the\n\t   parent and child differ) */\n\tif( forkCheck( TRUE ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Process forked, restarting pool mixing\" ));\n\t\tREQUIRES_KRNLMUTEX( retryCount < 5, MUTEX_RANDOM );\n\n\t\t/* Reset the pool mix count and fix up the pool checksum */\n\t\trandomInfo->randomPoolMixes = 0;\n\t\t( void ) checksumRandomPool( randomInfo );\n\n\t\t/* Try again with the buffer contents */\n\t\tbufPtr = buffer;\n\t\tgoto restartPoint;\n\t\t}\n\n\t/* Recalculate the random information checksum after the changes that \n\t   we've made */\n\t( void ) checksumRandomPool( randomInfo );\n\tCFI_CHECK_UPDATE( \"checksumRandomPool\" );\n\n\tkrnlExitMutex( MUTEX_RANDOM );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_7( \"sanityCheckRandom\", \"slowPoll\", \n\t\t\t\t\t\t\t\t\t\"waitforRandomCompletion\", \n\t\t\t\t\t\t\t\t\t\"sanityCheckRandom\", \"mixRandomPool\", \n\t\t\t\t\t\t\t\t\t\"getRandomOutput\", \"checksumRandomPool\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tInit/Shutdown Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test vectors for the PRNG */\n\n#ifdef USE_SHA1_PRNG\n  #define PRNG_OUTPUT_STEP1\t\"\\xF6\\x8F\\x30\\xEE\\x52\\x13\\x3E\\x40\\x06\\x06\\xA6\\xBE\\x91\\xD2\\xD9\\x82\"\n  #define PRNG_OUTPUT_STEP2\t\"\\xAE\\x94\\x3B\\xF2\\x86\\x5F\\xCF\\x76\\x36\\x2B\\x80\\xD5\\x73\\x86\\x9B\\x69\"\n  #define PRNG_OUTPUT_STEP3\t\"\\xBC\\x2D\\xC1\\x03\\x8C\\x78\\x6D\\x04\\xA8\\xBD\\xD5\\x51\\x80\\xCA\\x42\\xF4\"\n  #define PRNG_OUTPUT_FINAL\t\"\\x6B\\x59\\x1D\\xCD\\xE1\\xB3\\xA8\\x50\\x32\\x84\\x8C\\x8D\\x93\\xB0\\x74\\xD7\"\n  #define PRNG_OUTPUT_FINAL_LEN\t\t16\n#else\n  #define PRNG_OUTPUT_STEP1\t\"\\x2E\\xA9\\xAB\\x91\\x98\\xD1\\x63\\x80\\x07\\x40\\x0C\\xD2\\xC3\\xBE\\xF1\\xCC\"\n  #define PRNG_OUTPUT_STEP1_64\t\"\\x96\\xAB\\x81\\xE9\\xFB\\x55\\x5A\\x0F\\x05\\x82\\x8D\\x76\\xC1\\xF7\\xC1\\x86\"\n  #define PRNG_OUTPUT_STEP2\t\"\\xD2\\xA7\\x07\\x01\\x24\\x92\\x81\\x16\\x2B\\x23\\xCC\\x0A\\x94\\xDC\\x00\\x28\"\n  #define PRNG_OUTPUT_STEP3\t\"\\xE1\\xBF\\xAF\\x2B\\x56\\xA0\\xE3\\xFA\\xB2\\x42\\xD8\\x33\\x6E\\x94\\x70\\x78\"\n  #ifdef USE_3DES_X917\n\t#define PRNG_OUTPUT_FINAL\t\"\\x8F\\xCB\\x4D\\x50\\x44\\xFE\\x67\\xC8\\x6D\\xBC\\x85\\x8C\\xC5\\x6E\\xBE\\xE1\"\n\t#define PRNG_OUTPUT_FINAL_LEN\t16\n  #else\n\t#define PRNG_OUTPUT_FINAL\t\"\\x2A\\xFD\\x1F\\xB3\\x93\\x36\\xE9\\xA5\\x9E\\xBC\\xA8\\xC0\\xAA\\xA6\\xE5\\x0C\" \\\n\t\t\t\t\t\t\t\t\"\\x73\\x24\\x15\\xA6\\x76\\x25\\xEC\\x6E\\xF1\\x1B\\xF6\\x65\\xEB\\x7F\\x27\\x8F\"\n\t#define PRNG_OUTPUT_FINAL_LEN\t32\n  #endif /* USE_3DES_X917 */\n#endif /* SHA-1 vs. SHA-2 PRNG */\n\n/* Initialise the randomness subsystem */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initRandomInfo( OUT_PTR_COND TYPECAST( RANDOM_INFO ** ) void **randomInfoPtrPtr )\n\t{\n\tRANDOM_INFO *randomInfoPtr;\n#ifndef CONFIG_NO_SELFTEST\n\tRANDOM_INFO testRandomInfo;\n\tBYTE buffer[ PRNG_OUTPUT_FINAL_LEN + 8 ];\n#endif /* CONFIG_NO_SELFTEST */\n\tint status;\n\n\tassert( isWritePtr( randomInfoPtrPtr, sizeof( void * ) ) );\n\n\t/* Clear return value */\n\t*randomInfoPtrPtr = NULL;\n\n#ifndef CONFIG_NO_SELFTEST\n\t/* Make sure that the crypto that we need is functioning as required */\n\tstatus = randomAlgorithmSelfTest();\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* The underlying crypto is OK, check that the cryptlib PRNG is working\n\t   correctly.  Since the input of the first mixRandomPool() is an all-\n\t   zero block, we compare a second test block 64 bytes in which is the\n\t   result of hashing non-zero values */\n\tinitRandomPool( &testRandomInfo );\n\tstatus = mixRandomPool( &testRandomInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\t( memcmp( testRandomInfo.randomPool, PRNG_OUTPUT_STEP1, 16 ) || \\\n\t\t  memcmp( testRandomInfo.randomPool + 64, PRNG_OUTPUT_STEP1_64, 16 ) ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = mixRandomPool( &testRandomInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( testRandomInfo.randomPool, PRNG_OUTPUT_STEP2, 16 ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = mixRandomPool( &testRandomInfo );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( testRandomInfo.randomPool, PRNG_OUTPUT_STEP3, 16 ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendRandomPool( &testRandomInfo );\n\t\tretIntError();\n\t\t}\n\n\t/* Check that the ANSI X9.17 PRNG is working correctly */\n\tstatus = selfTestX917( &testRandomInfo, testRandomInfo.randomPool );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendRandomPool( &testRandomInfo );\n\t\tretIntError();\n\t\t}\n\n\t/* The underlying PRNGs are OK, check the overall random number\n\t   generation system.  Since we started with an all-zero seed we have\n\t   to fake the entropy-quality values for the artificial test pool */\n\ttestRandomInfo.randomQuality = 100;\n\ttestRandomInfo.randomPoolMixes = RANDOMPOOL_MIXES;\n\tstatus = getRandomOutput( &testRandomInfo, buffer, \n\t\t\t\t\t\t\t  PRNG_OUTPUT_FINAL_LEN );\n\tif( cryptStatusOK( status ) && \\\n\t\tmemcmp( buffer, PRNG_OUTPUT_FINAL, PRNG_OUTPUT_FINAL_LEN ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tendRandomPool( &testRandomInfo );\n\t\tretIntError();\n\t\t}\n\tendRandomPool( &testRandomInfo );\n\n\t/* Check the ANSI X9.17 PRNG again, this time using FIPS test vectors */\n\tinitRandomPool( &testRandomInfo );\n\tstatus = fipsTestX917( &testRandomInfo );\n\tif( cryptStatusError( status ) )\n\t\tretIntError();\n\tendRandomPool( &testRandomInfo );\n\n\t/* Finally, make sure that the error detection works */\n\tinitRandomPool( &testRandomInfo );\n\ttestRandomInfo.randomPool[ 12 ] ^= 0x01;\n\tif( checksumRandomPool( &testRandomInfo ) )\n\t\tretIntError();\n\ttestRandomInfo.randomPool[ 12 ] ^= 0x01;\n\ttestRandomInfo.randomPoolPos++;\n\tif( checksumRandomPool( &testRandomInfo ) )\n\t\tretIntError();\n\tendRandomPool( &testRandomInfo );\n#endif /* CONFIG_NO_SELFTEST */\n\n\t/* Allocate and initialise the random pool */\n#ifdef USE_EMBEDDED_OS\n\trandomInfoPtr = getRandomInfoStorage();\n#else\n\tif( ( status = krnlMemalloc( ( void ** ) &randomInfoPtr, \\\n\t\t\t\t\t\t\t\t sizeof( RANDOM_INFO ) ) ) != CRYPT_OK )\n\t\treturn( status );\n#endif /* USE_EMBEDDED_OS */\n\tinitRandomPool( randomInfoPtr );\n\n\t/* Initialise any helper routines that may be needed */\n\tinitRandomPolling();\n\n\t/* Mix the fixed seed into the pool if there's one defined.  We use\n\t   size_t as the data type since that typically matches the system word\n\t   size */\n#ifdef FIXED_SEED\n\t{\n\tconst size_t value = ( size_t ) FIXED_SEED;\n\n\t( void ) addEntropyData( randomInfoPtr, &value, sizeof( value ) );\n\t}\n#endif /* FIXED_SEED */\n\n\t*randomInfoPtrPtr = randomInfoPtr;\n\treturn( CRYPT_OK );\n\t}\n\n/* Shut down the randomness subsystem.  Exactly what to do if we can't \n   exit the polling thread or acquire the mutex is a bit complicated, this \n   is a shouldn't-occur exception condition condition so it's not even \n   possible to plan for this since it's uncertain under which conditions (if \n   ever) this situation would occur.  We can't even perform a failsafe \n   zeroise of the pool data because it could lead to the other thread using \n   an all-zero key from the unexpectedly-cleared pool.  For now we play it \n   by the book and don't do anything if we can't exit the thread or acquire \n   the mutex, which avoids a segfault from pulling the random data out from \n   underneath the other thread */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endRandomInfo( INOUT TYPECAST( RANDOM_INFO ** ) void **randomInfoPtrPtr )\n\t{\n\tRANDOM_INFO *randomInfoPtr = *randomInfoPtrPtr;\n\tint status;\n\n\tassert( isWritePtr( randomInfoPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( *randomInfoPtrPtr, sizeof( RANDOM_INFO ) ) );\n\n\t/* Make sure that there are no background threads/processes still trying\n\t   to send us data */\n\tstatus = waitforRandomCompletion( TRUE );\n\tENSURES_V( cryptStatusOK( status ) );\t/* See comment above */\n\n\t/* Call any special-case shutdown functions */\n\tendRandomPolling();\n\n\t/* Shut down the random data pool.  We acquire the randomness mutex \n\t   while we're doing this to ensure that any threads still using the\n\t   randomness info have exited before we destroy it */\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tENSURES_V( cryptStatusOK( status ) );\t/* See comment above */\n\tendRandomPool( randomInfoPtr );\n\tkrnlExitMutex( MUTEX_RANDOM );\n#ifndef USE_EMBEDDED_OS\n\tstatus = krnlMemfree( randomInfoPtrPtr );\n\tENSURES_V( cryptStatusOK( status ) );\t/* See comment above */\n#endif /* !USE_EMBEDDED_OS */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAdd Random (Entropy) Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add new entropy data and an entropy quality estimate to the random pool */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addEntropyData( INOUT TYPECAST( RANDOM_INFO * ) void *randomInfoPtr, \n\t\t\t\t\tIN_BUFFER( length ) const void *buffer, \n\t\t\t\t\tIN_DATALENGTH const int length )\n\t{\n\tRANDOM_INFO *randomInfo = ( RANDOM_INFO * ) randomInfoPtr;\n\tconst BYTE *bufPtr = ( BYTE * ) buffer;\n\tint count, status, LOOP_ITERATOR;\n#if 0\t/* See comment in addEntropyQuality */\n\tDECLARE_ORIGINAL_INT( entropyByteCount );\n#endif /* 0 */\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer, length ) );\n\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the random information is in order */\n\tif( !sanityCheckRandom( randomInfo ) || !checksumRandomPool( randomInfo ) )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\tretIntError();\n\t\t}\n\n#if 0\t/* See comment in addEntropyQuality */\n\tSTORE_ORIGINAL_INT( entropyByteCount, randomInfo->entropyByteCount );\n#endif /* 0 */\n\n\t/* Mix the incoming data into the pool.  This operation is resistant to\n\t   chosen- and known-input attacks because the pool contents are unknown\n\t   to an attacker so XORing in known data won't help them.  If an\n\t   attacker could determine pool contents by observing the generator\n\t   output (which is defeated by the postprocessing) we'd have to perform \n\t   an extra input mixing operation to defeat these attacks */\n\tLOOP_EXT( count = 0, count < length, count++, \n\t\t\t  MAX_BUFFER_SIZE + 1 )\n\t\t{\n\t\tORIGINAL_INT_VAR( bufVal, bufPtr[ count ] );\n\t\tDECLARE_ORIGINAL_INT( poolVal );\n\t\tDECLARE_ORIGINAL_INT( newPoolVal );\n\t\tDECLARE_ORIGINAL_INT( poolPos );\n\n\t\t/* If the pool write position has reached the end of the pool, mix\n\t\t   the pool */\n\t\tif( randomInfo->randomPoolPos >= RANDOMPOOL_SIZE )\n\t\t\t{\n\t\t\tstatus = mixRandomPool( randomInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) checksumRandomPool( randomInfo );\n\t\t\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tENSURES_KRNLMUTEX( randomInfo->randomPoolPos == 0, MUTEX_RANDOM );\n\t\t\t}\n\n\t\tSTORE_ORIGINAL_INT( poolVal,\n\t\t\t\t\t\t\trandomInfo->randomPool[ randomInfo->randomPoolPos ] );\n\t\tSTORE_ORIGINAL_INT( poolPos, randomInfo->randomPoolPos );\n\n\t\t/* Precondition: We're adding data inside the pool */\n\t\tREQUIRES_KRNLMUTEX( randomInfo->randomPoolPos >= 0 && \\\n\t\t\t\t\t\t\trandomInfo->randomPoolPos < RANDOMPOOL_SIZE, \\\n\t\t\t\t\t\t\tMUTEX_RANDOM );\n\n\t\trandomInfo->randomPool[ randomInfo->randomPoolPos++ ] ^= bufPtr[ count ];\n\n\t\tSTORE_ORIGINAL_INT( newPoolVal,\n\t\t\t\t\t\t\trandomInfo->randomPool[ randomInfo->randomPoolPos - 1 ] );\n\n\t\t/* Postcondition: We've updated the byte at the current pool\n\t\t   position, and the value really was XORed into the pool rather\n\t\t   than (for example) overwriting it as with PGP/xorbytes or\n\t\t   GPG/add_randomness.  Note that in this case we can use a non-XOR\n\t\t   operation to check that the XOR succeeded, unlike the pool mixing\n\t\t   code which requires an XOR to check the original XOR */\n\t\tENSURES_KRNLMUTEX( randomInfo->randomPoolPos == \\\n\t\t\t\t\t\t\t\tORIGINAL_VALUE( poolPos ) + 1, \n\t\t\t\t\t\t   MUTEX_RANDOM );\n\t\tENSURES_KRNLMUTEX( ( ( ORIGINAL_VALUE( newPoolVal ) == \\\n\t\t\t\t\t\t\t\tORIGINAL_VALUE( bufVal ) ) && \\\n\t\t\t\t\t\t\t ( ORIGINAL_VALUE( poolVal ) == 0 ) ) || \\\n\t\t\t\t\t\t   ( ORIGINAL_VALUE( newPoolVal ) != \\\n\t\t\t\t\t\t\t\tORIGINAL_VALUE( bufVal ) ),\n\t\t\t\t\t\t   MUTEX_RANDOM );\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_RANDOM );\n\n#if 0\t/* See comment in addEntropyQuality */\n\t/* Remember how many bytes of entropy we added on this update */\n\trandomInfo->entropyByteCount += length;\n#endif /* 0 */\n\n\t/* Postcondition: We processed all of the data */\n\tENSURES_KRNLMUTEX( count == length, MUTEX_RANDOM );\n#if 0\t/* See comment in addEntropyQuality */\n\tENSURES_KRNLMUTEX( randomInfo->entropyByteCount == \\\n\t\t\t\t\t\t ORIGINAL_VALUE( entropyByteCount ) + length, \\\n\t\t\t\t\t   MUTEX_RANDOM );\n#endif /* 0 */\n\n\tENSURES_KRNLMUTEX( sanityCheckRandom( randomInfo ), MUTEX_RANDOM );\n\n\t/* Recalculate the random information checksum after the changes that \n\t   we've made */\n\t( void ) checksumRandomPool( randomInfo );\n\n\tkrnlExitMutex( MUTEX_RANDOM );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addEntropyQuality( INOUT TYPECAST( RANDOM_INFO * ) void *randomInfoPtr, \n\t\t\t\t\t   IN_RANGE( 1, 100 ) const int quality )\n\t{\n\tRANDOM_INFO *randomInfo = ( RANDOM_INFO * ) randomInfoPtr;\n\tint status;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\tREQUIRES( quality > 0 && quality <= 100 );\n\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the random information is in order */\n\tif( !sanityCheckRandom( randomInfo ) || !checksumRandomPool( randomInfo ) )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\tretIntError();\n\t\t}\n\n\t/* In theory we could check to ensure that the claimed entropy quality\n\t   corresponds approximately to the amount of entropy data added,\n\t   however in a multithreaded environment this doesn't work because the\n\t   entropy addition is distinct from the entropy quality addition so \n\t   that (for example) with entropy being added by three threads we could\n\t   end up with the following:\n\n\t\tentropy1, entropy1,\n\t\tentropy2,\n\t\tentropy1,\n\t\tentropy3,\n\t\tentropy1,\n\t\tentropy3,\n\t\tentropy2,\n\t\tquality2, reset to 0\n\t\tquality1, fail since reset to 0\n\t\tquality3, fail since reset to 0\n\n\t   This means that the first entropy quality measure added is applied\n\t   to all of the previously added entropy after which the entropy byte \n\t   count is reset, causing subsequent attempts to add entropy quality to \n\t   fail.  In addition the first quality value is applied to all of the \n\t   entropy added until that point rather than just the specific entropy \n\t   samples that it corresponds to.  In theory this could be addressed by \n\t   requiring the entropy source to treat entropy addition as a \n\t   database-style BEGIN ... COMMIT transaction but this makes the \n\t   interface excessively complex for both source and sink, and more \n\t   prone to error than the small gain in entropy quality-checking is \n\t   worth */\n#if 0\n\tif( randomInfo->entropyByteCount <= 0 || \\\n\t\tquality / 2 > randomInfo->entropyByteCount )\n\t\t{\n\t\t/* If there's not enough entropy data present to justify the\n\t\t   claimed entropy quality level, signal an error.  We do however\n\t\t   retain the existing entropy byte count for use the next time an\n\t\t   entropy quality estimate is added, since it's still contributing\n\t\t   to the total entropy quality */\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\tretIntError();\n\t\t}\n\trandomInfo->entropyByteCount = 0;\n#endif /* 0 */\n\n\t/* If we haven't reached the minimum quality level for generating keys\n\t   yet, update the quality level */\n\tif( randomInfo->randomQuality < 100 )\n\t\t{\n\t\t/* Update the quality count, making sure that it stays within \n\t\t   bounds */\n\t\tif( randomInfo->randomQuality + quality > 100 )\n\t\t\trandomInfo->randomQuality = 100;\n\t\telse\n\t\t\trandomInfo->randomQuality += quality;\n\t\t}\n\n\tENSURES_KRNLMUTEX( sanityCheckRandom( randomInfo ), MUTEX_RANDOM );\n\n\t/* Recalculate the random information checksum after the changes that \n\t   we've made */\n\t( void ) checksumRandomPool( randomInfo );\n\n\tkrnlExitMutex( MUTEX_RANDOM );\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef CONFIG_RANDSEED\n\n/* Add entropy data from a stored seed value.  This is called with \n   MUTEX_RANDOM held so we don't need to perform any explicit mutex \n   management here */\n\n#define RANDSEED_MAX_SIZE\t1024\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void addStoredSeedData( INOUT RANDOM_INFO *randomInfo )\n\t{\n\tSTREAM stream;\n\tBYTE streamBuffer[ STREAM_BUFSIZE + 8 ];\n\tBYTE seedBuffer[ SAFEBUFFER_SIZE( RANDSEED_MAX_SIZE ) + 8 ] STACK_ALIGN_DATA;\n\tchar seedFilePath[ MAX_PATH_LENGTH + 8 ];\n\tint seedFilePathLen, poolCount, length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( randomInfo, sizeof( RANDOM_INFO ) ) );\n\n\t/* Try and access the stored seed data */\n\tstatus = fileBuildCryptlibPath( seedFilePath, MAX_PATH_LENGTH, \n\t\t\t\t\t\t\t\t\t&seedFilePathLen, NULL, 0,\n\t\t\t\t\t\t\t\t\tBUILDPATH_RNDSEEDFILE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The file path functions are normally used with krnlSendMessage()\n\t\t   which takes { data, length } parameters, since we've calling\n\t\t   the low-level function sFileOpen() directly we have to null-\n\t\t   terminate the string */\n\t\tseedFilePath[ seedFilePathLen ] = '\\0';\n\t\tstatus = sFileOpen( &stream, seedFilePath, FILE_FLAG_READ );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The seed data isn't present, don't try and access it again */\n\t\trandomInfo->seedProcessed = TRUE;\n\t\tDEBUG_DIAG(( \"Error opening random seed file, status %s\", \n\t\t\t\t\t getStatusName( status ) ));\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\n\t/* Read up to RANDSEED_MAX_SIZE of data from the stored seed */\n\tmemset( seedBuffer, 0, RANDSEED_MAX_SIZE );\n\tsafeBufferInit( SAFEBUFFER_PTR( seedBuffer ), RANDSEED_MAX_SIZE );\n\tsioctlSetString( &stream, STREAM_IOCTL_IOBUFFER, \n\t\t\t\t\t SAFEBUFFER_PTR( streamBuffer ), STREAM_BUFSIZE );\n\tsioctlSet( &stream, STREAM_IOCTL_PARTIALREAD, TRUE );\n\tstatus = length = sread( &stream, seedBuffer, RANDSEED_MAX_SIZE );\n\tsFileClose( &stream );\n\tzeroise( streamBuffer, STREAM_BUFSIZE );\n\tif( cryptStatusError( status ) || length <= 16 )\n\t\t{\n\t\t/* The seed data is present but we can't read it or there's not \n\t\t   enough present to use, don't try and access it again */\n\t\trandomInfo->seedProcessed = TRUE;\n\t\tDEBUG_DIAG(( \"Error reading random seed file, status %s, length %d\",\n\t\t\t\t\t getStatusName( status ), length ));\n\t\tassert( DEBUG_WARN );\n\t\treturn;\n\t\t}\n\tENSURES_V( length >= 16 && length <= RANDSEED_MAX_SIZE );\n\trandomInfo->seedSize = length;\n\n\t/* Precondition: We got at least some non-zero data */\n\tEXISTS( i, 0, length,\n\t\t\tseedBuffer[ i ] != 0 );\n\n\t/* Add the seed data to the entropy pool.  Both because the entropy-\n\t   management code gets suspicious about very small amounts of data with\n\t   claimed high entropy and because it's a good idea to start with all\n\t   of the pool set to the seed data (rather than most of it set at zero\n\t   if the seed data is short), we add the seed data repeatedly until\n\t   we've filled the pool */\n\tLOOP_MED( poolCount = RANDOMPOOL_SIZE, poolCount > 0, poolCount -= length )\n\t\t{\n\t\tstatus = addEntropyData( randomInfo, seedBuffer, length );\n\t\tENSURES_V( cryptStatusOK( status ) );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\t/* There were at least 128 bits of entropy present in the seed, set the \n\t   entropy quality to the user-provided value */\n\tstatus = addEntropyQuality( randomInfo, CONFIG_RANDSEED_QUALITY );\n\tENSURES_V( cryptStatusOK( status ) );\n\n\tzeroise( seedBuffer, RANDSEED_MAX_SIZE );\n\n\t/* Postcondition: Nulla vestigia retrorsum */\n\tFORALL( i, 0, RANDSEED_MAX_SIZE,\n\t\t\tseedBuffer[ i ] == 0 );\n\t}\n#endif /* CONFIG_RANDSEED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRandom Pool External Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convenience functions used by the system-specific randomness-polling\n   routines to send data to the system device.  These just accumulate as\n   close to bufSize bytes of data as possible in a user-provided buffer and\n   then forward them to the device object.  Note that addRandomData()\n   assumes that the quantity of data being added is small (a fixed-size\n   struct or something similar), it shouldn't be used to add large buffers\n   full of data since information at the end of the buffer will be lost */\n\ntypedef struct {\n\tBUFFER( bufSize, bufPos ) \\\n\tvoid *buffer;\t\t\t/* Entropy buffer */\n\tint bufPos, bufSize;\t/* Current buffer pos.and total size */\n\tint updateStatus;\t\t/* Error status if update failed */\n\t} RANDOM_STATE_INFO;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initRandomData( OUT TYPECAST( RANDOM_STATE_INFO * ) void *statePtr, \n\t\t\t\t\tWORKING_BUFFER( maxSize ) void *buffer, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) const int maxSize )\n\t{\n\tRANDOM_STATE_INFO *state = ( RANDOM_STATE_INFO * ) statePtr;\n\n\tassert( isWritePtr( state, sizeof( RANDOM_STATE_INFO ) ) );\n\tassert( isWritePtrDynamic( buffer, maxSize ) );\n\n\tstatic_assert( sizeof( RANDOM_STATE_INFO ) <= sizeof( RANDOM_STATE ),\n\t\t\t\t   \"Random pool state size\" );\n\n\tREQUIRES( maxSize >= 16 && maxSize < MAX_INTLENGTH_SHORT );\n\n\t/* The buffer is used purely as scratch space so it's neither an input\n\t   nor an output parameter, but some analysers will complain about the \n\t   use of uninitialised memory in this case, so we clear it (or at least\n\t   some of it) to keep checkers happy */\n\tmemset( buffer, 0, min( 16, maxSize ) );\n\n\t/* Set up the state information */\n\tmemset( state, 0, sizeof( RANDOM_STATE_INFO ) );\n\tstate->buffer = buffer;\n\tstate->bufSize = maxSize;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addRandomData( INOUT TYPECAST( RANDOM_STATE_INFO * ) void *statePtr, \n\t\t\t\t   IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t   IN_LENGTH_SHORT const int valueLength )\n\t{\n\tRANDOM_STATE_INFO *state = ( RANDOM_STATE_INFO * ) statePtr;\n\tMESSAGE_DATA msgData;\n\tconst BYTE *valuePtr = value;\n\tint bytesToCopy = min( valueLength, state->bufSize - state->bufPos );\n\tint totalLength = valueLength, status;\n\n\tassert( isWritePtr( state, sizeof( RANDOM_STATE_INFO ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES( state->bufSize >= 16 && state->bufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( state->bufPos >= 0 && state->bufPos <= state->bufSize );\n\tREQUIRES( isShortIntegerRangeNZ( valueLength ) );\n\n\t/* If we're in an error state, don't try and do anything */\n\tif( cryptStatusError( state->updateStatus ) )\n\t\treturn( state->updateStatus );\n\n\t/* Copy as much of the input as we can into the accumulator */\n\tif( bytesToCopy > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheckZ( state->bufPos, bytesToCopy, \n\t\t\t\t\t\t\t\tstate->bufSize ) );\n\t\tmemcpy( ( BYTE * ) state->buffer + state->bufPos, valuePtr, \n\t\t\t\tbytesToCopy );\n\t\tstate->bufPos += bytesToCopy;\n\t\tvaluePtr += bytesToCopy;\n\t\ttotalLength -= bytesToCopy;\n\t\t}\n\tENSURES( isShortIntegerRange( totalLength ) );\n\n\t/* If everything went into the accumulator, we're done */\n\tif( state->bufPos < state->bufSize )\n\t\treturn( CRYPT_OK );\n\n\tENSURES( state->bufPos == state->bufSize );\n\n\t/* The accumulator is full, send the data through to the system device */\n\tsetMessageData( &msgData, state->buffer, state->bufPos );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There was a problem moving the data through, make the error status \n\t\t   persistent.  Normally this is a should-never-occur error \n\t\t   condition but if cryptlib has been shut down from another thread \n\t\t   then the kernel will fail all non shutdown-related calls with a \n\t\t   permission error.  To avoid false alarms we mask out failures due \n\t\t   to permission errors */\n\t\tstate->updateStatus = status;\n\t\tassert( ( status == CRYPT_ERROR_PERMISSION ) || DEBUG_WARN );\n\t\treturn( status );\n\t\t}\n\tstate->bufPos = 0;\n\n\t/* If we've consumed all of the data, we're done */\n\tif( totalLength <= 0 )\n\t\treturn( CRYPT_OK );\n\n\t/* There's uncopied data left, copy it in now.  If there's more data \n\t   present than can fit in the accumulator's buffer we discard it \n\t   (although we warn in the debug build, which is why the code below\n\t   has an assert() rather than a REQUIRES()), the caller should be \n\t   sending quantities this large directly rather than using the \n\t   addRandomData() interface */\n\tassert( totalLength < state->bufSize );\t/* Debug warning only */\n\tbytesToCopy = min( totalLength, state->bufSize );\n\tREQUIRES( rangeCheck( bytesToCopy, 1, state->bufSize ) );\n\tmemcpy( state->buffer, valuePtr, bytesToCopy );\n\tstate->bufPos += bytesToCopy;\n\n\treturn( CRYPT_OK );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addRandomLong( INOUT void *statePtr, const long value )\n\t{\n\treturn( addRandomData( statePtr, &value, sizeof( long ) ) );\n\t}\n\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint endRandomData( INOUT void *statePtr, \\\n\t\t\t\t   IN_RANGE( 0, 100 ) const int quality )\n\t{\n\tRANDOM_STATE_INFO *state = ( RANDOM_STATE_INFO * ) statePtr;\n\tint status = state->updateStatus;\n\n\tassert( isWritePtr( state, sizeof( RANDOM_STATE_INFO ) ) );\n\n\tREQUIRES( state->bufSize >= 16 && state->bufSize < MAX_INTLENGTH_SHORT );\n\tREQUIRES( state->bufPos >= 0 && state->bufPos <= state->bufSize );\n\tREQUIRES( quality >= 0 && quality <= 100 );\n\n\t/* If we're in an error state, don't try and do anything */\n\tif( cryptStatusError( state->updateStatus ) )\n\t\treturn( state->updateStatus );\n\n\t/* If there's data still in the accumulator send it through to the \n\t   system device.  A failure at this point is a should-never-occur \n\t   condition but if cryptlib has been shut down from another thread then \n\t   the kernel will fail all non shutdown-related calls with a permission\n\t   error.  To avoid false alarms we mask out failures due to permission\n\t   errors */\n\tif( state->bufPos > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, state->buffer, state->bufPos );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t}\n\tassert( cryptStatusOK( status ) || ( status == CRYPT_ERROR_PERMISSION ) );\n\n\t/* If everything went OK, set the quality estimate for the data that\n\t   we've added */\n\tif( cryptStatusOK( status ) && quality > 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t}\n\tassert( cryptStatusOK( status ) || ( status == CRYPT_ERROR_PERMISSION ) );\n\n\t/* Clear the accumulator and exit */\n\tzeroise( state->buffer, state->bufSize );\n\tzeroise( state, sizeof( RANDOM_STATE_INFO ) );\n\treturn( status );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/random.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Randomness Interface\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _RANDOM_DEFINED\n\n#define _RANDOM_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRandomness Constants and Data Types\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The maximum amount of random data needed by any cryptlib operation,\n   equivalent to the size of a maximum-length PKC key.  However this isn't \n   the absolute length because when generating the k value for DLP\n   operations we get n + m bits and then reduce via one of the DLP\n   parameters to get the value within range.  If we just got n bits this\n   would introduce a bias into the top bit, see the DLP code for more\n   details.  Because of this we allow a length slightly larger than the\n   maximum PKC key size */\n\n#define MAX_RANDOM_BYTES\t( CRYPT_MAX_PKCSIZE + 8 )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRandomness Polling Internal Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some systems systems require special-case initialisation to allow\n   background randomness gathering, where this doesn't apply the routines to\n   do this are nop'd out */\n\n#if defined( __WIN32__ ) || defined( __WINCE__ )\n  void initRandomPolling( void );\n  void endRandomPolling( void );\n  CHECK_RETVAL \\\n  int waitforRandomCompletion( const BOOLEAN force );\n#elif defined( __Android__ ) || \\\n\t  ( defined( __UNIX__ ) && \\\n\t\t!( defined( __MVS__ ) || defined( __TANDEM_NSK__ ) || \\\n\t\t   defined( __TANDEM_OSS__ ) ) )\n  void initRandomPolling( void );\n  void endRandomPolling( void );\n  CHECK_RETVAL \\\n  int waitforRandomCompletion( const BOOLEAN force );\n#else\n  #define initRandomPolling()\n  #define endRandomPolling()\n  #define waitforRandomCompletion( dummy )\tCRYPT_OK\n#endif /* !( __WIN32__ || __UNIX__ ) */\n\n/* On Unix systems the randomness pool may be duplicated at any point if\n   the process forks (qualis pater, talis filius), so we need to perform a\n   complex check to make sure that we're running with a unique copy of the\n   pool contents rather than a clone of data held in another process.  The\n   following function checks whether we've forked or not, which is used as a\n   signal to adjust the pool contents */\n\n#if defined( __Android__ ) || \\\n\t( defined( __UNIX__ ) && \\\n\t  !( defined( __MVS__ ) || defined( __TANDEM_NSK__ ) || \\\n\t\t defined( __TANDEM_OSS__ ) ) )\n  CHECK_RETVAL_BOOL \\\n  BOOLEAN forkCheck( const BOOLEAN checkForked );\n#else\n  #define forkCheck( checkForked )\t\tFALSE\n#endif /* __UNIX__ */\n\n/* Prototypes for functions in the OS-specific randomness polling routines */\n\nvoid slowPoll( void );\nvoid fastPoll( void );\n\n/* In order to make it easier to add lots of arbitrary-sized random data\n   values, we make the following functions available to the polling code to\n   implement a clustered-write mechanism for small data quantities.  These\n   add an integer, long, or (short) string value to a buffer and send it\n   through to the system device when the buffer is full.  Using the\n   intermediate buffer ensures that we don't have to send a message to the\n   device for every bit of data added\n\n   The caller declares a state variable of type RANDOM_STATE, calls\n   initRandomData() to initialise it, calls addRandomData() for each\n   consecutive piece of data to add to the buffer, and finally calls\n   endRandomData() to flush the data through to the system device.  The\n   state pointer is declared as a void * because to the caller it's an\n   opaque memory block while to the randomData routines it's structured\n   storage */\n\ntypedef BYTE RANDOM_STATE[ 128 ];\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initRandomData( OUT void *statePtr, \n\t\t\t\t\tWORKING_BUFFER( maxSize ) void *buffer, \n\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) const int maxSize );\nRETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addRandomData( INOUT void *statePtr, \n\t\t\t\t   IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t   IN_LENGTH_SHORT const int valueLength );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addRandomLong( INOUT void *statePtr, const long value );\nRETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint endRandomData( INOUT void *statePtr, \\\n\t\t\t\t   IN_RANGE( 0, 100 ) const int quality );\n\n/* We also provide an addRandomValue() to make it easier to add function\n   return values for getXYZ()-style system calls that return system info as\n   their return value, for which we can't pass an address to addRandomData()\n   unless we copy it to a temporary var first */\n\n#define addRandomValue( statePtr, value ) \\\n\t\taddRandomLong( statePtr, ( long ) value )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRandomness External Interface Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in random.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initRandomInfo( OUT_PTR_COND void **randomInfoPtrPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endRandomInfo( INOUT void **randomInfoPtrPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint addEntropyData( INOUT void *randomInfoPtr, \n\t\t\t\t\tIN_BUFFER( length ) const void *buffer, \n\t\t\t\t\tIN_DATALENGTH const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addEntropyQuality( INOUT void *randomInfoPtr, \n\t\t\t\t\t   IN_RANGE( 1, 100 ) const int quality );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getRandomData( INOUT void *randomInfoPtr, \n\t\t\t\t   OUT_BUFFER_FIXED( length ) void *buffer, \n\t\t\t\t   IN_RANGE( 1, MAX_RANDOM_BYTES ) const int length );\n\n#endif /* _RANDOM_DEFINED */\n"
  },
  {
    "path": "deps/cl345/random/random_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Randomness Internal Interface\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _RANDOM_INT_DEFINED\n\n#define _RANDOM_INT_DEFINED\n\n#if defined( INC_ALL )\n  #ifdef USE_3DES_X917\n\t#include \"des.h\"\n  #else\n\t#include \"aes.h\"\n  #endif /* USE_3DES_X917 */\n  #include \"random.h\"\n#else\n  #ifdef USE_3DES_X917\n\t#include \"crypt/des.h\"\n  #else\n\t#include \"crypt/aes.h\"\n  #endif /* USE_3DES_X917 */\n  #include \"random/random.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRandomness Constants and Data Types\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size in bytes of the randomness pool and the size of the X9.17\n   post-processor generator pool */\n\n#define RANDOMPOOL_SIZE\t\t\t256\n#ifdef USE_3DES_X917\n  #define X917_POOLSIZE\t\t\t8\n#else\n  #define X917_POOLSIZE\t\t\t16\n#endif /* USE_3DES_X917 */\n\n/* cryptlib 2.00 to 3.42 use SHA-1 in the PRNG, cryptlib 3.43+ used SHA-2,\n   which simplifies things somewhat since the 32-byte output is a multiple\n   of the random pool size */\n\n#ifdef USE_SHA1_PRNG\n  /* The allocated size of the randomness pool, which allows for the \n     overflow created by the fact that the hash function blocksize, 20 bytes \n\t for SHA-1, isn't any useful multiple of a power of 2 */\n  #define PRNG_ALGO\t\t\t\tCRYPT_ALGO_SHA1\n  #define RANDOMPOOL_ALLOCSIZE\t( ( ( RANDOMPOOL_SIZE + 20 - 1 ) / 20 ) * 20 )\n#else\n  #define PRNG_ALGO\t\t\t\tCRYPT_ALGO_SHA2\n  #define RANDOMPOOL_ALLOCSIZE\tRANDOMPOOL_SIZE\n#endif /* SHA-1 vs. SHA-2 PRNG */\n\n/* The number of short samples of previous output that we keep for the FIPS\n   140 continuous tests, and the number of retries that we perform if we\n   detect a repeat of a previous output */\n\n#define RANDOMPOOL_SAMPLES\t\t16\n#define RANDOMPOOL_RETRIES\t\t5\n\n/* The size of the X9.17 generator key, 112/128 bits for 3DES/AES, and the \n   size of the generator output */\n\n#define X917_KEYSIZE\t\t\t16\n#define X917_BLOCKSIZE\t\t\tX917_POOLSIZE\n\n/* The number of times that we cycle the X9.17 generator before we load new\n   key and state variables.  This means that we re-seed for every\n   X917_MAX_BYTES of output produced */\n\n#define X917_MAX_BYTES\t\t\t4096\n#define X917_MAX_CYCLES\t\t\t( X917_MAX_BYTES / X917_POOLSIZE )\n\n/* In order to perform a FIPS 140-compliant check we have to signal a hard\n   failure on the first repeat value rather than retrying the operation in\n   case it's a one-off fault.  In order to avoid problems with false\n   positives we take a larger-than-normal sample of RANDOMPOOL_SAMPLE_SIZE\n   bytes for the first value, which we compare as a backup check if the\n   standard short sample indicates a repeat */\n\n#define RANDOMPOOL_SAMPLE_SIZE\t16\n\n/* The X9.17 generator can run with either the original 3DES algorithm \n   (cryptlib 2.0 to 3.43) or the more recent AES one (cryptlib 3.44+).\n\n   Since there may be alignment requirements for underlying hardware crypto, \n   we have to allow for padding alongside the key storage, see the comment \n   in initX917() for details.  To deal with this we allocate X917_KEYDATA \n   storage and then set up an aligned pointer to the X917_KEY within the \n   X917_KEYDATA block */\n\n#ifdef USE_3DES_X917\n\ntypedef struct {\n\tKey_schedule desKey1, desKey2, desKey3;\n\t} X917_KEY;\ntypedef struct {\n\tKey_schedule desKey1, desKey2, desKey3;\n\tBYTE padding[ 16 ];\n\t} X917_KEYDATA;\n#define DES_KEYSIZE\t\tsizeof( Key_schedule )\n\n#else\n\ntypedef struct {\n\taes_encrypt_ctx aesKey;\n\t} X917_KEY;\ntypedef struct {\n\taes_encrypt_ctx aesKey;\n\tBYTE padding[ 16 ];\n\t} X917_KEYDATA;\n#define AES_KEYSIZE\t\tsizeof( aes_encrypt_ctx )\n\n#endif /* USE_3DES_X917 */\n\n/* Random pool information.  We keep track of the write position in the\n   pool, which tracks where new data is added.  Whenever we add new data the\n   write position is updated, once we reach the end of the pool we mix the\n   pool and start again at the beginning.  We track the pool status by\n   recording the quality of the pool contents (1-100) and the number of\n   times the pool has been mixed, we can't draw data from the pool unless\n   both of these values have reached an acceptable level.  In addition to\n   the pool state information we keep track of the previous\n   RANDOMPOOL_SAMPLES output samples to check for stuck-at faults or (short)\n   cyles */\n\ntypedef struct {\n\t/* Pool state information */\n\tBUFFER( RANDOMPOOL_ALLOCSIZE, randomPoolPos ) \\\n\tBYTE randomPool[ RANDOMPOOL_ALLOCSIZE + 8 ];/* Random byte pool */\n\tint randomPoolPos;\t\t/* Current write position in the pool */\n\n\t/* Pool status information */\n\tint randomQuality;\t\t/* Level of randomness in the pool */\n\tint randomPoolMixes;\t/* Number of times pool has been mixed */\n\n\t/* X9.17 generator state information */\n\tBUFFER_FIXED( X917_POOLSIZE ) \\\n\tBYTE x917Pool[ X917_POOLSIZE + 8 ];\t/* Generator state */\n\tBUFFER_FIXED( X917_POOLSIZE ) \\\n\tBYTE x917DT[ X917_POOLSIZE + 8 ];\t/* Date/time vector */\n\tDATAPTR x917Key;\t\t/* Generator encryption key */\n\tX917_KEYDATA x917KeyData;\n\tBOOLEAN x917Inited;\t\t/* Whether generator has been inited */\n\tint x917Count;\t\t\t/* No.of times generator has been cycled */\n\tBOOLEAN useX931;\t\t/* X9.17 vs. X9.31 operation (see code comments */\n\n\t/* Information for the FIPS 140 continuous tests */\n\tARRAY( RANDOMPOOL_SAMPLES, prevOutputIndex ) \\\n\tunsigned long prevOutput[ RANDOMPOOL_SAMPLES + 2 ];\n\tARRAY( RANDOMPOOL_SAMPLES, prevOutputIndex ) \\\n\tunsigned long x917PrevOutput[ RANDOMPOOL_SAMPLES + 2 ];\n\tint prevOutputIndex;\n\tBUFFER_FIXED( RANDOMPOOL_SAMPLE_SIZE ) \\\n\tBYTE x917OuputSample[ RANDOMPOOL_SAMPLE_SIZE + 8 ];\n\n#if 0\t/* See comment in addEntropyQuality() */\n\t/* Other status information used to check the pool's operation */\n\tint entropyByteCount;\t/* Number of bytes entropy added */\n#endif /* 0 */\n\n\t/* Pool integrity-protection checksum.  This is set to zero before the\n\t   entire RANDOM_INFO structure is checksummed */\n\tint checksum;\t\t\t/* Integrity-protection checksum */\n\n\t/* Random seed data information if seeding is done from a stored seed */\n#ifdef CONFIG_RANDSEED\n\tBOOLEAN seedProcessed;\t/* Whether stored seed has been processed */\n\tint seedSize;\t\t\t/* Size of stored seed data */\n\tint seedUpdateCount;\t/* When to update stored seed data */\n#endif /* CONFIG_RANDSEED */\n\t} RANDOM_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRandomness Internal Interface Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in random.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initRandomPool( OUT RANDOM_INFO *randomInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endRandomPool( INOUT RANDOM_INFO *randomInfo );\n\n/* Get storage for the randomness information.  This is normally allocated \n   in non-pageable memory, but for embedded systems it's part of the \n   statically-allocated system storage */\n\n#ifdef USE_EMBEDDED_OS\nCHECK_RETVAL_PTR_NONNULL \\\nvoid *getRandomInfoStorage( void );\n#endif /* USE_EMBEDDED_OS */\n\n/* Prototypes for functions in rand_x917.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint setKeyX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\tIN_BUFFER_C( X917_KEYSIZE ) const BYTE *key,\n\t\t\t\tIN_BUFFER_C( X917_POOLSIZE ) const BYTE *state,\n\t\t\t\tIN_BUFFER_OPT_C( X917_POOLSIZE ) const BYTE *dateTime );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint generateX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\t  INOUT_BUFFER_FIXED( length ) BYTE *data,\n\t\t\t\t  IN_RANGE( 1, MAX_RANDOM_BYTES ) const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initX917( INOUT RANDOM_INFO *randomInfo );\n#ifndef CONFIG_NO_SELFTEST_\nCHECK_RETVAL \\\nint randomAlgorithmSelfTest( void );\nCHECK_RETVAL \\\nint selfTestX917( INOUT RANDOM_INFO *randomInfo, \n\t\t\t\t  IN_BUFFER_C( X917_KEYSIZE ) const BYTE *key );\nCHECK_RETVAL \\\nint fipsTestX917( INOUT RANDOM_INFO *randomInfo );\n#else\n  #define randomAlgorithmSelfTest()\t\t\tCRYPT_OK\n  #define selfTestX917( randomInfo, key )\tCRYPT_OK\n  #define fipsTestX917( randomInfo )\t\tCRYPT_OK\n#endif /* !CONFIG_NO_SELFTEST */\n#endif /* _RANDOM_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/random/tandem.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tTandem Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2002-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* Define the following to print diagnostic information on where randomness\n   is coming from */\n\n/* #define DEBUG_RANDOM\t*/\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <cextdecs>\n#include <tal.h>\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n\n/* The number of processes per CPU that we fetch attributes for.  We set an\n   upper limit on this to make sure that we don't take too much time doing\n   it */\n\n#define NO_PROCESSES\t50\n\n/* The CPU attributes that we fetch.  This typically yields 150 words\n   of attribute data */\n\nstatic const short int cpuAttrList[] = {\n\t\t2,\t\t/* INT: Processor type */\n\t\t7,\t\t/* INT_32: Swappable pages */\n\t\t8,\t\t/* INT_32: Free pages */\n\t\t9,\t\t/* INT_32: Current locked pages */\n\t\t11, \t/* INT_32: Max.locked memory pages */\n\t\t12, \t/* INT_32: No.page faults */\n\t\t13,\t\t/* INT_32: Scans per memory manager call */\n\t\t14,\t\t/* INT_32: No.mem manager scans */\n\t\t15,\t\t/* INT_32: Page fault frequency indicator */\n\t\t16,\t\t/* INT_32: Paging queue length */\n\t\t18,\t\t/* FIXED: Wall clock time */\n\t\t19,\t\t/* FIXED: CPU time */\n\t\t20,\t\t/* FIXED: Idle time */\n\t\t21,\t\t/* FIXED: Interrupt time */\n\t\t22,\t\t/* INT: Process queue length */\n\t\t23,\t\t/* INT_32: No.dispatch interrupts */\n\t\t24,\t\t/* INT[]: Process Control Blocks (PCBs) in low PINs */\n\t\t25,\t\t/* INT[]: Process Control Blocks (PCBs) in high PINs */\n\t\t26,\t\t/* INT_32[]: Time List Elements (TLEs) */\n\t\t27,\t\t/* INT_32[]: Process Time List Elements (TLEs) */\n\t\t28,\t\t/* INT: No.breakpoints currently set */\n\t\t29,\t\t/* FIXED: Time spent in message sends */\n\t\t35,\t\t/* INT_32[24]: Interrupt count */\n\t\t36,\t\t/* FIXED: Disk cache hits */\n\t\t37,\t\t/* FIXED: Disk I/Os */\n\t\t38,\t\t/* INT,INT,/* FIXED: Processor queue state */\n\t\t39,\t\t/* INT,INT,/* FIXED: Memory queue state */\n\t\t40,\t\t/* INT_32: IPC sequenced messages */\n\t\t41,\t\t/* INT_32: IPC unsequenced messages */\n\t\t42,\t\t/* INT_32: Correctable memory errors */\n\t\t43,\t\t/* INT_32: VM pages created */\n\t\t44,\t\t/* FIXED: Time spent in interpreter (for NSR-L CPUs) */\n\t\t45,\t\t/* INT_32: Interpreter transitions (for NSR-L CPUs) */\n\t\t46,\t\t/* INT_32: Transactions since Measure product started */\n\t\t50,\t\t/* FIXED: Time in accelerated mode (for TNS/R CPUs) */\n\t\t58,\t\t/* INT_32: Kernel segments in use */\n\t\t59\t\t/* INT_32: Maximum segments used */\n\t\t};\n\n#define NO_CPU_ATTRS\t( sizeof( cpuAttrList ) / sizeof( short int ) )\n\n/* The process attributes that we fetch.  This typically yields 80 words\n   of attribute data */\n\nstatic const short int procAttrList[] = {\n\t\t1,\t\t/* INT: Creator access ID */\n\t\t2,\t\t/* INT: Process access ID */\n\t\t6,\t\t/* INT[10]: gmom process handle */\n\t\t7,\t\t/* INT: Job ID */\n\t\t8,\t\t/* INT: Process subtype */\n\t\t10,\t\t/* INT: Process state */\n\t\t11,\t\t/* INT[2]: System process type */\n\t\t15,\t\t/* INT: Process list */\n\t\t28,\t\t/* INT: Process type */\n\t\t30,\t\t/* FIXED: Process time */\n\t\t31,\t\t/* INT: Wait state */\n\t\t32,\t\t/* INT: Process state */\n\t\t35,\t\t/* INT: Context switches */\n\t\t41,\t\t/* INT: Process file security */\n\t\t42,\t\t/* INT: Current priority */\n\t\t43,\t\t/* INT: Initial priority */\n\t\t44,\t\t/* INT: Remote creator */\n\t\t45,\t\t/* INT: Logged-on state */\n\t\t47,\t\t/* INT: Prim. or sec.in process pair */\n\t\t48,\t\t/* INT: Process handle */\n\t\t53,\t\t/* FIXED: Creation timestamp */\n\t\t54,\t\t/* INT: No resident pages */\n\t\t55,\t\t/* INT_32: Messages sent */\n\t\t56,\t\t/* INT_32: Messages received */\n\t\t57,\t\t/* INT: Receive queue length */\n\t\t58,\t\t/* INT: Receive queue max.length */\n\t\t59,\t\t/* INT_32: Page faults */\n\t\t63,\t\t/* INT: Stop mode */\n\t\t64,\t\t/* INT: Stop request queue */\n\t\t72,\t\t/* INT: Logon flags and states */\n\t\t73,\t\t/* INT: Applicable attributes */\n\t\t76,\t\t/* INT_32: Curr.process file segment (PFS) size */\n\t\t77,\t\t/* INT_32: Max.process file segment (PFS) extent */\n\t\t102,\t/* INT_32: Base addr.of main stack */\n\t\t103,\t/* INT_32: Current main stack size */\n\t\t104,\t/* INT_32: Max.main stack extent */\n\t\t105,\t/* INT_32: Base addr.of privileged stack */\n\t\t106,\t/* INT_32: Current privileged stack size */\n\t\t107,\t/* INT_32: Max.privileged stack extent */\n\t\t108,\t/* INT_32: Base addr. of global data */\n\t\t109,\t/* INT_32: Size of global data */\n\t\t110,\t/* INT_32: Base addr.of native heap */\n\t\t111,\t/* INT_32: Current native heap size */\n\t\t112\t\t/* INT_32: Max.native heap extent */\n\t\t};\n\n#define NO_PROC_ATTRS\t( sizeof( procAttrList ) / sizeof( short int ) )\n\n/* Get a list of process IDs of all running processes */\n\nstatic int getProcessList( const short int cpuNo, short int *pidBuffer,\n\t\t\t\t\t\t   const short int pidBufSize )\n\t{\n\tconst static short int retAttrList[] = { 38 };\t/* Process ID */\n\tconst static short int srchAttrList[] = { 9 };\t/* Minimum priority */\n\tconst static short int srchValList[] = { 0 };\t/* Priority >= 0 */\n\tshort int error, pin = 0, noAttrs;\n\n\t/* Get a list of active processes by searching for all processes with\n\t   a minimum priority (attribute 9) >= 0, returning a list of all\n\t   process IDs.  The search can return error code 7 (no more matches)\n\t   if we run out of processes before we run out of buffer space, this\n\t   isn't an error since we still got some matches */\n\terror = PROCESS_GETINFOLIST_( cpuNo\t\t\t\t/* CPU no.*/\n\t\t\t\t\t\t\t\t  ,&pin\t\t\t\t/* Process ID */\n\t\t\t\t\t\t\t\t  ,\t\t\t\t\t/* Node name */\n\t\t\t\t\t\t\t\t  ,\t\t\t\t\t/* Node name length */\n\t\t\t\t\t\t\t\t  ,\t\t\t\t\t/* Process handle */\n\t\t\t\t\t\t\t\t  ,( short int * ) retAttrList\n\t\t\t\t\t\t\t\t\t  \t\t\t\t/* Attrs.to read */\n\t\t\t\t\t\t\t\t  ,1\t\t\t\t/* No.attrs.to read */\n\t\t\t\t\t\t\t\t  ,pidBuffer\t\t/* Returned attrs.*/\n\t\t\t\t\t\t\t\t  ,pidBufSize\t\t/* Ret.attrs.buffer size */\n\t\t\t\t\t\t\t\t  ,&noAttrs\t\t\t/* No.returned attrs.*/\n\t\t\t\t\t\t\t\t  ,\t\t\t\t\t/* Error info */\n\t\t\t\t\t\t\t\t  ,2\t\t\t\t/* Find as many as will fit */\n\t\t\t\t\t\t\t\t  ,( short int * ) srchAttrList\n\t\t\t\t\t\t\t\t  \t\t\t\t\t/* Attrs.to search for */\n\t\t\t\t\t\t\t\t  ,1\t\t\t\t/* No.attrs.to search for */\n\t\t\t\t\t\t\t\t  ,( short int * ) srchValList\n\t\t\t\t\t\t\t\t  \t\t\t\t\t/* Attr.value to search for */\n\t\t\t\t\t\t\t\t  ,1\t\t\t\t/* No.attr.values */\n\t\t\t\t\t\t\t\t  );\n\treturn( ( error == 0 || error == 7 ) ? noAttrs : 0 );\n\t}\n\n/* Get various quick pieces of info */\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tlong long totalTime, busyTime, intTime, idleTime;\n\t_cc_status cc;\n\tshort int value, error;\n\tint quality = 0;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* CPU usage info */\n\tcc = CPUTIMES( \t\t\t\t\t\t/* Local CPU */\n\t\t\t\t   ,\t\t\t\t\t/* Local system */\n\t\t\t\t   ,&totalTime\t\t\t/* Wall clock time */\n\t\t\t\t   ,&busyTime\t\t\t/* CPU time */\n\t\t\t\t   ,&intTime\t\t\t/* Interrupt time */\n\t\t\t\t   ,&idleTime\t\t\t/* Idle time */\n\t\t\t\t   );\n\tif( _status_eq( cc ) )\n\t\t{\n\t\taddRandomData( randomState, &totalTime, sizeof( long long ) );\n\t\taddRandomData( randomState, &busyTime, sizeof( long long ) );\n\t\taddRandomData( randomState, &intTime, sizeof( long long ) );\n\t\taddRandomData( randomState, &idleTime, sizeof( long long ) );\n\t\tquality = 2;\n\t\t}\n\n\t/* Message queue info */\n\terror = MESSAGESYSTEMINFO( 4\t\t/* Messages in rcv.queue */\n\t\t\t\t\t\t\t   ,&value\t/* No.messages */\n\t\t\t\t\t\t\t   );\n\tif( error == 0 )\n\t\t{\n\t\taddRandomValue( randomState, value );\n\t\tquality++;\n\t\t}\n\terror = MESSAGESYSTEMINFO( 5\t\t/* Messages in send.queue */\n\t\t\t\t\t\t\t   ,&value\t/* No.messages */\n\t\t\t\t\t\t\t   );\n\tif( error == 0 )\n\t\t{\n\t\taddRandomValue( randomState, value );\n\t\tquality++;\n\t\t}\n\n\t/* Runtime of current process in microseconds */\n\ttotalTime = MYPROCESSTIME();\n\taddRandomData( randomState, &totalTime, sizeof( long long ) );\n\n\t/* Flush any remaining data through */\n#ifdef DEBUG_RANDOM\n\tprintf( \"fastPoll: quality = %d.\\n\", quality );\n#endif /* DEBUG_RANDOM */\n\tendRandomData( randomState, quality );\n\t}\n\n/* Enumerate all processes running on all CPUs and fetch the statistics\n   that are likely to be high-entropy */\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tconst long cpuStatus = PROCESSORSTATUS() & 0xFFFFUL;\n\tlong cpuStatusMask;\n\tshort int cpuNo;\n\tint attrCount = 0;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Enumerate all available CPUs.  Although the docs indicate that\n\t   PROCESSORSTATUS() starts numbering CPUs from bit 0, it actually\n\t   appears to number them from bit 15 */\n\tfor( cpuStatusMask = 0x8000, cpuNo = 0; \\\n\t\t cpuStatusMask > 0; \\\n\t\t cpuStatusMask >>= 1, cpuNo++ )\n\t\t{\n\t\tshort int pidBuffer[ NO_PROCESSES + 8 ];\n\t\tshort int noAttrs, error;\n\t\tint i, noProcesses;\n\n\t\t/* If this CPU isn't available, continue */\n\t\tif( !( cpuStatusMask & cpuStatus ) )\n\t\t\tcontinue;\n\n#ifdef DEBUG_RANDOM\n\t\tprintf( \"Getting info for CPU #%d.\\n\", cpuNo );\n#endif /* DEBUG_RANDOM */\n\t\t/* Get status info for this CPU */\n\t\terror = PROCESSOR_GETINFOLIST_(\t\t\t\t/* Node name */\n\t\t\t\t\t\t\t\t\t\t,\t\t\t/* Node name length */\n\t\t\t\t\t\t\t\t\t\t,cpuNo\t\t/* CPU no.*/\n\t\t\t\t\t\t\t\t\t\t,( short int * ) cpuAttrList\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* Attrs.to read */\n\t\t\t\t\t\t\t\t\t\t,NO_CPU_ATTRS\t/* No.attrs.to read */\n\t\t\t\t\t\t\t\t\t\t,( short int * ) buffer\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t/* Returned attrs.*/\n\t\t\t\t\t\t\t\t\t\t,RANDOM_BUFSIZE / sizeof( short int )\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* Ret.attrs.buffer size */\n\t\t\t\t\t\t\t\t\t\t,&noAttrs\t/* No.returned attrs.*/\n\t\t\t\t\t\t\t\t\t\t);\n\t\tif( error == 0 )\n\t\t\t{\n#ifdef DEBUG_RANDOM\n\t\t\tprintf( \"PROCESSOR_GETINFOLIST returned %d attributes.\\n\",\n\t\t\t\t\tnoAttrs );\n#endif /* DEBUG_RANDOM */\n\t\t\taddRandomData( randomState, buffer,\n\t\t\t\t\t\t   noAttrs * sizeof( short int ) );\n\t\t\tattrCount += noAttrs / 2;\n\t\t\t}\n\n\t\t/* Get status info for the first NO_PROCESSES processes on this\n\t\t   CPU */\n\t\tnoProcesses = getProcessList( cpuNo, pidBuffer, NO_PROCESSES );\n\t\tif( noProcesses <= 0 )\n\t\t\t{\n\t\t\t/* If the process-list read fails for some reason, we can still\n\t\t\t   get info for at least the first two processes, which are\n\t\t\t   always present */\n\t\t\tnoProcesses = 2;\n\t\t\tpidBuffer[ 0 ] = 0;\n\t\t\tpidBuffer[ 1 ] = 1;\n\t\t\t}\n\t\tfor( i = 0; i < noProcesses; i++ )\n\t\t\t{\n\t\t\tshort int pin = pidBuffer[ i ];\n\n\t\t\terror = PROCESS_GETINFOLIST_( cpuNo\t\t/* CPU no.*/\n\t\t\t\t\t\t\t\t\t\t  ,&pin\t\t/* Process ID */\n\t\t\t\t\t\t\t\t\t\t  ,\t\t\t/* Node name */\n\t\t\t\t\t\t\t\t\t\t  ,\t\t\t/* Node name length */\n\t\t\t\t\t\t\t\t\t\t  ,\t\t\t/* Process handle */\n\t\t\t\t\t\t\t\t\t\t  ,( short int * ) procAttrList\n\t\t\t\t\t\t\t\t\t\t  \t\t\t/* Attrs.to read */\n\t\t\t\t\t\t\t\t\t\t  ,NO_PROC_ATTRS/* No.attrs.to read */\n\t\t\t\t\t\t\t\t\t\t  ,( short int * ) buffer\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* Returned attrs.*/\n\t\t\t\t\t\t\t\t\t\t  ,RANDOM_BUFSIZE / sizeof( short int )\n\t\t\t\t\t\t\t\t\t\t\t\t\t/* Ret.attrs.buffer size */\n\t\t\t\t\t\t\t\t\t\t  ,&noAttrs\t/* No.returned attrs.*/\n\t\t\t\t\t\t\t\t\t\t  );\n\t\t\tif( error == 0 )\n\t\t\t\t{\n#ifdef DEBUG_RANDOM\n\t\t\t\tprintf( \"PROCESS_GETINFOLIST returned %d attributes for \"\n\t\t\t\t\t\t\"process %d.\\n\", noAttrs, pin );\n#endif /* DEBUG_RANDOM */\n\t\t\t\taddRandomData( randomState, buffer,\n\t\t\t\t\t\t\t   noAttrs * sizeof( short int ) );\n\t\t\t\tattrCount += max( noAttrs / 5, 10 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Flush any remaining data through.  Quality = attrCount */\n\tendRandomData( randomState, min( attrCount, 100 ) );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/telit.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tThreadX Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/threadx.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tThreadX Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/ucosii.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tuC/OS II Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/uitron.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t uITRON Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/unix.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Unix Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2018\t\t\t\t\t*\n*\tContributions to slow-poll code by Paul Kendall and Chris Wedgwood\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* Define the following to a nonzero value to print diagnostic information \n   on where randomness is coming from */\n\n#ifndef NDEBUG\n  #define debugRandom\t\t0\n#endif /* NDEBUG */\n\n/* General includes */\n\n#if defined( __GNUC__ )\n  #define _GNU_SOURCE\n#endif /* Needed for newer functions like setresuid() */\n#include <stdio.h>\n#include <time.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* Unix and Unix-like systems share the same makefile, make sure that the\n   user isn't trying to use the Unix randomness code under a non-Unix (but\n   Unix-like) system.  This would be pretty unlikely since the makefile\n   automatically adjusts itself based on the environment it's running in,\n   but we use the following safety check just in case.  We have to perform\n   this check before we try any includes because Unix and the Unix-like\n   systems don't have the same header files */\n\n#ifdef __BEOS__\n  #error For the BeOS build you need to edit $MISCOBJS in the makefile to use 'beos' and not 'unix'\n#endif /* BeOS has its own randomness-gathering file */\n#ifdef __ECOS__\n  #error For the eCOS build you need to edit $MISCOBJS in the makefile to use 'ecos' and not 'unix'\n#endif /* eCOS has its own randomness-gathering file */\n#ifdef __ITRON__\n  #error For the uITRON build you need to edit $MISCOBJS in the makefile to use 'itron' and not 'unix'\n#endif /* uITRON has its own randomness-gathering file */\n#ifdef __PALMSOURCE__\n  #error For the PalmOS build you need to edit $MISCOBJS in the makefile to use 'palmos' and not 'unix'\n#endif /* PalmOS has its own randomness-gathering file */\n#ifdef __RTEMS__\n  #error For the RTEMS build you need to edit $MISCOBJS in the makefile to use 'rtems' and not 'unix'\n#endif /* RTEMS has its own randomness-gathering file */\n#if defined( __TANDEM_NSK__ ) || defined( __TANDEM_OSS__ )\n  #error For the Tandem build you need to edit $MISCOBJS in the makefile to use 'tandem' and not 'unix'\n#endif /* Tandem OSS has its own randomness-gathering file */\n#if defined( __VxWorks__ )\n  #error For the VxWorks build you need to edit $MISCOBJS in the makefile to use 'vxworks' and not 'unix'\n#endif /* VxWorks has its own randomness-gathering file */\n#if defined( __XMK__ )\n  #error For the Xilinx XMK build you need to edit $MISCOBJS in the makefile to use 'xmk' and not 'unix'\n#endif /* XMK has its own randomness-gathering file */\n\n/* Some systems built on top of Unix kernels and/or Unix-like systems don't \n   support certain functionality like the SYSV shared memory that's used for \n   last-line-of-defence entropy polling, or only support it in an erratic \n   manner that we can't rely on.  For these systems we replace the shared-\n   memory-based polling with a stub the prints an error message for the\n   caller */\n\n#if defined( __Android__ ) || ( defined( __QNX__ ) && OSVERSION <= 4 )\n  #define NO_SYSV_SHAREDMEM\n#endif /* Android || QNX <= 4.x */\n\n/* OS-specific includes */\n\n#if defined( __hpux ) && ( OSVERSION >= 10 )\n  #define _XOPEN_SOURCE_EXTENDED\n#endif /* Workaround for inconsistent PHUX networking headers */\n#include <unistd.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <pwd.h>\n#if !( defined( __QNX__ ) || defined( __MVS__ ) )\n  #include <sys/errno.h>\n  #include <sys/ipc.h>\n#endif /* !( QNX || MVS ) */\n#include <sys/time.h>\t\t/* SCO and SunOS need this before resource.h */\n#ifndef __QNX__\n  #if defined( _MPRAS ) && !( defined( _XOPEN_SOURCE ) && \\\n\t  defined( __XOPEN_SOURCE_EXTENDED ) )\n\t/* On MP-RAS 3.02, the X/Open test macros must be set to include\n\t   getrusage(). */\n\t#define _XOPEN_SOURCE\t\t\t1\n\t#define _XOPEN_SOURCE_EXTENDED\t1\n\t#define MPRAS_XOPEN_DEFINES\n  #endif /* MP-RAS */\n  #include <sys/resource.h>\n  #if defined( MPRAS_XOPEN_DEFINES )\n\t#undef _XOPEN_SOURCE\n\t#undef _XOPEN_SOURCE_EXTENDED\n\t#undef MPRAS_XOPEN_DEFINES\n  #endif /* MP-RAS */\n#endif /* QNX */\n#ifdef __linux__ \n  #include <linux/random.h>\n#endif /* Linux */\n#ifdef __iOS__ \n  #include <Security/SecRandom.h>\n#endif /* __iOS__  */\n#if defined( _AIX ) || defined( __QNX__ )\n  #include <sys/select.h>\n#endif /* Aches || QNX */\n#ifdef _AIX\n  #include <sys/systemcfg.h>\n#endif /* Aches */\n#ifdef __CYGWIN__\n  #include <signal.h>\n  #include <sys/ipc.h>\n  #include <sys/sem.h>\n  #include <sys/shm.h>\n#endif /* CYGWIN */\n#if !( defined( __Android__ ) || defined( __CYGWIN__ ) || defined( __QNX__ ) )\n  #include <sys/shm.h>\n#endif /* !( __Android__  || Cygwin || QNX ) */\n#if defined( __linux__ ) && ( defined(__i386__) || defined(__x86_64__) )\n  #include <sys/timex.h>\t/* For rdtsc() */\n#endif /* Linux on x86 */\n#if defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __APPLE__ )\n  /* Get BSD version macros.  This is less useful, or at least portable, \n     than it seems because the recommended 'BSD' macro is frozen in time in \n\t the 1990s, and so each BSD variant has defined its own replacement, or\n\t in some cases several for good measures.  FreeBSD has \n\t '__FreeBSD_version' as a 7-digit decimal with the MSB being the major\n\t version, NetBSD has 'NetBSD' but this is frozen in 1999, the current \n\t form is '__NetBSD_Version__' as an 8-digit decimal with the MSB being \n\t the major version, OpenBSD has 'OpenBSD' in the BSD-standard YYYYMM \n\t format, and Apple has a 'NeXTBSD' frozen in 1995 but otherwise only\n\t '__APPLE_CC__' for the compiler version, otherwise all we have is\n\t <TargetConditionals.h> to tell us whether we're building for OS X vs.\n\t iOS (TARGET_OS_*) and the CPU type (TARGET_CPU_*) */\n  #include <sys/param.h>\n#endif /* *BSDs */\n#include <signal.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/types.h>\t\t/* Verschiedene komische Typen */\n#include <sys/un.h>\n#include <sys/wait.h>\n/* #include <kitchensink.h> */\n\n/* Crays and QNX 4.x don't have a rlimit/rusage so we have to fake the\n   functions and structs */\n\n#if defined( _CRAY ) || \\\n\t( defined( __QNX__ ) && OSVERSION <= 4 )\n  #define setrlimit( x, y )\n  struct rlimit { int dummy1, dummy2; };\n  struct rusage { int dummy; };\n#endif /* Systems without rlimit/rusage */\n\n/* If we're using threads, we have to protect the entropy gatherer with\n   a mutex to prevent multiple threads from trying to initate polls at the\n   same time.  Unlike the kernel mutexes, we don't have to worry about\n   being called recursively, so there's no need for special-case handling\n   for Posix' nasty non-reentrant mutexes */\n\n#ifdef USE_THREADS\n  #include <pthread.h>\n\n  #define lockPollingMutex()\tpthread_mutex_lock( &gathererMutex )\n  #define unlockPollingMutex()\tpthread_mutex_unlock( &gathererMutex )\n#else\n  #define lockPollingMutex()\n  #define unlockPollingMutex()\n#endif /* USE_THREADS */\n\n/* glibc, in line with its general policy of insanity, caches the pid so\n   that changes aren't visible (see \n   http://yarchive.net/comp/linux/getpid_caching.html).  Because of this, \n   we have to bypass the braindamage by invoking the pid syscall directly \n   in order to get the actual pid */\n\n#if defined( __GNUC__ ) && defined( SYS_getpid )\n\t#define getpid()\t( ( pid_t ) syscall( SYS_getpid ) )\n#endif /* glibc braindamage */\n\n/* The size of the intermediate buffer used to accumulate polled data,\n   and an extra-large version for calls that return lots of data */\n\n#define RANDOM_BUFSIZE\t\t\t4096\n#define BIG_RANDOM_BUFSIZE\t\t( RANDOM_BUFSIZE * 2 )\n\n#if BIG_RANDOM_BUFSIZE >= MAX_INTLENGTH_SHORT\n  #error RANDOM_BUFSIZE exceeds randomness accumulator size\n#endif /* RANDOM_BUFSIZE >= MAX_INTLENGTH_SHORT */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __hpux ) && ( OSVERSION == 9 )\n\n/* PHUX 9.x doesn't support getrusage in libc (wonderful...) */\n\n#include <syscall.h>\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int getrusage( int who, OUT struct rusage *rusage )\n\t{\n\treturn( syscall( SYS_getrusage, who, rusage ) );\n\t}\n#endif /* __hpux */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tFast Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Fast poll - not terribly useful.  SCO has a gettimeofday() prototype but\n   no actual system call that implements it, and no getrusage() at all, so\n   we use times() instead */\n\n#if defined( _CRAY ) || defined( _M_XENIX )\n  #include <sys/times.h>\n#endif /* Systems without getrusage() */\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n#if !( defined( _CRAY ) || defined( _M_XENIX ) )\n\tstruct timeval tv;\n  #if !( defined( __QNX__ ) && OSVERSION <= 4 )\n\tstruct rusage rusage;\n  #endif /* !QNX 4.x */\n#else\n\tstruct tms tms;\n#endif /* Systems without getrusage() */\n#ifdef _AIX\n\ttimebasestruct_t cpuClockInfo;\n#endif /* Aches */\n#if ( defined( sun ) && ( OSVERSION >= 5 ) )\n\thrtime_t hrTime;\n#endif /* Slowaris */\n#if defined( __clang__ ) && \\\n\t!( defined( __arm ) || defined( __arm__ ) || \\\n\t   defined( __aarch64__ ) || defined( __arm64 ) )\n  #if __has_builtin( __builtin_readcyclecounter )\n\tunsigned long long cycleCounterValue;\n  #endif /* Built-in function support */\n#endif /* __clang__ with readcyclecounter() */\n#if ( defined( __QNX__ ) && OSVERSION >= 5 )\n\tuint64_t clockCycles;\n#endif /* QNX */\n#if defined( _POSIX_TIMERS ) && ( _POSIX_TIMERS > 0 ) && 0\t/* See below */\n\tstruct timespec timeSpec;\n#endif /* _POSIX_TIMERS > 0 */\n\tint status;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_V( cryptStatusOK( status ) );\n\n\t/* Mix in the process ID.  This doesn't change per process but will\n\t   change if the process forks, ensuring that the child data differs \n\t   from the parent */\n\taddRandomValue( randomState, getpid() );\n\n#if !( defined( _CRAY ) || defined( _M_XENIX ) )\n\tgettimeofday( &tv, NULL );\n\taddRandomValue( randomState, tv.tv_sec );\n\taddRandomValue( randomState, tv.tv_usec );\n\n\t/* SunOS 5.4 has the function call but no prototypes for it, if you're\n\t   compiling this under 5.4 you'll have to copy the header files from 5.5\n\t   or something similar */\n  #if !( defined( __QNX__ ) && OSVERSION <= 4 )\n\tgetrusage( RUSAGE_SELF, &rusage );\n\taddRandomData( randomState, &rusage, sizeof( struct rusage ) );\n  #endif /* !QNX 4.x */\n#else\n\t/* Merely a subset of getrusage(), but it's the best that we can do.  On\n\t   Crays it provides access to the hardware clock, so the data is quite\n\t   good */\n\ttimes( &tms );\n\taddRandomData( randomState, &tms, sizeof( struct tms ) );\n#endif /* Systems without getrusage() */\n#ifdef _AIX\n\t/* Add the value of the nanosecond-level CPU clock or time base register */\n\tread_real_time( &cpuClockInfo, sizeof( timebasestruct_t ) );\n\taddRandomData( randomState, &cpuClockInfo, sizeof( timebasestruct_t ) );\n#endif /* _AIX */\n#if ( defined( sun ) && ( OSVERSION >= 5 ) )\n\t/* Read the Sparc %tick register (equivalent to the P5 TSC).  This is\n\t   only readable by the kernel by default, although Solaris 8 and newer\n\t   make it readable in user-space.  To do this portably, we use\n\t   gethrtime(), which does the same thing */\n\thrTime = gethrtime();\n\taddRandomData( randomState, &hrTime, sizeof( hrtime_t ) );\n#endif /* Slowaris */\n#ifdef rdtscl\n\tif( getSysCaps() & SYSCAP_FLAG_RDTSC )\n\t\t{\n\t\tunsigned long tscValue;\n\n\t\trdtscl( tscValue );\n\t\taddRandomValue( randomState, tscValue );\n\t\t}\n#endif /* rdtsc available */\n#if defined( __clang__ ) && \\\n\t!( defined( __arm ) || defined( __arm__ ) || \\\n\t   defined( __aarch64__ ) || defined( __arm64 ) )\n  /* ARM systems have a cycle-counter that's accessed via \n     \"mrs reg, PMCCNTR_EL0\", but access from user-space to this, and the\n\t Performance Monitoring Unit (PMU) that it's part of, is usually \n\t disabled by default.  What this means is that the compiler will emit \n\t an instruction that faults when executed, see e.g.\n\t http://neocontra.blogspot.com/2013/05/user-mode-performance-counters-for.html\n\t http://zhiyisun.github.io/2016/03/02/How-to-Use-Performance-Monitor-Unit-(PMU)-of-64-bit-ARMv8-A-in-Linux.html  \n\t Because it's unlikely to work in practice, we disable it for ARM\n\t systems even if the compiler would otherwise give us the intrinsic \n\t needed to access it */\n  #if __has_builtin( __builtin_readcyclecounter )\n\tcycleCounterValue = __builtin_readcyclecounter();\n\n\taddRandomData( randomState, &cycleCounterValue, sizeof( long long ) );\n  #endif /* Built-in function support */\n#endif /* __clang__ */\n#if ( defined( __QNX__ ) && OSVERSION >= 5 )\n\t/* Return the output of RDTSC or its equivalent on other systems.  We\n\t   don't worry about locking the thread to a CPU since we're not using\n\t   it for timing (in fact being run on another CPU helps the entropy) */\n\tclockCycles = ClockCycles();\n\taddRandomData( randomState, &clockCycles, sizeof( uint64_t ) );\n#endif /* QNX */\n\t/* Get real-time (or as close to it as possible) clock information if \n\t   it's available.  These values are platform-specific, but typically use \n\t   a high-resolution source like the Pentium TSC.\n\t   \n\t   (Unfortunately we can't safely use this function because it's often \n\t   not present in libc but needs to be pulled in via the real-time \n\t   extensions library librt instead, which causes all sorts of \n\t   portability problems) */\n#if defined( _POSIX_TIMERS ) && ( _POSIX_TIMERS > 0 ) && 0\n\tif( clock_gettime( CLOCK_REALTIME, &timeSpec ) == 0 )\n\t\taddRandomData( randomState, &timeSpec, sizeof( struct timespec ) );\n\tif( clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &timeSpec ) == 0 )\n\t\taddRandomData( randomState, &timeSpec, sizeof( struct timespec ) );\n\tif( clock_gettime( CLOCK_THREAD_CPUTIME_ID, &timeSpec ) == 0 )\n\t\taddRandomData( randomState, &timeSpec, sizeof( struct timespec ) );\n#endif /* _POSIX_TIMERS > 0 */\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 1 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSystem-specific Slow Poll Sources\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* *BSD-specific poll using sysctl */\n\n#if defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __APPLE__ )\n\n#define USE_SYSCTL\n#include <sys/sysctl.h>\n#include <netinet/in.h>\t\t\t\t/* For CTL_NET identifiers */\n#if defined( __APPLE__ )\n  /* The iPhone native SDK (but not the emulator) gets the paths for some of\n\t the include files wrong, so we have to use absolute paths.  To make \n\t things even crazier, starting with XCode 10 Apple decided that \n\t /usr/include wasn't where include files should go (see\n\t https://apple.stackexchange.com/questions/337940/why-is-usr-include-missing-i-have-xcode-and-command-line-tools-installed-moja)\n\t so we have to hardcode bizarro SDK paths for newer versions.  This is\n\t made even more complicated by the fact that there's no compile-time \n\t mechanism for checking which version of XCode is being used, so we have\n\t to use the badly-misnamed __IPHONE_OS_VERSION_MAX_ALLOWED define for \n\t the purpose */\n  #if TARGET_OS_IPHONE || TARGET_OS_WATCH\n\t#if ( __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 )\n\t  #include \"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/net/route.h\"\n\t  #include \"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/gmon.h\"\n\t#else\n\t  #include \"/usr/include/net/route.h\"\n\t  #include \"/usr/include/sys/gmon.h\"\n\t#endif /* Apple insanity */\n  #else\n\t#include <net/route.h>\t\t\t/* For CTL_NET:AF_ROUTE:0:AF_INET:\\\n\t\t\t\t\t\t\t\t\t   NET_RT_FLAGS idents */\n\t#include <sys/gmon.h>\t\t\t/* For CTL_KERN:KERN_PROF identifiers */\n  #endif /* Native iOS SDK vs. everything else */\n#else\n  #include <net/route.h>\t\t\t/* For CTL_NET:AF_ROUTE:0:AF_INET:\\\n\t\t\t\t\t\t\t\t\t   NET_RT_FLAGS idents */\n  #include <sys/gmon.h>\t\t\t\t/* For CTL_KERN:KERN_PROF identifiers */\n  #if defined( __NetBSD__ )\n\t#include <uvm/uvm_param.h>\t\t/* For CTL_VM identifiers */\n  #else\n\t#include <vm/vm_param.h>\t\t/* For CTL_VM identifiers */\n  #endif /* BSD-variant-specific include paths */\n#endif /* OS-specific include paths */\n\ntypedef struct {\n\tconst int mibCount;\t\t\t\t/* Number of MIB entries */\n\tconst int mib[ 6 ];\t\t\t\t/* MIB values for this info */\n\tconst int quality;\t\t\t\t/* Entropy quality if present */\n\t} SYSCTL_INFO;\n\nstatic const SYSCTL_INFO sysctlInfo[] = {\n\t/* Hardware info */\n\t{ 2, { CTL_HW, HW_MACHINE } },\t/* Machine class */\n\t{ 2, { CTL_HW, HW_MACHINE_ARCH } }, /* Machine architecture */\n\t{ 2, { CTL_HW, HW_MODEL } },\t/* Machine model */\n#ifdef HW_IOSTATS\n\t{ 2, { CTL_HW, HW_IOSTATS } },\t/* struct io_sysctl for each device \n\t\t\t\t\t\t\t\t\t   containing microsecond times and byte \n\t\t\t\t\t\t\t\t\t   counts */\n#endif /* HW_IOSTATS */\n\t{ 2, { CTL_HW, HW_PHYSMEM } },\t/* Physical memory */\n#ifdef HW_REALMEM\n\t{ 2, { CTL_HW, HW_REALMEM } },\t/* Real memory */\n#endif /* HW_REALMEM */\n\t{ 2, { CTL_HW, HW_USERMEM } },\t/* Non-kernel memory */\n#ifdef HW_DISKSTATS\n\t{ 2, { CTL_HW, HW_DISKSTATS } },/* struct diskstats for each disk,\n\t\t\t\t\t\t\t\t\t   structure format undocumented */\n#endif /* HW_DISKSTATS */\n\n\t/* Kernel info */\n\t{ 2, { CTL_KERN, KERN_BOOTTIME }, 1 }, \n\t\t\t\t\t\t\t\t\t/* Time system was booted */\n\t{ 2, { CTL_KERN, KERN_CLOCKRATE } },\n\t\t\t\t\t\t\t\t\t/* struct clockinfo of clock frequecies */\n#ifdef KERN_CP_TIME\n\t{ 2, { CTL_KERN, KERN_CP_TIME }, 1 },\n\t\t\t\t\t\t\t\t\t/* Number of clock ticks in different CPU\n\t\t\t\t\t\t\t\t\t   states */\n#endif /* KERN_CP_TIME */\n#ifdef KERN_DRIVERS\n\t{ 2, { CTL_KERN, KERN_DRIVERS } },/* struct kinfo_drivers with major/minor\n\t\t\t\t\t\t\t\t\t   ID and name for all drivers */\n#endif /* KERN_DRIVERS */\n#ifdef KERN_EVCNT\n\t{ 2, { CTL_KERN, KERN_EVCNT } },/* struct evcnts for all active event \n\t\t\t\t\t\t\t\t\t   counters.  There usually won't be any\n\t\t\t\t\t\t\t\t\t   set so this won't produce a result from\n\t\t\t\t\t\t\t\t\t   sysctl() */\n#endif /* KERN_EVCNT */\n\t{ 2, { CTL_KERN, KERN_FILE }, 5 }, \n\t\t\t\t\t\t\t\t\t/* struct xfile for each file in the system, \n\t\t\t\t\t\t\t\t\t   containing process IDs, fd no., ref.count, \n\t\t\t\t\t\t\t\t\t   file offset, vnode, and flags.  Produces a\n\t\t\t\t\t\t\t\t\t   huge amount of output so typically gets\n\t\t\t\t\t\t\t\t\t   truncated at SYSCTL_BUFFER_SIZE */\n#ifdef KERN_HARDCLOCK_TICKS\n\t{ 2, { CTL_KERN, KERN_HARDCLOCK_TICKS } },\n\t\t\t\t\t\t\t\t\t/* Number of hardclock (hard real-time timer) \n\t\t\t\t\t\t\t\t\t   ticks */\n#endif /* KERN_HARDCLOCK_TICKS */\n\t{ 2, { CTL_KERN, KERN_HOSTID } }, /* Host ID */\n\t{ 2, { CTL_KERN, KERN_HOSTNAME } },\t/* Hostname */\n#ifdef KERN_HOSTUUID\n\t{ 2, { CTL_KERN, KERN_HOSTUUID } },\t/* Host UUID */\n#endif /* KERN_HOSTUUID */\n#ifdef KERN_NTPTIME\n\t{ 2, { CTL_KERN, KERN_NTPTIME }, 1 },\n\t\t\t\t\t\t\t\t\t/* struct ntptimeval with NTP accuracy\n\t\t\t\t\t\t\t\t\t   information */\n\t{ 2, { CTL_KERN, KERN_TIMEX }, 3 }, \n\t\t\t\t\t\t\t\t\t/* struct timex containing detailed NTP\n\t\t\t\t\t\t\t\t\t   statistics.  This is a useful source\n\t\t\t\t\t\t\t\t\t   but typically isn't available so won't \n\t\t\t\t\t\t\t\t\t   produce a result from sysctl() */\n#endif /* KERN_NTPTIME */\n#ifdef KERN_OSRELDATE\n\t{ 2, { CTL_KERN, KERN_OSRELDATE } }, /* OS release version */\n#endif /* KERN_OSRELDATE */\n\t{ 2, { CTL_KERN, KERN_OSRELEASE } }, /* OS release string */\n\t{ 2, { CTL_KERN, KERN_OSREV } }, /* System revision string */\n\t{ 2, { CTL_KERN, KERN_OSTYPE } }, /* System type string */\n\t{ 3, { CTL_KERN, KERN_PROC, KERN_PROC_ALL }, 20, }, \n\t\t\t\t\t\t\t\t\t/* struct kinfo_proc for each process \n\t\t\t\t\t\t\t\t\t   containing a struct proc and a struct \n\t\t\t\t\t\t\t\t\t   eproc which contain everything you \n\t\t\t\t\t\t\t\t\t   could want to know about a process,\n\t\t\t\t\t\t\t\t\t   see /sys/sys/proc.h and \n\t\t\t\t\t\t\t\t\t   /sys/sys/kinfo_proc.h.  Produces a\n\t\t\t\t\t\t\t\t\t   huge amount of output so typically \n\t\t\t\t\t\t\t\t\t   gets truncated at SYSCTL_BUFFER_SIZE */\n#ifdef KERN_PROC2\n\t{ 6, { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, 0, sizeof( struct kinfo_proc2 ), 20 }, 10, }, \n\t\t\t\t\t\t\t\t\t/* struct kinfo_proc2 containing a \n\t\t\t\t\t\t\t\t\t   superset of struct kinfo_proc.  We \n\t\t\t\t\t\t\t\t\t   give this a lower weight than it \n\t\t\t\t\t\t\t\t\t   actually contains because a of the \n\t\t\t\t\t\t\t\t\t   contents have already been obtained\n\t\t\t\t\t\t\t\t\t   via KERN_PROC.  Produces a huge \n\t\t\t\t\t\t\t\t\t   amount of output so typically gets\n\t\t\t\t\t\t\t\t\t   truncated at SYSCTL_BUFFER_SIZE */\n#endif /* KERN_PROC2 */\n\t{ 3, { CTL_KERN, KERN_PROF, GPROF_COUNT }, 10 },\n\t\t\t\t\t\t\t\t\t/* If kernel is compiled for profiling, \n\t\t\t\t\t\t\t\t\t   an array of statistical program \n\t\t\t\t\t\t\t\t\t   counter counts.  This typically isn't\n\t\t\t\t\t\t\t\t\t   enabled so won't produce a result from\n\t\t\t\t\t\t\t\t\t   sysctl() */\n#ifdef KERN_TKSTAT\n\t{ 3, { CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_CANCC } },\n\t{ 3, { CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NIN } },\n\t{ 3, { CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NOUT } },\n\t{ 3, { CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_RAWCC } },\n\t\t\t\t\t\t\t\t\t/* Terminal chars sent/received */\n#endif /* KERN_TKSTAT */\n\t{ 2, { CTL_KERN, KERN_VERSION } }, /* System version string  */\n\t{ 2, { CTL_KERN, KERN_VNODE }, 15 }, \n\t\t\t\t\t\t\t\t\t/* struct xvnode for each vnode, see \n\t\t\t\t\t\t\t\t\t   /sys/sys/vnode.h.  Produces a huge \n\t\t\t\t\t\t\t\t\t   amount of output so typically gets\n\t\t\t\t\t\t\t\t\t   truncated at SYSCTL_BUFFER_SIZE */\n\n\t/* Networking info */\n\t{ 6, { CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0 }, 5 },\n\t\t\t\t\t\t\t\t\t/* IPv4 routing table */\n\t{ 6, { CTL_NET, AF_ROUTE, 0, AF_INET6, NET_RT_DUMP, 0 }, 5 },\n\t\t\t\t\t\t\t\t\t/* IPv6 routing table */\n\t{ 6, { CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO }, 5 },\n\t\t\t\t\t\t\t\t\t/* ARP cache */\n\n\t/* VM info */\n#ifdef VM_LOADAVG \n\t{ 2, { CTL_VM, VM_LOADAVG } },\t/* Load average */\n#endif /* VM_LOADAVG */\n#ifdef VM_TOTAL\n\t{ 2, { CTL_VM, VM_TOTAL }, 5 },\t/* struct vmtotal with count of jobs in\n\t\t\t\t\t\t\t\t\t   various states and amounts of virtual\n\t\t\t\t\t\t\t\t\t   memory */\n#endif /* VM_TOTAL */\n#ifdef VM_METER\n\t{ 2, { CTL_VM, VM_METER }, 5 },\t/* Another name for VM_TOTAL */\n#endif /* VM_METER */\n#ifdef VM_UVMEXP\n\t{ 2, { CTL_VM, VM_UVMEXP }, 10 },\t\n\t\t\t\t\t\t\t\t\t/* struct uvmexp containing global state \n\t\t\t\t\t\t\t\t\t   of the UVM system */\n#endif /* VM_UVMEXP */\n\t{ 0, { 0 } }, { 0, { 0 } }\n\t};\n\n#define SYSCTL_BUFFER_SIZE\t\t\t16384\n\nCHECK_RETVAL \\\nstatic int getSysctlData( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ BIG_RANDOM_BUFSIZE + 8 ];\n\tBYTE sysctlBuffer[ SYSCTL_BUFFER_SIZE + 8 ];\n\tint quality = 0, i, status;\n\n\tstatus = initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Get each set of sysctl() information.  Since some of the information \n\t   returned can be rather lengthy, we optionally send it directly to the \n\t   randomness pool rather than using the accumulator */\n\tfor( i = 0; sysctlInfo[ i ].mibCount != 0; i++ )\n\t\t{\n\t\tsize_t size = SYSCTL_BUFFER_SIZE;\n\n\t\t/* Since we only care about the information that's returned as an \n\t\t   entropy source, we treat a buffer-not-large-enough error (errno\n\t\t   = ENOMEM) as an OK status for the purpose of providing entropy.  \n\t\t   Since ENOMEM can be returned for reasons other than the buffer \n\t\t   not being large enough, we sanity-check the result by requiring\n\t\t   that at least half of the buffer was filled with information */\n\t\terrno = 0;\n \t\tstatus = sysctl( ( int * ) sysctlInfo[ i ].mib, \n\t\t\t\t\t\t sysctlInfo[ i ].mibCount, \n\t\t\t\t\t\t sysctlBuffer, &size, NULL, 0 );\n\t\tif( status == -1 && errno == ENOMEM )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Overflow in sysctl %d:%d, using %d bytes\", \n\t\t\t\t\t\t sysctlInfo[ i ].mib[ 0 ], sysctlInfo[ i ].mib[ 1 ], \n\t\t\t\t\t\t size ));\n\t\t\tif( size >= SYSCTL_BUFFER_SIZE / 2 )\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\tif( status )\n\t\t\tcontinue;\n\t\tDEBUG_PRINT_COND( debugRandom,\n\t\t\t\t\t\t  ( \"Got %d bytes data from sysctl %d:%d.\\n\", \n\t\t\t\t\t\t\tsize, sysctlInfo[ i ].mib[ 0 ], \n\t\t\t\t\t\t\tsysctlInfo[ i ].mib[ 1 ] ));\n\n\t\t/* Some sysctl() calls can successfully return zero bytes, so we \n\t\t   check for this special case and continue */\n\t\tif( size <= 0 )\n\t\t\tcontinue;\n\n\t\t/* We got some data, add it to the entropy pool */\n\t\tif( size > BIG_RANDOM_BUFSIZE )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tsetMessageData( &msgData, sysctlBuffer, size );\n\t\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t}\n\t\telse\n\t\t\taddRandomData( randomState, sysctlBuffer, size );\n\t\tquality += sysctlInfo[ i ].quality;\n\t\t}\n\n\t/* Flush any remaining data through and provide an estimate of its\n\t   value.  We cap it at 80 to ensure that some data is still coming \n\t   from other sources */\n\tif( quality > 80 )\n\t\tquality = 80;\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom,\n\t\t\t\t\t  ( \"sysctl contributed %d value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n#endif /* *BSDs */\n\n/* BSD/Linux-specific polling using getifaddrs() */\n\n#if defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __APPLE__ ) || \\\n\tdefined( __linux__  )\n\n#define USE_GETIFADDRS\n#include <ifaddrs.h>\n#include <netinet/in.h>\n#ifdef __linux__\n  #include <linux/if_link.h>\n#endif /* __linux__ */\n\nCHECK_RETVAL \\\nstatic int getIfaddrsData( void )\n\t{\n\tRANDOM_STATE randomState;\n\tstruct ifaddrs *ifAddr, *ifAddrPtr;\n\tBYTE buffer[ BIG_RANDOM_BUFSIZE + 8 ];\n\tint quality = 0, status;\n\n\tstatus = initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Walk through all interfaces getting statistics for them.  The only\n\t   really interesting one is AF_PACKET, which gives us packet \n\t   statistics */\n\tif( getifaddrs( &ifAddr ) < 0 )\n\t\treturn( 0 );\t\n\tfor( ifAddrPtr = ifAddr; ifAddrPtr != NULL; \n\t\t ifAddrPtr = ifAddrPtr->ifa_next )\n\t\t{\n\t\tvoid *infoPtr = NULL;\n\t\tint infoSize = 0;\n\t\t\n\t\tif( ifAddrPtr->ifa_addr == NULL )\n\t\t\tcontinue;\n\n\t\tswitch( ifAddrPtr->ifa_addr->sa_family )\n\t\t\t{\n\t\t\tcase AF_INET:\n\t\t\t\tinfoPtr = ifAddrPtr->ifa_addr;\n\t\t\t\tinfoSize = sizeof( struct sockaddr_in );\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase AF_INET6:\n\t\t\t\tinfoPtr = ifAddrPtr->ifa_addr;\n\t\t\t\tinfoSize = sizeof( struct sockaddr_in6 );\n\t\t\t\tbreak;\n\n#ifdef AF_PACKET\n\t\t\tcase AF_PACKET:\n\t\t\t\tif( ifAddrPtr->ifa_data == NULL )\n\t\t\t\t\tbreak;\n\t\t\t\tinfoPtr = ifAddrPtr->ifa_data;\n\t\t\t\tinfoSize = sizeof( struct rtnl_link_stats );\n\t\t\t\tquality += 2;\n\t\t\t\tbreak;\n#endif /* AF_PACKET */\n\t\t\t\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( infoPtr == NULL )\n\t\t\tcontinue;\n\t\taddRandomData( randomState, infoPtr, infoSize );\n\t\t}\n\tfreeifaddrs( ifAddr );\n\n\t/* Flush any remaining data through and provide an estimate of its\n\t   value.  We cap it at 80 to ensure that some data is still coming \n\t   from other sources */\n\tif( quality > 15 )\n\t\tquality = 15;\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"getifaddrs contributed %d entropy quality.\\n\", \n\t\t\t\t\t    quality ));\n\n\treturn( quality );\n\t}\n#endif /* *BSDs and Linux */\n\n/* BSD-specific polling using getfsstat() */\n\n#if defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __APPLE__ )\n\n#define USE_GETFSSTAT\n#include <sys/mount.h>\n\n#define FSSTAT_BUFFER_SIZE\t\t16384\n\nCHECK_RETVAL \\\nstatic int getFsstatData( void )\n\t{\n\tRANDOM_STATE randomState;\n\tstruct ifaddrs *ifAddr, *ifAddrPtr;\n\tBYTE buffer[ BIG_RANDOM_BUFSIZE + 8 ];\n\tBYTE fsstatBuffer[ FSSTAT_BUFFER_SIZE + 8 ];\n\tint quality = 0, count, status;\n\n\tstatus = initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Get statistics for all mounted filesystems, both standard static \n\t   information and dynamic data like free space, free file inodes, \n\t   and read/write statistics */\n\tcount = getfsstat( NULL, 0, MNT_NOWAIT );\n\tif( count <= 0 || count * sizeof( struct statfs ) > FSSTAT_BUFFER_SIZE )\n\t\treturn( 0 );\n\tcount = getfsstat( ( struct statfs * ) fsstatBuffer, FSSTAT_BUFFER_SIZE, \n\t\t\t\t\t   MNT_NOWAIT );\n\tif( count > 0 )\n\t\t{\n\t\taddRandomData( randomState, fsstatBuffer, \n\t\t\t\t\t   count * sizeof( struct statfs ) );\n\t\tquality = 3;\n\t\t}\n\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"getfsstat contributed %d value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n#endif /* *BSDs */\n\n/* Slowaris-specific slow poll using kstat, which provides kernel statistics.\n   Since there can be a hundred or more of these, we use a larger-than-usual\n   intermediate buffer to cut down on kernel traffic.\n   \n   Unfortunately Slowaris is the only OS that provides this interface, some\n   of the *BSDs have kenv, but this just returns fixed information like PCI\n   bus device addresses and so on, and isn't useful for providing entropy */\n\n#if ( defined( sun ) && ( OSVERSION >= 5 ) )\n\n#define USE_KSTAT\n#include <kstat.h>\n\nCHECK_RETVAL \\\nstatic int getKstatData( void )\n\t{\n\tkstat_ctl_t *kc;\n\tkstat_t *ksp;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ BIG_RANDOM_BUFSIZE + 8 ];\n\tint noEntries = 0, quality, status;\n\n\t/* Try and open a kernel stats handle */\n\tif( ( kc = kstat_open() ) == NULL )\n\t\treturn( 0 );\n\n\tstatus = initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Walk down the chain of stats reading each one.  Since some of the\n\t   stats can be rather lengthy, we optionally send them directly to\n\t   the randomness pool rather than using the accumulator, with a safe\n\t   bound on the data size to make sure we're not trying to inject\n\t   arbitrary-length data into the pool */\n\tfor( ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next )\n\t\t{\n\t\tif( kstat_read( kc, ksp, NULL ) == -1 || \\\n\t\t\tksp->ks_data_size <= 0 )\n\t\t\tcontinue;\n\t\taddRandomData( randomState, ksp, sizeof( kstat_t ) );\n\t\tif( ksp->ks_data_size > BIG_RANDOM_BUFSIZE )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\n\t\t\tsetMessageData( &msgData, ksp->ks_data, \n\t\t\t\t\t\t\tmin( ksp->ks_data_size, MAX_INTLENGTH_SHORT - 1 ) );\n\t\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t}\n\t\telse\n\t\t\taddRandomData( randomState, ksp->ks_data, ksp->ks_data_size );\n\t\tnoEntries++;\n\t\t}\n\tkstat_close( kc );\n\n\t/* Flush any remaining data through and produce an estimate of its\n\t   value.  We require that we get at least 50 entries and give them a\n\t   maximum value of 35 to ensure that some data is still coming from\n\t   other sources */\n\tquality = ( noEntries > 50 ) ? 35 : 0;\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"kstat contributed %d value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n#endif /* Slowaris */\n\n/* SYSV /proc interface, which provides assorted information that usually\n   has to be obtained the hard way via a slow poll.\n\n   Note that getProcData() gets data from the legacy /proc pseudo-filesystem\n   using ioctls() whereas getProcFSdata() gets data from the current /procfs\n   filesystem using file reads.  Because of this we don't enable it for\n   systems like Linux even though it's available since we both get far better\n   data from procfs and because we want to avoid double-counting the entropy\n   that we're getting */\n\n#if ( defined( sun ) && ( OSVERSION >= 5 ) ) || defined( __osf__ ) || \\\n\t  defined( __alpha__ )\n\n#define USE_PROC\n#include <sys/procfs.h>\n\nCHECK_RETVAL \\\nstatic int getProcData( void )\n\t{\n#ifdef PIOCSTATUS\n\tprstatus_t prStatus;\n#endif /* PIOCSTATUS */\n#ifdef PIOCPSINFO\n\tprpsinfo_t prMisc;\n#endif /* PIOCPSINFO */\n#ifdef PIOCUSAGE\n\tprusage_t prUsage;\n#endif /* PIOCUSAGE */\n#ifdef PIOCACINFO\n\tstruct pracinfo pracInfo;\n#endif /* PIOCACINFO */\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tchar fileName[ 128 + 8 ];\n\tint fd, noEntries = 0, quality, status;\n\n\t/* Try and open the process info for this process.  We don't use \n\t   O_NOFOLLOW because on some Unixen special files can be symlinks and \n\t   in any case a system that allows attackers to mess with privileged \n\t   filesystems like this is presumably a goner anyway */\n\tsprintf_s( fileName, 128, \"/proc/%d\", getpid() );\n\tif( ( fd = open( fileName, O_RDONLY ) ) == -1 )\n\t\treturn( 0 );\n\tif( fd <= 2 )\n\t\t{\n\t\t/* We've been given a standard I/O handle, something's wrong */\n\t\tclose( fd );\n\t\treturn( 0 );\n\t\t}\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"Reading /proc data via ioctls...\\n\" ));\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Get the process status information, misc information, and resource\n\t   usage */\n#ifdef PIOCSTATUS\n\tif( ioctl( fd, PIOCSTATUS, &prStatus ) != -1 )\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"PIOCSTATUS contributed %d bytes.\\n\", \n\t\t\t\t\t\t\tsizeof( prstatus_t ) ));\n\t\taddRandomData( randomState, &prStatus, sizeof( prstatus_t ) );\n\t\tnoEntries++;\n\t\t}\n#endif /* PIOCSTATUS */\n#ifdef PIOCPSINFO\n\tif( ioctl( fd, PIOCPSINFO, &prMisc ) != -1 )\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom,\n\t\t\t\t\t\t  ( \"PIOCPSINFO contributed %d bytes.\\n\",\n\t\t\t\t\t\t\tsizeof( prpsinfo_t ) ));\n\t\taddRandomData( randomState, &prMisc, sizeof( prpsinfo_t ) );\n\t\tnoEntries++;\n\t\t}\n#endif /* PIOCPSINFO */\n#ifdef PIOCUSAGE\n\tif( ioctl( fd, PIOCUSAGE, &prUsage ) != -1 )\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"PIOCUSAGE contributed %d bytes.\\n\",\n\t\t\t\t\t\t\tsizeof( prusage_t ) ));\n\t\taddRandomData( randomState, &prUsage, sizeof( prusage_t ) );\n\t\tnoEntries++;\n\t\t}\n#endif /* PIOCUSAGE */\n\n#ifdef PIOCACINFO\n\tif( ioctl( fd, PIOCACINFO, &pracInfo ) != -1 )\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"PIOCACINFO contributed %d bytes.\\n\",\n\t\t\t\t\t\t\tsizeof( struct pracinfo ) ));\n\t\taddRandomData( randomState, &pracInfo, sizeof( struct pracinfo ) );\n\t\tnoEntries++;\n\t\t}\n#endif /* PIOCACINFO */\n\tclose( fd );\n\n\t/* Flush any remaining data through and produce an estimate of its\n\t   value.  We require that at least two of the sources exist and accesses\n\t   to them succeed, and give them a relatively low value */\n\tquality = ( noEntries > 2 ) ? 5 : 0;\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"proc (via ioctls) contributed %d value.\\n\", \n\t\t\t\t\t    quality ));\n\n\treturn( quality );\n\t}\n#endif /* Slowaris || OSF/1 */\n\n/* Linux-specific polling using perf_event.  This is different to the \n   standard polling mechanisms in that it's called twice, once at the start\n   of the slow poll and a second time at the end, since it's being used\n   to collect event data over the process of the slow poll */\n\n#if defined( __linux__ ) \n\n#define USE_PERFEVENT\n#include <asm/unistd.h>\n#include <linux/perf_event.h>\n#include <sys/ioctl.h>\n#ifndef PERF_FLAG_FD_CLOEXEC\n  #define PERF_FLAG_FD_CLOEXEC\t0\n#endif /* !PERF_FLAG_FD_CLOEXEC */\n\ntypedef struct __attribute__((packed)) {\n\tuint64_t value;\t\t\t\t/* Event value */\n\tuint64_t time_enabled;\t\t/* Time enabled */\n\tuint64_t time_running;\t\t/* Time running */\n\tuint64_t id;\t\t\t\t/* Event group ID */\n\t} PERF_READ_INFO;\n\n#define PERF_EVENT_MAX\t\t32\n#define PERF_EVEN_LAST_HW\t9\n\n#define perf_event_open( hw_event, pid, cpu, group_fd, flags ) \\\n\t\tsyscall( __NR_perf_event_open, hw_event, pid, cpu, group_fd, flags )\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN getPerfEventBegin( int *pervEventFDs )\n\t{\n\ttypedef struct {\n\t\tconst int type, subType;\n\t\t} PERF_TYPE;\n\tconst PERF_TYPE perfType[ PERF_EVENT_MAX ] = {\n\t\t/* Hardware perf types.  These typically aren't available from user\n\t\t   space, producing ENOENT */\n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES },\n  #if OSVERSION >= 3\n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, \n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },\n  #endif /* OSVERSION >= 3 */\n  #if OSVERSION >= 4\t/* Actually 3.3 but we don't do minor versions */\n\t\t{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES },\n  #endif /* OSVERSION >= 4 */\n\t\t/* Software perf types, less useful than hardware.  In particular\n\t\t   usually only time_enabled and time_running contain useful data */\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS },\n\t\t{ PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS },\n\t\t{ -1, -1 }, { -1, -1 } };\n\tBOOLEAN eventAvailable = FALSE;\n\tint i;\n\n\t/* Clear the event information */\n\tfor( i = 0; i < PERF_EVENT_MAX; i++ )\n\t\tpervEventFDs[ i ] = -1;\n\n\t/* Set up the perf event information for each event type that we want\n\t   to record */\n\tfor( i = 0; i < PERF_EVENT_MAX && perfType[ i ].type >= 0; i++ )\n\t\t{\n\t\tstruct perf_event_attr pervEventInfo;\n\n\t\t/* Try and open the performance event data */\n\t\tmemset( &pervEventInfo, 0, sizeof( struct perf_event_attr ) );\n\t\tpervEventInfo.size = sizeof( struct perf_event_attr );\n\t\tpervEventInfo.type = perfType[ i ].type;\n\t\tpervEventInfo.config = perfType[ i ].subType;\n\t\tpervEventInfo.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \\\n\t\t\t\t\t\t\t\t\tPERF_FORMAT_TOTAL_TIME_RUNNING | \\\n\t\t\t\t\t\t\t\t\tPERF_FORMAT_ID;\n\t\tpervEventFDs[ i ] = perf_event_open( &pervEventInfo, 0, -1, -1, \n\t\t\t\t\t\t\t\t\t\t\t PERF_FLAG_FD_CLOEXEC );\n\t\tif( pervEventFDs[ i ] == -1 )\n\t\t\t{\n\t\t\tDEBUG_PRINT_COND( debugRandom && i == 0, \n\t\t\t\t\t\t\t  ( \"perf_event_open() for PERF_TYPE_HARDWARE \"\n\t\t\t\t\t\t\t    \"got errno %d.\\n\", errno ) );\n\t\t\tcontinue;\n\t\t\t}\n\t\teventAvailable = TRUE;\n\t\t}\n\n\tDEBUG_PRINT_COND( debugRandom && !eventAvailable , \n\t\t\t\t\t  ( \"No perf_event data available.\\n\" ) );\n\n\treturn( eventAvailable );\n\t}\n\nCHECK_RETVAL \\\nstatic int getPerfEventEnd( const int *pervEventFDs )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tint quality = 0, i, status;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Read the output from each event counter */\n\tfor( i = 0; i < PERF_EVENT_MAX; i++ )\n\t\t{\n\t\tPERF_READ_INFO eventInfo;\n\t\tint count;\n\n\t\tif( pervEventFDs[ i ] == -1 )\n\t\t\tcontinue;\n\t\tioctl( pervEventFDs[ i ], PERF_EVENT_IOC_DISABLE, 0 );\n\t\tcount = read( pervEventFDs[ i ], &eventInfo, \n\t\t\t\t\t  sizeof( PERF_READ_INFO ) );\n\t\tclose( pervEventFDs[ i ] );\n\t\tif( count <= 0 )\n\t\t\tcontinue;\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"perf_event %d returned value %ld, time %ld, \"\n\t\t\t\t\t\t    \"runtime %ld.\\n\", i, eventInfo.value, \n\t\t\t\t\t\t\teventInfo.time_enabled, eventInfo.time_running ) );\n\t\taddRandomData( randomState, &eventInfo, count );\n\t\tquality += ( i <= PERF_EVEN_LAST_HW ) ? 2 : 1;\n\t\t}\n\n\t/* Flush any remaining data through and produce an estimate of its\n\t   value */\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"perf_events contributed %d value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n#endif /* Linux */\n\n#ifdef __iOS__ \n\n#define IOS_BUFSIZE\t\t\t256\n\nCHECK_RETVAL \\\nstatic int getIOSData( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tBYTE secRandomBuffer[ IOS_BUFSIZE + 8 ];\n\tint quality = 0, status;\n\n\t/* Get random data from the iOS system randomness routine.  Although \n\t   SecRandomCopyBytes() takes as its first parameter the generator type, \n\t   only one is allowed, kSecRandomDefault, after which the call is \n\t   passed down to CCRandomCopyBytes(), which does something with one of \n\t   the NIST DRBGs, but it's all obfuscated with macros and function \n\t   pointers so it's hard to tell what.\n\n\t   Initially SecRandomCopyBytes() was just a wrapper for a thread-safe\n\t   read of Apple's /dev/random (for which see the comment in \n\t   getDevRandomData() about the value of this and why we only assign a \n\t   quality factor of 60%), however what's in use now isn't a /dev/random\n\t   read any more but something much more complex (see above).\n\t   \n\t   Another possible complication is that if both SecRandomCopyBytes() \n\t   and the explicit /dev/random read that we perform ourselves are \n\t   getting their input from the same source then we should only count \n\t   its value once, however the current Apple code, which seems to be out \n\t   of sync with the documentation, appears to do more than that */\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\tstatus = SecRandomCopyBytes( kSecRandomDefault, IOS_BUFSIZE, \n\t\t\t\t\t\t\t\t secRandomBuffer );\n\tif( status == 0 )\n\t\t{\n\t\taddRandomData( randomState, secRandomBuffer, 256 );\n\t\tquality = 60;\n\t\t}\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"SecRandomCopyBytes contributed %d value.\\n\", \n\t\t\t\t\t    quality ));\n\n\treturn( quality );\n\t}\n#endif /* __iOS__  */\n\n/* TPM poll: \"The Linux TPM implementation is Trousers\".\n\n   We can check for the existence of a TPM, at least under Linux, by \n   checking /sys/class/misc/hw_random/rng_available and \n   /sys/class/misc/hw_random/rng_current, which will point to \"tpm-rng\"\n   if this is present and/or available */\n\n#ifdef USE_TPM\n\n#include <tss/tspi.h>\n\nCHECK_RETVAL \\\nstatic int getTPMData( void )\n\t{\n\tTSS_HCONTEXT hTSPIContext;\n\tTSS_HTPM hTPM;\n\tBYTE *bufPtr;\n\tint quality = 0, status;\n\n\t/* Create a TSPI context, connect it to the system TPM, and get the TPM\n\t   handle from it.  The typical error return from Tspi_Context_Connect(),\n\t   if it fails, is the totally undocumented 0x3011 indicating that tcsd \n\t   isn't running (check with \"ps aux | grep tcsd\", and/or via the\n\t   \"tpm_version\" command which will print an error if it can't connect), \n\t   in which case it needs to be started with \n\t   \"sudo /etc/init.d/trousers start\" */\n\tif( Tspi_Context_Create( &hTSPIContext ) != TSS_SUCCESS )\n\t\treturn( 0 );\n\tstatus = Tspi_Context_Connect( hTSPIContext, NULL );\n\tif( status == 0x3011 )\n\t\tDEBUG_DIAG(( \"Couldn't connect to TPM, is tcsd running?\"));\n\tif( status != TSS_SUCCESS || \\\n\t\tTspi_Context_GetTpmObject( hTSPIContext, &hTPM ) != TSS_SUCCESS )\n\t\t{\n\t\tTspi_Context_Close( hTSPIContext );\n\t\treturn( 0 );\n\t\t}\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"Opened connection to system TPM.\\n\" ));\n\n\t/* Get random data from the TPM */ \n\tif( Tspi_TPM_GetRandom( hTPM, 256, &bufPtr ) == TSS_SUCCESS )\n\t\t{\n\t\tRANDOM_STATE randomState;\n\t\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\t\tint status;\n\n\t\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\t\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\t\taddRandomData( randomState, bufPtr, 256 );\n\t\tquality = 70;\n\t\tendRandomData( randomState, quality );\n\t\tzeroise( bufPtr, 256 );\n\t\tTspi_Context_FreeMemory( hTSPIContext, bufPtr );\n\t\t}\n\n\t/* Clean up */\n\tTspi_Context_Close( hTPM );\n\tTspi_Context_FreeMemory( hTSPIContext, NULL );\n\tTspi_Context_Close( hTSPIContext );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"TPM contributed %d value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n#endif /* USE_TPM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUniversal Slow Poll Sources\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#define HWRNG_BUFSIZE\t\t256\n\nstatic int getHWRNGNAME( BYTE *buffer, const int bufSize )\n\t{\n\tint fd, count;\n\t\n\t/* Clear return value */\n\tmemset( buffer, 0, bufSize );\n\n\t/* Try and read the HW RNG name.  This may or may not be terminated with\n\t   a LF, so we strip it if there's one present */\n\tfd = open( \"/sys/class/misc/hw_random/rng_current\", O_RDONLY );\n\tif( fd == -1 )\n\t\treturn( -1 );\n\tif( fd <= 2 )\n\t\t{\n\t\t/* We've been given a standard I/O handle, something's wrong */\n\t\tclose( fd );\n\t\treturn( -1 );\n\t\t}\n\tcount = read( fd, buffer, bufSize ); \n\tclose( fd ); \n\tif( count < 2 )\n\t\treturn( -1 );\n\tif( buffer[ count - 1 ] == '\\n' )\n\t\tbuffer[ count - 1 ] = '\\0'; \n\n\treturn( 0 );\n\t}\n\nCHECK_RETVAL \\\nstatic int getHWRNGData( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tBYTE hwrngBuffer[ HWRNG_BUFSIZE + 8 ];\n\tint hwrngFD, count, quality = 0, status;\n\n\t/* Open the hardware RNG device, whose nature is documented in \n\t   /sys/class/misc/hw_random/rng_current.  This is a real Clayton's \n\t   device because the fact that it can be opened doesn't mean that it \n\t   actually exists.  The justification for this is that the underlying \n\t   hardware can be altered at runtime, so the device may change at any \n\t   point, which means that we can happily open the nonexistent device \n\t   but won't be told that it's nonexistent until we try and read from \n\t   it.  Because of this we fail silently rather than warning that no \n\t   data was read, since it would lead to endless false positives */\n\thwrngFD = open( \"/dev/hwrng\", O_RDONLY );\n\tif( hwrngFD < 0 )\n\t\treturn( 0 );\n\tDEBUG_OP( count = getHWRNGNAME( buffer, 128 ) );\n\tDEBUG_PRINT_COND( debugRandom && count >= 0, \n\t\t\t\t\t  ( \"Hardware RNG is provided via '%s' source.\\n\", buffer ));\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\tcount = read( hwrngFD, hwrngBuffer, HWRNG_BUFSIZE );\n\tclose( hwrngFD );\n\tif( count > 0 )\n\t\t{\n\t\taddRandomData( randomState, hwrngBuffer, HWRNG_BUFSIZE );\n\t\tquality = 50;\n\t\t}\n\telse\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"Hardware RNG via /dev/hwrng is available but \"\n\t\t\t\t\t\t    \"not readable,\\n  this is broken but by-design \"\n\t\t\t\t\t\t\t\"functionality.\\n\" ));\n\t\t}\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom && quality > 0, \n\t\t\t\t\t  ( \"Hardware RNG read via /dev/hwrng contributed %d \"\n\t\t\t\t\t    \"value.\\n\", quality ));\n\n\treturn( quality );\n\t}\n\n/* Named process information via the /procfs interface.  Each source is \n   given a weighting of 1-3, with 1 being a static (although unpredictable) \n   source, 2 being a slowly-changing source, and 3 being a rapidly-changing\n   source */\n\n#define PROCS_BUFSIZE\t\t1024\n\nCHECK_RETVAL \\\nstatic int getProcFSdata( void )\n\t{\n\ttypedef struct {\n\t\tconst char *source;\n\t\tconst int value;\n\t\t} PROCSOURCE_INFO;\n\tstatic const PROCSOURCE_INFO procSources[] = {\n\t\t{ \"diskstats\", 2 }, { \"interrupts\", 3 }, { \"loadavg\", 2 }, \n\t\t{ \"locks\", 1 }, { \"meminfo\", 3 }, { \"net/dev\", 2 },\n\t\t{ \"net/ipx\", 2 }, { \"modules\", 1 }, { \"mounts\", 1 }, \n\t\t{ \"net/netstat\", 2 }, { \"net/rt_cache\", 1 }, \n\t\t{ \"net/rt_cache_stat\", 3 }, { \"net/snmp\", 2 }, \n\t\t{ \"net/softnet_stat\", 2 }, { \"net/stat/arp_cache\", 3 }, \n\t\t{ \"net/stat/ndisc_cache\", 2 }, { \"net/stat/rt_cache\", 3 }, \n\t\t{ \"net/tcp\", 3 }, { \"net/udp\", 2 }, { \"net/wireless\", 2 },\n\t\t{ \"slabinfo\", 3 }, { \"stat\", 3 }, { \"sys/fs/inode-state\", 1 }, \n\t\t{ \"sys/fs/file-nr\", 1 }, { \"sys/fs/dentry-state\", 1 }, \n\t\t{ \"sysvipc/msg\", 1 }, { \"sysvipc/sem\", 1 }, { \"sysvipc/shm\", 1 },\n\t\t{ \"zoneinfo\", 3 },\n/*\t\t{ \"/sys/devices/system/node/node0/numastat\", 2 }, */\n\t\t{ NULL, 0 }, { NULL, 0 }\n\t\t};\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ PROCS_BUFSIZE + 8 ];\n\tint procIndex, procFD, procValue = 0, quality;\n\n\t/* Read the first 1K of data from some of the more useful sources (most\n\t   of these produce far less than 1K output) */\n\tfor( procIndex = 0; \n\t\t procSources[ procIndex ].source != NULL && \\\n\t\t\tprocIndex < FAILSAFE_ARRAYSIZE( procSources, PROCSOURCE_INFO );\n\t\t procIndex++ )\n\t\t{\n\t\tchar fileName[ 128 + 8 ];\n\t\tint count, status;\n\n\t\t/* Try and open the data source.  We don't use O_NOFOLLOW because on \n\t\t   some Unixen special files can be symlinks and in any case a \n\t\t   system that allows attackers to mess with privileged filesystems \n\t\t   like this is presumably a goner anyway */\n\t\tsprintf_s( fileName, 128, \"/proc/%s\", \n\t\t\t\t   procSources[ procIndex ].source );\n\t\tprocFD = open( fileName, O_RDONLY );\n\t\tif( procFD < 0 )\n\t\t\tcontinue;\n\t\tif( procFD <= 2 )\n\t\t\t{\n\t\t\t/* We've been given a standard I/O handle, something's wrong */\n\t\t\tDEBUG_DIAG(( \"/proc/%s open returned file handle %d, something \"\n\t\t\t\t\t\t \"is seriously wrong\", fileName, procFD ));\n\t\t\tclose( procFD );\n\t\t\treturn( 0 );\n\t\t\t}\n\n\t\t/* Read data from the source */\n\t\tcount = read( procFD, buffer, PROCS_BUFSIZE );\n\t\tif( count > 16 )\n\t\t\t{\n\t\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t\t  ( \"/proc/%s contributed %d bytes.\\n\",\n\t\t\t\t\t\t\t\tprocSources[ procIndex ].source, count ));\n\t\t\tsetMessageData( &msgData, buffer, count );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tprocValue += procSources[ procIndex ].value;\n\t\t\t}\n\t\tclose( procFD );\n\t\t}\n\tENSURES( procIndex < FAILSAFE_ARRAYSIZE( procSources, PROCSOURCE_INFO ) );\n\tzeroise( buffer, PROCS_BUFSIZE );\n\n\t/* Produce an estimate of the data's value.  We require that we get a\n\t   quality value of at least 5 and limit it to a maximum value of 50 to \n\t   ensure that some data is still coming from other sources */\n\tif( procValue < 5 )\n\t\treturn( 0 );\n\tquality = min( procValue, 50 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &quality, \n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"procfs reads contributed %d entropy quality.\\n\", \n\t\t\t\t\t\tquality ));\n\n\treturn( quality );\n\t}\n\n/* System information via the sysfs interface.  These often provide very \n   small amounts of data each, although they're also somewhat schizophrenic, \n   some provide a single numeric value or string while others provide \n   formatted human-readable-only output */\n\n#define SYSFS_BUFSIZE\t\t1024\n\nCHECK_RETVAL \\\nstatic int getSysFSdata( void )\n\t{\n\tstatic const char *sysfsSources[] = {\n\t\t/* \"SCSI\" disk, using a very weird definition of SCSI */\n\t\t\"block/sda0/stat\", \"block/sda1/stat\", \"block/sda2/stat\", \n\t\t\"block/sda3/stat\",\n\t\t/* Xen virtual disk */\n\t\t\"block/xvda1/stat\", \"block/xvda2/stat\", \"block/xvda3/stat\",\n\t\t\"block/xvda4/stat\",\n\t\t/* MMC block device */\n\t\t\"block/mmcblk0/stat\", \"block/mmcblk1/stat\",\n\t\t/* Device mapper */\n\t\t\"block/dm-0/stat\", \"block/dm-1/stat\", \"block/dm-2/stat\", \n\t\t\"block/dm-3/stat\",\n\t\t/* Device-specific information */\n\t\t\"class/devfreq/devfreq0/cur_freq\", \"class/devfreq/devfreq0/trans_stat\",\n\t\t\"class/devfreq/devfreq1/cur_freq\", \"class/devfreq/devfreq1/trans_stat\",\n\t\t\"class/devfreq/devfreq2/cur_freq\", \"class/devfreq/devfreq2/trans_stat\",\n\t\t\"class/devfreq/devfreq3/cur_freq\", \"class/devfreq/devfreq3/trans_stat\",\n\t\t\"class/devfreq/devfreq4/cur_freq\", \"class/devfreq/devfreq4/trans_stat\",\n\t\t\"class/devfreq/devfreq5/cur_freq\", \"class/devfreq/devfreq5/trans_stat\",\n\t\t\"class/devfreq/devfreq6/cur_freq\", \"class/devfreq/devfreq6/trans_stat\",\n\t\t\"class/devfreq/devfreq7/cur_freq\", \"class/devfreq/devfreq7/trans_stat\",\n\t\t\"class/dma/dma0chan0/bytes_transferred\", \"class/dma/dma0chan0/memcpy_count\",\n\t\t\"class/dma/dma0chan1/bytes_transferred\", \"class/dma/dma0chan1/memcpy_count\",\n\t\t\"class/dma/dma1chan0/bytes_transferred\", \"class/dma/dma1chan0/memcpy_count\",\n\t\t\"class/dma/dma1chan1/bytes_transferred\", \"class/dma/dma1chan1/memcpy_count\",\n\t\t\"class/hwmon/hwmon0/fan_speed\", \"class/hwmon/hwmon0/pwm1\", \n\t\t\"class/hwmon/hwmon1/fan_speed\", \"class/hwmon/hwmon1/pwm1\", \n\t\t\"class/input/event0/dev\", \"class/input/event1/dev\", \n\t\t\"class/input/event2/dev\", \"class/input/event3/dev\", \n\t\t\"class/input/input0/modalias\", \"class/input/input1/modalias\", \n\t\t\"class/input/input2/modalias\", \"class/input/input3/modalias\", \n\t\t\"class/net/eth0/carrier_changes\", \"class/net/eth0/statistics/rx_bytes\", \n\t\t\"class/net/eth0/statistics/rx_dropped\", \"class/net/eth0/statistics/rx_packets\", \n\t\t\"class/net/eth0/statistics/tx_bytes\", \"class/net/eth0/statistics/tx_dropped\", \n\t\t\"class/net/eth0/statistics/tx_packets\",\n\t\t\"class/net/eth1/carrier_changes\", \"class/net/eth1/statistics/rx_bytes\",\n\t\t\"class/net/eth1/statistics/rx_dropped\", \"class/net/eth1/statistics/rx_packets\",\n\t\t\"class/net/eth1/statistics/tx_bytes\", \"class/net/eth1/statistics/tx_dropped\",\n\t\t\"class/net/eth1/statistics/tx_packets\", \n\t\t\"class/net/lo/statistics/rx_bytes\", \"class/net/lo/statistics/rx_dropped\", \n\t\t\"class/net/lo/statistics/rx_packets\", \"class/net/lo/statistics/tx_bytes\", \n\t\t\"class/net/lo/statistics/tx_dropped\", \"class/net/lo/statistics/tx_packets\", \n\t\t\"class/net/wlan0/statistics/rx_bytes\", \"class/net/wlan0/statistics/rx_dropped\", \n\t\t\"class/net/wlan0/statistics/rx_packets\", \"class/net/wlan0/statistics/tx_bytes\", \n\t\t\"class/net/wlan0/statistics/tx_dropped\", \"class/net/wlan0/statistics/tx_packets\", \n\t\t\"class/net/wlan1/statistics/rx_bytes\", \"class/net/wlan1/statistics/rx_dropped\", \n\t\t\"class/net/wlan1/statistics/rx_packets\", \"class/net/wlan1/statistics/tx_bytes\", \n\t\t\"class/net/wlan1/statistics/tx_dropped\", \"class/net/wlan1/statistics/tx_packets\", \n\t\t\t/* systemd insanity */\n\t\t\"class/net/eno1/statistics/rx_bytes\", \"class/net/eno1/statistics/rx_dropped\", \n\t\t\"class/net/eno1/statistics/rx_packets\", \"class/net/eno1/statistics/tx_bytes\", \n\t\t\"class/net/eno1/statistics/tx_dropped\", \"class/net/eno1/statistics/tx_packets\", \n\t\t\"class/net/eno2/statistics/rx_bytes\", \"class/net/eno2/statistics/rx_dropped\", \n\t\t\"class/net/eno2/statistics/rx_packets\", \"class/net/eno2/statistics/tx_bytes\", \n\t\t\"class/net/eno2/statistics/tx_dropped\", \"class/net/eno2/statistics/tx_packets\", \n\t\t\"class/net/ens1/statistics/rx_bytes\", \"class/net/ens1/statistics/rx_dropped\", \n\t\t\"class/net/ens1/statistics/rx_packets\", \"class/net/ens1/statistics/tx_bytes\", \n\t\t\"class/net/ens1/statistics/tx_dropped\", \"class/net/ens1/statistics/tx_packets\", \n\t\t\"class/net/ens2/statistics/rx_bytes\", \"class/net/ens2/statistics/rx_dropped\", \n\t\t\"class/net/ens2/statistics/rx_packets\", \"class/net/ens2/statistics/tx_bytes\", \n\t\t\"class/net/ens2/statistics/tx_dropped\", \"class/net/ens2/statistics/tx_packets\", \n\t\t\"class/regulator/regulator.0/microvolts\", \"class/regulator/regulator.1/microvolts\", \n\t\t\"class/regulator/regulator.2/microvolts\", \"class/regulator/regulator.3/microvolts\", \n\t\t\"class/regulator/regulator.4/microvolts\", \"class/regulator/regulator.5/microvolts\", \n\t\t\"class/regulator/regulator.6/microvolts\", \"class/regulator/regulator.7/microvolts\", \n\t\t\"class/rtc/rtc0/since_epoch\", \"class/rtc/rtc1/since_epoch\",\n\t\t\"class/spi_master/spi0/statistics/bytes_rx\", \n\t\t\"class/spi_master/spi0/statistics/bytes_tx\",\n\t\t\"class/spi_master/spi0/statistics/messages\",\n\t\t\"class/spi_master/spi0/statistics/transfers\",\n\t\t\"class/spi_master/spi1/statistics/bytes_rx\",\n\t\t\"class/spi_master/spi1/statistics/bytes_tx\",\n\t\t\"class/spi_master/spi1/statistics/messages\",\n\t\t\"class/spi_master/spi1/statistics/transfers\",\n\t\t\"class/thermal/thermal_zone0/temp\", \"class/thermal/thermal_zone1/temp\",\n\t\t\"class/thermal/thermal_zone2/temp\", \"class/thermal/thermal_zone3/temp\",\n\t\t\"class/thermal/thermal_zone4/temp\", \"class/thermal/thermal_zone5/temp\",\n\t\t\"class/thermal/thermal_zone6/temp\", \"class/thermal/thermal_zone7/temp\",\n\t\t/* System hardware stats */\n\t\t\"kernel/debug/gpio\", \"kernel/debug/irq_domain_mapping\", \n\t\t\"kernel/debug/pwm\", \"kernel/debug/suspend_stats\", \n\t\t\"kernel/debug/wakeup_sources\", \"kernel/debug/asoc/codecs\",\n\t\t\"kernel/debug/asoc/dais\", \"kernel/debug/asoc/platforms\",\n\t\t\"kernel/debug/clk/clk_dump\", \"kernel/debug/clk/clk_summary\",\n\t\t\"kernel/debug/memblock/reserved\", \"kernel/debug/mmc0/ios\",\n\t\t\"kernel/debug/mmc0/regs\", \"kernel/debug/mmc1/ios\", \n\t\t\"kernel/debug/mmc1/regs\", \"kernel/debug/pinctrl/pinctrl-handles\",\n\t\t\"kernel/debug/pinctrl/pinctrl-maps\",\n\t\t\"kernel/debug/regulator/regulator_summary\",\n\t\t\"kernel/debug/usb/devices\",\n\t\t\"power/wakeup_count\",\n\t\tNULL, NULL\n\t\t};\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ], sysfsBuffer[ SYSFS_BUFSIZE + 8 ];\n\tint sysfsIndex, sysfsFD, sysfsCount = 0, quality, status;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tENSURES_EXT( cryptStatusOK( status ), 0 );\n\n\t/* Read the first 1K of data from some of the more useful sources (most\n\t   of these produce far less than 1K output) */\n\tfor( sysfsIndex = 0; \n\t\t sysfsSources[ sysfsIndex ] != NULL && \\\n\t\t\tsysfsIndex < FAILSAFE_ARRAYSIZE( sysfsSources, char * );\n\t\t sysfsIndex++ )\n\t\t{\n\t\tchar fileName[ 128 + 8 ];\n\t\tint count;\n\n\t\t/* Try and open the data source.  We don't use O_NOFOLLOW because \n\t\t   sysfs is typically symlinked all over itself, with links from\n\t\t   /sys/whatever going into the system-specific /sys/devices tree\n\t\t   (as well as circular links) */\n\t\tsprintf_s( fileName, 128, \"/sys/%s\", sysfsSources[ sysfsIndex ] );\n\t\tsysfsFD = open( fileName, O_RDONLY );\n\t\tif( sysfsFD < 0 )\n\t\t\tcontinue;\n\t\tif( sysfsFD <= 2 )\n\t\t\t{\n\t\t\t/* We've been given a standard I/O handle, something's wrong */\n\t\t\tDEBUG_DIAG(( \"/sys/%s open returned file handle %d, something \"\n\t\t\t\t\t\t \"is seriously wrong\", fileName, sysfsFD ));\n\t\t\tclose( sysfsFD );\n\t\t\treturn( 0 );\n\t\t\t}\n\n\t\t/* Read data from the source */\n\t\tcount = read( sysfsFD, sysfsBuffer, SYSFS_BUFSIZE );\n\t\tclose( sysfsFD );\n\t\tif( count <= 0 )\n\t\t\tcontinue;\n\n\t\t/* Some sysfs reads return a value as \"<value>\" and some return it\n\t\t   as \"<value>\\n\", so before we continue we have to strip trailing\n\t\t   '\\n's */\n\t\tif( sysfsBuffer[ count - 1 ] == '\\n' )\n\t\t\t{\n\t\t\tcount--;\n\t\t\tif( count <= 0 )\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* We got something, check whether it's a dummy value ('0') or \n\t\t   something static ('0'/'1') */\n\t\tif( count <= 1 && \\\n\t\t\t( sysfsBuffer[ 0 ] == '0' || sysfsBuffer[ 0 ] == '1' ) )\n\t\t\tcontinue;\n\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"/sys/%s contributed %d %s.\\n\",\n\t\t\t\t\t\t\tsysfsSources[ sysfsIndex ], count,\n\t\t\t\t\t\t\t( count > 1 ) ? \"bytes\" : \"byte\" ));\n\t\taddRandomData( randomState, sysfsBuffer, count );\n\t\tsysfsCount++;\n\t\t}\n\tENSURES( sysfsIndex < FAILSAFE_ARRAYSIZE( sysfsSources, char * ) );\n\tzeroise( buffer, SYSFS_BUFSIZE );\n\n\t/* Produce an estimate of the data's value.  We require that we get \n\t   at least 20 results to get the basic quality value */\n\tquality = ( sysfsCount >= 50 ) ? 20 : ( sysfsCount >= 20 ) ? 10 : 0;\n\tendRandomData( randomState, quality );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"sysfs reads contributed %d entropy quality.\\n\", \n\t\t\t\t\t\tquality ));\n\n\treturn( quality );\n\t}\n\n/* /dev/random interface */\n\n#define DEVRANDOM_BUFSIZE\t128\n\nCHECK_RETVAL \\\nstatic int getDevRandomData( void )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ DEVRANDOM_BUFSIZE + 8 ];\n#if defined( __APPLE__ ) || ( defined( __FreeBSD__ ) && OSVERSION >= 5 )\n\tstatic const int quality = 60;\t/* See comment below */\n#else\n\tstatic const int quality = 80;\n#endif /* Mac OS X || FreeBSD 5.x */\n\tint randFD, noBytes = 0, status;\n\n\t/* Some OSes include a call to access the system randomness data \n\t   directly rather than having to go via a pseudo-device, if this \n\t   capability is available then we use a direct read.  This currently \n\t   applies to OpenBSD (added in 5.6, conveniently about the time that \n\t   LibreSSL needed it) and Linux kernels from 3.17 (in response to \n\t   prodding from LibreSSL and the appearance of the OpenBSD function).\n\t   \n\t   OpenBSD also has the older arc4random_buf(), which used to use\n\t   RC4 (ugh) until OpenBSD 5.5 when it was replaced by ChaCha20, which\n\t   postprocess the entropy data through the given stream cipher.  Since \n\t   we're feeding the output into our own PRNG and since this function\n\t   is a general interface to the system randomness data, we use \n\t   getentropy() rather than arc4random() */\n#if defined( __linux__ ) && defined( GRND_NONBLOCK ) && \\\n\tdefined( SYS_getrandom )\n\t/* getrandom() was defined in kernel 3.17 and above but is rarely\n\t   supported in libc (\"if we add support for it then people might use it\n\t   and things won't work any more with older libc versions\").  In some\n\t   cases it's possible to access it via syscall() with SYS_getrandom,\n\t   so the best that we can do is use that if it's available.\n\t   \n\t   Even then, getrandom() is somewat risky because its behaviour, at\n\t   least as originally designed, was to block until sufficient entropy \n\t   (128 bits) was available and then become nonblocking, see\n\t   https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f3.\n\t   This means that the call can block at random, presumably if it's \n\t   called early in the boot process.  Since cryptlib probably won't\n\t   be running as a kernel-mode implementation at early boot, this \n\t   should be safe... */\n\t#include <sys/syscall.h>\n\tnoBytes = syscall( SYS_getrandom, buffer, DEVRANDOM_BUFSIZE, \n\t\t\t\t\t   GRND_NONBLOCK );\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"getrandom() (via syscall) contributed %d bytes.\\n\", \n\t\t\t\t\t\tnoBytes ));\n#elif defined( __OpenBSD__ ) && OpenBSD > 201412\n\t/* See the comment at the start for why we use 'OpenBSD' for the version \n\t   number */\n\tnoBytes = getentropy( buffer, DEVRANDOM_BUFSIZE );\n\tif( noBytes == 0 )\n\t\t{\n\t\t/* OpenBSD's semantics for the call differ from the read()-alike\n\t\t   functionality of the Linux version and simply return 0 or -1\n\t\t   for success or failure, so we convert the former into a byte\n\t\t   count */\n\t\tnoBytes = DEVRANDOM_BUFSIZE;\n\t\t}\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"getentropy() contributed %d bytes.\\n\", noBytes ));\n#elif ( defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\t\tdefined( __OpenBSD__ ) || defined( __APPLE__ ) ) && \\\n\t  defined( KERN_ARND )\n\t{\n\tstatic const int mib[] = { CTL_KERN, KERN_ARND };\n\tsize_t size = DEVRANDOM_BUFSIZE;\n\tint status;\n\n\t/* Alternative to getentropy() if it's not present, supported by some \n\t   BSDs */\n\tif( sysctl( mib, 2, buffer, &size, NULL, 0 ) == 0 )\n\t\tnoBytes = size;\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"sysctl( KERN_ARND ) contributed %d bytes.\\n\", \n\t\t\t\t\t\tnoBytes ));\n\t}\n#else\n\t/* Check whether there's a /dev/random present.  We don't use O_NOFOLLOW \n\t   because on some Unixen special files can be symlinks and in any case \n\t   a system that allows attackers to mess with privileged filesystems \n\t   like this is presumably a goner anyway */\n\tif( ( randFD = open( \"/dev/urandom\", O_RDONLY ) ) < 0 )\n\t\treturn( 0 );\n\tif( randFD <= 2 )\n\t\t{\n\t\t/* We've been given a standard I/O handle, something's wrong */\n\t\tDEBUG_DIAG(( \"/dev/urandom open returned file handle %d, something\"\n\t\t\t\t\t \"is seriously wrong\", randFD ));\n\t\tclose( randFD );\n\t\treturn( 0 );\n\t\t}\n\n\t/* Read data from /dev/urandom, which won't block (although the quality\n\t   of the noise is arguably slightly less).  We only assign this a 75% \n\t   quality factor to ensure that we still get randomness from other \n\t   sources as well.  \n\t   \n\t   Under FreeBSD 5.x and OS X, the /dev/random implementation is broken, \n\t   using a pretend dev-random implemented with Yarrow and a 160-bit pool \n\t   (animi sub vulpe latent) so we only assign a 60% quality factor.  \n\t   These generators also lie about entropy, with both /random and \n\t   /urandom being the same PRNG-based implementation.\n\t   \n\t   The AIX /dev/random isn't an original /dev/random either but merely \n\t   provides a compatible interface, taking its input from interrupt \n\t   timings of a very small number of sources such as ethernet and SCSI \n\t   adapters and postprocessing them with Yarrow.  This implementation is \n\t   also a lot more conservative about its entropy estimation, such that \n\t   the blocking interface blocks a lot more often than the original \n\t   /dev/random implementation would.  In addition it stops gathering \n\t   entropy (from interrupts) when it thinks it has enough, and only \n\t   resumes when the value falls below a certain value.  \n\t   \n\t   OTOH this may still be better than the Linux implementation, which \n\t   in 2009 stopped gathering any information from interrupts at all by \n\t   removing the IRQF_SAMPLE_RANDOM flag.  The apparent intention was to \n\t   replace it with something else, but after much bikeshedding this \n\t   never happened, which makes the Linux /dev/random particularly bad \n\t   on headless and embedded systems */\n\tnoBytes = read( randFD, buffer, DEVRANDOM_BUFSIZE );\n\tclose( randFD );\n#endif /* OSes without API support for the randomness device */\n\tif( noBytes < 1 )\n\t\t{\n\t\tif( noBytes == 0 )\n\t\t\t{\n\t\t\t/* This can actually happen */\n\t\t\tDEBUG_DIAG(( \"/dev/urandom read returned EOF (bytes read == 0), \"\n\t\t\t\t\t\t \"randomness system is broken\" ));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"/dev/urandom read failed, status %d, errno = %d\", \n\t\t\t\t\t\t noBytes, errno ));\n\t\t\t}\n\t\treturn( 0 );\n\t\t}\n\tsetMessageData( &msgData, buffer, noBytes );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, DEVRANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) || noBytes < DEVRANDOM_BUFSIZE )\n\t\treturn( 0 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &quality, \n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"/dev/urandom contributed %d entropy quality.\\n\", \n\t\t\t\t\t  quality ));\n\n\treturn( quality );\n\t}\n\n/* egd/prngd interface */\n\nCHECK_RETVAL \\\nstatic int getEGDdata( void )\n\t{\n\tstatic const char *egdSources[] = {\n\t\t\"/var/run/egd-pool\", \"/dev/egd-pool\", \"/etc/egd-pool\", NULL, NULL };\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ DEVRANDOM_BUFSIZE + 8 ];\n\tstatic const int quality = 75;\n\tint egdIndex, sockFD, noBytes = CRYPT_ERROR, status;\n\n\t/* Look for the egd/prngd output.  We re-search each time we're called \n\t   because, unlike /dev/random, it's both a user-level process and a \n\t   movable feast, so it can in theory disappear and reappear at a \n\t   different location between runs */\n\tsockFD = socket( AF_UNIX, SOCK_STREAM, 0 );\n\tif( sockFD < 0 )\n\t\treturn( 0 );\n\tfor( egdIndex = 0; egdSources[ egdIndex ] != NULL && \\\n\t\t\t\t\t   egdIndex < FAILSAFE_ARRAYSIZE( egdSources, char * ); \n\t\t egdIndex++ )\n\t\t{\n\t\tstruct sockaddr_un sockAddr;\n\n\t\tmemset( &sockAddr, 0, sizeof( struct sockaddr_un ) );\n\t\tsockAddr.sun_family = AF_UNIX;\n\t\tstrlcpy_s( sockAddr.sun_path, sizeof( sockAddr.sun_path ), \n\t\t\t\t   egdSources[ egdIndex ] );\n\t\tif( connect( sockFD, ( struct sockaddr * ) &sockAddr,\n\t\t\t\t\t sizeof( struct sockaddr_un ) ) >= 0 )\n\t\t\tbreak;\n\t\t}\n\tENSURES( egdIndex < FAILSAFE_ARRAYSIZE( egdSources, char * ) );\n\tif( egdSources[ egdIndex ] == NULL )\n\t\t{\n\t\tclose( sockFD );\n\t\treturn( 0 );\n\t\t}\n\n\t/* Read up to 128 bytes of data from the source:\n\t\twrite:\tBYTE 1 = read data nonblocking\n\t\t\t\tBYTE DEVRANDOM_BUFSIZE = count\n\t\tread:\tBYTE returned bytes\n\t\t\t\tBYTE[] data\n\t   As with /dev/random we only assign this a 75% quality factor to\n\t   ensure that we still get randomness from other sources as well */\n\tbuffer[ 0 ] = 1;\n\tbuffer[ 1 ] = DEVRANDOM_BUFSIZE;\n\tstatus = write( sockFD, buffer, 2 );\n\tif( status == 2 )\n\t\t{\n\t\tstatus = read( sockFD, buffer, 1 );\n\t\tnoBytes = buffer[ 0 ];\n\t\tif( status != 1 || noBytes < 0 || noBytes > DEVRANDOM_BUFSIZE )\n\t\t\tstatus = -1;\n\t\telse\n\t\t\tstatus = read( sockFD, buffer, noBytes );\n\t\t}\n\tclose( sockFD );\n\tif( ( status < 0 ) || ( status != noBytes ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"EGD (%s) read failed\", egdSources[ egdIndex ] ));\n\t\treturn( 0 );\n\t\t}\n\n\t/* Send the data to the pool */\n\tsetMessageData( &msgData, buffer, noBytes );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, DEVRANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) || noBytes < DEVRANDOM_BUFSIZE )\n\t\treturn( 0 );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &quality, \n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"EGD (%s) contributed %d entropy quality.\\n\", \n\t\t\t\t\t\tegdSources[ egdIndex ], quality ));\n\n\treturn( quality );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tLast-resort External-Source Polling\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef NO_SYSV_SHAREDMEM\n\n/* The structure containing information on random-data sources.  Each record \n   contains the source and a relative estimate of its usefulness (weighting) \n   which is used to scale the number of kB of output from the source (total \n   = data_bytes / usefulness).  Usually the weighting is in the range 1-3 \n   (or 0 for especially useless sources), resulting in a usefulness rating \n   of 1...3 for each kB of source output (or 0 for the useless sources).\n\n   If the source is constantly changing (certain types of network statistics\n   have this characteristic) but the amount of output is small, the weighting\n   is given as a negative value to indicate that the output should be treated\n   as if a minimum of 1K of output had been obtained.  If the source produces\n   a lot of output then the scale factor is fractional, resulting in a\n   usefulness rating of < 1 for each kB of source output.\n\n   In order to provide enough randomness to satisfy the requirements for a\n   slow poll, we need to accumulate at least 20 points of usefulness (a\n   typical system should get about 30 points).  This is useful not only for \n   use on source-starved systems but also in special circumstances like \n   running in a *BSD jail, in which only other processes running in the jail\n   are visible, severely restricting the amount of entropy that can be \n   collected.\n\n   Some potential options are missed out because of special considerations.\n   pstat -i and pstat -f can produce amazing amounts of output (the record is\n   600K on an Oracle server) that floods the buffer and doesn't yield\n   anything useful (apart from perhaps increasing the entropy of the vmstat\n   output a bit), so we don't bother with this.  pstat in general produces\n   quite a bit of output but it doesn't change much over time, so it gets\n   very low weightings.  netstat -s produces constantly-changing output but\n   also produces quite a bit of it, so it only gets a weighting of 2 rather\n   than 3.  The same holds for netstat -in, which gets 1 rather than 2.  In\n   addition some of the lower-ranked sources are either rather heavyweight\n   or of low value, and frequently duplicate information obtained by other\n   means like kstat or /procfs.  To avoid waiting for a long time for them\n   to produce output, we only use them if earlier, quicker sources aren't\n   available.\n\n   Some binaries are stored in different locations on different systems so\n   alternative paths are given for them.  The code sorts out which one to run\n   by itself, once it finds an exectable somewhere it moves on to the next\n   source.  The sources are arranged roughly in their order of usefulness,\n   occasionally sources that provide a tiny amount of relatively useless\n   data are placed ahead of ones that provide a large amount of possibly\n   useful data because another 100 bytes can't hurt, and it means the buffer\n   won't be swamped by one or two high-output sources. All the high-output\n   sources are clustered towards the end of the list for this reason.  Some\n   binaries are checked for in a certain order, for example under Slowaris\n   /usr/ucb/ps understands aux as an arg, but the others don't.  Some systems\n   have conditional defines enabling alternatives to commands that don't\n   understand the usual options but will provide enough output (in the form\n   of error messages) to look like they're the real thing, causing\n   alternative options to be skipped (we can't check the return either\n   because some commands return peculiar, non-zero status values even when \n   they're working correctly).\n\n   In order to maximise use of the buffer, the code performs a form of run-\n   length compression on its input where a repeated sequence of bytes is\n   replaced by the occurrence count mod 256.  Some commands output an awful\n   lot of whitespace, this measure greatly increases the amount of data that \n   we can fit into the buffer.\n\n   When we scale the weighting using the SC() macro, some preprocessors may\n   give a division by zero warning for the most obvious expression 'weight ?\n   1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero trap), so\n   we define a value SC_0 that evaluates to zero when fed to '1024 / SC_0' */\n\n#define SC( weight )\t( int ) ( 1024 / weight )\t/* Scale factor */\n#define SC_0\t\t\t16384\t\t\t\t/* SC( SC_0 ) evalutes to 0 */\n\ntypedef struct {\n\tconst char *path;\t\t/* Path to check for existence of source */\n\tconst char *arg;\t\t/* Args for source */\n\tconst int usefulness;\t/* Usefulness of source */\n\tFILE *pipe;\t\t\t\t/* Pipe to source as FILE * */\n\tint pipeFD;\t\t\t\t/* Pipe to source as FD */\n\tpid_t pid;\t\t\t\t/* pid of child for waitpid() */\n\tint length;\t\t\t\t/* Quantity of output produced */\n\tconst BOOLEAN hasAlternative;\t/* Whether source has alt.location */\n\t} DATA_SOURCE_INFO;\n\nstatic DATA_SOURCE_INFO dataSources[] = {\n\t/* Sources that are always polled */\n\t{ \"/bin/vmstat\", \"-s\", SC( -3 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/vmstat\", \"-s\", SC( -3 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/vmstat\", \"-c\", SC( -3 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/vmstat\", \"-c\", SC( -3 ), NULL, 0, 0, 0, FALSE },\n#if defined( __APPLE__ )\n\t{ \"/usr/bin/vm_stat\", NULL, SC( -3 ), NULL, 0, 0, 0, FALSE },\n#endif /* Mach version of vmstat */\n\t{ \"/usr/bin/pfstat\", NULL, SC( -2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/vmstat\", \"-i\", SC( -2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/vmstat\", \"-i\", SC( -2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/vmstat\", \"-d\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/vmstat\", \"-d\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/vmstat\", \"-a\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/vmstat\", \"-a\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n#if defined( _AIX ) || defined( __SCO_VERSION__ )\n\t{ \"/usr/bin/vmstat\", \"-f\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n#endif /* OS-specific extensions to vmstat */\n\t{ \"/usr/ucb/netstat\", \"-s\", SC( 2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/netstat\", \"-s\", SC( 2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/netstat\", \"-s\", SC( 2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/netstat\", \"-s\", SC( 2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/etc/netstat\", \"-s\", SC( 2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/nfsstat\", NULL, SC( 2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/ucb/netstat\", \"-m\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/netstat\", \"-m\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/netstat\", \"-m\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/netstat\", \"-m\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/etc/netstat\", \"-m\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/ucb/netstat\", \"-in\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/netstat\", \"-in\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/netstat\", \"-in\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/netstat\", \"-in\", SC( -1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/etc/netstat\", \"-in\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n#ifndef __SCO_VERSION__\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.7.1.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* UDP in */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.7.4.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* UDP out */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.4.3.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* IP ? */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.6.10.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.6.11.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.6.13.0\", SC( -1 ), NULL, 0, 0, 0, FALSE }, /* TCP ? */\n#else\n\t{ \"/usr/sbin/snmpstat\", \"-an localhost public\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/snmpstat\", \"-in localhost public\", SC( SC_0 ), NULL, 0, 0, 0, FALSE }, /* Subset of netstat info */\n\t{ \"/usr/sbin/snmpstat\", \"-Sn localhost public\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n#endif /* SCO/UnixWare vs.everything else */\n\t{ \"/usr/bin/smartctl\", \"-A /dev/hda\" , SC( 1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/smartctl\", \"-A /dev/hda\" , SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/smartctl\", \"-A /dev/hdb\" , SC( 1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/smartctl\", \"-A /dev/hdb\" , SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/mpstat\", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/w\", NULL, SC( 1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bsd/w\", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/df\", NULL, SC( 1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/df\", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/portstat\", NULL, SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/iostat\", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/uptime\", NULL, SC( SC_0 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bsd/uptime\", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/vmstat\", \"-f\", SC( SC_0 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/vmstat\", \"-f\", SC( SC_0 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/ucb/netstat\", \"-n\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/netstat\", \"-n\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/netstat\", \"-n\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/netstat\", \"-n\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/etc/netstat\", \"-n\", SC( 0.5 ), NULL, 0, 0, 0, FALSE },\n\n\t/* End-of-lightweight-sources section marker */\n\t{ \"\", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\n\t/* Potentially heavyweight or low-value sources that are only polled if\n\t   alternative sources aren't available.  ntptrace is somewhat\n\t   problematic in that some versions don't support -r and -t, made worse\n\t   by the fact that various servers in the commonly-used pool.ntp.org\n\t   cluster refuse to answer ntptrace.  As a result, using this can hang\n\t   for quite awhile before it times out, so we treat it as a heavyweight\n\t   source even though in theory it's a nice high-entropy lightweight\n\t   one */\n\t{ \"/usr/sbin/ntptrace\", \"-r2 -t1 -nv\", SC( -1 ), NULL, 0, 0, 0, FALSE },\n#if defined( __sgi ) || defined( __hpux )\n\t{ \"/bin/ps\", \"-el\", SC( 0.3 ), NULL, 0, 0, 0, TRUE },\n#endif /* SGI || PHUX */\n\t{ \"/usr/ucb/ps\", \"aux\", SC( 0.3 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/ps\", \"aux\", SC( 0.3 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/ps\", \"aux\", SC( 0.3 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/ipcs\", \"-a\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/ipcs\", \"-a\", SC( 0.5 ), NULL, 0, 0, 0, FALSE },\n\t\t\t\t\t\t\t/* Unreliable source, depends on system usage */\n\t{ \"/etc/pstat\", \"-p\", SC( 0.5 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/pstat\", \"-p\", SC( 0.5 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/etc/pstat\", \"-S\", SC( 0.2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/pstat\", \"-S\", SC( 0.2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/etc/pstat\", \"-v\", SC( 0.2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/pstat\", \"-v\", SC( 0.2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/etc/pstat\", \"-x\", SC( 0.2 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/pstat\", \"-x\", SC( 0.2 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/etc/pstat\", \"-t\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/bin/pstat\", \"-t\", SC( 0.1 ), NULL, 0, 0, 0, FALSE },\n\t\t\t\t\t\t\t/* pstat is your friend */\n#ifndef __SCO_VERSION__\n\t{ \"/usr/sbin/sar\", \"-AR\", SC( 0.05 ), NULL, 0, 0, 0, FALSE }, /* Only updated hourly */\n#endif /* SCO/UnixWare */\n\t{ \"/usr/bin/last\", \"-n 50\", SC( 0.3 ), NULL, 0, 0, 0, TRUE },\n#ifdef __sgi\n\t{ \"/usr/bsd/last\", \"-50\", SC( 0.3 ), NULL, 0, 0, 0, FALSE },\n#endif /* SGI */\n#ifdef __hpux\n\t{ \"/etc/last\", \"-50\", SC( 0.3 ), NULL, 0, 0, 0, FALSE },\n#endif /* PHUX */\n\t{ \"/usr/bsd/last\", \"-n 50\", SC( 0.3 ), NULL, 0, 0, 0, FALSE },\n#ifdef sun\n\t{ \"/usr/bin/showrev\", \"-a\", SC( 0.1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/swap\", \"-l\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/prtconf\", \"-v\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n#endif /* SunOS/Slowaris */\n\t{ \"/usr/sbin/psrinfo\", NULL, SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/lsof\", \"-blnwP\", SC( 0.3 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/local/bin/lsof\", \"-blnwP\", SC( 0.3 ), NULL, 0, 0, 0, FALSE },\n\t\t\t\t\t\t\t/* Output is very system and version-dependent\n\t\t\t\t\t\t\t   and can also be extremely voluminous */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.5.1.0\", SC( 0.1 ), NULL, 0, 0, 0, FALSE }, /* ICMP ? */\n\t{ \"/usr/sbin/snmp_request\", \"localhost public get 1.3.6.1.2.1.5.3.0\", SC( 0.1 ), NULL, 0, 0, 0, FALSE }, /* ICMP ? */\n\t{ \"/etc/arp\", \"-a\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/etc/arp\", \"-a\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/arp\", \"-a\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/sbin/arp\", \"-a\", SC( 0.1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/ripquery\", \"-nw 1 127.0.0.1\", SC( 0.1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/lpstat\", \"-t\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/bin/lpstat\", \"-t\", SC( 0.1 ), NULL, 0, 0, 0, TRUE },\n\t{ \"/usr/ucb/lpstat\", \"-t\", SC( 0.1 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/bin/tcpdump\", \"-c 5 -efvvx\", SC( 1 ), NULL, 0, 0, 0, FALSE },\n\t\t\t\t\t\t\t/* This is very environment-dependant.  If\n\t\t\t\t\t\t\t   network traffic is low, it'll probably time\n\t\t\t\t\t\t\t   out before delivering 5 packets, which is OK\n\t\t\t\t\t\t\t   because it'll probably be fixed stuff like ARP\n\t\t\t\t\t\t\t   anyway */\n\t{ \"/usr/sbin/advfsstat\", \"-b usr_domain\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/advfsstat\", \"-l 2 usr_domain\", SC( 0.5 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/sbin/advfsstat\", \"-p usr_domain\", SC( SC_0 ), NULL, 0, 0, 0, FALSE },\n\t\t\t\t\t\t\t/* This is a complex and screwball program.  Some\n\t\t\t\t\t\t\t   systems have things like rX_dmn, x = integer,\n\t\t\t\t\t\t\t   for RAID systems, but the statistics are\n\t\t\t\t\t\t\t   pretty dodgy */\n#if 0\n\t/* The following aren't enabled since they're somewhat slow and not very\n\t   unpredictable, however they give an indication of the sort of sources\n\t   you can use (for example the finger might be more useful on a\n\t   firewalled internal network) */\n\t{ \"/usr/bin/finger\", \"@ml.media.mit.edu\", SC( 0.9 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/usr/local/bin/wget\", \"-O - http://lavarand.sgi.com/block.html\", SC( 0.9 ), NULL, 0, 0, 0, FALSE },\n\t{ \"/bin/cat\", \"/usr/spool/mqueue/syslog\", SC( 0.9 ), NULL, 0, 0, 0, FALSE },\n#endif /* 0 */\n\n\t/* End-of-sources marker */\n\t{ NULL, NULL, 0, NULL, 0, 0, 0, FALSE }, \n\t\t{ NULL, NULL, 0, NULL, 0, 0, 0, FALSE }\n\t};\n\n/* Variables to manage the child process that fills the buffer */\n\nstatic pid_t gathererProcess = 0;/* The child process that fills the buffer */\nstatic BYTE *gathererBuffer;\t/* Shared buffer for gathering random noise */\nstatic int gathererMemID;\t\t/* ID for shared memory */\nstatic int gathererBufSize;\t\t/* Size of the shared memory buffer */\nstatic struct sigaction gathererOldHandler;\t/* Previous signal handler */\n#ifdef USE_THREADS\n  static pthread_mutex_t gathererMutex;\t/* Mutex to protect the polling */\n#endif /* USE_THREADS */\n\n/* The struct at the start of the shared memory buffer used to communicate\n   information from the child to the parent */\n\ntypedef struct {\n\tint usefulness;\t\t\t\t/* Usefulness of data in buffer */\n\tint noBytes;\t\t\t\t/* No.of bytes in buffer */\n\t} GATHERER_INFO;\n\n#if defined( __MVS__ ) || defined( __hpux ) || defined( __Android__ )\n\n/* MVS USS, PHUX, and the Android version of Linux don't have wait4() so we \n   emulate it with waitpid() and getrusage() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\npid_t wait4( pid_t pid, int *status, int options, struct rusage *rusage )\n\t{\n\tconst pid_t waitPid = waitpid( pid, status, options );\n\n\tgetrusage( RUSAGE_CHILDREN, rusage );\n\treturn( waitPid );\n\t}\n#endif /* MVS USS || PHUX || Android */\n\n/* Cray Unicos and QNX 4.x have neither wait4() nor getrusage, so we fake\n   it */\n\n#if defined( _CRAY ) || ( defined( __QNX__ ) && OSVERSION <= 4 )\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\npid_t wait4( pid_t pid, int *status, int options, struct rusage *rusage )\n\t{\n\tmemset( rusage, 0, sizeof( struct rusage ) );\n\treturn( waitpid( pid, status, options ) );\n\t}\n#endif /* Cray Unicos || QNX 4.x */\n\n#if !defined( _POSIX_PRIORITY_SCHEDULING ) || ( _POSIX_PRIORITY_SCHEDULING < 0 )\n  /* No sched_yield() or sched_yield() not supported */\n  #define sched_yield()\n#elif ( _POSIX_PRIORITY_SCHEDULING == 0 )\n\nstatic void my_sched_yield( void )\n\t{\n\t/* sched_yield() is only supported if sysconf() tells us that it is */\n\tif( sysconf( _SC_PRIORITY_SCHEDULING ) > 0 )\n\t\tsched_yield();\n\t}\n#define sched_yield\t\t\t\tmy_sched_yield\n\n#endif /* Systems without sched_yield() */\n\n/* When exiting from the child, we call _exit() rather than exit() since \n   this skips certain cleanup operations (atexit() and signal handlers).\n   More technically, _exit() is a system call that performs kernel-space\n   cleanup while exit() also performs user-space cleanup */\n\t  \n#define CHILD_EXIT( status )\t_exit( status )\n\n/* A special form of the ENSURES() predicate used in the forked child \n   process, which calls CHILD_EXIT() rather than returning */\n\n#define ENSURES_EXIT( x ) \\\n\t\tif( !( x ) ) { assert( INTERNAL_ERROR ); CHILD_EXIT( -1 ); }\n\n/* Under SunOS 4.x popen() doesn't record the pid of the child process.  When\n   pclose() is called, instead of calling waitpid() for the correct child, it\n   calls wait() repeatedly until the right child is reaped.  The problem with\n   this behaviour is that this reaps any other children that happen to have\n   died at that moment, and when their pclose() comes along the process hangs\n   forever.\n\n   This behaviour may be related to older SVR3-compatible SIGCLD handling in\n   which, under the SIG_IGN disposition, the status of the child was discarded\n   (i.e. no zombies were generated) so that when the parent called wait() it\n   would block until all children terminated, whereupon wait() would return -1\n   with errno set to ECHILD.\n\n   The fix for this problem is to use a wrapper for popen()/pclose() that\n   saves the pid in the dataSources structure (code adapted from GNU-libc's\n   popen() call).  Doing our own popen() has other advantages as well, for\n   example we use the more secure execl() to run the child instead of the\n   dangerous system().\n\n   Aut viam inveniam aut faciam */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic FILE *my_popen( INOUT DATA_SOURCE_INFO *entry )\n\t{\n\tstatic uid_t gathererUID = ( uid_t ) -1, gathererGID = ( uid_t ) -1;\n\tint pipedes[ 2 + 8 ];\n\tFILE *stream;\n\n\t/* Sanity check for stdin and stdout */\n\tREQUIRES_N( STDIN_FILENO <= 1 && STDOUT_FILENO <= 1 );\n\n\t/* If we're root, get UID/GID information so that we can give up our \n\t   permissions to make sure that we don't inadvertently read anything \n\t   sensitive.  We do it at this point in order to avoid calling \n\t   getpwnam() between the fork() and the execl() since some getpwnam()s\n\t   may call malloc() which could be locked by another thread which the\n\t   child won't have access to */\n\tif( geteuid() == 0 && gathererUID == ( uid_t ) -1 )\n\t\t{\n\t\tstruct passwd *passwd;\n\n\t\tpasswd = getpwnam( \"nobody\" );\n\t\tif( passwd != NULL )\n\t\t\t{\n\t\t\tgathererUID = passwd->pw_uid;\n\t\t\tgathererGID = passwd->pw_gid;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tassert( DEBUG_WARN );\n\t\t\t}\n\t\t}\n\n\t/* Create the pipe.  Note that under QNX the pipe resource manager\n\t   'pipe' must be running in order to use pipes */\n\tif( pipe( pipedes ) < 0 )\n\t\treturn( NULL );\n\n\t/* Fork off the child.  In theory we could use vfork() (\"vfork() is like \n\t   an OS orgasm.  All OSes want to do it, but most just end up faking \n\t   it\" - Chris Wedgwood), but most modern Unixen use copy-on-write for \n\t   forks anyway (with vfork() being just an alias for fork()), so we get \n\t   most of the benefits of vfork() with a plain fork().  There is \n\t   however another problem with fork that isn't fixed by COW.  Any large \n\t   program, when forked, requires (at least temporarily) a lot of \n\t   address space.  That is, when the process is forked the system needs \n\t   to allocate many virtual pages (backing store) even if those pages \n\t   are never used.  If the system doesn't have enough swap space \n\t   available to support this, the fork() will fail when the system tries \n\t   to reserve backing store for pages that are never touched.  Even in \n\t   non-large processes this can cause problems when (as with the \n\t   randomness-gatherer) many children are forked at once.  However this \n\t   is a rather unlikely situation, and since the fork()-based entropy-\n\t   gathering is used only as a last resort when all other methods have\n\t   failed, we rarely get to this code, let alone run it in a situation\n\t   where the problem described above crops up.\n\n\t   In the absence of threads the use of pcreate() (which only requires\n\t   backing store for the new processes' stack, not the entire process)\n\t   would do the trick, however pcreate() isn't compatible with threads,\n\t   which makes it of little use for the default thread-enabled cryptlib\n\t   build */\n\tentry->pid = fork();\n\tif( entry->pid == ( pid_t ) -1 )\n\t\t{\n\t\t/* The fork failed */\n\t\tclose( pipedes[ 0 ] );\n\t\tclose( pipedes[ 1 ] );\n\t\treturn( NULL );\n\t\t}\n\n\tif( entry->pid == ( pid_t ) 0 )\n\t\t{\n\t\tint fd;\n\n\t\t/* We're the child, connect the read side of the pipe to stdout and\n\t\t   unplug stdin and stderr */\n\t\tif( dup2( pipedes[ STDOUT_FILENO ], STDOUT_FILENO ) < 0 )\n\t\t\tCHILD_EXIT( 127 );\n\t\tif( ( fd = open( \"/dev/null\", O_RDWR ) ) > 0 )\n\t\t\t{\n\t\t\tdup2( fd, STDIN_FILENO );\n\t\t\tdup2( fd, STDERR_FILENO );\n\t\t\tclose( fd );\n\t\t\t}\n\n\t\t/* Give up our permissions if required to make sure that we don't \n\t\t   inadvertently read anything sensitive.  We don't check whether \n\t\t   the change succeeds since it's not a major security problem but \n\t\t   just a precaution (in theory an attacker could do something like \n\t\t   fork()ing until RLIMIT_NPROC is reached, at which point it'd \n\t\t   fail, but that doesn't really give them anything) */\n\t\tif( gathererUID != ( uid_t ) -1 )\n\t\t\t{\n#if 0\t\t/* Not available on some OSes */\n\t\t\t( void ) setuid( gathererUID );\n\t\t\t( void ) seteuid( gathererUID );\n\t\t\t( void ) setgid( gathererGID );\n\t\t\t( void ) setegid( gathererGID );\n#else\n  #if( defined( __linux__ ) || ( defined( __FreeBSD__ ) && OSVERSION >= 5 ) || \\\n\t   ( defined( __hpux ) && OSVERSION >= 11 ) )\n\t\t\t( void ) setresuid( gathererUID, gathererUID, gathererUID );\n\t\t\t( void ) setresgid( gathererGID, gathererGID, gathererGID );\n  #else\n\t\t\t( void ) setreuid( gathererUID, gathererUID );\n\t\t\t( void ) setregid( gathererGID, gathererGID );\n  #endif /* OSses with setresXid() */\n#endif /* 0 */\n\t\t\t}\n\n\t\t/* Close the pipe descriptors */\n\t\tclose( pipedes[ STDIN_FILENO ] );\n\t\tclose( pipedes[ STDOUT_FILENO ] );\n\n\t\t/* Try and exec the program */\n\t\texecl( entry->path, entry->path, entry->arg, NULL );\n\n\t\t/* Die if the exec failed */\n\t\tCHILD_EXIT( 127 );\n\t\t}\n\n\t/* We're the parent, close the irrelevant side of the pipe and open the\n\t   relevant side as a new stream.  Mark our side of the pipe to close on\n\t   exec, so new children won't see it (if this call fails there's not \n\t   much that we can do, and it's mostly a hygiene thing so we don't fail\n\t   fatally on it) */\n\tclose( pipedes[ STDOUT_FILENO ] );\n\t( void ) fcntl( pipedes[ STDIN_FILENO ], F_SETFD, FD_CLOEXEC );\n\tstream = fdopen( pipedes[ STDIN_FILENO ], \"r\" );\n\tif( stream == NULL )\n\t\t{\n\t\tint savedErrno = errno;\n\n\t\t/* The stream couldn't be opened or the child structure couldn't be\n\t\t   allocated.  Kill the child and close the other side of the pipe */\n\t\tkill( entry->pid, SIGKILL );\n\t\tclose( pipedes[ STDOUT_FILENO ] );\n\t\twaitpid( entry->pid, NULL, 0 );\n\t\tentry->pid = 0;\n\t\terrno = savedErrno;\n\t\treturn( NULL );\n\t\t}\n\n\treturn( stream );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int my_pclose( INOUT DATA_SOURCE_INFO *entry, \n\t\t\t\t\t  INOUT struct rusage *rusage )\n\t{\n\tpid_t pid;\n\tint iterationCount = 0, status = 0;\n\n\t/* Close the pipe */\n\tfclose( entry->pipe );\n\tentry->pipe = NULL;\n\n\t/* Wait for the child to terminate, ignoring the return value from the\n\t   process because some programs return funny values that would result\n\t   in the input being discarded even if they executed successfully.\n\t   This isn't a problem because the result data size threshold will\n\t   filter out any programs that exit with a usage message without\n\t   producing useful output */\n\tdo\n\t\t{\n\t\t/* We use wait4() instead of waitpid() to get the last bit of\n\t\t   entropy data, the resource usage of the child */\n\t\terrno = 0;\n\t\tpid = wait4( entry->pid, NULL, 0, rusage );\n\t\t}\n\twhile( pid == -1 && errno == EINTR && \\\n\t\t   iterationCount++ < FAILSAFE_ITERATIONS_SMALL );\n\tif( pid != entry->pid )\n\t\tstatus = -1;\n\tentry->pid = 0;\n\n\treturn( status );\n\t}\n\n/* Get data from an external entropy source */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int getEntropySourceData( INOUT DATA_SOURCE_INFO *dataSource, \n\t\t\t\t\t\t\t\t OUT_BUFFER( bufSize, *bufPos ) BYTE *bufPtr, \n\t\t\t\t\t\t\t\t IN_DATALENGTH const int bufSize, \n\t\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *bufPos )\n\t{\n\tint bufReadPos = 0, bufWritePos = 0;\n\tsize_t noBytes;\n\n\t/* Try and get more data from the source.  If we get zero bytes then the\n\t   source has sent us all it has */\n\tif( ( noBytes = fread( bufPtr, 1, bufSize, dataSource->pipe ) ) <= 0 )\n\t\t{\n\t\tstruct rusage rusage;\n\t\tint total = 0;\n\n\t\t/* If there's a problem, exit */\n\t\tif( my_pclose( dataSource, &rusage ) != 0 )\n\t\t\treturn( 0 );\n\n\t\t/* Try and estimate how much entropy we're getting from a data\n\t\t   source */\n\t\tif( dataSource->usefulness != 0 )\n\t\t\t{\n\t\t\tif( dataSource->usefulness < 0 )\n\t\t\t\t{\n\t\t\t\t/* Absolute rating, 1024 / -n */\n\t\t\t\ttotal = 1025 / -dataSource->usefulness;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Relative rating, 1024 * n */\n\t\t\t\ttotal = dataSource->length / dataSource->usefulness;\n\t\t\t\t}\n\t\t\t}\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"%s %s contributed %d bytes (compressed), \"\n\t\t\t\t\t\t\t\"usefulness = %d.\\n\", dataSource->path,\n\t\t\t\t\t\t\t( dataSource->arg != NULL ) ? dataSource->arg : \"\",\n\t\t\t\t\t\t\tdataSource->length, total ));\n\n\t\t/* Copy in the last bit of entropy data, the resource usage of the\n\t\t   popen()ed child */\n\t\tif( sizeof( struct rusage ) < bufSize )\n\t\t\t{\n\t\t\tmemcpy( bufPtr, &rusage, sizeof( struct rusage ) );\n\t\t\t*bufPos += sizeof( struct rusage );\n\t\t\t}\n\n\t\treturn( total );\n\t\t}\n\n\t/* Run-length compress the input byte sequence */\n\twhile( bufReadPos < noBytes )\n\t\t{\n\t\tconst int ch = byteToInt( bufPtr[ bufReadPos ] );\n\n\t\t/* If it's a single byte or we're at the end of the buffer, just\n\t\t   copy it over */\n\t\tif( bufReadPos >= bufSize - 1 || ch != bufPtr[ bufReadPos + 1 ] )\n\t\t\t{\n\t\t\tbufPtr[ bufWritePos++ ] = intToByte( ch );\n\t\t\tbufReadPos++;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint count = 0;\n\n\t\t\t/* It's a run of repeated bytes, replace them with the byte\n\t\t\t   count mod 256 */\n\t\t\twhile( bufReadPos < noBytes && ( ch == bufPtr[ bufReadPos ] ) )\n\t\t\t\t{\n\t\t\t\tcount++;\n\t\t\t\tbufReadPos++;\n\t\t\t\t}\n\t\t\tbufPtr[ bufWritePos++ ] = intToByte( count );\n\t\t\t}\n\t\t}\n\n\t/* Remember the number of (compressed) bytes of input that we obtained */\n\t*bufPos += bufWritePos;\n\tdataSource->length += noBytes;\n\n\treturn( 0 );\n\t}\n\n/* The child process that performs the polling, forked from slowPoll() */\n\n#define SLOWPOLL_TIMEOUT\t30\t\t/* Time out after 30 seconds */\n\nstatic void childPollingProcess( const int existingEntropy )\n\t{\n\tGATHERER_INFO *gathererInfo;\n\tMONOTIMER_INFO timerInfo;\n\tBOOLEAN moreSources;\n\tstruct timeval tv;\n\tstruct rlimit rl = { 0, 0 };\n\tfd_set fds;\n#ifdef _SC_OPEN_MAX\n\tconst int fdTableSize = sysconf( _SC_OPEN_MAX );\n#else\n\tconst int fdTableSize = getdtablesize();\n#endif /* System-specific ways to get the file descriptor tbl.size */\n#if defined( __hpux )\n\tsize_t maxFD = 0;\n#else\n\tint maxFD = 0;\n#endif /* OS-specific brokenness */\n\tint usefulness = 0, fdIndex, bufPos, i, iterationCount, status;\n\n\t/* General housekeeping: Make sure that we can never dump core, and close\n\t   all inherited file descriptors.  We need to do this because if we\n\t   don't and the calling app has FILE's open, these will be flushed if \n\t   we call exit() in the child and again when the parent writes to them \n\t   or closes them, resulting in everything that was present in the\n\t   FILE * buffer at the time of the fork() being written twice.  An\n\t   alternative solution would be to call _exit() instead of exit() \n\t   (which is the default action for the CHILD_EXIT() macro), but this is \n\t   somewhat system-dependant and isn't present in all cases so we still\n\t   take the precaution of exit()-proofing the code.\n\t   \n\t   Note that we don't close any of the standard handles because this \n\t   could lead to the next file being opened being given the stdin/stdout/\n\t   stderr handle, which in general is just a nuisance but then some \n\t   older kernels didn't check handles when running a setuid program so \n\t   that it was actually an exploitable flaw.  In addition some later \n\t   kernels (e.g. NetBSD) overreact to the problem a bit and complain \n\t   when they see a setuid program with stdin/stdout/stderr closed, so \n\t   it's a good idea to leave these open.  We could in theory close them\n\t   anyway and reopen them to /dev/null, but it's not clear whether this\n\t   really buys us anything.\n\n\t   In addition to this we should in theory call cryptEnd() since we\n\t   don't need any cryptlib objects beyond this point and it'd be a good\n\t   idea to clean them up to get rid of sensitive data held in memory.\n\t   However in some cases when using a crypto device or network interface\n\t   or similar item the shutdown in the child will also shut down the\n\t   parent item because while cryptlib objects are reference-counted the\n\t   external items aren't (they're beyond the control of cryptlib).  Even\n\t   destroying just contexts with keys loaded isn't possible because they\n\t   may be tied to a device that will propagate the shutdown from the\n\t   child to the parent via the device.\n\n\t   In general the child will be short-lived, and the fact that any modern \n\t   fork() will have copy-on-write semantics will mean that cryptlib \n\t   memory is never copied to the child and further children.  It would, \n\t   however, be better if there were some way to perform a neutron-bomb \n\t   type shutdown that only zeroises senstive information while leaving \n\t   structures intact */\n\tsetrlimit( RLIMIT_CORE, &rl );\n\tfor( fdIndex = fdTableSize - 1; fdIndex > STDOUT_FILENO; fdIndex-- )\n\t\tclose( fdIndex );\n\tfclose( stderr );\t/* Arrghh!!  It's Stuart code!! */\n\n\t/* Fire up each randomness source */\n\tFD_ZERO( &fds );\n\tfor( i = 0; dataSources[ i ].path != NULL && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ); i++ )\n\t\t{\n\t\t/* Check for the end-of-lightweight-sources marker */\n\t\tif( dataSources[ i ].path[ 0 ] == '\\0' )\n\t\t\t{\n\t\t\t/* If we're only polling lightweight sources because we've\n\t\t\t   already obtained entropy from additional sources, we're\n\t\t\t   done */\n\t\t\tif( existingEntropy >= 50 )\n\t\t\t\t{\n\t\t\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t\t\t  ( \"All lightweight sources polled, exiting \"\n\t\t\t\t\t\t\t\t\t\"without polling heavyweight ones.\\n\" ));\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* We're polling all sources, continue with the heavyweight\n\t\t\t   ones */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Since popen() is a fairly heavyweight function, we check to see \n\t\t   whether the executable exists before we try to run it */\n\t\tif( access( dataSources[ i ].path, X_OK ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t\t  ( \"%s not present%s.\\n\", dataSources[ i ].path,\n\t\t\t\t\t\t\t\tdataSources[ i ].hasAlternative ? \\\n\t\t\t\t\t\t\t\t\t\", has alternatives\" : \"\" ));\n\t\t\tdataSources[ i ].pipe = NULL;\n\t\t\t}\n\t\telse\n\t\t\tdataSources[ i ].pipe = my_popen( &dataSources[ i ] );\n\t\tif( dataSources[ i ].pipe == NULL )\n\t\t\tcontinue;\n\t\tif( fileno( dataSources[ i ].pipe ) >= FD_SETSIZE )\n\t\t\t{\n\t\t\t/* The fd is larger than what can be fitted into an fd_set, don't\n\t\t\t   try and use it.  This can happen if the calling app opens a\n\t\t\t   large number of files, since most FD_SET() macros don't\n\t\t\t   perform any safety checks this can cause segfaults and other\n\t\t\t   problems if we don't perform the check ourselves */\n\t\t\tfclose( dataSources[ i ].pipe );\n\t\t\tdataSources[ i ].pipe = NULL;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Set up the data source information */\n\t\tdataSources[ i ].pipeFD = fileno( dataSources[ i ].pipe );\n\t\tif( dataSources[ i ].pipeFD > maxFD )\n\t\t\tmaxFD = dataSources[ i ].pipeFD;\n\t\tfcntl( dataSources[ i ].pipeFD, F_SETFL, O_NONBLOCK );\n\t\tFD_SET( dataSources[ i ].pipeFD, &fds );\n\t\tdataSources[ i ].length = 0;\n\n\t\t/* If there are alternatives for this command, don't try and execute\n\t\t   them */\n\t\titerationCount = 0;\n\t\twhile( dataSources[ i ].path != NULL && \\\n\t\t\t   dataSources[ i ].hasAlternative && \\\n\t\t\t   i < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ) && \\\n\t\t\t   iterationCount++ < FAILSAFE_ITERATIONS_MED ) \n\t\t\t{\n\t\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t\t  ( \"Skipping %s.\\n\", \n\t\t\t\t\t\t\t\tdataSources[ i + 1 ].path ));\n\t\t\ti++;\n\t\t\t}\n\t\tENSURES_EXIT( iterationCount < FAILSAFE_ITERATIONS_MED );\n\t\t\t\t\t  /* i is checked as part of the loop control */\n\t\t}\n\tENSURES_EXIT( i < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ) );\n\tgathererInfo = ( GATHERER_INFO * ) gathererBuffer;\n\tbufPos = sizeof( GATHERER_INFO );\t/* Start of buf.has status info */\n\n\t/* Suck up all of the data that we can get from each of the sources */\n\tstatus = setMonoTimer( &timerInfo, SLOWPOLL_TIMEOUT );\n\tENSURES_EXIT( cryptStatusOK( status ) );\n\tfor( moreSources = TRUE, iterationCount = 0;\n\t\t moreSources && bufPos < gathererBufSize && \\\n\t\t\titerationCount < FAILSAFE_ITERATIONS_MAX; \n\t\t iterationCount++ )\n\t\t{\n\t\t/* Wait for data to become available from any of the sources, with a\n\t\t   timeout of 10 seconds.  This adds even more randomness since data\n\t\t   becomes available in a nondeterministic fashion.  Kudos to HP's QA\n\t\t   department for managing to ship a select() that breaks its own\n\t\t   prototype */\n\t\ttv.tv_sec = 10;\n\t\ttv.tv_usec = 0;\n#if defined( __hpux ) && ( OSVERSION == 9 || OSVERSION == 0 )\n\t\tif( select( maxFD + 1, ( int * ) &fds, NULL, NULL, &tv ) == -1 )\n#else\n\t\tif( select( maxFD + 1, &fds, NULL, NULL, &tv ) == -1 )\n#endif /* __hpux */\n\t\t\tbreak;\n\n\t\t/* One of the sources has data available, read it into the buffer */\n\t\tfor( i = 0; dataSources[ i ].path != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ); \n\t\t\t i++ )\n\t\t\t{\n\t\t\tif( dataSources[ i ].pipe != NULL && \\\n\t\t\t\tFD_ISSET( dataSources[ i ].pipeFD, &fds ) )\n\t\t\t\t{\n\t\t\t\tusefulness += getEntropySourceData( &dataSources[ i ],\n\t\t\t\t\t\t\t\t\t\t\t\t\tgathererBuffer + bufPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgathererBufSize - bufPos,\n\t\t\t\t\t\t\t\t\t\t\t\t\t&bufPos );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_EXIT( i < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ) );\n\n\t\t/* Check if there's more input available on any of the sources */\n\t\tmoreSources = FALSE;\n\t\tFD_ZERO( &fds );\n\t\tfor( i = 0; dataSources[ i ].path != NULL && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ); \n\t\t\t i++ )\n\t\t\t{\n\t\t\tif( dataSources[ i ].pipe != NULL )\n\t\t\t\t{\n\t\t\t\tFD_SET( dataSources[ i ].pipeFD, &fds );\n\t\t\t\tmoreSources = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_EXIT( i < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ) );\n\n\t\t/* If we've gone over our time limit, kill anything still hanging\n\t\t   around and exit.  This prevents problems with input from blocked\n\t\t   sources */\n\t\tif( checkMonoTimerExpired( &timerInfo ) )\n\t\t\t{\n\t\t\tfor( i = 0; dataSources[ i ].path != NULL && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ); \n\t\t\t\t i++ )\n\t\t\t\t{\n\t\t\t\tif( dataSources[ i ].pipe != NULL )\n\t\t\t\t\t{\n\t\t\t\t\tDEBUG_DIAG(( \"Aborting read of %s due to timeout\", \n\t\t\t\t\t\t\t\t dataSources[ i ].path ));\n\t\t\t\t\tfclose( dataSources[ i ].pipe );\n\t\t\t\t\tkill( dataSources[ i ].pid, SIGKILL );\n\t\t\t\t\tdataSources[ i ].pipe = NULL;\n\t\t\t\t\tdataSources[ i ].pid = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES_EXIT( i < FAILSAFE_ARRAYSIZE( dataSources, DATA_SOURCE_INFO ) );\n\t\t\tmoreSources = FALSE;\n\t\t\tDEBUG_DIAG(( \"Poll timed out, probably due to blocked data \"\n\t\t\t\t\t\t \"source\" ));\n\t\t\t}\n\t\t}\n\tENSURES_EXIT( iterationCount < FAILSAFE_ITERATIONS_MAX );\n\tgathererInfo->usefulness = usefulness;\n\tgathererInfo->noBytes = bufPos;\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"Got %d bytes, usefulness = %d.\\n\", bufPos, \n\t\t\t\t\t\tusefulness ));\n\n\t/* \"Thou child of the daemon, ... wilt thou not cease...?\"\n\t   -- Acts 13:10 */\n\tCHILD_EXIT( 0 );\n\t}\n\n/* Unix external-source slow poll.  If a few of the randomness sources \n   create a large amount of output then the slowPoll() stops once the buffer \n   has been filled (but before all of the randomness sources have been \n   sucked dry) so that the 'usefulness' factor remains below the threshold.  \n   For this reason the gatherer buffer has to be fairly sizeable on \n   moderately loaded systems.\n\n   An alternative strategy, suggested by Massimo Squillace, is to use a \n   chunk of shared memory protected by a semaphore, with the first \n   sizeof( int ) bytes at the start serving as a high-water mark.  The \n   process forks and waitpid()'s for the child's pid.  The child forks all \n   the entropy-gatherers and exits, allowing the parent to resume execution. \n   The child's children are inherited by init (double-fork paradigm), when \n   each one is finished it takes the semaphore, writes data to the shared \n   memory segment at the given offset, updates the offset, releases the \n   semaphore again, and exits, to be reaped by init.\n\n   The parent monitors the shared memory offset and when enough data is \n   available takes the semaphore, grabs the data, and releases the shared \n   memory area and semaphore.  If any children are still running they'll get \n   errors when they try to access the semaphore or shared memory and \n   silently exit.\n\n   This approach has the advantage that all of the forked processes are \n   managed by init rather than having the parent have to wait for them, but \n   the disadvantage that the end-of-job handling is rather less rigorous. \n   An additional disadvantage is that the existing code has had a lot of \n   real-world testing and adaptation to system-specific quirks, which would \n   have to be repeated for any new version */\n\n#define SHARED_BUFSIZE\t\t49152\t/* Usually about 25K are filled */\n\nstatic void externalSourcesPoll( const int existingEntropy )\n\t{\n\tconst int pageSize = getSysVar( SYSVAR_PAGESIZE );\n\n\t/* Check whether a non-default SIGCHLD handler is present.  This is \n\t   necessary because if the program that cryptlib is a part of installs \n\t   its own handler it will end up reaping the cryptlib children before\n\t   cryptlib can.  As a result my_pclose() will call waitpid() on a\n\t   process that has already been reaped by the installed handler and\n\t   return an error, so the read data won't be added to the randomness\n\t   pool */\n\tif( sigaction( SIGCHLD, NULL, &gathererOldHandler ) < 0 )\n\t\t{\n\t\t/* This assumes that stderr is open, i.e. that we're not a daemon.\n\t\t   This should be the case at least during the development/debugging\n\t\t   stage */\n\t\tDEBUG_DIAG(( \"sigaction() failed, errno = %d\", errno ));\n\t\tfprintf( stderr, \"cryptlib: sigaction() failed, errno = %d, \"\n\t\t\t\t \"file \" __FILE__ \", line %d.\\n\", errno, __LINE__ );\n\t\tabort();\n\t\t}\n\n\t/* Check for handler override */\n\tif( gathererOldHandler.sa_handler != SIG_DFL && \\\n\t\tgathererOldHandler.sa_handler != SIG_IGN )\n\t\t{\n\t\t/* We overwrote the caller's handler, warn them about this */\n\t\tDEBUG_DIAG(( \"Conflicting SIGCHLD handling detected in randomness \"\n\t\t\t\t\t \"polling code,\\nsee the source code for more \"\n\t\t\t\t\t \"information\" ));\n\t\t}\n\n\t/* If a non-default handler is present, replace it with the default \n\t   handler */\n\tif( gathererOldHandler.sa_handler != SIG_DFL )\n\t\t{\n\t\tstruct sigaction newHandler;\n\n\t\tmemset( &newHandler, 0, sizeof( newHandler ) );\n\t\tnewHandler.sa_handler = SIG_DFL;\n\t\tsigemptyset( &newHandler.sa_mask );\n\t\tsigaction( SIGCHLD, &newHandler, NULL );\n\t\t}\n\n\t/* Determine how much memory we want to set up.  This can get a bit \n\t   tricky, implementations typically round the amount passed to shmget()\n\t   up to the system page size, typically 4kB, but some systems have\n\t   variable-size pages that can, in theory, go up to 4GB or more.  To\n\t   deal with this, we fit the amount that we're requesting into the page \n\t   size if pages are more or less standard-sized, but don't try and do \n\t   anything if pages are huge */\n\tgathererBufSize = ( pageSize <= SHARED_BUFSIZE ) ? \\\n\t\t\t\t\t  ( ( SHARED_BUFSIZE + pageSize - 1 ) / pageSize ) * pageSize : \\\n\t\t\t\t\t  SHARED_BUFSIZE;\n\n\t/* Set up the shared memory */\n\terrno = 0;\n\tif( ( gathererMemID = shmget( IPC_PRIVATE, gathererBufSize,\n\t\t\t\t\t\t\t\t  IPC_CREAT | 0600 ) ) == -1 || \\\n\t\t( gathererBuffer = ( BYTE * ) shmat( gathererMemID,\n\t\t\t\t\t\t\t\t\t\t\t NULL, 0 ) ) == ( BYTE * ) -1 )\n\t\t{\n\t\t/* There was a problem obtaining the shared memory, warn the user\n\t\t   and exit */\n#ifdef _CRAY\n\t\tif( errno == ENOSYS )\n\t\t\t{\n\t\t\t/* Unicos supports shmget/shmat, but older Crays don't implement\n\t\t\t   it and return ENOSYS */\n\t\t\tfprintf( stderr, \"cryptlib: SYSV shared memory required for \"\n\t\t\t\t\t \"random number gathering isn't\\n  supported on this \"\n\t\t\t\t\t \"type of Cray hardware (ENOSYS),\\n  file \" __FILE__ \n\t\t\t\t\t \", line %d.\\n\", __LINE__ );\n\t\t\t}\n#endif /* Cray */\n\t\tDEBUG_DIAG(( \"shmget()/shmat() failed, errno = %d\", errno ));\n\t\tif( gathererMemID != -1 )\n\t\t\tshmctl( gathererMemID, IPC_RMID, NULL );\n\t\tif( gathererOldHandler.sa_handler != SIG_DFL )\n\t\t\tsigaction( SIGCHLD, &gathererOldHandler, NULL );\n\t\tunlockPollingMutex();\n\t\treturn; /* Something broke */\n\t\t}\n\n\t/* At this point we have a possible race condition since we need to set\n\t   the gatherer PID value inside the mutex but messing with mutexes\n\t   across a fork() is somewhat messy.  To resolve this, we set the PID\n\t   to a nonzero value (which marks it as busy) and exit the mutex, then\n\t   overwrite it with the real PID (also nonzero) from the fork */\n\tgathererProcess = -1;\n\tunlockPollingMutex();\n\n\t/* Fork off the gatherer, the parent process returns to the caller.  \n\t\n\t   Programs using the OS X Core Foundation framework will complain if a \n\t   program calls fork() and doesn't follow it up with an exec() (which \n\t   really screws up daemonization ), printing an error message:\n\n\t\tThe process has forked and you cannot use this CoreFoundation \\\n\t\tfunctionality safely. You MUST exec().\n\n\t   There are workarounds possible but they're daemon-specific and \n\t   involve running under launchd, which isn't really an option here.\n\t   For now this is left as an OS X framework problem, there doesn't\n\t   seem to be anything that we can do to fix it here */\n\tif( ( gathererProcess = fork() ) != 0 )\n\t\t{\n\t\t/* If we're the parent, we're done */\n\t\tif( gathererProcess != -1 )\n\t\t\treturn;\n\n\t\t/* The fork() failed, clean up and reset the gatherer PID to make \n\t\t   sure that we're not locked out of retrying the poll later */\n\t\tDEBUG_DIAG(( \"fork() failed, errno = %d\", errno ));\n\t\tlockPollingMutex();\n\t\tshmctl( gathererMemID, IPC_RMID, NULL );\n\t\tif( gathererOldHandler.sa_handler != SIG_DFL )\n\t\t\tsigaction( SIGCHLD, &gathererOldHandler, NULL );\n\t\tgathererProcess = 0;\n\t\tunlockPollingMutex();\n\t\treturn;\n\t\t}\n\n\t/* Make the child an explicitly distinct function */\n\tchildPollingProcess( existingEntropy );\n\t}\n\nstatic int externalSourcesPollComplete( const BOOLEAN force )\n\t{\n\tMESSAGE_DATA msgData;\n\tGATHERER_INFO *gathererInfo = ( GATHERER_INFO * ) gathererBuffer;\n\tpid_t pid;\n\tint quality, waitPidStatus, iterationCount = 0;\n\n\tlockPollingMutex();\n\tif( gathererProcess\t<= 0 )\n\t\t{\n\t\t/* There's no gatherer running, exit */\n\t\tunlockPollingMutex();\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If this is a forced shutdown, be fairly assertive with the gathering \n\t   process */\n\tif( force )\n\t\t{\n\t\t/* Politely ask the the gatherer to shut down and (try and) yield \n\t\t   our timeslice a few times so that the shutdown can take effect. \n\t\t   This is unfortunately somewhat implementation-dependant in that \n\t\t   in some cases it'll only yield the current thread's timeslice \n\t\t   rather than the overall process' timeslice, or if it's a high-\n\t\t   priority thread it'll be scheduled again before any lower-\n\t\t   priority threads get to run */\n\t\tkill( gathererProcess, SIGTERM );\n\t\tsched_yield();\n\t\tsched_yield();\n\t\tsched_yield();\t/* Well, sync is done three times too... */\n\n\t\t/* If the gatherer is still running, ask again, less politely this \n\t\t   time */\n\t\terrno = 0;\n\t\tif( kill( gathererProcess, 0 ) != -1 || errno != ESRCH )\n\t\t\tkill( gathererProcess, SIGKILL );\n\t\t}\n\n\t/* Wait for the gathering process to finish and, if it was sucessful, \n\t   add the randomness that it's gathered */\n\tdo\n\t\t{\n\t\terrno = 0;\n\t\tpid = waitpid( gathererProcess, &waitPidStatus, 0 );\n\t\t}\n\twhile( pid == -1 && errno == EINTR && \\\n\t\t   iterationCount++ < FAILSAFE_ITERATIONS_SMALL );\n\tif( pid == gathererProcess && WIFEXITED( waitPidStatus ) )\n\t\t{\n\t\t/* The child terminated normally, forward its output to the system \n\t\t   device */\n\t\tif( gathererInfo->noBytes > 0 && !force )\n\t\t\t{\n\t\t\tint status;\n\n\t\t\tquality = min( gathererInfo->usefulness * 5, 100 );\t/* 0-20 -> 0-100 */\n\t\t\tsetMessageData( &msgData, gathererBuffer, gathererInfo->noBytes );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tassert( cryptStatusOK( status ) );\n\t\t\tif( quality > 0 )\n\t\t\t\t{\n\t\t\t\t/* On some very cut-down embedded systems the entropy \n\t\t\t\t   quality can be zero so we only send a quality estimate if \n\t\t\t\t   there's actually something there */\n\t\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\tassert( cryptStatusOK( status ) );\n\t\t\t\t}\n\n\t\t\tDEBUG_PRINT_COND( debugRandom,\n\t\t\t\t\t\t\t  ( \"Polling parent added %d bytes, \"\n\t\t\t\t\t\t\t\t\"quality = %d.\\n\", gathererInfo->noBytes, \n\t\t\t\t\t\t\t\tquality ));\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There was a problem with the gatherer process, let the user \n\t\t   know */\n\t\tDEBUG_DIAG(( \"Polling parent failed to get data from child,\\n  \"\n\t\t\t\t\t \"waitpid() status value %X, errno = %d\", waitPidStatus, \n\t\t\t\t\t errno ));\n\t\tDEBUG_PRINT_COND( debugRandom && WIFSIGNALED( waitPidStatus ),\n\t\t\t\t\t\t  ( \"  Child was terminated due to signal %d.\\n\",\n\t\t\t\t\t\t    WTERMSIG( waitPidStatus ) ));\n\t\t}\n\tzeroise( gathererBuffer, gathererBufSize );\n\n\t/* Detach and delete the shared memory (the latter is necessary because \n\t   otherwise the unused ID hangs around until the process terminates) \n\t   and restore the original signal handler if we replaced someone else's \n\t   one */\n\tshmdt( gathererBuffer );\n\tshmctl( gathererMemID, IPC_RMID, NULL );\n\tif( gathererOldHandler.sa_handler != SIG_DFL )\n\t\t{\n\t\tstruct sigaction oact;\n\n\t\t/* We replaced someone else's handler for the slow poll, reinstate \n\t\t   the original one.  Since someone else could have in turn replaced \n\t\t   our handler, we check for this and warn the user if necessary */\n\t\tsigaction( SIGCHLD, NULL, &oact );\n\t\tif( oact.sa_handler != SIG_DFL )\n\t\t\t{\n\t\t\t/* The current handler isn't the one that we installed, warn the \n\t\t\t   user */\n\t\t\tDEBUG_DIAG(( \"SIGCHLD handler was replaced while slow poll was \"\n\t\t\t\t\t\t \"in progress,\\nsee the source code for more \"\n\t\t\t\t\t\t \"information\" ));\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Our handler is still in place, replace it with the original \n\t\t\t   one */\n\t\t\tsigaction( SIGCHLD, &gathererOldHandler, NULL );\n\t\t\t}\n\t\t}\n\tgathererProcess = 0;\n\tunlockPollingMutex();\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* NO_SYSV_SHAREDMEM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSlow Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Slow poll.  We try for sources that are directly accessible \n   programmatically and only fall back to the external-sources poll as a \n   last resort (this is rarely, if ever, required) */\n\nvoid slowPoll( void )\n\t{\n#ifdef USE_PERFEVENT\n\tint perfEventFDs[ PERF_EVENT_MAX ];\n\tBOOLEAN perfEventsOK = FALSE;\n#endif /* USE_PERFEVENT */\n\tint entropy = 0;\n\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"Attempting to get entropy from /dev/urandom\" ));\n\tDEBUG_PRINT_COND( debugRandom && !access( \"/dev/hwrng\", R_OK ), \n\t\t\t\t\t  ( \", /dev/hwrng\" ));\n\tDEBUG_PRINT_COND( debugRandom && !access( \"/proc/interrupts\", R_OK ), \n\t\t\t\t\t  ( \", procfs\" ));\n\tDEBUG_PRINT_COND( debugRandom && !access( \"/sys/block\", R_OK ), \n\t\t\t\t\t  ( \", sysfs\" ));\n#ifdef USE_KSTAT\n\tDEBUG_PRINT_COND( debugRandom, ( \", kstat\" ));\n#endif /* USE_KSTAT */\n#ifdef USE_PROC\n\tDEBUG_PRINT_COND( debugRandom, ( \", proc (via ioctls)\" ));\n#endif /* USE_PROC */\n#ifdef USE_SYSCTL\n\tDEBUG_PRINT_COND( debugRandom, ( \", sysctl\" ));\n#endif /* USE_SYSCTL */\n#ifdef USE_GETIFADDRS\n\tDEBUG_PRINT_COND( debugRandom, ( \", getifaddrs\" ));\n#endif /* USE_GETIFADDRS */\n#ifdef USE_GETFSSTAT\n\tDEBUG_PRINT_COND( debugRandom, ( \", getfsstat\" ));\n#endif /* USE_GETFSSTAT */\n#ifdef USE_PERFEVENT\n\tDEBUG_PRINT_COND( debugRandom && !access( \"/proc/sys/kernel/perf_event_paranoid\", R_OK ),\n\t\t\t\t\t  ( \", perf_event\" ));\n#endif /* USE_PERFEVENT */\n#ifdef __iOS__ \n\tDEBUG_PRINT_COND( debugRandom, ( \", iOS SecRandomCopyBytes()\" ));\n#endif /* __iOS__  */\n#ifdef USE_TPM\n\tDEBUG_PRINT_COND( debugRandom, ( \", system TPM\" ));\n#endif /* USE_TPM */\n\tDEBUG_PRINT_COND( debugRandom, ( \".\\n\" ));\n\n\t/* If we can detect a TPM and its use isn't enabled, notify that it \n\t   could be used */\n#ifndef USE_TPM\n\tDEBUG_OP( { BYTE buffer[ 128 ]; int count; \n\t\t\t\t count = getHWRNGNAME( buffer, 128 ) );\n\tDEBUG_PRINT_COND( count >= 0 && !memcmp( buffer, \"tpm-rng\", 7 ),\n\t\t\t\t\t  ( \"System contains a TPM, consider enabling TPM use \"\n\t\t\t\t\t    \"via TSPI libraries.\\n\" ));\n\tDEBUG_OP( } );\n#endif /* USE_TPM */\n\n\t/* Make sure that we don't start more than one slow poll at a time.  The\n\t   gathererProcess value may be positive (a PID) or -1 (error), so we\n\t   compare it to the specific value 0 (= not-used) in the check */\n\tlockPollingMutex();\n\tif( gathererProcess != 0 )\n\t\t{\n\t\tunlockPollingMutex();\n\t\treturn;\n\t\t}\n\n\t/* Begin performance event polling.  This brackets the other polling \n\t   types since it measures system performance around the duration of the\n\t   other polls */\n#ifdef USE_PERFEVENT\n\tif( !access( \"/proc/sys/kernel/perf_event_paranoid\", R_OK ) )\n\t\tperfEventsOK = getPerfEventBegin( perfEventFDs );\n#endif /* USE_PERFEVENT */\n\n\t/* The popen()-level slow poll is the screen-scraping interface of last\n\t   resort that we use only if we can't get the entropy in any other\n\t   way.  If the system provides entropy from alternate sources, we don't \n\t   have have to try the screen-scraping slow poll (a number of these \n\t   additional sources, things like procfs and kstats, duplicate the \n\t   sources polled in the slow poll anyway, so we're not adding much by \n\t   polling these extra sources if we've already got the data directly) */\n\tentropy += getDevRandomData();\n\tif( !access( \"/dev/hwrng\", R_OK ) )\n\t\tentropy += getHWRNGData();\n\tif( !access( \"/proc/interrupts\", R_OK ) )\n\t\tentropy += getProcFSdata();\n\tif( !access( \"/sys/block\", R_OK ) )\n\t\tentropy += getSysFSdata();\n\tentropy += getEGDdata();\n#ifdef USE_KSTAT\n\tentropy += getKstatData();\n#endif /* USE_KSTAT */\n#ifdef USE_PROC\n\tentropy += getProcData();\n#endif /* USE_PROC */\n#ifdef USE_SYSCTL\n\tentropy += getSysctlData();\n#endif /* USE_SYSCTL */\n#ifdef USE_GETIFADDRS\n\tentropy += getIfaddrsData();\n#endif /* USE_GETIFADDRS */\n#ifdef USE_GETFSSTAT\n\tentropy += getFsstatData();\n#endif /* USE_GETFSSTAT */\n#ifdef __iOS__ \n\tentropy += getIOSData();\n#endif /* __iOS__  */\n#ifdef USE_TPM\n\tentropy += getTPMData();\n#endif /* USE_TPM */\n#ifdef USE_PERFEVENT\n\tif( perfEventsOK )\n\t\tentropy += getPerfEventEnd( perfEventFDs );\n#endif /* USE_PERFEVENT */\n\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t  ( \"Got %d entropy from direct sources.\\n\", entropy ));\n\tif( entropy >= 100 )\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"  Skipping full slowpoll since sufficient \"\n\t\t\t\t\t\t\t\"entropy is available.\\n\" ));\n\t\t}\n\telse\n\t\t{\n\t\tDEBUG_PRINT_COND( debugRandom, \n\t\t\t\t\t\t  ( \"  Continuing to full slowpoll since sufficient \"\n\t\t\t\t\t\t\t\"entropy wasn't gathered.\\n\" ));\n\t\t}\n\tif( entropy >= 100 )\n\t\t{\n\t\t/* We got enough entropy from the additional sources, we don't\n\t\t   have to go through with the full external-sources poll */\n\t\tunlockPollingMutex();\n\t\treturn;\n\t\t}\n\n\t/* A few systems don't support SYSV shared memory so we can't go beyond \n\t   this point, all that we can do is warn the user that they'll have to \n\t   use the entropy mechanisms intended for embedded systems without \n\t   proper entropy sources */\n#ifdef NO_SYSV_SHAREDMEM\n\tfprintf( stderr, \"cryptlib: This system doesn't contain the OS \"\n\t\t\t \"mechanisms required to provide\\n          system entropy \"\n\t\t\t \"sources that can be used for key generation.  In\\n\"\n\t\t\t \"          order to use cryptlib in this environment, you \"\n\t\t\t \"need to apply the\\n          randomness mechanisms for \"\n\t\t\t \"embedded systems described in the\\n          cryptlib \"\n\t\t\t \"manual.\\n\" );\n\tunlockPollingMutex();\n#else\n\texternalSourcesPoll( entropy );\n#endif /* NO_SYSV_SHAREDMEM */\n\t}\n\n/* Wait for the randomness gathering to finish */\n\nCHECK_RETVAL \\\nint waitforRandomCompletion( const BOOLEAN force )\n\t{\n#ifdef NO_SYSV_SHAREDMEM\n\treturn( CRYPT_OK );\n#else\n\treturn( externalSourcesPollComplete( force ) );\n#endif /* NO_SYSV_SHAREDMEM */\n\t}\n\n/* Check whether we've forked and we're the child.  The mechanism used varies\n   depending on whether we're running in a single-threaded or multithreaded\n   environment, for single-threaded we check whether the pid has changed\n   since the last check, for multithreaded environments this isn't reliable\n   since some systems have per-thread pid's so we need to use\n   pthread_atfork() as a trigger to set the pid-changed flag.\n   \n   This is complicated by the fact that some threads implementations don't \n   call pthread_atfork() on a vfork() (see the note about OS X below) while \n   others do, so that with sufficiently obstreperous use of vfork() (doing \n   stuff other than calling one of the exec() functions) it's possible to \n   end up with duplicate pools.  OTOH this behaviour is explicitly advised \n   against in vfork() manpages and documented as leading to undefined \n   behaviour, so anyone who does this kinda gets what they deserve.\n\n   In terms of OS-specific issues, under Aches calling pthread_atfork() with \n   any combination of arguments or circumstances produces a segfault, so we \n   disable its use and fall back to the getpid()-based fork detection.  In \n   addition some other environments don't support the call, so we exclude \n   those as well.  FreeBSD is a particular pain because of its highly \n   confusing use of -RELEASE, -STABLE (experimental), and -CURRENT (also \n   experimental but differently so) while maintaining the same version, it's \n   present in 5.x-CURRENT but not 5.x-RELEASE or -STABLE, so we have to \n   exclude it for all 5.x to be safe.  OS X is also a bit of a pain, support \n   was added after 10.4 (Tiger) but OS X uses vfork() internally so the \n   atfork handler doesn't get called because parent and child are still \n   sharing the same address space, so we also rely on the getpid()-based \n   fork detection mechanism.\n   \n   Another problem, specific to glibc and shared libraries, is that \n   pthread_atfork() isn't actually present in libpthread.so but in a static\n   library libpthread_nonshared.a, with libpthread.so actually being a \n   linker script that pulls in libpthread.so.0 and libpthread_nonshared.a.\n   If something goes wrong with this hack, it produces the gcc gibberish\n   \"hidden symbol `pthread_atfork' in XXX is referenced by DSO\", meaning \n   that there's a problem with linking in pthread_atfork() from \n   libpthread_nonshared.a.\n   \n   There are other possible fork-checking mechanisms, but they're even less\n   portable, and considerably more ugly, than pthread_atfork().  For example \n   some recent open-source Unix systems implement an INHERIT_ZERO flag for \n   minherit() which causes a page to be zeroed on fork, present in OpenBSD \n   5.6 and newer and FreeBSD 12.0 and newer, with the Linux version being \n   MADV_WIPEONFORK passed to madvise() in Linux 4.14 and newer.  One way to \n   implement this would be to mmap() a page, fill it with 0xFF, set \n   INHERIT_ZERO/MADV_WIPEONFORK as required, and treat it as a has-forked \n   boolean, but the lack of portability and general clunkiness makes it far \n   less useful than pthread_atfork() */\n\n#if defined( USE_THREADS ) && \\\n\t( defined( _AIX ) || defined( __Android__ ) || defined( _CRAY ) || \\\n\t  defined( __MVS__ ) || defined( _MPRAS ) || defined( __APPLE__ ) || \\\n\t  ( defined( __FreeBSD__ ) && OSVERSION <= 5 ) )\n  #define NO_PTHREAD_ATFORK\n#endif /* USE_THREADS && OSes without pthread_atfork() */\n\n#if defined( USE_THREADS ) && !defined( NO_PTHREAD_ATFORK )\n\nstatic BOOLEAN forked = FALSE;\nstatic pthread_mutex_t forkedMutex;\n\nBOOLEAN forkCheck( const BOOLEAN checkForked )\n\t{\n\tBOOLEAN hasForked;\n\n\t/* Read the forked-t flag in a thread-safe manner */\n\tpthread_mutex_lock( &forkedMutex );\n\tif( !checkForked )\n\t\thasForked = forked = FALSE;\n\telse\n\t\t{\n\t\thasForked = forked;\n\t\tforked = FALSE;\n\t\t}\n\tpthread_mutex_unlock( &forkedMutex );\n\n\treturn( hasForked );\n\t}\n\nvoid setForked( void )\n\t{\n\t/* Set the forked-t flag in a thread-safe manner */\n\tpthread_mutex_lock( &forkedMutex );\n\tforked = TRUE;\n\tpthread_mutex_unlock( &forkedMutex );\n\t}\n\n#else\n\nBOOLEAN forkCheck( const BOOLEAN checkForked )\n\t{\n\tstatic pid_t originalPID = -1;\n\n\t/* If this is an init, remember the current PID */\n\tif( !checkForked )\n\t\toriginalPID = getpid();\n\telse\n\t\t{\n\t\t/* This is a fork check, if the pid has changed then we've forked \n\t\t   and we're the child, remember the new pid */\n\t\tif( getpid() != originalPID )\n\t\t\t{\n\t\t\toriginalPID = getpid();\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\n\treturn( FALSE );\n\t}\n#endif /* USE_THREADS && !NO_PTHREAD_ATFORK */\n\n/* Initialise and clean up any auxiliary randomness-related objects */\n\nvoid initRandomPolling( void )\n\t{\n\t/* Hardcoding in the Posix function name at this point is safe because \n\t   it also works for Solaris threads */\n#ifdef USE_THREADS\n\tpthread_mutex_init( &gathererMutex, NULL );\n\n\t/* If it's multithreaded code then we need to ensure that we're \n\t   signalled if another thread calls fork().  We set the forked flag \n\t   in both the child and the parent to ensure that both sides remix the \n\t   pool thoroughly */\n  #ifndef NO_PTHREAD_ATFORK\n\tpthread_mutex_init( &forkedMutex, NULL );\n\tpthread_atfork( NULL, setForked, setForked );\n  #endif /* NO_PTHREAD_ATFORK */\n#endif /* USE_THREADS */\n\t}\n\nvoid endRandomPolling( void )\n\t{\n#ifdef USE_THREADS\n\tpthread_mutex_destroy( &gathererMutex );\n\n  #ifndef NO_PTHREAD_ATFORK\n\tpthread_mutex_destroy( &forkedMutex );\n  #endif /* NO_PTHREAD_ATFORK */\n#endif /* USE_THREADS */\n\t}\n"
  },
  {
    "path": "deps/cl345/random/vdk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tVDK Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/vmcms.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tVM/CMS Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\t  Copyright Peter Gutmann 1999\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide OS-specific randomness.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\ttime_t timeStamp = time( NULL );\n\n\t/* There's not much we can do under VM */\n\tsetMessageData( &msgData, &timeStamp, sizeof( time_t ) );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ 128 ];\n\tint quality = 1, total = 128;\n\n\t/* Kludge something here */\n\tsetMessageData( &msgData, buffer, total );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY );\n\tzeroise( buffer, sizeof( buffer ) );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE, &quality,\n\t\t\t\t\t CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/vxworks.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tVxWorks Randomness-Gathering Code\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   VxWorks provides very few entropy sources, the code below provides very \n   little usable entropy and should not be relied upon as the sole entropy \n   source for the system but should be augmented with randomness from \n   external hardware sources */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <vxWorks.h>\n#include <intLib.h>\n#include <sysLib.h>\n#include <taskLib.h>\n#include <tickLib.h>\n#include <time.h>\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t1024\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tREG_SET registerSet;\n\tstruct timespec timeSpec;\n\tULONG tickCount;\n\tint value, status;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Void();\n\n\t/* Add various clock/timer values.  These are both very fast clocks/\n\t   counters, however the difference over subsequent calls is only\n\t   2-3 bits in the LSB */\n\ttickCount = tickGet();\n\taddRandomLong( randomState, tickCount );\n\tstatus = clock_gettime( CLOCK_REALTIME, &timeSpec );\n\tif( status == 0 )\n\t\taddRandomData( randomState, &timeSpec, sizeof( struct timespec ) );\n\n\t/* Add the interrupt nesting depth (usually 0) */\n\tvalue = intCount();\n\taddRandomLong( randomState, value );\n\n\t/* Add the current task's registers.  The documentation states that \n\t   \"self-examination is not advisable as results are unpredictable\",\n\t   which is either good (the registers are random garbage values) or\n\t   bad (the registers have fixed values).  Usually they seem to be \n\t   pretty fixed, at least when called repeatedly in rapid succession */\n\tstatus = taskRegsGet( taskIdSelf(), &registerSet );\n\tif( status == OK )\n\t\taddRandomData( randomState, &registerSet, sizeof( REG_SET ) );\n\n\tendRandomData( randomState, 5 );\n\t}\n\nvoid slowPoll( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tint taskID, value, status;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Void();\n\n\t/* The following are fixed for the lifetime of the process (and in fact \n\t   for the BSP as a whole) so we only add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\tconst char *string;\n\n\t\t/* Add the model name of the CPU board and the BSP version and \n\t\t   revision number */\n\t\tstring = sysModel();\n\t\tif( string != NULL )\n\t\t\taddRandomData( randomState, string, strlen( string ) );\n\t\tstring = sysBspRev();\n\t\tif( string != NULL )\n\t\t\taddRandomData( randomState, string, strlen( string ) );\n\t\tvalue = sysProcNumGet();\t/* Usually 0 */\n\t\taddRandomLong( randomState, value );\n\t\t}\n\n\t/* Add the current task ID and task options.  The task options are \n\t   relatively fixed but the task ID seems quite random and over the full \n\t   32-bit range */\n\ttaskID = taskIdSelf();\n\taddRandomLong( randomState, taskID );\n\tstatus = taskOptionsGet( taskID, &value );\n\tif( status == OK )\n\t\taddRandomLong( randomState, value );\n\n\tendRandomData( randomState, 3 );\n\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/win16.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWin16 Randomness-Gathering Code\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2006\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include \"crypt.h\"\n\n/* OS-specific includes */\n\n#include <stress.h>\n#include <toolhelp.h>\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t1024\n\nvoid fastPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tSYSHEAPINFO sysHeapInfo;\n\tMEMMANINFO memManInfo;\n\tTIMERINFO timerInfo;\n\tPOINT point;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get various basic pieces of system information: Handle of the window\n\t   with mouse capture, handle of window with input focus, amount of\n\t   space in global heap, whether system queue has any events, cursor\n\t   position for last message, 55 ms time for last message, number of\n\t   active tasks, 55 ms time since Windows started, current mouse cursor\n\t   position, current caret position */\n\taddRandomValue( randomState, GetCapture() );\n\taddRandomValue( randomState, GetFocus() );\n\taddRandomValue( randomState, GetFreeSpace( 0 ) );\n\taddRandomValue( randomState, GetInputState() );\n\taddRandomValue( randomState, GetMessagePos() );\n\taddRandomValue( randomState, GetMessageTime() );\n\taddRandomValue( randomState, GetNumTasks() );\n\taddRandomValue( randomState, GetTickCount() );\n\tGetCursorPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\tGetCaretPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\n\t/* Get the largest free memory block, number of lockable pages, number of\n\t   unlocked pages, number of free and used pages, and number of swapped\n\t   pages */\n\tmemManInfo.dwSize = sizeof( MEMMANINFO );\n\tMemManInfo( &memManInfo );\n\taddRandomData( randomState, &memManInfo, sizeof( MEMMANINFO ) );\n\n\t/* Get the execution times of the current task and VM to approximately\n\t   1ms resolution */\n\ttimerInfo.dwSize = sizeof( TIMERINFO );\n\tTimerCount( &timerInfo );\n\taddRandomData( randomState, &timerInfo, sizeof( TIMERINFO ) );\n\n\t/* Get the percentage free and segment of the user and GDI heap */\n\tsysHeapInfo.dwSize = sizeof( SYSHEAPINFO );\n\tSystemHeapInfo( &sysHeapInfo );\n\taddRandomData( randomState, &sysHeapInfo, sizeof( SYSHEAPINFO ) );\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 25 );\n\t}\n\n/* The slow poll can get *very* slow because of the overhead involved in\n   obtaining the necessary information.  On a moderately loaded system there\n   are often 500+ objects on the global heap and 50+ modules, so we limit\n   the number checked to a reasonable level to make sure we don't spend\n   forever polling.  We give the global heap walk the most leeway since this\n   provides the best source of randomness */\n\nvoid slowPoll( void )\n\t{\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tMODULEENTRY moduleEntry;\n\tGLOBALENTRY globalEntry;\n\tTASKENTRY taskEntry;\n\tint count;\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Walk the global heap getting information on each entry in it.  This\n\t   retrieves the objects linear address, size, handle, lock count, owner,\n\t   object type, and segment type */\n\tcount = 0;\n\tglobalEntry.dwSize = sizeof( GLOBALENTRY );\n\tif( GlobalFirst( &globalEntry, GLOBAL_ALL ) )\n\t\tdo\n\t\t\t{\n\t\t\taddRandomData( randomState, &globalEntry, sizeof( GLOBALENTRY ) );\n\t\t\tcount++;\n\t\t\t}\n\t\twhile( count < 70 && GlobalNext( &globalEntry, GLOBAL_ALL ) );\n\n\t/* Walk the module list getting information on each entry in it.  This\n\t   retrieves the module name, handle, reference count, executable path,\n\t   and next module */\n\tcount = 0;\n\tmoduleEntry.dwSize = sizeof( MODULEENTRY );\n\tif( ModuleFirst( &moduleEntry ) )\n\t\tdo\n\t\t\t{\n\t\t\taddRandomData( randomState, &moduleEntry, sizeof( MODULEENTRY ) );\n\t\t\tcount++;\n\t\t\t}\n\t\twhile( count < 20 && ModuleNext( &moduleEntry ) );\n\n\t/* Walk the task list getting information on each entry in it.  This\n\t   retrieves the task handle, parent task handle, instance handle, stack\n\t   segment and offset, stack size, number of pending events, task queue,\n\t   and the name of module executing the task.  We also call TaskGetCSIP()\n\t   for the code segment and offset of each task if it's safe to do so\n\t   (note that this call can cause odd things to happen in debuggers and\n\t   runtime code checkers because of the way TaskGetCSIP() is implemented) */\n\tcount = 0;\n\ttaskEntry.dwSize = sizeof( TASKENTRY );\n\tif( TaskFirst( &taskEntry ) )\n\t\tdo\n\t\t\t{\n\t\t\taddRandomData( randomState, &taskEntry, sizeof( TASKENTRY ) );\n\t\t\tif( taskEntry.hTask != GetCurrentTask() )\n\t\t\t\taddRandomValue( randomState,\n\t\t\t\t\t\t\t\tTaskGetCSIP( taskEntry.hTask ) );\n\t\t\tcount++;\n\t\t\t}\n\t\twhile( count < 100 && TaskNext( &taskEntry ) );\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 100 );\n\t}\n"
  },
  {
    "path": "deps/cl345/random/win32.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  Win32 Randomness-Gathering Code\t\t\t\t\t*\n*\tCopyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2017\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom number\n   generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include <stdio.h>\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <lm.h>\t\t\t\t/* For NetStatisticsGet() */\n#include <winperf.h>\n#include <winioctl.h>\n#include <process.h>\n\n/* MinGW doesn't support inline asm (via gas) in its standard install\n   so we turn it off just for this file */\n\n#ifdef __MINGW32__\n  #define NO_ASM\n#endif /* __MINGW32__ */\n\n/* Some new CPU opcodes aren't supported by all compiler versions, if\n   they're not available we define them here.  BC++ can only handle the\n   emit directive outside an asm block, so we have to terminate the current\n   block, emit the opcode, and then restart the asm block.  In addition\n   while the 16-bit versions of BC++ had built-in asm support, the 32-bit\n   versions removed it and generate a temporary asm file which is passed\n   to Tasm32.  This is only included with some high-end versions of BC++\n   and it's not possible to order it separately, so if you're building with\n   BC++ and get error messages about a missing tasm32.exe, add NO_ASM to\n   Project Options | Compiler | Defines */\n\n#if defined( _MSC_VER )\n  #if _MSC_VER <= 1100\n\t#define cpuid\t\t__asm _emit 0x0F __asm _emit 0xA2\n\t#define rdtsc\t\t__asm _emit 0x0F __asm _emit 0x31\n  #endif /* VC++ 5.0 or earlier */\n  #define xstore_rng\t__asm _emit 0x0F __asm _emit 0xA7 __asm _emit 0xC0\n  #define rdrand_eax\t__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0\n  #define rdseed_eax\t__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF8\n#endif /* VC++ */\n#if defined __BORLANDC__\n  #define cpuid\t\t\t} __emit__( 0x0F, 0xA2 ); __asm {\n  #define rdtsc\t\t\t} __emit__( 0x0F, 0x31 ); __asm {\n  #define xstore_rng\t} __emit__( 0x0F, 0xA7, 0xC0 ); __asm {\n  #define rdrand_eax\t} __emit__( 0x0F, 0xC7, 0xF0 ); __asm {\n  #define rdseed_eax\t} __emit__( 0x0F, 0xC7, 0xF8 ); __asm {\n#endif /* BC++ */\n\n/* Map a value that may be 32 or 64 bits depending on the platform to a \n   long.  For 64-bit debug builds we can't use HandleToLong() because it\n   results in a runtime exception due to loss of precision so we mask it to \n   LONG_MAX and then cast it */\n\n#ifdef __WIN64__\n  #ifndef NDEBUG\n\t#define addRandomHandle( randomState, handle ) \\\n\t\t\taddRandomLong( randomState, \\\n\t\t\t\t\t\t   ( long ) ( ( LONG_PTR ) ( handle ) & LONG_MAX ) )\n  #else\n\t#define addRandomHandle( randomState, handle ) \\\n\t\t\taddRandomLong( randomState, HandleToLong( handle ) )\n  #endif /* Debug vs.non-debug */\n#else\n  #define addRandomHandle\taddRandomValue\n#endif /* 32- vs. 64-bit VC++ */\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n#if RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT\n  #error RANDOM_BUFSIZE exceeds randomness accumulator size\n#endif /* RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT */\n\n/* Handles to various randomness objects */\n\nstatic HANDLE hAdvAPI32;\t/* Handle to misc.library */\nstatic HANDLE hNTAPI;\t\t/* Handle to Windows kernel library */\nstatic HANDLE hThread;\t\t/* Background polling thread handle */\nstatic unsigned int threadID;\t/* Background polling thread ID */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSystem RNG Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The number of bytes to read from the system RNG on each slow poll */\n\n#define SYSTEMRNG_BYTES\t\t64\n\n/* Intel Chipset CSP type and name */\n\n#define PROV_INTEL_SEC\t22\n#define INTEL_DEF_PROV\t\"Intel Hardware Cryptographic Service Provider\"\n\n/* A mapping from CryptoAPI to standard data types */\n\n#define HCRYPTPROV\t\t\tHANDLE\n\n/* Type definitions for function pointers to call CryptoAPI functions */\n\ntypedef BOOL ( WINAPI *CRYPTACQUIRECONTEXT )( HCRYPTPROV *phProv,\n\t\t\t\t\t\t\t\t\t\t\t  LPCTSTR pszContainer,\n\t\t\t\t\t\t\t\t\t\t\t  LPCTSTR pszProvider, DWORD dwProvType,\n\t\t\t\t\t\t\t\t\t\t\t  DWORD dwFlags );\ntypedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen,\n\t\t\t\t\t\t\t\t\t\t BYTE *pbBuffer );\ntypedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );\n\n/* Somewhat alternative functionality available as a direct call, for \n   Windows XP and newer.  This is the CryptoAPI RNG, which isn't anywhere\n   near as good as the HW RNG, but we use it if it's present on the basis\n   that at least it can't make things any worse.  This direct access version \n   is only available under Windows XP and newer, we don't go out of our way \n   to access the more general CryptoAPI one since the main purpose of using \n   it is to take advantage of any possible future hardware RNGs that may be \n   added, for example via TCPA devices */\n\ntypedef BOOL ( WINAPI *RTLGENRANDOM )( PVOID RandomBuffer, \n\t\t\t\t\t\t\t\t\t   ULONG RandomBufferLength );\n\n/* Global function pointers. These are necessary because the functions need\n   to be dynamically linked since older versions of Windows NT don't contain \n   them */\n\nstatic CRYPTACQUIRECONTEXT pCryptAcquireContext = NULL;\nstatic CRYPTGENRANDOM pCryptGenRandom = NULL;\nstatic CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;\nstatic RTLGENRANDOM pRtlGenRandom = NULL;\n\n/* Handle to the RNG CSP */\n\nstatic BOOLEAN systemRngAvailable;\t/* Whether system RNG is available */\nstatic HCRYPTPROV hProv;\t\t\t/* Handle to Intel RNG CSP */\n\n/* Try and connect to the system RNG if there's one present.  In theory we \n   could also try and get data from a TPM if there's one present via the TPM\n   base services (TBS), but the TPM functions are only available under Vista \n   and newer (so they'd have to be dynamically bound), the chances of a TPM \n   being present, enabled, and accessible are pretty slim, and since the TBS\n   require use to to talk to the TPM at the raw APDU level (not to mention \n   all the horror stories in the MSDN forums about getting any of this stuff \n   to work) the amount of effort required versus the potential gain really \n   doesn't make it worthwhile (one talk on TPM programming calls it \"a \n   horrifically bad programming experience\"):\n\n\t#include <tbs.h>\n\n\tTBS_HCONTEXT hTbsContext;\n\tTBS_CONTEXT_PARAMS tbsContextParams;\n\tHRESULT hResult;\n\n\t// Include dynamic-linking management for all functions\n\n\t// Get a handle to the TBS interface\n\tmemset( &tspContextParams, 0, sizeof( TBS_CONTEXT_PARAMS ) );\n\ttspContextParams.version = TBS_CONTEXT_VERSION_ONE;\n\tresult = Tbsi_Context_Create( &tbsContextParams, &hTbsContext );\n\tif( SUCCEEDED( hResult ) )\n\t\t{\n\t\tBYTE tpmCommand[] = {\n\t\t\t0x00, 0xC1,\t\t\t\t\t// WORD: TPM_TAG_RQU_COMMAND\n\t\t\t0x00, 0x00, 0x00, 0x0E,\t\t// LONG: Total packet length\n\t\t\t0x00, 0x00, 0x00, 0x46,\t\t// LONG: Command TPM_ORD_GetRandom\n\t\t\t0x00, 0x00, 0x00, 0x20\t\t// Data: Get 0x20 bytes\n\t\tBYTE buffer[ 14 + 32 + 8 ];\n\t\tint length;\n\n\t\thResult = Tbsip_Submit_Command( hTbsContext, \n\t\t\t\t\t\t\t\t\t\tTBS_COMMAND_LOCALITY_ZERO,\n\t\t\t\t\t\t\t\t\t\tTBS_COMMAND_PRIORITY_NORMAL, \n\t\t\t\t\t\t\t\t\t\ttpmCommand, 14, buffer, &length );\n\t\tif( SUCCEEDED( hResult ) )\n\t\t\t{\n\t\t\t// Start of buffer contains the 14 bytes of returned command \n\t\t\t// followed by 32 bytes of random data\n\t\t\t}\n\t\tTbsip_Context_Close( hTbsContext );\n\t\t} \n\n   There is a higher-level API, the TSPI, but that's only available as a \n   semi-experimental implementation provided as a custom download, on the\n   off chance that someone is using this we optionally provide it under the\n   USE_TPM define */\n\nstatic void initSystemRNG( void )\n\t{\n\tsystemRngAvailable = FALSE;\n\thProv = NULL;\n\tif( ( hAdvAPI32 = GetModuleHandle( \"AdvAPI32.dll\" ) ) == NULL )\n\t\treturn;\n\n\t/* Get pointers to the CSP functions.  Although the acquire context\n\t   function looks like a standard function, it's actually a macro which\n\t   is mapped to (depending on the build type) CryptAcquireContextA or\n\t   CryptAcquireContextW, so we access it under the straight-ASCII-\n\t   function name */\n\tpCryptAcquireContext = ( CRYPTACQUIRECONTEXT ) GetProcAddress( hAdvAPI32,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"CryptAcquireContextA\" );\n\tpCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"CryptGenRandom\" );\n\tpCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"CryptReleaseContext\" );\n\n\t/* Get a pointer to the native randomness function if it's available.  \n\t   This isn't exported by name, so we have to get it by ordinal */\n\tpRtlGenRandom = ( RTLGENRANDOM ) GetProcAddress( hAdvAPI32,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"SystemFunction036\" );\n\n\t/* Try and connect to the PIII RNG CSP.  The AMD 768 southbridge (from \n\t   the 760 MP chipset) also has a hardware RNG, but there doesn't appear \n\t   to be any driver support for this as there is for the Intel RNG so we \n\t   can't do much with it.  OTOH the Intel RNG is also effectively dead, \n\t   mostly due to virtually nonexistant support/marketing by Intel, it's \n\t   included here mostly for form's sake */\n\tif( ( pCryptAcquireContext == NULL || \\\n\t\t  pCryptGenRandom == NULL || pCryptReleaseContext == NULL || \\\n\t\t  pCryptAcquireContext( &hProv, NULL, INTEL_DEF_PROV,\n\t\t\t\t\t\t\t\tPROV_INTEL_SEC, 0 ) == FALSE ) && \\\n\t\t( pRtlGenRandom == NULL ) )\n\t\t{\n\t\thAdvAPI32 = NULL;\n\t\thProv = NULL;\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember that we have a system RNG available for use */\n\t\tsystemRngAvailable = TRUE;\n\t\t}\n\t}\n\n/* Read data from the system RNG, in theory the PIII hardware RNG but in\n   practice the CryptoAPI software RNG */\n\nstatic void readSystemRNG( void )\n\t{\n\tBYTE buffer[ SYSTEMRNG_BYTES + 8 ];\n\tint quality = 0;\n\n\tif( !systemRngAvailable )\n\t\treturn;\n\n\t/* Read SYSTEMRNG_BYTES bytes from the system RNG.  Rather presciently, \n\t   the code up until late 2007 stated that \"We don't rely on this for \n\t   all our randomness requirements (particularly the software RNG) in \n\t   case it's broken in some way\", and in November 2007 an analysis paper\n\t   by Leo Dorrendorf, Zvi Gutterman, and Benny Pinkas showed that the\n\t   CryptoAPI RNG is indeed broken, being neither forwards- nor \n\t   backwards-secure, being reseeded far too infrequently, and (as far as\n\t   their reverse-engineering was able to tell) using far less entropy\n\t   sources than cryptlib's built-in mechanisms even though the CryptoAPI\n\t   one is deeply embedded in the OS.\n\n\t   The way the CryptoAPI RNG works is that a system RNG is used to key \n\t   a set of eight RC4 ciphers, each of which is used in turn in a round-\n\t   robin fashion to output 20 bytes of randomness which are then hashed \n\t   with SHA1, with the operation being approximately:\n\n\t\toutput[  0...19 ] = SHA1( RC4[ i++ % 8 ] );\n\t\toutput[ 20...39 ] = SHA1( RC4[ i++ % 8 ] );\n\t\t[...]\n\n\t   Each RC4 cipher is re-keyed every 16KB of output, so for 8 ciphers\n\t   the rekey interval is every 128KB of output.  Furthermore, although\n\t   the kernel RNG used to key the RC4 ciphers stores its state in-\n\t   kernel, the RC4 cipher state is stored in user-space and per-process.\n\t   This means that in most cases the RNG is never re-keyed.  Finally,\n\t   the way the RNG works means that it's possible to recover earlier\n\t   state in O( 2^23 ).  See \"Cryptanalysis of the Random Number \n\t   Generator of the Windows Operating System\" for details */\n\tif( hProv != NULL )\n\t\t{\n\t\tif( pCryptGenRandom( hProv, SYSTEMRNG_BYTES, buffer ) )\n\t\t\tquality = 70;\n\t\t}\n\telse\n\t\t{\n\t\tif( pRtlGenRandom( buffer, SYSTEMRNG_BYTES ) )\n\t\t\tquality = 60;\n\t\t}\n\tif( quality > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, buffer, SYSTEMRNG_BYTES );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tzeroise( buffer, SYSTEMRNG_BYTES );\n\t\t}\n\t}\n\n/* Clean up the system RNG access */\n\nstatic void endSystemRNG( void )\n\t{\n\tif( hProv != NULL )\n\t\t{\n\t\tpCryptReleaseContext( hProv, 0 );\n\t\thProv = NULL;\n\t\t}\n\t}\n\n#ifdef USE_TPM\n\nstatic void readTPMRNG( void )\n\t{\n\tTSS_HCONTEXT hTSPIContext;\n\tTSS_HTPM hTPM;\n\tBYTE *bufPtr;\n\n\t/* Create a TSPI context, connect it to the system TPM, and get the TPM\n\t   handle from it */\n\tif( Tspi_Context_Create( &hTSPIContext ) != TSS_SUCCESS )\n\t\treturn;\n    if( Tspi_Context_Connect( hTSPIContext, NULL ) != TSS_SUCCESS || \\\n\t\tTspi_Context_GetTpmObject( hTSPIContext, &hTPM ) != TSS_SUCCESS )\n\t\t{\n\t\tTspi_Context_Close( hTSPIContext );\n        return;\n\t\t}\n\n\t/* Get random data from the TPM */ \n\tif( Tspi_TPM_GetRandom( hTPM, SYSTEMRNG_BYTES, &bufPtr ) == TSS_SUCCESS )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tstatic const int quality = 70;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, bufPtr, SYSTEMRNG_BYTES );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tzeroise( bufPtr, SYSTEMRNG_BYTES );\n\t\tTspi_Context_FreeMemory( hTSPIContext, bufPtr );\n\t\t}\n\n\t/* Clean up */\n\tTspi_Context_Close( hTPM );\n\tTspi_Context_Free_Memory( hTSPIContext, NULL );\n\tTspi_Context_Close( hTSPIContext );\n\t}\n#else\n  #define readTPMRNG()\n#endif /* USE_TPM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tExternal RNG Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Interface to the Quantis quantum RNG */\n\ntypedef void *QUANTIS_HANDLE;\n\n/* Type definitions for function pointers to call Quantis functions */\n\ntypedef int ( *QUANTISOPEN )( int deviceType, unsigned int deviceNumber,\n\t\t\t\t\t\t\t  QUANTIS_HANDLE* deviceHandle );\ntypedef int ( *QUANTISREADHANDLE )( QUANTIS_HANDLE deviceHandle, \n\t\t\t\t\t\t\t\t\tvoid *buffer, size_t size );\ntypedef int ( *QUANTISCLOSE )( QUANTIS_HANDLE deviceHandle );\n\n/* Global function pointers. These are necessary because the functions need\n   to be dynamically linked since most systems won't contain them */\n\nstatic QUANTISOPEN pQuantisOpen = NULL;\nstatic QUANTISREADHANDLE pQuantisReadHandled = NULL;\nstatic QUANTISCLOSE pQuantisClose = NULL;\n\n#if 0\n\ntypedef struct {\n\tint deviceNumber;\n\tint deviceType;\n\t/* QuantisOperations* */ void *ops;\n\tvoid *privateData;\n\t} QUANTIS_HANDLE;\n#endif\n\n/* Quantis device types */\n\n#define QUANTIS_DEVICE_PCI\t\t\t1\t/* PCI device */\n#define QUANTIS_DEVICE_USB\t\t\t2\t/* USB device */\n\n/* Quantis error codes */\n\n#define QUANTIS_SUCCESS\t\t\t\t0\n#define QUANTIS_ERROR_NO_DRIVER\t\t1\t/* Invalid driver */\n#define QUANTIS_ERROR_INVALID_DEVICE_NUMBER\t2 /* Invalid device no.*/\n#define QUANTIS_ERROR_INVALID_READ_SIZE\t3 /* Invalid size to read (too high) */\n#define QUANTIS_ERROR_INVALID_PARAMETER\t4 /* Invalid parameter */\n#define QUANTIS_ERROR_NO_MEMORY\t\t5\t/* Insufficient memory */\n#define QUANTIS_ERROR_NO_MODULE\t\t6\t/* No module found */\n#define QUANTIS_ERROR_IO\t\t\t7\t/* Input/output error */\n#define QUANTIS_ERROR_NO_DEVICE\t\t8\t/* No such device or dev.disconnected */\n#define QUANTIS_ERROR_OPERATION_NOT_SUPPORTED 9 /* Op.not supported */\n#define QUANTIS_ERROR_OTHER\t\t\t99\t/* Other error */\n\n/* Handle to the Quantis RNG */\n\nstatic BOOLEAN externalRngAvailable;\t/* Whether external RNG is available */\nstatic HANDLE hQuantis;\t\t\t\t\t/* Handle to Quantis library */\nstatic QUANTIS_HANDLE quantisDevice;\t/* Handle to Quantis device */\n\nstatic void initExternalRNG( void )\n\t{\n\tint status;\n\n\texternalRngAvailable = FALSE;\n\tquantisDevice = NULL;\n\n\t/* Load the Quantis library.  This is a real pain to do because we have \n\t   no idea where the Quantis DLL will be, the Quantis manual puts it in \n\t   \"<path-to-quantis>\\Packages\\Windows\\lib\\<your system arch>\\\", and\n\t   as if that isn't vague enough, in \n\t   \"<path-to-filename>\\Libs-Apps\\Quantis\\<your system arch>\" if you \n\t   build the library yourself.  Because of this we wouldn't be able to\n\t   hardcode in an absolute path for SafeLoadLibrary(), but in practice\n\t   we require that it be stored in the Windows directory to avoid \n\t   having to break the security module for safe loads */\n\tif( ( hQuantis = SafeLoadLibrary( \"Quantis.dll\" ) ) == NULL )\n\t\t{\n\t\t/* If we're building the debug build we also allow the use of the\n\t\t   emulated RNG library */\n#if ( _MSC_VER == 1200 ) && !defined( NDEBUG )\n\t\tif( ( hQuantis = LoadLibrary( \"Quantis-NoHw.dll\" ) ) != NULL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Using software emulation of Quantis hardware \"\n\t\t\t\t\t\t \"RNG\" ));\n\t\t\t}\n\t\telse\n#endif /* VC++ 6.0 && !NDEBUG */\n\t\treturn;\n\t\t}\n\n\t/* Get pointers to the Quantis API functions */\n\tpQuantisOpen = ( QUANTISOPEN ) GetProcAddress( hQuantis, \"QuantisOpen\" );\n\tpQuantisReadHandled = ( QUANTISREADHANDLE ) GetProcAddress( hQuantis,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"QuantisReadHandled\" );\n\tpQuantisClose = ( QUANTISCLOSE ) GetProcAddress( hQuantis, \"QuantisClose\" );\n\tif( pQuantisOpen == NULL || pQuantisReadHandled == NULL || \\\n\t\tpQuantisClose == NULL )\n\t\t{\n\t\tFreeLibrary( hQuantis );\n\t\thQuantis = NULL;\n\t\treturn;\n\t\t}\n\n\t/* Try and connect to the Quantis device */\n\tstatus = pQuantisOpen ( QUANTIS_DEVICE_PCI, 0, &quantisDevice );\n\tif( status != QUANTIS_SUCCESS )\n\t\tstatus = pQuantisOpen ( QUANTIS_DEVICE_USB, 0, &quantisDevice );\n\tif( status != QUANTIS_SUCCESS )\n\t\t{\n\t\tFreeLibrary( hQuantis );\n\t\thQuantis = NULL;\n\t\tDEBUG_DIAG_ERRMSG(( \"Quantis hardware RNG device couldn't be \"\n\t\t\t\t\t\t\t\"accessed, status %s\", \n\t\t\t\t\t\t\tgetStatusName( status ) ));\n\t\treturn;\n\t\t}\n\n\texternalRngAvailable = TRUE;\n\t}\n\n/* Read data from the external RNG */\n\nstatic void readExternalRNG( void )\n\t{\n\tBYTE buffer[ SYSTEMRNG_BYTES + 8 ];\n\tint count, quality = 0;\n\n\tif( !externalRngAvailable )\n\t\treturn;\n\n\t/* Read SYSTEMRNG_BYTES bytes from the external RNG.  Note that the docs\n\t   are incorrect for this function since they claim that a successful\n\t   read products QUANTIS_SUCCES (sic), it's actually a byte count */\n\tcount = pQuantisReadHandled( quantisDevice, buffer, SYSTEMRNG_BYTES );\n\tif( count >= SYSTEMRNG_BYTES )\n\t\tquality = 70;\n\tif( quality > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, buffer, count );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tzeroise( buffer, SYSTEMRNG_BYTES );\n\t\t}\n\t}\n\n/* Clean up the external RNG access */\n\nstatic void endExternalRNG( void )\n\t{\n\tif( hQuantis != NULL )\n\t\t{\n\t\tFreeLibrary( hQuantis );\n\t\thQuantis = NULL;\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHardware Monitoring Interface\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* These interfaces currently support data supplied by MBM, Everest, \n   SysTool, RivaTuner, HMonitor, ATI Tray Tools, CoreTemp, and GPU-Z.  Two \n   notable omissions are SVPro and HWMonitor, unfortunately the authors \n   haven't responded to any requests for interfacing information */\n\n/* MBM data structures, originally by Alexander van Kaam, converted to C by\n   Anders@Majland.org, finally updated by Chris Zahrt <techn0@iastate.edu>.\n   The __int64 values below are actually (64-bit) doubles, but we overlay \n   them with __int64s since we don't care about the values */\n\n#define BusType\t\tchar\n#define SMBType\t\tchar\n#define SensorType\tchar\n\ntypedef struct {\n\tSensorType iType;\t\t\t/* Type of sensor */\n\tint Count;\t\t\t\t\t/* Number of sensor for that type */\n\t} SharedIndex;\n\ntypedef struct {\n\tSensorType ssType;\t\t\t/* Type of sensor */\n\tunsigned char ssName[ 12 ];\t/* Name of sensor */\n\tchar sspadding1[ 3 ];\t\t/* Padding of 3 bytes */\n\t__int64 /*double*/ ssCurrent;/* Current value */\n\t__int64 /*double*/ ssLow;\t/* Lowest readout */\n\t__int64 /*double*/ ssHigh;\t/* Highest readout */\n\tlong ssCount;\t\t\t\t/* Total number of readout */\n\tchar sspadding2[ 4 ];\t\t/* Padding of 4 bytes */\n\tBYTE /*long double*/ ssTotal[ 8 ];\t/* Total amout of all readouts */\n\tchar sspadding3[ 6 ];\t\t/* Padding of 6 bytes */\n\t__int64 /*double*/ ssAlarm1;/* Temp & fan: high alarm; voltage: % off */\n\t__int64 /*double*/ ssAlarm2;/* Temp: low alarm */\n\t} SharedSensor;\n\ntypedef struct {\n\tshort siSMB_Base;\t\t\t/* SMBus base address */\n\tBusType siSMB_Type;\t\t\t/* SMBus/Isa bus used to access chip */\n\tSMBType siSMB_Code;\t\t\t/* SMBus sub type, Intel, AMD or ALi */\n\tchar siSMB_Addr;\t\t\t/* Address of sensor chip on SMBus */\n\tunsigned char siSMB_Name[ 41 ];\t/* Nice name for SMBus */\n\tshort siISA_Base;\t\t\t/* ISA base address of sensor chip on ISA */\n\tint siChipType;\t\t\t\t/* Chip nr, connects with Chipinfo.ini */\n\tchar siVoltageSubType;\t\t/* Subvoltage option selected */\n\t} SharedInfo;\n\ntypedef struct {\n\t__int64 /*double*/ sdVersion;/* Version number (example: 51090) */\n\tSharedIndex sdIndex[ 10 ];\t/* Sensor index */\n\tSharedSensor sdSensor[ 100 ];\t/* Sensor info */\n\tSharedInfo sdInfo;\t\t\t/* Misc.info */\n\tunsigned char sdStart[ 41 ];\t/* Start time */\n\t/* We don't use the next two fields both because they're not random and\n\t   because it provides a nice safety margin in case of data size mis-\n\t   estimates (we always under-estimate the buffer size) */\n/*\tunsigned char sdCurrent[ 41 ];\t/* Current time */\n/*\tunsigned char sdPath[ 256 ];\t/* MBM path */\n\t} SharedData;\n\n/* Read data from MBM via the shared-memory interface */\n\nstatic void readMBMData( void )\n\t{\n\tHANDLE hMBMData;\n\tconst SharedData *mbmDataPtr;\n\n\tif( ( hMBMData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t  \"$M$B$M$5$S$D$\" ) ) == NULL )\n\t\treturn;\n\tif( ( mbmDataPtr = ( SharedData * ) \\\n\t\t\tMapViewOfFile( hMBMData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tstatic const int quality = 20;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) mbmDataPtr, \n\t\t\t\t\t\tsizeof( SharedData ) );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tUnmapViewOfFile( mbmDataPtr );\n\t\t}\n\tCloseHandle( hMBMData );\n\t}\n\n/* Read data from Everest via the shared-memory interface.  Everest returns \n   information as an enormous XML text string so we have to be careful about \n   handling of lengths.  In general the returned length is 1-3K, so we \n   hard-limit it at 2K to ensure there are no problems if the trailing null \n   gets lost */\n\nstatic void readEverestData( void )\n\t{\n\tHANDLE hEverestData;\n\tconst void *everestDataPtr;\n\n\tif( ( hEverestData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t  \"EVEREST_SensorValues\" ) ) == NULL )\n\t\treturn;\n\tif( ( everestDataPtr = MapViewOfFile( hEverestData, \n\t\t\t\t\t\t\t\t\t\t  FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tconst int length = strlen( everestDataPtr );\n\n\t\tif( length > 128 )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tstatic const int quality = 40;\n\t\t\tint status;\n\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) everestDataPtr, \n\t\t\t\t\t\t\tmin( length, 2048 ) );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t}\n\t\t\t}\n\t\tUnmapViewOfFile( everestDataPtr );\n\t\t}\n\tCloseHandle( hEverestData );\n\t}\n\n/* SysTool data structures, from forums.techpowerup.com.  This uses the\n   standard shared memory interface, but it gets a bit tricky because it \n   uses the OLE 'VARIANT' data type which we can't access because it's \n   included via a complex nested inclusion framework in windows.h, and the \n   use of '#pragma once' when we included it for use in crypt.h means that \n   we can't re-include any of the necessary files.  Since we don't actually \n   care what's inside a VARIANT, and it has a fixed size of 16 bytes, we \n   just use it as an opaque blob */\n\ntypedef BYTE VARIANT[ 16 ];\t/* Kludge for OLE data type */\ntypedef BYTE UINT8;\ntypedef WORD UINT16;\n\n#define SH_MEM_MAX_SENSORS 128\n\ntypedef enum { sUnknown, sNumber, sTemperature, sVoltage, sRPM, sBytes, \n\t\t\t   sBytesPerSecond, sMhz, sPercentage, sString, sPWM \n\t\t\t } SYSTOOL_SENSOR_TYPE;\n \ntypedef struct {\n\tWCHAR m_name[ 255 ];\t/* Sensor name */\n\tWCHAR m_section[ 64 ];\t/* Section in which this sensor appears */\n\tSYSTOOL_SENSOR_TYPE m_sensorType;\n\tLONG m_updateInProgress;/* Nonzero when sensor is being updated */\n\tUINT32 m_timestamp;\t\t/* GetTickCount() of last update */\n\tVARIANT m_value;\t\t/* Sensor data */\n\tWCHAR m_unit[ 8 ];\t\t/* Unit for text output */\n\tUINT8 m_nDecimals;\t\t/* Default number of decimals for formatted output */\n\t} SYSTOOL_SHMEM_SENSOR;\n \ntypedef struct {\n\tUINT32 m_version;\t\t/* Version of shared memory structure */\n\tUINT16 m_nSensors;\t\t/* Number of records with data in m_sensors */\n\tSYSTOOL_SHMEM_SENSOR m_sensors[ SH_MEM_MAX_SENSORS ];\n\t} SYSTOOL_SHMEM;\n\nstatic void readSysToolData( void )\n\t{\n\tHANDLE hSysToolData;\n\tconst SYSTOOL_SHMEM *sysToolDataPtr;\n\n\tif( ( hSysToolData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t  \"SysToolSensors\" ) ) == NULL )\n\t\treturn;\n\tif( ( sysToolDataPtr = ( SYSTOOL_SHMEM * ) \\\n\t\t\tMapViewOfFile( hSysToolData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tstatic const int quality = 40;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) sysToolDataPtr, \n\t\t\t\t\t\tsizeof( SYSTOOL_SHMEM ) );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tUnmapViewOfFile( sysToolDataPtr );\n\t\t}\n\tCloseHandle( hSysToolData );\n\t}\n\n/* RivaTuner data structures via the shared-memory interface, from the \n   RivaTuner sample source.  The DWORD values below are actually (32-bit) \n   floats, but we overlay them with DWORDs since we don't care about the \n   values.  The information is only accessible when the RivaTuner hardware \n   monitoring window is open.  This one is the easiest of the shared-mem \n   interfaces to monitor because for fowards-compatibility reasons it \n   stores a Windows-style indicator of the size of each struct entry in the \n   data header, so we can get the total size simply by multiplying out the \n   number of entries by the indicated size.  As a safety measure we limit \n   the maximum data size to 2K in case a value gets corrupted */\n\ntypedef struct {\n\tDWORD dwSignature;\t/* 'RTHM' if active */\n\tDWORD dwVersion;\t/* Must be 0x10001 or above */\n\tDWORD dwNumEntries;\t/* No.of RTHM_SHARED_MEMORY_ENTRY entries */\n\ttime_t time;\t\t/* Last polling time */\n\tDWORD dwEntrySize;\t/* Size of entries in RTHM_SHARED_MEMORY_ENTRY array */\n\t} RTHM_SHARED_MEMORY_HEADER;\n\ntypedef struct {\n\tchar czSrc[ 32 ];\t/* Source description */\n\tchar czDim[ 16 ];\t/* Source measurement units */\n\tDWORD /*float*/ data;\t/* Source data */\n\tDWORD /*float*/ offset;\t/* Source offset, e.g. temp.compensation */\n\tDWORD /*float*/ dataTransformed;/* Source data in transformed(?) form */\n\tDWORD flags;\t\t/* Misc.flags */\n\t} RTHM_SHARED_MEMORY_ENTRY;\n\nstatic void readRivaTunerData( void )\n\t{\n\tHANDLE hRivaTunerData;\n\tRTHM_SHARED_MEMORY_HEADER *rivaTunerHeaderPtr;\n\n\tif( ( hRivaTunerData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t\t\"RTHMSharedMemory\" ) ) == NULL )\n\t\treturn;\n\tif( ( rivaTunerHeaderPtr = ( RTHM_SHARED_MEMORY_HEADER * ) \\\n\t\t\tMapViewOfFile( hRivaTunerData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tif( rivaTunerHeaderPtr->dwSignature == 'RTHM' && \\\n\t\t\trivaTunerHeaderPtr->dwVersion >= 0x10001 )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tconst BYTE *entryPtr = ( ( BYTE * ) rivaTunerHeaderPtr ) + \\\n\t\t\t\t\t\t\t\t   sizeof( RTHM_SHARED_MEMORY_HEADER );\n\t\t\tconst int entryTotalSize = rivaTunerHeaderPtr->dwNumEntries * \\\n\t\t\t\t\t\t\t\t\t   rivaTunerHeaderPtr->dwEntrySize;\n\t\t\tstatic const int quality = 10;\n\t\t\tint status;\n\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) entryPtr, \n\t\t\t\t\t\t\tmin( entryTotalSize, 2048 ) );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t}\n\t\t\t}\n\t\tUnmapViewOfFile( rivaTunerHeaderPtr );\n\t\t}\n\tCloseHandle( hRivaTunerData );\n\t}\n\n/* Read data from HMonitor via the shared-memory interface.  The DWORD \n   values below are actually (32-bit) floats, but we overlay them with \n   DWORDs since we don't care about the values.  Like RivaTuner's data the \n   info structure contains a length value at the start, so it's fairly easy \n   to work with */\n\ntypedef struct {\n\tWORD length;\n\tWORD version;\t/* Single 'DWORD length' before version 4.1 */\n\tDWORD /*float*/ temp[ 3 ];\n\tDWORD /*float*/ voltage[ 7 ];\n\tint fan[ 3 ];\n\t} HMONITOR_DATA;\n\nstatic void readHMonitorData( void )\n\t{\n\tHANDLE hHMonitorData;\n\tHMONITOR_DATA *hMonitorDataPtr;\n\n\tif( ( hHMonitorData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t   \"Hmonitor_Counters_Block\" ) ) == NULL )\n\t\treturn;\n\tif( ( hMonitorDataPtr = ( HMONITOR_DATA * ) \\\n\t\t\tMapViewOfFile( hHMonitorData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tif( hMonitorDataPtr->version >= 0x4100 && \\\n\t\t\t( hMonitorDataPtr->length >= 48 && hMonitorDataPtr->length <= 1024 ) )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tstatic const int quality = 40;\n\t\t\tint status;\n\n\t\t\tsetMessageData( &msgData, hMonitorDataPtr, hMonitorDataPtr->length );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t}\n\t\t\t}\n\t\tUnmapViewOfFile( hMonitorDataPtr );\n\t\t}\n\tCloseHandle( hHMonitorData );\n\t}\n\n/* Read data from ATI Tray Tools via the shared-memory interface.  This has\n   an added twist in that just because it's available to be read doesn't \n   mean that it contains any data, so we check that at least the GPU speed \n   and temp-monitoring-supported flag have nonzero values */\n\ntypedef struct {\n\tDWORD CurGPU;\t\t/* GPU speed */\n\tDWORD CurMEM;\t\t/* Video memory speed */\n\tDWORD isGameActive;\n\tDWORD is3DActive;\t/* Boolean: 3D mode active */\n\tDWORD isTempMonSupported;\t/* Boolean: Temp monitoring available */\n\tDWORD GPUTemp;\t\t/* GPU temp */\n\tDWORD ENVTemp;\t\t/* Video card temp */\n\tDWORD FanDuty;\t\t/* Fan duty cycle */\n\tDWORD MAXGpuTemp, MINGpuTemp;\t/* Min/max GPU temp */\n\tDWORD MAXEnvTemp, MINEnvTemp;\t/* Min/max video card temp */\n\tDWORD CurD3DAA, CurD3DAF;\t/* Direct3D info */\n\tDWORD CurOGLAA, CurOGLAF;\t/* OpenGL info */\n\tDWORD IsActive;\t\t/* Another 3D boolean */\n\tDWORD CurFPS;\t\t/* FPS rate */\n\tDWORD FreeVideo;\t/* Available video memory */\n\tDWORD FreeTexture;\t/* Available texture memory */\n\tDWORD Cur3DApi;\t\t/* API used (D3D, OpenGL, etc) */\n\tDWORD MemUsed;\t\t/* ? */\n\t} TRAY_TOOLS_DATA;\n\nstatic void readATITrayToolsData( void )\n\t{\n\tHANDLE hTrayToolsData;\n\tTRAY_TOOLS_DATA *trayToolsDataPtr;\n\n\tif( ( hTrayToolsData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t\t\"ATITRAY_SMEM\" ) ) == NULL )\n\t\treturn;\n\tif( ( trayToolsDataPtr = ( TRAY_TOOLS_DATA * ) \\\n\t\t\tMapViewOfFile( hTrayToolsData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tif( trayToolsDataPtr->CurGPU >= 100 && \\\n\t\t\ttrayToolsDataPtr->isTempMonSupported != 0 )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tstatic const int quality = 10;\n\t\t\tint status;\n\n\t\t\tsetMessageData( &msgData, trayToolsDataPtr,\n\t\t\t\t\t\t\tsizeof( TRAY_TOOLS_DATA ) );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t}\n\t\t\t}\n\t\tUnmapViewOfFile( trayToolsDataPtr );\n\t\t}\n\tCloseHandle( hTrayToolsData );\n\t}\n\n/* CoreTemp data structure, from www.alcpu.com/CoreTemp.   The DWORD values \n   below are actually (32-bit) floats but we overlay them with DWORDs since \n   we don't care about the values */\n\ntypedef struct \n\t{\n\tunsigned int uiLoad[ 256 ];\n\tunsigned int uiTjMax[ 128 ];\n\tunsigned int uiCoreCnt;\n\tunsigned int uiCPUCnt;\n\tDWORD /*float*/ fTemp[ 256 ];\n\tDWORD /*float*/ fVID;\n\tDWORD /*float*/ fCPUSpeed;\n\tDWORD /*float*/ fFSBSpeed;\n\tDWORD /*float*/ fMultipier;\t\n\tDWORD /*float*/ sCPUName[ 100 ];\n\tunsigned char ucFahrenheit;\n\tunsigned char ucDeltaToTjMax;\n\t} CORE_TEMP_SHARED_DATA;\n\nstatic void readCoreTempData( void )\n\t{\n\tHANDLE hCoreTempData;\n\tCORE_TEMP_SHARED_DATA *coreTempDataPtr;\n\n\tif( ( hCoreTempData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t\t   \"CoreTempMappingObject\" ) ) == NULL )\n\t\treturn;\n\tif( ( coreTempDataPtr = ( CORE_TEMP_SHARED_DATA * ) \\\n\t\t\tMapViewOfFile( hCoreTempData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tstatic const int quality = 15;\n\t\tint status;\n\n\t\tsetMessageData( &msgData, coreTempDataPtr,\n\t\t\t\t\t\tsizeof( CORE_TEMP_SHARED_DATA ) );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\tUnmapViewOfFile( coreTempDataPtr );\n\t\t}\n\tCloseHandle( hCoreTempData );\n\t}\n\n/* GPU-Z data structures, from forums.techpowerup.com.  This uses an \n   incredibly wasteful memory layout so we end up having to submit around \n   200kB of data, unfortunately we can't easily pick out the few values of \n   interest because the 'data' entries push out the values of interest, the \n   'sensors' entries, to the end of the memory block */\n\n#define MAX_RECORDS\t\t128\n\n#pragma pack(push, 1)\n\ntypedef struct {\n\tWCHAR key[ 256 ];\n\tWCHAR value[ 256 ];\n\t} GPUZ_RECORD;\n\ntypedef struct {\n\tWCHAR name[ 256 ];\n\tWCHAR unit[ 8 ];\n\tUINT32 digits;\n\tdouble value;\n\t} GPUZ_SENSOR_RECORD;\n\ntypedef struct {\n\tUINT32 version;\t\t/* Version number, should be 1 */\n\tvolatile LONG busy;\t/* Data-update flag */\n\tUINT32 lastUpdate;\t/* GetTickCount() of last update */\n\tGPUZ_RECORD data[ MAX_RECORDS ];\n\tGPUZ_SENSOR_RECORD sensors[ MAX_RECORDS ];\n\t} GPUZ_SH_MEM;\n\n#pragma pack(pop)\n\nstatic void readGPUZData( void )\n\t{\n\tHANDLE hGPUZData;\n\tconst GPUZ_SH_MEM *gpuzDataPtr;\n\n\tif( ( hGPUZData = OpenFileMapping( FILE_MAP_READ, FALSE,\n\t\t\t\t\t\t\t\t\t   \"GPUZShMem\" ) ) == NULL )\n\t\treturn;\n\tif( ( gpuzDataPtr = ( GPUZ_SH_MEM * ) \\\n\t\t  MapViewOfFile( hGPUZData, FILE_MAP_READ, 0, 0, 0 ) ) != NULL )\n\t\t{\n\t\tif( gpuzDataPtr->version == 1 )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tstatic const int quality = 10;\n\t\t\tint status;\n\n\t\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) gpuzDataPtr, \n\t\t\t\t\t\t\tsizeof( GPUZ_SH_MEM ) );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t}\n\t\t\t}\n\t\tUnmapViewOfFile( gpuzDataPtr );\n\t\t}\n\tCloseHandle( hGPUZData );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHardware Configuration Data\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read PnP configuration data.  This is mostly static per machine, but\n   differs somewhat across machines, which means that it acts as a per-\n   machine salt, so that if a static image is deployed (for example as a VM \n   image) then we at least get the PRNG salted differently once the VM is \n   started.\n\n   We have to define the values ourselves here due to some of the values and \n   functions not existing at the time that VC++ 6.0 was released */\n\ntypedef void * HDEVINFO;\n\n#define DIGCF_PRESENT\t\t0x02\n#define DIGCF_ALLCLASSES\t0x04\n\n#define SPDRP_HARDWAREID\t\t\t\t\t0x01\n#define SPDRP_PHYSICAL_DEVICE_OBJECT_NAME\t0x0E\n#define SPDRP_SECURITY\t\t\t\t\t\t0x17\n#define SPDRP_DEVICE_POWER_DATA\t\t\t\t0x1E\n\ntypedef struct _SP_DEVINFO_DATA {\n\tDWORD cbSize;\n\tGUID classGuid;\n\tDWORD devInst;\n\tULONG *reserved;\n\t} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;\n\ntypedef BOOL ( WINAPI *SETUPDIDESTROYDEVICEINFOLIST )( HDEVINFO DeviceInfoSet );\ntypedef BOOL ( WINAPI *SETUPDIENUMDEVICEINFO )( HDEVINFO DeviceInfoSet,\n\t\t\t\t\t\t\t\t\t\t\t\tDWORD MemberIndex,\n\t\t\t\t\t\t\t\t\t\t\t\tPSP_DEVINFO_DATA DeviceInfoData );\ntypedef HDEVINFO ( WINAPI *SETUPDIGETCLASSDEVS )( /*CONST LPGUID*/ void *ClassGuid,\n\t\t\t\t\t\t\t\t\t\t\t\t  /*PCTSTR*/ void *Enumerator,\n\t\t\t\t\t\t\t\t\t\t\t\t  HWND hwndParent, DWORD Flags );\ntypedef BOOL ( WINAPI *SETUPDIGETDEVICEREGISTRYPROPERTY )( HDEVINFO DeviceInfoSet,\n\t\t\t\t\t\t\t\t\t\t\t\tPSP_DEVINFO_DATA DeviceInfoData,\n\t\t\t\t\t\t\t\t\t\t\t\tDWORD Property, PDWORD PropertyRegDataType,\n\t\t\t\t\t\t\t\t\t\t\t\tPBYTE PropertyBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\tDWORD PropertyBufferSize, PDWORD RequiredSize );\n\nstatic void readPnPData( void )\n\t{\n\tHANDLE hSetupAPI;\n\tHDEVINFO hDevInfo;\n\tSETUPDIDESTROYDEVICEINFOLIST pSetupDiDestroyDeviceInfoList = NULL;\n\tSETUPDIENUMDEVICEINFO pSetupDiEnumDeviceInfo = NULL;\n\tSETUPDIGETCLASSDEVS pSetupDiGetClassDevs = NULL;\n\tSETUPDIGETDEVICEREGISTRYPROPERTY pSetupDiGetDeviceRegistryProperty = NULL;\n\tSP_DEVINFO_DATA devInfoData;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ], pnpBuffer[ 1024 + 8 ];\n\tDWORD cbPnPBuffer;\n\tint deviceCount, status, LOOP_ITERATOR;\n\n\tif( ( hSetupAPI = DynamicLoad( \"SetupAPI.dll\" ) ) == NULL )\n\t\treturn;\n\n\t/* Get pointers to the PnP functions.  Although the get class-devs\n\t   and get device registry functions look like standard functions,\n\t   they're actually macros that are mapped to (depending on the build\n\t   type) xxxA or xxxW, so we access them under the straight-ASCII-\n\t   function name */\n\tpSetupDiDestroyDeviceInfoList = ( SETUPDIDESTROYDEVICEINFOLIST ) \\\n\t\t\t\tGetProcAddress( hSetupAPI, \"SetupDiDestroyDeviceInfoList\" );\n\tpSetupDiEnumDeviceInfo = ( SETUPDIENUMDEVICEINFO ) \\\n\t\t\t\tGetProcAddress( hSetupAPI, \"SetupDiEnumDeviceInfo\" );\n\tpSetupDiGetClassDevs = ( SETUPDIGETCLASSDEVS ) \\\n\t\t\t\tGetProcAddress( hSetupAPI, \"SetupDiGetClassDevsA\" );\n\tpSetupDiGetDeviceRegistryProperty = ( SETUPDIGETDEVICEREGISTRYPROPERTY ) \\\n\t\t\t\tGetProcAddress( hSetupAPI, \"SetupDiGetDeviceRegistryPropertyA\" );\n\tif( pSetupDiDestroyDeviceInfoList == NULL || \\\n\t\tpSetupDiEnumDeviceInfo == NULL || pSetupDiGetClassDevs == NULL || \\\n\t\tpSetupDiGetDeviceRegistryProperty == NULL )\n\t\t{\n\t\tDynamicUnload( hSetupAPI );\n\t\treturn;\n\t\t}\n\n\t/* Get info on all PnP devices */\n\thDevInfo = pSetupDiGetClassDevs( NULL, NULL, NULL,\n\t\t\t\t\t\t\t\t\t DIGCF_PRESENT | DIGCF_ALLCLASSES );\n\tif( hDevInfo == INVALID_HANDLE_VALUE )\n\t\t{\n\t\tDynamicUnload( hSetupAPI );\n\t\treturn;\n\t\t}\n\n\t/* Enumerate all PnP devices */\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDynamicUnload( hSetupAPI );\n\t\tretIntError_Void();\n\t\t}\n\tmemset( &devInfoData, 0, sizeof( devInfoData ) );\n\tdevInfoData.cbSize = sizeof( SP_DEVINFO_DATA );\n\tLOOP_MAX( deviceCount = 0, \n\t\t\t  pSetupDiEnumDeviceInfo( hDevInfo, deviceCount, \n\t\t\t\t\t\t\t\t\t  &devInfoData ), \n\t\t\t  deviceCount++ )\n\t\t{\n\t\tif( pSetupDiGetDeviceRegistryProperty( hDevInfo, &devInfoData,\n\t\t\t\t\t\t\t\t\t\t\t   SPDRP_HARDWAREID, NULL,\n\t\t\t\t\t\t\t\t\t\t\t   pnpBuffer, 1024, &cbPnPBuffer ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, pnpBuffer, cbPnPBuffer );\n\t\t\t}\n\t\tif( pSetupDiGetDeviceRegistryProperty( hDevInfo, &devInfoData,\n\t\t\t\t\t\t\t\t\t\t\t   SPDRP_DEVICE_POWER_DATA, NULL,\n\t\t\t\t\t\t\t\t\t\t\t   pnpBuffer, 1024, &cbPnPBuffer ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, pnpBuffer, cbPnPBuffer );\n\t\t\t}\n\t\tif( pSetupDiGetDeviceRegistryProperty( hDevInfo, &devInfoData,\n\t\t\t\t\t\t\t\t\t\t\t   SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, NULL,\n\t\t\t\t\t\t\t\t\t\t\t   pnpBuffer, 1024, &cbPnPBuffer ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, pnpBuffer, cbPnPBuffer );\n\t\t\t}\n\t\tif( pSetupDiGetDeviceRegistryProperty( hDevInfo, &devInfoData,\n\t\t\t\t\t\t\t\t\t\t\t   SPDRP_SECURITY, NULL,\n\t\t\t\t\t\t\t\t\t\t\t   pnpBuffer, 1024, &cbPnPBuffer ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, pnpBuffer, cbPnPBuffer );\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tpSetupDiDestroyDeviceInfoList( hDevInfo );\n\tendRandomData( randomState, 10 );\n\n\tDynamicUnload( hSetupAPI );\n\t}\n\n/* Read ACPI BIOS information, with the same requirements as for the PnP \n   read */\n\ntypedef UINT ( WINAPI *ENUMSYSTEMFIRMWARETABLES )( DWORD FirmwareTableProviderSignature,\n\t\t\t\t\t\t\t\t\t\t\t\t   PVOID pFirmwareTableBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\t   DWORD BufferSize );\ntypedef UINT ( WINAPI *GETSYSTEMFIRMWARETABLE )( DWORD FirmwareTableProviderSignature,\n\t\t\t\t\t\t\t\t\t\t\t\t DWORD FirmwareTableID,\n\t\t\t\t\t\t\t\t\t\t\t\t PVOID pFirmwareTableBuffer,\n\t\t\t\t\t\t\t\t\t\t\t\t DWORD BufferSize );\n\n#define NO_FW_IDS\t64\t/* No. ACPI FW IDs to check */\n\nstatic void readACPIData( void )\n\t{\n\tHANDLE hKernel32;\n\tENUMSYSTEMFIRMWARETABLES pEnumSystemFirmwareTables = NULL;\n\tGETSYSTEMFIRMWARETABLE pGetSystemFirmwareTable = NULL;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tDWORD fwTableIDs[ NO_FW_IDS + 8 ];\n\tint noIDs, i, status;\n\n\tif( ( hKernel32 = DynamicLoad( \"Kernel32.dll\" ) ) == NULL )\n\t\treturn;\n\n\t/* Get pointers to the ACPI functions */\n\tpEnumSystemFirmwareTables = ( ENUMSYSTEMFIRMWARETABLES ) \\\n\t\t\t\tGetProcAddress( hKernel32, \"EnumSystemFirmwareTables\" );\n\tpGetSystemFirmwareTable = ( GETSYSTEMFIRMWARETABLE ) \\\n\t\t\t\tGetProcAddress( hKernel32, \"GetSystemFirmwareTable\" );\n\tif( pEnumSystemFirmwareTables == NULL || \\\n\t\tpGetSystemFirmwareTable == NULL )\n\t\treturn;\n\n\t/* Get the IDs of the ACPI information that we want to retrieve, \n\t   consisting of four-character IDs encoded as DWORDs.  There are \n\t   typically 20-30 of these, NO_FW_IDS should work on most systems.\n\t   \n\t   This function has a weird return value, if it's zero or less then \n\t   there's been an error, if it's in the range of the buffer that we \n\t   passed it then it's the number of entries written to it, and if it's \n\t   greater than the buffer size it's the amount of buffer space that we \n\t   need to pass in to store the results.  Since this is non-critical\n\t   data, we don't bother with dynamically resizing the buffer, the given\n\t   one works in most cases */\n\tnoIDs = pEnumSystemFirmwareTables( 'ACPI', fwTableIDs, \n\t\t\t\t\t\t\t\t\t   NO_FW_IDS * sizeof( DWORD ) );\n\tif( noIDs <= sizeof( DWORD ) || \\\n\t\tnoIDs > NO_FW_IDS * sizeof( DWORD ) )\n\t\treturn;\n\tnoIDs /= sizeof( DWORD );\n\tENSURES_V( noIDs > 0 && noIDs <= NO_FW_IDS );\n\n\t/* Read the ACPI information for each ID.  As with the firmware table \n\t   IDs, we use a fixed-size buffer that works in most cases, the values\n\t   are only a few dozen or few hundred bytes */\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Void();\n\tfor( i = 0; i < noIDs; i++ )\n\t\t{\n\t\tBYTE acpiBuffer[ 2048 + 8 ];\n\t\tint acpiBufCount;\n\n\t\t/* Get the ACPI info for the current ID */\n\t\tacpiBufCount = pGetSystemFirmwareTable( 'ACPI', fwTableIDs[ i ], \n\t\t\t\t\t\t\t\t\t\t\t\tacpiBuffer, 2048 );\n\t\tif( acpiBufCount <= 1 || acpiBufCount > 2048 )\n\t\t\tcontinue;\t/* Error or more buffer needed */\n\t\taddRandomData( randomState, acpiBuffer, acpiBufCount );\n\t\t}\n\tendRandomData( randomState, 10 );\n\t}\n\n/* Read network adapter information.  See the comment for readPnPData() for\n   the salt-like nature of the data obtained.\n\n   We have to define the values ourselves here due to some of the values and \n   functions not existing at the time that VC++ 6.0 was released */\n\n#define AF_UNSPEC\t\t\t0\n#define GAA_FLAG_NONE\t\t0\n\n#define MAX_HOSTNAME_LEN\t128\n#define MAX_DOMAIN_NAME_LEN\t128\n#define MAX_SCOPE_ID_LEN\t256\n\ntypedef struct {\n\tchar String[ 4 * 4 ];\n\t} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;\n\ntypedef struct _IP_ADDR_STRING {\n\tstruct _IP_ADDR_STRING* Next;\n\tIP_ADDRESS_STRING IpAddress;\n\tIP_MASK_STRING IpMask;\n\tDWORD Context;\n\t} IP_ADDR_STRING, *PIP_ADDR_STRING;\n\ntypedef struct {\n\tchar HostName[ MAX_HOSTNAME_LEN + 4 ];\n\tchar DomainName[ MAX_DOMAIN_NAME_LEN + 4 ];\n\tPIP_ADDR_STRING CurrentDnsServer;\n\tIP_ADDR_STRING DnsServerList;\n\tUINT NodeType;\n\tchar ScopeId[ MAX_SCOPE_ID_LEN + 4 ];\n\tUINT EnableRouting;\n\tUINT EnableProxy;\n\tUINT EnableDns;\n\t} FIXED_INFO, *PFIXED_INFO;\n\ntypedef DWORD ( WINAPI *GETNETWORKPARAMS )( FIXED_INFO *pFixedInfo, \n\t\t\t\t\t\t\t\t\t\t\tULONG *pOutBufLen );\ntypedef ULONG ( WINAPI *GETADAPTERSADDRESSES )( ULONG Family, ULONG Flags, \n\t\t\t\t\t\t\tPVOID Reserved,\n\t\t\t\t\t\t\t/* IP_ADAPTER_ADDRESSES */ void *AdapterAddresses,\n\t\t\t\t\t\t\tPULONG SizePointer );\n\n#define NETWORK_INFO_BUFSIZE\t( RANDOM_BUFSIZE * 2 )\n\nstatic void readNetworkData( void )\n\t{\n\tHANDLE hIphlpAPI;\n\tGETNETWORKPARAMS pGetNetworkParams = NULL;\n\tGETADAPTERSADDRESSES pGetAdaptersAddresses = NULL;\n\tMESSAGE_DATA msgData;\n\tBYTE outBuf[ NETWORK_INFO_BUFSIZE + 8 ];\n\tULONG ulOutBufLen;\n\tint status;\n\n\tif( ( hIphlpAPI = DynamicLoad( \"Iphlpapi.dll\" ) ) == NULL )\n\t\treturn;\n\n\t/* Get pointers to the network helper functions */\n\tpGetNetworkParams = ( GETNETWORKPARAMS ) \\\n\t\t\t\tGetProcAddress( hIphlpAPI, \"GetNetworkParams\" );\n\tpGetAdaptersAddresses = ( GETADAPTERSADDRESSES ) \\\n\t\t\t\tGetProcAddress( hIphlpAPI, \"GetAdaptersAddresses\" );\n\tif( pGetNetworkParams == NULL || pGetAdaptersAddresses == NULL )\n\t\t{\n\t\tDynamicUnload( hIphlpAPI );\n\t\treturn;\n\t\t}\n\n\t/* Get the host name, domain name, DNS server info, and other odds and \n\t   ends */\n\tulOutBufLen = NETWORK_INFO_BUFSIZE;\n\tif( pGetNetworkParams( ( FIXED_INFO * ) outBuf, \n\t\t\t\t\t\t   &ulOutBufLen ) == ERROR_SUCCESS )\n\t\t{\n\t\tstatic const int quality = 5;\n\n\t\tsetMessageData( &msgData, outBuf, sizeof( FIXED_INFO ) );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\t}\n\n\t/* Get information on all network adapters in the system.  This returns \n\t   a linked list of information on every adapter (with per-adapter \n\t   internal embedded linked lists for address information (unicast, \n\t   anycast, multicast, DNS server), gateway and DNS data, and so on), \n\t   all linearised into a fixed memory block.  Alongside this is fixed \n\t   data like MAC address, MTU, metrics, link information, DHCPv6 data, \n\t   and other odds and ends.\n\n\t   MSDN recommends calling this function with an initial 15kB buffer and \n\t   then expanding it as required (see\n\t   http://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx)\n\t   but we just use a buffer of RANDOM_BUFSIZE * 2 and don't try and get \n\t   fancy if it fails.  Note that ulOutBufLen isn't modified unless the \n\t   function returns ERROR_BUFFER_OVERFLOW so the length value that we \n\t   pass to addRandomData() is most likely an over-estimate, but there's \n\t   no way to tell how much of the buffer got filled without parsing the \n\t   IP_ADAPTER_ADDRESSES contents.\n\n\t   Since we don't know how much data we're passing to addRandomData(), \n\t   we clear the entire buffer beforehand to avoid warnings from memory-\n\t   checkers that will detect that we're passing uninitialised memory to\n\t   addRandomData() */\n\tulOutBufLen = NETWORK_INFO_BUFSIZE;\n\tmemset( outBuf, 0, NETWORK_INFO_BUFSIZE );\n\tif( pGetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_NONE, NULL, outBuf, \n\t\t\t\t\t\t\t   &ulOutBufLen ) == ERROR_SUCCESS )\n\t\t{\n\t\tstatic const int quality = 10;\n\n\t\tsetMessageData( &msgData, outBuf, NETWORK_INFO_BUFSIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t}\n\t\t}\n\n\tDynamicUnload( hIphlpAPI );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tFast Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The shared Win32 fast poll routine */\n\nvoid fastPoll( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tFILETIME  creationTime, exitTime, kernelTime, userTime;\n\tSIZE_T minimumWorkingSetSize, maximumWorkingSetSize;\n#if VC_GE_2010( _MSC_VER )\n\tGUITHREADINFO guiThreadInfo;\n\tMEMORYSTATUSEX memoryStatus;\n#else\n\tMEMORYSTATUS memoryStatus;\n#endif /* VC++ >= 2010 */\n\tHANDLE handle;\n\tPOINT point;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE + 8 ];\n\tint trngValue = 0, status;\n\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\tstatus = initRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\tif( cryptStatusError( status ) )\n\t\tretIntError_Void();\n\n\t/* Get various basic pieces of system information: Handle of active\n\t   window, handle of window with mouse capture, handle of clipboard owner\n\t   handle of start of clpboard viewer list, pseudohandle of current\n\t   process, current process ID, pseudohandle of current thread, current\n\t   thread ID, handle of desktop window, handle  of window with keyboard\n\t   focus, whether system queue has any events, cursor position for last\n\t   message, 1 ms time for last message, handle of window with clipboard\n\t   open, handle of process heap, handle of procs window station, types of\n\t   events in input queue, and milliseconds since Windows was started.\n\t   Since a HWND/HANDLE can be a 64-bit value on a 64-bit platform, we \n\t   have to use a mapping macro that discards the high 32 bits (which\n\t   presumably won't be of much interest anyway).\n\t   \n\t   Note that there's another call that does almost the same thing as \n\t   GetTickCount(), timeGetTime() from the multimedia API, however this \n\t   has a fairly constant delta between ticks while GetTickCount() \n\t   wanders all over the place (while still averaging a fixed value).  So \n\t   timeGetTime() (which uses KeQueryInterruptTime()) isn't necessarily \n\t   more accurate than GetTickCount() (which uses KeQueryTickCount()), \n\t   just more regular.  In addition GetTickCount() is meant as a \n\t   monotonically increasing counter (at 1000 ticks per second) used to\n\t   measure intervals of time rather than absolute time, so its count \n\t   indication \"since the system was started\" really means \"since \n\t   whenever the HAL initialised the PIT used for the counter\".  Since \n\t   we're interested in unpredictability, we use GetTickCount() and not \n\t   timeGetTime() */\n\taddRandomHandle( randomState, GetActiveWindow() );\n\taddRandomHandle( randomState, GetCapture() );\n\taddRandomHandle( randomState, GetClipboardOwner() );\n\taddRandomHandle( randomState, GetClipboardViewer() );\n\taddRandomHandle( randomState, GetCurrentProcess() );\n\taddRandomValue( randomState, GetCurrentProcessId() );\n\taddRandomHandle( randomState, GetCurrentThread() );\n\taddRandomValue( randomState, GetCurrentThreadId() );\n\taddRandomHandle( randomState, GetDesktopWindow() );\n\taddRandomHandle( randomState, GetFocus() );\n\taddRandomValue( randomState, GetInputState() );\n\taddRandomValue( randomState, GetMessagePos() );\n\taddRandomValue( randomState, GetMessageTime() );\n\taddRandomHandle( randomState, GetOpenClipboardWindow() );\n\taddRandomHandle( randomState, GetProcessHeap() );\n\taddRandomHandle( randomState, GetProcessWindowStation() );\n#if VC_GE_2010( _MSC_VER )\n\t/* GetTickCount() overflows approximately every 49 days while \n\t   GetTickCount64() doesn't, however for our purposes this is a feature \n\t   since the value isn't monotonically incrementing any more, and in\n\t   any case we'd just end up casting the output of GetTickCount64()\n\t   to an integer to pass it to addRandomValue.  Using it does however\n\t   produce a compiler warning, which we disable around the call */\n\t#pragma warning( push )\n\t#pragma warning( disable:28159 )\n\taddRandomValue( randomState, GetTickCount() );\n\t#pragma warning( pop )\n#else\n\taddRandomValue( randomState, GetTickCount() );\n#endif /* VC++ >= 2010 */\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Calling the following function can cause problems in some cases in\n\t   that a calling application eventually stops getting events from its\n\t   event loop, so we can't (safely) use it as an entropy source */\n/*\taddRandomValue( randomState, GetQueueStatus( QS_ALLEVENTS ) ); */\n\n\t/* Get multiword system information: Current caret position, current\n\t   mouse cursor position */\n\tGetCaretPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\tGetCursorPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\n\t/* Get percent of memory in use, bytes of physical memory, bytes of free\n\t   physical memory, bytes in paging file, free bytes in paging file, user\n\t   bytes of address space, and free user bytes */\n#if VC_GE_2010( _MSC_VER )\n\tmemoryStatus.dwLength = sizeof( MEMORYSTATUSEX );\n\tGlobalMemoryStatusEx( &memoryStatus );\n\taddRandomData( randomState, &memoryStatus, sizeof( MEMORYSTATUSEX ) );\n#else\n\tmemoryStatus.dwLength = sizeof( MEMORYSTATUS );\n\tGlobalMemoryStatus( &memoryStatus );\n\taddRandomData( randomState, &memoryStatus, sizeof( MEMORYSTATUS ) );\n#endif /* VC++ >= 2010 */\n\n\t/* Get thread and process creation time, exit time, time in kernel mode,\n\t   and time in user mode in 100ns intervals */\n\thandle = GetCurrentThread();\n\tGetThreadTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );\n\taddRandomData( randomState, &creationTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &exitTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &kernelTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &userTime, sizeof( FILETIME ) );\n\thandle = GetCurrentProcess();\n\tGetProcessTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );\n\taddRandomData( randomState, &creationTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &exitTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &kernelTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &userTime, sizeof( FILETIME ) );\n\n\t/* Get assorted window handles and related information associated with \n\t   the current thread */\n#if VC_GE_2010( _MSC_VER )\n\tguiThreadInfo.cbSize = sizeof( GUITHREADINFO );\n\tGetGUIThreadInfo( 0, &guiThreadInfo );\n\taddRandomData( randomState, &guiThreadInfo, sizeof( GUITHREADINFO ) );\n#endif /* VC++ >= 2010 */\n\n\t/* Get the minimum and maximum working set size for the current process */\n\tGetProcessWorkingSetSize( handle, &minimumWorkingSetSize,\n\t\t\t\t\t\t\t  &maximumWorkingSetSize );\n\taddRandomValue( randomState, minimumWorkingSetSize );\n\taddRandomValue( randomState, maximumWorkingSetSize );\n\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\tSTARTUPINFO startupInfo;\n\n\t\t/* Get name of desktop, console window title, new window position and\n\t\t   size, window flags, and handles for stdin, stdout, and stderr */\n\t\tstartupInfo.cb = sizeof( STARTUPINFO );\n\t\tGetStartupInfo( &startupInfo );\n\t\taddRandomData( randomState, &startupInfo, sizeof( STARTUPINFO ) );\n\n\t\t/* Remember that we've got the fixed info */\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* The performance of QPC varies depending on the architecture that it's \n\t   running on and on the OS, the MS documentation is somewhat vague \n\t   about the details because they vary so much.  Under Win9x/ME it read \n\t   the 1.193180 MHz PIC timer.  Under Win32 it changed with almost every\n\t   OS update.\n\t   \n\t   Under the original Windows NT on machines with a uniprocessor HAL \n\t   KeQueryPerformanceCounter() used the 3.579545MHz timer and on \n\t   machines with a multiprocessor or APIC HAL it used the TSC (the exact \n\t   time source was controlled by the HalpUse8254 flag in the kernel).  \n\t   This choice of time sources was somewhat peculiar because on a \n\t   multiprocessor machine it was possible to get completely different \n\t   TSC readings depending on which CPU the thread was currently running \n\t   on while for uniprocessor machines this wasn't a problem.  This was \n\t   dealt with by having the kernel synchronise the TSCs across CPUs at \n\t   boot time if a multiprocessor HAL was used (it reset the TSC as part \n\t   of its system init).\n\t   \n\t   By about Windows 2000/XP it was discovered that some multiprocessor \n\t   systems couldn't have their TSCs synchronised in this manner, so you \n\t   still got inconsistent results.\n\t   \n\t   Under Windows Vista, QPC was changed to use the HPET (which was \n\t   mandated for the Vista hardware requirements) or, as a backup, the \n\t   ACPI power management (PM) timer, which provided a single counter \n\t   source but had a much higher access latency than the TSC.\n\n\t   Under Windows 7, the hardware requirements were set for constant-\n\t   rate TSCs (which is another issue with using the TSC, see below), so \n\t   QPC went back to using the TSC rather than the HPET if possible, with\n\t   fallback to the HPET or PM timer if there were problems (like a non-\n\t   constant-rate TSC, or oddball stuff like live migration of VMs).\n\n\t   Under Windows 8 the TSC is almost always used, with a better TSC\n\t   synchronisation algorithm for multi-CPU systems, although even then\n\t   on large multiprocessor systems it may not be possible to synchronise\n\t   them, leading to the usual fallback to the HPET or PM timer.\n\t   \n\t   Another feature of the TSC that affects QPC but not our use is that \n\t   mobile CPUs will turn off the TSC when they idle and newer CPUs with \n\t   advanced power management/clock throttling would change the rate of \n\t   the counter when they clock-throttle to match the current CPU speed, \n\t   and some hyperthreading CPUs would turn it off when both threads were \n\t   idle (this more or less makes sense since the CPU will be in the \n\t   halted state and not executing any instructions to count).  This\n\t   behaviour is known as a non-invariant TSC.\n\n\t   What makes non-invariant TSCs even more exciting is that the \n\t   resulting TSC output is somewhat nondeterministic, the only thing \n\t   that's guaranteed is that the counter is monotonically incrementing.  \n\t   For example when a processor with power-saving features and a non-\n\t   invariant TSC ramps down its core clock the TSC rate is lowered to \n\t   correspond to the clock rate.  However various events like cache \n\t   probes can cause the core to temporarily return to the original rate \n\t   to process the event before dropping back to the throttled rate, \n\t   which can cause TSC drift across multiple cores.  Hardware-specific \n\t   events like AMDs STPCLK signalling (\"shut 'er down ma, she's glowing \n\t   red\") can reach different cores at different times and lead to \n\t   ramping up and down and different times and for different durations, \n\t   leading to further drift.  Updated AMD CPUs fixed this by providing \n\t   invariant TSCs if the TscInvariant CPUID feature flag is set, and\n\t   more recent CPUs of all types have invariant TSCs by default.\n\n\t   As a result, if we're on a system with multiple CPUs and it doesn't \n\t   have an invariant TSC then the TSC skew can also be a source of \n\t   entropy.  To some extent this is just timing the context switch time \n\t   across CPUs (which in itself is a source of some entropy), but what's \n\t   left is the TSC skew across CPUs.  If this is if interest we can do \n\t   it with code something like the following.  Note that this is only \n\t   sample code, there are various complications such as the fact that \n\t   another thread may change the process affinity mask between the call \n\t   to the initial GetProcessAffinityMask() and the final \n\t   SetThreadAffinityMask() to restore the original mask, even if we \n\t   insert another GetProcessAffinityMask() just before the \n\t   SetThreadAffinityMask() there's still a small race condition present \n\t   but no real way to avoid it without OS API-level support:\n\n\t\tDWORD processAfinityMask, systemAffinityMask, mask = 0x10000;\n\n\t\t// Get the available processors that the thread can be scheduled on \n\t\tif( !GetProcessAffinityMask( GetCurrentProcess(), processAfinityMask, \n\t\t\t\t\t\t\t\t\t systemAffinityMask ) )\n\t\t\treturn;\n\n\t\t// Move the thread to each processor and read the TSC\n\t\twhile( mask != 0 )\n\t\t\t{\n\t\t\tmask >>= 1;\n\t\t\tif( !( mask & processAfinityMask ) )\n\t\t\t\tcontinue;\n\n\t\t\tSetThreadAffinityMask( GetCurrentThread(), mask );\n\t\t\t// RDTSC\n\t\t\t}\n\n\t\t// Restore the original thread affinity\n\t\tSetThreadAffinityMask( GetCurrentThread(), processAfinityMask );\n\n\t   A final complication, which doesn't actually affect us but only \n\t   causes problems when trying to count instruction timings, is that \n\t   RDTSC is affected by out-of-order instruction execution, for which\n\t   newer CPUs have a RDTSCP instruction that performs a serialised\n\t   read.\n\n\t   To make things unambiguous, we call RDTSC directly if possible and \n\t   fall back to QPC in the highly unlikely situation where this isn't \n\t   present */\n#if defined( __WIN64__ )\n\t{\n\tunsigned __int64 value;\n\t\n\t/* x86-64 always has a TSC, and the read is supported as an intrinsic */\n\tvalue = __rdtsc();\n\taddRandomData( randomState, &value, sizeof( __int64 ) );\n\t}\n#else\n  #ifndef NO_ASM\n\tif( getSysVar( SYSVAR_HWINTRINS ) & HWINTRINS_FLAG_RDTSC )\n\t\t{\n\t\tunsigned long value;\n\n\t\t__asm {\n\t\t\txor eax, eax\n\t\t\txor edx, edx\t\t/* Tell VC++ that EDX:EAX will be trashed */\n\t\t\trdtsc\n\t\t\tmov [value], eax\t/* Ignore high 32 bits, which are > 1s res */\n\t\t\t}\n\t\taddRandomValue( randomState, value );\n\t\t}\n  #endif /* NO_ASM */\n\telse\n\t\t{\n\t\tLARGE_INTEGER performanceCount;\n\n\t\tif( QueryPerformanceCounter( &performanceCount ) )\n\t\t\t{\n\t\t\taddRandomData( randomState, &performanceCount,\n\t\t\t\t\t\t   sizeof( LARGE_INTEGER ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Millisecond accuracy at best... */\n\t\t\taddRandomValue( randomState, GetTickCount() );\n\t\t\t}\n\t\t}\n#endif /* Win32 vs. Win64 */\n\n\t/* If there's a hardware RNG present, read data from it.  In cases where \n\t   there's an RNG status flag present, we check that the RNG is still \n\t   present/enabled on each fetch since it could (at least in theory) be \n\t   disabled by the OS between fetches.  We also read the data into an \n\t   explicitly dword-aligned buffer (which the standard buffer should be \n\t   anyway, but we make it explicit here just to be safe).  Note that we \n\t   have to force alignment using a LONGLONG rather than a #pragma pack, \n\t   since chars don't need alignment it would have no effect on the \n\t   BYTE [] member */\n#ifndef NO_ASM\n\tif( getSysVar( SYSVAR_HWINTRINS ) & HWINTRINS_FLAG_XSTORE )\n\t\t{\n\t\t/* VIA CPUs */\n\t\tstruct alignStruct {\n\t\t\tLONGLONG dummy1;\t\t/* Force alignment of following member */\n\t\t\tBYTE buffer[ 64 ];\n\t\t\t};\n\t\tstruct alignStruct *rngBuffer = ( struct alignStruct * ) buffer;\n\t\tvoid *bufPtr = rngBuffer->buffer;\t/* Get it into a form asm can handle */\n\t\tint byteCount = 0;\n\n\t\t/* VS 2015 will warn (incorrectly) about EBX being trashed, assuming \n\t\t   that the presence of the CPUID instruction changes it even though \n\t\t   the Centaur 0xC0000001 op only writes to EDX, and we save EBX \n\t\t   around the call.  There's no easy way to disable this warning, \n\t\t   #pragma warning( disable: 4713 ) only works on a per-function \n\t\t   level which means that it'd need to be disabled for the entire \n\t\t   function just to get rid of the spurious warning when cpuid is \n\t\t   called (and a second time for the pop ebx).  In addition it's\n\t\t   not clear whether we can use the VS 2015-native __cpuid() in \n\t\t   place of the inline asm because it takes the CPUID function type \n\t\t   as an int parameter, implying that it's not expecting a value \n\t\t   with the sign bit set (the docs imply that extended function\n\t\t   codes above 0x80000000 are permitted, but without a sample \n\t\t   system to test this on any more it's safer to stick to the known-\n\t\t   good inline asm) */\n\t\t__asm {\n\t\t\tpush es\n\t\t\tpush ebx\t\t\t/* Keep VC happy so it won't complain about \n\t\t\t\t\t\t\t\t   corrupting EBX when built without frame \n\t\t\t\t\t\t\t\t   pointer omission */\n\t\t\tmov eax, 0xC0000001\t/* Centaur extended feature flags */\n\t\t\tcpuid\n\t\t\tand edx, 01100b\n\t\t\tcmp edx, 01100b\t\t/* Check for RNG present + enabled flags */\n\t\t\tjne rngDisabled\t\t/* RNG was disabled after our initial check */\n\t\t\tpush ds\n\t\t\tpop es\n\t\t\tmov edi, bufPtr\t\t/* ES:EDI = buffer */\n\t\t\txor edx, edx\t\t/* Fetch 8 bytes */\n\t\t\txstore_rng\n\t\t\tand eax, 011111b\t/* Get count of bytes returned */\n\t\t\tjz rngDisabled\t\t/* Nothing read, exit */\n\t\t\tmov [byteCount], eax\n\t\trngDisabled:\n\t\t\tpop ebx\n\t\t\tpop es\n\t\t\t}\n\t\tif( byteCount > 0 )\n\t\t\t{\n\t\t\taddRandomData( randomState, bufPtr, byteCount );\n\t\t\ttrngValue = 45;\n\t\t\t}\n\t\t}\n\tif( getSysVar( SYSVAR_HWINTRINS ) & HWINTRINS_FLAG_RDRAND )\n\t\t{\n\t\t/* Intel and AMD CPUs */\n\t\tunsigned long rdrandBuffer[ 8 + 8 ];\n\t\tint byteCount = 0;\n\n\t\t__asm {\n\t\t\txor eax, eax\t\t/* Tell VC++ that EAX will be trashed */\n\t\t\txor ecx, ecx\n\t\ttrngLoop:\n\t\t\trdrand_eax\n\t\t\tjnc trngExit\t\t/* TRNG result bad, exit with byteCount = 0 */\n\t\t\tmov [rdrandBuffer+ecx], eax\n\t\t\tadd ecx, 4\n\t\t\tcmp ecx, 32\t\t\t/* Fill 32 bytes worth */\n\t\t\tjl trngLoop\n\t\t\tmov [byteCount], ecx\n\t\ttrngExit:\n\t\t\t}\n\t\tif( byteCount > 0 )\n\t\t\t{\n\t\t\taddRandomData( randomState, rdrandBuffer, byteCount );\n\t\t\ttrngValue = 45;\n\t\t\t}\n\t\t}\n\tif( getSysVar( SYSVAR_HWINTRINS ) & HWINTRINS_FLAG_TRNG )\n\t\t{\n\t\t/* AMD Geode LX.  The procedure for reading this is complex and\n\t\t   awkward, and probably only possible in kernel mode (see section\n\t\t   6.12.2 of the Geode LX data book).  In addition the CPU line was \n\t\t   more or less abandoned in 2005 so we don't try and do anything \n\t\t   with it */\n#if 0\n\t\tunsigned long value = 0;\n\n\t\t__asm {\n\t\t\txor eax, eax\n\t\t\txor edx, edx\t\t/* Tell VC++ that EDX:EAX will be trashed */\n\t\t\tmov ecx, 0x58002006\t/* GLD_MSR_CTRL */\n\t\t\trdmsr\n\t\t\tand eax, 0110000000000b\t\n\t\t\tcmp eax, 0010000000000b\t/* Check whether TRNG is enabled */\n\t\t\tjne trngDisabled\t/* TRNG isn't enabled */\n\t\ttrngDisabled:\n\t\t\t}\n\t\tif( value )\n\t\t\t{\n\t\t\taddRandomValue( randomState, value );\n\t\t\ttrngValue = 20;\n\t\t\t}\n#endif /* 0 */\n\t\t}\n#endif /* NO_ASM */\n\n\t/* Flush any remaining data through.  Quality = int( 33 1/3 % ) + any \n\t   additional quality from the TRNG if there's one present */\n\tendRandomData( randomState, 34 + trngValue );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSlow Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Type definitions for functions to call Windows native API functions */\n\ntypedef DWORD ( WINAPI *NTQUERYSYSTEMINFORMATION )( DWORD systemInformationClass,\n\t\t\t\t\t\t\t\tPVOID systemInformation,\n\t\t\t\t\t\t\t\tULONG systemInformationLength,\n\t\t\t\t\t\t\t\tPULONG returnLength );\ntypedef DWORD ( WINAPI *NTQUERYINFORMATIONPROCESS )( HANDLE processHandle,\n\t\t\t\t\t\t\t\tDWORD processInformationClass,\n\t\t\t\t\t\t\t\tPVOID processInformation,\n\t\t\t\t\t\t\t\tULONG processInformationLength,\n\t\t\t\t\t\t\t\tPULONG returnLength );\ntypedef DWORD ( WINAPI *NTPOWERINFORMATION )( DWORD powerInformationClass,\n\t\t\t\t\t\t\t\tPVOID inputBuffer, ULONG inputBufferLength,\n\t\t\t\t\t\t\t\tPVOID outputBuffer, ULONG outputBufferLength );\n\nstatic NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation = NULL;\nstatic NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;\nstatic NTPOWERINFORMATION pNtPowerInformation = NULL;\n\n/* When we query the performance counters, we allocate an initial buffer and\n   then reallocate it as required until RegQueryValueEx() stops returning\n   ERROR_MORE_DATA.  The following values define the initial buffer size and\n   step size by which the buffer is increased */\n\n#define PERFORMANCE_BUFFER_SIZE\t\t65536\t/* Start at 64K */\n#define PERFORMANCE_BUFFER_STEP\t\t16384\t/* Step by 16K */\n\nstatic void registryPoll( void )\n\t{\n\tstatic int cbPerfData = PERFORMANCE_BUFFER_SIZE;\n\tPPERF_DATA_BLOCK pPerfData;\n\tMESSAGE_DATA msgData;\n\tDWORD dwSize, dwStatus;\n\tint iterations = 0, status;\n\n\t/* Wait for any async keyset driver binding to complete.  You may be\n\t   wondering what this call is doing here... the reason why it's \n\t   necessary is because RegQueryValueEx() will hang indefinitely if the \n\t   async driver bind is in progress.  The problem occurs in the dynamic \n\t   loading and linking of driver DLL's, which work as follows:\n\n\t\thDriver = DynamicLoad( DRIVERNAME );\n\t\tpFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 );\n\t\tpFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 );\n\n\t   Under older Windows versions, if RegQueryValueEx() is called while \n\t   the GetProcAddress()'s are in progress, it will hang indefinitely.  \n\t   This is probably due to some synchronisation problem in the Windows \n\t   kernel where the GetProcAddress() calls affect something like a \n\t   module reference count or function reference count while \n\t   RegQueryValueEx() is trying to take a snapshot of the statistics, \n\t   which include the reference counts.  Because of this we have to wait \n\t   until any async driver bind has completed before we can call \n\t   RegQueryValueEx() */\n\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )\n\t\t{\n\t\t/* The kernel is shutting down, bail out */\n\t\treturn;\n\t\t}\n\n\t/* Get information from the system performance counters.  This can take a\n\t   few seconds to do.  In some environments the call to RegQueryValueEx()\n\t   can produce an access violation at some random time in the future, in\n\t   some cases adding a short delay after the following code block makes\n\t   the problem go away.  This problem is extremely difficult to\n\t   reproduce, I haven't been able to get it to occur despite running it\n\t   on a number of machines.  MS knowledge base article Q178887 covers\n\t   this type of problem, it's typically caused by an external driver or\n\t   other program that adds its own values under the\n\t   HKEY_PERFORMANCE_DATA key.  The NT kernel, via Advapi32.dll, calls the\n\t   required external module to map in the data inside an SEH try/except\n\t   block, so problems in the module's collect function don't pop up until\n\t   after it has finished, so the fault appears to occur in Advapi32.dll.\n\t   There may be problems in the NT kernel as well though, a low-level\n\t   memory checker indicated that ExpandEnvironmentStrings() in\n\t   Kernel32.dll, called an interminable number of calls down inside\n\t   RegQueryValueEx(), was overwriting memory (it wrote twice the\n\t   allocated size of a buffer to a buffer allocated by the NT kernel).\n\t   OTOH this could be coming from the external module calling back into\n\t   the kernel, which eventually causes the problem described above.\n\n\t   Possibly as an extension of the problem that the krnlWaitSemaphore()\n\t   call above works around, running two instances of cryptlib (e.g. two\n\t   applications that use it) under NT4 can result in one of them hanging\n\t   in the RegQueryValueEx() call.  This happens only under NT4 and is\n\t   hard to reproduce in any consistent manner.\n\n\t   One workaround that helps a bit is to read the registry as a remote\n\t   (rather than local) registry, it's possible that the use of a network\n\t   RPC call isolates the calling app from the problem in that whatever\n\t   service handles the RPC is taking the hit and not affecting the\n\t   calling app.  Since this would require another round of extensive\n\t   testing to verify and the Windows native API call is working fine, \n\t   we'll stick with the native API call for now.\n\n\t   Some versions of NT4 had a problem where the amount of data returned\n\t   was mis-reported and would never settle down, because of this the code\n\t   below includes a safety-catch that bails out after 10 attempts have\n\t   been made, this results in no data being returned but at does ensure\n\t   that the thread will terminate.\n\n\t   In addition to these problems the code in RegQueryValueEx() that\n\t   estimates the amount of memory required to return the performance\n\t   counter information isn't very accurate (it's much worse than the\n\t   \"slightly-inaccurate\" level that the MS docs warn about, it's usually\n\t   wildly off) since it always returns a worst-case estimate which is\n\t   usually nowhere near the actual amount required.  For example it may\n\t   report that 128K of memory is required, but only return 64K of data.\n\n\t   Even worse than the registry-based performance counters is the\n\t   performance data helper (PDH) shim that tries to make the counters\n\t   look like the old Win16 API (which is also used by Win95).  Under \n\t   Win32 this can consume tens of MB of memory and huge amounts of CPU \n\t   time while it gathers its data, and even running once can still \n\t   consume about 1/2MB of memory.\n\n\t   \"Windows NT is a thing of genuine beauty, if you're seriously into \n\t    genuine ugliness.  It's like a woman with a history of insanity in \n\t\tthe family, only worse\" -- Hans Chloride, \"Why I Love Windows NT\" */\n\tREQUIRES_V( rangeCheck( cbPerfData, 1, PERFORMANCE_BUFFER_SIZE ) );\n\tpPerfData = ( PPERF_DATA_BLOCK ) clAlloc( \"registryPoll\", cbPerfData );\n\twhile( pPerfData != NULL && iterations++ < 10 )\n\t\t{\n\t\tdwSize = cbPerfData;\n\t\tdwStatus = RegQueryValueEx( HKEY_PERFORMANCE_DATA, \"Global\", NULL,\n\t\t\t\t\t\t\t\t\tNULL, ( LPBYTE ) pPerfData, &dwSize );\n\t\tif( dwStatus == ERROR_SUCCESS )\n\t\t\t{\n\t\t\tif( !memcmp( pPerfData->Signature, L\"PERF\", 8 ) )\n\t\t\t\t{\n\t\t\t\tstatic const int quality = 100;\n\n\t\t\t\tsetMessageData( &msgData, pPerfData, dwSize );\n\t\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tclFree( \"registryPoll\", pPerfData );\n\t\t\tpPerfData = NULL;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( dwStatus == ERROR_MORE_DATA )\n\t\t\t\t{\n\t\t\t\tPPERF_DATA_BLOCK pTempPerfData;\n\t\t\t\t\n\t\t\t\tcbPerfData += PERFORMANCE_BUFFER_STEP;\n\t\t\t\tpTempPerfData = ( PPERF_DATA_BLOCK ) realloc( pPerfData, cbPerfData );\n\t\t\t\tif( pTempPerfData == NULL )\n\t\t\t\t\t{\n\t\t\t\t\t/* The realloc failed, free the original block and force \n\t\t\t\t\t   a loop exit */\n\t\t\t\t\tclFree( \"registryPoll\", pPerfData );\n\t\t\t\t\tpPerfData = NULL;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tpPerfData = pTempPerfData;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Although this isn't documented in the Win32 API docs, it's necessary to\n\t   explicitly close the HKEY_PERFORMANCE_DATA key after use (it's\n\t   implicitly opened on the first call to RegQueryValueEx()).  If this\n\t   isn't done then any system components that provide performance data\n\t   can't be removed or changed while the handle remains active */\n\tRegCloseKey( HKEY_PERFORMANCE_DATA );\n\t}\n\nstatic void slowPollWindows( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tstatic int isWorkstation = CRYPT_ERROR;\n\tMESSAGE_DATA msgData;\n\tHANDLE hDevice;\n\tLPBYTE lpBuffer;\n\tULONG ulSize;\n\tDWORD dwType, dwSize, dwResult;\n\tvoid *buffer;\n\tint nDrive, noResults = 0, status, LOOP_ITERATOR;\n\n\t/* Find out whether this is a server or workstation if necessary */\n\tif( isWorkstation == CRYPT_ERROR )\n\t\t{\n\t\tHKEY hKey;\n\n\t\tif( RegOpenKeyEx( HKEY_LOCAL_MACHINE,\n\t\t\t\t\t\t  \"SYSTEM\\\\CurrentControlSet\\\\Control\\\\ProductOptions\",\n\t\t\t\t\t\t  0, KEY_READ, &hKey ) == ERROR_SUCCESS )\n\t\t\t{\n\t\t\tBYTE szValue[ 32 + 8 ];\n\t\t\tdwSize = 32;\n\n\t\t\tisWorkstation = TRUE;\n\t\t\tif( RegQueryValueEx( hKey, \"ProductType\", 0, NULL, szValue,\n\t\t\t\t\t\t\t\t &dwSize ) == ERROR_SUCCESS && \\\n\t\t\t\tdwSize >= 5 && strCompare( szValue, \"WinNT\", 5 ) )\n\t\t\t\t{\n\t\t\t\t/* Note: There are (at least) three cases for ProductType:\n\t\t\t\t   WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =\n\t\t\t\t   NT Server acting as a Domain Controller */\n\t\t\t\tisWorkstation = FALSE;\n\t\t\t\t}\n\n\t\t\tRegCloseKey( hKey );\n\t\t\t}\n\t\t}\n\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\treadPnPData();\n\t\treadACPIData();\n\t\treadNetworkData();\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* Initialize the Windows native API function pointers if necessary */\n\tif( hNTAPI == NULL && \\\n\t\t( hNTAPI = GetModuleHandle( \"NTDll.dll\" ) ) != NULL )\n\t\t{\n\t\t/* Get a pointer to the Windows native information query functions */\n\t\tpNtQuerySystemInformation = ( NTQUERYSYSTEMINFORMATION ) \\\n\t\t\t\t\t\tGetProcAddress( hNTAPI, \"NtQuerySystemInformation\" );\n\t\tpNtQueryInformationProcess = ( NTQUERYINFORMATIONPROCESS ) \\\n\t\t\t\t\t\tGetProcAddress( hNTAPI, \"NtQueryInformationProcess\" );\n\t\tif( pNtQuerySystemInformation == NULL || \\\n\t\t\tpNtQueryInformationProcess == NULL )\n\t\t\thNTAPI = NULL;\n\t\tpNtPowerInformation = ( NTPOWERINFORMATION ) \\\n\t\t\t\t\t\tGetProcAddress( hNTAPI, \"NtPowerInformation\" );\n\t\t}\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Get network statistics.  Both workstations and servers by default \n\t   will be running both the workstation and server services, we always \n\t   get the workstation statistics since the returned structure, a \n\t   STAT_WORKSTATION_0, contains vastly more information than the \n\t   equivalent STAT_SERVER_0 */\n#if VC_GE_2010( _MSC_VER )\n\t#pragma warning( push )\n\t#pragma warning( disable:28159 )\t/* Incorrect annotation in lmstats.h */\n#endif /* VC++ >= 2010 */\n\tif( NetStatisticsGet( NULL, isWorkstation ? SERVICE_WORKSTATION : \\\n\t\t\t\t\t\t\t\t\t\t\t\tSERVICE_SERVER, 0, 0, \n\t\t\t\t\t\t  &lpBuffer ) == NERR_Success )\n\t\t{\n\t\tif( NetApiBufferSize( lpBuffer, &dwSize ) == NERR_Success )\n\t\t\t{\n\t\t\tsetMessageData( &msgData, lpBuffer, dwSize );\n\t\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t}\n\t\tNetApiBufferFree( lpBuffer );\n\t\t}\n#if VC_GE_2010( _MSC_VER )\n\t#pragma warning( pop )\n#endif /* VC++ >= 2010 */\n\n\t/* Get disk I/O statistics for all the hard drives */\n\tLOOP_MED( nDrive = 0, nDrive < 20, nDrive++ )\n\t\t{\n\t\tBYTE diskPerformance[ 256 + 8 ];\n\t\tchar szDevice[ 32 + 8 ];\n\n\t\t/* Check whether we can access this device */\n\t\tsprintf_s( szDevice, 32, \"\\\\\\\\.\\\\PhysicalDrive%d\", nDrive );\n\t\thDevice = CreateFile( szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,\n\t\t\t\t\t\t\t  NULL, OPEN_EXISTING, 0, NULL );\n\t\tif( hDevice == INVALID_HANDLE_VALUE )\n\t\t\tbreak;\n\n\t\t/* Note: This only works if the user has turned on the disk\n\t\t   performance counters with 'diskperf -y'.  These counters were\n\t\t   traditionally disabled under Windows NT, although in newer \n\t\t   installs of Win2K and newer the physical disk object is enabled \n\t\t   by default while the logical disk object is disabled by default \n\t\t   ('diskperf -yv' turns on the counters for logical drives in this \n\t\t   case, since they're already on for physical drives).\n\t\t   \n\t\t   In addition using the documented DISK_PERFORMANCE data structure \n\t\t   to contain the returned data returns ERROR_INSUFFICIENT_BUFFER \n\t\t   (which is wrong) and doesn't change dwSize (which is also wrong) \n\t\t   so we pass in a larger buffer and pre-set dwSize to a safe \n\t\t   value.  Finally, there's a bug in pre-SP4 Win2K in which enabling \n\t\t   diskperf, installing a file system filter driver, and then \n\t\t   disabling diskperf, causes diskperf to corrupt the registry key \n\t\t   HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\\n\t\t   {71A27CDD-812A-11D0-BEC7-08002BE2092F}\\Upper Filters, resulting \n\t\t   in a Stop 0x7B bugcheck */\n\t\tdwSize = sizeof( diskPerformance );\n\t\tif( DeviceIoControl( hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,\n\t\t\t\t\t\t\t &diskPerformance, 256, &dwSize, NULL ) )\n\t\t\t{\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tCloseHandle( hDevice );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tsetMessageData( &msgData, &diskPerformance, dwSize );\n\t\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t}\n\t\tCloseHandle( hDevice );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* In theory we should be using the Win32 performance query API to obtain\n\t   unpredictable data from the system, however this is so unreliable (see\n\t   the multiple sets of comments in registryPoll()) that it's too risky\n\t   to rely on it except as a fallback in emergencies.  Instead, we rely\n\t   mostly on the Windows native API function NtQuerySystemInformation(), \n\t   which has the dual advantages that it doesn't have as many (known) \n\t   problems as the Win32 equivalent and that it doesn't access the data \n\t   indirectly via pseudo-registry keys, which means that it's much faster.  \n\t   Note that the Win32 equivalent actually works almost all of the time, \n\t   the problem is that on one or two systems it can fail in strange ways \n\t   that are never the same and can't be reproduced on any other system, \n\t   which is why we use the native API here.  Microsoft officially \n\t   documented this function in early 2003, so it'll be fairly safe to \n\t   use */\n\tif( ( hNTAPI == NULL ) || \\\n\t\t( buffer = clAlloc( \"slowPollWindows\", \\\n\t\t\t\t\t\t\tPERFORMANCE_BUFFER_SIZE ) ) == NULL )\n\t\t{\n\t\tregistryPoll();\n\t\treturn;\n\t\t}\n\n\t/* Clear the buffer before use.  We have to do this because even though \n\t   NtQuerySystemInformation() tells us that it's filled in ulSize bytes, \n\t   it doesn't necessarily mean that it actually has provided that much \n\t   data */\n\tmemset( buffer, 0, PERFORMANCE_BUFFER_SIZE );\n\n\t/* Scan the first 64 possible information types (we don't bother with\n\t   increasing the buffer size as we do with the Win32 version of the\n\t   performance data read, we may miss a few classes but it's no big deal).\n\t   This scan typically yields around 20 pieces of data, there's nothing\n\t   in the range 65...128 so chances are there won't be anything above\n\t   there either */\n\tLOOP_LARGE( dwType = 0, dwType < 64, dwType++ )\n\t\t{\n\t\t/* Some information types are write-only (the IDs are shared with\n\t\t   a set-information call), we skip these */\n\t\tif( dwType == 26 || dwType == 27 || dwType == 38 || \\\n\t\t\tdwType == 46 || dwType == 47 || dwType == 48 || \\\n\t\t\tdwType == 52 )\n\t\t\tcontinue;\n\n\t\t/* ID 53 = SystemSessionProcessInformation reads input from the\n\t\t   output buffer, which has to contain a session ID and pointer\n\t\t   to the actual buffer in which to store the session information.\n\t\t   Because this isn't a standard query, we skip this */\n\t\tif( dwType == 53 )\n\t\t\tcontinue;\n\n\t\t/* Query the info for this ID.  Some results (for example for\n\t\t   ID = 6, SystemCallCounts) are only available in checked builds\n\t\t   of the kernel.  A smaller subcless of results require that\n\t\t   certain system config flags be set, for example\n\t\t   SystemObjectInformation requires that the\n\t\t   FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags.  To avoid\n\t\t   having to special-case all of these, we try reading each one and\n\t\t   only use those for which we get a success status */\n\t\tdwResult = pNtQuerySystemInformation( dwType, buffer,\n\t\t\t\t\t\t\t\t\t\t\t  PERFORMANCE_BUFFER_SIZE - 2048,\n\t\t\t\t\t\t\t\t\t\t\t  &ulSize );\n\t\tif( dwResult != ERROR_SUCCESS )\n\t\t\tcontinue;\n\n\t\t/* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,\n\t\t   SystemDpcInformation) incorrectly return a length of zero, so we\n\t\t   manually adjust the length to the correct value */\n\t\tif( ulSize == 0 )\n\t\t\t{\n\t\t\tif( dwType == 23 )\n\t\t\t\tulSize = 6 * sizeof( ULONG );\n\t\t\tif( dwType == 24 )\n\t\t\t\tulSize = 5 * sizeof( ULONG );\n\t\t\t}\n\n\t\t/* If we got some data back, add it to the entropy pool.  Note that \n\t\t   just because NtQuerySystemInformation() tells us that it's \n\t\t   provided ulSize bytes doesn't necessarily mean that it has, see \n\t\t   the comment after the malloc() for details */\n\t\tif( ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048 )\n\t\t\t{\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tclFree( \"slowPollWindows\", buffer );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tsetMessageData( &msgData, buffer, ulSize );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tnoResults++;\n\t\t\t}\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\t/* Now do the same for the process information.  This call is rather ugly\n\t   in that it requires an exact length match for the data returned,\n\t   failing with a STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if\n\t   the length isn't an exact match */\n#if 0\t/* This requires compiler-level assistance to handle complex nested \n\t\t   structs, alignment issues, and so on.  Without the headers in \n\t\t   which the entries are declared it's almost impossible to do */\n\tLOOP_LARGE( dwType = 0, dwType < 32, dwType++ )\n\t\t{\n\t\tstatic const struct { int type; int size; } processInfo[] = {\n\t\t\t{ CRYPT_ERROR, CRYPT_ERROR }\n\t\t\t};\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\tLOOP_SMALL_ALT( i = 0, processInfo[ i ].type != CRYPT_ERROR, i++ )\n\t\t\t{\n\t\t\t/* Query the info for this ID */\n\t\t\tdwResult = pNtQueryInformationProcess( GetCurrentProcess(),\n\t\t\t\t\t\t\t\t\t\t\tprocessInfo[ i ].type, buffer,\n\t\t\t\t\t\t\t\t\t\t\tprocessInfo[ i ].size, &ulSize );\n\t\t\tif( dwResult != ERROR_SUCCESS )\n\t\t\t\tcontinue;\n\n\t\t\t/* If we got some data back, add it to the entropy pool */\n\t\t\tif( ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048 )\n\t\t\t\t{\n\t\t\t\tif( krnlIsExiting() )\n\t\t\t\t\t{\n\t\t\t\t\tclFree( \"slowPollWindows\", buffer );\n\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\tsetMessageData( &msgData, buffer, ulSize );\n\t\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\tnoResults++;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK_ALT );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n#endif /* 0 */\n\n\t/* Finally do the same for the system power status information.  There \n\t   are only a limited number of useful information types available so we\n\t   restrict ourselves to the useful types.  In addition since this\n\t   function doesn't return length information we have to hardcode in\n\t   length data */\n\tif( pNtPowerInformation != NULL )\n\t\t{\n\t\tstatic const struct { int type; int size; } powerInfo[] = {\n\t\t\t{ 0, 128 },\t/* SystemPowerPolicyAc */\n\t\t\t{ 1, 128 },\t/* SystemPowerPolicyDc */\n\t\t\t{ 4, 64 },\t/* SystemPowerCapabilities */\n\t\t\t{ 5, 48 },\t/* SystemBatteryState */\n\t\t\t{ 11, 48 },\t/* ProcessorInformation */\n\t\t\t{ 12, 24 },\t/* SystemPowerInformation */\n\t\t\t{ CRYPT_ERROR, CRYPT_ERROR }\n\t\t\t};\n\t\tint i;\n\n\t\tLOOP_SMALL( i = 0, powerInfo[ i ].type != CRYPT_ERROR, i++ )\n\t\t\t{\n\t\t\t/* Query the info for this ID */\n\t\t\tdwResult = pNtPowerInformation( powerInfo[ i ].type, NULL, 0, buffer,\n\t\t\t\t\t\t\t\t\t\t\tPERFORMANCE_BUFFER_SIZE - 2048 );\n\t\t\tif( dwResult != ERROR_SUCCESS )\n\t\t\t\tcontinue;\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tclFree( \"slowPollWindows\", buffer );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tsetMessageData( &msgData, buffer, powerInfo[ i ].size );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tnoResults++;\n\t\t\t}\n\t\tENSURES_V( LOOP_BOUND_OK );\n\t\t}\n\tclFree( \"slowPollWindows\", buffer );\n\n\t/* If we got enough data, we can leave now without having to try for a\n\t   Win32-level performance information query */\n\tif( noResults > 15 )\n\t\t{\n\t\tstatic const int quality = 100;\n\n\t\tif( krnlIsExiting() )\n\t\t\treturn;\n\t\t( void ) krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &quality,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ENTROPY_QUALITY );\n\t\treturn;\n\t\t}\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* We couldn't get enough results from the kernel, fall back to the\n\t   somewhat troublesome registry poll */\n\tregistryPoll();\n\t}\n\n/* Perform a thread-safe slow poll */\n\nunsigned __stdcall threadSafeSlowPollWindows( void *dummy )\n\t{\n#if 0\n\ttypedef BOOL ( WINAPI *CREATERESTRICTEDTOKEN )( HANDLE ExistingTokenHandle,\n\t\t\t\t\t\t\t\tDWORD Flags, DWORD DisableSidCount,\n\t\t\t\t\t\t\t\tPSID_AND_ATTRIBUTES SidsToDisable,\n\t\t\t\t\t\t\t\tDWORD DeletePrivilegeCount,\n\t\t\t\t\t\t\t\tPLUID_AND_ATTRIBUTES PrivilegesToDelete,\n\t\t\t\t\t\t\t\tDWORD RestrictedSidCount,\n\t\t\t\t\t\t\t\tPSID_AND_ATTRIBUTES SidsToRestrict,\n\t\t\t\t\t\t\t\tPHANDLE NewTokenHandle );\n\tstatic CREATERESTRICTEDTOKEN pCreateRestrictedToken = NULL;\n\tstatic BOOLEAN isInited = FALSE;\n#endif /* 0 */\n\n\tUNUSED_ARG( dummy );\n\n\t/* If the poll performed any kind of active operation like the Unix one\n\t   rather than just basic data reads it'd be a good idea to drop \n\t   privileges before we begin, something that can be performed by the\n\t   following code.  Note though that this creates all sorts of \n\t   complications when cryptlib is running as a service and/or performing\n\t   impersonation, which is why it's disabled by default */\n#if 0\n\tif( !isInited )\n\t\t{\n\t\t/* Since CreateRestrictedToken() is a Win2K function we can only use\n\t\t   it on a post-NT4 system, and have to bind it at runtime */\n\t\tif( getSysVar( SYSVAR_OSVERSION ) > 4 )\n\t\t\t{\n\t\t\tconst HINSTANCE hAdvAPI32 = GetModuleHandle( \"AdvAPI32.dll\" );\n\n\t\t\tpCreateRestrictedToken = ( CREATERESTRICTEDTOKEN ) \\\n\t\t\t\t\t\tGetProcAddress( hAdvAPI32, \"CreateRestrictedToken\" );\n\t\t\t}\n\t\tisInited = TRUE;\n\t\t}\n\tif( pCreateRestrictedToken != NULL )\n\t\t{\n\t\tHANDLE hToken, hNewToken;\n\n\t\tImpersonateSelf( SecurityImpersonation );\n\t\tOpenThreadToken( GetCurrentThread(),\n\t\t\t\t\t\t TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | \\\n\t\t\t\t\t\t TOKEN_QUERY | TOKEN_ADJUST_DEFAULT | \\\n\t\t\t\t\t\t TOKEN_IMPERSONATE, TRUE, &hToken );\n\t\tCreateRestrictedToken( hToken, DISABLE_MAX_PRIVILEGE, 0, NULL, 0, NULL,\n\t\t\t\t\t\t\t   0, NULL, &hNewToken );\n\t\tSetThreadToken( &hThread, hNewToken );\n\t\t}\n#endif /* 0 */\n\n\tslowPollWindows();\n#if 0\n\tif( pCreateRestrictedToken != NULL )\n\t\tRevertToSelf();\n#endif /* 0 */\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\n/* Perform a generic slow poll.  This starts the OS-specific poll in a\n   separate thread */\n\nvoid slowPoll( void )\n\t{\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Read data from various hardware sources */\n\treadSystemRNG();\n\treadTPMRNG();\n\treadExternalRNG();\n\treadMBMData();\n\treadEverestData();\n\treadSysToolData();\n\treadRivaTunerData();\n\treadHMonitorData();\n\treadATITrayToolsData();\n\treadCoreTempData();\n\treadGPUZData();\n\n\t/* Start a threaded slow poll.  If a slow poll is already running, we\n\t   just return since there isn't much point in running two of them at the\n\t   same time */\n\tif( cryptStatusError( krnlEnterMutex( MUTEX_RANDOM ) ) )\n\t\treturn;\n\tif( hThread != NULL )\n\t\t{\n\t\tkrnlExitMutex( MUTEX_RANDOM );\n\t\treturn;\n\t\t}\n\n\t/* In theory since the thread is gathering info used (eventually) for \n\t   crypto keys we could set an ACL on the thread to make it explicit \n\t   that no-one else can mess with it:\n\n\t\tvoid *aclInfo = initACLInfo( THREAD_ALL_ACCESS );\n\n\t\thThread = ( HANDLE ) _beginthreadex( getACLInfo( aclInfo ),\n\t\t\t\t\t\t\t\t\t\t\t 0, threadSafeSlowPollWindows,\n\t\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\t\tfreeACLInfo( aclInfo );\n\n\t  However, although this is supposed to be the default access for \n\t  threads anyway, when used from a service (running under the \n\t  LocalSystem account) under Win2K SP4 and up, the thread creation fails \n\t  with error = 22 (invalid parameter).  Presumably MS patched some \n\t  security hole or other in SP4, which causes the thread creation to \n\t  fail.  Because of this problem, we don't set an ACL for the thread */\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0,\n\t\t\t\t\t\t\t\t\t\t threadSafeSlowPollWindows,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tkrnlExitMutex( MUTEX_RANDOM );\n\tassert( hThread );\n\t}\n\n/* Wait for the randomness gathering to finish.  Anything that requires the\n   gatherer process to have completed gathering entropy should call\n   waitforRandomCompletion(), which will block until the background process\n   completes */\n\nCHECK_RETVAL \\\nint waitforRandomCompletion( const BOOLEAN force )\n\t{\n\tDWORD dwResult;\n\tconst DWORD timeout = force ? 2000 : 300000L;\n\tint status;\n\n\tREQUIRES( force == TRUE || force == FALSE );\n\n\t/* If there's no polling thread running, there's nothing to do.  Note\n\t   that this isn't entirely thread-safe because someone may start\n\t   another poll after we perform this check, but there's no way to\n\t   handle this without some form of interlock mechanism with the\n\t   randomness mutex and the WaitForSingleObject().  In any case all\n\t   that'll happen is that the caller won't get all of the currently-\n\t   polling entropy */\n\tif( hThread == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Wait for the polling thread to terminate.  If it's a forced shutdown\n\t   we only wait a short amount of time (2s) before we bail out, \n\t   otherwise we hang around for as long as it takes (with a sanity-check\n\t   upper limit of 5 minutes) */\n\tdwResult = WaitForSingleObject( hThread, timeout );\n\tif( dwResult != WAIT_OBJECT_0 )\n\t\t{\n\t\t/* Since this is a cleanup function there's not much that we can do \n\t\t   at this point, although we warn in debug mode */\n\t\tDEBUG_DIAG(( \"Error %lX waiting for object\", dwResult ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tassert( dwResult != WAIT_FAILED );\t/* Warn in debug mode */\n\n\t/* Clean up */\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hThread != NULL )\n\t\t{\n\t\tCloseHandle( hThread );\n\t\thThread = NULL;\n\t\t}\n\tkrnlExitMutex( MUTEX_RANDOM );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and clean up any auxiliary randomness-related objects */\n\nvoid initRandomPolling( void )\n\t{\n\t/* Reset the various module and object handles and status info and\n\t   initialise the system and external RNG interfaces if they're \n\t   present */\n\thAdvAPI32 = hThread = NULL;\n\tinitSystemRNG();\n\tinitExternalRNG();\n\t}\n\nvoid endRandomPolling( void )\n\t{\n\tassert( hThread == NULL );\n\tendSystemRNG();\n\tendExternalRNG();\n\t}\n"
  },
  {
    "path": "deps/cl345/random/wince.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWinCE Randomness-Gathering Code\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom number\n   generator.  For usage conditions, see random.c */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* OS-specific includes */\n\n#include <tlhelp32.h>\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t4096\n\n/* Handles to various randomness objects */\n\nstatic HANDLE hToolHelp32;\t/* Handle to Toolhelp.library */\nstatic HANDLE hThread;\t\t/* Background polling thread handle */\nstatic DWORD threadID;\t\t/* Background polling thread ID */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tFast Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Type definitions for function pointers to call CE native functions */\n\ntypedef BOOL ( *CEGENRANDOM )( DWORD dwLen, BYTE *pbBuffer );\ntypedef DWORD ( *GETSYSTEMPOWERSTATUS )( PSYSTEM_POWER_STATUS_EX2 pSystemPowerStatusEx2,\n\t\t\t\t\t\t\t\t\t\t DWORD dwLen, BOOL fUpdate );\n\n/* The shared Win32 fast poll routine */\n\nvoid fastPoll( void )\n\t{\n\tstatic BOOLEAN addedFixedItems = FALSE;\n\tstatic CEGENRANDOM pCeGenRandom = NULL;\n\tstatic GETSYSTEMPOWERSTATUS pGetSystemPowerStatusEx2 = NULL;\n\tFILETIME  creationTime, exitTime, kernelTime, userTime;\n\tLARGE_INTEGER performanceCount;\n\tSYSTEM_POWER_STATUS_EX2 powerStatus;\n\tMEMORYSTATUS memoryStatus;\n\tHANDLE handle;\n\tPOINT point;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ RANDOM_BUFSIZE ];\n\tint length;\n\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Initialize the native function pointers if necessary.  CeGetRandom()\n\t   is only available in relatively new versions of WinCE, so we have to\n\t   link it dynamically */\n\tif( pCeGenRandom == NULL )\n\t\t{\n\t\tHANDLE hCoreDLL;\n\n\t\tif( ( hCoreDLL = GetModuleHandle( TEXT( \"Coredll.dll\" ) ) ) != NULL )\n\t\t\tpCeGenRandom = ( CEGENRANDOM ) GetProcAddress( hCoreDLL, TEXT( \"CeGenRandom\" ) );\n\t\t}\n\tif( pGetSystemPowerStatusEx2 == NULL )\n\t\t{\n\t\tHANDLE hGetpower;\n\n\t\tif( ( hGetpower = GetModuleHandle( TEXT( \"Getpower.dll\" ) ) ) != NULL )\n\t\t\tpGetSystemPowerStatusEx2 = ( GETSYSTEMPOWERSTATUS ) \\\n\t\t\t\t\t\t\tGetProcAddress( hGetpower, TEXT( \"GetSystemPowerStatusEx2\" ) );\n\t\t}\n\n\tinitRandomData( randomState, buffer, RANDOM_BUFSIZE );\n\n\t/* Get various basic pieces of system information: Handle of active\n\t   window, handle of window with mouse capture, handle of clipboard owner\n\t   handle of start of clpboard viewer list, pseudohandle of current\n\t   process, current process ID, pseudohandle of current thread, current\n\t   thread ID, handle of desktop window, handle  of window with keyboard\n\t   focus, whether system queue has any events, cursor position for last\n\t   message, 1 ms time for last message, handle of window with clipboard\n\t   open, handle of process heap, handle of procs window station, types of\n\t   events in input queue, and milliseconds since Windows was started */\n\taddRandomValue( randomState, GetActiveWindow() );\n\taddRandomValue( randomState, GetCapture() );\n\taddRandomValue( randomState, GetCaretBlinkTime() );\n\taddRandomValue( randomState, GetClipboardOwner() );\n\taddRandomValue( randomState, GetCurrentProcess() );\n\taddRandomValue( randomState, GetCurrentProcessId() );\n\taddRandomValue( randomState, GetCurrentThread() );\n\taddRandomValue( randomState, GetCurrentThreadId() );\n\taddRandomValue( randomState, GetDesktopWindow() );\n\taddRandomValue( randomState, GetDC( NULL ) );\n\taddRandomValue( randomState, GetDoubleClickTime() );\n\taddRandomValue( randomState, GetFocus() );\n\taddRandomValue( randomState, GetForegroundWindow() );\n\taddRandomValue( randomState, GetMessagePos() );\n\taddRandomValue( randomState, GetOpenClipboardWindow() );\n\taddRandomValue( randomState, GetProcessHeap() );\n\taddRandomValue( randomState, GetQueueStatus( QS_ALLINPUT ) );\n\taddRandomValue( randomState, GetTickCount() );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Get multiword system information: Current caret position, current\n\t   mouse cursor position */\n\tGetCaretPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\tGetCursorPos( &point );\n\taddRandomData( randomState, &point, sizeof( POINT ) );\n\n\t/* Get percent of memory in use, bytes of physical memory, bytes of free\n\t   physical memory, bytes in paging file, free bytes in paging file, user\n\t   bytes of address space, and free user bytes */\n\tmemoryStatus.dwLength = sizeof( MEMORYSTATUS );\n\tGlobalMemoryStatus( &memoryStatus );\n\taddRandomData( randomState, &memoryStatus, sizeof( MEMORYSTATUS ) );\n\n\t/* Get thread and process creation time, exit time, time in kernel mode,\n\t   and time in user mode in 100ns intervals */\n\thandle = GetCurrentThread();\n\tGetThreadTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime );\n\taddRandomData( randomState, &creationTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &exitTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &kernelTime, sizeof( FILETIME ) );\n\taddRandomData( randomState, &userTime, sizeof( FILETIME ) );\n\n\t/* Get extended battery/power status information.  We set the fUpdate\n\t   flag to force a re-read of fresh data rather than a re-use of cached\n\t   information */\n\tif( pGetSystemPowerStatusEx2 != NULL && \\\n\t\t( length = \\\n\t\t\t\tpGetSystemPowerStatusEx2( &powerStatus,\n\t\t\t\t\t\t\t\t\t\t  sizeof( SYSTEM_POWER_STATUS_EX2 ),\n\t\t\t\t\t\t\t\t\t\t  TRUE ) ) > 0 )\n\t\taddRandomData( randomState, &powerStatus, length );\n\n\t/* Get random data provided by the OS.  Since this is expected to be\n\t   provided by the system vendor, it's quite likely to be the usual\n\t   process ID + time */\n\tif( pCeGenRandom != NULL )\n\t\t{\n\t\tBYTE randomBuffer[ 32 ];\n\n\t\tif( pCeGenRandom( 32, randomBuffer ) )\n\t\t\taddRandomData( randomState, randomBuffer, 32 );\n\t\t}\n\n\t/* The following are fixed for the lifetime of the process so we only\n\t   add them once */\n\tif( !addedFixedItems )\n\t\t{\n\t\tSYSTEM_INFO systemInfo;\n\n\t\tGetSystemInfo( &systemInfo );\n\t\taddRandomData( randomState, &systemInfo, sizeof( SYSTEM_INFO ) );\n\t\taddedFixedItems = TRUE;\n\t\t}\n\n\t/* The performance of QPC varies depending on the architecture it's\n\t   running on, and is completely platform-dependant.  If there's no\n\t   hardware performance counter available, it uses the 1ms system timer,\n\t   although usually there's some form of hardware timer available.\n\t   Since there may be no correlation, or only a weak correlation,\n\t   between the performance counter and the system clock, we get the\n\t   time from both sources */\n\tif( QueryPerformanceCounter( &performanceCount ) )\n\t\taddRandomData( randomState, &performanceCount,\n\t\t\t\t\t   sizeof( LARGE_INTEGER ) );\n\taddRandomValue( randomState, GetTickCount() );\n\n\t/* Flush any remaining data through.  Quality = int( 33 1/3 % ) */\n\tendRandomData( randomState, 34 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tSlow Poll\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Type definitions for function pointers to call Toolhelp32 functions */\n\ntypedef BOOL ( WINAPI *MODULEWALK )( HANDLE hSnapshot, LPMODULEENTRY32 lpme );\ntypedef BOOL ( WINAPI *THREADWALK )( HANDLE hSnapshot, LPTHREADENTRY32 lpte );\ntypedef BOOL ( WINAPI *PROCESSWALK )( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );\ntypedef BOOL ( WINAPI *HEAPLISTWALK )( HANDLE hSnapshot, LPHEAPLIST32 lphl );\ntypedef BOOL ( WINAPI *HEAPFIRST )( HANDLE hSnapshot, LPHEAPENTRY32 lphe,\n\t\t\t\t\t\t\t\t\tDWORD th32ProcessID, DWORD th32HeapID );\ntypedef BOOL ( WINAPI *HEAPNEXT )( HANDLE hSnapshot, LPHEAPENTRY32 lphe );\ntypedef HANDLE ( WINAPI *CREATESNAPSHOT )( DWORD dwFlags, DWORD th32ProcessID );\ntypedef BOOL ( WINAPI *CLOSESNAPSHOT )( HANDLE hSnapshot );\n\n/* Global function pointers. These are necessary because the functions need to\n   be dynamically linked since only some WinCE builds contain them */\n\nstatic CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;\nstatic CLOSESNAPSHOT pCloseToolhelp32Snapshot = NULL;\nstatic MODULEWALK pModule32First = NULL;\nstatic MODULEWALK pModule32Next = NULL;\nstatic PROCESSWALK pProcess32First = NULL;\nstatic PROCESSWALK pProcess32Next = NULL;\nstatic THREADWALK pThread32First = NULL;\nstatic THREADWALK pThread32Next = NULL;\nstatic HEAPLISTWALK pHeap32ListFirst = NULL;\nstatic HEAPLISTWALK pHeap32ListNext = NULL;\nstatic HEAPFIRST pHeap32First = NULL;\nstatic HEAPNEXT pHeap32Next = NULL;\n\n/* Since there are a significant number of ToolHelp data blocks, we use a\n   larger-than-usual intermediate buffer to cut down on kernel traffic */\n\n#define BIG_RANDOM_BUFSIZE\t( RANDOM_BUFSIZE * 4 )\n\nstatic void slowPollWinCE( void )\n\t{\n\tPROCESSENTRY32 pe32;\n\tTHREADENTRY32 te32;\n\tMODULEENTRY32 me32;\n\tHEAPLIST32 hl32;\n\tHANDLE hSnapshot;\n\tRANDOM_STATE randomState;\n\tBYTE buffer[ BIG_RANDOM_BUFSIZE ];\n\tint iterationCount;\n\n\t/* Initialize the Toolhelp32 function pointers if necessary.  The\n\t   Toolhelp DLL isn't always present (some OEMs omit it) so we have to\n\t   link it dynamically */\n\tif( hToolHelp32 == NULL )\n\t\t{\n\t\t/* Obtain the module handle of the kernel to retrieve the addresses\n\t\t   of the ToolHelp32 functions */\n\t\tif( ( hToolHelp32 = LoadLibrary( TEXT( \"Toolhelp.dll\" ) ) ) == NULL )\n\t\t\t{\n\t\t\t/* There's no ToolHelp32 available, now we're in a bit of a\n\t\t\t   bind.  Try for at least a fast poll */\n\t\t\tfastPoll();\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* Now get pointers to the functions */\n\t\tpCreateToolhelp32Snapshot = ( CREATESNAPSHOT ) GetProcAddress( hToolHelp32, TEXT( \"CreateToolhelp32Snapshot\" ) );\n\t\tpCloseToolhelp32Snapshot = ( CLOSESNAPSHOT ) GetProcAddress( hToolHelp32, TEXT( \"CloseToolhelp32Snapshot\" ) );\n\t\tpModule32First = ( MODULEWALK ) GetProcAddress( hToolHelp32, TEXT( \"Module32First\" ) );\n\t\tpModule32Next = ( MODULEWALK ) GetProcAddress( hToolHelp32, TEXT( \"Module32Next\" ) );\n\t\tpProcess32First = ( PROCESSWALK ) GetProcAddress( hToolHelp32, TEXT( \"Process32First\" ) );\n\t\tpProcess32Next = ( PROCESSWALK ) GetProcAddress( hToolHelp32, TEXT( \"Process32Next\" ) );\n\t\tpThread32First = ( THREADWALK ) GetProcAddress( hToolHelp32, TEXT( \"Thread32First\" ) );\n\t\tpThread32Next = ( THREADWALK ) GetProcAddress( hToolHelp32, TEXT( \"Thread32Next\" ) );\n\t\tpHeap32ListFirst = ( HEAPLISTWALK ) GetProcAddress( hToolHelp32, TEXT( \"Heap32ListFirst\" ) );\n\t\tpHeap32ListNext = ( HEAPLISTWALK ) GetProcAddress( hToolHelp32, TEXT( \"Heap32ListNext\" ) );\n\t\tpHeap32First = ( HEAPFIRST ) GetProcAddress( hToolHelp32, TEXT( \"Heap32First\" ) );\n\t\tpHeap32Next = ( HEAPNEXT ) GetProcAddress( hToolHelp32, TEXT( \"Heap32Next\" ) );\n\n\t\t/* Make sure we got valid pointers for every Toolhelp32 function */\n\t\tif( pModule32First == NULL || pModule32Next == NULL || \\\n\t\t\tpProcess32First == NULL || pProcess32Next == NULL || \\\n\t\t\tpThread32First == NULL || pThread32Next == NULL || \\\n\t\t\tpHeap32ListFirst == NULL || pHeap32ListNext == NULL || \\\n\t\t\tpHeap32First == NULL || pHeap32Next == NULL || \\\n\t\t\tpCreateToolhelp32Snapshot == NULL )\n\t\t\t{\n\t\t\t/* Mark the main function as unavailable in case for future\n\t\t\t   reference */\n\t\t\tpCreateToolhelp32Snapshot = NULL;\n\t\t\treturn;\n\t\t\t}\n\t\t}\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\tinitRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );\n\n\t/* Take snapshots what's currently in the system.  In theory we could\n\t   do a TH32CS_SNAPALL to get everything at once, but this can lead\n\t   to out-of-memory errors on some memory-limited systems, so we only\n\t   snapshot the individual resource that we're interested in.\n\n\t   First we walk through the local heap.  We have to be careful to not\n\t   spend excessive amounts of time on this if we're linked into a large\n\t   application with a great many heaps and/or heap blocks, since the\n\t   heap-traversal functions are rather slow.  Fortunately this is\n\t   quite rare under WinCE since it implies a large/long-running server\n\t   app, which we're unlikely to run into.\n\n\t   Ideally in order to prevent excessive delays we'd count the number\n\t   of heaps and ensure that no_heaps * no_heap_blocks doesn't exceed\n\t   some maximum value, however this requires two passes of (slow) heap\n\t   traversal rather than one, which doesn't help the situation much.\n\t   To provide at least some protection, we limit the total number of\n\t   heaps and heap entries traversed, although this leads to slightly\n\t   suboptimal performance if we have a small number of deep heaps\n\t   rather than the current large number of shallow heaps.\n\n\t   There is however a second consideration that needs to be taken into\n\t   account when doing this, which is that the heap-management functions\n\t   aren't completely thread-safe, so that under (very rare) conditions\n\t   of heavy allocation/deallocation this can cause problems when calling\n\t   HeapNext().  By limiting the amount of time that we spend in each\n\t   heap, we can reduce our exposure somewhat */\n\thSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPHEAPLIST, 0 );\n\tif( hSnapshot == INVALID_HANDLE_VALUE )\n\t\t{\n\t\tassert( DEBUG_WARN );\t/* Make sure that we get some feedback */\n\t\treturn;\n\t\t}\n\thl32.dwSize = sizeof( HEAPLIST32 );\n\tif( pHeap32ListFirst( hSnapshot, &hl32 ) )\n\t\t{\n\t\tint listCount = 0;\n\n\t\tdo\n\t\t\t{\n\t\t\tHEAPENTRY32 he32;\n\n\t\t\t/* First add the information from the basic Heaplist32\n\t\t\t   structure */\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tpCloseToolhelp32Snapshot( hSnapshot );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\taddRandomData( randomState, &hl32, sizeof( HEAPLIST32 ) );\n\n\t\t\t/* Now walk through the heap blocks getting information\n\t\t\t   on each of them */\n\t\t\the32.dwSize = sizeof( HEAPENTRY32 );\n\t\t\tif( pHeap32First( hSnapshot, &he32, hl32.th32ProcessID, hl32.th32HeapID ) )\n\t\t\t\t{\n\t\t\t\tint entryCount = 0;\n\n\t\t\t\tdo\n\t\t\t\t\t{\n\t\t\t\t\tif( krnlIsExiting() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tpCloseToolhelp32Snapshot( hSnapshot );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\taddRandomData( randomState, &he32,\n\t\t\t\t\t\t\t\t   sizeof( HEAPENTRY32 ) );\n\t\t\t\t\t}\n\t\t\t\twhile( entryCount++ < 20 && pHeap32Next( hSnapshot, &he32 ) );\n\t\t\t\t}\n\t\t\t}\n\t\twhile( listCount++ < 20 && pHeap32ListNext( hSnapshot, &hl32 ) );\n\t\t}\n\tpCloseToolhelp32Snapshot( hSnapshot );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Now walk through all processes */\n\thSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );\n\tif( hSnapshot == INVALID_HANDLE_VALUE )\n\t\t{\n\t\tendRandomData( randomState, 40 );\n\t\treturn;\n\t\t}\n\tpe32.dwSize = sizeof( PROCESSENTRY32 );\n\titerationCount = 0;\n\tif( pProcess32First( hSnapshot, &pe32 ) )\n\t\t{\n\t\tdo\n\t\t\t{\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tpCloseToolhelp32Snapshot( hSnapshot );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\taddRandomData( randomState, &pe32, sizeof( PROCESSENTRY32 ) );\n\t\t\t}\n\t\twhile( pProcess32Next( hSnapshot, &pe32 ) && \\\n\t\t\t   iterationCount++ < FAILSAFE_ITERATIONS_LARGE );\n\t\t}\n\tpCloseToolhelp32Snapshot( hSnapshot );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Then walk through all threads */\n\thSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );\n\tif( hSnapshot == INVALID_HANDLE_VALUE )\n\t\t{\n\t\tendRandomData( randomState, 60 );\n\t\treturn;\n\t\t}\n\tte32.dwSize = sizeof( THREADENTRY32 );\n\titerationCount = 0;\n\tif( pThread32First( hSnapshot, &te32 ) )\n\t\t{\n\t\tdo\n\t\t\t{\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tpCloseToolhelp32Snapshot( hSnapshot );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\taddRandomData( randomState, &te32, sizeof( THREADENTRY32 ) );\n\t\t\t}\n\t\twhile( pThread32Next( hSnapshot, &te32 ) && \\\n\t\t\t   iterationCount++ < FAILSAFE_ITERATIONS_LARGE  );\n\t\t}\n\tpCloseToolhelp32Snapshot( hSnapshot );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Finally, walk through all modules associated with the process */\n\thSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, 0 );\n\tif( hSnapshot == INVALID_HANDLE_VALUE )\n\t\t{\n\t\tendRandomData( randomState, 80 );\n\t\treturn;\n\t\t}\n\tme32.dwSize = sizeof( MODULEENTRY32 );\n\titerationCount = 0;\n\tif( pModule32First( hSnapshot, &me32 ) )\n\t\t{\n\t\tdo\n\t\t\t{\n\t\t\tif( krnlIsExiting() )\n\t\t\t\t{\n\t\t\t\tpCloseToolhelp32Snapshot( hSnapshot );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\taddRandomData( randomState, &me32, sizeof( MODULEENTRY32 ) );\n\t\t\t}\n\t\twhile( pModule32Next( hSnapshot, &me32 ) && \\\n\t\t\t   iterationCount++ < FAILSAFE_ITERATIONS_LARGE  );\n\t\t}\n\tpCloseToolhelp32Snapshot( hSnapshot );\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Flush any remaining data through */\n\tendRandomData( randomState, 100 );\n\t}\n\n/* Perform a thread-safe slow poll for Windows CE */\n\nDWORD WINAPI threadSafeSlowPoll( void *dummy )\n\t{\n\tUNUSED_ARG( dummy );\n\n\tslowPollWinCE();\n\tExitThread( 0 );\n\treturn( 0 );\n\t}\n\n/* Perform a generic slow poll.  This starts the OS-specific poll in a\n   separate thread */\n\nvoid slowPoll( void )\n\t{\n\tif( krnlIsExiting() )\n\t\treturn;\n\n\t/* Start a threaded slow poll.  If a slow poll is already running, we\n\t   just return since there isn't much point in running two of them at the\n\t   same time */\n\tif( hThread )\n\t\treturn;\n\thThread = CreateThread( NULL, 0, threadSafeSlowPoll, NULL, 0, &threadID );\n\tassert( hThread );\n\t}\n\n/* Wait for the randomness gathering to finish.  Anything that requires the\n   gatherer process to have completed gathering entropy should call\n   waitforRandomCompletion(), which will block until the background process\n   completes */\n\nint waitforRandomCompletion( const BOOLEAN force )\n\t{\n\tDWORD dwResult;\n\tconst DWORD timeout = force ? 2000 : 300000L;\n\tint status;\n\n\tREQUIRES( force == TRUE || force == FALSE );\n\n\t/* If there's no polling thread running, there's nothing to do.  Note\n\t   that this isn't entirely thread-safe because someone may start\n\t   another poll after we perform this check, but there's no way to\n\t   handle this without some form of interlock mechanism with the\n\t   randomness mutex and the WaitForSingleObject().  In any case all\n\t   that'll happen is that the caller won't get all of the currently-\n\t   polling entropy */\n\tif( hThread == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Wait for the polling thread to terminate.  If it's a forced shutdown\n\t   we only wait a short amount of time (2s) before we bail out, \n\t   otherwise we hang around for as long as it takes (with a sanity-check\n\t   upper limit of 5 minutes) */\n\tdwResult = WaitForSingleObject( hThread, timeout );\n\tif( dwResult == WAIT_FAILED )\n\t\t{\n\t\t/* Since this is a cleanup function there's not much that we can do \n\t\t   at this point, although we warn in debug mode */\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tassert( dwResult != WAIT_FAILED );\t/* Warn in debug mode */\n\n\t/* Clean up */\n\tstatus = krnlEnterMutex( MUTEX_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( hThread != NULL )\n\t\t{\n\t\tCloseHandle( hThread );\n\t\thThread = NULL;\n\t\t}\n\tkrnlExitMutex( MUTEX_RANDOM );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Initialise and clean up any auxiliary randomness-related objects */\n\nvoid initRandomPolling( void )\n\t{\n\t/* Reset the various object handles and status info */\n\thToolHelp32 = hThread = NULL;\n\t}\n\nvoid endRandomPolling( void )\n\t{\n\tassert( hThread == NULL );\n\tif( hToolHelp32 )\n\t\t{\n\t\tFreeLibrary( hToolHelp32 );\n\t\thToolHelp32 = NULL;\n\t\t}\n\t}\n"
  },
  {
    "path": "deps/cl345/random/xmk.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tXilinx XMK Randomness-Gathering Code\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1996-2005\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This module is part of the cryptlib continuously seeded pseudorandom\n   number generator.  For usage conditions, see random.c.\n\n   This code represents a template for randomness-gathering only and will\n   need to be modified to provide randomness via an FPGA hardware entropy\n   source such as a standard ring oscillator generator.  In its current\n   form it does not provide any usable entropy and should not be used as an\n   entropy source */\n\n/* General includes */\n\n#include \"crypt.h\"\n#include \"random/random.h\"\n\n/* The size of the intermediate buffer used to accumulate polled data */\n\n#define RANDOM_BUFSIZE\t256\n\n\n/* OS-specific includes */\n\nvoid fastPoll( void )\n\t{\n\treturn;\n\t}\n\nvoid slowPoll( void )\n\t{\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\tfastPoll();\n\t}\n"
  },
  {
    "path": "deps/cl345/session/certstore.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib HTTP Certstore Session Management\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"certstore.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/certstore.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tShared Certstore/SCEP Utility Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* SCEP's bolted-on HTTP query mechanism requires that we use the HTTP \n   certstore access routines to return responses to certificate queries,\n   so we enable the use of this code if either certstores or SCEP are\n   used */\n\n#if defined( USE_CERTSTORE ) || defined( USE_SCEP )\n\n#ifdef USE_SCEP\n\n/* Table mapping a query submitted as an HTTP GET to a cryptlib-internal \n   keyset query.  Note that the first letter must be lowercase for the\n   case-insensitive quick match */\n\nstatic const CERTSTORE_READ_INFO certstoreReadInfo[] = {\n\t{ \"certHash\", 8, CRYPT_IKEYID_CERTID, CERTSTORE_FLAG_BASE64 },\n\t{ \"name\", 4, CRYPT_KEYID_NAME, CERTSTORE_FLAG_NONE },\n\t{ \"uri\", 3, CRYPT_KEYID_URI, CERTSTORE_FLAG_NONE },\n\t{ \"email\", 5, CRYPT_KEYID_URI, CERTSTORE_FLAG_NONE },\n\t{ \"sHash\", 5, CRYPT_IKEYID_ISSUERID, CERTSTORE_FLAG_BASE64 },\n\t{ \"iHash\", 5, CRYPT_IKEYID_ISSUERID, CERTSTORE_FLAG_BASE64 },\n\t{ \"iAndSHash\", 9, CRYPT_IKEYID_ISSUERANDSERIALNUMBER, CERTSTORE_FLAG_BASE64 },\n\t{ \"sKIDHash\", 8, CRYPT_IKEYID_KEYID, CERTSTORE_FLAG_BASE64 },\n\t{ NULL, 0, CRYPT_KEYID_NONE, CERTSTORE_FLAG_NONE },\n\t\t{ NULL, 0, CRYPT_KEYID_NONE, CERTSTORE_FLAG_NONE }\n\t};\n#endif /* USE_SCEP */\n\n/* Convert a query attribute into a text string suitable for use with \n   retExt() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int queryAttributeToString( OUT_BUFFER_FIXED( textBufMaxLen ) char *textBuffer, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) const int textBufMaxLen,\n\t\t\t\t\t\t\t\t   IN_BUFFER( attributeLen ) const BYTE *attribute, \n\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int attributeLen )\n\t{\n\tconst int bytesToCopy = min( attributeLen, textBufMaxLen );\n\n\tassert( isWritePtrDynamic( textBuffer, textBufMaxLen ) );\n\tassert( isReadPtrDynamic( attribute, attributeLen ) );\n\n\tREQUIRES( textBufMaxLen >= 16 && textBufMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( attributeLen ) );\n\n\t/* Copy as much of the attribute as will fit across and clean it up so\n\t   that it can be returned to the user */\n\tREQUIRES( rangeCheck( bytesToCopy, 1, textBufMaxLen ) );\n\tmemcpy( textBuffer, attribute, bytesToCopy );\n\tsanitiseString( textBuffer, textBufMaxLen, attributeLen );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process a certificate query and return the requested certificate.  See \n   the comment above for why this is declared non-static */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint processCertQuery( INOUT SESSION_INFO *sessionInfoPtr,\t\n\t\t\t\t\t  const HTTP_URI_INFO *httpReqInfo,\n\t\t\t\t\t  IN_ARRAY( queryReqInfoSize ) \\\n\t\t\t\t\t\t\tconst CERTSTORE_READ_INFO *queryReqInfo,\n\t\t\t\t\t  IN_RANGE( 1, 64 ) const int queryReqInfoSize,\n\t\t\t\t\t  OUT_ATTRIBUTE_Z int *attributeID, \n\t\t\t\t\t  OUT_BUFFER_OPT( attributeMaxLen, *attributeLen ) \\\n\t\t\t\t\t\t\tvoid *attribute, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int attributeMaxLen, \n\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *attributeLen )\n\t{\n\tconst CERTSTORE_READ_INFO *queryInfoPtr = NULL;\n\tconst int firstChar = toLower( httpReqInfo->attribute[ 0 ] );\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( httpReqInfo, sizeof( HTTP_URI_INFO ) ) );\n\tassert( isReadPtrDynamic( queryReqInfo, \n\t\t\t\t\t\t\t  sizeof( CERTSTORE_READ_INFO ) * queryReqInfoSize ) );\n\tassert( isWritePtr( attributeID, sizeof( int ) ) );\n\tassert( ( attribute == NULL && attributeMaxLen == 0 && \\\n\t\t\t  attributeLen == NULL ) || \\\n\t\t\t( isWritePtrDynamic( attribute, attributeMaxLen ) && \\\n\t\t\t  isWritePtr( attributeLen, sizeof( int ) ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( queryReqInfoSize > 0 && queryReqInfoSize <= 64 );\n\tREQUIRES( ( attribute == NULL && attributeMaxLen == 0 && \\\n\t\t\t\tattributeLen == NULL ) || \\\n\t\t\t  ( attribute != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( attributeMaxLen ) && \\\n\t\t\t\tattributeLen != NULL ) );\n\n\t/* Clear return values */\n\t*attributeID = CRYPT_ATTRIBUTE_NONE;\n\tif( attribute != NULL )\n\t\t{\n\t\tmemset( attribute, 0, min( 16, attributeMaxLen ) );\n\t\t*attributeLen = 0;\n\t\t}\n\n\t/* Convert the search attribute type into a cryptlib key ID */\n\tLOOP_MED( i = 0, i < queryReqInfoSize && \\\n\t\t\t\t\t queryReqInfo[ i ].attrName != NULL, i++ )\n\t\t{\n\t\tif( httpReqInfo->attributeLen == queryReqInfo[ i ].attrNameLen && \\\n\t\t\tqueryReqInfo[ i ].attrName[ 0 ] == firstChar && \\\n\t\t\t!strCompare( httpReqInfo->attribute, \\\n\t\t\t\t\t\t queryReqInfo[ i ].attrName, \\\n\t\t\t\t\t\t queryReqInfo[ i ].attrNameLen ) )\n\t\t\t{\n\t\t\tqueryInfoPtr = &queryReqInfo[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < queryReqInfoSize );\n\tif( queryInfoPtr == NULL )\n\t\t{\n\t\tchar queryText[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\tstatus = queryAttributeToString( queryText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t httpReqInfo->attribute, \n\t\t\t\t\t\t\t\t\t\t httpReqInfo->attributeLen );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate query attribute '%s'\", queryText ) );\n\t\t}\n\n\t/* We've got a valid attribute, let the caller know which one it is.  If\n\t   that's all the information that they're after, we're done */\n\t*attributeID = queryInfoPtr->attrID;\n\tif( attribute == NULL )\n\t\treturn( CRYPT_OK );\n\n#ifdef USE_BASE64\n\t/* If the query data wasn't encoded in any way, we're done */\n\tif( !( queryInfoPtr->flags & CERTSTORE_FLAG_BASE64 ) )\n\t\t{\n\t\treturn( attributeCopyParams( attribute, attributeMaxLen, \n\t\t\t\t\t\t\t\t\t attributeLen, httpReqInfo->value, \n\t\t\t\t\t\t\t\t\t httpReqInfo->valueLen ) );\n\t\t}\n\n\t/* The value was base64-encoded in transit, decode it to get the actual \n\t   query data */\n\tstatus = base64decode( attribute, attributeMaxLen, attributeLen, \n\t\t\t\t\t\t   httpReqInfo->value, httpReqInfo->valueLen, \n\t\t\t\t\t\t   CRYPT_CERTFORMAT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tchar queryText[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\tstatus = queryAttributeToString( queryText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t httpReqInfo->value, \n\t\t\t\t\t\t\t\t\t\t httpReqInfo->valueLen );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid base64-encoded query value '%s'\", queryText ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n#else\n\treturn( attributeCopyParams( attribute, attributeMaxLen, \n\t\t\t\t\t\t\t\t attributeLen, httpReqInfo->value, \n\t\t\t\t\t\t\t\t httpReqInfo->valueLen ) );\n#endif /* USE_BASE64 */\n\t}\n\n/* Send an HTTP error response to the client (the error status value is \n   mapped at the HTTP layer to an appropriate HTTP response).  We don't \n   return a status from this since the caller already has an error status \n   available */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendCertErrorResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tIN_ERROR const int errorStatus )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES_V( cryptStatusError( errorStatus ) );\n\n\tstatus = initHttpInfoReq( &httpDataInfo );\n\tENSURES_V( cryptStatusOK( status ) );\n\thttpDataInfo.reqStatus = errorStatus;\n\t( void ) swrite( &sessionInfoPtr->stream, &httpDataInfo, \n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\t}\n#endif /* USE_CERTSTORE || USE_SCEP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTSTORE\n\n/* Exchange data with an HTTP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tHTTP_URI_INFO httpReqInfo;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint keyIDtype, keyIDLen, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_GET );\n\n\t/* Read the request data from the client.  We do a direct read rather \n\t   than using readPkiDatagram() since we're reading an idempotent HTTP \n\t   GET request and not a PKI datagram submitted via an HTTP POST */\n\tmemset( &httpReqInfo, 0, sizeof( HTTP_URI_INFO ) );\n\tstatus = initHttpInfoReadEx( &httpDataInfo, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t\t\t &httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = sread( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\tsizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream, \n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* Convert the certificate query into a certstore search key */\n\tstatus = processCertQuery( sessionInfoPtr, &httpReqInfo, \n\t\t\t\t\t\t\t   certstoreReadInfo,\n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( certstoreReadInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t   CERTSTORE_READ_INFO ),\n\t\t\t\t\t\t\t   &keyIDtype, keyID, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t   &keyIDLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\treturn( status );\n\t\t}\n\n\t/* Try and fetch the requested certificate.  Note that this is somewhat \n\t   suboptimal since we have to instantiate the certificate only to \n\t   destroy it again as soon as we've exported the certificate data, for \n\t   a proper high-performance implementation the server would query the \n\t   certificate database directly and send the stored encoded value to \n\t   the client */\n\tsetMessageKeymgmtInfo( &getkeyInfo, keyIDtype, keyID, keyIDLen, \n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tchar queryText[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tchar textBuffer[ 64 + CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint textLength;\n\n\t\t/* Not finding a certificate in response to a request isn't a real \n\t\t   error so all we do is return a warning to the caller.  \n\t\t   Unfortunately since we're not using retExt() we have to assemble\n\t\t   the message string ourselves */\n\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\tstatus = queryAttributeToString( queryText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t httpReqInfo.value, \n\t\t\t\t\t\t\t\t\t\t httpReqInfo.valueLen );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\ttextLength = sprintf_s( textBuffer, 64 + CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\"Warning: Couldn't find certificate for '%s'\", \n\t\t\t\t\t\t\t\tqueryText );\n\t\tsetErrorString( SESSION_ERRINFO, textBuffer, textLength );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Write the certificate to the session buffer */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( getkeyInfo.cryptHandle, IMESSAGE_CRT_EXPORT, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTFORMAT_CERTIFICATE );\n\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DESTROY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tchar queryText[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint altStatus;\n\n\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\taltStatus = queryAttributeToString( queryText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t\thttpReqInfo.value, \n\t\t\t\t\t\t\t\t\t\t\thttpReqInfo.valueLen );\n\t\tENSURES( cryptStatusOK( altStatus ) );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't export requested certificate for '%s'\", \n\t\t\t\t  queryText ) );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd = msgData.length;\n\n\t/* Send the result to the client */\n\treturn( writePkiDatagram( sessionInfoPtr, CERTSTORE_CONTENT_TYPE, \n\t\t\t\t\t\t\t  CERTSTORE_CONTENT_TYPE_LEN ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodCertstore( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\t0,\t\t\t\t\t\t\t/* Client flags */\n\t\tSESSION_NEEDS_KEYSET,\t\t/* Server flags */\n\t\t1, 1, 1,\t\t\t\t\t/* Version 1 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\t\n\t\t/* Protocol-specific information */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers.  The client-side implementation is \n\t  just a standard HTTP fetch so there's no explicit certstore client\n\t  implementation */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t\t}\n\telse\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTSTORE */\n"
  },
  {
    "path": "deps/cl345/session/certstore.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Certstore Session Management\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2008\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CERTSTORE_DEFINED\n\n#define _CERTSTORE_DEFINED\n\n/* The certstore HTTP content type */\n\n#define CERTSTORE_CONTENT_TYPE\t\t\"application/pkix-cert\"\n#define CERTSTORE_CONTENT_TYPE_LEN\t21\n\n/* Processing flags for certstore query data.  These are:\n\n\tFLAG_BASE64: The attribute is base64-encoded and must be decoded before\n\t\tbeing returned to the caller */\n\n#define CERTSTORE_FLAG_NONE\t\t0x00\t/* No special processing */\n#define CERTSTORE_FLAG_BASE64\t0x01\t/* Data must be base64 */\n\n/* A mapping of a query submitted as an HTTP GET to a cryptlib-specific\n   attribute ID that can be used for an operation like a keyset query.  Note \n   that the first letter must be lowercase for the case-insensitive quick \n   match */\n\ntypedef struct {\n\tBUFFER_FIXED( attrNameLen ) \\\n\tconst char *attrName;\t\t\t\t/* Attribute name from HTTP GET */\n\tconst int attrNameLen;\t\t\t\t/* Attribute name length */\n\tconst int attrID;\t\t\t\t\t/* Attribute ID */\n\tconst int flags;\t\t\t\t\t/* Processing flags */\n\t} CERTSTORE_READ_INFO;\n\n/* Prototypes for functions in certstore.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint processCertQuery( INOUT SESSION_INFO *sessionInfoPtr,\t\n\t\t\t\t\t  const HTTP_URI_INFO *httpReqInfo,\n\t\t\t\t\t  IN_ARRAY( queryReqInfoSize ) \\\n\t\t\t\t\t\tconst CERTSTORE_READ_INFO *queryReqInfo,\n\t\t\t\t\t  IN_RANGE( 1, 64 ) const int queryReqInfoSize,\n\t\t\t\t\t  OUT_ATTRIBUTE_Z int *attributeID, \n\t\t\t\t\t  OUT_BUFFER_OPT( attributeMaxLen, *attributeLen ) \\\n\t\t\t\t\t\tvoid *attribute, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int attributeMaxLen, \n\t\t\t\t\t  OUT_OPT_LENGTH_SHORT_Z int *attributeLen );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendCertErrorResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tIN_ERROR const int errorStatus );\n\n#endif /* _CERTSTORE_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/cmp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib CMP Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionCMP( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( cmpInfo, sizeof( CMP_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckSession( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionCMP: Session check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check CMP session parameters */\n\tif( !CHECK_FLAGS( sessionInfoPtr->protocolFlags, CMP_PFLAG_NONE, \n\t\t\t\t\t  CMP_PFLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionCMP: Protocol flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( cmpInfo->requestType, CRYPT_REQUESTTYPE ) || \\\n\t\t( cmpInfo->userInfo != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( cmpInfo->userInfo ) ) || \\\n\t\t( cmpInfo->savedMacContext != CRYPT_ERROR && \\\n\t\t  !isHandleRangeValid( cmpInfo->savedMacContext ) ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionCMP: Session parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n#if defined( __WIN32__ ) && !defined( NDEBUG )\n\n/* Dump a message to disk for diagnostic purposes.  The CMP messages are\n   complex enough that we can't use the normal DEBUG_DUMP() macro but have\n   to use a special-purpose function that uses meaningful names for all\n   of the files that are created */\n\nSTDC_NONNULL_ARG( ( 3 ) ) \\\nvoid debugDumpCMP( IN_ENUM( CMP_MESSAGE ) const CMP_MESSAGE_TYPE type, \n\t\t\t\t   IN_RANGE( 1, 4 ) const int phase,\n\t\t\t\t   const SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const char *irStrings[] = \\\n\t\t{ \"cmpi1_ir\", \"cmpi2_ip\", \"cmpi3_conf\", \"cmpi4_confack\" };\n\tstatic const char *crStrings[] = \\\n\t\t{ \"cmpc1_cr\", \"cmpc2_cp\", \"cmpc3_conf\", \"cmpc4_confack\" };\n\tstatic const char *kurStrings[] = \\\n\t\t{ \"cmpk1_kur\", \"cmpk2_kup\", \"cmpk3_conf\", \"cmpk4_confack\" };\n\tstatic const char *rrStrings[] = \\\n\t\t{ \"cmpr1_rr\", \"cmpr2_rp\" };\n\tstatic const char *gmStrings[] = \\\n\t\t{ \"cmpg1_gr\", \"cmpg2_gp\" };\n\tstatic const char *errorStrings[] = \\\n\t\t{ \"cmpe1_error\" };\n\tstatic const char *unkStrings[] = \\\n\t\t{ \"cmp_unknown1\", \"cmp_unknown2\", \"cmp_unknown3\", \"cmp_unknown4\" };\n\tconst char **fnStringPtr = ( type == CTAG_PB_IR ) ? irStrings : \\\n\t\t\t\t\t\t\t   ( type == CTAG_PB_CR ) ? crStrings : \\\n\t\t\t\t\t\t\t   ( type == CTAG_PB_KUR ) ? kurStrings : \\\n\t\t\t\t\t\t\t   ( type == CTAG_PB_RR ) ? rrStrings : \\\n\t\t\t\t\t\t\t   ( type == CTAG_PB_GENM ) ? gmStrings : \\\n\t\t\t\t\t\t\t   ( type == CTAG_PB_ERROR ) ? errorStrings : \\\n\t\t\t\t\t\t\t  unkStrings;\n\tFILE *filePtr;\n\tchar fileName[ 1024 + 8 ];\n\n#ifndef DUMP_SERVER_MESSAGES\n\t/* Server messages have complex names based on the server DN so we only \n\t   dump them if explicitly requested */\n\tif( isServer( sessionInfoPtr ) )\n\t\treturn;\n#endif /* !DUMP_SERVER_MESSAGES */\n\n/*\tGetTempPath( 512, fileName ); */\n\tstrlcpy_s( fileName, 1024, \"/tmp/\" );\n#ifdef DUMP_SERVER_MESSAGES\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tconst int pathLength = strlen( fileName );\n\t\tint i, LOOP_ITERATOR;\n\n\t\tsetMessageData( &msgData, fileName + pathLength, 1024 - pathLength );\n\t\tkrnlSendMessage( sessionInfoPtr->privateKey, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t &msgData, CRYPT_CERTINFO_DN );\n\t\tLOOP_LARGE( i = 0, i < msgData.length, i++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( fileName[ pathLength + i ] );\n\n\t\t\tif( ch == ' ' || ch == '\\'' || ch == '\"' || ch == '?' || \\\n\t\t\t\tch == '*' || ch == '[' || ch == ']' || ch == '`' || \\\n\t\t\t\tch == ',' || ch < ' ' || ch > 'z' )\n\t\t\t\tfileName[ pathLength + i ] = '_';\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tstrlcat_s( fileName, 1024, \"_\" );\n\t\t}\n#endif /* DUMP_SERVER_MESSAGES */\n\tstrlcat_s( fileName, 1024, fnStringPtr[ phase - 1 ] );\n\tstrlcat_s( fileName, 1024, \".der\" );\n\n#ifdef __STDC_LIB_EXT1__\n\tif( fopen_s( &filePtr, fileName, \"wb\" ) != 0 )\n\t\tfilePtr = NULL;\n#else\n\tfilePtr = fopen( fileName, \"wb\" );\n#endif /* __STDC_LIB_EXT1__ */\n\tif( filePtr != NULL )\n\t\t{\n\t\tfwrite( sessionInfoPtr->receiveBuffer, 1,\n\t\t\t\tsessionInfoPtr->receiveBufEnd, filePtr );\n\t\tfclose( filePtr );\n\t\t}\n\t}\n#endif /* Windows debug mode only */\n\n/* Map request to response types */\n\nstatic const MAP_TABLE reqRespMapTbl[] = {\n\t{ CTAG_PB_IR, CTAG_PB_IP },\n\t{ CTAG_PB_CR, CTAG_PB_CP },\n\t{ CTAG_PB_P10CR, CTAG_PB_CP },\n\t{ CTAG_PB_POPDECC, CTAG_PB_POPDECR },\n\t{ CTAG_PB_KUR, CTAG_PB_KUP },\n\t{ CTAG_PB_KRR, CTAG_PB_KRP },\n\t{ CTAG_PB_RR, CTAG_PB_RP },\n\t{ CTAG_PB_CCR, CTAG_PB_CCP },\n\t{ CTAG_PB_GENM, CTAG_PB_GENP },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, \n\t\t{ CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nCHECK_RETVAL_RANGE( CMP_MESSAGE_NONE, CMP_MESSAGE_LAST - 1 ) \\\nint reqToResp( IN_ENUM_OPT( CMP_MESSAGE ) const CMP_MESSAGE_TYPE reqType )\n\t{\n\tint value, status;\n\n\tREQUIRES( reqType >= CTAG_PB_IR && reqType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\n\tstatus = mapValue( reqType, &value, reqRespMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( reqRespMapTbl, MAP_TABLE ) );\n\treturn( cryptStatusError( status ) ? status : value );\n\t}\n\n/* Initialise and destroy the protocol state information */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPprotocolInfo( OUT CMP_PROTOCOL_INFO *protocolInfo, \n\t\t\t\t\t\t  const BOOLEAN isCryptlib,\n\t\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES_V( isCryptlib == TRUE || isCryptlib == FALSE );\n\tREQUIRES_V( isServer == TRUE || isServer == FALSE );\n\n\tmemset( protocolInfo, 0, sizeof( CMP_PROTOCOL_INFO ) );\n\tprotocolInfo->iMacContext = protocolInfo->authContext = CRYPT_ERROR;\n\tif( isCryptlib )\n\t\tprotocolInfo->isCryptlib = TRUE;\n\tif( isServer )\n\t\tprotocolInfo->isServer = TRUE;\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setCMPprotocolInfo( INOUT CMP_PROTOCOL_INFO *protocolInfo, \n\t\t\t\t\t\tIN_BUFFER_OPT( userIDlength ) const void *userID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int userIDlength, \n\t\t\t\t\t\tIN_FLAGS_Z( CMP_INIT ) const int flags,\n\t\t\t\t\t\tconst BOOLEAN isCryptlib )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( ( userID == NULL && userIDlength == 0 ) || \\\n\t\t\tisReadPtrDynamic( userID, userIDlength ) );\n\n\tREQUIRES( ( !( flags & CMP_INIT_FLAG_USERID ) && userID == NULL && \\\n\t\t\t\tuserIDlength == 0 ) || \\\n\t\t\t  ( ( flags & CMP_INIT_FLAG_USERID ) && userID != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( userIDlength ) ) );\n\tREQUIRES( isFlagRangeZ( flags, CMP_INIT ) );\n\tREQUIRES( isCryptlib == TRUE || isCryptlib == FALSE );\n\n\t/* Initalise the protocol state information.  The sender nonce is \n\t   refreshed on each message read (i.e. at each round of the protocol),\n\t   but its initial value has to be set here at startup */\n\tsetMessageData( &msgData, protocolInfo->senderNonce, CMP_NONCE_SIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tprotocolInfo->senderNonceSize = CMP_NONCE_SIZE;\n\n\t/* Set fixed identification information */\n\tif( flags & CMP_INIT_FLAG_USERID )\n\t\t{\n\t\tREQUIRES( rangeCheck( userIDlength, 0, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( protocolInfo->userID, userID, userIDlength );\n\t\tprotocolInfo->userIDsize = userIDlength;\n\t\tDEBUG_PRINT(( \"%s: Set userID.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->userID, protocolInfo->userIDsize );\n\t\t}\n\tif( flags & CMP_INIT_FLAG_TRANSID )\n\t\t{\n\t\tsetMessageData( &msgData, protocolInfo->transID, CMP_NONCE_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprotocolInfo->transIDsize = CMP_NONCE_SIZE;\n\t\tDEBUG_PRINT(( \"%s: Set new transID.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->transID, protocolInfo->transIDsize );\n\t\t}\n\n\t/* Set the MAC information and context.  cryptlib uses strong passwords \n\t   (or at least MAC keys) so if we're using a cryptlib-generated key we\n\t   apply a smaller number of iterations than what'd be needed for an \n\t   unknown-strength password/MAC key */\n\tif( flags & CMP_INIT_FLAG_MACINFO )\n\t\t{\n\t\tsetMessageData( &msgData, protocolInfo->salt, CMP_NONCE_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprotocolInfo->saltSize = CMP_NONCE_SIZE;\n\t\tprotocolInfo->iterations = isCryptlib ? CMP_PW_ITERATIONS_CLIB : \\\n\t\t\t\t\t\t\t\t\t\t\t\tCMP_PW_ITERATIONS_OTHER;\n\t\t}\n\tif( flags & CMP_INIT_FLAG_MACCTX )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tREQUIRES( protocolInfo->iMacContext == CRYPT_ERROR );\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA1 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprotocolInfo->iMacContext = createInfo.cryptHandle;\n\t\tprotocolInfo->useMACsend = protocolInfo->useMACreceive = TRUE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroyCMPprotocolInfo( INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\t/* Destroy any active MAC contexts.  The authContext is just a reference \n\t   to the appropriate context in the session information so we don't \n\t   destroy it here.  The reason why we keep a reference to the \n\t   authentication context is because it could be one of several \n\t   different objects associated with the session information, if the\n\t   client private key that's being certified is a signing key then the\n\t   authentication context is the private key itself, if the private key \n\t   is an encryption-only key then the authentication context is a \n\t   separate signing key that was certified earlier.  Maintaining a\n\t   reference in the protocol information avoids having to decide on the \n\t   fly which one to use */\n\tif( protocolInfo->iMacContext != CRYPT_ERROR )\n\t\tkrnlSendNotifier( protocolInfo->iMacContext, IMESSAGE_DECREFCOUNT );\n\n\tzeroise( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Shut down a CMP session */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void shutdownFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Clean up CMP-specific objects */\n\tif( cmpInfo->userInfo != CRYPT_ERROR )\n\t\tkrnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );\n\tif( cmpInfo->savedMacContext != CRYPT_ERROR )\n\t\tkrnlSendNotifier( cmpInfo->savedMacContext, IMESSAGE_DECREFCOUNT );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tControl Information Management Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t OUT void *data, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tCRYPT_CERTIFICATE *cmpResponsePtr = ( CRYPT_CERTIFICATE * ) data;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( data, sizeof( int ) ) );\n\t\n\tREQUIRES( type == CRYPT_SESSINFO_RESPONSE || \\\n\t\t\t  type == CRYPT_SESSINFO_CMP_REQUESTTYPE );\n\n\t/* If it's a general protocol-specific attribute read, return the\n\t   information and exit */\n\tif( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )\n\t\t{\n\t\tif( cmpInfo->requestType == CRYPT_REQUESTTYPE_NONE )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t*( ( int * ) data ) = cmpInfo->requestType;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we didn't get a response there's nothing to return */\n\tif( sessionInfoPtr->iCertResponse == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Return the information to the caller */\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_INCREFCOUNT );\n\t*cmpResponsePtr = sessionInfoPtr->iCertResponse;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tCRYPT_CERTIFICATE cryptCert = *( ( CRYPT_CERTIFICATE * ) data );\n\tint certReqType, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_REQUEST || \\\n\t\t\t  type == CRYPT_SESSINFO_CACERTIFICATE || \\\n\t\t\t  type == CRYPT_SESSINFO_CMP_REQUESTTYPE || \\\n\t\t\t  type == CRYPT_SESSINFO_CMP_PRIVKEYSET );\n\n\t/* Standard CMP (with user-supplied request information) can't be \n\t   combined with plug-and-play CMP (with automatically-generated request \n\t   information) */\n\tif( ( type == CRYPT_SESSINFO_CMP_REQUESTTYPE || \\\n\t\t  type == CRYPT_SESSINFO_REQUEST ) && \\\n\t\tsessionInfoPtr->privKeyset != CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\tif( type == CRYPT_SESSINFO_CMP_PRIVKEYSET && \\\n\t\t( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE || \\\n\t\t  sessionInfoPtr->iCertRequest != CRYPT_ERROR ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, \n\t\t\t\t\t  ( sessionInfoPtr->iCertRequest != CRYPT_ERROR ) ? \\\n\t\t\t\t\t\tCRYPT_SESSINFO_REQUEST : \\\n\t\t\t\t\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( CRYPT_ERROR_INITED );\n\t\t}\n\n\t/* If it's general protocol-specific information other than a request or \n\t   certificate, set it */\n\tif( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )\n\t\t{\n\t\tconst int cmpReqType = *( ( int * ) data );\n\n\t\t/* Make sure that the value hasn't been set yet */\n\t\tif( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\n\t\t/* If the request object is already present, make sure that it \n\t\t   matches the request type.  We can't do this check unconditionally \n\t\t   because the request type may be set before the request object is \n\t\t   set */\n\t\tif( sessionInfoPtr->iCertRequest != CRYPT_ERROR )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &certReqType, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( certReqType == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\t\t{\n\t\t\t\tif( cmpReqType != CRYPT_REQUESTTYPE_INITIALISATION && \\\n\t\t\t\t\tcmpReqType != CRYPT_REQUESTTYPE_CERTIFICATE && \\\n\t\t\t\t\tcmpReqType != CRYPT_REQUESTTYPE_KEYUPDATE )\n\t\t\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( cmpReqType != CRYPT_REQUESTTYPE_REVOCATION )\n\t\t\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Set the CMP request type and tell the higher-level code that \n\t\t   further information needs to be provided before we can activate \n\t\t   the session */\n\t\tcmpInfo->requestType = cmpReqType;\n\t\tif( cmpReqType == CRYPT_REQUESTTYPE_INITIALISATION || \\\n\t\t\tcmpReqType == CRYPT_REQUESTTYPE_PKIBOOT )\n\t\t\t{\n\t\t\tsessionInfoPtr->clientReqAttrFlags = \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_USERID | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PASSWORD;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( cmpReqType == CRYPT_REQUESTTYPE_REVOCATION )\n\t\t\t\t{\n\t\t\t\tsessionInfoPtr->clientReqAttrFlags = \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVATEKEY | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_KEYORPASSWORD;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tsessionInfoPtr->clientReqAttrFlags = \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVATEKEY | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\t\t\t\t\t\t\tSESSION_NEEDS_PRIVKEYCERT;\n\t\t\t\t}\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( type == CRYPT_SESSINFO_CMP_PRIVKEYSET )\n\t\t{\n\t\tCRYPT_KEYSET privKeyset = *( ( CRYPT_KEYSET * ) data );\n\n\t\t/* Make sure that the value hasn't been set yet */\n\t\tif( sessionInfoPtr->privKeyset != CRYPT_ERROR )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\n\t\t/* Remember that we're using plug-and-play PKI functionality */\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_PNPPKI );\n\n\t\tkrnlSendNotifier( privKeyset, IMESSAGE_INCREFCOUNT );\n\t\tsessionInfoPtr->privKeyset = privKeyset;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that the request/certificate type is consistent with the \n\t   operation being performed.  The requirements for this are somewhat \n\t   more complex than the basic ACL-based check can manage, so we handle \n\t   it here with custom code */\n\tstatus = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, &certReqType, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTTYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_SESSINFO_REQUEST:\n\t\t\t{\n\t\t\tconst CRYPT_REQUESTTYPE_TYPE cmpReqType = cmpInfo->requestType;\n\n\t\t\tif( certReqType != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\t\t\tcertReqType != CRYPT_CERTTYPE_REQUEST_REVOCATION )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t\t/* If there's no CMP request type already set, we're done.  We \n\t\t\t   can't otherwise perform the checks that follow because the \n\t\t\t   request object may be set before the request type is set */\n\t\t\tif( cmpReqType == CRYPT_REQUESTTYPE_NONE )\n\t\t\t\tbreak;\n\n\t\t\t/* The request type is already present, make sure that it \n\t\t\t   matches the request object */\n\t\t\tif( certReqType == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t\t\t{\n\t\t\t\tif( cmpReqType != CRYPT_REQUESTTYPE_INITIALISATION && \\\n\t\t\t\t\tcmpReqType != CRYPT_REQUESTTYPE_CERTIFICATE && \\\n\t\t\t\t\tcmpReqType != CRYPT_REQUESTTYPE_KEYUPDATE )\n\t\t\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( cmpReqType != CRYPT_REQUESTTYPE_REVOCATION )\n\t\t\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( sessionInfoPtr, \n\t\t\t\t\t\t\t  CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_CONSTRAINT );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\t/* If it's a non-ir certificate request, make sure that there's \n\t\t\t   a subject DN present.  We perform this check because subject \n\t\t\t   DNs are optional for irs but may be required for some CMP\n\t\t\t   servers for other request types and we want to catch this \n\t\t\t   before we get into the CMP exchange itself */\n\t\t\tif( cmpReqType == CRYPT_REQUESTTYPE_CERTIFICATE || \\\n\t\t\t\tcmpReqType == CRYPT_REQUESTTYPE_KEYUPDATE )\n\t\t\t\t{\n\t\t\t\tMESSAGE_DATA msgData = { NULL, 0 };\n\n\t\t\t\tstatus = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_SUBJECTNAME,\n\t\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_CACERTIFICATE:\n\t\t\tif( certReqType != CRYPT_CERTTYPE_CERTIFICATE )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( certReqType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertReqType == CRYPT_CERTTYPE_REQUEST_CERT )\n\t\t{\n\t\tBOOLEAN_INT isImmutable;\n\n\t\t/* Make sure that everything is set up ready to go.  We don't check \n\t\t   for the object being a CA certificate when certReqType == \n\t\t   CRYPT_CERTTYPE_CERTIFICATE because we could be dealing with an \n\t\t   RA, which isn't necessarily a CA */\n\t\tstatus = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &isImmutable, CRYPT_CERTINFO_IMMUTABLE );\n\t\tif( cryptStatusError( status ) || !isImmutable )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\tMESSAGE_DATA msgData = { NULL, 0 };\n\n\t\t/* Make sure that everything is set up ready to go.  Since \n\t\t   revocation requests aren't signed like normal certificate objects \n\t\t   we can't just check the immutable attribute but have to perform a \n\t\t   dummy export for which the certificate export code will return an \n\t\t   error status if there's a problem with the request */\n\t\tstatus = krnlSendMessage( cryptCert, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Add the request and increment its usage count */\n\tkrnlSendNotifier( cryptCert, IMESSAGE_INCREFCOUNT );\n\tif( type == CRYPT_SESSINFO_CACERTIFICATE )\n\t\tsessionInfoPtr->iAuthInContext = cryptCert;\n\telse\n\t\tsessionInfoPtr->iCertRequest = cryptCert;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodCMP( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\t0,\t\t\t\t\t\t\t/* Client attributes */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server attributes */\n\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCACERT | \\\n\t\t\tSESSION_NEEDS_KEYSET | \\\n\t\t\tSESSION_NEEDS_CERTSTORE,\n\t\t2, 2, 2,\t\t\t\t\t/* Version 2 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE,\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\t\n\t\t/* Protocol-specific information */\n\t\tBUFFER_SIZE_DEFAULT\t\t\t/* Buffer size information */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\tinitCMPserverProcessing( sessionInfoPtr );\n\telse\n\t\tinitCMPclientProcessing( sessionInfoPtr );\n\tFNPTR_SET( sessionInfoPtr->shutdownFunction, shutdownFunction );\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\n\t/* Initialise CMP-specific objects */\n\tsessionInfoPtr->sessionCMP->userInfo = CRYPT_ERROR;\n\tsessionInfoPtr->sessionCMP->savedMacContext = CRYPT_ERROR;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMP Definitions Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _CMP_DEFINED\n\n#define _CMP_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tImplementation Notes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMP requires a variety of authentication contexts, which are mapped to \n   session information contexts as follows:\n\n\t\t\t|\tiAuthIn\t\t\t|\tiAuthOut\n\t--------+-------------------+-----------------------\n\tClient\t|\tCA cert\t\t\t|\tClient privKey or\n\t\t\t|\t\t\t\t\t|\t\tnone if MAC\n\tServer\t|\tClient cert or\t|\tCA privKey\n\t\t\t|\t\tnone if MAC\t|\n\n   This is complicated somewhat by the fact the iAuthOut can be one of three \n   objects, either the client or server's private key if it's signature-\n   capable, or a separate signing key on the client if it's requesting a\n   certificate for an encryption-only key, or a MAC context if no shared\n   public keys are available yet.  To avoid having to select the appropriate\n   private-key object each time that it's used we maintain a reference to the\n   appropriate one in the protocolInfo's authContext.  If we're using MAC\n   authentication then we store it in the protocolInfo's iMacContext.  Since\n   this is destroyed each time that the session is recycled we copy it to \n   and from the session state if required.  This is a little awkward but \n   keeping the sole copy in the session state is even worse because all of \n   the ephemeral MAC-related data is stored in the protocolInfo, and storing\n   the MAC context with the session state would require schlepping it around\n   alongside the protocolInfo to each location where it's needed.\n\n   The CMP message header includes a large amount of ambiguous, confusing, \n   and redundant information, we remove all of the unnecessary junk that's \n   required by the CMP spec by only sending the fields that are actually \n   useful (malum est consilium quod mutari non potest - Syrus).  Fields that \n   are completely pointless or can't be provided (sender and recipient DN, \n   nonces) are omitted entirely, fields that remain static throughout an \n   exchange (user ID information) are only sent in the first message and are \n   assumed to be the same as for the previous message if absent.  The \n   general schema for message fields during various sample exchanges is:\n\n\t\t\ttransID\tprotKeyID\tprotAlgo\t-- generalInfo data --\n\t\t\t------------------------------------------------------\n\n\tir:\t\ttransID\tuserID-user\tmac+param\tclibID\n\tip:\t\ttransID\t\t\t\tmac\t\t\tclibID\n\n\tcr:\t\ttransID\t\t\t\tsig\t\t\tclibID\tcertID-user\n\tcp:\t\ttransID\t\t\t\tsig\t\t\tclibID\tcertID-CA\n\n\tir:\t\ttransID\tuserID-user\tmac+param\tclibID\n\tip:\t\ttransID\t\t\t\tmac\t\t\tclibID\n\tcr:\t\ttransID2\t\t\tsig\t\t\t\t\tcertID-user\n\tcp:\t\ttransID2\t\t\tsig\t\t\t\t\tcertID-CA\n\n\tgenm:\ttransID\tuserID-user\tmac+param\tclibID\n\tgenp:\ttransID\t\t\t\tmac\t\t\tclibID\tcertID-CA\n\tir:\t\ttransID2\t\t\tmac\n\tip:\t\ttransID2\t\t\tmac\n\tcr:\t\ttransID3\t\t\tsig\t\t\t\t\tcertID-user\n\tcp:\t\ttransID3\t\t\tsig\n\n   The transID (= nonce) is sent in all messages and is constant during a\n   single transaction but not across a sequence of transactions.  At the\n   start of each new transaction the client generates a fresh transID and\n   sends it to the server, verifying that the same value is returned in \n   the server's response.  On the first message read in a transaction the\n   server records the client's transID and verifies it in subsequent \n   messages.\n   \n   The user ID (= protKeyID) is sent once, if absent it's assumed to be \n   \"same as previous\".  The user credentials (if MAC authentication is being \n   used) are tied to a MAC context which is maintained as part of the \n   protocol state information.  Since this is recycled on each transaction, \n   it's copied to the savedMacContext value in the session state in case \n   it's required in the following transaction.  This is necessary because \n   the creation of a MAC context is triggered by a new user ID being seen,\n   if it's \"same as previous\" then no new MAC context will be created.\n\n   (An alternative option would be to disable the user ID and MAC context\n   cacheing, but the main case where MAC authentication is used is in \n   PnPPKI where a PKIBoot is always followed by an ir, so it saves CMP \n   messaging, certificate store lookup, and context setup overhead by \n   cacheing the credentials across transactions).\n   \n   The certificate ID and MAC parameters are also sent once and if absent \n   they're similarly assumed to be \"same as previous\" (in the case of the \n   MAC parameters we simply send the MAC OID with NULL parameters to \n   indicate no change).  The cryptlib ID, a magic value used to indicate \n   that the other side is running cryptlib, is sent in the first message \n   only.\n\n   The sending of the CA certificate ID in the PKIBoot response even though \n   the response is MAC'd is necessary because we need this value to identify \n   which of the certificates in the CTL is the CA/RA certificate to be used \n   for further exchanges.  There are actually several ways in which we can \n   identify the certificate:\n\n\t1. PKIBoot response is a CTL, userID identifies the CA certificate.\n\n\t\tIssues: The userID is probably only meant to identify the \n\t\tauthenticator of the message (the spec is, as usual, unclear on \n\t\tthis), not a random certificate located elsewhere.\n\n\t2. PKIBoot response is a CTL, certID identifies the CA certificate.\n\n\t\tIssues: A less serious version of the above, we're overloading the \n\t\tcertID to some extent but since it doesn't affect CMP messages as a\n\t\twhole (as overloading the userID would) this is probably OK.\t\n\n\t3. PKIBoot response is SignedData, signer is CA certificate.\n\n\t\tIssues: Mostly nitpicks, we should probably only be sending a pure \n\t\tCTL rather than signed data, and the means of identifying the CA \n\t\tcertificate seems a bit clunky.  On one hand it provides POP of the \n\t\tCA key at the PKIBoot stage, but on the other it requires a CA \n\t\tsigning operation for every PKIBoot exchange, which is both rather \n\t\theavyweight if clients use it in a DHCP-like manner every time they\n\t\tstart up and a potential security issue if the CA signing key has to\n\t\tbe available at the CMP server.  In addition it requires a general-\n\t\tpurpose signature-capable CA key, which often isn't the case if it's \n\t\treserved specifically for certificate and CRL signing */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMP Constants\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMP version and the default port for the \"TCP transport\" kludge */\n\n#define CMP_VERSION\t\t\t\t2\t\t/* CMP version */\n\n/* Various CMP constants.  Since the cryptlib MAC keys are high-entropy \n   machine-generated values we don't have to use as many hashing iterations \n   as we would for generic passwords which are often weak, easily-guessed \n   values */\n\n#define CMP_NONCE_SIZE\t\t\t16\t\t/* Size of nonces */\n#define CMP_PW_ITERATIONS_CLIB\t500\t\t/* PW hashing iter.for clib pws */\n#define CMP_PW_ITERATIONS_OTHER\t2000\t/* PW hashing iter.for non-clib pws */\n#define CMP_MAX_PW_ITERATIONS\t10000\t/* Max allowable iterations */\n\n/* The CMP HTTP content type */\n\n#define CMP_CONTENT_TYPE\t\t\"application/pkixcmp\"\n#define CMP_CONTENT_TYPE_LEN\t19\n\n/* The CMP spec never defines any key size for the CMP/Entrust MAC, but\n   everyone seems to use 160 bits for this */\n\n#define CMP_HMAC_KEYSIZE\t\t20\n\n/* CMP protocol-specific flags that augment the general session flags.  If\n   we're running a PnP PKI session, we leave the client connection active \n   to allow for further transactions.  In order to minimise the mount of \n   junk in headers (see the comment in the implementation notes above) we \n   record when various identifiers have been sent and don't send them again \n   in subsequent messages */\n\n#define CMP_PFLAG_NONE\t\t\t0x00\t/* No protocol-specific flags */\n#define CMP_PFLAG_RETAINCONNECTION 0x01\t/* Leave conn.open for further trans.*/\n#define CMP_PFLAG_CLIBIDSENT\t0x02\t/* cryptlib ID sent */\n#define CMP_PFLAG_USERIDSENT\t0x04\t/* User ID sent */\n#define CMP_PFLAG_CERTIDSENT\t0x08\t/* Certificate ID sent */\n#define CMP_PFLAG_MACINFOSENT\t0x10\t/* MAC parameters sent */\n#define CMP_PFLAG_PNPPKI\t\t0x20\t/* Session is PnP PKI-capable */\n#define CMP_PFLAG_MAX\t\t\t0x3F\t/* Maximum possible flag value */\n\n/* Context-specific tags for the PKIHeader record */\n\nenum { CTAG_PH_MESSAGETIME, CTAG_PH_PROTECTIONALGO, CTAG_PH_SENDERKID,\n\t   CTAG_PH_RECIPKID, CTAG_PH_TRANSACTIONID, CTAG_PH_SENDERNONCE,\n\t   CTAG_PH_RECIPNONCE, CTAG_PH_FREETEXT, CTAG_PH_GENERALINFO };\n\n/* Context-specific tags for the PKIBody wrapper.  These are both context-\n   specific tags and message types so there are also extra values to handle\n   message-type indicators that don't correspond to tags.   At the moment\n   this is just a read-any indicator used by the server as a wildcard to \n   indicate that it'll accept any message that's valid as an initial client\n   message */\n\ntypedef enum { \n\tCTAG_PB_IR, CMP_MESSAGE_NONE = CTAG_PB_IR, /* _IR = 0 = _NONE */\n\tCTAG_PB_IP, CTAG_PB_CR, CTAG_PB_CP, CTAG_PB_P10CR, CTAG_PB_POPDECC, \n\tCTAG_PB_POPDECR, CTAG_PB_KUR, CTAG_PB_KUP, CTAG_PB_KRR, CTAG_PB_KRP, \n\tCTAG_PB_RR, CTAG_PB_RP, CTAG_PB_CCR, CTAG_PB_CCP, CTAG_PB_CKUANN, \n\tCTAG_PB_CANN, CTAG_PB_RANN, CTAG_PB_CRLANN, CTAG_PB_PKICONF, \n\tCTAG_PB_NESTED, CTAG_PB_GENM, CTAG_PB_GENP, CTAG_PB_ERROR, \n\tCTAG_PB_CERTCONF, \n\tCTAG_PB_READ_ANY,\t/* Special-case for match-any message */\n\tCTAG_PB_LAST, CMP_MESSAGE_LAST = CTAG_PB_LAST\t/* Last possible type */\n\t} CMP_MESSAGE_TYPE;\n\n/* Context-specific tags for the PKIMessage */\n\nenum { CTAG_PM_PROTECTION, CTAG_PM_EXTRACERTS };\n\n/* Context-specific tags for the CertifiedKeyPair in the PKIMessage */\n\nenum { CTAG_CK_CERT, CTAG_CK_ENCRYPTEDCERT, CTAG_CK_NEWENCRYPTEDCERT };\n\n/* Context-specific tags for the EncryptedValue in the CertifiedKeyPair */\n\nenum { CTAG_EV_DUMMY1, CTAG_EV_CEKALGO, CTAG_EV_ENCCEK, CTAG_EV_DUMMY2,\n\t   CTAG_EV_DUMMY3 };\n\n/* PKIStatus values */\n\nenum { PKISTATUS_OK, PKISTATUS_OK_WITHINFO, PKISTATUS_REJECTED,\n\t   PKISTATUS_WAITING, PKISTATUS_REVOCATIONIMMINENT,\n\t   PKISTATUS_REVOCATION, PKISTATUS_KEYUPDATE };\n\n/* PKIFailureInfo values */\n\n#define CMPFAILINFO_NONE\t\t\t\t0x00000000L\n#define CMPFAILINFO_OK\t\t\t\t\t0x00000000L\n#define CMPFAILINFO_BADALG\t\t\t\t0x00000001L\n#define CMPFAILINFO_BADMESSAGECHECK\t\t0x00000002L\n#define CMPFAILINFO_BADREQUEST\t\t\t0x00000004L\n#define CMPFAILINFO_BADTIME\t\t\t\t0x00000008L\n#define CMPFAILINFO_BADCERTID\t\t\t0x00000010L\n#define CMPFAILINFO_BADDATAFORMAT\t\t0x00000020L\n#define CMPFAILINFO_WRONGAUTHORITY\t\t0x00000040L\n#define CMPFAILINFO_INCORRECTDATA\t\t0x00000080L\n#define CMPFAILINFO_MISSINGTIMESTAMP\t0x00000100L\n#define CMPFAILINFO_BADPOP\t\t\t\t0x00000200L\n#define CMPFAILINFO_CERTREVOKED\t\t\t0x00000400L\n#define CMPFAILINFO_CERTCONFIRMED\t\t0x00000800L\n#define CMPFAILINFO_WRONGINTEGRITY\t\t0x00001000L\n#define CMPFAILINFO_BADRECIPIENTNONCE\t0x00002000L\n#define CMPFAILINFO_TIMENOTAVAILABLE\t0x00004000L\n#define CMPFAILINFO_UNACCEPTEDPOLICY\t0x00008000L\n#define CMPFAILINFO_UNACCEPTEDEXTENSION\t0x00010000L\n#define CMPFAILINFO_ADDINFONOTAVAILABLE\t0x00020000L\n#define CMPFAILINFO_BADSENDERNONCE\t\t0x00040000L\n#define CMPFAILINFO_BADCERTTEMPLATE\t\t0x00080000L\n#define CMPFAILINFO_SIGNERNOTTRUSTED\t0x00100000L\n#define CMPFAILINFO_TRANSACTIONIDINUSE\t0x00200000L\n#define CMPFAILINFO_UNSUPPORTEDVERSION\t0x00400000L\n#define CMPFAILINFO_NOTAUTHORIZED\t\t0x00800000L\n#define CMPFAILINFO_SYSTEMUNAVAIL\t\t0x01000000L\n#define CMPFAILINFO_SYSTEMFAILURE\t\t0x02000000L\n#define CMPFAILINFO_DUPLICATECERTREQ\t0x04000000L\n#define CMPFAILINFO_LAST\t\t\t\t0x08000000L\n\n/* Flags for initialising the protocol state information */\n\n#define CMP_INIT_FLAG_NONE\t\t\t0x00\n#define CMP_INIT_FLAG_USERID\t\t0x01\n#define CMP_INIT_FLAG_TRANSID\t\t0x02\n#define CMP_INIT_FLAG_MACINFO\t\t0x04\n#define CMP_INIT_FLAG_MACCTX\t\t0x08\n#define CMP_INIT_FLAG_ALL\t\t\t( CMP_INIT_FLAG_USERID | \\\n\t\t\t\t\t\t\t\t\t  CMP_INIT_FLAG_TRANSID | \\\n\t\t\t\t\t\t\t\t\t  CMP_INIT_FLAG_MACINFO | \\\n\t\t\t\t\t\t\t\t\t  CMP_INIT_FLAG_MACCTX )\n#define CMP_INIT_FLAG_MAX\t\t\t0x0F\n\n/* The OID for the Entrust MAC */\n\n#define OID_ENTRUST_MAC\tMKOID( \"\\x06\\x09\\x2A\\x86\\x48\\x86\\xF6\\x7D\\x07\\x42\\x0D\" )\n\n/* When we're writing the payload of a CMP message, we use a shared function\n   for most payload types because they're all pretty similar.  The following\n   values distinguish between the message classes that can be handled by a\n   single write function */\n\ntypedef enum {\n\tCMPBODY_NONE, CMPBODY_NORMAL, CMPBODY_CONFIRMATION, CMPBODY_ACK, \n\tCMPBODY_GENMSG, CMPBODY_ERROR, CMPBODY_LAST\n\t} CMPBODY_TYPE;\n\n/* CMP uses so many unnecessary EXPLICIT tags that we define a macro to\n   make it easier to evaluate the encoded sizes of objects tagged in this\n   manner */\n\n#define objSize( length )\t( ( int ) sizeofObject( length ) )\n\n/* The following macro can be used to enable dumping of PDUs to disk.  As a\n   safeguard, this only works in the Win32 debug version to prevent it from\n   being accidentally enabled in any release version */\n\n#if defined( __WIN32__ ) && !defined( NDEBUG )\n  #define DEBUG_DUMP_CMP( type, level, sessionInfo ) \\\n\t\t  debugDumpCMP( type, level, sessionInfo )\n\n  STDC_NONNULL_ARG( ( 3 ) ) \\\n  void debugDumpCMP( IN_ENUM( CMP_MESSAGE ) const CMP_MESSAGE_TYPE type, \n\t\t\t\t\t IN_RANGE( 1, 4 ) const int phase,\n\t\t\t\t\t const SESSION_INFO *sessionInfoPtr );\n#else\n  #define DEBUG_DUMP_CMP( type, level, sessionInfo )\n#endif /* Win32 debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMP Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMP protocol state information.  This is passed around various\n   subfunctions that handle individual parts of the protocol */\n\ntypedef struct {\n\t/* Session state information.  We record the operation being carried\n\t   out so that we can make decisions about message validity and contents \n\t   when reading/writing fields, and whether the other side is a cryptlib \n\t   implementation, which both allows us to work around some of the \n\t   braindamage in CMP since we know that the other side will do the \n\t   right thing and lets us include extra information required to avoid \n\t   CMP shortcomings.  We also record whether we're the server or the \n\t   client for use in situations where the overall session state isn't \n\t   available, this is used for diagnostic purposes to allow the display\n\t   of more specific error messages */\n\tint operation;\t\t\t\t\t\t\t/* genm/ir/cr/kur/rr */\n\tBOOLEAN isCryptlib;\t\t\t\t\t\t/* Whether peer is cryptlib */\n\tBOOLEAN isServer;\t\t\t\t\t\t/* Whether we're the server */\n\n\t/* Identification/state variable information.  The userID is either the\n\t   CA-supplied user ID value (for MAC'd messages) or the \n\t   subjectKeyIdentifier (for signed messages).  The sender and recipient\n\t   nonces change roles each at message turnaround (even though this is\n\t   totally unnecessary), so as we go through the various portions of the\n\t   protocol the different nonces slowly shift through the two values.\n\t   In order to accommodate nonstandard implementations, we allow for\n\t   nonces that are slightly larger than the required size.\n\t   \n\t   When using a persistent connection, the user information can change \n\t   over successive transactions.  If a new transaction arrives whose \n\t   user ID or certID differs from the previous one, we set the \n\t   userID/certID-changed flag to tell the higher-level code to update \n\t   the information that it has stored.\n\t   \n\t   If we encounter an error when reading the peer's PKI header, we can't\n\t   easily send a CMP error response because the information that we need\n\t   to create the CMP message may not have been read properly.  To handle\n\t   this we set the headerRead flag if the header has been successfully\n\t   read and if not, bail out rather than trying to create a response\n\t   based on incomplete information */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, userIDsize ) \\\n\tBYTE userID[ CRYPT_MAX_TEXTSIZE + 8 ];\t/* User ID */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, transIDsize ) \\\n\tBYTE transID[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Transaction nonce */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, certIDsize ) \\\n\tBYTE certID[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Sender certificate ID */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, senderNonceSize ) \\\n\tBYTE senderNonce[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Sender nonce */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, recipNonceSize ) \\\n\tBYTE recipNonce[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Recipient nonce */\n\tint userIDsize, transIDsize, certIDsize, senderNonceSize, recipNonceSize;\n\tBOOLEAN userIDchanged, certIDchanged;\t/* Whether ID information same as prev.*/\n\tBOOLEAN headerRead;\t\t\t\t\t\t/* Whether header read successfully */\n\n\t/* Usually the key that we're getting a certificate for is signature-\n\t   capable but sometimes we need to certify an encryption-only key.  In \n\t   this case we can't use the private key that created the request to \n\t   authenticate it but have to use a separate signing key, typically one \n\t   that we had certified before getting the encryption-only key certified.  \n\t   To keep things simple we keep a reference to whichever object is \n\t   being used for authentication to avoid having to explicitly select it\n\t   each time that it's used */\n\tBOOLEAN cryptOnlyKey;\t\t\t\t\t/* Whether key being cert'd is encr-only */\n\tCRYPT_CONTEXT authContext;\n\n\t/* When processing CMP data, we need to remember the last cryptlib error\n\t   status value we encountered and the last CMP extended failure value so\n\t   that we can send it to the remote client/server in an error response */\n\tint status;\t\t\t\t\t\t\t\t/* Last error status */\n\tlong pkiFailInfo;\t\t\t\t\t\t/* Last extended failure status */\n\n\t/* The information needed to verify message integrity.  Typically we\n\t   use a MAC, however in some cases the data isn't MAC'd but signed by\n\t   the user or CA, in which case we use the user private key to sign or\n\t   CA certificate to verify instead of MAC'ing it.  If we're signing,\n\t   we clear the useMACsend flag, if we're verifying we clear the\n\t   useMACreceive flag (in theory the two should match, but there are\n\t   implementations that use MACs one way and sigs the other).\n\t   \n\t   In addition to the standard MAC password there's also an alternative\n\t   MAC password that may be used to authenticated revocations.  Since \n\t   this doesn't fit into the conventional username+password model, we \n\t   keep a copy here in case it's needed to process a MAC'd revocation\n\t   request */\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t\t\t/* Hash algo for signature */\n\tint hashParam;\t\t\t\t\t\t\t/* Optional parameter for hash algo.*/\n\tCRYPT_CONTEXT iMacContext;\t\t\t\t/* MAC context */\n\tBUFFER( CRYPT_MAX_HASHSIZE, saltSize ) \\\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];\t/* MAC password salt  */\n\tint saltSize;\n\tint iterations;\t\t\t\t\t\t\t/* MAC password iterations */\n\tBYTE altMacKey[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint altMacKeySize;\t\t\t\t\t\t/* Alt.MAC key for revocations */\n\tBOOLEAN useMACsend, useMACreceive;\t\t/* Use MAC to verify integrity */\n\n\t/* Whether the certificate issue is being authorised by an RA user \n\t   rather than a standard user */\n\tBOOLEAN userIsRA;\n\n\t/* Other protocol information.  CMP uses an extremely clunky \n\t   confirmation mechanism in which a certificate conf uses as its hash \n\t   algorithm the algorithm that was used in a previous message by the CA \n\t   to sign the certificate, which means implementations will break each \n\t   time a new certificate format or CA hash algorithm is added since the \n\t   CMP transport-level code is now dependent on the format of the data \n\t   that it carries.  In order to support this content-coupling of \n\t   protocol and data we record the hash algorithm when we receive the \n\t   CA's reply so that it can be used later */\n\tCRYPT_ALGO_TYPE confHashAlgo;\t\t\t/* Certificate conf.hash algo */\n\n\t/* Pointers to parsed data in the current message, required to work \n\t   around CMP design flaws.  This is used by lower-level decoding \n\t   routines to return information needed by higher-level ones.  The MAC \n\t   information position records the position of the MAC information (we \n\t   can't set up the MAC information until we've read the sender key ID, \n\t   but the MAC information is sent first, so we have to go back and \n\t   re-process it once we've got the sender key ID).  The sender DN \n\t   pointer records the DN of the key used to sign the message if we're \n\t   not talking to a cryptlib peer (the DN is ambiguous and can't \n\t   properly identify the sender, so we only use it if there's no \n\t   alternative) */\n\tint macInfoPos;\t\t\t\t\t\t\t/* Position of MAC information in stream */\n\tBUFFER_OPT_FIXED( senderDNlength ) \\\n\tvoid *senderDNPtr;\n\tint senderDNlength;\t\t\t\t\t\t/* Position of auth.key ID in stream */\n\t} CMP_PROTOCOL_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMP Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* CMP message read/write methods for the different message types */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\n\t\tint ( *READMESSAGE_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t\t\t   IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int messageLength );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\n\t\tint ( *WRITEMESSAGE_FUNCTION )( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t\tINOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tconst CMP_PROTOCOL_INFO *protocolInfo );\n\nCHECK_RETVAL_PTR \\\nREADMESSAGE_FUNCTION getMessageReadFunction( IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType );\nCHECK_RETVAL_PTR \\\nWRITEMESSAGE_FUNCTION getMessageWriteFunction( IN_ENUM( CMPBODY ) \\\n\t\t\t\t\t\t\t\t\tconst CMPBODY_TYPE bodyType,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isServer );\n\n/* Prototypes for functions in cmp.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionCMP( IN const SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_RANGE( CMP_MESSAGE_NONE, CMP_MESSAGE_LAST - 1 ) \\\nint reqToResp( IN_ENUM_OPT( CMP_MESSAGE ) const CMP_MESSAGE_TYPE reqType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setCMPprotocolInfo( INOUT CMP_PROTOCOL_INFO *protocolInfo, \n\t\t\t\t\t\tIN_BUFFER_OPT( userIDlength ) const void *userID, \n\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int userIDlength, \n\t\t\t\t\t\tIN_FLAGS_Z( CMP_INIT ) const int flags,\n\t\t\t\t\t\tconst BOOLEAN isCryptlib );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPprotocolInfo( OUT CMP_PROTOCOL_INFO *protocolInfo, \n\t\t\t\t\t\t  const BOOLEAN isCryptlib,\n\t\t\t\t\t\t  const BOOLEAN isServer );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroyCMPprotocolInfo( INOUT CMP_PROTOCOL_INFO *protocolInfo );\n\n/* Prototypes for functions in cmp_cli/cmp_svr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initServerAuthentMAC( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initServerAuthentSign( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPserverProcessing( SESSION_INFO *sessionInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPclientProcessing( SESSION_INFO *sessionInfoPtr );\n\n/* Prototypes for functions in cmp_cry.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashMessageContents( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t IN_BUFFER( length ) const void *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint initMacInfo( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t IN_LENGTH_SHORT const int passwordLength, \n\t\t\t\t IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t IN_LENGTH_SHORT const int saltLength, \n\t\t\t\t IN_RANGE( 1, CMP_MAX_PW_ITERATIONS ) const int iterations );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readMacInfo( INOUT STREAM *stream, \n\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t IN_LENGTH_SHORT const int passwordLength,\n\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeMacInfo( INOUT STREAM *stream,\n\t\t\t\t  const CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t  const BOOLEAN sendFullInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkMessageMAC( INOUT STREAM *stream, \n\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t IN_BUFFER( messageLength ) const void *message,\n\t\t\t\t\t IN_DATALENGTH const int messageLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint checkMessageSignature( INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t   IN_BUFFER( messageLength ) const void *message,\n\t\t\t\t\t\t   IN_DATALENGTH const int messageLength,\n\t\t\t\t\t\t   IN_BUFFER( signatureLength ) const void *signature,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iAuthContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 6 ) ) \\\nint writeMacProtinfo( IN_HANDLE const CRYPT_CONTEXT iMacContext,\n\t\t\t\t\t  IN_BUFFER( messageLength ) const void *message, \n\t\t\t\t\t  IN_LENGTH_SHORT const int messageLength,\n\t\t\t\t\t  OUT_BUFFER( protInfoMaxLength, *protInfoLength ) \\\n\t\t\t\t\t\t\tvoid *protInfo, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int protInfoMaxLength,\n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( protInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *protInfoLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4, 6, 8 ) ) \\\nint writeSignedProtinfo( IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t IN_RANGE( 0, 999 ) const int hashParam,\n\t\t\t\t\t\t IN_BUFFER( messageLength ) const void *message, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int messageLength,\n\t\t\t\t\t\t OUT_BUFFER( protInfoMaxLength, *protInfoLength ) \\\n\t\t\t\t\t\t\t\tvoid *protInfo, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int protInfoMaxLength,\n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( protInfoMaxLength ) \\\n\t\t\t\t\t\t\t\tint *protInfoLength );\n\n/* Prototypes for functions in cmp_err.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readPkiStatusInfo( INOUT STREAM *stream, \n\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL_LENGTH_SHORT_NOERROR \\\nint sizeofPkiStatusInfo( IN_STATUS const int pkiStatus,\n\t\t\t\t\t\t IN_ENUM_OPT( CMPFAILINFO ) const long pkiFailureInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writePkiStatusInfo( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_STATUS const int pkiStatus,\n\t\t\t\t\t\tIN_ENUM_OPT( CMPFAILINFO ) const long pkiFailureInfo );\n\n/* Prototypes for functions in cmp_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPkiMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tINOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\tIN_ENUM_OPT( CMP_MESSAGE ) CMP_MESSAGE_TYPE messageType );\n\n/* Prototypes for functions in cmp_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writePkiMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t IN_ENUM( CMPBODY ) const CMPBODY_TYPE bodyType );\n\n/* Prototypes for functions in pnppki.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pnpPkiSession( INOUT SESSION_INFO *sessionInfoPtr );\n\n#endif /* _CMP_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/cmp_cli.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib CMP Client Management\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Map request to response types */\n\nstatic const MAP_TABLE clibReqReqMapTbl[] = {\n\t{ CRYPT_REQUESTTYPE_INITIALISATION, CTAG_PB_IR },\n\t{ CRYPT_REQUESTTYPE_CERTIFICATE, CTAG_PB_CR },\n\t{ CRYPT_REQUESTTYPE_CERTIFICATE, CTAG_PB_P10CR },\n\t{ CRYPT_REQUESTTYPE_KEYUPDATE, CTAG_PB_KUR },\n\t{ CRYPT_REQUESTTYPE_REVOCATION, CTAG_PB_RR },\n\t{ CRYPT_REQUESTTYPE_PKIBOOT, CTAG_PB_GENM },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nCHECK_RETVAL_RANGE( 0, CTAG_PB_LAST ) \\\nstatic int clibReqToReq( IN_ENUM( CRYPT_REQUESTTYPE ) const int reqType )\n\t{\n\tint value, status;\n\n\tREQUIRES( isEnumRange( reqType, CRYPT_REQUESTTYPE ) );\n\n\tstatus = mapValue( reqType, &value, clibReqReqMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( clibReqReqMapTbl, MAP_TABLE ) );\n\treturn( cryptStatusError( status ) ? status : value );\n\t}\n\n/* Set up information needed to perform a client-side transaction */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initClientInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tconst ATTRIBUTE_LIST *passwordPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( !isServer( sessionInfoPtr ) );\n\n\t/* Determine what we need to do based on the request type */\n\tstatus = protocolInfo->operation = clibReqToReq( cmpInfo->requestType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're using public key-based authentication, set up the key and \n\t   user ID information */\n\tif( cmpInfo->requestType != CRYPT_REQUESTTYPE_PKIBOOT && \\\n\t\tcmpInfo->requestType != CRYPT_REQUESTTYPE_INITIALISATION && \\\n\t\t!( cmpInfo->requestType == CRYPT_REQUESTTYPE_REVOCATION && \\\n\t\t   passwordPtr != NULL ) )\n\t\t{\n\t\t/* If it's an encryption-only key, remember this for later when we \n\t\t   need to authenticate our request messages */\n\t\tif( !checkContextCapability( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t{\n\t\t\t/* The private key can't be used for signature creation, use\n\t\t\t   the alternate authentication key instead */\n\t\t\tprotocolInfo->authContext = sessionInfoPtr->iAuthOutContext;\n\t\t\tprotocolInfo->cryptOnlyKey = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The private key that we're using is capable of authenticating \n\t\t\t   requests */\n\t\t\tprotocolInfo->authContext = sessionInfoPtr->privateKey;\n\t\t\t}\n\n\t\t/* If we're not talking to a cryptlib server, get the user ID.  If \n\t\t   it's a standard signed request the authenticating object will be \n\t\t   the private key, however if the private key is an encryption-only \n\t\t   key the message authentication key is a separate object.  To \n\t\t   handle this we get the user ID from the signing key rather than \n\t\t   automatically using the private key */\n\t\tif( !protocolInfo->isCryptlib )\n\t\t\t{\n\t\t\tMESSAGE_DATA msgData;\n\t\t\tBYTE userID[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t\tsetMessageData( &msgData, userID, CRYPT_MAX_HASHSIZE );\n\t\t\tstatus = krnlSendMessage( protocolInfo->authContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = setCMPprotocolInfo( protocolInfo, userID, \n\t\t\t\t\t\t\t\t\t\t\t msgData.length, \n\t\t\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_USERID | \\\n\t\t\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_TRANSID, FALSE );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* It's a cryptlib peer, the certificate is identified by an \n\t\t   unambiguous certificate ID and so we don't have to try and make\n\t\t   do with an arbitrary value derived from the associated public\n\t\t   key */\n\t\treturn( setCMPprotocolInfo( protocolInfo, NULL, 0, \n\t\t\t\t\t\t\t\t\tCMP_INIT_FLAG_TRANSID, TRUE ) );\n\t\t}\n\n\t/* If there's a MAC context present from a previous transaction, reuse \n\t   it for the current one.  See the discussion in cmp.h for details */\n\tif( cmpInfo->savedMacContext != CRYPT_ERROR )\n\t\t{\n\t\tstatus = setCMPprotocolInfo( protocolInfo, NULL, 0, \n\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_TRANSID, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprotocolInfo->useMACsend = protocolInfo->useMACreceive = TRUE;\n\t\tprotocolInfo->iMacContext = cmpInfo->savedMacContext;\n\t\tcmpInfo->savedMacContext = CRYPT_ERROR;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We're using MAC authentication, initialise the protocol information */\n\tREQUIRES( userNamePtr != NULL );\n\tif( TEST_FLAG( userNamePtr->flags, ATTR_FLAG_ENCODEDVALUE ) )\n\t\t{\n\t\tBYTE decodedValue[ 64 + 8 ];\n\t\tint decodedValueLength;\n\n\t\t/* It's a cryptlib-style encoded user ID, decode it into its binary \n\t\t   value */\n\t\tstatus = decodePKIUserValue( decodedValue, 64, &decodedValueLength,\n\t\t\t\t\t\t\t\t\t userNamePtr->value, \n\t\t\t\t\t\t\t\t\t userNamePtr->valueLength );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tstatus = setCMPprotocolInfo( protocolInfo, decodedValue,\n\t\t\t\t\t\t\t\t\t decodedValueLength, \n\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_ALL, TRUE );\n\t\tzeroise( decodedValue, CRYPT_MAX_TEXTSIZE );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an arbitrary non-cryptlib user ID, use it as is */\n\t\tstatus = setCMPprotocolInfo( protocolInfo, userNamePtr->value,\n\t\t\t\t\t\t\t\t\t min( userNamePtr->valueLength, \\\n\t\t\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ), \n\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_ALL, FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( passwordPtr != NULL );\n\n\t/* Set up the MAC context used to authenticate messages */\n\tif( TEST_FLAG( passwordPtr->flags, ATTR_FLAG_ENCODEDVALUE ) )\n\t\t{\n\t\tBYTE decodedValue[ 64 + 8 ];\n\t\tint decodedValueLength;\n\n\t\t/* It's a cryptlib-style encoded password, decode it into its binary \n\t\t   value */\n\t\tstatus = decodePKIUserValue( decodedValue, 64, &decodedValueLength,\n\t\t\t\t\t\t\t\t\t passwordPtr->value, \n\t\t\t\t\t\t\t\t\t passwordPtr->valueLength );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tstatus = initMacInfo( protocolInfo->iMacContext, decodedValue, \n\t\t\t\t\t\t\t  decodedValueLength, protocolInfo->salt, \n\t\t\t\t\t\t\t  protocolInfo->saltSize, \n\t\t\t\t\t\t\t  protocolInfo->iterations );\n\t\tzeroise( decodedValue, CRYPT_MAX_TEXTSIZE );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's an arbitrary non-cryptlib password, use it as is */\n\t\tstatus = initMacInfo( protocolInfo->iMacContext,\n\t\t\t\t\t\t\t  passwordPtr->value, passwordPtr->valueLength,\n\t\t\t\t\t\t\t  protocolInfo->salt, protocolInfo->saltSize,\n\t\t\t\t\t\t\t  protocolInfo->iterations );\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prepare a CMP session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientStartup( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tNET_CONNECT_INFO connectInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Make sure that we have all the needed information.  Plug-and-play PKI \n\t   uses PKIBoot to get the CA certificate and generates the requests \n\t   internally so we only need to check for these values if we're doing \n\t   standard CMP.  The check for user ID and authentication information \n\t   has already been done at the general session level */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_PNPPKI ) )\n\t\t{\n\t\tif( cmpInfo->requestType == CRYPT_REQUESTTYPE_NONE )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\tif( cmpInfo->requestType != CRYPT_REQUESTTYPE_PKIBOOT && \\\n\t\t\tsessionInfoPtr->iAuthInContext == CRYPT_ERROR )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\tif( cmpInfo->requestType != CRYPT_REQUESTTYPE_PKIBOOT && \\\n\t\t\tsessionInfoPtr->iCertRequest == CRYPT_ERROR )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\t}\n\n\t/* Connect to the remote server */\n\tstatus = initSessionNetConnectInfo( sessionInfoPtr, &connectInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sNetConnect( &sessionInfoPtr->stream, STREAM_PROTOCOL_HTTP, \n\t\t\t\t\t\t  &connectInfo, &sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NETSESSIONOPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Exchange data with a CMP server.  Since the plug-and-play PKI client \n   performs multiple transactions, we wrap the basic clientTransact() in an \n   external function that either calls it indirectly when required from the \n   PnP code or just passes the call through to the transaction function */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tCMP_PROTOCOL_INFO protocolInfo;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Check that everything we need is present.  If it's a general CMP \n\t   session this will already have been checked in clientStartup(), but\n\t   if it's coming from the PnPPKI wrapper it doesn't go through the\n\t   startup checks each time so we double-check here */\n\tREQUIRES( cmpInfo->requestType != CRYPT_REQUESTTYPE_NONE );\n\tREQUIRES( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT || \\\n\t\t\t  sessionInfoPtr->iCertRequest != CRYPT_ERROR );\n\tREQUIRES( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT || \\\n\t\t\t  sessionInfoPtr->iAuthInContext != CRYPT_ERROR );\n\n\t/* Initialise the client-side protocol state information */\n\tinitCMPprotocolInfo( &protocolInfo, \n\t\t\t\t\t\t TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t\t\t\tSESSION_FLAG_ISCRYPTLIB ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE, FALSE );\n\tstatus = initClientInfo( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"initCMPprotocolInfo\" );\n\n\t/* Write the message into the session buffer and send it to the server */\n\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo, \n\t\t\t\t\t\t\t  ( cmpInfo->requestType == \\\n\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_PKIBOOT ) ? \\\n\t\t\t\t\t\t\t  CMPBODY_GENMSG : CMPBODY_NORMAL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 1, sessionInfoPtr );\n\t\tif( ( protocolInfo.operation == CTAG_PB_GENM || \\\n\t\t\t  protocolInfo.operation == CTAG_PB_RR ) && \\\n\t\t\t!TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\tCMP_PFLAG_RETAINCONNECTION ) )\n\t\t\t{\n\t\t\t/* There's no confirmation handshake for PKIBoot or a revocation \n\t\t\t   request so we mark this as the last message if required */\n\t\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, \n\t\t\t\t\t   TRUE );\n\t\t\t}\n\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"writePkiMessage\" );\n\n\t/* Read the server response */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst int responseType = reqToResp( protocolInfo.operation );\n\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 2, sessionInfoPtr );\n\t\tif( cryptStatusError( responseType ) )\n\t\t\tstatus = responseType;\n\t\telse\n\t\t\t{\n\t\t\tstatus = readPkiMessage( sessionInfoPtr, &protocolInfo, \n\t\t\t\t\t\t\t\t\t responseType );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && protocolInfo.operation == CTAG_PB_GENM )\n\t\t{\n\t\t/* It's a PKIBoot, add the trusted certificates.  If the user wants \n\t\t   the setting made permanent then they need to flush the \n\t\t   configuration to disk after the session has completed */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CTL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t\t{\n\t\t\t\t/* If the certificates are already present, trying to add \n\t\t\t\t   them again isn't an error */\n\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tsetErrorString( SESSION_ERRINFO, \"Couldn't add trusted \"\n\t\t\t\t\t\t\t\t\"certificates from PKIBoot to trust store\", \n\t\t\t\t\t\t\t\t61 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readPkiDatagram\" );\n\n\t/* If it's a transaction type that doesn't need a confirmation, we're \n\t   done */\n\tif( protocolInfo.operation == CTAG_PB_GENM || \\\n\t\tprotocolInfo.operation == CTAG_PB_RR )\n\t\t{\n\t\t/* Remember the authentication context in case we can reuse it for \n\t\t   another transaction */\n\t\tif( protocolInfo.iMacContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tcmpInfo->savedMacContext = protocolInfo.iMacContext;\n\t\t\tprotocolInfo.iMacContext = CRYPT_ERROR;\n\t\t\t}\n\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"initCMPprotocolInfo\", \"writePkiMessage\", \n\t\t\t\t\t\t\t\t\t\t\"readPkiDatagram\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"noConfMessage\" );\n\n\t/* Exchange confirmation data with the server */\n\tINJECT_FAULT( CORRUPT_ID, SESSION_CORRUPT_ID_CMP_1 );\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\tCMP_PFLAG_RETAINCONNECTION ) )\n\t\t{\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, \n\t\t\t\t   TRUE );\n\t\t}\n\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo,\n\t\t\t\t\t\t\t  CMPBODY_CONFIRMATION );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 3, sessionInfoPtr );\n\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 4, sessionInfoPtr );\n\t\tstatus = readPkiMessage( sessionInfoPtr, &protocolInfo, CTAG_PB_PKICONF );\n\t\t}\n\tif( cryptStatusOK( status ) && protocolInfo.iMacContext != CRYPT_ERROR )\n\t\t{\n\t\t/* Remember the authentication context in case we can reuse it for \n\t\t   another transaction */\n\t\tcmpInfo->savedMacContext = protocolInfo.iMacContext;\n\t\tprotocolInfo.iMacContext = CRYPT_ERROR;\n\t\t}\n\tdestroyCMPprotocolInfo( &protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"confMessage\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"initCMPprotocolInfo\", \"writePkiMessage\", \n\t\t\t\t\t\t\t\t\t\"readPkiDatagram\", \"noConfMessage\", \n\t\t\t\t\t\t\t\t\t\"confMessage\" ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransactWrapper( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* If it's not a plug-and-play PKI session, just pass the call on down\n\t   to the client transaction function */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_PNPPKI ) )\n\t\treturn( clientTransact( sessionInfoPtr ) );\n\n\t/* We're doing plug-and-play PKI, point the transaction function at the \n\t   client-transact function while we execute the PnP steps, then reset \n\t   it back to the PnP wrapper after we're done */\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransact );\n\tstatus = pnpPkiSession( sessionInfoPtr );\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransactWrapper );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPclientProcessing( SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tFNPTR_SET( sessionInfoPtr->connectFunction, clientStartup );\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransactWrapper );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_crypt.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib CMP Crypto Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash/MAC the message header and body */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashMessageContents( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t IN_BUFFER( length ) const void *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int length )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 8 + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( data, length ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\t/* Delete the hash/MAC value, which resets the context */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the pseudoheader used for hashing/MACing the message and\n\t   hash/MAC it */\n\tsMemOpen( &stream, buffer, 8 );\n\tstatus = writeSequence( &stream, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, \n\t\t\t\t\t\t\t\t  stell( &stream ) );\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Hash/MAC the message itself */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) data, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 0 );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMAC Routines\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise the MAC information used to protect the messages */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint initMacInfo( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t IN_LENGTH_SHORT const int passwordLength, \n\t\t\t\t IN_BUFFER( saltLength ) const void *salt, \n\t\t\t\t IN_LENGTH_SHORT const int saltLength, \n\t\t\t\t IN_RANGE( 1, CMP_MAX_PW_ITERATIONS ) const int iterations )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE macKey[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isReadPtrDynamic( salt, saltLength ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( saltLength ) );\n\tREQUIRES( iterations >= 1 && iterations <= CMP_MAX_PW_ITERATIONS );\n\n\t/* Turn the password into an HMAC key using the CMP/Entrust password \n\t   derivation mechanism */\n\tsetMechanismDeriveInfo( &mechanismInfo, macKey, CMP_HMAC_KEYSIZE,\n\t\t\t\t\t\t\tpassword, passwordLength, CRYPT_ALGO_SHA1,\n\t\t\t\t\t\t\t( MESSAGE_CAST ) salt, saltLength, iterations );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, \n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_CMP );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Load the key into the MAC context */\n\tsetMessageData( &msgData, macKey, CMP_HMAC_KEYSIZE );\n\tstatus = krnlSendMessage( iMacContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_KEY );\n\tzeroise( macKey, CRYPT_MAX_HASHSIZE );\n\treturn( status );\n\t}\n\n/* Read/write the CMP/Entrust MAC information:\n\n\tmacInfo ::= SEQUENCE {\n\t\talgoID\t\t\tOBJECT IDENTIFIER (entrustMAC),\n\t\talgoParams\t\tSEQUENCE {\n\t\t\tsalt\t\tOCTET STRING,\n\t\t\tpwHashAlgo\tAlgorithmIdentifier (SHA-1)\n\t\t\titerations\tINTEGER,\n\t\t\tmacAlgo\t\tAlgorithmIdentifier (HMAC-SHA1)\n\t\t\t} OPTIONAL\n\t\t} \n\n   The standard only specifies the use of SHA1/HMAC-SHA1 (alongside the \n   usual confused text about what should actually be used, including \n   mention of options like single-DES MAC), so we only allow these \n   algorithms.  Since only we're using it as PRF rather than a hash \n   function, it doesn't require strong security properties */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint readMacInfo( INOUT STREAM *stream, \n\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t IN_BUFFER( passwordLength ) const void *password, \n\t\t\t\t IN_LENGTH_SHORT const int passwordLength,\n\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ALGO_TYPE algorithm DUMMY_INIT;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBYTE salt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tlong value DUMMY_INIT;\n\tint saltLength, tag, iterations, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( passwordLength ) );\n\n\t/* Read the various parameter fields */\n\treadSequence( stream, NULL );\n\tstatus = readFixedOID( stream, OID_ENTRUST_MAC,\n\t\t\t\t\t\t   sizeofOID( OID_ENTRUST_MAC ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we don't find the Entrust MAC OID we specifically report it \n\t\t   as an unknown algorithm problem rather than a generic bad data \n\t\t   error */\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADALG;\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \"Unrecognised password-based MAC \"\n\t\t\t\t  \"mechanism\" ) );\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == BER_NULL )\n\t\t{\n\t\t/* No parameters, use the same values as for the previous\n\t\t   transaction */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treadSequence( stream, NULL );\n\tstatus = readOctetString( stream, salt, &saltLength, 4, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAlgoID( stream, &algorithm, ALGOID_CLASS_HASH );\n\tif( cryptStatusOK( status ) && algorithm != CRYPT_ALGO_SHA1 )\n\t\tstatus = CRYPT_ERROR_NOTAVAIL;\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = readAlgoID( stream, &algorithm, ALGOID_CLASS_HASH );\n\t\tif( cryptStatusOK( status ) && algorithm != CRYPT_ALGO_HMAC_SHA1 )\n\t\t\tstatus = CRYPT_ERROR_NOTAVAIL;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid passwod-based MAC algorithm information\" ) );\n\t\t}\n\tif( value < 1 || value > CMP_MAX_PW_ITERATIONS )\n\t\t{\n\t\t/* Prevent DoS attacks due to excessive iteration counts (bad\n\t\t   algorithm is about the most appropriate error that we can return \n\t\t   here).  The spec never defines any appropriate limits for this \n\t\t   value, which leads to interesting effects when submitting a \n\t\t   request for bignum iterations to some implementations */\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADALG;\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid passwod-based MAC iteration count %ld\", \n\t\t\t\t  value ) );\n\t\t}\n\tENSURES( isIntegerRange( value ) );\n\titerations = ( int ) value;\n\n\t/* If the MAC parameters aren't set yet (meaing that we're the server), \n\t   set them based on the client's values */\n\tif( protocolInfo->saltSize <= 0 )\n\t\t{\n\t\tstatus = initMacInfo( protocolInfo->iMacContext, password,\n\t\t\t\t\t\t\t  passwordLength, salt, saltLength, iterations );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Couldn't initialise passwod-based MAC \"\n\t\t\t\t\t  \"information\" ) );\n\t\t\t}\n\t\tREQUIRES( rangeCheck( saltLength, 0, CRYPT_MAX_HASHSIZE ) );\n\t\tmemcpy( protocolInfo->salt, salt, saltLength );\n\t\tprotocolInfo->saltSize = saltLength;\n\t\tprotocolInfo->iterations = iterations;\n\t\tDEBUG_PRINT(( \"%s: Read initial MAC params with salt, %d iterations.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t  protocolInfo->iterations ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->salt, protocolInfo->saltSize );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the new parameters match our original MAC parameters, reuse the \n\t   existing MAC context.  As usual the spec is ambiguous over the use of \n\t   the MAC information, leaving it possible for implementations to re-\n\t   key the MAC on a per-message basis.  We try and cache MAC information \n\t   as much as possible to reduce the performance hit from re-keying for \n\t   each message */\n\tif( protocolInfo->iterations && \\\n\t\tsaltLength == protocolInfo->saltSize && \\\n\t\t!memcmp( salt, protocolInfo->salt, saltLength ) && \\\n\t\titerations == protocolInfo->iterations )\n\t\t{\n\t\tDEBUG_PRINT(( \"%s: Skipped repeated MAC params with salt, \"\n\t\t\t\t\t  \"%d iterations.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t  protocolInfo->iterations ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->salt, protocolInfo->saltSize );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* This is a new set of parameters, recreate the MAC context with them */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = initMacInfo( createInfo.cryptHandle, password, passwordLength,\n\t\t\t\t\t\t  salt, saltLength, iterations );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't initialise passwod-based MAC information\" ) );\n\t\t}\n\tif( protocolInfo->iMacContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( protocolInfo->iMacContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t}\n\tprotocolInfo->iMacContext = createInfo.cryptHandle;\n\n\t/* Remember the parameters that were used to set up the MAC context */\n\tREQUIRES( rangeCheck( saltLength, 0, CRYPT_MAX_HASHSIZE ) );\n\tmemcpy( protocolInfo->salt, salt, saltLength );\n\tprotocolInfo->saltSize = saltLength;\n\tprotocolInfo->iterations = iterations;\n\tDEBUG_PRINT(( \"%s: Read new MAC params with salt, %d iterations.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t  protocolInfo->iterations ));\n\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\tprotocolInfo->salt, protocolInfo->saltSize );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeMacInfo( INOUT STREAM *stream,\n\t\t\t\t  const CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t  const BOOLEAN sendFullInfo )\n\t{\n\tint paramSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sendFullInfo == TRUE || sendFullInfo == FALSE );\n\n\t/* If we've already sent the MAC parameters in an earlier transaction,\n\t   just send an indication that we're using MAC protection */\n\tif( !sendFullInfo )\n\t\t{\n\t\twriteSequence( stream, sizeofOID( OID_ENTRUST_MAC ) + sizeofNull() );\n\t\twriteOID( stream, OID_ENTRUST_MAC );\n\t\treturn( writeNull( stream, DEFAULT_TAG ) );\n\t\t}\n\n\t/* Determine how big the payload will be */\n\tparamSize = sizeofShortObject( protocolInfo->saltSize ) + \\\n\t\t\t\tsizeofAlgoID( CRYPT_ALGO_SHA1 ) + \\\n\t\t\t\tsizeofShortInteger( protocolInfo->iterations ) + \\\n\t\t\t\tsizeofAlgoID( CRYPT_ALGO_HMAC_SHA1 );\n\n\t/* Write the wrapper */\n\twriteSequence( stream, sizeofOID( OID_ENTRUST_MAC ) + \\\n\t\t\t\t\t\t   sizeofShortObject( paramSize ) );\n\twriteOID( stream, OID_ENTRUST_MAC );\n\n\t/* Write the payload */\n\tDEBUG_PRINT(( \"%s: Writing MAC params with salt, %d iterations.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t  protocolInfo->iterations ));\n\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\tprotocolInfo->salt, protocolInfo->saltSize );\n\twriteSequence( stream, paramSize );\n\twriteOctetString( stream, protocolInfo->salt, protocolInfo->saltSize,\n\t\t\t\t\t  DEFAULT_TAG );\n\twriteAlgoID( stream, CRYPT_ALGO_SHA1 );\n\twriteShortInteger( stream, protocolInfo->iterations, DEFAULT_TAG );\n\treturn( writeAlgoID( stream, CRYPT_ALGO_HMAC_SHA1 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tVerify Integrity-Protection Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check integrity protection on a message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkMessageMAC( INOUT STREAM *stream, \n\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t IN_BUFFER( messageLength ) const void *message,\n\t\t\t\t\t IN_DATALENGTH const int messageLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE macValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint macValueLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( isReadPtrDynamic( message, messageLength ) );\n\n\tREQUIRES( messageLength > 0 && messageLength < MAX_BUFFER_SIZE );\n\n\t/* Read the BIT STRING encapsulation and get a pointer to the MAC value */\n\tstatus = readBitStringHole( stream, &macValueLength, 16, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( macValueLength < MIN_HASHSIZE || \\\n\t\tmacValueLength > CRYPT_MAX_HASHSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sread( stream, macValue, macValueLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* MAC the data, and make sure that it matches the value attached to the \n\t   message */\n\tstatus = hashMessageContents( protocolInfo->iMacContext, message,\n\t\t\t\t\t\t\t\t  messageLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, macValue, macValueLength );\n\t\tstatus = krnlSendMessage( protocolInfo->iMacContext, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t  &msgData, MESSAGE_COMPARE_HASH );\n\t\tif( cryptStatusError( status ) )\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint checkMessageSignature( INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t   IN_BUFFER( messageLength ) const void *message,\n\t\t\t\t\t\t   IN_DATALENGTH const int messageLength,\n\t\t\t\t\t\t   IN_BUFFER( signatureLength ) const void *signature,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int signatureLength,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iAuthContext )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( isReadPtrDynamic( message, messageLength ) );\n\tassert( isReadPtrDynamic( signature, signatureLength ) );\n\n\tREQUIRES( messageLength > 0 && messageLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isShortIntegerRangeNZ( signatureLength ) );\n\tREQUIRES( isHandleRangeValid( iAuthContext ) );\n\n\t/* If it's a non-cryptlib message (in other words one where the \n\t   certificate/signing key isn't unambiguously identified via a certID),\n\t   make sure that the sig-check key that we'll be using is the correct \n\t   one.  Because of CMP's use of a raw signature format we have to do \n\t   this manually rather than relying on the sig-check code to do it for \n\t   us, and because of the braindamaged way of identifying integrity-\n\t   protection keys for non-cryptlib messages even this isn't enough to \n\t   definitely tell us that we're using the right key, in which case \n\t   we'll get a bad data or bad signature response from the sig-check \n\t   code */\n\tif( !protocolInfo->isCryptlib )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, protocolInfo->senderDNPtr,\n\t\t\t\t\t\tprotocolInfo->senderDNlength );\n\t\tstatus = krnlSendMessage( iAuthContext, IMESSAGE_COMPARE, &msgData,\n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_SUBJECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* A failed comparison is reported as a generic CRYPT_ERROR, \n\t\t\t   convert it into a wrong-key error if necessary */\n\t\t\treturn( ( status == CRYPT_ERROR ) ? \\\n\t\t\t\t\tCRYPT_ERROR_WRONGKEY : status );\n\t\t\t}\n\t\t}\n\n\t/* Hash the data and verify the signature */\n\tsetMessageCreateObjectInfo( &createInfo, protocolInfo->hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiHashContext = createInfo.cryptHandle;\n\tif( protocolInfo->hashParam != 0 )\n\t\t{\n\t\t/* Some hash algorithms have variable output size, in which case \n\t\t   we need to explicitly tell the context which one we're working \n\t\t   with */\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &protocolInfo->hashParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = hashMessageContents( iHashContext, message, messageLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = checkRawSignature( signature, signatureLength, \n\t\t\t\t\t\t\t\t\tiAuthContext, iHashContext );\n\t\t}\n\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCreate Integrity-Protection Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write MACd/signed message protection information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 6 ) ) \\\nint writeMacProtinfo( IN_HANDLE const CRYPT_CONTEXT iMacContext,\n\t\t\t\t\t  IN_BUFFER( messageLength ) const void *message, \n\t\t\t\t\t  IN_LENGTH_SHORT const int messageLength,\n\t\t\t\t\t  OUT_BUFFER( protInfoMaxLength, *protInfoLength ) \\\n\t\t\t\t\t\t\tvoid *protInfo, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) const int protInfoMaxLength,\n\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( protInfoMaxLength ) \\\n\t\t\t\t\t\t\tint *protInfoLength )\n\t{\n\tSTREAM macStream;\n\tMESSAGE_DATA msgData;\n\tBYTE macValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint macLength, status;\n\n\tassert( isReadPtrDynamic( message, messageLength ) );\n\tassert( isWritePtrDynamic( protInfo, protInfoMaxLength ) );\n\tassert( isWritePtr( protInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( messageLength ) );\n\tREQUIRES( protInfoMaxLength >= 16 && \\\n\t\t\t  protInfoMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( protInfo, 0, min( 16, protInfoMaxLength ) );\n\t*protInfoLength = 0;\n\n\t/* MAC the message and get the MAC value */\n\tstatus = hashMessageContents( iMacContext, message, messageLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, macValue, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iMacContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmacLength = msgData.length;\n\n\t/* Write the MAC value with BIT STRING encapsulation */\n\tsMemOpen( &macStream, protInfo, protInfoMaxLength );\n\twriteBitStringHole( &macStream, macLength, DEFAULT_TAG );\n\tstatus = swrite( &macStream, macValue, macLength );\n\tif( cryptStatusOK( status ) )\n\t\t*protInfoLength = stell( &macStream );\n\tsMemDisconnect( &macStream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4, 6, 8 ) ) \\\nint writeSignedProtinfo( IN_HANDLE const CRYPT_CONTEXT iSignContext,\n\t\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t IN_RANGE( 0, 999 ) const int hashParam,\n\t\t\t\t\t\t IN_BUFFER( messageLength ) const void *message, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int messageLength,\n\t\t\t\t\t\t OUT_BUFFER( protInfoMaxLength, *protInfoLength ) \\\n\t\t\t\t\t\t\t\tvoid *protInfo, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) \\\n\t\t\t\t\t\t\t\tconst int protInfoMaxLength,\n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( protInfoMaxLength ) \\\n\t\t\t\t\t\t\t\tint *protInfoLength )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isReadPtrDynamic( message, messageLength ) );\n\tassert( isWritePtrDynamic( protInfo, protInfoMaxLength ) );\n\tassert( isWritePtr( protInfoLength, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iSignContext ) );\n\tREQUIRES( isHashAlgo( hashAlgo ) );\n\tREQUIRES( hashParam >= 0 && hashParam <= 999 );\n\tREQUIRES( isShortIntegerRangeNZ( messageLength ) );\n\tREQUIRES( protInfoMaxLength >= 32 && \\\n\t\t\t  protInfoMaxLength < MAX_INTLENGTH_SHORT );\n\n\t/* Hash the data */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, \n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiHashContext = createInfo.cryptHandle;\n\tif( hashParam != 0 )\n\t\t{\n\t\t/* Some hash algorithms have variable output size, in which case\n\t\t   we need to explicitly tell the context which one we're working\n\t\t   with */\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &hashParam, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tstatus = hashMessageContents( iHashContext, message, messageLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Create the signature */\n\tstatus = createRawSignature( protInfo, protInfoMaxLength, \n\t\t\t\t\t\t\t\t protInfoLength, iSignContext, \n\t\t\t\t\t\t\t\t iHashContext );\n\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_err.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRead CMP (and TSP) Status Information\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1999-2009\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n/* The following code is shared between CMP and TSP due to TSP's use of\n   random elements cut & pasted from CMP without any real understanding of\n   their function or semantics */\n\n#if defined( USE_CMP ) || defined( USE_TSP )\n\n/* CMP includes a comical facility for the server to tell the client \"You\n   asked for food, I've given you a flaming telephone directory on a silver\n   platter\" (actually what it says is \"You asked for food, I've given you\n   something that isn't food but I won't tell you what\").  Like much of the\n   rest of CMP it's unclear what we're supposed to do in this situation, the\n   only implementation that's known to use this facility will return \n   something totally different from what was requested so for now we treat\n   PKISTATUS_OK_WITHINFO as an error */\n\n#define cmpStatusOK( value )\t( value == PKISTATUS_OK )\n\n/* CMP error messages */\n\ntypedef struct {\n\tconst int failureCode;\t\t\t/* CMP failure code */\n\tconst int status;\t\t\t\t/* cryptlib error status */\n\tconst char *string;\t\t\t\t/* Descriptive error message */\n\tconst int stringLength;\n\t} FAILURE_INFO;\n\nstatic const FAILURE_INFO failureInfo[] = {\n\t{ CMPFAILINFO_BADALG, CRYPT_ERROR_NOTAVAIL,\n\t  \"Unrecognized or unsupported Algorithm Identifier\", 48 },\n\t{ CMPFAILINFO_BADMESSAGECHECK, CRYPT_ERROR_SIGNATURE,\n\t  \"The integrity check failed (e.g. signature did not verify)\", 58 },\n\t{ CMPFAILINFO_BADREQUEST, CRYPT_ERROR_PERMISSION,\n\t  \"This transaction is not permitted or supported\", 46 },\n\t{ CMPFAILINFO_BADTIME, CRYPT_ERROR_FAILED,\n\t  \"The messageTime was not sufficiently close to the system time as \"\n\t  \"defined by local policy\", 88 },\n\t{ CMPFAILINFO_BADCERTID, CRYPT_ERROR_NOTFOUND,\n\t  \"No certificate could be found matching the provided criteria\", 60 },\n\t{ CMPFAILINFO_BADDATAFORMAT, CRYPT_ERROR_BADDATA,\n\t  \"The data submitted has the wrong format\", 39 },\n\t{ CMPFAILINFO_WRONGAUTHORITY, CRYPT_ERROR_FAILED,\n\t  \"The authority indicated in the request is different from the one \"\n\t  \"creating the response token\", 92 },\n\t{ CMPFAILINFO_INCORRECTDATA, CRYPT_ERROR_FAILED,\n\t  \"The requester's data is incorrect (used for notary services)\", 60 },\n\t{ CMPFAILINFO_MISSINGTIMESTAMP, CRYPT_ERROR_FAILED,\n\t  \"Timestamp is missing but should be there (by policy)\", 52 },\n\t{ CMPFAILINFO_BADPOP, CRYPT_ERROR_SIGNATURE,\n\t  \"The proof-of-possession failed\", 30 },\n\t{ CMPFAILINFO_CERTREVOKED, CRYPT_ERROR_FAILED,\n\t  \"The certificate has already been revoked\", 40 },\n\t{ CMPFAILINFO_CERTCONFIRMED, CRYPT_ERROR_FAILED,\n\t  \"The certificate has already been confirmed\", 42 },\n\t{ CMPFAILINFO_WRONGINTEGRITY, CRYPT_ERROR_FAILED,\n\t  \"Invalid integrity, password based instead of signature or vice \"\n\t  \"versa\", 68 },\n\t{ CMPFAILINFO_BADRECIPIENTNONCE, CRYPT_ERROR_FAILED,\n\t  \"Invalid recipient nonce, either missing or wrong value\", 54 },\n\t{ CMPFAILINFO_TIMENOTAVAILABLE, CRYPT_ERROR_FAILED,\n\t  \"The TSA's time source is not available\", 38 },\n\t{ CMPFAILINFO_UNACCEPTEDPOLICY, CRYPT_ERROR_INVALID,\n\t  \"The requested TSA policy is not supported by the TSA\", 52 },\n\t{ CMPFAILINFO_UNACCEPTEDEXTENSION, CRYPT_ERROR_INVALID,\n\t  \"The requested extension is not supported by the TSA\", 51 },\n\t{ CMPFAILINFO_ADDINFONOTAVAILABLE, CRYPT_ERROR_FAILED,\n\t  \"The additional information requested could not be understood or \"\n\t  \"is not available\", 80 },\n\t{ CMPFAILINFO_BADSENDERNONCE, CRYPT_ERROR_FAILED,\n\t  \"Invalid sender nonce, either missing or wrong size\", 50 },\n\t{ CMPFAILINFO_BADCERTTEMPLATE, CRYPT_ERROR_INVALID,\n\t  \"Invalid certificate template or missing mandatory information\", 61 },\n\t{ CMPFAILINFO_SIGNERNOTTRUSTED, CRYPT_ERROR_WRONGKEY,\n\t  \"Signer of the message unknown or not trusted\", 44 },\n\t{ CMPFAILINFO_TRANSACTIONIDINUSE, CRYPT_ERROR_DUPLICATE,\n\t  \"The transaction identifier is already in use\", 44 },\n\t{ CMPFAILINFO_UNSUPPORTEDVERSION, CRYPT_ERROR_NOTAVAIL,\n\t  \"The version of the message is not supported\", 43 },\n\t{ CMPFAILINFO_NOTAUTHORIZED, CRYPT_ERROR_PERMISSION,\n\t  \"The sender was not authorized to make the preceding request or \"\n\t  \"perform the preceding action\", 91 },\n\t{ CMPFAILINFO_SYSTEMUNAVAIL, CRYPT_ERROR_FAILED,\n\t  \"The request cannot be handled due to system unavailability\", 58 },\n\t{ CMPFAILINFO_SYSTEMFAILURE, CRYPT_ERROR_FAILED,\n\t  \"The request cannot be handled due to system failure\", 51 },\n\t{ CMPFAILINFO_DUPLICATECERTREQ, CRYPT_ERROR_DUPLICATE,\n\t  \"Certificate cannot be issued because a duplicate certificate \"\n\t  \"already exists\", 75 },\n\t{ CRYPT_ERROR, CRYPT_ERROR, \"Unknown PKI failure code\", 24 }, \n\t{ CRYPT_ERROR, CRYPT_ERROR, \"Unknown PKI failure code\", 24 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Map a PKI failure information value to an error string */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int getFailureInfo( OUT_BUFFER_ALLOC_OPT( *stringLength ) \\\n\t\t\t\t\t\t\t\tconst char **stringPtrPtr, \n\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *stringLength,\n\t\t\t\t\t\t   OUT_ERROR int *failureStatus,\n\t\t\t\t\t\t   OUT_INT_SHORT_Z int *failureBitPos,\n\t\t\t\t\t\t   IN_INT_Z const int value )\n\t{\n\tconst FAILURE_INFO *failureInfoPtr = NULL;\n\tint bitPos = 0, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( ( char ** ) stringPtrPtr, sizeof( char * ) ) );\n\tassert( isWritePtr( stringLength, sizeof( int ) ) );\n\tassert( isWritePtr( failureStatus, sizeof( int ) ) );\n\tassert( isWritePtr( failureBitPos, sizeof( int ) ) );\n\n\tREQUIRES( isIntegerRange( value ) );\n\n\t/* Clear return values */\n\t*stringPtrPtr = NULL;\n\t*stringLength = *failureBitPos = 0;\n\t*failureStatus = CRYPT_ERROR_FAILED;\n\n\t/* For no known reason the status is encoded as a BIT STRING instead of \n\t   an ENUMERATED so to find the appropriate failure string we have to \n\t   walk down the bit flags to find the first failure string \n\t   corresponding to a bit set in the failure information */\n\tif( value <= 0 )\n\t\t{\n\t\t*stringPtrPtr = \"Missing PKI failure code\";\n\t\t*stringLength = 24;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tLOOP_MED( i = 0,\n\t\t\t  failureInfo[ i ].failureCode != CRYPT_ERROR && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( failureInfo, FAILURE_INFO ), \n\t\t\t  i++ )\n\t\t{\n\t\tconst int failureCode = failureInfo[ i ].failureCode;\n\n\t\tif( ( failureCode & value ) == failureCode )\n\t\t\t{\n\t\t\tfailureInfoPtr = &failureInfo[ i ];\n\t\t\tbitPos = i;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( failureInfo, FAILURE_INFO ) );\n\tif( failureInfoPtr == NULL )\n\t\t{\n\t\t*stringPtrPtr = \"Unknown PKI failure code\";\n\t\t*stringLength = 24;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've got information for this failure code, return it to the \n\t   caller */\n\t*stringPtrPtr = failureInfoPtr->string;\n\t*stringLength = failureInfoPtr->stringLength;\n\t*failureStatus = failureInfoPtr->status;\n\t*failureBitPos = bitPos;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Map a cryptlib status value to PKI failure information.  Note that we use \n   a distinct mapping table rather than the general failureInfo table because \n   the mappings are multivalued, so that a single cryptlib status may \n   correspond to multiple CMP failure codes.  The mappings below are the most \n   generic ones */\n\nstatic const MAP_TABLE pkiStatusMapTbl[] = {\n\t{ CRYPT_ERROR_NOTAVAIL, CMPFAILINFO_BADALG },\n\t{ CRYPT_ERROR_SIGNATURE, CMPFAILINFO_BADMESSAGECHECK },\n\t{ CRYPT_ERROR_PERMISSION, CMPFAILINFO_BADREQUEST },\n\t{ CRYPT_ERROR_BADDATA, CMPFAILINFO_BADDATAFORMAT },\n\t{ CRYPT_ERROR_INVALID, CMPFAILINFO_BADCERTTEMPLATE },\n\t{ CRYPT_ERROR_DUPLICATE, CMPFAILINFO_DUPLICATECERTREQ },\n\t{ CRYPT_ERROR_WRONGKEY, CMPFAILINFO_SIGNERNOTTRUSTED },\n\t{ CRYPT_OK, CMPFAILINFO_OK }, { CRYPT_OK, CMPFAILINFO_OK }\n\t};\n\nstatic long getFailureBitString( IN_STATUS const int pkiStatus )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_EXT( cryptStatusError( pkiStatus ), 0 );\n\n\t/* Try and map the cryptlib status value to a CMP failure information \n\t   code.  We can't use mapValue() for this because we're mapping from a \n\t   negative value, which is used by mapValue() as the end-of-data \n\t   marker */\n\tLOOP_SMALL( i = 0,\n\t\t\t\tpkiStatusMapTbl[ i ].source != CRYPT_OK && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( pkiStatusMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\tMAP_TABLE ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( pkiStatusMapTbl[ i ].source == pkiStatus )\n\t\t\treturn( pkiStatusMapTbl[ i ].destination );\n\t\t}\n\tENSURES_EXT( LOOP_BOUND_OK, 0 );\n\tENSURES_EXT( i < FAILSAFE_ARRAYSIZE( pkiStatusMapTbl, MAP_TABLE ), 0 );\n\n\t/* We couldn't find any appropriate failure information code, don't use\n\t   one at all */\n\treturn( 0 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead Status Information\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read PKIStatus information:\n\n\tPKIStatusInfo ::= SEQUENCE {\n\t\tstatus\t\t\tINTEGER,\n\t\tdummy\t\t\tSEQUENCE ... OPTIONAL,\n\t\tfailInfo\t\tBIT STRING OPTIONAL\n\t\t} \n\n   In the usual CMP weirdness the failure information is encoded as a BIT \n   STRING instead of an ENUMERATED value, and comes with a side-order of an \n   arbitrary number of free-format text strings of unknown type or \n   function.  Although we could in theory jump through all sorts of hoops to \n   try and handle the resulting multivalued status code and multivalued \n   string data it doesn't make any sense to do so and just increases our \n   attack surface significantly, so all we do is look for the first (and in \n   all known implementations only) bit set and use that as the error value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readPkiStatusInfo( INOUT STREAM *stream, \n\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst char *failureString;\n\tlong endPos, value;\n\tint bitString = 0, bitPos, failureStringLength, failureStatus;\n\tint errorCode, tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Clear the return values */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Read the outer wrapper and status value */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusOK( status ) && !isIntegerRange( value ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo,\n\t\t\t\t  \"Invalid PKI status value\" ) );\n\t\t}\n\terrorCode = ( int ) value;\n\n\t/* Read the failure information, skipping any intervening junk that may \n\t   precede it */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_SEQUENCE )\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( !cryptStatusError( status ) && stell( stream ) < endPos )\n\t\tstatus = readBitString( stream, &bitString );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo,\n\t\t\t\t  \"Invalid PKI failure information\" ) );\n\t\t}\n\n\t/* If everything's OK, we're done */\n\tif( cmpStatusOK( errorCode ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Convert the failure code into a message string and report the result \n\t   to the caller */\n\tstatus = getFailureInfo( &failureString, &failureStringLength,\n\t\t\t\t\t\t\t &failureStatus, &bitPos, bitString );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( cryptStatusError( failureStatus ) );\n\tif( bitString == 0 )\n\t\t{\n\t\t/* If we haven't been given any specific details for the problem, \n\t\t   there's not much more that we can report.  Note that we need to\n\t\t   peform this operation after calling getFailureInfo() because\n\t\t   even though there's no returned detailed error information we're\n\t\t   still using the failure status value that's returned */\n\t\tretExt( failureStatus,\n\t\t\t\t( failureStatus, errorInfo,\n\t\t\t\t  \"%s returned nonspecific failure code\",\n\t\t\t\t  isServer ? \"Client\" : \"Server\" ) );\n\t\t}\n\tretExt( failureStatus,\n\t\t\t( failureStatus, errorInfo,\n\t\t\t  \"%s returned error code %X (bit %d): %s\",\n\t\t\t  isServer ? \"Client\" : \"Server\", bitString, bitPos, \n\t\t\t  failureString ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite Status Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write PKIStatus information:\n\n\tPKIStatusInfo ::= SEQUENCE {\n\t\tstatus\t\t\tINTEGER,\n\t\tfailInfo\t\tBIT STRING OPTIONAL\n\t\t} */\n\nCHECK_RETVAL_LENGTH_SHORT_NOERROR \\\nint sizeofPkiStatusInfo( IN_STATUS const int pkiStatus,\n\t\t\t\t\t\t IN_ENUM_OPT( CMPFAILINFO ) const long pkiFailureInfo )\n\t{\n\tlong localPKIFailureInfo;\n\n\tREQUIRES( cryptStatusOK( pkiStatus ) || cryptStatusError( pkiStatus ) );\n\tREQUIRES( pkiFailureInfo >= CMPFAILINFO_OK && \\\n\t\t\t  pkiFailureInfo < CMPFAILINFO_LAST );\n\t\t\t  /* The failure code is another piece of CMP stupidity, it \n\t\t\t     looks like an enum but it's actually a bit flag, however we\n\t\t\t\t only ever set one bit in it so we treat it as an enum for \n\t\t\t\t checking purposes.  In addition there's a no-error status \n\t\t\t\t CMPFAILINFO_OK that has the same value as CMPFAILINFO_NONE \n\t\t\t\t so we use _OPT and >= 0 for the low range check */\n\t\n\t/* If it's an OK status then there's just a single integer value */\n\tif( cryptStatusOK( pkiStatus ) )\n\t\treturn( objSize( sizeofShortInteger( PKISTATUS_OK ) ) );\n\n\t/* Return the size of the error status and optional extended error \n\t   code */\n\tlocalPKIFailureInfo = ( pkiFailureInfo != CMPFAILINFO_OK ) ? \\\n\t\t\t\t\t\t  pkiFailureInfo : getFailureBitString( pkiStatus );\n\treturn( objSize( sizeofShortInteger( PKISTATUS_REJECTED ) + \\\n\t\t\t\t\t ( ( localPKIFailureInfo != CMPFAILINFO_OK ) ? \\\n\t\t\t\t\t\tsizeofBitString( localPKIFailureInfo ) : 0 ) ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writePkiStatusInfo( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_STATUS const int pkiStatus,\n\t\t\t\t\t\tIN_ENUM_OPT( CMPFAILINFO ) const long pkiFailureInfo )\n\t{\n\tlong localPKIFailureInfo;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( cryptStatusOK( pkiStatus ) || cryptStatusError( pkiStatus ) );\n\tREQUIRES( pkiFailureInfo >= CMPFAILINFO_OK && \\\n\t\t\t  pkiFailureInfo < CMPFAILINFO_LAST );\n\t\t\t  /* The failure code is another piece of CMP stupidity, it \n\t\t\t     looks like an enum but it's actually a bit flag, however we\n\t\t\t\t only ever set one bit in it so we treat it as an enum for \n\t\t\t\t checking purposes.  In addition there's a no-error status \n\t\t\t\t CMPFAILINFO_OK that has the same value as CMPFAILINFO_NONE \n\t\t\t\t so we use _OPT and >= 0 for the low range check */\n\n\t/* If it's an OK status then there's just a single integer value */\n\tif( cryptStatusOK( pkiStatus ) )\n\t\t{\n\t\twriteSequence( stream, sizeofShortInteger( PKISTATUS_OK ) );\n\t\treturn( writeShortInteger( stream, PKISTATUS_OK, DEFAULT_TAG ) );\n\t\t}\n\n\t/* Write the error status and optional extended error code */\n\tlocalPKIFailureInfo = ( pkiFailureInfo != CMPFAILINFO_OK ) ? \\\n\t\t\t\t\t\t  pkiFailureInfo : getFailureBitString( pkiStatus );\n\tif( localPKIFailureInfo == CMPFAILINFO_OK )\n\t\t{\n\t\t/* There's no extended error code, just write a basic failure \n\t\t   status */\n\t\twriteSequence( stream, sizeofShortInteger( PKISTATUS_REJECTED ) );\n\t\treturn( writeShortInteger( stream, PKISTATUS_REJECTED, DEFAULT_TAG ) );\n\t\t}\n\twriteSequence( stream, sizeofShortInteger( PKISTATUS_REJECTED ) + \\\n\t\t\t\t\t\t   sizeofBitString( localPKIFailureInfo ) );\n\twriteShortInteger( stream, PKISTATUS_REJECTED, DEFAULT_TAG );\n\treturn( writeBitString( stream, localPKIFailureInfo, DEFAULT_TAG ) );\n\t}\n#endif /* USE_CMP || USE_TSP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead CMP Messages\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the kitchen-sink field in the PKI header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readGeneralInfoAttribute( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tBYTE oid[ MAX_OID_SIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\t/* Read the attribute.  Since there are only two attribute types that we \n\t   use, we hardcode the read in here rather than performing a general-\n\t   purpose attribute read */\n\treadSequence( stream, NULL );\n\tstatus = readEncodedOID( stream, oid, MAX_OID_SIZE, &length, \n\t\t\t\t\t\t\t BER_OBJECT_IDENTIFIER );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Process the cryptlib presence-check value */\n\tif( length == sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) && \\\n\t\t!memcmp( oid, OID_CRYPTLIB_PRESENCECHECK, length ) )\n\t\t{\n\t\t/* The other side is running cryptlib, we can make some common-sense \n\t\t   assumptions about its behaviour */\n\t\tprotocolInfo->isCryptlib = TRUE;\n\t\treturn( readUniversal( stream ) );\t\t\t/* Attribute */\n\t\t}\n\n\t/* Check for the ESSCertID, which fixes CMP's broken certificate \n\t   identification mechanism */\n\tif( length == sizeofOID( OID_ESS_CERTID ) && \\\n\t\t!memcmp( oid, OID_ESS_CERTID, length ) )\n\t\t{\n\t\tBYTE certID[ CRYPT_MAX_HASHSIZE + 8 ];\n\t\tint certIDsize, endPos;\n\n\t\t/* Extract the certificate hash from the ESSCertID */\n\t\treadSet( stream, NULL );\t\t\t\t\t/* Attribute */\n\t\treadSequence( stream, NULL );\t\t\t\t/* SigningCerts */\n\t\treadSequence( stream, NULL );\t\t\t\t/* Certs */\n\t\tstatus = readSequence( stream, &length );\t/* ESSCertID */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tendPos = stell( stream ) + length;\n\t\tstatus = readOctetString( stream, certID, &certIDsize, \n\t\t\t\t\t\t\t\t  KEYID_SIZE, KEYID_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( protocolInfo->certIDsize != KEYID_SIZE || \\\n\t\t\tmemcmp( certID, protocolInfo->certID, KEYID_SIZE ) )\n\t\t\t{\n\t\t\t/* The certificate used for authentication purposes has changed,\n\t\t\t   remember the new certID */\n\t\t\tmemcpy( protocolInfo->certID, certID, KEYID_SIZE );\n\t\t\tprotocolInfo->certIDsize = KEYID_SIZE;\n\t\t\tprotocolInfo->certIDchanged = TRUE;\n\t\t\t}\n\t\tif( stell( stream ) < endPos )\n\t\t\t{\n\t\t\t/* Skip the issuerSerial if there's one present.  We can't \n\t\t\t   really do much with it in this form without rewriting it into \n\t\t\t   the standard issuerAndSerialNumber, but in any case we don't \n\t\t\t   need it because we've already got the certificate ID */\n\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* It's something that we don't recognise, skip it */\n\treturn( readUniversal( stream ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readGeneralInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tlong endPos;\n\tint length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\t/* Go through the various attributes looking for anything that we can\n\t   use */\n\treadConstructed( stream, NULL, CTAG_PH_GENERALINFO );\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tLOOP_MED_CHECK( stell( stream ) < endPos )\n\t\t{\n\t\tstatus = readGeneralInfoAttribute( stream, protocolInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n\n/* Read the user ID in the PKI header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readUserID( INOUT STREAM *stream, \n\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tBYTE userID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint userIDsize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\t/* Read the PKI user ID that we'll need to handle the integrity \n\t   protection on the message */\n\treadConstructed( stream, NULL, CTAG_PH_SENDERKID );\n\tstatus = readOctetString( stream, userID, &userIDsize, 8, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( userIDsize >= 8 && userIDsize <= CRYPT_MAX_HASHSIZE );\n\n\t/* If there's already been a previous transaction (which means that we \n\t   have PKI user information present) and the current transaction \n\t   matches what was used in the previous one, we don't have to update \n\t   the user information */\n\tif( protocolInfo->userIDsize == userIDsize && \\\n\t\t!memcmp( protocolInfo->userID, userID, userIDsize ) )\n\t\t{\n\t\tDEBUG_PRINT(( \"%s: Skipped repeated userID.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->userID, protocolInfo->userIDsize );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Record the new or changed the PKI user information and delete the \n\t   MAC context associated with the previous user if necessary */\n\tREQUIRES( rangeCheck( userIDsize, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( protocolInfo->userID, userID, userIDsize );\n\tprotocolInfo->userIDsize = userIDsize;\n\tprotocolInfo->userIDchanged = TRUE;\n\tif( protocolInfo->iMacContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( protocolInfo->iMacContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tprotocolInfo->iMacContext = CRYPT_ERROR;\n\t\t}\n\tDEBUG_PRINT(( \"%s: Read new userID.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\tprotocolInfo->userID, protocolInfo->userIDsize );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the transaction ID (effectively the nonce) in the PKI header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readTransactionID( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t  const BOOLEAN isServerInitialMessage )\n\t{\n\tBYTE buffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( isServerInitialMessage == TRUE || \\\n\t\t\t  isServerInitialMessage == FALSE );\n\n\t/* If this is the first message and we're the server, record the \n\t   transaction ID for later */\n\tif( isServerInitialMessage )\n\t\t{\n\t\tstatus = readOctetString( stream, protocolInfo->transID,\n\t\t\t\t\t\t\t\t  &protocolInfo->transIDsize,\n\t\t\t\t\t\t\t\t  4, CRYPT_MAX_HASHSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"%s: Read initial transID.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->transID, protocolInfo->transIDsize );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that the transaction ID for this message matches the \n\t   recorded value (the bad signature error code is the best that we can \n\t   provide here) */\n\tstatus = readOctetString( stream, buffer, &length, 4, \n\t\t\t\t\t\t\t  CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( length >= 4 && length <= CRYPT_MAX_HASHSIZE );\n\tDEBUG_PRINT(( \"%s: Read transID.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\tprotocolInfo->transID, protocolInfo->transIDsize );\n\tif( protocolInfo->transIDsize != length || \\\n\t\tmemcmp( protocolInfo->transID, buffer, length ) )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the integrity protection algorithm information in the PKI header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readProtectionAlgo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo, hashAlgo;\n\tint hashParam, streamPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\t/* Read the wrapper.  If there's a problem we exit immediately since an \n\t   error status from the readAlgoIDex() that follows is interpreted to \n\t   indicate the presence of the weird Entrust MAC rather than a real \n\t   error */\n\tstatus = readConstructed( stream, NULL, CTAG_PH_PROTECTIONALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamPos = stell( stream );\n\tstatus = readAlgoIDex( stream, &cryptAlgo, &hashAlgo, &hashParam,\n\t\t\t\t\t\t   ALGOID_CLASS_PKCSIG );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Make sure that it's a recognised signature algorithm to avoid\n\t\t   false positives if the other side sends some bizarre algorithm \n\t\t   ID */\n\t\tif( !isSigAlgo( cryptAlgo ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t/* It's a recognised signature algorithm, use the CA certificate to \n\t\t   verify it rather than the MAC */\n\t\tprotocolInfo->useMACreceive = FALSE;\n\t\tprotocolInfo->hashAlgo = hashAlgo;\n\t\tprotocolInfo->hashParam = hashParam;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( cryptStatusError( status ) );\n\n\t/* It's nothing normal, it must be the Entrust MAC algorithm information, \n\t   remember where it starts so that we can process it later */\n\tsClearError( stream );\n\tprotocolInfo->macInfoPos = streamPos;\n\tstatus = readUniversal( stream );\n\tprotocolInfo->useMACreceive = TRUE;\n\n\treturn( status );\n\t}\n\n/* Update the session's user ID and certificate ID information from the \n   newly-read protocol information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint updateUserID( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t  const BOOLEAN isServerInitialMessage,\n\t\t\t\t  const BOOLEAN useMAC )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( isServerInitialMessage == TRUE || \\\n\t\t\t  isServerInitialMessage == FALSE );\n\tREQUIRES( useMAC == TRUE || useMAC == FALSE );\n\n\t/* We've got a new PKI user ID, if it looks like a cryptlib encoded ID \n\t   save it in encoded form, otherwise save it as is.  Again, CMP's\n\t   totally ambiguous protocol fields complicate things for us because \n\t   although in theory we could reject any message containing a \n\t   non-cryptlib user ID on the basis that it couldn't have been assigned \n\t   to the user by a cryptlib server, the fact that an arbitrary client \n\t   could be sending us who knows what sort of data in the user ID field, \n\t   expecting the key to be identified through other means, means that we \n\t   can't perform this simple check.  We can at least reject a \n\t   non-cryptlib ID for the ir, which must be MAC'd */\n\tif( isServer( sessionInfoPtr ) && protocolInfo->userIDsize == 9 )\n\t\t{\n\t\tchar encodedUserID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint encodedUserIDLength;\n\n\t\tstatus = encodePKIUserValue( encodedUserID, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t &encodedUserIDLength, \n\t\t\t\t\t\t\t\t\t protocolInfo->userID, \n\t\t\t\t\t\t\t\t\t protocolInfo->userIDsize, 3 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t\tencodedUserID, encodedUserIDLength, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, ATTR_FLAG_ENCODEDVALUE );\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're processing an ir then that at least must have a valid \n\t\t   cryptlib user ID */\n\t\tif( isServerInitialMessage && useMAC )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,\n\t\t\t\t\t  \"User ID provided by client isn't a cryptlib user \"\n\t\t\t\t\t  \"ID\" ) );\n\t\t\t}\n\n\t\t/* It's not a valid cryptlib PKI user ID, save it anyway since\n\t\t   it'll be used for diagnostic/error-reporting purposes */\n\t\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\tprotocolInfo->userID,\n\t\t\t\t\t\t\t\t\tprotocolInfo->userIDsize,\n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, ATTR_FLAG_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If this is the first message to the server and we're using MAC-based\n\t   authentication, set up the server's MAC context based on the \n\t   information supplied by the client */\n\tif( isServerInitialMessage && useMAC )\n\t\treturn( initServerAuthentMAC( sessionInfoPtr, protocolInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint updateCertID( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t  const BOOLEAN isServerInitialMessage )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( isServerInitialMessage == TRUE || \\\n\t\t\t  isServerInitialMessage == FALSE );\n\n\tstatus = addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t  protocolInfo->certID,\n\t\t\t\t\t\t\t  protocolInfo->certIDsize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If this is the first message to the server, set up the server's \n\t   public-key context for the client's key based on the information\n\t   supplied by the client */\n\tif( isServerInitialMessage )\n\t\treturn( initServerAuthentSign( sessionInfoPtr, protocolInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* In another piece of brilliant design, CMP provides the information \n   required to set up MAC processing in reverse order, so we don't know what \n   to do with any MAC information that may be present in the header until \n   we've read the start of the message body.  To handle this we have to \n   record the position of the MAC information in the header and then go back \n   and process it once we've read the necessary additional data from the \n   message body, which is handled by the following function */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int updateMacInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t  const BOOLEAN isRevocation )\n\t{\n\tconst ATTRIBUTE_LIST *passwordPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tBYTE macKey[ 64 + 8 ];\n\tBOOLEAN decodedMacKey = FALSE;\n\tconst void *macKeyPtr;\n\tconst int streamPos = stell( stream );\n\tint macKeyLength, status;\n\n\tREQUIRES( isRevocation == TRUE || isRevocation == FALSE );\n\tREQUIRES( passwordPtr != NULL );\n\n\tsseek( stream, protocolInfo->macInfoPos );\n\tif( isRevocation && protocolInfo->altMacKeySize > 0 )\n\t\t{\n\t\t/* If it's a revocation and we're using a distinct revocation\n\t\t   password (which we've already decoded into a MAC key), use\n\t\t   that */\n\t\tmacKeyPtr = protocolInfo->altMacKey;\n\t\tmacKeyLength = protocolInfo->altMacKeySize;\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a standard issue (or we're using the same password/key\n\t\t   for the issue and revocation), use that */\n\t\tif( TEST_FLAG( passwordPtr->flags, ATTR_FLAG_ENCODEDVALUE ) )\n\t\t\t{\n\t\t\t/* It's an encoded value, get the decoded form */\n\t\t\tmacKeyPtr = macKey;\n\t\t\tstatus = decodePKIUserValue( macKey, 64, &macKeyLength, \n\t\t\t\t\t\t\t\t\t\t passwordPtr->value, \n\t\t\t\t\t\t\t\t\t\t passwordPtr->valueLength );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\tdecodedMacKey = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tmacKeyPtr = passwordPtr->value;\n\t\t\tmacKeyLength = passwordPtr->valueLength;\n\t\t\t}\n\t\t}\n\tstatus = readMacInfo( stream, protocolInfo, macKeyPtr,\n\t\t\t\t\t\t  macKeyLength, SESSION_ERRINFO );\n\tif( decodedMacKey )\n\t\tzeroise( macKey, 64 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsseek( stream, streamPos );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead a PKI Header\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a PKI header and make sure that it matches the header that we sent\n   (for EE or non-initial CA/RA messages) or set up the EE information in\n   response to an initial message (for an initial CA/RA message).  We ignore\n   all of the redundant fields in the header that don't directly affect the\n   protocol, based on the results of CMP interop testing this appears to be\n   standard practice among implementers.  This also helps get around \n   problems with implementations that get the fields wrong, since most of \n   the fields aren't useful it doesn't affect the processing while making \n   the code more tolerant of implementation errors:\n\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t\tsenderDN\t[4]\tEXPLICIT DirectoryName,\t\t-- Copied if non-clib\n\t\tdummy\t\t[4]\tEXPLICIT DirectoryName,\t\t-- Ignored\n\t\tdummy\t\t[0] EXPLICIT GeneralisedTime OPT,-- Ignored\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier,\n\t\tprotKeyID\t[2] EXPLICIT OCTET STRING,\t\t-- Copied if changed\n\t\tdummy\t\t[3] EXPLICIT OCTET STRING OPT,\t-- Ignored\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING,\n\t\tnonce\t\t[5] EXPLICIT OCTET STRING OPT,\t-- Copied if non-clib\n\t\tdummy\t\t[6] EXPLICIT OCTET STRING OPT,\t-- Ignored\n\t\tdummy\t\t[7] SEQUENCE OF UTF8String OPT,\t-- Ignored\n\t\tgeneralInfo\t[8] EXPLICIT SEQUENCE OF Info OPT -- cryptlib-specific info\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readPkiHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo,\n\t\t\t\t\t\t  const BOOLEAN isServerInitialMessage )\n\t{\n\tint tag, length, endPos, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isServerInitialMessage == TRUE || \\\n\t\t\t  isServerInitialMessage == FALSE );\n\n\t/* Clear per-message state information */\n\tprotocolInfo->userIDchanged = protocolInfo->certIDchanged = \\\n\t\tprotocolInfo->useMACreceive = FALSE;\n\tprotocolInfo->macInfoPos = CRYPT_ERROR;\n\tprotocolInfo->senderDNPtr = NULL;\n\tprotocolInfo->senderDNlength = 0;\n\tprotocolInfo->headerRead = FALSE;\n\n\t/* Read the wrapper and skip the static information, which matches what \n\t   we sent and is protected by the MAC so there's little point in \n\t   looking at it */\n\tstatus = readSequence( stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\treadShortInteger( stream, NULL );\t\t/* Version */\n\tif( !protocolInfo->isCryptlib )\n\t\t{\n\t\t/* The ID of the key used for integrity protection (or in general\n\t\t   the identity of the sender) can be specified either as the sender\n\t\t   DN or the senderKID or both, or in some cases even indirectly via\n\t\t   the transaction ID.  With no real guidance as to which one to \n\t\t   use, implementors are using any of these options to identify the \n\t\t   key.  Since we need to check that the integrity-protection key \n\t\t   that we're using is correct so that we can report a more \n\t\t   appropriate error than bad signature or bad data, we need to \n\t\t   remember the sender DN for later in case this is the only form of \n\t\t   key identification provided.  Unfortunately since the sender DN \n\t\t   can't uniquely identify a certificate, if this is the only \n\t\t   identifier that we're given then the caller can still get a bad \n\t\t   signature error, yet another one of CMPs many wonderful features */\n\t\tstatus = readConstructed( stream, &protocolInfo->senderDNlength, 4 );\n\t\tif( cryptStatusOK( status ) && protocolInfo->senderDNlength > 0 )\n\t\t\t{\n\t\t\tstatus = sMemGetDataBlock( stream, &protocolInfo->senderDNPtr, \n\t\t\t\t\t\t\t\t\t   protocolInfo->senderDNlength );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = readUniversal( stream );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* cryptlib includes a proper certID so the whole signer\n\t\t   identification mess is avoided and we can ignore the sender DN */\n\t\tstatus = readUniversal( stream );\t/* Sender DN */\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readUniversal( stream );\t/* Recipient DN */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_MESSAGETIME ) )\n\t\tstatus = readUniversal( stream );\t/* Message time */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid DN information in PKI header\" ) );\n\t\t}\n\tif( !checkStatusPeekTag( stream, status, tag ) || \\\n\t\ttag != MAKE_CTAG( CTAG_PH_PROTECTIONALGO ) )\n\t\t{\n\t\t/* The message was sent without integrity protection, report it as\n\t\t   a signature error rather than the generic bad data error that\n\t\t   we'd get from the following read */\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, errorInfo, \n\t\t\t\t  \"Message was sent without integrity protection\" ) );\n\t\t}\n\tstatus = readProtectionAlgo( stream, protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid integrity protection information in PKI \"\n\t\t\t\t  \"header\" ) );\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_SENDERKID ) )\n\t\t{\t\t\t\t\t\t\t\t/* Sender protection keyID */\n\t\tstatus = readUserID( stream, protocolInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid PKI user ID in PKI header\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're the server, the client must provide a PKI user ID in the\n\t\t   first message unless we got one in an earlier transaction */\n\t\tif( isServerInitialMessage && protocolInfo->userIDsize <= 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Missing PKI user ID in PKI header\" ) );\n\t\t\t}\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_RECIPKID ) )\n\t\t{\n\t\t/* Recipient protection keyID */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Record the transaction ID (which is effectively the nonce) or make \n\t   sure that it matches the one that we sent.  There's no real need to \n\t   do an explicit duplicate check since a replay attempt will be \n\t   rejected as a duplicate by the certificate store and the locking \n\t   performed at that level makes it a much better place to catch \n\t   duplicates, but we do it anyway because it doesn't cost anything and\n\t   we can catch at least some problems a bit earlier */\n\tstatus = readConstructed( stream, NULL, CTAG_PH_TRANSACTIONID );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Missing transaction ID in PKI header\" ) );\n\t\t}\n\tstatus = readTransactionID( stream, protocolInfo, \n\t\t\t\t\t\t\t\tisServerInitialMessage );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADRECIPIENTNONCE;\n\t\tretExt( status, \n\t\t\t\t( status, errorInfo, \n\t\t\t\t  ( status == CRYPT_ERROR_SIGNATURE ) ? \\\n\t\t\t\t  \"Returned message transaction ID doesn't match our \"\n\t\t\t\t\t\t\"transaction ID\" : \\\n\t\t\t\t  \"Invalid transaction ID in PKI header\" ) );\n\t\t}\n\n\t/* Read the sender nonce, which becomes the new recipient nonce, and skip\n\t   the recipient nonce if there's one present.  These values may be\n\t   absent, either because the other side doesn't implement them or\n\t   because they're not available, for example because it's sending a\n\t   response to an error that occurred before it could read the nonce from\n\t   a request.  In any case we don't bother checking the nonce values\n\t   since the transaction ID serves the same purpose */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_SENDERNONCE ) )\n\t\t{\n\t\treadConstructed( stream, NULL, CTAG_PH_SENDERNONCE );\n\t\tstatus = readOctetString( stream, protocolInfo->recipNonce,\n\t\t\t\t\t\t\t\t  &protocolInfo->recipNonceSize,\n\t\t\t\t\t\t\t\t  4, CRYPT_MAX_HASHSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADSENDERNONCE;\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid sender nonce in PKI header\" ) );\n\t\t\t}\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_RECIPNONCE ) )\n\t\t{\n\t\treadConstructed( stream, NULL, CTAG_PH_RECIPNONCE );\n\t\tstatus = readUniversal( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADRECIPIENTNONCE;\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid recipient nonce in PKI header\" ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\t/* Residual error from peekTag() */\n\n\t/* Remember that we've successfully read enough of the header \n\t   information to generate a response */\n\tprotocolInfo->headerRead = TRUE;\n\n\t/* Skip any further junk and process the general information if there is \n\t   any */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_FREETEXT ) )\n\t\t{\n\t\t/* Skip junk */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( CTAG_PH_GENERALINFO ) )\n\t\t{\n\t\tstatus = readGeneralInfo( stream, protocolInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, errorInfo, \n\t\t\t\t\t  \"Invalid generalInfo information in PKI header\" ) );\n\t\t\t}\n\t\t}\n\n\treturn( cryptStatusError( status ) ? status : CRYPT_OK );\n\t}\t\t/* checkStatusLimitsPeekTag() can return tag as status */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead a PKI Message\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a PKI message:\n\n\tPkiMessage ::= SEQUENCE {\n\t\theader\t\t\tPKIHeader,\n\t\tbody\t\t\tCHOICE { [0]... [24]... },\n\t\tprotection\t[0]\tBIT STRING\n\t\t}\n\n   Note that readPkiDatagram() has already performed an initial valid-ASN.1\n   check before we get here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readPkiMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tINOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\tIN_ENUM_OPT( CMP_MESSAGE ) CMP_MESSAGE_TYPE messageType )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &sessionInfoPtr->errorInfo;\n#endif /* USE_ERRMSGS */\n\tREADMESSAGE_FUNCTION readMessageFunction;\n\tSTREAM stream;\n\tconst BOOLEAN isServerInitialMessage = \\\n\t\t\t\t\t( messageType == CTAG_PB_READ_ANY ) ? TRUE : FALSE;\n\tvoid *integrityInfoPtr DUMMY_INIT_PTR;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint protPartStart DUMMY_INIT, protPartSize, bodyStart DUMMY_INIT;\n\tint length, integrityInfoLength, tag, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( ( messageType >= CTAG_PB_IR && \\\n\t\t\t\tmessageType < CTAG_PB_LAST ) || \\\n\t\t\t  ( messageType == CTAG_PB_READ_ANY ) );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\n\tDEBUG_PRINT(( \"%s: Reading message type %d.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", messageType ));\n\n\t/* Strip off the header and PKIStatus wrapper */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = readSequence( &stream, NULL );\t\t/* Outer wrapper */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprotPartStart = stell( &stream );\n\t\tstatus = readPkiHeader( &stream, protocolInfo, SESSION_ERRINFO,\n\t\t\t\t\t\t\t\tisServerInitialMessage );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tENSURES( protocolInfo->transIDsize > 0 && \\\n\t\t\t protocolInfo->transIDsize <= CRYPT_MAX_HASHSIZE );\n\tCFI_CHECK_UPDATE( \"readPkiHeader\" );\n\n\t/* Set up session state information based on the header that we've just \n\t   read */\n\tif( protocolInfo->isCryptlib )\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISCRYPTLIB );\n\n\t/* In order to fix CMP's inability to properly identify keys via \n\t   certificates, we use the certID field in the generalInfo.  If there's\n\t   no PKI user ID present but no certID either then we can't identify \n\t   the key that's needed in order to continue.  This also retroactively \n\t   invalidates the headerRead flag, since we don't know which key to use\n\t   to authenticate our response.\n\n\t   In theory we shouldn't ever get into this state because we require \n\t   a PKI user ID for the client's initial message and the server will\n\t   always send a certID for its signing certificate, but due to the\n\t   confusing combination of values that can affect the protocol state\n\t   (see the start of writePkiHeader() in cmp_wr.c for an example) we\n\t   do the following as a safety check to catch potential problems \n\t   early.\n\t   \n\t   This also leads to a special-case exception, if we're the client then\n\t   the server may identify its signing key purely through the \n\t   dysfunctional sender DN mechanism (see the comment in \n\t   readPkiHeader()) so we allow this option as well.  The DN can't \n\t   usefully tell us whether it's the correct key or not (see the\n\t   comment in checkMessageSignature()) but there's not much else that\n\t   we can do */\n\tif( protocolInfo->useMACreceive )\n\t\t{\n\t\t/* There is one special-case situation in which we can have no user \n\t\t   ID present and that's when we're doing a PnP PKI transaction with \n\t\t   an initial PKIBoot that creates the required MAC context followed \n\t\t   by an ir that doesn't need to send any ID information since it's \n\t\t   reusing the MAC context that was created by the PKIBoot */\n\t\tif( protocolInfo->userIDsize <= 0 && \\\n\t\t\t!( protocolInfo->isCryptlib && \\\n\t\t\t   protocolInfo->iMacContext != CRYPT_ERROR ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tprotocolInfo->headerRead = FALSE;\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Missing PKI user ID for MAC authentication of PKI \"\n\t\t\t\t\t  \"messages\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* As with the case for MAC contexts, there's a special-case \n\t\t   situation in which there's no certID present and that's during a \n\t\t   PnP PKI transaction preceded by a PKIBoot that communicates the \n\t\t   CA's certificate, where the PKIBoot creates the required \n\t\t   sig-check context as part of the initialisation process.  In\n\t\t   addition we have to allow for DN-only identification from \n\t\t   servers, see the comment above for details */\n\t\tif( protocolInfo->certIDsize <= 0 && \\\n\t\t\t( !isServer( sessionInfoPtr ) && \n\t\t\t  protocolInfo->senderDNlength <= 0 ) && \\\n\t\t\t!( protocolInfo->isCryptlib && \\\n\t\t\t   sessionInfoPtr->iAuthInContext != CRYPT_ERROR ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tprotocolInfo->headerRead = FALSE;\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Missing certificate ID for signature authentication \"\n\t\t\t\t\t  \"of PKI messages\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If this is the first message from the client and we've been sent a \n\t   new user ID or certificate ID (via the ESSCertID in the header's\n\t   kitchen-sink field, used to identify the signing certificate when\n\t   signature-based authentication is used), process the user/\n\t   authentication information */\n\tif( protocolInfo->userIDchanged )\n\t\t{\n\t\tstatus = updateUserID( sessionInfoPtr, protocolInfo,\n\t\t\t\t\t\t\t   isServerInitialMessage, \n\t\t\t\t\t\t\t   protocolInfo->useMACreceive );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tif( protocolInfo->certIDchanged )\n\t\t{\n\t\tstatus = updateCertID( sessionInfoPtr, protocolInfo,\n\t\t\t\t\t\t\t   isServerInitialMessage );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateUserID\" );\n\n\t/* Determine the message body type.  An error response can occur at any\n\t   point in an exchange so we process this immediately.  We don't do an\n\t   integrity verification for this one since it's not certain what we\n\t   should report if the check fails (what if the error response is to\n\t   report that no key is available to authenticate the user, for \n\t   example?), and an unauthenticated error message is better than an \n\t   authenticated paketewhainau */\n\tstatus = tag = peekTag( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttag = EXTRACT_CTAG( tag );\n\tif( tag == CTAG_PB_ERROR )\n\t\t{\n\t\treadMessageFunction = getMessageReadFunction( CTAG_PB_ERROR );\n\t\tENSURES( readMessageFunction != NULL );\n\t\treadConstructed( &stream, NULL, CTAG_PB_ERROR );\n\t\tstatus = readSequence( &stream, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = readMessageFunction( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  protocolInfo, CTAG_PB_ERROR, \n\t\t\t\t\t\t\t\t\t\t  length );\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\n\t\t/* Reading an error response always returns an error status since \n\t\t   what we're reading is a report of an error, so we perform the CFI\n\t\t   check even in the presence of an error status */\n\t\tENSURES( cryptStatusError( status ) );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"readPkiHeader\", \"updateUserID\" ) );\n\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readError\" );\n\n\t/* If this is an initial message then we don't know what to expect yet \n\t   so we set the type to whatever we find, as long as it's a valid \n\t   message to send to a CA */\n\tif( messageType == CTAG_PB_READ_ANY )\n\t\t{\n\t\tif( tag == CTAG_PB_IR || tag == CTAG_PB_CR || \\\n\t\t\ttag == CTAG_PB_P10CR || tag == CTAG_PB_KUR || \\\n\t\t\ttag == CTAG_PB_RR || \\\n\t\t\t( messageType == CTAG_PB_READ_ANY && tag == CTAG_PB_GENM ) )\n\t\t\t{\n\t\t\tprotocolInfo->operation = messageType = tag;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADREQUEST;\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Client sent invalid initial message type %d\", \n\t\t\t\t\t  tag ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Make sure that this is what we're after */\n\t\tif( tag != messageType )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADREQUEST;\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid message type, expected %d, got %d\", \n\t\t\t\t\t  messageType, tag ) );\n\t\t\t}\n\t\t}\n\n\t/* If we're using a MAC for authentication, we can finally set up the\n\t   MAC information using the appropriate password.  We couldn't do this \n\t   when we read the header because the order of the information used to \n\t   set this up is backwards, so we have to go back and re-process it \n\t   now */\n\tif( protocolInfo->useMACreceive )\n\t\t{\n\t\tstatus = updateMacInfo( sessionInfoPtr, protocolInfo, &stream,\n\t\t\t\t\t\t\t\t( messageType == CTAG_PB_RR ) ? TRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateMacInfo\" );\n\n\t/* Remember where the message body starts and skip it (it'll be \n\t   processed after we verify its integrity) */\n\tstatus = readConstructed( &stream, &length, messageType );\n\tif( cryptStatusOK( status ) && !isIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK ( status ) )\n\t\t{\n\t\tbodyStart = stell( &stream );\n\t\tstatus = sSkip( &stream, length, SSKIP_MAX );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADDATAFORMAT;\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid message body start\" ) );\n\t\t}\n\n\t/* Read the start of the message integrity information */\n\tprotPartSize = stell( &stream ) - protPartStart;\n\tENSURES( isShortIntegerRangeNZ( protPartSize ) );\n\tstatus = readConstructed( &stream, &integrityInfoLength,\n\t\t\t\t\t\t\t  CTAG_PM_PROTECTION );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = sMemGetDataBlock( &stream, &integrityInfoPtr, \n\t\t\t\t\t\t\t\t   integrityInfoLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the integrity protection is missing report it as a wrong-\n\t\t   integrity-information problem, the closest that we can get to the \n\t\t   real error */\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_WRONGINTEGRITY;\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, errorInfo, \n\t\t\t\t  \"Signature/MAC data is missing or truncated\" ) );\n\t\t}\n\tif( tag == CTAG_PB_IR && !protocolInfo->useMACreceive )\n\t\t{\n\t\t/* An ir has to be MAC'd, in theory this doesn't really matter but\n\t\t   the spec requires that we only allow a MAC.  If it's not MAC'd it\n\t\t   has to be a cr, which is exactly the same only different */\n\t\tsMemDisconnect( &stream );\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_WRONGINTEGRITY;\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, errorInfo, \n\t\t\t\t  \"Received signed ir, should be MAC'd\" ) );\n\t\t}\n\tANALYSER_HINT( integrityInfoPtr != NULL );\n\tCFI_CHECK_UPDATE( \"readIntegrityInfo\" );\n\n\t/* Verify the message integrity.  We convert any error that we encounter \n\t   during this check to a CRYPT_ERROR_SIGNATURE, this is somewhat \n\t   overreaching since it could have been something like a formatting \n\t   error but overall the problem is in the signature-check so we make \n\t   this explicit rather than returning a somewhat vague underflow/\n\t   overflow/bad-data/whatever */\n\tif( protocolInfo->useMACreceive )\n\t\t{\n\t\tstatus = checkMessageMAC( &stream, protocolInfo, \n\t\t\t\t\t\tsessionInfoPtr->receiveBuffer + protPartStart,\n\t\t\t\t\t\tprotPartSize  );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Bad message MAC\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = checkMessageSignature( protocolInfo,\n\t\t\t\t\t\tsessionInfoPtr->receiveBuffer + protPartStart,\n\t\t\t\t\t\tprotPartSize, integrityInfoPtr, integrityInfoLength, \n\t\t\t\t\t\tsessionInfoPtr->iAuthInContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( status == CRYPT_ERROR_WRONGKEY )\n\t\t\t\t{\n\t\t\t\t/* Provide a more specific error message for the wrong-key \n\t\t\t\t   error */\n\t\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Message signature key doesn't match our \"\n\t\t\t\t\t\t  \"signature check key, signature can't be \"\n\t\t\t\t\t\t  \"checked\" ) );\n\t\t\t\t}\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t\t   \"Bad message signature\" ) );\n\t\t\t}\n\t\t}\n\tsseek( &stream, bodyStart );\n\tCFI_CHECK_UPDATE( \"checkIntegrityInfo\" );\n\n\t/* In the usual CMP tradition there's a nonstandard way used to encode\n\t   one of the message types, which we have to handle specially here */\n\tif( messageType == CTAG_PB_PKICONF )\n\t\t{\n\t\tstatus = readNull( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"readPkiHeader\", \"updateUserID\", \n\t\t\t\t\t\t\t\t\t\t\"readError\", \"updateMacInfo\", \n\t\t\t\t\t\t\t\t\t\t\"readIntegrityInfo\", \n\t\t\t\t\t\t\t\t\t\t\"checkIntegrityInfo\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"pkiConf\" );\n\n\t/* Read the message body wrapper */\n\tstatus = readSequence( &stream, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Process the message body */\n\treadMessageFunction = getMessageReadFunction( messageType );\n\tif( readMessageFunction == NULL )\n\t\t{\n\t\tDEBUG_DIAG(( \"No message-read function available for message \"\n\t\t\t\t\t \"type %d\", messageType ));\n\t\tassert( DEBUG_WARN );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Unexpected message type %d\", messageType ) );\n\t\t}\n\tstatus = readMessageFunction( &stream, sessionInfoPtr, protocolInfo,\n\t\t\t\t\t\t\t\t  messageType, length );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"readMessageFunction\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"readPkiHeader\", \"updateUserID\", \n\t\t\t\t\t\t\t\t\t\"readError\", \"updateMacInfo\", \n\t\t\t\t\t\t\t\t\t\"readIntegrityInfo\", \"checkIntegrityInfo\", \n\t\t\t\t\t\t\t\t\t\"pkiConf\", \"readMessageFunction\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_rdmsg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead CMP Message Types\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if 0\t/* 12/6/09 Due to a bug in the buffer-positioning the following code \n\t\t\t\t   hasn't actually worked since 3.2.1 in 2005, since this \n\t\t\t\t   hasn't caused any complaints we disable it for attack-\n\t\t\t\t   surface reduction */\n\n/* Read a certificate encrypted with CMP's garbled reinvention of CMS \n   content:\n\n\tEncryptedCert ::= SEQUENCE {\n\t\tdummy1\t\t\t[0]\t... OPTIONAL,\t\t-- Ignored\n\t\tcekAlg\t\t\t[1]\tAlgorithmIdentifier,-- CEK algorithm\n\t\tencCEK\t\t\t[2]\tBIT STRING,\t\t\t-- Encrypted CEK\n\t\tdummy2\t\t\t[3]\t... OPTIONAL,\t\t-- Ignored\n\t\tdummy3\t\t\t[4] ... OPTIONAL,\t\t-- Ignored\n\t\tencData\t\t\tBIT STRING\t\t\t\t-- Encrypted certificate\n\t\t} \n\n   This muddle is only applied for non-cryptlib sessions, if two cryptlib\n   implementations are communicating then the certificate is wrapped using \n   CMS */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nstatic int readEncryptedDataInfo( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  OUT_BUFFER_ALLOC( *encDataLength ) \\\n\t\t\t\t\t\t\t\t\t\tvoid **encDataPtrPtr, \n\t\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\t\t\t\tint *encDataLength, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int minLength,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 32 ) const int maxLength )\n\t{\n\tvoid *dataPtr;\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( encDataPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( encDataLength, sizeof( int ) ) );\n\n\tREQUIRES( minLength >= 32 && minLength < maxLength && \\\n\t\t\t  minLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\t*encDataPtrPtr = NULL;\n\t*encDataLength = 0;\n\n\t/* Read and remember the encrypted data */\n\tstatus = readBitStringHole( stream, &length, minLength, \n\t\t\t\t\t\t\t\tCTAG_EV_ENCCEK );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*encDataPtrPtr = dataPtr;\n\t*encDataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int readEncryptedCert( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iImportContext,\n\t\t\t\t\t\t\t  OUT_BUFFER( outDataMaxLength, *outDataLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *outData, \n\t\t\t\t\t\t\t  IN_DATALENGTH_MIN( 16 ) const int outDataMaxLength,\n\t\t\t\t\t\t\t  OUT_DATALENGTH_Z int *outDataLength, \n\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CONTEXT iSessionKey;\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tQUERY_INFO queryInfo;\n\tvoid *encKeyPtr = DUMMY_INIT_PTR, *encCertPtr;\n\tint encKeyLength = DUMMY_INIT, encCertLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iImportContext ) );\n\n\t/* Read the CEK algorithm identifier and encrypted CEK.  All of the\n\t   values are optional although there's no indication of why or what\n\t   you're supposed to do if they're not present (OTOH for others there's\n\t   no indication of what you're supposed to do when they're present\n\t   either) so we treat an absent required value as an error and ignore\n\t   the others */\n\tstatus = readSequence( stream, NULL );\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_EV_DUMMY1 ) )\t/* Junk */\n\t\tstatus = readUniversal( stream );\n\tif( !cryptStatusError( status ) )\t\t\t/* CEK algo */\n\t\tstatus = readContextAlgoID( stream, &iSessionKey, &queryInfo,\n\t\t\t\t\t\t\t\t\tCTAG_EV_CEKALGO );\n\tif( !cryptStatusError( status ) )\t\t\t/* Enc.CEK */\n\t\tstatus = readEncryptedDataInfo( stream, &encKeyPtr, &encKeyLength, \n\t\t\t\t\t\t\t\t\t\tMIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid encrypted certificate CEK information\" ) );\n\t\t}\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_EV_DUMMY2 ) )\n\t\tstatus = readUniversal( stream );\t\t/* Junk */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( CTAG_EV_DUMMY3 ) )\n\t\tstatus = readUniversal( stream );\t\t/* Junk */\n\tif( !cryptStatusError( status ) )\n\t\tstatus = readEncryptedDataInfo( stream, &encCertPtr, &encCertLength,\n\t\t\t\t\t\t\t\t\t\t128, 8192 );\n\tif( !cryptStatusError( status ) &&\t\t\t/* Enc.certificate */\n\t\t( queryInfo.cryptMode == CRYPT_MODE_ECB || \\\n\t\t  queryInfo.cryptMode == CRYPT_MODE_CBC ) )\n\t\t{\n\t\tint blockSize;\n\n\t\t/* Make sure that the data length is valid.  Checking at this point\n\t\t   saves a lot of unnecessary processing and allows us to return a\n\t\t   more meaningful error code */\n\t\tstatus = krnlSendMessage( iSessionKey, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\t( queryInfo.size % blockSize ) != 0 )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Invalid encrypted certificate data\" ) );\n\t\t}\n\n\t/* Import the wrapped session key into the session key context */\n\tsetMechanismWrapInfo( &mechanismInfo, encKeyPtr, encKeyLength,\n\t\t\t\t\t\t  NULL, 0, iSessionKey, iImportContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_PKCS1 );\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't decrypt encrypted certificate CEK\" ) );\n\t\t}\n\n\t/* Decrypt the returned certificate and copy the result back to the\n\t   caller.  We don't worry about padding because the certificate-import\n\t   code knows when to stop based on the encoded certificate data */\n\tstatus = krnlSendMessage( iSessionKey, IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t  encCertPtr, encCertLength );\n\tkrnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tregisterCryptoFailure();\n\t\tretExt( status,\n\t\t\t\t( status, errorInfo, \n\t\t\t\t  \"Couldn't decrypt returned encrypted certificate using \"\n\t\t\t\t  \"CEK\" ) );\n\t\t}\n\treturn( attributeCopyParams( outData, outDataMaxLength, outDataLength, \n\t\t\t\t\t\t\t\t encCertPtr, encCertLength ) );\n\t}\n#endif /* 0 */\n\n/* Process a request that's (supposedly) been authorised by an RA rather \n   than coming directly from a user */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nstatic int processRARequest( INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t IN_HANDLE const CRYPT_CERTIFICATE iCertRequest,\n\t\t\t\t\t\t\t IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCertRequest ) );\n\tREQUIRES( messageType >= CTAG_PB_IR && messageType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\n\t/* If the user isn't an RA then this can't be an RA-authorised request */\n\tif( !protocolInfo->userIsRA )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo, \n\t\t\t\t  \"Request supposedly from an RA didn't come from an actual \"\n\t\t\t\t  \"RA user\" ) );\n\t\t}\n\n\t/* An RA-authorised request can only be a CR.  They can't be an IR \n\t   because they need to be signed, and they can't be a KUR or RR because \n\t   we assume that users will be updating and revoking their own \n\t   certificates, it doesn't make much sense to require an RA for this */\n\tif( messageType != CTAG_PB_CR )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo, \n\t\t\t\t  \"Request type %d supposedly from an RA is of the wrong \"\n\t\t\t\t  \"type, should be %d\", messageType, CTAG_PB_CR ) );\n\t\t}\n\n\t/* It's an RA-authorised request, mark the request as such */\n\treturn( krnlSendMessage( iCertRequest, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t MESSAGE_VALUE_TRUE, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_REQFROMRA ) );\n\t}\n\n/* Try and obtain more detailed information on why a certificate request\n   wasn't compatible with stored PKI user information.  Note that the\n   mapping table below is somewhat specific to the implementation of \n   copyPkiUserToCertReq() in certs/comp_pkiu.c, we hardcode a few common \n   cases here and use a generic error message for the rest */\n\n#ifdef USE_ERRMSGS\n\ntypedef struct {\n\tconst CRYPT_ATTRIBUTE_TYPE errorLocus;\n\tconst CRYPT_ERRTYPE_TYPE errorType;\n\tconst char *errorString;\n\t} EXT_ERROR_MAP_INFO;\n\nstatic const EXT_ERROR_MAP_INFO extErrorMapTbl[] = {\n\t{ CRYPT_CERTINFO_SUBJECTNAME, CRYPT_ERRTYPE_ISSUERCONSTRAINT,\n\t  \"Certificate request DN differs from PKI user DN\" },\n\t{ CRYPT_CERTINFO_SUBJECTNAME, CRYPT_ERRTYPE_ATTR_ABSENT,\n\t  \"Certificate request contains an empty DN\" },\n\t{ CRYPT_CERTINFO_SUBJECTALTNAME, CRYPT_ERRTYPE_ISSUERCONSTRAINT,\n\t  \"Certificate request subjectAltName conflicts with PKI user \"\n\t  \"subjectAltName\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, CRYPT_ERRTYPE_ATTR_ABSENT,\n\t  \"Certificate request DN is missing a CommonName\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, CRYPT_ERRTYPE_ISSUERCONSTRAINT,\n\t  \"Certificate request CommonName differs from PKI user CommonName\" },\n\t{ CRYPT_ATTRIBUTE_NONE, CRYPT_ERRTYPE_NONE, NULL },\n\t\t{ CRYPT_ATTRIBUTE_NONE, CRYPT_ERRTYPE_NONE, NULL }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int reportExtendedCertErrorInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tIN_ERROR const int errorStatus )\n\t{\n\tconst EXT_ERROR_MAP_INFO *extErrorInfoPtr = NULL;\n\tint errorType, errorLocus DUMMY_INIT, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( cryptStatusError( errorStatus ) );\n\n\t/* Try and get further details on what went wrong */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &errorType,\n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_ERRORTYPE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &errorLocus,\n\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_ERRORLOCUS );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We couldn't get any further information, return a generic error\n\t\t   message */\n\t\tretExt( errorStatus,\n\t\t\t\t( errorStatus, SESSION_ERRINFO, \n\t\t\t\t  \"Information in certificate request can't be reconciled \"\n\t\t\t\t  \"with our information for the user (no further problem \"\n\t\t\t\t  \"details are available)\" ) );\n\t\t}\n\n\t/* Provide a more detailed report on what went wrong.  We search the \n\t   table by locus as the primary ID since these are more unique than the \n\t   error type */\n\tLOOP_SMALL( i = 0,\n\t\t\t\textErrorMapTbl[ i ].errorType != CRYPT_ERRTYPE_NONE && \\\n\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( extErrorMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\tEXT_ERROR_MAP_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( extErrorMapTbl[ i ].errorLocus == errorLocus && \\\n\t\t\textErrorMapTbl[ i ].errorType == errorType )\n\t\t\t{\n\t\t\textErrorInfoPtr = &extErrorMapTbl[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( extErrorMapTbl, EXT_ERROR_MAP_INFO ) );\n\tif( extErrorInfoPtr == NULL )\n\t\t{\n\t\t/* It's no obviously recognisable problem, return a lower-level \n\t\t   error message */\n\t\tretExt( errorStatus,\n\t\t\t\t( errorStatus, SESSION_ERRINFO, \n\t\t\t\t  \"Information in certificate request can't be reconciled \"\n\t\t\t\t  \"with our information for the user, error type %d, error \"\n\t\t\t\t  \"locus %d\", errorType, errorLocus ) );\n\t\t}\n\n\t/* Return the actual error message.  Note the somewhat unusual means\n\t   of passing the string argument, some tools will warn of a problem\n\t   due to passing in a non-literal string if we pass the errorString\n\t   in directly (even though it is a literal string) so we have to use \n\t   one level of indirection to bypass the warning */\n\tretExt( errorStatus,\n\t\t\t( errorStatus, SESSION_ERRINFO, \n\t\t\t  \"%s\", extErrorInfoPtr->errorString ) );\n\t}\n#else\n\n#define reportExtendedCertErrorInfo( sessionInfoPtr, errorStatus )\terrorStatus\n#endif /* USE_ERRMSGS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKI Body Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read request body:\n\n\tbody\t\t\t[n]\tEXPLICIT SEQUENCE {\t-- Processed by caller\n\t\t\t\t\t\t...\t\t\t\t\t-- CRMF request\n\t\t\t\t\t} \n\n   The outer tag and SEQUENCE have already been processed by the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readRequestBody( INOUT STREAM *stream, \n\t\t\t\t\t\t\tINOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tINOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\tIN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int messageLength )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tMESSAGE_DATA msgData;\n\tBYTE authCertID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint value, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( messageType >= CTAG_PB_IR && messageType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\tREQUIRES( isShortIntegerRangeNZ( messageLength ) );\n\n\t/* Import the CRMF request */\n\tstatus = importCertFromStream( stream,\n\t\t\t\t\t\t\t\t   &sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t   DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t   ( messageType == CTAG_PB_P10CR ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTREQUEST : \\\n\t\t\t\t\t\t\t\t   ( messageType == CTAG_PB_RR ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_REVOCATION : \\\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT,\n\t\t\t\t\t\t\t\t   messageLength, KEYMGMT_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADCERTTEMPLATE;\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid CRMF request\" ) );\n\t\t}\n\n\t/* If it's a request type that can be self-signed (revocation requests \n\t   are unsigned) and it's from an encryption-only key (that is, a key \n\t   that's not capable of signing, indicated by the request not being \n\t   self-signed) remember this so that we can peform special-case \n\t   processing later on */\n\tif( messageType != CTAG_PB_RR )\n\t\t{\n\t\tBOOLEAN_INT selfSigned;\n\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &selfSigned,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SELFSIGNED );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !selfSigned )\n\t\t\t{\n\t\t\t/* If the request is for a signing key then having an unsigned \n\t\t\t   request is an error */\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t( value & ( KEYUSAGE_SIGN | KEYUSAGE_CA ) ) )\n\t\t\t\t{\n\t\t\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADCERTTEMPLATE;\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"CRMF request is for a signing key but the request \"\n\t\t\t\t\t\t  \"isn't signed\" ) );\n\t\t\t\t}\n\t\t\tprotocolInfo->cryptOnlyKey = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* Record the identity of the PKI user (for a MAC'd request) or \n\t   certificate (for a signed request) that authorised this request */\n\tsetMessageData( &msgData, authCertID, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( protocolInfo->useMACreceive ? \\\n\t\t\t\t\t\t\t\tcmpInfo->userInfo : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_AUTHCERTID );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Revocation requests don't contain any information so there's nothing\n\t   further to check */\n\tif( messageType == CTAG_PB_RR )\n\t\treturn( CRYPT_OK );\n\n\t/* Check whether this request is one that's been authorised by an RA\n\t   rather than coming directly from a user */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &value, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYFEATURES );\n\tif( cryptStatusOK( status ) && ( value & KEYFEATURE_FLAG_RAISSUED ) )\n\t\t{\n\t\tstatus = processRARequest( protocolInfo, \n\t\t\t\t\t\t\t\t   sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\t   messageType, SESSION_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Make sure that the information in the request is consistent with the\n\t   user information template.  If it's an ir then the subject may not \n\t   know their DN or may only know their CN, in which case they'll send \n\t   an empty/CN-only subject DN in the hope that we can fill it in for \n\t   them.  If it's not an ir then the user information acts as a filter \n\t   to ensure that the request doesn't contain values that it shouldn't */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &cmpInfo->userInfo,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_PKIUSERINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADCERTTEMPLATE;\n\n\t\t/* See if we can get any additional information on what the problem \n\t\t   was */\n\t\treturn( reportExtendedCertErrorInfo( sessionInfoPtr, status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Read response body:\n\n\tbody\t\t\t[n] EXPLICIT SEQUENCE {\t-- Processed by caller\n\t\tcaPubs\t\t[1] EXPLICIT SEQUENCE {...} OPTIONAL,-- Ignored\n\t\tresponse\t\tSEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\t\tcertReqID\tINTEGER (0),\n\t\t\tstatus\t\tPKIStatusInfo,\n\t\t\tcertKeyPair\tSEQUENCE {\t\t\t-- If status == 0 or 1\n\t\t\t\tcert[0]\tEXPLICIT Certificate,\nor\t\t\t\tcmpEncCert\t\t\t\t\t-- For encr-only key\n\t\t\t\t\t[1] EXPLICIT CMPEncryptedCert,\nor\t\t\t\tcmsEncCert\t\t\t\t\t-- For encr-only key\n\t\t\t\t\t[2] EXPLICIT EncryptedCert,\n\t\t\t\t\t\t...\t\t\t\t\t-- Ignored\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n   The outer tag and SEQUENCE have already been processed by the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readResponseBody( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t STDC_UNUSED IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t\t STDC_UNUSED IN_LENGTH_SHORT const int messageLength )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tvoid *bodyInfoPtr DUMMY_INIT_PTR;\n\tint bodyLength, tag, value, status = CRYPT_OK;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Skip any noise before the payload if necessary */\n\tif( checkStatusPeekTag( stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\t{\n\t\t/* caPubs */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a revocation response then the only returned data is the \n\t   status value */\n\tif( protocolInfo->operation == CTAG_PB_RR )\n\t\t{\n\t\treadSequence( stream, NULL );\t\t/* Inner wrapper */\n\t\treturn( readPkiStatusInfo( stream, \n\t\t\t\t\t\t\t\t   isServer( sessionInfoPtr ) ? TRUE : FALSE,\n\t\t\t\t\t\t\t\t   &sessionInfoPtr->errorInfo ) );\n\t\t}\n\n\t/* It's a certificate response, unwrap the body to find the certificate \n\t   payload */\n\treadSequence( stream, NULL );\t\t\t/* Inner wrapper */\n\treadSequence( stream, NULL );\n\treadUniversal( stream );\t\t\t\t/* certReqId */\n\tstatus = readPkiStatusInfo( stream, \n\t\t\t\t\t\t\t\tisServer( sessionInfoPtr ) ? TRUE : FALSE,\n\t\t\t\t\t\t\t\t&sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treadSequence( stream, NULL );\t\t\t/* certKeyPair wrapper */\n\tstatus = tag = peekTag( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttag = EXTRACT_CTAG( tag );\n\tstatus = readConstructed( stream, &bodyLength, tag );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( stream, &bodyInfoPtr, bodyLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( bodyInfoPtr != NULL );\n\n\t/* Process the returned certificate as required */\n\tswitch( tag )\n\t\t{\n\t\tcase CTAG_CK_CERT:\n\t\t\t/* Plaintext certificate, we're done */\n\t\t\tbreak;\n\n#if 0\t/* 12/6/09 See earlier comment */\n\t\tcase CTAG_CK_ENCRYPTEDCERT:\n\t\t\t/* Certificate encrypted with CMP's garbled attempt at doing \n\t\t\t   CMS, try and decrypt it */\n\t\t\tstatus = readEncryptedCert( stream, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t\tSESSION_ERRINFO );\n\t\t\tbreak;\n#endif /* 0 */\n\n\t\tcase CTAG_CK_NEWENCRYPTEDCERT:\n\t\t\t{\n\t\t\tERROR_INFO errorInfo;\n\n\t\t\t/* Certificate encrypted with CMS, unwrap it.  Note that this \n\t\t\t   relies on the fact that cryptlib generates the \n\t\t\t   subjectKeyIdentifier that's used to identify the decryption \n\t\t\t   key by hashing the subjectPublicKeyInfo, this is needed \n\t\t\t   because when the newly-issued certificate is received only \n\t\t\t   the keyID is available (since the certificate hasn't been \n\t\t\t   decrypted and read yet) while the returned certificate uses \n\t\t\t   the sKID to identify the decryption key.  If the keyID and\n\t\t\t   sKID aren't the same then the envelope-unwrapping code will\n\t\t\t   report a CRYPT_ERROR_WRONGKEY */\n\t\t\tstatus = envelopeUnwrap( bodyInfoPtr, bodyLength,\n\t\t\t\t\t\t\t\t\t bodyInfoPtr, bodyLength, &bodyLength,\n\t\t\t\t\t\t\t\t\t sessionInfoPtr->privateKey, NULL, 0,\n\t\t\t\t\t\t\t\t\t &errorInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tregisterCryptoFailure();\n\t\t\t\tretExtErr( cryptArgError( status ) ? \\\n\t\t\t\t\t\t   CRYPT_ERROR_FAILED : status,\n\t\t\t\t\t\t   ( cryptArgError( status ) ? \\\n\t\t\t\t\t\t\t CRYPT_ERROR_FAILED : status, SESSION_ERRINFO, \n\t\t\t\t\t\t\t &errorInfo, \n\t\t\t\t\t\t\t \"Couldn't decrypt CMS enveloped certificate: \" ) );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tdefault:\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Unknown returned certificate encapsulation type %d\",\n\t\t\t\t\t  tag ) );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\t\t/* All error paths have already been checked above */\n\n\t/* Import the certificate as a cryptlib object */\n\tsetMessageCreateObjectIndirectInfo( &createInfo, bodyInfoPtr, bodyLength,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid returned certificate\" ) );\n\t\t}\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\n\t/* In order to acknowledge receipt of this message we have to return at a\n\t   later point a hash of the certificate carried in this message created \n\t   using the hash algorithm used in the certificate signature.  This \n\t   makes the CMP-level transport layer dependant on the certificate \n\t   format it's carrying (so the code will repeatedly break every time a \n\t   new certificate hash algorithm or certificate format is added), but \n\t   that's what the standard requires */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTHASHALGO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't extract confirmation hash type from returned \"\n\t\t\t\t  \"certificate\" ) );\n\t\t}\n\tif( ( value != CRYPT_ALGO_MD5 && value != CRYPT_ALGO_SHA1 && \\\n\t\t  value != CRYPT_ALGO_SHA2 && value != CRYPT_ALGO_SHAng ) || \\\n\t\t!algoAvailable( value ) )\n\t\t{\n\t\t/* Certificates can only provide fingerprints using a subset of\n\t\t   available hash algorithms */\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t  \"Can't confirm certificate issue using hash algorithm %s\",\n\t\t\t\t  getAlgoName( value ) ) );\n\t\t}\n\tprotocolInfo->confHashAlgo = value;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read conf body:\n\n\tbody\t\t   [19]\tEXPLICIT SEQUENCE {\t-- Processed by caller\n\t\t\t\t\t\tSEQUENCE {\n\t\tcertHash\t\tOCTET STRING\n\t\tcertReqID\t\tINTEGER (0),\n\t\t\t}\n\t\t}\n\n   The outer tag and SEQUENCE have already been processed by the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readConfBody( INOUT STREAM *stream, \n\t\t\t\t\t\t INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int messageLength )\n\t{\n\tstatic const MAP_TABLE hashMapTable[] = {\n\t\t/* We're the server so we control the hash algorithm that'll be \n\t\t   used, which means that it'll always be one of the following */\n\t\t{ CRYPT_ALGO_SHA1, MESSAGE_COMPARE_FINGERPRINT_SHA1 },\n\t\t{ CRYPT_ALGO_SHA2, MESSAGE_COMPARE_FINGERPRINT_SHA2 },\n\t\t{ CRYPT_ALGO_SHAng, MESSAGE_COMPARE_FINGERPRINT_SHAng },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tMESSAGE_DATA msgData;\n\tBYTE certHash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint compareMessageValue, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( messageType >= CTAG_PB_IR && messageType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\tREQUIRES( isShortIntegerRange( messageLength ) );\n\n\t/* If there's no certStatus then the client has rejected the \n\t   certificate.  This isn't an explicit error since it's a valid \n\t   protocol outcome so we return an OK status but set the overall \n\t   protocol status to a generic error value to indicate that we don't \n\t   want to continue normally */\n\tif( messageLength <= 0 )\n\t\t{\n\t\tprotocolInfo->status = CRYPT_ERROR;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Read the client's returned confirmation information */\n\treadSequence( stream, NULL );\n\tstatus = readOctetString( stream, certHash, &length,\n\t\t\t\t\t\t\t  8, CRYPT_MAX_HASHSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate confirmation\" ) );\n\t\t}\n\n\t/* Compare the certificate hash to the one sent by the client.  Since \n\t   we're the server this is a cryptlib-issued certificate so we know \n\t   that it'll always use one of the SHA family of hashes */\n\tstatus = mapValue( protocolInfo->confHashAlgo, &compareMessageValue,\n\t\t\t\t\t   hashMapTable, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( hashMapTable, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsetMessageData( &msgData, certHash, length );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t  compareMessageValue );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The user is confirming an unknown certificate, the best that we \n\t\t   can do is return a generic certificate-mismatch error */\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_BADCERTID;\n\t\tretExt( CRYPT_ERROR_NOTFOUND,\n\t\t\t\t( CRYPT_ERROR_NOTFOUND, SESSION_ERRINFO, \n\t\t\t\t  \"Returned certificate hash doesn't match issued \"\n\t\t\t\t  \"certificate\" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Read genMsg body:\n\n\tbody\t\t   [21]\tEXPLICIT SEQUENCE OF {\t-- Processed by caller\n\t\t\t\t\t\tSEQUENCE {\n\t\tinfoType\t\tOBJECT IDENTIFIER,\n\t\tintoValue\t\tANY DEFINED BY infoType OPTIONAL\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n   The outer tag and SEQUENCE have already been processed by the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readGenMsgBody( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   STDC_UNUSED CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t   IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t   IN_LENGTH_SHORT const int messageLength )\n\t{\n\tconst BOOLEAN isRequest = ( messageType == CTAG_PB_GENM ) ? TRUE : FALSE;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( messageType >= CTAG_PB_IR && messageType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\tREQUIRES( isShortIntegerRangeNZ( messageLength ) );\n\n\t/* If it's a request GenMsg, check for a PKIBoot request.  Note that \n\t   this assumes that the only GenMsg that we'll receive is a PKIBoot,\n\t   there are no known other users of this message type and even if \n\t   someone did decide to use it, it's not clear what we're supposed to\n\t   to with the contents */\n\tif( isRequest )\n\t\t{\n\t\treadSequence( stream, NULL );\n\t\tstatus = readFixedOID( stream, OID_PKIBOOT, \n\t\t\t\t\t\t\t   sizeofOID( OID_PKIBOOT ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid genMsg type, expected PKIBoot request\" ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a PKIBoot response with the InfoTypeAndValue handled as CMS\n\t   content (see the comment for writeGenMsgResponseBody() in \n\t   cmp_wrmsg.c), import the certificate trust list.  Since this isn't a \n\t   true certificate chain and isn't used as such, we import it as \n\t   data-only certificates */\n\tstatus = importCertFromStream( stream, &sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t\t   DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTCHAIN, messageLength,\n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_DATAONLY_CERT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid PKIBoot response\" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Read error body:\n\n\tbody\t\t   [23]\tEXPLICIT SEQUENCE {\t-- Processed by caller\n\t\tstatus\t\t\tPKIFailureInfo,\n\t\terrorCode\t\tINTEGER OPTIONAL,\n\t\terrorMsg\t\tSEQUENCE ... OPTIONAL\t-- Ignored\n\t\t}\n\n   The outer tag and SEQUENCE have already been processed by the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readErrorBody( INOUT STREAM *stream, \n\t\t\t\t\t\t  INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  STDC_UNUSED CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t  STDC_UNUSED const CMP_MESSAGE_TYPE messageType,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int messageLength )\n\t{\n#ifdef USE_ERRMSGS\n\tERROR_INFO *errorInfo = &sessionInfoPtr->errorInfo;\n\tconst char *peerTypeString = isServer( sessionInfoPtr ) ? \\\n\t\t\t\t\t\t\t\t \"Client\" : \"Server\";\n#endif /* USE_ERRMSGS */\n\tconst int endPos = stell( stream ) + messageLength;\n\tint tag, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( messageLength ) );\n\n\t/* Read the outer wrapper and PKI status information.  In another one of\n\t   CMP's many wonderful features there are two places to communicate \n\t   error information with no clear indication in the spec as to which one\n\t   is meant to be used.  To deal with this we stop at the first one that\n\t   contains an error status */\n\tstatus = readPkiStatusInfo( stream, \n\t\t\t\t\t\t\t\tisServer( sessionInfoPtr ) ? TRUE : FALSE,\n\t\t\t\t\t\t\t\t&sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* In addition to the PKI status information there can be a second lot\n\t   of error information which is exactly the same only different, so if \n\t   we haven't got anything from the status information we check to see \n\t   whether this layer can give us anything */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_INTEGER )\n\t\t{\n\t\tlong value;\n\n\t\tstatus = readShortInteger( stream, &value );\n\t\tif( cryptStatusOK( status ) && !isIntegerRange( value ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tconst int errorCode = ( int ) value;\n#endif /* USE_ERRMSGS */\n\n\t\t\tretExt( CRYPT_ERROR_FAILED,\n\t\t\t\t\t( CRYPT_ERROR_FAILED, errorInfo,\n\t\t\t\t\t  \"%s returned nonspecific failure code %d\",\n\t\t\t\t\t  peerTypeString, errorCode ) );\n\t\t\t}\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_SEQUENCE )\n\t\t{\n\t\tstatus = readUniversal( stream );\n\t\t}\n\n\t/* Make sure that we always return an error code.  That is, if there's no\n\t   error in reading the error information then we still have to return an\n\t   error because what we've successfully read is a report of an error */\n\tretExt( cryptStatusError( status ) ? status : CRYPT_ERROR_FAILED,\n\t\t\t( cryptStatusError( status ) ? status : CRYPT_ERROR_FAILED, \n\t\t\t  errorInfo, \n\t\t\t  \"%s returned nonspecific failure code\", peerTypeString ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead Function Access Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst CMP_MESSAGE_TYPE type;\n\tconst READMESSAGE_FUNCTION function;\n\t} MESSAGEREAD_INFO;\nstatic const MESSAGEREAD_INFO messageReadTable[] = {\n\t{ CTAG_PB_IR, readRequestBody },\n\t{ CTAG_PB_CR, readRequestBody },\n\t{ CTAG_PB_P10CR, readRequestBody },\n\t{ CTAG_PB_KUR, readRequestBody },\n\t{ CTAG_PB_RR, readRequestBody },\n\t{ CTAG_PB_IP, readResponseBody },\n\t{ CTAG_PB_CP, readResponseBody },\n\t{ CTAG_PB_KUP, readResponseBody },\n\t{ CTAG_PB_RP, readResponseBody },\n\t{ CTAG_PB_CERTCONF, readConfBody },\n\t{ CTAG_PB_PKICONF, readConfBody },\n\t{ CTAG_PB_GENM, readGenMsgBody },\n\t{ CTAG_PB_GENP, readGenMsgBody },\n\t{ CTAG_PB_ERROR, readErrorBody },\n\t{ CTAG_PB_LAST, NULL }, { CTAG_PB_LAST, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nREADMESSAGE_FUNCTION getMessageReadFunction( IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE messageType )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( messageType >= CTAG_PB_IR && messageType < CTAG_PB_LAST );\n\t\t\t\t/* CTAG_PB_IR == 0 so this is the same as _NONE */\n\n\tLOOP_MED( i = 0, \n\t\t\t  messageReadTable[ i ].type != CTAG_PB_LAST && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( messageReadTable, \\\n\t\t\t\t\t\t\t\t\t\tMESSAGEREAD_INFO ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( messageReadTable[ i ].type == messageType )\n\t\t\treturn( messageReadTable[ i ].function );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\tENSURES_N( i < FAILSAFE_ARRAYSIZE( messageReadTable, MESSAGEREAD_INFO ) );\n\n\treturn( NULL );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_svr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib CMP Server Management\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Map request to response types */\n\nstatic const MAP_TABLE reqClibReqMapTbl[] = {\n\t{ CTAG_PB_IR, CRYPT_REQUESTTYPE_INITIALISATION },\n\t{ CTAG_PB_CR, CRYPT_REQUESTTYPE_CERTIFICATE },\n\t{ CTAG_PB_P10CR, CRYPT_REQUESTTYPE_CERTIFICATE },\n\t{ CTAG_PB_KUR, CRYPT_REQUESTTYPE_KEYUPDATE },\n\t{ CTAG_PB_RR, CRYPT_REQUESTTYPE_REVOCATION },\n\t{ CTAG_PB_GENM, CRYPT_REQUESTTYPE_PKIBOOT },\n\t{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }\n\t};\n\nCHECK_RETVAL_RANGE( CRYPT_REQUESTTYPE_NONE, CRYPT_REQUESTTYPE_LAST ) \\\nstatic int reqToClibReq( IN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE reqType )\n\t{\n\tint value, status;\n\n\tREQUIRES( reqType >= CTAG_PB_IR && reqType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\n\tstatus = mapValue( reqType, &value, reqClibReqMapTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( reqClibReqMapTbl, MAP_TABLE ) );\n\treturn( cryptStatusError( status ) ? status : value );\n\t}\n\n/* Set up user authentication information (either a MAC context or a public \n   key) based on a request submitted by the client.  This is done whenever \n   the client starts a new transaction with a new user ID or certificate \n   ID */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initServerAuthentMAC( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tMESSAGE_DATA msgData;\n\tchar password[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Set up general authentication information and if there's user \n\t   information still present from a previous transaction, clear it */\n\tstatus = setCMPprotocolInfo( protocolInfo, NULL, 0, \n\t\t\t\t\t\t\t\t CMP_INIT_FLAG_MACCTX, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( cmpInfo->userInfo != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );\n\t\tcmpInfo->userInfo = CRYPT_ERROR;\n\t\t}\n\tif( protocolInfo->altMacKeySize > 0 )\n\t\t{\n\t\tzeroise( protocolInfo->altMacKey, CRYPT_MAX_HASHSIZE );\n\t\tprotocolInfo->altMacKeySize = 0;\n\t\t}\n\tprotocolInfo->userIsRA = FALSE;\n\n\t/* Get the user information for the user identified by the user ID from \n\t   the certificate store.  If we get a not-found error we report it as \n\t   \"signer not trusted\", which can also mean \"signer unknown\" */\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,\n\t\t\t\t\t\t   protocolInfo->userID, protocolInfo->userIDsize, \n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\t\tchar userID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint userIDlen;\n\n\t\tREQUIRES( userNamePtr != NULL );\n\t\tif( TEST_FLAG( userNamePtr->flags, ATTR_FLAG_ENCODEDVALUE ) )\n\t\t\t{\n\t\t\tuserIDlen = min( userNamePtr->valueLength, CRYPT_MAX_TEXTSIZE );\n\t\t\tREQUIRES( rangeCheck( userIDlen, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( userID, userNamePtr->value, userIDlen );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* The ID isn't a cryptlib user ID but a certificate ID used for \n\t\t\t   a cr rather than the user ID for an ir or rr (see the comment \n\t\t\t   at the start of initServerAuthentSign() for details), we have \n\t\t\t   to use a placeholder string since it's meaningless binary \n\t\t\t   data.  We can't try and map this to a user ID since we've just \n\t\t\t   failed to find the PKI user object that would contain it.\n\t\t\t   \n\t\t\t   Alternatively, in less likely cases it could also be an \n\t\t\t   incorrect user ID that we couldn't recognise and record as a \n\t\t\t   cryptlib user ID, which we can't do much with either */\n\t\t\tuserIDlen = 18;\n\t\t\tREQUIRES( rangeCheck( userIDlen, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( userID, \"the requested user\", userIDlen );\n\t\t\t}\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Couldn't find PKI user information for %s\",\n\t\t\t\t\t sanitiseString( userID, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t userIDlen ) ) );\n\t\t}\n\tcmpInfo->userInfo = getkeyInfo.cryptHandle;\n\tprotocolInfo->userIDchanged = FALSE;\n\n\t/* Get the password from the PKI user object */\n\tsetMessageData( &msgData, password, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( cmpInfo->userInfo, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD, \n\t\t\t\t\t\t\t\t\tpassword, msgData.length, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\tATTR_FLAG_ENCODEDVALUE );\n\t\t}\n\tzeroise( password, CRYPT_MAX_TEXTSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't copy PKI user data from PKI user object to \"\n\t\t\t\t  \"session object\" ) );\n\t\t}\n\n\t/* Things get a bit complicated for password-authenticated operations \n\t   because there's a second password that may (optionally) be used for\n\t   revocations that doesn't fit into the standard pattern of username+\n\t   password.  In order to handle MAC'd revocation requests, we keep a \n\t   copy of the revocation MAC key and use it in place of the standard\n\t   password if we get a revocation request rather than an issue\n\t   request */\n\tsetMessageData( &msgData, password, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( cmpInfo->userInfo, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_PKIUSER_REVPASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = decodePKIUserValue( protocolInfo->altMacKey, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t\t &protocolInfo->altMacKeySize, password, \n\t\t\t\t\t\t\t\t\t msgData.length );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\tzeroise( password, CRYPT_MAX_TEXTSIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initServerAuthentSign( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tMESSAGE_DATA msgData;\n\tchar userName[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBOOLEAN_INT isRA;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Set up general authentication information and if there's client \n\t   authentication information still present from a previous transaction \n\t   that used MAC authentication, clear it */\n\tstatus = setCMPprotocolInfo( protocolInfo, NULL, 0, CMP_INIT_FLAG_NONE,\n\t\t\t\t\t\t\t\t TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( cmpInfo->userInfo != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( cmpInfo->userInfo, IMESSAGE_DECREFCOUNT );\n\t\tcmpInfo->userInfo = CRYPT_ERROR;\n\t\t}\n\tprotocolInfo->userIsRA = FALSE;\n\n\t/* Get the user information for the user that originally authorised the \n\t   issue of the certificate that signed the request.  This serves two \n\t   purposes, it obtains the original user ID if it wasn't supplied in \n\t   the request (for example if the request uses only a certificate ID \n\t   from a certificate five generations downstream from the original PKI\n\t   user after an ir -> cr -> cr -> cr -> cr and we've got the \n\t   certificate ID from the final cr in the series), and it verifies that \n\t   the authorising certificate belongs to a currently valid user */\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,\n\t\t\t\t\t\t   protocolInfo->certID, protocolInfo->certIDsize, \n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_GETISSUER );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Couldn't find PKI user information for owner of \"\n\t\t\t\t\t \"requesting certificate\" ) );\n\t\t}\n\tcmpInfo->userInfo = getkeyInfo.cryptHandle;\n\n\t/* Update the user ID from the PKI user object and record whether the \n\t   user is an RA rather than a standard user */\n\tsetMessageData( &msgData, userName, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( getkeyInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t\tuserName, msgData.length, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\tATTR_FLAG_ENCODEDVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't copy PKI user data from PKI user object to \"\n\t\t\t\t  \"session object\" ) );\n\t\t}\n\tstatus = krnlSendMessage( getkeyInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &isRA,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_RA );\n\tif( cryptStatusOK( status ) && isRA == TRUE )\n\t\tprotocolInfo->userIsRA = TRUE;\n\n\t/* Get the public key identified by the certificate ID from the \n\t   certificate store.  This verifies the assumption that the owner of an \n\t   existing certificate/existing user is authorised to request further \n\t   certificates using the existing one.  If we get a not found error we \n\t   report it as \"signer not trusted\", which can also mean \"signer \n\t   unknown\" */\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,\n\t\t\t\t\t\t   protocolInfo->certID, protocolInfo->certIDsize, \n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_USAGE_SIGN );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprotocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Couldn't find certificate for requested user\" ) );\n\t\t}\n\tsessionInfoPtr->iAuthInContext = getkeyInfo.cryptHandle;\n\tprotocolInfo->certIDchanged = FALSE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Deliver an Einladung betreff Kehrseite to the client.  We don't bother\n   checking the return value for the write since there's nothing that we can \n   do in the case of an error except close the connection, which we do \n   anyway since this is the last message */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t   IN_ERROR const int errorStatus )\n\t{\n\tBOOLEAN writeHttpResponseOnly = protocolInfo->headerRead ? FALSE : TRUE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\t\n\tREQUIRES_V( cryptStatusError( errorStatus ) );\n\n\t/* If we were going to protect the communication with the client with a\n\t   MAC and something failed we don't try and MAC the response since the \n\t   failure could be a client MAC failure, failure to locate the MAC key, \n\t   or something similar */\n\tprotocolInfo->useMACsend = FALSE;\n\tprotocolInfo->status = errorStatus;\n\n\t/* Write the error response if we can.  We only do this if at least the\n\t   header of the client's message was successfully read (indicated by \n\t   the headerRead flag in the protocolInfo being set), otherwise we \n\t   can't create our own header for the response */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, TRUE );\n\tif( !writeHttpResponseOnly )\n\t\t{\n\t\tstatus = writePkiMessage( sessionInfoPtr, protocolInfo, CMPBODY_ERROR );\n\t\tif( cryptStatusError( status ) )\n\t\t\twriteHttpResponseOnly = TRUE;\n\t\t}\n\tif( writeHttpResponseOnly )\n\t\t{\n\t\tHTTP_DATA_INFO httpDataInfo;\n\n\t\t/* If we encounter an error processing the initial request then \n\t\t   there won't be enough information available to create an error \n\t\t   response.  At this point the best that we can do is send an error\n\t\t   at the HTTP level */\n\t\tstatus = initHttpInfoReq( &httpDataInfo );\n\t\tENSURES_V( cryptStatusOK( status ) ); \n\t\thttpDataInfo.reqStatus = errorStatus;\n\t\t( void ) swrite( &sessionInfoPtr->stream, &httpDataInfo, \n\t\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\t\t}\n\telse\n\t\t{\n\t\tDEBUG_DUMP_CMP( CTAG_PB_ERROR, 1, sessionInfoPtr );\n\t\t( void ) writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with a CMP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;\n\tMESSAGE_CERTMGMT_INFO certMgmtInfo;\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tSTREAM stream;\n\tCMP_PROTOCOL_INFO protocolInfo;\n\tconst ATTRIBUTE_LIST *userNamePtr;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Initialise the server-side protocol state information.  Since the \n\t   server doesn't have a user ID (it uses what the client sends it), we \n\t   set the userID-sent flag to indicate that it's been implicitly \n\t   exchanged */\n\tinitCMPprotocolInfo( &protocolInfo,\n\t\t\t\t\t\t TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t\t\t\tSESSION_FLAG_ISCRYPTLIB ) ? TRUE : FALSE, \n\t\t\t\t\t\t TRUE );\n\tprotocolInfo.authContext = sessionInfoPtr->privateKey;\n\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_USERIDSENT );\n\tuserNamePtr = findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tif( userNamePtr != NULL )\n\t\t{\n\t\tBYTE userID[ CRYPT_MAX_TEXTSIZE ];\n\t\tint userIDsize;\n\n\t\t/* There's already user information present from a previous \n\t\t   transaction, try and re-use it (this can happen if we're\n\t\t   handling a series of transactions from the client, see the\n\t\t   dicussion in cmp.h for details).  This information can still\n\t\t   be overridden by the client sending us new user information */\n\t\tif( TEST_FLAG( userNamePtr->flags, ATTR_FLAG_ENCODEDVALUE ) )\n\t\t\t{\n\t\t\t/* It's a cryptlib-style encoded user ID, decode it into its \n\t\t\t   binary value */\n\t\t\tstatus = decodePKIUserValue( userID, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t &userIDsize,\n\t\t\t\t\t\t\t\t\t\t userNamePtr->value,\n\t\t\t\t\t\t\t\t\t\t userNamePtr->valueLength );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a standard user ID, use it as is */\n\t\t\tuserIDsize = min( userNamePtr->valueLength, CRYPT_MAX_TEXTSIZE );\n\t\t\tREQUIRES( rangeCheck( userIDsize, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\t\tmemcpy( userID, userNamePtr->value, userIDsize );\n\t\t\t}\n\t\tstatus = setCMPprotocolInfo( &protocolInfo, userID, userIDsize,\n\t\t\t\t\t\t\t\t\t CMP_INIT_FLAG_USERID, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We're (potentially) re-using user information from a previous \n\t\t   session, if there are cryptographic credentials associated with\n\t\t   the user information we have to move them over to the current\n\t\t   protocol state data */\n\t\tif( cmpInfo->savedMacContext != CRYPT_ERROR )\n\t\t\t{\n\t\t\tprotocolInfo.iMacContext = cmpInfo->savedMacContext;\n\t\t\tcmpInfo->savedMacContext = CRYPT_ERROR;\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"initCMPprotocolInfo\" );\n\n\t/* Read the initial message from the client.  We don't write an error\n\t   response at the initial read stage to prevent scanning/DOS attacks \n\t   (vir sapit qui pauca loquitur) */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readPkiDatagram\" );\n\n\t/* Basic lint filter to check for approximately-OK requests before we\n\t   try applying message-processing operations to the data:\n\n\t\tSEQUENCE {\n\t\t\tSEQUENCE {\n\t\t\t\tINTEGER 1\t-- version\n\t\t\t\t... */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treadSequence( &stream, NULL );\n\treadSequence( &stream, NULL );\n\tstatus = readInteger( &stream, NULL, 2, NULL );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid CMP request header\" ) );\n\t\t}\n\n\t/* Process the initial client message */\n\tstatus = readPkiMessage( sessionInfoPtr, &protocolInfo,\n\t\t\t\t\t\t\t CTAG_PB_READ_ANY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cmpInfo->requestType = \\\n\t\t\t\t\treqToClibReq( protocolInfo.operation );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tDEBUG_DUMP_CMP( protocolInfo.operation, 1, sessionInfoPtr );\n\tCFI_CHECK_UPDATE( \"readPkiMessage\" );\n\n\t/* If it's a PKIBoot request, send the PKIBoot response */\n\tif( cmpInfo->requestType == CRYPT_REQUESTTYPE_PKIBOOT )\n\t\t{\n\t\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo, \n\t\t\t\t\t\t\t\t  CMPBODY_GENMSG );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tDEBUG_DUMP_CMP( CTAG_PB_GENM, 2, sessionInfoPtr );\n\t\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tdelayRandom();\t/* Dither error timing info */\n\t\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Remember the authentication context in case we can reuse it for \n\t\t   another transaction */\n\t\tcmpInfo->savedMacContext = protocolInfo.iMacContext;\n\t\tprotocolInfo.iMacContext = CRYPT_ERROR;\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"initCMPprotocolInfo\", \"readPkiDatagram\", \n\t\t\t\t\t\t\t\t\t\t\"readPkiMessage\" ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"PKIBoot\" );\n\n\t/* Make sure that the signature on the request data is OK (unless it's a \n\t   non-signed revocation request or a request for an encryption-only \n\t   key) */\n\tif( protocolInfo.operation != CTAG_PB_RR && !protocolInfo.cryptOnlyKey )\n\t\t{\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGCHECK, NULL, \n\t\t\t\t\t\t\t\t  CRYPT_UNUSED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdelayRandom();\t/* Dither error timing info */\n\t\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Certificate request signature check failed\" ) );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CRT_SIGCHECK\" );\n\n\t/* Add the request to the certificate store */\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, NULL, 0,\n\t\t\t\t\t\t   ( protocolInfo.operation == CTAG_PB_IR ) ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_INITIALOP : \\\n\t\t\t\t\t\t   ( protocolInfo.operation == CTAG_PB_KUR ) ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_UPDATE : KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = sessionInfoPtr->iCertRequest;\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_SETKEY, &setkeyInfo, \n\t\t\t\t\t\t\t  ( protocolInfo.operation == CTAG_PB_RR ) ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_ITEM_REVREQUEST : \\\n\t\t\t\t\t\t\t\tKEYMGMT_ITEM_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the certificate store reports that there's a problem with the \n\t\t   request, convert it to an invalid request error */\n\t\tif( cryptArgError( status ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\n\t\t/* A special error condition at this point arises when the user \n\t\t   tries to submit a second initialisation request for a PKI user \n\t\t   that has already had a certificate issued for it, so we catch \n\t\t   this condition and provide a more informative error response to \n\t\t   the client than the generic failure response */\n\t\tif( protocolInfo.operation == CTAG_PB_IR && \\\n\t\t\tstatus == CRYPT_ERROR_DUPLICATE )\n\t\t\tprotocolInfo.pkiFailInfo = CMPFAILINFO_DUPLICATECERTREQ;\n\n\t\t/* Clean up and return the appropriate error information to the\n\t\t   caller */\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\tif( protocolInfo.operation == CTAG_PB_IR && \\\n\t\t\tstatus == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tretExtObj( status, \n\t\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t \"Initialisation request couldn't be added to the \"\n\t\t\t\t\t\t \"certificate store because another initialisation \"\n\t\t\t\t\t\t \"request has already been processed for this user\" ) );\n\t\t\t}\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Request couldn't be added to the certificate store\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_KEY_SETKEY\" );\n\n\t/* Create or revoke a certificate from the request */\n\tif( protocolInfo.operation != CTAG_PB_RR )\n\t\t{\n\t\tsetMessageCertMgmtInfo( &certMgmtInfo, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCertRequest );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t\t  CRYPT_CERTACTION_CERT_CREATION );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tint value;\n\n\t\t\t/* Remember the issued certificate and save various pieces\n\t\t\t   of information that we'll need later */\n\t\t\tsessionInfoPtr->iCertResponse = certMgmtInfo.cryptCert;\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTHASHALGO );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tprotocolInfo.confHashAlgo = value;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCertRequest );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t\t  CRYPT_CERTACTION_REVOKE_CERT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the certificate store reports that there's a problem with the \n\t\t   request, convert it to an invalid request error */\n\t\tif( cryptArgError( status ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Certificate %s was denied by certificate store\",\n\t\t\t\t\t ( protocolInfo.operation != CTAG_PB_RR ) ? \\\n\t\t\t\t\t\t\"issue\" : \"revocation\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_KEY_CERTMGMT\" );\n\n\t/* Send the response to the client */\n\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo, CMPBODY_NORMAL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 2, sessionInfoPtr );\n\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,\n\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t}\n\telse\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( protocolInfo.operation != CTAG_PB_RR )\n\t\t\t{\n\t\t\t/* If there was a problem, drop the partially-issued certificate.  \n\t\t\t   We don't have to go all the way and do a full reversal \n\t\t\t   because it hasn't really been issued yet since we couldn't \n\t\t\t   get it to the client (or even if the client somehow got it,\n\t\t\t   the certificate store hasn't marked it as complete yet so \n\t\t\t   it's regarded as invalid if queried).  In addition we don't \n\t\t\t   do anything with the return status since we want to return \n\t\t\t   the status that caused the problem, not the result of the \n\t\t\t   drop operation */\n\t\t\tsetMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCertResponse );\n\t\t\t( void ) krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTACTION_CERT_CREATION_DROP );\n\t\t\t}\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"writePkiMessage\" );\n\n\t/* If it's a transaction type that doesn't need a confirmation, we're \n\t   done */\n\tif( protocolInfo.operation == CTAG_PB_RR )\n\t\t{\n\t\t/* Remember the authentication context in case we can reuse it for \n\t\t   another transaction */\n\t\tcmpInfo->savedMacContext = protocolInfo.iMacContext;\n\t\tprotocolInfo.iMacContext = CRYPT_ERROR;\n\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"initCMPprotocolInfo\", \"readPkiDatagram\", \n\t\t\t\t\t\t\t\t\t\t\"readPkiMessage\", \"PKIBoot\", \n\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_CRT_SIGCHECK\", \n\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_KEY_SETKEY\", \n\t\t\t\t\t\t\t\t\t\t\"IMESSAGE_KEY_CERTMGMT\", \n\t\t\t\t\t\t\t\t\t\t\"writePkiMessage\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"noConf\" );\n\n\t/* Read back the confirmation from the client */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readPkiMessage( sessionInfoPtr, &protocolInfo,\n\t\t\t\t\t\t\t\t CTAG_PB_CERTCONF );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\n\t\t/* Reverse the certificate issue operation by revoking the \n\t\t   incompletely-issued certificate, returning the status that caused \n\t\t   the failure earlier on */\n\t\tsetMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCertResponse );\n\t\t( void ) krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t\t  CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\t\treturn( status );\n\t\t}\n\tDEBUG_DUMP_CMP( protocolInfo.operation, 3, sessionInfoPtr );\n\tif( protocolInfo.status == CRYPT_ERROR )\n\t\t{\n\t\tint localStatus;\n\n\t\t/* The client rejected the certificate, this isn't a protocol error \n\t\t   so we send back a standard ack */\n\t\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo, \n\t\t\t\t\t\t\t\t  CMPBODY_ACK );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tdelayRandom();\t/* Dither error timing info */\n\t\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\t\t}\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\n\t\t/* Reverse the certificate issue operation by revoking the \n\t\t   incompletely-issued certificate */\n\t\tsetMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCertResponse );\n\t\tlocalStatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t\t\t   IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTACTION_CERT_CREATION_REVERSE );\n\t\treturn( cryptStatusOK( status ) ? localStatus : status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"confMessage\" );\n\n\t/* The client has confirmed the certificate creation, finalise it */\n\tsetMessageCertMgmtInfo( &certMgmtInfo, CRYPT_UNUSED,\n\t\t\t\t\t\t\tsessionInfoPtr->iCertResponse );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t  CRYPT_CERTACTION_CERT_CREATION_COMPLETE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroyCMPprotocolInfo( &protocolInfo );\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Certificate issue completion failed\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_KEY_CERTMGMT\" );\n\n\t/* Send back the final ack and clean up.  It's not certain whether we\n\t   should send an error response at this late stage if the creation of \n\t   the final ack fails since the certificate has been issued \n\t   successfully, so we leave it up to the client to decide how it should \n\t   treat this situation */\n\tstatus = writePkiMessage( sessionInfoPtr, &protocolInfo, CMPBODY_ACK );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tDEBUG_DUMP_CMP( protocolInfo.operation, 4, sessionInfoPtr );\n\t\tstatus = writePkiDatagram( sessionInfoPtr, CMP_CONTENT_TYPE,\n\t\t\t\t\t\t\t\t   CMP_CONTENT_TYPE_LEN );\n\t\t}\n\tCFI_CHECK_UPDATE( \"writePkiMessage\" );\n\n\t/* Remember the authentication context in case we can reuse it for \n\t   another transaction */\n\tcmpInfo->savedMacContext = protocolInfo.iMacContext;\n\tprotocolInfo.iMacContext = CRYPT_ERROR;\n\n\tdestroyCMPprotocolInfo( &protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_12( \"initCMPprotocolInfo\", \"readPkiDatagram\", \n\t\t\t\t\t\t\t\t\t \"readPkiMessage\", \"PKIBoot\", \n\t\t\t\t\t\t\t\t\t \"IMESSAGE_CRT_SIGCHECK\", \"IMESSAGE_KEY_SETKEY\", \n\t\t\t\t\t\t\t\t\t \"IMESSAGE_KEY_CERTMGMT\", \"writePkiMessage\", \n\t\t\t\t\t\t\t\t\t \"noConf\", \"confMessage\", \n\t\t\t\t\t\t\t\t\t \"IMESSAGE_KEY_CERTMGMT\", \"writePkiMessage\" ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initCMPserverProcessing( SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite CMP Messages\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n/* Enabling the following define forces the use of full headers at all times.\n   cryptlib always sends minimal headers once it detects that the other side \n   is using cryptlib, ommitting as much of the unnecessary junk as possible, \n   which significantly reduces the overall message size */\n\n/* #define USE_FULL_HEADERS */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write full certificate ID information.  This is written as an attribute \n   in the generalInfo field of the message header to allow unambiguous\n   identification of the signing certificate, which the standard CMP format \n   can't do.  Although CMP uses a gratuitously incompatible definition of \n   the standard attribute type (calling it InfoTypeAndValue), it's possible \n   to shoehorn a standard attribute type in by taking the \"ANY\" in \"ANY \n   DEFINED BY x\" to mean \"SET OF AttributeValue\" (for once the use of \n   obsolete ASN.1 is a help, since it's so imprecise that we can shovel in \n   anything and it's still valid):\n\n\tSigningCertificate ::=  SEQUENCE {\n\t\tcerts\t\t\tSEQUENCE OF ESSCertID\t-- Size (1)\n\t\t}\n\n\tESSCertID ::= SEQUENCE {\n\t\tcertID\t\t\tOCTET STRING\n\t\t}\n\n   All that we really need to identify certificates is the certificate ID, \n   so instead of writing a full ESSCertID (which also contains an optional \n   incompatible reinvention of the CMS IssuerAndSerialNumber) we write the \n   sole mandatory field, the certificate hash, which also keeps the overall \n   size down.\n   \n   This is further complicated though by the fact that certificate attributes\n   are defined as SET OF while CMS attributes are defined as SEQUENCE (and of \n   course CMP has to gratuitously invent its own type which is neither of the \n   two).  This means that the read code would need to know whether a given \n   OID corresponds to a certificate or CMS attribute and read it \n   appropriately.  Because this is just too much of a mess, we pretend that \n   all attributes are certificate attributes (since this is a PKIX protocol)\n   and encode them as a uniform SET OF */\n\nCHECK_RETVAL \\\nstatic int sizeofCertID( IN_HANDLE const CRYPT_CONTEXT iCryptCert )\n\t{\n\tconst int essCertIDSize = objSize( objSize( objSize( objSize( 20 ) ) ) );\n\t\t\t\t\t/* Infinitely-nested SHA-1 hash */\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\treturn( objSize( sizeofOID( OID_ESS_CERTID ) + \\\n\t\t\t\t\t sizeofShortObject( essCertIDSize ) ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeCertID( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT iCryptCert )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE certHash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint essCertIDSize, payloadSize, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\n\t/* Find out how big the payload will be */\n\tsetMessageData( &msgData, certHash, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tessCertIDSize = sizeofShortObject( msgData.length );\n\tpayloadSize = objSize( objSize( objSize( essCertIDSize ) ) );\n\n\t/* Write the signing certificate ID information */\n\twriteSequence( stream, sizeofOID( OID_ESS_CERTID ) + \\\n\t\t\t\t\t\t   sizeofShortObject( payloadSize ) );\n\twriteOID( stream, OID_ESS_CERTID );\n\twriteSet( stream, payloadSize );\n\twriteSequence( stream, objSize( objSize( essCertIDSize ) ) );\n\twriteSequence( stream, objSize( essCertIDSize ) );\n\twriteSequence( stream, essCertIDSize );\n\treturn( writeOctetString( stream, certHash, msgData.length, \n\t\t\t\t\t\t\t  DEFAULT_TAG ) );\n\t}\n\n/* Initialise the information needed to send client/server DNs in the PKI \n   header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 5 ) ) \\\nstatic int initDNInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_HANDLE *senderNameObject,\n\t\t\t\t\t   OUT_HANDLE_OPT CRYPT_HANDLE *recipNameObject,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *senderNameLength,\n\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *recipNameLength,\n\t\t\t\t\t   const BOOLEAN isInitialClientMessage,\n\t\t\t\t\t   const BOOLEAN isClientCryptOnlyKey )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( senderNameObject, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isWritePtr( recipNameObject, sizeof( CRYPT_HANDLE ) ) );\n\tassert( isWritePtr( senderNameLength, sizeof( int ) ) );\n\tassert( isWritePtr( recipNameLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( isInitialClientMessage == TRUE || \\\n\t\t\t  isInitialClientMessage == FALSE );\n\tREQUIRES( isClientCryptOnlyKey == TRUE || \\\n\t\t\t  isClientCryptOnlyKey == FALSE );\n\n\t/* Clear return values */\n\t*senderNameObject = *recipNameObject = CRYPT_ERROR;\n\t*senderNameLength = *recipNameLength = 0;\n\n\t/* Get the objects that we'll be using for our source of DN \n\t   information */\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\t*senderNameObject = sessionInfoPtr->privateKey;\n\t\t*recipNameObject = sessionInfoPtr->iCertResponse;\n\t\t}\n\telse\n\t\t{\n\t\t*senderNameObject = isClientCryptOnlyKey ? \\\n\t\t\t\t\t\t\tsessionInfoPtr->iAuthOutContext : \\\n\t\t\t\t\t\t\tsessionInfoPtr->iCertRequest;\n\t\t*recipNameObject = sessionInfoPtr->iAuthInContext;\n\t\t}\n\n\t/* Get the sender DN information */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( *senderNameObject, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_SUBJECT );\n\tif( status == CRYPT_ERROR_NOTFOUND && isInitialClientMessage )\n\t\t{\n\t\t/* If there's no subject DN present and it's the first message in a \n\t\t   client's ir exchange, this isn't an error because the subject \n\t\t   usually won't know their DN yet.  That's the theory anyway, \n\t\t   some X.500-obsessive servers will reject a message with no \n\t\t   sender name but there isn't really anything that we can do about \n\t\t   this, particularly since we can't tell in advance what beaviour \n\t\t   the server will exhibit */\n\t\tif( sessionInfoPtr->iCertResponse == CRYPT_ERROR )\n\t\t\t{\n\t\t\t*senderNameObject = CRYPT_ERROR;\n\t\t\tmsgData.length = sizeofShortObject( 0 );\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Try again with the response from the server, which contains \n\t\t\t   our newly-allocated DN */\n\t\t\t*senderNameObject = sessionInfoPtr->iCertResponse;\n\t\t\tstatus = krnlSendMessage( *senderNameObject,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*senderNameLength = msgData.length;\n\n\t/* Get the recipient DN information */\n\tsetMessageData( &msgData, NULL, 0 );\n\tif( *recipNameObject != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( *recipNameObject, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_SUBJECT );\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're sending an error response there may not be any recipient \n\t\t   name information present yet if the error occurred before the \n\t\t   recipient information could be established, and if this is a MAC-\n\t\t   authenticated PKIBoot we don't have the CA's certificate yet so \n\t\t   we don't know its DN.  To work around this we send a zero-length \n\t\t   DN (this is one of those places where an optional field is \n\t\t   specified as being mandatory, to lend balance to the places where \n\t\t   mandatory fields are specified as optional) */\n\t\tmsgData.length = sizeofShortObject( 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*recipNameLength = msgData.length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite a PKI Header\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a PKI header.  Fields marked with a * are unnecessary and are only \n   sent when we're not sending minimal headers.  Fields marked with a + are\n   only sent in the first message or when not sending minimal headers:\n\n\theader\t\t\t\tSEQUENCE {\n\t\tversion\t\t\tINTEGER (2),\n\t   *sender\t\t[4]\tEXPLICIT DirectoryName,\t-- DN of initiator\n\t   *recipient\t[4]\tEXPLICIT DirectoryName,\t-- DN of responder\n\t\tprotAlgo\t[1]\tEXPLICIT AlgorithmIdentifier,\n\t   +protKeyID\t[2] EXPLICIT OCTET STRING,\n\t\ttransID\t\t[4] EXPLICIT OCTET STRING SIZE (16),-- Random/copied from sender\n\t   *nonce\t\t[5] EXPLICIT OCTET STRING SIZE (16),-- Random\n\t   *nonceX\t\t[6] EXPLICIT OCTET STRING SIZE (n),\t-- Copied from sender\n\t\tgeneralInfo\t[8] EXPLICIT SEQUENCE OF Info OPT\t-- cryptlib-specific info\n\t\t} \n\n   The handling can get a bit complex if we're writing a header in response\n   to an error in reading the other side's header.  Since CMP includes such \n   a large amount of unnecessary or redundant information, it's not really \n   possible to detect in advance if we've got enough information to send a\n   header or not, the best that we can do is to require that enough of the \n   header fields have been read (indicated by the 'headerRead' flag in the \n   protocol information) before we try and create our own header in \n   response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writePkiHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_HANDLE senderNameObject DUMMY_INIT, recipNameObject DUMMY_INIT;\n\tSTREAM nullStream;\n\tMESSAGE_DATA msgData;\n#ifdef USE_FULL_HEADERS\n\tconst BOOLEAN sendFullHeader = TRUE;\n#else\n\tBOOLEAN sendFullHeader = FALSE;\n#endif /* USE_FULL_HEADERS */\n\tBOOLEAN sendClibID = FALSE, sendCertID = FALSE, sendMacInfo = FALSE;\n\tBOOLEAN sendUserID = FALSE;\n\tint senderNameLength, recipNameLength, attributeLength = 0;\n\tint protInfoLength DUMMY_INIT, totalLength, hashAlgo, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Determine which of the many unnecessary and inexplicable bits of the \n\t   CMP header we actually have to send:\n\n\t\tsendCertID: Sent on the first message where it's required (which \n\t\t\tisn't necessarily the first message in an exchange, for example \n\t\t\tit's not used in an ir/ip), either to identify the CA's cert in \n\t\t\ta CTL sent in a PKIBoot response or to identify the signing \n\t\t\tcertificate when we're using signature-based message \n\t\t\tauthentication.\n\n\t\tsendClibID: Sent on the first message to tell the other side that \n\t\t\tthis is a cryptlib client/server.\n\n\t\tsendFullHeader: Sent if the other side isn't running cryptlib, unless\n\t\t\twe're doing PKIBoot, for which we couldn't send full headers even \n\t\t\tif we wanted to \n\t\n\t\tsendMacInfo: Sent if we're using MAC integrity protection and the\n\t\t\tthe other side isn't running cryptlib, or if this is the first \n\t\t\tmessage.\n\n\t\tsendUserID: Sent on the first message or if we're sending full \n\t\t\theaders, provided that it's actually available to send */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\tCMP_PFLAG_CERTIDSENT ) && \\\n\t\t( ( isServer( sessionInfoPtr ) && \\\n\t\t\tprotocolInfo->operation == CTAG_PB_GENM ) || \\\n\t\t  !protocolInfo->useMACsend ) )\n\t\t{\n\t\tsendCertID = TRUE;\n\t\t}\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\tCMP_PFLAG_CLIBIDSENT ) )\n\t\t{\n\t\tsendClibID = TRUE;\n\t\t}\n#ifndef USE_FULL_HEADERS\n\tif( !protocolInfo->isCryptlib && \\\n\t\tprotocolInfo->operation != CTAG_PB_GENM )\n\t\t{\n\t\tsendFullHeader = TRUE;\n\t\t}\n#endif /* !USE_FULL_HEADERS */\n\tif( protocolInfo->useMACsend && \\\n\t\t!( protocolInfo->isCryptlib && \\\n\t\t   TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  CMP_PFLAG_MACINFOSENT ) ) )\n\t\t{\n\t\tsendMacInfo = TRUE;\n\t\t}\n\tif( ( sendFullHeader || \\\n\t\t  !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  CMP_PFLAG_USERIDSENT ) ) && \\\n\t\t( protocolInfo->userIDsize > 0 ) )\n\t\t{\n\t\tsendUserID = TRUE;\n\t\t}\n\n\tREQUIRES( !sendFullHeader || !protocolInfo->headerRead || \\\n\t\t\t  isShortIntegerRangeNZ( protocolInfo->userIDsize ) );\n\tREQUIRES( isShortIntegerRangeNZ( protocolInfo->transIDsize ) );\n\n\t/* Get any other state information that we may need */\n\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &hashAlgo, \n\t\t\t\t\t\t\t  CRYPT_OPTION_ENCR_HASH );\n\tENSURES( cryptStatusOK( status ) );\n\tprotocolInfo->hashAlgo = hashAlgo;\t/* int vs.enum */\n\n\t/* Determine how big the sender and recipient information will be.  We \n\t   shouldn't need to send a recipient name for an ir because it won't\n\t   usually be known yet, but various implementations can't handle a \n\t   zero-length GeneralName so we supply it if it's available even though \n\t   it's redundant */\n\tif( sendFullHeader )\n\t\t{\n\t\tstatus = initDNInfo( sessionInfoPtr, &senderNameObject, \n\t\t\t\t\t\t\t &recipNameObject, &senderNameLength, \n\t\t\t\t\t\t\t &recipNameLength, \n\t\t\t\t\t\t\t ( protocolInfo->operation == CTAG_PB_IR ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE,\n\t\t\t\t\t\t\t protocolInfo->cryptOnlyKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* We're not using sender or recipient information since it doesn't \n\t\t   serve any useful purpose, just set the fields to an empty \n\t\t   SEQUENCE */\n\t\tsenderNameLength = recipNameLength = sizeofObject( 0 );\n\t\t}\n\n\t/* Determine how big the remaining header data will be */\n\tsMemNullOpen( &nullStream );\n\tif( protocolInfo->useMACsend )\n\t\t{\n\t\tstatus = writeMacInfo( &nullStream, protocolInfo, sendMacInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeContextAlgoIDex( &nullStream, \n\t\t\t\t\t\t\t\t\t   protocolInfo->authContext, \n\t\t\t\t\t\t\t\t\t   protocolInfo->hashAlgo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tprotInfoLength = stell( &nullStream );\n\tsMemClose( &nullStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sendClibID )\n\t\t{\n\t\tattributeLength += sizeofObject( \\\n\t\t\t\t\t\t\t\tsizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \\\n\t\t\t\t\t\t\t\tsizeofObject( 0 ) );\n\t\t}\n\tif( sendCertID )\n\t\t{\n\t\tconst int certIDsize = sizeofCertID( protocolInfo->authContext );\n\n\t\tENSURES( isShortIntegerRangeNZ( certIDsize ) );\n\n\t\tattributeLength += certIDsize;\n\t\t}\n\ttotalLength = sizeofShortInteger( CMP_VERSION ) + \\\n\t\t\t\t  objSize( senderNameLength ) + objSize( recipNameLength ) + \\\n\t\t\t\t  objSize( protInfoLength ) + \\\n\t\t\t\t  objSize( sizeofObject( protocolInfo->transIDsize ) );\n\tif( sendUserID )\n\t\ttotalLength += objSize( sizeofObject( protocolInfo->userIDsize ) );\n\tif( sendFullHeader )\n\t\t{\n\t\tif( protocolInfo->senderNonceSize > 0 )\n\t\t\t{\n\t\t\ttotalLength += objSize( \\\n\t\t\t\t\t\t\t\tsizeofObject( protocolInfo->senderNonceSize ) );\n\t\t\t}\n\t\tif( protocolInfo->recipNonceSize > 0 )\n\t\t\t{\n\t\t\ttotalLength += objSize( \\\n\t\t\t\t\t\t\t\tsizeofObject( protocolInfo->recipNonceSize ) );\n\t\t\t}\n\t\t}\n\tif( attributeLength > 0 )\n\t\ttotalLength += objSize( objSize( attributeLength ) );\n\n\t/* Perform an early check for data-size problems before we go through \n\t   all of the following code */\n\tif( sizeofObject( totalLength ) <= 0 || \\\n\t\tsizeofObject( totalLength ) > sMemDataLeft( stream ) )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Write the PKI header wrapper, version information, and sender and \n\t   recipient names if there's name information present */\n\twriteSequence( stream, totalLength );\n\twriteShortInteger( stream, CMP_VERSION, DEFAULT_TAG );\n\tif( sendFullHeader )\n\t\t{\n\t\twriteConstructed( stream, senderNameLength, 4 );\n\t\tif( senderNameObject != CRYPT_ERROR )\n\t\t\t{\n\t\t\tstatus = exportAttributeToStream( stream, senderNameObject, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\telse\n\t\t\twriteSequence( stream, 0 );\n\t\twriteConstructed( stream, recipNameLength, 4 );\n\t\tif( recipNameObject != CRYPT_ERROR )\n\t\t\t{\n\t\t\tstatus = exportAttributeToStream( stream, recipNameObject, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\t\t\t}\n\t\telse\n\t\t\tstatus = writeSequence( stream, 0 );\n\t\t}\n\telse\n\t\t{\n\t\t/* This is one of the portions of CMP where an optional field is \n\t\t   marked as mandatory, to balance out the mandatory fields that are \n\t\t   marked as optional.  To work around this we write the names as \n\t\t   zero-length DNs */\n\t\twriteConstructed( stream, senderNameLength, 4 );\n\t\twriteSequence( stream, 0 );\n\t\twriteConstructed( stream, recipNameLength, 4 );\n\t\tstatus = writeSequence( stream, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the protection information, assorted nonces and IDs, and extra\n\t   information that the other side may be able to make use of */\n\twriteConstructed( stream, protInfoLength, CTAG_PH_PROTECTIONALGO );\n\tif( protocolInfo->useMACsend )\n\t\t{\n\t\tstatus = writeMacInfo( stream, protocolInfo, sendMacInfo );\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_MACINFOSENT );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeContextAlgoIDex( stream, protocolInfo->authContext, \n\t\t\t\t\t\t\t\t\t   protocolInfo->hashAlgo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sendUserID )\n\t\t{\n\t\t/* We're using full headers or we're the client sending our first\n\t\t   message, identify the sender key */\n\t\twriteConstructed( stream, objSize( protocolInfo->userIDsize ),\n\t\t\t\t\t\t  CTAG_PH_SENDERKID );\n\t\twriteOctetString( stream, protocolInfo->userID,\n\t\t\t\t\t\t  protocolInfo->userIDsize, DEFAULT_TAG );\n\t\tDEBUG_PRINT(( \"%s: Writing userID.\\n\",\n\t\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\" ));\n\t\tDEBUG_DUMP_HEX( protocolInfo->isServer ? \"SVR\" : \"CLI\", \n\t\t\t\t\t\tprotocolInfo->userID, protocolInfo->userIDsize );\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_USERIDSENT );\n\t\t}\n\twriteConstructed( stream, objSize( protocolInfo->transIDsize ),\n\t\t\t\t\t  CTAG_PH_TRANSACTIONID );\n\tstatus = writeOctetString( stream, protocolInfo->transID,\n\t\t\t\t\t\t\t   protocolInfo->transIDsize, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sendFullHeader )\n\t\t{\n\t\tif( protocolInfo->senderNonceSize > 0 )\n\t\t\t{\n\t\t\t/* We're using nonces, generate a new sender nonce (the initial \n\t\t\t   nonce will have been set when the protocol state was \n\t\t\t   initialised) */\n\t\t\tsetMessageData( &msgData, protocolInfo->senderNonce,\n\t\t\t\t\t\t\tprotocolInfo->senderNonceSize );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\twriteConstructed( stream, \n\t\t\t\t\t\t\t  objSize( protocolInfo->senderNonceSize ),\n\t\t\t\t\t\t\t  CTAG_PH_SENDERNONCE );\n\t\t\tstatus = writeOctetString( stream, protocolInfo->senderNonce,\n\t\t\t\t\t\t\t\t\t   protocolInfo->senderNonceSize, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\t}\n\t\tif( protocolInfo->recipNonceSize > 0 )\n\t\t\t{\n\t\t\twriteConstructed( stream, \n\t\t\t\t\t\t\t  objSize( protocolInfo->recipNonceSize ),\n\t\t\t\t\t\t\t  CTAG_PH_RECIPNONCE );\n\t\t\tstatus = writeOctetString( stream, protocolInfo->recipNonce,\n\t\t\t\t\t\t\t\t\t   protocolInfo->recipNonceSize, \n\t\t\t\t\t\t\t\t\t   DEFAULT_TAG );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( attributeLength > 0 )\n\t\t{\n\t\tENSURES( sendClibID || sendCertID );\n\n\t\t/* We haven't sent any messages yet, let the other side know that \n\t\t   we're running cryptlib and identify our signing certificate as\n\t\t   required */\n\t\twriteConstructed( stream, objSize( attributeLength ),\n\t\t\t\t\t\t  CTAG_PH_GENERALINFO );\n\t\twriteSequence( stream, attributeLength );\n\t\tif( sendClibID )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_CLIBIDSENT );\n\t\t\twriteSequence( stream, sizeofOID( OID_CRYPTLIB_PRESENCECHECK ) + \\\n\t\t\t\t\t\t\t\t   sizeofObject( 0 ) );\n\t\t\twriteOID( stream, OID_CRYPTLIB_PRESENCECHECK );\n\t\t\tstatus = writeSet( stream, 0 );\n\t\t\t}\n\t\tif( sendCertID )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_CERTIDSENT );\n\t\t\tstatus = writeCertID( stream, protocolInfo->authContext );\n\t\t\t}\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite a PKI Message\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write a PKI message:\n\n\tPkiMessage ::= SEQUENCE {\n\t\theader\t\t\tPKIHeader,\n\t\tbody\t\t\tCHOICE { [0]... [24]... },\n\t\tprotection\t[0]\tBIT STRING\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writePkiMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT CMP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t IN_ENUM( CMPBODY ) const CMPBODY_TYPE bodyType )\n\t{\n\tWRITEMESSAGE_FUNCTION writeMessageFunction;\n\tBYTE protInfo[ 64 + MAX_PKCENCRYPTED_SIZE + 8 ], headerBuffer[ 8 + 8 ];\n\tSTREAM stream;\n\tint headerSize DUMMY_INIT, protInfoSize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( bodyType, CMPBODY ) );\n\n\tDEBUG_PRINT(( \"%s: Writing message body type %d.\\n\",\n\t\t\t\t  protocolInfo->isServer ? \"SVR\" : \"CLI\", bodyType ));\n\n\t/* Write the header and payload so that we can MAC/sign it */\n\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t  sessionInfoPtr->receiveBufSize );\n\tstatus = writePkiHeader( &stream, sessionInfoPtr, protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the message data */\n\twriteMessageFunction = getMessageWriteFunction( bodyType, \n\t\t\t\t\t\t\t\tisServer( sessionInfoPtr ) ? TRUE : FALSE );\n\tENSURES( writeMessageFunction != NULL );\n\tstatus = writeMessageFunction( &stream, sessionInfoPtr, protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Generate the MAC or signature as appropriate */\n\tif( protocolInfo->useMACsend )\n\t\t{\n\t\tINJECT_FAULT( BADSIG_HASH, SESSION_BADSIG_HASH_CMP_1 );\n\t\tstatus = writeMacProtinfo( protocolInfo->iMacContext,\n\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, stell( &stream ),\n\t\t\t\t\t\tprotInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );\n\t\tINJECT_FAULT( BADSIG_HASH, SESSION_BADSIG_HASH_CMP_2 );\n\t\tINJECT_FAULT( BADSIG_DATA, SESSION_BADSIG_DATA_CMP_1 );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeSignedProtinfo( protocolInfo->authContext, \n\t\t\t\t\t\tprotocolInfo->hashAlgo, protocolInfo->hashParam,\n\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, stell( &stream ),\n\t\t\t\t\t\tprotInfo, 64 + MAX_PKCENCRYPTED_SIZE, &protInfoSize );\n\t\tINJECT_FAULT( BADSIG_SIG, SESSION_BADSIG_SIG_CMP_1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemClose( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Attach the MAC/signature to the payload */\n\twriteConstructed( &stream, protInfoSize, CTAG_PM_PROTECTION );\n\tstatus = swrite( &stream, protInfo, protInfoSize );\n\tif( cryptStatusOK( status ) )\n\t\tsessionInfoPtr->receiveBufEnd = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the wrapper and move it onto the front of the message:\n\n\t\treceiveBuffer\t\t\t\t\t\t\t\t  receiveBufSize\n\t\t\t|\t\t\t\t\t\t\t\t\t\t\t\t|\n\t\t\tv\t\t\t\t\t\t\t\t\t\t\t\tv\n\t\t\t+-------+-----------------------+---------------+\n\t\t\t|\t\t|\t\t\t\t\t\t|\t\t\t\t|\n\t\t\t+-------+-----------------------+---------------+\n\t\t\t|<--+-->|<--- receiveBufend --->|\n\t\t\t\t|\n\t\t\theaderSize\n\n\t   Unfortunately we can't just assume a fixed-length header because a \n\t   few messages (conf and pkiConf) will be short, leading to a 1-byte \n\t   length rather than the more typical 2-byte length */\n\tsMemOpen( &stream, headerBuffer, 8 );\n\tstatus = writeSequence( &stream, sessionInfoPtr->receiveBufEnd );\n\tif( cryptStatusOK( status ) )\n\t\theaderSize = stell( &stream );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\tREQUIRES( boundsCheck( headerSize, sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tmemmove( sessionInfoPtr->receiveBuffer + headerSize,\n\t\t\t sessionInfoPtr->receiveBuffer,\n\t\t\t sessionInfoPtr->receiveBufEnd );\n\tmemcpy( sessionInfoPtr->receiveBuffer, headerBuffer, headerSize );\n\tsessionInfoPtr->receiveBufEnd += headerSize;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/cmp_wrmsg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite CMP Messages Types\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_CMP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPKI Body Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write request body:\n\n\tbody\t\t\t[n]\tEXPLICIT SEQUENCE {\t-- n designates ir/cr/kur/rr\n\t\t\t\t\t\t...\t\t\t\t\t-- CRMF request\n\t\t\t\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeRequestBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\t INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tconst CRYPT_CERTFORMAT_TYPE certType = \\\n\t\t\t\t( protocolInfo->operation == CTAG_PB_RR ) ? \\\n\t\t\t\tCRYPT_ICERTFORMAT_DATA : CRYPT_CERTFORMAT_CERTIFICATE;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Find out how big the payload will be.  Since revocation requests are\n\t   unsigned entities we have to vary the attribute type that we're \n\t   reading (via the certType specifier) based on whether we're \n\t   submitting a signed or unsigned object in the request */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData, certType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the request body */\n\twriteConstructed( stream, objSize( msgData.length ),\n\t\t\t\t\t  protocolInfo->operation );\n\twriteSequence( stream, msgData.length );\n\treturn( exportCertToStream( stream, sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\tcertType ) );\n\t}\n\n/* Write response body:\n\n\tbody\t\t\t[n] EXPLICIT SEQUENCE {\t-- n designates ir/cr/kur\n\t\tresponse\t\tSEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\t\tcertReqID\tINTEGER (0),\t\t-- Not present for rp's\n\t\t\tstatus\t\tPKIStatusInfo,\n\t\t\tcertKeyPair\tSEQUENCE {\nEither\t\t\tcert[0]\tEXPLICIT Certificate,\t-- For sig-capable key\nor\t\t\t\tcmsEncCert\t\t\t\t\t-- For encr-only key\n\t\t\t\t\t[2] EXPLICIT EncryptedCert\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tbody\t\t\t[n] EXPLICIT SEQUENCE {\t-- n designates rr\n\t\tresponse\t\tSEQUENCE {\n\t\t\tstatus\t\tPKIStatusInfo\n\t\t\t}\n\t\t}\n\n   If we're returning an encryption-only certificate we send it as standard \n   CMS data under a new tag to avoid having to hand-assemble the garbled \n   mess that CMP uses for this */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeResponseBodyHeader( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tIN_ENUM_OPT( CMP_MESSAGE ) \\\n\t\t\t\t\t\t\t\t\t\tconst CMP_MESSAGE_TYPE operationType,\n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int payloadSize )\n\t{\n\tconst int respType = reqToResp( operationType );\n\tconst int statusInfoLength = sizeofPkiStatusInfo( CRYPT_OK, 0 );\n\tint totalPayloadSize;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( operationType >= CTAG_PB_IR && operationType < CTAG_PB_LAST );\n\t\t\t  /* CTAG_PB_IR == 0 so this is the same as _NONE */\n\tREQUIRES( isShortIntegerRange( payloadSize ) );\n\tREQUIRES( respType >= CTAG_PB_IP && respType < CTAG_PB_LAST );\n\t\n\t/* If it's a revocation response then the only content is the \n\t   OK-status */\n\tif( respType == CTAG_PB_RP )\n\t\t{\n\t\twriteConstructed( stream, objSize( objSize( statusInfoLength ) ),\n\t\t\t\t\t\t  CTAG_PB_RP );\n\t\twriteSequence( stream, objSize( statusInfoLength ) );\n\t\twriteSequence( stream, statusInfoLength );\n\t\treturn( writePkiStatusInfo( stream, CRYPT_OK, 0 ) );\n\t\t}\n\n\t/* Calculate the overall size of the header and payload */\n\ttotalPayloadSize = payloadSize + sizeofShortInteger( 0 ) + \\\n\t\t\t\t\t   statusInfoLength;\n\n\t/* Write the response body wrapper */\n\twriteConstructed( stream, objSize( objSize( objSize( totalPayloadSize ) ) ),\n\t\t\t\t\t  respType );\n\twriteSequence( stream, objSize( objSize( totalPayloadSize ) ) );\n\n\t/* Write the response.  We always write an OK status here because an \n\t   error will have been communicated by sending an explicit error \n\t   response */\n\twriteSequence( stream, objSize( totalPayloadSize ) );\n\twriteSequence( stream, totalPayloadSize );\n\twriteShortInteger( stream, 0, DEFAULT_TAG );\n\treturn( writePkiStatusInfo( stream, CRYPT_OK, 0 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeEncryptedResponseBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tvoid *srcPtr, *destPtr;\n\tint dataLength, destLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Get a pointer into the stream buffer.  To avoid having to juggle two\n\t   buffers we use the stream buffer some distance ahead of the write\n\t   position as a temporary location to store the encoded certificate for\n\t   encryption:\n\n\t\t  buffer\t\t\t\t srcPtr\n\t\t\t|\t\t\t\t\t\t|\n\t\t\tv\t\t\t\t\t\tv\n\t\t\t+-------+---+-----------+-----------------------+\n\t\t\t|  Hdr\t|-->|\t\t\t|\t\t\t\t\t\t|\n\t\t\t+-------+---+-----------+-----------------------+\n\t\t\t\t\t\t|<-- 100 -->|<---- dataLength ----->| */\n\tstatus = sMemGetDataBlockRemaining( stream, &srcPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsrcPtr = ( BYTE * ) srcPtr + 100;\n\tdataLength -= 100;\n\tENSURES( dataLength >= 1024 && dataLength < sMemDataLeft( stream ) );\n\n\t/* Extract the response data into the session buffer and wrap it using \n\t   the client's certificate.  Since the client doesn't actually have the \n\t   certificate yet (only we have it, since it's only just been issued) \n\t   we have to use the S/MIME v3 format (keys identified by key ID rather \n\t   than issuerAndSerialNumber) because the client won't know its iAndS \n\t   until it decrypts the certificate */\n\tsetMessageData( &msgData, srcPtr, dataLength );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = envelopeWrap( srcPtr, msgData.length, srcPtr, dataLength, \n\t\t\t\t\t\t   &dataLength, CRYPT_FORMAT_CRYPTLIB, \n\t\t\t\t\t\t   CRYPT_CONTENT_NONE, \n\t\t\t\t\t\t   sessionInfoPtr->iCertResponse, NULL, 0, \n\t\t\t\t\t\t   &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo, \n\t\t\t\t\t \"Couldn't wrap response data: \" ) );\n\t\t}\n\n\t/* Write the response body header */\n\tstatus = writeResponseBodyHeader( stream, protocolInfo->operation, \n\t\t\t\t\t\t\t\t\t  objSize( objSize( dataLength ) ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the encrypted certificate.  In theory we could use an swrite()\n\t   to move the data rather than a memmove() directly into the buffer but \n\t   this is a bit risky because the read position is only about 30-40 \n\t   bytes ahead of the write position and it's not guaranteed that the \n\t   two won't interfere:\n\n\t\t  buffer\t destPtr\t srcPtr\n\t\t\t|\t\t\t|\t\t\t|\n\t\t\tv\t\t\tv\t\t\tv\n\t\t\t+-----------+-----------+-----------------------+\n\t\t\t|\tHdr\t\t|\t\t\t|\t\t\t\t\t\t|\n\t\t\t+-----------+-----------+-----------------------+\n\t\t\t\t\t\t|\t\t\t|<---- dataLength ----->|\n\t\t\t\t\t\t|<---------- destLength ----------->| */\n\twriteSequence( stream, objSize( dataLength ) );\n\twriteConstructed( stream, dataLength, CTAG_CK_NEWENCRYPTEDCERT );\n\tstatus = sMemGetDataBlockRemaining( stream, &destPtr, &destLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( dataLength <= destLength );\n\t\t\t /* Should never occur since it implies that we're overwritten\n\t\t\t\tthe start of the wrapped certificate */\n\tREQUIRES( rangeCheck( dataLength, 1, destLength ) );\n\tmemmove( destPtr, srcPtr, dataLength );\n\treturn( sSkip( stream, dataLength, SSKIP_MAX ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeResponseBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\t  INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tint dataLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Revocation request responses have no body */\n\tif( protocolInfo->operation == CTAG_PB_RR )\n\t\t{\n\t\treturn( writeResponseBodyHeader( stream, protocolInfo->operation, \n\t\t\t\t\t\t\t\t\t\t 0 ) );\n\t\t}\n\n\t/* If it's an encryption-only key we return the certificate in encrypted\n\t   form, the client performs POP by decrypting the returned \n\t   certificate */\n\tif( protocolInfo->cryptOnlyKey )\n\t\t{\n\t\treturn( writeEncryptedResponseBody( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tprotocolInfo ) );\n\t\t}\n\n\t/* Write the response body header */\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdataLength = msgData.length;\n\tstatus = writeResponseBodyHeader( stream, protocolInfo->operation, \n\t\t\t\t\t\t\t\t\t  objSize( objSize( dataLength ) ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the certificate data */\n\twriteSequence( stream, objSize( dataLength ) );\n\twriteConstructed( stream, dataLength, CTAG_CK_CERT );\n\treturn( exportCertToStream( stream, sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE ) );\n\t}\n\n/* Write conf body:\n\n\tbody\t\t   [19]\tEXPLICIT SEQUENCE {\n\t\t\t\t\t\tSEQUENCE {\n\t\tcertHash\t\tOCTET STRING\n\t\tcertReqID\t\tINTEGER (0),\n\t\t\t}\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeConfBody( INOUT STREAM *stream,\n\t\t\t\t\t\t  INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tstatic const MAP_TABLE fingerprintMapTable[] = {\n\t\t{ CRYPT_ALGO_SHA1, CRYPT_CERTINFO_FINGERPRINT_SHA1 },\n\t\t{ CRYPT_ALGO_SHA2, CRYPT_CERTINFO_FINGERPRINT_SHA2 },\n\t\t{ CRYPT_ALGO_SHAng, CRYPT_CERTINFO_FINGERPRINT_SHAng },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tMESSAGE_DATA msgData;\n\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint length, fingerprintType, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Get the certificate hash */\n\tstatus = mapValue( protocolInfo->confHashAlgo, &fingerprintType,\n\t\t\t\t\t   fingerprintMapTable, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( fingerprintMapTable, MAP_TABLE ) );\n\tENSURES( cryptStatusOK( status ) );\n\tsetMessageData( &msgData, hashBuffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  fingerprintType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tlength = objSize( msgData.length ) + sizeofShortInteger( 0 );\n\n\t/* Write the confirmation body */\n\twriteConstructed( stream, objSize( objSize( length ) ),\n\t\t\t\t\t  CTAG_PB_CERTCONF );\n\twriteSequence( stream, objSize( length ) );\n\twriteSequence( stream, length );\n\twriteOctetString( stream, hashBuffer, msgData.length, DEFAULT_TAG );\n\treturn( writeShortInteger( stream, 0, DEFAULT_TAG ) );\n\t}\n\n/* Write pkiConf body:\n\n\tbody\t\t   [24]\tEXPLICIT NULL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writePKIConfBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\t STDC_UNUSED SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t STDC_UNUSED const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\twriteConstructed( stream, sizeofNull(), CTAG_PB_PKICONF );\n\treturn( writeNull( stream, DEFAULT_TAG ) );\n\t}\n\n/* Write genMsg body:\n\n\tbody\t\t   [21]\tEXPLICIT SEQUENCE OF {\n\t\t\t\t\t\tSEQUENCE {\n\t\tinfoType\t\tOBJECT IDENTIFIER,\n\t\tintoValue\t\tANY DEFINED BY infoType OPTIONAL\n\t\t\t\t\t\t}\n\t\t\t\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeGenMsgRequestBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\tSTDC_UNUSED SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tSTDC_UNUSED const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\twriteConstructed( stream, objSize( objSize( sizeofOID( OID_PKIBOOT ) ) ),\n\t\t\t\t\t  CTAG_PB_GENM );\n\twriteSequence( stream, objSize( sizeofOID( OID_PKIBOOT ) ) );\n\twriteSequence( stream, sizeofOID( OID_PKIBOOT ) );\n\treturn( writeOID( stream, OID_PKIBOOT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeGenMsgResponseBody( INOUT STREAM *stream,\n\t\t\t\t\t\t\tINOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tSTDC_UNUSED const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_CERTIFICATE iCTL;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionCMP( sessionInfoPtr ) );\n\n\t/* Get the CTL from the CA object.  We recreate this each time rather \n\t   than cacheing it in the session to ensure that changes in the trusted\n\t   certificate set while the session is active get reflected back to the \n\t   caller.\n\t   \n\t   In addition to the explicitly trusted certificates we also include \n\t   the CA certificate(s) in the CTL as implicitly-trusted certificates.  \n\t   This is done both because users often forget to mark them as trusted \n\t   on the server and then wonder where their CA certificates are on the \n\t   client, and because these should inherently be trusted since the user \n\t   is about to get their certificates issued by them */\n\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &iCTL,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CTL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\treturn( status );\n\n\t\t/* If there are no trusted certificates present then we won't be \n\t\t   able to assemble a CTL, so we explicitly create an empty CTL to \n\t\t   add the CA certificate to */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTCHAIN );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiCTL = createInfo.cryptHandle;\n\t\t}\n\tstatus = krnlSendMessage( iCTL, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTCOLLECTION );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCTL, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( iCTL, IMESSAGE_CRT_EXPORT, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTCHAIN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCTL, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the response body wrapper.  As with the certificate ID, we can \n\t   use the imprecision of the ASN.1 that CMP is specified in to \n\t   interpret the InfoTypeAndValue:\n\n\t\tInfoTypeAndValue ::= SEQUENCE {\n\t\t\tinfoType\tOBJECT IDENTIFIER,\n\t\t\tinfoValue\tANY DEFINED BY infoType OPTIONAL\n\t\t\t}\n\n\t   as:\n\n\t\tinfoType ::= id-signedData\n\t\tinfoValue ::= [0] EXPLICIT SignedData\n\n\t   which makes it standard CMS data that can be passed directly to the \n\t   CMS code */\n\twriteConstructed( stream, objSize( msgData.length ), CTAG_PB_GENP );\n\twriteSequence( stream, msgData.length );\n\tstatus = exportCertToStream( stream, iCTL, CRYPT_CERTFORMAT_CERTCHAIN );\n\tkrnlSendNotifier( iCTL, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/* Write error body:\n\n\tbody\t\t   [23]\tEXPLICIT SEQUENCE {\n\t\tstatus\t\t\tPKIStatusInfo\n\t\t\t\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writeErrorBody( INOUT STREAM *stream,\n\t\t\t\t\t\t   STDC_UNUSED SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   const CMP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tconst int statusInfoLength = \\\n\t\tsizeofPkiStatusInfo( protocolInfo->status, protocolInfo->pkiFailInfo );\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( statusInfoLength ) );\n\n\t/* Write the error body */\n\twriteConstructed( stream, objSize( statusInfoLength ), CTAG_PB_ERROR );\n\twriteSequence( stream, statusInfoLength );\n\treturn( writePkiStatusInfo( stream, protocolInfo->status,\n\t\t\t\t\t\t\t\tprotocolInfo->pkiFailInfo ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tWrite Function Access Information\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\ntypedef struct {\n\tconst CMPBODY_TYPE type;\n\tconst WRITEMESSAGE_FUNCTION function;\n\t} MESSAGEWRITE_INFO;\nstatic const MESSAGEWRITE_INFO messageWriteClientTable[] = {\n\t{ CMPBODY_NORMAL, writeRequestBody },\n\t{ CMPBODY_CONFIRMATION, writeConfBody },\n\t{ CMPBODY_GENMSG, writeGenMsgRequestBody },\n\t{ CMPBODY_ERROR, writeErrorBody },\n\t{ CMPBODY_NONE, NULL }, { CMPBODY_NONE, NULL }\n\t};\nstatic const MESSAGEWRITE_INFO messageWriteServerTable[] = {\n\t{ CMPBODY_NORMAL, writeResponseBody },\n\t{ CMPBODY_ACK, writePKIConfBody },\n\t{ CMPBODY_GENMSG, writeGenMsgResponseBody },\n\t{ CMPBODY_ERROR, writeErrorBody },\n\t{ CMPBODY_NONE, NULL }, { CMPBODY_NONE, NULL }\n\t};\n\nCHECK_RETVAL_PTR \\\nWRITEMESSAGE_FUNCTION getMessageWriteFunction( IN_ENUM( CMPBODY ) \\\n\t\t\t\t\t\t\t\t\tconst CMPBODY_TYPE bodyType,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isServer )\n\t{\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES_N( isEnumRange( bodyType, CMPBODY ) );\n\tREQUIRES_N( isServer == TRUE || isServer == FALSE );\n\n\tif( isServer )\n\t\t{\n\t\tLOOP_SMALL( i = 0, \n\t\t\t\t\tmessageWriteServerTable[ i ].type != CMPBODY_NONE && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( messageWriteServerTable, \\\n\t\t\t\t\t\t\t\t\t\t\t\tMESSAGEWRITE_INFO ), \n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( messageWriteServerTable[ i ].type == bodyType )\n\t\t\t\treturn( messageWriteServerTable[ i ].function );\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( i < FAILSAFE_ARRAYSIZE( messageWriteServerTable, MESSAGEWRITE_INFO ) );\n\t\t}\n\telse\n\t\t{\n\t\tLOOP_SMALL( i = 0, \n\t\t\t\t\tmessageWriteClientTable[ i ].type != CMPBODY_NONE && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( messageWriteClientTable, \\\n\t\t\t\t\t\t\t\t\t\t\t\tMESSAGEWRITE_INFO ), \n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tif( messageWriteClientTable[ i ].type == bodyType )\n\t\t\t\treturn( messageWriteClientTable[ i ].function );\n\t\t\t}\n\t\tENSURES_N( LOOP_BOUND_OK );\n\t\tENSURES_N( i < FAILSAFE_ARRAYSIZE( messageWriteClientTable, MESSAGEWRITE_INFO ) );\n\t\t}\n\n\treturn( NULL );\n\t}\n#endif /* USE_CMP */\n"
  },
  {
    "path": "deps/cl345/session/ocsp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib OCSP Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_OCSP\n\n/* OCSP HTTP content types */\n\n#define OCSP_CONTENT_TYPE_REQ\t\t\"application/ocsp-request\"\n#define OCSP_CONTENT_TYPE_REQ_LEN\t24\n#define OCSP_CONTENT_TYPE_RESP\t\t\"application/ocsp-response\"\n#define OCSP_CONTENT_TYPE_RESP_LEN\t25\n\n/* OCSP query/response types */\n\ntypedef enum {\n\tOCSPRESPONSE_TYPE_NONE,\t\t\t\t/* No response type */\n\tOCSPRESPONSE_TYPE_OCSP,\t\t\t\t/* OCSP standard response */\n\tOCSPRESPONSE_TYPE_LAST\t\t\t\t/* Last valid response type */\n\t} OCSPRESPONSE_TYPE;\n\n/* OCSP response status values */\n\nenum { OCSP_RESP_SUCCESSFUL, OCSP_RESP_MALFORMEDREQUEST,\n\t   OCSP_RESP_INTERNALERROR, OCSP_RESP_TRYLATER, OCSP_RESP_DUMMY,\n\t   OCSP_RESP_SIGREQUIRED, OCSP_RESP_UNAUTHORISED };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Deliver an Einladung betreff Kehrseite to the client.  We don't bother\n   checking the return value since there's nothing that we can do in the\n   case of an error except close the connection, which we do anyway since\n   this is the last message */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_BUFFER( responseDataLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *responseData,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int responseDataLength )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( responseData, responseDataLength ) );\n\n\tREQUIRES_V( isShortIntegerRangeNZ( responseDataLength ) );\n\n\t/* Since we're already in an error state there's not much that we can do\n\t   in terms of alerting the user if a further error occurs when writing \n\t   the error response, so we ignore any potential write errors that occur\n\t   at this point */\n\tREQUIRES_V( rangeCheck( responseDataLength, 1, \n\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize ) );\n\tmemcpy( sessionInfoPtr->receiveBuffer, responseData,\n\t\t\tresponseDataLength );\n\tsessionInfoPtr->receiveBufEnd = responseDataLength;\n\t( void ) writePkiDatagram( sessionInfoPtr, OCSP_CONTENT_TYPE_RESP,\n\t\t\t\t\t\t\t   OCSP_CONTENT_TYPE_RESP_LEN );\n\t}\n\n/* Compare the nonce in a request with the returned nonce in the response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nstatic int checkNonce( IN_HANDLE const CRYPT_CERTIFICATE iCertResponse,\n\t\t\t\t\t   IN_BUFFER( requestNonceLength ) const void *requestNonce, \n\t\t\t\t\t   IN_LENGTH_SHORT const int requestNonceLength )\n\t{\n\tMESSAGE_DATA responseMsgData;\n\tBYTE responseNonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtrDynamic( requestNonce, requestNonceLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCertResponse ) );\n\tREQUIRES( isShortIntegerRangeNZ( requestNonceLength ) );\n\n\t/* Make sure that the nonce has a plausible length */\n\tif( requestNonceLength < 4 || requestNonceLength > CRYPT_MAX_HASHSIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Try and read the nonce from the response */\n\tsetMessageData( &responseMsgData, responseNonceBuffer,\n\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCertResponse, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &responseMsgData, CRYPT_CERTINFO_OCSP_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Make sure that the two nonces match.  The comparison is in theory \n\t   somewhat complex because OCSP never specifies how the nonce is meant \n\t   to be encoded so it's possible that some implementations will use \n\t   things like TSP's bizarre INTEGER rather than the obvious and logical \n\t   OCTET STRING.  In theory this means that we might need to check for \n\t   the INTEGER-encoding alternatives that arise due to sign bits, but \n\t   this doesn't seem to be required in practice since everyone use a de \n\t   facto encoding of OCTET STRING */\n\tif( requestNonceLength != responseMsgData.length || \\\n\t\tmemcmp( requestNonce, responseMsgData.data, requestNonceLength ) )\n\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClient-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* OID information used to read responses */\n\nstatic const OID_INFO ocspOIDinfo[] = {\n\t{ OID_OCSP_RESPONSE_OCSP, OCSPRESPONSE_TYPE_OCSP },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/* Send a request to an OCSP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendClientRequest( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* If we're fuzzing, there's no request to send out */\n\tFUZZ_SKIP();\n\n\t/* Get the encoded request data.  We store this in the session buffer, \n\t   which at its minimum size is roughly two orders of magnitude larger \n\t   than the request */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't get OCSP request data from OCSP request \"\n\t\t\t\t  \"object\" ) );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd = msgData.length;\n\tDEBUG_DUMP_FILE( \"ocsp_req\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Send the request to the responder */\n\treturn( writePkiDatagram( sessionInfoPtr, OCSP_CONTENT_TYPE_REQ,\n\t\t\t\t\t\t\t  OCSP_CONTENT_TYPE_REQ_LEN ) );\n\t}\n\n/* Read the response from the OCSP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readServerResponse( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCRYPT_CERTIFICATE iCertResponse;\n\tMESSAGE_DATA msgData;\n\tSTREAM_PEER_TYPE peerSystemType;\n\tSTREAM stream;\n\tBYTE nonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n#ifdef USE_ERRMSGS\n\tconst char *errorString = NULL;\n#endif /* USE_ERRMSGS */\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint errorCode, responseType, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Read the response from the responder.  This may be only a few bytes \n\t   in the case of an error response, so we allow a datagram size of 4 \n\t   bytes and then later explicitly check for a valid length if we get a \n\t   non-error response  */\n\tstatus = readPkiDatagram( sessionInfoPtr, 4 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_DUMP_FILE( \"ocsp_resp\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tCFI_CHECK_UPDATE( \"readPkiDatagram\" );\n\n\t/* See whether we can determine the remote system type, used to work \n\t   around bugs in implementations */\n\tstatus = sioctlGet( &sessionInfoPtr->stream, STREAM_IOCTL_GETPEERTYPE, \n\t\t\t\t\t\t&peerSystemType, sizeof( STREAM_PEER_TYPE ) );\n\tif( cryptStatusError( status ) )\n\t\tpeerSystemType = STREAM_PEER_NONE;\n\n\t/* Try and extract an OCSP status code from the returned object:\n\n\t\tSEQUENCE {\n\t\t\trespStatus\t\t\tENUMERATED,\t\t\t-- 0 = OK\n\t\t\trespBytes\t\t[0]\tEXPLICIT SEQUENCE {\t-- If status == OK\n\t\t\t\t\t\t\t\t... */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treadSequence( &stream, NULL );\n\tstatus = readEnumerated( &stream, &errorCode );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid OCSP response status data\" ) );\n\t\t}\n\n\t/* If it's an error status, try and translate it into something a bit \n\t   more meaningful.  Some of the translations are a bit questionable, \n\t   but it's better than the generic no va response (which should \n\t   actually be \"no marcha\" in any case) */\n\tswitch( errorCode )\n\t\t{\n\t\tcase OCSP_RESP_SUCCESSFUL:\n\t\t\tstatus = CRYPT_OK;\n\t\t\tbreak;\n\n\t\tcase OCSP_RESP_TRYLATER:\n\t\t\tstatus = CRYPT_ERROR_NOTAVAIL;\n\t\t\tbreak;\n\n\t\tcase OCSP_RESP_SIGREQUIRED:\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t\tbreak;\n\n\t\tcase OCSP_RESP_UNAUTHORISED:\n\t\t\tstatus = CRYPT_ERROR_PERMISSION;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t\tbreak;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n#ifdef USE_ERRMSGS\n\t\tswitch( errorCode )\n\t\t\t{\n\t\t\tcase OCSP_RESP_TRYLATER:\n\t\t\t\terrorString = \"Try again later\";\n\t\t\t\tbreak;\n\n\t\t\tcase OCSP_RESP_SIGREQUIRED:\n\t\t\t\terrorString = \"Signed OCSP request required\";\n\t\t\t\tbreak;\n\n\t\t\tcase OCSP_RESP_UNAUTHORISED:\n\t\t\t\tif( peerSystemType == STREAM_PEER_MICROSOFT || \\\n\t\t\t\t\tpeerSystemType == STREAM_PEER_MICROSOFT_2008 || \\\n\t\t\t\t\tpeerSystemType == STREAM_PEER_MICROSOFT_2012 )\n\t\t\t\t\t{\n\t\t\t\t\terrorString = \"Client isn't authorised to perform query.  \"\n\t\t\t\t\t\t\t\t  \"This is probably due to a Windows Server \"\n\t\t\t\t\t\t\t\t  \"configuration issue, the server \"\n\t\t\t\t\t\t\t\t  \"administrator needs to enable 'Allow \"\n\t\t\t\t\t\t\t\t  \"Nonce requests' for compliance with RFC \"\n\t\t\t\t\t\t\t\t  \"2560\";\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\terrorString = \"Client isn't authorised to perform query\";\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\terrorString = \"Unknown error\";\n\t\t\t\tbreak;\n\t\t\t}\n#endif /* USE_ERRMSGS */\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t   \"OCSP server returned status %d: %s\",\n\t\t\t\t   errorCode, errorString ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readEnumerated\" );\n\n\t/* Now that we know we've got an actual OCSP response rather than just a \n\t   few bytes of error status, make sure that the data size is valid.  \n\t   This differs from the length check below in that we're checking the \n\t   overall amount of data received, not the value of a length field \n\t   inside the data.\n\n\t   Note that the following error message is the same as what\n\t   readPkiDatagram() reports, since we're checking the received message \n\t   length and not the OCSP response length */\n\tif( sessionInfoPtr->receiveBufEnd < MIN_CRYPT_OBJECTSIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_UNDERFLOW,\n\t\t\t\t( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKI message length %d\", \n\t\t\t\t  sessionInfoPtr->receiveBufEnd ) );\n\t\t}\n\n\t/* We've got a valid response, read the [0] EXPLICIT SEQUENCE { OID,\n\t   OCTET STRING { encapsulation and import the response into an OCSP\n\t   certificate object */\n\treadConstructed( &stream, NULL, 0 );\t\t/* responseBytes */\n\treadSequence( &stream, NULL );\n\treadOID( &stream, ocspOIDinfo,\t\t\t\t/* responseType */\n\t\t\t FAILSAFE_ARRAYSIZE( ocspOIDinfo, OID_INFO ), &responseType );\n\tstatus = readGenericHole( &stream, &length, 16, DEFAULT_TAG );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid OCSP response data header\" ) );\n\t\t}\n\tif( length < MIN_CRYPT_OBJECTSIZE || length >= MAX_INTLENGTH_SHORT )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid OCSP response size %d, should be %d...%d\", \n\t\t\t\t  length, MIN_CRYPT_OBJECTSIZE, MAX_INTLENGTH_SHORT ) );\n\t\t}\n\tstatus = importCertFromStream( &stream, &iCertResponse, \n\t\t\t\t\t\t\t\t   DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_OCSP_RESPONSE, length,\n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid OCSP response data\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"importCertFromStream\" );\n\n\t/* If we're fuzzing the input then we're reading static data for which \n\t   the nonces won't match so the check that follows will fail, so we \n\t   have to exit now */\n\tFUZZ_EXIT();\n\n\t/* If the request went out with a nonce included (which it does by\n\t   default), make sure that it matches the nonce in the response */\n\tsetMessageData( &msgData, nonceBuffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_OCSP_NONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* There's a nonce in the request, check that it matches the one in\n\t\t   the response */\n\t\tstatus = checkNonce( iCertResponse, msgData.data, msgData.length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* The response doesn't contain a nonce or it doesn't match what \n\t\t\t   we sent, we can't trust it.  The best error that we can return \n\t\t\t   here is a signature error to indicate that the integrity \n\t\t\t   check failed.\n\t\t\t   \n\t\t\t   Note that a later modification to OCSP, in an attempt to make \n\t\t\t   it scale, removed the nonce, thus breaking the security of \n\t\t\t   the protocol against replay attack.  Since the protocol is \n\t\t\t   now broken against attack we treat a nonce-less response from \n\t\t\t   one of these responders as a failure, since it's \n\t\t\t   indistinguishable from an actual attack */\n\t\t\tkrnlSendNotifier( iCertResponse, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t\t  ( status == CRYPT_ERROR_NOTFOUND ) ? \\\n\t\t\t\t\t  \"OCSP response doesn't contain a nonce\" : \\\n\t\t\t\t\t  \"OCSP response nonce doesn't match the one in the \"\n\t\t\t\t\t  \"request\" ) );\n\t\t\t}\n\t\t}\n\tkrnlSendNotifier( sessionInfoPtr->iCertRequest, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\tsessionInfoPtr->iCertResponse = iCertResponse;\n\tCFI_CHECK_UPDATE( \"checkNonce\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"readPkiDatagram\", \"readEnumerated\", \n\t\t\t\t\t\t\t\t\t\"importCertFromStream\", \"checkNonce\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tServer-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send an error response back to the client.  Since there are only a small\n   number of these, we write back a fixed blob rather than encoding each\n   one */\n\n#define RESPONSE_SIZE\t\t5\n\nstatic const BYTE respBadRequest[] = {\n\t0x30, 0x03, 0x0A, 0x01, 0x01\t/* Rejection, malformed request */\n\t};\nstatic const BYTE respIntError[] = {\n\t0x30, 0x03, 0x0A, 0x01, 0x02\t/* Rejection, internal error */\n\t};\n\n/* Read a request from an OCSP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readClientRequest( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCRYPT_CERTIFICATE iOcspRequest;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint tag, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Read the request data from the client.  We don't write an error\n\t   response at this initial stage to prevent scanning/DOS attacks\n\t   (vir sapit qui pauca loquitur) */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_DUMP_FILE( \"ocsp_sreq\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tCFI_CHECK_UPDATE( \"readPkiDatagram\" );\n\n\t/* Basic lint filter to check for approximately-OK requests before we\n\t   try creating a certificate object from the data:\n\n\t\tSEQUENCE {\n\t\t\tSEQUENCE {\t\t\t\t\t-- tbsRequest\n\t\t\t\tversion\t\t[0]\t...\n\t\t\t\treqName\t\t[1]\t...\n\t\t\t\tSEQUENCE {\t\t\t\t-- requestList\n\t\t\t\t\tSEQUENCE {\t\t\t-- request\n\t\t\t\t\t... */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treadSequence( &stream, NULL );\n\tstatus = readSequence( &stream, NULL );\n\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\tstatus = readUniversal( &stream );\n\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\ttag == MAKE_CTAG( 1 ) )\n\t\tstatus = readUniversal( &stream );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\treadSequence( &stream, NULL );\n\t\tstatus = readSequence( &stream, NULL );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid OCSP request header\" ) );\n\t\t}\n\n\t/* Import the request as a cryptlib object */\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_OCSP_REQUEST );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendErrorResponse( sessionInfoPtr, respBadRequest, RESPONSE_SIZE );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid OCSP request data\" ) );\n\t\t}\n\tiOcspRequest = createInfo.cryptHandle;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_CREATEOBJECT_INDIRECT\" );\n\n\t/* If we're fuzzing the input then we're done */\n\tFUZZ_EXIT();\n\n\t/* Create an OCSP response and add the request information to it */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_OCSP_RESPONSE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iOcspRequest, IMESSAGE_DECREFCOUNT );\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &iOcspRequest,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_OCSPREQUEST );\n\tkrnlSendNotifier( iOcspRequest, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create OCSP response from request\" ) );\n\t\t}\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_SETATTRIBUTE\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"readPkiDatagram\",\n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_CREATEOBJECT_INDIRECT\",\n\t\t\t\t\t\t\t\t\t\"IMESSAGE_SETATTRIBUTE\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Return a response to an OCSP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendServerResponse( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tint responseLength, responseDataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Check the entries from the request against the certificate store and \n\t   sign the resulting status information (\"Love, ken\").  Note that\n\t   CRYPT_ERROR_INVALID is a valid return status for the sigcheck call\n\t   since it indicates that one (or more) of the certificates was \n\t   revoked */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGCHECK, NULL,\n\t\t\t\t\t\t\t  sessionInfoPtr->cryptKeyset );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_INVALID )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't check OCSP request against certificate \"\n\t\t\t\t  \"store\" ) );\n\t\t}\n\tsetMessageData( &msgData, NULL, 0 );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGN, NULL,\n\t\t\t\t\t\t\t  sessionInfoPtr->privateKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create signed OCSP response\" ) );\n\t\t}\n\tresponseDataLength = msgData.length;\n\n\t/* Write the wrapper for the response */\n\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t  sessionInfoPtr->receiveBufSize );\n\tresponseLength = sizeofOID( OID_OCSP_RESPONSE_OCSP ) + \\\n\t\t\t\t\t sizeofObject( responseDataLength );\n\twriteSequence( &stream, sizeofEnumerated( 0 ) + \\\n\t\t\t\t   sizeofObject( sizeofObject( responseLength ) ) );\n\twriteEnumerated( &stream, 0, DEFAULT_TAG );\t\t/* respStatus */\n\twriteConstructed( &stream, sizeofObject( responseLength ), 0 );\n\twriteSequence( &stream, responseLength );\t\t/* respBytes */\n\twriteOID( &stream, OID_OCSP_RESPONSE_OCSP );\t/* respType */\n\tstatus = writeOctetStringHole( &stream, responseDataLength, \n\t\t\t\t\t\t\t\t   DEFAULT_TAG );\t/* response */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\treturn( status );\n\t\t}\n\n\t/* Get the encoded response data */\n\tstatus = exportCertToStream( &stream, sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\tsessionInfoPtr->receiveBufEnd = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, respIntError, RESPONSE_SIZE );\n\t\treturn( status );\n\t\t}\n\tDEBUG_DUMP_FILE( \"ocsp_sresp\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Send the response to the client */\n\treturn( writePkiDatagram( sessionInfoPtr, OCSP_CONTENT_TYPE_RESP,\n\t\t\t\t\t\t\t  OCSP_CONTENT_TYPE_RESP_LEN ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with an OCSP client/server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Get certificate revocation information from the server */\n\tstatus = sendClientRequest( sessionInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readServerResponse( sessionInfoPtr );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Send certificate revocation information to the client */\n\tstatus = readClientRequest( sessionInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendServerResponse( sessionInfoPtr );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tControl Information Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst CRYPT_CERTIFICATE ocspRequest = *( ( CRYPT_CERTIFICATE * ) data );\n\tMESSAGE_DATA msgData = { NULL, 0 };\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_REQUEST );\n\n\t/* Make sure that everything is set up ready to go.  Since OCSP requests\n\t   aren't (usually) signed like normal certificate objects we can't just \n\t   check the immutable attribute but have to perform a dummy export for \n\t   which the certificate export code will return an error status if \n\t   there's a problem with the request.  If not, it pseudo-signs the \n\t   request (if it hasn't already done so) and prepares it for use */\n\tstatus = krnlSendMessage( ocspRequest, IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* If we haven't already got a server name explicitly set, try and get\n\t   it from the request.  This is an opportunistic action so we ignore \n\t   any potential error, the caller can still set the value explicitly */\n\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME ) == NULL )\n\t\t{\n\t\tchar buffer[ MAX_URL_SIZE + 8 ];\n\n\t\tsetMessageData( &msgData, buffer, MAX_URL_SIZE );\n\t\tstatus = krnlSendMessage( ocspRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RESPONDERURL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( sessionInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME );\n\t\t\t}\n\t\t}\n\n\t/* Add the request and increment its usage count */\n\tkrnlSendNotifier( ocspRequest, IMESSAGE_INCREFCOUNT );\n\tsessionInfoPtr->iCertRequest = ocspRequest;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodOCSP( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\tSESSION_NEEDS_REQUEST,\t\t/* Client attributes */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server attributes */\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\tSESSION_NEEDS_KEYSET,\n\t\t1, 1, 2,\t\t\t\t\t/* Version 1 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t\t}\n\telse\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransact );\n\t\t}\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_OCSP */\n"
  },
  {
    "path": "deps/cl345/session/pnppki.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Plug-and-play PKI Routines\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1999-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"session.h\"\n  #include \"cmp.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/session.h\"\n  #include \"session/cmp.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_CMP ) || defined( USE_SCEP )\n\n/* When we generate a new key there are a variety of different key types\n   (meaning key usages) that we can generate it for, constrained to some\n   extent by what the underlying certificate management protocol supports.  \n   The following values identify the key type that we need to generate */\n\ntypedef enum {\n\tKEY_TYPE_NONE,\t\t\t/* No key type */\n\tKEY_TYPE_ENCRYPTION,\t/* Encryption key */\n\tKEY_TYPE_SIGNATURE,\t\t/* Signature key */\n\tKEY_TYPE_BOTH,\t\t\t/* Dual encryption/signature key */\n\tKEY_TYPE_LAST\t\t\t/* Last possible key type */\n\t} KEY_TYPE;\n\n/* A structure to store key type-related information, indexed by the KEY_TYPE \n   value */\n\nstatic const struct {\n\tconst char *label;\t\t/* Label for private key */\n\tconst int labelLength;\n\tconst int actionPerms;\t/* Context action perms */\n\tconst int keyUsage;\t\t/* Certificate key usage */\n\t} keyInfo[] = {\n\t{ NULL, 0,\t\t\t\t/* KEY_TYPE_NONE */\n\t\t0, CRYPT_KEYUSAGE_NONE },\n\t{ \"Encryption key\", 14,\t/* KEY_TYPE_ENCRYPTION */\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ),\n\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ \"Signature key\", 13,\t/* KEY_TYPE_SIGNATURE */\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ),\n\t\tCRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ \"Private key\", 11,\t/* KEY_TYPE_BOTH */\n\t\tMK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL ) | \\\n\t\tMK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL ),\n\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT | CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ NULL, 0, 0, CRYPT_KEYUSAGE_NONE }, { NULL, 0, 0, CRYPT_KEYUSAGE_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Clean up an object if the PnP operation fails.  This is required when \n   working with devices since we need to explicitly delete anything that\n   was created in the device as well as just deleting the cryptlib object.\n\n   Since the error-handling for this is a bit unclear (it's being called\n   in response to another error so that, for example, the delete-key call\n   could fail because the error that's being responded to resulted in it\n   not being created), and in any case there's not much that we can do to \n   recover if the delete fail for some other reason, we don't make checking \n   the return value mandatory */\n\nRETVAL \\\nstatic int cleanupObject( IN_HANDLE const CRYPT_CONTEXT iPrivateKey, \n\t\t\t\t\t\t  IN_ENUM( KEY_TYPE ) const KEY_TYPE keyType )\n\t{\n\tCRYPT_DEVICE iCryptDevice;\n\tMESSAGE_KEYMGMT_INFO deletekeyInfo;\n\tint status;\n\n\tREQUIRES( isHandleRangeValid( iPrivateKey ) );\n\tREQUIRES( isEnumRange( keyType, KEY_TYPE ) );\n\n\t/* Delete the cryptlib object.  If it's a native object, we're done */\n\tstatus = krnlSendMessage( iPrivateKey, IMESSAGE_GETDEPENDENT,\n\t\t\t\t\t\t\t  &iCryptDevice, OBJECT_TYPE_DEVICE );\n\tkrnlSendNotifier( iPrivateKey, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Delete the key from the device.  We set the item type to delete to\n\t   public key since the device object will interpret this correctly\n\t   to mean that it should also delete the associated private key */\n\tsetMessageKeymgmtInfo( &deletekeyInfo, CRYPT_KEYID_NAME, \n\t\t\t\t\t\t   keyInfo[ keyType ].label,\n\t\t\t\t\t\t   keyInfo[ keyType ].labelLength, NULL, 0, \n\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\treturn( krnlSendMessage( iCryptDevice, IMESSAGE_KEY_DELETEKEY,\n\t\t\t\t\t\t\t &deletekeyInfo, KEYMGMT_ITEM_PUBLICKEY ) );\n\t}\n\n/* Check whether a network connection is still open, used when performing\n   multiple transactions in a single session */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isConnectionOpen( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint streamState, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tstatus = sioctlGet( &sessionInfoPtr->stream, STREAM_IOCTL_CONNSTATE, \n\t\t\t\t\t\t&streamState, sizeof( int ) );\n\treturn( cryptStatusError( status ) ? FALSE : streamState );\n\t}\n\n/* Check for the presence of a named object in a keyset/device */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN isNamedObjectPresent( IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\t\t\t IN_ENUM( KEY_TYPE ) const KEY_TYPE keyType )\n\t{\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tconst char *keyLabel = keyInfo[ keyType ].label;\n\tconst int keyLabelLength = keyInfo[ keyType ].labelLength;\n\tint status;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES_B( isEnumRange( keyType, KEY_TYPE ) );\n\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_NAME, keyLabel, \n\t\t\t\t\t\t   keyLabelLength, NULL, 0, \n\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_KEYID_NAME, keyLabel, \n\t\t\t\t\t\t\t   keyLabelLength, NULL, 0,\n\t\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_GETKEY, \n\t\t\t\t\t\t\t\t  &getkeyInfo, KEYMGMT_ITEM_PRIVATEKEY );\n\t\t}\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\n/* Get the identified CA/RA certificate from a CTL */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getCACert( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iNewCert, \n\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCTL, \n\t\t\t\t\t  IN_BUFFER_OPT( certIDlength ) const void *certID, \n\t\t\t\t\t  IN_LENGTH_KEYID_Z const int certIDlength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( iNewCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\t( isReadPtrDynamic( certID,  certIDlength ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCTL ) );\n\tREQUIRES( ( certID == NULL && certIDlength == 0 ) || \\\n\t\t\t  ( certID != NULL && certIDlength == KEYID_SIZE ) );\n\n\t/* Clear return value */\n\t*iNewCert = CRYPT_ERROR;\n\n\t/* Step through the certificate trust list checking each certificate in \n\t   turn to see if it's the identified CA/RA certificate.  Some CAs may \n\t   only send a single certificate in the CTL and not explicitly identify \n\t   it so if there's no certificate ID present we just use the first \n\t   one.  Note that the limit is given as FAILSAFE_ITERATIONS_MED since \n\t   we're using it as a fallback check on the maximum chain length allowed\n\t   by the certificate-import code.  In other words anything over the\n\t   certificate-handling code's maximum chain length is handled as a \n\t   normal error and it's only if we exceed this that we have an internal \n\t   error */\n\tstatus = krnlSendMessage( iCTL, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( certIDlength > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tint LOOP_ITERATOR;\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) certID, KEYID_SIZE );\n\t\tLOOP_MED_CHECKINC( cryptStatusOK( status ),\n\t\t\t\t\t\t   status = krnlSendMessage( iCTL, \n\t\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iCTL, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_FINGERPRINT_SHA1 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* We've found the identified certificate, we're done */\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* We've run out of certificates without finding a match, exit */\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t}\n\n\t/* We've found the identified certificate, convert it from the data-only \n\t   form in the CTL to a full certificate that can be used to verify \n\t   returned data.  This is easier than trying to disconnect and re-\n\t   connect certificate and context objects directly (ex duobus malis \n\t   minimum eligendum est) */\n\treturn( krnlSendMessage( iCTL, IMESSAGE_GETATTRIBUTE, iNewCert, \n\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_CERTCOPY ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tCertificate Creation/Update Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate a new key of the appropriate type.  For CMP we typically \n   generate first a signature key and then an encryption key (unless it's\n   a CA key, for which we only generate a certificate-signing key), for\n   SCEP we generate a dual encryption/signature key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int generateKey( OUT_HANDLE_OPT CRYPT_CONTEXT *iPrivateKey,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_USER iCryptUser,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_DEVICE iCryptDevice,\n\t\t\t\t\t\tIN_ENUM( KEY_TYPE ) const KEY_TYPE keyType )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tBOOLEAN substitutedAlgorithm = FALSE;\n\tint pkcAlgo, keySize, status;\n\n\tassert( isWritePtr( iPrivateKey, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( iCryptUser == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptUser ) );\n\tREQUIRES( iCryptDevice == SYSTEM_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iCryptDevice ) );\n\tREQUIRES( isEnumRange( keyType, KEY_TYPE ) );\n\n\t/* Clear return value */\n\t*iPrivateKey = CRYPT_ERROR;\n\n\t/* Get the algorithm to use for the key.  We try and use the given \n\t   default PKC algorithm, however some devices don't support all \n\t   algorithm types so if this isn't available we try and fall back to \n\t   other choices */\n\tstatus = krnlSendMessage( iCryptUser, IMESSAGE_GETATTRIBUTE, &pkcAlgo, \n\t\t\t\t\t\t\t  CRYPT_OPTION_PKC_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !algoAvailable( pkcAlgo ) )\n\t\t{\n\t\t/* The default algorithm type isn't available for this device, try \n\t\t   and fall back to an alternative */\n\t\tswitch( pkcAlgo )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\tpkcAlgo = CRYPT_ALGO_DSA;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\tpkcAlgo = CRYPT_ALGO_RSA;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tif( !algoAvailable( pkcAlgo ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t\t/* Remember that we've switched to a fallback algorithm */\n\t\tsubstitutedAlgorithm = TRUE;\n\t\t}\n\n\t/* Make sure that the chosen algorithm is compatible with what we're \n\t   trying to do */\n\tswitch( keyType )\n\t\t{\n\t\tcase KEY_TYPE_ENCRYPTION:\n\t\t\t/* If we're being asked for an encryption key, which in normal \n\t\t\t   operation implies that we've already successfully completed \n\t\t\t   the process of acquiring a signature key, and only a non-\n\t\t\t   encryption algorithm is available, we return OK_SPECIAL to \n\t\t\t   tell the caller that the failure is non-fatal.  However if \n\t\t\t   we've substituted an algorithm (for example DSA when RSA was \n\t\t\t   requested) then we genuinely can't go any further and exit\n\t\t\t   with an error */\n\t\t\tif( !isCryptAlgo( pkcAlgo ) )\n\t\t\t\treturn( substitutedAlgorithm ? \\\n\t\t\t\t\t\tCRYPT_ERROR_NOTAVAIL : OK_SPECIAL );\n\t\t\tbreak;\n\n\t\tcase KEY_TYPE_SIGNATURE:\n\t\t\tif( !isSigAlgo( pkcAlgo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tbreak;\n\n\t\tcase KEY_TYPE_BOTH:\n\t\t\tif( !isCryptAlgo( pkcAlgo ) || !isSigAlgo( pkcAlgo ) )\n\t\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Create a new key using the given PKC algorithm and of the default \n\t   size */\n\tsetMessageCreateObjectInfo( &createInfo, pkcAlgo );\n\tstatus = krnlSendMessage( iCryptDevice, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( iCryptUser, IMESSAGE_GETATTRIBUTE, &keySize, \n\t\t\t\t\t\t\t  CRYPT_OPTION_PKC_KEYSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &keySize, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyInfo[ keyType ].label, \n\t\t\t\t\t\tkeyInfo[ keyType ].labelLength );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_LABEL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Generate the key */\n\tstatus = krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_CTX_GENKEY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( int * ) &keyInfo[ keyType ].actionPerms,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ACTIONPERMS );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iPrivateKey = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a certificate request for a key.  If a certificate with a subject \n   DN template is provided we copy this into the request, otherwise we \n   create a minimal key-only request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createCertRequest( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertReq, \n\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT iPrivateKey,\n\t\t\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CERTIFICATE iSubjDNCert,\n\t\t\t\t\t\t\t  IN_ENUM( KEY_TYPE ) const KEY_TYPE keyType )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tconst BOOLEAN isPKCS10 = ( keyType == KEY_TYPE_BOTH ) ? TRUE : FALSE;\n\tint status;\n\n\tassert( isWritePtr( iCertReq, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( isHandleRangeValid( iPrivateKey ) );\n\tREQUIRES( iSubjDNCert == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iSubjDNCert ) );\n\tREQUIRES( isEnumRange( keyType, KEY_TYPE ) );\n\n\t/* Clear return value */\n\t*iCertReq = CRYPT_ERROR;\n\n\t/* Create the signing key certificate request */\n\tsetMessageCreateObjectInfo( &createInfo, isPKCS10 ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTREQUEST : \\\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo, \n\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the key information to the request and sign it if it's a CMP\n\t   request.  We can't sign PKCS #10 requests (for SCEP) because the \n\t   client session has to add further information required by the server \n\t   to the request before it submits it */\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( int * ) &iPrivateKey,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( int * ) &keyInfo[ keyType ].keyUsage, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t}\n\tif( cryptStatusOK( status ) && iSubjDNCert != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( int * ) &iSubjDNCert,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTIFICATE );\n\t\t}\n\tif( cryptStatusOK( status ) && !isPKCS10 )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CRT_SIGN,\n\t\t\t\t\t\t\t\t  NULL, iPrivateKey );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iCertReq = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Update a keyset/device with a newly-created key and certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nstatic int updateKeys( IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT iPrivateKey,\n\t\t\t\t\t   IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t   IN_BUFFER( passwordLength ) const char *password, \n\t\t\t\t\t   IN_LENGTH_NAME const int passwordLength )\n\t{\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tint objectType, status;\n\n\tassert( isReadPtrDynamic( password, passwordLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( isHandleRangeValid( iPrivateKey ) );\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( passwordLength >= MIN_NAME_LENGTH && \\\n\t\t\t  passwordLength < MAX_ATTRIBUTE_SIZE );\n\n\t/* Find out whether the storage object is a keyset or a device.  If it's\n\t   a device there's no need to add the private key since it'll have been\n\t   created inside the device */\n\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &objectType, CRYPT_IATTRIBUTE_TYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Add the private key and certificate to the keyset/device */\n\tif( objectType == OBJECT_TYPE_KEYSET )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t\t   ( MESSAGE_CAST ) password, passwordLength,\n\t\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\t\tsetkeyInfo.cryptHandle = iPrivateKey;\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_SETKEY,\n\t\t\t\t\t\t\t\t  &setkeyInfo, KEYMGMT_ITEM_PRIVATEKEY );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = iCryptCert;\n\treturn( krnlSendMessage( iCryptHandle, IMESSAGE_KEY_SETKEY,\n\t\t\t\t\t\t\t &setkeyInfo, KEYMGMT_ITEM_PUBLICKEY ) );\n\t}\n\n/* Update the keyset/device with any required trusted certificates up to the \n   root.  This ensures that we can still build a full certificate chain even \n   if the PKIBoot trusted certificates aren't preserved */\n\nstatic int updateTrustedCerts( IN_HANDLE const CRYPT_HANDLE iCryptHandle,\n\t\t\t\t\t\t\t   IN_HANDLE const CRYPT_HANDLE iLeafCert )\n\t{\n\tCRYPT_CERTIFICATE iCertCursor = iLeafCert;\n\tint status, LOOP_ITERATOR;\n\n\tREQUIRES( isHandleRangeValid( iCryptHandle ) );\n\tREQUIRES( isHandleRangeValid( iLeafCert ) );\n\n\tLOOP_MED_INITCHECK( status = CRYPT_OK, cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\n\t\t/* Get the trusted issuer certificate for the current certificate \n\t\t   and send it to the keyset/device */\n\t\tstatus = krnlSendMessage( iCertCursor, IMESSAGE_USER_TRUSTMGMT, \n\t\t\t\t\t\t\t\t  &iCertCursor, MESSAGE_TRUSTMGMT_GETISSUER );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,\n\t\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\t\tsetkeyInfo.cryptHandle = iCertCursor;\n\t\tstatus = krnlSendMessage( iCryptHandle, IMESSAGE_KEY_SETKEY, \n\t\t\t\t\t\t\t\t  &setkeyInfo, KEYMGMT_ITEM_PUBLICKEY );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPnP PKI Session Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Run a plug-and-play PKI session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pnpPkiSession( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCRYPT_DEVICE iCryptDevice = SYSTEM_OBJECT_HANDLE;\n\tCRYPT_CONTEXT iPrivateKey1, iPrivateKey2 ;\n\tCRYPT_CERTIFICATE iCertReq, iCACert DUMMY_INIT;\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tconst ATTRIBUTE_LIST *passwordPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tconst KEY_TYPE keyType = ( sessionInfoPtr->type == CRYPT_SESSION_CMP ) ? \\\n\t\t\t\t\t\t\t KEY_TYPE_SIGNATURE : KEY_TYPE_BOTH;\n#ifdef USE_ERRMSGS\n\tconst char *storageObjectName = \"keyset\";\n#endif /* USE_ERRMSGS */\n\tSES_TRANSACT_FUNCTION transactFunction;\n\tBOOLEAN_INT isCAcert;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint objectType, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( passwordPtr != NULL );\n\n\ttransactFunction = ( SES_TRANSACT_FUNCTION ) \\\n\t\t\t\t\t   FNPTR_GET( sessionInfoPtr->transactFunction );\n\tREQUIRES( transactFunction != NULL );\n\n\t/* If we've been passed a device as the private-key storage location,\n\t   create the key in the device instead of as a local object */\n\tstatus = krnlSendMessage( sessionInfoPtr->privKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &objectType,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_TYPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( objectType == OBJECT_TYPE_DEVICE )\n\t\t{\n\t\tiCryptDevice = sessionInfoPtr->privKeyset;\n#ifdef USE_ERRMSGS\n\t\tstorageObjectName = \"device\";\n#endif /* USE_ERRMSGS */\n\t\t}\n\n\t/* Make sure that the named objects that are about to be created aren't \n\t   already present in the keyset/device */\n\tif( isNamedObjectPresent( sessionInfoPtr->privKeyset, keyType ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_DUPLICATE,\n\t\t\t\t( CRYPT_ERROR_DUPLICATE, SESSION_ERRINFO, \n\t\t\t\t  \"%s is already present in %s\",\n\t\t\t\t  ( keyType == KEY_TYPE_SIGNATURE ) ? \\\n\t\t\t\t\t\"Signature key\" : \"Key\", storageObjectName ) );\n\t\t}\n\tif( sessionInfoPtr->type == CRYPT_SESSION_CMP )\n\t\t{\n\t\tif( isNamedObjectPresent( sessionInfoPtr->privKeyset, \n\t\t\t\t\t\t\t\t  KEY_TYPE_ENCRYPTION ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_DUPLICATE,\n\t\t\t\t\t( CRYPT_ERROR_DUPLICATE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Encryption key is already present in %s\",\n\t\t\t\t\t  storageObjectName ) );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"isNamedObjectPresent\" );\n\n\t/* Perform the PKIBoot exchange (done as part of an ir) to get the \n\t   initial trusted certificate set.  We also set the retain-connection \n\t   flag since we're going to follow this with another transaction */\n\tif( sessionInfoPtr->type == CRYPT_SESSION_CMP )\n\t\t{\n\t\tsessionInfoPtr->sessionCMP->requestType = CRYPT_REQUESTTYPE_PKIBOOT;\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t  CMP_PFLAG_RETAINCONNECTION );\n\t\t}\n\tstatus = transactFunction( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !isConnectionOpen( sessionInfoPtr ) )\n\t\t{\n\t\t/* If the connection was shut down by the other side, signal an \n\t\t   error.  This is possibly a bit excessive since we could always \n\t\t   try reactivating the session, but there's no good reason for the \n\t\t   other side to simply close the connection and requiring it to \n\t\t   remain open simplifies the implementation */\n\t\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t( CRYPT_ERROR_READ, SESSION_ERRINFO, \n\t\t\t\t  \"Server closed connection after PKIBoot phase before any \"\n\t\t\t\t  \"certificates could be issued\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"transactFunction\" );\n\n\t/* Get the CA/RA certificate from the returned CTL and set it as the \n\t   certificate to use for authenticating server responses */\n\tattributeListPtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\tstatus = getCACert( &iCACert, sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\tattributeListPtr->value, \n\t\t\t\t\t\t\tattributeListPtr->valueLength );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = getCACert( &iCACert, sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\tNULL, 0 );\n\t\t}\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't read CA/RA certificate from returned \"\n\t\t\t\t  \"certificate trust list\" ) );\n\t\t}\n\tsessionInfoPtr->iAuthInContext = iCACert;\n\tCFI_CHECK_UPDATE( \"getCACert\" );\n\n\t/* Create a private key and a certificate request for it */\n\tstatus = generateKey( &iPrivateKey1, sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t  iCryptDevice, keyType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tENSURES( status != OK_SPECIAL );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Couldn't create %s key\",\n\t\t\t\t  ( keyType == KEY_TYPE_SIGNATURE ) ? \\\n\t\t\t\t\t\"signature\" : \"private\" ) );\n\t\t}\n\tstatus = createCertRequest( &iCertReq, iPrivateKey1, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tkeyType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, keyType );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create %skey certificate request\",\n\t\t\t\t  ( keyType == KEY_TYPE_SIGNATURE ) ? \\\n\t\t\t\t\t\"signature \" : \"\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createCertRequest\" );\n\n\t/* Set up the request information and activate the session */\n\tif( sessionInfoPtr->type == CRYPT_SESSION_CMP )\n\t\t{\n\t\t/* If it's CMP, start with an ir.  The second certificate will be \n\t\t   fetched with a cr */\n\t\tsessionInfoPtr->sessionCMP->requestType = \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_INITIALISATION;\n\t\t}\n\tsessionInfoPtr->iCertRequest = iCertReq;\n\tstatus = transactFunction( sessionInfoPtr );\n\tkrnlSendNotifier( sessionInfoPtr->iCertRequest, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, keyType );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"transactFunction\" );\n\n\t/* Check whether we've been issued a standalone CA certificate rather \n\t   than a standard signature certificate to be followed by an encryption \n\t   certificate or a standard signature + encryption certificate */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &isCAcert,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CA );\n\tif( cryptStatusError( status ) )\n\t\tisCAcert = FALSE;\n\n\t/* If the connection was shut down by the other side and we're \n\t   performing a multi-part operation that requires it to remain open, \n\t   signal an error.  This is possibly a bit excessive since we could \n\t   always try reactivating the session, but there's no good reason for \n\t   the other side to simply close the connection and requiring it to \n\t   remain open simplifies the implementation */\n\tif( sessionInfoPtr->type == CRYPT_SESSION_CMP && \\\n\t\t!isConnectionOpen( sessionInfoPtr ) && !isCAcert )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, keyType );\n\t\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\t\tretExt( CRYPT_ERROR_READ,\n\t\t\t\t( CRYPT_ERROR_READ, SESSION_ERRINFO, \n\t\t\t\t  \"Server closed connection before second (encryption) \"\n\t\t\t\t  \"certificate could be issued\" ) );\n\t\t}\n\n\t/* We've got the first certificate, update the keyset/device */\n\tstatus = updateKeys( sessionInfoPtr->privKeyset, iPrivateKey1,\n\t\t\t\t\t\t sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t passwordPtr->value, passwordPtr->valueLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tCRYPT_CERTIFICATE iNewCert;\n\n\t\t/* Recreate the certificate as a data-only certificate and attach it \n\t\t   to the signing key so that we can use it to authenticate a \n\t\t   request for an encryption key.  We need to recreate the \n\t\t   certificate because we're about to attach it to the private-key \n\t\t   context for further operations, and attaching a certificate with \n\t\t   a public-key context already attached isn't possible.  Even if \n\t\t   we're not getting a second certificate, we still need the current \n\t\t   certificate attached so that we can use it as the base \n\t\t   certificate for the trusted certificate update that we perform \n\t\t   before we exit */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &iNewCert, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_CERTCOPY_DATAONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( iPrivateKey1, IMESSAGE_SETDEPENDENT, \n\t\t\t\t\t\t\t\t\t   &iNewCert, SETDEP_OPTION_NOINCREF );\n\t\t\t}\n\t\t}\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, keyType );\n\t\tretExt( ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\tCRYPT_ERROR_INVALID : status,\n\t\t\t\t( ( status == CRYPT_ARGERROR_NUM1 ) ? \\\n\t\t\t\t  CRYPT_ERROR_INVALID : status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't update %s with %skey/certificate\", \n\t\t\t\t  storageObjectName, isCAcert ? \"CA \" : \\\n\t\t\t\t  ( keyType == KEY_TYPE_SIGNATURE ) ? \"signature \" : \"\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateKeys\" );\n\n\t/* If it's a combined encryption/signature key or a standalone CA key, \n\t   we're done.  See the comment at the end of this function for the \n\t   details of the trusted-certificates update process */\n\tif( keyType == KEY_TYPE_BOTH || isCAcert )\n\t\t{\n\t\tupdateTrustedCerts( sessionInfoPtr->privKeyset, iPrivateKey1 );\n\t\tkrnlSendNotifier( iPrivateKey1, IMESSAGE_DECREFCOUNT );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"isNamedObjectPresent\", \"transactFunction\", \n\t\t\t\t\t\t\t\t\t\t\"getCACert\", \"createCertRequest\", \n\t\t\t\t\t\t\t\t\t\t\"transactFunction\", \"updateKeys\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"singleCert\" );\n\n\t/* We're running a CMP session from this point on */\n\tENSURES( sessionInfoPtr->type == CRYPT_SESSION_CMP );\n\n\t/* Create the second, encryption private key and a certificate request \n\t   for it */\n\tstatus = generateKey( &iPrivateKey2, sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t  iCryptDevice, KEY_TYPE_ENCRYPTION );\n\tif( status == OK_SPECIAL )\n\t\t{\n\t\t/* Encryption isn't available via this device, exit without going\n\t\t   through the second phase of the exchange, leaving only the\n\t\t   signature key and certificates set up */\n\t\tupdateTrustedCerts( sessionInfoPtr->privKeyset, iPrivateKey1 );\n\t\tkrnlSendNotifier( iPrivateKey1, IMESSAGE_DECREFCOUNT );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, KEY_TYPE_SIGNATURE );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create encryption key\" ) );\n\t\t}\n\tstatus = createCertRequest( &iCertReq, iPrivateKey2, iPrivateKey1,\n\t\t\t\t\t\t\t\tKEY_TYPE_ENCRYPTION );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, KEY_TYPE_SIGNATURE );\n\t\tcleanupObject( iPrivateKey2, KEY_TYPE_ENCRYPTION );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create encryption key certificate request\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createCertRequest\" );\n\n\t/* Set up the request information and activate the session.  This \n\t   request is slightly different to the previous one since we now have a \n\t   signature certificate that we can use to authenticate the request (in \n\t   fact we have to use this since we can't authenticate the message with \n\t   an encryption-only key).  In addition since this is the last \n\t   transaction we turn off the retain-connection flag */\n\tCLEAR_FLAG( sessionInfoPtr->protocolFlags, CMP_PFLAG_RETAINCONNECTION );\n\tsessionInfoPtr->sessionCMP->requestType = CRYPT_REQUESTTYPE_CERTIFICATE;\n\tsessionInfoPtr->iCertRequest = iCertReq;\n\tsessionInfoPtr->privateKey = iPrivateKey2;\n\tsessionInfoPtr->iAuthOutContext = iPrivateKey1;\n\tstatus = transactFunction( sessionInfoPtr );\n\tsessionInfoPtr->privateKey = CRYPT_ERROR;\n\tsessionInfoPtr->iAuthOutContext = CRYPT_ERROR;\n\tkrnlSendNotifier( sessionInfoPtr->iCertRequest, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, KEY_TYPE_SIGNATURE );\n\t\tcleanupObject( iPrivateKey2, KEY_TYPE_ENCRYPTION );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"transactFunction\" );\n\n\t/* We've got the second certificate, update the keyset/device */\n\tstatus = updateKeys( sessionInfoPtr->privKeyset, iPrivateKey2,\n\t\t\t\t\t\t sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t passwordPtr->value, passwordPtr->valueLength );\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcleanupObject( iPrivateKey1, KEY_TYPE_SIGNATURE );\n\t\tcleanupObject( iPrivateKey2, KEY_TYPE_ENCRYPTION );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't update %s with encryption key/certificate\",\n\t\t\t\t  storageObjectName ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateKeys\" );\n\n\t/* Finally, update the keyset/device with any required trusted \n\t   certificates up to the root.  This ensures that we can still build a \n\t   full certificate chain even if the PKIBoot trusted certificates \n\t   aren't preserved.  We don't check for errors from this function since \n\t   it's not worth aborting the process for some minor CA certificate \n\t   update problem, the user keys and certificates will still function \n\t   without them */\n\tupdateTrustedCerts( sessionInfoPtr->privKeyset, iPrivateKey1 );\n\tCFI_CHECK_UPDATE( \"updateTrustedCerts\" );\n\n\t/* Both keys were certified and the keys and certificates sent to the \n\t   keyset/device, we're done */\n\tkrnlSendNotifier( iPrivateKey1, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( iPrivateKey2, IMESSAGE_DECREFCOUNT );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_11( \"isNamedObjectPresent\", \"transactFunction\", \n\t\t\t\t\t\t\t\t\t \"getCACert\", \"createCertRequest\", \n\t\t\t\t\t\t\t\t\t \"transactFunction\", \"updateKeys\", \"singleCert\", \n\t\t\t\t\t\t\t\t\t \"createCertRequest\", \"transactFunction\", \n\t\t\t\t\t\t\t\t\t \"updateKeys\", \"updateTrustedCerts\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CMP || USE_SCEP */\n"
  },
  {
    "path": "deps/cl345/session/rtcs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib RTCS Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_RTCS\n\n/* RTCS HTTP content types */\n\n#define RTCS_CONTENT_TYPE_REQ\t\t\"application/rtcs-request\"\n#define RTCS_CONTENT_TYPE_REQ_LEN\t24\n#define RTCS_CONTENT_TYPE_RESP\t\t\"application/rtcs-response\"\n#define RTCS_CONTENT_TYPE_RESP_LEN\t25\n\n/* The action to take to process an RTCS request/response */\n\ntypedef enum {\n\tACTION_NONE,\t\t\t\t/* No processing */\n\tACTION_UNWRAP,\t\t\t\t/* Unwrap raw data */\n\tACTION_CRYPT,\t\t\t\t/* Decrypt data */\n\tACTION_SIGN,\t\t\t\t/* Sig.check data */\n\tACTION_LAST\t\t\t\t\t/* Last valid action type */\n\t} ACTION_TYPE;\n\n/* RTCS protocol state information.  This is passed around various\n   subfunctions that handle individual parts of the protocol */\n\ntypedef struct {\n\t/* State variable information.  The nonce is copied from the request to\n\t   the response to prevent replay attacks */\n\tBYTE nonce[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint nonceSize;\n\t} RTCS_PROTOCOL_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check for a valid-looking RTCS request/response header */\n\nstatic const CMS_CONTENT_INFO oidInfoSignedData = { 0, 3 };\nstatic const CMS_CONTENT_INFO oidInfoEnvelopedData = { 0, 3 };\n\nstatic const OID_INFO envelopeOIDinfo[] = {\n\t{ OID_CRYPTLIB_RTCSREQ, ACTION_UNWRAP },\n\t{ OID_CRYPTLIB_RTCSRESP, ACTION_UNWRAP },\n\t{ OID_CRYPTLIB_RTCSRESP_EXT, ACTION_UNWRAP },\n\t{ OID_CMS_SIGNEDDATA, ACTION_SIGN, &oidInfoSignedData },\n\t{ OID_CMS_ENVELOPEDDATA, ACTION_CRYPT, &oidInfoEnvelopedData },\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkRtcsHeader( IN_BUFFER( rtcsDataLength ) const void *rtcsData, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int rtcsDataLength,\n\t\t\t\t\t\t\tOUT_ENUM_OPT( ACTION ) ACTION_TYPE *actionType )\n\t{\n\tSTREAM stream;\n\tint action, status;\n\n\tassert( isReadPtrDynamic( rtcsData, rtcsDataLength ) );\n\tassert( isWritePtr( actionType, sizeof( ACTION_TYPE ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( rtcsDataLength ) );\n\n\t/* Clear return value */\n\t*actionType = ACTION_NONE;\n\n\t/* We've got a valid response, check the CMS encapsulation */\n\tsMemConnect( &stream, rtcsData, rtcsDataLength );\n\tstatus = readCMSheader( &stream, envelopeOIDinfo, \n\t\t\t\t\t\t\tFAILSAFE_ARRAYSIZE( envelopeOIDinfo, OID_INFO ), \n\t\t\t\t\t\t\t&action, NULL, READCMS_FLAG_NONE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*actionType = action;\t/* int vs. enum */\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClient-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a request to an RTCS server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendClientRequest( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Get the encoded request data and wrap it up for sending */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't get RTCS request data from RTCS request \"\n\t\t\t\t  \"object\" ) );\n\t\t}\n\tstatus = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize,\n\t\t\t\t\t\t   &sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t   CRYPT_FORMAT_CMS, CRYPT_CONTENT_RTCSREQUEST,\n\t\t\t\t\t\t   CRYPT_UNUSED, NULL, 0, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't CMS-envelope RTCS request data: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"rtcs_req\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Send the request to the responder */\n\treturn( writePkiDatagram( sessionInfoPtr, RTCS_CONTENT_TYPE_REQ,\n\t\t\t\t\t\t\t  RTCS_CONTENT_TYPE_REQ_LEN ) );\n\t}\n\n/* Read the response from the RTCS server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readServerResponse( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tACTION_TYPE actionType;\n\tBYTE nonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint dataLength, sigResult, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Read the response from the responder */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_DUMP_FILE( \"rtcs_resp\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = checkRtcsHeader( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufEnd, &actionType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid RTCS response header\" ) );\n\t\t}\n\tif( actionType != ACTION_SIGN )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,\n\t\t\t\t  \"Unexpected RTCS encapsulation type %d\", actionType ) );\n\t\t}\n\n\t/* Sig.check the data using the responder's key */\n\tstatus = envelopeSigCheck( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength,\n\t\t\t\t\t\t\t   CRYPT_UNUSED, &sigResult, NULL,\n\t\t\t\t\t\t\t   &iCmsAttributes, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Invalid CMS-enveloped RTCS response data: \" ) );\n\t\t}\n\n\t/* Make sure that the nonce in the response matches the one in the\n\t   request */\n\tsetMessageData( &msgData, nonceBuffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_NONCE );\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA responseMsgData;\n\t\tBYTE responseNonceBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\tsetMessageData( &responseMsgData, responseNonceBuffer,\n\t\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &responseMsgData,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_NONCE );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( msgData.length < 4 || \\\n\t\t\t  msgData.length != responseMsgData.length || \\\n\t\t\t  memcmp( msgData.data, responseMsgData.data, msgData.length ) ) )\n\t\t\tstatus = CRYPT_ERROR_SIGNATURE;\n\t\t}\n\tkrnlSendNotifier( sessionInfoPtr->iCertRequest, IMESSAGE_DECREFCOUNT );\n\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The response doesn't contain a nonce or it doesn't match what\n\t\t   we sent, we can't trust it.  The best error that we can return\n\t\t   here is a signature error to indicate that the integrity check\n\t\t   failed */\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  ( status != CRYPT_ERROR_SIGNATURE ) ? \\\n\t\t\t\t  \"RTCS response doesn't contain a nonce\" : \\\n\t\t\t\t  \"RTCS response nonce doesn't match the one in the \"\n\t\t\t\t  \"request\" ) );\n\t\t}\n\n\t/* Everything is OK, import the response */\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_RTCS_RESPONSE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid RTCS response contents\" ) );\n\t\t}\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tServer-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a request from an RTCS client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readClientRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT RTCS_PROTOCOL_INFO *protocolInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tACTION_TYPE actionType;\n\tint dataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( RTCS_PROTOCOL_INFO ) ) );\n\n\t/* Read the request data from the client.  We don't write an error\n\t   response at this initial stage to prevent scanning/DOS attacks\n\t   (vir sapit qui pauca loquitur) */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_DUMP_FILE( \"rtcs_sreq\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = checkRtcsHeader( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufEnd, &actionType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid RTCS request header\" ) );\n\t\t}\n\tif( actionType != ACTION_UNWRAP )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,\n\t\t\t\t  \"Unexpected RTCS encapsulation type %d\", actionType ) );\n\t\t}\n\tstatus = envelopeUnwrap( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, &dataLength,\n\t\t\t\t\t\t\t CRYPT_UNUSED, NULL, 0, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tregisterCryptoFailure();\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Invalid CMS-enveloped RTCS request data: \" ) );\n\t\t}\n\n\t/* Create an RTCS response.  We always create this since an empty\n\t   response is sent to indicate an error condition */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_RTCS_RESPONSE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\n\t/* Import the request as a cryptlib object and read the nonce from it */\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\tCRYPT_CERTTYPE_RTCS_REQUEST );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, protocolInfo->nonce, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_NONCE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tprotocolInfo->nonceSize = msgData.length;\n\t\telse\n\t\t\t{\n\t\t\t/* We couldn't read the nonce, delete the request object prior \n\t\t\t   to exiting */\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid RTCS request contents\" ) );\n\t\t}\n\n\t/* Create an RTCS response and add the request information to it */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &createInfo.cryptHandle,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RTCSREQUEST );\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create RTCS response from request\" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Return a response to an RTCS client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sendServerResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT RTCS_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes = CRYPT_UNUSED;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( RTCS_PROTOCOL_INFO ) ) );\n\n\t/* Check the entries from the request against the certificate store and \n\t   sign the resulting status information (\"Love, ken\").  Note that\n\t   CRYPT_ERROR_INVALID is a valid return status for the sigcheck call\n\t   since it indicates that one (or more) of the certificates are \n\t   invalid */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGCHECK, NULL,\n\t\t\t\t\t\t\t  sessionInfoPtr->cryptKeyset );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_INVALID )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't check RTCS request against certificate \"\n\t\t\t\t  \"store\" ) );\n\t\t}\n\n\t/* If there's a nonce present, create CMS attributes to contain it */\n\tif( protocolInfo->nonceSize > 0 )\n\t\t{\n\t\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\n\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tiCmsAttributes = createInfo.cryptHandle;\n\t\tsetMessageData( &msgData, protocolInfo->nonce,\n\t\t\t\t\t\tprotocolInfo->nonceSize );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CMS_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Extract the response data */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( iCmsAttributes != CRYPT_UNUSED )\n\t\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't encode RTCS response\" ) );\n\t\t}\n\n\t/* Sign the response data using the responder's key and send it to the\n\t   client */\n\tstatus = envelopeSign( sessionInfoPtr->receiveBuffer, msgData.length,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize,\n\t\t\t\t\t\t   &sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t   CRYPT_CONTENT_RTCSRESPONSE,\n\t\t\t\t\t\t   sessionInfoPtr->privateKey, iCmsAttributes, \n\t\t\t\t\t\t   &errorInfo );\n\tif( iCmsAttributes != CRYPT_UNUSED )\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't CMS-envelope RTCS response: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"rtcs_sresp\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treturn( writePkiDatagram( sessionInfoPtr, RTCS_CONTENT_TYPE_RESP,\n\t\t\t\t\t\t\t  RTCS_CONTENT_TYPE_RESP_LEN ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with an RTCS client/server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Get certificate status information from the server */\n\tstatus = sendClientRequest( sessionInfoPtr );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readServerResponse( sessionInfoPtr );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tRTCS_PROTOCOL_INFO protocolInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Send certificate status information to the client */\n\tmemset( &protocolInfo, 0, sizeof( RTCS_PROTOCOL_INFO ) );\n\tstatus = readClientRequest( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendServerResponse( sessionInfoPtr, &protocolInfo );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tControl Information Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst CRYPT_CERTIFICATE rtcsRequest = *( ( CRYPT_CERTIFICATE * ) data );\n\tMESSAGE_DATA msgData = { NULL, 0 };\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_REQUEST );\n\n\t/* Make sure that everything is set up ready to go.  Since RTCS requests\n\t   aren't signed like normal certificate objects we can't just check the \n\t   immutable attribute but have to perform a dummy export for which the\n\t   certificate export code will return an error status if there's a \n\t   problem with the request.  If not, it pseudo-signs the request (if it \n\t   hasn't already done so) and prepares it for use */\n\tstatus = krnlSendMessage( rtcsRequest, IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_ICERTFORMAT_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* If we haven't already got a server name explicitly set, try and get\n\t   it from the request.  This is an opportunistic action so we ignore \n\t   any potential error, the caller can still set the value explicitly */\n\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME ) == NULL )\n\t\t{\n\t\tchar buffer[ MAX_URL_SIZE + 8 ];\n\n\t\tsetMessageData( &msgData, buffer, MAX_URL_SIZE );\n\t\tstatus = krnlSendMessage( rtcsRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RESPONDERURL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) krnlSendMessage( sessionInfoPtr->objectHandle,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME );\n\t\t\t}\n\t\t}\n\n\t/* Add the request and increment its usage count */\n\tkrnlSendNotifier( rtcsRequest, IMESSAGE_INCREFCOUNT );\n\tsessionInfoPtr->iCertRequest = rtcsRequest;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open/close an RTCS session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodRTCS( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\tSESSION_NEEDS_REQUEST,\t\t/* Client flags */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server flags */\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\tSESSION_NEEDS_KEYSET,\n\t\t1, 1, 1,\t\t\t\t\t/* Version 1 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t\t}\n\telse\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransact );\n\t\t}\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_RTCS */\n"
  },
  {
    "path": "deps/cl345/session/scep.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib SCEP Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"scep.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/scep.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SCEP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSCEP( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst SCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( scepInfo, sizeof( SCEP_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckSession( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSCEP: Session check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check SCEP session parameters */\n\tif( !CHECK_FLAGS( sessionInfoPtr->protocolFlags, SCEP_PFLAG_NONE, \n\t\t\t\t\t  SCEP_PFLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSCEP: Protocol flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !isEnumRangeOpt( scepInfo->requestType, CRYPT_REQUESTTYPE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSCEP: Session parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Initialise and clean up protocol information */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPprotocolInfo( OUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tmemset( protocolInfo, 0, sizeof( SCEP_PROTOCOL_INFO ) );\n\tprotocolInfo->iScepCert = protocolInfo->iPkiUser = CRYPT_ERROR;\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySCEPprotocolInfo( INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tif( protocolInfo->iScepCert != CRYPT_ERROR )\n\t\tkrnlSendNotifier( protocolInfo->iScepCert, IMESSAGE_DECREFCOUNT );\n\tif( protocolInfo->iPkiUser != CRYPT_ERROR )\n\t\tkrnlSendNotifier( protocolInfo->iPkiUser, IMESSAGE_DECREFCOUNT );\n\n\tzeroise( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) );\n\t}\n\n/* Check a private key being added to a SCEP session to make sure that it's\n   of the appropriate form */\n\nCHECK_RETVAL_BOOL \\\nstatic BOOLEAN checkPrivateKey( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t\tconst BOOLEAN isCertKey )\n\t{\n\tBOOLEAN_INT isInited;\n\tint value, status;\n\n\tREQUIRES_B( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES_B( isCertKey == TRUE || isCertKey == FALSE );\n\n\t/* If the private key requires an associated certificate, make sure that \n\t   it's present and of the correct form */\n\tif( isCertKey )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &isInited, CRYPT_CERTINFO_IMMUTABLE );\n\t\tif( cryptStatusError( status ) || !isInited )\n\t\t\treturn( FALSE );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\t( value != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t  value != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\treturn( FALSE );\n\t\t\n\t\treturn( TRUE );\n\t\t}\n\n\t/* The private key can't have an associated certificate, make sure \n\t   there's none present */\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\treturn( cryptStatusOK( status ) ? FALSE : TRUE );\n\t}\n\n/* Check that the CA's certificate can also sign and encrypt data.  This is\n   normally a really bad idea for CA certificates but is required by the \n   SCEP protocol.  We don't check for the object being a CA certificate \n   because we could be dealing with an RA, which isn't necessarily a CA */\n\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkSCEPCACert( IN_HANDLE const CRYPT_CERTIFICATE iCaCert,\n \t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options )\n\t{\n\tREQUIRES_B( isHandleRangeValid( iCaCert ) );\n\tREQUIRES_B( options == KEYMGMT_FLAG_NONE || \\\n\t\t\t\toptions == KEYMGMT_FLAG_USAGE_CRYPT || \\\n\t\t\t\toptions == KEYMGMT_FLAG_USAGE_SIGN );\n\n\t/* Since this could be a certificate chain, we need to select the leaf\n\t   certificate in the chain */\n\tkrnlSendMessage( iCaCert, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\n\t/* Check whether the certificate has the required capabilities */\n\tif( options != KEYMGMT_FLAG_USAGE_SIGN )\n\t\t{\n\t\tif( !checkContextCapability( iCaCert, MESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( options != KEYMGMT_FLAG_USAGE_CRYPT )\n\t\t{\n\t\tif( !checkContextCapability( iCaCert, MESSAGE_CHECK_PKC_SIGCHECK ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Process a user name, either by checking that what we've been given by the \n   user is valid or by auto-generating one if the user has specified\n   auto-detection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processUserName( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_BUFFER( userNameLength ) const BYTE *userName,\n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int userNameLength )\n\t{\n\tint index, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( userName, userNameLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( userNameLength ) );\n\n\t/* Because users won't necessarily have a user name/transaction ID to \n\t   use we allow them to specify the value as \"[Autodetect]\" and replace \n\t   it with a base64'd nonce (to meet the encoding requirements below) */\n\tif( userNameLength == 12 && !memcmp( userName, \"[Autodetect]\", 12 ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE nonce[ 16 + 8 ];\n#ifndef USE_BASE64\n\t\tstatic const char binToAscii[ 64 ] = \\\n\t\t\t\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\t\tint i;\n#else\n\t\tint transIDlength;\n#endif /* !USE_BASE64 */\n\t\tchar transID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint status;\n\n\t\t/* The caller has explicitly indicated that they want us to generate \n\t\t   a transaction ID for them, generate it as a random text string */\n\t\tsetMessageData( &msgData, nonce, 16 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n#ifdef USE_BASE64\n\t\tstatus = base64encode( transID, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t   &transIDlength, nonce, 16, \n\t\t\t\t\t\t\t   CRYPT_CERTTYPE_NONE );\n#else\n\t\tLOOP_MED( i = 0, i < 16, i++ )\n\t\t\ttransID[ i ] = binToAscii[ nonce[ i ] & 0x3F ];\n\t\tENSURES( LOOP_BOUND_OK );\n#endif /* USE_BASE64 */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = addSessionInfoEx( sessionInfoPtr, CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t\t   transID, 16, ATTR_FLAG_NONE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Tell the caller that the attribute was processed internally */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* For some bizarre reason SCEP encodes its transaction ID (which is our \n\t   user name) as a PrintableString (even though the specification \n\t   suggests that the value be created from a hash of the public key, \n\t   which doesn't fit into a PrintableString) so we have to filter any \n\t   supplied value to make sure that it can be encoded when we send it */\n\tLOOP_LARGE( index = 0, index < userNameLength, index++ )\n\t\t{\n\t\tstatic const char allowedChars[] = \"'\\\"()+,-./:=? \\x00\\x00\";\n\t\tconst int ch = byteToInt( userName[ index ] );\n\t\tBOOLEAN foundMatch = FALSE;\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\tif( isAlnum( ch ) )\n\t\t\tcontinue;\n\t\tLOOP_MED_ALT( i = 0,\n\t\t\t\t\t  allowedChars[ i ] != '\\0' && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( allowedChars, char ), \n\t\t\t\t\t  i++ )\n\t\t\t{\n\t\t\tif( allowedChars[ i ] == ch )\n\t\t\t\t{\n\t\t\t\tfoundMatch = TRUE;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( allowedChars, char ) );\n\t\tif( !foundMatch )\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t\t\n\treturn( CRYPT_OK );\n\t}\n\n/* Generate/check the server certificate fingerprint */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint processKeyFingerprint( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst ATTRIBUTE_LIST *fingerprintPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* If the caller has supplied a certificate fingerprint, compare it to \n\t   the received certificate's fingerprint to make sure that we're \n\t   talking to the right system */\n\tif( fingerprintPtr != NULL )\n\t\t{\n\t\tsetMessageData( &msgData, fingerprintPtr->value, \n\t\t\t\t\t\tfingerprintPtr->valueLength );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_FINGERPRINT_SHA1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"Server certificate doesn't match key fingerprint\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tBYTE certFingerprint[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t/* Remember the certificate fingerprint in case the caller wants to \n\t\t   check it.  We don't worry if the add fails, it's a minor thing \n\t\t   and not worth aborting the overall operation for */\n\t\tsetMessageData( &msgData, certFingerprint, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t( void ) addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t\t  certFingerprint, msgData.length );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create SCEP signing attributes */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint createScepAttributes( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT SCEP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iScepAttributes,\n\t\t\t\t\t\t  IN_STRING const char *messageType,\n\t\t\t\t\t\t  IN_STATUS const int scepStatus )\n\t{\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\tassert( isReadPtr( messageType, 2 ) );\n\tassert( isWritePtr( iScepAttributes, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\tREQUIRES( scepStatus >= MAX_ERROR && scepStatus <= CRYPT_OK );\n\tREQUIRES( userNamePtr != NULL );\n\n\t/* Clear return value */\n\t*iScepAttributes = CRYPT_ERROR;\n\n\t/* Create the signing attributes needed by SCEP and add the user name/\n\t   transaction ID and message type.  The transaction ID is a bit \n\t   complicated, it's used to tie together all messages related to a \n\t   certificate-issue transaction and acts more as a type of fixed nonce \n\t   than any real identifier (the specification suggests using \"an MD5 \n\t   hash on [sic] the public key\", later extended to also encompass SHA1, \n\t   SHA-256, and SHA-512).  This is complicated by the fact that the \n\t   encoding is a PrintableString so the hash can't actually be used, but \n\t   then another part of the spec says that it's encoded as a decimal \n\t   value (!!) within the string.\n\n\t   The way we handle it is that the client sends it to the server as is \n\t   (after a pre-check in checkAttributeFunction() for validity) and the \n\t   server tries to decode it as a cryptlib-encoded PKI user ID that's \n\t   used to look up the PKI user information.  If it can't be decoded by \n\t   the server then it's not a request meant for a cryptlib server, so we \n\t   can reject it immediately */\n\tINJECT_FAULT( SESSION_SCEP_CORRUPT_MESSAGETYPE,\t\n\t\t\t\t  SESSION_SCEP_CORRUPT_MESSAGETYPE_1 );\n\tINJECT_FAULT( CORRUPT_ID, SESSION_CORRUPT_TRANSACTIONID_SCEP_1 );\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCmsAttributes = createInfo.cryptHandle;\n\tsetMessageData( &msgData, userNamePtr->value, userNamePtr->valueLength );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_TRANSACTIONID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) messageType, \n\t\t\t\t\t\tstrlen( messageType ) );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_MESSAGETYPE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Add the message status if we're the server */\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tif( cryptStatusError( scepStatus ) )\n\t\t\t{\n\t\t\t/* SCEP provides an extremely limited set of error codes so \n\t\t\t   there's not much that we can return in the way of additional \n\t\t\t   failure information */\n\t\t\tsetMessageData( &msgData, \n\t\t\t\t\t\t\t( scepStatus == CRYPT_ERROR_SIGNATURE ) ? \\\n\t\t\t\t\t\t\t\tMESSAGEFAILINFO_BADMESSAGECHECK : \\\n\t\t\t\t\t\t\t\tMESSAGEFAILINFO_BADREQUEST,\n\t\t\t\t\t\t\tMESSAGEFAILINFO_SIZE );\n\t\t\tkrnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_CERTINFO_SCEP_FAILINFO );\n\t\t\tsetMessageData( &msgData, MESSAGESTATUS_FAILURE,\n\t\t\t\t\t\t\tMESSAGESTATUS_SIZE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tsetMessageData( &msgData, MESSAGESTATUS_SUCCESS, \n\t\t\t\t\t\t\tMESSAGESTATUS_SIZE );\n\t\t\t}\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_PKISTATUS );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Add the nonce, identified as a sender nonce if we're the client and \n\t   a recipient nonce if we're the server */\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\t/* We're the server, use the client's nonce */\n\t\tsetMessageData( &msgData, protocolInfo->nonce, \n\t\t\t\t\t\tprotocolInfo->nonceSize );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SCEP_RECIPIENTNONCE );\n\t\t}\n\telse\n\t\t{\n\t\t/* If we're the client, generate a new nonce */\n\t\tsetMessageData( &msgData, protocolInfo->nonce, SCEP_NONCE_SIZE );\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tprotocolInfo->nonceSize = SCEP_NONCE_SIZE;\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SCEP_SENDERNONCE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iScepAttributes = iCmsAttributes;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* For some bizarre reason integer status values are encoded as strings,\n   so we have to convert them to numeric values before we can do anything\n   with them */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getScepStatusValue( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType, \n\t\t\t\t\t\tOUT int *value )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint numericValue, status;\n\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCmsAttributes ) );\n\tREQUIRES( attributeType == CRYPT_CERTINFO_SCEP_MESSAGETYPE || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_SCEP_PKISTATUS || \\\n\t\t\t  attributeType == CRYPT_CERTINFO_SCEP_FAILINFO );\n\n\t/* Clear return value */\n\t*value = CRYPT_ERROR;\n\n\t/* Get the status string and decode it into an integer */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, attributeType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = strGetNumeric( buffer, msgData.length, &numericValue, 0, 20 );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*value = numericValue;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tControl Information Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t OUT void *data, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tCRYPT_CERTIFICATE *scepResponsePtr = ( CRYPT_CERTIFICATE * ) data;\n\tCRYPT_CERTIFICATE iCryptCert;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( data, sizeof( int ) ) );\n\t\n\tREQUIRES( type == CRYPT_SESSINFO_RESPONSE || \\\n\t\t\t  type == CRYPT_SESSINFO_CACERTIFICATE || \\\n\t\t\t  type == CRYPT_SESSINFO_CMP_REQUESTTYPE );\n\n\t/* If it's a general protocol-specific attribute read, return the\n\t   information and exit */\n\tif( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )\n\t\t{\n\t\tif( scepInfo->requestType == CRYPT_REQUESTTYPE_NONE )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\t*( ( int * ) data ) = scepInfo->requestType;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we didn't get a response or CA certificate then there's nothing to \n\t   return */\n\tiCryptCert = ( type == CRYPT_SESSINFO_RESPONSE ) ? \\\n\t\t\t\t   sessionInfoPtr->iCertResponse : \\\n\t\t\t\t   sessionInfoPtr->iAuthInContext;\n\tif( iCryptCert == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* If the user is asking for the CA certificate and it wasn't fetched as \n\t   part of the protocol run (in other words it was added by the user\n\t   when the session was set up) then they can't read it back as session\n\t   output */\n\tif( type == CRYPT_SESSINFO_CACERTIFICATE && \\\n\t\t!TEST_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_FETCHEDCACERT ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Return the information to the caller */\n\tkrnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );\n\t*scepResponsePtr = iCryptCert;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tCRYPT_CERTIFICATE cryptCert = *( ( CRYPT_CERTIFICATE * ) data );\n\tBOOLEAN_INT isInited;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_REQUEST || \\\n\t\t\t  type == CRYPT_SESSINFO_CACERTIFICATE || \\\n\t\t\t  type == CRYPT_SESSINFO_CMP_REQUESTTYPE );\n\n\t/* If it's a request type, set it and exit */\n\tif( type == CRYPT_SESSINFO_CMP_REQUESTTYPE )\n\t\t{\n\t\tconst int requestType = *( ( int * ) data );\n\n\t\t/* SCEP only allows a subset of the full range of request types */\n\t\tif( requestType != CRYPT_REQUESTTYPE_INITIALISATION && \\\n\t\t\trequestType != CRYPT_REQUESTTYPE_CERTIFICATE && \\\n\t\t\trequestType != CRYPT_REQUESTTYPE_KEYUPDATE )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* For an initialisation request the private key must be a raw key\n\t\t   without an associated certificate */\n\t\tif( requestType == CRYPT_REQUESTTYPE_INITIALISATION )\n\t\t\t{\n\t\t\tif( sessionInfoPtr->privateKey != CRYPT_ERROR && \\\n\t\t\t\t!checkPrivateKey( sessionInfoPtr->privateKey, FALSE ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* For a renewal request the private key must have an associated\n\t\t\t   certificate, and there can't be a password present */\n\t\t\tif( sessionInfoPtr->privateKey != CRYPT_ERROR && \\\n\t\t\t\t!checkPrivateKey( sessionInfoPtr->privateKey, TRUE ) )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD ) != NULL )\n\t\t\t\t{\n\t\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Remember the request type */\n\t\tscepInfo->requestType = requestType;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that there aren't any conflicts with existing attributes */\n\tif( !checkAttributesConsistent( sessionInfoPtr, type ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* Make sure that everything is set up ready to go */\n\tstatus = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE, &isInited, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_IMMUTABLE );\n\tif( cryptStatusError( status ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\tif( type == CRYPT_SESSINFO_CACERTIFICATE )\n\t\t{\n\t\tif( !isInited )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\telse\n\t\t{\n\t\t/* If the user has indicated which request type they're using, make\n\t\t   sure that the PKCS #10 request is signed or unsigned as \n\t\t   required */\n\t\tif( scepInfo->requestType != CRYPT_REQUESTTYPE_NONE )\n\t\t\t{\n\t\t\t/* If it's an initialisation request then the PKCS #10 has to be\n\t\t\t   unsigned so that we can add the challengePassword */\n\t\t\tif( scepInfo->requestType == CRYPT_REQUESTTYPE_INITIALISATION )\n\t\t\t\t{\n\t\t\t\tif( isInited == TRUE )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If it's a renewal request then the PKCS #10 has to be \n\t\t\t\t   signed */\n\t\t\t\tif( !isInited )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( type == CRYPT_SESSINFO_CACERTIFICATE )\n\t\t{\n\t\t/* Make sure that the CA certificate has the unusual additional \n\t\t   capabilities that are required to meet the SCEP protocol \n\t\t   requirements.  Microsoft's SCEP server generates and uses \n\t\t   CA certs that only have CRYPT_KEYUSAGE_KEYENCIPHERMENT set but \n\t\t   not CRYPT_KEYUSAGE_DIGITALSIGNATURE (or occasionally\n\t\t   CRYPT_KEYUSAGE_DIGITALSIGNATURE but not \n\t\t   CRYPT_KEYUSAGE_KEYENCIPHERMENT, there doesn't seem to be any \n\t\t   discernable pattern to this), making them unusable for SCEP, so \n\t\t   this check will reject anything coming from a Microsoft server \n\t\t   unless the certificate compliance level is set to oblivious */\n\t\tif( !checkSCEPCACert( cryptCert, KEYMGMT_FLAG_NONE ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\n\t/* Add the request and increment its usage count */\n\tkrnlSendNotifier( cryptCert, IMESSAGE_INCREFCOUNT );\n\tif( type == CRYPT_SESSINFO_CACERTIFICATE )\n\t\t{\n\t\tsessionInfoPtr->iAuthInContext = cryptCert;\n\t\tstatus = processKeyFingerprint( sessionInfoPtr );\n\t\t}\n\telse\n\t\tsessionInfoPtr->iCertRequest = cryptCert;\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN const void *data,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( type, CRYPT_ATTRIBUTE ) );\n\n\tif( type != CRYPT_SESSINFO_USERNAME && \\\n\t\ttype != CRYPT_SESSINFO_PRIVATEKEY && \\\n\t\ttype != CRYPT_SESSINFO_REQUEST )\n\t\treturn( CRYPT_OK );\n\n\t/* If it's a user name, used for the SCEP transaction ID, make sure that\n\t   it meets the SCEP requirements */\n\tif( type == CRYPT_SESSINFO_USERNAME )\n\t\t{\n\t\tstatus = processUserName( sessionInfoPtr, \n\t\t\t\t\t\t\t\t  ( ( MESSAGE_DATA * ) data )->data,\n\t\t\t\t\t\t\t\t  ( ( MESSAGE_DATA * ) data )->length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* A return status of OK_SPECIAL is valid because it means that \n\t\t\t   the name has been handled internally */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\treturn( OK_SPECIAL );\n\n\t\t\treturn( CRYPT_ARGERROR_STR1 );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a certificate request, check that appropriate attributes are/\n\t   aren't present */\n\tif( type == CRYPT_SESSINFO_REQUEST )\n\t\t{\n\t\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\t\tconst CRYPT_CERTIFICATE cryptCertRequest = \\\n\t\t\t\t\t\t\t\t\t*( ( CRYPT_CERTIFICATE * ) data );\n\t\tMESSAGE_DATA msgData;\n\n\t\t/* Make sure that the SCEP protocol attributes, which get stuffed \n\t\t   into the request alongside the standard PKCS #10 data, haven't \n\t\t   been set since we need to set them ourselves */\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( cryptCertRequest, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_CHALLENGEPASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_CHALLENGEPASSWORD,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\n\t\t/* Make sure that at least a CN and a public key are present.  \n\t\t   Normally this would be verified when the request is signed but \n\t\t   since we have to use an unsigned/incomplete request for SCEP\n\t\t   purposes we have to explicitly perform a check here that would \n\t\t   normally be performed by the certificate-processing code.\n\n\t\t   Unfortunately there isn't any obvius way to check for the \n\t\t   presence of a public key in an unsigned certificate request,\n\t\t   since it hasn't been signed yet neither the CRYPT_IATTRIBUTE_SPKI \n\t\t   nor the CRYPT_IATTRIBUTE_CERTKEYALGO are readable so we just have\n\t\t   to leave this to be caught by the certificate-request completion\n\t\t   code */\n\t\tstatus = krnlSendMessage( cryptCertRequest, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &nameValue, \n\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetMessageData( &msgData, NULL, 0 );\n\t\t\tstatus = krnlSendMessage( cryptCertRequest, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tENSURES( type == CRYPT_SESSINFO_PRIVATEKEY );\n\n\t/* Make sure that there aren't any conflicts with existing attributes */\n\tif( !checkAttributesConsistent( sessionInfoPtr, type ) )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* If it's a client key, make sure that it meets the requirements, \n\t   depending on whether we're doing an initialisation or renewal \n\t   request.  If the request type hasn't been set yet then we default to  \n\t   an initialisation request, the most common type */\n\tif( !isServer( sessionInfoPtr ) )\n\t\t{\n\t\tconst CRYPT_CONTEXT cryptContext = *( ( CRYPT_CONTEXT * ) data );\n\n\t\tif( !checkPrivateKey( cryptContext, \n\t\t\t\t( scepInfo->requestType == CRYPT_REQUESTTYPE_CERTIFICATE || \\\n\t\t\t\t  scepInfo->requestType == CRYPT_REQUESTTYPE_KEYUPDATE ) ? \\\n\t\t\t\t  TRUE : FALSE ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodSCEP( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\tSESSION_NEEDS_USERID |\t\t/* Client attributes */\n\t\t\tSESSION_NEEDS_KEYORPASSWORD | \\\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\tSESSION_NEEDS_REQUEST,\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server attributes */\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCACERT | \\\n\t\t\tSESSION_NEEDS_CERTSTORE,\n\t\t1, 1, 1,\t\t\t\t\t/* Version 1 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\tinitSCEPserverProcessing( sessionInfoPtr );\n\telse\n\t\tinitSCEPclientProcessing( sessionInfoPtr );\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->checkAttributeFunction, checkAttributeFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SCEP */\n"
  },
  {
    "path": "deps/cl345/session/scep.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSCEP Definitions Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SCEP_DEFINED\n\n#define _SCEP_DEFINED\n\n/* Various SCEP constants */\n\n#define SCEP_NONCE_SIZE\t\t\t16\n\n/* SCEP protocol-specific flags that augment the general session flags.  These\n   are:\n\n\tPFLAG_PNPPKI: The remote systenm is PnP PKI capable.\n\n\tPFLAG_PENDING: The last exchange with the server returned a 'pending' \n\t\tstatus, so the get-server-response needs to be retried without\n\t\tgenering a new request.\n\n\tPFLAG_GOTCACAPS: The GetCACaps message used to determine a server's\n\t\tcapabilities has been sent.\n\n\tPFLAG_USERCACERT: The CA certificate was fetched automatically by \n\t\tcryptlib as part of a SCEP protocol run rather than being added \n\t\texplicitly by the user.  If it was fetched automatically then it's\n\t\tpart of the output of a protocol run and can be read by the user\n\t\tafter the run is complete, otherwise it's part of the protocol \n\t\tparameters and write-only */\n\n#define SCEP_PFLAG_NONE\t\t\t0x00\t/* No protocol-specific flags */\n#define SCEP_PFLAG_PNPPKI\t\t0x01\t/* Session is PnP PKI-capable */\n#define SCEP_PFLAG_FETCHEDCACERT 0x02\t/* CA cert fetched via SCEP */\n#define SCEP_PFLAG_PENDING\t\t0x08\t/* Certificate issue is pending */\n#define SCEP_PFLAG_GOTCACAPS\t0x10\t/* Sent GetCACaps message to server */\n#define SCEP_PFLAG_MAX\t\t\t0x03F\t/* Maximum possible flag value */\n\n/* The SCEP message type, status, and failure information.  For some \n   bizarre reason these integer values are communicated as text strings */\n\n#define MESSAGETYPE_CERTREP\t\t\t\t\"3\"\n#define MESSAGETYPE_RENEWAL\t\t\t\t\"18\"\n#define MESSAGETYPE_PKCSREQ\t\t\t\t\"19\"\n#define MESSAGETYPE_GETCERTINITIAL\t\t\"20\"\n#define MESSAGETYPE_GETCERT\t\t\t\t\"21\"\n#define MESSAGETYPE_GETCRL\t\t\t\t\"22\"\n\n#define MESSAGESTATUS_SUCCESS\t\t\t\"0\"\n#define MESSAGESTATUS_FAILURE\t\t\t\"2\"\n#define MESSAGESTATUS_PENDING\t\t\t\"3\"\n\n#define MESSAGEFAILINFO_BADALG\t\t\t\"0\"\n#define MESSAGEFAILINFO_BADMESSAGECHECK\t\"1\"\n#define MESSAGEFAILINFO_BADREQUEST\t\t\"2\"\n#define MESSAGEFAILINFO_BADTIME\t\t\t\"3\"\n#define MESSAGEFAILINFO_BADCERTID\t\t\"4\"\n\n#define MESSAGESTATUS_SIZE\t\t\t\t1\n#define MESSAGEFAILINFO_SIZE\t\t\t1\n\n/* Numeric equivalents of the above, to make them easier to work with */\n\n#define MESSAGETYPE_CERTREP_VALUE\t\t3\n#define MESSAGETYPE_RENEWAL_VALUE\t\t18\n#define MESSAGETYPE_PKCSREQ_VALUE\t\t19\n#define MESSAGETYPE_GETCERTINITIAL_VALUE 20\n#define MESSAGETYPE_GETCERT_VALUE\t\t21\n#define MESSAGETYPE_GETCRL_VALUE\t\t22\n\n#define MESSAGESTATUS_SUCCESS_VALUE\t\t0\n#define MESSAGESTATUS_FAILURE_VALUE\t\t2\n#define MESSAGESTATUS_PENDING_VALUE\t\t3\n\n#define MESSAGEFAILINFO_BADALG_VALUE\t0\n#define MESSAGEFAILINFO_BADMESSAGECHECK_VALUE 1\n#define MESSAGEFAILINFO_BADREQUEST_VALUE 2\n#define MESSAGEFAILINFO_BADTIME_VALUE\t3\n#define MESSAGEFAILINFO_BADCERTID_VALUE\t4\n\n/* SCEP HTTP content type */\n\n#define SCEP_CONTENT_TYPE\t\t\t\t\"application/x-pki-message\"\n#define SCEP_CONTENT_TYPE_LEN\t\t\t25\n#define SCEP_CONTENT_TYPE_GETCACERT\t\t\"application/x-x509-ca-cert\"\n#define SCEP_CONTENT_TYPE_GETCACERT_LEN\t26\n#define SCEP_CONTENT_TYPE_GETCACERTCHAIN \"application/x-x509-ca-ra-cert-chain\"\n#define SCEP_CONTENT_TYPE_GETCACERTCHAIN_LEN 35\n\n/* SCEP protocol state information.  This is passed around various\n   subfunctions that handle individual parts of the protocol */\n\ntypedef struct {\n\t/* Identification/state variable information.  SCEP uses a single\n\t   nonce, but when present in the initiator's message it's identified\n\t   as a sender nonce and when present in the responder's message\n\t   it's identified as a recipient nonce.\n\t\n\t   In order to accommodate nonstandard implementations, we allow for \n\t   nonces that are slightly larger than the required size */\n\tBUFFER( CRYPT_MAX_HASHSIZE, transIDsize ) \\\n\tBYTE transID[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Transaction nonce */\n\tBUFFER( CRYPT_MAX_HASHSIZE, nonceSize ) \\\n\tBYTE nonce[ CRYPT_MAX_HASHSIZE + 8 ];\t/* Nonce */\n\tint transIDsize, nonceSize;\n\n\t/* When sending/receiving SCEP messages, the user has to sign the \n\t   request data and decrypt the response data.  Since they don't have a \n\t   certificate at this point, they need to create an ephemeral self-\n\t   signed certificate to handle this task */\n\tCRYPT_CERTIFICATE iScepCert;\n\n\t/* When issuing a certificate, we need to keep a copy of the PKI user \n\t   information around in order to apply it to the certificate-issue \n\t   process */\n\tCRYPT_CERTIFICATE iPkiUser;\n\n\t/* Normally SCEP requires that the client or server key be used for both\n\t   encryption and signing, however if the algorithm doesn't support\n\t   encryption then password-based messaging has to be used */\n\tBOOLEAN clientSignOnlyKey, caSignOnlyKey;\n\tBYTE userPassword[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint userPasswordSize;\n\t} SCEP_PROTOCOL_INFO;\n\n/* Prototypes for functions in scep.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSCEP( IN const SESSION_INFO *sessionInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPprotocolInfo( OUT SCEP_PROTOCOL_INFO *protocolInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySCEPprotocolInfo( INOUT SCEP_PROTOCOL_INFO *protocolInfo );\nCHECK_RETVAL_BOOL \\\nBOOLEAN checkSCEPCACert( IN_HANDLE const CRYPT_CERTIFICATE iCaCert,\n\t\t\t\t\t\t IN_FLAGS_Z( KEYMGMT ) const int options );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint processKeyFingerprint( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint getScepStatusValue( IN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes,\n\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeType, \n\t\t\t\t\t\tOUT int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint createScepAttributes( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT SCEP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iScepAttributes,\n\t\t\t\t\t\t  IN_STRING const char *messageType,\n\t\t\t\t\t\t  IN_STATUS const int scepStatus );\n\n/* Prototypes for functions in scep_cli/scep_svr.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPclientProcessing( SESSION_INFO *sessionInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPserverProcessing( SESSION_INFO *sessionInfoPtr );\n\n#endif /* _SCEP_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/scep_cli.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib SCEP Client Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"scep.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/scep.h\"\n#endif /* Compiler-specific includes */\n\n/* Prototypes for functions in pnppki.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint pnpPkiSession( INOUT SESSION_INFO *sessionInfoPtr );\n\n#ifdef USE_SCEP\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import a SCEP CA certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int importCACertificate( OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCryptCert,\n\t\t\t\t\t\t\t\tIN_BUFFER( certLength ) const void *certificate,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int certLength,\n\t\t\t\t\t\t\t\tIN_FLAGS( KEYMGMT ) const int options )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tSTREAM stream;\n\tBOOLEAN isCertChain = FALSE;\n\tint tag, status;\n\n\tassert( isWritePtr( iCryptCert, sizeof( CRYPT_CERTIFICATE ) ) );\n\tassert( isReadPtrDynamic( certificate, certLength ) );\n\n\tREQUIRES( certLength > 4 && certLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( options == KEYMGMT_FLAG_USAGE_CRYPT || \\\n\t\t\t  options == KEYMGMT_FLAG_USAGE_SIGN );\n\n\t/* Clear return value */\n\t*iCryptCert = CRYPT_ERROR;\n\n\t/* Depending on what the server feels like it can return either a single\n\t   certificate or a complete certificate chain, with the type denoted\n\t   by the HTTP-transport content type.  Because we have no easy way of\n\t   getting at this, we sniff the payload data to see what it contains.\n\t   The two objects begin with:\n\n\t\tCert:\t\tSEQUENCE { SEQUENCE ...\n\t\tCert.chain:\tSEQNEUCE { OID ...\n\n\t   so we can use the second tag to determine what we've got */\n\tsMemConnect( &stream, certificate, certLength );\n\tstatus = readSequence( &stream, NULL );\n\tif( checkStatusPeekTag( &stream, status, tag ) && \\\n\t\ttag == BER_OBJECT_IDENTIFIER )\n\t\t{\n\t\t/* We've been sent a certificate chain, we need to import it as \n\t\t   such */\n\t\tisCertChain = TRUE;\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Import the certificate */\n\tif( isCertChain )\n\t\t{\n\t\tsetMessageCreateObjectIndirectInfoEx( &createInfo, certificate, \n\t\t\t\t\t\t\tcertLength, CRYPT_CERTTYPE_CERTCHAIN, options );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageCreateObjectIndirectInfo( &createInfo, certificate, \n\t\t\t\t\t\t\tcertLength, CRYPT_CERTTYPE_CERTIFICATE );\n\t\t}\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*iCryptCert = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check whether two certificates are identical.  Since these may be present \n   at the end of a certificate chain, we have to jump through extra hoops to\n   compare them */\n\nstatic BOOLEAN isSameCertificate( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert1,\n\t\t\t\t\t\t\t\t  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert2 )\n\t{\n\tBOOLEAN isSameCert = FALSE;\n\tint status;\n\n\tREQUIRES( isHandleRangeValid( iCryptCert1 ) );\n\tREQUIRES( isHandleRangeValid( iCryptCert2 ) );\n\n\t/* Lock the certificate chains for exclusive use */\n\tstatus = krnlSendMessage( iCryptCert1, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( iCryptCert2, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t( void ) krnlSendMessage( iCryptCert1, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t\treturn( status );\n\t\t}\n\n\t/* Select the leaf certificate in both chains */\n\tstatus = krnlSendMessage( iCryptCert1, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert2, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t\t  MESSAGE_VALUE_CURSORFIRST,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint compareStatus;\n\n\t\tcompareStatus = krnlSendMessage( iCryptCert1, IMESSAGE_COMPARE, \n\t\t\t\t\t\t\t\t\t\t ( MESSAGE_CAST ) &iCryptCert2,\n\t\t\t\t\t\t\t\t\t\t MESSAGE_COMPARE_CERTOBJ );\n\t\tif( cryptStatusOK( compareStatus ) )\n\t\t\tisSameCert = TRUE;\n\t\t}\n\t( void ) krnlSendMessage( iCryptCert1, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\t( void ) krnlSendMessage( iCryptCert2, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  MESSAGE_VALUE_FALSE, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_LOCKED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* It's not clear what we should return in the case of an error \n\t\t   (mostly because it's a shouldn't-occur condition), we have two \n\t\t   valid certificates so we shouldn't abort processing because a\n\t\t   compare operation failed.  Because of this we report a non-\n\t\t   match, which in most cases will allow things to proceeed as\n\t\t   required, and when it is a match it'll be caught later */\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( isSameCert );\n\t}\n\n/* Write a PKI datagram, with additional information communicated as part of \n   the HTTP metadata */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writePkiDatagramEx( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   IN_BUFFER_OPT( contentTypeLen ) \\\n\t\t\t\t\t\t\t\t\tconst char *contentType, \n\t\t\t\t\t\t\t   IN_LENGTH_TEXT_Z const int contentTypeLen )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tstatic const HTTP_REQ_INFO httpReqInfo = {\n\t\t\"operation\", 9,\n\t\t\"PKIOperation\", 12, \n\t\t\"\", 0\n\t\t};\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( contentType == NULL || \\\n\t\t\tisReadPtrDynamic( contentType, contentTypeLen ) );\n\n\tREQUIRES( ( contentType == NULL && contentTypeLen ) || \\\n\t\t\t  ( contentType != NULL && \\\n\t\t\t\tcontentTypeLen > 0 && contentTypeLen <= CRYPT_MAX_TEXTSIZE ) );\n\tREQUIRES( sessionInfoPtr->receiveBufEnd > 4 && \\\n\t\t\t  sessionInfoPtr->receiveBufEnd < MAX_BUFFER_SIZE );\n\n\t/* Write the datagram.  Request/response sessions use a single buffer \n\t   for both reads and writes, which is why we're (apparently) writing\n\t   the contents of the read buffer */\n\tstatus = initHttpInfoWriteEx( &httpDataInfo,\n\t\t\t\tsessionInfoPtr->receiveBuffer, sessionInfoPtr->receiveBufEnd, \n\t\t\t\tsessionInfoPtr->receiveBufSize, &httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\thttpDataInfo.contentType = contentType;\n\thttpDataInfo.contentTypeLen = contentTypeLen;\n\tstatus = swrite( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t}\n\telse\n\t\tstatus = CRYPT_OK;\t/* swrite() returns a byte count */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\n\treturn( status );\n\t}\n\n#ifdef USE_BASE64\n\n/* Some broken servers (and we're specifically talking Microsoft's one here) \n   don't handle POST but require the use of a POST disguised as a GET, for \n   which we provide the following variant of writePkiDatagram() that sends\n   the POST as an HTTP GET */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writePkiDatagramAsGet( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tstatic const HTTP_REQ_INFO httpReqInfo = {\n\t\t\"operation\", 9,\n\t\t\"PKIOperation\", 12, \n\t\t\"message=\", 8\n\t\t};\n\tconst int dataSize = sessionInfoPtr->receiveBufEnd;\n\tint fullEncodedLength, encodedLength, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( dataSize > 4 && dataSize < MAX_BUFFER_SIZE );\n\n\t/* The way that we do the encoding is to move the raw data up in the \n\t   buffer to make room for the encoded form and then encode it into the \n\t   freed-up room:\n\n\t\t\t\t+---------------+\n\t\t\t\tv\t  Encode\t|\n\t\t+---------------+---------------+\n\t\t| base64'd data\t|\tRaw data\t|\n\t\t+---------------+---------------+\n\t\t|<-fullEncLen ->|<- dataSize -->|\n\n\t   First we have to determine how long the base64-encoded form of the \n\t   message will be and make sure that it fits into the buffer */\n\tstatus = base64encodeLen( dataSize, &fullEncodedLength, \n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_NONE );\n\tENSURES( cryptStatusOK( status ) );\n\tif( fullEncodedLength + dataSize >= sessionInfoPtr->receiveBufSize )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Move the message up in the buffer to make room for its encoded form \n\t   and encode it */\n\tREQUIRES( boundsCheck( fullEncodedLength, dataSize, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tmemmove( sessionInfoPtr->receiveBuffer + fullEncodedLength,\n\t\t\t sessionInfoPtr->receiveBuffer, dataSize );\n\tstatus = base64encode( sessionInfoPtr->receiveBuffer, fullEncodedLength, \n\t\t\t\t\t\t   &encodedLength, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer + fullEncodedLength,\n\t\t\t\t\t\t   dataSize, CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* The base64 encoding in the form that we're calling it produces raw \n\t   output without the trailing '=' padding bytes so we have to manually\n\t   insert the required padding in based on the calculated vs.actual\n\t   encoded length.  This can't overflow because we're simply padding the \n\t   data out to the fullEncodedLength size that was calculated earlier */\n\tif( encodedLength < fullEncodedLength )\n\t\t{\n\t\tconst int delta = fullEncodedLength - encodedLength;\n\n\t\tREQUIRES( delta > 0 && delta < 3 );\n\t\tREQUIRES( boundsCheck( encodedLength, delta, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\t\tmemcpy( sessionInfoPtr->receiveBuffer + encodedLength,\n\t\t\t\t\"========\", delta );\n\t\t}\n\n\t/* Now that it's base64-encoded it can no longer be sent as is because \n\t   some base64 values, specifically '/', '+' and '=', are used for other\n\t   purposes in URLs.  Because of this we have to make another pass over\n\t   the data escaping these characters into the '%xx' form */\n\tLOOP_MAX( i = 0, i < fullEncodedLength, i++ )\n\t\t{\n\t\tchar escapeBuffer[ 8 + 8 ];\n\t\tconst int ch = sessionInfoPtr->receiveBuffer[ i ];\n\n\t\t/* If this isn't a special character, there's nothing to do */\n\t\tif( ch != '/' && ch != '+' && ch != '=' )\n\t\t\tcontinue;\n\n\t\t/* Make room for the escaped form and encode the value */\n\t\tif( fullEncodedLength + 2 >= sessionInfoPtr->receiveBufSize )\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\tREQUIRES( boundsCheck( i + 2, fullEncodedLength - i, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\t\tmemmove( sessionInfoPtr->receiveBuffer + i + 2, \n\t\t\t\t sessionInfoPtr->receiveBuffer + i, fullEncodedLength - i );\n\t\tsprintf_s( escapeBuffer, 8, \"%%%02X\", ch );\n\t\tREQUIRES( boundsCheck( i, 3, sessionInfoPtr->receiveBufSize ) );\n\t\tmemcpy( sessionInfoPtr->receiveBuffer + i, escapeBuffer, 3 );\n\t\tfullEncodedLength += 2;\n\t\t} \n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Send the POST as an HTTP GET */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_POST_AS_GET );\n\tstatus = initHttpInfoWriteEx( &httpDataInfo, \n\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, fullEncodedLength, \n\t\t\t\t\t\tsessionInfoPtr->receiveBufSize, &httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\thttpDataInfo.contentType = SCEP_CONTENT_TYPE;\n\thttpDataInfo.contentTypeLen = SCEP_CONTENT_TYPE_LEN;\n\tstatus = swrite( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_POST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t}\n\telse\n\t\tstatus = CRYPT_OK;\t/* swrite() returns a byte count */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\n\treturn( status );\n\t}\n#endif /* USE_BASE64 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAdditional Request Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the various bolted-on additions to the basic SCEP protocol */\n\ntypedef enum { GETREQUEST_NONE, GETREQUEST_GETCACAPS, GETREQUEST_GETCACERT, \n\t\t\t   GETREQUEST_LAST } GETREQUEST_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendGetRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   const GETREQUEST_TYPE requestType )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n#if 0\t/* 23/3/18 Older versions of the SCEP draft specified the GetCACaps\n\t\t\t\t   format as '... \"?operation=GetCACaps&message=\" CA-IDENT' \n\t\t\t\t   but no-one knew what CA-IDENT was meant to be, see the \n\t\t\t\t   comment below.  Current versions of the draft specify\n\t\t\t\t   the message as '\"?operation=GetCACaps\"' */\n\tstatic const HTTP_REQ_INFO httpReqGetCACaps = {\n\t\t\"operation\", 9,\n\t\t\"GetCACaps\", 9,\n\t\t\"message=*\", 9\n\t\t};\n\tstatic const HTTP_REQ_INFO httpReqGetCACert = {\n\t\t\"operation\", 9,\n\t\t\"GetCACert\", 9,\n\t\t\"message=*\", 9\n\t\t};\n#else\n\tstatic const HTTP_REQ_INFO httpReqGetCACaps = {\n\t\t\"operation\", 9,\n\t\t\"GetCACaps\", 9,\n\t\t};\n\tstatic const HTTP_REQ_INFO httpReqGetCACert = {\n\t\t\"operation\", 9,\n\t\t\"GetCACert\", 9,\n\t\t};\n#endif /* 0 */\n\tHTTP_REQ_INFO *httpReqInfo = \\\n\t\t( requestType == GETREQUEST_GETCACAPS ) ? \\\n\t\t( void * ) &httpReqGetCACaps : ( void * ) &httpReqGetCACert;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES( isEnumRange( requestType, GETREQUEST ) );\n\n\t/* Perform an HTTP GET with arguments \"operation=<command>&message=*\".\n\t   The \"message=\" portion is rather unclear, according to the spec\n\t   it's \"a string that represents the certification authority issuer \n\t   identifier\" but no-one (including the spec's authors) seem to know\n\t   what this is supposed to be.  We use '*' on the basis that it's\n\t   better than nothing */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_GET );\n\tstatus = initHttpInfoReqEx( &httpDataInfo, httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\tif( requestType == GETREQUEST_GETCACAPS )\n\t\t{\n\t\t/* Indicate that a response consisting of a text message, rather \n\t\t   than PKI data, is valid for this operation */\n\t\thttpDataInfo.responseIsText = TRUE;\n\t\t}\n\tstatus = swrite( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tstatus = initHttpInfoRead( &httpDataInfo, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = sread( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\tsizeof( HTTP_DATA_INFO ) );\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_POST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\tretExtErr( status, \n\t\t\t\t   ( status, &sessionInfoPtr->errorInfo,\n\t\t\t\t     &sessionInfoPtr->errorInfo,\n\t\t\t\t\t \"'%s' operation failed: \", \n\t\t\t\t\t ( requestType == GETREQUEST_GETCACAPS ) ? \\\n\t\t\t\t\t\t\"GetCACaps\" : \"GetCACert\" ) );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd = httpDataInfo.bytesAvail;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getCACapabilities( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM stream;\n\tint length, lineCount, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Get the CA capabilities */\n\tstatus = sendGetRequest( sessionInfoPtr, GETREQUEST_GETCACAPS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Microsoft's NDES under Server 2003 and Server 2008 without the\n\t\t   KB2483564 hotfix either simply close the connection with no \n\t\t   further output or send back a zero-length response.  If we get \n\t\t   this then we provide a hint about what the problem could be.  \n\t\t   \n\t\t   This can be a bit problematic because we could also be talking \n\t\t   to something that isn't a SCEP server, which will lead to a \n\t\t   misleading diagnostic, but it should be safe to assume that the \n\t\t   user is intending to talk to a SCEP server and that if we get \n\t\t   this response then it's likely to be Server 2003/pre-hotfix \n\t\t   2008.\n\t\t   \n\t\t   In any case even with GetCACaps enabled via a hotfix the results\n\t\t   are more or less useless, AES isn't listed as a supported\n\t\t   algorithm but is supported anyway, and the response is hardcoded\n\t\t   to use single DES (!!!) no matter what algorithm is used for the\n\t\t   request (see http://serverfault.com/questions/458643/can-i-\n\t\t   configure-wndows-ndes-server-to-use-triple-des-3des-algorithm-\n\t\t   for-pkcs7) */\n\t\tif( status == CRYPT_ERROR_READ )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t\t( CRYPT_ERROR_OPEN, SESSION_ERRINFO, \n\t\t\t\t\t  \"Server closed the connection in response to a SCEP \"\n\t\t\t\t\t  \"GetCACaps message, if this is Windows Server 2003 \"\n\t\t\t\t\t  \"or 2008 then you need to upgrade to at least Server \"\n\t\t\t\t\t  \"2008 R2 with the KB2483564 hotfix in order to talk \"\n\t\t\t\t\t  \"to the server\" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\n\t/* Read the GetCACaps response lines */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, \n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tLOOP_MED( lineCount = 0, \n\t\t\t  sMemDataLeft( &stream ) > 0 && lineCount < 64, \n\t\t\t  lineCount++ )\n\t\t{\n\t\tchar buffer[ 512 + 8 ];\n\n\t\tstatus = readTextLine( ( READCHAR_FUNCTION ) sgetc, &stream, \n\t\t\t\t\t\t\t   buffer, 512, &length, NULL, \n\t\t\t\t\t\t\t   FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid GETCACaps response line %d\", lineCount ) );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( lineCount >= 64 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Excessive number (more than %d) of GETCACaps response \"\n\t\t\t\t  \"lines\", 64 ) );\n\t\t}\n\n\t/* We currently don't do much more with this, what the (effectively) \n\t   dummy read does is allow us to fingerprint NDES so that we can work \n\t   around its bugs later on */\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getCACertificate( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sessionInfoPtr->iAuthInContext == CRYPT_ERROR );\n\n\t/* Get the CA certificate */\n\tstatus = sendGetRequest( sessionInfoPtr, GETREQUEST_GETCACERT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Since we can't use readPkiDatagram() because of the weird dual-\n\t   purpose HTTP transport used in SCEP where the main protocol uses\n\t   POST + read response while the bolted-on portions use various GET\n\t   variations, we have to duplicate portions of readPkiDatagram() here.  \n\t   See the readPkiDatagram() function for code comments explaining the \n\t   following operations */\n\tif( sessionInfoPtr->receiveBufEnd < 4 || \\\n\t\tsessionInfoPtr->receiveBufEnd >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_UNDERFLOW,\n\t\t\t\t( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid CA certificate size %d\", \n\t\t\t\t  sessionInfoPtr->receiveBufEnd ) );\n\t\t}\n\tstatus = checkCertObjectEncodingLength( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t\t\t\t\t&sessionInfoPtr->receiveBufEnd );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid CA certificate encoding\" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_cacrt\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Import the CA/RA certificates and save it/them for later use.  There\n\t   may be distinct signature and encryption certificates stuffed into \n\t   the same chain so we first try for a signature certificate */\n\tstatus = importCACertificate( &sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_SIGN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid SCEP CA certificate\" ) );\n\t\t}\n\tSET_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_FETCHEDCACERT );\n\n\t/* Now that we've got a signing certificate, check whether this single\n\t   certificate has the unusual additional capabilities that are required\n\t   for SCEP */\n\tif( !checkSCEPCACert( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t  KEYMGMT_FLAG_NONE ) )\n\t\t{\n\t\t/* It doesn't have the required capabilities, assume that it's a\n\t\t   signature-only certificate and try again for an encryption\n\t\t   certificate */\n\t\tstatus = importCACertificate( &sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_CRYPT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid SCEP CA certificate\" ) );\n\t\t\t}\n\t\t\n\t\t/* Because of the vagaries of dealing with chains containing \n\t\t   multiple certificates, with or without keyUsage extensions, the\n\t\t   certificate-import code returns a best-match certificate rather\n\t\t   than an absolute-match certificate.  In particular if there's \n\t\t   only one certificate present and it doesn't have the encryption\n\t\t   keyUsage that we require, it'll be returned anyway since it's the\n\t\t   only certificate that can be returned.  In order to deal with \n\t\t   this we have to check whether the certificates at the end of the\n\t\t   two chains are identical */\n\t\tif( isSameCertificate( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t   sessionInfoPtr->iCryptOutContext ) )\n\t\t\t{\n\t\t\t/* There's only one certificate and it's signature-only, use the\n\t\t\t   signature-only form of SCEP */\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tsessionInfoPtr->iCryptOutContext = CRYPT_ERROR;\n\t\t\tprotocolInfo->caSignOnlyKey = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* Process the server's key fingerprint */\n\tstatus = processKeyFingerprint( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the CA certificate has the unusual additional \n\t   capabilities that are required to meet the SCEP protocol \n\t   requirements */\n\tif( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )\n\t\t{\n\t\t/* There are distinct encryption and signing certificates (probably\n\t\t   from an RA) present, make sure that they meet the necessary\n\t\t   requirements */\n\t\tif( !checkSCEPCACert( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_SIGN ) || \\\n\t\t\t!checkSCEPCACert( sessionInfoPtr->iCryptOutContext, \n\t\t\t\t\t\t\t  KEYMGMT_FLAG_USAGE_CRYPT ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"CA/RA certificate usage restrictions prevent them \"\n\t\t\t\t\t  \"from being used for SCEP\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* There's a single multipurpose certificate present, make sure that \n\t\t   it meets all of the requirements for SCEP use */\n\t\tif( !checkSCEPCACert( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t  protocolInfo->caSignOnlyKey ? \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_USAGE_SIGN : \\\n\t\t\t\t\t\t\t\tKEYMGMT_FLAG_NONE ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"CA certificate usage restrictions prevent it from being \"\n\t\t\t\t\t  \"used for SCEP\" ) );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRequest Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a self-signed certificate for signing the request and decrypting\n   the response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createScepCert( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_CERTIFICATE iNewCert;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\ttime_t currentTime = getTime();\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\t/* Create a certificate, add the certificate request and other \n\t   information required by SCEP to it, and sign it.  To limit the \n\t   exposure from having it floating around out there we give it a \n\t   validity of a day, which is somewhat longer than required but may be \n\t   necessary to get around time-zone issues in which the CA checks the \n\t   expiry time relative to the time zone that it's in rather than GMT \n\t   (although given some of the broken certificates used with SCEP it \n\t   seems likely that many CAs do little to no checking at all).\n\t   \n\t   SCEP requires that the certificate serial number match the user name/\n\t   transaction ID, the spec actually says that the transaction ID should \n\t   be a hash of the public key but since it never specifies exactly what \n\t   is hashed (\"MD5 hash on [sic] public key\") this can probably be \n\t   anything.  We use the user name, which is required to identify the \n\t   pkiUser entry in the CA certificate store */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  &sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTREQUEST );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Set the certificate usage to signing (to sign the request) and\n\t\t   encryption (to decrypt the response, if the key is capable of\n\t\t   this).  We've already checked that the sign capability was\n\t\t   available when the key was added to the session.\n\t\t   \n\t\t   We delete the attribute before we try and set it in case there \n\t\t   was already one present in the request */\n\t\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_DELETEATTRIBUTE, \n\t\t\t\t\t\t NULL, CRYPT_CERTINFO_KEYUSAGE );\n\t\tif( protocolInfo->clientSignOnlyKey )\n\t\t\t{\n\t\t\tstatic const int keyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE;\n\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &keyUsage, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatic const int keyUsage = CRYPT_KEYUSAGE_DIGITALSIGNATURE | \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_KEYENCIPHERMENT;\n\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &keyUsage, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_KEYUSAGE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) &currentTime, \n\t\t\t\t\t\tsizeof( time_t ) );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_VALIDFROM );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcurrentTime += 86400;\t/* 24 hours */\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) &currentTime, \n\t\t\t\t\t\tsizeof( time_t ) );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_VALIDTO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_TRUE,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SELFSIGNED );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGN, NULL,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->privateKey );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create ephemeral self-signed SCEP \"\n\t\t\t\t  \"certificate\" ) );\n\t\t}\n\n\t/* Now that we have a certificate, attach it to the private key.  This \n\t   is somewhat ugly since it alters the private key by attaching a \n\t   certificate that (as far as the user is concerned) shouldn't really \n\t   exist, but we need to do this to allow signing and decryption.  A \n\t   side-effect is that it constrains the private-key actions to make \n\t   them internal-only since it now has a certificate attached, hopefully \n\t   the user won't notice this since the key will have a proper CA-issued \n\t   certificate attached to it shortly.\n\n\t   To further complicate things, we can't directly attach the newly-\n\t   created certificate because it already has a public-key context \n\t   attached to it, which would result in two keys being associated with \n\t   the single certificate.  To resolve this, we create a second copy of \n\t   the certificate as a data-only certificate and attach that to the \n\t   private key */\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &iNewCert, CRYPT_IATTRIBUTE_CERTCOPY_DATAONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETDEPENDENT, &iNewCert, \n\t\t\t\t\t\t\t\t  SETDEP_OPTION_NOINCREF );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tprotocolInfo->iScepCert = createInfo.cryptHandle;\n\telse\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\treturn( status );\n\t}\n\n/* Complete the user-supplied PKCS #10 request by adding SCEP-internal\n   attributes and information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int completeScepCertRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\tINOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tMESSAGE_DATA msgData;\n\tint status = CRYPT_ERROR_NOTINITED;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Add the password to the PKCS #10 request as a ChallengePassword\n\t   attribute.  We always send this in its ASCII string form even if it's \n\t   an encoded value because the ChallengePassword attribute has to be a \n\t   text string */\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\t/* Copy the user password for later in case we need it to decrypt a\n\t\t   response for a signature-only key */\n\t\tREQUIRES( rangeCheck( attributeListPtr->valueLength, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( protocolInfo->userPassword, attributeListPtr->value,\n\t\t\t\tattributeListPtr->valueLength );\n\t\tprotocolInfo->userPasswordSize = attributeListPtr->valueLength;\n\n\t\tINJECT_FAULT( CORRUPT_AUTHENTICATOR, \n\t\t\t\t\t  SESSION_CORRUPT_AUTHENTICATOR_SCEP_1 );\n\t\tsetMessageData( &msgData, attributeListPtr->value,\n\t\t\t\t\t\tattributeListPtr->valueLength );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CHALLENGEPASSWORD );\n\t\tINJECT_FAULT( CORRUPT_AUTHENTICATOR, \n\t\t\t\t\t  SESSION_CORRUPT_AUTHENTICATOR_SCEP_2 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't finalise PKCS #10 certificate request\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Sign the request */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_SIGN, NULL,\n\t\t\t\t\t\t\t  sessionInfoPtr->privateKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtObj( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->iCertRequest,\n\t\t\t\t\t \"Couldn't sign PKCS #10 certificate request\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the request type needed to continue after the server responds with\n   an issue-pending response:\n\n\tissuerAndSubject ::= SEQUENCE {\n\t\tissuer\t\tName,\n\t\tsubject\t\tName\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int createScepPendingRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *dataLength )\n\t{\n\tSTREAM stream;\n\tint issuerAndSubjectLen DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* Determine the overall length of the issuer and subject DNs */\n\tsMemNullOpen( &stream );\n\tstatus = exportAttributeToStream( &stream, \n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = exportAttributeToStream( &stream, \n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tissuerAndSubjectLen = stell( &stream );\n\tsMemClose( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the issuerAndSubject to the session buffer */\n\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer, \n\t\t\t  sessionInfoPtr->receiveBufSize );\n\twriteSequence( &stream, issuerAndSubjectLen );\n\tstatus = exportAttributeToStream( &stream, \n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = exportAttributeToStream( &stream, \n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBJECT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t*dataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Create a SCEP request message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createScepRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tconst CRYPT_CERTIFICATE iCACryptContext = \\\n\t\t( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR ) ? \\\n\t\tsessionInfoPtr->iCryptOutContext : sessionInfoPtr->iAuthInContext;\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tERROR_INFO errorInfo;\n\tconst BOOLEAN isPendingRequest = TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t\t\t\tSCEP_PFLAG_PENDING ) ? \\\n\t\t\t\t\t\t\t\t\t TRUE : FALSE;\n\tint dataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* If it's a straight issue operation, extract the request data into the \n\t   session buffer */\n\tif( !isPendingRequest )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't get PKCS #10 request data from SCEP request \"\n\t\t\t\t\t  \"object\" ) );\n\t\t\t}\n\t\tdataLength = msgData.length;\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a continuation of a previous issue operation whose status \n\t\t   the server has reported as pending, encode the special-case form\n\t\t   that's required for this operation */\n\t\tstatus = createScepPendingRequest( sessionInfoPtr, &dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't create SCEP request needed to continue from \"\n\t\t\t\t\t  \"an issue-pending response\" ) );\n\t\t\t}\n\t\t}\n\tDEBUG_DUMP_FILE( isPendingRequest ? \"scep_req0pend\" : \"scep_req0\", \n\t\t\t\t\t sessionInfoPtr->receiveBuffer, dataLength );\n\n\t/* Phase 1: Encrypt the data using either the CA's key or the client's\n\t   password */\n\tif( protocolInfo->caSignOnlyKey )\n\t\t{\n\t\tstatus = envelopeWrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CMS, CRYPT_CONTENT_NONE, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, protocolInfo->userPassword, \n\t\t\t\t\t\t\t   protocolInfo->userPasswordSize, \n\t\t\t\t\t\t\t   &errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = envelopeWrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CMS, CRYPT_CONTENT_NONE, \n\t\t\t\t\t\t\t   iCACryptContext, NULL, 0, &errorInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't encrypt SCEP request data with CA key: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( isPendingRequest ? \"scep_req1pend\" : \"scep_req1\", \n\t\t\t\t\t sessionInfoPtr->receiveBuffer, dataLength );\n\n\t/* Create the SCEP signing attributes */\n\tstatus = createScepAttributes( sessionInfoPtr, protocolInfo,  \n\t\t\t\t\t&iCmsAttributes, isPendingRequest ? \\\n\t\t\t\t\t\tMESSAGETYPE_GETCERTINITIAL : \\\n\t\t\t\t\t( scepInfo->requestType == CRYPT_REQUESTTYPE_INITIALISATION ) ? \\\n\t\t\t\t\t\tMESSAGETYPE_PKCSREQ : MESSAGETYPE_RENEWAL, \n\t\t\t\t\tCRYPT_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create SCEP request signing attributes\" ) );\n\t\t}\n\n\t/* Phase 2: Sign the data using the self-signed certificate and SCEP \n\t   attributes */\n\tstatus = envelopeSign( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t   &sessionInfoPtr->receiveBufEnd, \n\t\t\t\t\t\t   CRYPT_CONTENT_NONE, sessionInfoPtr->privateKey, \n\t\t\t\t\t\t   iCmsAttributes, &errorInfo );\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't sign request data with ephemeral SCEP \"\n\t\t\t\t\t \"certificate: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( isPendingRequest ? \"scep_req2pend\" : \"scep_req2\", \n\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tResponse Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check the status of a SCEP response */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkScepStatus( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tIN_HANDLE const CRYPT_CERTIFICATE iCmsAttributes )\n\t{\n\ttypedef struct {\n\t\tconst int failInfoValue;\n\t\tconst int failStatus;\n\t\tconst char *failInfoString;\n\t\t} FAILINFO_MESSAGE;\n\tstatic const FAILINFO_MESSAGE failInfoMsgTbl[] = {\n\t\t{ MESSAGEFAILINFO_BADALG_VALUE, CRYPT_ERROR_NOTAVAIL,\n\t\t  \"Unrecognized or unsupported algorithm identifier\" },\n\t\t{ MESSAGEFAILINFO_BADMESSAGECHECK_VALUE, CRYPT_ERROR_SIGNATURE,\n\t\t  \"Integrity check failed\" },\n\t\t{ MESSAGEFAILINFO_BADREQUEST_VALUE, CRYPT_ERROR_PERMISSION,\n\t\t  \"Transaction not permitted or supported\" },\n\t\t{ MESSAGEFAILINFO_BADTIME_VALUE, CRYPT_ERROR_INVALID,\n\t\t  \"CMS signingTime attribute was not sufficiently close to the \"\n\t\t  \"system time\" },\n\t\t{ MESSAGEFAILINFO_BADCERTID_VALUE, CRYPT_ERROR_NOTFOUND,\n\t\t  \"No certificate could be identified matching the provided \"\n\t\t  \"criteria\" },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR_FAILED, \"<Unknown failure reason>\" },\n\t\t\t{ CRYPT_ERROR, CRYPT_ERROR_FAILED, \"<Unknown failure reason>\" }\n\t\t};\n#ifdef USE_ERRMSGS\n\tconst char *valueString = \"<Unknown failure reason>\";\n#endif /* USE_ERRMSGS */\n\tint value, extValue, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCmsAttributes ) );\n\n\t/* Make sure that we've got the correct response type */\n\tstatus = getScepStatusValue( iCmsAttributes,\n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SCEP_MESSAGETYPE, &value );\n\tif( cryptStatusError( status ) || value != MESSAGETYPE_CERTREP_VALUE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid SCEP response type, expected %d\", \n\t\t\t\t  MESSAGETYPE_CERTREP_VALUE ) );\n\t\t}\n\n\t/* Check the status of the operation */\n\tstatus = getScepStatusValue( iCmsAttributes, \n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SCEP_PKISTATUS, &value );\n\tif( cryptStatusError( status ) )\n\t\tvalue = MESSAGESTATUS_FAILURE_VALUE;\n\tif( value == MESSAGESTATUS_SUCCESS_VALUE )\n\t\treturn( CRYPT_OK );\n\n\t/* There was a problem with the operation, get more detailed information\n\t   on what went wrong.  If we get a MESSAGESTATUS_PENDING result then we \n\t   can't go any further until the CA makes up its mind about issuing us \n\t   a certificate */\n\tif( value == MESSAGESTATUS_PENDING_VALUE )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_PENDING );\n\t\tretExt( CRYPT_ENVELOPE_RESOURCE, \n\t\t\t\t( CRYPT_ENVELOPE_RESOURCE, SESSION_ERRINFO, \n\t\t\t\t  \"SCEP server reports that certificate status is \"\n\t\t\t\t  \"pending, try again later\" ) );\n\t\t}\n\n\t/* It's some other sort of error, report the details to the user */\n\tstatus = getScepStatusValue( iCmsAttributes, \n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SCEP_FAILINFO, &extValue );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\tLOOP_SMALL( i = 0,\n\t\t\t\t\tfailInfoMsgTbl[ i ].failInfoValue != extValue && \\\n\t\t\t\t\t\tfailInfoMsgTbl[ i ].failInfoValue != CRYPT_ERROR && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( failInfoMsgTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\tFAILINFO_MESSAGE ),\n\t\t\t\t\ti++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( failInfoMsgTbl, FAILINFO_MESSAGE ) );\n#ifdef USE_ERRMSGS\n\t\tvalueString = failInfoMsgTbl[ i ].failInfoString;\n#endif /* USE_ERRMSGS */\n\t\tvalue = extValue;\n\t\tstatus = failInfoMsgTbl[ i ].failStatus;\n\t\t}\n\telse\n\t\t{\n\t\t/* We can't report anything more than a generic \"failed\" */\n\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tretExt( status, \n\t\t\t( status, SESSION_ERRINFO, \n\t\t\t  \"SCEP server reports that certificate issue operation \"\n\t\t\t  \"failed with error code %d (%s)\", value, valueString ) );\n\t}\n\n/* Check a SCEP response message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkScepResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tBYTE buffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint dataLength, sigResult, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\tREQUIRES( userNamePtr != NULL );\n\n\t/* Reset any issue-pending status that may have been set from a previous\n\t   operation */\n\tCLEAR_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_PENDING );\n\n\t/* Phase 1: Sig-check the data using the CA's key */\n\tDEBUG_DUMP_FILE( \"scep_resp2\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = envelopeSigCheck( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   sessionInfoPtr->iAuthInContext, &sigResult,\n\t\t\t\t\t\t\t   NULL, &iCmsAttributes, &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Invalid CMS signed data in CA response: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE_OPT( \"scep_resp1\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t dataLength );\t/* May be zero len.if error status */\n\tif( cryptStatusError( sigResult ) )\n\t\t{\n\t\t/* The signed data was valid but the signature on it wasn't, this is\n\t\t   a different style of error than the previous one */\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( sigResult, \n\t\t\t\t( sigResult, SESSION_ERRINFO, \n\t\t\t\t  \"Bad signature on CA response data\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"envelopeSigCheck\" );\n\n\t/* Check that the returned transaction ID matches our transaction ID */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_TRANSACTIONID );\n\tif( cryptStatusError( status ) || \\\n\t\tmsgData.length != userNamePtr->valueLength || \\\n\t\tmemcmp( buffer, userNamePtr->value, userNamePtr->valueLength ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Returned transaction ID doesn't match our original \"\n\t\t\t\t  \"transaction ID\" ) );\n\t\t}\n\n\t/* Check that the returned nonce matches our initial nonce.  It's now\n\t   identified as a recipient nonce since it's coming from the \n\t   responder.  This is somewhat superfluous given that the transactionID\n\t   serves the same purpose, but we check it because it's in the spec */\n\tsetMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_RECIPIENTNONCE );\n\tif( cryptStatusError( status ) || \\\n\t\tmsgData.length != protocolInfo->nonceSize || \\\n\t\tmemcmp( buffer, protocolInfo->nonce, protocolInfo->nonceSize ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Returned nonce doesn't match our original nonce\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Check that the operation succeeded */\n\tstatus = checkScepStatus( sessionInfoPtr, iCmsAttributes );\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkScepStatus\" );\n\n\t/* Phase 2: Decrypt the data using either our self-signed key or our\n\t   password */\n\tif( protocolInfo->clientSignOnlyKey )\n\t\t{\n\t\tstatus = envelopeUnwrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t\t CRYPT_UNUSED, protocolInfo->userPassword, \n\t\t\t\t\t\t\t\t protocolInfo->userPasswordSize, &errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = envelopeUnwrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t\t sessionInfoPtr->privateKey, NULL, 0, \n\t\t\t\t\t\t\t\t &errorInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tregisterCryptoFailure();\n\t\tretExtErr( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't decrypt CMS enveloped data in CA \"\n\t\t\t\t\t \"response: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_resp0\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t dataLength );\n\tCFI_CHECK_UPDATE( \"envelopeUnwrap\" );\n\n\t/* Finally, import the returned certificate(s) as a PKCS #7 chain */\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTCHAIN );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKCS #7 certificate chain in CA response\" ) );\n\t\t}\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_CREATEOBJECT_INDIRECT\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"envelopeSigCheck\",\n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE_S\", \"checkScepStatus\",\n\t\t\t\t\t\t\t\t\t\"envelopeUnwrap\",\n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_CREATEOBJECT_INDIRECT\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSCEP Client Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with a SCEP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSCEP_PROTOCOL_INFO protocolInfo;\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tSTREAM_PEER_TYPE peerSystemType;\n\tconst BOOLEAN isPendingRequest = TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t\t\t\tSCEP_PFLAG_PENDING ) ? \\\n\t\t\t\t\t\t\t\t\t TRUE : FALSE;\n\tBOOLEAN sendPostAsGet = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* If the user hasn't explicitly set a request type, default to an \n\t   initialisation request */\n\tif( scepInfo->requestType == CRYPT_REQUESTTYPE_NONE )\n\t\tscepInfo->requestType = CRYPT_REQUESTTYPE_INITIALISATION;\n\n\t/* Try and find out which extended SCEP capabilities the CA supports */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_GOTCACAPS ) )\n\t\t{\n\t\t/* The returned status from getCACapabilities() isn't currently \n\t\t   used, the only system for which we need it is Microsoft's NDES \n\t\t   and that has a broken implementation of it unless the exact \n\t\t   conditions given in the long comment in getCACapabilities() are \n\t\t   met, a nice catch-22 where we can't identify the broken system \n\t\t   because the mechanism used to identify its brokenness is in turn \n\t\t   broken.\n\t\t   \n\t\t   We do however use the function side-effects indirectly by using \n\t\t   the HTTP GET that's sent to fingerprint the remote server, which \n\t\t   (usually) allows us to tell whether we're talking to NDES */\n\t\t( void ) getCACapabilities( sessionInfoPtr );\n\t\t\n\t\t/* We've got the CA capabilities, don't try and read them again */\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_GOTCACAPS );\n\t\t}\n\tCFI_CHECK_UPDATE( \"getCACapabilities\" );\n\n\t/* See whether we can determine the remote system type, used to work \n\t   around bugs in implementations (all of which are currently from\n\t   Microsoft) */\n\tstatus = sioctlGet( &sessionInfoPtr->stream, STREAM_IOCTL_GETPEERTYPE, \n\t\t\t\t\t\t&peerSystemType, sizeof( STREAM_PEER_TYPE ) );\n\tif( cryptStatusOK( status ) && peerSystemType != STREAM_PEER_NONE )\n\t\t{\n\t\tswitch( peerSystemType )\n\t\t\t{\n\t\t\tcase STREAM_PEER_MICROSOFT:\n\t\t\tcase STREAM_PEER_MICROSOFT_2008:\n\t\t\t\t/* Microsoft doesn't support HTTP POST, but then it also \n\t\t\t\t   doesn't have a working implementation of GetCACaps that\n\t\t\t\t   would indicate that it doesn't support HTTP POST either */\n\t\t\t\tsendPostAsGet = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase STREAM_PEER_MICROSOFT_2012:\n\t\t\t\t/* This server version has a different set of bugs, it \n\t\t\t\t   now supports GetCACaps but silently switches to OAEP when \n\t\t\t\t   AES is used.  If we're not running a custom build with \n\t\t\t\t   OAEP enabled then we probably won't be able to continue \n\t\t\t\t   later so we provide a warning about this now.\n\t\t\t\t   \n\t\t\t\t   In addition it now supports HTTP POST, but returns a\n\t\t\t\t   zero-length response as an \"HTTP/1.1 200 OK\"-status \n\t\t\t\t   message in response to a POSTed request, so we still need \n\t\t\t\t   to rely on HTTP GET to communicate with it */\n#ifndef USE_OAEP\n\t\t\t\tDEBUG_PUTS(( \"Peer is Server 2012, if decryption of the \"\n\t\t\t\t\t\t\t \"returned message fails then this is due to \"\n\t\t\t\t\t\t\t \"the server erroneously using OAEP in its \"\n\t\t\t\t\t\t\t \"response\" ));\n#endif /* USE_OAEP */\n\t\t\t\tsendPostAsGet = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\n\t/* Get the issuing CA certificate via SCEP's bolted-on HTTP GET facility \n\t   if necessary */\n\tinitSCEPprotocolInfo( &protocolInfo );\n\tif( sessionInfoPtr->iAuthInContext == CRYPT_ERROR )\n\t\t{\n\t\tstatus = getCACertificate( sessionInfoPtr, &protocolInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"initSCEPprotocolInfo\" );\n\n\t/* If this is an initialisation request and we're not still waiting for \n\t   a previous pending issue operation to complete, complete the PKCS #10 \n\t   request by adding the required SCEP attributes and signing it, and \n\t   create the self-signed certificate that we need in order to sign and \n\t   decrypt messages */\n\tif( !checkContextCapability( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_DECRYPT ) )\n\t\t{\n\t\t/* The client's key is signature-only, remember this for later when\n\t\t   we need to perform encrypted messaging */\n\t\tprotocolInfo.clientSignOnlyKey = TRUE;\n\t\t}\n\tif( ( scepInfo->requestType == CRYPT_REQUESTTYPE_INITIALISATION ) && \\\n\t\t!isPendingRequest )\n\t\t{\n\t\tstatus = completeScepCertRequest( sessionInfoPtr, &protocolInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = createScepCert( sessionInfoPtr, &protocolInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createScepCert\" );\n\n\t/* Get a new certificate from the server */\n\tstatus = createScepRequest( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef USE_BASE64\n\t\tif( sendPostAsGet )\n\t\t\tstatus = writePkiDatagramAsGet( sessionInfoPtr );\n\t\telse\n#endif /* USE_BASE64 */\n\t\t\t{\n\t\t\tstatus = writePkiDatagramEx( sessionInfoPtr, SCEP_CONTENT_TYPE,\n\t\t\t\t\t\t\t\t\t\t SCEP_CONTENT_TYPE_LEN );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = checkScepResponse( sessionInfoPtr, &protocolInfo );\n\tif( ( scepInfo->requestType == CRYPT_REQUESTTYPE_INITIALISATION ) && \\\n\t\t!isPendingRequest )\n\t\t{\n\t\t/* If this is a new request rather than a renewal or a retry of an \n\t\t   existing pending one then we've created a temporary certificate, \n\t\t   clean it up before we exit */\n\t\tkrnlSendNotifier( protocolInfo.iScepCert, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkScepResponse\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"getCACapabilities\", \"initSCEPprotocolInfo\", \n\t\t\t\t\t\t\t\t\t\"createScepCert\", \"checkScepResponse\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransactWrapper( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* If it's not a plug-and-play PKI session, just pass the call on down\n\t   to the client transaction function */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SCEP_PFLAG_PNPPKI ) )\n\t\treturn( clientTransact( sessionInfoPtr ) );\n\n\t/* We're doing plug-and-play PKI, point the transaction function at the \n\t   client-transact function to execute the PnP steps, then reset it back \n\t   to the PnP wrapper after we're done */\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransact );\n\tstatus = pnpPkiSession( sessionInfoPtr );\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransactWrapper );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPclientProcessing( SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransactWrapper );\n\t}\n#endif /* USE_SCEP */\n"
  },
  {
    "path": "deps/cl345/session/scep_svr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib SCEP Server Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n  #include \"certstore.h\"\n  #include \"scep.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n  #include \"session/certstore.h\"\n  #include \"session/scep.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SCEP\n\n/* Table mapping a query submitted as an HTTP GET to a supplementary SCEP\n   operation.  Note that the first letter must be lowercase for the\n   case-insensitive quick match */\n\nenum { SCEP_OPERATION_GETCACAPS, SCEP_OPERATION_GETCACERT, \n\t   SCEP_OPERATION_GETCACERTCHAIN };\n\nstatic const CERTSTORE_READ_INFO certstoreReadInfo[] = {\n\t{ \"getCACaps\", 9, SCEP_OPERATION_GETCACAPS, CERTSTORE_FLAG_NONE },\n\t{ \"getCACert\", 9, SCEP_OPERATION_GETCACERT, CERTSTORE_FLAG_NONE },\n\t{ \"getCACertChain\", 14, SCEP_OPERATION_GETCACERTCHAIN, CERTSTORE_FLAG_NONE },\n\t{ NULL, 0, CRYPT_ERROR, CERTSTORE_FLAG_NONE },\n\t\t{ NULL, 0, CRYPT_ERROR, CERTSTORE_FLAG_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Deliver an Einladung betreff Kehrseite to the client.  We don't bother\n   checking the return value since there's nothing that we can do in the case \n   of an error except close the connection, which we do anyway since this is \n   the last message.  We don't return extended error information since this \n   would overwrite the information for the error that caused us to return an \n   error response */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic void sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SCEP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t\t   IN_ERROR const int scepStatus )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\t\n\tREQUIRES_V( cryptStatusError( scepStatus ) );\n\n\t/* Sign the error response using the CA key and SCEP attributes */\n\tstatus = createScepAttributes( sessionInfoPtr, protocolInfo,  \n\t\t\t\t\t\t\t\t   &iCmsAttributes, MESSAGETYPE_CERTREP, \n\t\t\t\t\t\t\t\t   scepStatus );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tERROR_INFO errorInfo;\n\n\t\t/* Since this message is being sent in response to an existing \n\t\t   error, we don't care about the possible error information \n\t\t   returned from the function that sends the error response,\n\t\t   so the errorInfo result is ignored */\n\t\tstatus = envelopeSign( NULL, 0, sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t\t   &sessionInfoPtr->receiveBufEnd, \n\t\t\t\t\t\t\t   CRYPT_CONTENT_NONE, sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t   iCmsAttributes, &errorInfo );\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tHTTP_DATA_INFO httpDataInfo;\n\n\t\t/* If we encounter an error processing the initial request then \n\t\t   there won't be enough information available to create an error \n\t\t   response.  Similarly if we run into problems generating the\n\t\t   response then there won't be anything available to send.  At this \n\t\t   point the best that we can do is send an error at the HTTP \n\t\t   level */\n\t\tstatus = initHttpInfoReq( &httpDataInfo );\n\t\tENSURES_V( cryptStatusOK( status ) );\n\t\thttpDataInfo.reqStatus = scepStatus;\n\t\t( void ) swrite( &sessionInfoPtr->stream, &httpDataInfo, \n\t\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\t\treturn;\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_srespx\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Return the response to the client, discarding any error indication \n\t   from the write.  Since we're already in an error state there's not \n\t   much that we can do in terms of alerting the user if a further error \n\t   occurs when writing the error response, so we ignore any potential \n\t   write errors that occur at this point */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_LASTMESSAGE, TRUE );\n\t( void ) writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, \n\t\t\t\t\t\t\t   SCEP_CONTENT_TYPE_LEN );\n\t}\n\n/* Get information for a PKI user */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getPkiUserInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ 64 + 8 ];\n\tint keyIDsize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( userNamePtr != NULL );\n\t\n\t/* Since it's a cryptlib encoded user ID we need to decode it before we \n\t   can look up a PKI user with it */\n\tREQUIRES( TEST_FLAG( userNamePtr->flags, ATTR_FLAG_ENCODEDVALUE ) );\n\tstatus = decodePKIUserValue( keyID, 64, &keyIDsize,\n\t\t\t\t\t\t\t\t userNamePtr->value, \n\t\t\t\t\t\t\t\t userNamePtr->valueLength );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Get the user information for the request from the certificate \n\t   store */\n\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID, keyID, \n\t\t\t\t\t\t   keyIDsize, NULL, 0, KEYMGMT_FLAG_NONE );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tchar userID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint userIDlen;\n\n\t\tuserIDlen = min( userNamePtr->valueLength, CRYPT_MAX_TEXTSIZE );\n\t\tREQUIRES( rangeCheck( userIDlen, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( userID, userNamePtr->value, userIDlen );\n\t\tretExtObj( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t \"Couldn't find PKI user information for %s\",\n\t\t\t\t\t sanitiseString( userID, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t userIDlen ) ) );\n\t\t}\n\tprotocolInfo->iPkiUser = getkeyInfo.cryptHandle;\n\tDEBUG_DUMP_CERT( \"scep_pkiuser\", protocolInfo->iPkiUser );\n\n\t/* Get the password from the PKI user object */\n\tsetMessageData( &msgData, protocolInfo->userPassword, \n\t\t\t\t\tCRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( protocolInfo->iPkiUser, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprotocolInfo->userPasswordSize = msgData.length;\n\t\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD, \n\t\t\t\t\t\t\t\t\tprotocolInfo->userPassword, \n\t\t\t\t\t\t\t\t\tprotocolInfo->userPasswordSize, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\tATTR_FLAG_ENCODEDVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( protocolInfo->userPassword, CRYPT_MAX_TEXTSIZE );\n\t\tprotocolInfo->userPasswordSize = 0;\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't copy PKI user password from PKI user object \"\n\t\t\t\t  \"into session object\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAdditional Request Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process one of the bolted-on additions to the basic SCEP protocol */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processAdditionalScepRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t const HTTP_URI_INFO *httpUriInfo )\n\t{\n\tHTTP_URI_INFO rewrittenHttpUriInfo;\n\tMESSAGE_DATA msgData;\n\tint operationType, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( httpUriInfo, sizeof( HTTP_URI_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* If the client has fed us an HTTP GET request, find out what they  \n\t   want.  SCEP's handling of HTTP requests is a bit different from the \n\t   \"attribute '=' value\" lookup that's normally used for HTTP data \n\t   retrieval.  Instead, it uses the format \n\t   \"'operation =' value '&' extraData\", with the search key buried in \n\t   the 'extraData' value.  In addition the content of the 'extraData' \n\t   value isn't defined outside of \"any string which is understood by the \n\t   CA\".  However since 'value' defines what we want, we can determine \n\t   what to return based on this and ignore the 'extraData' portion.\n\n\t   In order to fix up the query information into a format that works \n\t   with standard HTTP queries, we rewrite the query data from the \n\t   \"'operation =' value '&' extraData\" form into \"attribute '=' value\" \n\t   before we process the query */\n\tmemset( &rewrittenHttpUriInfo, 0, sizeof( HTTP_URI_INFO ) );\n\tREQUIRES( rangeCheck( httpUriInfo->valueLen, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( rewrittenHttpUriInfo.attribute, httpUriInfo->value, \n\t\t\thttpUriInfo->valueLen );\n\trewrittenHttpUriInfo.attributeLen = httpUriInfo->valueLen;\n\tif( httpUriInfo->extraDataLen > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( httpUriInfo->extraDataLen, 1, \n\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( rewrittenHttpUriInfo.value, httpUriInfo->extraData, \n\t\t\t\thttpUriInfo->extraDataLen );\n\t\trewrittenHttpUriInfo.valueLen = httpUriInfo->extraDataLen;\n\t\t}\n\tstatus = processCertQuery( sessionInfoPtr, &rewrittenHttpUriInfo,\n\t\t\t\t\t\t\t   certstoreReadInfo, \n\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( certstoreReadInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t\t   CERTSTORE_READ_INFO ),\n\t\t\t\t\t\t\t   &operationType, NULL, 0, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\treturn( status );\n\t\t}\n\tENSURES( operationType == SCEP_OPERATION_GETCACAPS || \\\n\t\t\t operationType == SCEP_OPERATION_GETCACERT || \\\n\t\t\t operationType == SCEP_OPERATION_GETCACERTCHAIN );\n\n\t/* If it's a CA capabilities query, return the information as raw text\n\t   over HTTP */\n\tif( operationType == SCEP_OPERATION_GETCACAPS )\n\t\t{\n\t\tSTREAM stream;\n\n\t\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 );\n\t\tif( algoAvailable( CRYPT_ALGO_AES ) )\n\t\t\tswrite( &stream, \"AES\\n\", 4 );\n\t\tswrite( &stream, \"POSTPKIOperation\\n\", 17 );\n\t\tif( algoAvailable( CRYPT_ALGO_3DES ) )\n\t\t\tswrite( &stream, \"DES3\\n\", 5 );\n#if 0\t/* 14/6/14 Too risky to implement given its current state in the \n\t\t\t\t   spec, see the discussion on the JSCEP mailing list for\n\t\t\t\t   details */\n\t\tstatus = swrite( &stream, \"Renewal\\n\", 8 );\n#endif /* 0 */\n\t\tstatus = swrite( &stream, \"SCEPStandard\\n\", 13 );\n\t\tif( algoAvailable( CRYPT_ALGO_SHA1 ) )\n\t\t\tstatus = swrite( &stream, \"SHA-1\\n\", 6 );\n\t\tif( algoAvailable( CRYPT_ALGO_SHA2 ) )\n\t\t\tstatus = swrite( &stream, \"SHA-256\\n\", 8 );\n\t\tif( algoAvailable( CRYPT_ALGO_SHAng ) )\n\t\t\tstatus = swrite( &stream, \"SHAng\\n\", 6 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tsessionInfoPtr->receiveBufEnd = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\treturn( writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t  SCEP_CONTENT_TYPE_LEN ) );\n\t\t}\n\n\t/* Export the CA certificate, either as a standalone certificate or a \n\t   full certificate chain depending on what was requested, and send it \n\t   to the client */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  ( operationType == SCEP_OPERATION_GETCACERT ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTIFICATE : \\\n\t\t\t\t\t\t\t\tCRYPT_CERTFORMAT_CERTCHAIN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't export CA certificate%s for '%s' request\", \n\t\t\t\t  ( operationType == SCEP_OPERATION_GETCACERT ) ? \\\n\t\t\t\t\t\"\" : \" chain\",\n\t\t\t\t  ( operationType == SCEP_OPERATION_GETCACERT ) ? \\\n\t\t\t\t\t\"GetCACert\" : \"GetCACertChain\" ) );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd = msgData.length;\n\tif( operationType == SCEP_OPERATION_GETCACERT )\n\t\t{\n\t\treturn( writePkiDatagram( sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SCEP_CONTENT_TYPE_GETCACERT,\n\t\t\t\t\t\t\t\t  SCEP_CONTENT_TYPE_GETCACERT_LEN ) );\n\t\t}\n\treturn( writePkiDatagram( sessionInfoPtr,  \n\t\t\t\t\t\t\t  SCEP_CONTENT_TYPE_GETCACERTCHAIN,\n\t\t\t\t\t\t\t  SCEP_CONTENT_TYPE_GETCACERTCHAIN_LEN ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRequest Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check a SCEP request message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkScepRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT SCEP_PROTOCOL_INFO *protocolInfo, \n\t\t\t\t\t\t\t OUT_ALWAYS BOOLEAN *requestDataAvailable )\n\t{\n\tSCEP_INFO *scepInfo = sessionInfoPtr->sessionSCEP;\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tBYTE keyIDbuffer[ KEYID_SIZE + 8 ];\n\tBOOLEAN gotMessageValue = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint dataLength, algorithm, sigResult, value, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\tassert( isWritePtr( requestDataAvailable, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Clear return value */\n\t*requestDataAvailable = FALSE;\n\n\t/* Phase 1: Sig-check the self-signed data */\n\tDEBUG_DUMP_FILE( \"scep_sreq2\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = envelopeSigCheck( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, &sigResult, \n\t\t\t\t\t\t\t   &protocolInfo->iScepCert, &iCmsAttributes,\n\t\t\t\t\t\t\t   &errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Invalid CMS signed data in client request: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_sreq1\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t dataLength );\n\tif( cryptStatusError( sigResult ) )\n\t\t{\n\t\t/* The signed data was valid but the signature on it wasn't, this is\n\t\t   a different style of error than the previous one */\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( sigResult, \n\t\t\t\t( sigResult, SESSION_ERRINFO, \n\t\t\t\t  \"Bad signature on client request data\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"envelopeSigCheck\" );\n\n\t/* Make sure that the client certificate is valid for signing, and\n\t   decryption if it's a crypto-capable algorithm.  In effect the signing \n\t   capability has already been checked by the fact that the certificate \n\t   signed the request but we do an explicit check here just to be \n\t   thorough */\n\tstatus = krnlSendMessage( protocolInfo->iScepCert, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &algorithm, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) || \\\n\t\t!checkContextCapability( protocolInfo->iScepCert, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGCHECK ) || \\\n\t\t( isCryptAlgo( algorithm ) && \\\n\t\t  !checkContextCapability( protocolInfo->iScepCert, \n\t\t\t\t\t\t\t\t   MESSAGE_CHECK_PKC_ENCRYPT ) ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Ephemeral SCEP client certificate isn't valid for \"\n\t\t\t\t  \"signing/encryption\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkContextCapability\" );\n\n\t/* Get the nonce and transaction ID and save it for the reply */\n\tsetMessageData( &msgData, protocolInfo->nonce, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_SCEP_SENDERNONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprotocolInfo->nonceSize = msgData.length;\n\t\tsetMessageData( &msgData, protocolInfo->transID, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_SCEP_TRANSACTIONID );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Request is missing a nonce/transaction ID\" ) );\n\t\t}\n\tprotocolInfo->transIDsize = msgData.length;\n\tINJECT_FAULT( SESSION_CORRUPT_NONCE, SESSION_CORRUPT_NONCE_SCEP_1 );\n\tINJECT_FAULT( SESSION_SCEP_CORRUPT_TRANSIDVALUE, \n\t\t\t\t  SESSION_SCEP_CORRUPT_TRANSIDVALUE_1 );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_GETATTRIBUTE_S\" );\n\n\t/* Since the request is for a cryptlib server it'll have a transaction \n\t   ID that's a cryptlib-encoded PKI user ID.  If we don't get this then \n\t   we reject the request.\n\t   \n\t   Note that we have to actually decode the user ID to determine that\n\t   it's completely valid since isPKIUserValue() merely identifies it as\n\t   being a cryptlib-style user ID.  Only a full decode will tell us \n\t   whether it's actually a valid user ID rather than just looking like\n\t   one */\n\tif( protocolInfo->transIDsize != 17 || \\\n\t\t!isPKIUserValue( protocolInfo->transID, protocolInfo->transIDsize ) || \\\n\t\tcryptStatusError( decodePKIUserValue( keyIDbuffer, KEYID_SIZE, &value,\n\t\t\t\t\t\t\t\t\t\t\t  protocolInfo->transID, \n\t\t\t\t\t\t\t\t\t\t\t  protocolInfo->transIDsize ) ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,\n\t\t\t\t  \"Request has an invalid transaction ID '%s'\",\n\t\t\t\t  sanitiseString( protocolInfo->transID, \n\t\t\t\t\t\t\t\t  protocolInfo->transIDsize,\n\t\t\t\t  \t\t\t\t  protocolInfo->transIDsize ) ) );\n\t\t}\n\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\tprotocolInfo->transID, \n\t\t\t\t\t\t\t\tprotocolInfo->transIDsize, \n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, ATTR_FLAG_ENCODEDVALUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateSessionInfo\" );\n\n\t/* We've now got enough request data available to construct a SCEP-level \n\t   response to an error instead of an HTTP-level one, let the caller \n\t   know.  Note that this lets an attacker know that they've made it this\n\t   far in the checking, but it's not obvious that this is a security\n\t   problem, especially since they can get a good idea of how far they \n\t   got from the different error conditions that will be returned */\n\t*requestDataAvailable = TRUE;\n\n\t/* Check that we've been sent the correct type of message */\n\tstatus = getScepStatusValue( iCmsAttributes,\n\t\t\t\t\t\t\t\t CRYPT_CERTINFO_SCEP_MESSAGETYPE, &value );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tgotMessageValue = TRUE;\n\t\tif( value != MESSAGETYPE_PKCSREQ_VALUE && \\\n\t\t\tvalue != MESSAGETYPE_RENEWAL_VALUE )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We can get here through two error paths, either we've got a valid\n\t\t   message type but it's the wrong message, or we've got a \n\t\t   completely invalid message type.  We have to tailor the error\n\t\t   message to fit the exact condition */\n\t\tif( gotMessageValue )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Incorrect SCEP message type %d\", value ) );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid SCEP message type\" ) );\n\t\t}\n\tscepInfo->requestType = ( value == MESSAGETYPE_PKCSREQ_VALUE ) ? \\\n\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_INITIALISATION : \\\n\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_CERTIFICATE;\n\tCFI_CHECK_UPDATE( \"getScepStatusValue\" );\n\n\t/* Get the information on the indicated PKI user */\n\tstatus = getPkiUserInfo( sessionInfoPtr, protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Phase 2: Decrypt the data using either our CA key or the client's \n\t   password */\n\tif( protocolInfo->caSignOnlyKey )\n\t\t{\n\t\tstatus = envelopeUnwrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t\t CRYPT_UNUSED, protocolInfo->userPassword, \n\t\t\t\t\t\t\t\t protocolInfo->userPasswordSize,\n\t\t\t\t\t\t\t\t &errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = envelopeUnwrap( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t\t sessionInfoPtr->privateKey, NULL, 0, \n\t\t\t\t\t\t\t\t &errorInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tregisterCryptoFailure();\n\t\tretExtErr( status, \n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't decrypt CMS enveloped data in client \"\n\t\t\t\t\t \"request: \" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"envelopeUnwrap\" );\n\n\t/* Import the request as a PKCS #10 request */\n\tsetMessageCreateObjectIndirectInfo( &createInfo,\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTREQUEST );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKCS #10 request in client request\" ) );\n\t\t}\n\n\t/* Finally, check the certificate used to sign the SCEP message.  If \n\t   it's an initialisation request then the the key in the PKCS #10 \n\t   request has to match the one in the signing certificate */\n\tif( scepInfo->requestType == CRYPT_REQUESTTYPE_INITIALISATION )\n\t\t{\n\t\tsetMessageData( &msgData, keyIDbuffer, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEYID );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( protocolInfo->iScepCert, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_KEYID );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"Key in client request signing certificate doesn't \"\n\t\t\t\t\t  \"match key in PKCS #10 request\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\t\tBYTE certIDbuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\t/* It's a renewal request, the signing certificate has to be one\n\t\t   that we've issued in the past */\n\t\tsetMessageData( &msgData, certIDbuffer, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, \n\t\t\t\t\t\t\t\t   msgData.data, msgData.length, NULL, 0, \n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tchar certIDText[ CRYPT_MAX_TEXTSIZE + 8 ];\n#endif /* USE_ERRMSGS */\n\n\t\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tformatFingerprint( certIDText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   certIDbuffer, msgData.length );\n\t\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"Unrecognised certificate with ID '%s' used to sign \"\n\t\t\t\t\t  \"client renewal request\", certIDText ) );\n\t\t\t}\n\t\t}\n\tsessionInfoPtr->iCertRequest = createInfo.cryptHandle;\n\tCFI_CHECK_UPDATE( \"keyCheck\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"envelopeSigCheck\", \n\t\t\t\t\t\t\t\t\t\"checkContextCapability\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_GETATTRIBUTE_S\", \n\t\t\t\t\t\t\t\t\t\"getScepStatusValue\", \"envelopeUnwrap\",\n\t\t\t\t\t\t\t\t\t\"keyCheck\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Issue a certificate from a SCEP request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int issueCertFromRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tMESSAGE_KEYMGMT_INFO setkeyInfo;\n\tMESSAGE_CERTMGMT_INFO certMgmtInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE requestPassword[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Get the password from the PKCS #10 request and make sure that it \n\t   matches the user password.  In the case of a signature-only CA key\n\t   we've already confirmed this because we decrypted the client's\n\t   message with it, but the redundant check here only costs a few\n\t   cycles so it's not worth special-casing it */\n\tsetMessageData( &msgData, requestPassword, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CHALLENGEPASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't get challenge password from PKCS #10 \"\n\t\t\t\t  \"request\" ) );\n\t\t}\n\tif( protocolInfo->userPasswordSize != msgData.length || \\\n\t\t!compareDataConstTime( protocolInfo->userPassword, requestPassword, \n\t\t\t\t\t\t\t   protocolInfo->userPasswordSize ) )\n\t\t{\n\t\tzeroise( requestPassword, CRYPT_MAX_TEXTSIZE );\n\t\tretExt( CRYPT_ERROR_WRONGKEY, \n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,\n\t\t\t\t  \"Password in PKCS #10 request doesn't match PKI user \"\n\t\t\t\t  \"password\" ) );\n\t\t}\n\n\t/* If the subject only knows their CN, they may send a CN-only subject DN \n\t   in the hope that we can fill it in for them.  In addition there may be \n\t   other constraints that the CA wants to apply, these are handled by\n\t   applying the PKI user information to the request */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &protocolInfo->iPkiUser,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_PKIUSERINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID, \n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"User information in PKCS #10 request can't be \"\n\t\t\t\t  \"reconciled with stored information for the user\" ) );\n\t\t}\n\n\t/* Add the request to the certificate store */\n\tsetMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0, \n\t\t\t\t\t\t   NULL, 0, KEYMGMT_FLAG_NONE );\n\tsetkeyInfo.cryptHandle = sessionInfoPtr->iCertRequest;\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_SETKEY, &setkeyInfo, \n\t\t\t\t\t\t\t  KEYMGMT_ITEM_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Request couldn't be added to certificate store\" ) );\n\t\t}\n\n\t/* Convert the request into a certificate */\n\tsetMessageCertMgmtInfo( &certMgmtInfo, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\tsessionInfoPtr->iCertRequest );\n\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset,\n\t\t\t\t\t\t\t  IMESSAGE_KEY_CERTMGMT, &certMgmtInfo,\n\t\t\t\t\t\t\t  CRYPT_CERTACTION_ISSUE_CERT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't issue certificate for user\" ) );\n\t\t}\n\tsessionInfoPtr->iCertResponse = certMgmtInfo.cryptCert;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create an SCEP response message */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createScepResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SCEP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_DATA msgData;\n\tERROR_INFO errorInfo;\n\tint dataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( SCEP_PROTOCOL_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Check whether the key is encryption-capable */\n\tif( !checkContextCapability( sessionInfoPtr->iCertResponse, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\t{\n\t\t/* The client's key is signature-only, remember this for later when\n\t\t   we need to perform encrypted messaging */\n\t\tprotocolInfo->clientSignOnlyKey = TRUE;\n\t\t}\n\n\t/* Extract the response data into the session buffer */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer,\n\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t\t  IMESSAGE_CRT_EXPORT, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTCHAIN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't get PKCS #7 certificate chain from SCEP \"\n\t\t\t\t  \"response object\" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_sresp0\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t msgData.length );\n\n\t/* Phase 1: Encrypt the data using either the client's key or their \n\t   password */\n\tif( protocolInfo->clientSignOnlyKey )\n\t\t{\n\t\tstatus = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CMS, CRYPT_CONTENT_NONE, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, protocolInfo->userPassword, \n\t\t\t\t\t\t\t   protocolInfo->userPasswordSize, \n\t\t\t\t\t\t\t   &errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = envelopeWrap( sessionInfoPtr->receiveBuffer, msgData.length,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, &dataLength, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CMS, CRYPT_CONTENT_NONE, \n\t\t\t\t\t\t\t   protocolInfo->iScepCert, NULL, 0, \n\t\t\t\t\t\t\t   &errorInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo,\n\t\t\t\t\t \"Couldn't encrypt response data with client %s: \",\n\t\t\t\t\t protocolInfo->clientSignOnlyKey ? \"password\" : \"key\" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_sresp1\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t dataLength );\n\n\t/* Create the SCEP signing attributes */\n\tstatus = createScepAttributes( sessionInfoPtr, protocolInfo,  \n\t\t\t\t\t\t\t\t   &iCmsAttributes, MESSAGETYPE_CERTREP, \n\t\t\t\t\t\t\t\t   CRYPT_OK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create SCEP response signing attributes\" ) );\n\t\t}\n\n\t/* Phase 2: Sign the data using the CA key and SCEP attributes */\n\tstatus = envelopeSign( sessionInfoPtr->receiveBuffer, dataLength,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize, \n\t\t\t\t\t\t   &sessionInfoPtr->receiveBufEnd, \n\t\t\t\t\t\t   CRYPT_CONTENT_NONE, sessionInfoPtr->privateKey, \n\t\t\t\t\t\t   iCmsAttributes, &errorInfo );\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExtErr( status,\n\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo, \n\t\t\t\t\t \"Couldn't sign response data with CA key: \" ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"scep_sresp2\", sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSCEP Server Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with a SCEP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSCEP_PROTOCOL_INFO protocolInfo;\n\tSTREAM stream;\n\tBOOLEAN requestDataOK, processedAdditionalRequest = TRUE;\n\tBOOLEAN caSignOnlyKey = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint requestCount, length DUMMY_INIT, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSCEP( sessionInfoPtr ) );\n\n\t/* Check whether the server's key is encryption-capable */\n\tif( !checkContextCapability( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_DECRYPT ) )\n\t\t{\n\t\t/* The CA's key is signature-only, remember this for later when we \n\t\t   need to perform encrypted messaging */\n\t\tcaSignOnlyKey = TRUE;\n\t\t}\n\n\t/* SCEP is a weird protocol that started out as a basic IPsec \n\t   RSA certificate-provisioning mechanism for routers but then had a \n\t   pile of additional functionality bolted onto it via HTTP mechanisms \n\t   rather than having the protocol itself handle the extra \n\t   functionality.  Because of this we have to handle not only the \n\t   standard HTTP-as-a-substrate mechanism used by the other protocols \n\t   but also HTTP GET requests for additional information that the \n\t   original protocol didn't accommodate.  This means that we have to\n\t   set the allowed request type to STREAM_HTTPREQTYPE_ANY and provide\n\t   an additional HTTP_URI_INFO for the HTTP_DATA_INFO to contain the\n\t   GET request data if that's what the client is sending */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t   STREAM_HTTPREQTYPE_ANY );\n\tLOOP_SMALL( requestCount = 0, requestCount < 5, requestCount++ )\n\t\t{\n\t\tHTTP_DATA_INFO httpDataInfo;\n\t\tHTTP_URI_INFO httpUriInfo;\n\n\t\tmemset( &httpUriInfo, 0, sizeof( HTTP_URI_INFO ) );\n\t\tstatus = initHttpInfoReadEx( &httpDataInfo, \n\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize, &httpUriInfo );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\tstatus = sread( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\t\tsizeof( HTTP_DATA_INFO ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we've processed one of the bolted-on additions to SCEP \n\t\t\t   then a read error at this point isn't necessarily a protocol\n\t\t\t   error */\n\t\t\tif( processedAdditionalRequest && status == CRYPT_ERROR_READ )\n\t\t\t\t{\n\t\t\t\t/* It's possible to send one or more of the bolted-in\n\t\t\t\t   protocol messages without ever running the actual SCEP\n\t\t\t\t   protocol, so if we get a read error after performing a\n\t\t\t\t   bolted-on exchange then we report a success status\n\t\t\t\t   since that may be all that the client was intending to \n\t\t\t\t   do */\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\tsNetGetErrorInfo( &sessionInfoPtr->stream, \n\t\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If it's a proper SCEP protocol message, switch back to handling \n\t\t   the main protocol */\n\t\tif( httpDataInfo.reqType != STREAM_HTTPREQTYPE_GET )\n\t\t\t{\n\t\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t\t\t   STREAM_HTTPREQTYPE_POST );\n\t\t\tlength = httpDataInfo.bytesAvail;\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* It's one of the bolted-on additions to the basic SCEP protocol,\n\t\t   handle it specially.  processAdditionalScepRequest() does its\n\t\t   own error reporting to the client (since this can depend on what\n\t\t   the add-on request wanted) so we don't send an error response if\n\t\t   we get an error status */\n\t\tstatus = processAdditionalScepRequest( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t   &httpUriInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tprocessedAdditionalRequest = TRUE;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( requestCount >= 5 )\n\t\t{\n\t\t/* The exact type of error response to send at this point is a bit\n\t\t   tricky, the least inappropriate one is probably \n\t\t   CRYPT_ERROR_DUPLICATE to indicate that too many duplicate \n\t\t   requests were sent, since to get here the client would have had \n\t\t   to send repeated identical bolt-on requests */\n\t\tsendCertErrorResponse( sessionInfoPtr, CRYPT_ERROR_DUPLICATE );\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Excessive number (more than %d) of SCEP requests \"\n\t\t\t\t  \"encountered\", requestCount ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processAdditionalScepRequest\" );\n\n\t/* Unfortunately we can't use readPkiDatagram() because of the weird \n\t   dual-purpose HTTP transport used in SCEP where the main protocol uses \n\t   POST + read response while the bolted-on portions use various GET\n\t   variations, so we have to duplicate portions of readPkiDatagram() \n\t   here.  See the readPkiDatagram() function for code comments \n\t   explaining the following operations */\n\tif( length < 4 || length >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, CRYPT_ERROR_BADDATA );\n\t\tretExt( CRYPT_ERROR_UNDERFLOW,\n\t\t\t\t( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKI message length %d\", length ) );\n\t\t}\n\tstatus = checkObjectEncodingLength( sessionInfoPtr->receiveBuffer, length, \n\t\t\t\t\t\t\t\t\t\t&length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, CRYPT_ERROR_BADDATA );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid PKI message encoding\" ) );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd = length;\n\tCFI_CHECK_UPDATE( \"checkObjectEncodingLength\" );\n\n\t/* Basic lint filter to check for approximately-OK requests before we\n\t   try applying enveloping operations to the data:\n\n\t\tSEQUENCE {\n\t\t\tOID signedData\t\t-- contentType\n\t\t\t[0] {\t\t\t\t-- content\n\t\t\t\tSEQUENCE {\n\t\t\t\t\tINTEGER 1\t-- version\n\t\t\t\t\t... */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treadSequence( &stream, NULL );\n\treadUniversal( &stream );\n\treadConstructed( &stream, NULL, 0 );\n\treadSequence( &stream, NULL );\n\tstatus = readInteger( &stream, NULL, 2, NULL );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsendCertErrorResponse( sessionInfoPtr, CRYPT_ERROR_BADDATA );\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid SCEP request header\" ) );\n\t\t}\n\n\t/* Process the initial message from the client */\n\tinitSCEPprotocolInfo( &protocolInfo );\n\tprotocolInfo.caSignOnlyKey = caSignOnlyKey;\n\tstatus = checkScepRequest( sessionInfoPtr, &protocolInfo, \n\t\t\t\t\t\t\t   &requestDataOK );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we got far enough into the request data to be able to send a \n\t\t   SCEP-level response, send that, otherwise just send an HTTP-level\n\t\t   response */\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tif( requestDataOK )\n\t\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\telse\n\t\t\tsendCertErrorResponse( sessionInfoPtr, status );\n\t\tdestroySCEPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkScepRequest\" );\n\n\t/* Issue a certificate from the request */\n\tstatus = issueCertFromRequest( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\tdestroySCEPprotocolInfo( &protocolInfo );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"issueCertFromRequest\" );\n\n\t/* Return the certificate to the client */\n\tstatus = createScepResponse( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writePkiDatagram( sessionInfoPtr, SCEP_CONTENT_TYPE, \n\t\t\t\t\t\t\t\t   SCEP_CONTENT_TYPE_LEN );\n\t\t}\n\telse\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tsendErrorResponse( sessionInfoPtr, &protocolInfo, status );\n\t\t}\n\tdestroySCEPprotocolInfo( &protocolInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"createScepResponse\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"processAdditionalScepRequest\", \n\t\t\t\t\t\t\t\t\t\"checkObjectEncodingLength\", \n\t\t\t\t\t\t\t\t\t\"checkScepRequest\", \"issueCertFromRequest\",\n\t\t\t\t\t\t\t\t\t\"createScepResponse\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSCEPserverProcessing( SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t}\n#endif /* USE_SCEP */\n"
  },
  {
    "path": "deps/cl345/session/scorebrd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Session Scoreboard\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"scorebrd.h\"\n  #include \"scorebrd_int.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/scorebrd.h\"\n  #include \"session/scorebrd_int.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef CONFIG_CONSERVE_MEMORY_EXTRA\n\n/* Sanity-check the scoreboard state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckScoreboard( const SCOREBOARD_INDEX_INFO *scoreboardIndexInfo )\n\t{\n\tassert( isReadPtr( scoreboardIndexInfo, \n\t\t\t\t\t   sizeof( SCOREBOARD_INDEX_INFO ) ) );\n\n\t/* Make sure that the general state is in order */\n\tif( scoreboardIndexInfo->lastEntry < 0 || \\\n\t\tscoreboardIndexInfo->lastEntry > SCOREBOARD_ENTRIES )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboard: Scoreboard last entry\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( scoreboardIndexInfo->uniqueID < 0 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboard: Scoreboard unique ID\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( scoreboardIndexInfo->data ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboard: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckScoreboardEntry( const SCOREBOARD_INDEX *scoreboardIndex )\n\t{\n\tvoid *dataPtr;\n\n\tassert( isReadPtr( scoreboardIndex, \n\t\t\t\t\t   sizeof( SCOREBOARD_INDEX ) ) );\n\n\t/* Check lookup information */\n\tif( scoreboardIndex->sessionIDlength <= 0 || \\\n\t\tscoreboardIndex->sessionIDlength > SCOREBOARD_KEY_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboardEntry: Lookup information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check scoreboard data */\n\tif( scoreboardIndex->dataLength < 1 || \\\n\t\tscoreboardIndex->dataLength > SCOREBOARD_DATA_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboardEntry: Data size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tdataPtr = DATAPTR_GET( scoreboardIndex->data );\n\tif( dataPtr == NULL || \\\n\t\tchecksumData( dataPtr, scoreboardIndex->dataLength ) != \\\n\t\t\t\t\t  scoreboardIndex->dataChecksum )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboardEntry: Data\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check miscellaneous information */\n\tif( ( scoreboardIndex->isServerData != TRUE && \\\n\t\t  scoreboardIndex->isServerData != FALSE ) || \\\n\t\tscoreboardIndex->uniqueID < 0 || \\\n\t\tscoreboardIndex->uniqueID > INT_MAX - 10 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckScoreboardEntry: Miscellaneous information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* !CONFIG_CONSERVE_MEMORY_EXTRA */\n\n/* Check whether a scoreboard entry is empty.  This checks a number of \n   values in order to deal with false positives caused by corruption of a\n   single value, if this check declares the value non-empty then it has to\n   pass a sanityCheckScoreboardEntry() check immediately afterwards */\n\nstatic BOOLEAN isEmptyEntry( const SCOREBOARD_INDEX *scoreboardEntryPtr )\n\t{\n\tassert( isReadPtr( scoreboardEntryPtr, sizeof( SCOREBOARD_INDEX ) ) );\n\t\n\tif( scoreboardEntryPtr->sessionCheckValue == 0 && \\\n\t\tscoreboardEntryPtr->fqdnCheckValue == 0 && \\\n\t\tscoreboardEntryPtr->sessionIDlength == 0 && \\\n\t\tscoreboardEntryPtr->dataLength == 0 && \\\n\t\tscoreboardEntryPtr->timeStamp <= MIN_TIME_VALUE )\n\t\treturn( TRUE );\n\t\n\treturn( FALSE );\n\t}\n\n/* Clear a scoreboard entry */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void clearScoreboardEntry( SCOREBOARD_INDEX *scoreboardEntryPtr )\n\t{\n\tvoid *savedDataPtr;\n\n\tassert( isWritePtr( scoreboardEntryPtr, \\\n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX ) ) );\n\n\tsavedDataPtr = DATAPTR_GET( scoreboardEntryPtr->data );\n\tREQUIRES_V( savedDataPtr != NULL );\n\tzeroise( savedDataPtr, SCOREBOARD_DATA_SIZE );\n\tmemset( scoreboardEntryPtr, 0, sizeof( SCOREBOARD_INDEX ) );\n\tDATAPTR_SET( scoreboardEntryPtr->data, savedDataPtr );\n\t\n\tENSURES_V( isEmptyEntry( scoreboardEntryPtr ) );\n\t}\n\n/* Add a scoreboard entry */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 8 ) ) \\\nstatic int addEntryData( INOUT SCOREBOARD_INDEX *scoreboardEntryPtr, \n\t\t\t\t\t\t IN_INT_Z const int keyCheckValue,\n\t\t\t\t\t\t IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\t IN_INT_Z const int altKeyCheckValue,\n\t\t\t\t\t\t IN_BUFFER_OPT( altKeyLength ) const void *altKey, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int altKeyLength, \n\t\t\t\t\t\t const SCOREBOARD_INFO *scoreboardInfo,\n\t\t\t\t\t\t const time_t currentTime )\n\t{\n\tvoid *dataPtr;\n\tint status;\n\n\tassert( isWritePtr( scoreboardEntryPtr, sizeof( SCOREBOARD_INDEX ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( ( altKey == NULL && altKeyLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( altKey, altKeyLength ) );\n\tassert( isReadPtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );\n\n\tREQUIRES( keyCheckValue >= 0 );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( altKey == NULL && altKeyLength == 0 && \\\n\t\t\t\taltKeyCheckValue == 0 ) || \\\n\t\t\t  ( altKey != NULL && \\\n\t\t\t\taltKeyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t\taltKeyLength < MAX_INTLENGTH_SHORT && \\\n\t\t\t\taltKeyCheckValue >= 0 ) );\n\tREQUIRES( currentTime > MIN_TIME_VALUE );\n\n\t/* Clear the existing data in the entry */\n\tclearScoreboardEntry( scoreboardEntryPtr );\n\tdataPtr = DATAPTR_GET( scoreboardEntryPtr->data );\n\tENSURES( dataPtr != NULL );\n\n\t/* Copy across the key and value (Amicitiae nostrae memoriam spero \n\t   sempiternam fore - Cicero) */\n\tscoreboardEntryPtr->sessionCheckValue = keyCheckValue;\n\thashData( scoreboardEntryPtr->sessionHash, HASH_DATA_SIZE, \n\t\t\t  key, keyLength );\n\tif( altKey != NULL )\n\t\t{\n\t\tscoreboardEntryPtr->fqdnCheckValue = altKeyCheckValue;\n\t\thashData( scoreboardEntryPtr->fqdnHash, HASH_DATA_SIZE, \n\t\t\t\t  altKey, altKeyLength );\n\t\t}\n\tstatus = attributeCopyParams( scoreboardEntryPtr->sessionID, \n\t\t\t\t\t\t\t\t  SCOREBOARD_KEY_SIZE, \n\t\t\t\t\t\t\t\t  &scoreboardEntryPtr->sessionIDlength,\n\t\t\t\t\t\t\t\t  key, keyLength );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = attributeCopyParams( dataPtr, SCOREBOARD_DATA_SIZE, \n\t\t\t\t\t\t\t\t  &scoreboardEntryPtr->dataLength,\n\t\t\t\t\t\t\t\t  scoreboardInfo->data, \n\t\t\t\t\t\t\t\t  scoreboardInfo->dataSize );\n\tENSURES( cryptStatusOK( status ) );\n\tscoreboardEntryPtr->dataChecksum = \\\n\t\t\t\tchecksumData( dataPtr, scoreboardEntryPtr->dataLength );\n\tscoreboardEntryPtr->metaData = scoreboardInfo->metaData;\n\tscoreboardEntryPtr->isServerData = ( altKey == NULL ) ? TRUE : FALSE;\n\tscoreboardEntryPtr->timeStamp = currentTime;\n\n\tENSURES( sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tScoreboard Management Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an entry, returning its position in the scoreboard.  This function \n   currently uses a straightforward linear search with entries clustered \n   towards the start of the scoreboard.  Although this may seem somewhat \n   suboptimal, since cryptlib isn't running as a high-performance web server \n   the scoreboard will rarely contain more than a handful of entries (if \n   any).  In any case a quick scan through a small number of integers is \n   probably still faster than the complex in-memory database lookup schemes \n   used by many servers, and is also required to handle things like \n   scoreboard LRU management */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nstatic int findEntry( INOUT SCOREBOARD_INDEX_INFO *scoreboardIndexInfo,\n\t\t\t\t\t  IN_ENUM( SCOREBOARD_KEY ) \\\n\t\t\t\t\t\t\tconst SCOREBOARD_KEY_TYPE keyType,\n\t\t\t\t\t  IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 2 ) const int keyLength, \n\t\t\t\t\t  const time_t currentTime, \n\t\t\t\t\t  OUT_INT_SHORT_Z int *position )\n\t{\n\tBYTE hashValue[ HASH_DATA_SIZE + 8 ];\n\tconst BOOLEAN keyIsSessionID = \\\n\t\t( keyType == SCOREBOARD_KEY_SESSIONID_CLI || \\\n\t\t  keyType == SCOREBOARD_KEY_SESSIONID_SVR ) ? TRUE : FALSE;\n\tconst BOOLEAN isServerMatch = \\\n\t\t( keyType == SCOREBOARD_KEY_SESSIONID_SVR ) ? TRUE : FALSE;\n\tBOOLEAN dataHashed = FALSE;\n\ttime_t oldestTime = currentTime;\n\tconst int checkValue = checksumData( key, keyLength );\n\tint nextFreeEntry = CRYPT_ERROR, lastUsedEntry = 0, oldestEntry = 0;\n\tint matchPosition = CRYPT_ERROR, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isWritePtr( position, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( keyType, SCOREBOARD_KEY ) );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT);\n\tREQUIRES( currentTime > MIN_TIME_VALUE );\n\n\t/* Clear return value */\n\t*position = CRYPT_ERROR;\n\n\t/* Scan the scoreboard expiring old entries, looking for a match \n\t   (indicated by matchPosition), and keeping a record of the oldest \n\t   entry (recorded by oldestEntry) in case we need to expire an entry to\n\t   make room for a new one */\n\tLOOP_MAX( i = 0, i < scoreboardIndexInfo->lastEntry, i++ )\n\t\t{\n\t\tSCOREBOARD_INDEX *scoreboardEntryPtr = &scoreboardIndexInfo->index[ i ];\n\n\t\t/* If this entry has expired, delete it */\n\t\tif( scoreboardEntryPtr->timeStamp + SCOREBOARD_TIMEOUT < currentTime )\n\t\t\tclearScoreboardEntry( scoreboardEntryPtr );\n\n\t\t/* Check for a free entry and the oldest non-free entry.  We could\n\t\t   perform an early-out once we find a free entry but this would\n\t\t   prevent any following expired entries from being deleted */\n\t\tif( isEmptyEntry( scoreboardEntryPtr ) )\n\t\t\t{\n\t\t\t/* We've found a free entry, remember it for future use if\n\t\t\t   required and continue */\n\t\t\tif( nextFreeEntry == CRYPT_ERROR )\n\t\t\t\tnextFreeEntry = i;\n\t\t\tcontinue;\n\t\t\t}\n\t\tREQUIRES( sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\t\tlastUsedEntry = i;\n\t\tif( scoreboardEntryPtr->timeStamp < oldestTime )\n\t\t\t{\n\t\t\t/* We've found an older entry than the current oldest entry,\n\t\t\t   remember it */\n\t\t\toldestTime = scoreboardEntryPtr->timeStamp;\n\t\t\toldestEntry = i;\n\t\t\t}\n\n\t\t/* If we've already found a match then we're just scanning for LRU\n\t\t   purposes and we don't need to go any further */\n\t\tif( matchPosition != CRYPT_ERROR )\n\t\t\tcontinue;\n\n\t\t/* Make sure that this entry is appropriate for the match type that\n\t\t   we're performing */\n\t\tif( scoreboardEntryPtr->isServerData != isServerMatch )\n\t\t\tcontinue;\n\n\t\t/* Perform a quick check using a checksum of the name to weed out\n\t\t   most entries */\n\t\tif( ( keyIsSessionID && \\\n\t\t\t  scoreboardEntryPtr->sessionCheckValue == checkValue ) || \\\n\t\t\t( !keyIsSessionID && \\\n\t\t\t  scoreboardEntryPtr->fqdnCheckValue == checkValue ) )\n\t\t\t{\n\t\t\tvoid *hashPtr = keyIsSessionID ? \\\n\t\t\t\t\t\t\t\tscoreboardEntryPtr->sessionHash : \\\n\t\t\t\t\t\t\t\tscoreboardEntryPtr->fqdnHash;\n\n\t\t\tif( !dataHashed )\n\t\t\t\t{\n\t\t\t\thashData( hashValue, HASH_DATA_SIZE, key, keyLength );\n\t\t\t\tdataHashed = TRUE;\n\t\t\t\t}\n\t\t\tif( !memcmp( hashPtr, hashValue, HASH_DATA_SIZE ) )\n\t\t\t\t{\n\t\t\t\t/* Remember the match position.  We can't immediately exit \n\t\t\t\t   at this point because we still need to look for the last \n\t\t\t\t   used entry and potentually shrink the scoreboard-used \n\t\t\t\t   size */\n\t\t\t\tmatchPosition = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES( i < FAILSAFE_ITERATIONS_MAX );\n\n\t/* If the total number of entries has shrunk due to old entries expiring,\n\t   reduce the overall scoreboard-used size */\n\tif( lastUsedEntry + 1 < scoreboardIndexInfo->lastEntry )\n\t\tscoreboardIndexInfo->lastEntry = lastUsedEntry + 1;\n\n\t/* If we've found a match, we're done */\n\tif( matchPosition >= 0 )\n\t\t{\n\t\t*position = matchPosition;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The entry wasn't found, return the location where we can add a new \n\t   entry */\n\tif( nextFreeEntry >= 0 )\n\t\t{\n\t\t/* We've found a freed-up existing position (which will be before \n\t\t   any remaining free entries), add the new entry there */\n\t\t*position = nextFreeEntry;\n\t\t}\n\telse\n\t\t{\n\t\t/* If there are still free positions in the scoreboard, use the next\n\t\t   available one */\n\t\tif( scoreboardIndexInfo->lastEntry < SCOREBOARD_ENTRIES )\n\t\t\t*position = scoreboardIndexInfo->lastEntry;\n\t\telse\n\t\t\t{\n\t\t\t/* There are no free positions, overwrite the oldest entry */\n\t\t\t*position = oldestEntry;\n\t\t\t}\n\t\t}\n\tENSURES( *position >= 0 && *position < SCOREBOARD_ENTRIES );\n\n\t/* Let the caller know that this is an indication of a free position \n\t   rather than a match */\n\treturn( OK_SPECIAL );\n\t}\n\n/* Add an entry to the scoreboard.  The strategy for updating entries can \n   get quite complicated.  In the following the server-side cases are \n   denoted with -S and the client-side cases with -C:\n\n\t  Case\t|\tkey\t\t|\taltKey\t|\tAction\n\t\t\t| (sessID)\t|  (FQDN)\t|\n\t--------+-----------+-----------+---------------------------------------\n\t  1-S\t|  no match\t|\tabsent\t| Add entry\n\t--------+-----------+-----------+---------------------------------------\n\t  2-S\t|\tmatch\t|\tabsent\t| Add-special (see below)\n\t--------+-----------+-----------+---------------------------------------\n\t  3-C\t|  no match\t|  no match\t| Add entry\n\t--------+-----------+-----------+---------------------------------------\n\t  4-C\t|  no match\t|\tmatch\t| Replace existing match.  This situation\n\t\t\t|\t\t\t|\t\t\t| has presumably occurred because we've\n\t\t\t|\t\t\t|\t\t\t| re-connected to a server with a full\n\t\t\t|\t\t\t|\t\t\t| handshake and were allocated a new \n\t\t\t|\t\t\t|\t\t\t| session ID.\n\t--------+-----------+-----------+---------------------------------------\n\t  5-C\t|\tmatch\t|  no match\t| Clear entry.  This situation shouldn't\n\t\t\t|\t\t\t|\t\t\t| occur, it means that we've somehow \n\t\t\t|\t\t\t|\t\t\t| acquired a session ID with a different\n\t\t\t|\t\t\t|\t\t\t| server.\n\t--------+-----------+-----------+---------------------------------------\n\t  6-C\t|\tmatch\t|\tmatch\t| Add-special (see below)\n\t--------+-----------+-----------+---------------------------------------\n\t  7-C\t|  match-1\t|  match-2\t| Match, but at different locations, \n\t\t\t|\t\t\t|\t\t\t| clear both entries (variant of case\n\t\t\t|\t\t\t|\t\t\t| 5-C).\n\n   Add-special is a conditional add, if the data value that we're trying to \n   add corresponds to the existing one (and the search keys matched as well)\n   then it's an update of an existing entry and we update its timestamp.  If\n   the data value doesn't match (but the search keys did) then something \n   funny is going on and we clear the existing entry.  If we simply ignore \n   the add attempt then it'll appear to the caller that we've added the new \n   value when in fact we've retained the existing one.  If on the other hand \n   we overwrite the old value with the new one then it'll allow an attacker \n   to replace existing scoreboard contents with attacker-controlled ones.\n\n   In theory not every case listed above can occur because information is \n   only added for new (non-resumed) sessions, so for example case 2-S \n   wouldn't occur because if there's already a match for the session ID then \n   it'd result in a resumed session and so the information wouldn't be added \n   a second time.  However there are situations in which these oddball cases \n   can occur, in general not for servers (even with two threads racing each \n   other for scoreboard access) because it'd require that the cryptlib \n   server allocate the same session ID twice, but it can occur for clients \n   if (case 5-C) two servers allocate us the same session ID or (case 4-C) \n   two threads simultaneously connect to the same server, with FQDNs the \n   same but session IDs different */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6, 7 ) ) \\\nstatic int addEntry( INOUT SCOREBOARD_INDEX_INFO *scoreboardIndexInfo, \n\t\t\t\t\t IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t IN_BUFFER_OPT( altKeyLength ) const void *altKey, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int altKeyLength, \n\t\t\t\t\t const SCOREBOARD_INFO *scoreboardInfo,\n\t\t\t\t\t OUT int *uniqueID )\n\t{\n\tSCOREBOARD_INDEX *scoreboardIndex;\n\tSCOREBOARD_INDEX *scoreboardEntryPtr = NULL;\n\tconst time_t currentTime = getTime();\n\tconst BOOLEAN isClient = ( altKey != NULL ) ? TRUE : FALSE;\n\tint checkValue, altCheckValue = 0, altPosition DUMMY_INIT;\n\tint position, altStatus = CRYPT_ERROR, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( ( altKey == NULL && altKeyLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( altKey, altKeyLength ) );\n\tassert( isReadPtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );\n\tassert( isWritePtr( uniqueID, sizeof( int ) ) );\n\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( ( altKey == NULL && altKeyLength == 0 ) || \\\n\t\t\t  ( altKey != NULL && \\\n\t\t\t\taltKeyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t\taltKeyLength < MAX_INTLENGTH_SHORT ) );\n\n\t/* Clear return value */\n\t*uniqueID = CRYPT_ERROR;\n\n\tstatus = checkValue = checksumData( key, keyLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t\n\t/* If there's something wrong with the time then we can't perform (time-\n\t   based) scoreboard management */\n\tif( currentTime <= MIN_TIME_VALUE )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Try and find this entry in the scoreboard */\n\tstatus = findEntry( scoreboardIndexInfo, isClient ? \\\n\t\t\t\t\t\t\tSCOREBOARD_KEY_SESSIONID_CLI : \\\n\t\t\t\t\t\t\tSCOREBOARD_KEY_SESSIONID_SVR, \n\t\t\t\t\t\tkey, keyLength, currentTime, &position );\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\treturn( status );\n\tENSURES( position >= 0 && position < SCOREBOARD_ENTRIES );\n\tif( altKey != NULL )\n\t\t{\n\t\taltCheckValue = checksumData( altKey, altKeyLength );\n\t\tif( cryptStatusError( altCheckValue ) )\n\t\t\treturn( altCheckValue );\n\t\taltStatus = findEntry( scoreboardIndexInfo, SCOREBOARD_KEY_FQDN, \n\t\t\t\t\t\t\t   altKey, altKeyLength, currentTime, \n\t\t\t\t\t\t\t   &altPosition );\n\t\tif( cryptStatusError( altStatus ) && altStatus != OK_SPECIAL )\n\t\t\treturn( altStatus );\n\t\tENSURES( altPosition >= 0 && \\\n\t\t\t\t altPosition < SCOREBOARD_ENTRIES );\n\t\t}\n\tENSURES( cryptStatusOK( status ) || status == OK_SPECIAL );\n\tENSURES( altKey == NULL || \\\n\t\t\t cryptStatusOK( altStatus ) || altStatus == OK_SPECIAL );\n\tscoreboardIndex = scoreboardIndexInfo->index;\n\n\t/* We've done the match-checking, now we have to act on the results.  \n\t   The different result-value settings and corresponding actions are:\n\n\t\t  Case\t|\t\tsessID\t\t|\t\tFQDN\t\t| Action\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t1\t|  s = MT, pos = x\t|\t\t!altK\t\t| Add at x\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t2\t|  s = OK, pos = x\t|\t\t!altK\t\t| Add-special at x\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t3\t|  s = MT, pos = x\t| aS = MT, aPos = x\t| Add at x\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t4\t|  s = MT, pos = x\t| aS = OK, aPos = y\t| Replace at y\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t5\t|  s = OK, pos = x\t| aS = MT, aPos = y\t| Clear at x\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t6\t|  s = OK, pos = x\t| aS = OK, aPos = x\t| Add-special at x\n\t\t--------+-------------------+-------------------+-----------------\n\t\t\t7\t|  s = OK, pos = x\t| aS = OK, aPos = y\t| Clear at x and y */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tvoid *dataPtr;\n\n\t\t/* We matched on the main key (session ID), handle cases 2-S, 5-C, \n\t\t   6-C and 7-C */\n\t\tif( altKey != NULL && position != altPosition )\n\t\t\t{\n\t\t\t/* Cases 5-C + 7-C, clear */\n\t\t\tclearScoreboardEntry( &scoreboardIndex[ position ] );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\n\t\t/* Cases 2-S + 6-C, add-special */\n\t\tENSURES( altKey == NULL || ( cryptStatusOK( altStatus ) && \\\n\t\t\t\t\t\t\t\t\t position == altPosition ) );\n\t\tscoreboardEntryPtr = &scoreboardIndex[ position ];\n\t\tREQUIRES( sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\t\tdataPtr = DATAPTR_GET( scoreboardEntryPtr->data );\n\t\tREQUIRES( dataPtr != NULL );\n\t\tif( scoreboardEntryPtr->dataLength != scoreboardInfo->dataSize || \\\n\t\t\tmemcmp( dataPtr, scoreboardInfo->data, scoreboardInfo->dataSize ) )\n\t\t\t{\n\t\t\t/* The search keys match but the data doesn't, something funny \n\t\t\t   is going on */\n\t\t\tclearScoreboardEntry( &scoreboardIndex[ position ] );\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\t\tscoreboardEntryPtr->timeStamp = currentTime;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tREQUIRES( status == OK_SPECIAL );\n\n\t/* We didn't match on the main key (session ID), check for a match on \n\t   the alt.key (FQDN) */\n\tif( cryptStatusOK( altStatus ) )\n\t\t{\n\t\t/* Case 4-C, add at location 'altPosition' */\n\t\tENSURES( position != altPosition );\n\t\tscoreboardEntryPtr = &scoreboardIndex[ altPosition ];\n\t\t}\n\telse\n\t\t{\n\t\t/* Cases 1-S + 3-C, add at location 'position' */\n\t\tENSURES( altKey == NULL || \\\n\t\t\t\t ( altStatus == OK_SPECIAL && position == altPosition ) )\n\t\tscoreboardEntryPtr = &scoreboardIndex[ position ];\n\t\t}\n\n\t/* It's either an empty entry being added or an existing entry being \n\t   updated */\n\tREQUIRES( isEmptyEntry( scoreboardEntryPtr ) || \\\n\t\t\t  sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\n\t/* Add the data to the new scoreboard entry position */\n\tstatus = addEntryData( scoreboardEntryPtr, checkValue, key, keyLength, \n\t\t\t\t\t\t   altCheckValue, altKey, altKeyLength, \n\t\t\t\t\t\t   scoreboardInfo, currentTime );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tclearScoreboardEntry( scoreboardEntryPtr );\n\t\treturn( status );\n\t\t}\n\tif( scoreboardIndexInfo->uniqueID >= INT_MAX - 100 )\n\t\t{\n\t\t/* If we're about to wrap, reset the uniqueID value to the initial \n\t\t   value.  This can happen on 16-bit systems */\n\t\tscoreboardIndexInfo->uniqueID = 0;\n\t\t}\n\t*uniqueID = scoreboardEntryPtr->uniqueID = \\\n\t\t\t\tscoreboardIndexInfo->uniqueID++;\n\n\t/* If we've used a new entry, update the position-used index */\n\tif( position >= scoreboardIndexInfo->lastEntry )\n\t\tscoreboardIndexInfo->lastEntry = position + 1;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Look up data in the scoreboard */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5, 6 ) ) \\\nstatic int lookupScoreboard( INOUT SCOREBOARD_INDEX_INFO *scoreboardIndexInfo,\n\t\t\t\t\t\t\t IN_ENUM( SCOREBOARD_KEY ) \\\n\t\t\t\t\t\t\t\tconst SCOREBOARD_KEY_TYPE keyType,\n\t\t\t\t\t\t\t IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\t     OUT SCOREBOARD_INFO *scoreboardInfo,\n\t\t\t\t\t\t\t OUT_INT_Z int *uniqueID )\n\t{\n\tSCOREBOARD_INDEX *scoreboardEntryPtr;\n\tconst time_t currentTime = getTime();\n\tint position, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isWritePtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );\n\tassert( isWritePtr( uniqueID, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( keyType, SCOREBOARD_KEY ) );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\n\t/* Clear return values */\n\tmemset( scoreboardInfo, 0, sizeof( SCOREBOARD_INFO ) );\n\t*uniqueID = CRYPT_ERROR;\n\n\t/* If there's something wrong with the time then we can't perform (time-\n\t   based) scoreboard management */\n\tif( currentTime <= MIN_TIME_VALUE )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Try and find this entry in the scoreboard */\n\tstatus = findEntry( scoreboardIndexInfo, keyType, key, keyLength, \n\t\t\t\t\t\tcurrentTime, &position );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* An OK_SPECIAL status means that the search found an unused entry \n\t\t   position but not a matching entry (this is used by addEntry()), \n\t\t   anything else is an error */\n\t\treturn( ( status == OK_SPECIAL ) ? CRYPT_ERROR_NOTFOUND : status );\n\t\t}\n\tENSURES( position >= 0 && position < SCOREBOARD_ENTRIES );\n\tscoreboardEntryPtr = &scoreboardIndexInfo->index[ position ];\n\tREQUIRES( sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\n\t/* We've found a match, return a pointer to the data (which avoids \n\t   copying it out of secure memory) and the unique ID for it */\n\tscoreboardInfo->key = scoreboardEntryPtr->sessionID;\n\tscoreboardInfo->keySize = scoreboardEntryPtr->sessionIDlength;\n\tscoreboardInfo->data = DATAPTR_GET( scoreboardEntryPtr->data );\n\tENSURES( scoreboardInfo->data != NULL );\n\tscoreboardInfo->dataSize = scoreboardEntryPtr->dataLength;\n\tscoreboardInfo->metaData = scoreboardEntryPtr->metaData;\n\t*uniqueID = scoreboardEntryPtr->uniqueID;\n\n\t/* Update the entry's last-access date */\n\tscoreboardEntryPtr->timeStamp = currentTime;\n\n\tENSURES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tScoreboard Access Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add and delete entries to/from the scoreboard.  These are just wrappers\n   for the local scoreboard-access function, for use by external code */\n\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint lookupScoreboardEntry( INOUT TYPECAST( SCOREBOARD_INDEX_INFO * ) \\\n\t\t\t\t\t\t\t\tvoid *scoreboardIndexInfoPtr,\n\t\t\t\t\t\t   IN_ENUM( SCOREBOARD_KEY ) \\\n\t\t\t\t\t\t\t\tconst SCOREBOARD_KEY_TYPE keyType,\n\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 2 ) const int keyLength, \n\t\t\t\t\t\t   OUT SCOREBOARD_INFO *scoreboardInfo )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tint uniqueID, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isWritePtr( scoreboardInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INFO ) ) );\n\n\tREQUIRES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\tREQUIRES( isEnumRange( keyType, SCOREBOARD_KEY ) );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return values */\n\tmemset( scoreboardInfo, 0, sizeof( SCOREBOARD_INFO ) );\n\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = lookupScoreboard( scoreboardIndexInfo, keyType, key, keyLength, \n\t\t\t\t\t\t\t   scoreboardInfo, &uniqueID );\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\treturn( cryptStatusError( status ) ? status : uniqueID );\n\t}\n\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint addScoreboardEntry( INOUT void *scoreboardIndexInfoPtr,\n\t\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\tconst SCOREBOARD_INFO *scoreboardInfo )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tint uniqueID, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );\n\n\tREQUIRES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\n\t/* Add the entry to the scoreboard */\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = addEntry( scoreboardIndexInfo, key, keyLength, NULL, 0,\n\t\t\t\t\t   scoreboardInfo, &uniqueID );\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\n\tENSURES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\n\treturn( cryptStatusError( status ) ? status : uniqueID );\n\t}\n\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nint addScoreboardEntryEx( INOUT void *scoreboardIndexInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\t  IN_BUFFER( keyLength ) const void *altKey, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 2 ) const int altKeyLength, \n\t\t\t\t\t\t  const SCOREBOARD_INFO *scoreboardInfo )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tint uniqueID, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\tassert( isReadPtrDynamic( key, keyLength ) );\n\tassert( isReadPtrDynamic( altKey, altKeyLength ) );\n\tassert( isReadPtr( scoreboardInfo, sizeof( SCOREBOARD_INFO ) ) );\n\n\tREQUIRES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\tREQUIRES( keyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  keyLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( altKeyLength >= SCOREBOARD_KEY_MIN && \\\n\t\t\t  altKeyLength < MAX_INTLENGTH_SHORT );\n\n\t/* Add the entry to the scoreboard */\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = addEntry( scoreboardIndexInfo, key, keyLength, altKey, \n\t\t\t\t\t   altKeyLength, scoreboardInfo, &uniqueID );\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\n\tENSURES( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\n\treturn( cryptStatusError( status ) ? status : uniqueID );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteScoreboardEntry( INOUT TYPECAST( SCOREBOARD_INDEX_INFO * ) \\\n\t\t\t\t\t\t\t\tvoid *scoreboardIndexInfoPtr, \n\t\t\t\t\t\t\tIN_INT_Z const int uniqueID )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tint lastUsedEntry = -1, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\t\n\tREQUIRES_V( sanityCheckScoreboard( scoreboardIndexInfo ) );\n\tREQUIRES_V( isIntegerRange( uniqueID ) );\n\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tif( cryptStatusError( status ) )\n\t\treturn;\n\n\t/* Search the scoreboard for the entry with the given ID */\n\tLOOP_MAX( i = 0, i < scoreboardIndexInfo->lastEntry, i++ )\n\t\t{\n\t\tSCOREBOARD_INDEX *scoreboardEntryPtr = &scoreboardIndexInfo->index[ i ];\n\n\t\t/* If it's an empty entry (due to it having expired or being \n\t\t   deleted), skip it and continue */\n\t\tif( isEmptyEntry( scoreboardEntryPtr ) )\n\t\t\tcontinue;\n\n\t\tREQUIRES_V( sanityCheckScoreboardEntry( scoreboardEntryPtr ) );\n\n\t\t/* If we've found the entry that we're after, clear it and exit */\n\t\tif( scoreboardEntryPtr->uniqueID == uniqueID )\n\t\t\t{\n\t\t\tclearScoreboardEntry( scoreboardEntryPtr );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Remember how far we got */\n\t\tlastUsedEntry = i;\n\t\t}\n\tENSURES_KRNLMUTEX_V( LOOP_BOUND_OK, MUTEX_SCOREBOARD );\n\n\t/* Since we may have deleted entries at the end of the scoreboard, we \n\t   can reduce the lastEntry value to the highest remaining entry */\n\tscoreboardIndexInfo->lastEntry = lastUsedEntry + 1;\n\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tScoreboard Init/Shutdown\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a self-test of the scoreboard functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN selfTest( INOUT SCOREBOARD_INDEX_INFO *scoreboardIndexInfo )\n\t{\n\tSCOREBOARD_INFO scoreboardInfo;\n\tint uniqueID1, uniqueID2, foundUniqueID, status;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\n\t/* Add two entries to the scoreboard */\n\tmemset( &scoreboardInfo, 0, sizeof( SCOREBOARD_INFO ) );\n\tscoreboardInfo.data = \"test value 1\";\n\tscoreboardInfo.dataSize = 12;\n\tstatus = uniqueID1 = \\\n\t\taddScoreboardEntry( scoreboardIndexInfo, \"test key 1\", 10,\n\t\t\t\t\t\t\t&scoreboardInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tscoreboardInfo.data = \"test value 2\";\n\tscoreboardInfo.dataSize = 12;\n\tstatus = uniqueID2 = \\\n\t\taddScoreboardEntry( scoreboardIndexInfo, \"test key 2\", 10,\n\t\t\t\t\t\t\t&scoreboardInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Read them back and delete them */\n\tstatus = foundUniqueID = \\\n\t\tlookupScoreboardEntry( scoreboardIndexInfo, SCOREBOARD_KEY_SESSIONID_SVR, \n\t\t\t\t\t\t\t   \"test key 1\", 10, &scoreboardInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( foundUniqueID != uniqueID1 || \\\n\t\tscoreboardInfo.keySize != 10 || \\\n\t\tmemcmp( scoreboardInfo.key, \"test key 1\", 10 ) || \\\n\t\tscoreboardInfo.dataSize != 12 || \\\n\t\tmemcmp( scoreboardInfo.data, \"test value 1\", 12 ) )\n\t\t{\n\t\treturn( FALSE );\n\t\t}\n\tdeleteScoreboardEntry( scoreboardIndexInfo, uniqueID1 );\n\tfoundUniqueID = lookupScoreboardEntry( scoreboardIndexInfo, \n\t\t\t\t\t\t\tSCOREBOARD_KEY_SESSIONID_SVR, \"test key 1\", 10,\n\t\t\t\t\t\t\t&scoreboardInfo );\n\tif( foundUniqueID != CRYPT_ERROR_NOTFOUND )\n\t\treturn( FALSE );\n\tdeleteScoreboardEntry( scoreboardIndexInfo, uniqueID2 );\n\tif( scoreboardIndexInfo->lastEntry != 0 || \\\n\t\tscoreboardIndexInfo->uniqueID != 2 )\n\t\treturn( FALSE );\n\n#ifndef NDEBUG\n\t{\n\tchar dataString[ 16 + 8 ];\n\tint i, LOOP_ITERATOR;\n\n\tmemset( &scoreboardInfo, 0, sizeof( SCOREBOARD_INFO ) );\n\tscoreboardInfo.data = dataString;\n\tscoreboardInfo.dataSize = 4;\n\tLOOP_LARGE( i = 0, i < SCOREBOARD_ENTRIES + 10, i++ )\n\t\t{\n\t\tsprintf_s( dataString, 16, \"%04X\", i );\n\n\t\tstatus = \\\n\t\t\taddScoreboardEntry( scoreboardIndexInfo, dataString, 4,\n\t\t\t\t\t\t\t\t&scoreboardInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\t}\n#endif /* NDEBUG */\n\n\treturn( TRUE );\n\t}\n\n/* Initialise and shut down the scoreboard */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initScoreboard( INOUT TYPECAST( SCOREBOARD_INDEX_INFO * ) \\\n\t\t\t\t\t\tvoid *scoreboardIndexInfoPtr )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tSCOREBOARD_DATA *scoreboardData;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( scoreboardIndexInfo, \n\t\t\t\t\t\tsizeof( SCOREBOARD_INDEX_INFO ) ) );\n\t\n\t/* Allocate memory for the scoreboard, which we can do before acquiring \n\t   the scoreboard mutex */\n\tstatus = krnlMemalloc( ( void ** ) &scoreboardData, \\\n\t\t\t\t\t\t   SCOREBOARD_ENTRIES * sizeof( SCOREBOARD_DATA ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Couldn't allocate %d bytes secure memory for \"\n\t\t\t\t\t \"scoreboard data\",\n\t\t\t\t\t SCOREBOARD_ENTRIES * sizeof( SCOREBOARD_DATA ) ));\n\t\treturn( status );\n\t\t}\n\tmemset( scoreboardData, 0, \\\n\t\t\tSCOREBOARD_ENTRIES * sizeof( SCOREBOARD_DATA ) );\n\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = krnlMemfree( ( void ** ) &scoreboardData );\n\t\treturn( status );\n\t\t}\n\n\t/* Initialise the scoreboard */\n\tmemset( scoreboardIndexInfo, 0, sizeof( SCOREBOARD_INDEX_INFO ) );\n\tLOOP_MAX( i = 0, i < SCOREBOARD_ENTRIES, i++ )\n\t\t{\n\t\tDATAPTR_SET( scoreboardIndexInfo->index[ i ].data, \n\t\t\t\t\t &scoreboardData[ i ] );\n\t\t}\n\tENSURES_KRNLMUTEX( LOOP_BOUND_OK, MUTEX_SCOREBOARD );\n\tDATAPTR_SET( scoreboardIndexInfo->data, scoreboardData );\n\n\t/* Make sure that everything's working as intended */\n#ifndef CONFIG_FUZZ\n\tif( !selfTest( scoreboardIndexInfo ) )\n\t\t{\n\t\tstatus = krnlMemfree( ( void ** ) &scoreboardData );\n\t\tENSURES_KRNLMUTEX( cryptStatusOK( status ), MUTEX_SCOREBOARD );\n\t\tmemset( scoreboardIndexInfo, 0, sizeof( SCOREBOARD_INDEX_INFO ) );\n\t\tDEBUG_DIAG(( \"Couldn't initialise scoreboard\" ));\n\n\t\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\t\tretIntError();\n\t\t}\n#endif /* !CONFIG_FUZZ */\n\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid endScoreboard( INOUT TYPECAST( SCOREBOARD_INDEX_INFO * ) \\\n\t\t\t\t\t\tvoid *scoreboardIndexInfoPtr )\n\t{\n\tSCOREBOARD_INDEX_INFO *scoreboardIndexInfo = scoreboardIndexInfoPtr;\n\tSCOREBOARD_DATA *scoreboardData;\n\tint status;\n\n\t/* Shut down the scoreboard.  We acquire the mutex while we're doing \n\t   this to ensure that any threads still using it have exited before we \n\t   destroy it.  Exactly what to do if we can't acquire the mutex is a \n\t   bit complicated because failing to acquire the mutex is a special-\n\t   case exception condition so it's not even possible to plan for this \n\t   since it's uncertain under which conditions (if ever) it would \n\t   occur.  For now we play it by the book and don't do anything if we \n\t   can't acquire the mutex, which is at least consistent */\n\tstatus = krnlEnterMutex( MUTEX_SCOREBOARD );\n\tENSURES_V( cryptStatusOK( status ) );\t/* See comment above */\n\n\t/* Clear and free the scoreboard */\n\tscoreboardData = DATAPTR_GET( scoreboardIndexInfo->data );\n\tENSURES_KRNLMUTEX_V( scoreboardData != NULL, MUTEX_SCOREBOARD );\n\tstatus = krnlMemfree( ( void ** ) &scoreboardData );\n\tENSURES_KRNLMUTEX_V( cryptStatusOK( status ), MUTEX_SCOREBOARD );\n\tzeroise( scoreboardIndexInfo, sizeof( SCOREBOARD_INDEX_INFO ) );\n\n\tkrnlExitMutex( MUTEX_SCOREBOARD );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/scorebrd.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Session Scoreboard Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SCOREBRD_DEFINED\n\n#define _SCOREBRD_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tScoreboard Types and Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The search key to use for a scoreboard lookup.  We distinguish between\n   client and server sessionIDs in order to provide a logically distinct \n   namespace for client and server sessions */\n\ntypedef enum {\n\tSCOREBOARD_KEY_NONE,\n\tSCOREBOARD_KEY_SESSIONID_CLI,\t/* Lookup by client session ID */\n\tSCOREBOARD_KEY_SESSIONID_SVR,\t/* Lookup by server session ID */\n\tSCOREBOARD_KEY_FQDN,\t\t\t/* Lookup by server FQDN */\n\tSCOREBOARD_KEY_LAST\n\t} SCOREBOARD_KEY_TYPE;\n\n/* Information added to/read from an entry in the scoreboard */\n\ntypedef struct {\n\t/* Scoreboard search key information */\n\tBUFFER_OPT_FIXED( keySize ) \\\n\tconst void *key;\n\tint keySize;\n\n\t/* The data stored with the scoreboard entry */\n\tBUFFER_OPT_FIXED( dataSize ) \\\n\tconst void *data;\n\tint dataSize;\n\tint metaData;\n\t} SCOREBOARD_INFO;\n\n/* Storage for the scoreboard state.  When passed to scoreboard functions\n   it's declared as a void * because to the caller it's an opaque memory \n   block while to the scoreboard routines it's structured storage */\n\ntypedef BYTE SCOREBOARD_STATE[ 64 ];\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tScoreboard Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Session scoreboard management functions */\n\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nint lookupScoreboardEntry( INOUT void *scoreboardIndexInfoPtr,\n\t\t\t\t\t\t   IN_ENUM( SCOREBOARD_KEY ) \\\n\t\t\t\t\t\t\t\tconst SCOREBOARD_KEY_TYPE keyType,\n\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 2 ) const int keyLength, \n\t\t\t\t\t\t   OUT SCOREBOARD_INFO *scoreboardInfo );\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint addScoreboardEntry( INOUT void *scoreboardIndexInfoPtr,\n\t\t\t\t\t\tIN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\tconst SCOREBOARD_INFO *scoreboardInfo );\nCHECK_RETVAL_RANGE( 0, MAX_INTLENGTH ) STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nint addScoreboardEntryEx( INOUT void *scoreboardIndexInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( keyLength ) const void *key, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 8 ) const int keyLength, \n\t\t\t\t\t\t  IN_BUFFER( keyLength ) const void *altKey, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 2 ) const int altKeyLength, \n\t\t\t\t\t\t  const SCOREBOARD_INFO *scoreboardInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteScoreboardEntry( INOUT void *scoreboardIndexInfoPtr, \n\t\t\t\t\t\t\tIN_INT_Z const int uniqueID );\n\n#ifdef USE_SSL\n  CHECK_RETVAL_PTR_NONNULL \\\n  void *getScoreboardInfoStorage( void );\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int initScoreboard( INOUT void *scoreboardIndexInfoPtr );\n  STDC_NONNULL_ARG( ( 1 ) ) \\\n  void endScoreboard( INOUT void *scoreboardIndexInfoPtr );\n#else\n  #define getScoreboardInfoStorage()\t\t\tNULL\n  #define initScoreboard( scoreboardInfo )\t\tCRYPT_OK\n  #define endScoreboard( scoreboardInfo )\n#endif /* USE_SSL */\n#endif /* _SCOREBRD_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/scorebrd_int.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t Internal Scoreboard Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SCOREBRD_INT_DEFINED\n\n#define _SCOREBRD_INT_DEFINED\n\n#if defined( INC_ALL )\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tConstants\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The number of entries in the SSL session cache, the one specific instance\n   of the scoreboard that's used at the moment */\n\n#if defined( CONFIG_CONSERVE_MEMORY )\n  #define SCOREBOARD_ENTRIES\t\t8\n#else\n  #define SCOREBOARD_ENTRIES\t\t64\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n/* The minimum and maximum sizes of any identifiers and data values to be \n   stored in the scoreboard.  Since the scoreboard is currently only used \n   for SSL session resumption, these are MIN_SESSIONID_SIZE = 4 bytes, \n   MAX_SESSIONID_SIZE = 32 bytes, and SSL_SECRET_SIZE = 48 bytes */\n\n#define SCOREBOARD_KEY_MIN\t\t\tMIN_SESSIONID_SIZE\n#define SCOREBOARD_KEY_SIZE\t\t\tMAX_SESSIONID_SIZE\n#define SCOREBOARD_DATA_SIZE\t\tSSL_SECRET_SIZE\n\n/* The maximum amount of time that an entry is retained in the scoreboard,\n   one hour */\n\n#define SCOREBOARD_TIMEOUT\t\t\t3600\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tData Types and Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* An individual scoreboard entry containing index information, \n   SCOREBOARD_INDEX, and its corresponding data, SCOREBOARD_DATA.  These \n   are stored in separate memory blocks because one is allocated in secure \n   nonpageable storage and the other isn't, with scoreboardIndex[] \n   containing pointers into corresponding entries in scoreboardData[] */\n\ntypedef BYTE SCOREBOARD_DATA[ SCOREBOARD_DATA_SIZE ];\n\ntypedef struct {\n\t/* Identification information: The checksum and hash of the session ID \n\t   (to locate an entry based on the sessionID sent by the client) and \n\t   checksum and hash of the FQDN (to locate an entry based on the server\n\t   FQDN) */\n\tint sessionCheckValue;\n\tBUFFER_FIXED( HASH_DATA_SIZE ) \\\n\tBYTE sessionHash[ HASH_DATA_SIZE + 4 ];\n\tint fqdnCheckValue;\n\tBUFFER_FIXED( HASH_DATA_SIZE ) \\\n\tBYTE fqdnHash[ HASH_DATA_SIZE + 4 ];\n\n\t/* Since a lookup may have to return a session ID value if we're going\n\t   from an FQDN to a session ID, we have to store the full session ID \n\t   value alongside its checksum and hash */\n\tBUFFER( SCOREBOARD_KEY_SIZE, sessionIDlength ) \\\n\tBYTE sessionID[ SCOREBOARD_KEY_SIZE + 4 ];\n\tint sessionIDlength;\n\n\t/* The scoreboard data, just a pointer into the secure SCOREBOARD_DATA \n\t   memory, along with a word of metadata that can be used to convey\n\t   additional information about it, and a checksum for the \n\t   SCOREBOARD_DATA.  The dataLength variable records how much data is \n\t   actually present out of the SCOREBOARD_DATA_SIZE bytes that are \n\t   available for use */\n\tDATAPTR data;\t\t\t/* Pointer to SCOREBOARD_DATA entry */\n\tint dataLength, dataChecksum;\n\tint metaData;\n\n\t/* Miscellaneous information.  We record whether an entry corresponds to\n\t   server or client data in order to provide logically separate \n\t   namespaces for client and server */\n\ttime_t timeStamp;\t\t/* Time entry was added to the scoreboard */\n\tBOOLEAN isServerData;\t/* Whether this is client or server value */\n\tint uniqueID;\t\t\t/* Unique ID for this entry */\n\t} SCOREBOARD_INDEX;\n\n/* Overall scoreboard information.  Note that the SCOREBOARD_STATE size \n   define in scorebrd.h will need to be updated if this structure is \n   changed */\n\ntypedef struct {\n\t/* The last used entry in the scoreboard, and a unique ID for each \n\t   scoreboard entry.  This is incremented for each index entry added,\n\t   so that even if an entry is deleted and then another one with the \n\t   same index value added, the uniqueID for the two will be different */\n\tint lastEntry;\t\t\t\t/* Last used entry in scoreboard */\n\tint uniqueID;\t\t\t\t/* Unique ID for scoreboard entry */\n\n\t/* Scoreboard index and data storage */\n\tSCOREBOARD_INDEX index[ SCOREBOARD_ENTRIES ];\n\tDATAPTR data;\t\t\t\t/* Pointer to SCOREBOARD_DATA[] array */\n\t} SCOREBOARD_INDEX_INFO;\n\n#endif /* _SCOREBRD_INT_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/sess_attr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Session Attribute Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#include \"crypt.h\"\n#ifdef INC_ALL\n  #include \"session.h\"\n#else\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exit after setting extended error information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitError( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus,\n\t\t\t\t\t  IN_ENUM( CRYPT_ERRTYPE ) const CRYPT_ERRTYPE_TYPE errorType, \n\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\tREQUIRES( isEnumRange( errorType, CRYPT_ERRTYPE ) );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsetErrorInfo( sessionInfoPtr, errorLocus, errorType );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorInited( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_PRESENT,\n\t\t\t\t\t   CRYPT_ERROR_INITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotInited( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT,\n\t\t\t\t\t   CRYPT_ERROR_NOTINITED ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int exitErrorNotFound( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE errorLocus )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isAttribute( errorLocus ) || \\\n\t\t\t  isInternalAttribute( errorLocus ) );\n\n\treturn( exitError( sessionInfoPtr, errorLocus, CRYPT_ERRTYPE_ATTR_ABSENT,\n\t\t\t\t\t   CRYPT_ERROR_NOTFOUND ) );\n\t}\n\n/* Add the contents of an encoded URL to a session.  This requires parsing\n   the individual session attribute components out of the URL and then \n   adding each one in turn */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int addUrl( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   IN_BUFFER( urlLength ) const void *url,\n\t\t\t\t   IN_LENGTH_DNS const int urlLength )\n\t{\n\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\tURL_INFO urlInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( url, urlLength ) );\n\t\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( urlLength > 0 && urlLength < MAX_URL_SIZE );\n\tREQUIRES( protocolInfo != NULL );\n\n\t/* If there's already a network socket specified then we can't set a \n\t   server name as well */\n\tif( sessionInfoPtr->networkSocket != CRYPT_ERROR )\n\t\t{\n\t\treturn( exitErrorInited( sessionInfoPtr, \n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_NETWORKSOCKET ) );\n\t\t}\n\n\t/* Parse the server name.  The PKI protocols all use HTTP as their \n\t   substrate so if it's not SSH or SSL/TLS we require HTTP */\n\tstatus = sNetParseURL( &urlInfo, url, urlLength,\n\t\t\t\t\t\t   ( sessionInfoPtr->type == CRYPT_SESSION_SSH ) ? \\\n\t\t\t\t\t\t\t\tURL_TYPE_SSH : \\\n\t\t\t\t\t\t   ( sessionInfoPtr->type == CRYPT_SESSION_SSL ) ? \\\n\t\t\t\t\t\t\t\tURL_TYPE_HTTPS : URL_TYPE_HTTP );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( exitError( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ARGERROR_STR1 ) );\n\t\t}\n\n\t/* We can only use autodetection with PKI services */\n\tif( urlInfo.hostLen == 12 && \\\n\t\t!strCompare( urlInfo.host, \"[Autodetect]\", urlInfo.hostLen ) && \\\n\t\t!protocolInfo->isReqResp )\n\t\t{\n\t\treturn( exitError( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ARGERROR_STR1 ) );\n\t\t}\n\n\t/* Remember the server name */\n\tif( urlInfo.hostLen + urlInfo.locationLen >= MAX_URL_SIZE )\n\t\t{\n\t\t/* This should never happen since the overall URL size has to be \n\t\t   less than MAX_URL_SIZE */\n\t\tassert( INTERNAL_ERROR );\n\t\treturn( exitError( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ARGERROR_STR1 ) );\n\t\t}\n\tif( ( protocolInfo->flags & SESSION_FLAG_ISHTTPTRANSPORT ) && \\\n\t\turlInfo.locationLen > 0 )\n\t\t{\n\t\tchar urlBuffer[ MAX_URL_SIZE + 8 ];\n\n\t\t/* We only remember the location if the session uses HTTP transport.  \n\t\t   This is to deal with situations where the caller specifies a URL\n\t\t   like https://www.server.com/index.html for an SSL session, which \n\t\t   should be treated as valid even though it's not really a pure \n\t\t   FQDN */\n\t\tREQUIRES( boundsCheck( urlInfo.hostLen, urlInfo.locationLen,\n\t\t\t\t\t\t\t   MAX_URL_SIZE ) );\n\t\tmemcpy( urlBuffer, urlInfo.host, urlInfo.hostLen );\n\t\tmemcpy( urlBuffer + urlInfo.hostLen, urlInfo.location, \n\t\t\t\turlInfo.locationLen );\n\t\tstatus = addSessionInfoS( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t\t\t  urlBuffer, \n\t\t\t\t\t\t\t\t  urlInfo.hostLen + urlInfo.locationLen );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = addSessionInfoS( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t\t\t  urlInfo.host, urlInfo.hostLen );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( exitError( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ARGERROR_STR1 ) );\n\t\t}\n\n\t/* If there's a port or user name specified in the URL, remember them.  \n\t   We have to add the user name after we add any other attributes \n\t   because it's paired with a password, so adding the user name and then \n\t   following it with something that isn't a password will cause an error \n\t   return */\n\tif( urlInfo.port > 0 )\n\t\t{\n\t\t( void ) krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_PORT );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, &urlInfo.port,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_PORT );\n\t\t}\n\tif( cryptStatusOK( status ) && urlInfo.userInfoLen > 0 )\n\t\t{\n\t\tMESSAGE_DATA userInfoMsgData;\n\n\t\t( void ) krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME );\n\t\tsetMessageData( &userInfoMsgData, ( MESSAGE_CAST ) urlInfo.userInfo, \n\t\t\t\t\t\turlInfo.userInfoLen );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &userInfoMsgData,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( exitError( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME, \n\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_VALUE, CRYPT_ARGERROR_STR1 ) );\n\t\t}\n\n\t/* Remember the transport type */\n\tif( protocolInfo->flags & SESSION_FLAG_ISHTTPTRANSPORT )\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISHTTPTRANSPORT );\n#if defined( USE_WEBSOCKETS ) \n\tif( urlInfo.type == URL_TYPE_WEBSOCKET )\n\t\tsessionInfoPtr->subProtocol = CRYPT_SUBPROTOCOL_WEBSOCKETS;\n#endif /* USE_WEBSOCKETS */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add credentials (username/password) to a session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int addCredential( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( credentialLength ) const void *credential,\n\t\t\t\t\t\t  IN_LENGTH_TEXT const int credentialLength,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tint flags = isServer( sessionInfoPtr ) ? \\\n\t\t\t\tATTR_FLAG_MULTIVALUED : ATTR_FLAG_NONE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( credential, credentialLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( credentialLength > 0 && \\\n\t\t\t  credentialLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( attribute == CRYPT_SESSINFO_USERNAME || \\\n\t\t\t  attribute == CRYPT_SESSINFO_PASSWORD );\n\n\t/* If this is a client session then we can only have a single instance \n\t   of this attribute */\n\tif( !isServer( sessionInfoPtr ) )\n\t\t{\n\t\t/* Make sure that there's only a single instance present */\n\t\tif( findSessionInfo( sessionInfoPtr, attribute ) != NULL )\n\t\t\treturn( exitErrorInited( sessionInfoPtr, attribute ) );\n\t\t}\n\n\t/* Get the last-added attribute so that we can check that it's \n\t   consistent with what's being added now */\n\tstatus = setSessionAttributeCursor( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_LAST );\n\tif( attribute == CRYPT_SESSINFO_USERNAME )\n\t\t{\n\t\t/* It's a username, make sure that the last attribute added wasn't \n\t\t   also a username and that it doesn't duplicate an existing name */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeListCurrent );\n\n\t\t\tREQUIRES( attributeListPtr != NULL );\n\n\t\t\tif( attributeListPtr->attributeID == CRYPT_SESSINFO_USERNAME )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_USERNAME ) );\n\t\t\t\t}\n\t\t\tif( findSessionInfoEx( sessionInfoPtr, \n\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t   credential, credentialLength ) != NULL )\n\t\t\t\t{\n\t\t\t\treturn( exitError( sessionInfoPtr, \n\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_PRESENT, \n\t\t\t\t\t\t\t\t   CRYPT_ERROR_DUPLICATE ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\t\t/* It's a password, make sure that there's an associated username to \n\t\t   go with it.  There are two approaches that we can take here, the \n\t\t   first simply requires that the current cursor position is a \n\t\t   username, implying that the last-added attribute was a username.  \n\t\t   The other is to try and move the cursor to the last username in \n\t\t   the attribute list and check that the next attribute isn't a \n\t\t   password and then add it there, however this is doing a bit too \n\t\t   much behind the user's back, is somewhat difficult to back out \n\t\t   of, and leads to exceptions to exceptions, so we keep it simple \n\t\t   and only allow passwords to be added if there's an immediately \n\t\t   preceding username */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( exitErrorNotInited( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME ) );\n\t\t\t}\n\t\tattributeListPtr = \\\n\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeListCurrent );\n\t\tREQUIRES( attributeListPtr != NULL );\n\t\tif( attributeListPtr->attributeID != CRYPT_SESSINFO_USERNAME )\n\t\t\t{\n\t\t\treturn( exitErrorNotInited( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME ) );\n\t\t\t}\n\t\t}\n\n\t/* If it could be an encoded PKI value, check its validity */\n#ifdef USE_BASE64ID\n\tif( credentialLength >= 15 && \\\n\t\tisPKIUserValue( credential, credentialLength ) )\n\t\t{\n\t\tBYTE decodedValue[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint decodedValueLen;\n\n\t\t/* It's an encoded value, make sure that it's in order */\n\t\tstatus = decodePKIUserValue( decodedValue, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t &decodedValueLen, credential, \n\t\t\t\t\t\t\t\t\t credentialLength );\n\t\tzeroise( decodedValue, CRYPT_MAX_TEXTSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tflags = ATTR_FLAG_ENCODEDVALUE;\n\t\t}\n#endif /* USE_BASE64ID */\n\n\t/* Perform any protocol-specific additional checks if necessary */\n\tif( FNPTR_ISSET( sessionInfoPtr->checkAttributeFunction ) )\n\t\t{\n\t\tconst SES_CHECKATTRIBUTE_FUNCTION checkAttributeFunction = \\\n\t\t\t\t\t( SES_CHECKATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->checkAttributeFunction );\n\t\tMESSAGE_DATA msgData;\n\n\t\tREQUIRES( checkAttributeFunction != NULL );\n\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) credential, \n\t\t\t\t\t\tcredentialLength );\n\t\tstatus = checkAttributeFunction( sessionInfoPtr, &msgData, \n\t\t\t\t\t\t\t\t\t\t attribute );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* The value was dealt with as a side-effect of the check \n\t\t\t   function, there's nothing more to do */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Remember the value */\n\treturn( addSessionInfoEx( sessionInfoPtr, attribute, credential, \n\t\t\t\t\t\t\t  credentialLength, flags ) );\n\t}\n\n/* Add a private key to a session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addPrivateKey( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT privateKey )\n\t{\n\tconst int requiredAttributeFlags = \\\n\t\tisServer( sessionInfoPtr ) ? sessionInfoPtr->serverReqAttrFlags : \\\n\t\t\t\t\t\t\t\t\t sessionInfoPtr->clientReqAttrFlags;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isHandleRangeValid( privateKey ) );\n\n\t/* Make sure that it's a private key */\n\tif( !checkContextCapability( privateKey, \n\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_PRIVATE ) )\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t/* If we need a private key with certain capabilities, make sure that it \n\t   has these capabilities.  This is a more specific check than that \n\t   allowed by the kernel ACLs */\n\tif( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYSIGN )\n\t\t{\n\t\tif( !checkContextCapability( privateKey, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\tif( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCRYPT )\n\t\t{\n\t\tif( !checkContextCapability( privateKey, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_DECRYPT ) )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\t}\n\n\t/* If we need a private key with a certificate, make sure that the \n\t   appropriate type of initialised certificate object is present.  This \n\t   is a more specific check than that allowed by the kernel ACLs */\n\tif( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCERT )\n\t\t{\n\t\tBOOLEAN_INT isInited;\n\t\tint value;\n\n\t\tstatus = krnlSendMessage( privateKey, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &isInited, CRYPT_CERTINFO_IMMUTABLE );\n\t\tif( cryptStatusError( status ) || !isInited )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\tstatus = krnlSendMessage( privateKey, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, CRYPT_CERTINFO_CERTTYPE );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\t( value != CRYPT_CERTTYPE_CERTIFICATE && \\\n\t\t\t  value != CRYPT_CERTTYPE_CERTCHAIN ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tif( requiredAttributeFlags & SESSION_NEEDS_PRIVKEYCACERT )\n\t\t{\n\t\tif( !checkContextCapability( privateKey, \n\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN_CA ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* If we're using a certificate, make sure that it's currently valid.  \n\t   This self-check avoids ugly silent failures where everything appears \n\t   to work just fine on the server side but the client gets invalid data \n\t   back */\n\tif( requiredAttributeFlags & ( SESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\t\t\t\t\t\t   SESSION_NEEDS_PRIVKEYCACERT ) )\n\t\t{\n\t\tstatus = checkServerCertValid( privateKey, SESSION_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Perform any protocol-specific additional checks if necessary */\n\tif( FNPTR_ISSET( sessionInfoPtr->checkAttributeFunction ) )\n\t\t{\n\t\tconst SES_CHECKATTRIBUTE_FUNCTION checkAttributeFunction = \\\n\t\t\t\t\t\t( SES_CHECKATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( sessionInfoPtr->checkAttributeFunction );\n\n\t\tREQUIRES( checkAttributeFunction != NULL );\n\n\t\tstatus = checkAttributeFunction( sessionInfoPtr, &privateKey, \n\t\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_PRIVATEKEY );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* The value was dealt with as a side-effect of the check \n\t\t\t   function, there's nothing more to do */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Add the private key and increment its reference count */\n\tkrnlSendNotifier( privateKey, IMESSAGE_INCREFCOUNT );\n\tsessionInfoPtr->privateKey = privateKey;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Clear return value */\n\t*valuePtr = 0;\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\t\t{\n\t\t\tCRYPT_ATTRIBUTE_TYPE attributeID;\n\t\t\tint status;\n\n\t\t\tstatus = getSessionAttributeCursor( sessionInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\t\t\t&attributeID );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( exitError( sessionInfoPtr, attribute, \n\t\t\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_ABSENT, status ) );\n\t\t\t\t}\n\t\t\t*valuePtr = attributeID;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_OPTION_NET_CONNECTTIMEOUT:\n\t\t\tif( sessionInfoPtr->connectTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_CONNECTTIMEOUT ) );\n\t\t\t\t}\n\t\t\t*valuePtr = sessionInfoPtr->connectTimeout;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_READTIMEOUT:\n\t\t\tif( sessionInfoPtr->readTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_READTIMEOUT ) );\n\t\t\t\t}\n\t\t\t*valuePtr = sessionInfoPtr->readTimeout;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_WRITETIMEOUT:\n\t\t\tif( sessionInfoPtr->writeTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_WRITETIMEOUT ) );\n\t\t\t\t}\n\t\t\t*valuePtr = sessionInfoPtr->writeTimeout;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORTYPE:\n\t\t\t*valuePtr = sessionInfoPtr->errorType;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORLOCUS:\n\t\t\t*valuePtr = sessionInfoPtr->errorLocus;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_BUFFERSIZE:\n\t\t\t*valuePtr = sessionInfoPtr->receiveBufSize;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_ACTIVE:\n\t\t\t/* Only secure transport sessions can be persistently active,\n\t\t\t   request/response sessions are only active while the \n\t\t\t   transaction is in progress.  Note that this differs from the\n\t\t\t   connection-active state below, which records the fact that \n\t\t\t   there's a network-level connection established but not whether\n\t\t\t   there's any messages or a secure session active across it.  \n\t\t\t   See the comment in setSessionAttribute() for more on this */\n\t\t\t*valuePtr = sessionInfoPtr->iCryptInContext != CRYPT_ERROR && \\\n\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t\t\t   SESSION_FLAG_ISOPEN ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_CONNECTIONACTIVE:\n\t\t\t*valuePtr = TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t\t\t   SESSION_FLAG_ISOPEN ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_SERVER_PORT:\n\t\tcase CRYPT_SESSINFO_CLIENT_PORT:\n\t\t\t{\n\t\t\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\t\t\t\tfindSessionInfo( sessionInfoPtr, attribute );\n\t\t\tif( attributeListPtr == NULL )\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr, attribute ) );\n\t\t\t*valuePtr = attributeListPtr->intValue;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_VERSION:\n\t\t\t*valuePtr = sessionInfoPtr->version;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_AUTHRESPONSE:\n\t\t\tif( sessionInfoPtr->authResponse == AUTHRESPONSE_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_AUTHRESPONSE ) );\n\t\t\t\t}\n\t\t\t*valuePtr = \\\n\t\t\t\t( sessionInfoPtr->authResponse == AUTHRESPONSE_SUCCESS ) ? \\\n\t\t\t\tTRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( msgData, sizeof( MESSAGE_DATA ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_NET_SOCKS_SERVER:\n\t\tcase CRYPT_OPTION_NET_SOCKS_USERNAME:\n\t\tcase CRYPT_OPTION_NET_HTTP_PROXY:\n\t\t\t/* These aren't implemented on a per-session level yet since \n\t\t\t   they're almost never user */\n\t\t\treturn( exitErrorNotFound( sessionInfoPtr, attribute ) );\n\n\t\tcase CRYPT_ATTRIBUTE_ERRORMESSAGE:\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tERROR_INFO *errorInfo = &sessionInfoPtr->errorInfo;\n\n\t\t\tif( errorInfo->errorStringLength > 0 )\n\t\t\t\t{\n\t\t\t\treturn( attributeCopy( msgData, errorInfo->errorString,\n\t\t\t\t\t\t\t\t\t   errorInfo->errorStringLength ) );\n\t\t\t\t}\n#endif /* USE_ERRMSGS */\n\n\t\t\t/* We don't set extended error information for this atribute \n\t\t\t   because it's usually read in response to an existing error, \n\t\t\t   which would overwrite the existing error information */\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_USERNAME:\n\t\tcase CRYPT_SESSINFO_PASSWORD:\n\t\t\t/* If the session was resumed from cached information then the\n\t\t\t   username and password won't be present, however we provide a\n\t\t\t   dummy username to indicate what's happening */\n\t\t\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_CACHEDINFO ) )\n\t\t\t\t{\n\t\t\t\tif( attribute == CRYPT_SESSINFO_PASSWORD )\n\t\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr, attribute ) );\n\t\t\t\treturn( attributeCopy( msgData, \n\t\t\t\t\t\t\t\t\t   \"[Resumed from previous session]\", 31 ) );\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1:\n\t\tcase CRYPT_SESSINFO_SERVER_NAME:\n\t\tcase CRYPT_SESSINFO_CLIENT_NAME:\n\t\t\tattributeListPtr = findSessionInfo( sessionInfoPtr, attribute );\n\t\t\tif( attributeListPtr == NULL )\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr, attribute ) );\n\t\t\treturn( attributeCopy( msgData, attributeListPtr->value,\n\t\t\t\t\t\t\t\t   attributeListPtr->valueLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSet Attributes\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set a numeric/boolean attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN const int value, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( ( attribute == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t\tattribute == CRYPT_ATTRIBUTE_CURRENT ) || \n\t\t\t\t/* CURRENT = cursor positioning code */\n\t\t\t  ( attribute == CRYPT_SESSINFO_NETWORKSOCKET ) ||\n\t\t\t\t/* Socket = non-typed value */\n\t\t\t  isIntegerRange( value ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_ATTRIBUTE_CURRENT:\n\t\tcase CRYPT_ATTRIBUTE_CURRENT_GROUP:\n\t\t\t{\n\t\t\tREQUIRES( value >= CRYPT_CURSOR_LAST && \\\n\t\t\t\t\t  value <= CRYPT_CURSOR_FIRST );\t/* Values are -ve */\n\t\t\tstatus = setSessionAttributeCursor( sessionInfoPtr, attribute, \n\t\t\t\t\t\t\t\t\t\t\t\tvalue );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( exitError( sessionInfoPtr, attribute, \n\t\t\t\t\t\t\t\t   CRYPT_ERRTYPE_ATTR_ABSENT, status ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_OPTION_NET_CONNECTTIMEOUT:\n\t\t\tsessionInfoPtr->connectTimeout = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_READTIMEOUT:\n\t\t\tsessionInfoPtr->readTimeout = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_WRITETIMEOUT:\n\t\t\tsessionInfoPtr->writeTimeout = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ATTRIBUTE_BUFFERSIZE:\n\t\t\tREQUIRES( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) );\n\n\t\t\tsessionInfoPtr->receiveBufSize = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_ACTIVE:\n\t\t\t{\n\t\t\tCRYPT_ATTRIBUTE_TYPE missingInfo;\n\n\t\t\t/* Session state and persistent sessions are handled as follows:\n\t\t\t   The CRYPT_SESSINFO_ACTIVE attribute records the active state\n\t\t\t   of the session as a whole, and the CRYPT_SESSINFO_-\n\t\t\t   CONNECTIONACTIVE attribute records the state of the \n\t\t\t   underlying comms session.  Setting CRYPT_SESSINFO_ACTIVE for \n\t\t\t   the first time activates the comms session and leaves it \n\t\t\t   active if the underlying mechanism (e.g. HTTP 1.1 persistent \n\t\t\t   connections) supports it.  The CRYPT_SESSINFO_ACTIVE \n\t\t\t   attribute is reset once the transaction completes, and \n\t\t\t   further transactions can be initiated as long as \n\t\t\t   CRYPT_SESSINFO_CONNECTIONACTIVE is set:\n\n\t\t\t\t\t\t\t\t\t\tObj.state\t_active\t\t_connactive\n\t\t\t\t\t\t\t\t\t\t---------\t-------\t\t-----------\n\t\t\t\tcreate\t\t\t\t\t\t0\t\t\t0\t\t\t0\n\t\t\t\tsetattr\t\t\t\t\t\t0\t\t\t0\t\t\t0\n\t\t\t\t\t(clear out_param)\n\t\t\t\tactivate\t\t\t\t\t1\t\t0 -> 1 -> 0\t\t1\n\t\t\t\t\t(clear in_param)\n\t\t\t\tsetattr\t\t\t\t\t\t1\t\t\t0\t\t\t1\n\t\t\t\t\t(clear out_param)\n\t\t\t\tactivate\t\t\t\t\t1\t\t0 -> 1 -> 0\t\t1\n\t\t\t\t\t(clear in_param)\n\t\t\t\t\t(peer closes conn)\t\t1\t\t\t0\t\t\t0\n\t\t\t\tsetattr\t\t\t\t\t\t\tCRYPT_ERROR_COMPLETE */\n\t\t\tif( value == FALSE )\n\t\t\t\treturn( CRYPT_OK );\t/* No-op */\n\n\t\t\t/* If the session is in the partially-open state while we wait \n\t\t\t   for the caller to allow or disallow the session authentication \n\t\t\t   they have to provide a clear yes or no indication by setting \n\t\t\t   CRYPT_SESSINFO_AUTHRESPONSE to TRUE or FALSE before they can \n\t\t\t   try to continue the session activation */\n\t\t\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t   SESSION_FLAG_PARTIALOPEN ) && \\\n\t\t\t\tsessionInfoPtr->authResponse == AUTHRESPONSE_NONE )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t    CRYPT_SESSINFO_AUTHRESPONSE ) );\n\t\t\t\t}\n\n\t\t\t/* Make sure that all of the information that we need to proceed \n\t\t\t   is present */\n\t\t\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\t\t\tmissingInfo = checkMissingInfo( DATAPTR_GET( sessionInfoPtr->attributeList ),\n\t\t\t\t\t\t\t\tisServer( sessionInfoPtr ) ? TRUE : FALSE );\n\t\t\tif( missingInfo != CRYPT_ATTRIBUTE_NONE )\n\t\t\t\treturn( exitErrorNotInited( sessionInfoPtr, missingInfo ) );\n\n\t\t\tstatus = activateSession( sessionInfoPtr );\n\t\t\tif( cryptArgError( status ) )\n\t\t\t\t{\n\t\t\t\t/* Catch leaked low-level status values.  The session \n\t\t\t\t   management code does a large amount of work involving \n\t\t\t\t   other cryptlib objects so it's possible that an \n\t\t\t\t   unexpected failure at some point will leak through an \n\t\t\t\t   inappropriate status value */\n\t\t\t\tDEBUG_DIAG(( \"Session activate returned argError status\" ));\n\t\t\t\tassert( DEBUG_WARN );\n\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_SERVER_PORT:\n\t\t\t/* If there's already a network socket specified then we can't \n\t\t\t   set a port as well */\n\t\t\tif( sessionInfoPtr->networkSocket != CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_NETWORKSOCKET ) );\n\t\t\t\t}\n\n\t\t\treturn( addSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_PORT, value ) );\n\n\t\tcase CRYPT_SESSINFO_VERSION:\n\t\t\t{\n\t\t\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\t\t\tENSURES( protocolInfo != NULL );\n\n\t\t\tif( value < protocolInfo->minVersion || \\\n\t\t\t\tvalue > protocolInfo->maxVersion )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\t\tsessionInfoPtr->version = value;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_PRIVATEKEY:\n\t\t\treturn( addPrivateKey( sessionInfoPtr, value ) );\n\n\t\tcase CRYPT_SESSINFO_KEYSET:\n\t\t\t{\n\t\t\tint type;\n\n\t\t\t/* Make sure that it's either a certificate store (rather than \n\t\t\t   just a generic keyset) if required, or specifically not a \n\t\t\t   certificate store if not required.  This is to prevent a \n\t\t\t   session running with unnecessary privileges, we should only \n\t\t\t   be using a certificate store if it's actually required.  The \n\t\t\t   checking is already performed by the kernel but we do it \n\t\t\t   again here just to be safe */\n\t\t\tstatus = krnlSendMessage( value, IMESSAGE_GETATTRIBUTE, &type, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_SUBTYPE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\tif( sessionInfoPtr->serverReqAttrFlags & SESSION_NEEDS_CERTSTORE )\n\t\t\t\t{\n\t\t\t\tif( type != SUBTYPE_KEYSET_DBMS_STORE )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( type != SUBTYPE_KEYSET_DBMS )\n\t\t\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t\t}\n\n\t\t\t/* Add the keyset and increment its reference count */\n\t\t\tkrnlSendNotifier( value, IMESSAGE_INCREFCOUNT );\n\t\t\tsessionInfoPtr->cryptKeyset = value;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_AUTHRESPONSE:\n\t\t\t{\n\t\t\tconst SES_SETATTRIBUTE_FUNCTION setAttributeFunction = \\\n\t\t\t\t\t\t\t( SES_SETATTRIBUTE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( sessionInfoPtr->setAttributeFunction );\n\t\t\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\t\t\tREQUIRES( protocolInfo != NULL );\n\n\t\t\tsessionInfoPtr->authResponse = value ? AUTHRESPONSE_SUCCESS : \\\n\t\t\t\t\t\t\t\t\t\t\t\t   AUTHRESPONSE_FAILURE;\n\t\t\tif( !( protocolInfo->flags & SESSION_FLAG_REFLECTAUTHOK ) )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* Besides recording whether it's OK to continue, in some cases \n\t\t\t   we need to reflect the auth-response action down to session-\n\t\t\t   specific handlers for protocol-specific handling */\n\t\t\tREQUIRES( setAttributeFunction != NULL );\n\t\t\treturn( setAttributeFunction( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  &sessionInfoPtr->authResponse,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_AUTHRESPONSE ) );\n\t\t\t}\n\n\t\tcase CRYPT_SESSINFO_SESSION:\n\t\t\t/* Not used, blocked by the kernel */\n\t\t\tretIntError();\n\n\t\tcase CRYPT_SESSINFO_NETWORKSOCKET:\n\t\t\t{\n\t\t\tNET_CONNECT_INFO connectInfo;\n\t\t\tSTREAM stream;\n\n\t\t\t/* If there's already a host specified then we can't set a \n\t\t\t   network socket as well */\n\t\t\tif( findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_NAME ) != NULL )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorInited( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_NAME ) );\n\t\t\t\t}\n\n\t\t\t/* Create a dummy network stream to make sure that the network \n\t\t\t   socket is OK */\n\t\t\tinitNetConnectInfo( &connectInfo, sessionInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t\tsessionInfoPtr->readTimeout, \n\t\t\t\t\t\t\t\tsessionInfoPtr->connectTimeout,\n\t\t\t\t\t\t\t\tNET_OPTION_NETWORKSOCKET_DUMMY );\n\t\t\tconnectInfo.networkSocket = value;\n\t\t\tstatus = sNetConnect( &stream, STREAM_PROTOCOL_TCP, \n\t\t\t\t\t\t\t\t  &connectInfo, &sessionInfoPtr->errorInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsNetDisconnect( &stream );\n\n\t\t\t/* Add the network socket */\n\t\t\tsessionInfoPtr->networkSocket = value;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Set a string attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t  IN_LENGTH const int dataLength,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isIntegerRangeNZ( dataLength ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_NET_SOCKS_SERVER:\n\t\tcase CRYPT_OPTION_NET_SOCKS_USERNAME:\n\t\tcase CRYPT_OPTION_NET_HTTP_PROXY:\n\t\t\t/* These aren't implemented on a per-session level yet since \n\t\t\t   they're almost never used */\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\tcase CRYPT_SESSINFO_USERNAME:\n\t\tcase CRYPT_SESSINFO_PASSWORD:\n\t\t\treturn( addCredential( sessionInfoPtr, data, dataLength, \n\t\t\t\t\t\t\t\t   attribute ) );\n\n\t\tcase CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1:\n\t\t\t/* Remember the value */\n\t\t\treturn( addSessionInfoS( sessionInfoPtr, attribute, data, \n\t\t\t\t\t\t\t\t\t dataLength ) );\n\n\t\tcase CRYPT_SESSINFO_SERVER_NAME:\n\t\t\treturn( addUrl( sessionInfoPtr, data, dataLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete Attributes\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete an attribute */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) || \\\n\t\t\t  isInternalAttribute( attribute ) );\n\n\t/* Handle the various information types */\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_OPTION_NET_CONNECTTIMEOUT:\n\t\t\tif( sessionInfoPtr->connectTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_OPTION_NET_CONNECTTIMEOUT ) );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->connectTimeout = CRYPT_ERROR;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_READTIMEOUT:\n\t\t\tif( sessionInfoPtr->readTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_OPTION_NET_READTIMEOUT ) );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->readTimeout = CRYPT_ERROR;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_OPTION_NET_WRITETIMEOUT:\n\t\t\tif( sessionInfoPtr->writeTimeout == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_OPTION_NET_WRITETIMEOUT ) );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->writeTimeout = CRYPT_ERROR;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_USERNAME:\n\t\tcase CRYPT_SESSINFO_PASSWORD:\n\t\tcase CRYPT_SESSINFO_SERVER_NAME:\n\t\tcase CRYPT_SESSINFO_SERVER_PORT:\n\t\t\t/* Make sure that the attribute to delete is actually present */\n\t\t\tattributeListPtr = findSessionInfo( sessionInfoPtr, attribute );\n\t\t\tif( attributeListPtr == NULL )\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr, attribute ) );\n\n\t\t\t/* Delete the attribute.  If we're in the middle of a paired-\n\t\t\t   attribute add then the delete affects the paired attribute.  \n\t\t\t   This can get quite complex because the user could (for \n\t\t\t   example) add a { username, password } pair, then add a second \n\t\t\t   username (but not password), and then delete the first \n\t\t\t   password, leaving an orphaned password followed by an \n\t\t\t   orphaned username.  There isn't any easy way to fix this \n\t\t\t   short of forcing some form of group delete of paired \n\t\t\t   attributes, but this gets too complicated both to implement \n\t\t\t   and to explain to the user in an error status.  What we do \n\t\t\t   here is handle the simple case and let the pre-session-\n\t\t\t   activation sanity check catch situations where the user's \n\t\t\t   gone out of their way to be difficult */\n\t\t\tdeleteSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t   ( ATTRIBUTE_LIST * ) attributeListPtr );\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_REQUEST:\n\t\t\tif( sessionInfoPtr->iCertRequest == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_REQUEST ) );\n\t\t\t\t}\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_TSP_MSGIMPRINT:\n\t\t\tif( sessionInfoPtr->sessionTSP->imprintAlgo == CRYPT_ALGO_NONE || \\\n\t\t\t\tsessionInfoPtr->sessionTSP->imprintSize <= 0 )\n\t\t\t\t{\n\t\t\t\treturn( exitErrorNotFound( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_TSP_MSGIMPRINT ) );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->sessionTSP->imprintAlgo = CRYPT_ALGO_NONE;\n\t\t\tsessionInfoPtr->sessionTSP->imprintSize = 0;\n\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/session/sess_iattr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\tcryptlib Session-specific Attribute Support Routines\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2008\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Helper function used to access internal attributes within an attribute \n   group */\n\n#if 0\t/* Currently unused, may be enabled in a later version with a move \n\t\t   to composite attributes for host/client information */\n\n/* Reset the internal virtual cursor in a attribute-list item after we've \n   moved the attribute cursor */\n\n#define resetVirtualCursor( attributeListPtr ) \\\n\t\tif( attributeListPtr != NULL ) \\\n\t\t\tattributeListPtr->flags |= ATTR_FLAG_CURSORMOVED\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN accessFunction( INOUT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t   IN_ENUM( ATTR ) const ATTR_TYPE attrGetType )\n\t{\n\tstatic const CRYPT_ATTRIBUTE_TYPE attributeOrderList[] = {\n\t\t\t\tCRYPT_SESSINFO_NAME, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\tCRYPT_SESSINFO_KEY, CRYPT_ATTRIBUTE_NONE, \n\t\t\t\tCRYPT_ATTRIBUTE_NONE };\n\tUSER_INFO *userInfoPtr = attributeListPtr->value;\n\tCRYPT_ATTRIBUTE_TYPE attributeID = userInfoPtr->cursorPos;\n\tBOOLEAN doContinue;\n\tint iterationCount = 0, LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES_B( isEnumRange( attrGetType, ATTR ) );\n\n\t/* If we've just moved the cursor onto this attribute, reset the \n\t   position to the first internal attribute */\n\tif( attributeListPtr->flags & ATTR_FLAG_CURSORMOVED )\n\t\t{\n\t\tattributeID = userInfoPtr->cursorPos = \\\n\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE_RESULT;\n\t\tattributeListPtr->flags &= ~ATTR_FLAG_CURSORMOVED;\n\t\t}\n\n\t/* If it's an information fetch, return the currently-selected \n\t   attribute */\n\tif( attrGetType == ATTR_NONE )\n\t\treturn( attributeID );\n\n\tLOOP_LARGE_INITCHECK( doContinue = TRUE, doContinue )\n\t\t{\n\t\tint i, LOOP_ITERATOR_ALT;\n\n\t\t/* Find the position of the current sub-attribute in the attribute \n\t\t   order list and use that to get its successor/predecessor sub-\n\t\t   attribute */\n\t\tLOOP_SMALL_ALT( i = 0, \n\t\t\t\t\t\tattributeOrderList[ i ] != attributeID && \\\n\t\t\t\t\t\t\tattributeOrderList[ i ] != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE ), \n\t\t\t\t\t\ti++ );\n\t\tENSURES_B( LOOP_BOUND_OK_ALT );\n\t\tENSURES_B( i < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ATTRIBUTE_TYPE ) );\n\t\tif( attributeOrderList[ i ] == CRYPT_ATTRIBUTE_NONE )\n\t\t\tattributeID = CRYPT_ATTRIBUTE_NONE;\n\t\telse\n\t\t\t{\n\t\t\tif( attrGetType == ATTR_PREV )\n\t\t\t\t{\n\t\t\t\tattributeID = ( i < 1 ) ? CRYPT_ATTRIBUTE_NONE : \\\n\t\t\t\t\t\t\t\t\t\t  attributeOrderList[ i - 1 ];\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tattributeID = attributeOrderList[ i + 1 ];\n\t\t\t}\n\t\tif( attributeID == CRYPT_ATTRIBUTE_NONE )\n\t\t\t{\n\t\t\t/* We've reached the first/last sub-attribute within the current \n\t\t\t   item/group, tell the caller that there are no more sub-\n\t\t\t   attributes present and they have to move on to the next \n\t\t\t   group */\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Check whether the required sub-attribute is present.  If not, we\n\t\t   continue and try the next one */\n\t\tdoContinue = FALSE;\n\t\tswitch( attributeID )\n\t\t\t{\n\t\t\tcase CRYPT_SESSINFO_NAME:\n\t\t\t\tbreak;\t/* Always present */\n\t\t\t\t\n\t\t\tcase CRYPT_SESSINFO_PASSWORD:\n\t\t\t\tif( userInfoPtr->passwordLen <= 0 )\n\t\t\t\t\tdoContinue = TRUE;\n\t\t\t\tbreak;\n\t\n\t\t\tcase CRYPT_SESSINFO_KEY:\n\t\t\t\tif( userInfoPtr->key == CRYPT_ERROR )\n\t\t\t\t\tdoContinue = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError_Boolean();\n\t\t\t}\n\t\t}\n\tENSURES_B( LOOP_BOUND_OK );\n\tattributeListPtr->attributeCursorEntry = attributeID;\n\t\n\treturn( TRUE );\n\t}\n#else\n  #define resetVirtualCursor( attributeListPtr )\n#endif /* 0 */\n\n/* Callback function used to provide external access to attribute list-\n   internal fields */\n\nCHECK_RETVAL_PTR \\\nstatic const void *getAttrFunction( IN_OPT TYPECAST( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t\t\t\t\t\tconst void *attributePtr, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *groupID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *attributeID, \n\t\t\t\t\t\t\t\t\tOUT_OPT_ATTRIBUTE_Z \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_TYPE *instanceID,\n\t\t\t\t\t\t\t\t\tIN_ENUM( ATTR ) const ATTR_TYPE attrGetType )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr = ( ATTRIBUTE_LIST * ) attributePtr;\n\tBOOLEAN subGroupMove;\n\tint value, status;\n\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( groupID == NULL || \\\n\t\t\tisWritePtr( groupID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( attributeID == NULL || \\\n\t\t\tisWritePtr( attributeID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\tassert( instanceID == NULL || \\\n\t\t\tisWritePtr( instanceID, sizeof( CRYPT_ATTRIBUTE_TYPE ) ) );\n\n\tREQUIRES_N( isEnumRange( attrGetType, ATTR ) );\n\n\t/* Clear return values */\n\tif( groupID != NULL )\n\t\t*groupID = CRYPT_ATTRIBUTE_NONE;\n\tif( attributeID != NULL )\n\t\t*attributeID = CRYPT_ATTRIBUTE_NONE;\n\tif( instanceID != NULL )\n\t\t*instanceID = CRYPT_ATTRIBUTE_NONE;\n\n\t/* Move to the next or previous attribute if required.  This isn't just a\n\t   case of following the previous/next links because some attribute-list \n\t   items contain an entire attribute group so that positioning by \n\t   attribute merely changes the current selection within the group \n\t   (== attribute-list item) rather than moving to the previous/next \n\t   entry.  Because of this we have to special-case the code for \n\t   composite items and allow virtual positioning within the item */\n\tif( attributeListPtr == NULL )\n\t\treturn( NULL );\n\tsubGroupMove = ( attrGetType == ATTR_PREV || \\\n\t\t\t\t\t attrGetType == ATTR_NEXT ) && \\\n\t\t\t\t   TEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t  ATTR_FLAG_COMPOSITE );\n\tif( subGroupMove )\n\t\t{\n\t\tATTRACCESS_FUNCTION accessFunction;\n\n\t\tREQUIRES_N( attrGetType == ATTR_NEXT || attrGetType == ATTR_PREV );\n\t\tREQUIRES_N( TEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t   ATTR_FLAG_COMPOSITE ) );\n\n\t\taccessFunction = ( ATTRACCESS_FUNCTION ) \\\n\t\t\t\t\t\t FNPTR_GET( attributeListPtr->accessFunction );\n\t\tREQUIRES_N( accessFunction != NULL );\n\t\tstatus = accessFunction( attributeListPtr, attrGetType, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( NULL );\n\t\tsubGroupMove = value;\n\t\t}\n\n\t/* If we're moving by group, move to the next/previous attribute list\n\t   item and reset the internal virtual cursor.  Note that we always \n\t   advance the cursor to the next/previous attribute, it's up to the \n\t   calling code to manage attribute-by-attribute vs. group-by-group \n\t   moves */\n\tif( !subGroupMove && attrGetType != ATTR_CURRENT )\n\t\t{\n\t\tif( attrGetType == ATTR_PREV )\n\t\t\t{\n\t\t\tREQUIRES_N( DATAPTR_ISVALID( attributeListPtr->prev ) );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->prev );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tREQUIRES_N( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\t\t\t}\n\t\tresetVirtualCursor( attributeListPtr );\n\t\t}\n\tif( attributeListPtr == NULL )\n\t\treturn( NULL );\n\n\t/* Return ID information to the caller.  We only return the group ID if\n\t   we've moved within the attribute group, if we've moved from one group\n\t   to another we leave it cleared because sessions can contain multiple\n\t   groups with the same ID and returning an ID identical to the one from\n\t   the group that we've moved out of would make it look as if we're still \n\t   within the same group.  Note that this relies somewhat on the \n\t   implementation behaviour of the attribute-move functions, which first \n\t   get the current group using ATTR_CURRENT and then move to the next or \n\t   previous using ATTR_NEXT/PREV */\n\tif( groupID != NULL && ( attrGetType == ATTR_CURRENT || subGroupMove ) )\n\t\t*groupID = attributeListPtr->groupID;\n\tif( attributeID != NULL )\n\t\t{\n\t\tif( TEST_FLAG( attributeListPtr->flags, ATTR_FLAG_COMPOSITE ) )\n\t\t\t{\n\t\t\tATTRACCESS_FUNCTION accessFunction;\n\n\t\t\taccessFunction = ( ATTRACCESS_FUNCTION ) \\\n\t\t\t\t\t\t\t FNPTR_GET( attributeListPtr->accessFunction );\n\t\t\tREQUIRES_N( accessFunction != NULL );\n\t\t\tstatus = accessFunction( attributeListPtr, ATTR_NONE, &value );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( NULL );\n\t\t\t*attributeID = value;\n\t\t\t}\n\t\telse\n\t\t\t*attributeID = attributeListPtr->attributeID;\n\t\t}\n\n\treturn( attributeListPtr );\n\t}\n\n/* Lock ephemeral attributes so that they can't be deleted any more by\n   resetEphemeralAttributes().  This just clears the ephemeral flag so that\n   they're treated as normal attributes */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid lockEphemeralAttributes( INOUT ATTRIBUTE_LIST *attributeListHead )\n\t{\n\tATTRIBUTE_LIST *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributeListHead, sizeof( ATTRIBUTE_LIST * ) ) );\n\n\t/* Clear the ATTR_FLAG_EPHEMERAL flag on all attributes */\n\tLOOP_MAX( attributeListCursor = attributeListHead, \n\t\t\t  attributeListCursor != NULL,\n\t\t\t  attributeListCursor = DATAPTR_GET( attributeListCursor->next ) )\n\t\t{\n\t\tCLEAR_FLAG( attributeListCursor->flags, ATTR_FLAG_EPHEMERAL );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\t}\n\n/* Check that a set of attributes is well-formed.  We can perform most of \n   the checking as the attributes are added but some checks (for example\n   whether each username has a corresponding password) aren't possible \n   until all of the attributes are present */\n\nCHECK_RETVAL_ENUM( CRYPT_ATTRIBUTE ) \\\nCRYPT_ATTRIBUTE_TYPE checkMissingInfo( IN_OPT const ATTRIBUTE_LIST *attributeListHead,\n\t\t\t\t\t\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = attributeListHead;\n\n\tassert( attributeListHead == NULL || \\\n\t\t\tisReadPtr( attributeListHead, sizeof( ATTRIBUTE_LIST * ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\tif( attributeListPtr == NULL )\n\t\treturn( CRYPT_ATTRIBUTE_NONE );\n\n\t/* Make sure that every username attribute is paired up with a \n\t   corresponding authentication attribute.  This only applies to \n\t   servers because clients use a session-wide private key for \n\t   authentication, the presence of which is checked elsewhere */\n\tif( isServer )\n\t\t{\n\t\tint LOOP_ITERATOR;\n\n\t\tLOOP_MAX_CHECK( ( attributeListPtr = \\\n\t\t\t\t\t\t\tattributeFind( attributeListPtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_USERNAME ) ) != NULL )\n\t\t\t{\n\t\t\t/* Make sure that there's a matching authentication attribute.  \n\t\t\t   This is currently a password but in future versions could \n\t\t\t   also be a public key */\n\t\t\tREQUIRES_EXT( DATAPTR_ISVALID( attributeListPtr->next ), \\\n\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\t\t\tif( attributeListPtr == NULL || \\\n\t\t\t\tattributeListPtr->attributeID != CRYPT_SESSINFO_PASSWORD )\n\t\t\t\treturn( CRYPT_SESSINFO_PASSWORD );\n\n\t\t\t/* Move on to the next attribute */\n\t\t\tREQUIRES_EXT( DATAPTR_ISVALID( attributeListPtr->next ), \\\n\t\t\t\t\t\t  CRYPT_ATTRIBUTE_NONE );\n\t\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\t\t\t}\n\t\tENSURES_EXT( LOOP_BOUND_OK, CRYPT_SESSINFO_ACTIVE );\n\t\t}\n\n\treturn( CRYPT_ATTRIBUTE_NONE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tAttribute Cursor Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get/set the attribute cursor */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getSessionAttributeCursor( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,\n\t\t\t\t\t\t\t   OUT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *valuePtr )\n\t{\n\tATTRIBUTE_LIST *attributeListHead = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeList ); \n\tATTRIBUTE_LIST *attributeListCursor = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeListCurrent ); \n\n\tassert( attributeListHead == NULL || \\\n\t\t\tisReadPtr( attributeListHead, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( attributeListCursor == NULL || \\\n\t\t\tisReadPtr( attributeListCursor, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isWritePtr( valuePtr, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT || \\\n\t\t\t  sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t  ( sessionInfoType > CRYPT_SESSINFO_FIRST && \\\n\t\t\t\tsessionInfoType < CRYPT_SESSINFO_LAST ) );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeListCurrent ) );\n\n\t/* Clear return value */\n\t*valuePtr = CRYPT_ATTRIBUTE_NONE;\n\n\t/* We're querying something that resides in the attribute list, make \n\t   sure that there's an attribute list present.  If it's present but \n\t   nothing is selected, select the first entry */\n\tif( attributeListCursor == NULL )\n\t\t{\n\t\tif( attributeListHead == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\tattributeListCursor = attributeListHead;\n\t\tresetVirtualCursor( attributeListCursor );\n\t\tDATAPTR_SET( sessionInfoPtr->attributeListCurrent,\n\t\t\t\t\t attributeListCursor );\n\t\t}\n\tREQUIRES( attributeListCursor != NULL );\n\n\t/* If we're reading the group, return the group type */\n\tif( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP ) \n\t\t*valuePtr = attributeListCursor->groupID;\n\telse\n\t\t{\n\t\t/* If it's a single-attribute group, return the attribute type */\n\t\tif( !TEST_FLAG( attributeListCursor->flags, \n\t\t\t\t\t\tATTR_FLAG_COMPOSITE ) )\n\t\t\t*valuePtr = attributeListCursor->groupID;\n\t\telse\n\t\t\t{\n\t\t\tconst ATTRACCESS_FUNCTION accessFunction = \\\n\t\t\t\t\t( ATTRACCESS_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( attributeListCursor->accessFunction );\n\t\t\tint value, status;\n\n\t\t\tREQUIRES( accessFunction != NULL );\n\n\t\t\t/* It's a composite type, get the currently-selected sub-attribute */\n\t\t\tstatus = accessFunction( attributeListCursor, ATTR_NONE, &value );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t*valuePtr = value;\n\t\t\t}\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSessionAttributeCursor( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,\n\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\tconst int position )\n\t{\n\tATTRIBUTE_LIST *attributeListHead = \\\n\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeList );\n\tATTRIBUTE_LIST *attributeListCursor = \\\n\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeListCurrent );\n\n\tassert( attributeListHead == NULL || \\\n\t\t\tisReadPtr( attributeListHead, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( attributeListCursor == NULL || \\\n\t\t\tisReadPtr( attributeListCursor, sizeof( ATTRIBUTE_LIST ) ) );\n\t\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\t  sessionInfoType == CRYPT_ATTRIBUTE_CURRENT );\n\tREQUIRES( position <= CRYPT_CURSOR_FIRST && \\\n\t\t\t  position >= CRYPT_CURSOR_LAST );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeListCurrent ) );\n\n\t/* If it's an absolute positioning code, pre-set the attribute cursor if \n\t   required */\n\tif( position == CRYPT_CURSOR_FIRST || position == CRYPT_CURSOR_LAST )\n\t\t{\n\t\tif( attributeListHead == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t\t/* If it's an absolute attribute positioning code reset the \n\t\t   attribute cursor to the start of the list before we try to move \n\t\t   it, and if it's an attribute positioning code initialise the \n\t\t   attribute cursor if necessary */\n\t\tif( sessionInfoType == CRYPT_ATTRIBUTE_CURRENT_GROUP || \\\n\t\t\tattributeListCursor == NULL )\n\t\t\t{\n\t\t\tattributeListCursor = attributeListHead;\n\t\t\tresetVirtualCursor( attributeListCursor );\n\t\t\t}\n\n\t\t/* If there are no attributes present let the caller know.  Note \n\t\t   that this is a redundant check because if attributeListCursor was \n\t\t   NULL above then it had attributeListHead assigned to it, and \n\t\t   that's non-NULL from the other check above, however we leave the\n\t\t   following in to make things a bit more explicit */\n\t\tif( attributeListCursor == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a relative positioning code, return a not-inited error \n\t\t   rather than a not-found error if the cursor isn't set since there \n\t\t   may be attributes present but the cursor hasn't been initialised \n\t\t   yet by selecting the first or last absolute attribute */\n\t\tif( attributeListCursor == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Move the cursor */\n\tattributeListCursor = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t\t  attributeMoveCursor( attributeListCursor, getAttrFunction,\n\t\t\t\t\t\t\t\t\t\t\t   sessionInfoType, position );\n\tif( attributeListCursor == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tDATAPTR_SET( sessionInfoPtr->attributeListCurrent, attributeListCursor );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFind an Attribute\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find a session attribute by type */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeList ); \n\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES_N( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t\tattributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES_N( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\n\treturn( attributeFind( attributeListPtr, getAttrFunction, attributeID ) );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfoNext( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID )\n\t{\n\tassert( isReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES_N( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t\tattributeID < CRYPT_SESSINFO_LAST );\n\n\treturn( attributeFind( attributeListPtr, getAttrFunction, attributeID ) );\n\t}\n\n/* Find a session attribute by type and content */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfoEx( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int valueLength )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeList ); \n\tconst ATTRIBUTE_LIST *attributeListCursor;\n\tint LOOP_ITERATOR;\n\n\tassert( attributeListPtr == NULL || \\\n\t\t\tisReadPtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isReadPtrDynamic( value, valueLength ) );\n\n\tREQUIRES_N( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES_N( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t\tattributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES_N( isShortIntegerRangeNZ( valueLength ) );\n\tREQUIRES_N( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\n\t/* Find the first attribute of this type */\n\tattributeListCursor = attributeFind( attributeListPtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t\t attributeID );\n\tif( attributeListCursor == NULL )\n\t\treturn( NULL );\n\n\t/* Walk down the rest of the list looking for an attribute entry whose \n\t   contents match the requested contents.  Unfortunately we can't use \n\t   attributeFindNextInstance() to help us because that finds the next \n\t   instance of the current attribute in an attribute group, not the next \n\t   instance in an interleaved set of attributes */\n\tLOOP_MAX_CHECKINC( attributeListCursor != NULL,\n\t\t\t\t\t   attributeListCursor = DATAPTR_GET( attributeListCursor->next ) )\n\t\t{\n\t\tif( attributeListCursor->attributeID == attributeID && \\\n\t\t\tattributeListCursor->valueLength == valueLength && \\\n\t\t\t!memcmp( attributeListCursor->value, value, valueLength ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( attributeListCursor );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tAdd an Attribute\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a session attribute.  There are three versions of this function, the\n   standard version and two extended versions that allow the caller to \n   specify an access function to access session subtype-specific internal\n   attributes when the data being added is structured session-type-specific\n   data, and that allow the use of a set of ATTR_FLAG_xxx flags to provide \n   precise control over the attribute handling */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int addInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE groupID,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\tIN_LENGTH_SHORT const int dataLength, \n\t\t\t\t\tIN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\tIN_OPT const ATTRACCESS_FUNCTION accessFunction, \n\t\t\t\t\tIN_FLAGS_Z( ATTR ) const int flags )\n\t{\n\tATTRIBUTE_LIST *insertPoint = DATAPTR_GET( sessionInfoPtr->attributeList );\n\tATTRIBUTE_LIST *newElement;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( ( data == NULL ) || \\\n\t\t\t( isReadPtrDynamic( data, dataLength ) && \\\n\t\t\t  dataLength <= dataMaxLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( groupID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  groupID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataLength > 0 && dataLength <= dataMaxLength && \\\n\t\t\t\tdataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH_SHORT ) );\n\t\t\t  /* String = { data, dataLength, dataMaxLength }, \n\t\t\t     int = dataLength */\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\tREQUIRES( !( flags & ATTR_FLAG_COMPOSITE ) || \\\n\t\t\t  accessFunction != NULL );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\n\t/* Find the correct insertion point and make sure that the attribute \n\t   isn't already present */\n\tif( insertPoint != NULL )\n\t\t{\n\t\tATTRIBUTE_LIST *prevElement = NULL;\n\t\tint LOOP_ITERATOR;\n\n\t\tLOOP_MAX_CHECKINC( insertPoint != NULL,\n\t\t\t\t\t\t   insertPoint = DATAPTR_GET( insertPoint->next ) )\n\t\t\t{\n\t\t\t/* If this is a non-multivalued attribute, make sure that it\n\t\t\t   isn't already present */\n\t\t\tif( !( flags & ATTR_FLAG_MULTIVALUED ) && \\\n\t\t\t\tinsertPoint->attributeID == attributeID )\n\t\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\t\tprevElement = insertPoint;\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tinsertPoint = prevElement;\n\t\t}\n\n\t/* Allocate memory for the new element and copy the information across.  \n\t   The data is stored in storage ... storage + dataLength, with storage\n\t   reserved up to dataMaxLength (if it's greater than dataLength) to\n\t   allow the contents to be replaced with a new fixed-length value  */\n\tREQUIRES( dataMaxLength == 0 || \\\n\t\t\t  rangeCheck( dataMaxLength, 1, MAX_INTLENGTH_SHORT ) );\n\tif( ( newElement = ( ATTRIBUTE_LIST * ) \\\n\t\t\t\t\t   clAlloc( \"addSessionAttribute\", sizeof( ATTRIBUTE_LIST ) + \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   dataMaxLength ) ) == NULL )\n\t\treturn( CRYPT_ERROR_MEMORY );\n\tinitVarStruct( newElement, ATTRIBUTE_LIST, dataMaxLength, value );\n\tnewElement->groupID = groupID;\n\tnewElement->attributeID = attributeID;\n\tINIT_FLAGS( newElement->flags, flags );\n\tFNPTR_SET( newElement->accessFunction, accessFunction );\n\tDATAPTR_SET( newElement->next, NULL );\n\tDATAPTR_SET( newElement->prev, NULL );\n\tif( data == NULL )\n\t\tnewElement->intValue = dataLength;\n\telse\n\t\t{\n\t\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\t\tmemcpy( newElement->value, data, dataLength );\n\t\tnewElement->valueLength = dataLength;\n\t\t}\n\tinsertDoubleListElement( &sessionInfoPtr->attributeList, insertPoint, \n\t\t\t\t\t\t\t newElement, ATTRIBUTE_LIST );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\tIN_INT_Z const int value )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( isIntegerRange( value ) );\n\n\t/* Pre-3.3 kludge: Set the groupID to the attributeID since groups \n\t   aren't defined yet */\n\treturn( addInfo( sessionInfoPtr, attributeID, attributeID, NULL, \n\t\t\t\t\t value, 0, NULL, ATTR_FLAG_NONE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addSessionInfoS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t IN_LENGTH_SHORT const int dataLength )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Pre-3.3 kludge: Set the groupID to the attributeID since groups \n\t   aren't defined yet */\n\treturn( addInfo( sessionInfoPtr, attributeID, attributeID, data, \n\t\t\t\t\t dataLength, dataLength, NULL, ATTR_FLAG_NONE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addSessionInfoEx( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t\t  IN_FLAGS_Z( ATTR ) const int flags )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_ENCODEDVALUE | ATTR_FLAG_MULTIVALUED ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\n\t/* Pre-3.3 kludge: Set the groupID to the attributeID since groups \n\t   aren't defined yet */\n\treturn( addInfo( sessionInfoPtr, attributeID, attributeID, data, \n\t\t\t\t\t dataLength, dataLength, NULL, flags ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint addSessionInfoComposite( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t const ATTRACCESS_FUNCTION accessFunction, \n\t\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t\t\t IN_FLAGS( ATTR ) const int flags )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( accessFunction != NULL );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\nassert( flags == ATTR_FLAG_MULTIVALUED || flags == ATTR_FLAG_COMPOSITE || \\\n\t\tflags == ( ATTR_FLAG_MULTIVALUED | ATTR_FLAG_COMPOSITE ) );\n\tREQUIRES( isFlagRange( flags, ATTR ) );\n\n\t/* For composite attributes the groupID is the attributeID, with the\n\t   actual attributeID being returned by the accessFunction */\n\treturn( addInfo( sessionInfoPtr, attributeID, attributeID, data, \n\t\t\t\t\t dataLength, dataLength, accessFunction, flags ) );\n\t}\n\n/* Update a session attribute, either by replacing an existing entry if it\n   already exists or by adding a new entry.  Since we can potentially update\n   the entry later we specify two length values, the length of the data \n   currently being added and the maximum length that this value may take in\n   the future */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t   IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t   IN_FLAGS_Z( ATTR ) const int flags )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList );\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( attributeID > CRYPT_SESSINFO_FIRST && \\\n\t\t\t  attributeID < CRYPT_SESSINFO_LAST );\n\tREQUIRES( dataLength > 0 && dataLength <= dataMaxLength && \\\n\t\t\t  dataLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isShortIntegerRangeNZ( dataMaxLength ) );\nassert( ( flags & ~( ATTR_FLAG_NONE | ATTR_FLAG_EPHEMERAL | ATTR_FLAG_ENCODEDVALUE ) ) == 0 );\n\tREQUIRES( isFlagRangeZ( flags, ATTR ) );\n\tREQUIRES( !( flags & ATTR_FLAG_MULTIVALUED ) );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\n\t/* Find the first attribute of this type */\n\tattributeListPtr = attributeFind( attributeListPtr, getAttrFunction, \n\t\t\t\t\t\t\t\t\t  attributeID );\n\n\t/* If the attribute is already present, update the value */\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\tREQUIRES( attributeListPtr->attributeID == attributeID );\n\t\tREQUIRES( ( attributeListPtr->valueLength == 0 && \\\n\t\t\t\t\t!memcmp( attributeListPtr->value, \\\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\", 4 ) ) || \\\n\t\t\t\t  ( attributeListPtr->valueLength > 0 ) );\n\n\t\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\t\tREQUIRES( dataLength <= sizeofVarStruct( attributeListPtr, \\\n\t\t\t\t\t\t\t\t\t\t\t\t ATTRIBUTE_LIST ) - \\\n\t\t\t\t\t\t\t\tsizeof( ATTRIBUTE_LIST ) );\n\t\tzeroise( attributeListPtr->value, attributeListPtr->valueLength );\n\t\tmemcpy( attributeListPtr->value, data, dataLength );\n\t\tattributeListPtr->valueLength = dataLength;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The attribute isn't already present, it's a straight add */\n\treturn( addInfo( sessionInfoPtr, attributeID, attributeID, data, \n\t\t\t\t\t dataLength, dataMaxLength, NULL, flags ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDelete an Attribute\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete one, or a complete set of, session attributes */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint deleteSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT ATTRIBUTE_LIST *attributeListPtr )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListCurrent = \\\n\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeListCurrent );\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeListCurrent ) );\n\n\t/* If we're about to delete the attribute that's pointed to by the \n\t   current-attribute pointer, advance it to the next attribute.  If \n\t   there's no next attribute, move it to the previous attribute.  This \n\t   behaviour is the most logically consistent, it means that we can do \n\t   things like deleting an entire attribute list by repeatedly deleting \n\t   a single attribute */\n\tif( attributeListCurrent == attributeListPtr )\n\t\t{\n\t\tATTRIBUTE_LIST *attributeListCursor = \\\n\t\t\t\t\t\t\t\tDATAPTR_GET( attributeListPtr->next );\n\n\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->next ) );\n\n\t\tif( attributeListCursor == NULL )\n\t\t\t{\n\t\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->prev ) );\n\n\t\t\tattributeListCursor = DATAPTR_GET( attributeListPtr->prev );\n\t\t\t}\n\t\tDATAPTR_SET( sessionInfoPtr->attributeListCurrent, \n\t\t\t\t\t attributeListCursor );\n\t\t}\n\n\t/* Remove the item from the list */\n\tdeleteDoubleListElement( &sessionInfoPtr->attributeList, \n\t\t\t\t\t\t\t attributeListPtr, ATTRIBUTE_LIST );\n\n\t/* Clear all data in the list item and free the memory */\n\tendVarStruct( attributeListPtr, ATTRIBUTE_LIST );\n\tclFree( \"deleteSessionInfo\", attributeListPtr );\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteSessionInfoAll( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tATTRIBUTE_LIST *attributeListCursor = \\\n\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->attributeList );\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES_V( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\n\t/* If the list was empty, return now */\n\tif( attributeListCursor == NULL )\n\t\t{\n\t\tREQUIRES_V( DATAPTR_ISNULL( sessionInfoPtr->attributeListCurrent ) );\n\t\treturn;\n\t\t}\n\n\t/* Destroy any remaining list items */\n\tLOOP_MAX_CHECK( attributeListCursor != NULL )\n\t\t{\n\t\tATTRIBUTE_LIST *itemToFree = attributeListCursor;\n\n\t\tREQUIRES_V( DATAPTR_ISVALID( attributeListCursor->next ) );\n\t\tattributeListCursor = DATAPTR_GET( attributeListCursor->next );\n\t\tdeleteSessionInfo( sessionInfoPtr, itemToFree );\n\t\t}\n\tENSURES_V( LOOP_BOUND_OK );\n\n\tENSURES_V( DATAPTR_ISNULL( sessionInfoPtr->attributeList ) );\n\tENSURES_V( DATAPTR_ISNULL( sessionInfoPtr->attributeListCurrent ) );\n\t}\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/session/sess_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Session Read Support Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/* Common code to read data over a secure connection.  This is called by the \n   protocol-specific handlers, which supply three functions of which two are \n   used for read purposes:\n\n\treadHeaderFunction()\t- Reads the header for a packet and sets up\n\t\t\t\t\t\t\t  length information.\n\tprocessBodyFunction()\t- Processes the body of a packet.\n\n   The behaviour of the network-level stream handlers when called with given \n   timeout and byte-count values is as follows:\n\n\tTimeout\t\tbyteCount\t\tResult\n\t-------\t\t---------\t\t------\n\t\t  - error -\t\t\t\terror\n\t  0\t\t\t  0\t\t\t\t0\n\t  0\t\t\t> 0\t\t\t\tbyteCount\n\t> 0\t\t\t  0\t\t\t\tCRYPT_ERROR_TIMEOUT\n\t> 0\t\t\t> 0\t\t\t\tbyteCount\n\n   Errors encountered in processBodyFunction() are always fatal.  In theory \n   we could try to recover, however the functions update assorted crypto \n   state such as packet sequence numbers and IVs that would be tricky to \n   roll back, and in practice recoverable errors are likely to be extremely \n   rare (at best perhaps a CRYPT_ERROR_TIMEOUT for a context tied to a \n   device, however even this won't occur since the conventional encryption \n   and MAC contexts are all internal native contexts) so there's little \n   point in trying to make the functions recoverable */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state.  This function is called both from the\n   higher-level sanityCheckSession() and indirectly from lower-level read \n   functions as a pre/postcondition on read operations */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionRead( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst int pendingPacketLength = sessionInfoPtr->pendingPacketLength;\n\tconst int pendingPacketRemaining = sessionInfoPtr->pendingPacketRemaining;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Make sure that the general state is in order */\n\tif( sessionInfoPtr->receiveBufSize < MIN_BUFFER_SIZE || \\\n\t\tsessionInfoPtr->receiveBufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Receive buffer size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->receiveBuffer != NULL && \\\n\t\t!safeBufferCheck( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t  sessionInfoPtr->receiveBufSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Receive buffer state\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->type == CRYPT_SESSION_SSH || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_SSH_SERVER || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_SSL || \\\n\t\tsessionInfoPtr->type == CRYPT_SESSION_SSL_SERVER )\n\t\t{\n\t\tif( sessionInfoPtr->maxPacketSize < PACKET_SIZE_MIN || \\\n\t\t\tsessionInfoPtr->maxPacketSize > PACKET_SIZE_MAX )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Max packet size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( sessionInfoPtr->maxPacketSize != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Spurious max packet size\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that the buffer position values are within bounds.  The \n\t   difference between receiveBufStartOfs and partialHeaderRemaining\n\t   is that the former records a constant value, the position at the\n\t   start of the buffer where the metadata ends, while the latter records \n\t   a variable, the amount of metadata currently present */\n\tif( sessionInfoPtr->receiveBufEnd < 0 || \\\n\t\tsessionInfoPtr->receiveBufEnd > sessionInfoPtr->receiveBufSize || \\\n\t\tsessionInfoPtr->receiveBufPos < 0 || \\\n\t\tsessionInfoPtr->receiveBufPos > sessionInfoPtr->receiveBufEnd )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Receive buffer info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->receiveBufStartOfs < 0 || \\\n\t\tsessionInfoPtr->receiveBufStartOfs > FIXED_HEADER_MAX || \\\n\t\tsessionInfoPtr->partialHeaderRemaining < 0 || \\\n\t\tsessionInfoPtr->partialHeaderRemaining > FIXED_HEADER_MAX )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Receive buffer packet info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we haven't started processing data yet then there's no packet \n\t   information present */\n\tif( pendingPacketLength == 0 && pendingPacketRemaining == 0 )\n\t\treturn( TRUE );\n\n\t/* Make sure that packet information is within bounds */\n\tif( pendingPacketLength < 0 || \\\n\t\tpendingPacketLength >= sessionInfoPtr->receiveBufSize || \\\n\t\tpendingPacketRemaining < 0 || \\\n\t\tpendingPacketRemaining >= sessionInfoPtr->receiveBufSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Pending packet info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( ( sessionInfoPtr->receiveBufEnd - \\\n\t\t  sessionInfoPtr->receiveBufPos ) + pendingPacketRemaining != \\\n\t\tpendingPacketLength )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionRead: Pending packet calculation\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Process an inner protocol's data packets.  This iterates through the \n   payload contents until it's all been consumed, potentially handling\n   multiple packets in one go.  So for example an input buffer that\n   contained (H = header, O = out-of-band protocol packet):\n\n   bufPtr\t\t\t\t\t\t\t\t bufEnd\n\t|\t\t\t\t\t\t\t\t\t\t|\n\tv\t\t\t\t\t\t\t\t\t\tv\n\t+-+---------+-+---------+-+-+---------+-+-------+\n\t|H|/////////|H|\\\\\\\\\\\\\\\\\\|O|H|~~~~~~~~~|O|\t\t|\n\t+-+---------+-+---------+-+-+---------+-+-------+\n\n   would be converted in turn into:\n\n\tbytes-\tbufPtr\t\t\t\t\t\tbufEnd\n\tprocessed |\t\t\t\t\t\t\t  |\n\t|<------->v\t\t\t\t\t\t\t  v\n\t+---------+-+---------+-+-+---------+-+---------+\n\t|/////////|H|\\\\\\\\\\\\\\\\\\|O|H|~~~~~~~~~|O|\t\t\t|\n\t+---------+-+---------+-+-+---------+-+---------+\n\n\t\t\t  bytes\t  bufPtr\t\t  bufEnd\n\t\t\t  processed\tv\t\t\t\t|\n\t\t\t  |<------->|\t\t\t\tV\n\t+---------+---------+-+-+---------+-+-----------+\n\t|/////////|\\\\\\\\\\\\\\\\\\|O|H|~~~~~~~~~|O|\t\t\t|\n\t+---------+---------+-+-+---------+-+-----------+\n\n\t\t\t\t\t  bufPtr\t\tbufEnd\n\t\t\t\t\t\t|\t\t\t  |\n\t\t\t\t\t\tv\t\t\t  v\n\t+---------+---------+-+---------+-+-------------+\n\t|/////////|\\\\\\\\\\\\\\\\\\|H|~~~~~~~~~|O|\t\t\t\t|\n\t+---------+---------+-+---------+-+-------------+\n\n\t\t\t\t\t\tbytes\tbPtr/bEnd\n\t\t\t\t\t\tprocessed |\t|\n\t\t\t\t\t\t|<------->v\tv\n\t+---------+---------+---------+-+---------------+\n\t|/////////|\\\\\\\\\\\\\\\\\\|~~~~~~~~~|O|\t\t\t\t|\n\t+---------+---------+---------+-+---------------+\n\n\t+---------+---------+---------+-----------------+\n\t|/////////|\\\\\\\\\\\\\\\\\\|~~~~~~~~~|\t\t\t\t\t|\n\t+---------+---------+---------+-----------------+ \n\n   Note that in some cases bytesProcessed can be zero if an out-of-band \n   packet with no payload is removed */\n\n#define MAX_PACKETS\t\t\t16\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processInnerProtocolData( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT_BUFFER_FIXED( bufSize ) \\\n\t\t\t\t\t\t\t\t\t\tBYTE *buffer,\n\t\t\t\t\t\t\t\t\t IN_DATALENGTH const int bufSize )\n\t{\n\tBYTE *bufPtr = buffer;\n\tint bufEnd = bufSize, totalBytesProcessed, noPackets, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( buffer, bufSize ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( bufSize > 0 && bufSize < MAX_BUFFER_SIZE );\n\n\t/* Walk down the buffer processing each packet in it in turn */\n\tLOOP_MED( ( totalBytesProcessed = 0, noPackets = 0 ), \n\t\t\t  totalBytesProcessed < bufEnd && noPackets < MAX_PACKETS, \n\t\t\t  noPackets++ )\n\t\t{\n\t\tint bytesProcessed, status;\n\n#if 1\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n#else\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, 3,//bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n\t\tif( status == OK_SPECIAL )\tbytesProcessed = 3;\n\t\tbufPtr += bytesProcessed;\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, 3,//bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n\t\tif( status == OK_SPECIAL )\tbytesProcessed = 3;\n\t\tbufPtr += bytesProcessed;\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, 2,//bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n\t\tif( status == OK_SPECIAL )\tbytesProcessed = 2;\n\t\tbufPtr += bytesProcessed;\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, 2,//bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n\t\tif( status == OK_SPECIAL )\tbytesProcessed = 2;\n\t\tbufPtr += bytesProcessed;\n\t\tstatus = bytesProcessed = \\\n\t\t\tprocessInnerPacketFunction( sessionInfoPtr, bufPtr, 5,//bufEnd, \n\t\t\t\t\t\t\t\t\t\t&bufEnd );\n#endif\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If the packet processing returns OK_SPECIAL then all the data\n\t\t\t   in the buffer has been consumed */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\tbreak;\n\n\t\t\treturn( status );\n\t\t\t}\n\t\ttotalBytesProcessed += bytesProcessed;\n\t\tbufPtr += bytesProcessed;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noPackets >= MAX_PACKETS )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Encountered more than %d inner protocol packets\",\n\t\t\t\t  noPackets ) );\n\t\t}\n\n\treturn( bufEnd );\n\t}\n\n/* Data injection point for fuzzing the inner protocol */\n\n#ifdef CONFIG_FUZZ\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint fuzzInnerProtocol( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t   IN_DATALENGTH const int bufSize )\n\t{\n\treturn( processInnerProtocolData( sessionInfoPtr, buffer, bufSize ) );\n\t}\n#endif /* CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tHeader-Read Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read a fixed-size packet header, called by the secure data session\n   routines to read the fixed header on a data packet.  There are two\n   variations of this, an atomic-read readFixedHeaderAtomic() used during \n   the handshake phase that requires all data to be read and treats timeouts \n   as hard errors and a partial-read readFixedHeader() used during the \n   data-transfer phase that treats timeouts as soft errors.\n\n   Buffer handling for the soft-timeout version is as follows:\n\n\t\t| <- hdrSize ->\t|\n\t\t+---------------+\n\t\t|///////|\t\t|\n\t\t+---------------+\n\t\t\t\t|<--+-->|\n\t\t\t\t\t|\n\t\t\tpartialHdrRemaining\n\n   The data is read into the header buffer until partialHeaderRemaining\n   drops to zero.  The function returns OK_SPECIAL until this happens */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedHeaderAtomic( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   OUT_BUFFER_FIXED( headerLength ) void *headerBuffer, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \\\n\t\t\t\t\t\t\t\tconst int headerLength )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( headerBuffer, headerLength ) );\n\n\tREQUIRES( sanityCheckSessionRead( sessionInfoPtr ) );\n\tREQUIRES( headerLength >= FIXED_HEADER_MIN && \\\n\t\t\t  headerLength <= FIXED_HEADER_MAX );\n\n\t/* Clear return value */\n\tmemset( headerBuffer, 0, min( 16, headerLength ) );\n\n\t/* Try and read the header bytes */\n\tstatus = length = \\\n\t\tsread( &sessionInfoPtr->stream, headerBuffer, headerLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We could be trying to read an ack for a close packet sent in \n\t\t   response to an earlier error, in which case we don't want the\n\t\t   already-present error information overwritten by network\n\t\t   error information, so if the no-report-error flag is set we \n\t\t   don't update the extended error information */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t   SESSION_FLAG_NOREPORTERROR ) )\n\t\t\treturn( status );\n\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* We've timed out during the handshake phase, it's a hard timeout \n\t   error */\n\tif( length != headerLength )\n\t\t{\n\t\t/* See the comment above for the early-exit condition */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NOREPORTERROR ) )\n\t\t\treturn( status );\n\n\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t  \"Timeout during packet header read, only got %d of %d \"\n\t\t\t\t  \"bytes\", length, headerLength ) );\n\t\t}\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedHeader( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t OUT_BUFFER_FIXED( headerLength ) void *headerBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \\\n\t\t\t\t\t\t\tconst int headerLength )\n\t{\n\tBYTE *bufPtr = headerBuffer;\n\tint bytesToRead, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( headerBuffer, sizeof( headerLength ) ) );\n\n\tREQUIRES( sanityCheckSessionRead( sessionInfoPtr ) );\n\tREQUIRES( headerLength >= FIXED_HEADER_MIN && \\\n\t\t\t  headerLength <= FIXED_HEADER_MAX );\n\n\t/* We can't clear the return value at this point because there may \n\t   already be a partial header present in the buffer */\n\n\t/* If it's the first attempt at reading the header, set the total byte\n\t   count */\n\tif( sessionInfoPtr->partialHeaderRemaining <= 0 )\n\t\t{\n\t\tsessionInfoPtr->partialHeaderRemaining = headerLength;\n\t\tbytesToRead = headerLength;\n\t\t}\n\telse\n\t\t{\n\t\t/* We've already got a partial header present in the buffer, read \n\t\t   the remaining header data.  Note that the existing partial header \n\t\t   size may be zero (i.e. partialHeaderRemaining == headerLength) \n\t\t   if we got a soft-timeout on a previous call to readFixedHeader().  \n\t\t   This happens on any read in which the peer has sent only a single \n\t\t   packet and the packet fits entirely in the read buffer, and occurs \n\t\t   because we follow up every full packet read with an opportunistic \n\t\t   zero-timeout second read to check if further packets are \n\t\t   pending */\n\t\tbufPtr += headerLength - sessionInfoPtr->partialHeaderRemaining;\n\t\tbytesToRead = sessionInfoPtr->partialHeaderRemaining;\n\t\t}\n\tENSURES( bytesToRead > 0 && bytesToRead <= headerLength );\n\tENSURES( sessionInfoPtr->partialHeaderRemaining > 0 && \\\n\t\t\t sessionInfoPtr->partialHeaderRemaining <= headerLength );\n\n\t/* Now we can clear the return value */\n\tmemset( bufPtr, 0, min( 16, bytesToRead ) );\n\n\t/* Try and read the remaining header bytes */\n\tENSURES( boundsCheckZ( headerLength - sessionInfoPtr->partialHeaderRemaining,\n\t\t\t\t\t\t   bytesToRead, headerLength ) );\n\tstatus = length = \\\n\t\tsread( &sessionInfoPtr->stream, bufPtr, bytesToRead );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We could be trying to read an ack for a close packet sent in \n\t\t   response to an earlier error, in which case we don't want the\n\t\t   already-present error information overwritten by network\n\t\t   error information, so if the no-report-error flag is set we \n\t\t   don't update the extended error information */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NOREPORTERROR ) )\n\t\t\treturn( status );\n\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tsessionInfoPtr->partialHeaderRemaining -= length;\n\n\t/* If we didn't get the whole header, treat it as a soft timeout error */\n\tif( sessionInfoPtr->partialHeaderRemaining > 0 )\n\t\t{\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* We've got the whole header ready to process */\n\tENSURES( sessionInfoPtr->partialHeaderRemaining == 0 );\n\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Data Read Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The read data code uses a helper function tryRead() that either reads\n   everything which is available or to the end of the current packet.  In\n   other words it's an atomic, all-or-nothing function that can be used by\n   higher-level code to handle network-level packetisation.  \n   \n   Buffer management is handled as follows: The receiveBufPos index always \n   points to the end of the decoded data (i.e. data that can be used by the \n   user), if there's no partial packet present this index is the same as \n   receiveBufEnd:\n\n   rbPos/rbEnd\n\t\t|\n\t\tv\n\t----+------------------------\n\t....|\n\t----+------------------------\n\n   After readHeaderFunction() has been called pendingPacketRemaining \n   contains the number of bytes required to complete the packet of length\n   pendingPacketLength:\n  \n   rbPos/rbEnd\n\t\t|\n\t\tv\n\t----+-----------------------+----\n\t....|\t\t\t\t\t\t|\n\t----+-----------------------+----\n\t\t|<---- pPL == pPR ----->|\n\n   tryRead() then attempts to fill the buffer with the packet data, with \n   receiveBufEnd pointing to the end of the received data and advancing as \n   more data is read:\n\n\t  rbPos\t\t\t  rbEnd\n\t\t|\t\t\t\t|\n\t\tv\t\t\t\tv\n\t----+---------------+-------+----\n\t....|///////////////|\t\t|\n\t----+---------------+-------+----\n\t\t|\t\t\t\t|<-pPR->|\n\t\t|<-------- pPL -------->|\n\n   When we reach the end of tryRead(), which means that \n   pendingPacketRemaining reaches zero, we process the complete packet in \n   the buffer with processBody():\n\n\t  rbPos\t\t\t\t\t  rbEnd\n\t\t|\t\t\t\t\t\t|\n\t\tv\t\t\t\t\t\tv\n\t----+-----------------------+----\n\t....|///////////////////////|\n\t----+-----------------------+----\n\t\t|<-------- pPL -------->|\n\t\t\t\t\t\t\t\t| pPR = 0\n\n   If processBody() completes successfully then receiveBufPos and \n   receiveBufEnd are adjusted to point to the end of the new data:\n\n\t\t\t\t\t\t\trbPos/rbEnd\n\t\t\t\t\t\t\t\t|\n\t\t\t\t\t\t\t\tv\n\t----+-----------------------+----\n\t....|.......................|\n\t----+-----------------------+----\n\n   The handling of any header data present at the start of the packet\n   depends on the packet format.  If the header is independent of the\n   encrypted data then it's handled entirely by the readHeaderFunction() and \n   there's no need to provide special-case handling.  If the header is part \n   of the encrypted data then decryption is a two-stage operation in which\n   readHeaderFunction() decrypts just enough of the packet to extract and\n   process the header (depositing any leftover non-header data at the start\n   of the buffer) and processBodyFunction() processes the rest of the data.\n\n   Errors in the readHeaderFunction() are fatal if they come from the session\n   protocol level (e.g. a MAC failure or bad packet) and nonfatal if they\n   come from the network layer below the session (the stream-level code has\n   its own handling of fatal vs. nonfatal errors, so we don't try and get\n   down to that level) */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int tryRead( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesRead,\n\t\t\t\t\tOUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo )\n\t{\n\tSES_READHEADER_FUNCTION readHeaderFunction;\n\tSES_PROCESSBODY_FUNCTION processBodyFunction;\n\tint length, bytesLeft, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( bytesRead, sizeof( int ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\treadHeaderFunction = ( SES_READHEADER_FUNCTION ) \\\n\t\t\t\t\t\t FNPTR_GET( sessionInfoPtr->readHeaderFunction );\n\tprocessBodyFunction = ( SES_PROCESSBODY_FUNCTION ) \\\n\t\t\t\t\t\t  FNPTR_GET( sessionInfoPtr->processBodyFunction );\n\tREQUIRES( readHeaderFunction != NULL );\n\tREQUIRES( processBodyFunction != NULL );\n\n\t/* Clear return values */\n\t*bytesRead = 0;\n\t*readInfo = READINFO_NONE;\n\n\t/* If there's no pending packet information present, try and read it.\n\t   This can return one of four classes of values:\n\n\t\t1. An error code.\n\t\t2. Zero, to indicate that nothing was read.\n\t\t3. OK_SPECIAL and read information READINFO_NOOP to indicate that \n\t\t   header data but no payload data was read.\n\t\t4. A byte count and read information READINFO_HEADERPAYLOAD to \n\t\t   indicate that some payload data was read as part of the header */\n\tif( sessionInfoPtr->pendingPacketLength <= 0 )\n\t\t{\n\t\tstatus = length = readHeaderFunction( sessionInfoPtr, readInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Anything other than OK_SPECIAL to indicate a no-op read is an\n\t\t\t   error */\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\tENSURES( *readInfo == READINFO_NOOP );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If nothing was read then we're done */\n\t\t\tif( length <= 0 )\n\t\t\t\t{\n\t\t\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\t\t\t*bytesRead = 0;\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( ( status == OK_SPECIAL && *readInfo == READINFO_NOOP ) || \\\n\t\t\t\t ( length > 0 && *readInfo == READINFO_HEADERPAYLOAD ) );\n\t\tif( *readInfo == READINFO_HEADERPAYLOAD )\n\t\t\t{\n\t\t\t/* Some protocols treat the header information for a secured\n\t\t\t   data packet as part of the data so when we read the header we\n\t\t\t   can get part of the payload included in the read.  When the\n\t\t\t   protocol-specific header read code obtains some payload data\n\t\t\t   alongside the header it returns READINFO_HEADERPAYLOAD to\n\t\t\t   indicate that the packet information needs to be adjusted for \n\t\t\t   the packet header data that was just read */\n\t\t\tsessionInfoPtr->receiveBufEnd += length;\n\t\t\tsessionInfoPtr->pendingPacketRemaining -= length;\n\t\t\t}\n\t\t}\n\tENSURES( sessionInfoPtr->partialHeaderRemaining == 0 );\n\n\t/* Figure out how much we can read.  If there's not enough room in the \n\t   receive buffer to read at least 1K of packet data, don't try anything \n\t   until the user has emptied more data from the buffer */\n\tbytesLeft = sessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufEnd;\n\tif( bytesLeft < 1024 )\n\t\t{\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\t*bytesRead = 0;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( bytesLeft > sessionInfoPtr->pendingPacketRemaining )\n\t\t{\n\t\t/* Limit the amount of data to read to the remaining packet size */\n\t\tbytesLeft = sessionInfoPtr->pendingPacketRemaining;\n\t\t}\n\n\t/* Try and read more of the packet */\n\tENSURES( boundsCheckZ( sessionInfoPtr->receiveBufEnd, bytesLeft,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tstatus = length = \\\n\t\tsread( &sessionInfoPtr->stream,\n\t\t\t   sessionInfoPtr->receiveBuffer + sessionInfoPtr->receiveBufEnd,\n\t\t\t   bytesLeft );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tif( length <= 0 )\n\t\t{\n\t\t/* Nothing read, try again later.  This happens only if we're using\n\t\t   non-blocking reads (i.e. polled I/O), if any kind of timeout is\n\t\t   specified then we'll get a timeout error if no data is read */\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\treturn( 0 );\n\t\t}\n\tsessionInfoPtr->receiveBufEnd += length;\n\tsessionInfoPtr->pendingPacketRemaining -= length;\n\tif( sessionInfoPtr->pendingPacketRemaining > 0 )\n\t\t{\n\t\t/* We got some but not all of the data, try again later */\n\t\t*readInfo = READINFO_PARTIAL;\n\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tENSURES( sessionInfoPtr->pendingPacketRemaining == 0 );\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t/* We've got a complete packet in the buffer, process it */\n\tstatus = length = processBodyFunction( sessionInfoPtr, readInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If there's a layered protocol inside the outer one, process the inner\n\t   protocol data */\n\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t   SESSION_FLAG_SUBPROTOCOL_ACTIVE ) )\n\t\t{\n\t\tstatus = length = \\\n\t\t\tprocessInnerProtocolData( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufPos, \n\t\t\t\t\t\t\t\t\t  length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Adjust the data size indicators to account for the processed packet */\n\tsessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos + length;\n\tsessionInfoPtr->receiveBufPos = sessionInfoPtr->receiveBufEnd;\n\tsessionInfoPtr->pendingPacketLength = 0;\n\t*bytesRead = length;\n\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Get data from the remote system */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int getData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tOUT_BUFFER( length, *bytesCopied ) BYTE *buffer, \n\t\t\t\t\tIN_DATALENGTH const int length, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tconst int bytesToCopy = min( length, sessionInfoPtr->receiveBufPos );\n\tREADSTATE_INFO readInfo;\n\tint bytesRead, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( buffer, length ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionRead( sessionInfoPtr ) );\n\tREQUIRES( length > 0 && length < MAX_BUFFER_SIZE );\n\tREQUIRES( bytesToCopy >= 0 && bytesToCopy < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\tmemset( buffer, 0, min( 16, length ) );\n\t*bytesCopied = 0;\n\n\t/* Copy over as much data as we can and move any remaining data down to \n\t   the start of the receive buffer.  We copy out up to receiveBufPos, \n\t   the end of the decoded data, but move up to receiveBufEnd, the \n\t   combined decoded data and any as-yet-undecoded partial data that\n\t   follows the decoded data */\n\tif( bytesToCopy > 0 )\n\t\t{\n\t\tconst int remainder = sessionInfoPtr->receiveBufEnd - bytesToCopy;\n\n\t\tENSURES( remainder >= 0 && remainder < MAX_BUFFER_SIZE );\n\n\t\tREQUIRES( rangeCheck( bytesToCopy, 1, length ) );\n\t\tmemcpy( buffer, sessionInfoPtr->receiveBuffer, bytesToCopy );\n\t\tif( remainder > 0 )\n\t\t\t{\n\t\t\t/* There's decoded and/or non-decoded data left, move it down to\n\t\t\t   the start of the buffer */\n\t\t\tREQUIRES( boundsCheck( bytesToCopy, remainder,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd ) );\n\t\t\tmemmove( sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBuffer + bytesToCopy, remainder );\n\t\t\tsessionInfoPtr->receiveBufPos -= bytesToCopy;\n\t\t\tsessionInfoPtr->receiveBufEnd = remainder;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We've consumed all of the data in the buffer, reset the buffer\n\t\t\t   information */\n\t\t\tsessionInfoPtr->receiveBufPos = sessionInfoPtr->receiveBufEnd = 0;\n\t\t\t}\n\n\t\t/* Remember how much we've copied and, if we've satisfied the \n\t\t   request, exit */\n\t\t*bytesCopied = bytesToCopy;\n\t\tif( bytesToCopy >= length )\n\t\t\t{\n\t\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\tENSURES( sessionInfoPtr->receiveBufPos == 0 );\n\n\t/* Try and read a complete packet.  This can return one of four classes \n\t   of values:\n\n\t\t1. An error code.\n\t\t2. Zero to indicate that nothing was read (only happens on non-\n\t\t   blocking reads performing polled I/O, a blocking read will return \n\t\t   a timeout error) or that there isn't enough room left in the read \n\t\t   buffer to read any more.\n\t\t3a.OK_SPECIAL and read information READINFO_PARTIAL to indicate that \n\t\t   a partial packet (not enough to process) was read.\n\t\t3b.OK_SPECIAL and read information READINFO_NOOP to indicate that a \n\t\t   no-op packet was read and the caller should try again without \n\t\t   changing the read timeout value.\n\t\t4. A byte count if a complete packet was read and processed */\n\tstatus = tryRead( sessionInfoPtr, &bytesRead, &readInfo );\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t{\n\t\t/* If it's a crypto-related error, register it so that \n\t\t   countermeasures can be taken */\n\t\tif( readInfo == READINFO_FATAL_CRYPTO )\n\t\t\t{\n\t\t\tregisterCryptoFailure();\n\t\t\treadInfo = READINFO_FATAL;\n\t\t\t}\n\n\t\t/* If it's an internal error then the states of the by-reference\n\t\t   values may be undefined (the internal error could have been \n\t\t   triggered before the by-reference values could be cleared) so we \n\t\t   can't check any further */\n\t\tif( isInternalError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If there's an error reading data, only return an error status if \n\t\t   we haven't already returned all existing/earlier data.  This \n\t\t   ensures that the caller can drain out any remaining data from the \n\t\t   session buffer before they start getting error returns */\n\t\tif( *bytesCopied <= 0 )\n\t\t\t{\n\t\t\tif( readInfo == READINFO_FATAL )\n\t\t\t\tsessionInfoPtr->readErrorState = status;\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We got some data before encountering the error, if it's fatal \n\t\t   save the pending error state for later while returning the read \n\t\t   byte count to the caller.  Note that this results in non-fatal \n\t\t   errors being quietly dropped if data is otherwise available, the \n\t\t   alternative would be to save it as a pending (specially-marked) \n\t\t   non-fatal error, however since this error type by definition can \n\t\t   be resumed it may already have resolved itself by the next time \n\t\t   that we're called so this is safe to do */\n\t\tif( readInfo == READINFO_FATAL )\n\t\t\tsessionInfoPtr->pendingReadErrorState = status;\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* If we read a partial packet and there's room for the rest of the \n\t   packet in the buffer, set a minimum timeout to try and get the rest \n\t   of the packet.  This is safe because tryRead() could have behaved in \n\t   only one of two ways:\n\n\t\t1. Blocking read, in which case we waited for the full timeout \n\t\t   period anyway and a small additional timeout won't be noticed.\n\t\t2. Nonblocking read, in which case waiting for a nonzero time could \n\t\t   potentially have retrieved more data */\n\tif( status == OK_SPECIAL )\n\t\t{\n\t\tREQUIRES( readInfo == READINFO_PARTIAL || \\\n\t\t\t\t  readInfo == READINFO_NOOP );\n\t\tif( readInfo == READINFO_PARTIAL && \\\n\t\t\tsessionInfoPtr->pendingPacketRemaining <= \\\n\t\t\t\tsessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufEnd )\n\t\t\t{\n\t\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_READTIMEOUT, 1 );\n\t\t\t}\n\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* If we got nothing, exit */\n\tif( bytesRead <= 0 )\n\t\t{\n\t\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tENSURES( bytesRead > 0 && bytesRead < MAX_BUFFER_SIZE );\n\n\t/* Make the stream nonblocking if it was blocking before.  This is \n\t   necessary to avoid having the stream always block for the set timeout \n\t   value on the last read */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_READTIMEOUT, 0 );\n\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getSessionData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tOUT_BUFFER( dataMaxLength, *bytesCopied ) void *data, \n\t\t\t\t\tIN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tBYTE *dataPtr = data;\n\tint dataLength = dataMaxLength, status = CRYPT_OK, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( data, dataMaxLength ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*bytesCopied = 0;\n\n\t/* If there's an error pending (which will always be fatal, see the\n\t   comment after the tryRead() call in getData()) set the current error \n\t   state to the pending state and return */\n\tif( cryptStatusError( sessionInfoPtr->pendingReadErrorState ) )\n\t\t{\n\t\tREQUIRES( sessionInfoPtr->receiveBufPos == 0 );\n\n\t\tstatus = sessionInfoPtr->readErrorState = \\\n\t\t\t\t\t\tsessionInfoPtr->pendingReadErrorState;\n\t\tsessionInfoPtr->pendingReadErrorState = CRYPT_OK;\n\n\t\treturn( status );\n\t\t}\n\n\t/* Update the stream read timeout to the current user-selected read \n\t   timeout in case the user has changed the timeout setting.\n\t   \n\t   This isn't perfect in the case of the extremely chatty SSH protocol \n\t   because what looks like a read to the user can involve several reads \n\t   and writes under the hood, and what gets used for those is the \n\t   overall high-level timeout for the operation as a whole, with the \n\t   hidden internal reads and writes using that as their shared setting.  \n\t   \n\t   For example if the code performs a read and hits an SSH channel \n\t   command it has to send back a response, leading possibly to further \n\t   reads and writes, before it can actually read any data.  So the top-\n\t   level read command sets a read timeout and then the much lower-level \n\t   code ends up in a hidden long exchange with the other side using the\n\t   same timeout that was set for the overall read before the higher-\n\t   level read code gets to complete the actual read */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_READTIMEOUT, \n\t\t\t   sessionInfoPtr->readTimeout );\n\n\tLOOP_MAX_INITCHECK( dataLength = dataMaxLength, dataLength > 0 )\n\t\t{\n\t\tint byteCount;\n\n\t\t/* Get the next packets-worth of data.  This can return one of three\n\t\t   classes of values:\n\n\t\t\t1. An error code.\n\t\t\t2. OK_SPECIAL to indicate that some data was read but no more is\n\t\t\t   available.\n\t\t\t3. CRYPT_OK to indicate that data was read and more may be \n\t\t\t   available */\n\t\tstatus = getData( sessionInfoPtr, dataPtr, dataLength, &byteCount );\n\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\tbreak;\n\n\t\t/* We got at least some data, update the buffer indicators */\n\t\tif( byteCount > 0 )\n\t\t\t{\n\t\t\t*bytesCopied += byteCount;\n\t\t\tdataPtr += byteCount;\n\t\t\tdataLength -= byteCount;\n\t\t\t}\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* That was the last of the data, exit */\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tENSURES( sanityCheckSessionRead( sessionInfoPtr ) );\n\n\t/* If we got at least some data or encountered a soft timeout then the \n\t   operation was (nominally) successful, otherwise it's an error */\n\treturn( ( *bytesCopied > 0 || status == OK_SPECIAL ) ? \\\n\t\t\tCRYPT_OK : status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tRequest/response Session Data Read Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTIFICATES\n\n/* Read a PKI (i.e. ASN.1-encoded) datagram.  Unlike the secure session \n   protocols these operations are always atomic so the read process is much \n   simpler */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readPkiDatagram( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 4 ) const int minMessageSize )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tint length DUMMY_INIT, complianceLevel, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( minMessageSize >= 4 && minMessageSize < MAX_INTLENGTH_SHORT );\n\n\t/* Some servers send back sufficiently broken responses that they won't\n\t   pass the validity check on the data that we perform after we read it, \n\t   so we allow it to be disabled by setting the compliance level to\n\t   oblivious */\n\tstatus = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\tcomplianceLevel = CRYPT_COMPLIANCELEVEL_STANDARD;\n\n\t/* Read the datagram */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\tstatus = initHttpInfoRead( &httpDataInfo, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = sread( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\tsizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tlength = httpDataInfo.bytesAvail;\n\n\t/* Perform a sanity check on the length.  This avoids triggering \n\t   assertions in the debug build and provides somewhat more specific \n\t   information for the caller than the invalid-encoding error that we'd \n\t   get later */\n\tif( length < minMessageSize || length >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_UNDERFLOW,\n\t\t\t\t( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKI message length %d, should be %d to %d\", \n\t\t\t\t  length, minMessageSize, MAX_BUFFER_SIZE ) );\n\t\t}\n\n\t/* Find out how much data we got and perform a firewall check that\n\t   everything is OK.  We rely on this rather than the read byte count\n\t   since checking the ASN.1, which is the data that will actually be\n\t   processed, avoids any potential problems with implementations where\n\t   the transport layer gets data lengths slightly wrong */\n\tif( complianceLevel > CRYPT_COMPLIANCELEVEL_OBLIVIOUS )\n\t\t{\n#ifdef CONFIG_FUZZ\n\t\tstatus = getObjectLength( sessionInfoPtr->receiveBuffer, length, \n\t\t\t\t\t\t\t\t  &length );\n#else\n\t\tstatus = checkObjectEncodingLength( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t\t\t\tlength, &length );\n#endif /* CONFIG_FUZZ */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid PKI message encoding\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Perform the same check as before, but this time on the real object \n\t   size rather than the amount of data read */\n\tif( length < minMessageSize || length >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_UNDERFLOW,\n\t\t\t\t( CRYPT_ERROR_UNDERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PKI message length %d, should be %d to %d\", \n\t\t\t\t  length, minMessageSize, MAX_BUFFER_SIZE ) );\n\t\t}\n\n\tsessionInfoPtr->receiveBufEnd = length;\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_CERTIFICATES */\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/session/sess_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Session Write Support Routines\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/* Common code to write data over a secure connection.  This is called by \n   the protocol-specific handlers, which supply three functions of which one \n   is used for write purposes:\n\n\tpreparePacketFunction()\t- Wraps a packet in preparation for sending it.\n\n   The behaviour of the network-level stream handlers when called with given \n   timeout and byte-count values is as follows:\n\n\tTimeout\t\tbyteCount\t\tResult\n\t-------\t\t---------\t\t------\n\t\t  - error -\t\t\t\terror\n\t  0\t\t\t  0\t\t\t\t0\n\t  0\t\t\t> 0\t\t\t\tbyteCount\n\t> 0\t\t\t  0\t\t\t\tCRYPT_ERROR_TIMEOUT\n\t> 0\t\t\t> 0\t\t\t\tbyteCount\n\n   Errors encountered in preparePacketFunction() are always fatal.  In \n   theory we could try to recover, however the functions update assorted \n   crypto state such as packet sequence numbers and IVs that would be tricky \n   to roll back, and in practice recoverable errors are likely to be \n   extremely rare (at best perhaps a CRYPT_ERROR_TIMEOUT for a context tied \n   to a device, however even this won't occur since the conventional \n   encryption and MAC contexts are all internal native contexts) so there's \n   little point in trying to make the functions recoverable */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state.  This function is called both from the\n   higher-level sanityCheckSession() and indirectly from lower-level write \n   functions as a pre/postcondition on write operations */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionWrite( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Request/response sessions only need a single buffer, if this is one of \n\t   those then the send buffer isn't used */\n\tif( sessionInfoPtr->type != CRYPT_SESSION_SSH && \\\n\t\tsessionInfoPtr->type != CRYPT_SESSION_SSH_SERVER && \\\n\t\tsessionInfoPtr->type != CRYPT_SESSION_SSL && \\\n\t\tsessionInfoPtr->type != CRYPT_SESSION_SSL_SERVER )\n\t\t{\n\t\tif( sessionInfoPtr->sendBuffer != NULL || \\\n\t\t\tsessionInfoPtr->sendBufSize != CRYPT_UNUSED || \\\n\t\t\tsessionInfoPtr->sendBufPos != 0 || \\\n\t\t\tsessionInfoPtr->sendBufStartOfs != 0 || \\\n\t\t\tsessionInfoPtr->sendBufPartialBufPos != 0 )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Spurious send buffer\" ));\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Make sure that the general state is in order.  maxPacketSize has been\n\t   checked in the read check */\n\tif( sessionInfoPtr->sendBufSize < MIN_BUFFER_SIZE || \\\n\t\tsessionInfoPtr->sendBufSize >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Send buffer size\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->sendBuffer != NULL && \\\n\t\t!safeBufferCheck( sessionInfoPtr->sendBuffer, \n\t\t\t\t\t\t  sessionInfoPtr->sendBufSize ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Send buffer state\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->sendBufStartOfs < 0 || \\\n\t\tsessionInfoPtr->sendBufStartOfs > FIXED_HEADER_MAX )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Send buffer offset\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->partialWrite != TRUE && \\\n\t\tsessionInfoPtr->partialWrite != FALSE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Partial write\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the buffer position values are within bounds */\n\tif( sessionInfoPtr->sendBufPos < sessionInfoPtr->sendBufStartOfs || \\\n\t\tsessionInfoPtr->sendBufPos >= sessionInfoPtr->sendBufSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Send buffer info\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sessionInfoPtr->sendBufPartialBufPos < 0 || \\\n\t\tsessionInfoPtr->sendBufPartialBufPos >= sessionInfoPtr->sendBufPos )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Send buffer partial position\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( !sessionInfoPtr->partialWrite && \\\n\t\tsessionInfoPtr->sendBufPos > sessionInfoPtr->sendBufStartOfs + \\\n\t\t\t\t\t\t\t\t\t sessionInfoPtr->maxPacketSize )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionWrite: Write position\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Data Write Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the amount of space remaining in the send buffer\n\n\t\tstartOfs\t bufPos\n\t\t\t|\t\t\t|\n\t\t\tv\t\t\tv\n\t+-------+-----------+-----------+---+\n\t|.......|///////////|...........|\t|\n\t+-------+-----------+-----------+---+\n\t\t\t|<----- maxPacket ----->|\n\t\t\t\t\t\t|<- remain->| */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int getRemainingBufferSpace( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst int currentByteCount = sessionInfoPtr->sendBufPos - \\\n\t\t\t\t\t\t\t\t sessionInfoPtr->sendBufStartOfs;\n\tint remainingByteCount;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\tREQUIRES( currentByteCount >= 0 && \\\n\t\t\t  currentByteCount <= sessionInfoPtr->maxPacketSize && \\\n\t\t\t  currentByteCount < MAX_BUFFER_SIZE );\n\tremainingByteCount = sessionInfoPtr->maxPacketSize - currentByteCount;\n\tENSURES( remainingByteCount >= 0 && remainingByteCount < MAX_BUFFER_SIZE );\n\n\treturn( remainingByteCount );\n\t}\n\n/* Send data to the remote system.  There are two strategies for handling \n   buffer filling and partial writes, either to fill the buffer as full as \n   possible and write it all at once, or to write complete packets as soon \n   as they're available.  We use the latter strategy both because it \n   considerably simplifies buffer management and because interleaving \n   (asynchronous once it gets to the TCP stack) writes and packet processing \n   increases the chances that the current packet will be successfully \n   dispatched across the network while the next one is being encrypted - \n   trying to write a large amount of data in one go greatly increases the \n   chances that the write won't be completed in one go.\n\n   Session buffer management is handled as follows: The sendBufStartOfs \n   index points to the start of the payload space in the buffer (everything \n   before this is header data).  The maxPacketSize value indicates the end \n   of the payload space relative to the sendBufStartOfs:\n\n\t<- header ->|<---- payload ---->|\n\t+-----------+-------------------+-------+\n\t|\t\t\t|///////////////////|\t\t|\n\t+-----------+-------------------+-------+\n\t\t\t\t^\t\t\t\t\t^\n\t\t\t\t|\t\t\t\t\t|\n\t\t\tsbStartOfs\t\t  maxPacketSize\n\n   The sendBufPos index moves from sendBufStartOfs to maxPacketSize after \n   which the data is wrapped up by the protocol-specific code.  At this \n   point sendBufPos usually points past the end of maxPacketSize due to the \n   addition of trailer data such as encryption block padding and a MAC.  \n   Once the packet is assembled, the data is flushed and the sendBufPos \n   index reset to sendBufStartOfs:\n\n\t\t   sbStartOfs\t\t  maxPacketSize\n\t\t\t\t|\t\t\t\t\t|\n\t\t\t\tv\t\t\t\t\tv\n\t+-----------+-------+-----------+-------+\n\t|...........|.......|///////////|///////|\n\t+-----------+-------+-----------+-------+\n\t|<---- writtem ---->^<---- to write --->^\n\t\t\t\t\t\t|\t\t\t\t\t|\n\t\t\t\t  sbPartialBufPos\t\t  sbPos\n\n   As with reads, writes can be non-atomic, although on a more restrictive \n   scale than reads: Once an encrypted packet has been assembled in the \n   write buffer the entire contents must be written before a new packet can \n   be assembled.  This guarantees that when the caller flushes data through \n   to the other side all of the data will be sent (and the other side will \n   have a chance to react to it) before the next load of data can be flushed \n   through.\n\n   Once we have partial data in the send buffer all further attempts to add \n   more data fail until the remainder of the partially-written data has been \n   flushed.  This is handled by setting sendBufPartialBufPos to point to the \n   first byte of unwritten data, so that sendBufPartialBufPos ... sendBufPos \n   remains to be written */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int flushData( SESSION_INFO *sessionInfoPtr )\n\t{\n\tSES_PREPAREPACKET_FUNCTION preparePacketFunction;\n\tint bytesToWrite, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\tpreparePacketFunction = ( SES_PREPAREPACKET_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->preparePacketFunction );\n\tREQUIRES( preparePacketFunction != NULL );\n\n\t/* If there's no data to flush, exit */\n\tif( sessionInfoPtr->sendBufPos <= sessionInfoPtr->sendBufStartOfs )\n\t\treturn( CRYPT_OK );\t\n\n\t/* If there's no unwritten data from a previous write attempt still \n\t   present, prepare to send the new data */\n\tif( !sessionInfoPtr->partialWrite )\n\t\t{\n\t\tENSURES( sessionInfoPtr->sendBufPartialBufPos == 0 );\n\n\t\t/* If there's a layered protocol inside the outer one, prepare the \n\t\t   inner protocol's data packet */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t   SESSION_FLAG_SUBPROTOCOL_ACTIVE ) )\n\t\t\t{\n\t\t\tint newLength;\n\n\t\t\tstatus = newLength = \\\n\t\t\t\tprepareInnerPacketFunction( sessionInfoPtr,\n\t\t\t\t\t\tsessionInfoPtr->sendBuffer + sessionInfoPtr->sendBufStartOfs, \n\t\t\t\t\t\tsessionInfoPtr->sendBufSize - sessionInfoPtr->sendBufStartOfs,\n\t\t\t\t\t\tsessionInfoPtr->sendBufPos - sessionInfoPtr->sendBufStartOfs );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tENSURES( newLength > 0 && \\\n\t\t\t\t\t sessionInfoPtr->sendBufStartOfs + newLength <= \\\n\t\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos );\n\t\t\tsessionInfoPtr->sendBufPos = sessionInfoPtr->sendBufStartOfs + newLength;\n\t\t\t}\n\n\t\tstatus = length = preparePacketFunction( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Errors in the crypto are immediately fatal */\n\t\t\tsessionInfoPtr->writeErrorState = status;\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Adjust the buffer position to account for the wrapped packet\n\t\t   size */\n\t\tsessionInfoPtr->sendBufPos = length;\n\t\tENSURES( sessionInfoPtr->sendBufPos > 0 && \\\n\t\t\t\t sessionInfoPtr->sendBufPos <= sessionInfoPtr->sendBufSize );\n\t\t}\n\tbytesToWrite = sessionInfoPtr->sendBufPos - \\\n\t\t\t\t   sessionInfoPtr->sendBufPartialBufPos;\n\tENSURES( bytesToWrite > 0 && bytesToWrite < MAX_BUFFER_SIZE );\n\n\t/* Send the data through to the remote system */\n\tENSURES( boundsCheckZ( sessionInfoPtr->sendBufPartialBufPos, bytesToWrite,\n\t\t\t\t\t\t   sessionInfoPtr->sendBufPos ) );\n\tstatus = length = swrite( &sessionInfoPtr->stream, \n\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPartialBufPos, \n\t\t\t\t\t\t\t  bytesToWrite );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\t/* There was an error other than a (restartable) send timeout,\n\t\t   return the error details to the caller */\n\t\tsessionInfoPtr->writeErrorState = status;\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* If the send timed out before all of the data could be written, \n\t   record how much still remains to be sent and inform the caller.  We\n\t   return this special-case code rather than either a timeout or\n\t   CRYPT_OK / 0 bytes because the caller can turn this into a situation-\n\t   specific status at the higher level, a timeout error for an explicit\n\t   flush but a CRYPT_OK / 0 for an implicit flush performed as part of a\n\t   write */\n\tif( status == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\t/* We timed out with nothing written, let the caller know */\n\t\tsessionInfoPtr->partialWrite = TRUE;\n\t\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tif( length < bytesToWrite )\n\t\t{\n\t\t/* We wrote at least some part of the packet, adjust the partial-\n\t\t   write position by the amount that we wrote */\n\t\tsessionInfoPtr->sendBufPartialBufPos += length;\n\t\tsessionInfoPtr->partialWrite = TRUE;\n\t\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\tENSURES( length == bytesToWrite );\n\n\t/* We sent everything, reset the buffer status values */\n\tsessionInfoPtr->sendBufPos = sessionInfoPtr->sendBufStartOfs;\n\tsessionInfoPtr->partialWrite = FALSE;\n\tsessionInfoPtr->sendBufPartialBufPos = 0;\n\n\t/* If there's a layered protocol inside the outer one, write the inner \n\t   protocol's packet header in preparation for the future addition of\n\t   payload data */\n\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t   SESSION_FLAG_SUBPROTOCOL_ACTIVE ) )\n\t\t{\n\t\tstatus = length = \\\n\t\t\twriteInnerHeaderFunction( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos,\n\t\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsessionInfoPtr->sendBufPos += length;\n\t\t}\n\n\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint putSessionData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data,\n\t\t\t\t\tIN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied )\n\t{\n\tBYTE *dataPtr = ( BYTE * ) data;\n\tint length = dataLength, availableBuffer, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( data == NULL || isReadPtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( bytesCopied, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataLength > 0 && dataLength < MAX_BUFFER_SIZE ) );\n\n\t/* Clear return value */\n\t*bytesCopied = 0;\n\n\t/* If there's an error pending (which will always be fatal, see the\n\t   comment after the flushData() call below), set the current error state\n\t   to the pending state and return */\n\tif( cryptStatusError( sessionInfoPtr->pendingWriteErrorState ) )\n\t\t{\n\t\tREQUIRES( sessionInfoPtr->receiveBufPos == 0 );\n\n\t\tstatus = sessionInfoPtr->writeErrorState = \\\n\t\t\t\t\t\tsessionInfoPtr->pendingWriteErrorState;\n\t\tsessionInfoPtr->pendingWriteErrorState = CRYPT_OK;\n\t\treturn( status );\n\t\t}\n\n\t/* Update the stream write timeout to the current user-selected write \n\t   timeout in case the user has changed the timeout setting.\n\t   \n\t   See the long comment in getSessionData() for the unfortunate \n\t   interaction of the high-level timeout setting and the very chatty SSH \n\t   protocol */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_WRITETIMEOUT, \n\t\t\t   sessionInfoPtr->writeTimeout );\n\n\t/* If it's a flush, send the data through to the server.  If there's a \n\t   timeout error during an explicit flush (that is, some but not all of\n\t   the data is written, so it's a soft timeout) it's converted into an \n\t   explicit hard timeout failure */\n\tif( length <= 0 )\n\t\t{\n\t\tconst int oldBufPos = sessionInfoPtr->sendBufPartialBufPos;\n\t\tint bytesWritten;\n\n\t\tstatus = flushData( sessionInfoPtr );\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\n\t\t/* Since a partial write isn't a network-level error condition (it's \n\t\t   only treated as a problem once it gets to the putSessionData() \n\t\t   layer) there's no extended error information set for it so we \n\t\t   have to set the error information here when we turn the partial\n\t\t   write into a timeout error */\n\t\tbytesWritten = sessionInfoPtr->sendBufPartialBufPos - oldBufPos;\n\t\tif( bytesWritten > 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t\t  \"Timeout during flush, only %d bytes were written \"\n\t\t\t\t\t  \"before the timeout of %d seconds expired\",\n\t\t\t\t\t  sessionInfoPtr->sendBufPartialBufPos, \n\t\t\t\t\t  sessionInfoPtr->writeTimeout ) );\n\t\t\t}\n\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t  \"Timeout during flush, no data could be written before \"\n\t\t\t\t  \"the timeout of %d seconds expired\", \n\t\t\t\t  sessionInfoPtr->writeTimeout ) );\n\t\t}\n\tANALYSER_HINT( dataPtr != NULL );\n\n\t/* If there's unwritten data from a previous write still in the buffer, \n\t   flush that through first.  Since this isn't an explicit flush by the\n\t   caller we convert a soft timeout indicator into CRYPT_OK / 0 bytes */\n\tif( sessionInfoPtr->partialWrite )\n\t\t{\n\t\tstatus = flushData( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( ( status == OK_SPECIAL ) ? CRYPT_OK : status );\n\t\t}\n\n\t/* If there's too much data to fit into the send buffer we need to send \n\t   it through to the host to make room for more */\n\tstatus = availableBuffer = getRemainingBufferSpace( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tLOOP_LARGE_CHECK( length >= availableBuffer )\n\t\t{\n\t\tENSURES( availableBuffer >= 0 && availableBuffer <= length );\n\n\t\t/* Copy in as much data as we have room for and send it through.  The\n\t\t   flush can return one of three classes of values:\n\n\t\t\t1. An error code, but not CRYPT_ERROR_TIMEOUT, which is handled\n\t\t\t   as case (2) below.\n\t\t\t2. OK_SPECIAL to indicate that some of the requested data \n\t\t\t   (possibly 0 bytes) was written.\n\t\t\t3. CRYPT_OK to indicate that all of the requested data was\n\t\t\t   written and more can be written if necessary */\n\t\tif( availableBuffer > 0 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheck( sessionInfoPtr->sendBufPos, availableBuffer,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->sendBufSize ) );\n\t\t\tmemcpy( sessionInfoPtr->sendBuffer + sessionInfoPtr->sendBufPos,\n\t\t\t\t\tdataPtr, availableBuffer );\n\t\t\tsessionInfoPtr->sendBufPos += availableBuffer;\n\t\t\tdataPtr += availableBuffer;\n\t\t\tlength -= availableBuffer;\n\t\t\t*bytesCopied += availableBuffer;\n\t\t\t}\n\t\tstatus = flushData( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If it's a soft timeout indicator convert it to a CRYPT_OK / \n\t\t\t   0 bytes written */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\t{\n\t\t\t\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\t/* There was a problem flushing the data through, if we managed \n\t\t\t   to copy anything into the buffer we've made some progress so \n\t\t\t   we defer it until the next call */\n\t\t\tif( *bytesCopied > 0 )\n\t\t\t\t{\n\t\t\t\tsessionInfoPtr->pendingWriteErrorState = status;\n\n\t\t\t\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n\n\t\t\t/* Nothing was copied before the error occurred, it's \n\t\t\t   immediately fatal */\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* We've flushed the buffer, update the available-space value */\n\t\tstatus = availableBuffer = getRemainingBufferSpace( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If there's anything left, it'll fit completely into the send buffer, \n\t   just copy it in */\n\tif( length > 0 )\n\t\t{\n\t\tENSURES( length < availableBuffer );\n\n\t\tREQUIRES( boundsCheckZ( sessionInfoPtr->sendBufPos, length, \n\t\t\t\t\t\t\t    sessionInfoPtr->sendBufSize ) );\n\t\tmemcpy( sessionInfoPtr->sendBuffer + sessionInfoPtr->sendBufPos,\n\t\t\t\tdataPtr, length );\n\t\tsessionInfoPtr->sendBufPos += length;\n\t\t*bytesCopied += length;\n\t\t}\n\n\tENSURES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tRequest/response Session Data Write Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_CERTIFICATES\n\n/* Write a PKI (i.e. ASN.1-encoded) datagram.  Unlike the secure session \n   protocols these operations are always atomic so the write process is much \n   simpler */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writePkiDatagram( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  IN_BUFFER( contentTypeLen ) const char *contentType, \n\t\t\t\t\t  IN_LENGTH_TEXT const int contentTypeLen )\n\t{\n\tHTTP_DATA_INFO httpDataInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( contentType, contentTypeLen ) );\n\n\tREQUIRES( sanityCheckSessionWrite( sessionInfoPtr ) );\n\tREQUIRES( contentTypeLen > 0 && contentTypeLen <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( sessionInfoPtr->receiveBufEnd > 4 && \\\n\t\t\t  sessionInfoPtr->receiveBufEnd < MAX_BUFFER_SIZE );\n\n\t/* Write the datagram.  Request/response sessions use a single buffer \n\t   for both reads and writes, which is why we're (apparently) writing\n\t   the contents of the read buffer */\n\tstatus = initHttpInfoWrite( &httpDataInfo, \n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufEnd, \n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tENSURES( cryptStatusOK( status ) );\n\thttpDataInfo.contentType = contentType;\n\thttpDataInfo.contentTypeLen = contentTypeLen;\n\tstatus = swrite( &sessionInfoPtr->stream, &httpDataInfo,\n\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t}\n\telse\n\t\tstatus = CRYPT_OK;\t/* swrite() returns a byte count */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\n\treturn( status );\n\t}\n#endif /* USE_CERTIFICATES */\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/session/sess_ws.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Session WebSockets Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2015-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n  #include \"websockets.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n  #include \"session/websockets.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_WEBSOCKETS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the WebSockets state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckSessionSSLWS( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst SSL_WS_INFO *wsInfo = &sessionInfoPtr->sessionSSL->wsInfo;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\n\t/* Check the SSL session state */\n\tif( !sanityCheckSessionSSL( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSLWS: SSL state check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check header information */\n\tif( wsInfo->headerBytesRequired < 0 || \\\n\t\twsInfo->headerBytesRequired > SSL_WS_BUFSIZE || \\\n\t\twsInfo->headerBufPos < 0 || \\\n\t\twsInfo->headerBufPos > wsInfo->headerBytesRequired )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSLWS: Header info\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check miscellaneous metadata */\n\tif( wsInfo->maskPos < 0 || wsInfo->maskPos > WS_MASK_SIZE - 1 || \\\n\t\twsInfo->totalLength < 0 || wsInfo->totalLength >= MAX_BUFFER_SIZE || \\\n\t\t( wsInfo->sendPong != TRUE && wsInfo->sendPong != FALSE ) || \\\n\t\t( wsInfo->sendClose != TRUE && wsInfo->sendClose != FALSE ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSLWS: Metadata\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Initialise an HTTP virtual stream layered on top of the TLS session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initVirtualStream( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tNET_CONNECT_INFO connectInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\n\t/* Initialise the virtual stream information */\n\tinitNetConnectInfo( &connectInfo, sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\tsessionInfoPtr->readTimeout, \n\t\t\t\t\t\tsessionInfoPtr->connectTimeout,\n\t\t\t\t\t\tNET_OPTION_VIRTUAL );\n\tif( !isServer( sessionInfoPtr ) )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\t\t/* Add the server name, whose presence has been checked for\n\t\t   earlier */\n\t\tattributeListPtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME );\n\t\tENSURES( attributeListPtr != NULL );\n\t\tconnectInfo.name = attributeListPtr->value;\n\t\tconnectInfo.nameLength = attributeListPtr->valueLength;\n\t\t}\n\tconnectInfo.port = 443;\t\t/* Dummy port value */\n\tFNPTR_SET( connectInfo.virtualGetDataFunction, getSessionData );\n\tFNPTR_SET( connectInfo.virtualPutDataFunction, putSessionData );\n\tFNPTR_SET( connectInfo.virtualGetErrorInfoFunction, \n\t\t\t   getSessionErrorInfo );\n\tDATAPTR_SET( connectInfo.virtualStateInfo, sessionInfoPtr );\n\n\t/* Set up the virtual stream.  Since this is a virtual stream the listen/\n\t   connect merely sets up the appropriate type of server or client \n\t   stream, there's no actual network connection being established */\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tstatus = sNetListen( stream, STREAM_PROTOCOL_HTTP, &connectInfo, \n\t\t\t\t\t\t\t &sessionInfoPtr->errorInfo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = sNetConnect( stream, STREAM_PROTOCOL_HTTP, &connectInfo, \n\t\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = sioctlSet( stream, STREAM_IOCTL_HTTPREQTYPES, \n\t\t\t\t\t\t\tSTREAM_HTTPREQTYPE_WS_UPGRADE );\n\t\t}\n\treturn( status );\n\t}\n\n#ifdef USE_ERRMSGS\n\n/* Get a string description of WebSocket packet types, used for diagnostic \n   error messages */\n\nCHECK_RETVAL_PTR_NONNULL \\\nstatic const char *getPacketName( IN_BYTE const int packetType )\n\t{\n\tstatic const OBJECT_NAME_INFO packetNameInfo[] = {\n\t\t{ WS_PACKET_TEXT, \"text data\" },\n\t\t{ WS_PACKET_BINARY, \"binary data\" },\n\t\t{ WS_PACKET_TEXT_PARTIAL, \"indefinite text data\" },\n\t\t{ WS_PACKET_BINARY_PARTIAL, \"indefinite binary data\" },\n\t\t{ WS_PACKET_CLOSE, \"close\" },\n\t\t{ WS_PACKET_PING, \"ping\" },\n\t\t{ WS_PACKET_PONG, \"pong\" },\n\t\t{ CRYPT_ERROR, \"<Unknown type>\" },\n\t\t\t{ CRYPT_ERROR, \"<Unknown type>\" }\n\t\t};\n\n\tREQUIRES_EXT( ( packetType >= 0 && packetType <= 0xFF ),\n\t\t\t\t  \"<Internal error>\" );\n\n\treturn( getObjectName( packetNameInfo,\n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( packetNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t   OBJECT_NAME_INFO ),\n\t\t\t\t\t\t   packetType ) );\n\t}\n#endif /* USE_ERRMSGS */\n\n#if defined( __WIN32__ ) && defined( USE_ERRMSGS ) && !defined( NDEBUG ) && \\\n\t!defined( CONFIG_FUZZ )\n\n/* Dump a message to disk for diagnostic purposes */\n\n#define DEBUG_DUMP_WS( buffer, bufSize ) \\\n\t\tdebugDumpWS( sessionInfoPtr, buffer, bufSize )\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid debugDumpWS( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t  IN_BUFFER( bufSize ) const void *buffer, \n\t\t\t\t  IN_LENGTH_SHORT const int bufSize )\n\t{\n\tFILE *filePtr;\n\tstatic int messageCount = 1;\n\tchar fileName[ 1024 + 8 ];\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer,  bufSize ) );\n\n\tif( messageCount > 20 )\n\t\treturn;\t/* Don't dump too many messages */\n\tstrlcpy_s( fileName, 1024, \"/tmp/\" );\n\tsprintf_s( &fileName[ 5 ], 1024, \"websockets_%02d\", messageCount++ );\n\tstrlcat_s( fileName, 1024, \".dat\" );\n\n#ifdef __STDC_LIB_EXT1__\n\tif( fopen_s( &filePtr, fileName, \"wb\" ) != 0 )\n\t\tfilePtr = NULL;\n#else\n\tfilePtr = fopen( fileName, \"wb\" );\n#endif /* __STDC_LIB_EXT1__ */\n\tif( filePtr != NULL )\n\t\t{\n\t\tfwrite( buffer, 1, bufSize, filePtr );\n\t\tfclose( filePtr );\n\t\t}\n\t}\n#else\n  #define DEBUG_DUMP_WS( buffer, bufSize )\n#endif /* Windows debug mode only */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWebSockets Handshake Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The size of the buffer used for the virtual HTTP stream.  This value must\n   be at least as large as MIN_LINEBUF_SIZE in io/http.c */\n\n#define HTTP_BUFSIZE\t\t512\n\n/* Calculate the WebSockets authentication value from a given key value */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int calculateAuthValue( OUT_BUFFER_FIXED( outBufMaxLength ) \\\n\t\t\t\t\t\t\t\t\tBYTE *outBuffer, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( WS_ENCODED_AUTH_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int outBufMaxLength,\n\t\t\t\t\t\t\t   OUT_LENGTH_SHORT_Z int *outLength,\n\t\t\t\t\t\t\t   IN_BUFFER( keyLength ) const void *key,\n\t\t\t\t\t\t\t   IN_LENGTH_FIXED( WS_ENCODED_KEY_SIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int keyLength )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE authValue[ CRYPT_MAX_TEXTSIZE + WS_KEY_GUID_SIZE + 8 ];\n\tBYTE hashValue[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize, status;\n\n\tassert( isWritePtr( outBuffer, outBufMaxLength ) );\n\tassert( isWritePtr( outLength, sizeof( int ) ) );\n\tassert( isReadPtr( key, keyLength ) );\n\n\tREQUIRES( outBufMaxLength >= WS_ENCODED_AUTH_SIZE && \\\n\t\t\t  outBufMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( keyLength == WS_ENCODED_KEY_SIZE );\n\n\t/* Clear return value */\n\tmemset( outBuffer, 0, min( 16, outBufMaxLength ) );\n\t*outLength = 0;\n\n\t/* Concatenate the key and WebSockets GUID value, hash the resulting \n\t   string with SHA-1, and base64-encode the hash to get the \n\t   authentication value */\n\tREQUIRES( boundsCheck( keyLength, WS_KEY_GUID_SIZE, \n\t\t\t\t\t\t   CRYPT_MAX_TEXTSIZE + WS_KEY_GUID_SIZE ) );\n\tmemcpy( authValue, key, keyLength );\n\tmemcpy( authValue + keyLength, WS_KEY_GUID, WS_KEY_GUID_SIZE );\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\thashFunctionAtomic( hashValue, hashSize, authValue, \n\t\t\t\t\t\tkeyLength + WS_KEY_GUID_SIZE );\n\tstatus = base64encode( outBuffer, outBufMaxLength, outLength, \n\t\t\t\t\t\t   hashValue, hashSize, CRYPT_CERTTYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* base64 encoding in raw format strips the padding so we need to re-\n\t   add the padding byte that follows the encoded data */\n\tREQUIRES( *outLength == WS_ENCODED_AUTH_SIZE - 1 );\n\toutBuffer[ *outLength ] = '=';\n\t*outLength += 1;\n\t\n\tENSURES( *outLength == WS_ENCODED_AUTH_SIZE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Make sure that the client and server agree on which WebSockets sub-\n   protocol to use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 6 ) ) \\\nstatic int checkProtocol( IN_BUFFER( reqProtocolLen ) \\\n\t\t\t\t\t\t\t\tconst BYTE *reqProtocol,\n\t\t\t\t\t\t  IN_LENGTH_TEXT const int reqProtocolLen,\n\t\t\t\t\t\t  IN_BUFFER( respProtocolLen ) \\\n\t\t\t\t\t\t\t\tconst BYTE *respProtocol,\n\t\t\t\t\t\t  IN_LENGTH_TEXT_Z const int respProtocolLen,\n\t\t\t\t\t\t  const BOOLEAN isServer,\n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tchar reqProtocolName[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\tchar respProtocolName[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];\n\n\tassert( isReadPtr( reqProtocol, reqProtocolLen ) );\n\tassert( ( !isServer && respProtocolLen == 0 ) || \\\n\t\t\tisReadPtr( respProtocol, respProtocolLen ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( reqProtocolLen >= 1 && reqProtocolLen <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( ( !isServer && respProtocolLen == 0 ) || \\\n\t\t\t  ( respProtocolLen >= 1 && \\\n\t\t\t\trespProtocolLen <= CRYPT_MAX_TEXTSIZE ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Format the protocol names for display */\n\tREQUIRES( rangeCheck( reqProtocolLen, 1, CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( reqProtocolName, reqProtocol, reqProtocolLen );\n\tsanitiseString( reqProtocolName, reqProtocolLen + 1, \n\t\t\t\t\treqProtocolLen ); \n\tif( respProtocolLen > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( respProtocolLen, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( respProtocolName, respProtocol, respProtocolLen );\n\t\tsanitiseString( respProtocolName, respProtocolLen + 1, \n\t\t\t\t\t\trespProtocolLen ); \n\t\t}\n\n\t/* If we're the server, make sure that the client requested the protocol \n\t   that we provide */\n\tif( isServer )\n\t\t{\n\t\tif( reqProtocolLen != respProtocolLen || \\\n\t\t\tmemcmp( reqProtocol, respProtocol, reqProtocolLen ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t  \"Requested WebSockets protocol '%s' doesn't match \"\n\t\t\t\t\t  \"allowed protocol '%s'\", reqProtocolName,\n\t\t\t\t\t  respProtocolName ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Make sure that the server returned the protocol that we requested in \n\t   its response */\n\tif( respProtocolLen <= 0 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"WebSockets server didn't acknowledge requested \"\n\t\t\t\t  \"protocol '%s'\", reqProtocolName ) );\n\t\t}\n\tif( reqProtocolLen != respProtocolLen || \\\n\t\tmemcmp( reqProtocol, respProtocol, reqProtocolLen ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"Returned WebSockets protocol '%s' doesn't match \"\n\t\t\t\t  \"requested protocol '%s'\", respProtocolName, \n\t\t\t\t  reqProtocolName ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Activate a WebSockets protocol layered over the base protocol for a \n   session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int activateWebSocketsClient( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tHTTP_DATA_INFO httpDataInfo;\n\tHTTP_REQ_INFO httpReqInfo;\n\tHTTP_URI_INFO httpUriInfo;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE buffer[ SAFEBUFFER_SIZE( HTTP_BUFSIZE ) ] STACK_ALIGN_DATA;\n\tBYTE nonce[ WS_KEY_SIZE + 8 ], encodedNonce[ CRYPT_MAX_TEXTSIZE + 8 ]; \n\tchar authValue[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint encodedNonceLen DUMMY_INIT, authValueLength, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\n\tmemset( &httpReqInfo, 0, sizeof( HTTP_REQ_INFO ) );\n\n\t/* Fill in the WebSockets sub-protocol if available */\n\tattributeListPtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSL_WSPROTOCOL );\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\tENSURES( rangeCheck( attributeListPtr->valueLength, 1,\n\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE ) );\n\t\thttpReqInfo.protocol = attributeListPtr->value;\n\t\thttpReqInfo.protocolLen = attributeListPtr->valueLength;\n\t\t}\n\n\t/* Create the WebSockets key */\n\tsetMessageData( &msgData, nonce, WS_KEY_SIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = base64encode( encodedNonce, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t   &encodedNonceLen, nonce, WS_KEY_SIZE, \n\t\t\t\t\t\t\t   CRYPT_CERTTYPE_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thttpReqInfo.auth = encodedNonce;\n\t\thttpReqInfo.authLen = encodedNonceLen;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Layer a virtual stream over the top of the session */\n\tstatus = initVirtualStream( sessionInfoPtr, &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the WebSockets upgrade request to the server */\n\tstatus = initHttpInfoReqEx( &httpDataInfo, &httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = swrite( &stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &stream, &sessionInfoPtr->errorInfo );\n\t\tsNetDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Read the response to the WebSockets upgrade request */\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), HTTP_BUFSIZE );\n\tstatus = initHttpInfoReadEx( &httpDataInfo, SAFEBUFFER_PTR( buffer ),\n\t\t\t\t\t\t\t\t HTTP_BUFSIZE, &httpUriInfo );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = sread( &stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &stream, &sessionInfoPtr->errorInfo );\n\t\tsNetDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tsNetDisconnect( &stream );\n\n\t/* Make sure that the auth.key is valid */\n\tstatus = calculateAuthValue( authValue, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t &authValueLength, encodedNonce, \n\t\t\t\t\t\t\t\t encodedNonceLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tENSURES( authValueLength == WS_ENCODED_AUTH_SIZE );\n\tif( httpUriInfo.authLen != WS_ENCODED_AUTH_SIZE || \\\n\t\tmemcmp( httpUriInfo.auth, authValue, authValueLength ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO,\n\t\t\t\t  \"Returned WebSockets authentication value doesn't match \"\n\t\t\t\t  \"calculated value\" ) );\n\t\t}\n\n\t/* If we specified a protocol in our request, make sure that the server \n\t   returned the same one in its response */\n\tif( httpReqInfo.protocolLen > 0 )\n\t\t{\n\t\tstatus = checkProtocol( httpReqInfo.protocol, httpReqInfo.protocolLen,\n\t\t\t\t\t\t\t\thttpUriInfo.protocol, httpUriInfo.protocolLen,\n\t\t\t\t\t\t\t\tFALSE, SESSION_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Prepare the session buffer for the upcoming WebSockets packet \n\t   exchange by writing the WebSockets header to it */\n\tstatus = length = \\\n\t\twriteInnerHeaderFunction( sessionInfoPtr,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsessionInfoPtr->sendBufPos += length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int activateWebSocketsServer( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n\tHTTP_DATA_INFO httpDataInfo;\n\tHTTP_REQ_INFO httpReqInfo;\n\tHTTP_URI_INFO httpUriInfo;\n\tSTREAM stream;\n\tBYTE buffer[ SAFEBUFFER_SIZE( HTTP_BUFSIZE ) ] STACK_ALIGN_DATA;\n\tchar authValue[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint authValueLength, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\n\t/* Layer a virtual stream over the top of the session */\n\tstatus = initVirtualStream( sessionInfoPtr, &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the client's WebSockets upgrade request */\n\tsafeBufferInit( SAFEBUFFER_PTR( buffer ), HTTP_BUFSIZE );\n\tstatus = initHttpInfoReadEx( &httpDataInfo, SAFEBUFFER_PTR( buffer ),\n\t\t\t\t\t\t\t\t HTTP_BUFSIZE, &httpUriInfo );\n\tENSURES( cryptStatusOK( status ) );\n\tstatus = sread( &stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &stream, &sessionInfoPtr->errorInfo );\n\t\tsNetDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* If there's a WebSockets sub-protocol set, make sure that it matches \n\t   what the client requested */\n\tattributeListPtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSL_WSPROTOCOL );\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\tstatus = checkProtocol( httpUriInfo.protocol, httpUriInfo.protocolLen,\n\t\t\t\t\t\t\t\tattributeListPtr->value, \n\t\t\t\t\t\t\t\tattributeListPtr->valueLength, TRUE, \n\t\t\t\t\t\t\t\tSESSION_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tint localStatus;\n\n\t\t\tsNetDisconnect( &stream );\n\n\t\t\t/* The client requested a different protocol than what we \n\t\t\t   provide, let them know that it's not available.  There isn't \n\t\t\t   any particularly good HTTP-level status code to communicate \n\t\t\t   this, \"Not acceptable\" seems to be the least inappropriate \n\t\t\t   one */\n\t\t\tlocalStatus = initHttpInfoReq( &httpDataInfo );\n\t\t\tENSURES( cryptStatusOK( localStatus ) ); \n\t\t\thttpDataInfo.reqStatus = 406;\t/* Not acceptable */\n\t\t\t( void ) swrite( &sessionInfoPtr->stream, &httpDataInfo, \n\t\t\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that the auth.key is valid */\n\tstatus = calculateAuthValue( authValue, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t &authValueLength, httpUriInfo.auth, \n\t\t\t\t\t\t\t\t httpUriInfo.authLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tint localStatus;\n\n\t\tsNetDisconnect( &stream );\n\n\t\t/* The auth key isn't valid, send back the most okayest HTTP status \n\t\t   code that exists for this situation */\n\t\tlocalStatus = initHttpInfoReq( &httpDataInfo );\n\t\tENSURES( cryptStatusOK( localStatus ) ); \n\t\thttpDataInfo.reqStatus = 403;\t/* Forbidden */\n\t\t( void ) swrite( &sessionInfoPtr->stream, &httpDataInfo, \n\t\t\t\t\t\t sizeof( HTTP_DATA_INFO ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Send the WebSockets upgrade acknowledgement to the client */\n\tstatus = initHttpInfoReqEx( &httpDataInfo, &httpReqInfo );\n\tENSURES( cryptStatusOK( status ) );\n\thttpReqInfo.auth = authValue;\n\thttpReqInfo.authLen = authValueLength;\n\tif( httpUriInfo.protocolLen > 0 )\n\t\t{\n\t\thttpReqInfo.protocol = httpUriInfo.protocol;\n\t\thttpReqInfo.protocolLen = httpUriInfo.protocolLen;\n\t\t}\n\tstatus = swrite( &stream, &httpDataInfo, sizeof( HTTP_DATA_INFO ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &stream, &sessionInfoPtr->errorInfo );\n\t\tsNetDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\tsNetDisconnect( &stream );\n\n\t/* Prepare the session buffer for the upcoming WebSockets packet \n\t   exchange by writing the WebSockets header to it */\n\tstatus = length = \\\n\t\twriteInnerHeaderFunction( sessionInfoPtr,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBufPos );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsessionInfoPtr->sendBufPos += length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int closeWebSockets( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\n\t/* If we've already closed the higher-level protocol that we're running \n\t   inside then we're done */\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED ) )\n\t\treturn( CRYPT_OK );\n\n\t/* At this point things get a bit tricky because we're expected to send \n\t   WebSockets data over the TLS session that we're being called from.  \n\t   The standard putSessionData() process has the WebSockets layer modify \n\t   the contents of the send buffer before it gets passed on to the TLS \n\t   write code, but in this case we're being called from the \n\t   closeSession() code, not the putSessionData() code, so there's no \n\t   write to follow.\n\n\t   An additional complication is provided by the fact that we're running \n\t   inside a TLS tunnel, for which the spec requires that when a close \n\t   alert is received, \"The other party MUST respond with a close_notify \n\t   alert of its own and close down the connection immediately, \n\t   discarding any pending writes\".  The WebSockets content is presumably \n\t   a pending write, so on receipt of a TLS close from the other side we \n\t   need to respond with a TLS-level close rather than a WebSockets-level \n\t   close.\n\n\t   This leaves a close initiated by our side.  However, since we're \n\t   again running inside a TLS tunnel, our TLS close takes precedence \n\t   over the other side's WebSockets close, so even if we sent a \n\t   WebSockets close, the other side would have to discard their \n\t   WebSockets close response and send a TLS close back.\n\n\t   If we were going to send a WebSockets level close, the following code\n\t   sketch outlines how it might be done */\n#if 0\n\tSSL_WS_INFO *wsInfo = &sessionInfoPtr->sessionSSL->wsInfo;\n\tBYTE buffer[ WS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE + 8 ];\n\n\t/* Send a Close to the other side */\n\tmemcpy( buffer, isServer( sessionInfoPtr ) ? \\\n\t\t\t\t\tWS_CLOSE_DATA_SERVER : WS_CLOSE_DATA_CLIENT, \n\t\t\tWS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE );\n\tif( !isServer( sessionInfoPtr ) )\n\t\t{\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* If we're the client then we have to mask the Close payload data \n\t\t   before sending it */\n\t\tLOOP_SMALL( i = 0, i < WS_CLOSE_DATA_SIZE, i++ )\n\t\t\t{\n\t\t\tbuffer[ WS_CLOSE_SIZE + i ] ^= wsInfo->mask[ i % WS_MASK_SIZE ];\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* If there's not enough room in the receive buffer to read at least 1K\n\t   of packet data then we can't try anything further */\n\tif( sessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufEnd < \\\n\t\tmin( sessionInfoPtr->pendingPacketRemaining, 1024 ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're in the middle of reading other data then there's no hope of\n\t   reading back the other side's Close without first clearing all of the \n\t   other data, which is unlikely to happen because the session has been \n\t   closed (this can happen when the caller requests a shutdown of the \n\t   session in the middle of a data transfer), in which case we just \n\t   exit */\n\tif( sessionInfoPtr->receiveBufPos != sessionInfoPtr->receiveBufEnd )\n\t\treturn( CRYPT_OK );\n#endif /* 0 */\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWebSockets Read Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Decode the WebSockets fixed-size header and length information */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processFixedHeader( INOUT SSL_WS_INFO *wsInfo,\n\t\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo,\n\t\t\t\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tassert( isWritePtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Decode the packet type */\n\twsInfo->type = byteToInt( wsInfo->headerBuffer[ WS_TYPE_OFFSET ] );\n\tswitch( wsInfo->type )\n\t\t{\n\t\tcase WS_PACKET_TEXT:\n\t\tcase WS_PACKET_BINARY:\n\t\t\tbreak;\n\n\t\tcase WS_PACKET_TEXT_PARTIAL:\n\t\tcase WS_PACKET_BINARY_PARTIAL:\n\t\t\tbreak;\n\n\t\tcase WS_PACKET_CLOSE:\n\t\t\t/* Remember that we need to close our side of the connection */\n\t\t\twsInfo->sendClose = TRUE;\n\t\t\tbreak;\n\n\t\tcase WS_PACKET_PING:\n\t\t\t/* Remember that we need to respond with a Pong packet when \n\t\t\t   possible */\n\t\t\twsInfo->sendPong = TRUE;\n\t\t\tbreak;\n\n\t\tcase WS_PACKET_PONG:\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Unknown WebSockets packet type %X encountered\", \n\t\t\t\t\t  wsInfo->type ) );\n\t\t}\n\n\t/* Decode the length information.  Note that what's recorded at this \n\t   point as the length may be a length-of-length code indicating that \n\t   the actual length follows in a later, separate length field */\n\twsInfo->totalLength = \\\n\t\tbyteToInt( wsInfo->headerBuffer[ WS_LENGTHCODE_OFFSET ] & WS_LENGTH_MASK );\n\twsInfo->headerBytesRequired = isServer ? WS_BASE_HEADER_LENGTH_CLIENT : \\\n\t\t\t\t\t\t\t\t\t\t\t WS_BASE_HEADER_LENGTH_SERVER;\n\tif( wsInfo->totalLength == WS_LENGTH_16BIT )\n\t\twsInfo->headerBytesRequired += UINT16_SIZE;\n\telse\n\t\t{\n\t\tif( wsInfo->totalLength == WS_LENGTH_64BIT )\n\t\t\twsInfo->headerBytesRequired += UINT64_SIZE; \n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processLength( INOUT STREAM *stream,\n\t\t\t\t\t\t  INOUT SSL_WS_INFO *wsInfo,\n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\t/* Read the separate length field if there's one present */\n\tif( wsInfo->totalLength > WS_LENGTH_THRESHOLD )\n\t\t{\n\t\tint length, status;\n\n\t\tswitch( wsInfo->totalLength )\n\t\t\t{\n\t\t\tcase WS_LENGTH_16BIT:\n\t\t\t\tstatus = length = readUint16( stream );\n\t\t\t\tbreak;\n\n\t\t\tcase WS_LENGTH_64BIT:\n\t\t\t\t/* Although this is nominally a 64-bit value, it's bounded\n\t\t\t\t   to a standard integer by the read code */\n\t\t\t\tstatus = length = readUint64( stream );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\t\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t\t  \"Invalid length value for %s WebSockets packet\", \n\t\t\t\t\t  getPacketName( wsInfo->type ) ) );\n\t\t\t}\n\t\twsInfo->totalLength = length;\n\t\t}\n\n\t/* Make sure that the length is valid */\n\tif( wsInfo->totalLength < 0 || wsInfo->totalLength >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid length %d for %s WebSockets packet, should be \"\n\t\t\t\t  \"0...%d\", wsInfo->totalLength, \n\t\t\t\t  getPacketName( wsInfo->type ), MAX_BUFFER_SIZE ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Unmask WebSockets payload data */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int unmaskData( INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t   IN_DATALENGTH const int bufSize,\n\t\t\t\t\t   INOUT SSL_WS_INFO *wsInfo )\n\t{\n\tint maskIndex = wsInfo->maskPos, i, LOOP_ITERATOR;\n\n\tassert( isWritePtr( buffer, bufSize ) );\n\tassert( isWritePtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\n\tREQUIRES( bufSize > 0 && bufSize < MAX_BUFFER_SIZE );\n\n\tLOOP_MAX( i = 0, i < bufSize, ( i++, maskIndex++ ) )\n\t\tbuffer[ i ] ^= wsInfo->mask[ maskIndex % WS_MASK_SIZE ];\n\tENSURES( LOOP_BOUND_OK );\n\twsInfo->maskPos = maskIndex % WS_MASK_SIZE;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int processPayload( INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t   IN_DATALENGTH_Z const int bufSize,\n\t\t\t\t\t\t   INOUT SSL_WS_INFO *wsInfo,\n\t\t\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tBOOLEAN processedAllData = FALSE;\n\tint payloadBytes, status;\n\n\tassert( isWritePtr( buffer, bufSize ) );\n\tassert( isWritePtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\n\tREQUIRES( bufSize >= 0 && bufSize < MAX_BUFFER_SIZE );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Determine how many bytes we still need to process, either everything \n\t   still available or the remainder of the packet */\n\tif( wsInfo->totalLength >= bufSize )\n\t\t{\n\t\t/* The packet encompasses the remaining data */\n\t\tpayloadBytes = bufSize;\n\t\tprocessedAllData = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\t/* The packet ends before the buffer contents do, only process the \n\t\t   remaining packet data */\n\t\tpayloadBytes = wsInfo->totalLength;\n\t\t}\n\n\t/* Process any remaining payload data if required */\n\tif( payloadBytes > 0 )\n\t\t{\n\t\t/* Unmask the data if required */\n\t\tif( isServer )\n\t\t\t{\n\t\t\tstatus = unmaskData( buffer, payloadBytes, wsInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Adjust the total length by the number of bytes processed */\n\t\twsInfo->totalLength -= payloadBytes;\n\t\tENSURES( wsInfo->totalLength >= 0 && \\\n\t\t\t\t wsInfo->totalLength < MAX_BUFFER_SIZE - 1 );\n\t\t}\n\n\t/* If we've processed the entire buffer contents then let the caller \n\t   know via a special return code */\n\treturn( processedAllData ? OK_SPECIAL : payloadBytes );\n\t}\n\n/* Decode a WebSockets data packet inside a standard packet.  This takes \n   input data { buffer, bufSize } and processes one packet, returning the\n   new end-of-data position in *bufEnd and as return status either a byte\n   count of how much data was processed as part of the packet payload (with\n   further data available for processing) or OK_SPECIAL to indicate that the \n   entire buffer contents were processed and no further processing is \n   necessary */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint processInnerPacketFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT_BUFFER( bufSize, *bufEnd ) BYTE *buffer,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int bufSize,\n\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *bufEnd )\n\t{\n\tSSL_WS_INFO *wsInfo = &sessionInfoPtr->sessionSSL->wsInfo;\n\tSTREAM stream;\n\tconst BOOLEAN isServer = isServer( sessionInfoPtr ) ? TRUE : FALSE;\n\tconst int oldHeaderBufPos = wsInfo->headerBufPos;\n\tint bytesCopied, bytesFromBuffer, remainingData, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( buffer, bufSize ) );\n\tassert( isWritePtr( bufEnd, sizeof( int ) ) );\n\n\tstatic_assert( WS_HEADER_LENGTH_CLIENT <= SSL_WS_BUFSIZE,\n\t\t\t\t   \"WebSockets header buffer size\" );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\tREQUIRES( bufSize > 0 && bufSize < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*bufEnd = 0;\n\n\t/* If we're still in the middle of processing a packet, process it and \n\t   exit.  The test for this condition is based on there being no header\n\t   data in the process of being read, and length information (from a\n\t   previous header read) being available */\n\tif( wsInfo->headerBytesRequired <= 0 && wsInfo->totalLength > 0 )\n\t\t{\n\t\t*bufEnd = bufSize;\n\n\t\treturn( processPayload( buffer, bufSize, wsInfo, isServer ) );\n\t\t}\n\n\tDEBUG_DUMP_WS( buffer, bufSize );\n\n\t/* Read as much of the input data as we can into the header buffer */\n\tbytesCopied = min( SSL_WS_BUFSIZE - wsInfo->headerBufPos, bufSize );\n\tREQUIRES( boundsCheckZ( wsInfo->headerBufPos, bytesCopied, \n\t\t\t\t\t\t\tSSL_WS_BUFSIZE ) );\n\tmemcpy( wsInfo->headerBuffer + wsInfo->headerBufPos, buffer, \n\t\t\tbytesCopied );\n\twsInfo->headerBufPos += bytesCopied;\n\n\t/* If this is the start of a new header, process the type and \n\t   length-of-length information */\n\tif( wsInfo->headerBytesRequired <= 0 )\n\t\t{\n\t\t/* If there isn't at least a type and length-code field available \n\t\t   then we can't go any further */\n\t\tif( wsInfo->headerBufPos < 1 + 1 )\n\t\t\t{\n\t\t\t*bufEnd = 0;\n\t\t\treturn( OK_SPECIAL );\t/* All data consumed */\n\t\t\t}\n\n\t\tstatus = processFixedHeader( wsInfo, SESSION_ERRINFO, isServer );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's not enough data present to continue, we're done */\n\tif( wsInfo->headerBufPos < wsInfo->headerBytesRequired )\n\t\t{\n\t\t*bufEnd = 0;\n\t\treturn( OK_SPECIAL );\t\t/* All data consumed */\n\t\t}\n\n\t/* We've got all the data we need to process the header, remember how \n\t   many bytes we took from the buffer */\n\tbytesFromBuffer = wsInfo->headerBytesRequired - oldHeaderBufPos;\n\n\tsMemConnect( &stream, wsInfo->headerBuffer + WS_LENGTH_OFFSET,\n\t\t\t\t wsInfo->headerBytesRequired );\n\n\t/* Process any additional length information */\n\tstatus = processLength( &stream, wsInfo, SESSION_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\tDEBUG_PRINT(( \"Read %s (%X) WebSockets packet, length %ld.\\n\", \n\t\t\t\t  getPacketName( wsInfo->type ), wsInfo->type, \n\t\t\t\t  wsInfo->totalLength ));\n\n\t/* If we're the server, read the client's masking information */\n\tif( isServer )\n\t\t{\n\t\t/* Make sure that the data sent by the client has been masked \n\t\t   (because the spec says so, that's why) */\n\t\tif( !( wsInfo->headerBuffer[ WS_LENGTHCODE_OFFSET ] & WS_MASK_FLAG ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Client's WebSockets data isn't masked for %s packet\", \n\t\t\t\t\t  getPacketName( wsInfo->type ) ) );\n\t\t\t}\n\n\t\t/* Get the mask value */\n\t\tstatus = sread( &stream, wsInfo->mask, WS_MASK_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\twsInfo->maskPos = 0;\n\t\t}\n\n\tsMemDisconnect( &stream );\n\n\t/* Move any remaining data down in the input buffer */\n\tremainingData = bufSize - bytesFromBuffer;\n\tif( remainingData > 0 )\n\t\t{\n\t\tREQUIRES( boundsCheck( bytesFromBuffer, remainingData, bufSize ) );\n\t\tmemmove( buffer, buffer + bytesFromBuffer, remainingData );\n\t\t}\n\t*bufEnd = remainingData;\n\n\t/* We've finished processing the header, reset the header information */\n\tmemset( wsInfo->headerBuffer, 0, SSL_WS_BUFSIZE );\n\twsInfo->headerBufPos = wsInfo->headerBytesRequired = 0;\n\n\t/* Process the remaning data in the buffer */\n\treturn( processPayload( buffer, remainingData, wsInfo, isServer ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWebSockets Write Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send additional out-of-band data packets inside a WebSockets stream */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int sendExtraPacketData( INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int bufSize,\n\t\t\t\t\t\t\t\tINOUT SSL_WS_INFO *wsInfo,\n\t\t\t\t\t\t\t\tconst BOOLEAN isServer )\n\t{\n\tint length = 0;\n\n\tassert( isWritePtr( buffer, bufSize ) );\n\tassert( isWritePtr( wsInfo, sizeof( SSL_WS_INFO ) ) );\n\n\tREQUIRES( bufSize > 0 && bufSize < MAX_BUFFER_SIZE );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Send a Pong to the other side if required.  The spec is unclear over\n\t   whether it's necessary to send a Pong if a Close is also being sent,\n\t   since it doesn't make much sense to send one if we've closing the\n\t   channel we only send one if there's no Close pending */\n\tif( wsInfo->sendPong && !wsInfo->sendClose )\n\t\t{\n\t\t/* If there's no room for a Pong packet, return */\n\t\tif( WS_PONG_SIZE > bufSize )\n\t\t\treturn( 0 );\n\n\t\t/* Send an almighty Pong to the other side */\n\t\tREQUIRES( rangeCheck( WS_PONG_SIZE, 1, bufSize ) );\n\t\tmemcpy( buffer, \n\t\t\t\tisServer ? WS_PONG_DATA_SERVER : WS_PONG_DATA_CLIENT, \n\t\t\t\tWS_PONG_SIZE );\n\t\tlength += WS_PONG_SIZE;\n\t\twsInfo->sendPong = FALSE;\n\t\t}\n\n\t/* Send a close to the other side if required */\n\tif( wsInfo->sendClose )\n\t\t{\n\t\t/* If there's no room for a Close packet, return */\n\t\tif( length + WS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE > bufSize )\n\t\t\treturn( 0 );\n\n\t\t/* Send a Close to the other side */\n\t\tREQUIRES( rangeCheck( length + WS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE, 1, \n\t\t\t\t\t\t\t  bufSize ) );\n\t\tmemcpy( buffer + length, \n\t\t\t\tisServer ? WS_CLOSE_DATA_SERVER : WS_CLOSE_DATA_CLIENT, \n\t\t\t\tWS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE );\n\t\tif( !isServer )\n\t\t\t{\n\t\t\tint i, LOOP_ITERATOR;\n\n\t\t\t/* If we're the client then we have to mask the Close payload \n\t\t\t   data before sending it */\n\t\t\tLOOP_SMALL( i = 0, i < WS_CLOSE_DATA_SIZE, i++ )\n\t\t\t\t{\n\t\t\t\tbuffer[ length + WS_CLOSE_SIZE + i ] ^= \\\n\t\t\t\t\t\t\t\twsInfo->mask[ i % WS_MASK_SIZE ];\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\t}\n\t\tlength += WS_CLOSE_SIZE + WS_CLOSE_DATA_SIZE;\n\t\twsInfo->sendClose = FALSE;\n\t\t}\n\n\treturn( length );\n\t}\n\n/* Prepare a WebSockets data packet inside a standard packet */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInnerHeaderFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t\t  IN_DATALENGTH const int bufSize )\n\t{\n\tSTREAM stream;\n\tconst int headerSize = isServer( sessionInfoPtr ) ? \n\t\t\t\t\t\t   WS_HEADER_LENGTH_SERVER : WS_HEADER_LENGTH_CLIENT;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( buffer, bufSize ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\tREQUIRES( bufSize >= headerSize && bufSize < MAX_BUFFER_SIZE );\n\n\t/* Write a WebSockets header.  We always write a 16-bit length since \n\t   this is the most likely value, it can't be longer than 16 bits due to \n\t   the TLS packet size limit, and if it's less it'll only be a hundred\n\t   or so bytes so we move it down when we wrap the packet to get an \n\t   8-bit length */\n\tsMemOpen( &stream, buffer, headerSize );\n\tsputc( &stream, WS_PACKET_BINARY );\n\tif( isServer( sessionInfoPtr ) )\n\t\tsputc( &stream, WS_LENGTH_16BIT );\n\telse\n\t\tsputc( &stream, WS_MASK_FLAG | WS_LENGTH_16BIT );\n\tstatus = writeUint16( &stream, 0 );\t\t/* Placeholder */\n\tif( !isServer( sessionInfoPtr ) )\n\t\tstatus = swrite( &stream, WS_MASK_VALUE, WS_MASK_SIZE );\n\tENSURES( cryptStatusOK( status ) );\n\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( length );\n\t}\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint prepareInnerPacketFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int bufSize,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int dataSize )\n\t{\n\tSSL_WS_INFO *wsInfo = &sessionInfoPtr->sessionSSL->wsInfo;\n\tSTREAM stream;\n\tconst BYTE *maskPtr = buffer + WS_MASK_OFFSET;\n\tconst BOOLEAN isServer = isServer( sessionInfoPtr ) ? TRUE : FALSE;\n\tint headerSize = isServer ? WS_HEADER_LENGTH_SERVER : \\\n\t\t\t\t\t\t\t\tWS_HEADER_LENGTH_CLIENT;\n\tconst int payloadSize = dataSize - headerSize;\n\tint extraDataLength = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( buffer, bufSize ) );\n\n\tREQUIRES( sanityCheckSessionSSLWS( sessionInfoPtr ) );\n\tREQUIRES( bufSize >= headerSize && bufSize < MAX_BUFFER_SIZE );\n\tREQUIRES( dataSize >= headerSize && dataSize <= bufSize );\n\tREQUIRES( isIntegerRange( payloadSize ) );\n\n\t/* Add the length field as required */\n\tif( payloadSize > WS_LENGTH_THRESHOLD )\n\t\t{\n\t\t/* If there are more than WS_LENGTH_THRESHOLD bytes in the buffer \n\t\t   then we can write the length field directly into the header */\n\t\tsMemOpen( &stream, buffer + WS_LENGTH_OFFSET, UINT16_SIZE );\n\t\tstatus = writeUint16( &stream, payloadSize );\n\t\tsMemDisconnect( &stream );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\telse\n\t\t{\n\t\tconst int bytesToMove = isServer? payloadSize : \\\n\t\t\t\t\t\t\t\t\t\t  WS_MASK_SIZE + payloadSize;\n\n\t\t/* There are WS_LENGTH_THRESHOLD bytes or less in the buffer so the\n\t\t   length can be encoded as part of the header, move the payload \n\t\t   data down and insert the length byte at the appropriate \n\t\t   location */\n\t\tREQUIRES( boundsCheck( WS_LENGTH_OFFSET + UINT16_SIZE, bytesToMove, \n\t\t\t\t\t\t\t   dataSize ) );\n\t\tmemmove( buffer + WS_LENGTH_OFFSET, \n\t\t\t\t buffer + WS_LENGTH_OFFSET + UINT16_SIZE, bytesToMove );\n\t\tbuffer[ WS_LENGTHCODE_OFFSET ] = intToByte( payloadSize );\n\t\tif( !isServer )\n\t\t\tbuffer[ WS_LENGTHCODE_OFFSET ] |= WS_MASK_FLAG;\n\n\t\t/* Since we've just eliminated the length field, we need to adjust \n\t\t   various values to match */\n\t\tmaskPtr -= UINT16_SIZE;\n\t\theaderSize -= UINT16_SIZE;\n\t\t}\n\n\t/* If we're the client then we have to mask the payload */\n\tif( !isServer )\n\t\t{\n\t\tBYTE *payloadPtr = buffer + headerSize;\n\n\t\t/* Mask the payload contents */\n\t\tLOOP_MAX( i = 0, i < payloadSize, i++ )\n\t\t\tpayloadPtr[ i ] ^= maskPtr[ i % WS_MASK_SIZE ];\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Finally, if there's a response to a recent out-of-band packet \n\t   required, append it to the packet data.  This is more or less the \n\t   best that we can do in terms of handling out-of-band chatter, we can\n\t   only send data to the peer when the caller initiates it, so \n\t   piggybacking the out-of-band data on a standard packet write is the\n\t   best strategy for dealing with this.  Luckily the spec accommodates\n\t   this in the case of the Ping packet by not requiring an immediate \n\t   response to a Ping, allowing the receiver to collapse multiple Pings \n\t   into a single response, and instructing the peer to ignore \n\t   unsolicited Pongs, which our response may seem to be if it's delayed \n\t   too long */\n\tif( ( wsInfo->sendPong || wsInfo->sendClose ) && \\\n\t\t( headerSize + payloadSize < bufSize ) )\n\t\t{\n\t\tint length;\n\n\t\tstatus = length = sendExtraPacketData( buffer + headerSize + payloadSize,\n\t\t\t\t\t\t\t\t\t\t\t   bufSize - ( headerSize + payloadSize ),\n\t\t\t\t\t\t\t\t\t\t\t   wsInfo, isServer );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\textraDataLength += length;\n\t\t}\n\n\treturn( headerSize + payloadSize + extraDataLength );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSub-protocol Access Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSubprotocolWebSockets( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->activateInnerSubprotocolFunction, \n\t\t\t\t   activateWebSocketsServer );\n\t\t}\n\telse\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->activateInnerSubprotocolFunction, \n\t\t\t\t   activateWebSocketsClient );\n\t\t}\n\tFNPTR_SET( sessionInfoPtr->closeInnerSubprotocolFunction, \n\t\t\t   closeWebSockets );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_WEBSOCKETS */\n"
  },
  {
    "path": "deps/cl345/session/session.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Session Support Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Reset the state of a request/response session for reuse so that it can\n   process another request or response */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void cleanupReqResp( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tconst BOOLEAN preTransaction )\n\t{\n\tconst BOOLEAN isServer = isServer( sessionInfoPtr ) ? TRUE : FALSE;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES_V( preTransaction == TRUE || preTransaction == FALSE );\n\n\t/* Clean up server requests left over from a previous transaction or \n\t   that have been created by the just-completed transaction */\n\tif( isServer && sessionInfoPtr->iCertRequest != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCertRequest,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCertRequest = CRYPT_ERROR;\n\t\t}\n\n\t/* Clean up client/server responses left over from a previous\n\t   transaction */\n\tif( preTransaction && sessionInfoPtr->iCertResponse != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\t\t}\n\t}\n\n/* Initialise network connection information based on the contents of the\n   session object */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSessionNetConnectInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   OUT NET_CONNECT_INFO *connectInfo )\n\t{\n\tconst ATTRIBUTE_LIST *clientNamePtr, *serverNamePtr, *portInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( connectInfo, sizeof( NET_CONNECT_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\tinitNetConnectInfo( connectInfo, sessionInfoPtr->ownerHandle,\n\t\t\t\tsessionInfoPtr->readTimeout, sessionInfoPtr->connectTimeout,\n\t\t\t\t( sessionInfoPtr->networkSocket != CRYPT_ERROR ) ? \\\n\t\t\t\t\tNET_OPTION_NETWORKSOCKET : NET_OPTION_HOSTNAME );\n\n\t/* If there are subprotocol-specific options present, set them up */\n#ifdef USE_EAP\n\tif( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\t\tconst ATTRIBUTE_LIST *keyPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\t\t\n\t\tENSURES( userNamePtr != NULL && keyPtr != NULL );\n\n\t\tconnectInfo->authName = userNamePtr->value;\n\t\tconnectInfo->authNameLength = userNamePtr->valueLength;\n\t\tconnectInfo->authKey = userNamePtr->value;\n\t\tconnectInfo->authKeyLength = userNamePtr->valueLength;\n\t\t}\n#endif /* USE_EAP */\n\n\t/* If the user has supplied the network transport information, there's\n\t   nothing further to do */\n\tif( sessionInfoPtr->networkSocket != CRYPT_ERROR )\n\t\t{\n\t\tconnectInfo->networkSocket = sessionInfoPtr->networkSocket;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there are explicit client and/or server names set, record them.  \n\t   For a client the server name is the remote system to connect to\n\t   and the client name is the optional local interface to bind to, for\n\t   the server the server name is the optional local interface to bind\n\t   to */\n\tclientNamePtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_CLIENT_NAME );\n\tserverNamePtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_NAME );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tif( serverNamePtr != NULL )\n\t\t\t{\n\t\t\tconnectInfo->interface = serverNamePtr->value;\n\t\t\tconnectInfo->interfaceLength = serverNamePtr->valueLength;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tREQUIRES( serverNamePtr != NULL );\n\n\t\tconnectInfo->name = serverNamePtr->value;\n\t\tconnectInfo->nameLength = serverNamePtr->valueLength;\n\t\tif( clientNamePtr != NULL )\n\t\t\t{\n\t\t\tconnectInfo->interface = clientNamePtr->value;\n\t\t\tconnectInfo->interfaceLength = clientNamePtr->valueLength;\n\t\t\t}\n\t\t}\n\n\t/* If there's an explicit port set, connect/bind to it, otherwise use the\n\t   default port for the protocol */\n\tif( ( portInfoPtr = \\\n\t\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_PORT ) ) != NULL )\n\t\tconnectInfo->port = portInfoPtr->intValue;\n\telse\n\t\t{\n\t\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\t\tENSURES( protocolInfo != NULL );\n\n\t\tconnectInfo->port = protocolInfo->port;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Make sure that mutually exclusive session attributes haven't been set.\n   The checks performed are:\n\n\tCRYPT_SESSINFO_REQUEST\t\t-> !CRYPT_SESSINFO_REQUEST, \n\t\t\t\t\t\t\t\t   !CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t   !CRYPT_SESSINFO_CMP_PRIVKEYSET\n\n\tCRYPT_SESSINFO_PRIVATEKEY\t-> !CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t   !CRYPT_SESSINFO_CMP_PRIVKEYSET\n\n\tCRYPT_SESSINFO_CACERTIFICATE-> !CRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t\t\t\t   !CRYPT_SESSINFO_SERVER_FINGERPRINT\n\n\tCRYPT_SESSINFO_SERVER_FINGERPRINT\n\t\t\t\t\t\t\t\t-> !CRYPT_SESSINFO_SERVER_FINGERPRINT,\n\t\t\t\t\t\t\t\t   !CRYPT_SESSINFO_CACERTIFICATE */\n\n#define CHECK_ATTR_NONE\t\t\t0x00\n#define CHECK_ATTR_REQUEST\t\t0x01\n#define CHECK_ATTR_PRIVKEY\t\t0x02\n#define CHECK_ATTR_PRIVKEYSET\t0x04\n#define CHECK_ATTR_CACERT\t\t0x08\n#define CHECK_ATTR_FINGERPRINT\t0x10\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkAttributesConsistent( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute )\n\t{\n\tstatic const MAP_TABLE excludedAttrTbl[] = {\n\t\t{ CRYPT_SESSINFO_REQUEST, \n\t\t\tCHECK_ATTR_REQUEST | CHECK_ATTR_PRIVKEY | CHECK_ATTR_PRIVKEYSET },\n\t\t{ CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\tCHECK_ATTR_PRIVKEY | CHECK_ATTR_PRIVKEYSET },\n\t\t{ CRYPT_SESSINFO_CACERTIFICATE, \n\t\t\tCHECK_ATTR_CACERT | CHECK_ATTR_FINGERPRINT },\n\t\t{ CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1, \n\t\t\tCHECK_ATTR_FINGERPRINT | CHECK_ATTR_CACERT },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 } \n\t\t};\n\tint flags = 0, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES_B( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES_B( attribute == CRYPT_SESSINFO_REQUEST || \\\n\t\t\t\tattribute == CRYPT_SESSINFO_PRIVATEKEY || \\\n\t\t\t\tattribute == CRYPT_SESSINFO_CACERTIFICATE || \\\n\t\t\t\tattribute == CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );\n\n\t/* Find the excluded-attribute information for this attribute */\n\tstatus = mapValue( attribute, &flags, excludedAttrTbl,\n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( excludedAttrTbl, MAP_TABLE ) );\n\tENSURES_B( cryptStatusOK( status  ) );\n\n\t/* Make sure that none of the excluded attributes are present */\n\tif( ( flags & CHECK_ATTR_REQUEST ) && \\\n\t\tsessionInfoPtr->iCertRequest != CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( FALSE );\n\t\t}\n\tif( ( flags & CHECK_ATTR_PRIVKEYSET ) && \\\n\t\tsessionInfoPtr->privKeyset != CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( FALSE );\n\t\t}\n\tif( ( flags & CHECK_ATTR_CACERT ) && \\\n\t\tsessionInfoPtr->iAuthInContext != CRYPT_ERROR )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( FALSE );\n\t\t}\n\tif( ( flags & CHECK_ATTR_FINGERPRINT ) && \\\n\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 ) != NULL )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\treturn( FALSE );\n\t\t}\n\t\n\treturn( TRUE );\n\t}\n\n/* Copy session-level error information to an external ERROR_INFO structure.\n   This is used to return error information to higher-level streams layered\n   over a transport session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSessionErrorInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tcopyErrorInfo( errorInfo, &sessionInfoPtr->errorInfo );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check that a server's certificate is currently valid.  This self-check \n   avoids ugly silent failures where everything appears to work just fine on \n   the server side but the client gets invalid data back */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint checkServerCertValid( const CRYPT_CERTIFICATE iServerKey,\n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_CERTIFICATE iServerCert;\n\tCRYPT_ERRTYPE_TYPE errorType DUMMY_INIT;\n\tCRYPT_ATTRIBUTE_TYPE errorLocus DUMMY_INIT;\n\tstatic const int complianceLevelStandard = CRYPT_COMPLIANCELEVEL_STANDARD;\n\tint complianceLevel, status;\n\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iServerKey ) );\n\n\tstatus = krnlSendMessage( iServerKey, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &complianceLevel, \n\t\t\t\t\t\t\t  CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We can't do much more if we can't even get the initial compliance \n\t\t   level */\n\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* Check whether the certificate is valid at a standard level of \n\t   compliance, which catches expired certificates and other obvious\n\t   problems */\n\tkrnlSendMessage( iServerKey, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &complianceLevelStandard, \n\t\t\t\t\t CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tstatus = krnlSendMessage( iServerKey, IMESSAGE_CHECK, NULL, \n\t\t\t\t\t\t\t  MESSAGE_CHECK_CERT );\n\tkrnlSendMessage( iServerKey, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &complianceLevel, \n\t\t\t\t\t CRYPT_OPTION_CERT_COMPLIANCELEVEL );\n\tif( cryptStatusOK( status ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The certificate associated with the key isn't valid, get the \n\t   certificate (since otherwise we'd be querying the key rather than the\n\t   certificate) and fetch the extended error information */\n\tstatus = krnlSendMessage( iServerKey, IMESSAGE_GETDEPENDENT, \n\t\t\t\t\t\t\t  &iServerCert, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint value;\n\n\t\tstatus = krnlSendMessage( iServerCert, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &value, CRYPT_ATTRIBUTE_ERRORLOCUS );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorLocus = value;\t/* int to enum */\n\t\t\tstatus = krnlSendMessage( iServerCert, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  &value, CRYPT_ATTRIBUTE_ERRORTYPE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\terrorType = value;\t/* int to enum */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we can't get extended error information then there's not much \n\t\t   more that we can do */\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"Server certificate is invalid\" ) );\n\t\t}\n\n\t/* Try and get more\tinformation on common errors and report them to the\n\t   caller */\n\tif( errorType == CRYPT_ERRTYPE_CONSTRAINT )\n\t\t{\n\t\tswitch( errorLocus )\n\t\t\t{\n\t\t\tcase CRYPT_CERTINFO_VALIDFROM:\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t\t  \"Server certificate is not valid yet\" ) );\n\n\t\t\tcase CRYPT_CERTINFO_VALIDTO:\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t\t  \"Server certificate has expired\" ) );\n\n\t\t\tcase CRYPT_CERTINFO_KEYUSAGE:\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t\t  \"Server certificate's keyUsage doesn't allow it \"\n\t\t\t\t\t\t  \"to be used\" ) );\n\t\t\t}\n\t\t}\n\n\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t  \"Server certificate is invalid, error type %d, error \"\n\t\t\t  \"locus %d\", errorType, errorLocus ) );\n\t}\n\n/* Padding in order to defeat traffic analysis is extremely problematic.  \n   The simplistic approach of adding random padding provides little more \n   than warm fuzzies since it falls almost trivially to statistical \n   classifiers like Bayesian or support vector machines.  In fact almost any \n   attempt to defeat traffic analysis with low overhead, including random \n   padding, linear padding (padding to the nearest 128 bytes), exponential \n   padding (padding to the nearest power of two), mice/elephant padding \n   (padding short packets to 128 bytes and long ones to the MTU), straight \n   padding to the MTU, and padding by a random multiple of 8 or 16 bytes, \n   doesn't work (see \"Peek-a-Book, I Still See You: Why Efficient Traffic \n   Analysis Countermeasures Fail\" by Dyer, Coult, Ristenpart and Shrimpton).\n\n   It's only when quite complex traffic morphing, sending fixed-length \n   packets at fixed intervals and the like, is applied and reaches an \n   overhead of 400% that things start getting tricky for an attacker, or at \n   least an attacker using a straightforward Bayesian or SVM classifier.\n\n   This doesn't leave much choice in the way of padding, since no matter \n   what we do it won't be terribly effective.  The best option is to choose \n   the variant with the lowest overhead and use that, since it has at least \n   a small amount of effect.  This is linear padding, but we pad based on\n   message size instead of 128 because we're typically used in embedded \n   environments which both use shorter messages and often have bandwidth \n   constraints.  So the padding is:\n\n\tlen = 0 ... 64 bytes -> pad to nearest 16;\n\tlen = 65 ... 1024 bytes -> pad to nearest 64;\n\tlen > 1024 bytes -> pad to nearest 128;\n   \n   Note that we can't pad more than 256 bytes (or in some cases 255 due to \n   one byte being needed for the length) because most padding schemes only \n   allow a single-byte pad length value, so we use 128 bytes */\n\nCHECK_RETVAL_LENGTH \\\nint getPaddedSize( IN_DATALENGTH_Z const int length )\n\t{\n\tREQUIRES( length >= 0 && length < MAX_BUFFER_SIZE );\n\n\tif( length <= 64 )\n\t\treturn( roundUp( length, 16 ) );\n\tif( length <= 1024 )\n\t\treturn( roundUp( length, 64 ) );\n\treturn( roundUp( length, 128 ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Activation Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check client/server-specific required values */\n\nCHECK_RETVAL_ENUM( CRYPT_ATTRIBUTE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic CRYPT_ATTRIBUTE_TYPE checkClientParameters( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst BOOLEAN serverNamePresent = \\\n\t\t\tfindSessionInfo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_NAME ) != NULL ? TRUE : FALSE;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Make sure that the network comms parameters are present */\n\tif( sessionInfoPtr->networkSocket == CRYPT_ERROR && \\\n\t\t!serverNamePresent )\n\t\treturn( CRYPT_SESSINFO_SERVER_NAME );\n\n\t/* Make sure that the username + password and/or user private key are \n\t   present if required */\n\tif( ( sessionInfoPtr->clientReqAttrFlags & SESSION_NEEDS_USERID ) && \\\n\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME ) == NULL )\n\t\treturn( CRYPT_SESSINFO_USERNAME );\n\tif( ( sessionInfoPtr->clientReqAttrFlags & SESSION_NEEDS_PASSWORD ) && \\\n\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD ) == NULL )\n\t\t{\n\t\t/* There's no password present, see if we can use a private key as \n\t\t   an alternative */\n\t\tif( !( sessionInfoPtr->clientReqAttrFlags & \\\n\t\t\t   SESSION_NEEDS_KEYORPASSWORD ) || \\\n\t\t\tsessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t\treturn( CRYPT_SESSINFO_PASSWORD );\n\t\t}\n\tif( ( sessionInfoPtr->clientReqAttrFlags & SESSION_NEEDS_PRIVATEKEY ) && \\\n\t\tsessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t{\n\t\t/* There's no private key present, see if we can use a password as \n\t\t   an alternative */\n\t\tif( !( sessionInfoPtr->clientReqAttrFlags & \\\n\t\t\t   SESSION_NEEDS_KEYORPASSWORD ) || \\\n\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD ) == NULL )\n\t\t\treturn( CRYPT_SESSINFO_PRIVATEKEY );\n\t\t}\n\n\t/* Make sure that request/response protocol data is present if required */\n\tif( ( sessionInfoPtr->clientReqAttrFlags & SESSION_NEEDS_REQUEST ) && \\\n\t\tsessionInfoPtr->iCertRequest == CRYPT_ERROR )\n\t\treturn( CRYPT_SESSINFO_REQUEST );\n\n\t/* Check for subprotocol-specific information */\n#ifdef USE_EAP\n\tif( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS )\n\t\t{\n\t\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME ) == NULL )\n\t\t\treturn( CRYPT_SESSINFO_USERNAME );\n\t\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD ) == NULL )\n\t\t\treturn( CRYPT_SESSINFO_PASSWORD );\n\t\t}\n#endif /* USE_EAP */\n\n\treturn( CRYPT_ATTRIBUTE_NONE );\n\t}\n\nCHECK_RETVAL_ENUM( CRYPT_ATTRIBUTE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic CRYPT_ATTRIBUTE_TYPE checkServerParameters( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Make sure that server key and keyset information is present if \n\t   required */\n\tif( ( sessionInfoPtr->serverReqAttrFlags & SESSION_NEEDS_PRIVATEKEY ) && \\\n\t\tsessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t{\n\t\t/* There's no private key present, see if we can use a username +\n\t\t   password as an alternative */\n\t\tif( !( sessionInfoPtr->serverReqAttrFlags & \\\n\t\t\t   SESSION_NEEDS_KEYORPASSWORD ) || \\\n\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD ) == NULL )\n\t\t\treturn( CRYPT_SESSINFO_PRIVATEKEY );\n\t\t}\n\tif( ( sessionInfoPtr->serverReqAttrFlags & SESSION_NEEDS_KEYSET ) && \\\n\t\tsessionInfoPtr->cryptKeyset == CRYPT_ERROR )\n\t\treturn( CRYPT_SESSINFO_KEYSET );\n\n\treturn( CRYPT_ATTRIBUTE_NONE );\n\t}\n\n/* Activate the network connection for a session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int activateConnection( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE errorAttribute;\n\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( protocolInfo != NULL );\n\n\t/* Make sure that everything is set up ready to go */\n\terrorAttribute = isServer( sessionInfoPtr ) ? \\\n\t\t\t\t\t checkServerParameters( sessionInfoPtr ) : \\\n\t\t\t\t\t checkClientParameters( sessionInfoPtr );\n\tif( errorAttribute != CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, errorAttribute, \n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\tENSURES( isServer( sessionInfoPtr ) || \\\n\t\t\t findSessionInfo( sessionInfoPtr, \n\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME ) != NULL || \\\n\t\t\t sessionInfoPtr->networkSocket != CRYPT_ERROR );\n\tENSURES( findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_PORT ) != NULL || \\\n\t\t\t protocolInfo->port > 0 );\n\n\t/* Allocate the send and receive buffers if necessary.  The send buffer\n\t   isn't used for request-response session types that use the receive\n\t   buffer for both outgoing and incoming data so we only allocate it if\n\t   it's actually required */\n\tif( sessionInfoPtr->sendBuffer == NULL )\n\t\t{\n\t\tREQUIRES( sessionInfoPtr->receiveBufSize >= MIN_BUFFER_SIZE && \\\n\t\t\t\t  sessionInfoPtr->receiveBufSize < MAX_BUFFER_SIZE );\n\t\tREQUIRES( ( sessionInfoPtr->sendBufSize >= MIN_BUFFER_SIZE && \\\n\t\t\t\t\tsessionInfoPtr->sendBufSize < MAX_BUFFER_SIZE ) || \\\n\t\t\t\t  sessionInfoPtr->sendBufSize == CRYPT_UNUSED );\n\n\t\tsessionInfoPtr->receiveBuffer = \\\n\t\t\t\t\t\t\tsafeBufferAlloc( sessionInfoPtr->receiveBufSize );\n\t\tif( sessionInfoPtr->receiveBuffer == NULL )\n\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\tif( sessionInfoPtr->sendBufSize != CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* When allocating the send buffer we use the size given for the\n\t\t\t   receive buffer since the user may have overridden the default\n\t\t\t   buffer size */\n\t\t\tsessionInfoPtr->sendBuffer = \\\n\t\t\t\t\t\t\tsafeBufferAlloc( sessionInfoPtr->receiveBufSize );\n\t\t\tif( sessionInfoPtr->sendBuffer == NULL )\n\t\t\t\t{\n\t\t\t\tsafeBufferFree( sessionInfoPtr->receiveBuffer );\n\t\t\t\tsessionInfoPtr->receiveBuffer = NULL;\n\t\t\t\treturn( CRYPT_ERROR_MEMORY );\n\t\t\t\t}\n\t\t\tsessionInfoPtr->sendBufSize = sessionInfoPtr->receiveBufSize;\n\t\t\t}\n\t\t}\n\tENSURES( sessionInfoPtr->receiveBuffer != NULL && \\\n\t\t\t sessionInfoPtr->receiveBufSize >= MIN_BUFFER_SIZE && \\\n\t\t\t sessionInfoPtr->receiveBufSize < MAX_BUFFER_SIZE );\n\tENSURES( sessionInfoPtr->sendBufSize == CRYPT_UNUSED || \\\n\t\t\t sessionInfoPtr->sendBuffer != NULL );\n\n\t/* Set timeouts if they're not set yet.  If there's an error then we use\n\t   the default value rather than aborting the entire session because of \n\t   a minor difference in timeout values, although we also warn the \n\t   caller in debug mode */\n\tif( sessionInfoPtr->connectTimeout == CRYPT_ERROR )\n\t\t{\n\t\tint timeout;\n\n\t\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_CONNECTTIMEOUT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tsessionInfoPtr->connectTimeout = timeout;\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't get connect timeout config value\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tsessionInfoPtr->connectTimeout = 30;\n\t\t\t}\n\t\t}\n\tif( sessionInfoPtr->readTimeout == CRYPT_ERROR )\n\t\t{\n\t\tint timeout;\n\n\t\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_READTIMEOUT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tsessionInfoPtr->readTimeout = timeout;\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't get read timeout config value\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tsessionInfoPtr->readTimeout = 30;\n\t\t\t}\n\t\t}\n\tif( sessionInfoPtr->writeTimeout == CRYPT_ERROR )\n\t\t{\n\t\tint timeout;\n\n\t\tstatus = krnlSendMessage( sessionInfoPtr->ownerHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &timeout,\n\t\t\t\t\t\t\t\t  CRYPT_OPTION_NET_WRITETIMEOUT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tsessionInfoPtr->writeTimeout = timeout;\n\t\telse\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't get write timeout config value\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\tsessionInfoPtr->writeTimeout = 30;\n\t\t\t}\n\t\t}\n\n\t/* Wait for any async driver binding to complete.  We can delay this\n\t   until this very late stage because no networking functionality is\n\t   used until this point */\n\tif( !krnlWaitSemaphore( SEMAPHORE_DRIVERBIND ) )\n\t\t{\n\t\t/* The kernel is shutting down, bail out */\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\t\t}\n\n\t/* If this is the first time that we've got here, activate the session */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN ) )\n\t\t{\n\t\tconst SES_CONNECT_FUNCTION connectFunction = \\\n\t\t\t\t\t( SES_CONNECT_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->connectFunction );\n\n\t\tREQUIRES( !TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t\t  SESSION_FLAG_ISOPEN ) );\n\t\tREQUIRES( connectFunction != NULL );\n\n\t\tstatus = connectFunction( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If there's sub-protocol selected, activate that as well */\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_NONE && \\\n\t\tFNPTR_ISSET( sessionInfoPtr->activateOuterSubprotocolFunction ) )\n\t\t\t{\n\t\t\tconst SES_ACTIVATESUBPROTOCOL_FUNCTION activateSubprotocolFunction = \\\n\t\t\t\t\t( SES_ACTIVATESUBPROTOCOL_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->activateOuterSubprotocolFunction ); \n\t\t\tREQUIRES( activateSubprotocolFunction != NULL );\n\n\t\t\tstatus = activateSubprotocolFunction( sessionInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Record the fact that the layered protocol has been \n\t\t\t   activated */\n\t\t\tSET_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t  SESSION_FLAG_SUBPROTOCOL_ACTIVE );\n\t\t\t}\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\n\t/* If it's a secure data transport session, complete the session state\n\t   setup.  Note that some sessions dynamically change the protocol \n\t   information during the handshake to accommodate parameters negotiated \n\t   during the handshake so we can only access the protocol information \n\t   after the handshake has completed */\n\tif( !protocolInfo->isReqResp )\n\t\t{\n\t\tconst SES_TRANSACT_FUNCTION transactFunction = \\\n\t\t\t\t\t( SES_TRANSACT_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->transactFunction );\n\n\t\tREQUIRES( transactFunction != NULL );\n\n\t\t/* Complete the session handshake to set up the secure state */\n\t\tstatus = transactFunction( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we need feedback from the user before we can complete the \n\t\t\t   handshake (for example checking a user name and password or \n\t\t\t   certificate supplied by the other side) we remain in the \n\t\t\t   handshake state so that the user can re-activate the session \n\t\t\t   after confirming (or denying) the check */\n\t\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN );\n\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Notify the kernel that the session key context is attached to the\n\t\t   session object.  Note that we increment its reference count even\n\t\t   though it's an internal object used only by the session because\n\t\t   otherwise it'll be automatically destroyed by the kernel as a\n\t\t   zero-reference dependent object when the session object is\n\t\t   destroyed (but before the session object itself since the context \n\t\t   is just a dependent object).  This automatic cleanup could cause \n\t\t   problems for lower-level session management code that tries to \n\t\t   work with the (apparently still-valid) handle, for example \n\t\t   protocols that need to encrypt a close-channel message on session \n\t\t   shutdown */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->objectHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETDEPENDENT,\n\t\t\t\t\t\t\t\t  &sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t  SETDEP_OPTION_INCREF );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Set up the buffer management variables */\n\t\tsessionInfoPtr->receiveBufPos = sessionInfoPtr->receiveBufEnd = 0;\n\t\tsessionInfoPtr->sendBufPos = sessionInfoPtr->sendBufStartOfs;\n\n\t\t/* For data transport sessions, partial reads and writes (that is,\n\t\t   sending and receiving partial packets in the presence of \n\t\t   timeouts) are permitted */\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_PARTIALREAD, TRUE );\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_PARTIALWRITE, TRUE );\n\t\t}\n\n\t/* The handshake has been completed, switch from the handshake timeout\n\t   to the data transfer timeout and remember that the session has been\n\t   successfully established */\n\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_HANDSHAKECOMPLETE, TRUE );\n\tCLEAR_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN );\n\tSET_FLAG( sessionInfoPtr->flags , SESSION_FLAG_ISOPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Activate a session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint activateSession( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst PROTOCOL_INFO *protocolInfo;\n\tSES_TRANSACT_FUNCTION transactFunction;\n\tint streamState, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\ttransactFunction = ( SES_TRANSACT_FUNCTION ) \\\n\t\t\t\t\t   FNPTR_GET( sessionInfoPtr->transactFunction );\n\tprotocolInfo = DATAPTR_GET( sessionInfoPtr->protocolInfo );\n\tREQUIRES( transactFunction != NULL );\n\tREQUIRES( protocolInfo != NULL );\n\n\t/* Activate the connection if necessary */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) )\n\t\t{\n\t\tATTRIBUTE_LIST *attributeList;\n\n\t\t/* If there's a sub-protocol selected, set up the acccess methods \n\t\t   for it */\n#if defined( USE_WEBSOCKETS ) \n\t\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_NONE )\n\t\t\t{\n\t\t\tswitch( sessionInfoPtr->subProtocol )\n\t\t\t\t{\n\t\t\t\tcase CRYPT_SUBPROTOCOL_WEBSOCKETS:\n\t\t\t\t\tstatus = setSubprotocolWebSockets( sessionInfoPtr );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase CRYPT_SUBPROTOCOL_EAPTTLS:\n\t\t\t\t\t/* This subprotocol type affects the network transport\n\t\t\t\t\t   mechanism so there's no subprotocol set at this \n\t\t\t\t\t   level */\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tretIntError();\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n#endif /* USE_WEBSOCKETS */\n\n\t\t/* Try and activate the session */\n\t\tstatus = activateConnection( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* The session activation succeeded, make sure that we don't try\n\t\t   and replace the ephemeral attributes established during the \n\t\t   session setup during any later operations.  This is used for\n\t\t   example when we're the server and the client provides us with \n\t\t   authentication data but the validity of the data hasn't been \n\t\t   confirmed yet by the user (see the comment about the \n\t\t   CRYPT_ENVELOPE_RESOURCE status in activateConnection()), normally \n\t\t   this would be deleted/overwritten when the session is recycled \n\t\t   but once the caller has confirmed it as being valid we lock it to \n\t\t   make sure that it won't be changed any more */\n\t\tREQUIRES( DATAPTR_ISVALID( sessionInfoPtr->attributeList ) );\n\t\tattributeList = DATAPTR_GET( sessionInfoPtr->attributeList );\n\t\tif( attributeList != NULL )\n\t\t\tlockEphemeralAttributes( attributeList );\n\t\t}\n\n\t/* If it's a secure data transport session it's up to the caller to move \n\t   data over it, and we're done */\n\tif( !protocolInfo->isReqResp )\n\t\t{\n\t\t/* If there's sub-protocol selected, activate that as well */\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\t\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_NONE && \\\n\t\t\tFNPTR_ISSET( sessionInfoPtr->activateInnerSubprotocolFunction ) )\n\t\t\t{\n\t\t\tconst SES_ACTIVATESUBPROTOCOL_FUNCTION activateSubprotocolFunction = \\\n\t\t\t\t\t( SES_ACTIVATESUBPROTOCOL_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->activateInnerSubprotocolFunction ); \n\t\t\tREQUIRES( activateSubprotocolFunction != NULL );\n\n\t\t\tstatus = activateSubprotocolFunction( sessionInfoPtr );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Record the fact that the layered protocol has been \n\t\t\t   activated */\n\t\t\tSET_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t  SESSION_FLAG_SUBPROTOCOL_ACTIVE );\n\t\t\t}\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Carry out a transaction on the request-response connection.  We\n\t   perform a cleanup of request/response data around the activation,\n\t   beforehand to catch data such as responses left over from a previous\n\t   transaction and afterwards to clean up ephemeral data such as\n\t   requests sent to a server */\n\tcleanupReqResp( sessionInfoPtr, TRUE );\n\tstatus = transactFunction( sessionInfoPtr );\n\tcleanupReqResp( sessionInfoPtr, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check whether the other side has indicated that it's closing the \n\t   stream and if it has, shut down our side as well and record the fact\n\t   that the session is now closed */\n\tstatus = sioctlGet( &sessionInfoPtr->stream, STREAM_IOCTL_CONNSTATE,\n\t\t\t\t\t\t&streamState, sizeof( int ) );\n\tif( cryptStatusError( status ) || !streamState )\n\t\t{\n\t\tconst SES_SHUTDOWN_FUNCTION shutdownFunction = \\\n\t\t\t\t\t( SES_SHUTDOWN_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->shutdownFunction );\n\t\tREQUIRES( shutdownFunction != NULL );\n\n\t\tCLEAR_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN );\n\t\tshutdownFunction( sessionInfoPtr );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a close notification.  This requires special-case handling because\n   it's not certain how long we should wait around for the close to happen.\n   If we're in the middle of a cryptlib shutdown then we don't want to wait \n   around forever since this would stall the overall shutdown, but if it's a \n   standard session shutdown then we should wait for at least a small amount \n   of time to ensure that all of the data is sent */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendCloseNotification( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER_OPT( length ) const void *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int length )\n\t{\n\tBOOLEAN isShutdown = FALSE;\n\tint dummy, status = CRYPT_OK;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( ( data == NULL && length == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, length ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( ( data == NULL && length == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( length ) ) );\n\n\t/* Determine whether we're being shut down as a part of a general \n\t   cryptlib shutdown or just a session shutdown.  We do this by trying \n\t   to read a configuration option from the owning user object, if the \n\t   kernel is in the middle of a shutdown it disallows all frivolous \n\t   messages so if we get a permission error then we're in the middle of \n\t   the shutdown */\n\tif( krnlSendMessage( sessionInfoPtr->ownerHandle, \n\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE, &dummy, \n\t\t\t\t\t\t CRYPT_OPTION_INFO_MAJORVERSION ) == CRYPT_ERROR_PERMISSION )\n\t\tisShutdown = TRUE;\n\n\t/* If necessary set a timeout sufficient to at least provide a chance of \n\t   sending our close notification and receiving the other side's ack of \n\t   the close, but without leading to excessive delays during the \n\t   shutdown */\n\tif( isShutdown )\n\t\t{\n\t\t/* It's a cryptlib-wide shutdown, try and get out as quickly as\n\t\t   possible */\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_WRITETIMEOUT, 2 );\n\t\t}\n\telse\n\t\t{\n\t\tint timeout;\n\n\t\t/* It's a standard session shutdown, wait around for at least five\n\t\t   seconds, but not more than fifteen */\n\t\tstatus = sioctlGet( &sessionInfoPtr->stream, \n\t\t\t\t\t\t\tSTREAM_IOCTL_WRITETIMEOUT, &timeout, \n\t\t\t\t\t\t\tsizeof( int ) );\n\t\tif( cryptStatusError( status ) || timeout < 5 )\n\t\t\ttimeout = 5;\n\t\telse\n\t\t\t{\n\t\t\tif( timeout > 15 )\n\t\t\t\ttimeout = 15;\n\t\t\t}\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_WRITETIMEOUT, \n\t\t\t\t   timeout );\n\t\t}\n\n\t/* Send the close notification to the peer */\n\tif( data != NULL )\n\t\tstatus = swrite( &sessionInfoPtr->stream, data, length );\n\n\t/* Close the send side of the connection if it's a cryptlib-internal \n\t   socket.  This is needed by some implementations that want to see a \n\t   FIN before they react to a shutdown notification, as well as being\n\t   a hint to the network code to flush any remaining data enqueued for\n\t   sending before the arrival of the full close.  If it's a user-managed \n\t   socket we can't perform the partial close since this would affect the \n\t   state of the socket as seen by the user, since the need to see the \n\t   FIN is fairly rare we choose this as the less problematic of the two \n\t   options */\n\tif( sessionInfoPtr->networkSocket == CRYPT_ERROR )\n\t\t{\n\t\tsioctlSet( &sessionInfoPtr->stream, STREAM_IOCTL_CLOSESENDCHANNEL, \n\t\t\t\t   TRUE );\n\t\t}\n\n\treturn( ( data == NULL || !cryptStatusError( status ) ) ? \\\n\t\t\tCRYPT_OK : status );\n\t}\n\n/* Close a session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint closeSession( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst SES_SHUTDOWN_FUNCTION shutdownFunction = \\\n\t\t\t\t\t( SES_SHUTDOWN_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->shutdownFunction );\n\tBOOLEAN shutdownSession = TRUE;\n\n\tREQUIRES( shutdownFunction != NULL );\n\n\t/* If the session hasn't been opened yet, there's nothing to do */\n\tif( !TEST_FLAG( sessionInfoPtr->flags,\n\t\t\t\t\tSESSION_FLAG_ISOPEN | SESSION_FLAG_PARTIALOPEN ) )\n\t\t{\n\t\t/* Even if the overall session hasn't been established yet, we may\n\t\t   still need to clean up the lower-level network connection \n\t\t   information before we exit */\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NETSESSIONOPEN ) )\n\t\t\t{\n\t\t\tsNetDisconnect( &sessionInfoPtr->stream );\n\t\t\tCLEAR_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NETSESSIONOPEN );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's an additional protocol layered over or under the base \n\t   protocol, deal with that as well */\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_NONE )\n\t\t{\n\t\t/* If there's an inner protocol present, shut that down as well */\n\t\tif( FNPTR_ISSET( sessionInfoPtr->closeInnerSubprotocolFunction ) )\n\t\t\t{\n\t\t\tconst SES_CLOSESUBPROTOCOL_FUNCTION closeSubprotocolFunction = \\\n\t\t\t\t\t( SES_CLOSESUBPROTOCOL_FUNCTION ) \\\n\t\t\t\t\tFNPTR_GET( sessionInfoPtr->closeInnerSubprotocolFunction ); \n\t\t\tREQUIRES( closeSubprotocolFunction != NULL );\n\n\t\t\t( void ) closeSubprotocolFunction( sessionInfoPtr );\n\t\t\t}\n\n\t\t/* If protocol management is handled by an outer protocol, don't \n\t\t   perform a session shutdown.  This is in theory rather nasty in \n\t\t   that an attacker who can spoof an unsecured outer protocol packet \n\t\t   can shut down the secured session, but in practice TLS sessions \n\t\t   are often shut down by the other side going away anyway, and in\n\t\t   the case of EAP it's a ping-pong protocol for which the other \n\t\t   side will notice a lack of messages and retry/fail the exchange */\n\t\tif( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS )\n\t\t\tshutdownSession = FALSE;\n\t\t}\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\n\t/* Shut down the session.  Nemo nisi mors */\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISCLOSINGDOWN );\n\tif( shutdownSession )\n\t\t( void ) shutdownFunction( sessionInfoPtr );\n\n\tsNetDisconnect( &sessionInfoPtr->stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDefault Action Handlers\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Default init/shutdown functions used when no session-specific ones are\n   provided */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int defaultClientStartupFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tNET_CONNECT_INFO connectInfo;\n\tSTREAM_PROTOCOL_TYPE protocolType = STREAM_PROTOCOL_TCP;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n#ifdef USE_HTTP\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISHTTPTRANSPORT ) )\n\t\tprotocolType = STREAM_PROTOCOL_HTTP;\n#endif /* USE_HTTP */\n#ifdef USE_EAP\n\tif( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS ) \n\t\tprotocolType = STREAM_PROTOCOL_EAP;\n#endif /* USE_EAP */\n\n\t/* Connect to the server */\n\tstatus = initSessionNetConnectInfo( sessionInfoPtr, &connectInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sNetConnect( &sessionInfoPtr->stream, protocolType,\n\t\t\t\t\t\t  &connectInfo, &sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NETSESSIONOPEN );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int defaultServerStartupFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tNET_CONNECT_INFO connectInfo;\n\tSTREAM_PROTOCOL_TYPE protocolType = STREAM_PROTOCOL_TCP;\n\tint nameLen, port, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n#ifdef USE_HTTP\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISHTTPTRANSPORT ) )\n\t\tprotocolType = STREAM_PROTOCOL_HTTP;\n#endif /* USE_HTTP */\n#ifdef USE_EAP\n\tif( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS )\n\t\tprotocolType = STREAM_PROTOCOL_EAP;\n#endif /* USE_EAP */\n\n\t/* Wait for a client connection */\n\tstatus = initSessionNetConnectInfo( sessionInfoPtr, &connectInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sNetListen( &sessionInfoPtr->stream, protocolType,\n\t\t\t\t\t\t &connectInfo, &sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_NETSESSIONOPEN );\n\n\t/* Save the client details for the caller, using the (always-present)\n\t   receive buffer as the intermediate store */\n\tstatus = sioctlGet( &sessionInfoPtr->stream, \n\t\t\t\t\t\tSTREAM_IOCTL_GETCLIENTNAMELEN, \n\t\t\t\t\t\t&nameLen, sizeof( int ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = sioctlGet( &sessionInfoPtr->stream, \n\t\t\t\t\t\t\tSTREAM_IOCTL_GETCLIENTNAME,\n\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* No client information available, exit */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tstatus = addSessionInfoS( sessionInfoPtr, CRYPT_SESSINFO_CLIENT_NAME, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, nameLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sioctlGet( &sessionInfoPtr->stream, STREAM_IOCTL_GETCLIENTPORT, \n\t\t\t\t\t\t&port, sizeof( int ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* No port information available, exit */\n\t\treturn( CRYPT_OK );\n\t\t}\n\treturn( addSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_CLIENT_PORT, \n\t\t\t\t\t\t\tport ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void defaultShutdownFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* The default handler has nothing to do, the only action is the \n\t   sNetDisconnect() which is handled by closeSession() */\n\t}\n\n/* Default get-attribute function used when no session-specific one is\n   provided */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int defaultGetAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tOUT void *data,\n\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCRYPT_CERTIFICATE *responsePtr = ( CRYPT_CERTIFICATE * ) data;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( data, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( type == CRYPT_SESSINFO_RESPONSE );\n\n\t/* If we didn't get a response there's nothing to return */\n\tif( sessionInfoPtr->iCertResponse == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Return the information to the caller */\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_INCREFCOUNT );\n\t*responsePtr = sessionInfoPtr->iCertResponse;\n\treturn( CRYPT_OK );\n\t}\n\n/* Set up the function pointers to the session I/O methods */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initSessionIO( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( protocolInfo != NULL );\n\n\t/* Install default handler functions if required */\n\tif( !FNPTR_ISSET( sessionInfoPtr->shutdownFunction ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->shutdownFunction, defaultShutdownFunction );\n\t\t}\n\tif( !FNPTR_ISSET( sessionInfoPtr->connectFunction ) )\n\t\t{\n\t\tif( isServer( sessionInfoPtr ) )\n\t\t\t{\n\t\t\tFNPTR_SET( sessionInfoPtr->connectFunction, defaultServerStartupFunction );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tFNPTR_SET( sessionInfoPtr->connectFunction, defaultClientStartupFunction );\n\t\t\t}\n\t\t}\n\tif( protocolInfo->isReqResp && \\\n\t\t!FNPTR_ISSET( sessionInfoPtr->getAttributeFunction ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, \n\t\t\t\t   defaultGetAttributeFunction );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SESSIONS */\n"
  },
  {
    "path": "deps/cl345/session/session.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSecure Session Routines Header File\t\t\t\t\t*\n*\t\t\t\t\t\t Copyright Peter Gutmann 1998-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SES_DEFINED\n\n#define _SES_DEFINED\n\n#ifndef _STREAM_DEFINED\n  #if defined( INC_ALL )\n\t#include \"stream.h\"\n  #else\n\t#include \"io/stream.h\"\n  #endif /* Compiler-specific includes */\n#endif /* _STREAM_DEFINED */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Types and Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Session information flags.  These are:\n\n\tFLAG_CACHEDINFO: The session has been recreated from cached \n\t\t\tinformation rather than going through a full handshake, for \n\t\t\texample via an SSL session resumption.  This means that various\n\t\t\tparameters like credentials that would be established by\n\t\t\ta full handshake can't be read.\n\n\tFLAG_ISOPEN: The session is active.\n\n\tFLAG_PARTIALOPEN: The session is partially active pending \n\t\t\tconfirmation of credentials such as a username and password\n\t\t\tor certificate.  This means that the session remains in the\n\t\t\thandshake state, with the handshake being completed once the \n\t\t\tcredentials have been confirmed.\n\n\tFLAG_SENDCLOSED: The remote system has closed its receive channel, \n\t\t\twhich means that no more data can be sent to it.  This does not \n\t\t\thowever mean that no more data can be received on our receive \n\t\t\tchannel.\n\n\tFLAG_ISCLOSINGDOWN: The session is in the shutdown stage, if further\n\t\t\trequests from the remote system arrive they should be NACK'd or\n\t\t\tignored.\n\n\tFLAG_ISCRYPTLIB: The peer is also running cryptlib, which means that \n\t\t\twe can apply cryptlib-specific optimistions and security \n\t\t\tenhancements.\n\n\tFLAG_ISEAPTRANSPORT: The session is using EAP transport, for EAP-xTLS\n\t\t\twhich runs over RADIUS which runs over UDP.\n\n\tFLAG_ISHTTPTRANSPORT: The session is using HTTP transport, for \n\t\t\trequest/response sessions.\n\n\tFLAG_ISSERVER: The session is a server session.\n\n\tFLAG_ISSECURE_READ:  The read/write channel is in the secure state, \n\tFLAG_ISSECURE_WRITE: for secure data transport sessions.  In other\n\t\t\twords the session has passed the initial handshake stage and all \n\t\t\tdata is now being encrypted/MACd/whatever.\n\n\tFLAG_NETSESSIONOPEN: The network-level connection has been established,\n\t\t\teven if the overall session itself hasn't been.  This is used\n\t\t\tto control cleanup on shutdown, since the network-level \n\t\t\tconnection will still need to be closed even if the session \n\t\t\trunning on top of it has't been established.\n\n\tFLAG_NOREPORTERROR: Don't update the extended error information if\n\t\t\tan error occurs, since this has already been set.  This is\n\t\t\ttypically used when performing shutdown actions in response to\n\t\t\ta protocol error, when a network error such as the other side\n\t\t\tclosing the connection would overwrite the details of the\n\t\t\terror that caused the shutdown to be performed.\n\n\tFLAG_REFLECTAUTHOK: Normally the CRYPT_SESSINFO_AUTHRESPONSE attribute\n\t\t\tcontrols the handshake process, so it merely records that it's\n\t\t\tbeen set in the session info and the handshake continues, \n\t\t\thowever in some cases additional authentication process takes \n\t\t\tplace post-handshake, in which case this flag indicates that the\n\t\t\tsetting needs to be reflected down to the session handler via\n\t\t\tits setAttributeFunction().\n\n\tFLAG_SUBPROTOCOL_ACTIVE: The underlying protocol (e.g. TLS) has an \n\t\t\tadditional protocol layered over it (e.g. WebSockets).  This \n\t\t\tflag is used to distinguish between the layered protocol being \n\t\t\tenabled for use but not yet active for data reads and writes, \n\t\t\tand the layered protocol being active for reads and writes */\n\t\n#define SESSION_FLAG_NONE\t\t\t0x0000\t/* No session flags */\n#define SESSION_FLAG_ISOPEN\t\t\t0x0001\t/* Session is active */\n#define SESSION_FLAG_PARTIALOPEN\t0x0002\t/* Session is partially active */\n#define SESSION_FLAG_SENDCLOSED\t\t0x0004\t/* Send channel is closed */\n#define SESSION_FLAG_ISCLOSINGDOWN\t0x0008\t/* Session is in process of shutdown */\n#define SESSION_FLAG_NOREPORTERROR\t0x0010\t/* Don't report network-level errors */\n#define SESSION_FLAG_ISSERVER\t\t0x0020\t/* Session is server session */\n#define SESSION_FLAG_ISSECURE_READ\t0x0040\t/* Session read ch.in secure state */\n#define SESSION_FLAG_ISSECURE_WRITE\t0x0080\t/* Session write ch.in secure state */\n#define SESSION_FLAG_ISCRYPTLIB\t\t0x0100\t/* Peer is running cryptlib */\n#define SESSION_FLAG_ISHTTPTRANSPORT 0x0200\t/* Session using HTTP transport */\n#define SESSION_FLAG_ISEAPTRANSPORT\t0x0400\t/* Session using EAP transport */\n#define SESSION_FLAG_CACHEDINFO\t\t0x0800\t/* Session established from cached info */\n#define SESSION_FLAG_SUBPROTOCOL_ACTIVE 0x1000\t/* Higher-level protocol active */\n#define SESSION_FLAG_REFLECTAUTHOK\t0x2000\t/* Reflect auth-OK to protocol handler */\n#define SESSION_FLAG_NETSESSIONOPEN\t0x4000\t/* Network-level connection open */\n#define SESSION_FLAG_MAX\t\t\t0x7FFF\t/* Maximum possible flag value */\n\n/* Needed-information flags used by protocol-specific handlers to indicate\n   that the caller must set the given attributes in the session information\n   before the session can be activated.  This allows it to be checked at the\n   general cryptses.c level rather than at the per-protocol level.\n   \n   Some session types have private keys optional but if present they must \n   meet certain requirements, this is indicated by omitting the presence-\n   check SESSION_NEEDS_PRIVATEKEY but specifying one or more of the \n   SESSION_NEEDS_PRIVKEYxxx options */\n\n#define SESSION_NEEDS_NONE\t\t\t0x0000\t/* No needed information flags */\n#define SESSION_NEEDS_USERID\t\t0x0001\t/* Must have userID */\n#define SESSION_NEEDS_PASSWORD\t\t0x0002\t/* Must have password */\n#define SESSION_NEEDS_PRIVATEKEY\t0x0004\t/* Must have private key */\n#define SESSION_NEEDS_PRIVKEYCRYPT\t0x0008\t/* Priv.key must have certificate */\n#define SESSION_NEEDS_PRIVKEYSIGN\t0x0010\t/* Priv.key must have sig.capabil.*/\n#define SESSION_NEEDS_PRIVKEYCERT\t0x0020\t/* Priv.key must have crypt capabil.*/\n#define SESSION_NEEDS_PRIVKEYCACERT\t0x0040\t/* Priv key must have CA certificate */\n#define SESSION_NEEDS_KEYORPASSWORD\t( 0x0080 | SESSION_NEEDS_PASSWORD | \\\n\t\t\t\t\t\t\t\t\t  SESSION_NEEDS_PRIVATEKEY )\n\t\t\t\t\t\t\t\t\t\t\t/* Password can be used in place of \n\t\t\t\t\t\t\t\t\t\t\t   private, this is a modifier on top \n\t\t\t\t\t\t\t\t\t\t\t   of privKey/password */\n#define SESSION_NEEDS_REQUEST\t\t0x0100\t/* Must have request obj.*/\n#define SESSION_NEEDS_KEYSET\t\t0x0200\t/* Must have certificate keyset */\n#define SESSION_NEEDS_CERTSTORE\t\t0x0400\t/* Keyset must be certificate store */\n#define SESSION_NEEDS_MAX\t\t\t0x07FF\t/* Maximum possible flag value */\n\n/* The minimum- and maximum-length fixed headers that we should see in \n   header-read code */\n\n#define FIXED_HEADER_MIN\t\t\t5\t\t/* SSL header */\n#define FIXED_HEADER_MAX\t\t\t21\t\t/* TLS 1.1+ header with explicit \n\t\t\t\t\t\t\t\t\t\t\t   AES IV */\n\n/* The minimum and maximum packet size for procotols with variable-length\n   data packets */\n\n#define PACKET_SIZE_MIN\t\t\t\t1024\n#define PACKET_SIZE_MAX\t\t\t\t0x100000L\n\n/* When reading packets for a secure session protocol, we need to \n   communicate read state information which is more complex than the usual \n   length or error code.  The following values modify the standard return\n   value (either a positive or zero byte count or a negative error value) \n   with additional context-specific information */\n\ntypedef enum {\n\tREADINFO_NONE,\t\t\t\t\t/* No special handling */\n\tREADINFO_HEADERPAYLOAD,\t\t\t/* Header read got some payload data */\n\tREADINFO_NOOP,\t\t\t\t\t/* Packet was no-op, try again */\n\tREADINFO_PARTIAL,\t\t\t\t/* Partial packet, try again */\n\tREADINFO_FATAL,\t\t\t\t\t/* Treat errors as fatal */\n\tREADINFO_FATAL_CRYPTO,\t\t\t/* As above, but specifically crypt-related */\n\tREADINFO_LAST\t\t\t\t\t/* Last possible read information */\n\t} READSTATE_INFO;\n\n/* The control mechanism for authorisation in interactive sessions.  \n   Normally when the server gets a user-authorisation request it'll return a \n   CRYPT_ENVELOPE_RESOURCE to tell the caller that they need to decide what \n   to do with the request.  If they set it to AUTHRESPONSE_SUCCESS, we allow \n   the client authorisation, if they set it to AUTHRESPONSE_FAILURE we \n   disallow it and the client gets another go at authorising themselves.  \n   The default setting of AUTHRESPONSE_NONE means that we ask the user for \n   instructions */\n\ntypedef enum {\n\tAUTHRESPONSE_NONE,\t\t\t\t\t/* No authorisation response */\n\tAUTHRESPONSE_SUCCESS,\t\t\t\t/* Allow authorisation */\n\tAUTHRESPONSE_FAILURE,\t\t\t\t/* Disallow authorisation */\n\tAUTHRESPONSE_LAST\t\t\t\t\t/* Last possible authorisation response */\n\t} AUTHRESPONSE_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Subtype Structures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The internal fields in a session that hold data for the various session\n   types */\n\n#ifdef USE_SSL\n\n/* WebSockets state information */\n\n#ifdef USE_WEBSOCKETS\n\n#define SSL_WS_BUFSIZE\t\t32\n\ntypedef struct {\n\t/* The WebSockets header */\n\tBUFFER( SSL_WS_BUFSIZE, bufSize ) \\\n\tBYTE headerBuffer[ SSL_WS_BUFSIZE + 8 ];\n\tint headerBufPos;\t\t\t\t\t/* Current buffer position */\n\tint headerBytesRequired;\t\t\t/* Bytes required for header */\n\n\t/* The mask value used to mask client -> server packets */\n\tBYTE mask[ 4 + 8 ];\n\tint maskPos;\t\t\t\t\t\t/* Position in mask buffer */\n\n\t/* Payload information */\n\tint type;\t\t\t\t\t\t\t/* WebSockets packet type */\n\tint totalLength;\t\t\t\t\t/* Packet payload length */\n\n\t/* Miscellaneous information */\n\tBOOLEAN sendPong;\t\t\t\t\t/* Whether Pong queued to be sent */\n\tBOOLEAN sendClose;\t\t\t\t\t/* Whether Close queued to be sent */\n\t} SSL_WS_INFO;\n#endif /* USE_WEBSOCKETS */\n\ntypedef struct {\n\t/* Session state information */\n\tint sessionCacheID;\t\t\t\t\t/* Session cache ID for this session */\n\tint minVersion;\t\t\t\t\t\t/* Minimum acceptable protocol version */\n\tint ivSize;\t\t\t\t\t\t\t/* Explicit IV size for TLS 1.1+ */\n\n\t/* The incoming and outgoing packet sequence number, for detecting \n\t   insertion/deletion attacks */\n\tlong readSeqNo, writeSeqNo;\n\n\t/* The SSL MAC read/write secrets are required because SSL 3.0 uses a \n\t   proto-HMAC that isn't handled by cryptlib.  We leave the data in \n\t   normal memory because it's only usable for an active attack, which \n\t   means that recovering it from swap afterwards isn't a problem */\n#ifdef USE_SSL3\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE macReadSecret[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE macWriteSecret[ CRYPT_MAX_HASHSIZE + 8 ];\n#endif /* USE_SSL3 */\n\n\t/* TLS 1.2+ with GCM modes breaks the IV down into two parts, an \n\t   explicit portion that's sent with every packet and an implicit\n\t   portion that's derived from the master secret */\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE gcmReadSalt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE gcmWriteSalt[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint gcmSaltSize;\n\n\t/* When TLS 1.1+ explicit IVs are used the IV is stripped on read so \n\t   that the remaining packet data can be copied into the read buffer for \n\t   in-place processing, however when used with encrypt-then-MAC we need \n\t   to store the read IV in order that it can be MAC'd once the packet is \n\t   processed */\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\n\t/* When performing manual certificate checking the handshake is \n\t   interrupted halfway through, so we have to store the handshake state\n\t   in order to allow it to be continued later.  The following pointer\n\t   points to this state data, a buffer of size SSL_HANDSHAKE_INFO */\n\tDATAPTR savedHandshakeInfo;\t\t\t/* Saved handshake state */\n\n\t/* The session scoreboard, used for the SSL session cache */\n\tDATAPTR scoreboardInfoPtr;\t\t\t/* Session scoreboard */\n\n\t/* A buffer for the SSL packet header, which is read out-of-band */\n\tBUFFER_FIXED( 8 + CRYPT_MAX_IVSIZE ) \\\n\tBYTE headerBuffer[ 8 + CRYPT_MAX_IVSIZE + 8 ];\n\n\t/* WebSockets state information */\n#ifdef USE_WEBSOCKETS\n\tSSL_WS_INFO wsInfo;\n#endif /* USE_WEBSOCKETS */\n\t} SSL_INFO;\n#endif /* USE_SSL */\n\n#ifdef USE_SSH\n\n/* Deferred response information.  When we get a request, we may be in the \n   middle of assembling or sending a data packet, so the response has to be \n   deferred until after the data packet has been completed and sent.  The\n   following structure is used to hold the response data until the send\n   channel is clear */\n\n#define SSH_MAX_RESPONSESIZE\t16\t\t/* 2 * channelNo + 2 * param */\n\ntypedef struct {\n\tint type;\t\t\t\t\t\t\t/* Response type */\n\tBUFFER( SSH_MAX_RESPONSESIZE, dataLen ) \\\n\tBYTE data[ SSH_MAX_RESPONSESIZE + 8 ];\t/* Encoded response data */\n\tint dataLen;\n\t} SSH_RESPONSE_INFO;\n\ntypedef struct {\n\t/* The packet type and padding length, which are extracted from the \n\t   packet header during header processing */\n\tint packetType, padLength;\n\n\t/* The incoming and outgoing packet sequence number, for detecting \n\t   insertion/deletion attacks */\n\tlong readSeqNo, writeSeqNo;\n\n\t/* Per-channel state information */\n\tint currReadChannel, currWriteChannel; /* Current active R/W channels */\n\tint nextChannelNo;\t\t\t\t\t/* Next SSH channel no.to use */\n\tint channelIndex;\t\t\t\t\t/* Current cryptlib unique channel ID */\n\n\t/* Deferred response data, used to enqueue responses when unwritten data \n\t   remains in the send buffer */\n\tSSH_RESPONSE_INFO response;\n\n\t/* Whether an SSH user authentication packet has been read ready for the\n\t   server to act on */\n\tBOOLEAN authRead;\n\n\t/* A buffer for the SSH packet header, which we receive in encrypted \n\t   form so that it needs to be decrypted, parts discarded, and the \n\t   remainder copied into the main buffer as payload data (ugh) */\n\tBUFFER_FIXED( CRYPT_MAX_IVSIZE ) \\\n\tBYTE headerBuffer[ CRYPT_MAX_IVSIZE + 8 ];\n\n\t/* To keep track of the partially-processed data we need to augment the\n\t   standard pendingPacket indicators with an additional value that \n\t   tracks how much of the pending packet has already been processed as \n\t   part of the header read */\n\tint partialPacketDataLength;\t\t/* Length of data already processed */\n\n\t/* If we're using the SSH CTR-mode ciphers, we need to store the explicit\n\t   counter values */\n#ifdef USE_SSH_CTR\n\tBYTE readCTR[ CRYPT_MAX_IVSIZE + 8 ], writeCTR[ CRYPT_MAX_IVSIZE + 8 ];\n#endif /* USE_CTR */\n\n\t/* The SSH spec allows authentication to be performed in lots of little \n\t   bits and pieces, which give an attacker lots of leeway to fiddle with\n\t   the credentials being submitted on different passes of the \n\t   authentication to try and confuse the server.  To avoid this problem\n\t   we require that the userID and authentication method remain constant\n\t   over different iterations of authentication, which unfortunately \n\t   means recording a pile of server-side authentication state */\n\tBUFFER_FIXED( KEYID_SIZE ) \\\n\tBYTE authUserNameHash[ KEYID_SIZE + 8 ];\t/* Hashed userID */\n\tint authType;\t\t\t\t\t\t/* Authentication method */\n\t} SSH_INFO;\n#endif /* USE_SSH */\n\n#ifdef USE_TSP\n\ntypedef struct {\n\t/* The message imprint (hash) algorithm and hash value */\n\tCRYPT_ALGO_TYPE imprintAlgo;\n\tBUFFER( CRYPT_MAX_HASHSIZE, imprintSize ) \\\n\tBYTE imprint[ CRYPT_MAX_HASHSIZE ];\n\tint imprintSize;\n\t} TSP_INFO;\n#endif /* USE_TSP */\n\n#ifdef USE_CMP \n\ntypedef struct {\n\t/* CMP request subtype and user information */\n\tCRYPT_REQUESTTYPE_TYPE requestType;\t/* CMP request subtype */\n\tCRYPT_CERTIFICATE userInfo;\t\t\t/* PKI user information */\n\n\t/* The saved MAC context from a previous transaction (if any).  This is\n\t   saved across transactions in case the same user information is used\n\t   for subsequent transactions, see the comment in cmp.h for details */\n\tCRYPT_CONTEXT savedMacContext;\t\t/* MAC context from prev.trans */\n\t} CMP_INFO;\n#endif /* USE_CMP */\n\n#ifdef USE_SCEP\n\ntypedef struct {\n\t/* SCEP request type */\n\tint requestType;\t\t\t\t\t/* SCEP request subtype */\n\t} SCEP_INFO;\n#endif /* USE_SCEP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSession Structures\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Protocol-specific information for each session */\n\ntypedef struct {\n\t/* Information required for all sessions: Whether this is a secure\n\t   session or request/response protocol, protocol-specific flags, the\n\t   default port for the protocol, flags for attributes required before\n\t   the session can be activated, the default protocol version and lowest\n\t   and highest allowed versions, and the transport-protocol client and \n\t   server content-types */\n\tconst BOOLEAN isReqResp;\t\t\t/* Whether session is req/resp session */\n\tconst int flags;\t\t\t\t\t/* Protocol flags */\n\tconst int port;\t\t\t\t\t\t/* Default port */\n\tconst int clientReqAttrFlags, serverReqAttrFlags; /* Required attributes */\n\tconst int version, minVersion, maxVersion;/* Protocol version/subtype */\n\tconst CRYPT_SUBPROTOCOL_TYPE minSubProtocol, maxSubProtocol;\n\t\t\t\t\t\t\t\t\t\t/* Allowed sub-protocol types */\n\n\t/* Session type-specific information: The send and receive buffer size,\n\t   the alternative transport protocol for request/response sessions if\n\t   HTTP isn't being used, the minimum allowed size for the server's\n\t   private key */\n\tconst int bufSize;\t\t\t\t\t/* Send/receive buffer sizes */\n\tconst int sendBufStartOfs;\t\t\t/* Payload data start */\n\tconst int maxPacketSize;\t\t\t/* Maximum packet (payload data) size */\n\t} PROTOCOL_INFO;\n\n/* A value to initialise the session type-specific buffer size values to\n   default settings for request/response protocols */\n\n#define BUFFER_SIZE_DEFAULT\t\t0, 0, 0\n\n/* Attribute flags.  These are:\n\n\tFLAG_COMPOSITE: Composite attribute containing sub-attribute data in the \n\t\t\t{ value, valueLength } buffer.  The attribute cursor can be \n\t\t\tmoved within the attribute using the internal virtual cursor.\n\t\t\t\n\tFLAG_CURSORMOVED: The attribute (group) cursor has moved, so the virtual \n\t\t\tcursor within the attribute needs to be reset the next time that \n\t\t\tit's referenced.  This is used with composite attributes, whose \n\t\t\tinternal structure is opaque to the general session code.\n\n\tFLAG_ENCODEDVALUE: The attribute value is stored in cryptlib \n\t\t\tXXXXX-XXXXX-... style encoding and needs to be converted to \n\t\t\tbinary form before use.\n\n\tFLAG_EPHEMERAL: The attribute is only valid for the current session \n\t\t\tactivation and is cleared between session re-activations.\n\t\t\n\tFLAG_MULTIVALUED: Multiple instances of the attribute are permitted.  \n\t\t\tThis complements ATTR_FLAG_OVERWRITE in that instead of \n\t\t\toverwriting the single existing instance, another instance is \n\t\t\tcreated */\n\n#define ATTR_FLAG_NONE\t\t\t0x00\t/* No attribute flag */\n#define ATTR_FLAG_ENCODEDVALUE\t0x01\t/* Value uses XXX-XXX encoding */\n#define ATTR_FLAG_MULTIVALUED\t0x02\t/* Multiple instances permitted */\n#define ATTR_FLAG_COMPOSITE\t\t0x04\t/* Composite attribute */\n#define ATTR_FLAG_CURSORMOVED\t0x08\t/* Attribute virtual cursor reset */\n#define ATTR_FLAG_EPHEMERAL\t\t0x10\t/* Only valid for current sess.act.*/\n#define ATTR_FLAG_MAX\t\t\t0x1F\t/* Maximum possible flag value */\n\n/* The helper function used to access session subtype-specific internal\n   attributes within an attribute list entry */\n\nstruct AL;\t/* Forward declaration for attribute-list access function */\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\n\t\tint ( *ATTRACCESS_FUNCTION )( INOUT struct AL *attributeListPtr,\n\t\t\t\t\t\t\t\t\t  IN_ENUM_OPT( ATTR ) \\\n\t\t\t\t\t\t\t\t\t\tconst ATTR_TYPE attrGetType,\n\t\t\t\t\t\t\t\t\t  OUT_INT_Z int *value );\n\n/* An attribute list used to store session-related attributes such as \n   user names, passwords, and public keys.  Since some of these can be\n   composite attributes (with information stored in the { value, \n   valueLength } buffer), we implement a virtual cursor that points to the \n   currently-selected sub-attribute within the composite attribute */\n\ntypedef struct AL {\n\t/* Identification and other information for this attribute */\n\tCRYPT_ATTRIBUTE_TYPE groupID, attributeID;\t\n\t\t\t\t\t\t\t\t\t\t/* Attribute group and type */\n\tFNPTR accessFunction;\t\t\t\t/* Internal attribute access fn.*/\n\tSAFE_FLAGS flags;\t\t\t\t\t/* Attribute data flags */\n\n\t/* The data payload for this attribute.  If it's numeric data such as \n\t   a small integer or context, we store it in the intValue member.  If \n\t   it's a string or composite attribute data, we store it in the \n\t   variable-length buffer */\n\tlong intValue;\t\t\t\t\t\t/* Integer value for simple types */\n\tBUFFER_OPT_FIXED( valueLength ) \\\n\tvoid *value;\t\t\t\t\t\t/* Attribute value */\n\tint valueLength;\t\t\t\t\t/* Attribute value length */\n\n\t/* The previous and next list element in the linked list of elements */\n\tDATAPTR prev, next;\t\t\t\t\t/* Prev, next item in the list */\n\n\t/* Variable-length storage for the attribute data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} ATTRIBUTE_LIST;\n\n/* Defines to make access to the union fields less messy */\n\n#define sessionSSH\t\tsessionInfo.sshInfo\n#define sessionSSL\t\tsessionInfo.sslInfo\n#define sessionTSP\t\tsessionInfo.tspInfo\n#define sessionCMP\t\tsessionInfo.cmpInfo\n#define sessionSCEP\t\tsessionInfo.scepInfo\n\n/* The structure that stores the information on a session */\n\nstruct SI;\n\ntypedef STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tvoid ( *SES_SHUTDOWN_FUNCTION )( INOUT struct SI *sessionInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *SES_CONNECT_FUNCTION )( INOUT struct SI *sessionInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *SES_GETATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tOUT void *data,\n\t\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *SES_SETATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\tIN const void *data,\n\t\t\t\t\t\t\t\t\t\t\tIN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *SES_CHECKATTRIBUTE_FUNCTION )( INOUT struct SI *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t  IN const void *data,\n\t\t\t\t\t\t\t\t\t\t\t  IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE type );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *SES_TRANSACT_FUNCTION )( INOUT struct SI *sessionInfoPtr );\ntypedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *SES_READHEADER_FUNCTION )( INOUT struct SI *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  OUT_ENUM_OPT( READINFO ) \\\n\t\t\t\t\t\t\t\t\t\t\tREADSTATE_INFO *readInfo );\ntypedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\t\tint ( *SES_PROCESSBODY_FUNCTION )( INOUT struct SI *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t   OUT_ENUM_OPT( READINFO ) \\\n\t\t\t\t\t\t\t\t\t\t\tREADSTATE_INFO *readInfo );\ntypedef CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *SES_PREPAREPACKET_FUNCTION )( INOUT struct SI *sessionInfoPtr );\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *SES_ACTIVATESUBPROTOCOL_FUNCTION )( INOUT struct SI *sessionInfoPtr );\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n\t\tint ( *SES_CLOSESUBPROTOCOL_FUNCTION )( INOUT struct SI *sessionInfoPtr );\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\ntypedef struct SI {\n\t/* Control and status information */\n\tCRYPT_SESSION_TYPE type;\t\t\t/* Session type */\n\tDATAPTR protocolInfo;\t\t\t\t/* Session subtype information */\n\tint version;\t\t\t\t\t\t/* Protocol version/subtype */\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\tCRYPT_SUBPROTOCOL_TYPE subProtocol;\t/* Sub-protocol type */\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\tCRYPT_ALGO_TYPE cryptAlgo;\t\t\t/* Negotiated encryption algo */\n\tCRYPT_ALGO_TYPE integrityAlgo;\t\t/* Negotiated integrity prot.algo */\n\tSAFE_FLAGS flags, protocolFlags;\t/* Session information, protocol-specific flags */\n\tAUTHRESPONSE_TYPE authResponse;\t\t/* Response to user-auth request */\n\n\t/* Session type-specific information */\n\tunion {\n#ifdef USE_SSL\n\t\tSSL_INFO *sslInfo;\n#endif /* USE_SSL */\n#ifdef USE_SSH\n\t\tSSH_INFO *sshInfo;\n#endif /* USE_SSH */\n#ifdef USE_TSP\n\t\tTSP_INFO *tspInfo;\n#endif /* USE_TSP */\n#ifdef USE_CMP\n\t\tCMP_INFO *cmpInfo;\n#endif /* USE_CMP */\n#ifdef USE_SCEP\n\t\tSCEP_INFO *scepInfo;\n#endif /* USE_SCEP */\n\t\t} sessionInfo;\n\n\t/* When we add generic attributes to the session, we occasionally need to\n\t   perform protocol-specific checking of the attributes being added.  The\n\t   following values are used to tell the generic cryptses.c code which\n\t   checks need to be performed */\n\tint clientReqAttrFlags, serverReqAttrFlags; /* Required attributes */\n\n\t/* The overall session status.  If we run into a nonrecoverable error\n\t   (which for the encrypted session types means just about anything,\n\t   once we lose sync we're toast) we remember the status here so that\n\t   any further attempts to work with the session will return this\n\t   status.  Since an error on one side of the channel (e.g. bad data on\n\t   read) doesn't necessarily affect the operation of the other side, we\n\t   keep track of the two sides independantly, and only set the error\n\t   state for both sides for network-related errors.\n\n\t   In many cases there'll still be data in the internal buffer that the\n\t   user can read/write without triggering an error response so before we \n\t   set the error state we set the pending error state and only move the\n\t   pending state into the current state once all data still present in\n\t   the buffer has been read */\n\tint readErrorState, writeErrorState;/* Current error state */\n\tint pendingReadErrorState, pendingWriteErrorState;\n\t\t\t\t\t\t\t\t\t\t/* Error state when buffer emptied */\n\n\t/* Data buffer information.  In protocols that consist of single\n\t   messages sent back and forth only the receive buffer is used for\n\t   sending and receiving data, this buffer is somewhat more flexible\n\t   since it's associated with extra variables for handling the current\n\t   position in the buffer (bufPos) vs.the total amount of data present\n\t   (bufEnd) */\n\tBUFFER( sendBufSize, sendBufPos ) \\\n\tBYTE *sendBuffer;\n\tBUFFER_OPT( receiveBufSize, receiveBufEnd ) \\\n\tBYTE *receiveBuffer;\t\t\t\t/* Data buffer */\n\tint sendBufSize, receiveBufSize;\t/* Total buffer size */\n\tint sendBufPos, receiveBufPos;\t\t/* Current position in buffer */\n\tint sendBufStartOfs, receiveBufStartOfs; /* Space for header in buffer */\n\tint receiveBufEnd;\t\t\t\t\t/* Total data in buffer */\n\tint maxPacketSize;\t\t\t\t\t/* Maximum packet (payload data) size */\n\n\t/* When reading encrypted data packets we typically end up with a partial\n\t   packet in the read buffer that we can't process until the remainder\n\t   arrives, the following variables holds the eventual length of the\n\t   pending data packet and the amount of data remaining to be read */\n\tint pendingPacketLength;\t\t\t/* Lending of pending data packet */\n\tint pendingPacketRemaining;\t\t\t/* Bytes remaining to be read */\n\n\t/* Unlike payload data, the packet header can't be read in sections but\n\t   must be read completely since all of the header information needs to\n\t   be processed at once.  The following value is usually zero, if it's\n\t   nonzero it records how much of the header remains to be read */\n\tint partialHeaderRemaining;\t\t\t/* Header bytes still to read */\n\n\t/* When sending data we can also end up with partially-processed packets\n\t   in the send buffer, but for sending we prevent further packets from\n\t   being added until the current one is flushed.  To handle this all we\n\t   need is a simple high-water-mark indicator that indicates the start \n\t   position of any yet-to-be-written data */\n\tBOOLEAN partialWrite;\t\t\t\t/* Unwritten data remains in buffer */\n\tint sendBufPartialBufPos;\t\t\t/* Progress point of partial write */\n\n\t/* The session generally has various ephemeral contexts associated with\n\t   it, some short-term (e.g.public-key contexts used to establish the\n\t   session) and some long-term (e.g.encryption contexts used to perform\n\t   bulk data encryption).  These contexts are ephemeral ones that are\n\t   created as part of the session, long-term ones (e.g.signature keys\n\t   used for authentication) are held elsewhere */\n\tCRYPT_CONTEXT iKeyexCryptContext;\t/* Key exchange encryption */\n\tCRYPT_CONTEXT iKeyexAuthContext;\t/* Key exchange authentication */\n\tCRYPT_CONTEXT iCryptInContext, iCryptOutContext;\n\t\t\t\t\t\t\t\t\t\t/* In/outgoing data encryption */\n\tCRYPT_CONTEXT iAuthInContext, iAuthOutContext;\n\t\t\t\t\t\t\t\t\t\t/* In/outgoing auth/integrity */\n\tCRYPT_CERTIFICATE iCertRequest, iCertResponse;\n\t\t\t\t\t\t\t\t\t\t/* Certificate request/response */\n\tint cryptBlocksize, authBlocksize;\t/* Block size of crypt, auth.algos */\n\n\t/* The private key, which is required to authenticate the client or \n\t   server in some protocols */\n\tCRYPT_CONTEXT privateKey;\t\t\t/* Authentication private key */\n\n\t/* Certificate store for certificate management protocols like OCSP and \n\t   CMP and private-key keyset for PnP PKI protocols */\n\tCRYPT_KEYSET cryptKeyset;\t\t\t/* Certificate store */\n\tCRYPT_HANDLE privKeyset;\t\t\t/* Private-key keyset/device */\n\n\t/* Session-related attributes, a current-position cursor in the \n\t   attribute list */\n\tDATAPTR attributeList, attributeListCurrent;\n\n\t/* Network connection information */\n\tint networkSocket;\t\t\t\t\t/* User-supplied network socket */\n\tint readTimeout, writeTimeout, connectTimeout;\n\t\t\t\t\t\t\t\t\t\t/* Connect and data xfer.timeouts */\n\tSTREAM stream;\t\t\t\t\t\t/* Network I/O stream */\n\n\t/* Low-level error information */\n\tERROR_INFO errorInfo;\n\n\t/* Pointers to session access methods.  Stateful sessions use the read/\n\t   write functions, stateless ones use the transact function */\n\tFNPTR shutdownFunction, connectFunction;\n\tFNPTR getAttributeFunction, setAttributeFunction, checkAttributeFunction;\n\tFNPTR transactFunction, readHeaderFunction, processBodyFunction;\n\tFNPTR preparePacketFunction;\n#if defined( USE_WEBSOCKETS ) || defined( USE_EAP )\n\tFNPTR activateOuterSubprotocolFunction, closeOuterSubprotocolFunction;\n\tFNPTR activateInnerSubprotocolFunction, closeInnerSubprotocolFunction;\n#endif /* USE_WEBSOCKETS || USE_EAP */\n\n\t/* Error information */\n\tCRYPT_ATTRIBUTE_TYPE errorLocus;/* Error locus */\n\tCRYPT_ERRTYPE_TYPE errorType;\t/* Error type */\n\n\t/* The object's handle and the handle of the user who owns this object.\n\t   The former is used when sending messages to the object when only the\n\t   xxx_INFO is available, the latter is used to avoid having to fetch the\n\t   same information from the system object table */\n\tCRYPT_HANDLE objectHandle;\n\tCRYPT_USER ownerHandle;\n\n\t/* Variable-length storage for the type-specific data */\n\tDECLARE_VARSTRUCT_VARS;\n\t} SESSION_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSession Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Macros to make handling of error reporting on shutdown a bit more \n   obvious */\n\n#define disableErrorReporting( sessionInfoPtr )\t\\\n\t\tSET_FLAG( ( sessionInfoPtr )->flags, SESSION_FLAG_NOREPORTERROR )\n#define enableErrorReporting( sessionInfoPtr )\t\\\n\t\tCLEAR_FLAG( ( sessionInfoPtr )->flags, SESSION_FLAG_NOREPORTERROR )\n\n/* The SESSION_ISSERVER flag is checked so often that we define a macro to \n   handle it */\n\n#define isServer( sessionInfoPtr ) \\\n\t\tTEST_FLAG( ( sessionInfoPtr )->flags, SESSION_FLAG_ISSERVER )\n\n/* Session attribute handling functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t OUT_INT_Z int *valuePtr, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT MESSAGE_DATA *msgData, \n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN const int value, \n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint setSessionAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data,\n\t\t\t\t\t\t  IN_LENGTH const int dataLength,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteSessionAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\n\n/* Session-specific attribute management functions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint addSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\tIN_INT_Z const int value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addSessionInfoS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tIN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\tIN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\tIN_LENGTH_SHORT const int dataLength );\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint addSessionInfoEx( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t  IN_LENGTH_SHORT const int dataLength, \n\t\t\t\t\t  IN_FLAGS_Z( ATTR ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint addSessionInfoComposite( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t const ATTRACCESS_FUNCTION accessFunction, \n\t\t\t\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t\t\t IN_FLAGS( ATTR ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint updateSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength,\n\t\t\t\t\t   IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t   IN_FLAGS_Z( ATTR ) const int flags );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint getSessionAttributeCursor( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,\n\t\t\t\t\t\t\t   OUT_ATTRIBUTE_Z CRYPT_ATTRIBUTE_TYPE *valuePtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSessionAttributeCursor( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE sessionInfoType,\n\t\t\t\t\t\t\t   IN_RANGE( CRYPT_CURSOR_LAST, \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_CURSOR_FIRST ) /* Values are -ve */\n\t\t\t\t\t\t\t\t\tconst int position );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfoNext( const ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t\t\t\t\t   IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID );\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nconst ATTRIBUTE_LIST *findSessionInfoEx( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t IN_ATTRIBUTE \\\n\t\t\t\t\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE attributeID,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( valueLength ) const void *value, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int valueLength );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid lockEphemeralAttributes( INOUT ATTRIBUTE_LIST *attributeListHead );\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint deleteSessionInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT ATTRIBUTE_LIST *attributeListPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid deleteSessionInfoAll( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_ENUM( CRYPT_ATTRIBUTE ) \\\nCRYPT_ATTRIBUTE_TYPE checkMissingInfo( IN_OPT const ATTRIBUTE_LIST *attributeListHead,\n\t\t\t\t\t\t\t\t\t   const BOOLEAN isServer );\n\n/* Prototypes for functions in session.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initSessionIO( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSessionNetConnectInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   OUT NET_CONNECT_INFO *connectInfo );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN checkAttributesConsistent( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getSessionErrorInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint checkServerCertValid( const CRYPT_CERTIFICATE iServerKey,\n\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint activateSession( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendCloseNotification( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   IN_BUFFER_OPT( length ) const void *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_Z const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint closeSession( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_LENGTH \\\nint getPaddedSize( IN_DATALENGTH_Z const int length );\n\n/* Prototypes for functions in sess_rd.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedHeaderAtomic( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   OUT_BUFFER_FIXED( headerLength ) void *headerBuffer, \n\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \\\n\t\t\t\t\t\t\t\tconst int headerLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readFixedHeader( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t OUT_BUFFER_FIXED( headerLength ) void *headerBuffer, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( FIXED_HEADER_MIN ) \\\n\t\t\t\t\t\t\tconst int headerLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint getSessionData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tOUT_BUFFER( dataMaxLength, *bytesCopied ) void *data, \n\t\t\t\t\tIN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint readPkiDatagram( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 4 ) const int minMessageSize );\n\n/* Prototypes for functions in sess_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint putSessionData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tIN_BUFFER_OPT( dataLength ) const void *data,\n\t\t\t\t\tIN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\tOUT_DATALENGTH_Z int *bytesCopied );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writePkiDatagram( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  IN_BUFFER( contentTypeLen ) const char *contentType, \n\t\t\t\t\t  IN_LENGTH_TEXT const int contentTypeLen );\n\n/* Prototypes for subprotocol functions in sess_eap.c/sess_ws.c */\n\n#ifdef USE_WEBSOCKETS\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSubprotocolWebSockets( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeInnerHeaderFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t\t  IN_DATALENGTH const int bufSize );\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint prepareInnerPacketFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT_BUFFER_FIXED( bufSize ) BYTE *buffer,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int bufSize,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int dataSize );\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint processInnerPacketFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT_BUFFER( bufSize, *bufEnd ) BYTE *buffer,\n\t\t\t\t\t\t\t\tIN_DATALENGTH const int bufSize,\n\t\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *bufEnd );\n#else\n#define setSubprotocolWebsockets( sessionInfoPtr )\tCRYPT_ERROR_NOTAVAIL\n#define writeInnerHeaderFunction( sessionInfoPtr, buffer, bufSize ) CRYPT_ERROR\n#define prepareInnerPacketFunction( sessionInfoPtr, buffer, bufSize, dataSize ) CRYPT_ERROR\n#define processInnerPacketFunction( sessionInfoPtr, buffer, bufSize, bufEnd ) CRYPT_ERROR\n#endif /* USE_WEBSOCKETS */\n#ifdef USE_EAP\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setSubprotocolEAP( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n#define setSubprotocolEAP( sessionInfoPtr )\tCRYPT_ERROR_NOTAVAIL\n#endif /* USE_EAP */\n\n/* Prototypes for misc. management functions */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSession( const SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionRead( const SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionWrite( const SESSION_INFO *sessionInfoPtr );\n\n/* Prototypes for session mapping functions */\n\n#ifdef USE_CERTSTORE\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodCertstore( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodCertstore( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_CERTSTORE */\n#ifdef USE_CMP\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodCMP( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodCMP( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_CMP */\n#ifdef USE_RTCS\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodRTCS( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodRTCS( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_RTCS */\n#ifdef USE_OCSP\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodOCSP( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodOCSP( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_OCSP */\n#ifdef USE_SCEP\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodSCEP( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodSCEP( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_SCEP */\n#if defined( USE_SSH ) \n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodSSH( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodSSH( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_SSH */\n#ifdef USE_SSL\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodSSL( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodSSL( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_SSL */\n#ifdef USE_TSP\n  CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\n  int setAccessMethodTSP( INOUT SESSION_INFO *sessionInfoPtr );\n#else\n  #define setAccessMethodTSP( x )\tCRYPT_ARGERROR_NUM1\n#endif /* USE_TCP */\n#endif /* USE_SESSIONS */\n#endif /* _SES_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/ssh.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib SSH Session Management\t\t\t\t\t\t*\n*\t\t\t\t\t   Copyright Peter Gutmann 1998-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_SSH )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSSH( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst SSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( sshInfo, sizeof( SSH_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckSession( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSH: Session check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check SSH session parameters */\n\tif( !CHECK_FLAGS( sessionInfoPtr->protocolFlags, SSH_PFLAG_NONE, \n\t\t\t\t\t  SSH_PFLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSH: Protocol flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sshInfo->packetType < 0x00 || sshInfo->packetType > 0xFF || \\\n\t\tsshInfo->packetType < 0 || sshInfo->padLength > 255 || \\\n\t\tsshInfo->readSeqNo < 0 || sshInfo->readSeqNo > LONG_MAX / 2 || \\\n\t\tsshInfo->writeSeqNo < 0 || sshInfo->writeSeqNo > LONG_MAX / 2 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSH: Session parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( ( sshInfo->authRead != TRUE && sshInfo->authRead != FALSE ) || \\\n\t\tsshInfo->partialPacketDataLength < 0 || \\\n\t\tsshInfo->partialPacketDataLength >= sessionInfoPtr->receiveBufSize || \\\n\t\tsshInfo->authType < 0 || sshInfo->authType > 10 )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSH: State information\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n#if defined( __WIN32__ ) && !defined( NDEBUG )\n\n/* Dump a message to disk for diagnostic purposes.  Rather than using the \n   normal DEBUG_DUMP() macro we have to use a special-purpose function that \n   provides appropriate naming based on what we're processing */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid debugDumpSSH( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   IN_BUFFER( length ) const void *buffer, \n\t\t\t\t   IN_LENGTH_SHORT const int length,\n\t\t\t\t   const BOOLEAN isRead )\n\t{\n\tFILE *filePtr;\n\tstatic int messageCount = 1;\n\tconst BYTE *bufPtr = buffer;\n\tconst BOOLEAN encryptionActive = \\\n\t\t( ( isRead && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) ) || \\\n\t\t  ( !isRead && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE ) ) ) ? \\\n\t\tTRUE : FALSE;\n\tconst BOOLEAN isServerID = \\\n\t\t( !encryptionActive && messageCount < 10 && length >= 4 && \\\n\t\t  !memcmp( buffer, \"SSH-\", 4 ) ) ? TRUE : FALSE;\n\tchar fileName[ 1024 + 8 ], *slashPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer,  length ) );\n\n\tREQUIRES_V( isIntegerRangeNZ( length ) );\n\tREQUIRES_V( isRead == TRUE || isRead == FALSE );\n\n\t/* We don't want to dump too many messages, however SSH is very chatty \n\t   so we have to allow at least 30 or some parts of the exchange get \n\t   lost */\n\tif( messageCount > 30 )\n\t\treturn;\n\n\tstrlcpy_s( fileName, 1024, \"/tmp/\" );\n\tsprintf_s( &fileName[ 5 ], 1024, \"ssh%02d%c_\", messageCount++, \n\t\t\t   isRead ? 'r' : 'w' );\n\tif( isServerID )\n\t\t{\n\t\t/* The initial server-ID messages don't have defined packet names */\n\t\tstrlcat_s( fileName, 1024, \"server_ID\" );\n\t\t}\n\telse\n\t\t{\n\t\tif( !encryptionActive || isRead )\n\t\t\t{\n\t\t\tif( isRead && length > 1 )\n\t\t\t\tstrlcat_s( fileName, 1024, getSSHPacketName( bufPtr[ 1 ] ) );\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !encryptionActive && length > 5 )\n\t\t\t\t\t{\n\t\t\t\t\tstrlcat_s( fileName, 1024, \n\t\t\t\t\t\t\t   getSSHPacketName( bufPtr[ 5 ] ) );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tstrlcat_s( fileName, 1024, \"truncated_packet\" );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tstrlcat_s( fileName, 1024, \"encrypted_packet\" );\n\t\t}\n\tslashPtr = strchr( fileName + 5, '/' );\n\tif( slashPtr != NULL )\n\t\t{\n\t\t/* Some packet names contain slashes */\n\t\t*slashPtr = '\\0'; \n\t\t}\n\tstrlcat_s( fileName, 1024, \".dat\" );\n\n#ifdef __STDC_LIB_EXT1__\n\tif( fopen_s( &filePtr, fileName, \"wb\" ) != 0 )\n\t\tfilePtr = NULL;\n#else\n\tfilePtr = fopen( fileName, \"wb\" );\n#endif /* __STDC_LIB_EXT1__ */\n\tif( filePtr == NULL )\n\t\treturn;\n\tif( isRead && !isServerID )\n\t\t{\n\t\tSTREAM stream;\n\t\tBYTE lengthBuffer[ UINT32_SIZE + 8 ];\n\n\t\t/* The read code has stripped the length field at the start so we\n\t\t   have to reconstruct it and prepend it to the data being written */\n\t\tsMemOpen( &stream, lengthBuffer, UINT32_SIZE );\n\t\twriteUint32( &stream, length );\n\t\tsMemDisconnect( &stream );\n\t\tfwrite( lengthBuffer, 1, UINT32_SIZE, filePtr );\n\t\t}\n\tfwrite( buffer, 1, length, filePtr );\n\tfclose( filePtr );\n\t}\n#endif /* Windows debug mode only */\n\n/* Initialise and destroy the handshake state information */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void initHandshakeInfo( OUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\t/* Initialise the handshake state information values */\n\tmemset( handshakeInfo, 0, sizeof( SSH_HANDSHAKE_INFO ) );\n\thandshakeInfo->iExchangeHashContext = \\\n\t\thandshakeInfo->iExchangeHashAltContext = \\\n\t\t\thandshakeInfo->iServerCryptContext = CRYPT_ERROR;\n\tinitHandshakeCrypt( handshakeInfo );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void destroyHandshakeInfo( INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\t/* Destroy any active contexts.  We need to do this here (even though\n\t   it's also done in the general session code) to provide a clean exit in\n\t   case the session activation fails, so that a second activation attempt\n\t   doesn't overwrite still-active contexts */\n\tif( handshakeInfo->iExchangeHashContext != CRYPT_ERROR )\n\t\tkrnlSendNotifier( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\tif( handshakeInfo->iExchangeHashAltContext != CRYPT_ERROR )\n\t\tkrnlSendNotifier( handshakeInfo->iExchangeHashAltContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\tif( handshakeInfo->iServerCryptContext != CRYPT_ERROR )\n\t\tkrnlSendNotifier( handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\n\t/* Clear the handshake state information, then reset it to explicit non-\n\t   initialised values */\n\tzeroise( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) );\n\tinitHandshakeInfo( handshakeInfo );\n\t}\n\n/* Read the SSH version information string */\n\nCHECK_RETVAL_RANGE( 0, 255 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE ch;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sread( stream, &ch, 1 );\n\treturn( cryptStatusError( status ) ? status : byteToInt( ch ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readVersionString( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst BYTE *versionStringPtr;\n#ifdef USE_ERRMSGS\n\tconst char *peerType = isServer( sessionInfoPtr ) ? \"Client\" : \"Server\";\n#endif /* USE_ERRMSGS */\n\tint versionStringLength, length DUMMY_INIT, linesRead;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Read the server version information, with the format for the ID \n\t   string being \"SSH-protocolversion-softwareversion comments\", which \n\t   (in the original ssh.com interpretation) was \"SSH-x.y-x.y vendorname\" \n\t   (e.g. \"SSH-2.0-3.0.0 SSH Secure Shell\") but for almost everyone else \n\t   is \"SSH-x.y-vendorname*version\" (e.g \"SSH-2.0-OpenSSH_3.0\").\n\n\t   This version information handling is rather ugly since it's a \n\t   variable-length string terminated with a newline, so we have to use\n\t   readTextLine() as if we were talking HTTP.\n\n\t   Unfortunately the SSH RFC then further complicates this by allowing \n\t   implementations to send non-version-related text lines before the\n\t   version line.  The theory is that this will allow applications like\n\t   TCP wrappers to display a (human-readable) error message before\n\t   disconnecting, however some installations use it to display general\n\t   banners before the ID string.  Since the RFC doesn't provide any \n\t   means of distinguishing this banner information from arbitrary data \n\t   we can't quickly reject attempts to connect to something that isn't \n\t   an SSH server.  In other words we have to sit here waiting for \n\t   further data in the hope that eventually an SSH ID turns up, until \n\t   such time as the connect timeout expires */\n\tLOOP_MED( linesRead = 0, linesRead < 20, linesRead++ )\n\t\t{\n\t\tBOOLEAN isTextDataError;\n\n\t\t/* Get a line of input.  Since this is the first communication that\n\t\t   we have with the remote system we're a bit more loquacious about\n\t\t   diagnostics in the event of an error */\n\t\tstatus = readTextLine( readCharFunction, &sessionInfoPtr->stream, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   SSH_ID_MAX_SIZE, &length, &isTextDataError, \n\t\t\t\t\t\t\t   FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tconst char *lcPeerType = isServer( sessionInfoPtr ) ? \\\n\t\t\t\t\t\t\t\t\t \"client\" : \"server\";\n#endif /* USE_ERRMSGS */\n\t\t\tERROR_INFO errorInfo;\t/* Lowercase version of peerType */\n\n\t\t\tsNetGetErrorInfo( &sessionInfoPtr->stream, &errorInfo );\n\t\t\tretExtErr( status, \n\t\t\t\t\t   ( status, SESSION_ERRINFO, &errorInfo, \n\t\t\t\t\t     \"Error reading %s's SSH identifier string: \", \n\t\t\t\t\t\t lcPeerType ) );\n\t\t\t}\n\n\t\t/* If it's the SSH ID/version string, we're done */\n\t\tif( length >= SSH_ID_SIZE && \\\n\t\t\t!memcmp( sessionInfoPtr->receiveBuffer, SSH_ID, SSH_ID_SIZE ) )\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tDEBUG_DUMP_SSH( sessionInfoPtr->receiveBuffer, ( length < 1 ) ? 1 : length, \n\t\t\t\t\tTRUE );\t\t/* Dummy length value if empty line sent */\n\n\t/* The peer shouldn't be throwing infinite amounts of junk at us, if we \n\t   don't get an SSH ID after reading 20 lines of input then there's a \n\t   problem */\n\tif( linesRead >= 20 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"%s sent excessive amounts of text without sending an \"\n\t\t\t\t  \"SSH identifier string\", peerType ) );\n\t\t}\n\n\t/* Make sure that we got enough data to work with.  We need at least \n\t   \"SSH-\" (ID, size SSH_ID_SIZE) + \"x.y-\" (protocol version) + \"xx\" \n\t   (software version/ID, of which the shortest-known is \"Go\", used by\n\t   \"a fork of go's ssh lib\", followed by \"ConfD\") */\n\tif( length < SSH_ID_SIZE + 6 || length > SSH_ID_MAX_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"%s sent invalid-length identifier string '%s', total \"\n\t\t\t\t  \"length %d\", peerType,\n\t\t\t\t  sanitiseString( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE, length ),\n\t\t\t\t  length ) );\n\t\t}\n\tDEBUG_PRINT(( \"Read SSH ID string:\\n\" ));\n\tDEBUG_DUMP_DATA( sessionInfoPtr->receiveBuffer, length );\n\n\t/* Remember how much we've got and set a block of memory following the \n\t   string to zeroes in case of any slight range errors in the free-\n\t   format text-string checks that are required further on to identify \n\t   bugs in SSH implementations */\n\tmemset( sessionInfoPtr->receiveBuffer + length, 0, 16 );\n\tsessionInfoPtr->receiveBufEnd = length;\n\n\t/* Determine which version we're talking to */\n\tswitch( sessionInfoPtr->receiveBuffer[ SSH_ID_SIZE ] )\n\t\t{\n\t\tcase '1':\n\t\t\tif( !memcmp( sessionInfoPtr->receiveBuffer + SSH_ID_SIZE, \n\t\t\t\t\t\t \"1.99\", 4 ) )\n\t\t\t\t{\n\t\t\t\t/* SSHv2 server in backwards-compatibility mode */\n\t\t\t\tsessionInfoPtr->version = 2;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Server can only do SSHv1\" ) );\n\n\t\tcase '2':\n\t\t\tsessionInfoPtr->version = 2;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid SSH version '%s'\",\n\t\t\t\t\t  sanitiseString( &sessionInfoPtr->receiveBuffer[ SSH_ID_SIZE ],\n\t\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE, 1 ) ) );\n\t\t}\n\n\t/* Find the end of the protocol version substring, i.e. locate whatever \n\t   follows the \"SSH-x.y\" portion of the ID string by searching for the\n\t   second '-' delimiter */\n\tLOOP_LARGE( ( versionStringLength = length - SSH_ID_SIZE, \\\n\t\t\t\t  versionStringPtr = sessionInfoPtr->receiveBuffer + SSH_ID_SIZE ),\n\t\t\t\tversionStringLength > 0 && *versionStringPtr != '-',\n\t\t\t\t( versionStringLength--, versionStringPtr++ ) );\n\tENSURES( LOOP_BOUND_OK );\n\tif( versionStringLength < 4 )\n\t\t{\n\t\t/* We need at least \"-x.y\" after the initial ID string, we can't \n\t\t   require any more than this because of CuteFTP (see note below) */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"%s sent malformed identifier string '%s'\", peerType,\n\t\t\t\t  sanitiseString( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE, length ) ) );\n\t\t}\n\tversionStringPtr++, versionStringLength--;\t/* Skip '-' */\n\tENSURES( versionStringLength >= 3 && \\\n\t\t\t versionStringLength < SSH_ID_MAX_SIZE );\t/* From earlier checks */\n\n\t/* Check whether the peer is using cryptlib */\n\tif( versionStringLength >= 8 && \\\n\t\t!memcmp( versionStringPtr, \"cryptlib\", 8 ) )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISCRYPTLIB );\n\t\t}\n\n\t/* Check for various servers that require special-case bug workarounds.  \n\t   The versions that we check for are:\n\n\t\tBitVise WinSSHD:\n\t\t\tThis one is hard to identify because it's built on top of their \n\t\t\tSSH library and keeps changing names:\n\t\t\n\t\t\tWinSSHD version\t\tID string\n\t\t\t---------------\t\t---------\n\t\t\t\t 3, 4\t\t\t\"sshlib: WinSSHD 3/4.yy\"\n\t\t\t\t\t5\t\t\t\"FlowSsh: WinSSHD 5.xx\"\n\t\t\t\t 6, 7\t\t\t\"FlowSsh: Bitvise SSH Server (WinSSHD) 6/7.xx\"\n\n\t\t\tIn theory we could handle this by skipping the library name and \n\t\t\tlooking further inside the string for the \"WinSSHD\" identifier, \n\t\t\tbut then there's another version that uses \"SrSshServer\" instead \n\t\t\tof \"WinSSHD\", and there's also a \"GlobalScape\" ID used by \n\t\t\tCuteFTP (which means that CuteFTP might have finally fixed their \n\t\t\tbuggy implementation of SSH by using someone else's).  As a \n\t\t\tresult we can see any of \"sshlib: <vendor>\" or \n\t\t\t\"FlowSsh: <vendor>\", which we use as the identifier.\n\t\t\t\n\t\t\tSends mismatched compression algorithm IDs, no compression \n\t\t\tclient -> server, zlib server -> client, but works fine if no \n\t\t\tcompression is selected, for versions 4.x and up.\n\n\t\t\tDoesn't support any MTI encryption algorithms in the default \n\t\t\tconfig for versions 5.35 and up (!!).\n\n\t\tCerberus FTP:\n\t\t\tAnother difficult-to-ID one, this is an FTP server with SFTP\n\t\t\tcapabilities that identifies itself using the near-anonymous\n\t\t\tID \"SshServer\".\n\n\t\tCuteFTP:\n\t\t\tDrops the connection after seeing the server hello with no\n\t\t\t(usable) error indication.  This implementation is somewhat\n\t\t\ttricky to detect since it identifies itself using the dubious\n\t\t\tvendor ID string \"1.0\" (see the ssh.com note below), this\n\t\t\tproblem still hasn't been fixed several years after the vendor \n\t\t\twas notified of it, indicating that it's unlikely to ever be \n\t\t\tfixed.  This runs into problems with other implementations like \n\t\t\tBitVise WinSSHD 5.x, which has an ID string beginning with \"1.0\" \n\t\t\t(see the comment for WinSSHD above) so when trying to identify \n\t\t\tCuteFTP we check for an exact match for \"1.0\" as the ID string.\n\t\t\t\n\t\t\tCuteFTP also uses the SSHv1 backwards-compatible version string \n\t\t\t\"1.99\" even though it can't actually do SSHv1, which means that \n\t\t\tit'll fail if it ever tries to connect to an SSHv1 peer.\n\n\t\tOpenSSH:\n\t\t\tOmits hashing the exchange hash length when creating the hash\n\t\t\tto be signed for client auth for version 2.0 (all subversions).\n\n\t\t\tGenerates an invalid keyex signature if sent an \n\t\t\tSSH_MSG_KEX_DH_GEX_REQUEST rather than an \n\t\t\tSSH_MSG_KEX_DH_GEX_REQUEST_OLD, presumably due to hashing the \n\t\t\twrong packet format, for versions around the 3.x mark.\n\n\t\t\tRequires RSA signatures to be padded out with zeroes to the RSA \n\t\t\tmodulus size for all versions from 2.5 to 3.2.\n\n\t\t\tCan't handle \"password\" as a PAM sub-method (meaning an\n\t\t\tauthentication method hint), it responds with an authentication-\n\t\t\tfailed response as soon as we send the PAM authentication\n\t\t\trequest, for versions 3.8 onwards (this doesn't look like it'll\n\t\t\tget fixed any time soon so we enable it for all newer versions\n\t\t\tuntil further notice).\n\n\t\t\tRequires and actually checks SSH_MSG_USERAUTH_PK_OK, unlike all\n\t\t\tother known implementations.\n\n\t\t\tDoesn't support MTI encryption algorithms as of 7.4 or 7.6 (the\n\t\t\trelease notes are vague on when they were removed from client \n\t\t\tvs. server, in some cases it's been seen as early as 7.1).\n\n\t\tPutty:\n\t\t\tSends zero-length SSH_MSG_IGNORE messages for version 0.59.\n\n\t\tRSSBus:\n\t\t\tPlaceholder, ID \"IP*Works!\".\n\n\t\tssh.com:\n\t\t\tThis implementation puts the version number first so if we find\n\t\t\tsomething without a vendor name at the start we treat it as an\n\t\t\tssh.com version.  However, Van Dyke's SSH server VShell also\n\t\t\tuses the ssh.com-style identification (fronti nulla fides) so\n\t\t\twhen we check for the ssh.com implementation we habe to make \n\t\t\tsure that it isn't really VShell.  In addition CuteFTP \n\t\t\tadvertises its implementation as \"1.0\" (without any vendor \n\t\t\tname), which is going to cause problems in the future when they \n\t\t\tmove to 2.x.\n\n\t\t\tOmits the DH-derived shared secret when hashing the keying\n\t\t\tmaterial for versions identified as \"2.0.0\" (all\n\t\t\tsub-versions) and \"2.0.10\".\n\n\t\t\tUses an SSH2_FIXED_KEY_SIZE-sized key for HMAC instead of the de\n\t\t\tfacto 160 bits for versions identified as \"2.0.\", \"2.1 \", \"2.1.\",\n\t\t\tand \"2.2.\" (i.e. all sub-versions of 2.0, 2.1, and 2.2), and\n\t\t\tspecifically version \"2.3.0\".  This was fixed in 2.3.1.\n\n\t\t\tOmits the signature algorithm name for versions identified as\n\t\t\t\"2.0\" and \"2.1\" (all sub-versions), requiring a complex rewrite\n\t\t\tof the signature data in order to process it.\n\n\t\t\tMishandles large window sizes in a variety of ways.  Typically\n\t\t\tfor any size over about 8M the server gets slower and slower,\n\t\t\teventually more or less grinding to halt at about 64MB \n\t\t\t(presumably some O(n^2) algorithm, although how you manage to\n\t\t\tdo this for a window-size notification is a mystery).  Some\n\t\t\tversions also reportedly require a window adjust for every 32K \n\t\t\tor so sent no matter what the actual window size is, which seems\n\t\t\tto occur for versions identified as \"2.0\" and \"2.1\" (all \n\t\t\tsub-versions).  This may be just a variant of the general mis-\n\t\t\thandling of large window sizes so we treat it as the same thing\n\t\t\tand advertise a smaller-than-optimal window which, as a side-\n\t\t\teffect, results in a constant flow of window adjusts.\n\n\t\t\tOmits hashing the exchange hash length when creating the hash\n\t\t\tto be signed for client auth for versions 2.1 and 2.2 (all\n\t\t\tsubversions).\n\n\t\t\tSends an empty SSH_SERVICE_ACCEPT response for version 2.0 (all\n\t\t\tsubversions).\n\n\t\t\tSends an empty userauth-failure response if no authentication is\n\t\t\trequired instead of allowing the auth, for uncertain versions\n\t\t\tprobably in the 2.x range.\n\n\t\t\tDumps text diagnostics (that is, raw text strings rather than\n\t\t\tSSH error packets) onto the connection if something unexpected\n\t\t\toccurs, for uncertain versions probably in the 2.x range.\n\n\t\tVan Dyke:\n\t\t\tOmits hashing the exchange hash length when creating the hash to\n\t\t\tbe signed for client auth for version 3.0 (SecureCRT = SSH) and\n\t\t\t1.7 (SecureFX = SFTP).\n\n\t\tWeOnlyDo:\n\t\t\tHas the same mismatched compression algorithm ID bug as BitVise \n\t\t\tWinSSHD (see comment above) for unknown versions above about 2.x.\n\n\t   Further quirks and peculiarities abound, some are handled automatically \n\t   by workarounds in the code and for the rest they're fortunately rare \n\t   enough (mostly for long-obsolete SSHv1 versions) that we don't have to \n\t   go out of our way to handle them */\n\tif( versionStringLength >= 8 + 3 && \\\n\t\t!memcmp( versionStringPtr, \"OpenSSH_\", 8 ) )\n\t\t{\n\t\tconst BYTE *subVersionStringPtr = versionStringPtr + 8;\n\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t  SSH_PFLAG_CHECKSPKOK );\n\t\tif( !memcmp( subVersionStringPtr, \"2.0\", 3 ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_NOHASHLENGTH );\n\t\t\t}\n\t\tif( !memcmp( subVersionStringPtr, \"3.8\", 3 ) || \\\n\t\t\t!memcmp( subVersionStringPtr, \"3.9\", 3 ) || \\\n\t\t\t( versionStringLength >= 8 + 4 && \\\n\t\t\t  !memcmp( subVersionStringPtr, \"3.10\", 4 ) ) || \\\n\t\t\t*subVersionStringPtr >= '4' )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_PAMPW );\n\t\t\t}\n\t\tif( !memcmp( subVersionStringPtr, \"3.\", 2 ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_OLDGEX );\n\t\t\t}\n\t\tif( ( !memcmp( subVersionStringPtr, \"2.\", 2 ) && \\\n\t\t\t  subVersionStringPtr[ 2 ] >= '5' ) || \\\n\t\t\t( !memcmp( subVersionStringPtr, \"3.\", 2 ) && \\\n\t\t\t  subVersionStringPtr[ 2 ] <= '2' ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_RSASIGPAD );\n\t\t\t}\n\t\tif( ( !memcmp( subVersionStringPtr, \"7.\", 2 ) && \\\n\t\t\t  subVersionStringPtr[ 2 ] >= '1' ) || \\\n\t\t\t( subVersionStringPtr[ 0 ] >= '8' ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_NOMTI );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( versionStringLength >= 14 + 4 && \\\n\t\t!memcmp( versionStringPtr, \"PuTTY_Release_\", 14 ) )\n\t\t{\n\t\tconst BYTE *subVersionStringPtr = versionStringPtr + 14;\n\n\t\tif( !memcmp( subVersionStringPtr, \"0.59\", 4 ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_ZEROLENIGNORE );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( versionStringLength >= 9 && \\\n\t\t!memcmp( versionStringPtr, \"IP*Works!\", 9 ) )\n\t\t{\n\t\t/* RSSBus: Nothing yet, this is present only as a placeholder */\n\t\t}\n\tif( versionStringLength >= 6 && \\\n\t\t!memcmp( versionStringPtr, \"JSCAPE\", 6 ) )\n\t\t{\n\t\t/* JScape: Nothing yet, this is present only as a placeholder */\n\t\t}\n\tif( versionStringLength >= 9 && \\\n\t\t!memcmp( versionStringPtr, \"SshServer\", 9 ) )\n\t\t{\n\t\t/* Cerberus FTP: Nothing yet, this is present only as a \n\t\t   placeholder */\n\t\t}\n\tif( versionStringLength >= 9 && \\\n\t\t!memcmp( versionStringPtr, \"WeOnlyDo \", 9 ) )\n\t\t{\n\t\tconst BYTE *subVersionStringPtr = versionStringPtr + 9;\n\n\t\tif( subVersionStringPtr[ 0 ] >= '2' )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSH_PFLAG_ASYMMCOPR );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( isDigit( *versionStringPtr ) )\n\t\t{\n\t\tconst BYTE *vendorIDString;\n\t\tconst int versionDigit = byteToInt( *versionStringPtr );\n\t\tint vendorIDStringLength;\n\n\t\t/* Look for a vendor ID after the version information.  This breaks \n\t\t   down the string \"[SSH-x.y-]x.yy vendor-text\" to \n\t\t   'versionStringPtr = \"x.yy\"' and 'vendorIDString = \"vendor-text\"' */\n\t\tLOOP_LARGE( ( vendorIDStringLength = versionStringLength, \\\n\t\t\t\t\t  vendorIDString = versionStringPtr ),\n\t\t\t\t\tvendorIDStringLength > 0 && *vendorIDString != ' ',\n\t\t\t\t\t( vendorIDStringLength--, vendorIDString++ ) );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( vendorIDStringLength > 1 )\n\t\t\t{\n\t\t\t/* There's a vendor ID present, skip the ' ' separator */\n\t\t\tvendorIDString++, vendorIDStringLength--;\n\t\t\t}\n\t\tENSURES( vendorIDStringLength >= 0 && \\\n\t\t\t\t vendorIDStringLength < SSH_ID_MAX_SIZE );\n\t\tswitch( versionDigit )\n\t\t\t{\n\t\t\tcase '1':\n\t\t\t\tif( versionStringLength >= 12 && \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"1.7 SecureFX\", 12 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_NOHASHLENGTH );\n\t\t\t\t\t}\n\t\t\t\tif( versionStringLength == 3 && \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"1.0\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_CUTEFTP );\n\t\t\t\t\t}\n\t\t\t\tif( ( vendorIDStringLength > 8 && \\\n\t\t\t\t\t!memcmp( vendorIDString, \"sshlib: \", 8 ) ) || \\\n\t\t\t\t\t( vendorIDStringLength > 9 && \\\n\t\t\t\t\t!memcmp( vendorIDString, \"FlowSsh: \", 9 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_ASYMMCOPR );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase '2':\n\t\t\t\tif( vendorIDStringLength >= 6 && \\\n\t\t\t\t\t!memcmp( vendorIDString, \"VShell\", 6 ) )\n\t\t\t\t\tbreak;\t/* Make sure that it isn't VShell */\n\n\t\t\t\t/* ssh.com 2.x versions have quite a number of bugs so we\n\t\t\t\t   check for them as a group */\n\t\t\t\tif( ( versionStringLength >= 5 && \\\n\t\t\t\t\t  !memcmp( versionStringPtr, \"2.0.0\", 5 ) ) || \\\n\t\t\t\t\t( versionStringLength >= 6 && \\\n\t\t\t\t\t  !memcmp( versionStringPtr, \"2.0.10\", 6 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_NOHASHSECRET );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.0\", 3 ) || \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"2.1\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_SIGFORMAT );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.0\", 3 ) || \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"2.1\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_WINDOWSIZE );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.1\", 3 ) || \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"2.2\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_NOHASHLENGTH );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.0\", 3 ) || \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"2.1\", 3 ) || \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"2.2\", 3 ) || \\\n\t\t\t\t\t( versionStringLength >= 5 && \\\n\t\t\t\t\t  !memcmp( versionStringPtr, \"2.3.0\", 5 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_HMACKEYSIZE );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.0\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_EMPTYSVCACCEPT );\n\t\t\t\t\t}\n\t\t\t\tif( !memcmp( versionStringPtr, \"2.\", 2 ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Not sure of the exact versions where this occurs */\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_EMPTYUSERAUTH | SSH_PFLAG_TEXTDIAGS );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase '3':\n\t\t\t\tif( versionStringLength >= 13 && \\\n\t\t\t\t\t!memcmp( versionStringPtr, \"3.0 SecureCRT\", 13 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_NOHASHLENGTH );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase '5':\n\t\t\t\tif( versionStringLength >= 10 && \\\n\t\t\t\t\t!memcmp( vendorIDString, \"SSH Tectia\", 10 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_DUMMYUSERAUTH );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase '6':\n\t\t\tcase '7':\n\t\t\tcase '8':\n\t\t\tcase '9':\n\t\t\t\tif( vendorIDStringLength > 9 && \\\n\t\t\t\t\t!memcmp( vendorIDString, \"FlowSsh: \", 9 ) )\n\t\t\t\t\t{\n\t\t\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t  SSH_PFLAG_NOMTI );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Connect to an SSH server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initVersion( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\tINOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Get the remote softare version, needed to handle bug-workarounds */\n\tstatus = readVersionString( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* SSHv2 hashes parts of the handshake messages for integrity-protection\n\t   purposes so we create a context for the hash.  In addition since the \n\t   handshake can retroactively switch to a different hash algorithm mid-\n\t   exchange we have to speculatively hash the messages with SHA2 as well\n\t   as SHA1 in case the other side decides to switch */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thandshakeInfo->iExchangeHashContext = createInfo.cryptHandle;\n\tif( algoAvailable( CRYPT_ALGO_SHA2 ) )\n\t\t{\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA2 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\thandshakeInfo->iExchangeHashContext = CRYPT_ERROR;\n\t\t\treturn( status );\n\t\t\t}\n\t\thandshakeInfo->iExchangeHashAltContext = createInfo.cryptHandle;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int completeHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSSH_HANDSHAKE_FUNCTION handshakeFunction;\n\tSES_SHUTDOWN_FUNCTION shutdownFunction;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\thandshakeFunction = ( SSH_HANDSHAKE_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( handshakeInfo->completeHandshake );\n\tshutdownFunction = ( SES_SHUTDOWN_FUNCTION ) \\\n\t\t\t\t\t   FNPTR_GET( sessionInfoPtr->shutdownFunction );\n\tREQUIRES( handshakeFunction != NULL );\n\tREQUIRES( shutdownFunction != NULL );\n\n\tstatus = handshakeFunction( sessionInfoPtr, handshakeInfo );\n\tdestroyHandshakeInfo( handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we need confirmation from the user before continuing, let\n\t\t   them know */\n\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\treturn( status );\n\n\t\t/* At this point we could be in the secure state so we have to\n\t\t   keep the security information around until after we've called \n\t\t   the shutdown function, which could require sending secured \n\t\t   data */\n\t\tdisableErrorReporting( sessionInfoPtr );\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tshutdownFunction( sessionInfoPtr );\n\t\tdestroySecurityContextsSSH( sessionInfoPtr );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int completeStartup( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSES_SHUTDOWN_FUNCTION shutdownFunction;\n\tSSH_HANDSHAKE_FUNCTION handshakeFunction;\n\tSSH_HANDSHAKE_INFO handshakeInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\tshutdownFunction = ( SES_SHUTDOWN_FUNCTION ) \\\n\t\t\t\t\t   FNPTR_GET( sessionInfoPtr->shutdownFunction );\n\tREQUIRES( shutdownFunction != NULL );\n\n\t/* Initialise the handshake information and begin the handshake.  Since \n\t   we don't know what type of peer we're talking to and since the \n\t   protocols aren't compatible in anything but name we have to peek at \n\t   the peer's initial communication and, in initVersion(), redirect \n\t   function pointers based on that */\n\tinitHandshakeInfo( &handshakeInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\tinitSSH2serverProcessing( &handshakeInfo );\n\telse\n\t\tinitSSH2clientProcessing( &handshakeInfo );\n\tstatus = initVersion( sessionInfoPtr, &handshakeInfo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thandshakeFunction = ( SSH_HANDSHAKE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( handshakeInfo.beginHandshake );\n\t\tENSURES( handshakeFunction != NULL );\n\t\tstatus = handshakeFunction( sessionInfoPtr, &handshakeInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we run into an error at this point we need to disable error-\n\t\t   reporting during the shutdown phase since we've already got \n\t\t   status information present from the already-encountered error */\n\t\tdestroyHandshakeInfo( &handshakeInfo );\n\t\tdisableErrorReporting( sessionInfoPtr );\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tshutdownFunction( sessionInfoPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* Exchange a key with the server */\n\thandshakeFunction = ( SSH_HANDSHAKE_FUNCTION ) \\\n\t\t\t\t\t\tFNPTR_GET( handshakeInfo.exchangeKeys );\n\tENSURES( handshakeFunction != NULL );\n\tstatus = handshakeFunction( sessionInfoPtr, &handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroySecurityContextsSSH( sessionInfoPtr );\n\t\tdestroyHandshakeInfo( &handshakeInfo );\n\t\tdisableErrorReporting( sessionInfoPtr );\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\tshutdownFunction( sessionInfoPtr );\n\t\treturn( status );\n\t\t}\n\n\t/* Complete the handshake */\n\treturn( completeHandshake( sessionInfoPtr, &handshakeInfo ) );\n\t}\n\n/* Start an SSH server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverStartup( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst char *idString = SSH_ID_STRING \"\\r\\n\";\n\tconst int idStringLen = SSH_ID_STRING_SIZE + 2;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* If we're completing a handshake that was interrupted while we got\n\t   confirmation of the client auth, skip the initial handshake stages\n\t   and go straight to the handshake completion stage */\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN ) )\n\t\t{\n\t\tSSH_HANDSHAKE_INFO handshakeInfo;\n\n\t\tinitHandshakeInfo( &handshakeInfo );\n\t\tinitSSH2serverProcessing( &handshakeInfo );\n\t\treturn( completeHandshake( sessionInfoPtr, &handshakeInfo ) );\n\t\t}\n\n\t/* Send the ID string to the client before we continue with the\n\t   handshake.  We don't have to wait for any input from the client since\n\t   we know that if we got here there's a client listening.  Note that\n\t   standard cryptlib practice for sessions is to wait for input from the\n\t   client, make sure that it looks reasonable, and only then send back a\n\t   reply of any kind.  If anything that doesn't look right arrives, we\n\t   close the connection immediately without any response.  Unfortunately\n\t   this isn't possible with SSH, which requires that the server send data\n\t   before the client does */\n\tstatus = swrite( &sessionInfoPtr->stream, idString, idStringLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Complete the handshake in the shared code */\n\treturn( completeStartup( sessionInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tControl Information Management Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSH_EXTENDED\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t OUT void *data, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( type == CRYPT_SESSINFO_SSH_CHANNEL ||\\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_TYPE || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ARG1 || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ARG2 || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE );\n\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL || \\\n\t\ttype == CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE )\n\t\t{\n\t\tstatus = getChannelAttribute( sessionInfoPtr, type, data );\n\t\t}\n\telse\n\t\t{\n\t\tMESSAGE_DATA *msgData = data;\n\n\t\tstatus = getChannelAttributeS( sessionInfoPtr, type, msgData->data, \n\t\t\t\t\t\t\t\t\t   msgData->length, &msgData->length );\n\t\t}\n\treturn( ( status == CRYPT_ERROR ) ? CRYPT_ARGERROR_NUM1 : status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tint value DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( type == CRYPT_SESSINFO_SSH_CHANNEL || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_TYPE || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ARG1 || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ARG2 || \\\n\t\t\t  type == CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE );\n\n\t/* Get the data value if it's an integer parameter */\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL || \\\n\t\ttype == CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE )\n\t\tvalue = *( ( int * ) data );\n\n\t/* If we're selecting a channel and there's unwritten data from a\n\t   previous write still in the buffer, we can't change the write\n\t   channel */\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL && sessionInfoPtr->partialWrite )\n\t\treturn( CRYPT_ERROR_INCOMPLETE );\n\n\t/* If we're creating a new channel by setting the value to CRYPT_UNUSED,\n\t   create the new channel */\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL && value == CRYPT_UNUSED )\n\t\t{\n\t\t/* If the session hasn't been activated yet, we can only create a\n\t\t   single channel during session activation, any subsequent ones\n\t\t   have to be handled later */\n\t\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) && \\\n\t\t\tgetCurrentChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t CHANNEL_READ ) != UNUSED_CHANNEL_NO )\n\t\t\treturn( CRYPT_ERROR_INITED );\n\n\t\treturn( createChannel( sessionInfoPtr ) );\n\t\t}\n\n\t/* If we 're setting the channel-active attribute, this implicitly\n\t   activates or deactivates the channel rather than setting any\n\t   attribute value */\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE )\n\t\t{\n\t\tif( value )\n\t\t\treturn( sendChannelOpen( sessionInfoPtr ) );\n\t\treturn( closeChannel( sessionInfoPtr, FALSE ) );\n\t\t}\n\n\tif( type == CRYPT_SESSINFO_SSH_CHANNEL )\n\t\tstatus = setChannelAttribute( sessionInfoPtr, type, value );\n\telse\n\t\t{\n\t\tconst MESSAGE_DATA *msgData = data;\n\n\t\tstatus = setChannelAttributeS( sessionInfoPtr, type, msgData->data, \n\t\t\t\t\t\t\t\t\t   msgData->length );\n\t\t}\n\treturn( ( status == CRYPT_ERROR ) ? CRYPT_ARGERROR_NUM1 : status );\n\t}\n#endif /* USE_SSH_EXTENDED */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttributeFunction( SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN const void *data,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst CRYPT_CONTEXT cryptContext = *( ( CRYPT_CONTEXT * ) data );\n\tMESSAGE_DATA msgData;\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tSTREAM stream;\n\tBYTE buffer[ 128 + ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ];\n\tBYTE fingerPrint[ CRYPT_MAX_HASHSIZE + 8 ];\n\tvoid *blobData DUMMY_INIT_PTR;\n\tint blobDataLength DUMMY_INIT, hashSize, pkcAlgo, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( type ) );\n\n\tif( type != CRYPT_SESSINFO_PRIVATEKEY )\n\t\treturn( CRYPT_OK );\n\n\t/* If it's an ECC key then it has to be one of NIST { P256, P384, P521 }.\n\t   Unfortunately there's no easy way to determine whether the curve \n\t   being used is an SSH-compatible one or not since the user could load\n\t   their own custom 256-bit curve, or conversely load a known NIST curve \n\t   as a series of discrete key parameters, for now we just assume that a \n\t   curve of the given size is the correct one */\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &pkcAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isEccAlgo( pkcAlgo ) )\n\t\t{\n\t\tint keySize;\n\n\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &keySize, CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( keySize != bitsToBytes( 256 ) && \\\n\t\t\tkeySize != bitsToBytes( 384 ) && \\\n\t\t\tkeySize != bitsToBytes( 521 ) )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Only the server key has a fingerprint */\n\tif( !isServer( sessionInfoPtr ) )\n\t\treturn( CRYPT_OK );\n\n\tgetHashAtomicParameters( CRYPT_ALGO_MD5, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\n\t/* The fingerprint is computed from the \"key blob\", which is different\n\t   from the server key.  The server key is the full key while the \"key\n\t   blob\" is only the raw key components (e, n for RSA, p, q, g, y for\n\t   DSA) so we have to skip the key header before we hash the key data:\n\n\t\tuint32\t\tlength\n\t\t\tstring\talgorithm\n\t\t\tbyte[]\tkey_blob\n\n\t   Note that, as with the old PGP 2.x key hash mechanism, this allows\n\t   key spoofing (although it isn't quite as bad as the PGP 2.x key\n\t   fingerprint mechanism) since it doesn't hash an indication of the key\n\t   type or format */\n\tsetMessageData( &msgData, buffer, 128 + ( CRYPT_MAX_PKCSIZE * 4 ) );\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_SSH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, buffer, msgData.length );\n\treadUint32( &stream );\t\t\t\t\t/* Length */\n\tstatus = readUniversal32( &stream );\t/* Algorithm ID */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlockRemaining( &stream, &blobData, \n\t\t\t\t\t\t\t\t\t\t\t&blobDataLength );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashFunctionAtomic( fingerPrint, CRYPT_MAX_HASHSIZE, blobData, \n\t\t\t\t\t\tblobDataLength );\n\n\t/* Add the fingerprint */\n\treturn( addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t fingerPrint, hashSize ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodSSH( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tFALSE,\t\t\t\t\t\t/* Request-response protocol */\n\t\t SESSION_FLAG_NONE,\t\t\t/* Flags */\n\t\tSSH_PORT,\t\t\t\t\t/* SSH port */\n\t\tSESSION_NEEDS_USERID |\t\t/* Client attributes */\n\t\t\tSESSION_NEEDS_PASSWORD | \\\n\t\t\tSESSION_NEEDS_KEYORPASSWORD | \\\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN,\n\t\t\t\t/* The client private key is optional, but if present it has\n\t\t\t\t   to be signature-capable */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server attributes */\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN,\n\t\t2, 2, 2,\t\t\t\t\t/* Version 2 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE,\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\tEXTRA_PACKET_SIZE + \\\n\t\t\tDEFAULT_PACKET_SIZE,\t/* Send/receive buffer size */\n\t\tSSH2_HEADER_SIZE + \\\n\t\t\tSSH2_PAYLOAD_HEADER_SIZE,/* Payload data start */\n\t\tDEFAULT_PACKET_SIZE\t\t\t/* (Default) maximum packet size */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) ) \n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverStartup );\n\t\t}\n\telse\n\t\t{ \n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, completeStartup );\n\t\t}\n\tinitSSH2processing( sessionInfoPtr );\n#ifdef USE_SSH_EXTENDED\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n#endif /* USE_SSH_EXTENDED */\n\tFNPTR_SET( sessionInfoPtr->checkAttributeFunction, checkAttributeFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  SSH Definitions Header File\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SSH_DEFINED\n\n#define _SSH_DEFINED\n\n#if defined( USE_SSH_EXTENDED ) && defined( _MSC_VER )\n  #pragma message( \"  Building with extended SSH facilities enabled.\" )\n#endif /* USE_SSH_EXTENDED with VC++ */\n\n#ifdef USE_SESSIONS\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSH Constants\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Default SSH port */\n\n#define SSH_PORT\t\t\t\t22\n\n/* Various SSH constants */\n\n#define ID_SIZE\t\t\t\t\t1\t/* ID byte */\n#define LENGTH_SIZE\t\t\t\t4\t/* Size of packet length field */\n#define UINT_SIZE\t\t\t\t4\t/* Size of integer value */\n#define PADLENGTH_SIZE\t\t\t1\t/* Size of padding length field */\n#define BOOLEAN_SIZE\t\t\t1\t/* Size of boolean value */\n\n#define SSH2_COOKIE_SIZE\t\t16\t/* Size of SSHv2 cookie */\n#define SSH2_HEADER_SIZE\t\t5\t/* Size of SSHv2 packet header */\n#define SSH2_MIN_ALGOID_SIZE\t4\t/* Size of shortest SSHv2 algo.name */\n#define SSH2_MIN_PADLENGTH_SIZE\t4\t/* Minimum amount of padding for packets */\n#define SSH2_PAYLOAD_HEADER_SIZE 9\t/* Size of SSHv2 inner payload header */\n#define SSH2_FIXED_KEY_SIZE\t\t16\t/* Size of SSHv2 fixed-size keys */\n#ifdef USE_DH1024\n  #define SSH2_DEFAULT_KEYSIZE\t128\t/* Size of SSHv2 default DH key */\n#else\n  #define SSH2_DEFAULT_KEYSIZE\t192\t/* Size of SSHv2 default DH key */\n#endif /* USE_DH1024 */\n\n/* SSH packet/buffer size information.  The extra packet data is for\n   additional non-payload information including the header, MAC, and up to\n   256 bytes of padding */\n\n#define MAX_PACKET_SIZE\t\t\t262144L\n#define EXTRA_PACKET_SIZE\t\t512\n#define DEFAULT_PACKET_SIZE\t\t16384\n#define MAX_WINDOW_SIZE\t\t\t( MAX_INTLENGTH - 8192 )\n\n/* By default cryptlib uses DH key agreement, which is supported by all \n   servers.  It's also possible to use ECDH key agreement, however due to\n   SSH's braindamaged way of choosing algorithms the peer will always go\n   for ECDH if it can handle it (see the comment in sesion/ssh2_svr.c for\n   more on this), so we disable ECDH by default.  To use ECDH key agreement \n   in preference to DH, uncomment the following */\n\n/* #define PREFER_ECC */\n#if defined( PREFER_ECC ) && defined( _MSC_VER )\n  #pragma message( \"  Building with ECC preferred for SSH.\" )\n#endif /* PREFER_ECC && Visual C++ */\n#if defined( PREFER_ECC ) && \\\n\t!( defined( USE_ECDH ) && defined( USE_ECDSA ) )\n  #error PREFER_ECC can only be used with ECDH and ECDSA enabled\n#endif /* PREFER_ECC && !( USE_ECDH && USE_ECDSA ) */\n\n/* SSH protocol-specific flags that encode details of implementation bugs \n   that we need to work around */\n\n#define SSH_PFLAG_NONE\t\t\t0x00000/* No protocol-specific flags */\n#define SSH_PFLAG_HMACKEYSIZE\t0x00001/* Peer uses short HMAC keys */\n#define SSH_PFLAG_SIGFORMAT\t\t0x00002/* Peer omits signature algo name */\n#define SSH_PFLAG_NOHASHSECRET\t0x00004/* Peer omits secret in key derive */\n#define SSH_PFLAG_NOHASHLENGTH\t0x00008/* Peer omits length in exchange hash */\n#define SSH_PFLAG_RSASIGPAD\t\t0x00010/* Peer requires zero-padded RSA sig.*/\n#define SSH_PFLAG_WINDOWSIZE\t0x00020/* Peer mishandles large window sizes */\n#define SSH_PFLAG_TEXTDIAGS\t\t0x00040/* Peer dumps text diagnostics on error */\n#define SSH_PFLAG_PAMPW\t\t\t0x00080/* Peer chokes on \"password\" as PAM submethod */\n#define SSH_PFLAG_DUMMYUSERAUTH\t0x00100/* Peer requires dummy userAuth message */\n#define SSH_PFLAG_EMPTYUSERAUTH\t0x00200/* Peer sends empty userauth-failure response */\n#define SSH_PFLAG_ZEROLENIGNORE\t0x00400/* Peer sends zero-length SSH_IGNORE */\n#define SSH_PFLAG_ASYMMCOPR\t\t0x00800/* Peer sends asymmetric compression algos */\n#define SSH_PFLAG_EMPTYSVCACCEPT 0x01000/* Peer sends empty SSH_SERVICE_ACCEPT */\n#define SSH_PFLAG_CHECKSPKOK\t0x02000/* Peer checks SSH_MSG_USERAUTH_PK_OK */\n#define SSH_PFLAG_NOMTI\t\t\t0x04000/* Peer doesn't support any MTI algorithms */\n#define SSH_PFLAG_OLDGEX\t\t0x08000/* Peer requires old-style KEX_DH_GEX_REQ */\n#define SSH_PFLAG_CUTEFTP\t\t0x10000/* CuteFTP, drops conn.during handshake */\n#define SSH_PFLAG_CTR\t\t\t0x20000/* Use CTR mode synthesised from ECB */\n#define SSH_PFLAG_MAX\t\t\t0x3FFFF/* Maximum possible flag value */\n\n/* Various data sizes used for read-ahead and buffering.  The minimum SSH\n   packet size is used to determine how much data we can read when reading\n   a packet header, the SSH header remainder size is how much data we've\n   got left once we've extracted just the length but no other data */\n\n#define MIN_PACKET_SIZE\t\t\t16\n#define SSH_HEADER_REMAINDER_SIZE ( MIN_PACKET_SIZE - LENGTH_SIZE )\n\n/* SSH ID information */\n\n#define SSH_ID\t\t\t\t\t\"SSH-\"\t\t/* Start of SSH ID */\n#define SSH_ID_SIZE\t\t\t\t4\t/* Size of SSH ID */\n#define SSH_VERSION_SIZE\t\t4\t/* Size of SSH version */\n#define SSH_ID_MAX_SIZE\t\t\t255\t/* Max.size of SSH ID string */\n#define SSH_ID_STRING\t\t\t\"SSH-2.0-cryptlib\"\t/* cryptlib SSH ID strings */\n#define SSH_ID_STRING_SIZE\t\t16\t/* Size of ID strings */\n\n/* SSH packet types.  Note that the keyex (static DH keys), keyex_gex \n   (ephemeral DH keys), and keyex_ecdh (static ECDH keys) message types \n   overlap */\n\n#define SSH_MSG_DISCONNECT\t\t1\t/* Disconnect session */\n#define SSH_MSG_IGNORE\t\t\t2\t/* No-op */\n#define SSH_MSG_UNIMPLEMENTED\t3\t/* Treat as disconnect */\n#define SSH_MSG_DEBUG\t\t\t4\t/* No-op */\n#define SSH_MSG_SERVICE_REQUEST 5\t/* Request authentiction */\n#define SSH_MSG_SERVICE_ACCEPT\t6\t/* Acknowledge request */\n#define SSH_MSG_EXT_INFO\t\t7\t/* Extension info */\n#define SSH_MSG_KEXINIT\t\t\t20\t/* Hello */\n#define SSH_MSG_NEWKEYS\t\t\t21\t/* Change cipherspec */\n#define SSH_MSG_KEXDH_INIT\t\t30\t/* DH, phase 1 */\n#define SSH_MSG_KEXDH_REPLY\t\t31\t/* DH, phase 2 */\n#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30 /* Ephem.DH key request */\n#define SSH_MSG_KEX_DH_GEX_GROUP 31\t/* Ephem.DH key response */\n#define SSH_MSG_KEX_DH_GEX_INIT\t32\t/* Ephem.DH, phase 1 */\n#define SSH_MSG_KEX_DH_GEX_REPLY 33\t/* Ephem.DH, phase 2 */\n#define SSH_MSG_KEX_DH_GEX_REQUEST 34 /* Ephem.DH key request */\n#define SSH_MSG_KEX_ECDH_INIT\t30\t/* ECDH, phase 1 */\n#define SSH_MSG_KEX_ECDH_REPLY\t31\t/* ECDH, phase 2 */\n#define SSH_MSG_USERAUTH_REQUEST 50 /* Request authentication */\n#define SSH_MSG_USERAUTH_FAILURE 51 /* Authentication failed */\n#define SSH_MSG_USERAUTH_SUCCESS 52 /* Authentication succeeded */\n#define SSH_MSG_USERAUTH_BANNER 53\t/* No-op */\n#define SSH_MSG_USERAUTH_INFO_REQUEST 60 /* Generic auth.svr.request */\n#define SSH_MSG_USERAUTH_INFO_RESPONSE 61 /* Generic auth.cli.response */\n#define SSH_MSG_USERAUTH_PK_OK\t60\t/* Pubkey partial auth.continue */\n#define SSH_MSG_GLOBAL_REQUEST\t80\t/* Perform a global ioctl */\n#define SSH_MSG_GLOBAL_SUCCESS\t81\t/* Global request succeeded */\n#define SSH_MSG_GLOBAL_FAILURE\t82\t/* Global request failed */\n#define\tSSH_MSG_CHANNEL_OPEN\t90\t/* Open a channel over an SSH link */\n#define\tSSH_MSG_CHANNEL_OPEN_CONFIRMATION 91\t/* Channel open succeeded */\n#define SSH_MSG_CHANNEL_OPEN_FAILURE 92\t/* Channel open failed */\n#define\tSSH_MSG_CHANNEL_WINDOW_ADJUST 93\t/* No-op */\n#define SSH_MSG_CHANNEL_DATA\t94\t/* Data */\n#define SSH_MSG_CHANNEL_EXTENDED_DATA 95\t/* Out-of-band data */\n#define SSH_MSG_CHANNEL_EOF\t\t96\t/* EOF */\n#define SSH_MSG_CHANNEL_CLOSE\t97\t/* Close the channel */\n#define SSH_MSG_CHANNEL_REQUEST 98\t/* Perform a channel ioctl */\n#define SSH_MSG_CHANNEL_SUCCESS 99\t/* Channel request succeeded */\n#define SSH_MSG_CHANNEL_FAILURE 100/* Channel request failed */\n\n/* Special-case expected-packet-type values that are passed to\n   readHSPacketSSH2()/readAuthPacketSSH2() to handle situations where more \n   than one packet type can be received (see the code in readHSPacket() for \n   details):\n   \n\tMSG_SPECIAL_USERAUTH can return MSG_USERAUTH_FAILURE which indicates \n\t\ta wrong password used iff it's a response to the client sending a \n\t\tpassword, or MSG_EXT_INFO if the peer is using extensions.\n\n\tMSG_SPECIAL_USERAUTH_PAM can return the same values as \n\t\tMSG_SPECIAL_USERAUTH, but can also return MSG_USERAUTH_INFO_REQUEST \n\t\tas part of the multi-iteration PAM process.\n\n\tMSG_SPECIAL_CHANNEL can return SSH_MSG_CHANNEL_OPEN_FAILURE to indicate\n\t\tthat the request was successfully processed but the channel wasn't\n\t\topened.\n\n\tMSG_SPECIAL_REQUEST can return either MSG_GLOBAL_REQUEST or \n\t\tMSG_CHANNEL_REQUEST when the other side sends a general request.\n\n\tMSG_SPECIAL_SERVICEACCEPT can return either MSG_SERVICEACCEPT or \n\t\tMSG_EXT_INFO if the peer is using extensions */\n\n#define SSH_MSG_SPECIAL_FIRST\t\t500\t/* Boundary for _SPECIAL types */\n#define SSH_MSG_SPECIAL_USERAUTH\t501\t/* Value to handle SSH combined auth.*/\n#define SSH_MSG_SPECIAL_USERAUTH_PAM 502 /* Value to handle SSH PAM auth.*/\n#define SSH_MSG_SPECIAL_CHANNEL\t\t503\t/* Value to handle channel open */\n#define SSH_MSG_SPECIAL_REQUEST\t\t504\t/* Value to handle SSH global/channel req.*/\n#define SSH_MSG_SPECIAL_SERVICEACCEPT 505\t/* Value to handle optional ext.info */\n#define SSH_MSG_SPECIAL_LAST\t\t506\t/* Last valid _SPECIAL type */\n\n/* SSH disconnection codes */\n\nenum { SSH_DISCONNECT_NONE, SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, \n\t   SSH_DISCONNECT_PROTOCOL_ERROR, SSH_DISCONNECT_KEY_EXCHANGE_FAILED, \n\t   SSH_DISCONNECT_RESERVED, SSH_DISCONNECT_MAC_ERROR, \n\t   SSH_DISCONNECT_COMPRESSION_ERROR, SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, \n\t   SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, \n\t   SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, SSH_DISCONNECT_CONNECTION_LOST,\n\t   SSH_DISCONNECT_BY_APPLICATION, SSH_DISCONNECT_TOO_MANY_CONNECTIONS,\n\t   SSH_DISCONNECT_AUTH_CANCELLED_BY_USER, \n\t   SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE, \n\t   SSH_DISCONNECT_ILLEGAL_USER_NAME, SSH_DISCONNECT_LAST };\n\n/* SSH channel open failure codes */\n\n#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED\t\t\t1\n#define SSH_OPEN_CONNECT_FAILED\t\t\t\t\t\t\t2\n#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE\t\t\t\t\t3\n#define SSH_OPEN_RESOURCE_SHORTAGE\t\t\t\t\t\t4\n\n/* The status of the SSH protocol negotiation, which determines which packet \n   types are valid at this point */\n\ntypedef enum {\n\tSSH_PROTOSTATE_NONE,\t/* No protocol state */\n\tSSH_PROTOSTATE_HANDSHAKE, /* Handshake */\n\tSSH_PROTOSTATE_AUTH,\t/* Authentication */\n\tSSH_PROTOSTATE_DATA,\t/* Data transfer */\n\tSSH_PROTOSTATE_LAST\t\t/* Last possible protocol state */\n\t} SSH_PROTOCOL_STATE;\n\n/* An indicator of any additional information that we may need to stuff into\n   the SSH handshake when we write algorithm ID information */\n\ntypedef enum {\n\tSSH_ALGOSTRINGINFO_NONE,/* No addition information */\n\tSSH_ALGOSTRINGINFO_EXTINFO,\t/* Client extension-neg.indicator */\n\tSSH_ALGOSTRINGINFO_EXTINFO_ALTDHALGOS,\t/* EXTINFO + alt.DH algos */\n\tSSH_ALGOSTRINGINFO_LAST\t/* Last possible protocol state */\n\t} SSH_ALGOSTRINGINFO_TYPE;\n\n/* SSH requires the use of a number of additional (pseudo)-algorithm\n   types that don't correspond to normal cryptlib algorithms.  To handle\n   these, we define pseudo-algoID values that fall within the range of\n   the normal algorithm ID types but that aren't normal algorithm IDs.\n   \n   In addition to the standard (pseudo)-algorithm types, SSH's \n   schizophrenic error reporting can also indicate that no particular\n   algorithm is reuqired (or at least any algorithm is indicated and\n   it's up to the other side to guess which), so we define a special \n   value for that as well */\n\n#define CRYPT_PSEUDOALGO_AMBIGUOUS\t( CRYPT_ALGO_LAST_CONVENTIONAL - 3 )\n#define CRYPT_PSEUDOALGO_PASSWORD\t( CRYPT_ALGO_LAST_CONVENTIONAL - 2 )\n#define CRYPT_PSEUDOALGO_PAM\t\t( CRYPT_ALGO_LAST_CONVENTIONAL - 1 )\n#define CRYPT_PSEUDOALGO_LAST\t\t( CRYPT_ALGO_LAST_CONVENTIONAL )\n\n#define MK_ALGO( value )\t\t\t( CRYPT_ALGO_TYPE ) ( CRYPT_##value )\n\n/* The size of the encoded DH keyex value and the requested DHE key size, \n   which we have to store in encoded form so that we can hash them later in \n   the handshake */\n\n#define MAX_ENCODED_KEYEXSIZE\t\t( CRYPT_MAX_PKCSIZE + 16 ) \n#define ENCODED_REQKEYSIZE\t\t\t( UINT_SIZE * 3 )\n\n/* Check whether an algorithm ID is one of the above pseudo-algorithm\n   types */\n\n#define isPseudoAlgo( algorithm ) \\\n\t\t( ( algorithm ) >= CRYPT_PSEUDOALGO_PASSWORD && \\\n\t\t  ( algorithm ) <= CRYPT_PSEUDOALGO_PAM )\n\n/* SSH algorithms are grouped into classes such as keyex algorithms or MAC\n   algorithms, the following type identifies the different algorithm \n   classes */\n\ntypedef enum {\n\tSSH_ALGOCLASS_NONE,\t\t/* No algorithm class */\n\tSSH_ALGOCLASS_KEYEX,\t/* Keyex algorithms */\n\tSSH_ALGOCLASS_KEYEX_NOECC,/* Keyex algorithms limited to non-ECC algos */\n\tSSH_ALGOCLASS_ENCR,\t\t/* Encryption algorithms */\n\tSSH_ALGOCLASS_SIGN,\t\t/* Signature algorithms */\n\tSSH_ALGOCLASS_MAC,\t\t/* MAC algorithms */\n\tSSH_ALGOCLASS_COPR,\t\t/* Compression algorithms */\n\tSSH_ALGOCLASS_LAST\t\t/* Last possible algorithm class */\n\t} SSH_ALGOCLASS_TYPE;\n\n/* Values for working with SSH channels.  Channels have a 32-bit ID\n   (although no sane implementation uses very large values), to deal with\n   range checking for these we limit them to LONG_MAX in 32-bit systems.\n\n   SSH channels have a number of SSH-internal attributes that aren't exposed \n   as cryptlib-wide attribute types.  The following values are used to \n   access SSH-internal channel attributes */\n\n#ifdef SYSTEM_64BIT\n  #define CHANNEL_MAX\t\t\t\t0x0FFFFFFFFUL\n#else\n  #define CHANNEL_MAX\t\t\t\tLONG_MAX\n#endif /* 32- vs 64-bit systems */\n\ntypedef enum {\n\tSSH_ATTRIBUTE_NONE,\t\t\t\t\t\t/* No channel attribute */\n\tSSH_ATTRIBUTE_ACTIVE,\t\t\t\t\t/* Channel is active */\n\tSSH_ATTRIBUTE_WINDOWCOUNT,\t\t\t\t/* Data window count */\n\tSSH_ATTRIBUTE_WINDOWSIZE,\t\t\t\t/* Data window size */\n\tSSH_ATTRIBUTE_ALTCHANNELNO,\t\t\t\t/* Secondary channel no. */\n\tSSH_ATTRIBUTE_LAST\t\t\t\t\t\t/* Last channel attribute */\n\t} SSH_ATTRIBUTE_TYPE;\n\n/* Check whether a DH/ECDH value is valid for a given server key size.  The \n   check is slightly different for the ECC version because the value is\n   a composite ECC point with two coordinates, so we have to divide the \n   length by two to get the size of a single coordinate.  \n   \n   In addition when we print an error message based on the check we need to \n   extract the underlying size from the overall data item.  The reason for \n   masking the LSB for the DH extraction is because the value can have a\n   leading zero byte that isn't counted as part of the length */\n\n#define isValidDHsize( value, serverKeySize, extraLength ) \\\n\t\t( ( value ) > ( ( serverKeySize ) - 8 ) + ( extraLength ) && \\\n\t\t  ( value ) < ( ( serverKeySize ) + 2 ) + ( extraLength ) )\n#define extractDHsize( value, extraLength ) \\\n\t\t( ( value & ~1 ) - extraLength )\n#define isValidECDHsize( value, serverKeySize, extraLength ) \\\n\t\t( ( value ) / 2 > ( ( serverKeySize ) - 8 ) + ( extraLength ) && \\\n\t\t  ( value ) / 2 < ( ( serverKeySize ) + 2 ) + ( extraLength ) )\n#define extractECDHsize( value, extraLength ) \\\n\t\t( ( value - ( extraLength + 1 ) ) / 2 )\n\n/* The following macro can be used to enable dumping of PDUs to disk.  As a\n   safeguard, this only works in the Win32 debug version to prevent it from\n   being accidentally enabled in any release version */\n\n#if defined( __WIN32__ ) && !defined( NDEBUG )\n  #define DEBUG_DUMP_SSH( buffer, length, isRead ) \\\n\t\t  debugDumpSSH( sessionInfoPtr, buffer, length, isRead )\n\n  STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n  void debugDumpSSH( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t IN_BUFFER( length ) const void *buffer, \n\t\t\t\t\t IN_LENGTH_SHORT const int length,\n\t\t\t\t\t const BOOLEAN isRead );\n#else\n  #define DEBUG_DUMP_SSH( buffer, length, isRead )\n#endif /* Win32 debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSH Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Mapping of SSH algorithm names to cryptlib algorithm IDs, in preferred\n   algorithm order.  Some of the algorithms are pure algorithms while others\n   are more like cipher suites, in order to check whether they're available\n   for use we have to map the suite pseudo-value into one or more actual\n   algorithms, which are given via the checkXXXAlgo values */\n\ntypedef struct {\n\t/* Mapping from algorithm name to cryptlib algorithm ID.  The\n\t   \"encryption\" algorithm may not be a real cryptlib algorithm type but \n\t   an SSH-specific pseudo-algorithm in the CRYPT_PSEUDOALGO_xxx \n\t   range, for example CRYPT_PSEUDOALGO_PASSWORD */\n\tBUFFER_FIXED( nameLen ) \\\n\tconst char *name;\t\t\t\t\t\t/* Algorithm name */\n\tconst int nameLen;\n\tconst CRYPT_ALGO_TYPE algo;\t\t\t\t/* Algorithm ID */\n\n\t/* Optional parameters needed when the algorithm actually represents a \n\t   cipher suite.  The subAlgo is typically an algorithm but may be a \n\t   mode for conventional ciphers, the parameter is typically the key\n\t   size */\n\tconst int subAlgo;\n\tconst int parameter;\n\t} ALGO_STRING_INFO;\n\n/* SSH handshake state information.  This is passed around various\n   subfunctions that handle individual parts of the handshake */\n\n#ifdef SH\n  /* VxWorks defines 'SH' (for SuperH CPUs), so we have to undefine it to\n     allow the following struct to be declared.  The VxWorks include file\n\t order is such that it comes after osspec.h is included, so we can't\n\t cover up the problem in that */\n  #undef SH\n#endif /* SH */\n\nstruct SH;\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tint ( *SSH_HANDSHAKE_FUNCTION )( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT struct SH *handshakeInfo );\n\ntypedef struct SH {\n\t/* SSH exchange hash */\n\tBUFFER_FIXED( SSH2_COOKIE_SIZE ) \\\n\tBYTE cookie[ SSH2_COOKIE_SIZE + 8 ];\t/* Anti-spoofing cookie */\n\tBUFFER_FIXED( CRYPT_MAX_HASHSIZE ) \\\n\tBYTE sessionID[ CRYPT_MAX_HASHSIZE + 8 ];/* Session ID/exchange hash */\n\tint sessionIDlength;\n\tCRYPT_ALGO_TYPE exchangeHashAlgo;\t\t/* Exchange hash algorithm */\n\tCRYPT_CONTEXT iExchangeHashContext, iExchangeHashAltContext;\n\t\t\t\t\t\t\t\t\t\t\t/* Hash of exchanged information */\n\n\t/* Information needed to compute the session ID.  SSH requires the \n\t   client and server DH/ECDH values (along with various other things, \n\t   but these are hashed inline).  The SSH values are in MPI-encoded \n\t   form so we need to reserve a little extra room for the length and \n\t   leading zero-padding */\n\tBUFFER( MAX_ENCODED_KEYEXSIZE, clientKeyexValueLength ) \\\n\tBYTE clientKeyexValue[ MAX_ENCODED_KEYEXSIZE + 8 ];\n\tBUFFER( MAX_ENCODED_KEYEXSIZE, serverKeyexValueLength ) \\\n\tBYTE serverKeyexValue[ MAX_ENCODED_KEYEXSIZE + 8 ];\n\tint clientKeyexValueLength, serverKeyexValueLength;\n\n\t/* Encryption algorithm and key information */\n\tCRYPT_ALGO_TYPE pubkeyAlgo;\t\t\t\t/* Host signature algo */\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t\t\t/* Host signature hash algo */\n\tint cryptKeysize;\t\t\t\t\t\t/* Size of session key */\n\tBUFFER( CRYPT_MAX_PKCSIZE, secretValueLength ) \\\n\tBYTE secretValue[ CRYPT_MAX_PKCSIZE + 8 ];\t/* Shared secret value */\n\tint secretValueLength;\n\n\t/* DH/ECDH key agreement context and the client requested DH key size \n\t   for the key exchange.  Alongside the actual key size we also store \n\t   the original encoded form, which has to be hashed as part of the \n\t   exchange hash.  The long-term host key is stored as the session \n\t   information iKeyexCryptContext for the client and privateKey for the \n\t   server.   Since ECDH doesn't just entail a new algorithm but an \n\t   entire cipher suite, we provide a flag to make checking for this \n\t   easier */\n\tCRYPT_ALGO_TYPE keyexAlgo;\t\t\t\t/* Keyex algo */\n\tCRYPT_CONTEXT iServerCryptContext;\n\tint serverKeySize, requestedServerKeySize;\n\tBUFFER( ENCODED_REQKEYSIZE, encodedReqKeySizesLength ) \\\n\tBYTE encodedReqKeySizes[ ENCODED_REQKEYSIZE + 8 ];\n\tint encodedReqKeySizesLength;\n\tBOOLEAN isFixedDH;\t\t\t\t\t\t/* Whether DH is fixed or negotiated */\n\tBOOLEAN isECDH;\t\t\t\t\t\t\t/* Use of ECC cipher suite */\n\n\t/* Miscellaneous information */\n\tBOOLEAN sendExtInfo;\t\t\t\t\t/* Whether to send extended info */\n\n\t/* Table mapping SSH algorithm names to cryptlib algorithm IDs.  This \n\t   serves two purposes, firstly by declaring it once in ssh2.c and \n\t   referring to it via pointers we can make the data static const, which \n\t   is necessary in some environments to get them into the read-only \n\t   segment, and secondly for the server where we advertise algorithm X \n\t   to the client it allows us to switch to a restricted table that only\n\t   allows algorithm X in return from the client */\n\tconst ALGO_STRING_INFO *algoStringPubkeyTbl;\n\tint algoStringPubkeyTblNoEntries;\n\n\t/* Function pointers to handshaking functions.  These are set up as\n\t   required depending on whether the session is client or server */\n\tFNPTR beginHandshake, exchangeKeys, completeHandshake;\n\t} SSH_HANDSHAKE_INFO;\n\n/* Channel number and ID used to mark an unused channel */\n\n#define UNUSED_CHANNEL_NO\tCRYPT_ERROR\n#define UNUSED_CHANNEL_ID\t0\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSH Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike SSL, SSH only hashes portions of the handshake, and even then not\n   complete packets but arbitrary bits and pieces.  In order to perform the\n   hashing, we have to be able to bookmark positions in a stream to allow\n   the data at that point to be hashed once it's been encoded or decoded.  \n   The following macros set and complete a bookmark.\n\n   When we create or continue a packet stream, the packet type is written\n   before we can set the bookmark.  To handle this, we also provide a macro\n   that sets the bookmark for a full packet by adjusting for the packet type\n   that's already been written */\n\n#define streamBookmarkSet( stream, offset ) \\\n\t\toffset = stell( stream )\n#define streamBookmarkSetFullPacket( stream, offset ) \\\n\t\toffset = stell( stream ) - ID_SIZE\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint streamBookmarkComplete( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT_OPT_PTR void **dataPtrPtr, \n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\tIN_DATALENGTH const int position );\n\n/* Prototypes for functions in ssh.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSSH( IN const SESSION_INFO *sessionInfoPtr );\n\n/* Prototypes for functions in ssh2.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initHandshakeCrypt( INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint hashHandshakeStrings( INOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  IN_BUFFER( clientStringLength ) \\\n\t\t\t\t\t\t\t\tconst void *clientString,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int clientStringLength,\n\t\t\t\t\t\t  IN_BUFFER( serverStringLength ) \\\n\t\t\t\t\t\t\t\tconst void *serverString,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int serverStringLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nint readAlgoString( INOUT STREAM *stream, \n\t\t\t\t\tIN_ARRAY( noAlgoStringEntries ) \\\n\t\t\t\t\t\tconst ALGO_STRING_INFO *algoInfo,\n\t\t\t\t\tIN_RANGE( 1, 100 ) const int noAlgoStringEntries, \n\t\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *algo, \n\t\t\t\t\tconst BOOLEAN useFirstMatch, \n\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoString( INOUT STREAM *stream, \n\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE algo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoStringEx( INOUT STREAM *stream, \n\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE algo,\n\t\t\t\t\t   IN_INT_SHORT_Z const int subAlgo,\n\t\t\t\t\t   IN_INT_SHORT_Z const int parameter,\n\t\t\t\t\t   IN_ENUM_OPT( SSH_ALGOSTRINGINFO ) \\\n\t\t\t\t\t\t\tconst SSH_ALGOSTRINGINFO_TYPE algoStringInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeAlgoList( INOUT STREAM *stream, \n\t\t\t\t   IN_ARRAY( noAlgoStringInfoEntries ) \\\n\t\t\t\t\t\tconst ALGO_STRING_INFO *algoStringInfoTbl,\n\t\t\t\t   IN_RANGE( 1, 10 ) const int noAlgoStringInfoEntries );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoClassList( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ENUM( SSH_ALGOCLASS ) \\\n\t\t\t\t\t\t\tconst SSH_ALGOCLASS_TYPE algoClass );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint processHelloSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *keyexLength,\n\t\t\t\t\t const BOOLEAN isServer );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readExtensionsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeExtensionsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t    INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint checkReadPublicKey( INOUT STREAM *stream,\n\t\t\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *pubkeyAlgo,\n\t\t\t\t\t\tOUT_INT_SHORT_Z int *keyDataStart,\n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo );\n\n/* Prototypes for functions in ssh2_authc.c/ssh2_auths.c  */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processClientAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processServerAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   const SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t   const BOOLEAN userInfoPresent );\n\n/* Prototypes for functions in ssh2_chn.c */\n\ntypedef enum { CHANNEL_NONE, CHANNEL_READ, CHANNEL_WRITE,\n\t\t\t   CHANNEL_BOTH, CHANNEL_LAST } CHANNEL_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createChannel( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint addChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\tIN const long channelNo,\n\t\t\t\tIN_LENGTH_MIN( PACKET_SIZE_MIN ) const int maxPacketSize, \n\t\t\t\tIN_BUFFER( typeLen ) const void *type,\n\t\t\t\tIN_LENGTH_SHORT const int typeLen, \n\t\t\t\tIN_BUFFER_OPT( arg1Len ) const void *arg1, \n\t\t\t\tIN_LENGTH_SHORT_Z const int arg1Len );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   IN const long channelNo,\n\t\t\t\t   IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType,\n\t\t\t\t   const BOOLEAN deleteLastChannel );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   IN const long channelNo,\n\t\t\t\t   IN_ENUM_OPT( CHANNEL ) const CHANNEL_TYPE channelType );\nCHECK_RETVAL_RANGE_NOERROR( UNUSED_CHANNEL_NO, CHANNEL_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nlong getCurrentChannelNo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType );\nCHECK_RETVAL_ENUM( CHANNEL ) STDC_NONNULL_ARG( ( 1 ) ) \\\nCHANNEL_TYPE getChannelStatusByChannelNo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  IN const long channelNo );\nCHECK_RETVAL_ENUM( CHANNEL ) STDC_NONNULL_ARG( ( 1 ) ) \\\nCHANNEL_TYPE getChannelStatusByAddr( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_BUFFER( addrInfoLen ) const char *addrInfo,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int addrInfoLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t OUT_INT_Z int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelAttributeS( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelExtAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( SSH_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tconst SSH_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\tOUT_INT_Z int *value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setChannelAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t IN_INT_SHORT const int value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint setChannelAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t  IN_LENGTH_TEXT const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setChannelExtAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const SSH_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\tIN_INT_Z const int value );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint enqueueResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t IN_RANGE( 1, 255 ) const int type,\n\t\t\t\t\t IN_RANGE( 0, 4 ) const int noParams, \n\t\t\t\t\t IN const long channelNo,\n\t\t\t\t\t const int param1, const int param2, const int param3 );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendEnqueuedResponse( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint enqueueChannelData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tIN_RANGE( 1, 255 ) const int type,\n\t\t\t\t\t\tIN const long channelNo, \n\t\t\t\t\t\tconst int param );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint appendChannelData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int offset );\n\n/* Prototypes for functions in ssh2_msg.c */\n\nCHECK_RETVAL_RANGE_NOERROR( 10000, MAX_WINDOW_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getWindowSize( const SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint closeChannel( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t  const BOOLEAN closeAllChannels );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelControlMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t  INOUT STREAM *stream );\n\n/* Prototypes for functions in ssh2_msgc.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendChannelOpen( INOUT SESSION_INFO *sessionInfoPtr );\n\n/* Prototypes for functions in ssh2_msgs.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelOpen( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t\t   IN const long prevChannelNo );\n\n/* Prototypes for functions in ssh2_cry.c */\n\ntypedef enum { MAC_NONE, MAC_START, MAC_END, MAC_LAST } MAC_TYPE;\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSecurityInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSecurityContextsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySecurityContextsSSH( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initDHcontextSSH( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *keySize,\n\t\t\t\t\t  IN_BUFFER_OPT( keyDataLength ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int keyDataLength,\n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int requestedKeySize );\n#ifdef USE_ECDH\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initECDHcontextSSH( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *keySize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo );\n#endif /* USE_ECDH */\n#ifdef USE_SSH_CTR\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint ctrModeCrypt( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t  INOUT_BUFFER_FIXED( blockSize ) void *counter,\n\t\t\t\t  IN_LENGTH_IV const int counterSize,\n\t\t\t\t  INOUT_BUFFER_FIXED( dataLength ) void *data,\n\t\t\t\t  IN_LENGTH const int dataLength );\n#endif /* USE_SSH_CTR */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint completeKeyex( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t   const BOOLEAN isServer );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashAsString( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t  IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashAsMPI( IN_HANDLE const CRYPT_CONTEXT iHashContext, \n\t\t\t   IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t   IN_LENGTH_SHORT const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint checkMacSSH( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t IN_INT const long seqNo,\n\t\t\t\t IN_BUFFER( dataMaxLength ) const BYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t IN_DATALENGTH_Z const int dataLength, \n\t\t\t\t IN_RANGE( 16, CRYPT_MAX_HASHSIZE ) const int macLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint checkMacSSHIncremental( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t\t\t\tIN_INT_Z const long seqNo,\n\t\t\t\t\t\t\tIN_BUFFER( dataMaxLength ) const BYTE *data, \n\t\t\t\t\t\t\tIN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int packetDataLength, \n\t\t\t\t\t\t\tIN_ENUM( MAC ) const MAC_TYPE macType, \n\t\t\t\t\t\t\tIN_RANGE( 16, CRYPT_MAX_HASHSIZE ) const int macLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createMacSSH( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t  IN_INT const long seqNo,\n\t\t\t\t  IN_BUFFER( dataMaxLength ) BYTE *data, \n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  IN_DATALENGTH const int dataLength );\n\n/* Prototypes for functions in ssh2_rd.c */\n\n#ifdef USE_ERRMSGS\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSHPacketName( IN_RANGE( 0, 255 ) const int packetType );\n#else\n#define getSSHPacketName( packetType )\t\"unknown\"\n#endif /* USE_ERRMSGS */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint readPacketHeaderSSH2( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\tSSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\t\tconst int expectedType, \n\t\t\t\t\t\t  OUT_LENGTH_Z int *packetLength,\n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *packetExtraLength,\n\t\t\t\t\t\t  INOUT SSH_INFO *sshInfo,\n\t\t\t\t\t\t  INOUT READSTATE_INFO *readInfo,\n\t\t\t\t\t\t  const SSH_PROTOCOL_STATE protocolState );\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint readHSPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\tSSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\tint expectedType,\n\t\t\t\t\t  IN_RANGE( 1, 1024 ) const int minPacketSize );\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint readAuthPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tIN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t  SSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\tint expectedType,\n\t\t\t\t\t\tIN_RANGE( 1, 1024 ) const int minPacketSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getDisconnectInfo( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   INOUT STREAM *stream );\n\n/* Prototypes for functions in ssh2_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSH( OUT STREAM *stream, \n\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t   SSH_MSG_CHANNEL_FAILURE ) \n\t\t\t\t\t\t\tconst int packetType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSHEx( OUT STREAM *stream, \n\t\t\t\t\t\t   const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   IN_DATALENGTH const int bufferSize, \n\t\t\t\t\t\t   IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\t SSH_MSG_CHANNEL_FAILURE ) \n\t\t\t\t\t\t\t\tconst int packetType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint continuePacketStreamSSH( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\t   SSH_MSG_CHANNEL_FAILURE ) \\\n\t\t\t\t\t\t\t\tconst int packetType,\n\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *packetOffset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPlaintextPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_DATALENGTH_Z const int offset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream,\n\t\t\t\t\tIN_DATALENGTH_Z const int offset, \n\t\t\t\t\tconst BOOLEAN useQuantisedPadding );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapSendPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream );\n\n/* Prototypes for session mapping functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2processing( INOUT SESSION_INFO *sessionInfoPtr );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2clientProcessing( INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2serverProcessing( INOUT SSH_HANDSHAKE_INFO *handshakeInfo );\n#endif /* USE_SESSIONS */\n#endif /* _SSH_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/ssh2.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib SSHv2 Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* Tables mapping SSHv2 algorithm names to cryptlib algorithm IDs, in \n   preferred algorithm order.  The algorithm may not be a real cryptlib \n   algorithm type but an SSH-specific pseudo-algorithm in the \n   CRYPT_PSEUDOALGO_xxx range, for example CRYPT_PSEUDOALGO_PASSWORD.  \n   To deal with this we have to map the pseudo-algorithm value to a \n   CRYPT_ALGO_TYPE via the MK_ALGO() macro.\n\n   ECC support by SSH implementations is rather hit-and-miss.  If we were to \n   advertise ECC only (which we never do), some servers will respond with \n   RSA/DSA keys (even though they're not specified as being supported), and \n   others will respond with an empty host key.\n   \n   In addition the algorithms aren't just algorithm values but a combination \n   of the algorithm, the key size, and the hash algorithm, with \n   CRYPT_ALGO_ECDH/CRYPT_ALGO_ECDSA being the default P256 curve with \n   SHA-256.  Because the curve types are tied to the oddball SHA-2 hash \n   variants (we can't just use SHA-256 for every curve), we don't support \n   P384 and P512 because we'd have to support an entirely new (and 64-bit-\n   only) hash algorithm for each of the curves.\n\n   SSH has multiple ways to specify the same keyex algorithm, either\n   negotiated via \"diffie-hellman-group-exchange-sha256\" and \n   \"diffie-hellman-group-exchange-sha1\" or explicitly as\n   \"diffie-hellman-group14-sha256\" and \"diffie-hellman-group14-sha1\".  \n   We distinguish between DH + SHA1/SHA256 and DH + SHA1/SHA256 via the\n   addition of an algorithm parameter, which contains the DH key size for \n   the selected fixed group.  \n   \n   We don't support the 1024-bit DH group even though it's mandatory because\n   it's too obvious a target for an offline attack.  Unfortunately this \n   presents a problem with assorted Cisco security appliances which are\n   \"secure\" by executive fiat rather than by design, supporting only \n   \"diffie-hellman-group1-sha1\", and not even the mandatory-to-support \n   \"diffie-hellman-group14-sha1\" let alone the group-exchange suites */\n\nstatic const ALGO_STRING_INFO algoStringKeyexTbl[] = {\n#if defined( USE_ECDH ) && defined( PREFER_ECC )\n\t{ \"ecdh-sha2-nistp256\", 18, CRYPT_ALGO_ECDH, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDH && PREFER_ECC */\n\t{ \"diffie-hellman-group-exchange-sha256\", 36, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2 },\n\t{ \"diffie-hellman-group-exchange-sha1\", 34, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1 },\n\t{ \"diffie-hellman-group14-sha256\", 29, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2, bitsToBytes( 2048 ) },\n\t{ \"diffie-hellman-group14-sha1\", 27, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1, bitsToBytes( 2048 ) },\n#if defined( USE_ECDH ) && !defined( PREFER_ECC ) \n\t{ \"ecdh-sha2-nistp256\", 18, CRYPT_ALGO_ECDH, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDH && !PREFER_ECC */\n\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }, \n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }\n\t};\nstatic const ALGO_STRING_INFO algoStringKeyexNoECCTbl[] = {\n\t{ \"diffie-hellman-group-exchange-sha256\", 36, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2 },\n\t{ \"diffie-hellman-group-exchange-sha1\", 34, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1 },\n\t{ \"diffie-hellman-group14-sha256\", 29, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2, bitsToBytes( 2048 ) },\n\t{ \"diffie-hellman-group14-sha1\", 27, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1, bitsToBytes( 2048 ) },\n\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }, \n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }\n\t};\n\nstatic const ALGO_STRING_INFO algoStringPubkeyTbl[] = {\n#if defined( USE_ECDSA ) && defined( PREFER_ECC )\n\t{ \"ecdsa-sha2-nistp256\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDSA && PREFER_ECC */\n\t{ \"rsa-sha2-256\", 12, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2 },\n\t{ \"ssh-rsa\", 7, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1 },\n#ifdef USE_DSA\n\t{ \"ssh-dss\", 7, CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1 },\n#endif /* USE_DSA */\n#if defined( USE_ECDSA ) && !defined( PREFER_ECC )\n\t{ \"ecdsa-sha2-nistp256\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDSA && !PREFER_ECC */\n\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }, \n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, 0 }\n\t};\n\nstatic const ALGO_STRING_INFO algoStringEncrTbl[] = {\n\t{ \"aes128-cbc\", 10, CRYPT_ALGO_AES, CRYPT_MODE_CBC, bitsToBytes( 128 ) },\n\t{ \"aes256-cbc\", 10, CRYPT_ALGO_AES, CRYPT_MODE_CBC, bitsToBytes( 256 ) },\n#ifdef USE_SSH_CTR\n\t{ \"aes128-ctr\", 10, CRYPT_ALGO_AES, CRYPT_MODE_ECB, bitsToBytes( 128 ) },\n\t{ \"aes256-ctr\", 10, CRYPT_ALGO_AES, CRYPT_MODE_ECB, bitsToBytes( 256 ) },\n#endif /* USE_SSH_CTR */\n#ifdef USE_3DES\n\t{ \"3des-cbc\", 8, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, bitsToBytes( 192 ) },\n#endif /* USE_3DES */\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, 0, CRYPT_ALGO_NONE }\n\t};\n\nstatic const ALGO_STRING_INFO algoStringMACTbl[] = {\n\t{ \"hmac-sha2-256\", 13, CRYPT_ALGO_HMAC_SHA2 },\n\t{ \"hmac-sha1\", 9, CRYPT_ALGO_HMAC_SHA1 },\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, 0, CRYPT_ALGO_NONE }\n\t};\n\nstatic const ALGO_STRING_INFO algoStringCoprTbl[] = {\n\t{ \"none\", 4, CRYPT_ALGO_AES /* Always-valid placeholder */ },\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, 0, CRYPT_ALGO_NONE }\n\t};\n\n/* A grand unified version of the above, used to write algorithm names */\n\nstatic const ALGO_STRING_INFO algoStringMapTbl[] = {\n\t/* Keyex algorithms */\n\t{ \"diffie-hellman-group-exchange-sha256\", 36, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2 },\n\t{ \"diffie-hellman-group-exchange-sha1\", 34, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1 },\n\t{ \"diffie-hellman-group14-sha256\", 29, CRYPT_ALGO_DH, CRYPT_ALGO_SHA2, bitsToBytes( 2048 ) },\n\t{ \"diffie-hellman-group14-sha1\", 27, CRYPT_ALGO_DH, CRYPT_ALGO_SHA1, bitsToBytes( 2048 ) },\n#ifdef USE_ECDH\n\t{ \"ecdh-sha2-nistp256\", 18, CRYPT_ALGO_ECDH, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDH */\n\n\t/* Signature algorithms */\n\t{ \"rsa-sha2-256\", 12, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2 },\n\t{ \"ssh-rsa\", 7, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1 },\n#ifdef USE_DSA\n\t{ \"ssh-dss\", 7, CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1 },\n#endif /* USE_DSA */\n#ifdef USE_ECDSA\n\t{ \"ecdsa-sha2-nistp256\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, bitsToBytes( 256 ) },\n#endif /* USE_ECDSA */\n\n\t/* Encryption algorithms */\n\t{ \"aes128-cbc\", 10, CRYPT_ALGO_AES, CRYPT_MODE_CBC, bitsToBytes( 128 ) },\n\t{ \"aes256-cbc\", 10, CRYPT_ALGO_AES, CRYPT_MODE_CBC, bitsToBytes( 256 ) },\n#ifdef USE_SSH_CTR\n\t{ \"aes128-ctr\", 10, CRYPT_ALGO_AES, CRYPT_MODE_ECB, bitsToBytes( 128 ) },\n\t{ \"aes256-ctr\", 10, CRYPT_ALGO_AES, CRYPT_MODE_ECB, bitsToBytes( 256 ) },\n#endif /* USE_SSH_CTR */\n#ifdef USE_3DES\n\t{ \"3des-cbc\", 8, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, bitsToBytes( 192 ) },\n#endif /* USE_3DES */\n\n\t/* MAC algorithms */\n\t{ \"hmac-sha2-256\", 13, CRYPT_ALGO_HMAC_SHA2 },\n\t{ \"hmac-sha1\", 9, CRYPT_ALGO_HMAC_SHA1 },\n\n\t/* Miscellaneous */\n\t{ \"password\", 8, MK_ALGO( PSEUDOALGO_PASSWORD ) },\n\t{ \"none\", 4, CRYPT_ALGO_LAST },\t/* Catch-all */\n\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, 0, CRYPT_ALGO_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise crypto-related handshake information */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initHandshakeCrypt( INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\t/* Set the initial hash algorithm used to authenticate the handshake */\n\thandshakeInfo->exchangeHashAlgo = CRYPT_ALGO_SHA1;\n\n\t/* Most of the SSH <-> cryptlib mapping tables are fixed, however the \n\t   pubkey table table is pointed to by the handshakeInfo and may\n\t   later be changed dynamically on the server depending on the server's \n\t   key type */\n\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyTbl;\n\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyTbl, ALGO_STRING_INFO );\n\t}\n\n/* Hash the SSH ID strings that are exchanged as pre-handshake out-of-band \n   data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint hashHandshakeStrings( INOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  IN_BUFFER( clientStringLength ) \\\n\t\t\t\t\t\t\t\tconst void *clientString,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int clientStringLength,\n\t\t\t\t\t\t  IN_BUFFER( serverStringLength ) \\\n\t\t\t\t\t\t\t\tconst void *serverString,\n\t\t\t\t\t\t  IN_LENGTH_SHORT const int serverStringLength )\n\t{\n\tint status;\n\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( clientString, clientStringLength ) );\n\tassert( isReadPtrDynamic( serverString, serverStringLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( clientStringLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( serverStringLength ) );\n\n\t/* SSH hashes the handshake ID strings for integrity-protection purposes, \n\t   first the client string and then the server string, encoded as SSH \n\t   string values.  In addition since the handshake can retroactively \n\t   switch to a different hash algorithm mid-exchange we have to \n\t   speculatively hash the messages with alternative algorithms in case \n\t   the other side decides to switch */\n\tstatus = hashAsString( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t   clientString, clientStringLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = hashAsString( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t   serverString, serverStringLength );\n\t\t}\n\tif( handshakeInfo->iExchangeHashAltContext == CRYPT_ERROR )\n\t\treturn( status );\n\tstatus = hashAsString( handshakeInfo->iExchangeHashAltContext, \n\t\t\t\t\t\t   clientString, clientStringLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = hashAsString( handshakeInfo->iExchangeHashAltContext,\n\t\t\t\t\t\t\t   serverString, serverStringLength );\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead/Write Algorithm Info\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert an SSH algorithm list to a cryptlib ID in preferred-algorithm \n   order.  For some bizarre reason the algorithm information is communicated \n   as a comma-delimited list (in an otherwise binary protocol) so we have to \n   unpack and pack them into this cumbersome format alongside just choosing \n   which algorithm to use.  In addition the algorithm selection mechanism \n   differs depending on whether we're the client or the server, and what set \n   of algorithms we're matching.  Unlike SSL, which uses the offered-suites/\n   chosen-suites mechanism, in SSH both sides offer a selection of cipher \n   suites and then the server chooses the first one that appears on both it \n   and the client's list, with special-case handling for the keyex and \n   signature algorithms if the match isn't the first one on the list.  This \n   means that the client can choose as it pleases from the server's list if \n   it waits for the server hello (see the comment in the client/server hello \n   handling code on the annoying nature of this portion of the SSH handshake) \n   but the server has to perform a complex double-match of its own vs.the \n   client's list.  The cases that we need to handle are:\n\n\tBEST_MATCH: Get the best matching algorithm (that is, the one \n\t\tcorresponding to the strongest crypto mechanism), used by the client \n\t\tto match the server.\n\n\tFIRST_MATCH: Get the first matching algorithm, used by the server to \n\t\tmatch the client.\n\n\tFIRST_MATCH_WARN: Get the first matching algorithm and warn if it isn't \n\t\tthe first one on the list of possible algorithms, used by the server \n\t\tto match the client for the keyex and public-key algorithms.\n\n   This is a sufficiently complex and screwball function that we need to\n   define a composite structure to pass all of the control information in\n   and out */\n\ntypedef enum {\n\tGETALGO_NONE,\t\t\t/* No match action */\n\tGETALGO_FIRST_MATCH,\t/* Get first matching algorithm */\n\tGETALGO_FIRST_MATCH_WARN,/* Get first matching algo, warn if not first */\n\tGETALGO_BEST_MATCH,\t\t/* Get best matching algorithm */\n\tGETALGO_LAST\t\t\t/* Last possible match action */\n\t} GETALGO_TYPE;\n\ntypedef struct {\n\t/* Match information passed in by the caller */\n\tARRAY_FIXED( noAlgoInfoEntries ) \\\n\tconst ALGO_STRING_INFO *algoInfo;/* Algorithm selection information */\n\tint noAlgoInfoEntries;\n\tCRYPT_ALGO_TYPE preferredAlgo;\t/* Preferred algo for first-match */\n\tGETALGO_TYPE getAlgoType;\t\t/* Type of match to perform */\n\tBOOLEAN allowECC;\t\t\t\t/* Whether to allow ECC algos */\n\tBOOLEAN allowExtIndicator;\t\t/* Whether to allow extension indicator */\n\n\t/* Information returned by the read-algorithm function */\n\tCRYPT_ALGO_TYPE algo;\t\t\t/* Matched algorithm */\n\tCRYPT_ALGO_TYPE subAlgo;\t\t/* Sub-algorithm (e.g. hash for keyex) */\n\tint parameter;\t\t\t\t\t/* Optional algorithm parameter */\n\tBOOLEAN prefAlgoMismatch;\t\t/* First match != preferredAlgo */\n\tBOOLEAN extensionIndicator;\t\t/* Whether extension indicator was found */\n\t} ALGOID_INFO;\n\n#if defined( USE_ECDH ) || defined( USE_ECDSA )\n  #define ALLOW_ECC\t\tTRUE\n#else\n  #define ALLOW_ECC\t\tFALSE\n#endif /* USE_ECDH || USE_ECDSA */\n\n#define MAX_NO_SUBSTRINGS\t\t32\t/* Max.no of algorithm substrings */\n#define MAX_SUBSTRING_SIZE\t\t128\t/* Max.size of each substring */\n\n#define setAlgoIDInfo( algoIDInfo, algoStrInfo, algoStrInfoEntries, getType ) \\\n\t{ \\\n\tmemset( ( algoIDInfo ), 0, sizeof( ALGOID_INFO ) ); \\\n\t( algoIDInfo )->algoInfo = ( algoStrInfo ); \\\n\t( algoIDInfo )->noAlgoInfoEntries = ( algoStrInfoEntries ); \\\n\t( algoIDInfo )->preferredAlgo = CRYPT_ALGO_NONE; \\\n\t( algoIDInfo )->getAlgoType = ( getType ); \\\n\t( algoIDInfo )->allowECC = ALLOW_ECC; \\\n\t( algoIDInfo )->allowExtIndicator = FALSE; \\\n\t}\n#define setAlgoIDInfoEx( algoIDInfo, algoStrInfo, algoStrInfoEntries, prefAlgo, getType ) \\\n\t{ \\\n\tmemset( ( algoIDInfo ), 0, sizeof( ALGOID_INFO ) ); \\\n\t( algoIDInfo )->algoInfo = ( algoStrInfo ); \\\n\t( algoIDInfo )->noAlgoInfoEntries = ( algoStrInfoEntries ); \\\n\t( algoIDInfo )->preferredAlgo = ( prefAlgo ); \\\n\t( algoIDInfo )->getAlgoType = ( getType ); \\\n\t( algoIDInfo )->allowECC = ALLOW_ECC; \\\n\t( algoIDInfo )->allowExtIndicator = FALSE; \\\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readAlgoStringEx( INOUT STREAM *stream, \n\t\t\t\t\t\t\t INOUT ALGOID_INFO *algoIDInfo,\n\t\t\t\t\t\t\t INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst ALGO_STRING_INFO *algoInfoPtr;\n\tBOOLEAN foundMatch = FALSE;\n\tvoid *string DUMMY_INIT_PTR;\n\tint stringPos, stringLen, substringLen, algoIndex = 999;\n\tint noStrings, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( algoIDInfo, sizeof( ALGOID_INFO ) ) );\n\tassert( isReadPtrDynamic( algoIDInfo->algoInfo, \\\n\t\t\t\t\t\t\t  sizeof( ALGO_STRING_INFO ) * \\\n\t\t\t\t\t\t\t\t\talgoIDInfo->noAlgoInfoEntries ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( ( algoIDInfo->getAlgoType == GETALGO_BEST_MATCH && \\\n\t\t\t\talgoIDInfo->preferredAlgo == CRYPT_ALGO_NONE ) || \\\n\t\t\t  ( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH ) ||\n\t\t\t  ( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN && \\\n\t\t\t\t( algoIDInfo->preferredAlgo > CRYPT_ALGO_NONE && \\\n\t\t\t\t  algoIDInfo->preferredAlgo < CRYPT_ALGO_LAST_EXTERNAL ) ) );\n\t\t\t  /* FIRST_MATCH uses CRYPT_ALGO_NONE on the first match of an\n\t\t\t\t algorithm pair and the first algorithm chosen on the second\n\t\t\t\t match */\n\tREQUIRES( algoIDInfo->noAlgoInfoEntries > 0 && \\\n\t\t\t  algoIDInfo->noAlgoInfoEntries < 20 );\n\tREQUIRES( algoIDInfo->allowECC == TRUE || algoIDInfo->allowECC == FALSE );\n\tREQUIRES( algoIDInfo->allowExtIndicator == TRUE || \\\n\t\t\t  algoIDInfo->allowExtIndicator == FALSE );\n\n\t/* Get the string length and data and make sure that it's valid */\n\tstatus = stringLen = readUint32( stream );\n\tif( !cryptStatusError( status ) && \\\n\t\t( stringLen < SSH2_MIN_ALGOID_SIZE || \\\n\t\t  stringLen >= MAX_INTLENGTH_SHORT ) )\n\t\t{\n\t\t/* Quick-reject check for an obviously-invalid string */\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\tstatus = sMemGetDataBlock( stream, &string, stringLen );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, stringLen, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid algorithm ID string\" ) );\n\t\t}\n\tENSURES( stringLen >= SSH2_MIN_ALGOID_SIZE && \\\n\t\t\t stringLen < MAX_INTLENGTH_SHORT );\n\tANALYSER_HINT( string != NULL );\n\n\t/* Walk down the string looking for a recognised algorithm.  Since our\n\t   preference may not match the other side's preferences we have to walk\n\t   down the entire list to find our preferred choice:\n\n\t\t  stringPos\t\t\tstringLen\n\t\t\t   |\t\t\t   |\n\t\t\t   v\t\t\t   v\n\t\t\"algo1,algo2,algo3,algoN\"\n\t\t\t   ^   ^\t\t   ^\n\t\t\t   |   |\t\t   |\n\t\t\t   |substrLen\t   |\n\t\t\t   +- subStrMaxLen +\n\n\t   This works by walking an index stringPos down the string, with each \n\t   substring delimited by { stringPos, subStringLen }, which is checked\n\t   against the table of algorithm names */\n\tLOOP_MED( ( stringPos = 0, noStrings = 0 ),\n\t\t\t  stringPos <= stringLen - SSH2_MIN_ALGOID_SIZE && \\\n\t\t\t\t\tnoStrings < MAX_NO_SUBSTRINGS, \n\t\t\t  ( stringPos += substringLen + 1, noStrings++ ) )\n\t\t{\n\t\tconst ALGO_STRING_INFO *matchedAlgoInfo = NULL;\n\t\tconst BYTE *substringPtr = ( BYTE * ) string + stringPos;\n\t\tconst int substringMaxLen = stringLen - stringPos;\n\t\tBOOLEAN algoMatched = TRUE;\n\t\tint currentAlgoIndex, LOOP_ITERATOR_ALT;\n\n\t\t/* Find the length of the next algorithm name */\n\t\tLOOP_LARGE_ALT( substringLen = 0,\n\t\t\t\t\t\tsubstringLen < substringMaxLen && \\\n\t\t\t\t\t\t\tsubstringPtr[ substringLen ] != ',' && \\\n\t\t\t\t\t\t\tsubstringLen < MAX_SUBSTRING_SIZE, \\\n\t\t\t\t\t\tsubstringLen++ );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tif( substringLen >= MAX_SUBSTRING_SIZE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t\t( CRYPT_ERROR_OVERFLOW, errorInfo, \n\t\t\t\t\t  \"Excessively long (more than %d characters) SSH \"\n\t\t\t\t\t  \"algorithm string encountered\", substringLen ) );\n\t\t\t}\n\t\tif( substringLen < SSH2_MIN_ALGOID_SIZE || \\\n\t\t\tsubstringLen > CRYPT_MAX_TEXTSIZE )\n\t\t\t{\n\t\t\t/* Empty or too-short algorithm name (or excessively long one), \n\t\t\t   continue.  Note that even with an (invalid) zero-length \n\t\t\t   substring we'll still progress down the string since the loop\n\t\t\t   increment is the substring length plus one */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check for the presence of the special-case extension-info \n\t\t   indicator if required.  At the moment we only respond to a \n\t\t   client-side extension indicator so we don't need to distinguish \n\t\t   between which type we look for */\n\t\tif( algoIDInfo->allowExtIndicator )\n\t\t\t{\n\t\t\tif( substringLen == 10 && \\\n\t\t\t\t!memcmp( substringPtr, \"ext-info-c\", 10 ) )\n\t\t\t\t{\n\t\t\t\talgoIDInfo->extensionIndicator = TRUE;\n\n\t\t\t\t/* If we've already found matching algorithm information, \n\t\t\t\t   we're done */\n\t\t\t\tif( foundMatch )\n\t\t\t\t\tbreak;\n\n\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t/* If we've already found a match then all that we're looking \n\t\t\t   for is the extension info indicator */\n\t\t\tif( foundMatch )\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check whether it's something that we can handle */\n\t\tLOOP_MED( currentAlgoIndex = 0, \n\t\t\t\t  currentAlgoIndex < algoIDInfo->noAlgoInfoEntries && \\\n\t\t\t\t\talgoIDInfo->algoInfo[ currentAlgoIndex ].name != NULL,\n\t\t\t\t  currentAlgoIndex++ )\n\t\t\t{\n\t\t\tconst ALGO_STRING_INFO *algoIDInfoPtr = \\\n\t\t\t\t\t\t\t&algoIDInfo->algoInfo[ currentAlgoIndex ];\n\n\t\t\tif( algoIDInfoPtr->nameLen == substringLen && \\\n\t\t\t\t!memcmp( algoIDInfoPtr->name, substringPtr, substringLen ) )\n\t\t\t\t{\n\t\t\t\tmatchedAlgoInfo = algoIDInfoPtr;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( currentAlgoIndex < algoIDInfo->noAlgoInfoEntries );\n\t\tif( matchedAlgoInfo == NULL )\n\t\t\t{\n\t\t\t/* Unrecognised algorithm name, remember to warn the caller if \n\t\t\t   we have to match the first algorithm on the list, then move \n\t\t\t   on to the next name */\n\t\t\tif( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN )\n\t\t\t\talgoIDInfo->prefAlgoMismatch = TRUE;\n\t\t\tcontinue;\n\t\t\t}\n\t\tDEBUG_PRINT(( \"Offered suite: %s.\\n\", matchedAlgoInfo->name ));\n\n\t\t/* Make sure that the required algorithms and optional sub-\n\t\t   algorithms are available.  We don't check the sub-algorithm type \n\t\t   for the conventional algorithms because in this case it's an \n\t\t   encryption mode, not an algorithm */\n\t\tif( !isPseudoAlgo( matchedAlgoInfo->algo ) && \\\n\t\t\t!algoAvailable( matchedAlgoInfo->algo ) )\n\t\t\talgoMatched = FALSE;\n\t\tif( !isConvAlgo( matchedAlgoInfo->algo ) && \\\n\t\t\tmatchedAlgoInfo->subAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t!algoAvailable( matchedAlgoInfo->subAlgo ) )\n\t\t\talgoMatched = FALSE;\n\n\t\t/* If this is an ECC algorithm and the use of ECC algorithms has \n\t\t   been prevented by external conditions such as the server key\n\t\t   not being an ECC key, we can't use it even if ECC algorithms in\n\t\t   general are available */\n\t\tif( algoMatched && !algoIDInfo->allowECC && \\\n\t\t\tisEccAlgo( matchedAlgoInfo->algo ) )\n\t\t\talgoMatched = FALSE;\n\n\t\t/* If the matched algorithm isn't available, remember to warn the \n\t\t   caller if we have to match the first algorithm on the list, then \n\t\t   move on to the next name */\n\t\tif( !algoMatched )\n\t\t\t{\n\t\t\tif( algoIDInfo->getAlgoType == GETALGO_FIRST_MATCH_WARN )\n\t\t\t\talgoIDInfo->prefAlgoMismatch = TRUE;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\tswitch( algoIDInfo->getAlgoType )\n\t\t\t{\n\t\t\tcase GETALGO_BEST_MATCH:\n\t\t\t\t/* If we're looking for the best (highest-ranked algorithm)\n\t\t\t\t   match, see whether the current match ranks higher than\n\t\t\t\t   the existing one */\n\t\t\t\tif( currentAlgoIndex < algoIndex )\n\t\t\t\t\t{\n\t\t\t\t\talgoIndex = currentAlgoIndex;\n\t\t\t\t\tif( algoIndex <= 0 )\n\t\t\t\t\t\tfoundMatch = TRUE;\t/* Gruener werd's net */\n\t\t\t\t\tDEBUG_PRINT(( \"Accepted suite: %s.\\n\", \n\t\t\t\t\t\t\t\t  matchedAlgoInfo->name ));\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase GETALGO_FIRST_MATCH:\n\t\t\t\t/* If we've found an acceptable algorithm, remember it and\n\t\t\t\t   exit */\n\t\t\t\tif( algoIDInfo->preferredAlgo == CRYPT_ALGO_NONE || \\\n\t\t\t\t\talgoIDInfo->preferredAlgo == matchedAlgoInfo->algo )\n\t\t\t\t\t{\n\t\t\t\t\talgoIndex = currentAlgoIndex;\n\t\t\t\t\tfoundMatch = TRUE;\n\t\t\t\t\tDEBUG_PRINT(( \"Accepted suite: %s.\\n\", \n\t\t\t\t\t\t\t\t  matchedAlgoInfo->name ));\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase GETALGO_FIRST_MATCH_WARN:\n\t\t\t\t/* If we found the algorithm that we're after, remember it\n\t\t\t\t   and exit */\n\t\t\t\tif( algoIDInfo->preferredAlgo != matchedAlgoInfo->algo )\n\t\t\t\t\t{\n\t\t\t\t\t/* We didn't match the first algorithm on the list, warn\n\t\t\t\t\t   the caller */\n\t\t\t\t\talgoIDInfo->prefAlgoMismatch = TRUE;\n\t\t\t\t\tDEBUG_PRINT(( \"Accepted suite: %s.\\n\", \n\t\t\t\t\t\t\t\t  matchedAlgoInfo->name ));\n\t\t\t\t\t}\n\t\t\t\talgoIndex = currentAlgoIndex;\n\t\t\t\tfoundMatch = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\n\t\t/* If we've found a match, we're done unless we're looking for an \n\t\t   extension-info indicator, in which case we have to parse the \n\t\t   entire string */\n\t\tif( foundMatch && !algoIDInfo->allowExtIndicator )\n\t\t\tbreak;\t\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noStrings >= MAX_NO_SUBSTRINGS )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, errorInfo, \n\t\t\t\t  \"Excessive number (more than %d) of SSH algorithm \"\n\t\t\t\t  \"strings encountered\", noStrings ) );\n\t\t}\n\tif( algoIndex > 50 )\t/* Initialisated to 999 at start */\n\t\t{\n\t\tchar algoString[ 256 + 8 ];\n\t\tconst int algoStringLen = min( stringLen, \\\n\t\t\t\t\t\t\t\t\t   min( MAX_ERRMSG_SIZE - 80, 255 ) );\n\n\t\tREQUIRES( algoStringLen > 0 && \\\n\t\t\t\t  algoStringLen <= min( MAX_ERRMSG_SIZE - 80, 255 ) );\n\n\t\t/* We couldn't find anything to use, tell the caller what was\n\t\t   available */\n\t\tREQUIRES( rangeCheck( algoStringLen, 1, 256 ) );\n\t\tmemcpy( algoString, string, algoStringLen );\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, errorInfo, \n\t\t\t\t  \"No algorithm compatible with the remote system's \"\n\t\t\t\t  \"selection was found: '%s'\", \n\t\t\t\t  sanitiseString( algoString, 256, stringLen ) ) );\n\t\t}\n\n\t/* We found a more-preferred algorithm than the default, go with that */\n\talgoInfoPtr = &algoIDInfo->algoInfo[ algoIndex ];\n\talgoIDInfo->algo = algoInfoPtr->algo;\n\talgoIDInfo->subAlgo = algoInfoPtr->subAlgo;\n\talgoIDInfo->parameter = algoInfoPtr->parameter;\n\tDEBUG_PRINT(( \"Final accepted suite: %s.\\n\", algoInfoPtr->name ));\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 6 ) ) \\\nint readAlgoString( INOUT STREAM *stream, \n\t\t\t\t\tIN_ARRAY( noAlgoStringEntries ) \\\n\t\t\t\t\t\tconst ALGO_STRING_INFO *algoInfo,\n\t\t\t\t\tIN_RANGE( 1, 100 ) const int noAlgoStringEntries, \n\t\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *algo, \n\t\t\t\t\tconst BOOLEAN useFirstMatch, \n\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tALGOID_INFO algoIDInfo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( algoInfo, sizeof( ALGO_STRING_INFO ) * \\\n\t\t\t\t\t\t\t\t noAlgoStringEntries ) );\n\tassert( isWritePtr( algo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\n\tREQUIRES( noAlgoStringEntries > 0 && noAlgoStringEntries <= 100 );\n\tREQUIRES( useFirstMatch == TRUE || useFirstMatch == FALSE );\n\n\t/* Clear return value */\n\t*algo = CRYPT_ALGO_NONE;\n\n\tsetAlgoIDInfo( &algoIDInfo, algoInfo, noAlgoStringEntries, \n\t\t\t\t   useFirstMatch ? GETALGO_FIRST_MATCH : GETALGO_BEST_MATCH );\n\tstatus = readAlgoStringEx( stream, &algoIDInfo, errorInfo );\n\tif( cryptStatusOK( status ) )\n\t\t*algo = algoIDInfo.algo;\n\treturn( status );\n\t}\n\n/* Algorithms used to protect data packets are used in pairs, one for\n   incoming and the other for outgoing data.  To keep things simple we\n   always force these to be the same, first reading the algorithm for one\n   direction and then making sure that the one for the other direction\n   matches this.  All implementations seem to do this anyway, many aren't\n   even capable of supporting asymmetric algorithm choices */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5, 6, 9 ) ) \\\nstatic int readAlgoStringPair( INOUT STREAM *stream, \n\t\t\t\t\t\t\t   IN_ARRAY( noAlgoStringEntries ) \\\n\t\t\t\t\t\t\t\t\tconst ALGO_STRING_INFO *algoInfo,\n\t\t\t\t\t\t\t   IN_RANGE( 1, 100 ) const int noAlgoStringEntries,\n\t\t\t\t\t\t\t   OUT_ALGO_Z CRYPT_ALGO_TYPE *algo, \n\t\t\t\t\t\t\t   OUT_ENUM_OPT( CRYPT_MODE ) CRYPT_MODE_TYPE *mode,\n\t\t\t\t\t\t\t   OUT_INT_SHORT_Z int *parameter,\n\t\t\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t\t\t   const BOOLEAN allowAsymmetricAlgos,\n\t\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ALGO_TYPE pairPreferredAlgo;\n\tALGOID_INFO algoIDInfo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( algoInfo, sizeof( ALGO_STRING_INFO ) * \\\n\t\t\t\t\t\t\t\t noAlgoStringEntries ) );\n\tassert( isWritePtr( algo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\n\tREQUIRES( noAlgoStringEntries > 0 && noAlgoStringEntries <= 100 );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\tREQUIRES( allowAsymmetricAlgos == TRUE || \\\n\t\t\t  allowAsymmetricAlgos == FALSE );\n\n\t/* Clear return values */\n\t*algo = CRYPT_ALGO_NONE;\n\t*mode = CRYPT_MODE_NONE;\n\t*parameter = 0;\n\n\t/* Get the first algorithm */\n\tsetAlgoIDInfo( &algoIDInfo, algoInfo, noAlgoStringEntries, \n\t\t\t\t   isServer ? GETALGO_FIRST_MATCH : GETALGO_BEST_MATCH );\n\tstatus = readAlgoStringEx( stream, &algoIDInfo, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tpairPreferredAlgo = algoIDInfo.algo;\n\n\t/* Get the matched second algorithm.  Some buggy implementations request\n\t   mismatched algorithms (at the moment this is only for compression \n\t   algorithms) but have no problems in accepting the same algorithm in \n\t   both directions, so if we're talking to one of these then we ignore \n\t   an algorithm mismatch */\n\tsetAlgoIDInfoEx( &algoIDInfo, algoInfo, noAlgoStringEntries,\n\t\t\t\t\t pairPreferredAlgo, GETALGO_FIRST_MATCH );\n\tstatus = readAlgoStringEx( stream, &algoIDInfo, errorInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( pairPreferredAlgo != algoIDInfo.algo && !allowAsymmetricAlgos )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Client algorithm %d doesn't match server algorithm %d \"\n\t\t\t\t  \"in algorithm pair\", pairPreferredAlgo, \n\t\t\t\t  algoIDInfo.algo ) );\n\t\t}\n\t*algo = algoIDInfo.algo;\n\t*mode = ( CRYPT_MODE_TYPE ) algoIDInfo.subAlgo;\n\t*parameter = algoIDInfo.parameter;\n\n\treturn( status );\n\t}\n\n/* Write a cryptlib algorithm ID as an SSH algorithm name */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoStringEx( INOUT STREAM *stream, \n\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE algo,\n\t\t\t\t\t   IN_INT_SHORT_Z const int subAlgo,\n\t\t\t\t\t   IN_INT_SHORT_Z const int parameter,\n\t\t\t\t\t   IN_ENUM_OPT( SSH_ALGOSTRINGINFO ) \\\n\t\t\t\t\t\t\tconst SSH_ALGOSTRINGINFO_TYPE algoStringInfo )\n\t{\n\tint algoIndex, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( algo > CRYPT_ALGO_NONE && algo < CRYPT_ALGO_LAST_EXTERNAL );\n\tREQUIRES( ( subAlgo >= CRYPT_ALGO_NONE && \\\n\t\t\t\tsubAlgo < CRYPT_ALGO_LAST_EXTERNAL ) || \\\n\t\t\t  ( subAlgo > CRYPT_MODE_NONE && subAlgo < CRYPT_MODE_LAST ) );\n\tREQUIRES( parameter >= 0 && parameter < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isEnumRangeOpt( algoStringInfo, SSH_ALGOSTRINGINFO ) );\n\n\t/* Locate the name for this algorithm and optional sub-algoritihm and \n\t   encode it as an SSH string */\n\tLOOP_MED( algoIndex = 0, \n\t\t\t  algoStringMapTbl[ algoIndex ].algo != CRYPT_ALGO_NONE && \\\n\t\t\t\talgoStringMapTbl[ algoIndex ].algo != algo && \\\n\t\t\t\talgoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\tALGO_STRING_INFO ), \n\t\t\t  algoIndex++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( algoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ) );\n\tENSURES( algoStringMapTbl[ algoIndex ].algo == algo );\n\n\t/* If there are two algorithm groups (which occurs for the \n\t   schizophrenically-specified keyex algorithms) then we may need to \n\t   write the name from the second group rather than the first.  The\n\t   handling of this is somewhat ugly since it hardcodes knowledge of the\n\t   algorithm table, but there's no generalised way to do this without\n\t   adding a pile of extra complexity */\n\tif( algoStringInfo == SSH_ALGOSTRINGINFO_EXTINFO_ALTDHALGOS )\n\t\t{\n\t\tREQUIRES( algoStringMapTbl[ algoIndex ].algo == \\\n\t\t\t\t\t\talgoStringMapTbl[ algoIndex + 2 ].algo );\n\t\tREQUIRES( algoStringMapTbl[ algoIndex ].subAlgo == \\\n\t\t\t\t\t\talgoStringMapTbl[ algoIndex + 2 ].subAlgo );\n\t\talgoIndex += 2;\n\t\t}\n\n\t/* If there's a sub-algorithm or parameter, find the entry for that */\n\tif( subAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tLOOP_MED_CHECKINC( algoStringMapTbl[ algoIndex ].algo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t\t\talgoStringMapTbl[ algoIndex ].algo == algo && \\\n\t\t\t\t\t\t\talgoStringMapTbl[ algoIndex ].subAlgo != subAlgo && \\\n\t\t\t\t\t\t\talgoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tALGO_STRING_INFO ), \n\t\t\t\t\t\t   algoIndex++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( algoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ) );\n\t\tENSURES( algoStringMapTbl[ algoIndex ].algo == algo && \\\n\t\t\t\t algoStringMapTbl[ algoIndex ].subAlgo == subAlgo );\n\t\t}\n\tif( parameter != 0 )\n\t\t{\n\t\tLOOP_MED_CHECKINC( algoStringMapTbl[ algoIndex ].algo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t\t\talgoStringMapTbl[ algoIndex ].algo == algo && \\\n\t\t\t\t\t\t\talgoStringMapTbl[ algoIndex ].parameter != parameter && \\\n\t\t\t\t\t\t\talgoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tALGO_STRING_INFO ), \n\t\t\t\t\t\t   algoIndex++ );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( algoIndex < FAILSAFE_ARRAYSIZE( algoStringMapTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ) );\n\t\tENSURES( algoStringMapTbl[ algoIndex ].algo == algo && \\\n\t\t\t\t algoStringMapTbl[ algoIndex ].parameter == parameter );\n\t\t}\n\n\t/* If we're writing an extension negotiation indicator then we need to \n\t   append it to the algorithm ID.  This is always a client-side indicator\n\t   since the server writes its indicator as part of the algorithm list */\n\tif( algoStringInfo == SSH_ALGOSTRINGINFO_EXTINFO || \\\n\t\talgoStringInfo == SSH_ALGOSTRINGINFO_EXTINFO_ALTDHALGOS )\n\t\t{\n\t\twriteUint32( stream, algoStringMapTbl[ algoIndex ].nameLen + 11 );\n\t\tswrite( stream, algoStringMapTbl[ algoIndex ].name, \n\t\t\t\talgoStringMapTbl[ algoIndex ].nameLen );\n\t\treturn( swrite( stream, \",ext-info-c\", 11 ) );\n\t\t}\n\n\treturn( writeString32( stream, algoStringMapTbl[ algoIndex ].name, \n\t\t\t\t\t\t   algoStringMapTbl[ algoIndex ].nameLen ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoString( INOUT STREAM *stream, \n\t\t\t\t\t IN_ALGO const CRYPT_ALGO_TYPE algo )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( algo > CRYPT_ALGO_NONE && algo < CRYPT_ALGO_LAST_EXTERNAL );\n\n\treturn( writeAlgoStringEx( stream, algo, CRYPT_ALGO_NONE, 0,\n\t\t\t\t\t\t\t   SSH_ALGOSTRINGINFO_NONE ) );\n\t}\n\n/* Write a list of algorithms */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeAlgoList( INOUT STREAM *stream, \n\t\t\t\t   IN_ARRAY( noAlgoStringInfoEntries ) \\\n\t\t\t\t\t\tconst ALGO_STRING_INFO *algoStringInfoTbl,\n\t\t\t\t   IN_RANGE( 1, 10 ) const int noAlgoStringInfoEntries )\n\t{\n\tint availAlgoIndex[ 16 + 8 ];\n\tint noAlgos = 0, length = 0, algoIndex, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( algoStringInfoTbl, sizeof( ALGO_STRING_INFO ) * \\\n\t\t\t\t\t\t\t\t\t\t  noAlgoStringInfoEntries ) );\n\n\tREQUIRES( noAlgoStringInfoEntries > 0 && noAlgoStringInfoEntries <= 10 );\n\n\t/* Walk down the list of algorithms remembering the encoded name of each\n\t   one that's available for use */\n\tLOOP_SMALL( algoIndex = 0,\n\t\t\t\talgoIndex < noAlgoStringInfoEntries && \\\n\t\t\t\t\talgoStringInfoTbl[ algoIndex ].algo != CRYPT_ALGO_NONE,\n\t\t\t\talgoIndex++ )\n\t\t{\n\t\tconst ALGO_STRING_INFO *algoStringInfo = &algoStringInfoTbl[ algoIndex ];\n\n\t\t/* Make sure that this algorithm is available for use */\n\t\tif( !isPseudoAlgo( algoStringInfo->algo ) && \\\n\t\t\t!algoAvailable( algoStringInfo->algo ) )\n\t\t\tcontinue;\n\n\t\t/* Make sure that any required sub-algorithms are available */\n\t\tif( algoStringInfo->subAlgo != CRYPT_ALGO_NONE && \\\n\t\t\talgoStringInfo->subAlgo != CRYPT_MODE_ECB && \\\n\t\t\t!algoAvailable( algoStringInfo->subAlgo ) )\n\t\t\tcontinue;\n\n\t\t/* Remember the algorithm details */\n\t\tREQUIRES( noAlgos >= 0 && noAlgos < 16 );\n\t\tavailAlgoIndex[ noAlgos++ ] = algoIndex;\n\t\tlength += algoStringInfo->nameLen;\n\t\tif( noAlgos > 1 )\n\t\t\tlength++;\t\t\t/* Room for comma delimiter */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Encode the list of available algorithms into a comma-separated string */\n\tstatus = writeUint32( stream, length );\n\tLOOP_MED( algoIndex = 0, cryptStatusOK( status ) && algoIndex < noAlgos,\n\t\t\t  algoIndex++ )\n\t\t{\n\t\tconst ALGO_STRING_INFO *algoStringInfo = \\\n\t\t\t\t\t\t&algoStringInfoTbl[ availAlgoIndex[ algoIndex ] ];\n\n\t\tif( algoIndex > 0 )\n\t\t\tsputc( stream, ',' );\t/* Add comma delimiter */\n\t\tstatus = swrite( stream, algoStringInfo->name,\n\t\t\t\t\t\t algoStringInfo->nameLen );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint writeAlgoClassList( INOUT STREAM *stream, \n\t\t\t\t\t\tIN_ENUM( SSH_ALGOCLASS ) \\\n\t\t\t\t\t\t\tconst SSH_ALGOCLASS_TYPE algoClass )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isEnumRange( algoClass, SSH_ALGOCLASS ) );\n\n\t/* Write the appropriate algorithm list for this algorithm class */\n\tswitch( algoClass )\n\t\t{\n\t\tcase SSH_ALGOCLASS_KEYEX:\n\t\t\treturn( writeAlgoList( stream, algoStringKeyexTbl, \n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringKeyexTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\n\t\tcase SSH_ALGOCLASS_KEYEX_NOECC:\n\t\t\treturn( writeAlgoList( stream, algoStringKeyexNoECCTbl,\n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringKeyexNoECCTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\n\t\tcase SSH_ALGOCLASS_ENCR:\n\t\t\treturn( writeAlgoList( stream, algoStringEncrTbl, \n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringEncrTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\n\t\tcase SSH_ALGOCLASS_SIGN:\n\t\t\treturn( writeAlgoList( stream, algoStringPubkeyTbl, \n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringPubkeyTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\n\t\tcase SSH_ALGOCLASS_MAC:\n\t\t\treturn( writeAlgoList( stream, algoStringMACTbl,\n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringMACTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\n\t\tcase SSH_ALGOCLASS_COPR:\n\t\t\treturn( writeAlgoList( stream, algoStringCoprTbl,\n\t\t\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringCoprTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ) ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a client/server hello packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint processHelloSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t OUT_LENGTH_SHORT_Z int *keyexLength,\n\t\t\t\t\t const BOOLEAN isServer )\n\t{\n\tCRYPT_ALGO_TYPE dummyAlgo;\n\tCRYPT_MODE_TYPE mode, dummyMode;\n\tSTREAM stream;\n\tALGOID_INFO algoIDInfo;\n\tBOOLEAN preferredAlgoMismatch = FALSE, guessedKeyex = FALSE;\n\tint length, dummyParameter, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( keyexLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Clear return value */\n\t*keyexLength = 0;\n\n\t/* Process the client/server hello:\n\n\t\tbyte\t\ttype = SSH_MSG_KEXINIT\n\t\tbyte[16]\tcookie\n\t\tstring\t\tkeyex algorithms\n\t\tstring\t\tpubkey algorithms\n\t\tstring\t\tclient_crypto algorithms\n\t\tstring\t\tserver_crypto algorithms\n\t\tstring\t\tclient_mac algorithms\n\t\tstring\t\tserver_mac algorithms\n\t\tstring\t\tclient_compression algorithms\n\t\tstring\t\tserver_compression algorithms\n\t\tstring\t\tclient_language\n\t\tstring\t\tserver_language\n\t\tboolean\t\tfirst_keyex_packet_follows\n\t\tuint32\t\treserved\n\n\t   The cookie isn't explicitly processed since it's done implicitly when \n\t   the hello message is hashed */\n\tstatus = length = \\\n\t\t\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_KEXINIT, 128 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*keyexLength = length;\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstatus = sSkip( &stream, SSH2_COOKIE_SIZE, SSH2_COOKIE_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Read the keyex algorithm information.  Since this is the first \n\t   algorithm list read, we also allow the extension indicator at this \n\t   point */\n\tif( isServer )\n\t\t{\n\t\tint pkcAlgo;\n\n\t\tsetAlgoIDInfoEx( &algoIDInfo, algoStringKeyexTbl, \n\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringKeyexTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t CRYPT_ALGO_DH, GETALGO_FIRST_MATCH_WARN );\n\n\t\t/* By default the use of ECC algorithms is enabled if support for\n\t\t   them is present, however if the server key is a non-ECC key then \n\t\t   it can't be used with an ECC keyex so we have to explicitly\n\t\t   disable it (technically it is possible to mix ECDH with RSA but\n\t\t   this is more likely an error than anything deliberate) */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgo,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusError( status ) || !isEccAlgo( pkcAlgo ) )\n\t\t\talgoIDInfo.allowECC = FALSE;\n\t\talgoIDInfo.allowExtIndicator = TRUE;\n\t\t}\n\telse\n\t\t{\n\t\tsetAlgoIDInfo( &algoIDInfo, algoStringKeyexTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( algoStringKeyexTbl, \\\n\t\t\t\t\t\t\t\t\t\t   ALGO_STRING_INFO ),\n\t\t\t\t\t   GETALGO_BEST_MATCH );\n\t\t}\n\tstatus = readAlgoStringEx( &stream, &algoIDInfo, SESSION_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\thandshakeInfo->keyexAlgo = algoIDInfo.algo;\n\tif( algoIDInfo.prefAlgoMismatch )\n\t\t{\n\t\t/* We didn't get a match for our first choice, remember that we have\n\t\t   to discard any guessed keyex that may follow */\n\t\tpreferredAlgoMismatch = TRUE;\n\t\t}\n\tif( algoIDInfo.algo == CRYPT_ALGO_DH )\n\t\t{\n\t\thandshakeInfo->exchangeHashAlgo = algoIDInfo.subAlgo;\n\t\tif( algoIDInfo.parameter > 0 )\n\t\t\t{\n\t\t\thandshakeInfo->requestedServerKeySize = algoIDInfo.parameter;\n\t\t\thandshakeInfo->isFixedDH = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We're using negotiated rather than explicit DH keys, we need \n\t\t\t   to negotiate the keyex key before we can perform the \n\t\t\t   exchange */\n\t\t\thandshakeInfo->requestedServerKeySize = SSH2_DEFAULT_KEYSIZE;\n\t\t\t}\n\t\t}\n\tif( algoIDInfo.algo == CRYPT_ALGO_ECDH )\n\t\t{\n\t\t/* If we're using an ECDH cipher suite then we need to switch to the\n\t\t   appropriate hash algorithm for the keyex hashing */\n\t\thandshakeInfo->isECDH = TRUE;\n\t\thandshakeInfo->exchangeHashAlgo = algoIDInfo.subAlgo;\n\t\t}\n\tif( algoIDInfo.extensionIndicator )\n\t\thandshakeInfo->sendExtInfo = TRUE;\n\n\t/* Read the pubkey (signature) algorithm information */\n\tif( isServer )\n\t\t{\n\t\tsetAlgoIDInfoEx( &algoIDInfo, handshakeInfo->algoStringPubkeyTbl,\n\t\t\t\t\t\t handshakeInfo->algoStringPubkeyTblNoEntries,\n\t\t\t\t\t\t handshakeInfo->pubkeyAlgo, \n\t\t\t\t\t\t GETALGO_FIRST_MATCH_WARN );\n\t\t}\n\telse\n\t\t{\n\t\tsetAlgoIDInfo( &algoIDInfo, handshakeInfo->algoStringPubkeyTbl,\n\t\t\t\t\t   handshakeInfo->algoStringPubkeyTblNoEntries,\n\t\t\t\t\t   GETALGO_BEST_MATCH );\n\t\t}\n\tstatus = readAlgoStringEx( &stream, &algoIDInfo, SESSION_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tif( isServer && handshakeInfo->pubkeyAlgo != algoIDInfo.algo )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Client requested pubkey algorithm %s when we \"\n\t\t\t\t  \"advertised %s\", getAlgoName( algoIDInfo.algo ), \n\t\t\t\t  getAlgoName( handshakeInfo->pubkeyAlgo ) ) );\n\t\t}\n\thandshakeInfo->pubkeyAlgo = algoIDInfo.algo;\n\thandshakeInfo->hashAlgo = algoIDInfo.subAlgo;\n\tif( algoIDInfo.prefAlgoMismatch )\n\t\t{\n\t\t/* We didn't get a match for our first choice, remember that we have\n\t\t   to discard any guessed keyex that may follow */\n\t\tpreferredAlgoMismatch = TRUE;\n\t\t}\n\n\t/* Read the encryption and MAC algorithm information */\n\tstatus = readAlgoStringPair( &stream, algoStringEncrTbl,\n\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringEncrTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t &sessionInfoPtr->cryptAlgo, &mode,\n\t\t\t\t\t\t\t\t &handshakeInfo->cryptKeysize, isServer, \n\t\t\t\t\t\t\t\t FALSE, SESSION_ERRINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoStringPair( &stream, algoStringMACTbl,\n\t\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringMACTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t\t &sessionInfoPtr->integrityAlgo, \n\t\t\t\t\t\t\t\t\t &dummyMode, &dummyParameter, isServer, \n\t\t\t\t\t\t\t\t\t FALSE, SESSION_ERRINFO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\n\t\t/* Some implementations don't support the mandatory-to-implement SSH \n\t\t   encryption/MAC algorithms, in which case we let the caller know \n\t\t   that they're broken */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_NOMTI ) )\n\t\t\t{\n\t\t\tretExtErrAlt( status, \n\t\t\t\t\t\t  ( status, SESSION_ERRINFO,\n\t\t\t\t\t\t\t\", the server doesn't support the mandatory-to-\"\n\t\t\t\t\t\t\t\"implement SSH algorithms\" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n#ifdef USE_SSH_CTR\n\tif( sessionInfoPtr->cryptAlgo == CRYPT_ALGO_AES && \\\n\t\tmode == CRYPT_MODE_ECB )\n\t\t{\n\t\t/* If the indicated mode is ECB, which we use to synthesise CTR \n\t\t   mode, remember that we're using CTR mode encryption */\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR );\n\t\t}\n#endif /* USE_SSH_CTR */\n\n\t/* Read the remaining algorithm information.  The final reserved value \n\t   should always be zero but we don't specifically check for this since \n\t   at some point in the future it may become non-zero */\n\tstatus = readAlgoStringPair( &stream, algoStringCoprTbl, \n\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringCoprTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t &dummyAlgo, &dummyMode, &dummyParameter, \n\t\t\t\t\t\t\t\t isServer, \n\t\t\t\t\t\t\t\t TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t\t\tSSH_PFLAG_ASYMMCOPR ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE, SESSION_ERRINFO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\treadUniversal32( &stream );\n\tstatus = readUniversal32( &stream );\t\t/* Language string pair */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint value;\n\n\t\tstatus = value = sgetc( &stream );\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( value != 0 )\n\t\t\t\tguessedKeyex = TRUE;\n\t\t\tstatus = readUint32( &stream );\t\t/* Reserved value */\n\t\t\t}\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid hello packet language string/trailer data\" ) );\n\t\t}\n\n\t/* If we're using an alternative exchange hash algorithm, switch the \n\t   contexts around to using the alternative one for hashing from now \n\t   on */\n\tif( handshakeInfo->exchangeHashAlgo == CRYPT_ALGO_SHA2 )\n\t\t{\n\t\tconst CRYPT_CONTEXT tempContext = handshakeInfo->iExchangeHashContext;\n\n\t\thandshakeInfo->iExchangeHashContext = \\\n\t\t\t\thandshakeInfo->iExchangeHashAltContext;\n\t\thandshakeInfo->iExchangeHashAltContext = tempContext;\n\t\t}\n\n\t/* If there's a guessed keyex following this packet and we didn't match\n\t   the first-choice keyex/pubkey algorithm, tell the caller to skip it */\n\tif( guessedKeyex && preferredAlgoMismatch )\n\t\treturn( OK_SPECIAL );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read/write extension information packets:\n\n\tbyte\t\ttype = SSH_MSG_EXT_INFO\n\tuint32\t\tno_extensions\n\t\tstring\tname\n\t\tstring\tvalue (binary data) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint readExtensionsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tint noExtensions, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Get the number of extensions present and make sure that it's valid */\n\tstatus = noExtensions = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid SSH extension information\" ) );\n\t\t}\n\tif( noExtensions < 1 || noExtensions > 16 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid SSH extension count %d, should be 0...16\", \n\t\t\t\t  noExtensions ) );\n\t\t}\n\n\t/* Process the extensions */\n\tLOOP_MED( i = 0, i < noExtensions, i++ )\n\t\t{\n\t\tBYTE nameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tvoid *dataPtr DUMMY_INIT_PTR;\n\t\tint nameLength, dataLength;\n\n\t\t/* Read the extension name */\n\t\tstatus = readString32( stream, nameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t   &nameLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid SSH extension name for extension %d\", i ) );\n\t\t\t}\n\n\t\t/* Read the extension data.  This may in theory be of zero length \n\t\t   for some extensions, although currently all zero-length \n\t\t   extensions consist of a redundant 'y' or 'n' to back up the \n\t\t   presence of the extension itself */\n\t\tstatus = dataLength = readUint32( stream );\n\t\tif( !cryptStatusError( status ) && dataLength != 0 )\n\t\t\t{\n\t\t\t/* If there's data present then it must have a valid length */\n\t\t\tif( dataLength < 1 || dataLength >= MAX_INTLENGTH_SHORT )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* Get a pointer to the data payload */\n\t\t\t\tstatus = sMemGetDataBlock( stream, &dataPtr, dataLength );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = sSkip( stream, dataLength, \n\t\t\t\t\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid extension data for extension %d, '%s'\", i,\n\t\t\t\t\t  sanitiseString( nameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  nameLength ) ) );\n\t\t\t}\n\t\tENSURES( dataLength >= 0 && dataLength < MAX_INTLENGTH_SHORT );\n\t\tANALYSER_HINT( dataPtr != NULL );\n\t\tDEBUG_PRINT(( \"Read extension %d, '%s', length %d.\\n\", i,\n\t\t\t\t\t  sanitiseString( nameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  nameLength ), \n\t\t\t\t\t  dataLength ));\n\t\tDEBUG_DUMP_DATA( dataPtr, dataLength );\n\n\t\t/* Process the extension data.  For now there's nothing much to do \n\t\t   here, the only extension that really affects us is \n\t\t   \"server-sig-algs\" which in theory is required before using RSA \n\t\t   with SHA-2 signatures for client auth, however the presence of\n\t\t   a SHA-2 capability on the server always seems to imply SHA-2 \n\t\t   client signature handling so it's not clear whether the extra\n\t\t   parsing and processing is really worth it, particularly since\n\t\t   using RSA-with-SHA2 when SHA2 is indicated always seems to work\n\t\t   while using it only when \"server-sig-algs\" is present means that \n\t\t   it'll only work on the subset of servers that implement \n\t\t   extensions */\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeExtensionsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Write the total extension count.  See the comment for the \n\t   no-flow-control extension for why we only write this if basic SSH\n\t   functionality is enabled */\n#ifndef USE_SSH_EXTENDED \n\twriteUint32( stream, 2 );\n#else\n\twriteUint32( stream, 1 );\n#endif /* USE_SSH_EXTENDED */\n\n\t/* Write the server signature algorithms extension */\n\tstatus = writeString32( stream, \"server-sig-algs\", 15 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( stream, SSH_ALGOCLASS_SIGN );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the no-flow-control extension.  This is a real pain to deal \n\t   with, the RFC requires, for no obvious reason, that \"Implementations \n\t   MUST refuse to open more than one simultaneous channel when this \n\t   extension is in effect\", but then bizarrely adds that \"Nevertheless, \n\t   server implementations SHOULD support clients opening more than one \n\t   non-simultaneous channel\".  This confusion will no doubt lead to more\n\t   or less arbitrary behaviour among implementations, rather than having\n\t   to fingerprint and identify issues in who knows how many different\n\t   versions we only send this extension if USE_SSH_EXTENDED isn't \n\t   defined, in which case we only allow a single channel no matter \n\t   what */\n#ifndef USE_SSH_EXTENDED \n\twriteString32( stream, \"no-flow-control\", 15 );\n\tstatus = writeString32( stream, \"p\", 1 );\n#endif /* !USE_SSH_EXTENDED */\n\t\n\treturn( status );\n\t}\n\n/* Read and check a public key:\n\n   RSA/DSA:\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\tmpint\te\t\t\tp\t\t\t\n\t\tmpint\tn\t\t\tq\n\t\tmpint\t\t\t\tg\n\t\tmpint\t\t\t\ty\n\n   ECDSA:\n\tstring\t\t[ server key/certificate ]\n\t\tstring\t\"ecdsa-sha2-*\"\n\t\tstring\t\"*\"\t\t\t\t-- The \"*\" portion from the above field\n\t\tstring\tQ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint checkReadPublicKey( INOUT STREAM *stream,\n\t\t\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *pubkeyAlgo,\n\t\t\t\t\t\tOUT_INT_SHORT_Z int *keyDataStart,\n\t\t\t\t\t\tINOUT ERROR_INFO *errorInfo )\n\t{\n\tint dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyDataStart, sizeof( int ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\t/* Clear return values */\n\t*pubkeyAlgo = CRYPT_ALGO_NONE;\n\t*keyDataStart = 0;\n\n\tstatus = readUint32( stream );\t/* Server key data size */\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = readAlgoString( stream, algoStringPubkeyTbl, \n\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringPubkeyTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ), \n\t\t\t\t\t\t\t\t pubkeyAlgo, TRUE, errorInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamBookmarkSet( stream, *keyDataStart  );\n\tswitch( *pubkeyAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\t/* RSA e, n */\n\t\t\treadInteger32( stream, NULL, &dummy, 1, CRYPT_MAX_PKCSIZE );\n\t\t\tstatus = readInteger32Checked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\t\t   MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\t\tbreak;\n\n#ifdef USE_DSA\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\t/* DSA p, q, g, y */\n\t\t\tstatus = readInteger32Checked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\t\t   MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\treadInteger32( stream, NULL, &dummy, 1, CRYPT_MAX_PKCSIZE );\n\t\t\treadInteger32( stream, NULL, &dummy, 1, CRYPT_MAX_PKCSIZE );\n\t\t\tstatus = readInteger32Checked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\t\t   MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\t\tbreak;\n#endif /* USE_DSA */\n\n#ifdef USE_ECDSA\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\treadUniversal32( stream );\t\t/* Skip field size */\n\t\t\tstatus = readInteger32Checked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\t\t   MIN_PKCSIZE_ECCPOINT, \n\t\t\t\t\t\t\t\t\t\t   MAX_PKCSIZE_ECCPOINT );\n\t\t\tbreak;\n#endif /* USE_ECDSA */\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet/Put Data Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a control message received during the processBodyFunction() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processControlMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t  IN_DATALENGTH_Z const int payloadLength )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tBYTE *bufPtr = sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t   sessionInfoPtr->receiveBufPos;\n\tSTREAM stream;\n\tint localPayloadLength = payloadLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( payloadLength >= 0 && payloadLength < MAX_BUFFER_SIZE );\n\n\t/* Putty 0.59 erroneously sent zero-length SSH_MSG_IGNORE packets, if \n\t   we find one of these then we convert it into a valid packet.  Writing \n\t   into the buffer at this position is safe because we've got padding \n\t   and at least sessionInfoPtr->authBlocksize bytes of MAC following the \n\t   current position.  We can also modify the localPayloadLength value \n\t   for the same reason */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t   SSH_PFLAG_ZEROLENIGNORE ) && \\\n\t\tsshInfo->packetType == SSH_MSG_IGNORE && localPayloadLength == 0 )\n\t\t{\n\t\tmemset( bufPtr, 0, UINT32_SIZE );\n\t\tlocalPayloadLength = UINT32_SIZE;\n\t\t}\n\n\t/* Make sure that the message length is valid.  This will be caught \n\t   anyway when we try and process the channel control message (and the\n\t   excessive-length check has already been performed by the packet-read \n\t   code) but checking it here avoids an assertion in the debug build \n\t   when we connect the stream, as well as just being good programming \n\t   practice */\n\tif( localPayloadLength <= 0 || \\\n\t\tlocalPayloadLength > sessionInfoPtr->receiveBufEnd - \\\n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufPos )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid session control message payload length %d for \"\n\t\t\t\t  \"%s (%d), should be 0...%d\", localPayloadLength, \n\t\t\t\t  getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t  sshInfo->packetType, sessionInfoPtr->receiveBufEnd - \\\n\t\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufPos ) );\n\t\t}\n\n\t/* Process the control message and reset the receive buffer indicators \n\t   to clear it */\n\tENSURES( boundsCheckZ( sessionInfoPtr->receiveBufPos, localPayloadLength,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd ) );\n\tsMemConnect( &stream, bufPtr, localPayloadLength );\n\tstatus = processChannelControlMessage( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tsessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos;\n\tsessionInfoPtr->pendingPacketLength = 0;\n\n\treturn( status );\n\t}\n\n/* Read data over the SSH link */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readHeaderFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   OUT_ENUM_OPT( READINFO ) \\\n\t\t\t\t\t\t\t\t\tREADSTATE_INFO *readInfo )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tBYTE *bufPtr = sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t   sessionInfoPtr->receiveBufPos;\n\tint length, extraLength, removedDataLength = ID_SIZE + PADLENGTH_SIZE;\n\tint partialPayloadLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Clear return value */\n\t*readInfo = READINFO_NONE;\n\n\t/* Make sure that there's room left to handle the speculative read */\n\tif( sessionInfoPtr->receiveBufPos >= \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize - 128 )\n\t\treturn( 0 );\n\n\t/* Try and read the header data from the remote system */\n\tREQUIRES( sessionInfoPtr->receiveBufPos == sessionInfoPtr->receiveBufEnd );\n\tstatus = readPacketHeaderSSH2( sessionInfoPtr, SSH_MSG_CHANNEL_DATA,\n\t\t\t\t\t\t\t\t   &length, &extraLength, sshInfo, \n\t\t\t\t\t\t\t\t   readInfo, SSH_PROTOSTATE_DATA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* OK_SPECIAL means that we got a soft timeout before the entire \n\t\t   header was read, so we return zero bytes read to tell the \n\t\t   calling code that there's nothing more to do */\n\t\tif( status == OK_SPECIAL ) \n\t\t\treturn( 0 );\n\n\t\treturn( status );\n\t\t}\n\n\t/* All errors from this point are fatal crypto errors */\n\t*readInfo = READINFO_FATAL_CRYPTO;\n\n\tENSURES( length >= ID_SIZE + PADLENGTH_SIZE + SSH2_MIN_PADLENGTH_SIZE && \\\n\t\t\t length <= sessionInfoPtr->receiveBufSize - \\\n\t\t\t\t\t   sessionInfoPtr->receiveBufPos && \\\n\t\t\t length < MAX_BUFFER_SIZE );\n\tstatus = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t\t sshInfo->readSeqNo, bufPtr, \n\t\t\t\t\t\t\t\t\t MIN_PACKET_SIZE - LENGTH_SIZE,\n\t\t\t\t\t\t\t\t\t MIN_PACKET_SIZE - LENGTH_SIZE, \n\t\t\t\t\t\t\t\t\t length, MAC_START, \n\t\t\t\t\t\t\t\t\t sessionInfoPtr->authBlocksize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We don't return an extended status at this point because we\n\t\t   haven't completed the message MAC calculation/check yet so \n\t\t   any errors will be cryptlib-internal ones */\n\t\treturn( status );\n\t\t}\n\n\t/* If it's channel data, strip the encapsulation, which allows us to\n\t   process the payload directly without having to move it around in\n\t   the buffer:\n\n\t  [\tuint32\t\tlength (excluding MAC size)\t- Processed in rPHSSH2() ]\n\t\tbyte\t\tpadLen\n\t\tbyte\t\tSSH_MSG_CHANNEL_DATA\n\t\t\tuint32\trecipient channel\n\t\t\tuint32\tdataLength\t| string\tdata\n\t\t\tbyte[]\tdata\t\t|\n\t  [ byte[]\t\tpadding ]\n\t  [\tbyte[]\t\tMAC ] */\n\tif( sshInfo->packetType == SSH_MSG_CHANNEL_DATA )\n\t\t{\n\t\tSTREAM stream;\n\t\tint payloadLength;\n\n\t\tstatic_assert( SSH_HEADER_REMAINDER_SIZE >= ID_SIZE + \\\n\t\t\t\t\t\t\tPADLENGTH_SIZE + SSH2_MIN_PADLENGTH_SIZE,\n\t\t\t\t\t   \"SSH header size read\" );\n\n\t\tENSURES( boundsCheckZ( sessionInfoPtr->receiveBufPos, \n\t\t\t\t\t\t\t   SSH_HEADER_REMAINDER_SIZE, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\n\t\tsMemConnect( &stream, bufPtr, SSH_HEADER_REMAINDER_SIZE );\n\n\t\t/* Skip the type, padding length, and channel number and make sure \n\t\t   that the payload length matches the packet length */\n\t\tsSkip( &stream, PADLENGTH_SIZE + ID_SIZE + UINT32_SIZE,\n\t\t\t   PADLENGTH_SIZE + ID_SIZE + UINT32_SIZE );\n\t\tstatus = payloadLength = readUint32( &stream );\n\t\tif( !cryptStatusError( status ) )\n\t\t\tremovedDataLength = stell( &stream );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tpayloadLength != length - ( removedDataLength + \\\n\t\t\t\t\t\t\t\t\t\tsshInfo->padLength ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid data packet payload length %d for \"\n\t\t\t\t\t  \"SSH_MSG_CHANNEL_DATA (94), should be %d\", \n\t\t\t\t\t  cryptStatusError( status ) ? 0 : payloadLength,\n\t\t\t\t\t  length - ( removedDataLength + sshInfo->padLength ) ) );\n\t\t\t}\n\n\t\t/* Errors are back to standard fatal errors */\n\t\t*readInfo = READINFO_FATAL;\n\n\t\t/* Move back to the start of the payload and process the channel \n\t\t   data header, required in order to handle window size updates.  \n\t\t   This consists of the channel number and yet another length value,\n\t\t   present at the start of the payload which is encoded as an SSH\n\t\t   string (uint32 length + data).  This value has already been\n\t\t   checked above, and is only accepted if it matches the outer\n\t\t   length value.  This is important because the data hasn't been\n\t\t   verified by the MAC yet, since we need to process the header in\n\t\t   order to find out where the MAC is.  This means that the channel\n\t\t   number is processed unverified, but this shouldn't be a major\n\t\t   issue since at most an attacker can corrupt the value, and it \n\t\t   will end up being mapped to an invalid channel with a high\n\t\t   probability */\n\t\tsseek( &stream, PADLENGTH_SIZE + ID_SIZE );\n\t\tstatus = processChannelControlMessage( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Errors are back to standard fatal errors */\n\t*readInfo = READINFO_FATAL;\n\n\t/* Move the remainder down to the start of the buffer.  The general idea\n\t   is to remove all of the header data so that only the payload remains\n\t   in the buffer, avoiding the need to move it down afterwards:\n\n\t\t\t rBufPos\n\t\t\t\t|\n\t\t\t\tv\t\t\t\t|<-- pPayloadLen -->|\n\t\t+-------+---------------+-------------------+-------+\n\t\t|\t\t|\t\t\t\t|///////////////////|\t\t|\n\t\t+-------+---------------+-------------------+-------+\n\t\t\t\t^<-removedDLen->|\n\t\t\t\t|\n\t\t\t bufPtr\n\t   \n\t   This is complicated by the fact that (unlike SSL) all of the data \n\t   (including the header) is encrypted and MAC'd so we can't just read \n\t   that separately but have to process it as part of the payload, remove \n\t   it, and remember anything that's left for later */\n\tREQUIRES( isShortIntegerRangeNZ( removedDataLength ) );\n\tpartialPayloadLength = SSH_HEADER_REMAINDER_SIZE - removedDataLength;\n\tENSURES( partialPayloadLength > 0 && \\\n\t\t\t removedDataLength + partialPayloadLength <= \\\n\t\t\t\tsessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufPos && \\\n\t\t\t removedDataLength + partialPayloadLength < MAX_BUFFER_SIZE );\n\tREQUIRES( boundsCheck( sessionInfoPtr->receiveBufPos + removedDataLength, \n\t\t\t\t\t\t   partialPayloadLength, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tmemmove( bufPtr, bufPtr + removedDataLength, partialPayloadLength );\n\n\t/* Determine how much data we'll be expecting, adjusted for the fixed\n\t   information that we've removed and the (implicitly present) MAC data */\n\tsessionInfoPtr->pendingPacketLength = \\\n\t\t\tsessionInfoPtr->pendingPacketRemaining = \\\n\t\t\t\t\t( length + extraLength ) - removedDataLength;\n\tENSURES( sessionInfoPtr->pendingPacketLength > 0 && \\\n\t\t\t sessionInfoPtr->pendingPacketLength < MAX_BUFFER_SIZE );\n\tsshInfo->partialPacketDataLength = partialPayloadLength;\n\n\t/* Indicate that we got some payload as part of the header */\n\t*readInfo = READINFO_HEADERPAYLOAD;\n\treturn( partialPayloadLength );\n\t}\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processBodyFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tBYTE *dataRemainingPtr = sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufPos + \\\n\t\t\t\t\t\t\t sshInfo->partialPacketDataLength;\n\tconst int dataRemainingSize = sessionInfoPtr->pendingPacketLength - \\\n\t\t\t\t\t\t\t\t  sshInfo->partialPacketDataLength;\n\tconst int dataLength = dataRemainingSize - sessionInfoPtr->authBlocksize;\n\tint payloadLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( boundsCheck( sessionInfoPtr->receiveBufPos + \\\n\t\t\t\t\t\t\tsshInfo->partialPacketDataLength,\n\t\t\t\t\t\t   dataRemainingSize, sessionInfoPtr->receiveBufEnd ) );\n\tREQUIRES( dataRemainingSize >= sessionInfoPtr->authBlocksize && \\\n\t\t\t  dataLength >= 0 && dataLength < dataRemainingSize );\n\n\t/* All errors processing the payload are fatal, and for the following \n\t   operations specifically fatal crypto errors */\n\t*readInfo = READINFO_FATAL_CRYPTO;\n\n\t/* Decrypt the packet in the buffer and MAC the payload.  The length may\n\t   be zero if the entire message fits into the already-processed fixed-\n\t   length header portion, e.g. for channel-close messages that only \n\t   contain a channel number:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tKey:\n\t\t\tProcessed in header read\t\t\t\t\t\t\t+--+\n\t\trecBufPos |\t\t\t\t\t\t\t\t\t\t\t\t|  | Processed\n\t\t\t|<----v----- pendingPacketLength ---------->|\t\t+--+\n\t\t\tv<- pPDL -->|\t\t\t\t\t\t\t\t|\t\t+--+\n\t\t----+-----------+-----------------------+-------+--\t\t|//| Encrypted\n\t\t\t|\t\t\t|///////////////////////|\\\\\\\\\\\\\\|\t\t+--+\n\t\t----+-----------+-----------------------+-------+--\t\t+--+\n\t\t\t\t\t\t|<---- dataLength ----->|\t\t|\t\t|\\\\| MAC\n\t\t\t\t\t\t|<------- dataRemaining ------->|\t\t+--+ */\n\tif( dataLength > 0 )\n\t\t{\n#ifdef USE_SSH_CTR\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t\t{\n\t\t\tstatus = ctrModeCrypt( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t   sshInfo->readCTR, \n\t\t\t\t\t\t\t\t   sessionInfoPtr->cryptBlocksize,\n\t\t\t\t\t\t\t\t   dataRemainingPtr, dataLength );\n\t\t\t}\n\t\telse\n#endif /* USE_SSH_CTR */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, dataRemainingPtr,\n\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext, 0,\n\t\t\t\t\t\t\t\t\t\t\t dataRemainingPtr, dataRemainingSize, \n\t\t\t\t\t\t\t\t\t\t\t dataLength, 0, MAC_END, \n\t\t\t\t\t\t\t\t\t\t\t sessionInfoPtr->authBlocksize );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = checkMacSSHIncremental( sessionInfoPtr->iAuthInContext, 0, \n\t\t\t\t\t\t\t\t\t\t dataRemainingPtr, dataRemainingSize, \n\t\t\t\t\t\t\t\t\t\t 0, 0, MAC_END, \n\t\t\t\t\t\t\t\t\t\t sessionInfoPtr->authBlocksize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Bad message MAC for %s (%d) packet, length %d\",\n\t\t\t\t  getSSHPacketName( sshInfo->packetType ),\n\t\t\t\t  sshInfo->packetType,\n\t\t\t\t  sshInfo->partialPacketDataLength + dataLength ) );\n\t\t}\n\n\t/* Errors are back to standard fatal errors */\n\t*readInfo = READINFO_FATAL;\n\n\t/* Strip the padding and MAC and update the state information */\n\tpayloadLength = sessionInfoPtr->pendingPacketLength - \\\n\t\t\t\t\t( sshInfo->padLength + sessionInfoPtr->authBlocksize );\n\tsshInfo->readSeqNo++;\n\tENSURES( payloadLength >= 0 && \\\n\t\t\t payloadLength < sessionInfoPtr->pendingPacketLength + dataLength && \\\n\t\t\t payloadLength < MAX_BUFFER_SIZE );\n\t\t\t /* pendingPacketLength check must be '<' rather than '<=' \n\t\t\t    because of the stripped padding */\n\tDEBUG_PRINT(( \"Read %s (%d) packet, length %d.\\n\", \n\t\t\t\t  getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t  sshInfo->packetType, payloadLength ));\n\tDEBUG_DUMP_DATA( sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t sessionInfoPtr->receiveBufPos, payloadLength );\n\n\t/* If it's not plain data (which was handled at the readHeaderFunction()\n\t   stage), handle it as a control message */\n\tif( sshInfo->packetType != SSH_MSG_CHANNEL_DATA )\n\t\t{\n\t\tstatus = processControlMessage( sessionInfoPtr, payloadLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we got an OK_SPECIAL status then the packet was handled\n\t\t\t   internally and we can try again.  If it was a message that\n\t\t\t   the user has to respond to it's also not a fatal error\n\t\t\t   condition and they can continue afterwards */\n\t\t\tif( status == OK_SPECIAL || status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t\t*readInfo = READINFO_NOOP;\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tsshInfo->partialPacketDataLength = 0;\n\n\t*readInfo = READINFO_NONE;\n\treturn( payloadLength );\n\t}\n\n/* Write data over the SSH link */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int preparePacketFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tSTREAM stream;\n\tconst int dataLength = sessionInfoPtr->sendBufPos - \\\n\t\t\t\t\t\t   ( SSH2_HEADER_SIZE + SSH2_PAYLOAD_HEADER_SIZE );\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( !TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t  SESSION_FLAG_SENDCLOSED ) );\n\tREQUIRES( dataLength > 0 && dataLength < sessionInfoPtr->sendBufPos && \\\n\t\t\t  dataLength < MAX_BUFFER_SIZE );\n\n\t/* Wrap up the payload ready for sending:\n\n\t\tbyte\t\tSSH_MSG_CHANNEL_DATA\n\t\tuint32\t\tchannel_no\n\t\tstring\t\tdata\n\n\t   Since this is wrapping in-place data, we first open a write stream to\n\t   add the header, then open a read stream covering the full buffer in\n\t   preparation for wrapping the packet */\n\tstatus = openPacketStreamSSHEx( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\tSSH2_PAYLOAD_HEADER_SIZE,\n\t\t\t\t\t\t\t\t\tSSH_MSG_CHANNEL_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteUint32( &stream, getCurrentChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t\t   CHANNEL_WRITE ) );\n\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_DATA, \n\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_DATA_1 );\n\tstatus = writeUint32( &stream, dataLength );\n\tsMemDisconnect( &stream );\n\tENSURES( cryptStatusOK( status ) );\n\tsMemConnect( &stream, sessionInfoPtr->sendBuffer,\n\t\t\t\t sessionInfoPtr->sendBufSize );\n\tstatus = sSkip( &stream, SSH2_HEADER_SIZE + SSH2_PAYLOAD_HEADER_SIZE + \\\n\t\t\t\t\t\t\t dataLength, SSKIP_MAX );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, 0, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tINJECT_FAULT( SESSION_CORRUPT_DATA, SESSION_CORRUPT_DATA_SSH_1 );\n\n\t/* If there's control data enqueued to be written, try and append it to\n\t   the existing data to be sent.  This may or may not append it \n\t   (depending on whether there's room in the send buffer) so we may end\n\t   up here more than once */\n\tif( sshInfo->response.type > 0 )\n\t\t{\n\t\tint length2;\n\n\t\tstatus = length2 = appendChannelData( sessionInfoPtr, length );\n\t\tif( !cryptStatusError( status  ) )\n\t\t\tlength += length2;\n\t\t}\n\n\treturn( length );\n\t}\n\n/* Close a previously-opened SSH session */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void shutdownFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* If we haven't entered the secure state yet (i.e. we're still in the\n\t   middle of the handshake) then this is an abnormal termination, send \n\t   a disconnect indication:\n\n\t\tbyte\t\tSSH_MSG_DISCONNECT\n\t\tuint32\t\treason_code = SSH_DISCONNECT_PROTOCOL_ERROR\n\t\tstring\t\tdescription = \"Handshake failed\"\n\t\tstring\t\tlanguage_tag = \"\" */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE ) )\n\t\t{\n\t\tSTREAM stream;\n\t\tint status;\n\n\t\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  SSH_MSG_DISCONNECT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsNetDisconnect( &sessionInfoPtr->stream );\n\t\t\treturn;\n\t\t\t}\n\t\twriteUint32( &stream, SSH_DISCONNECT_PROTOCOL_ERROR );\n\t\twriteString32( &stream, \"Handshake failed\", 16 );\n\t\tstatus = writeUint32( &stream, 0 );\t\t/* No language tag */\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst int length = stell( &stream );\n\t\t\tvoid *dataPtr;\n\n\t\t\t/* Since there's nothing much that we can do at this point in \n\t\t\t   response to an error except continue and close the network\n\t\t\t   session, we don't check for errors */\n\t\t\tstatus = sMemGetDataBlockAbs( &stream, 0, &dataPtr, length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t( void ) sendCloseNotification( sessionInfoPtr, dataPtr, \n\t\t\t\t\t\t\t\t\t\t\t\tlength );\n\t\t\t\t}\n\t\t\t}\n\t\tsMemDisconnect( &stream );\n\t\treturn;\n\t\t}\n\n\t/* Close all remaining channels.  Since this is just a cleanup of a \n\t   network session that's about to be closed anyway we ignore any errors \n\t   that we encounter at this point (a typical error would be the link \n\t   going down, in which case the only useful response is to take down \n\t   the network session anyway) */\n\t( void ) closeChannel( sessionInfoPtr, TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up access to the SSH session processing */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2processing( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tFNPTR_SET( sessionInfoPtr->readHeaderFunction, readHeaderFunction );\n\tFNPTR_SET( sessionInfoPtr->processBodyFunction, processBodyFunction );\n\tFNPTR_SET( sessionInfoPtr->preparePacketFunction, preparePacketFunction );\n\tFNPTR_SET( sessionInfoPtr->shutdownFunction, shutdownFunction );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_authc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\tcryptlib SSHv2 Client-side Authentication Management\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n/* The SSH authentication process is awkward and complex and even with the \n   significant simplifications applied here still ends up a lot more \n   convoluted than it should be, particularly when we have to add all sorts\n   of special-case handling for valid but unusual interpretations of the\n   spec.  The overall control flow (excluding handling of special-case\n   peculiarities) is:\n\n\tprocessAuthFailure:\n\t\treadAuthFailureInfo();\n\t\treportAuthFailure();\n\n\tprocessPAM:\n\t\tperform PAM authentication;\n\t\tif( fail )\n\t\t\treturn( processAuthFailure() );\n\t\treturn error/success;\n\n\tprocessClientAuth:\n\t\tif( hasPassword )\n\t\t\tsend password auth;\n\t\telse\n\t\t\tsend PKC auth;\n\t\tif( success )\n\t\t\treturn success;\n\t\trequired = readAuthFailureInfo();\n\t\tif( required == PAM )\n\t\t\tprocessPAM();\n\t\tif( required == further auth )\n\t\t\tsend PKC auth if available;\n\t\treturn( processAuthFailure() ); */\n\n#ifdef USE_SSH\n\n/* Tables mapping SSH algorithm names to cryptlib algorithm IDs, in\n   preferred algorithm order.  There are two of these, one that favours\n   password-based authentication and one that favours PKC-based\n   authentication, depending on whether the user has specified a password\n   or a PKC as their authentication choice.  This is required in order to\n   handle SSH's weird way of reporting authentication failures, see the\n   comment in reportAuthFailure() for details */\n\nstatic const ALGO_STRING_INFO algoStringUserauthentPWTbl[] = {\n\t{ \"password\", 8, MK_ALGO( PSEUDOALGO_PASSWORD ) },\n\t{ \"keyboard-interactive\", 20, MK_ALGO( PSEUDOALGO_PAM ) },\n\t{ \"publickey\", 9, CRYPT_ALGO_RSA },\t/* Representative PKC */\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, 0, CRYPT_ALGO_NONE }\n\t};\nstatic const ALGO_STRING_INFO algoStringUserauthentPKCTbl[] = {\n\t{ \"publickey\", 9, CRYPT_ALGO_RSA },\t/* Representative PKC */\n\t{ \"password\", 8, MK_ALGO( PSEUDOALGO_PASSWORD ) },\n\t{ \"keyboard-interactive\", 20, MK_ALGO( PSEUDOALGO_PAM ) },\n\t{ NULL, 0, CRYPT_ALGO_NONE }, { NULL, CRYPT_ALGO_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a public-key authentication packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int rewriteRSASignature( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT STREAM *stream,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int sigLength,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int sigDataMaxLength )\n\t{\n\tBYTE sigDataBuffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\tconst int sigOffset = stell( stream );\n\tint sigSize, keySize, delta, i, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( sigLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( sigDataMaxLength ) );\n\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the signature length and check whether it needs padding.  Note \n\t   that we read the signature data with readString32() rather than \n\t   readInteger32() to ensure that we get the raw signature data exactly \n\t   as written rather than the cleaned-up integer value */\n\treadUint32( stream );\n\treadUniversal32( stream );\n\tstatus = readString32( stream, sigDataBuffer, CRYPT_MAX_PKCSIZE,\n\t\t\t\t\t\t   &sigSize );\n\tENSURES( cryptStatusOK( status ) );\n\tif( sigSize >= keySize )\n\t\t{\n\t\t/* The signature size is the same as the modulus size, there's \n\t\t   nothing to do.  The reads above have reset the stream-position \n\t\t   indicator to the end of the signature data so there's no need to \n\t\t   perform an explicit seek before exiting */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* We've got a signature that's shorter than the RSA modulus, we need to \n\t   rewrite it to pad it out to the modulus size:\n\n\t\t  sigOfs\t\t\t\t  sigDataBuffer\n\t\t\t|\t\t\t\t\t\t\t|\n\t\t\tv uint32\tstring32\t\tv\n\t\t\t+-------+---------------+---+-------------------+\n\t\t\t| length|\talgo-name\t|pad|\tsigData\t\t\t|\n\t\t\t+-------+---------------+---+-------------------+\n\t\t\t|\t\t\t\t\t\t|<+>|<---- sigSize ---->|\n\t\t\t|\t\t\t\t\t\tdelta\t\t\t\t\t|\n\t\t\t|\t\t\t\t\t\t|<------ keySize ------>|\n\t\t\t|<----------------- sigLength ----------------->|\n\t\t\t|<------------- sigDataMaxLength --------[...]-------->| */\n\tdelta = keySize - sigSize;\n\tENSURES( delta > 0 && delta < 16 );\n\tif( sigLength + delta > sigDataMaxLength )\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\tsseek( stream, sigOffset );\n\twriteUint32( stream, sizeofString32( 7 ) + \\\n\t\t\t\t\t\t sizeofString32( keySize ) );\n\twriteString32( stream, \"ssh-rsa\", 7 );\n\twriteUint32( stream, keySize );\n\tLOOP_MED( i = 0, i < delta, i++ )\n\t\tsputc( stream, 0 );\n\tENSURES( LOOP_BOUND_OK );\n\treturn( swrite( stream, sigDataBuffer, sigSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int createPubkeyAuth( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t const SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t INOUT STREAM *stream,\n\t\t\t\t\t\t\t const ATTRIBUTE_LIST *userNamePtr )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tvoid *sigDataPtr, *packetDataPtr DUMMY_INIT_PTR;\n\tint sigDataMaxLength, packetDataLength;\n\tint sigLength DUMMY_INIT, pkcAlgo, status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( userNamePtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgo, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/*\tbyte\ttype = SSH_MSG_USERAUTH_REQUEST\n\t\tstring\tuser_name\n\t\tstring\tservice_name = \"ssh-connection\"\n\t\tstring\tmethod-name = \"publickey\"\n\t\tboolean\tTRUE\n\t\tstring\t\t\"ssh-rsa\"\t\t\"rsa-sha2-256\"\t\t\"ssh-dss\"\n\t\tstring\t\t[ client key/certificate ]\n\t\t\tstring\t\"ssh-rsa\"\t\t\"ssh-rsa\"\t\t\t\"ssh-dss\"\n\t\t\tmpint\te\t\t\t\te\t\t\t\t\tp\n\t\t\tmpint\tn\t\t\t\tn\t\t\t\t\tq\n\t\t\tmpint\t\t\t\t\t\t\t\t\t\tg\n\t\t\tmpint\t\t\t\t\t\t\t\t\t\ty\n\t\tstring\t\t[ client signature ]\n\t\t\tstring\t\"ssh-rsa\"\t\t\"rsa-sha2-256\"\t\t\"ssh-dss\"\n\t\t\tstring\tsignature\t\tsignature\t\t\tsignature\n\n\t   Note the multiple copies of the algorithm name, the spec first \n\t   requires that the public-key authentication packet send the algorithm \n\t   name, then includes it a second time as part of the client key \n\t   information, and just for good measure specifies it a third time in \n\t   the signature.  However, just to keep everyone on their toes the\n\t   name changes for RSA with SHA2 so that the key is given the old\n\t   name and the overall blob and signature are given the new name */\n\tstreamBookmarkSetFullPacket( stream, packetDataLength );\n\twriteString32( stream, userNamePtr->value, userNamePtr->valueLength );\n\twriteString32( stream, \"ssh-connection\", 14 );\n\twriteString32( stream, \"publickey\", 9 );\n\tsputc( stream, 1 );\n\tstatus = writeAlgoStringEx( stream, pkcAlgo, handshakeInfo->hashAlgo, 0,\n\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_NONE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = exportAttributeToStream( stream, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( stream, &packetDataPtr, \n\t\t\t\t\t\t\t\t\t\t &packetDataLength, \n\t\t\t\t\t\t\t\t\t\t packetDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Hash the authentication request data, composed of:\n\n\t\tstring\t\texchange hash\n\t\t[ SSH_MSG_USERAUTH_REQUEST packet payload up to signature start ] */\n\tsetMessageCreateObjectInfo( &createInfo, handshakeInfo->hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_NOHASHLENGTH ) )\n\t\t{\n\t\t/* Some implementations erroneously omit the length when hashing the \n\t\t   exchange hash */\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) handshakeInfo->sessionID,\n\t\t\t\t\t\t\t\t  handshakeInfo->sessionIDlength );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = hashAsString( createInfo.cryptHandle, \n\t\t\t\t\t\t\t   handshakeInfo->sessionID,\n\t\t\t\t\t\t\t   handshakeInfo->sessionIDlength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  packetDataPtr, packetDataLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \"\", 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Sign the hash.  The reason for the min() part of the expression is \n\t   that iCryptCreateSignature() gets suspicious of very large buffer \n\t   sizes, for example when the user has specified the use of a huge send \n\t   buffer */\n\tstatus = sMemGetDataBlockRemaining( stream, &sigDataPtr, \n\t\t\t\t\t\t\t\t\t\t&sigDataMaxLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = iCryptCreateSignature( sigDataPtr, \n\t\t\t\t\t\tmin( sigDataMaxLength, MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\t&sigLength, CRYPT_IFORMAT_SSH, \n\t\t\t\t\t\tsessionInfoPtr->privateKey, createInfo.cryptHandle, \n\t\t\t\t\t\tNULL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Some buggy implementations require that RSA signatures be padded \n\t\t   with zeroes to the full modulus size, mysteriously failing the \n\t\t   authentication in a small number of randomly-distributed cases \n\t\t   when the signature format happens to be less than the modulus \n\t\t   size.  To handle this we have to rewrite the signature to include \n\t\t   the extra padding bytes */\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSH_PFLAG_RSASIGPAD ) && pkcAlgo == CRYPT_ALGO_RSA )\n\t\t\t{\n\t\t\tstatus = rewriteRSASignature( sessionInfoPtr, stream, sigLength, \n\t\t\t\t\t\t\t\t\t\t  min( sigDataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t   MAX_INTLENGTH_SHORT - 1 ) );\n\t\t\t}\n\t\telse\n\t\t\tstatus = sSkip( stream, sigLength, MAX_INTLENGTH_SHORT );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tProcess Authentication Failures\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the server's authentication failure response */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nstatic int readAuthFailureInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t\tOUT_ALGO_Z CRYPT_ALGO_TYPE *authAlgo,\n\t\t\t\t\t\t\t\tOUT_BOOL BOOLEAN *furtherAuthRequired,\n\t\t\t\t\t\t\t\tconst BOOLEAN usedPasswordAuth )\n\t{\n\tCRYPT_ALGO_TYPE requiredAuthAlgo;\n\tSTREAM stream;\n\tBOOLEAN partialSuccess = FALSE;\n\tint status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( authAlgo, sizeof( CRYPT_ALGO_TYPE ) ) );\n\tassert( isWritePtr( furtherAuthRequired, sizeof( BOOLEAN ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( usedPasswordAuth == TRUE || usedPasswordAuth == FALSE );\n\n\t/* Clear return values */\n\t*authAlgo = CRYPT_ALGO_NONE;\n\t*furtherAuthRequired = FALSE;\n\n\t/* Before we can try and interpret the response, we have to check for an\n\t   empty response */\n\tif( length >= LENGTH_SIZE && \\\n\t\t!memcmp( sessionInfoPtr->receiveBuffer,\n\t\t\t\t \"\\x00\\x00\\x00\\x00\", LENGTH_SIZE ) )\n\t\t{\n\t\t/* It's an empty response.  There are two interpretations for this, \n\t\t   the first of which is that some buggy implementations return an \n\t\t   authentication failure with the available-authentication types \n\t\t   string empty to indicate that no authentication is required \n\t\t   rather than returning an authentication success status as \n\t\t   required by the spec (although the problem is really in the spec \n\t\t   and not in the interpretation since there's no way to say that \n\t\t   \"no-auth\" is a valid authentication type).  If we find one of \n\t\t   these then we return an OK_SPECIAL status to let the caller know \n\t\t   that they should retry the authentication.  Because this is a \n\t\t   broken packet format we have to check the encoded form rather \n\t\t   than being able to read it as normal */\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSH_PFLAG_EMPTYUSERAUTH ) )\n\t\t\t{\n\t\t\t/* It's a garbled attempt to tell us that no authentication is\n\t\t\t   required, tell the caller to try again without \n\t\t\t   authentication */\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\n\t\t/* A more logical interpretation is that no further authentication\n\t\t   type is permitted */\n\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t  \"Remote system denied our authentication attempt\" ) );\n\t\t}\n\n\t/* The authentication failed, pick apart the response to see if we can\n\t   return more meaningful error information:\n\n\t  [\tbyte\ttype = SSH_MSG_USERAUTH_FAILURE ]\n\t\tstring\tavailable_auth_types\n\t\tboolean\tpartial_success\n\n\t  The available-auth types field is handled in the typical SSH \n\t  schizophrenic manner in which, instead of saying \"authentication \n\t  failed\", it returns a list of allowed authentication methods, one of \n\t  which may be the one that we just used, see the comment in \n\t  reportAuthFailure() for details.  In order to deal with this we use\n\t  two different mapping tables to read the available-auth types field,\n\t  one that prefers passwords if we used password auth and one that \n\t  prefers public keys if we used public-key auth.  In other words if we\n\t  used password auth then we assume that the failure was due to an\n\t  incorrect password and prefer a password-auth error report, and the\n\t  same for public keys.\n\t  \n\t  However this doesn't help in the case where the server asks for\n\t  something like { publickey, password } and reports partial success\n\t  with the required auth being { publickey, password }, because it\n\t  could be after two passwords or a public key and password or whatever.  \n\t  In order to deal with this, we have to re-read the available-auth \n\t  types field using the opposite preference, and if we get a different\n\t  result then report an ambiguous error to the caller, in other words\n\t  that the server has indicated that something is needed to continue but\n\t  it won't specify what.\n\n\t  The partial_success flag is a kitchen-sink kludge used to deal with\n\t  situation-specific events like changed passwords and similar issues, \n\t  in this case it means that the authentication was successful despite \n\t  the overall packet type indicating that the authentication failed, and \n\t  that something else is needed.  In general this whole section of the \n\t  protocol winds up in an extremely complex state machine with all sorts \n\t  of special-case conditions, several of which require manual \n\t  intervention by the user in order to continue, however we can handle\n\t  the specific case of \"authentication failed but it really succeeded\"\n\t  by letting the user know that further authentication is required on \n\t  top of the already-performed authentication */\n\tENSURES( rangeCheck( length, 1, sessionInfoPtr->receiveBufSize ) );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tif( usedPasswordAuth )\n\t\t{\n\t\tstatus = readAlgoString( &stream, algoStringUserauthentPWTbl,\n\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringUserauthentPWTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t &requiredAuthAlgo, FALSE, SESSION_ERRINFO );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readAlgoString( &stream, algoStringUserauthentPKCTbl,\n\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringUserauthentPKCTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t &requiredAuthAlgo, FALSE, SESSION_ERRINFO );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint value;\n\n\t\t/* Read the partial-success value to see whether we need to change\n\t\t   how we're dealing with the problem */\n\t\tstatus = value = sgetc( &stream );\n\t\tif( !cryptStatusError( status ) && value )\n\t\t\t{\n\t\t\tpartialSuccess = TRUE;\n\t\t\tstatus = CRYPT_OK;\t/* sgetc() returns boolean flag */\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && partialSuccess )\n\t\t{\n\t\tCRYPT_ALGO_TYPE altRequiredAuthAlgo;\n\n\t\t/* We've been given possibly garbled available-auth type information, \n\t\t   re-read the data with the preference reversed (see the comment at \n\t\t   the start of this code block).  If we now get a different \n\t\t   required algorithm then we can't really tell the user what to do \n\t\t   in order to continue because the server's indication of what's \n\t\t   required is ambiguous */\n\t\tsseek( &stream, 0 );\n\t\tif( usedPasswordAuth )\n\t\t\t{\n\t\t\tstatus = readAlgoString( &stream, algoStringUserauthentPKCTbl,\n\t\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringUserauthentPKCTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t\t &altRequiredAuthAlgo, FALSE, SESSION_ERRINFO );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = readAlgoString( &stream, algoStringUserauthentPWTbl,\n\t\t\t\t\t\t\t\t\t FAILSAFE_ARRAYSIZE( algoStringUserauthentPWTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t ALGO_STRING_INFO ),\n\t\t\t\t\t\t\t\t\t &altRequiredAuthAlgo, FALSE, SESSION_ERRINFO );\n\t\t\t}\n\t\tif( requiredAuthAlgo != altRequiredAuthAlgo )\n\t\t\trequiredAuthAlgo = CRYPT_PSEUDOALGO_AMBIGUOUS;\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the problem is due to lack of a compatible algorithm, make the\n\t\t   error message a bit more specific to tell the user that we got\n\t\t   through most of the handshake but failed at the authentication\n\t\t   stage */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t\t  \"Remote system supports neither password nor \"\n\t\t\t\t\t  \"public-key authentication\" ) );\n\t\t\t}\n\n\t\t/* There was some other problem with the returned information, we\n\t\t   still report it as a failed-authentication error but leave the\n\t\t   extended error information in place to let the caller see what \n\t\t   the underlying cause was */\n\t\treturn( CRYPT_ERROR_WRONGKEY );\n\t\t}\n\n\t*authAlgo = requiredAuthAlgo;\n\t*furtherAuthRequired = partialSuccess;\n\treturn( CRYPT_OK );\n\t}\n\n/* Process an authentication failure.  SSH reports authentication failures \n   in a somewhat bizarre way, instead of saying \"authentication failed\" it \n   returns a list of allowed authentication methods, one of which may \n   be the one that we just used, and one of which may be the one that we\n   need to continue (it's not guaranteed, see the comments in \n   readAuthFailureInfo() and other locations).  To figure out whether a \n   problem occurred because we used the wrong authentication method or \n   because we submitted the wrong authentication value we have to perform a \n   complex decode and match of the information in the returned packet with \n   what we sent.  The breakdown is:\n\n\t  Tried\t Partial Required\tResult\n\t  Auth.\t Success   Auth.\n\t--------+-------+-------+------------\n\t\t\t|\tN\t|  Sig\t| Wrong sig.\n\t\t\t|\tN\t|  PW\t| Need PW instead of sig.\n\t  Sig\t+-------+-------+\n\t\t\t|\tY\t|  Sig\t| Sig OK, need more sig.\n\t\t\t|\tY\t|  PW\t| Sig OK, need PW.\n\t--------+-------+-------+\n\t\t\t|\tN\t|  Sig\t| Need sig. instead of PW.\n\t\t\t|\tN\t|  PW\t| Wrong PW.\n\t   PW\t+-------+-------+\n\t\t\t|\tY\t|  Sig\t| PW OK, need sig.\n\t\t\t|\tY\t|  PW\t| PW OK, need more PW.\n\t--------+-------+-------+ */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int reportAuthFailure( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE providedAuthAlgo,\n\t\t\t\t\t\t\t  IN_ALGO const CRYPT_ALGO_TYPE requiredAuthAlgo,\n\t\t\t\t\t\t\t  const BOOLEAN partialAuthOK )\n\t{\n\tconst BOOLEAN needsPW = \\\n\t\t\t( requiredAuthAlgo == CRYPT_PSEUDOALGO_PASSWORD || \\\n\t\t\t  requiredAuthAlgo == CRYPT_PSEUDOALGO_PAM ) ? TRUE : FALSE;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isEnumRange( providedAuthAlgo, CRYPT_ALGO ) );\n\tREQUIRES( isEnumRange( requiredAuthAlgo, CRYPT_ALGO ) );\n\tREQUIRES( partialAuthOK == TRUE || partialAuthOK == FALSE );\n\n\t/* Deal with SSH's braindamaged ability to report a totally ambiguous \n\t   failure that could be any of \"invalid password\", \"invalid public \n\t   key\", \"valid password but public key required as well\", \"valid \n\t   public key but password required as well\", \"valid password but \n\t   further password required\", and so on */\n\tif( requiredAuthAlgo == CRYPT_PSEUDOALGO_AMBIGUOUS )\n\t\t{\n\t\tif( isSigAlgo( providedAuthAlgo ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t\t  \"Authenticated with public/private key, server \"\n\t\t\t\t\t  \"reports that further public/private key and/or \"\n\t\t\t\t\t  \"password authentication is required\" ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t\t  \"Authenticated with password, server reports that \"\n\t\t\t\t\t  \"further password and/or public/private key \"\n\t\t\t\t\t  \"authentication is required\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If the initial part of the authentication succeeded, report what\n\t   succeeded and what's needed to continue */\n\tif( partialAuthOK )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t  \"Authenticated with %s, server reports that further %s \"\n\t\t\t\t  \"authentication is required\", \n\t\t\t\t  isSigAlgo( providedAuthAlgo ) ? \"public/private key\" : \\\n\t\t\t\t\t\t\t\t\t\t\t\t  \"password\",\n\t\t\t\t  needsPW ? \"password\" : \"public/private key\" ) );\n\t\t\t}\n\n\t/* Break down the authentication response as per the table above to try \n\t   and return some sort of useful information to the caller */\n\tif( isSigAlgo( providedAuthAlgo ) )\n\t\t{\n\t\tif( needsPW )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t\t  \"Server requested password authentication but only a \"\n\t\t\t\t\t  \"public/private key was available\" ) );\n\t\t\t}\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"Server reported: Invalid public-key authentication\" ) );\n\t\t}\n\tif( isSigAlgo( requiredAuthAlgo ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t  \"Server requested public-key authentication but only a \"\n\t\t\t\t  \"password was available\" ) );\n\t\t}\n\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t  \"Server reported: Invalid password\" ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processAuthFailure( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int length,\n\t\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE providedAuthAlgo,\n\t\t\t\t\t\t\t   const BOOLEAN partialAuthOK )\n\t{\n\tCRYPT_ALGO_TYPE requiredAuthAlgo;\n\tBOOLEAN needFurtherAuth = FALSE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( isEnumRange( providedAuthAlgo, CRYPT_ALGO ) );\n\tREQUIRES( partialAuthOK == TRUE || partialAuthOK == FALSE );\n\n\tstatus = readAuthFailureInfo( sessionInfoPtr, length, &requiredAuthAlgo, \n\t\t\t\t\t\t\t\t  &needFurtherAuth, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( ( status == OK_SPECIAL ) ? CRYPT_ERROR_WRONGKEY : status );\n\treturn( reportAuthFailure( sessionInfoPtr, providedAuthAlgo, \n\t\t\t\t\t\t\t   requiredAuthAlgo, partialAuthOK ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSend/Receive Authentication Messages\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send an authentication request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int sendAuthRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tINOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\tconst ATTRIBUTE_LIST *userNamePtr,\n\t\t\t\t\t\t\tconst BOOLEAN preferPublickeyAuth )\n\t{\n\tconst ATTRIBUTE_LIST *passwordPtr = \\\n\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tconst BOOLEAN usePasswordAuth = \\\n\t\t\t( passwordPtr != NULL && !preferPublickeyAuth ) ? TRUE : FALSE;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtr( userNamePtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( preferPublickeyAuth == TRUE || preferPublickeyAuth == FALSE );\n\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( usePasswordAuth )\n\t\t{\n\t\t/*\tbyte\ttype = SSH_MSG_USERAUTH_REQUEST\n\t\t\tstring\tuser_name\n\t\t\tstring\tservice_name = \"ssh-connection\"\n\t\t\tstring\tmethod-name = \"password\"\n\t\t\tboolean\tFALSE\n\t\t\tstring\tpassword */\n\t\twriteString32( &stream, userNamePtr->value, \n\t\t\t\t\t   userNamePtr->valueLength );\n\t\twriteString32( &stream, \"ssh-connection\", 14 );\n\t\twriteString32( &stream, \"password\", 8 );\n\t\tsputc( &stream, 0 );\n\t\tstatus = writeString32( &stream, passwordPtr->value,\n\t\t\t\t\t\t\t\tpasswordPtr->valueLength );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = createPubkeyAuth( sessionInfoPtr, handshakeInfo, &stream, \n\t\t\t\t\t\t\t\t   userNamePtr );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Send the authentication information to the server.  If we're sending \n\t   a password, we enable the use of quantised padding, which also means \n\t   that we have to use distinct wrap + send calls */\n\tif( usePasswordAuth )\n\t\t{\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, 0, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\t\t}\n\telse\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\t\n\treturn( status );\n\t}\n\n/* Read the authentication response from the server */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readAuthResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t OUT_RANGE( 0, SSH_MSG_SPECIAL_LAST ) int *type,\n\t\t\t\t\t\t\t OUT_LENGTH_Z int *packetLength,\n\t\t\t\t\t\t\t const BOOLEAN isPAMAuth )\n\t{\n\tSTREAM stream;\n\tconst int authType = isPAMAuth ? SSH_MSG_SPECIAL_USERAUTH_PAM : \\\n\t\t\t\t\t\t\t\t\t SSH_MSG_SPECIAL_USERAUTH;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( type, sizeof( int ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\n\tREQUIRES( isPAMAuth == TRUE || isPAMAuth == FALSE );\n\n\t/* Clear return values */\n\t*type = 0;\n\t*packetLength = 0;\n\n\t/* Read the server's response to the authentication request */\n\tstatus = length = readAuthPacketSSH2( sessionInfoPtr, authType, ID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the server sent extension information, process it and then retry \n\t   the server response read */\n\tif( sessionInfoPtr->sessionSSH->packetType == SSH_MSG_EXT_INFO )\n\t\t{\n\t\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\t\tstatus = readExtensionsSSH( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Retry the authentication response read */\n\t\tstatus = length = readAuthPacketSSH2( sessionInfoPtr, authType, \n\t\t\t\t\t\t\t\t\t\t\t  ID_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\t*packetLength = length;\n\t*type = sessionInfoPtr->sessionSSH->packetType;\n\tif( sessionInfoPtr->sessionSSH->packetType == SSH_MSG_USERAUTH_SUCCESS )\n\t\t{\n\t\t/* We've successfully authenticated ourselves and we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The authentication failed, let the caller know that they need to \n\t   process further auth-failure information */\n\treturn( OK_SPECIAL );\n\t}\n\n/* Send a dummy authentication request, needed under various circumstances \n   for some buggy servers */\n\nCHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sendDummyAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_BUFFER( userNameLength ) const char *userName,\n\t\t\t\t\t\t  IN_LENGTH_TEXT const int userNameLength )\n\t{\n\tSTREAM stream;\n\tint type, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( userName, userNameLength ) );\n\n\tREQUIRES( userNameLength > 0 && userNameLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Send the dummy authentication request to the server */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteString32( &stream, userName, userNameLength );\n\twriteString32( &stream, \"ssh-connection\", 14 );\n\tstatus = writeString32( &stream, \"none\", 4 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Wait for the server's ack of the authentication.  In theory since \n\t   this is just something used to de-confuse the buggy servers we can \n\t   ignore the content (as long as the packet is valid) as any \n\t   authentication problems will be resolved by the real authentication \n\t   process below, but in some rare cases we can encounter oddball \n\t   devices that don't perform any authentication at the SSH level but \n\t   instead ask for a password via the protocol being tunneled over SSH, \n\t   which means that we'll get a USERAUTH_SUCCESS at this point even if \n\t   we haven't actually authenticated ourselves */\n\tstatus = readAuthResponse( sessionInfoPtr, &type, &length, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* We've successfully (non-)authenticated ourselves and we're done */\n\t\treturn( OK_SPECIAL );\n\t\t}\n\telse\n\t\t{\n\t\t/* There was an error authenticating, exit */\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\t}\n\n\t/* The authentication failed, in this case since what we've sent is a \n\t   dummy auth to de-confuse buggy servers we expect it to fail, in which\n\t   case we return CRYPT_OK to tell the caller that they can continue with\n\t   the actual authentication */\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tPerform PAM Authentication\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a single round of PAM authentication */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int pamAuthenticate( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_BUFFER( pamRequestDataLength ) \\\n\t\t\t\t\t\t\t\tconst void *pamRequestData, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int pamRequestDataLength )\n\t{\n\tconst ATTRIBUTE_LIST *passwordPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\tSTREAM stream;\n\tBYTE nameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBYTE promptBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint nameLength, promptLength = -1, noPrompts = -1;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( pamRequestData, pamRequestDataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( pamRequestDataLength ) );\n\n\t/* Process the PAM user-auth request:\n\n\t\tbyte\ttype = SSH_MSG_USERAUTH_INFO_REQUEST\n\t\tstring\tname\n\t\tstring\tinstruction\n\t\tstring\tlanguage = {}\n\t\tint\t\tnum_prompts\n\t\t\tstring\tprompt[ n ]\n\t\t\tboolean\techo[ n ]\n\n\t   Exactly who or what's name is supplied or what the instruction field \n\t   is for is left unspecified by the spec (and they may indeed be left \n\t   empty) so we just skip it.  Many implementations feel similarly about \n\t   this and leave the fields empty.  In addition the spec allows \n\t   num_prompts to be zero in one location (stating that the usually-\n\t   absent name and instruction field should be displayed to the user) \n\t   but then prohibits the prompt from being empty in another location, \n\t   so we require a nonzero number of prompts.\n\n\t   If the PAM authentication (from a previous iteration) fails or \n\t   succeeds then the server is supposed to send back a standard user-\n\t   auth success or failure status but could also send another\n\t   SSH_MSG_USERAUTH_INFO_REQUEST even if it contains no payload (an \n\t   OpenSSH bug) so we have to handle this as a special case */\n\tsMemConnect( &stream, pamRequestData, pamRequestDataLength );\n\tstatus = readString32Opt( &stream, nameBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t  &nameLength );\t/* Name */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\treadUniversal32( &stream );\t\t\t\t/* Instruction */\n\t\treadUniversal32( &stream );\t\t\t\t/* Language */\n\t\tstatus = noPrompts = readUint32( &stream );\t/* No.prompts */\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\tstatus = CRYPT_OK;\t/* readUint32() returns a count value */\n\t\t\tif( noPrompts <= 0 || noPrompts > 4 )\n\t\t\t\t{\n\t\t\t\t/* Requesting zero or more than a small number of prompts is \n\t\t\t\t   suspicious */\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readString32( &stream, promptBuffer, \n\t\t\t\t\t\t\t   CRYPT_MAX_TEXTSIZE, &promptLength );\n\t\tif( cryptStatusOK( status ) && promptLength <= 0 )\n\t\t\t{\n\t\t\t/* We must have at least some sort of prompt given that we \n\t\t\t   require num_prompts to be nonzero */\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid PAM authentication request packet\" ) );\n\t\t}\n\tREQUIRES( nameLength >= 0 && nameLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( promptLength >= 1 && promptLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Make sure that we're being asked for some form of password \n\t   authentication.  This assumes that the prompt string begins with the \n\t   word \"password\" (which always seems to be the case), if it isn't then \n\t   it may be necessary to do a substring search */\n\tif( promptLength < 8 || \\\n\t\t!strIsPrintable( promptBuffer, promptLength ) || \\\n\t\tstrCompare( promptBuffer, \"Password\", 8 ) )\n\t\t{\n\t\t/* The following may produce somewhat inconsistent results in terms\n\t\t   of what it reports because it's unclear what 'name' actually is, \n\t\t   on the off chance that something fills this in it could produce\n\t\t   a less appropriate error message than the prompt, but we \n\t\t   opportunistically try it in case it contains something useful */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Server requested unknown PAM authentication type '%s'\", \n\t\t\t\t  ( nameLength > 0 ) ? \\\n\t\t\t\t  sanitiseString( nameBuffer, CRYPT_MAX_TEXTSIZE, \\\n\t\t\t\t\t\t\t\t  nameLength ) : \\\n\t\t\t\t  sanitiseString( promptBuffer, CRYPT_MAX_TEXTSIZE, \\\n\t\t\t\t\t\t\t\t  promptLength ) ) );\n\t\t}\n\n\tREQUIRES( passwordPtr != NULL && \\\n\t\t\t  passwordPtr->valueLength > 0 && \\\n\t\t\t  passwordPtr->valueLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Send back the PAM user-auth response:\n\n\t\tbyte\ttype = SSH_MSG_USERAUTH_INFO_RESPONSE\n\t\tint\t\tnum_responses = num_prompts\n\t\t\tstring\tresponse[ n ]\n\n\t   What to do if there's more than one prompt is a bit tricky, usually \n\t   PAM is used as a form of (awkward) password authentication and \n\t   there's only a single prompt, if we ever encounter a situation where \n\t   there's more than one prompt then it's probably a request to confirm \n\t   the password so we just send it again for successive prompts */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_INFO_RESPONSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = writeUint32( &stream, noPrompts );\n\tLOOP_MED( i = 0, cryptStatusOK( status ) && i < noPrompts, i++ )\n\t\t{\n\t\tstatus = writeString32( &stream, passwordPtr->value,\n\t\t\t\t\t\t\t\tpasswordPtr->valueLength );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Handle PAM authentication */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processPamAuthentication( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tSTREAM stream;\n\tint length, pamIteration, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( userNamePtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( userNamePtr != NULL && \\\n\t\t\t  userNamePtr->valueLength > 0 && \\\n\t\t\t  userNamePtr->valueLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Send a user-auth request asking for PAM authentication:\n\n\t\tbyte\ttype = SSH_MSG_USERAUTH_REQUEST\n\t\tstring\tuser_name\n\t\tstring\tservice_name = \"ssh-connection\"\n\t\tstring\tmethod_name = \"keyboard-interactive\"\n\t\tstring\tlanguage = \"\"\n\t\tstring\tsub_methods = \"password\"\n\n\t   The sub-methods are implementation-dependent and the spec suggests an\n\t   implementation strategy in which the server ignores them so\n\t   specifying anything here is mostly wishful thinking, but we ask for\n\t   password authentication anyway in case it helps */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteString32( &stream, userNamePtr->value, userNamePtr->valueLength );\n\twriteString32( &stream, \"ssh-connection\", 14 );\n\twriteString32( &stream, \"keyboard-interactive\", 20 );\n\twriteUint32( &stream, 0 );\t\t/* No language tag */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_PAMPW ) )\n\t\t{\n\t\t/* Some servers choke if we supply a sub-method hint for the\n\t\t   authentication */\n\t\tstatus = writeUint32( &stream, 0 );\n\t\t}\n\telse\n\t\tstatus = writeString32( &stream, \"password\", 8 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Handle the PAM negotiation.  This can (in theory) go on indefinitely,\n\t   to avoid potential DoS problems we limit it to five iterations.  In\n\t   general we'll only need two iterations (or three for servers with the \n\t   empty-message bug) so we shouldn't ever get to five */\n\tLOOP_SMALL( pamIteration = 0, pamIteration < 5, pamIteration++ )\n\t\t{\n\t\tint type;\n\n\t\t/* Read back the response to our last message.  Although the spec\n\t\t   requires that the server not respond with a SSH_MSG_USERAUTH_-\n\t\t   FAILURE message if the request fails because of an invalid user\n\t\t   name (done for cargo-cult reasons to prevent an attacker from \n\t\t   being able to determine valid user names by checking for error \n\t\t   responses, although usability research on real-world users \n\t\t   indicates that this actually reduces security while having little\n\t\t   to no tangible benefit) some servers can return a failure \n\t\t   indication at this point so we have to allow for a failure \n\t\t   response as well as the expected SSH_MSG_USERAUTH_INFO_REQUEST */\n\t\tstatus = readAuthResponse( sessionInfoPtr, &type, &length, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* We've successfully authenticated ourselves and we're done */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* There was an error authenticating, exit */\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If the authentication failed provide more specific details to the \n\t\t   caller */\n\t\tif( type == SSH_MSG_USERAUTH_FAILURE )\n\t\t\t{\n\t\t\t/* If we failed on the first attempt (before we even tried to\n\t\t\t   send a password) it's probably because the user name is\n\t\t\t   invalid (or the server has the SSH_PFLAG_PAMPW bug).  Having\n\t\t\t   the server return a failure due to an invalid user name\n\t\t\t   shouldn't normally happen (see the comment above) but we \n\t\t\t   handle it just in case */\n\t\t\tif( pamIteration <= 0 )\n\t\t\t\t{\n\t\t\t\tchar userNameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\t\t\tREQUIRES( rangeCheck( userNamePtr->valueLength, 1, \n\t\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE ) );\n\t\t\t\tmemcpy( userNameBuffer, userNamePtr->value,\n\t\t\t\t\t\tuserNamePtr->valueLength );\n\t\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Server reported: Invalid user name '%s'\",\n\t\t\t\t\t\t  sanitiseString( userNameBuffer,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t      userNamePtr->valueLength ) ) );\n\t\t\t\t}\n\n\t\t\t/* It's a failure after we've tried to authenticate ourselves,\n\t\t\t   report the details to the caller */\n\t\t\treturn( processAuthFailure( sessionInfoPtr, length, \n\t\t\t\t\t\t\t\t\t\tCRYPT_PSEUDOALGO_PASSWORD, FALSE ) );\n\t\t\t}\n\t\tENSURES( type == SSH_MSG_USERAUTH_INFO_REQUEST )\n\t\t\t\t /* Guaranteed by the packet read with type = \n\t\t\t\t    SSH_MSG_SPECIAL_USERAUTH_PAM */\n\n\t\t/* Perform the PAM authentication */\n\t\tstatus = pamAuthenticate( sessionInfoPtr, \n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t  \"Too many iterations of negotiation during PAM \"\n\t\t\t  \"authentication\" ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPerform Client-side Authentication\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Authenticate the client to the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processClientAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tCRYPT_ALGO_TYPE requiredAuthAlgo;\n\tconst ATTRIBUTE_LIST *userNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\tconst BOOLEAN hasPassword = \\\n\t\t\t\t( findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_PASSWORD ) != NULL ) ? \\\n\t\t\t\tTRUE : FALSE;\n\tBOOLEAN needFurtherAuth = FALSE;\n\tint type, length DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( userNamePtr != NULL );\n\n\t/* Some buggy servers require a dummy request for authentication methods \n\t   otherwise they'll reject any method other than 'password' as invalid \n\t   with the error \"Client requested non-existing method 'publickey'\".  \n\t   To work around this we submit a dummy authentication request using the \n\t   method 'none' */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t   SSH_PFLAG_DUMMYUSERAUTH ) )\n\t\t{\n\t\tstatus = sendDummyAuth( sessionInfoPtr, userNamePtr->value, \n\t\t\t\t\t\t\t\tuserNamePtr->valueLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* Under some special circumstances involving other server bugs \n\t\t\t   (see the comment in sendDummyAuth() for details) this dummy \n\t\t\t   authentication can get us in, in which case we're done */\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* The way in which we handle authentication here isn't totally\n\t   appropriate since we assume that the user knows the appropriate form\n\t   of authentication to use.  If they're ambiguous and supply both a\n\t   password and a private key and the server only accepts PKC-based\n\t   authentication then we'll always preferentially choose password-based\n\t   authentication.  The way around this is to send an authentication \n\t   request with a method-type of \"none\" to see what the server wants but \n\t   the only thing that cryptlib can do in this case (since it's non-\n\t   interactive during the handshake phase) is disconnect, tell the user \n\t   what went wrong, and try again.  The current mechanism does this \n\t   anyway so we don't gain much except extra RTT delays by adding this \n\t   question-and-answer facility */\n\tstatus = sendAuthRequest( sessionInfoPtr, handshakeInfo, userNamePtr, \n\t\t\t\t\t\t\t  FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAuthResponse( sessionInfoPtr, &type, &length, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* We've successfully authenticated ourselves and we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\telse\n\t\t{\n\t\t/* There was an error authenticating, exit */\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Read the details of the authentication failure.  We decode the \n\t   response to favour password- or PKC-based authentication depending \n\t   on whether the user specified a password or a PKC as their \n\t   authentication choice */\n\tstatus = readAuthFailureInfo( sessionInfoPtr, length, &requiredAuthAlgo, \n\t\t\t\t\t\t\t\t  &needFurtherAuth, hasPassword );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\n\t\t/* Some buggy implementations return an authentication failure as a \n\t\t   garbled attempt to tell us that no authentication is required, if \n\t\t   we encounter one of these (indicated by readAuthFailureInfo() \n\t\t   returning an OK_SPECIAL status) then we retry by sending a dummy \n\t\t   authentication request, which should get us in.\n\n\t\t   The handling of return codes at this point is somewhat different \n\t\t   from normal because we're already in a failure state so even a \n\t\t   successful return (indicating that the dummy-auth was successfully \n\t\t   sent) has to be converted into an overall failure status */\n\t\tstatus = sendDummyAuth( sessionInfoPtr, userNamePtr->value, \n\t\t\t\t\t\t\t\tuserNamePtr->valueLength );\n\t\tif( status == OK_SPECIAL )\n\t\t\t{\n\t\t\t/* If we got in with the dummy authenticate, we're done */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\treturn( cryptStatusOK( status ) ? CRYPT_ERROR_WRONGKEY : status );\n\t\t}\n\n\t/* If we tried straight password authentication and the server requested \n\t   keyboard-interactive (== misnamed PAM) authentication try again using \n\t   PAM authentication */\n\tif( hasPassword && requiredAuthAlgo == CRYPT_PSEUDOALGO_PAM )\n\t\treturn( processPamAuthentication( sessionInfoPtr ) );\n\n\t/* If this is a final authentication failure, we're done */\n\tif( !needFurtherAuth )\n\t\t{\n\t\treturn( reportAuthFailure( sessionInfoPtr, \n\t\t\t\t\t\t\t\t   hasPassword ? CRYPT_PSEUDOALGO_PASSWORD : \\\n\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\t   requiredAuthAlgo, FALSE ) );\n\t\t}\n\n\t/* The authentication didn't actually fail, it succeeded but more \n\t   authentication is required.  If we authenticated with a public key \n\t   (meaning no password was available, since we preferentially \n\t   authenticate with that), report the problem as public key used, other \n\t   auth required */\n\tif( !hasPassword )\n\t\t{\n\t\treturn( reportAuthFailure( sessionInfoPtr, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\t   requiredAuthAlgo, TRUE ) );\n\t\t}\n\n\t/* We authenticated with a password, if there's no public key available \n\t   or what's required isn't a public key, report the problem as password \n\t   used, something else required */\n\tif( sessionInfoPtr->privateKey == CRYPT_ERROR || \\\n\t\t!( isSigAlgo( requiredAuthAlgo ) || \\\n\t\t   requiredAuthAlgo == CRYPT_PSEUDOALGO_AMBIGUOUS ) )\n\t\t{\n\t\treturn( reportAuthFailure( sessionInfoPtr, CRYPT_PSEUDOALGO_PASSWORD,\n\t\t\t\t\t\t\t\t   requiredAuthAlgo, TRUE ) );\n\t\t}\n\n\t/* We authenticated with a password and additional authentication with a\n\t   public key is required, perform the additional authentication */\n\tstatus = sendAuthRequest( sessionInfoPtr, handshakeInfo, userNamePtr, \n\t\t\t\t\t\t\t  TRUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readAuthResponse( sessionInfoPtr, &type, &length, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* We've successfully authenticated ourselves and we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\telse\n\t\t{\n\t\t/* There was an error authenticating, exit */\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\t}\n\n\t/* The additional authentication failed, provide more specific details \n\t   for the caller */\n\treturn( processAuthFailure( sessionInfoPtr, length, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\tTRUE ) );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_auths.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\tcryptlib SSHv2 Server-side Authentication Management\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* SSH user authentication gets quite complicated because of the way that \n   the multi-pass process defined in the spec affects our handling of user \n   name and password information.  The SSH spec allows the client to perform \n   authentication in bits and pieces and change the details of what it sends \n   at each step (and use authentication methods that it specifically knows \n   the server can't handle and all manner of other craziness, see the \n   SimpleSSH draft for a long discussion of these problems).  This is \n   particularly nasty because of the large amount of leeway that it provides \n   for malicious clients to subvert the authentication process, for example \n   the client can supply a privileged user name the first time around and \n   then authenticate the second time round as an unprivileged user.  If the \n   calling application just checks the first user name that it finds it'll \n   then treat the client as being an authenticated privileged user (which\n   indeed some server applications have done in the past).\n   \n   To defend against this we record the user name the first time that it's \n   entered and from then on require that the client supply the same name on \n   subsequent authentication attempts.  This is the standard client \n   behaviour anyway, if the user name + password are rejected then the \n   assumption is that the password is wrong and the user gets to retry the \n   password.  In order to accommodate public-key authentication we also \n   verify that the authentication method remains constant over successive \n   iterations, i.e. that the client doesn't try part of an authentication \n   with a public key and then another part with a password.\n\n   Handling the state machine required to process this gets a bit \n   complicated, the protocol flow that we enforce is:\n\n\tStep 0 (optional):\n\n\t\tClient sends SSH_MSG_USERAUTH_REQUEST with method \"none\" to query \n\t\tavailable authentication method types.\n\n\t\tServer responds with SSH_MSG_USERAUTH_FAILURE listing available \n\t\tmethods.\n\n\tStep 0a (optional):\n\n\t\tClient sends SSH_MSG_USERAUTH_REQUEST with only a public key, no\n\t\tsignature.\n\n\t\tServer responds with SSH_MSG_USERAUTH_PK_OK.\n\n\tStep 1:\n\n\t\tClient sends SSH_MSG_USERAUTH_REQUEST with method \"password\" or \n\t\t\"publickey\" and password data or a digital signature as appropriate.\n\n\tStep 2, one of:\n\n\t\ta. Server responds with SSH_MSG_USERAUTH_SUCCESS and the \n\t\tauthentication exchange terminates.\n\n\t\tb. Server responds to method \"password\" with \n\t\tSSH_MSG_USERAUTH_FAILURE, the client may retry step 1 if permitted \n\t\tby the server as described in the SSH specification.\n\n\t\tc. Server responds to method \"publickey\" with \n\t\tSSH_MSG_USERAUTH_FAILURE and the authentication exchange terminates.\n\n   This is a simplified form of what's given in the SSH spec, which allows\n   almost any jumble of messages including ones that don't make any sense \n   (again, see the SimpleSSH draft for more details).  The credential-type \n   matching that we perform in processUserAuth() is indicated by the caller \n   supplying one of the following values:\n\n\tNONE: No existing user name or password to match against, store the \n\t\tclient's user name and password for the caller to check.\n\n\tUSERNAME: Existing user name present from a previous iteration of\n\t\tauthentication, match the client's user name to the existing one and \n\t\tstore the client's password for the caller to check.\n\n\tUSERNAME_PASSWORD: Caller-supplied credentials present, match the\n\t\tclient's credentials against them */\n\ntypedef enum {\n\tCREDENTIAL_NONE,\t/* No credential information type */\n\tCREDENTIAL_USERNAME,/* User name is present and must match */\n\tCREDENTIAL_USERNAME_PASSWORD,/* User/password present and must match */\n\tCREDENTIAL_USERNAME_PUBKEY,/* User/pubkey present and must match */\n\tCREDENTIAL_LAST\t\t/* Last possible credential information type */\n\t} CREDENTIAL_TYPE;\n\n/* The processUserAuth() function has multiple possible return values, \n   broken down into CRYPT_OK for a password match, OK_SPECIAL for something \n   that the caller has to handle, and the standard error status, with \n   subvalues given in the userAuthInfo variable.  The different types and\n   subtypes are:\n\n\tCRYPT_OK + uAI = USERAUTH_SUCCESS: User credentials present and matched.  \n\t\tNote that the caller has to check both of these values, one a return \n\t\tstatus and the other a by-reference parameter, to avoid a single \n\t\tpoint of failure for the authentication.\n\n\tOK_SPECIAL + uAI = USERAUTH_CALLERCHECK: User credentials not present, \n\t\tadded to the session attributes for the caller to check.\n\n\tOK_SPECIAL + uAI = USERAUTH_NOOP: No-op read for a client query of \n\t\tavailable authentication methods via the pseudo-method \"none\".\n\n\tOK_SPECIAL + uAI = USERAUTH_NOOP_2: Additional no-op read for a client \n\t\tpartial pubkey auth without a signature, requiring another round\n\t\tof messages to get a pubkey auth with a signature.\n\n\tError + uAI = USERAUTH_ERROR: Standard error status, which includes non-\n\t\tmatched credentials */\n\ntypedef enum {\n\tUSERAUTH_NONE,\t\t/* No authentication type */\n\tUSERAUTH_SUCCESS,\t/* User authenticated successfully */\n\tUSERAUTH_CALLERCHECK,/* Caller must check whether auth.was successful */\n\tUSERAUTH_NOOP,\t\t/* No-op read */\n\tUSERAUTH_NOOP_2,\t/* Pubkey auth no-op */\n\tUSERAUTH_ERROR,\t\t/* User failed authentication */\n\tUSERAUTH_LAST\t\t/* Last possible authentication type */\n\t} USERAUTH_TYPE;\n\n/* The match options with a caller-supplied list of credentials to match \n   against are (this doesn't apply to public-key auth because that's always\n   implicitly present via the public-key database):\n\n\tClient sends | Cred.type\t| Action\t\t\t\t\t| Result\n\t-------------+--------------+---------------------------+--------------\n\tName, pw\t | USERNAME_PW\t| Match name, password\t\t| SUCCESS/ERROR\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| NOOP\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| ERROR (fatal)\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| NOOP\n\tName, pw\t | USERNAME_PW\t| Match name, password\t\t| SUCCESS/ERROR\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| NOOP\n\tName2, pw\t | USERNAME_PW\t| Match name2 -> Fail\t\t| ERROR (fatal)\n\t-------------+--------------+---------------------------+--------------\n\tName, wrongPW| USERNAME_PW\t| Match name, wrongPW\t\t|\n\t\t\t\t |\t\t\t\t|\t-> Fail\t\t\t\t\t| ERROR\n\tName, pw\t | USERNAME_PW\t| Match name, password\t\t| SUCCESS/ERROR\n\n  If an error status is returned then any value other than \n  CRYPT_ERROR_WRONGKEY is treated as a fatal error.  CRYPT_ERROR_WRONGKEY\n  is nonfatal as determined by the caller, for example until some predefined\n  retry count has been exceeded.\n\n  Handling of the third case (two different user names supplied in different\n  messages) gets a bit tricky because if both names are present in the list\n  of credentials then we'll get a successful match both times even though a \n  different user name was used.  To detect this we record the initial user \n  name in the SSH session information and check it against subsequently \n  supplied values.\n\n  The match options with no caller-supplied list of credentials to match \n  against are:\n\n\tClient sends | Cred.type\t| Action\t\t\t\t\t| Result\n\t-------------+--------------+---------------------------+--------------\n\tName, pw\t | NONE\t\t\t| Add name, password\t\t| CALLERCHECK\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| NOOP\n\tName, none\t | USERNAME_PW\t| Match name\t\t\t\t| ERROR (fatal)\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | NONE\t\t\t| Add name\t\t\t\t\t| NOOP\n\tName, pw\t | USERNAME\t\t| Match name, add password\t| CALLERCHECK\n\t-------------+--------------+---------------------------+--------------\n\tName, none\t | NONE\t\t\t| Add name\t\t\t\t\t| NOOP\n\tName2, pw\t | USERNAME\t\t| Match name2 -> Fail\t\t| ERROR (fatal)\n\t-------------+--------------+---------------------------+--------------\n\tName, wrongPW| NONE\t\t\t| Add name, wrongPW\t\t\t| CALLERCHECK\n\tName, pw\t | USERNAME\t\t| Match name, add password\t| CALLERCHECK\n\t-------------+--------------+---------------------------+--------------\n\tName, pkauth | NONE\t\t\t| Add name\t\t\t\t\t| SUCCESS/ERROR\n\t\t\t\t |\t\t\t\t| Check pkauth\t\t\t\t|\n\t-------------+--------------+---------------------------+--------------\n\tName, pubkey | NONE\t\t\t| Add name\t\t\t\t\t| NOOP_2\n\tName, pkauth | USERNAME_PUBK| Match name\t\t\t\t| SUCCESS/ERROR\n\t\t\t\t |\t\t\t\t| Check pkauth\t\t\t\t|\n\t-------------+--------------+---------------------------+--------------\n\tName, pubkey | NONE\t\t\t| Add name\t\t\t\t\t| NOOP_2\n\tName, pubkey | USERNAME_PUBK| Match name\t\t\t\t| ERROR (fatal)\n\t-------------+--------------+---------------------------+-------------- */\n\n/* A lookup table for the authentication methods submitted by the client */\n\ntypedef enum {\n\tMETHOD_NONE,\t\t/* No authentication method type */\n\tMETHOD_QUERY,\t\t/* Query available authentication methods */\n\tMETHOD_PASSWORD,\t/* Password authentication */\n\tMETHOD_PUBKEY,\t\t/* Pubkey authentication */\n\tMETHOD_LAST\t\t\t/* Last possible authentication method type */\n\t} METHOD_TYPE;\n\ntypedef struct {\n\tBUFFER_FIXED( nameLength ) \\\n\tconst char *name;\t\t\t/* Method name */\n\tconst int nameLength;\n\tconst METHOD_TYPE type;\t\t/* Method type */\n\t} METHOD_INFO;\n\nstatic const METHOD_INFO methodInfoTbl[] = {\n\t{ \"none\", 4, METHOD_QUERY },\n\t{ \"password\", 8, METHOD_PASSWORD },\n\t{ NULL, 0, METHOD_NONE }, { NULL, 0, METHOD_NONE }\n\t};\nstatic const METHOD_INFO methodInfoTblPubkeyAuth[] = {\n\t{ \"none\", 4, METHOD_QUERY },\n\t{ \"password\", 8, METHOD_PASSWORD },\n\t{ \"publickey\", 9, METHOD_PUBKEY },\n\t{ NULL, 0, METHOD_NONE }, { NULL, 0, METHOD_NONE }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a succeeded/failed-authentication response to the client:\n\n\tbyte\ttype = SSH_MSG_USERAUTH_SUCCESS\n\n   or\n\n\tbyte\ttype = SSH_MSG_USERAUTH_FAILURE\n\tstring\tallowed_authent = empty\n\tboolean\tpartial_success = FALSE \n\n   or\n\n\tbyte\ttype = SSH_MSG_USERAUTH_FAILURE\n\tstring\tallowed_authent = \"publickey\" / \"password\"\n\tboolean\tpartial_success = FALSE\n\n   The latter two variants are necessary because the failure response is\n   overloaded to perform two functions, firstly to indicate that the \n   authentication failed and secondly to provide a list of methods that can\n   be used to authenticate (see the comment at the start of this module for\n   the calisthentics that are required to support this) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendResponseSuccess( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_SUCCESS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendResponseFailure( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Straight failure response */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_FAILURE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteUint32( &stream, 0 );\n\tstatus = sputc( &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendResponseFailureInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN allowPubkeyAuth )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( allowPubkeyAuth == TRUE || allowPubkeyAuth == FALSE );\n\n\t/* Failure response but really a means of telling the client how they \n\t   can authenticate.  What to send as the allowed method is a bit \n\t   tricky, if the caller tells us that publickey auth is allowed then \n\t   we can always send that, but it's not clear whether we can say that\n\t   password auth is OK or not.  In theory we could check whether a \n\t   password is present in the attribute list, but the caller could be \n\t   performing on-demand checking without explicitly setting a password \n\t   attribute, so there's no way to tell whether passwords should be \n\t   allowed or not.  Because of this we always advertise password auth as \n\t   being available */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_FAILURE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( allowPubkeyAuth )\n\t\twriteString32( &stream, \"publickey,password\", 18 );\n\telse\n\t\twriteString32( &stream, \"password\", 8 );\n\tstatus = sputc( &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/* Check that the query form and credentials submitted by the client are \n   consistent with any information submitted during earlier rounds of \n   authentication */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int checkQueryValidity( INOUT SSH_INFO *sshInfo,\n\t\t\t\t\t\t\t   IN_BUFFER( userNameLength ) const void *userName,\n\t\t\t\t\t\t\t   IN_LENGTH_TEXT const int userNameLength,\n\t\t\t\t\t\t\t   IN_ENUM( METHOD ) const METHOD_TYPE authMethod,\n\t\t\t\t\t\t\t   const BOOLEAN isInitialAuth )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tBYTE userNameHash[ KEYID_SIZE + 8 ];\n\n\tassert( isWritePtr( sshInfo, sizeof( SSH_INFO ) ) );\n\tassert( isReadPtrDynamic( userName, userNameLength ) );\n\n\tREQUIRES( userNameLength >= 1 && userNameLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( isEnumRange( authMethod, METHOD ) );\n\tREQUIRES( isInitialAuth == TRUE || isInitialAuth == FALSE );\n\n\t/* Hash the user name so that we only need to store the fixed-length \n\t   hash rather than the variable-length user name */\n\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, NULL );\n\thashFunctionAtomic( userNameHash, KEYID_SIZE, userName, userNameLength );\n\n\t/* If this is the first message remember the user name and \n\t   authentication method in case we need to check it on a subsequent \n\t   round of authentication */\n\tif( isInitialAuth )\n\t\t{\n\t\tmemcpy( sshInfo->authUserNameHash, userNameHash, KEYID_SIZE );\n\t\tsshInfo->authType = authMethod;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If the client is switching credentials across authentication messages \n\t   then there's something fishy going on */\n\tif( !compareDataConstTime( sshInfo->authUserNameHash, userNameHash, \n\t\t\t\t\t\t\t   KEYID_SIZE ) )\n\t\treturn( CRYPT_ERROR_INVALID );\n\n\t/* Make sure that the authentication messages follow the state \n\t   transitions:\n\n\t\t<empty> -> query -> auth_method\n\t\t<empty> ----------> auth_method\n\n\t   There are two error cases that can occur here, either the client \n\t   sends multiple authentication requests with the pseudo-method \"none\"\n\t   (SSH's way of performing a method query) or they send a request with\n\t   a different method than a previous one, for example \"password\" in the\n\t   initial request and then \"publickey\" in a following one */\n\tif( sshInfo->authType == METHOD_QUERY )\n\t\t{\n\t\t/* If we've already processed a query message then any subsequent \n\t\t   message has to be an actual authentication message */\n\t\tif( authMethod == METHOD_QUERY )\n\t\t\treturn( CRYPT_ERROR_DUPLICATE );\n\n\t\t/* We've had a query followed by a standard authentication method, \n\t\t   remember the authentication method for later */\n\t\tsshInfo->authType = authMethod;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we've already seen a standard authentication method then the new \n\t   method must be the same */\n\tif( sshInfo->authType != authMethod )\n\t\treturn( CRYPT_ERROR_INVALID );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the public key value that'll be used for pubkey authentication and \n   verify the authentication data created with it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readPublicKey( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tCRYPT_ALGO_TYPE pubkeyAlgo;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tvoid *keyPtr DUMMY_INIT_PTR;\n\tint keyLength, dummy, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Skip the first of the three copies of the algorithm name (see the \n\t   comment in ssh2_cli.c for more on this).  We don't do anything with \n\t   it because we're about to get two more copies of the same thing, and \n\t   the key and signature information take precedence over anything that \n\t   we find here */\n\tstatus = readUniversal32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t\n\t/* Read the client's public key */\t\n\tstreamBookmarkSet( stream, keyLength );\n\tstatus = checkReadPublicKey( stream, &pubkeyAlgo, &dummy, \n\t\t\t\t\t\t\t\t SESSION_ERRINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( stream, &keyPtr, &keyLength, \n\t\t\t\t\t\t\t\t\t\t keyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid client pubkey data\" ) );\n\t\t}\n\n\t/* Import the public-key data into a context */\n\tsetMessageCreateObjectInfo( &createInfo, pubkeyAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, keyPtr, keyLength );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tretExt( cryptArgError( status ) ? \\\n\t\t\t\tCRYPT_ERROR_BADDATA : status,\n\t\t\t\t( cryptArgError( status ) ? \\\n\t\t\t\t  CRYPT_ERROR_BADDATA : status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid client pubkey value\" ) );\n\t\t}\n\tsessionInfoPtr->iKeyexAuthContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int checkPublicKeySig( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  const SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_BUFFER( userNameLength ) const void *userName, \n\t\t\t\t\t\t\t  IN_LENGTH_TEXT const int userNameLength )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_KEYMGMT_INFO getkeyInfo DUMMY_INIT_STRUCT;\n\tMESSAGE_DATA msgData;\n\tBYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBYTE holderName[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tvoid *packetDataPtr DUMMY_INIT_PTR, *sigDataPtr;\n\tint packetDataLength, sigDataLength, holderNameLen, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( userName, userNameLength ) );\n\n\tREQUIRES( userNameLength > 0 && userNameLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Make sure that this key is valid for authentication purposes, in \n\t   other words that it's present in the authentication keyset.\n\t   \n\t   Note that this uses a not-entirely-reliable means of identifying the\n\t   key in the database in that CRYPT_IKEYID_KEYID is the \n\t   subjectKeyIdentifier of the certificate if this is present, otherwise\n\t   a hash of the subjectPublicKey.  If the sKID is in a cryptlib-created \n\t   certificate then the two are the same thing, but a certificate coming\n\t   from an external CA may contain arbitrary data for the sKID.  \n\t   However, since it's unlikely that someone is performing SSH client \n\t   auth using a certificate from a commercial CA, it seems safe to \n\t   assume that any certificate present will be a cryptlib-generated one \n\t   used as a bit-bagging mechanism to get the key into a database, and\n\t   therefore that sKID == hash( subjectPublicKey ) */\n\tsetMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEYID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID, \n\t\t\t\t\t\t\t   msgData.data, msgData.length, NULL, 0, \n\t\t\t\t\t\t\t   KEYMGMT_FLAG_NONE );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset, \n\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n#ifdef USE_ERRMSGS\n\t\tchar keyIDText[ CRYPT_MAX_TEXTSIZE + 8 ];\n#endif /* USE_ERRMSGS */\n\n\t\tformatFingerprint( keyIDText, CRYPT_MAX_TEXTSIZE, keyID, \n\t\t\t\t\t\t   msgData.length );\n\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t  \"Client public key with ID '%s' is not trusted for \"\n\t\t\t\t  \"authentication purposes\", keyIDText ) );\n\t\t}\n\n\t/* Check that the name in the certificate matches the supplied user \n\t   name */\n\tsetMessageData( &msgData, holderName, CRYPT_MAX_TEXTSIZE );\n\tstatus = krnlSendMessage( getkeyInfo.cryptHandle, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_HOLDERNAME );\n\tkrnlSendNotifier( getkeyInfo.cryptHandle, IMESSAGE_DESTROY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tholderNameLen = msgData.length;\n\t\tif( userNameLength != holderNameLen || \\\n\t\t\t!compareDataConstTime( userName, holderName, userNameLength ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\telse\n\t\t{\n\t\tmemcpy( holderName, \"<<<Unknown>>>\", 13 );\n\t\tholderNameLen = 13;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tBYTE userNameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\tREQUIRES( rangeCheck( userNameLength, 1, CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( userNameBuffer, userName, userNameLength );\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Client public key name '%s' doesn't match supplied user \"\n\t\t\t\t  \"name '%s'\", \n\t\t\t\t  sanitiseString( holderName, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  holderNameLen ),\n\t\t\t\t  sanitiseString( userNameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  userNameLength ) ) );\n\t\t}\n\n\t/* Get a pointer to the portion of the packet that gets signed */\n\tstatus = packetDataLength = stell( stream );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = sMemGetDataBlockAbs( stream, 0, &packetDataPtr, \n\t\t\t\t\t\t\t\t\t  packetDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Hash the authentication request data, composed of:\n\t\n\t\tstring\t\texchange hash\n\t\t[ SSH_MSG_USERAUTH_REQUEST packet payload up to signature start ] */\n\tsetMessageCreateObjectInfo( &createInfo, handshakeInfo->hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = hashAsString( createInfo.cryptHandle, \n\t\t\t\t\t\t   handshakeInfo->sessionID,\n\t\t\t\t\t\t   handshakeInfo->sessionIDlength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatic const BYTE packetID = SSH_MSG_USERAUTH_REQUEST;\n\n\t\t/* readAuthPacketSSH2() has stripped the ID byte from the start of \n\t\t   the packet so we need to hash it in explicitly before we hash the \n\t\t   rest of the packet */\n\t\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t ( MESSAGE_CAST ) &packetID, ID_SIZE );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  packetDataPtr, packetDataLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \"\", 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Check the signature.  The reason for the min() part of the expression \n\t   is that iCryptCheckSignature() gets suspicious of very large buffer \n\t   sizes, for example if the client were to specify the use of a huge \n\t   signature packet */\n\tstatus = sMemGetDataBlockRemaining( stream, &sigDataPtr, \n\t\t\t\t\t\t\t\t\t\t&sigDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = iCryptCheckSignature( sigDataPtr, sigDataLength, \n\t\t\t\t\t\t\t\t\t   CRYPT_IFORMAT_SSH, \n\t\t\t\t\t\t\t\t\t   sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t\t\t   createInfo.cryptHandle, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t   NULL );\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Verification of client's pubkey auth failed\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tVerify the Client's Authentication\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle client authentication */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processUserAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tconst SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\tOUT_ENUM( USERAUTH ) USERAUTH_TYPE *userAuthInfo,\n\t\t\t\t\t\t\tIN_ENUM_OPT( CREDENTIAL ) \\\n\t\t\t\t\t\t\t\tconst CREDENTIAL_TYPE credentialType,\n\t\t\t\t\t\t\tconst BOOLEAN initialAuth )\n\t{\n\tSTREAM stream;\n\tconst BOOLEAN allowPubkeyAuth = \\\n\t\t\t( sessionInfoPtr->cryptKeyset != CRYPT_ERROR ) ? TRUE : FALSE;\n\tconst METHOD_INFO *methodInfoTblPtr = allowPubkeyAuth ? \\\n\t\t\tmethodInfoTblPubkeyAuth : methodInfoTbl;\n\tconst int methodInfoTblSize = allowPubkeyAuth ? \\\n\t\t\tFAILSAFE_ARRAYSIZE( methodInfoTblPubkeyAuth, METHOD_INFO ) : \\\n\t\t\tFAILSAFE_ARRAYSIZE( methodInfoTbl, METHOD_INFO );\n\tconst ATTRIBUTE_LIST *attributeListPtr DUMMY_INIT_PTR;\n\tconst METHOD_INFO *methodInfoPtr = NULL;\n\tBYTE userNameBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBOOLEAN kludgeFlag = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, userNameLength, stringLength, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( userAuthInfo, sizeof( USERAUTH_TYPE * ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isEnumRangeOpt( credentialType, CREDENTIAL ) );\n\t\t\t  /* CREDENTIAL_NONE is a valid type since it indicates that we \n\t\t\t     should record the user name and password for the caller to\n\t\t\t\t check */\n\tREQUIRES( initialAuth == TRUE || initialAuth == FALSE );\n\n\t/* Clear the return value, or at least set it to the default failed-\n\t   authentication state */\n\t*userAuthInfo = USERAUTH_ERROR;\n\n\t/* Get the userAuth packet from the client:\n\n\t\tbyte\ttype = SSH_MSG_USERAUTH_REQUEST\n\t\tstring\tuser_name\n\t\tstring\tservice_name = \"ssh-connection\"\n\t\tstring\tmethod_name = \"none\" | \"password\" | \"publickey\"\n\t  \"password\":\n\t\tboolean\tFALSE/TRUE\n\t\tstring\tpassword\n\t  \"publickey\":\n\t\tboolean\tFALSE/TRUE\n\t\tstring\t\t\"ssh-rsa\"\t\"ssh-dss\"\t\"ecdsa-sha2-*\"\n\t\tstring\t\t[ client key/certificate ]\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\t\"ecdsa-sha2-*\"\n\t\t\tmpint\te\t\t\tp\t\t\tQ\n\t\t\tmpint\tn\t\t\tq\n\t\t\tmpint\t\t\t\tg\n\t\t\tmpint\t\t\t\ty\n\t  [\tstring\t\t[ client signature ]\t\t\t-- If boolean == TRUE\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\t\"ecdsa-sha2-*\"\n\t\t\tstring\tsignature ]\n\n\t    The client can optionally send a method-type of \"none\" as its first\n\t\tmessage to indicate that it'd like the server to return a list of \n\t\tallowed authentication types, if we get a packet of this kind and \n\t\tthe initialAuth flag is set then we return our allowed types list */\n\tstatus = length = \\\n\t\treadAuthPacketSSH2( sessionInfoPtr, SSH_MSG_USERAUTH_REQUEST,\n\t\t\t\t\t\t\tID_SIZE + sizeofString32( 1 ) + \\\n\t\t\t\t\t\t\t\tsizeofString32( 8 ) + sizeofString32( 4 ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tCFI_CHECK_UPDATE( \"readAuthPacketSSH2\" );\n\n\t/* Read the user name, service name, and authentication method type */\n\tstatus = readString32( &stream, userNameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t   &userNameLength );\n\tif( cryptStatusError( status ) || \\\n\t\tuserNameLength <= 0 || userNameLength > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid user-authentication user name\" ) );\n\t\t}\n\tstatus = readString32( &stream, stringBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t   &stringLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( stringLength != 14 || \\\n\t\t\tmemcmp( stringBuffer, \"ssh-connection\", 14 ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readString32( &stream, stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   &stringLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( stringLength <= 0 || stringLength > CRYPT_MAX_TEXTSIZE )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid user-authentication service or method name\" ) );\n\t\t}\n\tINJECT_FAULT( CORRUPT_ID, SESSION_CORRUPT_ID_SSH_1 );\n\tCFI_CHECK_UPDATE( \"checkAuthPacketSSH2\" );\n\n\t/* Check which authentication method the client has requested.  We \n\t   perform this and the following checks for credential/query validity \n\t   before any checking of the user name to make it harder for an \n\t   attacker to scan for valid accounts (but see also the comment about \n\t   this issue further on where the user-name check is performed) */\n\tLOOP_SMALL( i = 0, methodInfoTblPtr[ i ].type != METHOD_NONE && \\\n\t\t\t\t\t   i < methodInfoTblSize, i++ )\n\t\t{\n\t\tconst METHOD_INFO *methodInfo = &methodInfoTblPtr[ i ];\n\n\t\tif( methodInfo->nameLength == stringLength && \\\n\t\t\t!memcmp( methodInfo->name, stringBuffer, stringLength ) )\n\t\t\t{\n\t\t\tmethodInfoPtr = methodInfo;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < methodInfoTblSize );\n\tif( methodInfoPtr == NULL )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Unknown user-authentication method type '%s'\",\n\t\t\t\t  sanitiseString( stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  stringLength ) ) );\n\t\t}\n\n\t/* Check that the query submitted by the client is valid, meaning that \n\t   it doesn't appear to be an attempt to subvert the authentication \n\t   process in some way, e.g. by changing data during subsequent rounds\n\t   of the authentication negotiation */\n\tstatus = checkQueryValidity( sessionInfoPtr->sessionSSH, userNameBuffer, \n\t\t\t\t\t\t\t\t userNameLength, methodInfoPtr->type, \n\t\t\t\t\t\t\t\t initialAuth );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\n\t\t/* There are two slightly different error conditions that we can \n\t\t   encounter here, we provide distinct error messages to give the\n\t\t   caller more information on what went wrong */\n\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Client sent duplicate authentication requests with \"\n\t\t\t\t\t  \"method 'none'\" ) );\n\t\t\t}\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Client supplied different credentials than the ones \"\n\t\t\t\t  \"supplied during a previous authentication attempt\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkQueryValidity\" );\n\n\t/* Read the kludge flag used to denote all sorts of additional \n\t   functionality kludged onto the basic message.  In some cases the\n\t   kludgeFlag is set to TRUE (the password-auth message is actually a\n\t   change-password message), in others it's set to FALSE (the pubkey\n\t   auth message doesn't contain any pubkey auth) */\n\tif( methodInfoPtr->type != METHOD_QUERY )\n\t\t{\n\t\tint value;\n\n\t\tstatus = value = sgetc( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tkludgeFlag = value ? TRUE : FALSE;\n\t\t}\n\n\t/* Read the authentication information */\n\tswitch( methodInfoPtr->type )\n\t\t{\n\t\tcase METHOD_QUERY:\n\t\t\t/* No payload */\n\t\t\tbreak;\n\n\t\tcase METHOD_PASSWORD:\n\t\t\t/* Read the password and check that it's approximately valid */\n\t\t\tstatus = readString32( &stream, stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t   &stringLength );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tif( stringLength <= 0 || stringLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid password payload\" ) );\n\t\t\t\t}\n\t\t\tINJECT_FAULT( CORRUPT_AUTHENTICATOR, \n\t\t\t\t\t\t  SESSION_CORRUPT_AUTHENTICATOR_SSH_1 );\n\t\t\tbreak;\n\n\t\tcase METHOD_PUBKEY:\n\t\t\t/* Read the public key */\n\t\t\tstatus = readPublicKey( sessionInfoPtr, &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tCFI_CHECK_UPDATE( \"readAuthInfo\" );\n\n\t/* If the user credentials are pre-set make sure that the newly-\n\t   submitted user name matches an existing one.  Note that we've left \n\t   this check as late as possible (so that it's right next to the \n\t   password check) to avoid timing attacks that might help an attacker \n\t   guess a valid user name.  On the other hand given the typical pattern \n\t   of SSH password-guessing attacks which just run through a fixed set \n\t   of user names this probably isn't worth the trouble since it'll have \n\t   little to no effect on attackers, so what it's avoiding is purely a \n\t   certificational weakness.\n\n\t   There's also a slight anomaly in error reporting here, if the client\n\t   is performing a dummy read and there are pre-set user credentials\n\t   present then instead of the expected list of available authentication\n\t   methods they'll get an error response.  This is consistent with the\n\t   specification (which is ambiguous on the topic), it says that the \n\t   server must return a failure response and may also include a list of \n\t   allowed methods, but it may not be what the client is expecting.  \n\t   This problem occurs because of the overloading of the authentication\n\t   mechanism as a method-query mechanism, it's not clear whether the\n\t   query response or the username-check response is supposed to take\n\t   precedence */\n\tif( credentialType != CREDENTIAL_NONE )\n\t\t{\n\t\tattributeListPtr = \\\n\t\t\t\t\tfindSessionInfoEx( sessionInfoPtr, CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t   userNameBuffer, userNameLength );\n\t\tif( attributeListPtr == NULL )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\t( void ) sendResponseFailure( sessionInfoPtr );\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"Unknown/invalid user name '%s'\", \n\t\t\t\t\t  sanitiseString( userNameBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  userNameLength ) ) );\n\t\t\t}\n\n\t\t/* We've matched an existing user name, select the attribute that\n\t\t   contains it */\n\t\tDATAPTR_SET( sessionInfoPtr->attributeListCurrent,\n\t\t\t\t\t ( ATTRIBUTE_LIST * ) attributeListPtr );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a new user name, add it */\n\t\tstatus = addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t  userNameBuffer, userNameLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( &stream );\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Error recording user name '%s'\", \n\t\t\t\t\t  sanitiseString( userNameBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t  userNameLength ) ) );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"findSessionInfoEx\" );\n\n\t/* If the client just wants a list of supported authentication \n\t   mechanisms tell them what we allow (handled by sending a failed-\n\t   authentication response, which contains a list of mechanisms that can \n\t   be used to continue) and await further input */\n\tif( methodInfoPtr->type == METHOD_QUERY )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\n\t\t/* Tell the client which authentication methods can continue */\n\t\tstatus = sendResponseFailureInfo( sessionInfoPtr, allowPubkeyAuth );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"sendResponseFailureInfo\" );\n\n\t\t/* Inform the caller that this was a no-op pass and the client can \n\t\t   try again */\n\t\t*userAuthInfo = USERAUTH_NOOP;\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"readAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkQueryValidity\", \"readAuthInfo\", \n\t\t\t\t\t\t\t\t\t\t\"findSessionInfoEx\",\n\t\t\t\t\t\t\t\t\t\t\"sendResponseFailureInfo\" ) );\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tCFI_CHECK_UPDATE( \"METHOD_QUERY\" );\n\n\t/* If it's public-key auth, try and verify the signature */\n\tif( methodInfoPtr->type == METHOD_PUBKEY )\n\t\t{\n\t\t/* In yet another variant of SSH's Lucy-and-Charlie-Brown \n\t\t   authentication process, for pubkey auth the client can supply a \n\t\t   public key but omit the signature, in which case the server has \n\t\t   to go through yet another round of messages exchanged in the hope \n\t\t   of eventually getting the actual authentication data */\n\t\tif( !kludgeFlag )\n\t\t\t{\n\t\t\tint pkcAlgo;\n\n\t\t\t/* Repeated partial pubkey auth messages are a sign that \n\t\t\t   something is wrong */\n\t\t\tif( credentialType == CREDENTIAL_USERNAME_PUBKEY )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( &stream );\n\t\t\t\t( void ) sendResponseFailure( sessionInfoPtr );\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Client sent duplicate partial pubkey \"\n\t\t\t\t\t\t  \"authentication request\" ) );\n\t\t\t\t}\n\n\t\t\t/* If we're given a pubkey auth message with the signature \n\t\t\t   missing, we have to send back a copy of the public key \n\t\t\t   algorithm name and data, presumably to confirm that the three \n\t\t\t   copies the client sent us arrived in good order:\n\t\t\t   \n\t\t\t\tbyte\ttype = SSH_MSG_USERAUTH_PK_OK\n\t\t\t\tstring\tpubkey_algorithm_from_request\n\t\t\t\tstring\tpubkey_data_from_request\n\t\t\n\t\t\t   There's no obvious reason for this, and no implementation \n\t\t\t   that bothers with this additional unnecessary step appears to \n\t\t\t   check the returned data except for OpenSSH, and even that \n\t\t\t   only checks it as an implementation artefact.  What OpenSSH \n\t\t\t   does is throw every key it has available at the server until \n\t\t\t   it finds one that sticks, however it doesn't remember which \n\t\t\t   key was sent in which request but relies on the server's \n\t\t\t   response to tell it which one it was.  It's likely that this \n\t\t\t   message only exists as an OpenSSH quirk that got written into \n\t\t\t   the spec, and as implemented in OpenSSH it allows a server to \n\t\t\t   request auth from a key other than the one the client thinks \n\t\t\t   it's using by sending back an ACK for key B when the client \n\t\t\t   has proposed key A.\n\t\t\t   \n\t\t\t   Because only OpenSSH appears to bother checking this message, \n\t\t\t   we send back an easter egg for any other implementation to \n\t\t\t   catch anything that we're not currently aware of that does \n\t\t\t   actually check */\n\t\t\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  SSH_MSG_USERAUTH_PK_OK );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t   SSH_PFLAG_CHECKSPKOK ) )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgo, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = writeAlgoStringEx( &stream, pkcAlgo, \n\t\t\t\t\t\t\t\t\t\t\t\thandshakeInfo->hashAlgo, 0,\n\t\t\t\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_NONE );\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = exportAttributeToStream( &stream, \n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iKeyexAuthContext,\n\t\t\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SSH );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\twriteString32( &stream, \"Surprise! Does anything check this?\", \n\t\t\t\t\t\t\t   35 );\n\t\t\t\tstatus = writeString32( &stream, \"Blah, blah, blah, stolen \"\n\t\t\t\t\t\t\t\t\t\t\"plans, blah, blah, blah, missing \"\n\t\t\t\t\t\t\t\t\t\t\"scientist, blah, blah, blah, atom \"\n\t\t\t\t\t\t\t\t\t\t\"bomb, blah, blah, blah\", 114 );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tCFI_CHECK_UPDATE( \"wrapSendPacketSSH2\" );\n\n\t\t\t/* Since the client is going to send us yet another copy of the \n\t\t\t   key in the next iteration, we destroy the one that we've just \n\t\t\t   read so that we can re-read it again later */\n\t\t\tkrnlSendNotifier( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t  IMESSAGE_DESTROY );\n\t\t\tsessionInfoPtr->iKeyexAuthContext = CRYPT_ERROR;\n\n\t\t\t/* Inform the caller that this was yet another no-op pass and \n\t\t\t   the client can try again */\n\t\t\t*userAuthInfo = USERAUTH_NOOP_2;\n\n\t\t\tREQUIRES( CFI_CHECK_SEQUENCE_7( \"readAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\t\"checkQueryValidity\", \"readAuthInfo\", \n\t\t\t\t\t\t\t\t\t\t\t\"findSessionInfoEx\", \"METHOD_QUERY\",\n\t\t\t\t\t\t\t\t\t\t\t\"wrapSendPacketSSH2\" ) );\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\n\t\t/* Check the signature on the authentication data */\n\t\tstatus = checkPublicKeySig( sessionInfoPtr, handshakeInfo, &stream,\n\t\t\t\t\t\t\t\t\tuserNameBuffer, userNameLength );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) sendResponseFailure( sessionInfoPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\tCFI_CHECK_UPDATE( \"checkPublicKeySig\" );\n\n\t\t/* The user has successfully authenticated, let the client know and \n\t\t   indicate this through a failsafe two-value return status (see the \n\t\t   comment for processFixedAuth()/processServerAuth() for details) */\n\t\tstatus = sendResponseSuccess( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*userAuthInfo = USERAUTH_SUCCESS;\n\t\tCFI_CHECK_UPDATE( \"sendResponseSuccess\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"readAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkQueryValidity\", \"readAuthInfo\", \n\t\t\t\t\t\t\t\t\t\t\"findSessionInfoEx\", \"METHOD_QUERY\",\n\t\t\t\t\t\t\t\t\t\t\"checkPublicKeySig\", \n\t\t\t\t\t\t\t\t\t\t\"sendResponseSuccess\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tsMemDisconnect( &stream );\n\tCFI_CHECK_UPDATE( \"METHOD_PUBKEY\" );\n\n\tENSURES( methodInfoPtr->type == METHOD_PASSWORD );\n\n\t/* If the client started with a partial pubkey auth then they can't \n\t   continue with a password auth */\n\tif( credentialType == CREDENTIAL_USERNAME_PUBKEY )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\t( void ) sendResponseFailure( sessionInfoPtr );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Client started pubkey auth but tried to complete with \"\n\t\t\t\t  \"password auth\" ) );\n\t\t}\n\n\t/* If full user credentials are present then the user name has been \n\t   matched to a caller-supplied list of allowed { user name, password } \n\t   pairs and we move on to the corresponding password and verify it */\n\tif( credentialType == CREDENTIAL_USERNAME_PASSWORD )\n\t\t{\n\t\t/* Move on to the password associated with the user name */\n\t\tREQUIRES( DATAPTR_ISVALID( attributeListPtr->next ) );\n\t\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\t\tENSURES( attributeListPtr != NULL && \\\n\t\t\t\t attributeListPtr->attributeID == CRYPT_SESSINFO_PASSWORD );\n\t\t\t\t /* Ensured by checkMissingInfo() in sess_iattr.c */\n\n\t\t/* Make sure that the password matches.  Note that in the case of an\n\t\t   error we don't report the incorrect password that was entered \n\t\t   since we don't want it appearing in logfiles */\n\t\tif( stringLength != attributeListPtr->valueLength || \\\n\t\t\t!compareDataConstTime( stringBuffer, attributeListPtr->value, \n\t\t\t\t\t\t\t\t   stringLength ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid password for user '%s'\", \n\t\t\t\t\t  sanitiseString( userNameBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t  userNameLength ) ) );\n\t\t\t}\n\n\t\t/* The user has successfully authenticated, let the client know and \n\t\t   indicate this through a failsafe two-value return status (see the \n\t\t   comment for processFixedAuth()/processServerAuth() for details) */\n\t\tstatus = sendResponseSuccess( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*userAuthInfo = USERAUTH_SUCCESS;\n\t\tCFI_CHECK_UPDATE( \"sendResponseSuccess\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"readAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\t\"checkQueryValidity\", \"readAuthInfo\", \n\t\t\t\t\t\t\t\t\t\t\"findSessionInfoEx\", \"METHOD_QUERY\",\n\t\t\t\t\t\t\t\t\t\t\"METHOD_PUBKEY\", \"sendResponseSuccess\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"CREDENTIAL_USERNAME_PASSWORD\" );\n\n\tENSURES( credentialType == CREDENTIAL_NONE || \\\n\t\t\t credentialType == CREDENTIAL_USERNAME );\n\n\t/* There are no pre-set credentials present to match against, record the \n\t   password for the caller to check, making it an ephemeral attribute \n\t   since the client could try and re-enter it on a subsequent iteration \n\t   if we tell them that it's incorrect.  This adds the password after \n\t   the first user name that it finds but since there's only one user\n\t   name present, namely the one that was recorded or matched above, \n\t   there's no problems with potentially ambiguous password entries in\n\t   the attribute list */\n\tstatus = updateSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\tstringBuffer, stringLength,\n\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, ATTR_FLAG_EPHEMERAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Error recording password for user '%s'\",\n\t\t\t\t  sanitiseString( userNameBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  userNameLength ) ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"updateSessionInfo\" );\n\n\t*userAuthInfo = USERAUTH_CALLERCHECK;\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_9( \"readAuthPacketSSH2\", \n\t\t\t\t\t\t\t\t\t\"checkAuthPacketSSH2\", \"checkQueryValidity\", \n\t\t\t\t\t\t\t\t\t\"readAuthInfo\", \"findSessionInfoEx\", \n\t\t\t\t\t\t\t\t\t\"METHOD_QUERY\", \"METHOD_PUBKEY\", \n\t\t\t\t\t\t\t\t\t\"CREDENTIAL_USERNAME_PASSWORD\", \n\t\t\t\t\t\t\t\t\t\"updateSessionInfo\" ) );\n\treturn( OK_SPECIAL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPerform Server-side Authentication\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Server-side authentication is a critical authorisation step so we don't \n   want to make it vulnerable to a simple boolean control-variable overwrite\n   that an attacker can use to bypass the authentication check.  To do this\n   we require confirmation both via the function return status and the by-\n   reference value, we require the two values to be different values (one a\n   zero value, the other a small nonzero integer value), and we store them \n   separated by a canary that's also checked when the status values are\n   checked.  In theory it's still possible to overwrite this if an exact\n   pattern of 96 bits (on a 32-bit system) can be placed in memory, but this\n   is now vastly harder than simply entering an over-long user name or \n   password that converts an access-granted boolean-flag zero value to a \n   nonzero value */\n\ntypedef struct {\n\tUSERAUTH_TYPE userAuthInfo;\n\tint canary;\n\tint status;\n\t} FAILSAFE_AUTH_INFO;\n\nstatic const FAILSAFE_AUTH_INFO failsafeAuthSuccessTemplate = \\\n\t{ USERAUTH_SUCCESS, OK_SPECIAL, CRYPT_OK };\n\n#define initFailsafeAuthInfo( authInfo ) \\\n\t{ \\\n\tmemset( ( authInfo ), 0, sizeof( FAILSAFE_AUTH_INFO ) ); \\\n\t( authInfo )->userAuthInfo = USERAUTH_ERROR; \\\n\t( authInfo )->canary = OK_SPECIAL; \\\n\t( authInfo )->status = CRYPT_ERROR_FAILED; \\\n\t}\n\n/* Process the client's authentication */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int processFixedAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t const SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tFAILSAFE_AUTH_INFO authInfo DUMMY_INIT_STRUCT;\n\tBOOLEAN isFatalError;\n\tint authAttempts, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* The caller has specified user credentials to match against so we can\n\t   perform a basic pass/fail check against the client-supplied \n\t   information.  Since this is an all-or-nothing process at the end of \n\t   which the client is either authenticated or not authenticated we \n\t   allow the traditional three retries (or until the first fatal error) \n\t   to get it right */\n\tLOOP_SMALL( ( isFatalError = FALSE, authAttempts = 0 ), \n\t\t\t\t!isFatalError && authAttempts < 3,\n\t\t\t\tauthAttempts++ )\n\t\t{\n\t\t/* Process the user authentication and, if it's a dummy read, try a \n\t\t   second time.  This can only happen on the first iteration since \n\t\t   the initialAuth flag for processUserAuth() is set to FALSE for \n\t\t   subsequent attempts, which means that further dummy reads are \n\t\t   disallowed */\n\t\tinitFailsafeAuthInfo( &authInfo );\n\t\tauthInfo.status = processUserAuth( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t\t\t&authInfo.userAuthInfo, \n\t\t\t\t\t\t\t\t\tCREDENTIAL_USERNAME_PASSWORD, \n\t\t\t\t\t\t\t\t\t( authAttempts <= 0 ) ? TRUE : FALSE );\n\t\tif( authInfo.status == OK_SPECIAL && \\\n\t\t\tauthInfo.userAuthInfo == USERAUTH_NOOP )\n\t\t\t{\n\t\t\t/* It was a dummy read, try again */\n\t\t\tauthInfo.status = processUserAuth( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t\t\t\t&authInfo.userAuthInfo, \n\t\t\t\t\t\t\t\t\t\tCREDENTIAL_USERNAME_PASSWORD, \n\t\t\t\t\t\t\t\t\t\tFALSE );\n\t\t\t}\n\t\tif( cryptStatusOK( authInfo.status ) && \\\n\t\t\t!memcmp( &authInfo, &failsafeAuthSuccessTemplate, \\\n\t\t\t\t\t sizeof( FAILSAFE_AUTH_INFO ) ) )\n\t\t\t{\n\t\t\t/* The user has authenticated successfully and this fact has \n\t\t\t   been verified in a (reasonably) failsafe manner, we're \n\t\t\t   done */\n\t\t\treturn( sendResponseSuccess( sessionInfoPtr ) );\n\t\t\t}\n\t\tENSURES( cryptStatusError( authInfo.status ) );\n\n\t\t/* If the authentication processing returns anything other than a \n\t\t   wrong-key error due to a failed authentication attempt then the\n\t\t   error is fatal */\n\t\tif( authInfo.status != CRYPT_ERROR_WRONGKEY )\n\t\t\tisFatalError = TRUE;\n\n\t\t/* Tell the client that the authentication failed.  If it's the \n\t\t   final attempt (either because it's a fatal error or because the\n\t\t   user has used up all of their retries) then we ignore any return \n\t\t   code since it's secondary to the authentication-failed status \n\t\t   that we're returning, and in any case since the caller is going \n\t\t   to close the session in response to this it'll be signalled to \n\t\t   the client one way or another */\n\t\tif( isFatalError || authAttempts >= 2 )\n\t\t\t( void ) sendResponseFailure( sessionInfoPtr );\n\t\telse\n\t\t\t{\n\t\t\tint status;\n\n\t\t\tstatus = sendResponseFailureInfo( sessionInfoPtr, FALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( authInfo.status != OK_SPECIAL );\n\n\t/* The user still hasn't successfully authenticated after multiple \n\t   attempts, we're done */\n\treturn( authInfo.status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processServerAuth( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   const SSH_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t   const BOOLEAN userInfoPresent )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tUSERAUTH_TYPE userAuthInfo;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status DUMMY_INIT;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( userInfoPresent == TRUE || userInfoPresent == FALSE );\n\n\t/* If the caller has specified user credentials to match against we \n\t   perform a basic pass/fail check against the client-supplied \n\t   information */\n\tif( userInfoPresent )\n\t\treturn( processFixedAuth( sessionInfoPtr, handshakeInfo ) );\n\n\t/* The caller hasn't supplied any user credentials to match against,\n\t   indicating that they're going to perform an on-demand match.  If this \n\t   is a second pass through then the caller will have supplied an\n\t   authentication response to be sent to the client, in which case we\n\t   send it before continuing */\n\tif( sshInfo->authRead )\n\t\t{\n\t\t/* If the caller accepted the authentication, we're done */\n\t\tif( sessionInfoPtr->authResponse == AUTHRESPONSE_SUCCESS )\n\t\t\treturn( sendResponseSuccess( sessionInfoPtr ) );\n\n\t\t/* The caller denied the authentication, inform the client and go \n\t\t   back to asking what to do at the next authentication attempt */\n\t\tstatus = sendResponseFailureInfo( sessionInfoPtr, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsessionInfoPtr->authResponse = AUTHRESPONSE_NONE;\n\t\t}\n\tCFI_CHECK_UPDATE( \"authRead\" );\n\n\t/* Process the user authentication and, if it's a dummy read, try a \n\t   second time and even a third time (see the comments at the start of\n\t   this module).  The first time that we're called (authRead == FALSE) \n\t   we accept and record the user name supplied by the client, on any \n\t   subsequent calls (authRead == TRUE) we require a match for the \n\t   previously-supplied user name.\n\n\t   Note that we don't use the complex failsafe-check method used by\n\t   processFixedAuth() because we're not performing the authorisation\n\t   check here but simply passing the data back to the caller */\n\tif( !sshInfo->authRead )\n\t\t{\n\t\tstatus = processUserAuth( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t  &userAuthInfo, CREDENTIAL_NONE, TRUE );\n\t\tif( status == OK_SPECIAL && userAuthInfo == USERAUTH_NOOP )\n\t\t\t{\n\t\t\t/* It was a dummy read, try again */\n\t\t\tstatus = processUserAuth( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t\t\t  &userAuthInfo, CREDENTIAL_USERNAME, \n\t\t\t\t\t\t\t\t\t  FALSE );\n\t\t\t}\n\t\tif( status == OK_SPECIAL && userAuthInfo == USERAUTH_NOOP_2 )\n\t\t\t{\n\t\t\t/* It was yet another a dummy read, try again */\n\t\t\tstatus = processUserAuth( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t\t\t  &userAuthInfo, \n\t\t\t\t\t\t\t\t\t  CREDENTIAL_USERNAME_PUBKEY, FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = processUserAuth( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t  &userAuthInfo, CREDENTIAL_USERNAME, \n\t\t\t\t\t\t\t\t  FALSE );\n\t\tENSURES( !( status == OK_SPECIAL && \\\n\t\t\t\t\tuserAuthInfo == USERAUTH_NOOP ) );\n\t\t}\n\tsshInfo->authRead = TRUE;\n\tENSURES( ( cryptStatusOK( status ) && \\\n\t\t\t   userAuthInfo == USERAUTH_SUCCESS ) || \\\n\t\t\t ( ( cryptStatusError( status ) || status == OK_SPECIAL ) && \\\n\t\t\t   userAuthInfo != USERAUTH_SUCCESS ) );\n\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processUserAuth\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_2( \"authRead\", \"processUserAuth\" ) );\n\treturn( ( status == OK_SPECIAL ) ? CRYPT_ENVELOPE_RESOURCE : CRYPT_OK );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_chn.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib SSHv2 Channel Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* Channel flags */\n\n#define CHANNEL_FLAG_NONE\t\t0x00\t/* No channel flag */\n#define CHANNEL_FLAG_ACTIVE\t\t0x01\t/* Channel is active */\n#define CHANNEL_FLAG_WRITECLOSED 0x02\t/* Write-side of ch.closed */\n\n/* Per-channel information.  SSH channel IDs are 32-bit/4 byte data values\n   and can be reused during sessions so we provide our own guaranteed-unique\n   short int ID for users to identify a particular channel.  Since each\n   channel can have its own distinct characteristics we have to record\n   information like the window size and count and packet size information on \n   a per-channel basis.  In addition if the channel is tied to a forwarded \n   port we also record port-forwarding information in the generic channel-\n   type and channel-type-argument strings */\n\ntypedef struct {\n\t/* General channel information.  The read and write channel numbers are \n\t   the same for everything but Cisco software */\n\tint channelID;\t\t\t\t\t\t/* cryptlib-level channel ID */\n\tlong readChannelNo, writeChannelNo;\t/* SSH-level channel ID */\n\tint flags;\t\t\t\t\t\t\t/* Channel flags */\n\n\t/* External interface information */\n\tCRYPT_ATTRIBUTE_TYPE cursorPos;\t\t/* Virtual cursor position */\n\n\t/* Channel parameters */\n\tint windowCount, windowSize;\t\t/* Current window usage and tot.size */\n\tint maxPacketSize;\t\t\t\t\t/* Max allowed packet size */\n\n\t/* Channel naming information */\n\tBUFFER( CRYPT_MAX_TEXTSIZE, typeLen ) \\\n\tchar type[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, arg1Len ) \\\n\tchar arg1[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBUFFER( CRYPT_MAX_TEXTSIZE, arg2Len ) \\\n\tchar arg2[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint typeLen, arg1Len, arg2Len;\n\n\t/* Channel extra data.  This contains encoded oddball protocol-specific\n\t   SSH packets to be sent or having been received */\n\tBUFFER_FIXED( UINT_SIZE + CRYPT_MAX_TEXTSIZE + ( UINT_SIZE * 4 ) ) \\\n\tBYTE extraData[ ( UINT_SIZE + CRYPT_MAX_TEXTSIZE ) + \\\n\t\t\t\t\t( UINT_SIZE * 4 ) + 8 ];\n\t} SSH_CHANNEL_INFO;\n\n/* Check whether a channel corresponds to a null channel (a placeholder used\n   when there's currently no channel active) and whether a channel is\n   currently active */\n\n#define isNullChannel( channelInfoPtr ) \\\n\t\t( ( channelInfoPtr )->readChannelNo == UNUSED_CHANNEL_NO )\n#define isActiveChannel( channelInfoPtr ) \\\n\t\t( channelInfoPtr->flags & CHANNEL_FLAG_ACTIVE )\n\n/* The maximum allowed number of channels */\n\n#ifdef USE_SSH_EXTENDED\n  #define SSH_MAX_CHANNELS\t\t4\n#else\n  #define SSH_MAX_CHANNELS\t\t1\n#endif /* USE_SSH_EXTENDED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether there are any active channels still present.  Since a\n   channel can be half-closed (we've closed it for write but the other\n   side hasn't acknowledged the close yet) we allow the caller to specify\n   an excluded channel ID that's treated as logically closed for active\n   channel-check purposes even if a channel entry is still present for it.\n   This can also be used when closing channels to check whether this is the \n   last channel open, since closing the last channel also shuts down the \n   entire session */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN isChannelActive( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tIN_INT_SHORT_Z const int excludedChannelID )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_B( ( excludedChannelID == UNUSED_CHANNEL_ID ) || \\\n\t\t\t\t( excludedChannelID > 0 && \\\n\t\t\t\t  excludedChannelID < MAX_INTLENGTH_SHORT ) );\n\n\tLOOP_MAX( attributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList ), \n\t\t\t  attributeListPtr != NULL,\n\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\t\t/* If it's not an SSH channel, continue */\n\t\tif( attributeListPtr->attributeID != CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t\tcontinue;\n\n\t\t/* It's an SSH channel, check whether it's the one that we're\n\t\t   after */\n\t\tENSURES( attributeListPtr->valueLength == sizeof( SSH_CHANNEL_INFO ) );\n\t\tchannelInfoPtr = attributeListPtr->value;\n\t\tif( isActiveChannel( channelInfoPtr ) && \\\n\t\t\tchannelInfoPtr->channelID != excludedChannelID )\n\t\t\treturn( TRUE );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( FALSE );\n\t}\n\n/* Helper function used to access SSH-specific internal attributes within\n   an attribute group (== single attribute-list item containing multiple\n   sub-items).  Returns the attribute ID of the currently selected attribute\n   when attrGetType == ATTR_CURRENT, otherwise a boolean indicating whether\n   ATTR_PREV/ATTR_NEXT is still within the current subgroup */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int accessFunction( INOUT ATTRIBUTE_LIST *attributeListPtr,\n\t\t\t\t\t\t   IN_ENUM_OPT( ATTR ) const ATTR_TYPE attrGetType,\n\t\t\t\t\t\t   OUT_INT_Z int *value )\n\t{\n\tstatic const CRYPT_ATTRIBUTE_TYPE attributeOrderList[] = {\n\t\t\tCRYPT_SESSINFO_SSH_CHANNEL, CRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\t\tCRYPT_SESSINFO_SSH_CHANNEL_ARG1, CRYPT_SESSINFO_SSH_CHANNEL_ARG2,\n\t\t\tCRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, CRYPT_ATTRIBUTE_NONE,\n\t\t\tCRYPT_ATTRIBUTE_NONE };\n\tSSH_CHANNEL_INFO *channelInfoPtr = attributeListPtr->value;\n\tCRYPT_ATTRIBUTE_TYPE attributeType = channelInfoPtr->cursorPos;\n\tBOOLEAN doContinue;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( attributeListPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRangeOpt( attrGetType, ATTR ) );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\t/* If we've just moved the cursor onto this attribute, reset the\n\t   position to the first internal attribute */\n\tif( TEST_FLAG( attributeListPtr->flags, ATTR_FLAG_CURSORMOVED ) )\n\t\t{\n\t\tattributeType = channelInfoPtr->cursorPos = \\\n\t\t\t\t\t\tCRYPT_SESSINFO_SSH_CHANNEL;\n\t\tCLEAR_FLAG( attributeListPtr->flags, ATTR_FLAG_CURSORMOVED );\n\t\t}\n\n\t/* If it's an information fetch, return the currently-selected \n\t   attribute */\n\tif( attrGetType == ATTR_NONE )\n\t\t{\n\t\t*value = attributeType;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tLOOP_MED_INITCHECK( doContinue = TRUE, doContinue )\n\t\t{\n\t\tint orderIndex, LOOP_ITERATOR_ALT;\n\n\t\t/* Find the position of the current sub-attribute in the attribute\n\t\t   order list and use that to get its successor/predecessor sub-\n\t\t   attribute */\n\t\tLOOP_MED_ALT( orderIndex = 0, \n\t\t\t\t\t  attributeOrderList[ orderIndex ] != attributeType && \\\n\t\t\t\t\t\tattributeOrderList[ orderIndex ] != CRYPT_ATTRIBUTE_NONE && \\\n\t\t\t\t\t\torderIndex < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_TYPE ),\n\t\t\t\t\t  orderIndex++ );\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( orderIndex < FAILSAFE_ARRAYSIZE( attributeOrderList, \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_ATTRIBUTE_TYPE ) );\n\t\tif( attributeOrderList[ orderIndex ] == CRYPT_ATTRIBUTE_NONE )\n\t\t\t{\n\t\t\t/* We've reached the first/last sub-attribute within the current\n\t\t\t   item/group, tell the caller that there are no more sub-\n\t\t\t   attributes present and they have to move on to the next item/\n\t\t\t   group */\n\t\t\t*value = FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tif( attrGetType == ATTR_PREV )\n\t\t\t{\n\t\t\tattributeType = ( orderIndex <= 0 ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_NONE : \\\n\t\t\t\t\t\t\t\tattributeOrderList[ orderIndex - 1 ];\n\t\t\t}\n\t\telse\n\t\t\tattributeType = attributeOrderList[ orderIndex + 1 ];\n\t\tif( attributeType == CRYPT_ATTRIBUTE_NONE )\n\t\t\t{\n\t\t\t/* We've reached the first/last sub-attribute within the current\n\t\t\t   item/group, exit as before */\n\t\t\t*value = FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Check whether the required sub-attribute is present.  If not, we\n\t\t   continue and try the next one */\n\t\tswitch( attributeType )\n\t\t\t{\n\t\t\tcase CRYPT_SESSINFO_SSH_CHANNEL:\n\t\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_TYPE:\n\t\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE:\n\t\t\t\tdoContinue = FALSE;\t/* Always present */\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG1:\n\t\t\t\tif( channelInfoPtr->arg1Len > 0 )\n\t\t\t\t\tdoContinue = FALSE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG2:\n\t\t\t\tif( channelInfoPtr->arg2Len > 0 )\n\t\t\t\t\tdoContinue = FALSE;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tchannelInfoPtr->cursorPos = attributeType;\n\n\t*value = TRUE;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tFind Channel Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find the attribute entry for a channel */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic ATTRIBUTE_LIST *findChannelAttr( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tIN const long channelNo )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_N( ( channelNo == CRYPT_USE_DEFAULT ) || \\\n\t\t\t\t( channelNo >= 0 && channelNo <= CHANNEL_MAX ) );\n\n\tLOOP_MAX( attributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList ), \n\t\t\t  attributeListPtr != NULL,\n\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\t\t/* If it's not an SSH channel, continue */\n\t\tif( attributeListPtr->attributeID != CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t\tcontinue;\n\n\t\t/* It's an SSH channel, check whether it's the one that we're\n\t\t   after */\n\t\tENSURES_N( attributeListPtr->valueLength == sizeof( SSH_CHANNEL_INFO ) );\n\t\tchannelInfoPtr = attributeListPtr->value;\n\t\tif( channelNo == CRYPT_USE_DEFAULT )\n\t\t\t{\n\t\t\t/* We're looking for any open channel channel, return the first\n\t\t\t   match */\n\t\t\tif( channelInfoPtr->flags & CHANNEL_FLAG_WRITECLOSED )\n\t\t\t\tcontinue;\n\t\t\treturn( attributeListPtr );\n\t\t\t}\n\t\tif( channelInfoPtr->readChannelNo == channelNo || \\\n\t\t\tchannelInfoPtr->writeChannelNo == channelNo )\n\t\t\treturn( attributeListPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\n/* Find the SSH channel information for a channel, matching by channel \n   number, channel ID, and channel host + port information */\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic SSH_CHANNEL_INFO *findChannelByChannelNo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t IN const long channelNo )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\t\t\t\tfindChannelAttr( sessionInfoPtr, channelNo );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_N( ( channelNo == CRYPT_USE_DEFAULT ) || \\\n\t\t\t\t( channelNo >= 0 && channelNo <= CHANNEL_MAX ) );\n\n\treturn( ( attributeListPtr == NULL ) ? NULL : attributeListPtr->value );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic SSH_CHANNEL_INFO *findChannelByID( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tIN_INT_SHORT const int channelID )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( channelID ) );\n\n\tLOOP_MAX( attributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList ), \n\t\t\t  attributeListPtr != NULL,\n\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\t\t/* If it's not an SSH channel, continue */\n\t\tif( attributeListPtr->attributeID != CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t\tcontinue;\n\n\t\t/* It's an SSH channel, check whether it's the that one we're\n\t\t   after */\n\t\tENSURES_N( attributeListPtr->valueLength == sizeof( SSH_CHANNEL_INFO ) );\n\t\tchannelInfoPtr = attributeListPtr->value;\n\t\tif( channelInfoPtr->channelID == channelID )\n\t\t\treturn( ( SSH_CHANNEL_INFO * ) channelInfoPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic SSH_CHANNEL_INFO *findChannelByAddr( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tIN_BUFFER( addrInfoLen ) \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst char *addrInfo,\n\t\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT \\\n\t\t\t\t\t\t\t\t\t\t\t\tconst int addrInfoLen )\n\t{\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( addrInfo, addrInfoLen ) );\n\n\tREQUIRES_N( isShortIntegerRangeNZ( addrInfoLen ) );\n\n\tLOOP_MAX( attributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList ), \n\t\t\t  attributeListPtr != NULL,\n\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\t\t/* If it's not an SSH channel, continue */\n\t\tif( attributeListPtr->attributeID != CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t\tcontinue;\n\n\t\t/* It's an SSH channel, check whether it's the one that we're\n\t\t   after */\n\t\tENSURES_N( attributeListPtr->valueLength == sizeof( SSH_CHANNEL_INFO ) );\n\t\tchannelInfoPtr = attributeListPtr->value;\n\t\tif( channelInfoPtr->arg1Len == addrInfoLen && \\\n\t\t\t!memcmp( channelInfoPtr->arg1, addrInfo, addrInfoLen ) )\n\t\t\treturn( ( SSH_CHANNEL_INFO * ) channelInfoPtr );\n\t\t}\n\tENSURES_N( LOOP_BOUND_OK );\n\n\treturn( NULL );\n\t}\n\nCHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic const SSH_CHANNEL_INFO *getCurrentChannelInfo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t\t  IN_ENUM( CHANNEL ) \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst CHANNEL_TYPE channelType )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tstatic const SSH_CHANNEL_INFO nullChannel = \\\n\t\t\t{ UNUSED_CHANNEL_ID, UNUSED_CHANNEL_NO, UNUSED_CHANNEL_NO, \n\t\t\t  CHANNEL_FLAG_NONE, CRYPT_ATTRIBUTE_NONE, 0 /*...*/ };\n\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\tconst int channelID = ( channelType == CHANNEL_READ ) ? \\\n\t\t\t\t\t\t\tsshInfo->currReadChannel : \\\n\t\t\t\t\t\t\tsshInfo->currWriteChannel;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_N( isEnumRange( channelType, CHANNEL ) );\n\n\t/* If there's no channel open yet, return the null channel */\n\tif( channelID == UNUSED_CHANNEL_ID )\n\t\treturn( ( SSH_CHANNEL_INFO * ) &nullChannel );\n\n\tchannelInfoPtr = findChannelByID( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t  ( channelType == CHANNEL_READ ) ? \\\n\t\t\t\t\t\t\t\t\t\tsshInfo->currReadChannel : \\\n\t\t\t\t\t\t\t\t\t\tsshInfo->currWriteChannel );\n\treturn( ( channelInfoPtr == NULL ) ? \\\n\t\t\t( SSH_CHANNEL_INFO * ) &nullChannel : channelInfoPtr );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGet/Set Channel Information\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the currently active channel */\n\nCHECK_RETVAL_RANGE_NOERROR( UNUSED_CHANNEL_NO, CHANNEL_MAX ) STDC_NONNULL_ARG( ( 1 ) ) \\\nlong getCurrentChannelNo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr = \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, channelType );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_EXT( sanityCheckSessionSSH( sessionInfoPtr ), UNUSED_CHANNEL_NO );\n\tREQUIRES_EXT( channelType == CHANNEL_READ || channelType == CHANNEL_WRITE,\n\t\t\t\t  UNUSED_CHANNEL_NO );\n\tREQUIRES_EXT( channelInfoPtr != NULL, UNUSED_CHANNEL_NO );\n\n\treturn( ( channelType == CHANNEL_READ ) ? \\\n\t\t\tchannelInfoPtr->readChannelNo : channelInfoPtr->writeChannelNo );\n\t}\n\n/* Get/set an attribute or SSH-specific internal attribute from/for the \n   current channel */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t OUT_INT_Z int *value )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr = \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, CHANNEL_READ );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) );\n\tREQUIRES( channelInfoPtr != NULL );\n\n\t/* Clear return values */\n\t*value = 0;\n\n\tif( isNullChannel( channelInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL:\n\t\t\t*value = channelInfoPtr->channelID;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE:\n\t\t\t*value = isActiveChannel( channelInfoPtr ) ? TRUE : FALSE;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelAttributeS( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  OUT_BUFFER_OPT( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\tvoid *data, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int dataMaxLength, \n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\tint *dataLength )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr = \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, CHANNEL_READ );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\tisWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) );\n\tREQUIRES( ( data == NULL && dataMaxLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( dataMaxLength ) ) );\n\tREQUIRES( channelInfoPtr != NULL );\n\n\t/* Clear return values */\n\tif( data != NULL )\n\t\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\tif( isNullChannel( channelInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_TYPE:\n\t\t\treturn( attributeCopyParams( data, dataMaxLength, dataLength,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->type,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->typeLen ) );\n\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG1:\n\t\t\treturn( attributeCopyParams( data, dataMaxLength, dataLength,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->arg1,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->arg1Len ) );\n\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG2:\n\t\t\treturn( attributeCopyParams( data, dataMaxLength, dataLength,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->arg2,\n\t\t\t\t\t\t\t\t\t\t channelInfoPtr->arg2Len ) );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint getChannelExtAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ENUM( SSH_ATTRIBUTE ) \\\n\t\t\t\t\t\t\t\tconst SSH_ATTRIBUTE_TYPE sshAttribute,\n\t\t\t\t\t\t\tOUT_INT_Z int *value )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr = \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, CHANNEL_READ );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( value, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( sshAttribute, SSH_ATTRIBUTE ) );\n\tREQUIRES( channelInfoPtr != NULL );\n\n\t/* Clear return value */\n\t*value = 0;\n\n\tif( isNullChannel( channelInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tswitch( sshAttribute )\n\t\t{\n\t\tcase SSH_ATTRIBUTE_WINDOWCOUNT:\n\t\t\t*value = channelInfoPtr->windowCount;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase SSH_ATTRIBUTE_WINDOWSIZE:\n\t\t\t*value = channelInfoPtr->windowSize;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setChannelAttribute( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t IN_INT_SHORT const int value )\n\t{\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) );\n\tREQUIRES( isShortIntegerRangeNZ( value ) );\n\n\t/* If we're setting the channel ID this doesn't change any channel\n\t   attribute but selects the one with the given ID */\n\tif( attribute == CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t{\n\t\tchannelInfoPtr = findChannelByID( sessionInfoPtr, value );\n\t\tif( channelInfoPtr == NULL )\n\t\t\treturn( CRYPT_ERROR_NOTFOUND );\n\t\treturn( selectChannel( sessionInfoPtr, channelInfoPtr->writeChannelNo,\n\t\t\t\t\t\t\t   CHANNEL_WRITE ) );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint setChannelAttributeS( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t  IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t  IN_LENGTH_TEXT const int dataLength )\n\t{\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isAttribute( attribute ) );\n\tREQUIRES( dataLength > 0 && dataLength <= CRYPT_MAX_TEXTSIZE );\n\n\t/* Set the attribute for the currently-active channel */\n\tchannelInfoPtr = ( SSH_CHANNEL_INFO * ) \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, CHANNEL_READ );\n\tREQUIRES( channelInfoPtr != NULL );\n\tif( isNullChannel( channelInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tswitch( attribute )\n\t\t{\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_TYPE:\n\t\t\treturn( attributeCopyParams( channelInfoPtr->type, \n\t\t\t\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t &channelInfoPtr->typeLen, \n\t\t\t\t\t\t\t\t\t\t data, dataLength ) );\n\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG1:\n\t\t\treturn( attributeCopyParams( channelInfoPtr->arg1, \n\t\t\t\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t &channelInfoPtr->arg1Len, \n\t\t\t\t\t\t\t\t\t\t data, dataLength ) );\n\n\t\tcase CRYPT_SESSINFO_SSH_CHANNEL_ARG2:\n\t\t\treturn( attributeCopyParams( channelInfoPtr->arg2, \n\t\t\t\t\t\t\t\t\t\t CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t &channelInfoPtr->arg2Len, \n\t\t\t\t\t\t\t\t\t\t data, dataLength ) );\n\t\t}\n\n\tretIntError();\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setChannelExtAttribute( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tIN_ATTRIBUTE const SSH_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\tIN_INT_Z const int value )\n\t{\n\tSSH_CHANNEL_INFO *channelInfoPtr = ( SSH_CHANNEL_INFO * ) \\\n\t\t\t\tgetCurrentChannelInfo( sessionInfoPtr, CHANNEL_READ );\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( ( attribute == SSH_ATTRIBUTE_ACTIVE && value == TRUE ) || \\\n\t\t\t  ( attribute != SSH_ATTRIBUTE_ACTIVE && \\\n\t\t\t\tvalue >= 0 && value < INT_MAX ) );\n\tREQUIRES( channelInfoPtr != NULL );\n\n\tif( isNullChannel( channelInfoPtr ) )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\tswitch( attribute )\n\t\t{\n\t\tcase SSH_ATTRIBUTE_ACTIVE:\n\t\t\tchannelInfoPtr->flags |= CHANNEL_FLAG_ACTIVE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase SSH_ATTRIBUTE_WINDOWCOUNT:\n\t\t\tchannelInfoPtr->windowCount = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase SSH_ATTRIBUTE_WINDOWSIZE:\n\t\t\tchannelInfoPtr->windowSize = value;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase SSH_ATTRIBUTE_ALTCHANNELNO:\n\t\t\tchannelInfoPtr->writeChannelNo = value;\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Get the status of a channel: Not open, read-side open/write-side closed, \n   open */\n\nCHECK_RETVAL_ENUM( CHANNEL ) STDC_NONNULL_ARG( ( 1 ) ) \\\nCHANNEL_TYPE getChannelStatusByChannelNo( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  IN const long channelNo )\n\t{\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_EXT( sanityCheckSessionSSH( sessionInfoPtr ), CHANNEL_NONE );\n\tREQUIRES_EXT( ( channelNo >= 0 && channelNo <= CHANNEL_MAX ), \\\n\t\t\t\t  CHANNEL_NONE );\n\n\tchannelInfoPtr = findChannelByChannelNo( sessionInfoPtr, channelNo );\n\treturn( ( channelInfoPtr == NULL ) ? CHANNEL_NONE : \\\n\t\t\t( channelInfoPtr->flags & CHANNEL_FLAG_WRITECLOSED ) ? \\\n\t\t\t\tCHANNEL_READ : CHANNEL_BOTH );\n\t}\n\nCHECK_RETVAL_ENUM( CHANNEL ) STDC_NONNULL_ARG( ( 1 ) ) \\\nCHANNEL_TYPE getChannelStatusByAddr( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t IN_BUFFER( addrInfoLen ) const char *addrInfo,\n\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int addrInfoLen )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( addrInfo, addrInfoLen ) );\n\n\tREQUIRES_EXT( sanityCheckSessionSSH( sessionInfoPtr ), CHANNEL_NONE );\n\tREQUIRES_EXT( isShortIntegerRangeNZ( addrInfoLen ), CHANNEL_NONE );\n\n\tchannelInfoPtr = findChannelByAddr( sessionInfoPtr, addrInfo,\n\t\t\t\t\t\t\t\t\t\taddrInfoLen );\n\treturn( ( channelInfoPtr == NULL ) ? CHANNEL_NONE : \\\n\t\t\t( channelInfoPtr->flags & CHANNEL_FLAG_WRITECLOSED ) ? \\\n\t\t\t\tCHANNEL_READ : CHANNEL_BOTH );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChannel Management Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Select a channel */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint selectChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   IN const long channelNo,\n\t\t\t\t   IN_ENUM_OPT( CHANNEL ) const CHANNEL_TYPE channelType )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( ( channelNo == CRYPT_USE_DEFAULT ) || \\\n\t\t\t  ( channelNo >= 0 && channelNo <= CHANNEL_MAX ) );\n\t\t\t  /* CRYPT_USE_DEFAULT is used to select the first available \n\t\t\t     channel, used when closing all channels in a loop */\n\tREQUIRES( isEnumRangeOpt( channelType, CHANNEL ) );\n\t\t\t  /* We allow CHANNEL_NONE to allow selection of created-but-not-\n\t\t\t     yet-active channels */\n\n\t/* Locate the channel and update the current channel information.  We \n\t   allow a special channel-type indicator of CHANNEL_NONE to specify the \n\t   selection of not-yet-activated channels.  Since it's possible to have \n\t   per-channel packet sizes we also update the overall packet size \n\t   value */\n\tchannelInfoPtr = findChannelByChannelNo( sessionInfoPtr, channelNo );\n\tif( channelInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\tif( !isActiveChannel( channelInfoPtr ) && channelType != CHANNEL_NONE )\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\tswitch( channelType )\n\t\t{\n\t\tcase CHANNEL_READ:\n\t\t\tsshInfo->currReadChannel = channelInfoPtr->channelID;\n\t\t\tbreak;\n\n\t\tcase CHANNEL_WRITE:\n\t\t\tsshInfo->currWriteChannel = channelInfoPtr->channelID;\n\t\t\tbreak;\n\n\t\tcase CHANNEL_BOTH:\n\t\tcase CHANNEL_NONE:\n\t\t\tsshInfo->currReadChannel = \\\n\t\t\t\tsshInfo->currWriteChannel = channelInfoPtr->channelID;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tsessionInfoPtr->maxPacketSize = channelInfoPtr->maxPacketSize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add/create/delete a channel */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \\\nint addChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\tIN const long channelNo,\n\t\t\t\tIN_LENGTH_MIN( PACKET_SIZE_MIN ) const int maxPacketSize, \n\t\t\t\tIN_BUFFER( typeLen ) const void *type,\n\t\t\t\tIN_LENGTH_SHORT const int typeLen, \n\t\t\t\tIN_BUFFER_OPT( arg1Len ) const void *arg1, \n\t\t\t\tIN_LENGTH_SHORT_Z const int arg1Len )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tATTRIBUTE_LIST *attributeListPtr;\n\tSSH_CHANNEL_INFO channelInfo;\n\tint channelCount, status, LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( type, typeLen ) );\n\tassert( ( arg1 == NULL && arg1Len == 0 ) || \n\t\t\tisReadPtrDynamic( arg1, arg1Len ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\tREQUIRES( maxPacketSize >= PACKET_SIZE_MIN && \\\n\t\t\t  maxPacketSize < PACKET_SIZE_MAX );\n\tREQUIRES( isShortIntegerRangeNZ( typeLen ) );\n\tREQUIRES( ( arg1 == NULL && arg1Len == 0 ) || \\\n\t\t\t  ( arg1 != NULL && isShortIntegerRangeNZ( arg1Len ) ) );\n\n\t/* Make sure that this channel doesn't already exist */\n\tif( findChannelByChannelNo( sessionInfoPtr, channelNo ) != NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_DUPLICATE,\n\t\t\t\t( CRYPT_ERROR_DUPLICATE, SESSION_ERRINFO, \n\t\t\t\t  \"Attempt to add duplicate channel %lX\", channelNo ) );\n\t\t}\n\n\t/* SSH channels are allocated unique IDs for tracking by cryptlib,\n\t   since (at least in theory) the SSH-level channel IDs may repeat.\n\t   If the initial (not-yet-initialised) channel ID matches the\n\t   UNUSED_CHANNEL_ID magic value we initialise it to one past that\n\t   value */\n\tif( sshInfo->channelIndex <= UNUSED_CHANNEL_ID )\n\t\tsshInfo->channelIndex = UNUSED_CHANNEL_ID + 1;\n\n\t/* Make sure that we haven't exceeded the maximum number of channels */\n\tLOOP_MAX( ( channelCount = 0, \\\n\t\t\t\tattributeListPtr = DATAPTR_GET( sessionInfoPtr->attributeList ) ), \n\t\t\t  attributeListPtr != NULL,\n\t\t\t  attributeListPtr = DATAPTR_GET( attributeListPtr->next ) )\n\t\t{\n\t\tif( attributeListPtr->attributeID == CRYPT_SESSINFO_SSH_CHANNEL )\n\t\t\tchannelCount++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( channelCount > SSH_MAX_CHANNELS )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Maximum number (%d) of SSH channels reached\",\n\t\t\t\t  SSH_MAX_CHANNELS ) );\n\t\t}\n\n\t/* Initialise the information for the new channel and create it */\n\tmemset( &channelInfo, 0, sizeof( SSH_CHANNEL_INFO ) );\n\tchannelInfo.channelID = sshInfo->channelIndex++;\n\tchannelInfo.readChannelNo = channelInfo.writeChannelNo = channelNo;\n\tchannelInfo.maxPacketSize = maxPacketSize;\n\tstatus = attributeCopyParams( channelInfo.type, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  &channelInfo.typeLen, type, typeLen );\n\tif( cryptStatusOK( status ) && arg1 != NULL )\n\t\t{\n\t\tstatus = attributeCopyParams( channelInfo.arg1, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  &channelInfo.arg1Len, arg1, arg1Len );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = addSessionInfoComposite( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL, \n\t\t\t\t\t\t\t\t\t\t  accessFunction, &channelInfo, \n\t\t\t\t\t\t\t\t\t\t  sizeof( SSH_CHANNEL_INFO ),\n\t\t\t\t\t\t\t\t\t\t  ATTR_FLAG_MULTIVALUED | \\\n\t\t\t\t\t\t\t\t\t\t  ATTR_FLAG_COMPOSITE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Select the newly-created channel.  We have to select it using the\n\t   special-case indicator of CHANNEL_NONE since we can't normally\n\t   select an inactive channel */\n\treturn( selectChannel( sessionInfoPtr, channelNo, CHANNEL_NONE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint createChannel( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tint LOOP_ITERATOR;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Find an unused channel number.  Since the peer can request the\n\t   creation of arbitrary-numbered channels we have to be careful to\n\t   ensure that we don't clash with any existing peer-requested channel\n\t   numbers when we create our own one */\n\tLOOP_MED_CHECK( findChannelByChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t\tsshInfo->nextChannelNo ) != NULL )\n\t\t{\n\t\t/* This channel number is already in use, move on to the next one */\n\t\tsshInfo->nextChannelNo++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Create a channel with the new channel number */\n\treturn( addChannel( sessionInfoPtr, sshInfo->nextChannelNo++,\n\t\t\t\t\t\tsessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE,\n\t\t\t\t\t\t\"session\", 7, NULL, 0 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint deleteChannel( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   IN const long channelNo,\n\t\t\t\t   IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType,\n\t\t\t\t   const BOOLEAN deleteLastChannel )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\tATTRIBUTE_LIST *attributeListPtr;\n\tint channelID;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\tREQUIRES( isEnumRange( channelType, CHANNEL ) );\n\tREQUIRES( deleteLastChannel == TRUE || deleteLastChannel == FALSE );\n\n\t/* Locate the channel information */\n\tattributeListPtr = findChannelAttr( sessionInfoPtr, channelNo );\n\tif( attributeListPtr == NULL )\n\t\treturn( isChannelActive( sessionInfoPtr, UNUSED_CHANNEL_ID ) ? \\\n\t\t\t\tCRYPT_ERROR_NOTFOUND : OK_SPECIAL );\n\tchannelInfoPtr = attributeListPtr->value;\n\tchannelID = channelInfoPtr->channelID;\n\n\t/* If we can't delete the last remaining channel (it has to be done\n\t   explicitly via a session close) and there are no active channels\n\t   left besides the current one then we can't do anything */\n\tif( !deleteLastChannel && \\\n\t\t!isChannelActive( sessionInfoPtr, channelID ) )\n\t\treturn( CRYPT_ERROR_PERMISSION );\n\n\t/* Delete the channel entry.  If we're only closing the write side we\n\t   mark the channel as closed for write but leave the overall channel\n\t   open */\n\tif( channelType == CHANNEL_WRITE )\n\t\t{\n\t\tREQUIRES( !( channelInfoPtr->flags & CHANNEL_FLAG_WRITECLOSED ) );\n\t\tchannelInfoPtr->flags |= CHANNEL_FLAG_WRITECLOSED;\n\t\tif( channelID == sshInfo->currWriteChannel )\n\t\t\tsshInfo->currWriteChannel = UNUSED_CHANNEL_ID;\n\t\treturn( isChannelActive( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t channelInfoPtr->channelID ) ? \\\n\t\t\t\tCRYPT_OK : OK_SPECIAL );\n\t\t}\n\tdeleteSessionInfo( sessionInfoPtr, attributeListPtr );\n\n\t/* If we've deleted the current channel, select a null channel until a\n\t   new one is created/selected */\n\tif( channelID == sshInfo->currReadChannel )\n\t\tsshInfo->currReadChannel = UNUSED_CHANNEL_ID;\n\tif( channelID == sshInfo->currWriteChannel )\n\t\tsshInfo->currWriteChannel = UNUSED_CHANNEL_ID;\n\n\t/* We've deleted an open channel, check if there are any channels left\n\t   and if not let the caller know */\n\treturn( isChannelActive( sessionInfoPtr, UNUSED_CHANNEL_ID ) ? \\\n\t\t\tCRYPT_OK : OK_SPECIAL );\n\t}\n\n#if 0\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint deleteChannelByAddr( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t IN_BUFFER( addrInfoLen ) const char *addrInfo,\n\t\t\t\t\t\t IN_LENGTH_SHORT const int addrInfoLen )\n\t{\n\tconst SSH_CHANNEL_INFO *channelInfoPtr;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( addrInfo, addrInfoLen ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( addrInfoLen ) );\n\n\tchannelInfoPtr = findChannelByAddr( sessionInfoPtr, addrInfo,\n\t\t\t\t\t\t\t\t\t\taddrInfoLen );\n\tif( channelInfoPtr == NULL )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* We've found the entry that it corresponds to, clear it.  This doesn't\n\t   actually delete the entire channel but merely deletes the forwarding.\n\t   See the note in ssh2_msg.c for why this is currently unused */\n\tmemset( channelInfoPtr->arg1, 0, CRYPT_MAX_TEXTSIZE );\n\tchannelInfoPtr->arg1Len = 0;\n\treturn( CRYPT_OK );\n\t}\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEnqueue/Send Channel Messages\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Enqueue a response to a request, to be sent at the next available\n   opportunity.  This is required because we may be in the middle of\n   assembling or sending a data packet when we need to send the response\n   so the response has to be deferred until after the data packet has been\n   completed and sent */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint enqueueResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t IN_RANGE( 1, 255 ) const int type,\n\t\t\t\t\t IN_RANGE( 0, 4 ) const int noParams, \n\t\t\t\t\t IN const long channelNo,\n\t\t\t\t\t const int param1, const int param2, const int param3 )\n\t{\n\tSSH_RESPONSE_INFO *respPtr = &sessionInfoPtr->sessionSSH->response;\n\tSTREAM stream;\n\tint status = CRYPT_OK;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( type > 0 && type <= 0xFF );\n\tREQUIRES( noParams >= 0 && noParams <= 4 );\n\t\t\t  /* channelNo is the first parameter */\n\tREQUIRES( ( noParams == 0 && channelNo == CRYPT_UNUSED ) || \\\n\t\t\t  ( channelNo >= 0 && channelNo <= CHANNEL_MAX ) );\n\n\t/* If there's already a response enqueued we can't enqueue another one\n\t   until it's been sent */\n\tREQUIRES( respPtr->type == 0 );\n\n\trespPtr->type = type;\n\tsMemOpen( &stream, respPtr->data, SSH_MAX_RESPONSESIZE );\n\tif( noParams > 0 )\n\t\tstatus = writeUint32( &stream, channelNo );\n\tif( noParams > 1 )\n\t\tstatus = writeUint32( &stream, param1 );\n\tif( noParams > 2 )\n\t\tstatus = writeUint32( &stream, param2 );\n\tif( noParams > 3 )\n\t\tstatus = writeUint32( &stream, param3 );\n\tENSURES( cryptStatusOK( status ) );\n\trespPtr->dataLen = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Assemble a packet for and send a previously enqueued response.  This \n   potentially appends a control packet after the end of an existing payload\n   packet so the buffer indicator used is sendBufSize rather than \n   maxPacketSize, since we may already have maxPacketSize bytes worth of\n   payload data present.\n\n   This can be called in one of two ways, if called as appendChannelData()\n   then it's being piggybacked onto the end of existing data at a location\n   specified by the 'offset' parameter and we assemble the packet at that \n   point but it'll be sent as part of the main packet send.  If called as \n   enqueueChannelData() or sendEnqueuedResponse() then we have the send \n   buffer to ourselves (offset == CRYPT_UNUSED) and can assemble and send it \n   immediately */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int encodeSendResponse( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   IN_LENGTH_OPT const int offset,\n\t\t\t\t\t\t\t   OUT_OPT_LENGTH_Z int *responseSize )\n\t{\n\tSSH_RESPONSE_INFO *respPtr = &sessionInfoPtr->sessionSSH->response;\n\tSTREAM stream;\n\tconst BOOLEAN assembleOnly = ( offset != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tBOOLEAN adjustedStartOffset = FALSE;\n\tint sendBufOffset = assembleOnly ? offset : sessionInfoPtr->sendBufPos;\n\tint encodedResponseSize DUMMY_INIT, dummy, status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( responseSize == NULL || \\\n\t\t\tisWritePtr( responseSize, sizeof( int ) ) );\n\n\tREQUIRES( ( offset == CRYPT_UNUSED && responseSize == NULL ) || \\\n\t\t\t  ( offset >= 0 && offset < sessionInfoPtr->sendBufSize && \\\n\t\t\t    responseSize != NULL ) );\n\tREQUIRES( sendBufOffset >= 0 && offset < sessionInfoPtr->sendBufSize );\n\n\t/* Make sure that there's room for at least two packets worth of \n\t   wrappers plus a short control packet, needed to handle a control \n\t   packet piggybacked onto the end of a data packet.  The reason for the\n\t   doubling of the IV count is because the minimum padding length \n\t   requirement can result in an expansion by two encrypted blocks rather\n\t   than one */\n\tstatic_assert( EXTRA_PACKET_SIZE > \\\n\t\t\t\t\t\t( 2 * ( SSH2_HEADER_SIZE + CRYPT_MAX_HASHSIZE + \\\n\t\t\t\t\t\t\t\t( 2 * CRYPT_MAX_IVSIZE ) ) ) + 32,\n\t\t\t\t   \"Buffer packet size\" );\n\n\t/* Clear return value */\n\tif( responseSize != NULL )\n\t\t*responseSize = 0;\n\n\t/* If there's an incomplete packet in the process of being assembled in\n\t   the send buffer then we can't do anything.  If we're just assembling\n\t   a response to append to a completed packet then we know that the \n\t   packet that's present is a complete one so we skip this check */\n\tif( assembleOnly && !sessionInfoPtr->partialWrite && \\\n\t\t( sendBufOffset > sessionInfoPtr->sendBufStartOfs ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The send buffer is allocated to always allow the piggybacking of one\n\t   packet of control data */\n\tENSURES( sendBufOffset + ( SSH2_HEADER_SIZE + 16 + respPtr->dataLen + \\\n\t\t\t\t\t\t\t   CRYPT_MAX_HASHSIZE + CRYPT_MAX_IVSIZE ) <= \\\n\t\t\t\t\t\tsessionInfoPtr->sendBufSize );\n\n\tENSURES( ( sendBufOffset <= sessionInfoPtr->sendBufStartOfs ) || \\\n\t\t\t ( sessionInfoPtr->partialWrite && \\\n\t\t\t   sendBufOffset + ( SSH2_HEADER_SIZE + 16 + respPtr->dataLen + \\\n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE + CRYPT_MAX_IVSIZE ) < \\\n\t\t\t\t\t\tsessionInfoPtr->sendBufSize ) );\n\n\t/* If we're in the data transfer phase and there's nothing in the send \n\t   buffer, set the packet start offset to zero.  We have to do this \n\t   because it's pre-adjusted to accomodate the header for a payload data \n\t   packet, since we're assembling our own packet in the buffer there's \n\t   no need for this additional header room */\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) && \\\n\t\tsendBufOffset == sessionInfoPtr->sendBufStartOfs )\n\t\t{\n\t\tsendBufOffset = 0;\n\t\tadjustedStartOffset = TRUE;\n\t\t}\n\n\t/* Assemble the response as a new packet at the end of any existing\n\t   data */\n\tREQUIRES( boundsCheckZ( sendBufOffset, \n\t\t\t\t\t\t    sessionInfoPtr->sendBufSize - sendBufOffset,\n\t\t\t\t\t\t    sessionInfoPtr->sendBufSize ) );\n\tsMemOpen( &stream, sessionInfoPtr->sendBuffer + sendBufOffset,\n\t\t\t  sessionInfoPtr->sendBufSize - sendBufOffset );\n\tswrite( &stream, \"\\x00\\x00\\x00\\x00\\x00\", SSH2_HEADER_SIZE );\n\tstatus = sputc( &stream, respPtr->type );\n\tif( respPtr->dataLen > 0 )\n\t\t{\n\t\t/* Some responses can consist purely of an ID byte */\n\t\tstatus = swrite( &stream, respPtr->data, respPtr->dataLen );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, 0, FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tencodedResponseSize = stell( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* We've sent (or at least assembled) the response, clear the enqueued\n\t   data */\n\tmemset( respPtr, 0, sizeof( SSH_RESPONSE_INFO ) );\n\n\t/* If we're only assembling the data and the caller is taking care of\n\t   sending the assembled packet, we're done */\n\tif( assembleOnly )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\t*responseSize = encodedResponseSize;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If we're still in the handshake phase (so this is part of the initial\n\t   session negotiation, for example a response to a global or channel\n\t   request) then we need to send the packet directly to avoid messing\n\t   up the send buffering */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) )\n\t\t{\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Write the response, using the standard data-flush mechanism to try \n\t   and get the data out.  We set the partial-write flag because what \n\t   we've just added is pre-packaged data that doesn't have to go through \n\t   the data-payload encoding process */\n\tsMemDisconnect( &stream );\n\tif( adjustedStartOffset )\n\t\t{\n\t\t/* We're in the data transfer phase, in which case the buffer \n\t\t   position is offset into the send buffer to leave room for the \n\t\t   packet header.  Since we're adding our own header we've started \n\t\t   the packet at the start of the send buffer, i.e. with \n\t\t   sendBufPos = 0 rather than sendBufPos = sendBufStartOffset, so we \n\t\t   set the new position to the total size of the data written rather \n\t\t   than adding it to the existing value */\n\t\tsessionInfoPtr->sendBufPos = encodedResponseSize;\n\t\t}\n\telse\n\t\t{\n\t\tassert( 0 );\t/* When does this occur? */\n\t\tsessionInfoPtr->sendBufPos += encodedResponseSize;\n\t\t}\n\tsessionInfoPtr->partialWrite = TRUE;\n\treturn( putSessionData( sessionInfoPtr, NULL, 0, &dummy ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendEnqueuedResponse( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\treturn( encodeSendResponse( sessionInfoPtr, CRYPT_UNUSED, NULL ) );\n\t}\n\n/* Enqueue channel control data ready to be sent, and try and send it if\n   possible.  This is used to send window-adjust messages for the SSH\n   performance handbrake by first enqueueing the window adjust and then,\n   if the send buffer is available, sending it.  If it's not available\n   then it'll be piggybacked onto the channel payload data later on when \n   it's being sent via appendChannelData() below */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint enqueueChannelData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tIN_RANGE( 1, 255 ) const int type,\n\t\t\t\t\t\tIN const long channelNo, \n\t\t\t\t\t\tconst int param )\n\t{\n\tint status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( type > 0 && type <= 0xFF );\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\n\tstatus = enqueueResponse( sessionInfoPtr, type, 2, channelNo, param,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( encodeSendResponse( sessionInfoPtr, CRYPT_UNUSED, NULL ) );\n\t}\n\n/* Append enqueued channel control data to existing channel payload data\n   without trying to send it.  In this case the control data send is being \n   piggybacked on a payload data send and will be handled by the caller,\n   with the control flow on the caller side being:\n\n\tpreparepacketFunction:\n\t\twrap channel data;\n\t\tif( enqueued control data present )\n\t\t\tappendChannelData();\n\tsend wrapped channel data and wrapped control data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint appendChannelData( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int offset )\n\t{\n\tint channelDataSize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( offset >= 0 && offset < sessionInfoPtr->sendBufSize );\n\n\tstatus = encodeSendResponse( sessionInfoPtr, offset, &channelDataSize );\n\treturn( cryptStatusError( status ) ? status : channelDataSize );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_cli.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tcryptlib SSHv2 Client\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate/check an SSH key fingerprint.  This is simply an MD5 hash of the \n   server's key/certificate data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processKeyFingerprint( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t  IN_BUFFER( keyDataLength ) const void *keyData,\n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyDataLength )\n\t{\n\tHASH_FUNCTION_ATOMIC hashFunctionAtomic;\n\tconst ATTRIBUTE_LIST *attributeListPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );\n\tBYTE fingerPrint[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint hashSize;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( keyDataLength ) );\n\n\tgetHashAtomicParameters( CRYPT_ALGO_MD5, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t &hashSize );\n\thashFunctionAtomic( fingerPrint, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\tkeyData, keyDataLength );\n\tif( attributeListPtr == NULL )\n\t\t{\n\t\t/* Remember the value for the caller.  Recording it as a \"SHA1\" hash\n\t\t   is a bit odd since it's an MD5 hash, but the use of MD5 hashes \n\t\t   has been deprecated everywhere else so there's no other way to\n\t\t   convey it */\n\t\treturn( addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t fingerPrint, hashSize ) );\n\t\t}\n\n\t/* In the unlikely event that the user has passed us a SHA-1 \n\t   fingerprint, which isn't allowed by the spec but no doubt someone out \n\t   there's using it based on the fact that the SSH architecture draft \n\t   suggested a SHA-1 fingerprint while the SSH fingerprint draft \n\t   required an MD5 one, calculate that instead */\n\tif( attributeListPtr->valueLength == 20 )\n\t\t{\n\t\tgetHashAtomicParameters( CRYPT_ALGO_SHA1, 0, &hashFunctionAtomic, \n\t\t\t\t\t\t\t\t &hashSize );\n\t\thashFunctionAtomic( fingerPrint, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\tkeyData, keyDataLength );\n\t\t}\n\n\t/* There's an existing fingerprint value, make sure that it matches what\n\t   we just calculated */\n\tif( attributeListPtr->valueLength != hashSize || \\\n\t\tmemcmp( attributeListPtr->value, fingerPrint, hashSize ) )\n\t\t{\n\t\t/* If there's enough fingerprint data present we can be a bit more\n\t\t   specific in our error message */\n\t\tif( attributeListPtr->valueLength >= 8 )\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tchar fingerPrintText[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\t\tchar reqFingerPrintText[ CRYPT_MAX_TEXTSIZE + 8 ];\n#endif /* USE_ERRMSGS */\n\n\t\t\tformatFingerprint( fingerPrintText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   fingerPrint, hashSize );\n\t\t\tformatFingerprint( reqFingerPrintText, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   attributeListPtr->value, \n\t\t\t\t\t\t\t   attributeListPtr->valueLength );\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"Server key fingerprint '%s' doesn't match requested \"\n\t\t\t\t\t  \"fingerprint '%s'\", fingerPrintText,\n\t\t\t\t\t  reqFingerPrintText ) );\n\t\t\t}\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"Server key fingerprint doesn't match requested \"\n\t\t\t\t  \"fingerprint\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Handle an ephemeral DH key exchange */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nstatic int processDHE( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t   INOUT KEYAGREE_PARAMS *keyAgreeParams )\n\t{\n\tconst int keyDataHdrSize = LENGTH_SIZE + sizeofString32( 6 );\n\tvoid *keyexInfoPtr DUMMY_INIT_PTR;\n\tint keyexInfoLength DUMMY_INIT, length, packetOffset, dummy, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/*\t...\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_REQUEST_NEW\n\t\tuint32\tmin = MIN_PKCSIZE bits\n\t\tuint32\tn = SSH_DEFAULT_KEYSIZE (as bits)\n\t\tuint32\tmax = CRYPT_MAX_PKCSIZE (as bits)\n\n\t   There's an older format for this that just allows the client to \n\t   specify a single preferred key size:\n\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_REQUEST_OLD\n\t\tuint32\tn = SSH_DEFAULT_KEYSIZE bits\n\n\t   which some older servers may still require (some will just drop the \n\t   connection without any error response if they encounter the newer \n\t   packet type), however some new servers will in turn reject the older\n\t   form if the preferred key size that's given doesn't match their \n\t   configured key size.  Since more servers handle the new form and will\n\t   reject the old form if the key size doesn't match, we send the new \n\t   form, however there is one widely-used buggy server that will generate\n\t   an invalid keyex signature if sent an SSH_MSG_KEX_DH_GEX_REQUEST \n\t   rather than an SSH_MSG_KEX_DH_GEX_REQUEST_OLD, presumably due to \n\t   hashing the wrong packet format, so we optionally send that as a\n\t   workaround */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_OLDGEX ) )\n\t\t{\n\t\tstatus = continuePacketStreamSSH( stream, \n\t\t\t\t\t\t\t\t\t\t  SSH_MSG_KEX_DH_GEX_REQUEST_OLD,\n\t\t\t\t\t\t\t\t\t\t  &packetOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstreamBookmarkSet( stream, keyexInfoLength );\n\t\t\tstatus = writeUint32( stream, bytesToBits( SSH2_DEFAULT_KEYSIZE ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = continuePacketStreamSSH( stream, SSH_MSG_KEX_DH_GEX_REQUEST,\n\t\t\t\t\t\t\t\t\t\t  &packetOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstreamBookmarkSet( stream, keyexInfoLength );\n\t\t\twriteUint32( stream, bytesToBits( MIN_PKCSIZE ) );\n\t\t\twriteUint32( stream, bytesToBits( SSH2_DEFAULT_KEYSIZE ) );\n\t\t\tstatus = writeUint32( stream, bytesToBits( CRYPT_MAX_PKCSIZE ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( stream, &keyexInfoPtr, \n\t\t\t\t\t\t\t\t\t\t &keyexInfoLength, keyexInfoLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, stream, packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, stream );\n\tsMemDisconnect( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( keyexInfoPtr != NULL );\n\n\t/* Remember the encoded key size information for later when we generate \n\t   the exchange hash */\n\tREQUIRES( rangeCheck( keyexInfoLength, 1, ENCODED_REQKEYSIZE ) );\n\tmemcpy( handshakeInfo->encodedReqKeySizes, keyexInfoPtr,\n\t\t\tkeyexInfoLength );\n\thandshakeInfo->encodedReqKeySizesLength = keyexInfoLength;\n\n\t/* Process the ephemeral DH key:\n\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_GROUP\n\t\tmpint\tp\n\t\tmpint\tg */\n\tstatus = length = \\\n\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_KEX_DH_GEX_GROUP,\n\t\t\t\t\t\t  ID_SIZE + sizeofString32( MIN_PKCSIZE ) + \\\n\t\t\t\t\t\t\tsizeofString32( 1 ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, length );\n\tstreamBookmarkSet( stream, keyexInfoLength );\n\tstatus = readInteger32Checked( stream, NULL, &dummy, MIN_PKCSIZE, \n\t\t\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readInteger32( stream, NULL, &dummy, 1, \n\t\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( stream, &keyexInfoPtr, \n\t\t\t\t\t\t\t\t\t\t &keyexInfoLength, \n\t\t\t\t\t\t\t\t\t\t keyexInfoLength );\n\t\t}\n\tsMemDisconnect( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some misconfigured servers may use very short keys, we perform\n\t\t   a special-case check for these and return a more specific message\n\t\t   than the generic bad-data */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure DH key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid DH ephemeral key data packet\" ) );\n\t\t}\n\tANALYSER_HINT( keyexInfoPtr != NULL );\n\n\t/* Since this phase of the key negotiation exchanges raw key components\n\t   rather than the standard SSH public-key format we have to rewrite the \n\t   raw key components into a standard SSH key so that we can import it:\n\n\t\t\tFrom:\t\t\t\t\tTo:\n\t\t\t\t\t\t\t\tstring\t\t[ key/certificate ]\n\t\t\t\t\t\t\t\t\tstring\t\"ssh-dh\"\n\t\t\tmpint\tp\t\t\t\tmpint\tp\n\t\t\tmpint\tg\t\t\t\tmpint\tg */\n\tREQUIRES( boundsCheck( keyDataHdrSize, keyexInfoLength, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tmemmove( ( BYTE * ) keyexInfoPtr + keyDataHdrSize, keyexInfoPtr, \n\t\t\t keyexInfoLength );\n\tsMemOpen( stream, keyexInfoPtr, keyDataHdrSize );\n\twriteUint32( stream, sizeofString32( 6 ) + keyexInfoLength );\n\tstatus = writeString32( stream, \"ssh-dh\", 6 );\n\tsMemDisconnect( stream );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Set up the DH context from the server's parameters and perform phase \n\t   1 of the DH key agreement process */\n\tstatus = initDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t   &handshakeInfo->serverKeySize, keyexInfoPtr,\n\t\t\t\t\t\t\t   keyDataHdrSize + keyexInfoLength,\n\t\t\t\t\t\t\t   CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create DH ephemeral key data\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tClient-side Connect Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform the initial part of the handshake with the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int beginClientHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tKEYAGREE_PARAMS keyAgreeParams DUMMY_INIT_STRUCT;\n\tSTREAM stream;\n\tvoid *clientHelloPtr DUMMY_INIT_PTR, *keyexPtr DUMMY_INIT_PTR;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint serverHelloLength, clientHelloLength, keyexLength DUMMY_INIT;\n\tint packetOffset = 0, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* The higher-level code has already read the server version information, \n\t   send back our own version information */\n\tstatus = swrite( &sessionInfoPtr->stream, SSH_ID_STRING \"\\r\\n\",\n\t\t\t\t\t SSH_ID_STRING_SIZE + 2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\n\t/* SSH hashes the handshake ID strings for integrity-protection purposes, \n\t   first our client string and then the server string that we read \n\t   previously */\n\tstatus = hashHandshakeStrings( handshakeInfo, \n\t\t\t\t\t\t\t\t   SSH_ID_STRING, SSH_ID_STRING_SIZE,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Now that we've processed the out-of-band data in the receive buffer, \n\t   mark it as empty */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\n\t/* In theory we could opportunistically set up a DH context while we \n\t   wait for the server to digest our version information and send back \n\t   its response, but in practice there are so many different ways in\n\t   which SSH can modify what the keyex does that we have to wait until\n\t   after the server hello to do anything */\n\n\t/* Process the server hello */\n\tstatus = processHelloSSH( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t  &serverHelloLength, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processHelloSSH\" );\n\n\t/* Build the client hello and DH/ECDH phase 1 keyex packet:\n\n\t\tbyte\t\ttype = SSH_MSG_KEXINIT\n\t\tbyte[16]\tcookie\n\t\tstring\t\tkeyex algorithms = DH/DHE/ECDH\n\t\tstring\t\tpubkey algorithms\n\t\tstring\t\tclient_crypto algorithms\n\t\tstring\t\tserver_crypto algorithms\n\t\tstring\t\tclient_mac algorithms\n\t\tstring\t\tserver_mac algorithms\n\t\tstring\t\tclient_compression algorithms = \"none\"\n\t\tstring\t\tserver_compression algorithms = \"none\"\n\t\tstring\t\tclient_language = \"\"\n\t\tstring\t\tserver_language = \"\"\n\t\tboolean\t\tfirst_keyex_packet_follows = FALSE\n\t\tuint32\t\treserved = 0\n\t\t...\n\n\t   The SSH spec leaves the order in which things happen ambiguous, in\n\t   order to save a whole round trip it has provisions for both sides\n\t   shouting at each other and then a complex interlock process where\n\t   bits of the initial exchange can be discarded and retried if necessary.\n\t   This is ugly and error-prone so what we do is wait for the server\n\t   hello (already done earlier), choose known-good algorithms, and then\n\t   send the client hello immediately followed by the client keyex.\n\t   Since we wait for the server to speak first we can choose parameters\n\t   that are accepted the first time.  In theory this means that we can\n\t   set keyex_follows to true (since a correct keyex packet always\n\t   follows the hello), however because of the nondeterministic initial\n\t   exchange the spec requires that a (guessed) keyex be discarded by the\n\t   server if the hello doesn't match (even if the keyex does):\n\n\t\tsvr: hello\n\t\tclient: matched hello, keyex\n\t\tsvr: (discard keyex)\n\n\t   To avoid this problem we set keyex_follows to false to make it clear\n\t   to the server that the keyex is the real thing and shouldn't be\n\t   discarded */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, SSH_MSG_KEXINIT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamBookmarkSetFullPacket( &stream, clientHelloLength );\n\tstatus = exportVarsizeAttributeToStream( &stream, SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_RANDOM_NONCE,\n\t\t\t\t\t\t\t\t\t\t\t SSH2_COOKIE_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tstatus = writeAlgoStringEx( &stream, handshakeInfo->keyexAlgo,\n\t\t\t\t\t\t\t\thandshakeInfo->exchangeHashAlgo, 0,\n\t\t\t\t\t\t\t\thandshakeInfo->isFixedDH ? \\\n\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_EXTINFO_ALTDHALGOS : \\\n\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_EXTINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAlgoStringEx( &stream, handshakeInfo->pubkeyAlgo, \n\t\t\t\t\t\t\t\t\thandshakeInfo->hashAlgo, 0,\n\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAlgoStringEx( &stream, sessionInfoPtr->cryptAlgo,\n\t\t\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \\\n\t\t\t\t\t\t\t\t\t\t\t   SSH_PFLAG_CTR ) ? \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_MODE_ECB : CRYPT_MODE_CBC, \n\t\t\t\t\t\t\t\t\thandshakeInfo->cryptKeysize,\n\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAlgoStringEx( &stream, sessionInfoPtr->cryptAlgo,\n\t\t\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \\\n\t\t\t\t\t\t\t\t\t\t\t   SSH_PFLAG_CTR ) ? \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_MODE_ECB : CRYPT_MODE_CBC, \n\t\t\t\t\t\t\t\t\thandshakeInfo->cryptKeysize,\n\t\t\t\t\t\t\t\t\tSSH_ALGOSTRINGINFO_NONE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoString( &stream, sessionInfoPtr->integrityAlgo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoString( &stream, sessionInfoPtr->integrityAlgo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_COPR );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_COPR );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteUint32( &stream, 0 );\t/* No language tag */\n\twriteUint32( &stream, 0 );\n\tsputc( &stream, 0 );\t\t/* Tell the server not to discard the packet */\n\tstatus = writeUint32( &stream, 0 );\t/* Reserved */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &clientHelloPtr, \n\t\t\t\t\t\t\t\t\t\t &clientHelloLength, \n\t\t\t\t\t\t\t\t\t\t clientHelloLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tANALYSER_HINT( clientHelloPtr != NULL );\n\tCFI_CHECK_UPDATE( \"writeClientHello\" );\n\n\t/* Hash the client and server hello messages.  We have to do this now\n\t   rather than deferring it until we're waiting on network traffic from\n\t   the server because they may get overwritten by the keyex negotiation\n\t   data if we're using a non-builtin DH key value.  In addition since the\n\t   entire encoded packet (including the type value) is hashed we have to\n\t   reconstruct this at the start of the packet */\n\tstatus = hashAsString( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t   clientHelloPtr, clientHelloLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tREQUIRES( rangeCheck( serverHelloLength, 1,\n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufSize ) );\n\t\tmemmove( sessionInfoPtr->receiveBuffer + 1, \n\t\t\t\t sessionInfoPtr->receiveBuffer, serverHelloLength );\n\t\tsessionInfoPtr->receiveBuffer[ 0 ] = SSH_MSG_KEXINIT;\n\t\tstatus = hashAsString( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t   serverHelloLength + 1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* SSH has a whole range of ways to specify the same keyex algorithm \n\t   (see the long comment in ssh.h), the following multi-option code is\n\t   required to handle them.  The original way to do it was to use an\n\t   explicitly-specified DH key, but an alternative mechanism uses a\n\t   negotiated DH key value, in which case we have to request the keyex \n\t   key from the server.  This additional negotiation requires \n\t   disconnecting and re-connecting the data packet stream since it \n\t   exchanges further data with the server, so if there's an error return \n\t   we don't disconnect the stream before we exit */\n\tif( handshakeInfo->isFixedDH )\n\t\t{\n\t\tREQUIRES( !handshakeInfo->isECDH );\n\n\t\t/* It's a fixed-size DH key */\n\t\tstatus = initDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t   &handshakeInfo->serverKeySize, NULL, 0,\n\t\t\t\t\t\t\t\t   handshakeInfo->requestedServerKeySize );\n\t\t}\n\telse\n\t\t{\n#ifdef USE_ECDH \n\t\t/* A second possibility is when we're using ECDH rather than DH, for \n\t\t   which we have to use ECDH contexts and values */\n\t\tif( handshakeInfo->isECDH )\n\t\t\t{\n\t\t\t/* Set up the ECDH context from the server's parameters and \n\t\t\t   perform phase 1 of the ECDH key agreement process */\n\t\t\tstatus = initECDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t\t\t &handshakeInfo->serverKeySize, \n\t\t\t\t\t\t\t\t\t\t handshakeInfo->keyexAlgo );\n\t\t\t}\n\t\telse\n#endif /* USE_ECDH */\n\t\t\t{\n\t\t\tstatus = processDHE( sessionInfoPtr, handshakeInfo, &stream,\n\t\t\t\t\t\t\t\t &keyAgreeParams );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* processDHE() has already disconnected the stream */\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\t\tstatus = krnlSendMessage( handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, &keyAgreeParams,\n\t\t\t\t\t\t\t\t  sizeof( KEYAGREE_PARAMS ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create %s ephemeral key data\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processDHE\" );\n\n\t/* If we're fuzzing the input then we're reading static data and no \n\t   further input is processed after this point, exit now to minimise\n\t   the overhead during fuzz testing */\n\tFUZZ_SET( handshakeInfo->clientKeyexValueLength,\n\t\t\t  handshakeInfo->serverKeySize );\n\tFUZZ_SKIP();\n\n\t/*\t...\n\t   DH:\n\t\tbyte\ttype = SSH_MSG_KEXDH_INIT / SSH_MSG_KEXDH_GEX_INIT\n\t\tmpint\ty\n\t   ECDH:\n\t\tbyte\ttype = SSH_MSG_KEX_ECDH_INIT\n\t\tstring\tq_c \n\n\t   SSH_MSG_KEXDH_INIT (isFixedDH) and SSH_MSG_KEX_ECDH_INIT (isECDH) \n\t   have the same value so they're handled with the same code */\n\tif( handshakeInfo->isFixedDH || handshakeInfo->isECDH )\n\t\t{\n\t\t/* It's a DH/ECDH exchange with static keys */\n\t\tstatus = continuePacketStreamSSH( &stream, SSH_MSG_KEXDH_INIT,\n\t\t\t\t\t\t\t\t\t\t  &packetOffset );\n\t\t}\n\telse\n\t\t{\n\t\t/* processDHE() has disconnected the stream as part of the ephemeral \n\t\t   DH packet exchange so we need to create a new stream */\n\t\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  SSH_MSG_KEX_DH_GEX_INIT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstreamBookmarkSet( &stream, keyexLength );\n\t\tif( handshakeInfo->isECDH )\n\t\t\t{\n\t\t\tstatus = writeString32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t\tkeyAgreeParams.publicValueLen );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tINJECT_FAULT( SESSION_CORRUPT_KEYEX_CLIENT,\t\n\t\t\t\t\t\t  SESSION_CORRUPT_KEYEX_CLIENT_SSH_1 );\n\t\t\tstatus = writeInteger32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t\t keyAgreeParams.publicValueLen );\n\t\t\tINJECT_FAULT( SESSION_CORRUPT_KEYEX_CLIENT,\t\n\t\t\t\t\t\t  SESSION_CORRUPT_KEYEX_CLIENT_SSH_2 );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &keyexPtr, &keyexLength, \n\t\t\t\t\t\t\t\t\t\t keyexLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Send the whole mess to the server.  Since SSH, unlike SSL,\n\t\t   requires that each packet in a multi-packet group be individually\n\t\t   gift-wrapped we have to first assemble the packets via \n\t\t   wrapPacket() and then send them in a group via sendPacket() with\n\t\t   the send-only flag set */\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( keyexPtr != NULL );\n\tCFI_CHECK_UPDATE( \"SSH_MSG_KEXDH_INIT\" );\n\n\t/* Save the MPI-encoded client DH keyex value/octet string-encoded client \n\t   ECDH keyex value for later, when we need to hash it */\n\tREQUIRES( rangeCheck( keyexLength, 1, MAX_ENCODED_KEYEXSIZE ) );\n\tmemcpy( handshakeInfo->clientKeyexValue, keyexPtr, keyexLength );\n\thandshakeInfo->clientKeyexValueLength = keyexLength;\n\n\t/* Set up PKC information while we wait for the server to process our\n\t   response */\n\tsetMessageCreateObjectInfo( &createInfo, handshakeInfo->pubkeyAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsessionInfoPtr->iKeyexAuthContext = createInfo.cryptHandle;\n\tCFI_CHECK_UPDATE( \"IMESSAGE_DEV_CREATEOBJECT\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"processHelloSSH\", \"writeClientHello\", \n\t\t\t\t\t\t\t\t\t\"processDHE\", \"SSH_MSG_KEXDH_INIT\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_DEV_CREATEOBJECT\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Exchange keys with the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int exchangeClientKeys( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tCRYPT_ALGO_TYPE pubkeyAlgo;\n\tSTREAM stream;\n\tMESSAGE_DATA msgData;\n\tvoid *keyPtr DUMMY_INIT_PTR, *keyBlobPtr DUMMY_INIT_PTR;\n\tvoid *sigPtr DUMMY_INIT_PTR;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint keyLength DUMMY_INIT, keyBlobLength, sigLength, length;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Process the DH/ECDH phase 2 keyex packet:\n\n\t  DH + RSA/DSA\n\t\tbyte\t\ttype = SSH_MSG_KEXDH_REPLY / SSH_MSG_KEXDH_GEX_REPLY \n\t\tstring\t\t[ server key/certificate ]\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\t\tmpint\te\t\t\tp\t\t\t\n\t\t\tmpint\tn\t\t\tq\n\t\t\tmpint\t\t\t\tg\n\t\t\tmpint\t\t\t\ty\n\t\tmpint\t\ty'\n\t\tstring\t\t[ signature of handshake data ]\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\t\tstring\tsignature\tsignature\n\n\t   ECDH + ECDSA\n\t\tbyte\t\tSSH_MSG_KEX_ECDH_REPLY\n\t\tstring\t\t[ server key/certificate ]\n\t\t\tstring\t\"ecdsa-sha2-*\"\n\t\t\tstring\t\"*\"\t\t\t\t-- The \"*\" portion from the above field\n\t\t\tstring\tQ\n\t\tstring\t\tq_s\n\t\tstring\t\t[ signature of handshake data ]\n\t\t\tstring\t\"ecdsa-sha2-*\"\n\t\t\tstring\tsignature\n\n\t   SSH_MSG_KEXDH_REPLY (isFixedDH) and SSH_MSG_KEX_ECDH_REPLY (isECDH) \n\t   have the same value so they're handled with the same code.\n\n\t   First, we read and hash the server key/certificate.  Since this is\n\t   already encoded as an SSH string we can hash it directly.\n\n\t   The two bookmarks are for the key as a whole and the \"key blob\" as\n\t   the raw key components that are hashed to create the key fingerprint.\n\t   \n\t   When we read the packet header we set the minimum key size to 512 \n\t   bits instead of MIN_PKCSIZE in order to provide better diagnostics if \n\t   the server is using weak keys since otherwise the data will be \n\t   rejected in the header read long before it gets to the keysize \n\t   check */\n\tstatus = length = \\\n\t\treadHSPacketSSH2( sessionInfoPtr, \n\t\t\t\t\t\t  ( handshakeInfo->isFixedDH || \\\n\t\t\t\t\t\t    handshakeInfo->isECDH ) ? \\\n\t\t\t\t\t\t\tSSH_MSG_KEXDH_REPLY : SSH_MSG_KEX_DH_GEX_REPLY,\n\t\t\t\t\t\t  ID_SIZE + LENGTH_SIZE + sizeofString32( 6 ) + \\\n\t\t\t\t\t\t\tsizeofString32( 1 ) + \\\n\t\t\t\t\t\t\tsizeofString32( bitsToBytes( 512 ) - 4 ) + \\\n\t\t\t\t\t\t\tsizeofString32( bitsToBytes( 512 ) - 4 ) + \\\n\t\t\t\t\t\t\tLENGTH_SIZE + sizeofString32( 6 ) + 40 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstreamBookmarkSet( &stream, keyLength );\n\tstatus = checkReadPublicKey( &stream, &pubkeyAlgo, &keyBlobLength, \n\t\t\t\t\t\t\t\t SESSION_ERRINFO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Key fingerprint data */\n\t\tstatus = streamBookmarkComplete( &stream, &keyBlobPtr, \n\t\t\t\t\t\t\t\t\t\t &keyBlobLength, keyBlobLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Overall key data */\n\t\tstatus = streamBookmarkComplete( &stream, &keyPtr, &keyLength, \n\t\t\t\t\t\t\t\t\t\t keyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\n\t\t/* Some misconfigured servers may use very short keys, we perform\n\t\t   a special-case check for these and return a more specific message\n\t\t   than the generic bad-data response */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure server public key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 server public key data\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tif( pubkeyAlgo != handshakeInfo->pubkeyAlgo )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 public key algorithm %s, expected %s\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\", \n\t\t\t\t  getAlgoName( pubkeyAlgo ), \n\t\t\t\t  getAlgoName( handshakeInfo->pubkeyAlgo ) ) );\n\t\t}\n#ifndef CONFIG_FUZZ\n\tsetMessageData( &msgData, keyPtr, keyLength );\n\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( cryptArgError( status ) ? \\\n\t\t\t\tCRYPT_ERROR_BADDATA : status,\n\t\t\t\t( cryptArgError( status ) ? \\\n\t\t\t\t  CRYPT_ERROR_BADDATA : status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 server public key value\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tANALYSER_HINT( keyBlobPtr != NULL );\n\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, keyPtr, keyLength );\n#endif /* CONFIG_FUZZ */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The fingerprint is computed from the \"key blob\" which is\n\t\t   different from the server key.  The server key is the full key\n\t\t   while the \"key blob\" is only the raw key components (e, n for\n\t\t   RSA, p, q, g, y for DSA).  Note that, as with the old PGP 2.x key\n\t\t   hash mechanism, this allows key spoofing (although it isn't quite\n\t\t   as bad as the PGP 2.x key fingerprint mechanism) since it doesn't\n\t\t   hash an indication of the key type or format */\n\t\tstatus = processKeyFingerprint( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tkeyBlobPtr, keyBlobLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"SSH_MSG_KEXDH_REPLY\" );\n\n\t/* Read the server DH/ECDH keyex value and complete the DH/ECDH key \n\t   agreement */\n\tstatus = readRawObject32( &stream, handshakeInfo->serverKeyexValue,\n\t\t\t\t\t\t\t  MAX_ENCODED_KEYEXSIZE,\n\t\t\t\t\t\t\t  &handshakeInfo->serverKeyexValueLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 keyex value\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tif( handshakeInfo->isECDH )\n\t\t{\n\t\tif( !isValidECDHsize( handshakeInfo->serverKeyexValueLength,\n\t\t\t\t\t\t\t  handshakeInfo->serverKeySize, \n\t\t\t\t\t\t\t  LENGTH_SIZE ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\telse\n\t\t{\n\t\tif( !isValidDHsize( handshakeInfo->serverKeyexValueLength,\n\t\t\t\t\t\t\thandshakeInfo->serverKeySize, \n\t\t\t\t\t\t\tLENGTH_SIZE ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tconst int serverKeyexSize = handshakeInfo->isECDH ? \\\n\t\t\textractECDHsize( handshakeInfo->serverKeyexValueLength, LENGTH_SIZE ) : \\\n\t\t\textractDHsize( handshakeInfo->serverKeyexValueLength, LENGTH_SIZE );\n\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 keyex size, expected %d (%d), \"\n\t\t\t\t  \"got %d (%d)\", handshakeInfo->isECDH ? \"ECDH\" : \"DH\",\n\t\t\t\t  handshakeInfo->serverKeySize, \n\t\t\t\t  handshakeInfo->serverKeySize * 8, \n\t\t\t\t  serverKeyexSize, serverKeyexSize * 8 ) );\n\t\t}\n\tstatus = completeKeyex( sessionInfoPtr, handshakeInfo, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"completeKeyex\" );\n\n\t/* Prepare to process the handshake packet signature (\"What are you \n\t   preparing?! You're always preparing! Just go!\") */\n\tstreamBookmarkSet( &stream, sigLength );\n\tstatus = length = readUint32( &stream );\n\tif( !cryptStatusError( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( !cryptStatusError( status ) )\n\t\tstatus = sSkip( &stream, length, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &sigPtr, &sigLength, \n\t\t\t\t\t\t\t\t\t\t sigLength );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 2 packet signature data\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tANALYSER_HINT( sigPtr != NULL );\n\n\t/* Since there are no crypto contexts set up during fuzzing, we can't go \n\t   any further */\n\tFUZZ_EXIT();\n\n\t/* Some implementations incorrectly format the signature packet,\n\t   omitting the algorithm name and signature blob length for DSA sigs\n\t   (that is, they just encode two 20-byte values instead of a properly-\n\t   formatted signature):\n\n\t\t\t\tRight\t\t\t\t\t\t\tWrong\n\t\tstring\t\t[ signature data ]\t\tstring\t[ nothing ]\n\t\t\tstring\t\"ssh-dss\"\n\t\t\tstring\tsignature\t\t\t\t\t\tsignature\n\n\t   If we're talking to one of these versions we check to see whether the \n\t   packet is correctly formatted (that is, that it has the algorithm-\n\t   type string present as required) and if it isn't present rewrite it \n\t   into the correct form so that we can verify the signature.  This \n\t   check requires that the signature format be one of the SSH standard \n\t   types but since we can't (by definition) handle proprietary formats \n\t   this isn't a problem.  What we're specifically checking for here is \n\t   the *absence* of any known algorithm string, if any known string \n\t   (even one for a format that we can't handle) is present then the\n\t   signature is in the correct format, it's only if we don't find a\n\t   match for any known string that we have to rewrite the signature */\n#ifdef USE_DSA\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_SIGFORMAT ) && \\\n\t\t( pubkeyAlgo == CRYPT_ALGO_DSA ) && \\\n\t\t( memcmp( ( BYTE * ) sigPtr + LENGTH_SIZE + LENGTH_SIZE,\n\t\t\t\t  \"ssh-dss\", 7 ) && \\\n\t\t  memcmp( ( BYTE * ) sigPtr + LENGTH_SIZE + LENGTH_SIZE,\n\t\t\t\t  \"x509v3-sign-dss\", 15 ) && \\\n\t\t  memcmp( ( BYTE * ) sigPtr + LENGTH_SIZE + LENGTH_SIZE,\n\t\t\t\t  \"spki-sign-dss\", 13 ) && \\\n\t\t  memcmp( ( BYTE * ) sigPtr + LENGTH_SIZE + LENGTH_SIZE,\n\t\t\t\t  \"pgp-sign-dss\", 12 ) ) )\n\t\t{\n\t\tint fixedSigLength DUMMY_INIT;\n\n\t\t/* Rewrite the signature to fix up the overall length at the start \n\t\t   and insert the algorithm name and signature length.  We can \n\t\t   safely reuse the receive buffer for this because the start \n\t\t   contains the complete server key/certificate and DH keyex value \n\t\t   which is far longer than the 12 bytes of header plus signature \n\t\t   that we'll be writing there */\n\t\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t  LENGTH_SIZE + sizeofString32( 7 ) + sigLength );\n\t\twriteUint32( &stream, sizeofString32( 7 ) + sigLength );\n\t\twriteString32( &stream, \"ssh-dss\", 7 );\n\t\tstatus = swrite( &stream, sigPtr, sigLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tfixedSigLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* The rewritten signature is now at the start of the buffer, update\n\t\t   the signature pointer and size to accomodate the added header */\n\t\tsigPtr = sessionInfoPtr->receiveBuffer;\n\t\tsigLength = fixedSigLength;\n\t\t}\n#endif /* USE_DSA */\n\n\t/* Finally, verify the server's signature on the exchange hash */\n\tstatus = iCryptCheckSignature( sigPtr, sigLength, CRYPT_IFORMAT_SSH,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->iKeyexAuthContext,\n\t\t\t\t\t\t\t\t   handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t\t\t   CRYPT_UNUSED, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid handshake data signature\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"iCryptCheckSignature\" );\n\n\t/* We don't need the exchange hash contexts any more, get rid of them */\n\tkrnlSendNotifier( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\thandshakeInfo->iExchangeHashContext = CRYPT_ERROR;\n\tif( handshakeInfo->iExchangeHashAltContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->iExchangeHashAltContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->iExchangeHashAltContext = CRYPT_ERROR;\n\t\t}\n\tCFI_CHECK_UPDATE( \"cleanup\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"SSH_MSG_KEXDH_REPLY\", \"completeKeyex\", \n\t\t\t\t\t\t\t\t\t\"iCryptCheckSignature\", \"cleanup\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete the handshake with the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int completeClientHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\tINOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM stream;\n\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint stringLength, packetOffset, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Set up the security information required for the session */\n\tstatus = initSecurityInfo( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"initSecurityInfo\" );\n\n\t/* Build our change cipherspec message and request authentication with\n\t   the server:\n\n\t\tbyte\ttype = SSH_MSG_NEWKEYS\n\t\t...\n\n\t   After this point the write channel is in the secure state, so we \n\t   switch from wrapPlaintextPacketSSH2() to wrapPacketSSH2() */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, SSH_MSG_NEWKEYS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE );\n\tCFI_CHECK_UPDATE( \"SSH_MSG_NEWKEYS\" );\n\n#if 0\n\t/*   byte       SSH_MSG_EXT_INFO\n\t     uint32     nr-extensions\n\t       string   extension-name\n\t       string   extension-value (binary) */\n\tstatus = continuePacketStreamSSH( &stream, SSH_MSG_EXT_INFO, \n\t\t\t\t\t\t\t\t\t  &packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\twriteUint32( &stream, 1 );\n\t\twriteString32( &stream, \"global-requests-ok\", 18 );\n\t\tstatus = writeUint32( &stream, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, packetOffset, \n\t\t\t\t\t\t\t\t FALSE );\n\t\t}\n#endif /* Test handling of trigger for global request after authentication */ \n\n\t/*\t...\n\t\tbyte\ttype = SSH_MSG_SERVICE_REQUEST\n\t\tstring\tservice_name = \"ssh-userauth\".\n\t\t\n\t   For some reason SSH requires the use of two authentication messages, \n\t   an \"I'm about to authenticate\" packet and an \"I'm authenticating\" \n\t   packet, so we have to perform the authentication in two parts (dum \n\t   loquimur, fugerit invida aetas) */\n\tstatus = continuePacketStreamSSH( &stream, SSH_MSG_SERVICE_REQUEST,\n\t\t\t\t\t\t\t\t\t  &packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeString32( &stream, \"ssh-userauth\", 12 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, packetOffset, \n\t\t\t\t\t\t\t\t FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"SSH_MSG_SERVICE_REQUEST\" );\n\n\t/* Send the whole mess to the server.  This is yet another place where \n\t   the SSH spec's vagueness over message ordering causes problems.  SSL \n\t   at this point uses a Finished message in which the client and server \n\t   do a mutual proof-of-possession of encryption and MAC keys via a \n\t   pipeline-stalling message that prevents any further (sensitive) data \n\t   from being exchanged until the PoP has concluded (the SSL Finished \n\t   also authenticates the handshake messages) but SSH doesn't have any\n\t   such requirements.  The signed exchange hash from the server proves \n\t   to the client that the server knows the master secret but not \n\t   necessarily that the client and server share encryption and MAC keys.  \n\t   Without this mutual PoP the client could potentially end up sending \n\t   passwords to the server using an incorrect (and potentially weak) key \n\t   if it's messed up and derived the key incorrectly.  Although mutual \n\t   PoP isn't a design goal of the SSH handshake we do it anyway (as far \n\t   as we can without a proper Finished message), although this \n\t   introduces a pipeline stall at this point.\n\t   \n\t   In addition because of the aforementioned ambiguity over message \n\t   ordering we have to send our change cipherspec first because some \n\t   implementations will stop and wait before they send their one, so if \n\t   they don't see our one first they lock up.  To make this even more \n\t   entertaining these are typically older ssh.com implementations with a \n\t   whole smorgasbord of handshaking and crypto bugs, because of the lack \n\t   of PoP and the fact that we have to send the first encrypted/MACd\n\t   message, encountering any of these bugs results in garbage from the\n\t   server followed by a closed connection with no ability to diagnose \n\t   the problem.\n\n\t   Complicating things even further is the fact that the SSH extension\n\t   request is sent immediately after the change cipherspec, before\n\t   receiving confirmation that that crypto has been correctly set up.\n\t   This is because of some vague desire to provide for the insertion\n\t   of extensions before the userauth is performed in case there's a \n\t   need to exchange extensions that may affect the authentication \n\t   process.  What this applies to in practice is \"server-sig-algs\",\n\t   which defines the algorithms that the server will accept for \n\t   \"publickey\"-format userauth.\n\n\t   The spec in fact says that after a key exchange with implicit server \n\t   authentication the client has to wait for the server to send a \n\t   service-accept packet before continuing, however it never explains \n\t   what implicit (and, by extension, explicit) server authentication \n\t   actually are.  This text is a leftover from an extremely early SSH \n\t   draft in which the only keyex mechanism was \"double-encrypting-sha\", \n\t   a mechanism that required a pipeline stall at this point because the \n\t   client wasn't able to authenticate the server until it received the \n\t   first encrypted/MAC'ed message from it.  To extricate ourselves from \n\t   the confusion due to the missing definition we could define \"implicit \n\t   authentication\" to be \"Something completely different from what we're \n\t   doing here\" which means that we could send the two packets together \n\t   without having to wait for the server, but it's probably better to \n\t   use SSL-tyle Finished semantics at this point even if it adds an \n\t   extra RTT delay */\n\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Wait for the server's change cipherspec message.  From this point\n\t   on the read channel is also in the secure state */\n\tstatus = readHSPacketSSH2( sessionInfoPtr, SSH_MSG_NEWKEYS, ID_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ );\n\tCFI_CHECK_UPDATE( \"readHSPacketSSH2\" );\n\n\t/* Wait for the server's service-accept message that should follow in\n\t   response to the service request sent after out change cipherspec.  \n\t   Some buggy versions send an empty service-accept packet so we only \n\t   check the contents if it's a correctly-formatted packet */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t   SSH_PFLAG_EMPTYSVCACCEPT ) )\n\t\t{\n\t\t/* It's a buggy implementation, just check for the presence of a \n\t\t   packet without looking at the contents */\n\t\tstatus = readHSPacketSSH2( sessionInfoPtr, SSH_MSG_SERVICE_ACCEPT, \n\t\t\t\t\t\t\t\t   ID_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* This is the first message after the change cipherspec, a \n\t\t\t   basic packet format error is more likely to be due to an \n\t\t\t   incorrect key than an actual format error */\n\t\t\tretExtErr( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t   ( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t SESSION_ERRINFO, \n\t\t\t\t\t\t \"Invalid packet data for SSH_MSG_SERVICE_ACCEPT, \"\n\t\t\t\t\t\t \"probably due to incorrect encryption keys being \"\n\t\t\t\t\t\t \"negotiated during the handshake:\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tint length;\n\n\t\t/* Check the service-accept packet:\n\n\t\t\tbyte\ttype = SSH_MSG_SERVICE_ACCEPT\n\t\t\tstring\tservice_name = \"ssh-userauth\".\n\t\t\t\n\t\t   This may also be an extension info packet if the server is using \n\t\t   extensions: \n\t\t   \n\t\t\tbyte\t\ttype = SSH_MSG_EXT_INFO\n\t\t\tuint32\t\tno_extensions\n\t\t\t\tstring\tname\n\t\t\t\tstring\tvalue (binary data) */\n\t\tstatus = length = \\\n\t\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_SPECIAL_SERVICEACCEPT,\n\t\t\t\t\t\t\t  ID_SIZE + UINT32_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* This is the first message after the change cipherspec, a \n\t\t\t   basic packet format error is more likely to be due to an \n\t\t\t   incorrect key than an actual format error */\n\t\t\tretExtErr( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t   ( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t SESSION_ERRINFO, \n\t\t\t\t\t\t \"Invalid packet data for SSH_MSG_SERVICE_ACCEPT, \"\n\t\t\t\t\t\t \"probably due to incorrect encryption keys being \"\n\t\t\t\t\t\t \"negotiated during the handshake:\" ) );\n\t\t\t}\n\t\tif( sessionInfoPtr->sessionSSH->packetType == SSH_MSG_EXT_INFO )\n\t\t\t{\n\t\t\t/* The server sent extension information, process it */\n\t\t\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\t\t\tstatus = readExtensionsSSH( sessionInfoPtr, &stream );\n\t\t\tsMemDisconnect( &stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Retry the service-accept read */\n\t\t\tstatus = length = \\\n\t\t\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_SERVICE_ACCEPT,\n\t\t\t\t\t\t\t\t  ID_SIZE + sizeofString32( 8 ) );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\t\tstatus = readString32( &stream, stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   &stringLength );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tstringLength != 12 || \\\n\t\t\tmemcmp( stringBuffer, \"ssh-userauth\", 12 ) )\n\t\t\t{\n\t\t\t/* More of a sanity check than anything else, the MAC should \n\t\t\t   have caught any keying problems */\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid service accept packet\" ) );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"serviceAccept\" );\n\n\t/* Try and authenticate ourselves to the server */\n\tstatus = processClientAuth( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processClientAuth\" );\n\n\t/* We've finally made it through all of the formalities (post proelia\n\t   praemia), create (if necessary) and open a channel */\n\tif( getCurrentChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t CHANNEL_READ ) == UNUSED_CHANNEL_NO )\n\t\t{\n\t\t/* The user hasn't specified any channel details, create a\n\t\t   channel of the default type */\n\t\tstatus = createChannel( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#if 1\n\tstatus = sendChannelOpen( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"sendChannelOpen\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_7( \"initSecurityInfo\", \"SSH_MSG_NEWKEYS\",\n\t\t\t\t\t\t\t\t\t\"SSH_MSG_SERVICE_REQUEST\", \n\t\t\t\t\t\t\t\t\t\"readHSPacketSSH2\", \"serviceAccept\",\n\t\t\t\t\t\t\t\t\t\"processClientAuth\", \n\t\t\t\t\t\t\t\t\t\"sendChannelOpen\" ) );\n\treturn( CRYPT_OK );\n#else\t/* Test handling of OpenSSH \"no-more-sessions@openssh.com\" */\n\tstatus = sendChannelOpen( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* byte\ttype = SSH_MSG_GLOBAL_REQUEST\n\t   string\trequest_name = \"no-more-sessions@openssh.com\"\n\t   boolean\twant_reply = FALSE */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\t  SSH_MSG_GLOBAL_REQUEST );\n\twriteString32( &stream, \"no-more-sessions@openssh.com\", 29 );\n\tsputc( &stream, 0 );\n\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, 0, TRUE, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream, TRUE );\n\tsMemDisconnect( &stream );\n\treturn( status );\n#endif /* 0 */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2clientProcessing( INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tFNPTR_SET( handshakeInfo->beginHandshake, beginClientHandshake );\n\tFNPTR_SET( handshakeInfo->exchangeKeys, exchangeClientKeys );\n\tFNPTR_SET( handshakeInfo->completeHandshake, completeClientHandshake );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_crypt.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib SSHv2 Crypto Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some versions of SSH want to use AES-CTR instead of AES-CBC, which is a \n   pain to deal with because it's not a standard encryption mode for\n   cryptlib (or many other crypto libraries/hardware).  To deal with this we \n   synthesise it from ECB mode.  This is possible because the spec requires\n   that the data size still be padded out to the cipher's block size, so \n   it's really just a stream-mode conversion of ECB */\n\n#ifdef USE_SSH_CTR\n\n#define KSG_BUFFER_SIZE\t\t512\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int incCtr( INOUT_BUFFER_FIXED( blockSize ) void *ctr,\n\t\t\t\t   IN_LENGTH_IV const int blockSize )\n\t{\n\tBYTE *ctrPtr = ctr, ctrMSB, ctrMSBnext;\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES( blockSize >= MIN_IVSIZE && blockSize <= CRYPT_MAX_IVSIZE );\n\n\t/* Since CTR-mode is an RC4-style stream cipher, it has the same \n\t   catastrophic failure mode if the keystream is ever reused.  To try \n\t   and guard against this, we check that the counter is being \n\t   incremented, or at least changed, on each call */\n\tctrMSB = ctrPtr[ blockSize - 1 ];\n\tctrMSBnext = ctrPtr[ blockSize - 2 ];\n\n\t/* Walk along the counter incrementing each byte if required */\n\tLOOP_MED( i = blockSize - 1, i >= 0, i-- )\n\t\t{\n         if (++ctrPtr[i] != 0)\n\t\t\tbreak;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( ctrMSB != ctrPtr[ blockSize - 1 ] );\n    ENSURES((ctrPtr[blockSize - 1] != 0 || ctrMSBnext != ctrPtr[blockSize - 2]));\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nint ctrModeCrypt( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t  INOUT_BUFFER_FIXED( blockSize ) void *counter,\n\t\t\t\t  IN_LENGTH_IV const int counterSize,\n\t\t\t\t  INOUT_BUFFER_FIXED( dataLength ) void *data,\n\t\t\t\t  IN_LENGTH const int dataLength )\n\t{\n\tBYTE ksgBuffer[ KSG_BUFFER_SIZE + 8 ];\n\tBYTE *dataPtr = data;\n\tint length, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( counter, counterSize ) );\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( counterSize >= MIN_IVSIZE && counterSize <= CRYPT_MAX_IVSIZE );\n\tREQUIRES( isIntegerRangeNZ( dataLength ) );\n\n\t/* Encrypt/decrypt the data in CTR mode KSG_BUFFER_SIZE bytes at a \n\t   time */\n\tLOOP_LARGE_INITCHECK( length = dataLength, length > 0 )\n\t\t{\n\t\tconst int ksgLen = min( length, KSG_BUFFER_SIZE );\n\t\tint i, status, LOOP_ITERATOR_ALT;\n\n\t\t/* Fill the KSG buffer with the counter values and encrypt them in\n\t\t   ECB mode to get the CTR cipher stream */\n\t\tLOOP_EXT_ALT( i = 0, i < ksgLen, i += counterSize, KSG_BUFFER_SIZE + 1 )\n\t\t\t{\n\t\t\tREQUIRES( boundsCheckZ( i, counterSize, KSG_BUFFER_SIZE ) );\n\t\t\tmemcpy( ksgBuffer + i, counter, counterSize );\n\t\t\tstatus = incCtr( counter, counterSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tzeroise( ksgBuffer, KSG_BUFFER_SIZE );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  ksgBuffer, ksgLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( ksgBuffer, KSG_BUFFER_SIZE );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Mask/unmask the data with the KSG buffer contents and move on to \n\t\t   the next block */\n\t\tLOOP_EXT_ALT( i = 0, i < ksgLen, i++, KSG_BUFFER_SIZE + 1 )\n\t\t\tdataPtr[ i ] ^= ksgBuffer[ i ];\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tdataPtr += ksgLen;\n\t\tlength -= ksgLen;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* Clean up */\n\tzeroise( ksgBuffer, KSG_BUFFER_SIZE );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH_CTR */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey Load/Init Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load a DH key into a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initDHcontextSSH( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t  OUT_LENGTH_SHORT_Z int *keySize,\n\t\t\t\t\t  IN_BUFFER_OPT( keyDataLength ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int keyDataLength,\n\t\t\t\t\t  IN_LENGTH_SHORT_OPT const int requestedKeySize )\n\t{\n\tCRYPT_CONTEXT iDHContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tint keyLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( keySize, sizeof( int ) ) );\n\tassert( ( isReadPtrDynamic( keyData, keyDataLength ) && \\\n\t\t\t  requestedKeySize == CRYPT_UNUSED ) || \\\n\t\t\t( keyData == NULL && keyDataLength == 0 && \\\n\t\t\t  requestedKeySize >= MIN_PKCSIZE && \\\n\t\t\t  requestedKeySize <= CRYPT_MAX_PKCSIZE ) );\n\n\tREQUIRES( ( keyData != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( keyDataLength ) && \\\n\t\t\t\trequestedKeySize == CRYPT_UNUSED ) || \\\n\t\t\t  ( keyData == NULL && keyDataLength == 0 && \\\n\t\t\t\trequestedKeySize >= MIN_PKCSIZE && \\\n\t\t\t\trequestedKeySize <= CRYPT_MAX_PKCSIZE ) );\n\n\t/* Clear return values */\n\t*iCryptContext = CRYPT_ERROR;\n\t*keySize = 0;\n\n\t/* Create the DH context to contain the key */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DH );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiDHContext = createInfo.cryptHandle;\n\tsetMessageData( &msgData, \"SSH DH key\", 10 );\n\tstatus = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iDHContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* If we're not being given externally-supplied DH key components, get \n\t   the actual key size based on the requested key size */\n\tif( keyData == NULL )\n\t\t{\n\t\tstatus = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &requestedKeySize, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_DLPPARAM );\n\t\t}\n\telse\n\t\t{\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength );\n\t\tstatus = krnlSendMessage( iDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iDHContext, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &keyLength, CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we're trying to load the context from stored data and the load \n\t\t   fails, record the fact that there's a problem */\n\t\tif( keyData == NULL )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't create DH context from stored data\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\t}\n\t\tkrnlSendNotifier( iDHContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iCryptContext = iDHContext;\n\t*keySize = keyLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_ECDH\n\n/* Load one of the fixed SSH ECDH keys into a context.  Since there's no SSH\n   format defined for this, we use the SSL format */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initECDHcontextSSH( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *keySize,\n\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_CONTEXT iECDHContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tstatic const int eccKeySize = CRYPT_ECCCURVE_P256;\n\tint status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isWritePtr( keySize, sizeof( int ) ) );\n\n\tREQUIRES( cryptAlgo == CRYPT_ALGO_ECDH );\n\n\t/* Clear return values */\n\t*iCryptContext = CRYPT_ERROR;\n\t*keySize = 0;\n\n\t/* Create the ECDH context to contain the key */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_ECDH );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiECDHContext = createInfo.cryptHandle;\n\tsetMessageData( &msgData, \"SSH ECDH key\", 12 );\n\tstatus = krnlSendMessage( iECDHContext, IMESSAGE_SETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iECDHContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the appropriate static ECDH key parameters */\n\tstatus = krnlSendMessage( iECDHContext, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &eccKeySize, \n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_DLPPARAM );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iECDHContext, IMESSAGE_DECREFCOUNT );\n\n\t\t/* We got an error loading a known-good, fixed-format key, report \n\t\t   the problem as an internal error rather than (say) a bad-data \n\t\t   error */\n\t\tretIntError();\n\t\t}\n\t*iCryptContext = iECDHContext;\n\t*keySize = bitsToBytes( 256 );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_ECDH */\n\n/* Complete the hashing necessary to generate a cryptovariable and send it\n   to a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4, 6, 7, 9 ) ) \\\nstatic int loadCryptovariable( IN_HANDLE const CRYPT_CONTEXT iCryptContext,\n\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE attribute,\n\t\t\t\t\t\t\t   IN_RANGE( 8, 40 ) const int attributeSize, \n\t\t\t\t\t\t\t   const HASH_FUNCTION hashFunction,\n\t\t\t\t\t\t\t   IN_RANGE( 20, 32 ) const int hashSize,\n\t\t\t\t\t\t\t   const HASHINFO initialHashInfo, \n\t\t\t\t\t\t\t   IN_BUFFER( nonceLen ) const BYTE *nonce, \n\t\t\t\t\t\t\t   IN_RANGE( 1, 4 ) const int nonceLen,\n\t\t\t\t\t\t\t   IN_BUFFER( dataLen ) const BYTE *data, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tHASHINFO hashInfo;\n\tBYTE buffer[ CRYPT_MAX_KEYSIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtr( initialHashInfo, sizeof( HASHINFO ) ) );\n\tassert( isReadPtrDynamic( nonce, nonceLen ) );\n\tassert( isReadPtrDynamic( data, dataLen ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( attribute == CRYPT_CTXINFO_IV || \\\n\t\t\t  attribute == CRYPT_CTXINFO_KEY );\n\tREQUIRES( attributeSize >= 8 && attributeSize <= 40 );\n\tREQUIRES( hashFunction != NULL );\n\tREQUIRES( hashSize == 20 || hashSize == 32 );\n\tREQUIRES( nonceLen >= 1 && nonceLen <= 4 );\n\tREQUIRES( isShortIntegerRangeNZ( dataLen ) );\n\n\tstatic_assert( CRYPT_MAX_KEYSIZE >= CRYPT_MAX_HASHSIZE * 2,\n\t\t\t\t   \"Key size buffer as hash target\" );\n\n\t/* Complete the hashing */\n\tmemcpy( hashInfo, initialHashInfo, sizeof( HASHINFO ) );\n\thashFunction( hashInfo, NULL, 0, nonce, nonceLen, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, buffer, CRYPT_MAX_HASHSIZE, data, dataLen, \n\t\t\t\t  HASH_STATE_END );\n\tif( attributeSize > hashSize )\n\t\t{\n\t\t/* If we need more data than the hashing will provide in one go,\n\t\t   generate a second block as:\n\n\t\t\thash( shared_secret || exchange_hash || data )\n\n\t\t   where the shared secret and exchange hash are present as the\n\t\t   precomputed data in the initial hash information and the data \n\t\t   part is the output of the hash step above */\n\t\tmemcpy( hashInfo, initialHashInfo, sizeof( HASHINFO ) );\n\t\thashFunction( hashInfo, buffer + hashSize, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t  buffer, hashSize, HASH_STATE_END );\n\t\t}\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\n\t/* Send the data to the context */\n\tsetMessageData( &msgData, buffer, attributeSize );\n\tstatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, attribute );\n\tzeroise( buffer, CRYPT_MAX_KEYSIZE );\n\n\treturn( status );\n\t}\n\n#ifdef USE_SSH_CTR\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5, 7 ) ) \\\nstatic int loadCTR( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\tconst HASH_FUNCTION hashFunction,\n\t\t\t\t\tIN_RANGE( 20, 32 ) const int hashSize,\n\t\t\t\t\tconst HASHINFO initialHashInfo, \n\t\t\t\t\tIN_BUFFER( nonceLen ) const BYTE *nonce, \n\t\t\t\t\tIN_RANGE( 1, 4 ) const int nonceLen,\n\t\t\t\t\tIN_BUFFER( dataLen ) const BYTE *data, \n\t\t\t\t\tIN_LENGTH_SHORT const int dataLen,\n\t\t\t\t\tconst BOOLEAN isWriteCTR )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tHASHINFO hashInfo;\n\tBYTE buffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( initialHashInfo, sizeof( HASHINFO ) ) );\n\tassert( isReadPtrDynamic( nonce, nonceLen ) );\n\tassert( isReadPtrDynamic( data, dataLen ) );\n\n\tREQUIRES( hashFunction != NULL );\n\tREQUIRES( hashSize == 20 || hashSize == 32 );\n\tREQUIRES( nonceLen >= 1 && nonceLen <= 4 );\n\tREQUIRES( isShortIntegerRangeNZ( dataLen ) );\n\tREQUIRES( isWriteCTR == TRUE || isWriteCTR == FALSE );\n\n\t/* Complete the hashing */\n\tmemcpy( hashInfo, initialHashInfo, sizeof( HASHINFO ) );\n\thashFunction( hashInfo, NULL, 0, nonce, nonceLen, HASH_STATE_CONTINUE );\n\thashFunction( hashInfo, buffer, CRYPT_MAX_HASHSIZE, data, dataLen, \n\t\t\t\t  HASH_STATE_END );\n\tzeroise( hashInfo, sizeof( HASHINFO ) );\n\n\t/* Send the data to the context */\n\tif( isWriteCTR )\n\t\tmemcpy( sshInfo->writeCTR, buffer, sessionInfoPtr->cryptBlocksize );\n\telse\n\t\tmemcpy( sshInfo->readCTR, buffer, sessionInfoPtr->cryptBlocksize );\n    zeroise(buffer, CRYPT_MAX_HASHSIZE);\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH_CTR */\n\n/* Initialise and destroy the security contexts */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSecurityContextsSSH( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\tsetMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n#ifdef USE_SSH_CTR\n\tif( cryptStatusOK( status ) && \\\n\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t{\n\t\tstatic const int mode = CRYPT_MODE_ECB;\t/* int vs.enum */\n\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\t\t}\n#endif /* USE_SSH_CTR */\n\tif( cryptStatusOK( status ) && handshakeInfo->cryptKeysize != 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &handshakeInfo->cryptKeysize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsessionInfoPtr->iCryptInContext = createInfo.cryptHandle;\n\t\tsetMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t}\n#ifdef USE_SSH_CTR\n\tif( cryptStatusOK( status ) && \\\n\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t{\n\t\tstatic const int mode = CRYPT_MODE_ECB;\t/* int vs.enum */\n\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\t\t}\n#endif /* USE_SSH_CTR */\n\tif( cryptStatusOK( status ) && handshakeInfo->cryptKeysize != 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  &handshakeInfo->cryptKeysize,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;\n\t\tkrnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE, &sessionInfoPtr->cryptBlocksize,\n\t\t\t\t\t\t CRYPT_CTXINFO_BLOCKSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageCreateObjectInfo( &createInfo, sessionInfoPtr->integrityAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsessionInfoPtr->iAuthInContext = createInfo.cryptHandle;\n\t\t\tsetMessageCreateObjectInfo( &createInfo,\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->integrityAlgo );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;\n\t\t\tkrnlSendMessage( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t &sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t\t CRYPT_CTXINFO_BLOCKSIZE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* One or more of the contexts couldn't be created, destroy all the\n\t\t   contexts created so far */\n\t\tdestroySecurityContextsSSH( sessionInfoPtr );\n\t\t}\n\treturn( status );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySecurityContextsSSH( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Destroy any active contexts */\n\tif( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCryptInContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCryptOutContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iAuthInContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iAuthOutContext = CRYPT_ERROR;\n\t\t}\n\t}\n\n/* Set up the security information required for the session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initSecurityInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tHASH_FUNCTION hashFunction;\n\tHASHINFO initialHashInfo;\n\tconst BOOLEAN isClient = isServer( sessionInfoPtr ) ? FALSE : TRUE;\n\tint keySize, hashSize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Create the security contexts required for the session */\n\tstatus = initSecurityContextsSSH( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Get the hash algorithm information and pre-hash the shared secret and\n\t   exchange hash, which are re-used for all cryptovariables.  The\n\t   overall hashing is:\n\n\t\thash( MPI( shared_secret ) || exchange_hash || \\\n\t\t\t  nonce || exchange_hash )\n\n\t   Note the apparently redundant double hashing of the exchange hash,\n\t   this is required because the spec refers to it by two different names,\n\t   the exchange hash and the session ID, and then requires that both be\n\t   hashed (actually it's a bit more complex than that with issues \n\t   related to re-keying but for now it acts as a re-hash of the same\n\t   data).\n\n\t   Before we can hash the shared secret we have to convert it into MPI\n\t   form, which we do by generating a pseudo-header and hashing that\n\t   separately.  The nonce is \"A\", \"B\", \"C\", ... */\n\tgetHashParameters( handshakeInfo->exchangeHashAlgo, 0, &hashFunction, \n\t\t\t\t\t   &hashSize );\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t   SSH_PFLAG_NOHASHSECRET ) )\n\t\t{\n\t\t/* Some implementations erroneously omit the shared secret when\n\t\t   creating the keying material.  This is suboptimal but not fatal,\n\t\t   since the shared secret is also hashed into the exchange hash */\n\t\thashFunction( initialHashInfo, NULL, 0, handshakeInfo->sessionID,\n\t\t\t\t\t  handshakeInfo->sessionIDlength, HASH_STATE_START );\n\t\t}\n\telse\n\t\t{\n\t\tSTREAM stream;\n\t\tBYTE header[ 8 + 8 ];\n\t\tconst int mpiLength = ( handshakeInfo->secretValue[ 0 ] & 0x80 ) ? \\\n\t\t\t\t\t\t\t\thandshakeInfo->secretValueLength + 1 : \\\n\t\t\t\t\t\t\t\thandshakeInfo->secretValueLength;\n\t\tint headerLength DUMMY_INIT;\n\n\t\t/* Hash the shared secret as an MPI.  We can't use hashAsMPI() for\n\t\t   this because it works with contexts rather than the internal hash\n\t\t   functions used here */\n\t\tsMemOpen( &stream, header, 8 );\n\t\tstatus = writeUint32( &stream, mpiLength );\n\t\tif( handshakeInfo->secretValue[ 0 ] & 0x80 )\n\t\t\t{\n\t\t\t/* MPIs are signed values */\n\t\t\tstatus = sputc( &stream, 0 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\theaderLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thashFunction( initialHashInfo, NULL, 0, header, headerLength,\n\t\t\t\t\t  HASH_STATE_START );\n\t\thashFunction( initialHashInfo, NULL, 0, handshakeInfo->secretValue,\n\t\t\t\t\t  handshakeInfo->secretValueLength, HASH_STATE_CONTINUE );\n\t\thashFunction( initialHashInfo, NULL, 0, handshakeInfo->sessionID,\n\t\t\t\t\t  handshakeInfo->sessionIDlength, HASH_STATE_CONTINUE );\n\t\t}\n\n\t/* Load the cryptovariables.  The order is:\n\n\t\tclient_write_iv, server_write_iv\n\t\tclient_write_key, server_write_key\n\t\tclient_write_mac, server_write_mac\n\n\t   Although HMAC has a variable-length key and should therefore follow\n\t   the SSH2_FIXED_KEY_SIZE rule, the key size was in later RFC drafts\n\t   set to the HMAC block size.  Some implementations erroneously use\n\t   the fixed-size key, so we adjust the HMAC key size if we're talking\n\t   to one of these */\n\tif( !isStreamCipher( sessionInfoPtr->cryptAlgo ) )\n\t\t{\n#ifdef USE_SSH_CTR\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t\t{\n\t\t\tstatus = loadCTR( sessionInfoPtr, hashFunction, hashSize, \n\t\t\t\t\t\t\tinitialHashInfo, MKDATA( \"A\" ), 1,\n\t\t\t\t\t\t\thandshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength,\n\t\t\t\t\t\t\tisClient ? TRUE : FALSE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = loadCTR( sessionInfoPtr, hashFunction, hashSize, \n\t\t\t\t\t\t\tinitialHashInfo, MKDATA( \"B\" ), 1,\n\t\t\t\t\t\t\thandshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength,\n\t\t\t\t\t\t\tisClient ? FALSE : TRUE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n#endif /* USE_SSH_CTR */\n\t\t\t{\n\t\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_IV, sessionInfoPtr->cryptBlocksize, \n\t\t\t\t\t\t\thashFunction, hashSize, initialHashInfo, \n\t\t\t\t\t\t\tMKDATA( \"A\" ), 1, handshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_IV, sessionInfoPtr->cryptBlocksize, \n\t\t\t\t\t\t\thashFunction, hashSize, initialHashInfo, \n\t\t\t\t\t\t\tMKDATA( \"B\" ), 1, handshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY, keySize, hashFunction, \n\t\t\t\t\t\t\thashSize, initialHashInfo, MKDATA( \"C\" ), 1,\n\t\t\t\t\t\t\thandshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY, keySize, hashFunction, \n\t\t\t\t\t\t\thashSize, initialHashInfo, MKDATA( \"D\" ), 1,\n\t\t\t\t\t\t\thandshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthOutContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \\\n\t\t\t\t\t\t\t\t\t   SSH_PFLAG_HMACKEYSIZE ) ? \\\n\t\t\t\t\t\t\t\tSSH2_FIXED_KEY_SIZE : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t\thashFunction, hashSize, initialHashInfo, \n\t\t\t\t\t\t\tMKDATA( \"E\" ), 1, handshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = loadCryptovariable( isClient ? \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthInContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \\\n\t\t\t\t\t\t\t\t\t   SSH_PFLAG_HMACKEYSIZE ) ? \\\n\t\t\t\t\t\t\t\tSSH2_FIXED_KEY_SIZE : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t\thashFunction, hashSize, initialHashInfo, \n\t\t\t\t\t\t\tMKDATA( \"F\" ), 1, handshakeInfo->sessionID,\n\t\t\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t}\n\tzeroise( initialHashInfo, sizeof( HASHINFO ) );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tHash/MAC Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Hash a value encoded as an SSH string and as an MPI */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashAsString( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t  IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t\t  IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 128 + 8 ];\n\tBOOLEAN copiedToBuffer = FALSE;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Prepend the string length to the data and hash it.  If it'll fit into\n\t   the buffer we copy it over to save a kernel call */\n\tsMemOpen( &stream, buffer, 128 );\n\tstatus = writeUint32( &stream, dataLength );\n\tif( cryptStatusOK( status ) && dataLength <= sMemDataLeft( &stream ) )\n\t\t{\n\t\t/* The data will fit into the buffer, copy it so that it can be \n\t\t   hashed in one go */\n\t\tstatus = swrite( &stream, data, dataLength );\n\t\tcopiedToBuffer = TRUE;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t  buffer, stell( &stream ) );\n\t\t}\n\tif( cryptStatusOK( status ) && !copiedToBuffer )\n\t\t{\n\t\t/* The data didn't fit into the buffer, hash it separately */\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) data, dataLength );\n\t\t}\n\tsMemClose( &stream );\n\tif( copiedToBuffer )\n\t\tzeroise( buffer, 128 );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint hashAsMPI( IN_HANDLE const CRYPT_CONTEXT iHashContext, \n\t\t\t   IN_BUFFER( dataLength ) const BYTE *data, \n\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 8 + 8 ];\n\tconst int length = ( data[ 0 ] & 0x80 ) ? dataLength + 1 : dataLength;\n\tint headerLength DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Prepend the MPI length to the data and hash it.  Since this is often\n\t   sensitive data we don't take a local copy but hash it in two parts */\n\tsMemOpen( &stream, buffer, 8 );\n\tstatus = writeUint32( &stream, length );\n\tif( data[ 0 ] & 0x80 )\n\t\t{\n\t\t/* MPIs are signed values */\n\t\tstatus = sputc( &stream, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\theaderLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t  buffer, headerLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) data, dataLength );\n\t\t}\n\treturn( status );\n\t}\n\n/* MAC the payload of a data packet.  Since we may not have the whole packet\n   available at once we can either do this in one go or incrementally.  If \n   it's incremental then packetDataLength is the packet-length value that's\n   encoded into a uint32 and hashed while dataLength is the amount of data \n   that we have available to hash right now.  If it's an atomic hash then\n   dataLength is both the length and data amount and packetDataLength is \n   zero */\n\nCHECK_RETVAL \\\nstatic int macDataSSH( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t\t   IN_INT_Z const long seqNo,\n\t\t\t\t\t   IN_BUFFER_OPT( dataLength ) const BYTE *data, \n\t\t\t\t\t   IN_DATALENGTH_Z const int dataLength,\n\t\t\t\t\t   IN_DATALENGTH_Z const int packetDataLength, \n\t\t\t\t\t   IN_ENUM_OPT( MAC ) const MAC_TYPE macType )\n\t{\n\tint status;\n\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( ( macType == MAC_END && seqNo == 0 ) || \\\n\t\t\t  ( macType != MAC_END && \\\n\t\t\t\tseqNo >= 2 && seqNo < INT_MAX ) );\n\t\t\t  /* Since SSH starts counting packets from the first one but \n\t\t\t\t unlike SSL doesn't MAC them, the seqNo is already nonzero \n\t\t\t\t when we start */\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataLength > 0 && dataLength < MAX_BUFFER_SIZE ) );\n\t\t\t  /* Payload may be zero for packets where all information is \n\t\t\t     contained in the header */\n\tREQUIRES( packetDataLength >= 0 && packetDataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRangeOpt( macType, MAC ) );\n\t\t\t  /* If we're doing a non-incremental MAC operation the type is \n\t\t\t     set to MAC_NONE */\n\n\t/* MAC the data and either compare the result to the stored MAC or\n\t   append the MAC value to the data:\n\n\t\tHMAC( seqNo || length || payload )\n\n\t   During the handshake process we have the entire packet at hand\n\t   (dataLength == packetDataLength) and can process it at once \n\t   (macType == MAC_NONE).  When we're processing payload data \n\t   (dataLength a subset of packetDataLength) we have to process the \n\t   header separately in order to determine how much more we have to read\n\t   so we have to MAC the packet in two parts (macType == MAC_START/\n\t   MAC_END) */\n\tif( macType == MAC_START || macType == MAC_NONE )\n\t\t{\n\t\tSTREAM stream;\n\t\tBYTE headerBuffer[ 16 + 8 ];\n\t\tint length = ( macType == MAC_NONE ) ? dataLength : packetDataLength;\n\t\tint headerLength DUMMY_INIT;\n\n\t\tREQUIRES( ( macType == MAC_NONE && packetDataLength == 0 ) || \\\n\t\t\t\t  ( macType == MAC_START && packetDataLength >= dataLength ) );\n\n\t\t/* Since the payload has had the length stripped during the \n\t\t   speculative read if we're MAC'ing read data we have to \n\t\t   reconstruct it and hash it separately before we hash the data.  \n\t\t   If we're doing the hash in parts then the amount of data being \n\t\t   hashed won't match the overall length so the caller needs to \n\t\t   supply the overall packet length as well as the current data \n\t\t   length */\n\t\tsMemOpen( &stream, headerBuffer, 16 );\n\t\twriteUint32( &stream, seqNo );\n\t\tstatus = writeUint32( &stream, length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\theaderLength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tkrnlSendMessage( iMacContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t  headerBuffer, headerLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( dataLength > 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) data, dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( macType == MAC_END || macType == MAC_NONE )\n\t\t{\n\t\tstatus = krnlSendMessage( iMacContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint checkMacSSHIncremental( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t\t\t\tIN_INT_Z const long seqNo,\n\t\t\t\t\t\t\tIN_BUFFER( dataMaxLength ) const BYTE *data, \n\t\t\t\t\t\t\tIN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\t\t\tIN_DATALENGTH_Z const int packetDataLength, \n\t\t\t\t\t\t\tIN_ENUM( MAC ) const MAC_TYPE macType, \n\t\t\t\t\t\t\tIN_LENGTH_HASH const int macLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataMaxLength ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( ( macType == MAC_END && seqNo == 0 ) || \\\n\t\t\t  ( macType != MAC_END && \\\n\t\t\t\tseqNo >= 2 && seqNo < INT_MAX ) );\n\t\t\t  /* Since SSH starts counting packets from the first one but \n\t\t\t\t unlike SSL doesn't MAC them, the seqNo is already nonzero \n\t\t\t\t when we start */\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( macType == MAC_END && dataLength == 0 ) || \\\n\t\t\t  ( dataLength > 0 && dataLength < MAX_BUFFER_SIZE ) );\n\t\t\t  /* Payload size may be zero for packets where all information\n\t\t\t     is contained in, and has already been MACd as part of, the \n\t\t\t\t header */\n\tREQUIRES( packetDataLength >= 0 && packetDataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( isEnumRange( macType, MAC ) );\n\tREQUIRES( macLength >= MIN_HASHSIZE && \\\n\t\t\t  macLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( ( macType == MAC_START && \\\n\t\t\t\tdataMaxLength == dataLength ) || \\\n\t\t\t  ( macType == MAC_END && \n\t\t\t\tdataLength + macLength <= dataMaxLength ) );\n\n\t/* MAC the payload.  If the data length is zero then there's no data \n\t   payload (which can happen with things like a channel close for which \n\t   the entire content is carried in the message header), only the MAC\n\t   data at the end, so we don't pass anything down to macDataSSH() */\n\tif( dataLength <= 0 )\n\t\t{\n\t\tstatus = macDataSSH( iMacContext, seqNo, NULL, 0, \n\t\t\t\t\t\t\t packetDataLength, macType );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = macDataSSH( iMacContext, seqNo, data, dataLength, \n\t\t\t\t\t\t\t packetDataLength, macType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're starting the ongoing hashing of a data block, we're done */\n\tif( macType == MAC_START )\n\t\treturn( CRYPT_OK );\n\n\t/* Compare the calculated MAC value to the stored MAC value */\n\tsetMessageData( &msgData, ( BYTE * ) data + dataLength, macLength );\n\treturn( krnlSendMessage( iMacContext, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t MESSAGE_COMPARE_HASH ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint checkMacSSH( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t IN_INT const long seqNo,\n\t\t\t\t IN_BUFFER( dataMaxLength ) const BYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t IN_DATALENGTH_Z const int dataLength, \n\t\t\t\t IN_LENGTH_HASH const int macLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isReadPtrDynamic( data, dataMaxLength ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( seqNo >= 2 && seqNo < INT_MAX );\n\t\t\t  /* Since SSH starts counting packets from the first one but \n\t\t\t\t unlike SSL doesn't MAC them, the seqNo is already nonzero \n\t\t\t\t when we start */\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( dataLength >= 0 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( macLength >= MIN_HASHSIZE && \\\n\t\t\t  macLength <= CRYPT_MAX_HASHSIZE );\n\tREQUIRES( dataLength + macLength <= dataMaxLength );\n\n\t/* MAC the payload.  If the data length is zero then there's no data \n\t   payload (which can happen with things like a channel close for which \n\t   the entire content is carried in the message header), only the MAC\n\t   data at the end, so we don't pass anything down to macDataSSH() */\n\tif( dataLength <= 0 )\n\t\tstatus = macDataSSH( iMacContext, seqNo, NULL, 0, 0, MAC_NONE );\n\telse\n\t\tstatus = macDataSSH( iMacContext, seqNo, data, dataLength, 0, MAC_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Compare the calculated MAC value to the stored MAC value */\n\tsetMessageData( &msgData, ( BYTE * ) data + dataLength, macLength );\n\treturn( krnlSendMessage( iMacContext, IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t MESSAGE_COMPARE_HASH ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nint createMacSSH( IN_HANDLE const CRYPT_CONTEXT iMacContext, \n\t\t\t\t  IN_INT const long seqNo,\n\t\t\t\t  IN_BUFFER( dataMaxLength ) BYTE *data, \n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  IN_DATALENGTH const int dataLength )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE mac[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iMacContext ) );\n\tREQUIRES( seqNo >= 2 && seqNo < INT_MAX );\n\t\t\t  /* Since SSH starts counting packets from the first one but \n\t\t\t\t unlike SSL doesn't MAC them, the seqNo is already nonzero \n\t\t\t\t when we start */\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( dataLength > 0 && dataLength < dataMaxLength && \\\n\t\t\t  dataLength < MAX_BUFFER_SIZE );\n\n\t/* MAC the payload */\n\tstatus = macDataSSH( iMacContext, seqNo, data, dataLength, 0, MAC_NONE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Append the calculated MAC value to the data */\n\tsetMessageData( &msgData, mac, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iMacContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tINJECT_FAULT( SESSION_CORRUPT_MAC, SESSION_CORRUPT_MAC_SSH_1 );\n\tREQUIRES( boundsCheck( dataLength, msgData.length, dataMaxLength ) );\n\tmemcpy( data + dataLength, mac, msgData.length );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyex Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Complete the DH/ECDH key agreement */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint completeKeyex( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tKEYAGREE_PARAMS keyAgreeParams;\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Read the other side's key agreement information.  Note that the size\n\t   check has already been performed at a higher level when the overall\n\t   key agreement value was read, this is a secondary check of the MPI\n\t   payload */\n\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tif( isServer )\n\t\t{\n\t\tsMemConnect( &stream, handshakeInfo->clientKeyexValue,\n\t\t\t\t\t handshakeInfo->clientKeyexValueLength );\n\t\t}\n\telse\n\t\t{\n\t\tsMemConnect( &stream, handshakeInfo->serverKeyexValue,\n\t\t\t\t\t handshakeInfo->serverKeyexValueLength );\n\t\t}\n\tif( handshakeInfo->isECDH )\n\t\t{\n\t\t/* This is actually a String32 and not an Integer32, however the\n\t\t   formats are identical and we need to read the value as an integer\n\t\t   to take advantage of the range-checking */\n\t\tstatus = readInteger32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t&keyAgreeParams.publicValueLen, \n\t\t\t\t\t\t\t\tMIN_PKCSIZE_ECCPOINT, MAX_PKCSIZE_ECCPOINT );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readInteger32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t&keyAgreeParams.publicValueLen, \n\t\t\t\t\t\t\t\tMIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 1 MPI\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( handshakeInfo->isECDH )\n\t\t\t{\n\t\t\tif( !isValidECDHsize( keyAgreeParams.publicValueLen,\n\t\t\t\t\t\t\t\t  handshakeInfo->serverKeySize, 0 ) )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( !isValidDHsize( keyAgreeParams.publicValueLen,\n\t\t\t\t\t\t\t\thandshakeInfo->serverKeySize, 0 ) )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tconst int clientKeyexSize = handshakeInfo->isECDH ? \\\n\t\t\textractECDHsize( keyAgreeParams.publicValueLen, 0 ) : \\\n\t\t\textractDHsize( keyAgreeParams.publicValueLen, 0 );\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 1 MPI size, expected %d (%d), \"\n\t\t\t\t  \"got %d (%d)\", handshakeInfo->isECDH ? \"ECDH\" : \"DH\",\n\t\t\t\t  handshakeInfo->serverKeySize, \n\t\t\t\t  handshakeInfo->serverKeySize * 8,\n\t\t\t\t  clientKeyexSize, clientKeyexSize * 8 ) );\n\t\t}\n\n\t/* Perform phase 2 of the DH/ECDH key agreement */\n\tstatus = krnlSendMessage( handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, &keyAgreeParams,\n\t\t\t\t\t\t\t  sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusOK( status ) && handshakeInfo->isECDH )\n\t\t{\n\t\tconst int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;\n\n\t\t/* The output of the ECDH operation is an ECC point, but for some\n\t\t   unknown reason SSH only uses the x coordinate and not the full\n\t\t   point.  To work around this we have to rewrite the point as a\n\t\t   standalone x coordinate, which is relatively easy because we're\n\t\t   using an \"uncompressed\" point format:\n\n\t\t\t+---+---------------+---------------+\n\t\t\t|04\t|\t\tqx\t\t|\t\tqy\t\t|\n\t\t\t+---+---------------+---------------+\n\t\t\t\t|<- fldSize --> |<- fldSize --> | */\n\t\tREQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \\\n\t\t\t\t  keyAgreeParams.wrappedKey[ 0 ] == 0x04 );\n\t\tREQUIRES( boundsCheck( 1, xCoordLen, CRYPT_MAX_PKCSIZE ) );\n\t\tmemmove( keyAgreeParams.wrappedKey,\n\t\t\t\t keyAgreeParams.wrappedKey + 1, xCoordLen );\n\t\tkeyAgreeParams.wrappedKeyLen = xCoordLen;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tREQUIRES( rangeCheck( keyAgreeParams.wrappedKeyLen, 0,\n\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE ) );\n\t\tmemcpy( handshakeInfo->secretValue, keyAgreeParams.wrappedKey,\n\t\t\t\tkeyAgreeParams.wrappedKeyLen );\n\t\thandshakeInfo->secretValueLength = keyAgreeParams.wrappedKeyLen;\n\t\t}\n\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're using ephemeral DH, hash the requested keyex key length(s)\n\t   and DH p and g values.  Since this has been deferred until long after\n\t   the keyex negotiation took place (so that the original data isn't \n\t   available any more) we have to recreate the original encoded values \n\t   here */\n\tif( !handshakeInfo->isFixedDH && !handshakeInfo->isECDH )\n\t\t{\n\t\tBYTE keyexBuffer[ 128 + ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];\n\t\tconst int extraLength = LENGTH_SIZE + sizeofString32( 6 );\n\n\t\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  handshakeInfo->encodedReqKeySizes,\n\t\t\t\t\t\t\t\t  handshakeInfo->encodedReqKeySizesLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsetMessageData( &msgData, keyexBuffer,\n\t\t\t\t\t\t128 + ( CRYPT_MAX_PKCSIZE * 2 ) );\n\t\tstatus = krnlSendMessage( handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t  keyexBuffer + extraLength,\n\t\t\t\t\t\t\t\t\t  msgData.length - extraLength );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Hash the client and server DH/ECDH values and shared secret */\n\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  handshakeInfo->clientKeyexValue,\n\t\t\t\t\t\t\t  handshakeInfo->clientKeyexValueLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  handshakeInfo->serverKeyexValue,\n\t\t\t\t\t\t\t\t  handshakeInfo->serverKeyexValueLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = hashAsMPI( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\thandshakeInfo->secretValue,\n\t\t\t\t\t\t\thandshakeInfo->secretValueLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Complete the hashing to obtain the exchange hash and then hash *that*\n\t   to get the hash that the server signs and sends to the client.  The\n\t   overall hashed data for the exchange hash is:\n\n\t\tstring\tV_C, client version string (CR and NL excluded)\n\t\tstring\tV_S, server version string (CR and NL excluded)\n\t\tstring\tI_C, client hello\n\t\tstring\tI_S, server hello\n\t\tstring\tK_S, the host key\n\t [[\tuint32\tmin, min.preferred keyex key size for ephemeral DH ]]\n\t  [\tuint32\tn, preferred keyex key size for ephemeral DH ]\n\t [[\tuint32\tmax, max.preferred keyex key size for ephemeral DH ]]\n\t  [\tmpint\tp, DH p for ephemeral DH ]\n\t  [\tmpint\tg, DH g for ephemeral DH ]\n\t   DH:\n\t\tmpint\te, client DH keyex value\n\t\tmpint\tf, server DH keyex value\n\t   ECDH:\n\t\tstring\tQ_C, client ECDH keyex value\n\t\tstring\tQ_S, server ECDH keyex value\n\t\tmpint\tK, the shared secret\n\n\t   The client and server version string ahd hellos and the host key were\n\t   hashed inline during the handshake.  The optional parameters are for\n\t   negotiated DH values (see the conditional-hashing code above).  The\n\t   double-optional parameters are for the revised version of the DH\n\t   negotiation mechanism, the original only had n, the revised version\n\t   allowed a { min, n, max } range */\n\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext, \n\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, handshakeInfo->sessionID, \n\t\t\t\t\t\tCRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\thandshakeInfo->sessionIDlength = msgData.length;\n\t\t\tINJECT_FAULT( SESSION_SSH_CORRUPT_EXCHANGE_HASH, \n\t\t\t\t\t\t  SESSION_SSH_CORRUPT_EXCHANGE_HASH_1 );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* At this point we continue the hash-algorithm dance, in most cases \n\t   switching back to SHA-1 if we've been using a different algorithm for \n\t   the hashing so far.  This is required because while the exchange hash \n\t   is calculated using the alternative algorithm that was negotiated \n\t   earlier, what gets signed is a SHA-1 hash of that.  Exceptions to \n\t   this occur when we're either using an ECC cipher suite or when the \n\t   use of SHA-2 has been explicitly indicated, in which case we \n\t   stick with SHA-2 */\n\tif( handshakeInfo->exchangeHashAlgo != handshakeInfo->hashAlgo )\n\t\t{\n\t\tconst CRYPT_CONTEXT tempContext = handshakeInfo->iExchangeHashContext;\n\n\t\thandshakeInfo->iExchangeHashContext = \\\n\t\t\t\thandshakeInfo->iExchangeHashAltContext;\n\t\thandshakeInfo->iExchangeHashAltContext = tempContext;\n\t\t}\n\tkrnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\tkrnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t IMESSAGE_CTX_HASH, handshakeInfo->sessionID,\n\t\t\t\t\t handshakeInfo->sessionIDlength );\n\tINJECT_FAULT( BADSIG_HASH, SESSION_BADSIG_HASH_SSH_1 );\n\treturn( krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t IMESSAGE_CTX_HASH, \"\", 0 ) );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_msg.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib SSHv2 Control Message Management\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* Forward declaration for channel-close function */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendChannelClose( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN const long channelNo,\n\t\t\t\t\t\t\t IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType,\n\t\t\t\t\t\t\t const BOOLEAN closeLastChannel );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Implement the SSH performance handbrake unless we've managed to disable\n   it during the channel-open */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int handleWindowAdjust( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   IN const long channelNo,\n\t\t\t\t\t\t\t   IN_LENGTH_Z const int length )\n\t{\n\tint windowCount, windowSize DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\tREQUIRES( isIntegerRange( length ) );\n\n\t/* Get the window parameters */\n\tstatus = getChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWCOUNT, \n\t\t\t\t\t\t\t\t\t &windowCount );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getChannelExtAttribute( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWSIZE,\n\t\t\t\t\t\t\t\t\t\t &windowSize );\n\t\t}\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Adjust the data window and communicate changes to the other side if \n\t   necessary.  This can get quite complicated because for those \n\t   implementations where we can't disable the SSH handbrake we have to \n\t   send a constant stream of 1977-vintage XMODEM XON/XOFF messages, but \n\t   since there may be a half-assembled packet in the send buffer we\n\t   can't just dispatch it immediately but have to enqueue it pending\n\t   availability of the send machinery (it also leads to strange error\n\t   messages returned to the caller when they get a write failure in\n\t   response to a read).  Fortunately only a few old buggy \n\t   implementations actually reject our disabling of the handbrake so \n\t   it's usually disabled (at least for the receive side, which we \n\t   control) and in the rare cases where it's present it's being used\n\t   for things like network router console interfaces for which the\n\t   traffic is highly interactive so there's a constant flow of packets\n\t   written to piggyback the XONs onto.\n\n\t   The exact strategy for window handling is a bit complex (mostly\n\t   because this isn't a good way to do things in the first place so it\n\t   would require horribly complex processing to really handle properly),\n\t   to keep things simple we just wait until the window size has fallen\n\t   to half its initial value and then reset it back to the initial\n\t   value again.  Since this is rarely used except where we can't disable\n\t   the handbrake it's not really worth introducing a huge amount of \n\t   extra complexity to manage it */\n\tREQUIRES( windowCount > 0 && windowCount <= windowSize );\n\twindowCount -= length;\n\tif( windowCount < windowSize / 2 )\n\t\t{\n\t\tint adjustCount;\n\n\t\t/* Send the window adjust to the remote system:\n\n\t\t\tbyte\tSSH_MSG_CHANNEL_WINDOW_ADJUST\n\t\t\tuint32\tchannel\n\t\t\tuint32\tbytes_to_add\n\n\t\t   Unfortunately the error status that we return from a failed \n\t\t   window adjust is going to come as a complete surprise to the \n\t\t   caller because we're supposed to be processing a read and not a \n\t\t   write at this point, the write is only required by SSH's \n\t\t   braindamaged flow-control handling */\n\t\tif( windowCount < 0 || windowCount >= windowSize )\n\t\t\t{\n\t\t\t/* We've consumed the remaining window and then some, reset it\n\t\t\t   to it's full size */\n\t\t\tadjustCount = windowSize;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Adjust the window back up to it's full size */\n\t\t\tadjustCount = windowSize - windowCount;\n\t\t\t}\n\t\tENSURES( adjustCount > windowSize / 2 && \\\n\t\t\t\t adjustCount <= windowSize );\n\t\tstatus = enqueueChannelData( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t SSH_MSG_CHANNEL_WINDOW_ADJUST,\n\t\t\t\t\t\t\t\t\t channelNo, adjustCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Error sending SSH window adjust for data flow \"\n\t\t\t\t\t  \"control\" ) );\n\t\t\t}\n\n\t\t/* We've reset the window, start again from zero */\n\t\twindowCount += adjustCount;\n\t\tif( windowCount < windowSize / 2 || windowCount > windowSize )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid SSH flow control window count %d, should be \"\n\t\t\t\t\t  \"%d ... %d\", windowCount, windowSize / 2, \n\t\t\t\t\t  windowSize ) );\n\t\t\t}\n\t\t}\n\tstatus = setChannelExtAttribute( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWCOUNT,\n\t\t\t\t\t\t\t\t\t windowCount );\n\tENSURES( cryptStatusOK( status ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGeneral Channel Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the data window size for a new channel.  Some buggy implementations \n   break when sent a window size over a certain limit in which case we have \n   to limit the window size.  Typically for these implementations for any \n   size over about 8M the server gets slower and slower, eventually more or \n   less grinding to halt at about 64MB (presumably some O(n^2) algorithm, \n   although how you manage to do this for a window-size notification is a \n   mystery).  Some variants of this buggy server reportedly require a window \n   adjust for every 32K or so sent no matter what the actual window size is, \n   but this may be just a variant of the general mis-handling of large \n   window sizes so we treat it as the same thing and advertise a smaller-\n   than-optimal 16MB window which, as a side-effect, results in a constant \n   flow of window adjusts */\n\nCHECK_RETVAL_RANGE_NOERROR( 10000, MAX_WINDOW_SIZE ) STDC_NONNULL_ARG( ( 1 ) ) \\\nint getWindowSize( const SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\treturn( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSH_PFLAG_WINDOWSIZE ) ? \\\n\t\t\t0x1000000 : MAX_WINDOW_SIZE );\n\t}\n\n/* Process a channel control message.  Returns OK_SPECIAL to tell the caller\n   to try again with the next packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelControlMessage( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tconst long prevChannelNo = \\\n\t\t\t\tgetCurrentChannelNo( sessionInfoPtr, CHANNEL_READ );\n\tlong channelNo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* See what we've got.  SSH has a whole pile of no-op equivalents that \n\t   we have to handle as well as the obvious no-ops.  We can also get \n\t   global and channel requests for assorted reasons and a constant \n\t   stream of window adjusts to implement the SSH performance handbrake */\n\tswitch( sshInfo->packetType )\n\t\t{\n\t\tcase SSH_MSG_GLOBAL_REQUEST:\n\t\t\tstatus = processChannelRequest( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\t\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase SSH_MSG_CHANNEL_OPEN:\n\t\t\t/* Process the channel-open request.  In theory we could \n\t\t\t   immediately reject any attempts by the server to open a\n\t\t\t   channel to the client at this point, but unfortunately we\n\t\t\t   have to process a considerable portion of the channel-open\n\t\t\t   request in order to use the information in it to send a\n\t\t\t   request-denied response back to the server */\n\t\t\tstatus = processChannelOpen( sessionInfoPtr, stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* Tell the caller that they have to process the new channel\n\t\t\t   information before they can continue */\n\t\t\treturn( CRYPT_ENVELOPE_RESOURCE );\n\n\t\tcase SSH_MSG_IGNORE:\n\t\tcase SSH_MSG_DEBUG:\n\t\t\t/* Nothing to see here, move along, move along:\n\n\t\t\t\tbyte\tSSH_MSG_IGNORE\n\t\t\t\tstring\tdata\n\n\t\t\t\tbyte\tSSH_MSG_DEBUG\n\t\t\t\tboolean\talways_display\n\t\t\t\tstring\tmessage\n\t\t\t\tstring\tlanguage_tag */\n\t\t\tDEBUG_PUTS(( \"Processing ignore/debug message\" ));\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase SSH_MSG_DISCONNECT:\n\t\t\t/* This only really seems to be used during the handshake phase,\n\t\t\t   once a channel is open it (and the session as a whole) is\n\t\t\t   disconnected with a channel EOF/close, but we handle it here\n\t\t\t   anyway just in case */\n\t\t\treturn( getDisconnectInfo( sessionInfoPtr, stream ) );\n\n\t\tcase SSH_MSG_KEXINIT:\n\t\t\t/* The SSH spec is extremely vague about the sequencing of\n\t\t\t   operations during a rehandshake.  Unlike SSL there's no real \n\t\t\t   indication of what happens to the connection-layer transfers \n\t\t\t   while a transport-layer rehandshake is in progress.  Also \n\t\t\t   unlike SSL we can't refuse a rehandshake by ignoring the \n\t\t\t   request, so once we've fallen we can't get up any more.  This \n\t\t\t   is most obvious with ssh.com's server, which starting with \n\t\t\t   version 2.3.0 would do a rehandshake every hour (for a basic \n\t\t\t   encrypted telnet session, while a high-volume IPsec link can \n\t\t\t   run for hours before it feels the need to do this).  To make \n\t\t\t   things even messier, neither side can block for too long \n\t\t\t   waiting for the rehandshake to complete before sending new \n\t\t\t   data because the lack of WINDOW_ADJUSTs (in an implementation \n\t\t\t   that sends these with almost every packet, as most do) will \n\t\t\t   screw up flow control and lead to deadlock.  This problem got \n\t\t\t   so bad that as of 2.4.0 the ssh.com implementation would \n\t\t\t   detect OpenSSH (the other main implementation at the time) \n\t\t\t   and disable the rehandshake when it was talking to it, but it \n\t\t\t   may not do this for other implementations.\n\n\t\t\t   To avoid falling into this hole, or at least to fail\n\t\t\t   obviously when the two sides can't agree on how to handle the\n\t\t\t   layering mismatch problem, we report a rehandshake request as\n\t\t\t   an error.  Trying to handle it properly results in hard-to-\n\t\t\t   diagnose errors (it depends on what the layers are doing at\n\t\t\t   the time of the problem), typically some bad-packet error\n\t\t\t   when the other side tries to interpret a connection-layer\n\t\t\t   packet as part of the rehandshake, or when the two sides\n\t\t\t   disagree on when to switch keys and one of the two decrypts \n\t\t\t   with the wrong keys and gets a garbled packet type */\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Unexpected KEXINIT request received\" ) );\n\n\t\tcase SSH_MSG_CHANNEL_DATA:\n\t\tcase SSH_MSG_CHANNEL_EXTENDED_DATA:\n\t\tcase SSH_MSG_CHANNEL_REQUEST:\n\t\tcase SSH_MSG_CHANNEL_WINDOW_ADJUST:\n\t\tcase SSH_MSG_CHANNEL_EOF:\n\t\tcase SSH_MSG_CHANNEL_CLOSE:\n\t\t\t/* All channel-specific messages end up here */\n\t\t\tchannelNo = readUint32( stream );\n\t\t\tif( cryptStatusError( channelNo ) )\n\t\t\t\t{\n\t\t\t\t/* We can't send an error response to a channel request at\n\t\t\t\t   this point both because we haven't got to the response-\n\t\t\t\t   required flag yet and because SSH doesn't provide a\n\t\t\t\t   mechanism for returning an error response without an\n\t\t\t\t   accompanying channel number.  The best that we can do is\n\t\t\t\t   to quietly ignore the packet */\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid channel number in channel-specific packet \"\n\t\t\t\t\t\t  \"%s (%d)\", \n\t\t\t\t\t\t  getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t\t\t  sshInfo->packetType ) );\n\t\t\t\t}\n\t\t\tif( channelNo != getCurrentChannelNo( sessionInfoPtr, \\\n\t\t\t\t\t\t\t\t\t\t\t\t  CHANNEL_READ ) )\n\t\t\t\t{\n\t\t\t\t/* It's a request on something other than the current\n\t\t\t\t   channel, try and select the new channel */\n\t\t\t\tstatus = selectChannel( sessionInfoPtr, channelNo,\n\t\t\t\t\t\t\t\t\t\tCHANNEL_READ );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* As before for error handling */\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid channel number %lX in \"\n\t\t\t\t\t\t\t  \"channel-specific packet %s (%d), current \"\n\t\t\t\t\t\t\t  \"channel is %lX\", channelNo,\n\t\t\t\t\t\t\t  getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t\t\t\t  sshInfo->packetType, prevChannelNo ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t{\n\t\t\tchar stringBuffer[ 256 + 8 ];\n\t\t\tint i, length, totalLength, LOOP_ITERATOR;\n\n\t\t\t/* If it's a channel message, try and read the channel number */\n\t\t\tchannelNo = -1;\n\t\t\tif( sshInfo->packetType >= SSH_MSG_CHANNEL_OPEN && \\\n\t\t\t\tsshInfo->packetType <= SSH_MSG_CHANNEL_FAILURE )\n\t\t\t\t{\n\t\t\t\tchannelNo = readUint32( stream );\n\t\t\t\tif( cryptStatusError( channelNo ) )\n\t\t\t\t\tchannelNo = -1;\n\t\t\t\t}\n\n\t\t\t/* We got something unexpected, throw an exception in the debug\n\t\t\t   version and let the caller know the details */\n\t\t\tDEBUG_DIAG(( \"Unexpected control packet %s (%d)\", \n\t\t\t\t\t\t getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t\t\t sshInfo->packetType ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\ttotalLength = length = sprintf_s( stringBuffer, 256, \n\t\t\t\t\t\t\t\"Unexpected control packet %s (%d) received\",\n\t\t\t\t\t\t\tgetSSHPacketName( sshInfo->packetType ), \n\t\t\t\t\t\t\tsshInfo->packetType );\n\t\t\tENSURES( length > 0 && length <= 256 );\n\t\t\tif( channelNo != -1 )\n\t\t\t\t{\n\t\t\t\tlength = sprintf_s( stringBuffer + totalLength, \n\t\t\t\t\t\t\t\t\t256 - totalLength, \", channel = %lX\", \n\t\t\t\t\t\t\t\t\tchannelNo );\n\t\t\t\tENSURES( length > 0 && length <= 256 );\n\t\t\t\ttotalLength += length;\n\t\t\t\t}\n\t\t\tLOOP_MED( i = 0, i < 16, i++ )\n\t\t\t\t{\n\t\t\t\tconst int ch = sgetc( stream );\n\n\t\t\t\tif( cryptStatusError( ch ) )\n\t\t\t\t\tbreak;\n\t\t\t\tif( i == 0 )\n\t\t\t\t\t{\n\t\t\t\t\tlength = sprintf_s( stringBuffer + totalLength, \n\t\t\t\t\t\t\t\t\t\t256 - totalLength, \", data begins\" );\n\t\t\t\t\tENSURES( length > 0 && length <= 256 );\n\t\t\t\t\ttotalLength += length;\n\t\t\t\t\t}\n\t\t\t\tlength = sprintf_s( stringBuffer + totalLength, \n\t\t\t\t\t\t\t\t\t256 - totalLength, \" %02X\", ch );\n\t\t\t\tENSURES( length > 0 && length <= 256 );\n\t\t\t\ttotalLength += length;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \"%s\", \n\t\t\t\t\t  stringBuffer ) );\t/* Redundant %s needed for gcc */\n\t\t\t}\n\t\t}\n\n\t/* From here on we're processing a channel-specific message that applies\n\t   to the currently selected channel */\n\tswitch( sshInfo->packetType )\n\t\t{\n\t\tcase SSH_MSG_CHANNEL_DATA:\n\t\tcase SSH_MSG_CHANNEL_EXTENDED_DATA:\n\t\t\t{\n\t\t\tint length;\n\n\t\t\t/* Get the payload length and make sure that it's\n\t\t\t   (approximately) valid, more exact checking has already been\n\t\t\t   done by the caller so we don't need to return extended error\n\t\t\t   information as this is just a backup check */\n\t\t\tstatus = length = readUint32( stream );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\tlength < 0 || length > sessionInfoPtr->receiveBufSize )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t\tDEBUG_PRINT(( \"Processing data message, length %d.\\n\", length ));\n\n\t\t\t/* These are messages that consume window space, adjust the data \n\t\t\t   window and communicate changes to the other side if \n\t\t\t   necessary */\n\t\t\tstatus = handleWindowAdjust( sessionInfoPtr, channelNo, length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* If it's a standard data packet, we're done */\n\t\t\tif( sshInfo->packetType == SSH_MSG_CHANNEL_DATA )\n\t\t\t\treturn( CRYPT_OK );\n\n\t\t\t/* The extended data message is used for out-of-band data sent\n\t\t\t   over a channel, specifically output sent to stderr from a\n\t\t\t   shell command.  What to do with this is somewhat uncertain,\n\t\t\t   the only possible action that we could take apart from just\n\t\t\t   ignoring it is to convert it back to in-band data.  However,\n\t\t\t   something running a shell command may not expect to get\n\t\t\t   anything returned in this manner (see the comment for the\n\t\t\t   port-forwarding channel open in the client-side channel-open\n\t\t\t   code for more on this) so for now we just ignore it and \n\t\t\t   assume that the user will rely on results sent as in-band\n\t\t\t   data.  This should be fairly safe since this message type\n\t\t\t   seems to be rarely (if ever) used, so apps will function\n\t\t\t   without it */\n\t\t\treturn( OK_SPECIAL );\n\t\t\t}\n\n\t\tcase SSH_MSG_CHANNEL_REQUEST:\n\t\t\tstatus = processChannelRequest( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\t\t\t\tprevChannelNo );\n\t\t\tif( cryptStatusError( status ) && status != OK_SPECIAL )\n\t\t\t\treturn( status );\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase SSH_MSG_CHANNEL_WINDOW_ADJUST:\n\t\t\t/* Another noop-equivalent (but a very performance-affecting\n\t\t\t   one) */\n\t\t\tDEBUG_PUTS(( \"Processing window adjust message\" ));\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase SSH_MSG_CHANNEL_EOF:\n\t\t\t/* According to the SSH docs the EOF packet is a courtesy \n\t\t\t   notification of no clear purpose (and specifically \"the \n\t\t\t   channel remains open after this message\"), however some \n\t\t\t   implementations seem to use a channel EOF in place of a \n\t\t\t   close before sending a disconnect message, so we record the\n\t\t\t   presence of an EOF in the log in case this turns into a \n\t\t\t   problem later */\n\t\t\tDEBUG_PUTS(( \"Processing EOF message\" ));\n\t\t\treturn( OK_SPECIAL );\n\n\t\tcase SSH_MSG_CHANNEL_CLOSE:\n\t\t\t/* The peer has closed their side of the channel, if our side\n\t\t\t   isn't already closed (in other words if this message isn't\n\t\t\t   a response to a close that we sent), close our side as well */\n\t\t\tif( getChannelStatusByChannelNo( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t channelNo ) == CHANNEL_BOTH )\n\t\t\t\t{\n\t\t\t\tstatus = sendChannelClose( sessionInfoPtr, channelNo,\n\t\t\t\t\t\t\t\t\t\t   CHANNEL_BOTH, TRUE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* We've already closed our side of the channel, delete it */\n\t\t\t\tstatus = deleteChannel( sessionInfoPtr, channelNo,\n\t\t\t\t\t\t\t\t\t\tCHANNEL_BOTH, TRUE );\n\t\t\t\t}\n\t\t\tDEBUG_PRINT(( \"Processing channel close message for \"\n\t\t\t\t\t\t  \"channel %d.\\n\", channelNo ));\n\n\t\t\t/* If this wasn't the last channel, we're done */\n\t\t\tif( status != OK_SPECIAL )\n\t\t\t\treturn( OK_SPECIAL );\n\n\t\t\t/* We've closed the last channel, indicate that the overall\n\t\t\t   connection is now closed.  This behaviour isn't mentioned in\n\t\t\t   the spec but it seems to be the standard way of handling \n\t\t\t   things, particularly for the most common case where\n\t\t\t   channel == session */\n\t\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\t\t\tretExt( CRYPT_ERROR_COMPLETE,\n\t\t\t\t\t( CRYPT_ERROR_COMPLETE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Remote system closed last remaining SSH channel\" ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChannel Close Handling\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a channel close notification.  Returns OK_SPECIAL if the last\n   channel is being closed */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendChannelClose( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN const long channelNo,\n\t\t\t\t\t\t\t IN_ENUM( CHANNEL ) const CHANNEL_TYPE channelType,\n\t\t\t\t\t\t\t const BOOLEAN closeLastChannel )\n\t{\n\tBOOLEAN lastChannel = FALSE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\tREQUIRES( isEnumRange( channelType, CHANNEL ) );\n\tREQUIRES( closeLastChannel == TRUE || closeLastChannel == FALSE );\n\n\t/* Delete the channel.  If we've deleted the last active channel\n\t   deleteChannel() will return OK_SPECIAL to let us know that there are\n\t   no more channels left to close */\n\tstatus = deleteChannel( sessionInfoPtr, channelNo, channelType,\n\t\t\t\t\t\t\tcloseLastChannel  );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\t\t\n\t\t/* We're closing the last remaining channel */\n\t\tlastChannel = TRUE;\n\t\t}\n\n\t/* Prepare the channel-close notification:\n\n\t\tbyte\t\tSSH_MSG_CHANNEL_CLOSE\n\t\tuint32\t\tchannel_no */\n\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_CLOSE, \n\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_CLOSE_1 );\n\tstatus = enqueueResponse( sessionInfoPtr, SSH_MSG_CHANNEL_CLOSE, 1,\n\t\t\t\t\t\t\t  channelNo, CRYPT_UNUSED, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_UNUSED );\n\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_CLOSE, \n\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_CLOSE_2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We can't safely use anything that ends up at sendPacketSSH2() at this\n\t   point since we may be closing the connection in response to a link\n\t   error, in which case the error returned from the packet send would\n\t   overwrite the actual error information.  Because of this we send the\n\t   response with the no-report-error flag set to suppress reporting of\n\t   network errors during the send */\n\tdisableErrorReporting( sessionInfoPtr );\n\tstatus = sendEnqueuedResponse( sessionInfoPtr );\n\tenableErrorReporting( sessionInfoPtr );\n\n\t/* If it's the last channel, let the caller know (this overrides any\n\t   possible error return status, since we're about to close the \n\t   connection there's not much that we can do with an error anyway) */\n\treturn( lastChannel ? OK_SPECIAL : status );\n\t}\n\n/* Close a channel */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint closeChannel( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t  const BOOLEAN closeAllChannels )\n\t{\n\tSES_READHEADER_FUNCTION readHeaderFunction;\n\tREADSTATE_INFO readInfo;\n\tconst int currWriteChannelNo = \\\n\t\t\t\tgetCurrentChannelNo( sessionInfoPtr, CHANNEL_WRITE );\n\tint noChannels = 1, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( closeAllChannels == TRUE || closeAllChannels == FALSE );\n\n\treadHeaderFunction = ( SES_READHEADER_FUNCTION ) \\\n\t\t\t\t\t\t FNPTR_GET( sessionInfoPtr->readHeaderFunction );\n\tREQUIRES( readHeaderFunction != NULL );\n\n\t/* If we've already sent the final channel-close message in response to\n\t   getting a final close notification from the peer then we're done */\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Normally we can keep closing open channels until we hit the last one\n\t   whereupon we close the overall session, however if we're closing a\n\t   single identified channel we can't automatically close the whole\n\t   session as a side-effect of closing the single channel */\n\tif( !closeAllChannels && currWriteChannelNo == UNUSED_CHANNEL_NO )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t  \"No channel information available to identify the \"\n\t\t\t\t  \"channel to close\" ) );\n\t\t}\n\n\t/* If there's no channel open, close the session with a session\n\t   disconnect rather than a channel close:\n\n\t\tbyte\t\tSSH_MSG_DISCONNECT\n\t\tuint32\t\treason_code = SSH_DISCONNECT_CONNECTION_LOST\n\t\tstring\t\tdescription = \"\"\n\t\tstring\t\tlanguage_tag = \"\"\n\n\t   The spec doesn't explain what the reason codes actually mean but\n\t   SSH_DISCONNECT_CONNECTION_LOST seems to be the least inappropriate\n\t   disconnect reason at this point */\n\tif( currWriteChannelNo == UNUSED_CHANNEL_NO )\n\t\t{\n\t\t/* Since we're closing the session there's not much that we can do\n\t\t   in the case of an error because the very next operation is to \n\t\t   shut down the network session, so we don't do anything if the \n\t\t   send fails */\n\t\tstatus = enqueueResponse( sessionInfoPtr, SSH_MSG_DISCONNECT, 3,\n\t\t\t\t\t\t\t\t  SSH_DISCONNECT_CONNECTION_LOST, 0, 0,\n\t\t\t\t\t\t\t\t  CRYPT_UNUSED );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t( void ) sendEnqueuedResponse( sessionInfoPtr );\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Close one or all channels */\n\tif( closeAllChannels )\n\t\t{\n\t\t/* Get the first available channel (which must succeed, since we\n\t\t   just checked it above) and close each successive channel in\n\t\t   turn */\n\t\tstatus = selectChannel( sessionInfoPtr, CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\tCHANNEL_WRITE );\n\t\tLOOP_MED( noChannels = 0, \n\t\t\t\t  cryptStatusOK( status ) && \\\n\t\t\t\t\tcryptStatusOK( selectChannel( sessionInfoPtr, CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\t\t\t\t\t  CHANNEL_WRITE ) ),\n\t\t\t\t  noChannels++ )\n\t\t\t{\n\t\t\tstatus = sendChannelClose( sessionInfoPtr,\n\t\t\t\t\t\tgetCurrentChannelNo( sessionInfoPtr, CHANNEL_WRITE ),\n\t\t\t\t\t\tCHANNEL_WRITE, TRUE );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\telse\n\t\t{\n\t\t/* We're just closing one channel, close the write side.  The\n\t\t   complete close will be done when the other side acknowledges our\n\t\t   close.  If this isn't the last open channel then the response to \n\t\t   our close will be handled as part of normal packet processing and \n\t\t   we're done */\n\t\tstatus = sendChannelClose( sessionInfoPtr, currWriteChannelNo,\n\t\t\t\t\t\t\t\t   CHANNEL_WRITE, FALSE );\n\t\tif( status != OK_SPECIAL )\n\t\t\t{\n\t\t\t/* If this is the last remaining channel, we similarly can't\n\t\t\t   close it */\n\t\t\tif( status == CRYPT_ERROR_PERMISSION )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Cannot close last remaining channel without \"\n\t\t\t\t\t\t  \"closing the overall session\" ) );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\t}\n\n\t/* It's the last open channel, flush through the remaining data */\n\tstatus = sendCloseNotification( sessionInfoPtr, NULL, 0 );\n\tif( cryptStatusError( status ) || \\\n\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, SESSION_FLAG_SENDCLOSED ) )\n\t\t{\n\t\t/* There's a problem at the network level or the other side has\n\t\t   already closed the session, exit */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If there's not enough room in the receive buffer to read at least 1K\n\t   of packet data then we can't try anything further */\n\tif( sessionInfoPtr->receiveBufSize - sessionInfoPtr->receiveBufEnd < \\\n\t\tmin( sessionInfoPtr->pendingPacketRemaining, 1024 ) )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're in the middle of reading other data then there's no hope of\n\t   reading back the other side's channel close without first clearing all\n\t   of the other data, which is unlikely to happen because the channel \n\t   has been closed (this can happen when the caller requests a shutdown\n\t   of the session in the middle of a data transfer), in which case we\n\t   just exit */\n\tif( sessionInfoPtr->receiveBufPos != sessionInfoPtr->receiveBufEnd )\n\t\treturn( CRYPT_OK );\n\n\t/* Read back the other side's channel close(s).  This is somewhat messy\n\t   since the other side could decide that it still wants to send us\n\t   arbitrary amounts of data (the spec is rather vague about how urgent\n\t   a channel close is, the general idea among implementors seems to be\n\t   that you should let output drain before you close your side but if \n\t   you're in the middle of sending a 2GB file that's a lot of output to \n\t   drain).  This can also be complicated by implementation-specific \n\t   quirks, for example OpenSSH may hang more or less indefinitely if\n\t   there's output coming from a background process on the server.  This\n\t   is because of a rather obscure race condition that would occur if it\n\t   exited immediately in which the SSH server gets the SIGCHLD from the\n\t   (local) background process exiting before it's written all of its\n\t   data to the (local) pipe connecting it to the SSH server, so it\n\t   closes the (remote) SSH channel/connection before the last piece of\n\t   data comes over the (local) pipe.  Because the server won't close the\n\t   (remote) SSH connection until it's certain that the (local) process\n\t   has written all of its data, and it'll never get the EOF over the\n\t   pipe, it hangs forever.  This is a piece of Unix plumbing arcana that\n\t   doesn't really concern us so again just exiting after a short wait \n\t   seems to be the best response.\n\n\t   Since we're about to shut down the session anyway we try to read a \n\t   basic channel close ack from the other side, if there's anything more \n\t   than that we drop it.  This is complicated somewhat by the fact that \n\t   what we're doing here is something that's normally handled by the \n\t   high-level read code in sess_rw.c.  What we implement here is the \n\t   absolute minimum needed to clear the stream (sendCloseNotification() \n\t   has already set the necessary (small) nonzero timeout for us).\n\t   \n\t   Finally, we don't bother trying to decode what's being sent, since \n\t   we're in the process of closing the session it doesn't really matter \n\t   what the other side is sending us, it's not as if we're going to\n\t   abort the shutdown because some channel flag is set wrong */\n\tLOOP_SMALL_CHECKINC( noChannels > 0, noChannels-- )\n\t\t{\n\t\tstatus = readHeaderFunction( sessionInfoPtr, &readInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* Adjust the packet information for the packet header data that was \n\t\t   just read */\n\t\tsessionInfoPtr->receiveBufEnd += status;\n\t\tsessionInfoPtr->pendingPacketRemaining -= status;\n\t\tif( sessionInfoPtr->pendingPacketRemaining <= 512 )\n\t\t\t{\n\t\t\tconst int bytesLeft = sessionInfoPtr->receiveBufSize - \\\n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufEnd;\n\n\t\t\t/* We got a packet and it's probably the channel close ack, read \n\t\t\t   it */\n\t\t\tstatus = sread( &sessionInfoPtr->stream,\n\t\t\t\t\t\t\tsessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\tmin( sessionInfoPtr->pendingPacketRemaining, \\\n\t\t\t\t\t\t\t\t bytesLeft ) );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_msgc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib SSHv2 Client-side Channel Message Management\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2008\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* The type of a channel-open request and the type of service that we're\n   requesting */\n\ntypedef enum { OPENREQUEST_NONE, /* OPENREQUEST_STANDALONE, */\n\t\t\t   OPENREQUEST_CHANNELONLY, OPENREQUEST_SESSION,\n\t\t\t   OPENREQUEST_LAST } OPENREQUEST_TYPE;\n\n#ifdef USE_SSH_EXTENDED\ntypedef enum { SERVICE_NONE, SERVICE_SHELL, SERVICE_PORTFORWARD, \n\t\t\t   SERVICE_SUBSYSTEM, SERVICE_EXEC, SERVICE_LAST } SERVICE_TYPE;\n#else\ntypedef enum { SERVICE_NONE, SERVICE_SHELL, SERVICE_LAST } SERVICE_TYPE;\n#endif /* USE_SSH_EXTENDED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSH_EXTENDED\n\n/* Determine which type of service the caller requested */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getServiceType( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   OUT_ENUM_OPT( SERVICE ) SERVICE_TYPE *serviceType )\n\t{\n\tBYTE typeString[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint typeLen, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( serviceType, sizeof( SERVICE_TYPE ) ) );\n\n\t/* Clear return value */\n\t*serviceType = SERVICE_NONE;\n\n\t/* Get the information that's needed for the channel that we're about \n\t   to create */\n\tstatus = getChannelAttributeS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\t\t\t\t\t\t\t   typeString, CRYPT_MAX_TEXTSIZE,  \n\t\t\t\t\t\t\t\t   &typeLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Missing channel type for channel activation\" ) );\n\t\t}\n\tif( !strCompare( typeString, \"subsystem\", 9 ) )\n\t\t{\n\t\t*serviceType = SERVICE_SUBSYSTEM;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( !strCompare( typeString, \"direct-tcpip\", 12 ) || \\\n\t\t!strCompare( typeString, \"forwarded-tcpip\", 15 ) )\n\t\t{\n\t\t*serviceType = SERVICE_PORTFORWARD;\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( !strCompare( typeString, \"exec\", 4 ) )\n\t\t{\n\t\t*serviceType = SERVICE_EXEC;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The default is a just a straight pipe from A to B, a shell in SSH \n\t   thinking */\n\t*serviceType = SERVICE_SHELL;\n\treturn( CRYPT_OK );\n\t}\n#else\n  #define getServiceType( sessionInfoPtr, serviceType ) \\\n\t\t  CRYPT_OK; \\\n\t\t  *( serviceType ) = SERVICE_SHELL\n#endif /* USE_SSH_EXTENDED */\n\n/* Get information on why a channel-open failed */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getOpenFailInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint stringLen, errorCode, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* The channel open failed, tell the caller why:\n\n\t\tbyte\tSSH_MSG_CHANNEL_OPEN_FAILURE\n\t\tuint32\trecipient_channel\n\t\tuint32\treason_code\n\t\tstring\tadditional_text */\n\treadUint32( stream );\t\t/* Skip channel number */\n\terrorCode = readUint32( stream );\n\tstatus = readString32( stream, stringBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t   &stringLen );\n\tif( cryptStatusError( status ) || \\\n\t\tstringLen <= 0 || stringLen > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\t/* No error message, the best that we can do is give the reason code \n\t\t   (or the stream status if we couldn't even get that) as part of \n\t\t   the message */\n\t\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t\t( CRYPT_ERROR_OPEN, SESSION_ERRINFO, \n\t\t\t\t  \"Channel open failed, reason code %d\", \n\t\t\t\t  errorCode ) );\n\t\t}\n\tretExt( CRYPT_ERROR_OPEN,\n\t\t\t( CRYPT_ERROR_OPEN, SESSION_ERRINFO, \n\t\t\t  \"Channel open failed, error message '%s'\",\n\t\t\t  sanitiseString( stringBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t  stringLen ) ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClient-side Channel Management\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create a request for the appropriate type of service, either encrypted-\n   telnet, SFTP (or more generically a subsystem), or port forwarding.\n   There are several different port-forwarding mechanisms that we can use.\n   A global request of type \"tcpip-forward\" requests forwarding of a remote\n   port to the local system, specifying the remote port to be forwarded but\n   without actually opening a session/channel, it's merely a request for\n   future forwarding.  When a connection arrives on the remote port for\n   which forwarding has been requested the remote system opens a channel of\n   type \"forwarded-tcpip\" to the local system.  To open a connection from a\n   locally-forwarded port to a port on the remote system the local system\n   opens a channel of type \"direct-tcpip\" to the remote system:\n\n\tPkt\t\tName\t\t\tArg1\t\t\tArg2\t\tComment\n\t---\t\t----\t\t\t----\t\t\t----\t\t-------\n\topen\t\"session\"\t\t\t\t\t\t\t\t\tFollowed by pty-req\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tor subsys\n\topen\t\"fwded-tcpip\"\tremote_info (in)\t\t\tServer -> client in\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tresponse.to tcpip-fd\n\topen\t\"direct-tcpip\"\tremote_info\t\tlocal_info\tClient -> server, currently\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tlocal_info = 127.0.0.1\n\tglobal\t\"tcpip-fwd\"\t\tremote_info (out)\t\t\tRequest for remote\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tforwarding\n\n   Once we've opened a standard session we need to follow it with either a\n   pty-request + shell request or a subsystem request:\n\n\tPkt\t\tName\t\t\tArg1\t\t\tArg2\t\tComment\n\t---\t\t----\t\t\t----\t\t\t----\t\t-------\n\tchannel\t\"pty-req\"\n\tchannel \"subsystem\"\t\tname\n\n   In theory we could bundle the channel open + pty-request + shell request\n   into a single packet group to save round-trips but the packets sent after\n   the channel open require the use of the receive-channel number supplied by\n   the remote system.  This is usually the same as the send channel that we\n   specify but for some unknown reason Cisco use different send and receive\n   channel numbers, requiring that we wait for the response to the channel-\n   open before we send any subsequent packets, which adds yet another RTT to \n   the exchange */\n\n#ifdef USE_SSH_EXTENDED \n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int createOpenRequest( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  OUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_ENUM( SERVICE ) const SERVICE_TYPE serviceType,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( OPENREQUEST ) \\\n\t\t\t\t\t\t\t\t\tOPENREQUEST_TYPE *requestType )\n\t{\n\tconst long channelNo = getCurrentChannelNo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tCHANNEL_WRITE );\n\tconst int maxPacketSize = sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t  EXTRA_PACKET_SIZE;\n\tURL_INFO urlInfo DUMMY_INIT_STRUCT;\n\tBYTE arg1String[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint arg1Len DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( requestType, sizeof( OPENREQUEST_TYPE ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( serviceType, SERVICE ) );\n\n\t/* Clear return values */\n\tmemset( stream, 0, sizeof( STREAM ) );\n\t*requestType = OPENREQUEST_NONE;\n\n\t/* If it's not a generic tunnel, get any additional parameters \n\t   required */\n\tif( serviceType != SERVICE_SHELL )\n\t\t{\n\t\tstatus = getChannelAttributeS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t   arg1String, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t   &arg1Len );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Missing channel argument (%s) for channel \"\n\t\t\t\t\t  \"activation\", \n\t\t\t\t\t  ( serviceType == SERVICE_PORTFORWARD ) ? \\\n\t\t\t\t\t\t\"host name/port\" : \\\n\t\t\t\t\t  ( serviceType == SERVICE_EXEC ) ? \\\n\t\t\t\t\t\t\"command\" : \\\n\t\t\t\t\t\t\"subsystem name\" ) );\n\t\t\t}\n\t\t}\n\n\t/* If we know that the argument is a URL (rather than a subsystem name \n\t   or command), check its validity */\n\tif( serviceType == SERVICE_PORTFORWARD )\n\t\t{\n\t\tstatus = sNetParseURL( &urlInfo, arg1String, arg1Len, URL_TYPE_SSH );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid channel argument (host name/port) for \"\n\t\t\t\t\t  \"channel activation\" ) );\n\t\t\t}\n\n\t\t/* Tell the caller what to do after the channel open */\n\t\t*requestType = OPENREQUEST_CHANNELONLY;\n\t\t}\n\telse\n\t\t{\n\t\t/* Set the request type to tell the caller what to do after they've\n\t\t   sent the initial channel open */\n\t\t*requestType = OPENREQUEST_SESSION;\n\t\t}\n\n#if 0\t/* 17/9/04 This is a complex mechanism that requires the use of an\n\t\t\t\t   interactive or scriptable tool to use, until someone \n\t\t\t\t   really needs this we don't implement it */\n\t/* Request forwarding of a port from the remote system to the local one.  \n\t   Once a connection arrives on the remote port it'll open a channel to \n\t   the local system of type \"forwarded-tcpip\".  Since this isn't a \n\t   normal channel open, we return a special status to let the caller \n\t   know that there's nothing further to do */\n\tif( serviceType == SERVICE_PORTFORWARD_REQUEST )\n\t\t{\n\t\tURL_INFO urlInfo;\n\n\t\t*requestType = OPENREQUEST_STANDALONE;\n\n\t\t/*\tbyte\ttype = SSH_MSG_GLOBAL_REQUEST\n\t\t\tstring\trequest_name = \"tcpip-forward\"\n\t\t\tboolean\twant_reply = FALSE\n\t\t\tstring\tremote_address_to_bind (e.g. \"0.0.0.0\")\n\t\t\tuint32\tremote_port_to_bind\n\n\t\t   Since this is a special-case request-only message we let the\n\t\t   caller know that they don't have to proceed further with the\n\t\t   channel-open */\n\t\tstatus = openPacketStreamSSH( stream, SSH_MSG_GLOBAL_REQUEST,\n\t\t\t\t\t\t\t\t\t  &packetOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\twriteString32( stream, \"tcpip-forward\", 13 );\n\t\tsputc( stream, 0 );\n\t\twriteString32( stream, urlInfo.host, urlInfo.hostLen );\n\t\twriteUint32( stream, urlInfo.port );\n\t\treturn( wrapPacketSSH2( sessionInfoPtr, stream, packetOffset ) );\n\t\t}\t\t/* If re-enabled, need to do wrapPacketSSH2() in caller */\n#endif /* 0 */\n\n\t/* Send a channel open:\n\n\t\tbyte\ttype = SSH_MSG_CHANNEL_OPEN\n\t\tstring\tchannel_type\n\t\tuint32\tsender_channel\n\t\tuint32\tinitial_window_size = MAX_WINDOW_SIZE\n\t\tuint32\tmax_packet_size = bufSize\n\t\t...\n\n\t   The use of security protocol-level flow control when there's already\n\t   a far better, heavily analysed and field-tested network protocol-\n\t   level flow control mechanism present is just stupid.  All it does is \n\t   create a performance handbrake where throughput can be reduced by as \n\t   much as an order of magnitude due to SSH's \"flow-control\" getting in \n\t   the way (Putty even has an FAQ entry \"Why is SFTP so much slower than \n\t   scp?\", for which the correct answer should be \"It's the SSH-level \n\t   flow-control braindamage\").  For this reason cryptlib always \n\t   advertises a maximum window size (effectively disabling the SSH-level \n\t   flow control) and lets the network stack and network hardware take \n\t   care of flow control, as they should.  Unfortunately some buggy \n\t   implementations break when sent a window size over a certain limit \n\t   in which case we have to limit the window size, thus reintroducing \n\t   the performance handbrake when dealing with these buggy \n\t   implementations, see the comments for the window handling in \n\t   ssh2_msg.c for details */\n\tstatus = openPacketStreamSSH( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_OPEN );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( serviceType == SERVICE_SUBSYSTEM || serviceType == SERVICE_EXEC )\n\t\t{\n\t\t/* A subsystem is an additional layer on top of the standard\n\t\t   channel so we have to open the channel first and then add the\n\t\t   subsystem later via a channel request rather than opening it\n\t\t   directly.  An exec is a special case that works like the default\n\t\t   type of session operation, \"shell\", but doesn't go via a pty */\n\t\twriteString32( stream, \"session\", 7 );\n\t\t}\n\telse\n\t\t{\n\t\tif( serviceType == SERVICE_PORTFORWARD )\n\t\t\twriteString32( stream, \"direct-tcpip\", 12 );\n\t\telse\n\t\t\t{\n\t\t\tENSURES( serviceType == SERVICE_SHELL );\n\n\t\t\t/* It's a generic secure-tunnel that'll be followed by a pty-\n\t\t\t   request and shell */\n\t\t\twriteString32( stream, \"session\", 7 );\n\t\t\t}\n\t\t}\n\twriteUint32( stream, channelNo );\n\twriteUint32( stream, getWindowSize( sessionInfoPtr ) );\n\tstatus = writeUint32( stream, maxPacketSize );\n\tif( serviceType == SERVICE_PORTFORWARD )\n\t\t{\n\t\t/* The caller has requested a port-forwarding channel open, continue\n\t\t   the basic channel-open packet with port-forwarding information:\n\n\t\t\t...\n\t\t\tstring\tremote_host_to_connect\n\t\t\tuint32\trempte_port_to_connect\n\t\t\tstring\tlocal_originator_IP_address\n\t\t\tuint32\tlocal_originator_port */\n\t\twriteString32( stream, urlInfo.host, urlInfo.hostLen );\n\t\twriteUint32( stream, urlInfo.port );\n\t\twriteString32( stream, \"127.0.0.1\", 9 );\n\t\tstatus = writeUint32( stream, 22 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n#else\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int createOpenRequest( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  OUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_ENUM( SERVICE ) const SERVICE_TYPE serviceType,\n\t\t\t\t\t\t\t  OUT_ENUM_OPT( OPENREQUEST ) \\\n\t\t\t\t\t\t\t\t\tOPENREQUEST_TYPE *requestType )\n\t{\n\tconst long channelNo = getCurrentChannelNo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tCHANNEL_WRITE );\n\tconst int maxPacketSize = sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t  EXTRA_PACKET_SIZE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( requestType, sizeof( OPENREQUEST_TYPE ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( serviceType, SERVICE ) );\n\n\t/* Set the request type to tell the caller what to do after they've sent \n\t   the initial channel open */\n\t*requestType = OPENREQUEST_SESSION;\n\n\t/* Send a channel open:\n\n\t\tbyte\ttype = SSH_MSG_CHANNEL_OPEN\n\t\tstring\tchannel_type\n\t\tuint32\tsender_channel\n\t\tuint32\tinitial_window_size = MAX_WINDOW_SIZE\n\t\tuint32\tmax_packet_size = bufSize\n\t\t...\n\n\t   The use of security protocol-level flow control when there's already\n\t   a far better, heavily analysed and field-tested network protocol-\n\t   level flow control mechanism present is just stupid.  All it does is \n\t   create a performance handbrake where throughput can be reduced by as \n\t   much as an order of magnitude due to SSH's \"flow-control\" getting in \n\t   the way (Putty even has an FAQ entry \"Why is SFTP so much slower than \n\t   scp?\", for which the correct answer should be \"It's the SSH-level \n\t   flow-control braindamage\").  For this reason cryptlib always \n\t   advertises a maximum window size (effectively disabling the SSH-level \n\t   flow control) and lets the network stack and network hardware take \n\t   care of flow control, as they should.  Unfortunately some buggy \n\t   implementations break when sent a window size over a certain limit \n\t   in which case we have to limit the window size, thus reintroducing \n\t   the performance handbrake when dealing with these buggy \n\t   implementations, see the comments for the window handling in \n\t   ssh2_msg.c for details */\n\tstatus = openPacketStreamSSH( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_OPEN );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteString32( stream, \"session\", 7 );\n\twriteUint32( stream, channelNo );\n\twriteUint32( stream, getWindowSize( sessionInfoPtr ) );\n\tstatus = writeUint32( stream, maxPacketSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSH_EXTENDED */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createSessionOpenRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t IN_ENUM( SERVICE ) \\\n\t\t\t\t\t\t\t\t\t\tconst SERVICE_TYPE serviceType )\n\t{\n\tconst long channelNo = getCurrentChannelNo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tCHANNEL_WRITE );\n\tint packetOffset, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( serviceType, SERVICE ) );\n\n#ifdef USE_SSH_EXTENDED\n\t/* If the caller has requested the use of a custom subsystem (and at the\n\t   moment the only one that's likely to be used is SFTP), request this\n\t   from the server by modifying the channel that we've just opened to\n\t   run the subsystem */\n\tif( serviceType == SERVICE_SUBSYSTEM )\n\t\t{\n\t\tBYTE arg1String[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint arg1Len;\n\n\t\t/* Get the subsystem type */\n\t\tstatus = getChannelAttributeS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t   arg1String, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t   &arg1Len );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/*\tbyte\ttype = SSH_MSG_CHANNEL_REQUEST\n\t\t\tuint32\trecipient_channel\n\t\t\tstring\trequest_name = \"subsystem\"\n\t\t\tboolean\twant_reply = FALSE\n\t\t\tstring\tsubsystem_name */\n\t\tstatus = openPacketStreamSSH( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_REQUEST );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\twriteUint32( stream, channelNo );\n\t\twriteString32( stream, \"subsystem\", 9 );\n\t\tsputc( stream, 0 );\n\t\tstatus = writeString32( stream, arg1String, arg1Len );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = wrapPacketSSH2( sessionInfoPtr, stream, 0, FALSE );\n\t\treturn( status );\n\t\t}\n\n\t/* If the caller has requested the use of remote command execution (i.e. \n\t   an rexec rather than the usual SSH rsh), run the command directly\n\t   without going via a pty */\n\tif( serviceType == SERVICE_EXEC )\n\t\t{\n\t\tBYTE arg1String[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint arg1Len;\n\n\t\t/* Get the command to execute */\n\t\tstatus = getChannelAttributeS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t   arg1String, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t   &arg1Len );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/*\tbyte\ttype = SSH_MSG_CHANNEL_REQUEST\n\t\t\tuint32\trecipient_channel\n\t\t\tstring\trequest_name = \"exec\"\n\t\t\tboolean\twant_reply = FALSE\n\t\t\tstring\tcommand */\n\t\tstatus = openPacketStreamSSH( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_REQUEST );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\twriteUint32( stream, channelNo );\n\t\twriteString32( stream, \"exec\", 4 );\n\t\tsputc( stream, 0 );\n\t\tstatus = writeString32( stream, arg1String, arg1Len );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = wrapPacketSSH2( sessionInfoPtr, stream, 0, FALSE );\n\t\treturn( status );\n\t\t}\n#endif /* USE_SSH_EXTENDED */\n\n\tREQUIRES( serviceType == SERVICE_SHELL );\n\n\t/* It's a standard channel open:\n\n\t\tbyte\ttype = SSH_MSG_CHANNEL_REQUEST\n\t\tuint32\trecipient_channel\n\t\tstring\trequest_name = \"pty-req\"\n\t\tboolean\twant_reply = FALSE\n\t\tstring\tTERM_environment_variable = \"xterm\"\n\t\tuint32\tcols = 80\n\t\tuint32\trows = 48\n\t\tuint32\tpixel_width = 0\n\t\tuint32\tpixel_height = 0\n\t\tstring\ttty_mode_info = \"\"\n\t\t... */\n\tstatus = openPacketStreamSSH( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteUint32( stream, channelNo );\n\twriteString32( stream, \"pty-req\", 7 );\n\tsputc( stream, 0 );\t\t\t\t\t/* No reply */\n\twriteString32( stream, \"xterm\", 5 );/* Generic */\n\twriteUint32( stream, 80 );\n\twriteUint32( stream, 48 );\t\t\t/* 48 x 80 (24 x 80 is so 1970s) */\n\twriteUint32( stream, 0 );\n\twriteUint32( stream, 0 );\t\t\t/* No graphics capabilities */\n\tstatus = writeUint32( stream, 0 );\t/* No special TTY modes */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, stream, 0, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/*\t...\n\t\tbyte\ttype = SSH_MSG_CHANNEL_REQUEST\n\t\tuint32\trecipient_channel\n\t\tstring\trequest_name = \"shell\"\n\t\tboolean\twant_reply = FALSE\n\n\t   This final request, once sent, moves the server into interactive\n\t   session mode */\n\tstatus = continuePacketStreamSSH( stream, SSH_MSG_CHANNEL_REQUEST,\n\t\t\t\t\t\t\t\t\t  &packetOffset );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\twriteUint32( stream, channelNo );\n\twriteString32( stream, \"shell\", 5 );\n\tstatus = sputc( stream, 0 );\t\t\t/* No reply */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSH2( sessionInfoPtr, stream, packetOffset, FALSE );\n\treturn( status );\n\t}\n\n/* Send a channel open */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint sendChannelOpen( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM stream;\n\tSERVICE_TYPE serviceType;\n\tOPENREQUEST_TYPE requestType;\n\tconst long channelNo = getCurrentChannelNo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\tCHANNEL_READ );\n\tlong currentChannelNo;\n\tint length, value, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Make sure that there's channel data available to activate and\n\t   that it doesn't correspond to an already-active channel */\n\tif( channelNo == UNUSED_CHANNEL_NO )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTINITED,\n\t\t\t\t( CRYPT_ERROR_NOTINITED, SESSION_ERRINFO, \n\t\t\t\t  \"No current channel information available to activate \"\n\t\t\t\t  \"channel\" ) );\n\t\t}\n\tstatus = getChannelAttribute( sessionInfoPtr,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,\n\t\t\t\t\t\t\t\t  &value );\n\tif( cryptStatusError( status ) || value )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INITED,\n\t\t\t\t( CRYPT_ERROR_INITED, SESSION_ERRINFO, \n\t\t\t\t  \"Current channel has already been activated\" ) );\n\t\t}\n\n\t/* Determine the service type that we'll be using */\n\tstatus = getServiceType( sessionInfoPtr, &serviceType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create a request for the appropriate type of service */\n\tstatus = createOpenRequest( sessionInfoPtr, &stream, serviceType, \n\t\t\t\t\t\t\t\t&requestType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the open request to the server.  The SSH spec doesn't really\n\t   explain the semantics of the server's response to the channel open\n\t   command, in particular whether the returned data size parameters are\n\t   merely a confirmation of the client's requested values or whether the\n\t   server is allowed to further modify them to suit its own requirements\n\t   (or perhaps one is for send and the other for receive?).  In the\n\t   absence of any further guidance we just ignore the returned values,\n\t   which seems to work for all deployed servers */\n\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n#if 0\t/* Never used, see comment in createOpenRequest() for \n\t\t   \"tcpip-forward\" type */\n\t/* If it's a request-only message that doesn't open a channel then\n\t   we're done */\n\tif( requestType == OPENREQUEST_STANDALONE )\n\t\treturn( CRYPT_OK );\n#endif /* 0 */\n\n\t/* Wait for the server's ack of the channel open request:\n\n\t\tbyte\tSSH_MSG_CHANNEL_OPEN_CONFIRMATION\n\t\tuint32\trecipient_channel\n\t\tuint32\tsender_channel\n\t\tuint32\tinitial_window_size\n\t\tuint32\tmaximum_packet_size\n\t\t... */\n\tstatus = length = \\\n\t\treadAuthPacketSSH2( sessionInfoPtr, SSH_MSG_SPECIAL_CHANNEL,\n\t\t\t\t\t\t\tID_SIZE + UINT32_SIZE + UINT32_SIZE + \\\n\t\t\t\t\t\t\t\tUINT32_SIZE + UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tif( sessionInfoPtr->sessionSSH->packetType == SSH_MSG_CHANNEL_OPEN_FAILURE )\n\t\t{\n\t\t/* The open failed, report the details to the user */\n\t\tstatus = getOpenFailInfo( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tcurrentChannelNo = readUint32( &stream );\n\tif( currentChannelNo != channelNo )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid channel number %lX in channel open confirmation, \"\n\t\t\t\t  \"should be %lX\", currentChannelNo, channelNo ) );\n\t\t}\n\tstatus = currentChannelNo = readUint32( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid channel data in channel open confirmation for \"\n\t\t\t\t  \"channel %lX\", channelNo ) );\n\t\t}\n\n\t/* The channel has been successfully created, mark it as active and\n\t   select it for future exchanges */\n\tstatus = setChannelExtAttribute( sessionInfoPtr, SSH_ATTRIBUTE_ACTIVE, \n\t\t\t\t\t\t\t\t\t TRUE );\n\tif( cryptStatusOK( status ) && currentChannelNo != channelNo )\n\t\t{\n\t\t/* It's unclear why anyone would want to use different channel\n\t\t   numbers for different directions since it's the same channel that \n\t\t   the data is moving across, but Cisco do it anyway */\n\t\tstatus = setChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_ALTCHANNELNO,\n\t\t\t\t\t\t\t\t\t\t currentChannelNo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst int windowSize = getWindowSize( sessionInfoPtr );\n\n\t\t/* The initial window count is the same as the data window size */\n\t\tstatus = setChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWSIZE,\n\t\t\t\t\t\t\t\t\t\t windowSize );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = setChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWCOUNT,\n\t\t\t\t\t\t\t\t\t\t\t windowSize );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = selectChannel( sessionInfoPtr, channelNo, CHANNEL_BOTH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're just opening a new channel in an existing session then we're \n\t   done */\n\tif( requestType == OPENREQUEST_CHANNELONLY )\n\t\treturn( CRYPT_OK );\n\n\tREQUIRES( requestType == OPENREQUEST_SESSION );\n\n\t/* It's a session open request that requires additional messages to do\n\t   anything useful, create and send the extra packets.  Unlike the \n\t   overall open request, we can't wrap and send the packets in one go\n\t   because serviceType == SERVICE_SHELL has to send multiple packets,\n\t   which are wrapped in createSessionOpenRequest() */\n\tstatus = createSessionOpenRequest( sessionInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t   serviceType );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* serviceType == SERVICE_SHELL creates two packets */\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\t\t}\n\tsMemDisconnect( &stream );\n\treturn( status );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_msgs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib SSHv2 Server-side Channel Message Management\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <stdio.h>\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/* SSH identifies lower-level operations using awkward string-based \n   identifiers, to make these easier to work with we use lookup tables to\n   manage them and optionally map them to integer values */\n\n#ifdef USE_SSH_EXTENDED\ntypedef enum { REQUEST_NONE, REQUEST_SUBSYSTEM, REQUEST_SHELL, REQUEST_EXEC,\n\t\t\t   REQUEST_PORTFORWARD, REQUEST_PORTFORWARD_CANCEL, REQUEST_PTY,\n\t\t\t   REQUEST_NOOP, REQUEST_DISALLOWED } REQUEST_TYPE;\n#else\ntypedef enum { REQUEST_NONE, REQUEST_SHELL, REQUEST_PTY, REQUEST_NOOP, \n\t\t\t   REQUEST_DISALLOWED } REQUEST_TYPE;\n#endif /* USE_SSH_EXTENDED */\n\n#define REQUEST_FLAG_NONE\t\t0x00/* No request flag */\n#define REQUEST_FLAG_TERMINAL\t0x01/* Request ends negotiation */\n\ntypedef struct {\n\tBUFFER_FIXED( requestNameLength ) \\\n\tconst char *requestName;\t\t/* String form of request type */\n\tconst int requestNameLength;\n\tconst REQUEST_TYPE requestType;\t/* Integer form of request type */\n\tconst int flags;\t\t\t\t/* Request flags */\n\t} REQUEST_TYPE_INFO;\n\ntypedef struct {\n\tBUFFER_FIXED( channelNameLength ) \\\n\tconst char *channelName;\t\t/* String form of channel type */\n\tconst int channelNameLength;\n\tconst BOOLEAN isPortForwarding;\n\t} CHANNEL_TYPE_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSH_EXTENDED\n\n/* Read host name/address and port information and format it into string\n   form for the caller */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int readAddressAndPort( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   INOUT STREAM *stream,\n\t\t\t\t\t\t\t   OUT_BUFFER( hostInfoMaxLen, *hostInfoLen ) \\\n\t\t\t\t\t\t\t\t\tchar *hostInfo, \n\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\tconst int hostInfoMaxLen, \n\t\t\t\t\t\t\t   OUT_LENGTH_BOUNDED_Z( hostInfoMaxLen ) \\\n\t\t\t\t\t\t\t\t\tint *hostInfoLen )\n\t{\n\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tchar portBuffer[ 16 + 8 ];\n\tint stringLength, port, portLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( hostInfo, hostInfoMaxLen ) );\n\tassert( isWritePtr( hostInfoLen, sizeof( int ) ) );\n\n\tREQUIRES( hostInfoMaxLen >= 16 && \\\n\t\t\t  hostInfoMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\tmemset( hostInfo, 0, hostInfoMaxLen );\n\t*hostInfoLen = 0;\n\n\t/* Get the host and port:\n\n\t\tstring\thost\n\t\tuint32\tport */\n\tstatus = readString32( stream, stringBuffer, CRYPT_MAX_TEXTSIZE - 4,\n\t\t\t\t\t\t   &stringLength );\n\tif( cryptStatusError( status ) || \\\n\t\tstringLength <= 0 || stringLength > CRYPT_MAX_TEXTSIZE - 4 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid host name value\" ) );\n\t\t}\n\tif( stringLength > hostInfoMaxLen )\n\t\t{\n\t\t/* Limit the returned size to the maximum requested by the caller */\n\t\tstringLength = hostInfoMaxLen;\n\t\t}\n\tstatus = port = readUint32( stream );\n\tif( cryptStatusError( status ) || port <= 0 || port >= 65535L )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid port number value\" ) );\n\t\t}\n\n\t/* Convert the information into string form for the caller to process.  \n\t   Note that although we limit the maximum string length to 8 bytes the\n\t   buffer is actually declared as 16 bytes in size for those systems \n\t   that don't have sprintf_s() */\n\tportLength = sprintf_s( portBuffer, 8, \":%d\", port );\n\tREQUIRES( rangeCheck( stringLength, 1, hostInfoMaxLen ) );\n\tmemcpy( hostInfo, stringBuffer, stringLength );\n\tif( stringLength + portLength <= hostInfoMaxLen )\n\t\t{\n\t\tREQUIRES( boundsCheck( stringLength, portLength, hostInfoMaxLen ) );\n\t\tmemcpy( hostInfo + stringLength, portBuffer, portLength );\n\t\tstringLength += portLength;\n\t\t}\n\t*hostInfoLen = stringLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Add or clear host name/address and port information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int getAddressAndPort( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t\t  OUT_BUFFER( hostInfoMaxLen, *hostInfoLen ) \\\n\t\t\t\t\t\t\t\t\tchar *hostInfo, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\tconst int hostInfoMaxLen,\n\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( hostInfoMaxLen ) \\\n\t\t\t\t\t\t\t\t\tint *hostInfoLen )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( hostInfo, hostInfoMaxLen ) );\n\tassert( isWritePtr( hostInfoLen, sizeof( int ) ) );\n\n\tREQUIRES( hostInfoMaxLen >= 16 && \\\n\t\t\t  hostInfoMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Read the address and port information */\n\tstatus = readAddressAndPort( sessionInfoPtr, stream, hostInfo,\n\t\t\t\t\t\t\t\t hostInfoMaxLen, hostInfoLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( getChannelStatusByAddr( sessionInfoPtr, hostInfo, \\\n\t\t\t\t\t\t\t\t*hostInfoLen ) != CHANNEL_NONE )\n\t\t{\n\t\t/* We're adding new forwarding information, if it already exists \n\t\t   this is an error */\n\t\tretExt( CRYPT_ERROR_DUPLICATE,\n\t\t\t\t( CRYPT_ERROR_DUPLICATE, SESSION_ERRINFO, \n\t\t\t\t  \"Received duplicate request for existing host/port %s\",\n\t\t\t\t  sanitiseString( hostInfo, *hostInfoLen, *hostInfoLen ) ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int clearAddressAndPort( SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t\tSTREAM *stream )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n#if 0\t/* This is a somewhat special-case function in that it does't apply\n\t\t   to an open channel but to a past request for forwarding that\n\t\t   exists outside of the normal attribute space.  Until this type of\n\t\t   functionality is explicitly requested by users we don't handle \n\t\t   this special-case non-attribute data setting */\n\tSSH_CHANNEL_INFO *channelInfoPtr;\n\tchar hostInfo[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint hostInfoLen, status;\n\n\t/* Read the address and port information */\n\tstatus = readAddressAndPort( sessionInfoPtr, stream, hostInfo, \n\t\t\t\t\t\t\t\t hostInfoMaxLen, &hostInfoLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( deleteChannelAddr( sessionInfoPtr, addrInfo, addrInfoLen ) );\n#else\n\treturn( CRYPT_ERROR );\n#endif /* 0 */\n\t}\n#endif /* USE_SSH_EXTENDED */\n\n/* Send a response to a global/channel request */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendChannelResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tIN const long channelNo,\n\t\t\t\t\t\t\t\tconst BOOLEAN isSuccessful )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( ( channelNo == CRYPT_USE_DEFAULT ) || \\\n\t\t\t  ( channelNo >= 0 && channelNo <= CHANNEL_MAX ) );\n\tREQUIRES( isSuccessful == TRUE || isSuccessful == FALSE );\n\n\t/* Indicate that the request succeeded/was denied:\n\n\t\tbyte\ttype = SSH_MSG_CHANNEL/GLOBAL_SUCCESS/FAILURE\n\t\tuint32\tchannel_no */\n\tstatus = enqueueResponse( sessionInfoPtr,\n\t\t\t\tisSuccessful ? SSH_MSG_CHANNEL_SUCCESS : \\\n\t\t\t\t\t\t\t   SSH_MSG_CHANNEL_FAILURE, 1,\n\t\t\t\t( channelNo == CRYPT_USE_DEFAULT ) ? \\\n\t\t\t\t\tgetCurrentChannelNo( sessionInfoPtr, CHANNEL_READ ) : \\\n\t\t\t\t\tchannelNo,\n\t\t\t\tCRYPT_UNUSED, CRYPT_UNUSED, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sendEnqueuedResponse( sessionInfoPtr ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendGlobalResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   const BOOLEAN isSuccessful )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( isSuccessful == TRUE || isSuccessful == FALSE );\n\n\t/* Indicate that the request succeeded/was denied:\n\n\t\tbyte\ttype = SSH_MSG_GLOBAL_SUCCESS/FAILURE */\n\tstatus = enqueueResponse( sessionInfoPtr,\n\t\t\t\tisSuccessful ? SSH_MSG_GLOBAL_SUCCESS : \\\n\t\t\t\t\t\t\t   SSH_MSG_GLOBAL_FAILURE, 0,\n\t\t\t\tCRYPT_UNUSED, CRYPT_UNUSED, CRYPT_UNUSED,\n\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sendEnqueuedResponse( sessionInfoPtr ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChannel Open Management\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a channel open.  These are server-only messages so in theory we\n   could immediately reject them in higher-level code if we're the client\n   but unfortunately we have to process at least some of the message in \n   order to obtain a channel number to use in the response */\n\nstatic const CHANNEL_TYPE_INFO channelInfo[] = {\n\t{ \"session\", 7, FALSE },\n#ifdef USE_SSH_EXTENDED\n\t{ \"direct-tcpip\", 12, TRUE },\n#endif /* USE_SSH_EXTENDED */\n\t{ NULL, 0, FALSE }, { NULL, 0, FALSE }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int sendOpenResponseFailed( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN const long channelNo )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( channelNo >= 0 && channelNo <= CHANNEL_MAX );\n\n\t/* Indicate that the request was denied:\n\n\t\tbyte\tSSH_MSG_CHANNEL_OPEN_FAILURE\n\t\tuint32\trecipient_channel\n\t\tuint32\treason_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED\n\t\tstring\tadditional_text = \"\"\n\t\tstring\tlanguage_tag = \"\"\n\n\t   We always send the same reason code to avoid giving away anything\n\t   to an attacker */\n\tstatus = enqueueResponse( sessionInfoPtr,\n\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_OPEN_FAILURE, 4,\n\t\t\t\t\t\t\t  channelNo,\n\t\t\t\t\t\t\t  SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,\n\t\t\t\t\t\t\t  0, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendEnqueuedResponse( sessionInfoPtr );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelOpen( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tconst CHANNEL_TYPE_INFO *channelInfoPtr = NULL;\n\tBYTE typeString[ CRYPT_MAX_TEXTSIZE + 8 ];\n#ifdef USE_SSH_EXTENDED\n\tBYTE arg1String[ CRYPT_MAX_TEXTSIZE + 8 ];\n#endif /* USE_SSH_EXTENDED */\n\tBYTE buffer[ UINT32_SIZE + 8 ], *arg1Ptr = NULL;\n\tlong channelNo;\n\tint typeLen, arg1Len = 0, maxPacketSize, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Read the channel open request (the type has already been read by the \n\t   caller):\n\n\t  [\tbyte\ttype = SSH_MSG_CHANNEL_OPEN ]\n\t\tstring\tchannel_type = \"session\" | \"direct-tcpip\"\n\t\tuint32\tsender_channel\n\t\tuint32\tinitial_window_size\n\t\tuint32\tmax_packet_size\n\t  [ string\thost_to_connect\t\t- For port-forwarding\n\t\tuint32\tport_to_connect\n\t\tstring\toriginator_IP_address\n\t\tuint32\toriginator_port ]\n\n\t   As with global/channel requests in processChannelOpen() we can't \n\t   return an error indication if we encounter a problem too early in the \n\t   packet, see the comment for that function for further details */\n\tstatus = readString32( stream, typeString, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t   &typeLen );\n\tif( cryptStatusError( status ) || \\\n\t\ttypeLen <= 0 || typeLen > CRYPT_MAX_TEXTSIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid channel type in channel open message\" ) );\n\t\t}\n\tDEBUG_OP(( typeString[ typeLen ] = '\\0' ));\n\tDEBUG_PRINT(( \"Processing channel open '%s'.\\n\", typeString ));\n\n\t/* Try and identify the channel type */\n\tLOOP_SMALL( i = 0, channelInfo[ i ].channelName != NULL && \\\n\t\t\t\t\t   i < FAILSAFE_ARRAYSIZE( channelInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t   CHANNEL_TYPE_INFO ),\n\t\t\t\ti++ )\n\t\t{\n\t\tif( typeLen == channelInfo[ i ].channelNameLength && \\\n\t\t\t!memcmp( typeString, channelInfo[ i ].channelName,\n\t\t\t\t\t typeLen ) )\n\t\t\t{\n\t\t\tchannelInfoPtr = &channelInfo[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( channelInfo, CHANNEL_TYPE_INFO ) );\n\tif( channelInfoPtr == NULL )\n\t\t{\n\t\t/* It's an unsupported channel open type, report it as an error */\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid channel-open channel type '%s'\", \n\t\t\t\t  sanitiseString( typeString, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  typeLen ) ) );\n\t\t}\n\n\t/* Read the channel number and window size.  Quite a number of \n\t   implementations use the same approach that we do to the windowing \n\t   problem and advertise a maximum-size window, since this is \n\t   typically INT_MAX (used by e.g. PSFTP, WinSCP, and FileZilla) we \n\t   have to use an sread() rather than the range-checking readUint32() \n\t   to read (or at least skip) this */\n\tchannelNo = readUint32( stream );\n\t( void ) sread( stream, buffer, UINT32_SIZE );\t/* Skip window size */\n\n\t/* Read the maximum packet size */\n\tstatus = maxPacketSize = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid '%s' channel parameters\", \n\t\t\t\t  channelInfoPtr->channelName ) );\n\t\t}\n\tif( maxPacketSize < PACKET_SIZE_MIN || maxPacketSize > PACKET_SIZE_MAX )\n\t\t{\n\t\t/* General sanity check to make sure that the packet size is in \n\t\t   range.  We've finally got valid packet data so we can send error \n\t\t   responses from now on */\n\t\t( void ) sendOpenResponseFailed( sessionInfoPtr, channelNo );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid '%s' channel maximum packet size parameter \"\n\t\t\t\t  \"value %d, should be 1K...1MB\", \n\t\t\t\t  channelInfoPtr->channelName, maxPacketSize ) );\n\t\t}\n\tmaxPacketSize = min( maxPacketSize, \\\n\t\t\t\t\t\t sessionInfoPtr->receiveBufSize - EXTRA_PACKET_SIZE );\n\n\t/* Read any other information that may be present */\n#ifdef USE_SSH_EXTENDED\n\tif( channelInfoPtr->isPortForwarding )\n\t\t{\n\t\t/* Get the source and destination host information */\n\t\tstatus = getAddressAndPort( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\t\targ1String, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t&arg1Len );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t( void ) sendOpenResponseFailed( sessionInfoPtr, channelNo );\n\t\t\treturn( status );\n\t\t\t}\n\t\targ1Ptr = arg1String;\n\t\t}\n#endif /* USE_SSH_EXTENDED */\n\n\t/* If this is the client then opening a new channel by the server isn't\n\t   permitted */\n\tif( !isServer( sessionInfoPtr ) )\n\t\t{\n\t\t( void ) sendOpenResponseFailed( sessionInfoPtr, channelNo );\n\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t  \"Server attempted to a open a '%s' channel to the client\",\n\t\t\t\t  channelInfoPtr->channelName ) );\n\t\t}\n\n\tENSURES( isServer( sessionInfoPtr ) );\n\n\t/* Add the new channel */\n\tstatus = addChannel( sessionInfoPtr, channelNo, maxPacketSize,\n\t\t\t\t\t\t typeString, typeLen, arg1Ptr, arg1Len );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t( void ) sendOpenResponseFailed( sessionInfoPtr, channelNo );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't add new '%s' channel %lX\", \n\t\t\t\t  channelInfoPtr->channelName, channelNo ) );\n\t\t}\n\n\t/* Send back the open confirmation:\n\n\t\tbyte\ttype = SSH_MSG_CHANNEL_OPEN_CONFIRMATION\n\t\tuint32\trecipient_channel = prev. sender_channel\n\t\tuint32\tsender_channel\n\t\tuint32\tinitial_window_size = MAX_WINDOW_SIZE\n\t\tuint32\tmax_packet_size = bufSize\n\n\t   The SSH spec doesn't really explain the semantics of the server's\n\t   response to the channel open command, in particular whether the\n\t   returned data size parameters are merely a confirmation of the\n\t   client's requested values or whether the server is allowed to further\n\t   modify them to suit its own requirements (or perhaps one is for send\n\t   and the other for receive?).  In the absence of any further guidance\n\t   we try and comply with a client's request for smaller data\n\t   quantities, but also return a smaller-than-requested data size value\n\t   if they ask for too much data.\n\n\t   See the comments in the client-side channel-open code for the reason\n\t   for the window size */\n\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_OPEN, \n\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_OPEN_1 );\n\tstatus = enqueueResponse( sessionInfoPtr,\n\t\t\t\t\t\t\t  SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 4,\n\t\t\t\t\t\t\t  channelNo, channelNo,\n\t\t\t\t\t\t\t  getWindowSize( sessionInfoPtr ), \n\t\t\t\t\t\t\t  maxPacketSize );\n\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_OPEN, \n\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_OPEN_2 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendEnqueuedResponse( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Since we're already in an error state we can't do much more if \n\t\t   the cleanup from the failed operation fails */\n\t\t( void ) deleteChannel( sessionInfoPtr, channelNo, CHANNEL_BOTH, \n\t\t\t\t\t\t\t\tTRUE );\n\t\treturn( status );\n\t\t}\n\n\t/* The channel has been successfully created, mark it as active and\n\t   select it for future exchanges */\n\tstatus = setChannelExtAttribute( sessionInfoPtr, SSH_ATTRIBUTE_ACTIVE,\n\t\t\t\t\t\t\t\t\t TRUE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst int windowSize = getWindowSize( sessionInfoPtr );\n\n\t\t/* The initial window count is the same as the data window size */\n\t\tstatus = setChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWSIZE,\n\t\t\t\t\t\t\t\t\t\t windowSize );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = setChannelExtAttribute( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t SSH_ATTRIBUTE_WINDOWCOUNT,\n\t\t\t\t\t\t\t\t\t\t\t windowSize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = selectChannel( sessionInfoPtr, channelNo, CHANNEL_BOTH );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tChannel Request Management\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a global or channel request */\n\nstatic const REQUEST_TYPE_INFO requestInfo[] = {\n\t/* Channel/session-creation requests, only permitted on the server-side */\n\t{ \"pty-req\", 7, REQUEST_PTY, REQUEST_FLAG_NONE },\n\t{ \"shell\", 5, REQUEST_SHELL, REQUEST_FLAG_TERMINAL },\n#ifdef USE_SSH_EXTENDED\n\t{ \"subsystem\", 9, REQUEST_SUBSYSTEM, REQUEST_FLAG_TERMINAL },\n\t{ \"tcpip-forward\", 13, REQUEST_PORTFORWARD, REQUEST_FLAG_NONE },\n\t{ \"cancel-tcpip-forward\", 20, REQUEST_PORTFORWARD_CANCEL, REQUEST_FLAG_NONE },\n\t{ \"exec\", 4, REQUEST_EXEC, REQUEST_FLAG_TERMINAL },\n#endif /* USE_SSH_EXTENDED */\n\n\t/* No-op requests */\n\t{ \"env\", 3, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\t{ \"exit-signal\", 11, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\t{ \"exit-status\", 11, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\t{ \"signal\", 6, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\t{ \"xon-xoff\", 8, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\t{ \"window-change\", 13, REQUEST_NOOP, REQUEST_FLAG_NONE },\n\n\t/* Disallowed requests */\n\t{ \"x11-req\", 7, REQUEST_DISALLOWED, REQUEST_FLAG_NONE },\n\t{ NULL, 0, REQUEST_NONE, REQUEST_FLAG_NONE },\n\t\t{ NULL, 0, REQUEST_NONE, REQUEST_FLAG_NONE }\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processChannelRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t\t   IN const long prevChannelNo )\n\t{\n\tconst REQUEST_TYPE_INFO *requestInfoPtr = NULL;\n\tconst BOOLEAN isChannelRequest = \\\n\t\t\t( prevChannelNo != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tBOOLEAN wantReply, requestOK = TRUE;\n\tint stringLength, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( ( prevChannelNo == CRYPT_UNUSED ) || \\\n\t\t\t  ( prevChannelNo >= 0 && prevChannelNo <= CHANNEL_MAX ) );\n\n\t/* Process the channel/global request (the type and channel number\n\t   have already been read by the caller):\n\n\t  [\tbyte\ttype = SSH_MSG_CHANNEL_REQUEST / SSH_MSG_GLOBAL_REQUEST ]\n\t  [\tuint32\trecipient_channel\t- For channel reqs ]\n\t\tstring\trequest_type\n\t\tboolean\twant_reply\n\t\t[...]\n\n\t   If there's an error at this point we can't send back a response\n\t   because one or both of the channel number and the want_reply flag\n\t   aren't available yet.  The consensus among SSH implementors was that\n\t   not doing anything if the request packet is invalid is preferable to\n\t   sending back a response with a placeholder channel number or a\n\t   response when want_reply could have been false had it been able to\n\t   be decoded */\n\treadString32( stream, stringBuffer, CRYPT_MAX_TEXTSIZE, &stringLength );\n\tstatus = wantReply = sgetc( stream );\n\tif( cryptStatusError( status ) || \\\n\t\tstringLength <= 0 || stringLength > CRYPT_MAX_TEXTSIZE  )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid request type in %s request packet\",\n\t\t\t\t  isChannelRequest ? \"channel\" : \"global\" ) );\n\t\t}\n\tDEBUG_OP(( stringBuffer[ stringLength ] = '\\0' ));\n\tDEBUG_PRINT(( \"Processing channel request '%s'.\\n\", stringBuffer ));\n\n\t/* Try and identify the request type */\n\tLOOP_MED( i = 0, requestInfo[ i ].requestName != NULL && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( requestInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t REQUEST_TYPE_INFO ), \n\t\t\t  i++ )\n\t\t{\n\t\tif( stringLength == requestInfo[ i ].requestNameLength && \\\n\t\t\t!memcmp( stringBuffer, requestInfo[ i ].requestName,\n\t\t\t\t\t stringLength ) )\n\t\t\t{\n\t\t\trequestInfoPtr = &requestInfo[ i ];\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( requestInfo, REQUEST_TYPE_INFO ) );\n\n\t/* If it's an explicitly disallowed request type or if we're the client\n\t   and it's anything other than a no-op request (for example a request\n\t   to execute a command or perform port forwarding) then it isn't \n\t   permitted */\n\tif( requestInfoPtr == NULL || \\\n\t\trequestInfoPtr->requestType == REQUEST_DISALLOWED || \\\n\t\t( !isServer( sessionInfoPtr ) && \\\n\t\t  requestInfoPtr->requestType != REQUEST_NOOP ) )\n\t\t{\n\t\t/* If the other side doesn't want a response to their request, we're \n\t\t   done */\n\t\tif( !wantReply )\n\t\t\treturn( CRYPT_OK );\n\n\t\t/* Send a request-denied response to the other side's request */\n\t\tif( isChannelRequest )\n\t\t\t{\n\t\t\tint localStatus;\n\n\t\t\t/* The request failed, go back to the previous channel */\n\t\t\tstatus = sendChannelResponse( sessionInfoPtr, prevChannelNo,\n\t\t\t\t\t\t\t\t\t\t  FALSE );\n\t\t\tlocalStatus = selectChannel( sessionInfoPtr, prevChannelNo, \n\t\t\t\t\t\t\t\t\t\t CHANNEL_READ );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = localStatus;\n\t\t\t}\n\t\telse\n\t\t\tstatus = sendGlobalResponse( sessionInfoPtr, FALSE );\n\t\treturn( status );\n\t\t}\n\n\tENSURES( requestInfoPtr != NULL && \\\n\t\t\t ( isServer( sessionInfoPtr ) || \\\n\t\t\t   ( requestInfoPtr->requestType == REQUEST_NOOP ) ) );\n\n\t/* Process the request.  Since these are administrative messages that\n\t   aren't visible to the caller we don't bail out if we encounter a\n\t   problem but just deny the request */\n\tswitch( requestInfoPtr->requestType )\n\t\t{\n\t\tcase REQUEST_SHELL:\n\t\tcase REQUEST_PTY:\n\t\tcase REQUEST_NOOP:\n\t\t\t/* Generic requests containing extra information that we're not\n\t\t\t   interested in */\n\t\t\tbreak;\n\n#ifdef USE_SSH_EXTENDED\n\t\tcase REQUEST_EXEC:\n\t\t\t/* A further generic request that we're not interested in */\n\t\t\tbreak;\n\n\t\tcase REQUEST_SUBSYSTEM:\n\t\t\t/* We're being asked for a subsystem, record the type:\n\n\t\t\t\t[...]\n\t\t\t\tstring\tsubsystem_name */\n\t\t\tstatus = readString32( stream, stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t   &stringLength );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\tstringLength <= 0 || stringLength > CRYPT_MAX_TEXTSIZE )\n\t\t\t\trequestOK = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* The handling of subsystems is somewhat awkward, instead\n\t\t\t\t   of opening a subsystem channel SSH first opens a standard\n\t\t\t\t   session channel and then layers a subsystem on top of it.\n\t\t\t\t   Because of this we have to replace the standard channel\n\t\t\t\t   type with a new subsystem channel-type as well as recording\n\t\t\t\t   the subsystem type */\n\t\t\t\tstatus = setChannelAttributeS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\t\t\t\t\t\t\t\t\t\t   \"subsystem\", 9 );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = setChannelAttributeS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t\t\t\t   stringBuffer, \n\t\t\t\t\t\t\t\t\t\t\t\t   stringLength );\n\t\t\t\t\t}\n\t\t\t\tENSURES( cryptStatusOK( status ) );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase REQUEST_PORTFORWARD:\n\t\t\t/* We're being asked for port forwarding, get the address and\n\t\t\t   port information:\n\n\t\t\t\t[...]\n\t\t\t\tstring\tlocal_address_to_bind (e.g. \"0.0.0.0\")\n\t\t\t\tuint32\tlocal_port_to_bind */\n\t\t\tstatus = getAddressAndPort( sessionInfoPtr, stream, stringBuffer,\n\t\t\t\t\t\t\t\t\t\tCRYPT_MAX_TEXTSIZE, &stringLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\trequestOK = FALSE;\n\t\t\telse\n\t\t\t\t{\n#if 0\t\t\t/* This is a global request that doesn't apply to any\n\t\t\t\t   channel which makes it rather hard to deal with since\n\t\t\t\t   we can't associate it with anything that the user can\n\t\t\t\t   work with.  For now we leave it until there's actual\n\t\t\t\t   user demand for it */\n\t\t\t\tsetChannelAttribute( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t stringBuffer, stringLength );\n#endif /* 0 */\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase REQUEST_PORTFORWARD_CANCEL:\n\t\t\t{\n\t\t\tconst int offset = stell( stream );\n\n\t\t\t/* Check that this is a request to close a port for which\n\t\t\t   forwarding was actually requested.  Since there could be\n\t\t\t   multiple channels open on the forwarded port we keep looking\n\t\t\t   for other channels open on this port until we've cleared them\n\t\t\t   all.  The spec is silent about what happens to open channels\n\t\t\t   when the forwarding is cancelled but from reading between the \n\t\t\t   lines (new channel-open requests can be received until the \n\t\t\t   forwarding is cancelled) it appears that the channels remain \n\t\t\t   active until the channel itself is closed */\n\t\t\tLOOP_MED_INITCHECK( requestOK = FALSE, cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tsseek( stream, offset );\n\t\t\t\tstatus = clearAddressAndPort( sessionInfoPtr, stream );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\trequestOK = TRUE;\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK );\n\t\t\tbreak;\n\t\t\t}\n#endif /* USE_SSH_EXTENDED */\n\n\t\tcase REQUEST_DISALLOWED:\n\t\tdefault:\n\t\t\t/* Anything else we don't allow */\n\t\t\trequestOK = FALSE;\n\t\t\tbreak;\n\t\t}\n\n\t/* Acknowledge the request if necessary */\n\tif( wantReply )\n\t\t{\n\t\tif( isChannelRequest )\n\t\t\t{\n\t\t\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_REQUEST, \n\t\t\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_REQUEST_1 );\n\t\t\tstatus = sendChannelResponse( sessionInfoPtr, prevChannelNo, \n\t\t\t\t\t\t\t\t\t\t  requestOK );\n\t\t\tINJECT_FAULT( SESSION_SSH_CORRUPT_CHANNEL_REQUEST, \n\t\t\t\t\t\t  SESSION_SSH_CORRUPT_CHANNEL_REQUEST_2 );\n\t\t\tif( cryptStatusError( status ) || !requestOK )\n\t\t\t\t{\n\t\t\t\t/* The request failed, go back to the previous channel */\n\t\t\t\tstatus = selectChannel( sessionInfoPtr, prevChannelNo,\n\t\t\t\t\t\t\t\t\t\tCHANNEL_READ );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tstatus = sendGlobalResponse( sessionInfoPtr, requestOK );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If this request ends the negotiation, let the caller know */\n\treturn( ( requestInfoPtr->flags & REQUEST_FLAG_TERMINAL ) ? \\\n\t\t\tOK_SPECIAL : CRYPT_OK );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib SSHv2 Session Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a string description of a packet type, used for diagnostic error\n   messages */\n\n#ifdef USE_ERRMSGS\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSHPacketName( IN_RANGE( 0, SSH_MSG_SPECIAL_LAST ) \\\n\t\t\t\t\t\t\t\t\tconst int packetType )\n\t{\n\tstatic const OBJECT_NAME_INFO packetNameInfo[] = {\n\t\t{ SSH_MSG_DISCONNECT, \"SSH_MSG_DISCONNECT\" },\n\t\t{ SSH_MSG_IGNORE, \"SSH_MSG_IGNORE\" },\n\t\t{ SSH_MSG_UNIMPLEMENTED, \"SSH_MSG_UNIMPLEMENTED\" },\n\t\t{ SSH_MSG_DEBUG, \"SSH_MSG_DEBUG\" },\n\t\t{ SSH_MSG_SERVICE_REQUEST, \"SSH_MSG_SERVICE_REQUEST\" },\n\t\t{ SSH_MSG_SERVICE_ACCEPT, \"SSH_MSG_SERVICE_ACCEPT\" },\n\t\t{ SSH_MSG_EXT_INFO, \"SSH_MSG_EXT_INFO\" },\n\t\t{ SSH_MSG_KEXINIT, \"SSH_MSG_KEXINIT\" },\n\t\t{ SSH_MSG_NEWKEYS, \"SSH_MSG_NEWKEYS\" },\n\t\t{ SSH_MSG_KEXDH_INIT, \n\t\t  \"SSH_MSG_KEXDH_INIT/SSH_MSG_KEX_DH_GEX_REQUEST_OLD/SSH_MSG_KEX_ECDH_INIT\" },\n\t\t{ SSH_MSG_KEXDH_REPLY, \n\t\t  \"SSH_MSG_KEXDH_REPLY/SSH_MSG_KEX_DH_GEX_GROUP/SSH_MSG_KEX_ECDH_REPLY\" },\n\t\t{ SSH_MSG_KEX_DH_GEX_INIT, \"SSH_MSG_KEX_DH_GEX_INIT\" },\n\t\t{ SSH_MSG_KEX_DH_GEX_REPLY, \"SSH_MSG_KEX_DH_GEX_REPLY\" },\n\t\t{ SSH_MSG_KEX_DH_GEX_REQUEST, \"SSH_MSG_KEX_DH_GEX_REQUEST\" },\n\t\t{ SSH_MSG_USERAUTH_REQUEST, \"SSH_MSG_USERAUTH_REQUEST\" },\n\t\t{ SSH_MSG_USERAUTH_FAILURE, \"SSH_MSG_USERAUTH_FAILURE\" },\n\t\t{ SSH_MSG_USERAUTH_SUCCESS, \"SSH_MSG_USERAUTH_SUCCESS\" },\n\t\t{ SSH_MSG_USERAUTH_BANNER, \"SSH_MSG_USERAUTH_BANNER\" },\n\t\t{ SSH_MSG_USERAUTH_INFO_REQUEST, \"SSH_MSG_USERAUTH_INFO_REQUEST\" },\n\t\t{ SSH_MSG_USERAUTH_INFO_RESPONSE, \"SSH_MSG_USERAUTH_INFO_RESPONSE\" },\n\t\t{ SSH_MSG_GLOBAL_REQUEST, \"SSH_MSG_GLOBAL_REQUEST\" },\n\t\t{ SSH_MSG_GLOBAL_SUCCESS, \"SSH_MSG_GLOBAL_SUCCESS\" },\n\t\t{ SSH_MSG_GLOBAL_FAILURE, \"SSH_MSG_GLOBAL_FAILURE\" },\n\t\t{ SSH_MSG_CHANNEL_OPEN, \"SSH_MSG_CHANNEL_OPEN\" },\n\t\t{ SSH_MSG_CHANNEL_OPEN_CONFIRMATION, \n\t\t  \"SSH_MSG_CHANNEL_OPEN_CONFIRMATION\" },\n\t\t{ SSH_MSG_CHANNEL_OPEN_FAILURE, \"SSH_MSG_CHANNEL_OPEN_FAILURE\" },\n\t\t{ SSH_MSG_CHANNEL_WINDOW_ADJUST, \"SSH_MSG_CHANNEL_WINDOW_ADJUST\" },\n\t\t{ SSH_MSG_CHANNEL_DATA, \"SSH_MSG_CHANNEL_DATA\" },\n\t\t{ SSH_MSG_CHANNEL_EXTENDED_DATA, \"SSH_MSG_CHANNEL_EXTENDED_DATA\" },\n\t\t{ SSH_MSG_CHANNEL_EOF, \"SSH_MSG_CHANNEL_EOF\" },\n\t\t{ SSH_MSG_CHANNEL_CLOSE, \"SSH_MSG_CHANNEL_CLOSE\" },\n\t\t{ SSH_MSG_CHANNEL_REQUEST, \"SSH_MSG_CHANNEL_REQUEST\" },\n\t\t{ SSH_MSG_CHANNEL_SUCCESS, \"SSH_MSG_CHANNEL_SUCCESS\" },\n\t\t{ SSH_MSG_CHANNEL_FAILURE, \"SSH_MSG_CHANNEL_FAILURE\" },\n\n\t\t/* Special-case packet types that aren't read from the wire but that\n\t\t   we can get passed as pseudo-expected packet types to denote that \n\t\t   one of a range of types is expected/permitted */\n\t\t{ SSH_MSG_SPECIAL_USERAUTH, \n\t\t  \"SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE or \"\n\t\t  \"SSH_MSG_EXT_INFO\" },\n\t\t{ SSH_MSG_SPECIAL_USERAUTH_PAM, \n\t\t  \"SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, \"\n\t\t  \"SSH_MSG_USERAUTH_INFO_REQUEST, or SSH_MSG_EXT_INFO\" },\n\t\t{ SSH_MSG_SPECIAL_CHANNEL, \n\t\t  \"SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE \"\n\t\t  \"or SSH_MSG_GLOBAL_REQUEST\" },\n\t\t{ SSH_MSG_SPECIAL_REQUEST, \n\t\t  \"SSH_MSG_GLOBAL_REQUEST or SSH_MSG_CHANNEL_REQUEST\" },\n\t\t{ SSH_MSG_SPECIAL_SERVICEACCEPT,\n\t\t  \"SSH_MSG_SERVICE_ACCEPT or SSH_MSG_EXT_INFO\" }, \n\n\t\t{ CRYPT_ERROR, \"<Unknown type>\" },\n\t\t\t{ CRYPT_ERROR, \"<Unknown type>\" }\n\t\t};\n\n\tREQUIRES_EXT( ( packetType >= 0 && packetType <= SSH_MSG_SPECIAL_LAST ),\n\t\t\t\t  \"Internal error\" );\n\n\treturn( getObjectName( packetNameInfo,\n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( packetNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t   OBJECT_NAME_INFO ),\n\t\t\t\t\t\t   packetType ) );\n\t}\n#endif /* USE_ERRMSGS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck a Packet\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Processing handshake data can run into a number of special-case \n   conditions due to buggy SSH implementations, we handle these in a special\n   function to avoid cluttering up the main packet-read code */\n\nCHECK_RETVAL_RANGE( 0, 255 ) STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )\n\t{\n\tSTREAM *stream = streamPtr;\n\tBYTE ch;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sread( stream, &ch, 1 );\n\treturn( cryptStatusError( status ) ? status : byteToInt( ch ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int checkHandshakePacketStatus( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t   IN_RANGE( MAX_ERROR, CRYPT_OK ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int headerStatus,\n\t\t\t\t\t\t\t\t\t   IN_BUFFER( headerLength ) const BYTE *header, \n\t\t\t\t\t\t\t\t\t   IN_LENGTH_SHORT_MIN( MIN_PACKET_SIZE ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int headerLength,\n\t\t\t\t\t\t\t\t\t   IN_RANGE( SSH_MSG_DISCONNECT, \n\t\t\t\t\t\t\t\t\t\t\t\t SSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int expectedType )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( header, headerLength ) );\n\t\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( headerStatus == CRYPT_ERROR_READ || \\\n\t\t\t  cryptStatusOK( headerStatus ) );\n\tREQUIRES( headerLength >= MIN_PACKET_SIZE && \\\n\t\t\t  headerLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( expectedType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  expectedType < SSH_MSG_SPECIAL_LAST );\n\n\t/* If the other side has simply dropped the connection, see if we can \n\t   get further details on what went wrong */\n\tif( headerStatus == CRYPT_ERROR_READ )\n\t\t{\n\t\t/* Some servers just close the connection in response to a bad \n\t\t   password rather than returning an error, if it looks like this \n\t\t   has occurred then we return a more informative error than the \n\t\t   low-level networking one */\n\t\tif( !isServer( sessionInfoPtr ) && \\\n\t\t\t( expectedType == SSH_MSG_SPECIAL_USERAUTH || \\\n\t\t\t  expectedType == SSH_MSG_SPECIAL_USERAUTH_PAM ) )\n\t\t\t{\n\t\t\tretExt( headerStatus,\n\t\t\t\t\t( headerStatus, SESSION_ERRINFO, \n\t\t\t\t\t  \"Remote server has closed the connection, possibly \"\n\t\t\t\t\t  \"in response to an incorrect password or other \"\n\t\t\t\t\t  \"authentication value\" ) );\n\t\t\t}\n\n\t\t/* Some versions of CuteFTP simply drop the connection with no\n\t\t   diagnostics or error information when they get the phase 2 keyex\n\t\t   packet, the best that we can do is tell the user to hassle the\n\t\t   CuteFTP vendor about this */\n\t\tif( isServer( sessionInfoPtr ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSH_PFLAG_CUTEFTP ) && \\\n\t\t\texpectedType == SSH_MSG_NEWKEYS )\n\t\t\t{\n\t\t\tretExt( headerStatus,\n\t\t\t\t\t( headerStatus, SESSION_ERRINFO, \n\t\t\t\t\t  \"CuteFTP client has aborted the handshake due to a \"\n\t\t\t\t\t  \"CuteFTP bug, please contact the CuteFTP vendor\" ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tENSURES( cryptStatusOK( headerStatus ) );\n\n\t/* Versions of SSH derived from the original SSH code base can sometimes\n\t   dump raw text strings (that is, strings not encapsulated in SSH\n\t   packets such as error packets) onto the connection if something\n\t   unexpected occurs.  Normally this would result in a bad data or MAC\n\t   error since they decrypt to garbage so we try and catch them here */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\tSSH_PFLAG_TEXTDIAGS ) && \\\n\t\theader[ 0 ] == 'F' && \\\n\t\t( !memcmp( header, \"FATAL: \", 7 ) || \\\n\t\t  !memcmp( header, \"FATAL ERROR:\", 12 ) ) )\n\t\t{\n\t\tBOOLEAN isTextDataError;\n\t\tint length, status;\n\n\t\t/* Copy across what we've got so far.  Since this is a fatal error,\n\t\t   we use the receive buffer to contain the data since we don't need\n\t\t   it for any further processing */\n\t\tmemcpy( sessionInfoPtr->receiveBuffer, header, \n\t\t\t\tMIN_PACKET_SIZE );\n\n\t\t/* Read the rest of the error message */\n\t\tstatus = readTextLine( readCharFunction, &sessionInfoPtr->stream, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer + MIN_PACKET_SIZE, \n\t\t\t\t\t\t\t   min( MAX_ERRMSG_SIZE - 128, \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize - 128 ), \n\t\t\t\t\t\t\t   &length, &isTextDataError, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we encounter an error reading the rest of the data we just \n\t\t\t   go with what we've already got */\n\t\t\tlength = 0;\n\t\t\t}\n\t\tsessionInfoPtr->receiveBuffer[ MIN_PACKET_SIZE + length ] = '\\0';\n\n\t\t/* Report the error as a problem with the remote software.  Since\n\t\t   the other side has bailed out, we mark the channel as closed to\n\t\t   prevent any attempt to try and perform a standard shutdown.\n\t\t   \"The great thing about a conversation like this, you only have\n\t\t   to have it once\" - Gabriel, \"The Prophecy\" */\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Remote SSH software has crashed, diagnostic was: '%s'\",\n\t\t\t\t  sanitiseString( sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t  MAX_ERRMSG_SIZE - 64, \n\t\t\t\t\t\t\t\t  MIN_PACKET_SIZE + length ) ) );\n\t\t}\n\n\t/* No (obviously) buggy behaviour detected */\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a preliminary check whether a packet is valid for a particular\n   situation */\n\nCHECK_RETVAL \\\nstatic int checkPacketValid( IN_BYTE const int packetType, \n\t\t\t\t\t\t\t const SSH_PROTOCOL_STATE protocolState )\n\t{\n\tstatic const int validHSPacketTbl[] = {\n\t\t/* General messages */\n\t\tSSH_MSG_DISCONNECT, SSH_MSG_IGNORE, SSH_MSG_DEBUG,\n\t\t/* Handshake-only messages */\n\t\tSSH_MSG_SERVICE_REQUEST, SSH_MSG_SERVICE_ACCEPT, SSH_MSG_EXT_INFO, \n\t\tSSH_MSG_KEXINIT, SSH_MSG_NEWKEYS, SSH_MSG_KEXDH_INIT, \n\t\tSSH_MSG_KEXDH_REPLY, SSH_MSG_KEX_DH_GEX_REQUEST_OLD, \n\t\tSSH_MSG_KEX_DH_GEX_GROUP, SSH_MSG_KEX_DH_GEX_INIT, \n\t\tSSH_MSG_KEX_DH_GEX_REPLY, SSH_MSG_KEX_DH_GEX_REQUEST, \n\t\t/* Dual-use messages */\n\t\tSSH_MSG_CHANNEL_OPEN, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, \n\t\tSSH_MSG_CHANNEL_OPEN_FAILURE,\n\t\tCRYPT_ERROR, CRYPT_ERROR };\n\tstatic const int validAuthPacketTbl[] = {\n\t\t/* General messages */\n\t\tSSH_MSG_DISCONNECT, SSH_MSG_IGNORE, SSH_MSG_DEBUG,\n\t\t/* Auth-only messages */\n\t\tSSH_MSG_USERAUTH_REQUEST, SSH_MSG_USERAUTH_FAILURE, \n\t\tSSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_BANNER, \n\t\tSSH_MSG_USERAUTH_INFO_REQUEST, \n\t\tSSH_MSG_USERAUTH_INFO_RESPONSE,\n\t\t/* Dual-use messages */\n\t\tSSH_MSG_CHANNEL_OPEN, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, \n\t\tSSH_MSG_CHANNEL_OPEN_FAILURE,\n\t\t/* Data-only message that can be seen during the auth phase from \n\t\t   some servers */\n\t\tSSH_MSG_GLOBAL_REQUEST, \n\t\tCRYPT_ERROR, CRYPT_ERROR };\n\tstatic const int validDataPacketTbl[] = {\n\t\t/* General messages */\n\t\tSSH_MSG_DISCONNECT, SSH_MSG_IGNORE, SSH_MSG_DEBUG,\n\t\t/* Special-case rehandshake message */\n\t\tSSH_MSG_KEXINIT,\n\t\t/* Data-only messages */\n\t\tSSH_MSG_GLOBAL_REQUEST, SSH_MSG_GLOBAL_SUCCESS, \n\t\tSSH_MSG_GLOBAL_FAILURE,\n\t\t/* Dual-use messages */\n\t\tSSH_MSG_CHANNEL_OPEN, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, \n\t\tSSH_MSG_CHANNEL_OPEN_FAILURE,\n\t\t/* More data-only messages */\n\t\tSSH_MSG_CHANNEL_WINDOW_ADJUST, SSH_MSG_CHANNEL_DATA,\n\t\tSSH_MSG_CHANNEL_EXTENDED_DATA, SSH_MSG_CHANNEL_EOF,\n\t\tSSH_MSG_CHANNEL_CLOSE, SSH_MSG_CHANNEL_REQUEST,\n\t\tSSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE,\n\t\tCRYPT_ERROR, CRYPT_ERROR };\n\tconst int *validPacketTbl = \\\n\t\t\t( protocolState == SSH_PROTOSTATE_HANDSHAKE ) ? validHSPacketTbl : \\\n\t\t\t( protocolState == SSH_PROTOSTATE_AUTH ) ? validAuthPacketTbl : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t   validDataPacketTbl;\n\tconst int validPacketTblSize = \\\n\t\t\t( protocolState == SSH_PROTOSTATE_HANDSHAKE ) ? \\\n\t\t\t  FAILSAFE_ARRAYSIZE( validHSPacketTbl, int ) : \\\n\t\t\t( protocolState == SSH_PROTOSTATE_AUTH ) ? \\\n\t\t\t  FAILSAFE_ARRAYSIZE( validAuthPacketTbl, int ) : \\\n\t\t\t  FAILSAFE_ARRAYSIZE( validDataPacketTbl, int );\n\tint i, LOOP_ITERATOR;\n\n\tREQUIRES( packetType >= 0 && packetType <= 0xFF );\n\tREQUIRES( isEnumRange( protocolState, SSH_PROTOSTATE ) );\n\n\t/* Make sure that the packet is valid */\n\tLOOP_MED( i = 0, i < validPacketTblSize && \\\n\t\t\t\t\t validPacketTbl[ i ] != packetType && \\\n\t\t\t\t\t validPacketTbl[ i ] != CRYPT_ERROR, i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < validPacketTblSize );\n\tif( validPacketTbl[ i ] == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead/Unwrap a Packet\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get the reason why the peer closed the connection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint getDisconnectInfo( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tstatic const MAP_TABLE errorMapTbl[] = {\n\t\t/* A mapping of SSH error codes that have cryptlib equivalents to\n\t\t   the equivalent cryptlib codes.  If there's no mapping available,\n\t\t   we use a default of CRYPT_ERROR_READ */\n\t\t{ SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT, CRYPT_ERROR_PERMISSION },\n\t\t{ SSH_DISCONNECT_MAC_ERROR, CRYPT_ERROR_SIGNATURE },\n\t\t{ SSH_DISCONNECT_SERVICE_NOT_AVAILABLE, CRYPT_ERROR_NOTAVAIL },\n\t\t{ SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED, CRYPT_ERROR_NOTAVAIL },\n\t\t{ SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE, CRYPT_ERROR_WRONGKEY },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tchar errorString[ MAX_ERRMSG_SIZE + 8 ];\n\tint errorCode, clibStatus, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Peer is disconnecting, find out why:\n\n\t  [\tbyte\tSSH_MSG_DISCONNECT ]\n\t\tuint32\treason\n\t\tstring\tdescription\n\t\tstring\tlanguage_tag */\n\terrorCode = readUint32( stream );\n\tif( cryptStatusError( errorCode ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid disconnect status information in disconnect \"\n\t\t\t\t  \"message\" ) );\n\t\t}\n\tstatus = readString32Opt( stream, errorString, MAX_ERRMSG_SIZE - 64, \n\t\t\t\t\t\t\t  &length );\n\tif( cryptStatusOK( status ) && length > 0 )\n\t\t{\n\t\t/* The string is always present but may have a zero length so we \n\t\t   have to check for both its presence and a nonzero size */\n\t\tsanitiseString( errorString, MAX_ERRMSG_SIZE - 64, length );\n\t\t}\n\telse\n\t\t{\n\t\tmemcpy( errorString, \"<No details available>\", 22 + 1 );\n\t\t}\n\tDEBUG_PRINT(( \"Processing disconnect message, reason %d, \"\n\t\t\t\t  \"description '%s'.\\n\", errorCode, errorString ));\n\n\t/* Try and map the SSH status to an equivalent cryptlib one */\n\tif( errorCode <= SSH_DISCONNECT_NONE || errorCode >= SSH_DISCONNECT_LAST )\n\t\t{\n\t\t/* Return a general error code */\n\t\tclibStatus = CRYPT_ERROR_READ;\n\t\t}\n\telse\n\t\t{\n\t\tstatus = mapValue( errorCode, &clibStatus, errorMapTbl,\n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( errorMapTbl, MAP_TABLE ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* We couldn't find anything appropriate, return a general error \n\t\t\t   code */\n\t\t\tclibStatus = CRYPT_ERROR_READ;\n\t\t\t}\n\t\t}\n\tretExt( clibStatus,\n\t\t\t( clibStatus, SESSION_ERRINFO, \n\t\t\t  \"Received disconnect message: %s\", errorString ) );\n\t}\n\n/* Read, decrypt if necessary, and check the start of a packet header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint readPacketHeaderSSH2( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\tSSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\t\tconst int expectedType, \n\t\t\t\t\t\t  OUT_LENGTH_Z int *packetLength,\n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *packetExtraLength,\n\t\t\t\t\t\t  INOUT SSH_INFO *sshInfo,\n\t\t\t\t\t\t  INOUT READSTATE_INFO *readInfo,\n\t\t\t\t\t\t  const SSH_PROTOCOL_STATE protocolState )\n\t{\n\tSTREAM stream;\n\tBYTE headerBuffer[ MIN_PACKET_SIZE + 8 ];\n\tconst BOOLEAN isHandshake = \\\n\t\t\t( protocolState == SSH_PROTOSTATE_HANDSHAKE  || \\\n\t\t\t  protocolState == SSH_PROTOSTATE_AUTH ) ? TRUE : FALSE;\n\tconst BOOLEAN isSecureRead = \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, \\\n\t\t\t\t\t   SESSION_FLAG_ISSECURE_READ ) ? TRUE : FALSE;\n\tBYTE *headerBufPtr = isHandshake ? headerBuffer : sshInfo->headerBuffer;\n\tint length, extraLength = 0, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\tassert( isWritePtr( packetExtraLength, sizeof( int ) ) );\n\tassert( isWritePtr( sshInfo, sizeof( SSH_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( expectedType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  expectedType < SSH_MSG_SPECIAL_LAST );\n\tREQUIRES( isEnumRange( protocolState, SSH_PROTOSTATE ) );\n\n\t/* Clear return values */\n\t*packetLength = 0;\n\t*packetExtraLength = 0;\n\t*readInfo = READINFO_NONE;\n\n\tstatic_assert( CRYPT_MAX_IVSIZE >= MIN_PACKET_SIZE, \\\n\t\t\t\t   \"Packet header size\" );\n\t\t\t/* Packet header is a single cipher block */\n\n\t/* SSH encrypts everything but the MAC (including the packet length) so \n\t   we need to speculatively read ahead for the minimum packet size and \n\t   decrypt that in order to figure out what to do:\n\n\t\tuint32\t\tlength (excluding MAC size)\n\t\tbyte\t\tpadLen\n\t\tbyte\t\ttype\n\t\tbyte[]\t\tdata \n\t\tbyte[]\t\tpad\n\t\tbyte[]\t\tMAC*/\n\tif( isHandshake )\n\t\t{\n\t\t/* Processing handshake data can run into a number of special-case\n\t\t   conditions due to buggy SSH implementations, to handle these we\n\t\t   check the return code as well as the returned data to see if we\n\t\t   need to process it specially */\n\t\tstatus = readFixedHeaderAtomic( sessionInfoPtr, headerBufPtr, \n\t\t\t\t\t\t\t\t\t\tMIN_PACKET_SIZE );\n\t\tif( status == CRYPT_ERROR_READ || cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst int localStatus = \\\n\t\t\t\tcheckHandshakePacketStatus( sessionInfoPtr, status, \n\t\t\t\t\t\t\t\t\t\t\theaderBufPtr, MIN_PACKET_SIZE, \n\t\t\t\t\t\t\t\t\t\t\texpectedType );\n\t\t\tif( cryptStatusError( localStatus ) )\n\t\t\t\tstatus = localStatus;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readFixedHeader( sessionInfoPtr, headerBufPtr, \n\t\t\t\t\t\t\t\t  MIN_PACKET_SIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're in the data-processing stage (i.e. it's a post-handshake\n\t   data packet read) exception conditions need to be handled specially \n\t   if they occur.  In addition if we're still in the handshake stage \n\t   but with encryption enabled (also covered by isSecureRead), the same \n\t   conditions apply */\n\tif( isSecureRead )\n\t\t*readInfo = READINFO_FATAL_CRYPTO;\n\telse\n\t\t*readInfo = READINFO_FATAL;\n\n\t/* The MAC size isn't included in the packet length so we have to add it \n\t   manually if required */\n\tif( isSecureRead )\n\t\textraLength = sessionInfoPtr->authBlocksize;\n\n\t/* Decrypt the header if necessary */\n\tif( isSecureRead )\n\t\t{\n#ifdef USE_SSH_CTR\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t\t{\n\t\t\tstatus = ctrModeCrypt( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t   sshInfo->readCTR, \n\t\t\t\t\t\t\t\t   sessionInfoPtr->cryptBlocksize,\n\t\t\t\t\t\t\t\t   headerBufPtr, MIN_PACKET_SIZE );\n\t\t\t}\n\t\telse\n#endif /* USE_SSH_CTR */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, headerBufPtr,\n\t\t\t\t\t\t\t\t  MIN_PACKET_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Process the packet header.  The dual minimum-length checks actually\n\t   simplify to the following:\n\n\t\tNon-secure mode: length < SSH2_HEADER_REMAINDER_SIZE (extraLength = 0).\n\t\t\tIn this case there's no MAC being used, so all that we need to\n\t\t\tguarantee is that the packet is at least as long as the\n\t\t\t(remaining) data that we've already read.\n\n\t\tSecure mode: length < ID_SIZE + PADLENGTH_SIZE + \\\n\t\t\tSSH2_MIN_PADLENGTH_SIZE.  In this case there's an (implicit) MAC\n\t\t\tpresent so the packet (length + extraLength) will always be\n\t\t\tlarger than the (remaining) data that we've already read.  For\n\t\t\tthis case we need to check that the data payload is at least as\n\t\t\tlong as the minimum-length packet */\n\tsMemConnect( &stream, headerBufPtr, MIN_PACKET_SIZE );\n\tstatus = length = readUint32( &stream );\n\tstatic_assert( SSH_HEADER_REMAINDER_SIZE == MIN_PACKET_SIZE - \\\n\t\t\t\t\t\t\t\t\t\t\t\tLENGTH_SIZE, \\\n\t\t\t\t   \"Header length calculation\" );\n\tif( cryptStatusError( status ) || \\\n\t\tlength + extraLength < SSH_HEADER_REMAINDER_SIZE || \\\n\t\tlength < ID_SIZE + PADLENGTH_SIZE + SSH2_MIN_PADLENGTH_SIZE || \\\n\t\tlength + extraLength >= sessionInfoPtr->receiveBufSize || \\\n\t\tlength >= MAX_BUFFER_SIZE )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid packet length %d, should be %d...%d\", \n\t\t\t\t  cryptStatusError( length ) ? 0 : length,\n\t\t\t\t  ID_SIZE + PADLENGTH_SIZE + SSH2_MIN_PADLENGTH_SIZE,\n\t\t\t\t  sessionInfoPtr->receiveBufSize - extraLength ) );\n\t\t}\n\tif( isSecureRead && \\\n\t\t( LENGTH_SIZE + length ) % sessionInfoPtr->cryptBlocksize != 0 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid packet length %d, isn't a multiple of cipher \"\n\t\t\t\t  \"block size %d\", LENGTH_SIZE + length, \n\t\t\t\t  sessionInfoPtr->cryptBlocksize ) );\n\t\t}\n\n\t/* Extract the pad length and type information.  We have to leave this \n\t   in place in the session buffer because it's MACd later on so we can't \n\t   read it from the stream above but have to manually extract it here */\n\tstatic_assert( LENGTH_SIZE + 1 + ID_SIZE <= MIN_PACKET_SIZE,\n\t\t\t\t   \"Header length calculation\" );\n\tsshInfo->padLength = headerBufPtr[ LENGTH_SIZE ];\n\tsshInfo->packetType = headerBufPtr[ LENGTH_SIZE + 1 ];\n\tif( sshInfo->padLength < SSH2_MIN_PADLENGTH_SIZE || \\\n\t\tsshInfo->padLength > 255 )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid%s packet padding length %d, should be %d...255\", \n\t\t\t\t  isHandshake ? \" handshake\" : \"\", \n\t\t\t\t  sshInfo->padLength, SSH2_MIN_PADLENGTH_SIZE ) );\n\t\t}\n\n\t/* Perform a basic validity check for the packet type */\n\tstatus = checkPacketValid( sshInfo->packetType, protocolState );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid%s packet %s (%d), expected %s (%d)\", \n\t\t\t\t  isHandshake ? \" handshake\" : \"\", \n\t\t\t\t  getSSHPacketName( sshInfo->packetType ), sshInfo->packetType,\n\t\t\t\t  getSSHPacketName( expectedType ), expectedType ) );\n\t\t}\n\n\t/* We've passed the crypto stage, errors are still fatal but no longer\n\t   fatal crypto errors */\n\tif( isSecureRead )\n\t\t*readInfo = READINFO_FATAL;\n\n\t/* Move the body of the header (excluding the length at the start) from \n\t   the header buffer into the session buffer so that we can work with \n\t   it */\n\tENSURES( ( isHandshake && sessionInfoPtr->receiveBufPos == 0 ) || \\\n\t\t\t !isHandshake );\n\tENSURES( boundsCheckZ( sessionInfoPtr->receiveBufPos, \n\t\t\t\t\t\t   SSH_HEADER_REMAINDER_SIZE, \n\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\tstatus = sread( &stream, sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufPos, \n\t\t\t\t\tSSH_HEADER_REMAINDER_SIZE );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*packetLength = length;\n\t*packetExtraLength = extraLength;\n\treturn( CRYPT_OK );\n\t}\n\n/* Read an SSH handshake packet.  This function is only used during the \n   handshake phase (the data transfer phase has its own read/write code) so \n   we can perform some special-case handling based on this.  In particular \n   we know that packets will always be read into the start of the receive \n   buffer so we don't have to perform special buffer-space-remaining \n   calculations */\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readHSPacket( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t   SSH_MSG_SPECIAL_REQUEST ) int expectedType,\n\t\t\t\t\t\t IN_RANGE( 1, 1024 ) const int minPacketSize,\n\t\t\t\t\t\t OUT READSTATE_INFO *readInfo,\n\t\t\t\t\t\t const SSH_PROTOCOL_STATE protocolState )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tconst BOOLEAN isSecureRead = \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, \\\n\t\t\t\t\t   SESSION_FLAG_ISSECURE_READ ) ? TRUE : FALSE;\n\tint length DUMMY_INIT, minPacketLength = minPacketSize, noPackets;\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( expectedType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  expectedType < SSH_MSG_SPECIAL_LAST );\n\tREQUIRES( minPacketSize >= 1 && minPacketSize <= 1024 );\n\tREQUIRES( protocolState == SSH_PROTOSTATE_HANDSHAKE || \\\n\t\t\t  protocolState == SSH_PROTOSTATE_AUTH );\n\n\t/* Errors in reading handshake packets are fatal */\n\t*readInfo = READINFO_FATAL;\n\n\t/* Alongside the expected handshake packets the server can send us all \n\t   sorts of no-op messages ranging from explicit no-ops \n\t   (SSH_MSG_IGNORE) through to general chattiness (SSH_MSG_DEBUG, \n\t   SSH_MSG_USERAUTH_BANNER).  Because we can receive any quantity of \n\t   these at any time we have to run the receive code in a (bounds-\n\t   checked) loop to strip them out (Quo usque tandem abutere, Catilina, \n\t   patientia nostra?) */\n\tLOOP_SMALL( ( sshInfo->packetType = SSH_MSG_IGNORE, noPackets = 0 ),\n\t\t\t\t( sshInfo->packetType == SSH_MSG_IGNORE || \\\n\t\t\t\t  sshInfo->packetType == SSH_MSG_DEBUG || \\\n\t\t\t\t  sshInfo->packetType == SSH_MSG_USERAUTH_BANNER ) && \\\n\t\t\t\tnoPackets < 5, noPackets++ )\n\t\t{\n\t\tint extraLength, status;\n\n\t\t/* Read the SSH handshake packet header:\n\n\t\t\tuint32\t\tlength (excluding MAC size)\n\t\t\tbyte\t\tpadLen\n\t\t\tbyte\t\ttype\n\t\t\tbyte[]\t\tdata\n\t\t\tbyte[]\t\tpadding\n\t\t\tbyte[]\t\tMAC\n\n\t\t  The reason why the length and padding length precede the packet \n\t\t  type and other information is that these two fields are part of \n\t\t  the SSH transport layer while the type and payload are seen as \n\t\t  part of the connection layer, although the different RFCs tend to \n\t\t  mix them up quite thoroughly */\n\t\tREQUIRES( sessionInfoPtr->receiveBufPos == 0 && \\\n\t\t\t\t  sessionInfoPtr->receiveBufEnd == 0 );\n\t\tstatus = readPacketHeaderSSH2( sessionInfoPtr, expectedType, &length,\n\t\t\t\t\t\t\t\t\t   &extraLength, sshInfo, readInfo,\n\t\t\t\t\t\t\t\t\t   protocolState );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tENSURES( length + extraLength >= SSH_HEADER_REMAINDER_SIZE && \\\n\t\t\t\t length + extraLength < sessionInfoPtr->receiveBufSize );\n\t\t\t\t /* Guaranteed by readPacketHeaderSSH2() */\n\n\t\t/* Read the remainder of the handshake-packet message.  The change \n\t\t   cipherspec message has length 0 so we only perform the read if \n\t\t   there's packet data present */\n\t\tif( length + extraLength > SSH_HEADER_REMAINDER_SIZE )\n\t\t\t{\n\t\t\tconst long remainingLength = length + extraLength - \\\n\t\t\t\t\t\t\t\t\t\t SSH_HEADER_REMAINDER_SIZE;\n\t\t\tint readLength;\n\n\t\t\t/* Because this code is called conditionally we can't make the\n\t\t\t   read part of the fixed-header read but have to do independent\n\t\t\t   handling of shortfalls due to read timeouts */\n\t\t\tstatus = readLength = \\\n\t\t\t\tsread( &sessionInfoPtr->stream,\n\t\t\t\t\t   sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\tSSH_HEADER_REMAINDER_SIZE, remainingLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tif( readLength != remainingLength )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Timeout during handshake packet remainder read, \"\n\t\t\t\t\t\t  \"only got %d of %ld bytes\", readLength,\n\t\t\t\t\t\t  remainingLength ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Decrypt and MAC the packet if required */\n\t\tif( isSecureRead )\n\t\t\t{\n\t\t\t/* Errors in this section are fatal crypto errors */\n\t\t\t*readInfo = READINFO_FATAL_CRYPTO;\n\n\t\t\t/* Decrypt the remainder of the packet except for the MAC.\n\t\t\t   Sometimes the payload can be zero-length so we have to check\n\t\t\t   for this before we try the decrypt */\n\t\t\tif( length > SSH_HEADER_REMAINDER_SIZE )\n\t\t\t\t{\n#ifdef USE_SSH_CTR\n\t\t\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t   SSH_PFLAG_CTR ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = ctrModeCrypt( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t\t\t   sshInfo->readCTR, \n\t\t\t\t\t\t\t\t\t\t   sessionInfoPtr->cryptBlocksize,\n\t\t\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\t\t\t\tSSH_HEADER_REMAINDER_SIZE,\n\t\t\t\t\t\t\t\t\t\t   length - SSH_HEADER_REMAINDER_SIZE );\n\t\t\t\t\t}\n\t\t\t\telse\n#endif /* USE_SSH_CTR */\n\t\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\t\t\t\tSSH_HEADER_REMAINDER_SIZE,\n\t\t\t\t\t\t\t\t\t\t  length - SSH_HEADER_REMAINDER_SIZE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\t/* MAC the decrypted payload */\n\t\t\tstatus = checkMacSSH( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t\t  sshInfo->readSeqNo,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t  length + extraLength, length, \n\t\t\t\t\t\t\t\t  extraLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If we're expecting a service control packet after a change\n\t\t\t\t   cipherspec packet and don't get it then it's more likely\n\t\t\t\t   that the problem is due to the wrong key being used than\n\t\t\t\t   data corruption so we return a wrong key error instead of \n\t\t\t\t   bad data */\n\t\t\t\tif( expectedType == SSH_MSG_SERVICE_REQUEST || \\\n\t\t\t\t\texpectedType == SSH_MSG_SERVICE_ACCEPT )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t\t  \"Bad message MAC for %s (%d) packet, length %d, \"\n\t\t\t\t\t\t\t  \"probably due to an incorrect key being used \"\n\t\t\t\t\t\t\t  \"to generate the MAC\", \n\t\t\t\t\t\t\t  getSSHPacketName( sessionInfoPtr->receiveBuffer[ 1 ] ), \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer[ 1 ], length ) );\n\t\t\t\t\t}\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Bad message MAC for %s packet, length %d\", \n\t\t\t\t\t\t  getSSHPacketName( sessionInfoPtr->receiveBuffer[ 1 ] ),\n\t\t\t\t\t\t  length ) );\n\t\t\t\t}\n\n\t\t\t/* Errors are back to normal fatal errors */\n\t\t\t*readInfo = READINFO_FATAL;\n\t\t\t}\n\t\tsshInfo->readSeqNo++;\n\t\tDEBUG_PRINT(( \"Read %s (%d) packet, length %d.\\n\", \n\t\t\t\t\t  getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t\t  sshInfo->packetType,\n\t\t\t\t\t  length - ( 1 + ID_SIZE + sshInfo->padLength ) ));\n\t\tDEBUG_DUMP_DATA( sessionInfoPtr->receiveBuffer + 1 + ID_SIZE, \n\t\t\t\t\t\t length - ( 1 + ID_SIZE + sshInfo->padLength ) );\n\t\tDEBUG_DUMP_SSH( sessionInfoPtr->receiveBuffer, length, TRUE );\n\n\t\t/* The SSH protocol spec is extremely lax about which packets can \n\t\t   appear where, with interoperability relying on the fact that most\n\t\t   implementations only send them in stereotyped patterns (with\n\t\t   interesting breakage being possible if you send a valid but\n\t\t   unexpected packet to some servers).  For example global requests\n\t\t   can be sent at any time (e.g. a channel open during the keyex),\n\t\t   and the other side is expected to deal with them in this state.  \n\t\t   Currently no-one sends global requests during the handshake and\n\t\t   only OpenSSH sends global requests in the middle of the auth\n\t\t   process (the client sends an auth request and gets back a global\n\t\t   request rather than the expected auth response), so we check for \n\t\t   this special case and turn it into a no-op.\n\t\t   \n\t\t   (In theory we're supposed to turn it into a SSH_MSG_REQUEST_FAILURE\n\t\t   response, but the OpenSSH server doesn't seem to mind if it\n\t\t   doesn't get a response and it keeps the logic simpler) */\n\t\tif( protocolState == SSH_PROTOSTATE_AUTH && \\\n\t\t\texpectedType == SSH_MSG_SPECIAL_CHANNEL && \\\n\t\t\tsshInfo->packetType == SSH_MSG_GLOBAL_REQUEST )\n\t\t\t{\n\t\t\t/* Turn a bogus global request in the middle of the auth process\n\t\t\t   into a no-op */\n\t\t\tsshInfo->packetType = SSH_MSG_IGNORE;\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noPackets >= 5 )\n\t\t{\n\t\t/* We have to be a bit careful here in case this is a strange\n\t\t   implementation that sends large numbers of no-op packets as cover\n\t\t   traffic.  Complaining after 5 consecutive no-ops seems to be a \n\t\t   safe tradeoff between catching DoS's and handling cover traffic */\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"%s sent an excessive number of consecutive no-op \"\n\t\t\t\t  \"packets, it may be stuck in a loop\",\n\t\t\t\t  isServer( sessionInfoPtr ) ? \"Client\" : \"Server\" ) );\n\t\t}\n\n\t/* Adjust the length to account for the fixed-size fields, remember\n\t   where the data starts, and make sure that there's some payload\n\t   present (there should always be at least one byte, the packet type) */\n\tlength -= PADLENGTH_SIZE + sshInfo->padLength;\n\tif( sshInfo->packetType == SSH_MSG_DISCONNECT )\n\t\t{\n\t\t/* If we're expecting a standard data packet and we instead get a \n\t\t   disconnect packet due to an error then the length can be less \n\t\t   than the mimimum length of the expected packet.  To make sure \n\t\t   that we don't bail out with a spurious length check failure we \n\t\t   adjust the minPacketLength to the minimum packet length of a \n\t\t   disconnect packet */\n\t\tminPacketLength = ID_SIZE + UINT32_SIZE + \\\n\t\t\t\t\t\t  sizeofString32( 0 ) + sizeofString32( 0 );\n\t\t}\n\tif( length < minPacketLength || \\\n\t\tlength > sessionInfoPtr->receiveBufSize - EXTRA_PACKET_SIZE || \\\n\t\tlength >= MAX_INTLENGTH_SHORT )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid length %d for %s (%d) packet, should be %d...%d\", \n\t\t\t\t  length, getSSHPacketName( sshInfo->packetType ), \n\t\t\t\t  sshInfo->packetType, minPacketLength,\n\t\t\t\t  min( sessionInfoPtr->receiveBufSize - EXTRA_PACKET_SIZE,\n\t\t\t\t\t   MAX_INTLENGTH_SHORT ) ) );\n\t\t}\n\n\t/* Although the packet type is theoretically part of the packet data we\n\t   strip it since it's already reported in the sshInfo, leaving only the\n\t   actual payload data in place */\n\tlength -= ID_SIZE;\n\n\t/* Move the data that's left beyond the header down in the buffer to get \n\t   rid of the header information.  This isn't as inefficient as it seems \n\t   since it's only used for the short handshake messages */\n\tif( length > 0 )\n\t\t{\n\t\tREQUIRES( rangeCheck( length, PADLENGTH_SIZE + ID_SIZE, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufSize ) );\n\t\tmemmove( sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBuffer + PADLENGTH_SIZE + ID_SIZE, \n\t\t\t\t length );\n\t\t}\n\n\t/* If the other side has gone away, report the details */\n\tif( sshInfo->packetType == SSH_MSG_DISCONNECT )\n\t\t{\n\t\tSTREAM stream;\n\t\tint status;\n\n\t\tif( length <= 0 )\n\t\t\treturn( CRYPT_ERROR_BADDATA );\n\t\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\t\tstatus = getDisconnectInfo( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Make sure that we either got what we asked for or one of the allowed\n\t   special-case packets.  When deciding among valid alternatives we \n\t   leave the most obvious choice as the default to look for, which makes\n\t   the error message more meaningful if none of the choices are found */\n\tswitch( expectedType )\n\t\t{\n\t\tcase SSH_MSG_SPECIAL_USERAUTH_PAM:\n\t\t\t/* PAM authentication can go through multiple iterations of back-\n\t\t\t   and-forth negotiation, for this case an information-request is \n\t\t\t   also a valid response, otherwise the responses are as for\n\t\t\t   SSH_MSG_SPECIAL_USERAUTH below */\n\t\t\tif( sshInfo->packetType == SSH_MSG_USERAUTH_INFO_REQUEST )\n\t\t\t\t{\n\t\t\t\texpectedType = SSH_MSG_USERAUTH_INFO_REQUEST;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tSTDC_FALLTHROUGH;\n\n\t\tcase SSH_MSG_SPECIAL_USERAUTH:\n\t\t\t/* If we're reading a response to a user authentication message\n\t\t\t   then getting a failure response is valid (even if it's not\n\t\t\t   what we're expecting) since it's an indication that an\n\t\t\t   incorrect password was used rather than that there was some\n\t\t\t   general type of failure.\n\t\t\t   \n\t\t\t   In addition to getting a success/failure status we can also\n\t\t\t   get an additional extension info message alongside the one\n\t\t\t   sent earlier for SSH_MSG_SPECIAL_SERVICEACCEPT, because the \n\t\t\t   server may want to send additional extension info after\n\t\t\t   authentication */\n\t\t\texpectedType = \\\n\t\t\t\t( sshInfo->packetType == SSH_MSG_EXT_INFO ) ? \\\n\t\t\t\t\tSSH_MSG_EXT_INFO : \\\n\t\t\t\t( sshInfo->packetType == SSH_MSG_USERAUTH_FAILURE ) ? \\\n\t\t\t\t\tSSH_MSG_USERAUTH_FAILURE : \\\n\t\t\t\t\tSSH_MSG_USERAUTH_SUCCESS;\n\t\t\tbreak;\n\n\t\tcase SSH_MSG_SPECIAL_CHANNEL:\n\t\t\t/* If we're reading a response to a channel open message then\n\t\t\t   getting a failure response is valid (even if it's not what\n\t\t\t   we're expecting) since it's an indication that the channel\n\t\t\t   open (for example a port-forwarding operation) failed rather\n\t\t\t   than that there was some general type of failure */\n\t\t\texpectedType = \\\n\t\t\t\t( sshInfo->packetType == SSH_MSG_CHANNEL_OPEN_FAILURE ) ? \\\n\t\t\t\t\tSSH_MSG_CHANNEL_OPEN_FAILURE : \\\n\t\t\t\t\tSSH_MSG_CHANNEL_OPEN_CONFIRMATION;\n\t\t\tbreak;\n\n\t\tcase SSH_MSG_SPECIAL_REQUEST:\n\t\t\t/* If we're at the end of the handshake phase we can get either\n\t\t\t   a global or a channel request to tell us what to do next */\n\t\t\tif( sshInfo->packetType != SSH_MSG_GLOBAL_REQUEST && \\\n\t\t\t\tsshInfo->packetType != SSH_MSG_CHANNEL_REQUEST )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid handshake packet %s (%d), expected \"\n\t\t\t\t\t\t  \"SSH_MSG_GLOBAL_REQUEST (80) or \"\n\t\t\t\t\t\t  \"SSH_MSG_CHANNEL_REQUEST (98)\", \n\t\t\t\t\t\t  getSSHPacketName( sshInfo->packetType ),\n\t\t\t\t\t\t  sshInfo->packetType ) );\n\t\t\t\t}\n\t\t\texpectedType = sshInfo->packetType;\n\t\t\tbreak;\n\n\t\tcase SSH_MSG_KEX_DH_GEX_REQUEST_OLD:\n\t\t\t/* The ephemeral DH key exchange spec was changed halfway\n\t\t\t   through to try and work around problems with key negotiation,\n\t\t\t   because of this we can see two different types of ephemeral\n\t\t\t   DH request, although they're functionally identical */\n\t\t\tif( sshInfo->packetType == SSH_MSG_KEX_DH_GEX_REQUEST )\n\t\t\t\texpectedType = SSH_MSG_KEX_DH_GEX_REQUEST;\n\t\t\tbreak;\n\n\t\tcase SSH_MSG_SPECIAL_SERVICEACCEPT:\n\t\t\t/* This should be a service accept message but may be an \n\t\t\t   extension-info message if the other side is using \n\t\t\t   extensions */\n\t\t\texpectedType = \\\n\t\t\t\t( sshInfo->packetType == SSH_MSG_EXT_INFO ) ? \\\n\t\t\t\t\tSSH_MSG_EXT_INFO : SSH_MSG_SERVICE_ACCEPT;\n\t\t\tbreak;\n\t\t}\n\tif( sshInfo->packetType != expectedType )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid handshake packet %s (%d), expected %s (%d)\", \n\t\t\t\t  getSSHPacketName( sshInfo->packetType ), sshInfo->packetType,\n\t\t\t\t  getSSHPacketName( expectedType ), expectedType ) );\n\t\t}\n\n\treturn( length );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint readHSPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\tSSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\tint expectedType,\n\t\t\t\t\t  IN_RANGE( 1, 1024 ) const int minPacketSize )\n\t{\n\tREADSTATE_INFO readInfo;\n\tint status;\n\n\tstatus = readHSPacket( sessionInfoPtr, expectedType, minPacketSize,\n\t\t\t\t\t\t   &readInfo, SSH_PROTOSTATE_HANDSHAKE );\n\tif( cryptStatusOK( status ) && readInfo == READINFO_FATAL_CRYPTO )\n\t\t{\n\t\t/* We have to explicitly handle crypto failures at this point \n\t\t   because we're not being called from the higher-level session\n\t\t   read handlers that do this for us */\n\t\tregisterCryptoFailure();\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL_LENGTH_SHORT STDC_NONNULL_ARG( ( 1 ) ) \\\nint readAuthPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tIN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t  SSH_MSG_SPECIAL_REQUEST ) \\\n\t\t\t\t\t\t\tint expectedType,\n\t\t\t\t\t\tIN_RANGE( 1, 1024 ) const int minPacketSize )\n\t{\n\tREADSTATE_INFO readInfo;\n\tint status;\n\n\tstatus = readHSPacket( sessionInfoPtr, expectedType, minPacketSize,\n\t\t\t\t\t\t   &readInfo, SSH_PROTOSTATE_AUTH );\n\tif( cryptStatusOK( status ) && readInfo == READINFO_FATAL_CRYPTO )\n\t\t{\n\t\t/* We have to explicitly handle crypto failures at this point \n\t\t   because we're not being called from the higher-level session\n\t\t   read handlers that do this for us */\n\t\tregisterCryptoFailure();\n\t\t}\n\treturn( status );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_svr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tcryptlib SSHv2 Server\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the public-key algorithm that we'll be advertising to the client \n   based on the server key */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initPubkeyAlgo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tstatic const ALGO_STRING_INFO algoStringPubkeyRSATbl[] = {\n\t\t{ \"rsa-sha2-256\", 12, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2 },\n\t\t{ \"ssh-rsa\", 7, CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1 },\n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }, \n\t\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }\n\t\t};\n\tstatic const ALGO_STRING_INFO algoStringPubkeyDSATbl[] = {\n\t\t{ \"ssh-dss\", 7, CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1 },\n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }, \n\t\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }\n\t\t};\n#ifdef USE_ECDSA\n\tstatic const ALGO_STRING_INFO algoStringPubkeyECDSATbl[] = {\n\t\t{ \"ecdsa-sha2-nistp256\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2 },\n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }, \n\t\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }\n\t\t};\n\tstatic const ALGO_STRING_INFO algoStringPubkeyECDSA384Tbl[] = {\n\t\t{ \"ecdsa-sha2-nistp384\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2 },\n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }, \n\t\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }\n\t\t};\n\tstatic const ALGO_STRING_INFO algoStringPubkeyECDSA521Tbl[] = {\n\t\t{ \"ecdsa-sha2-nistp521\", 19, CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2 },\n\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }, \n\t\t\t{ NULL, 0, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE }\n\t\t};\n\tint keySize;\n#endif /* USE_ECDSA */\n\tint pubKeyAlgo, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\t/* Find out which algorithm the server key is using */\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pubKeyAlgo,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thandshakeInfo->pubkeyAlgo = pubKeyAlgo;\t/* int vs.enum */\n\n\t/* If it's a standard public-key algorithm, return the algorithm \n\t   information directly */\n\tif( handshakeInfo->pubkeyAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyRSATbl;\n\t\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyRSATbl, ALGO_STRING_INFO );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( handshakeInfo->pubkeyAlgo == CRYPT_ALGO_DSA )\n\t\t{\n\t\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyDSATbl;\n\t\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyDSATbl, ALGO_STRING_INFO );\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef USE_ECDSA\n\tENSURES( handshakeInfo->pubkeyAlgo == CRYPT_ALGO_ECDSA );\n\n\t/* ECDSA gets more complicated because there are multiple fixed key \n\t   sizes possible so we have to vary the algrithm table based on our key \n\t   size */\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( keySize )\n\t\t{\n\t\tcase bitsToBytes( 256 ):\n\t\t\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyECDSATbl;\n\t\t\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyECDSATbl, ALGO_STRING_INFO );\n\t\t\tbreak;\n\n\t\tcase bitsToBytes( 384 ):\n\t\t\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyECDSA384Tbl;\n\t\t\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyECDSA384Tbl, ALGO_STRING_INFO );\n\t\t\tbreak;\n\n\t\tcase bitsToBytes( 521 ):\n\t\t\thandshakeInfo->algoStringPubkeyTbl = algoStringPubkeyECDSA521Tbl;\n\t\t\thandshakeInfo->algoStringPubkeyTblNoEntries = \\\n\t\t\t\tFAILSAFE_ARRAYSIZE( algoStringPubkeyECDSA521Tbl, ALGO_STRING_INFO );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\treturn( CRYPT_OK );\n#else\n\tretIntError();\n#endif /* USE_ECDSA */\n\t}\n\n/* Handle an ephemeral DH key exchange */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processDHE( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE keyData[ ( CRYPT_MAX_PKCSIZE * 2 ) + 16 + 8 ];\n\tvoid *keyexInfoPtr DUMMY_INIT_PTR;\n\tint keyexInfoLength, keyDataStart, keyDataLength, length;\n\tint keySize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Get the keyex key request from the client:\n\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_REQUEST_OLD\n\t\tuint32\tn (bits)\n\n\t   or:\n\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_REQUEST\n\t\tuint32\tmin (bits)\n\t\tuint32\tn (bits)\n\t\tuint32\tmax (bits)\n\n\t   Since we need to deal with either, readHSPacketSSH2() takes a call to \n\t   read SSH_MSG_KEX_DH_GEX_REQUEST_OLD as allowing both.\n\n\t   Portions of the the request information are hashed later as part of \n\t   the exchange hash so we have to save a copy for then.  We save the\n\t   original encoded form because some clients send non-integral lengths\n\t   that don't survive the conversion from bits to bytes */\n\tstatus = length = \\\n\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_KEX_DH_GEX_REQUEST_OLD,\n\t\t\t\t\t\t  ID_SIZE + UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstreamBookmarkSet( &stream, keyexInfoLength );\n\tif( sessionInfoPtr->sessionSSH->packetType == SSH_MSG_KEX_DH_GEX_REQUEST )\n\t\t{\n\t\tint minKeySize;\n\n\t\t/* It's a { min_length, length, max_length } sequence, save a copy\n\t\t   and get the length value */\n\t\tminKeySize = readUint32( &stream );\n\t\tkeySize = readUint32( &stream );\n\t\tstatus = readUint32( &stream );\n\t\tDEBUG_PRINT(( \"Client specified key size range %d...%d (%d \"\n\t\t\t\t\t  \"preferred) bits.\\n\", minKeySize, status, keySize ));\n\n\t\t/* Some implementations (e.g. OpenSSH >= 6.7) request ridiculous key \n\t\t   sizes, to deal with this we change the effective key size to \n\t\t   CRYPT_MAX_PKCSIZE if the client has asked for a key size > \n\t\t   CRYPT_MAX_PKCSIZE but also specified that they'll accept a \n\t\t   min_length <= CRYPT_MAX_PKCSIZE */\n\t\tif( !cryptStatusError( status ) && \\\n\t\t\tkeySize > bytesToBits( CRYPT_MAX_PKCSIZE ) && \\\n\t\t\tminKeySize <= bytesToBits( CRYPT_MAX_PKCSIZE ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"Client requested excessive key size %d bits but \"\n\t\t\t\t\t\t  \"specified %d...%d bits, using %d bits.\\n\", \n\t\t\t\t\t\t  keySize, minKeySize, status, \n\t\t\t\t\t\t  bytesToBits( CRYPT_MAX_PKCSIZE ) ));\n\t\t\tkeySize = bytesToBits( CRYPT_MAX_PKCSIZE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a straight length, save a copy and get the length value */\n\t\tstatus = keySize = readUint32( &stream );\n\t\tDEBUG_PRINT(( \"Client specified key size %d bits.\\n\", keySize ));\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &keyexInfoPtr, \n\t\t\t\t\t\t\t\t\t\t &keyexInfoLength, keyexInfoLength );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid ephemeral DH key data request packet\" ) );\n\t\t}\n\tANALYSER_HINT( keyexInfoPtr != NULL );\n\tif( keySize < bytesToBits( MIN_PKCSIZE ) || \\\n\t\tkeySize > bytesToBits( CRYPT_MAX_PKCSIZE ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Client requested invalid ephemeral DH key size %d bits, \"\n\t\t\t\t  \"should be %d...%d\", keySize, \n\t\t\t\t  bytesToBits( MIN_PKCSIZE ), \n\t\t\t\t  bytesToBits( CRYPT_MAX_PKCSIZE ) ) );\n\t\t}\n\tREQUIRES( rangeCheck( keyexInfoLength, 1, MAX_ENCODED_KEYEXSIZE ) );\n\tmemcpy( handshakeInfo->encodedReqKeySizes, keyexInfoPtr,\n\t\t\tkeyexInfoLength );\n\thandshakeInfo->encodedReqKeySizesLength = keyexInfoLength;\n\thandshakeInfo->requestedServerKeySize = bitsToBytes( keySize );\n\n\t/* If we're fuzzing the input then we're done */\n\tFUZZ_SET( handshakeInfo->serverKeySize, \n\t\t\t  handshakeInfo->requestedServerKeySize );\n\tFUZZ_SKIP();\n\n\t/* Load a DH key of the appropriate size.  Things get quite confusing \n\t   here because the spec is a schizophrenic mix of two different \n\t   documents, one that specifies the behaviour for the original message \n\t   format which uses a single length value and a second one that \n\t   specifies the behaviour for the { min, n, max } combination (multi \n\t   sunt, qui ad id, quod non proposuerant scribere, alicuius verbi \n\t   placentis decore vocentur).\n\t   \n\t   The range option was added as an attempted fix for implementations \n\t   that couldn't handle the single size option but the real problem is \n\t   that the server knows what key sizes are appropriate but the client \n\t   has to make the choice, without any knowledge of what the server can \n\t   actually handle.  Because of this the spec (in its n-only mindset, \n\t   which also applies to the min/n/max version since it's the same \n\t   document) contains assorted weasel-words that allow the server to \n\t   choose any key size it feels like if the client sends a range \n\t   indication that's inappropriate.  Although the spec ends up saying \n\t   that the server can do anything it feels like (\"The server should \n\t   return the smallest group it knows that is larger than the size the \n\t   client requested.  If the server does not know a group that is \n\t   larger than the client request, then it SHOULD return the largest \n\t   group it knows\"), we use a least-upper-bound interpretation of the \n\t   above, mostly because we store a range of fixed keys of different \n\t   sizes and can always find something reasonably close to any \n\t   (sensible) requested length */\n\tstatus = initDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t   &handshakeInfo->serverKeySize, NULL, 0,\n\t\t\t\t\t\t\t   handshakeInfo->requestedServerKeySize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the DH key values to the client:\n\n\t\tbyte\ttype = SSH_MSG_KEXDH_GEX_GROUP\n\t\tmpint\tp\n\t\tmpint\tg\n\n\t   Since this phase of the key negotiation exchanges raw key components\n\t   rather than the standard SSH public-key format we have to rewrite\n\t   the public key before we can send it to the client.  What this \n\t   involves is stripping the:\n\n\t\tuint32\tlength\n\t\tstring\t\"ssh-dh\"\n\n\t   header from the start of the datab and then writing what's left to the \n\t   packet.  First we export the key data and figure out the location of\n\t   the payload that we need to send */\n\tsetMessageData( &msgData, keyData, ( CRYPT_MAX_PKCSIZE * 2 ) + 16 );\n\tstatus = krnlSendMessage( handshakeInfo->iServerCryptContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, keyData, msgData.length );\n\treadUint32( &stream );\t\t\t\t\t/* Length */\n\tstatus = readUniversal32( &stream );\t/* ID string */\n\tENSURES( cryptStatusOK( status ) );\n\tkeyDataStart = stell( &stream );\n\tkeyDataLength = sMemDataLeft( &stream );\n\tsMemDisconnect( &stream );\n\n\t/* Then we create and send the SSH packet using as the payload the key\n\t   data content of the SSH public key */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  SSH_MSG_KEX_DH_GEX_GROUP );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = swrite( &stream, keyData + keyDataStart, keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tServer-side Connect Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform the initial part of the handshake with the client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int beginServerHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM stream;\n\tBOOLEAN skipGuessedKeyex = FALSE;\n\tvoid *serverHelloPtr DUMMY_INIT_PTR;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, serverHelloLength, clientHelloLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Get the public-key algorithm that we'll be advertising to the client\n\t   and set the algorithm table used for processing the client hello to\n\t   match the one that we're offering */\n\tstatus = initPubkeyAlgo( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"initPubkeyAlgo\" );\n\n\t/* SSH hashes the handshake ID strings for integrity-protection purposes, \n\t   first the client string that we read previously and then our server \n\t   string */\n\tstatus = hashHandshakeStrings( handshakeInfo, \n\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd,\n\t\t\t\t\t\t\t\t   SSH_ID_STRING, SSH_ID_STRING_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"hashHandshakeStrings\" );\n\n\t/* Now that we've processed the out-of-band data in the receive buffer, \n\t   mark it as empty */\n\tsessionInfoPtr->receiveBufEnd = 0;\n\n\t/* Send the server hello packet:\n\n\t\tbyte\t\ttype = SSH_MSG_KEXINIT\n\t\tbyte[16]\tcookie\n\t\tstring\t\tkeyex algorithms\n\t\tstring\t\tpubkey algorithms\n\t\tstring\t\tclient_crypto algorithms\n\t\tstring\t\tserver_crypto algorithms\n\t\tstring\t\tclient_mac algorithms\n\t\tstring\t\tserver_mac algorithms\n\t\tstring\t\tclient_compression algorithms = \"none\"\n\t\tstring\t\tserver_compression algorithms = \"none\"\n\t\tstring\t\tclient_language = \"\"\n\t\tstring\t\tserver_language = \"\"\n\t\tboolean\t\tfirst_keyex_packet_follows = FALSE\n\t\tuint32\t\treserved = 0\n\n\t   The SSH spec leaves the order in which things happen ambiguous, in\n\t   order to save a while round trip it has provisions for both sides\n\t   shouting at each other and then a complex interlock process where\n\t   bits of the initial exchange can be discarded and retried if necessary.\n\t   This is ugly and error-prone.  The client code solves this by waiting\n\t   for the server hello, choosing known-good parameters based on what the\n\t   server communicates in its hello message, and then sending the client \n\t   hello immediately followed by the client key exchange data.  Since it \n\t   waits for the server to speak first it can choose parameters that are \n\t   accepted the first time.\n\n\t   Unfortunately this doesn't work if we're the server since we'd end up \n\t   waiting for the client to speak first while it waits for us to speak \n\t   first, so we have to send the server hello in order to prevent \n\t   deadlock.  This works fine with most clients, which take the same\n\t   approach and wait for the server to speak first.  The message flow is\n\t   then:\n\n\t\tserver hello;\n\t\tclient hello;\n\t\tclient keyex;\n\t\tserver keyex;\n\n\t   There are one or two exceptions to this, the worst of which is older\n\t   versions of the F-Secure client, which has the client speak first \n\t   choosing as its preference the incompletely specified \n\t   \"x509v3-sign-dss\" format (see the comment in exchangeServerKeys() \n\t   below) that we can't use since no-one's quite sure what the format is \n\t   (this was fixed in mid-2004 when the x509v3-* schemes were removed \n\t   from the spec since no-one could figure out what they were.  F-Secure \n\t   still specifies them, but has moved them down so that they follow \n\t   the standard ssh-* schemes).  In this case the message flow is:\n\n\t\tserver hello;\n\t\tclient hello;\n\t\tclient keyex1;\n\t\tclient keyex2;\n\t\tserver keyex;\n\n\t   This is handled by having the code that reads the client hello return\n\t   OK_SPECIAL to indicate that the next packet should be skipped.  An\n\t   alternative (and simpler) strategy would be to always throw away the\n\t   client's first keyex sent by older versions of the F-Secure client\n\t   since they're using an algorithm choice that's impossible to use, but \n\t   that implementation-specific approach doesn't generalise well to \n\t   other versions or other clients */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, SSH_MSG_KEXINIT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamBookmarkSetFullPacket( &stream, serverHelloLength );\n\tstatus = exportVarsizeAttributeToStream( &stream, SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_RANDOM_NONCE,\n\t\t\t\t\t\t\t\t\t\t\t SSH2_COOKIE_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint pkcAlgo;\n\n\t\t/* If the server key is a non-ECC key then it can't be used with an \n\t\t   ECC keyex so we have to explicitly disable it (technically it's \n\t\t   possible to mix ECDH with RSA but this is more likely an error \n\t\t   than anything deliberate) */\n\t\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgo,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = writeAlgoClassList( &stream, isEccAlgo( pkcAlgo ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tSSH_ALGOCLASS_KEYEX : \\\n\t\t\t\t\t\t\t\t\t\t\tSSH_ALGOCLASS_KEYEX_NOECC );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = writeAlgoList( &stream, handshakeInfo->algoStringPubkeyTbl,\n\t\t\t\t\t\t\t\thandshakeInfo->algoStringPubkeyTblNoEntries );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_ENCR );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_ENCR );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_MAC );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_MAC );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_COPR );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = writeAlgoClassList( &stream, SSH_ALGOCLASS_COPR );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\twriteUint32( &stream, 0 );\t\t\t/* No language tag */\n\t\twriteUint32( &stream, 0 );\n\t\tsputc( &stream, 0 );\t\t\t\t/* Don't try and guess the keyex */\n\t\tstatus = writeUint32( &stream, 0 );\t/* Reserved */\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &serverHelloPtr, \n\t\t\t\t\t\t\t\t\t\t &serverHelloLength, \n\t\t\t\t\t\t\t\t\t\t serverHelloLength );\n\t\t}\n\tINJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSH_1 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( serverHelloPtr != NULL );\n\tINJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSH_2 );\n\tCFI_CHECK_UPDATE( \"sendServerHello\" );\n\n\t/* Process the client hello packet and hash the client and server\n\t   hello.  Since the entire encoded packet (including the type value) \n\t   is hashed we have to reconstruct this at the start of the client\n\t   hello packet */\n\tstatus = processHelloSSH( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t  &clientHelloLength, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\n\t\t/* There's a guessed keyex following the client hello that we have\n\t\t   to skip later (we can't process it at this point because we still\n\t\t   need to hash the data sitting in the receive buffer) */\n\t\tskipGuessedKeyex = TRUE;\n\t\t}\n\tREQUIRES( rangeCheck( clientHelloLength, 1,\n\t\t\t\t\t\t  sessionInfoPtr->receiveBufSize ) );\n\tmemmove( sessionInfoPtr->receiveBuffer + 1, \n\t\t\t sessionInfoPtr->receiveBuffer, clientHelloLength );\n\tsessionInfoPtr->receiveBuffer[ 0 ] = SSH_MSG_KEXINIT;\n\tstatus = hashAsString( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t   sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t\t   clientHelloLength + 1 );\n\tif( cryptStatusOK( status ) && skipGuessedKeyex )\n\t\t{\n\t\t/* There's an incorrectly-guessed keyex following the client hello, \n\t\t   skip it */\n\t\tstatus = readHSPacketSSH2( sessionInfoPtr, \n\t\t\t\t\t\t\t\t   ( handshakeInfo->isFixedDH || \\\n\t\t\t\t\t\t\t\t     handshakeInfo->isECDH ) ?\n\t\t\t\t\t\t\t\t\tSSH_MSG_KEXDH_INIT : \\\n\t\t\t\t\t\t\t\t\tSSH_MSG_KEX_DH_GEX_INIT,\n\t\t\t\t\t\t\t\t   ID_SIZE + sizeofString32( MIN_PKCSIZE ) );\n\t\t}\n\tif( !cryptStatusError( status ) )\t/* readHSPSSH2() returns a length */\n\t\t{\n\t\tstatus = hashAsString( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t   serverHelloPtr, serverHelloLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processHelloSSH\" );\n\n\t/* SSH has a whole range of ways to specify the same keyex algorithm \n\t   (see the long comment in ssh.h), the following multi-option code is\n\t   required to handle them.  The original way to do it was to use an\n\t   explicitly-specified DH key, but an alternative mechanism uses a\n\t   negotiated DH key value, in which case we have to request the keyex \n\t   key from the server.  This additional negotiation requires \n\t   disconnecting and re-connecting the data packet stream since it \n\t   exchanges further data with the server, so if there's an error return \n\t   we don't disconnect the stream before we exit */\n\tif( handshakeInfo->isFixedDH )\n\t\t{\n\t\tREQUIRES( !handshakeInfo->isECDH );\n\n\t\t/* It's a fixed-size DH key */\n\t\tstatus = initDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t   &handshakeInfo->serverKeySize, NULL, 0,\n\t\t\t\t\t\t\t\t   handshakeInfo->requestedServerKeySize );\n\t\t}\n\telse\n\t\t{\n#ifdef USE_ECDH \n\t\t/* A second possibility is when we're using ECDH rather than DH, for \n\t\t   which we have to use ECDH contexts and values */\n\t\tif( handshakeInfo->isECDH )\n\t\t\t{\n\t\t\t/* Set up the ECDH context from the server's parameters and \n\t\t\t   perform phase 1 of the ECDH key agreement process */\n\t\t\tstatus = initECDHcontextSSH( &handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t\t\t\t &handshakeInfo->serverKeySize, \n\t\t\t\t\t\t\t\t\t\t handshakeInfo->keyexAlgo );\n\t\t\t}\n\t\telse\n#endif /* USE_ECDH */\n\t\t\t{\n\t\t\tstatus = processDHE( sessionInfoPtr, handshakeInfo );\n \t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create %s ephemeral key data\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processDHE\" );\n\n\t/* Process the client keyex:\n\n\t   DH:\n\t\tbyte\ttype = SSH_MSG_KEXDH_INIT / SSH_MSG_KEXDH_GEX_INIT\n\t\tmpint\ty\n\t   ECDH:\n\t\tbyte\ttype = SSH_MSG_KEX_ECDH_INIT\n\t\tstring\tq_c\n\n\t   SSH_MSG_KEXDH_INIT (isFixedDH) and SSH_MSG_KEX_ECDH_INIT (isECDH) \n\t   have the same value so they're handled with the same code.\n\n\t   Since we're reading the value as a raw object (as it gets hashed \n\t   later), we need to offset the length field of LENGTH_SIZE bytes in\n\t   later calculations with the data */\n\tstatus = length = \\\n\t\treadHSPacketSSH2( sessionInfoPtr,\n\t\t\t\t\t\t  ( handshakeInfo->isFixedDH || \\\n\t\t\t\t\t\t    handshakeInfo->isECDH ) ? \\\n\t\t\t\t\t\t\tSSH_MSG_KEXDH_INIT : SSH_MSG_KEX_DH_GEX_INIT,\n\t\t\t\t\t\t  ID_SIZE + ( handshakeInfo->isECDH ? \\\n\t\t\t\t\t\t\tsizeofString32( MIN_PKCSIZE_ECCPOINT ) : \\\n\t\t\t\t\t\t\tsizeofString32( MIN_PKCSIZE ) ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstatus = readRawObject32( &stream, handshakeInfo->clientKeyexValue,\n\t\t\t\t\t\t\t  MAX_ENCODED_KEYEXSIZE,\n\t\t\t\t\t\t\t  &handshakeInfo->clientKeyexValueLength );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 1 keyex value\",\n\t\t\t\t  handshakeInfo->isECDH ? \"ECDH\" : \"DH\" ) );\n\t\t}\n\tif( handshakeInfo->isECDH )\n\t\t{\n\t\tif( !isValidECDHsize( handshakeInfo->clientKeyexValueLength,\n\t\t\t\t\t\t\t  handshakeInfo->serverKeySize, LENGTH_SIZE ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\telse\n\t\t{\n\t\tif( !isValidDHsize( handshakeInfo->clientKeyexValueLength,\n\t\t\t\t\t\t\thandshakeInfo->serverKeySize, LENGTH_SIZE ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tconst int clientKeyexSize = handshakeInfo->isECDH ? \\\n\t\t\textractECDHsize( handshakeInfo->clientKeyexValueLength, LENGTH_SIZE ) : \\\n\t\t\textractDHsize( handshakeInfo->clientKeyexValueLength, LENGTH_SIZE );\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid %s phase 1 keyex size, expected %d (%d), \"\n\t\t\t\t  \"got %d (%d)\", handshakeInfo->isECDH ? \"ECDH\" : \"DH\",\n\t\t\t\t  handshakeInfo->serverKeySize, \n\t\t\t\t  handshakeInfo->serverKeySize * 8,\n\t\t\t\t  clientKeyexSize, clientKeyexSize * 8 ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"SSH_MSG_KEXDH_INIT\" );\n\n\t/* If we're fuzzing the input then we're reading static data for which \n\t   we can't go beyond this point */\n\tFUZZ_EXIT();\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"initPubkeyAlgo\", \"hashHandshakeStrings\", \n\t\t\t\t\t\t\t\t\t\"sendServerHello\", \"processHelloSSH\", \n\t\t\t\t\t\t\t\t\t\"processDHE\", \"SSH_MSG_KEXDH_INIT\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Exchange keys with the client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int exchangeServerKeys( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tKEYAGREE_PARAMS keyAgreeParams;\n\tSTREAM stream;\n\tvoid *keyPtr DUMMY_INIT_PTR, *dataPtr;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint keyLength, dataLength, sigLength DUMMY_INIT, packetOffset, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Create the server DH/ECDH value */\n\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = krnlSendMessage( handshakeInfo->iServerCryptContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, &keyAgreeParams,\n\t\t\t\t\t\t\t  sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemOpen( &stream, handshakeInfo->serverKeyexValue, \n\t\t\t  MAX_ENCODED_KEYEXSIZE );\n\tif( handshakeInfo->isECDH )\n\t\t{\n\t\tstatus = writeString32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\tkeyAgreeParams.publicValueLen );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = writeInteger32( &stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t keyAgreeParams.publicValueLen );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\thandshakeInfo->serverKeyexValueLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT\" );\n\n\t/* Build the DH phase 2 keyex packet:\n\n\t  DH + RSA/DSA\n\t\tbyte\t\ttype = SSH_MSG_KEXDH_REPLY / SSH_MSG_KEXDH_GEX_REPLY \n\t\tstring\t\t[ server key/certificate ]\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\t\tmpint\te\t\t\tp\t\t\t\n\t\t\tmpint\tn\t\t\tq\n\t\t\tmpint\t\t\t\tg\n\t\t\tmpint\t\t\t\ty\n\t\tmpint\t\ty'\n\t\tstring\t\t[ signature of handshake data ]\n\t\t\tstring\t\"ssh-rsa\"\t\"ssh-dss\"\n\t\t\tstring\tsignature\tsignature\n\t\t...\n\n\t   ECDH + ECDSA\n\t\tbyte\t\tSSH_MSG_KEX_ECDH_REPLY\n\t\tstring\t\t[ server key/certificate ]\n\t\t\tstring\t\"ecdsa-sha2-*\"\n\t\t\tstring\t\"*\"\t\t\t\t-- The \"*\" portion from the above field\n\t\t\tstring\tQ\n\t\tstring\t\tq_s\n\t\tstring\t\t[ signature of handshake data ]\n\t\t\tstring\t\"ecdsa-sha2-*\"\n\t\t\tstring\tsignature\n\t\t...\n\n\t   SSH_MSG_KEXDH_REPLY (isFixedDH) and SSH_MSG_KEX_ECDH_REPLY (isECDH) \n\t   have the same value so they're handled with the same code.\n\n\t   The specification also makes provision for using X.509 and PGP keys,\n\t   but only so far as to say that keys and signatures are in \"X.509 DER\"\n\t   and \"PGP\" formats, neither of which actually explain what it is\n\t   that's sent or signed (and no-one on the SSH list can agree on what\n\t   they're supposed to look like) so we can't use either of them */\n\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  ( handshakeInfo->isFixedDH || \\\n\t\t\t\t\t\t\t\t    handshakeInfo->isECDH ) ? \\\n\t\t\t\t\t\t\t\t\tSSH_MSG_KEXDH_REPLY : \\\n\t\t\t\t\t\t\t\t\tSSH_MSG_KEX_DH_GEX_REPLY );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstreamBookmarkSet( &stream, keyLength );\n\tINJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSH_1 );\n\tstatus = exportAttributeToStream( &stream, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_SSH );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = streamBookmarkComplete( &stream, &keyPtr, &keyLength, \n\t\t\t\t\t\t\t\t\t\t keyLength );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, keyPtr, keyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tINJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSH_2 );\n\tINJECT_FAULT( SESSION_CORRUPT_KEYEX_SERVER, \n\t\t\t\t  SESSION_CORRUPT_KEYEX_SERVER_SSH_1 );\n\tstatus = swrite( &stream, handshakeInfo->serverKeyexValue,\n\t\t\t\t\t handshakeInfo->serverKeyexValueLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tINJECT_FAULT( SESSION_CORRUPT_KEYEX_SERVER, \n\t\t\t\t  SESSION_CORRUPT_KEYEX_SERVER_SSH_1 );\n\tCFI_CHECK_UPDATE( \"SSH_MSG_KEXDH_REPLY\" );\n\n\t/* Complete phase 2 of the DH key agreement process to obtain the shared\n\t   secret value */\n\tstatus = completeKeyex( sessionInfoPtr, handshakeInfo, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"completeKeyex\" );\n\n\t/* Sign the hash.  The reason for the min() part of the expression is\n\t   that iCryptCreateSignature() gets suspicious of very large buffer\n\t   sizes, for example when the user has specified the use of a 1MB send\n\t   buffer */\n\tstatus = sMemGetDataBlockRemaining( &stream, &dataPtr, &dataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = iCryptCreateSignature( dataPtr, \n\t\t\t\t\t\t\tmin( dataLength, MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\t\t&sigLength, CRYPT_IFORMAT_SSH, \n\t\t\t\t\t\t\tsessionInfoPtr->privateKey,\n\t\t\t\t\t\t\thandshakeInfo->iExchangeHashContext, NULL );\n\t\tinsertCryptoDelay();\n\t\t}\n\tkrnlSendNotifier( handshakeInfo->iExchangeHashContext,\n\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\thandshakeInfo->iExchangeHashContext = CRYPT_ERROR;\n\tif( handshakeInfo->iExchangeHashAltContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->iExchangeHashAltContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->iExchangeHashAltContext = CRYPT_ERROR;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tINJECT_FAULT( BADSIG_SIG, SESSION_BADSIG_SIG_SSH_1 );\n\t\tstatus = sSkip( &stream, sigLength, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"iCryptCreateSignature\" );\n\n\t/* Set up the security information required for the session.  We have to \n\t   do this before sending the change cipherspec (rather than during the \n\t   pause while we're waiting for the other side's response) because we \n\t   can only tell the other side to switch to secure mode if we're sure \n\t   that we're already in that state ourselves */\n\tstatus = initSecurityInfo( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"initSecurityInfo\" );\n\n\t/* Build our change cipherspec message and send the whole mess through\n\t   to the client:\n\t\t...\n\t\tbyte\ttype = SSH_MSG_NEWKEYS\n\n\t   After this point the write channel is in the secure state, so we \n\t   switch from wrapPlaintextPacketSSH2() to wrapPacketSSH2() */\n\tstatus = continuePacketStreamSSH( &stream, SSH_MSG_NEWKEYS, \n\t\t\t\t\t\t\t\t\t  &packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = wrapPlaintextPacketSSH2( sessionInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t\t  packetOffset );\n\t\t}\n\tif( cryptStatusOK( status ) && handshakeInfo->sendExtInfo )\n\t\t{\n\t\t/* If the client has indicated that it supports extension \n\t\t   information, send our extensions */\n\t\tstatus = continuePacketStreamSSH( &stream, SSH_MSG_EXT_INFO, \n\t\t\t\t\t\t\t\t\t\t  &packetOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = writeExtensionsSSH( sessionInfoPtr, &stream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = wrapPacketSSH2( sessionInfoPtr, &stream, \n\t\t\t\t\t\t\t\t\t packetOffset, FALSE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSH2( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE );\n\tCFI_CHECK_UPDATE( \"SSH_MSG_NEWKEYS\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"IMESSAGE_CTX_ENCRYPT\", \"SSH_MSG_KEXDH_REPLY\", \n\t\t\t\t\t\t\t\t\t\"completeKeyex\", \"iCryptCreateSignature\", \n\t\t\t\t\t\t\t\t\t\"initSecurityInfo\", \"SSH_MSG_NEWKEYS\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Complete the handshake with the client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int completeServerHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\tSTDC_UNUSED \\\n\t\t\t\t\t\t\t\t\t\tSSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM stream;\n\tBOOLEAN userInfoPresent = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* If this is the first time through, set up the security information \n\t   and wait for the client's pre-authentication */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN ) )\n\t\t{\n\t\tBYTE stringBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\t\tint stringLength;\n\n\t\t/* If the caller has supplied user information to match against then \n\t\t   we require a match against the fixed caller-supplied information \n\t\t   rather than accepting what the client sends us and passing it \n\t\t   back to the caller to check */\n\t\tif( findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME ) != NULL )\n\t\t\tuserInfoPresent = TRUE;\n\n\t\t/* Wait for the client's change cipherspec message.  From this point\n\t\t   on the read channel is in the secure state */\n\t\tstatus = readHSPacketSSH2( sessionInfoPtr, SSH_MSG_NEWKEYS, \n\t\t\t\t\t\t\t\t   ID_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ );\n\n\t\t/* Wait for the client's pre-authentication packets, which aren't \n\t\t   used for any authentication but which are required anyway by the\n\t\t   protocol.  For some reason SSH requires the use of two messages \n\t\t   where one would do, first an \"I'm about to authenticate\" packet \n\t\t   and then an \"I'm authenticating\" packet after that (\"What are you \n\t\t   preparing?! You're always preparing! Just go!\").  Since the \n\t\t   former isn't useful for anything we clear it to get it out of the \n\t\t   way so that we can perform the actual authentication:\n\n\t\t\tbyte\ttype = SSH_MSG_SERVICE_REQUEST\n\t\t\tstring\tservice_name = \"ssh-userauth\"\n\n\t\t\tbyte\ttype = SSH_MSG_SERVICE_ACCEPT\n\t\t\tstring\tservice_name = \"ssh-userauth\" */\n\t\tstatus = length = \\\n\t\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_SERVICE_REQUEST,\n\t\t\t\t\t\t\t  ID_SIZE + sizeofString32( 8 ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\t\tstatus = readString32( &stream, stringBuffer, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t   &stringLength );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid service request packet\" ) );\n\t\t\t}\n\t\tif( stringLength != 12 || \\\n\t\t\tmemcmp( stringBuffer, \"ssh-userauth\", 12 ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid service request packet '%s'\",\n\t\t\t\t\t  sanitiseString( stringBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  stringLength ) ) );\n\t\t\t}\n\t\tstatus = openPacketStreamSSH( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  SSH_MSG_SERVICE_ACCEPT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = writeString32( &stream, \"ssh-userauth\", 12 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = wrapSendPacketSSH2( sessionInfoPtr, &stream );\n\t\tsMemDisconnect( &stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"SSH_MSG_NEWKEYS\" );\n\n\t/* Process the client's authentication */\n\tstatus = processServerAuth( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\tuserInfoPresent );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processServerAuth\" );\n\n\t/* Handle the channel open */\n\tstatus = length = \\\n\t\treadHSPacketSSH2( sessionInfoPtr, SSH_MSG_CHANNEL_OPEN,\n\t\t\t\t\t\t  ID_SIZE + sizeofString32( 4 ) + \\\n\t\t\t\t\t\t\tUINT32_SIZE + UINT32_SIZE + UINT32_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstatus = processChannelOpen( sessionInfoPtr, &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"processChannelOpen\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"SSH_MSG_NEWKEYS\", \"processServerAuth\", \n\t\t\t\t\t\t\t\t\t\"processChannelOpen\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSH2serverProcessing( INOUT SSH_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSH_HANDSHAKE_INFO ) ) );\n\n\tFNPTR_SET( handshakeInfo->beginHandshake, beginServerHandshake );\n\tFNPTR_SET( handshakeInfo->exchangeKeys, exchangeServerKeys );\n\tFNPTR_SET( handshakeInfo->completeHandshake, completeServerHandshake );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssh2_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib SSHv2 Session Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssh.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssh.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSH\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSub-packet Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike SSL, SSH only hashes portions of the handshake, and even then not\n   complete packets but arbitrary bits and pieces.  In order to handle this\n   we have to be able to break out bits and pieces of data from the stream\n   buffer in order to hash them.  The following function extracts a block\n   of data from a given position in the stream buffer */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint streamBookmarkComplete( INOUT STREAM *stream, \n\t\t\t\t\t\t\tOUT_OPT_PTR void **dataPtrPtr, \n\t\t\t\t\t\t\tOUT_DATALENGTH_Z int *length, \n\t\t\t\t\t\t\tIN_DATALENGTH const int position )\n\t{\n\tconst int dataLength = stell( stream ) - position;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( dataPtrPtr, sizeof( void * ) ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( position >= 0 && position < MAX_BUFFER_SIZE );\n\tREQUIRES( dataLength > 0 && dataLength <= stell( stream ) && \\\n\t\t\t  dataLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return values */\n\t*dataPtrPtr = NULL;\n\t*length = 0;\n\n\t*length = dataLength;\n\treturn( sMemGetDataBlockAbs( stream, position, dataPtrPtr, dataLength ) );\n\t}\n\n/* Open a stream to write an SSH2 packet or continue an existing stream to\n   write further packets.  This opens the stream (if it's an open), skips\n   the storage for the packet header, and writes the packet type */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSH( OUT STREAM *stream, \n\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t   SSH_MSG_CHANNEL_FAILURE ) \n\t\t\t\t\t\t\tconst int packetType )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES( packetType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  packetType <= SSH_MSG_CHANNEL_FAILURE );\n\n\tsMemOpen( stream, sessionInfoPtr->sendBuffer, \n\t\t\t  sessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE );\n\tswrite( stream, \"\\x00\\x00\\x00\\x00\\x00\", SSH2_HEADER_SIZE );\n\treturn( sputc( stream, packetType ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSHEx( OUT STREAM *stream, \n\t\t\t\t\t\t   const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   IN_DATALENGTH const int bufferSize, \n\t\t\t\t\t\t   IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\t SSH_MSG_CHANNEL_FAILURE ) \n\t\t\t\t\t\t\tconst int packetType )\n\t{\n\tconst int streamSize = bufferSize + SSH2_HEADER_SIZE;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtrDynamic( sessionInfoPtr->sendBuffer, streamSize ) );\n\t\n\tREQUIRES( bufferSize > 0 && bufferSize < MAX_BUFFER_SIZE );\n\tREQUIRES( packetType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  packetType <= SSH_MSG_CHANNEL_FAILURE );\n\tREQUIRES( streamSize > SSH2_HEADER_SIZE && \\\n\t\t\t  streamSize <= sessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE );\n\n\tsMemOpen( stream, sessionInfoPtr->sendBuffer, streamSize );\n\tswrite( stream, \"\\x00\\x00\\x00\\x00\\x00\", SSH2_HEADER_SIZE );\n\treturn( sputc( stream, packetType ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint continuePacketStreamSSH( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_RANGE( SSH_MSG_DISCONNECT, \\\n\t\t\t\t\t\t\t\t\t   SSH_MSG_CHANNEL_FAILURE ) \\\n\t\t\t\t\t\t\t\tconst int packetType,\n\t\t\t\t\t\t\t OUT_DATALENGTH_Z int *packetOffset )\n\t{\n\tconst int offset = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetOffset, sizeof( int ) ) );\n\n\tREQUIRES( packetType >= SSH_MSG_DISCONNECT && \\\n\t\t\t  packetType <= SSH_MSG_CHANNEL_FAILURE );\n\tREQUIRES( stell( stream ) == 0 || \\\n\t\t\t  ( stell( stream ) > SSH2_HEADER_SIZE + 1 && \\\n\t\t\t\tstell( stream ) < MAX_BUFFER_SIZE ) );\n\n\t/* Clear return value */\n\t*packetOffset = 0;\n\n\tswrite( stream, \"\\x00\\x00\\x00\\x00\\x00\", SSH2_HEADER_SIZE );\n\tstatus = sputc( stream, packetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*packetOffset = offset;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWrite/Wrap a Packet\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send an SSH packet.  During the handshake phase we may be sending \n   multiple packets at once, however unlike SSL, SSH requires that each\n   packet in a multi-packet group be individually gift-wrapped so we have to\n   provide a facility for separately wrapping and sending packets to handle\n   this:\n\n\tsendBuffer\tbStartPtr\t\t\t\t  eLen (may be zero)\n\t\t|\t\t\t|\t\t\t\t\t\t\t  |\n\t\tv\t\t\tv\t|<-- payloadLen --->|\t<-+->\n\t\t+-----------+---+-------------------+---+---+\n\t\t|///////////|hdr|\t\tdata\t\t|pad|MAC|\n\t\t+-----------+---+-------------------+---+---+\n\t\t\t\t\t^\t\t\t\t\t\t^\t|\n\t\t\t\t\t|\t\t\t\t\t\t|\t|\n\t\t\t\t offset\t\t\t\t\tstell(s)|\n\t\t\t\t\t|<-------- length --------->| \n\n   Packets are usually sent encrypted, however during the handshake phase\n   they're sent in plaintext.  We keep these two separate to ensure that \n   there's no chance of some glitch resulting in the accidental sending of \n   plaintext once we enter secure mode */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPlaintextPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t INOUT STREAM *stream,\n\t\t\t\t\t\t\t IN_DATALENGTH_Z const int offset )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tSTREAM metadataStream;\n\tBYTE padding[ 128 + 8 ];\n\tint length = stell( stream ) - offset;\n\tconst int padLength = \\\n\t\t\t\tgetPaddedSize( length + SSH2_MIN_PADLENGTH_SIZE ) - length;\n\tconst int payloadLength = length - SSH2_HEADER_SIZE;\n\tvoid *bufStartPtr;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( sStatusOK( stream ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( offset >= 0 && offset < MAX_BUFFER_SIZE );\n\tREQUIRES( length >= SSH2_HEADER_SIZE && length < MAX_BUFFER_SIZE );\n\tREQUIRES( padLength >= SSH2_MIN_PADLENGTH_SIZE && padLength < 128 );\n\tREQUIRES( payloadLength >= 0 && payloadLength < length );\n\tREQUIRES( offset + length <= sessionInfoPtr->sendBufSize );\n\n\t/* Adjust the length by the padding, which is required even when there's \n\t   no encryption being applied(?), although we set the padding to all \n\t   zeroes in this case */\n\tlength += padLength;\n\n\t/* Make sure that there's enough room for the padding */\n\tstatus = sMemGetDataBlockAbs( stream, offset, &bufStartPtr, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Not enough room for padding in data block\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* Add the SSH packet header and all-zero padding:\n\n\t\tuint32\t\tlength\n\t\tbyte\t\tpadLen\n\t  [\tbyte[]\t\tdata ]\n\t\tbyte[]\t\tpadding */\n\tsMemOpen( &metadataStream, bufStartPtr, SSH2_HEADER_SIZE );\n\twriteUint32( &metadataStream, 1 + payloadLength + padLength );\n\tstatus = sputc( &metadataStream, padLength );\n\tsMemDisconnect( &metadataStream );\n\tENSURES( cryptStatusOK( status ) );\n\tDEBUG_PRINT(( \"Wrote %s (%d) packet, length %d.\\n\", \n\t\t\t\t  getSSHPacketName( ( ( BYTE * ) bufStartPtr )[ LENGTH_SIZE + 1 ] ), \n\t\t\t\t  ( ( BYTE * ) bufStartPtr )[ LENGTH_SIZE + 1 ],\n\t\t\t\t  length - ( LENGTH_SIZE + 1 + ID_SIZE + padLength ) ));\n\tDEBUG_DUMP_DATA( ( BYTE * ) bufStartPtr + LENGTH_SIZE + 1 + ID_SIZE, \n\t\t\t\t\t length - ( LENGTH_SIZE + 1 + ID_SIZE + padLength ) );\n\tmemset( padding, 0, padLength );\n\tstatus = swrite( stream, padding, padLength );\n\tENSURES( cryptStatusOK( status ) );\n\n\tsshInfo->writeSeqNo++;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream,\n\t\t\t\t\tIN_DATALENGTH_Z const int offset, \n\t\t\t\t\tconst BOOLEAN useQuantisedPadding )\n\t{\n\tSSH_INFO *sshInfo = sessionInfoPtr->sessionSSH;\n\tSTREAM metadataStream;\n\tMESSAGE_DATA msgData;\n\tBYTE padding[ 128 + 8 ];\n\tint length = stell( stream ) - offset;\n\tconst int payloadLength = length - SSH2_HEADER_SIZE;\n\tvoid *bufStartPtr;\n\tconst int extraLength = sessionInfoPtr->authBlocksize;\n\tint padLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( sStatusOK( stream ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\tREQUIRES( offset >= 0 && offset < MAX_BUFFER_SIZE );\n\tREQUIRES( useQuantisedPadding == TRUE || useQuantisedPadding == FALSE );\n\tREQUIRES( length >= SSH2_HEADER_SIZE && length < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength >= 0 && payloadLength < length );\n\tREQUIRES( offset + length + extraLength <= sessionInfoPtr->sendBufSize );\n\n\t/* Evaluate the number of padding bytes that we need to add to a packet\n\t   to make it a multiple of the cipher block size long, with a minimum\n\t   padding size of SSH2_MIN_PADLENGTH_SIZE bytes */\n\tif( useQuantisedPadding )\n\t\t{\n\t\tint LOOP_ITERATOR;\n\n\t\t/* It's something like a user-authentication packet that (probably) \n\t\t   contains a password, adjust the padding to make the overall \n\t\t   packet fixed-length to hide the password length information.\n\t\t   Note that we can't pad more than 255 bytes because the padding \n\t\t   schemes has a single-byte pad length value, so we use 128 */\n\t\tLOOP_MED( padLength = 128,\n\t\t\t\t  ( length + SSH2_MIN_PADLENGTH_SIZE ) > padLength,\n\t\t\t\t  padLength += 128 );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tpadLength -= length;\n\t\t}\n\telse\n\t\t{\n\t\tconst int paddedLength = getPaddedSize( length + SSH2_MIN_PADLENGTH_SIZE );\n\t\t\n\t\tENSURES( paddedLength >= 16 && paddedLength <= MAX_BUFFER_SIZE ); \n\t\tpadLength = paddedLength - length;\n\t\t}\n\tENSURES( padLength >= SSH2_MIN_PADLENGTH_SIZE && padLength < 256 );\n\tlength += padLength;\n\n\t/* Make sure that there's enough room for the padding and MAC */\n\tstatus = sMemGetDataBlockAbs( stream, offset, &bufStartPtr, \n\t\t\t\t\t\t\t\t  length + extraLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tDEBUG_DIAG(( \"Not enough room for padding and MAC in data block\" ));\n\t\tassert( DEBUG_WARN );\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t}\n\n\t/* Add the SSH packet header, padding, and MAC:\n\n\t\tuint32\t\tlength (excluding MAC size)\n\t\tbyte\t\tpadLen\n\t  [\tbyte[]\t\tdata ]\n\t\tbyte[]\t\tpadding\n\t\tbyte[]\t\tMAC */\n\tsMemOpen( &metadataStream, bufStartPtr, SSH2_HEADER_SIZE );\n\twriteUint32( &metadataStream, 1 + payloadLength + padLength );\n\tstatus = sputc( &metadataStream, padLength );\n\tsMemDisconnect( &metadataStream );\n\tENSURES( cryptStatusOK( status ) );\n\tDEBUG_PRINT(( \"Wrote %s (%d) packet, length %d.\\n\", \n\t\t\t\t  getSSHPacketName( ( ( BYTE * ) bufStartPtr )[ LENGTH_SIZE + 1 ] ), \n\t\t\t\t  ( ( BYTE * ) bufStartPtr )[ LENGTH_SIZE + 1 ],\n\t\t\t\t  length - ( LENGTH_SIZE + 1 + ID_SIZE + padLength ) ));\n\tDEBUG_DUMP_DATA( ( BYTE * ) bufStartPtr + LENGTH_SIZE + 1 + ID_SIZE, \n\t\t\t\t\t length - ( LENGTH_SIZE + 1 + ID_SIZE + padLength ) );\n\n\t/* Append the padding */\n\tsetMessageData( &msgData, padding, padLength );\n\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tsMemOpen( &metadataStream, \n\t\t\t  ( BYTE * ) bufStartPtr + ( length - padLength ), \n\t\t\t  padLength );\n\tstatus = swrite( &metadataStream, padding, padLength );\n\tsMemDisconnect( &metadataStream );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, padLength, MAX_INTLENGTH_SHORT );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* MAC the data and append the MAC to the stream.  We skip the length \n\t   value at the start since this is computed by the MAC'ing code */\n\tstatus = createMacSSH( sessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t   sshInfo->writeSeqNo, \n\t\t\t\t\t\t   ( BYTE * ) bufStartPtr + LENGTH_SIZE,\n\t\t\t\t\t\t   length + extraLength - LENGTH_SIZE, \n\t\t\t\t\t\t   length - LENGTH_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sSkip( stream, sessionInfoPtr->authBlocksize, \n\t\t\t\t\tMAX_INTLENGTH_SHORT );\n\tENSURES( cryptStatusOK( status ) );\n\n\t/* Encrypt the entire packet except for the MAC */\n#ifdef USE_SSH_CTR\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSH_PFLAG_CTR ) )\n\t\t{\n\t\tstatus = ctrModeCrypt( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t   sshInfo->writeCTR, \n\t\t\t\t\t\t\t   sessionInfoPtr->cryptBlocksize,\n\t\t\t\t\t\t\t   bufStartPtr, length );\n\t\t}\n\telse\n#endif /* USE_SSH_CTR */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, bufStartPtr,\n\t\t\t\t\t\t\t  length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\tsshInfo->writeSeqNo++;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tvoid *dataPtr;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Send the contents of the stream to the peer */\n\tlength = stell( stream );\n\tstatus = sMemGetDataBlockAbs( stream, 0, &dataPtr, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( dataPtr != NULL );\n\tstatus = swrite( &sessionInfoPtr->stream, dataPtr, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( !TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\tSESSION_FLAG_NOREPORTERROR ) )\n\t\t\t{\n\t\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tDEBUG_DUMP_SSH( dataPtr, length, FALSE );\n\n\treturn( CRYPT_OK );\t/* swrite() returns a byte count */\n\t}\n\n/* Convenience functions that combine the frequently-used pattern wrap + send\n   into one */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapSendPacketSSH2( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSH( sessionInfoPtr ) );\n\n\t/* Wrap up the payload in an SSH packet and send it */\n\tstatus = wrapPacketSSH2( sessionInfoPtr, stream, 0, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( sendPacketSSH2( sessionInfoPtr, stream ) );\n\t}\n#endif /* USE_SSH */\n"
  },
  {
    "path": "deps/cl345/session/ssl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TLS Session Management\t\t\t\t\t\t*\n*\t\t\t\t\t   Copyright Peter Gutmann 1998-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSSL( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( sslInfo, sizeof( SSL_INFO ) ) );\n\n\t/* Check the general session state */\n\tif( !sanityCheckSession( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSL: Session check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check SSL session parameters */\n\tif( !CHECK_FLAGS( sessionInfoPtr->protocolFlags, SSL_PFLAG_NONE, \n\t\t\t\t\t  SSL_PFLAG_MAX ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSL: Protocol flags\" ));\n\t\treturn( FALSE );\n\t\t}\n\tif( sslInfo->minVersion < 0 || sslInfo->minVersion > 5 || \\\n\t\t( sslInfo->ivSize != 0 && sslInfo->ivSize != 8 && \\\n\t\t  sslInfo->ivSize != 16 ) || \\\n\t\tsslInfo->readSeqNo < 0 || sslInfo->readSeqNo > LONG_MAX / 2 || \\\n\t\tsslInfo->writeSeqNo < 0 || sslInfo->writeSeqNo > LONG_MAX / 2 || \\\n\t\tsslInfo->gcmSaltSize < 0 || sslInfo->gcmSaltSize > CRYPT_MAX_IVSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSL: Session parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check safe pointers */\n\tif( !DATAPTR_ISVALID( sslInfo->savedHandshakeInfo ) || \\\n\t\t!DATAPTR_ISVALID( sslInfo->scoreboardInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionSSL: Safe pointers\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n#if defined( __WIN32__ ) && defined( USE_ERRMSGS ) && !defined( NDEBUG )\n\n/* Dump a message to disk for diagnostic purposes.  The SSL messages are\n   broken up into parts by the read/write code so that we can't use the \n   normal DEBUG_DUMP() macro but have to use a special-purpose function that \n   assembles the packet contents if required, as well as providing \n   appropriate naming */\n\nSTDC_NONNULL_ARG( ( 1, 2 ) ) \\\nvoid debugDumpSSL( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   IN_BUFFER( buffer1size ) const void *buffer1, \n\t\t\t\t   IN_LENGTH_SHORT const int buffer1size,\n\t\t\t\t   IN_BUFFER_OPT( buffer2size ) const void *buffer2, \n\t\t\t\t   IN_LENGTH_SHORT_Z const int buffer2size )\n\t{\n\tFILE *filePtr;\n\tstatic int messageCount = 1;\n\tconst BYTE *bufPtr = buffer1;\n\tconst BOOLEAN isRead = ( buffer2 != NULL ) ? TRUE : FALSE;\n\tconst BOOLEAN encryptionActive = \\\n\t\t( ( isRead && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) ) || \\\n\t\t  ( !isRead && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE ) ) ) ? \\\n\t\tTRUE : FALSE;\n\tchar fileName[ 1024 + 8 ];\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( buffer1,  buffer1size ) );\n\tassert( ( buffer2 == NULL && buffer2size == 0 ) || \\\n\t\t\tisReadPtrDynamic( buffer2, buffer2size ) );\n\n\tif( messageCount > 20 )\n\t\treturn;\t/* Don't dump too many messages */\n\tstrlcpy_s( fileName, 1024, \"/tmp/\" );\n\tsprintf_s( &fileName[ 5 ], 1024, \"tls3%d_%02d%c_\", \n\t\t\t   sessionInfoPtr->version, messageCount++, \n\t\t\t   isRead ? 'r' : 'w' );\n\tif( bufPtr[ 0 ] == SSL_MSG_HANDSHAKE && !encryptionActive )\n\t\t{\n\t\tif( isRead && buffer2size >= 1 )\n\t\t\t{\n\t\t\tstrlcat_s( fileName, 1024, \n\t\t\t\t\t   getSSLHSPacketName( ( ( BYTE * ) buffer2 )[ 0 ] ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( !isRead && buffer1size >= 6 )\n\t\t\t\t{\n\t\t\t\tstrlcat_s( fileName, 1024, \n\t\t\t\t\t\t   getSSLHSPacketName( bufPtr[ 5 ] ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tstrlcat_s( fileName, 1024, \"truncated_packet\" );\n\t\t\t}\n\t\t}\n\telse\t\n\t\tstrlcat_s( fileName, 1024, getSSLPacketName( bufPtr[ 0 ] ) );\n\tstrlcat_s( fileName, 1024, \".dat\" );\n\n#ifdef __STDC_LIB_EXT1__\n\tif( fopen_s( &filePtr, fileName, \"wb\" ) != 0 )\n\t\tfilePtr = NULL;\n#else\n\tfilePtr = fopen( fileName, \"wb\" );\n#endif /* __STDC_LIB_EXT1__ */\n\tif( filePtr != NULL )\n\t\t{\n\t\tfwrite( buffer1, 1, buffer1size, filePtr );\n\t\tif( buffer2 != NULL )\n\t\t\tfwrite( buffer2, 1, buffer2size, filePtr );\n\t\tfclose( filePtr );\n\t\t}\n\t}\n#endif /* Windows debug mode only */\n\n/* Initialise and destroy the handshake state information */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void destroyHandshakeInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\t/* Destroy any active contexts.  We need to do this here (even though\n\t   it's also done in the general session code) to provide a clean exit in\n\t   case the session activation fails, so that a second activation attempt\n\t   doesn't overwrite still-active contexts */\n\tdestroyHandshakeCryptInfo( handshakeInfo );\n\n\tzeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int initHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  OUT_ALWAYS SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\tmemset( handshakeInfo, 0, sizeof( SSL_HANDSHAKE_INFO ) );\n\tif( isServer )\n\t\tinitSSLserverProcessing( handshakeInfo );\n\telse\n\t\tinitSSLclientProcessing( handshakeInfo );\n\thandshakeInfo->originalVersion = sessionInfoPtr->version;\n\treturn( initHandshakeCryptInfo( sessionInfoPtr, handshakeInfo ) );\n\t}\n\n/* Push and pop the handshake state */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int pushHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tvoid *savedHandshakeInfo;\n\tconst int bufPos = sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t   sizeof( SSL_HANDSHAKE_INFO );\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\t\t\t   \n\t/* Save the handshake state so that we can resume the handshake later \n\t   on.  This is somewhat ugly in that we need to store \n\t   sizeof( SSL_HANDSHAKE_INFO ) bytes of data somewhere.  One way to do \n\t   this would be to allocate memory, use it for storage, and free it \n\t   again, however we have the send buffer sitting unused so we save it \n\t   at the end of the send buffer.  \n\t   \n\t   This creates the slight problem that we're saving the premaster \n\t   secret in the send buffer and potentially exposing it to a bug in \n\t   the send code, however it would have to be a pretty unusual bug to \n\t   jump into the send function and then write a block of data all the \n\t   way at the end of the buffer, far past where a handshake packet would \n\t   be, to the peer */\n\tREQUIRES( bufPos > 1024 && bufPos < sessionInfoPtr->sendBufSize - 512 );\n\tsavedHandshakeInfo = sessionInfoPtr->sendBuffer + bufPos;\n\tmemcpy( savedHandshakeInfo, handshakeInfo, \n\t\t\tsizeof( SSL_HANDSHAKE_INFO ) );\n\tDATAPTR_SET( sslInfo->savedHandshakeInfo, savedHandshakeInfo );\n\n\t/* Clear the original copy of the handshake info (without doing a full \n\t   cleanup of objects and so on), which leaves the copy that we've just \n\t   made intact */\n\tzeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );\n\t\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int popHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t OUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tvoid *savedHandshakeInfo;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Restore the saved handshake state so that we can continue a partially-\n\t   completed handshake */\n\tsavedHandshakeInfo = DATAPTR_GET( sslInfo->savedHandshakeInfo );\n\tREQUIRES( savedHandshakeInfo != NULL );\n\tmemcpy( handshakeInfo, savedHandshakeInfo, \n\t\t\tsizeof( SSL_HANDSHAKE_INFO ) );\n\tzeroise( savedHandshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );\n\tDATAPTR_SET( sslInfo->savedHandshakeInfo, NULL );\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/* SSL uses 24-bit lengths in some places even though the maximum packet \n   length is only 16 bits (actually it's limited even further by the spec \n   to 14 bits).  To handle this odd length we define our own read/\n   writeUint24() functions that always set the high byte to zero */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint24( INOUT STREAM *stream )\n\t{\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tstatus = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( status != 0 )\n\t\treturn( sSetError( stream, CRYPT_ERROR_BADDATA ) );\n\treturn( readUint16( stream ) );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint24( INOUT STREAM *stream, IN_LENGTH_Z const int length )\n\t{\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES_S( length >= 0 && \\\n\t\t\t\tlength < MAX_PACKET_SIZE + EXTRA_PACKET_SIZE );\n\n\tsputc( stream, 0 );\n\treturn( writeUint16( stream, length ) );\n\t}\n\n/* The ECDH public value is a bit complex to process because it's the usual \n   X9.62 stuff-point-data-into-a-byte-string value, and to make things even \n   messier it's stored with an 8-bit length instead of a 16-bit one so we \n   can't even read it as an integer16U().  To work around this we have to \n   duplicate a certain amount of the integer-read code here */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readEcdhValue( INOUT STREAM *stream,\n\t\t\t\t   OUT_BUFFER( valueMaxLen, *valueLen ) void *value,\n\t\t\t\t   IN_LENGTH_SHORT_MIN( 64 ) const int valueMaxLen,\n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( value, valueMaxLen ) );\n\tassert( isWritePtr( valueLen, sizeof( int ) ) );\n\n\tREQUIRES( valueMaxLen >= 64 && valueMaxLen < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\tmemset( value, 0, min( 16, valueMaxLen ) );\n\t*valueLen = 0;\n\n\n\t/* Get the length (as a byte) and make sure that it's valid */\n\tstatus = length = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isShortECCKey( length / 2 ) )\n\t\treturn( CRYPT_ERROR_NOSECURE );\n\tif( length < MIN_PKCSIZE_ECCPOINT || length > MAX_PKCSIZE_ECCPOINT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t*valueLen = length;\n\n\t/* Read the X9.62 point value */\n\treturn( sread( stream, value, length ) );\n\t}\n\n/* Abort a session startup */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int abortStartup( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT_OPT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t const BOOLEAN cleanupSecurityContexts,\n\t\t\t\t\t\t IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( handshakeInfo == NULL || \\\n\t\t\tisWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( cleanupSecurityContexts == TRUE || \\\n\t\t\t  cleanupSecurityContexts == FALSE );\n\tREQUIRES( cryptStatusError( status ) );\n\n\tsendHandshakeFailAlert( sessionInfoPtr, \n\t\t\t\t\t\t\t( handshakeInfo != NULL && \\\n\t\t\t\t\t\t\t  handshakeInfo->failAlertType != 0 ) ? \\\n\t\t\t\t\t\t\t\thandshakeInfo->failAlertType : \\\n\t\t\t\t\t\t\t\tSSL_ALERT_HANDSHAKE_FAILURE );\n\tif( cleanupSecurityContexts )\n\t\tdestroySecurityContextsSSL( sessionInfoPtr );\n\tif( handshakeInfo != NULL )\n\t\tdestroyHandshakeInfo( handshakeInfo );\n\treturn( status );\n\t}\n\n#ifdef CONFIG_SUITEB\n\n/* Check that a private key is valid for Suite B use */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkSuiteBKey( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tint keySize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isPkcAlgo( cryptAlgo ) );\n\n\t/* Suite B only allows P256 and P384 keys so we need to make sure that\n\t   the server key is of the appropriate type and size */\n\tif( cryptAlgo != CRYPT_ALGO_ECDSA )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_ALGO, \n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#ifdef CONFIG_SUITEB_TESTS \n\tif( suiteBTestValue == SUITEB_TEST_SVRINVALIDCURVE && \\\n\t\tkeySize == bitsToBytes( 521 ) )\n\t\treturn( CRYPT_OK );\n#endif /* CONFIG_SUITEB_TESTS */\n\tif( keySize != bitsToBytes( 256 ) && keySize != bitsToBytes( 384 ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* In addition if a specific crypto strength has been configured then \n\t   the key size has to correspond to that strength.  At 128 bits we can\n\t   use both P256 and P384, but at 256 bits we have to use P384 */\n\tif( ( ( sessionInfoPtr->protocolFlags & \\\n\t\t\t\t\t\tSSL_PFLAG_SUITEB ) == SSL_PFLAG_SUITEB_256 ) && \\\n\t\tkeySize != bitsToBytes( 384 ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef CONFIG_SUITEB_TESTS \n\n/* Special kludge function used to enable nonstandard behaviour for Suite\n   B tests.  The magic value is used in appropriate locations to enable\n   nonstandard behaviour for testing purposes.  The values are listed in\n   ssl.h */\n\nSUITEB_TEST_VALUE suiteBTestValue = SUITEB_TEST_NONE;\nBOOLEAN suiteBTestClientCert = FALSE;\n\nint sslSuiteBTestConfig( const int magicValue )\n\t{\n\tREQUIRES( ( magicValue >= SUITEB_TEST_NONE && \\\n\t\t\t\tmagicValue < SUITEB_TEST_LAST ) || \\\n\t\t\t  magicValue == 1000 );\n\n\t/* If it's the client-cert test indicator, set the flag and exit */\n\tif( magicValue == 1000 )\n\t\t{\n\t\tsuiteBTestClientCert = TRUE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tsuiteBTestValue = magicValue;\n\tif( magicValue == 0 )\n\t\t{\n\t\t/* If we're doing a reset, clear the client-cert test indicator as\n\t\t   well */\n\t\tsuiteBTestClientCert = FALSE;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_SUITEB_TESTS  */\n#endif /* CONFIG_SUITEB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tRead/Write SSL/TLS Certificate Chains\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write an SSL/TLS certificate chain:\n\n\tbyte\t\tID = SSL_HAND_CERTIFICATE\n\tuint24\t\tlen\n\tuint24\t\tcertListLen\n\tuint24\t\tcertLen\t\t\t| 1...n certificates ordered\n\tbyte[]\t\tcertificate\t\t|   leaf -> root */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertChain, \n\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tCRYPT_CERTIFICATE iLocalCertChain;\n\tconst ATTRIBUTE_LIST *fingerprintPtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );\n\tMESSAGE_DATA msgData;\n\tBYTE certFingerprint[ CRYPT_MAX_HASHSIZE + 8 ];\n#ifdef USE_ERRMSGS\n\tconst char *peerTypeName = isServer ? \"Client\" : \"Server\";\n#endif /* USE_ERRMSGS */\n#ifdef CONFIG_SUITEB\n\tconst char *requiredLengthString = NULL;\n#endif /* CONFIG_SUITEB */\n\tint certAlgo, certFingerprintLength, chainLength, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( iCertChain, sizeof( CRYPT_CERTIFICATE ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Clear return value */\n\t*iCertChain = CRYPT_ERROR;\n\n\t/* Make sure that the packet header is in order */\n\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t  SSL_HAND_CERTIFICATE, \n\t\t\t\t\t\t\t\t  isServer ? 0 : LENGTH_SIZE + MIN_CERTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isServer && ( length == 0 || length == LENGTH_SIZE ) )\n\t\t{\n\t\t/* There is one special case in which a too-short certificate packet \n\t\t   is valid and that's where it constitutes the TLS equivalent of an \n\t\t   SSL no-certificates alert.  SSLv3 sent an \n\t\t   SSL_ALERT_NO_CERTIFICATE alert to indicate that the client \n\t\t   doesn't have a certificate, which is handled by the \n\t\t   readHSPacketSSL() call.  TLS changed this to send an empty \n\t\t   certificate packet instead, supposedly because it lead to \n\t\t   implementation problems (presumably it's necessary to create a \n\t\t   state machine-based implementation to reproduce these problems, \n\t\t   whatever they are).  The TLS 1.0 spec is ambiguous as to what \n\t\t   constitutes an empty packet, it could be either a packet with a \n\t\t   length of zero or a packet containing a zero-length certificate \n\t\t   list so we check for both.  TLS 1.1 fixed this to say that that \n\t\t   certListLen entry has a length of zero.  To report this condition \n\t\t   we fake the error indicators for consistency with the status \n\t\t   obtained from an SSLv3 no-certificate alert */\n\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t  \"Received TLS alert message: No certificate\" ) );\n\t\t}\n\tstatus = chainLength = readUint24( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate chain length information\" ) );\n\t\t}\n\tif( chainLength < MIN_CERTSIZE || chainLength >= MAX_INTLENGTH_SHORT || \\\n\t\tchainLength != length - LENGTH_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate chain length %d, should be %d\",\n\t\t\t\t  chainLength, length - LENGTH_SIZE ) );\n\t\t}\n\n\t/* Import the certificate chain.  This isn't a true certificate chain (in \n\t   the sense of being degenerate PKCS #7 SignedData) but a special-case \n\t   SSL/TLS-encoded certificate chain */\n\tstatus = importCertFromStream( stream, &iLocalCertChain, \n\t\t\t\t\t\t\t\t   DEFAULTUSER_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t   CRYPT_ICERTTYPE_SSL_CERTCHAIN,\n\t\t\t\t\t\t\t\t   chainLength, KEYMGMT_FLAG_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There are sufficient numbers of broken certificates around that \n\t\t   if we run into a problem importing one we provide a custom error\n\t\t   message telling the user to try again with a reduced compliance\n\t\t   level */\n\t\tif( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_INVALID )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"%s provided a broken/invalid certificate, try again \"\n\t\t\t\t\t  \"with a reduced level of certificate compliance \"\n\t\t\t\t\t  \"checking\", peerTypeName ) );\n\t\t\t}\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \"Invalid certificate chain data\" ) );\n\t\t}\n\n\t/* Get information on the chain */\n\tstatus = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &certAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tsetMessageData( &msgData, certFingerprint, CRYPT_MAX_HASHSIZE );\n\tif( fingerprintPtr != NULL )\n\t\t{\n\t\tconst CRYPT_ATTRIBUTE_TYPE fingerprintAttribute = \\\n\t\t\t\t\t\t\t( fingerprintPtr->valueLength == 32 ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_FINGERPRINT_SHA2 : \\\n\t\t\t\t\t\t\tCRYPT_CERTINFO_FINGERPRINT_SHA1;\n\n\t\t/* Use the hint provided by the fingerprint size to select the\n\t\t   appropriate algorithm to generate the fingerprint that we want\n\t\t   to compare against */\n\t\tstatus = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, fingerprintAttribute );\n\t\t}\n\telse\n\t\t{\n\t\t/* There's no algorithm hint available, use the default of SHA-1 */\n\t\tstatus = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tcertFingerprintLength = msgData.length;\n\tif( !isServer && certAlgo != handshakeInfo->authAlgo )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"Server key algorithm %s doesn't match negotiated \"\n\t\t\t\t  \"algorithm %s\", getAlgoName( certAlgo ), \n\t\t\t\t  getAlgoName( handshakeInfo->authAlgo ) ) );\n\t\t}\n\n\t/* Either compare the certificate fingerprint to a supplied one or save \n\t   it for the caller to examine */\n\tif( fingerprintPtr != NULL )\n\t\t{\n\t\t/* The caller has supplied a certificate fingerprint, compare it to \n\t\t   the received certificate's fingerprint to make sure that we're \n\t\t   talking to the right system */\n\t\tif( fingerprintPtr->valueLength != certFingerprintLength || \\\n\t\t\tmemcmp( fingerprintPtr->value, certFingerprint, \n\t\t\t\t\tcertFingerprintLength ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"%s key didn't match key fingerprint\", peerTypeName ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember the certificate fingerprint in case the caller wants to \n\t\t   check it.  We don't worry if the add fails, it's a minor thing \n\t\t   and not worth aborting the handshake for */\n\t\t( void ) addSessionInfoS( sessionInfoPtr,\n\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t  certFingerprint, certFingerprintLength );\n\t\t}\n\n\t/* Make sure that we can perform the required operation using the key\n\t   that we've been given.  For a client key we need signing capability,\n\t   for a server key when using DH/ECDH key agreement we also need \n\t   signing capability to authenticate the DH/ECDH parameters, and for \n\t   an RSA key transport key we need encryption capability.  This \n\t   operation also performs a variety of additional checks alongside the \n\t   obvious one so it's a good general health check before we go any \n\t   further */\n\tif( !checkContextCapability( iLocalCertChain, \n\t\t\t\t\t\t\t\t isServer || \\\n\t\t\t\t\t\t\t\t isKeyxAlgo( handshakeInfo->keyexAlgo ) ? \\\n\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_SIGCHECK : \\\n\t\t\t\t\t\t\t\t\tMESSAGE_CHECK_PKC_ENCRYPT ) )\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"%s provided a key incapable of being used for %s\",\n\t\t\t\t  peerTypeName,\n\t\t\t\t  isServer ? \"client authentication\" : \\\n\t\t\t\t  isKeyxAlgo( certAlgo ) ? \"key exchange authentication\" : \\\n\t\t\t\t\t\t\t\t\t\t    \"encryption\" ) );\n\t\t}\n\n\t/* For ECC with Suite B there are additional constraints on the key\n\t   size */\n#ifdef CONFIG_SUITEB\n\tstatus = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &length, CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )\n\t\t{\n\t\tcase 0:\n\t\t\t/* If we're not configured for Suite B mode then there's\n\t\t\t   nothing to check */\n\t\t\tbreak;\n\n\t\tcase SSL_PFLAG_SUITEB_128:\n\t\t\t/* 128-bit level can be P256 or P384 */\n\t\t\tif( length != bitsToBytes( 256 ) && \\\n\t\t\t\tlength != bitsToBytes( 384 ) )\n\t\t\t\trequiredLengthString = \"256- or 384\";\n\t\t\tbreak;\n\n\t\tcase SSL_PFLAG_SUITEB_256:\n\t\t\t/* 256-bit level only allows P384 */\n\t\t\tif( length != bitsToBytes( 384 ) )\n\t\t\t\trequiredLengthString = \"384\";\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\tif( requiredLengthString != NULL )\t\n\t\t{\n\t\tkrnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"%s provided a %d-bit Suite B key, should have been a \"\n\t\t\t\t  \"%s-bit key\", peerTypeName, bytesToBits( length ),\n\t\t\t\t  requiredLengthString ) );\n\t\t}\n#endif /* CONFIG_SUITEB */\n\n\t*iCertChain = iLocalCertChain;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tint packetOffset, certListOffset DUMMY_INIT, certListEndPos, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\tstatus = continueHSPacketStream( stream, SSL_HAND_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t &packetOffset );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t{\n\t\t/* If there's no private key available, write an empty certificate \n\t\t   chain */\n\t\tstatus = writeUint24( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\treturn( completeHSPacketStream( stream, packetOffset ) );\n\t\t}\n\n\t/* Write a dummy length and export the certificate list to the stream */\n\tstatus = writeUint24( stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertListOffset = stell( stream );\n\t\tstatus = exportCertToStream( stream, sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t CRYPT_ICERTFORMAT_SSL_CERTCHAIN );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcertListEndPos = stell( stream );\n\n\t/* Go back and insert the length, then wrap up the packet */\n\tsseek( stream, certListOffset - LENGTH_SIZE );\n\tstatus = writeUint24( stream, certListEndPos - certListOffset );\n\tsseek( stream, certListEndPos );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\treturn( completeHSPacketStream( stream, packetOffset ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Close a previously-opened SSL/TLS session */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void shutdownFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Clean up SSL/TLS-specific objects if required */\n\tif( DATAPTR_ISSET( sslInfo->savedHandshakeInfo ) )\n\t\t{\n\t\tSSL_HANDSHAKE_INFO handshakeInfo;\n\t\tint status;\n\n\t\t/* We got halfway through the handshake but didn't complete it, \n\t\t   restore the handshake state and use it to shut down the session.  \n\t\t   We set a dummy status since this is handled by the higher-level \n\t\t   code that called us.  Since we're being called as part of a\n\t\t   shutdown rather than directly from the startup code, we set the \n\t\t   shutdownNetworkSession flag to FALSE since it'll be closed down \n\t\t   by the code that called us */\n\t\tstatus = popHandshakeInfo( sessionInfoPtr, &handshakeInfo );\n\t\tENSURES_V( cryptStatusOK( status ) );\n\t\t( void ) abortStartup( sessionInfoPtr, &handshakeInfo, FALSE, \n\t\t\t\t\t\t\t   CRYPT_ERROR_FAILED );\n\t\treturn;\n\t\t}\n\n\tsendCloseAlert( sessionInfoPtr, FALSE );\n\t}\n\n/* Connect to an SSL/TLS server/client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int commonStartup( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tSSL_HANDSHAKE_INFO handshakeInfo;\n\tBOOLEAN resumedSession = FALSE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* TLS 1.2 switched from the MD5+SHA-1 dual hash/MACs to SHA-2 so if the\n\t   user has requesetd TLS 1.2 or newer we need to make sure that SHA-2\n\t   is available */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 && \\\n\t\t!algoAvailable( CRYPT_ALGO_SHA2 ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t  \"TLS 1.2 and newer require the SHA-2 hash algorithms which \"\n\t\t\t\t  \"aren't available in this build of cryptlib\" ) );\n\t\t}\n\n\t/* Begin the handshake, unless we're continuing a partially-opened \n\t   session */\n\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN ) )\n\t\t{\n\t\tSSL_HANDSHAKE_FUNCTION handshakeFunction;\n\n\t\t/* Initialise the handshake information */\n\t\tstatus = initHandshakeInfo( sessionInfoPtr, &handshakeInfo, \n\t\t\t\t\t\t\t\t\tisServer );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( abortStartup( sessionInfoPtr, &handshakeInfo, FALSE, \n\t\t\t\t\t\t\t\t  status ) );\n\t\t\t}\n\n\t\t/* Exchange client/server hellos and other pleasantries */\n\t\thandshakeFunction = ( SSL_HANDSHAKE_FUNCTION ) \\\n\t\t\t\t\t\t\tFNPTR_GET( handshakeInfo.beginHandshake );\n\t\tENSURES( handshakeFunction != NULL );\n\t\tstatus = handshakeFunction( sessionInfoPtr, &handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( status == OK_SPECIAL )\n\t\t\t\tresumedSession = TRUE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tdelayRandom();\t/* Dither error timing info */\t\t\t\t\n\t\t\t\treturn( abortStartup( sessionInfoPtr, &handshakeInfo, \n\t\t\t\t\t\t\t\t\t  TRUE, status ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Exchange keys with the server */\n\t\tif( !resumedSession )\n\t\t\t{\n\t\t\thandshakeFunction = ( SSL_HANDSHAKE_FUNCTION ) \\\n\t\t\t\t\t\t\t\tFNPTR_GET( handshakeInfo.exchangeKeys );\n\t\t\tENSURES( handshakeFunction != NULL );\n\t\t\tstatus = handshakeFunction( sessionInfoPtr, &handshakeInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tdelayRandom();\t/* Dither error timing info */\t\t\t\t\n\t\t\t\treturn( abortStartup( sessionInfoPtr, &handshakeInfo, TRUE,\n\t\t\t\t\t\t\t\t\t  status ) );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Remember that we've resumed the session from cached data and\n\t\t\t   that some handshake-related information won't be avaiable */\n\t\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_CACHEDINFO );\n\t\t\t}\n\n\t\t/* If we're performing manual verification of the peer's \n\t\t   certificate, let the caller know that they have to check it,\n\t\t   unless they've specified that they want to allow any certificate\n\t\t   (which implies that they'll perform the check after the handshake\n\t\t   completes) */\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_MANUAL_CERTCHECK ) && \\\n\t\t\tsessionInfoPtr->authResponse != AUTHRESPONSE_SUCCESS )\n\t\t\t{\n\t\t\t/* Save the handshake state so that we can resume the handshake \n\t\t\t   later on */\n\t\t\tstatus = pushHandshakeInfo( sessionInfoPtr, &handshakeInfo );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\n\t\t\treturn( CRYPT_ENVELOPE_RESOURCE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* We're continuing a partially-completed handshake, restore the \n\t\t   handshake state */\n\t\tstatus = popHandshakeInfo( sessionInfoPtr, &handshakeInfo );\n\t\tENSURES( cryptStatusOK( status ) );\n\n\t\t/* Reset the partial-open state since we're about to complete the \n\t\t   open.  This is also done by the calling code once the handshake\n\t\t   completes successfully, but we want to do it preemptively \n\t\t   unconditionally */\n\t\tCLEAR_FLAG( sessionInfoPtr->flags, SESSION_FLAG_PARTIALOPEN );\n\t\t}\n\n\t/* Complete the handshake */\n\tstatus = completeHandshakeSSL( sessionInfoPtr, &handshakeInfo, \n\t\t\t\t\t\t\t\t   isServer ? FALSE : TRUE, resumedSession );\n\tdestroyHandshakeInfo( &handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\t\t\t\t\n\t\treturn( abortStartup( sessionInfoPtr, NULL, TRUE, status ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientStartup( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Complete the handshake using the common client/server code */\n\treturn( commonStartup( sessionInfoPtr, FALSE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverStartup( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Complete the handshake using the common client/server code */\n\treturn( commonStartup( sessionInfoPtr, TRUE ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tControl Information Management Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t OUT void *data, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCRYPT_CERTIFICATE *certPtr = ( CRYPT_CERTIFICATE * ) data;\n\tCRYPT_CERTIFICATE iCryptCert = isServer( sessionInfoPtr ) ? \\\n\t\tsessionInfoPtr->iKeyexAuthContext : sessionInfoPtr->iKeyexCryptContext;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( type == CRYPT_SESSINFO_RESPONSE || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_OPTIONS || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_SUBPROTOCOL || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_EAPCHALLENGE || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_EAPKEY );\n\n\t/* If the caller is after the current SSL option settings or sub-\n\t   protocol type, return them */\n\tif( type == CRYPT_SESSINFO_SSL_OPTIONS )\n\t\t{\n\t\tconst SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = sslInfo->minVersion & SSL_MINVER_MASK;\n#ifdef CONFIG_SUITEB\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_SUITEB_128 ) )\n\t\t\t*valuePtr |= CRYPT_SSLOPTION_SUITEB_128;\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_SUITEB_256 ) )\n\t\t\t*valuePtr |= CRYPT_SSLOPTION_SUITEB_256;\n#endif /* CONFIG_SUITEB */\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_MANUAL_CERTCHECK ) )\n\t\t\t*valuePtr |= CRYPT_SSLOPTION_MANUAL_CERTCHECK;\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_DISABLE_NAMEVERIFY ) )\n\t\t\t*valuePtr |= CRYPT_SSLOPTION_DISABLE_NAMEVERIFY;\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_DISABLE_CERTVERIFY ) )\n\t\t\t*valuePtr |= CRYPT_SSLOPTION_DISABLE_CERTVERIFY;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef USE_WEBSOCKETS\n\tif( type == CRYPT_SESSINFO_SSL_SUBPROTOCOL )\n\t\t{\n\t\tint *valuePtr = ( int * ) data;\n\n\t\t*valuePtr = sessionInfoPtr->subProtocol;\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_WEBSOCKETS */\n\n\t/* If it's a subprotocol-specific attribute, return it */\n\tif( type == CRYPT_SESSINFO_SSL_EAPCHALLENGE || \\\n\t\ttype == CRYPT_SESSINFO_SSL_EAPKEY )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListPtr;\n\t\tMESSAGE_DATA *msgData = ( MESSAGE_DATA * ) data;\n\n\t\tattributeListPtr = findSessionInfo( sessionInfoPtr, type );\n\t\tif( attributeListPtr == NULL )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, type, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t\t}\n\t\treturn( attributeCopy( msgData, attributeListPtr->value,\n\t\t\t\t\t\t\t   attributeListPtr->valueLength ) );\n\t\t}\n\tENSURES( type == CRYPT_SESSINFO_RESPONSE );\n\n\t/* If we didn't get a client/server certificate then there's nothing to \n\t   return */\n\tif( iCryptCert == CRYPT_ERROR )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* Return the information to the caller */\n\tkrnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );\n\t*certPtr = iCryptCert;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tconst int value = *( ( int * ) data );\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( type == CRYPT_SESSINFO_AUTHRESPONSE || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_OPTIONS || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_SUBPROTOCOL || \\\n\t\t\t  type == CRYPT_SESSINFO_SSL_WSPROTOCOL );\n\n\t/* The authentication response isn't usually a protocol-specific \n\t   attribute, but in some cases it needs to be set as part of another\n\t   protocol layered over TLS.  This is complicated by the fact that it\n\t   may have to be specified twice, once for the TLS handshake and a \n\t   second time for the protocol layered over TLS */\n\tif( type == CRYPT_SESSINFO_AUTHRESPONSE )\n\t\t{\n\t\t/* If we're expecting an authentication response for a certificate \n\t\t   provided during the TLS handshake, it has to be given during the \n\t\t   handshake phase */\n\t\tif( !TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISOPEN ) )\n\t\t\t{\n\t\t\t/* We're in the handshake phase, make sure that we're expecting \n\t\t\t   an authentication response at this point */\n\t\t\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\tSSL_PFLAG_MANUAL_CERTCHECK ) || \\\n\t\t\t\t!DATAPTR_ISSET( sslInfo->savedHandshakeInfo ) )\n\t\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* We're in the established-session state, at the moment the only \n\t\t   protocol requiring an auth-response action is EAP */\n#ifdef USE_EAP\n\t\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_EAPTTLS )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\n\t\t/* Send an EAP-protocol-level message to the peer, denoted by the \n\t\t   special-case data content \"EAPACK\" */\n\t\treturn( swrite( &sessionInfoPtr->stream, \"EAPACK\", 6 ) );\n#else\n\t\treturn( CRYPT_ARGERROR_VALUE );\n#endif /* USE_EAP */\n\t\t}\n#ifdef USE_WEBSOCKETS\n\tif( type == CRYPT_SESSINFO_SSL_SUBPROTOCOL )\n\t\t{\n\t\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\t\tENSURES( protocolInfo != NULL );\n\n\t\tif( value < protocolInfo->minSubProtocol || \\\n\t\t\tvalue > protocolInfo->maxSubProtocol )\n\t\t\treturn( CRYPT_ARGERROR_VALUE );\n\t\tsessionInfoPtr->subProtocol = value;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( type == CRYPT_SESSINFO_SSL_WSPROTOCOL )\n\t\t{\n\t\tconst MESSAGE_DATA *msgData = data;\n\t\tint status;\n\n\t\t/* If WebSockets isn't enabled then we can't set the subprotocol \n\t\t   attribute */\n\t\tif( sessionInfoPtr->subProtocol != CRYPT_SUBPROTOCOL_WEBSOCKETS )\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\n\t\t/* Remember the sub-protocol type */\n\t\tstatus = addSessionInfoS( sessionInfoPtr, type, msgData->data, \n\t\t\t\t\t\t\t\t  msgData->length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* USE_WEBSOCKETS */\n\tENSURES( type == CRYPT_SESSINFO_SSL_OPTIONS );\n\n\t/* Set SuiteB options if this is enabled */\n#ifdef CONFIG_SUITEB\n\tif( value & ( CRYPT_SSLOPTION_SUITEB_128 | CRYPT_SSLOPTION_SUITEB_256 ) )\n\t\t{\n\t\tconst int suiteBvalue = value & ( CRYPT_SSLOPTION_SUITEB_128 | \\\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SSLOPTION_SUITEB_256 );\n\n\t\tif( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )\n\t\t\t{\n\t\t\t/* If a Suite B configuration option is already set then we \n\t\t\t   can't set another one on top of it */\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_SSL_OPTIONS, \n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_PRESENT );\n\t\t\treturn( CRYPT_ERROR_INITED );\n\t\t\t}\n\t\tif( suiteBvalue == ( CRYPT_SSLOPTION_SUITEB_128 | \\\n\t\t\t\t\t\t\t CRYPT_SSLOPTION_SUITEB_256 ) )\n\t\t\t{\n\t\t\t/* We can't set both the 128-bit and 256-bit security levels at \n\t\t\t   the same time */\n\t\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t\t}\n\t\tif( suiteBvalue == CRYPT_SSLOPTION_SUITEB_128 )\n\t\t\tsessionInfoPtr->protocolFlags |= SSL_PFLAG_SUITEB_128;\n\t\telse\n\t\t\tsessionInfoPtr->protocolFlags |= SSL_PFLAG_SUITEB_256;\n\t\t}\n#endif /* CONFIG_SUITEB */\n\n\t/* Set the minimum protocol version, a two-bit field that contains the \n\t   minimum version that we're prepared to accept */\n\tif( value & SSL_MINVER_MASK )\n\t\tsslInfo->minVersion = value & SSL_MINVER_MASK;\n\n\t/* By default if a certificate is used we try and verify the server name \n\t   against the name(s) in the certificate, and the certificate itself, \n\t   but since certificate use is so erratic we allow the user to disable \n\t   this if required */\n\tif( value & CRYPT_SSLOPTION_DISABLE_NAMEVERIFY )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t  SSL_PFLAG_DISABLE_NAMEVERIFY );\n\t\t}\n\tif( value & CRYPT_SSLOPTION_DISABLE_CERTVERIFY )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t  SSL_PFLAG_DISABLE_CERTVERIFY );\n\t\t}\n\n\t/* Enable manual checking of certificates if required */\n\tif( value & CRYPT_SSLOPTION_MANUAL_CERTCHECK )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t  SSL_PFLAG_MANUAL_CERTCHECK );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN const void *data,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst CRYPT_CONTEXT cryptContext = *( ( CRYPT_CONTEXT * ) data );\n\tint pkcAlgo, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( isEnumRange( type, CRYPT_ATTRIBUTE ) );\n\n\tif( type != CRYPT_SESSINFO_PRIVATEKEY || !isServer( sessionInfoPtr ) )\n\t\treturn( CRYPT_OK );\n\n\t/* Check that the server key that we've been passed is usable.  For an \n\t   RSA key we can have either encryption (for RSA keyex) or signing (for \n\t   DH keyex) or both, for a DSA or ECDSA key we need signing (for DH/ECDH \n\t   keyex) */\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &pkcAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tswitch( pkcAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tif( !checkContextCapability( cryptContext, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_DECRYPT ) && \\\n\t\t\t\t!checkContextCapability( cryptContext, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ARGERROR_NUM1,\n\t\t\t\t\t\t( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,\n\t\t\t\t\t\t  \"Server key can't be used for encryption or \"\n\t\t\t\t\t\t  \"signing\" ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tif( !checkContextCapability( cryptContext, \n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ARGERROR_NUM1,\n\t\t\t\t\t\t( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,\n\t\t\t\t\t\t  \"Server key can't be used for signing\" ) );\n\t\t\t\t}\n#ifdef CONFIG_SUITEB\n\t\t\treturn( checkSuiteBKey( sessionInfoPtr, cryptContext, pkcAlgo ) );\n#else\n\t\t\treturn( CRYPT_OK );\n#endif /* CONFIG_SUITEB */\n\n\t\tdefault:\n\t\t\tretExt( CRYPT_ARGERROR_NUM1,\n\t\t\t\t\t( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,\n\t\t\t\t\t  \"Server key uses algorithm that can't be used with \"\n\t\t\t\t\t  \"SSL/TLS\" ) );\n\t\t}\n\n\tretIntError();\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGet/Put Data Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write data over the SSL/TLS link */\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readHeaderFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   OUT_ENUM_OPT( READINFO ) \\\n\t\t\t\t\t\t\t\t\tREADSTATE_INFO *readInfo )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tSTREAM stream;\n\tint packetLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* Clear return value */\n\t*readInfo = READINFO_NONE;\n\n\t/* Read the SSL/TLS packet header data */\n\tstatus = readFixedHeader( sessionInfoPtr, sslInfo->headerBuffer, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufStartOfs );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* OK_SPECIAL means that we got a soft timeout before the entire \n\t\t   header was read, so we return zero bytes read to tell the \n\t\t   calling code that there's nothing more to do */\n\t\treturn( ( status == OK_SPECIAL ) ? 0 : status );\n\t\t}\n\n\t/* Since data errors are always fatal, we make all errors fatal until\n\t   we've finished handling the header */\n\t*readInfo = READINFO_FATAL;\n\n\t/* Check for an SSL/TLS alert message */\n\tif( sslInfo->headerBuffer[ 0 ] == SSL_MSG_ALERT )\n\t\t{\n\t\treturn( processAlert( sessionInfoPtr, sslInfo->headerBuffer, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufStartOfs,\n\t\t\t\t\t\t\t  readInfo ) );\n\t\t}\n\n\t/* Process the header data */\n\tsMemConnect( &stream, sslInfo->headerBuffer, \n\t\t\t\t sessionInfoPtr->receiveBufStartOfs );\n\tstatus = checkPacketHeaderSSL( sessionInfoPtr, &stream, &packetLength );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Determine how much data we'll be expecting */\n\tsessionInfoPtr->pendingPacketLength = \\\n\t\tsessionInfoPtr->pendingPacketRemaining = packetLength;\n\n\t/* Indicate that we got the header */\n\t*readInfo = READINFO_NOOP;\n\treturn( OK_SPECIAL );\n\t}\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processBodyFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tOUT_ENUM_OPT( READINFO ) \\\n\t\t\t\t\t\t\t\t\tREADSTATE_INFO *readInfo )\n\t{\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\n\t/* All errors processing the payload are fatal, and specifically fatal \n\t   crypto errors */\n\t*readInfo = READINFO_FATAL_CRYPTO;\n\n\t/* If we're potentially performing a rehandshake, process the packet\n\t   as a handshake message and treat it as a no-op.  What the server\n\t   does in response to this is implementation-specific, the spec says\n\t   that a client can ignore this (as we do) at which point the server\n\t   can close the connection or hang waiting for a rehandshake that'll\n\t   never come (as IIS does) */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t   SSL_PFLAG_CHECKREHANDSHAKE ) )\n\t\t{\n\t\tCLEAR_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\tSSL_PFLAG_CHECKREHANDSHAKE );\n\t\tstatus = unwrapPacketSSL( sessionInfoPtr, \n\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufPos, \n\t\t\t\t\t\t\t\t  sessionInfoPtr->pendingPacketLength, \n\t\t\t\t\t\t\t\t  &length, SSL_MSG_HANDSHAKE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Discard the read packet */\n\t\tsessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos;\n\t\tsessionInfoPtr->pendingPacketLength = 0;\n\t\t*readInfo = READINFO_NOOP;\n\t\treturn( OK_SPECIAL );\n\t\t}\n\n\t/* Unwrap the payload */\n\tstatus = unwrapPacketSSL( sessionInfoPtr, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufPos, \n\t\t\t\t\t\t\t  sessionInfoPtr->pendingPacketLength, \n\t\t\t\t\t\t\t  &length, SSL_MSG_APPLICATION_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*readInfo = READINFO_NONE;\n\treturn( length );\n\t}\n\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int preparePacketFunction( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSession( sessionInfoPtr ) );\n\tREQUIRES( !TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t  SESSION_FLAG_SENDCLOSED ) );\n\tREQUIRES( !TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t  SSL_PFLAG_ALERTSENT ) );\n\n\t/* Wrap up the payload ready for sending.  Since this is wrapping in-\n\t   place data we first open a write stream to add the header, then open\n\t   a read stream covering the full buffer in preparation for wrapping\n\t   the packet (the first operation looks a bit counter-intuitive because\n\t   we're opening a packet stream and then immediately closing it again,\n\t   but this is as intended since all that we're using it for is to write\n\t   the packet header at the start).  Note that we connect the later read \n\t   stream to the full send buffer (bufSize) even though we only advance \n\t   the current stream position to the end of the stream contents \n\t   (bufPos), since the packet-wrapping process adds further data to the \n\t   stream that exceeds the current stream position */\n\tstatus = openPacketStreamSSL( &stream, sessionInfoPtr, 0,\n\t\t\t\t\t\t\t\t  SSL_MSG_APPLICATION_DATA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemDisconnect( &stream );\n\tsMemConnect( &stream, sessionInfoPtr->sendBuffer,\n\t\t\t\t sessionInfoPtr->sendBufSize );\n\tstatus = sSkip( &stream, sessionInfoPtr->sendBufPos, SSKIP_MAX );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSL( sessionInfoPtr, &stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = stell( &stream );\n\tINJECT_FAULT( SESSION_CORRUPT_DATA, SESSION_CORRUPT_DATA_SSL_1 );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodSSL( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tFALSE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_REFLECTAUTHOK,\t/* Flags */\n\t\tSSL_PORT,\t\t\t\t\t/* SSL/TLS port */\n\t\tSESSION_NEEDS_PRIVKEYSIGN,\t/* Client attributes */\n\t\t\t/* The client private key is optional, but if present it has to\n\t\t\t   be signature-capable */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server attributes */\n\t\t\tSESSION_NEEDS_PRIVKEYCERT | \\\n\t\t\tSESSION_NEEDS_KEYORPASSWORD,\n\t\t\t/* The server key capabilities are complex enough that they\n\t\t\t   need to be checked specially via checkAttributeFunction(),\n\t\t\t   for an RSA key we can have either encryption (for RSA keyex)\n\t\t\t   or signing (for DH keyex) or both, for a DSA or ECDSA key\n\t\t\t   we need signing (for DH/ECDH keyex).\n\n\t\t\t   In theory we need neither a private key nor a password \n\t\t\t   because the caller can provide the password during the\n\t\t\t   handshake in response to a CRYPT_ENVELOPE_RESOURCE\n\t\t\t   notification, however this facility is likely to be \n\t\t\t   barely-used in comparison to users forgetting to add server\n\t\t\t   certificates and the like, so we require some sort of \n\t\t\t   server-side key set in advance */\n\t\tSSL_MINOR_VERSION_TLS12,\t/* TLS 1.2 */\n#ifdef USE_SSL3\n\t\t\tSSL_MINOR_VERSION_SSL, SSL_MINOR_VERSION_TLS12,\n#else\n\t\t\tSSL_MINOR_VERSION_TLS, SSL_MINOR_VERSION_TLS12,\n#endif /* USE_SSL3 */\n\t\t\t/* Up until 2018 we defaulted to TLS 1.1 rather than TLS 1.2 \n\t\t\t   because support for the latter was minimal for a long time, \n\t\t\t   particularly among things like embedded devices.  Even TLS \n\t\t\t   1.1 support was unreliable for many years, with vendors\n\t\t\t   apparently choosing to jump from 1.0 straight to 1.2 when\n\t\t\t   they finally did upgrade (see\n\t\t\t   https://www.trustworthyinternet.org/ssl-pulse for current\n\t\t\t   public-Internet stats, which however is nothing like the \n\t\t\t   state of the non-visible use of TLS).  \n\t\t\t   \n\t\t\t   We need at least 1.1 in any case in order to have support for \n\t\t\t   TLS extensions and explicit IVs */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_EAPTTLS,\n\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\tEXTRA_PACKET_SIZE + \\\n\t\t\tMAX_PACKET_SIZE,\t\t/* Send/receive buffer size */\n\t\tSSL_HEADER_SIZE,\t\t\t/* Payload data start */\n\t\t\t/* This may be adjusted during the handshake if we're talking\n\t\t\t   TLS 1.1+, which prepends extra data in the form of an IV to\n\t\t\t   the payload */\n\t\tMAX_PACKET_SIZE\t\t\t\t/* (Default) maximum packet size */\n\t\t};\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Make sure that the huge list of cipher suites is set up correctly */\n\tassert( SSL_NULL_WITH_NULL == 0x00 );\n\tassert( TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA == 0x0B );\n\tassert( TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 == 0x17 );\n\tassert( TLS_KRB5_WITH_DES_CBC_SHA == 0x1E );\n\tassert( TLS_PSK_WITH_NULL_SHA == 0x2C );\n\tassert( TLS_RSA_WITH_AES_128_CBC_SHA == 0x2F );\n\tassert( TLS_RSA_WITH_NULL_SHA256 == 0x3B );\n\tassert( TLS_DH_DSS_WITH_AES_128_CBC_SHA256 == 0x3E );\n\tassert( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA == 0x41 );\n\tassert( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 == 0x67 );\n\tassert( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA == 0x84 );\n\tassert( TLS_PSK_WITH_RC4_128_SHA == 0x8A );\n\tassert( TLS_RSA_WITH_SEED_CBC_SHA == 0x96 );\n\tassert( TLS_RSA_WITH_AES_128_GCM_SHA256 == 0x9C );\n\tassert( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 == 0xBA );\n\tassert( TLS_ECDH_ECDSA_WITH_NULL_SHA == 0xC001 );\n\tassert( TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA == 0xC01A );\n\tassert( TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 == 0xC023 );\n\tassert( TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == 0xC02B );\n\tassert( TLS_ECDHE_PSK_WITH_RC4_128_SHA == 0xC033 );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tFNPTR_SET( sessionInfoPtr->shutdownFunction, shutdownFunction );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverStartup );\n\t\t}\n\telse\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, clientStartup );\n\t\t}\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->checkAttributeFunction, checkAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->readHeaderFunction, readHeaderFunction );\n\tFNPTR_SET( sessionInfoPtr->processBodyFunction, processBodyFunction );\n\tFNPTR_SET( sessionInfoPtr->preparePacketFunction, preparePacketFunction );\n\n\t/* Initialise additional safe pointers in the session state */\n\tDATAPTR_SET( sslInfo->savedHandshakeInfo, NULL );\n\tDATAPTR_SET( sslInfo->scoreboardInfoPtr, NULL );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tSSL v3/TLS Definitions Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _SSL_DEFINED\n\n#define _SSL_DEFINED\n\n#if defined( INC_ALL )\n  #include \"scorebrd.h\"\n#else\n  #include \"session/scorebrd.h\"\n#endif /* _STREAM_DEFINED */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSL Constants\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Default SSL/TLS port */\n\n#define SSL_PORT\t\t\t\t\t443\n\n/* SSL and TLS constants */\n\n#define ID_SIZE\t\t\t\t\t\t1\t/* ID byte */\n#define LENGTH_SIZE\t\t\t\t\t3\t/* 24 bits */\n#define SEQNO_SIZE\t\t\t\t\t8\t/* 64 bits */\n#define VERSIONINFO_SIZE\t\t\t2\t/* 0x03, 0x0n */\n#define ALERTINFO_SIZE\t\t\t\t2\t/* level + description */\n#define SSL_HEADER_SIZE\t\t\t\t5\t/* Type, version, length */\n#define SSL_NONCE_SIZE\t\t\t\t32\t/* Size of client/svr nonce */\n#define SSL_SECRET_SIZE\t\t\t\t48\t/* Size of premaster/master secret */\n#define MD5MAC_SIZE\t\t\t\t\t16\t/* Size of MD5 proto-HMAC/dual hash */\n#define SHA1MAC_SIZE\t\t\t\t20\t/* Size of SHA-1 proto-HMAC/dual hash */\n#define SHA2MAC_SIZE\t\t\t\t32\t/* Size of SHA-2 HMAC hash */\n#define GCMICV_SIZE\t\t\t\t\t16\t/* Size of GCM ICV */\n#define GCM_SALT_SIZE\t\t\t\t4\t/* Size of implicit portion of GCM IV */\n#define GCM_IV_SIZE\t\t\t\t\t12\t/* Overall size of GCM IV */\n#define TLS_HASHEDMAC_SIZE\t\t\t12\t/* Size of TLS PRF( MD5 + SHA1 ) */\n#define SESSIONID_SIZE\t\t\t\t16\t/* Size of session ID */\n#define MIN_SESSIONID_SIZE\t\t\t4\t/* Min.allowed session ID size */\n#define MAX_SESSIONID_SIZE\t\t\t32\t/* Max.allowed session ID size */\n#define MAX_KEYBLOCK_SIZE\t\t\t( ( 64 + 32 + 16 ) * 2 )\n\t\t\t\t\t\t\t\t\t\t/* HMAC-SHA2 + AES-256 key + AES IV */\n#define MIN_PACKET_SIZE\t\t\t\t4\t/* Minimum SSL packet size */\n#define MAX_PACKET_SIZE\t\t\t\t16384\t/* Maximum SSL packet size */\n#define MAX_CIPHERSUITES\t\t\t200\t/* Max.allowed cipher suites */\n#ifdef USE_DH1024\n  #define TLS_DH_KEYSIZE\t\t\t128\t/* Size of server DH key */\n#else\n  #define TLS_DH_KEYSIZE\t\t\t192\t/* Size of server DH key */\n#endif /* USE_DH1024 */\n\n/* SSL/TLS packet/buffer size information.  The extra packet size is \n   somewhat large because it can contains the packet header (5 bytes), IV \n   (0/8/16 bytes), MAC/ICV (12/16/20 bytes), and cipher block padding (up to \n   256 bytes) */\n\n#define EXTRA_PACKET_SIZE\t\t\t512\t\n\n/* By default cryptlib uses DH key agreement, it's also possible to use ECDH \n   key agreement but we disable ECDH by default in order to stick to the\n   safer DH.  To use ECDH key agreement in preference to DH, uncomment the \n   following */\n\n/* #define PREFER_ECC */\n#if defined( PREFER_ECC ) && defined( _MSC_VER )\n  #pragma message( \"  Building with ECC preferred for SSL.\" )\n#endif /* PREFER_ECC && Visual C++ */\n#if defined( PREFER_ECC ) && \\\n\t!( defined( USE_ECDH ) && defined( USE_ECDSA ) )\n  #error PREFER_ECC can only be used with ECDH and ECDSA enabled\n#endif /* PREFER_ECC && !( USE_ECDH && USE_ECDSA ) */\n\n/* SSL/TLS protocol-specific flags that augment the general session flags:\n\n\tFLAG_ALERTSENT: Whether we've already sent a close-alert.  Keeping track \n\t\tof this is necessary because we're required to send a close alert \n\t\twhen shutting down to prevent a truncation attack, however lower-\n\t\tlevel code may have already sent an alert so we have to remember not \n\t\tto send it twice.\n\n\tFLAG_DISABLE_CERTVERIFY: Disable checking of the server certificate \n\tFLAG_DISABLE_NAMEVERIFY: and/or host name.  By default we check both of\n\t\tthese, but because of all of the problems surrounding certificates \n\t\twe allow the checking to be disabled.\n\n\tFLAG_CHECKREHANDSHAKE: The header-read got a handshake packet instead of \n\t\ta data packet, when the body-read decrypts the payload it should \n\t\tcheck for a rehandshake request in the payload.\n\n\tFLAG_CLIAUTHSKIPPED: The client saw an auth-request from the server and \n\t\tresponded with a no-certificates alert, if we later get a close \n\t\talert from the server then we provide additional error information \n\t\tindicating that this may be due to the lack of a client certificate.\n\n\tFLAG_EMS: Use extended Master Secret to protect handshake messages.\n\n\tFLAG_ENCTHENMAC: Use encrypt-then-MAC rather than the standard \n\t\tMAC-then-encrypt.\n\n\tFLAG_GCM: The encryption used is GCM and not the usual CBC, which \n\t\tunifies encryption and MACing into a single operation.\n\t\n\tFLAG_MANUAL_CERTCHECK: Interrupt the handshake (returning \n\t\tCRYPT_ERROR_RESOURCE) to allow the caller to check the peer's \n\t\tcerificate.\n\n\tFLAG_SUITEB_128: Enforce Suite B semantics on top of the standard TLS \n\tFLAG_SUITEB_256: 1.2 + ECC + AES-GCM ones.  _128 = P256 + P384, \n\t\t_256 = P384 only.\n\n\tFLAG_TLS12LTS: TLS 1.2 LTS session with enhanced crypto protection */\n\n#define SSL_PFLAG_NONE\t\t\t\t0x0000\t/* No protocol-specific flags */\n#define SSL_PFLAG_ALERTSENT\t\t\t0x0001\t/* Close alert sent */\n#define SSL_PFLAG_CLIAUTHSKIPPED\t0x0002\t/* Client auth-req.skipped */\n#define SSL_PFLAG_GCM\t\t\t\t0x0004\t/* Encryption uses GCM, not CBC */\n#define SSL_PFLAG_SUITEB_128\t\t0x0008\t/* Enforce Suite B 128-bit semantics */\n#define SSL_PFLAG_SUITEB_256\t\t0x0010\t/* Enforce Suite B 256-bit semantics */\n#define SSL_PFLAG_CHECKREHANDSHAKE\t0x0020\t/* Check decrypted pkt.for rehandshake */\n#define SSL_PFLAG_MANUAL_CERTCHECK\t0x0040\t/* Interrupt handshake for cert.check */\n#define SSL_PFLAG_DISABLE_NAMEVERIFY 0x0080\t/* Disable host name verification */\n#define SSL_PFLAG_DISABLE_CERTVERIFY 0x0100\t/* Disable certificate verification */\n#define SSL_PFLAG_ENCTHENMAC\t\t0x0200\t/* Use encrypt-then-MAC */\n#define SSL_PFLAG_EMS\t\t\t\t0x0400\t/* Use extended Master Secret */\n#define SSL_PFLAG_TLS12LTS\t\t\t0x0800\t/* Use TLS 1.2 LTS profile */\n#define SSL_PFLAG_MAX\t\t\t\t0x0FFF\t/* Maximum possible flag value */\n\n/* Some of the flags above denote extended TLS facilities that need to be\n   preserved across session resumptions.  The following value defines the \n   flags that need to be preserved across resumes */\n\n#define SSL_RESUMEDSESSION_FLAGS\t( SSL_PFLAG_EMS | SSL_PFLAG_ENCTHENMAC | \\\n\t\t\t\t\t\t\t\t\t  SSL_PFLAG_TLS12LTS )\n\n/* Symbolic defines for static analysis checking */\n\n#define SSL_FLAG_NONE\t\t\t\tSSL_PFLAG_NONE\n#define SSL_FLAG_MAX\t\t\t\tSSL_PFLAG_MAX\n\n/* Suite B consists of two subclasses, the 128-bit security level (AES-128 \n   with P256 and SHA2-256) and the 192-bit security level (AES-256 with P384 \n   and SHA2-384), in order to identify generic use of Suite B we provide a\n   pseudo-value that combines the 128-bit and 192-bit subclasses */\n\n#define SSL_PFLAG_SUITEB\t\t\t( SSL_PFLAG_SUITEB_128 | \\\n\t\t\t\t\t\t\t\t\t  SSL_PFLAG_SUITEB_256 )\n\n/* The SSL minimmum version number is encoded as a CRYPT_SSLOPTION_MINVER_xxx\n   value, the following mask allows the version to be extracted from the SSL\n   option value */\n\n#define SSL_MINVER_MASK\t\t\t\t( CRYPT_SSLOPTION_MINVER_SSLV3 | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_SSLOPTION_MINVER_TLS10 | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_SSLOPTION_MINVER_TLS11 | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_SSLOPTION_MINVER_TLS12 | \\\n\t\t\t\t\t\t\t\t\t  CRYPT_SSLOPTION_MINVER_TLS13 )\n\n/* SSL/TLS message types */\n\n#define SSL_MSG_CHANGE_CIPHER_SPEC\t20\n#define SSL_MSG_ALERT\t\t\t\t21\n#define SSL_MSG_HANDSHAKE\t\t\t22\n#define SSL_MSG_APPLICATION_DATA\t23\n\n#define SSL_MSG_FIRST\t\t\t\tSSL_MSG_CHANGE_CIPHER_SPEC\n#define SSL_MSG_LAST\t\t\t\tSSL_MSG_APPLICATION_DATA\n\n/* Special expected packet-type values that are passed to readHSPacketSSL() \n   to handle situations where special-case handling is required for read\n   packets.  The first handshake packet from the client or server is treated \n   specially in that the version number information is taken from this \n   packet, and the attempt to read the first encrypted handshake packet may \n   be met with a TCP close from the peer if it handles errors badly, in \n   which case we provide a special-case error message that indicates more\n   than just \"connection closed\" */\n\n#define SSL_MSG_FIRST_HANDSHAKE\t\t0xFE\n#define SSL_MSG_FIRST_ENCRHANDSHAKE\t0xFF\n#define SSL_MSG_LAST_SPECIAL\t\tSSL_MSG_FIRST_ENCRHANDSHAKE\n#define SSL_MSG_V2HANDSHAKE\t\t\t0x80\n\n/* SSL/TLS handshake message subtypes */\n\n#define SSL_HAND_CLIENT_HELLO\t\t1\n#define SSL_HAND_SERVER_HELLO\t\t2\n#define SSL_HAND_CERTIFICATE\t\t11\n#define SSL_HAND_SERVER_KEYEXCHANGE\t12\n#define SSL_HAND_SERVER_CERTREQUEST\t13\n#define SSL_HAND_SERVER_HELLODONE\t14\n#define SSL_HAND_CLIENT_CERTVERIFY\t15\n#define SSL_HAND_CLIENT_KEYEXCHANGE\t16\n#define SSL_HAND_FINISHED\t\t\t20\n#define SSL_HAND_SUPPLEMENTAL_DATA\t23\n\n#define SSL_HAND_FIRST\t\t\t\tSSL_HAND_CLIENT_HELLO\n#define SSL_HAND_LAST\t\t\t\tSSL_HAND_SUPPLEMENTAL_DATA\n\n/* SSL and TLS alert levels and types */\n\n#define SSL_ALERTLEVEL_WARNING\t\t\t\t1\n#define SSL_ALERTLEVEL_FATAL\t\t\t\t2\n\n#define SSL_ALERT_CLOSE_NOTIFY\t\t\t\t0\n#define SSL_ALERT_UNEXPECTED_MESSAGE\t\t10\n#define SSL_ALERT_BAD_RECORD_MAC\t\t\t20\n#define TLS_ALERT_DECRYPTION_FAILED\t\t\t21\n#define TLS_ALERT_RECORD_OVERFLOW\t\t\t22\n#define SSL_ALERT_DECOMPRESSION_FAILURE\t\t30\n#define SSL_ALERT_HANDSHAKE_FAILURE\t\t\t40\n#define SSL_ALERT_NO_CERTIFICATE\t\t\t41\n#define SSL_ALERT_BAD_CERTIFICATE\t\t\t42\n#define SSL_ALERT_UNSUPPORTED_CERTIFICATE\t43\n#define SSL_ALERT_CERTIFICATE_REVOKED\t\t44\n#define SSL_ALERT_CERTIFICATE_EXPIRED\t\t45\n#define SSL_ALERT_CERTIFICATE_UNKNOWN\t\t46\n#define TLS_ALERT_ILLEGAL_PARAMETER\t\t\t47\n#define TLS_ALERT_UNKNOWN_CA\t\t\t\t48\n#define TLS_ALERT_ACCESS_DENIED\t\t\t\t49\n#define TLS_ALERT_DECODE_ERROR\t\t\t\t50\n#define TLS_ALERT_DECRYPT_ERROR\t\t\t\t51\n#define TLS_ALERT_EXPORT_RESTRICTION\t\t60\n#define TLS_ALERT_PROTOCOL_VERSION\t\t\t70\n#define TLS_ALERT_INSUFFICIENT_SECURITY\t\t71\n#define TLS_ALERT_INTERNAL_ERROR\t\t\t80\n#define TLS_ALERT_INAPPROPRIATE_FALLBACK\t86\n#define TLS_ALERT_USER_CANCELLED\t\t\t90\n#define TLS_ALERT_NO_RENEGOTIATION\t\t\t100\n#define TLS_ALERT_UNSUPPORTED_EXTENSION\t\t110\n#define TLS_ALERT_CERTIFICATE_UNOBTAINABLE\t111\n#define TLS_ALERT_UNRECOGNIZED_NAME\t\t\t112\n#define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113\n#define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114\n#define TLS_ALERT_UNKNOWN_PSK_IDENTITY\t\t115\n\n#define SSL_ALERT_FIRST\t\t\t\t\t\tSSL_ALERT_CLOSE_NOTIFY\n#define SSL_ALERT_LAST\t\t\t\t\t\tTLS_ALERT_UNKNOWN_PSK_IDENTITY\n\n/* TLS supplemental data subtypes */\n\n#define TLS_SUPPDATA_USERMAPPING\t\t\t0\n\n/* SSL and TLS cipher suites */\n\ntypedef enum {\n\t/* SSLv3 cipher suites (0-10) */\n\tSSL_NULL_WITH_NULL, SSL_RSA_WITH_NULL_MD5, SSL_RSA_WITH_NULL_SHA,\n\tSSL_RSA_EXPORT_WITH_RC4_40_MD5,\t\t/* Non-valid/accapted suites */\n\tSSL_RSA_WITH_RC4_128_MD5, SSL_FIRST_VALID_SUITE = SSL_RSA_WITH_RC4_128_MD5,\n\tSSL_RSA_WITH_RC4_128_SHA, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,\n\tSSL_RSA_WITH_IDEA_CBC_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,\n\tSSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA,\n\n\t/* TLS (RFC 2246) DH cipher suites (11-22) */\n\tTLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_DSS_WITH_DES_CBC_SHA,\n\tTLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,\n\tTLS_DH_RSA_WITH_DES_CBC_SHA, TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,\n\tTLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_DHE_DSS_WITH_DES_CBC_SHA,\n\tTLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,\n\tTLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,\n\n\t/* TLS (RFC 2246) anon-DH cipher suites (23-27) */\n\tTLS_DH_anon_EXPORT_WITH_RC4_40_MD5, TLS_DH_anon_WITH_RC4_128_MD5,\n\tTLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_DH_anon_WITH_DES_CBC_SHA,\n\tTLS_DH_anon_WITH_3DES_EDE_CBC_SHA,\n\n\t/* TLS (RFC 2246) reserved cipher suites (28-29, used for Fortezza in\n\t   SSLv3) */\n\tTLS_reserved_1, TLS_reserved_2,\n\n\t/* TLS with Kerberos (RFC 2712) suites (30-43) */\n\tTLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_SHA,\n\tTLS_KRB5_WITH_RC4_128_SHA, TLS_KRB5_WITH_IDEA_CBC_SHA,\n\tTLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_MD5,\n\tTLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_IDEA_CBC_MD5,\n\tTLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,\n\tTLS_KRB5_EXPORT_WITH_RC4_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,\n\tTLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5, TLS_KRB5_EXPORT_WITH_RC4_40_MD5,\n\n\t/* Formerly reserved (44-46), later assigned to PSK-with-NULL suites \n\t   (RFC 4785) */\n\tTLS_PSK_WITH_NULL_SHA, TLS_DHE_PSK_WITH_NULL_SHA, \n\tTLS_RSA_PSK_WITH_NULL_SHA,\n\n\t/* TLS 1.1 (RFC 4346) cipher suites (47-58) */\n\tTLS_RSA_WITH_AES_128_CBC_SHA, TLS_DH_DSS_WITH_AES_128_CBC_SHA,\n\tTLS_DH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA,\n\tTLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA,\n\tTLS_RSA_WITH_AES_256_CBC_SHA, TLS_DH_DSS_WITH_AES_256_CBC_SHA,\n\tTLS_DH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA,\n\tTLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DH_anon_WITH_AES_256_CBC_SHA,\n\n\t/* TLS 1.2 (RFC 5246) cipher suites (59-61) */\n\tTLS_RSA_WITH_NULL_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256,\n\tTLS_RSA_WITH_AES_256_CBC_SHA256,\n\n\t/* TLS 1.2 (RFC 5246) DH cipher suites (62-64), continued at 103 */\n\tTLS_DH_DSS_WITH_AES_128_CBC_SHA256, TLS_DH_RSA_WITH_AES_128_CBC_SHA256, \n\tTLS_DHE_DSS_WITH_AES_128_CBC_SHA256, \n\n\t/* Camellia (RFC 4132) AES-128 suites (65-70) */\n\tTLS_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA, \n\tTLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, \n\tTLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,\n\n\t/* Unknown/reserved suites (71-103) */\n\n\t/* More TLS 1.2 (RFC 5246) DH cipher suites (103-109) */\n\tTLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 103, TLS_DH_DSS_WITH_AES_256_CBC_SHA256,\n\tTLS_DH_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,\n\tTLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DH_anon_WITH_AES_128_CBC_SHA256,\n\tTLS_DH_anon_WITH_AES_256_CBC_SHA256,\n\n\t/* Unknown suites (110-131) */\n\n\t/* Camellia (RFC 4132) AES-256 suites (132-137) */\n\tTLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 132,\n\tTLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,\n\tTLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,\n\tTLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,\n\n\t/* TLS-PSK (RFC 4279) cipher suites (138-149) */\n\tTLS_PSK_WITH_RC4_128_SHA, TLS_PSK_WITH_3DES_EDE_CBC_SHA, \n\tTLS_PSK_WITH_AES_128_CBC_SHA, TLS_PSK_WITH_AES_256_CBC_SHA, \n\tTLS_DHE_PSK_WITH_RC4_128_SHA, TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,\n\tTLS_DHE_PSK_WITH_AES_128_CBC_SHA, TLS_DHE_PSK_WITH_AES_256_CBC_SHA,\n\tTLS_RSA_PSK_WITH_RC4_128_SHA, TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,\n\tTLS_RSA_PSK_WITH_AES_128_CBC_SHA, TLS_RSA_PSK_WITH_AES_256_CBC_SHA,\n\n\t/* SEED (RFC 4162) suites (150-155) */\n\tTLS_RSA_WITH_SEED_CBC_SHA, TLS_DH_DSS_WITH_SEED_CBC_SHA,\n\tTLS_DH_RSA_WITH_SEED_CBC_SHA, TLS_DHE_DSS_WITH_SEED_CBC_SHA,\n\tTLS_DHE_RSA_WITH_SEED_CBC_SHA, TLS_DH_anon_WITH_SEED_CBC_SHA,\n\n\t/* TLS 1.2 (RFC 5288) GCM cipher suites (156-167) */\n\tTLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DH_RSA_WITH_AES_128_GCM_SHA256, TLS_DH_RSA_WITH_AES_256_GCM_SHA384,\n    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,\n    TLS_DH_DSS_WITH_AES_128_GCM_SHA256, TLS_DH_DSS_WITH_AES_256_GCM_SHA384,\n    TLS_DH_anon_WITH_AES_128_GCM_SHA256, TLS_DH_anon_WITH_AES_256_GCM_SHA384,\n\n\t/* TLS 1.2 (RFC 5487) PSK cipher suites (168-185 */\n\tTLS_PSK_WITH_AES_128_GCM_SHA256, TLS_PSK_WITH_AES_256_GCM_SHA384,\n\tTLS_DHE_PSK_WITH_AES_128_GCM_SHA256, TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,\n\tTLS_RSA_PSK_WITH_AES_128_GCM_SHA256, TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,\n\tTLS_PSK_WITH_AES_128_CBC_SHA256, TLS_PSK_WITH_AES_256_CBC_SHA384,\n\tTLS_PSK_WITH_NULL_SHA256, TLS_PSK_WITH_NULL_SHA384,\n\tTLS_DHE_PSK_WITH_AES_128_CBC_SHA256, TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,\n\tTLS_DHE_PSK_WITH_NULL_SHA256, TLS_DHE_PSK_WITH_NULL_SHA384,\n\tTLS_RSA_PSK_WITH_AES_128_CBC_SHA256, TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,\n\tTLS_RSA_PSK_WITH_NULL_SHA256, TLS_RSA_PSK_WITH_NULL_SHA384,\n\n\t/* TLS 1.2 (RFC 5932) Camellia cipher suites (186-197) */\n\tTLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,\n\tTLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,\n\tTLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,\n\tTLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,\n\tTLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,\n\tTLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,\n\n\t/* TLS secure-rengotiation signalling cipher suite, RFC 5746 */\n\tTLS_EMPTY_RENEGOTIATION_INFO_SCSV = 255,\n\n\t/* TLS fallback signalling cpiher suite, RFC 7507, stuffed into a gap in \n\t   the range starting at 22016/0x5600 */\n\tTLS_FALLBACK_SCSV = 22016,\n\n\t/* TLS-ECC (RFC 4492) cipher suites.  For some unknown reason these \n\t   start above 49152/0xC000, so the range is 49153...49177 */\n\tTLS_ECDH_ECDSA_WITH_NULL_SHA = 49153, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,\n\tTLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,\n\tTLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_NULL_SHA,\n\tTLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,\n\tTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,\n\tTLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA,\n\tTLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,\n\tTLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA,\n\tTLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,\n\tTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\n\tTLS_ECDH_anon_WITH_NULL_SHA, TLS_ECDH_anon_WITH_RC4_128_SHA,\n\tTLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_anon_WITH_AES_128_CBC_SHA,\n\tTLS_ECDH_anon_WITH_AES_256_CBC_SHA,\n\n\t/* TLS-SRP (RFC 5054) cipher suites, following the pattern from \n\t   above at 49178/0xC01A...49186 */\n\tTLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,\n\tTLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, TLS_SRP_SHA_WITH_AES_128_CBC_SHA,\n\tTLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,\n\tTLS_SRP_SHA_WITH_AES_256_CBC_SHA, TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,\n\tTLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,\n\n\t/* TLS-ECC (RFC 5289) SHA-2 cipher suites, following the pattern from \n\t   above at 49187/0xC023...49194 */\n\tTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,\n\tTLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,\n\tTLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,\n\tTLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,\n\n\t/* TLS-ECC (RFC 5289) GCM cipher suites, following the pattern from above\n\t   at 49195/0xC02B...49202 */\n\tTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\n\tTLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,\n\tTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n\tTLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,\n\n\t/* TLS-ECC (RFC 5489) PSK cipher suites, following the pattern from above\n\t   at 49203/0xC033...49211 */\n\tTLS_ECDHE_PSK_WITH_RC4_128_SHA, TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,\n    TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,\n\tTLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,\n    TLS_ECDHE_PSK_WITH_NULL_SHA, TLS_ECDHE_PSK_WITH_NULL_SHA256,\n    TLS_ECDHE_PSK_WITH_NULL_SHA384,\n\n\t/* Endless vanity suites, Aria, Camellia, etc */\n\n\tSSL_LAST_SUITE\n\t} SSL_CIPHERSUITE_TYPE;\n\n/* TLS extension types, from \n   http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml */\n\ntypedef enum {\n\tTLS_EXT_SERVER_NAME,\t\t/* 0: Name of virtual server to contact */\n\tTLS_EXT_MAX_FRAGMENT_LENTH,\t/* 1: Max.fragment length if smaller than 2^14 bytes */\n\tTLS_EXT_CLIENT_CERTIFICATE_URL,\t/* 2: Location for server to find client certificate */\n\tTLS_EXT_TRUSTED_CA_KEYS,\t/* 3: Indication of which CAs clients trust */\n\tTLS_EXT_TRUNCATED_HMAC,\t\t/* 4: Use 80-bit truncated HMAC */\n\tTLS_EXT_STATUS_REQUEST,\t\t/* 5: OCSP status request from server */\n\tTLS_EXT_USER_MAPPING,\t\t/* 6: RFC 4681 mapping of user name to account */\n\tTLS_EXT_CLIENT_AUTHZ,\t\t/* 7: RFC 5878 authorisation exts */\n\tTLS_EXT_SERVER_AUTHZ,\t\t/* 8: RFC 5878 authorisation exts */\n\tTLS_EXT_CERTTYPE,\t\t\t/* 9: RFC 5081/6091 OpenPGP key support */\n\tTLS_EXT_ELLIPTIC_CURVES,\t/* 10: RFC 4492 ECDH/ECDSA support */\n\tTLS_EXT_EC_POINT_FORMATS,\t/* 11: RFC 4492 ECDH/ECDSA support */\n\tTLS_EXT_SRP,\t\t\t\t/* 12: RFC 5054 SRP support */\n\tTLS_EXT_SIGNATURE_ALGORITHMS,/* 13: RFC 5246 TLSv1.2 */\n\tTLS_EXT_USE_SRP,\t\t\t/* 14: RFC 5764, DTLS for SRTP keying */\n\tTLS_EXT_HEARTBEAT,\t\t\t/* 15: RFC 6520 DTLS heartbeat */\n\tTLS_EXT_ALPN,\t\t\t\t/* 16: RFC 7301 Application layer protocol negotiation */\n\tTLS_EXT_STATUS_REQUEST_V2,\t/* 17: RFC 6961 OCSP status request from server */\n\tTLS_EXT_CERT_TRANSPARENCY,\t/* 18: RFC 6962 Certificate transparency timestamp */\n\tTLS_EXT_RAWKEY_CLIENT,\t\t/* 19: RFC 7250 Raw client public key */\n\tTLS_EXT_RAWKEY_SERVER,\t\t/* 20: RFC 7250 Raw server public key */\n\tTLS_EXT_PADDING,\t\t\t/* 21: RFC 7685 Padding */\n\tTLS_EXT_ENCTHENMAC,\t\t\t/* 22: RFC 7366 Encrypt-then-MAC */\n\tTLS_EXT_EMS,\t\t\t\t/* 23: RFC 7627 Extended master secret */\n\tTLS_EXT_TOKENBIND,\t\t\t/* 24: Draft, Token binding */\n\tTLS_EXT_CACHED_INFO,\t\t/* 25: RFC 7924 Cached info */\n\tTLS_EXT_TLS12LTS,\t\t\t/* 26: Draft, TLS 1.2 LTS */\n\tTLS_EXT_COMPRESS_CERT,\t\t/* 27: Draft, Compress certificate */\n\tTLS_EXT_RECORD_SIZE_LIMIT,\t/* 28: Draft, Record size limit */\n\t\t/* 29...34 unused */\n\tTLS_EXT_SESSIONTICKET = 35,\t/* 35: RFC 4507 Session ticket */\n\t\t/* 36...40 unused */\n\tTLS_EXT_PRESHARED_KEY = 41,\t/* 41: RFC XXXX TLS 1.3 pre-shared key */\n\tTLS_EXT_EARLY_DATA,\t\t\t/* 42: RFC XXXX TLS 1.3 early data */\n\tTLS_EXT_SUPPORTED_VERSIONS,\t/* 43: RFC XXXX TLS 1.3 supported versions */\n\tTLS_EXT_COOKIE,\t\t\t\t/* 44: RFC XXXX TLS 1.3 cookie */\n\tTLS_EXT_PSK_KEYEX_MODES,\t/* 45: RFC XXXX TLS 1.3 key exchange modes */\n\t\t/* 46 unused */\n\tTLS_EXT_CAS = 47,\t\t\t/* 47: RFC XXXX TLS 1.3 certificate authorities */\n\tTLS_EXT_OID_FILTERS,\t\t/* 48: RFC XXXX TLS 1.3 OID filters */\n\tTLS_EXT_POST_HS_AUTH,\t\t/* 49: RFC XXXX TLS 1.3 post-handshake auth */\n\tTLS_EXT_SIG_ALGOS_CERT,\t\t/* 50: RFC XXXX TLS 1.3 certificate signature algos */\n\tTLS_EXT_KEY_SHARE,\t\t\t/* 51: RFC XXXX TLS 1.3 key share */\n\tTLS_EXT_LAST,\n\t\t/* 52....65280 unused */\n\n\t/* The secure-renegotiation extension, for some unknown reason, is given\n\t   a value of 65281 / 0xFF01, so we define it outside the usual \n\t   extension range in order for the standard range-checking to be a bit\n\t   more sensible */\n\tTLS_EXT_SECURE_RENEG = 65281,/* RFC 5746 secure renegotiation */\n\t} TLS_EXT_TYPE;\n\n/* SSL/TLS certificate types */\n\ntypedef enum {\n\tTLS_CERTTYPE_NONE, TLS_CERTTYPE_RSA, TLS_CERTTYPE_DSA, \n\tTLS_CERTTYPE_DUMMY1 /* RSA+DH */, TLS_CERTTYPE_DUMMY2 /* DSA+DH */,\n\tTLS_CERTTYPE_DUMMY3 /* RSA+EDH */, TLS_CERTTYPE_DUMMY4 /* DSA+EDH */,\n\tTLS_CERTTYPE_ECDSA = 64, TLS_CERTTYPE_LAST\n\t} TLS_CERTTYPE_TYPE;\n\n/* TLS signature and hash algorithm identifiers */\n\ntypedef enum {\n\tTLS_SIGALGO_NONE, TLS_SIGALGO_RSA, TLS_SIGALGO_DSA, TLS_SIGALGO_ECDSA,\n\tTLS_SIGALGO_LAST \n\t} TLS_SIGALGO_TYPE;\n\ntypedef enum {\n\tTLS_HASHALGO_NONE, TLS_HASHALGO_MD5, TLS_HASHALGO_SHA1, \n\tTLS_HASHALGO_DUMMY1 /* SHA2-224 */, TLS_HASHALGO_SHA2, \n\tTLS_HASHALGO_SHA384, TLS_HASHALGO_DUMMY3 /* SHA2-512 */, \n\tTLS_HASHALGO_LAST \n\t} TLS_HASHALGO_TYPE;\n\n/* TLS ECC curve identifiers */\n\ntypedef enum {\n\tTLS_CURVE_NONE, TLS_CURVE_SECT163K1, TLS_CURVE_SECT163R1, \n\tTLS_CURVE_SECT163R2, TLS_CURVE_SECT193R1, TLS_CURVE_SECT193R2, \n\tTLS_CURVE_SECT233K1, TLS_CURVE_SECT233R1, TLS_CURVE_SECT239K1, \n\tTLS_CURVE_SECT283K1, TLS_CURVE_SECT283R1, TLS_CURVE_SECT409K1, \n\tTLS_CURVE_SECT409R1, TLS_CURVE_SECT571K1, TLS_CURVE_SECT571R1, \n\tTLS_CURVE_SECP160K1, TLS_CURVE_SECP160R1, TLS_CURVE_SECP160R2, \n\tTLS_CURVE_SECP192K1, TLS_CURVE_SECP192R1 /* P192 */, \n\tTLS_CURVE_SECP224K1, TLS_CURVE_SECP224R1 /* P224 */, \n\tTLS_CURVE_SECP256K1, TLS_CURVE_SECP256R1 /* P256 */, \n\tTLS_CURVE_SECP384R1 /* P384 */, TLS_CURVE_SECP521R1 /* P521 */,\n\tTLS_CURVE_BRAINPOOLP256R1 /* Brainpool P256 */, \n\tTLS_CURVE_BRAINPOOLP384R1 /* Brainpool P384 */, \n\tTLS_CURVE_BRAINPOOLP512R1 /* Brainpool P512 */, \n\tTLS_CURVE_LAST\n\t} TLS_CURVE_TYPE;\n\n/* SSL and TLS major and minor version numbers */\n\n#define SSL_MAJOR_VERSION\t\t3\n#define SSL_MINOR_VERSION_SSL\t0\n#define SSL_MINOR_VERSION_TLS\t1\n#define SSL_MINOR_VERSION_TLS11\t2\n#define SSL_MINOR_VERSION_TLS12\t3\n\n/* SSL sender label values for the finished message MAC */\n\n#define SSL_SENDER_CLIENTLABEL\t\"CLNT\"\n#define SSL_SENDER_SERVERLABEL\t\"SRVR\"\n#define SSL_SENDERLABEL_SIZE\t4\n\n/* SSL/TLS cipher suite flags.  These are:\n\n\tCIPHERSUITE_PSK: Suite is a TLS-PSK suite and is used only if we're\n\t\tusing TLS-PSK.\n\n\tCIPHERSUITE_DH:\t Suite is a DH suite.\n\n\tCIPHERSUITE_ECC: Suite is an ECC suite and is used only if ECC is\n\t\tenabled.\n\n\tCIPHERSUITE_GCM: Encryption uses GCM instead of the usual CBC.\n\n\tCIPHERSUITE_TLS12: Suite is a TLS 1.2 suite and is only sent if\n\t\tTLS 1.2 is enabled */\n\n#define CIPHERSUITE_FLAG_NONE\t0x00\t/* No suite */\n#define CIPHERSUITE_FLAG_PSK\t0x01\t/* TLS-PSK suite */\n#define CIPHERSUITE_FLAG_DH\t\t0x02\t/* DH suite */\n#define CIPHERSUITE_FLAG_ECC\t0x04\t/* ECC suite */\n#define CIPHERSUITE_FLAG_TLS12\t0x08\t/* TLS 1.2 suite */\n#define CIPHERSUITE_FLAG_GCM\t0x10\t/* GCM instead of CBC */\n#define CIPHERSUITE_FLAG_MAX\t0x1F\t/* Maximum possible flag value */\n\ntypedef struct {\n\t/* The SSL/TLS cipher suite */\n\tconst int cipherSuite;\n#ifndef NDEBUG\n\tconst char *description;\n#endif /* NDEBUG */\n\n\t/* cryptlib algorithms for the cipher suite */\n\tconst CRYPT_ALGO_TYPE keyexAlgo, authAlgo, cryptAlgo, macAlgo;\n\n\t/* Auxiliary information for the suite */\n\tconst int macParam, cryptKeySize, macBlockSize;\n\tconst int flags;\n\t} CIPHERSUITE_INFO;\n\n/* Check for the presence of a TLS signalling suite */\n\n#define isSignallingSuite( suite ) \\\n\t\t( ( suite ) == TLS_FALLBACK_SCSV || \\\n\t\t  ( suite ) == TLS_EMPTY_RENEGOTIATION_INFO_SCSV )\n\n/* If we're configured to only use Suite B algorithms, we override the\n   algoAvailable() check to report that only Suite B algorithms are\n   available */\n\n#ifdef CONFIG_SUITEB\n\n#if defined( _MSC_VER )\n  #pragma message( \"  Building with Suite B algorithms only.\" )\n#endif /* VC++ */\n\n#define algoAvailable( algo ) \\\n\t\t( ( ( algo ) == CRYPT_ALGO_AES || ( algo ) == CRYPT_ALGO_ECDSA || \\\n\t\t\t( algo ) == CRYPT_ALGO_ECDH || ( algo ) == CRYPT_ALGO_SHA2 || \\\n\t\t\t( algo ) == CRYPT_ALGO_HMAC_SHA2 ) ? TRUE : FALSE )\n\n  /* Special configuration defines to enable nonstandard behaviour for \n     Suite B tests */\n  #ifdef CONFIG_SUITEB_TESTS \n\ttypedef enum {\n\t\tSUITEB_TEST_NONE,\t\t\t/* No special test behaviour */\n\n\t\t/* RFC 5430bis tests */\n\t\tSUITEB_TEST_CLIINVALIDCURVE,/* Client sends non-Suite B curve */\n\t\tSUITEB_TEST_SVRINVALIDCURVE,/* Server sends non-Suite B curve */\n\t\tSUITEB_TEST_BOTHCURVES,\t\t/* Client must send P256 and P384 as supp.curves */\n\t\tSUITEB_TEST_BOTHSIGALGOS,\t/* Client must send SHA256 and SHA384 as sig.algos */\n\n\t\tSUITEB_TEST_LAST\n\t\t} SUITEB_TEST_VALUE;\n\n\textern SUITEB_TEST_VALUE suiteBTestValue;\n\textern BOOLEAN suiteBTestClientCert;\n  #endif /* CONFIG_SUITEB_TESTS */\n#endif /* Suite B algorithms only */\n\n/* The following macro can be used to enable dumping of PDUs to disk.  As a\n   safeguard, this only works in the Win32 debug version to prevent it from\n   being accidentally enabled in any release version */\n\n#if defined( __WIN32__ ) && defined( USE_ERRMSGS ) && !defined( NDEBUG )\n  #define DEBUG_DUMP_SSL( buffer1, buffer1size, buffer2, buffer2size ) \\\n\t\t  debugDumpSSL( sessionInfoPtr, buffer1, buffer1size, buffer2, buffer2size )\n\n  STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n  void debugDumpSSL( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t IN_BUFFER( buffer1size ) const void *buffer1, \n\t\t\t\t\t IN_LENGTH_SHORT const int buffer1size,\n\t\t\t\t\t IN_BUFFER_OPT( buffer2size ) const void *buffer2, \n\t\t\t\t\t IN_LENGTH_SHORT_Z const int buffer2size );\n#else\n  #define DEBUG_DUMP_SSL( buffer1, buffer1size, buffer2, buffer2size )\n#endif /* Win32 debug */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSL Structures\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* SSL/TLS handshake state information.  This is passed around various \n   subfunctions that handle individual parts of the handshake */\n\nstruct SL;\n\ntypedef CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\n\tint ( *SSL_HANDSHAKE_FUNCTION )( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT struct SL *handshakeInfo );\n\ntypedef struct SL {\n\t/* Client and server dual-hash/hash contexts */\n\tCRYPT_CONTEXT md5context, sha1context, sha2context;\n#ifdef CONFIG_SUITEB\n\tCRYPT_CONTEXT sha384context;\n#endif /* CONFIG_SUITEB */\n\n\t/* Client and server nonces, session ID, and hashed SNI (which is used\n\t   alongside the session ID for scoreboard lookup) */\n\tBUFFER_FIXED( SSL_NONCE_SIZE ) \\\n\tBYTE clientNonce[ SSL_NONCE_SIZE + 8 ];\n\tBUFFER_FIXED( SSL_NONCE_SIZE ) \\\n\tBYTE serverNonce[ SSL_NONCE_SIZE + 8 ];\n\tBUFFER( MAX_SESSIONID_SIZE, sessionIDlength ) \\\n\tBYTE sessionID[ MAX_SESSIONID_SIZE + 8 ];\n\tint sessionIDlength;\n\tBYTE hashedSNI[ KEYID_SIZE + 8 ];\n\tBOOLEAN hashedSNIpresent;\n\n\t/* Client/server hello hash, the hash of the Client Hello and Server \n\t   Hello, and session hash, the hash of all messages from Client Hello \n\t   to Client Keyex */\n\tHASH_FUNCTION helloHashFunction;\n\tHASHINFO helloHashInfo;\n\tint helloHashSize;\n\tCRYPT_CONTEXT sessionHashContext;\n\tBUFFER( 16, CRYPT_MAX_HASHSIZE ) \\\n\tBYTE sessionHash[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint sessionHashSize;\n\n\t/* Premaster/master secret */\n\tBUFFER( CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE, premasterSecretSize ) \\\n\tBYTE premasterSecret[ CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE + 8 ];\n\tint premasterSecretSize;\n\n\t/* Encryption/security information.  The encryption algorithm (cryptAlgo)\n\t   and integrity algorithm (integrityAlgo) are stored with the session\n\t   information, although the optional integrity-algorithm parameters are\n\t   stored here */\n\tCRYPT_CONTEXT dhContext;\t/* DH context if DHE is being used */\n\tint cipherSuite;\t\t\t/* Selected cipher suite */\n\tCRYPT_ALGO_TYPE keyexAlgo, authAlgo;/* Selected cipher suite algos */\n\tint integrityAlgoParam;\t\t/* Optional param.for integrity algo */\n\tCRYPT_ALGO_TYPE keyexSigHashAlgo;/* Algo.for keyex authentication */\n\tint keyexSigHashAlgoParam;\t/* Optional params.for keyex hash */\n\tint cryptKeysize;\t\t\t/* Size of session key */\n\n\t/* Other information */\n\tint clientOfferedVersion;\t/* Prot.vers.originally offered by client */\n\tint originalVersion;\t\t/* Original version set by the user before\n\t\t\t\t\t\t\t\t   it was modified based on what the peer\n\t\t\t\t\t\t\t\t   requested */\n\tBOOLEAN hasExtensions;\t\t/* Hello has TLS extensions */\n\tBOOLEAN needSNIResponse;\t/* Server needs to respond to SNI */\n\tBOOLEAN needRenegResponse;\t/* Server needs to respond to reneg.ind.*/\n\tBOOLEAN needEncThenMACResponse;/* Server needs to respond to encThenMAC */\n\tBOOLEAN needEMSResponse;\t/* Server needs to respond to EMS */\n\tBOOLEAN needTLS12LTSResponse;/* Server needs to respond to TLS-LTS */\n\tint failAlertType;\t\t\t/* Alert type to send on failure */\n\n\t/* ECC-related information.  Since ECC algorithms have a huge pile of\n\t   parameters we need to parse any extensions that the client sends in \n\t   order to locate any additional information required to handle them.  \n\t   In the worst case these can retroactively modify the already-\n\t   negotiated cipher suites, disabling the use of ECC algorithms after \n\t   they were agreed on via cipher suites.  To handle this we remember\n\t   both the preferred mainstream suite and a pointer to the preferred\n\t   ECC suite in 'eccSuiteInfoPtr', if it later turns out that the use\n\t   of ECC is OK we reset the crypto parameters using the save ECC suite\n\t   pointer.\n\t   \n\t   If the use of ECC isn't retroactively disabled then the eccCurveID \n\t   and sendECCPointExtn values indicate which curve to use and whether \n\t   the server needs to respond with a point-extension indicator */\n\tBOOLEAN disableECC;\t\t\t/* Extn.disabled use of ECC suites */\n\tCRYPT_ECCCURVE_TYPE eccCurveID;\t/* cryptlib ID of ECC curve to use */\n\tBOOLEAN sendECCPointExtn;\t/* Whether svr.has to respond with ECC point ext.*/\n\tconst void *eccSuiteInfoPtr;\t/* ECC suite information */\n\n\t/* The packet data stream.  Since SSL can encapsulate multiple handshake\n\t   packets within a single SSL packet, the stream has to be persistent\n\t   across the different handshake functions to allow the continuation of\n\t   packets */\n\tSTREAM stream;\t\t\t\t/* Packet data stream */\n\n\t/* Function pointers to handshaking functions.  These are set up as \n\t   required depending on whether the session is client or server */\n\tFNPTR beginHandshake, exchangeKeys;\n\t} SSL_HANDSHAKE_INFO;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSSL/TLS Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in ssl.c */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nBOOLEAN sanityCheckSessionSSL( IN const SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \\\nint readUint24( INOUT STREAM *stream );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nint writeUint24( INOUT STREAM *stream, IN_LENGTH_Z const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint readEcdhValue( INOUT STREAM *stream,\n\t\t\t\t   OUT_BUFFER( valueMaxLen, *valueLen ) void *value,\n\t\t\t\t   IN_LENGTH_SHORT_MIN( 64 ) const int valueMaxLen,\n\t\t\t\t   OUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint readSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertChain, \n\t\t\t\t\t  const BOOLEAN isServer );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   INOUT STREAM *stream );\n\n/* Prototypes for functions in ssl_cry.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint encryptData( const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t INOUT_BUFFER( dataMaxLength, *dataLength ) \\\n\t\t\t\t\tBYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataMaxLength,\n\t\t\t\t OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t IN_DATALENGTH const int payloadLength );\n\t\t\t\t /* This one's a bit tricky, the input is \n\t\t\t\t    { data, payloadLength } which is padded (if necessary) \n\t\t\t\t\tand the padded length returned in '*dataLength' */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint decryptData( SESSION_INFO *sessionInfoPtr, \n\t\t\t\t INOUT_BUFFER_FIXED( dataLength ) \\\n\t\t\t\t\tBYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t OUT_DATALENGTH_Z int *processedDataLength );\n\t\t\t\t/* This one's also tricky, the entire data block will be \n\t\t\t\t   processed but only 'processedDataLength' bytes of result \n\t\t\t\t   are valid output */\n#ifdef USE_SSL3\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint createMacSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t  IN_DATALENGTH const int payloadLength, \n\t\t\t\t  IN_RANGE( 0, 255 ) const int type );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkMacSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t IN_DATALENGTH_Z const int payloadLength, \n\t\t\t\t IN_RANGE( 0, 255 ) const int type, \n\t\t\t\t const BOOLEAN noReportError );\n#endif /* USE_SSL3 */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint createMacTLS( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data,\n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t  IN_DATALENGTH const int payloadLength, \n\t\t\t\t  IN_RANGE( 0, 255 ) const int type );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkMacTLS( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t IN_DATALENGTH_Z const int payloadLength, \n\t\t\t\t IN_RANGE( 0, 255 ) const int type, \n\t\t\t\t const BOOLEAN noReportError );\n#ifdef USE_GCM\nCHECK_RETVAL \\\nint macDataTLSGCM( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t   IN_INT_Z const long seqNo, \n\t\t\t\t   IN_RANGE( SSL_MINOR_VERSION_TLS, \\\n\t\t\t\t\t\t\t SSL_MINOR_VERSION_TLS12 ) const int version,\n\t\t\t\t   IN_LENGTH_Z const int payloadLength, \n\t\t\t\t   IN_RANGE( 0, 255 ) const int type );\n#endif /* USE_GCM */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashHSPacketRead( const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t  INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashHSPacketWrite( const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t   INOUT STREAM *stream,\n\t\t\t\t\t   IN_DATALENGTH_Z const int offset );\n#ifdef USE_SSL3\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \\\nint completeSSLDualMAC( IN_HANDLE const CRYPT_CONTEXT md5context,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT sha1context, \n\t\t\t\t\t\tOUT_BUFFER( hashValuesMaxLen, *hashValuesLen )\n\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MD5MAC_SIZE + SHA1MAC_SIZE ) \\\n\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\tIN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\tIN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\tIN_BUFFER( masterSecretLen ) const BYTE *masterSecret, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int masterSecretLen );\n#endif /* USE_SSL3 */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \\\nint completeTLSHashedMAC( IN_HANDLE const CRYPT_CONTEXT md5context,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT sha1context, \n\t\t\t\t\t\t  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \\\n\t\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \\\n\t\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\t  IN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t  IN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\t  IN_BUFFER( masterSecretLen ) const BYTE *masterSecret, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int masterSecretLen );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5, 7 ) ) \\\nint completeTLS12HashedMAC( IN_HANDLE const CRYPT_CONTEXT sha2context,\n\t\t\t\t\t\t\tOUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \\\n\t\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \\\n\t\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\t\tIN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t\tIN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\t\tIN_BUFFER( masterSecretLen ) const BYTE *masterSecret, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int masterSecretLen,\n\t\t\t\t\t\t\tconst BOOLEAN fullSizeMAC );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createSessionHash( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint createCertVerify( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t  INOUT STREAM *stream );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkCertVerify( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\tconst int sigLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint createKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_BUFFER( keyDataLength ) const void *keyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyDataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint checkKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t IN_BUFFER( keyDataLength ) const void *keyData, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int keyDataLength,\n\t\t\t\t\t\t const BOOLEAN isECC );\n\n/* Prototypes for functions in ssl_ext.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readExtensions( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\tIN_LENGTH_SHORT const int length );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeClientExtensions( INOUT STREAM *stream,\n\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeServerExtensions( INOUT STREAM *stream,\n\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo );\n\n/* Prototypes for functions in ssl_hs.c/ssl_hsc.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint processHelloSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t INOUT STREAM *stream, const BOOLEAN isServer );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint completeHandshakeSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  const BOOLEAN isClient,\n\t\t\t\t\t\t  const BOOLEAN isResumedSession );\n\n/* Prototypes for functions in ssl_keymgmt.c */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initHandshakeCryptInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroyHandshakeCryptInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint cloneHashContext( IN_HANDLE const CRYPT_CONTEXT hashContext,\n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CONTEXT *clonedHashContext );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDHcontextSSL( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t  IN_BUFFER_OPT( keyDataLength ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int keyDataLength,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iServerKeyTemplate,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE eccParams,\n\t\t\t\t\t  const BOOLEAN isTLSLTS );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint createSharedPremasterSecret( OUT_BUFFER( premasterSecretMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t *premasterSecretLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *premasterSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT \\\n\t\t\t\t\t\t\t\t\tconst int premasterSecretMaxLength, \n\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( premasterSecretMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *premasterSecretLength,\n\t\t\t\t\t\t\t\t IN_BUFFER( sharedSecretLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *sharedSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int sharedSecretLength,\n\t\t\t\t\t\t\t\t IN_BUFFER_OPT( otherSecretLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *otherSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC_Z const int otherSecretLength,\n\t\t\t\t\t\t\t\t const BOOLEAN isEncodedValue );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint wrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t OUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\tint *dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint unwrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint initCryptoSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t   OUT_BUFFER_FIXED( masterSecretSize ) void *masterSecret,\n\t\t\t\t   IN_LENGTH_SHORT const int masterSecretSize,\n\t\t\t\t   const BOOLEAN isClient,\n\t\t\t\t   const BOOLEAN isResumedSession );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint loadExplicitIV( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\tOUT_INT_SHORT_Z int *ivLength );\n#ifdef USE_EAP\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint addDerivedKeydata( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t   IN_BUFFER( masterSecretSize ) void *masterSecret,\n\t\t\t\t\t   IN_LENGTH_SHORT const int masterSecretSize,\n\t\t\t\t\t   IN_ENUM( CRYPT_SUBPROTOCOL ) \\\n\t\t\t\t\t\t\tconst CRYPT_SUBPROTOCOL_TYPE type );\n#endif /* USE_EAP */\n\n/* Prototypes for functions in ssl_rd.c */\n\n#ifdef USE_ERRMSGS\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSLPacketName( IN_RANGE( 0, 255 ) const int packetType );\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSLHSPacketName( IN_RANGE( 0, 255 ) const int packetType );\n#else\n  #define getSSLPacketName( x )\t\t\"<<<Unknown>>>\"\n  #define getSSLHSPacketName( x )\t\"<<<Unknown>>>\"\n#endif /* USE_ERRMSGS */\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processVersionInfo( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\t\tOUT_OPT int *clientVersion,\n\t\t\t\t\t\tconst BOOLEAN generalCheckOnly );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkPacketHeaderSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *packetLength );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkHSPacketHeader( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *packetLength, \n\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int minSize );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint unwrapPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t   *dataLength ) void *data, \n\t\t\t\t\t IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readHSPacketSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT_OPT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t OUT_DATALENGTH_Z int *packetLength, \n\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t   SSL_MSG_LAST_SPECIAL ) const int packetType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint refreshHSStream( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo );\n\n/* Prototypes for functions in ssl_suites.c */\n\n#ifndef CONFIG_SUITEB\n\nCHECK_RETVAL \\\nint getCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,\n\t\t\t\t\t\tOUT_INT_Z int *noSuiteEntries );\n#else\n\n#define getCipherSuiteInfo( infoPtr, noEntries, isServer ) \\\n\t\tgetSuiteBCipherSuiteInfo( infoPtr, noEntries, isServer, suiteBinfo )\n\nCHECK_RETVAL \\\nint getSuiteBCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,\n\t\t\t\t\t\t\t  OUT_INT_Z int *noSuiteEntries,\n\t\t\t\t\t\t\t  const BOOLEAN isServer,\n\t\t\t\t\t\t\t  IN_FLAGS_Z( SSL ) const int suiteBinfo );\n\n#endif /* CONFIG_SUITEB */\n\n/* Prototypes for functions in ssl_svr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint convertSNISessionID( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t OUT_BUFFER_FIXED( idBufferLength ) BYTE *idBuffer,\n\t\t\t\t\t\t IN_LENGTH_FIXED( KEYID_SIZE ) const int idBufferLength );\n\n/* Prototypes for functions in ssl_wr.c */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t   IN_LENGTH_Z const int offset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   INOUT STREAM *stream, const BOOLEAN sendOnly );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSL( OUT STREAM *stream, \n\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t IN_DATALENGTH_OPT const int bufferSize, \n\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint continuePacketStreamSSL( INOUT STREAM *stream, \n\t\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType,\n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *packetOffset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completePacketStreamSSL( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_LENGTH_Z const int offset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint continueHSPacketStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t  SSL_HAND_LAST ) const int packetType,\n\t\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *packetOffset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completeHSPacketStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_LENGTH const int offset );\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processAlert( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  IN_BUFFER( headerLength ) const void *header, \n\t\t\t\t  IN_DATALENGTH const int headerLength,\n\t\t\t\t  OUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendCloseAlert( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t const BOOLEAN alertReceived );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendHandshakeFailAlert( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN_RANGE( SSL_ALERT_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_ALERT_LAST ) const int alertType );\n\n/* Prototypes for session mapping functions */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSLclientProcessing( INOUT SSL_HANDSHAKE_INFO *handshakeInfo );\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSLserverProcessing( SSL_HANDSHAKE_INFO *handshakeInfo );\n\n#endif /* _SSL_DEFINED */\n"
  },
  {
    "path": "deps/cl345/session/ssl_cli.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib TLS Client\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t   Copyright Peter Gutmann 1998-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n/* Testing the SSL/TLS code gets a bit complicated because in the presence \n   of the session cache every session after the first one will be a resumed \n   session.  To deal with this we disable the client-side session cache in \n   the VC++ 6 debug build.\n\n   Note that changing the follow requires an equivalent change in \n   test/ssl.c */\n\n#if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && \\\n\t!defined( NDEBUG ) && 1\n  #define NO_SESSION_CACHE\n#endif /* VC++ 6.0 debug build */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef CONFIG_SUITEB\n\n/* For Suite B the first suite must be ECDHE/AES128-GCM/SHA256 or \n   ECDHE/AES256-GCM/SHA384 depending on the security level and the second \n   suite, at the 128-bit security level, must be ECDHE/AES256-GCM/SHA384 */\n\nCHECK_RETVAL_BOOL \\\nstatic int checkSuiteBSelection( IN_RANGE( SSL_FIRST_VALID_SUITE, \\\n\t\t\t\t\t\t\t\t\t\t   SSL_LAST_SUITE - 1 ) \\\n\t\t\t\t\t\t\t\t\tconst int cipherSuite,\n\t\t\t\t\t\t\t\t const int flags,\n\t\t\t\t\t\t\t\t const BOOLEAN isFirstSuite )\n\t{\n\tREQUIRES( cipherSuite >= SSL_FIRST_VALID_SUITE && \\\n\t\t\t  cipherSuite < SSL_LAST_SUITE );\n\tREQUIRES( ( flags & ~( SSL_PFLAG_SUITEB ) ) == 0 );\n\tREQUIRES( isFirstSuite == TRUE || isFirstSuite == FALSE );\n\n\tif( isFirstSuite )\n\t\t{\n\t\tswitch( flags )\n\t\t\t{\n\t\t\tcase SSL_PFLAG_SUITEB_128:\n\t\t\t\tif( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 )\n\t\t\t\t\treturn( TRUE );\n\t\t\t\tbreak;\n\n\t\t\tcase SSL_PFLAG_SUITEB_256:\n\t\t\t\tif( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )\n\t\t\t\t\treturn( TRUE );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tswitch( flags )\n\t\t\t{\n\t\t\tcase SSL_PFLAG_SUITEB_128:\n\t\t\t\tif( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )\n\t\t\t\t\treturn( TRUE );\n\t\t\t\tbreak;\n\n\t\t\tcase SSL_PFLAG_SUITEB_256:\n\t\t\t\t/* For the 256-bit level there are no further requirements */\n\t\t\t\treturn( TRUE );\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\n\treturn( FALSE );\n\t}\n#endif /* CONFIG_SUITEB */\n\n/* Encode a list of available algorithms */\n\n#define MAX_NO_SUITES\t32\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeCipherSuiteList( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t IN_RANGE( SSL_MINOR_VERSION_SSL, \\\n\t\t\t\t\t\t\t\t\t\t   SSL_MINOR_VERSION_TLS12 ) \\\n\t\t\t\t\t\t\t\t\tconst int sslVersion,\n\t\t\t\t\t\t\t\t const BOOLEAN usePSK, \n\t\t\t\t\t\t\t\t IN_FLAGS_Z( SSL ) const int suiteBinfo )\n\t{\n\tconst CIPHERSUITE_INFO **cipherSuiteInfo;\n\tint availableSuites[ MAX_NO_SUITES + 8 ], cipherSuiteCount = 0;\n\tint suiteIndex, cipherSuiteInfoSize, status;\n#ifdef CONFIG_SUITEB\n\tint suiteNo = 0;\n#endif /* CONFIG_SUITEB */\n\tint LOOP_ITERATOR;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sslVersion >= SSL_MINOR_VERSION_SSL && \\\n\t\t\t  sslVersion <= SSL_MINOR_VERSION_TLS12 );\n\tREQUIRES( usePSK == TRUE || usePSK == FALSE );\n#ifdef CONFIG_SUITEB\n\tREQUIRES( suiteBinfo >= SSL_PFLAG_NONE && suiteBinfo < SSL_PFLAG_MAX );\n#endif /* CONFIG_SUITEB */\n\n\t/* Get the information for the supported cipher suites */\n\tstatus = getCipherSuiteInfo( &cipherSuiteInfo, &cipherSuiteInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Walk down the list of algorithms (and the corresponding cipher\n\t   suites) remembering each one that's available for use */\n\tLOOP_EXT_INITCHECK( suiteIndex = 0,\n\t\t\t\t\t\tsuiteIndex < cipherSuiteInfoSize && \\\n\t\t\t\t\t\t\tcipherSuiteInfo[ suiteIndex ]->cipherSuite != SSL_NULL_WITH_NULL,\n\t\t\t\t\t\tMAX_NO_SUITES + 1 )\n\t\t{\n\t\tconst CIPHERSUITE_INFO *cipherSuiteInfoPtr = cipherSuiteInfo[ suiteIndex ];\n\t\tconst CRYPT_ALGO_TYPE keyexAlgo = cipherSuiteInfoPtr->keyexAlgo;\n\t\tconst CRYPT_ALGO_TYPE cryptAlgo = cipherSuiteInfoPtr->cryptAlgo;\n\t\tconst CRYPT_ALGO_TYPE authAlgo = cipherSuiteInfoPtr->authAlgo;\n\t\tconst CRYPT_ALGO_TYPE macAlgo = cipherSuiteInfoPtr->macAlgo;\n\t\tconst int suiteFlags = cipherSuiteInfoPtr->flags;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* Make sure that the cipher suite is appropriate for SuiteB use if \n\t\t   necessary */\n#ifdef CONFIG_SUITEB\n\t\tif( suiteNo == 0 || suiteNo == 1 )\n\t\t\t{\n\t\t\tif( !checkSuiteBSelection( cipherSuiteInfoPtr->cipherSuite,\n\t\t\t\t\t\t\t\t\t   ( suiteBinfo == 0 ) ? \\\n\t\t\t\t\t\t\t\t\t\t\tSSL_PFLAG_SUITEB_128 : suiteBinfo, \n\t\t\t\t\t\t\t\t\t   ( suiteNo == 0 ) ? TRUE : FALSE ) )\n\t\t\t\t{\n\t\t\t\tsuiteIndex++;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\tsuiteNo++;\n\t\t\t}\n#endif /* CONFIG_SUITEB */\n\n\t\t/* Make sure that the suite is appropriate for the SSL/TLS version\n\t\t   that we're using.  Normally we can use TLS suites in SSL (e.g. \n\t\t   the AES suites), but we can't use ECC both because this requires \n\t\t   extensions and because the SSLv3 PRF mechanisms can't handle \n\t\t   ECC's premaster secrets */\n\t\tif( ( ( suiteFlags & CIPHERSUITE_FLAG_ECC ) && \\\n\t\t\t  sslVersion <= SSL_MINOR_VERSION_SSL ) || \\\n\t\t\t( ( suiteFlags & CIPHERSUITE_FLAG_TLS12 ) && \\\n\t\t\t  sslVersion <= SSL_MINOR_VERSION_TLS11 ) )\n\t\t\t{\n\t\t\tsuiteIndex++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If it's a PSK suite but we're not using PSK, skip it */\n\t\tif( ( suiteFlags & CIPHERSUITE_FLAG_PSK ) && !usePSK )\n\t\t\t{\n\t\t\tsuiteIndex++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If the keyex algorithm for this suite isn't enabled for this \n\t\t   build of cryptlib, skip all suites that use it.  We have to \n\t\t   explicitly exclude the special case where there's no keyex \n\t\t   algorithm in order to accomodate the bare TLS-PSK suites (used \n\t\t   without DH/ECDH or RSA), whose keyex mechanism is pure PSK */\n\t\tif( keyexAlgo != CRYPT_ALGO_NONE && !algoAvailable( keyexAlgo ) )\n\t\t\t{\n\t\t\tLOOP_EXT_CHECKINC_ALT( \\\n\t\t\t\t\tcipherSuiteInfo[ suiteIndex ]->keyexAlgo == keyexAlgo && \\\n\t\t\t\t\t\tsuiteIndex < cipherSuiteInfoSize,\n\t\t\t\t\tsuiteIndex++, MAX_NO_SUITES + 1 );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tENSURES( suiteIndex < cipherSuiteInfoSize );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If the bulk encryption algorithm or MAC algorithm for this suite \n\t\t   isn't enabled for this build of cryptlib, skip all suites that \n\t\t   use it */\n\t\tif( !algoAvailable( cryptAlgo ) )\n\t\t\t{\n\t\t\tLOOP_EXT_CHECKINC_ALT( \\\n\t\t\t\t\tcipherSuiteInfo[ suiteIndex ]->cryptAlgo == cryptAlgo && \\\n\t\t\t\t\t\tsuiteIndex < cipherSuiteInfoSize,\n\t\t\t\t\tsuiteIndex++, MAX_NO_SUITES + 1 );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tENSURES( suiteIndex < cipherSuiteInfoSize );\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( !algoAvailable( macAlgo ) )\n\t\t\t{\n\t\t\tLOOP_EXT_CHECKINC_ALT( \\\n\t\t\t\t\tcipherSuiteInfo[ suiteIndex ]->macAlgo == macAlgo && \\\n\t\t\t\t\t\tsuiteIndex < cipherSuiteInfoSize,\n\t\t\t\t\tsuiteIndex++, MAX_NO_SUITES + 1 );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tENSURES( suiteIndex < cipherSuiteInfoSize );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* The suite is supported, remember it.  In theory there's only a\n\t\t   single combination of the various algorithms present, but these \n\t\t   can be subsetted into different key sizes (because they're there, \n\t\t   that's why) so we have to iterate the recording of available \n\t\t   suites instead of just assigning a single value on match */\n\t\tLOOP_EXT_CHECK_ALT( \\\n\t\t\t\tcipherSuiteInfo[ suiteIndex ]->keyexAlgo == keyexAlgo && \\\n\t\t\t\tcipherSuiteInfo[ suiteIndex ]->authAlgo == authAlgo && \\\n\t\t\t\tcipherSuiteInfo[ suiteIndex ]->cryptAlgo == cryptAlgo && \\\n\t\t\t\tcipherSuiteInfo[ suiteIndex ]->macAlgo == macAlgo && \\\n\t\t\t\tsuiteIndex < cipherSuiteInfoSize, MAX_NO_SUITES + 1 )\n\t\t\t{\n\t\t\tavailableSuites[ cipherSuiteCount++ ] = \\\n\t\t\t\t\t\tcipherSuiteInfo[ suiteIndex++ ]->cipherSuite;\n#ifdef CONFIG_SUITEB\n\t\t\tif( suiteNo == 0 || suiteNo == 1 )\n\t\t\t\tbreak;\t/* Suite B has special requirements for initial suites */\n#endif /* CONFIG_SUITEB */\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( suiteIndex < cipherSuiteInfoSize );\n\t\tENSURES( cipherSuiteCount < MAX_NO_SUITES );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( suiteIndex < cipherSuiteInfoSize );\n\tENSURES( cipherSuiteCount > 0 && cipherSuiteCount < MAX_NO_SUITES );\n\n\t/* Encode the list of available cipher suites */\n\tstatus = writeUint16( stream, cipherSuiteCount * UINT16_SIZE );\n\tLOOP_EXT( suiteIndex = 0, \n\t\t\t  cryptStatusOK( status ) && suiteIndex < cipherSuiteCount, \n\t\t\t  suiteIndex++, MAX_NO_SUITES + 1 )\n\t\t{\n\t\tstatus = writeUint16( stream, availableSuites[ suiteIndex ] );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\treturn( status );\n\t}\n\n/* Process the server's certificate request:\n\n\t\tbyte\tID = SSL_HAND_SERVER_CERTREQUEST\n\t\tuint24\tlen\n\t\tbyte\tcertTypeLen\n\t\tbyte[]\tcertType\n\t  [\tuint16\tsigHashListLen\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\thashAlgoID\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\tcaNameListLen\n\t\t\tuint16\tcaNameLen\n\t\t\tbyte[]\tcaName\n\n   We don't really care what's in the certificate request packet since the \n   contents are irrelevant, in a number of cases servers have been known to \n   send out superfluous certificate requests without the admins even knowing \n   that they're doing it, in other cases servers send out requests for every \n   CA that they know of.  This can produce certificate requests containing \n   150-160 CAs, either because they've carefully catalogued every CA they've \n   ever heard of or because the software enumerates every CA in the local \n   system's trust list, leading in extreme cases to certificate request \n   messages that overflow the maximum SSL message size.  This is pretty much \n   meaningless since they can't possibly trust all of those CAs to authorise \n   access to their site.  In addition virtually all clients just have a \n   single certificate, so if there's one available we try with the one \n   certificate we've got rather than failing the handshake because the \n   server sent out the wrong CA name.\n\n   Because of this, all that we do here is perform a basic sanity check and \n   remember that we may need to submit a certificate later on if we've got \n   one, with special-case handling for certificate requests fragmented \n   across multiple SSL packets because the server wants to list every CA in \n   the known universe.\n\n   See the long comment in the cert-request handling code in ssl_svr.c \n   for the handling of the sigHashList */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processFragmentedRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t\t\t INOUT STREAM *stream,\n\t\t\t\t\t\t\t\t\t IN_RANGE( 1, MAX_PACKET_SIZE * 2 ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst int totalLength )\n\t{\n\tconst int dataLeft = sMemDataLeft( stream );\n\tconst int remainder = totalLength - dataLeft;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( totalLength >= 1 && \\\n\t\t\t  totalLength <= MAX_PACKET_SIZE + ( MAX_PACKET_SIZE / 2 ) );\n\tREQUIRES( isShortIntegerRange( dataLeft ) );\n\tREQUIRES( isShortIntegerRangeNZ( remainder ) );\n\n\t/* Skip the remaining data in the packet if there is any */\n\tif( dataLeft > 0 )\n\t\t{\n\t\tstatus = sSkip( stream, sMemDataLeft( stream ), MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Read the next packet */\n\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Returning at this point is problematic because refreshHSStream()\n\t\t   has disconnected the memory stream while reading in new data for\n\t\t   it, so that when the caller tries to disconnect the stream in\n\t\t   response to getting an error status it'll trigger a sanity-check\n\t\t   exception.  This isn't normally a problem because the top-level\n\t\t   code exits without trying to disconnect the stream in response to\n\t\t   an error from refreshHSStream(), but in this case it's being \n\t\t   called from inside a low-level function to deal with a fragmented\n\t\t   packet rather than at the top level.  To deal with this we \n\t\t   temporarily connect the stream to the receive buffer in order for\n\t\t   the caller to have something to disconnect */\n\t\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, 1 );\n\t\treturn( status );\n\t\t}\n\treturn( sSkip( stream, remainder, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processCertRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t   INOUT STREAM *stream )\n\t{\n\tint packetLength, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Although the spec says that at least one CA name entry must be \n\t   present, some implementations send a zero-length list so we allow \n\t   this as well.  The spec was changed in late TLS 1.1 drafts to reflect \n\t   this practice.\n\t   \n\t   This packet may be longer than the encapsulating SSL packet, \n\t   checkHSPacketHeader() has code to special-case this and allow a\n\t   packetLength of up to 1 1/2 SSL packet lengths */\n\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &packetLength,\n\t\t\t\t\t\t\t\t  SSL_HAND_SERVER_CERTREQUEST,\n\t\t\t\t\t\t\t\t  1 + 1 + ( ( sessionInfoPtr->version >= \\\n\t\t\t\t\t\t\t\t\t\t\t  SSL_MINOR_VERSION_TLS12 ) ? \\\n\t\t\t\t\t\t\t\t\t\t  ( UINT16_SIZE + 1 + 1 ) : 0 ) + \\\n\t\t\t\t\t\t\t\t  UINT16_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = length = sgetc( stream );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tif( length < 1 || length > 64 )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate request certificate-type \"\n\t\t\t\t  \"information\" ) );\n\t\t}\n\n\t/* If it's TLS 1.2, skip the assorted additional algorithm \n\t   information */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = length = readUint16( stream );\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( length < UINT16_SIZE || length > 64 || \\\n\t\t\t\t( length % UINT16_SIZE ) != 0 )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\tif( !cryptStatusError( status ) )\n\t\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid certificate request signature/hash \"\n\t\t\t\t\t  \"algorithm information\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Finally, skip the CA name list.  Since the packet could be an over-\n\t   length, and therefore fragmented, packet we can't use \n\t   readUniversal16() but have to apply custom proccessing that deals \n\t   with over-long packets */\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length <= 0 )\n\t\t{\n\t\t/* Zero-length CA name list */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( length < ( UINT16_SIZE + 16 ) || \\\n\t\tlength > sMemDataLeft( stream ) + ( MAX_PACKET_SIZE / 2 ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\telse\n\t\t{\n\t\t/* If the server sent an insanely long certificate request packet\n\t\t   that's fragmented across multiple SSL packets, process the\n\t\t   fragments */\n\t\tif( length > sMemDataLeft( stream ) )\n\t\t\t{\n\t\t\tstatus = processFragmentedRequest( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t\t\t   stream, length );\n\t\t\t}\n\t\telse\n\t\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid certificate request CA name list\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHandle Client/Server Keyex\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the identity hint sent with the server keyex.  It's uncertain \n   what we're supposed to do with this so we just skip it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readIdentityHint( INOUT STREAM *stream )\n\t{\n\tint length, status;\n\n\tstatus = length = readUint16( stream );\n\tif( !cryptStatusError( status ) && !isShortIntegerRange( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( !cryptStatusError( status ) && length > 0 )\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\treturn( status );\n\t}\n\n/* Read a server's DH/ECDH key agreement data:\n\n\t   DH:\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t\tuint16\t\tdh_YsLen\n\t\tbyte[]\t\tdh_Ys\n\t   ECDH:\n\t\tbyte\t\tcurveType\n\t\tuint16\t\tnamedCurve\n\t\tuint8\t\tecPointLen\t\t-- NB uint8 not uint16\n\t\tbyte[]\t\tecPoint */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readServerKeyexDH( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  OUT KEYAGREE_PARAMS *keyAgreeParams,\n\t\t\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CONTEXT *dhContextPtr,\n\t\t\t\t\t\t\t  const BOOLEAN isTLSLTS )\n\t{\n\tvoid *keyData;\n\tconst int keyDataOffset = stell( stream );\n\tint keyDataLength, dummy, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\tassert( isWritePtr( dhContextPtr, sizeof( CRYPT_CONTEXT ) ) );\n\n\tREQUIRES( isTLSLTS == TRUE || isTLSLTS == FALSE );\n\n\t/* Clear return values */\n\tmemset( keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\t*dhContextPtr = CRYPT_ERROR;\n\n\t/* Read the server DH public key data */\n\tstatus = readInteger16UChecked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE );\n\tif( cryptStatusOK( status ) && isTLSLTS )\n\t\t{\n\t\tstatus = readInteger16UChecked( stream, NULL, &dummy, \n\t\t\t\t\t\t\t\t\t\tMIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readInteger16U( stream, NULL, &dummy, 1, \n\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create a DH context from the public key data */\n\tkeyDataLength = stell( stream ) - keyDataOffset;\n\tstatus = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData, \n\t\t\t\t\t\t\t\t  keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = initDHcontextSSL( dhContextPtr, keyData, keyDataLength, \n\t\t\t\t\t\t\t\t   CRYPT_UNUSED, CRYPT_ECCCURVE_NONE, \n\t\t\t\t\t\t\t\t   isTLSLTS );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the DH public value */\n\treturn( readInteger16UChecked( stream, keyAgreeParams->publicValue,\n\t\t\t\t\t\t\t\t   &keyAgreeParams->publicValueLen,\n\t\t\t\t\t\t\t\t   MIN_PKCSIZE_THRESHOLD, \n\t\t\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readServerKeyexECDH( INOUT STREAM *stream, \n\t\t\t\t\t\t\t\tOUT KEYAGREE_PARAMS *keyAgreeParams,\n\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *dhContextPtr )\n\t{\n\tvoid *keyData;\n\tconst int keyDataOffset = stell( stream );\n\tint keyDataLength, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );\n\tassert( isWritePtr( dhContextPtr, sizeof( CRYPT_CONTEXT ) ) );\n\n\t/* Clear return values */\n\tmemset( keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\t*dhContextPtr = CRYPT_ERROR;\n\n\t/* Read the server ECDH public key data */\n\t( void ) sgetc( stream );\n\tstatus = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create an ECDH context from the public key data.  We set a dummy \n\t   curve type, the actual value is determined by the parameters sent \n\t   by the server */\n\tkeyDataLength = stell( stream ) - keyDataOffset;\n\tstatus = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData, \n\t\t\t\t\t\t\t\t  keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = initDHcontextSSL( dhContextPtr, keyData, keyDataLength, \n\t\t\t\t\t\t\t\t   CRYPT_UNUSED, CRYPT_ECCCURVE_P256, \n\t\t\t\t\t\t\t\t   FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the ECDH public value */\n\treturn( readEcdhValue( stream, keyAgreeParams->publicValue,\n\t\t\t\t\t\t   CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t   &keyAgreeParams->publicValueLen ) );\n\t}\n\n/* Process the optional server keyex:\n\n\t\tbyte\t\tID = SSL_HAND_SERVER_KEYEXCHANGE\n\t\tuint24\t\tlen\n\t   DH:\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t\tuint16\t\tdh_YsLen\n\t\tbyte[]\t\tdh_Ys\n\t [\tbyte\t\thashAlgoID\t\t-- TLS 1.2 ]\n\t [\tbyte\t\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tsignatureLen\n\t\tbyte[]\t\tsignature \n\t   DH-PSK:\n\t\tuint16\t\tpskIdentityHintLen\n\t\tbyte\t\tpskIdentityHint\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t\tuint16\t\tdh_YsLen\n\t\tbyte[]\t\tdh_Ys\n\t   ECDH:\n\t\tbyte\t\tcurveType\n\t\tuint16\t\tnamedCurve\n\t\tuint8\t\tecPointLen\t\t-- NB uint8 not uint16\n\t\tbyte[]\t\tecPoint\n\t [\tbyte\t\thashAlgoID\t\t-- TLS 1.2 ]\n\t [\tbyte\t\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tsignatureLen\n\t\tbyte[]\t\tsignature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \\\nstatic int processServerKeyex( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t   INOUT STREAM *stream,\n\t\t\t\t\t\t\t   OUT_BUFFER( keyexPublicValueMaxLen, \\\n\t\t\t\t\t\t\t\t\t\t   *keyexPublicValueLen ) \\\n\t\t\t\t\t\t\t\t\tvoid *keyexPublicValue,\n\t\t\t\t\t\t\t   IN_LENGTH_SHORT const int keyexPublicValueMaxLen,\n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *keyexPublicValueLen )\n\n\t{\n\tKEYAGREE_PARAMS keyAgreeParams, tempKeyAgreeParams;\n\tvoid *keyData DUMMY_INIT_PTR;\n\tconst BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo ) ? \\\n\t\t\t\t\t\t  TRUE : FALSE;\n\tconst BOOLEAN isPSK = ( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \\\n\t\t\t\t\t\t  TRUE : FALSE;\n\tconst BOOLEAN isTLSLTS = TEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t\tSSL_PFLAG_TLS12LTS ) ? \\\n\t\t\t\t\t\t\t TRUE : FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint keyDataOffset, keyDataLength DUMMY_INIT;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtrDynamic( keyexPublicValue, keyexPublicValueMaxLen ) );\n\tassert( isWritePtr( keyexPublicValueLen, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyexPublicValueMaxLen ) );\n\n\t/* Clear return values */\n\tmemset( keyexPublicValue, 0, min( 16, keyexPublicValueMaxLen ) );\n\t*keyexPublicValueLen = 0;\n\n\t/* Make sure that we've got an appropriate server keyex packet.  We set \n\t   the minimum key size to MIN_PKCSIZE_THRESHOLD/MIN_PKCSIZE_ECC_THRESHOLD \n\t   instead of MIN_PKCSIZE/MIN_PKCSIZE_ECC in order to provide better \n\t   diagnostics if the server is using weak keys since otherwise the data \n\t   will be rejected in the packet read long before we get to the keysize \n\t   check */\n\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\tSSL_HAND_SERVER_KEYEXCHANGE, \n\t\t\t\t\tisECC ? \\\n\t\t\t\t\t\t( 1 + UINT16_SIZE + \\\n\t\t\t\t\t\t  1 + MIN_PKCSIZE_ECCPOINT_THRESHOLD + \\\n\t\t\t\t\t\t  UINT16_SIZE + MIN_PKCSIZE_ECCPOINT_THRESHOLD ) : \\\n\t\t\t\t\t\t( UINT16_SIZE + MIN_PKCSIZE_THRESHOLD + \\\n\t\t\t\t\t\t  UINT16_SIZE + 1 + \\\n\t\t\t\t\t\t  UINT16_SIZE + MIN_PKCSIZE_THRESHOLD + \\\n\t\t\t\t\t\t  UINT16_SIZE + MIN_PKCSIZE_THRESHOLD ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"checkHSPacketHeader\" );\n\n\t/* If we're using a PSK suite then the keyex information is preceded by \n\t   a PSK identity hint */\n\tif( isPSK )\n\t\t{\n\t\tstatus = readIdentityHint( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid PSK identity hint\" ) );\n\t\t\t}\n\t\t}\n\n\t/* Read the server's keyex information and convert it into a DH/ECDH \n\t   context */\n\tkeyDataOffset = stell( stream );\n\tif( isECC )\n\t\t{\n\t\tstatus = readServerKeyexECDH( stream, &keyAgreeParams, \n\t\t\t\t\t\t\t\t\t  &handshakeInfo->dhContext );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = readServerKeyexDH( stream, &keyAgreeParams,\n\t\t\t\t\t\t\t\t\t&handshakeInfo->dhContext, isTLSLTS );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tkeyDataLength = stell( stream ) - keyDataOffset;\n\t\tstatus = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData, \n\t\t\t\t\t\t\t\t\t  keyDataLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some misconfigured servers may use very short keys, we perform a \n\t\t   special-case check for these and return a more specific message \n\t\t   than the generic bad-data error */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( cryptArgError( status ) ? \\\n\t\t\t\tCRYPT_ERROR_BADDATA : status,\n\t\t\t\t( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status,\n\t\t\t\t  SESSION_ERRINFO, \n\t\t\t\t  \"Invalid server key agreement parameters\" ) );\n\t\t}\n\tANALYSER_HINT( keyData != NULL );\n\tCFI_CHECK_UPDATE( \"readServerKeyex\" );\n\n#ifdef CONFIG_FUZZ\n\t/* Skip the server's signature, set up a dummy premaster secret, and \n\t   exit */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\t/* Skip algorithm IDs */\n\t\tsgetc( stream );\n\t\tsgetc( stream );\n\t\t}\n\tstatus = readUniversal16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmemset( handshakeInfo->premasterSecret, '*', SSL_SECRET_SIZE );\n\thandshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;\n\tFUZZ_SKIP();\n#endif /* CONFIG_FUZZ */\n\n\t/* Check the server's signature on the DH/ECDH parameters, unless it's a \n\t   PSK suite in which case the exchange is authenticated via the PSK */\n\tif( !isPSK )\n\t\t{\n\t\tstatus = checkKeyexSignature( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t\t\t  keyData, keyDataLength, isECC );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid server key agreement parameter signature\" ) );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkKeyexSignature\" );\n\n\t/* Perform phase 1 of the DH/ECDH key agreement process and save the \n\t   result so that we can send it to the server later on.  The order of \n\t   the SSL messages is a bit unfortunate since we get the one for phase \n\t   2 before we need the phase 1 value, so we have to cache the phase 1 \n\t   result for when we need it later on */\n\tmemset( &tempKeyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = krnlSendMessage( handshakeInfo->dhContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, &tempKeyAgreeParams,\n\t\t\t\t\t\t\t  sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &tempKeyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\treturn( status );\n\t\t}\n\tREQUIRES( rangeCheck( tempKeyAgreeParams.publicValueLen, 1,\n\t\t\t\t\t\t  keyexPublicValueMaxLen ) );\n\tmemcpy( keyexPublicValue, tempKeyAgreeParams.publicValue,\n\t\t\ttempKeyAgreeParams.publicValueLen );\n\t*keyexPublicValueLen = tempKeyAgreeParams.publicValueLen;\n\tzeroise( &tempKeyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_ENCRYPT\" );\n\n\t/* Perform phase 2 of the DH/ECDH key agreement */\n\tstatus = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\treturn( status );\n\t\t}\n\tif( isECC && !isTLSLTS )\n\t\t{\n\t\tconst int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;\n\n\t\t/* The output of the ECDH operation is an ECC point, but for some \n\t\t   unknown reason TLS only uses the x coordinate and not the full \n\t\t   point.  To work around this we have to rewrite the point as a \n\t\t   standalone x coordinate, which is relatively easy because we're \n\t\t   using an uncompressed point format: \n\n\t\t\t+---+---------------+---------------+\n\t\t\t|04\t|\t\tqx\t\t|\t\tqy\t\t|\n\t\t\t+---+---------------+---------------+\n\t\t\t\t|<- fldSize --> |<- fldSize --> | */\n\t\tREQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \\\n\t\t\t\t  keyAgreeParams.wrappedKey[ 0 ] == 0x04 );\n\t\tREQUIRES( boundsCheck( 1, xCoordLen, CRYPT_MAX_PKCSIZE ) );\n\t\tmemmove( keyAgreeParams.wrappedKey, \n\t\t\t\t keyAgreeParams.wrappedKey + 1, xCoordLen );\n\t\tkeyAgreeParams.wrappedKeyLen = xCoordLen;\n\t\t}\n\tREQUIRES( rangeCheck( keyAgreeParams.wrappedKeyLen, 1,\n\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,\n\t\t\tkeyAgreeParams.wrappedKeyLen );\n\thandshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;\n\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_DECRYPT\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_5( \"checkHSPacketHeader\", \"readServerKeyex\", \n\t\t\t\t\t\t\t\t\t\"checkKeyexSignature\", \"IMESSAGE_CTX_ENCRYPT\", \n\t\t\t\t\t\t\t\t\t\"IMESSAGE_CTX_DECRYPT\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Build the client key exchange packet:\n\n\t  [\tbyte\t\tID = SSL_HAND_CLIENT_KEYEXCHANGE ]\n\t  [\tuint24\t\tlen\t\t\t\t-- Written by caller ]\n\t   DH:\n\t\tuint16\t\tyLen\n\t\tbyte[]\t\ty\n\t   DH-PSK:\n\t\tuint16\t\tuserIDLen\n\t\tbyte[]\t\tuserID\n\t\tuint16\t\tyLen\n\t\tbyte[]\t\ty\n\t   ECDH:\n\t\tuint8\t\tecPointLen\t\t-- NB uint8 not uint16\n\t\tbyte[]\t\tecPoint\n\t   PSK:\n\t\tuint16\t\tuserIDLen\n\t\tbyte[]\t\tuserID\n\t   RSA:\n\t  [ uint16\t\tencKeyLen\t\t-- TLS only ]\n\t\tbyte[]\t\trsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int createClientKeyex( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t\t  IN_BUFFER_OPT( keyexPublicValueLen ) \\\n\t\t\t\t\t\t\t\tconst BYTE *keyexPublicValue,\n\t\t\t\t\t\t\t  IN_LENGTH_PKC_Z const int keyexPublicValueLen,\n\t\t\t\t\t\t\t  const BOOLEAN isPSK )\n\t{\n\tconst ATTRIBUTE_LIST *userNamePtr DUMMY_INIT_PTR;\n\tconst ATTRIBUTE_LIST *passwordPtr DUMMY_INIT_PTR;\n#ifdef USE_RSA_SUITES\n\tBYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];\n\tint wrappedKeyLength;\n#endif /* USE_RSA_SUITES */\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( ( keyexPublicValue == NULL && keyexPublicValueLen == 0 ) || \\\n\t\t\tisReadPtrDynamic( keyexPublicValue, keyexPublicValueLen ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( ( keyexPublicValue == NULL && keyexPublicValueLen == 0 ) || \\\n\t\t\t  ( keyexPublicValueLen > 0 && \\\n\t\t\t\tkeyexPublicValueLen <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isPSK == TRUE || isPSK == FALSE );\n\n\t/* If we're using a PSK mechanism, get the user name and password/PSK */\n\tif( isPSK )\n\t\t{\n\t\tuserNamePtr = findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME );\n\t\tpasswordPtr = findSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_PASSWORD );\n\n\t\tREQUIRES( passwordPtr != NULL );\n\t\tREQUIRES( userNamePtr != NULL );\n\t\t}\n\n\t/* If we're using DH/ECDH (with optional PSK additions), write the \n\t   necessary information */\n\tif( keyexPublicValue != NULL )\n\t\t{\n\t\t/* If it's a PSK algorithm, convert the DH/ECDH premaster secret to\n\t\t   a DH/ECDH + PSK premaster secret and write the client identity \n\t\t   that's required by PSK */\n\t\tif( isPSK )\n\t\t\t{\n\t\t\tBYTE premasterTempBuffer[ CRYPT_MAX_PKCSIZE + 8 ];\n\t\t\tconst int premasterTempSize = handshakeInfo->premasterSecretSize;\n\n\t\t\t/* Since this operation rewrites the premaster secret, we have to\n\t\t\t   save the original contents into a temporary buffer first */\n\t\t\tREQUIRES( rangeCheck( handshakeInfo->premasterSecretSize, 1,\n\t\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE ) );\n\t\t\tmemcpy( premasterTempBuffer, handshakeInfo->premasterSecret,\n\t\t\t\t\thandshakeInfo->premasterSecretSize );\n\t\t\tstatus = createSharedPremasterSecret( \\\n\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t&handshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\tpasswordPtr->value, \n\t\t\t\t\t\t\tpasswordPtr->valueLength, \n\t\t\t\t\t\t\tpremasterTempBuffer, premasterTempSize,\n\t\t\t\t\t\t\tTEST_FLAG( passwordPtr->flags, \n\t\t\t\t\t\t\t\t\t   ATTR_FLAG_ENCODEDVALUE ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t\tzeroise( premasterTempBuffer, premasterTempSize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tretExt( status,\n\t\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Couldn't create master secret from shared \"\n\t\t\t\t\t\t  \"secret/password value\" ) );\n\t\t\t\t}\n\n\t\t\t/* Write the PSK client identity */\n\t\t\twriteUint16( stream, userNamePtr->valueLength );\n\t\t\tstatus = swrite( stream, userNamePtr->value,\n\t\t\t\t\t\t\t userNamePtr->valueLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Write the DH/ECDH public value that we saved earlier when we\n\t\t   performed phase 1 of the key agreement process */\n\t\tif( isEccAlgo( handshakeInfo->keyexAlgo ) )\n\t\t\t{\n\t\t\tsputc( stream, keyexPublicValueLen );\n\t\t\tstatus = swrite( stream, keyexPublicValue,\n\t\t\t\t\t\t\t keyexPublicValueLen );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = writeInteger16U( stream, keyexPublicValue,\n\t\t\t\t\t\t\t\t\t  keyexPublicValueLen );\n\t\t\t}\n\t\t\n\t\treturn( status );\n\t\t}\n\n\t/* To get to this point, we can't have been using DH/ECDH */\n\tREQUIRES( keyexPublicValue == NULL && keyexPublicValueLen == 0 );\n\n\t/* If we're using straight PSK, write the client identity */\n\tif( isPSK )\n\t\t{\n\t\t/* Create the shared premaster secret from the user password */\n\t\tstatus = createSharedPremasterSecret( \\\n\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t&handshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\tpasswordPtr->value, \n\t\t\t\t\t\t\tpasswordPtr->valueLength, NULL, 0,\n\t\t\t\t\t\t\tTEST_FLAG( passwordPtr->flags, \n\t\t\t\t\t\t\t\t\t   ATTR_FLAG_ENCODEDVALUE ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't create master secret from shared \"\n\t\t\t\t\t  \"secret/password value\" ) );\n\t\t\t}\n\n\t\t/* Write the PSK client identity */\n\t\twriteUint16( stream, userNamePtr->valueLength );\n\t\treturn( swrite( stream, userNamePtr->value,\n\t\t\t\t\t\tuserNamePtr->valueLength ) );\n\t\t}\n\n#ifdef USE_RSA_SUITES\n\t/* It's an RSA keyex, write the RSA-wrapped premaster secret */\n\tstatus = wrapPremasterSecret( sessionInfoPtr, handshakeInfo, wrappedKey, \n\t\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE, &wrappedKeyLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\t/* The original Netscape SSL implementation didn't provide a length \n\t\t   for the encrypted key and everyone copied that so it became the \n\t\t   de facto standard way to do it (sic faciunt omnes.  The spec \n\t\t   itself is ambiguous on the topic).  This was fixed in TLS \n\t\t   (although the spec is still ambiguous) so the encoding differs \n\t\t   slightly between SSL and TLS */\n\t\treturn( swrite( stream, wrappedKey, wrappedKeyLength ) );\n\t\t}\n#endif /* USE_SSL3 */\n\n\treturn( writeInteger16U( stream, wrappedKey, wrappedKeyLength ) );\n#else\n\tretIntError();\n#endif /* USE_RSA_SUITES */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tServer Certificate Checking Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Matching names in certificates can get quite tricky due to the usual \n   erratic nature of what gets put in them.  Firstly, supposed FQDNs can be \n   unqualified names and/or can be present as full URLs rather than just \n   domain names, so we use sNetParseURL() on them before doing anything else \n   with them.  Secondly, PKIX tries to pretend that wildcard certificates \n   don't exist, and so there are no official guidelines for how they should \n   be laid out.  To minimise the potential for mischief we only allow a\n   wildcard at the start of the domain, and don't allow wildcards for the \n   first- or second-level names.\n   \n   Since this code is going to result in server names (and therefore \n   connections) being rejected, it's unusually loquacious about the reasons \n   for the rejection */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int matchName( INOUT_BUFFER_FIXED( serverNameLength ) \\\n\t\t\t\t\t\tBYTE *serverName,\n\t\t\t\t\t  IN_LENGTH_DNS const int serverNameLength,\n\t\t\t\t\t  INOUT_BUFFER_FIXED( originalCertNameLength ) \\\n\t\t\t\t\t\tBYTE *certName,\n\t\t\t\t\t  IN_LENGTH_DNS const int originalCertNameLength,\n\t\t\t\t\t  OUT ERROR_INFO *errorInfo )\n\t{\n\tURL_INFO urlInfo;\n\tBOOLEAN hasWildcard = FALSE;\n\tint certNameLength, dotCount = 0, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( serverName, serverNameLength ) );\n\tassert( isWritePtrDynamic( certName, originalCertNameLength ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( serverNameLength > 0 && serverNameLength <= MAX_DNS_SIZE );\n\tREQUIRES( originalCertNameLength > 0 && \\\n\t\t\t  originalCertNameLength <= MAX_DNS_SIZE );\n\n\t/* Clear return value */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Extract the FQDN portion from the certificate name */\n\tstatus = sNetParseURL( &urlInfo, certName, originalCertNameLength, \n\t\t\t\t\t\t   URL_TYPE_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"Invalid host name '%s' in server's certificate\",\n\t\t\t\t  sanitiseString( certName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  originalCertNameLength ) ) );\n\t\t}\n\tcertName = ( BYTE * ) urlInfo.host;\n\tcertNameLength = urlInfo.hostLen;\n\tENSURES( certNameLength > 0 && certNameLength <= MAX_URL_SIZE ); \n\n\t/* If the name in the certificate is longer than the server name then it \n\t   can't be a match */\n\tif( certNameLength > serverNameLength )\n\t\t{\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"Server name '%s' doesn't match host name '%s' in \"\n\t\t\t\t  \"server's certificate\", \n\t\t\t\t  sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  serverNameLength ),\n\t\t\t\t  sanitiseString( certName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  certNameLength ) ) );\n\t\t}\n\n\t/* Make sure that, if it's a wildcarded name, it follows the pattern \n\t   \"'*' ... '.' ... '.' ...\" */\n\tLOOP_EXT( i = 0, i < certNameLength, i++, MAX_URL_SIZE + 1 )\n\t\t{\n\t\tconst int ch = byteToInt( certName[ i ] );\n\n\t\tif( ch == '*' )\n\t\t\t{\n\t\t\tif( i != 0 )\n\t\t\t\t{\n\t\t\t\t/* The wildcard character isn't the first one in the name, \n\t\t\t\t   it's invalid */\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t\t  \"Host name '%s' in server's certificate contains \"\n\t\t\t\t\t\t  \"wildcard at invalid location\",\n\t\t\t\t\t\t  sanitiseString( certName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t\t  certNameLength ) ) );\n\t\t\t\t}\n\t\t\thasWildcard = TRUE;\n\t\t\t}\n\t\tif( ch == '.' )\n\t\t\tdotCount++;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( hasWildcard && dotCount < 2 )\n\t\t{\n\t\t/* The wildcard applies to the first- or second-level domain, it's \n\t\t   invalid */\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t  \"Host name '%s' in server's certificate contains \"\n\t\t\t\t  \"wildcard at invalid domain level\",\n\t\t\t\t  sanitiseString( certName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t  certNameLength ) ) );\n\t\t}\n\n\t/* Match the certificate name and the server name, taking into account\n\t   wildcarding */\n\tif( hasWildcard )\n\t\t{\n\t\tconst int delta = serverNameLength - ( certNameLength - 1 );\n\n\t\tENSURES_B( delta > 0 && delta < serverNameLength );\n\n\t\t/* Match the suffix past the wildcard */\n\t\tif( !memcmp( certName + 1, serverName + delta, certNameLength - 1 ) )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a straight match */\n\t\tif( certNameLength == serverNameLength && \\\n\t\t\t!memcmp( certName, serverName, certNameLength ) )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* The name doesn't match */\n\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t  \"Server name '%s' doesn't match host name '%s' in server's \" \n\t\t\t  \"certificate\", \n\t\t\t  sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t  serverNameLength ),\n\t\t\t  sanitiseString( certName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t  certNameLength ) ) );\n\t}\n\n/* Check the remote host name against one or more server names in the \n   certificate */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 5 ) ) \\\nstatic int checkHostName( const CRYPT_CERTIFICATE iCryptCert,\n\t\t\t\t\t\t  INOUT_BUFFER_FIXED( serverNameLength ) void *serverName,\n\t\t\t\t\t\t  IN_LENGTH_DNS const int serverNameLength,\n\t\t\t\t\t\t  const BOOLEAN multipleNamesPresent,\n\t\t\t\t\t\t  OUT ERROR_INFO *errorInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\tstatic const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;\n\tstatic const int dnsNameValue = CRYPT_CERTINFO_DNSNAME;\n\tchar certName[ MAX_DNS_SIZE + 8 ];\n\tint certNameLength = CRYPT_ERROR, status, LOOP_ITERATOR;\n\n\tassert( isWritePtrDynamic( serverName, serverNameLength ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( isHandleRangeValid( iCryptCert ) );\n\tREQUIRES( serverNameLength > 0 && serverNameLength <= MAX_DNS_SIZE );\n\tREQUIRES( multipleNamesPresent == TRUE || \\\n\t\t\t  multipleNamesPresent == FALSE );\n\n\t/* Clear return value */\n\tmemset( errorInfo, 0, sizeof( ERROR_INFO ) );\n\n\t/* Get the CN and check it against the host name */\n\tsetMessageData( &msgData, certName, MAX_DNS_SIZE );\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_COMMONNAME );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcertNameLength = msgData.length;\n\t\tstatus = matchName( serverName, serverNameLength, certName,\n\t\t\t\t\t\t\tcertNameLength, errorInfo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\treturn( status );\n\n\t\t/* If this was the only name that's present then we can't go any \n\t\t   further (the extended error information will have been provided \n\t\t   by matchName()) */\n\t\tif( !multipleNamesPresent )\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t}\n\n\t/* The CN didn't match, check the altName */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &altNameValue, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &dnsNameValue, \n\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT_INSTANCE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We couldn't find a DNS name in the altName, which means that the \n\t\t   server name doesn't match the name (from the previously-used CN) \n\t\t   in the certificate.\n\t\t   \n\t\t   If there's no CN present then there's no certificate host name to \n\t\t   use in the error message and we have to construct our own one, \n\t\t   otherwise it'll have been provided by the previous call to \n\t\t   matchName() */\n\t\tkrnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t ( MESSAGE_CAST ) &nameValue, \n\t\t\t\t\t\t CRYPT_ATTRIBUTE_CURRENT );\t/* Re-select subject DN */\n\t\tif( certNameLength == CRYPT_ERROR )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t\t\t  \"Server name '%s' doesn't match host name in \"\n\t\t\t\t\t  \"server's certificate\",\n\t\t\t\t\t  sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t\t\t  serverNameLength ) ) );\n\t\t\t}\n\t\treturn( CRYPT_ERROR_INVALID );\t/* See comment above */\n\t\t}\n\tLOOP_LARGE_CHECKINC( cryptStatusOK( status ), \n\t\t\t\t\t\t status = krnlSendMessage( iCryptCert, \n\t\t\t\t\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\t\tMESSAGE_VALUE_CURSORNEXT,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_CURRENT_INSTANCE ) )\n\t\t{\n\t\tsetMessageData( &msgData, certName, MAX_DNS_SIZE );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_DNSNAME );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = matchName( serverName, serverNameLength, certName,\n\t\t\t\t\t\t\t\tmsgData.length, errorInfo );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tkrnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &nameValue, CRYPT_ATTRIBUTE_CURRENT );\n\t\t\t\t\t /* Re-select subject DN */\n\n\t/* We couldn't find any name that matches the server name */\n\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t( CRYPT_ERROR_INVALID, errorInfo,\n\t\t\t  \"Server name '%s' doesn't match any of the host names in \"\n\t\t\t  \"server's certificate\",\n\t\t\t  sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t  serverNameLength ) ) );\n\t}\n\n/* Check that the certificate from the remote system is in order.  This \n   involves checking that the name of the host that we've connected to\n   matches one of the names in the certificate, and that the certificate \n   itself is in order */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkCertificateInfo( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst CRYPT_CERTIFICATE iCryptCert = sessionInfoPtr->iKeyexCryptContext;\n\tMESSAGE_DATA msgData;\n\tconst ATTRIBUTE_LIST *serverNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME );\n\tstatic const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;\n\tstatic const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;\n\tconst int verifyFlags = \\\n\t\t\t\tGET_FLAGS( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t   SSL_PFLAG_DISABLE_NAMEVERIFY | \\\n\t\t\t\t\t\t   SSL_PFLAG_DISABLE_CERTVERIFY );\n\tBOOLEAN multipleNamesPresent = FALSE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* If all verification has been disabled then there's nothing to do */\n\tif( verifyFlags == ( SSL_PFLAG_DISABLE_NAMEVERIFY | \\\n\t\t\t\t\t\t SSL_PFLAG_DISABLE_CERTVERIFY ) )\n\t\treturn( CRYPT_OK );\n\n\t/* The server name is traditionally given as the certificate's CN, \n\t   however it may also be present as an altName.  First we check whether \n\t   there's an altName present, this is used to control error handling \n\t   since if there isn't one present we stop after a failed CN check and \n\t   if there is one present we continue on to the altName(s) */\n\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &altNameValue, \n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CERTINFO_DNSNAME );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tmultipleNamesPresent = TRUE;\n\t\t}\n\tkrnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t ( MESSAGE_CAST ) &nameValue, CRYPT_ATTRIBUTE_CURRENT );\n\t\t\t\t\t /* Re-select the subject DN */\n\n\t/* If there's a server name present and name checking hasn't been \n\t   disabled, make sure that it matches one of the names in the \n\t   certificate */\n\tif( serverNamePtr != NULL && \\\n\t\t!( verifyFlags & SSL_PFLAG_DISABLE_NAMEVERIFY ) )\n\t\t{\n\t\tstatus = checkHostName( iCryptCert, serverNamePtr->value, \n\t\t\t\t\t\t\t\tserverNamePtr->valueLength, \n\t\t\t\t\t\t\t\tmultipleNamesPresent, SESSION_ERRINFO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* If certificate verification hasn't been disabled, make sure that the \n\t   server's certificate verifies */\n\tif( !( verifyFlags & SSL_PFLAG_DISABLE_CERTVERIFY ) )\n\t\t{\n\t\t/* This is something that can't be easily enabled by default since \n\t\t   cryptlib isn't a web browser and therefore won't follow the \n\t\t   \"trust anything from a commercial CA\" model.  In particular \n\t\t   cryptlib users tend to fall into two classes, commercial/\n\t\t   government users, often in high-security environments, who run \n\t\t   their own PKIs and definitely won't want anything from a \n\t\t   commercial CA to be accepted, and noncommercial users who won't \n\t\t   be buying certificates from a commercial CA.  In neither of these \n\t\t   cases is trusting certs from a commercial CA useful, in the \n\t\t   former case it leads to a serious security breach (as some US \n\t\t   government agencies have discovered), in the latter case it leads \n\t\t   to all certificates being rejected since they weren't bought from \n\t\t   a commercial CA.  The recommended solutions to this problem are \n\t\t   covered in the cryptlib manual */\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClient-side Connect Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform the initial part of the handshake with the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int beginClientHandshake( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n#ifndef NO_SESSION_CACHE\n\tconst ATTRIBUTE_LIST *attributeListPtr;\n#endif /* NO_SESSION_CACHE */\n\tSTREAM *stream = &handshakeInfo->stream;\n\tSCOREBOARD_INFO scoreboardInfo = { 0 };\n\tMESSAGE_DATA msgData;\n\tBYTE sentSessionID[ MAX_SESSIONID_SIZE + 8 ];\n\tBOOLEAN sessionIDsent = FALSE, resumeSession = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint packetOffset, clientHelloLength, serverHelloLength;\n\tint sentSessionIDlength DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Check whether we have (potentially) cached data available for the\n\t   server.  If we've had the connection to the remote system provided\n\t   by the user (for example as an already-connected socket) then there\n\t   won't be any server name information present, so we can only\n\t   perform a session resume if we've established the connection\n\t   ourselves */\n#ifndef NO_SESSION_CACHE\n\tattributeListPtr = findSessionInfo( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME );\n\tif( attributeListPtr != NULL )\n\t\t{\n\t\tvoid *scoreboardInfoPtr = \\\n\t\t\t\tDATAPTR_GET( sessionInfoPtr->sessionSSL->scoreboardInfoPtr );\n\t\tint resumedSessionID;\n\n\t\tREQUIRES( scoreboardInfoPtr != NULL );\n\n\t\tresumedSessionID = \\\n\t\t\tlookupScoreboardEntry( scoreboardInfoPtr, SCOREBOARD_KEY_FQDN, \n\t\t\t\t\t\t\t\t   attributeListPtr->value,\n\t\t\t\t\t\t\t\t   attributeListPtr->valueLength, \n\t\t\t\t\t\t\t\t   &scoreboardInfo );\n\t\tif( !cryptStatusError( resumedSessionID ) )\n\t\t\t{\n\t\t\t/* We've got cached data for the server available, remember the \n\t\t\t   session ID so that we can send it to the server */\n\t\t\tstatus = attributeCopyParams( handshakeInfo->sessionID, \n\t\t\t\t\t\t\t\t\t\t  MAX_SESSIONID_SIZE, \n\t\t\t\t\t\t\t\t\t\t  &handshakeInfo->sessionIDlength,\n\t\t\t\t\t\t\t\t\t\t  scoreboardInfo.key, \n\t\t\t\t\t\t\t\t\t\t  scoreboardInfo.keySize );\n\t\t\tENSURES( cryptStatusOK( status ) );\n\n\t\t\t/* Make a copy of the session ID that we're sending so that we \n\t\t\t   can check it against what the server sends back to us later.  \n\t\t\t   This is required for when the server can't resume the session\n\t\t\t   and sends us a fresh session ID */\n\t\t\tREQUIRES( rangeCheck( handshakeInfo->sessionIDlength, 1, \n\t\t\t\t\t\t\t\t  MAX_SESSIONID_SIZE ) );\n\t\t\tmemcpy( sentSessionID, handshakeInfo->sessionID, \n\t\t\t\t\thandshakeInfo->sessionIDlength );\n\t\t\tsentSessionIDlength = handshakeInfo->sessionIDlength;\n\t\t\t}\n\t\t}\n#endif /* NO_SESSION_CACHE */\n\tCFI_CHECK_UPDATE( \"lookupScoreboardEntry\" );\n\n\t/* Get the nonce that's used to randomise all crypto ops */\n\tsetMessageData( &msgData, handshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Build the client hello packet:\n\n\t\tbyte\t\tID = SSL_HAND_CLIENT_HELLO\n\t\tuint24\t\tlen\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tbyte[32]\tnonce\n\t\tbyte\t\tsessIDlen\n\t\tbyte[]\t\tsessID\n\t\tuint16\t\tsuiteLen\n\t\tuint16[]\tsuite\n\t\tbyte\t\tcoprLen = 1\n\t\tbyte[]\t\tcopr = { 0x00 }\n\t  [\tuint16\textListLen\t\t\t-- RFC 3546/RFC 4366/RFC 6066\n\t\t\tbyte\textType\n\t\t\tuint16\textLen\n\t\t\tbyte[]\textData ] \n\n\t   Extensions present a bit of an interoperability problem on the client\n\t   side, if we use them then we have to add them to the client hello \n\t   before we know whether the server can handle them, and some older \n\t   servers can't.  This is particularly bad in cryptlib's case where \n\t   it's used with embedded systems, which have ancient and buggy SSL/TLS\n\t   implementations that are rarely if ever updated.  A reasonable \n\t   compromise is to only enable the use of extensions when the user has \n\t   asked for TLS 1.1+ support, however if ECC suites are being used then\n\t   we have to write them because they're required for ECC use */\n\tstatus = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = continueHSPacketStream( stream, SSL_HAND_CLIENT_HELLO, \n\t\t\t\t\t\t\t\t\t &packetOffset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tsputc( stream, SSL_MAJOR_VERSION );\n\tsputc( stream, sessionInfoPtr->version );\n\thandshakeInfo->clientOfferedVersion = sessionInfoPtr->version;\n\tswrite( stream, handshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\tsputc( stream, handshakeInfo->sessionIDlength );\n\tif( handshakeInfo->sessionIDlength > 0 )\n\t\t{\n\t\tswrite( stream, handshakeInfo->sessionID, \n\t\t\t\thandshakeInfo->sessionIDlength );\n\t\tsessionIDsent = TRUE;\n\t\t}\n\tstatus = writeCipherSuiteList( stream, sessionInfoPtr->version,\n\t\t\t\t\t\tfindSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t CRYPT_SESSINFO_USERNAME ) != NULL ? \\\n\t\t\t\t\t\t\tTRUE : FALSE,\n\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t   SSL_PFLAG_SUITEB ) ? TRUE : FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsputc( stream, 1 );\t\t/* No compression */\n\t\tstatus = sputc( stream, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS11 || \\\n\t\t  ( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS && \\\n\t\t\talgoAvailable( CRYPT_ALGO_ECDH ) ) ) )\n\t\t{\n\t\t/* Extensions are only written when newer versions of TLS are \n\t\t   enabled, unless they're required for ECC use, see the comment \n\t\t   at the start of this code block for details */\n\t\tstatus = writeClientExtensions( stream, sessionInfoPtr );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendPacketSSL( sessionInfoPtr, stream, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tclientHelloLength = stell( stream ) - SSL_HEADER_SIZE;\n\tCFI_CHECK_UPDATE( \"sendPacketSSL\" );\n\n\t/* Perform the assorted hashing of the client hello in between the \n\t   network ops where it's effectively free */\n\tstatus = hashHSPacketWrite( handshakeInfo, stream, 0 );\n\tsMemDisconnect( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"hashHSPacketWrite\" );\n\n\t/* Process the server hello.  The server will usually send us a session \n\t   ID to indicate a resumable session (if we've sent one in our \n\t   request).  This indicated by a return status of OK_SPECIAL, if this \n\t   is present then we try and resume the session.\n\n\t   Note that this processing leads to a slight inefficiency in hashing \n\t   when multiple hash algorithms need to be accommodated (as they do\n\t   when TLS 1.2+ is enabled) because readHSPacketSSL() hashes the \n\t   incoming packet data as it arrives, and if all possible server \n\t   handshake packets are combined into a single SSL message packet then \n\t   they'll arrive, and need to be hashed, before the server hello is\n\t   processed and we can selectively disable the hash algorithms that\n\t   won't be needed.  Fixing this would require adding special-case\n\t   processing to readHSPacketSSL() to detect the use of \n\t   SSL_MSG_FIRST_HANDSHAKE for the client and skip the hashing, relying\n\t   on the calling code to then pick out the portions that need to be\n\t   hashed.  This probably isn't worth the effort required, since it adds\n\t   a lot of code complexity and custom processing just to save a small\n\t   amount of hashing on the client, which will generally be the less\n\t   resource-constrained of the two parties */\n\tstatus = readHSPacketSSL( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t  &serverHelloLength, SSL_MSG_FIRST_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, serverHelloLength );\n\tstatus = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, FALSE );\n\tif( status == OK_SPECIAL )\n\t\t{\n\t\t/* The server has provided a session ID, if we sent one in our \n\t\t   request and it matches what the server returned then this is a \n\t\t   resumed session */\n\t\tif( sessionIDsent && \\\n\t\t\thandshakeInfo->sessionIDlength == sentSessionIDlength && \\\n\t\t\t!memcmp( handshakeInfo->sessionID, sentSessionID,\n\t\t\t\t\t sentSessionIDlength ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"Server negotiated session resumption\" ));\n\t\t\tresumeSession = TRUE;\n\t\t\t}\n\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tserverHelloLength = stell( stream );\t/* May be followed by other packets */\n\tCFI_CHECK_UPDATE( \"processHelloSSL\" );\n\n\t/* The server has acknowledged our attempt to resume a session, handle \n\t   the session resumption */\n\tif( resumeSession )\n\t\t{\n\t\tsMemDisconnect( stream );\n\n\t\t/* We're resuming a previous session, if extended TLS facilities \n\t\t   were in use then make sure that the resumed session uses the same \n\t\t   facilities */\n\t\tif( !TEST_FLAGS( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t SSL_RESUMEDSESSION_FLAGS, \n\t\t\t\t\t\t scoreboardInfo.metaData ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"Server negotiated resumption of session with \"\n\t\t\t\t\t\t  \"options %x using options %x.\\n\", \n\t\t\t\t\t\t  scoreboardInfo.metaData,\n\t\t\t\t\t\t  GET_FLAGS( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t\t\t\t SSL_RESUMEDSESSION_FLAGS ) ));\n\t\t\treturn( CRYPT_ERROR_INVALID );\n\t\t\t}\n\n\t\t/* Remember the premaster secret for the resumed session */\n\t\tstatus = attributeCopyParams( handshakeInfo->premasterSecret, \n\t\t\t\t\t\t\t\t\t  SSL_SECRET_SIZE,\n\t\t\t\t\t\t\t\t\t  &handshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\t\t\t  scoreboardInfo.data, \n\t\t\t\t\t\t\t\t\t  scoreboardInfo.dataSize );\n\t\tENSURES( cryptStatusOK( status ) );\n\n\t\t/* Tell the caller that it's a resumed session */\n\t\tDEBUG_PRINT(( \"Resuming session with server based on \"\n\t\t\t\t\t  \"sessionID = \\n\" ));\n\t\tDEBUG_DUMP_DATA( handshakeInfo->sessionID, \n\t\t\t\t\t\t handshakeInfo->sessionIDlength );\n\t\tstatus = OK_SPECIAL;\n\t\t}\n\tCFI_CHECK_UPDATE( \"resumeSession\" );\n\n\t/* TLS 1.2 LTS implicitly enables various other crypto options, now that\n\t   we've got past the initial negotiations, enable those too */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS ) )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS );\n\t\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSL_PFLAG_ENCTHENMAC );\n\t\t\t}\n\n\t\t/* Hash the hello messages */\n\t\tgetHashParameters( CRYPT_ALGO_SHA2, 0, &handshakeInfo->helloHashFunction, \n\t\t\t\t\t\t   &handshakeInfo->helloHashSize );\n\t\thandshakeInfo->helloHashFunction( handshakeInfo->helloHashInfo, NULL, 0,\n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE, \n\t\t\t\t\t\t\t\t\t\t  clientHelloLength, HASH_STATE_START );\n\t\thandshakeInfo->helloHashFunction( handshakeInfo->helloHashInfo, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t\t\t  serverHelloLength, HASH_STATE_CONTINUE );\n\t\t}\n\tCFI_CHECK_UPDATE( \"TLS12LTS\" );\n\n\t/* Return CRYPT_OK for a standard session, OK_SPECIAL for a resumed \n\t   one */\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"lookupScoreboardEntry\", \"sendPacketSSL\", \n\t\t\t\t\t\t\t\t\t\"hashHSPacketWrite\", \"processHelloSSL\",\n\t\t\t\t\t\t\t\t\t\"resumeSession\", \"TLS12LTS\" ) );\n\treturn( status );\n\t}\n\n/* Exchange keys with the server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int exchangeClientKeys( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM *stream = &handshakeInfo->stream;\n\tBYTE keyexPublicValue[ CRYPT_MAX_PKCSIZE + 8 ];\n\tBOOLEAN needClientCert = FALSE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint packetOffset, length, keyexPublicValueLen = 0, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Process the optional server supplemental data:\n\n\t\tbyte\t\tID = SSL_HAND_SUPPLEMENTAL_DATA\n\t\tuint24\t\tlen\n\t\tuint16\t\ttype\n\t\tuint16\t\tlen\n\t\tbyte[]\t\tvalue\n\n\t   This is a kitchen-sink mechanism for exchanging arbitrary further \n\t   data during the TLS handshake (see RFC 4680).  The presence of the\n\t   supplemental data has to be negotiated using TLS extensions, however\n\t   the nature of this negotiation is unspecified so we can't just\n\t   reject an unexpected supplemental data message as required by the RFC \n\t   because it may have been quite legitimately negotiated by a TLS\n\t   extension that we don't know about.  Because of this we perform\n\t   basic validity checks on any supplemental data messages that arrive\n\t   but otherwise ignore them */\n\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sPeek( stream ) == SSL_HAND_SUPPLEMENTAL_DATA )\n\t\t{\n\t\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t\t  SSL_HAND_SUPPLEMENTAL_DATA, \n\t\t\t\t\t\t\t\t\t  UINT16_SIZE + UINT16_SIZE + 1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\treadUint16( stream );\t\t\t\t/* Type */\n\t\tstatus = readUniversal16( stream );\t/* Value */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid supplemental data\" ) );\n\t\t\t}\n\t\tDEBUG_PRINT(( \"Server sent %d bytes TLS supplemental data.\\n\",\n\t\t\t\t\t  length ));\n\t\tassert_nofuzz( DEBUG_WARN );\n\t\t}\n\tCFI_CHECK_UPDATE( \"checkHSPacketHeader\" );\n\n#ifndef CONFIG_FUZZ\n\t/* Process the optional server certificate chain:\n\n\t\tbyte\t\tID = SSL_HAND_CERTIFICATE\n\t\tuint24\t\tlen\n\t\tuint24\t\tcertLen\t\t\t-- 1...n certificates ordered\n\t\tbyte[]\t\tcertificate\t\t-- leaf -> root */\n\tif( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = readSSLCertChain( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\tstream, &sessionInfoPtr->iKeyexCryptContext,\n\t\t\t\t\t\t\tFALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Check the details in the certificate chain */\n\t\tstatus = checkCertificateInfo( sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n#endif /* CONFIG_FUZZ */\n\tCFI_CHECK_UPDATE( \"readSSLCertChain\" );\n\n\t/* Process the optional server keyex */\n\tif( isKeyxAlgo( handshakeInfo->keyexAlgo ) )\n\t\t{\n\t\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tstatus = processServerKeyex( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t stream, keyexPublicValue, \n\t\t\t\t\t\t\t\t\t CRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t\t\t &keyexPublicValueLen );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's a pure PSK mechanism then there may be a pointless server \n\t\t   keyex containing an identity hint whose purpose is never \n\t\t   explained (more specifically the RFC makes it a SHOULD NOT, and\n\t\t   clients MUST ignore it), in which case we have to process the \n\t\t   packet to get rid of the identity hint */\n\t\tif( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )\n\t\t\t{\n\t\t\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( sPeek( stream ) == SSL_HAND_SUPPLEMENTAL_DATA )\n\t\t\t\t{\n\t\t\t\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t\t\t\t  SSL_HAND_SERVER_KEYEXCHANGE, \n\t\t\t\t\t\t\t\t\t\t\t  ( UINT16_SIZE + 1 ) );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\tstatus = readIdentityHint( stream );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t\t  \"Invalid PSK identity hint\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n#ifdef CONFIG_FUZZ\n\t\t/* Set up a dummy premaster secret */\n\t\tmemset( handshakeInfo->premasterSecret, '*', SSL_SECRET_SIZE );\n\t\thandshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;\n#endif /* CONFIG_FUZZ */\n\t\t\n\t\t/* Keep static analysers happy */\n\t\tmemset( keyexPublicValue, 0, CRYPT_MAX_PKCSIZE );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processServerKeyex\" );\n\n\t/* Process the optional server certificate request.  Since we're about \n\t   to peek ahead into the stream to see if we need to process a server \n\t   certificate request, we have to refresh the stream at this point in \n\t   case the certificate request wasn't bundled with the preceding \n\t   packets */\n\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sPeek( stream ) == SSL_HAND_SERVER_CERTREQUEST )\n\t\t{\n\t\tstatus = processCertRequest( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tneedClientCert = TRUE;\n\t\t}\n\tCFI_CHECK_UPDATE( \"processCertRequest\" );\n\n\t/* Process the server hello done:\n\n\t\tbyte\t\tID = SSL_HAND_SERVER_HELLODONE\n\t\tuint24\t\tlen = 0 */\n\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t  SSL_HAND_SERVER_HELLODONE, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\n\t/* If we're fuzzing the input then we don't need to go through any of \n\t   the following crypto calisthenics */\n\tFUZZ_SKIP();\n\n\t/* If we need a client certificate, build the client certificate packet */\n\tstatus = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( needClientCert )\n\t\t{\n\t\tBOOLEAN sentResponse = FALSE;\n\n\t\t/* If we haven't got a certificate available, tell the server.  SSL \n\t\t   and TLS differ here, SSL sends a no-certificate alert while TLS \n\t\t   sends an empty client certificate packet, which is handled \n\t\t   further on */\n\t\tif( sessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t\t{\n\t\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n#ifdef USE_SSL3\n\t\t\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\t\t\t{\n\t\t\t\tstatic const BYTE noCertAlertSSLTemplate[] = {\n\t\t\t\t\tSSL_MSG_ALERT,\t\t\t\t\t\t\t/* ID */\n\t\t\t\t\tSSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL,/* Version */\n\t\t\t\t\t0, 2,\t\t\t\t\t\t\t\t\t/* Length */\n\t\t\t\t\tSSL_ALERTLEVEL_WARNING, SSL_ALERT_NO_CERTIFICATE\n\t\t\t\t\t};\n\n\t\t\t\t/* This is an alert-protocol message rather than a handshake\n\t\t\t\t   message so we don't add it to the handshake packet stream\n\t\t\t\t   but write it directly to the network stream */\n\t\t\t\tswrite( &sessionInfoPtr->stream, noCertAlertSSLTemplate, 7 );\n\t\t\t\tsentResponse = TRUE;\n\t\t\t\t}\n#endif /* USE_SSL3 */\n\n\t\t\t/* The reaction to the lack of a certificate is up to the server \n\t\t\t   (some just request one anyway even though they can't do \n\t\t\t   anything with it) so from here on we just continue as if \n\t\t\t   nothing had happened */\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSL_PFLAG_CLIAUTHSKIPPED );\n\t\t\tneedClientCert = FALSE;\n\t\t\t}\n\n\t\t/* If we haven't sent a response yet, send it now.  If no private \n\t\t   key is available this will send the zero-length chain that's \n\t\t   required by TLS  */\n\t\tif( !sentResponse )\n\t\t\t{\n\t\t\tstatus = writeSSLCertChain( sessionInfoPtr, stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tsMemDisconnect( stream );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"writeSSLCertChain\" );\n\n\t/* Build the client key exchange packet */\n\tstatus = continueHSPacketStream( stream, SSL_HAND_CLIENT_KEYEXCHANGE,\n\t\t\t\t\t\t\t\t\t &packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = createClientKeyex( sessionInfoPtr, handshakeInfo, stream,\n\t\t\t\t\t\t\t\t\tisKeyxAlgo( handshakeInfo->keyexAlgo ) ? \\\n\t\t\t\t\t\t\t\t\t\tkeyexPublicValue : NULL, \n\t\t\t\t\t\t\t\t\tkeyexPublicValueLen,\n\t\t\t\t\t\t\t\t\t( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \\\n\t\t\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createClientKeyex\" );\n\n\t/* Wrap up the packet and create the session hash if required */\n\tstatus = completePacketStreamSSL( stream, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = hashHSPacketWrite( handshakeInfo, stream, 0 );\n\tif( cryptStatusOK( status ) && \\\n\t\t( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS ) || \\\n\t\t  needClientCert ) )\n\t\t{\n\t\tstatus = createSessionHash( sessionInfoPtr, handshakeInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createSessionHash\" );\n\n\t/* If we need to supply a client certificate, send the signature \n\t   generated with the certificate to prove possession of the private \n\t   key */\n\tif( needClientCert )\n\t\t{\n\t\tint packetStreamOffset;\n\n\t\t/* Write the packet header and drop in the signature data.  Since \n\t\t   we've interrupted the packet stream to perform the hashing we \n\t\t   have to restart it at this point */\n\t\tstatus = continuePacketStreamSSL( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE, \n\t\t\t\t\t\t\t\t\t\t  &packetStreamOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = continueHSPacketStream( stream, SSL_HAND_CLIENT_CERTVERIFY,\n\t\t\t\t\t\t\t\t\t\t &packetOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = createCertVerify( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t   stream );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Wrap the packet and perform the assorted hashing for it */\n\t\tstatus = completePacketStreamSSL( stream, packetStreamOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = hashHSPacketWrite( handshakeInfo, stream, \n\t\t\t\t\t\t\t\t\t\tpacketStreamOffset );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tCFI_CHECK_UPDATE( \"createCertVerify\" );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"checkHSPacketHeader\", \"readSSLCertChain\", \n\t\t\t\t\t\t\t\t\t\t\"processServerKeyex\", \n\t\t\t\t\t\t\t\t\t\t\"processCertRequest\", \"writeSSLCertChain\",\n\t\t\t\t\t\t\t\t\t\t\"createClientKeyex\", \"createSessionHash\", \n\t\t\t\t\t\t\t\t\t\t\"createCertVerify\" ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tCFI_CHECK_UPDATE( \"needClientCert\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_8( \"checkHSPacketHeader\", \"readSSLCertChain\", \n\t\t\t\t\t\t\t\t\t\"processServerKeyex\", \"processCertRequest\", \n\t\t\t\t\t\t\t\t\t\"writeSSLCertChain\", \"createClientKeyex\", \n\t\t\t\t\t\t\t\t\t\"createSessionHash\", \"needClientCert\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSLclientProcessing( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tFNPTR_SET( handshakeInfo->beginHandshake, beginClientHandshake );\n\tFNPTR_SET( handshakeInfo->exchangeKeys, exchangeClientKeys );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_crypt.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TLS Crypto Routines\t\t\t\t\t\t*\n*\t\t\t\t\t Copyright Peter Gutmann 1998-2015\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write packet metadata for input to the MAC/ICV authentication process:\n\n\tseq_num || type || version || length */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nstatic int writePacketMetadata( OUT_BUFFER( dataMaxLength, *dataLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *data,\n\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 16 ) \\\n\t\t\t\t\t\t\t\t\tconst int dataMaxLength,\n\t\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *dataLength,\n\t\t\t\t\t\t\t\tIN_BYTE const int type,\n\t\t\t\t\t\t\t\tIN_INT_Z const long seqNo, \n\t\t\t\t\t\t\t\tIN_RANGE( SSL_MINOR_VERSION_TLS, \\\n\t\t\t\t\t\t\t\t\t\t  SSL_MINOR_VERSION_TLS12 ) \\\n\t\t\t\t\t\t\t\t\tconst int version,\n\t\t\t\t\t\t\t\tIN_LENGTH_Z const int payloadLength )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( type >= 0 && type <= 255 );\n\tREQUIRES( seqNo >= 0 );\n\tREQUIRES( version >= SSL_MINOR_VERSION_TLS && \\\n\t\t\t  version <= SSL_MINOR_VERSION_TLS12 );\n\tREQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE + 512 );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* Write the sequence number, packet type, version, and length \n\t  information to the output buffer */\n\tsMemOpen( &stream, data, dataMaxLength );\n\twriteUint64( &stream, seqNo );\n\tsputc( &stream, type );\n\tsputc( &stream, SSL_MAJOR_VERSION );\n\tsputc( &stream, version );\n\tstatus = writeUint16( &stream, payloadLength );\n\tif( cryptStatusOK( status ) )\n\t\t*dataLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tEncrypt/Decrypt Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Encrypt/decrypt a data block (in mose cases this also includes the MAC, \n   which has been added to the data by the caller).  The handling of length \n   arguments for these is a bit tricky, for encryption the input is { data, \n   payloadLength } which is padded (if necessary) and the padded length \n   returned in '*dataLength', for decryption the entire data block will be \n   processed but only 'processedDataLength' bytes of result are valid \n   output */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint encryptData( const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t INOUT_BUFFER( dataMaxLength, *dataLength ) \\\n\t\t\t\t\tBYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataMaxLength,\n\t\t\t\t OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t IN_DATALENGTH const int payloadLength )\n\t{\n\tint length = payloadLength, status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength > 0 && \\\n\t\t\t  payloadLength <= MAX_PACKET_SIZE + CRYPT_MAX_HASHSIZE && \\\n\t\t\t  payloadLength <= sessionInfoPtr->sendBufSize && \\\n\t\t\t  payloadLength <= dataMaxLength );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* If it's a block cipher then we add end-of-block and message padding.  \n\t   We can't pad GCM because the spec doesn't allow it.\n\t   \n\t   Note that the padding size can range from 0 to 255 bytes, with zero\n\t   bytes of padding being non-PKCS #5 conformant.  This is possible\n\t   because the padding doesn't also encode the length as it does in \n\t   PKCS #5, the padding length is an extra byte that's always present \n\t   but is also treated as the last byte of the padding.  To deal with \n\t   this special case we round up the payload size to ensure that \n\t   there's always at least one byte of padding present */\n\tif( sessionInfoPtr->cryptBlocksize > 1 )\n\t\t{\n#ifdef USE_SSL3\n\t\tconst int paddedSize = ( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL ) ? \\\n\t\t\t\t\t\t\t\t roundUp( payloadLength + 1, sessionInfoPtr->cryptBlocksize ) : \\\n\t\t\t\t\t\t\t\t getPaddedSize( payloadLength + 1 );\n#else\n\t\tconst int paddedSize = getPaddedSize( payloadLength + 1 );\n#endif /* USE_SSL3 */\n\t\tconst int padSize = paddedSize - payloadLength;\n\t\tint i, LOOP_ITERATOR;\n\n\t\tENSURES( paddedSize >= 16 && paddedSize <= MAX_BUFFER_SIZE ); \n\t\tENSURES( padSize > 0 && padSize <= 255 && \\\n\t\t\t\t length + padSize <= dataMaxLength );\n\n\t\t/* Add the PKCS #5-style padding (PKCS #5 uses n, TLS uses n-1) */\n\t\tLOOP_EXT( i = 0, i < padSize, i++, 257 )\n\t\t\tdata[ length++ ] = intToByte( padSize - 1 );\n\t\tENSURES( LOOP_BOUND_OK );\n\t\t}\n\n\t/* Encrypt the data and optional padding */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_ENCRYPT, data, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*dataLength = length;\n\n\t/* If we're using GCM then we have to append the ICV to the data */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tREQUIRES( length + sessionInfoPtr->authBlocksize <= dataMaxLength );\n\n\t\tsetMessageData( &msgData, data + length, \n\t\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_ICV );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t*dataLength += sessionInfoPtr->authBlocksize;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint decryptData( SESSION_INFO *sessionInfoPtr, \n\t\t\t\t INOUT_BUFFER_FIXED( dataLength ) \\\n\t\t\t\t\tBYTE *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t OUT_DATALENGTH_Z int *processedDataLength )\n\t{\n\tint length = dataLength, padSize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataLength ) );\n\tassert( isWritePtr( processedDataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( dataLength > 0 && \\\n\t\t\t  dataLength <= sessionInfoPtr->receiveBufEnd && \\\n\t\t\t  dataLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*processedDataLength = 0;\n\n\t/* Decrypt the data */\n\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t  IMESSAGE_CTX_DECRYPT, data, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Packet decryption failed\" ) );\n\t\t}\n\n\t/* If we're using GCM then we have to check the ICV that follows the \n\t   data */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\tsetMessageData( &msgData, data + length, \n\t\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t\t  MESSAGE_COMPARE_ICV );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Bad message ICV for packet type %d, length %d\",\n\t\t\t\t\t  data[ 0 ], length ) );\n\t\t\t}\n\t\t}\n\n\t/* If it's a stream cipher then there's no padding present */\n\tif( sessionInfoPtr->cryptBlocksize <= 1 )\n\t\t{\n\t\t*processedDataLength = length;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* If it's a block cipher, we need to remove end-of-block padding.  Up \n\t   until TLS 1.1 the spec was silent about any requirement to check the \n\t   padding (and for SSLv3 it didn't specify the padding format at all\n\t   apart from specifying that it had to be  less than the cipher block\n\t   size) so it's not really safe to reject an SSL message if we don't \n\t   find the correct padding because many SSL implementations didn't \n\t   process the padded data space in any way, leaving it containing \n\t   whatever was there before (which can include old plaintext (!!)).  \n\t   Almost all TLS implementations get it right (even though in TLS 1.0 \n\t   there was only a requirement to generate, but not to check, the PKCS \n\t   #5-style padding).  Because of this we only check the padding bytes \n\t   if we're talking TLS.\n\n\t   First we make sure that the padding information looks OK.  TLS allows \n\t   up to 256 bytes of padding (only GnuTLS actually seems to use this \n\t   capability though) so we can't check for a sensible (small) padding \n\t   length, however we can check this for SSL, which is good because for \n\t   that we can't check the padding itself.\n\n\t   There's no easy way to perform these checks in a timing-independent\n\t   manner because we're using them to reject completely malformed\n\t   packets (out-of-bounds array references), but hopefully the few \n\t   cycles difference won't be measurable in the overall scheme of \n\t   things */\n\tpadSize = byteToInt( data[ dataLength - 1 ] );\n\tif( padSize < 0 || padSize > 255 || \\\n\t\t( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL && \\\n\t\t  padSize > sessionInfoPtr->cryptBlocksize - 1 ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid encryption padding value 0x%02X (%d)\", \n\t\t\t\t  padSize, padSize ) );\n\t\t}\n\tlength -= padSize + 1;\n\tif( length < 0 || length > MAX_BUFFER_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Encryption padding adjustment value %d is greater \"\n\t\t\t\t  \"than packet length %d\", padSize, dataLength ) );\n\t\t}\n\n\t/* Check for PKCS #5-type padding (PKCS #5 uses n, TLS uses n-1) if \n\t   necessary, in a timing-independent manner */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS )\n\t\t{\n\t\tint value = 0, i, LOOP_ITERATOR;\n\n\t\tLOOP_EXT( i = 0, i < padSize, i++, 257 )\n\t\t\tvalue |= data[ length + i ] ^ padSize;\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tif( value != 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid encryption padding byte, expected 0x%02X\",\n\t\t\t\t\t  padSize ) );\n\t\t\t}\n\t\t}\n\t*processedDataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSL MAC Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_SSL3\n\n/* Proto-HMAC padding data */\n\n#define PROTOHMAC_PAD1_VALUE\t0x36\n#define PROTOHMAC_PAD2_VALUE\t0x5C\n#define PROTOHMAC_PAD1\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\" \\\n\t\t\t\t\t\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\" \\\n\t\t\t\t\t\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\" \\\n\t\t\t\t\t\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\" \\\n\t\t\t\t\t\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\" \\\n\t\t\t\t\t\t\t\t\"\\x36\\x36\\x36\\x36\\x36\\x36\\x36\\x36\"\n#define PROTOHMAC_PAD2\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\" \\\n\t\t\t\t\t\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\" \\\n\t\t\t\t\t\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\" \\\n\t\t\t\t\t\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\" \\\n\t\t\t\t\t\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\" \\\n\t\t\t\t\t\t\t\t\"\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\\x5C\"\n\n/* Perform an SSL MAC of a data block.  We have to provide special-case \n   handling of zero-length blocks since some versions of OpenSSL send these \n   as a kludge in SSL/TLS 1.0 to work around chosen-IV attacks.\n\n   In the following functions we don't check the return value of every \n   single component MAC operation since it would lead to endless sequences\n   of 'status = x; if( cSOK( x ) ) ...' chains, on the remote chance that\n   there's some transient failure in a single component operation it'll be\n   picked up at the end anyway when the overall MAC check fails */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \\\nstatic int macDataSSL( IN_HANDLE const CRYPT_CONTEXT iHashContext, \n\t\t\t\t\t   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t   IN_BUFFER( macSecretLength ) \\\n\t\t\t\t\t\t\tconst void *macSecret, \n\t\t\t\t\t   IN_LENGTH_SHORT const int macSecretLength,\n\t\t\t\t\t   IN_INT_Z const long seqNo, \n\t\t\t\t\t   IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t   IN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\t   IN_BYTE const int type )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE buffer[ 128 + 8 ];\n\tconst int padSize = ( hashAlgo == CRYPT_ALGO_MD5 ) ? 48 : 40;\n\tint length DUMMY_INIT, status;\n\n\tassert( isReadPtrDynamic( macSecret, macSecretLength ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( hashAlgo == CRYPT_ALGO_MD5 || \\\n\t\t\t  hashAlgo == CRYPT_ALGO_SHA1 );\n\tREQUIRES( isShortIntegerRangeNZ( macSecretLength ) );\n\tREQUIRES( seqNo >= 0 );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataLength > 0 && dataLength <= MAX_PACKET_SIZE + 512 ) );\n\tREQUIRES( type >= 0 && type <= 255 );\n\n\t/* Set up the sequence number and length data */\n\tmemset( buffer, PROTOHMAC_PAD1_VALUE, padSize );\n\tsMemOpen( &stream, buffer + padSize, 128 - padSize );\n\twriteUint64( &stream, seqNo );\n\tsputc( &stream, type );\n\tstatus = writeUint16( &stream, dataLength );\n\tif( cryptStatusOK( status ) )\n\t\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Reset the hash context and generate the inner portion of the MAC:\n\n\t\thash( MAC_secret || pad1 || seq_num || type || length || data ) */\n\tkrnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) macSecret, macSecretLength );\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,\n\t\t\t\t\t padSize + length );\n\tif( dataLength > 0 )\n\t\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t ( MESSAGE_CAST ) data, dataLength );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Extract the inner hash value */\n\tmemset( buffer, PROTOHMAC_PAD2_VALUE, padSize );\n\tsetMessageData( &msgData, buffer + padSize, CRYPT_MAX_HASHSIZE );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the outer portion of the handshake message's MAC:\n\n\t\thash( MAC_secret || pad2 || inner_hash ) */\n\tkrnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) macSecret, macSecretLength );\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,\n\t\t\t\t\t padSize + msgData.length );\n\treturn( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint createMacSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t  IN_DATALENGTH const int payloadLength, \n\t\t\t\t  IN_BYTE const int type )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE + 512 && \\\n\t\t\t  payloadLength + sessionInfoPtr->authBlocksize <= dataMaxLength );\n\tREQUIRES( type >= 0 && type <= 255 );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* MAC the payload */\n\tstatus = macDataSSL( sessionInfoPtr->iAuthOutContext, \n\t\t\t\t\t\t sessionInfoPtr->integrityAlgo,\n\t\t\t\t\t\t sslInfo->macWriteSecret, \n\t\t\t\t\t\t sessionInfoPtr->authBlocksize, sslInfo->writeSeqNo,\n\t\t\t\t\t\t data, payloadLength, type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->writeSeqNo++;\n\n\t/* Append the MAC value to the end of the packet */\n\tENSURES( boundsCheck( payloadLength, sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t  dataMaxLength ) );\n\tsetMessageData( &msgData, ( BYTE * ) data + payloadLength,\n\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iAuthOutContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*dataLength = payloadLength + msgData.length;\n\tINJECT_FAULT( SESSION_CORRUPT_MAC, SESSION_CORRUPT_MAC_SSL_1 );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkMacSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t IN_DATALENGTH_Z const int payloadLength,\n\t\t\t\t IN_BYTE const int type, \n\t\t\t\t const BOOLEAN noReportError )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE + 512 && \\\n\t\t\t  payloadLength + sessionInfoPtr->authBlocksize <= dataLength );\n\tREQUIRES( type >= 0 && type <= 255 );\n\tREQUIRES( noReportError == TRUE || noReportError == FALSE );\n\n\t/* MAC the payload.  If the payload length is zero then there's no data \n\t   payload, this can happen with some versions of OpenSSL that send \n\t   zero-length blocks as a kludge to work around pre-TLS 1.1 chosen-IV\n\t   attacks */\n\tif( payloadLength <= 0 )\n\t\t{\n\t\tstatus = macDataSSL( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t sessionInfoPtr->integrityAlgo,\n\t\t\t\t\t\t\t sslInfo->macReadSecret, \n\t\t\t\t\t\t\t sessionInfoPtr->authBlocksize, \n\t\t\t\t\t\t\t sslInfo->readSeqNo, NULL, 0, type );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = macDataSSL( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t sessionInfoPtr->integrityAlgo,\n\t\t\t\t\t\t\t sslInfo->macReadSecret, \n\t\t\t\t\t\t\t sessionInfoPtr->authBlocksize, \n\t\t\t\t\t\t\t sslInfo->readSeqNo, data, payloadLength, type );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->readSeqNo++;\n\n\t/* Compare the calculated MAC to the MAC present at the end of the \n\t   data */\n\tENSURES( boundsCheckZ( payloadLength, sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t   dataLength ) );\n\tsetMessageData( &msgData, ( BYTE * ) data + payloadLength,\n\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t  MESSAGE_COMPARE_HASH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the error message has already been set at a higher level, \n\t\t   don't update the error information */\n\t\tif( noReportError )\n\t\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Bad message MAC for packet type %d, length %d\",\n\t\t\t\t  type, dataLength ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL3 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTLS MAC Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform a TLS MAC of a data block.  We have to provide special-case \n   handling of zero-length blocks since some versions of OpenSSL send these \n   as a kludge in SSL/TLS 1.0 to work around chosen-IV attacks.\n\n   In the following functions we don't check the return value of every \n   single component MAC operation since it would lead to endless sequences\n   of 'status = x; if( cSOK( x ) ) ...' chains, on the remote chance that\n   there's some transient failure in a single component operation it'll be\n   picked up at the end anyway when the overall MAC check fails */\n\nCHECK_RETVAL \\\nstatic int macDataTLS( IN_HANDLE const CRYPT_CONTEXT iHashContext, \n\t\t\t\t\t   IN_INT_Z const long seqNo, \n\t\t\t\t\t   IN_RANGE( SSL_MINOR_VERSION_TLS, \\\n\t\t\t\t\t\t\t\t SSL_MINOR_VERSION_TLS12 ) const int version,\n\t\t\t\t\t   IN_BUFFER_OPT( ivLength ) const void *iv, \n\t\t\t\t\t   IN_LENGTH_IV_Z const int ivLength, \n\t\t\t\t\t   IN_BUFFER_OPT( dataLength ) const void *data, \n\t\t\t\t\t   IN_DATALENGTH_Z const int dataLength, \n\t\t\t\t\t   IN_BYTE const int type )\n\t{\n\tBYTE buffer[ 64 + CRYPT_MAX_IVSIZE + 8 ];\n\tint length, status;\n\n\tassert( ( iv == NULL && ivLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( iv, ivLength ) );\n\tassert( ( data == NULL && dataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( seqNo >= 0 );\n\tREQUIRES( version >= SSL_MINOR_VERSION_TLS && \\\n\t\t\t  version <= SSL_MINOR_VERSION_TLS12 );\n\tREQUIRES( ( iv == NULL && ivLength == 0 ) || \\\n\t\t\t  ( iv != NULL && \\\n\t\t\t\tivLength > 0 && ivLength <= CRYPT_MAX_IVSIZE ) );\n\tREQUIRES( ( data == NULL && dataLength == 0 ) || \\\n\t\t\t  ( data != NULL && \\\n\t\t\t\tdataLength > 0 && dataLength <= MAX_PACKET_SIZE + 512 ) );\n\tREQUIRES( type >= 0 && type <= 255 );\n\n\t/* Set up the packet metadata to be MACed */\n\tstatus = writePacketMetadata( buffer, 64, &length, type, seqNo, version,\n\t\t\t\t\t\t\t\t  dataLength + ivLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ivLength > 0 )\n\t\t{\n\t\t/* If we're using an explicit IV, append it to the metadata for\n\t\t   MAC'ing */\n\t\tREQUIRES( boundsCheck( length, ivLength, 64 + CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( buffer + length, iv, ivLength );\n\t\tlength += ivLength;\n\t\t}\n\n\t/* Reset the hash context and generate the MAC:\n\n\t\tHMAC( metadata || (IV) || data ) */\n\tkrnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, length );\n\tif( dataLength > 0 )\n\t\t{\n\t\tkrnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t ( MESSAGE_CAST ) data, dataLength );\n\t\t}\n\treturn( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint createMacTLS( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t  IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t  OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t  IN_DATALENGTH const int payloadLength, \n\t\t\t\t  IN_BYTE const int type )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE + 512 && \\\n\t\t\t  payloadLength + sessionInfoPtr->authBlocksize <= dataMaxLength );\n\tREQUIRES( type >= 0 && type <= 255 );\n\n\t/* Clear return values */\n\t*dataLength = 0;\n\n\t/* MAC the payload.  When wrapping a packet the IV is treaded as part of\n\t   the payload so it's always passed in as { NULL, 0 }, it's only when\n\t   unwrapping that it's stripped before the payload data is copied into\n\t   the session buffer and so needs to be passed in explicitly */\n\tstatus = macDataTLS( sessionInfoPtr->iAuthOutContext, sslInfo->writeSeqNo,\n\t\t\t\t\t\t sessionInfoPtr->version, NULL, 0, data, \n\t\t\t\t\t\t payloadLength, type );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->writeSeqNo++;\n\n\t/* Append the MAC value to the end of the packet */\n\tENSURES( boundsCheck( payloadLength, sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t  dataMaxLength ) );\n\tsetMessageData( &msgData, ( BYTE * ) data + payloadLength,\n\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iAuthOutContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*dataLength = payloadLength + msgData.length;\n\tINJECT_FAULT( SESSION_CORRUPT_MAC, SESSION_CORRUPT_MAC_SSL_1 );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint checkMacTLS( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t IN_DATALENGTH const int dataLength, \n\t\t\t\t IN_DATALENGTH_Z const int payloadLength, \n\t\t\t\t IN_BYTE const int type, \n\t\t\t\t const BOOLEAN noReportError )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tconst void *ivPtr = NULL;\n\tint ivLength = 0, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\tREQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE + 512 && \\\n\t\t\t  payloadLength + sessionInfoPtr->authBlocksize <= dataLength );\n\tREQUIRES( type >= 0 && type <= 255 );\n\tREQUIRES( noReportError == TRUE || noReportError == FALSE );\n\n\t/* MAC the payload.  If the payload length is zero then there's no data \n\t   payload, this can happen with some versions of OpenSSL that send \n\t   zero-length blocks as a kludge to work around pre-TLS 1.1 chosen-IV\n\t   attacks */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC ) && \\\n\t\tsslInfo->ivSize > 0 )\n\t\t{\n\t\t/* When using encrypt-then-MAC and TLS 1.1+ explicit IVs, the IV is\n\t\t   authenticated alongside the encrypted payload data */\n\t\tivPtr = sslInfo->iv;\n\t\tivLength = sslInfo->ivSize;\n\t\t}\n\tif( payloadLength <= 0 )\n\t\t{\n\t\tstatus = macDataTLS( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t sslInfo->readSeqNo, sessionInfoPtr->version, \n\t\t\t\t\t\t\t ivPtr, ivLength, NULL, 0, type );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = macDataTLS( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t sslInfo->readSeqNo, sessionInfoPtr->version, \n\t\t\t\t\t\t\t ivPtr, ivLength, data, payloadLength, type );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->readSeqNo++;\n\n\t/* Compare the calculated MAC to the MAC present at the end of the \n\t   data */\n\tENSURES( boundsCheckZ( payloadLength, sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t   dataLength ) );\n\tsetMessageData( &msgData, ( BYTE * ) data + payloadLength,\n\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\tstatus = krnlSendMessage( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t  IMESSAGE_COMPARE, &msgData, \n\t\t\t\t\t\t\t  MESSAGE_COMPARE_HASH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the error message has already been set at a higher level, \n\t\t   don't update the error information */\n\t\tif( noReportError )\n\t\t\treturn( CRYPT_ERROR_SIGNATURE );\n\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Bad message MAC for packet type %d, length %d\",\n\t\t\t\t  type, dataLength ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTLS GCM Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_GCM\n\n/* Perform a TLS GCM integrity check of a data block.  This differs somewhat\n   from the more conventional MACing routines because GCM combines the ICV\n   generation with encryption, so all that we're actually doing is \n   generating the initial stage of the ICV over the packet metadata handled\n   as GCM AAD */\n\nCHECK_RETVAL \\\nint macDataTLSGCM( IN_HANDLE const CRYPT_CONTEXT iCryptContext, \n\t\t\t\t   IN_INT_Z const long seqNo, \n\t\t\t\t   IN_RANGE( SSL_MINOR_VERSION_TLS, \\\n\t\t\t\t\t\t\t SSL_MINOR_VERSION_TLS12 ) const int version,\n\t\t\t\t   IN_LENGTH_Z const int payloadLength, \n\t\t\t\t   IN_BYTE const int type )\n\t{\n\tMESSAGE_DATA msgData;\n\tBYTE buffer[ 64 + 8 ];\n\tint length, status;\n\n\tREQUIRES( isHandleRangeValid( iCryptContext ) );\n\tREQUIRES( seqNo >= 0 );\n\tREQUIRES( version >= SSL_MINOR_VERSION_TLS && \\\n\t\t\t  version <= SSL_MINOR_VERSION_TLS12 );\n\tREQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE );\n\tREQUIRES( type >= 0 && type <= 255 );\n\n\t/* Set up the packet metadata to be MACed */\n\tstatus = writePacketMetadata( buffer, 64, &length, type, seqNo, \n\t\t\t\t\t\t\t\t  version, payloadLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Send the AAD to the GCM context for inclusion in the ICV \n\t   calculation */\n\tsetMessageData( &msgData, buffer, length );\n\treturn( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_AAD ) );\n\t}\n#endif /* USE_GCM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tHandshake Message Hash/MAC Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform assorted hashing of a data block, a dual dual MD5+SHA-1 hash for \n   SSL or straight SHA-2 hash for TLS 1.2+.  Since this is part of an \n   ongoing message exchange (in other words a failure potentially won't be \n   detected for some time) we check each return value.  This processing was \n   originally done using a dual MD5+SHA-1 hash, however TLS 1.2+ switched to \n   using a single SHA-2 hash, because of this we have to explicitly check \n   which hashing option we're using (in some cases it might be both since we \n   have to speculatively hash initial messages until we've agreed on a \n   version) and only use that hash.\n   \n   In addition to the overall hashing we may also be running a separate hash \n   of the messages that stops before the other hashing does if certificate-\n   based client authentication is being used.  This would add even more \n   overhead to the whole process, however since it's only used with TLS 1.2+\n   and in that case is restricted to using SHA-2 via hashing preferences\n   sent in the hello messages, we can obtain the necessary hash value by\n   cloning the SHA-2 context when we have to generate or verify the client\n   signature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int hashHSData( const SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t   IN_DATALENGTH const int dataLength )\n\t{\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\n\tif( handshakeInfo->md5context != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( handshakeInfo->md5context,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data,\n\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = krnlSendMessage( handshakeInfo->sha1context,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data,\n\t\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( handshakeInfo->sha2context != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( handshakeInfo->sha2context,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data,\n\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#ifdef CONFIG_SUITEB\n\tif( handshakeInfo->sha384context != CRYPT_ERROR )\n\t\t{\n\t\tstatus = krnlSendMessage( handshakeInfo->sha384context,\n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, ( MESSAGE_CAST ) data,\n\t\t\t\t\t\t\t\t  dataLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* CONFIG_SUITEB */\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashHSPacketRead( const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tconst int dataLength = sMemDataLeft( stream );\n\tvoid *data;\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\n\t/* On a read we've just processed the packet header and everything \n\t   that's left in the stream is the data to be MACd.  Note that we can't \n\t   use sMemGetDataBlockRemaining() for this because that returns the\n\t   entire available buffer, not just the amount of data in the buffer */\n\tstatus = sMemGetDataBlock( stream, &data, dataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tANALYSER_HINT( data != NULL );\n\t\tstatus = hashHSData( handshakeInfo, data, dataLength );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint hashHSPacketWrite( const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t   INOUT STREAM *stream,\n\t\t\t\t\t   IN_DATALENGTH_Z const int offset )\n\t{\n\tconst int dataStart = offset + SSL_HEADER_SIZE;\n\tconst int dataLength = stell( stream ) - dataStart;\n\tvoid *data;\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( offset >= 0 && offset < MAX_BUFFER_SIZE );\n\tREQUIRES( dataLength > 0 && dataLength < MAX_BUFFER_SIZE );\n\n\t/* On a write we've just finished writing the packet and everything but\n\t   the header needs to be MACd */\n\tstatus = sMemGetDataBlockAbs( stream, dataStart, &data, dataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tANALYSER_HINT( data != NULL );\n\t\tstatus = hashHSData( handshakeInfo, data, dataLength );\n\t\t}\n\treturn( status );\n\t}\n\n/* Complete the dual MD5/SHA1 hash/MAC or SHA2 MAC that's used in the \n   finished message.  There are no less than three variations of this, one\n   for SSL's dual MAC, one for TLS 1.0 - 1.1's IPsec cargo cult 96-bit\n   PRF'd dual MAC, and one for TLS 1.2's similarly cargo-cult 96-bit PRF'd\n   single MAC (unless we're using TLS 1.2 LTS).\n   \n   We don't check the return value of every single component MAC operation \n   since it would lead to endless sequences of 'status = x; \n   if( cSOK( x ) ) ...' chains, on the remote chance that there's some \n   transient failure in a single component operation it'll be picked up at \n   the end anyway when the overall MAC check fails */\n\n#ifdef USE_SSL3\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \\\nint completeSSLDualMAC( IN_HANDLE const CRYPT_CONTEXT md5context,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT sha1context, \n\t\t\t\t\t\tOUT_BUFFER( hashValuesMaxLen, *hashValuesLen )\n\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( MD5MAC_SIZE + SHA1MAC_SIZE ) \\\n\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\tIN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\tIN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\tIN_BUFFER( masterSecretLen ) const BYTE *masterSecret, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int masterSecretLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtrDynamic( hashValues, hashValuesMaxLen ) );\n\tassert( isWritePtr( hashValuesLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( label, labelLength ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLen ) );\n\n\tREQUIRES( isHandleRangeValid( md5context ) );\n\tREQUIRES( isHandleRangeValid( sha1context ) );\n\tREQUIRES( hashValuesMaxLen >= MD5MAC_SIZE + SHA1MAC_SIZE && \\\n\t\t\t  hashValuesMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( labelLength > 0 && labelLength <= 64 );\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretLen ) );\n\n\t/* Clear return value */\n\t*hashValuesLen = 0;\n\n\t/* Generate the inner portion of the handshake message's MAC:\n\n\t\thash( handshake_messages || cl/svr_label || master_secret || pad1 )\n\n\t   Note that the SHA-1 pad size is 40 bytes and not 44 (to get a total\n\t   length of 64 bytes), this is due to an error in the spec */\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) label, labelLength );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) label, labelLength );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) masterSecret, masterSecretLen );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) masterSecret, masterSecretLen );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 48 );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 40 );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tsetMessageData( &msgData, hashValues, MD5MAC_SIZE );\n\tstatus = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );\n\t\tstatus = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Reset the hash contexts */\n\tkrnlSendMessage( md5context, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\tkrnlSendMessage( sha1context, IMESSAGE_DELETEATTRIBUTE, NULL,\n\t\t\t\t\t CRYPT_CTXINFO_HASHVALUE );\n\n\t/* Generate the outer portion of the handshake message's MAC:\n\n\t\thash( master_secret || pad2 || inner_hash ) */\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) masterSecret, masterSecretLen );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t ( MESSAGE_CAST ) masterSecret, masterSecretLen );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 48 );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 40 );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, hashValues,\n\t\t\t\t\t MD5MAC_SIZE );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, hashValues + MD5MAC_SIZE,\n\t\t\t\t\t SHA1MAC_SIZE );\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tsetMessageData( &msgData, hashValues, MD5MAC_SIZE );\n\tstatus = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );\n\tstatus = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusOK( status ) )\n\t\t*hashValuesLen = MD5MAC_SIZE + SHA1MAC_SIZE;\n\treturn( status );\n\t}\n#endif /* USE_SSL3 */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \\\nint completeTLSHashedMAC( IN_HANDLE const CRYPT_CONTEXT md5context,\n\t\t\t\t\t\t  IN_HANDLE const CRYPT_CONTEXT sha1context, \n\t\t\t\t\t\t  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen )\n\t\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\t  IN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \\\n\t\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\t  IN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t  IN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\t  IN_BUFFER( masterSecretLen ) \\\n\t\t\t\t\t\t\t\tconst BYTE *masterSecret, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int masterSecretLen )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE hashBuffer[ 64 + ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];\n\tint status;\n\n\tassert( isWritePtrDynamic( hashValues, hashValuesMaxLen ) );\n\tassert( isWritePtr( hashValuesLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( label, labelLength ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLen ) );\n\n\tREQUIRES( isHandleRangeValid( md5context ) );\n\tREQUIRES( isHandleRangeValid( sha1context ) );\n\tREQUIRES( hashValuesMaxLen >= TLS_HASHEDMAC_SIZE && \\\n\t\t\t  hashValuesMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( labelLength > 0 && labelLength <= 64 && \\\n\t\t\t  labelLength + MD5MAC_SIZE + SHA1MAC_SIZE <= \\\n\t\t\t\t\t\t64 + ( CRYPT_MAX_HASHSIZE * 2 ) );\n\n\t/* Clear return value */\n\t*hashValuesLen = 0;\n\n\tREQUIRES( rangeCheck( labelLength, 1, \n\t\t\t  64 + ( CRYPT_MAX_HASHSIZE * 2 ) ) );\n\tmemcpy( hashBuffer, label, labelLength );\n\n\t/* Complete the hashing and get the MD5 and SHA-1 hashes */\n\tkrnlSendMessage( md5context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tkrnlSendMessage( sha1context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tsetMessageData( &msgData, hashBuffer + labelLength, MD5MAC_SIZE );\n\tstatus = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, hashBuffer + labelLength + MD5MAC_SIZE,\n\t\t\t\t\t\tSHA1MAC_SIZE );\n\t\tstatus = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the TLS check value.  This isn't really a hash or a MAC but\n\t   is generated by feeding the MD5 and SHA1 hashes of the handshake \n\t   messages into the TLS key derivation (PRF) function and truncating \n\t   the result to 12 bytes (96 bits) IPsec cargo cult protocol design\n\t   purposes:\n\n\t\tTLS_PRF( label || MD5_hash || SHA1_hash ) */\n\tsetMechanismDeriveInfo( &mechanismInfo, hashValues, \n\t\t\t\t\t\t\tTLS_HASHEDMAC_SIZE, ( MESSAGE_CAST ) masterSecret, \n\t\t\t\t\t\t\tmasterSecretLen, \n\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, hashBuffer, \n\t\t\t\t\t\t\tlabelLength + MD5MAC_SIZE + SHA1MAC_SIZE, 1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_TLS );\n\tif( cryptStatusOK( status ) )\n\t\t*hashValuesLen = TLS_HASHEDMAC_SIZE;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5, 7 ) ) \\\nint completeTLS12HashedMAC( IN_HANDLE const CRYPT_CONTEXT sha2context,\n\t\t\t\t\t\t\tOUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \\\n\t\t\t\t\t\t\t\tBYTE *hashValues, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( TLS_HASHEDMAC_SIZE ) \\\n\t\t\t\t\t\t\t\tconst int hashValuesMaxLen,\n\t\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( hashValuesMaxLen ) \\\n\t\t\t\t\t\t\t\tint *hashValuesLen,\n\t\t\t\t\t\t\tIN_BUFFER( labelLength ) const char *label, \n\t\t\t\t\t\t\tIN_RANGE( 1, 64 ) const int labelLength, \n\t\t\t\t\t\t\tIN_BUFFER( masterSecretLen ) \\\n\t\t\t\t\t\t\t\tconst BYTE *masterSecret, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int masterSecretLen,\n\t\t\t\t\t\t\tconst BOOLEAN fullSizeMAC )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tBYTE hashBuffer[ 64 + ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];\n\tconst int hashedMacSize = ( fullSizeMAC ) ? 32 : TLS_HASHEDMAC_SIZE;\n\tint macSize, status;\n\n\tassert( isWritePtrDynamic( hashValues, hashValuesMaxLen ) );\n\tassert( isWritePtr( hashValuesLen, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( label, labelLength ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLen ) );\n\n\tREQUIRES( isHandleRangeValid( sha2context ) );\n\tREQUIRES( hashValuesMaxLen >= 32 && \\\n\t\t\t  hashValuesMaxLen < MAX_INTLENGTH_SHORT );\n\tREQUIRES( labelLength > 0 && labelLength <= 64 && \\\n\t\t\t  labelLength + CRYPT_MAX_HASHSIZE <= 64 + ( CRYPT_MAX_HASHSIZE ) );\n\tREQUIRES( fullSizeMAC == TRUE || fullSizeMAC == FALSE );\n\n\t/* Clear return value */\n\t*hashValuesLen = 0;\n\n\tREQUIRES( rangeCheck( labelLength, 1, \n\t\t\t  64 + ( CRYPT_MAX_HASHSIZE * 2 ) ) );\n\tmemcpy( hashBuffer, label, labelLength );\n\n\t/* Get the MAC size */\n\tstatus = krnlSendMessage( sha2context, IMESSAGE_GETATTRIBUTE, &macSize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Complete the hashing and get the SHA-2 hash */\n\tkrnlSendMessage( sha2context, IMESSAGE_CTX_HASH, \"\", 0 );\n\tsetMessageData( &msgData, hashBuffer + labelLength, macSize );\n\tstatus = krnlSendMessage( sha2context, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Generate the TLS check value.  This isn't really a hash or a MAC but\n\t   is generated by feeding the SHA-2 hash of the handshake messages into \n\t   the TLS key derivation (PRF) function and truncating the result to 12 \n\t   bytes (96 bits) for IPsec cargo cult protocol design purposes, unless\n\t   we're using TLS-LTS in which case we use the full-size result:\n\n\t\tTLS_PRF( label || SHA2_hash ) */\n\tsetMechanismDeriveInfo( &mechanismInfo, hashValues, hashedMacSize, \n\t\t\t\t\t\t\t( MESSAGE_CAST ) masterSecret, masterSecretLen, \n\t\t\t\t\t\t\tCRYPT_ALGO_SHA2, hashBuffer, \n\t\t\t\t\t\t\tlabelLength + macSize, 1 );\n\tif( macSize != bitsToBytes( 256 ) )\n\t\tmechanismInfo.hashParam = macSize;\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_DERIVE_TLS12 );\n\tif( cryptStatusOK( status ) )\n\t\t*hashValuesLen = hashedMacSize;\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tClient-Auth Signature Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create/check the signature on an SSL certificate verify message.  \n   SSLv3/TLS use a weird signature format that dual-MACs (SSLv3) or hashes \n   (TLS) all of the handshake messages exchanged to date (SSLv3 additionally \n   hashes in further data like the master secret), then signs them using \n   nonstandard PKCS #1 RSA without the ASN.1 wrapper (that is, it uses the \n   raw concatenated SHA-1 and MD5 MAC (SSL) or hash (TLS) of the handshake \n   messages with PKCS #1 padding prepended), unless we're using DSA in which \n   case it drops the MD5 MAC/hash and uses only the SHA-1 one.  \n   \n   This is an incredible pain to support because it requires running a \n   parallel hash of handshake messages that terminates before the main \n   hashing does, further hashing/MAC'ing of additional data, and the use of \n   weird nonstandard data formats and signature mechanisms that aren't \n   normally supported by anything.  For example if the signing is to be done \n   via a smart card then we can't use the standard PKCS #1 sig mechanism, we \n   can't even use raw RSA and kludge the format together ourselves because \n   some PKCS #11 implementations don't support the _X509 (raw) mechanism, \n   what we have to do is tunnel the nonstandard sig.format information down \n   through several cryptlib layers and then hope that the PKCS #11 \n   implementation that we're using (a) supports this format and (b) gets it \n   right.\n   \n   Another problem (which only occurs for SSLv3) is that the MAC requires \n   the use of the master secret, which isn't available for several hundred \n   more lines of code, so we have to delay producing any more data packets \n   until the master secret is available (either that or squirrel all packets\n   away in some buffer somewhere so that they can be hashed later), which \n   severely screws up the handshake processing flow.  TLS is slightly better \n   here since it simply signs MD5-hash || SHA1-hash without requiring the\n   use of the master secret, but even then it requires speculatively running \n   an MD5 and SHA-1 hash of all messages on every exchange on the remote \n   chance that the client will be using client certificates.  TLS 1.2\n   finally moved to using standard signatures (PKCS #1 for RSA, conventional\n   signatures for DSA/ECDSA), but still requires the speculative hashing of\n   handshake messages.\n\n   The chances of all of this custom data and signature handling working \n   correctly are fairly low, and in any case there's no advantage to the \n   weird mechanism and format used in SSL/TLS, all that we actually need to \n   do is sign the client and server nonces to ensure signature freshness.  \n   Because of this what we actually do is just this, after which we create a \n   standard PKCS #1 signature via the normal cryptlib mechanisms, which \n   guarantees that it'll work with native cryptlib as well as any crypto \n   hardware implementation.  Since client certificates are hardly ever used \n   and when they are it's in a closed environment, it's extremely unlikely \n   that anyone will ever notice.  There'll be far more problems in trying to \n   use the nonstandard SSL/TLS signature mechanism than there are with using \n   a standard (but not-in-the-spec) one.\n   \n   The one exception to this is, as already mentioned above, TLS 1.2+, for\n   which we can finally use a standard signature.  In this case we take\n   a clone of the SHA-2 context that's been used to hash the handshake\n   messages so far (the use of SHA-2 for this is enforced by the judicious\n   use of TLS extensions, see the comments in ssl_ext.c for more on this)\n   and sign that */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int createCertVerifyAltHash( const SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *iHashContext )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tBYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( iHashContext, sizeof( CRYPT_CONTEXT ) ) );\n\n\t/* Clear return value */\n\t*iHashContext = CRYPT_ERROR;\n\n\t/* Hash the client and server nonces */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmemcpy( nonceBuffer, \"certificate verify\", 18 );\n\tmemcpy( nonceBuffer + 18, handshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\tmemcpy( nonceBuffer + 18 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,\n\t\t\tSSL_NONCE_SIZE );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t  nonceBuffer, \n\t\t\t\t\t\t\t  18 + SSL_NONCE_SIZE + SSL_NONCE_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_CTX_HASH, nonceBuffer, 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*iHashContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4 ) ) \\\nstatic int getSessionHash( IN_HANDLE const CRYPT_CONTEXT iHashContext,\n\t\t\t\t\t\t   OUT_BUFFER( hashValueMaxLen, *hashValueLen ) \\\n\t\t\t\t\t\t\t\tvoid *hashValue,\n\t\t\t\t\t\t   IN_LENGTH_HASH const int hashValueMaxLen,\n\t\t\t\t\t\t   OUT_LENGTH_HASH_Z int *hashValueLen )\n\t{\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtrDynamic( hashValue, hashValueMaxLen ) );\n\tassert( isWritePtr( hashValueLen, sizeof( int ) ) );\n\n\tREQUIRES( isHandleRangeValid( iHashContext ) );\n\tREQUIRES( hashValueMaxLen >= MIN_HASHSIZE && \\\n\t\t\t  hashValueMaxLen <= CRYPT_MAX_HASHSIZE );\n\n\t/* Clear return values */\n\tmemset( hashValue, 0, min( 16, hashValueMaxLen ) );\n\t*hashValueLen = 0;\n\n\t/* Wrap up the hashing and record the hash value */\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, hashValue, hashValueMaxLen );\n\tstatus = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*hashValueLen = msgData.length;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint createSessionHash( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Clone the current hash state, complete the hashing for the cloned \n\t   context(s), and get the hash value(s) */\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tint hash1Size, hash2Size;\n\n\t\t/* TLS < 1.2 uses an MD5/SHA1 dual hash so we have to extract both \n\t\t   hash values and concatenate them */\n\t\tstatus = cloneHashContext( handshakeInfo->md5context, &iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = getSessionHash( iHashContext, handshakeInfo->sessionHash,\n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, &hash1Size );\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = cloneHashContext( handshakeInfo->sha1context, &iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = getSessionHash( iHashContext, \n\t\t\t\t\t\t\t\t handshakeInfo->sessionHash + hash1Size,\n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE - hash1Size, &hash2Size );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\thandshakeInfo->sessionHashSize = hash1Size + hash2Size;\n\t\t}\n\telse\n\t\t{\n\t\t/* TLS 1.2 uses a single hash value */\n\t\tif( handshakeInfo->sha2context != CRYPT_ERROR )\n\t\t\tstatus = cloneHashContext( handshakeInfo->sha2context, &iHashContext );\n\t\telse\n\t\t\tstatus = cloneHashContext( handshakeInfo->sha1context, &iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = getSessionHash( iHashContext, handshakeInfo->sessionHash,\n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t &handshakeInfo->sessionHashSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\thandshakeInfo->sessionHashContext = iHashContext;\n\n\tDEBUG_PUTS(( \"Session hash:\" ));\n\tDEBUG_DUMP_DATA( handshakeInfo->sessionHash, \n\t\t\t\t\t handshakeInfo->sessionHashSize );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint createCertVerify( const SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tvoid *dataPtr;\n\tint dataLength, length DUMMY_INIT, status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Get a pointer to the signature data block */\n\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the signature.  The reason for the min() part of the\n\t   expression is that iCryptCreateSignature() gets suspicious of very\n\t   large buffer sizes, for example when the user has specified the use\n\t   of a huge send buffer */\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tCRYPT_CONTEXT iHashContext;\n\n\t\t/* Create the hash of the data to sign if necessary */\n\t\tstatus = createCertVerifyAltHash( handshakeInfo, &iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* See the note above about the complexities of handling the ever-\n\t\t   changing pre-TLS 1.2 signature format */\n\t\tstatus = iCryptCreateSignature( dataPtr, \n\t\t\t\t\t\tmin( dataLength, MAX_INTLENGTH_SHORT - 1 ), &length, \n\t\t\t\t\t\tCRYPT_FORMAT_CRYPTLIB, sessionInfoPtr->privateKey, \n\t\t\t\t\t\tiHashContext, NULL );\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = iCryptCreateSignature( dataPtr, \n\t\t\t\t\t\tmin( dataLength, MAX_INTLENGTH_SHORT - 1 ), &length, \n\t\t\t\t\t\tCRYPT_IFORMAT_TLS12, sessionInfoPtr->privateKey, \n\t\t\t\t\t\thandshakeInfo->sessionHashContext, NULL );\n\t\tkrnlSendNotifier( handshakeInfo->sessionHashContext, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sessionHashContext = CRYPT_ERROR;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sSkip( stream, length, MAX_INTLENGTH_SHORT );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkCertVerify( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \\\n\t\t\t\t\t\tconst int sigLength )\n\t{\n\tvoid *dataPtr;\n\tint status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( sigLength >= MIN_CRYPT_OBJECTSIZE && \\\n\t\t\t  sigLength < MAX_INTLENGTH_SHORT );\n\n\t/* Get a pointer to the signature data block */\n\tstatus = sMemGetDataBlock( stream, &dataPtr, sigLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( dataPtr != NULL );\n\n\t/* Verify the signature.  The reason for the min() part of the\n\t   expression is that iCryptCheckSignature() gets suspicious of very\n\t   large buffer sizes, for example when the user has specified the use\n\t   of a huge send buffer */\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tCRYPT_CONTEXT iHashContext;\n\n\t\t/* See the note above about the complexities of handling the ever-\n\t\t   changing pre-TLS 1.2 signature format.  To catch any use of one \n\t\t   of these formats, we check for a non-cryptlib signature being \n\t\t   passed to us by checking for the absence of an ASN.1 SEQUENCE \n\t\t   tag and report it as a signature-verification failures.\n\t\t   \n\t\t   In theory if there's ever any demand for support for this, we\n\t\t   could take advantage of the fact that the signature can really\n\t\t   only be RSA (DSA is gone and ECC is TLS 1.2-only) and perform a\n\t\t   raw RSA public-key operation on the signature data, extract the\n\t\t   lowest 20 bytes (the SHA-1 portion), and compare it with the hash \n\t\t   data */\n\t\tif( *( ( BYTE * ) dataPtr ) != 0x30 )\n\t\t\t{\n\t\t\tassert( DEBUG_WARN );\n\t\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't verify old-style (pre-TLS 1.2) client \"\n\t\t\t\t\t  \"certificate-verify message\" ) );\n\t\t\t}\n\n\t\t/* Create the hash of the data to verify if necessary */\n\t\tstatus = createCertVerifyAltHash( handshakeInfo, &iHashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\tstatus = iCryptCheckSignature( dataPtr, \n\t\t\t\t\t\tmin( sigLength, MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\tCRYPT_FORMAT_CRYPTLIB, sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\tiHashContext, CRYPT_UNUSED, NULL );\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = iCryptCheckSignature( dataPtr, \n\t\t\t\t\t\tmin( sigLength, MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\tCRYPT_IFORMAT_TLS12, sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\thandshakeInfo->sessionHashContext, CRYPT_UNUSED, NULL );\n\t\tkrnlSendNotifier( handshakeInfo->sessionHashContext, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sessionHashContext = CRYPT_ERROR;\n#ifdef CONFIG_SUITEB_TESTS \n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tint sigKeySize;\n\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &sigKeySize, \n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tDEBUG_PRINT(( \"Verified client's P%d authentication.\\n\", \n\t\t\t\t\t\t\t  bytesToBits( sigKeySize ) ));\n\t\t\t\t}\n\t\t\t}\n#endif /* CONFIG_SUITEB_TESTS */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Verification of client's certificate-verify message \"\n\t\t\t\t  \"failed\" ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tKeyex Signature Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create/check the signature on the server key data */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int createKeyexHash( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\tOUT_HANDLE_OPT CRYPT_CONTEXT *hashContext,\n\t\t\t\t\t\t\tIN_ALGO const CRYPT_ALGO_TYPE hashAlgo,\n\t\t\t\t\t\t\tIN_INT_SHORT_Z const int hashParam,\n\t\t\t\t\t\t\tIN_BUFFER( keyDataLength ) const void *keyData, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int keyDataLength,\n\t\t\t\t\t\t\tconst BOOLEAN hashTLSLTS )\n\t{\n\tCRYPT_CONTEXT iHashContext;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( hashContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t\t  hashAlgo <= CRYPT_ALGO_LAST_HASH );\n\tREQUIRES( isShortIntegerRange( hashParam ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyDataLength ) );\n\tREQUIRES( hashTLSLTS == TRUE || hashTLSLTS == FALSE );\n\n\t/* Clear return value */\n\t*hashContext = CRYPT_ERROR;\n\n\t/* Create the hash context */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiHashContext = createInfo.cryptHandle;\n\tif( hashParam != 0 )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &hashParam,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Hash the client and server nonces and key data */\n\tif( hashTLSLTS )\n\t\t{\n\t\tBYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\n\t\thandshakeInfo->helloHashFunction( handshakeInfo->helloHashInfo, \n\t\t\t\t\t\t\t\t\t\t  hashBuffer, CRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t\t\t  NULL, 0, HASH_STATE_END );\n\t\tDEBUG_PUTS(( \"Client/Server hello hash =\" ));\n\t\tDEBUG_DUMP_DATA( hashBuffer, handshakeInfo->helloHashSize );\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  hashBuffer, handshakeInfo->helloHashSize );\n\t\t}\n\telse\n\t\t{\n\t\tBYTE nonceBuffer[ SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];\n\n\t\tmemcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\t\tmemcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,\n\t\t\t\tSSL_NONCE_SIZE );\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t  nonceBuffer, \n\t\t\t\t\t\t\t\t  SSL_NONCE_SIZE + SSL_NONCE_SIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) keyData, keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, \"\", 0 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t*hashContext = iHashContext;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint createKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t  IN_BUFFER( keyDataLength ) const void *keyData, \n\t\t\t\t\t\t  IN_LENGTH_SHORT const int keyDataLength )\n\t{\n\tCRYPT_CONTEXT md5Context DUMMY_INIT, shaContext;\n\tvoid *dataPtr;\n\tint dataLength, sigLength DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyDataLength ) );\n\n\t/* Hash the data to be signed */\n\tstatus = createKeyexHash( handshakeInfo, &shaContext, \n\t\t\t\t( handshakeInfo->keyexSigHashAlgo != CRYPT_ALGO_NONE ) ? \\\n\t\t\t\t\thandshakeInfo->keyexSigHashAlgo : CRYPT_ALGO_SHA1,\n\t\t\t\thandshakeInfo->keyexSigHashAlgoParam, keyData, keyDataLength,\n\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = createKeyexHash( handshakeInfo, &md5Context, \n\t\t\t\t\t\t\t\t  CRYPT_ALGO_MD5, 0, keyData, keyDataLength, \n\t\t\t\t\t\t\t\t  FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tINJECT_FAULT( BADSIG_HASH, SESSION_BADSIG_HASH_SSL_1 );\n\n\t/* Sign the hashes.  The reason for the min() part of the expression is\n\t   that iCryptCreateSignature() gets suspicious of very large buffer\n\t   sizes, for example when the user has specified the use of a huge send\n\t   buffer */\n\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t\t{\n\t\t\tstatus = iCryptCreateSignature( dataPtr, \n\t\t\t\t\t\t\t\t\t\t\tmin( dataLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\t\t\t\t\t\t&sigLength, CRYPT_IFORMAT_TLS12, \n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t\t\tshaContext, NULL );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tSIGPARAMS sigParams;\n\n\t\t\tinitSigParams( &sigParams );\n\t\t\tsigParams.iSecondHash = shaContext;\n\t\t\tstatus = iCryptCreateSignature( dataPtr, \n\t\t\t\t\t\t\t\t\t\t\tmin( dataLength, \\\n\t\t\t\t\t\t\t\t\t\t\t\t MAX_INTLENGTH_SHORT - 1 ), \n\t\t\t\t\t\t\t\t\t\t\t&sigLength, CRYPT_IFORMAT_SSL, \n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t\t\tmd5Context, &sigParams );\n\t\t\t}\n\t\t}\n\tinsertCryptoDelay();\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\tkrnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tINJECT_FAULT( BADSIG_SIG, SESSION_BADSIG_SIG_SSL_1 );\n\n\treturn( sSkip( stream, sigLength, MAX_INTLENGTH_SHORT ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \\\nint checkKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t IN_BUFFER( keyDataLength ) const void *keyData, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int keyDataLength,\n\t\t\t\t\t\t const BOOLEAN isECC )\n\t{\n\tCRYPT_CONTEXT md5Context DUMMY_INIT, shaContext;\n\tCRYPT_ALGO_TYPE hashAlgo = CRYPT_ALGO_SHA1;\n\tvoid *dataPtr;\n\tint dataLength, keyexKeySize, sigKeySize DUMMY_INIT, hashParam = 0;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyDataLength ) );\n\tREQUIRES( isECC == TRUE || isECC == FALSE );\n\n\t/* Make sure that there's enough data present for at least a minimal-\n\t   length signature and get a pointer to the signature data */\n\tif( sMemDataLeft( stream ) < ( isECC ? \\\n\t\t\t\t\t\t\t\t   MIN_PKCSIZE_ECCPOINT : MIN_PKCSIZE ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( dataPtr != NULL );\n\n\t/* TLS 1.2+ precedes the signature itself with an indication of the hash\n\t   and signature algorithm that's required to verify it, so if we're \n\t   using this format then we have to process the identifiers before we\n\t   can create the signature-verification hashes.\n\n\t   We disallow SHA1 since the whole point of TLS 1.2 was to move away \n\t   from it, and a poll on the ietf-tls list indicated that all known \n\t   implementations (both of them) work fine with this configuration */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatic const MAP_TABLE hashAlgoIDTbl[] = {\n\t\t\t{ 1000, CRYPT_ALGO_SHAng },\n#ifdef CONFIG_SUITEB\n\t\t\t{ TLS_HASHALGO_SHA384, CRYPT_ALGO_SHA2 },\n#endif /* CONFIG_SUITEB */\n\t\t\t{ TLS_HASHALGO_SHA2, CRYPT_ALGO_SHA2 },\n#if 0\t/* 2/11/11 Disabled option for SHA1 after poll on ietf-tls list */\n\t\t\t{ TLS_HASHALGO_SHA1, CRYPT_ALGO_SHA1 },\n#endif /* 0 */\n\t\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t\t};\n\t\tint cryptHashAlgo, tlsHashAlgo;\n\n\t\t/* Get the hash algorithm that we need to use.  We don't care about\n\t\t   the signature algorithm since we've already been given the public\n\t\t   key for it */\n\t\tstatus = tlsHashAlgo = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t( void ) sgetc( stream );\n\t\tif( !isEnumRange( tlsHashAlgo, TLS_HASHALGO ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL ); \n\t\tstatus = mapValue( tlsHashAlgo, &cryptHashAlgo, hashAlgoIDTbl, \n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL ); \n\t\thashAlgo = cryptHashAlgo;\t/* int vs.enum */\n\t\tif( tlsHashAlgo == TLS_HASHALGO_SHA384 )\n\t\t\thashParam = bitsToBytes( 384 );\n\t\t}\n\n\t/* Hash the data to be signed */\n\tstatus = createKeyexHash( handshakeInfo, &shaContext, hashAlgo, \n\t\t\t\t\t\t\t  hashParam, keyData, keyDataLength,\n\t\t\t\t\t\t\t  TEST_FLAG( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t\t\t\t\t SSL_PFLAG_TLS12LTS ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = createKeyexHash( handshakeInfo, &md5Context, \n\t\t\t\t\t\t\t\t  CRYPT_ALGO_MD5, 0, keyData, keyDataLength,\n\t\t\t\t\t\t\t\t  FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tkrnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Check the signature on the hashes.  The reason for the min() part of\n\t   the expression is that iCryptCheckSignature() gets suspicious of\n\t   very large buffer sizes, for example when the user has specified the\n\t   use of a huge send buffer */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = iCryptCheckSignature( dataPtr, \n\t\t\t\t\t\t\t\tmin( dataLength, MAX_INTLENGTH_SHORT - 1 ),\n\t\t\t\t\t\t\t\tCRYPT_IFORMAT_TLS12, \n\t\t\t\t\t\t\t\tsessionInfoPtr->iKeyexCryptContext, \n\t\t\t\t\t\t\t\tshaContext, CRYPT_UNUSED, NULL );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = iCryptCheckSignature( dataPtr, \n\t\t\t\t\t\t\t\tmin( dataLength, MAX_INTLENGTH_SHORT - 1 ),\n\t\t\t\t\t\t\t\tCRYPT_IFORMAT_SSL, \n\t\t\t\t\t\t\t\tsessionInfoPtr->iKeyexCryptContext, \n\t\t\t\t\t\t\t\tmd5Context, shaContext, NULL );\n\t\t}\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\tkrnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );\n\tkrnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Make sure that the relative strengths of the keyex and signature keys \n\t   match.  This is just a general precaution for RSA/DSA, but is \n\t   mandated for ECC with Suite B in order to make the appropriate \n\t   fashion statement (see the comment below).  When performing the check \n\t   we allow a small amount of wiggle room to deal with keygen \n\t   differences */\n\tstatus = krnlSendMessage( handshakeInfo->dhContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keyexKeySize, \n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexCryptContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &sigKeySize, \n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( isECC )\n\t\t{\n\t\t/* For ECC with Suite B the signature key size has to match the \n\t\t   keyex key size otherwise fashion dictums are violated (if you \n\t\t   could just sign size n with size n+1 then you wouldn't need \n\t\t   hashsize n/n+1 and keysize n/n+1 and whatnot) */\n\t\tif( sigKeySize < keyexKeySize - bitsToBytes( 8 ) )\n\t\t\t{\n\t\t\tDEBUG_PRINT(( \"Server used P%d keyex but only P%d signature.\\n\",\n\t\t\t\t\t\t  bytesToBits( keyexKeySize ),\n\t\t\t\t\t\t  bytesToBits( sigKeySize ) ));\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n\t\t\t}\n#ifdef CONFIG_SUITEB\n\t\tif( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB ) && \\\n\t\t\tsigKeySize > keyexKeySize + bitsToBytes( 8 ) )\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n  #ifdef CONFIG_SUITEB_TESTS \n\t\tDEBUG_PRINT(( \"Verified server's P%d keyex with P%d signature.\\n\", \n\t\t\t\t\t  bytesToBits( keyexKeySize ), \n\t\t\t\t\t  bytesToBits( sigKeySize ) ));\n  #endif /* CONFIG_SUITEB_TESTS */\n#endif /* CONFIG_SUITEB */\n\t\t}\n\telse\n\t\t{\n#if 1\n\t\t/* For conventional keyex/signatures things get a bit complicated,\n\t\t   using (say) a 1024-bit key to sign a 1536-bit keyex seems like a\n\t\t   mismatch, but then the 1024-bit key may be regenerated relatively\n\t\t   frequently while the 1536-bit DH parameters may be static and\n\t\t   shared with everyone else on earth, making the high-value 1536-\n\t\t   bit key a more viable target for attack than the singleton 1024-\n\t\t   bit one.  Because of this we allow a difference of up to 512 bits\n\t\t   between the signing key and the keyex key */\n\t\tif( sigKeySize < keyexKeySize - bitsToBytes( 512 + 32 ) )\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n#else\n\t\t/* For conventional keyex/signatures the bounds are a bit looser \n\t\t   because non-ECC keygen mechanisms can result in a wider variation \n\t\t   of actual vs. nominal key size */\n\t\tif( sigKeySize < keyexKeySize - bitsToBytes( 32 ) )\n\t\t\treturn( CRYPT_ERROR_NOSECURE );\n#endif /* 0 */\n\t\t}\n\n\t/* Skip the signature data */\n\treturn( readUniversal16( stream ) );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_ext.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib TLS Extension Management\t\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/* The maximum number of extensions that we allow before getting \n   suspicious */\n\n#define MAX_EXTENSIONS\t\t32\n\n/* The maximum size for a single extension */\n\n#define MAX_EXTENSION_SIZE\t8192\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTLS Extension Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* TLS extension information.  Further types are defined at\n   http://www.iana.org/assignments/tls-extensiontype-values.\n\n   We specify distinct minimum and maximum lengths for client- and server-\n   side use (so minLengthClient is the minimum length that a client can \n   send).  A value of CRYPT_ERROR means that this extension isn't valid when \n   sent by the client or server */\n\ntypedef struct {\n\tconst int type;\t\t\t\t\t/* Extension type */\n\tconst int minLengthClient, minLengthServer;\t/* Min.length */\n\tconst int maxLength;\t\t\t/* Max.length */\n#ifdef USE_ERRMSGS\n\tconst char *description;\t\t/* Text description for error messages */\n#endif /* USE_ERRMSGS */\n\t} EXT_CHECK_INFO;\n\n#ifdef USE_ERRMSGS\n  #define TYPENAME( text )\t\t, text\n#else\n  #define TYPENAME( text )\n#endif /* USE_ERRMSGS */\n\nstatic const EXT_CHECK_INFO extCheckInfoTbl[] = {\n\t/* Server name indication (SNI), RFC 4366/RFC 6066:\n\n\t\tuint16\t\tlistLen\n\t\t\tbyte\tnameType\n\t\t\tuint16\tnameLen\n\t\t\tbyte[]\tname */\n\t{ TLS_EXT_SERVER_NAME, 1, 0, MAX_EXTENSION_SIZE \n\t  TYPENAME( \"server name indication\" ) },\n\n#ifndef CONFIG_CONSERVE_MEMORY\n\t/* Maximum fragment length, RFC 4366/RFC 6066:\n\n\t\tbyte\t\tfragmentLength */\n\t{ TLS_EXT_MAX_FRAGMENT_LENTH, 1, 1, 1 \n\t  TYPENAME( \"fragment length\" ) },\n\n\t/* Client certificate URL.  This dangerous extension allows a client to \n\t   direct a server to grope around in arbitrary external (and untrusted) \n\t   URLs trying to locate certificates, provinding a convenient mechanism \n\t   for bounce attacks and all manner of similar firewall/trusted-host \n\t   subversion problems:\n\n\t\tbyte\t\tchainType\n\t\tuint16\t\turlAndHashList\n\t\t\tuint16\turlLen\n\t\t\tbyte[]\turl\n\t\t\tbyte\thashPresent\n\t\t\tbyte[20] hash\t\t\t-- If hashPresent flag set */\n\t{ TLS_EXT_CLIENT_CERTIFICATE_URL, \n\t  1 + UINT16_SIZE + UINT16_SIZE + MIN_URL_SIZE + 1, CRYPT_ERROR, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"client certificate URL\" ) },\n\n\t/* Trusted CA certificate(s), RFC 4366/RFC 6066.  This allows a client \n\t   to specify which CA certificates it trusts and by extension which \n\t   server certificates it trusts, supposedly to reduce handshake \n\t   messages in constrained clients.  Since the server usually has only a \n\t   single certificate signed by a single CA, specifying the CAs that the \n\t   client trusts doesn't serve much purpose:\n\n\t\tuint16\t\tcaList\n\t\t\tbyte\tidType\n\t\t\t[ choice of keyHash, certHash, or DN, another \n\t\t\t  ASN.1-as-TLS structure ] */\n\t{ TLS_EXT_TRUSTED_CA_KEYS, UINT16_SIZE + 1, CRYPT_ERROR, MAX_EXTENSION_SIZE \n\t  TYPENAME( \"trusted CA\" ) },\n\n\t/* Truncate the HMAC to a nonstandard 80 bits rather than the de facto \n\t   IPsec cargo-cult standard of 96 bits, RFC 3546/4366/6066.  \n\t   \n\t   In 2017, fourteen years after it was standardised, it was first \n\t   noticed that none of the three publicly-available SSL implementations \n\t   that support this could interoperate (they'd all implemented it \n\t   differently), indicating that this capability has never actually been \n\t   used by anyone, so we don't bother supporting it */\n\t{ TLS_EXT_TRUNCATED_HMAC, 0, 0, 0\n\t  TYPENAME( \"truncated HMAC\" ) },\n\n\t/* OCSP status request, RFC 4366/RFC 6066.  Another bounce-attack \n\t   enabler, this time on both the server and an OCSP responder.  Both \n\t   the responder list and the extensions list may have length zero:\n\n\t\tbyte\t\tstatusType\n\t\tuint16\t\tocspResponderList\t-- May be length 0\n\t\t\tuint16\tresponderLength\n\t\t\tbyte[]\tresponder\n\t\tuint16\textensionLength\t\t\t-- May be length 0\n\t\t\tbyte[]\textensions */\n\t{ TLS_EXT_STATUS_REQUEST, \n\t  1 + UINT16_SIZE + UINT16_SIZE, CRYPT_ERROR, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"OCSP status request\" ) },\n\n\t/* User mapping.  Used with a complex RFC 4680 mechanism (the extension \n\t   itself is in RFC 4681):\n\n\t\tbyte\t\tmappingLength\n\t\tbyte[]\t\tmapping */\n\t{ TLS_EXT_USER_MAPPING, 1 + 1, CRYPT_ERROR, 1 + 255\n\t  TYPENAME( \"user-mapping\" ) },\n\n\t/* Authorisation extenions.  From an experimental RFC for adding \n\t   additional authorisation data to the TLS handshake, RFC 5878:\n\n\t\tbyte\t\tauthzFormatsList\n\t\t\tbyte\tauthzFormatType\n\n\t   with the additional authorisation data being carried in the \n\t   SupplementalData handshake message */\n\t{ TLS_EXT_CLIENT_AUTHZ, 1 + 1, CRYPT_ERROR, 1 + 255\n\t  TYPENAME( \"client-authz\" ) },\n\t{ TLS_EXT_SERVER_AUTHZ, CRYPT_ERROR, 1 + 1, 1 + 255\n\t  TYPENAME( \"server-authz\" ) },\n\n\t/* OpenPGP key.  From an experimental (later informational) RFC with \n\t   support for OpenPGP keys, RFC 5081/6091:\n\n\t\tbyte\t\tcertTypeListLength\n\t\tbyte[]\t\tcertTypeList */\n\t{ TLS_EXT_CERTTYPE, 1 + 1, CRYPT_ERROR, 1 + 255\n\t  TYPENAME( \"cert-type (OpenPGP keying)\" ) },\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n\t/* Supported ECC curve IDs, RFC 4492 modified by RFC 5246/TLS 1.2:\n\n\t\tuint16\t\tnamedCurveListLength\n\t\tuint16[]\tnamedCurve */\n\t{ TLS_EXT_ELLIPTIC_CURVES, UINT16_SIZE + UINT16_SIZE, CRYPT_ERROR, 512\n\t  TYPENAME( \"ECDH/ECDSA curve ID\" ) },\n\n\t/* Supported ECC point formats, RFC 4492 modified by RFC 5246/TLS 1.2:\n\n\t\tbyte\t\tpointFormatListLength\n\t\tbyte[]\t\tpointFormat */\n\t{ TLS_EXT_EC_POINT_FORMATS, 1 + 1, 1 + 1, 255 \n\t  TYPENAME( \"ECDH/ECDSA point format\" ) },\n\n#ifndef CONFIG_CONSERVE_MEMORY\n\t/* SRP user name, RFC 5054:\n\n\t\tbyte\t\tuserNameLength\n\t\tbyte[]\t\tuserName */\n\t{ TLS_EXT_SRP, 1 + 1, CRYPT_ERROR, 1 + 255 \n\t  TYPENAME( \"SRP username\" ) },\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n\t/* Signature algorithms, RFC 5246/TLS 1.2:\n\n\t\tuint16\t\talgorithmListLength\n\t\t\tbyte\thashAlgo\n\t\t\tbyte\tsigAlgo */\n\t{ TLS_EXT_SIGNATURE_ALGORITHMS, UINT16_SIZE + 1 + 1, CRYPT_ERROR, 512 \n\t  TYPENAME( \"signature algorithm\" ) },\n\n#ifndef CONFIG_CONSERVE_MEMORY\n\t/* DTLS for SRTP keying, RFC 5764:\n\n\t\tuint16\t\tsrtpProtectionProfileListLength\n\t\t\tuint16\tsrtpProtectionProfile\n\t\t\tbyte[]\tsrtp_mki */\n\t{ TLS_EXT_USE_SRP, UINT16_SIZE + UINT16_SIZE + 1, CRYPT_ERROR, 512\n\t  TYPENAME( \"DTLS SRTP keying\" ) },\n\n\t/* DTLS heartbeat, RFC 6520:\n\n\t\tbyte\t\theartBeatMode */\n\t{ TLS_EXT_HEARTBEAT, 1, 1, 1 \n\t  TYPENAME( \"DTLS heartbeat\" ) },\n\n\t/* TLS ALPN, RFC 7301:\n\t\tuint16\t\tprotocolNameListLength\n\t\t\tuint8\tprotocolNameLength\n\t\t\tbyte[]\tprotocolName */\n\t{ TLS_EXT_ALPN, UINT16_SIZE + 1 + 1, CRYPT_ERROR, 512\n\t  TYPENAME( \"ALPN\" ) },\n\n\t/* OCSP status request v2, RFC 6961.  See the comment for \n\t   TLS_EXT_STATUS_REQUEST:\n\n\t\tbyte\t\tstatusType\n\t\tuint16\t\trequestLength\n\t\t\tuint16\tocspResponderList\t-- May be length 0\n\t\t\t\tuint16\tresponderLength\n\t\t\t\tbyte[]\tresponder\n\t\t\tuint16\textensionLength\t\t-- May be length 0\n\t\t\t\tbyte[]\textensions */\n\t{ TLS_EXT_STATUS_REQUEST_V2, \n\t  1 + UINT16_SIZE + UINT16_SIZE + UINT16_SIZE, CRYPT_ERROR, MAX_EXTENSION_SIZE \n\t  TYPENAME( \"OCSP status request v2\" ) },\n\n\t/* Certificate transparency timestamp, RFC 6962.  This is another\n\t   Trusted-CA-certificate level of complexity extension, the client\n\t   sends an empty request and the server responds with an X.509 level\n\t   of complexity extension, a SignedCertificateTimestampList:\n\n\t\tuint16\t\tsignedCertTimestampListLength\n\t\t\tuint16\tserialisedSignedCertTimestampLength\n\t\t\t\tbyte[]\t[ X.509 level of complexity ]\n\n\t   Decoding what all of this requires from the RFC is excessively\n\t   complex (the spec is vague and ambiguous in several locations, with\n\t   details of what's required scattered all over the RFC in a mixture of\n\t   ASN.1 and TLS notation), but requiring a length of 64 bytes seems\n\t   sound */\n\t{ TLS_EXT_CERT_TRANSPARENCY, 0, UINT16_SIZE + UINT16_SIZE + 64, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"certificate transparency\" ) },\n\n\t/* Raw client/server public keys, RFC 7250:\n\n\t\tuint8\t\tcertificateTypeLength\n\t\t\tbyte[]\tcertificateTypes */\n\t{ TLS_EXT_RAWKEY_CLIENT, 1 + 1, 1 + 1, 64\n\t  TYPENAME( \"client raw public key\" ) },\n\t{ TLS_EXT_RAWKEY_SERVER, 1 + 1, 1 + 1, 64\n\t  TYPENAME( \"server raw public key\" ) },\n\n\t/* Client hello padding, RFC 7685:\n\n\t\tuint16\t\tpaddingLength\n\t\t\tbyte[]\tpadding */\n\t{ TLS_EXT_PADDING, UINT16_SIZE, CRYPT_ERROR, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"client hello padding\" ) },\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n\t/* Encrypt-then-MAC, RFC 7366 */\n\t{ TLS_EXT_ENCTHENMAC, 0, 0, 0\n\t  TYPENAME( \"encrypt-then-MAC\" ) },\n\n\t/* Extended Master Secret, RFC 7627 */\n\t{ TLS_EXT_EMS, 0, 0, 0\n\t  TYPENAME( \"extended master secret\" ) },\n\n#ifndef CONFIG_CONSERVE_MEMORY\n\t/* Draft, Token binding:\n\n\t\tbyte\t\tmajorVersion\n\t\tbyte\t\tminorVersion\n\t\tbyte\t\tparameterLength\n\t\t\tbyte[]\tparameters */\n\t{ TLS_EXT_TOKENBIND, 1 + 1 + 1 + 1, 1 + 1 + 1 + 1, 128\n\t  TYPENAME( \"token binding\" ) },\n\n\t/* Cached info, RFC 7924:\n\n\t\tuint16\t\tcachedInfoLength\n\t\t\tbyte[]\tcachedInfo */\n\t{ TLS_EXT_CACHED_INFO, UINT16_SIZE + 1, UINT16_SIZE + 1, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"cached information\" ) },\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n\t/* TLS 1.2 LTS, RFC xxxx */\n\t{ TLS_EXT_TLS12LTS, 0, 0, 0\n\t  TYPENAME( \"TLS 1.2 LTS\" ) },\n\n#ifndef CONFIG_CONSERVE_MEMORY\n\t/* Draft, Compress certificate:\n\n\t\tbyte\t\tcompressionAlgoListLength\n\t\t\tbyte\tcompressionAlgos */\n\t{ TLS_EXT_COMPRESS_CERT, 1 + 1, 0, 128\n\t  TYPENAME( \"compress certificate\" ) },\n\n\t/* Draft, Record size limit:\n\n\t\tuint16\t\trecordSizeLimit */\n\t{ TLS_EXT_RECORD_SIZE_LIMIT, UINT16_SIZE, UINT16_SIZE, UINT16_SIZE\n\t  TYPENAME( \"record size limit\" ) },\n\n\t/* Session ticket, RFC 4507/5077.  The client can send a zero-length \n\t   session ticket to indicate that it supports the extension but doesn't \n\t   have a session ticket yet, and the server can send a zero-length \n\t   ticket to indicate that it'll send the client a new ticket later in \n\t   the handshake.  Confusing this even more, the specification says that \n\t   the client sends \"a zero-length ticket\" but the server sends \"a \n\t   zero-length extension\".  The original specification, RFC 4507, was \n\t   later updated by a second version, RFC 5077, that makes explicit (via \n\t   Appendix A) the fact that there's no \"ticket length\" field in the \n\t   extension, so that the entire extension consists of the opaque ticket \n\t   data:\n\n\t\tbyte[]\t\tsessionTicket (implicit size) */\n\t{ TLS_EXT_SESSIONTICKET, 0, 0, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"session ticket\" ) },\n\n\t/* Monster list of TLS 1.3 extensions:\n\n\t   Pre-shared key:\n\t\tcomplex[]\tpskInfo\t\t\t\t-- Client: Complex nested structure\n\t\tuint16\t\tpskIdentity\t\t\t-- Server\n\n\t   Early data:\n\n\t   Supported versions:\n\t\tbyte\t\tversionListLength\t-- Client\n\t\t\tuint16[] versionList\n\t\tuint16\t\tversion\t\t\t\t-- Server\n\n\t   Cookie:\n\t\tuint16\t\tcookieLength\n\t\t\tbyte[]\tcookie\n\n\t   Key exchange modes:\n\t\tbyte\t\tkeyexModesLength\n\t\t\tbyte[]\tkeyexModes\n\n\t   Certificate authorities:\n\t\tuint16\t\tcaDNListLength\n\t\t\tbyte[]\tcaDNList\n\n\t   OID filters:\n\t\tuint16\t\toidFilterListLength\n\t\t\tbyte\toidLength\n\t\t\t\tbyte[] oid\n\t\t\tuint16\textensionsLength\t-- May be 0\n\t\t\t\tbyte extensions\n\n\t   Post-handshake auth:\n\n\t   Certificate signature algorithms:\n\t\tuint16\t\talgorithmListLength\n\t\t\tbyte\thashAlgo\n\t\t\tbyte\tsigAlgo\n\n\t   Key share:\n\t\tuint16\t\tkeyShareListLength\t-- Client, may be 0\n\t\t\tbyte[]\tkeyShareList\n\t\tcomplex\t\tkeyShare\t\t\t-- Server\n\t*/\n\t{ TLS_EXT_PRESHARED_KEY, 40, UINT16_SIZE, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"TLS 1.3 pre-shared key\" ) },\n\t{ TLS_EXT_EARLY_DATA, 0, 0, 0\n\t  TYPENAME( \"TLS 1.3 early data\" ) },\n\t{ TLS_EXT_SUPPORTED_VERSIONS, 1 + UINT16_SIZE, UINT16_SIZE, 64\n\t  TYPENAME( \"TLS 1.3 supported versions\" ) },\n\t{ TLS_EXT_COOKIE, UINT16_SIZE + 1, UINT16_SIZE + 1, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"TLS 1.3 cookie\" ) },\n\t{ TLS_EXT_PSK_KEYEX_MODES, 1, CRYPT_ERROR, 128\n\t  TYPENAME( \"TLS 1.3 key exchange modes\" ) },\n\t{ TLS_EXT_CAS, UINT16_SIZE, UINT16_SIZE, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"TLS 1.3 certificate authorities\" ) },\n\t{ TLS_EXT_OID_FILTERS, UINT16_SIZE + 1 + 1 + UINT16_SIZE, UINT16_SIZE + 1 + 1 + UINT16_SIZE, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"TLS 1.3 OID filters\" ) },\n\t{ TLS_EXT_POST_HS_AUTH, 0, CRYPT_ERROR, 0\n\t  TYPENAME( \"TLS 1.3 post-handshake auth\" ) },\n\t{ TLS_EXT_SIG_ALGOS_CERT, UINT16_SIZE + 1 + 1, UINT16_SIZE + 1 + 1, 512 \n\t  TYPENAME( \"TLS 1.3 certificate signature algorithms\" ) },\n\t{ TLS_EXT_KEY_SHARE, UINT16_SIZE, 2, MAX_EXTENSION_SIZE\n\t  TYPENAME( \"TLS 1.3 key share\" ) },\n#endif /* CONFIG_CONSERVE_MEMORY */\n\n\t/* Secure renegotiation indication, RFC 5746:\n\n\t\tbyte renegotiated_connection[]\n\t\n\t   See the comment below for why we (apparently) support this even \n\t   though we don't do renegotiation.  We give the length as one, \n\t   corresponding to zero-length content, the one is for the single-byte \n\t   length field in the extension itself, set to a value of zero.  It can \n\t   in theory be larger as part of the secure renegotiation process but \n\t   this would be an indication of an attack since we don't do \n\t   renegotiation */\n\t{ TLS_EXT_SECURE_RENEG, 1, 1, 1\n\t  TYPENAME( \"secure renegotiation\" ) },\n\n\t/* End-of-list marker */\n\t{ CRYPT_ERROR, 0, 0, 0 TYPENAME( NULL ) }, \n\t\t{ CRYPT_ERROR, 0, 0, 0 TYPENAME( NULL ) }\n\t};\n\n/* In addition to the variable-format extenions above we also support the \n   secure-renegotiation extension.  This is a strange extension to support \n   because cryptlib doesn't do renegotiation, but we have to send it at the \n   client side in order to avoid being attacked via a (non-cryptlib) server \n   that's vulnerable, and we have to process it on the server side in order \n   to not appear to be a vulnerable server (sigh) */\n\n#define RENEG_EXT_SIZE\t5\n#define RENEG_EXT_DATA\t\"\\xFF\\x01\\x00\\x01\\x00\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRead TLS Extensions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the SNI:\n\n\tuint16\t\tlistLen\n\t\tbyte\tnameType\n\t\tuint16\tnameLen\n\t\tbyte[]\tname \n\n   If we're the client and we sent this extension to the server then the \n   server may responed with a zero-length server-name extension for no \n   immediately obvious purpose (if the server doesn't recognise the name \n   then it's required to send an 'unrecognised-name' alert so any non-alert \n   return means that the value was accepted, but for some reason it's \n   required to send a zero-length response anyway) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processSNI( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t   IN_LENGTH_SHORT_Z const int extLength,\n\t\t\t\t\t   const BOOLEAN isServer )\n\t{\n\tBYTE nameBuffer[ MAX_DNS_SIZE + 8 ];\n\tint listLen, nameLen, status;\n\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isShortIntegerRange( extLength ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* If we're the client then the server should have sent us an empty\n\t   extension */\n\tif( !isServer )\n\t\treturn( ( extLength != 0 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );\n\n\t/* Remember that we've seen the server-name extension so that we can \n\t   send a zero-length reply to the client */\n\thandshakeInfo->needSNIResponse = TRUE;\n\n\t/* Read the extension wrapper */\n\tstatus = listLen = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( listLen != extLength - UINT16_SIZE || \\\n\t\tlistLen < 1 + UINT16_SIZE || \\\n\t\tlistLen >= MAX_INTLENGTH_SHORT )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the name type and length */\n\tif( sgetc( stream ) != 0 )\t/* Name type 0 = hostname */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tstatus = nameLen = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( nameLen != listLen - ( 1 + UINT16_SIZE ) || \\\n\t\tnameLen < MIN_DNS_SIZE || nameLen > MAX_DNS_SIZE )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the SNI and hash it */\n\tstatus = sread( stream, nameBuffer, nameLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\thashData( handshakeInfo->hashedSNI, KEYID_SIZE, nameBuffer, nameLen );\n\thandshakeInfo->hashedSNIpresent = TRUE;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the list of preferred (or at least supported) ECC curves.  This \n   is a somewhat problematic extension because it applies to any use of ECC, \n   so if (for some reason) the server wants to use a P256 ECDH key with a \n   P521 ECDSA signing key then it has to verify that the client reports that \n   it supports both P256 and P521.  Since our limiting factor is the ECDSA \n   key that we use for signing, we require that the client report support \n   for the curve that matches our signing key.  Support for the \n   corresponding ECDH curve is automatic, since we support all curves for \n   ECDH that are supported for ECDSA:\n\n\tuint16\t\tnamedCurveListLength\n\tuint16[]\tnamedCurve */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \\\nstatic int processSupportedCurveID( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT_Z const int extLength,\n\t\t\t\t\t\t\t\t\tOUT_ENUM_OPT( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_ECCCURVE_TYPE *preferredCurveIdPtr,\n\t\t\t\t\t\t\t\t\tOUT_BOOL BOOLEAN *extErrorInfoSet )\n\t{\n\tstatic const MAP_TABLE curveIDTbl[] = {\n\t\t{ TLS_CURVE_SECP256R1, CRYPT_ECCCURVE_P256 },\n\t\t{ TLS_CURVE_SECP384R1, CRYPT_ECCCURVE_P384 },\n\t\t{ TLS_CURVE_SECP521R1, CRYPT_ECCCURVE_P521 },\n\t\t{ TLS_CURVE_BRAINPOOLP256R1, CRYPT_ECCCURVE_BRAINPOOL_P256 },\n\t\t{ TLS_CURVE_BRAINPOOLP384R1, CRYPT_ECCCURVE_BRAINPOOL_P384 },\n\t\t{ TLS_CURVE_BRAINPOOLP512R1, CRYPT_ECCCURVE_BRAINPOOL_P512 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tstatic const MAP_TABLE curveSizeTbl[] = {\n\t\t{ CRYPT_ECCCURVE_P256, bitsToBytes( 256 ) },\n\t\t{ CRYPT_ECCCURVE_P384, bitsToBytes( 384 ) },\n\t\t{ CRYPT_ECCCURVE_P521, bitsToBytes( 521 ) },\n\t\t{ CRYPT_ECCCURVE_BRAINPOOL_P256, bitsToBytes( 256 ) },\n\t\t{ CRYPT_ECCCURVE_BRAINPOOL_P384, bitsToBytes( 384 ) },\n\t\t{ CRYPT_ECCCURVE_BRAINPOOL_P512, bitsToBytes( 512 ) },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tCRYPT_ECCCURVE_TYPE preferredCurveID = CRYPT_ECCCURVE_NONE;\n\tint listLen, keySize, i, status, LOOP_ITERATOR;\n#ifdef CONFIG_SUITEB_TESTS \n\tint curvesSeen = 0;\n#endif /* CONFIG_SUITEB_TESTS */\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( preferredCurveIdPtr, \\\n\t\t\t\t\t\tsizeof( CRYPT_ECCCURVE_TYPE ) ) );\n\n\tREQUIRES( isShortIntegerRange( extLength ) );\n\n\t/* Clear return values */\n\t*preferredCurveIdPtr = CRYPT_ECCCURVE_NONE;\n\t*extErrorInfoSet = FALSE;\n\n\t/* Get the size of the server's signing key to bound the curve size */\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read and check the ECC curve list header */\n\tstatus = listLen = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( listLen != extLength - UINT16_SIZE || \\\n\t\tlistLen < UINT16_SIZE || listLen > 256 || \\\n\t\t( listLen % UINT16_SIZE ) != 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Read the list of curve IDs, recording the most preferred one */\n\tLOOP_EXT( i = 0, i < listLen / UINT16_SIZE, i++, 130 )\n\t\t{\n\t\tint value, curveID, curveSize;\n\n\t\tstatus = value = readUint16( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( !isEnumRange( value, TLS_CURVE ) )\n\t\t\tcontinue;\t/* Unrecognised curve type */\n\t\tstatus = mapValue( value, &curveID, curveIDTbl, \n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( curveIDTbl, MAP_TABLE ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\tcontinue;\t/* Unrecognised curve type */\n\t\tstatus = mapValue( curveID, &curveSize, curveSizeTbl, \n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( curveSizeTbl, MAP_TABLE ) );\n\t\tENSURES( cryptStatusOK( status ) );\n#ifdef CONFIG_SUITEB\n\t\tif( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )\n\t\t\t{\n\t\t\tconst int suiteBinfo = \\\n\t\t\t\t\t\tsessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;\n\n\t\t\t/* Suite B only allows P256 and P384.  At the 128-bit level both \n\t\t\t   P256 and P384 are allowed, at the 256-bit level only P384 is \n\t\t\t   allowed */\n\t\t\tif( curveID != CRYPT_ECCCURVE_P256 && \\\n\t\t\t\tcurveID != CRYPT_ECCCURVE_P384 )\n\t\t\t\tcontinue;\n\t\t\tif( suiteBinfo == SSL_PFLAG_SUITEB_256 && \\\n\t\t\t\tcurveID == CRYPT_ECCCURVE_P256 )\n\t\t\t\tcontinue;\n  #ifdef CONFIG_SUITEB_TESTS \n\t\t\tif( suiteBTestValue == SUITEB_TEST_BOTHCURVES )\n\t\t\t\t{\n\t\t\t\t/* We're checking whether the client sends both curve IDs, \n\t\t\t\t   remember which ones we've seen so far */\n\t\t\t\tif( curveID == CRYPT_ECCCURVE_P256 )\n\t\t\t\t\tcurvesSeen |= 1;\n\t\t\t\tif( curveID == CRYPT_ECCCURVE_P384 )\n\t\t\t\t\tcurvesSeen |= 2;\n\t\t\t\t}\n  #endif /* CONFIG_SUITEB_TESTS */\n\t\t\t}\n#endif /* CONFIG_SUITEB */\n\n\t\t/* Make sure that the curve matches the server's signing key */\n\t\tif( curveSize != keySize )\n\t\t\tcontinue;\n\n\t\t/* We've got a matching curve, remember it.  In theory we could exit\n\t\t   at this point but we continue anyway to clear the remainder of \n\t\t   the data */\n\t\tpreferredCurveID = curveID;\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n#ifdef CONFIG_SUITEB_TESTS \n\t/* If we're checking for the presence of both P256 and P384 as supported \n\t   elliptic curves and we don't see them, complain */\n\tif( suiteBTestValue == SUITEB_TEST_BOTHCURVES && curvesSeen != 3 )\n\t\t{\n\t\t*extErrorInfoSet = TRUE;\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Supported elliptic curves extension should have \"\n\t\t\t\t  \"contained both P256 and P384 but didn't\" ) );\n\t\t}\n#endif /* CONFIG_SUITEB_TESTS */\n\n\t*preferredCurveIdPtr = preferredCurveID;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Process the list of signature algorithms that the client can accept.  \n   This is a complex and confusing TLS 1.2+ extension with weird \n   requirements attached to it, for example if the client indicates hash \n   algorithm X then the server (section 7.4.2) has to somehow produce a \n   certificate chain signed only using that hash algorithm, as if a \n   particular algorithm choice for TLS use could somehow dictate what \n   algorithms the CA and certificate-processing library that's being used \n   will provide (in addition the spec is rather confused on this issue, \n   giving it first as a MUST and then a paragraph later as a SHOULD).  This \n   also makes some certificate signature algorithms like RSA-PSS impossible \n   even if the hash algorithm used is supported by both the TLS and \n   certificate library, because TLS only allows the specification of PKCS \n   #1 v1.5 signatures.  What's worse, it creates a situation from which \n   there's no recovery because in the case of a problem all that the server \n   can say is \"failed\", but not \"try again using this algorithm\", while \n   returning certificates or a signature with the server's available \n   algorithm (ignoring the requirement to summarily abort the handshake in \n   the case of a mismatch) at least tells the client what the problem is.\n\n   To avoid this mess we assume that everyone can do SHA-256, the TLS 1.2 \n   default.  A poll of TLS implementers in early 2011 indicated that \n   everyone else ignores this requirement as well (one implementer described\n   the requirement as \"that is not just shooting yourself in the foot, that \n   is shooting 'the whole nine yards' (the entire ammunition belt) in your \n   foot\"), so we're pretty safe here.  Since the extension isn't valid for \n   earlier versions, we ignore it if we're not using TLS 1.2+:\n\n\tuint16\t\talgorithmListLength\n\t\tbyte\thashAlgo\n\t\tbyte\tsigAlgo */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int processSignatureAlgos( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t\t\t  IN_LENGTH_SHORT_Z const int extLength,\n\t\t\t\t\t\t\t\t  OUT_BOOL BOOLEAN *extErrorInfoSet )\n\t{\n#ifdef CONFIG_SUITEB\n\tstatic const MAP_TABLE curveSizeTbl[] = {\n\t\t{ bitsToBytes( 256 ), TLS_HASHALGO_SHA2 },\n\t\t{ bitsToBytes( 384 ), TLS_HASHALGO_SHA384 },\n\t\t{ CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }\n\t\t};\n\tconst int suiteBinfo = sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;\n\tint keySize, hashType, LOOP_ITERATOR;\n  #ifdef CONFIG_SUITEB_TESTS \n\tint hashesSeen = 0;\n  #endif /* CONFIG_SUITEB_TESTS */\n#endif /* CONFIG_SUITEB */\n\tint listLen, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( isShortIntegerRange( extLength ) );\n\n\t/* Clear return values */\n\t*extErrorInfoSet = FALSE;\n\n\t/* Read and check the signature algorithm list header */\n\tstatus = listLen = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( listLen != extLength - UINT16_SIZE || \\\n\t\tlistLen < 1 + 1 || listLen > 64 + 64 || \\\n\t\t( listLen % UINT16_SIZE ) != 0 )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* If we're not using TLS 1.2+, skip the extension */\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\treturn( sSkip( stream, listLen, MAX_INTLENGTH_SHORT ) );\n\n\t/* For the more strict handling requirements in Suite B only 256- or \n\t   384-bit algorithms are allowed at the 128-bit level and only 384-bit \n\t   algorithms are allowed at the 256-bit level */\n#ifdef CONFIG_SUITEB\n\t/* If we're not running in Suite B mode then there are no additional\n\t   checks required */\n\tif( !suiteBinfo )\n\t\t{\n\t\thandshakeInfo->keyexSigHashAlgo = CRYPT_ALGO_SHA2;\n\n\t\treturn( sSkip( stream, listLen, MAX_INTLENGTH_SHORT ) );\n\t\t}\n\n\t/* Get the size of the server's signing key to try and match the \n\t   client's preferred hash size */\n\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &keySize,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = mapValue( keySize, &hashType, curveSizeTbl, \n\t\t\t\t\t   FAILSAFE_ARRAYSIZE( curveSizeTbl, MAP_TABLE ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Suite B only allows P256 and P384 keys (checked by the higher-\n\t\t   level code when we add the server key) so we should never get to \n\t\t   this situation */\n\t\treturn( status );\n\t\t}\n\thandshakeInfo->keyexSigHashAlgo = CRYPT_ALGO_NONE;\n\n\t/* Read the hash and signature algorithms and choose the best one to \n\t   use */\n\tLOOP_EXT_CHECKINC( listLen > 0, listLen -= 1 + 1, 66 )\n\t\t{\n\t\tint hashAlgo, sigAlgo;\n\n\t\t/* Read the hash and signature algorithm and make sure that it's one \n\t\t   that we can use.  At the 128-bit level both SHA256 and SHA384 are \n\t\t   allowed, at the 256-bit level only SHA384 is allowed */\n\t\thashAlgo = sgetc( stream );\t\t\t/* Hash algorithm */\n\t\tstatus = sigAlgo = sgetc( stream );\t/* Sig.algorithm */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( sigAlgo != TLS_SIGALGO_ECDSA || \\\n\t\t\t( hashAlgo != TLS_HASHALGO_SHA2 && \\\n\t\t\t  hashAlgo != TLS_HASHALGO_SHA384 ) )\n\t\t\tcontinue;\n\t\tif( suiteBinfo == SSL_PFLAG_SUITEB_256 && \\\n\t\t\thashAlgo != TLS_HASHALGO_SHA384 )\n\t\t\tcontinue;\n  #ifdef CONFIG_SUITEB_TESTS \n\t\tif( suiteBTestValue == SUITEB_TEST_BOTHSIGALGOS )\n\t\t\t{\n\t\t\t/* We're checking whether the client sends both hash algorithm \n\t\t\t   IDs, remember which ones we've seen so far */\n\t\t\tif( hashAlgo == TLS_HASHALGO_SHA2 )\n\t\t\t\thashesSeen |= 1;\n\t\t\tif( hashAlgo == TLS_HASHALGO_SHA384 )\n\t\t\t\thashesSeen |= 2;\n\t\t\t}\n  #endif /* CONFIG_SUITEB_TESTS */\n\n\t\t/* In addition to the general validity checks, the hash type also has\n\t\t   to match the server's key size */\n\t\tif( hashType != hashAlgo )\n\t\t\tcontinue;\n\n\t\t/* We've found one that we can use, set the appropriate variant.  \n\t\t   Note that since SHA384 is just a variant of SHA2, we always \n\t\t   choose this if it's available.  Even if the order given is \n\t\t   { SHA384, SHA256 } the parameter value for the original SHA384 \n\t\t   will remain set when SHA256 is subsequently read */\n\t\thandshakeInfo->keyexSigHashAlgo = CRYPT_ALGO_SHA2;\n\t\tif( hashAlgo == TLS_HASHALGO_SHA384 )\n\t\t\thandshakeInfo->keyexSigHashAlgoParam = bitsToBytes( 384 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* For Suite B the client must send either SHA256 or SHA384 as an \n\t   option */\n\tif( handshakeInfo->keyexSigHashAlgo == CRYPT_ALGO_NONE )\n\t\t{\n\t\t*extErrorInfoSet = TRUE;\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Signature algorithms extension should have \"\n\t\t\t\t  \"contained %sP384/SHA384 but didn't\",\n\t\t\t\t  ( suiteBinfo != SSL_PFLAG_SUITEB_256 ) ? \\\n\t\t\t\t\t\"P256/SHA256 and/or \" : \"\" ) );\n\t\t}\n#ifdef CONFIG_SUITEB_TESTS \n\t/* If we're checking for the presence of both SHA256 and SHA384 as \n\t   supported hash algorithms and we don't see them, complain */\n\tif( suiteBTestValue == SUITEB_TEST_BOTHSIGALGOS && hashesSeen != 3 )\n\t\t{\n\t\t*extErrorInfoSet = TRUE;\n\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t  \"Signature algortithms extension should have contained \"\n\t\t\t\t  \"both P256/SHA256 and P384/SHA384 but didn't\" ) );\n\t\t}\n#endif /* CONFIG_SUITEB_TESTS */\n\n\treturn( CRYPT_OK );\n#else\n\thandshakeInfo->keyexSigHashAlgo = CRYPT_ALGO_SHA2;\n\n\treturn( sSkip( stream, listLen, MAX_INTLENGTH_SHORT ) );\n#endif /* CONFIG_SUITEB */\n\t}\n\n/* Process a single extension.  The internal structure of some of these \n   things shows that they were created by ASN.1 people... */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 6 ) ) \\\nstatic int processExtension( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_RANGE( 0, 65536 ) const int type,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int extLength,\n\t\t\t\t\t\t\t OUT_BOOL BOOLEAN *extErrorInfoSet )\n\t{\n\tint value, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( type >= 0 && type <= 65536 );\n\tREQUIRES( isShortIntegerRange( extLength ) );\n\n\t/* Clear return values */\n\t*extErrorInfoSet = FALSE;\n\n\tswitch( type )\n\t\t{\n\t\tcase TLS_EXT_SERVER_NAME:\n\t\t\t/* Read and process the SNI */\n\t\t\treturn( processSNI( handshakeInfo, stream, extLength, \n\t\t\t\t\t\t\t\tisServer( sessionInfoPtr ) ? \\\n\t\t\t\t\t\t\t\t\tTRUE : FALSE ) );\n\n\t\tcase TLS_EXT_MAX_FRAGMENT_LENTH:\n\t\t\t{\n/*\t\t\tstatic const int fragmentTbl[] = \\\n\t\t\t\t\t{ 0, 512, 1024, 2048, 4096, 8192, 16384, 16384 }; */\n\n\t\t\t/* Response: If fragment-size == 3...5, send same to peer.  Note \n\t\t\t   that we also allow a fragment-size value of 5, which isn't \n\t\t\t   specified in the standard but should probably be present \n\t\t\t   since it would otherwise result in a missing value between \n\t\t\t   4096 and the default of 16384:\n\n\t\t\t\tbyte\t\tfragmentLength */\n\t\t\tstatus = value = sgetc( stream );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( value < 1 || value > 5 )\n\t\t\t\treturn( CRYPT_ERROR_BADDATA );\n\n/*\t\t\tsessionInfoPtr->maxPacketSize = fragmentTbl[ value ]; */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase TLS_EXT_ELLIPTIC_CURVES:\n\t\t\t{\n\t\t\tCRYPT_ECCCURVE_TYPE preferredCurveID;\n\n\t\t\t/* If we're using pure PSK then there's no ECC information \n\t\t\t   (or a private key in general) available */\n\t\t\tif( sessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\thandshakeInfo->disableECC = TRUE;\n\t\t\t\treturn( sSkip( stream, extLength, MAX_INTLENGTH_SHORT ) );\n\t\t\t\t}\n\n\t\t\t/* Read and process the list of preferred curves */\n\t\t\tstatus = processSupportedCurveID( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\t\t\t\t  extLength, &preferredCurveID,\n\t\t\t\t\t\t\t\t\t\t\t  extErrorInfoSet );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\n\t\t\t/* If we couldn't find a curve that we have in common with the \n\t\t\t   other side, disable the use of ECC algorithms.  This is a \n\t\t\t   somewhat nasty failure mode because it means that something \n\t\t\t   like a buggy implementation that sends the wrong hello \n\t\t\t   extension (which is rather more likely than, say, an \n\t\t\t   implementation not supporting the de facto universal-standard \n\t\t\t   NIST curves) means that the crypto is quietly switched to \n\t\t\t   non-ECC with the user being none the wiser, but there's no \n\t\t\t   way for an implementation to negotiate ECC-only encryption */\n\t\t\tif( preferredCurveID == CRYPT_ECCCURVE_NONE )\n\t\t\t\thandshakeInfo->disableECC = TRUE;\n\t\t\telse\n\t\t\t\thandshakeInfo->eccCurveID = preferredCurveID;\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tcase TLS_EXT_EC_POINT_FORMATS:\n\t\t\t/* We don't really need to process this extension because every \n\t\t\t   implementation is required to support uncompressed points (it \n\t\t\t   also seems to be the universal standard that everyone uses by \n\t\t\t   default anyway) so all that we do is treat the presence of \n\t\t\t   the overall extension as an indicator that we should send \n\t\t\t   back our own one in the server hello:\n\n\t\t\t\tbyte\t\tpointFormatListLength\n\t\t\t\tbyte[]\t\tpointFormat */\n\t\t\tif( extLength > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = sSkip( stream, extLength, MAX_INTLENGTH_SHORT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\thandshakeInfo->sendECCPointExtn = TRUE;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase TLS_EXT_SIGNATURE_ALGORITHMS:\n\t\t\t/* Read and process the list of signature algorithms */\n\t\t\treturn( processSignatureAlgos( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t\t   stream, extLength, \n\t\t\t\t\t\t\t\t\t\t   extErrorInfoSet ) );\n\n\t\tcase TLS_EXT_SECURE_RENEG:\n\t\t\t/* If we get a nonzero length for this extension (the '1' is the \n\t\t\t   initial length byte at the start) then it's an indication of \n\t\t\t   an attack.  The status code to return here is a bit \n\t\t\t   uncertain, but CRYPT_ERROR_INVALID seems to be the least\n\t\t\t   inappropriate */\n\t\t\tif( extLength != 1 || sgetc( stream ) != 0 )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t\t/* If we're the server, remember that we have to echo the \n\t\t\t   extension back to the client */\n\t\t\tif( isServer( sessionInfoPtr ) )\n\t\t\t\thandshakeInfo->needRenegResponse = TRUE;\n\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase TLS_EXT_ENCTHENMAC:\n\t\t\tif( extLength != 0 )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t\t/* Turn on enrypt-then-MAC and, if we're the server, rememeber \n\t\t\t   that we have to echo the extension back to the client */\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC );\n\t\t\tif( isServer( sessionInfoPtr ) )\n\t\t\t\thandshakeInfo->needEncThenMACResponse = TRUE;\n\t\t\t\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase TLS_EXT_EMS:\n\t\t\tif( extLength != 0 )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t\t/* Turn on extended master secret use */\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS );\n\t\t\tif( isServer( sessionInfoPtr ) )\n\t\t\t\thandshakeInfo->needEMSResponse = TRUE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tcase TLS_EXT_TLS12LTS:\n\t\t\tif( extLength != 0 )\n\t\t\t\treturn( CRYPT_ERROR_INVALID );\n\n\t\t\t/* Turn on TLS 1.2 LTS use.  This option implicitly includes \n\t\t\t   encrypt-then-MAC and extended master secret, but we can't set \n\t\t\t   these yet since that would result in us sending spurious \n\t\t\t   response extensions if LTS was present in a request but the \n\t\t\t   others weren't */\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS );\n\t\t\tif( isServer( sessionInfoPtr ) )\n\t\t\t\thandshakeInfo->needTLS12LTSResponse = TRUE;\n\t\t\treturn( CRYPT_OK );\n\n\t\tdefault:\n\t\t\t/* Default: Ignore the extension */\n\t\t\tif( extLength > 0 )\n\t\t\t\t{\n\t\t\t\tstatus = sSkip( stream, extLength, MAX_INTLENGTH_SHORT );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\treturn( CRYPT_OK );\n\t\t}\n\n\tretIntError();\n\t}\n\n/* Read TLS extensions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint readExtensions( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\tIN_LENGTH_SHORT const int length )\n\t{\n\tconst int endPos = stell( stream ) + length;\n\tint extensionSeen[ 16 + 8 ];\n\tint extListLen, noExtensions, extensionSeenLast = 0;\n\tint status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\tREQUIRES( isShortIntegerRangeNZ( endPos ) );\n\n\t/* Read the extension header and make sure that it's valid:\n\n\t\tuint16\t\textListLen\n\t\t\tuint16\textType\n\t\t\tuint16\textLen\n\t\t\tbyte[]\textData \n\n\t   We can get a single zero-length extension for both client and server, \n\t   for the server it's a session-ticket request sent by the client, for \n\t   the client it's a zero-length SNI sent by the server for no \n\t   immediately obvious purpose in response to our SNI, so we can't take \n\t   the precaution of requiring at least one byte of payload data as a \n\t   sanity check */\n\tif( length < UINT16_SIZE + UINT16_SIZE + UINT16_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"TLS hello contains %d bytes extraneous data\", length ) );\n\t\t}\n\tstatus = extListLen = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid TLS extension information\" ) );\n\t\t}\n\tif( extListLen != length - UINT16_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid TLS extension data length %d, should be %d\",\n\t\t\t\t  extListLen, length - UINT16_SIZE ) );\n\t\t}\n\n\t/* Process the extensions */\n\tLOOP_MED( noExtensions = 0,\n\t\t\t  stell( stream ) < endPos && noExtensions < MAX_EXTENSIONS, \n\t\t\t  noExtensions++ )\n\t\t{\n\t\tconst EXT_CHECK_INFO *extCheckInfoPtr = NULL;\n\t\tBOOLEAN extErrorInfoSet;\n\t\tint type, extLen DUMMY_INIT, i, LOOP_ITERATOR_ALT;\n\n\t\t/* Read the header for the next extension and get the extension-\n\t\t   checking information.  The length check at this point is just a\n\t\t   generic sanity check, more specific checking is done once we've \n\t\t   got the extension type-specific information */\n\t\tstatus = type = readUint16( stream );\n\t\tif( !cryptStatusError( status ) )\t/* For static analysers */\n\t\t\tstatus = extLen = readUint16( stream );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\t!isShortIntegerRange( extLen ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid TLS extension list item header\" ) );\n\t\t\t}\n\t\tLOOP_MED_ALT( i = 0,\n\t\t\t\t\t  extCheckInfoTbl[ i ].type != CRYPT_ERROR && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( extCheckInfoTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\tEXT_CHECK_INFO ), \n\t\t\t\t\t  i++ )\n\t\t\t{\n\t\t\tif( extCheckInfoTbl[ i ].type == type )\n\t\t\t\t{\n\t\t\t\textCheckInfoPtr = &extCheckInfoTbl[ i ];\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( extCheckInfoTbl, EXT_CHECK_INFO ) ); \n\t\tif( extCheckInfoPtr != NULL )\n\t\t\t{\n\t\t\tconst int minLength = isServer( sessionInfoPtr ) ? \\\n\t\t\t\t\t\textCheckInfoPtr->minLengthClient : \\\n\t\t\t\t\t\textCheckInfoPtr->minLengthServer;\n\n\t\t\t/* Perform any necessary initial checking of the extension */\n\t\t\tif( minLength == CRYPT_ERROR )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Received disallowed TLS %s extension from %s\", \n\t\t\t\t\t\t  extCheckInfoPtr->description, \n\t\t\t\t\t\t  isServer( sessionInfoPtr ) ? \"server\" : \"client\" ) );\n\t\t\t\t}\n\t\t\tif( extLen < minLength || extLen > extCheckInfoPtr->maxLength )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid TLS %s extension length %d, should be \"\n\t\t\t\t\t\t  \"%d...%d\", extCheckInfoPtr->description, extLen,\n\t\t\t\t\t\t  minLength, extCheckInfoPtr->maxLength ) );\n\t\t\t\t}\n\n\t\t\t/* Make sure that we haven't already seen this extension.  Note \n\t\t\t   that we only perform this check for known extensions, since \n\t\t\t   we don't know whether new/unknown extensions may be allowed \n\t\t\t   in duplicate form or not */\n\t\t\tLOOP_EXT_ALT( i = 0, i < extensionSeenLast && i < 16, i++, 17 )\n\t\t\t\t{\n\t\t\t\tif( extensionSeen[ i ] == type )\n\t\t\t\t\t{\n\t\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t\t  \"Duplicate TLS %s extension encountered\", \n\t\t\t\t\t\t\t  extCheckInfoPtr->description ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tif( extensionSeenLast < 16 )\n\t\t\t\textensionSeen[ extensionSeenLast++ ] = type;\n\t\t\t}\n\t\tDEBUG_PRINT(( \"Read extension %s (%d), length %d.\\n\",\n\t\t\t\t\t  ( extCheckInfoPtr != NULL ) ? \\\n\t\t\t\t\t\textCheckInfoPtr->description : \"<Unknown>\", \n\t\t\t\t\t  type, extLen ));\n\t\tDEBUG_DUMP_STREAM( stream, stell( stream ), extLen );\n\n\t\t/* Process the extension data */\n\t\tstatus = processExtension( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t\t   type, extLen, &extErrorInfoSet );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( isInternalError( status ) )\n\t\t\t\t{\n\t\t\t\t/* If it's an internal error then we can't rely on the value\n\t\t\t\t   of the by-reference parameters */\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tif( extErrorInfoSet )\n\t\t\t\treturn( status );\n\t\t\tif( extCheckInfoPtr != NULL )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid TLS %s extension data\", \n\t\t\t\t\t\t  extCheckInfoPtr->description ) );\n\t\t\t\t}\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid TLS extension data for extension \"\n\t\t\t\t\t  \"type %d\", type ) );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tif( noExtensions >= MAX_EXTENSIONS )\n\t\t{\n\t\tretExt( CRYPT_ERROR_OVERFLOW,\n\t\t\t\t( CRYPT_ERROR_OVERFLOW, SESSION_ERRINFO, \n\t\t\t\t  \"Excessive number (more than %d) of TLS extensions \"\n\t\t\t\t  \"encountered\", noExtensions ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite TLS Extensions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write the list of supported signature and hash algorithms as a \n   combinatorial explosion of { hash, sig } algorithm pairs (they're called\n   SignatureAndHashAlgorithm in the spec, but are actually encoded as\n   HashAndSignatureAlgorithm).  This is used both for extensions and for the \n   TLS 1.2 signature format.\n   \n   This gets a bit complicated because we both have to emit the values in\n   preferred-algorithm order and some combinations aren't available, so \n   instead of simply iterating down two lists we have to exhaustively\n   enumerate each possible algorithm combination.\n\n   We disallow SHA1 (except for DSA where it's needed due to the hardcoding\n   into the signature format) since the whole point of TLS 1.2 was to move \n   away from it, and a poll on the ietf-tls list indicated that all known \n   implementations (both of them) work fine with this configuration */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int writeSigHashAlgoList( STREAM *stream )\n\t{\n\ttypedef struct {\n\t\tCRYPT_ALGO_TYPE sigAlgo, hashAlgo;\n\t\tTLS_SIGALGO_TYPE tlsSigAlgoID;\n\t\tTLS_HASHALGO_TYPE tlsHashAlgoID;\n\t\t} SIG_HASH_INFO;\n\tstatic const SIG_HASH_INFO algoTbl[] = {\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHAng, \n\t\t  TLS_SIGALGO_RSA, 255 },\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA2, \n\t\t  TLS_SIGALGO_RSA, TLS_HASHALGO_SHA2 },\n#if 0\t/* 2/11/11 Disabled option for SHA1 after poll on ietf-tls list */\n\t\t{ CRYPT_ALGO_RSA, CRYPT_ALGO_SHA1, \n\t\t  TLS_SIGALGO_RSA, TLS_HASHALGO_SHA1 },\n#endif /* 0 */\n\t\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHAng, \n\t\t  TLS_SIGALGO_DSA, 255 },\n\t\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA2, \n\t\t  TLS_SIGALGO_DSA, TLS_HASHALGO_SHA2 },\n\t\t{ CRYPT_ALGO_DSA, CRYPT_ALGO_SHA1, \n\t\t  TLS_SIGALGO_DSA, TLS_HASHALGO_SHA1 },\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHAng, \n\t\t  TLS_SIGALGO_ECDSA, 255 },\n#ifdef CONFIG_SUITEB\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, \n\t\t  TLS_SIGALGO_ECDSA, TLS_HASHALGO_SHA384 },\n#endif /* CONFIG_SUITEB */\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA2, \n\t\t  TLS_SIGALGO_ECDSA, TLS_HASHALGO_SHA2 },\n#if 0\t/* 2/11/11 Disabled option for SHA1 after poll on ietf-tls list */\n\t\t{ CRYPT_ALGO_ECDSA, CRYPT_ALGO_SHA1, \n\t\t  TLS_SIGALGO_ECDSA, TLS_HASHALGO_SHA1 },\n#endif /* 0 */\n\t\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, TLS_SIGALGO_NONE }, \n\t\t\t{ CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, TLS_SIGALGO_NONE }\n\t\t};\n\tBYTE algoList[ 32 + 8 ];\n\tint algoIndex = 0, i, LOOP_ITERATOR;\n\n\t/* Determine which signature and hash algorithms are available for use */\n\tLOOP_MED( i = 0, algoTbl[ i ].sigAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t\t\t i < FAILSAFE_ARRAYSIZE( algoTbl, SIG_HASH_INFO ), i++ )\n\t\t{\n\t\tconst CRYPT_ALGO_TYPE sigAlgo = algoTbl[ i ].sigAlgo;\n\t\tint LOOP_ITERATOR_ALT;\n\n\t\t/* If the given signature algorithm isn't enabled, skip any further\n\t\t   occurrences of this algorithm */\n\t\tif( !algoAvailable( sigAlgo ) )\n\t\t\t{\n\t\t\tLOOP_MED_CHECKINC_ALT( algoTbl[ i ].sigAlgo == sigAlgo && \\\n\t\t\t\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( algoTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSIG_HASH_INFO ),\n\t\t\t\t\t\t\t\t   i++ );\n\t\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\t\tENSURES( i < FAILSAFE_ARRAYSIZE( algoTbl, SIG_HASH_INFO ) );\n\t\t\ti--;\t/* Adjust for increment also done in outer loop */\n\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* If the hash algorithm isn't enabled, skip this entry */\n\t\tif( !algoAvailable( algoTbl[ i ].hashAlgo ) )\n\t\t\tcontinue;\n\n\t\t/* Add the TLS IDs for this signature and hash algorithm combination.  \n\t\t   Although the record is called SignatureAndHashAlgorithm, what's \n\t\t   written first is the hash algorithm and not the signature \n\t\t   algorithm */\n\t\talgoList[ algoIndex++ ] = intToByte( algoTbl[ i ].tlsHashAlgoID );\n\t\talgoList[ algoIndex++ ] = intToByte( algoTbl[ i ].tlsSigAlgoID );\n\t\tENSURES( algoIndex <= 32 );\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( algoTbl, SIG_HASH_INFO ) );\n\n\t/* Write the combination of hash and signature algorithms */\n\twriteUint16( stream, algoIndex );\n\treturn( swrite( stream, algoList, algoIndex ) );\n\t}\n\n/* Write the server name indication (SNI) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeServerName( INOUT STREAM *stream,\n\t\t\t\t\t\t\tINOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst ATTRIBUTE_LIST *serverNamePtr = \\\n\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_SERVER_NAME );\n\tURL_INFO urlInfo;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( serverNamePtr != NULL );\n\n\t/* Extract the server FQDN from the overall server name value */\n\tstatus = sNetParseURL( &urlInfo, serverNamePtr->value, \n\t\t\t\t\t\t   serverNamePtr->valueLength, URL_TYPE_HTTPS );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the server name */\n\twriteUint16( stream, 1 + UINT16_SIZE + urlInfo.hostLen );\n\tsputc( stream, 0 );\t\t/* Type = DNS name */\n\twriteUint16( stream, urlInfo.hostLen );\n\treturn( swrite( stream, urlInfo.host, urlInfo.hostLen ) );\n\t}\n\n/* Write TLS extensions */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeClientExtensions( INOUT STREAM *stream,\n\t\t\t\t\t\t   INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tSTREAM nullStream;\n\tconst void *eccCurveInfoPtr DUMMY_INIT_PTR;\n\tconst BOOLEAN hasServerName = \\\n\t\t\t\t( findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_SERVER_NAME ) != NULL ) ? \\\n\t\t\t\tTRUE : FALSE;\n\tint serverNameHdrLen = 0, serverNameExtLen = 0;\n\tint sigHashHdrLen = 0, sigHashExtLen = 0;\n\tint eccCurveTypeLen DUMMY_INIT, eccInfoLen = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS );\n\n\t/* Determine the overall length of the extension data, first the server \n\t   name indication (SNI) if it's present (it may not be if we're using\n\t   a raw network socket) */\n\tif( hasServerName )\n\t\t{\n\t\tsMemNullOpen( &nullStream );\n\t\tstatus = writeServerName( &nullStream, sessionInfoPtr );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tserverNameHdrLen = UINT16_SIZE + UINT16_SIZE;\n\t\t\tserverNameExtLen = stell( &nullStream );\n\t\t\t}\n\t\tsMemClose( &nullStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Signature and hash algorithms.  These are only used with TLS 1.2+ so \n\t   we only write them if we're using these versions of the protocol */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tsMemNullOpen( &nullStream );\n\t\tstatus = writeSigHashAlgoList( &nullStream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsigHashHdrLen = UINT16_SIZE + UINT16_SIZE;\n\t\t\tsigHashExtLen = stell( &nullStream );\n\t\t\t}\n\t\tsMemClose( &nullStream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* ECC information.  This is only sent if we're proposing ECC suites in\n\t   the client hello */\n\tif( algoAvailable( CRYPT_ALGO_ECDH ) )\n\t\t{\n\t\tstatic const BYTE eccCurveInfo[] = {\n\t\t\t0, TLS_CURVE_BRAINPOOLP512R1, 0, TLS_CURVE_BRAINPOOLP384R1,\n\t\t\t0, TLS_CURVE_BRAINPOOLP256R1,\n\t\t\t0, TLS_CURVE_SECP521R1, 0, TLS_CURVE_SECP384R1, \n\t\t\t0, TLS_CURVE_SECP256R1, 0, TLS_CURVE_SECP224R1, \n\t\t\t0, TLS_CURVE_SECP192R1, 0, 0 \n\t\t\t};\n\t\tstatic const int eccCurveCount = 8;\n\n#ifdef CONFIG_SUITEB\n\t\tif( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )\n\t\t\t{\n\t\t\tstatic const BYTE eccCurveSuiteB128Info[] = {\n\t\t\t\t0, TLS_CURVE_SECP256R1, 0, TLS_CURVE_SECP384R1, 0, 0 \n\t\t\t\t};\n\t\t\tstatic const BYTE eccCurveSuiteB256Info[] = {\n\t\t\t\t0, TLS_CURVE_SECP384R1, 0, 0 \n\t\t\t\t};\n\t\t\tconst int suiteBinfo = \\\n\t\t\t\t\tsessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;\n\n\t\t\tif( suiteBinfo == SSL_PFLAG_SUITEB_128 )\n\t\t\t\t{\n\t\t\t\teccCurveInfoPtr = eccCurveSuiteB128Info;\n\t\t\t\teccCurveTypeLen = 2 * UINT16_SIZE;\n\t\t\t\t}\n\t\t\telse\t\t\t\t\n\t\t\t\t{\n\t\t\t\teccCurveInfoPtr = eccCurveSuiteB256Info;\n\t\t\t\teccCurveTypeLen = UINT16_SIZE;\n\t\t\t\t}\n  #ifdef CONFIG_SUITEB_TESTS \n\t\t\t/* In some cases for test purposes we have to send invalid ECC\n\t\t\t   information */\n\t\t\tif( suiteBTestValue == SUITEB_TEST_CLIINVALIDCURVE )\n\t\t\t\t{\n\t\t\t\tstatic const BYTE eccCurveSuiteBInvalidInfo[] = {\n\t\t\t\t\t0, TLS_CURVE_SECP521R1, 0, 0, TLS_CURVE_SECP192R1, 0, 0 \n\t\t\t\t\t};\n\n\t\t\t\teccCurveInfoPtr = eccCurveSuiteBInvalidInfo;\n\t\t\t\teccCurveTypeLen = 2 * UINT16_SIZE;\n\t\t\t\t}\n  #endif /* CONFIG_SUITEB_TESTS  */\n\t\t\t}\n\t\telse\n#endif /* CONFIG_SUITEB */\n\t\t\t{\n\t\t\teccCurveInfoPtr = eccCurveInfo;\n\t\t\teccCurveTypeLen = eccCurveCount * UINT16_SIZE;\n\t\t\t}\n\t\teccInfoLen = UINT16_SIZE + UINT16_SIZE + \\\n\t\t\t\t\t UINT16_SIZE + eccCurveTypeLen;\n\t\teccInfoLen += UINT16_SIZE + UINT16_SIZE + 1 + 1;\n\t\t}\n\n\t/* Write the list of extensions */\n\twriteUint16( stream, serverNameHdrLen + serverNameExtLen + \\\n\t\t\t\t\t\t RENEG_EXT_SIZE +\t\t\t\t\t/* Renegotiation */\n\t\t\t\t\t\t ( UINT16_SIZE + UINT16_SIZE ) +\t/* EncThenMAC */\n\t\t\t\t\t\t ( UINT16_SIZE + UINT16_SIZE ) +\t/* Extended MS */\n\t\t\t\t\t\t ( UINT16_SIZE + UINT16_SIZE ) +\t/* TLS 1.2 LTS */\n\t\t\t\t\t\t sigHashHdrLen + sigHashExtLen + eccInfoLen );\n\tif( hasServerName )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_SERVER_NAME );\n\t\twriteUint16( stream, serverNameExtLen );\n\t\tstatus = writeServerName( stream, sessionInfoPtr );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension server name indication (%d), length %d.\\n\",\n\t\t\t\t\t  TLS_EXT_SERVER_NAME, serverNameExtLen ));\n\t\tDEBUG_DUMP_STREAM( stream, stell( stream ) - serverNameExtLen, \n\t\t\t\t\t\t   serverNameExtLen );\n\t\t}\n\tstatus = swrite( stream, RENEG_EXT_DATA, RENEG_EXT_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_PRINT(( \"Wrote extension secure renegotiation (%d), length 1.\\n\",\n\t\t\t\t  TLS_EXT_SECURE_RENEG ));\n\tDEBUG_DUMP_STREAM( stream, stell( stream ) - 1, 1 );\n\twriteUint16( stream, TLS_EXT_ENCTHENMAC );\n\tstatus = writeUint16( stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_PRINT(( \"Wrote extension encrypt-then-MAC (%d), length 0.\\n\",\n\t\t\t\t  TLS_EXT_ENCTHENMAC ));\n\twriteUint16( stream, TLS_EXT_EMS );\n\tstatus = writeUint16( stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_PRINT(( \"Wrote extension extended Master Secret (%d), length 0.\\n\",\n\t\t\t\t  TLS_EXT_EMS ));\n\twriteUint16( stream, TLS_EXT_TLS12LTS );\n\tstatus = writeUint16( stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_PRINT(( \"Wrote extension TLS 1.2 LTS (%d), length 0.\\n\",\n\t\t\t\t  TLS_EXT_TLS12LTS ));\n\tif( sigHashExtLen > 0 )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_SIGNATURE_ALGORITHMS );\n\t\twriteUint16( stream, sigHashExtLen );\n\t\tstatus = writeSigHashAlgoList( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension signature algorithm (%d), length %d.\\n\",\n\t\t\t\t\t  TLS_EXT_SIGNATURE_ALGORITHMS, sigHashExtLen ));\n\t\tDEBUG_DUMP_STREAM( stream, \n\t\t\t\t\t\t   stell( stream ) - sigHashExtLen, sigHashExtLen );\n\t\t}\n\tif( eccInfoLen > 0 )\n\t\t{\n\t\t/* Write the ECC curve type extension */\n\t\twriteUint16( stream, TLS_EXT_ELLIPTIC_CURVES );\n\t\twriteUint16( stream, UINT16_SIZE + eccCurveTypeLen );/* Ext.len */\n\t\twriteUint16( stream, eccCurveTypeLen );\t\t/* Curve list len.*/\n\t\tstatus = swrite( stream, eccCurveInfoPtr, eccCurveTypeLen );\t\n\t\tif( cryptStatusError( status ) )\t\t\t/* Curve list */\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension ECC curve type (%d), length %d.\\n\",\n\t\t\t\t\t  TLS_EXT_ELLIPTIC_CURVES, eccCurveTypeLen ));\n\t\tDEBUG_DUMP_STREAM( stream, \n\t\t\t\t\t\t   stell( stream ) - ( UINT16_SIZE + eccCurveTypeLen ), \n\t\t\t\t\t\t   UINT16_SIZE + eccCurveTypeLen );\n\n\t\t/* Write the ECC point format extension */\n\t\twriteUint16( stream, TLS_EXT_EC_POINT_FORMATS );\n\t\twriteUint16( stream, 1 + 1 );\t\t\t/* Extn. length */\n\t\tsputc( stream, 1 );\t\t\t\t\t\t/* Point-format list len.*/\n\t\tstatus = sputc( stream, 0 );\t\t\t/* Uncompressed points */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension ECC point format (%d), length %d.\\n\",\n\t\t\t\t\t  TLS_EXT_EC_POINT_FORMATS, 1 + 1 ));\n\t\tDEBUG_DUMP_STREAM( stream, stell( stream ) - ( 1 + 1 ), 1 + 1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint writeServerExtensions( INOUT STREAM *stream,\n\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tint extListLen = 0, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\t/* Calculate the size of the extensions */\n\tif( isEccAlgo( handshakeInfo->keyexAlgo ) && \\\n\t\thandshakeInfo->sendECCPointExtn )\n\t\textListLen += UINT16_SIZE + UINT16_SIZE + 1 + 1;\n\tif( handshakeInfo->needSNIResponse )\n\t\textListLen += UINT16_SIZE + UINT16_SIZE;\n\tif( handshakeInfo->needRenegResponse )\n\t\textListLen += RENEG_EXT_SIZE;\n\tif( handshakeInfo->needEncThenMACResponse )\n\t\textListLen += UINT16_SIZE + UINT16_SIZE;\n\tif( handshakeInfo->needEMSResponse )\n\t\textListLen += UINT16_SIZE + UINT16_SIZE;\n\tif( handshakeInfo->needTLS12LTSResponse )\n\t\textListLen += UINT16_SIZE + UINT16_SIZE;\n\tif( extListLen <= 0 )\n\t\t{\n\t\t/* No extensions to write, we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Write the overall extension list length */\n\twriteUint16( stream, extListLen );\n\n\t/* If the client sent an SNI extension then we have to acknowledge it\n\t   with a zero-length SNI extension response.  This is slightly \n\t   dishonest because we haven't passed the SNI data back to the caller,\n\t   but SNI will (at some point in the future) be sent by default by \n\t   clients and since we're highly unlikely to be used with multihomed \n\t   servers but likely to be used in oddball environments like ones \n\t   without DNS we just accept any SNI and allow a connect.  SNI is \n\t   merely a courtesy notification to allow selection of the correct \n\t   server certificate for multihomed servers with the actual virtual-\n\t   host management being done via the HTTP Host: header, so not making \n\t   use of it isn't a real problem */\n\tif( handshakeInfo->needSNIResponse )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_SERVER_NAME );\n\t\tstatus = writeUint16( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension server name indication (%d), \"\n\t\t\t\t\t  \"length 0.\\n\", TLS_EXT_SERVER_NAME, 0 ));\n\t\t}\n\n\t/* If the client sent a secure-renegotiation indicator we have to send a\n\t   response even though we don't support renegotiation.  See the comment \n\t   by extCheckInfoTbl for why this odd behaviour is necessary */\n\tif( handshakeInfo->needRenegResponse )\n\t\t{\n\t\tstatus = swrite( stream, RENEG_EXT_DATA, RENEG_EXT_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension secure renegotiation (%d), length 1.\\n\",\n\t\t\t\t\t  TLS_EXT_SECURE_RENEG ));\n\t\tDEBUG_DUMP_STREAM( stream, stell( stream ) - 1, 1 );\n\t\t}\n\n\t/* If the client sent various request indicators, acknowledge them */\n\tif( handshakeInfo->needEncThenMACResponse )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_ENCTHENMAC );\n\t\tstatus = writeUint16( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension encrypt-then-MAC (%d), length 0.\\n\", \n\t\t\t\t\t  TLS_EXT_ENCTHENMAC, 0 ));\n\t\t}\n\tif( handshakeInfo->needEMSResponse )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_EMS );\n\t\tstatus = writeUint16( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension extended Master Secret (%d), length 0.\\n\", \n\t\t\t\t\t  TLS_EXT_EMS, 0 ));\n\t\t}\n\tif( handshakeInfo->needTLS12LTSResponse )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_TLS12LTS );\n\t\tstatus = writeUint16( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension TLS 1.2 LTS (%d), length 0.\\n\", \n\t\t\t\t\t  TLS_EXT_TLS12LTS, 0 ));\n\t\t}\n\n\t/* If the client sent ECC extensions and we've negotiated an ECC cipher \n\t   suite, send back the appropriate response.  We don't have to send \n\t   back the curve ID that we've chosen because this is communicated \n\t   explicitly in the server keyex */\n\tif( isEccAlgo( handshakeInfo->keyexAlgo ) && \\\n\t\thandshakeInfo->sendECCPointExtn )\n\t\t{\n\t\twriteUint16( stream, TLS_EXT_EC_POINT_FORMATS );\n\t\twriteUint16( stream, 1 + 1 );\t/* Extn. length */\n\t\tsputc( stream, 1 );\t\t\t\t/* Point-format list len.*/\n\t\tstatus = sputc( stream, 0 );\t/* Uncompressed points */\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tDEBUG_PRINT(( \"Wrote extension ECC point format (%d), length %d.\\n\",\n\t\t\t\t\t  TLS_EXT_EC_POINT_FORMATS, 1 + 1 ));\n\t\tDEBUG_DUMP_STREAM( stream, stell( stream ) - 1 + 1, 1 + 1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_hs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib TLS Hello Handshake Management\t\t\t\t\t*\n*\t\t\t\t\t  Copyright Peter Gutmann 1998-2009\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process a session ID */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processSessionID( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t INOUT STREAM *stream )\n\t{\n\tBYTE sessionID[ MAX_SESSIONID_SIZE + 8 ];\n\tint sessionIDlength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Get the session ID information */\n\tstatus = sessionIDlength = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid session ID information\" ) );\n\t\t}\n\tif( sessionIDlength <= 0 )\n\t\t{\n\t\t/* No session ID, we're done */\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( sessionIDlength < MIN_SESSIONID_SIZE || \\\n\t\tsessionIDlength > MAX_SESSIONID_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid session ID length %d, should be %d...%d\", \n\t\t\t\t  sessionIDlength, MIN_SESSIONID_SIZE, \n\t\t\t\t  MAX_SESSIONID_SIZE ) );\n\t\t}\n\tstatus = sread( stream, sessionID, sessionIDlength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid session ID data\" ) );\n\t\t}\n\n\t/* If we're the server and it's not (potentially) one of our sessionIDs, \n\t   we're done */\n\tif( isServer( sessionInfoPtr ) && sessionIDlength != SESSIONID_SIZE )\n\t\treturn( CRYPT_OK );\n\n\t/* It's a potentially resumed session, remember the details and let the \n\t   caller know */\n\tREQUIRES( rangeCheck( sessionIDlength, 1, MAX_SESSIONID_SIZE ) );\n\tmemcpy( handshakeInfo->sessionID, sessionID, sessionIDlength );\n\thandshakeInfo->sessionIDlength = sessionIDlength;\n\treturn( OK_SPECIAL );\n\t}\n\n#ifdef CONFIG_SUITEB\n\n/* For Suite B the first suite must be ECDHE/AES128-GCM/SHA256 or \n   ECDHE/AES256-GCM/SHA384 depending on the security level and the second\n   suite, at the 128-bit security level, must be ECDHE/AES256-GCM/SHA384.  \n   This is one of those pedantic checks that requires vastly more work to \n   support its nitpicking than the whole check is worth (since the same \n   thing is checked anyway when we check the suite strength), but it's \n   required by the spec */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 4 ) ) \\\nstatic int checkSuiteBSuiteSelection( IN_RANGE( SSL_FIRST_VALID_SUITE, \\\n\t\t\t\t\t\t\t\t\t\t\t\tSSL_LAST_SUITE - 1 ) \\\n\t\t\t\t\t\t\t\t\t\tconst int cipherSuite,\n\t\t\t\t\t\t\t\t\t  const int flags,\n\t\t\t\t\t\t\t\t\t  const BOOLEAN isFirstSuite,\n\t\t\t\t\t\t\t\t\t  INOUT ERROR_INFO *errorInfo )\n\t{\n\tconst char *precedenceString = isFirstSuite ? \"First\" : \"Second\";\n\tconst char *suiteName = NULL;\n\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( cipherSuite >= SSL_FIRST_VALID_SUITE && \\\n\t\t\t  cipherSuite < SSL_LAST_SUITE );\n\tREQUIRES( ( flags & ~( SSL_PFLAG_SUITEB ) ) == 0 );\n\tREQUIRES( isFirstSuite == TRUE || isFirstSuite == FALSE );\n\n\tif( isFirstSuite )\n\t\t{\n\t\tswitch( flags )\n\t\t\t{\n\t\t\tcase SSL_PFLAG_SUITEB_128:\n\t\t\t\tif( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 )\n\t\t\t\t\tsuiteName = \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\";\n\t\t\t\tbreak;\n\n\t\t\tcase SSL_PFLAG_SUITEB_256:\n\t\t\t\tif( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )\n\t\t\t\t\tsuiteName = \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\";\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tswitch( flags )\n\t\t\t{\n\t\t\tcase SSL_PFLAG_SUITEB_128:\n\t\t\t\tif( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )\n\t\t\t\t\tsuiteName = \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\";\n\t\t\t\tbreak;\n\n\t\t\tcase SSL_PFLAG_SUITEB_256:\n\t\t\t\t/* For the 256-bit level there are no further requirements */\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tretIntError();\n\t\t\t}\n\t\t}\n\tif( suiteName != NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, errorInfo, \n\t\t\t\t  \"%s cipher suite for Suite B at the %d-bit security \"\n\t\t\t\t  \"level must be %s\", precedenceString, \n\t\t\t\t  ( flags == SSL_PFLAG_SUITEB_128 ) ? 128 : 256, \n\t\t\t\t  suiteName ) );\n\t\t}\n\n\t/* At the 256-bit level there's an additional requirement that the \n\t   client not offer any P256 cipher suites, or specifically that it not\n\t   offer the one P256 cipher suite allowed for Suite B (whether it can \n\t   offer non-Suite B P256 cipher suites is left ambiguous) */\n\tif( flags == SSL_PFLAG_SUITEB_256 && \\\n\t\tcipherSuite == TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, errorInfo, \n\t\t\t\t  \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher suite \"\n\t\t\t\t  \"can't be offered at the 256-bit security level\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_SUITEB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNegotiate a Cipher Suite\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set up the crypto information based on the cipher suite */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int setSuiteInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t const CIPHERSUITE_INFO *cipherSuiteInfoPtr )\n\t{\n\tCRYPT_QUERY_INFO queryInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtr( cipherSuiteInfoPtr, sizeof( CIPHERSUITE_INFO ) ) );\n\n\thandshakeInfo->cipherSuite = cipherSuiteInfoPtr->cipherSuite;\n\thandshakeInfo->keyexAlgo = cipherSuiteInfoPtr->keyexAlgo;\n\thandshakeInfo->authAlgo = cipherSuiteInfoPtr->authAlgo;\n\thandshakeInfo->cryptKeysize = cipherSuiteInfoPtr->cryptKeySize;\n\tsessionInfoPtr->cryptAlgo = cipherSuiteInfoPtr->cryptAlgo;\n\tsessionInfoPtr->integrityAlgo = cipherSuiteInfoPtr->macAlgo;\n\thandshakeInfo->integrityAlgoParam = cipherSuiteInfoPtr->macParam;\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\t/* SSL uses a proto-HMAC which requires that we synthesize it from\n\t\t   raw hash functionality */\n\t\tsessionInfoPtr->integrityAlgo = CRYPT_ALGO_SHA1;\n\t\t}\n#endif /* USE_SSL3 */\n\tsessionInfoPtr->authBlocksize = cipherSuiteInfoPtr->macBlockSize;\n\tif( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_GCM )\n\t\t{\n\t\t/* GCM is a stream cipher with special-case requirements */\n\t\tsessionInfoPtr->cryptBlocksize = 1;\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a standard cipher, get the block size */\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,\n\t\t\t\t\t\t\t\t  sessionInfoPtr->cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tsessionInfoPtr->cryptBlocksize = queryInfo.blockSize;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Choose the best cipher suite from a list of suites */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processCipherSuite( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t\t\t   IN_RANGE( 1, MAX_CIPHERSUITES ) \\\n\t\t\t\t\t\t\t\t\tconst int noSuites )\n\t{\n\tconst CIPHERSUITE_INFO **cipherSuiteInfo;\n\tconst BOOLEAN isServer = isServer( sessionInfoPtr ) ? TRUE : FALSE;\n\tBOOLEAN allowDH = algoAvailable( CRYPT_ALGO_DH ) ? TRUE : FALSE;\n\tBOOLEAN allowECC = ( algoAvailable( CRYPT_ALGO_ECDH ) && \\\n\t\t\t\t\t\t algoAvailable( CRYPT_ALGO_ECDSA ) ) ? TRUE : FALSE;\n\tBOOLEAN allowRSA = algoAvailable( CRYPT_ALGO_RSA ) ? TRUE : FALSE;\n\tBOOLEAN allowTLS12 = \\\n\t\t( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 ) ? TRUE : FALSE;\n\tint cipherSuiteInfoSize, suiteIndex = 999, altSuiteIndex = 999;\n\tint i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( noSuites > 0 && noSuites <= MAX_CIPHERSUITES );\n\n\t/* Get the information for the supported cipher suites */\n\tstatus = getCipherSuiteInfo( &cipherSuiteInfo, &cipherSuiteInfoSize );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're the server then our choice of possible suites is constrained \n\t   by the server key that we're using, figure out what we can use */\n\tif( isServer )\n\t\t{\n\t\tif( sessionInfoPtr->privateKey == CRYPT_ERROR )\n\t\t\t{\n\t\t\t/* There's no server private key present, we're limited to PSK\n\t\t\t   suites */\n\t\t\tallowECC = allowRSA = FALSE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint pkcAlgo;\n\n\t\t\t/* To be usable for DH/ECC the server key has to be signature-\n\t\t\t   capable */\n\t\t\tif( !checkContextCapability( sessionInfoPtr->privateKey,\n\t\t\t\t\t\t\t\t\t\t MESSAGE_CHECK_PKC_SIGN ) )\n\t\t\t\tallowDH = allowECC = FALSE;\n\n\t\t\t/* To be usable for ECC or RSA the server key has to itself be \n\t\t\t   an ECC or RSA key */\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->privateKey, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &pkcAlgo,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_ALGO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tallowECC = allowRSA = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !isEccAlgo( pkcAlgo ) )\n\t\t\t\t\tallowECC = FALSE;\n\t\t\t\tif( pkcAlgo != CRYPT_ALGO_RSA )\n\t\t\t\t\tallowRSA = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tLOOP_EXT( i = 0, i < noSuites, i++, MAX_CIPHERSUITES + 1 )\n\t\t{\n\t\tconst CIPHERSUITE_INFO *cipherSuiteInfoPtr = NULL;\n\t\tint newSuite, newSuiteIndex, LOOP_ITERATOR_ALT;\n\n\t\t/* Get the cipher suite information */\n\t\tstatus = newSuite = readUint16( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status,\n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid cipher suite information\" ) );\n\t\t\t}\n\n\t\t/* If it's an obviously non-valid suite, continue */\n\t\tif( newSuite < SSL_FIRST_VALID_SUITE || newSuite >= SSL_LAST_SUITE )\n\t\t\tcontinue;\n\n\t\t/* If it's a signalling suite, handle it specially */\n\t\tif( isSignallingSuite( newSuite ) )\n\t\t\t{\n\t\t\tconst PROTOCOL_INFO *protocolInfo = \\\n\t\t\t\t\t\t\tDATAPTR_GET( sessionInfoPtr->protocolInfo );\n\n\t\t\tENSURES( protocolInfo != NULL );\n\n\t\t\tswitch( newSuite )\n\t\t\t\t{\n\t\t\t\tcase TLS_EMPTY_RENEGOTIATION_INFO_SCSV:\n\t\t\t\t\t/* If the client is signalling its support for secure \n\t\t\t\t\t   renegotiation, remember that we have to acknowledge \n\t\t\t\t\t   this in our response.  In theory this shouldn't be\n\t\t\t\t\t   necessary since the renegotiation information is \n\t\t\t\t\t   handled through a TLS extension, but OpenSSL uses an\n\t\t\t\t\t   SCSV instead of the extension for no obvious reason */\n\t\t\t\t\tif( isServer )\n\t\t\t\t\t\thandshakeInfo->needRenegResponse = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase TLS_FALLBACK_SCSV:\n\t\t\t\t\t/* If the client has fallen back to a lower version and \n\t\t\t\t\t   has indicated this to us, and if this version is \n\t\t\t\t\t   lower than what we'd normally be using, abort the\n\t\t\t\t\t   handshake with an insecure-fallback alert */\n\t\t\t\t\tif( isServer && \\\n\t\t\t\t\t\thandshakeInfo->clientOfferedVersion < \\\n\t\t\t\t\t\t\t\t\t\t\t\tprotocolInfo->maxVersion )\n\t\t\t\t\t\t{\n\t\t\t\t\t\thandshakeInfo->failAlertType = \\\n\t\t\t\t\t\t\t\t\t\t\tTLS_ALERT_INAPPROPRIATE_FALLBACK;\n\t\t\t\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t\t\t\t  \"Client attempted insecure falback from \"\n\t\t\t\t\t\t\t\t  \"protocol version %d to version %d\",\n\t\t\t\t\t\t\t\t  protocolInfo->maxVersion,\n\t\t\t\t\t\t\t\t  handshakeInfo->clientOfferedVersion ) );\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Signalling suites aren't standard cipher suites so we don't \n\t\t\t   try and process anything else that we don't recognise */\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* When resuming a cached session the client is required to offer\n\t\t   as one of its suites the original suite that was used.  There's\n\t\t   no good reason for this requirement (it's probable that the spec\n\t\t   is intending that there be at least one cipher suite and that if\n\t\t   there's only one it should really be the one originally\n\t\t   negotiated) and it complicates implementation of shared-secret\n\t\t   key sessions so we don't perform this check */\n\n\t\t/* Try and find the information for the proposed cipher suite */\n\t\tLOOP_EXT_ALT( newSuiteIndex = 0, \n\t\t\t\t\t  newSuiteIndex < cipherSuiteInfoSize && \\\n\t\t\t\t\t\tcipherSuiteInfo[ newSuiteIndex ]->cipherSuite != SSL_NULL_WITH_NULL,\n\t\t\t\t\t  newSuiteIndex++, MAX_CIPHERSUITES + 1 )\n\t\t\t{\n\t\t\tif( cipherSuiteInfo[ newSuiteIndex ]->cipherSuite == newSuite )\n\t\t\t\t{\n\t\t\t\tcipherSuiteInfoPtr = cipherSuiteInfo[ newSuiteIndex ];\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK_ALT );\n\t\tENSURES( newSuiteIndex < cipherSuiteInfoSize );\n#ifdef CONFIG_SUITEB\n\t\tif( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB ) && \\\n\t\t\t( i == 0 || i == 1 ) )\n\t\t\t{\n\t\t\tstatus = checkSuiteBSuiteSelection( \\\n\t\t\t\t\t\t\t( cipherSuiteInfoPtr == NULL ) ? \\\n\t\t\t\t\t\t\t\tSSL_FIRST_VALID_SUITE /* Dummy value */ : \\\n\t\t\t\t\t\t\t\tcipherSuiteInfoPtr->cipherSuite,\n\t\t\t\t\t\t\tsessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB,\n\t\t\t\t\t\t\t( i == 0 ) ? TRUE : FALSE, SESSION_ERRINFO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n#endif /* CONFIG_SUITEB */\n\t\tif( cipherSuiteInfoPtr == NULL )\n\t\t\tcontinue;\n\t\tDEBUG_PRINT(( \"Offered suite: %s.\\n\", \n\t\t\t\t\t  cipherSuiteInfoPtr->description ));\n\n\t\t/* Perform a short-circuit check, if the new suite is inherently \n\t\t   less-preferred than what we've already got then there's no point \n\t\t   to performing any of the remaining checks since it'll never be\n\t\t   selected */\n\t\tif( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC )\n\t\t\t{\n\t\t\tif( newSuiteIndex > altSuiteIndex )\n\t\t\t\tcontinue;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( newSuiteIndex > suiteIndex )\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Make sure that the required algorithms are available.  If we're\n\t\t   using TLS-PSK then there's no authentication algorithm because \n\t\t   the exchange is authenticated using the PSK.  We don't have to \n\t\t   check the keyex algorithm because that's handled via the \n\t\t   algorithm-class check below except for RSA, which is implicitly\n\t\t   checked by the fact that it's also used for the (checked) \n\t\t   authentication algorithm */\n\t\tif( cipherSuiteInfoPtr->authAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t!algoAvailable( cipherSuiteInfoPtr->authAlgo ) )\n\t\t\tcontinue;\n\t\tif( !algoAvailable( cipherSuiteInfoPtr->cryptAlgo ) )\n\t\t\tcontinue;\n\t\tif( !algoAvailable( cipherSuiteInfoPtr->macAlgo ) )\n\t\t\tcontinue;\n\n\t\t/* If it's a suite that's disabled because of external constraints \n\t\t   then we can't use it */\n\t\tif( !allowRSA && \\\n\t\t\t( cipherSuiteInfoPtr->keyexAlgo == CRYPT_ALGO_RSA || \\\n\t\t\t  cipherSuiteInfoPtr->authAlgo == CRYPT_ALGO_RSA ) )\n\t\t\tcontinue;\n\t\tif( !allowDH && \\\n\t\t\t( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_DH ) )\n\t\t\tcontinue;\n\t\tif( !allowECC && \\\n\t\t\t( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC ) )\n\t\t\tcontinue;\n\t\tif( !allowTLS12 && \\\n\t\t\t( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_TLS12 ) )\n\t\t\tcontinue;\n\n\t\t/* If we're only able to do basic TLS-PSK because there's no private \n\t\t   key present and the suite requires a private key then we can't \n\t\t   use this suite */\n\t\tif( isServer && sessionInfoPtr->privateKey == CRYPT_ERROR && \\\n\t\t\t( cipherSuiteInfoPtr->keyexAlgo != CRYPT_ALGO_NONE && \\\n\t\t\t  !isKeyxAlgo( cipherSuiteInfoPtr->keyexAlgo ) ) ) \n\t\t\tcontinue;\n\n\t\t/* If the new suite is more preferred (i.e. with a lower index) than \n\t\t   the existing one, use that.  The presence of the ECC suites \n\t\t   significantly complicates this process because the ECC curve \n\t\t   information sent later on in the handshake can retroactively \n\t\t   disable an already-negotiated ECC cipher suite, forcing a fallback \n\t\t   to a non-ECC suite (this soft-fail fallback is also nasty for the\n\t\t   user since they can't guarantee that they're actually using ECC\n\t\t   if they ask for it).  To handle this we keep track of both the\n\t\t   most-preferred (non-ECC) suite and the most preferred ECC suite \n\t\t   so that we can switch later if necessary */\n\t\tif( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC )\n\t\t\t{\n\t\t\tif( newSuiteIndex < altSuiteIndex )\n\t\t\t\t{\n\t\t\t\taltSuiteIndex = newSuiteIndex;\n\t\t\t\tDEBUG_PRINT(( \"Accepted suite: %s.\\n\", \n\t\t\t\t\t\t\t  cipherSuiteInfoPtr->description ));\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( newSuiteIndex < suiteIndex )\n\t\t\t\t{\n\t\t\t\tsuiteIndex = newSuiteIndex;\n\t\t\t\tDEBUG_PRINT(( \"Accepted suite: %s.\\n\", \n\t\t\t\t\t\t\t  cipherSuiteInfoPtr->description ));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If the only matching suite that we found was an ECC one, set it to \n\t   the primary suite (which can then be retroactively knocked out as per \n\t   the comment earlier) */\n\tif( suiteIndex >= cipherSuiteInfoSize )\n\t\t{\n\t\tsuiteIndex = altSuiteIndex;\n\t\taltSuiteIndex = 999;\n\t\t}\n\n\t/* If we couldn't find anything to use, exit.  The range comparison is \n\t   actually for whether it's still set to the original value of 999 but \n\t   some source code analysis tools think that it's an index check so we \n\t   compare to the upper bound of the array size instead */\n\tif( suiteIndex >= cipherSuiteInfoSize && \\\n\t\taltSuiteIndex >= cipherSuiteInfoSize )\n\t\t{\n\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t  \"No encryption mechanism compatible with the remote \"\n\t\t\t\t  \"system could be found\" ) );\n\t\t}\n\n\t/* We got a cipher suite that we can handle, set up the crypto information */\n\tstatus = setSuiteInfo( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t   cipherSuiteInfo[ suiteIndex ] );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we found an ECC suite and it's not already been selected due to \n\t   there being no other suites available, remember this in case we later \n\t   find out that we can use it */\n\tif( altSuiteIndex < cipherSuiteInfoSize )\n\t\t{\n\t\tREQUIRES( allowECC );\n\n\t\thandshakeInfo->eccSuiteInfoPtr = cipherSuiteInfo[ altSuiteIndex ];\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tProcess Client/Server Hello \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the client/server hello:\n\n\t\tbyte\t\tID = SSL_HAND_CLIENT_HELLO / SSL_HAND_SERVER_HELLO\n\t\tuint24\t\tlen\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tbyte[32]\tnonce\n\t\tbyte\t\tsessIDlen\t\t-- May receive nonzero len +\n\t\tbyte[]\t\tsessID\t\t\t-- <len> bytes data\n\n\t\t\tClient\t\t\t\t\t\tServer\n\t\tuint16\t\tsuiteLen\t\t-\n\t\tuint16[]\tsuites\t\t\tuint16\t\tsuite\n\t\tbyte\t\tcoprLen = 1\t\t-\n\t\tbyte\t\tcopr = 0\t\tbyte\t\tcopr = 0 \n\t  [\tuint16\textListLen\t\t\t-- RFC 3546/RFC 4366/RFC 6066\n\t\t\tbyte\textType\n\t\t\tuint16\textLen\n\t\t\tbyte[]\textData ] */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint processHelloSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t const BOOLEAN isServer )\n\t{\n\tBOOLEAN potentiallyResumedSession = FALSE;\n\tint endPos, length, suiteLength = 1, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\n\t/* Check the header and version information */\n\tif( isServer )\n\t\t{\n\t\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t\t  SSL_HAND_CLIENT_HELLO,\n\t\t\t\t\t\t\t\t\t  VERSIONINFO_SIZE + SSL_NONCE_SIZE + \\\n\t\t\t\t\t\t\t\t\t\t1 + ( UINT16_SIZE * 2 ) + 1 + 1 );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t\t  SSL_HAND_SERVER_HELLO,\n\t\t\t\t\t\t\t\t\t  VERSIONINFO_SIZE + SSL_NONCE_SIZE + \\\n\t\t\t\t\t\t\t\t\t\t1 + UINT16_SIZE + 1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tendPos = stell( stream ) + length;\n\tstatus = processVersionInfo( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\t isServer ? \\\n\t\t\t\t\t\t\t\t\t&handshakeInfo->clientOfferedVersion : \\\n\t\t\t\t\t\t\t\t\tNULL, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Since we now know which protocol version we're using, we can turn off\n\t   any hashing that we don't require any more */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tif( handshakeInfo->md5context != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( handshakeInfo->md5context,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\thandshakeInfo->md5context = CRYPT_ERROR;\n\t\t\tkrnlSendNotifier( handshakeInfo->sha1context,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\thandshakeInfo->sha1context = CRYPT_ERROR;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( handshakeInfo->sha2context != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( handshakeInfo->sha2context,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\thandshakeInfo->sha2context = CRYPT_ERROR;\n\t\t\t}\n#ifdef CONFIG_SUITEB\n\t\tif( handshakeInfo->sha384context != CRYPT_ERROR )\n\t\t\t{\n\t\t\tkrnlSendNotifier( handshakeInfo->sha384context,\n\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\thandshakeInfo->sha384context = CRYPT_ERROR;\n\t\t\t}\n#endif /* CONFIG_SUITEB */\n\t\t}\n\n\t/* Process the nonce and session ID */\n\tstatus = sread( stream, isServer ? \\\n\t\t\t\t\t\thandshakeInfo->clientNonce : \\\n\t\t\t\t\t\thandshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = processSessionID( sessionInfoPtr, handshakeInfo, stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == OK_SPECIAL )\n\t\t\tpotentiallyResumedSession = TRUE;\n\t\telse\n\t\t\treturn( status );\n\t\t}\n\n\t/* Process the cipher suite information */\n\tif( isServer )\n\t\t{\n\t\t/* We're reading the client hello, the packet contains a\n\t\t   selection of suites preceded by a suite count */\n\t\tstatus = suiteLength = readUint16( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid cipher suite information\" ) );\n\t\t\t}\n\t\tif( suiteLength < UINT16_SIZE || \\\n\t\t\tsuiteLength > ( UINT16_SIZE * MAX_CIPHERSUITES ) || \\\n\t\t\t( suiteLength % UINT16_SIZE ) != 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid cipher suite length %d\", \n\t\t\t\t\t  suiteLength ) );\n\t\t\t}\n\t\tsuiteLength /= UINT16_SIZE;\n\t\t}\n\tstatus = processCipherSuite( sessionInfoPtr, handshakeInfo, stream,\n\t\t\t\t\t\t\t\t suiteLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Process the compression suite information.  Since we don't implement\n\t   compression all that we need to do is check that the format is valid\n\t   and then skip the suite information */\n\tif( isServer )\n\t\t{\n\t\t/* We're reading the client hello, the packet contains a selection \n\t\t   of suites preceded by a suite count */\n\t\tstatus = suiteLength = sgetc( stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid compression suite information\" ) );\n\t\t\t}\n\t\tif( suiteLength < 1 || suiteLength > 20 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid compression suite length %d, should be \"\n\t\t\t\t\t  \"1...20\", suiteLength ) );\n\t\t\t}\n\t\t}\n\tstatus = sSkip( stream, suiteLength, MAX_INTLENGTH_SHORT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid compression algorithm information\" ) );\n\t\t}\n\n\t/* If there's extra data present at the end of the packet, check for TLS\n\t   extension data */\n\tif( endPos - stell( stream ) > 0 )\n\t\t{\n\t\tconst int extensionLength = endPos - stell( stream );\n\n\t\tif( extensionLength < UINT16_SIZE || \\\n\t\t\textensionLength >= MAX_INTLENGTH_SHORT )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"TLS hello contains %d bytes extraneous data\", \n\t\t\t\t\t  extensionLength ) );\n\t\t\t}\n\t\tstatus = readExtensions( sessionInfoPtr, handshakeInfo, stream,\n\t\t\t\t\t\t\t\t extensionLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thandshakeInfo->hasExtensions = TRUE;\n\t\t}\n\n\t/* If we're the server, perform any special-case handling required by \n\t   the fact that the selection of an ECC cipher suite can be \n\t   retroactively modified by TLS extensions that disable its use \n\t   again */\n\tif( isServer )\n\t\t{\n\t\tif( handshakeInfo->disableECC )\n\t\t\t{\n\t\t\t/* If the only available suite is an ECC one but it's been \n\t\t\t   disabled through an incompatible choice of client-selected \n\t\t\t   algorithm parameters then we can't continue */\n\t\t\tif( isEccAlgo( handshakeInfo->keyexAlgo ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_NOTAVAIL,\n\t\t\t\t\t\t( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Client specified use of an ECC cipher suite but \"\n\t\t\t\t\t\t  \"didn't provide any compatible ECC parameters\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n#ifdef PREFER_ECC\n\t\t\t/* If the client has chosen an ECC suite and it hasn't \n\t\t\t   subsequently been disabled by an incompatible choice of \n\t\t\t   client-selected parameters, switch to the ECC suite.  If the\n\t\t\t   only available option was an ECC suite then it'll already\n\t\t\t   have been enabled so we don't need to do it */\n\t\t\tif( handshakeInfo->eccSuiteInfoPtr != NULL )\n\t\t\t\t{\n\t\t\t\tstatus = setSuiteInfo( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t   handshakeInfo->eccSuiteInfoPtr );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n#endif /* PREFER_ECC */\n\n\t\t\t/* If we're using an ECC cipher suite (either due to it being \n\t\t\t   the only suite available or because it was selected above) \n\t\t\t   and there's no ECC curve selected by the client, default to \n\t\t\t   P256.  This is pretty much the universal default in any case,\n\t\t\t   in fact 25% of servers on the Internet will run with P256 \n\t\t\t   even if the client explicitly says they don't support it, see\n\t\t\t   \"In search of CurveSwap: Measuring elliptic curve \n\t\t\t   implementations in the wild\" by Valenta, Sullivan, Sanso and \n\t\t\t   Heninger */\n\t\t\tif( isEccAlgo( handshakeInfo->keyexAlgo ) && \\\n\t\t\t\thandshakeInfo->eccCurveID == CRYPT_ECCCURVE_NONE )\n\t\t\t\thandshakeInfo->eccCurveID = CRYPT_ECCCURVE_P256;\n\t\t\t}\n\t\t}\n\n\t/* If we're the server and the client requested a TLS 1.2-only extension\n\t   and we're not talking TLS 1.2, disable it */\n\tif( isServer && sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tCLEAR_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS );\n\t\thandshakeInfo->needTLS12LTSResponse = FALSE;\n\t\t}\n\n\t/* If we've eventually ended up with a GCM suite, typically in \n\t   conjunction with an ECC suite, turn off encrypt-then-MAC in case it \n\t   was selected */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\tCLEAR_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC );\n\t\tif( isServer )\n\t\t\thandshakeInfo->needEncThenMACResponse = FALSE;\n\t\t}\n\n\t/* If we're using Suite B and the MAC algorithm is an extended \n\t   HMAC-SHA-2 algorithm (which means that the hash algorithm will also \n\t   be extended SHA-2), replace the straight SHA2 context with the \n\t   extended version */\n#ifdef CONFIG_SUITEB\n\tif( sessionInfoPtr->integrityAlgo == CRYPT_ALGO_HMAC_SHA2 && \\\n\t\thandshakeInfo->integrityAlgoParam == bitsToBytes( 384 ) )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->sha2context,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sha2context = handshakeInfo->sha384context;\n\t\thandshakeInfo->sha384context = CRYPT_ERROR;\n\t\t}\n#endif /* CONFIG_SUITEB */\n\n\treturn( potentiallyResumedSession ? OK_SPECIAL : CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_hsc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib TLS Handshake Completion Management\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1998-2012\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/* Pre-encoded finished message header that we can use for message hashing:\n\n\tbyte\t\tID = SSL_HAND_FINISHED\n\tuint24\t\tlen = 16 + 20 (SSL), 12 (TLS) */\n\n#define FINISHED_TEMPLATE_SIZE\t\t\t\t4\n\nstatic const BYTE finishedTemplateSSL[] = \\\n\t\t{ SSL_HAND_FINISHED, 0, 0, MD5MAC_SIZE + SHA1MAC_SIZE };\nstatic const BYTE finishedTemplateTLS[] = \\\n\t\t{ SSL_HAND_FINISHED, 0, 0, TLS_HASHEDMAC_SIZE };\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Destroy cloned hash contexts, used to clean up dual-hash (SSL, TLS 1.0-1.1)\n   or single-hash (TLS 1.2+) contexts */\n\nstatic void destroyHashContexts( IN_HANDLE_OPT const CRYPT_CONTEXT hashContext1,\n\t\t\t\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT hashContext2,\n\t\t\t\t\t\t\t\t IN_HANDLE_OPT const CRYPT_CONTEXT hashContext3 )\n\t{\n\tREQUIRES_V( ( isHandleRangeValid( hashContext1 ) && \\\n\t\t\t\t  isHandleRangeValid( hashContext2 ) && \\\n\t\t\t\t  hashContext3 == CRYPT_ERROR ) || \\\n\t\t\t\t( hashContext1 == CRYPT_ERROR && \\\n\t\t\t\t  hashContext2 == CRYPT_ERROR && \\\n\t\t\t\t  isHandleRangeValid( hashContext3 ) ) );\n\n\tif( hashContext1 != CRYPT_ERROR )\n\t\tkrnlSendNotifier( hashContext1, IMESSAGE_DECREFCOUNT );\n\tif( hashContext2 != CRYPT_ERROR )\n\t\tkrnlSendNotifier( hashContext2, IMESSAGE_DECREFCOUNT );\n\tif( hashContext3 != CRYPT_ERROR )\n\t\tkrnlSendNotifier( hashContext3, IMESSAGE_DECREFCOUNT );\n\t}\n\n/* Add the current session information to the session cache */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int addSessionToCache( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t  IN_BUFFER( masterSecretSize ) void *masterSecret,\n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int masterSecretSize,\n\t\t\t\t\t\t\t  const BOOLEAN isClient )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tvoid *scoreboardInfoPtr = DATAPTR_GET( sslInfo->scoreboardInfoPtr );\n\tSCOREBOARD_INFO scoreboardInfo;\n\tint cachedID, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtrDynamic( masterSecret, masterSecretSize ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretSize ) );\n\tREQUIRES( isClient == TRUE || isClient == FALSE );\n\tREQUIRES( scoreboardInfoPtr != NULL );\n\n\t/* Set up the information that we're going to add to the scoreboard.  We \n\t   store as metadata the state of various enhanced TLS capabilities that\n\t   are enabled for the current session in order to detect attempts at\n\t   rollback in resumed sessions */\n\tmemset( &scoreboardInfo, 0, sizeof( SCOREBOARD_INFO ) );\n\tscoreboardInfo.data = masterSecret;\n\tscoreboardInfo.dataSize = masterSecretSize;\n\tscoreboardInfo.metaData = GET_FLAGS( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t\t\t\t\t SSL_RESUMEDSESSION_FLAGS );\n\n\t/* If we're the client then we have to add additional information to the\n\t   cache, in this case the server's name/address so that we can look up\n\t   the information if we try to reconnect later */\n\tif( isClient )\n\t\t{\n\t\tconst ATTRIBUTE_LIST *attributeListPtr;\n\n\t\tattributeListPtr = findSessionInfo( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME );\n\t\tif( attributeListPtr == NULL )\n\t\t\t{\n\t\t\t/* If the connection was established by passing cryptlib a raw\n\t\t\t   network socket then there's no server name information \n\t\t\t   present, so we can't cache anything based on this */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\t\tstatus = cachedID = \\\n\t\t\t\taddScoreboardEntryEx( scoreboardInfoPtr,\n\t\t\t\t\t\t\t\t\t  handshakeInfo->sessionID,\n\t\t\t\t\t\t\t\t\t  handshakeInfo->sessionIDlength,\n\t\t\t\t\t\t\t\t\t  attributeListPtr->value,\n\t\t\t\t\t\t\t\t\t  attributeListPtr->valueLength,\n\t\t\t\t\t\t\t\t\t  &scoreboardInfo );\n\t\t}\n\telse\n\t\t{\n\t\tBYTE sessionIDbuffer[ KEYID_SIZE + 8 ];\n\t\tconst BYTE *sessionIDptr = handshakeInfo->sessionID;\n\t\tint sessionIDlength = handshakeInfo->sessionIDlength;\n\n\t\t/* We're the server, add the client's state information indexed by \n\t\t   the sessionID */\n\t\tif( handshakeInfo->hashedSNIpresent )\n\t\t\t{\n\t\t\t/* If there's an SNI present, update the session ID to include \n\t\t\t   it */\n\t\t\tstatus = convertSNISessionID( handshakeInfo, sessionIDbuffer, \n\t\t\t\t\t\t\t\t\t\t  KEYID_SIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsessionIDptr = sessionIDbuffer;\n\t\t\tsessionIDlength = KEYID_SIZE;\n\t\t\t}\n\t\tstatus = cachedID = \\\n\t\t\t\t\taddScoreboardEntry( scoreboardInfoPtr,\n\t\t\t\t\t\t\t\t\t\tsessionIDptr, sessionIDlength,\n\t\t\t\t\t\t\t\t\t\t&scoreboardInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->sessionCacheID = cachedID;\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tRead/Write Handshake Completion Messages\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write the handshake completion data (change cipherspec + finished) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readHandshakeCompletionData( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\tIN_BUFFER( hashValuesLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst BYTE *hashValues,\n\t\t\t\t\t\t\t\t\t\tIN_LENGTH_SHORT const int hashValuesLength,\n\t\t\t\t\t\t\t\t\t\tINOUT READSTATE_INFO *readInfo )\n\t{\n\tSTREAM stream;\n\tBYTE macBuffer[ MD5MAC_SIZE + SHA1MAC_SIZE + 8 ];\n\tBOOLEAN startOffsetChanged = FALSE;\n\tconst int macValueLength = \\\n\t\t\t\t\t( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL ) ? \\\n\t\t\t\t\t\tMD5MAC_SIZE + SHA1MAC_SIZE : \n\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? \\\n\t\t\t\t\t\t32 : TLS_HASHEDMAC_SIZE;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, value, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( hashValues, hashValuesLength ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( hashValuesLength == macValueLength );\n\n\t/* All errors are fatal */\n\t*readInfo = READINFO_FATAL;\n\n\t/* Process the other side's change cipher spec:\n\n\t\tbyte\t\ttype = SSL_MSG_CHANGE_CIPHER_SPEC\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tuint16\t\tlen = 1\n\t\tbyte\t\t1 */\n\tstatus = readHSPacketSSL( sessionInfoPtr, NULL, &length,\n\t\t\t\t\t\t\t  SSL_MSG_CHANGE_CIPHER_SPEC );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we don't get the change cipherspec at this point this may be\n\t\t   because the server asked us for client authentication but we \n\t\t   skipped it because we don't have a certificate, in which case\n\t\t   we return extended error information indicating this */\n\t\tif( !isServer( sessionInfoPtr ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t   SSL_PFLAG_CLIAUTHSKIPPED ) )\n\t\t\t{\n\t\t\tretExtErrAlt( status, \n\t\t\t\t\t\t  ( status, SESSION_ERRINFO, \n\t\t\t\t\t\t\t\", probably due to missing client \"\n\t\t\t\t\t\t\t\"authentication\" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tvalue = sgetc( &stream );\n\tsMemDisconnect( &stream );\n\tif( value != 1 )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid change cipher spec packet payload, expected \"\n\t\t\t\t  \"0x01, got 0x%02X\", value ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readHSPacketSSL\" );\n\n\t/* Change cipher spec was the last message not subject to security\n\t   encapsulation so we turn on security for the read channel after\n\t   seeing it.  In addition if we're using TLS 1.1+ explicit IVs the\n\t   effective header size changes because of the extra IV data, so we\n\t   record the size of the additional IV data and update the receive\n\t   buffer start offset to accomodate it */\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ );\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS11 && \\\n\t\tsessionInfoPtr->cryptBlocksize > 1 )\n\t\t{\n\t\tsessionInfoPtr->sessionSSL->ivSize = sessionInfoPtr->cryptBlocksize;\n\t\tstartOffsetChanged = TRUE;\n\t\t}\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\t/* If we're using GCM then the IV is partially explicit and \n\t\t   partially implicit, and unrelated to the cipher block size */\n\t\tsessionInfoPtr->sessionSSL->ivSize = \\\n\t\t\t\t\tGCM_IV_SIZE - sessionInfoPtr->sessionSSL->gcmSaltSize;\n\t\tstartOffsetChanged = TRUE;\n\t\t}\n\tif( startOffsetChanged )\n\t\t{\n\t\tconst int newStartPos = sessionInfoPtr->receiveBufStartOfs + \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->sessionSSL->ivSize;\n\n\t\t/* Since we've changed the amount of metadata that needs to be \n\t\t   accomodated before the payload we have to adjust the data start\n\t\t   offsets to match.  This includes adjusting related offsets in\n\t\t   order to preserve invariants for the receive buffer */\n\t\tsessionInfoPtr->receiveBufStartOfs = \\\n\t\t\tsessionInfoPtr->receiveBufPos = \\\n\t\t\t\tsessionInfoPtr->receiveBufEnd = newStartPos;\n\t\t}\n\n\t/* We can't go any further when fuzzing because the crypto hasn't been \n\t   set up */\n\tFUZZ_EXIT();\n\n\t/* Process the other side's finished message.  Since this is the first \n\t   chance that we have to test whether our crypto keys are set up \n\t   correctly, we report problems with decryption or MACing or a failure \n\t   to find any recognisable header as a wrong key rather than a bad data \n\t   error.  In addition we signal the fact that the other side may \n\t   respond unexpectedly because of the use of encryption to \n\t   readHSPacketSSL() by specifying a special-case packet type, see the \n\t   comment in readHSPacketSSL() for how this is handled and why it's \n\t   necessary:\n\n\t\tbyte\t\tID = SSL_HAND_FINISHED\n\t\tuint24\t\tlen\n\t\t\tSSLv3\t\t\t\t\tTLS\t\tTLS12-LTS\n\t\tbyte[16]\tMD5 MAC\t\tbyte[12]\t\t\t\thashedMAC\n\t\tbyte[20]\tSHA-1 MAC\t\t\t\tbyte[32]\thashedMAC.\n\t\n\t   Since we've now turned in crypto, all errors are now fatal crypto \n\t   errors */\n\tstatus = readHSPacketSSL( sessionInfoPtr, NULL, &length, \n\t\t\t\t\t\t\t  SSL_MSG_FIRST_ENCRHANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*readInfo = READINFO_FATAL_CRYPTO;\n\tstatus = unwrapPacketSSL( sessionInfoPtr, sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t  length, &length, SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_BADDATA || \\\n\t\t\tstatus == CRYPT_ERROR_SIGNATURE )\n\t\t\t{\n\t\t\tretExtErr( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t   ( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t SESSION_ERRINFO, \n\t\t\t\t\t\t \"Decrypted data was corrupt, probably due to \"\n\t\t\t\t\t\t \"incorrect encryption keys being negotiated \"\n\t\t\t\t\t\t \"during the handshake: \" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstatus = checkHSPacketHeader( sessionInfoPtr, &stream, &length,\n\t\t\t\t\t\t\t\t  SSL_HAND_FINISHED, macValueLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( length != macValueLength )\n\t\t\t{\n\t\t\t/* A length mis-match can only be an overflow, since an\n\t\t\t   underflow would be caught by checkHSPacketHeader() */\n\t\t\tstatus = CRYPT_ERROR_OVERFLOW;\n\t\t\t}\n\t\telse\n\t\t\tstatus = sread( &stream, macBuffer, macValueLength );\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_BADDATA )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid handshake finished packet, probably due to \"\n\t\t\t\t\t  \"incorrect encryption keys being negotiated during \"\n\t\t\t\t\t  \"the handshake\" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"unwrapPacketSSL\" );\n\n\t/* Make sure that the dual MAC/hashed MAC of all preceding messages is\n\t   valid */\n\tif( !compareDataConstTime( hashValues, macBuffer, macValueLength ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_SIGNATURE,\n\t\t\t\t( CRYPT_ERROR_SIGNATURE, SESSION_ERRINFO, \n\t\t\t\t  \"Bad MAC for handshake messages, handshake messages were \"\n\t\t\t\t  \"corrupted/modified\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"compareDataConstTime\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"readHSPacketSSL\", \"unwrapPacketSSL\", \n\t\t\t\t\t\t\t\t\t\"compareDataConstTime\" ) );\n\n\t*readInfo = READINFO_NONE;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int writeHandshakeCompletionData( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t\t\t\t IN_BUFFER( hashValuesLength ) \\\n\t\t\t\t\t\t\t\t\t\t\tconst BYTE *hashValues, \n\t\t\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int hashValuesLength,\n\t\t\t\t\t\t\t\t\t\t const BOOLEAN continuedStream )\n\t{\n\tSTREAM *stream = &handshakeInfo->stream;\n\tBOOLEAN startOffsetChanged = FALSE;\n\tint offset = 0, ccsEndPos, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( hashValues, hashValuesLength ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( hashValuesLength ) );\n\tREQUIRES( continuedStream == TRUE || continuedStream == FALSE );\n\n\t/* Build the change cipher spec packet:\n\n\t\tbyte\t\ttype = SSL_MSG_CHANGE_CIPHER_SPEC\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tuint16\t\tlen = 1\n\t\tbyte\t\t1\n\n\t   Since change cipher spec is its own protocol, we use SSL-level packet\n\t   encoding rather than handshake protocol-level encoding */\n\tif( continuedStream )\n\t\t{\n\t\tstatus = continuePacketStreamSSL( stream, sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  SSL_MSG_CHANGE_CIPHER_SPEC, \n\t\t\t\t\t\t\t\t\t\t  &offset );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = openPacketStreamSSL( stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_USE_DEFAULT,\n\t\t\t\t\t\t\t\t\t  SSL_MSG_CHANGE_CIPHER_SPEC );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = sputc( stream, 1 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completePacketStreamSSL( stream, offset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\n\t/* Change cipher spec was the last message not subject to security\n\t   encapsulation so we turn on security for the write channel after\n\t   seeing it.  In addition if we're using TLS 1.1+ explicit IVs the\n\t   effective header size changes because of the extra IV data, so we\n\t   record the size of the additional IV data and update the receive\n\t   buffer start offset to accomodate it */\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_WRITE );\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS11 && \\\n\t\tsessionInfoPtr->cryptBlocksize > 1 )\n\t\t{\n\t\tsessionInfoPtr->sessionSSL->ivSize = sessionInfoPtr->cryptBlocksize;\n\t\tstartOffsetChanged = TRUE;\n\t\t}\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\t/* If we're using GCM then the IV is partially explicit and \n\t\t   partially implicit, and unrelated to the cipher block size */\n\t\tsessionInfoPtr->sessionSSL->ivSize = \\\n\t\t\t\t\tGCM_IV_SIZE - sessionInfoPtr->sessionSSL->gcmSaltSize;\n\t\tstartOffsetChanged = TRUE;\n\t\t}\n\tif( startOffsetChanged )\n\t\t{\n\t\tconst int newStartPos = sessionInfoPtr->sendBufStartOfs + \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->sessionSSL->ivSize;\n\n\t\t/* Since we've changed the amount of metadata that needs to be \n\t\t   accomodated before the payload we have to adjust the data start\n\t\t   offsets to match.  This includes adjusting related offsets in\n\t\t   order to preserve invariants for the send buffer */\n\t\tsessionInfoPtr->sendBufStartOfs = \\\n\t\t\tsessionInfoPtr->sendBufPos = newStartPos;\n\t\t}\n\n\t/* Build the finished packet.  The initiator sends the MAC of the\n\t   contents of every handshake packet before the finished packet, the\n\t   responder sends the MAC of the contents of every packet before its own\n\t   finished packet but including the MAC of the initiator's packet\n\t   contents:\n\n\t\tbyte\t\tID = SSL_HAND_FINISHED\n\t\tuint24\t\tlen\n\t\t\tSSLv3\t\t\t\t\t\tTLS\n\t\tbyte[16]\tMD5 MAC\t\t\tbyte[12]\thashedMAC\n\t\tbyte[20]\tSHA-1 MAC */\n\tstatus = continuePacketStreamSSL( stream, sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE, &ccsEndPos );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = continueHSPacketStream( stream, SSL_HAND_FINISHED, \n\t\t\t\t\t\t\t\t\t\t &offset );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tINJECT_FAULT( SESSION_SSL_CORRUPT_FINISHED, \n\t\t\t\t\t  SESSION_SSL_CORRUPT_FINISHED_1 );\n\t\tstatus = swrite( stream, hashValues, hashValuesLength );\n\t\tINJECT_FAULT( SESSION_SSL_CORRUPT_FINISHED, \n\t\t\t\t\t  SESSION_SSL_CORRUPT_FINISHED_2 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeHSPacketStream( stream, offset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = wrapPacketSSL( sessionInfoPtr, stream, ccsEndPos );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = sendPacketSSL( sessionInfoPtr, stream,\n\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tsMemDisconnect( stream );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tComplete the SSL/TLS Handshake\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Complete the handshake with the client or server.  The logic gets a bit\n   complex here because the roles of the client and server are reversed if\n   we're resuming a session:\n\n\t\tNormal\t\t\t\t\tResumed\n\tClient\t\tServer\t\tClient\t\tServer\n\t------\t\t------\t\t------\t\t------\n\t\t   <--- ...\t\t\tHello  --->\n\tKeyEx  --->\t\t\t\t\t   <---\tHello\n\t------------------------------------------ completeHandshakeSSL()\n\tCCS\t   --->\t\t\t\t\t   <--- CCS\n\tFin\t   --->\t\t\t\t\t   <--- Fin\n\t\t   <---\tCCS\t\t\tCCS\t   --->\n\t\t   <---\tFin\t\t\tFin\t   --->\n\n   Because of this the handshake-completion step treats the two sides as\n   initiator and responder rather than client and server.  The overall flow\n   is then:\n\n\tdualMAC/MAC( initiator );\n\tif( !initiator )\n\t\tread initiator CCS + Fin;\n\tdualMAC/MAC( responder );\n\tsend initiator/responder CCS + Fin;\n\tif( initiator )\n\t\tread responder CCS + Fin; */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint completeHandshakeSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t  const BOOLEAN isClient,\n\t\t\t\t\t\t  const BOOLEAN isResumedSession )\n\t{\n\tconst CRYPT_CONTEXT initiatorMD5context = handshakeInfo->md5context;\n\tconst CRYPT_CONTEXT initiatorSHA1context = handshakeInfo->sha1context;\n\tconst CRYPT_CONTEXT initiatorSHA2context = handshakeInfo->sha2context;\n\tCRYPT_CONTEXT responderMD5context = CRYPT_ERROR;\n\tCRYPT_CONTEXT responderSHA1context = CRYPT_ERROR;\n\tCRYPT_CONTEXT responderSHA2context = CRYPT_ERROR;\n\tBYTE masterSecret[ SSL_SECRET_SIZE + 8 ];\n\tBYTE initiatorHashes[ ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];\n\tBYTE responderHashes[ ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];\n#ifdef USE_SSL3\n\tconst void *sslInitiatorString, *sslResponderString;\n\tint sslLabelLength;\n#endif /* USE_SSL3 */\n\tconst void *tlsInitiatorString, *tlsResponderString;\n\tREADSTATE_INFO readInfo = READINFO_NONE;\n\tconst BOOLEAN isInitiator = isResumedSession ? \\\n\t\t\t( isClient ? FALSE : TRUE ) : isClient;\n\tconst BOOLEAN updateSessionCache = \t\\\n\t\t\t( !isResumedSession && handshakeInfo->sessionIDlength > 0 ) ? \\\n\t\t\tTRUE : FALSE;\n#if defined( USE_EAP ) \n\tconst BOOLEAN createDerivedKeydata = \\\n\t\t\t( sessionInfoPtr->subProtocol == CRYPT_SUBPROTOCOL_EAPTTLS ) ? \\\n\t\t\tTRUE : FALSE;\n#else\n\tconst BOOLEAN createDerivedKeydata = FALSE;\n#endif /* USE_EAP */\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint initiatorHashLength, responderHashLength;\n\tint tlsLabelLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( MAX_KEYBLOCK_SIZE >= ( sessionInfoPtr->authBlocksize + \\\n\t\t\t\t\t\t\t\t\t handshakeInfo->cryptKeysize +\n\t\t\t\t\t\t\t\t\t sessionInfoPtr->cryptBlocksize ) * 2 );\n\tREQUIRES( handshakeInfo->authAlgo == CRYPT_ALGO_NONE || \\\n\t\t\t  ( isEccAlgo( handshakeInfo->keyexAlgo ) && \\\n\t\t\t\thandshakeInfo->premasterSecretSize >= MIN_PKCSIZE_ECC ) || \\\n\t\t\t  ( !isEccAlgo( handshakeInfo->keyexAlgo ) && \\\n\t\t\t\thandshakeInfo->premasterSecretSize >= SSL_SECRET_SIZE ) );\n\tREQUIRES( isClient == TRUE || isClient == FALSE );\n\tREQUIRES( isResumedSession == TRUE || isResumedSession == FALSE );\n\n\t/* Perform the necessary juggling of values for the reversed message\n\t   flow of resumed sessions */\n\tif( isResumedSession )\n\t\t{\n\t\t/* Resumed session, initiator = server, responder = client */\n#ifdef USE_SSL3\n\t\tsslInitiatorString = SSL_SENDER_SERVERLABEL;\n\t\tsslResponderString = SSL_SENDER_CLIENTLABEL;\n#endif /* USE_SSL3 */\n\t\ttlsInitiatorString = \"server finished\";\n\t\ttlsResponderString = \"client finished\";\n\t\t}\n\telse\n\t\t{\n\t\t/* Normal session, initiator = client, responder = server */\n#ifdef USE_SSL3\n\t\tsslInitiatorString = SSL_SENDER_CLIENTLABEL;\n\t\tsslResponderString = SSL_SENDER_SERVERLABEL;\n#endif /* USE_SSL3 */\n\t\ttlsInitiatorString = \"client finished\";\n\t\ttlsResponderString = \"server finished\";\n\t\t}\n#ifdef USE_SSL3\n\tsslLabelLength = SSL_SENDERLABEL_SIZE;\n#endif /* USE_SSL3 */\n\ttlsLabelLength = 15;\n\n#ifndef CONFIG_FUZZ\n\t/* Initialise and load cryptovariables into all encryption contexts */\n\tstatus = initCryptoSSL( sessionInfoPtr, handshakeInfo, masterSecret,\n\t\t\t\t\t\t\tSSL_SECRET_SIZE, isClient, isResumedSession );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"initCryptoSSL\" );\n\n\t/* At this point the hashing of the initiator and responder diverge.\n\t   The initiator sends its change cipherspec and finished messages \n\t   first, so the hashing stops there, while the responder has to keep \n\t   hasing the initiator's messages until it's its turn to send its \n\t   change cipherspec and finished messages.  To handle this we clone \n\t   the initiator's hash context(s) so that we can contine the hashing \n\t   after the initiator has wrapped things up */\n\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = cloneHashContext( initiatorMD5context, \n\t\t\t\t\t\t\t\t   &responderMD5context );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cloneHashContext( initiatorSHA1context, \n\t\t\t\t\t\t\t\t\t   &responderSHA1context );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tkrnlSendNotifier( responderMD5context, \n\t\t\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cloneHashContext( initiatorSHA2context, \n\t\t\t\t\t\t\t\t   &responderSHA2context );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"cloneHashContext\" );\n\n\t/* Complete the dual-MAC/MAC of the initiator-side messages and, if \n\t   we're the responder, check that the MACs match the ones supplied by\n\t   the initiator */\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\tstatus = completeSSLDualMAC( initiatorMD5context, initiatorSHA1context,\n\t\t\t\t\t\t\tinitiatorHashes, CRYPT_MAX_HASHSIZE * 2,\n\t\t\t\t\t\t\t&initiatorHashLength, sslInitiatorString, \n\t\t\t\t\t\t\tsslLabelLength, masterSecret, SSL_SECRET_SIZE );\n\t\t}\n\telse\n#endif /* USE_SSL3 */\n\t\t{\n\t\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t\t{\n\t\t\tstatus = completeTLSHashedMAC( initiatorMD5context, \n\t\t\t\t\t\t\tinitiatorSHA1context, initiatorHashes, \n\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE * 2, &initiatorHashLength, \n\t\t\t\t\t\t\ttlsInitiatorString, tlsLabelLength, masterSecret, \n\t\t\t\t\t\t\tSSL_SECRET_SIZE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = completeTLS12HashedMAC( initiatorSHA2context,\n\t\t\t\t\t\t\tinitiatorHashes, CRYPT_MAX_HASHSIZE,\n\t\t\t\t\t\t\t&initiatorHashLength, tlsInitiatorString, \n\t\t\t\t\t\t\ttlsLabelLength, masterSecret, SSL_SECRET_SIZE,\n\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? TRUE : FALSE );\n\t\t\t}\n\t\t}\n#else\n\tinitiatorHashLength = \\\n\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS ) ? \\\n\t\t\t\t\t   32 : TLS_HASHEDMAC_SIZE;\n\tstatus = CRYPT_OK;\n#endif /* CONFIG_FUZZ */\n\tif( cryptStatusOK( status ) && !isInitiator )\n\t\t{\n\t\tstatus = readHandshakeCompletionData( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\t\t  initiatorHashes, \n\t\t\t\t\t\t\t\t\t\t\t  initiatorHashLength, \n\t\t\t\t\t\t\t\t\t\t\t  &readInfo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\t\tdestroyHashContexts( responderMD5context, responderSHA1context,\n\t\t\t\t\t\t\t responderSHA2context );\n\n\t\t/* We have to explicitly handle crypto failures at this point \n\t\t   because we're not being called from the higher-level session\n\t\t   read handlers that do this for us */\n\t\tif( readInfo == READINFO_FATAL_CRYPTO )\n\t\t\tregisterCryptoFailure();\n\t\treturn( status );\n\t\t}\n#ifndef CONFIG_FUZZ\n\tCFI_CHECK_UPDATE( \"completeHashedMAC\" );\n\n\t/* Now that we have the initiator MACs, complete the dual-hashing/\n\t   hashing and dual-MAC/MAC of the responder-side messages and destroy \n\t   the master secret unless we need to keep it around to update the\n\t   session cache.  We haven't created the full message yet at this \n\t   point so we manually hash the individual pieces so that we can \n\t   finally get rid of the master secret */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tstatus = krnlSendMessage( responderSHA2context, IMESSAGE_CTX_HASH,\n\t\t\t\t( MESSAGE_CAST ) finishedTemplateTLS, FINISHED_TEMPLATE_SIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( responderSHA2context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t  initiatorHashes, initiatorHashLength );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tconst BYTE *finishedTemplate = \\\n\t\t\t( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL ) ? \\\n\t\t\tfinishedTemplateSSL : finishedTemplateTLS;\n\n\t\tstatus = krnlSendMessage( responderMD5context, IMESSAGE_CTX_HASH,\n\t\t\t\t( MESSAGE_CAST ) finishedTemplate, FINISHED_TEMPLATE_SIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( responderSHA1context, IMESSAGE_CTX_HASH,\n\t\t\t\t( MESSAGE_CAST ) finishedTemplate, FINISHED_TEMPLATE_SIZE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( responderMD5context, IMESSAGE_CTX_HASH, \n\t\t\t\t\t\t\t\t\t  initiatorHashes, initiatorHashLength );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( responderSHA1context, IMESSAGE_CTX_HASH,\n\t\t\t\t\t\t\t\t\t  initiatorHashes, initiatorHashLength );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\t\tdestroyHashContexts( responderMD5context, responderSHA1context,\n\t\t\t\t\t\t\t responderSHA2context );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"IMESSAGE_CTX_HASH\" );\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\tstatus = completeSSLDualMAC( responderMD5context, responderSHA1context,\n\t\t\t\t\t\t\tresponderHashes, CRYPT_MAX_HASHSIZE * 2,\n\t\t\t\t\t\t\t&responderHashLength, sslResponderString, \n\t\t\t\t\t\t\tsslLabelLength, masterSecret, SSL_SECRET_SIZE );\n\t\t}\n\telse\n#endif /* USE_SSL3 */\n\t\t{\n\t\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t\t{\n\t\t\tstatus = completeTLSHashedMAC( responderMD5context, \n\t\t\t\t\t\t\tresponderSHA1context, responderHashes, \n\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE * 2, &responderHashLength, \n\t\t\t\t\t\t\ttlsResponderString, tlsLabelLength, masterSecret, \n\t\t\t\t\t\t\tSSL_SECRET_SIZE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = completeTLS12HashedMAC( responderSHA2context, \n\t\t\t\t\t\t\tresponderHashes, CRYPT_MAX_HASHSIZE * 2, \n\t\t\t\t\t\t\t&responderHashLength, tlsResponderString, \n\t\t\t\t\t\t\ttlsLabelLength, masterSecret, SSL_SECRET_SIZE,\n\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? TRUE : FALSE );\n\t\t\t}\n\t\t}\n\tif( !updateSessionCache && !createDerivedKeydata )\n\t\t{\n\t\t/* If we don't need the master secret beyond this point, clear it \n\t\t   from memory now */\n\t\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\t\t}\n\tdestroyHashContexts( responderMD5context, responderSHA1context,\n\t\t\t\t\t\t responderSHA2context );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"completeHashedMAC\" );\n\n\t/* Send our MACs to the other side and read back their response if\n\t   necessary.  The initiatorHashLength is the same as the \n\t   responderHashLength (it's just a naming difference based on the\n\t   role that we're playing) so we use initiatorHashLength for both */\n\tstatus = writeHandshakeCompletionData( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\tisInitiator ? initiatorHashes : responderHashes,\n\t\t\t\t\tinitiatorHashLength /* Same as responderHashLength */,\n\t\t\t\t\t( ( isClient && !isResumedSession ) || \\\n\t\t\t\t\t  ( !isClient && isResumedSession ) ) ? TRUE : FALSE );\n#endif /* !CONFIG_FUZZ */\n\tif( cryptStatusOK( status ) && isInitiator )\n\t\t{\n\t\tstatus = readHandshakeCompletionData( sessionInfoPtr, responderHashes,\n\t\t\t\t\t\t\t\t\t\t\t  initiatorHashLength, &readInfo );\n\t\t}\n\tif( cryptStatusOK( status ) && updateSessionCache )\n\t\t{\n\t\t/* The handshake completed successfully, add the master secret to \n\t\t   the session cache */\n\t\tstatus = addSessionToCache( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\tmasterSecret, SSL_SECRET_SIZE,\n\t\t\t\t\t\t\t\t\tisClient );\n\t\t}\n#ifdef USE_EAP\n\tif( cryptStatusOK( status ) && createDerivedKeydata )\n\t\t{\n\t\t/* The handshake completed successfully, add the derived keying data\n\t\t   required by EAP */\n\t\tstatus = addDerivedKeydata( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\tmasterSecret, SSL_SECRET_SIZE,\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->subProtocol );\n\t\t}\n#endif /* USE_EAP */\n\tCFI_CHECK_UPDATE( \"writeHandshakeCompletionData\" );\n\n\t/* Clean up */\n\tzeroise( masterSecret, SSL_SECRET_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* We have to explicitly handle crypto failures at this point \n\t\t   because we're not being called from the higher-level session\n\t\t   read handlers that do this for us */\n\t\tif( readInfo == READINFO_FATAL_CRYPTO )\n\t\t\tregisterCryptoFailure();\n\t\treturn( status );\n\t\t}\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"initCryptoSSL\", \"cloneHashContext\", \n\t\t\t\t\t\t\t\t\t\"completeHashedMAC\", \"IMESSAGE_CTX_HASH\", \n\t\t\t\t\t\t\t\t\t\"completeHashedMAC\",\n\t\t\t\t\t\t\t\t\t\"writeHandshakeCompletionData\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_kmgmt.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib TLS Key Management Routines\t\t\t\t\t*\n*\t\t\t\t\t Copyright Peter Gutmann 1998-2012\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Initialise and destroy the crypto information in the handshake state\n   information */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint initHandshakeCryptInfo( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Clear the handshake information contexts */\n\thandshakeInfo->md5context = \\\n\t\thandshakeInfo->sha1context = \\\n\t\t\thandshakeInfo->sha2context = CRYPT_ERROR;\n#ifdef CONFIG_SUITEB\n\thandshakeInfo->sha384context = CRYPT_ERROR;\n#endif /* CONFIG_SUITEB */\n\thandshakeInfo->dhContext = \\\n\t\thandshakeInfo->sessionHashContext = CRYPT_ERROR;\n\n\t/* Create the MAC/dual-hash contexts for incoming and outgoing data.\n\t   SSL uses a pre-HMAC variant for which we can't use real HMAC but have\n\t   to construct it ourselves from MD5 and SHA-1, TLS uses a straight dual\n\t   hash and MACs that once a MAC key becomes available at the end of the\n\t   handshake */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thandshakeInfo->md5context = createInfo.cryptHandle;\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thandshakeInfo->sha1context = createInfo.cryptHandle;\n\t\tif( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )\n\t\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef CONFIG_SUITEB\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Create the additional SHA2-384 context that's needed for Suite \n\t\t   B use */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA2 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatic const int blockSize = bitsToBytes( 384 );\n\n\t\t\thandshakeInfo->sha384context = createInfo.cryptHandle;\n\t\t\tstatus = krnlSendMessage( handshakeInfo->sha384context, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &blockSize,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t\t}\n\t\t}\n#endif /* CONFIG_SUITEB */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Create additional contexts that may be needed for TLS 1.2 */\n\t\tsetMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA2 );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\thandshakeInfo->sha2context = createInfo.cryptHandle;\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* One or more of the contexts couldn't be created, destroy all of the\n\t   contexts that have been created so far */\n\tdestroyHandshakeCryptInfo( handshakeInfo );\n\treturn( status );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroyHandshakeCryptInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\t/* Destroy any active contexts.  We need to do this here (even though\n\t   it's also done in the general session code) to provide a clean exit in\n\t   case the session activation fails, so that a second activation attempt\n\t   doesn't overwrite still-active contexts */\n\tif( handshakeInfo->md5context != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->md5context,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->md5context = CRYPT_ERROR;\n\t\t}\n\tif( handshakeInfo->sha1context != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->sha1context,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sha1context = CRYPT_ERROR;\n\t\t}\n\tif( handshakeInfo->sha2context != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->sha2context,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sha2context = CRYPT_ERROR;\n\t\t}\n#ifdef CONFIG_SUITEB\n\tif( handshakeInfo->sha384context != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->sha384context,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sha384context = CRYPT_ERROR;\n\t\t}\n#endif /* CONFIG_SUITEB */\n\tif( handshakeInfo->dhContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->dhContext, IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->dhContext = CRYPT_ERROR;\n\t\t}\n\tif( handshakeInfo->sessionHashContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( handshakeInfo->sessionHashContext, \n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\thandshakeInfo->sessionHashContext = CRYPT_ERROR;\n\t\t}\n\t}\n\n/* Initialise and destroy the session security contexts */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int initSecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr\n#ifdef CONFIG_SUITEB\n\t\t\t\t\t\t\t\t\t, INOUT SSL_HANDSHAKE_INFO *handshakeInfo\n#endif /* CONFIG_SUITEB */\n\t\t\t\t\t\t\t\t   )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n#ifdef CONFIG_SUITEB\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n#endif /* CONFIG_SUITEB */\n\n\t/* Create the authentication contexts, unless we're using a combined\n\t   encryption+authentication mode */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\tconst CRYPT_ALGO_TYPE integrityAlgo = sessionInfoPtr->integrityAlgo;\n\n\t\tsetMessageCreateObjectInfo( &createInfo, integrityAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsessionInfoPtr->iAuthInContext = createInfo.cryptHandle;\n\t\t\tsetMessageCreateObjectInfo( &createInfo, integrityAlgo );\n\t\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroySecurityContextsSSL( sessionInfoPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\tsessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;\n#ifdef CONFIG_SUITEB\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\thandshakeInfo->integrityAlgoParam == bitsToBytes( 384 ) )\n\t\t\t{\n\t\t\tstatic const int blockSize = bitsToBytes( 384 );\n\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iAuthInContext, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &blockSize,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iAuthOutContext, \n\t\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &blockSize,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_BLOCKSIZE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tdestroySecurityContextsSSL( sessionInfoPtr );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n#endif /* CONFIG_SUITEB */\n\t\t}\n\n\t/* Create the encryption contexts */\n\tsetMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsessionInfoPtr->iCryptInContext = createInfo.cryptHandle;\n\t\tsetMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroySecurityContextsSSL( sessionInfoPtr );\n\t\treturn( status );\n\t\t}\n\tsessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;\n\n\t/* If we're using GCM we also need to change the encryption mode from \n\t   the default CBC */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) ) \n\t\t{\n\t\tstatic const int mode = CRYPT_MODE_GCM;\t/* int vs.enum */\n\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &mode,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_MODE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroySecurityContextsSSL( sessionInfoPtr );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid destroySecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Destroy any active contexts */\n\tif( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iAuthInContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iAuthOutContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCryptInContext = CRYPT_ERROR;\n\t\t}\n\tif( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCryptOutContext = CRYPT_ERROR;\n\t\t}\n\t}\n\n/* Clone a hash context so that we can continue using the original to hash \n   further messages */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \\\nint cloneHashContext( IN_HANDLE const CRYPT_CONTEXT hashContext,\n\t\t\t\t\t  OUT_HANDLE_OPT CRYPT_CONTEXT *clonedHashContext )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tint hashAlgo, status;\t/* int vs.enum */\n\n\tassert( isWritePtr( clonedHashContext, sizeof( CRYPT_CONTEXT * ) ) );\n\n\tREQUIRES( isHandleRangeValid( hashContext ) );\n\n\t/* Clear return value */\n\t*clonedHashContext = CRYPT_ERROR;\n\n\t/* Determine the type of context that we have to clone */\n\tstatus = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &hashAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create a new hash context and clone the existing one's state into \n\t   it */\n\tsetMessageCreateObjectInfo( &createInfo, hashAlgo );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = krnlSendMessage( hashContext, IMESSAGE_CLONE, NULL, \n\t\t\t\t\t\t\t  createInfo.cryptHandle );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\t*clonedHashContext = createInfo.cryptHandle;\n\t\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKeyex Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load a DH/ECDH key into a context */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint initDHcontextSSL( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext, \n\t\t\t\t\t  IN_BUFFER_OPT( keyDataLength ) const void *keyData, \n\t\t\t\t\t  IN_LENGTH_SHORT_Z const int keyDataLength,\n\t\t\t\t\t  IN_HANDLE_OPT const CRYPT_CONTEXT iServerKeyTemplate,\n\t\t\t\t\t  IN_ENUM_OPT( CRYPT_ECCCURVE ) \\\n\t\t\t\t\t\t\tconst CRYPT_ECCCURVE_TYPE eccParams,\n\t\t\t\t\t  const BOOLEAN isTLSLTS )\n\t{\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tint keySize = TLS_DH_KEYSIZE, status;\n\n\tassert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );\n\tassert( ( keyData == NULL && keyDataLength == 0 ) || \\\n\t\t\tisReadPtrDynamic( keyData, keyDataLength ) );\n\n\tREQUIRES( ( keyData == NULL && keyDataLength == 0 ) || \\\n\t\t\t  ( keyData != NULL && \\\n\t\t\t\tisShortIntegerRangeNZ( keyDataLength ) ) );\n\tREQUIRES( iServerKeyTemplate == CRYPT_UNUSED || \\\n\t\t\t  isHandleRangeValid( iServerKeyTemplate ) );\n\tREQUIRES( isEnumRangeOpt( eccParams, CRYPT_ECCCURVE ) );\n\tREQUIRES( isTLSLTS == TRUE || isTLSLTS == FALSE );\n\n\t/* Clear return value */\n\t*iCryptContext = CRYPT_ERROR;\n\n\t/* If we're loading a built-in DH key, match the key size to the server \n\t   authentication key size.  If there's no server key present, we \n\t   default to the TLS_DH_KEYSIZE-byte key because we don't know how much \n\t   processing power the client has */\n\tif( keyData == NULL && iServerKeyTemplate != CRYPT_UNUSED && \\\n\t\teccParams == CRYPT_ECCCURVE_NONE )\n\t\t{\n\t\tstatus = krnlSendMessage( iServerKeyTemplate, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t\t  &keySize, CRYPT_CTXINFO_KEYSIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Create the DH/ECDH context */\n\tsetMessageCreateObjectInfo( &createInfo, \\\n\t\t\t\t\t\t\t\t( eccParams != CRYPT_ECCCURVE_NONE ) ? \\\n\t\t\t\t\t\t\t\t\tCRYPT_ALGO_ECDH : CRYPT_ALGO_DH );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CONTEXT );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, \"TLS key agreement key\", 21 );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the key into the context.  If we're being given externally-\n\t   supplied DH/ECDH key components, load them, otherwise use the built-\n\t   in key */\n\tif( keyData != NULL )\n\t\t{\n\t\t/* If we're the client we'll have been sent DH/ECDH key components \n\t\t   by the server */\n\t\tsetMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength ); \n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  isTLSLTS ? CRYPT_IATTRIBUTE_KEY_SSL_EXT : \\\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_IATTRIBUTE_KEY_SSL );\n\t\t}\n\telse\n\t\t{\n#ifdef USE_ECDH \n\t\t/* If we've been given ECC parameter information then we're using\n\t\t   ECDH */\n\t\tif( eccParams != CRYPT_ECCCURVE_NONE )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &eccParams, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_DLPPARAM );\n\t\t\t}\n\t\telse\n#endif /* USE_ECDH */\n\t\t\t{\n\t\t\t/* We're loading a standard DH key of the appropriate size */\n\t\t\tstatus = krnlSendMessage( createInfo.cryptHandle, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &keySize, \n\t\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_KEY_DLPPARAM );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\tif( keyData == NULL )\n\t\t\t{\n\t\t\t/* If we got an error loading a known-good, fixed-format key \n\t\t\t   then we report the problem as an internal error rather than \n\t\t\t   (say) a bad-data error */\n\t\t\tretIntError();\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\t*iCryptContext = createInfo.cryptHandle;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the master secret from a shared (PSK) secret value, typically a\n   password */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \\\nint createSharedPremasterSecret( OUT_BUFFER( premasterSecretMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t *premasterSecretLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *premasterSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT \\\n\t\t\t\t\t\t\t\t\tconst int premasterSecretMaxLength, \n\t\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( premasterSecretMaxLength ) \\\n\t\t\t\t\t\t\t\t\tint *premasterSecretLength,\n\t\t\t\t\t\t\t\t IN_BUFFER( sharedSecretLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *sharedSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_SHORT const int sharedSecretLength,\n\t\t\t\t\t\t\t\t IN_BUFFER_OPT( otherSecretLength ) \\\n\t\t\t\t\t\t\t\t\tconst void *otherSecret, \n\t\t\t\t\t\t\t\t IN_LENGTH_PKC_Z const int otherSecretLength,\n\t\t\t\t\t\t\t\t const BOOLEAN isEncodedValue )\n\t{\n\tSTREAM stream;\n\tBYTE decodedValue[ 64 + 8 ];\n\tstatic const BYTE zeroes[ CRYPT_MAX_TEXTSIZE + 8 ] = { 0 };\n\tint valueLength = sharedSecretLength;\n\tint status;\n\n\tassert( isWritePtrDynamic( premasterSecret, premasterSecretMaxLength ) );\n\tassert( isWritePtr( premasterSecretLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( sharedSecret, sharedSecretLength ) );\n\tassert( otherSecret == NULL || \\\n\t\t\tisReadPtrDynamic( otherSecret, otherSecretLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( premasterSecretMaxLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( sharedSecretLength ) );\n\tREQUIRES( ( otherSecret == NULL && otherSecretLength == 0 ) || \\\n\t\t\t  ( otherSecret != NULL && \\\n\t\t\t\totherSecretLength > 0 && \\\n\t\t\t\totherSecretLength <= CRYPT_MAX_PKCSIZE ) );\n\tREQUIRES( isEncodedValue == TRUE || isEncodedValue == FALSE );\n\n\t/* Clear return values */\n\tmemset( premasterSecret, 0, min( 16, premasterSecretMaxLength ) );\n\t*premasterSecretLength = 0;\n\n\t/* Write the PSK-derived premaster secret value:\n\n\t\tuint16\totherSecretLen\n\t\tbyte[]\totherSecret\t\t-- DH value for DHE-PSK, zeroes for pure PSK\n\t\tuint16\tpskLen\n\t\tbyte[]\tpsk\n\n\t   Because the TLS PRF splits the input into two halves of which one half \n\t   is processed by HMAC-MD5 and the other by HMAC-SHA1, it's necessary\n\t   to extend the PSK in some way to provide input to both halves of the\n\t   PRF.  In a rather dubious decision, the spec requires that for pure\n\t   PSK (not DHE-PSK or RSA-PSK) the MD5 half be set to all zeroes, with \n\t   only the SHA1 half being used.  This is done by writing otherSecret \n\t   as a number of zero bytes equal in length to the password */\n\tsMemOpen( &stream, premasterSecret, premasterSecretMaxLength );\n\tif( isEncodedValue )\n\t\t{\n\t\t/* It's a cryptlib-style encoded password, decode it into its binary\n\t\t   value */\n\t\tstatus = decodePKIUserValue( decodedValue, 64, &valueLength,\n\t\t\t\t\t\t\t\t\t sharedSecret, sharedSecretLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tDEBUG_DIAG(( \"Couldn't decode supposedly valid PKI user \"\n\t\t\t\t\t\t \"value\" ));\n\t\t\tassert( DEBUG_WARN );\n\t\t\treturn( status );\n\t\t\t}\n\t\tsharedSecret = decodedValue;\n\t\t}\n\tif( otherSecret != NULL )\n\t\t{\n\t\twriteUint16( &stream, otherSecretLength );\n\t\tswrite( &stream, otherSecret, otherSecretLength );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's pure PSK, otherSecret is a string of zeroes */\n\t\twriteUint16( &stream, valueLength );\n\t\tswrite( &stream, zeroes, valueLength );\n\t\t}\n\twriteUint16( &stream, valueLength );\n\tstatus = swrite( &stream, sharedSecret, valueLength );\n\tif( isEncodedValue )\n\t\tzeroise( decodedValue, valueLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*premasterSecretLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_RSA_SUITES\n\n/* Wrap/unwrap the pre-master secret */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nint wrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t OUT_BUFFER( dataMaxLength, *dataLength ) void *data, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int dataMaxLength, \n\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \\\n\t\t\t\t\t\t\tint *dataLength )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tMESSAGE_DATA msgData;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( dataMaxLength ) );\n\n\t/* Clear return values */\n\tmemset( data, 0, min( 16, dataMaxLength ) );\n\t*dataLength = 0;\n\n\t/* Create the premaster secret and wrap it using the server's public\n\t   key.  Note that the version that we advertise at this point is the\n\t   version originally offered by the client in its hello message, not\n\t   the version eventually negotiated for the connection.  This is\n\t   designed to prevent rollback attacks (but see also the comment in\n\t   unwrapPremasterSecret() below) */\n\thandshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;\n\thandshakeInfo->premasterSecret[ 0 ] = SSL_MAJOR_VERSION;\n\thandshakeInfo->premasterSecret[ 1 ] = \\\n\t\t\t\t\t\tintToByte( handshakeInfo->clientOfferedVersion );\n\tsetMessageData( &msgData,\n\t\t\t\t\thandshakeInfo->premasterSecret + VERSIONINFO_SIZE,\n\t\t\t\t\tSSL_SECRET_SIZE - VERSIONINFO_SIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMechanismWrapInfo( &mechanismInfo, data, dataMaxLength,\n\t\t\t\t\t\t  handshakeInfo->premasterSecret, SSL_SECRET_SIZE, \n\t\t\t\t\t\t  CRYPT_UNUSED, sessionInfoPtr->iKeyexCryptContext );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );\n\tif( cryptStatusOK( status ) )\n\t\t*dataLength = mechanismInfo.wrappedDataLength;\n\tclearMechanismInfo( &mechanismInfo );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint unwrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t   IN_BUFFER( dataLength ) const void *data, \n\t\t\t\t\t\t   IN_LENGTH_SHORT const int dataLength )\n\t{\n\tMECHANISM_WRAP_INFO mechanismInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( data, dataLength ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( dataLength ) );\n\n\t/* Decrypt the encrypted premaster secret.  In theory we could\n\t   explicitly defend against Bleichenbacher-type attacks at this point\n\t   by setting the premaster secret to a pseudorandom value if we get a\n\t   bad data or (later) an incorrect version error and continuing as\n\t   normal, however the attack depends on the server returning\n\t   information required to pinpoint the cause of the failure and\n\t   cryptlib just returns a generic \"failed\" response for any handshake\n\t   failure, so this explicit defence isn't really necessary, and not\n\t   doing this avoids a trivial DoS attack in which a client sends us\n\t   junk and forces us to continue with the handshake even though we've\n\t   detected that it's junk.\n\n\t   There's a second, lower-grade level of oracle that an attacker can\n\t   use in the version check if they can distinguish between a decrypt \n\t   failure due to bad PKCS #1 padding and a failure due to a bad version \n\t   number (see \"Attacking RSA-based Sessions in SSL/TLS\", Vlastimil\n\t   Klima, Ondrej Pokorny, and Tomas Rosa, CHES'03), or many other later \n\t   variants of the Bleichenbacher attack that target additional features\n\t   like missing padding terminators or padding terminators in odd \n\t   locations (leading to incorrect payload sizes), and so on.\n\t   \n\t   If we use the Bleichenbacher defence and continue the handshake on \n\t   bad padding but bail out on a bad version then the two cases can be \n\t   distinguished, however since cryptlib bails out immediately in either \n\t   case the two shouldn't be distinguishable */\n\thandshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;\n\tsetMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST ) data, dataLength,\n\t\t\t\t\t\t  handshakeInfo->premasterSecret, SSL_SECRET_SIZE, \n\t\t\t\t\t\t  CRYPT_UNUSED, sessionInfoPtr->privateKey );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,\n\t\t\t\t\t\t\t  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );\n\tif( cryptStatusOK( status ) && \\\n\t\tmechanismInfo.keyDataLength != SSL_SECRET_SIZE )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tclearMechanismInfo( &mechanismInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* This is a pretty nonspecific error message, but it's useful for\n\t\t   diagnosing general decryption problems, as well as the potential \n\t\t   presence of various types of oracle attacks */\n\t\tif( status == CRYPT_ERROR_BADDATA )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"RSA decryption of premaster secret produced invalid \"\n\t\t\t\t\t  \"PKCS #1 data\" ) );\n\t\t\t}\n\t\tretExt( status,\n\t\t\t\t( status , SESSION_ERRINFO, \n\t\t\t\t  \"RSA decryption of premaster secret failed\" ) );\n\t\t}\n\n\t/* Make sure that it looks OK.  Note that the version that we check for\n\t   at this point is the version originally offered by the client in its\n\t   hello message, not the version eventually negotiated for the\n\t   connection.  This is designed to prevent rollback attacks */\n\tif( handshakeInfo->premasterSecret[ 0 ] != SSL_MAJOR_VERSION || \\\n\t\thandshakeInfo->premasterSecret[ 1 ] != handshakeInfo->clientOfferedVersion )\n\t\t{\n#if 0\t/* 18/12/17 Unlikely to still be an issue */\n\t\t/* Microsoft braindamage, older versions of MSIE send the wrong \n\t\t   version number for the premaster secret (making it look like a \n\t\t   rollback attack) so if we're expecting 3.1 from the client and \n\t\t   get 3.0 in the premaster secret then it's MSIE screwing up.  Note \n\t\t   that this bug-check is only applied for SSL and TLS 1.0, for TLS \n\t\t   1.1 and later the check of the version is mandatory */\n\t\tif( handshakeInfo->originalVersion <= SSL_MINOR_VERSION_TLS && \\\n\t\t\thandshakeInfo->clientOfferedVersion == SSL_MINOR_VERSION_TLS && \\\n\t\t\thandshakeInfo->premasterSecret[ 0 ] == SSL_MAJOR_VERSION && \\\n\t\t\thandshakeInfo->premasterSecret[ 1 ] == SSL_MINOR_VERSION_SSL )\n\t\t\t{\n\t\t\tsetErrorString( ( ERROR_INFO * ) &sessionInfoPtr->errorInfo, \n\t\t\t\t\t\t\t\"Warning: Accepting invalid premaster secret \"\n\t\t\t\t\t\t\t\"version 3.0 (MSIE bug)\", 66 );\n\t\t\t}\n\t\telse\n#endif /* 0 */\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid premaster secret version data 0x%02X 0x%02X, \"\n\t\t\t\t\t  \"expected 0x03 0x%02X\",\n\t\t\t\t\t  handshakeInfo->premasterSecret[ 0 ],\n\t\t\t\t\t  handshakeInfo->premasterSecret[ 1 ],\n\t\t\t\t\t  handshakeInfo->clientOfferedVersion ) );\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_RSA_SUITES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tPremaster -> Master -> Key Material Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Convert a pre-master secret to a master secret, and a master secret to\n   keying material */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int premasterToMaster( const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\t  OUT_BUFFER_FIXED( masterSecretLength ) \\\n\t\t\t\t\t\t\t\t\tvoid *masterSecret, \n\t\t\t\t\t\t\t  IN_LENGTH_SHORT const int masterSecretLength )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tBYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];\n\tint nonceSize;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretLength ) );\n\n\tDEBUG_PUTS(( \"Premaster secret:\" ));\n\tDEBUG_DUMP_DATA( handshakeInfo->premasterSecret, \n\t\t\t\t\t handshakeInfo->premasterSecretSize );\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\tmemcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\t\tmemcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,\n\t\t\t\tSSL_NONCE_SIZE );\n\t\tsetMechanismDeriveInfo( &mechanismInfo, masterSecret,\n\t\t\t\t\t\t\t\tmasterSecretLength, \n\t\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\t\thandshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\t\tnonceBuffer, \n\t\t\t\t\t\t\t\tSSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_SSL ) );\n\t\t}\n#endif /* USE_SSL3 */\n\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS ) )\n\t\t{\n\t\tREQUIRES( boundsCheck( 22, handshakeInfo->sessionHashSize, \n\t\t\t\t\t\t\t   64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE ) );\n\t\tmemcpy( nonceBuffer, \"extended master secret\", 22 );\n\t\tmemcpy( nonceBuffer + 22, handshakeInfo->sessionHash, \n\t\t\t\thandshakeInfo->sessionHashSize );\n\t\tnonceSize = 22 + handshakeInfo->sessionHashSize;\n\t\t}\n\telse\n\t\t{\n\t\tmemcpy( nonceBuffer, \"master secret\", 13 );\n\t\tmemcpy( nonceBuffer + 13, handshakeInfo->clientNonce, \n\t\t\t\tSSL_NONCE_SIZE );\n\t\tmemcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, \n\t\t\t\thandshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\t\tnonceSize = 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE;\n\t\t}\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tsetMechanismDeriveInfo( &mechanismInfo, masterSecret, \n\t\t\t\t\t\t\t\tmasterSecretLength, \n\t\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\t\thandshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\t\tCRYPT_ALGO_SHA2, nonceBuffer, nonceSize, 1 );\n\t\tif( handshakeInfo->integrityAlgoParam != 0 )\n\t\t\tmechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );\n\t\t}\n\tsetMechanismDeriveInfo( &mechanismInfo, masterSecret, masterSecretLength,\n\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\thandshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\tnonceBuffer, nonceSize, 1 );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \\\nstatic int masterToKeys( const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t const SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t IN_BUFFER( masterSecretLength ) \\\n\t\t\t\t\t\t\t\tconst void *masterSecret, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int masterSecretLength,\n\t\t\t\t\t\t OUT_BUFFER_FIXED( keyBlockLength ) void *keyBlock, \n\t\t\t\t\t\t IN_LENGTH_SHORT const int keyBlockLength )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tBYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLength ) );\n\tassert( isWritePtrDynamic( keyBlock, keyBlockLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretLength ) );\n\tREQUIRES( isShortIntegerRangeNZ( keyBlockLength ) );\n\n\tDEBUG_PUTS(( \"Master secret:\" ));\n\tDEBUG_DUMP_DATA( masterSecret, masterSecretLength );\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\tmemcpy( nonceBuffer, handshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\t\tmemcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->clientNonce,\n\t\t\t\tSSL_NONCE_SIZE );\n\t\tsetMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,\n\t\t\t\t\t\t\t\tmasterSecret, masterSecretLength, \n\t\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\t\tnonceBuffer, \n\t\t\t\t\t\t\t\tSSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_SSL ) );\n\t\t}\n#endif /* USE_SSL3 */\n\n\tmemcpy( nonceBuffer, \"key expansion\", 13 );\n\tmemcpy( nonceBuffer + 13, handshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\tmemcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->clientNonce,\n\t\t\tSSL_NONCE_SIZE );\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tsetMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,\n\t\t\t\t\t\t\t\tmasterSecret, masterSecretLength, \n\t\t\t\t\t\t\t\tCRYPT_ALGO_SHA2, nonceBuffer, \n\t\t\t\t\t\t\t\t13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\t\tif( handshakeInfo->integrityAlgoParam != 0 )\n\t\t\tmechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );\n\t\t}\n\tsetMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,\n\t\t\t\t\t\t\tmasterSecret, masterSecretLength, \n\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\tnonceBuffer, \n\t\t\t\t\t\t\t13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS ) );\n\t}\n\n#ifdef USE_EAP\n\n/* Convert a master secret to additional keying material.  Note that we \n   can't use masterToKeys() here because the sub-protocols that use these\n   derived values reverse the order of the nonces */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5, 7 ) ) \\\nstatic int masterToKeydata( const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tconst SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\tIN_BUFFER( masterSecretLength ) \\\n\t\t\t\t\t\t\t\tconst void *masterSecret, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int masterSecretLength,\n\t\t\t\t\t\t\tIN_BUFFER( diversifierLength ) \\\n\t\t\t\t\t\t\t\tconst void *diversifier,\n\t\t\t\t\t\t\tIN_LENGTH_TEXT const int diversifierLength,\n\t\t\t\t\t\t\tOUT_BUFFER_FIXED( keyBlockLength ) void *keyBlock, \n\t\t\t\t\t\t\tIN_LENGTH_SHORT const int keyBlockLength )\n\t{\n\tMECHANISM_DERIVE_INFO mechanismInfo;\n\tBYTE nonceBuffer[ CRYPT_MAX_TEXTSIZE + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( masterSecret, masterSecretLength ) );\n\tassert( isReadPtrDynamic( diversifier, diversifierLength ) );\n\tassert( isWritePtrDynamic( keyBlock, keyBlockLength ) );\n\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretLength ) );\n\tREQUIRES( diversifierLength >= 1 && \\\n\t\t\t  diversifierLength <= CRYPT_MAX_TEXTSIZE );\n\tREQUIRES( isShortIntegerRangeNZ( keyBlockLength ) );\n\n\tmemcpy( nonceBuffer, diversifier, diversifierLength );\n\tmemcpy( nonceBuffer + diversifierLength, \n\t\t\thandshakeInfo->clientNonce, SSL_NONCE_SIZE );\n\tmemcpy( nonceBuffer + diversifierLength + SSL_NONCE_SIZE, \n\t\t\thandshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\tsetMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,\n\t\t\t\t\t\t\t\tmasterSecret, masterSecretLength, \n\t\t\t\t\t\t\t\tCRYPT_ALGO_SHA2, nonceBuffer, \n\t\t\t\t\t\t\t\tdiversifierLength + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\t\tif( handshakeInfo->integrityAlgoParam != 0 )\n\t\t\tmechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;\n\t\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );\n\t\t}\n\tsetMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,\n\t\t\t\t\t\t\tmasterSecret, masterSecretLength, \n\t\t\t\t\t\t\t( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\tnonceBuffer, \n\t\t\t\t\t\t\tdiversifierLength + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );\n\treturn( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,\n\t\t\t\t\t\t\t &mechanismInfo, MECHANISM_DERIVE_TLS ) );\n\t}\n#endif /* USE_EAP */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey-load Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Load the SSL/TLS cryptovariables */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int loadKeys( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t const SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t IN_BUFFER( keyBlockLength ) const void *keyBlock, \n\t\t\t\t\t IN_LENGTH_SHORT_MIN( 16 ) const int keyBlockLength,\n\t\t\t\t\t const BOOLEAN isClient )\n\t{\n#ifdef USE_SSL3\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n#endif /* USE_SSL3 */\n\tMESSAGE_DATA msgData;\n\tBYTE *keyBlockPtr = ( BYTE * ) keyBlock;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isReadPtrDynamic( keyBlock, keyBlockLength ) );\n\n\tREQUIRES( keyBlockLength >= ( sessionInfoPtr->authBlocksize * 2 ) + \\\n\t\t\t\t\t\t\t\t( handshakeInfo->cryptKeysize * 2 ) + \\\n\t\t\t\t\t\t\t\t( sessionInfoPtr->cryptBlocksize * 2 ) && \\\n\t\t\t  keyBlockLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( isClient == TRUE || isClient == FALSE );\n\n\t/* Load the keys and secrets:\n\n\t\t( client_write_mac || server_write_mac || \\\n\t\t  client_write_key || server_write_key || \\\n\t\t  client_write_iv  || server_write_iv )\n\n\t   First we load the MAC keys.  For TLS these are proper MAC keys, for\n\t   SSL we have to build the proto-HMAC ourselves from a straight hash\n\t   context so we store the raw cryptovariables rather than loading them\n\t   into a context, and if we're using GCM we skip them since the \n\t   encryption key also functions as the authentication key */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n#ifdef USE_SSL3\n\t\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\t\t{\n\t\t\tENSURES( rangeCheck( sessionInfoPtr->authBlocksize, 0,\n\t\t\t\t\t\t\t\t CRYPT_MAX_HASHSIZE ) );\n\t\t\tREQUIRES( boundsCheck( sessionInfoPtr->authBlocksize, \n\t\t\t\t\t\t\t\t   sessionInfoPtr->authBlocksize, \n\t\t\t\t\t\t\t\t   keyBlockLength ) );\n\t\t\tmemcpy( isClient ? sslInfo->macWriteSecret : sslInfo->macReadSecret,\n\t\t\t\t\tkeyBlockPtr, sessionInfoPtr->authBlocksize );\n\t\t\tmemcpy( isClient ? sslInfo->macReadSecret : sslInfo->macWriteSecret,\n\t\t\t\t\tkeyBlockPtr + sessionInfoPtr->authBlocksize,\n\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\t\t\t}\n\t\telse\n#endif /* USE_SSL3 */\n\t\t\t{\n\t\t\tsetMessageData( &msgData, keyBlockPtr, \n\t\t\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\t\t\tstatus = krnlSendMessage( isClient ? \\\n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthOutContext : \\\n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthInContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsetMessageData( &msgData, \n\t\t\t\t\t\t\tkeyBlockPtr + sessionInfoPtr->authBlocksize,\n\t\t\t\t\t\t\tsessionInfoPtr->authBlocksize );\n\t\t\tstatus = krnlSendMessage( isClient ? \\\n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthInContext: \\\n\t\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iAuthOutContext,\n\t\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tkeyBlockPtr += sessionInfoPtr->authBlocksize * 2;\n\t\t}\n\n\t/* Then we load the encryption keys */\n\tsetMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );\n\tstatus = krnlSendMessage( isClient ? \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext : \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\tkeyBlockPtr += handshakeInfo->cryptKeysize;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsetMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );\n\tstatus = krnlSendMessage( isClient ? \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext : \\\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY );\n\tkeyBlockPtr += handshakeInfo->cryptKeysize;\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're using a stream cipher, there are no IVs */\n\tif( isStreamCipher( sessionInfoPtr->cryptAlgo ) )\n\t\treturn( CRYPT_OK );\t/* No IV, we're done */\n\n\t/* If we're using GCM then the IV is composed of two parts, an explicit \n\t   portion that's sent with every packet and an implicit portion that's \n\t   derived from the master secret */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\tmemcpy( isClient ? sessionInfoPtr->sessionSSL->gcmWriteSalt : \\\n\t\t\t\t\t\t   sessionInfoPtr->sessionSSL->gcmReadSalt, \n\t\t\t\tkeyBlockPtr, GCM_SALT_SIZE );\n\t\tmemcpy( isClient ? sessionInfoPtr->sessionSSL->gcmReadSalt : \\\n\t\t\t\t\t\t   sessionInfoPtr->sessionSSL->gcmWriteSalt, \n\t\t\t\tkeyBlockPtr + GCM_SALT_SIZE, GCM_SALT_SIZE );\n\t\tsessionInfoPtr->sessionSSL->gcmSaltSize = GCM_SALT_SIZE;\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* It's a standard block cipher, load the IVs.  This load is actually \n\t   redundant for TLS 1.1+ since it uses explicit IVs, but it's easier to \n\t   just do it anyway */\n\tsetMessageData( &msgData, keyBlockPtr,\n\t\t\t\t\tsessionInfoPtr->cryptBlocksize );\n\tkrnlSendMessage( isClient ? sessionInfoPtr->iCryptOutContext : \\\n\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptInContext,\n\t\t\t\t\t IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t CRYPT_CTXINFO_IV );\n\tkeyBlockPtr += sessionInfoPtr->cryptBlocksize;\n\tsetMessageData( &msgData, keyBlockPtr,\n\t\t\t\t\tsessionInfoPtr->cryptBlocksize );\n\treturn( krnlSendMessage( isClient ? sessionInfoPtr->iCryptInContext : \\\n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t CRYPT_CTXINFO_IV ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint initCryptoSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t   OUT_BUFFER_FIXED( masterSecretSize ) void *masterSecret,\n\t\t\t\t   IN_LENGTH_SHORT const int masterSecretSize,\n\t\t\t\t   const BOOLEAN isClient,\n\t\t\t\t   const BOOLEAN isResumedSession )\n\t{\n\tBYTE keyBlock[ MAX_KEYBLOCK_SIZE + 8 ];\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtrDynamic( masterSecret, masterSecretSize ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretSize ) );\n\tREQUIRES( isClient == TRUE || isClient == FALSE );\n\tREQUIRES( isResumedSession == TRUE || isResumedSession == FALSE );\n\n\t/* Create the security contexts required for the session */\n\tstatus = initSecurityContextsSSL( sessionInfoPtr );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's a fresh (i.e. non-cached) session, convert the premaster \n\t   secret into the master secret */\n\tif( !isResumedSession )\n\t\t{\n\t\tstatus = premasterToMaster( sessionInfoPtr, handshakeInfo,\n\t\t\t\t\t\t\t\t\tmasterSecret, masterSecretSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\telse\n\t\t{\n\t\t/* We've already got the master secret present from the session that\n\t\t   we're resuming from, reuse that */\n\t\tREQUIRES( rangeCheck( handshakeInfo->premasterSecretSize, 0,\n\t\t\t\t\t\t\t  masterSecretSize ) );\n\t\tmemcpy( masterSecret, handshakeInfo->premasterSecret,\n\t\t\t\thandshakeInfo->premasterSecretSize );\n\t\t}\n\n\t/* Convert the master secret into keying material.  Unfortunately we\n\t   can't delete the master secret at this point because it's still \n\t   needed to calculate the MAC for the handshake messages and because \n\t   we may still need it in order to add it to the session cache */\n\tstatus = masterToKeys( sessionInfoPtr, handshakeInfo, masterSecret,\n\t\t\t\t\t\t   masterSecretSize, keyBlock, MAX_KEYBLOCK_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, masterSecretSize );\n\t\treturn( status );\n\t\t}\n\n\t/* Load the keys and secrets */\n\tstatus = loadKeys( sessionInfoPtr, handshakeInfo, keyBlock, \n\t\t\t\t\t   MAX_KEYBLOCK_SIZE, isClient );\n\tzeroise( keyBlock, MAX_KEYBLOCK_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( masterSecret, masterSecretSize );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* TLS versions greater than 1.0 prepend an explicit IV to the data, the\n   following function loads this from the packet data stream */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint loadExplicitIV( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\tOUT_INT_SHORT_Z int *ivLength )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\tint ivSize = sslInfo->ivSize, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( ivLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Clear return value */\n\t*ivLength = 0;\n\n\t/* Read and load the IV */\n\tstatus = sread( stream, iv, sslInfo->ivSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Packet IV read\" ) );\n\t\t}\n\tINJECT_FAULT( SESSION_SSL_CORRUPT_IV, SESSION_SSL_CORRUPT_IV_1 );\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t{\n\t\t/* If we're using GCM then the IV has to be assembled from the \n\t\t   implicit and explicit portions */\n\t\tREQUIRES( boundsCheck( sslInfo->gcmSaltSize, sslInfo->ivSize,\n\t\t\t\t\t\t\t   CRYPT_MAX_IVSIZE ) );\n\t\tmemmove( iv + sslInfo->gcmSaltSize, iv, sslInfo->ivSize );\n\t\tmemcpy( iv, sslInfo->gcmReadSalt, sslInfo->gcmSaltSize );\n\t\tivSize += sslInfo->gcmSaltSize;\n\t\t}\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC ) )\n\t\t{\n\t\t/* If we're using encrypt-then-MAC then we have to save a copy of\n\t\t   the IV for MAC'ing when the packet is processed */\n\t\tREQUIRES( rangeCheck( sslInfo->ivSize, 1, CRYPT_MAX_IVSIZE ) );\n\t\tmemcpy( sslInfo->iv, iv, sslInfo->ivSize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, iv, ivSize );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iCryptInContext,\n\t\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S, &msgData,\n\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Packet IV load failed\" ) );\n\t\t}\n\n\t/* Tell the caller how much data we've consumed */\n\t*ivLength = sslInfo->ivSize;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* The EAP protocols that use SSL/TLS derive additional keying data from the\n   SSL/TLS master secret.  The following function creates this subprotocol-\n   specific additional keying material and adds it as session attributes */\n\n#ifdef USE_EAP\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint addDerivedKeydata( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t   IN_BUFFER( masterSecretSize ) void *masterSecret,\n\t\t\t\t\t   IN_LENGTH_SHORT const int masterSecretSize,\n\t\t\t\t\t   IN_ENUM( CRYPT_SUBPROTOCOL ) \\\n\t\t\t\t\t\t\tconst CRYPT_SUBPROTOCOL_TYPE type )\n\t{\n\tconst char *challengeDiversifier = NULL, *keyDiversifier = NULL;\n\tint challengeDiversifierLength, keyDiversifierLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtrDynamic( masterSecret, masterSecretSize ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( isShortIntegerRangeNZ( masterSecretSize ) );\n\tREQUIRES( isEnumRange( type, CRYPT_SUBPROTOCOL ) );\n\n\t/* Select the appripriate diversifier for the sub-protocol type */\n\tswitch( type )\n\t\t{\n\t\tcase CRYPT_SUBPROTOCOL_EAPTTLS:\n\t\t\tchallengeDiversifier = \"ttls challenge\";\n\t\t\tchallengeDiversifierLength = 14;\n\t\t\tkeyDiversifier = \"ttls keying material\";\n\t\t\tkeyDiversifierLength = 20;\n\t\t\tbreak;\n\n#if 0\n\t\tcase CRYPT_SUBPROTOCOL_EAPTLS:\n\t\t\t// Also has IV using keyDiversifier and empty master secret value\n\t\t\tkeyDiversifier = \"client EAP encryption\";\n\t\t\tkeyDiversifierLength = 21;\n\t\t\tbreak;\n\n\t\tcase CRYPT_SUBPROTOCOL_PEAP:\n\t\t\tkeyDiversifier = \"client EAP encryption\";\n\t\t\tkeyDiversifierLength = 21;\n\t\t\tbreak;\n#endif\n\n\t\tdefault:\n\t\t\tretIntError();\n\t\t}\n\n\t/* Set up the EAP challenge and key values */\n\tif( challengeDiversifier != NULL )\n\t\t{\n\t\tBYTE challengeBuffer[ 32 + 8 ];\n\n\t\tstatus = masterToKeydata( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t  masterSecret, masterSecretSize,\n\t\t\t\t\t\t\t\t  challengeDiversifier, \n\t\t\t\t\t\t\t\t  challengeDiversifierLength,\n\t\t\t\t\t\t\t\t  challengeBuffer, 32 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"EAP challenge:\" ));\n\t\t\tDEBUG_DUMP_DATA( challengeBuffer, 32 );\n\t\t\tstatus = addSessionInfoS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSL_EAPCHALLENGE,\n\t\t\t\t\t\t\t\t\t  challengeBuffer, 32 );\n\t\t\t}\n\t\tzeroise( challengeBuffer, 32 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"EAP challenge value initialistion failed\" ) );\n\t\t\t}\n\t\t}\n\tif( keyDiversifier != NULL )\n\t\t{\n\t\tBYTE keyBuffer[ 128 + 8 ];\n\n\t\tstatus = masterToKeydata( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t  masterSecret, masterSecretSize,\n\t\t\t\t\t\t\t\t  keyDiversifier, \n\t\t\t\t\t\t\t\t  keyDiversifierLength,\n\t\t\t\t\t\t\t\t  keyBuffer, 128 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tDEBUG_PUTS(( \"EAP key:\" ));\n\t\t\tDEBUG_DUMP_DATA( keyBuffer, 128 );\n\t\t\tstatus = addSessionInfoS( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSL_EAPKEY,\n\t\t\t\t\t\t\t\t\t  keyBuffer, 128 );\n\t\t\t}\n\t\tzeroise( keyBuffer, 128 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"EAP keying value initialistion failed\" ) );\n\t\t\t}\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_EAP */\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_rd.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TLS Session Read Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef USE_ERRMSGS\n\n/* Get a string description of overall and handshake packet types, used for \n   diagnostic error messages */\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSLPacketName( IN_BYTE const int packetType )\n\t{\n\tstatic const OBJECT_NAME_INFO packetNameInfo[] = {\n\t\t{ SSL_MSG_CHANGE_CIPHER_SPEC, \"change_cipher_spec\" },\n\t\t{ SSL_MSG_ALERT, \"alert\" },\n\t\t{ SSL_MSG_HANDSHAKE, \"handshake (encrypted)\" },\n\t\t\t/* We denote this one as an encrypted handshake packet rather \n\t\t\t  than a straight handshake packet because handshake messages \n\t\t\t  are identified via getSSLHSPacketName(), it's only when we're \n\t\t\t  encrypting the handshake messages that we can no longer dump \n\t\t\t  the inner contents, so if we ever get a handshake packet \n\t\t\t  dumped using getSSLPacketName() then it has to be encrypted */\n\t\t{ SSL_MSG_APPLICATION_DATA, \"application_data\" },\n\t\t{ CRYPT_ERROR, \"<Unknown type>\" },\n\t\t\t{ CRYPT_ERROR, \"<Unknown type>\" }\n\t\t};\n\n\tREQUIRES_EXT( ( packetType >= 0 && packetType <= 0xFF ),\n\t\t\t\t  \"<Internal error>\" );\n\n\treturn( getObjectName( packetNameInfo,\n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( packetNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t   OBJECT_NAME_INFO ),\n\t\t\t\t\t\t   packetType ) );\n\t}\n\nCHECK_RETVAL_PTR_NONNULL \\\nconst char *getSSLHSPacketName( IN_BYTE const int packetType )\n\t{\n\tstatic const OBJECT_NAME_INFO packetNameInfo[] = {\n\t\t{ SSL_HAND_CLIENT_HELLO, \"client_hello\" },\n\t\t{ SSL_HAND_SERVER_HELLO, \"server_hello\" },\n\t\t{ SSL_HAND_CERTIFICATE, \"certificate\" },\n\t\t{ SSL_HAND_SERVER_KEYEXCHANGE, \"server_key_exchange\" },\n\t\t{ SSL_HAND_SERVER_CERTREQUEST, \"certificate_request\" },\n\t\t{ SSL_HAND_SERVER_HELLODONE, \"server_hello_done\" },\n\t\t{ SSL_HAND_CLIENT_CERTVERIFY, \"certificate_verify\" },\n\t\t{ SSL_HAND_CLIENT_KEYEXCHANGE, \"client_key_exchange\" },\n\t\t{ SSL_HAND_FINISHED, \"finished\" },\n\t\t{ SSL_HAND_SUPPLEMENTAL_DATA, \"supplemental_data\" },\n\t\t{ CRYPT_ERROR, \"<Unknown type>\" },\n\t\t\t{ CRYPT_ERROR, \"<Unknown type>\" }\n\t\t};\n\n\tREQUIRES_EXT( ( packetType >= 0 && packetType <= 0xFF ),\n\t\t\t\t  \"<Internal error>\" );\n\n\treturn( getObjectName( packetNameInfo,\n\t\t\t\t\t\t   FAILSAFE_ARRAYSIZE( packetNameInfo, \\\n\t\t\t\t\t\t\t\t\t\t\t   OBJECT_NAME_INFO ),\n\t\t\t\t\t\t   packetType ) );\n\t}\n#endif /* USE_ERRMSGS */\n\n/* Process version information.  This is always called with sufficient data \n   in the input stream so we don't have to worry about special-casing error\n   reporting for stream read errors.\n   \n   Handling of version numbering in the SSL/TLS protocol is complex and \n   messy (or at least the way that some implementations do it is complex\n   and messy), the client and server hellos have two version numbers, one in \n   the overall SSL/TLS message wrapper and a second one in the client/server \n   hello itself.  Many browsers send a meaningless version number in the \n   overall wrapper that bears no relation to the version in the hello \n   message contents, so for the initial message we skip the outer version \n   (or at least just check that it's approximately valid) and use the inner \n   version number given in the hello message itself.  For subsequent \n   messages, where the wrapper version number seems to make sense, we ensure \n   that the version number matches */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processVersionInfo( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT STREAM *stream, \n\t\t\t\t\t\tOUT_OPT int *clientVersion,\n\t\t\t\t\t\tconst BOOLEAN generalCheckOnly )\n\t{\n\tint version, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( clientVersion == NULL || \\\n\t\t\tisWritePtr( clientVersion, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( generalCheckOnly == TRUE || generalCheckOnly == FALSE );\n\n\t/* Clear return value */\n\tif( clientVersion != NULL )\n\t\t*clientVersion = CRYPT_ERROR;\n\n\t/* Check the major version number */\n\tstatus = version = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( version != SSL_MAJOR_VERSION )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid major version number %d, should be 3\", version ) );\n\t\t}\n\n\t/* Check the minor version number.  If we've already got the version\n\t   established, make sure that it matches the existing one, otherwise\n\t   determine which version we'll be using */\n\tstatus = version = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( clientVersion == NULL )\n\t\t{\n\t\t/* If it's the first message in the exchange then the outer version\n\t\t   number is meaningless and often doesn't correspond to the inner \n\t\t   version number in the client/server hello, so all we do is check \n\t\t   that it's generally within range */\n\t\tif( generalCheckOnly )\n\t\t\t{\n\t\t\tif( version < SSL_MINOR_VERSION_SSL || \\\n\t\t\t\tversion > SSL_MINOR_VERSION_TLS12 + 2 )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Invalid version number 3.%d, should be \"\n\t\t\t\t\t\t  \"3.0...3.%d\", version, \n\t\t\t\t\t\t  SSL_MINOR_VERSION_TLS12 + 2 ) );\n\t\t\t\t}\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* It's a subsequent message in the exchange, the version number has\n\t\t   to match what we're expecting */\n\t\tif( version != sessionInfoPtr->version )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid version number 3.%d, should be 3.%d\", \n\t\t\t\t\t  version, sessionInfoPtr->version ) );\n\t\t\t}\n\t\treturn( CRYPT_OK );\n\t\t}\n\tDEBUG_PRINT(( \"%s offered protocol version: 3.%d.\\n\", \n\t\t\t\t  isServer( sessionInfoPtr ) ? \"Client\" : \"Server\", \n\t\t\t\t  version ));\n\tswitch( version )\n\t\t{\n\t\tcase SSL_MINOR_VERSION_SSL:\n#ifdef USE_SSL3\n\t\t\t/* If the other side can't do TLS, fall back to SSL */\n\t\t\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS )\n\t\t\t\tsessionInfoPtr->version = SSL_MINOR_VERSION_SSL;\n\t\t\tbreak;\n#else\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"%s requested use of insecure SSL version 3, we can \"\n\t\t\t\t\t  \"only do TLS\", \n\t\t\t\t\t  isServer( sessionInfoPtr ) ? \"Client\" : \"Server\" ) );\n#endif /* USE_SSL3 */\n\n\t\tcase SSL_MINOR_VERSION_TLS:\n\t\t\t/* If the other side can't do TLS 1.1, fall back to TLS 1.0 */\n\t\t\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS11 )\n\t\t\t\tsessionInfoPtr->version = SSL_MINOR_VERSION_TLS;\n\t\t\tbreak;\n\n\t\tcase SSL_MINOR_VERSION_TLS11:\n\t\t\t/* If the other side can't do TLS 1.2, fall back to TLS 1.1 */\n\t\t\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t\t\tsessionInfoPtr->version = SSL_MINOR_VERSION_TLS11;\n\t\t\tbreak;\n\n\t\tcase SSL_MINOR_VERSION_TLS12:\n\t\t\t/* If the other side can't do post-TLS 1.2, fall back to \n\t\t\t   TLS 1.2 */\n\t\t\tif( sessionInfoPtr->version > SSL_MINOR_VERSION_TLS12 )\n\t\t\t\tsessionInfoPtr->version = SSL_MINOR_VERSION_TLS12;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* If we're the server and the client has offered a vaguely \n\t\t\t   sensible version, fall back to the highest version that we\n\t\t\t   support */\n\t\t\tif( isServer( sessionInfoPtr ) && \\\n\t\t\t\tversion <= SSL_MINOR_VERSION_TLS12 + 2 )\n\t\t\t\t{\n\t\t\t\tsessionInfoPtr->version = SSL_MINOR_VERSION_TLS12;\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* It's nothing that we can handle */\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid protocol version 3.%d\", version ) );\n\t\t}\n\tDEBUG_PRINT(( \"Accepted protocol version: 3.%d.\\n\", \n\t\t\t\t  sessionInfoPtr->version ));\n\n\t/* If there's a requirement for a minimum version, make sure that it's\n\t   been met */\n\tif( sessionInfoPtr->sessionSSL->minVersion > 0 && \\\n\t\tversion < sessionInfoPtr->sessionSSL->minVersion )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid version number 3.%d, should be at least 3.%d\", \n\t\t\t\t  version, sessionInfoPtr->sessionSSL->minVersion ) );\n\t\t}\n\n\t*clientVersion = version;\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCheck a Packet\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check that the header of an SSL packet is in order:\n\n\tbyte\ttype\n\tbyte[2]\tvers = { 0x03, 0x0n }\n\tuint16\tlength\n  [ byte[]\tiv\t- TLS 1.1+ ]\n\n  This is always called with sufficient data in the input stream that we \n  don't have to worry about special-casing error reporting for stream read\n  errors.\n\n  If this is the initial hello packet then we request a dummy version \n  information read since the peer's version isn't known yet this point.  The \n  actual version information is taken from the hello packet data, not from \n  the SSL wrapper */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int checkPacketHeader( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  INOUT STREAM *stream,\n\t\t\t\t\t\t\t  OUT_LENGTH_BOUNDED_Z( maxLength ) \\\n\t\t\t\t\t\t\t\t\tint *packetLength, \n\t\t\t\t\t\t\t  IN_RANGE( SSL_MSG_FIRST, \\\n\t\t\t\t\t\t\t\t\t\tSSL_MSG_LAST_SPECIAL ) \\\n\t\t\t\t\t\t\t\t\tconst int packetType, \n\t\t\t\t\t\t\t  IN_DATALENGTH_Z const int minLength, \n\t\t\t\t\t\t\t  IN_DATALENGTH const int maxLength )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tconst int expectedPacketType = \\\n\t\t\t\t\t( packetType == SSL_MSG_FIRST_HANDSHAKE ) ? \\\n\t\t\t\t\tSSL_MSG_HANDSHAKE : packetType;\n\tint value, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\n\tREQUIRES( ( packetType >= SSL_MSG_FIRST && \\\n\t\t\t\tpacketType <= SSL_MSG_LAST ) || \\\n\t\t\t  ( packetType == SSL_MSG_FIRST_HANDSHAKE ) );\n\tREQUIRES( ( packetType == SSL_MSG_APPLICATION_DATA && \\\n\t\t\t\tminLength == 0 ) || \\\n\t\t\t  ( minLength > 0 && minLength < MAX_BUFFER_SIZE ) );\n\tREQUIRES( maxLength >= minLength && maxLength < MAX_BUFFER_SIZE );\n\n\t/* Clear return value */\n\t*packetLength = 0;\n\n\t/* Check the packet type */\n\tstatus = value = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != expectedPacketType )\n\t\t{\n\t\t/* There is one special case in which a mismatch is allowed and \n\t\t   that's when we're expecting a data packet and we instead get a\n\t\t   handshake packet, which may be a rehandshake request from the \n\t\t   server.  Unfortunately we can't tell that at this point because \n\t\t   the packet is encrypted, so all that we can do is set a flag \n\t\t   indicating that when we process the actual payload we need to \n\t\t   check for a re-handshake */\n\t\tif( expectedPacketType == SSL_MSG_APPLICATION_DATA && \\\n\t\t\tvalue == SSL_MSG_HANDSHAKE && !isServer( sessionInfoPtr ) )\n\t\t\t{\n\t\t\t/* Tell the body-read code to check for a rehandshake (via a\n\t\t\t   hello_request) in the decrypted packet payload */\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSL_PFLAG_CHECKREHANDSHAKE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Unexpected %s (%d) packet, expected %s (%d)\", \n\t\t\t\t\t  getSSLPacketName( value ), value, \n\t\t\t\t\t  getSSLPacketName( expectedPacketType ), \n\t\t\t\t\t  expectedPacketType ) );\n\t\t\t}\n\t\t}\n\n\t/* Process the version information.  Alongside not requiring a version \n\t   number match on the first message exchanged we also allow this for\n\t   alert packets, since version-intolerant servers can send back alerts\n\t   with lower-then-expected version numbers */\n\tstatus = processVersionInfo( sessionInfoPtr, stream, NULL,\n\t\t\t\t\t\t( packetType == SSL_MSG_FIRST_HANDSHAKE || \\\n\t\t\t\t\t\t  packetType == SSL_MSG_ALERT ) ? TRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Check the packet length */\n\tstatus = length = readUint16( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) )\n\t\t{\n\t\tif( length < sslInfo->ivSize + minLength + \\\n\t\t\t\t\t sessionInfoPtr->authBlocksize || \\\n\t\t\tlength > sslInfo->ivSize + MAX_PACKET_SIZE + \\\n\t\t\t\t\t sessionInfoPtr->authBlocksize + 256 || \\\n\t\t\tlength > maxLength )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\telse\n\t\t{\n\t\tif( length < minLength || length > MAX_PACKET_SIZE || \\\n\t\t\tlength > maxLength )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid packet length %d for %s (%d) packet\", \n\t\t\t\t  length, getSSLPacketName( packetType ), packetType ) );\n\t\t}\n\n\t/* Load the TLS 1.1+ explicit IV if necessary */\n\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t   SESSION_FLAG_ISSECURE_READ ) && \\\n\t\tsslInfo->ivSize > 0 )\n\t\t{\n\t\tint ivLength;\n\n\t\tstatus = loadExplicitIV( sessionInfoPtr, stream, &ivLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Error loading TLS explicit IV\" ) );\n\t\t\t}\n\t\tlength -= ivLength;\n\t\tENSURES( length >= minLength + sessionInfoPtr->authBlocksize && \\\n\t\t\t\t length <= maxLength );\n\t\t}\n\t*packetLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Check that the header of an SSL packet and SSL handshake packet is in \n   order.  This is always called with sufficient data in the input stream so \n   we don't have to worry about special-casing error reporting for stream \n   read errors, however for the handshake packet read we do need to check \n   the length because several of these can be encapsulated within a single \n   SSL packet so we can't check the exact space requirements in advance */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkPacketHeaderSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT STREAM *stream, \n\t\t\t\t\t\t  OUT_DATALENGTH_Z int *packetLength )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\treturn( checkPacketHeader( sessionInfoPtr, stream, packetLength,\n\t\t\t\t\t\t\t   SSL_MSG_APPLICATION_DATA, 0, \n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufSize ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nint checkHSPacketHeader( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t INOUT STREAM *stream, \n\t\t\t\t\t\t OUT_DATALENGTH_Z int *packetLength, \n\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType, \n\t\t\t\t\t\t IN_LENGTH_SHORT_Z const int minSize )\n\t{\n\tint type, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\t\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\tREQUIRES( isShortIntegerRange( minSize ) );\n\t\t\t  /* May be zero for change cipherspec */\n\n\t/* Clear return value */\n\t*packetLength = 0;\n\n\t/* Make sure that there's enough data left in the stream to safely read\n\t   the header from it.  This will be caught anyway by the checks below, \n\t   but performing the check here makes the error reporting a bit more \n\t   precise */\n\tif( sMemDataLeft( stream ) < 1 + LENGTH_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid handshake packet header\" ) );\n\t\t}\n\n\t/*\tbyte\t\tID = type\n\t\tuint24\t\tlength */\n\tstatus = type = sgetc( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( type != packetType )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid handshake packet %s (%d), expected %s (%d)\", \n\t\t\t\t  getSSLHSPacketName( type ), type, \n\t\t\t\t  getSSLHSPacketName( packetType ), packetType ) );\n\t\t}\n\tstatus = length = readUint24( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( length < minSize || length > MAX_PACKET_SIZE || \\\n\t\tlength > sMemDataLeft( stream ) )\n\t\t{\n\t\t/* Some servers may send insanely-long certificate request packets\n\t\t   that are fragmented across multiple SSL packets (see the comment\n\t\t   in processCertRequest() in ssl_cli.c), so if we encounter one of \n\t\t   these we allow an encapsulated packet up to 1 1/2 times the \n\t\t   length of a standard one which will be handled specially by the \n\t\t   caller */\n\t\tif( type == SSL_HAND_SERVER_CERTREQUEST && \\\n\t\t\tlength >= minSize && \\\n\t\t\tlength < sMemDataLeft( stream ) + ( MAX_PACKET_SIZE / 2 ) )\n\t\t\t{\n\t\t\t*packetLength = length;\n\t\t\tDEBUG_PRINT(( \"Read over-long %s (%d) handshake packet, \"\n\t\t\t\t\t\t  \"length %ld.\\n\", getSSLHSPacketName( type ), type, \n\t\t\t\t\t\t  length ));\n\t\t\tDEBUG_PRINT(( \"  First fragment of length %d follows.\\n\",\n\t\t\t\t\t\t  sMemDataLeft( stream ) ));\n\t\t\tDEBUG_DUMP_DATA( sessionInfoPtr->receiveBuffer + stell( stream ), \n\t\t\t\t\t\t\t sMemDataLeft( stream ) );\n\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid length %d for %s (%d) handshake packet, should \"\n\t\t\t\t  \"be %d...%d\", length, getSSLHSPacketName( type ), \n\t\t\t\t  type, minSize, min( MAX_PACKET_SIZE, \\\n\t\t\t\t\t\t\t\t\t  sMemDataLeft( stream ) ) ) );\n\t\t}\n\t*packetLength = length;\n\tDEBUG_PRINT(( \"Read %s (%d) handshake packet, length %ld.\\n\", \n\t\t\t\t  getSSLHSPacketName( type ), type, length ));\n\tDEBUG_DUMP_DATA( sessionInfoPtr->receiveBuffer + stell( stream ), \n\t\t\t\t\t length );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRead/Unwrap a Packet\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unwrap an SSL data packet.  There are three forms of this, the first for\n   standard MAC-then-encrypt:\n\n\t\t\t  data\n\t\t\t\t|------------\t\t\t  MAC'd\n\t\t\t\tv======================== Encrypted\n\t+-----+-----+-----------+-----+-----+\n\t| hdr |(IV)\t|\tdata\t| MAC | pad |\n\t+-----+-----+-----------+-----+-----+\n\t\t\t\t|<---- dataMaxLen ----->|\n\t\t\t\t|<- dLen -->|\n\n   The second for encrypt-then-MAC:\n\n\t\t\t  data\n\t\t\t\t|==================\t\t  Encrypted\n\t------------v------------------\t\t  MAC'd\n\t+-----+-----+-----------+-----+-----+\n\t| hdr |(IV)\t|\tdata\t| pad | MAC |\n\t+-----+-----+-----------+-----+-----+\n\t\t\t\t|<---- dataMaxLen ----->|\n\t\t\t\t|<- dLen -->|\n\n   And the third for GCM:\n\n\t\t\t  data\n\t\t\t\t|\n\t------\t\tv================\t\tAuthEnc'd\n\t+-----+-----+---------------+-----+\n\t| hdr |(IV)\t|\tdata\t\t| ICV |\n\t+-----+-----+---------------+-----+\n\t\t\t\t|<--- dataMaxLen ---->|\n\t\t\t\t|<--- dLen ---->|\n\n   These are sufficiently different that we use three distinct functions to\n   do the job.  These decrypt the data, remove the padding if necessary, \n   check and remove the MAC/ICV, and return the payload length.  Processing \n   of the header and IV have already been performed during the packet header \n   read */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int unwrapPacketSSLStd( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   INOUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t *dataLength ) void *data, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t\t\t\t   IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t\t SSL_HAND_LAST ) const int packetType )\n\t{\n\tBYTE dummyDataBuffer[ CRYPT_MAX_HASHSIZE + 8 ];\n\tBOOLEAN badDecrypt = FALSE;\n\tint length = dataMaxLength, payloadLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength >= sessionInfoPtr->authBlocksize && \\\n\t\t\t  dataMaxLength <= MAX_PACKET_SIZE + \\\n\t\t\t\t\t\t\t   sessionInfoPtr->authBlocksize + 256 && \\\n\t\t\t  dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( dataMaxLength % sessionInfoPtr->cryptBlocksize ) == 0 );\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* Decrypt the packet in the buffer.  We allow zero-length blocks (once\n\t   the padding is stripped) because some versions of OpenSSL send these \n\t   as a kludge to work around pre-TLS 1.1 chosen-IV attacks */\n\tstatus = decryptData( sessionInfoPtr, data, length, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status != CRYPT_ERROR_BADDATA )\n\t\t\treturn( status );\n\n\t\t/* There's been a padding error, don't exit immediately but record \n\t\t   that there was a problem for after we've done the MAC'ing.  \n\t\t   Delaying the error reporting until then helps prevent timing \n\t\t   attacks of the kind described by Brice Canvel, Alain Hiltgen,\n\t\t   Serge Vaudenay, and Martin Vuagnoux in \"Password Interception \n\t\t   in a SSL/TLS Channel\", Crypto'03, LNCS No.2729, p.583.  These \n\t\t   are close to impossible in most cases because we delay sending \n\t\t   the close notify over a much longer period than the MAC vs.non-\n\t\t   MAC time difference and because it requires repeatedly connecting\n\t\t   with a fixed-format secret such as a password at the same \n\t\t   location in the packet (which MS Outlook does however manage to \n\t\t   do), but we take this step anyway just to be safe */\n\t\tbadDecrypt = TRUE;\n\t\tlength = min( dataMaxLength, \n\t\t\t\t\t  MAX_PACKET_SIZE + sessionInfoPtr->authBlocksize );\n\t\t}\n\tpayloadLength = length - sessionInfoPtr->authBlocksize;\n\tif( payloadLength < 0 || payloadLength > MAX_PACKET_SIZE )\n\t\t{\n\t\t/* This is a bit of an odd situation and can really only occur if \n\t\t   we've been sent a malformed packet for which removing the padding\n\t\t   reduces the remaining data size to less than the minimum required\n\t\t   to store a MAC.  In order to avoid being used as a timing oracle\n\t\t   we create a minimum-length dummy MAC value and use that as the \n\t\t   MAC for a zero-length packet, with the same error suppression as \n\t\t   for a bad decrypt */\n\t\tdata = dummyDataBuffer;\n\t\tpayloadLength = 0;\n\t\tlength = sessionInfoPtr->authBlocksize;\n\t\tmemset( data, 0, length );\n\t\tbadDecrypt = TRUE;\n\t\t}\n\n\t/* MAC the decrypted data.  The badDecrypt flag suppresses the reporting\n\t   of a MAC error due to an earlier bad decrypt, which has already been\n\t   reported by decryptData() */\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\tstatus = checkMacSSL( sessionInfoPtr, data, length, payloadLength, \n\t\t\t\t\t\t\t  packetType, badDecrypt );\n\telse\n#endif /* USE_SSL3 */\n\t\tstatus = checkMacTLS( sessionInfoPtr, data, length, payloadLength, \n\t\t\t\t\t\t\t  packetType, badDecrypt );\n\tif( badDecrypt )\n\t\t{\n\t\t/* Report the delayed decrypt error, held to this point to make \n\t\t   timing attacks more difficult */\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*dataLength = payloadLength;\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int unwrapPacketTLSMAC( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   INOUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t *dataLength ) void *data, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t\t\t\t   IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t\t SSL_HAND_LAST ) const int packetType )\n\t{\n\tint length = dataMaxLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength >= sessionInfoPtr->authBlocksize && \\\n\t\t\t  dataMaxLength <= MAX_PACKET_SIZE + \\\n\t\t\t\t\t\t\t   sessionInfoPtr->authBlocksize + 256 && \\\n\t\t\t  dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( ( ( dataMaxLength - sessionInfoPtr->authBlocksize ) % \\\n\t\t\t\tsessionInfoPtr->cryptBlocksize ) == 0 );\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* MAC the encrypted data */\n\tstatus = checkMacTLS( sessionInfoPtr, data, length, \n\t\t\t\t\t\t  length - sessionInfoPtr->authBlocksize, \n\t\t\t\t\t\t  packetType, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Decrypt the packet in the buffer.  We allow zero-length blocks (once\n\t   the padding is stripped) because some versions of OpenSSL send these \n\t   as a kludge to work around pre-TLS 1.1 chosen-IV attacks */\n\tstatus = decryptData( sessionInfoPtr, data, \n\t\t\t\t\t\t  length - sessionInfoPtr->authBlocksize, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t*dataLength = length;\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_GCM\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nstatic int unwrapPacketTLSGCM( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t   INOUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t\t\t\t *dataLength ) void *data, \n\t\t\t\t\t\t\t   IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t\t\t   OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t\t\t\t   IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t\t SSL_HAND_LAST ) const int packetType )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tint length = dataMaxLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( dataMaxLength >= sessionInfoPtr->authBlocksize && \\\n\t\t\t  dataMaxLength <= MAX_PACKET_SIZE + \\\n\t\t\t\t\t\t\t   sessionInfoPtr->authBlocksize + 256 && \\\n\t\t\t  dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* Shorten the packet by the size of the ICV */\n\tlength -= sessionInfoPtr->authBlocksize;\n\tif( length < 0 || length > MAX_PACKET_SIZE )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid payload length %d for %s (%d) packet\", length, \n\t\t\t\t  getSSLPacketName( packetType ), packetType ) );\n\t\t}\n\n\t/* Process the packet metadata as GCM AAD */\n\tstatus = macDataTLSGCM( sessionInfoPtr->iCryptInContext, \n\t\t\t\t\t\t\tsslInfo->readSeqNo, sessionInfoPtr->version, \n\t\t\t\t\t\t\tlength, packetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->readSeqNo++;\n\n\t/* Decrypt the packet in the buffer.  We allow zero-length blocks (once\n\t   the padding is stripped) because some versions of OpenSSL send these \n\t   as a kludge to work around pre-TLS 1.1 chosen-IV attacks */\n\tstatus = decryptData( sessionInfoPtr, data, length, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The ICV check has been performed as part of the decryption, so \n\t\t   we're done */\n\t\treturn( status );\n\t\t}\n\n\t/* Tell the caller what the final data size is */\n\t*dataLength = length;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_GCM */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint unwrapPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT_BUFFER( dataMaxLength, \\\n\t\t\t\t\t\t\t\t   *dataLength ) void *data, \n\t\t\t\t\t IN_DATALENGTH const int dataMaxLength, \n\t\t\t\t\t OUT_DATALENGTH_Z int *dataLength,\n\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType )\n\t{\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) && \\\n\t\t\tTEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) );\n\tassert( isWritePtrDynamic( data, dataMaxLength ) );\n\tassert( isWritePtr( dataLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( dataMaxLength >= sessionInfoPtr->authBlocksize && \\\n\t\t\t  dataMaxLength <= MAX_PACKET_SIZE + \\\n\t\t\t\t\t\t\t   sessionInfoPtr->authBlocksize + 256 && \\\n\t\t\t  dataMaxLength < MAX_BUFFER_SIZE );\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\n\t/* Clear return value */\n\t*dataLength = 0;\n\n\t/* Make sure that the length is a multiple of the block cipher size */\n\tif( sessionInfoPtr->cryptBlocksize > 1 )\n\t\t{\n\t\tconst int encryptedDataSize = \\\n\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t   SSL_PFLAG_ENCTHENMAC ) ? \\\n\t\t\t\t\tdataMaxLength - sessionInfoPtr->authBlocksize : \\\n\t\t\t\t\tdataMaxLength;\n\n\t\tif( ( encryptedDataSize % sessionInfoPtr->cryptBlocksize ) != 0 )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid encrypted packet length %d relative to cipher \"\n\t\t\t\t\t  \"block size %d for %s (%d) packet\", dataMaxLength, \n\t\t\t\t\t  sessionInfoPtr->cryptBlocksize, \n\t\t\t\t\t  getSSLPacketName( packetType ), packetType ) );\n\t\t\t}\n\t\t}\n\n\t/* Unwrap the data based on the type of processing that we're using */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC ) )\n\t\t{\n\t\tstatus = unwrapPacketTLSMAC( sessionInfoPtr, data, dataMaxLength, \n\t\t\t\t\t\t\t\t\t dataLength, packetType );\n\t\t}\n\telse\n\t\t{\n#ifdef USE_GCM\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t\t{\n\t\t\tstatus = unwrapPacketTLSGCM( sessionInfoPtr, data, dataMaxLength, \n\t\t\t\t\t\t\t\t\t\t dataLength, packetType );\n\t\t\t}\n\t\telse\n#endif /* USE_GCM */\n\t\t\t{\n\t\t\tstatus = unwrapPacketSSLStd( sessionInfoPtr, data, dataMaxLength, \n\t\t\t\t\t\t\t\t\t\t dataLength, packetType );\n\t\t\t}\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Read an SSL handshake packet.  Since the data transfer phase has its own \n   read/write code we can perform some special-case handling based on this */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int readHSPacketPayload( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\tINOUT_OPT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t\t\t\tIN_DATALENGTH const int payloadLength,\n\t\t\t\t\t\t\t\tIN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t\t  SSL_MSG_LAST_SPECIAL ) \\\n\t\t\t\t\t\t\t\t\tconst int packetType )\n\t{\n\tSTREAM stream;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( ( handshakeInfo == NULL ) || \\\n\t\t\tisWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE );\n\tREQUIRES( ( packetType >= SSL_MSG_FIRST && \\\n\t\t\t\tpacketType <= SSL_MSG_LAST ) || \\\n\t\t\t  ( packetType == SSL_MSG_FIRST_HANDSHAKE || \\\n\t\t\t\tpacketType == SSL_MSG_FIRST_ENCRHANDSHAKE ) );\n\n\t/* Read the packet payload */\n\tstatus = length = \\\n\t\tsread( &sessionInfoPtr->stream, sessionInfoPtr->receiveBuffer, \n\t\t\t   payloadLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tsessionInfoPtr->receiveBufPos = 0;\n\tsessionInfoPtr->receiveBufEnd = length;\n\n\t/* If we timed out during the handshake phase, treat it as a hard \n\t   timeout error */\n\tif( length != payloadLength )\n\t\t{\n\t\tretExt( CRYPT_ERROR_TIMEOUT,\n\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t  \"Timed out reading packet data for %s (%d) packet, only \"\n\t\t\t\t  \"got %d of %d bytes\", getSSLPacketName( packetType ), \n\t\t\t\t  packetType, length, payloadLength ) );\n\t\t}\n\n\t/* If we're not hashing the payload, we're done */\n\tif( handshakeInfo == NULL )\n\t\treturn( CRYPT_OK );\n\n\t/* Hash the payload data that we've just read */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer, length );\n\tstatus = hashHSPacketRead( handshakeInfo, &stream );\n\tsMemDisconnect( &stream );\n\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readHSPacketSSL( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t INOUT_OPT SSL_HANDSHAKE_INFO *handshakeInfo, \n\t\t\t\t\t OUT_DATALENGTH_Z int *packetLength, \n\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t   SSL_MSG_LAST_SPECIAL ) const int packetType )\n\t{\n\tSTREAM stream;\n\tBYTE headerBuffer[ SSL_HEADER_SIZE + CRYPT_MAX_IVSIZE + 8 ];\n\tconst int localPacketType = \\\n\t\t\t\t\t( packetType == SSL_MSG_FIRST_ENCRHANDSHAKE ) ? \\\n\t\t\t\t\tSSL_MSG_HANDSHAKE : packetType;\n\tint firstByte, bytesToRead, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( ( handshakeInfo == NULL ) || \\\n\t\t\tisWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( packetLength, sizeof( int ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( ( packetType >= SSL_MSG_FIRST && \\\n\t\t\t\tpacketType <= SSL_MSG_LAST ) || \\\n\t\t\t  ( packetType == SSL_MSG_FIRST_HANDSHAKE || \\\n\t\t\t\tpacketType == SSL_MSG_FIRST_ENCRHANDSHAKE ) );\n\tREQUIRES( sessionInfoPtr->receiveBufStartOfs >= SSL_HEADER_SIZE && \\\n\t\t\t  sessionInfoPtr->receiveBufStartOfs < \\\n\t\t\t\t\t\t\tSSL_HEADER_SIZE + CRYPT_MAX_IVSIZE );\n\n\t/* Clear return value */\n\t*packetLength = 0;\n\n\t/* Read and process the header */\n\tstatus = readFixedHeaderAtomic( sessionInfoPtr, headerBuffer,\n\t\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufStartOfs );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* This is the first packet for which encryption has been turned on.  \n\t\t   Some implementations handle crypto failures badly, simply closing \n\t\t   the connection rather than returning an alert message as they're \n\t\t   supposed to.  In particular IIS, due to the separation of \n\t\t   protocol and transport layers, has the HTTP server layer close \n\t\t   the connect before any error-handling at the SSL protocol layer \n\t\t   can take effect.  To deal with this problem, we assume that a\n\t\t   closed connection in this situation is due to a crypto problem\n\t\t   rather than a networking problem */\n\t\tif( status == CRYPT_ERROR_READ && \\\n\t\t\tpacketType == SSL_MSG_FIRST_ENCRHANDSHAKE )\n\t\t\t{\n\t\t\tretExtErr( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t\t   ( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t\t\t SESSION_ERRINFO, \n\t\t\t\t\t\t \"Other side unexpectedly closed the connection, \"\n\t\t\t\t\t\t \"probably due to incorrect encryption keys being \"\n\t\t\t\t\t\t \"negotiated during the handshake: \" ) );\n\t\t\t}\n\t\treturn( status );\n\t\t}\n\tfirstByte = byteToInt( headerBuffer[ 0 ] );\n\n\t/* Check for an SSL alert message */\n\tif( firstByte == SSL_MSG_ALERT )\n\t\t{\n\t\treturn( processAlert( sessionInfoPtr, headerBuffer, \n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufStartOfs, NULL ) );\n\t\t}\n\n\t/* Decode and process the SSL packet header.  If this is the first \n\t   packet sent by the other side we check for various special-case \n\t   conditions and handle them specially.  Since the first byte is \n\t   supposed to be an SSL_MSG_HANDSHAKE (value 22 or 0x16) which in \n\t   ASCII would be a SYN we can quickly weed out use of non-encrypted\n\t   protocols like SMTP, POP3, IMAP, and FTP that are often used with \n\t   SSL, and the obsolete SSLv2 protocol */\n\tif( packetType == SSL_MSG_FIRST_HANDSHAKE && \\\n\t\tfirstByte != SSL_MSG_HANDSHAKE )\n\t\t{\n\t\t/* Try and detect whether the other side is talking something that \n\t\t   isn't SSL, typically SMTP, POP3, IMAP, or FTP, which are used\n\t\t   with SSL but require explicit negotiation to switch to xxx-with-\n\t\t   SSL.  In theory we could check for more explicit indications of\n\t\t   one of these protocols (\"220\" for SMTP and FTP, \"+OK\" for POP3\n\t\t   and \"OK\" for IMAP) but there's a danger of mis-identifying the\n\t\t   other protocol and returning a message that's worse than a\n\t\t   generic bad-data, so for now we just report the text that was \n\t\t   sent and let the user figure it out */\n\t\tif( strIsPrintable( headerBuffer, SSL_HEADER_SIZE ) )\n\t\t\t{\n\t\t\tchar textBuffer[ CRYPT_MAX_TEXTSIZE + 8 ];\n\n\t\t\tmemcpy( textBuffer, headerBuffer, SSL_HEADER_SIZE );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"%s sent ASCII text string beginning '%s...', is \"\n\t\t\t\t\t  \"this the correct address/port?\",\n\t\t\t\t\t  isServer( sessionInfoPtr ) ? \"Server\" : \"Client\",\n\t\t\t\t\t  sanitiseString( textBuffer, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t\t  SSL_HEADER_SIZE ) ) );\n\t\t\t}\n\n\t\t/* Detect whether the other side is using the obsolete SSLv2 \n\t\t   protocol */\n\t\tif( firstByte == SSL_MSG_V2HANDSHAKE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Client sent obsolete handshake for the insecure SSLv2 \"\n\t\t\t\t\t  \"protocol\" ) );\n\t\t\t}\n\t\t}\n\tsMemConnect( &stream, headerBuffer, sessionInfoPtr->receiveBufStartOfs );\n\tstatus = checkPacketHeader( sessionInfoPtr, &stream, &bytesToRead, \n\t\t\t\t\t\tlocalPacketType, \n\t\t\t\t\t\t( localPacketType == SSL_MSG_CHANGE_CIPHER_SPEC ) ? \\\n\t\t\t\t\t\t\t1 : MIN_PACKET_SIZE,\n\t\t\t\t\t\tsessionInfoPtr->receiveBufSize ); \n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the payload packet(s) */\n\tstatus = readHSPacketPayload( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t  bytesToRead, localPacketType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*packetLength = bytesToRead;\n\tDEBUG_DUMP_SSL( headerBuffer, sessionInfoPtr->receiveBufStartOfs,\n\t\t\t\t\tsessionInfoPtr->receiveBuffer, bytesToRead );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read the next handshake stream packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint refreshHSStream( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM *stream = &handshakeInfo->stream;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* If there's still data present in the stream, there's nothing left\n\t   to do */\n\tlength = sMemDataLeft( stream );\n\tif( length > 0 )\n\t\t{\n\t\t/* We need enough data to contain at least a handshake packet header \n\t\t   in order to continue */\n\t\tif( length < 1 + LENGTH_SIZE || length > MAX_BUFFER_SIZE )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t\t  \"Invalid handshake packet data length %d\", length ) );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Refill the stream */\n\tsMemDisconnect( stream );\n\tstatus = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,\n\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, length );\n\n\treturn( CRYPT_OK );\n\t}\t\t\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tReceive SSL Alerts\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* SSL alert information */\n\ntypedef struct {\n\tconst int type;\t\t\t\t/* SSL alert type */\n\tconst char *message;\t\t/* Description string */\n\tconst int messageLength;\n\tconst int cryptlibError;\t/* Equivalent cryptlib error status */\n\t} ALERT_INFO;\n\nstatic const ALERT_INFO alertInfo[] = {\n\t{ SSL_ALERT_CLOSE_NOTIFY, \"Close notify\", 12, CRYPT_ERROR_COMPLETE },\n\t{ SSL_ALERT_UNEXPECTED_MESSAGE, \"Unexpected message\", 18, CRYPT_ERROR_FAILED },\n\t{ SSL_ALERT_BAD_RECORD_MAC, \"Bad record MAC\", 14, CRYPT_ERROR_SIGNATURE },\n\t{ TLS_ALERT_DECRYPTION_FAILED, \"Decryption failed\", 17, CRYPT_ERROR_WRONGKEY },\n\t{ TLS_ALERT_RECORD_OVERFLOW, \"Record overflow\", 15, CRYPT_ERROR_OVERFLOW },\n\t{ SSL_ALERT_DECOMPRESSION_FAILURE, \"Decompression failure\", 21, CRYPT_ERROR_FAILED },\n\t{ SSL_ALERT_HANDSHAKE_FAILURE, \"Handshake failure\", 17, CRYPT_ERROR_FAILED },\n\t{ SSL_ALERT_NO_CERTIFICATE, \"No certificate\", 14, CRYPT_ERROR_PERMISSION },\n\t{ SSL_ALERT_BAD_CERTIFICATE, \"Bad certificate\", 15, CRYPT_ERROR_INVALID },\n\t{ SSL_ALERT_UNSUPPORTED_CERTIFICATE, \"Unsupported certificate\", 23, CRYPT_ERROR_INVALID },\n\t{ SSL_ALERT_CERTIFICATE_REVOKED, \"Certificate revoked\", 19, CRYPT_ERROR_INVALID },\n\t{ SSL_ALERT_CERTIFICATE_EXPIRED, \"Certificate expired\", 19, CRYPT_ERROR_INVALID },\n\t{ SSL_ALERT_CERTIFICATE_UNKNOWN, \"Certificate unknown\", 19, CRYPT_ERROR_INVALID },\n\t{ TLS_ALERT_ILLEGAL_PARAMETER, \"Illegal parameter\", 17, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_UNKNOWN_CA, \"Unknown CA\", 10, CRYPT_ERROR_INVALID },\n\t{ TLS_ALERT_ACCESS_DENIED, \"Access denied\", 13, CRYPT_ERROR_PERMISSION },\n\t{ TLS_ALERT_DECODE_ERROR, \"Decode error\", 12, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_DECRYPT_ERROR, \"Decrypt error\", 13, CRYPT_ERROR_WRONGKEY },\n\t{ TLS_ALERT_EXPORT_RESTRICTION, \"Export restriction\", 18, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_PROTOCOL_VERSION, \"Protocol version\", 16, CRYPT_ERROR_NOTAVAIL },\n\t{ TLS_ALERT_INSUFFICIENT_SECURITY, \"Insufficient security\", 21, CRYPT_ERROR_NOSECURE },\n\t{ TLS_ALERT_INTERNAL_ERROR, \"Internal error\", 14, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_INAPPROPRIATE_FALLBACK, \"Inappropriate fallback\", 22, CRYPT_ERROR_NOSECURE },\n\t{ TLS_ALERT_USER_CANCELLED, \"User cancelled\", 14, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_NO_RENEGOTIATION, \"No renegotiation\", 16, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_UNSUPPORTED_EXTENSION, \"Unsupported extension\", 21, CRYPT_ERROR_NOTAVAIL },\n\t{ TLS_ALERT_CERTIFICATE_UNOBTAINABLE, \"Certificate unobtainable\", 24, CRYPT_ERROR_NOTFOUND },\n\t{ TLS_ALERT_UNRECOGNIZED_NAME, \"Unrecognized name\", 17, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE, \"Bad certificate status response\", 31, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE, \"Bad certificate hash value\", 26, CRYPT_ERROR_FAILED },\n\t{ TLS_ALERT_UNKNOWN_PSK_IDENTITY, \"Unknown PSK identity\", 20, CRYPT_ERROR_NOTFOUND },\n\t{ CRYPT_ERROR, NULL }, { CRYPT_ERROR, NULL }\n\t};\n\n/* Process an alert packet.  IIS often just drops the connection rather than \n   sending an alert when it encounters a problem.  In addition when \n   communicating with IIS the only error indication that we sometimes get \n   will be a \"Connection closed by remote host\" rather than an SSL-level \n   error message, see the comment in readHSPacketSSL() for the reason for \n   this.  Also, when it encounters an unknown certificate MSIE will complete \n   the handshake and then close the connection (via a proper close alert in \n   this case rather than just closing the connection), wait while the user \n   clicks OK several times, and then restart the connection via an SSL \n   resume.  Netscape-derived browsers in contrast just hope that the session \n   won't time out while waiting for the user to click OK.  As a result \n   cryptlib sees a closed connection and aborts the session setup process \n   when talking to MSIE, requiring a second call to the session setup to \n   continue with the resumed session */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint processAlert( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t  IN_BUFFER( headerLength ) const void *header, \n\t\t\t\t  IN_DATALENGTH const int headerLength,\n\t\t\t\t  OUT_ENUM_OPT( READINFO ) READSTATE_INFO *readInfo )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 256 + 8 ];\n\tint length, type, i, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( header, headerLength ) );\n\tassert( readInfo == NULL || \\\n\t\t\tisWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( headerLength > 0 && headerLength < MAX_BUFFER_SIZE );\n\n\t/* Alerts are fatal errors */\n\tif( readInfo != NULL )\n\t\t*readInfo = READINFO_FATAL;\n\n\t/* Process the alert packet header */\n\tsMemConnect( &stream, header, headerLength );\n\tstatus = checkPacketHeader( sessionInfoPtr, &stream, &length, \n\t\t\t\t\t\t\t\tSSL_MSG_ALERT, ALERTINFO_SIZE,\n\t\t\t\t\t\t\t\tsessionInfoPtr->receiveBufSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tif( TEST_FLAG( sessionInfoPtr->flags, SESSION_FLAG_ISSECURE_READ ) )\n\t\t{\n\t\tif( length < ALERTINFO_SIZE || length > 256 )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\telse\n\t\t{\n\t\tif( length != ALERTINFO_SIZE )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid alert message length %d\", length ) );\n\t\t}\n\n\t/* Read and process the alert packet */\n\tstatus = sread( &sessionInfoPtr->stream, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tif( status != length )\n\t\t{\n\t\t/* If we timed out before we could get all of the alert data, bail\n\t\t   out without trying to perform any further processing.  We're \n\t\t   about to shut down the session anyway so there's no point in \n\t\t   potentially stalling for ages trying to find a lost byte */\n\t\tsendCloseAlert( sessionInfoPtr, TRUE );\n\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\t\tretExt( CRYPT_ERROR_TIMEOUT, \n\t\t\t\t( CRYPT_ERROR_TIMEOUT, SESSION_ERRINFO, \n\t\t\t\t  \"Timed out reading alert message, only got %d of %d \"\n\t\t\t\t  \"bytes\", status, length ) );\n\t\t}\n\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t   SESSION_FLAG_ISSECURE_READ ) && \\\n\t\t( length > ALERTINFO_SIZE || \\\n\t\t  isStreamCipher( sessionInfoPtr->cryptAlgo ) ) )\n\t\t{\n\t\t/* All errors beyond this point are fatal crypto errors */\n\t\tif( readInfo != NULL )\n\t\t\t*readInfo = READINFO_FATAL_CRYPTO;\n\n\t\t/* We only try and decrypt if the alert information is big enough to \n\t\t   be encrypted, i.e. it contains the fixed-size data + padding.  \n\t\t   This situation can occur if there's an error moving from the non-\n\t\t   secure to the secure state.  However, if it's a stream cipher the \n\t\t   ciphertext and plaintext are the same size so we always have to \n\t\t   try the decryption.\n\n\t\t   Before calling unwrapPacketSSL() we set the receive-buffer end-\n\t\t   position indicator if it hasn't already been set as part of a\n\t\t   read of other data.  This isn't otherwise explicitly used but is \n\t\t   required for a sanity check in the unwrap code */\n\t\tif( sessionInfoPtr->receiveBufEnd <= 0 )\n\t\t\tsessionInfoPtr->receiveBufEnd = length;\n\t\tstatus = unwrapPacketSSL( sessionInfoPtr, buffer, length, &length, \n\t\t\t\t\t\t\t\t  SSL_MSG_ALERT );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsendCloseAlert( sessionInfoPtr, TRUE );\n\t\t\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that we've got a valid alert message */\n\tif( buffer[ 0 ] != SSL_ALERTLEVEL_WARNING && \\\n\t\tbuffer[ 0 ] != SSL_ALERTLEVEL_FATAL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid alert message level %d, expected %d or %d\", \n\t\t\t\t  buffer[ 0 ], SSL_ALERTLEVEL_WARNING, \n\t\t\t\t  SSL_ALERTLEVEL_FATAL ) );\n\t\t}\n\n\t/* Everything seems OK so far, we're back to standard fatal errors \n\t   again */\n\tif( readInfo != NULL )\n\t\t*readInfo = READINFO_FATAL;\n\n\t/* Tell the other side that we're going away */\n\tsendCloseAlert( sessionInfoPtr, TRUE );\n\tSET_FLAG( sessionInfoPtr->flags, SESSION_FLAG_SENDCLOSED );\n\n\t/* Process the alert information.  In theory we should also make the \n\t   session non-resumable if the other side goes away without sending a \n\t   close alert, but this leads to too many problems with non-resumable \n\t   sessions if we do so.  For example many protocols do their own \n\t   end-of-data indication (e.g. \"Connection: close\" in HTTP and BYE in \n\t   SMTP) and so don't bother with a close alert.  In other cases \n\t   implementations just drop the connection without sending a close \n\t   alert, carried over from many early Unix protocols that used a \n\t   connection close to signify end-of-data, which has caused problems \n\t   ever since for newer protocols that want to keep the connection open.  \n\t   This behaviour is nearly universal for some protocols tunneled over \n\t   SSL, for example vsftpd by default disables close-alert handling\n\t   because the author was unable to find an FTP client anywhere that \n\t   uses it (see the manpage entry for \"strict_ssl_write_shutdown\").  \n\t   Other implementations still send their alert but then immediately \n\t   close the connection.  Because of this haphazard approach to closing \n\t   connections many implementations allow a session to be resumed even \n\t   if no close alert is sent.  In order to be compatible with this \n\t   behaviour, we do the same (thus perpetuating the problem).\n\t   \n\t   If required this can be fixed by calling deleteSessionCacheEntry() \n\t   if the connection is closed without a close alert having been sent */\n\ttype = buffer[ 1 ];\n\tLOOP_MED( i = 0,\n\t\t\t  alertInfo[ i ].type != CRYPT_ERROR && \\\n\t\t\t\talertInfo[ i ].type != type && \\\n\t\t\t\ti < FAILSAFE_ARRAYSIZE( alertInfo, ALERT_INFO ),\n\t\t\t  i++ );\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( i < FAILSAFE_ARRAYSIZE( alertInfo, ALERT_INFO ) );\n\tif( alertInfo[ i ].type == CRYPT_ERROR )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Unknown alert message type %d at alert level %d\", \n\t\t\t\t  type, buffer[ 0 ] ) );\n\t\t}\n\tretExtStr( alertInfo[ i ].cryptlibError,\n\t\t\t   ( alertInfo[ i ].cryptlibError, SESSION_ERRINFO, \n\t\t\t\t alertInfo[ i ].message, alertInfo[ i ].messageLength,\n\t\t\t\t ( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL ) ? \\\n\t\t\t\t\t\"Received SSL alert message: \" : \\\n\t\t\t\t\t\"Received TLS alert message: \" ) );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_suites.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TLS Cipher Suites\t\t\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCipher Suite Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The monster list of cryptlib's SSL/TLS cipher suites (the full list is \n   much, much longer than this).  There are a pile of DH cipher suites, in \n   practice only DHE is used, DH requires the use of X9.42 DH certificates \n   (there aren't any) and DH_anon uses unauthenticated DH which implementers \n   seem to have an objection to even though it's not much different in \n   effect from the way RSA cipher suites are used in practice.\n\n   To keep things simple for the caller we only allow RSA auth for DH key\n   agreement and not DSA, since the former also automatically works for the\n   far more common RSA key exchange that's usually used for key setup.\n   In theory we should only allow ECDSA for ECDH, since anyone who wants to \n   make the ECC fashion statement wouldn't be falling back to RSA for the \n   server authentication, however due to the practical nonexistence of ECDSA\n   certificates except from boutique CAs everyone who does ECDH uses it with\n   RSA certificates, so we have to support the rather odd combination of\n   ECDH for keyex but RSA for authentication.\n\n   We prefer AES-128 to AES-256 since -256 has a weaker key schedule than\n   -128, so if anyone's going to attack it they'll go for the key schedule\n   rather than the (mostly irrelevant) -128 vs. -256.\n\n   In some piece of SuiteB bizarritude a number of suites that have a\n   xxx_WITH_AES_128_xxx_SHA256 only have a xxx_WITH_AES_256_xxx_SHA384\n   equivalent but no xxx_WITH_AES_256_xxx_SHA256, which is why there are a\n   number of suites with apparently-mismatched AES-128 only options.\n\n   The number of suites and different configuration options are sufficiently\n   complex that we can't use a fixed table for them but have to dynamically\n   build them up at runtime from the following sub-tables */\n\n#define MAX_CIPHERSUITE_TBLSIZE\t\t64\n\nstatic const CIPHERSUITE_INFO cipherSuiteDH[] = {\n\t/* AES with DH */\n\t{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 32, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_DH },\n\t{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, CIPHERSUITE_FLAG_DH },\n\n\t/* 3DES with DH */\n#ifdef USE_3DES\n\t{ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_3DES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_DH },\n#endif /* USE_3DES */\n\n\t/* End-of-list marker */\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE },\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE }\n\t};\n\n#ifdef USE_ECDH\n\nstatic const CIPHERSUITE_INFO cipherSuiteECC[] = {\n#ifdef USE_ECDSA\n\t/* ECDH with ECDSA */\n\t{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 },\n/*\t{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA384, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA384\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 48, 16, 48, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 }, */\n\t{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC },\n\t{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC },\n  #ifdef USE_3DES\n\t{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_3DES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC },\n  #endif /* USE_3DES */\n#endif /* USE_ECDSA */\n\n\t/* ECDH with RSA, see the comment at the start for why this is used */\n\t{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 32, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 },\n/*\t{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 48, 32, 48, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 }, */\n\t{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC }, \n\t{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_ECC },\n\n\t/* End-of-list marker */\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE },\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE }\n\t};\n#endif /* USE_ECDH */\n\n#ifdef USE_GCM\n\nstatic const CIPHERSUITE_INFO cipherSuiteGCM[] = {\n\t/* ECDH with ECDSA and AES-GCM */\n\t{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },\n/*\t{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA384, \n\t  DESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA384\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 48, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 }, */\n\n\t/* ECDH with RSA and AES-GCM, see the comment at the start for why this \n\t   is used */\n\t{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \n\t  DESCRIPTION( \"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\" )\n\t  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 48, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },\n\n\t/* AES-GCM with DH */\n\t{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },\n/*\t{ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,\n\t  DESCRIPTION( \"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 }, */\n\n\t/* AES-GCM with RSA */\n\t{ TLS_RSA_WITH_AES_128_GCM_SHA256,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_128_GCM_SHA256\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },\n/*\t{ TLS_RSA_WITH_AES_256_GCM_SHA384,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_256_GCM_SHA384\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 48, 16, GCMICV_SIZE, \n\t  CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 }, */\n\n\t/* End-of-list marker */\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE },\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE }\n\t};\n#endif /* USE_GCM */\n\nstatic const CIPHERSUITE_INFO cipherSuitePSK[] = {\n\t/* PSK with PFS */\n\t{ TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK | CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_DHE_PSK_WITH_AES_128_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_PSK_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK | CIPHERSUITE_FLAG_DH },\n\t{ TLS_DHE_PSK_WITH_AES_256_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_PSK_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK | CIPHERSUITE_FLAG_DH },\n#ifdef USE_3DES\n\t{ TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,\n\t  DESCRIPTION( \"TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA\" )\n\t  CRYPT_ALGO_DH, CRYPT_ALGO_NONE, CRYPT_ALGO_3DES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK | CIPHERSUITE_FLAG_DH },\n#endif /* USE_3DES */\n\n\t/* PSK without PFS */\n\t{ TLS_PSK_WITH_AES_128_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_PSK_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK | CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_PSK_WITH_AES_128_CBC_SHA,\n\t  DESCRIPTION( \"TLS_PSK_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK },\n\t{ TLS_PSK_WITH_AES_256_CBC_SHA,\n\t  DESCRIPTION( \"TLS_PSK_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK },\n#ifdef USE_3DES\n\t{ TLS_PSK_WITH_3DES_EDE_CBC_SHA,\n\t  DESCRIPTION( \"TLS_PSK_WITH_3DES_EDE_CBC_SHA\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_3DES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_PSK },\n#endif /* USE_3DES */\n\n\t/* End-of-list marker */\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE },\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE }\n\t};\n\n#ifdef USE_RSA_SUITES\n\nstatic const CIPHERSUITE_INFO cipherSuiteRSA[] = {\n\t/* AES with RSA */\n\t{ TLS_RSA_WITH_AES_128_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_128_CBC_SHA256\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_RSA_WITH_AES_256_CBC_SHA256,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_256_CBC_SHA256\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA2, 0, 32, SHA2MAC_SIZE, \n\t  CIPHERSUITE_FLAG_TLS12 },\n\t{ TLS_RSA_WITH_AES_128_CBC_SHA,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_128_CBC_SHA\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_NONE },\n\t{ TLS_RSA_WITH_AES_256_CBC_SHA,\n\t  DESCRIPTION( \"TLS_RSA_WITH_AES_256_CBC_SHA\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_NONE },\n\n\t/* 3DES with RSA */\n#ifdef USE_3DES\n\t{ SSL_RSA_WITH_3DES_EDE_CBC_SHA,\n\t  DESCRIPTION( \"SSL_RSA_WITH_3DES_EDE_CBC_SHA\" )\n\t  CRYPT_ALGO_RSA, CRYPT_ALGO_RSA, CRYPT_ALGO_3DES,\n\t  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE, \n\t  CIPHERSUITE_FLAG_NONE },\n#endif /* USE_3DES */\n\n\t/* End-of-list marker */\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE },\n\t{ SSL_NULL_WITH_NULL,\n\t  DESCRIPTION( \"End-of-list marker\" )\n\t  CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t  CRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE }\n\t};\n#endif /* USE_RSA_SUITES */\n\n/* Tables defining the arrangement of the above sets of suites into a \n   single monster list.  The order of adding suites is as follows:\n\n\t[ Optional special-case suites, for testing or custom configurations ].\n\tPSK suites, since they provide proper mutual authentication. \n\tECC suites if PREFER_ECC is defined, since anyone wanting to make this \n\t\t\tparticular fashion statement probably wants to actually use the \n\t\t\tsuites rather than having them ignored as the 25th-ranked \n\t\t\toption.  (GCM with ECC is a variant of this, this is even more \n\t\t\tof a fashion statement and really only makes sense with ECC).\n\tDH suites.\n\tRSA suites with strong ciphers.\n\tMisc RSA suites with also-ran ciphers */\n\ntypedef struct {\n\tconst CIPHERSUITE_INFO *cipherSuites;\n\tconst int cipherSuiteCount;\n\t} CIPHERSUITES_LIST;\n\nstatic const CIPHERSUITES_LIST cipherSuitesList[] = {\n\t{ cipherSuitePSK, FAILSAFE_ARRAYSIZE( cipherSuitePSK, CIPHERSUITE_INFO ) },\n#ifdef PREFER_ECC\n  #ifdef USE_GCM\n\t{ cipherSuiteGCM, FAILSAFE_ARRAYSIZE( cipherSuiteGCM, CIPHERSUITE_INFO ) },\n  #endif /* USE_GCM */\n  #if defined( USE_ECDH )\n\t{ cipherSuiteECC, FAILSAFE_ARRAYSIZE( cipherSuiteECC, CIPHERSUITE_INFO ) },\n  #endif /* USE_ECDH */\n#endif /* PREFER_ECC */\n\t{ cipherSuiteDH, FAILSAFE_ARRAYSIZE( cipherSuiteDH, CIPHERSUITE_INFO ) },\n#ifdef USE_RSA_SUITES \n\t{ cipherSuiteRSA, FAILSAFE_ARRAYSIZE( cipherSuiteRSA, CIPHERSUITE_INFO ) },\n#endif /* USE_RSA_SUITES */\n#ifndef PREFER_ECC\n  #ifdef USE_GCM\n\t{ cipherSuiteGCM, FAILSAFE_ARRAYSIZE( cipherSuiteGCM, CIPHERSUITE_INFO ) },\n  #endif /* USE_GCM */\n  #if defined( USE_ECDH )\n\t{ cipherSuiteECC, FAILSAFE_ARRAYSIZE( cipherSuiteECC, CIPHERSUITE_INFO ) },\n  #endif /* USE_ECDH */\n#endif /* !PREFER_ECC */\n\t{ NULL, 0 }, { NULL, 0 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCipher Suite Definitions for Suite B\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're running in a Suite B configuration then we don't bother with any\n   of the standard cipher suites but only provide Suite B suites */\n\n#if defined( CONFIG_SUITEB )\n\n#if defined( _MSC_VER ) || defined( __GNUC__ )\n  #pragma message( \"  Building with custom suite: Suite B\" )\n  #if defined( CONFIG_SUITEB_TESTS )\n\t#pragma message( \"  Building with custom suite: Suite B test suites\" )\n  #endif /* Suite B special test suites */\n#endif /* VC++ */\n\n/* 256-bit Suite B suites */\n\nstatic const CIPHERSUITE_INFO suiteBP384GCM = { \n\tTLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \n\tDESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\" )\n\tCRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\tCRYPT_ALGO_HMAC_SHA2, bitsToBytes( 384 ), 32, GCMICV_SIZE, \n\tCIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 \n\t};\n\n/* 128-bit Suite B suites */\n\nstatic const CIPHERSUITE_INFO suiteBP256GCM = { \n\tTLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \n\tDESCRIPTION( \"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\" )\n\tCRYPT_ALGO_ECDH, CRYPT_ALGO_ECDSA, CRYPT_ALGO_AES,\n\tCRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE, \n\tCIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 \n\t};\n\n/* End-of-list marker */\n\nstatic const CIPHERSUITE_INFO suiteBEOL = { \n\tSSL_NULL_WITH_NULL,\n\tDESCRIPTION( \"End-of-list marker\" )\n\tCRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\tCRYPT_ALGO_NONE, 0, 0, 0, CIPHERSUITE_FLAG_NONE \n\t};\n\n/* Since the only suites that we're enabling are the Suite B ones, we \n   override the default getCipherSuiteInfo() with our own one */\n\nCHECK_RETVAL \\\nint getSuiteBCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,\n\t\t\t\t\t\t\t  OUT_INT_Z int *noSuiteEntries,\n\t\t\t\t\t\t\t  const BOOLEAN isServer,\n\t\t\t\t\t\t\t  IN_FLAGS_Z( SSL ) const int suiteBinfo )\n\t{\n\tstatic const CIPHERSUITE_INFO *cipherSuite192InfoTbl[] = \\\n\t\t{ &suiteBP384GCM, &suiteBEOL, &suiteBEOL };\n\tstatic const CIPHERSUITE_INFO *cipherSuite128InfoTbl[] = \\\n\t\t{ &suiteBP256GCM, &suiteBP384GCM, &suiteBEOL, &suiteBEOL };\n\tBOOLEAN is128bitLevel = ( ( suiteBinfo & SSL_PFLAG_SUITEB ) == \\\n\t\t\t\t\t\t\t\t\tSSL_PFLAG_SUITEB_128 ) ? TRUE : FALSE;\n\n\tassert( isReadPtr( cipherSuiteInfoPtrPtrPtr, \\\n\t\t\t\t\t   sizeof( CIPHERSUITE_INFO ** ) ) );\n\tassert( isWritePtr( noSuiteEntries, sizeof( int ) ) );\n\n\tREQUIRES( isServer == TRUE || isServer == FALSE );\n\tREQUIRES( suiteBinfo >= SSL_PFLAG_NONE && suiteBinfo < SSL_PFLAG_MAX );\n\n\t/* Depending on the security level that we're configured for we either \n\t   prefer the 128-bit suites or the 192-bit suites */\n\tif( is128bitLevel )\n\t\t{\n\t\t*cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \\\n\t\t\t\t\t\t\t\t\tcipherSuite128InfoTbl;\t/* For gcc */\n\t\t*noSuiteEntries = FAILSAFE_ARRAYSIZE( cipherSuite128InfoTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t  CIPHERSUITE_INFO * );\n\t\t}\n\telse\n\t\t{\n\t\t*cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \\\n\t\t\t\t\t\t\t\t\tcipherSuite192InfoTbl;\t/* For gcc */\n\t\t*noSuiteEntries = FAILSAFE_ARRAYSIZE( cipherSuite192InfoTbl, \\\n\t\t\t\t\t\t\t\t\t\t\t  CIPHERSUITE_INFO * );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Remap the usual getCipherSuiteInfo() into an alternative name that\n   doesn't clash with the Suite B replacement */\n\n#undef getCipherSuiteInfo\n#define\tgetCipherSuiteInfo\tgetCipherSuiteInfoOriginal\n\n#endif /* CONFIG_SUITEB */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCipher Suite Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Build the single unified list of ciphers suites in preferred-algorithm\n   order */\n\nCHECK_RETVAL \\\nstatic int addCipherSuiteInfo( INOUT CIPHERSUITE_INFO **cipherSuiteTbl, \n\t\t\t\t\t\t\t   IN_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE ) \\\n\t\t\t\t\t\t\t\t\tconst int cipherSuiteTblCount,\n\t\t\t\t\t\t\t   OUT_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE ) \\\n\t\t\t\t\t\t\t\t\tint *newCipherSuiteTblCount, \n\t\t\t\t\t\t\t   const CIPHERSUITE_INFO *cipherSuites,\n\t\t\t\t\t\t\t   IN_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE / 2 ) \\\n\t\t\t\t\t\t\t\t\tconst int cipherSuitesCount )\n\t{\n\tint srcIndex, destIndex, LOOP_ITERATOR;\n\n\tassert( isReadPtr( cipherSuiteTbl, \\\n\t\t\t\t\t   sizeof( CIPHERSUITE_INFO * ) * MAX_CIPHERSUITE_TBLSIZE ) );\n\tassert( isWritePtr( newCipherSuiteTblCount, sizeof( int ) ) );\n\tassert( isReadPtr( cipherSuites,\n\t\t\t\t\t   sizeof( CIPHERSUITE_INFO * ) * 2 ) );\n\n\tREQUIRES( cipherSuiteTblCount >= 0 && \\\n\t\t\t  cipherSuiteTblCount < MAX_CIPHERSUITE_TBLSIZE );\n\tREQUIRES( cipherSuitesCount >= 0 && \\\n\t\t\t  cipherSuitesCount < MAX_CIPHERSUITE_TBLSIZE / 2 );\n\n\t/* Clear return value.  Unlike standard practice this doesn't set it to\n\t   zero but to the existing count, making the call a no-op */\n\t*newCipherSuiteTblCount = cipherSuiteTblCount;\n\n\t/* Add any new suites to the existing table */\n\tLOOP_LARGE( ( srcIndex = 0, destIndex = cipherSuiteTblCount ), \n\t\t\t\tcipherSuites[ srcIndex ].cipherSuite != SSL_NULL_WITH_NULL && \\\n\t\t\t\t\tsrcIndex < cipherSuitesCount && \\\n\t\t\t\t\tdestIndex < MAX_CIPHERSUITE_TBLSIZE,\n\t\t\t\t( srcIndex++, destIndex++ ) )\n\t\t{\n\t\tcipherSuiteTbl[ destIndex ] = ( CIPHERSUITE_INFO * ) \\\n\t\t\t\t\t\t\t\t\t  &cipherSuites[ srcIndex ];\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\tENSURES( srcIndex < cipherSuitesCount );\n\tENSURES( destIndex < MAX_CIPHERSUITE_TBLSIZE );\n\n\t*newCipherSuiteTblCount = destIndex;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL \\\nint getCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,\n\t\t\t\t\t\tOUT_INT_Z int *noSuiteEntries )\n\t{\n\tstatic CIPHERSUITE_INFO *cipherSuiteInfoTbl[ MAX_CIPHERSUITE_TBLSIZE + 8 ];\n\tstatic BOOLEAN cipherSuitInfoInited = FALSE;\n\tstatic int cipherSuiteCount = 0;\n\tint status;\n\n\tassert( isReadPtr( cipherSuiteInfoPtrPtrPtr, \\\n\t\t\t\t\t   sizeof( CIPHERSUITE_INFO ** ) ) );\n\tassert( isWritePtr( noSuiteEntries, sizeof( int ) ) );\n\n\t/* Dynamically set up the monster table of cipher suites.  Note that \n\t   this isn't thread-safe, but since it performs the setup in a\n\t   completely deterministic manner it doesn't matter if the extremely\n\t   unlikely situation of two threads initialising the array at the same\n\t   time occurs, since they're initialising it identically */\n\tif( !cipherSuitInfoInited )\n\t\t{\n\t\tstatic const CIPHERSUITE_INFO endOfList = {\n\t\t\tSSL_NULL_WITH_NULL,\n\t\t\tDESCRIPTION( \"End-of-list marker\" )\n\t\t\tCRYPT_ALGO_NONE, CRYPT_ALGO_NONE, CRYPT_ALGO_NONE, \n\t\t\tCRYPT_ALGO_NONE, 0, 0, CIPHERSUITE_FLAG_NONE };\n\t\tint i, LOOP_ITERATOR;\n\n\t\t/* Build the unified list of cipher suites */\n\t\tLOOP_LARGE( i = 0, \n\t\t\t\t\tcipherSuitesList[ i ].cipherSuites != NULL && \\\n\t\t\t\t\t\ti < FAILSAFE_ARRAYSIZE( cipherSuitesList, \\\n\t\t\t\t\t\t\t\t\t\t\t\tCIPHERSUITES_LIST ),\n\t\t\t\t\ti++ )\n\t\t\t{\n\t\t\tstatus = addCipherSuiteInfo( cipherSuiteInfoTbl, cipherSuiteCount,\n\t\t\t\t\t\t&cipherSuiteCount, cipherSuitesList[ i ].cipherSuites,\n\t\t\t\t\t\tcipherSuitesList[ i ].cipherSuiteCount );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tENSURES( LOOP_BOUND_OK );\n\t\tENSURES( i < FAILSAFE_ARRAYSIZE( cipherSuitesList, CIPHERSUITES_LIST ) );\n\n\t\t/* Add the end-of-list marker suites.  Note that we don't increment \n\t\t   the suite count when the second one is added to match the \n\t\t   behaviour of FAILSAFE_ARRAYSIZE() */\n\t\tREQUIRES( cipherSuiteCount + 2 < MAX_CIPHERSUITE_TBLSIZE );\n\t\tcipherSuiteInfoTbl[ cipherSuiteCount++ ] = \\\n\t\t\t\t\t\t\t\t( CIPHERSUITE_INFO * ) &endOfList;\n\t\tcipherSuiteInfoTbl[ cipherSuiteCount ] = \\\n\t\t\t\t\t\t\t\t( CIPHERSUITE_INFO * ) &endOfList;\n\n\t\tcipherSuitInfoInited = TRUE;\n\t\t}\n\n\t*cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \\\n\t\t\t\t\t\t\t\tcipherSuiteInfoTbl;\t/* For gcc */\n\t*noSuiteEntries = cipherSuiteCount;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_svr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib TLS Server\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t   Copyright Peter Gutmann 1998-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/* Determine whether the server needs to request client certificates/client\n   authentication.  This is normally determined by whether an access-control\n   keyset is available, but for the Suite B tests in which any test \n   certificate is regarded as being acceptable it can be overridden with a\n   self-test flag */\n\n#ifdef CONFIG_SUITEB_TESTS \n#define clientCertAuthRequired( sessionInfoPtr ) \\\n\t\t( sessionInfoPtr->cryptKeyset != CRYPT_ERROR || suiteBTestClientCert )\n#else\n#define clientCertAuthRequired( sessionInfoPtr ) \\\n\t\t( sessionInfoPtr->cryptKeyset != CRYPT_ERROR || \\\n\t\t  TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_MANUAL_CERTCHECK ) )\n#endif /* CONFIG_SUITEB_TESTS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read the client certificate chain and make sure that the certificate \n   being presented is valid for access */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int readCheckClientCerts( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t\t INOUT STREAM *stream )\n\t{\n#ifdef CONFIG_SUITEB\n\tint length;\n#endif /* CONFIG_SUITEB */\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Read the client certificate chain */\n\tstatus = readSSLCertChain( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t   &sessionInfoPtr->iKeyexAuthContext, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If we're doing keyset-based certificate verification, make sure that \n\t   the client certificate is present in our certificate store.  Since \n\t   we've already got a copy of the certificate, we only do a presence \n\t   check rather than actually fetching the certificate.\n\t   \n\t   Checking whether the certificate is known to us at this point opens\n\t   us up to a theoretical account-enumeration attack in which an \n\t   attacker who has obtained a copy of every certificate in the world\n\t   can throw them at us one after the other and then use timing \n\t   measurements to see which ones get past this point.  OTOH deferring\n\t   the \"is this certificate known to us\" check until after we process\n\t   the keyex opens us up to a DoS attack since the attacker can force\n\t   us to perform a DH keyex rather than rejecting the handshake at this\n\t   point.  We could further flip things around and first read the\n\t   certificate, then read and cache the keyex data, then try and verify\n\t   the keyex data using the client signature, and only then actually\n\t   use it, but this greatly complicates the code and given the practical \n\t   nonexistence of client certificates just adds a pile of needless\n\t   complexity for a mechanism that's virtually never used anyway.\n\n\t   Because of this we do a quick-reject check here and don't even go\n\t   into a keyex unless we recognise the certificate */\n#ifndef CONFIG_SUITEB_TESTS \n\tif( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )\n\t\t{\n\t\tMESSAGE_KEYMGMT_INFO getkeyInfo;\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE certID[ KEYID_SIZE + 8 ];\n\n\t\tsetMessageData( &msgData, certID, KEYID_SIZE );\n\t\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tsetMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, \n\t\t\t\t\t\t\t\t   certID, KEYID_SIZE, NULL, 0, \n\t\t\t\t\t\t\t\t   KEYMGMT_FLAG_CHECK_ONLY );\n\t\t\tstatus = krnlSendMessage( sessionInfoPtr->cryptKeyset, \n\t\t\t\t\t\t\t\t\t  IMESSAGE_KEY_GETKEY, &getkeyInfo, \n\t\t\t\t\t\t\t\t\t  KEYMGMT_ITEM_PUBLICKEY );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n#ifdef USE_ERRMSGS\n\t\t\tchar certIDText[ CRYPT_MAX_TEXTSIZE + 8 ];\n#endif /* USE_ERRMSGS */\n\n\t\t\tformatFingerprint( certIDText, CRYPT_MAX_TEXTSIZE, certID, \n\t\t\t\t\t\t\t   KEYID_SIZE );\n\t\t\tretExt( CRYPT_ERROR_PERMISSION,\n\t\t\t\t\t( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO, \n\t\t\t\t\t  \"Client certificate with ID '%s' is not trusted for \"\n\t\t\t\t\t  \"authentication purposes\", certIDText ) );\n\t\t\t}\n\t\t}\n#endif /* !CONFIG_SUITEB_TESTS */\n\n\t/* Make sure that the key is of the appropriate size for the Suite B \n\t   security level.  At the 128-bit level both P256 and P384 are allowed, \n\t   at the 256-bit level only P384 is allowed */\n#ifdef CONFIG_SUITEB\n\tstatus = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext, \n\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE, &length,\n\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYSIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst int suiteBtype = \\\n\t\t\t\t\t\tsessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;\n\n\t\tif( suiteBtype == SSL_PFLAG_SUITEB_256 )\n\t\t\t{\n\t\t\tif( length != bitsToBytes( 384 ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Client Suite B certificate uses %d-bit key at \"\n\t\t\t\t\t\t  \"256-bit security level, should use 384-bit key\", \n\t\t\t\t\t\t  bytesToBits( length ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( length != bitsToBytes( 256 ) && \\\n\t\t\t\tlength != bitsToBytes( 384 ) )\n\t\t\t\t{\n\t\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t\t  \"Client Suite B certificate uses %d-bit key at \"\n\t\t\t\t\t\t  \"128-bit security level, should use 256- or \"\n\t\t\t\t\t\t  \"384-bit key\", bytesToBits( length ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif /* CONFIG_SUITEB */\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Write the certificate request:\n\n\t  [\tbyte\t\tID = SSL_HAND_SERVER_CERTREQUEST ]\n\t  [\tuint24\t\tlen\t\t\t\t-- Written by caller ]\n\t\tbyte\t\tcertTypeLen\n\t\tbyte[]\t\tcertType = { RSA, DSA, ECDSA }\n\t  [\tuint16\tsigHashListLen\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\thashAlgoID\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tcaNameListLen = 0\n\t  [\t\tuint16\tcaNameLen\t\t-- Omitted due to zero length ]\n\t  [\t\tbyte[]\tcaName\t\t\t-- Omitted due to zero length ]\n\n   This message is a real mess, it originally had a rather muddled \n   certificate-type indicator (which included things like \"Ephemeral DH \n   signed with RSA\") and an equally ambiguous CA list that many \n   implementations either left empty or filled with the name of every CA \n   that they'd ever heard of, see the special-case handling in \n   processCertRequest() in session/ssl_cli.c for the calisthenics required \n   to deal with this.  \n   \n   TLS 1.2 added a means of indicating which signature and hash algorithms \n   were acceptable, which is kind of essential because the explosion of hash \n   algorithms in 1.2 means that a server would have to run parallel hashes \n   of every handshake message for every possible hash algorithm until the \n   client sends their certificate-verify message (!!).  In other words \n   although it was planned as a means of indicating the server's \n   capabilities, it actually acts as a mechanism for keeping the client-auth \n   process manageable */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int writeCertRequest( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t INOUT STREAM *stream )\n\t{\n\tconst BOOLEAN rsaAvailable = algoAvailable( CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t\t\t\t\t TRUE : FALSE;\n\tconst BOOLEAN dsaAvailable = algoAvailable( CRYPT_ALGO_DSA ) ? \\\n\t\t\t\t\t\t\t\t TRUE : FALSE;\n\tconst BOOLEAN ecdsaAvailable = algoAvailable( CRYPT_ALGO_ECDSA ) ? \\\n\t\t\t\t\t\t\t\t   TRUE : FALSE;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( rsaAvailable == TRUE || ecdsaAvailable == TRUE );\n\n\t/* Write the certificate type */\n\tstatus = sputc( stream, ( rsaAvailable ? 1 : 0 ) + \\\n\t\t\t\t\t\t\t( dsaAvailable ? 1 : 0 ) + \\\n\t\t\t\t\t\t\t( ecdsaAvailable ? 1 : 0 ) );\n\tif( rsaAvailable )\n\t\tstatus = sputc( stream, TLS_CERTTYPE_RSA );\n\tif( dsaAvailable )\n\t\tstatus = sputc( stream, TLS_CERTTYPE_DSA );\n\tif( ecdsaAvailable )\n\t\tstatus = sputc( stream, TLS_CERTTYPE_ECDSA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write the list of accepted signature and hash algorithms if required.  \n\t   In theory we could write the full list of algorithms, but thanks to \n\t   SSL/TLS' braindamaged way of handling certificate-based \n\t   authentication (see the comment above) this would make the \n\t   certificate-authentication process unmanageable.  To get around this \n\t   we only allow one single algorithm, the SHA-2 default for TLS 1.2+ */\n\tif( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )\n\t\t{\n\t\twriteUint16( stream, ( rsaAvailable ? 2 : 0 ) + \\\n\t\t\t\t\t\t\t ( dsaAvailable ? 2 : 0 ) + \\\n\t\t\t\t\t\t\t ( ecdsaAvailable ? 2 : 0 ) );\n\t\tif( rsaAvailable )\n\t\t\t{\n\t\t\tsputc( stream, TLS_HASHALGO_SHA2 );\n\t\t\tstatus = sputc( stream, TLS_SIGALGO_RSA );\n\t\t\t}\n\t\tif( dsaAvailable )\n\t\t\t{\n\t\t\tsputc( stream, TLS_HASHALGO_SHA2 );\n\t\t\tstatus = sputc( stream, TLS_SIGALGO_DSA );\n\t\t\t}\n\t\tif( ecdsaAvailable )\n\t\t\t{\n\t\t\tsputc( stream, TLS_HASHALGO_SHA2 );\n\t\t\tstatus = sputc( stream, TLS_SIGALGO_ECDSA );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Write the CA name list.  Since all we care about is whether a \n\t   certificate is present in the authentication database, we don't try \n\t   and write a list of every imaginable CA that the client will most \n\t   likely ignore anyway */ \n\treturn( writeUint16( stream, 0 ) );\n\t}\n\n/* Calculate an ID for use with the session scoreboard from the session ID \n   and the SNI.  This prevents an attacker from taking advantage of virtual \n   hosting with a shared session cache to redirect a connection from one \n   domain to another, which a purely session ID-based lookup would allow */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint convertSNISessionID( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t OUT_BUFFER_FIXED( idBufferLength ) BYTE *idBuffer,\n\t\t\t\t\t\t IN_LENGTH_FIXED( KEYID_SIZE ) const int idBufferLength )\n\t{\n\tSTREAM sniStream;\n\tBYTE sniInfo[ UINT16_SIZE + MAX_SESSIONID_SIZE + \\\n\t\t\t\t  UINT16_SIZE + KEYID_SIZE + 8 ];\n\tint sniInfoLength, status;\n\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtrDynamic( idBuffer, idBufferLength ) );\n\n\tREQUIRES( idBufferLength == KEYID_SIZE );\n\n\t/* Clear return value */\n\tmemset( idBuffer, 0, idBufferLength );\n\n\t/* Write the session ID and hashed SNI to a buffer for hashing */\n\tsMemOpen( &sniStream, sniInfo, UINT16_SIZE + MAX_SESSIONID_SIZE + \\\n\t\t\t\t\t\t\t\t   UINT16_SIZE + KEYID_SIZE );\n\twriteUint16( &sniStream, handshakeInfo->sessionIDlength );\n\tswrite( &sniStream, handshakeInfo->sessionID, \n\t\t\thandshakeInfo->sessionIDlength );\n\twriteUint16( &sniStream, KEYID_SIZE );\n\tstatus = swrite( &sniStream, handshakeInfo->hashedSNI, KEYID_SIZE );\n\tENSURES( !cryptStatusError( status ) );\n\tsniInfoLength = stell( &sniStream );\n\n\t/* Generate the final ID from the combined session ID and SNI */\n\thashData( idBuffer, idBufferLength, sniInfo, sniInfoLength );\n\tsMemClose( &sniStream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHandle Client/Server Keyex\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Process the client key exchange packet:\n\n\t\tbyte\t\tID = SSL_HAND_CLIENT_KEYEXCHANGE\n\t\tuint24\t\tlen\n\t   DH:\n\t\tuint16\t\tyLen\n\t\tbyte[]\t\ty\n\t   DH-PSK:\n\t\tuint16\t\tuserIDLen\n\t\tbyte[]\t\tuserID\n\t\tuint16\t\tyLen\n\t\tbyte[]\t\ty\n\t   ECDH:\n\t\tuint16\t\tecPointLen\n\t\tbyte[]\t\tecPoint\n\t   PSK:\n\t\tuint16\t\tuserIDLen\n\t\tbyte[]\t\tuserID \n\t   RSA:\n\t  [ uint16\t\tencKeyLen\t\t-- TLS 1.x ]\n\t\tbyte[]\t\trsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processDHKeyex( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t\t\t   IN_OPT const ATTRIBUTE_LIST *passwordInfoPtr )\n\t{\n\tKEYAGREE_PARAMS keyAgreeParams;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( passwordInfoPtr == NULL || \\\n\t\t\tisReadPtr( passwordInfoPtr, sizeof( ATTRIBUTE_LIST ) ) );\n\n\t/* Read the DH key agreement parameters */\n\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = readInteger16UChecked( stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t\t\t&keyAgreeParams.publicValueLen,\n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some misconfigured clients may use very short keys, we perform a \n\t\t   special-case check for these and return a more specific message \n\t\t   than the generic bad-data error */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure DH key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid DH phase 2 key agreement data\" ) );\n\t\t}\n\n\t/* If we're fuzzing the input then we don't need to go through any of \n\t   the following crypto calisthenics.  In addition we can exit now \n\t   because the remaining fuzzable code is common with the client and\n\t   has already been tested there */\n\tFUZZ_EXIT();\n\n\t/* Perform phase 2 of the DH key agreement */\n\tstatus = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid DH phase 2 key agreement value\" ) );\n\t\t}\n\tif( passwordInfoPtr != NULL )\n\t\t{\n\t\tstatus = createSharedPremasterSecret( \\\n\t\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t\t&handshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\tpasswordInfoPtr->value,\n\t\t\t\t\t\t\tpasswordInfoPtr->valueLength, \n\t\t\t\t\t\t\tkeyAgreeParams.wrappedKey, \n\t\t\t\t\t\t\tkeyAgreeParams.wrappedKeyLen,\n\t\t\t\t\t\t\tTEST_FLAG( passwordInfoPtr->flags,\n\t\t\t\t\t\t\t\t\t   ATTR_FLAG_ENCODEDVALUE ) ? \\\n\t\t\t\t\t\t\t\tTRUE : FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\t\tretExt( status, \n\t\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t\t  \"Couldn't create master secret from shared \"\n\t\t\t\t\t  \"secret/password value\" ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Remember the premaster secret, the output of the DH operation */\n\t\tREQUIRES( rangeCheck( keyAgreeParams.wrappedKeyLen, 1,\n\t\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE ) );\n\t\tmemcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,\n\t\t\t\tkeyAgreeParams.wrappedKeyLen );\n\t\thandshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;\n\t\t}\n\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processECDHKeyex( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t INOUT STREAM *stream )\n\t{\n\tKEYAGREE_PARAMS keyAgreeParams;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\t/* Read the ECDH key agreement parameters */\n\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = readEcdhValue( stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\tCRYPT_MAX_PKCSIZE, \n\t\t\t\t\t\t\t&keyAgreeParams.publicValueLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some misconfigured clients may use very short keys, we perform a \n\t\t   special-case check for these and return a more specific message \n\t\t   than the generic bad-data error */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure ECDH key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid ECDH phase 2 key agreement data\" ) );\n\t\t}\n\n\t/* If we're fuzzing the input then we don't need to go through any of \n\t   the following crypto calisthenics.  In addition we can exit now \n\t   because the remaining fuzzable code is common with the client and\n\t   has already been tested there */\n\tFUZZ_EXIT();\n\n\t/* Perform phase 2 of the ECDH key agreement */\n\tstatus = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_DECRYPT, \n\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid ECDH phase 2 key agreement value\" ) );\n\t\t}\n\n\t/* The output of the ECDH operation is an ECC point, but for some \n\t   unknown reason standard TLS only uses the x coordinate and not the \n\t   full point.  To work around this we have to rewrite the point as a \n\t   standalone x coordinate, which is relatively easy because we're  \n\t   using the uncompressed point format: \n\n\t\t+---+---------------+---------------+\n\t\t|04\t|\t\tqx\t\t|\t\tqy\t\t|\n\t\t+---+---------------+---------------+\n\t\t\t|<- fldSize --> |<- fldSize --> | */\n\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS ) )\n\t\t{\n\t\tconst int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;\n\n\t\tREQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \\\n\t\t\t\t  ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \\\n\t\t\t\t  keyAgreeParams.wrappedKey[ 0 ] == 0x04 );\n\t\tREQUIRES( boundsCheck( 1, xCoordLen, CRYPT_MAX_PKCSIZE ) );\n\t\tmemmove( keyAgreeParams.wrappedKey, \n\t\t\t\t keyAgreeParams.wrappedKey + 1, xCoordLen );\n\t\tkeyAgreeParams.wrappedKeyLen = xCoordLen;\n\t\t}\n\n\t/* Remember the premaster secret, the output of the ECDH operation */\n\tREQUIRES( rangeCheck( keyAgreeParams.wrappedKeyLen, 1,\n\t\t\t\t\t\t  CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE ) );\n\tmemcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,\n\t\t\tkeyAgreeParams.wrappedKeyLen );\n\thandshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;\n\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processPSKKeyex( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\tINOUT STREAM *stream )\n\t{\n\tconst ATTRIBUTE_LIST *attributeListPtr, *attributeListCursor;\n\tconst BOOLEAN isKeyex = \\\n\t\t\t\tisKeyxAlgo( handshakeInfo->keyexAlgo ) ? TRUE : FALSE;\n\tBYTE userID[ CRYPT_MAX_TEXTSIZE + 8 ];\n\tint length, status, LOOP_ITERATOR;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( !isEccAlgo( handshakeInfo->keyexAlgo ) );\n\n\t/* Read the client user ID and make sure that it's a valid user.  \n\t   Handling non-valid users is somewhat problematic, we can either bail \n\t   out immediately or invent a fake password for the (non-)user and \n\t   continue with that.  The problem with this is that it doesn't really \n\t   help hide whether the user is valid or not due to the fact that we're \n\t   still vulnerable to a timing attack because it takes considerably \n\t   longer to generate the random password than it does to read a fixed \n\t   password string from memory, so an attacker can tell from the timing \n\t   whether the username is valid or not.  In addition usability research \n\t   on real-world users indicates that this actually reduces security \n\t   while having little to no tangible benefit.  Because of this we don't \n\t   try and fake out the valid/invalid user name indication but just exit \n\t   immediately if an invalid name is found */\n\tlength = readUint16( stream );\n\tif( length < 1 || length > CRYPT_MAX_TEXTSIZE || \\\n\t\tcryptStatusError( sread( stream, userID, length ) ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid client user ID\" ) );\n\t\t}\n\tattributeListPtr = findSessionInfoEx( sessionInfoPtr,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t\t\t  userID, length );\n\tif( attributeListPtr == NULL )\n\t\t{\n\t\tretExt( CRYPT_ERROR_WRONGKEY,\n\t\t\t\t( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO, \n\t\t\t\t  \"Unknown user name '%s'\", \n\t\t\t\t  sanitiseString( userID, CRYPT_MAX_TEXTSIZE, \n\t\t\t\t\t\t\t\t  length ) ) );\n\t\t}\n\n\t/* Move on to the associated password */\n\tattributeListPtr = DATAPTR_GET( attributeListPtr->next );\n\tENSURES( attributeListPtr != NULL && \\\n\t\t\t attributeListPtr->attributeID == CRYPT_SESSINFO_PASSWORD );\n\n\t/* Delete any other username/password pairs that may be present so that\n\t   the caller knows which set was used to authenticate.  These are \n\t   present in the attribute list as:\n\n\t\tusername - password - ... - username - password - ... \n\t\n\t   so to delete them we repeatedly look for a username attribute and \n\t   then delete that and the following attribute */\n\tLOOP_LARGE_INITCHECK( attributeListCursor = \\\n\t\t\t\t\t\t\tfindSessionInfo( sessionInfoPtr, CRYPT_SESSINFO_USERNAME ), \n\t\t\t\t\t\t  attributeListCursor != NULL )\n\t\t{\n\t\tATTRIBUTE_LIST *userNamePtr = ( ATTRIBUTE_LIST * ) attributeListCursor;\n\t\tATTRIBUTE_LIST *passwordPtr = DATAPTR_GET( userNamePtr->next );\n\n\t\tENSURES( passwordPtr != NULL && \\\n\t\t\t\t passwordPtr->attributeID == CRYPT_SESSINFO_PASSWORD );\n\t\tREQUIRES( DATAPTR_ISVALID( passwordPtr->next ) );\n\n\t\t/* Try and find the next username/password pair after the current one */\n\t\tattributeListCursor = DATAPTR_GET( passwordPtr->next );\n\t\tif( attributeListCursor != NULL )\n\t\t\t{\n\t\t\t/* There are more attributes present after the current username/\n\t\t\t   password pair, look for another username/password */\n\t\t\tattributeListCursor = findSessionInfoNext( attributeListCursor, \n\t\t\t\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_USERNAME );\n\t\t\t}\n\n\t\t/* If this is a non-matching username/password pair, delete it */\n\t\tif( passwordPtr != attributeListPtr )\n\t\t\t{\n\t\t\tdeleteSessionInfo( sessionInfoPtr, userNamePtr );\n\t\t\tdeleteSessionInfo( sessionInfoPtr, passwordPtr );\n\t\t\t}\n\t\t}\n\tENSURES( LOOP_BOUND_OK );\n\n\t/* If it's PSK with DH, perform the keyex with the PSK added */\n\tif( isKeyex )\n\t\t{\n\t\treturn( processDHKeyex( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t\tattributeListPtr ) );\n\t\t}\n\n\t/* If we're fuzzing the input then we don't need to go through any of \n\t   the following crypto calisthenics.  In addition we can exit now \n\t   because the remaining fuzzable code is common with the client and\n\t   has already been tested there */\n\tFUZZ_EXIT();\n\n\t/* We're using straight PSK, the premaster secret is derived from the \n\t   user password */\n\tstatus = createSharedPremasterSecret( \\\n\t\t\t\t\t\thandshakeInfo->premasterSecret,\n\t\t\t\t\t\tCRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,\n\t\t\t\t\t\t&handshakeInfo->premasterSecretSize, \n\t\t\t\t\t\tattributeListPtr->value,\n\t\t\t\t\t\tattributeListPtr->valueLength, NULL, 0,\n\t\t\t\t\t\tTEST_FLAG( attributeListPtr->flags, \n\t\t\t\t\t\t\t\t   ATTR_FLAG_ENCODEDVALUE ) ? \\\n\t\t\t\t\t\t\tTRUE : FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status, \n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  \"Couldn't create master secret from shared secret/password \"\n\t\t\t\t  \"value\" ) );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_RSA_SUITES\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int processRSAKeyex( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\tINOUT STREAM *stream\n#ifdef USE_SSL3\n\t\t\t\t\t\t\t, IN_LENGTH_SHORT const int packetLength \n#endif /* USE_SSL3 */\n\t\t\t\t\t\t\t)\n\t{\n\tBYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];\n#ifdef USE_SSL3\n\tint length = packetLength, status = CRYPT_OK;\n#else\n\tint length, status;\n#endif /* USE_SSL3 */\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n#ifdef USE_SSL3\n\tREQUIRES( isShortIntegerRangeNZ( length ) );\n\n\t/* Read and unwrap the RSA-wrapped premaster secret */\n\tif( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\t/* The original Netscape SSL implementation didn't provide a length \n\t\t   for the encrypted key so that the packet length is the same as\n\t\t   the key length.  Everyone copied that so it became the de facto \n\t\t   standard way to do it (sic faciunt omnes.  The spec itself is \n\t\t   ambiguous on the topic).  \n\t\t   \n\t\t   This was fixed in TLS (although the spec is still ambigous) so \n\t\t   the encoding differs slightly between SSL and TLS.  To work \n\t\t   around this we have to duplicate a certain amount of the \n\t\t   code in readInteger16UChecked() here */\n\t\tif( isShortPKCKey( length ) )\n\t\t\tstatus = CRYPT_ERROR_NOSECURE;\n\t\telse\n\t\t\t{\n\t\t\tif( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE || \\\n\t\t\t\tcryptStatusError( sread( stream, wrappedKey, length ) ) )\n\t\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t\t}\n\t\t}\n\telse\n#endif /* USE_SSL3 */\n\tstatus = readInteger16UChecked( stream, wrappedKey, &length, \n\t\t\t\t\t\t\t\t\tMIN_PKCSIZE, CRYPT_MAX_PKCSIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some misconfigured clients may use very short keys, we perform a \n\t\t   special-case check for these and return a more specific message \n\t\t   than the generic bad-data */\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_NOSECURE,\n\t\t\t\t\t( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO, \n\t\t\t\t\t  \"Insecure RSA key used in key exchange\" ) );\n\t\t\t}\n\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, SESSION_ERRINFO, \n\t\t\t\t  \"Invalid RSA encrypted key data\" ) );\n\t\t}\n\n\t/* If we're fuzzing the input then we don't need to go through any of \n\t   the following crypto calisthenics.  In addition we can exit now \n\t   because the remaining fuzzable code is common with the client and\n\t   has already been tested there */\n\tFUZZ_EXIT();\n\n\t/* Decrypt the pre-master secret */\n\treturn( unwrapPremasterSecret( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t   wrappedKey, length ) );\n\t}\n#endif /* USE_RSA_SUITES */\n\n/* Process the client's keyex.  This demultuplexing function sorts out which \n   type of keyex we're using and passes control to the appropriate keyex-\n   specific function to handle it */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int processKeyex( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t INOUT STREAM *stream\n#ifdef USE_SSL3\n\t\t\t\t\t\t , IN_LENGTH_SHORT const int length\n#endif /* USE_SSL3 */\n\t\t\t\t\t\t )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* If we're using any form of PSK (either raw PSK or PSK with DH) then \n\t   the keyex is handled specially */\n\tif( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )\n\t\treturn( processPSKKeyex( sessionInfoPtr, handshakeInfo, stream ) );\n\n\t/* If we're using DH/ECDH, perform the necessary keyex operations */\n\tif( isKeyxAlgo( handshakeInfo->keyexAlgo ) )\n\t\t{\n\t\tif( isEccAlgo( handshakeInfo->keyexAlgo ) )\n\t\t\t{\n\t\t\treturn( processECDHKeyex( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t  stream ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\treturn( processDHKeyex( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\tstream, NULL ) );\n\t\t\t}\n\t\t}\n\n\t/* It's a regular RSA keyex */\n#ifdef USE_RSA_SUITES\n  #ifdef USE_SSL3\n\treturn( processRSAKeyex( sessionInfoPtr, handshakeInfo, stream, length ) );\n  #else\n\treturn( processRSAKeyex( sessionInfoPtr, handshakeInfo, stream ) );\n  #endif /* USE_SSL3 */\n#else\n\tretIntError();\n#endif /* USE_RSA_SUITES */\n\t}\n\n/* Build the server key exchange packet:\n\n\t  [\tbyte\t\tID = SSL_HAND_SERVER_KEYEXCHANGE ]\n\t  [\tuint24\t\tlen\t\t\t\t-- Written by caller ]\n\t   DH:\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t  [ uint16\t\tdh_qLen\n\t\tbyte[]\t\tdh_q\t\t\t-- TLS LTS ]\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t\tuint16\t\tdh_YsLen\n\t\tbyte[]\t\tdh_Ys\n\t  [\tbyte\t\thashAlgoID\t\t-- TLS 1.2 ]\n\t  [\tbyte\t\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tsignatureLen\n\t\tbyte[]\t\tsignature\n\t   DH-PSK:\n\t\tuint16\t\tpskIdentityHintLen = 0\n\t\tuint16\t\tdh_pLen\n\t\tbyte[]\t\tdh_p\n\t\tuint16\t\tdh_gLen\n\t\tbyte[]\t\tdh_g\n\t\tuint16\t\tdh_YsLen\n\t\tbyte[]\t\tdh_Ys\n\t   ECDH-PSK: (Not present)\n\t   ECDH:\n\t\tbyte\t\tcurveType\n\t\tuint16\t\tnamedCurve\n\t\tuint8\t\tecPointLen\t\t-- NB uint8 not uint16\n\t\tbyte[]\t\tecPoint\n\t  [\tbyte\t\thashAlgoID\t\t-- TLS 1.2 ]\n\t  [\tbyte\t\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tsignatureLen\n\t\tbyte[]\t\tsignature */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \\\nstatic int createServerKeyex( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,\n\t\t\t\t\t\t\t  INOUT STREAM *stream )\n\t{\n\tconst BOOLEAN isPSK = ( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \\\n\t\t\t\t\t\t  TRUE : FALSE;\n\tKEYAGREE_PARAMS keyAgreeParams;\n\tvoid *keyData;\n\tint keyDataOffset, keyDataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Perform phase 1 of the DH/ECDH key agreement process */\n\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n\tstatus = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_ENCRYPT, \n\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\treturn( status );\n\t\t}\n\n\t/* Write an empty PSK identity hint (whatever that's supposed to be) if\n\t   it's a PSK suite.  Perhaps we should always write \"nan-demo \n\t   kaimasen\" */\n\tif( isPSK )\n\t\t{\n\t\tstatus = writeUint16( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\n\t/* Write the DH/ECDH key parameters and public value */\n\tkeyDataOffset = stell( stream );\n\tstatus = exportAttributeToStream( stream, handshakeInfo->dhContext,\n\t\t\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SSL_EXT : \n\t\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_KEY_SSL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( isEccAlgo( handshakeInfo->keyexAlgo ) )\n\t\t\t{\n\t\t\tsputc( stream, keyAgreeParams.publicValueLen );\n\t\t\tstatus = swrite( stream, keyAgreeParams.publicValue,\n\t\t\t\t\t\t\t keyAgreeParams.publicValueLen );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = writeInteger16U( stream, keyAgreeParams.publicValue, \n\t\t\t\t\t\t\t\t\t  keyAgreeParams.publicValueLen );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\treturn( status );\n\t\t}\n\tkeyDataLength = stell( stream ) - keyDataOffset;\n\n\t/* If we're using a PSK suite then the exchange is authenticated via the \n\t   PSK and we're done */\n\tif( isPSK )\n\t\t{\n\t\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\t/* Non-PSK suites authenticate the exchange by signing it */\n\tstatus = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData, \n\t\t\t\t\t\t\t\t  keyDataLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tANALYSER_HINT( keyData != NULL );\n\n\t\tINJECT_FAULT( BADSIG_DATA, SESSION_BADSIG_DATA_SSL_1 );\n\t\tstatus = createKeyexSignature( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t\t\t   keyData, keyDataLength );\n\t\tINJECT_FAULT( BADSIG_DATA, SESSION_BADSIG_DATA_SSL_2 );\n\t\t}\n\tzeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tServer-side Connect Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Perform the initial part of the handshake with the client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint beginServerHandshake( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM *stream = &handshakeInfo->stream;\n\tSCOREBOARD_INFO scoreboardInfo DUMMY_INIT_STRUCT;\n\tMESSAGE_DATA msgData;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint packetOffset, clientHelloLength, serverHelloLength;\n\tint resumedSessionID = CRYPT_ERROR, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Read and process the client hello */\n\tstatus = readHSPacketSSL( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t  &clientHelloLength, SSL_MSG_FIRST_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, clientHelloLength );\n\tstatus = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, TRUE );\n\tsMemDisconnect( stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tBYTE sessionIDbuffer[ KEYID_SIZE + 8 ];\n\t\tvoid *scoreboardInfoPtr = \\\n\t\t\t\tDATAPTR_GET( sessionInfoPtr->sessionSSL->scoreboardInfoPtr );\n\t\tconst BYTE *sessionIDptr = handshakeInfo->sessionID;\n\t\tint sessionIDlength = handshakeInfo->sessionIDlength;\n\n\t\tREQUIRES( scoreboardInfoPtr != NULL );\n\n\t\tif( status != OK_SPECIAL )\n\t\t\treturn( status );\n\n\t\t/* If there's an SNI present, generate a pseudo-session ID that \n\t\t   includes it.  This is used for the session cache lookup, but the \n\t\t   original session ID is sent back to the client.  The same \n\t\t   operation is performed when the session ID is added to the cache */\n\t\tif( handshakeInfo->hashedSNIpresent )\n\t\t\t{\n\t\t\tstatus = convertSNISessionID( handshakeInfo, sessionIDbuffer,\n\t\t\t\t\t\t\t\t\t\t  KEYID_SIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tsessionIDptr = sessionIDbuffer;\n\t\t\tsessionIDlength = KEYID_SIZE;\n\t\t\t}\n\n\t\t/* The client has sent us a sessionID in an attempt to resume a \n\t\t   previous session, see if it's in the session cache */\n\t\tresumedSessionID = \\\n\t\t\t\tlookupScoreboardEntry( scoreboardInfoPtr, \n\t\t\t\t\t\t\t\t\t   SCOREBOARD_KEY_SESSIONID_SVR, \n\t\t\t\t\t\t\t\t\t   sessionIDptr, sessionIDlength, \n\t\t\t\t\t\t\t\t\t   &scoreboardInfo );\n#ifdef CONFIG_SUITEB_TESTS \n\t\tresumedSessionID = CRYPT_ERROR;\t/* Disable for Suite B tests */\n#endif /* CONFIG_SUITEB_TESTS */\n\t\t}\n\tCFI_CHECK_UPDATE( \"processHelloSSL\" );\n\n\t/* If we're fuzzing the input then we can skip all data writes to \n\t   minimise the overhead during fuzz testing */\n\tFUZZ_SKIP();\n\n\t/* Handle session resumption.  If it's a new session or the session data \n\t   has expired from the cache, generate a new session ID */\n\tif( cryptStatusError( resumedSessionID ) )\n\t\t{\n\t\tsetMessageData( &msgData, handshakeInfo->sessionID, SESSIONID_SIZE );\n\t\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, \n\t\t\t\t\t\t\t\t  IMESSAGE_GETATTRIBUTE_S, &msgData, \n\t\t\t\t\t\t\t\t  CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\thandshakeInfo->sessionIDlength = SESSIONID_SIZE;\n\t\t}\n\telse\n\t\t{\n\t\t/* We're resuming a previous session, if extended TLS facilities were\n\t\t   in use then make sure that the resumed session uses the same \n\t\t   facilities.  This check preents downgrade attacks where additional\n\t\t   security features are disabled by a MITM */\n\t\tif( !TEST_FLAGS( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t\t SSL_RESUMEDSESSION_FLAGS, \n\t\t\t\t\t\t scoreboardInfo.metaData ) )\n\t\t\t{\n\t\t\tretExt( CRYPT_ERROR_INVALID,\n\t\t\t\t\t( CRYPT_ERROR_INVALID, SESSION_ERRINFO, \n\t\t\t\t\t  \"Session with options %X was resumed with options \"\n\t\t\t\t\t  \"%X.\\n\", scoreboardInfo.metaData,\n\t\t\t\t\t  GET_FLAGS( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t\t\t SSL_RESUMEDSESSION_FLAGS ) ) );\n\t\t\t}\n\n\t\t/* Remember the premaster secret for the resumed session */\n\t\tstatus = attributeCopyParams( handshakeInfo->premasterSecret, \n\t\t\t\t\t\t\t\t\t  SSL_SECRET_SIZE,\n\t\t\t\t\t\t\t\t\t  &handshakeInfo->premasterSecretSize,\n\t\t\t\t\t\t\t\t\t  scoreboardInfo.data, \n\t\t\t\t\t\t\t\t\t  scoreboardInfo.dataSize );\n\t\tENSURES( cryptStatusOK( status ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"resumedSession\" );\n\n\t/* Get the nonce that's used to randomise all crypto operations and set \n\t   up the server DH/ECDH context if necessary */\n\tsetMessageData( &msgData, handshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusOK( status ) && isKeyxAlgo( handshakeInfo->keyexAlgo ) )\n\t\t{\n\t\tstatus = initDHcontextSSL( &handshakeInfo->dhContext, NULL, 0,\n\t\t\t\t\t\t( handshakeInfo->authAlgo != CRYPT_ALGO_NONE ) ? \\\n\t\t\t\t\t\t\tsessionInfoPtr->privateKey : CRYPT_UNUSED,\n\t\t\t\t\t\tisEccAlgo( handshakeInfo->keyexAlgo ) ? \\\n\t\t\t\t\t\t\thandshakeInfo->eccCurveID : CRYPT_ECCCURVE_NONE,\n\t\t\t\t\t\tTEST_FLAG( sessionInfoPtr->protocolFlags,\n\t\t\t\t\t\t\t\t   SSL_PFLAG_TLS12LTS ) ? TRUE : FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"initDHcontextSSL\" );\n\n\t/* Build the server hello, certificate, optional certificate request, \n\t   and done packets:\n\n\t\tbyte\t\tID = SSL_HAND_SERVER_HELLO\n\t\tuint24\t\tlen\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tbyte[32]\tnonce\n\t\tbyte\t\tsessIDlen\n\t\tbyte[]\t\tsessID\n\t\tuint16\t\tsuite\n\t\tbyte\t\tcopr = 0\n\t  [\tuint16\textListLen\t\t-- RFC 3546/RFC 4366/RFC 6066\n\t\t\tbyte\textType\n\t\t\tuint16\textLen\n\t\t\tbyte[]\textData ] \n\t\t...\n\n\t   We have to be careful how we handle extensions because the RFC makes \n\t   the rather optimistic assumption that implementations can handle the \n\t   presence of unexpected data at the end of the hello packet, to avoid \n\t   problems with this we avoid sending extensions unless they're in \n\t   response to extensions already sent by the client */\n\tstatus = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT, \n\t\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLO, \n\t\t\t\t\t\t\t\t\t &packetOffset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tsputc( stream, SSL_MAJOR_VERSION );\n\tsputc( stream, sessionInfoPtr->version );\n\tswrite( stream, handshakeInfo->serverNonce, SSL_NONCE_SIZE );\n\tsputc( stream, handshakeInfo->sessionIDlength );\n\tswrite( stream, handshakeInfo->sessionID, \n\t\t\thandshakeInfo->sessionIDlength );\n\tINJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSL_1 );\n\twriteUint16( stream, handshakeInfo->cipherSuite ); \n\tstatus = sputc( stream, 0 );\t/* No compression */\n\tif( cryptStatusOK( status ) && handshakeInfo->hasExtensions )\n\t\tstatus = writeServerExtensions( stream, handshakeInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tserverHelloLength = stell( stream ) - SSL_HEADER_SIZE;\n\tCFI_CHECK_UPDATE( \"serverHello\" );\n\n\t/* TLS 1.2 LTS implicitly enables various other crypto options, now that\n\t   we've got past the initial negotiations, enable those too */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_TLS12LTS ) )\n\t\t{\n\t\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS );\n\t\tif( !TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t\t{\n\t\t\tSET_FLAG( sessionInfoPtr->protocolFlags, \n\t\t\t\t\t  SSL_PFLAG_ENCTHENMAC );\n\t\t\t}\n\n\t\t/* Hash the hello messages */\n\t\tgetHashParameters( CRYPT_ALGO_SHA2, 0, &handshakeInfo->helloHashFunction, \n\t\t\t\t\t\t   &handshakeInfo->helloHashSize );\n\t\thandshakeInfo->helloHashFunction( handshakeInfo->helloHashInfo, NULL, 0, \n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->receiveBuffer, \n\t\t\t\t\t\t\t\t\t\t  clientHelloLength, HASH_STATE_START );\n\t\thandshakeInfo->helloHashFunction( handshakeInfo->helloHashInfo, NULL, 0,\n\t\t\t\t\t\t\t\t\t\t  sessionInfoPtr->sendBuffer + SSL_HEADER_SIZE, \n\t\t\t\t\t\t\t\t\t\t  serverHelloLength, HASH_STATE_CONTINUE );\n\t\t}\n\tCFI_CHECK_UPDATE( \"TLS12LTS\" );\n\n\t/* If it's a resumed session then the server hello is followed \n\t   immediately by the change cipherspec, which is sent by the shared \n\t   handshake completion code */\n\tif( !cryptStatusError( resumedSessionID ) )\n\t\t{\n\t\tstatus = completePacketStreamSSL( stream, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = hashHSPacketWrite( handshakeInfo, stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tCFI_CHECK_UPDATE( \"resumedSession\" );\n\n\t\t/* Tell the caller that it's a resumed session, leaving the stream\n\t\t   open in order to write the change cipherspec message that follows \n\t\t   the server hello in a resumed session */\n\t\tDEBUG_PUTS(( \"Resuming session with client based on sessionID =\" ));\n\t\tDEBUG_DUMP_DATA( handshakeInfo->sessionID, \n\t\t\t\t\t\t handshakeInfo->sessionIDlength );\n\n\t\tREQUIRES( CFI_CHECK_SEQUENCE_6( \"processHelloSSL\", \"resumedSession\", \n\t\t\t\t\t\t\t\t\t\t\"initDHcontextSSL\", \"serverHello\", \n\t\t\t\t\t\t\t\t\t\t\"TLS12LTS\", \"resumedSession\" ) );\n\t\treturn( OK_SPECIAL );\n\t\t}\n\tCFI_CHECK_UPDATE( \"nonResumedSession\" );\n\n\t/*\t...\t(optional server supplemental data)\n\t\tbyte\t\tID = SSL_HAND_SUPPLEMENTAL_DATA\n\t\tuint24\t\tlen\n\t\tuint16\t\ttype\n\t\tuint16\t\tlen\n\t\tbyte[]\t\tvalue\n\t\t... */\n\n\t/*\t...\n\t\t(optional server certificate chain)\n\t\t... */\n\tif( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tINJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSL_1 );\n\t\tstatus = writeSSLCertChain( sessionInfoPtr, stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tINJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSL_2 );\n\t\t}\n\tCFI_CHECK_UPDATE( \"writeSSLCertChain\" );\n\n\t/*\t...\t\t\t(optional server keyex) */\n\tif( isKeyxAlgo( handshakeInfo->keyexAlgo ) )\n\t\t{\n\t\tstatus = continueHSPacketStream( stream, SSL_HAND_SERVER_KEYEXCHANGE, \n\t\t\t\t\t\t\t\t\t\t &packetOffset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = createServerKeyex( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t\tstream );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"createServerKeyex\" );\n\n\t/*\t...\t\t\t(optional request for client certificate authentication)\n\t\tbyte\t\tID = SSL_HAND_SERVER_CERTREQUEST\n\t\tuint24\t\tlen\n\t\tbyte\t\tcertTypeLen\n\t\tbyte[]\t\tcertType = { RSA, DSA, ECDSA }\n\t  [\tuint16\tsigHashListLen\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\thashAlgoID\t\t-- TLS 1.2 ]\n\t  [\t\tbyte\tsigAlgoID\t\t-- TLS 1.2 ]\n\t\tuint16\t\tcaNameListLen = 4\n\t\t\tuint16\tcaNameLen = 2\n\t\t\tbyte[]\tcaName = { 0x30, 0x00 }\n\t\t... */\n\tif( clientCertAuthRequired( sessionInfoPtr ) )\n\t\t{\n\t\tstatus = continueHSPacketStream( stream, SSL_HAND_SERVER_CERTREQUEST, \n\t\t\t\t\t\t\t\t\t\t &packetOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = writeCertRequest( sessionInfoPtr, stream );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tCFI_CHECK_UPDATE( \"writeCertRequest\" );\n\n\t/*\t...\n\t\tbyte\t\tID = SSL_HAND_SERVER_HELLODONE\n\t\tuint24\t\tlen = 0 */\n\tstatus = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLODONE, \n\t\t\t\t\t\t\t\t\t &packetOffset );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = completeHSPacketStream( stream, packetOffset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"completeHSPacketStream\" );\n\n\t/* Send the combined server packets to the client.  We perform the \n\t   assorted hashing of the packets in between the network ops where \n\t   it's effectively free */\n\tstatus = sendPacketSSL( sessionInfoPtr, stream, FALSE );\n\tINJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSL_2 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = hashHSPacketWrite( handshakeInfo, stream, 0 );\n\tsMemDisconnect( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"sendPacketSSL\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_12( \"processHelloSSL\", \"resumedSession\", \n\t\t\t\t\t\t\t\t\t \"initDHcontextSSL\", \"serverHello\", \n\t\t\t\t\t\t\t\t\t \"TLS12LTS\", \"resumedSession\",\n\t\t\t\t\t\t\t\t\t \"nonResumedSession\", \"writeSSLCertChain\", \n\t\t\t\t\t\t\t\t\t \"createServerKeyex\", \"writeCertRequest\",\n\t\t\t\t\t\t\t\t\t \"completeHSPacketStream\", \"sendPacketSSL\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/* Exchange keys with the client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint exchangeServerKeys( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\tINOUT SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tSTREAM *stream = &handshakeInfo->stream;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\n\t/* Read the response from the client and, if we're expecting a client \n\t   certificate, make sure that it's present */\n\tstatus = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,\n\t\t\t\t\t\t\t  SSL_MSG_HANDSHAKE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( stream, sessionInfoPtr->receiveBuffer, length );\n\tif( clientCertAuthRequired( sessionInfoPtr ) )\n\t\t{\n\t\t/* Read the client certificate chain and make sure that the \n\t\t   certificate being presented is valid for access */\n\t\tstatus = readCheckClientCerts( sessionInfoPtr, handshakeInfo, \n\t\t\t\t\t\t\t\t\t   stream );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Read the next packet(s) if necessary */\n\t\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readCheckClientCerts\" );\n\n\t/* Process the client key exchange packet */\n\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t  SSL_HAND_CLIENT_KEYEXCHANGE, \n\t\t\t\t\t\t\t\t  UINT16_SIZE + 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n#ifdef USE_SSL3\n\tstatus = processKeyex( sessionInfoPtr, handshakeInfo, stream, length );\n#else\n\tstatus = processKeyex( sessionInfoPtr, handshakeInfo, stream );\n#endif /* USE_SSL3 */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsMemDisconnect( stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processKeyex\" );\n\n\t/* Create the session hash if required */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_EMS ) || \\\n\t\tclientCertAuthRequired( sessionInfoPtr ) )\n\t\t{\n\t\tstatus = createSessionHash( sessionInfoPtr, handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"createSessionHash\" );\n\n\t/* If we're expecting a client certificate, process the client \n\t   certificate verify */\n\tif( clientCertAuthRequired( sessionInfoPtr ) )\n\t\t{\n\t\tconst BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo ) ? \\\n\t\t\t\t\t\t\t  TRUE : FALSE;\n\n\t\t/* Read the next packet(s) if necessary */\n\t\tstatus = refreshHSStream( sessionInfoPtr, handshakeInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Process the client certificate verify packet:\n\n\t\t\tbyte\t\tID = SSL_HAND_CLIENT_CERTVERIFY\n\t\t\tuint24\t\tlen\n\t\t\tbyte[]\t\tsignature */\n\t\tstatus = checkHSPacketHeader( sessionInfoPtr, stream, &length,\n\t\t\t\t\t\t\t\t\t  SSL_HAND_CLIENT_CERTVERIFY, \n\t\t\t\t\t\t\t\t\t  isECC ? MIN_PKCSIZE_ECCPOINT : \\\n\t\t\t\t\t\t\t\t\t\t\t  MIN_PKCSIZE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = checkCertVerify( sessionInfoPtr, handshakeInfo, stream, \n\t\t\t\t\t\t\t\t\t  length );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tsMemDisconnect( stream );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tsMemDisconnect( stream );\n\tCFI_CHECK_UPDATE( \"checkCertVerify\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_4( \"readCheckClientCerts\", \"processKeyex\", \n\t\t\t\t\t\t\t\t\t\"createSessionHash\", \"checkCertVerify\" ) );\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid initSSLserverProcessing( SSL_HANDSHAKE_INFO *handshakeInfo )\n\t{\n\tassert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );\n\n\tFNPTR_SET( handshakeInfo->beginHandshake, beginServerHandshake );\n\tFNPTR_SET( handshakeInfo->exchangeKeys, exchangeServerKeys );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/ssl_wr.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib TLS Session Write Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"misc_rw.h\"\n  #include \"session.h\"\n  #include \"ssl.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/misc_rw.h\"\n  #include \"session/session.h\"\n  #include \"session/ssl.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_SSL\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSub-packet Management Routines\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Open and complete an SSL packet:\n\n\t offset\t\t\t\t\t\t\t\t\t\tpacketEndOfs\n\t\t|\t\t\t\t\t\t\t\t\t\t\t|\n\t\tv\t\t\t\t\t\t\t\t\t\t\tv\n\t\t+---+---+---+----+--------------------------+\n\t\t|ID\t|Ver|Len|(IV)|\t\t\t\t\t\t\t|\n\t\t+---+---+---+----+--------------------------+\n\n   An initial openXXX() starts a new packet at the start of a stream and \n   continueXXX() adds another packet after an existing one, or (for the\n   xxxHSXXX() variants) adds a handshake sub-packet within an existing \n   packet.  The continueXXX() operations return the start offset of the new \n   packet within the stream, openXXX() always starts at the start of the SSL \n   send buffer so the start offset is an implied 0.  completeXXX() then goes \n   back to the given offset and deposits the appropriate length value in the \n   header that was written earlier.  So typical usage (with state variables \n   and error checking omitted for clarity) would be:\n\n\t// Change-cipher-spec packet\n\topenPacketStreamSSL( CRYPT_USE_DEFAULT, SSL_MSG_CHANGE_CIPHER_SPEC );\n\twrite( stream, ... );\n\tcompletePacketStreamSSL( stream, 0 );\n\n\t// Finished handshake sub-packet within a handshake packet\n\tcontinuePacketStreamSSL( SSL_MSG_HANDSHAKE );\n\tcontinueHSPacketStream( SSL_HAND_FINISHED, &offset );\n\twrite( stream, ... );\n\tcompleteHSPacketStream( stream, offset );\n\t// (Packet stream is completed by wrapPacketSSL()) */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int startPacketStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\t  const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t  IN_RANGE( SSL_MSG_FIRST, \\\n\t\t\t\t\t\t\t\t\t\tSSL_MSG_LAST ) const int packetType )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\n\t/* Write the packet header:\n\n\t\tbyte\t\tID = packetType\n\t\tbyte[2]\t\tversion = { 0x03, 0x0n }\n\t\tuint16\t\tlen = 0 (placeholder) \n\t  [ byte[]\t\tiv\t- TLS 1.1+ only ] */\n\tsputc( stream, packetType );\n\tsputc( stream, SSL_MAJOR_VERSION );\n\tsputc( stream, sessionInfoPtr->version );\n\tstatus = writeUint16( stream, 0 );\t\t/* Placeholder */\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t   SESSION_FLAG_ISSECURE_WRITE ) && \\\n\t\tsslInfo->ivSize > 0 )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\t\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\n\t\tsetMessageData( &msgData, iv, sslInfo->ivSize );\n\t\tkrnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, \n\t\t\t\t\t\t &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\t\tstatus = swrite( stream, iv, sslInfo->ivSize );\n\t\t}\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint openPacketStreamSSL( OUT STREAM *stream, \n\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t IN_DATALENGTH_OPT const int bufferSize, \n\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType )\n\t{\n\tconst int streamSize = ( bufferSize == CRYPT_USE_DEFAULT ) ? \\\n\t\t\t\t\t\t   sessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE : \\\n\t\t\t\t\t\t   bufferSize + sessionInfoPtr->sendBufStartOfs;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) && \\\n\t\t\tisWritePtrDynamic( sessionInfoPtr->sendBuffer, streamSize ) );\n\n\tREQUIRES( bufferSize == CRYPT_USE_DEFAULT || \\\n\t\t\t  ( packetType == SSL_MSG_APPLICATION_DATA && \\\n\t\t\t    bufferSize == 0 ) || \\\n\t\t\t  ( bufferSize > 0 && bufferSize < MAX_BUFFER_SIZE ) );\n\t\t\t  /* When wrapping up data packets we only write the implicit-\n\t\t\t\t length header so the buffer size is zero */\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\tREQUIRES( streamSize >= sessionInfoPtr->sendBufStartOfs && \\\n\t\t\t  streamSize <= sessionInfoPtr->sendBufSize - EXTRA_PACKET_SIZE );\n\n\t/* Create the stream */\n\tsMemOpen( stream, sessionInfoPtr->sendBuffer, streamSize );\n\treturn( startPacketStream( stream, sessionInfoPtr, packetType ) );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \\\nint continuePacketStreamSSL( INOUT STREAM *stream, \n\t\t\t\t\t\t\t const SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_HAND_LAST ) const int packetType,\n\t\t\t\t\t\t\t OUT_LENGTH_SHORT_Z int *packetOffset )\n\t{\n\tconst int offset = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( packetOffset, sizeof( int ) ) );\n\t\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\tREQUIRES( offset >= SSL_HEADER_SIZE && \\\n\t\t\t  offset <= sessionInfoPtr->sendBufSize );\n\n\t/* Clear return value */\n\t*packetOffset = 0;\n\n\t/* Continue the stream */\n\tstatus = startPacketStream( stream, sessionInfoPtr, packetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*packetOffset = offset;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completePacketStreamSSL( INOUT STREAM *stream, \n\t\t\t\t\t\t\t IN_LENGTH_Z const int offset )\n\t{\n\tconst int packetEndOffset = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\t\n\tREQUIRES( ( offset == 0 || offset >= SSL_HEADER_SIZE ) && \\\n\t\t\t  offset <= packetEndOffset - ( ID_SIZE + VERSIONINFO_SIZE ) );\n\tREQUIRES( packetEndOffset >= SSL_HEADER_SIZE && \\\n\t\t\t  packetEndOffset < MAX_INTLENGTH_SHORT );\n\n\t/* Update the length field at the start of the packet */\n\tsseek( stream, offset + ID_SIZE + VERSIONINFO_SIZE );\n\tstatus = writeUint16( stream, ( packetEndOffset - offset ) - \\\n\t\t\t\t\t\t\t\t  SSL_HEADER_SIZE );\n\tsseek( stream, packetEndOffset );\n\n\treturn( status );\n\t}\n\n/* Start and complete a handshake packet within an SSL packet.  Since this\n   continues an existing packet stream that's been opened using \n   openPacketStreamSSL(), it's denoted as continueXXX() rather than \n   openXXX() */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint continueHSPacketStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_RANGE( SSL_HAND_FIRST, \\\n\t\t\t\t\t\t\t\t\t  SSL_HAND_LAST ) const int packetType,\n\t\t\t\t\t\t\tOUT_LENGTH_SHORT_Z int *packetOffset )\n\t{\n\tconst int offset = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( packetOffset, sizeof( int ) ) );\n\n\tREQUIRES( packetType >= SSL_HAND_FIRST && packetType <= SSL_HAND_LAST );\n\tREQUIRES( offset >= SSL_HEADER_SIZE && \\\n\t\t\t  offset < MAX_INTLENGTH_SHORT );\n\n\t/* Clear return value */\n\t*packetOffset = 0;\n\n\t/* Write the handshake packet header:\n\n\t\tbyte\t\tID = packetType\n\t\tuint24\t\tlen = 0 (placeholder) */\n\tsputc( stream, packetType );\n\tstatus = writeUint24( stream, 0 );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\t*packetOffset = offset;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint completeHSPacketStream( INOUT STREAM *stream, \n\t\t\t\t\t\t\tIN_LENGTH const int offset )\n\t{\n\tconst int packetEndOffset = stell( stream );\n\tint status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( offset >= SSL_HEADER_SIZE && \\\n\t\t\t  offset <= packetEndOffset - ( ID_SIZE + LENGTH_SIZE ) );\n\t\t\t  /* HELLO_DONE has size zero so \n\t\t\t     offset == packetEndOffset - HDR_SIZE */\n\tREQUIRES( packetEndOffset >= SSL_HEADER_SIZE && \\\n\t\t\t  packetEndOffset < MAX_INTLENGTH_SHORT );\n\n\t/* Update the length field at the start of the packet */\n\tsseek( stream, offset + ID_SIZE );\n\tstatus = writeUint24( stream, packetEndOffset - \\\n\t\t\t\t\t\t\t\t  ( offset + ID_SIZE + LENGTH_SIZE ) );\n\tsseek( stream, packetEndOffset );\n\tDEBUG_PRINT(( \"Wrote %s (%d) handshake packet, length %ld.\\n\", \\\n\t\t\t\t  getSSLHSPacketName( DEBUG_GET_STREAMBYTE( stream, offset ) ), \n\t\t\t\t  DEBUG_GET_STREAMBYTE( stream, offset ),\n\t\t\t\t  ( packetEndOffset - offset ) - ( ID_SIZE + LENGTH_SIZE ) ));\n\tDEBUG_DUMP_STREAM( stream, offset + ( ID_SIZE + LENGTH_SIZE ), \n\t\t\t\t\t   ( packetEndOffset - offset ) - ( ID_SIZE + LENGTH_SIZE ) );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWrite/Wrap a Packet\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wrap an SSL data packet.  There are three forms of this, the first for\n   standard MAC-then-encrypt:\n\n\tsendBuffer hdrPtr\tdataPtr\n\t\t|\t\t|-----\t\t|-------------------\t\t\t  MAC'd\n\t\tv\t\tv\t\t\tv================================ Encrypted\n\t\t+-------+-----+-----+-------------------+-----+-----+\n\t\t|///////| hdr | IV\t|\t\tdata\t\t| MAC | pad |\n\t\t+-------+-----+-----+-------------------+-----+-----+\n\t\t\t\t^<----+---->|<-- dataLength --->^\t\t\t|\n\t\t\t\t|\t  |\t\t <-------- bMaxLen -|---------->\n\t\t\t offset sBufStartOfs\t\t  stell( stream )\n\n   The second for encrypt-then-MAC:\n\n\tsendBuffer hdrPtr\tdataPtr\n\t\t|\t\t|\t\t\t|=========================\t\t  Encrypted\n\t\tv\t\tv-----------v-------------------------        MAC'd\n\t\t+-------+-----+-----+-------------------+-----+-----+\n\t\t|///////| hdr | IV\t|\t\tdata\t\t| pad | MAC |\n\t\t+-------+-----+-----+-------------------+-----+-----+\n\t\t\t\t^<----+---->|<-- dataLength --->^\t\t\t|\n\t\t\t\t|\t  |\t\t <-------- bMaxLen -|---------->\n\t\t\t offset sBufStartOfs\t\t  stell( stream )\n\n   And the third for GCM:\n\n\tsendBuffer hdrPtr\tdataPtr\n\t\t|\t\t|\t\t\t|\n\t\tv\t\tv-----\t\tv============================== AuthEnc'd\n\t\t+-------+-----+-----+-----------------------+-----+\n\t\t|///////| hdr | IV\t|\t\tdata\t\t\t| ICV |\n\t\t+-------+-----+-----+-----------------------+-----+\n\t\t\t\t^<----+---->|<-- dataLength --->^\t  |\n\t\t\t\t|\t  |\t\t <-------- bMaxLen -----|---->\n\t\t\t offset sBufStartOfs\t\t\t  stell( stream )\n\n   These are sufficiently different that we use three distinct functions to\n   do the job.  These MAC/ICV the data, add the IV if necessary, pad and \n   encrypt, and update the header */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int wrapPacketSSLStd( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( SSL_MSG_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_MSG_LAST ) const int packetType,\n\t\t\t\t\t\t\t INOUT_BUFFER( bufMaxLen, *length ) \\\n\t\t\t\t\t\t\t\tBYTE *dataPtr,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int bufMaxLen,\n\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxLen ) \\\n\t\t\t\t\t\t\t\tint *length,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tint effectiveBufMaxLen, payloadLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( dataPtr, bufMaxLen ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\tREQUIRES( bufMaxLen > 0 && bufMaxLen <= sessionInfoPtr->sendBufSize );\n\tREQUIRES( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );\n\n\t/* Clear return values */\n\t*length = 0;\n\n\t/* MAC the payload */\n#ifdef USE_SSL3\n\tif( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )\n\t\t{\n\t\tstatus = createMacSSL( sessionInfoPtr, dataPtr, bufMaxLen, \n\t\t\t\t\t\t\t   &payloadLength, dataLength, packetType );\n\t\t}\n\telse\n#endif /* USE_SSL3 */\n\t\t{\n\t\tstatus = createMacTLS( sessionInfoPtr, dataPtr, bufMaxLen, \n\t\t\t\t\t\t\t   &payloadLength, dataLength, packetType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If it's TLS 1.1+ and we're using a block cipher, adjust for the \n\t   explicit IV that precedes the data.  This is because the IV load is\n\t   handled implicitly by encrypting it as part of the data.  We know \n\t   that the resulting values are within bounds because \n\t   dataPtr = headerPtr + hdr + IV */\n\tif( sslInfo->ivSize > 0 )\n\t\t{\n\t\tREQUIRES( sessionInfoPtr->sendBufStartOfs >= SSL_HEADER_SIZE + \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t sslInfo->ivSize && \\\n\t\t\t\t  sessionInfoPtr->sendBufStartOfs <= sessionInfoPtr->sendBufSize );\n\t\tdataPtr -= sslInfo->ivSize;\n\t\tpayloadLength += sslInfo->ivSize;\n\t\teffectiveBufMaxLen = bufMaxLen + sslInfo->ivSize;\n\t\tENSURES( payloadLength > 0 && payloadLength <= effectiveBufMaxLen )\n\t\t}\n\telse\n\t\teffectiveBufMaxLen = bufMaxLen;\n\tDEBUG_PRINT(( \"Wrote %s (%d) packet, length %ld.\\n\", \n\t\t\t\t  getSSLPacketName( packetType ), packetType, \n\t\t\t\t  payloadLength ));\n\tDEBUG_DUMP_DATA( dataPtr, payloadLength );\n\n\t/* Pad and encrypt the payload */\n\tstatus = encryptData( sessionInfoPtr, dataPtr, effectiveBufMaxLen, \n\t\t\t\t\t\t  &payloadLength, payloadLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Tell the caller what the final packet size is */\n\t*length = payloadLength;\n\n\treturn( CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int wrapPacketTLSMAC( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( SSL_MSG_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_MSG_LAST ) const int packetType,\n\t\t\t\t\t\t\t INOUT_BUFFER( bufMaxLen, *length ) \\\n\t\t\t\t\t\t\t\tBYTE *dataPtr,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int bufMaxLen,\n\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxLen ) int *length,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tint effectiveBufMaxLen, payloadLength = dataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( dataPtr, bufMaxLen ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\tREQUIRES( bufMaxLen > 0 && bufMaxLen <= sessionInfoPtr->sendBufSize );\n\tREQUIRES( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );\n\n\t/* Clear return values */\n\t*length = 0;\n\n\t/* If it's TLS 1.1+ and we're using a block cipher, adjust for the \n\t   explicit IV that precedes the data.  This is because the IV load is \n\t   handled implicitly by encrypting it as part of the data.  We know \n\t   that the resulting values are within bounds because \n\t   dataPtr = headerPtr + hdr + IV */\n\tif( sslInfo->ivSize > 0 )\n\t\t{\n\t\tREQUIRES( sessionInfoPtr->sendBufStartOfs >= SSL_HEADER_SIZE + \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t sslInfo->ivSize && \\\n\t\t\t\t  sessionInfoPtr->sendBufStartOfs <= sessionInfoPtr->sendBufSize );\n\t\tdataPtr -= sslInfo->ivSize;\n\t\tpayloadLength += sslInfo->ivSize;\n\t\teffectiveBufMaxLen = bufMaxLen + sslInfo->ivSize;\n\t\tENSURES( payloadLength > 0 && payloadLength <= effectiveBufMaxLen )\n\t\t}\n\telse\n\t\teffectiveBufMaxLen = bufMaxLen;\n\tDEBUG_PRINT(( \"Wrote %s (%d) packet, length %ld.\\n\", \n\t\t\t\t  getSSLPacketName( packetType ), packetType, \n\t\t\t\t  payloadLength ));\n\tDEBUG_DUMP_DATA( dataPtr, payloadLength );\n\n\t/* Pad and encrypt the payload */\n\tstatus = encryptData( sessionInfoPtr, dataPtr, effectiveBufMaxLen, \n\t\t\t\t\t\t  &payloadLength, payloadLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* MAC the payload */\n\tstatus = createMacTLS( sessionInfoPtr, dataPtr, bufMaxLen, \n\t\t\t\t\t\t   &payloadLength, payloadLength, packetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Tell the caller what the final packet size is */\n\t*length = payloadLength;\n\n\treturn( CRYPT_OK );\n\t}\n\n#ifdef USE_GCM\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int wrapPacketTLSGCM( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t\t\t IN_RANGE( SSL_MSG_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_MSG_LAST ) const int packetType,\n\t\t\t\t\t\t\t INOUT_BUFFER( bufMaxLen, *length ) \\\n\t\t\t\t\t\t\t\t\tBYTE *dataPtr,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int bufMaxLen,\n\t\t\t\t\t\t\t OUT_LENGTH_BOUNDED_Z( bufMaxLen ) int *length,\n\t\t\t\t\t\t\t IN_LENGTH_SHORT const int dataLength )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tMESSAGE_DATA msgData;\n\tBYTE iv[ CRYPT_MAX_IVSIZE + 8 ];\n\tint payloadLength = dataLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtrDynamic( dataPtr, bufMaxLen ) );\n\tassert( isWritePtr( length, sizeof( int ) ) );\n\n\tREQUIRES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\tREQUIRES( bufMaxLen > 0 && bufMaxLen <= sessionInfoPtr->sendBufSize );\n\tREQUIRES( dataLength >= 0 && dataLength <= MAX_PACKET_SIZE );\n\n\t/* Clear return values */\n\t*length = 0;\n\n\t/* For GCM the IV has to be assembled from implicit and explicit \n\t   components and set explicitly.  The implicit portion is fixed for \n\t   each session and equivalent to the TLS client/server_write_IV derived\n\t   from the master secret, the explicit portion is randomly chosen for \n\t   each message.\n\t   \n\t   There are a variety of options for this one, all of which are \n\t   designed to meet the general requirement that the nonce not repeat, \n\t   which leads to a catastrophic failure of security: use a counter \n\t   starting at zero, use the sequence number, use a counter starting at \n\t   a random position, and use a completely random number.  The last \n\t   option runs into a potential collision problem after 2^32 TLS \n\t   messages on average, however due to the incredible brittleness of GCM \n\t   the use of completely unrelated, random nonces may be the best way of \n\t   protecting against issues (apart from not using GCM at all, which is \n\t   the default config setting).  Given cryptlib's field of application, \n\t   the chances of it being used to send several billion TLS messages in \n\t   a single session is extremely remote, so we use the (possible) extra\n\t   protection offered by the use of unrelated nonces.\n\n\t   The reason why it's twelve bytes is because AES-GCM preferentially \n\t   uses 96 bits of IV followed by 32 bits of 000...1, with other lengths \n\t   being possible but then the data has to be cryptographically reduced \n\t   to 96 bits before processing, so TLS specifies a fixed length of 96 \n\t   bits:\n\n\t\t|<--- 12 bytes ---->|\n\t\t+-------+-----------+\n\t\t| Salt\t|\tNonce\t|\n\t\t+-------+-----------+\n\t\t|<- 4 ->|<--- 8 --->| \n\n\t   In addition we have to process the packet metadata that's normally\n\t   MACed as GCM AAD */\n\tREQUIRES( boundsCheck( sslInfo->gcmSaltSize, sslInfo->ivSize, \n\t\t\t\t\t\t   CRYPT_MAX_IVSIZE ) );\n\tmemcpy( iv, sslInfo->gcmWriteSalt, sslInfo->gcmSaltSize );\n\tmemcpy( iv + sslInfo->gcmSaltSize, dataPtr - sslInfo->ivSize, \n\t\t\tsslInfo->ivSize );\n\tsetMessageData( &msgData, iv, GCM_IV_SIZE );\n\tstatus = krnlSendMessage( sessionInfoPtr->iCryptOutContext,\n\t\t\t\t\t\t\t  IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_IV );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Process the packet metadata as GCM AAD */\n\tstatus = macDataTLSGCM( sessionInfoPtr->iCryptOutContext, \n\t\t\t\t\t\t\tsslInfo->writeSeqNo, sessionInfoPtr->version, \n\t\t\t\t\t\t\tpayloadLength, packetType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsslInfo->writeSeqNo++;\n\tDEBUG_PRINT(( \"Wrote %s (%d) packet, length %ld.\\n\", \n\t\t\t\t  getSSLPacketName( packetType ), packetType, \n\t\t\t\t  payloadLength ));\n\tDEBUG_DUMP_DATA( dataPtr, payloadLength );\n\n\t/* Pad and encrypt the payload */\n\tstatus = encryptData( sessionInfoPtr, dataPtr, bufMaxLen, \n\t\t\t\t\t\t  &payloadLength, payloadLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Adjust the length to account for the IV data at the start (for non-\n\t   GCM modes this is handled implicitly by making the IV part of the \n\t   data to encrypt) */\n\tpayloadLength += sslInfo->ivSize;\n\n\t/* Tell the caller what the final packet size is */\n\t*length = payloadLength;\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_GCM */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint wrapPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t   IN_LENGTH_Z const int offset )\n\t{\n\tSSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;\n\tSTREAM lengthStream;\n\tBYTE lengthBuffer[ UINT16_SIZE + 8 ];\n\tBYTE *dataPtr, *headerPtr;\n\tconst int payloadLength = stell( stream ) - \\\n\t\t\t\t\t\t\t  ( offset + sessionInfoPtr->sendBufStartOfs );\n\tconst int bufMaxLen = payloadLength + sMemDataLeft( stream );\n\tint packetType, length, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t\t SESSION_FLAG_ISSECURE_WRITE ) );\n\tREQUIRES( sStatusOK( stream ) );\n\tREQUIRES( offset >= 0 && \\\n\t\t\t  offset <= stell( stream ) - \\\n\t\t\t\t\t\t\t( payloadLength + \\\n\t\t\t\t\t\t\t  sessionInfoPtr->sendBufStartOfs ) );\n\tREQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE && \\\n\t\t\t  payloadLength < sessionInfoPtr->sendBufSize - \\\n\t\t\t\t\t\t\t  ( sessionInfoPtr->sendBufStartOfs + \\\n\t\t\t\t\t\t\t\tsslInfo->ivSize ) );\n\n\t/* Get pointers into the data stream for the crypto processing */\n\tstatus = sMemGetDataBlockAbs( stream, offset, ( void ** ) &headerPtr, \n\t\t\t\t\t\t\t\t  SSL_HEADER_SIZE + sslInfo->ivSize + \\\n\t\t\t\t\t\t\t\t\t\t\t\t\tbufMaxLen );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdataPtr = headerPtr + SSL_HEADER_SIZE + sslInfo->ivSize;\n\tpacketType = byteToInt( *headerPtr );\n\tENSURES( packetType >= SSL_MSG_FIRST && packetType <= SSL_MSG_LAST );\n\n\t/* Wrap the data based on the type of processing that we're using */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ENCTHENMAC ) )\n\t\t{\n\t\tstatus = wrapPacketTLSMAC( sessionInfoPtr, packetType, dataPtr, \n\t\t\t\t\t\t\t\t   bufMaxLen, &length, payloadLength );\n\t\t}\n\telse\n\t\t{\n#ifdef USE_GCM\n\t\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_GCM ) )\n\t\t\t{\n\t\t\tstatus = wrapPacketTLSGCM( sessionInfoPtr, packetType, dataPtr, \n\t\t\t\t\t\t\t\t\t   bufMaxLen, &length, payloadLength );\n\t\t\t}\n\t\telse\n#endif /* USE_GCM */\n\t\t\t{\n\t\t\tstatus = wrapPacketSSLStd( sessionInfoPtr, packetType, dataPtr, \n\t\t\t\t\t\t\t\t\t   bufMaxLen, &length, payloadLength );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Insert the final packet payload length into the packet header.  We \n\t   directly copy the data in because the stream may have been opened in \n\t   read-only mode if we're using it to write pre-assembled packet data \n\t   that's been passed in by the caller */\n\tsMemOpen( &lengthStream, lengthBuffer, UINT16_SIZE );\n\tstatus = writeUint16( &lengthStream, length );\n\tsMemDisconnect( &lengthStream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tmemcpy( headerPtr + ID_SIZE + VERSIONINFO_SIZE, lengthBuffer, \n\t\t\tUINT16_SIZE );\n\n\t/* Sync the stream information to match the new payload size */\n\treturn( sSkip( stream, length - ( sslInfo->ivSize + payloadLength ),\n\t\t\t\t   SSKIP_MAX ) );\n\t}\n\n/* Wrap up and send an SSL packet */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nint sendPacketSSL( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t   INOUT STREAM *stream, \n\t\t\t\t   const BOOLEAN sendOnly )\n\t{\n\tconst int length = stell( stream );\n\tvoid *dataPtr;\n\tint status;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\n\tREQUIRES( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES( sStatusOK( stream ) );\n\tREQUIRES( sendOnly == TRUE || sendOnly == FALSE );\n\tREQUIRES( length >= SSL_HEADER_SIZE && \\\n\t\t\t  length <= sessionInfoPtr->sendBufSize );\n\n\t/* Update the length field at the start of the packet if necessary */\n\tif( !sendOnly )\n\t\t{\n\t\tstatus = completePacketStreamSSL( stream, 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Send the packet to the peer */\n\tstatus = sMemGetDataBlockAbs( stream, 0, &dataPtr, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tANALYSER_HINT( dataPtr != NULL );\n\tstatus = swrite( &sessionInfoPtr->stream, dataPtr, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsNetGetErrorInfo( &sessionInfoPtr->stream,\n\t\t\t\t\t\t  &sessionInfoPtr->errorInfo );\n\t\treturn( status );\n\t\t}\n\tDEBUG_DUMP_SSL( dataPtr, length, NULL, 0 );\n\n\treturn( CRYPT_OK );\t/* swrite() returns a byte count */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSend SSL Alerts\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a close alert, with appropriate protection if necessary */\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nstatic void sendAlert( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t   IN_RANGE( SSL_ALERTLEVEL_WARNING, \\\n\t\t\t\t\t\t\t\t SSL_ALERTLEVEL_FATAL ) const int alertLevel, \n\t\t\t\t\t   IN_RANGE( SSL_ALERT_FIRST, \\\n\t\t\t\t\t\t\t\t SSL_ALERT_LAST ) const int alertType,\n\t\t\t\t\t   const BOOLEAN alertReceived )\n\t{\n\tSTREAM stream;\n\tint length DUMMY_INIT, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\t\n\tREQUIRES_V( alertLevel == SSL_ALERTLEVEL_WARNING || \\\n\t\t\t\talertLevel == SSL_ALERTLEVEL_FATAL );\n\tREQUIRES_V( alertType >= SSL_ALERT_FIRST && \\\n\t\t\t\talertType <= SSL_ALERT_LAST );\n\tREQUIRES_V( alertReceived == TRUE || alertReceived == FALSE );\n\n\t/* Make sure that we only send a single alert.  Normally we do this \n\t   automatically on shutdown, but we may have already sent it earlier \n\t   as part of an error-handler */\n\tif( TEST_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ALERTSENT ) )\n\t\treturn;\n\tSET_FLAG( sessionInfoPtr->protocolFlags, SSL_PFLAG_ALERTSENT );\n\n\t/* Create the alert.  We can't really do much with errors at this point, \n\t   although we can throw an exception in the debug version to draw \n\t   attention to the fact that there's a problem.  The one error type \n\t   that we don't complain about is an access permission problem, which \n\t   can occur when cryptlib is shutting down, for example when the \n\t   current thread is blocked waiting for network traffic and another \n\t   thread shuts things down.\n\t   \n\t   If we encounter an error during this processing, we continue anyway \n\t   and drop through and perform a clean shutdown even if the creation of \n\t   the close alert fails */\n\tstatus = openPacketStreamSSL( &stream, sessionInfoPtr, \n\t\t\t\t\t\t\t\t  CRYPT_USE_DEFAULT, SSL_MSG_ALERT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsputc( &stream, alertLevel );\n\t\tstatus = sputc( &stream, alertType );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( TEST_FLAG( sessionInfoPtr->flags, \n\t\t\t\t\t   SESSION_FLAG_ISSECURE_WRITE ) )\n\t\t\t{\n\t\t\tstatus = wrapPacketSSL( sessionInfoPtr, &stream, 0 );\n\t\t\tassert( cryptStatusOK( status ) || \\\n\t\t\t\t\tstatus == CRYPT_ERROR_PERMISSION );\n\t\t\t}\n\t\telse\n\t\t\tstatus = completePacketStreamSSL( &stream, 0 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tlength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\t}\n\t/* Fall through with status passed on to the following code */\n\n\t/* Send the alert, or if there was an error at least perform a clean \n\t   shutdown */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = sendCloseNotification( sessionInfoPtr, \n\t\t\t\t\t\t\t\t\t\tsessionInfoPtr->sendBuffer, \n\t\t\t\t\t\t\t\t\t\tlength );\n\t\t}\n\telse\n\t\tstatus = sendCloseNotification( sessionInfoPtr, NULL, 0 );\n\tif( cryptStatusError( status ) || alertReceived )\n\t\treturn;\n\n\t/* Read back the other side's close alert acknowledgement.  Again, since \n\t   we're closing down the session anyway there's not much that we can do \n\t   in response to an error */\n\t( void ) readHSPacketSSL( sessionInfoPtr, NULL, &length, \n\t\t\t\t\t\t\t  SSL_MSG_ALERT );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendCloseAlert( INOUT SESSION_INFO *sessionInfoPtr, \n\t\t\t\t\t const BOOLEAN alertReceived )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES_V( alertReceived == TRUE || alertReceived == FALSE );\n\n\tsendAlert( sessionInfoPtr, SSL_ALERTLEVEL_WARNING, \n\t\t\t   SSL_ALERT_CLOSE_NOTIFY, alertReceived );\n\t}\n\nSTDC_NONNULL_ARG( ( 1 ) ) \\\nvoid sendHandshakeFailAlert( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t IN_RANGE( SSL_ALERT_FIRST, \\\n\t\t\t\t\t\t\t\t\t   SSL_ALERT_LAST ) const int alertType )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES_V( sanityCheckSessionSSL( sessionInfoPtr ) );\n\tREQUIRES_V( alertType >= SSL_ALERT_FIRST && \\\n\t\t\t\talertType <= SSL_ALERT_LAST );\n\n\t/* We set the alertReceived flag to true when sending a handshake\n\t   failure alert to avoid waiting to get back an ack, since this \n\t   alert type isn't acknowledged by the other side */\n\tsendAlert( sessionInfoPtr, SSL_ALERTLEVEL_FATAL, alertType, TRUE );\n\t}\n#endif /* USE_SSL */\n"
  },
  {
    "path": "deps/cl345/session/tsp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t cryptlib TSP Session Management\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1999-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( INC_ALL )\n  #include \"crypt.h\"\n  #include \"asn1.h\"\n  #include \"asn1_ext.h\"\n  #include \"session.h\"\n#else\n  #include \"crypt.h\"\n  #include \"enc_dec/asn1.h\"\n  #include \"enc_dec/asn1_ext.h\"\n  #include \"session/session.h\"\n#endif /* Compiler-specific includes */\n\n#ifdef USE_TSP\n\n/* TSP constants */\n\n#define TSP_VERSION\t\t\t\t\t1\t/* Version number */\n#define MIN_MSGIMPRINT_SIZE\t\t\t( 2 + 10 + 16 )\t/* SEQ + MD5 OID + MD5 hash */\n#define MAX_MSGIMPRINT_SIZE\t\t\t( 32 + CRYPT_MAX_HASHSIZE )\n\n/* TSP HTTP content types */\n\n#define TSP_CONTENT_TYPE_REQ\t\t\"application/timestamp-query\"\n#define TSP_CONTENT_TYPE_REQ_LEN\t27\n#define TSP_CONTENT_TYPE_RESP\t\t\"application/timestamp-reply\"\n#define TSP_CONTENT_TYPE_RESP_LEN\t27\n\n/* TSP protocol state information.  This is passed around the various\n   subfunctions that handle individual parts of the protocol */\n\ntypedef struct {\n\t/* TSP protocol control information.  The hashAlgo is usually unset (so \n\t   it has a value of CRYPT_ALGO_NONE) but may be set if the client has\n\t   indicated that they want to use a stronger hash algorithm than the \n\t   default one */\n\tCRYPT_ALGO_TYPE hashAlgo;\t\t\t/* Optional hash algorithm for TSA resp.*/\n\tBOOLEAN includeSigCerts;\t\t\t/* Whether to include signer certificates */\n\n\t/* TSP request/response data */\n\tBUFFER( MAX_MSGIMPRINT_SIZE, msgImprintSize ) \\\n\tBYTE msgImprint[ MAX_MSGIMPRINT_SIZE + 8 ];\n\tint msgImprintSize;\t\t\t\t\t/* Message imprint */\n\tBUFFER( CRYPT_MAX_HASHSIZE, nonceSize ) \\\n\tBYTE nonce[ CRYPT_MAX_HASHSIZE + 8 ];\n\tint nonceSize;\t\t\t\t\t\t/* Nonce (if present) */\n\n\t} TSP_PROTOCOL_INFO;\n\n/* Prototypes for functions in cmp_rd.c.  This code is shared due to TSP's use\n   of random elements cut & pasted from CMP */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \\\nint readPkiStatusInfo( INOUT STREAM *stream, \n\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t   INOUT ERROR_INFO *errorInfo );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Sanity-check the session state */\n\nCHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic BOOLEAN sanityCheckSessionTSP( IN const SESSION_INFO *sessionInfoPtr )\n\t{\n\tconst TSP_INFO *tspInfo = sessionInfoPtr->sessionTSP;\n\n\tassert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( tspInfo, sizeof( TSP_INFO ) ) );\n\n\t/* Check the general envelope state */\n\tif( !sanityCheckSession( sessionInfoPtr ) )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionTSP: Session check\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check TSP session parameters */\n\tif( ( tspInfo->imprintAlgo != CRYPT_ALGO_NONE && \\\n\t\t  !isHashAlgo( tspInfo->imprintAlgo ) ) || \\\n\t\ttspInfo->imprintSize < 0 || \\\n\t\ttspInfo->imprintSize > CRYPT_MAX_HASHSIZE )\n\t\t{\n\t\tDEBUG_PUTS(( \"sanityCheckSessionTSP: Session parameters\" ));\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Read a TSP request:\n\n\tTSARequest ::= SEQUENCE {\n\t\tversion\t\t\t\tINTEGER (1),\n\t\tmsgImprint\t\t\tMessageDigest,\n\t\tpolicy\t\t\t\tOBJECT IDENTIFIER OPTIONAL,\n\t\t\t\t\t\t\t\t\t\t\t\t-- Ignored\n\t\tnonce\t\t\t\tINTEGER OPTIONAL,\t-- Copy to output if present\n\t\tincludeSigCerts\t\tBOOLEAN DEFAULT FALSE,\n\t\t\t\t\t\t\t\t\t\t\t\t-- Include signer certs if set\n\t\textensions\t\t[0]\tExtensions OPTIONAL\t-- Ignored, see below\n\t\t} */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \\\nstatic int readTSPRequest( INOUT STREAM *stream, \n\t\t\t\t\t\t   INOUT TSP_PROTOCOL_INFO *protocolInfo,\n\t\t\t\t\t\t   IN_HANDLE const CRYPT_USER iOwnerHandle, \n\t\t\t\t\t\t   IN_LENGTH const int endPos, \n\t\t\t\t\t\t   INOUT ERROR_INFO *errorInfo )\n\t{\n\tCRYPT_ALGO_TYPE defaultHashAlgo, msgImprintHashAlgo DUMMY_INIT;\n\tSTREAM msgImprintStream;\n\tvoid *dataPtr DUMMY_INIT_PTR;\n\tlong value;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint tag, length, status;\n\n\tassert( isWritePtr( stream, sizeof( STREAM ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( TSP_PROTOCOL_INFO ) ) );\n\tassert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );\n\n\tREQUIRES( iOwnerHandle == DEFAULTUSER_OBJECT_HANDLE || \\\n\t\t\t  isHandleRangeValid( iOwnerHandle ) );\n\tREQUIRES( endPos > 0 && endPos > stell( stream ) && \\\n\t\t\t  endPos < MAX_BUFFER_SIZE );\n\n\t/* Read the request header and make sure everything is in order */\n\treadSequence( stream, NULL );\n\tstatus = readShortInteger( stream, &value );\n\tif( cryptStatusError( status ) || value != TSP_VERSION )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid TSP request header\" ) );\n\t\t}\n\n\t/* Read the message imprint.  We don't really care what this is so we\n\t   just treat it as a blob */\n\tstatus = getStreamObjectLength( stream, &length );\n\tif( cryptStatusOK( status ) && !isShortIntegerRangeNZ( length ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sMemGetDataBlock( stream, &dataPtr, length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( length < MIN_MSGIMPRINT_SIZE || length > MAX_MSGIMPRINT_SIZE || \\\n\t\t\tcryptStatusError( sSkip( stream, length, MAX_INTLENGTH_SHORT ) ) )\n\t\t\tstatus = CRYPT_ERROR_BADDATA;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid TSP message imprint data\" ) );\n\t\t}\n\tANALYSER_HINT( dataPtr != NULL );\n\tREQUIRES( rangeCheck( length, 1, MAX_MSGIMPRINT_SIZE ) );\n\tmemcpy( protocolInfo->msgImprint, dataPtr, length );\n\tprotocolInfo->msgImprintSize = length;\n\tCFI_CHECK_UPDATE( \"readMessageImprint\" );\n\n\t/* Pick apart the msgImprint:\n\n\t\tmsgImprint\t\t\tSEQUENCE {\n\t\t\talgorithm\t\tAlgorithmIdentifier,\n\t\t\thash\t\t\tOCTET STRING\n\t\t\t}\n\n\t   to see whether we can use a stronger hash in our response than the \n\t   default SHA-1.  This is done on the basis that if the client sends us\n\t   a message imprint with a stronger hash then they should be able to\n\t   process a response with a stronger hash as well */\n\tsMemConnect( &msgImprintStream, protocolInfo->msgImprint, \n\t\t\t\t protocolInfo->msgImprintSize );\n\tstatus = readSequence( &msgImprintStream, NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readAlgoID( &msgImprintStream, &msgImprintHashAlgo, \n\t\t\t\t\t\t\t ALGOID_CLASS_HASH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = readOctetStringHole( &msgImprintStream, NULL, 16, \n\t\t\t\t\t\t\t\t\t  DEFAULT_TAG );\n\t\t}\n\tsMemDisconnect( &msgImprintStream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA,\n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid TSP message imprint content\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processMessageImprint\" );\n\n\t/* Upgrade to a stronger hash if we can */\n\tstatus = krnlSendMessage( iOwnerHandle, IMESSAGE_GETATTRIBUTE, \n\t\t\t\t\t\t\t  &defaultHashAlgo, CRYPT_OPTION_ENCR_HASH );\n\tif( cryptStatusOK( status ) && \\\n\t\tisStrongerHash( msgImprintHashAlgo, defaultHashAlgo ) )\n\t\tprotocolInfo->hashAlgo = msgImprintHashAlgo;\n\n\t/* Check for the presence of the assorted optional fields */\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_OBJECT_IDENTIFIER )\n\t\t{\n\t\t/* This could be anything since it's defined as \"by prior agreement\"\n\t\t   so we ignore it and give them whatever policy we happen to\n\t\t   implement, if they don't like it then they're free to ignore it */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_INTEGER )\n\t\t{\n\t\t/* For some unknown reason the nonce is encoded as an INTEGER \n\t\t   instead of an OCTET STRING, so in theory we'd have to jump \n\t\t   through all sorts of hoops to handle it because it's really an \n\t\t   OCTET STRING blob dressed up as an INTEGER.  To avoid this mess,\n\t\t   we just read it as a blob and memcpy() it back to the output */\n\t\tstatus = readRawObject( stream, protocolInfo->nonce,\n\t\t\t\t\t\t\t\tCRYPT_MAX_HASHSIZE, \n\t\t\t\t\t\t\t\t&protocolInfo->nonceSize, BER_INTEGER );\n\t\t}\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == BER_BOOLEAN )\n\t\tstatus = readBoolean( stream, &protocolInfo->includeSigCerts );\n\tif( checkStatusLimitsPeekTag( stream, status, tag, endPos ) && \\\n\t\ttag == MAKE_CTAG( 0 ) )\n\t\t{\n\t\t/* The TSP RFC specifies a truly braindamaged interpretation of\n\t\t   extension handling, added at the last minute with no debate or\n\t\t   discussion.  This says that extensions are handled just like RFC\n\t\t   2459 except when they're not.  In particular it requires that you\n\t\t   reject all extensions that you don't recognise, even if they\n\t\t   don't have the critical bit set (in violation of RFC 2459).\n\t\t   Since \"recognise\" is never defined and the spec doesn't specify\n\t\t   any particular extensions that must be handled (via MUST/SHALL/\n\t\t   SHOULD), any extension at all is regarded as unrecognised in the\n\t\t   context of the RFC.  For example if a request with a\n\t\t   subjectAltName is submitted then although the TSA knows perfectly\n\t\t   well what a subjectAltName, it has no idea what it's supposed to\n\t\t   do with it when it sees it in the request.  Since the semantics of\n\t\t   all extensions are unknown (in the context of the RFC), any\n\t\t   request with extensions has to be rejected.\n\n\t\t   Along with assorted other confusing and often contradictory terms\n\t\t   added in the last-minute rewrite, cryptlib ignores this\n\t\t   requirement and instead uses the common-sense interpretation of\n\t\t   allowing any extension that the RFC doesn't specifically provide\n\t\t   semantics for.  Since it doesn't provide semantics for any\n\t\t   extension, we allow anything */\n\t\tstatus = readUniversal( stream );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( CRYPT_ERROR_BADDATA, \n\t\t\t\t( CRYPT_ERROR_BADDATA, errorInfo, \n\t\t\t\t  \"Invalid TSP request additional information fields\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"processAddiotionalFields\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"readMessageImprint\", \n\t\t\t\t\t\t\t\t\t\"processMessageImprint\", \n\t\t\t\t\t\t\t\t\t\"processAddiotionalFields\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Sign a timestamp token */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \\\nstatic int signTSToken( OUT_BUFFER( tsaRespMaxLength, *tsaRespLength ) \\\n\t\t\t\t\t\t\tBYTE *tsaResp, \n\t\t\t\t\t\tIN_LENGTH_SHORT_MIN( 64 ) \\\n\t\t\t\t\t\t\tconst int tsaRespMaxLength, \n\t\t\t\t\t\tOUT_LENGTH_BOUNDED_Z( tsaRespMaxLength ) \\\n\t\t\t\t\t\t\tint *tsaRespLength,\n\t\t\t\t\t\tIN_ALGO_OPT const CRYPT_ALGO_TYPE tsaRespHashAlgo,\n\t\t\t\t\t\tIN_BUFFER( tstInfoLength ) const BYTE *tstInfo, \n\t\t\t\t\t\tIN_LENGTH_SHORT const int tstInfoLength,\n\t\t\t\t\t\tIN_HANDLE const CRYPT_CONTEXT privateKey,\n\t\t\t\t\t\tconst BOOLEAN includeCerts )\n\t{\n\tCRYPT_CERTIFICATE iCmsAttributes;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tDYNBUF essCertDB;\n\tstatic const int minBufferSize = MIN_BUFFER_SIZE;\n\tstatic const int contentType = CRYPT_CONTENT_TSTINFO;\n\tint status;\n\n\tassert( isWritePtrDynamic( tsaResp, tsaRespMaxLength ) );\n\tassert( isWritePtr( tsaRespLength, sizeof( int ) ) );\n\tassert( isReadPtrDynamic( tstInfo, tstInfoLength ) );\n\n\tREQUIRES( tsaRespMaxLength >= 64 && \\\n\t\t\t  tsaRespMaxLength < MAX_INTLENGTH_SHORT );\n\tREQUIRES( tsaRespHashAlgo == CRYPT_ALGO_NONE || \\\n\t\t\t  ( tsaRespHashAlgo >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t\t\ttsaRespHashAlgo <= CRYPT_ALGO_LAST_HASH ) );\n\tREQUIRES( isShortIntegerRangeNZ( tstInfoLength ) );\n\tREQUIRES( isHandleRangeValid( privateKey ) );\n\tREQUIRES( includeCerts == TRUE || includeCerts == FALSE );\n\n\t/* Clear return values */\n\tmemset( tsaResp, 0, min( 16, tsaRespMaxLength ) );\n\t*tsaRespLength = 0;\n\n\t/* Create the signing attributes.  We don't have to set the content-type\n\t   attribute since it'll be set automatically based on the envelope\n\t   content type */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tiCmsAttributes = createInfo.cryptHandle;\n\tstatus = dynCreate( &essCertDB, privateKey, CRYPT_IATTRIBUTE_ESSCERTID );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, dynData( essCertDB ),\n\t\t\t\t\t\tdynLength( essCertDB ) );\n\t\tstatus = krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t&msgData, CRYPT_CERTINFO_CMS_SIGNINGCERT_ESSCERTID );\n\t\tdynDestroy( &essCertDB );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Create a cryptlib envelope to sign the data.  If we're not being\n\t   asked to include signer certificates we have to explicitly disable \n\t   the inclusion of certificates in the signature since S/MIME includes \n\t   them by default.  In addition the caller may have asked us to use a\n\t   non-default hash algorithm, which we specify for the envelope if it's\n\t   been set.  Unfortunately these special-case operations mean that we \n\t   can't use envelopeSign() to process the data, but have to perform the \n\t   whole process ourselves */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_CMS );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,\n\t\t\t\t\t\t\t  &createInfo, OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t\t\t  ( MESSAGE_CAST ) &minBufferSize,\n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_BUFFERSIZE );\n\tif( cryptStatusOK( status ) && tsaRespHashAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, \n\t\t\t\t\t\t\t( MESSAGE_CAST ) &tsaRespHashAlgo,\n\t\t\t\t\t\t\tCRYPT_OPTION_ENCR_HASH );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &tstInfoLength,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_DATASIZE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &contentType,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_CONTENTTYPE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, ( MESSAGE_CAST ) &privateKey,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, &iCmsAttributes,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA );\n\t\t}\n\tif( cryptStatusOK( status ) && !includeCerts )\n\t\t{\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\tIMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE,\n\t\t\t\t\t\t\tCRYPT_IATTRIBUTE_INCLUDESIGCERT );\n\t\t}\n\tkrnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\t\treturn( status );\n\t\t}\n\n\t/* Push in the data and pop the signed result */\n\tsetMessageData( &msgData, ( MESSAGE_CAST ) tstInfo, tstInfoLength );\n\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t  IMESSAGE_ENV_PUSHDATA, &msgData, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_ENV_PUSHDATA, &msgData, 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, tsaResp, tsaRespMaxLength );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_ENV_POPDATA, &msgData, 0 );\n\t\t*tsaRespLength = msgData.length;\n\t\t}\n\tkrnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tClient-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send a request to a TSP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sendClientRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT TSP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tTSP_INFO *tspInfo = sessionInfoPtr->sessionTSP;\n\tSTREAM stream;\n\tvoid *msgImprintPtr;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( TSP_PROTOCOL_INFO ) ) );\n\n\t/* If we're fuzzing, there's no request to send out */\n#ifdef CONFIG_FUZZ\n\tmemset( protocolInfo->msgImprint, '*', 16 );\n\tprotocolInfo->msgImprintSize = 16;\n\treturn( CRYPT_OK );\n#endif /* CONFIG_FUZZ */\n\n\t/* Create the encoded request:\n\n\t\tTSARequest ::= SEQUENCE {\n\t\t\tversion\t\t\t\tINTEGER (1),\n\t\t\tmsgImprint\t\t\tMessageDigest,\n\t\t\tincludeSigCerts\t\tBOOLEAN TRUE\n\t\t\t}\n\t\n\t   We have to ask for the inclusion of signing certificates in the\n\t   response (by default they're not included) because the caller may not \n\t   have the TSA's certificate, or may have an out-of-date version \n\t   depending on how frequently the TSA rolls over certificates.  This \n\t   tends to bloat up the response somewhat, but it's only way to deal\n\t   with the certificate issue without requiring lots of manual \n\t   certificate-processing from the caller.\n\n\t   When we write the message imprint as a hash value we save a copy of\n\t   the encoded data so that we can check it against the returned\n\t   timestamp, see the comment in readServerResponse() for details */\n\tprotocolInfo->msgImprintSize = \\\n\t\t\t\t\t\t\tsizeofMessageDigest( tspInfo->imprintAlgo,\n\t\t\t\t\t\t\t\t\t\t\t\t tspInfo->imprintSize );\n\tENSURES( protocolInfo->msgImprintSize > 0 && \\\n\t\t\t protocolInfo->msgImprintSize <= MAX_MSGIMPRINT_SIZE );\n\tsMemOpen( &stream, sessionInfoPtr->receiveBuffer, 1024 );\n\twriteSequence( &stream, sizeofShortInteger( TSP_VERSION ) + \\\n\t\t\t\t\t\t\tprotocolInfo->msgImprintSize + \\\n\t\t\t\t\t\t\tsizeofBoolean() );\n\twriteShortInteger( &stream, TSP_VERSION, DEFAULT_TAG );\n\tstatus = sMemGetDataBlock( &stream, &msgImprintPtr, \n\t\t\t\t\t\t\t   protocolInfo->msgImprintSize );\n\tENSURES( cryptStatusOK( status ) );\n\twriteMessageDigest( &stream, tspInfo->imprintAlgo, \n\t\t\t\t\t\ttspInfo->imprint, tspInfo->imprintSize );\n\tREQUIRES( rangeCheck( protocolInfo->msgImprintSize, 1, \n\t\t\t\t\t\t  MAX_MSGIMPRINT_SIZE ) );\n\tmemcpy( protocolInfo->msgImprint, msgImprintPtr,\n\t\t\tprotocolInfo->msgImprintSize );\n\tstatus = writeBoolean( &stream, TRUE, DEFAULT_TAG );\n\tif( cryptStatusOK( status ) )\n\t\tsessionInfoPtr->receiveBufEnd = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tDEBUG_DUMP_FILE( \"tsa_req\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\n\t/* Send the request to the server */\n\treturn( writePkiDatagram( sessionInfoPtr, TSP_CONTENT_TYPE_REQ,\n\t\t\t\t\t\t\t  TSP_CONTENT_TYPE_REQ_LEN ) );\n\t}\n\n/* Read the response from the TSP server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readServerResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT TSP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tSTREAM stream;\n\tCFI_CHECK_TYPE CFI_CHECK_VALUE = CFI_CHECK_INIT;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( TSP_PROTOCOL_INFO ) ) );\n\n\t/* Reset the buffer position indicators to clear any old data in the\n\t   buffer from previous transactions */\n\tsessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos = 0;\n\n\t/* Read the response data from the server */\n\tstatus = readPkiDatagram( sessionInfoPtr, MIN_CRYPT_OBJECTSIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tCFI_CHECK_UPDATE( \"readPkiDatagram\" );\n\n\t/* Strip off the header and check the PKIStatus wrapper to make sure\n\t   that everything's OK:\n\n\t\tSEQUENCE {\n\t\t\tstatus\tSEQUENCE {\n\t\t\t\tstatus\tINTEGER,\t\t\t-- 0 = OK\n\t\t\t\t\t\t... OPTIONAL\n\t\t\t\t}\n\t\t\t... */\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treadSequence( &stream, NULL );\n\tstatus = readPkiStatusInfo( &stream, FALSE, \n\t\t\t\t\t\t\t\t&sessionInfoPtr->errorInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* readPkiStatusInfo() has already set the extended error \n\t\t   information */\n\t\tsMemDisconnect( &stream );\n\t\treturn( status );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readPkiStatusInfo\" );\n\n\t/* Remember where the encoded timestamp payload starts in the buffer so\n\t   that we can return it to the caller */\n\tsessionInfoPtr->receiveBufPos = stell( &stream );\n\n\t/* Make sure that we got back a timestamp of the value that we sent.  \n\t   This check means that it works with and without nonces (in theory \n\t   someone could repeatedly contersign the same signature rather than \n\t   countersigning the last timestamp as they're supposed to, but (a) \n\t   that's rather unlikely and (b) cryptlib doesn't support it so they'd \n\t   have to make some rather serious changes to the code to do it) */\n\treadSequence( &stream, NULL );\t\t/* contentInfo */\n\treadUniversal( &stream );\t\t\t/* contentType */\n\treadConstructed( &stream, NULL, 0 );/* content */\n\treadSequence( &stream, NULL );\t\t\t/* signedData */\n\treadShortInteger( &stream, NULL );\t\t/* version */\n\treadUniversal( &stream );\t\t\t\t/* digestAlgos */\n\treadSequence( &stream, NULL );\t\t\t/* encapContent */\n\treadUniversal( &stream );\t\t\t\t\t/* contentType */\n\treadConstructed( &stream, NULL, 0 );\t\t/* content */\n\treadOctetStringHole( &stream, NULL, 16, \n\t\t\t\t\t\t DEFAULT_TAG );\t\t\t/* OCTET STRING hole */\n\treadSequence( &stream, NULL );\t\t\t\t\t/* tstInfo */\n\treadShortInteger( &stream, NULL );\t\t\t\t/* version */\n\tstatus = readUniversal( &stream );\t\t\t\t/* policy */\n\tif( cryptStatusError( status ) )\n\t\tstatus = CRYPT_ERROR_BADDATA;\n\telse\n\t\t{\n\t\tvoid *msgImprintPtr;\n\n\t\tstatus = sMemGetDataBlock( &stream, &msgImprintPtr, \n\t\t\t\t\t\t\t\t   protocolInfo->msgImprintSize );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\tmemcmp( protocolInfo->msgImprint, msgImprintPtr,\n\t\t\t\t\tprotocolInfo->msgImprintSize ) )\n\t\t\tstatus = CRYPT_ERROR_INVALID;\n\t\t}\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tretExt( status,\n\t\t\t\t( status, SESSION_ERRINFO, \n\t\t\t\t  ( status == CRYPT_ERROR_BADDATA || \\\n\t\t\t\t\tstatus == CRYPT_ERROR_UNDERFLOW ) ? \\\n\t\t\t\t\t\"Invalid timestamp data\" : \\\n\t\t\t\t\t\"Returned timestamp message imprint doesn't match \"\n\t\t\t\t\t\"original message imprint\" ) );\n\t\t}\n\tCFI_CHECK_UPDATE( \"readTimestamp\" );\n\n\tREQUIRES( CFI_CHECK_SEQUENCE_3( \"readPkiDatagram\", \"readPkiStatusInfo\", \n\t\t\t\t\t\t\t\t\t\"readTimestamp\" ) );\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tServer-side Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Send an error response back to the client.  Since there are only a small\n   number of these, we write back a fixed blob rather than encoding each\n   one */\n\n#define respSize( data )\t( data[ 1 ] + 2 )\n\nstatic const BYTE respBadGeneric[] = {\n\t0x30, 0x05, \n\t\t  0x30, 0x03, \n\t\t\t    0x02, 0x01, 0x02\t\t/* Rejection, unspecified reason */\n\t};\nstatic const BYTE respBadData[] = {\n\t0x30, 0x09, \n\t\t  0x30, 0x07, \n\t\t\t    0x02, 0x01, 0x02, \n\t\t\t\t0x03, 0x02, 0x05, 0x20\t/* Rejection, badDataFormat */\n\t};\nstatic const BYTE respBadExtension[] = {\n\t0x30, 0x0B, \n\t\t  0x30, 0x09, \n\t\t\t\t0x02, 0x01, 0x02, \n\t\t\t\t0x03, 0x04, 0x07, 0x00, 0x00, 0x80\t/* Rejection, unacceptedExtension */\n\t};\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sendErrorResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  const BYTE *errorResponse, \n\t\t\t\t\t\t\t  IN_ERROR const int status )\n\t{\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( cryptStatusError( status ) );\n\n\t/* Since we're already in an error state there's not much that we can do\n\t   in terms of alerting the user if a further error occurs when writing \n\t   the error response, so we ignore any potential write errors that occur\n\t   at this point */\n\tREQUIRES( rangeCheck( respSize( errorResponse ), 1, \n\t\t\t\t\t\t  sessionInfoPtr->receiveBufSize ) );\n\tmemcpy( sessionInfoPtr->receiveBuffer, errorResponse,\n\t\t\trespSize( errorResponse ) );\n\tsessionInfoPtr->receiveBufEnd = respSize( errorResponse );\n\t( void ) writePkiDatagram( sessionInfoPtr, TSP_CONTENT_TYPE_RESP,\n\t\t\t\t\t\t\t   TSP_CONTENT_TYPE_RESP_LEN );\n\treturn( status );\n\t}\n\n/* Read a request from a TSP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int readClientRequest( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t  INOUT TSP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tSTREAM stream;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( TSP_PROTOCOL_INFO ) ) );\n\n\t/* Read the request data from the client.  This can be quite short, just \n\t   an OID and a hash, so we specify a minimum length shorter than\n\t   MIN_CRYPT_OBJECTSIZE */\n\tstatus = readPkiDatagram( sessionInfoPtr, 32 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( sendErrorResponse( sessionInfoPtr, respBadGeneric, \n\t\t\t\t\t\t\t\t   status ) );\n\t\t}\n\tsMemConnect( &stream, sessionInfoPtr->receiveBuffer,\n\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\tstatus = readTSPRequest( &stream, protocolInfo, \n\t\t\t\t\t\t\t sessionInfoPtr->ownerHandle, \n\t\t\t\t\t\t\t sessionInfoPtr->receiveBufEnd, \n\t\t\t\t\t\t\t SESSION_ERRINFO );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\treturn( sendErrorResponse( sessionInfoPtr, \\\n\t\t\t\t\t( status == CRYPT_ERROR_BADDATA || \\\n\t\t\t\t\t  status == CRYPT_ERROR_UNDERFLOW ) ? respBadData : \\\n\t\t\t\t\t( status == CRYPT_ERROR_INVALID ) ? respBadExtension : \\\n\t\t\t\t\trespBadGeneric, status ) );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\n/* Send a response to the TSP client */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int sendServerResponse( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t   INOUT TSP_PROTOCOL_INFO *protocolInfo )\n\t{\n\tMESSAGE_DATA msgData;\n\tSTREAM stream;\n\tBYTE tstBuffer[ 1024 ];\n\tBYTE serialNo[ 16 + 8 ];\n\tBYTE *bufPtr = sessionInfoPtr->receiveBuffer;\n\tconst time_t currentTime = getReliableTime( sessionInfoPtr->privateKey );\n\tint tstLength DUMMY_INIT, responseLength, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( protocolInfo, sizeof( TSP_PROTOCOL_INFO ) ) );\n\n\tENSURES( currentTime > MIN_TIME_VALUE );\n\t\t\t /* Already checked in checkAttributeFunction() */\n\n\t/* If we're fuzzing, there's nothing to send */\n\tFUZZ_SKIP();\n\n\t/* Create a timestamp token */\n\tsetMessageData( &msgData, serialNo, 16 );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemOpen( &stream, tstBuffer, 1024 );\n\twriteSequence( &stream, sizeofShortInteger( 1 ) + \\\n\t\t\tsizeofOID( OID_TSP_POLICY ) + protocolInfo->msgImprintSize + \\\n\t\t\tsizeofInteger( serialNo, 16 ) + sizeofGeneralizedTime() + \\\n\t\t\tprotocolInfo->nonceSize );\n\twriteShortInteger( &stream, 1, DEFAULT_TAG );\n\twriteOID( &stream, OID_TSP_POLICY );\n\tswrite( &stream, protocolInfo->msgImprint, protocolInfo->msgImprintSize );\n\twriteInteger( &stream, serialNo, 16, DEFAULT_TAG );\n\tstatus = writeGeneralizedTime( &stream, currentTime, DEFAULT_TAG );\n\tif( protocolInfo->nonceSize > 0 )\n\t\t{\n\t\tstatus = swrite( &stream, protocolInfo->nonce,\n\t\t\t\t\t\t protocolInfo->nonceSize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\ttstLength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( sendErrorResponse( sessionInfoPtr, respBadGeneric, \n\t\t\t\t\t\t\t\t   status ) );\n\t\t}\n\t\n\t/* Sign the token.   The reason for the min() part of the expression is \n\t   that signTSToken() gets suspicious of very large buffer sizes, for \n\t   example when the user has specified the use of a huge send buffer */\n\tstatus = signTSToken( sessionInfoPtr->receiveBuffer + 9,\n\t\t\t\t\t\t  min( sessionInfoPtr->receiveBufSize, \\\n\t\t\t\t\t\t\t   MAX_INTLENGTH_SHORT - 1 ), &responseLength, \n\t\t\t\t\t\t  protocolInfo->hashAlgo, tstBuffer, tstLength, \n\t\t\t\t\t\t  sessionInfoPtr->privateKey, \n\t\t\t\t\t\t  protocolInfo->includeSigCerts );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdelayRandom();\t/* Dither error timing info */\n\t\treturn( sendErrorResponse( sessionInfoPtr, respBadGeneric, status ) );\n\t\t}\n\tDEBUG_DUMP_FILE( \"tsa_token\", sessionInfoPtr->receiveBuffer + 9,\n\t\t\t\t\t responseLength );\n\n\t/* Add the TSA response wrapper and send it to the client.  This assumes\n\t   that the TSA response will be >= 256 bytes (for a 4-byte SEQUENCE\n\t   header encoding), which is always the case since it uses PKCS #7\n\t   signed data */\n\tREQUIRES( responseLength >= 256 && \\\n\t\t\t  responseLength < MAX_INTLENGTH_SHORT );\n\tsMemOpen( &stream, bufPtr, 4 + 5 );\t\t/* SEQ + resp.header */\n\twriteSequence( &stream, 5 + responseLength );\n\tswrite( &stream, \"\\x30\\x03\\x02\\x01\\x00\", 5 );\n\tsMemDisconnect( &stream );\n\tsessionInfoPtr->receiveBufEnd = 9 + responseLength;\n\tDEBUG_DUMP_FILE( \"tsa_resp\", sessionInfoPtr->receiveBuffer,\n\t\t\t\t\t sessionInfoPtr->receiveBufEnd );\n\treturn( writePkiDatagram( sessionInfoPtr, TSP_CONTENT_TYPE_RESP,\n\t\t\t\t\t\t\t  TSP_CONTENT_TYPE_RESP_LEN ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tInit/Shutdown Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Exchange data with a TSP client/server */\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int clientTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tTSP_PROTOCOL_INFO protocolInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionTSP( sessionInfoPtr ) );\n\n\t/* Make sure that we have all of the needed information */\n\tif( sessionInfoPtr->sessionTSP->imprintSize <= 0 )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_TSP_MSGIMPRINT,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ERROR_NOTINITED );\n\t\t}\n\n\t/* Get a timestamp from the server */\n\tmemset( &protocolInfo, 0, sizeof( TSP_PROTOCOL_INFO ) );\n\tstatus = sendClientRequest( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = readServerResponse( sessionInfoPtr, &protocolInfo );\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int serverTransact( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tTSP_PROTOCOL_INFO protocolInfo;\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\tREQUIRES( sanityCheckSessionTSP( sessionInfoPtr ) );\n\n\t/* Send a timestamp to the client */\n\tmemset( &protocolInfo, 0, sizeof( TSP_PROTOCOL_INFO ) );\n\tstatus = readClientRequest( sessionInfoPtr, &protocolInfo );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = sendServerResponse( sessionInfoPtr, &protocolInfo );\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tControl Information Management Functions\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t void *data, \n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCRYPT_ENVELOPE *cryptEnvelopePtr = ( CRYPT_ENVELOPE * ) data;\n\tMESSAGE_CREATEOBJECT_INFO createInfo;\n\tMESSAGE_DATA msgData;\n\tconst int dataSize = sessionInfoPtr->receiveBufEnd - \\\n\t\t\t\t\t\t sessionInfoPtr->receiveBufPos;\n\tconst int bufSize = max( dataSize + 128, MIN_BUFFER_SIZE );\n\tint status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isWritePtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_RESPONSE || \\\n\t\t\t  type == CRYPT_IATTRIBUTE_ENC_TIMESTAMP );\n\n\t/* Make sure that there's actually a timestamp present (this can happen \n\t   if we're using a persistent session and a subsequent transaction\n\t   fails, resulting in no timestamp being available) */\n\tif( sessionInfoPtr->receiveBufPos <= 0 )\n\t\treturn( CRYPT_ERROR_NOTFOUND );\n\n\t/* If we're being asked for raw encoded timestamp data, return it\n\t   directly to the caller */\n\tif( type == CRYPT_IATTRIBUTE_ENC_TIMESTAMP )\n\t\t{\n\t\tREQUIRES( boundsCheck( sessionInfoPtr->receiveBufPos, dataSize,\n\t\t\t\t\t\t\t   sessionInfoPtr->receiveBufEnd ) );\n\t\treturn( attributeCopy( ( MESSAGE_DATA * ) data,\n\t\t\t\t\tsessionInfoPtr->receiveBuffer + sessionInfoPtr->receiveBufPos,\n\t\t\t\t\tdataSize ) );\n\t\t}\n\n\t/* Delete any existing response if necessary */\n\tif( sessionInfoPtr->iCertResponse != CRYPT_ERROR )\n\t\t{\n\t\tkrnlSendNotifier( sessionInfoPtr->iCertResponse,\n\t\t\t\t\t\t  IMESSAGE_DECREFCOUNT );\n\t\tsessionInfoPtr->iCertResponse = CRYPT_ERROR;\n\t\t}\n\n\t/* We're being asked for interpreted data, create a cryptlib envelope to\n\t   contain it */\n\tsetMessageCreateObjectInfo( &createInfo, CRYPT_FORMAT_AUTO );\n\tstatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,\n\t\t\t\t\t\t\t  IMESSAGE_DEV_CREATEOBJECT, &createInfo,\n\t\t\t\t\t\t\t  OBJECT_TYPE_ENVELOPE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tkrnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,\n\t\t\t\t\t ( MESSAGE_CAST ) &bufSize, \n\t\t\t\t\t CRYPT_ATTRIBUTE_BUFFERSIZE );\n\n\t/* Push in the timestamp data */\n\tsetMessageData( &msgData, sessionInfoPtr->receiveBuffer + \\\n\t\t\t\t\t\t\t  sessionInfoPtr->receiveBufPos, dataSize );\n\tstatus = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_ENV_PUSHDATA,\n\t\t\t\t\t\t\t  &msgData, 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tsetMessageData( &msgData, NULL, 0 );\n\t\tstatus = krnlSendMessage( createInfo.cryptHandle,\n\t\t\t\t\t\t\t\t  IMESSAGE_ENV_PUSHDATA, &msgData, 0 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsessionInfoPtr->iCertResponse = createInfo.cryptHandle;\n\n\t/* Return the information to the caller */\n\tkrnlSendNotifier( sessionInfoPtr->iCertResponse, IMESSAGE_INCREFCOUNT );\n\t*cryptEnvelopePtr = sessionInfoPtr->iCertResponse;\n\treturn( status );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \\\nstatic int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t IN const void *data,\n\t\t\t\t\t\t\t\t IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tCRYPT_CONTEXT hashContext = *( ( CRYPT_CONTEXT * ) data );\n\tTSP_INFO *tspInfo = sessionInfoPtr->sessionTSP;\n\tint imprintAlgo, status;\t/* int vs.enum */\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( type == CRYPT_SESSINFO_TSP_MSGIMPRINT );\n\n\tif( tspInfo->imprintSize != 0 )\n\t\treturn( CRYPT_ERROR_INITED );\n\n\t/* Get the message imprint from the hash context */\n\tstatus = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,\n\t\t\t\t\t\t\t  &imprintAlgo, CRYPT_CTXINFO_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tMESSAGE_DATA msgData;\n\n\t\ttspInfo->imprintAlgo = imprintAlgo;\t/* int vs.enum */\n\t\tsetMessageData( &msgData, tspInfo->imprint, CRYPT_MAX_HASHSIZE );\n\t\tstatus = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_CTXINFO_HASHVALUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\ttspInfo->imprintSize = msgData.length;\n\t\t}\n\n\treturn( cryptStatusError( status ) ? CRYPT_ARGERROR_NUM1 : CRYPT_OK );\n\t}\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nstatic int checkAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,\n\t\t\t\t\t\t\t\t   IN const void *data,\n\t\t\t\t\t\t\t\t   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )\n\t{\n\tconst CRYPT_CONTEXT cryptContext = *( ( CRYPT_CONTEXT * ) data );\n\tint value, status;\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\tassert( isReadPtr( data, sizeof( int ) ) );\n\n\tREQUIRES( isEnumRange( type, CRYPT_ATTRIBUTE ) );\n\n\tif( type != CRYPT_SESSINFO_PRIVATEKEY )\n\t\treturn( CRYPT_OK );\n\n\t/* Make sure that the key is valid for timestamping */\n\tif( !checkContextCapability( cryptContext, MESSAGE_CHECK_PKC_SIGN ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_KEYUSAGE,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\tstatus = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, &value,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_EXTKEY_TIMESTAMPING );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_EXTKEY_TIMESTAMPING,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_ABSENT );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\t/* Make sure that the time appears correct (if the time is screwed up \n\t   then we can't really provide a signed indication of it to clients).  \n\t   The error information is somewhat misleading, but there's not much \n\t   else that we can provide at this point */\n\tif( getReliableTime( cryptContext ) <= MIN_TIME_VALUE )\n\t\t{\n\t\tsetErrorInfo( sessionInfoPtr, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t  CRYPT_ERRTYPE_ATTR_VALUE );\n\t\treturn( CRYPT_ARGERROR_NUM1 );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSession Access Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nCHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \\\nint setAccessMethodTSP( INOUT SESSION_INFO *sessionInfoPtr )\n\t{\n\tstatic const PROTOCOL_INFO protocolInfo = {\n\t\t/* General session information */\n\t\tTRUE,\t\t\t\t\t\t/* Request-response protocol */\n\t\tSESSION_FLAG_ISHTTPTRANSPORT, /* Flags */\n\t\t80,\t\t\t\t\t\t\t/* HTTP port */\n\t\t0,\t\t\t\t\t\t\t/* Client flags */\n\t\tSESSION_NEEDS_PRIVATEKEY |\t/* Server flags */\n\t\t\tSESSION_NEEDS_PRIVKEYSIGN | \\\n\t\t\tSESSION_NEEDS_PRIVKEYCERT,\n\t\t1, 1, 1,\t\t\t\t\t/* Version 1 */\n\t\tCRYPT_SUBPROTOCOL_NONE, CRYPT_SUBPROTOCOL_NONE,\n\t\t\t\t\t\t\t\t\t/* Allowed sub-protocols */\n\n\t\t/* Protocol-specific information */\n\t\tBUFFER_SIZE_DEFAULT\t\t\t/* Send/receive buffers */\n\t\t};\n\n\tassert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );\n\n\t/* Set the access method pointers */\n\tDATAPTR_SET( sessionInfoPtr->protocolInfo, ( void * ) &protocolInfo );\n\tif( isServer( sessionInfoPtr ) )\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, serverTransact );\n\t\t}\n\telse\n\t\t{\n\t\tFNPTR_SET( sessionInfoPtr->transactFunction, clientTransact );\n\t\t}\n\tFNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );\n\tFNPTR_SET( sessionInfoPtr->checkAttributeFunction, checkAttributeFunction );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* USE_TSP */\n"
  },
  {
    "path": "deps/cl345/session/websockets.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib WebSockets Header\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2015-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _WEBSOCKETS_DEFINED\n\n#define _WEBSOCKETS_DEFINED\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWebSockets Packet Types\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* WebSockets packet types */\n\n#define WS_PACKET_TEXT\t\t\t0x81\n#define WS_PACKET_BINARY\t\t0x82\n#define WS_PACKET_TEXT_PARTIAL\t0x01\n#define WS_PACKET_BINARY_PARTIAL 0x02\n#define WS_PACKET_CLOSE\t\t\t0x88\n#define WS_PACKET_PING\t\t\t0x89\n#define\tWS_PACKET_PONG\t\t\t0x8A\n\n/* A WebSockets Pong packet, sent in response to a received Ping packet */\n\n#define WS_PONG_DATA_CLIENT\t\t\"\\x8A\\x80\"\n#define WS_PONG_DATA_SERVER\t\t\"\\x8A\\x00\"\n#define WS_PONG_SIZE\t\t\t2\n\n/* A WebSockets Close packet, consisting of the standard Close packet and a\n   status code of WS_CLOSE_NORMAL sent as payload data.  Note that this \n   then needs to be masked if it's sent by the client */\n\n#define WS_CLOSE_DATA_CLIENT\t\"\\x88\\x82\\x03\\xE8\"\n#define WS_CLOSE_DATA_SERVER\t\"\\x88\\x02\\x03\\xE8\"\n#define WS_CLOSE_SIZE\t\t\t2\n#define WS_CLOSE_DATA_SIZE\t\t2\n\n/* WebSockets Close packet status codes.  God knows how some of these are \n   supposed to be used, for example the various Clayton's codes can't be set\n   but have defined meanings, and the policy code is a kind of catch-all \n   that's meant to be used if other codes like overflow error aren't \n   suitable, so it has nothing to do with actual policies but is more a \n   catch-all for when there's nothing else available */\n\n#define WS_CLOSE_NORMAL\t\t\t1000\t/* Normal close */\n#define WS_CLOSE_SHUTDOWN\t\t1001\t/* Client/server is closing down */\n#define WS_CLOSE_PROTOCOL_ERROR\t1002\t/* Protocol error */\n#define WS_CLOSE_UNACCEPTABLE_DATA 1003\t/* Unacceptable data, e.g.txt vs.bin */\n#define WS_CLOSE_RESERVED\t\t1004\t/* RFU */\n#define WS_CLOSE_CLAYTONS_NORMAL 1005\t/* Clayton's version of 1000 */\n#define WS_CLOSE_CLAYTONS_ERROR\t1006\t/* Claytons version of 1002 etc */\n#define WS_CLOSE_INVALID_DATA\t1007\t/* Invalid data, e.g. bin in txt packet */\n#define WS_CLOSE_POLICY\t\t\t1008\t/* Catch-all, see above */\n#define WS_CLOSE_OVERFLOW\t\t1009\t/* Message too large */\n#define WS_CLOSE_MISSING_EXTENSION 1010\t/* Client expected extension from server */\n#define WS_CLOSE_UNEXPECTED\t\t1011\t/* Server encountered unexpected condition */\n#define WS_CLOSE_CLAYTONS_TLS_ERROR\t1015 /* Clayton's TLS error */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tWebSockets Constants\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The payload length at which we need to move to an explicit length field \n   rather than having the length encoded as as length-code in the header, \n   and the magic values to indicate the size of the length field: 0x7E = \n   16-bit length follows, 0x7F = 64-bit length follows */\n\n#define WS_LENGTH_THRESHOLD\t\t0x7D\t/* 0 - 125 = encoded in header */\n\n#define WS_LENGTH_16BIT\t\t\t0x7E\t/* 16-bit length follows */\n#define WS_LENGTH_64BIT\t\t\t0x7F\t/* 64-bit length follows */\n\n#define WS_LENGTH_MASK\t\t\t0x7F\t/* Mask for length in length-code field */\n\n/* The flag indicating that data is masked, encoded as part of the length-\n   code field, and the size of the masking value that the client has to use \n   when sending data to the server */\n\n#define WS_MASK_FLAG\t\t\t0x80\t/* Flag for masking in length-code field */\n#define WS_MASK_SIZE\t\t\t4\t\t/* Size of masking value */\n\n/* WebSockets requires that client-to-server messages be masked, this \n   mechanism was added to deal with cache-poisoning attacks on proxies\n   via maliciously-structured payloads, a specific thing that seems to \n   have grabbed the RFC authors' attention at the time it was written.\n   In theory the masking value is supposed to be random and different for \n   each packet, however this only applies for plaintext messaging, when\n   running inside a TLS tunnel there's no need for masking (it could be\n   argued that there's no need for masking outside a TLS tunnel either, or\n   at least that the one very specific attack that's mitigated, if it's \n   even a concern, could be replaced with any number of other attacks that \n   aren't addressed).  To simplify the code we don't bother with the \n   overhead of using cryptographically strong sources of entropy but just\n   use a fixed value that satisfies the requirement for masking */\n\n#define WS_MASK_VALUE\t\t\t\"\\x6E\\x2A\\xF7\\xA4\"\n\n/* The position of various fields within the WebSockets header: the packet\n   type, the length code (containing either a 7-bit length or a length \n   extension indicator), the optional length field, and the optional mask \n   for client->server data masking assuming a default 16-bit explicit length\n   is present */\n\n#define WS_TYPE_OFFSET\t\t\t0\n#define WS_LENGTHCODE_OFFSET\t1\n#define WS_LENGTH_OFFSET\t\t( 1 + 1 )\n#define WS_MASK_OFFSET\t\t\t( 1 + 1 + UINT16_SIZE )\n\n/* WebSockets header lengths, the basic (minimal) size header with a single-\n   byte length and the typical size header with a UINT16 length.  Since the \n   client has to mask the payload, the client length differs from the server \n   length */\n\n#define WS_BASE_HEADER_LENGTH_CLIENT ( 1 + 1 + WS_MASK_SIZE )\n#define WS_BASE_HEADER_LENGTH_SERVER ( 1 + 1 )\n\n#define WS_HEADER_LENGTH_CLIENT\t( 1 + 1 + UINT16_SIZE + WS_MASK_SIZE )\n#define WS_HEADER_LENGTH_SERVER\t( 1 + 1 + UINT16_SIZE )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tWebSockets Handshake Constants\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The sizes of various data values used to perform the WebSockets \n   HTTP upgrade authentication/authorisation process */\n\n#define WS_KEY_SIZE\t\t\t\t16\t\t/* Key used to generate auth.response */\n#define WS_ENCODED_KEY_SIZE\t\t22\t\t/* base64-encoded key size */\n\n#define WS_KEY_GUID\t\t\t\t\"258EAFA5-E914-47DA-95CA-C5AB0DC85B11\"\n#define WS_KEY_GUID_SIZE\t\t36\n\n#define WS_ENCODED_AUTH_SIZE\t28\t\t/* base64-encoded auth.response size */\n\n#endif /* _WEBSOCKETS_DEFINED */\n"
  },
  {
    "path": "deps/cl345/test/certimp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Certificate Handling Test Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Handle various types of certificate-processing errors */\n\nstatic BOOLEAN handleCertImportError( const int errorCode, const int lineNo )\n\t{\n\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t \"code %d, line %d.\\n\", errorCode, lineNo );\n\treturn( FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Import Routines Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test certificate import code */\n\nstatic BOOLEAN handleCertError( const CRYPT_CERTIFICATE cryptCert, \n\t\t\t\t\t\t\t\tconst int certNo )\n\t{\n\tint errorLocus, status;\n\n\tfprintf( outputStream, \"\\n\" );\n\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_ERRORLOCUS, \n\t\t\t\t\t\t\t\t&errorLocus );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't get error locus for certificate check failure.\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we don't fail just because the certificate that we're \n\t   using as a test has expired */\n\tif( errorLocus == CRYPT_CERTINFO_VALIDTO )\n\t\t{\n\t\tfputs( \"Warning: Validity check failed because the certificate \"\n\t\t\t   \"has expired.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* RegTP CA certs are marked as non-CA certs, report the problem and \n\t   continue */\n\tif( certNo == 3 && errorLocus == CRYPT_CERTINFO_CA )\n\t\t{\n\t\tfputs( \"Warning: Validity check failed due to RegTP CA certificate \"\n\t\t\t   \"incorrectly\\n         marked as non-CA certificate.\\n\\n\",\n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Certificate #26 has an invalid keyUsage for the key it contains, it's\n\t   used in order to check for the ability to handle a non-hole BIT \n\t   STRING in a location where a hole encoding is normally used so we \n\t   don't care about this particular problem */\n\tif( certNo == 25 && errorLocus == CRYPT_CERTINFO_KEYUSAGE )\n\t\t{\n\t\tfputs( \"Warning: Validity check failed due to CA certificate with \"\n\t\t\t   \"incorrect\\n         key usage field (this will be ignored \"\n\t\t\t   \"since the certificate\\n         is used to test for other \"\n\t\t\t   \"error handling conditions).\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\nstatic int certImport( const int certNo, const BOOLEAN isECC, \n\t\t\t\t\t   const BOOLEAN isBase64 )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, value, status;\n\n\tfprintf( outputStream, \"Testing %scertificate #%d import...\\n\",\n\t\t\t isECC ? \"ECC \" : isBase64 ? \"base64 \" : \"\", certNo );\n\tfilenameFromTemplate( buffer, isECC ? ECC_CERT_FILE_TEMPLATE : \\\n\t\t\t\t\t\t\t\t  isBase64 ? BASE64CERT_FILE_TEMPLATE : \\\n\t\t\t\t\t\t\t\t\t\t\t CERT_FILE_TEMPLATE, certNo );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find certificate file for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\n\t/* Import the certificate */\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\n\tif( status == CRYPT_ERROR_NOSECURE && !( isECC || isBase64 ) && \\\n\t\t( certNo == 8 || certNo == 9 ) )\t/* 9 = 512-bit, 10 = P12 512-bit */\n\t\t{\n\t\t/* Some older certs use totally insecure 512-bit keys and can't be\n\t\t   processed unless we deliberately allow insecure keys.  \n\t\t   Unfortunately this also blocks out the certificate that's used to \n\t\t   check the ability to handle invalid PKCS #1 padding, since this \n\t\t   only uses a 512-bit key, but if necessary it can be tested by \n\t\t   lowering MIN_PKCSIZE when building cryptlib */\n\t\tfputs( \"Warning: Certificate import failed because the certificate \"\n\t\t\t   \"uses a very short\\n         (insecure) key.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_NOSECURE && isECC && \\\n\t\t( certNo == 1 || certNo == 2 || certNo == 3 || certNo == 4 ) )\n\t\t{\n\t\t/* Some ECC certs are now showing the same problem as conventional\n\t\t   encryption certs */\n\t\tfputs( \"Warning: ECC certificate import failed because the \"\n\t\t\t   \"certificate uses a short\\n         (insecure) key.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_BADDATA && !( isECC || isBase64 ) && \\\n\t\tcertNo == 3 )\t/* With RIPEMD-160 support */\n\t\t{\n\t\tfputs( \"Warning: Certificate import failed for RegTP/Deutsche \"\n\t\t\t   \"Telekom CA\\n         certificate with negative public-key \"\n\t\t\t   \"values.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_NOTAVAIL && !( isECC || isBase64 ) && \\\n\t\tcertNo == 3 )\t/* Without RIPEMD-160 support */\n\t\t{\n\t\t/* This certificate uses RIPEMD-160 as its hash algorithm */\n\t\tfputs( \"Warning: Certificate import failed because the certificate \"\n\t\t\t   \"uses an\\n         obsolete algorithm no longer supported in \"\n\t\t\t   \"this build of cryptlib.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_NOTAVAIL && !( isECC || isBase64 ) && \\\n\t\t( certNo == 20 || certNo == 33 ) )\n\t\t{\n\t\t/* These are ECDSA certificates, the algorithm isn't enabled by \n\t\t   default */\n\t\tfputs( \"Warning: Certificate import failed because the certificate \"\n\t\t\t   \"uses an\\n         algorithm that isn't enabled in this build \"\n\t\t\t   \"of cryptlib.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n#ifndef USE_RPKI\n\tif( status == CRYPT_ERROR_BADDATA && certNo == 28 )\n\t\t{\n\t\tfputs( \"Warning: Certificate import failed for RPKI certificate \"\n\t\t\t   \"with oversize\\n         attribute because RPKI support \"\n\t\t\t   \"isn't enabled in this build of\\n         cryptlib.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n#endif /* USE_RPKI */\n\tif( status == CRYPT_ERROR_BADDATA && !( isECC || isBase64 ) && \\\n\t\tcertNo == 30 )\n\t\t{\n\t\t/* This certificate has has the algoID in the signature altered to \n\t\t   make it invalid, since this isn't covered by the signature it\n\t\t   isn't detected by many implementations */\n\t\tfputs( \"Certificate import failed for certificate with manipulated \"\n\t\t\t   \"signature data.\\n\", outputStream );\n\t\tfputs( \"  (This is the correct result for this test).\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_BADDATA && isBase64 && \\\n\t\t( certNo == 3 || certNo == 4 ) )\n\t\t{\n\t\t/* These certificates claim to be in PEM format but have a single \n\t\t   continuous block of base64 data, one with and one without\n\t\t   the base64 termination characters */\n\t\tfputs( \"Certificate import failed for certificate with invalid PEM \"\n\t\t\t   \"encoding.\\n\", outputStream );\n\t\tfputs( \"  (This is the correct result for this test).\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() for certificate #%d \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", certNo, \n\t\t\t\t status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_SELFSIGNED,\n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Sanity check to make sure that the certificate internal state is\n\t\t   consistent - this should never happen */\n\t\tprintf( \"Couldn't get certificate self-signed status, status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( value )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate is self-signed, checking \"\n\t\t\t\t \"signature... \" );\n\t\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( !handleCertError( cryptCert, certNo ) )\n\t\t\t\t{\n\t\t\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", \n\t\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tfputs( \"signature verified.\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tfputs( \"Certificate is signed, signature key unknown.\\n\", \n\t\t\t   outputStream );\n\t\t}\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Perform a dummy generalised extension read to make sure that nothing\n\t   goes wrong for this */\n\tstatus = cryptGetCertExtension( cryptCert, \"1.2.3.4\", &value, NULL, 0, \n\t\t\t\t\t\t\t\t\t&count );\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tprintf( \"Read of dummy extension didn't fail with \"\n\t\t\t\t\"CRYPT_ERROR_NOTFOUND, status %d, line %d.\\n\", status, \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"Certificate import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n#if 0\t/* Test rig for NISCC certificate data */\n\nstatic void importTestData( void )\n\t{\n\tint i;\n\n\tfor( i = 1; i <= 110000; i++ )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert;\n\t\tFILE *filePtr;\n\t\tBYTE buffer[ BUFFER_SIZE ];\n\t\tint count, status;\n\n\t\tif( !( i % 100 ) )\n\t\t\tprintf( \"%06d\\r\", i );\n/*\t\tfilenameFromTemplate( buffer, \"/tmp/simple_client/%08d\", i ); */\n/*\t\tfilenameFromTemplate( buffer, \"/tmp/simple_server/%08d\", i ); */\n\t\tfilenameFromTemplate( buffer, \"/tmp/simple_rootca/%08d\", i );\n\t\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t\tbreak;\n\t\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\t\tfclose( filePtr );\n\t\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  &cryptCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\t}\n#endif /* 0 */\n\nint testCertImport( void )\n\t{\n\tint i;\n\n\tfor( i = 1; i <= 34; i++ )\n\t\t{\n\t\tif( !certImport( i, FALSE, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testCertImportECC( void )\n\t{\n\tint i;\n\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"ECC algorithm support appears to be disabled, skipping \"\n\t\t\t   \"processing of ECDSA\\ncertificates.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\tfor( i = 1; i <= 10; i++ )\n\t\t{\n\t\tif( !certImport( i, TRUE, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nstatic int certReqImport( const int certNo )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, complianceValue, status;\n\n\tfprintf( outputStream, \"Testing certificate request #%d import...\\n\", \n\t\t\t certNo );\n\tfilenameFromTemplate( buffer, CERTREQ_FILE_TEMPLATE, certNo );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find certificate file for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\n\t/* Import the certificate request and check that the signature is valid */\n\tif( certNo == 3 )\n\t\t{\n\t\t/* Some of the requests are broken and we have to set the compliance\n\t\t   level to oblivious to handle them */\n\t\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t\t&complianceValue );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n\t\t}\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( certNo == 3 )\n\t\t{\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   complianceValue );\n\t\t}\n#ifdef __UNIX__\n\tif( status == CRYPT_ERROR_NOTAVAIL || status == CRYPT_ERROR_BADDATA )\n\t\t{\n\t\tputs( \"The certificate request import failed, probably because \"\n\t\t\t  \"you're using an\\nolder version of unzip that corrupts \"\n\t\t\t  \"certain types of files when it\\nextracts them.  To fix this, \"\n\t\t\t  \"you need to re-extract test/*.der without\\nusing the -a \"\n\t\t\t  \"option to convert text files.\\n\\n\" );\n\t\treturn( TRUE );\t\t/* Skip this test and continue */\n\t\t}\n#endif /* __UNIX__ */\n\tif( status == CRYPT_ERROR_NOSECURE && certNo == 1 )\n\t\t{\n\t\tfputs( \"Warning: Certificate request import failed because the \"\n\t\t\t   \"request uses a very short\\n         (insecure) key.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\tif( certNo == 5 )\n\t\t{\n\t\tfputs( \"  (Skipping signature check because CRMF data is \"\n\t\t\t   \"unsigned).\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tfprintf( outputStream, \"Checking signature... \" );\n\t\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status, \n\t\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t\t}\n\t\tfputs( \"signature verified.\\n\", outputStream );\n\t\t}\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"Certificate request import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testCertReqImport( void )\n\t{\n\tint i;\n\n\tfor( i = 1; i <= 7; i++ )\n\t\t{\n\t\tif( !certReqImport( i ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\n#define LARGE_CRL_SIZE\t45000\t/* Large CRL is too big for std.buffer */\n\nstatic int crlImport( const int crlNo, BYTE *buffer )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tFILE *filePtr;\n\tint count, status;\n\n\tfilenameFromTemplate( buffer, CRL_FILE_TEMPLATE, crlNo );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tprintf( \"Couldn't find CRL file for CRL #%d import test.\\n\", crlNo );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, LARGE_CRL_SIZE, filePtr );\n\tfclose( filePtr );\n\tfprintf( outputStream, \"CRL #%d has size %d bytes.\\n\", crlNo, count );\n\n\t/* Import the CRL.  Since CRL's don't include the signing certificate, \n\t   we can't (easily) check the signature on it */\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\n\t/* Print information on what we've got and clean up */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptCert );\n\n\treturn( TRUE );\n\t}\n\nint testCRLImport( void )\n\t{\n\tBYTE *bufPtr;\n\tint i;\n\n\tfputs( \"Testing CRL import...\\n\", outputStream );\n\n\t/* Since we're working with an unusually large certificate object we \n\t   have to dynamically allocate the buffer for it */\n\tif( ( bufPtr = malloc( LARGE_CRL_SIZE ) ) == NULL )\n\t\t{\n\t\tputs( \"Out of memory.\" );\n\t\treturn( FALSE );\n\t\t}\n\tfor( i = 1; i <= 4; i++ )\n\t\t{\n\t\tif( !crlImport( i, bufPtr ) )\n\t\t\t{\n\t\t\tfree( bufPtr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tfree( bufPtr );\n\tfputs( \"CRL import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic BOOLEAN isSingleCert( const CRYPT_CERTIFICATE cryptCertChain )\n\t{\n\tint value, status;\n\n\t/* Check whether a certificate chain contains a single non-self-signed \n\t   certificate, which means that we can't perform a signature check on \n\t   it */\n\tstatus = cryptGetAttribute( cryptCertChain, CRYPT_CERTINFO_SELFSIGNED, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\t/* It's a self-signed certificate, we should be able to check this \n\t\t   chain */\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( cryptCertChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\tif( cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t   CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t   CRYPT_CURSOR_NEXT ) == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* There's only a single certificate in the chain and it's not self-\n\t\t   signed, we can't check it */\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\nstatic int checkExpiredCertChain( const CRYPT_CERTIFICATE cryptCertChain )\n\t{\n\tint complianceValue, status;\n\n\tfprintf( outputStream, \"Warning: The certificate chain didn't verify \"\n\t\t\t \"because one or more\\n         certificates in it have \"\n\t\t\t \"expired.  Trying again in oblivious\\n         mode... \" );\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t&complianceValue );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   complianceValue );\n\n\treturn( status );\n\t}\n\nstatic BOOLEAN handleCertChainError( const CRYPT_CERTIFICATE cryptCertChain, \n\t\t\t\t\t\t\t\t\t const int certNo, const int errorCode )\n\t{\n\tint trustValue = CRYPT_UNUSED, errorLocus, status;\n\n\t/* If the chain contains a single non-CA certificate, we'll get a \n\t   parameter error since we haven't supplied a signing certificate */\n\tif( errorCode == CRYPT_ERROR_PARAM2 && isSingleCert( cryptCertChain ) )\n\t\t{\n\t\t/* There's only a single certificate present, we can't do much with \n\t\t   it */\n\t\tfputs( \"\\nCertificate chain contains only a single standalone \"\n\t\t\t   \"certificate, skipping\\nsignature check...\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If it's not a problem with validity, we can't go any further */\n\tif( errorCode != CRYPT_ERROR_INVALID )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptCheckCert()\", \n\t\t\t\t\t\t\t   errorCode, __LINE__ ) );\n\t\t}\n\n\t/* Check the nature of the problem */\n\tstatus = cryptGetAttribute( cryptCertChain, CRYPT_ATTRIBUTE_ERRORLOCUS,\n\t\t\t\t\t\t\t\t&errorLocus );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't get error locus for certificate check failure.\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Try to work around the error */\n\tstatus = errorCode;\n\tif( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT || \\\n\t\terrorLocus == CRYPT_CERTINFO_TRUSTED_USAGE )\n\t\t{\n\t\t/* The error occured because of a problem with the root certificate, \n\t\t   try again with an implicitly-trusted root */\n\t\tif( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nWarning: The certificate chain didn't \"\n\t\t\t\t\t \"verify because it didn't end in a\\n         trusted \"\n\t\t\t\t\t \"root certificate.  Checking again using an \"\n\t\t\t\t\t \"implicitly\\n         trusted root... \" );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nWarning: The certificate chain didn't \"\n\t\t\t\t\t \"verify because the root certificate's\\n         key \"\n\t\t\t\t\t \"isn't enabled for this usage.  Checking again using \"\n\t\t\t\t\t \"an\\n         implicitly trusted root... \" );\n\t\t\t}\n\t\tif( cryptStatusError( \\\n\t\t\t\tsetRootTrust( cryptCertChain, &trustValue, 1 ) ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nAttempt to make chain root implicitly \"\n\t\t\t\t\t \"trusted failed, status = %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\t\tif( status == CRYPT_ERROR_INVALID )\n\t\t\t{\n\t\t\t( void ) cryptGetAttribute( cryptCertChain,\t\n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORLOCUS,\n\t\t\t\t\t\t\t\t\t\t&errorLocus );\n\t\t\t}\n\t\t}\n\tif( errorLocus == CRYPT_CERTINFO_VALIDTO )\n\t\t{\n\t\t/* One (or more) certs in the chain have expired, try again with the \n\t\t   compliance level wound down to nothing */\n\t\tfputc( '\\n', outputStream );\n\t\tstatus = checkExpiredCertChain( cryptCertChain );\n\t\tif( status == CRYPT_ERROR_PARAM2 && isSingleCert( cryptCertChain ) )\n\t\t\t{\n\t\t\t/* There's only a single certificate present, we can't do much \n\t\t\t   with it */\n\t\t\tfputs( \"\\nCertificate chain contains only a single standalone \"\n\t\t\t\t   \"certificate, skipping\\nsignature check...\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\tif( errorLocus == CRYPT_CERTINFO_CERTIFICATE )\n\t\t{\n\t\tfputs( \"\\nCertificate chain is incomplete (one or more certificates \"\n\t\t\t   \"needed to\\ncomplete the chain are missing), skipping \"\n\t\t\t   \"signature check...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If we changed settings, restore their original values */\n\tif( trustValue != CRYPT_UNUSED )\n\t\tsetRootTrust( cryptCertChain, NULL, trustValue );\n\n\t/* If we've got a long-enough chain, try again with the next-to-last \n\t   certificate marked as trusted */\n\tif( cryptStatusOK( status ) && certNo == 4 )\n\t\t{\n\t\tfputs( \"signatures verified.\\n\", outputStream );\n\t\tfputs( \"Checking again with an intermediate certificate marked as \"\n\t\t\t   \"trusted...\\n\", outputStream );\n\t\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_LAST );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_PREVIOUS );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT, 1 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\t\tif( status == CRYPT_ERROR_INVALID )\n\t\t\t{\n\t\t\t( void ) cryptGetAttribute( cryptCertChain, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORLOCUS,\n\t\t\t\t\t\t\t\t\t\t&errorLocus );\n\t\t\tif( errorLocus == CRYPT_CERTINFO_VALIDTO )\n\t\t\t\t{\n\t\t\t\t/* One (or more) certs in the chain have expired, try again \n\t\t\t\t   with the compliance level wound down to nothing */\n\t\t\t\tstatus = checkExpiredCertChain( cryptCertChain );\n\t\t\t\t}\n\t\t\t}\n\t\tif( trustValue != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tcryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_TRUSTED_IMPLICIT, \n\t\t\t\t\t\t\t   trustValue );\n\t\t\t}\n\t\t}\n\n\t/* If the lowered-limits check still didn't work, it's an error */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputc( '\\n', outputStream );\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptCheckCert()\", status, \n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\tfputs( \"signatures verified.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic int certChainImport( const int certNo, const BOOLEAN isBase64 )\n\t{\n\tCRYPT_CERTIFICATE cryptCertChain;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, value, status;\n\n\tfprintf( outputStream, \"Testing %scert chain #%d import...\\n\",\n\t\t\t isBase64 ? \"base64 \" : \"\", certNo );\n\tfilenameFromTemplate( buffer, isBase64 ? BASE64CERTCHAIN_FILE_TEMPLATE : \\\n\t\t\t\t\t\t\t\t\t\t\t CERTCHAIN_FILE_TEMPLATE, certNo );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find certificate chain file for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tif( count == BUFFER_SIZE )\n\t\t{\n\t\tputs( \"The certificate buffer size is too small for the certificate \"\n\t\t\t  \"chain.  To fix\\nthis, increase the BUFFER_SIZE value in \"\n\t\t\t  \"test/testcert.c and recompile the code.\\n\\n\" );\n\t\treturn( TRUE );\t\t/* Skip this test and continue */\n\t\t}\n\tfprintf( outputStream, \"Certificate chain has size %d bytes.\\n\", count );\n\n\t/* This certificate chain has an exponent of 3, which throws a debug \n\t   exception in debug builds */\n\tif( checkLibraryIsDebug() && certNo == 2 )\n\t\t{\n\t\tfprintf( outputStream, \"Import of certificate with invalid e=3 \"\n\t\t\t\t \"skipped for debug build, line %d.\\n\", __LINE__ );\n\t\tfputs( \"  (This is the correct result for this test).\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Import the certificate chain.  This assumes that the default certs are\n\t   installed as trusted certs, which is required for cryptCheckCert() */\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCertChain );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we failed on the RSA e=3 certificate, this is a valid result */\n\t\tif( certNo == 2 && status == CRYPT_ERROR_BADDATA )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Import of certificate with invalid e=3 \"\n\t\t\t\t\t \"key failed, line %d.\\n\", __LINE__ );\n\t\t\tfputs( \"  (This is the correct result for this test).\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\t\t}\n\tif( certNo == 2 )\n\t\t{\n\t\tprintf( \"Import of certificate with invalid e=3 key succeeded when \"\n\t\t\t\t\"it should have\\n  failed, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttribute( cryptCertChain, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptGetAttribute()\", \n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\tif( certNo == 1 || certNo == 6 )\n\t\t{\n\t\t/* The first chain has length 1 so it should be imported as a \n\t\t   standard certificate */\n\t\tif( value != CRYPT_CERTTYPE_CERTIFICATE )\n\t\t\t{\n\t\t\tprintf( \"Imported object isn't a certificate, line %d.\\n\", \n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( value != CRYPT_CERTTYPE_CERTCHAIN )\n\t\t\t{\n\t\t\tprintf( \"Imported object isn't a certificate chain, line %d.\\n\", \n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tfprintf( outputStream, \"Checking signatures... \" );\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( !handleCertChainError( cryptCertChain, certNo, status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\tfputs( \"signatures verified.\\n\", outputStream );\n\n\t/* Display info on each certificate in the chain */\n\tif( !printCertChainInfo( cryptCertChain ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCertChain );\n\tfputs( \"Certificate chain import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testCertChainImport( void )\n\t{\n\tint i;\n\n\tfor( i = 1; i <= 6; i++ )\n\t\t{\n\t\tif( !certChainImport( i, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testOCSPImport( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptResponderCert;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, status;\n\n\tif( ( filePtr = fopen( convertFileName( OCSP_OK_FILE ), \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find OCSP OK response file for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Testing OCSP OK response import...\\n\", outputStream );\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tfprintf( outputStream, \"OCSP OK response has size %d bytes.\\n\", count );\n\n\t/* Import the OCSP OK response.  Because of the choose-your-own-trust-\n\t   model status of the OCSP RFC we have to supply our own signature\n\t   check certificate to verify the response */\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\tfprintf( outputStream, \"Checking signature... \" );\n\tstatus = importCertFile( &cryptResponderCert, OCSP_CA_FILE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCheckCert( cryptCert, cryptResponderCert );\n\t\tcryptDestroyCert( cryptResponderCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfputs( \"signatures verified.\\n\", outputStream );\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptCert );\n\n\t/* Now import the OCSP revoked response.  This has a different CA \n\t   certificate than the OK response, to keep things simple we don't \n\t   bother with a sig check for this one */\n\tfputs( \"Testing OCSP revoked response import...\\n\", outputStream );\n\tif( ( filePtr = fopen( convertFileName( OCSP_REV_FILE ), \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find OCSP revoked response file for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tfprintf( outputStream, \"OCSP revoked response has size %d bytes.\\n\", \n\t\t\t count );\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"OCSP import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testBase64CertImport( void )\n\t{\n\tint i;\n\n\t/* If this is an EBCDIC system, we can't (easily) import the base64-\n\t   encoded certificate without complex calisthenics to handle the \n\t   different character sets */\n#if 'A' == 0xC1\n\tputs( \"Skipping import of base64-encoded data on EBCDIC system.\\n\\n\" );\n\treturn( TRUE );\n#endif /* EBCDIC system */\n\n\tfor( i = 1; i <= 4; i++ )\n\t\t{\n\t\tif( !certImport( i, FALSE, TRUE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testBase64CertChainImport( void )\n\t{\n\tint i;\n\n\t/* If this is an EBCDIC system, we can't (easily) import the base64-\n\t   encoded certificate without complex calisthenics to handle the \n\t   different character sets */\n#if 'A' == 0xC1\n\tputs( \"Skipping import of base64-encoded data on EBCDIC system.\\n\\n\" );\n\treturn( TRUE );\n#endif /* EBCDIC system */\n\n\tfor( i = 1; i <= 1; i++ )\n\t\t{\n\t\tif( !certChainImport( i, TRUE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nstatic int miscImport( const char *fileName, const char *description )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, status;\n\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\t{\n\t\tprintf( \"Couldn't find file for %s key import test.\\n\",\n\t\t\t\tdescription );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\n\t/* Import the object.  Since this isn't a certificate we can't do much\n\t   more with it than this - this is only used to test the low-level\n\t   code and needs to be run inside a debugger, since the call always\n\t   fails (the data being imported isn't a certificate) */\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( status != CRYPT_ERROR_BADDATA && status != CRYPT_ERROR_UNDERFLOW )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() for %s key failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", description, status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\treturn( TRUE );\n\t}\n\nint testMiscImport( void )\n\t{\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint i;\n\n\tfputs( \"Testing base64-encoded SSH/PGP key import...\\n\", outputStream );\n\tfor( i = 1; i <= 4; i++ )\n\t\t{\n\t\tfilenameFromTemplate( buffer, SSHKEY_FILE_TEMPLATE, i );\n\t\tif( !miscImport( buffer, \"SSH\" ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tfor( i = 1; i <= 3; i++ )\n\t\t{\n\t\tfilenameFromTemplate( buffer, PGPASCKEY_FILE_TEMPLATE, i );\n\t\tif( !miscImport( buffer, \"PGP\" ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test handling of certs that chain by DN but not by keyID */\n\nint testNonchainCert( void )\n\t{\n\t/* The EE certificate expired in November 2007 so unfortunately we can't \n\t   perform this test any more until we can obtain further broken\n\t   certs from DigiCert */\n#if 0\n\tCRYPT_CERTIFICATE cryptLeafCert, cryptCACert;\n\tint value, status;\n\n\tfputs( \"Testing handling of incorrectly chained certs...\\n\", \n\t\t   outputStream );\n\n\t/* Since this test requires the use of attributes that aren't decoded at\n\t   the default compliance level, we have to raise it a notch to make sure\n\t   that we get the certificate attributes necessary to sort out the \n\t   mess */\n\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   &value );\n\tif( value < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )\n\t\t{\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL );\n\t\t}\n\n\t/* Get the EE and incorrectly chained CA certs */\n\tstatus = importCertFile( &cryptLeafCert, NOCHAIN_EE_FILE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = importCertFile( &cryptCACert, NOCHAIN_CA_FILE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   value );\n\n\t/* Check the EE certificate using the apparently-correct but actually \n\t   incorrect CA certificate and make sure that we get the correct error \n\t   message */\n\tstatus = cryptCheckCert( cryptLeafCert, cryptCACert );\n\tif( status != CRYPT_ERROR_SIGNATURE )\n\t\t{\n\t\tprintf( \"Sig.check of incorrectly chained certificate returned %d, \"\n\t\t\t\t\"should have been %d, line %d.\\n\", status, \n\t\t\t\tCRYPT_ERROR_SIGNATURE, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptLeafCert );\n\tcryptDestroyCert( cryptCACert );\n\n\tfputs( \"Handling of incorrectly chained certs succeeded.\\n\\n\", \n\t\t   outputStream );\n#endif /* 0 */\n\treturn( TRUE );\n\t}\n\n/* Test certificate handling at various levels of compliance */\n\nint testCertComplianceLevel( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptCaCert DUMMY_INIT;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, value, status;\n\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL, &value );\n\n\t/* Test import of a broken certificate.  The brokenness is an invalid \n\t   authorityKeyIdentifier which is processed at level\n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL and above, so first we try it in \n\t   CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL mode, which should fail, and then\n\t   again in oblivious mode, which should succeed */\n\tfprintf( outputStream, \"Testing certificate handling at various \"\n\t\t\t \"compliance levels (current = %d)...\\n\", value );\n\tif( ( filePtr = fopen( convertFileName( BROKEN_CERT_FILE ), \\\n\t\t\t\t\t\t   \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't certificate for import test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tif( value < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )\n\t\t{\n\t\tstatus = cryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_PKIX_PARTIAL );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\t{\n\t\t\tputs( \"(Couldn't set compliance level to \"\n\t\t\t\t  \"CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL, probably\\n because \"\n\t\t\t\t  \"cryptlib has been configured to not use this level, \"\n\t\t\t\t  \"skipping this\\n test...)\" );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  &cryptCert );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* Import in CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL mode should \n\t\t\t   fail */\n\t\t\tcryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t   CRYPT_OPTION_CERT_COMPLIANCELEVEL, value );\n\t\t\tprintf( \"cryptImportCert() of broken certificate succeeded when \"\n\t\t\t\t\t\"it should have failed, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_STANDARD );\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Import in standard mode should succeed */\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\t\t}\n\n\t/* Print information on what we've got.  This should only print info for\n\t   the two basic extensions that are handled in oblivious mode  */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptCert );\n\n\t/* Test checking of an expired certificate using a broken CA certificate \n\t   in oblivious mode (this checks chaining and the signature, but little \n\t   else) */\n\tstatus = importCertFile( &cryptCert, BROKEN_USER_CERT_FILE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = importCertFile( &cryptCaCert, BROKEN_CA_CERT_FILE );\n\tif( cryptStatusError( status ) )\n\t\treturn( handleCertImportError( status, __LINE__ ) );\n\tstatus = cryptCheckCert( cryptCert, cryptCaCert );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Checking in normal mode should fail */\n\t\tfprintf( outputStream, \"cryptCheckCert() of broken certificate \"\n\t\t\t\t \"succeeded when it should have failed, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n\tstatus = cryptCheckCert( cryptCert, cryptCaCert );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Checking in oblivious mode should succeed */\n\t\tfprintf( outputStream, \"cryptCheckCert() of broken certificate \"\n\t\t\t\t \"failed when it should have succeeded, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCaCert );\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfputs( \"Certificate handling at different compliance levels \"\n\t\t   \"succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test handling of chain verification with various combinations of trusted \n   and untrusted certificates and chains */\n\nstatic int checkChain( const CHAINTEST_CERT_TYPE leftCertType, \n\t\t\t\t\t   const BOOLEAN leftCertTrusted,\n\t\t\t\t\t   const CHAINTEST_CERT_TYPE rightCertType, \n\t\t\t\t\t   const BOOLEAN rightCertTrusted,\n\t\t\t\t\t   const BOOLEAN statusOK )\n\t{\n\tCRYPT_CERTIFICATE leftCert, rightCert = CRYPT_UNUSED;\n\tstatic const char *certNames[] = \\\n\t\t{ \"no certificate\", \"leaf certificate\", \"issuer certificate\",\n\t\t  \"root certificate\", \"certificate chain\", \n\t\t  \"certificate chain (no root)\", \"certificate chain (no leaf)\", \n\t\t  \"error\", \"error\" \n\t\t};\n\tint status;\n\n\tfprintf( outputStream, \"Verifying %s%s using %s%s...\\n\", \n\t\t\t leftCertTrusted ? \"trusted \" : \"\",\n\t\t\t certNames[ leftCertType ], rightCertTrusted ? \"trusted \" : \"\",\n\t\t\t certNames[ rightCertType ] );\n\n\t/* Import the test certificates/chains */\n\tstatus = importCertFromTemplate( &leftCert, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t leftCertType );\n\tif( cryptStatusOK( status ) && rightCertType != CHAINTEST_NOCERT )\n\t\t{\n\t\tstatus = importCertFromTemplate( &rightCert, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t\t rightCertType );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate import for certificate chain \"\n\t\t\t\t \"test failed, status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Apply any necessary trust settings */\n\tif( leftCertTrusted )\n\t\t{\n\t\tif( leftCertType == CHAINTEST_CHAIN || \\\n\t\t\tleftCertType == CHAINTEST_CHAIN_NOROOT || \\\n\t\t\tleftCertType == CHAINTEST_CHAIN_NOLEAF )\n\t\t\t{\n\t\t\t/* If it's a chain then we have to make sure we set the trust on\n\t\t\t   the top-level certificate in it */\n\t\t\tcryptSetAttribute( leftCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_LAST );\n\t\t\t}\n\t\tstatus = setRootTrust( leftCert, NULL, 1 );\n\t\t}\n\tif( cryptStatusOK( status ) && rightCertTrusted )\n\t\t{\n\t\tif( rightCertType == CHAINTEST_CHAIN || \\\n\t\t\trightCertType == CHAINTEST_CHAIN_NOROOT || \\\n\t\t\trightCertType == CHAINTEST_CHAIN_NOLEAF )\n\t\t\t{\n\t\t\t/* If it's a chain then we have to make sure we set the trust on\n\t\t\t   the top-level certificate in it */\n\t\t\tcryptSetAttribute( rightCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_LAST );\n\t\t\t}\n\t\tstatus = setRootTrust( rightCert, NULL, 1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't make certificate/certificate chain \"\n\t\t\t\t \"trusted, status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check the left item with the right one */\n\tstatus = cryptCheckCert( leftCert, rightCert );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( !statusOK )\n\t\t\t{\n\t\t\tprintf( \"Check succeeded, should have failed, line %d.\\n\", \n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( statusOK )\n\t\t\t{\n\t\t\tprintErrorAttributeInfo( leftCert );\n\t\t\tfprintf( outputStream, \"Check failed, should have succeeded, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tif( leftCertTrusted )\n\t\tcryptSetAttribute( leftCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, 0 );\n\tif( rightCertType != CHAINTEST_NOCERT && rightCertTrusted )\n\t\tcryptSetAttribute( rightCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, 0 );\n\tcryptDestroyCert( leftCert );\n\tif( rightCertType != CHAINTEST_NOCERT )\n\t\tcryptDestroyCert( rightCert );\n\tfprintf( outputStream, \"Certificate chain check succeeded.\\n\\n\" );\n\n\treturn( TRUE );\n\t}\n\nint testCertChainHandling( void )\n\t{\n\t/* The certificate chain types, from test/test.h:\n\n\t\tCHAINTEST_NOCERT\t\tNo certificate\n\t\tCHAINTEST_LEAF\t\t\tLeaf certificate\n\t\tCHAINTEST_ISSUER\t\tIssuer of leaf (= intermed.CA)\n\t\tCHAINTEST_ROOT\t\t\tRoot certificate\n\t\tCHAINTEST_CHAIN\t\t\tFull certificate chain\n\t\tCHAINTEST_CHAIN_NOROOT\tChain without root certificate\n\t\tCHAINTEST_CHAIN_NOLEAF\tChain without leaf certificate \n\t\n\t   The parameters for checkChain() are:\n\n\t\tleftCert, leftCertTrusted, rightCert, rightCertTrusted, check result */\n\n\t/* Leaf + issuer: \n\t\tIssuer implicitly trusted = OK\n\t\tIssuer explicitly trusted so check is done via trust database = OK */\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_ISSUER, FALSE, TRUE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_ISSUER, TRUE, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Standalone chain + CRYPT_UNUSED:\n\t\tRoot untrusted = !OK\n\t\tRoot trusted = OK */\n\tif( !checkChain( CHAINTEST_CHAIN, FALSE, CHAINTEST_NOCERT, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_CHAIN, TRUE, CHAINTEST_NOCERT, FALSE, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Chain + root:\n\t\tRoot untrusted = !OK\n\t\tRoot trusted = OK */\n\tif( !checkChain( CHAINTEST_CHAIN, FALSE, CHAINTEST_ROOT, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_CHAIN, FALSE, CHAINTEST_ROOT, TRUE, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Leaf + chain:\n\t\tChain untrusted = !OK since LHS and RHS can't overlap\n\t\tChain trusted = !OK since LHS and RHS can't overlap */\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_CHAIN, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_CHAIN, TRUE, FALSE ) )\n\t\treturn( FALSE );\n\n\t/* Leaf + chain without leaf:\n\t\tChain w/o leaf untrusted = !OK \n\t\tChain w/o leaf trusted = OK */\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_CHAIN_NOLEAF, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_LEAF, FALSE, CHAINTEST_CHAIN_NOLEAF, TRUE, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Chain without root + root:\n\t\tRoot untrusted = !OK\n\t\tRoot trusted = OK */\n\tif( !checkChain( CHAINTEST_CHAIN_NOROOT, FALSE, CHAINTEST_ROOT, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_CHAIN_NOROOT, FALSE, CHAINTEST_ROOT, TRUE, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Chain without root + chain without leaf:\n\t\tChain w/o leaf untrusted = !OK since LHS and RHS can't overlap\n\t\tChain w/o leaf trusted = !OK since LHS and RHS can't overlap */\n\tif( !checkChain( CHAINTEST_CHAIN_NOROOT, FALSE, CHAINTEST_CHAIN_NOLEAF, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !checkChain( CHAINTEST_CHAIN_NOROOT, FALSE, CHAINTEST_CHAIN_NOLEAF, TRUE, FALSE ) )\n\t\treturn( FALSE );\n\t\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tNIST Path-processing Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test path processing using the NIST PKI test suite.  This doesn't run all\n   of the tests since some are somewhat redundant (e.g. path length \n   constraints ending at certificate n in a chain vs.cert n+1 in a chain \n   where both are well short of the constraint length) or require complex\n   additional processing (e.g. CRL fetches) which it's difficult to\n   automate */\n\ntypedef struct {\n\tconst int fileMajor, fileMinor;\t/* Major and minor number of file */\n\tconst BOOLEAN isValid;\t\t\t/* Whether path is valid */\n\tconst BOOLEAN policyOptional;\t/* Whether explicit policy optional */\n\t} PATH_TEST_INFO;\n\nstatic const PATH_TEST_INFO pathTestInfo[] = {\n\t/* Signature verification */\n\t/*   0 */ { 1, 1, TRUE },\n\t/*   1 */ { 1, 2, FALSE },\n\t/*   2 */ { 1, 3, FALSE },\n\t/*   3 */ { 1, 4, TRUE },\n\t/*   4 */ { 1, 6, FALSE },\n\n\t/* Validity periods */\n\t/*   5 */ { 2, 1, FALSE },\n\t/*   6 */ { 2, 2, FALSE },\n\t/* The second certificate in test 4.2.3 has a validFrom date of 1950 \n\t   which cryptlib rejects on import as being not even remotely valid (it \n\t   can't even be represented in the ANSI/ISO C date format).  Supposedly \n\t   half-century-old certs are symptomatic of severely broken software so\n\t   rejecting this certificate is justified */\n/*\t**  X ** { 2, 3, TRUE }, */\n\t/*   7 */ { 2, 4, TRUE },\n\t/*   8 */ { 2, 5, FALSE },\n\t/*   9 */ { 2, 6, FALSE },\n\t/*  10 */ { 2, 7, FALSE },\n\t/*  11 */ { 2, 8, TRUE },\n\n\t/* Name chaining */\n\t/*  12 */ { 3, 1, FALSE },\n\t/*  13 */ { 3, 2, FALSE },\n\t/*  14 */ { 3, 6, TRUE },\n\t/*  15 */ { 3, 7, TRUE },\n\t/*  16 */ { 3, 8, TRUE },\n\t/*  17 */ { 3, 9, TRUE },\n\n\t/* 4 = CRLs */\n\n\t/* oldWithNew / newWithOld */\n\t/*  18 */ { 5, 1, TRUE },\n\t/*  19 */ { 5, 3, TRUE },\n\n\t/* Basic constraints */\n\t/*  20 */ { 6, 1, FALSE },\n\t/*  21 */ { 6, 2, FALSE },\n\t/*  22 */ { 6, 3, FALSE },\n\t/*  23 */ { 6, 4, TRUE },\n\t/*  24 */ { 6, 5, FALSE },\n\t/*  25 */ { 6, 6, FALSE },\n\t/*  26 */ { 6, 7, TRUE },\n\t/* The second-to-last certificate in the path sets a pathLenConstraint of \n\t   zero with the next certificate being a CA certificate (there's no EE \n\t   certificate present).  cryptlib treats this as invalid since it can \n\t   never lead to a valid path once the EE certificate is added */\n\t/*  27 */ { 6, 8, FALSE /* TRUE */ },\n\t/*  28 */ { 6, 9, FALSE },\n\t/*  29 */ { 6, 10, FALSE },\n\n\t/*  30 */ { 6, 11, FALSE },\n\t/*  31 */ { 6, 12, FALSE },\n\t/*  32 */ { 6, 13, TRUE },\n\t/* This has the same problem as 4.6.8 */\n\t/*  33 */ { 6, 14, FALSE /* TRUE */ },\n\t/* The following are 4.5.x-style oldWithNew / newWithOld but with path\n\t   constraints */\n\t/*  34 */ { 6, 15, TRUE },\n\t/*  35 */ { 6, 16, FALSE },\n\t/*  36 */ { 6, 17, TRUE },\n\n\t/* Key usage */\n\t/*  37 */ { 7, 1, FALSE },\n\t/*  38 */ { 7, 2, FALSE },\n\t/*  39 */ { 7, 3, TRUE },\n\n\t/* Policies */\n\t/*  40 */ { 8, 1, TRUE },\n\t/*  41 */ { 8, 2, TRUE },\n\t/* The first certificate asserts a policy that differs from that of all \n\t   other certificates in the path.  If no explicit policy is required \n\t   (by setting CRYPT_OPTION_REQUIREPOLICY to FALSE) it will verify, \n\t   otherwise it won't */\n\t/*  42 */ { 8, 3, TRUE, TRUE },\t/* Policy optional */\n\t/*  43 */ { 8, 3, FALSE },\n\t/*  44 */ { 8, 4, FALSE },\n\t/*  45 */ { 8, 5, FALSE },\n\t/*  46 */ { 8, 6, TRUE },\n\t/* The false -> true changes below (4.8.7, 4.8.8, 4.8.9) occur because \n\t   cryptlib takes its initial policy from the first CA certificate with \n\t   a policy that it finds.  This is due to real-world issues where re-\n\t   parented certificate chains due to re-sold CA root keys end up with \n\t   different policies in the root and the next-level-down pseudo-root \n\t   and problems where the root is an extension-less X.509v1 certificate.\n\t   The same issue crops up in the 4.10.* / 4.11.* tests further down */\n\t/*  47 */ { 8, 7, /* FALSE */ TRUE },\n\t/*  48 */ { 8, 8, /* FALSE */ TRUE },\n\t/*  49 */ { 8, 9, /* FALSE */ TRUE },\n\t/*  50 */ { 8, 10, TRUE },\n\t/*  51 */ { 8, 11, TRUE },\n\t/*  52 */ { 8, 12, FALSE },\n\t/*  53 */ { 8, 13, TRUE },\n\t/*  54 */ { 8, 14, TRUE },\n\t/*  55 */ { 8, 15, TRUE },\n\t/*  56 */ { 8, 20, TRUE },\n\n\t/* Policy constraints.  For these tests policy handling is dictated by\n\t   policy constraints so we don't require explicit policies */\n\t/*  57 */ { 9, 1, TRUE },\n\t/*  58 */ { 9, 2, TRUE, TRUE },\n\t/* The NIST test value for this one is wrong.  RFC 3280 section 4.2.1.12\n\t   says:\n\n\t\tIf the requireExplicitPolicy field is present, the value of\n\t\trequireExplicitPolicy indicates the number of additional\n\t\tcertificates that may appear in the path before an explicit policy\n\t\tis required for the entire path.  When an explicit policy is\n\t\trequired, it is necessary for all certificates in the path to\n\t\tcontain an acceptable policy identifier in the certificate policies\n\t\textension.\n\n\t   Test 4.9.3 has requireExplicitPolicy = 4 in a chain of 4 certs for\n\t   which the last one has no policy.  NIST claims this shouldn't\n\t   validate, which is incorrect */\n\t/*  59 */ { 9, 3, TRUE /* FALSE */, TRUE },\n\t/*  60 */ { 9, 4, TRUE, TRUE },\n\t/*  61 */ { 9, 5, FALSE, TRUE },\n\t/*  62 */ { 9, 6, TRUE, TRUE },\n\t/*  63 */ { 9, 7, FALSE, TRUE },\n\t/*  64 */ { 9, 8, FALSE, TRUE },\n\n\t/* 10, 11 = Policy mappings.  The false -> true changes below (4.10.2,\n\t   4.10.4) occur because cryptlib takes its initial policy from the \n\t   first CA certificate with a policy that it finds.  This is due to \n\t   real-world issues where re-parented certificate chains due to re-sold \n\t   CA root keys end up with different policies in the root and the next-\n\t   level-down pseudo-root and problems where the root is an extension-\n\t   less X.509v1 certificate */\n\t/*  65 */ { 10, 1, TRUE },\n\t/*  66 */ { 10, 2, /* FALSE */ TRUE },\n\t/*  67 */ { 10, 3, TRUE },\n\t/*  68 */ { 10, 4, /* FALSE */ TRUE },\n\t/*  69 */ { 10, 5, TRUE },\n\t/*  70 */ { 10, 6, TRUE },\n\t/*  71 */ { 10, 7, FALSE },\n\t/*  72 */ { 10, 8, FALSE },\n\t/*  73 */ { 10, 9, TRUE },\n\t/* The test for 4.10.10 is a special case because it contains  the \n\t   retroactively triggered requireExplicitPolicy extension, see the long \n\t   comment in chk_chn.c for a discussion of this, for now we just \n\t   disable the check by recording it as a value-true check because even \n\t   the standards committee can't explain why it does what it does */\n\t/*  74 */ { 10, 10, /* FALSE */ TRUE },\n\t/*  75 */ { 10, 11, TRUE },\n\t/*  76 */ { 10, 12, TRUE },\n\t/*  77 */ { 10, 13, TRUE },\n\t/*  78 */ { 10, 14, TRUE },\n\n\t/* Policy inhibitPolicy.  The false -> true changes below (4.11.1) are \n\t   as for the 10.x tests */\n\t/*  79 */ { 11, 1, /* FALSE */ TRUE },\n\t/* The NIST test value for 4.11.2 is wrong, the top-level CA \n\t   certificate sets inhibitPolicyMapping to 1, the mid-level CA \n\t   certificate maps policy 1 to policy 3, and the EE certificte asserts\n\t   policy 3, however at this point inhibitPolicyMapping is in effect\n\t   and policy 3 is no longer valid */\n\t/*  80 */ { 11, 2, /* TRUE */ FALSE },\n\t/*  81 */ { 11, 3, FALSE },\n\t/* The NIST test value for 4.11.4 is wrong for the same reason as for \n\t   4.11.2, except that the point of failure is a second sub-CA rather \n\t   than the EE */\n\t/*  82 */ { 11, 4, /* TRUE */ FALSE },\n\t/*  83 */ { 11, 5, FALSE },\n\t/*  84 */ { 11, 6, FALSE },\n\t/* The NIST test value for 4.11.7 is wrong for the same reason as for \n\t   4.11.2, except that the mapping is from policy 1 to policy 2 instead \n\t   of policy 3 */\n\t/*  85 */ { 11, 7, /* TRUE */ FALSE },\n\t/*  86 */ { 11, 8, FALSE },\n\t/*  87 */ { 11, 9, FALSE },\n\t/*  88 */ { 11, 10, FALSE },\n\t/*  89 */ { 11, 11, FALSE },\n\n\t/* Policy inhibitAny */\n\t/*  90 */ { 12, 1, FALSE },\n\t/*  91 */ { 12, 2, TRUE },\n\t/*  92 */ { 12, 3, TRUE },\n\t/*  93 */ { 12, 4, FALSE },\n\t/*  94 */ { 12, 5, FALSE },\n\t/*  95 */ { 12, 6, FALSE },\n\t/* The NIST test results for 4.12.7 and 4.12.9 are wrong or more \n\t   specifically the PKIX spec is wrong, contradicting itself in the body \n\t   of the spec and the path-processing pseudocode in that there's no \n\t   path-kludge exception for policy constraints in the body but there is \n\t   one in the pseudocode.  Since these chains contain path-kludge certs \n\t   the paths are invalid - they would only be valid if there was a path-\n\t   kludge exception for inhibitAnyPolicy.  Note that 4.9.7 and 4.9.8 \n\t   have the same conditions for requireExplicitPolicy but this time the \n\t   NIST test results go the other way.  So although the PKIX spec is \n\t   wrong the NIST test is also wrong in that it applies an inconsistent \n\t   interpretation of the contradictions in the PKIX spec */\n\t/*  96 */ { 12, 7, FALSE /* TRUE */ },\n\t/*  97 */ { 12, 8, FALSE },\n\t/*  98 */ { 12, 9, FALSE /* TRUE */ },\n\t/*  99 */ { 12, 10, FALSE },\n\n\t/* Name constraints */\n\t/* 100 */ { 13, 1, TRUE },\n\t/* 101 */ { 13, 2, FALSE },\n\t/* 102 */ { 13, 3, FALSE },\n\t/* 103 */ { 13, 4, TRUE },\n\t/* 104 */ { 13, 5, TRUE },\n\t/* 105 */ { 13, 6, TRUE },\n\t/* 106 */ { 13, 7, FALSE },\n\t/* 107 */ { 13, 8, FALSE },\n\t/* 108 */ { 13, 9, FALSE },\n\t/* 109 */ { 13, 10, FALSE },\n\t/* 110 */ { 13, 11, TRUE },\n\t/* 111 */ { 13, 12, FALSE },\n\t/* 112 */ { 13, 13, FALSE },\n\t/* 113 */ { 13, 14, TRUE },\n\t/* 114 */ { 13, 15, FALSE },\n\t/* 115 */ { 13, 16, FALSE },\n\t/* 116 */ { 13, 17, FALSE },\n\t/* 117 */ { 13, 18, TRUE },\n\t/* 118 */ { 13, 19, TRUE },\n\t/* 119 */ { 13, 20, FALSE },\n\t/* 120 */ { 13, 21, TRUE },\n\t/* 121 */ { 13, 22, FALSE },\n\t/* 122 */ { 13, 23, TRUE },\n\t/* 123 */ { 13, 24, FALSE },\n\t/* 124 */ { 13, 25, TRUE },\n\t/* 125 */ { 13, 26, FALSE },\n\t/* 126 */ { 13, 27, TRUE },\n\t/* 127 */ { 13, 28, FALSE },\n\t/* 188 */ { 13, 29, FALSE },\n\t/* 129 */ { 13, 30, TRUE },\n\t/* 130 */ { 13, 31, FALSE },\n\t/* 131 */ { 13, 32, TRUE },\n\t/* 132 */ { 13, 33, FALSE },\n\t/* 133 */ { 13, 34, TRUE },\n\t/* 134 */ { 13, 35, FALSE },\n\t/* 135 */ { 13, 36, TRUE },\n\t/* 136 */ { 13, 37, FALSE },\n\t/* The NIST test results for 4.13.38 are wrong.  PKIX section 4.2.1.11\n\t   says:\n\n\t\tDNS name restrictions are expressed as foo.bar.com.  Any DNS name\n\t\tthat can be constructed by simply adding to the left hand side of\n\t\tthe name satisfies the name constraint.  For example,\n\t\twww.foo.bar.com would satisfy the constraint but foo1.bar.com would\n\t\tnot.\n\n\t   The permitted subtree is testcertificates.gov and the altName is\n\t   mytestcertificates.gov which satisfies the above rule so the path\n\t   should be valid and not invalid */\n\t/* 137 */ { 13, 38, TRUE /* FALSE */ },\n\n\t/* 14, 15 = CRLs */\n\n\t/* Private certificate extensions */\n\t/* 138 */ { 16, 1, TRUE },\n\t/* 139 */ { 16, 2, FALSE },\n\t{ 0, 0 }\n\t};\n\nstatic int testPath( const PATH_TEST_INFO *pathInfo )\n\t{\n\tCRYPT_CERTIFICATE cryptCertPath;\n\tchar pathName[ 64 ];\n\tint pathNo, requirePolicy, status;\n\n\t/* Convert the composite path info into a single number used for fetching\n\t   the corresponding data file */\n\tsprintf( pathName, \"4%d%d\", pathInfo->fileMajor, pathInfo->fileMinor );\n\tpathNo = atoi( pathName );\n\n\t/* Test the path */\n\tsprintf( pathName, \"4.%d.%d\", pathInfo->fileMajor, pathInfo->fileMinor );\n\tfprintf( outputStream, \"  Path %s%s...\", pathName, \n\t\t\t pathInfo->policyOptional ? \" without explicit policy\" : \"\" );\n\tstatus = importCertFromTemplate( &cryptCertPath,\n\t\t\t\t\t\t\t\t\t PATHTEST_FILE_TEMPLATE, pathNo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate import for test path %s failed, \"\n\t\t\t\t \"status %d, line %d.\\n\", pathName, status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( pathInfo->policyOptional )\n\t\t{\n\t\t/* By default we require policy chaining, for some tests we can turn\n\t\t   this off to check non-explict policy processing */\n\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_REQUIREPOLICY,\n\t\t\t\t\t\t\t\t\t&requirePolicy );\n\t\tassert( cryptStatusOK( status ) && requirePolicy != FALSE );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_REQUIREPOLICY,\n\t\t\t\t\t\t   FALSE );\n\t\tstatus = cryptCheckCert( cryptCertPath, CRYPT_UNUSED );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_REQUIREPOLICY,\n\t\t\t\t\t\t   requirePolicy );\n\t\t}\n\telse\n\t\tstatus = cryptCheckCert( cryptCertPath, CRYPT_UNUSED );\n\tif( pathInfo->isValid )\n\t\t{\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tputs( \" didn't verify even though it should be valid.\" );\n\t\t\treturn( attrErrorExit( cryptCertPath, \"cryptCheckCert()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tputs( \" verified even though it should have failed.\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tfputs( \" succeeded.\\n\", outputStream );\n\tcryptDestroyCert( cryptCertPath );\n\n\treturn( TRUE );\n\t}\n\nint testPathProcessing( void )\n\t{\n\tCRYPT_CERTIFICATE cryptRootCert;\n\tint certTrust DUMMY_INIT, complianceLevel, i, status;\n\n\tfputs( \"Testing path processing...\\n\", outputStream );\n\n\t/* Get the root certificate and make it implicitly trusted and crank the\n\t   compliance level up to maximum, since we're going to be testing some\n\t   pretty obscure extensions */\n\tstatus = importCertFromTemplate( &cryptRootCert,\n\t\t\t\t\t\t\t\t\t PATHTEST_FILE_TEMPLATE, 0 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = setRootTrust( cryptRootCert, &certTrust, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't create trusted root certificate \"\n\t\t\t\t \"for path processing, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t&complianceLevel );\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_PKIX_FULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't set compliance level to \"\n\t\t\t\t\"CRYPT_COMPLIANCELEVEL_PKIX_FULL, line %d.\\nThis may be \"\n\t\t\t\t\"because cryptlib has been configured not to run at this \"\n\t\t\t\t\"level.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Process each certificate path and make sure that it succeeds or fails \n\t   as required */\n\tfor( i = 0; pathTestInfo[ i ].fileMajor != 0; i++ )\n\t\t{\n\t\tif( !testPath( &pathTestInfo[ i ] ) )\n\t\t\tbreak;\n\t\t}\n\tsetRootTrust( cryptRootCert, NULL, certTrust );\n\tcryptDestroyCert( cryptRootCert );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   complianceLevel );\n\tif( pathTestInfo[ i ].fileMajor )\n\t\treturn( FALSE );\n\n\tfputs( \"Path processing succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMiscellaneous Tests\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test handling of invalid PKCS #1 padding in certificate signatures.  Note \n   that running this test properly requires disabling the PKCS#1 padding \n   format check in decodePKCS1() in mechs/mech_sig.c since the signatures \n   have such an obviously dodgy format that they don't even make it past the \n   basic padding sanity check */\n\nint testPKCS1Padding( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tint i, complianceValue, status;\n\n\tfputs( \"Testing invalid PKCS #1 padding handling...\\n\", outputStream );\n\n\t/* The test certs don't have a keyUsage present in a CA certificate so \n\t   we have to lower the compliance level to be able to get past this \n\t   check to the signatures */\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t&complianceValue );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n\tfor( i = 1; i <= 11; i++ )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptCert, PADTEST_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t i );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't import certificate for PKCS #1 \"\n\t\t\t\t\t \"padding check, status %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tprintf( \"Certificate with bad PKSC #1 padding verified, should \"\n\t\t\t\t\t\"have failed, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   complianceValue );\n\n\tfputs( \"Padding handling succeeded (all certs rejected).\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\n/* Generic test routines used for debugging.  These are only meant to be\n   used interactively, and throw exceptions rather than returning status\n   values */\n\nint xxxCertImport( const char *fileName )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ], *bufPtr = buffer;\n\tlong length, count;\n\tint status;\n\n\tfilePtr = fopen( fileName, \"rb\" );\n\tassert( filePtr != NULL );\n\tfseek( filePtr, 0L, SEEK_END );\n\tlength = ftell( filePtr );\n\tfseek( filePtr, 0L, SEEK_SET );\n\tif( length > BUFFER_SIZE )\n\t\t{\n\t\tbufPtr = malloc( length );\n\t\tassert( bufPtr != NULL );\n\t\t}\n\tcount = fread( bufPtr, 1, length, filePtr );\n\tassert( count == length );\n\tfclose( filePtr );\n\tstatus = cryptImportCert( bufPtr, count, CRYPT_UNUSED, &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate import failed, status = %d.\\n\", \n\t\t\t\t status );\n\t\tassert( cryptStatusOK( status ) );\n\t\tif( bufPtr != buffer )\n\t\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( bufPtr != buffer )\n\t\tfree( bufPtr );\n\tprintCertChainInfo( cryptCert );\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\t/* Opportunistic only */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"(Opportunistic) certificate check failed, \"\n\t\t\t\t \"status = %d.\\n\", status );\n\t\tprintErrorAttributeInfo( cryptCert );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n\nint xxxCertCheck( const C_STR certFileName, const C_STR caFileNameOpt )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptCaCert;\n\tint status;\n\n\tstatus = importCertFile( &cryptCert, certFileName );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate import failed, status = %d.\\n\", \n\t\t\t\t status );\n\t\tassert( cryptStatusOK( status ) );\n\t\treturn( FALSE );\n\t\t}\n\tif( caFileNameOpt == NULL )\n\t\t{\n\t\t/* It's a self-signed certificate or certificate chain, make it\n\t\t   implicitly trusted in order to allow the signature check to\n\t\t   work */\n\t\tcryptCaCert = CRYPT_UNUSED;\n\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_LAST );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT, 1 );\n\t\t\t}\n\t\tassert( cryptStatusOK( status ) );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = importCertFile( &cryptCaCert, caFileNameOpt );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't import certificate from '%s', \"\n\t\t\t\t\t \"status = %d.\\n\", caFileNameOpt, status );\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, cryptCaCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate check failed, status = %d.\\n\", \n\t\t\t\t status );\n\t\tprintErrorAttributeInfo( cryptCert );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\tcryptDestroyCert( cryptCaCert );\n\n\treturn( cryptStatusOK( status ) ? TRUE : FALSE );\n\t}\n"
  },
  {
    "path": "deps/cl345/test/certproc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Certificate Handling Test Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\nextern BYTE certBuffer[ BUFFER_SIZE ];\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Processing Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nstatic const CERT_DATA certRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA certProcessData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* Create a certification request */\n\nstatic int createCertRequest( void *certRequest,\n\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t  const BOOLEAN useCRMF )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT cryptContext;\n\tint length DUMMY_INIT, status;\n\n\t/* Create a new key */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t TEXT( \"Private key\" ),\n\t\t\t\t\t\t\t paramStrlen( TEXT( \"Private key\" ) ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the certification request */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED, useCRMF ? \\\n\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT : CRYPT_CERTTYPE_CERTREQUEST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !addCertFields( cryptCert, certRequestData, __LINE__ ) )\n\t\treturn( -1 );\n#ifndef _WIN32_WCE\n\tif( useCRMF )\n\t\t{\n\t\tconst time_t startTime = time( NULL ) - 1000;\n\t\tconst time_t endTime = time( NULL ) + 86400;\n\n\t\t/* Since we're using a CRMF request, set some fields that can't\n\t\t   be specified in the standard certificate request */\n\t\tstatus = cryptSetAttributeString( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDFROM, &startTime, sizeof( time_t ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &endTime, sizeof( time_t ) );\n\t\t\t}\n\t\t}\n#endif /* _WIN32_WCE */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, cryptContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certRequest, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptContext );\n\treturn( length );\n\t}\n\n/* Create a certificate from a certificate request */\n\nstatic int createCertificate( void *certificate, const void *certRequest,\n\t\t\t\t\t\t\t  const int certReqLength,\n\t\t\t\t\t\t\t  const CRYPT_CONTEXT caKeyContext )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptCertRequest;\n\tint length, status;\n\n\t/* Import and verify the certification request */\n\tstatus = cryptImportCert( certRequest, certReqLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCertRequest );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptCheckCert( cryptCertRequest, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_CERTREQUEST, cryptCertRequest );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, caKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certificate, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCertRequest );\n\treturn( ( cryptStatusOK( status ) ) ? length : status );\n\t}\n\n/* Create a certificate directly, used for algorithms that don't support\n   self-signed certificate requests */\n\nstatic int createCertDirect( void *certificate,\n\t\t\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT caKeyContext )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT cryptContext;\n\tint length, status;\n\n\t/* Create a new key */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t TEXT( \"Private key\" ),\n\t\t\t\t\t\t\t paramStrlen( TEXT( \"Private key\" ) ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the certification */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !addCertFields( cryptCert, certProcessData, __LINE__ ) )\n\t\treturn( FALSE );\n\tstatus = cryptSignCert( cryptCert, caKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certificate, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptContext );\n\treturn( ( cryptStatusOK( status ) ) ? length : status );\n\t}\n\n/* Test the full certification process */\n\nstatic int certProcess( const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\tconst char *algoName,\n\t\t\t\t\t\tconst CRYPT_CONTEXT cryptCAKey,\n\t\t\t\t\t\tconst BOOLEAN useCRMF )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tconst char *certName = \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t( useCRMF ? \"prcrtrsa_c\" : \"prcrtrsa\" ) : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_DSA ) ? \"prcrtdsa\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_DH ) ? \"prcrtdh\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \"prcrtelg\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ECDSA ) ? \"prcrtecdsa\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ECDH ) ? \"prcrtecdh\" : \"prcrtxxx\";\n\tint length, status;\n\n\tprintf( \"Testing %s certificate processing%s...\\n\", algoName,\n\t\t\tuseCRMF ? \" from CRMF request\" : \"\" );\n\n\t/* Some algorithms can't create self-signed certificate requests so we \n\t   have to create the certificate directly */\n\tif( cryptAlgo != CRYPT_ALGO_ELGAMAL && cryptAlgo != CRYPT_ALGO_DH && \\\n\t\tcryptAlgo != CRYPT_ALGO_ECDH )\n\t\t{\n\t\tconst char *reqName = \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t( useCRMF ? \"prreqrsa_c\" : \"prreqrsa\" ) : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_DSA ) ? \"prreqdsa\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ECDSA ) ? \"prreqecdsa\" : \"prreqxxx\";\n\n\t\t/* Create the certification request */\n\t\tstatus = length = createCertRequest( certBuffer, cryptAlgo, useCRMF );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Certification request creation failed with error code \"\n\t\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tdebugDump( reqName, certBuffer, length );\n\n\t\t/* Create a certificate from the certification request */\n\t\tstatus = createCertificate( certBuffer, certBuffer, length,\n\t\t\t\t\t\t\t\t\tcryptCAKey );\n\t\t}\n\telse\n\t\tstatus = createCertDirect( certBuffer, cryptAlgo, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Certificate creation failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tlength = status;\n\tdebugDump( certName, certBuffer, length );\n\n\t/* Import the certificate and check its validity using the CA key (we use\n\t   the private key context since it's handy, in practice we should use\n\t   the public key certificate */\n\tstatus = cryptImportCert( certBuffer, length, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptCheckCert( cryptCert, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Certificate validation failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tprintf( \"%s certificate processing succeeded.\\n\\n\", algoName );\n\treturn( TRUE );\n\t}\n\nint testCertProcess( void )\n\t{\n\tCRYPT_CONTEXT cryptCAKey;\n\tint value, status;\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"CA private key read failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test each PKC algorithm */\n\tif( !certProcess( CRYPT_ALGO_RSA, \"RSA\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n\tif( !certProcess( CRYPT_ALGO_DSA, \"DSA\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ELGAMAL, NULL ) ) && \\\n\t\t!certProcess( CRYPT_ALGO_ELGAMAL, \"Elgamal\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n\tif( !certProcess( CRYPT_ALGO_DH, \"Diffie-Hellman\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) && \\\n\t\t!certProcess( CRYPT_ALGO_ECDSA, \"ECDSA\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n#if 0\n\t/* We can't perform the test for ECDH because there's only one algorithm\n\t   type available for public keys, \"ECC\", and that doesn't distinguish\n\t   between an ECDH ECC key and an ECDSA ECC key.  Because of this the \n\t   code assumes that any ECC key is an ECDSA key, so that while we can\n\t   create an ECDH certificate, we can't read it back because it'll be\n\t   read as an ECDSA certificate */\n\tif( !certProcess( CRYPT_ALGO_ECDH, \"ECDH\", cryptCAKey, FALSE ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n\n\t/* Run the test again with a CRMF instead of PKCS #10 request */\n\tif( !certProcess( CRYPT_ALGO_RSA, \"RSA\", cryptCAKey, TRUE ) )\n\t\treturn( FALSE );\n\n\t/* Now try a different hash algorithm */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH,\n\t\t\t\t\t   ( value == CRYPT_ALGO_SHA1 ) ? \\\n\t\t\t\t\t\t CRYPT_ALGO_SHA2 : CRYPT_ALGO_SHA1 );\n\tstatus = certProcess( CRYPT_ALGO_RSA, \"RSA with non-default hash algorithm\", \n\t\t\t\t\t\t  cryptCAKey, FALSE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, value );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptCAKey );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCA Certificate Management Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since opening the certificate store for update creates a log entry each \n   time, we open it once at the start and then call a series of sub-tests \n   with the store open throughout the tests.  This also allows us to keep the\n   CA key active througout */\n\nstatic const CERT_DATA cert1Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test user 1\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"test1@testusers.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA revokableCert1Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Revoked cert user 1\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"test2@testusers.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA revokableCert2Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Revoked cert user 2\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"revoked1@testusers.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA expiredCert1Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Expired cert user 1\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"revoked2@testusers.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA expiredCert2Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Expired cert user 2\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"expired2@testusers.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* Certificate requests for which the issue should fail, for various \n   reasons */\n\nstatic const CERT_DATA certCA1Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test CA user 1\" ) },\n\n\t/* CA extensions.  These should be rejected/stripped by the certificate\n\t   management code, since new CAs can only be created by the issuing CA\n\t   specifying it in the PKI user info */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA certCA2Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test CA user 2\" ) },\n\n\t/* CA extensions.  A variant of the above with no basicConstraints but a \n\t   CA-only key usage */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t  CRYPT_KEYUSAGE_CRLSIGN },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n#ifdef USE_CERT_DNSTRING\nstatic const CERT_DATA certDodgyDNData[] = {\n\t/* Identification information.  The multi-AVA RDN should be rejected */\n\t{ CRYPT_CERTINFO_DN, IS_STRING, 0, \n\t  TEXT( \"cn=www.example.com + cn=www.wetaburgers.com, ou=Procurement, o=Wetaburgers, c=NZ\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n#endif /* USE_CERT_DNSTRING */\n\n/* Add a certification request to the certificate store */\n\nstatic int addCertRequest( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t   const CERT_DATA *certReqData,\n\t\t\t\t\t\t   const BOOLEAN isExpired )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CERTIFICATE cryptCertRequest;\n\tint length, status;\n\n\t/* Generate a (short) key for the request */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t TEXT( \"Private key\" ),\n\t\t\t\t\t\t\t paramStrlen( TEXT( \"Private key\" ) ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Creation of private key for certificate failed with error \"\n\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certification request.  If we're adding an expiry time\n\t   we have to make it a CRMF request since a standard request can't\n\t   handle this */\n\tstatus = cryptCreateCert( &cryptCertRequest, CRYPT_UNUSED, isExpired ? \\\n\t\t\t\t\tCRYPT_CERTTYPE_REQUEST_CERT : CRYPT_CERTTYPE_CERTREQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCertRequest,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n#ifndef _WIN32_WCE\n\tif( cryptStatusOK( status ) && isExpired )\n\t\t{\n\t\tconst time_t theTime = time( NULL ) + 5;\n\n\t\t/* Set the expiry time to a few seconds after the current time to\n\t\t   ensure that the certificate has expired by the time we need it.  \n\t\t   This is a tiny bit risky since it requires that the interval \n\t\t   between setting this attribute and the creation of the certificate \n\t\t   below is less than five seconds, however there's no easy way to \n\t\t   guarantee the creation of a pre-expired certificate since if we \n\t\t   set the time too far back it won't be created */\n\t\tstatus = cryptSetAttributeString( cryptCertRequest,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &theTime, sizeof( time_t ) );\n\t\t}\n#endif /* _WIN32_WCE */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertRequest, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCertRequest, certReqData, __LINE__ ) )\n\t\t{\n\t\t/* We have to make sure that we exit cleanly here since some of the \n\t\t   tests verify the rejection of invalid request data, so a failure\n\t\t   at this point isn't a true error for these tests */\n\t\tcryptDestroyCert( cryptCertRequest );\n\t\tcryptDestroyContext( cryptContext );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSignCert( cryptCertRequest, cryptContext );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertRequest, \"cryptSignCert()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\n\t/* Export the request, destroy it, and recreate it by importing it again.\n\t   This is just a pedantic check to make sure that we emulate exactly a\n\t   real-world scenario of an externally-obtained request */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE,\n\t\t\t\t\t\t\t  cryptCertRequest );\n\tcryptDestroyCert( cryptCertRequest );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptImportCert( certBuffer, length, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  &cryptCertRequest );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't export/re-import certificate request, status = \"\n\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the request to the certificate store */\n\tstatus = cryptCAAddItem( cryptCertStore, cryptCertRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAAddItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\n\treturn( cryptCertRequest );\n\t}\n\n/* Add a revocation request to the certificate store.  This code isn't \n   currently used because CMP doesn't allow revocation requests to be \n   signed so we can't create a signed object to add directly but have to \n   come in via CMP */\n\n#if 0\n\nstatic int addRevRequest( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t  const CERT_DATA *certReqData )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptCertRequest;\n\tint i, status;\n\n\t/* Find the CN of the certificate we're revoking and use it to fetch the \n\t   certificate */\n\tfor( i = 0; certReqData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\tif( certReqData[ i ].type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\tprintf( \"Revoking certificate for '%s'.\\n\",\n\t\t\t\t\t( char * ) certReqData[ i ].stringValue );\n\tstatus = cryptGetPublicKey( cryptCertStore, &cryptCert, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tcertReqData[ i ].stringValue );\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptCertStore, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\n\t/* Create the revocation request */\n\tstatus = cryptCreateCert( &cryptCertRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCertRequest, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\tcryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertRequest, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCertRequest, revRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Add the request to the certificate store */\n\tstatus = cryptCAAddItem( cryptCertStore, cryptCertRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAAddItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\n\treturn( cryptCertRequest );\n\t}\n#endif /* 0 */\n\n/* Issue a certificate from a certificate request, and try and issue an\n   invalid certificate from a request, for which the issue process should \n   fail */\n\nstatic int issueCert( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t  const CRYPT_CONTEXT cryptCAKey,\n\t\t\t\t\t  const CERT_DATA *certReqData, \n\t\t\t\t\t  const BOOLEAN isExpired )\n\t{\n\tCRYPT_CERTIFICATE cryptCertRequest;\n\tint i, status;\n\n\t/* Provide some feedback on what we're doing */\n\tfor( i = 0; certReqData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t{\n\t\tif( certReqData[ i ].type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\t{\n\t\t\tprintf( \"Issuing certificate for '%s'.\\n\",\n\t\t\t\t\t( char * ) certReqData[ i ].stringValue );\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t/* Issue the certificate via the certificate store */\n\tcryptCertRequest = addCertRequest( cryptCertStore, certReqData, isExpired );\n\tif( !cryptCertRequest )\n\t\treturn( FALSE );\n\tstatus = cryptCACertManagement( NULL, CRYPT_CERTACTION_ISSUE_CERT,\n\t\t\t\t\t\t\t\t\tcryptCertStore, cryptCAKey,\n\t\t\t\t\t\t\t\t\tcryptCertRequest );\n\tcryptDestroyCert( cryptCertRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( isExpired && status == CRYPT_ERROR_INVALID )\n\t\t\t{\n\t\t\tputs( \"The short-expiry-time certificate has already expired at \"\n\t\t\t\t  \"the time of issue.\\nThis happened because there was a \"\n\t\t\t\t  \"delay of more than 5s between adding the\\nrequest and \"\n\t\t\t\t  \"issuing the certificate for it.  Try re-running the test \"\n\t\t\t\t  \"on a\\nless-heavily-loaded system, or increase the expiry \"\n\t\t\t\t  \"delay to more than 5s.\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCACertManagement()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int checkInvalidIssueRejected( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t\t\t\t  const CRYPT_CONTEXT cryptCAKey,\n\t\t\t\t\t\t\t\t\t  const CERT_DATA *certReqData,\n\t\t\t\t\t\t\t\t\t  const BOOLEAN requestCreationShouldFail )\n\t{\n\tCRYPT_CERTIFICATE cryptCertRequest;\n\tint i, status;\n\n\t/* Provide some feedback on what we're doing */\n\tfor( i = 0; certReqData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t{\n\t\tif( certReqData[ i ].type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\t{\n\t\t\tprintf( \"Issuing certificate for '%s'.\\n\",\n\t\t\t\t\t( char * ) certReqData[ i ].stringValue );\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tif( certReqData[ i ].type == CRYPT_ATTRIBUTE_NONE )\n\t\t{\n\t\t/* If the certificate doesn't have a CN attribute then it's one with\n\t\t   a synthetic DN created to test the DN-validity checks */\n\t\tputs( \"Issuing certificate for synthetic invalid DN.\" );\n\t\t}\n\n\t/* Issue the certificate via the certificate store */\n\tcryptCertRequest = addCertRequest( cryptCertStore, certReqData, FALSE );\n\tif( !cryptCertRequest )\n\t\t{\n\t\t/* In some cases the invalid request will be caught as soon as it's \n\t\t   created (this is a bit unfortunate because we really want to \n\t\t   check whether an import of someone else's invalid request will\n\t\t   fail, however this is checked indirectly because it demonstrates\n\t\t   that the certificate code won't allow the use of such a value in\n\t\t   a certificate */\n\t\tif( requestCreationShouldFail )\n\t\t\t{\n\t\t\tputs( \"  (This is an expected result since this test verifies \"\n\t\t\t\t  \"handling of\\n   invalid request data).\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCACertManagement( NULL, CRYPT_CERTACTION_ISSUE_CERT,\n\t\t\t\t\t\t\t\t\tcryptCertStore, cryptCAKey,\n\t\t\t\t\t\t\t\t\tcryptCertRequest );\n\tcryptDestroyCert( cryptCertRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* This is a check of the request validity-checking system so the \n\t\t   issue is supposed to fail */\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\n/* Issue a CRL.  Although we can't do this directly (see the comment above\n   for the revocation request code) we can at least test the ability to\n   create an empty CRL (and if the CMP code has been run there will probably\n   be a few revocation entries present to fill the CRL) */\n\nstatic int issueCRL( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t const CRYPT_CONTEXT cryptCAKey )\n\t{\n\tCRYPT_CERTIFICATE cryptCRL;\n\tint noEntries = 0, status;\n\n\t/* Issue the CRL via the certificate store */\n\tstatus = cryptCACertManagement( &cryptCRL, CRYPT_CERTACTION_ISSUE_CRL,\n\t\t\t\t\t\t\t\t\tcryptCertStore, cryptCAKey,\n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCACertManagement()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\n\t/* Print information on the CRL */\n\tif( cryptStatusOK( cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CURSOR_FIRST ) ) )\n\t\tdo\n\t\t\t{\n\t\t\tnoEntries++;\n\t\t\t}\n\t\twhile( cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\tprintf( \"CRL has %d entr%s.\\n\", noEntries,\n\t\t\t( noEntries == 1 ) ? \"y\" : \"ies\" );\n\tif( !noEntries )\n\t\t{\n\t\tputs( \"  (This is probably because there haven't been any revocation \"\n\t\t\t  \"entries added\\n   via the CMP test yet).\" );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCRL );\n\treturn( TRUE );\n\t}\n\n/* Fetch the issued certificate that was created from a given cert template */\n\nstatic CRYPT_CERTIFICATE getCertFromTemplate( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t\t\t\t\t\t  const CERT_DATA *certReqData )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tint i, status;\n\n\tfor( i = 0; certReqData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t{\n\t\tif( certReqData[ i ].type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\tbreak;\n\t\t}\n\tstatus = cryptGetPublicKey( cryptCertStore, &cryptCert, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t    certReqData[ i ].stringValue );\n\treturn( cryptStatusOK( status ) ? cryptCert : status );\n\t}\n\nint testCertManagement( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptCertRequest;\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\ttime_t certTime;\n\tint dummy, status;\n\n\tputs( \"Testing certificate management using certificate store...\" );\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"CA private key read failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certificate store keyset with a check to make sure that \n\t   this access method exists so we can return an appropriate error \n\t   message.  If the database table already exists, this will return a \n\t   duplicate data error so we retry the open with no flags to open the \n\t   existing database keyset for write access */\n\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tputs( \"Created new certificate store '\" CERTSTORE_KEYSET_NAME_ASCII\n\t\t\t  \"'.\" );\n\t\t}\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access isn't available, return a special error\n\t\t   code to indicate that the test wasn't performed, but that this\n\t\t   isn't a reason to abort processing */\n\t\tcryptDestroyContext( cryptCAKey );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\t{\n\t\t\tcryptDestroyContext( cryptCAKey );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create a certificate request, add it to the store, and destroy it, \n\t   simulating a delayed certificate issue in which the request can't \n\t   immediately be converted into a certificate.  Then read the request \n\t   back from the store and issue a certificate based on it */\n\tputs( \"Issuing certificate for 'Test user 1'...\" );\n\tcryptCertRequest = addCertRequest( cryptCertStore, cert1Data, FALSE );\n\tif( !cryptCertRequest )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptCertRequest );\n\tstatus = cryptCAGetItem( cryptCertStore, &cryptCertRequest,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_REQUEST_CERT, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t TEXT( \"Test user 1\" ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAGetItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tstatus = cryptCACertManagement( &cryptCert, CRYPT_CERTACTION_ISSUE_CERT,\n\t\t\t\t\t\t\t\t\tcryptCertStore, cryptCAKey,\n\t\t\t\t\t\t\t\t\tcryptCertRequest );\n\tcryptDestroyCert( cryptCertRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCACertManagement()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Issue some more certs, this time directly from the request and without\n\t   bothering to obtain the resulting certificate.  The first two have a \n\t   validity time that expires in a few seconds so that we can use them \n\t   to test certificate expiry processing, we issue these first to ensure \n\t   that as much time as possible passes due to other operations occurring \n\t   before we run the expiry.  The second two are for revocation and CRL \n\t   testing */\n\tif( !issueCert( cryptCertStore, cryptCAKey, expiredCert1Data, TRUE ) )\n\t\treturn( FALSE );\n\tif( !issueCert( cryptCertStore, cryptCAKey, expiredCert2Data, TRUE ) )\n\t\treturn( FALSE );\n\tif( !issueCert( cryptCertStore, cryptCAKey, revokableCert1Data, FALSE ) )\n\t\treturn( FALSE );\n\tif( !issueCert( cryptCertStore, cryptCAKey, revokableCert2Data, FALSE ) )\n\t\treturn( FALSE );\n\n\t/* The following tests are specifically inserted at this point (rather\n\t   than at some other point in the test run) because they'll add some\n\t   further delay before the expiry operation */\n\n\t/* Try and get a CA certificate issued.  This should fail, since new CAs \n\t   can only be created if the issuing CA specifies it (either directly \n\t   when it creates the certificate manually or via the PKI user info), \n\t   but never at the request of the user */\n\tif( !checkInvalidIssueRejected( cryptCertStore, cryptCAKey, \n\t\t\t\t\t\t\t\t\tcertCA1Data, TRUE ) || \\\n\t\t!checkInvalidIssueRejected( cryptCertStore, cryptCAKey, \n\t\t\t\t\t\t\t\t\tcertCA2Data, FALSE ) )\n\t\t{\n\t\tprintf( \"Issue of certificate from invalid request succeeded when \"\n\t\t\t\t\"it should have failed,\\nline %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n#ifdef USE_CERT_DNSTRING\n\t/* Try and get a certificate with a multi-AVA RDN issued.  This should\n\t   fail, since such DN shenanigans can only be performed if the CA \n\t   creates the required DN directly */\n\tif( !checkInvalidIssueRejected( cryptCertStore, cryptCAKey, \n\t\t\t\t\t\t\t\t\tcertDodgyDNData, FALSE ) )\n\t\t{\n\t\tprintf( \"Issue of certificate from invalid request succeeded when \"\n\t\t\t\t\"it should have failed,\\nline %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_CERT_DNSTRING */\n\n\t/* Get a certificate and (to-be-)revoked certificate from the store and \n\t   save them to disk for later tests */\n\tstatus = cryptCert = getCertFromTemplate( cryptCertStore, cert1Data );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tBYTE fileName[ BUFFER_SIZE ];\n\t\tFILE *filePtr;\n\t\tint length;\n\n\t\t/* First save the CA certificate */\n\t\tfilenameFromTemplate( fileName, OCSP_CA_FILE_TEMPLATE, 1 );\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCAKey );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( filePtr = fopen( fileName, \"wb\" ) ) != NULL )\n\t\t\t{\n\t\t\tint count;\n\n\t\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\t\tfclose( filePtr );\n\t\t\tif( count < length )\n\t\t\t\t{\n\t\t\t\tremove( fileName );\n\t\t\t\tputs( \"Warning: Couldn't save OCSP CA certificate to disk, \"\n\t\t\t\t\t  \"this will cause later\\n         OCSP server tests to \"\n\t\t\t\t\t  \"fail.  Press a key to continue.\" );\n\t\t\t\tgetchar();\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Then the EE certificate */\n\t\tfilenameFromTemplate( fileName, OCSP_EEOK_FILE_TEMPLATE, 1 );\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCert );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( filePtr = fopen( fileName, \"wb\" ) ) != NULL )\n\t\t\t{\n\t\t\tint count;\n\n\t\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\t\tfclose( filePtr );\n\t\t\tif( count < length )\n\t\t\t\t{\n\t\t\t\tremove( fileName );\n\t\t\t\tputs( \"Warning: Couldn't save OCSP non-revoked certificate \"\n\t\t\t\t\t  \"to disk, this will cause later\\n         OCSP server \"\n\t\t\t\t\t  \"tests to fail.  Press a key to continue.\" );\n\t\t\t\tgetchar();\n\t\t\t\t}\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = cryptCert = getCertFromTemplate( cryptCertStore,\n\t\t\t\t\t\t\t\t\t\t\t\t  revokableCert1Data );\n\t\t}\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tBYTE fileName[ BUFFER_SIZE ];\n\t\tFILE *filePtr;\n\t\tint length;\n\n\t\tfilenameFromTemplate( fileName, OCSP_EEREV_FILE_TEMPLATE, 1 );\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCert );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( filePtr = fopen( fileName, \"wb\" ) ) != NULL )\n\t\t\t{\n\t\t\tint count;\n\n\t\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\t\tfclose( filePtr );\n\t\t\tif( count < length )\n\t\t\t\t{\n\t\t\t\tremove( fileName );\n\t\t\t\tputs( \"Warning: Couldn't save OCSP revoked certificate \"\n\t\t\t\t\t  \"to disk, this will cause later\\n         OCSP server \"\n\t\t\t\t\t  \"tests to fail.  Press a key to continue.\" );\n\t\t\t\tgetchar();\n\t\t\t\t}\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Issued certificates couldn't be fetched from the certificate \"\n\t\t\t  \"store and written\\nto disk, the OCSP server test will abort \"\n\t\t\t  \"when it fails to find\\nthese certificates.\" );\n\t\t}\n\n\t/* Issue a CRL.  This will probably be a zero-length CRL unless we've run\n\t   the CMP tests because we can't directly revoke a certificate.  Again, \n\t   we perform it before the expiry test because it'll add some further\n\t   delay */\n\tif( !issueCRL( cryptCertStore, cryptCAKey ) )\n\t\treturn( FALSE );\n\n\t/* Get the most recent of the expired certs and wait for it to expire\n\t   if necessary */\n\tstatus = cryptCert = getCertFromTemplate( cryptCertStore,\n\t\t\t\t\t\t\t\t\t\t\t  expiredCert1Data );\n\tif( !cryptStatusError( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDTO,\n\t\t\t\t\t\t\t\t\t\t  &certTime, &dummy );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't get expiry information for expired certificate.\" );\n\t\treturn( FALSE );\n\t\t}\n#ifndef _WIN32_WCE\n\tif( certTime >= time( NULL ) )\n\t\t{\n\t\tconst long timeToWait = ( long ) ( certTime - time( NULL ) );\n\n\t\tif( timeToWait > 100 )\n\t\t\t{\n\t\t\tprintf( \"Certificate doesn't expire for %ld seconds (approx.%ld \"\n\t\t\t\t\t\"hours or\\n  %ld days), certificate time setting is \"\n\t\t\t\t\t\"wrong...\\n\", timeToWait, \n\t\t\t\t\ttimeToWait / 360, timeToWait / ( 86400L ) );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tprintf( \"Waiting for certificates to expire..\" );\n\t\twhile( certTime >= time( NULL ) )\n\t\t\t{\n\t\t\tdelayThread( 1 );\n\t\t\tprintf( \".\" );\n\t\t\t}\n\t\tputs( \" done.\" );\n\t\t}\n#endif /* _WIN32_WCE */\n\tcryptDestroyCert( cryptCert );\n\n\t/* Expire the certs */\n\tputs( \"Expiring certificates...\" );\n\tstatus = cryptCACertManagement( NULL, CRYPT_CERTACTION_EXPIRE_CERT,\n\t\t\t\t\t\t\t\t\tcryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCACertManagement()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptCAKey );\n\tcryptKeysetClose( cryptCertStore );\n\tputs( \"Certificate management using certificate store succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n"
  },
  {
    "path": "deps/cl345/test/certs/cert1.asc",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIG\nA1UEChMLRW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5l\ndC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikx\nJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAx\nBgNVBAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5\nICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0\nMRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3LmVudHJ1\nc3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp\nYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl\nZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRo\nb3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtT\nK91euHaYNZOLGp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAk\nAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuXMlBvPci6Zgzj/L24\nScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzWnLLP\nKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/\nHoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJm\nQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0j\nBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER\ngL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w\nAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8\nTj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMooPS7mmNz7W3lKtvt\nFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOd\nBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18\nf3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9r\nTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5L\nWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "deps/cl345/test/certs/cert2.asc",
    "content": "-----BEGIN CERTIFICATE-----\nMIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg\nQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG\nA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz\nMjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL\nEx5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0\nIEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u\nsJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql\nHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID\nAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW\nM4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF\nNMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "deps/cl345/test/certs/cert3.asc",
    "content": "-----BEGIN CERTIFICATE-----\nMIID6TCCAtGgAwIBAgICJVIwDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCTk8xEDAOBgNVBAoMB0J1eXBhc3MxIzAhBgNVBAMMGkJ1eXBhc3MgQ2xhc3MgMyBUZXN0NCBDQSAxMB4XDTA5MDkwMTA4MDIxMFoXDTEyMDkwMTA4MDIxMFowUzELMAkGA1UEBhMCTk8xFzAVBgNVBAoMDklOMyBTVVBQT1JUIEFTMRcwFQYDVQQDDA5JTjMgU1VQUE9SVCBBUzESMBAGA1UEBRMJOTg0MDI2MDEzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAXqPf+2bU1wXV/T7Z7VFvhq8zZmnEhkISvpJZ595m721x0rPc7LEphvYvSD9Judq3o6DwWv13IX3HIZDz/HAN402B3vu5vcyi0YQ4wzewftxHLI4QVFrXGzT7RmWT9n4MB3L9SSkq/3BTKP7ieMr2ljvS8Piy+X8VdDY6EmCllwIDAQABo4IBWDCCAVQwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBSeWcLQPqz9CKUgPnL0Vk3JulyqUjAdBgNVHQ4EFgQUJBO95uWMly2uQBlp+ieVK6rs3s0wDgYDVR0PAQH/BAQDAgSwMBYGA1UdIAQPMA0wCwYJYIRCARoBAAMCMIGXBgNVHR8EgY8wgYwwUaBPoE2GS2xkYXA6Ly9sZGFwLnRlc3Q0LmJ1eXBhc3Mubm8vZGM9QnV5cGFzcyxkYz1OTyxDTj1CdXlwYXNzIENsYXNzIDMgVGVzdDQgQ0EgMTA3oDWgM4YxaHR0cDovL2NybC50ZXN0NC5idXlwYXNzLm5vL2NybC9CUENsYXNzM1Q0Q0ExLmNybDBFBggrBgEFBQcBAQQ5MDcwNQYIKwYBBQUHMAGGKWh0dHBzOi8vb2NzcC50ZXN0NC5idXlwYXNzLm5vL0JQQ2xhc3MyM1Q0MA0GCSqGSIb3DQEBBQUAA4IBAQAARSqNLMtynO0zPhSawM5BMLoHAbu4RgwT0Bc75Ngsis5g5XYBBnjTZggD9ICLhm8gea3KUMR7dzVWWVsOcgxFijAwr1RJSkuWkkHLVLMxJBwIJlNqXKSCgLKVwiSxrz17HdGhvuNUG/4rlGyDH3q2PJpOxF5JWbYo+w4vjHWfeRAKhzefVx0gb5JVbSp3JZ+lo3KuYYmf0sGrSKCmt2OiB8DhjnIZSdMwz8CllBIpeTJwfG4eJP9CdJsjFn8wG8sGaFPxVoHSJ/JVsJVQpUCZMjPQmkkp4kT2tDEtlJZmuQWGDA6VuBsiY+txTCCrrlOa6OHtAJAupaCJabsLfInS\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "deps/cl345/test/certs/cert4.asc",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEFDCCAvygAwIBAgIDDJjIMA0GCSqGSIb3DQEBBQUAMEsxCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEdMBsGA1UEAwwUQnV5cGFzcyBDbGFzcyAzIENBIDEwHhcNMTEwMjIzMTM0OTU0WhcNMTQwMjIzMTM0OTUzWjBrMQswCQYDVQQGEwJOTzEjMCEGA1UECgwaQVJCRUlEUy0gT0cgVkVMRkVSRFNFVEFURU4xIzAhBgNVBAMMGkFSQkVJRFMtIE9HIFZFTEZFUkRTRVRBVEVOMRIwEAYDVQQFEwk4ODk2NDA3ODIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK4qputS9vi3n9EvQqYGychsDGOdImU34wKd2VmDNqI/K7x/ucou56WOPYJ1B60i28CYX2GxsiG/ZI8RihaMLd3IIHTOXHbH6WOkSls6Xpn0ebkzzpoKzD47z3H0Bgd/kGjNnVyZTdXDCYCGzA6PIbYDiPRy+TNuvh4pg5k/+ZafAgMBAAGjggFjMIIBXzAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFDgU5sjwqaQD9E4+IqNb8tbgrUB0MB0GA1UdDgQWBBQPqfe+mwOat/lNcmAv7+YbmtbjIzAOBgNVHQ8BAf8EBAMCBkAwFQYDVR0gBA4wDDAKBghghEIBGgEDAjCBpQYDVR0fBIGdMIGaMC+gLaArhilodHRwOi8vY3JsLmJ1eXBhc3Mubm8vY3JsL0JQQ2xhc3MzQ0ExLmNybDBnoGWgY4ZhbGRhcDovL2xkYXAuYnV5cGFzcy5uby9kYz1CdXlwYXNzLGRjPU5PLENOPUJ1eXBhc3MlMjBDbGFzcyUyMDMlMjBDQSUyMDE/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDBDBggrBgEFBQcBAQQ3MDUwMwYIKwYBBQUHMAGGJ2h0dHA6Ly9vY3NwLmJ1eXBhc3Mubm8vb2NzcC9CUENsYXNzM0NBMTANBgkqhkiG9w0BAQUFAAOCAQEAfWAYIahRE6jKXn12i3Xy6l8oucrhnpa26y1Y3tNlJhIB7iKtOtd0aoGsfD7EpqSEE9btZBMY2FOz3HeiJkdavBaNrw4EO7oINk6TzbQqHv3YVIGTXIDST8CkYtoov6iZw0XB9d02NE3xnrZqGyNt0PL9wtFst5GtXYTK7do+JfeaWls72F/syp+D9cM6RURMgaq9TYBVBnaMmUJVVJ5i/OSe4WpC19etDocJ4jBT4a36EvBa2OH6ar8IMtLAS95tCh7TH0Le6omPUrD2UKeCGDkj678ILWUFUB+ra1H8MlGGNfE7FXV1/tJs99bXyI578HdY4rWnDAHYMua3Laypxg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "deps/cl345/test/certs.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Certificate Handling Test Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2013\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* Certificate times.  Note that this value must be greater than the value\n   defined by the kernel as MIN_TIME_VALUE, the minimum allowable \n   (backdated) timestamp value.\n\n   Unlike every other system on the planet, the Mac Classic takes the time_t \n   epoch as 1904 rather than 1970 (even VMS, MVS, VM/CMS, the AS/400, Tandem \n   NSK, and God knows what other sort of strangeness stick to 1970 as the \n   time_t epoch) so we have to add an offset of 2082844800L to adjust for \n   this.  ANSI and ISO C are very careful to avoid specifying what the epoch \n   actually is, so it's legal to do this in the same way that it's legal for \n   Microsoft to break Kerberos because the standard doesn't say they can't */\n\n#define ONE_YEAR_TIME\t( 365 * 86400L )\n#if defined( __MWERKS__ ) || defined( SYMANTEC_C ) || defined( __MRC__ )\n  #define CERTTIME_DATETEST\t( ( ( 2019 - 1970 ) * ONE_YEAR_TIME ) + 2082844800L )\n#else\n  #define CERTTIME_DATETEST\t( ( 2019 - 1970 ) * ONE_YEAR_TIME )\n#endif /* Macintosh-specific weird epoch */\n#include \"misc/consts.h\"\n#if defined( _MSC_VER )\n  /* The following must be on a separate line since some compilers can't \n     evaluate it in the preprocessor */\n  #if CERTTIME_DATETEST <= MIN_TIME_VALUE \n\t#error CERTTIME_DATETEST must be > MIN_TIME_VALUE\n  #endif /* CERTTIME_DATETEST <= MIN_TIME_VALUE */\n#endif /* Safety check of time test value against MIN_TIME_VALUE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set the trust setting for the root CA in a certificate chain.  This is \n   required for the self-test in order to allow signature checks for chains \n   signed by arbitrary CAs to work */\n\nint setRootTrust( const CRYPT_CERTIFICATE cryptCertChain,\n\t\t\t\t  BOOLEAN *oldTrustValue, const BOOLEAN newTrustValue )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\tCRYPT_CURSOR_LAST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( oldTrustValue != NULL )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptCertChain, \n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t\t\t\t\toldTrustValue );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\treturn( cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t\t\t   newTrustValue ) );\n\t}\n\n/* Export a certificate in a given format and make sure that the resulting \n   size is consistent with the calculated size */\n\nstatic int checkExportCert( const CRYPT_CERTIFICATE cryptCert,\n\t\t\t\t\t\t\tconst BOOLEAN isCertChain,\n\t\t\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE format,\n\t\t\t\t\t\t\tconst C_STR formatDescription )\n\t{\n\tBYTE buffer[ 4096 ];\n\tint size, status;\n\n\tstatus = cryptExportCert( NULL, 0, &size, format, cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptExportCert( buffer, size, &size, format, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate%s export in %s format failed\\n  \"\n\t\t\t\t \"with status %d, line %d.\\n\", isCertChain ? \" chain\" : \"\", \n\t\t\t\t formatDescription, status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCertificate Creation Routines Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nBYTE certBuffer[ BUFFER_SIZE ];\n\n/* Create a series of self-signed certs */\n\nstatic const CERT_DATA certData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Self-signed X.509v3 certificate (technically it'd be an X.509v1, but\n\t   cryptlib automatically adds some required standard attributes so it\n\t   becomes an X.509v3 certificate) */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testBasicCert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength, value, status;\n\n#if defined( _MSC_VER ) && ( _MSC_VER <= 800 )\n\ttime_t testTime = time( NULL ), newTime;\n\n\tnewTime = mktime( localtime( &testTime ) );\n\tif( newTime == testTime )\n\t\t{\n\t\tputs( \"Illogical local/GMT time detected.  VC++ 1.5x occasionally \"\n\t\t\t  \"exhibits a bug in\\nits time zone handling in which it thinks \"\n\t\t\t  \"that the local time zone is GMT and\\nGMT itself is some \"\n\t\t\t  \"negative offset from the current time.  This upsets\\n\"\n\t\t\t  \"cryptlibs certificate date validity checking, since \"\n\t\t\t  \"certificates appear to\\nhave inconsistent dates.  Deleting \"\n\t\t\t  \"all the temporary files and rebuilding\\ncryptlib after \"\n\t\t\t  \"restarting your machine may fix this.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n#endif /* VC++ 1.5 bug check */\n\n\tfputs( \"Testing certificate creation/export...\\n\", outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, certData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Delete a component and replace it with something else */\n\tstatus = cryptDeleteAttribute( cryptCert, CRYPT_CERTINFO_COMMONNAME );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptDeleteAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptSetAttributeString( cryptCert,\n\t\t\t\tCRYPT_CERTINFO_COMMONNAME, TEXT( \"Dave Taylor\" ),\n\t\t\t\tparamStrlen( TEXT( \"Dave Taylor\" ) ) );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since it's self-signed, we don't need to pass in\n\t   a signature check key */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Set the certificate usage to untrusted for any purpose, which should \n\t   result in the signature check failing */\n\tcryptSetAttribute( cryptCert, CRYPT_CERTINFO_TRUSTED_USAGE,\n\t\t\t\t\t   CRYPT_KEYUSAGE_NONE );\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tputs( \"Untrusted certificate signature check succeeded, should \"\n\t\t\t  \"have failed.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDeleteAttribute( cryptCert, CRYPT_CERTINFO_TRUSTED_USAGE );\n\n\t/* Export the certificate.  We perform a length check using a null \n\t   buffer to make sure that this facility is working as required */\n\tstatus = cryptExportCert( NULL, 0, &value, CRYPT_CERTFORMAT_CERTIFICATE,\n\t\t\t\t\t\t\t  cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( value != certificateLength )\n\t\t{\n\t\tputs( \"Exported certificate size != actual data size.\" );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"cert\", certBuffer, certificateLength );\n\n\t/* Export the chain in the various text formats to make sure that each\n\t   one works correctly */\n\tif( !checkExportCert( cryptCert, FALSE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTIFICATE,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_TEXT_CERTIFICATE\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCert, FALSE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTCHAIN,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_TEXT_CERTCHAIN\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCert, FALSE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_XML_CERTIFICATE,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_XML_CERTIFICATE\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCert, FALSE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_XML_CERTCHAIN,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_XML_CERTCHAIN\" ) )\n\t\treturn( FALSE );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tint errorType, errorLocus;\n\n\t\tattrErrorExit( cryptCert, \"cryptCheckCert()\", status, __LINE__ );\n\t\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_ERRORTYPE,\n\t\t\t\t\t\t\t\t\t&errorType );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORLOCUS, \n\t\t\t\t\t\t\t\t\t\t&errorLocus );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\terrorType == CRYPT_ERRTYPE_CONSTRAINT && \\\n\t\t\terrorLocus == CRYPT_CERTINFO_VALIDFROM )\n\t\t\t{\n\t\t\tputs( \"  (If this test was run within +/- 12 hours of a \"\n\t\t\t\t  \"daylight savings time (DST)\\n   switchover then this is \"\n\t\t\t\t  \"a false positive caused by problems in\\n   performing \"\n\t\t\t\t  \"date calculations using the C standard libraries on days \"\n\t\t\t\t  \"that\\n   have 23 or 25 hours due to hours missing or \"\n\t\t\t\t  \"being repeated.  This problem\\n   will correct itself \"\n\t\t\t\t  \"once the time is more than 12 hours away from the DST\\n\"\n\t\t\t\t  \"   switchover, and only affects the certificate-creation \"\n\t\t\t\t  \"self-test).\" );\n\t\t\t}\n\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfputs( \"Certificate creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA cACertData[] = {\n\t/* Identification information.  Note the non-heirarchical order of the\n\t   components to test the automatic arranging of the DN */\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and CA\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Himself\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Certification Division\" ) },\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t/* Start date set to a fixed value to check for problems in date/time\n\t   conversion routines */\n\t{ CRYPT_CERTINFO_VALIDFROM, IS_TIME, 0, NULL, CERTTIME_DATETEST },\n\n\t/* CA extensions.  Policies are very much CA-specific and currently\n\t   undefined, so we use a dummy OID for a nonexistant private org for\n\t   now */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_PATHLENCONSTRAINT, IS_NUMERIC, 0 },\n\t{ CRYPT_CERTINFO_CERTPOLICYID, IS_STRING, 0, TEXT( \"1 3 6 1 4 1 9999 1\" ) },\n\t\t/* Blank line needed due to bug in Borland C++ parser */\n\t{ CRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT, IS_STRING, 0, TEXT( \"This policy isn't worth the paper it's not printed on.\" ) },\n\t{ CRYPT_CERTINFO_CERTPOLICY_ORGANIZATION, IS_STRING, 0, TEXT( \"Honest Joe's used cars and certification authority\" ) },\n\t{ CRYPT_CERTINFO_CERTPOLICY_NOTICENUMBERS, IS_NUMERIC, 1 },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testCACert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tconst time_t invalidStartTime = MIN_TIME_VALUE; \n\tconst time_t invalidEndTime = MAX_TIME_VALUE;\n\ttime_t startTime, endTime DUMMY_INIT;\n\tint certificateLength, value, status;\n\n\tfputs( \"Testing CA certificate creation/export...\\n\", outputStream );\n\n\t/* The following check has to be in C code rather than as a #ifdef \n\t   because CERTTIME_DATETEST is calculated from __DATE__ and may not be\n\t   an expression that can be resolved by the preprocessor */\n\tif( CERTTIME_DATETEST <= MIN_TIME_VALUE )\n\t\t{\n\t\tfputs( \"Error: CERTTIME_DATETEST must be > MIN_TIME_VALUE.\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test the ability to handle conversion of 32 <-> 64-bit time_t \n\t   values in Win32 (but not Win64, where they're always 64-bit) */\n#if defined( __WINDOWS__ ) && defined( _WIN32 ) && defined( _MSC_VER ) && \\\n\t!defined( _M_X64 )\n\t{\n\tconst __int64 time64 = CERTTIME_DATETEST;\n\tconst unsigned int time32 = CERTTIME_DATETEST;\n\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &time64, sizeof( time64 ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptDeleteAttribute( cryptCert, CRYPT_CERTINFO_VALIDFROM );\n\t\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t\t  &time32, sizeof( time32 ) );\n\t\tcryptDeleteAttribute( cryptCert, CRYPT_CERTINFO_VALIDFROM );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Automatic 64 <-> 32-bit time_t correction failed, \"\n\t\t\t\t\"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\t}\n#endif /* Win32 with VC++ */\n\n\t/* Test the ability to reject invalid dates */\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &invalidStartTime, sizeof( time_t ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t\t  &invalidEndTime, sizeof( time_t ) );\n\t\t}\n\tif( status != CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\tprintf( \"Rejection of out-of-range time_t failed, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, cACertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate, this time with base64 encoding to make sure \n\t   that this works.  As before, we perform a length check using a null\n\t   buffer to make sure that this facility is working as required */\n\tstatus = cryptExportCert( NULL, 0, &value,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTIFICATE, cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTIFICATE, cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( value != certificateLength )\n\t\t{\n\t\tputs( \"Exported certificate size != actual data size.\" );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"cacert\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created.  We make the second\n\t   parameter to the check function the certificate (rather than \n\t   CRYPT_UNUSED as done for the basic self-signed certificate) to check \n\t   that this option works as required, and then retry with CRYPT_UNUSED \n\t   to check the other possibility (although it's already been checked in \n\t   the basic certificate above) */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &startTime, &value );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDTO,\n\t\t\t\t\t\t\t\t\t\t  &endTime, &value );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Certificate time read failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( startTime != CERTTIME_DATETEST )\n\t\t{\n\t\tprintf( \"Warning: Certificate start time is wrong, got \" \n\t\t\t\tTIMET_FORMAT \", should be %lX.\\n         This is probably \"\n\t\t\t\t\"due to problems in the system time handling routines.\\n\",\n\t\t\t\tstartTime, CERTTIME_DATETEST );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n#if defined( __WINDOWS__ ) || defined( __linux__ ) || defined( sun )\n\tif( ( startTime != CERTTIME_DATETEST && \\\n\t\t  ( startTime - CERTTIME_DATETEST != 3600 && \\\n\t\t\tstartTime - CERTTIME_DATETEST != -3600 ) ) )\n\t\t{\n\t\t/* If the time is off by exactly one hour this isn't a problem\n\t\t   because the best we can do is get the time adjusted for DST\n\t\t   now rather than DST when the certificate was created, a problem \n\t\t   that is more or less undecidable.  In addition we don't \n\t\t   automatically abort for arbitrary systems since date problems \n\t\t   usually arise from incorrectly configured time zone info or bugs \n\t\t   in the system date-handling routines or who knows what, aborting \n\t\t   on every random broken system would lead to a flood of \n\t\t   unnecessary \"bug\" reports */\n\t\treturn( FALSE );\n\t\t}\n#endif /* System with known-good time handling */\n\n\t/* Clean up */\n\tfputs( \"CA certificate creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA xyzzyCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* XYZZY certificate */\n\t{ CRYPT_CERTINFO_XYZZY, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic int xyzzyCert( const BOOLEAN useAltAlgo )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength, status;\n\n\tfprintf( outputStream, \"Testing %sXYZZY certificate creation/export...\\n\",\n\t\t\t useAltAlgo ? \"DSA \" : \"\" );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( useAltAlgo )\n\t\t{\n\t\tif( !loadDSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, xyzzyCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since it's self-signed, we don't need to pass in\n\t   a signature check key */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( useAltAlgo ? \"certxyd\" : \"certxy\", certBuffer, \n\t\t\t   certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfprintf( outputStream, \"%sXYZZY certificate creation succeeded.\\n\\n\",\n\t\t\t useAltAlgo ? \"DSA \" : \"\" );\n\treturn( TRUE );\n\t}\n\nint testXyzzyCert( void )\n\t{\n\tif( !xyzzyCert( FALSE ) )\n\t\treturn( FALSE );\n\treturn( xyzzyCert( TRUE ) );\n\t}\n\n#ifdef HAS_WIDECHAR\n\nstatic const wchar_t unicodeStr[] = {\n\t0x0414, 0x043E, 0x0432, 0x0435, 0x0440, 0x044F, 0x0439, 0x002C,\n\t0x0020, 0x043D, 0x043E, 0x0020, 0x043F, 0x0440, 0x043E, 0x0432,\n\t0x0435, 0x0440, 0x044F, 0x0439, 0x0000 };\nstatic const wchar_t unicode2Str[] = {\n\t0x004D, 0x0061, 0x0072, 0x0074, 0x0069, 0x006E, 0x0061, 0x0020,\n\t0x0160, 0x0069, 0x006B, 0x006F, 0x0076, 0x006E, 0x00E1, 0x0000 };\n#ifdef __UNIX__\t\t/* Only enabled for native-UTF8 environments */\n  #if 0\t\t\t\t/* Original form of the UTF string below */\nstatic const BYTE utf8OriginalStr[] = {\n\t0xC3, 0x98, 0xC3, 0x86, 0xC3, 0x85, 0xC3, 0xA6, 0xC3, 0xB8, 0xC3, \n\t0xA5, 0x00 };\n  #endif /* 0 */\nstatic const BYTE utf8EncodedStr[] = {\n\t0xC3, 0x83, 0xCB, 0x9C, 0xC3, 0x83, 0xE2, 0x80, 0xA0, 0xC3, 0x83, \n\t0xE2, 0x80, 0xA6, 0xC3, 0x83, 0xC2, 0xA6, 0xC3, 0x83, 0xC2, 0xB8, \n\t0xC3, 0x83, 0xC2, 0xA5, 0x00 };\n#endif /* __UNIX__ */\n\nstatic const CERT_DATA textStringCertData[] = {\n\t/* Identification information: A latin-1 string, an obviously Unicode \n\t   string, a less-obviously Unicode string (only the 0x160 value is \n\t   larger than 8 bits), an ASCII-in-Unicode string, and an ASCII \n\t   string */\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Hrr sterix\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_WCSTRING, 0, unicodeStr },\n\t{ CRYPT_CERTINFO_LOCALITYNAME, IS_WCSTRING, 0, unicode2Str },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_WCSTRING, 0, L\"Dave's Unicode-aware CA with very long string\" },\n#ifdef __UNIX__\n\t{ CRYPT_CERTINFO_STATEORPROVINCENAME, IS_STRING, 0, utf8EncodedStr },\n#endif /* __UNIX__ */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"GB\" ) },\n\n\t/* Another XYZZY certificate */\n\t{ CRYPT_CERTINFO_XYZZY, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testTextStringCert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength, i, status;\n\n\tfputs( \"Testing complex string type certificate creation/export...\\n\", \n\t\t   outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, textStringCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since it's self-signed, we don't need to pass in\n\t   a signature check key */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\",\n\t\t\t certificateLength );\n\tdebugDump( \"certstr\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Make sure that we can read back what we've written and that it was\n\t   correctly converted back to the original string value */\n\tfor( i = 0; textStringCertData[ i ].type != CRYPT_CERTINFO_XYZZY; i++ )\n\t\t{\n\t\tconst CRYPT_ATTRIBUTE_TYPE attribute = textStringCertData[ i ].type;\n\t\tBYTE buffer[ 256 ];\n\t\tint length;\n\n\t\tstatus = cryptGetAttributeString( cryptCert, attribute, buffer, \n\t\t\t\t\t\t\t\t\t\t  &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Attempt to read back DN value %d failed with error \"\n\t\t\t\t\t\"code %d, line %d.\\n\", attribute, status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( textStringCertData[ i ].componentType == IS_WCSTRING )\n\t\t\t{\n#ifdef HAS_WIDECHAR\n\t\t\tconst int wstrLen = wcslen( textStringCertData[ i ].stringValue ) * \\\n\t\t\t\t\t\t\t\tsizeof( wchar_t );\n\t\t\tif( wstrLen != length || \\\n\t\t\t\tmemcmp( buffer, textStringCertData[ i ].stringValue, length ) )\n\t\t\t\t{\n\t\t\t\tif( attribute == CRYPT_CERTINFO_ORGANIZATIONNAME )\n\t\t\t\t\t{\n\t\t\t\t\t/* This is an ASCII string disguised as Unicode, which \n\t\t\t\t\t   cryptlib correctly canonicalises back to ASCII */\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\tprintf( \"Widechar DN value %d read from certificate with value\\n\", \n\t\t\t\t\t\tattribute );\n\t\t\t\tprintHex( \"  \", buffer, length );\n\t\t\t\tprintf( \"doesn't match value\\n\" );\n\t\t\t\tprintHex( \"  \", textStringCertData[ i ].stringValue, wstrLen );\n\t\t\t\tprintf( \"that was written, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n#endif /* HAS_WIDECHAR */\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tconst int strLen = paramStrlen( textStringCertData[ i ].stringValue );\n\t\t\tif( strLen != length || \\\n\t\t\t\tmemcmp( buffer, textStringCertData[ i ].stringValue, length ) )\n\t\t\t\t{\n\t\t\t\tif( attribute == CRYPT_CERTINFO_STATEORPROVINCENAME )\n\t\t\t\t\t{\n\t\t\t\t\t/* This is a UTF8 string that cryptlib canonicalises into\n\t\t\t\t\t   Unicode (since there's no way to tell what the host\n\t\t\t\t\t   system uses as its native 8-bit character system) so \n\t\t\t\t\t   the encoded form as read doesn't match what's \n\t\t\t\t\t   written */\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\tprintf( \"DN value %d read from certificate with value\\n\", \n\t\t\t\t\t\tattribute );\n\t\t\t\tprintHex( \"  \", buffer, length );\n\t\t\t\tprintf( \"doesn't match value\\n\" );\n\t\t\t\tprintHex( \"  \", textStringCertData[ i ].stringValue, strLen );\n\t\t\t\tprintf( \"that was written, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfputs( \"Complex string type certificate creation succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n#else\n\nint testTextStringCert( void )\n\t{\n\treturn( TRUE );\n\t}\n#endif /* Unicode-aware systems */\n\nstatic const CERT_DATA complexCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"US\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and Netscape CA\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"SSL Certificates\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Robert';DROP TABLE certificates;--\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dean@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"drew@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"donn@wetas-r-us.com\" ) },\t/* Multiple email addresses */\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Oddball altName components.  Note that the otherName.value must be a\n\t   DER-encoded ASN.1 object */\n\t{ CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER, IS_STRING, 0, TEXT( \"EDI Name Assigner\" ) },\n\t{ CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME, IS_STRING, 0, TEXT( \"EDI Party Name\" ) },\n\t{ CRYPT_CERTINFO_OTHERNAME_TYPEID, IS_STRING, 0, TEXT( \"1 3 6 1 4 1 9999 2\" ) },\n\t{ CRYPT_CERTINFO_OTHERNAME_VALUE, IS_STRING, 10, \"\\x04\\x08\" \"12345678\" },\n\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t/* Path constraint */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_EXCLUDEDSUBTREES },\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"CZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Brother's CA\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"SSL Certificates\" ) },\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* CRL distribution points */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_CRLDIST_FULLNAME },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.revocations.com/crls/\" ) },\n\n\t/* SubjectInfoAccess */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTINFO_CAREPOSITORY },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://192.168.1.1:8080/timesheet.asp?userid=1234;DROP%20TABLE%20USERS\" ) },\n\n#ifdef USE_CERT_OBSOLETE\n\t/* Add a vendor-specific extension, in this case a Thawte strong extranet\n\t   extension */\n\t{ CRYPT_CERTINFO_STRONGEXTRANET_ZONE, IS_NUMERIC, 0x99 },\n\t{ CRYPT_CERTINFO_STRONGEXTRANET_ID, IS_STRING, 0, TEXT( \"EXTRA1\" ) },\n#endif /* USE_CERT_OBSOLETE */\n\n#ifdef USE_CERTLEVEL_PKIX_PARTIAL\n\t/* Misc funnies */\n\t{ CRYPT_CERTINFO_OCSP_NOCHECK, IS_NUMERIC, CRYPT_UNUSED },\n#endif /* USE_CERTLEVEL_PKIX_PARTIAL */\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testComplexCert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tC_CHR buffer1[ 64 ], buffer2[ 64 ];\n\tint certificateLength, length1 DUMMY_INIT, length2 DUMMY_INIT;\n\tint status;\n\n\tfputs( \"Testing complex certificate creation/export...\\n\", \n\t\t   outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, complexCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Add an OID, read it back, and make sure that the OID en/decoding \n\t   worked correctly */\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\t\t\t\t  TEXT( \"1 2 3 4 5\" ), \n\t\t\t\t\t\t\t\t\t  paramStrlen( TEXT( \"1 2 3 4 5\" ) ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CERTPOLICYID, \n\t\t\t\t\t\t\t\t\t\t  buffer1, &length1 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptDeleteAttribute( cryptCert, CRYPT_CERTINFO_CERTPOLICYID );\n\tif( cryptStatusOK( status ) && \\\n\t\t( length1 != ( int ) paramStrlen( TEXT( \"1 2 3 4 5\" ) ) || \\\n\t\t  memcmp( buffer1, TEXT( \"1 2 3 4 5\" ), length1 ) ) )\n\t\t{\n\t\tprintf( \"Error in OID en/decoding, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add a non-CA basicConstraint, delete it, and re-add it as CA\n\t   constraint */\n\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CA, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tstatus = cryptDeleteAttribute( cryptCert,\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_BASICCONSTRAINTS );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptDeleteAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CA, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Add a disabled attribute and make sure that it's detected.  This can \n\t   be done in one of two ways, either directly by the kernel with a \n\t   permission error or by the certificate-processing code with a not-\n\t   available error if we go in indirectly, for example using the \n\t   attribute cursor */\n#ifndef USE_CERT_OBSOLETE\n\tstatus = cryptSetAttribute( cryptCert, \n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_STRONGEXTRANET_ZONE, 1 );\n\tif( status != CRYPT_ERROR_PARAM2 )\n\t\t{\n\t\tprintf( \"Addition of disabled attribute %d wasn't detected, \"\n\t\t\t\t\"line %d.\\n\", CRYPT_CERTINFO_STRONGEXTRANET_ZONE, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_CERT_OBSOLETE */\n#ifndef USE_CERTLEVEL_PKIX_FULL\n\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT, \n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_EXCLUDEDSUBTREES );\n\tif( status != CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\tprintf( \"Indirect addition of disabled attribute %d wasn't \"\n\t\t\t\t\"detected, line %d.\\n\", CRYPT_CERTINFO_EXCLUDEDSUBTREES, \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that GeneralName component selection is working properly */\n\tcryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME );\n\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_RFC822NAME, buffer1, &length1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_RFC822NAME, buffer2, &length2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Attempt to read and re-read email address failed, line \"\n\t\t\t\t\"%d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifdef UNICODE_STRINGS\n\tbuffer1[ length1 / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\tbuffer2[ length2 / sizeof( wchar_t ) ] = TEXT( '\\0' );\n#else\n\tbuffer1[ length1 ] = '\\0';\n\tbuffer2[ length2 ] = '\\0';\n#endif /* UNICODE_STRINGS */\n\tif( ( length1 != ( int ) paramStrlen( TEXT( \"dave@wetas-r-us.com\" ) ) ) || \\\n\t\t( length1 != length2 ) || \\\n\t\tmemcmp( buffer1, TEXT( \"dave@wetas-r-us.com\" ), length1 ) || \\\n\t\tmemcmp( buffer2, TEXT( \"dave@wetas-r-us.com\" ), length2 ) )\n\t\t{\n\t\tprintf( \"Email address on read #1 = '%s',\\n  read #2 = '%s', should \"\n\t\t\t\t\"have been '%s', line %d.\\n\", buffer1, buffer2,\n\t\t\t\t\"dave@wetas-r-us.com\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certc\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfputs( \"Complex certificate creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA altnameCertData1[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"US\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Subject O\" ) },\n\n\t/* Subject altName in the middle of the subjectName.  We add two\n\t   attributes, the first to check the imlicit creation and selection of \n\t   the altName, the second to check its implicit selection */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Subject OU\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Subject CN\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA altnameCertData2[] = {\n\t/* Identification information for subject DN */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"US\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Subject O\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Subject OU\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Subject CN\" ) },\n\n\t/* Select altName DN */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTALTNAME },\n\n\t/* Identification information for altName DN */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"US\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Altname O\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Altname OU\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Altname CN\" ) },\n\n\t/* Select subject DN */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t/* Back to an altName, implicitly selected */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\n\t/* Subject DN value again */\n\t{ CRYPT_CERTINFO_LOCALITYNAME, IS_STRING, 0, TEXT( \"Subject L\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA altnameCertData3[] = {\n\t/* Straight to the altName as the first attribute */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"US\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Subject O\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Subject OU\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Subject CN\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic int testAltnameHandling( const CERT_DATA *altnameCertData,\n\t\t\t\t\t\t\t\tconst char *fileName )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength, status;\n\n\tfputs( \"Testing automatic handling of certificate altnames...\\n\", \n\t\t   outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, altnameCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( fileName, certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tfputs( \"Certificate altname handling succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testAltnameCert( void )\n\t{\n\tif( !testAltnameHandling( altnameCertData1, \"certalt1\" ) )\n\t\treturn( FALSE );\n\tif( !testAltnameHandling( altnameCertData2, \"certalt2\" ) )\n\t\treturn( FALSE );\n\tif( !testAltnameHandling( altnameCertData3, \"certalt3\" ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\nint testCertExtension( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tBYTE buffer[ 16 ];\n\tconst char *extensionData = \"\\x0C\\x04Test\";\n\tint certificateLength, value, length, status;\n\n\tfputs( \"Testing certificate with nonstd.extension creation/export...\\n\",\n\t\t   outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CA, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, certData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Add a nonstandard critical extension */\n\tstatus = cryptAddCertExtension( cryptCert, \"1.2.3.4.5\", TRUE, extensionData, 6 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptAddCertExtension()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Sign the certificate.  Since we're adding a nonstandard extension we\n\t   have to set the CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES flag to\n\t   make sure that cryptlib will sign it */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t   CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, TRUE );\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tcryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t   CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate and make sure that we can read what we \n\t   created */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certext\", certBuffer, certificateLength );\n\tcryptDestroyCert( cryptCert );\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check the certificate.  Since it contains an unrecognised critical \n\t   extension it should be rejected, but accepted at a lowered compliance \n\t   level */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"Certificate with unrecognised critical extension was \"\n\t\t\t\t\"accepted when it should\\nhave been rejected, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL, &value );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_REDUCED );\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Read back the nonstandard extension and make sure that it's what we\n\t   originally wrote */\n\tstatus = cryptGetCertExtension( cryptCert, \"1.2.3.4.5\", &value, buffer,\n\t\t\t\t\t\t\t\t\t16, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptGetCertExtension()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( value != TRUE || length != 6 || memcmp( extensionData, buffer, 6 ) )\n\t\t{\n\t\tprintf( \"Recovered nonstandard extension data differs from what was \"\n\t\t\t\t\"written, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"Certificate with nonstd.extension creation succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testCustomDNCert( void )\n\t{\n#ifdef USE_CERT_DNSTRING\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tconst C_STR customDN = \\\n\t\t\t\tTEXT( \"cn=Dave Taylor + sn=12345, ou=Org.Unit 2\\\\=1, \" )\n\t\t\t\tTEXT( \"ou=Org.Unit 2, ou=Org.Unit 1, \" )\n\t\t\t\tTEXT( \"o=Dave's Big Organisation, c=PT\" );\n\tconst C_STR invalidDnStrings[] = {\n\t\tTEXT( \"abc\\x01\\x64\" ) TEXT( \"def\" ),/* Invalid chars */\n\t\tTEXT( \"cn=\" ),\t\t\t\t/* No value */\n\t\tTEXT( \"cn=\\\\\" ),\t\t\t/* No escaped char */\n\t\tTEXT( \"c\\\\n=x\" ),\t\t\t/* Escape in type */\n\t\tTEXT( \"cn+x\" ),\t\t\t\t/* Spurious '+' */\n\t\tTEXT( \"cn,x\" ),\t\t\t\t/* Spurious ',' */\n\t\tTEXT( \"cn=z=y\" ),\t\t\t/* Spurious '=' */\n\t\tTEXT( \"cn=x,\" ),\t\t\t/* Spurious ',' */\n\t\tTEXT( \"xyz=x\" ),\t\t\t/* Unknown type */\n\t\tNULL\n\t\t};\n\tchar buffer[ BUFFER_SIZE ];\n\tint certificateLength, length, i, status;\n\n\tfputs( \"Testing certificate with custom DN creation/export...\\n\", \n\t\t   outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CA, TRUE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_SELFSIGNED, \n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Make sure that invalid DN strings are detected */\n\tfor( i = 0; invalidDnStrings[ i ] != NULL; i++ )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_DN,\n\t\t\t\t\t\t\t\t\t\t  invalidDnStrings[ i ], \n\t\t\t\t\t\t\t\t\t\t  paramStrlen( invalidDnStrings[ i ] ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tprintf( \"Addition of invalid DN string '%s' wasn't detected, \"\n\t\t\t\t\t\"line %d.\\n\", invalidDnStrings[ i ], __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Add the custom DN in string form */\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_DN,\n\t\t\t\t\t\t\t\t\t  customDN, paramStrlen( customDN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttributeString()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate and make sure that we can read what we \n\t   created */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certext\", certBuffer, certificateLength );\n\tcryptDestroyCert( cryptCert );\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Read back the custom DN and make sure that it's what we originally\n\t   wrote */\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_DN,\n\t\t\t\t\t\t\t\t\t  buffer, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptGetAttributeString()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( length != ( int ) paramStrlen( customDN ) || \\\n\t\tmemcmp( customDN, buffer, length ) )\n\t\t{\n\t\tprintf( \"Recovered custom DN differs from what was written, line \"\n\t\t\t\t\"%d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"Certificate with custom DN creation succeeded.\\n\\n\", \n\t\t   outputStream );\n#else\n\tfputs( \"Skipping custom DN certificate creation/export test because \"\n\t\t   \"support for\\nthis capability has been disabled via the cryptlib \"\n\t\t   \"config options.\\n\\n\", outputStream );\n#endif /* USE_CERT_DNSTRING */\n\treturn( TRUE );\n\t}\n\nint testCertAttributeHandling( void )\n\t{\n#ifdef USE_CERT_DNSTRING\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tconst C_STR customDN = \\\n\t\t\t\tTEXT( \"cn=Dave Taylor, ou=Org.Unit 3, ou=Org.Unit 2, \" )\n\t\t\t\tTEXT( \"ou=Org.Unit 1, o=Dave's Big Organisation, c=PT\" );\n\tconst C_STR email = TEXT( \"dave@example.com\" );\n\tconst char *errorString = \"(Generic attribute get/set/select error)\";\n\tchar buffer[ BUFFER_SIZE ];\n\tint length, value, status;\n\n\tfputs( \"Testing certificate attribute handling...\\n\", outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_CERTINFO_SELFSIGNED, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Add the custom DN in string form and an altName component */\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_DN,\n\t\t\t\t\t\t\t\t\t  customDN, paramStrlen( customDN ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t\t  email, paramStrlen( email ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttributeString()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Sign the certificate */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\n\t/* Make sure that the attribute-manipulation routines work as \n\t   intended */\n\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tvalue != CRYPT_CERTINFO_SUBJECTALTNAME )\n\t\t\t{\n\t\t\terrorString = \"Current attribute != subject altName after \"\n\t\t\t\t\t\t  \"subject altName was selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Fetch of email address from altName failed\";\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Should fail since we've now selected the DN in the altName */\n\t\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorString = \"OU was returned after altName was selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\telse\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"%s, line %d.\\n\", errorString, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTNAME );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tvalue != CRYPT_CERTINFO_SUBJECTNAME )\n\t\t\t{\n\t\t\terrorString = \"Current attribute != subject DN after subject DN \"\n\t\t\t\t\t\t  \"was selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\t}\n#if 0\t/* The following should in theory fail but doesn't because of the \n\t\t   auto-selection of the subject altName when no other GeneralName \n\t\t   is selected.  This is required in order for reads of commonly-\n\t\t   used fields like email addresses to work without the user having\n\t\t   to explicitly select the subject altName (which they're likely\n\t\t   unaware of) first.  This result is slightly non-orthogonal, but \n\t\t   given the choice of enforcing strict orthogonality in a facility\n\t\t   that most users will never use vs. making something that's widely\n\t\t   used work as expected, the latter is the preferable option */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Should fail since the subject DN is the currently selected \n\t\t   attribute */\n\t\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorString = \"email from altName was returned after subject DN was selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\telse\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n#endif /* 0 */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Fetch of first OU failed\";\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Should fail since there's no current attribute */\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorString = \"CURSOR_NEXT succeeded when no attribute selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\telse\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Should fail since there's no attribute instance selected */\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorString = \"CURSOR_NEXT succeeded when no attribute instance selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\telse\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"%s, line %d.\\n\", errorString, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t  buffer, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ORGANISATIONALUNITNAME );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tvalue != CRYPT_CERTINFO_ORGANISATIONALUNITNAME )\n\t\t\t{\n\t\t\terrorString = \"Current instance != OU after OU was selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Should fail since there's no current attribute */\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorString = \"CURSOR_NEXT succeeded when no attribute selected\";\n\t\t\tstatus = -1;\n\t\t\t}\n\t\telse\n\t\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_NEXT );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Move to second OU failed\";\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Fetch of second OU failed\";\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t\tCRYPT_CURSOR_LAST );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Move to last (third) OU failed\";\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\terrorString = \"Fetch of third OU failed\";\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"%s, line %d.\\n\", errorString, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tfputs( \"Certificate attribute handling succeeded.\\n\\n\", outputStream );\n#else\n\tfputs( \"Skipping certificate attribute handling test because support \"\n\t\t   \"for the\\nrequired custom DN creation has been disabled via the \"\n\t\t   \"cryptlib config\\noptions.\\n\\n\", outputStream );\n#endif /* USE_CERT_DNSTRING */\n\treturn( TRUE );\n\t}\n\n#ifdef USE_CERT_OBSOLETE\n\nstatic const CERT_DATA setCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and Temple of SET\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"SET Commerce Division\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Cousin Bob\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t/* Add the SET extensions */\n\t{ CRYPT_CERTINFO_SET_CERTIFICATETYPE, IS_NUMERIC, CRYPT_SET_CERTTYPE_RCA },\n\t{ CRYPT_CERTINFO_SET_CERTCARDREQUIRED, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_SET_ROOTKEYTHUMBPRINT, IS_STRING, 20, TEXT( \"12345678900987654321\" ) },\n\t{ CRYPT_CERTINFO_SET_MERID, IS_STRING, 0, TEXT( \"Wetaburger Vendor\" ) },\n\t{ CRYPT_CERTINFO_SET_MERACQUIRERBIN, IS_STRING, 0, TEXT( \"123456\" ) },\n\t{ CRYPT_CERTINFO_SET_MERCHANTLANGUAGE, IS_STRING, 0, TEXT( \"English\" ) },\n\t{ CRYPT_CERTINFO_SET_MERCHANTNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and SET Merchant\" ) },\n\t{ CRYPT_CERTINFO_SET_MERCHANTCITY, IS_STRING, 0, TEXT( \"Eketahuna\" ) },\n\t{ CRYPT_CERTINFO_SET_MERCHANTCOUNTRYNAME, IS_STRING, 0, TEXT( \"New Zealand\" ) },\n\t{ CRYPT_CERTINFO_SET_MERCOUNTRY, IS_NUMERIC, 554 },\t\t/* ISO 3166 */\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n#endif /* USE_CERT_DNSTRING */\n\nint testSETCert( void )\n\t{\n#ifdef USE_CERT_OBSOLETE\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint status;\n\n\tfputs( \"Testing SET certificate creation/export...\\n\", outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, setCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certset\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tfputs( \"SET certificate creation succeeded.\\n\\n\", outputStream );\n#else\n\tfputs( \"Skipping SET certificate creation/export test because support \"\n\t\t   \"for this\\ncertificate type has been disabled via the cryptlib \"\n\t\t   \"config options.\\n\\n\", outputStream );\n#endif /* USE_CERT_OBSOLETE */\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA attributeCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NI\" ) },\t\t/* Ni! Ni! Ni! */\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and Attributes\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Attribute Management\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Mum\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nint testAttributeCert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT cryptAuthorityKey;\n\tint certificateLength, status;\n\n\tfputs( \"Testing attribute certificate creation/export...\\n\", \n\t\t   outputStream );\n\n\t/* Get the authority's private key */\n\tstatus = getPrivateKey( &cryptAuthorityKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Authority private key read failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certificate */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_ATTRIBUTE_CERT );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certificate components.  We don't add any attributes because \n\t   these hadn't been defined yet (at least not as of the JTC1 SC21/ITU-T \n\t   Q.17/7 draft of July 1997) */\n\tif( !addCertFields( cryptCert, attributeCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certificate and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, cryptAuthorityKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certattr\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCert, cryptAuthorityKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptAuthorityKey );\n\tfputs( \"Attribute certificate creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test certification request code.  These create a basic certificate \n   request, a more complex certificate request with all extensions encoded \n   as attributes of an extensionReq, and a request with a separate PKCS #9\n   attribute alongside the other attributes in the extensionReq */\n\nstatic const CERT_DATA certRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"PT\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA complexCertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t/* SSL server and client authentication */\n\t{ CRYPT_CERTINFO_EXTKEY_SERVERAUTH, IS_NUMERIC, CRYPT_UNUSED },\n\t{ CRYPT_CERTINFO_EXTKEY_CLIENTAUTH, IS_NUMERIC, CRYPT_UNUSED },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA certRequestAttrib1Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"PT\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Subject altName encoded as an extensionReq */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA certRequestAttrib2Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"PT\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* PKCS #9 attribute that isn't encoded as an extensionReq */\n\t{ CRYPT_CERTINFO_CHALLENGEPASSWORD, IS_STRING, 0, TEXT( \"password\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA certRequestAttrib3Data[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"PT\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\n\t/* Subject altName encoded as an extensionReq */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Re-select the subject name after poking around in the altName */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\n\n\t/* PKCS #9 attribute that isn't encoded as an extensionReq */\n\t{ CRYPT_CERTINFO_CHALLENGEPASSWORD, IS_STRING, 0, TEXT( \"password\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic int createRequest( void *certificateData, \n\t\t\t\t\t\t  const int certificateDataMaxSize, \n\t\t\t\t\t\t  int *certificateDataSize, \n\t\t\t\t\t\t  const BOOLEAN isCRMF,\n\t\t\t\t\t\t  const char *description, \n\t\t\t\t\t\t  const CERT_DATA *certInfo,\n\t\t\t\t\t\t  const CRYPT_CONTEXT pubKeyContext,\n\t\t\t\t\t\t  const CRYPT_CONTEXT privKeyContext,\n\t\t\t\t\t\t  const char *fileName )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tint dummy, status;\n\n\t/* Create the certificate object */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  isCRMF ? CRYPT_CERTTYPE_REQUEST_CERT : \\\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTTYPE_CERTREQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some certification request components */\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, certInfo, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Sign the certification request and print information on what we got */\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !printCertInfo( cryptCert ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since it's self-signed we don't need to pass in\n\t   a signature check key (but see further down for checks using a key).\n\t   Note that at this point there's no public-key object associated with \n\t   the request since it's a freshly-created object that's implicitly\n\t   signed, so the check merely checks the details on a known-OK object */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certificateData, certificateDataMaxSize,  \n\t\t\t\t\t\t\t  certificateDataSize, CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t  cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported %s is %d bytes long.\\n\", description, \n\t\t\t *certificateDataSize );\n\tdebugDump( fileName, certBuffer, *certificateDataSize );\n\n\t/* Make sure that an export in an illogical format is disallowed */\n\tstatus = cryptExportCert( NULL, 0, &dummy, CRYPT_CERTFORMAT_CERTCHAIN, \n\t\t\t\t\t\t\t  cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( NULL, 0, &dummy, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTCHAIN, \n\t\t\t\t\t\t\t\t  cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( NULL, 0, &dummy, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_XML_CERTCHAIN, \n\t\t\t\t\t\t\t\t  cryptCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"Attempt to export certificate request in illogical format \"\n\t\t\t\t\"succeeded when it\\n  should have failed, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int checkRequest( const void *certificateData, \n\t\t\t\t\t\t const int certificateDataSize, \n\t\t\t\t\t\t const CRYPT_CONTEXT pubKeyContext )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tint status;\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateDataSize, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check the signature on the request.  We do this twice, once with the\n\t   checking object given as CRYPT_UNUSED since it's a self-signed \n\t   object, the second time with the checking object explicitly \n\t   specified.  Since the request has been imported rather than being\n\t   a fresly-created known-good object, there's a public-key context\n\t   associated with it that can verify the signature.  In the case of the\n\t   explicitly-given public key object, this is checked against the public\n\t   key associated with the request */\n\tstatus = cryptCheckCert( cryptCert, CRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptCheckCert( cryptCert, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\treturn( TRUE );\n\t}\n\nstatic int createCertRequest( const char *description, \n\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t  const CERT_DATA *certInfo,\n\t\t\t\t\t\t\t  const char *fileName )\n\t{\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength;\n\n\tfprintf( outputStream, \"Testing %s creation/export...\\n\", description );\n\n\t/* Create the public/private key contexts */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, \n\t\t\t\t\t\t\t\t  &privKeyContext ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tif( !loadDSAContexts( CRYPT_UNUSED, &pubKeyContext, \n\t\t\t\t\t\t\t\t  &privKeyContext ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the request and export it */\n\tif( !createRequest( certBuffer, BUFFER_SIZE, &certificateLength, \n\t\t\t\t\t\tFALSE, description, certInfo, pubKeyContext, \n\t\t\t\t\t\tprivKeyContext, fileName ) )\n\t\treturn( FALSE );\n\n\t/* Check that the request can be recovered from the request data */\n\tif( !checkRequest( certBuffer, certificateLength, pubKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tfprintf( outputStream, \"Creation of %s succeeded.\\n\\n\", description );\n\treturn( TRUE );\n\t}\n\nint testCertRequest( void )\n\t{\n\tif( !createCertRequest( \"RSA certification request\", CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\tcertRequestData, \"certreqr\" ) )\n\t\treturn( FALSE );\n\treturn( createCertRequest( \"DSA certification request\", CRYPT_ALGO_DSA,\n\t\t\t\t\t\t\t   certRequestData, \"certreqd\" ) );\n\t}\n\nint testComplexCertRequest( void )\n\t{\n\treturn( createCertRequest( \"complex certification request\", \n\t\t\t\t\t\t\t   CRYPT_ALGO_RSA, complexCertRequestData,\n\t\t\t\t\t\t\t   \"certreqc\" ) );\n\t}\n\nint testCertRequestAttrib( void )\n\t{\n\tif( !createCertRequest( \"cert.request with non-encapsulated attributes\", \n\t\t\t\t\t\t\tCRYPT_ALGO_RSA, certRequestAttrib1Data, \n\t\t\t\t\t\t\t\"certreqa1\" ) )\n\t\treturn( FALSE );\t/* extReq attribute */\n\tif( !createCertRequest( \"cert.request with encapsulated attributes\", \n\t\t\t\t\t\t\tCRYPT_ALGO_RSA, certRequestAttrib2Data, \n\t\t\t\t\t\t\t\"certreqa2\" ) )\n\t\treturn( FALSE );\t/* Non-extReq attribute */\n\treturn( createCertRequest( \"cert.request with both types of attributes\", \n\t\t\t\t\t\t\t   CRYPT_ALGO_RSA, certRequestAttrib3Data, \n\t\t\t\t\t\t\t   \"certreqa3\" ) );\n\t}\t\t\t\t\t\t/* Both types of attributes */\n\n/* Test CRMF certification request code */\n\nstatic int crmfRequest( const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength;\n\n\tfprintf( outputStream, \"Testing CRMF %s certification request \"\n\t\t\t \"creation/export...\\n\",\n\t\t\t ( cryptAlgo == CRYPT_ALGO_DSA ) ? \"DSA\" : \\\n\t\t\t ( cryptAlgo == CRYPT_ALGO_ECDSA ) ? \"ECDSA\" : \"RSA\" );\n\n\t/* Create the en/decryption contexts */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tif( !loadDSAContexts( CRYPT_UNUSED, &pubKeyContext, \n\t\t\t\t\t\t\t\t  &privKeyContext ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tif( !loadECDSAContexts( CRYPT_UNUSED, &pubKeyContext, \n\t\t\t\t\t\t\t\t  &privKeyContext ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, \n\t\t\t\t\t\t\t\t  &privKeyContext ) )\n\t\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the request and export it */\n\tif( !createRequest( certBuffer, BUFFER_SIZE, &certificateLength, \n\t\t\t\t\t\tTRUE, \"certification request\", certRequestData, \n\t\t\t\t\t\tpubKeyContext, privKeyContext, \n\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_DSA ) ? \"req_crmf_d\" : \\\n\t\t\t\t\t\t( cryptAlgo == CRYPT_ALGO_ECDSA ) ? \"req_crmf_ec\" : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"req_crmf_r\" ) )\n\t\treturn( FALSE );\n\n\t/* Check that the request can be recovered from the request data */\n\tif( !checkRequest( certBuffer, certificateLength, pubKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tfputs( \"CRMF certification request creation succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testCRMFRequest( void )\n\t{\n\tif( !crmfRequest( CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\n\tif( !crmfRequest( CRYPT_ALGO_DSA ) )\n\t\treturn( FALSE );\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) != CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tif( !crmfRequest( CRYPT_ALGO_ECDSA ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testComplexCRMFRequest( void )\n\t{\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint certificateLength;\n\n\tfputs( \"Testing complex CRMF certification request \"\n\t\t   \"creation/export...\\n\", outputStream );\n\n\t/* Create the RSA en/decryption contexts */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the request and export it */\n\tif( !createRequest( certBuffer, BUFFER_SIZE, &certificateLength, \n\t\t\t\t\t\tTRUE, \"certification request\", complexCertRequestData, \n\t\t\t\t\t\tpubKeyContext, privKeyContext, \"req_crmfc\" ) )\n\t\treturn( FALSE );\n\n\t/* Check that the request can be recovered from the request data */\n\tif( !checkRequest( certBuffer, certificateLength, pubKeyContext ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tfputs( \"Complex CRMF certification request creation succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test CRL code.  This one represents a bit of a chicken-and-egg problem\n   since we need a CA certificate to create the CRL, but we can't read this \n   until the private key file read has been tested, and that requires \n   testing of the certificate management.  At the moment we just assume that \n   private key file reads work for this test */\n\nstatic int testCRLExt( const CRYPT_CONTEXT cryptCAKey,\n\t\t\t\t\t   const BOOLEAN hasEntries )\n\t{\n\tCRYPT_CERTIFICATE cryptCRL;\n\tint certificateLength, status;\n\n\tfprintf( outputStream, \"Testing %sCRL creation/export...\\n\", \n\t\t\t hasEntries ? \"\" : \"empty \" );\n\n\t/* Create the CRL */\n\tstatus = cryptCreateCert( &cryptCRL, CRYPT_UNUSED, CRYPT_CERTTYPE_CRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add a certificate to revoke if requires.  In this case the CA is \n\t   revoking its own key */\n\tif( hasEntries )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCRL, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tcryptCAKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptCRL, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t\t}\n\t\t}\n\n\t/* Sign the CRL */\n\tstatus = cryptSignCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCRL ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since we have the CA private key handy, we\n\t   use that to check the signature */\n\tstatus = cryptCheckCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Export the CRL */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported CRL is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( hasEntries ? \"crl1\" : \"crl0\", certBuffer, certificateLength );\n\n\t/* Destroy the CRL */\n\tstatus = cryptDestroyCert( cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCRL );\n\n\tfputs( \"CRL creation succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\nint testCRL( void )\n\t{\n\tCRYPT_CONTEXT cryptCAKey;\n\tint status;\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test CRL creation, first an emptry CRL, then one with a revoked \n\t   certificate */\n\tstatus = testCRLExt( cryptCAKey, FALSE );\n\tif( status )\n\t\tstatus = testCRLExt( cryptCAKey, TRUE );\n\n\tcryptDestroyContext( cryptCAKey );\n\n\t/* Clean up */\n\treturn( status );\n\t}\n\n/* Test complex CRL code */\n\nstatic const CERT_DATA complexCRLData[] = {\n\t/* Next update time */\n\t{ CRYPT_CERTINFO_NEXTUPDATE, IS_TIME, 0, NULL, CERTTIME_DATETEST + ONE_YEAR_TIME },\n\n\t/* CRL number and delta CRL indicator */\n\t{ CRYPT_CERTINFO_CRLNUMBER, IS_NUMERIC, 1 },\n\t{ CRYPT_CERTINFO_DELTACRLINDICATOR, IS_NUMERIC, 2 },\n\n\t/* Issuing distribution points */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_ISSUINGDIST_FULLNAME },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_ISSUINGDIST_USERCERTSONLY, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testComplexCRL( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCRL, cryptRevokeCert;\n\tCRYPT_CONTEXT cryptCAKey;\n\ttime_t revocationTime;\n\tint certificateLength, revocationReason DUMMY_INIT, dummy, status;\n\n\tfputs( \"Testing complex CRL creation/export...\\n\", outputStream );\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the CRL */\n\tstatus = cryptCreateCert( &cryptCRL, CRYPT_UNUSED, CRYPT_CERTTYPE_CRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some CRL components with per-entry attributes.  In this case the\n\t   CA is revoking its own key because it was compromised (would you trust\n\t   this CRL?) and some keys from test certs */\n\tif( !addCertFields( cryptCRL, complexCRLData, __LINE__ ) )\n\t\treturn( FALSE );\n\tstatus = cryptSetAttribute( cryptCRL, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\tcryptCAKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* The CA key was compromised */\n\t\tstatus = cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\tCRYPT_CRLREASON_CACOMPROMISE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptRevokeCert,\n\t\t\t\t\t\t\t\t\t\t CRLCERT_FILE_TEMPLATE, 1 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCRL, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tcryptRevokeCert );\n\t\tcryptDestroyCert( cryptRevokeCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Hold certificate, call issuer for details */\n\t\tstatus = cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\tCRYPT_CRLREASON_CERTIFICATEHOLD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t\tstatus = cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE,\n\t\t\t\t\t\t\t\t\t\tCRYPT_HOLDINSTRUCTION_CALLISSUER );\n#else\n\t\t\tstatus = cryptSetAttribute( cryptCRL, \n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE, \n\t\t\t\t\t\t\t\t\t\tCRYPT_HOLDINSTRUCTION_CALLISSUER );\n\t\t\tif( status != CRYPT_ERROR_PARAM2 )\n\t\t\t\t{\n\t\t\t\tprintf( \"Addition of disabled attribute %d wasn't \"\n\t\t\t\t\t\t\"detected, line %d.\\n\", \n\t\t\t\t\t\tCRYPT_CERTINFO_HOLDINSTRUCTIONCODE, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = CRYPT_OK;\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptSetAttribute(), certificate \"\n\t\t\t\t\t\t\t   \"#1\", status, __LINE__ ) );\n\t\t}\n\tstatus = importCertFromTemplate( &cryptRevokeCert,\n\t\t\t\t\t\t\t\t\t CRLCERT_FILE_TEMPLATE, 2 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCRL, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tcryptRevokeCert );\n\t\tcryptDestroyCert( cryptRevokeCert );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst time_t invalidityDate = CERTTIME_DATETEST - ( ONE_YEAR_TIME / 12 );\n\n\t\t/* The private key was invalid some time ago.  We can't go back too \n\t\t   far because the cryptlib kernel won't allow suspiciously old \n\t\t   dates */\n\t\tstatus = cryptSetAttributeString( cryptCRL,\n\t\t\t\t\tCRYPT_CERTINFO_INVALIDITYDATE, &invalidityDate,\n\t\t\t\t\tsizeof( time_t ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptSetAttribute(), certificate \"\n\t\t\t\t\t\t\t   \"#2\", status, __LINE__ ) );\n\t\t}\n\n\t/* Sign the CRL */\n\tstatus = cryptSignCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptCRL ) )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since we have the CA private key handy, we\n\t   use that to check the signature */\n\tstatus = cryptCheckCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Export the CRL */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported CRL is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"crlc\", certBuffer, certificateLength );\n\n\t/* Destroy the CRL */\n\tstatus = cryptDestroyCert( cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCRL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCheckCert( cryptCRL, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Check the newly-revoked CA key agains the CRL */\n\tstatus = cryptCheckCert( cryptCAKey, cryptCRL );\n\tif( status != CRYPT_ERROR_INVALID )\n\t\t{\n\t\tprintf( \"Revoked certificate wasn't reported as being revoked, \"\n\t\t\t\t\"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCRL, CRYPT_CERTINFO_REVOCATIONDATE,\n\t\t\t\t\t\t\t\t\t  &revocationTime, &dummy );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptCRL, CRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\t&revocationReason );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCRL, \"cryptGetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( revocationReason != CRYPT_CRLREASON_CACOMPROMISE )\n\t\t{\n\t\tprintf( \"Revocation reason was %d, should have been %d, line %d.\\n\",\n\t\t\t\trevocationReason, CRYPT_CRLREASON_CACOMPROMISE, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCRL );\n\tcryptDestroyContext( cryptCAKey );\n\tfputs( \"CRL creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test revocation request code */\n\nstatic const CERT_DATA revRequestData[] = {\n\t/* Revocation reason */\n\t{ CRYPT_CERTINFO_CRLREASON, IS_NUMERIC, CRYPT_CRLREASON_SUPERSEDED },\n\n\t/* Invalidity date */\n\t{ CRYPT_CERTINFO_INVALIDITYDATE, IS_TIME, 0, NULL, CERTTIME_DATETEST - ( ONE_YEAR_TIME / 12 ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testRevRequest( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert, cryptRequest;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count, status;\n\n\tfputs( \"Testing revocation request creation/export...\\n\", outputStream );\n\n\tfilenameFromTemplate( buffer, CERT_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't find certificate file for revocation request test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tstatus = cryptImportCert( buffer, count, CRYPT_UNUSED, &cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"Certificate import failed, skipping test of revocation \"\n\t\t\t   \"request...\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Create the certificate object and add the certificate details and\n\t   revocation info */\n\tstatus = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptRequest, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\tcryptCert );\n\tcryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptRequest, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptRequest, revRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptRequest ) )\n\t\treturn( FALSE );\n\n#if 0\t/* CMP doesn't currently allow revocation requests to be signed, so\n\t\t   it's treated like CMS attributes as a series of uninitialised\n\t\t   attributes */\n\t/* Export the certificate */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptRequest, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported revocation request is %d bytes \"\n\t\t\t \"long.\\n\", certificateLength );\n\tdebugDump( \"req_rev\", certBuffer, certificateLength );\n\n\t/* Destroy the certificate */\n\tstatus = cryptDestroyCert( cryptRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#endif /* 0 */\n\tcryptDestroyCert( cryptRequest );\n\n\t/* Clean up */\n\tfputs( \"Revocation request creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test certificate chain creation */\n\nstatic const CERT_DATA certRequestNoDNData[] = {\n\t/* Identification information for an empty-DN certificate.  There's no \n\t   DN, only a subject altName.  This type of identifier is only possible \n\t   with a CA-signed certificate since it contains an empty DN */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic int createChain( CRYPT_CERTIFICATE *cryptCertChain,\n\t\t\t\t\t\tconst CRYPT_CONTEXT cryptCAKey,\n\t\t\t\t\t\tconst BOOLEAN useEmptyDN, \n\t\t\t\t\t\tconst BOOLEAN createCAcert, \n\t\t\t\t\t\tconst BOOLEAN reportError )\n\t{\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tint status;\n\n\t/* Create the certificate chain */\n\tstatus = cryptCreateCert( cryptCertChain, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTCHAIN );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create a simple certificate request to turn into the end-user \n\t   certificate */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\tstatus = cryptSetAttribute( *cryptCertChain,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( !addCertFields( *cryptCertChain, useEmptyDN ? \\\n\t\t\t\t\t\t\tcertRequestNoDNData : certRequestData, \n\t\t\t\t\t\t\t__LINE__ ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( status ) && createCAcert )\n\t\t{\n\t\tstatus = cryptSetAttribute( *cryptCertChain,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CA, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( *cryptCertChain,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE, \n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYUSAGE_CRLSIGN );\n\t\t\t}\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate creation failed with \"\n\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Sign the leaf of the certificate chain */\n\tstatus = cryptSignCert( *cryptCertChain, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If we're trying to create a CA certificate then this should fail \n\t\t   due to the parent CA having a path length constraint of zero */\n\t\tif( createCAcert )\n\t\t\t{\n\t\t\tint errorType, errorLocus;\n\n\t\t\tstatus = cryptGetAttribute( *cryptCertChain, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORTYPE,\n\t\t\t\t\t\t\t\t\t\t&errorType );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptGetAttribute( *cryptCertChain, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORLOCUS, \n\t\t\t\t\t\t\t\t\t\t\t&errorLocus );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\terrorType != CRYPT_ERRTYPE_ISSUERCONSTRAINT || \\\n\t\t\t\terrorLocus != CRYPT_CERTINFO_PATHLENCONSTRAINT )\n\t\t\t\t{\n\t\t\t\tcryptDestroyCert( *cryptCertChain );\n\t\t\t\tfprintf( outputStream, \"Path length constraint violation \"\n\t\t\t\t\t\t \"didn't report error type %d, locus %d,\\n  \"\n\t\t\t\t\t\t \"line %d.\\n\", errorType, errorLocus, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tcryptDestroyCert( *cryptCertChain );\n\t\tif( !reportError )\n\t\t\t{\n\t\t\t/* This is a text that's expected to fail, return a special-case \n\t\t\t   error code */\n\t\t\treturn( -1 );\n\t\t\t}\n\t\treturn( attrErrorExit( *cryptCertChain, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nint testCertChain( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCertChain;\n\tCRYPT_CONTEXT cryptCAKey;\n\tint certificateLength, value, status;\n\n\tfputs( \"Testing certificate chain creation/export...\\n\", outputStream );\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create a new certificate chain */\n\tstatus = createChain( &cryptCertChain, cryptCAKey, FALSE, FALSE, TRUE );\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\n\t/* Check the signature.  Since the chain counts as self-signed, we don't\n\t   have to supply a sig.check key.  Since the DIY CA certificate isn't \n\t   trusted we have to force cryptlib to treat it as explicitly trusted \n\t   when we try to verify the chain */\n\tstatus = setRootTrust( cryptCertChain, &value, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"Setting certificate chain \"\n\t\t\t\t\t\t\t   \"trusted\", status, __LINE__ ) );\n\t\t}\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tsetRootTrust( cryptCertChain, NULL, value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Try the other way of verifying the chain, by making the signing key\n\t   implicitly trusted */\n\tstatus = cryptSetAttribute( cryptCAKey, CRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t\t\t\tTRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"Setting chain signing key \"\n\t\t\t\t\t\t\t   \"trusted\", status, __LINE__ ) );\n\t\t}\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tcryptSetAttribute( cryptCAKey, CRYPT_CERTINFO_TRUSTED_IMPLICIT, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\n\t/* Finally, make sure that the non-trusted chain doesn't verify */\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"Certificate chain verified OK even though it wasn't \"\n\t\t\t\t\"trusted, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Export the certificate chain */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTCHAIN, cryptCertChain );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptExportCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfprintf( outputStream, \"Exported certificate chain is %d bytes long.\\n\", \n\t\t\t certificateLength );\n\tdebugDump( \"certchn\", certBuffer, certificateLength );\n\n\t/* Export the chain in the various text formats to make sure that each\n\t   one works correctly */\n\tif( !checkExportCert( cryptCertChain, TRUE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTIFICATE,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_TEXT_CERTIFICATE\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCertChain, TRUE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_TEXT_CERTCHAIN,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_TEXT_CERTCHAIN\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCertChain, TRUE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_XML_CERTIFICATE,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_XML_CERTIFICATE\" ) )\n\t\treturn( FALSE );\n\tif( !checkExportCert( cryptCertChain, TRUE, \n\t\t\t\t\t\t  CRYPT_CERTFORMAT_XML_CERTCHAIN,\n\t\t\t\t\t\t  \"CRYPT_CERTFORMAT_XML_CERTCHAIN\" ) )\n\t\treturn( FALSE );\n\n\t/* Destroy the certificate chain */\n\tstatus = cryptDestroyCert( cryptCertChain );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can read what we created */\n\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  &cryptCertChain );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"Checking signatures... \" );\n\tstatus = setRootTrust( cryptCertChain, &value, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"Setting certificate chain \"\n\t\t\t\t\t\t\t   \"trusted\", status, __LINE__ ) );\n\t\t}\n\tstatus = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );\n\tsetRootTrust( cryptCertChain, NULL, value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCertChain, \"cryptCheckCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tfputs( \"signatures verified.\\n\", outputStream );\n\n\t/* Display info on each certificate in the chain */\n\tif( !printCertChainInfo( cryptCertChain ) )\n\t\treturn( FALSE );\n\n\t/* Create a second certificate chain with a null DN.  For this to \n\t   succeed we have to set the compliance level to \n\t   CRYPT_COMPLIANCELEVEL_PKIX_FULL */\n\tcryptDestroyCert( cryptCertChain );\n\tstatus = createChain( &cryptCertChain, cryptCAKey, TRUE, FALSE, FALSE );\n\tif( status != -1 )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to create certificate with null \"\n\t\t\t\t \"DN %s, line %d.\\n\",\n\t\t\t\t ( status == FALSE ) ? \\\n\t\t\t\t\t\"failed\" : \"succeeded when it should have failed\",\n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL, &value );\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\tCRYPT_COMPLIANCELEVEL_PKIX_FULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If the maximum level of PKIX weirdness that cryptlib will allow \n\t\t   is less than CRYPT_COMPLIANCELEVEL_PKIX_FULL then we can't\n\t\t   perform this test, so we just skip it */\n\t\tif( status != CRYPT_ERROR_PARAM3 )\n\t\t\t{\n\t\t\tprintf( \"Attempt to set compliance level to \"\n\t\t\t\t\t\"CRYPT_COMPLIANCELEVEL_PKIX_FULL failed with error code \"\n\t\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfputs( \"(Couldn't set compliance level to \"\n\t\t\t   \"CRYPT_COMPLIANCELEVEL_PKIX_FULL, probably\\n because cryptlib \"\n\t\t\t   \"has been configured not to use this level, skipping final\\n\"\n\t\t\t   \" tests...).\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = createChain( &cryptCertChain, cryptCAKey, TRUE, FALSE, TRUE );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   value );\n\t\tif( status != TRUE )\n\t\t\t{\n\t\t\tputs( \"  (This may be because the internal compliance-level \"\n\t\t\t\t  \"handling is wrong).\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTCHAIN, cryptCertChain );\n\t\tcryptDestroyCert( cryptCertChain );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptCertChain, \"cryptExportCert()\", \n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tdebugDump( \"certchndn\", certBuffer, certificateLength );\n\t\tstatus = cryptImportCert( certBuffer, certificateLength, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  &cryptCertChain );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCertChain );\n\tcryptDestroyContext( cryptCAKey );\n\tfputs( \"Certificate chain creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test CA certificate constraints */\n\nint testCAConstraints( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCertChain;\n\tCRYPT_CONTEXT cryptCAKey;\n\tint value, status;\n\n\tfputs( \"Testing CA constraint enforcement...\\n\", outputStream );\n\n\t/* Get the CA's private key and make sure that the path length \n\t   constraint is zero.  This should be inherited from the parent (root)\n\t   CA, which has a path length constraint of 1 */\n\tstatus = getPrivateKey( &cryptCAKey, ICA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttribute( cryptCAKey, CRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) || value != 0 )\n\t\t{\n\t\tfprintf( outputStream, \"CA path length != 0, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create a certificate chain containing a CA certificate.  This should \n\t   fail due to the path length being exceeded */\n\tstatus = createChain( &cryptCertChain, cryptCAKey, FALSE, TRUE, FALSE );\n\tif( status != -1 )\n\t\t{\n\t\tfprintf( outputStream, \"CA cert creation with path length 0 \"\n\t\t\t\t \"succeeded, should have failed, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform the same operation with an EE certificate.  This should \n\t   succeed */\n\tstatus = createChain( &cryptCertChain, cryptCAKey, FALSE, FALSE, TRUE );\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCertChain );\n\tcryptDestroyContext( cryptCAKey );\n\tfputs( \"CA constraint enforcement test succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test CMS attribute code.  This doesn't actually test much since this\n   object type is just a basic data container used for the extended signing\n   functions */\n\nstatic const CERT_DATA cmsAttributeData[] = {\n\t/* Content type and an S/MIME capability */\n\t{ CRYPT_CERTINFO_CMS_CONTENTTYPE, IS_NUMERIC, CRYPT_CONTENT_SIGNEDDATA },\n\t{ CRYPT_CERTINFO_CMS_SMIMECAP_PREFERSIGNEDDATA, IS_NUMERIC, CRYPT_UNUSED },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testCMSAttributes( void )\n\t{\n\tCRYPT_CERTIFICATE cryptAttributes;\n\tint status;\n\n\tfputs( \"Testing CMS attribute creation...\\n\", outputStream );\n\n\t/* Create the CMS attribute container */\n\tstatus = cryptCreateCert( &cryptAttributes, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add some CMS attribute components */\n\tif( !addCertFields( cryptAttributes, cmsAttributeData, __LINE__ ) )\n\t\treturn( FALSE );\n\n\t/* Print information on what we've got */\n\tif( !printCertInfo( cryptAttributes ) )\n\t\treturn( FALSE );\n\n\t/* Destroy the attributes.  We can't do much more than this at this\n\t   stage since the attributes are only used internally by other\n\t   functions */\n\tstatus = cryptDestroyCert( cryptAttributes );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tfputs( \"CMS attribute creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test RTCS request/response code.  This test routine itself doesn't\n   actually test much since this object type is just a basic data container\n   used for RTCS sessions, however the shared initRTCS() routine is used by\n   the RTCS session code to test the rest of the functionality.\n   \n   initRTCS() is also called by the RTCS session code, which is why it's\n   declared non-static */\n\nint initRTCS( CRYPT_CERTIFICATE *cryptRTCSRequest, \n\t\t\t  const CRYPT_CERTIFICATE cryptCert, \n\t\t\t  const BOOLEAN multipleCerts )\n\t{\n\tCRYPT_CERTIFICATE cryptErrorObject;\n\tC_CHR rtcsURL[ 512 ];\n\tint count DUMMY_INIT, status;\n\n\t/* Select the RTCS responder location from the EE certificate and read \n\t   the URL/FQDN value (this isn't used but is purely for display to the \n\t   user) */\n\tstatus = cryptSetAttribute( cryptCert, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITYINFO_RTCS );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t\t\t\t\t\t\t\trtcsURL, &count );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_DNSNAME, rtcsURL, &count );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tputs( \"RTCS responder URL not present in certificate, server \"\n\t\t\t\t  \"name must be provided\\n  externally.\" );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tprintf( \"Attempt to read RTCS responder URL failed with error \"\n\t\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\tprintErrorAttributeInfo( cryptCert );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\trtcsURL[ count / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"RTCS responder URL = %sS.\\n\", rtcsURL );\n#else\n\t\trtcsURL[ count ] = '\\0';\n\t\tfprintf( outputStream, \"RTCS responder URL = %s.\\n\", rtcsURL );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\n\t/* Create the RTCS request container */\n\tstatus = cryptCreateCert( cryptRTCSRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_RTCS_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptErrorObject = *cryptRTCSRequest;\n\n\t/* Add the request components */\n\tstatus = cryptSetAttribute( *cryptRTCSRequest,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTIFICATE, cryptCert );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\tcryptErrorObject = cryptCert;\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptErrorObject, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\n\t/* If we're doing a query with multiple certs, add another certificate.  \n\t   To keep things simple and avoid having to stockpile a whole \n\t   collection of certificates for each responder we just use a random \n\t   certificate for which we expect an 'unknown' response */\n\tif( multipleCerts )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptSecondCert;\n\n\t\tstatus = importCertFromTemplate( &cryptSecondCert, \n\t\t\t\t\t\t\t\t\t\t CERT_FILE_TEMPLATE, 1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( *cryptRTCSRequest,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTIFICATE, \n\t\t\t\t\t\t\t\t\t\tcryptSecondCert );\n\t\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\t\tcryptErrorObject = cryptSecondCert;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptErrorObject, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptSecondCert );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nint testRTCSReqResp( void )\n\t{\n\tCRYPT_CERTIFICATE cryptRTCSRequest, cryptCert;\n\tint status;\n\n\tfputs( \"Testing RTCS request creation...\\n\", outputStream );\n\n\t/* Import the EE certificate for the RTCS request */\n\tstatus = importCertFromTemplate( &cryptCert, RTCS_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the RTCS request using the certs and print information on what\n\t   we've got */\n\tif( !initRTCS( &cryptRTCSRequest, cryptCert, FALSE ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptCert );\n\tif( !printCertInfo( cryptRTCSRequest ) )\n\t\treturn( FALSE );\n\n\t/* Destroy the request.  We can't do much more than this at this stage\n\t   since the request is only used internally by the RTCS session code */\n\tstatus = cryptDestroyCert( cryptRTCSRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"RTCS request creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test OCSP request/response code.  This test routine itself doesn't\n   actually test much since this object type is just a basic data container\n   used for OCSP sessions, however the shared initOCSP() routine is used by\n   the OCSP session code to test the rest of the functionality */\n\nint initOCSP( CRYPT_CERTIFICATE *cryptOCSPRequest, \n\t\t\t  CRYPT_CERTIFICATE *cert1, CRYPT_CERTIFICATE *cert2,\n\t\t\t  const int number, const BOOLEAN ocspv2, \n\t\t\t  const BOOLEAN revokedCert, const BOOLEAN multipleCerts,\n\t\t\t  const CRYPT_SIGNATURELEVEL_TYPE sigLevel,\n\t\t\t  const CRYPT_CONTEXT privKeyContext )\n\t{\n\tCRYPT_CERTIFICATE cryptOCSPEE = CRYPT_UNUSED, cryptOCSPEE2 = CRYPT_UNUSED;\n\tCRYPT_CERTIFICATE cryptOCSPCA, cryptErrorObject;\n\tC_CHR ocspURL[ 512 ];\n\tint count DUMMY_INIT, status;\n\n\tassert( ( cert1 == NULL && cert2 == NULL ) || \\\n\t\t\t( cert1 != NULL && cert2 != NULL ) );\n\tassert( !ocspv2 );\n\n\t/* Clear return values */\n\tif( cert1 != NULL )\n\t\t*cert1 = *cert2 = CRYPT_UNUSED;\n\n\t/* Import the OCSP CA (if required) and EE certs */\n\tif( !ocspv2 )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptOCSPCA,\n\t\t\t\t\t\t\t\t\t\t OCSP_CA_FILE_TEMPLATE, number );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"CA cryptImportCert() failed with \"\n\t\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tstatus = importCertFromTemplate( &cryptOCSPEE, revokedCert ? \\\n\t\t\t\t\t\tOCSP_EEREV_FILE_TEMPLATE: OCSP_EEOK_FILE_TEMPLATE,\n\t\t\t\t\t\tnumber );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"EE cryptImportCert() failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Select the OCSP responder location from the EE certificate and read \n\t   the URL/FQDN value (this isn't used but is purely for display to the \n\t   user) */\n\tstatus = cryptSetAttribute( cryptOCSPEE, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITYINFO_OCSP );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptOCSPEE,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER,\n\t\t\t\t\t\t\tocspURL, &count );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptOCSPEE,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_DNSNAME, ocspURL, &count );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tfputs( \"OCSP responder URL not present in certificate, server \"\n\t\t\t\t   \"name must be provided\\n  externally.\\n\", outputStream );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tprintf( \"Attempt to read OCSP responder URL failed with error \"\n\t\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\tprintErrorAttributeInfo( cryptOCSPEE );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tocspURL[ count / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"OCSP responder URL = %S.\\n\", ocspURL );\n#else\n\t\tocspURL[ count ] = '\\0';\n\t\tfprintf( outputStream, \"OCSP responder URL = %s.\\n\", ocspURL );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\n\t/* Create the OCSP request container */\n\tstatus = cryptCreateCert( cryptOCSPRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_OCSP_REQUEST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptErrorObject = *cryptOCSPRequest;\n\n\t/* Add the request components.  Note that if we're using v1 we have to\n\t   add the CA certificate first since it's needed to generate the \n\t   request ID for the EE certificate */\n\tif( !ocspv2 )\n\t\t{\n\t\tstatus = cryptSetAttribute( *cryptOCSPRequest,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CACERTIFICATE, cryptOCSPCA );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\tcryptErrorObject = cryptOCSPCA;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( *cryptOCSPRequest,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTIFICATE, cryptOCSPEE );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\tcryptErrorObject = cryptOCSPEE;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptErrorObject, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\n\t/* If we're doing a query with multiple certs, add another certificate.  \n\t   To keep things simple and avoid having to stockpile a whole \n\t   collection of certificates for each responder we just use a random \n\t   certificate for which we expect an 'unknown' response */\n\tif( multipleCerts )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptOCSPEE2, CERT_FILE_TEMPLATE, 1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( *cryptOCSPRequest,\n\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTIFICATE, cryptOCSPEE2 );\n\t\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\t\tcryptErrorObject = cryptOCSPEE2;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( *cryptOCSPRequest, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\t}\n\n\t/* If we have a signing key, create a signed request */\n\tif( privKeyContext != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = cryptSetAttribute( *cryptOCSPRequest,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SIGNATURELEVEL, sigLevel );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( *cryptOCSPRequest, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tstatus = cryptSignCert( *cryptOCSPRequest, privKeyContext );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\tcryptErrorObject = privKeyContext;\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptErrorObject, \"cryptSignCert()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tif( !ocspv2 )\n\t\tcryptDestroyCert( cryptOCSPCA );\n\tif( cert1 == NULL )\n\t\t{\n\t\tcryptDestroyCert( cryptOCSPEE );\n\t\tif( cryptOCSPEE != CRYPT_UNUSED )\n\t\t\tcryptDestroyCert( cryptOCSPEE2 );\n\t\t}\n\telse\n\t\t{\n\t\t/* Return the certificates to the caller */\n\t\t*cert1 = cryptOCSPEE;\n\t\t*cert2 = cryptOCSPEE2;\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nint testOCSPReqResp( void )\n\t{\n\tCRYPT_CERTIFICATE cryptOCSPRequest;\n\tCRYPT_CONTEXT cryptPrivateKey;\n\tint status;\n\n\tfputs( \"Testing OCSP request creation...\\n\", outputStream );\n\n\t/* Create the OCSP request using the certs and print information on what\n\t   we've got */\n\tif( !initOCSP( &cryptOCSPRequest, NULL, NULL, 1, FALSE, FALSE, FALSE,\n\t\t\t\t   CRYPT_SIGNATURELEVEL_NONE, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\n\tfputs( \"OCSPv1 succeeded.\\n\", outputStream );\n\tif( !printCertInfo( cryptOCSPRequest ) )\n\t\treturn( FALSE );\n\n\t/* Destroy the request.  We can't do much more than this at this stage\n\t   since the request is only used internally by the OCSP session code */\n\tstatus = cryptDestroyCert( cryptOCSPRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n#if 0\t/* OCSPv2 is still in too much of a state of flux to implement this */\n\t/* Try again with a v2 request.  This only differs from the v1 request in\n\t   the way the ID generation is handled so we don't bother printing any\n\t   information on the request */\n\tif( !initOCSP( &cryptOCSPRequest, NULL, NULL, 1, TRUE, FALSE, FALSE,\n\t\t\t\t   CRYPT_SIGNATURELEVEL_NONE, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\n\tfputs( \"OCSPv2 succeeded.\\n\", outputStream );\n\tcryptDestroyCert( cryptOCSPRequest );\n#endif\n\n\t/* Finally, create a signed request, first without and then with signing\n\t   certs */\n\tstatus = getPrivateKey( &cryptPrivateKey, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"User private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !initOCSP( &cryptOCSPRequest, NULL, NULL, 1, FALSE, FALSE, FALSE,\n\t\t\t\t   CRYPT_SIGNATURELEVEL_NONE, cryptPrivateKey ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptOCSPRequest );\n\tfputs( \"Signed OCSP request succeeded.\\n\", outputStream );\n\tif( !initOCSP( &cryptOCSPRequest, NULL, NULL, 1, FALSE, FALSE, FALSE,\n\t\t\t\t   CRYPT_SIGNATURELEVEL_SIGNERCERT, cryptPrivateKey ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptOCSPRequest );\n\tfputs( \"Signed OCSP request with single signing certificate \"\n\t\t   \"succeeded.\\n\", outputStream );\n\tif( !initOCSP( &cryptOCSPRequest, NULL, NULL, 1, FALSE, FALSE, FALSE,\n\t\t\t\t   CRYPT_SIGNATURELEVEL_ALL, cryptPrivateKey ) )\n\t\treturn( FALSE );\n\tcryptDestroyCert( cryptOCSPRequest );\n\tfputs( \"Signed OCSP request with signing certificate chain \"\n\t\t   \"succeeded.\\n\", outputStream );\n\tcryptDestroyContext( cryptPrivateKey );\n\n\tfputs( \"OCSP request creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test PKI user information creation.  This doesn't actually test much\n   since this object type is just a basic data container used to hold user\n   information in a certificate store */\n\nstatic const CERT_DATA pkiUserData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test PKI user\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA pkiUserExtData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test extended PKI user\" ) },\n\n\t/* SSL server and client authentication */\n\t{ CRYPT_CERTINFO_EXTKEY_SERVERAUTH, IS_NUMERIC, CRYPT_UNUSED },\n\t{ CRYPT_CERTINFO_EXTKEY_CLIENTAUTH, IS_NUMERIC, CRYPT_UNUSED },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA pkiUserCAData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test CA PKI user\" ) },\n\n\t/* CA extensions */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA pkiUserRAData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test RA PKI user\" ) },\n\n\t/* RA flag */\n\t{ CRYPT_CERTINFO_PKIUSER_RA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n#define PKIUSER_NAME_INDEX\t3\t/* Index of name in CERT_DATA info */\n\nstatic int testPKIUserCreate( const CERT_DATA *pkiUserInfo )\n\t{\n\tCRYPT_CERTIFICATE cryptPKIUser;\n\tint status;\n\n\t/* Create the PKI user object and add the user's identification\n\t   information */\n\tstatus = cryptCreateCert( &cryptPKIUser, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !addCertFields( cryptPKIUser, pkiUserInfo, __LINE__ ) )\n\t\t{\n\t\tprintf( \"Couldn't create PKI user info for user '%s', line %d.\\n\",\n\t\t\t\t( char * ) pkiUserInfo[ PKIUSER_NAME_INDEX ].stringValue, \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptPKIUser );\n\n\treturn( TRUE );\n\t}\n\nint testPKIUser( void )\n\t{\n\tfputs( \"Testing PKI user information creation...\\n\", outputStream );\n\tif( !testPKIUserCreate( pkiUserData ) )\n\t\treturn( FALSE );\n\tif( !testPKIUserCreate( pkiUserExtData ) )\n\t\treturn( FALSE );\n\tif( !testPKIUserCreate( pkiUserCAData ) )\n\t\treturn( FALSE );\n\tif( !testPKIUserCreate( pkiUserRAData ) )\n\t\treturn( FALSE );\n\tfputs( \"PKI user information creation succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n"
  },
  {
    "path": "deps/cl345/test/devices.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t  cryptlib Device Test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2015\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\t/* For algorithm usage */\n#include \"misc/consts.h\"\t/* For DEFAULT_CRYPT_ALGO */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* Which devices we want to test.  We always test PKCS #11 (if device tests\n   are enabled) but only test the generic hardware device if it's explicitly\n   enabled, since it's system-specific or will only be present as emulated\n   hardware which will fail later tests */\n\n#define TEST_PKCS11\n#if 0\n  #define TEST_GENERIC_HARDWARE\n#endif /* 0 */\n\n/* Set the following to a nonzero value to test cryptlib's device init\n   capability.  THIS WILL ZEROISE/ERASE THE DEVICE BEING TESTED AS A PART\n   OF THE PROCESS.  All data contained in it will be destroyed.\n   \n   A number of buggy PKCS #11 devices can't be properly initialised through \n   the PKCS #11 API but require a vendor-supplied init program to be run.\n   If they're initialised via the PKCS #11 API then everything appears to\n   be fine but the device will then fail in a variety of strange ways when\n   an attempt is made to use it.  The PKCS #11 code will perform some sanity\n   checks to try and detect obvious cases of not-really-intitialised \n   initialised devices, but it can't catch every possible kind of brokenness.\n\n   Device initialisation is always performed for native cryptographic \n   hardware devices since these are typically being subject to development\n   self-tests and need to be reset to their ground state as part of the\n   testing process.  In other words TEST_INITIALISE_DEVICE has an implicit\n   value of '1' for this device type */\n\n#define TEST_INITIALISE_DEVICE\t0\n\n/* If the device is very slow (e.g. a smart card), clear the following to\n   not test the keygen capabilities of the device.  You can set this once\n   initially to generate the test keys and then re-clear it to use the\n   initially-generated keys from then on */\n\n#define TEST_KEYGEN\n#if ( TEST_INITIALISE_DEVICE > 0 ) && !defined( TEST_KEYGEN )\n  #define TEST_KEYGEN\t\t/* Must be enabled if initialising card */\n#endif /* TEST_INITIALISE_DEVICE && !TEST_KEYGEN */\n\n/* When testing high-level functionality, it's useful to be able to disable\n   the low-level algorithm tests and go straight to the high-level tests.\n   The following define can be used to disable the algorithm tests */\n\n#define TEST_ALGORITHMS\n\n/* The default PKC algorithm that we use when generating keys in the device.\n   This is usually the universal-standard RSA, but can be switched to other\n   algorithms when we're testing different device capabilities */\n\n#ifdef TEST_KEYGEN\n  #define DEVICE_PKC_ALGO\t\t\tCRYPT_ALGO_RSA\n/* #define DEVICE_PKC_ALGO\t\t\tCRYPT_ALGO_ECDSA */\n#endif /* TEST_KEYGEN */\n\n#ifdef TEST_DEVICE\n\n/* Note that Fortezza support was removed as of cryptlib 3.4.0, the Fortezza \n   test code is still present here for historical purposes but it's no \n   longer supported in cryptlib itself */\n\n/* The device code will produce a large number of warnings because of ASCII\n   <-> Unicode issues, since there aren't any PKCS #11 drivers for WinCE\n   it's not worth adding a mountain of special-case code to handle this so\n   we no-op it out under WinCE */\n\n#ifndef _WIN32_WCE\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDevice Information\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Device information tables for PKCS #11 device types.  This lists all the\n   devices we know about and can check for.  If you have a PKCS #11 device\n   that isn't listed below, you need to add an entry with its name and a\n   password and key object label usable for testing to the table, and also\n   add the name of the driver as a CRYPT_OPTION_DEVICE_PKCS11_DVRxx entry so\n   cryptlib can load the appropriate driver for it.  To add this, use the\n   updateConfig() function in testlib.c, see the code comments there for more\n   details.\n\n   The ActivCard driver is so broken that it's incredible it works at all,\n   it's more of a PKCS #11-like API that only works if you use it in exactly\n   the same way as the single test case that ActivCard must have used to\n   evaluate it.  The Telesec driver is even more broken than that (it's so\n   bad that it doesn't even work with Netscape), it just fakes a PKCS #11\n   API while doing something completely different.\n\n   The SEIS EID cards name their private key objects slightly differently\n   from the name used in the software-only eID driver, if you're using a\n   card-based version you need to switch the commented lines below to the\n   alternate name.\n\n   The Rainbow iKey uses Datakey drivers, so the Datakey test below will work\n   for both Datakey cards/keys and iKeys.  The newer Rainbow USB tokens\n   (using DataKey 232 drivers) can't be usefully initialised via PKCS #11\n   but have to be initialised using the vendor utility or operations fail in\n   strange and illogical ways.  In addition the driver partially ignores\n   user-specified key attributes such as encrypt-only or sign-only and uses\n   its own internal defaults.  Finally, operations with these keys then fail\n   with a key-type-inconsistent error even though there's nothing wrong with\n   them.  The solution to these problems is to use the Datakey 201 drivers\n   (intended for Entrust compatibility, which means they actually test them\n   properly), which work properly.\n\n   The iD2 driver implements multiple virtual slots, one for each key type,\n   so the entry is given in the extended driver::slot name format to tell\n   cryptlib which slot to use.\n\n   To reset the Rainbow card after it locks up and stops responding to\n   commands, run /samples/cryptoki20/sample.exe, enter 1 CR, 4 CR, 5 CR,\n   7 CR 2 CR \"rainbow\" CR, g CR \"test\" CR q CR (you need to follow that\n   sequence exactly for it to work).\n\n   To (try to) get the Eracom 3.09 CProv to work, delete the /cryptoki\n   directory (where it dumps all its config data, ignoring the settings in\n   cryptoki.ini), run ctconf.exe to set up a new device config, then\n   run 'ctconf -v -n0' (optionally 'ctconf -v -r0' to reinitialise the token\n   if you get an error about it already being initialised).  Then set \n   TEST_INITIALISE_DEVICE to a nonzero value and things should run OK (as \n   with the Rainbow tests, you need to follow this exactly for it to work).  \n   Re-running the test with the initialised device, or trying to re-run the \n   initialisation, both fail.  The re-init reports that no login is required \n   for the token, returns an already-logged-in error if an attempt is made \n   to log in, and returns a not-logged-in error of an attempt is made to do \n   anything that needs a login.  The re-use of the initialised device fails \n   with an invalid object handle for every object that's created (that is, \n   it's possible to create any object, but any attempt to use it returns an \n   invalid object handle error).  However, retrying this on a different \n   machine with a fresh install of the 3.09 CProv jumped immediately to the \n   not-logged-in error state in which it's possible to log in, but trying to \n   perform any operation that needs a login results in a not-logged-in \n   error.\n   \n   The Eracom 2.10 CProv is usually a lot less problematic, although even\n   with that it's not possible to initialise the device in software (in\n   other words never enable TEST_INITIALISE_DEVICE), you have to run \n   'ctinit -ptest' otherwise the device will end up in a state where any \n   attempt to use an object results in a CKR_KEY_HANDLE_INVALID (so even a \n   C_CreateObject() followed immediately by a C_EncryptInit() using the\n   handle returned from C_CreateObject() returns CKR_KEY_HANDLE_INVALID).\n\n   The Spyrus USB drivers don't get on with various drivers for other USB\n   devices such as USB printers (basic devices like USB storage keys are\n   OK).  To get the Spyrus driver to see the USB token, it may be necessary\n   to completely remove (not just disable) other USB device drivers.  The\n   Rosetta cards/USB tokens are very flaky, in general it's only possible\n   to safely generate new keys and add certs to a freshly-initialised token,\n   trying to add/update objects when there are already existing objects\n   present tends to fail with internal errors, and deleting the existing\n   objects isn't possible, the delete call succeeds but the object isn't\n   touched.  In addition with most versions of the Spyrus drivers data\n   isn't persisted to the token correctly, so some information (and even\n   complete objects) are only visible for the duration of the session that\n   created them.\n\n   The Netscape soft-token (softokn3.dll, i.e. NSS) is a bit problematic to \n   use, it requires the presence of three additional libraries (nspr4.dll, \n   plc4.dll, and plds4.dll) in the same directory, and even then requires \n   that C_Initialize() be called with proprietary and only partially-\n   documented nonstandard arguments, see the comment in device/pkcs11_init.c \n   for more on this.  The easiest way to arrange to have all the files in \n   the right place is to chdir to \"C:/Program Files/Mozilla Firefox\" before \n   loading the DLL, but even this doesn't mean that it'll work properly \n   (this behaviour isn't really a bug, softokn3.dll was only ever meant to \n   be used as a crypto layer for NSS, it was never intended to be a general-\n   purpose PKCS #11 soft-token).\n\n   The SoftHSM config is pointed to by the SOFTHSM2_CONF environment\n   variable, default is C:/Program Files (x86)/SoftHSM2/etc/softhsm2.conf.\n   This in turn points to C:/Program Files (x86)/SoftHSM2/var/softhsm2/tokens/\n   for token storage, which isn't a writeable location.  To deal with this,\n   the config file needs to be edited while running with admin privs to \n   point to %APPDATA%\\SoftHSM2\\ (and specifically the full expanded form of\n   %APPDATA% since SoftHSM doesn't understand shell variables).  Finally,\n   initialise the token with \n   'softhsm2-util --init-token --slot 0 --label \"SoftHSM2 Token\"'.\n\n   The presence of a device entry in this table doesn't necessarily mean \n   that the PKCS #11 driver that it comes with functions correctly, or at \n   all.  In particular the iButton driver never really got out of beta so it \n   has some features unimplemented, and the Utimaco driver apparently has \n   some really strange bugs, as well as screwing up Windows power management \n   so that suspends either aren't possible any more or will crash apps.  At \n   the other end of the scale the Datakey (before Rainbow got to them), \n   Eracom (usually, for older versions of the driver), iD2, and nCipher \n   drivers are pretty good */\n\ntypedef struct {\n\tconst char *name;\n\tconst char *description;\n\tconst char *password;\n\tconst char *keyLabel;\t/* Existing-key name, otherwise 'Test user key' */\n\t} DEVICE_CONFIG_INFO;\n\nstatic const DEVICE_CONFIG_INFO pkcs11DeviceInfo[] = {\n\t{ \"[Autodetect]\", \"Automatically detect device\", \"test\", \"Test user key\" },\n\t{ \"ActivCard Cryptoki Library\", \"ActivCard\", \"test\", \"Test user key\" },\n\t{ \"Bloomberg PKCS#11 Library\", \"Bloomberg\", \"test1234\", \"Test user key\" },\n\t{ \"Chrystoki\", \"Chrysalis Luna\", \"test\", \"Test user key\" },\n\t{ \"CryptoFlex\", \"CryptoFlex\", \"ABCD1234\", \"012345678901234567890123456789ME\" },\n\t{ \"Cryptographic Token Interface\", \"AET SafeSign\", \"test\", \"Test user key\" },\n\t{ \"Cryptoki for CardMan API\", \"Utimaco\", \"test\", \"Test user key\" },\n\t{ \"Cryptoki for eID\", \"Nexus soft-token\", \"1234\", \"Private key\" },\n\t{ \"Cryptoki for eID\", \"Nexus signature token\", \"1234\", \"eID private nonrepudiation key\" },\n\t{ \"Cryptoki for eID\", \"Nexus signature token\", \"1234\", \"eID private key encipherment key\" },\n\t{ \"Cryptoki PKCS-11\", \"Gemplus\", \"test\", \"Test user key\" },\n\t{ \"CryptoKit Extended Version\", \"Eutron (via Cylink)\", \"12345678\", \"Test user key\" },\n\t{ \"Datakey Cryptoki DLL - NETSCAPE\", \"Datakey pre-4.1, post-4.4 driver\", \"test\", \"Test user key\" },\n\t{ \"Datakey Cryptoki DLL - Version\", \"Datakey 4.1-4.4 driver\", \"test\", \"Test user key\" },\n\t{ \"Eracom Cryptoki\", \"Eracom\", \"test\", \"Test user key\" },\n\t{ \"ERACOM Software Only\", \"Eracom 1.x soft-token\", \"test\", \"Test user key\" },\n\t{ \"Software Only\", \"Eracom 2.x soft-token\", \"test\", \"Test user key\" },\n\t{ \"eToken PKCS#11\", \"Aladdin eToken\", \"test\", \"Test user key\" },\n\t{ \"G&D PKCS#11 Library\", \"Giesecke and Devrient\", \"test\", \"Test user key\" },\n\t{ \"FTSmartCard\", \"Feitian\", \"test\", \"1234\" },\n\t{ \"iButton\", \"Dallas iButton\", \"test\", \"Test user key\" },\n\t{ \"iD2 Cryptographic Library::iD2 Smart Card (PIN1)\", \"iD2 signature token::Slot 1\", \"1234\", \"Digital Signature\" },\n\t{ \"iD2 Cryptographic Library::iD2 Smart Card (PIN2)\", \"iD2 signature token::Slot 2\", \"5678\", \"Non Repudiation\" },\n\t{ \"ISG\", \"CryptoSwift HSM\", \"test\", \"Test user key\" },\n\t{ \"ISG Cryptoki API library\", \"CryptoSwift card\", \"test\", \"Test user key\" },\n\t{ \"Lynks/EES Token in SpyrusNATIVE\", \"Spyrus Lynks/EES\", \"test\", \"Test user key\" },\n\t{ \"NShield 75\", \"nCipher\", \"test\", \"Test user key\" },\n\t{ \"NSS Generic Crypto Services\", \"Netscape\", \"test\", \"Test user key\" },\n\t{ \"PKCS#11 Private Cryptoki\", \"GemSAFE\", \"1234\", \"Test user key\" },\n\t{ \"Safelayer PKCS#11\", \"Safelayer\", \"test\", \"Test user key\" },\n\t{ \"Schlumberger\", \"Schlumberger\", \"QWERTYUI\", \"Test user key\" },\n\t{ \"SignLite security module\", \"IBM SignLite\", \"test\", \"Test user key\" },\n\t{ \"SmartCard-HSM (UserPIN)\", \"CardContact\", \"123456\", \"rsa2k\" },\n\t{ \"SoftHSM2 Token\", \"SoftHSM2\", \"test\", \"Test user key\" },\n\t{ \"Spyrus Rosetta\", \"Spyrus Rosetta\", \"test\", \"Test user key\" },\n\t{ \"Spyrus Lynks\", \"Spyrus Lynks\", \"test\", \"Test user key\" },\n\t{ \"Sun Metaslot\", \"nCipher on Solaris\", \"test\", \"Test user key\" },\n\t{ \"TCrypt\", \"Telesec\", \"123456\", \"Test user key\" },\n\t{ \"TrustCenter PKCS#11 Library\", \"GPKCS11\", \"12345678\", \"Test user key\" },\n\t{ NULL, NULL, NULL }\n\t};\n\n/* Device information for Fortezza cards */\n\n#define FORTEZZA_ZEROISE_PIN\t\t\"ZeroizedCard\"\n#define FORTEZZA_SSO_DEFAULT_PIN\t\"Mosaic\"\n#define FORTEZZA_SSO_PIN\t\t\t\"test\"\n#define FORTEZZA_USER_PIN\t\t\t\"test\"\n\nstatic const DEVICE_CONFIG_INFO fortezzaDeviceInfo = \\\n\t{ \"[Autodetect]\", \"Automatically detect device\", FORTEZZA_USER_PIN, \"Test user key\" };\n\n/* Device information for CryptoAPI */\n\nstatic const DEVICE_CONFIG_INFO capiDeviceInfo[] = {\n\t{ \"[Autodetect]\", \"Automatically detect device\", \"\", \"Encryption key\" },\n\t{ \"Microsoft Base Cryptographic Provider v1.0::MY\", \"Microsoft Base Cryptographic Provider\", \"\", \"Encryption key\" },\n\t{ NULL, NULL, NULL }\n\t};\n\n/* Device information for generic crypto hardware */\n\nstatic const DEVICE_CONFIG_INFO hardwareDeviceInfo[] = {\n\t{ \"[Autodetect]\", \"Automatically detect device\", \"test\", \"Test user key\" },\n\t{ \"Dummy device\", \"Dummy test device\", \"test\", \"Test user key\" },\n\t{ NULL, NULL, NULL }\n\t};\n\n/* Data used to create certs in the device */\n\nstatic const CERT_DATA paaCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"NZ\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"Honest Dave's PAA\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, \"Certification Policy Division\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"Dave the PAA\" },\n\n\t/* Self-signed X.509v3 CA certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA cACertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"NZ\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"Dave's Wetaburgers and CA\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, \"Certification Division\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"Dave Himself\" },\n\n\t/* Self-signed X.509v3 CA certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA userCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"NZ\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"Dave's Wetaburgers\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"Dave's key\" },\n\t{ CRYPT_CERTINFO_EMAIL, IS_STRING, 0, TEXT( \"dave@wetaburgers.com\" ) },\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\t/* Re-select subject DN */\n\n\t/* X.509v3 general-purpose certificate */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_DIGITALSIGNATURE | CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA userSigOnlyCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"NZ\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"Dave's Wetaburgers\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"Dave's signing key\" },\n\n\t/* X.509v3 signature-only certificate */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic const CERT_DATA userKeyAgreeCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"NZ\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"Dave's Wetaburgers\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"Dave's key agreement key\" },\n\n\t/* X.509v3 key agreement certificate */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYAGREEMENT },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Delete leftover keys created during testing */\n\nstatic void deleteTestKey( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   const C_STR keyName, const char *keyDescription )\n\t{\n\tif( cryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, \\\n\t\t\t\t\t\tkeyName ) == CRYPT_OK && keyDescription != NULL )\n\t\t{\n\t\tprintf( \"(Deleted a %s key object, presumably a leftover from a \"\n\t\t\t\t\"previous run).\\n\", keyDescription );\n\t\t}\n\t}\n\n/* Create a key and certificate in a device */\n\nstatic BOOLEAN createKey( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t  const char *description, const char *dumpName,\n\t\t\t\t\t\t  const CRYPT_CONTEXT signingKey )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CERTIFICATE cryptCert;\n\tBYTE certBuffer[ BUFFER_SIZE ], labelBuffer[ CRYPT_MAX_TEXTSIZE ];\n\tconst BOOLEAN isCA = ( signingKey == CRYPT_UNUSED ) ? TRUE : FALSE;\n\tconst CERT_DATA *certData = ( isCA ) ? cACertData : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_RSA ) ? userCertData : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_DSA ) ? userSigOnlyCertData : \\\n\t\t\tuserKeyAgreeCertData;\n\tint certificateLength, status;\n\n\tsprintf( labelBuffer, \"Test %s key\", description );\n\n\t/* Generate a key in the device */\n\tprintf( \"Generating a %s key in the device...\", description );\n\tstatus = cryptDeviceCreateContext( cryptDevice, &cryptContext,\n\t\t\t\t\t\t\t\t\t   cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptDeviceCreateContext() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL, labelBuffer,\n\t\t\t\t\t\t\t strlen( labelBuffer ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tprintf( \"\\ncryptGenerateKey() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* Create a certificate for the key */\n\tprintf( \"Generating a certificate for the key...\" );\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED, ( isCA ) ? \\\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE : \\\n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTCHAIN );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCert, certData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, isCA ? cryptContext : signingKey );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyCert( cryptCert );\n\t\tprintf( \"\\nCreation of certificate failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* Dump the resulting certificate for debugging */\n\tif( dumpName != NULL )\n\t\t{\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certificateLength,\n\t\t\t\tisCA ? CRYPT_CERTFORMAT_CERTIFICATE : CRYPT_CERTFORMAT_CERTCHAIN,\n\t\t\t\tcryptCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tdebugDump( dumpName, certBuffer, certificateLength );\n\t\t}\n\n\t/* Update the device with the certificate */\n\tprintf( \"Updating device with certificate...\" );\n\tstatus = cryptAddPublicKey( cryptDevice, cryptCert );\n\tcryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptAddPublicKey() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tDevice Logon/Initialisation\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Print information about a device and log in if necessary */\n\nstatic const DEVICE_CONFIG_INFO *checkLogonDevice( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t\t\t\t\t\t   const DEVICE_CONFIG_INFO *deviceInfo,\n\t\t\t\t\t\t\t\t\t\t\t\t   const BOOLEAN isAutoDetect,\n\t\t\t\t\t\t\t\t\t\t\t\t   const BOOLEAN willInitialise )\n\t{\n\tchar tokenLabel[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint loggedOn, tokenLabelSize, status;\n\n\t/* Tell the user what we're talking to */\n\tstatus = cryptGetAttributeString( cryptDevice, CRYPT_DEVINFO_LABEL,\n\t\t\t\t\t\t\t\t\t  tokenLabel, &tokenLabelSize );\n\tif( cryptStatusError( status ) )\n\t\tputs( \"(Device doesn't appear to have a label).\" );\n\telse\n\t\t{\n\t\ttokenLabel[ tokenLabelSize ] = '\\0';\n\t\tprintf( \"Device label is '%s'.\\n\", tokenLabel );\n\t\t}\n\n\t/* Check whether the device corresponds to a known device.  We do this\n\t   because some devices require specific test passwords and whatnot in\n\t   order to work */\n\tif( isAutoDetect )\n\t\t{\n\t\tint i;\n\n\t\tfor( i = 1; deviceInfo[ i ].name != NULL; i++ )\n\t\t\t{\n\t\t\tif( tokenLabelSize == \\\n\t\t\t\t\t\t\t( int ) strlen( deviceInfo[ i ].name ) && \\\n\t\t\t\t!memcmp( deviceInfo[ i ].name, tokenLabel,\n\t\t\t\t\t\t tokenLabelSize ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Found a match for pre-defined device '%s',\\n\"\n\t\t\t\t\t\t\"  using pre-set parameters.\\n\",\n\t\t\t\t\t\tdeviceInfo[ i ].description );\n\t\t\t\tdeviceInfo = &deviceInfo[ i ];\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* See if we need to authenticate ourselves */\n\tstatus = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN,\n\t\t\t\t\t\t\t\t&loggedOn );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't obtain device login status.\" );\n\t\treturn( NULL );\n\t\t}\n\tif( loggedOn )\n\t\t{\n\t\t/* Device may not require a login, or has already been logged in\n\t\t   via a keypad or similar mechanism */\n\t\tputs( \"Device is already logged in, skipping login.\" );\n\t\treturn( deviceInfo );\n\t\t}\n\n\t/* Try and log in */\n\tprintf( \"Logging on to the device...\" );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\tCRYPT_DEVINFO_AUTHENT_USER, deviceInfo->password,\n\t\t\t\t\t\t\tstrlen( deviceInfo->password ) );\n\tif( status == CRYPT_ERROR_INITED )\n\t\t{\n\t\t/* Some devices may not require any login, in which case we're\n\t\t   done */\n\t\tputs( \" device is already logged in.\" );\n\t\treturn( deviceInfo );\n\t\t}\n\tif( status == CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\t/* It's an uninitialised device, tell the user and exit */\n\t\tputs( \" device needs to be initialised.\" );\n\t\tif( willInitialise )\n\t\t\treturn( deviceInfo );\n\t\tprintf( \"cryptlib will not automatically initialise the device \"\n\t\t\t\t\"during the self-test\\n  in case it contains data that \"\n\t\t\t\t\"needs to be preserved or requires special\\n  steps to be \"\n\t\t\t\t\"taken before the initialisation is performed.  If you want \"\n\t\t\t\t\"to\\n  initialise it, set TEST_INITIALISE_DEVICE at the top \"\n\t\t\t\t\"of\\n  \" __FILE__ \" to a nonzero value.\\n\" );\n\t\treturn( NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nDevice login%s failed with error code %d, line %d.\\n\",\n\t\t\t\t( status == CRYPT_ERROR_WRONGKEY ) ? \\\n\t\t\t\t\t\"\" : \" for initialisation/setup purposes\", \n\t\t\t\tstatus, __LINE__ );\n\t\tif( status == CRYPT_ERROR_WRONGKEY && willInitialise )\n\t\t\t{\n\t\t\t/* If we're going to initialise the card, being in the wrong (or\n\t\t\t   even totally uninitialised) state isn't an error */\n\t\t\tputs( \"This may be because the device isn't in the user-\"\n\t\t\t\t  \"initialised state, in which\\n  case the standard user \"\n\t\t\t\t  \"PIN can't be used to log on to it.\" );\n\t\t\treturn( deviceInfo );\n\t\t\t}\n\t\tif( isAutoDetect )\n\t\t\t{\n\t\t\tputs( \"This may be because the auto-detection test uses a fixed \"\n\t\t\t\t  \"login value rather\\n  than one specific to the device \"\n\t\t\t\t  \"type.\" );\n\t\t\t}\n\t\treturn( NULL );\n\t\t}\n\tputs( \" succeeded.\" );\n\treturn( deviceInfo );\n\t}\n\n/* Initialise a device.  Note that when doing this with a Fortezza card,\n   these operations have to be done in a more or less continuous sequence\n   (i.e. without an intervening device open call) because it's not possible\n   to escape from some of the states if the card is closed and reopened in\n   between.  In addition the PKCS #11 interface maps some of the\n   initialisation steps differently than the CI interface, so we have to\n   special-case this below */\n\nstatic BOOLEAN initialiseDevice( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t\t const CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t\t\t\t const DEVICE_CONFIG_INFO *deviceInfo )\n\t{\n\tconst char *defaultSSOPIN = ( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \\\n\t\t\t\t\t\t\t\tFORTEZZA_SSO_DEFAULT_PIN : \\\n\t\t\t\t\t\t\t\tdeviceInfo->password;\n\tconst char *ssoPIN = ( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \\\n\t\t\t\t\t\t FORTEZZA_SSO_PIN : deviceInfo->password;\n\tconst char *userPIN = deviceInfo->password;\n\tint status;\n\n\t/* PKCS #11 doesn't distinguish between zeroisation and initialisation,\n\t   so we only perform the zeroise test if it's a Fortezza card or built-\n\t   in hardware.  The latter doesn't really distinguish between the two\n\t   either but we perform the separate zeroise/initialise to make sure \n\t   that the two work as required */\n\tif( deviceType == CRYPT_DEVICE_FORTEZZA || \\\n\t\tdeviceType == CRYPT_DEVICE_HARDWARE )\n\t\t{\n\t\tprintf( \"Zeroising device...\" );\n\t\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\tCRYPT_DEVINFO_ZEROISE, FORTEZZA_ZEROISE_PIN,\n\t\t\t\t\t\tstrlen( FORTEZZA_ZEROISE_PIN ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\nZeroise failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tputs( \" succeeded.\" );\n\t\t}\n\n\t/* Initialise the device and set the SO PIN.   */\n\tprintf( \"Initialising device...\" );\n\tstatus = cryptSetAttributeString( cryptDevice, CRYPT_DEVINFO_INITIALISE,\n\t\t\t\t\t\t\t\t\t  defaultSSOPIN, strlen( defaultSSOPIN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't initialise device, status = %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\tprintf( \"Setting SO PIN to '%s'...\", ssoPIN );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR,\n\t\t\t\t\t\t\t\t\t  ssoPIN, strlen( ssoPIN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't set SO PIN, status = %d, line %d.\\n\", status,\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* If it's a Fortezza card, create a CA root key and install its \n\t   certificate.  We have to do it at this point because the operation is \n\t   only allowed in the SSO initialised state.  In addition we can't use \n\t   the card for this operation because certificate slot 0 is a data-only \n\t   slot (that is, it can't correspond to a key held on the card), so we \n\t   create a dummy external certificate and use that */\n\tif( deviceType == CRYPT_DEVICE_FORTEZZA )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert;\n\t\tCRYPT_CONTEXT signContext;\n\n\t\tprintf( \"Loading PAA certificate...\" );\n\t\tif( !loadDSAContexts( CRYPT_UNUSED, &signContext, NULL ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, signContext );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!addCertFields( cryptCert, paaCertData, __LINE__ ) )\n\t\t\treturn( FALSE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSignCert( cryptCert, signContext );\n\t\tcryptDestroyContext( signContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t\tprintf( \"\\nCreation of certificate failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptDevice, cryptCert );\n\t\tcryptDestroyCert( cryptCert );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\ncryptAddPublicKey() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tputs( \" succeeded.\" );\n\t\t}\n\n\t/* Set the user PIN and log on as the user */\n\tprintf( \"Setting user PIN to '%s'...\", userPIN );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_SET_AUTHENT_USER,\n\t\t\t\t\t\t\t\t\t  userPIN, strlen( userPIN ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint loggedOn;\n\n\t\t/* Some devices automatically log the user in when they set the user\n\t\t   password, so we check to see if it's necessary to log in before we\n\t\t   actually do it */\n\t\tstatus = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN,\n\t\t\t\t\t\t\t\t\t&loggedOn );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tputs( \"Couldn't obtain device login status.\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !loggedOn )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_AUTHENT_USER,\n\t\t\t\t\t\t\t\t\t\t\t  userPIN, strlen( userPIN ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't set user PIN/log on as user, status = %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tDevice Tests\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test the general capabilities of a device */\n\nstatic BOOLEAN testDeviceCapabilities( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t\t\t   const char *deviceName,\n\t\t\t\t\t\t\t\t\t   const BOOLEAN isWriteProtected )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint testCount = 0, failCount = 0;\n\n\tprintf( \"Checking %s capabilities...\\n\", deviceName );\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_CONVENTIONAL;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptDeviceQueryCapability( cryptDevice,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   cryptAlgo, NULL ) ) )\n\t\t\t{\n\t\t\ttestCount++;\n\t\t\tif( !testLowlevel( cryptDevice, cryptAlgo, isWriteProtected ) )\n\t\t\t\t{\n\t\t\t\t/* The test failed, we don't exit at this point but only\n\t\t\t\t   remember that there was a problem since we want to test\n\t\t\t\t   every possible algorithm */\n\t\t\t\tfailCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tif( isWriteProtected )\n\t\tputs( \"No tests were performed since the device is write-protected.\" );\n\telse\n\t\t{\n\t\tif( failCount )\n\t\t\t{\n\t\t\tprintf( \"%d of %d test%s failed.\\n\", failCount, testCount,\n\t\t\t\t\t( testCount > 1 ) ? \"s\" : \"\" );\n\t\t\t}\n\t\telse\n\t\t\tputs( \"Device capabilities test succeeded.\" );\n\t\t}\n\n\treturn( ( failCount == testCount ) ? FALSE : TRUE );\n\t}\n\n/* Test the high-level functionality provided by a device */\n\nstatic BOOLEAN testPersistentObject( const CRYPT_DEVICE cryptDevice )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_HMAC_SHA1;\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\tprintf( \"Loading a persistent symmetric key into the device...\" );\n\n\t/* Find an encryption algorithm that we can use and create a context in\n\t   the device */\n\tstatus = cryptDeviceQueryCapability( cryptDevice, cryptAlgo, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptAlgo = DEFAULT_CRYPT_ALGO;\n\t\tstatus = cryptDeviceQueryCapability( cryptDevice, cryptAlgo, NULL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t   cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't create conventional-encryption context in \"\n\t\t\t\t\"device, status = %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make it a persistent object and load a key */\n\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL, \n\t\t\t\t\t\t\t\t\t  SYMMETRIC_KEY_LABEL, \n\t\t\t\t\t\t\t\t\t  strlen( SYMMETRIC_KEY_LABEL ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptContext, CRYPT_CTXINFO_PERSISTENT, \n\t\t\t\t\t\t\t\t\tTRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't make device context persistent, status = %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't load key into persistent context, status = %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* Destroy the context.  Since it's persistent, it'll still be present \n\t   in the device */\n\tcryptDestroyContext( cryptContext );\n\n\t/* Recreate the object from the device */\n\tprintf( \"Reading back symmetric key...\" );\n\tstatus = cryptGetKey( cryptDevice, &cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t  SYMMETRIC_KEY_LABEL, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nRead of symmetric key failed, status = %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* Re-destroy it and make sure that it's still there afterwards.  This \n\t   tests the persistence of read-back objects vs. created objects */\n\tcryptDestroyContext( cryptContext );\n\tprintf( \"Re-reading back symmetric key...\" );\n\tstatus = cryptGetKey( cryptDevice, &cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t  SYMMETRIC_KEY_LABEL, NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nRe-read of symmetric key failed, status = %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" succeeded.\" );\n\n\t/* Perform an encrypt/decrypt test with the recreated object */\n\tprintf( \"Performing encryption test with recovered key...\" );\n\tstatus = testCrypt( cryptContext, cryptContext, cryptAlgo, NULL, TRUE, \n\t\t\t\t\t\tFALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tputs( \" succeeded.\" );\n\n\t/* Clean up.  Unlike the public/private keys which are reused for \n\t   various tests, this object isn't really useful for anything else so \n\t   we always clean it up once we're done */\n\tcryptDestroyContext( cryptContext );\n\tdeleteTestKey( cryptDevice, SYMMETRIC_KEY_LABEL, NULL );\n\treturn( TRUE );\n\t}\n\nstatic BOOLEAN testDeviceHighlevel( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t\t\tconst CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t\t\t\t\tconst char *keyLabel,\n\t\t\t\t\t\t\t\t\tconst char *password,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN isWriteProtected )\n\t{\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext, sigKeyContext;\n\tint status;\n\n#ifdef TEST_KEYGEN\n\tif( !isWriteProtected )\n\t\t{\n\t\tconst CRYPT_ALGO_TYPE cryptAlgo = \\\n\t\t\t\t\t\t( deviceType == CRYPT_DEVICE_FORTEZZA ) ? \\\n\t\t\t\t\t\tCRYPT_ALGO_DSA : DEVICE_PKC_ALGO;\n\n\t\tif( deviceType != CRYPT_DEVICE_CRYPTOAPI )\n\t\t\t{\n\t\t\t/* Create a CA key in the device */\n\t\t\tif( !createKey( cryptDevice, cryptAlgo, \"CA\",\n\t\t\t\t\t\t\t( deviceType == CRYPT_DEVICE_PKCS11 ) ? \\\n\t\t\t\t\t\t\t\"dp_cacert\" : \"df_cacert\", CRYPT_UNUSED ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Read back the CA key for use in generating end entity certs */\n\t\t\tstatus = cryptGetPrivateKey( cryptDevice, &sigKeyContext,\n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t\t TEXT( \"Test CA key\" ), NULL );\n\t\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t\t{\n\t\t\t\t/* If we're using a PKCS #11 device that doesn't support\n\t\t\t\t   object labels then we have to use the alternate read\n\t\t\t\t   method via the certificate CN.  This requires enabling \n\t\t\t\t   PKCS11_FIND_VIA_CRYPTLIB in device/pkcs11_rw.c */\n\t\t\t\tassert( cACertData[ 3 ].type == CRYPT_CERTINFO_COMMONNAME );\n\t\t\t\tstatus = cryptGetPrivateKey( cryptDevice, &sigKeyContext, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \n\t\t\t\t\t\t\t\t\t\t\t cACertData[ 3 ].stringValue, \n\t\t\t\t\t\t\t\t\t\t\t NULL );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* CryptoAPI can only store one private key per provider so we\n\t\t\t   can't have both a CA key and user key in the same \"device\".\n\t\t\t   Because of this we have to use the fixed CA key to issue the\n\t\t\t   certificate */\n\t\t\tstatus = getPrivateKey( &sigKeyContext, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\nRead of CA key failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Create end-entity certificate(s) for keys using the previously-\n\t\t   generated CA key.  If it's a Fortezza card and we're using KEA we\n\t\t   have to generate two sets of keys/certs, one for signing and one\n\t\t   for encryption */\n\t\tstatus = createKey( cryptDevice, cryptAlgo, \"user\",\n\t\t\t\t\t\t\t( deviceType == CRYPT_DEVICE_PKCS11 ) ? \\\n\t\t\t\t\t\t\t\"dp_usrcert\" : \"df_usrcert\", sigKeyContext );\n#ifdef USE_KEA\n\t\tif( status && deviceType == CRYPT_DEVICE_FORTEZZA )\n\t\t\t{\n\t\t\tstatus = createKey( cryptDevice, CRYPT_ALGO_KEA, \"KEA\",\n\t\t\t\t\t\t\t\t\"df_keacert\", sigKeyContext );\n\t\t\t}\n#endif /* USE_KEA */\n\t\tcryptDestroyContext( sigKeyContext );\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n#endif /* TEST_KEYGEN */\n\t\t{\n\t\tputs( \"Skipping key generation test, this assumes that the device \"\n\t\t\t  \"contains pre-\\n  existing keys.\" );\n\t\t}\n\n\t/* See whether there are any existing keys or certs.  Some tokens have\n\t   these built in and don't allow anything new to be created, after this\n\t   point the handling is somewhat special-case but we can at least report\n\t   their presence.  Although generally we can re-use a private key\n\t   context for both public and private operations, some devices or drivers\n\t   (and by logical extension thereof the cryptlib kernel) don't allow\n\t   public-key ops with private keys so we have to eplicitly handle public\n\t   and private keys.  This gets somewhat messy because some devices don't\n\t   have public keys but allow public-key ops with their private keys,\n\t   while others separate public and private keys and don't allow the\n\t   private key to do public-key ops */\n\tstatus = cryptGetPublicKey( cryptDevice, &pubKeyContext,\n\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, keyLabel );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint value;\n\n\t\tputs( \"Found a public key in the device, details follow...\" );\n\t\tprintCertChainInfo( pubKeyContext );\n\t\tif( cryptStatusOK( \\\n\t\t\t\tcryptGetAttribute( pubKeyContext,\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SELFSIGNED, &value ) ) && \\\n\t\t\tvalue )\n\t\t\t{\n\t\t\t/* It's a self-signed certificate/certificate chain, make sure \n\t\t\t   that it's valid.  Because it's probably not trusted, we make \n\t\t\t   it temporarily implicitly trusted in order for the sig.check \n\t\t\t   to succeed */\n\t\t\tstatus = cryptGetAttribute( pubKeyContext,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT, &value );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptSetAttribute( pubKeyContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_TRUSTED_IMPLICIT, 1 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptCheckCert( pubKeyContext, CRYPT_UNUSED );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Signature on certificate is invalid, status %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tcryptSetAttribute( pubKeyContext,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_TRUSTED_IMPLICIT, value );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tputs( \"Error: Couldn't locate public key in device.\" );\n\t\tpubKeyContext = CRYPT_UNUSED;\n\t\t}\n\tstatus = cryptGetPrivateKey( cryptDevice, &privKeyContext,\n\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, keyLabel, NULL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tputs( \"Found a private key in the device, details follow...\" );\n\t\tprintCertChainInfo( privKeyContext );\n\t\tif( pubKeyContext == CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* No explicit public key found, try using the private key for\n\t\t\t   both key types */\n\t\t\tputs( \"No public key found, attempting to continue using the \"\n\t\t\t\t  \"private key as both a\\n  public and a private key.\" );\n\t\t\tpubKeyContext = privKeyContext;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tputs( \"Error: Couldn't locate private key in device.\" );\n\t\tprivKeyContext = CRYPT_UNUSED;\n\t\t}\n\tsigKeyContext = privKeyContext;\n\tif( deviceType == CRYPT_DEVICE_FORTEZZA )\n\t\t{\n\t\tcryptDestroyContext( pubKeyContext );\t/* pubK is sig.only */\n\t\tstatus = cryptGetPrivateKey( cryptDevice, &privKeyContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \"Test KEA key\", NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tputs( \"Found a key agreement key in the device, details follow...\" );\n\t\t\tprintCertChainInfo( privKeyContext );\n\t\t\tpubKeyContext = privKeyContext;\t\t/* Fortezza allows both uses */\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tpubKeyContext = CRYPT_UNUSED;\n\t\t\tprivKeyContext = CRYPT_UNUSED;\n\t\t\t}\n\t\t}\n\n\t/* If we got something, try some simple operations with it */\n\tif( pubKeyContext != CRYPT_UNUSED )\n\t\t{\n\t\tchar emailAddress[ CRYPT_MAX_TEXTSIZE + 1 ];\n\t\tint length;\n\n\t\tif( !testEnvelopePKCCryptEx( pubKeyContext, cryptDevice ) )\n\t\t\t{\n\t\t\tif( deviceType == CRYPT_DEVICE_HARDWARE )\n\t\t\t\t{\n\t\t\t\tputs( \"\\nEnveloping test failed when using the built-in \"\n\t\t\t\t\t  \"cryptographic hardware device.\\nIf this is an \"\n\t\t\t\t\t  \"emulated device that doesn't fully implement \"\n\t\t\t\t\t  \"public/private-key\\nencryption and the test failed \"\n\t\t\t\t\t  \"with a CRYPT_ERROR_BADDATA then this isn't\\na fatal \"\n\t\t\t\t\t  \"error, it simply means that cryptlib has detected \"\n\t\t\t\t\t  \"that the emulation\\nisn't performing a genuine \"\n\t\t\t\t\t  \"crypto operation.\" );\n\t\t\t\t}\n\t\t\tcryptDestroyContext( pubKeyContext );\n\t\t\tif( privKeyContext != CRYPT_UNUSED )\n\t\t\t\tcryptDestroyContext( privKeyContext );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !testCMSEnvelopePKCCryptEx( pubKeyContext, cryptDevice, \n\t\t\t\t\t\t\t\t\t\tpassword, NULL ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttribute( pubKeyContext, CRYPT_ATTRIBUTE_CURRENT, \n\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME );\n\t\tstatus = cryptGetAttributeString( pubKeyContext, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t\t  emailAddress, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't read recipient address from certificate, \"\n\t\t\t\t\t\"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\temailAddress[ length ] = '\\0';\n\t\tif( !testCMSEnvelopePKCCryptEx( CRYPT_UNUSED, cryptDevice, \n\t\t\t\t\t\t\t\t\t\tpassword, emailAddress ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tputs( \"Public-key enveloping tests skipped because no key was \"\n\t\t\t  \"available.\\n\" );\n\t\t}\n\tif( sigKeyContext != CRYPT_UNUSED )\n\t\t{\n\t\tif( !testCMSEnvelopeSignEx( sigKeyContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tputs( \"Signed enveloping tests skipped because no key was \"\n\t\t\t  \"available.\" );\n\t\t}\n\n\t/* Test persistent (non-public-key) object creation */\n#ifdef TEST_KEYGEN\n\tif( !isWriteProtected )\n\t\t{\n\t\tif( !testPersistentObject( cryptDevice ) )\n\t\t\treturn( FALSE );\n\t\t}\n#endif /* TEST_KEYGEN */\n\n\t/* Clean up */\n\tif( pubKeyContext == CRYPT_UNUSED && sigKeyContext == CRYPT_UNUSED )\n\t\treturn( FALSE );\n\tif( privKeyContext != CRYPT_UNUSED )\n\t\tcryptDestroyContext( privKeyContext );\n\tif( sigKeyContext != CRYPT_UNUSED && privKeyContext != sigKeyContext )\n\t\tcryptDestroyContext( sigKeyContext );\n\tif( pubKeyContext != CRYPT_UNUSED && pubKeyContext != privKeyContext )\n\t\tcryptDestroyContext( pubKeyContext );\n\treturn( TRUE );\n\t}\n\n/* General device test routine */\n\nstatic int testCryptoDevice( const CRYPT_DEVICE_TYPE deviceType,\n\t\t\t\t\t\t\t const char *deviceName,\n\t\t\t\t\t\t\t const DEVICE_CONFIG_INFO *deviceInfo )\n\t{\n\tCRYPT_DEVICE cryptDevice;\n\tBOOLEAN isWriteProtected = FALSE, isAutoDetect = FALSE;\n\tBOOLEAN testResult = FALSE, partialSuccess = FALSE;\n\tint status;\n\n\t/* Open a connection to the device */\n\tif( deviceType == CRYPT_DEVICE_PKCS11 || \\\n\t\tdeviceType == CRYPT_DEVICE_CRYPTOAPI || \\\n\t\tdeviceType == CRYPT_DEVICE_HARDWARE )\n\t\t{\n\t\tif( !memcmp( deviceInfo->name, \"[A\", 2 ) )\n\t\t\t{\n\t\t\tprintf( \"\\nTesting %s with autodetection...\\n\", deviceName );\n\t\t\tisAutoDetect = TRUE;\n\t\t\t}\n\t\telse\n\t\t\tprintf( \"\\nTesting %s %s...\\n\", deviceInfo->description, deviceName );\n\t\tstatus = cryptDeviceOpen( &cryptDevice, CRYPT_UNUSED, deviceType,\n\t\t\t\t\t\t\t\t  deviceInfo->name );\n\t\t}\n\telse\n\t\t{\n\t\tprintf( \"\\nTesting %s...\\n\", deviceName );\n\t\tstatus = cryptDeviceOpen( &cryptDevice, CRYPT_UNUSED, deviceType,\n\t\t\t\t\t\t\t\t  deviceName );\n\t\t}\n\tif( status == CRYPT_ERROR_PARAM2 )\n\t\t{\n\t\tputs( \"Support for this device type isn't enabled in this build of \"\n\t\t\t  \"cryptlib.\" );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\t/* Device access not available */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_PARAM3 || status == CRYPT_ERROR_NOTFOUND )\n\t\t\tputs( \"Crypto device not detected, skipping test.\" );\n\t\telse\n\t\t\tprintf( \"cryptDeviceOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's one of the smarter classes of device, authenticate ourselves to\n\t   the device, which is usually required in order to allow it to be used\n\t   fully */\n\tif( deviceType == CRYPT_DEVICE_PKCS11 || \\\n\t\tdeviceType == CRYPT_DEVICE_FORTEZZA || \\\n\t\tdeviceType == CRYPT_DEVICE_HARDWARE )\n\t\t{\n\t\tdeviceInfo = checkLogonDevice( cryptDevice, deviceInfo, isAutoDetect, \n\t\t\t\t\t\t\t\t\t   TEST_INITIALISE_DEVICE );\n\t\tif( deviceInfo == NULL )\n\t\t\t{\n\t\t\tcryptDeviceClose( cryptDevice );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Write-protected devices won't allow contexts to be created in them,\n\t   before we try the general device capabilities test we make sure that\n\t   we can actually perform the operation */\n\tif( deviceType == CRYPT_DEVICE_PKCS11 )\n\t\t{\n\t\tCRYPT_CONTEXT cryptContext;\n\n\t\t/* Try and create an encryption object.  The following check for \n\t\t   read-only devices always works because the device object ACL is \n\t\t   applied at a much higher level than any device capability \n\t\t   checking, the device will never even see the create object \n\t\t   message if it's write-protected so all we have to do is make sure \n\t\t   that whatever we create is ephemeral */\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, &cryptContext,\n\t\t\t\t\t\t\t\t\t\t   DEFAULT_CRYPT_ALGO );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tcryptDestroyContext( cryptContext );\n\t\tif( status == CRYPT_ERROR_PERMISSION )\n\t\t\tisWriteProtected = TRUE;\n\t\t}\n\n\t/* To force the code not to try to create keys and certs in a writeable\n\t   device, uncomment the following line of code.  This requires that keys/\n\t   certs of the required type are already present in the device */\n/*\tKLUDGE_WARN( \"write-protect status\" );\n\tisWriteProtected = TRUE; */\n\tif( !isWriteProtected )\n\t\t{\n\t\t/* If it's a device that we can initialise, go through a full\n\t\t   initialisation.  Note that if this we're using built-in \n\t\t   cryptographic hardware then we always perform the initialisation\n\t\t   because we're typically doing this as a development self-test and\n\t\t   need to restore the hardware to the ground state before we can\n\t\t   continue */\n#ifdef TEST_KEYGEN\n\t\tif( deviceType != CRYPT_DEVICE_CRYPTOAPI && \\\n\t\t\t( TEST_INITIALISE_DEVICE || deviceType == CRYPT_DEVICE_HARDWARE ) )\n\t\t\t{\n\t\t\tstatus = initialiseDevice( cryptDevice, deviceType,\n\t\t\t\t\t\t\t\t\t   deviceInfo );\n\t\t\tif( status == FALSE )\n\t\t\t\t{\n\t\t\t\tcryptDeviceClose( cryptDevice );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n#endif /* TEST_KEYGEN */\n\t\t\t{\n\t\t\t/* There may be test keys lying around from an earlier run, in\n\t\t\t   which case we try to delete them to make sure they won't\n\t\t\t   interfere with the current one */\n\t\t\tdeleteTestKey( cryptDevice, \"Test CA key\", \"CA\" );\n\t\t\tdeleteTestKey( cryptDevice, deviceInfo->keyLabel, \"user\" );\n\t\t\tif( deviceType == CRYPT_DEVICE_PKCS11 )\n\t\t\t\t{\n\t\t\t\tdeleteTestKey( cryptDevice, RSA_PUBKEY_LABEL, \"RSA public\" );\n\t\t\t\tdeleteTestKey( cryptDevice, RSA_PRIVKEY_LABEL, \"RSA private\" );\n\t\t\t\tdeleteTestKey( cryptDevice, DSA_PUBKEY_LABEL, \"DSA public\" );\n\t\t\t\tdeleteTestKey( cryptDevice, DSA_PRIVKEY_LABEL, \"DSA private\" );\n\t\t\t\tdeleteTestKey( cryptDevice, ECDSA_PUBKEY_LABEL, \"ECDSA public\" );\n\t\t\t\tdeleteTestKey( cryptDevice, ECDSA_PRIVKEY_LABEL, \"ECDSA private\" );\n\t\t\t\tdeleteTestKey( cryptDevice, SYMMETRIC_KEY_LABEL, \"symmetric\" );\n\t\t\t\tassert( cACertData[ 3 ].type == CRYPT_CERTINFO_COMMONNAME );\n\t\t\t\tdeleteTestKey( cryptDevice, cACertData[ 3 ].stringValue,\n\t\t\t\t\t\t\t   \"CA-cert\" );\n\t\t\t\tassert( userCertData[ 2 ].type == CRYPT_CERTINFO_COMMONNAME );\n\t\t\t\tdeleteTestKey( cryptDevice, userCertData[ 2 ].stringValue,\n\t\t\t\t\t\t\t   \"user-cert\" );\n\t\t\t\tassert( userSigOnlyCertData[ 2 ].type == CRYPT_CERTINFO_COMMONNAME );\n\t\t\t\tdeleteTestKey( cryptDevice, \n\t\t\t\t\t\t\t   userSigOnlyCertData[ 2 ].stringValue,\n\t\t\t\t\t\t\t   \"sig-only-cert\" );\n\t\t\t\tassert( userKeyAgreeCertData[ 2 ].type == CRYPT_CERTINFO_COMMONNAME );\n\t\t\t\tdeleteTestKey( cryptDevice, \n\t\t\t\t\t\t\t   userKeyAgreeCertData[ 2 ].stringValue,\n\t\t\t\t\t\t\t   \"keyagree-only-cert\" );\n\t\t\t\t}\n\t\t\tif( deviceType == CRYPT_DEVICE_FORTEZZA )\n\t\t\t\tdeleteTestKey( cryptDevice, \"Test KEA key\", \"KEA\" );\n\t\t\tif( deviceType == CRYPT_DEVICE_CRYPTOAPI )\n\t\t\t\t{\n\t\t\t\tdeleteTestKey( cryptDevice, \"Encryption key\", \"RSA private\" );\n\t\t\t\tdeleteTestKey( cryptDevice, \"Signature key\", \"secondary RSA private\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n#ifdef TEST_DH\n\treturn( testLowlevel( cryptDevice, CRYPT_ALGO_DH, FALSE ) );\n#endif /* TEST_DH */\n\n\t/* Report what the device can do.  This is intended mostly for simple\n\t   crypto accelerators and may fail with for devices that work only\n\t   with the higher-level functions centered around certificates,\n\t   signatures,and key wrapping, so we skip the tests for devices that\n\t   allow only high-level access */\n#ifdef TEST_ALGORITHMS\n\tif( deviceType != CRYPT_DEVICE_FORTEZZA )\n\t\t{\n\t\ttestResult = testDeviceCapabilities( cryptDevice, deviceName,\n\t\t\t\t\t\t\t\t\t\t\t isWriteProtected );\n\t\t}\n#else\n\tputs( \"Skipping device algorithm tests.\" );\n#endif /* TEST_ALGORITHMS */\n\n\t/* If it's a smart device, try various device-specific operations */\n\tif( deviceType == CRYPT_DEVICE_FORTEZZA || \\\n\t\tdeviceType == CRYPT_DEVICE_PKCS11 || \\\n\t\tdeviceType == CRYPT_DEVICE_CRYPTOAPI || \\\n\t\tdeviceType == CRYPT_DEVICE_HARDWARE )\n\t\t{\n\t\tpartialSuccess = testDeviceHighlevel( cryptDevice, deviceType,\n\t\t\t\t\t\t\t\tdeviceInfo->keyLabel, deviceInfo->password,\n\t\t\t\t\t\t\t\tisWriteProtected );\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDeviceClose( cryptDevice );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDeviceClose() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !testResult && !partialSuccess )\n\t\treturn( FALSE );\n\tif( testResult && partialSuccess )\n\t\tprintf( \"\\n%s tests succeeded.\\n\\n\", deviceName );\n\telse\n\t\tprintf( \"\\nSome %s tests succeeded.\\n\\n\", deviceName );\n\treturn( TRUE );\n\t}\n\nint testDevices( void )\n\t{\n\tint i, status;\n\n\t/* Test PKCS #11 devices */\n#ifdef TEST_PKCS11\n\tfor( i = 0; pkcs11DeviceInfo[ i ].name != NULL; i++ )\n\t\t{\n\t\tstatus = testCryptoDevice( CRYPT_DEVICE_PKCS11, \"PKCS #11 crypto token\",\n\t\t\t\t\t\t\t\t   &pkcs11DeviceInfo[ i ] );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\t!( status == CRYPT_ERROR_NOTAVAIL || \\\n\t\t\t   ( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* TEST_PKCS11 */\n\n\t/* Test generic crypto hardware interface */\n#ifdef TEST_GENERIC_HARDWARE\n\tfor( i = 0; hardwareDeviceInfo[ i ].name != NULL; i++ )\n\t\t{\n\t\tstatus = testCryptoDevice( CRYPT_DEVICE_HARDWARE, \"generic crypto hardware\",\n\t\t\t\t\t\t\t\t   &hardwareDeviceInfo[ i ] );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\t!( status == CRYPT_ERROR_NOTAVAIL || \\\n\t\t\t   ( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* TEST_GENERIC_HARDWARE */\n\n#if 0\t/* For test purposes only to check CAPI data, don't use the CAPI code */\n#ifdef __WINDOWS__\n\tfor( i = 0; capiDeviceInfo[ i ].name != NULL; i++ )\n\t\t{\n\t\tstatus = testCryptoDevice( CRYPT_DEVICE_CRYPTOAPI, \"Microsoft CryptoAPI\",\n\t\t\t\t\t\t\t\t   &capiDeviceInfo[ i ] );\n\t\tif( cryptStatusError( status ) && \\\n\t\t\t!( status == CRYPT_ERROR_NOTAVAIL || \\\n\t\t\t   ( i == 0 && status == CRYPT_ERROR_WRONGKEY ) ) )\n\t\t\treturn( status );\n\t\t}\n#endif /* __WINDOWS__ */\n#endif /* 0 */\n\tputchar( '\\n' );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tFull Device Initialisation Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following code takes two unitialised devices and turns one into a\n   fully initialised CA device, which then runs a PnP PKI session that turns\n   the other into a fully initialised user device.\n\n   The following configuration options can be used to change the beaviour of\n   the self-test, for example to run it on the local machine in loopback mode\n   vs. running on two distinct machines.  Defining an IP address (or host\n   name) for SERVER_MACHINE_ADDRESS will have the client connect to that\n   address instead of running a local loopback test */\n\n#if 0\n  #define SERVER_MACHINE_ADDRESS\t\"161.5.99.22\"\n  #define SERVER_MACHINE_PORT\t\t4080\n  #define CLIENT_DEVICE_TYPE\t\tCRYPT_DEVICE_FORTEZZA\n  #define SERVER_DEVICE_TYPE\t\tCRYPT_DEVICE_FORTEZZA\n  #define CLIENT_ID\t\t\t\t\t\"25CHS-UDQBU-BPASM\"\n  #define CLIENT_AUTHENTICATOR\t\t\"5ZCJ8-34A5C-YSXRD-C9EME\"\n  #define CLIENT_TOKEN_SLOT\t\t\tCRYPT_USE_DEFAULT\n  #define NET_TIMEOUT\t\t\t\t300\n#else\n  #define SERVER_MACHINE_ADDRESS\t\"localhost\"\n  #define SERVER_MACHINE_PORT\t\t80\n  #define CLIENT_DEVICE_TYPE\t\tCRYPT_DEVICE_FORTEZZA\n  #define SERVER_DEVICE_TYPE\t\tCRYPT_DEVICE_FORTEZZA\n  #define CLIENT_TOKEN_SLOT\t\t\t1\n  #define NET_TIMEOUT\t\t\t\tCRYPT_USE_DEFAULT\n#endif /* Loopback vs. general test */\n\n/* Default PIN values */\n\n#if CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA\n  #define DEFAULT_SSO_PIN\tFORTEZZA_SSO_DEFAULT_PIN\n#else\n  #define DEFAULT_SSO_PIN\t\"0000\"\n#endif /* Fortezza vs. PKCS #11 default SSO PINs */\n#define SSO_PIN\t\t\t\t\"0000\"\n#define USER_PIN\t\t\t\"0000\"\n\n/* Set up a client/server to connect locally (usually) or to a custom\n   address and port if we're running on distinct machines.  For the client\n   this simply tells it where to connect, for the server in loopback mode\n   this binds it to the local address so that we don't inadvertently open\n   up outside ports */\n\nstatic BOOLEAN setConnectInfo( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t\t   const char *address, const int port,\n\t\t\t\t\t\t\t   const int timeout )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t  address,  strlen( address ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_PORT, port );\n\tif( cryptStatusOK( status ) && timeout != CRYPT_USE_DEFAULT )\n\t\t{\n\t\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t   NET_TIMEOUT );\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_WRITETIMEOUT,\n\t\t\t\t\t\t\t\t\tNET_TIMEOUT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute/AttributeString() failed with error code \"\n\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Create a CA certificate in a device */\n\nstatic const CERT_DATA rootCACertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, \"AT\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, \"IAEA\" },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, \"SGTIE\" },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, \"IAEA CA root\" },\n\n\t/* Self-signed X.509v3 CA certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\n\t/* Access information */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_AUTHORITYINFO_RTCS },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, \"http://localhost\" },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic int createCACert( const CRYPT_DEVICE cryptDevice )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CERTIFICATE cryptCert;\n\tint status;\n\n\t/* Generate a key in the device */\n\tprintf( \"Generating a CA key in the device...\" );\n\tstatus = cryptDeviceCreateContext( cryptDevice, &cryptContext,\n\t\t\t\t\t\t( SERVER_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA ) ? \\\n\t\t\t\t\t\t\tCRYPT_ALGO_DSA : CRYPT_ALGO_RSA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptDeviceCreateContext() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t  \"CA key\", strlen( \"CA key\" ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tprintf( \"\\ncryptGenerateKey() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\t/* Create a certificate for the key */\n\tprintf( \"Generating a CA certificate for the key...\" );\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED, \n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCert, rootCACertData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, cryptContext );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyCert( cryptCert );\n\t\tprintf( \"\\nCreation of certificate failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\t/* Update the key with the CA certificate */\n\tprintf( \"Updating device with certificate...\" );\n\tstatus = cryptAddPublicKey( cryptDevice, cryptCert );\n\tcryptDestroyCert( cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptAddPublicKey() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\treturn( TRUE );\n\t}\n\n/* Connect to a device */\n\nstatic int connectDevice( CRYPT_DEVICE *cryptDevice, CRYPT_DEVICE_TYPE type,\n\t\t\t\t\t\t  const int slotNo )\n\t{\n\tchar buffer[ 128 ];\n\tint status;\n\n\t/* Clear return value */\n\t*cryptDevice = -1;\n\n\t/* Connect to the device */\n\tif( slotNo == CRYPT_USE_DEFAULT )\n\t\t{\n\t\tprintf( \"Connecting to crypto device in default slot...\" );\n\t\tstrcpy( buffer, \"[Autodetect]\" );\n\t\t}\n\telse\n\t\t{\n\t\tprintf( \"Connecting to crypto device in slot %d...\", slotNo );\n\t\tsprintf( buffer, \"[Autodetect]::%d\", slotNo );\n\t\t}\n\tstatus = cryptDeviceOpen( cryptDevice, CRYPT_UNUSED, type, buffer );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_PARAM3 || status == CRYPT_ERROR_NOTFOUND )\n\t\t\tputs( \"\\nDevice not detected, skipping test.\" );\n\t\telse\n\t\t\tprintf( \"\\ncryptDeviceOpen() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\treturn( TRUE );\n\t}\n\n/* Log on to a device */\n\nstatic int logonDevice( const CRYPT_DEVICE cryptDevice, const char *userPIN )\n\t{\n\tchar tokenLabel[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint loggedOn, tokenLabelSize, status;\n\n\t/* Tell the user what we're talking to */\n\tstatus = cryptGetAttributeString( cryptDevice, CRYPT_DEVINFO_LABEL,\n\t\t\t\t\t\t\t\t\t  tokenLabel, &tokenLabelSize );\n\tif( cryptStatusError( status ) )\n\t\tputs( \"(Device doesn't appear to have a label).\" );\n\telse\n\t\t{\n\t\ttokenLabel[ tokenLabelSize ] = '\\0';\n\t\tprintf( \"Device label is '%s'.\\n\", tokenLabel );\n\t\t}\n\n\t/* See if we need to authenticate ourselves */\n\tstatus = cryptGetAttribute( cryptDevice, CRYPT_DEVINFO_LOGGEDIN,\n\t\t\t\t\t\t\t\t&loggedOn );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't obtain device login status.\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( loggedOn )\n\t\t{\n\t\t/* Device may not require a login, or has already been logged in\n\t\t   via a keypad or similar mechanism */\n\t\tputs( \"Device is already logged in, skipping login.\" );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Try and log in */\n\tprintf( \"Logging on to the device...\" );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\tCRYPT_DEVINFO_AUTHENT_USER, userPIN,\n\t\t\t\t\t\t\t\tstrlen( userPIN ) );\n\tif( status == CRYPT_ERROR_INITED )\n\t\t{\n\t\t/* Some devices may not require any login, in which case we're\n\t\t   done */\n\t\tputs( \" device is already logged in.\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( status == CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\t/* It's an uninitialised device, tell the user and exit */\n\t\tputs( \" device needs to be initialised.\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nDevice login failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\treturn( TRUE );\n\t}\n\n/* Initialise a device */\n\nstatic int initDevice( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t   const char *defaultSSOPIN, const char *ssoPIN,\n\t\t\t\t\t   const char *userPIN )\n\t{\n\tint status;\n\n\t/* Most devices don't distinguish between zeroisation and initialisation\n\t   so we only need to zeroise the device if it's a Fortezza card */\n\tif( CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA )\n\t\t{\n\t\tprintf( \"Zeroising device...\" );\n\t\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\tCRYPT_DEVINFO_ZEROISE, FORTEZZA_ZEROISE_PIN,\n\t\t\t\t\t\tstrlen( FORTEZZA_ZEROISE_PIN ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\nCouldn't zeroise device, status = %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tputs( \" done.\" );\n\t\t}\n\n\t/* Initialise the device and set the SO PIN */\n\tprintf( \"Initialising device with default SO PIN '%s'...\",\n\t\t\tdefaultSSOPIN );\n\tstatus = cryptSetAttributeString( cryptDevice, CRYPT_DEVINFO_INITIALISE,\n\t\t\t\t\t\t\t\t\t  defaultSSOPIN, strlen( defaultSSOPIN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't initialise device, status = %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\tprintf( \"Setting SO PIN to '%s'...\", ssoPIN );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_SET_AUTHENT_SUPERVISOR,\n\t\t\t\t\t\t\t\t\t  ssoPIN, strlen( ssoPIN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't set SO PIN, status = %d, line %d.\\n\", status,\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\t/* If it's a Fortezza card, create a dummy PAA key and install its \n\t   certificate.  We have to do it at this point because the operation is \n\t   only allowed in the SSO initialised state.  In addition we can't use \n\t   the card for this operation because certificate slot 0 is a data-only \n\t   slot (that is, it can't correspond to a key held on the card) so we \n\t   create a dummy external certificate and use that */\n\tif( CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert;\n\t\tCRYPT_CONTEXT signContext;\n\n\t\tprintf( \"Loading PAA certificate...\" );\n\t\tif( !loadDSAContexts( CRYPT_UNUSED, &signContext, NULL ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, signContext );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!addCertFields( cryptCert, paaCertData, __LINE__ ) )\n\t\t\treturn( FALSE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSignCert( cryptCert, signContext );\n\t\tcryptDestroyContext( signContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t\tprintf( \"\\nCreation of certificate failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptDevice, cryptCert );\n\t\tcryptDestroyCert( cryptCert );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\ncryptAddPublicKey() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tputs( \" done.\" );\n\t\t}\n\n\t/* Set the user PIN and log on as the user.  Some devices automatically\n\t   log the user in when they set the user password, however, for some\n\t   devices this is a pseudo-login for which any subsequent operations\n\t   fail with a not-logged-in error or something similar, so rather than\n\t   relying on the existing login we always (re-)log in, which performs\n\t   an explicit logoff if we're already logged in at the time */\n\tprintf( \"Setting user PIN to '%s'...\", userPIN );\n\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_SET_AUTHENT_USER,\n\t\t\t\t\t\t\t\t\t  userPIN, strlen( userPIN ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttributeString( cryptDevice,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_AUTHENT_USER,\n\t\t\t\t\t\t\t\t\t\t  userPIN, strlen( userPIN ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCouldn't set user PIN/log on as user, status = %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\treturn( TRUE );\n\t}\n\n/* Open a certificate store */\n\nstatic int openCertStore( CRYPT_KEYSET *cryptCertStore )\n\t{\n\tint status;\n\n\t/* Clear return value */\n\t*cryptCertStore = -1;\n\n\t/* Open the certificate store */\n\tprintf( \"Opening CA certificate store...\" );\n\tstatus = cryptKeysetOpen( cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_KEYSET_ODBC_STORE, \"testcertstore\",\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\tstatus = cryptKeysetOpen( cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_ODBC_STORE, \"testcertstore\",\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\treturn( TRUE );\n\t}\n\n/* Add a PKI user to a certificate store */\n\nstatic int initUserInfo( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t const char *userName )\n\t{\n\tCRYPT_CERTIFICATE cryptPKIUser;\n\tint length, status;\n\n\t/* Create the PKI user object and add the user's identification\n\t   information */\n\tprintf( \"Creating PKI user...\" );\n\tstatus = cryptCreateCert( &cryptPKIUser, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptCreateCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME, userName,\n\t\t\t\t\t\t\t\t\t  strlen( userName ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( attrErrorExit( cryptPKIUser, \"cryptSetAttributeString()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\tputs( \" done.\" );\n\n\t/* Add the user info to the certificate store */\n\tprintf( \"Adding PKI user to CA certificate store...\" );\n\tstatus = cryptCAAddItem( cryptCertStore, cryptPKIUser );\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tchar userCN[ CRYPT_MAX_TEXTSIZE + 1 ];\n\n\t\t/* The PKI user info is already present from a previous run, get the\n\t\t   existing info */\n\t\tprintf( \"\\nPKI user information is already present from a previous \"\n\t\t\t\t\"run, re-using existing\\n  PKI user data...\" );\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t\t  userCN, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( attrErrorExit( cryptPKIUser, \"cryptGetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\tuserCN[ length ] = '\\0';\n\t\tcryptDestroyCert( cryptPKIUser );\n\t\tstatus = cryptCAGetItem( cryptCertStore, &cryptPKIUser,\n\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t userCN );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAAddItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\tputs( \" done.\" );\n\n\t/* Display the information for the user */\n\tif( !printCertInfo( cryptPKIUser ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptPKIUser );\n\treturn( TRUE );\n\t}\n\n/* Get details for a PKI user */\n\nstatic int getUserInfo( char *userID, char *issuePW )\n\t{\n#ifndef CLIENT_ID\n\tCRYPT_KEYSET cryptCertStore;\n\tCRYPT_CERTIFICATE cryptPKIUser;\n\tint length, status;\n\n\t/* Get the PKIUser object from the certificate store */\n\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_KEYSET_ODBC_STORE, \"testcertstore\",\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCAGetItem( cryptCertStore, &cryptPKIUser,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t \"Test PKI user\" );\n\tcryptKeysetClose( cryptCertStore );\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAGetItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\n\t/* Extract the information from the PKIUser object */\n\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ID,\n\t\t\t\t\t\t\t\t\t  userID, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tuserID[ length ] = '\\0';\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\n\t\t\t\t\t\t\t\t\tissuePW, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tissuePW[ length ] = '\\0';\n\tcryptDestroyCert( cryptPKIUser );\n\tif( cryptStatusError( status ) )\n\t\treturn( attrErrorExit( cryptPKIUser, \"cryptGetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n#else\n\tstrcpy( userID, CLIENT_ID );\n\tstrcpy( issuePW, CLIENT_AUTHENTICATOR );\n#endif /* CLIENT_ID */\n\n\t/* We've got what we need, tell the user what we're doing */\n\tprintf( \"Using user name %s, password %s.\\n\", userID, issuePW );\n\treturn( TRUE );\n\t}\n\n/* Run the PnP PKI server */\n\nstatic int pnpServer( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t  const CRYPT_KEYSET cryptCertStore )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT cryptPrivateKey;\n\tint caCertTrusted, status;\n\n\t/* Perform a cleanup action to remove any leftover requests from\n\t   previous runs */\n\tstatus = cryptCACertManagement( NULL, CRYPT_CERTACTION_CLEANUP, \n\t\t\t\t\t\t\t\t\tcryptCertStore, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCA certificate store cleanup failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the CA's key from the device and make it trusted for PKIBoot\n\t   functionality.  If we're running the test in loopback mode with the\n\t   Fortezza interface we can't have both the client and server using\n\t   Fortezza cards due to Spyrus driver bugs, and also can't have the\n\t   client and server as PKCS #11 and Fortezza due to other driver bugs,\n\t   so we have to fake the CA key using a software-only implementation */\n\tprintf( \"Making CA certificate trusted for PKIBoot...\" );\n#ifndef CLIENT_ID\n\tif( CLIENT_DEVICE_TYPE == CRYPT_DEVICE_FORTEZZA )\n\t\tstatus = getPrivateKey( &cryptPrivateKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\telse\n#endif /* CLIENT_ID */\n\t\tstatus = cryptGetPrivateKey( cryptDevice, &cryptPrivateKey,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \"CA key\", NULL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nCA private key read failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptGetAttribute( cryptPrivateKey, CRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t   &caCertTrusted );\n\tcryptSetAttribute( cryptPrivateKey, CRYPT_CERTINFO_TRUSTED_IMPLICIT, 1 );\n\tputs( \" done.\" );\n\n\t/* Create the CMP session and add the CA key and certificate store */\n\tprintf( \"Creating CMP server session...\" );\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP_SERVER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptCreateSession() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, cryptPrivateKey );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, cryptCertStore );\n\tif( cryptStatusError( status ) )\n\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\tif( !setConnectInfo( cryptSession, SERVER_MACHINE_ADDRESS,\n\t\t\t\t\t\t SERVER_MACHINE_PORT, NET_TIMEOUT ) )\n\t\treturn( FALSE );\n\tputs( \" done.\" );\n\n\t/* Activate the session */\n\tstatus = activatePersistentServerSession( cryptSession, TRUE );\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptSession, \"Attempt to activate CMP \"\n\t\t\t\t\t\t\t  \"server session\", status, __LINE__ ) );\n\n\t/* Clean up */\n\tcryptDestroySession( cryptSession );\n\tif( !caCertTrusted )\n\t\tcryptSetAttribute( cryptPrivateKey,\n\t\t\t\t\t\t   CRYPT_CERTINFO_TRUSTED_IMPLICIT, 0 );\n\n\treturn( TRUE );\n\t}\n\n/* Run the PnP PKI client */\n\nstatic int pnpClient( const CRYPT_DEVICE cryptDevice, const char *userID,\n\t\t\t\t\t  const char *issuePW )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\t/* Create the CMP session and set up the information we need for the\n\t   plug-and-play PKI process */\n\tprintf( \"Creating CMP client session...\" );\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptCreateSession() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME, userID,\n\t\t\t\t\t\t\t\t\t  paramStrlen( userID ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  issuePW, paramStrlen( issuePW ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t\t\t\t\tcryptDevice );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\nAddition of session information failed with error code \"\n\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setConnectInfo( cryptSession, SERVER_MACHINE_ADDRESS,\n\t\t\t\t\t\t SERVER_MACHINE_PORT, NET_TIMEOUT ) )\n\t\treturn( FALSE );\n\tputs( \" done.\" );\n\n\t/* Activate the session */\n\tprintf( \"Obtaining keys and certs...\" );\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"\\nAttempt to activate plug-and-play \"\n\t\t\t\t\t   \"PKI client session\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \" done.\" );\n\n\t/* Clean up */\n\tcryptDestroySession( cryptSession );\n\treturn( TRUE );\n\t}\n\n/* Client/server test harness */\n\nstatic int testServer( void )\n\t{\n\tCRYPT_KEYSET cryptCertStore;\n\tCRYPT_DEVICE cryptDevice;\n\tint status;\n\n\t/* Open the device and certificate store */\n\tstatus = connectDevice( &cryptDevice, SERVER_DEVICE_TYPE, 0 );\n\tif( status )\n\t\tstatus = openCertStore( &cryptCertStore );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Create a CA key in the device.  Due to Spyrus bugs it's necessary to \n\t   disconnect from the device and then re-connect after initialising it \n\t   or crypto operations fail in various ways.  In older (and even \n\t   buggier) devices crypto ops simply fail after initialisation and it \n\t   may be necessary to eject and re-insert the card before they'll work \n\t   properly */\n#if 0\n\tstatus = initDevice( cryptDevice, DEFAULT_SSO_PIN, SSO_PIN, USER_PIN );\n\tcryptDeviceClose( cryptDevice );\n\tif( status )\n\t\tstatus = connectDevice( &cryptDevice, SERVER_DEVICE_TYPE, 0 );\n\tif( status )\n\t\tstatus = logonDevice( cryptDevice, USER_PIN );\n\tif( status )\n\t\tstatus = createCACert( cryptDevice );\n#else\n\tstatus = logonDevice( cryptDevice, USER_PIN );\n#endif /* 0 */\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Init the PKI user */\n\tstatus = initUserInfo( cryptCertStore, \"Test user #1\" );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Run the PnP PKI server */\n\tstatus = pnpServer( cryptDevice, cryptCertStore );\n\n\t/* Clean up */\n\tcryptDeviceClose( cryptDevice );\n\tcryptKeysetClose( cryptCertStore );\n\n\treturn( status );\n\t}\n\nstatic int testClient( void )\n\t{\n\tCRYPT_DEVICE cryptDevice;\n\tchar userID[ CRYPT_MAX_TEXTSIZE + 1 ], issuePW[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint status;\n\n\t/* Open the device and get the user ID and password from the certificate \n\t   store.  Normally this would be communicated directly, for our test \n\t   purposes we cheat and get it from the certificate store */\n\tstatus = connectDevice( &cryptDevice, CLIENT_DEVICE_TYPE,\n\t\t\t\t\t\t\tCLIENT_TOKEN_SLOT );\n\tif( status )\n\t\tstatus = getUserInfo( userID, issuePW );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Initialise the device */\n#if 1\n\tstatus = initDevice( cryptDevice, DEFAULT_SSO_PIN, SSO_PIN, USER_PIN );\n\tcryptDeviceClose( cryptDevice );\n\tif( status )\n\t\tstatus = connectDevice( &cryptDevice, CLIENT_DEVICE_TYPE,\n\t\t\t\t\t\t\t\tCLIENT_TOKEN_SLOT );\n\tif( status )\n\t\tstatus = logonDevice( cryptDevice, USER_PIN );\n#else\n\tstatus = logonDevice( cryptDevice, USER_PIN );\n#endif /* 0 */\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Run the PnP PKI client */\n\tstatus = pnpClient( cryptDevice, userID, issuePW );\n\n\t/* Clean up */\n\tcryptDeviceClose( cryptDevice );\n\n\treturn( status );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall serverThread( void *dummy )\n\t{\n\ttestServer();\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testDeviceLifeCycle( void )\n\t{\n#ifdef CLIENT_ID\n#if 1\n\treturn( testClient() );\n#else\n\treturn( testServer() );\n#endif /* 0 */\n#else\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait 15s for it to initialise */\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, serverThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 15000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = testClient();\n\tif( WaitForSingleObject( hThread, 15000 ) == WAIT_TIMEOUT )\n\t\t{\n\t\tputs( \"Warning: Server thread is still active due to session \"\n\t\t\t  \"negotiation failure,\\n         this will cause an error \"\n\t\t\t  \"condition when cryptEnd() is called due\\n         to \"\n\t\t\t  \"resources remaining allocated.  Press a key to continue.\" );\n\t\tgetchar();\n\t\t}\n\tCloseHandle( hThread );\n\n\treturn( status );\n#endif /* CLIENT_ID */\n\t}\n#endif /* WINDOWS_THREADS */\n#endif /* WinCE */\n\n#endif /* TEST_DEVICE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tUser Management Routines Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_USER\n\nint testUser( void )\n\t{\n\tCRYPT_USER cryptUser;\n\tint status;\n\n\tputs( \"Testing (minimal) user management functions...\" );\n\n\t/* Perform a zeroise.  This currently isn't done because (a) it would\n\t   zeroise all user data whenever anyone runs the self-test and (b) the\n\t   external API to trigger this isn't defined yet */\n/*\tstatus = cryptZeroise( ... ); */\n\n\t/* Log in as primary SO using the zeroisation password.  Because of the\n\t   above situation this currently performs an implicit zeroise */\n\tstatus = cryptLogin( &cryptUser, TEXT( \"Security officer\" ),\n\t\t\t\t\t\t TEXT( \"zeroised\" ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptLogin() (Primary SO) failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set the SO password */\n\tstatus = cryptSetAttributeString( cryptUser, CRYPT_USERINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t  TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttributeString() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Log out and log in again with the new password.  At the moment it's\n\t   possible to use any password until the PKCS #15 attribute situation\n\t   is resolved */\n\tstatus = cryptLogout( cryptUser );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptLogout() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptLogin( &cryptUser, TEXT( \"Security officer\" ),\n\t\t\t\t\t\t TEST_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptLogin() (SO) failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptLogout( cryptUser );\n\tputs( \"User management tests succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\n#endif /* TEST_USER */\n"
  },
  {
    "path": "deps/cl345/test/envelope.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Enveloping Test Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1996-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <limits.h>\t\t/* To determine max.buffer size we can encrypt */\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n#include \"misc/consts.h\"\t/* For DEFAULT_CRYPT_ALGO */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n/* Test data to use for the self-test.  The PGP test data is slightly\n   different since it's not possible to include a null character in data\n   generated via the command-line versions of PGP.  On EBCDIC systems we\n   have to hardcode in the character codes since the pre-generated data\n   came from an ASCII system */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #define ENVELOPE_TESTDATA\t\t( ( BYTE * ) \"\\x53\\x6F\\x6D\\x65\\x20\\x74\\x65\\x73\\x74\\x20\\x64\\x61\\x74\\x61\" )\n  #define ENVELOPE_PGP_TESTDATA\t( ( BYTE * ) \"\\x53\\x6F\\x6D\\x65\\x20\\x74\\x65\\x73\\x74\\x20\\x64\\x61\\x74\\x61\\x2E\" )\n  #define ENVELOPE_COMPRESSEDDATA\t\"\\x2F\\x2A\\x20\\x54\\x68\\x69\\x73\\x20\\x69\\x73\\x20\\x61\\x20\\x6C\\x6F\\x77\\x65\\x73\\x74\\x2D\"\n#else\n  #define ENVELOPE_TESTDATA\t\t( ( BYTE * ) \"Some test data\" )\n  #define ENVELOPE_PGP_TESTDATA\t( ( BYTE * ) \"Some test data.\" )\n  #define ENVELOPE_COMPRESSEDDATA\t\"/* This is a lowest-\"\n#endif /* EBCDIC systems */\n#define ENVELOPE_TESTDATA_SIZE\t\t\t15\n#define ENVELOPE_COMPRESSEDDATA_SIZE\t20\n\n/* External flags which indicate that the key read/update routines worked OK.\n   This is set by earlier self-test code, if it isn't set some of the tests\n   are disabled */\n\nextern int keyReadOK, doubleCertOK;\n\n#if defined( TEST_ENVELOPE ) || defined( TEST_SESSION )\t/* For TSP enveloping */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines \t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The general-purpose buffer used for enveloping.  We use a fixed buffer\n   if possible to save having to add huge amounts of allocation/deallocation\n   code */\n\nBYTE globalBuffer[ BUFFER_SIZE ];\n\n/* Determine the size of a file.  If there's a problem, we return the\n   default buffer size, which will cause a failure further up the chain\n   where the error can be reported better */\n\nstatic int getFileSize( const char *fileName )\n\t{\n\tFILE *filePtr;\n\tlong size;\n\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\treturn( BUFFER_SIZE );\n\tfseek( filePtr, 0L, SEEK_END );\n\tsize = ftell( filePtr );\n\tfclose( filePtr );\n\tif( size > INT_MAX )\n\t\treturn( BUFFER_SIZE );\n\n\treturn( ( int ) size );\n\t}\n\n/* Read test data from a file */\n\nstatic int readFileFromTemplate( const C_STR fileTemplate, const int count,\n\t\t\t\t\t\t\t\t const char *description, BYTE *buffer, \n\t\t\t\t\t\t\t\t const int bufSize )\n\t{\n\tBYTE fileName[ BUFFER_SIZE ];\n\n\tfilenameFromTemplate( fileName, fileTemplate, count );\n\treturn( readFileData( fileName, description, buffer, bufSize, 32, \n\t\t\t\t\t\t  FALSE ) );\n\t}\n\n/* Verify the contents of a data buffer */\n\nstatic void initBufferContents( BYTE *buffer, const int bufSize ) \n\t{\n\tint i;\n\n\tfor( i = 0; i < bufSize; i++ )\n\t\tbuffer[ i ] = i & 0xFF;\n\t}\n\nstatic int verifyBufferContents( const BYTE *buffer, const int bufSize,\n\t\t\t\t\t\t\t\t const int startCount )\n\t{\n\tint i;\n\n\tfor( i = 0; i < bufSize; i++ )\n\t\t{\n\t\tif( buffer[ i ] != ( ( startCount + i ) & 0xFF ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"De-enveloped data != original data at \"\n\t\t\t\t\t \"byte %d, line %d.\\n\", i, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Common routines to create an envelope, add enveloping information, push\n   data, pop data, and destroy an envelope */\n\nstatic int createEnvelope( CRYPT_ENVELOPE *envelope,\n\t\t\t\t\t\t   const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tint status;\n\n\t/* Create the envelope */\n\tstatus = cryptCreateEnvelope( envelope, CRYPT_UNUSED, formatType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateEnvelope() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int createDeenvelope( CRYPT_ENVELOPE *envelope )\n\t{\n\tint status;\n\n\t/* Create the envelope */\n\tstatus = cryptCreateEnvelope( envelope, CRYPT_UNUSED, CRYPT_FORMAT_AUTO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateEnvelope() for de-enveloping \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int addEnvInfoString( const CRYPT_ENVELOPE envelope,\n\t\t\t\t\t\t\t const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\t const void *envInfo, const int envInfoLen )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttributeString( envelope, type, envInfo, envInfoLen );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( envelope, \"cryptSetAttributeString()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int addEnvInfoNumeric( const CRYPT_ENVELOPE envelope,\n\t\t\t\t\t\t\t  const CRYPT_ATTRIBUTE_TYPE type,\n\t\t\t\t\t\t\t  const int envInfo )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttribute( envelope, type, envInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( envelope, \"cryptSetAttributeString()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int processEnvelopeResource( const CRYPT_ENVELOPE envelope, \n\t\t\t\t\t\t\t\t\tconst void *stringEnvInfo,\n\t\t\t\t\t\t\t\t\tconst int numericEnvInfo,\n\t\t\t\t\t\t\t\t\tBOOLEAN *isRestartable )\n\t{\n\tBOOLEAN isWrongKey = FALSE, exitLoop = FALSE;\n\tint cryptEnvInfo, cryptAlgo, keySize DUMMY_INIT;\n\tint integrityLevel, iteration = 0, status;\n\n\t/* Args are either NULL, a handle, or { data, length } */\n\tassert( ( stringEnvInfo == NULL && numericEnvInfo == 0 ) || \\\n\t\t\t( stringEnvInfo == NULL && numericEnvInfo != 0 ) || \\\n\t\t\t( stringEnvInfo != NULL && numericEnvInfo >= 1 ) );\n\n\t/* Clear return value */\n\t*isRestartable = FALSE;\n\t\n\t/* Add the appropriate enveloping information that we need to \n\t   continue */\n\tstatus = cryptSetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to move cursor to start of list \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( status );\n\t\t}\n\tdo\n\t\t{\n\t\tC_CHR label[ CRYPT_MAX_TEXTSIZE + 1 ];\n\t\tint labelLength;\n\n\t\tstatus = cryptGetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t&cryptEnvInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Attempt to read current group failed \"\n\t\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\titeration++;\n\n\t\tswitch( cryptEnvInfo )\n\t\t\t{\n\t\t\tcase CRYPT_ATTRIBUTE_NONE:\n\t\t\t\t/* The required information was supplied via other means (in \n\t\t\t\t   practice this means there's a crypto device available and \n\t\t\t\t   that was used for the decrypt), there's nothing left to \n\t\t\t\t   do */\n\t\t\t\tfputs( \"(Decryption key was recovered using crypto device \"\n\t\t\t\t\t   \"or non-password-protected\\n private key).\\n\", \n\t\t\t\t\t   outputStream );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_PRIVATEKEY:\n\t\t\t\t/* If there's no decryption password present, the private \n\t\t\t\t   key must be passed in directly */\n\t\t\t\tif( stringEnvInfo == NULL )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = cryptSetAttribute( envelope,\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t\t\t\t\tnumericEnvInfo );\n\t\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tif( status != CRYPT_ERROR_WRONGKEY )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfprintf( outputStream, \"Attempt to add private \"\n\t\t\t\t\t\t\t\t\t \"key failed with error code %d, \"\n\t\t\t\t\t\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\t\t\t\t\t\treturn( status );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tfprintf( outputStream, \"Attempt to add private key \"\n\t\t\t\t\t\t\t\t \"for attribute #%d failed with \"\n\t\t\t\t\t\t\t\t \"CRYPT_ERROR_WRONGKEY,\\n  trying for \"\n\t\t\t\t\t\t\t\t \"subsequent attributes.\\n\", iteration );\n\t\t\t\t\t\tisWrongKey = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\tif( isWrongKey )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tisWrongKey = FALSE;\n\t\t\t\t\t\t\tfprintf( outputStream, \"Decryption succeeded \"\n\t\t\t\t\t\t\t\t\t \"for attribute #%d.\\n\", iteration );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\texitLoop = TRUE;\n\t\t\t\t\t\t}\n\t\t\t\t\t*isRestartable = TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t/* A private-key keyset is present in the envelope, we need \n\t\t\t\t   a password to decrypt the key */\n\t\t\t\tstatus = cryptGetAttributeString( envelope,\n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PRIVATEKEY_LABEL,\n\t\t\t\t\t\t\t\t\tlabel, &labelLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Private key label read failed \"\n\t\t\t\t\t\t\t \"with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t\t __LINE__ );\n\t\t\t\t\treturn( status );\n\t\t\t\t\t}\n#ifdef UNICODE_STRINGS\n\t\t\t\tlabel[ labelLength / sizeof( wchar_t ) ] = '\\0';\n\t\t\t\tfprintf( outputStream, \"Need password to decrypt private \"\n\t\t\t\t\t\t \"key '%S'.\\n\", label );\n#else\n\t\t\t\tlabel[ labelLength ] = '\\0';\n\t\t\t\tfprintf( outputStream, \"Need password to decrypt private key \"\n\t\t\t\t\t\t \"'%s'.\\n\", label );\n#endif /* UNICODE_STRINGS */\n\t\t\t\tif( !addEnvInfoString( envelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t   stringEnvInfo, numericEnvInfo ) )\n\t\t\t\t\treturn( SENTINEL );\n\t\t\t\t*isRestartable = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_PASSWORD:\n\t\t\t\tfputs( \"Need user password.\\n\", outputStream );\n\t\t\t\tassert( stringEnvInfo != NULL );\t/* For static analysers */\n\t\t\t\tstatus = cryptSetAttributeString( envelope, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PASSWORD, stringEnvInfo, \n\t\t\t\t\t\t\t\t\tnumericEnvInfo );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tif( status != CRYPT_ERROR_WRONGKEY )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfprintf( outputStream, \"Attempt to add password \"\n\t\t\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", \n\t\t\t\t\t\t\t\t status, __LINE__ );\n\t\t\t\t\t\treturn( status );\n\t\t\t\t\t\t}\n\t\t\t\t\tfprintf( outputStream, \"Attempt to add password for \"\n\t\t\t\t\t\t\t \"attribute #%d failed with \"\n\t\t\t\t\t\t\t \"CRYPT_ERROR_WRONGKEY, trying for subsequent \"\n\t\t\t\t\t\t\t \"attributes.\\n\", iteration );\n\t\t\t\t\tisWrongKey = TRUE;\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( isWrongKey )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tisWrongKey = FALSE;\n\t\t\t\t\t\tfprintf( outputStream, \"Decryption succeeded for \"\n\t\t\t\t\t\t\t\t \"attribute #%d.\\n\", iteration );\n\t\t\t\t\t\t}\n\t\t\t\t\texitLoop = TRUE;\n\t\t\t\t\t}\n\t\t\t\t*isRestartable = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_SESSIONKEY:\n\t\t\t\tfputs( \"Need session key.\\n\", outputStream );\n\t\t\t\tif( !addEnvInfoNumeric( envelope, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t\t\t\tnumericEnvInfo ) )\n\t\t\t\t\treturn( SENTINEL );\n\t\t\t\t*isRestartable = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_KEY:\n\t\t\t\tfputs( \"Need conventional encryption key.\\n\", \n\t\t\t\t\t   outputStream );\n\t\t\t\tif( !addEnvInfoNumeric( envelope, CRYPT_ENVINFO_KEY,\n\t\t\t\t\t\t\t\t\t\tnumericEnvInfo ) )\n\t\t\t\t\treturn( SENTINEL );\n\t\t\t\t*isRestartable = TRUE;\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ENVINFO_SIGNATURE:\n\t\t\t\t/* If we've processed the entire data block in one go, we \n\t\t\t\t   may end up with only signature information available, in \n\t\t\t\t   which case we defer processing them until after we've \n\t\t\t\t   finished with the deenveloped data */\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tfprintf( outputStream, \"Need unknown enveloping information \"\n\t\t\t\t\t\t \"type %d.\\n\", cryptEnvInfo );\n\t\t\t\treturn( SENTINEL );\n\t\t\t}\n\t\t}\n\twhile( !exitLoop && \\\n\t\t   cryptSetAttribute( envelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\n\t/* If we couldn't find a usable decryption key, we can't go any \n\t   further */\n\tif( isWrongKey )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't find key capable of decrypting \"\n\t\t\t\t \"enveloped data, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check whether there's any integrity protection present */\n\tstatus = cryptGetAttribute( envelope, CRYPT_ENVINFO_INTEGRITY, \n\t\t\t\t\t\t\t\t&integrityLevel );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't query integrity protection used \"\n\t\t\t\t \"in envelope, status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tif( integrityLevel > CRYPT_INTEGRITY_NONE )\n\t\t{\n\t\t/* Display the integrity level.  For PGP it's not really a MAC but\n\t\t   a sort-of-keyed encrypted hash, but we call it a MAC to keep \n\t\t   things simple */\n\t\tfprintf( outputStream, \"Data is integrity-protected using %s \"\n\t\t\t\t \"authentication.\\n\",\n\t\t\t\t( integrityLevel == CRYPT_INTEGRITY_MACONLY ) ? \\\n\t\t\t\t\t\"MAC\" : \\\n\t\t\t\t( integrityLevel == CRYPT_INTEGRITY_FULL ) ? \\\n\t\t\t\t\t\"MAC+encrypt\" : \"unknown\" );\n\t\t}\n\n\t/* If we're not using encryption, we're done */\n\tif( cryptEnvInfo != CRYPT_ATTRIBUTE_NONE && \\\n\t\tcryptEnvInfo != CRYPT_ENVINFO_PRIVATEKEY && \\\n\t\tcryptEnvInfo != CRYPT_ENVINFO_PASSWORD )\n\t\t{\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( integrityLevel == CRYPT_INTEGRITY_MACONLY )\n\t\treturn( CRYPT_OK );\n\n\t/* If we're using some form of encrypted enveloping, report the \n\t   algorithm and keysize used */\n\tstatus = cryptGetAttribute( envelope, CRYPT_CTXINFO_ALGO, &cryptAlgo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( envelope, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t\t\t\t\t&keySize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't query encryption algorithm and \"\n\t\t\t\t \"keysize used in envelope, status %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( status );\n\t\t}\n\tfprintf( outputStream, \"Data is protected using algorithm %d with %d \"\n\t\t\t \"bit key.\\n\", cryptAlgo, keySize * 8 );\n\t\n\treturn( CRYPT_OK );\n\t}\n\nstatic int pushData( const CRYPT_ENVELOPE envelope, const BYTE *buffer,\n\t\t\t\t\t const int length, const void *stringEnvInfo,\n\t\t\t\t\t const int numericEnvInfo )\n\t{\n\tint bytesIn, contentType, status;\n\n\t/* Args are either NULL, a handle, or { data, length } */\n\tassert( ( stringEnvInfo == NULL && numericEnvInfo == 0 ) || \\\n\t\t\t( stringEnvInfo == NULL && numericEnvInfo != 0 ) || \\\n\t\t\t( stringEnvInfo != NULL && numericEnvInfo >= 1 ) );\n\n\t/* Push in the data */\n\tstatus = cryptPushData( envelope, buffer, length, &bytesIn );\n\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tBOOLEAN isRestartable = FALSE;\n\n\t\t/* Process the required de-enveloping resource */\n\t\tstatus = processEnvelopeResource( envelope, stringEnvInfo, \n\t\t\t\t\t\t\t\t\t\t  numericEnvInfo, &isRestartable );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* If we only got some of the data in due to the envelope stopping to\n\t\t   ask us for a decryption resource, push in the rest */\n\t\tif( bytesIn < length && isRestartable )\n\t\t\t{\n\t\t\tconst int initialBytesIn = bytesIn;\n\n\t\t\tstatus = cryptPushData( envelope, buffer + initialBytesIn,\n\t\t\t\t\t\t\t\t\tlength - initialBytesIn, &bytesIn );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"cryptPushData() for remaining data \"\n\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tbytesIn += initialBytesIn;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( envelope, \"cryptPushData()\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tif( bytesIn < length )\n\t\t{\n\t\tBYTE tempBuffer[ 8192 ];\n\t\tint bytesIn2, bytesOut;\n\n\t\t/* In the case of very large data quantities we may run out of \n\t\t   envelope buffer space during processing so we have to push the\n\t\t   remainder a second time.  Removing some of the data destroys\n\t\t   the ability to compare the popped data with the input data later\n\t\t   on, but this is only done for the known self-test data and not \n\t\t   for import of arbitrary external data quantities */\n\t\tfprintf( outputStream, \"(Ran out of input buffer data space, \"\n\t\t\t\t \"popping %d bytes to make room).\\n\", 8192 );\n\t\tstatus = cryptPopData( envelope, tempBuffer, 8192, &bytesOut );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptPopData() to make way for \"\n\t\t\t\t\t \"remaining data failed with error code %d, line %d.\\n\", \n\t\t\t\t\t status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = cryptPushData( envelope, buffer + bytesIn, \n\t\t\t\t\t\t\t\tlength - bytesIn, &bytesIn2 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( envelope, \"cryptPushData() of remaining data\", \n\t\t\t\t\t\t   status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\tbytesIn += bytesIn2;\n\t\t}\n\tif( bytesIn != length )\n\t\t{\n\t\tfprintf( outputStream, \"cryptPushData() only copied %d of %d \"\n\t\t\t\t \"bytes, line %d.\\n\", bytesIn, length, __LINE__ );\n\t\treturn( SENTINEL );\n\t\t}\n\n\t/* Flush the data */\n\tstatus = cryptFlushData( envelope );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_COMPLETE )\n\t\t{\n\t\tprintExtError( envelope, \"cryptFlushData()\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\n\t/* Now that we've finished processing the data, report the inner content \n\t   type.  We can't do in until this stage because some enveloping format\n\t   types encrypt the inner content type with the payload, so we can't \n\t   tell what it is until we've decrypted the payload */\n\tstatus = cryptGetAttribute( envelope, CRYPT_ENVINFO_CONTENTTYPE,\n\t\t\t\t\t\t\t\t&contentType );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tint value;\n\n\t\t/* A detached signature doesn't have any content to an inability to \n\t\t   determine the content type isn't a failure */\n\t\tstatus = cryptGetAttribute( envelope, CRYPT_ENVINFO_DETACHEDSIGNATURE,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusOK( status ) && value == TRUE )\n\t\t\t{\n\t\t\tfputs( \"(Data is from a detached signature, couldn't determine \"\n\t\t\t\t   \"content type).\\n\", outputStream );\n\t\t\treturn( bytesIn );\n\t\t\t}\n\t\tfprintf( outputStream, \"Couldn't query content type in envelope, \"\n\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tif( contentType != CRYPT_CONTENT_DATA )\n\t\t{\n\t\tfprintf( outputStream, \"Nested content type = %d.\\n\", \n\t\t\t\t contentType );\n\t\t}\n\n\treturn( bytesIn );\n\t}\n\nstatic int popData( CRYPT_ENVELOPE envelope, BYTE *buffer, int bufferSize )\n\t{\n\tint status, bytesOut;\n\n\tstatus = cryptPopData( envelope, buffer, bufferSize, &bytesOut );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( envelope, \"cryptPopData()\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\n\treturn( bytesOut );\n\t}\n\nstatic int destroyEnvelope( CRYPT_ENVELOPE envelope )\n\t{\n\tint status;\n\n\t/* Destroy the envelope */\n\tstatus = cryptDestroyEnvelope( envelope );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDestroyEnvelope() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tData Enveloping Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test raw data enveloping */\n\ntypedef enum {\n\tDATA_AMOUNT_SMALL,\n\tDATA_AMOUNT_MEDIUM,\n\tDATA_AMOUNT_LARGE,\n\tDATA_AMOUNT_VARIABLE,\n\tDATA_AMOUNT_MEDIUM_MULTIPLE\n\t} DATA_AMOUNT_TYPE;\n\nstatic int envelopeData( const char *dumpFileName,\n\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t const DATA_AMOUNT_TYPE dataAmountType,\n\t\t\t\t\t\t const int dataAmount,\n\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE *inBufPtr, *outBufPtr = globalBuffer;\n\tint length, bufSize, count;\n\n\tswitch( dataAmountType )\n\t\t{\n\t\tcase DATA_AMOUNT_SMALL:\n\t\t\tfprintf( outputStream, \"Testing %splain data enveloping%s...\\n\",\n\t\t\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\",\n\t\t\t\t\t ( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \\\n\t\t\t\t\t \" with datasize hint\" : \"\" );\n\t\t\tlength = ENVELOPE_TESTDATA_SIZE;\n\t\t\tinBufPtr = ENVELOPE_TESTDATA;\n\t\t\tbreak;\n\n\t\tcase DATA_AMOUNT_MEDIUM:\n\t\tcase DATA_AMOUNT_MEDIUM_MULTIPLE:\n\t\t\tfprintf( outputStream, \"Testing %splain data enveloping of \"\n\t\t\t\t\t \"%sintermediate-size data...\\n\",\n\t\t\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\",\n\t\t\t\t\t( dataAmountType == DATA_AMOUNT_MEDIUM_MULTIPLE ) ? \\\n\t\t\t\t\t  \"multiple blocks of \" : \"\" );\n\t\t\tlength = 512;\n\t\t\tinBufPtr = globalBuffer;\n\t\t\tinitBufferContents( inBufPtr, length );\n\t\t\tbreak;\n\n\t\tcase DATA_AMOUNT_LARGE:\n\t\t\tfprintf( outputStream, \"Testing %senveloping of large data \"\n\t\t\t\t\t \"quantity...\\n\",\n\t\t\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\" );\n\n\t\t\t/* Allocate a large buffer and fill it with a known value */\n\t\t\tlength = ( INT_MAX <= 32768L ) ? 16384 : 1048576;\n\t\t\tif( ( inBufPtr = malloc( length + 128 ) ) == NULL )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't allocate buffer of %d \"\n\t\t\t\t\t\t \"bytes, skipping large buffer enveloping test.\\n\\n\", \n\t\t\t\t\t\t length );\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\toutBufPtr = inBufPtr;\n\t\t\tinitBufferContents( inBufPtr, length );\n\t\t\tbreak;\n\n\t\tcase DATA_AMOUNT_VARIABLE:\n\t\t\tlength = dataAmount;\n\t\t\tinBufPtr = globalBuffer;\n\t\t\tinitBufferContents( inBufPtr, length );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\tbufSize = length + 128;\n\n\t/* Create the envelope, push in the data, pop the enveloped result, and\n\t   destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( useDatasize )\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE, length );\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\t\t\t\t\t   length + 1024 );\n\t\t}\n\tcount = pushData( cryptEnvelope, inBufPtr, length, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tcount = popData( cryptEnvelope, outBufPtr, bufSize );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( dataAmountType == DATA_AMOUNT_SMALL && \\\n\t\tcount != length + ( ( formatType == CRYPT_FORMAT_PGP ) ? 8 : \\\n\t\t\t\t\t\t\tuseDatasize ? 17 : 25 ) )\n\t\t{\n\t\tfprintf( outputStream, \"Enveloped data length %d, should be %d, \"\n\t\t\t\t \"line %d.\\n\", count, length + 25, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tif( dumpFileName != NULL && dataAmountType != DATA_AMOUNT_LARGE )\n\t\tdebugDump( dumpFileName, outBufPtr, count );\n\n\t/* Create the envelope, push in the data, pop the de-enveloped result,\n\t   and destroy the envelope */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\t\t\t\t\t   length + 1024 );\n\t\t}\n\tcount = pushData( cryptEnvelope, outBufPtr, count, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tcount = popData( cryptEnvelope, outBufPtr, bufSize );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\t{\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the result matches what we pushed */\n\tif( count != length )\n\t\t{\n\t\tfputs( \"De-enveloped data length != original length.\\n\", \n\t\t\t   outputStream );\n\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\tfree( inBufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( dataAmountType != DATA_AMOUNT_SMALL )\n\t\t{\n\t\tif( !verifyBufferContents( outBufPtr, length, 0 ) )\n\t\t\t{\n\t\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\t\tfree( inBufPtr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( !compareData( ENVELOPE_TESTDATA, length, outBufPtr, length ) )\n\t\t\t{\n\t\t\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t\t\tfree( inBufPtr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\tfree( inBufPtr );\n\tfputs( \"Enveloping of plain data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeData( void )\n\t{\n\tif( !envelopeData( \"env_datn\", FALSE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite-length */\n\tif( !envelopeData( \"env_dat\", TRUE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize */\n\tif( !envelopeData( \"env_dat.pgp\", TRUE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* PGP format */\n\treturn( envelopeData( \"env_datl.pgp\", TRUE, DATA_AMOUNT_MEDIUM, 0, CRYPT_FORMAT_PGP ) );\n\t}\t\t\t\t\t\t/* PGP format, longer data */\n\nint testEnvelopeDataLargeBuffer( void )\n\t{\n\tif( !envelopeData( NULL, TRUE, DATA_AMOUNT_LARGE, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, large buffer */\n\treturn( envelopeData( NULL, TRUE, DATA_AMOUNT_LARGE, 0, CRYPT_FORMAT_PGP ) );\n\t}\t\t\t\t\t\t/* Large buffer, PGP format */\n\nint testEnvelopeDataVariable( void )\n\t{\n\tFILE *origOutputStream = outputStream;\n\tconst int maxCount = min( BUFFER_SIZE, 8192 );\n\tint i;\t\t\t\t /* Maximum is 32600, from size of internal envelope buffer */\n\n\tfprintf( outputStream, \"Testing enveloping quantities from 1 to %d \"\n\t\t\t \"bytes to check for\\n  boundary errors...\\n\", maxCount );\n\n\toutputStream = fopen( DEVNULL, \"w\" );\n\tassert( outputStream != NULL );\n\tfor( i = 1; i < maxCount; i++ )\n\t\t{\n\t\tfprintf( origOutputStream, \"%d.\\r\", i );\n\t\tif( !envelopeData( NULL, FALSE, DATA_AMOUNT_VARIABLE, i, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"Failed for indefinite-length enveloping \"\n\t\t\t\t\t \"size %d.\\n\", i );\n\t\t\treturn( FALSE );\t/* Indefinite-length */\n\t\t\t}\n\t\tif( !envelopeData( NULL, TRUE, DATA_AMOUNT_VARIABLE, i, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"Failed for definite-length enveloping \"\n\t\t\t\t\t \"size %d.\\n\", i );\n\t\t\treturn( FALSE );\t/* Datasize */\n\t\t\t}\n\t\tif( !envelopeData( NULL, TRUE, DATA_AMOUNT_VARIABLE, i, CRYPT_FORMAT_PGP ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"Failed for PGP-format enveloping \"\n\t\t\t\t\t \"size %d.\\n\", i );\n\t\t\treturn( FALSE );\t/* PGP format */\n\t\t\t}\n\t\t}\n\toutputStream = origOutputStream;\n\n\tfprintf( outputStream, \"Boundary error test succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n\nstatic int envelopeDataMultiple( const int dataSize, \n\t\t\t\t\t\t\t\t const BOOLEAN useEncryption )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_ENVELOPE cryptEnvelope, decryptEnvelope;\n\tBYTE inBuffer[ BUFFER_SIZE ], *inBufPtr = inBuffer;\n\tBYTE *outBufPtr = globalBuffer;\n\tint count, startCount = 0, i, status;\n\n\t/* Create the encryption context that'll be used for en/de-enveloping */\n\tif( useEncryption )\n\t\t{\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_AES );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t \"0123456789ABCDEF\", 16 );\n\t\t}\n\n\tinitBufferContents( inBufPtr, BUFFER_SIZE );\n\tif( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\n\tif( useEncryption && \\\n\t\t!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\tcryptContext ) )\n\t\treturn( FALSE );\n\tif( !createDeenvelope( &decryptEnvelope ) )\n\t\treturn( FALSE );\n\tfor( i = 0; i < BUFFER_SIZE / dataSize; i++ )\n\t\t{\n\t\t/* Envelope the data */\n\t\tstatus = cryptPushData( cryptEnvelope, inBufPtr, dataSize, &count );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tinBufPtr += count;\n\t\tcount = popData( cryptEnvelope, outBufPtr, BUFFER_SIZE );\n\t\tif( cryptStatusError( count ) )\n\t\t\treturn( FALSE );\n\n\t\t/* If the envelope has absorbed all of the data, continue */\n\t\tif( count == 0 )\n\t\t\tcontinue;\n\n\t\t/* De-envelope the data */\n\t\tstatus = cryptPushData( decryptEnvelope, outBufPtr, count, &count );\n\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t{\n\t\t\tif( !addEnvInfoNumeric( decryptEnvelope, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t\t\tcryptContext ) )\n\t\t\t\treturn( FALSE );\n\t\t\tstatus = CRYPT_OK;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptPopData( decryptEnvelope, outBufPtr, BUFFER_SIZE, \n\t\t\t\t\t\t\t   &count );\n\t\tif( cryptStatusError( count ) )\n\t\t\t{\n\t\t\t/* If we're doing encrypted enveloping then there won't be any \n\t\t\t   output available until we've got a full block of data */\n\t\t\tif( useEncryption && i < 16 )\n\t\t\t\tcontinue;\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Make sure that it matches what was pushed into the envelope */\n\t\tif( !verifyBufferContents( outBufPtr, count, startCount ) )\n\t\t\treturn( FALSE );\n\t\tstartCount = ( startCount + count ) & 0xFF;\n\t\t}\n\n\t/* Flush through the final trailer bytes, e.g. EOCs */\n\tstatus = cryptFlushData( cryptEnvelope );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, outBufPtr, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tstatus = cryptPushData( decryptEnvelope, outBufPtr, count, &count );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcount = popData( decryptEnvelope, outBufPtr, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tif( useEncryption )\n\t\tcryptDestroyContext( cryptContext );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( decryptEnvelope ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nint testEnvelopeDataMultiple( void )\n\t{\n\tint i;\n\n\tfprintf( outputStream, \"Testing plain data enveloping of multiple \"\n\t\t\t \"blocks of data...\\n\" );\n\tfor( i = 1; i < 8192; i++ )\n\t\t{\n\t\tfprintf( outputStream, \"%d.\\r\", i );\n\t\tif( !envelopeDataMultiple( i, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"Enveloping of multiple blocks of data \"\n\t\t\t \"succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Test compressed enveloping */\n\nstatic int envelopeDecompress( BYTE *buffer, const int bufSize,\n\t\t\t\t\t\t\t   const int length )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE smallBuffer[ 128 ];\n\tint count, zeroCount;\n\n\t/* Create the envelope, push in the data, and pop the de-enveloped\n\t   result */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tcount = pushData( cryptEnvelope, buffer, length, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, buffer, bufSize );\n\tif( cryptStatusError( count ) )\n\t\t{\n#ifdef __hpux\n\t\tif( count == -1 )\n\t\t\t{\n\t\t\tfputs( \"Older HPUX compilers break zlib, to remedy this you \"\n\t\t\t\t   \"can either get a better\\ncompiler/OS or grab a debugger \"\n\t\t\t\t   \"and try to figure out what HPUX is doing to\\nzlib.  To \"\n\t\t\t\t   \"continue the self-tests, comment out the call to\\n\"\n\t\t\t\t   \"testEnvelopeCompress() and rebuild.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\t}\n#endif /* __hpux */\n\t\treturn( FALSE );\n\t\t}\n\n\t/* See what happens when we try and pop out more data.  This test is done\n\t   because some compressed-data formats don't indicate the end of the\n\t   data properly, and we need to make sure that the de-enveloping code\n\t   handles this correctly.  This also tests for correct handling of \n\t   oddball OOB data tacked onto the end of the payload, like PGP's \n\t   MDCs */\n\tzeroCount = popData( cryptEnvelope, smallBuffer, 128 );\n\tif( zeroCount != 0 )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to pop more data after end-of-data \"\n\t\t\t\t \"had been reached succeeded, the\\nenvelope should have \"\n\t\t\t\t \"reported 0 bytes available rather than %d.\\n\", \n\t\t\t\t zeroCount );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopeCompress( const char *dumpFileName,\n\t\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tFILE *inFile;\n\tBYTE *buffer, *envelopedBuffer;\n\tint dataCount = 0, count, status;\n\n\tfprintf( outputStream, \"Testing %scompressed data enveloping%s...\\n\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\",\n\t\t\t useDatasize ? \" with datasize hint\" : \"\"  );\n\n\t/* Since this needs a nontrivial amount of data for the compression, we\n\t   read it from an external file into dynamically-allocated buffers */\n\tif( ( ( buffer = malloc( FILEBUFFER_SIZE ) ) == NULL ) || \\\n\t\t( ( envelopedBuffer = malloc( FILEBUFFER_SIZE ) ) == NULL ) )\n\t\t{\n\t\tif( buffer != NULL )\n\t\t\tfree( buffer );\n\t\tfputs( \"Couldn't allocate test buffers.\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tinFile = fopen( convertFileName( COMPRESS_FILE ), \"rb\" );\n\tif( inFile != NULL )\n\t\t{\n\t\tdataCount = fread( buffer, 1, FILEBUFFER_SIZE, inFile );\n\t\tfclose( inFile );\n\t\tassert( dataCount < FILEBUFFER_SIZE );\n\t\t}\n\tif( dataCount < 1000 || dataCount == FILEBUFFER_SIZE )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\tfputs( \"Couldn't read test file for compression.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the envelope, push in the data, pop the enveloped result, and\n\t   destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_COMPRESSION,\n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\tfprintf( outputStream, \"Attempt to enable compression failed, \"\n\t\t\t\t \"status = %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE, \n\t\t\t\t\t\t   dataCount );\n\t\t}\n\tcount = pushData( cryptEnvelope, buffer, dataCount, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\tcount = popData( cryptEnvelope, envelopedBuffer, FILEBUFFER_SIZE );\n\tif( count > dataCount - 1000 )\n\t\t{\n\t\tfprintf( outputStream, \"Compression of data failed, %d bytes in \"\n\t\t\t\t \"-> %d bytes out, line %d.\\n\", dataCount, count, \n\t\t\t\t __LINE__ );\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( count ) || \\\n\t\t!destroyEnvelope( cryptEnvelope ) )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, envelopedBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tcount = envelopeDecompress( envelopedBuffer, FILEBUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\tif( !compareData( buffer, dataCount, envelopedBuffer, count ) )\n\t\t{\n\t\tfree( buffer );\n\t\tfree( envelopedBuffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tfree( buffer );\n\tfree( envelopedBuffer );\n\tfputs( \"Enveloping of compressed data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeCompress( void )\n\t{\n\t/* In practice these two produce identical output since we always have to\n\t   use the indefinite-length encoding internally because we don't know in\n\t   advance how large the compressed data will be */\n\tif( !envelopeCompress( \"env_cprn\", FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\tif( !envelopeCompress( \"env_cpr\", TRUE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize */\n\treturn( envelopeCompress( \"env_cpr.pgp\", TRUE, CRYPT_FORMAT_PGP ) );\n\t}\t\t\t\t\t\t/* PGP format */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tEncrypted Enveloping Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test encrypted enveloping with a raw session key */\n\nstatic int envelopeSessionCrypt( const char *dumpFileName,\n\t\t\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t\t\t const BOOLEAN useStreamCipher,\n\t\t\t\t\t\t\t\t const DATA_AMOUNT_TYPE dataAmountType,\n\t\t\t\t\t\t\t\t const int dataAmount,\n\t\t\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_ALGO_TYPE cryptAlgo = ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\tselectCipher( CRYPT_ALGO_IDEA ) : \\\n\t\t\t\t\t\t\t\tselectCipher( CRYPT_ALGO_AES );\n\tBYTE *inBufPtr, *outBufPtr;\n\tint length, bufSize, count, status;\n\n\tswitch( dataAmountType )\n\t\t{\n\t\tcase DATA_AMOUNT_SMALL:\n\t\t\tfprintf( outputStream, \"Testing %sraw-session-key encrypted \"\n\t\t\t\t\t \"enveloping%s...\\n\",\n\t\t\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\",\n\t\t\t\t\t ( useStreamCipher ) ? \" with stream cipher\" : \\\n\t\t\t\t\t ( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \\\n\t\t\t\t\t \" with datasize hint\" : \"\" );\n\t\t\tinBufPtr = ENVELOPE_TESTDATA;\n\t\t\tlength = ENVELOPE_TESTDATA_SIZE;\n\t\t\tbufSize = length + 128;\n\t\t\toutBufPtr = globalBuffer;\n\t\t\tbreak;\n\n\t\tcase DATA_AMOUNT_LARGE:\n\t\t\tfprintf( outputStream, \"Testing %sraw-session-key encrypted \"\n\t\t\t\t\t \"enveloping of large data quantity...\\n\",\n\t\t\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\" );\n\t\t\tlength = 1048576L;\n\t\t\tbufSize = length + 128;\n\n\t\t\t/* Allocate a large buffer and fill it with a known value */\n\t\t\tif( ( inBufPtr = malloc( bufSize ) ) == NULL )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't allocate buffer of %d bytes, \"\n\t\t\t\t\t\t \"skipping large buffer enveloping test.\\n\\n\", length );\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\toutBufPtr = inBufPtr;\n\t\t\tinitBufferContents( inBufPtr, length );\n\t\t\tbreak;\n\n\t\tcase DATA_AMOUNT_VARIABLE:\n\t\t\tlength = dataAmount;\n\t\t\tbufSize = length + 128;\n\t\t\tinBufPtr = globalBuffer;\n\t\t\toutBufPtr = inBufPtr;\n\t\t\tinitBufferContents( inBufPtr, length );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\treturn( FALSE );\n\t\t}\n\n\tif( formatType != CRYPT_FORMAT_PGP )\n\t\t{\n\t\t/* Create the session key context.  We don't check for errors here\n\t\t   since this code will already have been tested earlier */\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\t/* PGP only allows a limited subset of algorithms and modes, in\n\t\t   addition we have to specifically check that IDEA is available\n\t\t   since it's possible to build cryptlib without IDEA support */\n\t\tif( cryptAlgo != CRYPT_ALGO_IDEA )\n\t\t\t{\n\t\t\tfputs( \"Can't test PGP enveloping because the IDEA algorithm \"\n\t\t\t\t   \"isn't available in this\\nbuild of cryptlib.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t   CRYPT_MODE_CFB );\n\t\t}\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t \"0123456789ABCDEF\", 16 );\n\n\t/* Create the envelope, push in a password and the data, pop the\n\t   enveloped result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) || \\\n\t\t!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\tcryptContext ) )\n\t\treturn( FALSE );\n\tif( useDatasize && dataAmountType != DATA_AMOUNT_LARGE )\n\t\t{\n\t\t/* Test the ability to destroy the context after it's been added\n\t\t   (we replace it with a different context that's used later for\n\t\t   de-enveloping) */\n\t\tcryptDestroyContext( cryptContext );\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t \"0123456789ABCDEF\", 16 );\n\n\t\t/* As a side-effect, use the new context to test the rejection of \n\t\t   addition of a second session key */\n\t\tif( addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t   cryptContext ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Addition of duplicate session key \"\n\t\t\t\t\t \"succeeded when it should have failed,\\nline %d.\\n\", \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfputs( \"  (The above message indicates that the test condition was \"\n\t\t\t   \"successfully\\n   checked).\\n\", outputStream );\n\t\t}\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE, \n\t\t\t\t\t\t   length );\n\t\t}\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\t\t\t\t\t   length + 1024 );\n\t\t}\n\tcount = pushData( cryptEnvelope, inBufPtr, length, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, outBufPtr, bufSize );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tif( dumpFileName != NULL && dataAmountType != DATA_AMOUNT_LARGE )\n\t\tdebugDump( dumpFileName, outBufPtr, count );\n\n\t/* Create the envelope, push in the data, pop the de-enveloped result,\n\t   and destroy the envelope */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\t\t\t\t\t   length + 1024 );\n\t\t}\n\tcount = pushData( cryptEnvelope, outBufPtr, count, NULL, cryptContext );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, outBufPtr, bufSize );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that the result matches what we pushed */\n\tif( count != length )\n\t\t{\n\t\tfputs( \"De-enveloped data length != original length.\\n\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tif( dataAmountType != DATA_AMOUNT_SMALL )\n\t\t{\n\t\tif( !verifyBufferContents( outBufPtr, length, 0 ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !compareData( ENVELOPE_TESTDATA, length, outBufPtr, length ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tif( dataAmountType == DATA_AMOUNT_LARGE )\n\t\tfree( inBufPtr );\n\tcryptDestroyContext( cryptContext );\n\tfputs( \"Enveloping of raw-session-key-encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSessionCrypt( void )\n\t{\n\tif( !envelopeSessionCrypt( \"env_sesn\", FALSE, FALSE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\tif( !envelopeSessionCrypt( \"env_ses\", TRUE, FALSE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize */\n\tif( !envelopeSessionCrypt( \"env_ses\", TRUE, TRUE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, stream cipher */\n#if 0\n\t/* Although in theory PGP supports raw session-key based enveloping, in\n\t   practice this key is always (implicitly) derived from a user password,\n\t   so the enveloping code doesn't allow the use of raw session keys */\n\treturn( envelopeSessionCrypt( \"env_ses.pgp\", TRUE, FALSE, DATA_AMOUNT_SMALL, 0, CRYPT_FORMAT_PGP ) );\n#endif /* 0 */\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSessionCryptLargeBuffer( void )\n\t{\n\treturn( envelopeSessionCrypt( \"env_ses\", TRUE, FALSE, DATA_AMOUNT_LARGE, 0, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* Datasize, large buffer */\n\nint testEnvelopeSessionCryptVariable( void )\n\t{\n\tFILE *origOutputStream = outputStream;\n\tconst int maxCount = min( BUFFER_SIZE, 8192 );\n\tint i;\t\t\t\t /* Maximum is 32600, from size of internal envelope buffer */\n\n\tfprintf( outputStream, \"Testing encrypted enveloping quantities from \"\n\t\t\t \"1 to %d bytes to check for\\n  boundary errors...\\n\", maxCount );\n\n\toutputStream = fopen( DEVNULL, \"w\" );\n\tassert( outputStream != NULL );\n\tfor( i = 1; i < maxCount; i++ )\n\t\t{\n\t\tfprintf( origOutputStream, \"%d.\\r\", i );\n\t\tif( !envelopeSessionCrypt( NULL, FALSE, FALSE, DATA_AMOUNT_VARIABLE, i, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"Failed for indefinite-length encrypted enveloping \"\n\t\t\t\t\t \"size %d.\\n\", i );\n\t\t\treturn( FALSE );\t/* Indefinite length */\n\t\t\t}\n\t\tif( !envelopeSessionCrypt( NULL, TRUE, FALSE, DATA_AMOUNT_VARIABLE, i, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"Failed for definite-length encrypted enveloping \"\n\t\t\t\t\t \"size %d.\\n\", i );\n\t\t\treturn( FALSE );\t/* Datasize */\n\t\t\t}\n\t\t}\n\toutputStream = origOutputStream;\n\n\tfprintf( outputStream, \"Boundary error test succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSessionCryptMultiple( void )\n\t{\n\tint i;\n\n\tfprintf( outputStream, \"Testing encrypted data enveloping of multiple \"\n\t\t\t \"blocks of data...\\n\" );\n\tfor( i = 1; i < 8192; i++ )\n\t\t{\n\t\tfprintf( outputStream, \"%d.\\r\", i );\n\t\tif( !envelopeDataMultiple( i, TRUE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"Enveloping of multiple blocks of encrypted \"\n\t\t\t \"data succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Test encrypted enveloping */\n\nstatic int envelopeDecrypt( BYTE *buffer, const int length,\n\t\t\t\t\t\t\tconst CRYPT_CONTEXT cryptContext )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count;\n\n\t/* Create the envelope, push in the data, pop the de-enveloped result,\n\t   and destroy the envelope */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tcount = pushData( cryptEnvelope, buffer, length, NULL, cryptContext );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopeCrypt( const char *dumpFileName,\n\t\t\t\t\t\t  const BOOLEAN useDatasize,\n\t\t\t\t\t\t  const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\tfprintf( outputStream, \"Testing encrypted enveloping%s...\\n\",\n\t\t\t useDatasize ? \" with datasize hint\" : \"\" );\n\n\t/* Create the session key context.  We don't check for errors here\n\t   since this code will already have been tested earlier */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t \"0123456789ABCDEF\", 16 );\n\n\t/* Create the envelope, push in a KEK and the data, pop the enveloped\n\t   result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) || \\\n\t\t!addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEY, \n\t\t\t\t\t\t\tcryptContext ) )\n\t\t{\n\t\treturn( FALSE );\n\t\t}\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t}\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tcount = envelopeDecrypt( globalBuffer, count, cryptContext );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptContext );\n\tfputs( \"Enveloping of encrypted data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeCrypt( void )\n\t{\n\tif( !envelopeCrypt( \"env_kekn\", FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\treturn( envelopeCrypt( \"env_kek\", TRUE, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* Datasize */\n\n/* Test password-based encrypted enveloping */\n\nstatic int envelopePasswordDecrypt( BYTE *buffer, const int length )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count;\n\n\t/* Create the envelope, push in the data, pop the de-enveloped result,\n\t   and destroy the envelope */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tcount = pushData( cryptEnvelope, buffer, length, TEST_PASSWORD,\n\t\t\t\t\t  paramStrlen( TEST_PASSWORD ) );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopePasswordCrypt( const char *dumpFileName,\n\t\t\t\t\t\t\t\t  const BOOLEAN useDatasize,\n\t\t\t\t\t\t\t\t  const BOOLEAN useAltCipher,\n\t\t\t\t\t\t\t\t  const BOOLEAN multiKeys,\n\t\t\t\t\t\t\t\t  const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count;\n\n\tfprintf( outputStream, \"Testing %s%spassword-encrypted enveloping%s\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\",\n\t\t\t multiKeys ? \"multiple-\" : \"\",\n\t\t\t ( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) ) ? \\\n\t\t\t \" with datasize hint\" : \"\" );\n\tif( useAltCipher )\n\t\t{\n\t\tfprintf( outputStream, ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t \" with non-default cipher type\" : \" and stream cipher\" );\n\t\t}\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Create the envelope, push in a password and the data, pop the\n\t   enveloped result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( useAltCipher )\n\t\t{\n\t\tint status;\n\n\t\tif( formatType == CRYPT_FORMAT_PGP ) \n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, \n\t\t\t\t\t\t\t\t\t\tCRYPT_OPTION_ENCR_ALGO, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ALGO_AES );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tCRYPT_CONTEXT sessionKeyContext;\n\n\t\t\t/* Test enveloping with an IV-less stream cipher, which tests \n\t\t\t   the handling of algorithms that can't be used to wrap \n\t\t\t   themselves in the RecipientInfo */\n\t\t\tstatus = cryptCreateContext( &sessionKeyContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_RC4 );\n\t\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t\t{\n\t\t\t\tfputs( \"Warning: Couldn't set non-default envelope cipher \"\n\t\t\t\t\t   \"RC4, this may be disabled\\n         in this build of \"\n\t\t\t\t\t   \"cryptlib.\\n\\n\", outputStream );\n\t\t\t\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptGenerateKey( sessionKeyContext );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttribute( cryptEnvelope,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_SESSIONKEY,\n\t\t\t\t\t\t\t\t\t\t\tsessionKeyContext );\n\t\t\t\tcryptDestroyContext( sessionKeyContext );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't set non-default envelope \"\n\t\t\t\t\t \"cipher, error code %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t   TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) ) )\n\t\treturn( FALSE );\n\tif( multiKeys )\n\t\t{\n\t\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEXT( \"Password1\" ),\n\t\t\t\t\t\t\t   paramStrlen( TEXT( \"Password1\" ) ) ) || \\\n\t\t\t!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEXT( \"Password2\" ),\n\t\t\t\t\t\t\t   paramStrlen( TEXT( \"Password2\" ) ) ) || \\\n\t\t\t!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEXT( \"Password3\" ),\n\t\t\t\t\t\t\t   paramStrlen( TEXT( \"Password3\" ) ) ) )\n\t\t\t{\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t}\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", \n\t\t\t count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tcount = envelopePasswordDecrypt( globalBuffer, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of password-encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePasswordCrypt( void )\n\t{\n\tif( !envelopePasswordCrypt( \"env_pasn\", FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\tif( !envelopePasswordCrypt( \"env_pas\", TRUE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize */\n\tif( !envelopePasswordCrypt( \"env_mpas\", TRUE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, multiple keys */\n\tif( !envelopePasswordCrypt( \"env_pas.pgp\", TRUE, FALSE, FALSE, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* PGP format */\n\tif( !envelopePasswordCrypt( \"env_pasa.pgp\", TRUE, TRUE, FALSE, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* PGP format */\n\treturn( envelopePasswordCrypt( \"env_pasr\", TRUE, TRUE, FALSE, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* IV-less cipher */\n\n/* Test boundary conditions for encrypted enveloping.  The strategies are:\n\n\tAll: Push data up to the EOC, then:\n\n\tStrategy 0: Pop exact data length.\n\tStrategy 1: Pop as much as possible.\n\n   For encrypted data, 8 bytes should be left un-popped since the enveloping\n   code hasn't hit the EOCs yet and so can't know how many bytes at the end\n   are payload vs. padding */\n\nstatic int envelopeBoundaryTest( const BOOLEAN usePassword,\n\t\t\t\t\t\t\t\t const int strategy )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE encBuffer[ 1024 ];\n\tint eocPos = 34;\n\tint count, status;\n\n\tfprintf( outputStream, \"Testing %senveloping boundary condition \"\n\t\t\t \"handling, strategy %d...\\n\", \n\t\t\t usePassword ? \"encrypted \" : \"\", strategy );\n\n\t/* If we're using password-based enveloping then the EOC position can\n\t   vary depending on the hash algorithm used */\n\tif( usePassword )\n\t\t{\n\t\tint hashAlgo;\n\n\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_KEYING_ALGO, \n\t\t\t\t\t\t\t\t\t&hashAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\teocPos = ( hashAlgo == CRYPT_ALGO_SHA1 ) ? 182 : 216;\n\t\t}\n\n\t/* Create an envelope and envelope some data using indefinite-length\n\t   encoding */\n\tif( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\n\tif( usePassword )\n\t\t{\n\t\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, encBuffer, 1024 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( strategy == 0 )\t/* Different strategies produce the same output */\n\t\tdebugDump( usePassword ? \"env_ovfe\" : \"env_ovfd\", encBuffer, count );\n\n\t/* Make sure the EOCs are at the expected position */\n\tif( usePassword )\n\t\t{\n\t\tassert( ( encBuffer[ eocPos - 1 ] != 0 || \\\n\t\t\t\t  encBuffer[ eocPos - 2 ] != 0 || \\\n\t\t\t\t  encBuffer[ eocPos - 3 ] != 0 ) && \\\n\t\t\t\tencBuffer[ eocPos ] == 0 && encBuffer[ eocPos + 1 ] == 0 );\n\t\t}\n\telse\n\t\t{\n\t\tassert( encBuffer[ eocPos - 2 ] == \\\n\t\t\t\t\t\t\tENVELOPE_TESTDATA[ ENVELOPE_TESTDATA_SIZE - 2 ] && \\\n\t\t\t\tencBuffer[ eocPos - 1 ] == \\\n\t\t\t\t\t\t\tENVELOPE_TESTDATA[ ENVELOPE_TESTDATA_SIZE - 1 ] && \\\n\t\t\t\tencBuffer[ eocPos ] == 0 && encBuffer[ eocPos + 1 ] == 0 );\n\t\t\t\t/* [ -2 ] = last char, [ -1 ] = '\\0' */\n\t\t}\n\n\t/* De-envelope the data.  We can't use envelopePasswordDecrypt() for this\n\t   because we need to perform custom data handling to test the boundary\n\t   conditions.  First we push the data up to the EOC */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tstatus = cryptPushData( cryptEnvelope, encBuffer, eocPos, &count );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( !usePassword || status != CRYPT_ENVELOPE_RESOURCE )\n\t\t\t{\n\t\t\tprintExtError( cryptEnvelope, \"cryptPushData()\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Then we pop data either up to the EOC or as much as we can */\n\tif( strategy == 0 )\n\t\t{\n\t\t/* Pop the exact data length */\n\t\tstatus = cryptPopData( cryptEnvelope, globalBuffer, \n\t\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE, &count );\n\t\t}\n\telse\n\t\t{\n\t\t/* Pop as much as we can get */\n\t\tstatus = cryptPopData( cryptEnvelope, globalBuffer, \n\t\t\t\t\t\t\t   BUFFER_SIZE, &count );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Error popping data before final-EOC push, \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( usePassword )\n\t\t{\n\t\t/* If it's password-encrypted, there are five EOCs at the end of the \n\t\t   data */\n\t\tstatus = cryptPushData( cryptEnvelope, encBuffer + eocPos, 10, \n\t\t\t\t\t\t\t\t&count );\n\t\t}\n\telse\n\t\t{\n\t\t/* If it's plain data, there are three EOCs at the end of the data */\n\t\tstatus = cryptPushData( cryptEnvelope, encBuffer + eocPos, 6, \n\t\t\t\t\t\t\t\t&count );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Error pushing final EOCs, error code %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Finally we pop the remaining data.  Due to the internal envelope\n\t   buffering strategy the remaining data can be either the cipher\n\t   blocksize or ENVELOPE_TESTDATA_SIZE - blocksize if we're working with\n\t   encrypted data */\n\tstatus = cryptPopData( cryptEnvelope, &globalBuffer, BUFFER_SIZE, \n\t\t\t\t\t\t   &count );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Error popping data after final-EOC push, \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( usePassword )\n\t\t{\n\t\tint blockSize;\n\n\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_CTXINFO_BLOCKSIZE, \n\t\t\t\t\t\t\t\t\t&blockSize );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( count != ( ENVELOPE_TESTDATA_SIZE % blockSize ) && \\\n\t\t    count != ENVELOPE_TESTDATA_SIZE - \\\n\t\t\t\t\t\t\t( ENVELOPE_TESTDATA_SIZE % blockSize ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Final data count should have been %d, \"\n\t\t\t\t\t \"was %d, line %d.\\n\", \n\t\t\t\t\t ENVELOPE_TESTDATA_SIZE % blockSize, count, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( count != 0 )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Final data count should have been 0, \"\n\t\t\t\t\t \"was %d, line %d.\\n\", count, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping boundary-condition handling succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePasswordCryptBoundary( void )\n\t{\n\tif( !envelopeBoundaryTest( FALSE, 0 ) )\n\t\treturn( FALSE );\n\tif( !envelopeBoundaryTest( FALSE, 1 ) )\n\t\treturn( FALSE );\n\tif( !envelopeBoundaryTest( TRUE, 0 ) )\n\t\treturn( FALSE );\n\treturn( envelopeBoundaryTest( TRUE, 1 ) );\n\t}\n\n/* Test PKC-encrypted enveloping */\n\nstatic int envelopePKCDecrypt( BYTE *buffer, const int length,\n\t\t\t\t\t\t\t   const KEYFILE_TYPE keyFileType,\n\t\t\t\t\t\t\t   const CRYPT_HANDLE externalCryptKeyset )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\tassert( ( keyFileType != KEYFILE_NONE && \\\n\t\t\t  externalCryptKeyset == CRYPT_UNUSED ) || \\\n\t\t\t( keyFileType == KEYFILE_NONE && \\\n\t\t\t  externalCryptKeyset != CRYPT_UNUSED ) );\n\n\t/* Create the envelope and push in the decryption keyset */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( keyFileType != KEYFILE_NONE )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\t\tconst C_STR keysetName = getKeyfileName( keyFileType, TRUE );\n\n\t\t/* Add the decryption keyset */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName, \n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroyEnvelope( cryptEnvelope );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = addEnvInfoNumeric( cryptEnvelope, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_DECRYPT, \n\t\t\t\t\t\t\t\t\tcryptKeyset );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\telse\n\t\t{\n\t\t/* We're using a device to handle decryption keys */\n\t\tstatus = addEnvInfoNumeric( cryptEnvelope, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_DECRYPT, \n\t\t\t\t\t\t\t\t\texternalCryptKeyset );\n\t\t}\n\tif( status <= 0 )\n\t\t{\n\t\tdestroyEnvelope( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Push in the data */\n\tif( keyFileType != KEYFILE_NONE )\n\t\t{\n\t\tconst C_STR password = getKeyfilePassword( keyFileType );\n\n\t\tcount = pushData( cryptEnvelope, buffer, length, password, \n\t\t\t\t\t\t  paramStrlen( password ) );\n\t\t}\n\telse\n\t\t{\n\t\tcount = pushData( cryptEnvelope, buffer, length, NULL, 0 );\n\t\t}\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tdestroyEnvelope( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\tcount = popData( cryptEnvelope, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tdestroyEnvelope( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopePKCDecryptDirect( BYTE *buffer, const int length,\n\t\t\t\t\t\t\t\t\t const KEYFILE_TYPE keyFileType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CONTEXT cryptContext;\n\tint count, status;\n\n\t/* Create the envelope and get the decryption key */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tstatus = getPrivateKey( &cryptContext,\n\t\t\t\t\t\t\tgetKeyfileName( keyFileType, TRUE ),\n\t\t\t\t\t\t\tgetKeyfileUserID( keyFileType, TRUE ),\n\t\t\t\t\t\t\tgetKeyfilePassword( keyFileType ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Push in the data */\n\tcount = pushData( cryptEnvelope, buffer, length, NULL, cryptContext );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopePKCCrypt( const char *dumpFileName,\n\t\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t\t const KEYFILE_TYPE keyFileType,\n\t\t\t\t\t\t\t const BOOLEAN useRecipient,\n\t\t\t\t\t\t\t const BOOLEAN useMultipleKeyex,\n\t\t\t\t\t\t\t const BOOLEAN useAltAlgo,\n\t\t\t\t\t\t\t const BOOLEAN useDirectKey,\n\t\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT externalCryptContext,\n\t\t\t\t\t\t\t const CRYPT_HANDLE externalCryptKeyset )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_HANDLE cryptKey;\n\tconst C_STR keysetName = TEXT( \"<None>\" );\n\tconst C_STR keyID = TEXT( \"<None>\" );\n\tint count, status;\n\n\tassert( ( keyFileType != KEYFILE_NONE && \\\n\t\t\t  externalCryptContext == CRYPT_UNUSED && \\\n\t\t\t  externalCryptKeyset == CRYPT_UNUSED ) || \\\n\t\t\t( keyFileType == KEYFILE_NONE && \\\n\t\t\t  externalCryptContext != CRYPT_UNUSED && \\\n\t\t\t  externalCryptKeyset != CRYPT_UNUSED ) );\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of public-key \"\n\t\t\t   \"encrypted enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( keyFileType != KEYFILE_NONE )\n\t\t{\n\t\t/* When reading keys we have to explicitly use the first matching\n\t\t   key in the PGP 2.x keyring since the remaining keys are (for some\n\t\t   reason) stored unencrypted, and the keyring read code will\n\t\t   disallow the use of the key if it's stored in this manner */\n\t\tkeysetName = getKeyfileName( keyFileType, FALSE );\n\t\tkeyID = ( keyFileType == KEYFILE_PGP ) ? \\\n\t\t\t\tTEXT( \"test\" ) : getKeyfileUserID( keyFileType, FALSE );\n\t\t}\n\tfprintf( outputStream, \"Testing %spublic-key encrypted enveloping\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t( ( keyFileType == KEYFILE_PGP ) ? \"PGP \" : \"OpenPGP \" ) : \"\" );\n\tif( useDatasize && ( formatType != CRYPT_FORMAT_PGP ) && \\\n\t\t!( useRecipient || useMultipleKeyex || useDirectKey ) )\n\t\t{\n\t\tfprintf( outputStream, \" with datasize hint\" );\n\t\t}\n\tfprintf( outputStream, \" using \" );\n\tfprintf( outputStream, ( keyFileType == KEYFILE_PGP ) ? \\\n\t\t\t\t( ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\"PGP key\" : \"raw public key\" ) : \\\n\t\t\t  \"X.509 cert\" );\n\tif( useRecipient && !useAltAlgo )\n\t\tfprintf( outputStream, \" and recipient info\" );\n\tif( useMultipleKeyex )\n\t\tfprintf( outputStream, \" and additional keying info\" );\n\tif( useAltAlgo )\n\t\tfprintf( outputStream, \" and alt.encr.algo\" );\n\tif( useDirectKey )\n\t\tfprintf( outputStream, \" and direct key add\" );\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Open the keyset and either get the public key explicitly (to make sure\n\t   that this version works) or leave the keyset open to allow it to be\n\t   added to the envelope */\n\tif( keyFileType != KEYFILE_NONE )\n\t\t{\n\t\tif( useRecipient )\n\t\t\t{\n\t\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName, \n\t\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't open keyset '%s', \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", keysetName, status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = getPublicKey( &cryptKey, keysetName, keyID );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tcryptKey = externalCryptContext;\n\t\tcryptKeyset = externalCryptKeyset;\n\t\t}\n\n\t/* Create the envelope, push in the recipient info or public key and data,\n\t   pop the enveloped result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( useAltAlgo )\n\t\t{\n\t\t/* Specify the use of an alternative (non-default) bulk encryption\n\t\t   algorithm */\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_OPTION_ENCR_ALGO,\n\t\t\t\t\t\t\t\tCRYPT_ALGO_3DES ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( useRecipient )\n\t\t{\n\t\t/* Add recipient information to the envelope.  Since we can't\n\t\t   guarantee for enveloping with cryptlib native key types that we\n\t\t   have a real public-key keyset available at this time (it's created\n\t\t   by a different part of the self-test code that may not have run\n\t\t   yet) we're actually reading the public key from the private-key\n\t\t   keyset.  Normally we couldn't do this, however since PKCS #15\n\t\t   doesn't store email addresses as key ID's (there's no need to),\n\t\t   the code will drop back to trying for a match on the key label.\n\t\t   Because of this we specify the private key label instead of a real\n\t\t   recipient email address.  Note that this trick only works because\n\t\t   of a coincidence of two or three factors and wouldn't normally be\n\t\t   used, it's only used here because we can't assume that a real\n\t\t   public-key keyset is available for use.\n\n\t\t   An additional test that would be useful is the ability to handle\n\t\t   multiple key exchange records, however the keyset kludge makes\n\t\t   this rather difficult.  Since the functionality is tested by the\n\t\t   use of multiple passwords in the conventional-encryption test\n\t\t   earlier on this isn't a major issue */\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEYSET_ENCRYPT,\n\t\t\t\t\t\t\t\tcryptKeyset ) || \\\n\t\t\t!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_RECIPIENT,\n\t\t\t\t\t\t\t   keyID, paramStrlen( keyID ) ) )\n\t\t\t{\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\telse\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\t\tcryptKey ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Test the ability to detect the addition of a duplicate key */\n\t\tif( !( useRecipient || useMultipleKeyex || useDirectKey ) )\n\t\t\t{\n\t\t\tif( addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\t\t   cryptKey ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Addition of duplicate key \"\n\t\t\t\t\t\t \"succeeded when it should have failed,\\n  \"\n\t\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tfputs( \"  (The above message indicates that the test condition \"\n\t\t\t\t   \"was successfully\\n   checked).\\n\", outputStream );\n\t\t\t}\n\n\t\tif( keyFileType != KEYFILE_NONE )\n\t\t\tcryptDestroyObject( cryptKey );\n\t\t}\n\tif( useMultipleKeyex && \\\n\t\t!addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t   TEXT( \"test\" ), paramStrlen( TEXT( \"test\" ) ) ) )\n\t\treturn( FALSE );\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t}\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tif( useDirectKey )\n\t\tcount = envelopePKCDecryptDirect( globalBuffer, count, keyFileType );\n\telse\n\t\t{\n\t\tcount = envelopePKCDecrypt( globalBuffer, count, keyFileType, \n\t\t\t\t\t\t\t\t\texternalCryptKeyset );\n\t\t}\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of public-key encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePKCCrypt( void )\n\t{\n#ifndef USE_PGP2\n\tfputs( \"Skipping raw public-key and PGP enveloping, which requires PGP \"\n\t\t   \"2.x support to\\n  be enabled.\\n\\n\", outputStream );\n#else\n\tif( cryptQueryCapability( CRYPT_ALGO_IDEA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"Skipping raw public-key and PGP enveloping, which requires \"\n\t\t\t   \"the IDEA cipher to\\nbe enabled.\\n\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tif( !envelopePKCCrypt( \"env_pkcn\", FALSE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* Indefinite length, raw key */\n\t\tif( !envelopePKCCrypt( \"env_pkc\", TRUE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* Datasize, raw key */\n\t\tif( !envelopePKCCrypt( \"env_pkc.pgp\", TRUE, KEYFILE_PGP, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* PGP format */\n\t\tif( !envelopePKCCrypt( \"env_pkc.pgp\", TRUE, KEYFILE_PGP, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* PGP format, recipient */\n\t\tif( !envelopePKCCrypt( \"env_pkc.pgp\", TRUE, KEYFILE_PGP, FALSE, FALSE, FALSE, TRUE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* PGP format, decrypt key provided directly */\n#ifdef USE_3DES\n\t\tif( !envelopePKCCrypt( \"env_pkca.pgp\", TRUE, KEYFILE_PGP, TRUE, FALSE, TRUE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\t\treturn( FALSE );\t/* PGP format, recipient, nonstandard bulk encr.algo */\n#endif /* USE_3DES */\n\t\t}\n#endif /* USE_PGP2 */\n\tif( !envelopePKCCrypt( \"env_crt.pgp\", TRUE, KEYFILE_X509, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\t/* PGP format, certificate */\n\tif( !envelopePKCCrypt( \"env_crtn\", FALSE, KEYFILE_X509, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\t/* Indefinite length, certificate */\n\tif( !envelopePKCCrypt( \"env_crt\", TRUE, KEYFILE_X509, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\t/* Datasize, certificate */\n\tif( !envelopePKCCrypt( \"env_crt\", TRUE, KEYFILE_X509, FALSE, FALSE, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\t/* Datasize, certificate, decrypt key provided directly */\n\tif( !envelopePKCCrypt( \"env_crt\", TRUE, KEYFILE_X509, TRUE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) )\n\t\treturn( FALSE );\t/* Datasize, cerficate, recipient */\n\treturn( envelopePKCCrypt( \"env_crtp\", TRUE, KEYFILE_X509, FALSE, TRUE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, CRYPT_UNUSED, CRYPT_UNUSED ) );\n\t}\t\t\t\t\t\t/* Datasize, cerficate+password */\n\nint testEnvelopePKCCryptEx( const CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\t\tconst CRYPT_HANDLE decryptKeyset )\n\t{\n\t/* Note that we can't test PGP enveloping with device-based keys since \n\t   the PGP keyIDs aren't supported by any known device type */\n#if 0\n\tif( !envelopePKCCrypt( \"env_pkc.pgp\", TRUE, KEYFILE_NONE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_PGP, cryptContext, decryptKeyset ) )\n\t\treturn( FALSE );\t/* PGP format */\n#endif\n\treturn( envelopePKCCrypt( \"env_pkc\", TRUE, KEYFILE_NONE, FALSE, FALSE, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB, cryptContext, decryptKeyset ) );\n\t}\t\t\t\t\t\t/* Datasize, raw key */\n\n/* Perform an iterated envelope/deenvelope test to catch errors that only \n   occur in a small subset of runs.  This is used to check for problems in \n   data-dependant operations, e.g. leading-zero truncation which only crops \n   up in 1/256 runs */\n\n#define NO_ITERS\t1000\n\nstatic int envelopePKCIterated( const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_CONTEXT cryptPubKey, cryptPrivKey;\n\tFILE *origOutputStream = outputStream;\n\tint i, status;\n\n\tfprintf( outputStream, \"Testing %d iterations of %s enveloping to \"\n\t\t\t \"check for pad/trunc.errors...\\n\", NO_ITERS,\n\t\t\t( formatType == CRYPT_FORMAT_CRYPTLIB ) ? \"cryptlib\" : \"PGP\" );\n\tstatus = getPublicKey( &cryptPubKey, \n\t\t\t\t\t\t   getKeyfileName( KEYFILE_X509, FALSE ), \n\t\t\t\t\t\t   getKeyfileUserID( KEYFILE_X509, FALSE ) );\n\tassert( cryptStatusOK( status ) );\n\tstatus = getPrivateKey( &cryptPrivKey, \n\t\t\t\t\t\t\tgetKeyfileName( KEYFILE_X509, FALSE ), \n\t\t\t\t\t\t\tgetKeyfileUserID( KEYFILE_X509, FALSE ),\n\t\t\t\t\t\t\tgetKeyfilePassword( KEYFILE_X509 ) );\n\tassert( cryptStatusOK( status ) );\n\toutputStream = fopen( DEVNULL, \"w\" );\n\tassert( outputStream != NULL );\n\tfor( i = 0; i < NO_ITERS; i++ )\n\t\t{\n\t\tCRYPT_ENVELOPE cryptEnvelope;\n\t\tint count;\n\n\t\tfprintf( origOutputStream, \"%d.\\r\", i );\n\n\t\t/* Envelope the data */\n\t\tstatus = createEnvelope( &cryptEnvelope, formatType );\n\t\tassert( status == TRUE );\n\t\tstatus = addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY, \n\t\t\t\t\t\t\t\t\tcryptPubKey );\n\t\tassert( status == TRUE );\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\t\tassert( !cryptStatusError( count ) );\n\t\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\t\tassert( !cryptStatusError( count ) );\n\t\tdestroyEnvelope( cryptEnvelope );\n\n\t\t/* De-envelope the data */\n\t\tstatus = createDeenvelope( &cryptEnvelope );\n\t\tassert( status == TRUE );\n\t\tstatus = pushData( cryptEnvelope, globalBuffer, count, NULL, \n\t\t\t\t\t\t   cryptPrivKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"\\nFailed, iteration = %d.\\n\", i );\n\t\t\tdebugDump( \"r:/out.der\", globalBuffer, count );\n\t\t\tdestroyEnvelope( cryptEnvelope );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\t\tassert( !cryptStatusError( count ) );\n\t\tdestroyEnvelope( cryptEnvelope );\n\t\t}\n\toutputStream = origOutputStream;\n\tcryptDestroyContext( cryptPubKey );\n\tcryptDestroyContext( cryptPrivKey );\n\t\n\tfprintf( outputStream, \"Tested %d iterations of %s PKC enveloping.\\n\\n\", \n\t\t\t NO_ITERS, \n\t\t\t ( formatType == CRYPT_FORMAT_CRYPTLIB ) ? \"cryptlib\" : \"PGP\" );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePKCIterated( void )\n\t{\n\tif( !envelopePKCIterated( CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\n\treturn( envelopePKCIterated( CRYPT_FORMAT_PGP ) );\n\t}\n\n/* Test each encryption algorithm */\n\nstatic int envelopeAlgoCrypt( const char *dumpFileName,\n\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_HANDLE encryptKey, decryptKey;\n\tconst char *algoName = \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_RSA ) ? \"RSA\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \"Elgamal\" : \"<Unknown>\";\n\tint count;\n\n\tfprintf( outputStream, \"Testing %s public-key encrypted \"\n\t\t\t \"enveloping...\\n\", algoName );\n\n\t/* Create the en/decryption contexts */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tif( !loadRSAContexts( CRYPT_UNUSED, &encryptKey, &decryptKey ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\tif( !loadElgamalContexts( &encryptKey, &decryptKey ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfprintf( outputStream, \"Unknown encryption algorithm %d, \"\n\t\t\t\t\t \"line %d.\\n\", cryptAlgo, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the envelope, push in the public key and data, pop the \n\t   enveloped result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\tencryptKey ) )\n\t\treturn( FALSE );\n\tcryptDestroyContext( encryptKey );\n\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"%s-enveloped data has size %d bytes.\\n\", \n\t\t\t algoName, count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tcount = pushData( cryptEnvelope, globalBuffer, count, NULL, \n\t\t\t\t\t  decryptKey );\n\tcryptDestroyContext( decryptKey );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of public-key encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePKCCryptAlgo( void )\n\t{\n\tif( !envelopeAlgoCrypt( \"env_pkc_rsa\", CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ELGAMAL, NULL ) ) && \\\n\t\t!envelopeAlgoCrypt( \"env_pkc_elg\", CRYPT_ALGO_ELGAMAL ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\n/* Test PKC-encrypted enveloping with multiple recipients */\n\nstatic int envelopePKCCryptMulti( const char *dumpFileName,\n\t\t\t\t\t\t\t\t  const int recipientNo,\n\t\t\t\t\t\t\t\t  const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_HANDLE cryptKey1, cryptKey2;\n\tint count, status;\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of public-key \"\n\t\t\t   \"encrypted enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing %spublic-key encrypted enveloping with \"\n\t\t\t \"multiple recipients,\\n\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\" );\n\tfprintf( outputStream, \"  recipient %d to decrypt\", recipientNo );\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Open the keysets and get the two public keys */\n\tstatus = getPublicKey( &cryptKey1, \n\t\t\t\t\t\t   getKeyfileName( KEYFILE_X509, FALSE ), \n\t\t\t\t\t\t   getKeyfileUserID( KEYFILE_X509, FALSE ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getPublicKey( &cryptKey2, \n\t\t\t\t\t\t\t   getKeyfileName( KEYFILE_X509_ALT, FALSE ), \n\t\t\t\t\t\t\t   getKeyfileUserID( KEYFILE_X509_ALT, FALSE ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Create the envelope, push in the keys and data, pop the enveloped \n\t   result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\tcryptKey1 ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\tcryptKey2 ) )\n\t\treturn( FALSE );\n\tcryptDestroyObject( cryptKey1 );\n\tcryptDestroyObject( cryptKey2 );\n\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tcount = envelopePKCDecryptDirect( globalBuffer, count, \n\t\t\t\t\t\t\t\t\t  ( recipientNo == 1 ) ? KEYFILE_X509 : \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t KEYFILE_X509_ALT );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of public-key encrypted data with multiple \"\n\t\t   \"recipients succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopePKCCryptMulti( void )\n\t{\n\tif( cryptQueryCapability( CRYPT_ALGO_IDEA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"Skipping raw public-key and PGP enveloping, which requires \"\n\t\t\t   \"the IDEA cipher to\\nbe enabled.\\n\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tif( !envelopePKCCryptMulti( \"env_pkc_mp\", 1, CRYPT_FORMAT_PGP ) )\n\t\t\treturn( FALSE );\t/* PGP format, multiple recip, key #1 decrypts */\n\t\tif( !envelopePKCCryptMulti( \"env_pkc_mp\", 2, CRYPT_FORMAT_PGP ) )\n\t\t\treturn( FALSE );\t/* PGP format, multiple recip, key #2 decrypts */\n\t\t}\n\tif( !envelopePKCCryptMulti( \"env_pkc_m\", 1, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Multiple recipients, key #1 decrypts */\n\treturn( envelopePKCCryptMulti( \"env_pkc_m\", 2, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* Multiple recipients, key #2 decrypts */\n\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSigned Enveloping Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test signed enveloping */\n\nstatic int getSigCheckResult( const CRYPT_ENVELOPE cryptEnvelope,\n\t\t\t\t\t\t\t  const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t\t\t  const BOOLEAN showAttributes,\n\t\t\t\t\t\t\t  const BOOLEAN isAuthData )\n\t{\n\tint value, status;\n\n\t/* Display all of the attributes that we've got */\n\tif( showAttributes && !displayAttributes( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Determine the result of the signature check.  If it's authenticated\n\t   data there's no need to do anything with keys, if it's signed data\n\t   we have to do some extra processing */\n\tif( !isAuthData )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Read of required attribute for signature \"\n\t\t\t\t\t \"check returned status %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( value != CRYPT_ENVINFO_SIGNATURE )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Envelope requires unexpected enveloping \"\n\t\t\t\t\t \"information type %d, line %d.\\n\", value, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( sigCheckContext != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\t\t\tsigCheckContext );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Attempt to add signature check key \"\n\t\t\t\t\t\t \"returned status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE_RESULT,\n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Signature check returned status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tswitch( value )\n\t\t{\n\t\tcase CRYPT_OK:\n\t\t\tfputs( \"Signature is valid.\\n\", outputStream );\n\t\t\treturn( TRUE );\n\n\t\tcase CRYPT_ERROR_NOTFOUND:\n\t\t\tfputs( \"Cannot find key to check signature.\\n\", outputStream );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ERROR_SIGNATURE:\n\t\t\tfputs( \"Signature is invalid.\\n\", outputStream );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ERROR_NOTAVAIL:\n\t\t\tfputs( \"Warning: Couldn't verify signature due to use of a \"\n\t\t\t\t   \"deprecated/insecure\\n         signature algorithm.\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\n\t\tdefault:\n\t\t\tfprintf( outputStream, \"Signature check failed, result = %d, \"\n\t\t\t\t\t \"line %d.\\n\", value, __LINE__ );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\nstatic int envelopeSigCheck( BYTE *buffer, const int length,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT hashContext,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT sigContext,\n\t\t\t\t\t\t\t const KEYFILE_TYPE keyFileType,\n\t\t\t\t\t\t\t const BOOLEAN detachedSig,\n\t\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\t/* Create the envelope and push in the sig.check keyset if we're not\n\t   using a supplied context for the sig.check */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( sigContext == CRYPT_UNUSED )\n\t\t{\n\t\tconst C_STR keysetName = getKeyfileName( keyFileType, FALSE );\n\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = addEnvInfoNumeric( cryptEnvelope,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_SIGCHECK, \n\t\t\t\t\t\t\t\t\t\tcryptKeyset );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\tif( status <= 0 )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* If the hash value is being supplied externally, add it to the envelope\n\t   before we add the signature data */\n\tif( detachedSig && hashContext != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptEnvelope, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_DETACHEDSIGNATURE, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_HASH,\n\t\t\t\t\t\t\t\t\t\thashContext );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't add externally-generated hash \"\n\t\t\t\t\t \"value to envelope, status %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Push in the data */\n\tcount = pushData( cryptEnvelope, buffer, length, NULL, 0 );\n\tif( !cryptStatusError( count ) )\n\t\t{\n\t\tif( detachedSig )\n\t\t\t{\n\t\t\tif( hashContext == CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tcount = popData( cryptEnvelope, buffer, length );\n\t\t}\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Determine the result of the signature check */\n\tif( !getSigCheckResult( cryptEnvelope, sigContext, TRUE, FALSE ) )\n\t\t{\n\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we're testing the automatic upgrade of the envelope hash function\n\t   to a stronger one, make sure that the hash algorithm was upgraded */\n\tif( keyFileType == KEYFILE_X509_ALT )\n\t\t{\n\t\t/* There's no easy way to retrieve the hash algorithm used for \n\t\t   signing from the envelope since it's a low-level internal \n\t\t   attribute, so the only way to verify that the algorithm upgrade \n\t\t   was successful is by running dumpasn1 on the output data file */\n\t\t}\n\n\t/* If we supplied the sig-checking key, make sure that it's handled\n\t   correctly by the envelope.  We shouldn't be able to read it back from\n\t   a PGP envelope, and from a cryptlib/CMS/SMIME envelope we should get\n\t   back only a certificate, not the full private key that we added */\n\tif( sigContext != CRYPT_UNUSED )\n\t\t{\n\t\tCRYPT_CONTEXT sigCheckContext;\n\n\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\t\t&sigCheckContext );\n\t\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t\t{\n\t\t\t/* If it's a PGP envelope, we can't retrieve the signing key from\n\t\t\t   it */\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Attempt to read signature check key \"\n\t\t\t\t\t\t \"from PGP envelope succeeded when it\\ns  hould have \"\n\t\t\t\t\t\t \"failed, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tCRYPT_ENVELOPE testEnvelope;\n\n\t\t\t/* If it's a cryptlib/CMS/SMIME envelope then we should be able \n\t\t\t   to retrieve the signing key from it */\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't retrieve signature check \"\n\t\t\t\t\t\t \"key from envelope, status %d, line %d.\\n\", status,\n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* The signing key should be a pure certificate, not the private \n\t\t\t   key+certificate combination that we pushed in.  Note that the \n\t\t\t   following will result in an error message being printed in\n\t\t\t   addEnvInfoNumeric() */\n\t\t\tif( !createEnvelope( &testEnvelope, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\t\treturn( FALSE );\n\t\t\tif( addEnvInfoNumeric( testEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\t   sigCheckContext ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Retrieved signature check key is a \"\n\t\t\t\t\t\t \"private key, not a certificate, line %d.\\n\", \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tfputs( \"  (The above message indicates that the test \"\n\t\t\t\t\t   \"condition was successfully\\n   checked).\\n\", \n\t\t\t\t\t   outputStream );\n\t\t\t\t}\n\t\t\tif( !destroyEnvelope( testEnvelope ) )\n\t\t\t\treturn( FALSE );\n\t\t\tcryptDestroyCert( sigCheckContext );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( count );\n\t}\n\nstatic int envelopeSign( const void *data, const int dataLength,\n\t\t\t\t\t\t const char *dumpFileName, \n\t\t\t\t\t\t const KEYFILE_TYPE keyFileType, \n\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t const BOOLEAN useCustomHash, \n\t\t\t\t\t\t const BOOLEAN useSuppliedKey,\n\t\t\t\t\t\t const CRYPT_CONTENT_TYPE contentType,\n\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext DUMMY_INIT;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint count, status;\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of signed \"\n\t\t\t   \"enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing %ssigned enveloping%s\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \\\n\t\t\t ( formatType == CRYPT_FORMAT_SMIME ) ? \"S/MIME \" : \"\",\n\t\t\t ( useDatasize && formatType != CRYPT_FORMAT_PGP && \\\n\t\t\t   keyFileType != KEYFILE_X509_ALT ) ? \\\n\t\t\t \" with datasize hint\" : \"\" );\n\tif( useCustomHash )\n\t\t{\n\t\tfprintf( outputStream, \" %s custom hash\",\n\t\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"with\" : \"and\" );\n\t\t}\n\tif( contentType == CRYPT_CONTENT_NONE )\n\t\t{\n\t\tfprintf( outputStream, \" using %s\", \n\t\t\t\t ( keyFileType == KEYFILE_OPENPGP_HASH ) ? \"raw DSA key\" : \\\n\t\t\t\t ( keyFileType == KEYFILE_PGP ) ? \"raw public key\" : \\\n\t\t\t\t useSuppliedKey ? \"supplied X.509 cert\" : \"X.509 cert\" );\n\t\t}\n\tif( keyFileType == KEYFILE_X509_ALT )\n\t\tfprintf( outputStream, \" and automatic hash upgrade\" );\n\tif( contentType != CRYPT_CONTENT_NONE )\n\t\tfprintf( outputStream, \" and custom content type\" );\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Get the private key */\n\tif( keyFileType == KEYFILE_OPENPGP_HASH || keyFileType == KEYFILE_PGP )\n\t\t{\n\t\tconst C_STR keysetName = getKeyfileName( keyFileType, TRUE );\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, \n\t\t\t\t\t\t\t\t\tgetKeyfileUserID( KEYFILE_PGP, TRUE ),\n\t\t\t\t\t\t\t\t\tgetKeyfilePassword( KEYFILE_PGP ) );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 2 );\n\t\tstatus = getPrivateKey( &cryptContext, \n\t\t\t\t\t\t\t\t( keyFileType == KEYFILE_X509 ) ? \\\n\t\t\t\t\t\t\t\t\tUSER_PRIVKEY_FILE : filenameBuffer,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Read of private key from key file failed, \"\n\t\t\t\t \"status %d, line %d, cannot test enveloping.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the envelope, push in the signing key, any extra information,\n\t   and the data to sign, pop the enveloped result, and destroy the\n\t   envelope */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( contentType != CRYPT_CONTENT_NONE )\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_CONTENTTYPE,\n\t\t\t\t\t\t\t\tcontentType ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\tcryptContext ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\tif( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\tcontentType != CRYPT_CONTENT_NONE )\n\t\t\t{\n\t\t\tfputs( \"  (This is an expected result since this test verifies \"\n\t\t\t\t   \"rejection of an\\n   attempt to set a non-data content \"\n\t\t\t\t   \"type with PGP).\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( formatType == CRYPT_FORMAT_PGP && \\\n\t\t\tcontentType != CRYPT_CONTENT_NONE )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Addition of custom content type to PGP \"\n\t\t\t\t\t \"envelope succeeded when it should\\n  have failed, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t   cryptContext ) != CRYPT_ERROR_INITED )\n\t\t{\n\t\tfputs( \"Addition of duplicate key to envelope wasn't \"\n\t\t\t   \"detected.\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tif( !useSuppliedKey )\n\t\tcryptDestroyContext( cryptContext );\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   dataLength );\n\t\t}\n\tcount = pushData( cryptEnvelope, data, dataLength, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tcount = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  ( useSuppliedKey ) ? cryptContext : CRYPT_UNUSED,\n\t\t\t\t\t\t\t  keyFileType, FALSE, formatType );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( data, dataLength, globalBuffer, count ) )\n\t\treturn( FALSE );\n\tif( useSuppliedKey )\n\t\t{\n\t\t/* If the following fails, there's a problem with handling reference\n\t\t   counting for keys */\n\t\tstatus = cryptDestroyContext( cryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Attempt to destroy externally-added \"\n\t\t\t\t\t \"sig.check key returned %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tfputs( \"Enveloping of signed data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSign( void )\n\t{\n#ifndef USE_PGP2\n\tfputs( \"Skipping raw public-key and PGP signing, which requires PGP 2.x \"\n\t\t   \"support to\\n  be enabled.\\n\\n\", outputStream );\n#else\n\tif( cryptQueryCapability( CRYPT_ALGO_IDEA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"Skipping raw public-key based signing, which requires the \"\n\t\t\t   \"IDEA cipher to\\n  be enabled.\\n\\n\", outputStream );\n\t\t}\n\telse\n\t\t{\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sign\", KEYFILE_PGP, FALSE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\treturn( FALSE );\t/* Indefinite length, raw key */\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sig\", KEYFILE_PGP, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\treturn( FALSE );\t/* Datasize, raw key */\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sigc\", KEYFILE_PGP, TRUE, FALSE, FALSE, CRYPT_CONTENT_COMPRESSEDDATA, CRYPT_FORMAT_CRYPTLIB ) )\n\t\t\treturn( FALSE );\t/* Datasize, raw key, custom content type */\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sig.pgp\", KEYFILE_PGP, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_PGP ) )\n\t\t\treturn( FALSE );\t/* PGP format, datasize, raw key */\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sigc.pgp\", KEYFILE_PGP, TRUE, FALSE, FALSE, CRYPT_CONTENT_COMPRESSEDDATA, CRYPT_FORMAT_PGP ) )\n\t\t\treturn( FALSE );\t/* PGP format, datasize, raw key, custom content type */\n#ifdef USE_3DES\t\t/* Uses 3DES keyring */\n\t\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_sigd.pgp\", KEYFILE_OPENPGP_HASH, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_PGP ) )\n\t\t\treturn( FALSE );\t/* PGP format, datasize, raw DSA key */\n#endif /* USE_3DES */\n\t\t}\n#endif /* USE_PGP2 */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csgn\", KEYFILE_X509, FALSE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Indefinite length, certificate */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csg\", KEYFILE_X509, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, certificate */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csgs\", KEYFILE_X509, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_SMIME ) )\n\t\treturn( FALSE );\t/* Datasize, certificate, S/MIME semantics */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csg\", KEYFILE_X509, TRUE, FALSE, TRUE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, certificate, sigcheck key supplied */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csg.pgp\", KEYFILE_X509, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* PGP format, certificate */\n#if 0\t/* 8/7/2012 Removed since it conflicts with the functionality for \n\t\t\t\t\tsetting hash values for detached signatures.  This\n\t\t\t\t\tcapability was never documented in the manual so it's\n\t\t\t\t\tunlikely that it was ever used */\n\tif( !envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_hsg\", KEYFILE_X509, TRUE, TRUE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Datasize, certificate, externally-suppl.hash */\n#endif /* 0 */\n\treturn( envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csg\", KEYFILE_X509, TRUE, FALSE, TRUE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* Externally-supplied key, to test isolation of sig.check key */\n\nstatic int envelopeAlgoSign( const char *dumpFileName,\n\t\t\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CONTEXT sigKey, sigCheckKey;\n\tconst char *algoName = \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_RSA ) ? \"RSA\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_DSA ) ? \"DSA\" : \\\n\t\t\t( cryptAlgo == CRYPT_ALGO_ECDSA ) ? \"ECDSA\" : \"<Unknown>\";\n\tint count;\n\n\tfprintf( outputStream, \"Testing %s signed enveloping...\\n\", algoName );\n\n\t/* Create the en/decryption contexts */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tif( !loadRSAContexts( CRYPT_UNUSED, &sigCheckKey, &sigKey ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tif( !loadDSAContexts( CRYPT_UNUSED, &sigCheckKey, &sigKey ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tif( !loadECDSAContexts( CRYPT_UNUSED, &sigCheckKey, &sigKey ) )\n\t\t\t\treturn( FALSE );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tfprintf( outputStream, \"Unknown signature algorithm %d, \"\n\t\t\t\t\t \"line %d.\\n\", cryptAlgo, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the envelope, push in the signing key and the data to sign, \n\t   pop the enveloped result, and destroy the envelope */\n\tif( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\tsigKey ) )\n\t\treturn( FALSE );\n\tcryptDestroyContext( sigKey );\n\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA, \n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"%s-signed data has size %d bytes.\\n\", \n\t\t\t algoName, count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tcount = pushData( cryptEnvelope, globalBuffer, count, NULL, 0 );\n\tif( !cryptStatusError( count ) )\n\t\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !getSigCheckResult( cryptEnvelope, sigCheckKey, TRUE, FALSE ) )\n\t\treturn( FALSE );\n\tcryptDestroyContext( sigCheckKey );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of signed data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSignAlgos( void )\n\t{\n\tif( !envelopeAlgoSign( \"env_sig_rsa\", CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\n\tif( !envelopeAlgoSign( \"env_sig_dsa\", CRYPT_ALGO_DSA ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) && \\\n\t\t!envelopeAlgoSign( \"env_sig_ecc\", CRYPT_ALGO_ECDSA ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\n/* Test envelope signing with automatic upgrade of the signing algorithm to\n   SHA256 */\n\nint testEnvelopeSignHashUpgrade( void )\n\t{\n\treturn( envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \"env_csgh\", KEYFILE_X509_ALT, TRUE, FALSE, FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\n\n/* Test signed envelope with forced envelope buffer overflow */\n\nstatic int envelopeSignOverflow( const void *data, const int dataLength,\n\t\t\t\t\t\t\t\t const char *dumpFileName,\n\t\t\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\t\t const char *description )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CONTEXT cryptContext;\n\tBYTE localBuffer[ 8192 + 4096 ];\n\tconst BOOLEAN forceOverflow = ( dataLength <= 8192 ) ? TRUE : FALSE;\n\tint localBufPos, bytesIn, bytesOut, status;\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of signed \"\n\t\t\t   \"enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing %ssigned enveloping with forced \"\n\t\t\t \"overflow in %s...\\n\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \\\n\t\t\t ( formatType == CRYPT_FORMAT_SMIME ) ? \"S/MIME \" : \"\",\n\t\t\t description );\n\n\t/* Get the private key */\n\tstatus = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Read of private key from key file failed, \"\n\t\t\t\t \"cannot test enveloping, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the envelope and push in the signing key and any extra\n\t   information */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\tcryptContext ) )\n\t\treturn( FALSE );\n\tcryptDestroyContext( cryptContext );\n\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t\t\tdataLength );\n\tif( cryptStatusOK( status ) && forceOverflow )\n\t\t{\n\t\t/* Set an artificially-small buffer to force an overflow */\n\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_BUFFERSIZE,\n\t\t\t\t\t\t\t\t\t8192 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't set envelope parameters to force \"\n\t\t\t\t \"overflow, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Push in the data to sign.  Since we're forcing an overflow, we can't\n\t   do this via the usual pushData() but have to do it manually to handle\n\t   the restart once the overflow occurs */\n\tstatus = cryptPushData( cryptEnvelope, data, dataLength, &bytesIn );\n\tif( cryptStatusError( status ) || bytesIn != dataLength )\n\t\t{\n\t\tfprintf( outputStream, \"cryptPushData() failed with status %d, \"\n\t\t\t\t \"copied %d of %d bytes, line %d.\\n\", status, bytesIn, \n\t\t\t\t dataLength, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptFlushData( cryptEnvelope );\n\tif( forceOverflow && status != CRYPT_ERROR_OVERFLOW )\n\t\t{\n\t\tfprintf( outputStream, \"cryptFlushData() returned status %d, \"\n\t\t\t\t \"should have been CRYPT_ERROR_OVERFLOW,\\n  line %d.\\n\", \n\t\t\t\t status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptPopData( cryptEnvelope, localBuffer, 8192 + 4096,\n\t\t\t\t\t\t   &bytesOut );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptPopData() #1 failed with status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tlocalBufPos = bytesOut;\n\tstatus = cryptFlushData( cryptEnvelope );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptFlushData() failed with error code %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptEnvelope );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptPopData( cryptEnvelope, localBuffer + localBufPos,\n\t\t\t\t\t\t   8192 + 4096 - localBufPos, &bytesOut );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptPopData() #2 failed with status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tlocalBufPos += bytesOut;\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", \n\t\t\t localBufPos );\n\tdebugDump( dumpFileName, localBuffer, localBufPos );\n\n\t/* De-envelope the data and make sure that the result matches what we\n\t   pushed */\n\tbytesOut = envelopeSigCheck( localBuffer, localBufPos, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_UNUSED, KEYFILE_X509, FALSE, \n\t\t\t\t\t\t\t\t formatType );\n\tif( bytesOut <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( localBuffer, bytesOut, data, dataLength ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of signed data succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeSignOverflow( void )\n\t{\n\tBYTE buffer[ 8192 + 1024 ];\n\n\t/* Push in just the right amount of data to force an overflow when we\n\t   generate the signature, to check overflow handling in the enveloping\n\t   code.\n\n\t   For PGP it's almost impossible to invoke overflow handling since the\n\t   enveloping code is set up to either emit the signature directly into\n\t   the buffer or, via an over-conservative estimation of buffer space,\n\t   ensure that the user leaves enough space in the buffer for the entire\n\t   sig.  For an estimated space requirement of 256 bytes, 8192 - 280\n\t   will force the sig into the auxBuffer, but since this is an over-\n\t   conservative estimate it'll then be flushed straight into the\n\t   envelope buffer.  The only way to actually force overflow handling\n\t   would be to use the longest possible key size and a certificate with \n\t   a large issuerAndSerialNumber.\n\n\t   (In addition to the envelope buffer-overflow check, we also try\n\t   enveloping data with a length at the boundary where PGP switches from\n\t   2-byte to 4-byte lengths, 8384 bytes, to verify that this works OK).\n\n\t   For CMS, we can cause an overflow in one of two locations.  The first,\n\t   with 8192 - 1152 bytes of data, causes an overflow when emitting the\n\t   signing certs.  This is fairly straightforward, the enveloping code\n\t   always requires enough room for the signing certs, so all that happens\n\t   is that the user pops some data and tries again.\n\n\t   The second overflow is with 8192 - 1280 bytes of data, which causes an\n\t   overflow on signing */\n\tmemset( buffer, '*', 8192 + 1024 );\n\tif( !envelopeSignOverflow( buffer, 8192 - 280, \"env_sigo.pgp\", CRYPT_FORMAT_PGP, \"signature\" ) )\n\t\treturn( FALSE );\t/* PGP format, raw key */\n\tif( !envelopeSignOverflow( buffer, 8384 - 6, \"env_sigo2.pgp\", CRYPT_FORMAT_PGP, \"seg.boundary\" ) )\n\t\treturn( FALSE );\t/* PGP format, raw key */\n\tif( !envelopeSignOverflow( buffer, 8192 - 1152, \"env_csgo1\", CRYPT_FORMAT_SMIME, \"signing certs\" ) )\n\t\treturn( FALSE );\t/* Datasize, certificate, S/MIME semantics */\n\treturn( envelopeSignOverflow( buffer, 8192 - 1280, \"env_csgo2\", CRYPT_FORMAT_SMIME, \"signature\" ) );\n\t}\t\t\t\t\t\t/* Datasize, certificate, S/MIME semantics */\n\n/* Test the ability to process indefinite-length data with a break at every \n   byte position in the file */\n\nint testEnvelopeSignIndef( void )\n\t{\n\tint count, bufPos, status;\n\n\tfputs( \"Testing ability to process indefinite-length data at any byte \"\n\t\t   \"position...\\n\", outputStream );\n\n\t/* Read the data to be checked */\n\tcount = readFileData( SMIME_SIG_FILE_INDEF, \n\t\t\t\t\t\t  \"Indefinite-length signed data\", globalBuffer, \n\t\t\t\t\t\t  BUFFER_SIZE, 128, FALSE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\n\t/* De-envelope the data, breaking the data quantity at every byte\n\t   position */\n\tfor( bufPos = 1; bufPos < count; bufPos++ )\n\t\t{\n\t\tCRYPT_ENVELOPE cryptEnvelope;\n\t\tint byteCount;\n\n\t\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\t\treturn( FALSE );\n\t\tfprintf( outputStream, \"Testing byte position %d.\\r\", bufPos );\n\n\t\t/* Push the first half of the data */\n\t\tstatus = cryptPushData( cryptEnvelope, globalBuffer, bufPos, \n\t\t\t\t\t\t\t\t&byteCount );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t/* If we get an underflow error within the header or trailer \n\t\t\t   then everything's OK and we can continue */\n\t\t\tif( status == CRYPT_ERROR_UNDERFLOW && \\\n\t\t\t\t( bufPos < 50 || bufPos > 69 ) )\n\t\t\t\t{\n\t\t\t\t/* We're in the middle of the header or trailer, a \n\t\t\t\t   CRYPT_ERROR_UNDERFLOW is expected if we break at this \n\t\t\t\t   point */\n\t\t\t\t}\n\t\t\telse\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( byteCount != bufPos )\n\t\t\treturn( FALSE );\n\n\t\t/* Push the second half of the data */\n\t\tstatus = cryptPushData( cryptEnvelope, globalBuffer + bufPos, \n\t\t\t\t\t\t\t\tcount - bufPos, &byteCount );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptEnvelope );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( byteCount != count - bufPos )\n\t\t\treturn( FALSE );\n\n\t\t/* Destroy the envelope.  Since we haven't processed the signed data\n\t\t   we'll get a CRYPT_ERROR_INCOMPLETE, so we ignore any error \n\t\t   result */\n\t\t( void ) cryptDestroyEnvelope( cryptEnvelope );\n\t\t}\n\n\tfputs( \"Ability to process indefinite-length data at any byte position \"\n\t\t   \"succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test authenticated (MACd/authEnc) enveloping */\n\nstatic int envelopeAuthent( const void *data, const int dataLength,\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t\tconst BOOLEAN useAuthEnc, \n\t\t\t\t\t\t\tconst BOOLEAN useDatasize,\n\t\t\t\t\t\t\tconst BOOLEAN usePKC,\n\t\t\t\t\t\t\tconst int corruptDataLocation )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBOOLEAN corruptionDetected = FALSE;\n\tint count, integrityLevel, status;\n\n\tfprintf( outputStream, \"Testing %sauthenticated%s enveloping\", \n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP-format \" : \"\",\n\t\t\t useAuthEnc ? \"+encrypted\" : \"\" );\n\tif( corruptDataLocation )\n\t\tfprintf( outputStream, \" with deliberate corruption of data\" );\n\telse\n\t\t{\n\t\tif( useDatasize )\n\t\t\tfprintf( outputStream, \" with datasize hint\" );\n\t\t}\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Create the envelope and push in the password after telling the\n\t   enveloping code that we want to MAC rather than encrypt */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_INTEGRITY,\n\t\t\t\t\t\t\tuseAuthEnc ? CRYPT_INTEGRITY_FULL : \\\n\t\t\t\t\t\t\t\t\t\t CRYPT_INTEGRITY_MACONLY ) )\n\t\t{\n\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\tif( formatType == CRYPT_FORMAT_PGP && !useAuthEnc )\n\t\t\t{\n\t\t\tfputs( \"  (This is an expected result since this test verifies \"\n\t\t\t\t   \"rejection of an\\n   attempt to use a MAC with \"\n\t\t\t\t   \"PGP).\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\tif( usePKC )\n\t\t{\n\t\tCRYPT_CONTEXT cryptKey;\n\n\t\tstatus = getPublicKey( &cryptKey, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\t\tcryptKey ) )\n\t\t\t{\n\t\t\tcryptDestroyContext( cryptKey );\n\t\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\t\tif( formatType == CRYPT_FORMAT_CRYPTLIB && !useAuthEnc )\n\t\t\t\t{\n\t\t\t\tfputs( \"  (This is an expected result since this test \"\n\t\t\t\t\t   \"verifies rejection of an\\n   attempt to use a PKC \"\n\t\t\t\t\t   \"with a MAC-only envelope).\\n\\n\", outputStream );\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyContext( cryptKey );\n\t\t}\n\telse\n\t\t{\n\t\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_PASSWORD,\n\t\t\t\t\t\t\t   TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( formatType == CRYPT_FORMAT_PGP && !useAuthEnc )\n\t\t{\n\t\tfprintf( outputStream, \"Invalid attempt to use MAC-only \"\n\t\t\t\t \"authentication for PGP-enveloped data wasn't\\n  detected, \"\n\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Push in the data, pop the enveloped result, and destroy the\n\t   envelope */\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   dataLength );\n\t\t}\n\tcount = pushData( cryptEnvelope, data, dataLength, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( ( formatType == CRYPT_FORMAT_PGP ) ? \"env_mdc.pgp\" : \\\n\t\t\t   useAuthEnc ? ( usePKC ? \"env_authenp\" : \"env_authenc\" ) : \\\n\t\t\t   useDatasize ? \"env_mac\" : usePKC ? \"env_macp\" : \"env_macn\", \n\t\t\t   globalBuffer, count );\n\n\t/* If we're testing sig.verification, corrupt one of the payload bytes.  \n\t   This is a bit tricky because we have to hardcode the location of the\n\t   payload byte, if we change the format at (for example by using a \n\t   different algorithm somewhere) then this location will change */\n\tif( corruptDataLocation > 0 )\n\t\tglobalBuffer[ corruptDataLocation ]++;\n\n\t/* Create the envelope */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( usePKC )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEYSET_DECRYPT, \n\t\t\t\t\t\t\t\tcryptKeyset ) )\n\t\t\treturn( FALSE );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\n\t/* Push in the data */\n\tif( usePKC )\n\t\t{\n\t\tcount = pushData( cryptEnvelope, globalBuffer, count, \n\t\t\t\t\t\t  TEST_PRIVKEY_PASSWORD, \n\t\t\t\t\t\t  paramStrlen( TEST_PRIVKEY_PASSWORD ) );\n\t\t}\n\telse\n\t\t{\n\t\tcount = pushData( cryptEnvelope, globalBuffer, count, \n\t\t\t\t\t\t  TEST_PASSWORD, paramStrlen( TEST_PASSWORD ) );\n\t\t}\n\tif( cryptStatusError( count ) )\n\t\t{\n\t\tif( corruptDataLocation && count == CRYPT_ERROR_SIGNATURE )\n\t\t\t{\n\t\t\tfputs( \"  (This is an expected result since this test verifies \"\n\t\t\t\t   \"handling of\\n   corrupted authenticated data).\\n\", \n\t\t\t\t   outputStream );\n\t\t\tcorruptionDetected = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\t\tif( cryptStatusError( count ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the envelope is reported as being authenticated */\n\tif( cryptStatusError( \\\n\t\t\tcryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_INTEGRITY, \n\t\t\t\t\t\t\t   &integrityLevel ) ) || \\\n\t\tintegrityLevel <= CRYPT_INTEGRITY_NONE )\n\t\t{\n\t\tfprintf( outputStream, \"Integrity-protected envelope is reported \"\n\t\t\t\t \"as having no integrity protection,\\n  line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Determine the result of the MAC check */\n\tif( !getSigCheckResult( cryptEnvelope, CRYPT_UNUSED, FALSE, TRUE ) && \\\n\t\tcorruptDataLocation == 0 )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Make sure that we got what we were expecting */\n\tif( corruptDataLocation == 0 )\n\t\t{\n\t\tif( !compareData( data, dataLength, globalBuffer, count ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !corruptionDetected )\n\t\t\t{\n\t\t\tfputs( \"Corruption of encrypted data wasn't detected.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tfputs( \"Enveloping of authenticated data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testEnvelopeAuthenticate( void )\n\t{\n\tint macAlgo, status;\n\n\t/* Find out what the default MAC algorithm is.  This is required because \n\t   the data location that we corrupt changes based on the MAC algorithm \n\t   used */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_MAC, &macAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* MAC-only envelopes are currently only supported via password (or at \n\t   least shared-key) key management, using a PKC implies encrypt+MAC.\n\t   It's also somewhat unclear what the benefits of using a PKC for a MAC\n\t   are, so until there's a demand for this we only allow use with\n\t   passwords */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, FALSE, FALSE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, FALSE, TRUE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* Datasize */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, FALSE, TRUE, TRUE, 0 ) )\n\t\treturn( FALSE );\t/* Datasize, PKC to check rejection of this format */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_PGP, FALSE, TRUE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* PGP format to check rejection of this format */\n\treturn( envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, FALSE, TRUE, FALSE, ( macAlgo == CRYPT_ALGO_HMAC_SHA1 ) ? 175 : 208 ) );\n\t}\t\t\t\t\t\t/* Datasize, corrupt data to check sig.verification */\n\nint testEnvelopeAuthEnc( void )\n\t{\n\tint macAlgo, status;\n\n\t/* Find out what the default MAC algorithm is.  This is required because \n\t   the data location that we corrupt changes based on the MAC algorithm \n\t   used */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_MAC, &macAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, TRUE, FALSE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* Indefinite length */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, TRUE, TRUE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* Datasize */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, TRUE, TRUE, TRUE, 0 ) )\n\t\treturn( FALSE );\t/* Datasize, PKC */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_PGP, TRUE, TRUE, FALSE, 0 ) )\n\t\treturn( FALSE );\t/* PGP format */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_PGP, TRUE, TRUE, TRUE, 0 ) )\n\t\treturn( FALSE );\t/* PGP format, PKC */\n\tif( !envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, TRUE, TRUE, FALSE, ( macAlgo == CRYPT_ALGO_HMAC_SHA1 ) ? 192 : 260 ) )\n\t\treturn( FALSE );\t/* Datasize, corrupt payload data to check sig.verification */\n\treturn( envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, CRYPT_FORMAT_CRYPTLIB, TRUE, TRUE, FALSE, ( macAlgo == CRYPT_ALGO_HMAC_SHA1 ) ? 170 : 228 ) );\n\t}\t\t\t\t\t\t/* Datasize, corrupt metadata to check sig.verification */\n\n/* Test handling of injected faults */\n\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\ntypedef enum { TEST_SIGN, TEST_AUTH, TEST_AUTHENC } TEST_TYPE;\n\nstatic int testCMSDebugCheck( const TEST_TYPE testType, const FAULT_TYPE testFaultType )\n\t{\n\tint status;\n\n\tcryptSetFaultType( testFaultType );\n\tswitch( testType )\n\t\t{\n\t\tcase TEST_SIGN:\n\t\t\tstatus = envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t\t\t\t   \"fault\", KEYFILE_X509, TRUE, FALSE, FALSE, \n\t\t\t\t\t\t\t\t   CRYPT_CONTENT_NONE, CRYPT_FORMAT_SMIME );\n\t\t\tbreak;\n\n\t\tcase TEST_AUTH:\n\t\t\tstatus = envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CRYPTLIB, FALSE, TRUE, \n\t\t\t\t\t\t\t\t\t  FALSE, 0 );\n\t\t\tbreak;\n\n\t\tcase TEST_AUTHENC:\n\t\t\tstatus = envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CRYPTLIB, TRUE, TRUE, \n\t\t\t\t\t\t\t\t\t  FALSE, 0 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tassert( 0 );\n\t\t}\n\tif( status )\n\t\t{\n\t\tcryptSetFaultType( FAULT_NONE );\n\t\tfputs( \"  (This test should have led to an enveloping failure but \"\n\t\t\t   \"didn't, test has\\n   failed).\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* These tests are supposed to fail, so if this happens then the overall \n\t   test has succeeded */\n\tfputs( \"  (This test checks error handling, so the failure response is \"\n\t\t   \"correct).\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic int testPGPDebugCheck( const TEST_TYPE testType, const FAULT_TYPE testFaultType )\n\t{\n\tint status;\n\n\tcryptSetFaultType( testFaultType );\n\tswitch( testType )\n\t\t{\n\t\tcase TEST_SIGN:\n\t\t\tstatus = envelopeSign( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t\t\t\t   \"fault.pgp\", KEYFILE_PGP, TRUE, FALSE, \n\t\t\t\t\t\t\t\t   FALSE, CRYPT_CONTENT_NONE, CRYPT_FORMAT_PGP );\n\t\t\tbreak;\n\n\t\tcase TEST_AUTH:\n\t\t\tstatus = envelopeAuthent( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP, TRUE, TRUE, FALSE, 0 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tassert( 0 );\n\t\t}\n\tif( status )\n\t\t{\n\t\tcryptSetFaultType( FAULT_NONE );\n\t\tfputs( \"  (This test should have led to an enveloping failure but \"\n\t\t\t   \"didn't, test has\\n   failed).\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* These tests are supposed to fail, so if this happens then the overall \n\t   test has succeeded */\n\tfputs( \"  (This test checks error handling, so the failure response is \"\n\t\t   \"correct).\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* CONFIG_FAULTS && Debug */\n\nint testEnvelopeCMSDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !testCMSDebugCheck( TEST_SIGN, FAULT_BADSIG_DATA ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_SIGN, FAULT_BADSIG_HASH ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_SIGN, FAULT_ENVELOPE_CORRUPT_AUTHATTR ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_AUTH, FAULT_ENVELOPE_CMS_CORRUPT_AUTH_DATA ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_AUTH, FAULT_ENVELOPE_CMS_CORRUPT_AUTH_MAC ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_AUTHENC, FAULT_ENVELOPE_CMS_CORRUPT_AUTH_DATA ) )\n\t\treturn( FALSE );\n\tif( !testCMSDebugCheck( TEST_AUTHENC, FAULT_ENVELOPE_CMS_CORRUPT_AUTH_MAC ) )\n\t\treturn( FALSE );\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n\nint testEnvelopePGPDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !testPGPDebugCheck( TEST_AUTH, FAULT_BADSIG_DATA ) )\n\t\treturn( FALSE );\n\tif( !testPGPDebugCheck( TEST_AUTH, FAULT_BADSIG_HASH ) )\n\t\treturn( FALSE );\n\tif( !testPGPDebugCheck( TEST_SIGN, FAULT_ENVELOPE_PGP_CORRUPT_ONEPASS_ID ) )\n\t\treturn( FALSE );\n\tif( !testPGPDebugCheck( TEST_SIGN, FAULT_CORRUPT_ID ) )\n\t\treturn( FALSE );\n\tif( !testPGPDebugCheck( TEST_SIGN, FAULT_ENVELOPE_CORRUPT_AUTHATTR ) )\n\t\treturn( FALSE );\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCMS Enveloping Test Routines \t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test CMS signature generation/checking */\n\nstatic int displaySigResult( const CRYPT_ENVELOPE cryptEnvelope,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT sigCheckContext,\n\t\t\t\t\t\t\t const BOOLEAN mustHaveAttributes,\n\t\t\t\t\t\t\t const BOOLEAN firstSig )\n\t{\n\tCRYPT_CERTIFICATE signerInfo;\n\tBOOLEAN sigStatus;\n\tint status;\n\n\t/* Determine the result of the signature check.  We only display the\n\t   attributes for the first sig since this operation walks the attribute\n\t   list,which moves the attribute cursor */\n\tsigStatus = getSigCheckResult( cryptEnvelope, sigCheckContext,\n\t\t\t\t\t\t\t\t   firstSig, FALSE );\n\tif( sigCheckContext != CRYPT_UNUSED && !mustHaveAttributes )\n\t\t{\n\t\t/* If this is a PGP signature (indicated by the fact that the \n\t\t   sig-check key isn't included in the signed data and we're not \n\t\t   checking attributes), there's no signer info or extra data \n\t\t   present */\n\t\treturn( sigStatus );\n\t\t}\n\n\t/* Report on the signer and signature info.  We continue even if the sig.\n\t   status is bad since we can still try and display signing info even if\n\t   the check fails */\n\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\t&signerInfo );\n\tif( cryptStatusError( status ) && sigStatus )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't retrieve signer information from \"\n\t\t\t\t \"CMS signature, status = %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfputs( \"Signer information is:\\n\", outputStream );\n\t\tif( !printCertInfo( signerInfo ) )\n\t\t\treturn( FALSE );\n\t\tcryptDestroyCert( signerInfo );\n\t\t}\n\tstatus = cryptGetAttribute( cryptEnvelope,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA, &signerInfo );\n\tif( cryptStatusError( status ) && sigStatus && \\\n\t\t( mustHaveAttributes || status != CRYPT_ERROR_NOTFOUND ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't retrieve signature information \"\n\t\t\t\t \"from CMS signature, status = %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfputs( \"Signature information is:\\n\", outputStream );\n\t\tif( !printCertInfo( signerInfo ) )\n\t\t\treturn( FALSE );\n\t\tcryptDestroyCert( signerInfo );\n\t\t}\n\n\treturn( sigStatus );\n\t}\n\nstatic int cmsEnvelopeSigCheck( const void *signedData, \n\t\t\t\tconst int signedDataLength, \n\t\t\t\tconst CRYPT_CONTEXT sigCheckContext, \n\t\t\t\tconst CRYPT_CONTEXT hashContext, const BOOLEAN detachedSig,\n\t\t\t\tconst BOOLEAN hasTimestamp, const BOOLEAN checkData,\n\t\t\t\tconst BOOLEAN mustHaveAttributes, const BOOLEAN checkWrongKey,\n\t\t\t\tconst BOOLEAN testRefCount )\n\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\t/* Create the (de-)envelope and push in the data.  Since this is a CMS\n\t   signature that carries its certs with it, there's no need to push in\n\t   a sig.check keyset.  If it has a detached sig, we need to push two\n\t   lots of data, first the signature to set the envelope state, then the\n\t   data, however if the hash is being supplied externally we just set the\n\t   hash attribute.  In addition if it's a detached sig, there's nothing\n\t   to be unwrapped so we don't pop any data */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( detachedSig && hashContext != CRYPT_UNUSED )\n\t\t{\n\t\t/* The hash value is being supplied externally, add it to the\n\t\t   envelope before we add the signature data */\n\t\tstatus = cryptSetAttribute( cryptEnvelope, \n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_DETACHEDSIGNATURE, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_HASH,\n\t\t\t\t\t\t\t\t\t\thashContext );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't add externally-generated hash \"\n\t\t\t\t\t \"value to envelope, status %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tcount = pushData( cryptEnvelope, signedData, signedDataLength, NULL, 0 );\n\tif( count == CRYPT_ERROR_NOTAVAIL && \\\n\t\t!( detachedSig || hasTimestamp || checkData ) )\n\t\t{\n\t\t/* Some old signed data uses deprecated or now-broken algorithms\n\t\t   which will produce a CRYPT_ERROR_NOTAVAIL if we try and verify\n\t\t   the signature, treat this as a special case */\n\t\tfputs( \"Warning: The hash/signature algorithm required to verify \"\n\t\t\t   \"the signed data\\n         isn't enabled in this build of \"\n\t\t\t   \"cryptlib, can't verify the\\n         signature.\\n\\n\", \n\t\t\t   outputStream );\n\t\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\t\treturn( FALSE );\n\t\treturn( TRUE );\n\t\t}\n\tif( !cryptStatusError( count ) )\n\t\t{\n\t\tif( detachedSig )\n\t\t\t{\n\t\t\tif( hashContext == CRYPT_UNUSED )\n\t\t\t\t{\n\t\t\t\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\t\t}\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\n\t/* If we're checking for the ability to reject an incorrect key, fetch\n\t   a bogus signature key and try and add that */\n\tif( checkWrongKey )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptWrongCert;\n\n\t\tstatus = getPublicKey( &cryptWrongCert, DUAL_PRIVKEY_FILE, \n\t\t\t\t\t\t\t   DUAL_SIGNKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\t\tcryptWrongCert );\n\t\tcryptDestroyCert( cryptWrongCert );\n\t\tif( status != CRYPT_ERROR_WRONGKEY )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Use of incorrect key wasn't detected, \"\n\t\t\t\t\t \"got %d, should have been %d, line %d.\\n\", status, \n\t\t\t\t\t CRYPT_ERROR_WRONGKEY, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Display the details of the envelope signature and check whether\n\t   there's more information such as a timestamp or a second signature\n\t   present */\n\tstatus = displaySigResult( cryptEnvelope, sigCheckContext, \n\t\t\t\t\t\t\t   mustHaveAttributes, TRUE );\n\tif( status == TRUE && hasTimestamp )\n\t\t{\n\t\tCRYPT_ENVELOPE cryptTimestamp;\n\t\tint contentType;\n\n\t\t/* Try and get the timestamp info.  Note that we can't safely use\n\t\t   displaySigResult() on every timestamp because many are stripped-\n\t\t   down minimal-size CMS messages with no additional sig-checking\n\t\t   info present (for those ones we have to stop at reading the CMS \n\t\t   content-type to make sure that everything's OK), but for the\n\t\t   cryptlib test TSA there's always a full CMS signed message \n\t\t   returned */\n\t\tfprintf( outputStream, \"Envelope contains a timestamp...\" );\n\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_TIMESTAMP,\n\t\t\t\t\t\t\t\t\t&cryptTimestamp );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nCouldn't read timestamp from \"\n\t\t\t\t\t \"envelope, status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptGetAttribute( cryptTimestamp,\n\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_CONTENTTYPE, &contentType );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tcontentType != CRYPT_CONTENT_TSTINFO )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nTimestamp data envelope doesn't \"\n\t\t\t\t\t \"appear to contain a timestamp, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfputs( \" timestamp data appears OK.\\n\", outputStream );\n\n\t\t/* Now get the signature info (if the timestamp doesn't contain a \n\t\t   full CMS message then we'd set 'status = TRUE' at this point\n\t\t   without performing the signture check) */\n\t\tfputs( \"Timestamp signature information is:\\n\", outputStream );\n\t\tstatus = displaySigResult( cryptTimestamp, sigCheckContext, \n\t\t\t\t\t\t\t\t   TRUE, TRUE );\n\t\tcryptDestroyEnvelope( cryptTimestamp );\n\t\t}\n\tif( status == TRUE && cryptStatusOK( \\\n\t\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_NEXT ) ) )\n\t\t{\n\t\tfputs( \"Data has a second signature:\\n\", outputStream );\n\t\tstatus = displaySigResult( cryptEnvelope, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t   mustHaveAttributes, FALSE );\n\t\t}\n\tif( status == TRUE && cryptStatusOK( \\\n\t\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_NEXT ) ) )\n\t\t{\n\t\t/* We can have two, but not three */\n\t\tfprintf( outputStream, \"Data appears to have (nonexistent) third \"\n\t\t\t\t \"signature, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we're testing the ability to handle reference-counted objects, \n\t   create multiple references to the certificate object in the signed\n\t   data and make sure they're accessible */\n\tif( testRefCount )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert1, cryptCert2, cryptCert3;\n\t\tint value;\n\n\t\t/* Create three references to the signing certificate */\n\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t\t\t&cryptCert1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t\t\t\t&cryptCert2 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t\t\t\t&cryptCert3 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't retrieve 3 copies of signing \"\n\t\t\t\t\t \"certificate from envelope, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( cryptCert1 != cryptCert2 || cryptCert1 != cryptCert3 )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Multiple-referenced object has \"\n\t\t\t\t\t \"different object handles, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Destroy the second reference and make sure that it's still\n\t\t   accessible via both itself and another reference */\n\t\tstatus = cryptDestroyCert( cryptCert2 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert2, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert1, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Removing signing certificate reference \"\n\t\t\t\t\t \"caused consistency failure, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Destroy the original reference and make sure that it's no longer \n\t\t   accessible but other references are */\n\t\tstatus = cryptDestroyCert( cryptCert1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert1, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert3, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Removing signing certificate reference \"\n\t\t\t\t\t \"caused consistency failure, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Destroy the last reference and make sure that it's now \n\t\t   inaccessible */\n\t\tstatus = cryptDestroyCert( cryptCert1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptCert1, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\tstatus = cryptStatusError( status ) ? \\\n\t\t\t\t\t CRYPT_OK : CRYPT_ERROR_FAILED;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Removing signing certificate reference \"\n\t\t\t\t\t \"caused consistency failure, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Remember that everything went OK */\n\t\tstatus = TRUE;\n\t\t}\n\n\t/* Make sure that the result matches what we pushed */\n\tif( !detachedSig && checkData && \\\n\t\t!compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \\\n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\treturn( status );\n\t}\n\nstatic int cmsEnvelopeSign( const BOOLEAN useDatasize,\n\t\t\t\tconst BOOLEAN useAttributes, const BOOLEAN useExtAttributes,\n\t\t\t\tconst BOOLEAN detachedSig, const int externalHashLevel,\n\t\t\t\tconst BOOLEAN useTimestamp, const BOOLEAN useNonDataContent,\n\t\t\t\tconst BOOLEAN dualSig, const BOOLEAN testRefCount,\n\t\t\t\tconst CRYPT_CONTEXT externalSignContext,\n\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CONTEXT cryptContext, cryptContext2, hashContext = CRYPT_UNUSED;\n\tBOOLEAN isPGP = ( formatType == CRYPT_FORMAT_PGP ) ? TRUE : FALSE;\n\tBOOLEAN isRawCMS = ( formatType == CRYPT_FORMAT_CRYPTLIB ) ? TRUE : FALSE;\n\tint count, status = CRYPT_OK;\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of CMS signed \"\n\t\t\t   \"enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing %s %s%s\", isPGP ? \"PGP\" : \"CMS\",\n\t\t\t useExtAttributes ? \"extended \" : \"\",\n\t\t\t detachedSig ? \"detached signature\" : \\\n\t\t\t\tdualSig ? \"dual signature\" : \"signed enveloping\" );\n\tif( useNonDataContent )\n\t\tfprintf( outputStream, \" of non-data content\" );\n\tif( testRefCount )\n\t\tfprintf( outputStream, \" for reference-count capability check\" );\n\tif( externalHashLevel )\n\t\t{\n\t\tfprintf( outputStream, ( externalHashLevel == 1 ) ? \\\n\t\t\t\t \" with externally-supplied hash for verify\" : \\\n\t\t\t\t \" with ext-supplied hash for sign and verify\" );\n\t\t}\n\tif( !isPGP && !( useAttributes || testRefCount ) )\n\t\tfprintf( outputStream, \" without signing attributes\" );\n\tif( useDatasize && \\\n\t\t!( useNonDataContent || useAttributes || useExtAttributes || \\\n\t\t   detachedSig || useTimestamp || testRefCount ) )\n\t\t{\n\t\t/* Keep the amount of stuff being printed down */\n\t\tfprintf( outputStream, \" with datasize hint\" );\n\t\t}\n\tif( useTimestamp )\n\t\tfprintf( outputStream, \" and timestamp\" );\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Get the private key.  If we're applying two signatures, we also get\n\t   a second signing key.  Since the dual-key file test has created a\n\t   second signing key, we use that as the most convenient one */\n\tif( externalSignContext != CRYPT_UNUSED )\n\t\tcryptContext = externalSignContext;\n\telse\n\t\t{\n\t\tstatus = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfputs( \"Read of private key from key file failed, cannot test \"\n\t\t\t\t   \"CMS enveloping.\\n\\n\", outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( dualSig )\n\t\t{\n\t\tstatus = getPrivateKey( &cryptContext2, DUAL_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tDUAL_SIGNKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfputs( \"Read of private key from key file failed, cannot test \"\n\t\t\t\t   \"CMS enveloping.\\n\\n\", outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* If we're supplying the hash value for signing externally, calculate \n\t   it now */\n\tif( externalHashLevel > 1 )\n\t\t{\n\t\tint hashAlgo;\n\n\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t\t\t&hashAlgo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t hashAlgo );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( hashContext, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && formatType == CRYPT_FORMAT_CMS )\n\t\t\tstatus = cryptEncrypt( hashContext, \"\", 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfputs( \"Couldn't create external hash of data.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Create the CMS envelope and  push in the signing key(s) and data */\n\tif( !createEnvelope( &cryptEnvelope, formatType ) )\n\t\treturn( FALSE );\n\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\tcryptContext ) )\n\t\treturn( FALSE );\n\tif( dualSig )\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_SIGNATURE,\n\t\t\t\t\t\t\t\tcryptContext2 ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( detachedSig )\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, \n\t\t\t\t\t\t\t\tCRYPT_ENVINFO_DETACHEDSIGNATURE, TRUE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( externalHashLevel > 1 )\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_HASH,\n\t\t\t\t\t\t\t\thashContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( ( externalSignContext == CRYPT_UNUSED ) && !isPGP && !isRawCMS )\n\t\tcryptDestroyContext( cryptContext );\n\tif( dualSig )\n\t\tcryptDestroyContext( cryptContext2 );\n\tif( externalHashLevel > 1 )\n\t\t{\n\t\tcryptDestroyContext( hashContext );\n\t\thashContext = CRYPT_UNUSED;\n\t\t}\n\tif( useNonDataContent )\n\t\t{\n\t\t/* Test non-data content type w.automatic attribute handling */\n\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_CONTENTTYPE,\n\t\t\t\t\t\t\t\t\tCRYPT_CONTENT_SIGNEDDATA );\n\t\t}\n\tif( cryptStatusOK( status ) && useDatasize )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t\t\t\tENVELOPE_TESTDATA_SIZE );\n\t\t}\n\tif( cryptStatusOK( status ) && useExtAttributes )\n\t\t{\n\t\t/* We have to be careful when setting CMS attributes because most \n\t\t   are never used by anything so they're only available of use of \n\t\t   obscure attributes is enabled (unfortunately there aren't\n\t\t   actually any attributes that are available for this, but the\n\t\t   functionality is tested by the added-by-default attributes such\n\t\t   as the signing time) */\n#ifdef USE_CMS_OBSCURE\n\t\tCRYPT_CERTIFICATE cmsAttributes;\n\n\t\t/* Add an ESS security label and signing description as signing\n\t\t   attributes */\n\t\tstatus = cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptSetAttributeString( cmsAttributes,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SECLABEL_POLICY,\n\t\t\t\t\t\t\tTEXT( \"1 3 6 1 4 1 9999 1\" ),\n\t\t\t\t\t\t\tparamStrlen( TEXT( \"1 3 6 1 4 1 9999 1\" ) ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cmsAttributes,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SECLABEL_CLASSIFICATION,\n\t\t\t\t\t\t\tCRYPT_CLASSIFICATION_SECRET );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cmsAttributes,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SECLABEL_CATTYPE,\n\t\t\t\t\t\t\tTEXT( \"1 3 6 1 4 1 9999 2\" ),\n\t\t\t\t\t\t\tparamStrlen( TEXT( \"1 3 6 1 4 1 9999 2\" ) ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cmsAttributes,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SECLABEL_CATVALUE,\n\t\t\t\t\t\t\t\"\\x04\\x04\\x01\\x02\\x03\\x04\", 6 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cmsAttributes,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CMS_SIGNINGDESCRIPTION,\n\t\t\t\t\t\t\t\"This signature isn't worth the paper it's not \"\n\t\t\t\t\t\t\t\"printed on\", 56 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope,\n\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE_EXTRADATA, cmsAttributes );\n\t\t\t}\n\t\tcryptDestroyCert( cmsAttributes );\n#endif /* USE_CMS_OBSCURE */\n\t\t}\n\tif( cryptStatusOK( status ) && !isPGP && !useAttributes )\n\t\tstatus = cryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t\tCRYPT_OPTION_CMS_DEFAULTATTRIBUTES, FALSE );\n\tif( cryptStatusOK( status ) && useTimestamp )\n\t\t{\n\t\tCRYPT_SESSION cryptSession;\n\n\t\t/* Create the TSP session, add the TSA URL, and add it to the\n\t\t   envelope */\n\t\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_SESSION_TSP );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\t/* TSP session access not available */\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  TSP_DEFAULTSERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( TSP_DEFAULTSERVER_NAME ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttributeString()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tstatus = cryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_TIMESTAMP,\n\t\t\t\t\t\t\t\t\tcryptSession );\n\t\tcryptDestroySession( cryptSession );\n\t\tif( isRawCMS )\n\t\t\t{\n\t\t\t/* Signing attributes aren't allowed for raw CMS data */\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tdestroyEnvelope( cryptEnvelope );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Addition of timestamping attribute \"\n\t\t\t\t\t\t \"to CRYPT_FORMAT_CRYPTLIB envelope\\n  succeeded, \"\n\t\t\t\t\t\t \"should have failed, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tfputs( \"Enveloping with timestamp using invalid env.type was \"\n\t\t\t\t   \"correctly rejected.\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttribute() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Push in the data to be signed, unless it's already been processed via\n\t   an external hash */\n\tif( externalHashLevel < 2 )\n\t\t{\n\t\tstatus = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\t\t}\n\tif( !isPGP && !useAttributes )\n\t\t{\n\t\t/* Restore the default attributes setting */\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CMS_DEFAULTATTRIBUTES,\n\t\t\t\t\t\t   TRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The timestamping can fail for a wide range of (non-fatal) reasons,\n\t\t   typically either because this build doesn't have networking\n\t\t   enabled or because the TSA can't be contacted, so we don't treat\n\t\t   this one as a fatal error */\n\t\tif( useTimestamp )\n\t\t\t{\n\t\t\tfputs( \"Envelope timestamping failed due to problems talking to \"\n\t\t\t\t   \"TSA, this is a non-\\ncritical problem.  \"\n\t\t\t\t   \"Continuing...\\n\\n\", outputStream );\n\t\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Pop the resulting signature data and destroy the envelope */\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"%s %s has size %d bytes.\\n\", \n\t\t\t isPGP ? \"PGP\" : \"CMS\",\n\t\t\t ( detachedSig ) ? \"detached signature\" : \"signed data\",\n\t\t\t count );\n\tdebugDump( detachedSig ?\n\t\t\t\t ( !isPGP ? \\\n\t\t\t\t   ( useDatasize ? \"smi_dsg\" : \"smi_dsgn\" ) : \\\n\t\t\t\t   \"pgp_dsg.pgp\" ) : \\\n\t\t\t   useExtAttributes ? \\\n\t\t\t\t ( useDatasize ? \"smi_esg\" : \"smi_esgn\" ) : \\\n\t\t\t   useTimestamp ? \\\n\t\t\t\t ( useDatasize ? \"smi_tsg\" : \"smi_tsgn\" ) : \\\n\t\t\t   useNonDataContent ? \\\n\t\t\t\t ( useDatasize ? \"smi_ndc\" : \"smi_ndcn\" ) : \\\n\t\t\t   dualSig ? \\\n\t\t\t\t ( useDatasize ? \"smi_2sg\" : \"smi_n2sg\" ) : \\\n\t\t\t   useDatasize ? \"smi_sig\" : \"smi_sign\", globalBuffer, count );\n\n\t/* If we're supplying the hash value for verification externally, \n\t   calculate it now */\n\tif( externalHashLevel > 0 )\n\t\t{\n\t\tint hashAlgo;\n\n\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t\t\t&hashAlgo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t hashAlgo );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( hashContext, ENVELOPE_TESTDATA,\n\t\t\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && formatType == CRYPT_FORMAT_CMS )\n\t\t\tstatus = cryptEncrypt( hashContext, \"\", 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfputs( \"Couldn't create external hash of data.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Make sure that the signature is valid.  The somewhat redundant mapping\n\t   of useNonDataContent is because we're performing an additional check\n\t   of envelope key-handling as part of this particular operation */\n\tstatus = cmsEnvelopeSigCheck( globalBuffer, count,\n\t\t\t\t\tisPGP || isRawCMS ? cryptContext : CRYPT_UNUSED, \n\t\t\t\t\thashContext, detachedSig, useTimestamp, TRUE, \n\t\t\t\t\tuseAttributes, useNonDataContent ? TRUE : FALSE, \n\t\t\t\t\ttestRefCount );\n\tif( externalHashLevel > 0 )\n\t\tcryptDestroyContext( hashContext );\n\tif( isPGP || isRawCMS )\n\t\tcryptDestroyContext( cryptContext );\n\tif( status <= 0 )\n\t\treturn( FALSE );\n\n\tif( detachedSig )\n\t\t{\n\t\tfprintf( outputStream, \"Creation of %s %sdetached signature \"\n\t\t\t\t \"%ssucceeded.\\n\\n\",\n\t\t\t\t isPGP ? \"PGP\" : \"CMS\", useExtAttributes ? \"extended \" : \"\",\n\t\t\t\t ( hashContext != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\"with externally-supplied hash \" : \"\" );\n\t\t}\n\telse\n\t\t{\n\t\tfprintf( outputStream, \"Enveloping of CMS %s%ssigned data \"\n\t\t\t\t \"succeeded.\\n\\n\", useExtAttributes ? \"extended \" : \"\",\n\t\t\t\t useTimestamp ? \"timestamped \" : \"\" );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testCMSEnvelopeSign( void )\n\t{\n\tif( !cmsEnvelopeSign( FALSE, FALSE, FALSE, FALSE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Minimal (no default S/MIME attributes) */\n\tif( !cmsEnvelopeSign( FALSE, TRUE, FALSE, FALSE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Standard (default S/MIME signing attributes) */\n\tif( !cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Datasize and attributes */\n\tif( !cmsEnvelopeSign( FALSE, TRUE, TRUE, FALSE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Extended signing attributes */\n\tif( !cmsEnvelopeSign( TRUE, TRUE, TRUE, FALSE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Datasize and extended attributes */\n\treturn( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, 0, FALSE, TRUE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) );\n\t}\t\t\t\t\t\t/* Signing of non-data content */\n\nint testCMSEnvelopeDualSign( void )\n\t{\n\treturn( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) );\n\t\t\t\t\t\t\t/* Standard, with two signatures */\n\t}\n\nint testCMSEnvelopeDetachedSig( void )\n\t{\n\tif( !cmsEnvelopeSign( FALSE, TRUE, FALSE, TRUE, 0, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Detached sig and attributes */\n\tif( !cmsEnvelopeSign( FALSE, TRUE, FALSE, TRUE, 1, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Detached sig, attributes, externally-suppl.hash for verify */\n\treturn( cmsEnvelopeSign( FALSE, TRUE, FALSE, TRUE, 2, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) );\n\t}\t\t\t\t\t\t/* Detached sig, externally-suppl.hash for sign and verify */\n\nint testCMSEnvelopeSignEx( const CRYPT_CONTEXT signContext )\n\t{\n\treturn( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, signContext, CRYPT_FORMAT_CMS ) );\n\t}\t\t\t\t\t\t/* Datasize, attributes, external signing context */\n\nint testCMSEnvelopeRefCount( void )\n\t{\n\t/* This isn't so much a signature test as a test of the reference-\n\t   counting mechanism in the cryptlib kernel, but it uses a CMS \n\t   signature with associated certificate data for the test */\n\treturn( cmsEnvelopeSign( TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) );\n\t}\n\nint testPGPEnvelopeDetachedSig( void )\n\t{\n\tif( !cmsEnvelopeSign( TRUE, FALSE, FALSE, TRUE, 1, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* Detached sig, data size, externally-suppl.hash for verify, PGP format */\n\treturn( cmsEnvelopeSign( TRUE, FALSE, FALSE, TRUE, 2, FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_PGP ) );\n\t}\t\t\t\t\t\t/* Detached sig, data size, externally-suppl.hash for sign and verify, PGP format */\n\nint testSessionEnvTSP( void )\n\t{\n\t/* This is a pseudo-enveloping test that uses the enveloping\n\t   functionality but is called as part of the session tests since full\n\t   testing of the TSP handling requires that it be used to timestamp an\n\t   S/MIME sig */\n\tif( !cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\t/* Datasize, attributes, timestamp */\n\treturn( cmsEnvelopeSign( TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_FORMAT_CRYPTLIB ) );\n\t}\t\t\t\t\t\t/* Invalid attempt to use attrs.with raw CMS envelope */\n\nstatic int cmsImportSignedData( const char *fileName, const int fileNo )\n\t{\n\tBYTE *bufPtr = globalBuffer;\n\tchar msgBuffer[ 128 ];\n\tint count, status;\n\n\t/* Read the test data */\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE )\n\t\t{\n\t\tif( ( bufPtr = malloc( count ) ) == NULL )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't allocate test buffer of \"\n\t\t\t\t\t \"%d bytes, line %d.\\n\", count, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tsprintf( msgBuffer, \"S/MIME SignedData #%d\", fileNo );\n\tcount = readFileData( fileName, msgBuffer, bufPtr, count, 2048, FALSE );\n\tif( count <= 0 )\n\t\t{\n\t\tif( bufPtr != globalBuffer )\n\t\t\tfree( bufPtr );\n\t\treturn( count );\n\t\t}\n\n\t/* Check the signature on the data */\n\tstatus = cmsEnvelopeSigCheck( bufPtr, count, CRYPT_UNUSED, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  FALSE, FALSE, FALSE, \n\t\t\t\t\t\t\t\t  ( fileNo == 1 ) ? FALSE : TRUE, FALSE, FALSE );\n\tif( bufPtr != globalBuffer )\n\t\tfree( bufPtr );\n\tif( status )\n\t\tfputs( \"S/MIME SignedData import succeeded.\\n\\n\", outputStream );\n\telse\n\t\t{\n\t\t/* The AuthentiCode data sig-check fails for some reason */\n\t\tif( fileNo == 2 )\n\t\t\t{\n\t\t\tfputs( \"AuthentiCode SignedData import succeeded but signature \"\n\t\t\t\t   \"couldn't be verified\\n  due to AuthentiCode special \"\n\t\t\t\t   \"processing requirements.\\n\\n\", outputStream );\n\t\t\t}\n\t\t}\n\treturn( status );\n\t}\n\n/* Test CMS enveloping/de-enveloping */\n\nstatic int cmsEnvelopeDecrypt( const void *envelopedData,\n\t\t\t\t\t\t\t   const int envelopedDataLength,\n\t\t\t\t\t\t\t   const CRYPT_HANDLE externalKeyset,\n\t\t\t\t\t\t\t   const C_STR externalPassword,\n\t\t\t\t\t\t\t   const BOOLEAN checkDataMatch )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\t/* Create the envelope and push in the decryption keyset */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( externalKeyset != CRYPT_UNUSED )\n\t\tstatus = addEnvInfoNumeric( cryptEnvelope,\n\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_DECRYPT, externalKeyset );\n\telse\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = addEnvInfoNumeric( cryptEnvelope,\n\t\t\t\t\t\t\t\tCRYPT_ENVINFO_KEYSET_DECRYPT, cryptKeyset );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( status <= 0 )\n\t\treturn( FALSE );\n\n\t/* Push in the data */\n\tif( externalPassword == NULL )\n\t\texternalPassword = TEST_PRIVKEY_PASSWORD;\n\tcount = pushData( cryptEnvelope, envelopedData, envelopedDataLength,\n\t\t\t\t\t  externalPassword, paramStrlen( externalPassword ) );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* If we're not checking for a match of the decrypted data (done when \n\t   the data is coming from an external source rather than being \n\t   something that we generated ourselves), we're done */\n\tif( !checkDataMatch )\n\t\treturn( TRUE );\n\n\t/* Make sure that the result matches what we pushed */\n\tif( !compareData( ENVELOPE_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\nstatic int cmsEnvelopeCrypt( const char *dumpFileName,\n\t\t\t\t\t\t\t const BOOLEAN useDatasize,\n\t\t\t\t\t\t\t const BOOLEAN useStreamCipher,\n\t\t\t\t\t\t\t const BOOLEAN useLargeBlockCipher,\n\t\t\t\t\t\t\t const BOOLEAN useExternalRecipientKeyset,\n\t\t\t\t\t\t\t const CRYPT_HANDLE externalCryptContext,\n\t\t\t\t\t\t\t const CRYPT_HANDLE externalKeyset,\n\t\t\t\t\t\t\t const C_STR externalPassword,\n\t\t\t\t\t\t\t const C_STR recipientName )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_HANDLE cryptKey;\n\tint count, status;\n\n\tif( !keyReadOK )\n\t\t{\n\t\tfputs( \"Couldn't find key files, skipping test of CMS encrypted \"\n\t\t\t   \"enveloping...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing CMS public-key encrypted enveloping\" );\n\tif( externalKeyset != CRYPT_UNUSED && recipientName != NULL )\n\t\t{\n\t\tif( useExternalRecipientKeyset )\n\t\t\tfprintf( outputStream, \" with recipient keys in device\" );\n\t\telse\n\t\t\tfprintf( outputStream, \" with dual encr./signing certs\" );\n\t\t}\n\telse\n\t\t{\n\t\tif( useStreamCipher )\n\t\t\tfprintf( outputStream, \" with stream cipher\" );\n\t\telse\n\t\t\t{\n\t\t\tif( useLargeBlockCipher )\n\t\t\t\tfprintf( outputStream, \" with large block size cipher\" );\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( useDatasize )\n\t\t\t\t\tfprintf( outputStream, \" with datasize hint\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Get the public key.  We use assorted variants to make sure that they\n\t   all work */\n\tif( externalCryptContext != CRYPT_UNUSED )\n\t\t{\n\t\tint cryptAlgo;\n\n\t\tstatus = cryptGetAttribute( externalCryptContext, CRYPT_CTXINFO_ALGO,\n\t\t\t\t\t\t\t\t\t&cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfputs( \"Couldn't determine algorithm for public key, cannot \"\n\t\t\t\t   \"test CMS enveloping.\\n\\n\", outputStream );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptKey = externalCryptContext;\n\t\t}\n\telse\n\t\t{\n\t\tif( recipientName == NULL )\n\t\t\t{\n\t\t\t/* No recipient name, get the public key */\n\t\t\tstatus = getPublicKey( &cryptKey, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Create the envelope, add the public key and originator key if\n\t   necessary, push in the data, pop the enveloped result, and destroy\n\t   the envelope */\n\tif( !createEnvelope( &cryptEnvelope, CRYPT_FORMAT_CMS ) )\n\t\treturn( FALSE );\n\tif( recipientName != NULL )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset = externalKeyset;\n\n\t\t/* We're using a recipient name, add the recipient keyset and\n\t\t   recipient name */\n\t\tif( !useExternalRecipientKeyset )\n\t\t\t{\n\t\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, \n\t\t\t\t\t\t\t\t\t  DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't open key database, \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_KEYSET_ENCRYPT,\n\t\t\t\t\t\t\t\tcryptKeyset ) )\n\t\t\treturn( FALSE );\n\t\tif( !useExternalRecipientKeyset )\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\tif( !addEnvInfoString( cryptEnvelope, CRYPT_ENVINFO_RECIPIENT,\n\t\t\t\t\t\t\t   recipientName, paramStrlen( recipientName ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !addEnvInfoNumeric( cryptEnvelope, CRYPT_ENVINFO_PUBLICKEY,\n\t\t\t\t\t\t\t\tcryptKey ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( externalCryptContext == CRYPT_UNUSED && recipientName == NULL )\n\t\tcryptDestroyObject( cryptKey );\n\tif( useDatasize )\n\t\t{\n\t\tcryptSetAttribute( cryptEnvelope, CRYPT_ENVINFO_DATASIZE,\n\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\t\t}\n\tcount = pushData( cryptEnvelope, ENVELOPE_TESTDATA,\n\t\t\t\t\t  ENVELOPE_TESTDATA_SIZE, NULL, 0 );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tcount = popData( cryptEnvelope, globalBuffer, BUFFER_SIZE );\n\tif( cryptStatusError( count ) )\n\t\treturn( FALSE );\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\n\t/* Tell them what happened */\n\tfprintf( outputStream, \"Enveloped data has size %d bytes.\\n\", count );\n\tdebugDump( dumpFileName, globalBuffer, count );\n\n\t/* Make sure that the enveloped data is valid */\n\tstatus = cmsEnvelopeDecrypt( globalBuffer, count, externalKeyset,\n\t\t\t\t\t\t\t\t externalPassword, TRUE );\n\tif( status <= 0 )\t/* Can be FALSE or an error code */\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tfputs( \"Enveloping of CMS public-key encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nstatic int cmsImportEnvelopedData( const char *fileName, const int fileNo )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE *bufPtr = globalBuffer;\n\tchar msgBuffer[ 128 ];\n\tint count, bytesIn, byteCount = 0, status;\n\n\t/* Read the test data */\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE )\n\t\t{\n\t\tif( ( bufPtr = malloc( count ) ) == NULL )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't allocate test buffer of \"\n\t\t\t\t\t \"%d bytes, lin e%d.\\n\", count, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tsprintf( msgBuffer, \"S/MIME EnvelopedData #%d\", fileNo );\n\tcount = readFileData( fileName, msgBuffer, bufPtr, count, 128, FALSE );\n\tif( count <= 0 )\n\t\t{\n\t\tif( bufPtr != globalBuffer )\n\t\t\tfree( bufPtr );\n\t\treturn( count );\n\t\t}\n\n\t/* Make sure that we can parse the data */\n\tif( !createDeenvelope( &cryptEnvelope ) )\n\t\t{\n\t\tif( bufPtr != globalBuffer )\n\t\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptPushData( cryptEnvelope, bufPtr, count, &bytesIn );\n\twhile( status == CRYPT_ERROR_UNDERFLOW )\n\t\t{\n\t\tbyteCount += bytesIn;\n\t\tstatus = cryptPushData( cryptEnvelope, bufPtr + byteCount,\n\t\t\t\t\t\t\t\tcount - byteCount, &bytesIn );\n\t\t}\n\tif( bufPtr != globalBuffer )\n\t\tfree( bufPtr );\n\tif( cryptStatusError( status ) && status != CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tprintExtError( cryptEnvelope, \"cryptPushData()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\t}\n\tif( !destroyEnvelope( cryptEnvelope ) )\n\t\treturn( FALSE );\n\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\t/* When we get to the CRYPT_ENVELOPE_RESOURCE stage we know that \n\t\t   we've successfully processed all of the recipients because\n\t\t   cryptlib is asking us for a key to continue */\n\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\tfputs( \"S/MIME EnvelopedData import succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nint testCMSEnvelopePKCCrypt( void )\n\t{\n\tint value, status;\n\n\tif( !cmsEnvelopeCrypt( \"smi_pkcn\", FALSE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_UNUSED, NULL, NULL ) )\n\t\treturn( FALSE );\t/* Standard */\n\tif( !cmsEnvelopeCrypt( \"smi_pkc\", TRUE, FALSE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_UNUSED, NULL, NULL ) )\n\t\treturn( FALSE );\t/* Datasize hint */\n\n\t/* Test enveloping with an IV-less stream cipher, which bypasses the usual\n\t   CBC-mode block cipher handling.  The alternative way of doing this is\n\t   to manually add a CRYPT_CTXINFO_SESSIONKEY object, doing it this way is\n\t   less work */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_RC4 );\n\tstatus = cmsEnvelopeCrypt( \"smi_pkcs\", TRUE, TRUE, FALSE, FALSE, CRYPT_UNUSED, CRYPT_UNUSED, NULL, NULL );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, value );\n\tif( !status )\t\t\t/* Datasize and stream cipher */\n\t\treturn( status );\n\n\t/* Test enveloping with a cipher with a larger-than-usual block size */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, &value );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, CRYPT_ALGO_AES );\n\tstatus = cmsEnvelopeCrypt( \"smi_pkcb\", TRUE, FALSE, TRUE, FALSE, CRYPT_UNUSED, CRYPT_UNUSED, NULL, NULL );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_ALGO, value );\n\treturn( status );\t\t/* Datasize and large blocksize cipher */\n\t}\n\nint testCMSEnvelopePKCCryptEx( const CRYPT_HANDLE encryptContext,\n\t\t\t\t\t\t\t   const CRYPT_HANDLE decryptKeyset,\n\t\t\t\t\t\t\t   const C_STR password, const C_STR recipient )\n\t{\n\tint status;\n\n\tassert( ( encryptContext != CRYPT_UNUSED && recipient == NULL ) || \\\n\t\t\t( encryptContext == CRYPT_UNUSED && recipient != NULL ) );\n\n\t/* We can either provide the recipient's key directly as a pubkey\n\t   context or indirectly as a recipient name.  This is used to test\n\t   a device's ability to act as a recipient key store */\n\tstatus = cmsEnvelopeCrypt( \"smi_pkcd\", TRUE, FALSE, FALSE, \\\n\t\t\t\t\t\t\t   ( recipient != NULL ) ? TRUE : FALSE, \\\n\t\t\t\t\t\t\t   encryptContext, decryptKeyset, password, \\\n\t\t\t\t\t\t\t   recipient );\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\t\t\t\t\t/* Datasize, keys in crypto device */\n\t\tfputs( \"  (This is probably because the public key certificate was \"\n\t\t\t   \"regenerated after\\n   the certificate stored with the \"\n\t\t\t   \"private key was created, so that the\\n   private key can't \"\n\t\t\t   \"be identified any more using the public key that was\\n   \"\n\t\t\t   \"used for encryption.  This can happen when the cryptlib \"\n\t\t\t   \"self-test is run\\n   in separate stages, with one stage \"\n\t\t\t   \"re-using data that was created\\n   earlier during a \"\n\t\t\t   \"previous stage).\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\treturn( status );\n\t}\n\nint testCMSEnvelopePKCCryptDoubleCert( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* The dual-certificate test uses cryptlib's internal key management to \n\t   read the appropriate certificate from a database keyset, if this \n\t   hasn't been set up then the test will fail so we try and detect the \n\t   presence of the database keyset here.  This isn't perfect since it \n\t   requires that the database keyset be updated with the certificates in \n\t   the same run as this test, but it's the best we can do */\n\tif( !doubleCertOK )\n\t\t{\n\t\tfputs( \"The certificate database wasn't updated with dual encryption/\"\n\t\t\t   \"signing certs\\nduring this test run (either because database \"\n\t\t\t   \"keysets aren't enabled in this\\nbuild of cryptlib or because \"\n\t\t\t   \"only some portions of the self-tests are being\\nrun), \"\n\t\t\t   \"skipping the test of CMS enveloping with dual certs.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Since we're using certs with the same DN and email address present\n\t   in multiple certs, we can't use the generic user keyset but have to\n\t   use one that has been set up to have multiple certs that differ\n\t   only in keyUsage */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  DUAL_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"Couldn't find keyset with dual encryption/signature certs \"\n\t\t\t   \"for test of dual certificate\\nencryption.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cmsEnvelopeCrypt( \"smi_pkcr\", TRUE, FALSE, FALSE, FALSE, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, cryptKeyset, \n\t\t\t\t\t\t\t   TEST_PRIVKEY_PASSWORD, \n\t\t\t\t\t\t\t   TEXT( \"dave@wetaburgers.com\" ) );\n\tcryptKeysetClose( cryptKeyset );\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\t\t\t\t\t/* Datasize, recipient */\n\t\tfputs( \"  (This is probably because the public key certificate was \"\n\t\t\t   \"regenerated after\\n   the certificate stored with the \"\n\t\t\t   \"private key was created, so that the\\n   private key can't \"\n\t\t\t   \"be identified any more using the public key that was\\n   \"\n\t\t\t   \"used for encryption.  This can happen when the cryptlib \"\n\t\t\t   \"self-test is run\\n   in separate stages, with one stage \"\n\t\t\t   \"re-using data that was created\\n   earlier during a \"\n\t\t\t   \"previous stage).\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTest Data Import Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Import S/MIME signed data */\n\nint testCMSEnvelopeSignedDataImport( void )\n\t{\n\tFILE *filePtr;\n\tBYTE fileName[ BUFFER_SIZE ];\n\tint i;\n\n\t/* Make sure that the test data is present so that we can return a\n\t   useful error message */\n\tfilenameFromTemplate( fileName, SMIME_SIG_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't find S/MIME SignedData file, skipping test of \"\n\t\t\t   \"SignedData import...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfclose( filePtr );\n\n\t/* There are many encoding variations possible for signed data so we try\n\t   a representative sample to make sure that the code works in all\n\t   cases */\n\tfor( i = 1; i <= 3; i++ )\n\t\t{\n\t\tfilenameFromTemplate( fileName, SMIME_SIG_FILE_TEMPLATE, i );\n\t\tif( !cmsImportSignedData( fileName, i ) && i != 2 )\n\t\t\t{\n\t\t\t/* AuthentiCode sig check fails for some reason */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\tfputs( \"Import of S/MIME SignedData succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import S/MIME encrypted data */\n\nint testCMSEnvelopePKCCryptImport( void )\n\t{\n\tFILE *filePtr;\n\tBYTE fileName[ BUFFER_SIZE ];\n\tint i;\n\n\t/* Make sure that the test data is present so that we can return a\n\t   useful error message */\n\tfilenameFromTemplate( fileName, SMIME_ENV_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't find S/MIME EnvelopedData file, skipping test of \"\n\t\t\t   \"EnvelopedData import...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfclose( filePtr );\n\n\t/* Enveloped data requires decryption keys that aren't generally\n\t   available, so all that we do in this case is make sure that we can\n\t   parse the data */\n\tfor( i = 1; i <= 1; i++ )\n\t\t{\n\t\tfilenameFromTemplate( fileName, SMIME_ENV_FILE_TEMPLATE, i );\n\t\tif( !cmsImportEnvelopedData( fileName, i ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Import of S/MIME EnvelopedData succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import CMS password-encrypted/authenticated data */\n\nint testEnvelopePasswordCryptImport( void )\n\t{\n\tFILE *filePtr;\n\tBYTE fileName[ BUFFER_SIZE ];\n\tint i;\n\n\t/* Make sure that the test data is present so that we can return a\n\t   useful error message */\n\tfilenameFromTemplate( fileName, CMS_ENC_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't find CMS EnvelopedData file, skipping test of \"\n\t\t\t   \"EnvelopedData/AuthentcatedData import...\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfclose( filePtr );\n\n\t/* Process the password-protected data.  The files are:\n\n\t\tFile 1: CMS Authenticated data, AES-256 key wrap with HMAC-SHA1.\n\n\t\tFile 2: CMS Enveloped data, AES-128 key wrap with AES-128 */\n\tfor( i = 1; i <= 2; i++ )\n\t\t{\n\t\tint count;\n\n\t\tcount = readFileFromTemplate( CMS_ENC_FILE_TEMPLATE, i, \n\t\t\t\t\t\t\t\t\t  \"CMS password-encrypted/authd data\",\n\t\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\t\tif( count <= 0 )\n\t\t\treturn( FALSE );\n\t\tif( !cmsEnvelopeDecrypt( globalBuffer, count, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t TEST_PASSWORD, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Import of CMS password-encrypted/authenticated data \"\n\t\t   \"succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import PGP 2.x and OpenPGP-generated password-encrypted data */\n\nint testPGPEnvelopePasswordCryptImport( void )\n\t{\n\tint count;\n\n\t/* Process the PGP 2.x data: IDEA with MD5 hash.  Create with:\n\n\t\tpgp -c +compress=off -o conv_enc1.pgp test.txt */\n#ifdef USE_IDEA\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 1, \n\t\t\t\t\t\t\t\t  \"PGP password-encrypted data\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePasswordDecrypt( globalBuffer, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tfputs( \"Import of PGP password-encrypted data succeeded.\\n\", \n\t\t   outputStream );\n#endif /* USE_IDEA */\n\n\t/* Process the OpenPGP data, all with password \"password\".  The files are:\n\t\n\t\tFile 2: 3DES with SHA1 hash.  Create with:\n\n\t\t\tpgp65 -c +compress=off -o conv_enc2.pgp test.txt \n\t\n\t\tFile 3: 3DES with SHA1 non-iterated hash.  Create with:\n\n\t\t\tgpg -c -z 0 --cipher-algo 3des --s2k-mode 1 -o conv_enc3.pgp test.txt \n\t\t\t\n\t\tFile 4: AES without MDC.  Create with\n\n\t\t\tgpg -c -z 0 --disable-mdc --cipher-algo aes -o conv_enc4.pgp test.txt \n\n\t\tFile 5: AES with MDC.  Create with:\n\n\t\t\tgpg -c -z 0 --cipher-algo aes -o conv_enc5.pgp test.txt\n\n\t\tFile 6: AES with MDC and indefinite inner length.  Create with:\n\n\t\t\tgpg -c --cipher-algo aes -o conv_enc5.pgp test.txt\n\n\t\tFile 7: 3DES with partial lengths.  Create with:\n\n\t\t\tcat test.c | gpg -c -z 0 --cipher-algo 3des -o conv_enc6.pgp\n\t\t\t\n\t\t\tNote that this requires using a file with a minimum length of a \n\t\t\tfew hundred bytes, since anything shorter is encoded into a \n\t\t\tfixed-length packet.\n\t\t\t\n\t\tSince the inner content for files 6 and 7 are indefinite-length, we \n\t\tneed to process that in a separate pass, which we do by handing it to \n\t\tthe compressed-data de-enveloping code, this is really a general \n\t\t\"process non-encrypted content\" function so we get back the inner \n\t\tcontent */\n#ifdef USE_3DES\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 2, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (3DES)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !envelopePasswordDecrypt( globalBuffer, count ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 3, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (3DES+non-iterated hash)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !envelopePasswordDecrypt( globalBuffer, count ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n#endif /* USE_3DES */\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 4, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (AES)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !envelopePasswordDecrypt( globalBuffer, count ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 5, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (AES+MDC)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !envelopePasswordDecrypt( globalBuffer, count ) )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 6, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (AES+MDC, indef-len inner)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePasswordDecrypt( globalBuffer, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeDecompress( globalBuffer, BUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n#ifdef USE_3DES\n\tcount = readFileFromTemplate( PGP_ENC_FILE_TEMPLATE, 7, \n\t\t\t\t\t\t\t\t  \"OpenPGP password-encrypted data (partial lengths)\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePasswordDecrypt( globalBuffer, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeDecompress( globalBuffer, BUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_COMPRESSEDDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_TESTDATA_SIZE ) )\n\t\treturn( FALSE );\n#endif /* USE_3DES */\n\tfputs( \"Import of OpenPGP password-encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import PGP 2.x and OpenPGP-generated PKC-encrypted data */\n\nint testPGPEnvelopePKCCryptImport( void )\n\t{\n#if defined( USE_PGP2 ) || defined( USE_3DES ) || defined( USE_BLOWFISH )\n\tint count;\n#endif /* USE_PGP2 || USE_3DES || USE_BLOWFISH */\n\n\t/* Process the PGP 2.x encrypted data */\n#ifdef USE_PGP2\n\tcount = readFileFromTemplate( PGP_PKE_FILE_TEMPLATE, 1, \n\t\t\t\t\t\t\t\t  \"PGP-encrypted data\", globalBuffer,\n\t\t\t\t\t\t\t\t  BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_PGP, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tcount = readFileFromTemplate( PGP_PKE_FILE_TEMPLATE, 2, \n\t\t\t\t\t\t\t\t  \"PGP (NAI)-encrypted data\", globalBuffer,\n\t\t\t\t\t\t\t\t  BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_NAIPGP, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( globalBuffer[ 0 ] != 0xA3 || globalBuffer[ 1 ] != 0x01 || \\\n\t\tglobalBuffer[ 2 ] != 0x5B || globalBuffer[ 3 ] != 0x53 )\n\t\t{\n\t\tfputs( \"De-enveloped data != original data.\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Import of PGP-encrypted data succeeded.\\n\\n\", outputStream );\n#endif /* USE_PGP2 */\n\n\t/* Process the OpenPGP encrypted data.  The files are:\n\n\t\tFile 1: RSA with 3DES.  Create with:\n\n\t\t\tpgpo -e +pubring=\".\\pubring.pgp\" +compress=off -o gpg_enc1.pgp -r test test.txt\n\n\t\t\t(In theory it could be created with\n\t\t\tgpg -e -z 0 --homedir . --always-trust -r test test.txt\n\t\t\tand pubring.pgp renamed to pubring.gpg, however GPG won't allow \n\t\t\tthe use of the RSA key in pubring.pgp no matter what command-\n\t\t\tline options you specify because it's not self-signed).\n\n\t\tFile 2: Elgamal and AES without MDC.  Create with:\n\n\t\t\tcp sec_hash.gpg secring.gpg\n\t\t\tcp pub_hash.gpg pubring.gpg\n\t\t\tgpg -e --disable-mdc -z 0 --homedir . -o gpg_enc2.gpg -r test1 test.txt\n\t\t\trm secring.gpg pubring.gpg\n\n\t\tFile 3: Elgamal and AES with MDC.  Create with:\n\n\t\t\tcp sec_hash.gpg secring.gpg\n\t\t\tcp pub_hash.gpg pubring.gpg\n\t\t\tgpg -e -z 0 --homedir . -o gpg_enc3.gpg -r test1 test.txt\n\t\t\trm secring.gpg pubring.gpg\n\n\t\tFile 4: Elgamal and Blowfish with MDC.  Create with:\n\n\t\t\tcp sec_hash.gpg secring.gpg\n\t\t\tcp pub_hash.gpg pubring.gpg\n\t\t\tgpg -e -z 0 --homedir . --cipher-algo blowfish -o gpg_enc4.gpg -r test1 test.txt\n\t\t\trm secring.gpg pubring.gpg\n\t\t\n\t\tFile 5: Elgamal and AES with MDC and partial lengths (not sure how \n\t\t\t\tthis was created) */\n#if defined( USE_PGP2 ) && defined( USE_3DES )\t/* Uses PGP 2.x private keyring */\n\tcount = readFileFromTemplate( OPENPGP_PKE_FILE_TEMPLATE, 1, \n\t\t\t\t\t\t\t\t  \"OpenPGP (GPG)-encrypted data\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_PGP, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n#endif /* USE_PGP2 && USE_3DES */\n#ifdef USE_3DES\t\t/* Uses 3DES-encrypted keyring */\n\tcount = readFileFromTemplate( OPENPGP_PKE_FILE_TEMPLATE, 2, \n\t\t\t\t\t\t\t\t  \"OpenPGP (GPG)-encrypted data (AES)\", \n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_OPENPGP_HASH, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tcount = readFileFromTemplate( OPENPGP_PKE_FILE_TEMPLATE, 3, \n\t\t\t\t\t\t\t\t  \"OpenPGP (GPG)-encrypted data (AES+MDC)\", \n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_OPENPGP_HASH, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n#endif /* USE_3DES */\n#ifdef USE_BLOWFISH\t\t/* Uses Blowfish for encryption */\n\tcount = readFileFromTemplate( OPENPGP_PKE_FILE_TEMPLATE, 4, \n\t\t\t\t\t\t\t\t  \"OpenPGP (GPG)-encrypted data (Blowfish+MDC)\", \n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_OPENPGP_HASH, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n#endif /* USE_BLOWFISH */\n#ifdef USE_3DES\t\t/* Uses 3DES-encrypted keyring */\n\tcount = readFileFromTemplate( OPENPGP_PKE_FILE_TEMPLATE, 5, \n\t\t\t\t\t\t\t\t  \"OpenPGP (GPG)-encrypted data (partial lengths)\", \n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopePKCDecrypt( globalBuffer, count, KEYFILE_OPENPGP_PARTIAL, \n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeDecompress( globalBuffer, BUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( resume )\n#endif /* IBM big iron */\n\tif( count < 600 || \\\n\t\t!compareData( \"\\n\\n<sect>Vorwort\\n\", 16, globalBuffer, 16 ) )\n\t\treturn( FALSE );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#endif /* USE_3DES */\n\tfputs( \"Import of OpenPGP-encrypted data succeeded.\\n\\n\", \n\t\t   outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import PGP 2.x and OpenPGP-generated signed data */\n\nint testPGPEnvelopeSignedDataImport( void )\n\t{\n\tCRYPT_CONTEXT hashContext;\n\tint count, status;\n\n\t/* Process the PGP 2.x signed data.  Create with:\n\n\t\tpgp -s +secring=\"secring.pgp\" +pubring=\"pubring.pgp\" -u test test.txt */\n#ifdef USE_PGP2\n\tcount = readFileFromTemplate( PGP_SIG_FILE_TEMPLATE, 1, \n\t\t\t\t\t\t\t\t  \"PGP-signed data\", globalBuffer,\n\t\t\t\t\t\t\t\t  BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, KEYFILE_PGP, FALSE, \n\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tfputs( \"Import of PGP-signed data succeeded.\\n\\n\", outputStream );\n#endif /* USE_PGP2 */\n\n#if 0\t/* Disabled because it uses a 512-bit sig and there doesn't appear to\n\t\t   be any way to create a new file in this format */\n\t/* Process the OpenPGP (actually a weird 2.x/OpenPGP hybrid produced by\n\t   PGP 5.0) signed data.  In theory this could be created with:\n\n\t\tpgpo -s +secring=\"secring.pgp\" +pubring=\"pubring.pgp\" +compress=off -o signed2.pgp -u test test.txt\n\t\n\t   but the exact details of how to create this packet are a mystery, it \n\t   starts with a marker packet and then a one-pass sig, which isn't \n\t   generated by default by any of the PGP 5.x or 6.x versions */\n\tcount = readFileFromTemplate( PGP_SIG_FILE_TEMPLATE, 2, \n\t\t\t\t\t\t\t\t  \"PGP 2.x/OpenPGP-hybrid-signed data\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, TRUE, FALSE, FALSE,\n\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tfputs( \"Import of PGP 2.x/OpenPGP-hybrid-signed data succeeded.\\n\\n\", \n\t\t   outputStream );\n#endif /* 0 */\n\n\t/* Process the OpenPGP signed data: DSA with SHA1.  Create with:\n\n\t\tcp sec_hash.gpg secring.gpg\n\t\tcp pub_hash.gpg pubring.gpg\n\t\tgpg -s -z 0 --homedir . -o signed3.pgp test.txt \n\t\trm secring.gpg pubring.gpg */\n\tcount = readFileFromTemplate( PGP_SIG_FILE_TEMPLATE, 3, \n\t\t\t\t\t\t\t\t  \"OpenPGP-signed data\",\n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, KEYFILE_OPENPGP_HASH, FALSE, \n\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tif( !compareData( ENVELOPE_PGP_TESTDATA, ENVELOPE_TESTDATA_SIZE, \n\t\t\t\t\t  globalBuffer, count ) )\n\t\treturn( FALSE );\n\tfputs( \"Import of OpenPGP-signed data succeeded.\\n\\n\", outputStream );\n\n\t/* Process the OpenPGP detached signed data.  Create with:\n\n\t\tcp sec_hash.gpg secring.gpg\n\t\tcp pub_hash.gpg pubring.gpg\n\t\tgpg -b -z 0 --openpgp --homedir . -o signed4.pgp test.txt\n\t\trm secring.gpg pubring.gpg \n\n\t   (the --openpgp is for another GPG bug, without it it'll generate\n\t   v3 sigs as if --force-v3-sigs had been specified).  The data is \n\t   provided externally so we have to hash it ourselves.  Since PGP \n\t   hashes further data after hashing the content, we can't complete \n\t   the hashing but have to use the partially-completed hash */\n\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptEncrypt( hashContext, ENVELOPE_PGP_TESTDATA,\n\t\t\t\t\t\t\t   ENVELOPE_TESTDATA_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"Couldn't create external hash of data.\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tcount = readFileFromTemplate( PGP_SIG_FILE_TEMPLATE, 4, \n\t\t\t\t\t\t\t\t  \"OpenPGP-signed data with externally-supplied hash\", \n\t\t\t\t\t\t\t\t  globalBuffer, BUFFER_SIZE );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tcount = envelopeSigCheck( globalBuffer, count, hashContext,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, KEYFILE_OPENPGP_HASH, TRUE,\n\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP );\n\tcryptDestroyContext( hashContext );\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\tfputs( \"Import of OpenPGP-signed data with externally-supplied hash \"\n\t\t   \"succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Import PGP 2.x and OpenPGP-generated compressed data */\n\nint testPGPEnvelopeCompressedDataImport( void )\n\t{\n\tBYTE *bufPtr;\n\tint count;\n\n\t/* Since this needs a nontrivial amount of data for the compression, we\n\t   use a dynamically-allocated buffer */\n\tif( ( bufPtr = malloc( FILEBUFFER_SIZE ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't allocate test buffer.\\n\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Process the PGP 2.x compressed data */\n\tcount = readFileFromTemplate( PGP_COPR_FILE_TEMPLATE, 1, \n\t\t\t\t\t\t\t\t  \"PGP 2.x compressed data\",\n\t\t\t\t\t\t\t\t  bufPtr, FILEBUFFER_SIZE );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tcount = envelopeDecompress( bufPtr, FILEBUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( !compareData( bufPtr, ENVELOPE_COMPRESSEDDATA_SIZE, \n\t\t\t\t\t  ENVELOPE_COMPRESSEDDATA, \n\t\t\t\t\t  ENVELOPE_COMPRESSEDDATA_SIZE ) )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Import of PGP 2.x compressed data succeeded.\\n\\n\", \n\t\t   outputStream );\n\n\t/* Process the OpenPGP compressed nested data.  GPG is weird in that \n\t   instead of signing compressed data it first creates the signature\n\t   and then compresses that, so that the result isn't { one-pass sig,\n\t   copr.data, signature } but { copr.data { one-pass sig, data, \n\t   signature } }.  Create with:\n\n\t\tcp sec_hash.gpg secring.gpg\n\t\tcp pub_hash.gpg pubring.gpg\n\t\tgpg -s --openpgp --homedir . -o copr2.pgp test.c\n\t\trm secring.gpg pubring.gpg\n\t\n\t   with the same note as before for GPG bugs and --openpgp */\n\tcount = readFileFromTemplate( PGP_COPR_FILE_TEMPLATE, 2, \n\t\t\t\t\t\t\t\t  \"OpenPGP compressed signed data\",\n\t\t\t\t\t\t\t\t  bufPtr, FILEBUFFER_SIZE );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tcount = envelopeDecompress( bufPtr, FILEBUFFER_SIZE, count );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( !compareData( \"\\x90\\x0D\\x03\\x00\", 4, bufPtr, 4 ) )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tmemcpy( globalBuffer, bufPtr, count );\n\tdebugDump( \"decopr_sig.pgp\", globalBuffer, count );\n\tcount = envelopeSigCheck( globalBuffer, count, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_UNUSED, KEYFILE_OPENPGP_HASH, FALSE,\n\t\t\t\t\t\t\t  CRYPT_FORMAT_PGP );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tif( !compareData( ENVELOPE_COMPRESSEDDATA, ENVELOPE_COMPRESSEDDATA_SIZE, \n\t\t\t\t\t  globalBuffer, ENVELOPE_COMPRESSEDDATA_SIZE ) )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Import of OpenPGP compressed signed data succeeded.\\n\\n\", \n\t\t   outputStream );\n\n\t/* Process booby-traped compressed data import.  This is a PGP quine \n\t   which decompresses to itself, which crashes some PGP implementations, \n\t   see https://nvd.nist.gov/vuln/detail/CVE-2013-4402 for a discussion \n\t   and http://mumble.net/%7Ecampbell/misc/pgp-quine/ for the data.\n\t   This doesn't affect cryptlib since it only removes one layer at a \n\t   time, but we test it anyway just to show it's not affected.\n\t   \n\t   Since this is custom-generated malformed data, there's a spurious\n\t   byte at the end so we end up with a CRYPT_ERROR_INCOMPLETE when we \n\t   try and destroy the envelope, this is expected behaviour */\n\tcount = readFileFromTemplate( PGP_COPR_FILE_TEMPLATE, 3, \n\t\t\t\t\t\t\t\t  \"PGP quine compressed data\", \n\t\t\t\t\t\t\t\t  bufPtr, FILEBUFFER_SIZE );\n\tif( count <= 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\treturn( FALSE );\n\t\t}\n\tcount = envelopeDecompress( bufPtr, FILEBUFFER_SIZE, count );\n\tif( count > 0 )\n\t\t{\n\t\tfree( bufPtr );\n\t\tfputs( \"Import of PGP quine succeeded, should have failed.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tfree( bufPtr );\n\tfputs( \"  (This is an expected result from importing invalid data).\\n\", \n\t\t   outputStream );\n\tfputs( \"Import of PGP quine compressed data succeeded.\\n\\n\", \n\t\t   outputStream );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tDebugging Data Import Routines \t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generic test routines used for debugging.  These are only meant to be\n   used interactively, and throw exceptions rather than returning status\n   values */\n\nstatic void dataImport( void *buffer, const int length, \n\t\t\t\t\t\tconst BOOLEAN resultBad )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tint count, status;\n\n\tstatus = createDeenvelope( &cryptEnvelope );\n\tassert( status == TRUE );\n\tcount = pushData( cryptEnvelope, buffer, length, NULL, 0 );\n\tif( resultBad )\n\t\t{\n\t\tassert( cryptStatusError( count ) );\n\t\treturn;\n\t\t}\n\tassert( !cryptStatusError( count ) );\n\tcount = popData( cryptEnvelope, buffer, length );\n\tassert( !cryptStatusError( count ) );\n\tstatus = destroyEnvelope( cryptEnvelope );\n\tassert( status == TRUE );\n\t}\n\nvoid xxxDataImport( const char *fileName )\n\t{\n\tBYTE *bufPtr = globalBuffer;\n\tint count;\n\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE && \\\n\t\t( bufPtr = malloc( count ) ) == NULL )\n\t\t{\n\t\tassert( 0 );\n\t\treturn;\n\t\t}\n\tcount = readFileData( fileName, \"Generic test data\", bufPtr, count, 32,\n\t\t\t\t\t\t  FALSE );\n\tassert( count > 0 );\n\tdataImport( bufPtr, count, FALSE );\n\tif( bufPtr != globalBuffer )\n\t\tfree( bufPtr );\n\t}\n\nstatic void signedDataImport( const BYTE *data, const int length )\n\t{\n\tint status;\n\n\tstatus = cmsEnvelopeSigCheck( data, length, CRYPT_UNUSED, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE );\n\tassert( status > 0 );\n\t}\n\nvoid xxxSignedDataImport( const char *fileName )\n\t{\n\tBYTE *bufPtr = globalBuffer;\n\tint count;\n\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE && \\\n\t\t( bufPtr = malloc( count ) ) == NULL )\n\t\t{\n\t\tassert( 0 );\n\t\treturn;\n\t\t}\n\tcount = readFileData( fileName, \"S/MIME test data\", bufPtr, count, 64,\n\t\t\t\t\t\t  FALSE );\n\tassert( count > 0 );\n\tsignedDataImport( bufPtr, count );\n\tif( bufPtr != globalBuffer )\n\t\tfree( bufPtr );\n\t}\n\nstatic void encryptedDataImport( const BYTE *data, const int length,\n\t\t\t\t\t\t\t\t const char *keyset, const char *password )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keyset, CRYPT_KEYOPT_READONLY );\n\tassert( cryptStatusOK( status ) );\n\tstatus = cmsEnvelopeDecrypt( data, length, cryptKeyset, password, FALSE );\n\tassert( status > 0 );\n\tcryptKeysetClose( cryptKeyset );\n\t}\n\nvoid xxxEncryptedDataImport( const char *fileName, const char *keyset,\n\t\t\t\t\t\t\t const char *password )\n\t{\n\tBYTE *buffer = globalBuffer;\n\tint count;\n\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE )\n\t\t{\n\t\tbuffer = malloc( count );\n\t\tassert( buffer != NULL );\n\t\t}\n\tcount = readFileData( fileName, \"S/MIME test data\", buffer, 32,\n\t\t\t\t\t\t  count, FALSE );\n\tassert( count > 0 );\n\tencryptedDataImport( buffer, count, keyset, password );\n\tif( buffer != globalBuffer )\n\t\tfree( buffer );\n\t}\n\nvoid xxxSignedEncryptedDataImport( const char *fileName, const char *keyset,\n\t\t\t\t\t\t\t\t   const char *password )\n\t{\n\tBYTE *bufPtr = globalBuffer;\n\tint count;\n\n\tcount = getFileSize( fileName ) + 10;\n\tif( count >= BUFFER_SIZE && \\\n\t\t( bufPtr = malloc( count ) ) == NULL )\n\t\t{\n\t\tassert( 0 );\n\t\treturn;\n\t\t}\n\tcount = readFileData( fileName, \"S/MIME test data\", bufPtr, count, 64,\n\t\t\t\t\t\t  FALSE );\n\tassert( count > 0 );\n\tsignedDataImport( bufPtr, count );\n\tencryptedDataImport( bufPtr, count, keyset, password );\n\tif( bufPtr != globalBuffer )\n\t\tfree( bufPtr );\n\t}\n\nvoid xxxEnvelopeTest( const char *certFileName, const char *outFile )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tint status;\n\n\tstatus = importCertFile( &cryptCert, certFileName );\n\tassert( cryptStatusOK( status ) );\n\tstatus = envelopePKCCrypt( outFile, TRUE, KEYFILE_NONE, FALSE,\n\t\t\t\t\t\t\t   FALSE, FALSE, TRUE, CRYPT_FORMAT_CMS, \n\t\t\t\t\t\t\t   cryptCert, 0 );\n\tassert( status > 0 );\n\t}\n#endif /* TEST_ENVELOPE || TEST_SESSION */\n"
  },
  {
    "path": "deps/cl345/test/filename.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Test Data Filenames\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2014\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The names of the test key and certificate files.  For flat filesystems we\n   give the test files names starting with 'z' so they're easier to find */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tAS/400\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __OS400__ )\n\n#define TEST_PRIVKEY_FILE\t\t\t\"testlib/zkeytest\"\n#define TEST_PRIVKEY_TMP_FILE\t\t\"testlib/zkeytstt\"\n#define TEST_PRIVKEY_ALT_FILE\t\t\"testlib/zkeytsta\"\n#define TEST_PRIVKEY_PGP_FILE\t\t\"testlib/zkeytstp\"\n#define CA_PRIVKEY_FILE\t\t\t\t\"testlib/zkeyca\"\n#define ICA_PRIVKEY_FILE\t\t\t\"testlib/zkeycai\"\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE \"testlib/zkeycs%d\"\n#define USER_PRIVKEY_FILE\t\t\t\"testlib/zkeyuse1\"\n#define USER_PRIVKEY_FILE_TEMPLATE\t\"testlib/zkeyuse%d\"\n#define DUAL_PRIVKEY_FILE\t\t\t\"testlib/zkeydual\"\n#define RENEW_PRIVKEY_FILE\t\t\t\"testlib/zkeyrene\"\n#define P15_FILE_TEMPLATE\t\t\t\"testlib/zkeyp15%d\"\n#define CMP_PRIVKEY_FILE_TEMPLATE\t\"testlib/zkeycmp\"\n#define PNP_PRIVKEY_FILE\t\t\t\"testlib/zkeypnpu\"\n#define PNPCA_PRIVKEY_FILE\t\t\t\"testlib/zkeypnpc\"\n#define SERVER_PRIVKEY_FILE_TEMPLATE \"testlib/zkeysrv%d\"\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE \"testlib/zkeysrp%d\"\n#define SSH_PRIVKEY_FILE_TEMPLATE\t\"testlib/zkeyssh%d\"\n#define SSL_CLI_PRIVKEY_FILE\t\t\"testlib/zkeysslc\"\n#define TSA_PRIVKEY_FILE\t\t\t\"testlib/zkeytsa\"\n#define MISC_PRIVKEY_FILE_TEMPLATE\t\"testlib/zkeymis%d\"\n#define PKCS12_FILE_TEMPLATE\t\t\"testlib/zkeyp12%d\"\n#define PSEUDOCERT_FILE_TEMPLATE\t\"testlib/zpseudo%d\"\n\n#define PGP_PUBKEY_FILE\t\t\t\t\"testlib/zpubring\"\n#define PGP_PRIVKEY_FILE\t\t\t\"testlib/zsecring\"\n#define OPENPGP_PUBKEY_FILE\t\t\t\"testlib/zpubringg\"\n#define OPENPGP_PRIVKEY_HASH_FILE\t\"testlib/zsechash\"\n#define OPENPGP_PUBKEY_AES_FILE\t\t\"testlib/zpubaes\"\n#define OPENPGP_PRIVKEY_AES_FILE\t\"testlib/zsecaes\"\n#define OPENPGP_PRIVKEY_CAST_FILE\t\"testlib/zseccast\"\n#define OPENPGP_PUBKEY_RSA_FILE\t\t\"testlib/zpubrsa\"\n#define OPENPGP_PRIVKEY_RSA_FILE\t\"testlib/zsecrsa\"\n#define OPENPGP_PRIVKEY_PART_FILE\t\"testlib/zsecpart\"\n#define OPENPGP_PRIVKEY_BC_FILE\t\t\"testlib/zsecbc\"\n#define OPENPGP_PUBKEY_ECC_FILE\t\t\"testlib/zpubecc\"\n#define OPENPGP_PRIVKEY_ECC_FILE\t\"testlib/zsececc\"\n#define OPENPGP_PUBKEY_MULT_FILE\t\"testlib/zpubmult\"\n#define NAIPGP_PUBKEY_FILE\t\t\t\"testlib/zpubnai\"\n#define NAIPGP_PRIVKEY_FILE\t\t\t\"testlib/zsecnai\"\n\n#define CERT_FILE_TEMPLATE\t\t\t\"testlib/zcert%02d\"\n#define BASE64CERT_FILE_TEMPLATE\t\"testlib/zcerta%d\"\n#define ECC_CERT_FILE_TEMPLATE\t\t\"testlib/zeccert%02d\"\n#define BROKEN_CERT_FILE\t\t\t\"testlib/zcertb\"\n#define BROKEN_USER_CERT_FILE\t\t\"testlib/zcertbus\"\n#define BROKEN_CA_CERT_FILE\t\t\t\"testlib/zcertbca\"\n#define CERTREQ_FILE_TEMPLATE\t\t\"testlib/zcertreq%d\"\n#define CRL_FILE_TEMPLATE\t\t\t\"testlib/zcrl%d\"\n#define CERTCHAIN_FILE_TEMPLATE\t\t\"testlib/zcertchn%d\"\n#define BASE64CERTCHAIN_FILE_TEMPLATE \"testlib/zcertcha%d\"\n#define CHAINTEST_FILE_TEMPLATE\t\t\"testlib/zctest%d\"\n#define PATHTEST_FILE_TEMPLATE\t\t\"testlib/zntest%d\"\n#define PADTEST_FILE_TEMPLATE\t\t\"testlib/zbadsig%d\"\n#define SSHKEY_FILE_TEMPLATE\t\t\"testlib/zsshkey%d\"\n#define PGPKEY_FILE_TEMPLATE\t\t\"testlib/zpgpkey%d\"\n#define PGPASCKEY_FILE_TEMPLATE\t\t\"testlib/zpgpkea%d\"\n#define NOCHAIN_EE_FILE\t\t\t\t\"testlib/znochn_ee\"\n#define NOCHAIN_CA_FILE\t\t\t\t\"testlib/znochn_ca\"\n#define RTCS_OK_FILE\t\t\t\t\"testlib/zrtcsok\"\n#define OCSP_OK_FILE\t\t\t\t\"testlib/zocsprok\"\n#define OCSP_REV_FILE\t\t\t\t\"testlib/zocsprre\"\n#define OCSP_CA_FILE\t\t\t\t\"testlib/zocspca\"\n#define CRLCERT_FILE_TEMPLATE\t\t\"testlib/zcrlcrt%d\"\n#define RTCS_FILE_TEMPLATE\t\t\t\"testlib/zrtcsee%do\"\n#define OCSP_CA_FILE_TEMPLATE\t\t\"testlib/zocspca%d\"\n#define OCSP_EEOK_FILE_TEMPLATE\t\t\"testlib/zocspok%d\"\n#define OCSP_EEREV_FILE_TEMPLATE\t\"testlib/zocspre%d\"\n#define CMP_CA_FILE_TEMPLATE\t\t\"testlib/zcmpca%d\"\n#define SCEP_CA_FILE_TEMPLATE\t\t\"testlib/zscepca%d\"\n\n#define CMS_ENC_FILE_TEMPLATE\t\t\"testlib/zspwenc%d\"\n#define SMIME_SIG_FILE_TEMPLATE\t\t\"testlib/zsigned%d\"\n#define SMIME_SIG_FILE_INDEF\t\t\"testlib/zsigndef\"\n#define SMIME_ENV_FILE_TEMPLATE\t\t\"testlib/zsenvel%d\"\n#define PGP_ENC_FILE_TEMPLATE\t\t\"testlib/zconven%d\"\n#define PGP_PKE_FILE_TEMPLATE\t\t\"testlib/zpgpenc%d\"\n#define OPENPGP_PKE_FILE_TEMPLATE\t\"testlib/zgpgenc%d\"\n#define PGP_SIG_FILE_TEMPLATE\t\t\"testlib/zsigned%d\"\n#define PGP_COPR_FILE_TEMPLATE\t\t\"testlib/zcopr%d\"\n\n#define TESTDATA_FILE_TEMPLATE\t\t\"testlib/ztestd%d\"\n#define COMPRESS_FILE\t\t\t\t\"test/filename\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMacintosh pre-OS X\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __MWERKS__ ) || defined( SYMANTEC_C ) || defined( __MRC__ )\n\n#define TEST_PRIVKEY_FILE\t\t\t\":test:keys:test.p15\"\n#define TEST_PRIVKEY_TMP_FILE\t\t\":test:keys:test_tmp.p15\"\n#define TEST_PRIVKEY_ALT_FILE\t\t\":test:keys:test.p12\"\n#define TEST_PRIVKEY_PGP_FILE\t\t\":test:keys:test.pgp\"\n#define CA_PRIVKEY_FILE\t\t\t\t\":test:keys:ca.p15\"\n#define ICA_PRIVKEY_FILE\t\t\t\":test:keys:ca_int.p15\"\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE \":test:keys:scep_ca%d.p15\"\n#define USER_PRIVKEY_FILE\t\t\t\":test:keys:user1.p15\"\n#define USER_PRIVKEY_FILE_TEMPLATE\t\":test:keys:user%d.p15\"\n#define DUAL_PRIVKEY_FILE\t\t\t\":test:keys:dual.p15\"\n#define RENEW_PRIVKEY_FILE\t\t\t\":test:keys:renewed.p15\"\n#define P15_FILE_TEMPLATE\t\t\t\":test:keys:pkcs15_%d.p15\"\n#define CMP_PRIVKEY_FILE_TEMPLATE\t\":test:keys:cmp%d.p15\"\n#define PNP_PRIVKEY_FILE\t\t\t\":test:keys:pnp_user.p15\"\n#define PNPCA_PRIVKEY_FILE\t\t\t\":test:keys:pnp_ca.p15\"\n#define SERVER_PRIVKEY_FILE_TEMPLATE \":test:keys:server%d.p15\"\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE \":test:keys:serverp%d.p15\"\n#define SSH_PRIVKEY_FILE_TEMPLATE\t\":test:keys:ssh%d.p15\"\n#define SSL_CLI_PRIVKEY_FILE\t\t\":test:keys:ssl_cli.p15\"\n#define TSA_PRIVKEY_FILE\t\t\t\":test:keys:tsa.p15\"\n#define MISC_PRIVKEY_FILE_TEMPLATE\t\":test:keys:misc%d.p15\"\n#define PKCS12_FILE_TEMPLATE\t\t\":test:keys:pkcs12_%d.p12\"\n#define PSEUDOCERT_FILE_TEMPLATE\t\":test:keys:pseudocrt%d.dat\"\n\n#define PGP_PUBKEY_FILE\t\t\t\t\":test:pgp:pubring.pgp\"\n#define PGP_PRIVKEY_FILE\t\t\t\":test:pgp:secring.pgp\"\n#define OPENPGP_PUBKEY_HASH_FILE\t\":test:pgp:pub_hash.gpg\"\n#define OPENPGP_PRIVKEY_HASH_FILE\t\":test:pgp:sec_hash.gpg\"\n#define OPENPGP_PUBKEY_AES_FILE\t\t\":test:pgp:pub_aes.pkr\"\n#define OPENPGP_PRIVKEY_AES_FILE\t\":test:pgp:sec_aes.skr\"\n#define OPENPGP_PRIVKEY_CAST_FILE\t\":test:pgp:sec_cast.gpg\"\n#define OPENPGP_PUBKEY_RSA_FILE\t\t\":test:pgp:pub_rsa.gpg\"\n#define OPENPGP_PRIVKEY_RSA_FILE\t\":test:pgp:sec_rsa.gpg\"\n#define OPENPGP_PRIVKEY_PART_FILE\t\":test:pgp:sec_part.gpg\"\n#define OPENPGP_PRIVKEY_BC_FILE\t\t\":test:pgp:sec_bc.gpg\"\n#define OPENPGP_PUBKEY_ECC_FILE\t\t\":test:pgp:pub_ecc.gpg\"\n#define OPENPGP_PRIVKEY_ECC_FILE\t\":test:pgp:sec_ecc.gpg\"\n#define OPENPGP_PUBKEY_MULT_FILE\t\":test:pgp:pub_mult.gpg\"\n#define NAIPGP_PUBKEY_FILE\t\t\t\":test:pgp:pub_nai.pkr\"\n#define NAIPGP_PRIVKEY_FILE\t\t\t\":test:pgp:sec_nai.skr\"\n\n#define CERT_FILE_TEMPLATE\t\t\t\":test:certs:cert%02d.der\"\n#define BASE64CERT_FILE_TEMPLATE\t\":test:certs:cert%d.asc\"\n#define ECC_CERT_FILE_TEMPLATE\t\t\":test:certs:eccert%02d.der\"\n#define BROKEN_CERT_FILE\t\t\t\":test:certs:broken.der\"\n#define BROKEN_USER_CERT_FILE\t\t\":test:certs:broken_ee.der\"\n#define BROKEN_CA_CERT_FILE\t\t\t\":test:certs:broken_ca.der\"\n#define CERTREQ_FILE_TEMPLATE\t\t\":test:certs:certreq%d.der\"\n#define CRL_FILE_TEMPLATE\t\t\t\":test:certs:crl%d.crl\"\n#define CERTCHAIN_FILE_TEMPLATE\t\t\":test:certs:certchn%d.der\"\n#define BASE64CERTCHAIN_FILE_TEMPLATE \":test:certs:certchn%d.asc\"\n#define CHAINTEST_FILE_TEMPLATE\t\t\":test:certs:chntest%d.der\"\n#define PATHTEST_FILE_TEMPLATE\t\t\":test:nist:ntest%d.p7s\"\n#define PADTEST_FILE_TEMPLATE\t\t\":test:certs:badsig%d.der\"\n#define SSHKEY_FILE_TEMPLATE\t\t\":test:misc:sshkey%d.asc\"\n#define PGPKEY_FILE_TEMPLATE\t\t\":test:pgp:pubkey%d.pgp\"\n#define PGPASCKEY_FILE_TEMPLATE\t\t\":test:pgp:pubkey%d.asc\"\n#define NOCHAIN_EE_FILE\t\t\t\t\":test:misc:nochn_ee.der\"\n#define NOCHAIN_CA_FILE\t\t\t\t\":test:misc:nochn_ca.der\"\n#define RTCS_OK_FILE\t\t\t\t\":test:misc:rtcsrok.der\"\n#define OCSP_OK_FILE\t\t\t\t\":test:session:ocspr_ok.der\"\n#define OCSP_REV_FILE\t\t\t\t\":test:session:ocspr_re.der\"\n#define OCSP_CA_FILE\t\t\t\t\":test:session:ocspca.der\"\n#define CRLCERT_FILE_TEMPLATE\t\t\":test:misc:crl_cert%d.der\"\n#define RTCS_FILE_TEMPLATE\t\t\t\":test:misc:rtcs_ee%do.der\"\n#define OCSP_CA_FILE_TEMPLATE\t\t\":test:session:ocsp_ca%d.der\"\n#define OCSP_EEOK_FILE_TEMPLATE\t\t\":test:session:ocsp_ok%d.der\"\n#define OCSP_EEREV_FILE_TEMPLATE\t\":test:session:ocsp_re%d.der\"\n#define CMP_CA_FILE_TEMPLATE\t\t\":test:session:cmp_cacert%d.der\"\n#define SCEP_CA_FILE_TEMPLATE\t\t\":test:session:scep_cacert%d.der\"\n\n#define CMS_ENC_FILE_TEMPLATE\t\t\":test:smime:pwenc%d.p7m\"\n#define SMIME_SIG_FILE_TEMPLATE\t\t\":test:smime:signed%d.p7s\"\n#define SMIME_SIG_FILE_INDEF\t\t\":test:smime:signdef.p7s\"\n#define SMIME_ENV_FILE_TEMPLATE\t\t\":test:smime:envel%d.p7m\"\n#define PGP_ENC_FILE_TEMPLATE\t\t\":test:pgp:conv_enc%d.pgp\"\n#define PGP_PKE_FILE_TEMPLATE\t\t\":test:pgp:pgp_enc%d.pgp\"\n#define OPENPGP_PKE_FILE_TEMPLATE\t\":test:pgp:gpg_enc%d.gpg\"\n#define PGP_SIG_FILE_TEMPLATE\t\t\":test:pgp:signed%d.pgp\"\n#define PGP_COPR_FILE_TEMPLATE\t\t\":test:pgp:copr%d.pgp\"\n\n#define TESTDATA_FILE_TEMPLATE\t\t\":test:misc:testdata%d.dat\"\n#define COMPRESS_FILE\t\t\t\t\":test:filename.h\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMVS with DDNAME I/O\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( DDNAME_IO )\n\n#define TEST_PRIVKEY_FILE\t\t\t\"DD:CLBTEST\"\n#define TEST_PRIVKEY_TMP_FILE\t\t\"DD:CLBTESTT\"\n#define TEST_PRIVKEY_ALT_FILE\t\t\"DD:CLBTESTA\"\n#define TEST_PRIVKEY_PGP_FILE\t\t\"DD:CLBTESTP\"\n#define CA_PRIVKEY_FILE\t\t\t\t\"DD:CLBP15(KEYCA)\"\n#define ICA_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYCAI)\"\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE \"DD:CLBP15(KEYCAS%d)\"\n#define USER_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYUSER1)\"\n#define USER_PRIVKEY_FILE_TEMPLATE\t\"DD:CLBP15(KEYUSE%d)\"\n#define DUAL_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYDUAL)\"\n#define RENEW_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYRENE)\"\n#define P15_FILE_TEMPLATE\t\t\t\"DD:CLBP15(KEYP15%d)\"\n#define CMP_PRIVKEY_FILE_TEMPLATE\t\"DD:CLBP15(KEYCMP%d)\"\n#define PNP_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYPNPU)\"\n#define PNPCA_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYPNPC)\"\n#define SERVER_PRIVKEY_FILE_TEMPLATE \"DD:CLBP15(KEYSRV%d)\"\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE \"DD:CLBP15(KEYSRP%d)\"\n#define SSH_PRIVKEY_FILE_TEMPLATE\t\"DD:CLBP15(KEYSSH%d)\"\n#define SSL_CLI_PRIVKEY_FILE\t\t\"DD:CLBP15(KEYSSLC)\"\n#define TSA_PRIVKEY_FILE\t\t\t\"DD:CLBP15(KEYTSA)\"\n#define MISC_PRIVKEY_FILE_TEMPLATE\t\"DD:CLBP15(KEYMIS%d)\"\n#define PKCS12_FILE_TEMPLATE\t\t\"DD:CLBP12(KEYP12%d)\"\n#define PSEUDOCERT_FILE_TEMPLATE\t\"DD:CLBPCR(CRT%d)\"\n\n#define PGP_PUBKEY_FILE\t\t\t\t\"DD:CLBPGP(PUBRING)\"\n#define PGP_PRIVKEY_FILE\t\t\t\"DD:CLBPGP(SECRING)\"\n#define OPENPGP_PUBKEY_HASH_FILE\t\"DD:CLBGPG(PUBHASH)\"\n#define OPENPGP_PRIVKEY_HASH_FILE\t\"DD:CLBGPG(SECHASH)\"\n#define OPENPGP_PUBKEY_AES_FILE\t\t\"DD:CLBPKR(PUBAES)\"\n#define OPENPGP_PRIVKEY_AES_FILE\t\"DD:CLBSKR(SECAES)\"\n#define OPENPGP_PRIVKEY_CAST_FILE\t\"DD:CLBSKR(SECCAS)\"\n#define OPENPGP_PUBKEY_RSA_FILE\t\t\"DD:CLBGPG(PUBRSA)\"\n#define OPENPGP_PRIVKEY_RSA_FILE\t\"DD:CLBGPG(SECRSA)\"\n#define OPENPGP_PRIVKEY_PART_FILE\t\"DD:CLBGPG(SECPART)\"\n#define OPENPGP_PRIVKEY_BC_FILE\t\t\"DD:CLBGPG(SECBC)\"\n#define OPENPGP_PUBKEY_ECC_FILE\t\t\"DD:CLBGPG(PUBECC)\"\n#define OPENPGP_PRIVKEY_ECC_FILE\t\"DD:CLBGPG(SECECC)\"\n#define OPENPGP_PUBKEY_MULT_FILE\t\"DD:CLBGPG(PUBMULT)\"\n#define NAIPGP_PUBKEY_FILE\t\t\t\"DD:CLBPKR(PUBNAI)\"\n#define NAIPGP_PRIVKEY_FILE\t\t\t\"DD:CLBSKR(SECNAI)\"\n\n#define CERT_FILE_TEMPLATE\t\t\t\"DD:CLBDER(CERT%02d)\"\n#define BASE64CERT_FILE_TEMPLATE\t\"DD:CLBDER(CERT%d)\"\n#define ECC_CERT_FILE_TEMPLATE\t\t\"DD:CLBDER(ECCERT%02d)\"\n#define BROKEN_CERT_FILE\t\t\t\"DD:CLBDER(CERTB)\"\n#define BROKEN_USER_CERT_FILE\t\t\"DD:CLBDER(CERTBUS)\"\n#define BROKEN_CA_CERT_FILE\t\t\t\"DD:CLBDER(CERTBCA)\"\n#define CERTREQ_FILE_TEMPLATE\t\t\"DD:CLBDER(CERTREQ%d)\"\n#define CRL_FILE_TEMPLATE\t\t\t\"DD:CLBDER(CRL%d)\"\n#define CERTCHAIN_FILE_TEMPLATE\t\t\"DD:CLBDER(CERTCHN%d)\"\n#define BASE64CERTCHAIN_FILE_TEMPLATE \"DD:CLBDER(CERT%d)\"\n#define CHAINTEST_FILE_TEMPLATE\t\t\"DD:CLBDER(CHNTEST%d)\"\n#define PATHTEST_FILE_TEMPLATE\t\t\"DD:CLBDER(NTEST%d)\"\n#define PADTEST_FILE_TEMPLATE\t\t\"DD:CLBDER(BADSIG%d)\"\n#define SSHKEY_FILE_TEMPLATE\t\t\"DD:CLBDER(SSHKEY%d)\"\n#define PGPKEY_FILE_TEMPLATE\t\t\"DD:CLBDER(PGPKEY%d)\"\n#define PGPASCKEY_FILE_TEMPLATE\t\t\"DD:CLBDER(PGPKEA%d)\"\n#define NOCHAIN_EE_FILE\t\t\t\t\"DD:CLBDER(NOCHNEE)\"\n#define NOCHAIN_CA_FILE\t\t\t\t\"DD:CLBDER(NOCHNCA)\"\n#define RTCS_OK_FILE\t\t\t\t\"DD:CLBDER(RTCSROK)\"\n#define OCSP_OK_FILE\t\t\t\t\"DD:CLBDER(OCSPROK)\"\n#define OCSP_REV_FILE\t\t\t\t\"DD:CLBDER(OCSPRRE)\"\n#define OCSP_CA_FILE\t\t\t\t\"DD:CLBDER(OCSPCA)\"\n#define CRLCERT_FILE_TEMPLATE\t\t\"DD:CLBDER(CRLCERT%d)\"\n#define RTCS_FILE_TEMPLATE\t\t\t\"DD:CLBDER(RTCSEE%dO)\"\n#define OCSP_CA_FILE_TEMPLATE\t\t\"DD:CLBDER(OCSPCA%d)\"\n#define OCSP_EEOK_FILE_TEMPLATE\t\t\"DD:CLBDER(OCSPOK%d)\"\n#define OCSP_EEREV_FILE_TEMPLATE\t\"DD:CLBDER(OCSPRE%d)\"\n#define CMP_CA_FILE_TEMPLATE\t\t\"DD:CLBDER(CMPCA%d)\"\n#define SCEP_CA_FILE_TEMPLATE\t\t\"DD:CLBDER(SCEPCA%d)\"\n\n#define CMS_ENC_FILE_TEMPLATE\t\t\"DD:CLBP7M(PWENC%d)\"\n#define SMIME_SIG_FILE_TEMPLATE\t\t\"DD:CLBP7S(SIGNED%d)\"\n#define SMIME_SIG_FILE_INDEF\t\t\"DD:CLBP7S(SIGNDEF)\"\n#define SMIME_ENV_FILE_TEMPLATE\t\t\"DD:CLBP7M(ENVEL%d)\"\n#define PGP_ENC_FILE_TEMPLATE\t\t\"DD:CLBPGP(CONVEN%d)\"\n#define PGP_PKE_FILE_TEMPLATE\t\t\"DD:CLBPGP(PGPENC%d)\"\n#define OPENPGP_PKE_FILE_TEMPLATE\t\"DD:CLBGPG(GPGENC%d)\"\n#define PGP_SIG_FILE_TEMPLATE\t\t\"DD:CLBPGP(SIGNED%d)\"\n#define PGP_COPR_FILE_TEMPLATE\t\t\"DD:CLBPGP(COPR%d)\"\n\n#define TESTDATA_FILE_TEMPLATE\t\t\"DD:CLBCMP(TESTD%d)\"\n#define COMPRESS_FILE\t\t\t\t\"DD:CLBCMP(FILENAME)\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tNucleus\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generic embedded system using the FAT filesystem */\n\n#elif defined (__Nucleus__)\n\n#define TEST_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\test.p15\" )\n#define TEST_PRIVKEY_TMP_FILE\t\tTEXT( \"c:\\\\test\\\\keys\\\\test_tmp.p15\" )\n#define TEST_PRIVKEY_ALT_FILE\t\tTEXT( \"c:\\\\test\\\\keys\\\\test.p12\" )\n#define TEST_PRIVKEY_PGP_FILE\t\tTEXT( \"c:\\\\test\\\\keys\\\\test.pgp\" )\n#define CA_PRIVKEY_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\ca.p15\" )\n#define ICA_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\ca_int.p15\" )\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE TEXT( \"c:\\\\test\\\\keys\\\\scep_ca%d.p15\" )\n#define USER_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\user1.p15\" )\n#define USER_PRIVKEY_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\keys\\\\user%d.p15\" )\n#define DUAL_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\dual.p15\" )\n#define RENEW_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\renewed.p15\" )\n#define P15_FILE_TEMPLATE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\pkcs15_%d.p15\" )\n#define CMP_PRIVKEY_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\keys\\\\cmp%d.p15\" )\n#define PNP_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\pnp_user.p15\" )\n#define PNPCA_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\pnp_ca.p15\" )\n#define SERVER_PRIVKEY_FILE_TEMPLATE TEXT( \"c:\\\\test\\\\keys\\\\server%d.p15\" )\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE TEXT( \"c:\\\\test\\\\keys\\\\serverp%d.p15\" )\n#define SSH_PRIVKEY_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\keys\\\\ssh%d.p15\" )\n#define SSL_CLI_PRIVKEY_FILE\t\tTEXT( \"c:\\\\test\\\\keys\\\\ssl_cli.p15\" )\n#define TSA_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\keys\\\\tsa.p15\" )\n#define MISC_PRIVKEY_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\keys\\\\misc%d.p15\" )\n#define PKCS12_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\keys\\\\pkcs12_%d.p12\" )\n#define PSEUDOCERT_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\keys\\\\pseudocrt%d.dat\" )\n\n#define PGP_PUBKEY_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pubring.pgp\" )\n#define PGP_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\pgp\\\\secring.pgp\" )\n#define OPENPGP_PUBKEY_HASH_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\pub_hash.gpg\" )\n#define OPENPGP_PRIVKEY_HASH_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_hash.gpg\" )\n#define OPENPGP_PUBKEY_AES_FILE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pub_aes.pkr\" )\n#define OPENPGP_PRIVKEY_AES_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_aes.skr\" )\n#define OPENPGP_PUBKEY_RSA_FILE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pub_rsa.gpg\" )\n#define OPENPGP_PRIVKEY_RSA_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_rsa.gpg\" )\n#define OPENPGP_PRIVKEY_PART_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_part.gpg\" )\n#define OPENPGP_PRIVKEY_BC_FILE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_bc.gpg\" )\n#define OPENPGP_PUBKEY_ECC_FILE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pub_ecc.gpg\" )\n#define OPENPGP_PRIVKEY_ECC_FILE\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_ecc.gpg\" )\n#define NAIPGP_PUBKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pub_nai.pkr\" )\n#define NAIPGP_PRIVKEY_FILE\t\t\tTEXT( \"c:\\\\test\\\\pgp\\\\sec_nai.skr\" )\n\n#define CERT_FILE_TEMPLATE\t\t\tTEXT( \"c:\\\\test\\\\certs\\\\cert%02d.der\" )\n#define BASE64CERT_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\certs\\\\cert%d.asc\" )\n#define ECC_CERT_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\certs\\\\eccert%02d.der\" )\n#define BROKEN_CERT_FILE\t\t\tTEXT( \"c:\\\\test\\\\certs\\\\broken.der\" )\n#define BROKEN_USER_CERT_FILE\t\tTEXT( \"c:\\\\test\\\\certs\\\\broken_ee.der\" )\n#define BROKEN_CA_CERT_FILE\t\t\tTEXT( \"c:\\\\test\\\\certs\\\\broken_ca.der\" )\n#define CERTREQ_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\certs\\\\certreq%d.der\" )\n#define CRL_FILE_TEMPLATE\t\t\tTEXT( \"c:\\\\test\\\\certs\\\\crl%d.crl\" )\n#define CERTCHAIN_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\certs\\\\certchn%d.der\" )\n#define BASE64CERTCHAIN_FILE_TEMPLATE TEXT( \"c:\\\\test\\\\certs\\\\certchn%d.asc\" )\n#define CHAINTEST_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\certs\\\\chntest%d.der\" )\n#define PATHTEST_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\nist\\\\test%d.p7s\" )\n#define PADTEST_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\certs\\\\bad_sig%d.der\" )\n#define SSHKEY_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\misc\\\\sshkey%d.asc\" )\n#define PGPKEY_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pubkey%d.pgp\" )\n#define PGPASCKEY_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pubkey%d.asc\" )\n#define NOCHAIN_EE_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\misc\\\\nochn_ee.der\" )\n#define NOCHAIN_CA_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\misc\\\\nochn_ca.der\" )\n#define RTCS_OK_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\misc\\\\rtcsrok.der\" )\n#define OCSP_OK_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\session\\\\ocspr_ok.der\" )\n#define OCSP_REV_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\session\\\\ocspr_re.der\" )\n#define OCSP_CA_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\session\\\\ocspca.der\" )\n#define CRLCERT_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\misc\\\\crl_cert%d.der\" )\n#define RTCS_FILE_TEMPLATE\t\t\tTEXT( \"c:\\\\test\\\\misc\\\\rtcs_ee%do.der\" )\n#define OCSP_CA_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\session\\\\ocsp_ca%d.der\" )\n#define OCSP_EEOK_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\session\\\\ocsp_ok%d.der\" )\n#define OCSP_EEREV_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\session\\\\ocsp_re%d.der\" )\n#define CMP_CA_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\session\\\\cmp_ca%d.der\" )\n#define SCEP_CA_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\session\\\\scep_cacert%d.der\" )\n\n#define CMS_ENC_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\smime\\\\pw_enc%d.p7m\" )\n#define SMIME_SIG_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\smime\\\\signed%d.p7s\" )\n#define SMIME_SIG_FILE_INDEF\t\tTEXT( \"c:\\\\test\\\\smime\\\\sig_ndef.p7s\" )\n#define SMIME_ENV_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\smime\\\\envel%d.p7m\" )\n#define PGP_ENC_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\conv_enc%d.pgp\" )\n#define PGP_PKE_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\pgp_enc%d.pgp\" )\n#define OPENPGP_PKE_FILE_TEMPLATE\tTEXT( \"c:\\\\test\\\\pgp\\\\gpg_enc%d.gpg\" )\n#define PGP_SIG_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\signed%d.pgp\" )\n#define PGP_COPR_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\pgp\\\\copr%d.pgp\" )\n\n#define TESTDATA_FILE_TEMPLATE\t\tTEXT( \"c:\\\\test\\\\misc\\\\testdata%d.dat\" )\n#define COMPRESS_FILE\t\t\t\tTEXT( \"c:\\\\test\\\\filename.h\" )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tVM/CMS\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( __VMCMS__ )\n\n#define TEST_PRIVKEY_FILE\t\t\t\"zkeytest.p15\"\n#define TEST_PRIVKEY_TMP_FILE\t\t\"zkeytstt.p15\"\n#define TEST_PRIVKEY_ALT_FILE\t\t\"zkeytest.p12\"\n#define TEST_PRIVKEY_PGP_FILE\t\t\"zkeytest.pgp\"\n#define CA_PRIVKEY_FILE\t\t\t\t\"zkeyca.p15\"\n#define ICA_PRIVKEY_FILE\t\t\t\"zkeycai.p15\"\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE \"zkeycas%d.p15\"\n#define USER_PRIVKEY_FILE\t\t\t\"zkeyuse1.p15\"\n#define USER_PRIVKEY_FILE_TEMPLATE\t\"zkeyuse%d.p15\"\n#define DUAL_PRIVKEY_FILE\t\t\t\"zkeydual.p15\"\n#define RENEW_PRIVKEY_FILE\t\t\t\"zkeyren.p15\"\n#define P15_FILE_TEMPLATE\t\t\t\"zkeyp15%d.p15\"\n#define CMP_PRIVKEY_FILE_TEMPLATE\t\"zkeycmp.p15\"\n#define PNP_PRIVKEY_FILE\t\t\t\"zkeypnpu.p15\"\n#define PNPCA_PRIVKEY_FILE\t\t\t\"zkeypnpc.p15\"\n#define SERVER_PRIVKEY_FILE_TEMPLATE \"zkeysrv%d.p15\"\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE \"zkeysrp%d.p15\"\n#define SSH_PRIVKEY_FILE_TEMPLATE\t\"zkeyssh%d.p15\"\n#define SSL_CLI_PRIVKEY_FILE\t\t\"zkeysslc.p15\"\n#define TSA_PRIVKEY_FILE\t\t\t\"zkeytsa.p15\"\n#define MISC_PRIVKEY_FILE_TEMPLATE\t\"zkeymis%d.p15\"\n#define PKCS12_FILE_TEMPLATE\t\t\"zkeyp12%d.p12\"\n#define PSEUDOCERT_FILE_TEMPLATE\t\"zpseudo%d.dat\"\n\n#define PGP_PUBKEY_FILE\t\t\t\t\"zpubring.pgp\"\n#define PGP_PRIVKEY_FILE\t\t\t\"zsecring.pgp\"\n#define OPENPGP_PUBKEY_HASH_FILE\t\"zpubhash.gpg\"\n#define OPENPGP_PRIVKEY_HASH_FILE\t\"zsechash.gpg\"\n#define OPENPGP_PUBKEY_AES_FILE\t\t\"zpubaes.pkr\"\n#define OPENPGP_PRIVKEY_AES_FILE\t\"zsecaes.skr\"\n#define OPENPGP_PRIVKEY_CAST_FILE\t\"zseccas.gpg\"\n#define OPENPGP_PUBKEY_RSA_FILE\t\t\"zpubrsa.gpg\"\n#define OPENPGP_PRIVKEY_RSA_FILE\t\"zsecrsa.gpg\"\n#define OPENPGP_PRIVKEY_PART_FILE\t\"zsecpart.gpg\"\n#define OPENPGP_PRIVKEY_BC_FILE\t\t\"zsecbc.gpg\"\n#define OPENPGP_PUBKEY_ECC_FILE\t\t\"zpubecc.gpg\"\n#define OPENPGP_PRIVKEY_ECC_FILE\t\"zsececc.gpg\"\n#define OPENPGP_PUBKEY_MULT_FILE\t\"zpubmult.gpg\"\n#define NAIPGP_PUBKEY_FILE\t\t\t\"zpubnai.pkr\"\n#define NAIPGP_PRIVKEY_FILE\t\t\t\"zsecnai.skr\"\n\n#define CERT_FILE_TEMPLATE\t\t\t\"zcert%02d.der\"\n#define BASE64CERT_FILE_TEMPLATE\t\"zcert%d.asc\"\n#define ECC_CERT_FILE_TEMPLATE\t\t\"zeccert%02d.der\"\n#define BROKEN_CERT_FILE\t\t\t\"zcertb.der\"\n#define BROKEN_USER_CERT_FILE\t\t\"zcertbus.der\"\n#define BROKEN_CA_CERT_FILE\t\t\t\"zcertbca.der\"\n#define CERTREQ_FILE_TEMPLATE\t\t\"zcertreq%d.der\"\n#define CRL_FILE_TEMPLATE\t\t\t\"zcrl%d.crl\"\n#define CERTCHAIN_FILE_TEMPLATE\t\t\"zcertchn%d.der\"\n#define BASE64CERTCHAIN_FILE_TEMPLATE \"zcertchn%d.asc\"\n#define CHAINTEST_FILE_TEMPLATE\t\t\"zchntest%d.der\"\n#define PATHTEST_FILE_TEMPLATE\t\t\"zntest%d.p7s\"\n#define PADTEST_FILE_TEMPLATE\t\t\"zbadsig%d.der\"\n#define SSHKEY_FILE_TEMPLATE\t\t\"zsshkey%d.asc\"\n#define PGPKEY_FILE_TEMPLATE\t\t\"zpgpkey%d.pgp\"\n#define PGPASCKEY_FILE_TEMPLATE\t\t\"zpgpkey%d.asc\"\n#define NOCHAIN_EE_FILE\t\t\t\t\"znochn_ee.der\"\n#define NOCHAIN_CA_FILE\t\t\t\t\"znochn_ca.der\"\n#define RTCS_OK_FILE\t\t\t\t\"zrtcsrok.der\"\n#define OCSP_OK_FILE\t\t\t\t\"zocsprok.der\"\n#define OCSP_REV_FILE\t\t\t\t\"zocsprre.der\"\n#define OCSP_CA_FILE\t\t\t\t\"zocspca.der\"\n#define CRLCERT_FILE_TEMPLATE\t\t\"zcrlcrt%d.der\"\n#define RTCS_FILE_TEMPLATE\t\t\t\"zrtcsee%do.der\"\n#define OCSP_CA_FILE_TEMPLATE\t\t\"zocspca%d.der\"\n#define OCSP_EEOK_FILE_TEMPLATE\t\t\"zocspok%d.der\"\n#define OCSP_EEREV_FILE_TEMPLATE\t\"zocspre%d.der\"\n#define CMP_CA_FILE_TEMPLATE\t\t\"zcmpca%d.der\"\n#define SCEP_CA_FILE_TEMPLATE\t\t\"zscepca%d.der\"\n\n#define CMS_ENC_FILE_TEMPLATE\t\t\"zpwenc%d.p7m\"\n#define SMIME_SIG_FILE_TEMPLATE\t\t\"zsigned%d.p7s\"\n#define SMIME_SIG_FILE_INDEF\t\t\"zsigndef.p7s\"\n#define SMIME_ENV_FILE_TEMPLATE\t\t\"zenvel%d.p7m\"\n#define PGP_ENC_FILE_TEMPLATE\t\t\"zconven%d.pgp\"\n#define PGP_PKE_FILE_TEMPLATE\t\t\"zpgpenc%d.pgp\"\n#define OPENPGP_PKE_FILE_TEMPLATE\t\"zgpgenc%d.gpg\"\n#define PGP_SIG_FILE_TEMPLATE\t\t\"zsigned%d.pgp\"\n#define PGP_COPR_FILE_TEMPLATE\t\t\"zcopr%d.pgp\"\n\n#define TESTDATA_FILE_TEMPLATE\t\t\"ztestd%d.dat\"\n#define COMPRESS_FILE\t\t\t\t\"filename.h\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tWindows CE\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#elif defined( _WIN32_WCE )\n\n#define TEST_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\test.p15\"\n#define TEST_PRIVKEY_TMP_FILE\t\tL\"\\\\Storage Card\\\\keys\\\\test_tmp.p15\"\n#define TEST_PRIVKEY_ALT_FILE\t\tL\"\\\\Storage Card\\\\keys\\\\test.p12\"\n#define TEST_PRIVKEY_PGP_FILE\t\tL\"\\\\Storage Card\\\\keys\\\\test.pgp\"\n#define CA_PRIVKEY_FILE\t\t\t\tL\"\\\\Storage Card\\\\keys\\\\ca.p15\"\n#define ICA_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\ca_int.p15\"\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE L\"\\\\Storage Card\\\\keys\\\\scep_ca%d.p15\"\n#define USER_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\user1.p15\"\n#define USER_PRIVKEY_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\keys\\\\user%d.p15\"\n#define DUAL_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\dual.p15\"\n#define RENEW_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\renewed.p15\"\n#define P15_FILE_TEMPLATE\t\t\tL\"\\\\Storage Card\\\\keys\\\\pkcs15_%d.p15\"\n#define CMP_PRIVKEY_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\keys\\\\cmp%d.p15\"\n#define PNP_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\pnp_user.p15\"\n#define PNPCA_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\pnp_ca.p15\"\n#define SERVER_PRIVKEY_FILE_TEMPLATE L\"\\\\Storage Card\\\\keys\\\\server%d.p15\"\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE L\"\\\\Storage Card\\\\keys\\\\serverp%d.p15\"\n#define SSH_PRIVKEY_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\keys\\\\ssh%d.p15\"\n#define SSL_CLI_PRIVKEY_FILE\t\tL\"\\\\Storage Card\\\\keys\\\\ssl_cli.p15\"\n#define TSA_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\keys\\\\tsa.p15\"\n#define MISC_PRIVKEY_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\keys\\\\misc%d.p15\"\n#define PKCS12_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\keys\\\\pkcs12_%d.p12\"\n#define PSEUDOCERT_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\keys\\\\pseudocrt%d.dat\"\n\n#define PGP_PUBKEY_FILE\t\t\t\tL\"\\\\Storage Card\\\\pgp\\\\pubring.pgp\"\n#define PGP_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\pgp\\\\secring.pgp\"\n#define OPENPGP_PUBKEY_HASH_FILE\tL\"\\\\Storage Card\\\\pgp\\\\pub_hash.gpg\"\n#define OPENPGP_PRIVKEY_HASH_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_hash.gpg\"\n#define OPENPGP_PUBKEY_AES_FILE\t\tL\"\\\\Storage Card\\\\pgp\\\\pub_aes.pkr\"\n#define OPENPGP_PRIVKEY_AES_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_aes.skr\"\n#define OPENPGP_PRIVKEY_CAST_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_cast.gpg\"\n#define OPENPGP_PUBKEY_RSA_FILE\t\tL\"\\\\Storage Card\\\\pgp\\\\pub_rsa.gpg\"\n#define OPENPGP_PRIVKEY_RSA_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_rsa.gpg\"\n#define OPENPGP_PRIVKEY_PART_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_part.gpg\"\n#define OPENPGP_PRIVKEY_BC_FILE\t\tL\"\\\\Storage Card\\\\pgp\\\\sec_bc.gpg\"\n#define OPENPGP_PUBKEY_ECC_FILE\t\tL\"\\\\Storage Card\\\\pgp\\\\pub_ecc.gpg\"\n#define OPENPGP_PRIVKEY_ECC_FILE\tL\"\\\\Storage Card\\\\pgp\\\\sec_ecc.gpg\"\n#define OPENPGP_PUBKEY_MULT_FILE\tL\"\\\\Storage Card\\\\pgp\\\\pub_mult.gpg\"\n#define NAIPGP_PUBKEY_FILE\t\t\tL\"\\\\Storage Card\\\\pgp\\\\pub_nai.pkr\"\n#define NAIPGP_PRIVKEY_FILE\t\t\tL\"\\\\Storage Card\\\\pgp\\\\sec_nai.skr\"\n\n#define CERT_FILE_TEMPLATE\t\t\tL\"\\\\Storage Card\\\\certs\\\\cert%02d.der\"\n#define BASE64CERT_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\certs\\\\cert%d.asc\"\n#define ECC_CERT_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\certs\\\\eccert%02d.der\"\n#define BROKEN_CERT_FILE\t\t\tL\"\\\\Storage Card\\\\certs\\\\broken.der\"\n#define BROKEN_USER_CERT_FILE\t\tL\"\\\\Storage Card\\\\certs\\\\broken_ee.der\"\n#define BROKEN_CA_CERT_FILE\t\t\tL\"\\\\Storage Card\\\\certs\\\\broken_ca.der\"\n#define CERTREQ_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\certs\\\\certreq%d.der\"\n#define CRL_FILE_TEMPLATE\t\t\tL\"\\\\Storage Card\\\\certs\\\\crl%d.crl\"\n#define CERTCHAIN_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\certs\\\\certchn%d.der\"\n#define BASE64CERTCHAIN_FILE_TEMPLATE L\"\\\\Storage Card\\\\certs\\\\certchn%d.asc\"\n#define CHAINTEST_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\certs\\\\chntest%d.der\"\n#define PATHTEST_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\nist\\\\test%d.p7s\"\n#define PADTEST_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\certs\\\\badsig%d.der\"\n#define SSHKEY_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\misc\\\\sshkey%d.asc\"\n#define PGPKEY_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\pubkey%d.pgp\"\n#define PGPASCKEY_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\pubkey%d.asc\"\n#define NOCHAIN_EE_FILE\t\t\t\tL\"\\\\Storage Card\\\\misc\\\\nochn_ee.der\"\n#define NOCHAIN_CA_FILE\t\t\t\tL\"\\\\Storage Card\\\\misc\\\\nochn_ca.der\"\n#define RTCS_OK_FILE\t\t\t\tL\"\\\\Storage Card\\\\misc\\\\rtcsrok.der\"\n#define OCSP_OK_FILE\t\t\t\tL\"\\\\Storage Card\\\\session\\\\ocspr_ok.der\"\n#define OCSP_REV_FILE\t\t\t\tL\"\\\\Storage Card\\\\session\\\\ocspr_re.der\"\n#define OCSP_CA_FILE\t\t\t\tL\"\\\\Storage Card\\\\session\\\\ocspca.der\"\n#define CRLCERT_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\misc\\\\crl_cert%d.der\"\n#define RTCS_FILE_TEMPLATE\t\t\tL\"\\\\Storage Card\\\\misc\\\\rtcs_ee%do.der\"\n#define OCSP_CA_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\session\\\\ocsp_ca%d.der\"\n#define OCSP_EEOK_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\session\\\\ocsp_ok%d.der\"\n#define OCSP_EEREV_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\session\\\\ocsp_re%d.der\"\n#define CMP_CA_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\session\\\\cmp_cacert%d.der\"\n#define SCEP_CA_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\session\\\\scep_cacert%d.der\"\n\n#define CMS_ENC_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\smime\\\\pw_enc%d.p7m\"\n#define SMIME_SIG_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\smime\\\\signed%d.p7s\"\n#define SMIME_SIG_FILE_INDEF\t\tL\"\\\\Storage Card\\\\smime\\\\sig_ndef.p7s\"\n#define SMIME_ENV_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\smime\\\\envel%d.p7m\"\n#define PGP_ENC_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\conv_enc%d.pgp\"\n#define PGP_PKE_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\pgp_enc%d.pgp\"\n#define OPENPGP_PKE_FILE_TEMPLATE\tL\"\\\\Storage Card\\\\pgp\\\\gpg_enc%d.gpg\"\n#define PGP_SIG_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\signed%d.pgp\"\n#define PGP_COPR_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\pgp\\\\copr%d.pgp\"\n\n#define TESTDATA_FILE_TEMPLATE\t\tL\"\\\\Storage Card\\\\misc\\\\testdata%d.dat\"\n#define COMPRESS_FILE\t\t\t\tL\"\\\\Storage Card\\\\filename.h\"\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tGeneric Filesystem\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#else\n\n#define TEST_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/test.p15\" )\n#define TEST_PRIVKEY_TMP_FILE\t\tTEXT( \"test/keys/test_tmp.p15\" )\n#define TEST_PRIVKEY_ALT_FILE\t\tTEXT( \"test/keys/test.p12\" )\n#define TEST_PRIVKEY_PGP_FILE\t\tTEXT( \"test/keys/test.pgp\" )\n#define CA_PRIVKEY_FILE\t\t\t\tTEXT( \"test/keys/ca.p15\" )\n#define ICA_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/ca_int.p15\" )\n#define SCEPCA_PRIVKEY_FILE_TEMPLATE TEXT( \"test/keys/scep_ca%d.p15\" )\n#define USER_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/user1.p15\" )\n#define USER_PRIVKEY_FILE_TEMPLATE\tTEXT( \"test/keys/user%d.p15\" )\n#define DUAL_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/dual.p15\" )\n#define RENEW_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/renewed.p15\" )\n#define P15_FILE_TEMPLATE\t\t\tTEXT( \"test/keys/pkcs15_%d.p15\" )\n#define CMP_PRIVKEY_FILE_TEMPLATE\tTEXT( \"test/keys/cmp%d.p15\" )\n#define PNP_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/pnp_user.p15\" )\n#define PNPCA_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/pnp_ca.p15\" )\n#define SERVER_PRIVKEY_FILE_TEMPLATE TEXT( \"test/keys/server%d.p15\" )\n#define SERVER_ECPRIVKEY_FILE_TEMPLATE TEXT( \"test/keys/serverp%d.p15\" )\n#define SSH_PRIVKEY_FILE_TEMPLATE\tTEXT( \"test/keys/ssh%d.p15\" )\n#define SSL_CLI_PRIVKEY_FILE\t\tTEXT( \"test/keys/ssl_cli.p15\" )\n#define TSA_PRIVKEY_FILE\t\t\tTEXT( \"test/keys/tsa.p15\" )\n#define MISC_PRIVKEY_FILE_TEMPLATE\tTEXT( \"test/keys/misc%d.p15\" )\n#define PKCS12_FILE_TEMPLATE\t\tTEXT( \"test/keys/pkcs12_%d.p12\" )\n#define PSEUDOCERT_FILE_TEMPLATE\tTEXT( \"test/keys/pseudocrt%d.dat\" )\n\n#define PGP_PUBKEY_FILE\t\t\t\tTEXT( \"test/pgp/pubring.pgp\" )\n#define PGP_PRIVKEY_FILE\t\t\tTEXT( \"test/pgp/secring.pgp\" )\n#define OPENPGP_PUBKEY_HASH_FILE\tTEXT( \"test/pgp/pub_hash.gpg\" )\n#define OPENPGP_PRIVKEY_HASH_FILE\tTEXT( \"test/pgp/sec_hash.gpg\" )\n#define OPENPGP_PUBKEY_AES_FILE\t\tTEXT( \"test/pgp/pub_aes.pkr\" )\n#define OPENPGP_PRIVKEY_AES_FILE\tTEXT( \"test/pgp/sec_aes.skr\" )\n#define OPENPGP_PRIVKEY_CAST_FILE\tTEXT( \"test/pgp/sec_cast.gpg\" )\n#define OPENPGP_PUBKEY_RSA_FILE\t\tTEXT( \"test/pgp/pub_rsa.gpg\" )\n#define OPENPGP_PRIVKEY_RSA_FILE\tTEXT( \"test/pgp/sec_rsa.gpg\" )\n#define OPENPGP_PRIVKEY_PART_FILE\tTEXT( \"test/pgp/sec_part.gpg\" )\n#define OPENPGP_PRIVKEY_BC_FILE\t\tTEXT( \"test/pgp/sec_bc.gpg\" )\n#define OPENPGP_PUBKEY_ECC_FILE\t\tTEXT( \"test/pgp/pub_ecc.gpg\" )\n#define OPENPGP_PRIVKEY_ECC_FILE\tTEXT( \"test/pgp/sec_ecc.gpg\" )\n#define OPENPGP_PUBKEY_MULT_FILE\tTEXT( \"test/pgp/pub_mult.gpg\" )\n#define NAIPGP_PUBKEY_FILE\t\t\tTEXT( \"test/pgp/pub_nai.pkr\" )\n#define NAIPGP_PRIVKEY_FILE\t\t\tTEXT( \"test/pgp/sec_nai.skr\" )\n\n#define CERT_FILE_TEMPLATE\t\t\tTEXT( \"test/certs/cert%02d.der\" )\n#define BASE64CERT_FILE_TEMPLATE\tTEXT( \"test/certs/cert%d.asc\" )\n#define ECC_CERT_FILE_TEMPLATE\t\tTEXT( \"test/certs/eccert%02d.der\" )\n#define BROKEN_CERT_FILE\t\t\tTEXT( \"test/certs/broken.der\" )\n#define BROKEN_USER_CERT_FILE\t\tTEXT( \"test/certs/broken_ee.der\" )\n#define BROKEN_CA_CERT_FILE\t\t\tTEXT( \"test/certs/broken_ca.der\" )\n#define CERTREQ_FILE_TEMPLATE\t\tTEXT( \"test/certs/certreq%d.der\" )\n#define CRL_FILE_TEMPLATE\t\t\tTEXT( \"test/certs/crl%d.crl\" )\n#define CERTCHAIN_FILE_TEMPLATE\t\tTEXT( \"test/certs/certchn%d.der\" )\n#define BASE64CERTCHAIN_FILE_TEMPLATE TEXT( \"test/certs/certchn%d.asc\" )\n#define CHAINTEST_FILE_TEMPLATE\t\tTEXT( \"test/certs/chntest%d.der\" )\n#define PATHTEST_FILE_TEMPLATE\t\tTEXT( \"test/nist/test%d.p7s\" )\n#define PADTEST_FILE_TEMPLATE\t\tTEXT( \"test/certs/bad_sig%d.der\" )\n#define SSHKEY_FILE_TEMPLATE\t\tTEXT( \"test/misc/sshkey%d.asc\" )\n#define PGPKEY_FILE_TEMPLATE\t\tTEXT( \"test/pgp/pubkey%d.pgp\" )\n#define PGPASCKEY_FILE_TEMPLATE\t\tTEXT( \"test/pgp/pubkey%d.asc\" )\n#define NOCHAIN_EE_FILE\t\t\t\tTEXT( \"test/misc/nochn_ee.der\" )\n#define NOCHAIN_CA_FILE\t\t\t\tTEXT( \"test/misc/nochn_ca.der\" )\n#define RTCS_OK_FILE\t\t\t\tTEXT( \"test/misc/rtcsrok.der\" )\n#define OCSP_OK_FILE\t\t\t\tTEXT( \"test/session/ocspr_ok.der\" )\n#define OCSP_REV_FILE\t\t\t\tTEXT( \"test/session/ocspr_re.der\" )\n#define OCSP_CA_FILE\t\t\t\tTEXT( \"test/session/ocspca.der\" )\n#define CRLCERT_FILE_TEMPLATE\t\tTEXT( \"test/misc/crl_cert%d.der\" )\n#define RTCS_FILE_TEMPLATE\t\t\tTEXT( \"test/misc/rtcs_ee%do.der\" )\n#define OCSP_CA_FILE_TEMPLATE\t\tTEXT( \"test/session/ocsp_ca%d.der\" )\n#define OCSP_EEOK_FILE_TEMPLATE\t\tTEXT( \"test/session/ocsp_ok%d.der\" )\n#define OCSP_EEREV_FILE_TEMPLATE\tTEXT( \"test/session/ocsp_re%d.der\" )\n#define CMP_CA_FILE_TEMPLATE\t\tTEXT( \"test/session/cmp_cacert%d.der\" )\n#define SCEP_CA_FILE_TEMPLATE\t\tTEXT( \"test/session/scep_cacert%d.der\" )\n\n#define CMS_ENC_FILE_TEMPLATE\t\tTEXT( \"test/smime/pw_enc%d.p7m\" )\n#define SMIME_SIG_FILE_TEMPLATE\t\tTEXT( \"test/smime/signed%d.p7s\" )\n#define SMIME_SIG_FILE_INDEF\t\tTEXT( \"test/smime/sig_ndef.p7s\" )\n#define SMIME_ENV_FILE_TEMPLATE\t\tTEXT( \"test/smime/envel%d.p7m\" )\n#define PGP_ENC_FILE_TEMPLATE\t\tTEXT( \"test/pgp/conv_enc%d.pgp\" )\n#define PGP_PKE_FILE_TEMPLATE\t\tTEXT( \"test/pgp/pgp_enc%d.pgp\" )\n#define OPENPGP_PKE_FILE_TEMPLATE\tTEXT( \"test/pgp/gpg_enc%d.gpg\" )\n#define PGP_SIG_FILE_TEMPLATE\t\tTEXT( \"test/pgp/signed%d.pgp\" )\n#define PGP_COPR_FILE_TEMPLATE\t\tTEXT( \"test/pgp/copr%d.pgp\" )\n\n#define TESTDATA_FILE_TEMPLATE\t\tTEXT( \"test/misc/testdata%d.dat\" )\n#define COMPRESS_FILE\t\t\t\tTEXT( \"test/filename.h\" )\n\n#endif /* OS-specific naming */\n"
  },
  {
    "path": "deps/cl345/test/fuzz/websockets.min",
    "content": "n*)oA\n:zؕ@\u001ac "
  },
  {
    "path": "deps/cl345/test/highlvl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Mid and High-Level Test Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <limits.h>\t\t/* To determine max.buffer size we can encrypt */\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\t/* For checking availability of test options */\n#include \"misc/consts.h\"\t/* For DEFAULT_CRYPT_ALGO */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n#ifndef max\t\t\t\t/* Some compilers don't define this */\n  #define max( a, b )\t( ( ( a ) > ( b ) ) ? ( ( int ) a ) : ( ( int ) b ) )\n#endif /* !max */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( TEST_MIDLEVEL ) || defined( TEST_HIGHLEVEL )\n\n/* Test whether two session keys are identical */\n\nstatic int compareSessionKeys( const CRYPT_CONTEXT cryptContext1,\n\t\t\t\t\t\t\t   const CRYPT_CONTEXT cryptContext2 )\n\t{\n\tBYTE buffer[ CRYPT_MAX_IVSIZE ];\n\tint blockSize, ivSize, status;\n\n\tstatus = cryptGetAttribute( cryptContext1, CRYPT_CTXINFO_BLOCKSIZE, \n\t\t\t\t\t\t\t\t&blockSize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptContext1, CRYPT_CTXINFO_IVSIZE,\n\t\t\t\t\t\t\t\t\t&ivSize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext1, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", ivSize );\n\tcryptSetAttributeString( cryptContext2, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", ivSize );\n\tmemcpy( buffer, \"0123456789ABCDEF\", max( blockSize, 8 ) );\n\tstatus = cryptEncrypt( cryptContext1, buffer, max( blockSize, 8 ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptEncrypt() with first key failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptDecrypt( cryptContext2, buffer, max( blockSize, 8 ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDecrypt() with second key failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( memcmp( buffer, \"0123456789ABCDEF\", max( blockSize, 8 ) ) )\n\t\t{\n\t\tfputs( \"Data decrypted with key2 != plaintext encrypted with key1.\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\n/* Test whether two hash/MAC values are identical */\n\nstatic int compareHashValues( const CRYPT_CONTEXT hashContext1,\n\t\t\t\t\t\t\t  const CRYPT_CONTEXT hashContext2 )\n\t{\n\tconst BYTE *data = ( BYTE * ) \"0123456789ABCDEF\"; \n\tBYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];\n\tint length1, length2, status;\n\n\tstatus = cryptEncrypt( hashContext1, ( void * ) data, 16 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptEncrypt( hashContext1, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( hashContext1, CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t  &hash1, &length1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptEncrypt() with first hash/MAC context \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptEncrypt( hashContext2, ( void * ) data, 16 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptEncrypt( hashContext2, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( hashContext2, CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t  &hash2, &length2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptEncrypt() with second hash/MAC context \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( length1 != length2 || memcmp( hash1, hash2, length1 ) )\n\t\t{\n\t\tfputs( \"Hash/MAC value from context1 != hash/MAC value from \"\n\t\t\t  \"context2.\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n#endif /* TEST_MIDLEVEL || TEST_HIGHLEVEL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tMid-level Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_MIDLEVEL\n\n/* General-purpose routines to perform a key exchange and sign and sig\n   check data */\n\nstatic int signData( const char *algoName, const CRYPT_ALGO_TYPE algorithm,\n\t\t\t\t\t const CRYPT_CONTEXT externalSignContext,\n\t\t\t\t\t const CRYPT_CONTEXT externalCheckContext,\n\t\t\t\t\t const BOOLEAN useSidechannelProtection,\n\t\t\t\t\t const BOOLEAN useSHA2,\n\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType )\n\t{\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tCRYPT_CONTEXT signContext, checkContext;\n\tCRYPT_CONTEXT hashSignContext, hashCheckContext;\n\tconst int extraData = ( formatType == CRYPT_FORMAT_CMS || \\\n\t\t\t\t\t\t\tformatType == CRYPT_FORMAT_SMIME ) ? \\\n\t\t\t\t\t\t\tCRYPT_USE_DEFAULT : CRYPT_UNUSED;\n\tBYTE buffer[ 1024 ], hashBuffer[] = \"abcdefghijklmnopqrstuvwxyz\";\n\tint status, value, length;\n\n\tfprintf( outputStream, \"Testing %s%s digital signature%s...\\n\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\", algoName,\n\t\t\t useSidechannelProtection ? \" with side-channel protection\" : \"\" );\n\n\t/* Create SHA/SHA2 hash contexts and hash the test buffer.  We don't\n\t   complete the hashing if it's a PGP signature since this hashes in\n\t   extra data before generating the signature.  In addition we use two\n\t   hash contexts, one to create the signature and the other to verify\n\t   it, to eliminate common-mode failures and, in the PGP case, because\n\t   the signature-generation process completes the hashing so we'd need\n\t   to reset the context before we could use the same one for the\n\t   checking step */\n\tstatus = cryptCreateContext( &hashSignContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t useSHA2 ? CRYPT_ALGO_SHA2 : \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateContext( &hashCheckContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t useSHA2 ? CRYPT_ALGO_SHA2 : \\\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_SHA1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptEncrypt( hashSignContext, hashBuffer, 26 );\n\tcryptEncrypt( hashCheckContext, hashBuffer, 26 );\n\tif( formatType != CRYPT_FORMAT_PGP )\n\t\t{\n\t\tcryptEncrypt( hashSignContext, hashBuffer, 0 );\n\t\tcryptEncrypt( hashCheckContext, hashBuffer, 0 );\n\t\t}\n\n\t/* Create the appropriate en/decryption contexts */\n\tif( externalSignContext != CRYPT_UNUSED )\n\t\t{\n\t\tsignContext = externalSignContext;\n\t\tcheckContext = externalCheckContext;\n\t\t}\n\telse\n\t\t{\n\t\tswitch( algorithm )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\tif( useSHA2 )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we're using SHA-2 then we have to use a larger RSA \n\t\t\t\t\t   key to ensure that the hash values fits into the \n\t\t\t\t\t   signature data */\n\t\t\t\t\tstatus = loadRSAContextsLarge( CRYPT_UNUSED, &checkContext,\n\t\t\t\t\t\t\t\t\t\t\t\t   &signContext );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tstatus = loadRSAContexts( CRYPT_UNUSED, &checkContext,\n\t\t\t\t\t\t\t\t\t\t\t  &signContext );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\tstatus = loadDSAContexts( CRYPT_UNUSED, &checkContext,\n\t\t\t\t\t\t\t\t\t\t  &signContext );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t\tstatus = loadECDSAContexts( CRYPT_UNUSED, &checkContext, \n\t\t\t\t\t\t\t\t\t\t\t&signContext );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tstatus = FALSE;\n\t\t\t}\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Find out how big the signature will be */\n\tstatus = cryptCreateSignatureEx( NULL, 0, &length, formatType,\n\t\t\t\t\t\t\t\t\t signContext, hashSignContext, extraData );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSignatureEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptCreateSignatureEx() reports signature object \"\n\t\t\t \"will be %d bytes long\\n\", length );\n\tassert( length <= 1024 );\n\n\t/* Sign the hashed data */\n\tif( useSidechannelProtection )\n\t\t{\n\t\t( void ) cryptGetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_MISC_SIDECHANNELPROTECTION, \n\t\t\t\t\t\t\t\t\t&value );\n\t\tcryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t   CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, 1 );\n\t\t}\n\tstatus = cryptCreateSignatureEx( buffer, 1024, &length, formatType,\n\t\t\t\t\t\t\t\t\t signContext, hashSignContext, extraData );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSignatureEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( useSidechannelProtection && value != 1 )\n\t\t{\n\t\tcryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t   CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, value );\n\t\t}\n\n\t/* Query the signed object */\n\tstatus = cryptQueryObject( buffer, length, &cryptObjectInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptQueryObject() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptQueryObject() reports object type %d, \"\n\t\t\t \"algorithm %d, hash algorithm %d.\\n\", \n\t\t\t cryptObjectInfo.objectType, cryptObjectInfo.cryptAlgo, \n\t\t\t cryptObjectInfo.hashAlgo );\n\tmemset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );\n\tif( formatType == CRYPT_FORMAT_CRYPTLIB )\n\t\t{\n\t\tdebugDump( ( algorithm == CRYPT_ALGO_DSA ) ? \"sigd\" : \\\n\t\t\t\t   ( algorithm == CRYPT_ALGO_ECDSA ) ? \"sigec\" : \\\n\t\t\t\t   useSHA2 ? \"sigr2\" : \"sigr\", buffer, length );\n\t\t}\n\telse\n\t\t{\n\t\tdebugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t   \"sigr.pgp\" : \"sigd.pgp\", buffer, length );\n\t\t}\n\n\t/* Check the signature on the hash */\n\tstatus = cryptCheckSignature( buffer, length, checkContext, \n\t\t\t\t\t\t\t\t  hashCheckContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( hashSignContext );\n\t\tcryptDestroyContext( hashCheckContext );\n\t\tif( externalSignContext == CRYPT_UNUSED )\n\t\t\tdestroyContexts( CRYPT_UNUSED, checkContext, signContext );\n\t\tfprintf( outputStream, \"cryptCheckSignature() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( hashSignContext );\n\tcryptDestroyContext( hashCheckContext );\n\tif( externalSignContext == CRYPT_UNUSED )\n\t\tdestroyContexts( CRYPT_UNUSED, checkContext, signContext );\n\tfprintf( outputStream, \"Generation and checking of %s digital signature \"\n\t\t\t \"succeeded.\\n\\n\", algoName );\n\treturn( TRUE );\n\t}\n\nstatic int keyExportImport( const char *algoName,\n\t\t\t\t\t\t\tconst CRYPT_ALGO_TYPE algorithm,\n\t\t\t\t\t\t\tconst CRYPT_CONTEXT externalCryptContext,\n\t\t\t\t\t\t\tconst CRYPT_CONTEXT externalDecryptContext,\n\t\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType )\n\t{\n\tconst CRYPT_ALGO_TYPE cryptAlgo = ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\t\t  CRYPT_ALGO_IDEA : CRYPT_ALGO_RC2;\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\tBYTE *buffer;\n\tint status, length;\n\n\tfprintf( outputStream, \"Testing %s%s public-key export/import...\\n\",\n\t\t\t ( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\", algoName );\n\n\t/* Create encryption contexts for the session key.  PGP stores the\n\t   session key information with the encrypted key data, so we can't\n\t   create the context at this point */\n\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t selectCipher( cryptAlgo ) );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( sessionKeyContext1, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t   CRYPT_MODE_CFB );\n\tstatus = cryptGenerateKey( sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( formatType != CRYPT_FORMAT_PGP )\n\t\t{\n\t\tstatus = cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t selectCipher( cryptAlgo ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttribute( sessionKeyContext2, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t\t   CRYPT_MODE_CFB );\n\t\t}\n\n\t/* Create the appropriate en/decryption contexts */\n\tif( externalCryptContext != CRYPT_UNUSED )\n\t\t{\n\t\tcryptContext = externalCryptContext;\n\t\tdecryptContext = externalDecryptContext;\n\t\t}\n\telse\n\t\t{\n\t\tif( algorithm == CRYPT_ALGO_ELGAMAL )\n\t\t\tstatus = loadElgamalContexts( &cryptContext, &decryptContext );\n\t\telse\n\t\t\t{\n\t\t\tstatus = loadRSAContexts( CRYPT_UNUSED, &cryptContext, \n\t\t\t\t\t\t\t\t\t  &decryptContext );\n\t\t\t}\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Find out how big the exported key will be */\n\tstatus = cryptExportKeyEx( NULL, 0, &length, formatType, cryptContext,\n\t\t\t\t\t\t\t   sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptExportKeyEx() reports exported key object \"\n\t\t\t \"will be %d bytes long\\n\", length );\n\tif( ( buffer = malloc( length ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Export the session key */\n\tstatus = cryptExportKeyEx( buffer, length, &length, formatType,\n\t\t\t\t\t\t\t   cryptContext, sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Query the encrypted key object */\n\tstatus = cryptQueryObject( buffer, length, &cryptObjectInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptQueryObject() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptQueryObject() reports object type %d, \"\n\t\t\t \"algorithm %d.\\n\", cryptObjectInfo.objectType, \n\t\t\t cryptObjectInfo.cryptAlgo );\n\tmemset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );\n\tif( formatType == CRYPT_FORMAT_CRYPTLIB )\n\t\t{\n\t\tdebugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t   \"keytrans\" : \"keytr_el\", buffer, length );\n\t\t}\n\telse\n\t\t{\n\t\tdebugDump( ( algorithm == CRYPT_ALGO_RSA ) ? \\\n\t\t\t\t   \"keytrans.pgp\" : \"keytr_el.pgp\", buffer, length );\n\t\t}\n\n\t/* Recreate the session key by importing the encrypted key */\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\tstatus = cryptImportKeyEx( buffer, length, decryptContext,\n\t\t\t\t\t\t\t\t   CRYPT_UNUSED, &sessionKeyContext2 );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptImportKeyEx( buffer, length, decryptContext,\n\t\t\t\t\t\t\t\t   sessionKeyContext2, NULL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\t\tif( externalCryptContext == CRYPT_UNUSED )\n\t\t\tdestroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );\n\t\tfprintf( outputStream, \"cryptImportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the two keys match */\n\tif( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\tif( externalCryptContext == CRYPT_UNUSED )\n\t\tdestroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );\n\tfprintf( outputStream, \"Export/import of session key via %s-encrypted \"\n\t\t\t \"data block\\n  succeeded.\\n\\n\", algoName );\n\tfree( buffer );\n\treturn( TRUE );\n\t}\n\n/* Test the ability to encrypt a large amount of data */\n\nint testLargeBufferEncrypt( void )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\tBYTE *buffer;\n\tconst size_t length = ( INT_MAX <= 32768L ) ? 16384 : 1048576;\n\tint i, status;\n\n\tfputs( \"Testing encryption of large data quantity...\\n\", outputStream );\n\n\tstatus = cryptQueryCapability( DEFAULT_CRYPT_ALGO, &cryptQueryInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Allocate a large buffer and fill it with a known value */\n\tif( ( buffer = malloc( length ) ) == NULL )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't allocate buffer of %ld bytes, \"\n\t\t\t\t \"skipping large buffer encryption test.\\n\", \n\t\t\t\t ( long ) length );\n\t\treturn( TRUE );\n\t\t}\n\tmemset( buffer, '*', length );\n\n\t/* Encrypt the buffer */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY, \n\t\t\t\t\t\t\t \"123456789012345678901234\", \n\t\t\t\t\t\t\t cryptQueryInfo.keySize );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", \n\t\t\t\t\t\t\t cryptQueryInfo.blockSize );\n\tstatus = cryptEncrypt( cryptContext, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptEncrypt() of large data quantity \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Decrypt the buffer */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t \"123456789012345678901234\", \n\t\t\t\t\t\t\t cryptQueryInfo.keySize );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n\t\t\t\t\t\t\t \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", \n\t\t\t\t\t\t\t cryptQueryInfo.blockSize );\n\tstatus = cryptDecrypt( cryptContext, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDecrypt() of large data quantity \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Make sure that it went OK */\n\tfor( i = 0; i < ( int ) length; i++ )\n\t\t{\n\t\tif( buffer[ i ] != '*' )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Decrypted data != original plaintext \"\n\t\t\t\t\t \"at position %d, line %d.\\n\", i, __LINE__ );\n\t\t\tfree( buffer );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tfree( buffer );\n\tfprintf( outputStream , \"Encryption of %ld bytes of data \"\n\t\t\t \"succeeded.\\n\\n\", ( long ) length );\n\treturn( TRUE );\n\t}\n\n/* Test the code to derive a fixed-length encryption/MAC key from a \n   variable-length user key */\n\nstatic int deriveKey( const C_STR userKey, const int userKeyLength,\n\t\t\t\t\t  const C_STR description, BOOLEAN useMAC, \n\t\t\t\t\t  BOOLEAN useAltDeriveAlgo )\n\t{\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tint hashAlgo, status;\n\n\tfprintf( outputStream, \"Testing %s key derivation \", \n\t\t\t useMAC ? \"MAC\" : \"encryption\" );\n\tif( useAltDeriveAlgo )\n\t\tfprintf( outputStream, \"using alternative derivation algorithm\" );\n\telse\n\t\tfprintf( outputStream, \"from %s\", description );\n\tfputs( \"...\\n\", outputStream );\n\n\t/* Find out what the default key derivation algorithm is.  This is \n\t   required because we need to use something other than the default\n\t   for the useAltDeriveAgo test */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_KEYING_ALGO, \n\t\t\t\t\t\t\t\t&hashAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\tif( useMAC )\n\t\t{\n\t\t/* Create HMAC-SHA1 MAC contexts */\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_HMAC_SHA1 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptCreateContext( &decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_HMAC_SHA1 );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Create IDEA/CBC encryption and decryption contexts/and load them \n\t\t   with identical salt values for the key derivation (this is easier \n\t\t   than reading the salt from one and writing it to the other) */\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_IDEA ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptCreateContext( &decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_IDEA ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tcryptSetAttributeString( decryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tif( useAltDeriveAlgo )\n\t\t{\n\t\tconst CRYPT_ALGO_TYPE altAlgo = \n\t\t\t\t( hashAlgo == CRYPT_ALGO_HMAC_SHA1 ) ? \\\n\t\t\t\tCRYPT_ALGO_HMAC_SHA2 : CRYPT_ALGO_HMAC_SHA1;\n\n\t\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ALGO,\n\t\t\t\t\t\t   altAlgo );\n\t\tcryptSetAttribute( decryptContext, CRYPT_CTXINFO_KEYING_ALGO,\n\t\t\t\t\t\t   altAlgo );\n\t\t}\n\n\t/* Load a key derived from a user key into both contexts */\n\tstatus = cryptSetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Key derivation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttributeString( decryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Key derivation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the two derived keys match */\n\tif( useMAC )\n\t\t{\n\t\tif( !compareHashValues( cryptContext, decryptContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !compareSessionKeys( cryptContext, decryptContext ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );\n\n\tfprintf( outputStream, \"%s key derivation succeeded.\\n\\n\", \n\t\t\t useMAC ? \"MAC\" : \"Encryption\" );\n\treturn( TRUE );\n\t}\n\nint testDeriveKey( void )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tC_STR shortUserKey = TEXT( \"12345678\" );\n\tC_STR medUserKey = TEXT( \"This is a long user key for key derivation testing\" );\n\tC_STR longUserKey = TEXT( \"This is a really long user key that exceeds the HMAC input limit for keys\" );\n#ifdef USE_3DES\n\tBYTE buffer[ 8 ];\n#endif /* USE_3DES */\n\tint value DUMMY_INIT, status;\n\n\t/* Make sure that we can get/set the keying values with equivalent\n\t   systemwide settings using either the context-specific or global\n\t   option attributes */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptSetAttribute( cryptContext,\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_ITERATIONS, 5 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_KEYING_ITERATIONS,\n\t\t\t\t\t\t\t\t\t&value );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) || value != 5 )\n\t\t{\n\t\tif( cryptStatusError( status ) )\n\t\t\tvalue = -1;\t/* Set dummy value if read failed */\n\t\tfprintf( outputStream, \"Failed to get/set context attribute via \"\n\t\t\t\t \"equivalent global attribute, error\\ncode %d, value %d \"\n\t\t\t\t \"(should be 5), line %d.\\n\", status, value, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test the derivation of encryption keys from short, medium, and long \n\t   passwords */\n\tstatus = deriveKey( shortUserKey, paramStrlen( shortUserKey ), \n\t\t\t\t\t\t\"short user key\", FALSE, FALSE );\n\tif( status ) \n\t\t{\n\t\tstatus = deriveKey( medUserKey, paramStrlen( medUserKey ), \n\t\t\t\t\t\t\t\"medium user key\", FALSE, FALSE );\n\t\t}\n\tif( status ) \n\t\t{\n\t\tstatus = deriveKey( longUserKey, paramStrlen( longUserKey ), \n\t\t\t\t\t\t\t\"long user key\", FALSE, FALSE );\n\t\t}\n\tif( !status ) \n\t\treturn( FALSE );\n\n\t/* Test the derivation of MAC keys from short, medium, and long \n\t   passwords */\n\tstatus = deriveKey( shortUserKey, paramStrlen( shortUserKey ), \n\t\t\t\t\t\t\"short user key\", TRUE, FALSE );\n\tif( status ) \n\t\t{\n\t\tstatus = deriveKey( medUserKey, paramStrlen( medUserKey ), \n\t\t\t\t\t\t\t\"medium user key\", TRUE, FALSE );\n\t\t}\n\tif( status ) \n\t\t{\n\t\tstatus = deriveKey( longUserKey, paramStrlen( longUserKey ), \n\t\t\t\t\t\t\t\"long user key\", TRUE, FALSE );\n\t\t}\n\tif( !status ) \n\t\treturn( FALSE );\n\n\t/* Test the derivation process using a non-default hash algorithm */\n\tstatus = deriveKey( shortUserKey, paramStrlen( shortUserKey ), \"\", \n\t\t\t\t\t\tFALSE, TRUE );\n\tif( !status ) \n\t\treturn( FALSE );\n\tstatus = deriveKey( shortUserKey, paramStrlen( shortUserKey ), \"\", \n\t\t\t\t\t\tTRUE, TRUE );\n\tif( !status ) \n\t\treturn( FALSE );\n\n\t/* Test the derivation process using fixed test data: password =\n\t   \"password\", hash = HMAC_SHA1, salt = { 0x12 0x34 0x56 0x78 0x78 0x56 \n\t   0x34 0x12 }, iterations = 5, algorithm = 3DES */\n#ifdef USE_3DES\n\tfputs( \"Testing key derivation using fixed test vectors...\\n\", \n\t\t   outputStream );\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_3DES );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE, CRYPT_MODE_ECB );\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ALGO, \n\t\t\t\t\t   CRYPT_ALGO_HMAC_SHA1 );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ITERATIONS, 5 );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t TEXT( \"password\" ),\n\t\t\t\t\t\t\t paramStrlen( TEXT( \"password\" ) ) );\n\tmemset( buffer, 0, 8 );\n\tcryptEncrypt( cryptContext, buffer, 8 );\n\tcryptDestroyContext( cryptContext );\n#if 0\t/* Older single-DES value */\n\tif( memcmp( buffer, \"\\x9B\\xBD\\x78\\xFC\\x11\\xA3\\xA9\\x08\", 8 ) )\n#else\n\tif( memcmp( buffer, \"\\x87\\x91\\x20\\xAF\\x19\\x2F\\xB6\\x03\", 8 ) )\n#endif /* 0 */\n\t\t{\n\t\tfputs( \"Derived key value doesn't match predefined test value.\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n#endif /* USE_3DES */\n\tfputs( \"Key derivation succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Test the code to export/import an encrypted key via conventional\n   encryption.\n\n   To create the CMS PWRI test vectors, substitute the following code for the\n   normal key load:\n\n\tconst C_STR userKey = \"password\"; \n\tconst int userKeyLength = 8;\n\n\tcryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED, CRYPT_ALGO_DES );\n\tcryptSetAttributeString( sessionKeyContext1, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t \"\\x8C\\x63\\x7D\\x88\\x72\\x23\\xA2\\xF9\", 8 );\n\tcryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_DES );\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ITERATIONS, 5 );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tstatus = cryptSetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength ); \n\n\tTo create the PKCS #5 v2.0 Amd.1 test vectors use:\n\n\tconst C_STR userKey = \"foo123\"; \n\tconst int userKeyLength = 6;\n\n\tcryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_3DES );\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ITERATIONS, 1000 );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x3E\\xFF\\x3C\\x4A\\x72\\x12\\x9C\", 8 );\n\tstatus = cryptSetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength ); */\n\ntypedef enum { AES_NONE, AES_128_128, AES_128_256, \n\t\t\t   AES_256_128, AES_256_256 } AES_KEYSIZE_OPT;\n\t\t\t   /* First parameter = session key, second \n\t\t\t      parameter = wrap key */\n\nstatic int conventionalExportImport( const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t\t\t const CRYPT_CONTEXT sessionKeyContext1,\n\t\t\t\t\t\t\t\t\t const CRYPT_CONTEXT sessionKeyContext2,\n\t\t\t\t\t\t\t\t\t const BOOLEAN useAltAlgo,\n\t\t\t\t\t\t\t\t\t const AES_KEYSIZE_OPT aesKeysizeOpt )\n\t{\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tCRYPT_CONTEXT decryptContext;\n\tBYTE *buffer;\n\tconst C_STR userKey = TEXT( \"All n-entities must communicate with other n-entities via n-1 entiteeheehees\" );\n\tconst int userKeyLength = paramStrlen( userKey );\n\tint prfAlgo, altPrfAlgo, length, status;\n\n\t/* Check what the default PRF algorithm is so that we can set a \n\t   different one if required */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_KEYING_ALGO, \n\t\t\t\t\t\t\t\t&prfAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptGetAttribute() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\taltPrfAlgo = ( prfAlgo == CRYPT_ALGO_HMAC_SHA1 ) ? \\\n\t\t\t\t CRYPT_ALGO_HMAC_SHA2 : CRYPT_ALGO_HMAC_SHA1;\n\n\t/* Set the key for the exporting context */\n\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t\t\t  \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tif( cryptStatusOK( status ) && useAltAlgo )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptContext, CRYPT_CTXINFO_KEYING_ALGO,\n\t\t\t\t\t\t\t\t\taltPrfAlgo );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttributeString() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Find out how big the exported key will be */\n\tstatus = cryptExportKey( NULL, 0, &length, cryptContext,\n\t\t\t\t\t\t\t sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptExportKey() reports exported key object \"\n\t\t\t \"will be %d bytes long\\n\", length );\n\tif( ( buffer = malloc( length ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Export the session information */\n\tstatus = cryptExportKey( buffer, length, &length, cryptContext,\n\t\t\t\t\t\t\t sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Query the encrypted key object */\n\tstatus = cryptQueryObject( buffer, length, &cryptObjectInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptQueryObject() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptQueryObject() reports object type %d, \"\n\t\t\t \"algorithm %d, mode %d.\\n\", cryptObjectInfo.objectType, \n\t\t\t cryptObjectInfo.cryptAlgo, cryptObjectInfo.cryptMode );\n\tfprintf( outputStream, \"cryptQueryObject() reports key derivation info \"\n\t\t\t \"as an %d-byte salt\\n  processed with %d iterations of PRF \"\n\t\t\t \"algorithm %d.\\n\", cryptObjectInfo.saltSize, \n\t\t\t cryptObjectInfo.iterations, cryptObjectInfo.hashAlgo );\n\tif( aesKeysizeOpt == AES_NONE )\n\t\tdebugDump( \"kek\", buffer, length );\n\telse\n\t\t{\n\t\tconst char *fileName = ( aesKeysizeOpt == AES_128_128 ) ? \\\n\t\t\t\t\t\t\t\t \"kek_aes128_128\" : \\\n\t\t\t\t\t\t\t   ( aesKeysizeOpt == AES_128_256 ) ? \\\n\t\t\t\t\t\t\t\t \"kek_aes128_256\" : \\\n\t\t\t\t\t\t\t   ( aesKeysizeOpt == AES_256_128 ) ? \\\n\t\t\t\t\t\t\t\t \"kek_aes256_128\" : \"kek_aes256_256\";\n\t\tdebugDump( fileName, buffer, length );\n\t\t}\n\tif( useAltAlgo && cryptObjectInfo.hashAlgo != altPrfAlgo )\n\t\t{\n\t\tfprintf( outputStream, \"Key wrap with PRF algorithm %d reported \"\n\t\t\t\t \"algorithm as %d,\\n\" \"line %d.\\n\", altPrfAlgo, \n\t\t\t\t cryptObjectInfo.hashAlgo, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Recreate the session key by importing the encrypted key */\n\tstatus = cryptCreateContext( &decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t cryptObjectInfo.cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( decryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t   cryptObjectInfo.cryptMode );\n\tstatus = cryptSetAttributeString( decryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t\t\t  cryptObjectInfo.salt,\n\t\t\t\t\t\t\t\t\t  cryptObjectInfo.saltSize );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( decryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_ITERATIONS,\n\t\t\t\t\t\t\t\t\tcryptObjectInfo.iterations );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\tcryptObjectInfo.hashAlgo != CRYPT_ALGO_NONE )\n\t\t{\n\t\tstatus = cryptSetAttribute( decryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYING_ALGO,\n\t\t\t\t\t\t\t\t\tcryptObjectInfo.hashAlgo );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t( aesKeysizeOpt == AES_128_256 || aesKeysizeOpt == AES_256_256 ) )\n\t\t{\n\t\t/* The CRYPT_OBJECT_INFO structure doesn't contain an entry for the\n\t\t   key size because it hadn't been needed previously and it can't be \n\t\t   changed now without breaking the ABI, so we have to explicitly \n\t\t   set the non-default key size via an externally-supplied parameter \n\t\t   until there's a rev.of the minor version and we can modify the \n\t\t   ABI */\n\t\tstatus = cryptSetAttribute( decryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYSIZE, 32 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( decryptContext,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttributeString() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptImportKey( buffer, length, decryptContext,\n\t\t\t\t\t\t\t sessionKeyContext2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( decryptContext );\n\t\tfprintf( outputStream, \"cryptImportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the two keys match */\n\tif( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )\n\t\treturn( FALSE );\n\n\t/* If we're using variable-length keys, make sure that the lengths are \n\t   right.  We only need to check one of the two contexts since the fact \n\t   that the key sizes are the same has already been confirmed */\n\tif( aesKeysizeOpt != AES_NONE )\n\t\t{\n\t\tconst int sessionKeySize = ( aesKeysizeOpt == AES_128_128 || \\\n\t\t\t\t\t\t\t\t\t aesKeysizeOpt == AES_128_256 ) ? \\\n\t\t\t\t\t\t\t\t\t 16 : 32;\n\t\tconst int wrapKeySize = ( aesKeysizeOpt == AES_128_128 || \\\n\t\t\t\t\t\t\t\t  aesKeysizeOpt == AES_256_128 ) ? \\\n\t\t\t\t\t\t\t\t  16 : 32;\n\n\t\tstatus = cryptGetAttribute( sessionKeyContext1, \n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYSIZE, &length );\n\t\tif( cryptStatusError( status ) || length != sessionKeySize )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"AES session key size is incorrect, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptGetAttribute( decryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYSIZE, &length );\n\t\tif( cryptStatusError( status ) || length != wrapKeySize )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"AES wrap key size is incorrect, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( decryptContext );\n\tfree( buffer );\n\treturn( TRUE );\n\t}\n\nstatic int testConv3DES( void )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\tint status;\n\n\tfputs( \"Testing 3DES conventional key export/import...\\n\", \n\t\t   outputStream );\n\n\t/* Create triple-DES contexts for the session key */\n\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_3DES );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( sessionKeyContext1, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t\t\tCRYPT_MODE_CFB );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( sessionKeyContext1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_3DES );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( sessionKeyContext2, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t\t\tCRYPT_MODE_CFB );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Session key context setup failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create a CAST context to export the session key */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_CAST ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Export key context setup failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Export the key.  We indicate the use of an alternative PRF algorithm \n\t   because this is the now-deprecated SHA1, previously the default was\n\t   SHA1 and the alternative was SHA2 but since the default is now SHA2 \n\t   the original default has become the alternative */\n\tif( !conventionalExportImport( cryptContext, sessionKeyContext1,\n\t\t\t\t\t\t\t\t   sessionKeyContext2, TRUE, AES_NONE ) )\n\t\treturn( FALSE );\n\tcryptDestroyContext( cryptContext );\n\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\tfputs( \"Export/import of 3DES key via user-key-based conventional\\n  \"\n\t\t   \"encryption succeeded.\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\nstatic int testConvAES( const AES_KEYSIZE_OPT aesKeysizeOpt )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\tconst char *aesKey1Name = ( aesKeysizeOpt == AES_128_128 || \\\n\t\t\t\t\t\t\t\taesKeysizeOpt == AES_128_256 ) ? \\\n\t\t\t\t\t\t\t   \"AES-128\" : \"AES-256\";\n\tconst char *aesKey2Name = ( aesKeysizeOpt == AES_128_128 || \\\n\t\t\t\t\t\t\t\taesKeysizeOpt == AES_256_128 ) ? \\\n\t\t\t\t\t\t\t   \"AES-128\" : \"AES-256\";\n\tint status;\n\n\tfprintf( outputStream, \"Testing %s conventional key export/import via \"\n\t\t\t \"%s...\\n\", aesKey1Name, aesKey2Name );\n\n\t/* Create AES contexts for the session key and another AES context to\n\t   export the session key.  In addition to using AES we use a non-\n\t   default PRF algorithm */\n\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_AES ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( sessionKeyContext1, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t\t\tCRYPT_MODE_CFB );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t( aesKeysizeOpt == AES_256_128 || aesKeysizeOpt == AES_256_256 ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( sessionKeyContext1, \n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYSIZE, 32 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( sessionKeyContext1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_AES ) );\n\t\tcryptSetAttribute( sessionKeyContext2, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\tCRYPT_MODE_CFB );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Session key context setup failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t selectCipher( CRYPT_ALGO_AES ) );\n\tif( cryptStatusOK( status ) && \\\n\t\t( aesKeysizeOpt == AES_128_256 || aesKeysizeOpt == AES_256_256 ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEYSIZE, 32 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Export key context setup failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Export the key */\n\tif( !conventionalExportImport( cryptContext, sessionKeyContext1,\n\t\t\t\t\t\t\t\t   sessionKeyContext2, FALSE, \n\t\t\t\t\t\t\t\t   aesKeysizeOpt ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\tfprintf( outputStream, \"Export/import of %s key via user-key-based %s \"\n\t\t\t \"conventional encryption\\n  succeeded.\\n\", aesKey1Name, \n\t\t\t aesKey2Name );\n\n\treturn( TRUE );\n\t}\n\nint testConventionalExportImport( void )\n\t{\n#ifdef USE_INT_CMS\n  #ifdef USE_3DES\n\tif( !testConv3DES() )\n\t\treturn( FALSE );\n  #endif /* USE_3DES */\n\tif( !testConvAES( AES_128_128 ) )\n\t\treturn( FALSE );\n\tif( !testConvAES( AES_128_256 ) )\n\t\treturn( FALSE );\n\tif( !testConvAES( AES_256_128 ) )\n\t\treturn( FALSE );\n\tif( !testConvAES( AES_256_256 ) )\n\t\treturn( FALSE );\n\tfprintf( outputStream, \"\\n\" );\n#else\n\tfputs( \"Couldn't run conv. key export tests because CMS support has been \"\n\t\t  \"disabled,\\n\" \"skipping tests...\\n\", outputStream );\n#endif /* USE_INT_CMS */\n\n\treturn( TRUE );\n\t}\n\nint testMACExportImport( void )\n\t{\n#ifdef USE_INT_CMS\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tCRYPT_CONTEXT macContext1, macContext2;\n\tBYTE mac1[ CRYPT_MAX_HASHSIZE ], mac2[ CRYPT_MAX_HASHSIZE ];\n\tC_STR userKey = TEXT( \"This is a long user key for MAC testing\" );\n\tBYTE *buffer;\n\tint userKeyLength = paramStrlen( userKey );\n\tint status, length1, length2;\n\n\tfputs( \"Testing MAC key export/import...\\n\", outputStream );\n\n\t/* Create HMAC-SHA1 contexts for the MAC key */\n\tstatus = cryptCreateContext( &macContext1, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_HMAC_SHA1 );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( macContext1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateContext( &macContext2, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_HMAC_SHA1 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Create an encryption context to export the MAC key */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t \"\\x12\\x34\\x56\\x78\\x78\\x56\\x34\\x12\", 8 );\n\tstatus = cryptSetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Find out how big the exported key will be */\n\tstatus = cryptExportKey( NULL, 0, &length1, cryptContext, macContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptExportKey() reports exported key object \"\n\t\t\t \"will be %d bytes long\\n\", length1 );\n\tif( ( buffer = malloc( length1 ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Export the MAC information */\n\tstatus = cryptExportKey( buffer, length1, &length1, cryptContext,\n\t\t\t\t\t\t\t macContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Query the encrypted key object */\n\tstatus = cryptQueryObject( buffer, length1, &cryptObjectInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptQueryObject() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptQueryObject() reports object type %d, \"\n\t\t\t \"algorithm %d, mode %d.\\n\", cryptObjectInfo.objectType, \n\t\t\t cryptObjectInfo.cryptAlgo, cryptObjectInfo.cryptMode );\n\tdebugDump( \"kek_mac\", buffer, length1 );\n\n\t/* Recreate the MAC key by importing the encrypted key */\n\tstatus = cryptCreateContext( &decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t cryptObjectInfo.cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t   cryptObjectInfo.cryptMode );\n\tcryptSetAttributeString( decryptContext, CRYPT_CTXINFO_KEYING_SALT,\n\t\t\t\t\t\t\t cryptObjectInfo.salt, cryptObjectInfo.saltSize );\n\tstatus = cryptSetAttributeString( decryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEYING_VALUE,\n\t\t\t\t\t\t\t\t\t  userKey, userKeyLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptImportKey( buffer, length1, decryptContext,\n\t\t\t\t\t\t\t\t macContext2 );\n\t\t}\n\tfree( buffer );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the two MAC keys match */\n\tcryptEncrypt( macContext1, \"1234\", 4 );\n\tstatus = cryptEncrypt( macContext1, \"\", 0 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptEncrypt( macContext2, \"1234\", 4 );\n\t\tstatus = cryptEncrypt( macContext2, \"\", 0 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( macContext1,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t  mac1, &length1 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( macContext2,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t  mac2, &length2 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"MAC operation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( ( length1 != length2 ) || memcmp( mac1, mac2, length1 ) || \\\n\t\t!memcmp( mac1, \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 8 ) || \\\n\t\t!memcmp( mac2, \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 8 ) )\n\t\t{\n\t\tfputs( \"Data MAC'd with key1 != data MAC'd with key2.\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, macContext1, macContext2 );\n\tdestroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );\n\tfprintf( outputStream, \"Export/import of MAC key via user-key-based \"\n\t\t\t \"triple DES conventional\\n  encryption succeeded.\\n\\n\" );\n#else\n\tfputs( \"Couldn't run MAC key export tests because CMS support has been \"\n\t\t   \"disabled,\\n\" \"skipping tests...\\n\", outputStream );\n#endif /* USE_INT_CMS */\n\treturn( TRUE );\n\t}\n\n/* Test the code to export/import an encrypted key and sign data.  We're not\n   as picky with error-checking here since most of the functions have just\n   executed successfully.  We check every algorithm type since there are\n   different code paths for DLP and non-DLP PKCs */\n\nint testKeyExportImport( void )\n\t{\n#ifdef USE_INT_CMS\n\tif( !keyExportImport( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* RSA */\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ELGAMAL, NULL ) ) && \\\n\t\t!keyExportImport( \"Elgamal\", CRYPT_ALGO_ELGAMAL, CRYPT_UNUSED, CRYPT_UNUSED, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* Elgamal */\n#else\n\tfputs( \"Couldn't run PKC key export tests because CMS support has been \"\n\t\t   \"disabled,\\n\" \"skipping tests...\\n\", outputStream );\n#endif /* USE_INT_CMS */\n#ifdef USE_PGP\n\tif( !keyExportImport( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* RSA, PGP format */\n\treturn( keyExportImport( \"Elgamal\", CRYPT_ALGO_ELGAMAL, CRYPT_UNUSED, CRYPT_UNUSED, CRYPT_FORMAT_PGP ) );\n\t\t\t\t\t\t\t/* Elgamal, PGP format */\n#else\n\treturn( TRUE );\n#endif /* USE_PGP */\n\t}\n\nint testSignData( void )\n\t{\n#ifdef USE_INT_CMS\n\tif( !signData( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* RSA */\n\tif( !signData( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, TRUE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* RSA, side-channel attack protection */\n\tif( !signData( \"RSA with SHA2\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, TRUE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* RSA with SHA2 */\n\tif( !signData( \"DSA\", CRYPT_ALGO_DSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* DSA */\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) && \\\n\t\t!signData( \"ECDSA\", CRYPT_ALGO_ECDSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, FALSE, CRYPT_FORMAT_CRYPTLIB ) )\n\t\treturn( FALSE );\t/* ECDSA */\n#else\n\tfputs( \"Couldn't run signing tests because CMS support has been \"\n\t\t   \"disabled,\\n\" \"skipping tests...\\n\", outputStream );\n#endif /* USE_INT_CMS */\n#ifdef USE_PGP\n\tif( !signData( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, FALSE, CRYPT_FORMAT_PGP ) )\n\t\treturn( FALSE );\t/* RSA, PGP format */\n\treturn( signData( \"DSA\", CRYPT_ALGO_DSA, CRYPT_UNUSED, CRYPT_UNUSED, FALSE, FALSE, CRYPT_FORMAT_PGP ) );\n\t\t\t\t\t\t\t/* DSA, PGP format */\n#else\n\treturn( TRUE );\n#endif /* USE_PGP */\n\t}\n\n/* Test normal and asynchronous public-key generation */\n\nstatic int keygen( const CRYPT_ALGO_TYPE cryptAlgo, const char *algoName )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint length, status;\n\n\tfprintf( outputStream, \"Testing %s key generation...\\n\", algoName );\n\n\t/* Create an encryption context and generate a (short) key into it.\n\t   Generating a minimal-length 512 bit key is faster than the default\n\t   1-2K bit keys */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t TEXT( \"Private key\" ),\n\t\t\t\t\t\t\t paramStrlen( TEXT( \"Private key\" ) ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptGenerateKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform a test operation to check the new key */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\tcase CRYPT_ALGO_DSA:\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t{\n\t\t\tCRYPT_CONTEXT hashContext;\n\t\t\tBYTE hashBuffer[] = \"abcdefghijklmnopqrstuvwxyz\";\n\n\t\t\t/* Create an SHA hash context and hash the test buffer */\n\t\t\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tcryptEncrypt( hashContext, hashBuffer, 26 );\n\t\t\tcryptEncrypt( hashContext, hashBuffer, 0 );\n\n\t\t\t/* Sign the hashed data and check the signature */\n\t\t\tstatus = cryptCreateSignature( buffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t\t\t   cryptContext, hashContext );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptCheckSignature( buffer, length, cryptContext,\n\t\t\t\t\t\t\t\t\t\t\t  hashContext );\n\t\t\t\t}\n\n\t\t\t/* Clean up */\n\t\t\tcryptDestroyContext( hashContext );\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Sign/signature check with generated \"\n\t\t\t\t\t\t \"key failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\t{\n\t\t\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\n\t\t\t/* Test the key exchange */\n\t\t\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tstatus = cryptCreateContext( &sessionKeyContext2, \n\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, DEFAULT_CRYPT_ALGO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tcryptDestroyContext( sessionKeyContext1 );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptGenerateKey( sessionKeyContext1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tstatus = cryptExportKey( buffer, BUFFER_SIZE, &length, \n\t\t\t\t\t\t\t\t\t cryptContext, sessionKeyContext1 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptImportKey( buffer, length, cryptContext,\n\t\t\t\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\t\t}\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1,\n\t\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\t\tfprintf( outputStream, \"Key exchange with generated key \"\n\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Make sure that the two keys match */\n\t\t\tif( !compareSessionKeys( sessionKeyContext1, \n\t\t\t\t\t\t\t\t\t sessionKeyContext2 ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Clean up */\n\t\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1,\n\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase CRYPT_ALGO_DH:\n\t\tcase CRYPT_ALGO_ECDH:\n\t\t\t{\nKLUDGE_WARN( \"DH/ECDH test because of absence of DH/ECDH key exchange mechanism\" );\ncryptDestroyContext( cryptContext );\nreturn( TRUE );\n\n#if 0\t\t/* Get rid if unreachable-code warnings */\n\t\t\tCRYPT_CONTEXT dhContext;\n\t\t\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\n\t\t\t/* Test the key exchange */\n\t\t\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptCreateContext( &sessionKeyContext2, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, DEFAULT_CRYPT_ALGO );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptCreateContext( &dhContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_DH );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\tstatus = cryptExportKey( buffer, BUFFER_SIZE, &length, \n\t\t\t\t\t\t\t\t\t cryptContext, sessionKeyContext1 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptImportKey( buffer, length, dhContext,\n\t\t\t\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptExportKey( buffer, BUFFER_SIZE, &length, \n\t\t\t\t\t\t\t\t\t\t dhContext, sessionKeyContext2 );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptImportKey( buffer, length, cryptContext,\n\t\t\t\t\t\t\t\t\t\t sessionKeyContext1 );\n\t\t\t\t}\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tcryptDestroyContext( dhContext );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1,\n\t\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\t\tfprintf( outputStream, \"Key exchange with generated key \"\n\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Make sure that the two keys match */\n\t\t\tif( !compareSessionKeys( sessionKeyContext1, \n\t\t\t\t\t\t\t\t\t sessionKeyContext2 ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Clean up */\n\t\t\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1,\n\t\t\t\t\t\t\t sessionKeyContext2 );\n\t\t\tbreak;\n#endif /* 0 */\n\t\t\t}\n\n\t\tdefault:\n\t\t\tfprintf( outputStream, \"Unexpected encryption algorithm %d \"\n\t\t\t\t\t \"found, line %d.\\n\", cryptAlgo, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"%s key generation succeeded.\\n\", algoName );\n\treturn( TRUE );\n\t}\n\nint testKeygen( void )\n\t{\n\tif( !keygen( CRYPT_ALGO_RSA, \"RSA\" ) )\n\t\treturn( FALSE );\n\tif( !keygen( CRYPT_ALGO_DSA, \"DSA\" ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ELGAMAL, NULL ) ) && \\\n\t\t!keygen( CRYPT_ALGO_ELGAMAL, \"Elgamal\" ) )\n\t\treturn( FALSE );\n\tif( !keygen( CRYPT_ALGO_DH, \"DH\" ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) && \\\n\t\t!keygen( CRYPT_ALGO_ECDSA, \"ECDSA\" ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDH, NULL ) ) && \\\n\t\t!keygen( CRYPT_ALGO_ECDH, \"ECDH\" ) )\n\t\treturn( FALSE );\n\tfprintf( outputStream, \"\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Test handling of injected faults */\n\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\ntypedef enum { TEST_SIGN_RSA, TEST_SIGN_ECDSA, TEST_KEYEX_CONV, \n\t\t\t   TEST_KEYEX_PKC, TEST_PRF } TEST_TYPE;\n\nstatic int testDebugCheck( const TEST_TYPE testType, const FAULT_TYPE testFaultType )\n\t{\n\tint status;\n\n\tcryptSetFaultType( testFaultType );\n\tswitch( testType )\n\t\t{\n\t\tcase TEST_SIGN_RSA:\n\t\t\tstatus = signData( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, FALSE, FALSE, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CRYPTLIB );\n\t\t\tbreak;\n\t\t\n\t\tcase TEST_SIGN_ECDSA:\n\t\t\tstatus = signData( \"ECDSA\", CRYPT_ALGO_ECDSA, CRYPT_UNUSED, \n\t\t\t\t\t\t\t   CRYPT_UNUSED, FALSE, FALSE, \n\t\t\t\t\t\t\t   CRYPT_FORMAT_CRYPTLIB );\n\t\t\tbreak;\n\t\t\n\t\tcase TEST_KEYEX_CONV:\n\t\t\tstatus = testConvAES( AES_128_128 );\n\t\t\tbreak;\n\t\t\n\t\tcase TEST_KEYEX_PKC:\n\t\t\tstatus = keyExportImport( \"RSA\", CRYPT_ALGO_RSA, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_UNUSED, CRYPT_FORMAT_CRYPTLIB );\n\t\t\tbreak;\n\t\t\n\t\tcase TEST_PRF:\n\t\t\tstatus = testConvAES( AES_128_128 );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tassert( 0 );\n\t\t}\n\tif( status )\n\t\t{\n\t\tcryptSetFaultType( FAULT_NONE );\n\t\tfputs( \"  (This test should have led to an enveloping failure but \"\n\t\t\t   \"didn't, test has\\n   failed).\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* These tests are supposed to fail, so if this happens then the overall \n\t   test has succeeded */\n\tfputs( \"  (This test checks error handling, so the failure response is \"\n\t\t   \"correct).\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* CONFIG_FAULTS && Debug */\n\nint testMidLevelDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !testDebugCheck( TEST_SIGN_RSA, FAULT_MECH_CORRUPT_HASH ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_SIGN_RSA, FAULT_MECH_CORRUPT_SIG ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_SIGN_ECDSA, FAULT_MECH_CORRUPT_HASH ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_SIGN_ECDSA, FAULT_MECH_CORRUPT_SIG ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_KEYEX_CONV, FAULT_MECH_CORRUPT_KEY ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_KEYEX_PKC, FAULT_MECH_CORRUPT_KEY ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_PRF, FAULT_MECH_CORRUPT_SALT ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_PRF, FAULT_MECH_CORRUPT_ITERATIONS ) )\n\t\treturn( FALSE );\n\tif( !testDebugCheck( TEST_PRF, FAULT_MECH_CORRUPT_PRFALGO ) )\n\t\treturn( FALSE );\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n#endif /* TEST_MIDLEVEL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tRandom Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_RANDOM\n\n/* Test the randomness gathering routines */\n\nint testRandomRoutines( void )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\tfputs( \"Testing randomness routines.  This may take a few seconds...\\n\",\n\t\t   outputStream );\n\n\t/* Create an encryption context to generate a key into */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptGenerateKey( cryptContext );\n\tcryptDestroyContext( cryptContext );\n\n\t/* Check whether we got enough randomness */\n\tif( status == CRYPT_ERROR_RANDOM )\n\t\t{\n\t\tfputs( \"The randomness-gathering routines can't acquire enough random information to\", \n\t\t\t   outputStream );\n\t\tfputs( \"allow key generation and public-key encryption to function.  You will need to\", \n\t\t\t   outputStream );\n\t\tfputs( \"change the randomness-polling code or reconfigure your system to allow the\", \n\t\t\t   outputStream );\n\t\tfputs( \"randomness-gathering routines to function.  The code to change can be found\", \n\t\t\t   outputStream );\n\t\tfputs( \"in random/<osname>.c\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Randomness-gathering self-test succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_RANDOM */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHigh-level Routines Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_HIGHLEVEL\n\n/* Test the code to export/import a CMS key */\n\nint testKeyExportImportCMS( void )\n\t{\n\tCRYPT_OBJECT_INFO cryptObjectInfo;\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tCRYPT_CONTEXT sessionKeyContext1, sessionKeyContext2;\n\tBYTE *buffer;\n\tint status, length;\n\n\tfputs( \"Testing CMS public-key export/import...\", outputStream );\n\n\t/* Get a private key with a certificate chain attached */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't read private key, status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create encryption contexts for the exported and imported session \n\t   keys */\n\tstatus = cryptCreateContext( &sessionKeyContext1, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( sessionKeyContext1 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateContext( &sessionKeyContext2, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Find out how big the exported key will be */\n\tstatus = cryptExportKeyEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,\n\t\t\t\t\t\t\t   cryptContext, sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptExportKeyEx() reports CMS exported key \"\n\t\t\t \"will be %d bytes long\\n\", length );\n\tif( ( buffer = malloc( length ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Export the key */\n\tstatus = cryptExportKeyEx( buffer, length, &length, CRYPT_FORMAT_SMIME,\n\t\t\t\t\t\t\t   cryptContext, sessionKeyContext1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Query the encrypted key object */\n\tstatus = cryptQueryObject( buffer, length, &cryptObjectInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptQueryObject() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptQueryObject() reports object type %d, \"\n\t\t\t \"algorithm %d.\\n\", cryptObjectInfo.objectType, \n\t\t\t cryptObjectInfo.cryptAlgo );\n\tmemset( &cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );\n\tdebugDump( \"cms_ri\", buffer, length );\n\n\t/* Import the encrypted key and load it into the session key context */\n\tstatus = cryptImportKey( buffer, length, cryptContext,\n\t\t\t\t\t\t\t sessionKeyContext2 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptImportKey() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the two keys match */\n\tif( !compareSessionKeys( sessionKeyContext1, sessionKeyContext2 ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, sessionKeyContext1, sessionKeyContext2 );\n\tcryptDestroyContext( cryptContext );\n\tfputs( \"Export/import of CMS session key succeeded.\\n\", outputStream );\n\tfree( buffer );\n\treturn( TRUE );\n\t}\n\n/* Test the code to create an CMS signature */\n\nstatic const CERT_DATA cmsAttributeData[] = {\n\t/* We have to be careful when setting CMS attributes because most are \n\t   never used by anything so they're only available of use of obscure \n\t   attributes is enabled */\n#ifdef USE_CMSATTR_OBSCURE\n\t/* Content type */\n\t{ CRYPT_CERTINFO_CMS_CONTENTTYPE, IS_NUMERIC, CRYPT_CONTENT_SPCINDIRECTDATACONTEXT },\n\n\t/* Odds and ends.  We can't (portably) set the opusInfo name since it's\n\t   a Unicode string so we only add this one under Windows */\n  #ifdef __WINDOWS__\n\t{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_NAME, IS_WCSTRING, 0, L\"Program v3.0 SP2\" },\n  #endif /* __WINDOWS__ */\n\t{ CRYPT_CERTINFO_CMS_SPCOPUSINFO_URL, IS_STRING, 0, TEXT( \"http://bugs-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_CMS_SPCSTMT_COMMERCIALCODESIGNING, IS_NUMERIC, CRYPT_UNUSED },\n#else\n\t/* Content type */\n\t{ CRYPT_CERTINFO_CMS_CONTENTTYPE, IS_NUMERIC, CRYPT_CONTENT_ENCRYPTEDDATA },\n#endif /* USE_CMSATTR_OBSCURE */\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nstatic int signDataCMS( const char *description,\n\t\t\t\t\t\tconst CRYPT_CERTIFICATE signingAttributes,\n\t\t\t\t\t\tconst BOOLEAN isCustomAttributes )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cmsAttributes = signingAttributes;\n\tCRYPT_CONTEXT signContext, hashContext;\n\tBYTE *buffer, hashBuffer[] = \"abcdefghijklmnopqrstuvwxyz\";\n\tint status, length;\n\n\tfprintf( outputStream, \"Testing %s...\\n\", description );\n\n\t/* Create an SHA hash context and hash the test buffer */\n\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA1 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptEncrypt( hashContext, hashBuffer, 26 );\n\tcryptEncrypt( hashContext, hashBuffer, 0 );\n\n\t/* Get a private key with a certificate chain attached */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  USER_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &signContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't read private key, status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Find out how big the signature will be */\n\tstatus = cryptCreateSignatureEx( NULL, 0, &length, CRYPT_FORMAT_SMIME,\n\t\t\t\t\t\t\t\t\t signContext, hashContext, \n\t\t\t\t\t\t\t\t\t cmsAttributes );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSignatureEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"cryptCreateSignatureEx() reports CMS signature \"\n\t\t\t \"will be %d bytes long\\n\", length );\n\tif( ( buffer = malloc( length ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Sign the hashed data */\n\tstatus = cryptCreateSignatureEx( buffer, length, &length,\n\t\t\t\t\t\t\t\t\t CRYPT_FORMAT_SMIME, signContext,\n\t\t\t\t\t\t\t\t\t hashContext, cmsAttributes );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSignatureEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\tdebugDump( ( signingAttributes == CRYPT_USE_DEFAULT ) ? \\\n\t\t\t\t\t\"cms_sigd\" : \\\n\t\t\t   ( isCustomAttributes ) ? \"cms_sigc\" : \"cms_sig\", \n\t\t\t   buffer, length );\n\n\t/* Check the signature on the hash */\n\tstatus = cryptCheckSignatureEx( buffer, length, signContext, hashContext,\n\t\t\t( cmsAttributes == CRYPT_USE_DEFAULT ) ? NULL : &cmsAttributes );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCheckSignatureEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tfree( buffer );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Display the signing attributes */\n\tif( cmsAttributes != CRYPT_USE_DEFAULT )\n\t\tprintCertInfo( cmsAttributes );\n\n\t/* Clean up */\n\tcryptDestroyContext( hashContext );\n\tcryptDestroyContext( signContext );\n\tcryptDestroyCert( cmsAttributes );\n\tfprintf( outputStream, \"Generation and checking of %s succeeded.\\n\\n\", \n\t\t\t description );\n\tfree( buffer );\n\treturn( TRUE );\n\t}\n\nint testSignDataCMS( void )\n\t{\n\tCRYPT_CERTIFICATE cmsAttributes;\n    const BYTE *extensionData = ( BYTE * ) \"\\x0C\\x04Test\";\n\tint value, status;\n\n\t/* First test the basic CMS signature with default attributes (content\n\t   type, signing time, and message digest) */\n\tif( !signDataCMS( \"CMS signature\", CRYPT_USE_DEFAULT, FALSE ) )\n\t\treturn( FALSE );\n\n\t/* Create some CMS attributes and sign the data with the user-defined\n\t   attributes */\n\tstatus = cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tif( cryptStatusError( status ) || \\\n\t\t!addCertFields( cmsAttributes, cmsAttributeData, __LINE__ ) )\n\t\treturn( FALSE );\n\tstatus = signDataCMS( \"complex CMS signature\", cmsAttributes, FALSE );\n\tcryptDestroyCert( cmsAttributes );\n\tif( !status )\n\t\treturn( status );\n\n\t/* Create some custom CMS attributes and sign those too.  In order to do\n\t   this we have to set the CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES\n\t   configuration option */\n\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \n\t\t\t\t\t\t\t\t&value );\n\tstatus = cryptCreateCert( &cmsAttributes, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CMS_ATTRIBUTES );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptAddCertExtension( cmsAttributes, \"1.2.3.4.5\", \n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED, extensionData, 6 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = signDataCMS( \"CMS signature with custom attributes\", \n\t\t\t\t\t\t\t  cmsAttributes, TRUE );\n\t\t}\n\tcryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t   CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, value );\n\tcryptDestroyCert( cmsAttributes );\n\tif( !status )\n\t\treturn( status );\n\treturn( status );\n\t}\n\n#endif /* TEST_HIGHLEVEL */\n"
  },
  {
    "path": "deps/cl345/test/keydbx.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib Database Keyset Test Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n#include <ctype.h>\n\n#ifdef TEST_KEYSET\n\n/* A certificate containing an email address */\n\n#define EMAILADDR_CERT_NO\t14\n\n/* A certificate chain that can be added to a database keyset and\n   looked up again afterwards */\n\n#define CERT_CHAIN_NO\t\t5\n\n/* Some LDAP keyset names and names of probably-present certs and CRLs.\n   These keysets (and their contents) come and go, so we have a variety of\n   them and try them in turn until something works.  There's a list of more\n   LDAP servers at http://www.dante.net/np/pdi.html, but none of these are\n   known to contain certificates.\n\n   Note that the following strings have to be given on one line in order for\n   the widechar conversion voodoo to work */\n\nstatic const struct {\n\tconst C_STR url;\t\t\t/* LDAP URL for keyset */\n\tconst char *asciiURL;\t\t/* URL in ASCII */\n\tconst C_STR certName;\t\t/* DN for certificate and CRL */\n\tconst C_STR crlName;\n\t} ldapUrlInfo[] = {\n\t{ 0 },\n\t{ TEXT( \"ldap://ldap.diginotar.nl:389\" ), \"ldap.diginotar.nl\",\n\t\t\t/* Long URL form also tests LDAP URL-parsing code.  This was \n\t\t\t   the genuine original LDAP test URL, it's kept in here now \n\t\t\t   purely for giggles */\n\t  TEXT( \"cn=Root Certificaat Productie, o=DigiNotar Root,c=NL\" ),\n\t  TEXT( \"CN=CRL Productie,O=DigiNotar CRL,C=NL\" ) },\n\t{ TEXT( \"ds.katalog.posten.se\" ), \"ds.katalog.posten.se\",\n\t  TEXT( \"cn=Posten CertPolicy_eIDKort_1 CA_nyckel_1, o=Posten_Sverige_AB 556451-4148, c=SE\" ),\n\t  TEXT( \"cn=Posten CertPolicy_eIDKort_1 CA_nyckel_1, o=Posten_Sverige_AB 556451-4148, c=SE\" ) },\n\t{ TEXT( \"ldap2.zebsign.com\" ), \"ldap2.zebsign.com\",\n\t  TEXT( \"pssUniqueIdentifier=24090, CN=First ZebSign Community ID CA, O=ZebSign - 983163432, C=NO\" ) }\n\t};\n\n#define LDAP_SERVER_NO\t\t1\n#define LDAP_ALT_SERVER_NO\t2\t/* Secondary svr.if main server unavailable */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tDatabase Keyset Read/Write Tests\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Certificate with fields designed to cause problems for some keysets */\n\nstatic const CERT_DATA sqlCertData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"x'); DROP TABLE certificates; --\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"x' OR 1=1; DROP TABLE certificates; --\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"x'; DROP TABLE certificates; --\" ) },\n\n\t/* Other information */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* Read/write a certificate from a public-key keyset.  Returns\n   CRYPT_ERROR_NOTAVAIL if this keyset type isn't available from this\n   cryptlib build, CRYPT_ERROR_FAILED if the keyset/data source access\n   failed */\n\nenum { READ_OPTION_NORMAL, READ_OPTION_MULTIPLE };\n\nstatic int checkKeysetCRL( const CRYPT_KEYSET cryptKeyset,\n\t\t\t\t\t\t   const CRYPT_CERTIFICATE cryptCert,\n\t\t\t\t\t\t   const BOOLEAN isCertChain )\n\t{\n\tint errorLocus, status;\n\n\t/* Perform a revocation check against the CRL in the keyset */\n\tprintf( \"Checking certificate%s against CRL.\\n\", \n\t\t\tisCertChain ? \" chain\" : \"\" );\n\tstatus = cryptCheckCert( cryptCert, cryptKeyset );\n\tif( cryptStatusOK( status ) )\n\t\treturn( TRUE );\n\tif( isCertChain )\n\t\t{\n\t\t/* Checking a chain against a keyset doesn't really make sense, so\n\t\t   this should be rejected */\n\t\tif( status == CRYPT_ERROR_PARAM2 )\n\t\t\treturn( TRUE );\n\n\t\tprintf( \"Check of certificate chain against keyset returned %d, \"\n\t\t\t\t\"should have been %d.\\n\", status, CRYPT_ERROR_PARAM2 );\n\t\treturn( FALSE );\n\t\t}\n\tif( status != CRYPT_ERROR_INVALID )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptCheckCert() (for CRL in \"\n\t\t\t\t\t\t\t  \"keyset)\", status, __LINE__ ) );\n\t\t}\n\n\t/* If the certificate has expired then it'll immediately be reported as \n\t   invalid without bothering to check the CRL, so we have to perform the \n\t   check in oblivious mode to avoid the expiry check */\n\tstatus = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_ERRORLOCUS, \n\t\t\t\t\t\t\t\t&errorLocus );\n\tif( cryptStatusOK( status ) && errorLocus == CRYPT_CERTINFO_VALIDTO )\n\t\t{\n\t\tint complianceValue;\n\n\t\tputs( \"  (Certificate has already expired, re-checking in oblivious \"\n\t\t\t  \"mode).\" );\n\t\t( void ) cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t\t\t\t&complianceValue );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n\t\tstatus = cryptCheckCert( cryptCert, cryptKeyset );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   complianceValue );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( extErrorExit( cryptKeyset, \"cryptCheckCert() (for CRL in \"\n\t\t\t\t\t\t\t  \"keyset)\", status, __LINE__ ) );\n\n\treturn( TRUE );\n\t}\n\nstatic int testKeysetRead( const CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t\t   const C_STR keysetName,\n\t\t\t\t\t\t   const CRYPT_KEYID_TYPE keyType,\n\t\t\t\t\t\t   const C_STR keyName,\n\t\t\t\t\t\t   const CRYPT_CERTTYPE_TYPE type,\n\t\t\t\t\t\t   const int option )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tBOOLEAN isCertChain = FALSE;\n\tint value, status;\n\n\t/* Open the keyset with a check to make sure this access method exists\n\t   so we can return an appropriate error message */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Read the certificate from the keyset */\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, keyType, keyName );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The access to network-accessible keysets can be rather\n\t\t   temperamental and can fail at this point even though it's not a\n\t\t   fatal error.  The calling code knows this and will continue the\n\t\t   self-test with an appropriate warning, so we explicitly clean up\n\t\t   after ourselves to make sure we don't get a CRYPT_ORPHAN on\n\t\t   shutdown */\n\t\tif( keysetType == CRYPT_KEYSET_HTTP && \\\n\t\t\tstatus == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* 404's are relatively common, and non-fatal */\n\t\t\textErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status, __LINE__ );\n\t\t\tputs( \"  (404 is a common HTTP error, and non-fatal).\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\n\t/* Make sure that we got what we were expecting */\n\tstatus = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) || ( value != type ) )\n\t\t{\n\t\tprintf( \"Expecting certificate object type %d, got %d, line %d.\", \n\t\t\t\ttype, value, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( value == CRYPT_CERTTYPE_CERTCHAIN )\n\t\tisCertChain = TRUE;\n\tif( value == CRYPT_CERTTYPE_CERTCHAIN || value == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\tvalue = 0;\n\t\tcryptSetAttribute( cryptCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\t\tdo\n\t\t\t{\n\t\t\tvalue++;\n\t\t\t}\n\t\twhile( cryptSetAttribute( cryptCert,\n\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\tprintf( isCertChain ? \"Certificate chain length = %d.\\n\" : \\\n\t\t\t\t\t\t\t  \"CRL has %d entries.\\n\", value );\n\t\t}\n\n\t/* Check the certificate against the CRL.  Any kind of error is a \n\t   failure since the certificate isn't in the CRL */\n\tif( keysetType != CRYPT_KEYSET_LDAP && \\\n\t\tkeysetType != CRYPT_KEYSET_HTTP )\n\t\t{\n\t\tif( !checkKeysetCRL( cryptKeyset, cryptCert, isCertChain ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* If we're reading multiple certs using the same (cached) query type,\n\t   try re-reading the certificate.  This can't be easily tested from the\n\t   outside because it's database back-end specific, so it'll require\n\t   attaching a debugger to the read code to make sure that the cacheing\n\t   is working as required */\n\tif( option == READ_OPTION_MULTIPLE )\n\t\t{\n\t\tint i;\n\n\t\tfor( i = 0; i < 3; i++ )\n\t\t\t{\n\t\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, keyType,\n\t\t\t\t\t\t\t\t\t\tkeyName );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"cryptGetPublicKey() with cached query failed with \"\n\t\t\t\t\t\t\"error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t\t}\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetClose() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int testKeysetWrite( const CRYPT_KEYSET_TYPE keysetType,\n\t\t\t\t\t\t\tconst C_STR keysetName,\n\t\t\t\t\t\t\tconst BOOLEAN useAltCert )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT pubKeyContext, privKeyContext;\n\tC_CHR filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tC_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint length, status;\n\n\t/* Import the certificate from a file - this is easier than creating one\n\t   from scratch.  We use one of the later certs in the test set, since\n\t   this contains an email address, which the earlier ones don't */\n\tif( useAltCert )\n\t\t{\n\t\tstatus = getPublicKey( &cryptCert, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t\t EMAILADDR_CERT_NO );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read certificate from file, status %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the certificate does actually contain an email \n\t   address */\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t  name, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Certificate doesn't contain an email address and can't be \"\n\t\t\t\t\"used for testing,\\n  line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the database keyset with a check to make sure this access\n\t   method exists so we can return an appropriate error message.  If the\n\t   database table already exists, this will return a duplicate data\n\t   error so we retry the open with no flags to open the existing database\n\t   keyset for write access */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusOK( status ) )\n\t\tprintf( \"Created new certificate database '%s'.\\n\", keysetName );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access isn't available, return a special error\n\t\t   code to indicate that the test wasn't performed, but that this\n\t\t   isn't a reason to abort processing */\n\t\tcryptDestroyCert( cryptCert );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,\n\t\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyCert( cryptCert );\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Write the key to the database */\n\tputs( \"Adding certificate.\" );\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\t/* The key is already present, delete it and retry the write */\n\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, name, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n#ifdef UNICODE_STRINGS\n\t\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\t\tname[ length ] = TEXT( '\\0' );\n\t\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptDeleteKey()\", status,\n\t\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPublicKey()\", status, __LINE__ );\n\n\t\t/* LDAP writes can fail due to the chosen directory not supporting the\n\t\t   schema du jour, so we're a bit more careful about cleaning up since\n\t\t   we'll skip the error and continue processing */\n\t\tcryptDestroyCert( cryptCert );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Add a second certificate with C=US so that we've got enough certs to \n\t   properly exercise the query code.  This certificate is highly unusual \n\t   in that it doesn't have a DN, so we have to move up the DN looking \n\t   for higher-up values, in this case the OU */\n\tif( keysetType != CRYPT_KEYSET_LDAP )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 2 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't read certificate from file, status %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, name, &length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_ORGANIZATIONALUNITNAME, name, \n\t\t\t\t\t\t\t&length );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n#ifdef UNICODE_STRINGS\n\t\t\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\t\t\tname[ length ] = TEXT( '\\0' );\n\t\t\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\",\n\t\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\n\t/* Add a third certificate with a DN that'll cause problems for some \n\t   storage technologies */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &pubKeyContext, &privKeyContext ) )\n\t\treturn( FALSE );\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, pubKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tif( !addCertFields( cryptCert, sqlCertData, __LINE__ ) )\n\t\treturn( FALSE );\n\tstatus = cryptSignCert( cryptCert, privKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptCert, \"cryptSignCert()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tdestroyContexts( CRYPT_UNUSED, pubKeyContext, privKeyContext );\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The key is already present, delete it and retry the write */\n\t\tstatus = cryptGetAttributeString( cryptCert,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, name, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n#ifdef UNICODE_STRINGS\n\t\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\t\tname[ length ] = TEXT( '\\0' );\n\t\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptDeleteKey()\", status,\n\t\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Now try the same thing with a CRL.  This code also tests the\n\t   duplicate-detection mechanism, if we don't get a duplicate error\n\t   there's a problem */\n\tputs( \"Adding CRL.\" );\n\tstatus = importCertFromTemplate( &cryptCert, CRL_FILE_TEMPLATE, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read CRL from file, status %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( TRUE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tprintf( \"Addition of duplicate item to keyset failed to produce \"\n\t\t\t    \"CRYPT_ERROR_DUPLICATE, status %d, line %d.\\n\", status,\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Finally, try it with a certificate chain */\n\tputs( \"Adding certificate chain.\" );\n\tfilenameParamFromTemplate( filenameBuffer, CERTCHAIN_FILE_TEMPLATE, \n\t\t\t\t\t\t\t   CERT_CHAIN_NO );\n\tstatus = importCertFile( &cryptCert, filenameBuffer );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read certificate chain from file, status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* In addition to the other certs we also add the generic user \n\t   certificate, which is used later in other tests.  Since it may have \n\t   been added earlier we try and delete it first (we can't use the \n\t   existing version since the issuerAndSerialNumber won't match the one \n\t   in the private-key keyset) */\n\tstatus = getPublicKey( &cryptCert, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read user certificate from file, status %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t  name, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\tname[ length ] = TEXT( '\\0' );\n\tdo\n\t\t{\n\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );\n\t\t}\n\twhile( cryptStatusOK( status ) );\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\t/* This can occur if a database keyset is defined but hasn't been\n\t\t   initialised yet so the necessary tables don't exist, it can be\n\t\t   opened but an attempt to add a key will return a not found error\n\t\t   since it's the table itself rather than any item within it that\n\t\t   isn't being found */\n\t\tstatus = CRYPT_OK;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Finally, if ECC is enabled we also add ECC certificates that are used\n\t   later in other tests */\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\t\tvoid *fileNamePtr = filenameBuffer;\n\n\t\t/* Add the P256 certificate */\n\t\tfilenameFromTemplate( filenameBuffer, \n\t\t\t\t\t\t\t  SERVER_ECPRIVKEY_FILE_TEMPLATE, 256 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPublicKey( &cryptCert, fileNamePtr,\n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't read user certificate from file, status %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\", status,\n\t\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\n\t\t/* Add the P384 certificate */\n\t\tfilenameFromTemplate( filenameBuffer, \n\t\t\t\t\t\t\t  SERVER_ECPRIVKEY_FILE_TEMPLATE, 384 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPublicKey( &cryptCert, fileNamePtr,\n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't read user certificate from file, status %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\tif( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\", status,\n\t\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\n\t/* Make sure the deletion code works properly.  This is an artifact of\n\t   the way RDBMS' work, the delete query can execute successfully but\n\t   not delete anything so we make sure the glue code correctly\n\t   translates this into a CRYPT_DATA_NOTFOUND */\n\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t TEXT( \"Mr.Not Appearing in this Keyset\" ) );\n\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tputs( \"Attempt to delete a nonexistant key reports success, the \"\n\t\t\t  \"database backend glue\\ncode needs to be fixed to handle this \"\n\t\t\t  \"correctly.\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetClose() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Perform a general keyset query */\n\nint testQuery( const CRYPT_KEYSET_TYPE keysetType, const C_STR keysetName )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint count = 0, status;\n\n\t/* Open the database keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Send the query to the database and read back the results */\n\tstatus = cryptSetAttributeString( cryptKeyset, CRYPT_KEYINFO_QUERY,\n\t\t\t\t\t\t\t\t\t  TEXT( \"$C='US'\" ),\n\t\t\t\t\t\t\t\t\t  paramStrlen( TEXT( \"$C='US'\" ) ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"Keyset query\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tdo\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert;\n\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert,\n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NONE, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tcount++;\n\t\t\tcryptDestroyCert( cryptCert );\n\t\t\t}\n\t\t}\n\twhile( cryptStatusOK( status ) );\n\tif( cryptStatusError( status ) && status != CRYPT_ERROR_COMPLETE )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tif( count < 2 )\n\t\t{\n\t\tputs( \"Only one certificate was returned, this indicates that the \"\n\t\t\t  \"database backend\\nglue code isn't processing ongoing queries \"\n\t\t\t  \"correctly.\" );\n\t\treturn( FALSE );\n\t\t}\n\tprintf( \"%d certificate(s) matched the query.\\n\", count );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetClose() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Read/write/query a certificate from a database keyset */\n\nint testReadCert( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tC_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ], email[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tC_CHR filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint length, status;\n\n\t/* Get the DN from one of the test certs (the one that we wrote to the\n\t   keyset earlier with testKeysetWrite() */\n\tstatus = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t EMAILADDR_CERT_NO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read certificate from file, status %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t  name, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tname[ length ] = TEXT( '\\0' );\n\t\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_EMAIL,\n\t\t\t\t\t\t\t\t\t\t  email, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint i;\n\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\temail[ length ] = TEXT( '\\0' );\n\n\t\t/* Mess up the case to make sure that case-insensitive matching is\n\t\t   working */\n\t\tfor( i = 0; i < length; i++ )\n\t\t\t{\n\t\t\tif( i & 1 )\n\t\t\t\temail[ i ] = toupper( email[ i ] );\n\t\t\telse\n\t\t\t\temail[ i ] = tolower( email[ i ] );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\treturn( extErrorExit( cryptCert, \"cryptGetAttributeString()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\tputs( \"Testing certificate database read...\" );\n\tstatus = testKeysetRead( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t \t\t\t\t\t\t CRYPT_KEYID_NAME, name,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t\t\t READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Database keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tputs( \"This is probably because you haven't set up a database or \"\n\t\t\t  \"data source for use\\nas a key database.  For this test to \"\n\t\t\t  \"work, you need to set up a database/data\\nsource with the \"\n\t\t\t  \"name '\" DATABASE_KEYSET_NAME_ASCII \"'.\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( !status )\n\t\treturn( FALSE );\n\tputs( \"Reading certs using cached query.\" );\n\tstatus = testKeysetRead( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t \t\t\t\t\t\t CRYPT_KEYID_EMAIL, email,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t\t\t READ_OPTION_MULTIPLE );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Get the DN from one of the test certificate chains */\n\tfilenameParamFromTemplate( filenameBuffer, CERTCHAIN_FILE_TEMPLATE, \n\t\t\t\t\t\t\t   CERT_CHAIN_NO );\n\tstatus = importCertFile( &cryptCert, filenameBuffer );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't read certificate chain from file, status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t  name, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tname[ length ] = TEXT( '\\0' );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\n\t/* Now read the complete certificate chain */\n\tputs( \"Reading complete certificate chain.\" );\n\tstatus = testKeysetRead( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t \t\t\t\t\t\t CRYPT_KEYID_NAME, name,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTCHAIN, READ_OPTION_NORMAL );\n\tif( !status )\n\t\treturn( FALSE );\n\tputs( \"Certificate database read succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testWriteCert( void )\n\t{\n\tint status;\n\n\tputs( \"Testing certificate database write...\" );\n\tstatus = testKeysetWrite( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME, \n\t\t\t\t\t\t\t  FALSE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Database keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tprintf( \"This may be because you haven't set up a data source \"\n\t\t\t\t\"called '\" DATABASE_KEYSET_NAME_ASCII \"'\\nof type %d that \"\n\t\t\t\t\"can be used for the certificate store.  You can \"\n\t\t\t\t\"configure\\nthe data source type and name using the \"\n\t\t\t\t\"DATABASE_KEYSET_xxx settings in\\ntest/test.h.\\n\",\n\t\t\t\tDATABASE_KEYSET_TYPE );\n\t\treturn( FALSE );\n\t\t}\n\tif( !status )\n\t\treturn( FALSE );\n\tstatus = testKeysetWrite( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME, \n\t\t\t\t\t\t\t  TRUE );\n\tif( !status )\n\t\treturn( FALSE );\n\tputs( \"Certificate database write succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testKeysetQuery( void )\n\t{\n\tint status;\n\n\tputs( \"Testing general certificate database query...\" );\n\tstatus = testQuery( DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Database keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tputs( \"This is probably because you haven't set up a database or \"\n\t\t\t  \"data source for use\\nas a key database.  For this test to \"\n\t\t\t  \"work, you need to set up a database/data\\nsource with the \"\n\t\t\t  \"name '\" DATABASE_KEYSET_NAME_ASCII \"'.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( !status )\n\t\treturn( FALSE );\n\tputs( \"Certificate database query succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Read/write/query a certificate from an LDAP keyset */\n\nint testReadCertLDAP( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tstatic const char *ldapErrorString = \\\n\t\t\"LDAP directory read failed, probably because the standard being \"\n\t\t\"used by the\\ndirectory server differs from the one used by the \"\n\t\t\"LDAP client software (pick\\na standard, any standard).  If you \"\n\t\t\"know how the directory being used is\\nconfigured, you can try \"\n\t\t\"changing the CRYPT_OPTION_KEYS_LDAP_xxx settings to\\nmatch those \"\n\t\t\"used by the server.  Processing will continue without treating\\n\"\n\t\t\"this as a fatal error.\\n\";\n\tconst C_STR ldapKeysetName = ldapUrlInfo[ LDAP_SERVER_NO ].url;\n\tchar ldapAttribute1[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tchar ldapAttribute2[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tchar certName[ CRYPT_MAX_TEXTSIZE ], caCertName[ CRYPT_MAX_TEXTSIZE ];\n\tchar crlName[ CRYPT_MAX_TEXTSIZE ];\n\tint length, status;\n\n\t/* LDAP directories come and go, check to see which one is currently\n\t   around */\n\tputs( \"Testing LDAP directory availability...\" );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_LDAP,\n\t\t\t\t\t\t\t  ldapKeysetName, CRYPT_KEYOPT_READONLY );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* LDAP keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_OPEN )\n\t\t{\n\t\tprintf( \"%s not available for some odd reason,\\n  trying \"\n\t\t\t\t\"alternative directory instead...\\n\", \n\t\t\t\tldapUrlInfo[ LDAP_SERVER_NO ].asciiURL );\n\t\tldapKeysetName = ldapUrlInfo[ LDAP_ALT_SERVER_NO ].url;\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_LDAP, ldapKeysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\t}\n\tif( status == CRYPT_ERROR_OPEN )\n\t\t{\n\t\tprintf( \"%s not available either.\\n\",\n\t\t\t\tldapUrlInfo[ LDAP_ALT_SERVER_NO ].asciiURL );\n\t\tputs( \"None of the test LDAP directories are available.  If you need \"\n\t\t\t  \"to test the\\nLDAP capabilities, you need to set up an LDAP \"\n\t\t\t  \"directory that can be used\\nfor the certificate store.  You \"\n\t\t\t  \"can configure the LDAP directory using the\\nLDAP_KEYSET_xxx \"\n\t\t\t  \"settings in test/test.h.  Alternatively, if this message\\n\"\n\t\t\t  \"took a long time to appear you may be behind a firewall that \"\n\t\t\t  \"blocks LDAP\\ntraffic.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS,\n\t\t\t\t\t\t\t\t\t  ldapAttribute1, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tldapAttribute1[ length ] = TEXT( '\\0' );\n\t\tstatus = cryptGetAttributeString( cryptKeyset,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS,\n\t\t\t\t\t\t\t\t\t\t  ldapAttribute2, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tldapAttribute2[ length ] = TEXT( '\\0' );\n\t\t}\n\tif( cryptStatusError( status ) || \\\n\t\tstrcmp( ldapAttribute1, ldapAttribute2 ) )\n\t\t{\n\t\tprintf( \"Failed to get/set keyset attribute via equivalent global \"\n\t\t\t\t\"attribute, error\\ncode %d, value '%s', should be\\n'%s', \"\n\t\t\t\t\"line %d.\\n\", status, ldapAttribute2, ldapAttribute1,\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptKeysetClose( cryptKeyset );\n\tprintf( \"  LDAP directory %s seems to be up, using that for read test.\\n\",\n\t\t\tldapKeysetName );\n\n\t/* Now it gets tricky, we have to jump through all sorts of hoops to\n\t   run the tests in an automated manner since the innate incompatibility\n\t   of LDAP directory setups means that even though cryptlib's LDAP access\n\t   code retries failed queries with various options, we still need to\n\t   manually override some settings here.  The simplest option is a direct\n\t   read with no special-case handling */\n\tif( !paramStrcmp( ldapKeysetName, ldapUrlInfo[ LDAP_SERVER_NO ].url ) )\n\t\t{\n\t\tputs( \"Testing LDAP certificate read...\" );\n\t\tstatus = testKeysetRead( CRYPT_KEYSET_LDAP, ldapKeysetName,\n\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t ldapUrlInfo[ LDAP_SERVER_NO ].certName,\n\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE,\n\t\t\t\t\t\t\t\t READ_OPTION_NORMAL );\n\t\tif( !status )\n\t\t\t{\n\t\t\t/* Since we can never be sure about the LDAP schema du jour, we\n\t\t\t   don't treat a failure as a fatal error */\n\t\t\tputs( ldapErrorString );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* This directory doesn't contain CRLs (or at least not at any known\n\t\t   location) so we skip the CRL read test */\n\t\tputs( \"LDAP certificate read succeeded (CRL read skipped).\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* The secondary LDAP directory that we're using for these tests doesn't\n\t   recognise the ';binary' modifier which is required by LDAP servers in\n\t   order to get them to work properly, we have to change the attribute\n\t   name around the read calls to the format expected by the server.\n\n\t   In addition because the magic formula for fetching a CRL doesn't seem\n\t   to work for certificates, the CRL read is done first */\n\tputs( \"Testing LDAP CRL read...\" );\n\tstatus = cryptGetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYS_LDAP_CRLNAME,\n\t\t\t\t\t\t\t\t\t  crlName, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\tcertName[ length ] = TEXT( '\\0' );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CRLNAME,\n\t\t\t\t\t\t\t \"certificateRevocationList\", 25 );\n\tstatus = testKeysetRead( CRYPT_KEYSET_LDAP, ldapKeysetName,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t ldapUrlInfo[ LDAP_ALT_SERVER_NO ].crlName,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CRL, READ_OPTION_NORMAL );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CRLNAME,\n\t\t\t\t\t\t\t crlName, strlen( crlName ) );\n\tif( !status )\n\t\t{\n\t\t/* Since we can never be sure about the LDAP schema du jour, we\n\t\t   don't treat a failure as a fatal error */\n\t\tputs( ldapErrorString );\n\t\treturn( FALSE );\n\t\t}\n\n\tputs( \"Testing LDAP certificate read...\" );\n\tstatus = cryptGetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYS_LDAP_CERTNAME,\n\t\t\t\t\t\t\t\t\t  certName, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\tcertName[ length ] = TEXT( '\\0' );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CERTNAME,\n\t\t\t\t\t\t\t \"userCertificate\", 15 );\n\tstatus = cryptGetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_KEYS_LDAP_CACERTNAME,\n\t\t\t\t\t\t\t\t\t  caCertName, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\tcertName[ length ] = TEXT( '\\0' );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CACERTNAME,\n\t\t\t\t\t\t\t \"cACertificate\", 13 );\n\tstatus = testKeysetRead( CRYPT_KEYSET_LDAP, ldapKeysetName,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t ldapUrlInfo[ LDAP_ALT_SERVER_NO ].certName,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE, READ_OPTION_NORMAL );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CERTNAME,\n\t\t\t\t\t\t\t certName, strlen( certName ) );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_KEYS_LDAP_CACERTNAME,\n\t\t\t\t\t\t\t caCertName, strlen( caCertName ) );\n\tif( !status )\n\t\t{\n\t\t/* Since we can never be sure about the LDAP schema du jour, we\n\t\t   don't treat a failure as a fatal error */\n\t\tputs( \"LDAP directory read failed, probably due to the magic \"\n\t\t\t  \"incantatation to fetch\\na certificate from this server not \"\n\t\t\t  \"matching the one used to fetch a CRL.\\nProcessing will \"\n\t\t\t  \"continue without treating this as a fatal error.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"LDAP certificate/CRL read succeeded.\\n\" );\n\n\treturn( TRUE );\n\t}\n\nint testWriteCertLDAP( void )\n\t{\n\tint status;\n\n\tputs( \"Testing LDAP directory write...\" );\n\tstatus = testKeysetWrite( CRYPT_KEYSET_LDAP,\n\t\t\t\t\t\t\t  ldapUrlInfo[ LDAP_SERVER_NO ].url, FALSE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* LDAP keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tprintf( \"This is probably because you haven't set up an LDAP \"\n\t\t\t\t\"directory for use as the\\nkey store.  For this test to \"\n\t\t\t\t\"work,you need to set up a directory with the\\nname \"\n\t\t\t\t\"'%s'.\\n\\n\", ldapUrlInfo[ LDAP_SERVER_NO ].asciiURL );\n\t\treturn( FALSE );\n\t\t}\n\tif( !status )\n\t\t{\n\t\t/* Since we can never be sure about the LDAP schema du jour, we\n\t\t   don't treat a failure as a fatal error */\n\t\tputs( \"LDAP directory write failed, probably due to the standard \"\n\t\t\t  \"being used by the\\ndirectory differing from the one used \"\n\t\t\t  \"by cryptlib (pick a standard, any\\nstandard).  Processing \"\n\t\t\t  \"will continue without treating this as a fatal error.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"LDAP directory write succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Read a certificate from a web page */\n\nint testReadCertURL( void )\n\t{\n\tint status;\n\n\t/* Test fetching a certificate from a URL via an HTTP proxy.  This \n\t   requires a random open proxy for testing (unless the site happens to \n\t   be running an HTTP proxy), www.openproxies.com will provide this.\n\t   \n\t   Alternatively, for testing from a NZ-local ISP, proxy.xtra.co.nz:8080\n\t   can also be used */\n#if 0\t/* This is usually disabled because most people aren't behind HTTP\n\t\t   proxies, and abusing other people's misconfigured HTTP caches/\n\t\t   proxies for testing isn't very nice */\n\tputs( \"Testing HTTP certificate read from URL via proxy...\" );\n\tcryptSetAttributeString( CRYPT_UNUSED, CRYPT_OPTION_NET_HTTP_PROXY,\n\t\t\t\t\t\t\t \"proxy.zetwuinwest.com.pl:80\", 27 );\n\tstatus = testKeysetRead( CRYPT_KEYSET_HTTP, HTTP_KEYSET_CERT_NAME,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \"[none]\",\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE, READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\t/* HTTP keyset access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( !status )\n\t\treturn( FALSE );\n#endif /* 0 */\n\n\t/* Test fetching a certificate from a URL */\n\tputs( \"Testing HTTP certificate read from URL...\" );\n\tstatus = testKeysetRead( CRYPT_KEYSET_HTTP, HTTP_KEYSET_CERT_NAME,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"[none]\" ),\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE, READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\t/* HTTP keyset access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tputs( \"This is probably because the server isn't available or \"\n\t\t\t  \"inaccessible.\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( !status )\n\t\t{\n\t\tputs( \"If this message took a long time to appear, you may be \"\n\t\t\t  \"behind a firewall\\nthat blocks HTTP traffic.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test fetching a CRL from a URL */\n\tputs( \"Testing HTTP CRL read from URL...\" );\n\tstatus = testKeysetRead( CRYPT_KEYSET_HTTP, HTTP_KEYSET_CRL_NAME,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"[none]\" ),\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CRL, READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\t/* HTTP keyset access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Test fetching a huge CRL from a URL, to check the ability to read\n\t   arbitrary-length HTTP data */\n#if 1\t/* We allow this to be disabled because of the CRL size */\n\tputs( \"Testing HTTP mega-CRL read from URL...\" );\n\tstatus = testKeysetRead( CRYPT_KEYSET_HTTP, HTTP_KEYSET_HUGECRL_NAME,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"[none]\" ), \n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CRL, READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\t/* HTTP keyset access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( !status )\n\t\treturn( FALSE );\n#endif /* 0 */\n\n\tputs( \"HTTP certificate/CRL read from URL succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Read a certificate from an HTTP certificate store */\n\nint testReadCertHTTP( void )\n\t{\n\tint status;\n\n\tputs( \"Testing HTTP certificate store read...\" );\n\tstatus = testKeysetRead( CRYPT_KEYSET_HTTP, HTTP_KEYSET_CERT_NAME,\n\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"Verisign\" ),\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_CERTIFICATE, READ_OPTION_NORMAL );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\t/* HTTP keyset access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( status == CRYPT_ERROR_FAILED )\n\t\t{\n\t\tputs( \"This is probably because the server isn't available or \"\n\t\t\t  \"inaccessible.\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( !status )\n\t\t{\n\t\tputs( \"If this message took a long time to appear, you may be \"\n\t\t\t  \"behind a firewall\\nthat blocks HTTP traffic.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n\tputs( \"HTTP certificate store read succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\n#endif /* TEST_KEYSET */\n"
  },
  {
    "path": "deps/cl345/test/keyfile.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib File Keyset Test Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* External flags that indicate that the key read/update routines worked OK.\n   This is set by earlier self-test code, if it isn't set some of the tests\n   are disabled */\n\nextern int keyReadOK, doubleCertOK;\n\n#ifdef TEST_KEYSET\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get an algorithm name and the label for the key for that algorithm */\n\nstatic const char *getAlgoName( const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\treturn( \"RSA\" );\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\treturn( \"DSA\" );\n\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\treturn( \"Elgamal\" );\n\n\t\tcase CRYPT_ALGO_ECDH:\n\t\t\treturn( \"ECDH\" );\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\treturn( \"ECDSA\" );\n\t\t}\n\n\treturn( \"<Unknown>\" );\n\t}\n\nstatic const C_STR getAlgoLabel( const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\treturn( RSA_PRIVKEY_LABEL );\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\treturn( DSA_PRIVKEY_LABEL );\n\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\treturn( ELGAMAL_PRIVKEY_LABEL );\n\n\t\tcase CRYPT_ALGO_ECDH:\n\t\t\treturn( ECDSA_PRIVKEY_LABEL );\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\treturn( ECDSA_PRIVKEY_LABEL );\n\t\t}\n\n\treturn( TEXT( \"<Unknown>\" ) );\n\t}\n\n/* Load a private-key context for a particular algorithm */\n\nstatic int loadPrivateKeyContext( CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\treturn( loadRSAContexts( CRYPT_UNUSED, NULL, cryptContext ) );\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\treturn( loadDSAContexts( CRYPT_UNUSED, NULL, cryptContext ) );\n\n\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\treturn( loadElgamalContexts( NULL, cryptContext ) );\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\treturn( loadECDSAContexts( CRYPT_UNUSED, NULL, cryptContext ) );\n\t\t}\n\n\tfprintf( outputStream, \"Algorithm %d not available, line %d.\\n\", \n\t\t\t cryptAlgo, __LINE__ );\n\treturn( FALSE );\n\t}\n\n/* Make sure that an item read from a keyset is a certificate */\n\nstatic int checkCertPresence( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t\t\t  const char *certTypeName,\n\t\t\t\t\t\t\t  const CRYPT_CERTTYPE_TYPE certType )\n\t{\n\tint value, status;\n\n\t/* Make sure that what we've got is a certificate */\n\tstatus = cryptGetAttribute( cryptHandle, CRYPT_CERTINFO_CERTTYPE, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) || value != certType )\n\t\t{\n\t\tfprintf( outputStream, \"Returned object isn't a %s, line %d.\\n\", \n\t\t\t\t certTypeName, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The test that follows requires an encryption-capable algorithm, if \n\t   the algorithm can't be used for encryption then we skip it */\n\tstatus = cryptGetAttribute( cryptHandle, CRYPT_CTXINFO_ALGO, &value );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't read algorithm from certificate, \"\n\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( value != CRYPT_ALGO_RSA )\n\t\t{\n\t\tfputs( \"(Skipping certificate use test since algorithm can't be used \"\n\t\t\t   \"for encryption).\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Make sure that we can't use the read key (the certificate constrains \n\t   it from being used externally) */\n\tstatus = testCrypt( cryptHandle, cryptHandle, value, NULL, FALSE, TRUE );\n\tif( status != CRYPT_ERROR_NOTAVAIL && status != CRYPT_ERROR_PERMISSION )\n\t\t{\n\t\tfputs( \"Attempt to perform external operation on context with \"\n\t\t\t   \"internal-only action\\npermissions succeeded.\\n\", \n\t\t\t   outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Copy a source file to a destination file, corrupting a given byte in the \n   process.  This is used to test the ability of the keyset-processing code \n   to detect data manipulation in keyset data */\n\nstatic int copyModifiedFile( const C_STR srcFileName, \n\t\t\t\t\t\t\t const C_STR destFileName, const int bytePos )\n\t{\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count = 0;\n\n\t/* Read the source file into the data buffer */\n\tif( ( filePtr = fopen( convertFileName( srcFileName ), \"rb\" ) ) != NULL )\n\t\t{\n\t\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\t\tif( count >= BUFFER_SIZE )\n\t\t\tcount = 0;\n\t\tfclose( filePtr );\n\t\t}\n\tif( count <= 0 )\n\t\treturn( FALSE );\n\n\t/* Corrupt a specific byte in the file */\n\tbuffer[ bytePos ] ^= 0xFF;\n\n\t/* Write the changed result to the output buffer */\n\tif( ( filePtr = fopen( convertFileName( destFileName ), \"wb\" ) ) != NULL )\n\t\t{\n\t\tint writeCount;\n\n\t\twriteCount = fwrite( buffer, 1, count, filePtr );\n\t\tif( writeCount != count )\n\t\t\tcount = 0;\n\t\tfclose( filePtr );\n\t\t}\n\t\n\treturn( ( count > 0 ) ? TRUE : FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPGP/PKCS #12 Key Read/Write Tests\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get a public key from a PGP keyring */\n\nstatic int getPGPPublicKey( const KEYFILE_TYPE keyFileType,\n\t\t\t\t\t\t\tconst C_STR keyFileTemplate,\n\t\t\t\t\t\t\tconst BOOLEAN useWildcardName,\n\t\t\t\t\t\t\tconst char *description )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tFILE *filePtr;\n\tchar fileName[ BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tconst C_STR keysetName = getKeyfileName( keyFileType, FALSE );\n\tint status;\n\n\t/* If this is the first file read, check that the file actually exists\n\t   so that we can return an appropriate error message */\n\tif( keyFileType == KEYFILE_PGP )\n\t\t{\n\t\tif( ( filePtr = fopen( convertFileName( keysetName ),\n\t\t\t\t\t\t\t   \"rb\" ) ) == NULL )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\tfclose( filePtr );\n\t\tkeyReadOK = FALSE;\n\t\t}\n\n\t/* If the caller has overridden the keyfile to use, use the caller-\n\t   supplied name */\n\tif( keyFileTemplate != NULL )\n\t\t{\n\t\tfilenameFromTemplate( fileName, keyFileTemplate, 1 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, fileName, strlen( fileName ) + 1 );\n\t\tkeysetName = wcBuffer;\n#else\n\t\tkeysetName = fileName;\n#endif /* UNICODE_STRINGS */\n\t\t}\n\n\tfprintf( outputStream, \"Testing %s public key read...\\n\", description );\n\n\t/* Open the keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error code %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the key.  The read of the special-case PGP keyring tests the \n\t   ability to handle over-long key packet groups so this should return\n\t   a not-found error due to the packets being skipped */\n\tif( useWildcardName )\n\t\t{\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, \"[none]\" );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\tgetKeyfileUserID( keyFileType, FALSE ) );\n\t\t}\n\tif( ( keyFileType == KEYFILE_PGP_SPECIAL && \\\n\t\t  status != CRYPT_ERROR_NOTFOUND ) || \\\n\t\t( keyFileType != KEYFILE_PGP_SPECIAL && \\\n\t\t  cryptStatusError( status ) ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPublicKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"Read of public key from %s keyring \"\n\t\t\t \"succeeded.\\n\\n\", description );\n\treturn( TRUE );\n\t}\n\nint testGetPGPPublicKey( void )\n\t{\n\t/* See testGetPGPPrivateKey() for the descriptions of the files */\n\tif( !getPGPPublicKey( KEYFILE_PGP, NULL, FALSE, \"PGP\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_PGP, NULL, TRUE, \"PGP with wildcard name\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_HASH, NULL, FALSE, \"OpenPGP (GPG/hashed key)\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_HASH, NULL, TRUE, \"OpenPGP with wildcard name\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_AES, NULL, FALSE, \"OpenPGP (GPG/AES-256 key)\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_AES_KEYID, NULL, FALSE, \"OpenPGP (GPG/AES-256 key) by keyID\" ) )\n\t\treturn( FALSE );\n#if 0\t/* The key in this file has an S2K iteration count of 3.5M and will \n\t\t   be rejected by cryptlib's anti-DoS sanity checks */\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_CAST, NULL, FALSE, \"OpenPGP (GPG/CAST5 key)\" ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_RSA, NULL, FALSE, \"OpenPGP (GPG/RSA key)\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_MULT, NULL, FALSE, \"OpenPGP (multiple subkeys)\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPublicKey( KEYFILE_NAIPGP, NULL, FALSE, \"OpenPGP (NAI)\" ) )\n\t\treturn( FALSE );\n#if 0\t/* This file is nearly 100K long and consists of endless strings of \n\t\t   userIDs and signatures for the same identity, so it's rejected by\n\t\t   cryptlib's sanity-check code */\n\tif( !getPGPPublicKey( KEYFILE_PGP_SPECIAL, PGPKEY_FILE_TEMPLATE, FALSE, \"Complex PGP key\" ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n#if 0\t/* Not fully supported yet */\n\tif( !getPGPPublicKey( KEYFILE_OPENPGP_ECC, NULL, FALSE, \"OpenPGP (ECC)\" ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n\treturn( TRUE );\n\t}\n\n/* Get a private key from a PGP keyring */\n\nstatic int getPGPPrivateKey( const KEYFILE_TYPE keyFileType,\n\t\t\t\t\t\t\t const BOOLEAN useWildcardName,\n\t\t\t\t\t\t\t const char *description )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tconst C_STR keysetName = getKeyfileName( keyFileType, TRUE );\n\tconst C_STR password = getKeyfilePassword( keyFileType );\n\tint status;\n\n\tfprintf( outputStream, \"Testing %s private key read...\\n\", \n\t\t\t description );\n\n\t/* Open the keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the key.  First we try it without a password, if that fails we\n\t   retry it with the password - this tests a lot of the private-key get\n\t   functionality including things like key cacheing */\n\tif( useWildcardName )\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \"[none]\", NULL );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t getKeyfileUserID( keyFileType, TRUE ), \n\t\t\t\t\t\t\t\t\t NULL );\n\t\t}\n\tif( status == CRYPT_ERROR_WRONGKEY )\n\t\t{\n\t\t/* We need a password for this private key */\n\t\tif( useWildcardName )\n\t\t\t{\n\t\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \"[none]\", \n\t\t\t\t\t\t\t\t\t\t password );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t\t getKeyfileUserID( keyFileType, TRUE ), \n\t\t\t\t\t\t\t\t\t\t password );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can use the key that we've read.  We can only do this \n\t   with PGP 2.x keys, OpenPGP's peculiar multi-keys identify two (or more) \n\t   keys with the same label and we can't specify (at this level) which \n\t   key we want to use (the enveloping code can be more specific and so \n\t   doesn't run into this problem) */\n\tif( keyFileType == KEYFILE_PGP )\n\t\t{\n\t\tint value;\n\n\t\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, \n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = testCrypt( cryptContext, cryptContext, value, NULL, \n\t\t\t\t\t\t\t\tFALSE, FALSE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The public and private key reads worked, remember this for later when\n\t   we use the keys in other tests */\n\tkeyReadOK = TRUE;\n\n\tfprintf( outputStream, \"Read of private key from %s keyring \"\n\t\t\t \"succeeded.\\n\\n\", description );\n\treturn( TRUE );\n\t}\n\nint testGetPGPPrivateKey( void )\n\t{\n\t/* PGP 2.x file, RSA with IDEA, secring.pgp */\n#ifdef USE_PGP2\n\tif( !getPGPPrivateKey( KEYFILE_PGP, FALSE, \"PGP\" ) )\n\t\treturn( FALSE );\n#endif /* USE_PGP2 */\n\n\t/* OpenPGP file, DSA+Elgamal with 3DES, sec_hash.gpg.  Create with:\n\n\t\tgpg --gen-key --homedir . --s2k-cipher-algo 3des\n\n\t   Select DSA+Elgamal, size 1024 bits, key does not expire, \n\t   name = Test1, email = test1@test.org, comment blank, \n\t   password = test1 */\n#ifdef USE_3DES\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_HASH, FALSE, \"OpenPGP (GPG/hashed key)\" ) )\n\t\treturn( FALSE );\n#endif /* USE_3DES */\n\n\t/* OpenPGP file, DSA+Elgamal with AES, sec_aes.skr */\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_AES, FALSE, \"OpenPGP (GPG/AES-256 key)\" ) )\n\t\treturn( FALSE );\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_AES, TRUE, \"OpenPGP with wildcard name\" ) )\n\t\treturn( FALSE );\n\n#if 0\t/* The key in this file has an S2K iteration count of 3.5M and will \n\t\t   be rejected by cryptlib's anti-DoS sanity checks */\n\t/* OpenPGP file, DSA+Elgamal with CAST5, sec_cast.gpg */\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_CAST, FALSE, \"OpenPGP (GPG/CAST5 key)\" ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n\t\n\t/* OpenPGP file, RSA+RSA with 3DES and SHA256, sec_rsa.gpg.  Create with:\n\n\t\tgpg --gen-key --homedir . --s2k-cipher-algo 3des --s2k-digest-algo sha256\n\n\t   Select RSA, size 2048 bits, key does not expire, name = Test1, \n\t   email = test1@test.org, comment blank, password = test1 */\n#ifdef USE_3DES\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_RSA, FALSE, \"OpenPGP (GPG/RSA key)\" ) )\n\t\treturn( FALSE );\n#endif /* USE_3DES */\n\n\t/* OpenPGP file, RSA with IDEA, sec_nai.skr */\n#ifdef USE_PGP2\n\tif( !getPGPPrivateKey( KEYFILE_NAIPGP, FALSE, \"OpenPGP (NAI)\" ) )\n\t\treturn( FALSE );\n#endif /* USE_PGP2 */\n\n\t/* OpenPGP, RSA p and q swapped, sec_bc.gpg.  Create using \n\t   BouncyCastle */\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_BOUNCYCASTLE, FALSE, \"OpenPGP (RSA p,q swapped)\" ) )\n\t\treturn( FALSE );\n\n\t/* OpenPGP, ECC keys, sec_ecc.gpg.  Create using a development release \n\t   of GPG 2.x (which involves installing about a dozen dependency \n\t   libraries and apps), then:\n\n\t\tgpg2 --expert --full-gen-key\n\n\t   Select ECC, NIST P256, key does not expire, name = Test1,\n\t   email = test1@test.org, comment blank, password = test1 */\n#if 0\t/* Not fully supported yet */\n\tif( !getPGPPrivateKey( KEYFILE_OPENPGP_ECC, FALSE, \"OpenPGP (ECC)\" ) )\n\t\treturn( FALSE );\n#endif /* 0 */\n\n\treturn( TRUE );\n\t}\n\n/* Get a key from a PKCS #12 file.  Because of the security problems\n   associated with this format, the code only checks the data format but\n   doesn't try to read or use the keys.  If anyone wants this, they'll\n   have to add the code themselves.  Your security warranty is automatically \n   void when you implement this */\n\nstatic int borkenKeyImport( const int fileNo )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tconst C_STR userID;\n\tconst C_STR password;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint status;\n\n\t/* Set up the file access information:\n\t\n\t\tKeyset #1 = CryptoAPI via OpenSSL, privKey with ID data and 3DES, \n\t\t\tthen anonymous cert with RC2/40.\n\t\tKeyset #2 = CryptoAPI, privKey with ID data and 3DES, then \n\t\t\tanonymous cert with RC2/40.  The private key is identified via a \n\t\t\tGUID which we can't do much with so we pass in the special-case \n\t\t\tuserID \"[none]\" meaning \"return the first key that we find\".\n\t\tKeyset #3 = Unknown source, cert chain in plaintext with ID data, \n\t\t\tthen privKey with ID data and 3DES.  The userID for the private \n\t\t\tkey is the single hex byte 0x8C, again we use \"[none]\" for this.\n\t\tKeyset #4 = OpenSSL, anonymous cert with RC2/40, then privKey with \n\t\t\tID data and 3DES.\n\t\tKeyset #5 = Unknown source (possibly OpenSSL), anonymous cert with\n\t\t\tRC2/40, then privKey with ID data and 3DES.  Unlike keyset #4\n\t\t\tthe ID data doesn't include a userID, so we again have to resort\n\t\t\tto \"[none]\" to read it.\n\t\tKeyset #6 = Unknown source, from some CA that generates the private \n\t\t\tkey for you rather than allowing you to generate it, possibly \n\t\t\tBuypass based on the encoding bug in the EncryptedContentInfo, \n\t\t\tsee below.  Contains mostly indefinite-length encodings of data, \n\t\t\tcurrently not readable, see the comments in keyset/pkcs12_rd.c \n\t\t\tfor more details.  Even if this were readable, it encodes the \n\t\t\tEncryptedContentInfo.encryptedContent as if it were declared as \n\t\t\t\"[0] EXPLICIT OCTET STRING\" instead of\n\t\t\t\"[0] IMPLICIT OCTET STRING\", so the encoding is \n\t\t\t\"[0] { OCTET STRING { ...\", which we can't even auto-detect since\n\t\t\tthere's a 1/256 chance that any encrypted data block will appear\n\t\t\tto contain an OCTET STRING tag.\n\t\tKeyset #7 = Nexus 4 phone, DSA cert and private key.\n\t\tKeyset #8 = EJBCA, ECDSA cert and private key in no documented format\n\t\t\t(the code reads it from reverse-engineering the DER dump).\n\t\tKeyset #9 = Windows, ECDSA cert and private key, as above, created\n\t\t\tby importing and exporting Keyset #8 to/from Windows */\n\tswitch( fileNo )\n\t\t{\n\t\tcase 1:\n\t\t\tuserID = TEXT( \"test pkcs#12\" );\n\t\t\tpassword = TEXT( \"test\" );\n\t\t\tbreak;\n\n\t\tcase 2:\n\t\t\tuserID = TEXT( \"[none]\" );\t\t/* Label = GUID */\n\t\t\tpassword = TEXT( \"<unknown>\" );\t/* Unknown, RC2=2C 28 14 C4 01 */\n\t\t\tbreak;\n\t\n\t\tcase 3:\n\t\t\tuserID = TEXT( \"[none]\" );\t\t/* No label, ID = 0x8C */\n\t\t\tpassword = TEXT( \"7OPWKMIX\" );\n\t\t\tbreak;\n\n\t\tcase 4:\n\t\t\tuserID = TEXT( \"server\" );\n\t\t\tpassword = TEXT( \"cryptlib\" );\n\t\t\tbreak;\n\n\t\tcase 5:\n\t\t\tuserID = TEXT( \"[none]\" );\t\t/* No label, ID = hash */\n\t\t\tpassword = TEXT( \"password\" );\n\t\t\tbreak;\n\n\t\tcase 6:\n\t\t\tuserID = TEXT( \"SignLabel\" );\n\t\t\tpassword = TEXT( \"vpsign\" );\n\n\t\t\t/* See comment above */\n\t\t\treturn( TRUE );\n\n\t\tcase 7:\n\t\t\tuserID = TEXT( \"ClientDSA\" );\n\t\t\tpassword = TEXT( \"nexus4\" );\n\t\t\tbreak;\n\n\t\tcase 8:\n\t\t\tuserID = TEXT( \"CMG\" );\n\t\t\tpassword = TEXT( \"skylight\" );\n\t\t\tbreak;\n\n\t\tcase 9:\n\t\t\tuserID = TEXT( \"[none]\" );\t\t/* Label = GUID */\n\t\t\tpassword = TEXT( \"test\" );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tassert( 0 );\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Open the file keyset.  Note that we print the usual test message only\n\t   after we try and open the keyset, in order to avoid a cascade of PKCS \n\t   #12 file non-opened messages */\n\tfilenameFromTemplate( buffer, PKCS12_FILE_TEMPLATE, fileNo );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  buffer, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) && status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* If support for this isn't enabled, just exit quietly */\n\t\treturn( TRUE );\n\t\t}\n\tfprintf( outputStream, \"Testing PKCS #12 file #%d import...\\n\", fileNo ); \n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the key */\n\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,\n \t\t\t\t\t\t\t\t userID, password );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tswitch( fileNo )\n\t\t\t{\n\t\t\tcase 1:\n\t\t\t\t/* This file has a 512-bit key and will give a \n\t\t\t\t   CRYPT_ERROR_NOSECURE on import */\n\t\t\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\tbreak;\n\n\t\t\tcase  2:\n\t\t\t\t/* This file has an unknown password, although the cracked \n\t\t\t\t   RC2/40 key for it is 2C 28 14 C4 01 */\n\t\t\t\tif( status == CRYPT_ERROR_WRONGKEY )\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\t/* This file contains an invalid private key, specifically\n\t\t\t\t   ( q * u ) mod p != 1 (!!!) */\n\t\t\t\tif( status == CRYPT_ERROR_INVALID )\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t\t   __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Make sure that we got a certificate alongside the private key */\n\t\tif( !checkCertPresence( cryptContext, \"private key with certificate\", \n\t\t\t\t\t\t\t\tCRYPT_CERTTYPE_CERTIFICATE ) )\n\t\t\treturn( FALSE );\n\t\tcryptDestroyContext( cryptContext );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"Read of key from PKCS #12 file #%d \"\n\t\t\t \"succeeded.\\n\\n\", fileNo ); \n\treturn( TRUE );\n\t}\n\nint testReadAltFileKey( void )\n\t{\n#ifdef USE_3DES\n\tint i;\n\n\tfor( i = 1; i <= 9; i++ )\n\t\t{\n\t\tif( !borkenKeyImport( i ) )\n\t\t\treturn( FALSE );\n\t\t}\n#else\n\tfputs( \"Skipping alternative key file read since 3DES isn't \"\n\t\t   \"available.\\n\\n\", outputStream );\n#endif /* USE_3DES */\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tPublic/Private Key Read/Write Tests\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read/write a private key from a file */\n\nstatic int readFileKey( const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\tconst CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\tconst BOOLEAN useWildcardRead )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tconst char *keyFileDescr = \\\n\t\t\t( formatType == CRYPT_FORMAT_NONE ) ? \"alternative \" : \\\n\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\";\n\tint status;\n\n\tfprintf( outputStream, \"Testing %s private key read from %skey \"\n\t\t\t \"file%s...\\n\", getAlgoName( cryptAlgo ), keyFileDescr,\n\t\t\t useWildcardRead ? \" using wildcard ID\" : \"\" );\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  ( formatType == CRYPT_FORMAT_NONE ) ? \\\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_ALT_FILE : \\\n\t\t\t\t\t\t\t  ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_PGP_FILE : TEST_PRIVKEY_FILE,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( ( formatType != CRYPT_FORMAT_CRYPTLIB ) && \\\n\t\t\t( status == CRYPT_ERROR_NOTAVAIL ) )\n\t\t\t{\n\t\t\t/* If the format isn't supported, this isn't a problem */\n\t\t\tfputs( \"Read of RSA private key from alternative key file \"\n\t\t\t\t   \"skipped as this format is\\ndisabled.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Read the key from the file */\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\t{\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, useWildcardRead ? \\\n\t\t\t\t\t\t\t\t\t\tTEXT( \"[none]\" ) : getAlgoLabel( cryptAlgo ) );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, useWildcardRead ? \\\n\t\t\t\t\t\t\t\t\t\tTEXT( \"[none]\" ) : getAlgoLabel( cryptAlgo ),\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that we can use the read key unless its a PGP key, for \n\t   which we only have the public key */\n\tif( cryptAlgo == CRYPT_ALGO_RSA && formatType != CRYPT_FORMAT_PGP )\n\t\t{\n\t\tstatus = testCrypt( cryptContext, cryptContext, cryptAlgo, NULL, \n\t\t\t\t\t\t\tFALSE, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"Read of %s private key from %skey file \"\n\t\t\t \"succeeded.\\n\\n\", getAlgoName( cryptAlgo ), keyFileDescr );\n\treturn( TRUE );\n\t}\n\nstatic int writeFileKey( const CRYPT_ALGO_TYPE cryptAlgo, \n\t\t\t\t\t\t const CRYPT_FORMAT_TYPE formatType,\n\t\t\t\t\t\t const BOOLEAN createFile,\n\t\t\t\t\t\t const BOOLEAN generateKey )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT privateKeyContext;\n\tconst char *keyFileDescr = \\\n\t\t\t( formatType == CRYPT_FORMAT_NONE ) ? \"alternative \" : \\\n\t\t\t( formatType == CRYPT_FORMAT_PGP ) ? \"PGP \" : \"\";\n\tint status;\n\n\tfprintf( outputStream, \"Testing %s private key write to %skey \"\n\t\t\t \"file...\\n\", getAlgoName( cryptAlgo ), keyFileDescr );\n\n\t/* Create the private key context */\n\tif( generateKey )\n\t\t{\n\t\tstatus = cryptCreateContext( &privateKeyContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( privateKeyContext, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_LABEL, \n\t\t\t\t\t\t\t\t\t\t\t  getAlgoLabel( cryptAlgo ), \n\t\t\t\t\t\t\t\t\t\t\t  paramStrlen( getAlgoLabel( cryptAlgo ) ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptGenerateKey( privateKeyContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !loadPrivateKeyContext( &privateKeyContext, cryptAlgo ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Create/open the file keyset.  For the first call (with RSA) we create\n\t   a new keyset, for subsequent calls we update the existing keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  ( formatType == CRYPT_FORMAT_NONE ) ? \\\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_ALT_FILE : \\\n\t\t\t\t\t\t\t  ( formatType == CRYPT_FORMAT_PGP ) ? \\\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_PGP_FILE : TEST_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tcreateFile ? CRYPT_KEYOPT_CREATE : \\\n\t\t\t\t\t\t\t\t\t\t\t CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( privateKeyContext );\n\t\tif( ( formatType != CRYPT_FORMAT_CRYPTLIB ) && \\\n\t\t\t( status == CRYPT_ERROR_NOTAVAIL ) )\n\t\t\t{\n\t\t\t/* If the format isn't supported, this isn't a problem */\n\t\t\tfputs( \"Write of RSA private key to alternative key file \"\n\t\t\t\t   \"skipped as this format is\\ndisabled.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Write the key to the file */\n\tif( formatType == CRYPT_FORMAT_PGP )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, privateKeyContext );\n\telse\n\t\t{\n\t\tstatus = cryptAddPrivateKey( cryptKeyset, privateKeyContext,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( privateKeyContext );\n\tfprintf( outputStream, \"Write of %s private key to %skey file \"\n\t\t\t \"succeeded.\\n\\n\", getAlgoName( cryptAlgo ), keyFileDescr );\n\treturn( TRUE );\n\t}\n\nint testReadWriteFileKey( void )\n\t{\n\tif( !writeFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_CRYPTLIB, TRUE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !readFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_CRYPTLIB, FALSE ) )\n\t\treturn( FALSE );\n\tif( !readFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_CRYPTLIB, TRUE ) )\n\t\treturn( FALSE );\n\tif( !writeFileKey( CRYPT_ALGO_DSA, CRYPT_FORMAT_CRYPTLIB, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !readFileKey( CRYPT_ALGO_DSA, CRYPT_FORMAT_CRYPTLIB, FALSE ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ELGAMAL, NULL ) ) ) \n\t\t{\n\t\tif( !writeFileKey( CRYPT_ALGO_ELGAMAL, CRYPT_FORMAT_CRYPTLIB, FALSE, FALSE ) )\n\t\t\treturn( FALSE );\n\t\tif( !readFileKey( CRYPT_ALGO_ELGAMAL, CRYPT_FORMAT_CRYPTLIB, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) )\n\t\t{\n\t\tif( !writeFileKey( CRYPT_ALGO_ECDSA, CRYPT_FORMAT_CRYPTLIB, FALSE, FALSE ) )\n\t\t\treturn( FALSE );\n\t\tif( !readFileKey( CRYPT_ALGO_ECDSA, CRYPT_FORMAT_CRYPTLIB, FALSE ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nint testReadWriteAltFileKey( void )\n\t{\n#ifdef USE_3DES\n\tint status;\n\n\t/* We use CRYPT_FORMAT_NONE to denote the alternative format to the \n\t   standard PKCS #15 */\n\tstatus = writeFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_NONE, TRUE, FALSE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Alternative keyset access not available */\n\t\treturn( TRUE );\n\t\t}\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\treturn( readFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_NONE, FALSE ) );\n#else\n\tfputs( \"Skipping alternative key file test since 3DES isn't \"\n\t\t   \"available.\\n\\n\", outputStream );\n\treturn( TRUE );\n#endif /* USE_3DES */\n\t}\n\nint testReadWritePGPFileKey( void )\n\t{\n\t/* To display the written keyring data:\n\n\t\tgpg --list-sigs --keyring .\\test.pgp\n\t\tgpg --check-sigs --keyring .\\test.pgp\n\t\tgpg --list-keys --keyring .\\test.pgp */\n\tif( !writeFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_PGP, TRUE, FALSE ) )\n\t\treturn( FALSE );\n\treturn( readFileKey( CRYPT_ALGO_RSA, CRYPT_FORMAT_PGP, FALSE ) );\n\t}\n\n#if 0\t/* Disabled until we can get valid third-party PKCS #15 test data */\n\nstatic int fileKeyImport( const int fileNo )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint status;\n\n\tfprintf( outputStream, \"Testing PKCS #15 file #%d import...\\n\", fileNo );\n\n\t/* Open the file keyset */\n\tfilenameFromTemplate( buffer, P15_FILE_TEMPLATE, fileNo );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  buffer, CRYPT_KEYOPT_READONLY );\n\tif( fileNo == 1 && status == CRYPT_ERROR_OVERFLOW )\n\t\t{\n\t\t/* Depending on the setting of MAX_PKCS15_OBJECTS this keyset may \n\t\t   contain too many keys to be read, if we get an overflow error we\n\t\t   continue normally */\n\t\tfprintf( outputStream, \"Keyset contains too many items to read, \"\n\t\t\t\t \"line %d.\\n  (This is an expected condition, \"\n\t\t\t\t \"continuing...).\\n\", __LINE__ );\n\t\treturn( TRUE );\n\t\t}\n\tif( fileNo == 2 && status == CRYPT_ERROR_BADDATA )\n\t\t{\n\t\t/* This test file is from a pre-release implementation and may not\n\t\t   necessarily be correct so we don't complain in the case of \n\t\t   errors */\n\t\tfputs( \"Skipping keyset containing specil-case data values.\\n\\n\", \n\t\t\t   outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Read the key from the file */\n\tif( fileNo == 1 )\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"John Smith 0\" ),\n\t\t\t\t\t\t\t\t\t TEXT( \"password\" ) );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, TEXT( \"key and chain\" ),\n\t\t\t\t\t\t\t\t\t TEXT( \"password\" ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* 0 */\n\nint testImportFileKey( void )\n\t{\n#if 0\t/* Disabled until we can get valid third-party PKCS #15 test data */\n\tint i;\n\n\tfor( i = 1; i <= 1; i++ )\n\t\t{\n\t\tif( !fileKeyImport( i ) )\n\t\t\treturn( FALSE );\n\t\t}\n#endif /* 0 */\n\n\treturn( TRUE );\n\t}\n\n/* Read only the public key/certificate/certificate chain portion of a \n   keyset */\n\nint testReadFilePublicKey( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tint cryptAlgo, status;\n\n\tfputs( \"Testing public key read from key file...\\n\", outputStream );\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Read the public key from the file and make sure that it really is a\n\t   public-key context */\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tRSA_PRIVKEY_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPublicKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, &cryptAlgo );\n\tif( cryptStatusError( status ) || \\\n\t\tcryptAlgo < CRYPT_ALGO_FIRST_PKC || cryptAlgo > CRYPT_ALGO_LAST_PKC )\n\t\t{\n\t\tfputs( \"Returned object isn't a public-key context.\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tcryptDestroyContext( cryptContext );\n\n\tfputs( \"Read of public key from key file succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic int readCert( const char *certTypeName,\n\t\t\t\t\t const CRYPT_CERTTYPE_TYPE certType,\n\t\t\t\t\t const BOOLEAN readPrivateKey )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint value, status;\n\n\tfprintf( outputStream, \"Testing %s read from key file...\\n\", \n\t\t\t certTypeName );\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Read the certificate from the file and make sure that it really is a\n\t   certificate */\n\tif( readPrivateKey )\n\t\t{\n\t\tCRYPT_CONTEXT cryptContext;\n\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t\t   __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !checkCertPresence( cryptContext, certTypeName, certType ) )\n\t\t\treturn( FALSE );\n\t\tcryptDestroyContext( cryptContext );\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCert;\n\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t( certType == CRYPT_CERTTYPE_CERTIFICATE ) ? \\\n\t\t\t\t\t\t\t\t\tRSA_PRIVKEY_LABEL : USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptKeyset, \"cryptGetPublicKey()\", status, \n\t\t\t\t\t\t   __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, &value );\n\t\tif( cryptStatusError( status ) || value != certType )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Returned object isn't a %s, line %d.\\n\", \n\t\t\t\t\t certTypeName, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"Read of %s from key file succeeded.\\n\\n\", \n\t\t\t certTypeName );\n\treturn( TRUE );\n\t}\n\nint testReadFileCert( void )\n\t{\n\treturn( readCert( \"certificate\", CRYPT_CERTTYPE_CERTIFICATE, FALSE ) );\n\t}\nint testReadFileCertPrivkey( void )\n\t{\n\treturn( readCert( \"private key with certificate\", CRYPT_CERTTYPE_CERTIFICATE, TRUE ) );\n\t}\nint testReadFileCertChain( void )\n\t{\n\treturn( readCert( \"certificate chain\", CRYPT_CERTTYPE_CERTCHAIN, FALSE ) );\n\t}\n\n/* Test the ability to detect key data corruption/modification */\n\nint testReadCorruptedKey( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tint i, status;\n\n\tfputs( \"Testing detection of key corruption in key file...\\n\", \n\t\t   outputStream );\n\tfor( i = 0; i < 4; i++ )\n\t\t{\n\t\t/* Copy the file to a temporary one, corrupting a data byte in the \n\t\t   process */\n\t\tstatus = copyModifiedFile( TEST_PRIVKEY_FILE, TEST_PRIVKEY_TMP_FILE, \n\t\t\t\t\t\t\t\t   256 );\n\t\tif( !status )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't copy keyset to temporary file, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Try and read the key.  The open should succeed, the read should \n\t\t   fail */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, TEST_PRIVKEY_TMP_FILE, \n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tfprintf( outputStream, \"Read of corrupted key succeeded when it \"\n\t\t\t\t\t \"should have failed, line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tfputs( \"Detection of key corruption succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Read/Write Tests\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Update a keyset to contain a certificate */\n\nint testAddTrustedCert( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE trustedCert;\n\tint value, status;\n\n\tfputs( \"Testing trusted certificate add to key file...\\n\", \n\t\t   outputStream );\n\n\t/* Read the CA root certificate.  We have to make it explicitly non-\n\t   trusted since something else may have made it trusted previously */\n\tstatus = importCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"Couldn't read certificate from file, skipping test of trusted \"\n\t\t\t   \"certificate write...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tstatus = cryptGetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT,\n\t\t\t\t\t\t   FALSE );\n\t\t}\n\n\t/* Open the keyset, update it with the trusted certificate, and close it.\n\t   Before we make the certificate trusted, we try adding it as a standard \n\t   certificate, which should fail */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, trustedCert );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptAddPublicKey() of non-trusted \"\n\t\t\t\t \"certificate succeeded when it should have failed, \"\n\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\tstatus = cryptAddPublicKey( cryptKeyset, trustedCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPublicKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, value );\n\tcryptDestroyCert( trustedCert );\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Trusted certificate add to key file succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nint testAddGloballyTrustedCert( void )\n\t{\n\tCRYPT_CERTIFICATE trustedCert;\n\tint status;\n\n\tfputs( \"Testing globally trusted certificate add...\\n\", outputStream );\n\n\t/* Read the CA root certificate and make it trusted */\n\tstatus = importCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 1 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"Couldn't read certificate from file, skipping test of trusted \"\n\t\t\t   \"certificate write...\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\n\t/* Update the config file with the globally trusted certificate */\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CONFIGCHANGED,\n\t\t\t\t\t\t\t\tFALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Globally trusted certificate add failed \"\n\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make the certificate untrusted and update the config again */\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, FALSE );\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CONFIGCHANGED,\n\t\t\t\t\t\t\t\tFALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Globally trusted certificate delete failed \"\n\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Globally trusted certificate add succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA cACertData[] = {\n\t/* Identification information.  Note the non-heirarchical order of the\n\t   components to test the automatic arranging of the DN */\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers and CA\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Himself\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Certification Division\" ) },\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\n\t/* Self-signed X.509v3 certificate */\n\t{ CRYPT_CERTINFO_SELFSIGNED, IS_NUMERIC, TRUE },\n\n\t/* CA key usage */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_PATHLENCONSTRAINT, IS_NUMERIC, 1 },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\nint testUpdateFileCert( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT publicKeyContext, privateKeyContext;\n\tint status;\n\n\tfputs( \"Testing certificate update to key file...\\n\", outputStream );\n\n\t/* Create a self-signed CA certificate using the in-memory key (which is\n\t   the same as the one in the keyset) */\n\tif( !loadRSAContexts( CRYPT_UNUSED, &publicKeyContext, &privateKeyContext ) )\n\t\treturn( FALSE );\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, publicKeyContext );\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCert, cACertData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, privateKeyContext );\n\tdestroyContexts( CRYPT_UNUSED, publicKeyContext, privateKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate creation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tcryptDestroyCert( status );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Open the keyset, update it with the certificate, and close it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPublicKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyCert( cryptCert );\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Certificate update to key file succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Update a keyset to contain a certificate chain */\n\nstatic int writeFileCertChain( const CERT_DATA *certRequestData,\n\t\t\t\t\t\t\t   const C_STR keyFileName,\n\t\t\t\t\t\t\t   const C_STR certFileName,\n\t\t\t\t\t\t\t   const BOOLEAN isTestRun,\n\t\t\t\t\t\t\t   const BOOLEAN writeLongChain,\n\t\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t   const int keySize )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCertChain;\n\tCRYPT_CONTEXT cryptCAKey, cryptKey;\n\tint status;\n\n\tif( isTestRun )\n\t\t{\n\t\tfprintf( outputStream, \"Testing %scert chain write to key file ...\\n\",\n\t\t\t\t writeLongChain ? \"long \" : \"\" );\n\t\t}\n\n\t/* Generate a key to certify.  We can't just reuse the built-in test key\n\t   because this has already been used as the CA key and the keyset code\n\t   won't allow it to be added to a keyset as both a CA key and user key,\n\t   so we have to generate a new one */\n\tstatus = cryptCreateContext( &cryptKey, CRYPT_UNUSED, cryptAlgo );\n\tif( cryptStatusOK( status ) && keySize != CRYPT_USE_DEFAULT )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptKey, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t\t\t\t\tkeySize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptKey, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t\t  USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( USER_PRIVKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Test key generation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the CA's key.  The length of the chain is determined by the\n\t   number of certs attached to the CAs certificate, so handling long vs.\n\t   short chains is pretty simple */\n\tif( writeLongChain )\n\t\t{\n\t\tstatus = getPrivateKey( &cryptCAKey, ICA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the keyset and add the private key to it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keyFileName, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptKey,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certificate chain for the new key */\n\tstatus = cryptCreateCert( &cryptCertChain, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTCHAIN );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptKey );\n\t\t}\n\tcryptDestroyContext( cryptKey );\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCertChain, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n#ifndef _WIN32_WCE\t/* Windows CE doesn't support ANSI C time functions */\n\tif( cryptStatusOK( status ) && !isTestRun )\n\t\t{\n\t\tconst time_t validity = time( NULL ) + ( 86400L * 365 * 5 );\n\n\t\t/* Make it valid for 5 years instead of 1 to avoid problems when \n\t\t   users run the self-test with very old copies of the code */\n\t\tstatus = cryptSetAttributeString( cryptCertChain,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );\n\t\t}\n#endif /* WinCE */\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCertChain, cryptCAKey );\n\tcryptDestroyContext( cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate chain creation failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptCertChain );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the certificate chain to the file */\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptCertChain );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( certFileName != NULL )\n\t\t{\n\t\tFILE *filePtr;\n\t\tBYTE certBuffer[ BUFFER_SIZE ];\n\t\tint length;\n\n\t\t/* Save the certificate to disk for use in request/response \n\t\t   protocols */\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCertChain );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptExportCert() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( ( filePtr = fopen( convertFileName( certFileName ), \\\n\t\t\t\t\t\t\t   \"wb\" ) ) != NULL )\n\t\t\t{\n\t\t\tint count;\n\n\t\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\t\tfclose( filePtr );\n\t\t\tif( count < length )\n\t\t\t\t{\n\t\t\t\tremove( convertFileName( certFileName ) );\n\t\t\t\tfputs( \"Warning: Couldn't save certificate chain to disk, \"\n\t\t\t\t\t   \"this will cause later\\n         tests to fail.  \"\n\t\t\t\t\t   \"Press a key to continue.\\n\", outputStream );\n\t\t\t\tgetchar();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tcryptDestroyCert( cryptCertChain );\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tif( isTestRun )\n\t\t{\n\t\tfputs( \"Certificate chain write to key file succeeded.\\n\\n\", \n\t\t\t   outputStream );\n\t\t}\n\treturn( TRUE );\n\t}\n\nstatic const CERT_DATA certRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\t{ CRYPT_CERTINFO_EMAIL, IS_STRING, 0, TEXT( \"dave@wetaburgers.com\" ) },\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\t/* Re-select subject DN */\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nint testWriteFileCertChain( void )\n\t{\n\treturn( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,\n\t\t\t\t\t\t\t\tTRUE, FALSE, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\tCRYPT_USE_DEFAULT ) );\n\t}\n\nint testWriteFileLongCertChain( void )\n\t{\n\treturn( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,\n\t\t\t\t\t\t\t\tTRUE, TRUE, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\tCRYPT_USE_DEFAULT ) );\n\t}\n\n/* Delete a key from a file */\n\nint testDeleteFileKey( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\tfputs( \"Testing delete from key file...\\n\", outputStream );\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Delete the key from the file.  Since we don't need the DSA key any\n\t   more we use it as the key to delete */\n\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t DSA_PRIVKEY_LABEL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptDeletePrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tDSA_PRIVKEY_LABEL );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tfputs( \"cryptDeleteKey() claimed the key was deleted but it's still \"\n\t\t\t   \"present.\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Delete from key file succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Change the password for a key in a file */\n\nint testChangeFileKeyPassword( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\tfputs( \"Testing change of key password for key file...\\n\", \n\t\t   outputStream );\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Read the key using the old password, delete it, and write it back\n\t   using the new password.  To keep things simple we just use the same\n\t   password (since the key will be used again later), the test of the\n\t   delete function earlier on has already confirmed that the old key\n\t   and password will be deleted so there's no chance of a false positive */\n\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t RSA_PRIVKEY_LABEL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"password change\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Close the keyset */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Password change for key in key file succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\n/* Write a key and certificate to a file in a single operation */\n\nstatic int writeSingleStepFileCert( const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN useAltKeyFile,\n\t\t\t\t\t\t\t\t\tconst BOOLEAN useCombinedKeyCert )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT cryptContext;\n\tconst C_STR userName = useCombinedKeyCert ? \\\n\t\t\t\t\t\t   USER_PRIVKEY_LABEL : getAlgoLabel( cryptAlgo );\n\tint status;\n\n\tfprintf( outputStream, \"Testing single-step %s key+certificate write to \"\n\t\t\t \"%skey file...\\n\", getAlgoName( cryptAlgo ), \n\t\t\t useAltKeyFile ? \"alternative \" : \"\" );\n\n\tif( useCombinedKeyCert )\n\t\t{\n\t\tassert( cryptAlgo == CRYPT_ALGO_RSA );\n\n\t\t/* Read a combined private key + certificate object */\n\t\tstatus = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Private key + certificate read failed \"\n\t\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Create a self-signed CA certificate */\n\t\tif( !loadPrivateKeyContext( &cryptContext, cryptAlgo ) )\n\t\t\treturn( FALSE );\n\t\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptCreateCert() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, \n\t\t\t\t\t\t\t\t\tcryptContext );\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t!addCertFields( cryptCert, cACertData, __LINE__ ) )\n\t\t\treturn( FALSE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSignCert( cryptCert, cryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Certificate creation failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\tcryptDestroyCert( status );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Open the keyset, write the key and certificate, and close it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\tuseAltKeyFile ? TEST_PRIVKEY_ALT_FILE : TEST_PRIVKEY_FILE,\n\t\t\t\t\tCRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroyContext( cryptContext );\n\t\tif( !useCombinedKeyCert )\n\t\t\tcryptDestroyCert( cryptCert );\n\t\tif( useAltKeyFile && status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\t/* If the format isn't supported, this isn't a problem */\n\t\t\tfputs( \"Single-step update to alternative key file \"\n\t\t\t\t   \"skipped as this form is\\ndisabled.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The alternative format can't store RSA keys unless they contain\n\t\t   additional, unused parameters, so we don't treat this as a\n\t\t   fatal error */\n\t\tif( useAltKeyFile && useCombinedKeyCert && \\\n\t\t\tstatus == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"%s key+certificate doesn't contain \"\n\t\t\t\t\t \"additional unused parameters required\\n  by the \"\n\t\t\t\t\t \"alternative format and can't be written to the \"\n\t\t\t\t\t \"keyset.\\n\", getAlgoName( cryptAlgo ) );\n\t\t\tfputs( \"  (This is an expected result since this test verifies \"\n\t\t\t\t   \"handling of\\n   this key type).\\n\\n\", outputStream );\n\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !useCombinedKeyCert )\n\t\t{\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptKeyset, \"cryptAddPublic/PrivateKey()\", \n\t\t\t\t\t\t   status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\t/* Try and read the key+certificate back before we close the keyset.  \n\t   This ensures that the in-memory data has been updated correctly */\n\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, userName,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptKeysetClose( cryptKeyset );\n\t\tprintExtError( cryptKeyset, \n\t\t\t\t\t   \"private key read from in-memory cached keyset data\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Close the keyset, which flushes the in-memory changes to disk.  The\n\t   cacheing of data in memory ensures that all keyset updates are atomic,\n\t   so that it's nearly impossible to corrupt a private key keyset during\n\t   an update */\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Try and read the key+certificate back from disk rather than the \n\t   cached, in-memory version */\n\tstatus = getPrivateKey( &cryptContext, \n\t\t\t\t\t\t\tuseAltKeyFile ? \\\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_ALT_FILE : TEST_PRIVKEY_FILE,\n\t\t\t\t\t\t\tuserName, TEST_PRIVKEY_PASSWORD );\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \n\t\t\t\t\t   \"private key read from on-disk keyset data\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfprintf( outputStream, \"Single-step %s key+certificate write to %skey \"\n\t\t\t \"file succeeded.\\n\\n\", getAlgoName( cryptAlgo ), \n\t\t\t useAltKeyFile ? \"alternative \" : \"\" );\n\treturn( TRUE );\n\t}\n\nint testSingleStepFileCert( void )\n\t{\n\tif( !writeSingleStepFileCert( CRYPT_ALGO_RSA, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !writeSingleStepFileCert( CRYPT_ALGO_RSA, FALSE, TRUE ) )\n\t\treturn( FALSE );\n\tif( !writeSingleStepFileCert( CRYPT_ALGO_DSA, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) && \\\n\t\t!writeSingleStepFileCert( CRYPT_ALGO_ECDSA, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\nint testSingleStepAltFileCert( void )\n\t{\n#ifdef USE_3DES\n\tint status;\n\n\t/* Note that the combined key + cert test has to come first since this\n\t   will fail and leave no keyset written, while the standard test will\n\t   leave the keyset available for later */\n\tstatus = writeSingleStepFileCert( CRYPT_ALGO_RSA, TRUE, TRUE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Alternative keyset access not available */\n\t\treturn( TRUE );\n\t\t}\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\tif( !writeSingleStepFileCert( CRYPT_ALGO_RSA, TRUE, FALSE ) )\n\t\treturn( FALSE );\n#else\n\tfputs( \"Skipping alternative key file single-step test since 3DES \"\n\t\t   \"isn't available.\\n\\n\", outputStream );\n#endif /* USE_3DES */\n\treturn( TRUE );\n\t}\n\n/* Write two keys and certs (signature + encryption) with the same DN to a\n   file */\n\nint testDoubleCertFile( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptSigCert, cryptEncryptCert;\n\tCRYPT_CONTEXT cryptCAKey, cryptSigContext, cryptEncryptContext;\n\tint status;\n\n\tfputs( \"Testing separate signature+encryption certificate write to key \"\n\t\t   \"file...\\n\", outputStream );\n\tdoubleCertOK = FALSE;\n\n\t/* Get the CA's key */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Generate two keys to certify.  We can't just use the built-in test key\n\t   because cryptlib will detect it being added to the keyset a second time\n\t   (if we reuse it for both keys) and because the label is a generic one\n\t   that doesn't work if there are two keys */\n\tstatus = cryptCreateContext( &cryptSigContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSigContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_LABEL, DUAL_SIGNKEY_LABEL,\n\t\t\t\t\t\t\tparamStrlen( DUAL_SIGNKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptSigContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Test key generation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCreateContext( &cryptEncryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptEncryptContext,\n\t\t\t\t\t\t\tCRYPT_CTXINFO_LABEL, DUAL_ENCRYPTKEY_LABEL,\n\t\t\t\t\t\t\tparamStrlen( DUAL_ENCRYPTKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptEncryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Test key generation failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certs containing the keys.  In order to avoid clashes with\n\t   other keys with the same CN in the public-key database, we give the\n\t   certs abnormal CNs.  This isn't necessary for cryptlib to manage them,\n\t   but because later code tries to delete leftover certs from previous\n\t   runs with the generic name used in the self-tests, which would also\n\t   delete these certs */\n\tstatus = cryptCreateCert( &cryptSigCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSigCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptSigContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptSigCert, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptDeleteAttribute( cryptSigCert,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_COMMONNAME );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSigCert,\n\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, TEXT( \"Dave Smith (Dual)\" ),\n\t\t\t\t\tparamStrlen( TEXT( \"Dave Smith (Dual)\" ) ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSigCert,\n\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE, CRYPT_KEYUSAGE_DIGITALSIGNATURE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptSigCert, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Signature certificate creation failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptSigCert );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCreateCert( &cryptEncryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptEncryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptEncryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptEncryptCert, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptDeleteAttribute( cryptEncryptCert,\n\t\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_COMMONNAME );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptEncryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, TEXT( \"Dave Smith (Dual)\" ),\n\t\t\t\t\tparamStrlen( TEXT( \"Dave Smith (Dual)\" ) ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptEncryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE, CRYPT_KEYUSAGE_KEYENCIPHERMENT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptEncryptCert, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Encryption certificate creation failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptEncryptCert );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptCAKey );\n\n\t/* Open the keyset, write the keys and certificates, and close it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  DUAL_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptSigContext,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptAddPrivateKey( cryptKeyset, cryptEncryptContext,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptSigCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPublicKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Write the two certs to a public-key database if there's one available\n\t   (because it may not be present, we fail quietly if access to this\n\t   keyset type isn't available or the keyset isn't present, it'll be\n\t   picked up later by other tests).\n\n\t   This certificate write is needed later to test the encryption vs. \n\t   signature certificate handling.  Since they may have been added \n\t   earlier we try and delete them first (we can't use the existing \n\t   version since the issuerAndSerialNumber won't match the ones in the \n\t   private-key keyset) */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\tif( status != CRYPT_ERROR_PARAM3 && status != CRYPT_ERROR_OPEN )\n\t\t{\n\t\tC_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ];\n\t\tint length;\n\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptGetAttributeString( cryptSigCert, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t\t  name, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tname[ length ] = TEXT( '\\0' );\n\t\tdo\n\t\t\tstatus = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );\n\t\twhile( cryptStatusOK( status ) );\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* Deletion of the existing keys failed for some reason, we can't\n\t\t\t   continue */\n\t\t\treturn( extErrorExit( cryptKeyset, \"cryptDeleteKey()\",\n\t\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t\t}\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptSigCert );\n\t\tif( status != CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\t/* We can get a notfound if a database keyset is defined but\n\t\t\t   hasn't been initialised yet so the necessary tables don't\n\t\t\t   exist, it can be opened but an attempt to add a key will\n\t\t\t   return a not found error since it's the table itself rather\n\t\t\t   than any item within it that isn't being found */\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( extErrorExit( cryptKeyset, \"cryptAddPublicKey()\",\n\t\t\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t\t\t}\n\n\t\t\t/* The double-certificate keyset is set up, remember this for \n\t\t\t   later tests */\n\t\t\tdoubleCertOK = TRUE;\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptSigContext );\n\tcryptDestroyContext( cryptEncryptContext );\n\tcryptDestroyCert( cryptSigCert );\n\tcryptDestroyCert( cryptEncryptCert );\n\n\t/* Try and read the keys+certs back */\n\tstatus = getPrivateKey( &cryptSigContext, DUAL_PRIVKEY_FILE,\n\t\t\t\t\t\t\tDUAL_SIGNKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tcryptDestroyContext( cryptSigContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = getPrivateKey( &cryptEncryptContext, DUAL_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tDUAL_ENCRYPTKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tcryptDestroyContext( cryptEncryptContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( \"Separate signature+encryption certificate write to key file \"\n\t\t   \"succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Write a key and two certs of different validity periods to a file */\n\n#ifndef _WIN32_WCE\t/* Windows CE doesn't support ANSI C time functions */\n\nint testRenewedCertFile( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptOldCert, cryptNewCert;\n\tCRYPT_CONTEXT cryptCAKey, cryptContext;\n\ttime_t writtenValidTo = 0 /* Dummy */, readValidTo;\n\tint dummy, status;\n\n\tfputs( \"Testing renewed certificate write to key file...\\n\", \n\t\t   outputStream );\n\n\t/* Get the CA's key and the key to certify */\n\tstatus = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"CA private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptContext ) )\n\t\treturn( FALSE );\n\n\t/* Create the certs containing the keys */\n\tstatus = cryptCreateCert( &cryptOldCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptOldCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptOldCert, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttime_t validity = time( NULL );\n\n\t\t/* Valid for one month ending tomorrow (we can't make it already-\n\t\t   expired or cryptlib will complain) */\n\t\tvalidity += 86400;\n\t\tcryptSetAttributeString( cryptOldCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );\n\t\tvalidity -= ( 86400 * 31 );\n\t\tstatus = cryptSetAttributeString( cryptOldCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptOldCert, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Signature certificate creation failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptOldCert );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCreateCert( &cryptNewCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptNewCert,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptNewCert, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\ttime_t validity = time( NULL );\n\n\t\t/* Valid for one month starting yesterday (it's actually valid for\n\t\t   one month + one day to sidestep the one-month sanity check in the\n\t\t   private key read code that warns of about-to-expire keys) */\n\t\tvalidity -= 86400;\n\t\tcryptSetAttributeString( cryptNewCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );\n\t\tvalidity += ( 86400 * 32 );\n\t\tstatus = cryptSetAttributeString( cryptNewCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );\n\t\twrittenValidTo = validity;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptNewCert, cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Encryption certificate creation failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\tprintErrorAttributeInfo( cryptNewCert );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptCAKey );\n\n\t/* First, open the keyset, write the key and certificates (using an\n\t   in-memory update), and close it.  This tests the ability to use\n\t   information cached in memory to handle the update */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  RENEW_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetOpen() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPublicKey( cryptKeyset, cryptOldCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptNewCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \n\t\t\t\t\t   \"cryptAddPublicKey() (in-memory update)\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Then try again, but this time perform an on-disk update, closing the\n\t   keyset between the first and second update.  This tests the ability\n\t   to recover the information needed to handle the update from data in\n\t   the keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  RENEW_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptOldCert );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Keyset creation in preparation for on-disk \"\n\t\t\t\t \"update failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  RENEW_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptNewCert );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPublicKey() (on-disk update)\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptKeysetClose() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyContext( cryptContext );\n\tcryptDestroyCert( cryptOldCert );\n\tcryptDestroyCert( cryptNewCert );\n\n\t/* Try and read the (newest) key+certificate back */\n\tstatus = getPrivateKey( &cryptContext, RENEW_PRIVKEY_FILE,\n\t\t\t\t\t\t\tRSA_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Private key read failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( cryptContext,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &readValidTo, &dummy );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptContext, \"cryptGetAttributeString\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\tif( writtenValidTo != readValidTo )\n\t\t{\n\t\tconst int diff = ( int ) ( readValidTo - writtenValidTo );\n\t\tconst char *units = ( diff % 60 ) ? \"seconds\" : \"minutes\";\n\n\t\tfprintf( outputStream, \"Returned certificate != latest valid \"\n\t\t\t\t \"certificate, diff.= %d %s, line %d.\\n\", \n\t\t\t\t ( diff % 60 ) ? diff : diff / 60, units, __LINE__ );\n\t\tif( diff == 3600 || diff == -3600 )\n\t\t\t{\n\t\t\t/* See the comment on DST issues in testcert.c */\n\t\t\tfputs( \"  (This is probably due to a difference between DST at \"\n\t\t\t\t   \"certificate creation and DST\\n   now, and isn't a \"\n\t\t\t\t   \"serious problem).\\n\\n\", outputStream );\n\t\t\t}\n\t\telse\n\t\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\n\tfputs( \"Renewed certificate write to key file succeeded.\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\n#else\n\nint testRenewedCertFile( void )\n\t{\n\t/* Since the renewal is time-based, we can't easily test this under\n\t   WinCE */\n\treturn( TRUE );\n\t}\n#endif /* WinCE */\n\n/* Test reading various non-cryptlib PKCS #15 files */\n\nint testReadMiscFile( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tBYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tvoid *fileNamePtr = filenameBuffer;\n\tint status;\n\n\tfputs( \"Testing miscellaneous key file read...\\n\", outputStream );\n\n\tfilenameFromTemplate( filenameBuffer, MISC_PRIVKEY_FILE_TEMPLATE, 1 );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  fileNamePtr, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't open/scan keyset, status %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#if 0\n\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext, \n\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, \n\t\t\t\t\t\t\t\t TEXT( \"56303156793b318327b25a84808f2cb311c55b0b\" ), \n\t\t\t\t\t\t\t\t TEXT( \"PASSWORD\" ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#endif /* 0 */\n\tcryptKeysetClose( cryptKeyset );\n\n\tfputs( \"Miscellaneous key file succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Generic test routines used for debugging */\n\nvoid xxxPrivKeyRead( const char *fileName, const char *keyName, \n\t\t\t\t\t const char *password )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\t/* Open the file keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  fileName, CRYPT_KEYOPT_READONLY );\n\tassert( cryptStatusOK( status ) );\n\n\t/* Read the key from the file */\n\tif( password == NULL )\n\t\t{\n\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, keyName );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptContext,\n\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, keyName, password );\n\t\t}\n\tassert( cryptStatusOK( status ) );\n\n\tcryptKeysetClose( cryptKeyset );\n\t}\n\nvoid xxxPubKeyRead( const char *fileName, const char *keyName )\n\t{\n\txxxPrivKeyRead( fileName, keyName, NULL );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Key Generation\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if 1\n\n/* Generate test keys for CA and security protocol use.  This enables \n   various special-case extensions such as extKeyUsages or protocol-specific \n   AIA entries, as well as using a validity period of 5 years instead of the \n   usual 1 year to avoid problems when users run the self-test on very old \n   copies of the code.  The keys generated into /test/keys are:\n\n\tFile define\t\t\tFile\t\t\tDescription\n\t-----------\t\t\t----\t\t\t-----------\n\tCA_PRIVKEY_FILE\t\tca.p15\t\t\tRoot CA key.\n\t\tCMP_CA_FILE\t\tcmp_ca1.der\t\tWritten as side-effect of the above.\n\tICA_PRIVKEY_FILE\tca_int.p15\t\tIntermediate CA key + root CA cert,\n\t\t\t\t\t\t\t\t\t\tpathlen = 0.\n\tSCEPCA_PRIVKEY_FILE\tca_scep1.p15\tSCEP RSA CA key + root CA cert, SCEP \n\t\t\t\t\t\t\t\t\t\tCA keyUsage allows encryption + \n\t\t\t\t\t\t\t\t\t\tsigning.\n\t\tSCEP_CA_FILE\tscep_ca1.der\tWritten as side-effect of the above.\n\tSCEPCA_PRIVKEY_FILE\tca_scep2.p15\tSCEP ECC CA key + root CA cert, SCEP \n\t\t\t\t\t\t\t\t\t\tCA keyUsage allows signing.\n\t\tSCEP_CA_FILE\tscep_ca2.der\tWritten as side-effect of the above.\n\tSERVER_PRIVKEY_FILE\tserver1.p15\t\tSSL server key + root CA cert, server\n\t\t\t\t\t\t\t\t\t\tcert has CN = localhost, OCSP AIA.\n\tSERVER_PRIVKEY_FILE\tserver2.p15\t\tAs server2.p15 but with a different \n\t\t\t\t\t\t\t\t\t\tkey, used to check that use of the\n\t\t\t\t\t\t\t\t\t\twrong key is detected.\n\tSSH_PRIVKEY_FILE\tssh1.p15\t\tRaw SSHv1 RSA key.\n\tSSH_PRIVKEY_FILE\tssh2.p15\t\tRaw SSHv2 DSA key.\n\tSSH_PRIVKEY_FILE\tssh3.p15\t\tRaw SSHv2 ECDSA key.\n\tTSA_PRIVKEY_FILE\ttsa.p15\t\t\tTSA server key + root CA cert, TSA \n\t\t\t\t\t\t\t\t\t\tcert has TSP extKeyUsage.\n\tUSER_PRIVKEY_FILE\tuser1.p15\t\tUser key + root CA cert, user cert \n\t\t\t\t\t\t\t\t\t\thas email address.\n\tUSER_PRIVKEY_FILE\tuser2.p15\t\t(Via template): User key using SHA256 \n\t\t\t\t\t\t\t\t\t\t+ root CA cert, user cert has email \n\t\t\t\t\t\t\t\t\t\taddress.  Used to test auto-upgrade \n\t\t\t\t\t\t\t\t\t\tof enveloping algos to SHA256.\n\t\t\t\t\t\t\t\t\t\tNote that since 3.4.3 the default \n\t\t\t\t\t\t\t\t\t\talgorithm is now SHA256 anyway so \n\t\t\t\t\t\t\t\t\t\tthis test is a no-op, but the \n\t\t\t\t\t\t\t\t\t\tfunctionality is left in place to \n\t\t\t\t\t\t\t\t\t\ttest future upgrades to new hash \n\t\t\t\t\t\t\t\t\t\talgorithms.\n\tUSER_PRIVKEY_FILE\tuser3.p15\t\t(Via template): User key + \n\t\t\t\t\t\t\t\t\t\tintermediate CA cert + root CA cert.\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t(OCSP_CA_FILE is written by the\n\t\t\t\t\t\t\t\t\t\ttestCertManagement() code).\n\n   Other keys written by the self-test process are:\n\n\tCMP_PRIVKEY_FILE\tcmp*.p15\t\tCreated during the CMP self-test.\n\tDUAL_PRIVKEY_FILE\tdual.p15\t\tFor test of signature + encryption \n\t\t\t\t\t\t\t\t\t\tcert in same file in \n\t\t\t\t\t\t\t\t\t\ttestDoubleCertFile().\n\tPNPCA_PRIVKEY_FILE\tpnp_ca.p15\t\tCreated during the PnP PKI self-test,\n\tPNP_PRIVKEY_FILE\tpnp_user.p15\t_ca is for a CA cert request, _user \n\t\t\t\t\t\t\t\t\t\tis for a user cert request.\n\tRENEW_PRIVKEY_FILE\trenewed.p15\t\tFor test of update of older cert with\n\t\t\t\t\t\t\t\t\t\tnewer one in testRenewedCertFile().\n\tTEST_PRIVKEY_FILE\ttest.p15\t\tGeneric test key file */\n\nstatic const CERT_DATA serverCertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Server cert\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"localhost\" ) },\n\n\t/* Add an OCSP AIA entry */\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_AUTHORITYINFO_OCSP },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://localhost\" ) },\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA iCACertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Intermediate CA cert\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Spare CA\" ) },\n\n\t/* Set the CA key usage extensions */\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYCERTSIGN },\n#if 0\t/* Implied because parent CA has pathLen = 1 */\n\t{ CRYPT_CERTINFO_PATHLENCONSTRAINT, IS_NUMERIC, 0 },\n#endif /* 0 */\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA scepCACertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"SCEP CA cert\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's SCEP CA\" ) },\n\n\t/* Set the CA as well as generic sign+encrypt key usage extensions */\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_KEYUSAGE_DIGITALSIGNATURE | \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA scepCAECCCertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"SCEP CA cert\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's SCEP CA\" ) },\n\n\t/* Set the CA as well as generic sign key usage extensions */\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYCERTSIGN | \\\n\t\t\t\t\t\t\t\t\t\t   CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA tsaCertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"TSA Cert\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's TSA\" ) },\n\n\t/* Set the TSP extended key usage */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\t{ CRYPT_CERTINFO_EXTKEY_TIMESTAMPING, IS_NUMERIC, CRYPT_UNUSED },\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic const CERT_DATA userCertRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave Smith\" ) },\n\t{ CRYPT_CERTINFO_EMAIL, IS_STRING, 0, TEXT( \"dave@wetaburgers.com\" ) },\n\t{ CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME },\t/* Re-select subject DN */\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\n/* Create a standalone private key + certificate */\n\nstatic int createCAKeyFile( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_CONTEXT cryptContext;\n\tFILE *filePtr;\n\tBYTE certBuffer[ BUFFER_SIZE ];\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifndef _WIN32_WCE\t/* Windows CE doesn't support ANSI C time functions */\n\tconst time_t validity = time( NULL ) + ( 86400L * 365 * 3 );\n#endif /* _WIN32_WCE */\n\tint length, status;\n\n\t/* Create a self-signed CA certificate */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t\t  CA_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( CA_PRIVKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCert,\n\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( !addCertFields( cryptCert, cACertData, __LINE__ ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n#ifndef _WIN32_WCE\t/* Windows CE doesn't support ANSI C time functions */\n\t/* Make it valid for 5 years instead of 1 to avoid problems when users\n\t   run the self-test with very old copies of the code */\n\tcryptSetAttributeString( cryptCert,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCert, cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n#endif /* _WIN32_WCE */\n\n\t/* Open the keyset, update it with the certificate, and close it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  CA_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext, \n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Save the certificate to disk for use in request/response protocols */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tfilenameFromTemplate( filenameBuffer, CMP_CA_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( filenameBuffer, \"wb\" ) ) != NULL )\n\t\t{\n\t\tint count;\n\n\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\tfclose( filePtr );\n\t\tif( count < length )\n\t\t\t{\n\t\t\tremove( filenameBuffer );\n\t\t\tputs( \"Warning: Couldn't save CA certificate to disk, \"\n\t\t\t\t  \"this will cause later\\n         tests to fail.  \"\n\t\t\t\t  \"Press a key to continue.\" );\n\t\t\tgetchar();\n\t\t\t}\n\t\t}\n\n\tcryptDestroyCert( cryptCert );\n\tcryptDestroyContext( cryptContext );\n\tcryptKeysetClose( cryptKeyset );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a raw SSH private key */\n\nstatic int createSSHKeyFile( const int keyNo )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\tBYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint status;\n\n\t/* Create a private key */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t ( keyNo == 1 ) ? CRYPT_ALGO_RSA : \\\n\t\t\t\t\t\t\t\t ( keyNo == 2 ) ? CRYPT_ALGO_DSA : \\\n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ALGO_ECDSA );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t\t  USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( USER_PRIVKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Open the keyset, add the key, and close it */\n\tfilenameFromTemplate( filenameBuffer, SSH_PRIVKEY_FILE_TEMPLATE, keyNo );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  filenameBuffer, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext, \n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tcryptDestroyContext( cryptContext );\n\tcryptKeysetClose( cryptKeyset );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create a pseudo-certificate file, used to test embedded versions of \n   cryptlib running an SSL/TLS server when it's built with \n   CONFIG_NO_CERTIFICATES */\n\nstatic int createPseudoCertificateFile( void )\n\t{\n\tCRYPT_CONTEXT cryptContext, cryptCAKey;\n\tCRYPT_CERTIFICATE cryptCertChain;\n\tFILE *filePtr;\n\tBYTE certBuffer[ BUFFER_SIZE ], *certBufPtr = certBuffer;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint certBufSize = BUFFER_SIZE, status;\n\n\t/* Load a fixed RSA private key */\n\tif( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptContext ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( &cryptCAKey, ICA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Create the certificate chain for the SSL server key */\n\tstatus = cryptCreateCert( &cryptCertChain, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTCHAIN );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCertChain, serverCertRequestData, __LINE__ ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCertChain, cryptCAKey );\n\tcryptDestroyContext( cryptCAKey );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Export the chain as an SSL certificate chain.  We can't use \n\t   CRYPT_IFORMAT_SSL for this since it's is a cryptlib-internal format,\n\t   so we have to manually assemble the SSL chain ourselves */\n\tstatus = cryptSetAttribute( cryptCertChain, \n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tdo\n\t\t{\n\t\tint length;\n\n\t\t/* Export the certificate, leaving room for the 24-bit length at the\n\t\t   start */\n\t\tstatus = cryptExportCert( certBufPtr + 3, certBufSize - 3, &length, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCertChain );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Add in the 24-bit length required by SSL/TLS */\n\t\tcertBufPtr[ 0 ] = 0;\n\t\tcertBufPtr[ 1 ] = ( length >> 8 );\n\t\tcertBufPtr[ 2 ] = ( length & 0xFF );\n\t\tcertBufPtr += 3 + length;\n\t\tcertBufSize -= 3 + length;\n\t\t}\n\twhile( cryptSetAttribute( cryptCertChain,\n\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\tcryptDestroyCert( cryptCertChain );\n\n\t/* Write the SSL-format certificate chain to disk */\n\tfilenameFromTemplate( filenameBuffer, PSEUDOCERT_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( filenameBuffer, \"wb\" ) ) != NULL )\n\t\t{\n\t\tconst int length = BUFFER_SIZE - certBufSize;\n\t\tint count;\n\n\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\tfclose( filePtr );\n\t\tif( count < length )\n\t\t\t{\n\t\t\tremove( filenameBuffer );\n\t\t\tputs( \"Warning: Couldn't save SSL chain to disk, \"\n\t\t\t\t  \"this will cause later\\n         tests to fail.  \"\n\t\t\t\t  \"Press a key to continue.\" );\n\t\t\tgetchar();\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Build a certificate chain without the root certificate.  This gets quite \n   complicated to do, we can't just delete the root with:\n\n\tcryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_CERTIFICATE, \n\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\tcryptDeleteAttribute( certificate, CRYPT_CERTINFO_CURRENT_CERTIFICATE );\n\n   because the chain is locked against updates, and we can't use a \n   temporary keyset file to assemble the chain via:\n\n\tcryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t TEST_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );\n\tcryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE, \n\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\tcryptExportCert( buffer, BUFFER_SIZE, &certSize, \n\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE, certChain );\n\tcryptImportCert( buffer, certSize, CRYPT_UNUSED, &certificate );\n\tcryptSetAttribute( certificate, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\tcryptAddPublicKey( cryptKeyset, certificate );\n\tcryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE, \n\t\t\t\t\t   CRYPT_CURSOR_NEXT );\n\tcryptExportCert( buffer, BUFFER_SIZE, &certSize, \n\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE, certChain );\n\tcryptImportCert( buffer, certSize, CRYPT_UNUSED, &certificate );\n\tcryptSetAttribute( certificate, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\tcryptAddPublicKey( cryptKeyset, certificate );\n\tcryptKeysetClose( cryptKeyset );\n\tcryptDestroyCert( certificate );\n\n   because the leaf certificate is an EE certificate and therefore can't be \n   made explicitly trusted.  Because of this we have to create a pesudo-\n   encoding of a certificate chain by copying a fixed-size indefinite-length-\n   encoding header into a buffer:\n\n\t   0 NDEF: SEQUENCE {\n\t   2    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)\n\t  13 NDEF:   [0] {\n\t  15 NDEF:     SEQUENCE {\n\t  17    1:       INTEGER 1\n\t  20   11:       SET {\n\t  22    9:         SEQUENCE {\n\t  24    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)\n\t  31    0:           NULL\n\t         :           }\n\t         :         }\n\t  33   11:       SEQUENCE {\n\t  35    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)\n\t         :         }\n\t  46 NDEF:       [0] {\n   \n   and then appending the certificates to it, which on import becomes a \n   canonicalised certificate chain */\n\nstatic BYTE certChainHeader[] = { \\\n\t0x30, 0x80, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, \n\t0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x80, 0x30,\n\t0x80, 0x02, 0x01, 0x01, 0x31, 0x0B, 0x30, 0x09, \n\t0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05,\n\t0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, \n\t0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x80\n\t};\n\nstatic int writeCertChainNoRoot( void )\n\t{\n\tCRYPT_CERTIFICATE certChain;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint bufPos, certSize, status;\n\n\t/* Get the complete certificate chain */\n\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 3 );\n\tstatus = getPublicKey( &certChain, filenameBuffer, USER_PRIVKEY_LABEL );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Export the required individual certificates from the chain and write\n\t   them into a new pseudo-chain that we can import */\n\tmemcpy( buffer, certChainHeader, 48 );\n\tbufPos = 48;\n\tcryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE, \n\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\tstatus = cryptExportCert( buffer + bufPos, BUFFER_SIZE - bufPos, \n\t\t\t\t\t\t\t  &certSize, CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t  certChain );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tbufPos += certSize;\n\t\tcryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE, \n\t\t\t\t\t\t   CRYPT_CURSOR_NEXT );\n\t\tstatus = cryptExportCert( buffer + bufPos, BUFFER_SIZE - bufPos, \n\t\t\t\t\t\t\t\t  &certSize, CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  certChain );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\t/* Add the 2-byte EOCs */\n\t\tbufPos += certSize;\n\t\tmemset( buffer + bufPos, 0, 4 * 2 );\n\t\tbufPos += 4 * 2;\n\t\t}\n\tcryptDestroyCert( certChain );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Import the data as a new certificate chain, re-export it to \n\t   canonicalise it, and finally write the results to the output file */\n\tstatus = cryptImportCert( buffer, bufPos, CRYPT_UNUSED, &certChain );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( buffer, BUFFER_SIZE, &certSize, \n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTCHAIN, certChain );\n\t\t}\n\tcryptDestroyCert( certChain );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t  CHAINTEST_CHAIN_NOROOT );\n\tif( ( filePtr = fopen( filenameBuffer, \"wb\" ) ) != NULL )\n\t\t{\n\t\tint count;\n\n\t\tcount = fwrite( buffer, 1, certSize, filePtr );\n\t\tfclose( filePtr );\n\t\tif( count < certSize )\n\t\t\t{\n\t\t\tremove( filenameBuffer );\n\t\t\tputs( \"Warning: Couldn't save certificate chain to disk, \"\n\t\t\t\t  \"this will cause later\\n         tests to fail.  \"\n\t\t\t\t  \"Press a key to continue.\" );\n\t\t\tgetchar();\n\t\t\t}\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Create the cryptlib test keys */\n\nint createTestKeys( void )\n\t{\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tchar altFilenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint status;\n\n\tputs( \"Creating custom key files and associated certificate files...\" );\n\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, \\\n\t\t\t\t\t\t\t  NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Error: ECDSA must be enabled to create the custom key \"\n\t\t\t  \"files.\" );\n\t\treturn( FALSE );\n\t\t}\n\n\tprintf( \"CA root key + CMP request certificate... \" );\n\tstatus = createCAKeyFile();\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSH RSA server key... \" );\n\t\tstatus = createSSHKeyFile( 1 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSH DSA server key... \" );\n\t\tstatus = createSSHKeyFile( 2 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSH ECC server key... \" );\n\t\tstatus = createSSHKeyFile( 3 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS RSA server key... \" );\n\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_PRIVKEY_FILE_TEMPLATE, 1 );\n\t\tif( !writeFileCertChain( serverCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS RSA alternative server key... \" );\n\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_PRIVKEY_FILE_TEMPLATE, 2 );\n\t\tif( !writeFileCertChain( serverCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS ECC P256 server key... \" );\n\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 256 );\n\t\tif( !writeFileCertChain( serverCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS ECC P384 server key... \" );\n\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 384 );\n\t\tif( !writeFileCertChain( serverCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,\n\t\t\t\t\t\t\t\t 48 /* P384 */ ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS ECC P521 server key... \" );\n\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 521 );\n\t\tif( !writeFileCertChain( serverCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,\n\t\t\t\t\t\t\t\t 66 /* P521 */ ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nIntermediate CA key... \" );\n\t\tif( !writeFileCertChain( iCACertRequestData, ICA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSCEP CA key + SCEP request certificate... \" );\n\t\tfilenameFromTemplate( filenameBuffer, SCEPCA_PRIVKEY_FILE_TEMPLATE, 1 );\n\t\tfilenameFromTemplate( altFilenameBuffer, SCEP_CA_FILE_TEMPLATE, 1 );\n\t\tif( !writeFileCertChain( scepCACertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t altFilenameBuffer, FALSE, FALSE, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA, CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSCEP ECC CA key + SCEP request certificate... \" );\n\t\tfilenameFromTemplate( filenameBuffer, SCEPCA_PRIVKEY_FILE_TEMPLATE, 2 );\n\t\tfilenameFromTemplate( altFilenameBuffer, SCEP_CA_FILE_TEMPLATE, 2 );\n\t\tif( !writeFileCertChain( scepCAECCCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t altFilenameBuffer, FALSE, FALSE, \n\t\t\t\t\t\t\t\t CRYPT_ALGO_ECDSA, CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nTSA key... \" );\n\t\tif( !writeFileCertChain( tsaCertRequestData, TSA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nUser key... \" );\n\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 1 );\n\t\tif( !writeFileCertChain( userCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tint hashAlgo = CRYPT_ALGO_NONE;\n\n\t\t/* The following is currently redundant since the default hash is \n\t\t   SHA-256 anyway, see the comment with the filenames above for \n\t\t   details */\n\t\tprintf( \"done.\\nUser key using SHA256... \" );\n\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 2 );\n\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t\t\t&hashAlgo );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t   CRYPT_ALGO_SHA2 );\n\t\t\t}\n\t\tif( !writeFileCertChain( userCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, FALSE, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\tif( hashAlgo != CRYPT_ALGO_NONE )\n\t\t\t{\n\t\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, \n\t\t\t\t\t\t\t   hashAlgo );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nUser key (long chain)... \" );\n\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 3 );\n\t\tif( !writeFileCertChain( userCertRequestData, filenameBuffer,\n\t\t\t\t\t\t\t\t NULL, FALSE, TRUE, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t CRYPT_USE_DEFAULT ) )\n\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tCRYPT_CERTIFICATE certificate;\n\n\t\tprintf( \"done.\\nCertificate chain test data... \" );\n\n\t\t/* Leaf certificate */\n\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 3 );\n\t\tstatus = getPublicKey( &certificate, filenameBuffer, \n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t  CHAINTEST_LEAF );\n\t\t\tstatus = exportCertFile( filenameBuffer, certificate, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t\tcryptDestroyCert( certificate );\n\t\t\t}\n\n\t\t/* Issuer (= intermediate CA) certificate */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getPublicKey( &certificate, ICA_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t  CHAINTEST_ISSUER );\n\t\t\tstatus = exportCertFile( filenameBuffer, certificate, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t\tcryptDestroyCert( certificate );\n\t\t\t}\n\n\t\t/* Root certificate */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getPublicKey( &certificate, CA_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t   CA_PRIVKEY_LABEL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t  CHAINTEST_ROOT );\n\t\t\tstatus = exportCertFile( filenameBuffer, certificate, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTIFICATE );\n\t\t\tcryptDestroyCert( certificate );\n\t\t\t}\n\n\t\t/* Full certificate chain */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 3 );\n\t\t\tstatus = getPublicKey( &certificate, filenameBuffer, \n\t\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t  CHAINTEST_CHAIN );\n\t\t\tstatus = exportCertFile( filenameBuffer, certificate, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTCHAIN );\n\t\t\tcryptDestroyCert( certificate );\n\t\t\t}\n\n\t\t/* Certificate chain without root certificate */\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = writeCertChainNoRoot();\n\n\t\t/* Certificate chain without leaf certificate */\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = getPublicKey( &certificate, ICA_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfilenameFromTemplate( filenameBuffer, CHAINTEST_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t  CHAINTEST_CHAIN_NOLEAF );\n\t\t\tstatus = exportCertFile( filenameBuffer, certificate, \n\t\t\t\t\t\t\t\t\t CRYPT_CERTFORMAT_CERTCHAIN );\n\t\t\tcryptDestroyCert( certificate );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"done.\\nSSL/TLS pseudo-certificate chain... \" );\n\t\tstatus = createPseudoCertificateFile();\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"\\nCustom key file create failed.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"done.\" );\n\n\tputs( \"Custom key file creation succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n#endif /* 0 */\n\n#endif /* TEST_KEYSET */\n"
  },
  {
    "path": "deps/cl345/test/loadkey.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib Test Key Load Code\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2012\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tKey Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The keys for testing the RSA, DSA, and Elgamal implementations. The key \n   values may be extracted with the following code pasted into the \n   generateKey() function in ctx_dsa.c/ctx_rsa.c */\n\n#if 0\t/* RSA */\n{\n#include <stdio.h>\n\nBYTE buffer[ CRYPT_MAX_PKCSIZE ];\nint length, i;\n\nprintf( \"static const RSA_KEY rsaTestKey = {\\n\" );\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_n, buffer );\nprintf( \"\\t/* n */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_n ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_e, buffer );\nprintf( \"\\n\\n\\t/* e */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_e ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_d, buffer );\nprintf( \"\\n\\n\\t/* d */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_d ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_p, buffer );\nprintf( \"\\n\\n\\t/* p */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_p ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_q, buffer );\nprintf( \"\\n\\n\\t/* q */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_q ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_u, buffer );\nprintf( \"\\n\\n\\t/* u */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_u ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_exponent1, buffer );\nprintf( \"\\n\\n\\t/* exponent1 */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_exponent1 ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->rsaParam_exponent2, buffer );\nprintf( \"\\n\\n\\t/* exponent2 */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->rsaParam_exponent2 ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nputs( \"\\n\\t};\" );\nfflush( stdout );\n}\n#endif\n#if 0\t/* DLP */\n{\n#include <stdio.h>\n\nBYTE buffer[ CRYPT_MAX_PKCSIZE ];\nint length, i;\n\nprintf( \"static const DLP_KEY dlpTestKey = {\\n\" );\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->dlpParam_p, buffer );\nprintf( \"\\t/* p */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->dlpParam_p ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->dlpParam_q, buffer );\nprintf( \"\\n\\n\\t/* q */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->dlpParam_q ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->dlpParam_g, buffer );\nprintf( \"\\n\\n\\t/* g */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->dlpParam_g ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->dlpParam_x, buffer );\nprintf( \"\\n\\n\\t/* x */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->dlpParam_x ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nlength = BN_bn2bin( &contextInfoPtr->ctxPKC->dlpParam_y, buffer );\nprintf( \"\\n\\n\\t/* y */\\n\\t%d,\", BN_num_bits( &contextInfoPtr->ctxPKC->dlpParam_y ) );\nfor( i = 0; i < length; i++ )\n\t{ if( !( i % 8 ) ) printf( \"\\n\\t  \" );\n\tprintf( \"0x%02X, \", buffer[ i ] ); }\nputs( \"\\n\\t};\" );\nfflush( stdout );\n}\n#endif\n\ntypedef struct {\n\tconst int nLen; const BYTE n[ 256 ];\n\tconst int eLen; const BYTE e[ 3 ];\n\tconst int dLen; const BYTE d[ 256 ];\n\tconst int pLen; const BYTE p[ 128 ];\n\tconst int qLen; const BYTE q[ 128 ];\n\tconst int uLen; const BYTE u[ 128 ];\n\tconst int e1Len; const BYTE e1[ 128 ];\n\tconst int e2Len; const BYTE e2[ 128 ];\n\t} RSA_KEY;\n\nstatic const RSA_KEY rsa1024TestKey = {\n\t/* n */\n\t1024,\n\t{ 0x9C, 0x4D, 0x98, 0x18, 0x67, 0xF9, 0x45, 0xBC,\n\t  0xB6, 0x75, 0x53, 0x5D, 0x2C, 0xFA, 0x55, 0xE4,\n\t  0x51, 0x54, 0x9F, 0x0C, 0x16, 0xB1, 0xAF, 0x89,\n\t  0xF6, 0xF3, 0xE7, 0x78, 0xB1, 0x2B, 0x07, 0xFB,\n\t  0xDC, 0xDE, 0x64, 0x23, 0x34, 0x87, 0xDA, 0x0B,\n\t  0xE5, 0xB3, 0x17, 0x16, 0xA4, 0xE3, 0x7F, 0x23,\n\t  0xDF, 0x96, 0x16, 0x28, 0xA6, 0xD2, 0xF0, 0x0A,\n\t  0x59, 0xEE, 0x06, 0xB3, 0x76, 0x6C, 0x64, 0x19,\n\t  0xD9, 0x76, 0x41, 0x25, 0x66, 0xD1, 0x93, 0x51,\n\t  0x52, 0x06, 0x6B, 0x71, 0x50, 0x0E, 0xAB, 0x30,\n\t  0xA5, 0xC8, 0x41, 0xFC, 0x30, 0xBC, 0x32, 0xD7,\n\t  0x4B, 0x22, 0xF2, 0x45, 0x4C, 0x94, 0x68, 0xF1,\n\t  0x92, 0x8A, 0x4C, 0xF9, 0xD4, 0x5E, 0x87, 0x92,\n\t  0xA8, 0x54, 0x93, 0x92, 0x94, 0x48, 0xA4, 0xA3,\n\t  0xEE, 0x19, 0x7F, 0x6E, 0xD3, 0x14, 0xB1, 0x48,\n\t  0xCE, 0x93, 0xD1, 0xEA, 0x4C, 0xE1, 0x9D, 0xEF },\n\n\t/* e */\n\t17,\n\t{ 0x01, 0x00, 0x01 },\n\n\t/* d */\n\t1022,\n\t{ 0x37, 0xE2, 0x66, 0x67, 0x13, 0x85, 0xC4, 0xB1,\n\t  0x5C, 0x6B, 0x46, 0x8B, 0x21, 0xF1, 0xBF, 0x94,\n\t  0x0A, 0xA0, 0x3E, 0xDD, 0x8B, 0x9F, 0xAC, 0x2B,\n\t  0x9F, 0xE8, 0x44, 0xF2, 0x9A, 0x25, 0xD0, 0x8C,\n\t  0xF4, 0xC3, 0x6E, 0xFA, 0x47, 0x65, 0xEB, 0x48,\n\t  0x25, 0xB0, 0x8A, 0xA8, 0xC5, 0xFB, 0xB1, 0x11,\n\t  0x9A, 0x77, 0x87, 0x24, 0xB1, 0xC0, 0xE9, 0xA2,\n\t  0x49, 0xD5, 0x19, 0x00, 0x41, 0x6F, 0x2F, 0xBA,\n\t  0x9F, 0x28, 0x47, 0xF9, 0xB8, 0xBA, 0xFF, 0xF4,\n\t  0x8B, 0x20, 0xC9, 0xC9, 0x39, 0xAB, 0x52, 0x0E,\n\t  0x8A, 0x5A, 0xAF, 0xB3, 0xA3, 0x93, 0x4D, 0xBB,\n\t  0xFE, 0x62, 0x9B, 0x02, 0xCC, 0xA7, 0xB4, 0xAE,\n\t  0x86, 0x65, 0x88, 0x19, 0xD7, 0x44, 0xA7, 0xE4,\n\t  0x18, 0xB6, 0xCE, 0x01, 0xCD, 0xDF, 0x36, 0x81,\n\t  0xD5, 0xE1, 0x62, 0xF8, 0xD0, 0x27, 0xF1, 0x86,\n\t  0xA8, 0x58, 0xA7, 0xEB, 0x39, 0x79, 0x56, 0x41 },\n\n\t/* p */\n\t512,\n\t{ 0xCF, 0xDA, 0xF9, 0x99, 0x6F, 0x05, 0x95, 0x84,\n\t  0x09, 0x90, 0xB3, 0xAB, 0x39, 0xB7, 0xDD, 0x1D,\n\t  0x7B, 0xFC, 0xFD, 0x10, 0x35, 0xA0, 0x18, 0x1D,\n\t  0x9A, 0x11, 0x30, 0x90, 0xD4, 0x3B, 0xF0, 0x5A,\n\t  0xC1, 0xA6, 0xF4, 0x53, 0xD0, 0x94, 0xA0, 0xED,\n\t  0xE0, 0xE4, 0xE0, 0x8E, 0x44, 0x18, 0x42, 0x42,\n\t  0xE1, 0x2C, 0x0D, 0xF7, 0x30, 0xE2, 0xB8, 0x09,\n\t  0x73, 0x50, 0x28, 0xF6, 0x55, 0x85, 0x57, 0x03 },\n\n\t/* q */\n\t512,\n\t{ 0xC0, 0x81, 0xC4, 0x82, 0x6E, 0xF6, 0x1C, 0x92,\n\t  0x83, 0xEC, 0x17, 0xFB, 0x30, 0x98, 0xED, 0x6E,\n\t  0x89, 0x92, 0xB2, 0xA1, 0x21, 0x0D, 0xC1, 0x95,\n\t  0x49, 0x99, 0xD3, 0x79, 0xD3, 0xBD, 0x94, 0x93,\n\t  0xB9, 0x28, 0x68, 0xFF, 0xDE, 0xEB, 0xE8, 0xD2,\n\t  0x0B, 0xED, 0x7C, 0x08, 0xD0, 0xD5, 0x59, 0xE3,\n\t  0xC1, 0x76, 0xEA, 0xC1, 0xCD, 0xB6, 0x8B, 0x39,\n\t  0x4E, 0x29, 0x59, 0x5F, 0xFA, 0xCE, 0x83, 0xA5 },\n\n\t/* u */\n\t511,\n\t{ 0x4B, 0x87, 0x97, 0x1F, 0x27, 0xED, 0xAA, 0xAF,\n\t  0x42, 0xF4, 0x57, 0x82, 0x3F, 0xEC, 0x80, 0xED,\n\t  0x1E, 0x91, 0xF8, 0xB4, 0x33, 0xDA, 0xEF, 0xC3,\n\t  0x03, 0x53, 0x0F, 0xCE, 0xB9, 0x5F, 0xE4, 0x29,\n\t  0xCC, 0xEE, 0x6A, 0x5E, 0x11, 0x0E, 0xFA, 0x66,\n\t  0x85, 0xDC, 0xFC, 0x48, 0x31, 0x0C, 0x00, 0x97,\n\t  0xC6, 0x0A, 0xF2, 0x34, 0x60, 0x6B, 0xF7, 0x68,\n\t  0x09, 0x4E, 0xCF, 0xB1, 0x9E, 0x33, 0x9A, 0x41 },\n\n\t/* exponent1 */\n\t511,\n\t{ 0x6B, 0x2A, 0x0D, 0xF8, 0x22, 0x7A, 0x71, 0x8C,\n\t  0xE2, 0xD5, 0x9D, 0x1C, 0x91, 0xA4, 0x8F, 0x37,\n\t  0x0D, 0x5E, 0xF1, 0x26, 0x73, 0x4F, 0x78, 0x3F,\n\t  0x82, 0xD8, 0x8B, 0xFE, 0x8F, 0xBD, 0xDB, 0x7D,\n\t  0x1F, 0x4C, 0xB1, 0xB9, 0xA8, 0xD7, 0x88, 0x65,\n\t  0x3C, 0xC7, 0x24, 0x53, 0x95, 0x1E, 0x20, 0xC3,\n\t  0x94, 0x8E, 0x7F, 0x20, 0xCC, 0x2E, 0x88, 0x0E,\n\t  0x2F, 0x4A, 0xCB, 0xE3, 0xBD, 0x52, 0x02, 0xFB },\n\n\t/* exponent2 */\n\t509,\n\t{ 0x10, 0x27, 0xD3, 0xD2, 0x0E, 0x75, 0xE1, 0x17,\n\t  0xFA, 0xB2, 0x49, 0xA0, 0xEF, 0x07, 0x26, 0x85,\n\t  0xEC, 0x4D, 0xBF, 0x67, 0xFE, 0x5A, 0x25, 0x30,\n\t  0xDE, 0x28, 0x66, 0xB3, 0x06, 0xAE, 0x16, 0x55,\n\t  0xFF, 0x68, 0x00, 0xC7, 0xD8, 0x71, 0x7B, 0xEC,\n\t  0x84, 0xCB, 0xBD, 0x69, 0x0F, 0xFD, 0x97, 0xB9,\n\t  0xA1, 0x76, 0xD5, 0x64, 0xC6, 0x5A, 0xD7, 0x7C,\n\t  0x4B, 0xAE, 0xF4, 0xAD, 0x35, 0x63, 0x37, 0x71 }\n\t};\n\nstatic const RSA_KEY rsa2048TestKey = {\n\t/* n */\n\t2048,\n\t{ 0xBC, 0xB9, 0x69, 0xBE, 0x8A, 0xDE, 0x29, 0x4B, \n\t  0xFC, 0x0C, 0xCA, 0x10, 0xBC, 0x16, 0x30, 0x9B, \n\t  0x78, 0xE2, 0xDB, 0x18, 0x61, 0x4F, 0x2C, 0xD8, \n\t  0x88, 0xFD, 0xC8, 0x59, 0xD0, 0x24, 0x95, 0x79, \n\t  0x95, 0x33, 0x8E, 0x41, 0xAB, 0x8E, 0x36, 0x6A, \n\t  0xB1, 0xAA, 0xE7, 0xA0, 0x06, 0x70, 0xA8, 0x47, \n\t  0xC3, 0xA7, 0xFB, 0x3F, 0xA6, 0x62, 0xC2, 0xD1, \n\t  0x9B, 0xA2, 0x7A, 0x93, 0x65, 0x02, 0x31, 0x5C, \n\t  0x61, 0x18, 0xF3, 0x61, 0x4E, 0x11, 0x1F, 0x77, \n\t  0xDB, 0x86, 0x11, 0x73, 0xA3, 0x7A, 0x30, 0x46, \n\t  0x10, 0xE3, 0x23, 0xE2, 0x9E, 0x41, 0x23, 0xA2, \n\t  0x32, 0x25, 0x1D, 0x9B, 0x15, 0x64, 0x52, 0x88, \n\t  0x97, 0x70, 0x3D, 0x83, 0x0A, 0xAC, 0x47, 0x2E, \n\t  0x0E, 0xFE, 0x56, 0xBA, 0x2E, 0x3A, 0xEB, 0xE7, \n\t  0x56, 0xDC, 0x60, 0xA2, 0xEA, 0xBF, 0xFC, 0xD0, \n\t  0xAD, 0xED, 0xB3, 0xC2, 0x6B, 0x0E, 0xAE, 0x00, \n\t  0x2A, 0x19, 0xE1, 0xFD, 0x85, 0x14, 0x53, 0xA6, \n\t  0xD4, 0xBE, 0x7D, 0xF0, 0xC8, 0x39, 0xFF, 0x07, \n\t  0x58, 0x79, 0x52, 0x1E, 0xE4, 0xF9, 0xC9, 0xE1, \n\t  0x82, 0xD1, 0xF6, 0x1B, 0x8B, 0x69, 0x26, 0x2E, \n\t  0x9F, 0x8D, 0xDE, 0xB5, 0x9A, 0x9C, 0xAF, 0x7A, \n\t  0x61, 0x00, 0xFC, 0x7B, 0xC1, 0x47, 0x34, 0xBB, \n\t  0x49, 0x1C, 0x99, 0x4D, 0x63, 0xC3, 0x47, 0xE8, \n\t  0xE9, 0x75, 0x08, 0xD0, 0xE2, 0x9D, 0xA6, 0x56, \n\t  0x64, 0x7D, 0xCE, 0x62, 0x7B, 0xE9, 0x4E, 0xE5, \n\t  0x25, 0xA2, 0xAF, 0x36, 0xC4, 0x95, 0x17, 0xA5, \n\t  0xE9, 0x52, 0x0D, 0xF6, 0x29, 0x1E, 0xAE, 0xC5, \n\t  0x6C, 0x43, 0x00, 0x02, 0xE3, 0x03, 0xE5, 0x2C, \n\t  0x12, 0x63, 0x7E, 0x5E, 0x97, 0x93, 0x7D, 0x35, \n\t  0xBB, 0x58, 0xD0, 0xD1, 0x74, 0x3B, 0xC0, 0x2D, \n\t  0x86, 0x66, 0x1B, 0x81, 0x45, 0x64, 0xE5, 0xE0, \n\t  0xAC, 0x39, 0x22, 0xEA, 0x25, 0x5B, 0x7D, 0x41 }, \n\n\t/* e */\n\t17,\n\t{ 0x01, 0x00, 0x01 }, \n\n\t/* d */\n\t2047,\n\t{ 0x4A, 0x93, 0x15, 0xD7, 0x06, 0x76, 0xDD, 0x68, \n\t  0xBA, 0x33, 0xAF, 0x91, 0x47, 0x51, 0x99, 0x69, \n\t  0x86, 0x2E, 0x56, 0x97, 0x5E, 0xB4, 0x73, 0xAB, \n\t  0x29, 0x0E, 0xE7, 0xA1, 0x9D, 0xDF, 0x26, 0xF5, \n\t  0xC1, 0x60, 0x7B, 0x01, 0x36, 0x32, 0x5F, 0x0C, \n\t  0x70, 0x22, 0x71, 0x9E, 0xC9, 0x8C, 0xB0, 0xE2, \n\t  0x92, 0xCD, 0x09, 0x3A, 0x50, 0x9C, 0x4C, 0x11, \n\t  0x99, 0xE7, 0x6D, 0x7A, 0x5A, 0xFA, 0xAF, 0xD8, \n\t  0xAA, 0x41, 0xBA, 0xC2, 0xA3, 0x9F, 0x9E, 0x88, \n\t  0xB5, 0x45, 0x58, 0x16, 0x12, 0xEE, 0x50, 0xAF, \n\t  0x0F, 0x33, 0x42, 0x55, 0xE5, 0x65, 0x26, 0x18, \n\t  0x8C, 0xAA, 0x1F, 0xF5, 0xCD, 0x51, 0x34, 0x4F, \n\t  0xE7, 0x4F, 0xA1, 0xEE, 0xEB, 0x43, 0xC2, 0x68, \n\t  0xCF, 0xE1, 0xEF, 0x11, 0x68, 0xFD, 0x3D, 0x84, \n\t  0xCF, 0xCD, 0x0B, 0x9E, 0xB5, 0x16, 0xA2, 0x67, \n\t  0x2F, 0xA3, 0x73, 0x5A, 0x0B, 0x05, 0xE4, 0xF9, \n\t  0x5B, 0x60, 0xE1, 0xEF, 0x7A, 0x12, 0x3C, 0xFC, \n\t  0xF7, 0xD6, 0x34, 0x09, 0x77, 0x6D, 0xF3, 0x70, \n\t  0x34, 0x16, 0x35, 0x26, 0xB4, 0xF8, 0x5F, 0x05, \n\t  0xB9, 0xB2, 0x7F, 0x07, 0x17, 0x62, 0x9E, 0x1C, \n\t  0x96, 0xCC, 0x9B, 0xF3, 0x19, 0xE5, 0xDA, 0x86, \n\t  0x0A, 0x91, 0x06, 0x8B, 0xB6, 0xCF, 0x21, 0xD8, \n\t  0x68, 0x9C, 0x5F, 0xF1, 0xA7, 0xF4, 0x80, 0x7B, \n\t  0x09, 0xC5, 0x64, 0x1D, 0x3D, 0xDD, 0x68, 0x66, \n\t  0x55, 0x6C, 0xDD, 0xED, 0x48, 0x43, 0x3B, 0x19, \n\t  0x84, 0x6F, 0x8E, 0x87, 0x3E, 0x6D, 0xEB, 0xE5, \n\t  0x28, 0x22, 0xEA, 0xE1, 0x3F, 0x44, 0xDF, 0x40, \n\t  0xE3, 0xED, 0xDB, 0x0D, 0x6C, 0x96, 0x5C, 0x41, \n\t  0xD7, 0x32, 0xF7, 0x12, 0x4A, 0xA3, 0x01, 0xD2, \n\t  0x23, 0x79, 0x0D, 0xE6, 0xAF, 0x33, 0x8D, 0xDE, \n\t  0x88, 0x32, 0x14, 0x56, 0x60, 0x03, 0x9A, 0x93, \n\t  0x05, 0x2E, 0xFC, 0xB4, 0x3F, 0xB9, 0xA2, 0x31 }, \n\n\t/* p */\n\t1024,\n\t{ 0xEE, 0x5B, 0x04, 0xEB, 0x5C, 0x16, 0x87, 0x89, \n\t  0x6C, 0xF7, 0xD4, 0xDC, 0x42, 0x6D, 0xCD, 0xCA, \n\t  0x3C, 0x9B, 0x7C, 0x4A, 0x94, 0x1F, 0xAD, 0xFA, \n\t  0xCC, 0x6F, 0xE1, 0x7E, 0xA0, 0x50, 0x48, 0xBF, \n\t  0xA7, 0x6A, 0x66, 0x66, 0x81, 0x1E, 0x79, 0xF9, \n\t  0xE8, 0x45, 0xBB, 0xF4, 0xC9, 0xE1, 0x85, 0x38, \n\t  0xDB, 0xF2, 0x7F, 0x77, 0x66, 0x42, 0xB4, 0xAD, \n\t  0xFA, 0xFC, 0xFF, 0xE4, 0x7D, 0xC6, 0xB0, 0x4B, \n\t  0xB2, 0xAD, 0x2A, 0x16, 0x2E, 0x22, 0x97, 0x8D, \n\t  0x98, 0xEF, 0x7C, 0x96, 0xA3, 0x7B, 0xF0, 0x5F, \n\t  0x40, 0x4E, 0xE7, 0x66, 0x06, 0x60, 0x25, 0x5B, \n\t  0x36, 0x2E, 0x6A, 0x37, 0xEF, 0xC7, 0xF6, 0xDC, \n\t  0x34, 0xC6, 0xC4, 0x40, 0x92, 0xC1, 0x20, 0x91, \n\t  0x5C, 0xB8, 0xEB, 0xBD, 0xA5, 0xF5, 0x7B, 0x54, \n\t  0x93, 0x20, 0x49, 0x02, 0x4F, 0xA4, 0x0A, 0x7F, \n\t  0xD4, 0x76, 0x6F, 0x6D, 0x92, 0x8B, 0xD0, 0xDD }, \n\n\t/* q */\n\t1024,\n\t{ 0xCA, 0xB1, 0xD9, 0xF4, 0x19, 0x4B, 0xDC, 0x6E, \n\t  0xF8, 0x88, 0xED, 0x8C, 0x93, 0x3F, 0x56, 0x79, \n\t  0xA4, 0x2E, 0x54, 0x3B, 0xD5, 0x69, 0xCD, 0x4F, \n\t  0xE0, 0x0C, 0x2B, 0x82, 0xEC, 0xFF, 0x7C, 0x05, \n\t  0x83, 0x7D, 0x68, 0xB6, 0x7B, 0x51, 0x8B, 0x00, \n\t  0x3F, 0x90, 0x63, 0x62, 0xA9, 0xFC, 0xA0, 0xBC, \n\t  0x47, 0xD9, 0x7B, 0x0E, 0xC3, 0x3A, 0x0C, 0x89, \n\t  0x96, 0x23, 0xAC, 0xBA, 0x09, 0xCF, 0x2D, 0xC2, \n\t  0x0A, 0x0C, 0xA1, 0xDD, 0x63, 0x82, 0x4B, 0xDC, \n\t  0x88, 0x0D, 0x9B, 0xF4, 0x9C, 0x0F, 0x5F, 0xA6, \n\t  0xB4, 0xA2, 0xFE, 0xFB, 0x08, 0xB7, 0x0E, 0xED, \n\t  0xA5, 0x04, 0x13, 0xAB, 0x6B, 0x66, 0xF1, 0x85, \n\t  0xD0, 0xB1, 0xAB, 0xDC, 0x2F, 0x7E, 0x61, 0xB1, \n\t  0x28, 0x87, 0xBD, 0xC6, 0xA3, 0xD5, 0xA0, 0x04, \n\t  0xD4, 0x9F, 0x49, 0xF9, 0xA9, 0xB4, 0xB1, 0x33, \n\t  0x8C, 0xFA, 0x62, 0xDE, 0x9A, 0x16, 0x85, 0xB5 }, \n\n\t/* u */\n\t1023,\n\t{ 0x5F, 0x6C, 0x5D, 0x2D, 0x73, 0x9C, 0x2B, 0x8C, \n\t  0x1C, 0x8B, 0x96, 0x6C, 0x84, 0xDB, 0x21, 0x86, \n\t  0xF1, 0xEA, 0x75, 0xE1, 0xC5, 0x96, 0x23, 0x38, \n\t  0x82, 0x02, 0x77, 0x8B, 0xFA, 0x79, 0xE3, 0xA2, \n\t  0x88, 0x0C, 0x38, 0x9C, 0x56, 0x44, 0xAA, 0x1C, \n\t  0x20, 0xB2, 0x9E, 0x9D, 0xD9, 0xAE, 0x95, 0x6B, \n\t  0x43, 0xB1, 0x4C, 0x38, 0x88, 0x9C, 0x12, 0x4E, \n\t  0x7C, 0x1F, 0xD1, 0x41, 0x6E, 0x11, 0xAA, 0x48, \n\t  0x7A, 0xAC, 0x56, 0xF0, 0x6B, 0xA3, 0x35, 0xE4, \n\t  0x6B, 0xC0, 0xF4, 0x33, 0x74, 0xC0, 0x1E, 0xC4, \n\t  0x04, 0x44, 0xF0, 0x24, 0x32, 0x83, 0xB0, 0xC7, \n\t  0xAC, 0x5C, 0x6D, 0x29, 0x87, 0x1A, 0xA7, 0x03, \n\t  0x7B, 0x61, 0x69, 0x18, 0xA1, 0x26, 0x00, 0x0A, \n\t  0x96, 0x3A, 0x56, 0x1A, 0xA0, 0xFC, 0xE2, 0x4C, \n\t  0x51, 0xE0, 0x8F, 0xE5, 0x68, 0x69, 0xEE, 0xE8, \n\t  0xA9, 0x1B, 0x24, 0x0D, 0x55, 0x55, 0x98, 0x72 }, \n\n\t/* exponent1 */\n\t1023,\n\t{ 0x71, 0xC3, 0x9F, 0xA5, 0x76, 0x5E, 0x8A, 0x72, \n\t  0x5D, 0x40, 0x2C, 0xA8, 0xB4, 0x4C, 0x14, 0x5C, \n\t  0xE2, 0x70, 0x93, 0xF2, 0x44, 0xA0, 0x9A, 0x39, \n\t  0x8A, 0x3A, 0x1C, 0x36, 0x83, 0xED, 0xCD, 0xCB, \n\t  0x2B, 0xEC, 0xEC, 0xD3, 0x1F, 0xED, 0x9B, 0xEA, \n\t  0x5B, 0xA2, 0x6D, 0x03, 0x79, 0x17, 0xDA, 0xAE, \n\t  0x38, 0xCC, 0x95, 0x6A, 0x37, 0xB4, 0xBE, 0xE8, \n\t  0x0B, 0x53, 0x96, 0x0F, 0x48, 0xB8, 0xFC, 0x8C, \n\t  0x24, 0xCB, 0xE1, 0xBA, 0x94, 0x6A, 0x8E, 0x4B, \n\t  0x57, 0x23, 0x77, 0x23, 0xAF, 0x04, 0x08, 0xC6, \n\t  0x6D, 0xBB, 0x3B, 0x56, 0xC6, 0xD4, 0x3D, 0x00, \n\t  0x3B, 0xEC, 0x0B, 0x66, 0x87, 0x5B, 0xB9, 0xC7, \n\t  0x80, 0xA9, 0x1E, 0x22, 0x73, 0xE9, 0x19, 0xD2, \n\t  0x47, 0x9F, 0x3B, 0x65, 0x59, 0x40, 0xC1, 0x8C, \n\t  0xAC, 0x6C, 0x4C, 0x6C, 0x7D, 0xF6, 0x9D, 0xCC, \n\t  0x45, 0x6C, 0x01, 0xE3, 0x1A, 0x7F, 0x01, 0x41 }, \n\n\t/* exponent2 */\n\t1022,\n\t{ 0x32, 0x07, 0x93, 0xF4, 0x5C, 0x0A, 0x0D, 0x6E, \n\t  0x96, 0x89, 0xB5, 0x98, 0x6C, 0xFF, 0xC5, 0x28, \n\t  0x61, 0x0D, 0xCE, 0x5C, 0xB6, 0x60, 0x56, 0xFC, \n\t  0xD0, 0x20, 0x30, 0xDD, 0x30, 0x02, 0x1F, 0x6A, \n\t  0x7C, 0xFA, 0x07, 0x4E, 0x83, 0x41, 0xAD, 0x3D, \n\t  0x72, 0x73, 0x01, 0x14, 0xE9, 0x40, 0x21, 0xAC, \n\t  0x57, 0x4F, 0xA6, 0xC0, 0x0E, 0x0F, 0xD5, 0xE8, \n\t  0x5F, 0xD6, 0x8E, 0x5B, 0x9C, 0xF0, 0x36, 0x2B, \n\t  0x1E, 0xAF, 0xDF, 0x83, 0xF5, 0x7B, 0xC3, 0x9D, \n\t  0xBB, 0x37, 0x20, 0xB7, 0x4F, 0x8D, 0xBB, 0xDE, \n\t  0x39, 0xD7, 0xC1, 0x77, 0xD4, 0xBE, 0xDA, 0x40, \n\t  0x6D, 0xEA, 0x83, 0xB0, 0x5B, 0xE2, 0x1C, 0xDB, \n\t  0x1A, 0x97, 0xC0, 0x03, 0xA8, 0xF5, 0x58, 0xC7, \n\t  0x91, 0x69, 0x6F, 0xBE, 0x07, 0xD2, 0x42, 0x9C, \n\t  0xEE, 0x9E, 0x22, 0x74, 0x2D, 0x1F, 0x1C, 0x5D, \n\t  0xCC, 0xFE, 0x40, 0x49, 0x11, 0x5F, 0x5D, 0xC1 }\n\t};\n\ntypedef struct {\n\tconst int pLen; const BYTE p[ 128 ];\n\tconst int qLen; const BYTE q[ 20 ];\n\tconst int gLen; const BYTE g[ 128 ];\n\tconst int xLen; const BYTE x[ 20 ];\n\tconst int yLen; const BYTE y[ 128 ];\n\t} DLP_KEY;\n\nstatic const DLP_KEY dlp1024TestKey = {\n\t/* p */\n\t1024,\n\t{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE, \n\t  0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27, \n\t  0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3, \n\t  0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10, \n\t  0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88, \n\t  0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36, \n\t  0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30, \n\t  0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE, \n\t  0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71, \n\t  0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F, \n\t  0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F, \n\t  0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB, \n\t  0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D, \n\t  0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09, \n\t  0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F, \n\t  0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 }, \n\n\t/* q */\n\t160,\n\t{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79, \n\t  0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90, \n\t  0x97, 0x13, 0x26, 0x1D }, \n\n\t/* g */\n\t1024,\n\t{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42, \n\t  0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31, \n\t  0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11, \n\t  0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79, \n\t  0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37, \n\t  0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4, \n\t  0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88, \n\t  0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F, \n\t  0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9, \n\t  0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8, \n\t  0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12, \n\t  0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78, \n\t  0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2, \n\t  0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16, \n\t  0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE, \n\t  0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B }, \n\n\t/* x */\n\t160,\n\t{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71, \n\t  0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4, \n\t  0xF2, 0xAB, 0x54, 0xA1 }, \n\n\t/* y */\n\t1024,\n\t{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA, \n\t  0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D, \n\t  0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E, \n\t  0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51, \n\t  0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5, \n\t  0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8, \n\t  0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59, \n\t  0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90, \n\t  0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C, \n\t  0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52, \n\t  0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD, \n\t  0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92, \n\t  0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC, \n\t  0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A, \n\t  0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50, \n\t  0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F } \n\t};\n\n/* The DH key uses cryptlib-internal mechanisms, the following data and\n   associated test can't be used with an unmodified version of cryptlib */\n\n#ifdef TEST_DH\n\n#define CRYPT_IATTRIBUTE_KEY_SPKI\t8015\n\nstatic const BYTE dh1024SPKI[] = {\n\t0x30, 0x82, 0x01, 0x21,\n\t\t0x30, 0x82, 0x01, 0x17,\n\t\t\t0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x02, 0x01,\n\t\t\t0x30, 0x82, 0x01, 0x0A,\n\t\t\t\t0x02, 0x81, 0x81, 0x00,\t\t/* p */\n\t\t\t\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t\t\t\t0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,\n\t\t\t\t\t0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,\n\t\t\t\t\t0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,\n\t\t\t\t\t0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,\n\t\t\t\t\t0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,\n\t\t\t\t\t0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,\n\t\t\t\t\t0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,\n\t\t\t\t\t0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,\n\t\t\t\t\t0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,\n\t\t\t\t\t0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,\n\t\t\t\t\t0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,\n\t\t\t\t\t0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,\n\t\t\t\t\t0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,\n\t\t\t\t\t0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,\n\t\t\t\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t\t\t0x02, 0x01,\t\t\t\t\t/* g */\n\t\t\t\t\t0x02,\n\t\t\t\t0x02, 0x81, 0x80,\t\t\t/* q */\n\t\t\t\t\t0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t\t\t\t0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A,\n\t\t\t\t\t0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68,\n\t\t\t\t\t0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A,\n\t\t\t\t\t0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91,\n\t\t\t\t\t0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E,\n\t\t\t\t\t0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D,\n\t\t\t\t\t0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B,\n\t\t\t\t\t0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22,\n\t\t\t\t\t0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63,\n\t\t\t\t\t0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5,\n\t\t\t\t\t0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6,\n\t\t\t\t\t0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2,\n\t\t\t\t\t0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3,\n\t\t\t\t\t0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0,\n\t\t\t\t\t0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\n\t\t0x03, 0x04, 0x00,\n\t\t\t0x02, 0x01, 0x00\t\t\t\t/* y */\n\t};\n#endif /* TEST_DH */\n\ntypedef struct {\n\tconst CRYPT_ECCCURVE_TYPE curveType;\n\tconst int pLen; const BYTE p[ 66 ];\n\tconst int aLen; const BYTE a[ 66 ];\n\tconst int bLen; const BYTE b[ 66 ];\n\tconst int gxLen; const BYTE gx[ 66 ];\n\tconst int gyLen; const BYTE gy[ 66 ];\n\tconst int nLen; const BYTE n[ 66 ];\n\tconst int qxLen; const BYTE qx[ 66 ];\n\tconst int qyLen; const BYTE qy[ 66 ];\n\tconst int dLen; const BYTE d[ 66 ];\n\t} ECC_KEY;\n\n/* NIST curve P-256 */\n\nstatic const ECC_KEY eccP256TestKey = {\n#if 0\n\tCRYPT_ECCCURVE_NONE,\n\t/* p */\n\t256,\n\t{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, \n\t  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n\t  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \n\t  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },\n\t/* a */\n\t256,\n\t{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, \n\t  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \n\t  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \n\t  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC },\n\t/* b */\n\t256,\n\t{ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, \n\t  0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, \n\t  0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, \n\t  0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B },\n\t/* gx */\n\t256,\n\t{ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, \n\t  0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, \n\t  0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, \n\t  0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 },\n\t/* gy */\n\t256,\n\t{ 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, \n\t  0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, \n\t  0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, \n\t  0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 },\n\t/* n */\n\t256,\n\t{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,  \n\t  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \n\t  0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, \n\t  0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 },\n#else\n\tCRYPT_ECCCURVE_P256,\n\t0, { 0 },\t/* p */\n\t0, { 0 },\t/* a */\n\t0, { 0 },\t/* b */\n\t0, { 0 },\t/* gx */\n\t0, { 0 },\t/* gy */\n\t0, { 0 },\t/* n */\n#endif /* 0 */\n\t/* qx */\n\t256,\n\t{ 0x26, 0x0C, 0xAB, 0x1F, 0xF2, 0x5E, 0x8F, 0x54,\n\t  0x1C, 0x52, 0x66, 0x4A, 0x1B, 0x23, 0x8F, 0x68,\n\t  0x0D, 0xEB, 0xCB, 0x0B, 0x4A, 0x4E, 0x4C, 0x88,\n\t  0xCA, 0x53, 0x1F, 0x32, 0xAB, 0x0F, 0x72, 0x56 },\n\t/* qy */\n\t256,\n\t{ 0x94, 0x56, 0xD7, 0x00, 0x6A, 0x50, 0x06, 0xC0,\n\t  0x87, 0x9B, 0x73, 0x0D, 0x3F, 0x16, 0x37, 0x42,\n\t  0xE8, 0x8A, 0xA0, 0x7F, 0x9F, 0x87, 0xD5, 0x29,\n\t  0xCF, 0x3C, 0x83, 0xC7, 0xC3, 0xE3, 0x93, 0x58 },\n\t/* d */\n\t256,\n\t{ 0xC6, 0x91, 0x9E, 0xD5, 0xF2, 0x84, 0xE0, 0x30,\n\t  0xD5, 0x7B, 0xA8, 0x13, 0x51, 0x0B, 0x50, 0x1C,\n\t  0x7D, 0x8E, 0x14, 0x66, 0xE2, 0xF1, 0x49, 0x97,\n\t  0x06, 0x49, 0x61, 0x67, 0xFA, 0xA3, 0xEA, 0x05 }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKey Load Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Set the label for a device object */\n\nstatic BOOLEAN setLabel( const CRYPT_CONTEXT cryptContext, const C_STR label )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t  label, paramStrlen( label ) );\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tprintf( \"A key object with the label '%s' already exists inside the\\n\"\n\t\t\t\t\"device.  To perform this test, you need to delete the \"\n\t\t\t\t\"existing object so\\nthat cryptlib can create a new one, \"\n\t\t\t\t\"line %d.\\n\", label, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Attempt to set object label failed with status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Load DH, RSA, DSA, and Elgamal PKC encrytion contexts */\n\n#ifdef TEST_DH\n\ntypedef struct {\n\tvoid *data;\t\t\t\t\t\t\t/* Data */\n\tint length;\t\t\t\t\t\t\t/* Length */\n\t} xMESSAGE_DATA;\n\n#define xsetMessageData( msgDataPtr, dataPtr, dataLength ) \\\n\t{ \\\n\t( msgDataPtr )->data = ( dataPtr ); \\\n\t( msgDataPtr )->length = ( dataLength ); \\\n\t}\n\nBOOLEAN loadDHKey( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t   CRYPT_CONTEXT *cryptContext )\n\t{\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tint status;\n\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, cryptContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_DH );\n\telse\n\t\tstatus = cryptCreateContext( cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_DH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"crypt%sCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", isDevice ? \"Device\" : \"\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *cryptContext, \"DH key\" ) )\n\t\t{\n\t\tcryptDestroyContext( *cryptContext );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\txMESSAGE_DATA msgData;\n\n\t\txsetMessageData( &msgData, ( void * ) dh1024SPKI,\n\t\t\t\t\t\t sizeof( dh1024SPKI ) );\n\t\tstatus = krnlSendMessage( *cryptContext, IMESSAGE_SETATTRIBUTE_S,\n\t\t\t\t\t\t\t\t  &msgData, CRYPT_IATTRIBUTE_KEY_SPKI );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"DH key load failed, status = %d, line %d.\\n\", status,\n\t\t\t\t__LINE__ );\n\t\tcryptDestroyContext( *cryptContext );\n\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n#endif /* TEST_DH */\n\nstatic int loadRSAPublicKey( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t const C_STR cryptContextLabel,\n\t\t\t\t\t\t\t CRYPT_PKCINFO_RSA *rsaKey,\n\t\t\t\t\t\t\t const BOOLEAN isDevice,\n\t\t\t\t\t\t\t const BOOLEAN useLargeKey )\n\t{\n\tconst RSA_KEY *rsaKeyTemplate = useLargeKey ? \\\n\t\t\t\t\t\t\t\t&rsa2048TestKey : &rsa1024TestKey;\n\tint status;\n\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, cryptContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_RSA );\n\telse\n\t\tstatus = cryptCreateContext( cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"crypt%sCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", isDevice ? \"Device\" : \"\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( status );\n\t\t}\n\tif( isDevice && !setLabel( *cryptContext, cryptContextLabel ) )\n\t\t{\n\t\tcryptDestroyContext( *cryptContext );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tcryptInitComponents( rsaKey, CRYPT_KEYTYPE_PUBLIC );\n\tcryptSetComponent( rsaKey->n, rsaKeyTemplate->n, rsaKeyTemplate->nLen );\n\tcryptSetComponent( rsaKey->e, rsaKeyTemplate->e, rsaKeyTemplate->eLen );\n\tstatus = cryptSetAttributeString( *cryptContext,\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY_COMPONENTS, rsaKey,\n\t\t\t\t\t\t\t\tsizeof( CRYPT_PKCINFO_RSA ) );\n\tcryptDestroyComponents( rsaKey );\n\tif( cryptStatusError( status ) )\n\t\tcryptDestroyContext( *cryptContext );\n\treturn( status );\n\t}\n\nBOOLEAN loadRSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *decryptContext,\n\t\t\t\t\t\t   const C_STR cryptContextLabel,\n\t\t\t\t\t\t   const C_STR decryptContextLabel,\n\t\t\t\t\t\t   const BOOLEAN useLargeKey,\n\t\t\t\t\t\t   const BOOLEAN useMinimalKey )\n\t{\n\tCRYPT_PKCINFO_RSA *rsaKey;\n\tconst RSA_KEY *rsaKeyTemplate = useLargeKey ? \\\n\t\t\t\t\t\t\t\t\t&rsa2048TestKey : &rsa1024TestKey;\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tBOOLEAN loadLargeKey = useLargeKey;\n\tint status;\n\n\t/* Allocate room for the public-key components */\n\tif( ( rsaKey = ( CRYPT_PKCINFO_RSA * ) malloc( sizeof( CRYPT_PKCINFO_RSA ) ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Some devices only support a single key size that isn't the same as\n\t   the built-in one so we adjust the key size being used if necessary */\n\tif( isDevice )\n\t\t{\n\t\tCRYPT_QUERY_INFO cryptQueryInfo;\n\n\t\tstatus = cryptDeviceQueryCapability( cryptDevice, CRYPT_ALGO_RSA,\n\t\t\t\t\t\t\t\t\t\t\t &cryptQueryInfo );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( rsaKey );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( cryptQueryInfo.keySize != ( rsa1024TestKey.nLen >> 3 ) )\n\t\t\t{\n\t\t\tif( cryptQueryInfo.keySize != ( rsa2048TestKey.nLen >> 3 ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Device requires a %d-bit key, which doesn't \"\n\t\t\t\t\t\t\"correspond to any built-in\\ncryptlib key.\\n\",\n\t\t\t\t\t\tcryptQueryInfo.keySize );\n\t\t\t\tfree( rsaKey );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\trsaKeyTemplate = &rsa2048TestKey;\n\t\t\tloadLargeKey = TRUE;\n\t\t\t}\n\t\t}\n\n\t/* Create the encryption context */\n\tif( cryptContext != NULL )\n\t\t{\n\t\tstatus = loadRSAPublicKey( cryptDevice, cryptContext,\n\t\t\t\t\t\t\t\t   cryptContextLabel, rsaKey, isDevice,\n\t\t\t\t\t\t\t\t   loadLargeKey );\n\t\tif( status == CRYPT_ERROR_NOTAVAIL && isDevice )\n\t\t\t{\n\t\t\t/* The device doesn't support public-key ops, use a native\n\t\t\t   context for the public key */\n\t\t\tputs( \"  Warning: Device doesn't support public-key operations, \"\n\t\t\t\t  \"using a cryptlib\\n  native context instead.\" );\n\t\t\tstatus = loadRSAPublicKey( CRYPT_UNUSED, cryptContext,\n\t\t\t\t\t\t\t\t\t   cryptContextLabel, rsaKey, FALSE,\n\t\t\t\t\t\t\t\t\t   loadLargeKey );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( rsaKey );\n\t\t\tfprintf( outputStream, \"Public key load failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( decryptContext == NULL )\n\t\t\t{\n\t\t\t/* We're only using a public-key context, return */\n\t\t\tfree( rsaKey );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\n\t/* Create the decryption context */\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, decryptContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_RSA );\n\telse\n\t\tstatus = cryptCreateContext( decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_RSA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( rsaKey );\n\t\tif( cryptContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tcryptContextLabel );\n\t\t\t}\n\t\tfprintf( outputStream, \"crypt%sCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", isDevice ? \"Device\" : \"\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *decryptContext, decryptContextLabel ) )\n\t\t{\n\t\tfree( rsaKey );\n\t\tcryptDestroyContext( *decryptContext );\n\t\tif( cryptContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tcryptContextLabel );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( rsaKey, CRYPT_KEYTYPE_PRIVATE );\n\tcryptSetComponent( rsaKey->n, rsaKeyTemplate->n, rsaKeyTemplate->nLen );\n\tcryptSetComponent( rsaKey->e, rsaKeyTemplate->e, rsaKeyTemplate->eLen );\n\tcryptSetComponent( rsaKey->d, rsaKeyTemplate->d, rsaKeyTemplate->dLen );\n\tcryptSetComponent( rsaKey->p, rsaKeyTemplate->p, rsaKeyTemplate->pLen );\n\tcryptSetComponent( rsaKey->q, rsaKeyTemplate->q, rsaKeyTemplate->qLen );\n\tif( !useMinimalKey )\n\t\t{\n\t\tcryptSetComponent( rsaKey->u, rsaKeyTemplate->u, rsaKeyTemplate->uLen );\n\t\tcryptSetComponent( rsaKey->e1, rsaKeyTemplate->e1, rsaKeyTemplate->e1Len );\n\t\tcryptSetComponent( rsaKey->e2, rsaKeyTemplate->e2, rsaKeyTemplate->e2Len );\n\t\t}\n\tstatus = cryptSetAttributeString( *decryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, rsaKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_RSA ) );\n\tcryptDestroyComponents( rsaKey );\n\tfree( rsaKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( cryptContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tcryptContextLabel );\n\t\t\t}\n\t\tcryptDestroyContext( *decryptContext );\n\t\tif( isDevice )\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tdecryptContextLabel );\n\t\tprintf( \"Private key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nBOOLEAN loadRSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t CRYPT_CONTEXT *decryptContext )\n\t{\n\treturn( loadRSAContextsEx( cryptDevice, cryptContext, decryptContext,\n\t\t\t\t\t\t\t   RSA_PUBKEY_LABEL, RSA_PRIVKEY_LABEL, FALSE, \n\t\t\t\t\t\t\t   FALSE ) );\n\t}\nBOOLEAN loadRSAContextsLarge( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t  CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t  CRYPT_CONTEXT *decryptContext )\n\t{\n\treturn( loadRSAContextsEx( cryptDevice, cryptContext, decryptContext,\n\t\t\t\t\t\t\t   RSA_PUBKEY_LABEL, RSA_PRIVKEY_LABEL, TRUE, \n\t\t\t\t\t\t\t   FALSE ) );\n\t}\n\nBOOLEAN loadDSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *signContext,\n\t\t\t\t\t\t   const C_STR sigCheckContextLabel,\n\t\t\t\t\t\t   const C_STR signContextLabel )\n\t{\n\tCRYPT_PKCINFO_DLP *dsaKey;\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tint status;\n\n\t/* Allocate room for the public-key components */\n\tif( ( dsaKey = ( CRYPT_PKCINFO_DLP * ) malloc( sizeof( CRYPT_PKCINFO_DLP ) ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Create the signature context */\n\tif( signContext != NULL )\n\t\t{\n\t\tif( isDevice )\n\t\t\tstatus = cryptDeviceCreateContext( cryptDevice, signContext,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_DSA );\n\t\telse\n\t\t\tstatus = cryptCreateContext( signContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_DSA );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( dsaKey );\n\t\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !setLabel( *signContext, signContextLabel ) )\n\t\t\t{\n\t\t\tfree( dsaKey );\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptInitComponents( dsaKey, CRYPT_KEYTYPE_PRIVATE );\n\t\tcryptSetComponent( dsaKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\t\tcryptSetComponent( dsaKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\t\tcryptSetComponent( dsaKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\t\tcryptSetComponent( dsaKey->x, dlp1024TestKey.x, dlp1024TestKey.xLen );\n\t\tcryptSetComponent( dsaKey->y, dlp1024TestKey.y, dlp1024TestKey.yLen );\n\t\tstatus = cryptSetAttributeString( *signContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY_COMPONENTS, dsaKey,\n\t\t\t\t\t\t\t\t\tsizeof( CRYPT_PKCINFO_DLP ) );\n\t\tcryptDestroyComponents( dsaKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( dsaKey );\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tprintf( \"Private key load failed with error code %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( sigCheckContext == NULL )\n\t\t\t{\n\t\t\tfree( dsaKey );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\n\t/* Create the sig.check context */\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, sigCheckContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_DSA );\n\telse\n\t\tstatus = cryptCreateContext( sigCheckContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_DSA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( dsaKey );\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *sigCheckContext, sigCheckContextLabel ) )\n\t\t{\n\t\tfree( dsaKey );\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tcryptDestroyContext( *sigCheckContext );\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( dsaKey, CRYPT_KEYTYPE_PUBLIC );\n\tcryptSetComponent( dsaKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\tcryptSetComponent( dsaKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\tcryptSetComponent( dsaKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\tcryptSetComponent( dsaKey->y, dlp1024TestKey.y, dlp1024TestKey.yLen );\n\tstatus = cryptSetAttributeString( *sigCheckContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, dsaKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_DLP ) );\n\tcryptDestroyComponents( dsaKey );\n\tfree( dsaKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tcryptDestroyContext( *sigCheckContext );\n\t\tif( isDevice )\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tsigCheckContextLabel );\n\t\tprintf( \"Public key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nBOOLEAN loadDSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t CRYPT_CONTEXT *signContext )\n\t{\n\treturn( loadDSAContextsEx( cryptDevice, sigCheckContext, signContext, \n\t\t\t\t\t\t\t   DSA_PUBKEY_LABEL, DSA_PRIVKEY_LABEL ) );\n\t}\n\nBOOLEAN loadElgamalContexts( CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *decryptContext )\n\t{\n\tCRYPT_PKCINFO_DLP *elgamalKey;\n\tint status;\n\n\t/* Allocate room for the public-key components */\n\tif( ( elgamalKey = ( CRYPT_PKCINFO_DLP * ) malloc( sizeof( CRYPT_PKCINFO_DLP ) ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Create the encryption context */\n\tif( cryptContext != NULL )\n\t\t{\n\t\tstatus = cryptCreateContext( cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_ELGAMAL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( elgamalKey );\n\t\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !setLabel( *cryptContext, ELGAMAL_PUBKEY_LABEL ) )\n\t\t\t{\n\t\t\tfree( elgamalKey );\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptInitComponents( elgamalKey, CRYPT_KEYTYPE_PUBLIC );\n\t\tcryptSetComponent( elgamalKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\t\tcryptSetComponent( elgamalKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\t\tcryptSetComponent( elgamalKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\t\tcryptSetComponent( elgamalKey->y, dlp1024TestKey.y, dlp1024TestKey.yLen );\n\t\tstatus = cryptSetAttributeString( *cryptContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY_COMPONENTS, elgamalKey,\n\t\t\t\t\t\t\t\t\tsizeof( CRYPT_PKCINFO_DLP ) );\n\t\tcryptDestroyComponents( elgamalKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( elgamalKey );\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\tprintf( \"Public key load failed with error code %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( decryptContext == NULL )\n\t\t\t{\n\t\t\tfree( elgamalKey );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\n\t/* Create the decryption context */\n\tstatus = cryptCreateContext( decryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_ALGO_ELGAMAL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( elgamalKey );\n\t\tif( cryptContext != NULL )\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *decryptContext, ELGAMAL_PRIVKEY_LABEL ) )\n\t\t{\n\t\tfree( elgamalKey );\n\t\tif( cryptContext != NULL )\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\tcryptDestroyContext( *decryptContext );\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( elgamalKey, CRYPT_KEYTYPE_PRIVATE );\n\tcryptSetComponent( elgamalKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\tcryptSetComponent( elgamalKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\tcryptSetComponent( elgamalKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\tcryptSetComponent( elgamalKey->y, dlp1024TestKey.y, dlp1024TestKey.yLen );\n\tcryptSetComponent( elgamalKey->x, dlp1024TestKey.x, dlp1024TestKey.xLen );\n\tstatus = cryptSetAttributeString( *decryptContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, elgamalKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_DLP ) );\n\tcryptDestroyComponents( elgamalKey );\n\tfree( elgamalKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( cryptContext != NULL )\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\tcryptDestroyContext( *decryptContext );\n\t\tprintf( \"Private key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Load Diffie-Hellman encrytion contexts */\n\nBOOLEAN loadDHContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\tCRYPT_CONTEXT *cryptContext1,\n\t\t\t\t\t\tCRYPT_CONTEXT *cryptContext2 )\n\t{\n\tCRYPT_PKCINFO_DLP *dhKey;\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tint status;\n\n\t/* Allocate room for the public-key components */\n\tif( ( dhKey = ( CRYPT_PKCINFO_DLP * ) malloc( sizeof( CRYPT_PKCINFO_DLP ) ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Create the first encryption context */\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, cryptContext1,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_DH );\n\telse\n\t\tstatus = cryptCreateContext( cryptContext1, CRYPT_UNUSED, CRYPT_ALGO_DH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( dhKey );\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *cryptContext1, DH_KEY1_LABEL ) )\n\t\t{\n\t\tfree( dhKey );\n\t\tcryptDestroyContext( *cryptContext1 );\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( dhKey, CRYPT_KEYTYPE_PUBLIC );\n\tcryptSetComponent( dhKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\tcryptSetComponent( dhKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\tcryptSetComponent( dhKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\tstatus = cryptSetAttributeString( *cryptContext1,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, dhKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_DLP ) );\n\tcryptDestroyComponents( dhKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( dhKey );\n\t\tprintf( \"DH #1 key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptContext2 == NULL )\n\t\t{\n\t\tfree( dhKey );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Create the second encryption context */\n\tstatus = cryptCreateContext( cryptContext2, CRYPT_UNUSED, CRYPT_ALGO_DH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( dhKey );\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *cryptContext2, DH_KEY2_LABEL ) )\n\t\t{\n\t\tfree( dhKey );\n\t\tif( isDevice )\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tDH_KEY1_LABEL );\n\t\tcryptDestroyContext( *cryptContext1 );\n\t\tcryptDestroyContext( *cryptContext2 );\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( dhKey, CRYPT_KEYTYPE_PUBLIC );\n\tcryptSetComponent( dhKey->p, dlp1024TestKey.p, dlp1024TestKey.pLen );\n\tcryptSetComponent( dhKey->q, dlp1024TestKey.q, dlp1024TestKey.qLen );\n\tcryptSetComponent( dhKey->g, dlp1024TestKey.g, dlp1024TestKey.gLen );\n\tstatus = cryptSetAttributeString( *cryptContext2,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, dhKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_DLP ) );\n\tcryptDestroyComponents( dhKey );\n\tfree( dhKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( isDevice )\n\t\t\t{\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tDH_KEY1_LABEL );\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tDH_KEY2_LABEL );\n\t\t\t}\n\t\tprintf( \"DH #2 key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Load ECDSA encrytion contexts */\n\nBOOLEAN loadECDSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *signContext,\n\t\t\t\t\t\t\t const C_STR sigCheckContextLabel,\n\t\t\t\t\t\t\t const C_STR signContextLabel )\n\t{\n\tCRYPT_PKCINFO_ECC *eccKey;\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tconst ECC_KEY *eccKeyData = &eccP256TestKey;\n\tint status;\n\n\t/* Allocate room for the public-key components */\n\tif( ( eccKey = ( CRYPT_PKCINFO_ECC * ) malloc( sizeof( CRYPT_PKCINFO_ECC ) ) ) == NULL )\n\t\treturn( FALSE );\n\n\t/* Create the signature context */\n\tif( signContext != NULL )\n\t\t{\n\t\tif( isDevice )\n\t\t\tstatus = cryptDeviceCreateContext( cryptDevice, signContext,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_ECDSA );\n\t\telse\n\t\t\tstatus = cryptCreateContext( signContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t CRYPT_ALGO_ECDSA );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( eccKey );\n\t\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !setLabel( *signContext, signContextLabel ) )\n\t\t\t{\n\t\t\tfree( eccKey );\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptInitComponents( eccKey, CRYPT_KEYTYPE_PRIVATE );\n\t\teccKey->curveType = CRYPT_ECCCURVE_P256;\n\t\tif( eccKeyData->pLen > 0 )\n\t\t\t{\n\t\t\tcryptSetComponent( eccKey->p, eccKeyData->p, eccKeyData->pLen );\n\t\t\tcryptSetComponent( eccKey->a, eccKeyData->a, eccKeyData->aLen );\n\t\t\tcryptSetComponent( eccKey->b, eccKeyData->b, eccKeyData->bLen );\n\t\t\tcryptSetComponent( eccKey->gx, eccKeyData->gx, eccKeyData->gxLen );\n\t\t\tcryptSetComponent( eccKey->gy, eccKeyData->gy, eccKeyData->gyLen );\n\t\t\tcryptSetComponent( eccKey->n, eccKeyData->n, eccKeyData->nLen );\n\t\t\t}\n\t\tcryptSetComponent( eccKey->qx, eccKeyData->qx, eccKeyData->qxLen );\n\t\tcryptSetComponent( eccKey->qy, eccKeyData->qy, eccKeyData->qyLen );\n\t\tcryptSetComponent( eccKey->d, eccKeyData->d, eccKeyData->dLen );\n\t\tstatus = cryptSetAttributeString( *signContext,\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_KEY_COMPONENTS, eccKey,\n\t\t\t\t\t\t\t\t\tsizeof( CRYPT_PKCINFO_ECC ) );\n\t\tcryptDestroyComponents( eccKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfree( eccKey );\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tprintf( \"Private key load failed with error code %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( sigCheckContext == NULL )\n\t\t\t{\n\t\t\tfree( eccKey );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n\n\t/* Create the sig.check context */\n\tif( isDevice )\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, sigCheckContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_ALGO_ECDSA );\n\telse\n\t\tstatus = cryptCreateContext( sigCheckContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_ECDSA );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfree( eccKey );\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLabel( *sigCheckContext, sigCheckContextLabel ) )\n\t\t{\n\t\tfree( eccKey );\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tcryptDestroyContext( *sigCheckContext );\n\t\treturn( FALSE );\n\t\t}\n\tcryptInitComponents( eccKey, CRYPT_KEYTYPE_PUBLIC );\n\teccKey->curveType = CRYPT_ECCCURVE_P256;\n\tif( eccKeyData->pLen > 0 )\n\t\t{\n\t\tcryptSetComponent( eccKey->p, eccKeyData->p, eccKeyData->pLen );\n\t\tcryptSetComponent( eccKey->a, eccKeyData->a, eccKeyData->aLen );\n\t\tcryptSetComponent( eccKey->b, eccKeyData->b, eccKeyData->bLen );\n\t\tcryptSetComponent( eccKey->gx, eccKeyData->gx, eccKeyData->gxLen );\n\t\tcryptSetComponent( eccKey->gy, eccKeyData->gy, eccKeyData->gyLen );\n\t\tcryptSetComponent( eccKey->n, eccKeyData->n, eccKeyData->nLen );\n\t\t}\n\tcryptSetComponent( eccKey->qx, eccKeyData->qx, eccKeyData->qxLen );\n\tcryptSetComponent( eccKey->qy, eccKeyData->qy, eccKeyData->qyLen );\n\tstatus = cryptSetAttributeString( *sigCheckContext,\n\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_KEY_COMPONENTS, eccKey,\n\t\t\t\t\t\t\t\t\t  sizeof( CRYPT_PKCINFO_ECC ) );\n\tcryptDestroyComponents( eccKey );\n\tfree( eccKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( signContext != NULL )\n\t\t\t{\n\t\t\tcryptDestroyContext( *signContext );\n\t\t\tif( isDevice )\n\t\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tsignContextLabel );\n\t\t\t}\n\t\tcryptDestroyContext( *sigCheckContext );\n\t\tprintf( \"Public key load failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nBOOLEAN loadECDSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *signContext )\n\t{\n\treturn( loadECDSAContextsEx( cryptDevice, sigCheckContext, signContext, \n\t\t\t\t\t\t\t\t ECDSA_PUBKEY_LABEL, ECDSA_PRIVKEY_LABEL ) );\n\t}\n\n/* Destroy the encryption contexts */\n\nvoid destroyContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t  const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t  const CRYPT_CONTEXT decryptContext )\n\t{\n\tint cryptAlgo, status;\n\n\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, \n\t\t\t\t\t\t\t\t&cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\tcryptAlgo = CRYPT_ALGO_RSA;\n\tstatus = cryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyContext() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t}\n\tstatus = cryptDestroyContext( decryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroyContext() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t}\n\tif( cryptDevice == CRYPT_UNUSED )\n\t\treturn;\n\n\t/* If the context is associated with a device then creating the object\n\t   will generally also create a persistent object in the device, after\n\t   performing the tests we have to explicitly delete the persistent\n\t   object */\n\tswitch( cryptAlgo )\n\t\t{\n\t\tcase CRYPT_ALGO_RSA:\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, RSA_PUBKEY_LABEL );\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_DSA:\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, DSA_PUBKEY_LABEL );\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, DSA_PRIVKEY_LABEL );\n\t\t\tbreak;\n\n\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, ECDSA_PUBKEY_LABEL );\n\t\t\tcryptDeleteKey( cryptDevice, CRYPT_KEYID_NAME, ECDSA_PRIVKEY_LABEL );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t/* No special-case handling */\n\t\t\tbreak;\n\t\t}\n\t}\n"
  },
  {
    "path": "deps/cl345/test/lowlvl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Low-level Test Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\t/* For algorithm usage */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* The size of the test buffers */\n\n#define TESTBUFFER_SIZE\t\t256\n\n/* Since the DH/ECDH operations aren't visible externally, we have to use \n   the kernel API to perform the test.  To get the necessary definitions \n   and prototypes, we have to use crypt.h, however since we've already \n   included cryptlib.h the built-in guards preclude us from pulling it in \n   again with the internal-only values defined, so we have to explicitly \n   define things like attribute values that normally aren't visible \n   externally */\n\n#ifdef TEST_DH\n  #undef __WINDOWS__\n  #undef __WIN16__\n  #undef __WIN32__\n  #undef BYTE\n  #include \"crypt.h\"\n#endif /* TEST_DH */\n\n#if defined( TEST_LOWLEVEL ) || defined( TEST_KEYSET )\t/* Needed for PGP keysets */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check for an algorithm/mode */\n\nstatic BOOLEAN checkLowlevelInfo( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tint status;\n\n\tif( isDevice )\n\t\t{\n\t\tstatus = cryptDeviceQueryCapability( cryptDevice, cryptAlgo,\n\t\t\t\t\t\t\t\t\t\t\t &cryptQueryInfo );\n\t\t}\n\telse\n\t\tstatus = cryptQueryCapability( cryptAlgo, &cryptQueryInfo );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"crypt%sQueryCapability() reports algorithm %d is not \"\n\t\t\t\t\"available, status = %d.\\n\", isDevice ? \"Device\" : \"\",\n\t\t\t\tcryptAlgo, status );\n\t\treturn( FALSE );\n\t\t}\n#ifdef UNICODE_STRINGS\n\tfprintf( outputStream, \"cryptQueryCapability() reports availability of \"\n\t\t\t \"%S algorithm with\\n  block size %d bits\", \n\t\t\t cryptQueryInfo.algoName, cryptQueryInfo.blockSize << 3 );\n#else\n\tfprintf( outputStream, \"cryptQueryCapability() reports availability of \"\n\t\t\t \"%s algorithm with\\n  block size %d bits\", \n\t\t\t cryptQueryInfo.algoName, cryptQueryInfo.blockSize << 3 );\n#endif /* UNICODE_STRINGS */\n\tif( cryptAlgo < CRYPT_ALGO_FIRST_HASH || cryptAlgo > CRYPT_ALGO_LAST_HASH )\n\t\t{\n\t\tfprintf( outputStream, \", keysize %d-%d bits (recommended = %d bits)\",\n\t\t\t\tcryptQueryInfo.minKeySize << 3,\n\t\t\t\tcryptQueryInfo.maxKeySize << 3, cryptQueryInfo.keySize << 3 );\n\t\t}\n\tfputs( \".\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n\n/* Set a pair of encrypt/decrypt buffers to a known state, and make sure\n   that they're still in that known state */\n\nstatic void initTestBuffers( BYTE *buffer1, BYTE *buffer2, const int length )\n\t{\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( resume )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 819 )\n#endif /* IBM medium iron */\n\t/* Set the buffers to a known state */\n\tmemset( buffer1, '*', length );\n\tmemcpy( buffer1, \"12345678\", 8 );\t\t/* For endianness check */\n\tif( buffer2 != NULL )\n\t\tmemcpy( buffer2, buffer1, length );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\t}\n\nstatic BOOLEAN checkTestBuffers( const BYTE *buffer1, const BYTE *buffer2 )\n\t{\n\t/* Make sure that everything went OK */\n\tif( !memcmp( buffer1, buffer2, TESTBUFFER_SIZE ) )\n\t\treturn( TRUE );\n\tputs( \"Error: Decrypted data != original plaintext.\" );\n\n\t/* Try and guess at block chaining problems */\n\tif( !memcmp( buffer1, \"12345678****\", 12 ) )\n\t\t{\n\t\tputs( \"\\t\\bIt looks like there's a problem with block chaining.\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Try and guess at endianness problems - we want \"1234\" */\n\tif( !memcmp( buffer1, \"4321\", 4 ) )\n\t\t{\n\t\tputs( \"\\t\\bIt looks like the 32-bit word endianness is reversed.\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( !memcmp( buffer1, \"2143\", 4 ) )\n\t\t{\n\t\tputs( \"\\t\\bIt looks like the 16-bit word endianness is reversed.\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( buffer1[ 0 ] >= '1' && buffer1[ 0 ] <= '9' )\n\t\t{\n\t\tputs( \"\\t\\bIt looks like there's some sort of endianness problem \"\n\t\t\t  \"which is\\n\\t more complex than just a reversal.\" );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"\\t\\bIt's probably more than just an endianness problem.\" );\n\treturn( FALSE );\n\t}\n\n/* Load the encryption contexts */\n\nstatic BOOLEAN loadContexts( CRYPT_CONTEXT *cryptContext, CRYPT_CONTEXT *decryptContext,\n\t\t\t\t\t\t\t const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t const CRYPT_MODE_TYPE cryptMode,\n\t\t\t\t\t\t\t const BYTE *key, const int length )\n\t{\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tconst BOOLEAN hasKey = ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t\t\t\t\t\t cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) || \\\n\t\t\t\t\t\t   ( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \\\n\t\t\t\t\t\t\t cryptAlgo <= CRYPT_ALGO_LAST_MAC );\n\tBOOLEAN adjustKey = FALSE;\n\tint status;\n\n\t/* Create the encryption context */\n\tif( isDevice )\n\t\t{\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, cryptContext,\n\t\t\t\t\t\t\t\t\t\t   cryptAlgo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptCreateContext( cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"crypt%sCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", isDevice ? \"Device\" : \"\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \\\n\t\tcryptAlgo != CRYPT_ALGO_RC4 )\n\t\t{\n\t\tstatus = cryptSetAttribute( *cryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t\t\t\t\tcryptMode );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcryptDestroyContext( *cryptContext );\n\t\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t\t{\n\t\t\t\t/* This mode isn't available, return a special-case value to\n\t\t\t\t   tell the calling code to continue */\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tprintf( \"Encryption mode %d selection failed with status %d, \"\n\t\t\t\t\t\"line %d.\\n\", cryptMode, status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( hasKey )\n\t\t{\n\t\tstatus = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\t\t  key, length );\n\t\tif( length > 16 && status == CRYPT_ERROR_PARAM4 )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\t\t\t  key, 16 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tputs( \"  Load of full-length key failed, using shorter 128-\"\n\t\t\t\t\t  \"bit key.\" );\n\t\t\t\tadjustKey = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Encryption key load failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( decryptContext == NULL )\n\t\treturn( TRUE );\n\n\t/* Create the decryption context */\n\tif( isDevice )\n\t\t{\n\t\tstatus = cryptDeviceCreateContext( cryptDevice, decryptContext,\n\t\t\t\t\t\t\t\t\t\t   cryptAlgo );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptCreateContext( decryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"crypt%sCreateContext() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", ( cryptDevice != CRYPT_UNUSED ) ? \\\n\t\t\t\t\t\t\t\t\t\t\"Device\" : \"\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \\\n\t\tcryptAlgo != CRYPT_ALGO_RC4 )\n\t\t{\n\t\tstatus = cryptSetAttribute( *decryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t\t\t\t\tcryptMode );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tcryptDestroyContext( *decryptContext );\n\t\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t\t{\n\t\t\t\t/* This mode isn't available, return a special-case value to\n\t\t\t\t   tell the calling code to continue */\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tprintf( \"Encryption mode %d selection failed with status %d, \"\n\t\t\t\t\t\"line %d.\\n\", cryptMode, status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( hasKey )\n\t\t{\n\t\tstatus = cryptSetAttributeString( *decryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\t\t  key, adjustKey ? 16 : length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Decryption key load failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Perform a test en/decryption */\n\nint testCrypt( const CRYPT_CONTEXT cryptContext, \n\t\t\t   const CRYPT_CONTEXT decryptContext,\n\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer, \n\t\t\t   const BOOLEAN isDevice, const BOOLEAN noWarnFail )\n\t{\n\tBYTE iv[ CRYPT_MAX_IVSIZE ];\n\tBYTE localBuffer[ TESTBUFFER_SIZE ];\n\tint cryptMode = CRYPT_MODE_NONE, status;\n\n\t/* If the user hasn't supplied a test buffer, use our own one */\n\tif( buffer == NULL )\n\t\t{\n\t\tbuffer = localBuffer;\n\t\tinitTestBuffers( buffer, NULL, TESTBUFFER_SIZE );\n\t\t}\n\n\t/* Find out about the algorithm we're using */\n\tif( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\tcryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t\t\t&cryptMode );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \\\n\t\tcryptMode == CRYPT_MODE_CFB )\n\t\t{\n\t\t/* Encrypt the buffer in two odd-sized chunks */\n\t\tstatus = cryptEncrypt( cryptContext, buffer, 79 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( cryptContext, buffer + 79,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 79 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't encrypt data, status = %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Copy the IV from the encryption to the decryption context if\n\t\t   necessary */\n\t\tif( cryptAlgo != CRYPT_ALGO_RC4 )\n\t\t\t{\n\t\t\tint ivLength;\n\n\t\t\tstatus = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  iv, &ivLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't retrieve IV after encryption, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tstatus = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  iv, ivLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't load IV for decryption, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Decrypt the buffer in different odd-size chunks */\n\t\tstatus = cryptDecrypt( decryptContext, buffer, 125 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptDecrypt( decryptContext, buffer + 125,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 125 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't decrypt data, status = %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \\\n\t\t( cryptMode == CRYPT_MODE_ECB || cryptMode == CRYPT_MODE_CBC || \\\n\t\t  cryptMode == CRYPT_MODE_GCM ) )\n\t\t{\n\t\t/* Encrypt the buffer in two odd-sized chunks */\n\t\tstatus = cryptEncrypt( cryptContext, buffer, 80 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( cryptContext, buffer + 80,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 80 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't encrypt data, status = %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* Copy the IV from the encryption to the decryption context if\n\t\t   necessary */\n\t\tif( cryptMode != CRYPT_MODE_ECB )\n\t\t\t{\n\t\t\tint ivLength;\n\n\t\t\tstatus = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  iv, &ivLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't retrieve IV after encryption, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\tstatus = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  iv, ivLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't load IV for decryption, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Decrypt the buffer in different odd-size chunks */\n\t\tstatus = cryptDecrypt( decryptContext, buffer, 128 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptDecrypt( decryptContext, buffer + 128,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 128 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't decrypt data, status = %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifdef TEST_DH\n\tif( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_ECDH )\n\t\t{\n\t\tKEYAGREE_PARAMS keyAgreeParams;\n\t\tint status;\n\n\t\t/* Perform the DH/ECDH key agreement */\n\t\tmemset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );\n#if 0\n\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_CTX_ENCRYPT,\n\t\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT,\n\t\t\t\t\t\t\t\t\t  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );\n\t\t\t}\n#else\n\t\tstatus = cryptDeviceQueryCapability( cryptContext, 1001,\n\t\t\t\t\t\t\t\t\t( CRYPT_QUERY_INFO * ) &keyAgreeParams );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptDeviceQueryCapability( cryptContext, 1002,\n\t\t\t\t\t\t\t\t\t\t( CRYPT_QUERY_INFO * ) &keyAgreeParams );\n\t\t\t}\n#endif /* 0 */\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't perform DH/ECDH key agreement, status = %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n#endif /* TEST_DH */\n\tif( cryptAlgo == CRYPT_ALGO_RSA )\n\t\t{\n\t\tstatic const BYTE rsa512Value[] = \\\n\t\t\t\"\\x4E\\x1F\\x2F\\x10\\xA9\\xFB\\x4F\\xD9\\xC1\\x25\\x79\\x7A\\x36\\x00\\x58\\xD0\"\n\t\t\t\"\\x9E\\x8B\\x9F\\xBA\\xC7\\x04\\x10\\x77\\xDB\\xBC\\xC9\\xD1\\x70\\xCD\\xF6\\x86\"\n\t\t\t\"\\xA4\\xDC\\x39\\xA9\\x57\\xD7\\xC7\\xE0\\x87\\xF2\\x31\\xDF\\x83\\x7d\\x27\\x0E\"\n\t\t\t\"\\xB4\\xA6\\x93\\x3D\\x11\\xEB\\xA5\\x0E\\x42\\x66\\x7B\\x30\\x50\\x84\\xC1\\x81\";\n\t\tstatic const BYTE rsa1024Value[] = \\\n\t\t\t\"\\x84\\x8E\\x00\\x3E\\x49\\x11\\x0D\\x42\\x4C\\x71\\x6B\\xB4\\xCF\\x13\\xDD\\xCD\"\n\t\t\t\"\\x12\\x30\\x56\\xC2\\x4A\\x55\\x3B\\xD8\\x30\\xA2\\xB8\\x73\\xA7\\xAB\\xF0\\x7A\"\n\t\t\t\"\\x2E\\x07\\x20\\xCC\\xBE\\xEA\\x58\\x03\\x56\\xF6\\x18\\x27\\x28\\x4F\\xE1\\x02\"\n\t\t\t\"\\xC6\\x49\\x79\\x6C\\xB4\\x7E\\x6C\\xC6\\x93\\x2E\\xF1\\x46\\x83\\x15\\x5A\\xB7\"\n\t\t\t\"\\x7D\\xCC\\x21\\xEE\\x4E\\x3E\\x0B\\x8B\\x85\\xEE\\x08\\x21\\xE6\\xA7\\x31\\x53\"\n\t\t\t\"\\x2E\\x92\\x3D\\x2D\\xB0\\xD4\\xA1\\x30\\xF4\\xE9\\xEB\\x37\\xBF\\xCD\\x2F\\xE1\"\n\t\t\t\"\\x60\\x89\\x19\\xB6\\x8C\\x01\\xFB\\xD8\\xAC\\xF5\\xC7\\x4B\\xB4\\x74\\x8A\\x35\"\n\t\t\t\"\\x79\\xE6\\xE0\\x48\\xBD\\x9C\\x9F\\xD7\\x4A\\x1C\\x8A\\x58\\xAB\\xA9\\x3C\\x44\";\n\t\tBYTE testBuffer[ TESTBUFFER_SIZE ], tmpBuffer[ 32 ];\n\t\tBOOLEAN encryptOK = TRUE;\n\t\tint length;\n\n\t\t/* Take a copy of the input so that we can compare it with the \n\t\t   decrypted output and find out how much data we need to process */\n\t\tmemcpy( testBuffer, buffer, TESTBUFFER_SIZE );\n\t\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t\t\t\t\t&length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Since we're doing raw RSA encryption we need to format the data\n\t\t   specially to work with the RSA key being used.  If we're using the\n\t\t   cryptlib native routines, we need to ensure that the magnitude of\n\t\t   the integer corresponding to the data to be encrypted is less than\n\t\t   the modulus, which we do by setting the first byte of the buffer\n\t\t   to 1.  If we're using a crypto device, we need to create a (dummy)\n\t\t   PKCS #1-like format since some devices expect to see PKCS #1-\n\t\t   formatted data as input to/output from the RSA encryption/\n\t\t   decryption operation */\n\t\tmemcpy( tmpBuffer, buffer, 18 );\n\t\tif( isDevice )\n\t\t\t{\n\t\t\tmemcpy( buffer, \"\\x00\\x02\\xA5\\xA5\\xA5\\xA5\\xA5\\xA5\"\n\t\t\t\t\t\t\t\"\\xA5\\xA5\\xA5\\xA5\\xA5\\xA5\\xA5\\xA5\"\n\t\t\t\t\t\t\t\"\\xA5\\x00\", 18 );\n\t\t\t}\n\t\telse\n\t\t\tbuffer[ 0 ] = 1;\n\n\t\t/* Since the PKC algorithms only handle a single block, we only\n\t\t   perform a single encrypt and decrypt operation */\n\t\tstatus = cryptEncrypt( cryptContext, buffer, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( !noWarnFail )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't encrypt data, status = %d, line %d.\\n\", \n\t\t\t\t\t\tstatus, __LINE__ );\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( cryptAlgo == CRYPT_ALGO_RSA && \\\n\t\t\t!isDevice && buffer != localBuffer && \\\n\t\t\tmemcmp( buffer, ( length == 64 ) ? rsa512Value : rsa1024Value,\n\t\t\t\t\tlength ) )\n\t\t\t{\n\t\t\t/* For a non-randomized PKC the encryption of the fixed value\n\t\t\t   produces known output, so if we're being called from with a\n\t\t\t   fixed test key from testLowlevel() we make sure that this \n\t\t\t   matches the expected value.  This makes diagnosing problems \n\t\t\t   rather easier */\n\t\t\tputs( \"The actual encrypted value doesn't match the expected value.\" );\n\t\t\tencryptOK = FALSE;\n\t\t\t}\n\t\tstatus = cryptDecrypt( decryptContext, buffer, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tif( !noWarnFail )\n\t\t\t\t{\n\t\t\t\tif( encryptOK )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Couldn't decrypt data even though the \"\n\t\t\t\t\t\t\t\"encrypted input data was valid,\\nstatus = \"\n\t\t\t\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Couldn't decrypt data, probably because the \"\n\t\t\t\t\t\t\t\"data produced by the encrypt step\\nwas \"\n\t\t\t\t\t\t\t\"invalid, status = %d, line %d.\\n\", status, \n\t\t\t\t\t\t\t__LINE__ );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( isDevice )\n\t\t\tmemcpy( buffer, tmpBuffer, 18 );\n\t\telse\n\t\t\tbuffer[ 0 ] = tmpBuffer[ 0 ];\n\n\t\t/* Make sure that the recovered result matches the input data */\n\t\tif( memcmp( buffer, testBuffer, length ) )\n\t\t\t{\n\t\t\tif( encryptOK )\n\t\t\t\t{\n\t\t\t\t/* This could happen with simple-minded CRT implementations\n\t\t\t\t   that only work when p > q (the test key has p < q in\n\t\t\t\t   order to find this problem) */\n\t\t\t\tputs( \"Decryption failed even though encryption produced \"\n\t\t\t\t\t  \"valid data.  The RSA\\ndecryption step is broken.\" );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tputs( \"Decryption failed because the encryption step \"\n\t\t\t\t\t  \"produced invalid data. The RSA\\nencryption step is \"\n\t\t\t\t\t  \"broken.\" );\n\t\t\t\t}\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( !encryptOK )\n\t\t\t\t{\n\t\t\t\tputs( \"Decryption succeeded even though encryption produced \"\n\t\t\t\t\t  \"invalid data.  The RSA\\nimplementation is broken.\" );\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \\\n\t\tcryptAlgo <= CRYPT_ALGO_LAST_MAC )\n\t\t{\n\t\t/* Hash the buffer in two odd-sized chunks.  Note the use of the hash\n\t\t   wrap-up call, this is the only time when we can call\n\t\t   cryptEncrypt() with a zero length */\n\t\tstatus = cryptEncrypt( cryptContext, buffer, 80 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( cryptContext, buffer + 80,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 80 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, \n\t\t\t\t\t\t\t\t   0 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't %s data, status = %d, line %d.\\n\", \n\t\t\t\t\t( cryptAlgo >= CRYPT_ALGO_FIRST_MAC ) ? \"MAC\" : \"hash\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\t/* If we're just testing for the ability to use a context, the same \n\t\t   hash context may be used for both operations, in which case we \n\t\t   have to reset the context between the two */\n\t\tif( cryptContext == decryptContext )\n\t\t\tcryptDeleteAttribute( cryptContext, CRYPT_CTXINFO_HASHVALUE );\n\n\t\t/* Hash the buffer in different odd-size chunks */\n\t\tstatus = cryptEncrypt( decryptContext, buffer, 128 );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( decryptContext, buffer + 128,\n\t\t\t\t\t\t\t\t   TESTBUFFER_SIZE - 128 );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( decryptContext, buffer + TESTBUFFER_SIZE, \n\t\t\t\t\t\t\t\t   0 );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't %s data, status = %d, line %d.\\n\", \n\t\t\t\t\t( cryptAlgo >= CRYPT_ALGO_FIRST_MAC ) ? \"MAC\" : \"hash\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\n\t\treturn( CRYPT_OK );\n\t\t}\n\n\tprintf( \"Unknown encryption algorithm/mode %d.\\n\", cryptAlgo );\n\treturn( CRYPT_OK );\n\t}\n\n/* Perform a test en/decryption using the direct API */\n\n#if defined( CONFIG_DIRECT_API ) && !defined( CONFIG_FUZZ )\n\nstatic int testCryptDirectAPI( const CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_DIRECT_FUNCTION encryptFunction, decryptFunction;\n\tBYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];\n\tBYTE iv[ CRYPT_MAX_IVSIZE ];\n\tvoid *contextPtr;\n\tint cryptMode = CRYPT_MODE_NONE, ivLength = 0, status;\n\n\t/* RC4 is a pure stream cipher that updates its internal state for every\n\t   byte encrypted, so we can't use the same context for en- and \n\t   decryption */\n\tif( cryptAlgo == CRYPT_ALGO_RC4 )\n\t\treturn( CRYPT_OK );\n\n\t/* Get context information */\n\tif( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\tcryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_MODE, \n\t\t\t\t\t\t\t\t\t&cryptMode );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( cryptMode != CRYPT_MODE_ECB )\n\t\t\t{\n\t\t\t/* Set a fixed IV for the encryption, which will be reused for \n\t\t\t   decryption */\n\t\t\tmemset( iv, '#', CRYPT_MAX_IVSIZE );\n\t\t\tstatus = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  NULL, &ivLength );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttributeString( cryptContext, \n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t\t  iv, ivLength );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\tstatus = cryptGetDirectAPI( cryptContext, &contextPtr, &encryptFunction, \n\t\t\t\t\t\t\t\t&decryptFunction );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't get direct-access function for algorithm %d, \"\n\t\t\t\t\"status = %d, line %d.\\n\", cryptAlgo, status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\n\t/* Encrypt and decrypt data using the direct-access API */\n\tinitTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );\n\tstatus = encryptFunction( contextPtr, buffer, TESTBUFFER_SIZE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( cryptMode == CRYPT_MODE_CBC || cryptMode == CRYPT_MODE_CFB || \\\n\t\t\tcryptMode == CRYPT_MODE_GCM )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\t\t\t  iv, ivLength );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = decryptFunction( contextPtr, buffer, TESTBUFFER_SIZE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't encrypt data, status = %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tif( !checkTestBuffers( buffer, testBuffer ) )\n\t\treturn( CRYPT_ERROR_FAILED );\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* CONFIG_DIRECT_API && !CONFIG_FUZZ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tLow-level Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test an algorithm/mode implementation */\n\nint testLowlevel( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo, const BOOLEAN checkOnly )\n\t{\n\tCRYPT_MODE_TYPE cryptMode = CRYPT_MODE_ECB;\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tBYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];\n\tconst BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;\n\tBOOLEAN modesTested[ 8 ] = { 0 }, testSucceeded = FALSE;\n\tint status;\n\n\t/* Initialise the test buffers */\n\tinitTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );\n\n\t/* Check cryptlib's capabilities */\n\tif( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )\n\t\treturn( FALSE );\n\n\t/* If we're only doing a capability check, don't try anything else */\n\tif( checkOnly )\n\t\treturn( TRUE );\n\n\t/* Since DH/ECDH and KEA only perform key agreement rather than a true \n\t   key exchange we can't test their encryption capabilities unless we're\n\t   using a custom-modified version of cryptlib */\n#ifndef TEST_DH\n\tif( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_ECDH )\n\t\treturn( TRUE );\n#endif /* TEST_DH */\n\n\t/* Test each mode of an algorithm.  We have to be very careful about\n\t   destroying any objects we create before we exit, because objects left\n\t   active in a device will prevent it from being shut down once the\n\t   tests have completed */\n\tdo\n\t\t{\n\t\t/* Set up an encryption context, load a user key into it, and\n\t\t   perform a key setup */\n\t\tswitch( cryptAlgo )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_DES:\n\t\t\t\tstatus = loadContexts( &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\t\t   cryptDevice, cryptAlgo, cryptMode,\n\t\t\t\t\t\t\t\t\t   ( BYTE * ) \"12345678\", 8 );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_CAST:\n\t\t\tcase CRYPT_ALGO_IDEA:\n\t\t\tcase CRYPT_ALGO_AES:\n\t\t\t\tstatus = loadContexts( &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\t\t   cryptDevice, cryptAlgo, cryptMode,\n\t\t\t\t\t\t\t\t\t   ( BYTE * ) \"1234567887654321\", 16 );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_3DES:\n\t\t\t\tstatus = loadContexts( &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\t\t   cryptDevice, cryptAlgo, cryptMode,\n\t\t\t\t\t\t\t\t\t   ( BYTE * ) \"123456788765432112345678\", 24 );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_RC2:\n\t\t\tcase CRYPT_ALGO_RC4:\n\t\t\tcase CRYPT_ALGO_HMAC_SHA1:\n\t\t\tcase CRYPT_ALGO_HMAC_SHA2:\n\t\t\t\tstatus = loadContexts( &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\t\t   cryptDevice, cryptAlgo, cryptMode,\n\t\t\t\t\t\t\t\t\t   ( BYTE * ) \"1234567890098765432112345678900987654321\", 40 );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_MD5:\n\t\t\tcase CRYPT_ALGO_SHA1:\n\t\t\tcase CRYPT_ALGO_SHA2:\n\t\t\t\tstatus = loadContexts( &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\t\t   cryptDevice, cryptAlgo, CRYPT_MODE_NONE,\n\t\t\t\t\t\t\t\t\t   ( BYTE * ) \"\", 0 );\n\t\t\t\tbreak;\n\n#ifdef TEST_DH\n\t\t\tcase CRYPT_ALGO_DH:\n\t\t\t\tstatus = loadDHKey( cryptDevice, &cryptContext );\n\t\t\t\tbreak;\n#endif /* TEST_DH */\n\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\tstatus = loadRSAContexts( cryptDevice, &cryptContext,\n\t\t\t\t\t\t\t\t\t\t  &decryptContext );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\tstatus = loadDSAContexts( cryptDevice, &cryptContext,\n\t\t\t\t\t\t\t\t\t\t  &decryptContext );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_ELGAMAL:\n\t\t\t\tstatus = loadElgamalContexts( &cryptContext, &decryptContext );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t\tstatus = loadECDSAContexts( cryptDevice, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t\t&decryptContext );\n\t\t\t\tbreak;\n\n#ifdef TEST_DH\n\t\t\tcase CRYPT_ALGO_ECDH:\n\t\t\t\tstatus = loadECDHKey( cryptDevice, &cryptContext );\n\t\t\t\tbreak;\n#endif /* TEST_DH */\n\n\t\t\tdefault:\n\t\t\t\tprintf( \"Unknown encryption algorithm ID %d, cannot perform \"\n\t\t\t\t\t\t\"encryption test, line %d.\\n\", cryptAlgo, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\t/* It's a conventional algorithm for which this mode isn't\n\t\t\t   available, try a different mode */\n\t\t\tcryptMode++;\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\n\t\t/* DLP-based algorithms can't be called directly from user code\n\t\t   because of the special data-formatting requirements */\n\t\tif( cryptAlgo == CRYPT_ALGO_DSA || cryptAlgo == CRYPT_ALGO_ELGAMAL || \\\n\t\t\tcryptAlgo == CRYPT_ALGO_ECDSA )\n\t\t\t{\n\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* Perform a test en/decryption */\n\t\tstatus = testCrypt( cryptContext, decryptContext, cryptAlgo, buffer, \n\t\t\t\t\t\t\tisDevice, FALSE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\tif( isDevice && status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t\t{\n\t\t\t\t/* Some primitive tokens or accelerators support only the\n\t\t\t\t   barest minimum of functionality, which may include being\n\t\t\t\t   able to create objects but not use them (e.g. public key\n\t\t\t\t   objects in a device which is just an RSA private-key\n\t\t\t\t   modexp engine).  Because of this we may get a\n\t\t\t\t   CRYPT_ERROR_NOTAVAIL when we try and perform a low-level\n\t\t\t\t   crypto test, this isn't normally a problem for cryptlib\n\t\t\t\t   high-level objects because public-key ops are always done\n\t\t\t\t   in software, but when we explicitly try to do them in the\n\t\t\t\t   token it's a problem.  Because of this we report a problem\n\t\t\t\t   but continue anyway */\n\t\t\t\tputs( \"The crypto device reported that this operation isn't \"\n\t\t\t\t\t  \"available even though it\\nsupports the use of \"\n\t\t\t\t\t  \"encryption objects that implement this algorithm.  \"\n\t\t\t\t\t  \"This\\nis probably a bare-bones device that only \"\n\t\t\t\t\t  \"supports minimal functionality (eg\\nprivate-key \"\n\t\t\t\t\t  \"decryption but not encryption).\" );\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Make sure that everything went OK */\n\t\tif( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )\n\t\t\t{\n\t\t\tBYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];\n\t\t\tint length1, length2;\n\n\t\t\tstatus = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t\t  hash1, &length1 );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptGetAttributeString( decryptContext, \n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t\t\t  hash2, &length2 );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't get hash information, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Hash value of identical buffers differs.\" );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !memcmp( hash1, \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 8 ) || \\\n\t\t\t\t!memcmp( hash2, \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 8 ) )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Hash contains all zeroes.\" );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Make sure that we can get repeatable results after deleting\n\t\t\t   the hash/MAC and rehashing the data */\n\t\t\tstatus = cryptDeleteAttribute( cryptContext,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_HASHVALUE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptDeleteAttribute( decryptContext,\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_CTXINFO_HASHVALUE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Deletion of hash/MAC value failed with status %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( cryptStatusError( testCrypt( cryptContext, decryptContext,\n\t\t\t\t\t\t\t\t\t\t\t cryptAlgo, buffer, isDevice, \n\t\t\t\t\t\t\t\t\t\t\t FALSE ) ) )\n\t\t\t\t{\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,\n\t\t\t\t\t\t\t\t\t\t\t  hash1, &length1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't get hash information for re-hashed data, \"\n\t\t\t\t\t\t\"status = %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Hash value of re-hashed data differs.\" );\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* If it's a PKC then we'll have performed the check during the\n\t\t\t   encrypt/decrypt step */\n\t\t\tif( cryptAlgo < CRYPT_ALGO_FIRST_PKC && \\\n\t\t\t\t!checkTestBuffers( buffer, testBuffer ) )\n\t\t\t\t{\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Remember that at least one test succeeded */\n\t\ttestSucceeded = TRUE;\n\t\tif( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t\tmodesTested[ cryptMode++ ] = TRUE;\n\n\t\t/* If use of the direct API is enabled, check this */\n#ifdef CONFIG_DIRECT_API\n\t\tif( ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) || \\\n\t\t\t( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_HASH ) || \\\n\t\t\t( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \\\n\t\t\t  cryptAlgo <= CRYPT_ALGO_LAST_MAC ) )\n\t\t\t{\n\t\t\tstatus = testCryptDirectAPI( cryptContext, cryptAlgo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n#endif /* CONFIG_DIRECT_API */\n\n\t\t/* Clean up */\n\t\tdestroyContexts( cryptDevice, cryptContext, decryptContext );\n\t\t}\n\twhile( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL && \\\n\t\t   cryptMode < CRYPT_MODE_LAST );\n\n\t/* If it's a conventional algorithm, report the encryption modes that\n\t   were tested */\n\tif( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )\n\t\t{\n\t\tfprintf( outputStream, \"  Encryption modes tested:\" );\n\t\tif( modesTested[ CRYPT_MODE_ECB ] )\n\t\t\tfprintf( outputStream, \" ECB\" );\n\t\tif( modesTested[ CRYPT_MODE_CBC ] )\n\t\t\tfprintf( outputStream, \" CBC\" );\n\t\tif( modesTested[ CRYPT_MODE_CFB ] )\n\t\t\tfprintf( outputStream, \" CFB\" );\n\t\tif( modesTested[ CRYPT_MODE_GCM ] )\n\t\t\tfprintf( outputStream, \" GCM\" );\n\t\tfputs( \".\\n\", outputStream );\n\t\t}\n\n\t/* Make sure that at least one of the algorithm's modes was tested */\n\tif( !testSucceeded )\n\t\t{\n\t\tputs( \"No processing modes were found for this algorithm.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Test the ability of the RSA key-load code to reconstruct a full RSA key\n   from only the minimal non-CRT components */\n\nint testRSAMinimalKey( void )\n\t{\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tBYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];\n\tint status;\n\n\tfputs( \"Testing ability to recover CRT components for RSA private \"\n\t\t   \"key...\\n\", outputStream );\n\n\t/* Load the RSA contexts from the minimal (non-CRT) RSA key */\n\tstatus = loadRSAContextsEx( CRYPT_UNUSED, &cryptContext, &decryptContext,\n\t\t\t\t\t\t\t\tRSA_PUBKEY_LABEL, RSA_PRIVKEY_LABEL, FALSE, \n\t\t\t\t\t\t\t\tTRUE );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Initialise the test buffers */\n\tinitTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );\n\n\t/* Make sure that we can encrypt and decrypt with the reconstituted CRT\n\t   private key */\n\tstatus = testCrypt( cryptContext, decryptContext, CRYPT_ALGO_RSA, \n\t\t\t\t\t\tbuffer, FALSE, FALSE );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tdestroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );\n\n\tfputs( \"RSA CRT component recovery test succeeded.\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tPerformance Tests\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* General performance characteristics test.  Since high-precision timing is\n   rather OS-dependent, we only enable this under Windows where we've got\n   guaranteed high-res timer access */\n\n#if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1100 )\n\n#include <math.h>\t/* For sqrt() for standard deviation */\n\n#define NO_TESTS\t25\n\n/* Print timing info.  This gets a bit hairy because we're actually counting\n   timer ticks rather than thread times, which means we'll be affected by\n   things like context switches.  There are two approaches to this:\n\n\t1. Take the fastest time, which will be the time least affected by system\n\t   overhead.\n\n\t2. Apply standard statistical techniques to weed out anomalies.  Since\n\t   this is just for testing purposes all we do is discard any results\n\t   out by more than 10%, which is crude but reasonably effective.  A\n\t   more rigorous approach is to discards results more than n standard\n\t   deviations out, but this gets screwed up by the fact that a single\n\t   context switch of 20K ticks can throw out results from an execution\n\t   time of only 50 ticks.  In any case (modulo context switches) the\n\t   fastest, 10%-out, and 2 SD out times are all within about 1% of each\n\t   other, so all methods are roughly equally accurate */\n\nstatic void printTimes( long times[ NO_TESTS + 1 ][ 8 ] )\n\t{\n\tint i;\n\n\tfor( i = 0; i < 7; i++ )\n\t\t{\n\t\tlong timeSum = 0, timeAvg, timeDelta;\n\t\tlong timeMin = 1000000L, timeCorrSum10 = 0, timeCorrSumSD = 0;\n#ifdef USE_SD\n\t\tdouble stdDev;\n#endif /* USE_SD */\n\t\tint j, timesCount10 = 0, timesCountSD = 0;\n\n\t\t/* Find the mean execution time */\n\t\tfor( j = 1; j < NO_TESTS + 1; j++ )\n\t\t\ttimeSum += times[ j ][ i ];\n\t\ttimeAvg = timeSum / NO_TESTS;\n\t\ttimeDelta = timeSum / 10;\t/* 10% variation */\n\t\tif( timeSum == 0 )\n\t\t\t{\n\t\t\t/* Some ciphers can't provide results for some cases (e.g.\n\t\t\t   AES for 8-byte blocks) */\n\t\t\tprintf( \"      \" );\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Find the fastest overall time */\n\t\tfor( j = 1; j < NO_TESTS + 1; j++ )\n\t\t\tif( times[ j ][ i ] < timeMin )\n\t\t\t\ttimeMin = times[ j ][ i ];\n\n\t\t/* Find the mean time, discarding anomalous results more than 10%\n\t\t   out */\n\t\tfor( j = 1; j < NO_TESTS + 1; j++ )\n\t\t\tif( times[ j ][ i ] > timeAvg - timeDelta && \\\n\t\t\t\ttimes[ j ][ i ] < timeAvg + timeDelta )\n\t\t\t\t{\n\t\t\t\ttimeCorrSum10 += times[ j ][ i ];\n\t\t\t\ttimesCount10++;\n\t\t\t\t}\n\t\tprintf( \"%6d\", timeCorrSum10 / timesCount10 );\n#if 0\t/* Print difference to fastest time, usually only around 1% */\n\t\tprintf( \"(%4d)\", ( timeCorrSum10 / timesCount10 ) - timeMin );\n#endif /* 0 */\n\n#ifdef USE_SD\n\t\t/* Find the standard deviation */\n\t\tfor( j = 1; j < NO_TESTS + 1; j++ )\n\t\t\t{\n\t\t\tconst long timeDev = times[ j ][ i ] - timeAvg;\n\n\t\t\ttimeCorrSumSD += ( timeDev * timeDev );\n\t\t\t}\n\t\tstdDev = timeCorrSumSD / NO_TESTS;\n\t\tstdDev = sqrt( stdDev );\n\n\t\t/* Find the mean time, discarding anomalous results more than two\n\t\t   standard deviations out */\n\t\ttimeCorrSumSD = 0;\n\t\ttimeDelta = ( long ) stdDev * 2;\n\t\tfor( j = 1; j < NO_TESTS + 1; j++ )\n\t\t\tif( times[ j ][ i ] > timeAvg - timeDelta && \\\n\t\t\t\ttimes[ j ][ i ] < timeAvg + timeDelta )\n\t\t\t\t{\n\t\t\t\ttimeCorrSumSD += times[ j ][ i ];\n\t\t\t\ttimesCountSD++;\n\t\t\t\t}\n\t\tif( timesCountSD == 0 )\n\t\t\ttimesCountSD++;\t/* Context switch, fudge it */\n\t\tprintf( \"%6d\", timeCorrSumSD / timesCountSD );\n\n#if 1\t/* Print difference to fastest and mean times, usually only around\n\t\t   1% */\n\t\tprintf( \" (dF = %4d, dM = %4d)\\n\",\n\t\t\t\t( timeCorrSumSD / timesCountSD ) - timeMin,\n\t\t\t\tabs( ( timeCorrSumSD / timesCountSD ) - \\\n\t\t\t\t\t ( timeCorrSum10 / timesCount10 ) ) );\n#endif /* 0 */\n#endif /* USE_SD */\n\t\t}\n\tprintf( \"\\n\" );\n\t}\n\nstatic long encOne( const CRYPT_CONTEXT cryptContext, BYTE *buffer,\n\t\t\t\t\tconst int length )\n\t{\n\tunsigned long timeVal;\n\tint status;\n\n\tmemset( buffer, '*', length );\n\ttimeVal = timeDiff( 0 );\n\tstatus = cryptEncrypt( cryptContext, buffer, length );\n\treturn( timeDiff( timeVal ) );\n\t}\n\nstatic int encTest( const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer,\n\t\t\t\t\tlong times[] )\n\t{\n\tint index = 0;\n\n\ttimes[ index++ ] = ( cryptAlgo != CRYPT_ALGO_AES ) ? \\\n\t\t\t\t\t   encOne( cryptContext, buffer, 8 ) : 0;\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 16 );\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 64 );\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 1024 );\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 4096 );\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 8192 );\n\ttimes[ index++ ] = encOne( cryptContext, buffer, 65536L );\n\treturn( TRUE );\n\t}\n\nstatic int encTests( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t const CRYPT_ALGO_TYPE cryptMode,\n\t\t\t\t\t BYTE *buffer )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tunsigned long times[ NO_TESTS + 1 ][ 8 ], timeVal, timeSum = 0;\n\tint i, status;\n\n\tmemset( buffer, 0, 100000L );\n\n\t/* Set up the context for use */\n\tif( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )\n\t\treturn( FALSE );\n\tfor( i = 0; i < 10; i++ )\n\t\t{\n\t\ttimeVal = timeDiff( 0 );\n\t\tstatus = loadContexts( &cryptContext, NULL, cryptDevice,\n\t\t\t\t\t\t\t   cryptAlgo, cryptMode,\n\t\t\t\t\t\t\t   ( BYTE * ) \"12345678901234567890\",\n\t\t\t\t\t\t\t   ( cryptAlgo == CRYPT_ALGO_DES ) ? 8 : \\\n\t\t\t\t\t\t\t   ( cryptAlgo == CRYPT_ALGO_3DES || \\\n\t\t\t\t\t\t\t     cryptAlgo == CRYPT_ALGO_RC4 || \\\n\t\t\t\t\t\t\t\t cryptAlgo == CRYPT_ALGO_AES ) ? 16 : 0 );\n\t\ttimeVal = timeDiff( timeVal );\n\t\tif( status == CRYPT_ERROR_NOTAVAIL || !status )\n\t\t\treturn( FALSE );\n\t\ttimeSum += timeVal;\n\t\tif( i < 9 )\n\t\t\tcryptDestroyContext( cryptContext );\n\t\t}\n\tprintf( \"Setup time = %d ticks.\\n\", timeSum / 10 );\n\tputs( \"     8    16    64    1K    4K    8K   64K\" );\n\tputs( \"  ----  ----  ----  ----  ----  ----  ----\" );\n\n\t/* Run the encryption tests NO_TESTS times, discard the first set of\n\t   results since the cache will be empty at that point */\n\tfor( i = 0; i < NO_TESTS + 1; i++ )\n\t\tencTest( cryptContext, cryptAlgo, buffer, times[ i ] );\n\tprintTimes( times );\n\n\t/* Re-run the encryption tests with a 1-byte misalignment */\n\tfor( i = 0; i < NO_TESTS + 1; i++ )\n\t\tencTest( cryptContext, cryptAlgo, buffer + 1, times[ i ] );\n\tprintTimes( times );\n\n\t/* Re-run the encryption tests with a 4-byte misalignment */\n\tfor( i = 0; i < NO_TESTS + 1; i++ )\n\t\tencTest( cryptContext, cryptAlgo, buffer + 4, times[ i ] );\n\tprintTimes( times );\n\n\t/* Re-run the test 1000 times with various buffer alignments */\n\ttimeVal = 0;\n\tfor( i = 0; i < 1000; i++ )\n\t\ttimeVal += encOne( cryptContext, buffer, 1024 );\n\tprintf( \"Aligned: %d \", timeVal / 1000 );\n\ttimeVal = 0;\n\tfor( i = 0; i < 1000; i++ )\n\t\ttimeVal += encOne( cryptContext, buffer + 1, 1024 );\n\tprintf( \"misaligned + 1: %d \", timeVal / 1000 );\n\ttimeVal = 0;\n\tfor( i = 0; i < 1000; i++ )\n\t\ttimeVal += encOne( cryptContext, buffer + 4, 1024 );\n\tprintf( \"misaligned + 4: %d.\\n\", timeVal / 1000 );\n\n\treturn( TRUE );\n\t}\n\nvoid performanceTests( const CRYPT_DEVICE cryptDevice )\n\t{\n\tLARGE_INTEGER performanceCount;\n\tBYTE *buffer;\n\n\tQueryPerformanceFrequency( &performanceCount );\n\tprintf( \"Clock ticks %d times per second.\\n\", performanceCount.LowPart );\n\tif( ( buffer = malloc( 100000L ) ) == NULL )\n\t\t{\n\t\tputs( \"Couldn't 100K allocate test buffer.\" );\n\t\treturn;\n\t\t}\n#ifdef USE_DES\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_ECB, buffer );\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_CBC, buffer );\n#endif /* USE_DES */\n#ifdef USE_3DES\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_ECB, buffer );\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, buffer );\n#endif /* USE_3DES */\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_AES, CRYPT_MODE_CBC, buffer );\n#ifdef USE_MD5\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_MD5, CRYPT_MODE_NONE, buffer );\n#endif /* USE_MD5 */\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_SHA1, CRYPT_MODE_NONE, buffer );\n\tencTests( CRYPT_UNUSED, CRYPT_ALGO_SHA2, CRYPT_MODE_NONE, buffer );\n\tfree( buffer );\n\t}\n#endif /* Win32 with VC++ */\n\n#endif /* TEST_LOWLEVEL || TEST_KEYSET */\n"
  },
  {
    "path": "deps/cl345/test/misc/sshkey1.asc",
    "content": "---- BEGIN SSH2 PUBLIC KEY ----\nSubject: galb\nComment: 1024-bit rsa, created by galb@shimi Mon Jan 15 08:31:24 2001\nAAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt459\n6k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6\nNUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=\n---- END SSH2 PUBLIC KEY ----\n"
  },
  {
    "path": "deps/cl345/test/misc/sshkey2.asc",
    "content": "---- BEGIN SSH2 PUBLIC KEY ----\nAAAAB3NzaC1kc3MAAACBAPY8ZOHY2yFSJA6XYC9HRwNHxaehvx5wOJ0rzZdzoSOXxbETW6\nToHv8D1UJ/z+zHo9Fiko5XybZnDIaBDHtblQ+Yp7StxyltHnXF1YLfKD1G4T6JYrdHYI14\nOm1eg9e4NnCRleaqoZPF3UGfZia6bXrGTQf3gJq2e7Yisk/gF+1VAAAAFQDb8D5cvwHWTZ\nDPfX0D2s9Rd7NBvQAAAIEAlN92+Bb7D4KLYk3IwRbXblwXdkPggA4pfdtW9vGfJ0/RHd+N\njB4eo1D+0dix6tXwYGN7PKS5R/FXPNwxHPapcj9uL1Jn2AWQ2dsknf+i/FAAvioUPkmdMc\n0zuWoSOEsSNhVDtX3WdvVcGcBq9cetzrtOKWOocJmJ80qadxTRHtUAAACBAN7CY+KKv1gH\npRzFwdQm7HK9bb1LAo2KwaoXnadFgeptNBQeSXG1vO+JsvphVMBJc9HSn24VYtYtsMu74q\nXviYjziVucWKjjKEb11juqnF0GDlB3VVmxHLmxnAz643WK42Z7dLM5sY29ouezv4Xz2PuM\nch5VGPP+CDqzCM4loWgV\n---- END SSH2 PUBLIC KEY ----\n"
  },
  {
    "path": "deps/cl345/test/misc/sshkey3.asc",
    "content": "---- BEGIN SSH2 PUBLIC KEY ----\nComment: \"rsa-key-20171029\"\nAAAAB3NzaC1yc2EAAAABJQAAAQEAyRmNuHg0Q9m3yU/+aG7f5cne7fls/q94GSf1\nLrDSFkcMgFBm2qq8wyE5mgJDvX3ltBVyiLvkz8Uwl5wiuolqqkerPyxgtym2Mjb+\n4rIvb4prvBGn6P9+YruJS8VPFk4lUkKker+p4wjloqxtTMYW63S7JJayPhx2ITuj\nCu7V8O3GYswNoaDVwy9CwutQcAzxk4BVBT6y0dhSEjqC4Z3dGAVEeiXRMu0m1hiN\nT0UwCjkaDJnS2ySv7r3OcRov4+ctVgbSppZ/JZTB7ovbCDm14sy6jaG2y1mUhga/\nK0tAWK70DfTcF1RrCg4QMZgCaOM6sLsdU8iJFSYZrGHxOdOV+w==\n---- END SSH2 PUBLIC KEY ----\n"
  },
  {
    "path": "deps/cl345/test/misc/sshkey4.asc",
    "content": "---- BEGIN SSH2 PUBLIC KEY ----\nComment: \"Created by Ipswitch WS_FTP Pro\"\nAAAAB3NzaC1yc2EAAAADAQABAAAAgQDeAsennWaylnU1DYryE5HrpGTPooXbeMu\nqb21FEgBSYylJu+pzA7mPr2Phsw6h0s4K+CN1/X6znVa1u0cLbl352ulRhojybe\nnGAmyw0P8eHH2IwCR9lBbuQDBR7OZ0v/MgO/xg9dnGw2g+65aRgP+TWe6h7SyUS\njd945iabnXwrw==\n---- END SSH2 PUBLIC KEY ----\n"
  },
  {
    "path": "deps/cl345/test/misc/test.txt",
    "content": "Some test data."
  },
  {
    "path": "deps/cl345/test/pgp/conv_enc2.pgp",
    "content": "\u0003PGP\r\u0004\u0002\u0003\u0002Xrnfl`)s\fz5\u001d;&\u000b>k\u001at]-G\",\u001b\u0015vL*lS\u001a"
  },
  {
    "path": "deps/cl345/test/pgp/conv_enc4.pgp",
    "content": "\r\u0004\u0007\u0003\u0002/EPt`1\u000fp\u0003!\u0011*ҿ9\u001a5F㾇0=oi\f/%Cc*B\""
  },
  {
    "path": "deps/cl345/test/pgp/conv_enc5.pgp",
    "content": "\r\u0004\u0007\u0003\u00026\u000b`H\u0001>`\u0011+YUa\u0010\u0006yyM<\u0013\u0007ýE~ާ+q66;\r_XZy!\u0010b0WaB"
  },
  {
    "path": "deps/cl345/test/pgp/conv_enc6.pgp",
    "content": "\r\u0004\u0007\u0003\u0002LΠ`J\u0001_$mR\t\u0007 ub$(\u0013\u001edMݥk=S][ef᷼3\u0015<S+\u0002!`\u001cW\u0011'9O-;6"
  },
  {
    "path": "deps/cl345/test/pgp/pubkey1.asc",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: 2.6.2\n\nmQCNAy9clXEAAAEEANgctpL2oDfbc/V2uZjW/qfCctnpRiBryutL4IN2QkgDaQ9p\n03nMpO5TdMB+fn3EUTl8fkbV666N42o2Jfj5CUZ3EZUDTxvMmpXKrPIrAGijUY9+\nesWb4uKS8EwZiOQKu/lyZdILwzO0kR4+9WnR53JCpZQDBX0+91F2Q2Bf1xDRAAUR\ntBtSYXZpIEguIFBpbmEgPHJhdmlAY293Lm9yZz6JAJUDBRA2wLWHUXZDYF/XENEB\nAcVyA/41WM+NZs08PktjT4Rc3Hl91sNMRjL1ki35KuEH2+6rMH8h4EC7xA/G5wVd\nVgQ5hCrjgIVUxGmJs7hv2BSm5h+xguNTjhYlaeIQU3y8LGKIHyxheluv+jveh4q7\nnTa4MXCaT/9k0y9P6uBFo7GP2lH88eYvZQ8TeYfQo4FpE/4Se4kAlQMFEDXTPJfI\nUcOkwSc8MQEBBT8D/RlgjU5EPgvxW/NXJ2ZR+qe//mA170mXd78bZOB7103lvoWM\ncbiIh6CMDCnXjnVetk7e66xQJcKF8nmgrp+HWW3L2f+bafFq8SjfIm8GVVG7yVvt\nVy38nLl3zixyp/FTThOcfx0OuHyyRyImiC7Vll3OM1D2NELL8dsFianeptMBiQCV\nAwUQNdM7dDFN97UwewmdAQFIkwQAs7tAP6apUoY3CO5G7nby4MH5/X3iu061+J//\n0H2rnRMNo9pyZY5rcjgKpWRcbZWMyygF+ZIoUhsIiP9UfJTBiuIikvVUMV2XYnN1\nLgRe3y07H45AKXqXjGwAnm4x4pG2sKv6p4KkLQMWSWw/JmaU75NqcvakggqwJCtl\nYcUFmk+JAHUDBRA10zmb2MQJ2oDRi+EBAcJRAwCV+uq+i2A9A4/l9ZbIFucs1Li3\ncT3KdoqJiPhOVcyNrN9qu4j8WgNzpz96Frcf/XTl2MR2Rsir2xfDHwFtGGN+2jAm\ndh1n0MHrWf84kebFtsESMRGHLch9ZTS6K6/dnNG0HFJhdmkgSC4gUGluYSA8cmF2\naUBwaW5hLm9yZz60H1JhdmkgSC4gUGluYSA8ZmFsY29uQGdlcnNoLm9yZz6JAJUD\nBRA026ywxWnERVMeKk0BAeWrBACbo5qEB8qrqfzyCOKkuQqnCi5mkWoueZDfMxnp\nefv+aeWpy5eLEMDC7S/Nx1toPw1ABUmQ9VVVWqX/xcl+4kZDM9LzwuGx6qpK7NzM\nkRGJFtx7P27M7HNV2Xyr4hPEkMulbdPfVHoDimkN1wlTJFXTJqKjxV2cy7I5M3MR\nm1mmYYkAlQMFEDV9+TQxTfe1MHsJnQEBavEEALkaZnHnz5/KoWVPK4ZVoAIzptYV\nrewFQrobwgQqFN6IIjCLLYhxq4cegQQsaD3oHse1br8i4vhrwnoSY99xfcrtdr+W\nYoFWLDaF18qTh9ZBL89HVnrEX76o2H0NmLoBkQThuQq0I9sdI3zWEHtDpc6pQz5V\nC8nCU2pxkzu9gTATiQCVAwUQNHCDSspllYGSHBNdAQEpmwP/T+Hwg+NwzNiFQi05\n+KJ/zhr38PyZqnGHObnvCpABy/kZmv8tQwjl2cg2K5Mtb0vXCg+07sJcrCR7YXVm\nfIszvy5OznyPXtbBvA0w6FgWV/G2cUFMqCT0BK4IQJ3ziLUXIKBq58wp4VBCblio\n2+WrE9s8S6cDzN/mG8L0Ki0Bw1a0HlJhdmkgSC4gUGluYSA8cmF2aUBpYWduZXQu\nbmV0PokAlQMFEDTkr8MCYpE2RznIyQEB800D+wRTZl5QH4iSUwFc6e99+s989iHX\n92ka6z5FfOlt7p/9ASqdJLEDKzM8MDsaJoBC7yqJveFmLUfmpCCe7nQj/zVBtOz0\nMe1BZ9MWSz1reoUSXde1DqsVnfAVGWtm/hOD9XaIibnraUSoqlM1rKI0wsAT1Qyb\nRe+rCxiOLVD+vgqS\n=ztpq\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": "deps/cl345/test/pgp/pubkey2.asc",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: PGPfreeware 6.5.1 Int. for non-commercial use\n<http://www.pgpinternational.com>\n\nmQGiBDr2mCIRBADrPcbYvWqbgx58ReH/XqGjGbN72+8AvNWvZc/RCi2uwH9bT3wQ\ngiDwkKtx7M2aWvKGWwjlaw5nAvOsdLsqgBTjeOMz+mb6vQ5iicF4j3YiQlAjRyGy\nNzMxvm/1NDYJTF5whCBlj0Zo2zWv4A+FjJMt9944qfwQg+0h0Q+sd2E8NQCg/3lU\nZ0w5nGED8C00WyAIsdDAKJED/R4XlqjaTz3UW7iFSboDwWu17y2ejWVUkXP7UvaT\nsmhDp8YZ0fGUQRMYytdIDx+nnWKypTFKI2nrv0yD1C9kLCiT93XRaZse2fBo+3Qo\ndJrafUnw2389iKyco+9J/21Ge9p1V+ufXJn2WY5lvD6eOm4aDXZCFMClkAUWuCky\n+kQbA/0VW80eR/Or0T9z7KHtjEAZMoDgvdduBbQo7ieMkHiXExJpgtE9P5zyJoGx\na1FJ+MH1lgY6v9g/rCZDnGXg4Bpm+aya1khRGgxfkt8lP9JF1lRTPdYoM1aMUjkD\na30GXth4CriUeZRaOzhXbrMEvkA74BZTSoQpdOHBirP7gtqRvLQ3Rm9ydHJlc3Mg\nTWFuYWdlbWVudCBHcm91cCA8aW5mb0Bmb3J0cmVzc21hbmFnZW1lbnQuY29tPokA\nTgQQEQIADgUCOvaYIgQLAwIBAhkBAAoJEP+rOaen0wbJ9r0Anj4hkx7zjtvJCVdg\n5Ke1NVZyTVk6AJ4o0BVplgRvafgQlvy9saVsC37tarkCDQQ69pgiEAgA9kJXtwh/\nCBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4\nDIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/\nFfm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUd\nD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGx\nKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkm\nuquiXsNV6TILOwACAggAs0sJhzTu5R2Mg5QHhKNCieJ8GNx9I5LjCVRdPBUGTjzP\npKF76gYAxNBau5xsLBAuxii+dOhLm/eYPvSfbDdcB8Se2UjpWApCYVK2q17QfoUf\njeJhuJkWdAPP3lOMFpT31N/oWit1EpOZfcEmVyxUTdgy++ElOA4XxOsZloBbWEnO\ncd90zK9WZsPyIu25im5luUa7ZlLWwNEVNNrGq9ovFcIAXGlk1EUT1F9eXUD7FByt\nsI1NN2/GmqmDEBGyCd4d1f8BJ5sHfuRBwbQFhGDlBdPKhDwA8vbDLZnE5aFR0EDU\nMZYJ71OUrL5ImRIBcfa9olD3M2ubTwy7s6b5myYprokARgQYEQIABgUCOvaYIgAK\nCRD/qzmnp9MGyZc3AKDcgVOKUY/R3sEVQV1TpPDjZXMGXwCg+FwHij4laRMV6Kr9\nEptEJiW+E30=\n=FBVB\n-----END PGP PUBLIC KEY BLOCK-----"
  },
  {
    "path": "deps/cl345/test/pgp/pubkey3.asc",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: PGP 8.0\n\nmQGiBDoRZ8gRBADEGxTvaj/MhDcgTsXbKxq4TbkFhMRVEKHuwIH8POp8UkKZ/ZQN\nCffS8p0bA+EfTxWS+oEuwddMYVToRLBpIPwQ5paya+iCn8fe0eK3Amd3Grn6lkFn\nnoKBO+dxgQvKlfa8pa1cPhsX/p+yohtSfxkaMNlBqEVxNaiAJKF/j6H8UwCg/1Ul\nmc8QzOdFFaRU9ykVTaM8gYED/i1jwKquXPq4gzOK/DYe0Xbu2CdKyovOotpLWB5j\ncildGUOvzcYeedgi2rmRBehRTBeDwLaN7trx8JmfzQ9D+RryFkRpf8QbiK05e5hP\nkcqMopXZWx+gF1JRpyP7T1DveeQM2YWLFDrz5Sg42Z0zTufgdFAh8PBkHhf0FDtj\nVIJ+A/9KdJv8HoUwSURUWTA+ZRIfyRKc6+Cj3Aft3QsCBej6mBuZwBPrOkeDqYeO\nnFjOY0YxT/AfHyGYrjTmVutOwkh78n3Q2Y8gy5slc+pr2q/jkX0kSPGcIdXhJ0W8\nHynSXWZqA9s59aTNTvAWPLxVFLDnY0FzOviGr4jIwYXnIih29rQnS2VtYWwgT2Zs\nYXplciA8b2ZsYXplckBzYWJhbmNpdW5pdi5lZHU+iQBOBBARAgAOBQI6EWfIBAsD\nAgECGQEACgkQUSLunXjKRC1/mwCfWkN8MxWIdHjvvB9vFGFmwe5+mKIAoLGqvFB1\nH8/Tt49D6tQ6Smu/6Oa0uQINBDoRZ8gQCAD2Qle3CH8IF3KiutapQvMF6PlTETlP\ntvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2\nUk89PY3bzpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVy\nOtQa8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPw\npVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnI\nByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICCADb\niHOFaBiwAfXWMY9AfiKB8GmWE8sDFug+uwyzyx5iw/jVzcA7K0tkOU7D6EruWUnb\nygLuOG+JzSIwHg7sRVfOiyg4HzThn72ExSilWMXGIyUKdZSoup2mm7os+PkK6H+R\nES132b8KGgYRMWc/Rar+9Cx5y0Dus6r1GbggULyRO0Vr+35wqQENLtpUGAcK6jFs\nbTjfZvdd4cXnGKro6crECxmCMx67pcj1dYacvOTltaM31Mt4SlArqd16rxjGCm6x\nKkomGypCvpsm1g8wMlBIss/DqbvTFgxbEnWjimkGcg3aLemOxh+JbkFtZYY5k8o+\nSjRqxFONWReS6yaYYx+tiQBGBBgRAgAGBQI6EWfIAAoJEFEi7p14ykQtDW0AoIDY\nosL9c/dZiaGAJjjz5ARQ/O0yAKDG0S0TuS3AOviCDSegYhs2IEW7Ag==\n=RXfJ\n-----END PGP PUBLIC KEY BLOCK-----"
  },
  {
    "path": "deps/cl345/test/pgp/test.c",
    "content": "/* This is a lowest-common-denominator program which should compile under\n   the default cc on any system, no matter how primitive (even the SunOS\n   one - note the use of 1970s-vintage octal escapes).  This is necessary\n   because it's compiled before we can try and select a decent compiler via\n   the makefile */\n\n#include <stdio.h>\n#include <stdlib.h>\n\nint main()\n\t{\n\tif( *( long * ) \"\\200\\0\\0\\0\\0\\0\\0\\0\" < 0 )\n\t\tprintf( \"-DDATA_BIGENDIAN\" );\n\telse\n\t\tprintf( \"-DDATA_LITTLEENDIAN\" );\n\n\treturn( 0 );\n\t}\n"
  },
  {
    "path": "deps/cl345/test/pgp/test.txt",
    "content": "Some test data."
  },
  {
    "path": "deps/cl345/test/s_cmp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib CMP Session Test Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2009\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n/* If we're running the test with a crypto device, we have to set an extended\n   timeout because of the long time it takes many devices to generate keys */\n\n#define NET_TIMEOUT\t\t180\n\n#if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )\n\n/* CMP test types */\n\ntypedef enum {\n\tCMP_TEST_NONE,\t\t\t/* No CMP test type */\n\tCMP_TEST_NORMAL,\t\t/* Standard CMP test */\n\tCMP_TEST_PKIBOOT,\t\t/* Use PKIBoot functionality */\n\tCMP_TEST_CORRUPT_TRANSACTIONID,\t/* Detect corruption of transaction ID */\n\tCMP_TEST_CORRUPT_NONCE,\t/* Detect corruption of sender/recipNonce */\n\tCMP_TEST_BADSIG_DATA,\t/* Sig.check failure - bad data */\n\tCMP_TEST_BADSIG_HASH,\t/* Sig.check failure - bad hash/MAC */\n\tCMP_TEST_BADSIG_SIG,\t/* Sig.check failure - bad signature */\n\tCMP_TEST_LAST\t\t\t/* Last possible CMP test type */\n\t} CMP_TEST_TYPE;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMP Test Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There are various CMP test CAs available, the following mappings can be\n   used to test different ones.  Implementation peculiarities:\n\n\t#1 - cryptlib: Implicitly revokes certificate being replaced during a \n\t\t\tkur (this is a requirement for maintaining certificate store \n\t\t\tconsistency).\n\t\t\tTested: ir, cr/kur, rr\n\t#2 - cryptlib with PKIBoot/PnP PKI functionality, otherwise as for #1.\n\t#3 - Certicom: Requires signature for revocation rather than MAC,\n\t\t\trequires that all certs created after the ir one have the same\n\t\t\tDN as the ir certificate.\n\t\t\tTested: ir, cr/kur, rr\n\t#4 - ssh old: None (recently re-issued their CA certificate which is \n\t\t\tbroken, CA couldn't be re-tested.  In addition since CMP \n\t\t\tidentifies the sender by DN the new certificate can't be \n\t\t\tdistinguished from the old one, causing all sig checks to \n\t\t\tfail).\n\t\t\tTested (late 2000): ir, cr/kur, rr\n\t#5 - ssh new:\n\t#6 - Entrust: Won't allow altNames, changes sender and request DN,\n\t\t\treturns rejected response under an altered DN belonging to a\n\t\t\tcompletely different EE for anything but ir.\n\t\t\tTested: ir\n\t#7 - Trustcenter: Requires HTTPS and pre-existing trusted private key\n\t\t\tdistributed as PKCS #12 file, couldn't be tested.\n\t#8 - Baltimore: Server unavailable for testing.\n\t\t\tTested: -\n\t#9 - Initech: Needs DN cn=CryptLIB EE 1,o=INITECH,c=KR.\n\t\t\tTested: ir, cr/kur, rr\n\t#10 - RSA labs: Rejects signed requests, couldn't be tested beyond initial\n\t\t\t(MACd) ir.  Attempt to revoke newly-issued certificate with MACd \n\t\t\trr returns error indicating that the certificate is already \n\t\t\trevoked.\n\t\t\tTested: ir\n\t#11 - Cylink: Invalid CA root certificate, requires use of DN from RA \n\t\t\trather than CA when communicating with server.\n\t\t\tTested: - \n\t#12 - Insta-Certifier: Returned garbled bits of the \"tcp\" protocol \n\t\t\theader in earlier versions, later versions improved somewhat,\n\t\t\thowever a kur is rejected with the message \"CRMF did not contain \n\t\t\toldCertId control\".  Information at \n\t\t\thttp://www.certificate.fi/resources/demos/demo.htm.\n\t\t\tTested: ir, cr.\n\t#13 - EJBCA: Implements a broken version of pre-RFC CMPv1, can't be \n\t\t\ttested */\n\n#define CA_CRYPTLIB\t\t\t\t1\n#define CA_CRYPTLIB_PNPPKI\t\t2\n\n#define CA_NO\t\t\t\t\tCA_CRYPTLIB\t\n\ntypedef struct {\n\tconst char *name;\n\tconst C_CHR *url, *user, *password, *revPassword;\n\t} CA_INFO;\n\nstatic const CA_INFO caInfoTbl[] = {\n\t{ NULL },\t/* Dummy so index == CA_NO */\n\t{ /*1*/ \"cryptlib\", TEXT( \"http://\" LOCAL_HOST_NAME ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*2*/\t\"cryptlib/PKIBoot\", /*\"_pkiboot._tcp.cryptoapps.com\"*/TEXT( \"http://localhost\" ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*3*/ \"Certicom\", TEXT( \"cmp://gandalf.trustpoint.com:8081\" ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*4*/ \"ssh\", TEXT( \"cmp://interop-ca.ssh.com:8290\" ), TEXT( \"123456\" ), TEXT( \"interop\" ) },\n\t{ /*5*/ \"ssh\", TEXT( \"http://pki.ssh.com:8080/pkix/\" ), TEXT( \"62154\" ), TEXT( \"ssh\" ) },\n\t{ /*6*/ \"Entrust\", TEXT( \"cmp://204.101.128.45:829\" ), TEXT( \"39141091\" ), TEXT( \"ABCDEFGHIJK\" ) },\n\t{ /*7*/ \"Trustcenter\", TEXT( \"cmp://demo.trustcenter.de/cgi-bin/cmp:829\" ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*8*/ \"Baltimore\", TEXT( \"cmp://hip.baltimore.ie:8290\" ), TEXT( \"pgutmann\" ), TEXT( \"the-magical-land-near-oz\" ) },\n\t{ /*9*/ \"Initech\", TEXT( \"cmp://61.74.133.49:8290\" ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*A*/ \"RSA\", TEXT( \"cmp://ca1.kcspilot.com:32829\" ), TEXT( \"interop\" ), TEXT( \"interop\" ) },\n\t{ /*B*/ \"Cylink\", TEXT( \"cmp://216.252.217.227:8082\" ), TEXT( \"3986\" ), TEXT( \"11002\" ) /* \"3987\", \"6711\" */ },\n\t{ /*C*/ \"Insta-Certifier\", TEXT( \"http://pki.certificate.fi:8700/pkix/\" ), TEXT( \"3078\" ), TEXT( \"insta\" ) },\n\t{ /*D*/ \"EJBCA\", TEXT( \"http://192.168.1.103:8080/ejbca/publicweb/cmp\" ), TEXT( \"user\" ), TEXT( \"password\" ) }\n\t};\n\n/* Enable additional tests if we're using cryptlib as the server */\n\n#if ( CA_NO == CA_CRYPTLIB ) || ( CA_NO == CA_CRYPTLIB_PNPPKI )\n  #define SERVER_IS_CRYPTLIB\n#endif /* Extra tests for cryptib CA */\n\n/* Define the following to work around CA bugs/quirks */\n\n#if ( CA_NO == 3 )\t\t\t/* Certicom */\n  #define SERVER_IR_DN\n#endif /* CAs that require same DN in cr as ir */\n#if ( CA_NO == 6 )\t\t\t/* Entrust */\n  #define SERVER_NO_ALTNAMES\n#endif /* CAs that won't allow altNames in requests */\n#if ( CA_NO == 9 )\t\t\t/* Initech */\n  #define SERVER_FIXED_DN\n#endif /* CAs that require a fixed DN in requests */\n\n/* The following defines can be used to selectively enable or disable some\n   of the test (for example to do an ir + rr, or ir + kur + rr) */\n\n#ifdef SERVER_IS_CRYPTLIB\n  #define TEST_IR_NODN\n  #define TEST_IR\n/*#define TEST_DUP_IR */\n  #define TEST_KUR\n  #define TEST_CR\n  #define TEST_RR\n\n  /* Set the following to FALSE to use a MAC'd rr instead of a signed one */\n  #define USE_SIGNED_RR\t\tTRUE\n\n  /* 4 certificate reqs (two ir variants), 1 rev.req (kur = impl.rev).  \n\t \n\t The duplicate-ir check is currently disabled because it's enforced via \n\t database transaction constraints, which means that once the initial ir \n\t has been recorded all further issue operations with the same ID are \n\t excluded by the presence of the ID for the ir.  This is a strong \n\t guarantee that subsequent requests with the same ID will be disallowed, \n\t but not terribly useful for self-test purposes */\n  #define NO_CA_REQUESTS\t( 5 + 0 )\n#else\n  #define TEST_IR\n  #define TEST_KUR\n  #define TEST_CR\n  #define TEST_RR\n  #define USE_SIGNED_RR\t\tFALSE\n\n  /* Loopback test requires SERVER_IS_CRYPTLIB */\n  #define NO_CA_REQUESTS\t0\n#endif /* SERVER_IS_CRYPTLIB */\n\n/* Define the following to enable testing of servers where the initial DN \n   (and optional additional information like the altName) is supplied by the \n   server (i.e. the user supplies a null DN) */\n\n#ifdef SERVER_IS_CRYPTLIB\n  #define SERVER_PROVIDES_DN\n#endif /* CAs where the server provides the DN */\n\n/* PKI user data to authorise the issuing of the various certificates */\n\nstatic const CERT_DATA cmpPkiUserFullDNData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test PKI user\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpPkiUserPartialDNData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpPkiUserCaData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test CA PKI user\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@ca.wetas-r-us.com\" ) },\n\n\t/* CA extensions */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpPkiUserRaData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test RA PKI user\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@ca.wetas-r-us.com\" ) },\n\n\t/* RA flag */\n\t{ CRYPT_CERTINFO_PKIUSER_RA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* Certificate request data for the various types of certificates that the \n   cryptlib CMP CA can return */\n\nstatic const CERT_DATA cmpCryptlibRequestNoDNData[] = {\t/* For ir */\n\t/* Identification information - none, it's provided by the server */\n\n\t/* Subject altName - none, it's provided by the server */\n\n\t/* Signature-only key */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpCryptlibRequestData[] = {\t\t/* For cr */\n\t/* Identification information.  The rest of the DN is provided by the \n\t   CA.  Note that the ability to handle full DNs in the request is\n\t   tested by the kur, whose contents aren't defined here since they're\n\t   taken from the certificate being updated */\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Signature Key\" ) },\n\n\t/* Subject altName.  The email address is provided by the CA */\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* Signature-only key */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpCryptlibDsaRequestData[] = {\t/* Unused */\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's DSA Key\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* Certificate request data for the various types of certs that a CMP CA can \n   return */\n\nstatic const CERT_DATA cmpRsaSignRequestData[] = {\t\t/* For cr */\n\t/* Identification information */\n  #ifdef SERVER_FIXED_DN\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"KR\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"INITECH\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"CryptLIB EE 1\" ) },\n  #else\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Signature Key\" ) },\n  #endif /* CAs that require a fixed DN in requests */\n\n\t/* Subject altName */\n#ifndef SERVER_NO_ALTNAMES\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n#endif /* CAs that won't allow altNames in requests */\n\n\t/* Signature-only key */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_DIGITALSIGNATURE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpRsaEncryptRequestData[] = {\t/* Unused */\n\t/* Identification information */\n#ifdef SERVER_FIXED_DN\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"KR\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"INITECH\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"CryptLIB EE 1\" ) },\n#else\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Encryption Key\" ) },\n#endif /* CAs that require a fixed DN in requests */\n\n\t/* Subject altName */\n#ifndef SERVER_NO_ALTNAMES\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n#endif /* CAs that won't allow altNames in requests */\n\n\t/* Encryption-only key */\n\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC, CRYPT_KEYUSAGE_KEYENCIPHERMENT },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\nstatic const CERT_DATA cmpRsaCaRequestData[] = {\t\t/* For ir-CA */\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Dave's Intermediate CA Key\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave-ca@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t/* CA key */\n\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Create various CMP objects */\n\nstatic int createCmpNewKeyRequest( const CERT_DATA *requestData,\n\t\t\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t\t   const BOOLEAN useFixedKey,\n\t\t\t\t\t\t\t\t   const CRYPT_KEYSET cryptKeyset )\n\t{\n\tCRYPT_CERTIFICATE cryptRequest;\n\tCRYPT_CONTEXT cryptContext;\n\tint status;\n\n\t/* It's a new request, generate a private key and create a self-signed \n\t   request */\n\tif( useFixedKey )\n\t\t{\n\t\t/* Use a fixed private key, for testing purposes */\n\t\tswitch( cryptAlgo )\n\t\t\t{\n\t\t\tcase CRYPT_ALGO_RSA:\n\t\t\t\tstatus = loadRSAContextsEx( CRYPT_UNUSED, NULL, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t\tNULL, USER_PRIVKEY_LABEL, FALSE, \n\t\t\t\t\t\t\t\t\t\t\tFALSE );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_DSA:\n\t\t\t\tstatus = loadDSAContextsEx( CRYPT_UNUSED, NULL, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t\tNULL, USER_PRIVKEY_LABEL );\n\t\t\t\tbreak;\n\n\t\t\tcase CRYPT_ALGO_ECDSA:\n\t\t\t\tstatus = loadECDSAContextsEx( CRYPT_UNUSED, NULL, &cryptContext, \n\t\t\t\t\t\t\t\t\t\t\t  NULL, USER_PRIVKEY_LABEL );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tprintf( \"Couldn't create CMP request with algorithm %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", cryptAlgo, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t paramStrlen( USER_PRIVKEY_LABEL ) );\n\t\tstatus = cryptGenerateKey( cryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_CERT );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptRequest,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptRequest, requestData, __LINE__ ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptRequest, cryptContext );\n\tif( cryptStatusOK( status ) && cryptKeyset != CRYPT_UNUSED )\n\t\t{\n\t\tif( cryptStatusError( \\\n\t\t\t\tcryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Creation of CMP request failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( cryptRequest );\n\t}\n\nstatic int createCmpRequest( const CERT_DATA *requestData,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT privateKey,\n\t\t\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t\t const BOOLEAN useFixedKey,\n\t\t\t\t\t\t\t const CRYPT_KEYSET cryptKeyset )\n\t{\n\tCRYPT_CERTIFICATE cryptRequest;\n\ttime_t startTime;\n\tint dummy, status;\n\n\t/* If there's no existing private key available, generate a new key \n\t   along with the request */\n\tif( privateKey == CRYPT_UNUSED )\n\t\t{\n\t\treturn( createCmpNewKeyRequest( requestData, cryptAlgo, useFixedKey, \n\t\t\t\t\t\t\t\t\t\tcryptKeyset ) );\n\t\t}\n\n\t/* We're updating an existing certificate we have to vary something in \n\t   the request to make sure that the result doesn't duplicate an existing \n\t   certificate, to do this we fiddle the start time */\n\tstatus = cryptGetAttributeString( privateKey, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &startTime, &dummy );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstartTime++;\n\n\t/* It's an update of existing information, sign the request with the \n\t   given private key */\n\tstatus = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_CERT );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptRequest, CRYPT_CERTINFO_CERTIFICATE, \n\t\t\t\t\t\t\t\t\tprivateKey );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptRequest, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_VALIDFROM, \n\t\t\t\t\t\t\t\t\t\t  &startTime, sizeof( time_t ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptRequest, privateKey );\n\tif( cryptKeyset != CRYPT_UNUSED )\n\t\t{\n\t\tif( cryptStatusError( \\\n\t\t\t\tcryptAddPrivateKey( cryptKeyset, privateKey,\n\t\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD ) ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Creation of CMP request failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( cryptRequest );\n\t}\n\nstatic int createCmpRevRequest( const CRYPT_CERTIFICATE cryptCert )\n\t{\n\tCRYPT_CERTIFICATE cryptRequest;\n\tint status;\n\n\t/* Create the CMP (CRMF) revocation request */\n\tstatus = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_REQUEST_REVOCATION );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptRequest, CRYPT_CERTINFO_CERTIFICATE,\n\t\t\t\t\t\t\t\t\tcryptCert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Creation of CMP revocation request failed with error code \"\n\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( cryptRequest );\n\t}\n\nstatic int createCmpSession( const CRYPT_CONTEXT cryptCACert,\n\t\t\t\t\t\t\t const C_STR server, const C_STR user,\n\t\t\t\t\t\t\t const C_STR password,\n\t\t\t\t\t\t\t const CRYPT_CONTEXT privateKey,\n\t\t\t\t\t\t\t const BOOLEAN isRevocation,\n\t\t\t\t\t\t\t const BOOLEAN isUpdate,\n\t\t\t\t\t\t\t const BOOLEAN isPKIBoot,\n\t\t\t\t\t\t\t const CRYPT_KEYSET pnpPkiKeyset )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\tassert( cryptCACert == CRYPT_UNUSED || !isPKIBoot );\n\tassert( ( privateKey != CRYPT_UNUSED ) || \\\n\t\t\t( user != NULL && password != NULL ) );\n\n\t/* Create the CMP session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* CMP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifdef SERVER_IS_CRYPTLIB\n\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\treturn( FALSE );\n#endif /* SERVER_IS_CRYPTLIB */\n\n\t/* Set up the user and server information.  Revocation requests can be\n\t   signed or MACd so we handle either.  When requesting a certificate \n\t   using a signed request (i.e.not an initialisation request) we use an \n\t   update since we're reusing the previously-generated certificate data \n\t   to request a new one and some CAs won't allow this reuse for a \n\t   straight request but require explicit use of an update request */\n\tif( privateKey != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t\t\tisRevocation ? \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_REVOCATION : \\\n\t\t\t\t\t\t\t\t\tisUpdate ? \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_KEYUPDATE : \\\n\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_CERTIFICATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t\t\tprivateKey );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME, user,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( user ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, password,\n\t\t\t\t\t\t\t\t\tparamStrlen( password ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && pnpPkiKeyset != CRYPT_UNUSED )\n\t\t\t{\n\t\t\t/* PnP PKI, no request type, keyset to store returned data */\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t\t\t\t\t\tpnpPkiKeyset );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Standard transaction, specify the request type */\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t\t\t\tisPKIBoot ? \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_PKIBOOT : \\\n\t\t\t\t\t\t\t\t\t\tisRevocation ? \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_REVOCATION : \\\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_INITIALISATION );\n\t\t\t}\n\t\t}\n#ifndef SERVER_IS_CRYPTLIB\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, server,\n\t\t\t\t\t\t\t\t\t\tparamStrlen( server ) );\n\t\t}\n#endif /* SERVER_IS_CRYPTLIB */\n\tif( cryptStatusOK( status ) && cryptCACert != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t\t\t\t\tcryptCACert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Addition of session information failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( cryptSession );\n\t}\n\n/* Request a particular certificate type */\n\nstatic int requestCert( const char *description, const CA_INFO *caInfoPtr,\n\t\t\t\t\t\tconst C_STR readKeysetName,\n\t\t\t\t\t\tconst C_STR writeKeysetName,\n\t\t\t\t\t\tconst CERT_DATA *requestData,\n\t\t\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\tconst CRYPT_CONTEXT cryptCACert,\n\t\t\t\t\t\tconst BOOLEAN isPKIBoot, \n\t\t\t\t\t\tconst BOOLEAN isPnPPKI,\n\t\t\t\t\t\tCRYPT_CERTIFICATE *issuedCert )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_KEYSET cryptKeyset = CRYPT_UNUSED;\n\tCRYPT_CONTEXT privateKey = CRYPT_UNUSED;\n\tCRYPT_CERTIFICATE cryptCmpResponse;\n\tconst BOOLEAN useExistingKey = ( requestData == NULL ) ? TRUE : FALSE;\n\tBOOLEAN hasC = FALSE, hasCN = FALSE;\n\tint status;\n\n\tassert( !isPKIBoot || !isPnPPKI );\n\tassert( !( isPnPPKI && writeKeysetName == NULL ) );\n\n\tif( requestData != NULL )\n\t\t{\n\t\tint i;\n\n\t\tfor( i = 0; requestData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t\t{\n\t\t\tif( requestData[ i ].type == CRYPT_CERTINFO_COUNTRYNAME )\n\t\t\t\thasC = TRUE;\n\t\t\tif( requestData[ i ].type == CRYPT_CERTINFO_COMMONNAME )\n\t\t\t\thasCN = TRUE;\n\t\t\t}\n\t\t}\n\tif( isPKIBoot )\n\t\tputs( \"Testing standalone PKIBoot with no certificate request\" );\n\telse\n\t\t{\n\t\tprintf( \"Testing %s processing\", description );\n\t\tif( requestData == NULL )\n\t\t\tprintf( \"with implicitly-supplied subject DN\" );\n\t\telse\n\t\t\t{\n\t\t\tif( hasCN )\n\t\t\t\tprintf( \" with partial subject DN\" );\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !hasC )\n\t\t\t\t\tprintf( \" with CA-supplied subject DN\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tputs( \"...\" );\n\n\t/* Read the key needed to request a new certificate from a keyset if \n\t   necessary and create a keyset to save a new key to if required.  We \n\t   have to do the write last in case the read and write keyset are the \n\t   same */\n\tif( readKeysetName != NULL )\n\t\t{\n\t\tstatus = getPrivateKey( &privateKey, readKeysetName,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't get private key to request new certificate, \"\n\t\t\t\t\t\"status = %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( writeKeysetName != NULL )\n\t\t{\n\t\tassert( !isPKIBoot );\t/* Keyset -> PnPPKI, not just PKIBoot */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, writeKeysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't create keyset to store certificate to, \"\n\t\t\t\t\t\"status = %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Create the CMP session */\n\tcryptSession = createCmpSession( cryptCACert, caInfoPtr->url,\n\t\t\t\t\t\t\t\t\t caInfoPtr->user, caInfoPtr->password,\n\t\t\t\t\t\t\t\t\t privateKey, FALSE, useExistingKey,\n\t\t\t\t\t\t\t\t\t isPKIBoot, \n\t\t\t\t\t\t\t\t\t isPnPPKI ? cryptKeyset : CRYPT_UNUSED );\n\tif( cryptSession <= 0 )\n\t\t{\n\t\tif( cryptKeyset != CRYPT_UNUSED )\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn( cryptSession );\n\t\t}\n\n\t/* Set up the request.  Some CAs explicitly disallow multiple dissimilar \n\t   certs to exist for the same key (in fact for non-test servers other \n\t   CAs probably enforce this as well) but generating a new key for each \n\t   request is time-consuming so we only do it if it's enforced by the \n\t   CA */\n\tif( !isPKIBoot )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCmpRequest;\n\n#if defined( SERVER_IS_CRYPTLIB ) || defined( SERVER_FIXED_DN )\n\t\tcryptCmpRequest = createCmpRequest( requestData,\n\t\t\t\t\t\t\t\tuseExistingKey ? privateKey : CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tcryptAlgo, FALSE, cryptKeyset );\n#else\n\t\tKLUDGE_WARN( \"fixed key for request\" );\n\t\tcryptCmpRequest = createCmpRequest( requestData,\n\t\t\t\t\t\t\t\tuseExistingKey ? privateKey : CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tcryptAlgo, TRUE, cryptKeyset );\n#endif /* cryptlib and Initech won't allow two certs for same key */\n\t\tif( !cryptCmpRequest )\n\t\t\treturn( FALSE );\n\t\tif( privateKey != CRYPT_UNUSED )\n\t\t\tcryptDestroyContext( privateKey );\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t\t\tcryptCmpRequest );\n\t\tcryptDestroyCert( cryptCmpRequest );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptSetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Activate the session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( cryptKeyset != CRYPT_UNUSED )\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\tprintExtError( cryptSession, \"Attempt to activate CMP client session\",\n\t\t\t\t\t   status, __LINE__ );\n#ifdef SERVER_IS_CRYPTLIB\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tchar errorMessage[ 512 ];\n\t\t\tint errorMessageLength;\n\n\t\t\t/* If there's something else listening on the local port that\n\t\t\t   we use for CMP then it's unlikely to respond to a CMP \n\t\t\t   request, so we add a special-case check for this and don't \n\t\t\t   treat it as a fatal error */\n\t\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_ERRORMESSAGE,\n\t\t\t\t\t\t\t\t\t\t\t  errorMessage, \n\t\t\t\t\t\t\t\t\t\t\t  &errorMessageLength );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\terrorMessageLength > 13 && \n\t\t\t\t!memcmp( errorMessage, \"HTTP response\", 13 ) )\n\t\t\t\t{\n\t\t\t\tputs( \"  (Something other than a CMP server is listening on \"\n\t\t\t\t\t  \"the local port used for\\n   testing, \"\n\t\t\t\t\t  \"continuing...)\\n\" );\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t\t}\n\t\t\t}\n#endif /* SERVER_IS_CRYPTLIB */\n\t\tif( isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tfputs( \"  (Server could be down, faking it and \"\n\t\t\t\t   \"continuing...)\\n\", outputStream );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\tif( status == CRYPT_ERROR_FAILED )\n\t\t\t{\n\t\t\t/* A general failed response is more likely to be due to the\n\t\t\t   server doing something unexpected than a cryptlib problem so\n\t\t\t   we don't treat it as a fatal error */\n\t\t\tputs( \"  (This is more likely to be an issue with the server than \"\n\t\t\t\t  \"with cryptlib,\\n   faking it and continuing...)\\n\" );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's a PKIBoot, which just sets (implicitly) trusted certs, we're\n\t   done */\n\tif( isPKIBoot )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Obtain the response information */\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t&cryptCmpResponse );\n\tcryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptGetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifndef SERVER_IS_CRYPTLIB\n\tputs( \"Returned certificate details are:\" );\n\tprintCertInfo( cryptCmpResponse );\n#endif /* Keep the cryptlib results on one screen */\n\tif( cryptKeyset != CRYPT_UNUSED )\n\t\t{\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCmpResponse );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't write certificate to keyset, status = %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( issuedCert != NULL )\n\t\t*issuedCert = cryptCmpResponse;\n\telse\n\t\tcryptDestroyCert( cryptCmpResponse );\n\n\t/* Clean up */\n\tprintf( \"Successfully processed %s.\\n\\n\", description );\n\treturn( TRUE );\n\t}\n\n/* Revoke a previously-issued certificate */\n\nstatic int revokeCert( const char *description, const CA_INFO *caInfoPtr,\n\t\t\t\t\t   const C_STR keysetName,\n\t\t\t\t\t   const CRYPT_CERTIFICATE certToRevoke,\n\t\t\t\t\t   const CRYPT_CONTEXT cryptCACert,\n\t\t\t\t\t   const BOOLEAN signRequest )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CERTIFICATE cryptCmpRequest, cryptCert = certToRevoke;\n\tint status;\n\n\tprintf( \"Testing %s revocation processing...\\n\", description );\n\n\t/* Get the certificate to revoke if necessary.  This may have been \n\t   obtained as part of the issue process, so it's stored with the key\n\t   rather than being directly present */\n\tif( cryptCert == CRYPT_UNUSED )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert,\n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tputs( \"Couldn't fetch certificate to revoke.\\n\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* In some cases the server won't accept a revocation password so we \n\t   have to get the private key and then sign the request */\n\tif( signRequest )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\t\tCRYPT_CONTEXT privateKey = CRYPT_UNUSED;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, keysetName,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) && signRequest )\n\t\t\t{\n\t\t\tstatus = getPrivateKey( &privateKey, keysetName,\n\t\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\t\t\t}\n\t\tcryptKeysetClose( cryptKeyset );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tputs( \"Couldn't fetch certificate/key to revoke.\\n\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Create the CMP session and revocation request */\n\t\tcryptSession = createCmpSession( cryptCACert, caInfoPtr->url, NULL, \n\t\t\t\t\t\t\t\t\t\t NULL, privateKey, TRUE, FALSE, \n\t\t\t\t\t\t\t\t\t\t FALSE, CRYPT_UNUSED );\n\t\tif( privateKey != CRYPT_UNUSED )\n\t\t\tcryptDestroyContext( privateKey );\n\t\t}\n\telse\n\t\t{\n\t\t/* Create the CMP session and revocation request */\n\t\tcryptSession = createCmpSession( cryptCACert, caInfoPtr->url,\n\t\t\t\t\t\t\t\t\t\t caInfoPtr->user, caInfoPtr->revPassword,\n\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED, TRUE, FALSE, FALSE,\n\t\t\t\t\t\t\t\t\t\t CRYPT_UNUSED );\n\t\t}\n\tif( cryptSession <= 0 )\n\t\treturn( cryptSession );\n\tcryptCmpRequest = createCmpRevRequest( cryptCert );\n\tif( !cryptCmpRequest )\n\t\treturn( FALSE );\n\n\t/* Set up the request and activate the session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t\tcryptCmpRequest );\n\tcryptDestroyCert( cryptCmpRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"Attempt to activate CMP client session\",\n\t\t\t\t\t   status, __LINE__ );\n\t\tif( cryptCert != certToRevoke )\n\t\t\tcryptDestroyCert( cryptCert );\n\t\tif( isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tputs( \"  (Server could be down, faking it and continuing...)\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_FAILED )\n\t\t\t{\n\t\t\t/* A general failed response is more likely to be due to the\n\t\t\t   server doing something unexpected than a cryptlib problem so\n\t\t\t   we don't treat it as a fatal error */\n\t\t\tputs( \"  (This is more likely to be an issue with the server than \"\n\t\t\t\t  \"with cryptlib,\\n   faking it and continuing...)\\n\" );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tif( cryptCert != certToRevoke )\n\t\tcryptDestroyCert( cryptCert );\n\tcryptDestroySession( cryptSession );\n\tprintf( \"%s processing succeeded.\\n\\n\", description );\n\treturn( TRUE );\n\t}\n\n/* Get the user name and password for a PKI user */\n\nstatic int getPkiUserInfo( const C_STR pkiUserName,\n\t\t\t\t\t\t   CA_INFO *caInfoPtr, C_STR userID, \n\t\t\t\t\t\t   C_STR issuePW, C_STR revPW  )\n\t{\n\tint status;\n\n\t/* cryptlib implements per-user (rather than shared interop) IDs and \n\t   passwords so we have to read the user ID and password information \n\t   before we can perform any operations */\n\tstatus = pkiGetUserInfo( userID, issuePW, revPW, pkiUserName );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\treturn( status );\n\tif( !status )\n\t\treturn( FALSE );\n\tmemcpy( caInfoPtr, &caInfoTbl[ CA_NO ], sizeof( CA_INFO ) );\n\tcaInfoPtr->name = \"cryptlib\";\n\tcaInfoPtr->user = userID;\n\tcaInfoPtr->password = issuePW;\n\tcaInfoPtr->revPassword = revPW;\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tCMP Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test the full range of CMP functionality.  This performs the following\n   tests:\n\n\tRSA sign:\n\t\tir + ip + reject (not performed since requires cmp.c mod)\n\t\tir + ip + certconf + pkiconf\n\t\tcr + cp + certconf + pkiconf\n\t\tkur + kup + certconf + pkiconf\n\t\trr + rp (of ir certificate)\n\t\trr + rp (of kur certificate)\n\tRSA encr.:\n\t\tir + ip + reject (requires cmp.c mod)\n\t\tir + ip + certconf + pkiconf\n\t\trr + rp (of ir certificate)\n\tDSA/ECDSA:\n\t\tcr + cp + certconf + pkiconf (success implies that ir/kur/rr\n\t\t\t\t\t\tworks since they've already been tested for RSA) */\n\n/* Connect to a cryptlib server, for the loopback tests */\n\nstatic int connectCryptlibCMP( const CMP_TEST_TYPE testType,\n\t\t\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_CERTIFICATE cryptCACert = CRYPT_UNUSED, cryptCert;\n\tC_CHR readFileName[ FILENAME_BUFFER_SIZE ];\n\tC_CHR writeFileName[ FILENAME_BUFFER_SIZE ];\n\tCA_INFO caInfo;\n\tC_CHR userID[ 64 ], issuePW[ 64 ], revPW[ 64 ];\n\tconst BOOLEAN usePKIBoot = \\\n\t\t( testType == CMP_TEST_PKIBOOT ) ? TRUE : FALSE;\n\tconst BOOLEAN isErrorTest = ( testType >= CMP_TEST_CORRUPT_TRANSACTIONID && \\\n\t\t\t\t\t\t\t\t  testType < CMP_TEST_LAST ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tint status;\n\n\t/* Wait for the server to finish initialising */\n\tif( waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the required user information is present.  If it isn't\n\t   then the CA auditing will detect a request from a nonexistent user \n\t   and refuse to issue a certificate */\n\tstatus = pkiGetUserInfo( NULL, NULL, NULL, TEXT( \"Test PKI user\" ) );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Cert store operations aren't available, exit but continue with\n\t\t   other tests */\n\t\treturn( TRUE );\n\t\t}\n\tif( !status )\n\t\t{\n\t\tputs( \"CA certificate store doesn't contain the PKI user \"\n\t\t\t  \"information needed to\\nauthenticate certificate issue \"\n\t\t\t  \"operations.  This is probably because the\\nserver loopback \"\n\t\t\t  \"test (which initialises the certificate store) hasn't been \"\n\t\t\t  \"run yet.\\nSkipping CMP test.\\n\" );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\n\t/* If we're not doing PKIBoot (which obtains the CA's certificate during \n\t   the PKIBoot process), get the certificate of the CA who will issue \n\t   the certificate */\n\tif( !usePKIBoot )\n\t\t{\n\t\tstatus = importCertFromTemplate( &cryptCACert, CMP_CA_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t CA_NO );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't get cryptlib CMP CA certificate, status = %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\t/* If we're testing fault handling, inject the appropriate fault type */\n\tif( isErrorTest )\n\t\t{\n\t\tcryptSetFaultType( ( testType == CMP_TEST_CORRUPT_TRANSACTIONID ) ? \\\n\t\t\t\t\t\t\t FAULT_CORRUPT_ID : \\\n\t\t\t\t\t\t   ( testType == CMP_TEST_CORRUPT_NONCE ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_CORRUPT_NONCE : \\\n\t\t\t\t\t\t   ( testType == CMP_TEST_BADSIG_DATA ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_DATA : \\\n\t\t\t\t\t\t   ( testType == CMP_TEST_BADSIG_HASH ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_HASH : \\\n\t\t\t\t\t\t   ( testType == CMP_TEST_BADSIG_SIG ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_SIG : \\\n\t\t\t\t\t\t   \t FAULT_NONE );\n\t\t}\n#endif /* CONFIG_FAULTS && Debug */\n\n\t/* Initialisation request.  We perform two ir's, the first with the CA\n\t   supplying the full user DN and email address, the second with the CA \n\t   supplying a partial DN and no email address, and the user filling in \n\t   the rest.  We continue with the certificate from the second ir, \n\t   because the first one doesn't allow anything other than a kur since \n\t   the DN is fixed */\n\tstatus = getPkiUserInfo( TEXT( \"Test PKI user\" ), &caInfo, \n\t\t\t\t\t\t\t userID, issuePW, revPW );\n\tif( status != TRUE )\n\t\t{\n\t\tif( !usePKIBoot )\n\t\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( FALSE );\n\t\t}\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"certificate init.request (ir)\", &caInfo, NULL, \n\t\t\t\t\t\t  usePKIBoot ? NULL : writeFileName,\n\t\t\t\t\t\t  cmpCryptlibRequestNoDNData, cryptAlgo, \n\t\t\t\t\t\t  cryptCACert, usePKIBoot, FALSE, NULL );\n\tif( status != TRUE )\n\t\t{\n\t\tif( isErrorTest )\n\t\t\t{\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tcryptDestroyCert( cryptCACert );\n\t\t\tputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t  \"response is correct).\\n\\n\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\t/* If this is the self-test and there's a non-fatal error, make sure\n\t\t   we don't fail with a CRYPT_ERROR_INCOMPLETE when we're finished */\n\t\tif( !usePKIBoot )\n\t\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n\tif( isErrorTest && testType != CMP_TEST_BADSIG_SIG )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\tputs( \"  (This test should have led to a failure but \"\n\t\t\t  \"didn't, test has failed).\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( usePKIBoot )\n\t\t{\n\t\t/* If we're testing the PKIBoot capability there's only a single\n\t\t   request to process and we're done */\n\t\treturn( TRUE );\n\t\t}\n\tdelayThread( 2 );\t/* Wait for server to recycle */\n\tstatus = getPkiUserInfo( TEXT( \"Procurement\" ), &caInfo, userID, \n\t\t\t\t\t\t\t issuePW, revPW );\n\tif( status != TRUE )\n\t\t{\n\t\tif( !usePKIBoot )\n\t\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( FALSE );\n\t\t}\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"certificate init.request (ir)\", &caInfo, NULL, \n\t\t\t\t\t\t  usePKIBoot ? NULL : writeFileName,\n\t\t\t\t\t\t  cmpCryptlibRequestData, cryptAlgo, cryptCACert, \n\t\t\t\t\t\t  FALSE, FALSE, &cryptCert );\n\tif( status != TRUE )\n\t\treturn( FALSE );\n#ifdef TEST_DUP_IR\n\t/* Attempt a second ir using the same PKI user data.  This should fail,\n\t   since the certificate store only allows a single ir per user */\n\tif( requestCert( \"Duplicate init.request\", &caInfo, NULL, NULL,\n\t\t\t\t\t cmpCryptlibRequestNoDNData, cryptAlgo, cryptCACert, \n\t\t\t\t\t FALSE, TRUE, NULL ) )\n\t\t{\n\t\tprintf( \"Duplicate init request wasn't detected by the CMP server, \"\n\t\t\t\t\"line %d.\\n\\n\", __LINE__ );\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( FALSE );\n\t\t}\n#endif /* TEST_DUP_IR */\n\n\t/* Certificate request.  We have to perform this test before the kur \n\t   because cryptlib implicitly revokes the certificate being replaced, \n\t   which means that we can't use it to authenticate requests any more \n\t   once the kur has been performed */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 2 );\n\tstatus = requestCert( \"certificate request (cr)\", &caInfo, readFileName, \n\t\t\t\t\t\t  writeFileName, cmpCryptlibRequestData, cryptAlgo, \n\t\t\t\t\t\t  cryptCACert, FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCert );\n\t\tcryptDestroyCert( cryptCACert );\n\t\tif( isErrorTest )\n\t\t\t{\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t  \"response is correct).\\n\\n\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\treturn( status );\n\t\t}\n\tif( isErrorTest )\n\t\t{\n\t\tcryptDestroyCert( cryptCert );\n\t\tcryptDestroyCert( cryptCACert );\n\t\tputs( \"  (This test should have led to a failure but \"\n\t\t\t  \"didn't, test has failed).\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tdelayThread( 2 );\t\t/* Wait for server to recycle */\n\n\t/* Key update request.  This updates the existing key that we've just\n\t   written to a file, so there's no new certificate-request data that\n\t   gets submitted.  In other words the new certificate that's issued is\n\t   identical to the existing one except for the date/time value.\n\n\t   Since we've just created the certificate, we have to delete it so \n\t   that we can replace it with the kur'd form */\n\tcryptDestroyCert( cryptCert );\n\n\t/* If it's a CA that implicitly revokes the certificate being replaced \n\t   (in which case tracking things gets a bit too complicated since we \n\t   now need to use the updated rather than original certificate to \n\t   authenticate the request) we just leave it unrevoked (the first \n\t   certificate is always revoked) */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"certificate update (kur)\", &caInfo, readFileName, \n\t\t\t\t\t\t  NULL, NULL, CRYPT_UNUSED, cryptCACert, FALSE, \n\t\t\t\t\t\t  FALSE, &cryptCert );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n\tdelayThread( 2 );\t\t/* Wait for server to recycle */\n#if 0\n\t/* DSA certificate request.  We have to get this now because we're about \n\t   to revoke the certificate we're using to sign the requests.  This \n\t   currently isn't checked since it's a standard signature-only \n\t   certificate request whose processing has already been checked in\n\t   testCertProcess() */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"DSA certificate\", &caInfo, readFileName, NULL,\n\t\t\t\t\t\t  cmpDsaRequestData, CRYPT_ALGO_DSA, cryptCACert,\n\t\t\t\t\t\t  FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\treturn( status );\n\tdelayThread( 2 );\t\t/* Wait for server to recycle */\n#endif /* 0 */\n\n\t/* Revocation request.  The current certificate is a kur'd certificate \n\t   for which the original has been implicitly revoked by the kur process \n\t   and what we have now is an ephemeral test-only certificate whose \n\t   details weren't stored (so they can't be passed to requestCert(), we \n\t   can't do much else with it */\n\tcryptDestroyCert( cryptCert );\n\n\t/* We requested a second certificate whose details were recorded, revoke \n\t   that.  Note that we have to sign this with the second certificate \n\t   since the first one was the implicitly-revoked kur'd one */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 2 );\n\tstatus = revokeCert( \"RSA signing certificate\", &caInfo, readFileName,\n\t\t\t\t\t\t CRYPT_UNUSED, cryptCACert, USE_SIGNED_RR );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCACert );\n\treturn( TRUE );\n\t}\n\n/* Connect to a non-cryptlib CMP server */\n\nstatic int connectCMP( const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_CERTIFICATE cryptCACert, cryptCert;\n\tC_CHR readFileName[ FILENAME_BUFFER_SIZE ];\n\tC_CHR writeFileName[ FILENAME_BUFFER_SIZE ];\n\tconst CA_INFO *caInfoPtr = &caInfoTbl[ CA_NO ];\n\tint status;\n\n\t/* Get the certificate of the CA who will issue the certificate */\n\tstatus = importCertFromTemplate( &cryptCACert, CMP_CA_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t CA_NO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't get CMP CA certificate, status = %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Test each certificate request type */\n\n#ifdef TEST_IR\n\t/* Initialisation request.  We define REVOKE_FIRST_CERT to indicate that \n\t   we can revoke this one later on */\n\t#define REVOKE_FIRST_CERT\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"certificate init.request (ir)\", caInfoPtr, NULL, \n\t\t\t\t\t\t  writeFileName, cmpRsaSignRequestData, cryptAlgo, \n\t\t\t\t\t\t  cryptCACert, FALSE, FALSE, &cryptCert );\n\tif( status != TRUE )\n\t\t{\n\t\t/* If this is the self-test and there's a non-fatal error, make sure\n\t\t   we don't fail with a CRYPT_ERROR_INCOMPLETE when we're finished */\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n#endif /* TEST_IR */\n\n#ifdef TEST_CR\n\t/* Certificate request.  We have to perform this test before the kur \n\t   since some CAs implicitly revoke the certificate being replaced, \n\t   which means that we can't use it to authenticate requests any more \n\t   once the kur has been performed.  We define REVOKE_SECOND_CERT to \n\t   indicate that we can revoke this one later on alongside the ir/kur'd \n\t   certificate, and save a copy to a file for later use */\n\t#define REVOKE_SECOND_CERT\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 2 );\n\tstatus = requestCert( \"certificate request (cr)\", caInfoPtr, \n\t\t\t\t\t\t  readFileName, writeFileName, cmpRsaSignRequestData,\n\t\t\t\t\t\t  cryptAlgo, cryptCACert, FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\t{\n  #if defined( TEST_IR )\n\t\tcryptDestroyCert( cryptCert );\n  #endif /* TEST_IR || TEST_KUR */\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n#endif /* TEST_CR */\n\n#ifdef TEST_KUR\n\t/* Key update request.  This updates the existing key that we've just\n\t   written to a file, so there's no new certificate-request data that\n\t   gets submitted.  In other words the new certificate that's issued is\n\t   identical to the existing one except for the dates/time values */\n  #ifdef TEST_IR\n\t/* We just created the certificate, delete it so we can replace it with \n\t   the updated form */\n\tcryptDestroyCert( cryptCert );\n  #endif /* TEST_IR */\n\n\t/* If it's a CA that implicitly revokes the certificate being replaced \n\t   (in which case tracking things gets a bit too complicated since we \n\t   now need to use the updated rather than original certificate to \n\t   authenticate the request) we just leave it unrevoked (the first \n\t   certificate is always revoked) */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"certificate update (kur)\", caInfoPtr, \n\t\t\t\t\t\t  readFileName, NULL, NULL, CRYPT_UNUSED,\n\t\t\t\t\t\t  cryptCACert, FALSE, FALSE, &cryptCert );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n#endif /* TEST_KUR */\n#if 0\n\t/* Encryption-only certificate request.  This test requires a change in\n\t   certsign.c because when creating a certificate request cryptlib \n\t   always allows signing for the request even if it's an encryption-only \n\t   key (this is required for PKCS #10, see the comment in the kernel \n\t   code).  Because of this a request will always appear to be associated \n\t   with a signature-enabled key so it's necessary to make a code change \n\t   to disallow this.  Disallowing sigs for encryption-only keys would \n\t   break PKCS #10 since it's then no longer possible to create the self-\n\t   signed request, this is a much bigger concern than CMP.  Note that \n\t   this functionality is tested by the PnP PKI test, which creates the\n\t   necessary encryption-only requests internally and can do things that\n\t   we can't do from the outside */\n\tstatus = requestCert( \"encryption-only certificate\", caInfoPtr,\n\t\t\t\t\t\t  readFileName, writeFileName, \n\t\t\t\t\t\t  cmpRsaEncryptRequestData, CRYPT_ALGO_RSA, \n\t\t\t\t\t\t  cryptCACert, FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\treturn( status );\n#endif /* 0 */\n\n\t/* Revocation request */\n#ifdef TEST_RR\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n  #ifdef REVOKE_FIRST_CERT\n\t#ifdef SERVER_IR_DN\n\tstatus = revokeCert( \"RSA initial/updated certificate\", caInfoPtr,\n\t\t\t\t\t\t readFileName, cryptCert, cryptCACert, TRUE );\n\t#else\n\tstatus = revokeCert( \"RSA initial/updated certificate\", caInfoPtr,\n\t\t\t\t\t\t readFileName, cryptCert, cryptCACert, FALSE );\n\t#endif /* Certicom requires signed request */\n\tcryptDestroyCert( cryptCert );\n  #elif !defined( TEST_KUR )\n\t/* We didn't issue the first certificate in this run, try revoking it \n\t   from the certificate stored in the key file unless we're talking to a \n\t   CA that implicitly revokes the certificate being replaced during a \n\t   kur */\n\tstatus = revokeCert( \"RSA initial/updated certificate\", caInfoPtr,\n\t\t\t\t\t\t readFileName, CRYPT_UNUSED, cryptCACert, TRUE );\n  #else\n\t/* This is a kur'd certificate for which the original has been \n\t   implicitly revoked, we can't do much else with it */\n\tcryptDestroyCert( cryptCert );\n  #endif /* REVOKE_FIRST_CERT */\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n  #ifdef REVOKE_SECOND_CERT\n\t/* We requested a second certificate, revoke that too.  Note that we \n\t   have to sign this with the second certificate since the first one may \n\t   have just been revoked */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 2 );\n\tstatus = revokeCert( \"RSA signing certificate\", caInfoPtr, readFileName,\n\t\t\t\t\t\t CRYPT_UNUSED, cryptCACert, TRUE );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n  #endif /* REVOKE_SECOND_CERT */\n#endif /* TEST_RR */\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCACert );\n\treturn( TRUE );\n\t}\n\n/* Connect to a non-cryptlib CMP server with RA functionality */\n\nstatic int connectCMPRA( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCACert;\n\tC_CHR readFileName[ FILENAME_BUFFER_SIZE ];\n\tC_CHR writeFileName[ FILENAME_BUFFER_SIZE ];\n\tC_CHR userID[ 64 ], issuePW[ 64 ], revPW[ 64 ];\n\tconst CA_INFO *caInfoPtr = &caInfoTbl[ CA_NO ];\n\tCA_INFO caInfo;\n\tint status;\n\n\t/* Get the certificate of the CA who will issue the certificate */\n\tstatus = importCertFromTemplate( &cryptCACert, CMP_CA_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t CA_NO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't get CMP CA certificate, status = %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Wait for the server to finish initialising */\n\tif( waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the certificate for the RA to use to authorise the issuance of\n\t   further certificates */\n\tstatus = getPkiUserInfo( TEXT( \"Test RA PKI user\" ), &caInfo, \n\t\t\t\t\t\t\t userID, issuePW, revPW );\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tstatus = requestCert( \"RA certificate request\", &caInfo, NULL, \n\t\t\t\t\t\t  writeFileName, cmpCryptlibRequestNoDNData, \n\t\t\t\t\t\t  CRYPT_ALGO_RSA, cryptCACert, FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\treturn( FALSE );\n\n\t/* Test the certificate request functionality using an RA certificate, \n\t   which means using CMP's CR operation with an RA certificate instead \n\t   of the user's certificate from an IR */\n\tfilenameParamFromTemplate( readFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 2 );\n\tstatus = requestCert( \"certificate request (cr) via RA\", caInfoPtr, \n\t\t\t\t\t\t  readFileName, writeFileName, cmpRsaSignRequestData,\n\t\t\t\t\t\t  CRYPT_ALGO_RSA, cryptCACert, FALSE, FALSE, NULL );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( status );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCACert );\n\treturn( TRUE );\n\t}\n\nstatic int connectCMPFail( const int count )\n\t{\n\tstatic const CERT_DATA cmpFailRequestData1[] = {\n\t\t/* Fails when tested against the full-DN PKI user because the CN \n\t\t   doesn't match the PKI user CN */\n\t\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Not the test PKI user\" ) },\n\n\t\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t\t};\n\tstatic const CERT_DATA cmpFailRequestData2[] = {\n\t\t/* Fails when tested against the full-DN PKI user because there's \n\t\t   already an email address present in the PKI user data */\n#if 0\n\t\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n#endif /* 0 */\n\t\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t\t};\n\tstatic const CERT_DATA cmpFailRequestData3[] = {\n\t\t/* Fails when tested against the partial-DN (no CN specified) PKI \n\t\t   user because the OU doesn't match the PKI user OU even though the \n\t\t   CN is allowed */\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Not procurement\" ) },\n\t\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test PKI user\" ) },\n\n\t\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t\t};\n#if 0\t/* Reuse cmpRsaCaRequestData[] */\n\tstatic const CERT_DATA cmpFailRequestData4[] = {\n\t\t/* Fails because we're asking for a CA certificate when the PKI \n\t\t   user is only an EE */\n\t\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test PKI user\" ) },\n\t\t{ CRYPT_CERTINFO_CA, IS_NUMERIC, TRUE },\n\t\t{ CRYPT_CERTINFO_KEYUSAGE, IS_NUMERIC,\n\t\t  CRYPT_KEYUSAGE_KEYCERTSIGN | CRYPT_KEYUSAGE_CRLSIGN },\n\n\t\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t\t};\n#endif /* 0 */\n\tstatic const CERT_DATA *cmpFailRequestDataTbl[] = {\n\t\tcmpFailRequestData1, cmpFailRequestData2, cmpFailRequestData3, \n#if 0\n\t\tcmpFailRequestData4\n#else\n\t\tcmpRsaCaRequestData\n#endif /* 0 */\n\t\t};\n\tstatic const char *cmpFailRequestDescriptionTbl[] = {\n\t\t\"request containing full DN with CN mis-matching\\n  pkiUser CN\",\n\t\t\"request containing extra field in altName\\n  not present in pkiUser altName\",\n\t\t\"request containing partial DN with OU\\n  mis-matching pkiUser CN\",\n\t\t\"request for a CA cert for an EE user\"\n\t\t};\n\tCRYPT_CERTIFICATE cryptCACert = CRYPT_UNUSED, cryptCert;\n\tC_CHR writeFileName[ FILENAME_BUFFER_SIZE ];\n\tCA_INFO caInfo;\n\tC_CHR userID[ 64 ], issuePW[ 64 ], revPW[ 64 ];\n\tchar message[ 128 ];\n\tint status;\n\n\t/* Wait for the server to finish initialising */\n\tif( count == 0 && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get the certificate of the CA who will issue the certificate and the \n\t   PKI user details */\n\tstatus = importCertFromTemplate( &cryptCACert, CMP_CA_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t CA_CRYPTLIB );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't get CMP CA certificate, status = %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = getPkiUserInfo( TEXT( \"Test PKI user\" ), &caInfo, \n\t\t\t\t\t\t\t userID, issuePW, revPW );\n\tif( status != TRUE )\n\t\t{\n\t\tcryptDestroyCert( cryptCACert );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Send the request, which should be rejected by the server because \n\t   something in the request differs from what's in the PKI user \n\t   template */\n\tfilenameParamFromTemplate( writeFileName, CMP_PRIVKEY_FILE_TEMPLATE, 1 );\n\tsprintf( message, \"invalid request %d with %s,\", count + 1,\n\t\t\t cmpFailRequestDescriptionTbl[ count ] );\n\tstatus = requestCert( message, &caInfo, NULL, NULL, \n\t\t\t\t\t\t  cmpFailRequestDataTbl[ count ], CRYPT_ALGO_RSA, \n\t\t\t\t\t\t  cryptCACert, FALSE, FALSE, &cryptCert );\n\tcryptDestroyCert( cryptCACert );\n\tif( status )\n\t\t{\n\t\t/* The request should have been rejected */\n\t\tputs( \"Invalid CMP request should have been rejected, but \"\n\t\t\t  \"wasn't.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The request was successfully rejected, let the user know that the \n\t   error spew was supposed to be there */\n\tputs( \"  (This isn't an error since we're checking for the rejection \"\n\t\t  \"of invalid\\n   requests).\\n\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionCMP( void )\n\t{\n\treturn( connectCMP( CRYPT_ALGO_RSA ) );\n\t}\n\n/* Test the plug-and-play PKI functionality */\n\nstatic int connectPNPPKI( const BOOLEAN isCaUser, const BOOLEAN useDevice,\n\t\t\t\t\t\t  const BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_KEYSET cryptKeyset;\n\tC_CHR userID[ 64 ], issuePW[ 64 ], revPW[ 64 ];\n\tint status;\n\n\t/* Create the CMP session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* CMP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifdef SERVER_IS_CRYPTLIB\n\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\treturn( FALSE );\n#endif /* SERVER_IS_CRYPTLIB */\n\n\t/* Open the device/create the keyset to contain the keys.  This doesn't\n\t   perform a full device.c-style auto-configure but assumes that it's\n\t   talking to a device that's already been initialised and is ready to\n\t   go */\n\tif( useDevice )\n\t\t{\n\t\tstatus = cryptDeviceOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_DEVICE_PKCS11,\n\t\t\t\t\t\t\t\t  TEXT( \"[Autodetect]\" ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Crypto device open failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptSetAttributeString( cryptKeyset,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_DEVINFO_AUTHENT_USER,\n\t\t\t\t\t\t\t\t\t\t  \"test\", 4 );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"\\nDevice login failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tTEXT( \"Signature key\" ) ) == CRYPT_OK )\n\t\t\t{\n\t\t\tputs( \"(Deleted a signature key object, presumably a leftover \"\n\t\t\t\t  \"from a previous run).\" );\n\t\t\t}\n\t\tif( cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\tTEXT( \"Encryption key\" ) ) == CRYPT_OK )\n\t\t\t{\n\t\t\tputs( \"(Deleted an encryption key object, presumably a leftover \"\n\t\t\t\t  \"from a previous run).\" );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, isCaUser ? \\\n\t\t\t\t\t\t\t\t\t\tPNPCA_PRIVKEY_FILE : PNP_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"User keyset create failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Wait for the server to finish initialising */\n\tif( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Get information needed for enrolment */\n\tstatus = pkiGetUserInfo( userID, issuePW, revPW, isCaUser ? \\\n\t\t\t\t\t\t\t\tTEXT( \"Test CA PKI user\" ) : \\\n\t\t\t\t\t\t\t\tTEXT( \"Test PKI user\" ) );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\t/* Certificate store operations aren't available, exit but continue \n\t\t   with other tests */\n\t\treturn( TRUE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Set up the information we need for the plug-and-play PKI process */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME, userID,\n\t\t\t\t\t\t\t\t\t  paramStrlen( userID ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  issuePW, paramStrlen( issuePW ) );\n\t\t}\n#ifndef SERVER_IS_CRYPTLIB\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  caInfoTbl[ CA_CRYPTLIB_PNPPKI ].url,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( caInfoTbl[ CA_CRYPTLIB_PNPPKI ].url ) );\n\t\t}\n#endif /* SERVER_IS_CRYPTLIB */\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_PRIVKEYSET,\n\t\t\t\t\t\t\t\t\tcryptKeyset );\n\t\t}\n\tif( cryptStatusOK( status ) && useDevice )\n\t\t{\n\t\t/* Keygen on a device can take an awfully long time for some devices,\n\t\t   so we set an extended timeout to allow for this */\n\t\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t   NET_TIMEOUT );\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_WRITETIMEOUT,\n\t\t\t\t\t\t\t\t\tNET_TIMEOUT );\n\t\t}\n\tif( useDevice )\n\t\tcryptDeviceClose( cryptKeyset );\n\telse\n\t\tcryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Addition of session information failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Activate the session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"Attempt to activate plug-and-play PKI \"\n\t\t\t\t\t   \"client session\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroySession( cryptSession );\n\n\t/* If this is the intermediate CA certificate, change the password to \n\t   allow it to be used with the standard PnP PKI test */\n\tif( isCaUser )\n\t\t{\n\t\tCRYPT_CONTEXT cryptKey DUMMY_INIT;\n\n\t\t/* Get the newly-issued key */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, PNPCA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetPrivateKey( cryptKeyset, &cryptKey,\n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t\t TEXT( \"Signature key\" ), issuePW );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Certified private-key read failed with error code %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Replace the keyset with one with the key protected with a\n\t\t   different password */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, PNPCA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptAddPrivateKey( cryptKeyset, cryptKey,\n\t\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\tcryptDestroyContext( cryptKey );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Certified private-key password change failed with error \"\n\t\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nint testSessionPNPPKI( void )\n\t{\n\treturn( connectPNPPKI( FALSE, FALSE, FALSE ) );\n\t}\n\n/* Test the CMP server */\n\nstatic int cmpServerSingleIteration( const CRYPT_CONTEXT cryptPrivateKey,\n\t\t\t\t\t\t\t\t\t const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t\t\t\t\t const BOOLEAN useDevice )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\t/* Create the CMP session and add the CA key and certificate store */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP_SERVER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptCreateSession() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_PRIVATEKEY, \n\t\t\t\t\t\t\t\tcryptPrivateKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_KEYSET, \n\t\t\t\t\t\t\t\t\tcryptCertStore );\n\t\t}\n\tif( cryptStatusOK( status ) && useDevice )\n\t\t{\n\t\t/* Keygen on a device can take an awfully long time for some devices,\n\t\t   so we set an extended timeout to allow for this */\n\t\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t   NET_TIMEOUT );\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_WRITETIMEOUT,\n\t\t\t\t\t\t\t\t\tNET_TIMEOUT );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\treturn( FALSE );\n\n\t/* Activate the session */\n\tstatus = activatePersistentServerSession( cryptSession, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tstatus = extErrorExit( cryptSession, \"SVR: Attempt to activate CMP \"\n\t\t\t\t\t\t\t   \"server session\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( status );\n\t\t}\n\n\t/* We processed the request, clean up */\n\tcryptDestroySession( cryptSession );\n\treturn( TRUE );\n\t}\n\nstatic int cmpServer( void )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\tint i, status;\n\n\t/* Acquire the init mutex */\n\tacquireMutex();\n\n\tputs( \"SVR: Testing CMP server session...\" );\n\n\t/* Perform a test create of a CMP server session to verify that we can\n\t   do this test */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP_SERVER );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* CMP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptCreateSession() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\n\t/* Set up the server-side objects */\n\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore, CA_PRIVKEY_FILE,\n\t\t\t\t\t\tCA_PRIVKEY_LABEL, cmpPkiUserFullDNData, \n\t\t\t\t\t\tcmpPkiUserPartialDNData, cmpPkiUserCaData, \n\t\t\t\t\t\tcmpPkiUserRaData, \"CMP\" ) )\n\t\treturn( FALSE );\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Run the server several times to handle the different requests */\n\tfor( i = 0; i < NO_CA_REQUESTS; i++ )\n\t\t{\n\t\tprintf( \"SVR: Running server iteration %d.\\n\", i + 1 );\n\t\tif( !cmpServerSingleIteration( cryptCAKey, cryptCertStore, FALSE ) )\n\t\t\t{\n#if defined( SERVER_IS_CRYPTLIB ) && defined( TEST_DUP_IR )\n\t\t\t/* If we're running the loopback test and this is the second\n\t\t\t   iteration, the client is testing the ability to detect a\n\t\t\t   duplicate ir, so a failure is expected */\n\t\t\tif( i == 1 )\n\t\t\t\t{\n\t\t\t\tputs( \"SVR: Failure was due to a rejected duplicate request \"\n\t\t\t\t\t  \"from the client,\\n     continuing...\" );\n\t\t\t\tcontinue;\n\t\t\t\t}\n#endif /* SERVER_IS_CRYPTLIB && TEST_DUP_IR */\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tif( i < NO_CA_REQUESTS )\n\t\t{\n\t\tcryptKeysetClose( cryptCertStore );\n\t\tcryptDestroyContext( cryptCAKey );\n\t\tif( i == 0 )\n\t\t\treturn( FALSE );\n\t\tprintf( \"SVR: Only %d of %d server requests were processed.\\n\", i,\n\t\t\t\tNO_CA_REQUESTS );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"SVR: All server requests were successfully processed.\" );\n\n\t/* Issue a CRL to make sure that the revocation was performed correctly.\n\t   We do this now because the certificate management self-test can't \n\t   easily perform the check because it requires a CMP-revoked \n\t   certificate in order to function */\n\tif( i >= NO_CA_REQUESTS )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCRL;\n\t\tint noEntries = 0;\n\n\t\t/* Issue the CRL */\n\t\tstatus = cryptCACertManagement( &cryptCRL, CRYPT_CERTACTION_ISSUE_CRL,\n\t\t\t\t\t\t\t\t\t\tcryptCertStore, cryptCAKey,\n\t\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( extErrorExit( cryptCertStore, \"cryptCACertManagement()\",\n\t\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t\t}\n\n\t\t/* Make sure that the CRL contains at least one entry */\n\t\tif( cryptStatusOK( \\\n\t\t\t\tcryptSetAttribute( cryptCRL, \n\t\t\t\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE, CRYPT_CURSOR_FIRST ) ) )\n\t\t\t{\n\t\t\tdo\n\t\t\t\tnoEntries++;\n\t\t\twhile( cryptSetAttribute( cryptCRL,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\t\t}\n\t\tif( noEntries <= 0 )\n\t\t\t{\n\t\t\tputs( \"CRL created from revoked certificate is empty, should \"\n\t\t\t\t  \"contain at least one\\ncertificate entry.\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Clean up */\n\t\tcryptDestroyCert( cryptCRL );\n\t\t}\n\n\t/* Clean up */\n\tcryptKeysetClose( cryptCertStore );\n\tcryptDestroyContext( cryptCAKey );\n\tputs( \"SVR: CMP session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionCMPServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = cmpServer();\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\nstatic int cmpServerRA( void )\n\t{\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\n\t/* Acquire the init mutex */\n\tacquireMutex();\n\n\tputs( \"SVR: Testing CMP server for RA processing...\" );\n\n\t/* Set up the server-side objects */\n\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore, CA_PRIVKEY_FILE,\n\t\t\t\t\t\tCA_PRIVKEY_LABEL, cmpPkiUserFullDNData, \n\t\t\t\t\t\tcmpPkiUserPartialDNData, cmpPkiUserCaData, \n\t\t\t\t\t\tcmpPkiUserRaData, \"CMP\" ) )\n\t\treturn( FALSE );\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Run the server twice to handle the RA's certificate request followed\n\t   by the RA-authorised client's certificate request */\n\tputs( \"SVR: Running server for RA certificate issue.\" );\n\tif( !cmpServerSingleIteration( cryptCAKey, cryptCertStore, FALSE ) )\n\t\t{\n\t\tputs( \"SVR: CMP RA certificate issue failed.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tputs( \"SVR: Running server for RA-authorised certificate issue.\" );\n\tif( !cmpServerSingleIteration( cryptCAKey, cryptCertStore, FALSE ) )\n\t\t{\n\t\tputs( \"SVR: CMP RA-authorised certificate issue failed.\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tcryptKeysetClose( cryptCertStore );\n\tcryptDestroyContext( cryptCAKey );\n\n\tputs( \"SVR: CMP RA processing successful.\\n\" );\n\treturn( TRUE );\n\t}\n\nstatic int cmpServerFail( void )\n\t{\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\tint i;\n\n\t/* Acquire the init mutex */\n\tacquireMutex();\n\n\tputs( \"SVR: Testing CMP server for rejection of invalid requests...\" );\n\n\t/* Set up the server-side objects */\n\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore, CA_PRIVKEY_FILE,\n\t\t\t\t\t\tCA_PRIVKEY_LABEL, cmpPkiUserFullDNData, \n\t\t\t\t\t\tcmpPkiUserPartialDNData, cmpPkiUserCaData, \n\t\t\t\t\t\tcmpPkiUserRaData, \"CMP\" ) )\n\t\treturn( FALSE );\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Run the server several times to handle the different requests, which \n\t   should all be rejected */\n\tfor( i = 0; i < 3; i++ )\n\t\t{\n\t\tprintf( \"SVR: Running server iteration %d.\\n\", i + 1 );\n\t\tif( cmpServerSingleIteration( cryptCAKey, cryptCertStore, FALSE ) )\n\t\t\t{\n\t\t\tputs( \"SVR: CMP request succeeded when it should have \"\n\t\t\t\t  \"failed.\\n\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tcryptKeysetClose( cryptCertStore );\n\tcryptDestroyContext( cryptCAKey );\n\n\tputs( \"SVR: CMP invalid requests successfully rejected.\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nstatic int pnppkiServer( const BOOLEAN pkiBootOnly, const BOOLEAN isCaUser,\n\t\t\t\t\t\t const BOOLEAN isIntermediateCA,\n\t\t\t\t\t\t const BOOLEAN useDevice )\n\t{\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\n\t/* Acquire the PNP PKI init mutex */\n\tacquireMutex();\n\n\tprintf( \"SVR: Testing %s server session%s...\\n\",\n\t\t\tpkiBootOnly ? \"PKIBoot\" : \"plug-and-play PKI\",\n\t\t\tisCaUser ? \" for CA certificate\" : \\\n\t\t\t\tisIntermediateCA ? \" using intermediate CA\" : \"\" );\n\n\t/* Get the information needed by the server */\n\tif( isIntermediateCA )\n\t\t{\n\t\t/* The intermediate CA has a PnP-generated, so the key label is\n\t\t   the predefined PnP signature key one */\n\t\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore,\n\t\t\t\t\t\t\tPNPCA_PRIVKEY_FILE, TEXT( \"Signature key\" ),\n\t\t\t\t\t\t\tcmpPkiUserFullDNData, cmpPkiUserPartialDNData, \n\t\t\t\t\t\t\tcmpPkiUserCaData, cmpPkiUserRaData, \"CMP\" ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore, CA_PRIVKEY_FILE,\n\t\t\t\t\t\t\tCA_PRIVKEY_LABEL, cmpPkiUserFullDNData,\n\t\t\t\t\t\t\tcmpPkiUserPartialDNData, cmpPkiUserCaData, \n\t\t\t\t\t\t\tcmpPkiUserRaData, \"CMP\" ) )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Run the server once to handle the plug-and-play PKI process */\n\tif( !cmpServerSingleIteration( cryptCAKey, cryptCertStore, useDevice ) )\n\t\treturn( FALSE );\n\n\t/* Clean up */\n\tcryptKeysetClose( cryptCertStore );\n\tcryptDestroyContext( cryptCAKey );\n\n\tputs( \"SVR: Plug-and-play PKI session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nunsigned __stdcall cmpServerThread( void *dummy )\n\t{\n\tcmpServer();\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nstatic int cmpClientServer( const CMP_TEST_TYPE testType,\n\t\t\t\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n#ifndef SERVER_IS_CRYPTLIB\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local CMP session test only works with the cryptlib \"\n\t\t  \"CA.\" );\n\treturn( FALSE );\n#endif /* !SERVER_IS_CRYPTLIB */\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectCryptlibCMP( testType, cryptAlgo );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionCMPClientServer( void )\n\t{\n\treturn( cmpClientServer( CMP_TEST_NORMAL, CRYPT_ALGO_RSA ) );\n\t}\n\nint testSessionCMPAltAlgoClientServer( void )\n\t{\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"ECC algorithm support appears to be disabled, skipping \"\n\t\t\t   \"CMP processing of\\nECDSA certificates.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( cmpClientServer( CMP_TEST_NORMAL, CRYPT_ALGO_ECDSA ) );\n\t}\n\nint testSessionCMPSHA2ClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint value, status;\n\n#ifndef SERVER_IS_CRYPTLIB\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local CMP session test only works with the cryptlib \"\n\t\t  \"CA.\" );\n\treturn( FALSE );\n#endif /* !SERVER_IS_CRYPTLIB */\n\n\t/* Switch the hash algorithm to SHA-2 */\n\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, &value );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH,\n\t\t\t\t\t   CRYPT_ALGO_SHA2 );\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectCryptlibCMP( CMP_TEST_NORMAL, CRYPT_ALGO_RSA );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, value );\n\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpPKIBootServerThread( void *dummy )\n\t{\n\tpnppkiServer( TRUE, FALSE, FALSE, FALSE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionCMPPKIBootClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n#ifndef SERVER_IS_CRYPTLIB\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local CMP session test only works with the cryptlib \"\n\t\t  \"CA.\" );\n\treturn( FALSE );\n#endif /* !SERVER_IS_CRYPTLIB */\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpPKIBootServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = connectCryptlibCMP( CMP_TEST_PKIBOOT, CRYPT_ALGO_RSA );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpPnPPKIServerThread( void *dummy )\n\t{\n\t/* Call with the third parameter set to TRUE to use a chain of CA certs\n\t   (i.e. an intermediate CA between the root and end user) rather than\n\t   a single CA certificate directly issuing the certificate to the end \n\t   user */\n\tpnppkiServer( FALSE, FALSE, FALSE, FALSE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionPNPPKIClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpPnPPKIServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = connectPNPPKI( FALSE, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpPnPPKIDeviceServerThread( void *dummy )\n\t{\n\t/* Call with the third parameter set to TRUE to use a chain of CA certs\n\t   (i.e. an intermediate CA between the root and end user) rather than\n\t   a single CA certificate directly issuing the certificate to the end \n\t   user */\n\tpnppkiServer( FALSE, FALSE, FALSE, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionPNPPKIDeviceClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpPnPPKIDeviceServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = connectPNPPKI( FALSE, TRUE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpPnPPKICaServerThread( void *dummy )\n\t{\n\tpnppkiServer( FALSE, TRUE, FALSE, FALSE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionPNPPKICAClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpPnPPKICaServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = connectPNPPKI( TRUE, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpPnPPKIIntermedCaServerThread( void *dummy )\n\t{\n\tpnppkiServer( FALSE, FALSE, TRUE, FALSE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionPNPPKIIntermedCAClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpPnPPKIIntermedCaServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with PKIBoot enabled */\n\tstatus = connectPNPPKI( FALSE, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpServerRAThread( void *dummy )\n\t{\n\tcmpServerRA();\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionCMPRAClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpServerRAThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with RA functionality */\n\tstatus = connectCMPRA();\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall cmpFailServerThread( void *dummy )\n\t{\n\tcmpServerFail();\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionCMPFailClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, cmpFailServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server with several requests that should fail */\n\tstatus = connectCMPFail( 0 );\n\tif( status )\n\t\tstatus = connectCMPFail( 1 );\n\tif( status )\n\t\tstatus = connectCMPFail( 2 );\n\tif( status )\n\t\t{\n\t\t/* This test currently fails before the request is even submitted \n\t\t   because cryptlib prevents any attempt to request a CA \n\t\t   certificate, it's present in case this functionality is enabled\n\t\t   in the future */\n\t\tstatus = connectCMPFail( 3 );\n\t\t}\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionCMPClientServerDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !cmpClientServer( CMP_TEST_CORRUPT_TRANSACTIONID, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of transaction ID */\n\tif( !cmpClientServer( CMP_TEST_BADSIG_DATA, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Sig.check failure - bad data */\n\tif( !cmpClientServer( CMP_TEST_BADSIG_HASH, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Sig.check failure - bad hash/MAC */\n\tif( !cmpClientServer( CMP_TEST_BADSIG_SIG, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Sig.check failure - bad hash/MAC */\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n#endif /* WINDOWS_THREADS */\n\n#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */\n"
  },
  {
    "path": "deps/cl345/test/s_scep.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tcryptlib SCEP Session Test Routines\t\t\t\t\t\t*\n*\t\t\t\t\tCopyright Peter Gutmann 1998-2016\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n/* Define the following to test the use of custom attributes via the pkiUser\n   object */\n\n/* #define TEST_CUSTOM_ATTRIBUTE */\n\n/* We can run the SCEP self-test with a large variety of options, rather \n   than using dozens of boolean option flags to control them all we define \n   various test classes that exercise each option type */\n\ntypedef enum {\n\tSCEP_TEST_NONE,\t\t\t\t/* No SCEP test type */\n\tSCEP_TEST_NORMAL,\t\t\t/* Standard SCEP test */\n\tSCEP_TEST_CACERT,\t\t\t/* Get CA cert instead of std.one */\n\tSCEP_TEST_CUSTOMEXT,\t\t/* Add custom extension to request */\n\tSCEP_TEST_RENEW,\t\t\t/* Renew existing certificate */\n\tSCEP_TEST_CORRUPT_TRANSACTIONID, /* Detect corruption of transaction ID */\n\tSCEP_TEST_CORRUPT_TRANSIDVALUE, /* Detect corruption of trans.ID data */\n\tSCEP_TEST_CORRUPT_MESSAGETYPE, /* Detect corruption of message type */\n\tSCEP_TEST_CORRUPT_NONCE,\t/* Detect corruption of sender/recipNonce */\n\tSCEP_TEST_CORRUPT_AUTHENTICATOR, /* Detect corruption of password */\n\tSCEP_TEST_LAST\t\t\t\t/* Last possible CMP test type */\n\t} SCEP_TEST_TYPE;\n\n#if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSCEP Test Data\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There were various SCEP test servers available at some point, although \n   most of them are either semi- or entirely nonfunctional or vanished years\n   ago.  The following mappings can be used to test different ones.  \n   Implementation peculiarities:\n\n\t#1 - cryptlib: None.\n\n\t#2 - SSH (www.ssh.com/support/testzone/pki.html): Invalid CA \n\t     certificates, and disappeared some years ago.  Continued as Insta-\n\t\t Certifier, see #6 below.\n\n\t#3 - OpenSCEP (openscep.othello.ch): Seems to be permanently unavailable.\n\n\t#4 - Entrust (freecerts.entrust.com/vpncerts/cep.htm): Only seems to be\n\t\t set up to handle Cisco gear.\n\n\t#5 - EJBCA: Server has vanished.\n\t\n\t#6 - Insta-Certifier: Information originally at \n\t\t http://www.certificate.fi/resources/demos/demo.htm, then at\n\t\t http://security.insta.fi/solutions-en/product/productid=24167486.\n\t\t This apparently implements SCEP as per the -09 draft from 2003 and\n\t\t based on the appearance of the web page hasn't changed since it was\n\t\t the SSH server in #2, so it doesn't really interoperate with any\n\t\t version of SCEP from about the last ten years (no GetCACaps, no\n\t\t POST, etc).  If necessary this behaviour can be forced by adding:\n\n\t\t\tscepInfo->flags |= SCEP_PFLAG_GOTCACAPS;\n\t\t\tsendPostAsGet = TRUE;\n\n\t\t to the start of clientTransact() in session/scep_cli.c but this \n\t\t isn't recommended since it breaks correct functioning with any \n\t\t standard SCEP server.\n\n\t#7 - Microsoft NDES: Reverted to a fresh install with no content several \n\t\t years ago, but used to return an invalid CA certificate.  The code \n\t\t sets the compliance level to CRYPT_COMPLIANCELEVEL_OBLIVIOUS to \n\t\t handle this.  GetCACaps \n\t\t (via http://qa4-mdm3.qa4.imdmdemo.com/certsrv/mscep/?operation=GetCACaps) \n\t\t is implemented but broken, returns a zero-length response.\n\t\n\t#8 - Windows Server 2003: Closes the connection on seeing GetCACaps.\n\n\t#9 - Windows Server 2008: Returns an invalid CA certificate (keyUsage is \n\t     set to keyEncipherment but not digitalSignature).  The code sets \n\t\t the compliance level to CRYPT_COMPLIANCELEVEL_OBLIVIOUS to handle \n\t\t this\n\n\t#10 - Windows Server 2008 (upgraded form of #8): Sends two certificates, \n\t     one with keyUsage = digitalSignature, one with keyUsage = \n\t\t keyEncipherment, so CA certificate fetch must be implicit so that \n\t\t the SCEP code can sort out which certificate to use at what point.\n\n\t\t When used with a implicit GetCACert (caCertUrl = \"default\") it \n\t\t closes the connection after the request has completed ('No data was \n\t\t read because the remote system closed the connection (recv() == \n\t\t 0)'), when an explicit fetch is performed it doesn't get a chance \n\t\t to do this but then the certificate(s) that are returned can't be \n\t\t used.\n\n\t#11 - Private vendor: Uses an auth key that changes every 10-15 minutes,\n\t\t obtained via https://jen.nuk9.com/pkiclient.exe?operation=GetChallengePassword&subject=CommonNameToBeUsed  \n\t\t in this case https://jen.nuk9.com/pkiclient.exe?operation=GetChallengePassword&subject=Test%20SCEP%20PKI%20user\n\t*/\n\n#define SCEP_NO\t\t1\n\ntypedef struct {\n\tconst char *name;\n\tconst C_CHR *url, *user, *password;\n\tconst C_CHR *caCertUrl;\n\t\t/* A URL fetches the CA certificate before starting the SCEP session,\n\t\t   NULL reads it from a file, and the string \"default\" use the built-\n\t\t   in GetCACert capability to read it automatically */\n\t} SCEP_INFO;\n\nstatic const SCEP_INFO scepInfo[] = {\n\t{ NULL },\t/* Dummy so index == SCEP_NO */\n\t{ /*1*/ \"cryptlib\", TEXT( \"http://localhost/pkiclient.exe\" ), NULL, NULL, \n/*\t\t\tTEXT( \"http://localhost/pkiclient.exe?operation=GetCACert&message=*\" ) }, */\n\t\t\tTEXT( \"default\" ) },\n\t\t\t/* We have to implicitly get the certificate via the client's \n\t\t\t   built-in GetCACert because if we do an explicit fetch from \n\t\t\t   the caCertUrl via an HTTP keyset then the server won't have \n\t\t\t   time to recycle before the next request comes in.  See also\n\t\t\t   the comment in scepServerThread() on mutex management for\n\t\t\t   the explicit HTTP fetch */\n\t{ /*2*/ \"SSH\", TEXT( \"http://pki.ssh.com:8080/scep/pkiclient.exe\" ), \n\t\t\tTEXT( \"ssh\" ), TEXT( \"ssh\" ),\n\t\t\tTEXT( \"http://pki.ssh.com:8080/scep/pkiclient.exe?operation=GetCACert&message=test-ca1.ssh.com\" ) },\n\t{ /*3*/ \"OpenSCEP\", TEXT( \"http://openscep.othello.ch/pkiclient.exe\" ), \n\t\t\tTEXT( \"????\" ), TEXT( \"????\" ), \n\t\t\tNULL },\n\t{ /*4*/ \"Entrust\", TEXT( \"http://vpncerts.entrust.com/pkiclient.exe\" ), \n\t\t\tTEXT( \"????\" ), TEXT( \"????\" ), \n\t\t\tNULL },\n\t{ /*5*/ \"EJBCA\", TEXT( \"http://q-rl-xp:8080/ejbca/publicweb/apply/scep/pkiclient.exe\" ),\n\t\t\tTEXT( \"test2\" ), TEXT( \"test2\" ),\n\t\t\tTEXT( \"http://q-rl-xp:8080/ejbca/publicweb/webdist/certdist?cmd=nscacert&issuer=O=Test&+level=1\" ) },\n\t{ /*6*/ \"Insta-Certifier\", TEXT( \"http://pki.certificate.fi:8082/scep/\" ), \n\t\t\tTEXT( \"user\" ), TEXT( \"scep\" ), \n\t\t\tTEXT( \"http://pki.certificate.fi:8082/scep/?operation=GetCACert&message=Insta%20Demo%20CA\" ) },\n\t{ /*7*/ \"Microsoft NDES\", TEXT( \"http://qa4-mdm3.qa4.imdmdemo.com\" ), \n\t\t\tTEXT( \"cryptlibtest\" ), TEXT( \"password!1\" ), \n\t\t\tTEXT( \"http://qa4-mdm3.qa4.imdmdemo.com/certsrv/mscep/?operation=GetCACert&message=qa\" ) },\n\t{ /*8*/ \"Win Server 2003\", TEXT( \"http://202.93.162.4/certsrv/mscep/mscep.dll\" ), \n\t\t\tTEXT( \"test\" ), TEXT( \"BF51DFAA61874412\" ), \"default\" },\n\t{ /*9*/ \"Win Server 2008, explicit GetCACert\", TEXT( \"http://142.176.86.157\" ), \n\t\t\tTEXT( \"cryptlibtest\" ), TEXT( \"password!1\" ), \n\t\t\tTEXT( \"http://142.176.86.157/certsrv/mscep/?operation=GetCACert&message=qa\" ) },\n\t{ /*10*/ \"Win Server 2008, implicit GetCACert\", TEXT( \"http://202.93.162.4/certsrv/mscep/mscep.dll\" ), \n\t\t\tTEXT( \"test\" ), TEXT( \"00654F176111B253DD996EEA67BBF16D\" ), \n\t\t\tTEXT( \"default\" ) },\n\t{ /*11*/ \"Private vendor\", TEXT( \"http://jen.nuk9.com/pkiclient.exe\" ), \n\t\t\tTEXT( \"user\" ), TEXT( \"STNDRUhGNXBLamU5TE5QWERwb2RicFdnUGVNOHNaTWtLZlo4cEpEazdkWT0sMTgzODY=\" ), \n\t\t\tTEXT( \"default\" ) }\n\t};\n\n/* SCEP requires that its CA certificates be usable for decryption of request\n   messages and signing of response messages.  Some SCEP CAs don't have the\n   appropriate keyUsage bits for this set, in which case we have to process \n   the certificates in oblivious mode in order to use them */\n\n#if ( SCEP_NO == 6 ) || ( SCEP_NO == 7 ) || ( SCEP_NO == 8 ) || \\\n\t( SCEP_NO == 9 )\n  #define SCEP_BROKEN_CA_CERT\n#endif /* Insta-Certifier, Windows Server */\n\n/* Certificate request data for the certificate from the SCEP server.  Note \n   that we have to set the CN to the PKI user CN, for CMP ir's we just omit \n   the DN entirely and have the server provide it for us but since SCEP uses \n   PKCS #10 requests we need to provide a DN, and since we provide it it has \n   to match the PKI user DN */\n\nstatic const CERT_DATA scepRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test SCEP PKI user\" ) },\n\n\t/* Subject altName */\n\t{ CRYPT_CERTINFO_RFC822NAME, IS_STRING, 0, TEXT( \"dave@wetas-r-us.com\" ) },\n\t{ CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( \"http://www.wetas-r-us.com\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/* PKI user data to authorise the issuing of the various certs */\n\nstatic const CERT_DATA scepPkiUserData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( \"Procurement\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"Test SCEP PKI user\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, IS_VOID }\n\t};\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Add a PKI user to the certificate store */\n\nstatic int addPKIUser( const CRYPT_KEYSET cryptCertStore,\n\t\t\t\t\t   const CERT_DATA *pkiUserData,\n\t\t\t\t\t   const BOOLEAN isSCEP, \n\t\t\t\t\t   const BOOLEAN testErrorChecking )\n\t{\n\tCRYPT_CERTIFICATE cryptPKIUser;\n\tCRYPT_SESSION cryptSession;\n\tC_CHR userID[ CRYPT_MAX_TEXTSIZE + 1 ], issuePW[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint length, status;\n\n\tputs( \"-- Adding new PKI user information --\" );\n\n\t/* Create the PKI user object and add the user's identification\n\t   information */\n\tstatus = cryptCreateCert( &cryptPKIUser, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_PKIUSER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !addCertFields( cryptPKIUser, pkiUserData, __LINE__ ) )\n\t\treturn( FALSE );\n#ifdef TEST_CUSTOM_ATTRIBUTE\n\tif( isSCEP && pkiUserData == scepPkiUserData )\n\t\t{\n\t\tconst char *extensionData = \"\\x0C\\x04Test\";\n\n\t\tstatus = cryptAddCertExtension( cryptPKIUser, \"1.2.3.4.5\", FALSE, \n\t\t\t\t\t\t\t\t\t\textensionData, 6 );\n\t\t}\n#endif /* TEST_CUSTOM_ATTRIBUTE */\n\n\t/* Add the user info to the certificate store */\n\tstatus = cryptCAAddItem( cryptCertStore, cryptPKIUser );\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tC_CHR userIdentifier[ CRYPT_MAX_TEXTSIZE + 1 ];\n\n\t\t/* Get the name of the duplicate user.  Since this may be just a\n\t\t   template we fall back to higher-level DN components if there's\n\t\t   no CN present */\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_COMMONNAME,\n\t\t\t\t\t\t\t\t\t\t  userIdentifier, &length );\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONALUNITNAME,\n\t\t\t\t\t\t\t\t\t\t\t  userIdentifier, &length );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_ORGANISATIONNAME,\n\t\t\t\t\t\t\t\t\t\t\t  userIdentifier, &length );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptPKIUser, \"cryptGetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tuserIdentifier[ length ] = TEXT( '\\0' );\n\n\t\t/* The PKI user info was already present, for SCEP this isn't a\n\t\t   problem since we can just re-use the existing info, but for CMP\n\t\t   we can only authorise a single certificate issue per user so we \n\t\t   have to delete the existing user info and try again */\n\t\tif( isSCEP )\n\t\t\t{\n\t\t\t/* The PKI user info is already present from a previous run, get\n\t\t\t   the existing info */\n\t\t\tputs( \"PKI user information is already present from a previous \"\n\t\t\t\t  \"run, reusing existing\\n  PKI user data...\" );\n\t\t\tcryptDestroyCert( cryptPKIUser );\n\t\t\tstatus = cryptCAGetItem( cryptCertStore, &cryptPKIUser,\n\t\t\t\t\t\t\t\t\t CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\t userIdentifier );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tputs( \"PKI user information is already present from a previous \"\n\t\t\t\t  \"run, deleting existing\\n  PKI user data...\" );\n\t\t\tstatus = cryptCADeleteItem( cryptCertStore, CRYPT_CERTTYPE_PKIUSER,\n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, userIdentifier );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( extErrorExit( cryptCertStore, \"cryptCADeleteItem()\",\n\t\t\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t\t\t}\n\t\t\tstatus = cryptCAAddItem( cryptCertStore, cryptPKIUser );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptCertStore, \"cryptCAAdd/GetItem()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\n\t/* Display the information for the new user */\n\tif( !printCertInfo( cryptPKIUser ) )\n\t\treturn( FALSE );\n\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ID,\n\t\t\t\t\t\t\t\t\t  userID, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tuserID[ length ] = '\\0';\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\n\t\t\t\t\t\t\t\t\tissuePW, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tlength /= sizeof( wchar_t );\n#endif /* UNICODE_STRINGS */\n\t\tissuePW[ length ] = '\\0';\n\t\t}\n\telse\n\t\t{\n\t\treturn( attrErrorExit( cryptPKIUser, \"cryptGetAttribute()\", status,\n\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t}\n\tputs( \"-- New PKI user information ends --\\n\" );\n\n\t/* If we're not testing the error-checking capability of the user\n\t   identifiers, we're done */\n\tif( !testErrorChecking )\n\t\t{\n\t\tcryptDestroyCert( cryptPKIUser );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Make sure that the error-checking in the user information works via a\n\t   dummy CMP client session.  We have to check both passwords to reduce \n\t   false positives since it's just a simple integrity check meant to \n\t   catch typing errors rather than a cryptographically strong check */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_SESSION_CMP );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( userID[ 2 ] >= TEXT( 'A' ) && userID[ 2 ] < TEXT( 'Z' ) )\n\t\tuserID[ 2 ]++;\n\telse\n\t\tuserID[ 2 ] = TEXT( 'A' );\n\tif( issuePW[ 8 ] >= TEXT( 'A' ) && issuePW[ 8 ] < TEXT( 'Z' ) )\n\t\tissuePW[ 8 ]++;\n\telse\n\t\tissuePW[ 8 ] = TEXT( 'A' );\n\tstatus = cryptSetAttributeString( cryptSession, CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t  userID, paramStrlen( userID ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  issuePW, paramStrlen( issuePW ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tputs( \"Integrity check of user ID and password failed to catch \"\n\t\t\t  \"errors in the data.\\n(This check isn't foolproof and is \"\n\t\t\t  \"intended only to catch typing errors when\\nentering the \"\n\t\t\t  \"data.  Try running the test again to see if the problem \"\n\t\t\t  \"still\\noccurs).\" );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptPKIUser );\n\treturn( TRUE );\n\t}\n\n/* Get information on a PKI user */\n\nint pkiGetUserInfo( C_STR userID, C_STR issuePW, C_STR revPW, \n\t\t\t\t\tconst C_STR userName )\n\t{\n\tCRYPT_KEYSET cryptCertStore;\n\tCRYPT_CERTIFICATE cryptPKIUser;\n\tint length, status;\n\n\t/* cryptlib implements per-user (rather than shared interop) IDs and\n\t   passwords so we need to read the user ID and password information\n\t   before we can perform any operations.  First we get the PkiUser\n\t   object */\n\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access isn't available, return a special error\n\t\t   code to indicate that the test wasn't performed, but that this\n\t\t   isn't a reason to abort processing */\n\t\tputs( \"No certificate store available, aborting CMP/SCEP test.\\n\" );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCAGetItem( cryptCertStore, &cryptPKIUser,\n\t\t\t\t\t\t\t CRYPT_CERTTYPE_PKIUSER, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t userName );\n\tcryptKeysetClose( cryptCertStore );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Only report error info if it's not a basic presence check */\n\t\tif( userID != NULL )\n\t\t\textErrorExit( cryptCertStore, \"cryptCAGetItem()\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's a presence check only, we're done */\n\tif( userID == NULL )\n\t\t{\n\t\tcryptDestroyCert( cryptPKIUser );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Then we extract the information from the PkiUser object */\n\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ID,\n\t\t\t\t\t\t\t\t\t  userID, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tuserID[ length ] = '\\0';\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\n\t\t\t\t\t\t\t\t\tissuePW, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tissuePW[ length ] = '\\0';\n\tif( cryptStatusOK( status ) && revPW != NULL )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptPKIUser,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_PKIUSER_REVPASSWORD,\n\t\t\t\t\t\t\t\t\trevPW, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\trevPW[ length ] = '\\0';\n\t\t}\n\tcryptDestroyCert( cryptPKIUser );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tattrErrorExit( cryptPKIUser, \"cryptGetAttribute()\", status,\n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* We've got what we need, tell the user what we're doing */\n\tprintf( \"Using user name %s, password %s.\\n\", userID, issuePW );\n\treturn( TRUE );\n\t}\n\n/* Set up objects and information needed by a server-side PKI session */\n\nint pkiServerInit( CRYPT_CONTEXT *cryptPrivateKey, \n\t\t\t\t   CRYPT_KEYSET *cryptCertStore, const C_STR keyFileName,\n\t\t\t\t   const C_STR keyLabel, const CERT_DATA *pkiUserData,\n\t\t\t\t   const CERT_DATA *pkiUserAltData, \n\t\t\t\t   const CERT_DATA *pkiUserCAData, \n\t\t\t\t   const CERT_DATA *pkiUserRAData, \n\t\t\t\t   const char *protocolName )\n\t{\n\tconst BOOLEAN isSCEP = !strcmp( protocolName, \"SCEP\" ) ? TRUE : FALSE;\n\tint status;\n\n\t/* Get the certificate store to use with the session.  Before we use the \n\t   store we perform a cleanup action to remove any leftover requests from\n\t   previous runs */\n\tstatus = cryptKeysetOpen( cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access isn't available, return a special error\n\t\t   code to indicate that the test wasn't performed, but that this\n\t\t   isn't a reason to abort processing */\n\t\tprintf( \"SVR: No certificate store available, aborting %s server \"\n\t\t\t\t\"test.\\n\\n\", protocolName );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tstatus = cryptKeysetOpen( cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_NONE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptKeysetOpen() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptCACertManagement( NULL, CRYPT_CERTACTION_CLEANUP, \n\t\t\t\t\t\t\t\t\t*cryptCertStore, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: CA certificate store cleanup failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the EE and CA PKI users */\n\tputs( \"Creating PKI users...\" );\n\tif( !addPKIUser( *cryptCertStore, pkiUserData, isSCEP, !isSCEP ) )\n\t\treturn( FALSE );\n\tif( pkiUserAltData != NULL && \\\n\t\t!addPKIUser( *cryptCertStore, pkiUserAltData, isSCEP, FALSE ) )\n\t\treturn( FALSE );\n\tif( pkiUserCAData != NULL && \\\n\t\t!addPKIUser( *cryptCertStore, pkiUserCAData, isSCEP, FALSE ) )\n\t\treturn( FALSE );\n\tif( pkiUserRAData != NULL && \\\n\t\t!addPKIUser( *cryptCertStore, pkiUserRAData, isSCEP, FALSE ) )\n\t\treturn( FALSE );\n\n\t/* Get the CA's private key */\n\tstatus = getPrivateKey( cryptPrivateKey, keyFileName,\n\t\t\t\t\t\t\tkeyLabel, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: CA private key read failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSCEP Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get an SCEP CA certificate */\n\nstatic int getScepCACert( const C_STR caCertUrl,\n\t\t\t\t\t\t  CRYPT_CERTIFICATE *cryptCACert )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n\t\t\t\t\t\t\t  caCertUrl, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetPublicKey( cryptKeyset, cryptCACert, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t\tTEXT( \"[None]\" ) );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\",\n\t\t\t\t\t\t\t  status, __LINE__ ) );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Perform a SCEP test */\n\nstatic int connectSCEP( const BOOLEAN localSession,\n\t\t\t\t\t\tconst SCEP_TEST_TYPE testType,\n\t\t\t\t\t\tconst CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CERTIFICATE cryptRequest DUMMY_INIT, cryptResponse, cryptCACert;\n\tCRYPT_CONTEXT cryptContext, cryptRenewalKey;\n#if ( SCEP_NO == 1 )\n\tC_CHR userID[ 64 ], password[ 64 ];\n\tconst C_STR userPtr;\n\tconst C_STR passwordPtr;\n\tBYTE caKeyFingerprint[ 20 ];\n\tint caKeyFingerprintSize = 0;\n#else\n\tconst C_STR userPtr = scepInfo[ SCEP_NO ].user;\n\tconst C_STR passwordPtr = scepInfo[ SCEP_NO ].password;\n#endif /* cryptlib SCEP server */\n\tconst BOOLEAN isErrorTest = ( testType >= SCEP_TEST_CORRUPT_TRANSACTIONID && \\\n\t\t\t\t\t\t\t\t  testType < SCEP_TEST_LAST ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tBOOLEAN addCACert = ( testType == SCEP_TEST_CACERT ) ? FALSE : TRUE;\n#ifdef SCEP_BROKEN_CA_CERT\n\tint complianceValue;\n#endif /* SCEP servers with broken CA certificates */\n\tint retryCount = 0, status;\n\n\tprintf( \"Testing %s %sSCEP session\", scepInfo[ SCEP_NO ].name,\n\t\t\t( testType == SCEP_TEST_RENEW ) ? \"renewed-certificate \" : \"\" );\n\tif( addCACert )\n\t\t{\n\t\tprintf( \" with CA certificate read\" );\n\t\tif( cryptAlgo != CRYPT_ALGO_RSA )\n\t\t\tprintf( \"\\n  and alternative algorithm\" );\n\t\t}\n\tprintf( \"...\\n\" );\n\n\t/* Wait for the server to finish initialising */\n\tif( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n#if ( SCEP_NO == 1 )\n\t/* If we're doing a loopback test, make sure that the required user info\n\t   is present.  If it isn't, the CA auditing will detect a request from\n\t   a nonexistant user and refuse to issue a certificate */\n\tif( !pkiGetUserInfo( NULL, NULL, NULL, TEXT( \"Test SCEP PKI user\" ) ) )\n\t\t{\n\t\tputs( \"CA certificate store doesn't contain the PKI user \"\n\t\t\t  \"information needed to\\nauthenticate certificate issue \"\n\t\t\t  \"operations, can't perform SCEP test.\\n\" );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n#endif /* cryptlib SCEP server */\n\n#ifdef SCEP_BROKEN_CA_CERT\n\t/* Some SCEP server's CA certificates are broken so we have to turn \n\t   down the compliance level to allow them to be used */\n\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   &complianceValue );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n#endif /* SCEP servers with broken CA certificates */\n\n\t/* Get the issuing CA's certificate if required */\n\tif( addCACert )\n\t\t{\n\t\tif( scepInfo[ SCEP_NO ].caCertUrl != NULL )\n\t\t\t{\n\t\t\tif( !strcmp( scepInfo[ SCEP_NO ].caCertUrl, \"default\" ) )\n\t\t\t\taddCACert = FALSE;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !getScepCACert( scepInfo[ SCEP_NO ].caCertUrl, \n\t\t\t\t\t\t\t\t\t&cryptCACert ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = importCertFromTemplate( &cryptCACert, \n\t\t\t\t\t\t\t\t\t\t\t SCEP_CA_FILE_TEMPLATE, SCEP_NO );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Couldn't get SCEP CA certificate, status = %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* cryptlib implements per-user (rather than shared interop) IDs and\n\t   passwords so we need to read the user ID and password information\n\t   before we can perform any operations */\n#if ( SCEP_NO == 1 )\n\tstatus = pkiGetUserInfo( userID, password, NULL,\n\t\t\t\t\t\t\t TEXT( \"Test SCEP PKI user\" ) );\n\tif( !status || status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tif( addCACert )\n\t\t\tcryptDestroyCert( cryptCACert );\n\n\t\t/* If certificate store operations aren't available, exit but \n\t\t   continue with other tests, otherwise abort the tests */\n\t\treturn( ( status == CRYPT_ERROR_NOTAVAIL ) ? TRUE : FALSE );\n\t\t}\n\tuserPtr = userID;\n\tpasswordPtr = password;\n#endif /* cryptlib SCEP server */\n\n\t/* Get the certificate used to authenticate the renewal if required */\n\tif( testType == SCEP_TEST_RENEW ) \n\t\t{\n\t\tstatus = getPrivateKey( &cryptRenewalKey, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't get SCEP-issued certificate for renewal, \"\n\t\t\t\t\t\"status = %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n#if ( SCEP_NO == 1 )\n\t/* Get the CA certificate fingerprint */\n\tif( !addCACert )\n\t\t{\n\t\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\n\t\tfilenameFromTemplate( filenameBuffer, SCEPCA_PRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t\t  ( cryptAlgo == CRYPT_ALGO_RSA ) ? 1 : 2 );\n\t\tstatus = getPublicKey( &cryptCACert, filenameBuffer,\n\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't get SCEP CA certificate, status = %d, \"\n\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tstatus = cryptGetAttributeString( cryptCACert, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t\t  caKeyFingerprint, \n\t\t\t\t\t\t\t\t\t  &caKeyFingerprintSize );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( !addCACert )\n\t\t\tcryptDestroyCert( cryptCACert );\n\t\tprintf( \"Couldn't get SCEP CA certificate fingerprint, status = %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !addCACert )\n\t\tcryptDestroyCert( cryptCACert );\n#endif /* cryptlib SCEP server */\n\n\t/* Create the SCEP session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SCEP );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SCEP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Make sure that the SCEP client's checking for invalid transactionIDs\n\t   works (this is an obscure problem caused by the SCEP protocol, see \n\t   the SCEP client code comments for more information) */\n\tif( testType == SCEP_TEST_NORMAL )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t  TEXT( \"abc@def\" ), \n\t\t\t\t\t\t\t\t\t\t  paramStrlen( TEXT( \"abc@def\" ) ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tprintf( \"Addition of invalid SCEP user information wasn't detected, \"\n\t\t\t\t\t\"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Set up the user and server information */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t\t( testType == SCEP_TEST_RENEW ) ? \\\n\t\t\t\t\t\t\t\t  CRYPT_REQUESTTYPE_CERTIFICATE : \\\n\t\t\t\t\t\t\t\t  CRYPT_REQUESTTYPE_INITIALISATION );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t  userPtr, paramStrlen( userPtr ) );\n\t\t}\n\tif( cryptStatusOK( status ) && testType != SCEP_TEST_RENEW )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  passwordPtr, paramStrlen( passwordPtr ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\tscepInfo[ SCEP_NO ].url,\n\t\t\t\t\t\t\t\t\tparamStrlen( scepInfo[ SCEP_NO ].url ) );\n\t\t}\n\tif( addCACert )\n\t\t{\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t\t\t\t\t\tcryptCACert );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCACert );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Addition of SCEP user/server information failed with error \"\n\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the PKCS #10 request.  For standard SCEP this is unsigned \n\t   since we need to add the SCEP challengePassword to it before we send \n\t   it to the server, however for a SCEP renewal it's signed since \n\t   there's no challengePassword and the request is authenticated by being\n\t   signed with the previously-issued SCEP certificate */\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t paramStrlen( USER_PRIVKEY_LABEL ) );\n\tstatus = cryptGenerateKey( cryptContext );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptCreateCert( &cryptRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTREQUEST );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptRequest,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, \n\t\t\t\t\t\t\t\t\tcryptContext );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptRequest, scepRequestData, __LINE__ ) )\n\t\tstatus = CRYPT_ERROR_FAILED;\n\tif( cryptStatusOK( status ) && ( testType == SCEP_TEST_CUSTOMEXT ) )\n\t\t{\n\t\tconst char *extensionData = \"\\x0C\\x04Test\";\n\n\t\tstatus = cryptAddCertExtension( cryptRequest, \"1.2.3.4.5\", FALSE, \n\t\t\t\t\t\t\t\t\t\textensionData, 6 );\n\t\t}\n\tif( cryptStatusOK( status ) && ( testType == SCEP_TEST_RENEW ) )\n\t\tstatus = cryptSignCert( cryptRequest, cryptContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Creation of PKCS #10 request failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set up the private key and request */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t( testType == SCEP_TEST_RENEW ) ? \\\n\t\t\t\t\t\t\t\t  cryptRenewalKey : cryptContext );\n\tif( testType != SCEP_TEST_NORMAL )\n\t\tcryptDestroyContext( cryptContext );\n\tif( testType == SCEP_TEST_RENEW )\n\t\tcryptDestroyContext( cryptRenewalKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t\t\tcryptRequest );\n\t\t}\n\tcryptDestroyCert( cryptRequest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we've explicitly fetched the issuing CA's certificate via an HTTP\n\t   request then the server session has already been run, so we need to\n\t   wait for it to recycle before we continue */\n\tif( localSession && addCACert && \\\n\t\tscepInfo[ SCEP_NO ].caCertUrl != NULL && \\\n\t\twaitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\t/* If we're testing fault handling, inject the appropriate fault type */\n\tif( isErrorTest )\n\t\t{\n\t\tcryptSetFaultType( ( testType == SCEP_TEST_CORRUPT_TRANSACTIONID ) ? \\\n\t\t\t\t\t\t\t FAULT_CORRUPT_ID : \\\n\t\t\t\t\t\t   ( testType == SCEP_TEST_CORRUPT_TRANSIDVALUE ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_SCEP_CORRUPT_TRANSIDVALUE : \\\n\t\t\t\t\t\t   ( testType == SCEP_TEST_CORRUPT_MESSAGETYPE ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_SCEP_CORRUPT_MESSAGETYPE : \\\n\t\t\t\t\t\t   ( testType == SCEP_TEST_CORRUPT_NONCE ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_CORRUPT_NONCE : \\\n\t\t\t\t\t\t   ( testType == SCEP_TEST_CORRUPT_AUTHENTICATOR ) ? \\\n\t\t\t\t\t\t\t FAULT_CORRUPT_AUTHENTICATOR : \\\n\t\t\t\t\t\t   \t FAULT_NONE );\n\t\t}\n#endif /* CONFIG_FAULTS && Debug */\n\n\t/* Activate the session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\twhile( status == CRYPT_ENVELOPE_RESOURCE && retryCount < 5 )\n\t\t{\n\t\t/* The server has indicated that the certificate-issue operation is \n\t\t   pending, try again in case it works this time */\n\t\tprintExtError( cryptSession, \"Attempt to activate SCEP client \"\n\t\t\t\t\t   \"session\", status, __LINE__ );\n\t\tputs( \"  (Retrying operation after 10 seconds in case certificate \"\n\t\t\t  \"issue is now approved...)\" );\n\t\tdelayThread( 10 );\n\t\tprintf( \"Retrying, attempt #%d.\\n\", ++retryCount );\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, \n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"Attempt to activate SCEP client \"\n\t\t\t\t\t   \"session\", status, __LINE__ );\n\t\tif( isErrorTest )\n\t\t\t{\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t  \"response is correct).\\n\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tif( isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tfputs( \"  (Server could be down, faking it and \"\n\t\t\t\t   \"continuing...)\\n\", outputStream );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t{\n\t\t\tputs( \"Status is still marked as pending, the server may \"\n\t\t\t\t  \"require manual approval\\n  of the certificate-issue \"\n\t\t\t\t  \"process.\\n\" );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\tif( isErrorTest )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\tputs( \"  (This test should have led to a failure but \"\n\t\t\t  \"didn't, test has failed).\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\n#ifdef SCEP_BROKEN_CA_CERT\n\t/* Restore normal certificate checking */\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   complianceValue );\n#endif /* SCEP servers with broken CA certificates */\n\n\t/* Print the session security information */\n\tprintFingerprint( cryptSession, FALSE );\n\n\t/* Obtain the response information, the newly-issued certificate and the \n\t   CA certificate if it wasn't added explicitly but fetched as part of\n\t   the SCEP protocol run */\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t&cryptResponse );\n\tif( cryptStatusOK( status ) && testType == SCEP_TEST_NORMAL )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptResponseCopy;\n\n\t\t/* Try and read back a second copy of the same object.  This tests \n\t\t   an internal processing condition in which the object being read \n\t\t   back needs to be made external the first time but not the \n\t\t   second */\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptResponseCopy );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tcryptDestroyCert( cryptResponseCopy );\n\t\t}\n\tif( cryptStatusOK( status ) && !addCACert )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CACERTIFICATE,\n\t\t\t\t\t\t\t\t\t&cryptCACert );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptGetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#if ( SCEP_NO != 1 )\n\tputs( \"Returned certificate details are:\" );\n\tprintCertInfo( cryptResponse );\n\tif( !addCACert )\n\t\t{\n\t\tputs( \"Returned CA certificate details are:\" );\n\t\tprintCertInfo( cryptCACert );\n\t\t}\n#endif /* Keep the cryptlib results on one screen */\n\n\t/* If this is the initial SCEP test, save the key and certificate so \n\t   that we can use it later in the SCEP renewal test */\n\tif( testType == SCEP_TEST_NORMAL )\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptAddPrivateKey( cryptKeyset, cryptContext,\n\t\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\tcryptDestroyContext( cryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't save SCEP certificate to file for later use, \"\n\t\t\t\t\t\"error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn(\tFALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptResponse );\n\tif( !addCACert )\n\t\tcryptDestroyCert( cryptCACert );\n\tputs( \"SCEP client session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionSCEP( void )\n\t{\n\treturn( connectSCEP( FALSE, SCEP_TEST_NORMAL, CRYPT_ALGO_RSA ) );\n\t}\n\nint testSessionSCEPCACert( void )\n\t{\n\treturn( connectSCEP( FALSE, SCEP_TEST_CACERT, CRYPT_ALGO_RSA ) );\n\t}\n\nenum { MUTEX_NONE, MUTEX_ACQUIRE, MUTEX_ACQUIRE_REACQUIRE };\n\nstatic int scepServer( const int mutexBehaviour,\n\t\t\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT cryptCAKey;\n\tCRYPT_KEYSET cryptCertStore;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint status;\n\n\t/* Acquire the init mutex */\n\tif( mutexBehaviour == MUTEX_ACQUIRE || \\\n\t\tmutexBehaviour == MUTEX_ACQUIRE_REACQUIRE )\n\t\tacquireMutex();\n\n\tprintf( \"SVR: Testing SCEP server session%s...\\n\",\n\t\t\t( mutexBehaviour == MUTEX_ACQUIRE_REACQUIRE ) ? \\\n\t\t\t\t\" (GetCACert portion)\" : \\\n\t\t\t( mutexBehaviour == MUTEX_NONE ) ? \\\n\t\t\t\t\" following GetCACert\" : \"\" );\n\n\t/* Perform a test create of a SCEP server session to verify that we can\n\t   do this test */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SCEP_SERVER );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SCEP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptCreateSession() failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\n\t/* Set up the server-side objects */\n\tfilenameFromTemplate( filenameBuffer, SCEPCA_PRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t  ( cryptAlgo == CRYPT_ALGO_RSA ) ? 1 : 2 );\n\tif( !pkiServerInit( &cryptCAKey, &cryptCertStore, filenameBuffer,\n\t\t\t\t\t\tUSER_PRIVKEY_LABEL, scepPkiUserData, NULL, NULL, \n\t\t\t\t\t\tNULL, \"SCEP\" ) )\n\t\treturn( FALSE );\n\n\t/* Create the SCEP session and add the CA key and certificate store */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SCEP_SERVER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptCreateSession() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, cryptCAKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, cryptCertStore );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Activate the session */\n\tstatus = activatePersistentServerSession( cryptSession, FALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\tcryptKeysetClose( cryptCertStore );\n\t\tcryptDestroyContext( cryptCAKey );\n\t\treturn( extErrorExit( cryptSession, \"SVR: Attempt to activate SCEP \"\n\t\t\t\t\t\t\t  \"server session\", status, __LINE__ ) );\n\t\t}\n\n\t/* If we're running a second server session, reacquire the mutex for\n\t   the client to wait on */\n\tif( mutexBehaviour == MUTEX_ACQUIRE_REACQUIRE )\n\t\tacquireMutex();\n\n\t/* Clean up */\n\tcryptDestroySession( cryptSession );\n\tcryptKeysetClose( cryptCertStore );\n\tcryptDestroyContext( cryptCAKey );\n\n\tif( mutexBehaviour == MUTEX_ACQUIRE_REACQUIRE )\n\t\tputs( \"SVR: SCEP session (GetCACert portion) succeeded.\" );\n\telse\n\t\tputs( \"SVR: SCEP session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionSCEPServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = scepServer( MUTEX_ACQUIRE, CRYPT_ALGO_RSA );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall scepServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n#if 0\n\t/* If we do an explicit GetCACert via an HTTP keyset before the main \n\t   SCEP session then we have to run the server twice, however this leads \n\t   to the problems covered in the comment for the first entry in \n\t   scepInfo[] above */\n\tscepServer( MUTEX_ACQUIRE_REACQUIRE, argValue );\n\tscepServer( MUTEX_NONE, argValue );\n#else\n\tscepServer( MUTEX_ACQUIRE, argValue );\n#endif /* 0 */\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nstatic int scepClientServer( const SCEP_TEST_TYPE testType,\n\t\t\t\t\t\t\t const CRYPT_ALGO_TYPE cryptAlgo )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = cryptAlgo, status;\n\n#if ( SCEP_NO != 1 )\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local SCEP session test only works with SCEP_NO == 1.\" );\n\treturn( FALSE );\n#endif /* cryptlib CA */\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,\n\t\t\t\t\t\t\t\t\t\t &arg, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSCEP( TRUE, testType, cryptAlgo );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionSCEPClientServer( void )\n\t{\n\treturn( scepClientServer( SCEP_TEST_NORMAL, CRYPT_ALGO_RSA ) );\n\t}\n\nint testSessionSCEPAltAlgoClientServer( void )\n\t{\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"ECC algorithm support appears to be disabled, skipping \"\n\t\t\t   \"SCEP processing of\\nECDSA certificates.\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( scepClientServer( SCEP_TEST_NORMAL, CRYPT_ALGO_ECDSA ) );\n\t}\n\nint testSessionSCEPCustomExtClientServer( void )\n\t{\n\tint oldValue, status;\n\n\t/* Since we're creating a certificate with custom attributes, we have to \n\t   enable the setting of unrecognised attribute types around the cert-\n\t   issue operation */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \n\t\t\t\t\t\t\t\t&oldValue );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\tCRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't enable use of custom attributes for SCEP test.\" );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = scepClientServer( SCEP_TEST_CUSTOMEXT, CRYPT_ALGO_RSA );\n\tcryptSetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t   CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, oldValue );\n\n\treturn( status );\n\t}\n\nint testSessionSCEPSHA2ClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tconst int arg = CRYPT_ALGO_RSA;\n\tint value, status;\n\n#if ( SCEP_NO != 1 )\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local SCEP session test only works with SCEP_NO == 1.\" );\n\treturn( FALSE );\n#endif /* cryptlib CA */\n\n\t/* Switch the hash algorithm to SHA-2 */\n\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, &value );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH,\n\t\t\t\t\t   CRYPT_ALGO_SHA2 );\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,\n\t\t\t\t\t\t\t\t\t\t ( void * ) &arg, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSCEP( TRUE, SCEP_TEST_NORMAL, CRYPT_ALGO_RSA );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_ENCR_HASH, value );\n\n\treturn( status );\n\t}\n\nint testSessionSCEPCACertClientServer( void )\n\t{\n\tHANDLE hThread;\n\tconst int arg = CRYPT_ALGO_RSA;\n\tunsigned threadID;\n\tint status;\n\n#if ( SCEP_NO != 1 )\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local SCEP session test only works with SCEP_NO == 1.\" );\n\treturn( FALSE );\n#endif /* cryptlib CA */\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,\n\t\t\t\t\t\t\t\t\t\t ( void * ) &arg, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSCEP( TRUE, SCEP_TEST_CACERT, CRYPT_ALGO_RSA );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionSCEPRenewClientServer( void )\n\t{\n\tHANDLE hThread;\n\tconst int arg = CRYPT_ALGO_RSA;\n\tunsigned threadID;\n\tint status;\n\n#if ( SCEP_NO != 1 )\n\t/* Because the code has to handle so many CA-specific peculiarities, we\n\t   can only perform this test when the CA being used is the cryptlib\n\t   CA */\n\tputs( \"Error: The local SCEP session test only works with SCEP_NO == 1.\" );\n\treturn( FALSE );\n#endif /* cryptlib CA */\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, scepServerThread,\n\t\t\t\t\t\t\t\t\t\t ( void * ) &arg, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSCEP( TRUE, SCEP_TEST_RENEW, CRYPT_ALGO_RSA );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionSCEPClientServerDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !scepClientServer( SCEP_TEST_CORRUPT_TRANSACTIONID, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of transaction ID */\n\tif( !scepClientServer( SCEP_TEST_CORRUPT_TRANSIDVALUE, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of trans.ID data */\n\tif( !scepClientServer( SCEP_TEST_CORRUPT_MESSAGETYPE, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of message type */\n\tif( !scepClientServer( SCEP_TEST_CORRUPT_NONCE, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of sender/recipNonce */\n\tif( !scepClientServer( SCEP_TEST_CORRUPT_AUTHENTICATOR, CRYPT_ALGO_RSA ) )\n\t\treturn( FALSE );\t/* Detect corruption of password */\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n#endif /* WINDOWS_THREADS */\n\n#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */\n"
  },
  {
    "path": "deps/cl345/test/sreqresp.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\tcryptlib Request/Response Session Test Routines\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* Prototypes for functions in certs.c */\n\nint initRTCS( CRYPT_CERTIFICATE *cryptRTCSRequest, \n\t\t\t  const CRYPT_CERTIFICATE cryptCertificateTemplate,\n\t\t\t  const int number, const BOOLEAN multipleCerts );\nint initOCSP( CRYPT_CERTIFICATE *cryptOCSPRequest, \n\t\t\t  CRYPT_CERTIFICATE *cert1, CRYPT_CERTIFICATE *cert2,\n\t\t\t  const int number, const BOOLEAN ocspv2, \n\t\t\t  const BOOLEAN revokedCert, const BOOLEAN multipleCerts,\n\t\t\t  const CRYPT_SIGNATURELEVEL_TYPE sigLevel,\n\t\t\t  const CRYPT_CONTEXT privKeyContext );\n\n#if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tHTTP Certstore Routines Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* This isn't really a proper session but just an HTTP certificate store \n   interface, but the semantics for the server side fit the session \n   interface better than the keyset interface */\n\nstatic int connectCertstoreServer( void )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_KEYSET cryptCertStore;\n\tint connectionActive, status;\n\n\tputs( \"Testing HTTP certstore server session...\" );\n\n\t/* Create the HTTP certstore session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_CERTSTORE_SERVER );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* Certstore session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\treturn( FALSE );\n\n\t/* Add the certificate store that we'll be using to provide certs (it's\n\t   actually just the generic database keyset and not the full \n\t   certificate store, because this contains more test certs) */\n\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access isn't available, return a special\n\t\t   error code to indicate that the test wasn't performed, but\n\t\t   that this isn't a reason to abort processing */\n\t\tputs( \"SVR: No certificate store available, aborting HTTP certstore \"\n\t\t\t\t  \"responder test.\\n\" );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tconst C_STR certID = TEXT( \"dave@wetaburgers.com\" );\n\t\tCRYPT_CERTIFICATE cryptCert;\n\n\t\tstatus = cryptGetPublicKey( cryptCertStore, &cryptCert, \n\t\t\t\t\t\t\t\t\tCRYPT_KEYID_EMAIL, certID );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tputs( \"SVR: Sample certificate required for client test not \"\n\t\t\t\t  \"present in certstore.\\n\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyCert( cryptCert );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, cryptCertStore );\n\tcryptKeysetClose( cryptCertStore );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n\n\t/* Activate the server */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"SVR: Attempt to activate HTTP \"\n\t\t\t\t\t   \"certstore server session\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Check whether the session connection is still open */\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,\n\t\t\t\t\t\t\t\t&connectionActive );\n\tif( cryptStatusError( status ) || !connectionActive )\n\t\t{\n\t\tprintExtError( cryptSession, \"SVR: Persistent connection has been \"\n\t\t\t\t\t   \"closed, operation\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Activate the connection to handle two more requests */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"SVR: Attempt to perform second HTTP \"\n\t\t\t\t\t   \"certstore server transaction\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( status );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"SVR: Attempt to perform third HTTP \"\n\t\t\t\t\t   \"certstore server transaction\", status, __LINE__ );\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( status );\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tputs( \"SVR: HTTP certstore server session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nstatic int connectCertstoreClient( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tconst C_STR cert1ID = TEXT( \"dave@wetaburgers.com\" );\n\tconst C_STR cert2ID = TEXT( \"notpresent@absent.com\" );\n\tint status;\n\n\t/* Open the keyset with a check to make sure this access method exists\n\t   so we can return an appropriate error message */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n\t\t\t\t\t\t\t  TEXT( \"localhost\" ), CRYPT_KEYOPT_READONLY );\n\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t{\n\t\t/* This type of keyset access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Read a present certificate from the keyset using the ASCII email\n\t   address */\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,\n\t\t\t\t\t\t\t\tcert1ID );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tprintf( \"Successfully read certificate for '%s'.\\n\", cert1ID );\n\tcryptDestroyCert( cryptCert );\n\n\t/* Read a non-present certificate from the keyset */\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,\n\t\t\t\t\t\t\t\tcert2ID );\n\tif( status == CRYPT_ERROR_NOTFOUND )\n\t\t{\n\t\tprintf( \"Successfully processed not-present code for '%s'.\\n\",\n\t\t\t\tcert2ID );\n\t\t}\n\telse\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\n\t/* Read the certificate from the keyset using the base64-encoded certID.\n\t   Since this uses an internal identifier, we can't actually do it from\n\t   here, this requires modifying the internal keyset read code to\n\t   substitute the different identifier type.\n\t   \n\t   A second purpose for this call is to test the ability of the client\n\t   to recover from the CRYPT_ERROR_NOTFOUND in the previous call, i.e.\n\t   the error should be nonfatal with further requests possible */\n\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_EMAIL,\n\t\t\t\t\t\t\t\tcert1ID );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( extErrorExit( cryptKeyset, \"cryptGetPublicKey()\", status,\n\t\t\t\t\t\t\t  __LINE__ ) );\n\t\t}\n\tprintf( \"Successfully read certificate for '%s'.\\n\", cert1ID );\n\tcryptDestroyCert( cryptCert );\n\n\t/* Clean up */\n\tcryptKeysetClose( cryptKeyset );\n\treturn( TRUE );\n\t}\n\nint testSessionHTTPCertstoreServer( void )\n\t{\n\treturn( connectCertstoreServer() );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall certstoreServerThread( void *dummy )\n\t{\n\tconnectCertstoreServer();\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionHTTPCertstoreClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, certstoreServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectCertstoreClient();\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tRTCS Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There are various test RTCS servers running, the following remapping\n   allows us to switch between them.  Implementation peculiarities:\n\n\t#1 - cryptlib:\n\t\t\tNone */\n\n#define RTCS_SERVER_NO\t\t1\n#if RTCS_SERVER_NO == 1\n  #define RTCS_SERVER_NAME\tTEXT( \"http://localhost\" )\n#endif /* RTCS server name kludge */\n\n/* Perform an RTCS test */\n\nstatic int connectRTCS( const CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t\tconst BOOLEAN multipleCerts,\n\t\t\t\t\t\tconst BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CERTIFICATE cryptRTCSRequest;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tvoid *fileNamePtr = filenameBuffer;\n\tconst BOOLEAN isServer = ( sessionType == CRYPT_SESSION_RTCS_SERVER ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tint status;\n\n\tprintf( \"%sTesting %sRTCS session...\\n\", isServer ? \"SVR: \" : \"\",\n\t\t\tlocalSession ? \"local \" : \"\" );\n\n\t/* If we're the client, wait for the server to finish initialising */\n\tif( localSession && !isServer && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the RTCS session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* RTCS session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( isServer )\n\t\t{\n\t\tCRYPT_CONTEXT cryptPrivateKey;\n\t\tCRYPT_KEYSET cryptCertStore;\n\n\t\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Add the responder private key */\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_PRIVKEY_FILE_TEMPLATE, 1 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPrivateKey( &cryptPrivateKey, fileNamePtr, \n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, cryptPrivateKey );\n\t\t\tcryptDestroyContext( cryptPrivateKey );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\n\t\t/* Add the certificate store that we'll be using to provide \n\t\t   revocation information */\n\t\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\t{\n\t\t\t/* This type of keyset access isn't available, return a special\n\t\t\t   error code to indicate that the test wasn't performed, but\n\t\t\t   that this isn't a reason to abort processing */\n\t\t\tputs( \"SVR: No certificate store available, aborting RTCS \"\n\t\t\t\t  \"responder test.\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\t{\n\t\t\t/* The keyset is available, but it hasn't been created yet by an\n\t\t\t   earlier self-test, this isn't a reason to abort processing */\n\t\t\tputs( \"SVR: Certificate store hasn't been created yet by \"\n\t\t\t\t  \"earlier tests, aborting\\n     RTCS responder test.\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, cryptCertStore );\n\t\t\tcryptKeysetClose( cryptCertStore );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\n\t\t/* Tell the client that we're ready to go */\n\t\tif( localSession )\n\t\t\treleaseMutex();\n\t\t}\n\telse\n\t\t{\n\t\tCRYPT_KEYSET cryptKeyset;\n\t\tCRYPT_CERTIFICATE cryptCert DUMMY_INIT;\n\n\t\t/* Get the certificate whose status we're checking */\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetPublicKey( cryptKeyset, &cryptCert, \n\t\t\t\t\t\t\t\t\t\tCRYPT_KEYID_NAME, \n\t\t\t\t\t\t\t\t\t\tTEXT( \"Test user 1\" ) );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"Couldn't read certificate for RTCS status check, error \"\n\t\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\t\tputs( \"  (Has the testCertManagement() code been run?).\" );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Create the RTCS request */\n\t\tif( !initRTCS( &cryptRTCSRequest, cryptCert, localSession ? \\\n\t\t\t\t\t\t\t1 : RTCS_SERVER_NO, multipleCerts ) )\n\t\t\treturn( FALSE );\n\t\tcryptDestroyCert( cryptCert );\n\n\t\t/* Set up the server information and activate the session.  In\n\t\t   theory the RTCS request will contain all the information needed\n\t\t   for the session so there'd be nothing else to add before we\n\t\t   activate it, however many certs contain incorrect server URLs so\n\t\t   we set the server name manually if necessary, overriding the\n\t\t   value present in the RTCS request (via the certificate) */\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t\t\tcryptRTCSRequest );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptRTCSRequest );\n\t\tif( localSession && !setLocalConnect( cryptSession, 80 ) )\n\t\t\treturn( FALSE );\n#ifdef RTCS_SERVER_NAME\n\t\tif( !localSession )\n\t\t\t{\n\t\t\tprintf( \"Setting RTCS server to %s.\\n\", RTCS_SERVER_NAME );\n\t\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_NAME );\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, RTCS_SERVER_NAME,\n\t\t\t\t\t\t\t\tparamStrlen( RTCS_SERVER_NAME ) );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( attrErrorExit( cryptSession,\n\t\t\t\t\t\t\t\t\t   \"cryptSetAttributeString()\", status,\n\t\t\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t\t\t}\n\t\t\t}\n#endif /* Kludges for incorrect/missing authorityInfoAccess values */\n\n\t\t/* Wait for the server to finish initialising */\n\t\tif( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t\t{\n\t\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\t\t\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( isServer )\n\t\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t   \"SVR: Attempt to activate RTCS server session\" : \\\n\t\t\t\t\t   \"Attempt to activate RTCS client session\", status,\n\t\t\t\t\t   __LINE__ );\n\t\tif( !isServer && isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tputs( \"  (Server could be down, faking it and continuing...)\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Obtain the response information */\n\tif( !isServer )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptRTCSResponse;\n\t\t\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptRTCSResponse );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptGetAttribute() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tprintCertInfo( cryptRTCSResponse );\n\t\tcryptDestroyCert( cryptRTCSResponse );\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tputs( isServer ? \"SVR: RTCS server session succeeded.\\n\" : \\\n\t\t\t\t\t \"RTCS client session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nstatic int connectRTCSDirect( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\tprintf( \"Testing direct RTCS query...\\n\" );\n\n\t/* Get the EE certificate */\n\tstatus = importCertFromTemplate( &cryptCert, RTCS_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t RTCS_SERVER_NO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"EE cryptImportCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the RTCS session and add the server URL */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_RTCS );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* RTCS session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#ifdef RTCS_SERVER_NAME\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, RTCS_SERVER_NAME,\n\t\t\t\t\t\t\t\tparamStrlen( RTCS_SERVER_NAME ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttributeString()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n#endif /* Kludges for incorrect/missing authorityInfoAccess values */\n\n\t/* Check the certificate directly against the server */\n\tstatus = cryptCheckCert( cryptCert, cryptSession );\n\tprintf( \"Certificate status check returned %d.\\n\", status );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tcryptDestroySession( cryptSession );\n\n\tputs( \"RTCS direct query succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionRTCS( void )\n\t{\n\tif( !connectRTCS( CRYPT_SESSION_RTCS, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !connectRTCSDirect() )\n\t\treturn( FALSE );\n#if RTCS_SERVER_NO == 1\n\treturn( connectRTCS( CRYPT_SESSION_RTCS, TRUE, FALSE ) );\n#else\n\treturn( TRUE );\n#endif /* Server that has a revoked certificate */\n\t}\nint testSessionRTCSServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tacquireMutex();\n\tstatus = connectRTCS( CRYPT_SESSION_RTCS_SERVER, FALSE, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall rtcsServerThread( void *dummy )\n\t{\n\tacquireMutex();\n\tconnectRTCS( CRYPT_SESSION_RTCS_SERVER, FALSE, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionRTCSClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, rtcsServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 2000 );\n\n\t/* Connect to the local server */\n\tstatus = connectRTCS( CRYPT_SESSION_RTCS, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tOCSP Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There are various test OCSP servers running, the following remapping\n   allows us to switch between them.  Implementation peculiarities:\n\n\t#1 - cryptlib:\n\t\t\tNone\n\t#2 - iD2 aka SmartTrust\n\t\t\tAuthorityInfoAccess doesn't match the real server URL, requires\n\t\t\tthe SmartTrust server name below to override the AIA value.\n\t\t\tCurrently not active.\n\t#3 - Identrus aka Xetex:\n\t\t\tAuthorityInfoAccess doesn't match the real server URL, requires\n\t\t\tthe Xetex server name below to override the AIA value.  Currently\n\t\t\tnot active.\n\t#4 - Thawte aka Valicert\n\t\t\tNo AuthorityInfoAccess, requires the Valicert server name below\n\t\t\tto provide a server.  Since all Thawte CA certs are invalid (no\n\t\t\tkeyUsage, meaning they're non-CA certs) cryptlib will reject them\n\t\t\tfor OCSPv1 queries.\n\t#5 - Verisign\n\t\t\tNo AuthorityInfoAccess, requires the Verisign server name below\n\t\t\tto provide a server.\n\t#6 - Diginotar\n\t\t\tHave an invalid CA certificate, and (apparently) a broken OCSP\n\t\t\timplementation that gets the IDs wrong (this is par for the\n\t\t\tcourse for this particular CA).\n\t#7 - Windows Server 2008\n\t\t\tReturns a permission-denied error with the default server \n\t\t\tconfiguration.  This is because Windows Server by default doesn't \n\t\t\tallow nonces, and responds to any request containing a nonce \n\t\t\twith a permission-denied error.  Enabling nonces via Revocation \n\t\t\tConfigurations | Action | Edit Properties | Allow Nonce requests \n\t\t\tcorrects this */\n\n#define OCSP_SERVER_NO\t\t5\n#if OCSP_SERVER_NO == 2\n  #define OCSP_SERVER_NAME\tTEXT( \"http://ocsp.smarttrust.com:82/ocsp\" )\n#elif OCSP_SERVER_NO == 3\n  #define OCSP_SERVER_NAME\tTEXT( \"http://ocsp.xetex.com:8080/servlet/ocsp\" )\n#elif OCSP_SERVER_NO == 4\n  #define OCSP_SERVER_NAME\tTEXT( \"http://ocsp2.valicert.net\" )\n#elif OCSP_SERVER_NO == 5\n  #define OCSP_SERVER_NAME\tTEXT( \"http://ocsp.verisign.com/ocsp/status\" )\n#elif OCSP_SERVER_NO == 7\n\t#define OCSP_SERVER_NAME\tTEXT( \"http://142.176.86.157/ocsp\" )\n#endif /* OCSP server name kludge */\n\n/* Define the following to sign the OCSP request */\n\n/* #define OCSP_SIGN_REQUEST /**/\n\n/* Perform an OCSP test */\n\nstatic int connectOCSP( const CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t\tconst BOOLEAN revokedCert,\n\t\t\t\t\t\tconst BOOLEAN multipleCerts,\n\t\t\t\t\t\tconst BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CERTIFICATE cryptOCSPRequest, cryptCert1, cryptCert2;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tvoid *fileNamePtr = filenameBuffer;\n#if OCSP_SERVER_NO == 7\n\tint complianceValue;\n#endif /* OCSP servers that return broken resposnes */\n\tconst BOOLEAN isServer = ( sessionType == CRYPT_SESSION_OCSP_SERVER ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tint status;\n\n#ifdef OCSP_SIGN_REQUEST\n\tprintf( \"%sTesting %sOCSP session...\\n\", isServer ? \"SVR: \" : \"\",\n\t\t\tlocalSession ? \"local \" : \"\" );\n#else\n\tprintf( \"%sTesting %sOCSP session with signed request...\\n\", \n\t\t\tisServer ? \"SVR: \" : \"\", localSession ? \"local \" : \"\" );\n#endif /* OCSP_SIGN_REQUEST */\n\n\t/* If we're the client, wait for the server to finish initialising */\n\tif( localSession && !isServer && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the OCSP session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* OCSP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( isServer )\n\t\t{\n\t\tCRYPT_CONTEXT cryptPrivateKey;\n\t\tCRYPT_KEYSET cryptCertStore;\n\n\t\tif( !setLocalConnect( cryptSession, 80 ) )\n\t\t\treturn( FALSE );\n\n\t\t/* Add the responder private key */\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_PRIVKEY_FILE_TEMPLATE, 1 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPrivateKey( &cryptPrivateKey, fileNamePtr, \n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, cryptPrivateKey );\n\t\t\tcryptDestroyContext( cryptPrivateKey );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\n\t\t/* Add the certificate store that we'll be using to provide \n\t\t   revocation information */\n\t\tstatus = cryptKeysetOpen( &cryptCertStore, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\t\tif( status == CRYPT_ERROR_PARAM3 )\n\t\t\t{\n\t\t\t/* This type of keyset access isn't available, return a special\n\t\t\t   error code to indicate that the test wasn't performed, but\n\t\t\t   that this isn't a reason to abort processing */\n\t\t\tputs( \"SVR: No certificate store available, aborting OCSP \"\n\t\t\t\t  \"responder test.\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_OPEN )\n\t\t\t{\n\t\t\t/* This is the first of the loopback tests that requires the \n\t\t\t   presence of a certificate store (created by previous tests), \n\t\t\t   if we can't open it then we report the issue in a situation-\n\t\t\t   specific manner */\n\t\t\tputs( \"SVR: Can't open certificate store, have the earlier \"\n\t\t\t\t  \"tests that create this\\n     been run?\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, cryptCertStore );\n\t\t\tcryptKeysetClose( cryptCertStore );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"SVR: cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\n\t\t/* Tell the client that we're ready to go */\n\t\tif( localSession )\n\t\t\treleaseMutex();\n\t\t}\n\telse\n\t\t{\n\t\t/* Create the OCSP request */\n#ifdef OCSP_SIGN_REQUEST \n\t\tCRYPT_CONTEXT cryptPrivateKey;\n\n\t\tstatus = getPrivateKey( &cryptPrivateKey, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n#else\n\t\tconst CRYPT_CONTEXT cryptPrivateKey = CRYPT_UNUSED;\n#endif /* OCSP_SIGN_REQUEST */\n\t\tif( !initOCSP( &cryptOCSPRequest, &cryptCert1, &cryptCert2, \n\t\t\t\t\t   localSession ? 1 : OCSP_SERVER_NO, FALSE, \n\t\t\t\t\t   revokedCert, multipleCerts,\n\t\t\t\t\t   CRYPT_SIGNATURELEVEL_NONE, cryptPrivateKey ) )\n\t\t\treturn( FALSE );\n\t\tif( cryptPrivateKey != CRYPT_UNUSED )\n\t\t\tcryptDestroyContext( cryptPrivateKey );\n\n\t\t/* Set up the server information and activate the session.  In\n\t\t   theory the OCSP request will contain all the information needed\n\t\t   for the session so there'd be nothing else to add before we\n\t\t   activate it, however many certs contain incorrect server URLs so\n\t\t   we set the server name manually if necessary, overriding the\n\t\t   value present in the OCSP request (via the certificate) */\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_REQUEST,\n\t\t\t\t\t\t\t\t\tcryptOCSPRequest );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t}\n\t\tcryptDestroyCert( cryptOCSPRequest );\n\t\tif( localSession && !setLocalConnect( cryptSession, 80 ) )\n\t\t\treturn( FALSE );\n#ifdef OCSP_SERVER_NAME\n\t\tif( !localSession )\n\t\t\t{\n\t\t\tprintf( \"Setting OCSP server to %s.\\n\", OCSP_SERVER_NAME );\n\t\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_NAME );\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, OCSP_SERVER_NAME,\n\t\t\t\t\t\t\t\tparamStrlen( OCSP_SERVER_NAME ) );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( attrErrorExit( cryptSession,\n\t\t\t\t\t\t\t\t\t   \"cryptSetAttributeString()\", status,\n\t\t\t\t\t\t\t\t\t   __LINE__ ) );\n\t\t\t\t}\n\t\t\t}\n#endif /* Kludges for incorrect/missing authorityInfoAccess values */\n\t\tif( OCSP_SERVER_NO == 1 || localSession )\n\t\t\t{\n\t\t\t/* The cryptlib server doesn't handle the weird v1 certIDs */\n\t\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,\n\t\t\t\t\t\t\t\t\t\t2 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttribute()\",\n\t\t\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t\t\t}\n\t\t\t}\n#if OCSP_SERVER_NO == 7\n\t\t/* Some OCSP server's responses are broken so we have to turn down \n\t\t   the compliance level to allow them to be processed */\n\t\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   &complianceValue );\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n#endif /* OCSP servers that return broken resposnes */\n\n\t\t/* Wait for the server to finish initialising */\n\t\tif( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t\t{\n\t\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\t\t\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n#if OCSP_SERVER_NO == 7\n\tif( !isServer )\n\t\t{\n\t\t/* Restore normal certificate processing */\n\t\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t\t   complianceValue );\n\t\t}\n#endif /* OCSP servers that return broken resposnes */\n\tif( isServer )\n\t\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t   \"SVR: Attempt to activate OCSP server session\" : \\\n\t\t\t\t\t   \"Attempt to activate OCSP client session\", status,\n\t\t\t\t\t   __LINE__ );\n#if OCSP_SERVER_NO == 5\n\t\tif( status == CRYPT_ERROR_SIGNATURE )\n\t\t\t{\n\t\t\tchar errorMessage[ 512 ];\n\t\t\tint errorMessageLength;\n\n\t\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_ERRORMESSAGE,\n\t\t\t\t\t\t\t\t\t\t\t  errorMessage, &errorMessageLength );\n\t\t\tif( cryptStatusOK( status ) && errorMessageLength >= 29 && \\\n\t\t\t\t!memcmp( errorMessage, \"OCSP response doesn't contain\", 29 ) )\n\t\t\t\t{\n\t\t\t\tcryptDestroyCert( cryptCert1 );\n\t\t\t\tif( cryptCert2 != CRYPT_UNUSED )\n\t\t\t\t\tcryptDestroyCert( cryptCert2 );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\tputs( \"  (Verisign's OCSP responder sends broken responses, \"\n\t\t\t\t\t  \"continuing...)\\n\" );\n\t\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t\t}\n\t\t\t}\n#endif /* Verisign's broken OCSP responder */\n\t\tif( !isServer && isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tputs( \"  (Server could be down, faking it and continuing...)\\n\" );\n\t\t\tcryptDestroyCert( cryptCert1 );\n\t\t\tif( cryptCert2 != CRYPT_UNUSED )\n\t\t\t\tcryptDestroyCert( cryptCert2 );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Obtain the response information */\n\tif( !isServer )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptOCSPResponse;\n\t\t\n\t\t/* Display the status information in the response */\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptOCSPResponse );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptGetAttribute() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tprintCertInfo( cryptOCSPResponse );\n\n\t\t/* Check each certificate against the response.  This is somewhat\n\t\t   redundant since the status has already been displayed by the code\n\t\t   above, but it tests the check-against-response functionality */\n\t\tstatus = cryptCheckCert( cryptCert1, cryptOCSPResponse );\n\t\tprintf( \"Check of certificate status against OCSP response reports \"\n\t\t\t\t\"status %d.\\n\", status );\n\t\tif( cryptCert2 != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = cryptCheckCert( cryptCert2, cryptOCSPResponse );\n\t\t\tprintf( \"Check of second certificate status against OCSP \"\n\t\t\t\t\t\"response reports status %d.\\n\", status );\n\t\t\t}\n\n\t\tcryptDestroyCert( cryptOCSPResponse );\n\t\tcryptDestroyCert( cryptCert1 );\n\t\tif( cryptCert2 != CRYPT_UNUSED )\n\t\t\tcryptDestroyCert( cryptCert2 );\n\t\t}\n\n\t/* There are so many weird ways to delegate trust and signing authority\n\t   mentioned in the OCSP RFC without any indication of which one\n\t   implementors will follow that we can't really perform any sort of\n\t   automated check since every responder seems to interpret this\n\t   differently, and many require manual installation of responder certs\n\t   in order to function */\n#if 0\n\tstatus = cryptCheckCert( cryptOCSPResponse , CRYPT_UNUSED );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptOCSPResponse , \"cryptCheckCert()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n#endif /* 0 */\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tputs( isServer ? \"SVR: OCSP server session succeeded.\\n\" : \\\n\t\t\t\t\t \"OCSP client session succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nstatic int connectOCSPDirect( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\tprintf( \"Testing direct OCSP query...\\n\" );\n\n\t/* Get the EE certificate */\n\tstatus = importCertFromTemplate( &cryptCert, OCSP_EEOK_FILE_TEMPLATE,\n\t\t\t\t\t\t\t\t\t OCSP_SERVER_NO );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"EE cryptImportCert() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the OCSP session and add the server URL */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_OCSP );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* OCSP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n#ifdef OCSP_SERVER_NAME\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, OCSP_SERVER_NAME,\n\t\t\t\t\t\t\t\tparamStrlen( OCSP_SERVER_NAME ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\treturn( attrErrorExit( cryptSession, \"cryptSetAttributeString()\",\n\t\t\t\t\t\t\t   status, __LINE__ ) );\n\t\t}\n#endif /* Kludges for incorrect/missing authorityInfoAccess values */\n\n\t/* Check the certificate directly against the server.  This check \n\t   quantises the result into a basic pass/fail that doesn't provide as \n\t   much detail as the low-level OCSP check, so it's not unusual to get\n\t   CRYPT_ERROR_INVALID whent he low-level check returns\n\t   CRYPT_OCSPSTATUS_UNKNOWN */\n\tstatus = cryptCheckCert( cryptCert, cryptSession );\n\tprintf( \"Certificate status check returned %d.\\n\", status );\n\n\t/* Clean up */\n\tcryptDestroyCert( cryptCert );\n\tcryptDestroySession( cryptSession );\n\n\tputs( \"OCSP direct query succeeded.\\n\" );\n\treturn( TRUE );\n\t}\n\nint testSessionOCSP( void )\n\t{\n\tif( !connectOCSP( CRYPT_SESSION_OCSP, FALSE, FALSE, FALSE ) )\n\t\treturn( FALSE );\n\tif( !connectOCSPDirect() )\n\t\treturn( FALSE );\n#if OCSP_SERVER_NO == 1\n\tif( !( connectOCSP( CRYPT_SESSION_OCSP, TRUE, FALSE, FALSE ) ) )\n\t\treturn( FALSE );\n\treturn( connectOCSP( CRYPT_SESSION_OCSP, FALSE, TRUE, FALSE ) );\n#else\n\treturn( TRUE );\n#endif /* Server that has a revoked certificate */\n\t}\nint testSessionOCSPServer( void )\n\t{\n\treturn( connectOCSP( CRYPT_SESSION_OCSP_SERVER, FALSE, FALSE, FALSE ) );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall ocspServerThread( void *dummy )\n\t{\n\tacquireMutex();\n\tconnectOCSP( CRYPT_SESSION_OCSP_SERVER, FALSE, FALSE, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionOCSPClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, ocspServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectOCSP( CRYPT_SESSION_OCSP, FALSE, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionOCSPMulticertClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, ocspServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectOCSP( CRYPT_SESSION_OCSP, FALSE, TRUE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTSP Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There are various test TSP servers running, the following remapping allows\n   us to switch between them in the hope of finding at least one which is\n   actually working.  Implementation peculiarities:\n\n\t#1 - cryptlib:\n\t\t\tNone.\n\t#2 - Peter Sylvester\n\t\t\tRequires Host: header even for HTTP 1.0.\n\t#3 - Timeproof\n\t\t\tNone (currently not active).\n\t#4 - Korea Mobile Payment Service\n\t\t\tCurrently not active.\n\t#5 - IAIK Graz\n\t\t\tNever been seen active.\n\t#6 - Fst s.r.l.\n\t\t\tReturns garbled TCP-socket-protocol header.\n\t#7 - Datum\n\t\t\tAlmost never active\n\t#8 - Chinese University of Hong Kong\n\t\t\tNone, info at http://www.e-timestamping.com/status.html.\n\t#9 - SeMarket\n\t\t\tNone.\n\t#10 - Entrust\n\t\t\tNone.\n\t#11 - nCipher\n\t\t\tVery slow TSP, requires extended read timeout to get response.\n\t#12 - Comodo\n\t\t\tNone.\n\t#13 - Verisign \n\t\t\tThis \"TSA\" doesn't support TSP but uses an AuthentiCode-specific \n\t\t\tmechanism documented at \n\t\t\thttp://msdn.microsoft.com/en-us/library/windows/desktop/bb931395%28v=vs.85%29.aspx. \n\t\t\tSubmitting a TSP request returns the text message \"error \n\t\t\thandling request, status = 0x9300\" \n\t#14 - SecureSoft \n\t\t\tNone (but uses an invalid policy OID '1 2' in the response).\n\t#15 - OpenTSA \n\t\t\tCurrently not active, info at http://opentsa.org/#service \n\n   Note that this only tests the low-level raw TSP mechanism, timestamps are \n   usually used in conjunction with signed (enveloped) data, for which see \n   testSessionEnvTSP() */\n\n#define TSP_SERVER1_NAME\tTEXT( \"localhost\" )\n#define TSP_SERVER2_NAME\tTEXT( \"http://timestamping.edelweb.fr/service/tsp\" )\n#define TSP_SERVER3_NAME\tTEXT( \"tcp://test.timeproof.de\" )\n#define TSP_SERVER4_NAME\tTEXT( \"tcp://203.238.37.132:3318\" )\n#define TSP_SERVER5_NAME\tTEXT( \"tcp://neurath.iaik.at\" )\n#define TSP_SERVER6_NAME\tTEXT( \"tcp://ricerca.fst.it\" )\n#define TSP_SERVER7_NAME\tTEXT( \"tcp://tssdemo2.datum.com\" )\n#define TSP_SERVER8_NAME\tTEXT( \"tcp://ts2.itsc.cuhk.edu.hk:3318\" )\n#define TSP_SERVER9_NAME\tTEXT( \"tcp://80.81.104.150\" )\n#define TSP_SERVER10_NAME\tTEXT( \"http://vsinterop.entrust.com:7001/verificationserver/rfc3161timestamp\" )\n#define TSP_SERVER11_NAME\tTEXT( \"tcp://dse200.ncipher.com\" )\n#define TSP_SERVER12_NAME\tTEXT( \"http://timestamp.comodoca.com/rfc3161\" )\n#define TSP_SERVER13_NAME\tTEXT( \"http://timestamp.verisign.com/scripts/timstamp.dll\" )\n#define TSP_SERVER14_NAME\tTEXT( \"http://ca.signfiles.com/TSAServer.aspx\" )\n#define TSP_SERVER15_NAME\tTEXT( \"http://ns.szikszi.hu:8080/tsa\" )\n\n#define TSP_SERVER_NAME\t\tTSP_SERVER2_NAME\n#define TSP_SERVER_NO\t\t2\t/* Only used to identify slow-timeout server #11 */\n\n/* Perform a timestamping test */\n\nstatic int testTSP( const CRYPT_SESSION cryptSession,\n\t\t\t\t\tconst BOOLEAN isServer,\n\t\t\t\t\tconst BOOLEAN isRecycledConnection,\n\t\t\t\t\tconst BOOLEAN useAltHash,\n\t\t\t\t\tconst BOOLEAN localSession )\n\t{\n\tint status;\n\n\t/* If we're the client, wait for the server to finish initialising */\n\tif( localSession && !isServer && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we're the client, create a message imprint to timestamp */\n\tif( !isServer )\n\t\t{\n\t\tCRYPT_CONTEXT hashContext;\n\n\t\t/* Create the hash value to add to the TSP request */\n\t\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t useAltHash ? CRYPT_ALGO_SHA256 : \\\n\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_ALGO_SHA1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\tcryptEncrypt( hashContext, \"12345678\", 8 );\n\t\tcryptEncrypt( hashContext, \"\", 0 );\n\t\tif( isRecycledConnection )\n\t\t\t{\n\t\t\t/* If we're moving further data over an existing connection, \n\t\t\t   delete the message imprint from the previous run */\n\t\t\tstatus = cryptDeleteAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t   CRYPT_SESSINFO_TSP_MSGIMPRINT );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"cryptDeleteAttribute() failed with error code %d, \"\n\t\t\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_TSP_MSGIMPRINT,\n\t\t\t\t\t\t\t\t\thashContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptSetAttribute() failed with error code %d, line \"\n\t\t\t\t\t\"%d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tcryptDestroyContext( hashContext );\n\n\t\t/* If it's a local session, wait for the server to finish \n\t\t   initialising */\n\t\tif( localSession && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t\t{\n\t\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t\t__LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\t\t\n\t\t}\n\telse\n\t\t{\n\t\t/* We're the server, if this is the first connect tell the client \n\t\t   that we're ready to go */\n\t\tif( localSession && !isRecycledConnection )\n\t\t\treleaseMutex();\n\t\t}\n\n\t/* Activate the session and timestamp the message */\n#if TSP_SERVER_NO == 11\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT, 30 );\n#endif /* Very slow TSP */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( isServer )\n\t\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t   \"SVR: Attempt to activate TSP server session\" : \\\n\t\t\t\t\t   \"Attempt to activate TSP client session\", status,\n\t\t\t\t\t   __LINE__ );\n\t\tif( !isServer && isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tputs( \"  (Server could be down, faking it and continuing...)\\n\" );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* There's not much more we can do in the client at this point since the \n\t   TSP data is only used internally by cryptlib, OTOH if we get to here \n\t   then we've received a valid response from the TSA so all is OK */\n\tif( !isServer )\n\t\t{\n\t\tCRYPT_ENVELOPE cryptEnvelope;\n\t\tBYTE buffer[ BUFFER_SIZE ];\n\t\tint bytesCopied;\n\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptEnvelope );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"Attempt to process returned \"\n\t\t\t\t\t\t   \"timestamp\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tstatus = cryptPopData( cryptEnvelope, buffer, BUFFER_SIZE,\n\t\t\t\t\t\t\t   &bytesCopied );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptPopData() failed with error code %d, line %d.\\n\",\n\t\t\t\t\tstatus, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tprintf( \"Timestamp data size = %d bytes.\\n\", bytesCopied );\n\t\tdebugDump( \"tstinfo\", buffer, bytesCopied );\n\t\tcryptDestroyEnvelope( cryptEnvelope );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic int connectTSP( const CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t   const CRYPT_HANDLE externalCryptContext,\n\t\t\t\t\t   const BOOLEAN persistentConnection,\n\t\t\t\t\t   const BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tconst BOOLEAN isServer = ( sessionType == CRYPT_SESSION_TSP_SERVER ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tconst BOOLEAN useAltHash = ( !isServer && 0 ) ? TRUE : FALSE;\n\tint status;\n\n\tprintf( \"%sTesting %sTSP session...\\n\", isServer ? \"SVR: \" : \"\",\n\t\t\tlocalSession ? \"local \" : \"\" );\n\n\t/* Acquire the init mutex if we're the server */\n\tif( localSession && isServer && waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\",\n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\t\t\n\n\t/* Create the TSP session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* TSP session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"%scryptCreateSession() failed with error code %d, line \"\n\t\t\t\t\"%d.\\n\", isServer ? \"SVR: \" : \"\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set up the server information and activate the session.  Since this \n\t   test explicitly tests the ability to handle persistent connections, \n\t   we don't use the general-purpose request/response server wrapper, \n\t   which only uses persistent connections opportunistically */\n\tif( isServer )\n\t\t{\n\t\tCRYPT_CONTEXT privateKey = externalCryptContext;\n\n\t\tif( !setLocalConnect( cryptSession, 318 ) )\n\t\t\treturn( FALSE );\n\t\tif( externalCryptContext == CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = getPrivateKey( &privateKey, TSA_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\t\t\tif( externalCryptContext == CRYPT_UNUSED )\n\t\t\t\tcryptDestroyContext( privateKey );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( localSession )\n\t\t\t{\n\t\t\tif( !setLocalConnect( cryptSession, 318 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, TSP_SERVER_NAME,\n\t\t\t\t\t\t\tparamStrlen( TSP_SERVER_NAME ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute/cryptSetAttributeString() failed with \"\n\t\t\t\t\"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = testTSP( cryptSession, isServer, FALSE, useAltHash, localSession );\n\tif( status <= 0 )\n\t\treturn( status );\n\n\t/* Check whether the session connection is still open */\n\tif( persistentConnection )\n\t\t{\n\t\tint connectionActive;\n\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CONNECTIONACTIVE,\n\t\t\t\t\t\t\t\t\t&connectionActive );\n\t\tif( cryptStatusError( status ) || !connectionActive )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t\t   \"SVR: Persistent connection has been closed, \"\n\t\t\t\t\t\t\t\"operation\" : \\\n\t\t\t\t\t\t   \"Persistent connection has been closed, operation\",\n\t\t\t\t\t\t   status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Activate the connection to handle two more requests */\n\t\tstatus = testTSP( cryptSession, isServer, TRUE, FALSE, FALSE );\n\t\tif( status <= 0 )\n\t\t\treturn( status );\n\t\tstatus = testTSP( cryptSession, isServer, TRUE, FALSE, FALSE );\n\t\tif( status <= 0 )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\tprintf( isServer ? \"SVR: %sTSP server session succeeded.\\n\\n\" : \\\n\t\t\t\t\t   \"%sTSP client session succeeded.\\n\\n\",\n\t\t\tpersistentConnection ? \"Persistent \" : \"\" );\n\treturn( TRUE );\n\t}\n\nint testSessionTSP( void )\n\t{\n\treturn( connectTSP( CRYPT_SESSION_TSP, CRYPT_UNUSED, FALSE, FALSE ) );\n\t}\nint testSessionTSPServer( void )\n\t{\n\treturn( connectTSP( CRYPT_SESSION_TSP_SERVER, CRYPT_UNUSED, FALSE, FALSE ) );\n\t}\nint testSessionTSPServerEx( const CRYPT_CONTEXT privKeyContext )\n\t{\n\treturn( connectTSP( CRYPT_SESSION_TSP_SERVER, privKeyContext, FALSE, FALSE ) );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall tspServerThread( void *dummy )\n\t{\n\tacquireMutex();\n\tconnectTSP( CRYPT_SESSION_TSP_SERVER, CRYPT_UNUSED, FALSE, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionTSPClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tspServerThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectTSP( CRYPT_SESSION_TSP, CRYPT_UNUSED, FALSE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall tspServerPersistentThread( void *dummy )\n\t{\n\tacquireMutex();\n\tconnectTSP( CRYPT_SESSION_TSP_SERVER, CRYPT_UNUSED, TRUE, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionTSPClientServerPersistent( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server and wait for it to initialise */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tspServerPersistentThread,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectTSP( CRYPT_SESSION_TSP, CRYPT_UNUSED, TRUE, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n#endif /* WINDOWS_THREADS */\n\n#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */\n"
  },
  {
    "path": "deps/cl345/test/ssh.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib SSH Test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n#if defined( __MVS__ )\n  /* MVS control section (CSECT) names default to the file name and can't\n\t match any symbol name either in the file or in another file or library \n\t (e.g. write.c vs. write()).  Because of this we have to explicitly \n\t name the csect's so that they don't conflict with external symbol\n\t names */\n  #pragma csect( CODE, \"testSSHC\" )\n  #pragma csect( STATIC, \"testSSHS\" )\n  #pragma csect( TEST, \"testSSHT\" )\n#endif /* __MVS__ */\n\n/* Uncomment the following to ask the user for a password rather than using\n   a hardcoded password when testing against live accounts */\n\n/* #define USER_SUPPLIED_PASSWORD */\n#ifdef USER_SUPPLIED_PASSWORD\n  #undef SSH2_SERVER_NAME\n  #undef SSH_USER_NAME\n  #define SSH2_SERVER_NAME\t\"192.168.1.1\"\n  #define SSH_USER_NAME\t\t\"root\"\n#endif /* USER_SUPPLIED_PASSWORD */\n\n/* We can run the SSH self-test with a large variety of options, rather than\n   using dozens of boolean option flags to control them all we define\n   various test classes that exercise each option type */\n\ntypedef enum {\n\tSSL_TEST_NONE,\t\t\t\t/* No SSHv2 test type */\n\tSSH_TEST_NORMAL,\t\t\t/* Standard SSHv2 test */\n\tSSH_TEST_DSAKEY,\t\t\t/* DSA server key instead of RSA */\n\tSSH_TEST_ECCKEY,\t\t\t/* ECDSA server key instead of RSA */\n\tSSH_TEST_PUBKEYAUTH,\t\t/* Use public key for auth */\n\tSSH_TEST_PUBKEYAUTH_WRONGKEY, /* Use public key for auth but with wrong key */\n\tSSH_TEST_PUBKEYAUTH_WRONGNAME, /* Use public key for auth but with wrong name */\n\tSSH_TEST_PUBKEYAUTH_PASSWORD,/* Enable public key but use password */\n\tSSH_TEST_SUBSYSTEM,\t\t\t/* Test SFTP subsystem */\n\tSSH_TEST_PORTFORWARDING,\t/* Test port forwarding */\n\tSSH_TEST_EXEC,\t\t\t\t/* Test rexec rather than rsh functionality */\n\tSSH_TEST_MULTICHANNEL,\t\t/* Test multi-channel handling */\n\tSSH_TEST_FINGERPRINT,\t\t/* Test (invalid) key fingerprint */\n\tSSH_TEST_CONFIRMAUTH,\t\t/* Test manual server confirmation of auth.*/\n\tSSH_TEST_DUALTHREAD,\n\tSSH_TEST_DUALTHREAD2,\t\t/* Two-phase connect via different threads */\n\tSSH_TEST_CORRUPT_HANDSHAKE,\t/* Detect corruption of handshake data */\n\tSSH_TEST_CORRUPT_KEYEX_CLIENT, /* Detect corruption of client keyex */\n\tSSH_TEST_CORRUPT_KEYEX_SERVER, /* Detect corruption of server keyex */\n\tSSH_TEST_CORRUPT_EXCHANGE_HASH, /* Detect corruption of exchange hash */\n\tSSH_TEST_BADSIG_HASH,\t\t/* Detect corruption of hash for signature */\n\tSSH_TEST_BADSIG_SIG,\t\t/* Detect corruption of signature data */\n\tSSH_TEST_WRONG_CERT,\t\t/* Detect wrong key for server */\n\tSSH_TEST_CORRUPT_USERNAME,\t/* Detect wrong username */\n\tSSH_TEST_CORRUPT_PASSWORD,\t/* Detect wrong password */\n\tSSH_TEST_CORRUPT_CHANNEL_OPEN,\t/* Detect various types of channel corruption */\n\tSSH_TEST_CORRUPT_CHANNEL_DATA,\n\tSSH_TEST_CORRUPT_CHANNEL_CLOSE,\n\tSSH_TEST_CORRUPT_CHANNEL_REQUEST,\n\tSSH_TEST_CORRUPT_DATA,\t\t/* Detect corruption of payload data */\n\tSSH_TEST_CORRUPT_MAC,\t\t/* Detect corruption of payload MAC */\n\tSSH_TEST_LAST\t\t\t\t/* Last possible SSHv2 test type */\n\t} SSH_TEST_TYPE;\n\n#if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test the ability to parse URLs */\n\ntypedef struct {\n\tconst C_STR url;\t\t\t/* Server URL */\n\tconst C_STR name;\t\t\t/* Parsed server name */\n\tconst int port;\t\t\t\t/* Parsed server port */\n\tconst C_STR userInfo;\t\t/* Parsed user info */\n\t} URL_PARSE_INFO;\n\nstatic const URL_PARSE_INFO urlParseInfo[] = {\n\t/* IP address forms */\n\t{ TEXT( \"1.2.3.4\" ), TEXT( \"1.2.3.4\" ), 0, NULL },\n\t{ TEXT( \"1.2.3.4:80\" ), TEXT( \"1.2.3.4\" ), 80, NULL },\n\t{ TEXT( \"user@1.2.3.4\" ), TEXT( \"1.2.3.4\" ), 0, TEXT( \"user\" ) },\n\t{ TEXT( \"[1:2:3:4]\" ), TEXT( \"[1:2:3:4]\" ), 0, NULL },\n\t{ TEXT( \"[1:2:3:4]:80\" ), TEXT( \"[1:2:3:4]\" ), 80, NULL },\n\t{ TEXT( \"user@[1:2:3:4]\" ), TEXT( \"[1:2:3:4]\" ), 0, TEXT( \"user\" ) },\n\t{ TEXT( \"[::1]\" ), TEXT( \"[::1]\" ), 0, NULL },\n\n\t/* General URI forms */\n\t{ TEXT( \"www.server.com\" ), TEXT( \"www.server.com\" ), 0, NULL },\n\t{ TEXT( \"www.server.com:80\" ), TEXT( \"www.server.com\" ), 80, NULL },\n\t{ TEXT( \"http://www.server.com/\" ), TEXT( \"www.server.com\" ), 0, NULL },\n\t{ TEXT( \"http://www.server.com:80\" ), TEXT( \"www.server.com\" ), 80, NULL },\n\t{ TEXT( \"http://user@www.server.com:80\" ), TEXT( \"www.server.com\" ), 80, TEXT( \"user\" ) },\n\t{ TEXT( \"http://www.server.com/location.php\" ), TEXT( \"www.server.com\" ), 0, NULL },\n\t{ TEXT( \"http://www.server.com:80/location.php\" ), TEXT( \"www.server.com\" ), 80, NULL },\n\t{ TEXT( \"http://www.server.com/location1/location2/location.php\" ), TEXT( \"www.server.com\" ), 0, NULL },\n\n\t/* Spurious whitespace */\n\t{ TEXT( \"  www.server.com  :   80 \" ), TEXT( \"www.server.com\" ), 80, NULL },\n\t{ TEXT( \" user  @  www.server.com  :   80 \" ), TEXT( \"www.server.com\" ), 80, NULL },\n\t{ TEXT( \"http:// user  @ www.server.com  :   80 \" ), TEXT( \"www.server.com\" ), 80, TEXT( \"user\" ) },\n\t{ TEXT( \"www.server.com  :   80 /location.php\" ), TEXT( \"www.server.com\" ), 80, NULL },\n\n\t{ NULL, NULL, 0, NULL }\n\t};\n\nstatic const URL_PARSE_INFO invalidUrlParseInfo[] = {\n\t/* Bad port */\n\t{ TEXT( \"www.server.com:2\" ), NULL, 0, NULL },\n\t{ TEXT( \"www.server.com:80abcd\" ), NULL, 0, NULL },\n\t{ TEXT( \"www.server.com:abcd\" ), NULL, 0, NULL },\n\n\t/* Bad general URI */\n\t{ TEXT( \"http://\" ), NULL, 0, NULL },\n\t{ TEXT( \"http://xy\" ), NULL, 0, NULL },\n\t{ TEXT( \"@www.server.com\" ), NULL, 0, NULL },\n\t{ TEXT( \"   @www.server.com\" ), NULL, 0, NULL },\n\n\t{ NULL, NULL, 0, NULL }\n\t};\n\nint testSessionUrlParse( void )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint i, status;\n\n\tfputs( \"Testing session URL parsing...\", outputStream );\n\n\t/* Create a session of the most generic type */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, CRYPT_SESSION_SSL );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSL session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set various URLs as the server name and retrieve the parsed form */\n\tfor( i = 0; urlParseInfo[ i ].url != NULL; i++ )\n\t\t{\n\t\tC_CHR nameBuffer[ 256 ], userInfoBuffer[ 256 ];\n\t\tint nameLength, userInfoLength DUMMY_INIT, port DUMMY_INIT;\n\n\t\t/* Clear any leftover attributes from previous tests */\n\t\tmemset( nameBuffer, 0, 16 );\n\t\tmemset( userInfoBuffer, 0, 16 );\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_NAME );\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT );\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_USERNAME );\n\n\t\t/* Set the URL */\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  urlParseInfo[ i ].url,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( urlParseInfo[ i ].url ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't set URL '%s', status %d, \"\n\t\t\t\t\t \"line %d.\\n\", urlParseInfo[ i ].url, status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Make sure that the parsed form is OK */\n\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  nameBuffer, &nameLength );\n\t\tif( cryptStatusOK( status ) && urlParseInfo[ i ].port )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_PORT, &port );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && urlParseInfo[ i ].userInfo != NULL )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t\t  userInfoBuffer,\n\t\t\t\t\t\t\t\t\t\t\t  &userInfoLength );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't get parsed URL info for '%s', \"\n\t\t\t\t\t \"status %d, line %d.\\n\", urlParseInfo[ i ].url, status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( paramStrlen( urlParseInfo[ i ].name ) != ( size_t ) nameLength || \\\n\t\t\tmemcmp( nameBuffer, urlParseInfo[ i ].name, nameLength ) || \\\n\t\t\t( urlParseInfo[ i ].port && port != urlParseInfo[ i ].port ) || \\\n\t\t\t( urlParseInfo[ i ].userInfo != NULL && \\\n\t\t\t  memcmp( userInfoBuffer, urlParseInfo[ i ].userInfo,\n\t\t\t  userInfoLength ) ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Parsed URL info for '%s' is incorrect, \"\n\t\t\t\t\t \"line %d.\\n\", urlParseInfo[ i ].url, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Now try it with invalid URLs */\n\tfor( i = 0; invalidUrlParseInfo[ i ].url != NULL; i++ )\n\t\t{\n\t\t/* Clear any leftover attributes from previous tests */\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_NAME );\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT );\n\t\tcryptDeleteAttribute( cryptSession, CRYPT_SESSINFO_USERNAME );\n\n\t\t/* Set the URL */\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  invalidUrlParseInfo[ i ].url,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( invalidUrlParseInfo[ i ].url ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Invalid URL '%s' was accepted as valid, \"\n\t\t\t\t\t \"line %d.\\n\", invalidUrlParseInfo[ i ].url, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDestroySession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Session URL parsing succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/* Test session attribute handling */\n\nint testSessionAttributes( void )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\tfputs( \"Testing session attribute handling...\", outputStream );\n\n\t/* Create a server session of the most generic type */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SSL_SERVER );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSL server session access not avail.*/\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add an initial attribute */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, TEXT( \"servername\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"servername\" ) ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttributeString() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add several username/password pairs */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"test1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test1\" ) ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"test1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test1\" ) ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"test2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test2\" ) ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"test2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test2\" ) ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"test3\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test3\" ) ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"test3\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test3\" ) ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttributeString() for \"\n\t\t\t\t \"username/password pairs failed with error code %d, \"\n\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add a duplicate entry and make sure that it's detected */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"test2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"test2\" ) ) );\n\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t{\n\t\tfprintf( outputStream, \"Addition of duplicate user/password entry \"\n\t\t\t\t \"wasn't detected, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add a password without a preceding username and make sure that it's\n\t   detected */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"invalid_pw\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"invalid_pw\" ) ) );\n\tif( status != CRYPT_ERROR_NOTINITED )\n\t\t{\n\t\tfprintf( outputStream, \"Addition of password without username \"\n\t\t\t\t \"wasn't detected, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add a username without a password and make sure that it's detected */\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"valid_name\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"valid_name\" ) ) );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"invalid_name\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"invalid_name\" ) ) );\n\t\t}\n\tif( status != CRYPT_ERROR_INITED )\n\t\t{\n\t\tfprintf( outputStream, \"Addition of username without password \"\n\t\t\t\t \"wasn't detected, line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDestroySession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"Session attribute handling succeeded.\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSSH Utility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* There are various servers running that we can use for testing, the\n   following remapping allows us to switch between them.  Notes:\n\n\tServer 1: Local loopback.\n\tServer 2: Sends extraneous lines of text before the SSH ID string\n\t\t\t  (technically allowed by the RFC, but probably not in the way\n\t\t\t  that it's being used here).\n\tServer 3: Reference ssh.com implementation.\n\tServer 4: Reference OpenSSH implementation.  As of early 2016 switched \n\t\t\t  to a bunch of oddball nonstandard suites that we don't support.\n\tServer 5: OpenSSH with ECC support.  There are two aliases for the same \n\t\t\t  server, anoncvs is a somewhat nonstandard config that only \n\t\t\t  allows access via the 'anoncvs' account and is rather abrupt\n\t\t\t  about disconnecting clients, and natsu, which is a more \n\t\t\t  standard config that behaves more normally.\n\tServer 6: Sends PAM auth request consisting of 16 bytes of zeroes, \n\t\t\t  technically this is valid (since the spec is so vague) but it\n\t\t\t  doesn't make any sense to send it.\n\tServer 7: Test server for SHA-256 signing support.\n\tServer 8: Cisco router with suboptimal handling of DH lengths, aborts on\n\t\t\t  old-style SSH_MSG_KEXDH_GEX_REQUEST with 2K bit key rather than \n\t\t\t  continuing with what's available.\n\tServer 9: Cisco router that only supports the broken \n\t\t\t  diffie-hellman-group1-sha1 (not even the mandatory\n\t\t\t  diffie-hellman-group14-sha1, let alone any \n\t\t\t  diffie-hellman-group-exchange-xxx suite).\n\tServer 10: Cisco router with no support for any of the\n\t\t\t   diffie-hellman-group-exchange-xxx DH suites.\n\tServer 11: Bitvise test server for RFC 8308 and 8309.\n\tServer 12: Bitvise test server on localhost configured for both password \n\t\t\t   and publickey auth.  To enable multiple auth: Settings | \n\t\t\t   Access Control | Windows Groups, click on Everyone, Entry 0 \n\t\t\t   in Windows Groups | Authentication, set both Password and \n\t\t\t   Public-key to Required and set Public Key to use.  In \n\t\t\t   addition newer versions of the server don't support the MTI \n\t\t\t   algorithms by default, to enable MTI algorithms: Settings | \n\t\t\t   Algorithms | Encryption.\n\tServer 13: RSSBus test server on localhost configured for both password \n\t\t\t   and publickey auth.  To set up a server, in the Flow tab drag \n\t\t\t   SFTP across to workspace, set User, Auth.Mode = \"Multiple \n\t\t\t   Factor\", set Password and Public Key to use.\n\tServer 14: SSH test server using non-OpenSSH implementation \n\t\t\t   (\"RebexSSH_1.0.0.0\").  Uses a g value the same size as p,\n\t\t\t   which cryptlib rejects as too suspicious.\n\tServer 15: SSH test server running an ancient version of OpenSSH (RC4,\n\t\t\t   MD5, etc).  Returns an invalid signature for the keyex (the\n\t\t\t   hash values differ) if sending SSH_MSG_KEX_DH_GEX_REQUEST \n\t\t\t   rather than SSH_MSG_KEX_DH_GEX_REQUEST_OLD.\n\tServer 16: Generally-available site that runs SSH, implemented via some\n\t\t\t   customised libssh variant.\n\tServer 17: Bitvise test server that sends out Global Requests on \n\t\t\t   connect.\n\tServer 18: OpenSSH server on test device.\n\n   To test local -> remote/remote -> local forwarding:\n\n\tssh localhost -v -l test -pw test -L 110:pop3.test.com:110\n\tssh localhost -v -l test -pw test -R 110:pop3.test.com:110\n\n  For test purposes we connect to the OpenSSH server because this is the \n  most frequently-used one around, so maintaining compatibility with it \n  whenever it changes is important.  Using it for test connects is slightly \n  antisocial but in practice few people seem to run the self-test and we \n  never get past the initial handshake phase so it shouldn't be a big deal */\n\nstatic const struct {\n\tconst C_STR name;\n\tconst C_STR userName;\n\tconst C_STR password;\n\tconst BOOLEAN useDualAuth;\n\t} sshInfo[] = {\n\t{ NULL, NULL, NULL, FALSE },\n\t/*  1 */ { TEXT( \"localhost\" ), SSH_USER_NAME, SSH_PASSWORD },\n\t/*  2 */ { TEXT( \"sorrel.humboldt.edu:222\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  3 */ { TEXT( \"www.ssh.com\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  4 */ { TEXT( \"www.openssh.com\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  5 */ /* { TEXT( \"anoncvs.mindrot.org\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\tSee comment above */\n\t/*  5 */ { TEXT( \"natsu.mindrot.org\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  6 */ { TEXT( \"home.bbsdev.net\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  7 */ { TEXT( \"experiment.bitvise.com:10712\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  8 */ { TEXT( \"212.152.166.227\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/*  9 */ { TEXT( \"212.152.166.226:22\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/* 10 */ { TEXT( \"212.152.166.227:2222\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/* 11 */ { TEXT( \"experiment.bitvise.com:10739\" ), TEXT( \"test\" ), TEXT( \"test\" ) },\n\t/* 12 */ { TEXT( \"localhost\" ), TEXT( \"user\" ), TEXT( \"test\" ), TRUE },\n\t/* 13 */ { TEXT( \"localhost\" ), TEXT( \"test\" ), TEXT( \"test\" ), TRUE },\n\t/* 14 */ { TEXT( \"test.rebex.net\" ), \"demo\", \"password\" },\n\t/* 15 */ { TEXT( \"itcsubmit.wustl.edu\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/* 16 */ { TEXT( \"github.com\" ), TEXT( \"user\" ), TEXT( \"password\" ) },\n\t/* 17 */ { TEXT( \"experiment.bitvise.com:10999\" ), TEXT( \"test\" ), TEXT( \"test\" ) },\n\t/* 18 */ { TEXT( \"192.168.1.40\" ), TEXT( \"root\" ), TEXT( \"odroid\" ) },\n\t{ NULL, NULL, NULL, FALSE }\n\t};\n\n#define SSH2_SERVER_NO\t3\n\n#if defined( WINDOWS_THREADS ) || defined( UNIX_THREADS )\n\n/* Test the ability to have multiple server threads waiting on a session.\n   Since this requries (OS-specific) threading, we just use two sample\n   systems, Win32 (Windows threads) and Linux (pthreads).  Since Linux's\n   somewhat strange not-quite-a-thread/not-quite-a-process implementation\n   can be a bit buggy, we also use another sample pthreads implementation\n   (FreeBSD/NetBSD) as a sanity check */\n\n#ifdef WINDOWS_THREADS\n  unsigned __stdcall sshServerMultiThread( void *dummy )\n#else\n  void *sshServerMultiThread( void *dummy )\n#endif /* Windows vs. pthreads */\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT privateKey;\n\tBYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tvoid *fileNamePtr = filenameBuffer;\n\tint status;\n\n\tfprintf( outputStream, \"Server thread %lX activated.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tfflush( outputStream );\n\n\t/* Create the session and try to activate it.  We don't do anything\n\t   beyond that point since this is a test of multi-thread handling\n\t   capability, not session handling */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SSH_SERVER );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tTHREAD_EXIT();\n\t\t}\n\tif( !setLocalConnect( cryptSession, 22 ) )\n\t\t{\n\t\tTHREAD_EXIT();\n\t\t}\n\tfilenameFromTemplate( filenameBuffer, SSH_PRIVKEY_FILE_TEMPLATE, 1 );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\tstatus = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL, \n\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\t\tcryptDestroyContext( privateKey );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_AUTHRESPONSE,\n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Private key read/set failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tTHREAD_EXIT();\n\t\t}\n\tfprintf( outputStream, \"Server for thread %lX activated.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession,\n\t\t\t\t\t   \"Attempt to activate SSH server session\", status,\n\t\t\t\t\t   __LINE__ );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\tfprintf( outputStream, \"Server for thread %lX has exited.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tfflush( outputStream );\n\n\tTHREAD_EXIT();\n\t}\n\n#ifdef WINDOWS_THREADS\n  unsigned __stdcall sshClientMultiThread( void *dummy )\n#else\n  void *sshClientMultiThread( void *dummy )\n#endif /* Windows vs. pthreads */\n\t{\n\tCRYPT_SESSION cryptSession;\n\tint status;\n\n\tfprintf( outputStream, \"Client thread %lX activated.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tfflush( outputStream );\n\n\t/* Create the session and try to activate it.  We don't do anything\n\t   beyond that point since this is a test of multi-thread handling\n\t   capability, not session handling */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_SESSION_SSH );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\tTHREAD_EXIT();\n\t\t}\n\tif( !setLocalConnect( cryptSession, 22 ) )\n\t\t{\n\t\tTHREAD_EXIT();\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_CONNECTTIMEOUT, 10 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t  sshInfo[ SSH2_SERVER_NO ].userName,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( sshInfo[ SSH2_SERVER_NO ].userName ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  sshInfo[ SSH2_SERVER_NO ].password,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( sshInfo[ SSH2_SERVER_NO ].password ) );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttribute/AttributeString() failed \"\n\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\tTHREAD_EXIT();\n\t\t}\n\tfprintf( outputStream, \"Client for thread %lX activated.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tprintConnectInfo( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession,\n\t\t\t\t\t   \"Attempt to activate SSH client session\", status,\n\t\t\t\t\t   __LINE__ );\n\t\t}\n\tcryptDestroySession( cryptSession );\n\tfprintf( outputStream, \"Client for thread %lX has exited.\\n\", \n\t\t\t ( unsigned long ) THREAD_SELF() );\n\tfflush( outputStream );\n\n\tTHREAD_EXIT();\n\t}\n\nint testSessionSSHClientServerMultiThread( void )\n\t{\n\treturn( multiThreadDispatch( sshClientMultiThread, \n\t\t\t\t\t\t\t\t sshServerMultiThread, MAX_NO_THREADS ) );\n\t}\n#endif /* OS-specific threading functions */\n\n#ifdef USE_SSH_EXTENDED\n\n/* Create an SSH channel */\n\nstatic int createChannel( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t  const C_STR type, const C_STR arg1 )\n\t{\n\tint status;\n\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,\n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\t\t\t\t\t\t\t\t\t  type, paramStrlen( type ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t\t  arg1, paramStrlen( arg1 ) );\n\t\t}\n\treturn( status );\n\t}\n\n/* Print information on an SSH channel */\n\nstatic BOOLEAN printChannelInfo( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t\t\t const SSH_TEST_TYPE testType,\n\t\t\t\t\t\t\t\t const BOOLEAN isServer )\n\t{\n\tC_CHR stringBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tC_CHR argBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint channel, stringLength, argLength = 0, status;\n\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,\n\t\t\t\t\t\t\t\t&channel );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL_TYPE,\n\t\t\t\t\t\t\t\t\t\t  stringBuffer, &stringLength );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"%sCouldn't query channel ID/type, \"\n\t\t\t\t \"status %d, line %d.\\n\", isServer ? \"SVR: \" : \"\", \n\t\t\t\t status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifdef UNICODE_STRINGS\n\tstringBuffer[ stringLength / sizeof( wchar_t ) ] = TEXT( '\\0' );\n#else\n\tstringBuffer[ stringLength ] = '\\0';\n#endif /* UNICODE_STRINGS */\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\tif( !paramStrcmp( stringBuffer, TEXT( \"subsystem\" ) ) || \\\n\t\t!paramStrcmp( stringBuffer, TEXT( \"direct-tcpip\" ) ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSH_CHANNEL_ARG1,\n\t\t\t\t\t\t\t\t\t\t  argBuffer, &argLength );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"%sCouldn't query channel arg, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", isServer ? \"SVR: \" : \"\", \n\t\t\t\t\t status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n#ifdef UNICODE_STRINGS\n\t\targBuffer[ argLength / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"SVR: Client opened channel #%d, type '%S', \"\n\t\t\t\t \"arg '%S'.\\n\", channel, stringBuffer, argBuffer );\n#else\n\t\targBuffer[ argLength ] = '\\0';\n  #if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\tbufferToEbcdic( argBuffer, argBuffer );\n  #endif /* EBCDIC systems */\n\t\tfprintf( outputStream, \"SVR: Client opened channel #%d, type '%s', \"\n\t\t\t\t \"arg '%s'.\\n\", channel, stringBuffer, argBuffer );\n#endif /* UNICODE_STRINGS */\n\t\tfflush( outputStream );\n\n\t\treturn( TRUE );\n\t\t}\n\n\tif( testType == SSH_TEST_SUBSYSTEM )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Client requested subsystem but server \"\n\t\t\t\t \"reported request as '%s', line %d.\\n\", stringBuffer, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n#ifdef UNICODE_STRINGS\n\tfprintf( outputStream, \"SVR: Client opened channel #%d, type '%S'.\\n\",\n\t\t\t channel, stringBuffer );\n#else\n\tfprintf( outputStream, \"SVR: Client opened channel #%d, type '%s'.\\n\",\n\t\t\t channel, stringBuffer );\n#endif /* UNICODE_STRINGS */\n\tfflush( outputStream );\n\treturn( TRUE );\n\t}\n#endif /* USE_SSH_EXTENDED */\n\n/* Print information on data sent over an SSH channel */\n\nstatic int printDataInfo( CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t  char *buffer, int *bytesCopied,\n\t\t\t\t\t\t  const BOOLEAN isServer, \n\t\t\t\t\t\t  const BOOLEAN isErrorTest )\n\t{\n\tint channel = 0, status;\n\n#ifdef USE_SSH_EXTENDED\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL, \n\t\t\t\t\t\t\t\t&channel );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \n\t\t\t\t\t   isServer ? \"SVR: Couldn't get data channel number\" : \\\n\t\t\t\t\t\t\t\t  \"Couldn't get data channel number\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( status );\n\t\t}\n#endif /* USE_SSH_EXTENDED */\n\tstatus = cryptPopData( cryptSession, buffer, BUFFER_SIZE, bytesCopied );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \n\t\t\t\t\t   isServer ? \"SVR: Client data read failed\" : \\\n\t\t\t\t\t\t\t\t  \"Server data read failed\", \n\t\t\t\t\t   status, __LINE__ );\n#ifndef NDEBUG\n\t\tif( isErrorTest )\n\t\t\t{\n\t\t\tif( !isServer && status != CRYPT_ERROR_SIGNATURE && \\\n\t\t\t\t\t\t\t status != CRYPT_ERROR_BADDATA )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Test returned status %d, should \"\n\t\t\t\t\t\t \"have been %d or %d.\\n\", status, \n\t\t\t\t\t\t CRYPT_ERROR_SIGNATURE, CRYPT_ERROR_BADDATA );\n\t\t\t\treturn( status );\n\t\t\t\t}\n\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tfputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t   \"response is correct).\\n\", outputStream );\n\t\t\treturn( SENTINEL );\n\t\t\t}\n#endif /* !NDEBUG */\n\t\treturn( status );\n\t\t}\n\tbuffer[ *bytesCopied ] = '\\0';\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\tfprintf( outputStream, \"%s---- %s sent %d bytes on channel #%d ----\\n\",\n\t\t\t isServer ? \"SVR: \" : \"\", isServer ? \"Client\" : \"Server\",\n\t\t\t *bytesCopied, channel );\n\tif( isServer )\n\t\tfprintf( outputStream, \"SVR: \" );\n\tfputs( buffer, outputStream );\n\tfprintf( outputStream, \"%s---- End of output ----\\n\", \n\t\t\t isServer ? \"SVR: \" : \"\" );\n\tfflush( outputStream );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Print information on SSH authorisation info */\n\nstatic BOOLEAN printAuthInfo( CRYPT_SESSION cryptSession )\n\t{\n\tC_CHR stringBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];\n\tint length, status;\n\n\tstatus = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t  stringBuffer, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tstringBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"SVR: User name = '%S', \", stringBuffer );\n#else\n\t\tstringBuffer[ length ] = '\\0';\n  #if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\tbufferToEbcdic( stringBuffer, stringBuffer );\n  #endif /* EBCDIC systems */\n\t\tfprintf( outputStream, \"SVR: User name = '%s', \", stringBuffer );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t  stringBuffer, &length );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tstringBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"password = '%S'.\\n\", stringBuffer );\n#else\n\t\tstringBuffer[ length ] = '\\0';\n  #if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\tbufferToEbcdic( stringBuffer, stringBuffer );\n  #endif /* EBCDIC systems */\n\t\tfprintf( outputStream, \"password = '%s'.\\n\", stringBuffer );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Couldn't read client authentication \"\n\t\t\t\t \"details, status = %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfflush( outputStream );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSH Routines Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're testing dual-thread handling of sessions, we need to provide a\n   forward declaration of the threading function since it's called from \n   within the SSH connect code */\n\n#ifdef WINDOWS_THREADS\n  unsigned __stdcall ssh2ServerThread( void *arg );\n#endif /* WINDOWS_THREADS */\n\n/* Establish an SSH session */\n\nstatic int connectSSH( const CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t   const SSH_TEST_TYPE testType,\n\t\t\t\t\t   const BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n#ifdef SSH2_SERVER_NAME\n\tconst C_STR serverName = SSH2_SERVER_NAME;\n#else\n\tconst C_STR serverName = localSession ? TEXT( \"localhost\" ) : \\\n\t\t\t\t\t\t\t\t\t\t\tsshInfo[ SSH2_SERVER_NO ].name;\n#endif /* SSH2_SERVER_NAME */\n\tconst BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSH_SERVER ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tconst BOOLEAN isErrorTest = ( testType >= SSH_TEST_CORRUPT_HANDSHAKE && \\\n\t\t\t\t\t\t\t\t  testType < SSH_TEST_LAST ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tconst BOOLEAN useDualAuth = !isServer && \\\n\t\t\t\t\t\t\t\tsshInfo[ SSH2_SERVER_NO ].useDualAuth;\n\tchar buffer[ BUFFER_SIZE ];\n#ifdef USE_SSH_EXTENDED\n\tint channel;\n#endif /* USE_SSH_EXTENDED */\n\tint bytesCopied, status;\n\n\t/* If this is a local session, synchronise the client and server */\n\tif( localSession )\n\t\t{\n\t\tif( isServer )\n\t\t\t{\n\t\t\t/* Acquire the init mutex */\n\t\t\tacquireMutex();\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We're the client Wait for the server to finish initialising */\n\t\t\tif( waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Timed out waiting for server to \"\n\t\t\t\t\t\t \"initialise, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If this is the dual-thread server test and we're the second server \n\t   thread, skip the portions that have already been handled by the first \n\t   thread */\n#ifdef WINDOWS_THREADS\n\tif( isServer && testType == SSH_TEST_DUALTHREAD2 )\n\t\tgoto dualThreadContinue;\n#endif /* WINDOWS_THREADS */\n\n\tfprintf( outputStream, \"%sTesting %sSSH%s session...\\n\",\n\t\t\t isServer ? \"SVR: \" : \"\",\n\t\t\t localSession ? \"local \" : \"\",\n\t\t\t ( testType == SSH_TEST_DSAKEY ) ? \" with DSA server key\" : \\\n\t\t\t ( testType == SSH_TEST_ECCKEY ) ? \" with ECDSA server key\" : \\\n\t\t\t ( testType == SSH_TEST_SUBSYSTEM ) ? \" SFTP\" : \\\n\t\t\t ( testType == SSH_TEST_PORTFORWARDING ) ? \" port-forwarding\" : \\\n\t\t\t ( testType == SSH_TEST_EXEC ) ? \" remote exec\" : \\\n\t\t\t ( testType == SSH_TEST_MULTICHANNEL ) ? \" multi-channel\" : \\\n\t\t\t ( testType == SSH_TEST_PUBKEYAUTH ) ? \" pubkey-auth\" : \\\n\t\t\t ( testType == SSH_TEST_PUBKEYAUTH_WRONGKEY ) ? \" pubkey-auth with incorrect key\" : \\\n\t\t\t ( testType == SSH_TEST_PUBKEYAUTH_WRONGNAME ) ? \" pubkey-auth with incorrect name\" : \\\n\t\t\t ( testType == SSH_TEST_PUBKEYAUTH_PASSWORD ) ? \" pubkey-auth but using password\" : \\\n\t\t\t isErrorTest ? \" with checking for error handling\" : \"\" );\n\tif( !isServer && !localSession )\n\t\t{\n#ifdef UNICODE_STRINGS\n\t\tfprintf( outputStream, \"  Remote host: %S.\\n\", serverName );\n#else\n\t\tfprintf( outputStream, \"  Remote host: %s.\\n\", serverName );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\tfflush( outputStream );\n\n\t/* Create the session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSH session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tif( isErrorTest )\n\t\t{\n\t\tint testFaultType;\n\n\t\tif( isServer )\n\t\t\t{\n\t\t\ttestFaultType = \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_HANDSHAKE ) ? \\\n\t\t\t\t\t  FAULT_SESSION_CORRUPT_HANDSHAKE : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_KEYEX_SERVER ) ? \\\n\t\t\t\t\t  FAULT_SESSION_CORRUPT_KEYEX_SERVER : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_EXCHANGE_HASH ) ? \\\n\t\t\t\t\t  FAULT_SESSION_SSH_CORRUPT_EXCHANGE_HASH : \\\n\t\t\t\t\t( testType == SSH_TEST_BADSIG_HASH ) ? \\\n\t\t\t\t\t  FAULT_BADSIG_HASH : \\\n\t\t\t\t\t( testType == SSH_TEST_BADSIG_SIG ) ? \\\n\t\t\t\t\t  FAULT_BADSIG_SIG : \\\n\t\t\t\t\t( testType == SSH_TEST_WRONG_CERT ) ? \\\n\t\t\t\t\t  FAULT_SESSION_WRONGCERT : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_USERNAME ) ? \\\n\t\t\t\t\t  FAULT_CORRUPT_ID : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_PASSWORD ) ? \\\n\t\t\t\t\t  FAULT_CORRUPT_AUTHENTICATOR : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_CHANNEL_OPEN ) ? \\\n\t\t\t\t\t  FAULT_SESSION_SSH_CORRUPT_CHANNEL_OPEN : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_CHANNEL_DATA ) ? \\\n\t\t\t\t\t  FAULT_SESSION_SSH_CORRUPT_CHANNEL_DATA : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_CHANNEL_CLOSE ) ? \\\n\t\t\t\t\t  FAULT_SESSION_SSH_CORRUPT_CHANNEL_CLOSE : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_CHANNEL_REQUEST ) ? \\\n\t\t\t\t\t  FAULT_SESSION_SSH_CORRUPT_CHANNEL_REQUEST : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_DATA ) ? \\\n\t\t\t\t\t  FAULT_SESSION_CORRUPT_DATA : \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_MAC ) ? \\\n\t\t\t\t\t  FAULT_SESSION_CORRUPT_MAC : \\\n\t\t\t\t\t  FAULT_NONE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\ttestFaultType = \\\n\t\t\t\t\t( testType == SSH_TEST_CORRUPT_KEYEX_CLIENT ) ? \\\n\t\t\t\t\t  FAULT_SESSION_CORRUPT_KEYEX_CLIENT : \\\n\t\t\t\t\t  FAULT_NONE;\n\t\t\t}\n\t\tif( testFaultType != FAULT_NONE )\n\t\t\tcryptSetFaultType( testFaultType );\n\t\t}\n#endif /* CONFIG_FAULTS && Debug */\n\n\t/* Set up the server and user information and activate the session */\n\tif( isServer )\n\t\t{\n\t\tCRYPT_CONTEXT privateKey;\n\t\tBYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\t\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\t\tvoid *fileNamePtr = filenameBuffer;\n\n\t\tif( !setLocalConnect( cryptSession, 22 ) )\n\t\t\treturn( FALSE );\n\t\tfilenameFromTemplate( filenameBuffer, SSH_PRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t\t  ( testType == SSH_TEST_ECCKEY ) ? 3 : \\\n\t\t\t\t\t\t\t  ( testType == SSH_TEST_DSAKEY ) ? 2 : 1 );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL, \n\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\t\t\tcryptDestroyContext( privateKey );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSH_TEST_PUBKEYAUTH || \\\n\t\t\t  testType == SSH_TEST_PUBKEYAUTH_WRONGKEY || \\\n\t\t\t  testType == SSH_TEST_PUBKEYAUTH_WRONGNAME || \\\n\t\t\t  testType == SSH_TEST_PUBKEYAUTH_PASSWORD ) )\n\t\t\t{\n\t\t\tCRYPT_KEYSET cryptKeyset;\n\t\t\tCRYPT_CONTEXT publicKey;\n\n\t\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tDATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t\tCRYPT_KEYOPT_NONE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"SVR: Pubkey auth.keyset open failed \"\n\t\t\t\t\t\t \"with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = getPublicKey( &publicKey, USER_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t   USER_PRIVKEY_LABEL );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* Add the key to the authorisation database */\n\t\t\t\tstatus = cryptAddPublicKey( cryptKeyset, publicKey );\n\t\t\t\tif( status == CRYPT_ERROR_DUPLICATE )\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\tcryptDestroyContext( publicKey );\n\t\t\t\t}\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_KEYSET, \n\t\t\t\t\t\t\t\t\t\t\tcryptKeyset );\n\t\t\t\t}\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( localSession )\n\t\t\t{\n\t\t\tif( !setLocalConnect( cryptSession, 22 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, serverName, \n\t\t\t\t\t\t\tparamStrlen( serverName ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType != SSH_TEST_PUBKEYAUTH && \\\n\t\t\t  testType != SSH_TEST_PUBKEYAUTH_WRONGKEY ) )\n\t\t\t{\t\t\t\t\t\t   /* pubkey takes user name from certificate */\n#if defined USER_SUPPLIED_PASSWORD\n\t\t\tconst C_STR userName = SSH_USER_NAME; \n#else\n\t\t\tconst C_STR userName = sshInfo[ SSH2_SERVER_NO ].userName;\n#endif /* USER_SUPPLIED_PASSWORD */\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, userName, \n\t\t\t\t\t\t\tparamStrlen( userName ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tconst BOOLEAN usePubkeyAuth = \\\n\t\t\t\t( testType == SSH_TEST_PUBKEYAUTH || \\\n\t\t\t\t  testType == SSH_TEST_PUBKEYAUTH_WRONGKEY || \\\n\t\t\t\t  testType == SSH_TEST_PUBKEYAUTH_WRONGNAME ) ? TRUE : FALSE;\n\n\t\t\tif( usePubkeyAuth || useDualAuth )\n\t\t\t\t{\n\t\t\t\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\t\t\t\tCRYPT_CONTEXT privateKey;\n\n\t\t\t\tfilenameFromTemplate( filenameBuffer, \n\t\t\t\t\t\t\tUSER_PRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t\t( testType != SSH_TEST_PUBKEYAUTH_WRONGKEY ) ? \\\n\t\t\t\t\t\t\t  1 : 2 );\n\t\t\t\tstatus = getPrivateKey( &privateKey, filenameBuffer,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\t\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t\t( testType == SSH_TEST_PUBKEYAUTH || \\\n\t\t\t\t\t  testType == SSH_TEST_PUBKEYAUTH_WRONGKEY ) )\n\t\t\t\t\t{\n\t\t\t\t\tchar userName[ 128 ];\n\t\t\t\t\tint userNameLength;\n\n\t\t\t\t\t/* For the pubkey auth we have to provide the same name \n\t\t\t\t\t   that's associated with the public key via the \n\t\t\t\t\t   certificate or the auth will be rejected, unless \n\t\t\t\t\t   we're using dual auth in which case we have a \n\t\t\t\t\t   hardcoded user name */\n\t\t\t\t\tif( useDualAuth )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tconst BYTE *userNamePtr = \\\n\t\t\t\t\t\t\t\t\t\tsshInfo[ SSH2_SERVER_NO ].userName;\n\n\t\t\t\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t\tuserNamePtr, \n\t\t\t\t\t\t\t\t\t\t\tparamStrlen( userNamePtr ) );\n\t\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = cryptGetAttributeString( privateKey, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_COMMONNAME, \n\t\t\t\t\t\t\t\t\t\t\tuserName, &userNameLength );\n\t\t\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\t\t\t\t\tuserName, userNameLength );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\t\t\t\t\tcryptDestroyContext( privateKey );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tif( !usePubkeyAuth || useDualAuth )\n\t\t\t\t{\n#ifdef USER_SUPPLIED_PASSWORD\n\t\t\t\tchar password[ 256 ];\n\n\t\t\t\tfprintf( outputStream, \"Enter SSHv2 server password: \" );\n\t\t\t\tfgets( password, 255, stdin );\n\t\t\t\tpassword[ strlen( password ) - 1 ] = '\\0';\n\t\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, password, \n\t\t\t\t\t\t\tstrlen( password ) );\n#else\n\t\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\tsshInfo[ SSH2_SERVER_NO ].password,\n\t\t\t\t\t\t\tparamStrlen( sshInfo[ SSH2_SERVER_NO ].password ) );\n#endif /* User-supplied password */\n\t\t\t\t}\n\t\t\t}\n#ifdef USE_SSH_EXTENDED\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSH_TEST_SUBSYSTEM ) )\n\t\t\t{\n\t\t\tstatus = createChannel( cryptSession, TEXT( \"subsystem\" ),\n\t\t\t\t\t\t\t\t\tTEXT( \"sftp\" ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSH_TEST_PORTFORWARDING || \\\n\t\t\t  testType == SSH_TEST_MULTICHANNEL || \\\n\t\t\t  testType == SSH_TEST_CORRUPT_CHANNEL_CLOSE || \\\n\t\t\t  testType == SSH_TEST_CORRUPT_CHANNEL_REQUEST ) )\n\t\t\t{\n\t\t\tstatus = createChannel( cryptSession, TEXT( \"direct-tcpip\" ),\n\t\t\t\t\t\t\t\t\tTEXT( \"localhost:1234\" ) );\n\t\t\t}\n#endif /* USE_SSH_EXTENDED */\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSH_TEST_FINGERPRINT ) )\n\t\t\t{\n\t\t\tBYTE fingerPrint[ CRYPT_MAX_HASHSIZE ];\n\n\t\t\t/* Set a dummy (all-zero) fingerprint to force the connect to\n\t\t\t   fail */\n\t\t\tmemset( fingerPrint, 0, CRYPT_MAX_HASHSIZE );\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t\t\t\t  fingerPrint, 20 );\n\t\t\t}\n#ifdef USE_SSH_EXTENDED\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSH_TEST_EXEC ) )\n\t\t\t{\n\t\t\tstatus = createChannel( cryptSession, TEXT( \"exec\" ),\n\t\t\t\t\t\t\t\t\tTEXT( \"/bin/netstat\" ) );\n\t\t\t}\n#endif /* USE_SSH_EXTENDED */\n\t\t}\n\tif( cryptStatusOK( status ) && isServer && \\\n\t\t( testType != SSH_TEST_CONFIRMAUTH && \\\n\t\t  testType != SSH_TEST_DUALTHREAD ) )\n\t\t{\n\t\t/* If we're not testing manual confirmation of client auth, have\n\t\t   cryptlib automatically confirm the auth */\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_AUTHRESPONSE,\n\t\t\t\t\t\t\t\t\tTRUE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"%scryptSetAttribute/AttributeString() \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", \n\t\t\t\t isServer ? \"SVR: \" : \"\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Activate the session.  Since we need to be able to process out-of-\n\t   band signalling such as channel control messages, we set a non-zero\n\t   timeout for reads */\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT, 5 );\n\tif( localSession )\n\t\t{\n\t\t/* For the loopback test we also increase the connection timeout to \n\t\t   a higher-than-normal level, since this gives us more time for\n\t\t   tracing through the code when debugging */\n\t\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_CONNECTTIMEOUT, \n\t\t\t\t\t\t   120 );\n\t\t}\n\tif( localSession && isServer )\n\t\t{\n\t\t/* Tell the client that we're ready to go */\n\t\treleaseMutex();\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( isServer )\n\t\t{\n#ifdef WINDOWS_THREADS\n\t\tif( isServer && testType == SSH_TEST_DUALTHREAD && \\\n\t\t\tstatus == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t{\n\t\t\tstatic CRYPT_SESSION localCryptSession = 0;\n\t\t\tint arg = SSH_TEST_DUALTHREAD2;\n\t\t\tunsigned threadID;\n\n\t\t\t/* Start a second thread to complete the handshake and exit */\n\t\t\tlocalCryptSession = cryptSession;\n\t\t\t_beginthreadex( NULL, 0, ssh2ServerThread, &arg, 0, &threadID );\n\t\t\treturn( TRUE );\n\n\t\t\t/* The second thread continues from here */\ndualThreadContinue:\n\t\t\tassert( localSession > 0 );\n\t\t\tcryptSession = localCryptSession;\n\n\t\t\t/* Allow the auth.and complete the handshake */\n\t\t\tfputs( \"SVR: Confirming authentication to client...\", \n\t\t\t\t   outputStream );\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, TRUE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_ACTIVE, TRUE );\n\t\t\t}\n#endif /* WINDOWS_THREADS */\n\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t{\n\t\t\t/* The client has tried to authenticate themselves, print the\n\t\t\t   info */\n\t\t\tif( !printAuthInfo( cryptSession ) )\n\t\t\t\treturn( FALSE );\n\n\t\t\t/* Deny the auth.and force them to retry, unless it's a loopback\n\t\t\t   test which is non-interactive and for which the client can't\n\t\t\t   perform an interactive re-auth */\n\t\t\tif( !localSession )\n\t\t\t\t{\n\t\t\t\tfputs( \"SVR: Denying authentication to client, who should \"\n\t\t\t\t\t   \"reauth...\", outputStream );\n\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, \n\t\t\t\t\t\t\t\t\t\t\tFALSE );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_ACTIVE, TRUE );\n\t\t\t\t\t}\n\t\t\t\tif( status != CRYPT_ENVELOPE_RESOURCE )\n\t\t\t\t\t{\n\t\t\t\t\tprintExtError( cryptSession, \n\t\t\t\t\t\t\t\t   \"SVR: Attempt to deny auth.to client\", \n\t\t\t\t\t\t\t\t   status, __LINE__ );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tif( !printAuthInfo( cryptSession ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Allow the auth.and complete the handshake */\n\t\t\tfputs( \"SVR: Confirming authentication to client...\", \n\t\t\t\t   outputStream );\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, TRUE );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_ACTIVE, TRUE );\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Now that the handshake is complete, display the connection info */\n\t\tif( cryptStatusOK( status ) && !printConnectInfo( cryptSession ) )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( testType == SSH_TEST_FINGERPRINT )\n\t\t\t{\n\t\t\t/* We've forced the connect to fail by using a dummy fingerprint,\n\t\t\t   everything is OK */\n\t\t\tif( isServer )\n\t\t\t\tfprintf( outputStream, \"SVR: \" );\n\t\t\tfputs( \"SSH client rejected key with invalid fingerprint.\", \n\t\t\t\t   outputStream );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tfputs( isServer ? \"SVR: SSH server session succeeded.\\n\\n\" : \\\n\t\t\t\t\t\t\t  \"SSH client session succeeded.\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\tfflush( outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t   \"SVR: Attempt to activate SSH server session\" : \\\n\t\t\t\t\t   \"Attempt to activate SSH client session\", status,\n\t\t\t\t\t   __LINE__ );\n\t\tif( isErrorTest || testType == SSH_TEST_PUBKEYAUTH_WRONGKEY || \\\n\t\t\t\t\t\t   testType == SSH_TEST_PUBKEYAUTH_WRONGNAME || \\\n\t\t\t\t\t\t   testType == SSH_TEST_PUBKEYAUTH_PASSWORD )\n\t\t\t{\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tif( !isServer && \\\n\t\t\t\t( testType != SSH_TEST_CORRUPT_MAC && \\\n\t\t\t\t  testType != SSH_TEST_PUBKEYAUTH_WRONGKEY && \\\n\t\t\t\t  testType != SSH_TEST_PUBKEYAUTH_WRONGNAME && \\\n\t\t\t\t  testType != SSH_TEST_PUBKEYAUTH_PASSWORD ) && \\\n\t\t\t\t( status != CRYPT_ERROR_SIGNATURE && \\\n\t\t\t\t  status != CRYPT_ERROR_BADDATA && \\\n\t\t\t\t  status != CRYPT_ERROR_PERMISSION ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Test returned status %d, should \"\n\t\t\t\t\t\t \"have been %d or %d.\\n\", status, \n\t\t\t\t\t\t CRYPT_ERROR_SIGNATURE, CRYPT_ERROR_BADDATA );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tfputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t   \"response is correct).\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tif( localSession )\n\t\t\t{\n\t\t\t/* If it's a local session then none of the following soft-\n\t\t\t   failure conditions are valid */\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( !isServer && isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tfputs( \"  (Server could be down, faking it and \"\n\t\t\t\t   \"continuing...)\\n\\n\", outputStream );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\tif( status == CRYPT_ERROR_WRONGKEY )\n\t\t\t{\n\t\t\t/* This is another possible soft error condition, the default\n\t\t\t   username and password shouldn't be able to get into many\n\t\t\t   machines */\n\t\t\tfputs( \"  (Incorrect username/password, continuing...)\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tif( status == CRYPT_ERROR_NOSECURE )\n\t\t\t{\n\t\t\t/* Another soft error condition, the server can't handle the\n\t\t\t   security level we want (usually occurs when trying to perform\n\t\t\t   an SSHv2 connect to an SSHv1 server) */\n\t\t\tfputs( \"  (Insufficiently secure protocol parameters, \"\n\t\t\t\t   \"continuing...)\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\tif( testType == SSH_TEST_FINGERPRINT )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to connect with invalid key \"\n\t\t\t\t \"fingerprint succeeded when it should\\nhave failed, \"\n\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( testType == SSH_TEST_PUBKEYAUTH_WRONGKEY || \\\n\t\ttestType == SSH_TEST_PUBKEYAUTH_WRONGNAME )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to connect with invalid key or \"\n\t\t\t\t \"user name succeeded when it\\nshould have failed, \"\n\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The error tests should cause handshake failures, so getting to this \n\t   point is an error */\n\tif( isErrorTest && \\\n\t\t( testType != SSH_TEST_CORRUPT_DATA && \\\n\t\t  testType != SSH_TEST_CORRUPT_CHANNEL_DATA && \\\n\t\t  testType != SSH_TEST_CORRUPT_CHANNEL_CLOSE && \\\n\t\t  testType != SSH_TEST_CORRUPT_CHANNEL_REQUEST ) )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\tfputs( \"  (This test should have led to a handshake failure but \"\n\t\t\t   \"didn't, test has\\n   failed).\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Report the session security info.  In standard SSH usage \n\t   channel == session so we only try and report channel details if the\n\t   SSH extended capabilities are enabled */\n\tif( !printSecurityInfo( cryptSession, isServer, TRUE, FALSE, FALSE ) )\n\t\treturn( FALSE );\n#ifdef USE_SSH_EXTENDED\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_SSH_CHANNEL,\n\t\t\t\t\t\t\t\t&channel );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptGetAttributeString() failed with \"\n\t\t\t\t \"error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"%sCurrent channel is #%d.\\n\", \n\t\t\t isServer ? \"SVR: \" : \"\", channel );\n#endif /* USE_SSH_EXTENDED */\n\tfflush( outputStream );\n\n\t/* Report additional channel-specific information */\n\tif( isServer )\n\t\t{\n\t\t/* Display info on any channels that the client has opened.  As with\n\t\t   the earlier channel display, we can only do this if SSH extended\n\t\t   capabilities are enabled */\n#ifdef USE_SSH_EXTENDED\n\t\tif( !printChannelInfo( cryptSession, testType, TRUE ) )\n\t\t\treturn( FALSE );\n#endif /* USE_SSH_EXTENDED */\n\n\t\t/* Process any additional information that the client may throw\n\t\t   at us after the user-auth has completed */\n\t\tstatus = cryptPopData( cryptSession, buffer, BUFFER_SIZE,\n\t\t\t\t\t\t\t   &bytesCopied );\n\t\tif( cryptStatusOK( status ) && bytesCopied > 0 )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: Client sent additional %d bytes \"\n\t\t\t\t\t \"post-handshake data.\\n\", bytesCopied );\n\t\t\tfflush( outputStream );\n\t\t\t}\n#ifdef USE_SSH_EXTENDED\n\t\telse\n\t\t\t{\n\t\t\tif( status == CRYPT_ENVELOPE_RESOURCE )\n\t\t\t\t{\n\t\t\t\t/* The client performed additional control actions that were\n\t\t\t\t   handled inline as part of the data-pop, report the\n\t\t\t\t   details */\n\t\t\t\tif( !printChannelInfo( cryptSession, testType, TRUE ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n#endif /* USE_SSH_EXTENDED */\n\t\t}\n\n\t/* If we're using the SFTP subsystem as a server, use the special-case\n\t   routines for this */\n#if defined( WINDOWS_THREADS ) && 0\n\tif( testType == SSH_TEST_SUBSYSTEM )\n\t\t{\n\t\tif( isServer )\n\t\t\t{\n\t\t\tint sftpServer( const CRYPT_SESSION cryptSession );\n\n\t\t\tstatus = sftpServer( cryptSession );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"SVR: Couldn't receive SFTP data \"\n\t\t\t\t\t\t \"from client, status %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tfputs( \"SVR: SFTP server session succeeded.\\n\\n\", outputStream );\n\t\t\tfflush( outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tint sftpClient( const CRYPT_SESSION cryptSession );\n\n\t\t\tstatus = sftpClient( cryptSession );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't send SFTP data to server, \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\tfputs( \"SFTP client session succeeded.\\n\\n\", outputStream );\n\t\t\tfflush( outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\t}\n#endif /* WINDOWS_THREADS && 0 */\n\n#ifdef USE_SSH_EXTENDED\n\t/* If we're performing a multi-channel test, open a second channel (the\n\t   server handles this as part of its general connect-handling) */\n\tif( ( testType == SSH_TEST_MULTICHANNEL || \\\n\t\t  testType == SSH_TEST_CORRUPT_CHANNEL_CLOSE || \\\n\t\t  testType == SSH_TEST_CORRUPT_CHANNEL_REQUEST ) && !isServer )\n\t\t{\n\t\tstatus = createChannel( cryptSession, TEXT( \"direct-tcpip\" ),\n\t\t\t\t\t\t\t\tTEXT( \"localhost:5678\" ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSH_CHANNEL,\n\t\t\t\t\t\t\t\t\t\t&channel );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,\n\t\t\t\t\t\t\t\t\t\tTRUE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't open second SSH chanel, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfprintf( outputStream, \"Opened additional channel #%d to server.\\n\", \n\t\t\t\t channel );\n\t\tfflush( outputStream );\n\t\t}\n#endif /* USE_SSH_EXTENDED */\n\n\t/* Send data over the SSH link */\n\tif( isServer )\n\t\t{\n\t\t/* Send a status message to the client */\n\t\tstrcpy( buffer, \"Welcome to cryptlib, now go away.\\r\\n\" );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\tbufferToAscii( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\tstatus = cryptPushData( cryptSession, buffer, strlen( buffer ), \n\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptSession );\n\t\tif( cryptStatusError( status ) || bytesCopied != strlen( buffer ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: Couldn't send data to client, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Wait a bit while data arrives */\n\tdelayThread( 2 );\n\n\t/* Print the first lot of output from the other side */\n\tstatus = printDataInfo( cryptSession, buffer, &bytesCopied, isServer, \n\t\t\t\t\t\t\tisErrorTest );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* Some tests are meant to fail because they check failure \n\t\t   conditions, if we encounter one of these then we exit cleanly */\n\t\tif( status == SENTINEL )\n\t\t\t{\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we're the server, echo the command to the client */\n\tif( isServer )\n\t\t{\n\t\tconst int clientBytesCopied = bytesCopied;\n\t\tint dummy, i;\n\n\t\t/* If it's a multi-channel test, send the response back on a\n\t\t   different channel.  The currently-selected channel will be the\n\t\t   last one that the client opened (#2), so we can hardcode in\n\t\t   #1 for testing purposes */\n\t\tif( testType == SSH_TEST_MULTICHANNEL || \\\n\t\t\ttestType == SSH_TEST_CORRUPT_CHANNEL_CLOSE || \\\n\t\t\ttestType == SSH_TEST_CORRUPT_CHANNEL_REQUEST )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSH_CHANNEL, 1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"SVR: Couldn't select channel #1 to \"\n\t\t\t\t\t\t \"return data to client, status %d, line %d.\\n\", \n\t\t\t\t\t\t status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\tfor( i = 0; i < clientBytesCopied; i++ )\n\t\t\t{\n\t\t\tif( buffer[ i ] < ' ' || buffer[ i ] >= 0x7F )\n\t\t\t\tbuffer[ i ] = '.';\n\t\t\t}\n\t\tstrcpy( buffer, \"Input was [\" );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\tbufferToAscii( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\tstatus = cryptPushData( cryptSession, buffer, strlen( buffer ), \n\t\t\t\t\t\t\t\t&dummy );\n\t\tif( cryptStatusOK( status ) && clientBytesCopied > 0 )\n\t\t\t{\n\t\t\tstatus = cryptPushData( cryptSession, buffer, clientBytesCopied,\n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstrcpy( buffer, \"]\\r\\n\" );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToAscii( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\tstatus = cryptPushData( cryptSession, buffer, strlen( buffer ), \n\t\t\t\t\t\t\t\t\t&dummy );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptSession );\n\t\tif( cryptStatusError( status ) || bytesCopied != clientBytesCopied )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: Couldn't send data to client, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* We're the client, if it's a session to a Unix ssh server, send a\n\t\t   sample command and display the output */\n\t\tif( !localSession )\n\t\t\t{\n\t\t\t/* Send a command to the server and get the results */\n\t\t\tstrcpy( buffer, \"ls -l | head -25\\n\" );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToAscii( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\tstatus = cryptPushData( cryptSession, buffer, strlen( buffer ),\n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\tbytesCopied != strlen( buffer ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't send data to server, \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tfputs( \"Sent 'ls -l | head -25'\", outputStream );\n\t\t\tdelayThread( 3 );\n\t\t\tstatus = printDataInfo( cryptSession, buffer, &bytesCopied, \n\t\t\t\t\t\t\t\t\tisServer, isErrorTest );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* It's a local session, just send a simple text string for\n\t\t\t   testing */\n\t\t\tstrcpy( buffer, \"Some test data\" );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToAscii( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\tstatus = cryptPushData( cryptSession, buffer, strlen( buffer ),\n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\tbytesCopied != strlen( buffer ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't send data to server, \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Make sure that we stay around long enough to get the\n\t\t\t   server's response */\n\t\t\tdelayThread( 1 );\n\n\t\t\t/* Print the server's response */\n\t\t\tstatus = printDataInfo( cryptSession, buffer, &bytesCopied, \n\t\t\t\t\t\t\t\t\tisServer, isErrorTest );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* If we're performing a multi-channel test, close the second channel */\n\tif( testType == SSH_TEST_MULTICHANNEL || \\\n\t\ttestType == SSH_TEST_CORRUPT_CHANNEL_CLOSE || \\\n\t\ttestType == SSH_TEST_CORRUPT_CHANNEL_REQUEST )\n\t\t{\n\t\tif( isServer )\n\t\t\t{\n\t\t\t/* Perform a dummy pop to process the channel close */\n\t\t\tstatus = cryptPopData( cryptSession, buffer, BUFFER_SIZE, \n\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession, \n\t\t\t\t\t\t\t   \"SVR: Processing of second channel close\", \n\t\t\t\t\t\t\t   status, __LINE__ );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Close the current channel */\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSH_CHANNEL_ACTIVE,\n\t\t\t\t\t\t\t\t\t\tFALSE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Couldn't close second SSH channel, \"\n\t\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tfprintf( outputStream, \"Closed second channel to server.\\n\" );\n\t\t\tfflush( outputStream );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDestroySession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* If we were expecting an error and got this far, this is in turn an \n\t   error */\n\tif( isErrorTest )\n\t\t{\n\t\tfputs( \"  (This test should have led to a failure but didn't, test \"\n\t\t\t   \"has failed).\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\tfputs( isServer ? \"SVR: SSH server session succeeded.\\n\\n\" : \\\n\t\t\t\t\t  \"SSH client session succeeded.\\n\\n\", outputStream );\n\tfflush( outputStream );\n\treturn( TRUE );\n\t}\n\nint testSessionSSH( void )\n\t{\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_NORMAL, FALSE ) );\n\t}\nint testSessionSSHPubkeyAuth( void )\n\t{\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PUBKEYAUTH, FALSE ) );\n\t}\nint testSessionSSHPubkeyAuthWrongKey( void )\n\t{\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PUBKEYAUTH_WRONGKEY, FALSE ) );\n\t}\nint testSessionSSHPubkeyAuthWrongName( void )\n\t{\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PUBKEYAUTH_WRONGNAME, FALSE ) );\n\t}\nint testSessionSSHPubkeyAuthPassword( void )\n\t{\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PUBKEYAUTH_PASSWORD, FALSE ) );\n\t}\nint testSessionSSHPortforward( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_PORTFORWARDING, FALSE ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSHExec( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_EXEC, FALSE ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSH_SFTP( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( connectSSH( CRYPT_SESSION_SSH, SSH_TEST_SUBSYSTEM, FALSE ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSHServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_CONFIRMAUTH, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionSSHServerPubkeyAuth( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_PUBKEYAUTH, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionSSH_SFTPServer( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSH( CRYPT_SESSION_SSH_SERVER, SSH_TEST_SUBSYSTEM, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall ssh2ServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n\tconnectSSH( CRYPT_SESSION_SSH_SERVER, argValue, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nstatic int sshClientServer( const SSH_TEST_TYPE testType )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = testType, status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, ssh2ServerThread, &arg, 0, \n\t\t\t\t\t\t\t\t\t\t &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSH( CRYPT_SESSION_SSH, testType, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nint testSessionSSHClientServer( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_NORMAL ) );\n\t}\nint testSessionSSHClientServerDsaKey( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_DSAKEY ) );\n\t}\nint testSessionSSHClientServerEccKey( void )\n\t{\n\t/* ECC algorithms may not be available so we only run this test if \n\t   they've been enabled */\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, \\\n\t\t\t\t\t\t\t  NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\treturn( TRUE );\n\n\treturn( sshClientServer( SSH_TEST_ECCKEY ) );\n\t}\nint testSessionSSHClientServerPubkeyAuth( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_PUBKEYAUTH ) );\n\t}\nint testSessionSSHClientServerPubkeyAuthWrongKey( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_PUBKEYAUTH_WRONGKEY ) );\n\t}\nint testSessionSSHClientServerPubkeyAuthWrongName( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_PUBKEYAUTH_WRONGNAME ) );\n\t}\nint testSessionSSHClientServerPubkeyAuthPassword( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_PUBKEYAUTH_PASSWORD ) );\n\t}\nint testSessionSSHClientServerFingerprint( void )\n\t{\n\t/* Note that this test tests the correct functioning of a refused\n\t   connection when an incorrect key fingerprint is used, so it's\n\t   supposed to fail */\n\treturn( sshClientServer( SSH_TEST_FINGERPRINT ) );\n\t}\nint testSessionSSHClientServerSFTP( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_SUBSYSTEM ) );\n\t}\nint testSessionSSHClientServerPortForward( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( sshClientServer( SSH_TEST_PORTFORWARDING ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSHClientServerExec( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( sshClientServer( SSH_TEST_EXEC ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSHClientServerMultichannel( void )\n\t{\n#ifdef USE_SSH_EXTENDED\n\treturn( sshClientServer( SSH_TEST_MULTICHANNEL ) );\n#else\n\treturn( TRUE );\n#endif /* USE_SSH_EXTENDED */\n\t}\nint testSessionSSHClientServerDualThread( void )\n\t{\n\treturn( sshClientServer( SSH_TEST_DUALTHREAD ) );\n\t}\nint testSessionSSHClientServerDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\tif( !sshClientServer( SSH_TEST_CORRUPT_HANDSHAKE ) )\n\t\treturn( FALSE );\t/* Detect corruption of handshake data */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_KEYEX_CLIENT ) )\n\t\treturn( FALSE );\t/* Detect corruption of client keyex */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_KEYEX_SERVER ) )\n\t\treturn( FALSE );\t/* Detect corruption of server keyex */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_EXCHANGE_HASH ) )\n\t\treturn( FALSE );\t/* Detect corruption of exchange hash */\n\tif( !sshClientServer( SSH_TEST_BADSIG_HASH ) )\n\t\treturn( FALSE );\t/* Detect corruption of hash for signature */\n\tif( !sshClientServer( SSH_TEST_BADSIG_SIG ) )\n\t\treturn( FALSE );\t/* Detect corruption of signature data */\n\tif( !sshClientServer( SSH_TEST_WRONG_CERT ) )\n\t\treturn( FALSE );\t/* Detect wrong key for server */\n#if 0\t/* See comments in fault.h */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_USERNAME ) )\n\t\treturn( FALSE );\t/* Detect wrong username */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_PASSWORD ) )\n\t\treturn( FALSE );\t/* Detect wrong username */\n#endif /* 0 */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_MAC ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload MAC */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_CHANNEL_OPEN ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_CHANNEL_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n#if 0\t/* See comments in fault.h */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_CHANNEL_CLOSE ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !sshClientServer( SSH_TEST_CORRUPT_CHANNEL_REQUEST ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n#endif /* 0 */\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSFTP Routines for SSH\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The following code re-uses internal parts of cryptlib, so it provides its\n   own dummy functions as stubs for cryptlib-internal ones.  Since this would\n   produce link errors when cryptlib is statically linked with the test\n   app, we only enable it for the threaded Windows (i.e. DLL) self-test */\n\n#if defined( WINDOWS_THREADS ) && 0\n\n/* The following code is a bare-bones SFTP implementation created purely for\n   interop/performance testing of cryptlib's SSH implementation.  It does\n   the bare minimum needed to set up an SFTP transfer, and shouldn't be used\n   for anything other than testing.\n\n   Rather than creating our own versions of code already present in cryptlib,\n   we pull in the cryptlib code wholesale here unless we've built cryptlib as\n   a static lib, in which case it'll already be present.  This is a pretty\n   ugly hack, but saves having to copy over a pile of cryptlib code.\n\n   Because cryptlib has an internal BYTE type, we need to no-op it out before\n   we pull in any cryptlib code */\n\n#undef BYTE\n#define BYTE\t_BYTE_DUMMY\n#ifdef BOOLEAN\n  #undef BOOLEAN\t/* May be a typedef or a #define */\n#endif /* BOOLEAN */\n#ifndef STATIC_LIB\n  #include \"enc_dec/misc_rw.c\"\n#endif /* Non-static lib cryptlib */\n#undef BYTE\n#define BYTE\tunsigned char\n\n/* Replacements for cryptlib stream routines */\n\n#define sMemDisconnect(\tstream )\n#define sMemConnect\t\t\t\t\tsMemOpen\n#define stell( stream )\t\t\t\t( ( stream )->bufPos )\n\nint sSetError( STREAM *stream, const int status )\n\t{\n\tstream->status = status;\n\treturn( status );\n\t}\n\nint sMemOpen( STREAM *stream, void *buffer, const int bufSize )\n\t{\n\tmemset( stream, 0, sizeof( STREAM ) );\n\tstream->buffer = ( void * ) buffer;\n\tstream->bufEnd = bufSize;\n\treturn( CRYPT_OK );\n\t}\n\nint sread( STREAM *stream, void *buffer, const int count )\n\t{\n\tif( stream->bufPos + count > stream->bufEnd )\n\t\t{\n\t\tsSetError( stream, CRYPT_ERROR_UNDERFLOW );\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\tmemcpy( buffer, stream->buffer + stream->bufPos, count );\n\tstream->bufPos += count;\n\treturn( CRYPT_OK );\n\t}\n\nint swrite( STREAM *stream, const void *buffer, const int count )\n\t{\n\tif( stream->buffer != NULL )\n\t\t{\n\t\tif( stream->bufPos + count > stream->bufEnd )\n\t\t\t{\n\t\t\tsSetError( stream, CRYPT_ERROR_OVERFLOW );\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\tmemcpy( stream->buffer + stream->bufPos, buffer, count );\n\t\t}\n\tstream->bufPos += count;\n\treturn( CRYPT_OK );\n\t}\n\nint sgetc( STREAM *stream )\n\t{\n\tint ch;\n\n\tif( stream->bufPos + 1 > stream->bufEnd )\n\t\t{\n\t\tsSetError( stream, CRYPT_ERROR_UNDERFLOW );\n\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t}\n\tch = stream->buffer[ stream->bufPos ];\n\tstream->bufPos++;\n\treturn( ch );\n\t}\n\nint sputc( STREAM *stream, const int data )\n\t{\n\tif( stream->buffer != NULL )\n\t\t{\n\t\tif( stream->bufPos + 1 > stream->bufEnd )\n\t\t\t{\n\t\t\tsSetError( stream, CRYPT_ERROR_OVERFLOW );\n\t\t\treturn( CRYPT_ERROR_OVERFLOW );\n\t\t\t}\n\t\tstream->buffer[ stream->bufPos++ ] = data;\n\t\t}\n\telse\n\t\tstream->bufPos++;\n\treturn( CRYPT_OK );\n\t}\n\nint sseek( STREAM *stream, const long position )\n\t{\n\treturn( 0 );\n\t}\n\nint sPeek( STREAM *stream )\n\t{\n\treturn( 0 );\n\t}\n\nint sSkip( STREAM *stream, const long offset )\n\t{\n\treturn( 0 );\n\t}\n\nint sMemDataLeft( const STREAM *stream )\n\t{\n\treturn( stream->bufSize - stream->bufPos );\n\t}\n\n/* Dummy routines needed in misc_rw.c */\n\nint BN_num_bits( const BIGNUM *a ) { return 0; }\nint BN_high_bit( BIGNUM *a ) { return 0; }\nBIGNUM *BN_bin2bn( const unsigned char *s, int len, BIGNUM *ret ) { return NULL; }\nint\tBN_bn2bin( const BIGNUM *a, unsigned char *to ) { return 0; }\nint importBignum( BIGNUM *bn, const void *buffer, const int length,\n\t\t\t\t  const int minLength, const int maxLength, \n\t\t\t\t  const BIGNUM *maxRange, const BOOLEAN checkKeysize ) { return -1; }\nint exportBignum( void *data, const int dataMaxLength, int *dataLength,\n\t\t\t\t  const void *bignumPtr ) { return -1; }\n\n/* SFTP command types */\n\n#define SSH_FXP_INIT\t\t\t1\n#define SSH_FXP_VERSION\t\t\t2\n#define SSH_FXP_OPEN\t\t\t3\n#define SSH_FXP_CLOSE\t\t\t4\n#define SSH_FXP_READ\t\t\t5\n#define SSH_FXP_WRITE\t\t\t6\n#define SSH_FXP_LSTAT\t\t\t7\n#define SSH_FXP_FSTAT\t\t\t8\n#define SSH_FXP_SETSTAT\t\t\t9\n#define SSH_FXP_FSETSTAT\t\t10\n#define SSH_FXP_OPENDIR\t\t\t11\n#define SSH_FXP_READDIR\t\t\t12\n#define SSH_FXP_REMOVE\t\t\t13\n#define SSH_FXP_MKDIR\t\t\t14\n#define SSH_FXP_RMDIR\t\t\t15\n#define SSH_FXP_REALPATH\t\t16\n#define SSH_FXP_STAT\t\t\t17\n#define SSH_FXP_RENAME\t\t\t18\n#define SSH_FXP_READLINK\t\t19\n#define SSH_FXP_SYMLINK\t\t\t20\n#define SSH_FXP_STATUS\t\t\t101\n#define SSH_FXP_HANDLE\t\t\t102\n#define SSH_FXP_DATA\t\t\t103\n#define SSH_FXP_NAME\t\t\t104\n#define SSH_FXP_ATTRS\t\t\t105\n\n/* SFTP attribute presence flags.  When these flags are set, the\n   corresponding file attribute value is present */\n\n#define SSH_FILEXFER_ATTR_SIZE\t\t\t0x01\n#define SSH_FILEXFER_ATTR_UIDGID\t\t0x02\n#define SSH_FILEXFER_ATTR_PERMISSIONSv3\t0x04\n#define SSH_FILEXFER_ATTR_ACMODTIME\t\t0x08\n#define SSH_FILEXFER_ATTR_ACCESSTIME\t0x08\n#define SSH_FILEXFER_ATTR_CREATETIME\t0x10\n#define SSH_FILEXFER_ATTR_MODIFYTIME\t0x20\n#define SSH_FILEXFER_ATTR_PERMISSIONSv4\t0x40\n#define SSH_FILEXFER_ATTR_ACL\t\t\t0x40\n#define SSH_FILEXFER_ATTR_OWNERGROUP\t0x80\n#define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x100\n#define SSH_FILEXFER_ATTR_EXTENDED\t\t0x80000000\n\n/* SFTP file open/create flags */\n\n#define SSH_FXF_READ\t\t\t0x01\n#define SSH_FXF_WRITE\t\t\t0x02\n#define SSH_FXF_APPEND\t\t\t0x04\n#define SSH_FXF_CREAT\t\t\t0x08\n#define SSH_FXF_TRUNC\t\t\t0x10\n#define SSH_FXF_EXCL\t\t\t0x20\n#define SSH_FXF_TEXT\t\t\t0x40\n\n/* SFTP file types */\n\n#define SSH_FILETYPE_REGULAR\t1\n#define SSH_FILETYPE_DIRECTORY\t2\n#define SSH_FILETYPE_SYMLINK\t3\n#define SSH_FILETYPE_SPECIAL\t4\n#define SSH_FILETYPE_UNKNOWN\t5\n\n/* SFTP status codes */\n\n#define SSH_FX_OK\t\t\t\t0\n#define SSH_FX_EOF\t\t\t\t1\n#define SSH_FX_NO_SUCH_FILE\t\t2\n#define SSH_FX_PERMISSION_DENIED 3\n#define SSH_FX_FAILURE\t\t\t4\n#define SSH_FX_BAD_MESSAGE\t\t5\n#define SSH_FX_NO_CONNECTION\t6\n#define SSH_FX_CONNECTION_LOST\t7\n#define SSH_FX_OP_UNSUPPORTED\t8\n#define SSH_FX_INVALID_HANDLE\t9\n#define SSH_FX_NO_SUCH_PATH\t\t10\n#define SSH_FX_FILE_ALREADY_EXISTS 11\n#define SSH_FX_WRITE_PROTECT\t12\n#define SSH_FX_NO_MEDIA\t\t\t13\n\n/* A structure to contain SFTP file attributes */\n\ntypedef struct {\n\tBOOLEAN isDirectory;\t\t/* Whether directory or normal file */\n\tlong size;\t\t\t\t\t/* File size */\n\tint permissions;\t\t\t/* File permissions */\n\ttime_t ctime, atime, mtime;\t/* File create, access, mod times */\n\t} SFTP_ATTRS;\n\n/* A structure to contain SFTP session information */\n\n#define MAX_HANDLE_SIZE\t\t16\n\ntypedef struct {\n\tint version;\t\t\t\t/* SFTP protocol version */\n\tlong id;\t\t\t\t\t/* Session ID */\n\tBYTE handle[ MAX_HANDLE_SIZE ];\t/* File handle */\n\tint handleSize;\n\t} SFTP_INFO;\n\n/* Read/write SFTP attributes.  This changed completely from v3 to v4, so we\n   have to treat them as special-cases:\n\n\tuint32\t\tflags\n\tbyte\t\tfile_type\n\tuint64\t\tsize (present if ATTR_SIZE)\n\tstring\t\towner (present if ATTR_OWNERGROUP)\n\tstring\t\tgroup (present if ATTR_OWNERGROUP)\n\tuint32\t\tpermissions (present if ATTR_PERMISSIONS)\n\tuint64\t\tatime (present if ATTR_ACCESSTIME)\n\tuint32\t\tatime_nseconds (present if ATTR_SUBSECOND_TIMES)\n\tuint64\t\tcreatetime (present if ATTR_CREATETIME)\n\tuint32\t\tcreatetime_nseconds (present if ATTR_SUBSECOND_TIMES)\n\tuint64\t\tmtime (present if ATTR_MODIFYTIME)\n\tuint32\t\tmtime_nseconds (present if ATTR_SUBSECOND_TIMES)\n\tstring\t\tacl (present if ATTR_ACL)\n\tuint32\t\textended_count (present if ATTR_EXTENDED)\n\t\tstring\textended_type\n\t\tstring\textended_value\n   \t\t[ extended_count type/value pairs ] */\n\nstatic int sizeofAttributes( SFTP_ATTRS *attributes, const int version )\n\t{\n\tint size = UINT32_SIZE;\t/* Flags */\n\n\tif( version < 4 )\n\t\t{\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\tsize += UINT64_SIZE;\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\tsize += UINT32_SIZE;\n\t\tif( attributes->atime )\n\t\t\tsize += UINT32_SIZE;\n\t\tif( attributes->mtime )\n\t\t\tsize += UINT32_SIZE;\n\t\t}\n\telse\n\t\t{\n\t\tsize++;\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\tsize += UINT64_SIZE;\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\tsize += UINT32_SIZE;\n\t\tif( attributes->ctime )\n\t\t\tsize += UINT64_SIZE;\n\t\tif( attributes->atime )\n\t\t\tsize += UINT64_SIZE;\n\t\tif( attributes->mtime )\n\t\t\tsize += UINT64_SIZE;\n\t\t}\n\n\treturn( size );\n\t}\n\nstatic int readAttributes( STREAM *stream, SFTP_ATTRS *attributes, const int version )\n\t{\n\tlong flags;\n\n\tmemset( attributes, 0, sizeof( SFTP_ATTRS ) );\n\tattributes->permissions = CRYPT_UNUSED;\n\tattributes->size = CRYPT_UNUSED;\n\n\t/* Read basic attribute information: File size, and owner, and\n\t   permissions */\n\tflags = readUint32( stream );\n\tif( cryptStatusError( flags ) )\n\t\treturn( flags );\n\tif( version < 4 )\n\t\t{\n\t\tif( flags & SSH_FILEXFER_ATTR_SIZE )\n\t\t\treadUint64( stream, &attributes->size );\n\t\tif( flags & SSH_FILEXFER_ATTR_UIDGID )\n\t\t\t{\n\t\t\treadUint32( stream );\n\t\t\treadUint32( stream );\n\t\t\t}\n\t\tif( flags & SSH_FILEXFER_ATTR_PERMISSIONSv3 )\n\t\t\tattributes->permissions = readUint32( stream );\n\n\t\t/* Read file access and modify times */\n\t\tif( flags & SSH_FILEXFER_ATTR_ACMODTIME )\n\t\t\t{\n\t\t\treadUint32Time( stream, &attributes->atime );\n\t\t\treadUint32Time( stream, &attributes->mtime );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( flags & SSH_FILEXFER_ATTR_SIZE )\n\t\t\treadUint64( stream, &attributes->size );\n\t\tif( flags & SSH_FILEXFER_ATTR_OWNERGROUP )\n\t\t\t{\n\t\t\treadString32( stream, NULL, 0, NULL );\n\t\t\treadString32( stream, NULL, 0, NULL );\n\t\t\t}\n\t\tif( flags & SSH_FILEXFER_ATTR_PERMISSIONSv4 )\n\t\t\tattributes->permissions = readUint32( stream );\n\n\t\t/* Read file create, access, and modify times */\n\t\tif( flags & SSH_FILEXFER_ATTR_ACCESSTIME )\n\t\t\t{\n\t\t\treadUint64Time( stream, &attributes->atime );\n\t\t\tif( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )\n\t\t\t\treadUint32( stream );\n\t\t\t}\n\t\tif( flags & SSH_FILEXFER_ATTR_CREATETIME )\n\t\t\t{\n\t\t\treadUint64Time( stream, &attributes->ctime );\n\t\t\tif( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )\n\t\t\t\treadUint32( stream );\n\t\t\t}\n\t\tif( flags & SSH_FILEXFER_ATTR_MODIFYTIME )\n\t\t\t{\n\t\t\treadUint64Time( stream, &attributes->mtime );\n\t\t\tif( flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES )\n\t\t\t\treadUint32( stream );\n\t\t\t}\n\t\t}\n\n\t/* Read ACLs and extended attribute type/value pairs, the one thing that\n\t   stayed the same from v3 to v4 */\n\tif( flags & SSH_FILEXFER_ATTR_ACL )\n\t\treadString32( stream, NULL, 0, NULL );\n\tif( flags & SSH_FILEXFER_ATTR_EXTENDED )\n\t\t{\n\t\tint extAttrCount = readUint32( stream );\n\n\t\tif( cryptStatusError( extAttrCount ) )\n\t\t\treturn( extAttrCount );\n\t\twhile( extAttrCount > 0 )\n\t\t\t{\n\t\t\treadString32( stream, NULL, 0, NULL );\n\t\t\treadString32( stream, NULL, 0, NULL );\n\t\t\textAttrCount--;\n\t\t\t}\n\t\t}\n\n\treturn( sGetStatus( stream ) );\n\t}\n\nstatic int writeAttributes( STREAM *stream, SFTP_ATTRS *attributes, const int version )\n\t{\n\tint flags = 0;\n\n\tif( version < 4 )\n\t\t{\n\t\t/* Indicate which attribute values we're going to write */\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\tflags |= SSH_FILEXFER_ATTR_SIZE;\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\tflags |= SSH_FILEXFER_ATTR_PERMISSIONSv3;\n\t\tif( attributes->atime )\n\t\t\tflags |= SSH_FILEXFER_ATTR_ACMODTIME;\n\t\twriteUint32( stream, flags );\n\n\t\t/* Write the optional attributes */\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\twriteUint64( stream, attributes->size );\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\twriteUint32( stream, attributes->permissions );\n\t\tif( attributes->atime )\n\t\t\t{\n\t\t\twriteUint32Time( stream, attributes->atime );\n\t\t\twriteUint32Time( stream, attributes->mtime );\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Indicate which attribute values we're going to write */\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\tflags |= SSH_FILEXFER_ATTR_SIZE;\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\tflags |= SSH_FILEXFER_ATTR_PERMISSIONSv4;\n\t\tif( attributes->ctime )\n\t\t\tflags |= SSH_FILEXFER_ATTR_CREATETIME;\n\t\tif( attributes->atime )\n\t\t\tflags |= SSH_FILEXFER_ATTR_ACCESSTIME;\n\t\tif( attributes->mtime )\n\t\t\tflags |= SSH_FILEXFER_ATTR_MODIFYTIME;\n\t\twriteUint32( stream, flags );\n\t\tsputc( stream, attributes->isDirectory ? \\\n\t\t\t\t\t   SSH_FILETYPE_DIRECTORY : SSH_FILETYPE_REGULAR );\n\n\t\t/* Write the optional attributes */\n\t\tif( attributes->size != CRYPT_UNUSED )\n\t\t\twriteUint64( stream, attributes->size );\n\t\tif( attributes->permissions != CRYPT_UNUSED )\n\t\t\twriteUint32( stream, attributes->permissions );\n\t\tif( attributes->ctime )\n\t\t\twriteUint64Time( stream, attributes->ctime );\n\t\tif( attributes->atime )\n\t\t\twriteUint64Time( stream, attributes->atime );\n\t\tif( attributes->mtime )\n\t\t\twriteUint64Time( stream, attributes->mtime );\n\t\t}\n\n\treturn( sGetStatus( stream ) );\n\t}\n\n/* Read/write SFTP status:\n\n\tuint32\t\tid\n\tuint32\t\terror/status code\n\tstring\t\terror message (ISO-10646 UTF-8 [RFC-2279])\n\tstring\t\tlanguage tag (as defined in [RFC-1766]) */\n\nstatic int sizeofStatus( const char *sshStatusString )\n\t{\n\treturn( UINT32_SIZE + UINT32_SIZE + \\\n\t\t\t( UINT32_SIZE + strlen( sshStatusString ) ) + \\\n\t\t\tUINT32_SIZE );\n\t}\n\nstatic int readStatus( STREAM *stream, SFTP_INFO *info )\n\t{\n\tstatic const struct {\n\t\tconst int sftpStatus, cryptlibStatus;\n\t\t} sftpStatusMap[] = {\n\t\t{ SSH_FX_OK, CRYPT_OK },\n\t\t{ SSH_FX_EOF, CRYPT_ERROR_COMPLETE },\n\t\t{ SSH_FX_NO_SUCH_FILE, CRYPT_ERROR_NOTFOUND },\n\t\t{ SSH_FX_PERMISSION_DENIED, CRYPT_ERROR_PERMISSION },\n\t\t{ SSH_FX_FAILURE, CRYPT_ERROR_FAILED },\n\t\t{ SSH_FX_BAD_MESSAGE, CRYPT_ERROR_BADDATA },\n\t\t{ SSH_FX_NO_CONNECTION, CRYPT_ERROR_FAILED },\n\t\t{ SSH_FX_CONNECTION_LOST, CRYPT_ERROR_FAILED },\n\t\t{ SSH_FX_OP_UNSUPPORTED, CRYPT_ERROR_NOTAVAIL },\n\t\t{ SSH_FX_INVALID_HANDLE, CRYPT_ERROR_BADDATA },\n\t\t{ SSH_FX_NO_SUCH_PATH, CRYPT_ERROR_NOTFOUND },\n\t\t{ SSH_FX_FILE_ALREADY_EXISTS, CRYPT_ERROR_DUPLICATE },\n\t\t{ SSH_FX_WRITE_PROTECT, CRYPT_ERROR_PERMISSION },\n\t\t{ SSH_FX_NO_MEDIA, CRYPT_ERROR_FAILED },\n\t\t{ CRYPT_ERROR, CRYPT_ERROR_FAILED }\n\t\t};\n\tint value, i, status;\n\n\t/* Read the status info and make sure that it's valid */\n\tvalue = readUint32( stream );\n\tstatus = readUint32( stream );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( value != info->id )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\n\t/* Translate the SFTP status into a cryptlib status */\n\tfor( i = 0; sftpStatusMap[ i ].sftpStatus != CRYPT_ERROR && \\\n\t\t\t\tsftpStatusMap[ i ].sftpStatus != status; i++ );\n\tstatus = sftpStatusMap[ i ].cryptlibStatus;\n\n\treturn( status );\n\t}\n\nstatic int writeStatus( STREAM *stream, SFTP_INFO *info, const int sshStatus,\n\t\t\t\t\t\tconst char *sshStatusString )\n\t{\n\twriteUint32( stream, info->id );\n\twriteUint32( stream, sshStatus );\n\twriteString32( stream, sshStatusString, strlen( sshStatusString ) );\n\treturn( writeString32( stream, \"\", 0 ) );\n\t}\n\nstatic int readSftpPacket( const CRYPT_SESSION cryptSession, void *buffer,\n\t\t\t\t\t\t   const int bufSize )\n\t{\n\tint bytesCopied, status;\n\n\tstatus = cryptPopData( cryptSession, buffer, BUFFER_SIZE, &bytesCopied );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Couldn't read data from SFTP client, \"\n\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\treturn( bytesCopied > 0 ? bytesCopied : CRYPT_ERROR_UNDERFLOW );\n\t}\n\nstatic int writeSftpPacket( const CRYPT_SESSION cryptSession, const void *data,\n\t\t\t\t\t\t\tconst int length )\n\t{\n\tint bytesCopied, status;\n\n\tstatus = cryptPushData( cryptSession, data, length, &bytesCopied );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptFlushData( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Couldn't write data to SFTP client, \"\n\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tif( bytesCopied < length )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Only wrote %d of %d bytes of SFTP \"\n\t\t\t\t \"data, line %d.\\n\", bytesCopied, length, __LINE__ );\n\t\treturn( status );\n\t\t}\n\treturn( CRYPT_OK );\n\t}\n\nstatic int sendAck( const CRYPT_SESSION cryptSession, SFTP_INFO *sftpInfo )\n\t{\n\tSTREAM stream;\n\tBYTE buffer[ 128 ];\n\tint length;\n\n\t/* Ack an SFTP packet */\n\tsMemOpen( &stream, buffer, 128 );\n\twriteUint32( &stream, 1 + sizeofStatus( \"\" ) );\n\tsputc( &stream, SSH_FXP_STATUS );\n\twriteStatus( &stream, sftpInfo, SSH_FX_OK, \"\" );\n\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\treturn( writeSftpPacket( cryptSession, buffer, length ) );\n\t}\n\nint sftpServer( const CRYPT_SESSION cryptSession )\n\t{\n\tSTREAM stream;\n\tSFTP_ATTRS sftpAttrs;\n\tSFTP_INFO sftpInfo;\n\tBYTE buffer[ BUFFER_SIZE ], nameBuffer[ 128 ];\n\ttime_t xferTime;\n\tlong xferCount = 0, dataLength;\n\tint length, value, status;\n\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT, 30 );\n\n\tmemset( &sftpInfo, 0, sizeof( SFTP_INFO ) );\n\n\t/* Read the client's FXP_INIT and send our response */\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, buffer, status );\n\tlength = readUint32( &stream );\n\tvalue = sgetc( &stream );\n\tif( ( length != 1 + 4 ) || ( value != SSH_FXP_INIT ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tsftpInfo.version = readUint32( &stream );\n\tsMemDisconnect( &stream );\n\tfprintf( outputStream, \"SVR: Client supports SFTP version %d.\\n\", \n\t\t\t sftpInfo.version );\n\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\twriteUint32( &stream, 1 + 4 );\n\tsputc( &stream, SSH_FXP_VERSION );\n\twriteUint32( &stream, 3 );\n\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tstatus = writeSftpPacket( cryptSession, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Read the client's FXP_OPEN and send our response */\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"SVR: Attempt to read data from \"\n\t\t\t\t\t   \"client\", status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tsMemConnect( &stream, buffer, status );\n\tlength = readUint32( &stream );\n\tvalue = sgetc( &stream );\n\tif( value == SSH_FXP_STAT )\n\t\t{\n\t\t/* See what the client is after */\n\t\tsftpInfo.id = readUint32( &stream );\n\t\tlength = readUint32( &stream );\n\t\tsread( &stream, nameBuffer, length );\n\t\tsMemDisconnect( &stream );\n\t\tnameBuffer[ length ] = '\\0';\n\t\tfprintf( outputStream, \"SVR: Client tried to stat file '%s'.\\n\", \n\t\t\t\t nameBuffer );\n\t\tif( strcmp( nameBuffer, \".\" ) )\n\t\t\t{\n\t\t\tfputs( \"SVR: Don't know how to respond to stat request for this \"\n\t\t\t\t   \"file.\", outputStream );\n\t\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\t\t\t}\n\n\t\t/* Send back a dummy response */\n\t\tmemset( &sftpAttrs, 0, sizeof( SFTP_ATTRS ) );\n\t\tsftpAttrs.isDirectory = TRUE;\n\t\tsftpAttrs.permissions = 0777;\n\t\tsftpAttrs.size = CRYPT_UNUSED;\n\t\tsftpAttrs.atime = sftpAttrs.ctime = sftpAttrs.mtime = time( NULL );\n\t\tlength = sizeofAttributes( &sftpAttrs, sftpInfo.version );\n\t\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\t\twriteUint32( &stream, 1 + UINT32_SIZE + length );\n\t\tsputc( &stream, SSH_FXP_ATTRS );\n\t\twriteUint32( &stream, sftpInfo.id );\n\t\twriteAttributes( &stream, &sftpAttrs, sftpInfo.version );\n\t\tlength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tstatus = writeSftpPacket( cryptSession, buffer, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* See what they want next */\n\t\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"SVR: Attempt to read data from \"\n\t\t\t\t\t\t   \"client\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\tsMemConnect( &stream, buffer, status );\n\t\tlength = readUint32( &stream );\n\t\tvalue = sgetc( &stream );\n\t\t}\n\tif( value == SSH_FXP_OPEN )\n\t\t{\n\t\t/* See what the client is after */\n\t\tsftpInfo.id = readUint32( &stream );\n\t\tlength = readUint32( &stream );\n\t\tsread( &stream, nameBuffer, length );\n\t\tvalue = readUint32( &stream );\n\t\treadAttributes( &stream, &sftpAttrs, sftpInfo.version );\n\t\tsMemDisconnect( &stream );\n\t\tnameBuffer[ length ] = '\\0';\n\t\tfprintf( outputStream, \"Client tried to open file '%s', mode %02X, \"\n\t\t\t\t \"length %d.\\n\", nameBuffer, value, sftpAttrs.size );\n\n\t\t/* Putty for some reason tries to open the current directory for\n\t\t   create (rather than the filename), and bails out when it gets a\n\t\t   permission-denied.  So I guess we tell it to go ahead... */\n\t\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\t\twriteUint32( &stream, 1 + UINT32_SIZE + ( UINT32_SIZE + 1 ) );\n\t\tsputc( &stream, SSH_FXP_HANDLE );\n\t\twriteUint32( &stream, sftpInfo.id );\n\t\twriteUint32( &stream, 1 );\n\t\tsputc( &stream, 1 );\n\t\tlength = stell( &stream );\n\t\tsMemDisconnect( &stream );\n\t\tstatus = writeSftpPacket( cryptSession, buffer, length );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Now we're in the write loop... */\n\txferTime = time( NULL );\n\tdataLength = 0;\n\twhile( TRUE )\n\t\t{\n\t\t/* See what they want next */\n\t\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"SVR: Attempt to read data from \"\n\t\t\t\t\t\t   \"client\", status, __LINE__ );\n\t\t\treturn( status );\n\t\t\t}\n\t\tif( status < 1 )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: Read 0 bytes from client.\\n\" );\n\t\t\treturn( CRYPT_ERROR_UNDERFLOW );\n\t\t\t}\n\t\tif( dataLength > 0 )\n\t\t\t{\n\t\t\txferCount += status;\n\t\t\tdataLength -= status;\n\t\t\tfprintf( outputStream, \"SRV: -------- : %d.\\r\", xferCount );\n\t\t\tif( dataLength <= 0 )\n\t\t\t\tbreak;\n\t\t\tcontinue;\n\t\t\t}\n\t\tsMemConnect( &stream, buffer, status );\n\t\tlength = readUint32( &stream );\n\t\tif( status < BUFFER_SIZE && ( length != status - UINT32_SIZE ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Didn't read complete packet, \"\n\t\t\t\t\t \"length = %d, byte count = %d.\\n\", length, \n\t\t\t\t\t status - UINT32_SIZE );\n\t\t\t}\n\t\tvalue = sgetc( &stream );\n\t\tif( value != SSH_FXP_WRITE )\n\t\t\tbreak;\n\t\tsftpInfo.id = readUint32( &stream );\n\t\treadString32( &stream, nameBuffer, 128, &length );\n\t\treadUint64( &stream, &value );\n\t\tdataLength = readUint32( &stream );\n\t\tfprintf( outputStream, \"SRV: %8d : %d.\\r\", value, length );\n\t\txferCount += status - stell( &stream );\n\t\tdataLength -= status - stell( &stream );\n\t\tsMemDisconnect( &stream );\n\n\t\t/* Ack the write */\n\t\tif( dataLength <= 0 )\n\t\t\t{\n\t\t\tstatus = sendAck( cryptSession, &sftpInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\t}\n\txferTime = time( NULL ) - xferTime;\n\tfprintf( outputStream, \"Transfer time = %d seconds, %ld bytes, \"\n\t\t\t \"%d bytes/sec.\\n\", xferTime, xferCount, \n\t\t\t xferCount / xferTime );\n\n\t/* Clean up */\n\tif( value != SSH_FXP_CLOSE )\n\t\t{\n\t\tfprintf( outputStream, \"SVR: Client sent unexpected packet %d.\\n\", \n\t\t\t\t value );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\tsftpInfo.id = readUint32( &stream );\n\tstatus = sendAck( cryptSession, &sftpInfo );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( status == CRYPT_ERROR_COMPLETE )\n\t\t{\n\t\tfputs( \"SVR: Client has closed the channel.\", outputStream );\n\t\treturn( CRYPT_OK );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, buffer, status );\n\tlength = readUint32( &stream );\n\tvalue = sgetc( &stream );\n\n\treturn( CRYPT_OK );\n\t}\n\n#define SFTP_DATA_AMOUNT\t( 1024 * 1024 )\n\nint sftpClient( const CRYPT_SESSION cryptSession )\n\t{\n\tSTREAM stream;\n\tSFTP_ATTRS sftpAttrs;\n\tSFTP_INFO sftpInfo;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tlong totalLength = SFTP_DATA_AMOUNT;\n\tint length, value, status;\n\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT, 30 );\n\n\tmemset( &sftpInfo, 0, sizeof( SFTP_INFO ) );\n\n\t/* Send our FXP_INIT and read back the response */\n\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\twriteUint32( &stream, 1 + 4 );\n\tsputc( &stream, SSH_FXP_INIT );\n\twriteUint32( &stream, 3 );\n\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tstatus = writeSftpPacket( cryptSession, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tsMemConnect( &stream, buffer, status );\n\tlength = readUint32( &stream );\n\tvalue = sgetc( &stream );\n\tif( ( length != 1 + 4 ) || ( value != SSH_FXP_VERSION ) )\n\t\treturn( CRYPT_ERROR_BADDATA );\n\tsftpInfo.version = readUint32( &stream );\n\tsMemDisconnect( &stream );\n\tfprintf( outputStream, \"Server supports SFTP version %d.\\n\", \n\t\t\t sftpInfo.version );\n\n\t/* Open the file to transfer */\n\tmemset( &sftpAttrs, 0, sizeof( SFTP_ATTRS ) );\n\tsftpAttrs.permissions = 0777;\n\tsftpAttrs.size = CRYPT_UNUSED;\n\tsftpAttrs.atime = sftpAttrs.ctime = sftpAttrs.mtime = time( NULL );\n\tlength = sizeofAttributes( &sftpAttrs, sftpInfo.version );\n\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\twriteUint32( &stream, 1 + UINT32_SIZE + ( UINT32_SIZE + 8 ) + UINT32_SIZE + length );\n\tsputc( &stream, SSH_FXP_OPEN );\n\twriteUint32( &stream, 1 );\n\twriteString32( &stream, \"test.dat\", 8 );\n\twriteUint32( &stream, SSH_FXF_CREAT | SSH_FXF_WRITE\t);\n\twriteAttributes( &stream, &sftpAttrs, sftpInfo.version );\n\tlength = stell( &stream );\n\tsMemDisconnect( &stream );\n\tstatus = writeSftpPacket( cryptSession, buffer, length );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"Attempt to read data from server\",\n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\tsMemConnect( &stream, buffer, status );\n\tlength = readUint32( &stream );\n\tvalue = sgetc( &stream );\n\treadUint32( &stream );\n\treadString32( &stream, sftpInfo.handle, MAX_HANDLE_SIZE, \n\t\t\t\t  &sftpInfo.handleSize );\n\tsMemDisconnect( &stream );\n\tif( value != SSH_FXP_HANDLE )\n\t\t{\n\t\tfprintf( outputStream, \"Server sent packet %d, expected file \"\n\t\t\t\t \"handle.\\n\", value );\n\t\treturn( CRYPT_ERROR_BADDATA );\n\t\t}\n\n\t/* Send the file (just 1MB of test data) */\n\tsMemOpen( &stream, buffer, BUFFER_SIZE );\n\twriteUint32( &stream, 1 + UINT32_SIZE + \\\n\t\t\t\t\t\t  ( UINT32_SIZE + sftpInfo.handleSize ) + \\\n\t\t\t\t\t\t  UINT64_SIZE + ( UINT32_SIZE + SFTP_DATA_AMOUNT ) );\n\tsputc( &stream, SSH_FXP_WRITE );\n\twriteUint32( &stream, sftpInfo.id );\n\twriteString32( &stream, sftpInfo.handle, sftpInfo.handleSize );\n\twriteUint64( &stream, 0 );\n\twriteUint32( &stream, SFTP_DATA_AMOUNT );\n\tlength = stell( &stream );\n\tmemset( buffer + length, '*', BUFFER_SIZE - length );\n\tstatus = writeSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\ttotalLength -= BUFFER_SIZE - length;\n\twhile( totalLength > 0 )\n\t\t{\n\t\tmemset( buffer, '*', BUFFER_SIZE );\n\t\tstatus = writeSftpPacket( cryptSession, buffer,\n\t\t\t\t\t\t\t\t  min( totalLength, BUFFER_SIZE ) );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\ttotalLength -= min( totalLength, BUFFER_SIZE );\n\t\t}\n\n\t/* Wait for the ack */\n\tstatus = readSftpPacket( cryptSession, buffer, BUFFER_SIZE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptSession, \"Attempt to read data from server\",\n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( status );\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n#endif /* WINDOWS_THREADS && 0 */\n\n#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */\n"
  },
  {
    "path": "deps/cl345/test/ssl.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tcryptlib SSL/TLS Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1998-2017\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\n#ifndef NDEBUG\n  #include \"misc/analyse.h\"\t\t/* Needed for fault.h */\n  #include \"misc/fault.h\"\n#endif /* !NDEBUG */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n#if defined( __MVS__ )\n  /* MVS control section (CSECT) names default to the file name and can't\n\t match any symbol name either in the file or in another file or library \n\t (e.g. write.c vs. write()).  Because of this we have to explicitly \n\t name the csect's so that they don't conflict with external symbol\n\t names */\n  #pragma csect( CODE, \"testSSLC\" )\n  #pragma csect( STATIC, \"testSSLS\" )\n  #pragma csect( TEST, \"testSSLT\" )\n#endif /* __MVS__ */\n\n/* SSL/TLS gets a bit complicated because in the presence of the session \n   cache every session after the first one will be a resumed session.  To \n   deal with this, the VC++ 6 debug build disables the client-side session \n   cache, while every other version just ends up going through a series \n   of session resumes.\n   \n   Note that changing the follow requires an equivalent change in \n   session/ssl_cli.c */\n\n#if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && \\\n\t!defined( NDEBUG ) && 1\n  #define NO_SESSION_CACHE\n#endif /* VC++ 6.0 debug build */\n\n/* We can run the SSL/TLS self-test with a large variety of options, rather \n   than using dozens of boolean option flags to control them all we define \n   various test classes that exercise each option type.\n   \n   Two of the tests aren't run as part of the normal self-test since their \n   use of random threads results in somewhat nondeterministic behaviour that \n   would require extensive extra locking to resolve.  SSL_TEST_DUALTHREAD \n   starts the SSL server with one thread and has the server session return \n   control to the caller for the password check.  The initial server thread \n   then exits and a second thread takes over for the rest of the connect.\n\n   SSL_TEST_MULTITHREAD is just a multithreaded client and server test. \n   This is even more nondeterministic, with thread pileups possible due to \n   the lack of extensive locking on the client side.\n\n   For SSL_TEST_CLIENTCERT against the Windows interop server, the test \n   server client-auth key needs to be converted to PKCS #15 format since it \n   uses a too-short password in the original Microsoft-provided file.  To do \n   this, in mechs/mech_drv.c, initDSP() add the following kludge:\n\n\t*( ( int * ) &keyLength ) = 1;\n\n   and then use the following code:\n\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT cryptContext;\n\n\tcryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, \n\t\t\t\t\t \"r:/woodgrove.p12\", CRYPT_KEYOPT_READONLY );\n\tcryptGetPrivateKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME, \n \t\t\t\t\t\tTEXT( \"test\" ), TEXT( \"11\" ) );\n\tcryptKeysetClose( cryptKeyset );\n\tcryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, \n\t\t\t\t\t TEST_PRIVKEY_TMP_FILE, CRYPT_KEYOPT_CREATE );\n\tcryptAddPrivateKey( cryptKeyset, cryptContext, TEST_PRIVKEY_PASSWORD );\n\tcryptKeysetClose( cryptKeyset );\n\tcryptDestroyContext( cryptContext );\n\t} */\n\ntypedef enum {\n\tSSL_TEST_NONE,\t\t\t\t/* No SSL/TLS test type */\n\tSSL_TEST_NORMAL,\t\t\t/* Standard SSL/TLS test */\n\tSSL_TEST_BULKTRANSER,\t\t/* Bulk data transfer */\n\tSSL_TEST_CLIENTCERT,\t\t/* User auth.with client certificate */\n\tSSL_TEST_CLIENTCERT_MANUAL,\t/* User auth.client certificate manual verif.*/\n\tSSL_TEST_PSK,\t\t\t\t/* User auth.with shared key */\n\tSSL_TEST_PSK_SVRONLY,\t\t/* Client = no PSK, server = TLS-PSK */\n\tSSL_TEST_PSK_CLIONLY,\t\t/* Client = TLS-PSK, server = no PSK */\n\tSSL_TEST_PSK_WRONGKEY,\t\t/* User auth.with incorrect shared key */\n\tSSL_TEST_ECC,\t\t\t\t/* Use ECC instead of RSA/DH */\n\tSSL_TEST_ECC_P384,\t\t\t/* Use ECC P384 instead of P256 */\n\tSSL_TEST_STARTTLS,\t\t\t/* Local client socket speaking STARTTLS/STLS/AUTH TLS */\n\tSSL_TEST_LOCALSERVER,\t\t/* Local server socket */\n\tSSL_TEST_RESUME,\t\t\t/* Session resumption */\n\tSSL_TEST_DUALTHREAD,\t\t/* Two-phase connect via different threads */\n\tSSL_TEST_MULTITHREAD,\t\t/* Multiple server threads */\n\tSSL_TEST_WEBSOCKETS,\t\t/* WebSockets over TLS */\n\tSSL_TEST_EAPTTLS,\t\t\t/* EAP-TTLS */\n\tSSL_TEST_BADSSL_DH512,\t\t/* BadSSL tests */\n\tSSL_TEST_BADSSL_DH1024,\n\tSSL_TEST_BADSSL_DH2048,\n\tSSL_TEST_BADSSL_DHSMALLSUBGROUP,\n\tSSL_TEST_BADSSL_DHCOMPOSITE,\n\tSSL_TEST_BADSSL_STATICRSA,\n\tSSL_TEST_BADSSL_RSA2048,\n\tSSL_TEST_BADSSL_ECC256,\n\tSSL_TEST_BADSSL_CBC,\n\tSSL_TEST_BADSSL_RC4MD5,\n\tSSL_TEST_BADSSL_RC4,\n\tSSL_TEST_BADSSL_3DES,\n\tSSL_TEST_BADSSL_NOCN,\n\tSSL_TEST_BADSSL_NOSUBJECT,\n\tSSL_TEST_BADSSL_LONGNAME1,\n\tSSL_TEST_BADSSL_LONGNAME2,\n\tSSL_TEST_CORRUPT_HANDSHAKE,\t/* Detect corruption of handshake data */\n\tSSL_TEST_CORRUPT_DATA,\t\t/* Detect corruption of payload data */\n\tSSL_TEST_CORRUPT_MAC,\t\t/* Detect corruption of payload MAC */\n\tSSL_TEST_CORRUPT_FINISHED,\t/* Detect corruption of finished MAC */\n\tSSL_TEST_CORRUPT_IV,\t\t/* Detect corruption of IV */\n\tSSL_TEST_WRONGCERT,\t\t\t/* Detect wrong key for server */\n\tSSL_TEST_BADSIG_HASH,\t\t/* Detect corruption of signed DH params */\n\tSSL_TEST_BADSIG_SIG,\t\t/* Detect corruption of DH signature */\n\tSSL_TEST_BADSIG_DATA,\t\t/* Detect corruption of signed DH params */\n\tSSL_TEST_LAST\t\t\t\t/* Last possible SSL/TLS test type */\n\t} SSL_TEST_TYPE;\n\n#if defined( TEST_SESSION ) || defined( TEST_SESSION_LOOPBACK )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSL/TLS Test Data\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* If we're using local sockets, we have to pull in the sockets defines.  \n   We only use this on systems where there's fixed, known support for the\n   various functions that we need */\n\n#if defined( __WINDOWS__ ) || defined( __linux__ )\n  #define USE_TCP\n  #define STDC_NONNULL()\n  #define NET_STREAM_INFO\tvoid *\n  #define USE_TCP\n  #include <ctype.h>\t\t/* isspace() */\n  #if defined( __linux__ )\n\t#include <unistd.h>\t\t/* close() */\n  #endif /* Linux */\n  #include \"misc/analyse.h\"\t/* For values in tcp.h fn. prototypes */\n  #include \"io/tcp.h\"\n  #define USE_LOCAL_SOCKETS\n#endif /* Windows || Linux */\n\n/* There are various servers running that we can use for testing, the \n   following remapping allows us to switch between them.  Notes:\n\n\tServer 1: Local loopback.\n\tServer 2-4: Generic test servers at google.com (formerly amazon.com), \n\t\t\t  paypal.com, redhat.com.  There have to be three distinct \n\t\t\t  servers in order to force a full handshake rather than just \n\t\t\t  pulling a previous session out of the session cache.  \n\t\t\t  \n\t\t\t  In late 2014 Amazon disabled SSLv3 on all of its servers, \n\t\t\t  Paypal disabled it in early 2015, and Google disabled in mid \n\t\t\t  2016, which is what the Amazon/Google servers were used to \n\t\t\t  test, so now we use any number of US banks, which will \n\t\t\t  hopefully keep supporting insecure modes more or less forever, \n\t\t\t  see the entries around #45 for samples.  Use:\n\t\t\t  \n\t\t\t\topenssl s_client -connect <server>:443 -tls1\n\t\t\t\topenssl s_client -connect <server>:443 -tls1_1\n\n\t\t\t  to check for support of older protocols.  Use:\n\n\t\t\t\thttps://cryptoreport.websecurity.symantec.com/checker/\n\t\t\t\thttps://www.ssllabs.com/ssltest/\n\n\t\t\t  to check for cipher suites supported (the latter provides\n\t\t\t  per-protocol-version information, the former just overall\n\t\t\t  information).\n\t\t\t  \n\t\t\t  In addition as part of the deprecation of SHA-1 in early 2016 \n\t\t\t  Comodo, used by the Red Hat server, switched its CA certs to \n\t\t\t  SHA-384, so we need to enable the use of the extended SHA-2 \n\t\t\t  hash functions to deal with this.\n\tServer 5: ~40K data returned.  Returns an incorrect certificate for the\n\t\t\t  server when using SSL, although when accessed from a web\n\t\t\t  browser it works as expected.\n\tServer 6: Sends zero-length blocks (actually a POP server).  This server\n\t\t\t  is accessible under two names, pop.web.de and pop3.web.de,\n\t\t\t  but the certificate is for pop3.web.de.  In addition the\n\t\t\t  certificate has the host name in both the CN and \n\t\t\t  altName.domainName, allowing both code paths to be tested.\n\tServer 7: Novell GroupWise, requires CRYPT_OPTION_CERT_COMPLIANCELEVEL = \n\t\t\t  CRYPT_COMPLIANCELEVEL_OBLIVIOUS due to b0rken certs.\n\tServer 8: (Causes MAC failure during handshake when called from PMail, \n\t\t\t   works OK when called here).\n\tServer 9: Can only do crippled crypto (not even conventional crippled \n\t\t\t  crypto but RC4-56) and instead of sending an alert for this \n\t\t\t  just drops the connection (this may be caused by the NetApp \n\t\t\t  NetCache it's using).  This site is also running an Apache \n\t\t\t  server that claims it's optimised for MSIE, and that the page \n\t\t\t  won't work properly for non-MSIE browsers.  The mind \n\t\t\t  boggles...\n\tServer 10: Server (\"Hitachi Web Server 02-00\") can only do SSL, when \n\t\t\t   cryptlib is set to perform a TLS handshake (i.e. cryptlib is \n\t\t\t   told to expect TLS but falls back to SSL), goes through the \n\t\t\t   full handshake, then returns a handshake failure alert.  The \n\t\t\t   same occurs for other apps (e.g. MSIE) when TLS is enabled.\n\tServer 11: Buggy older IIS that can only do crippled crypto and drops \n\t\t\t   the connection as soon as it sees the client hello \n\t\t\t   advertising strong crypto only.\n\tServer 12: Newer IIS (certificate is actually for akamai.net, so the SSL \n\t\t\t   may not be Microsoft's at all).\n\tServer 13: IBM (Websphere?).\n\tServer 14: Server is running TLS with SSL disabled, drops connection \n\t\t\t   when it sees an SSL handshake.  MSIE in its default config \n\t\t\t   (TLS disabled) can't connect to this server.\n\tServer 15: GnuTLS.\n\tServer 16: GnuTLS test server with TLS 1.1.\n\tServer 17: Can only do SSLv2, server hangs when sent an SSLv3 handshake.\n\tServer 18: Can't handle TLS 1.1 handshake (drops connection).  In \n\t\t\t   addition the server returns a certificate chain leading up\n\t\t\t   to a Verisign MD2 root that gets rejected due to the use of\n\t\t\t   MD2.\n\tServer 19: Can't handle TLS 1.1 handshake (drops connection).  Both of \n\t\t\t   these servers are sitting behind NetApp NetCaches (see also \n\t\t\t   server #9), which could be the cause of the problem.\n\tServer 20: Generic OpenSSL server.\n\tServer 21: Crippled crypto using NS Server 3.6.\n\tServer 22: Apache with Thawte certs, requires \n\t\t\t   CRYPT_OPTION_CERT_COMPLIANCELEVEL = \n\t\t\t   CRYPT_COMPLIANCELEVEL_REDUCED due to b0rken certs.\n\tServer 23: Supports TLS-ext, max-fragment-size extension, session \n\t\t\t   tickets, TLS 1.2, and assorted other odds and ends, but \n\t\t\t   not ECC or GCM, reports info on connect in handy text \n\t\t\t   format.  Will also perform client-auth verification if the \n\t\t\t   client sends a client-auth message, accepting any cert and \n\t\t\t   using it to verify the handshake-data signature.  Uses the\n\t\t\t   1024-bit DH value from RFC 2409, see also server 46.\n\tServer 24: GnuTLS server supporting all sorts of oddities (PGP certs, \n\t\t\t   SRP, compression, TLS-ext, and others, see \n\t\t\t   http://www.gnu.org/software/gnutls/server.html for details), \n\t\t\t   reports info on connect in HTML table format.  Note that this \n\t\t\t   server claims to support TLS 1.2 but returns a TLS 1.1 server \n\t\t\t   hello in response to a TLS 1.2 handshake request for several \n\t\t\t   different TLS 1.2 client implementations.\n\tServer 25: Supports SNI extension and reports info on connect, can \n\t\t\t   connect to either alice.sni.velox.ch or carol.sni.velox.ch.\n\t\t\t   A connect to the default sni.velox.ch will return a \n\t\t\t   certificate-mismatch error.\n\tServer 26: Certicom server using ECDSA P256.  Returns a server cert with  \n\t\t\t   a bizarro X9.62 OID with implied sub-parameters that can't be \n\t\t\t   handled (at least in a sane manner) by the AlgoID read code.\n\tServer 27: RedHat server using NSS for ECC support for ECDSA P256.  This \n\t\t\t   server doesn't support any non-ECC suites, making it useful \n\t\t\t   for testing handling of the ECC-only case.\n\tServer 28: Certicom umbrella server (see #26) that also does TLS 1.2 \n\t\t\t   under very restricted circumstances (see below) and GCM.  \n\t\t\t   Details at https://tls.secg.org/, transaction log at \n\t\t\t   https://tls.secg.org/index1.php?action=https_log (this log \n\t\t\t   rolls over fairly quickly, requiring opening the last several \n\t\t\t   entries and matching cipher suites to see which one was \n\t\t\t   yours).  Note that this server claims to support TLS 1.2 but \n\t\t\t   returns a TLS 1.1 server hello in response to a TLS 1.2 \n\t\t\t   handshake request unless you report DHE_DSS as your only \n\t\t\t   available cipher suite.  A more standard combination like \n\t\t\t   RSA or DHE_RSA results in the server returning a TLS 1.1 \n\t\t\t   response, and an attempt to force matters with a TLS 1.2-only \n\t\t\t   cipher suite like DHE_AES_GCM returns an alert message with \n\t\t\t   the version number set to SSLv3, i.e. { 3, 0 }.  This server\n\t\t\t   also has a certificate in which the CN is a combination of\n\t\t\t   the server FQDN and further text, requiring a match on the\n\t\t\t   altName even though the first part of the DN would also\n\t\t\t   match.\n\tServer 29: Microsoft interop test server that does TLS 1.2, ECC, and \n\t\t\t   unlike GnuTLS and Certicom/SECG it actually really does TLS \n\t\t\t   1.2.  This is the generic interface with all cipher suites, \n\t\t\t   see Server #30 and #31 for variants.  This server also claims \n\t\t\t   to support GCM (although only with ECC, not with RSA/DSA) but \n\t\t\t   in practice closes the connection when sent a client hello \n\t\t\t   with this cipher suite.  \n\tServer 30: As Server #29 but restricted to 256-bit ECC only, this server \n\t\t\t   does actually support GCM.  Requires \n\t\t\t   CRYPT_OPTION_CERT_COMPLIANCELEVEL = \n\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS due to b0rken certs.\n\tServer 31: As server #29 but restricted to 384-bit ECC only, however it \n\t\t\t   closes the connection when sent a SHA-384 cipher suite.\n\tServer 32: As Server #29 but tests rehandshake handling.  This is \n\t\t\t   actually meant to test RSA client authentication, i.e. \n\t\t\t   SSL_TEST_CLIENTCERT, but Windows implements this by \n\t\t\t   performning a standard handshake without client-auth and then \n\t\t\t   immediately performing a rehandshake with client-auth, which \n\t\t\t   can be used to test the ability to handle a rehandshake \n\t\t\t   request.  In practice the Windows server hangs waiting for \n\t\t\t   the rehandshake, so eventually we exit with a read timeout \n\t\t\t   error.\n\tServer 33: RSA interop server, this requires a complex pre-approval \n\t\t\t   application process to enable access which makes it not worth \n\t\t\t   the bother, it's only listed here for completeness.\n\tServer 34: Encrypt-then-MAC extension support.\n\tServer 35: DHE-PSK support via PolarSSL, name = gutman, \n\t\t\t   PSK = 0x0123456789abcdef.\n\tServer 36: Returns a certificate with \"outlook.com\" in the CN, requires\n\t\t\t   matching the altName to find \"smtp.office365.com\".\n\tServer 37: Returns (deliberately) invalid DH parameters to test whether\n\t\t\t   clients check these.\n\tServer 38: As #37, 768-bit DH.\n\tServer 39: As #37, but valid 2048-bit DH.\n\tServer 40: As #37, but valid 2048-bit DH with 2048-bit DSA.\n\tServer 41: As #37, but valid 2048-bit DH with 1024-bit DSA.\n\tServer 42: As #37, but invalid (non-prime) 1024-bit DH.\n\tServer 43: Checks for SKIP-TLS vulnerability.\n\tServer 44: MiTLS reference implementation, but doesn't seem to implement\n\t\t\t   much out of the ordinary.\n\tServer 45: Remaining SSLv3 server in 2016, SSLv3 disabled 2017.\n\tServer 46: As server 23 but with the 2048-bit DH value from RFC 3526.\n\tServer 47: Rejects any connect attempt where extensions are present.\n\t\t\t   Alternative server is \n\t\t\t   https://preprod.connect.elemica.com:5443.\n\tServer 48: nmap.org deliberately-insecure test server, however even this\n\t\t\t   doesn't do SSLv3 any more.\n\tServer 49: WebSockets local loopback.\n\tServer 50: WebSockets echo test server, direct access.  Note that this \n\t\t\t   returns a certificate chain with a broken GoDaddy certificate\n\t\t\t   with RSA e = 3, which will need a safety check in kg_rsa.c\n\t\t\t   disabled.\n\tServer 51: WebSockets echo test server, URL access.  See #50 for the\n\t\t\t   GoDaddy certificate issue.\n\tServer 52: WebSockets AMQP test server.  See #50 for the GoDaddy \n\t\t\t   certificate issue.\n\tServer 53: EAPlab EAP public test server, see\n\t\t\t   https://eaplab.supplicants.net/.\n\tServer 54: IronWiFi EAP public test server, see \n\t\t\t   https://www.ironwifi.com/captive-portal-demos/.\n\tServer 55: IronWiFi EAP private demo test server.\n\tServer 56: FreeRADIUS local test server. \n\tServer 57: Reported to cause SIGFPE's in some builds of (OpenSSL's) \n\t\t\t   BN_div(), but unable to reproduce across multiple cryptlib\n\t\t\t   platforms.\n\tServer 58: Sends a CertificateRequest larger than the maximum packet \n\t\t\t   size */\n\n#define SSL_SERVER_NO\t48\t/* Getting very hard to find... */\n#define TLS_SERVER_NO\t3\n#define TLS11_SERVER_NO\t4\t/* Use #27 for ECC, otherwise #4 */\n#define TLS12_SERVER_NO\t23\t/* Options = #23, #24, #28, #29/30/31\n\t\t\t\t\t\t\t   (but see above for #24, #28, and some of \n\t\t\t\t\t\t\t   #29) */\n#define WS_SERVER_NO\t50\n#define EAP_SERVER_NO\t56\n#if ( SSL_SERVER_NO == TLS_SERVER_NO ) || \\\n\t( SSL_SERVER_NO == TLS11_SERVER_NO ) || \\\n\t( TLS_SERVER_NO == TLS11_SERVER_NO )\n  #error SSL/TLS/TLS11 servers must be distinct to avoid tests being skipped due to session cacheing\n#endif /* Make sure that servers are distinct */\n\n#if ( TLS_SERVER_NO == 35 )\n  #undef SSL_USER_NAME\n  #undef SSL_PASSWORD\n  #define SSL_USER_NAME\t\t\"gutman\"\n  #define SSL_PASSWORD\t\t\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\"\n#endif /* DHE-PSK test server */\n\nstatic const struct {\n\tconst C_STR name;\n\tconst C_STR path;\n\tconst C_STR userName;\n\tconst C_STR password;\n\t} sslInfo[] = {\n\t{ NULL, NULL },\n\t/*  1 */ { TEXT( \"localhost\" ), \"/\" },\n\t/*  2 */ { TEXT( \"https://www.google.com\" ), \"/\" },\n\t/*  3 */ { TEXT( \"https://www.paypal.com\" ), \"/\" },\n\t/*  4 */ { TEXT( \"https://www.redhat.com\" ), \"/\" },\n\t/*  5 */ { TEXT( \"https://www.cs.berkeley.edu\" ), \"/~daw/people/crypto.html\" },\n\t/*  6 */ { TEXT( \"pop.web.de:995\" ), \"/\" },\n\t/*  7 */ { TEXT( \"imap4-gw.uni-regensburg.de:993\" ), \"/\" },\n\t/*  8 */ { TEXT( \"securepop.t-online.de:995\" ), \"/\" },\n\t/*  9 */ { TEXT( \"https://homedir.wlv.ac.uk\" ), \"/\" },\n\t/* 10 */ { TEXT( \"https://www.horaso.com:20443\" ), \"/\" },\n\t/* 11 */ { TEXT( \"https://homedir.wlv.ac.uk\" ), \"/\" },\n\t/* 12 */ { TEXT( \"https://www.microsoft.com\" ), \"/\" },\n\t/* 13 */ { TEXT( \"https://alphaworks.ibm.com/\" ), \"/\" },\n\t/* 14 */ { TEXT( \"https://webmount.turbulent.ca/\" ), \"/\" },\n\t/* 15 */ { TEXT( \"https://www.gnutls.org/\" ), \"/\" },\n\t/* 16 */ { TEXT( \"https://www.gnutls.org:5555/\" ), \"/\" },\n\t/* 17 */ { TEXT( \"https://www.networksolutions.com/\" ), \"/\" },\n\t/* 18 */ { TEXT( \"https://olb.westpac.com.au/\" ), \"/\" },\n\t/* 19 */ { TEXT( \"https://www.hertz.com/\" ), \"/\" },\n\t/* 20 */ { TEXT( \"https://www.openssl.org/\" ), \"/\" },\n\t/* 21 */ { TEXT( \"https://secureads.ft.com/\" ), \"/\" },\n\t/* 22 */ { TEXT( \"https://mail.maine.edu/\" ), \"/\" },\n\t/* 23 */ { TEXT( \"https://www.mikestoolbox.org/\" ), \"/\" },\n\t/* 24 */ { TEXT( \"https://test.gnutls.org:5556/\" ), \"/\" },\n\t/* 25 */ { TEXT( \"https://sni.velox.ch/\" ), \"/\" },\n\t/* 26 */ { TEXT( \"https://tls.secg.org:40023/connect.php\" ), \"/\" },\n\t/* 27 */ { TEXT( \"https://ecc.fedora.redhat.com\" ), \"/\" },\n\t/* 28 */ { TEXT( \"https://tls.secg.org/\" ), \"/\" },\n\t/* 29 */ { TEXT( \"https://tls.woodgrovebank.com:25000/\" ), \"/\" },\n\t/* 30 */ { TEXT( \"https://tls.woodgrovebank.com:25002/\" ), \"/\" },\n\t/* 31 */ { TEXT( \"https://tls.woodgrovebank.com:25003/\" ), \"/\" },\n\t/* 32 */ { TEXT( \"https://tls.woodgrovebank.com:25005/\" ), \"/\" },\n\t/* 33 */ { TEXT( \"https://203.166.62.199/\" ), \"/\" },\n\t/* 34 */ { TEXT( \"https://eid.vx4.net\" ), \"/\" },\n\t/* 35 */ { TEXT( \"https://beta.polarssl.org:4433\" ), \"/\" },\n\t/* 36 */ { TEXT( \"https://smtp.office365.com\" ), \"/\" },\n\t/* 37 */ { TEXT( \"https://demo.cmrg.net/\" ), \"/\" },\n\t/* 38 */ { TEXT( \"https://dh768.tlsfun.de/\" ), \"/\" },\n\t/* 39 */ { TEXT( \"https://dh2048.tlsfun.de/\" ), \"/\" },\n\t/* 40 */ { TEXT( \"https://dh2048-dsa.tlsfun.de/\" ), \"/\" },\n\t/* 41 */ { TEXT( \"https://dh2048-dsa1024.tlsfun.de/\" ), \"/\" },\n\t/* 42 */ { TEXT( \"https://dh1024nop.tlsfun.de/\" ), \"/\" },\n\t/* 43 */ { TEXT( \"https://ht.vc:6443\" ), \"/\" },\n\t/* 44 */ { TEXT( \"https://mitls.org/\" ), \"/\" },\n\t/* 45 */ { TEXT( \"https://firstus.org/\" ), \"/\" },\n\t/* 46 */ { TEXT( \"https://www.mikestoolbox.org/\" ), \"/\" },\n\t/* 47 */ { TEXT( \"https://connect.elemica.com:5443\" ), \"/\" },\n\t/* 48 */ { TEXT( \"https://www.insecure.org/nmap/\" ), \"/\" },\n\t/* 49 */ { TEXT( \"wss://localhost\" ), \"/\" },\n\t/* 50 */ { TEXT( \"wss://echo.websocket.org\" ), \"/\" },\n\t/* 51 */ { TEXT( \"wss://demos.kaazing.com/echo\" ), \"/\" },\n\t/* 52 */ { TEXT( \"wss://demos.kaazing.com/amqp\" ), \"/\" },\n\t/* 53 */ { TEXT( \"radius.supplicants.net:1812\" ), \"/\", \"eaplab@r1.supplicants.net\", \"????\" },\n\t/* 54 */ { TEXT( \"130.211.138.166:7197\" ), \"/\", \"demouser\", \"????\" },\n\t/* 55 */ { TEXT( \"35.197.133.220:11315\" ), \"/\", \"test\", \"test\" },\n\t/* 56 */ { TEXT( \"192.168.1.36:1812\" ), \"/\", \"test\", \"test\" },\n\t/* 57 */ { TEXT( \"excalibur.mudcovered.org.uk\" ), \"/\" },\n\t/* 58 */ { TEXT( \"https://testacig.ariba.com\" ), \"/as2/as2\" },\n\t{ NULL, NULL }\n\t};\n\nstatic const struct {\n\tconst SSL_TEST_TYPE testType;\n\tconst C_STR path;\n\tconst BOOLEAN result;\n\t} badSslInfo[] = {\n\t{ SSL_TEST_BADSSL_DH512, TEXT( \"https://dh512.badssl.com/\" ), FALSE },\n\t{ SSL_TEST_BADSSL_DH1024, \n\t  TEXT( \"https://dh1024.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_DH2048, \n\t  TEXT( \"https://dh2048.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_DHSMALLSUBGROUP, \n\t  TEXT( \"https://dh-small-subgroup.badssl.com/\" ), FALSE },\n\t{ SSL_TEST_BADSSL_DHCOMPOSITE, \n\t  TEXT( \"https://dh-composite.badssl.com/\" ), FALSE },\n#ifdef USE_RSA_SUITES\n\t{ SSL_TEST_BADSSL_STATICRSA, \n\t  TEXT( \"https://static-rsa.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_RSA2048, \n\t  TEXT( \"https://rsa2048.badssl.com/\" ), TRUE },\n#else\n\t{ SSL_TEST_BADSSL_STATICRSA, \n\t  TEXT( \"https://static-rsa.badssl.com/\" ), FALSE },\n\t{ SSL_TEST_BADSSL_RSA2048, \n\t  TEXT( \"https://rsa2048.badssl.com/\" ), FALSE },\n#endif /* USE_RSA_SUITES */\n#if defined( USE_ECDSA ) && defined( USE_ECDH )\n\t/* However see comment before the include of config.h, this doesn't work \n\t   with mixed debug/release builds */\n\t{ SSL_TEST_BADSSL_ECC256, TEXT( \"https://ecc256.badssl.com/\" ), TRUE },\n#else\n\t{ SSL_TEST_BADSSL_ECC256, TEXT( \"https://ecc256.badssl.com/\" ), FALSE },\n#endif /* USE_ECDSA && USE_ECDH */\n\t{ SSL_TEST_BADSSL_CBC, TEXT( \"https://cbc.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_RC4MD5, TEXT( \"https://rc4-md5.badssl.com/\" ), FALSE },\n\t{ SSL_TEST_BADSSL_RC4, TEXT( \"https://rc4.badssl.com/\" ), FALSE },\n\t{ SSL_TEST_BADSSL_3DES, TEXT( \"https://3des.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_NOCN, \n\t  TEXT( \"https://no-common-name.badssl.com/\" ), TRUE },\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t{ SSL_TEST_BADSSL_NOSUBJECT, \n\t  TEXT( \"https://no-subject.badssl.com\" ), TRUE },\t\t/* Name is in altName */\n#else\n\t{ SSL_TEST_BADSSL_NOSUBJECT, \n\t  TEXT( \"https://no-subject.badssl.com\" ), FALSE },\t\t/* Name is in altName */\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t{ SSL_TEST_BADSSL_LONGNAME1, \n\t  TEXT( \"https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/\" ), TRUE },\n\t{ SSL_TEST_BADSSL_LONGNAME2, \n\t  TEXT( \"https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/\" ), TRUE },\n\t{ 0, NULL }\n\t};\n\n/* Various servers used for STARTTLS/STLS/AUTH TLS testing.  Notes:\n\n\tServer 1: SMTP: mailbox.ucsd.edu:25, requires a client certificate.\n\tServer 2: POP: pop.cae.wisc.edu:1110, OK.\n\tServer 3: SMTP: smtpauth.cae.wisc.edu:25, requires a client certificate.\n\tServer 4: SMTP: send.columbia.edu:25, returns invalid certificate (lower \n\t\t\t  compliance level to fix).\n\tServer 5: POP: pop3.myrealbox.com:110, returns invalid certificate \n\t\t\t  (lower compliance level to fix).\n\tServer 6: Encrypted POP: securepop.t-online.de:995, direct SSL connect.\n\tServer 7: FTP: ftp.windsorchapel.net:21, sends redundant client \n\t\t\t  certificate request with invalid length.\n\tServer 8: POP: webmail.chm.tu-dresden.de:110, another GroupWise server \n\t\t\t  (see the server comments above) with b0rken certs.\n\n\t\t\t  To test FTP with SSL/TLS manually: Disable auto-login with \n\t\t\t  FTP, then send an RFC 2389 FEAT command to check security \n\t\t\t  facilities.  If this is supported, one of the responses will \n\t\t\t  be either AUTH SSL or AUTH TLS, use this to turn on SSL/TLS.  \n\t\t\t  If FEAT isn't supported, AUTH TLS should usually work:\n\n\t\t\t\tftp -n ftp.windsorchapel.net\n\t\t\t\tquote feat\n\t\t\t\tquote auth ssl\n\n\t\t\t  or just:\n\n\t\t\t\ttelnet ftp.windsorchapel.net 21\n\t\t\t\tauth ssl\n\n\tServer 9: SMTP: mailer.gwdg.de:25, sends each SSL message as a discrete \n\t\t\t  packet, providing a nice test of cryptlib's on-demand buffer \n\t\t\t  refill.\n\tServer 10: Encrypted POP: mrdo.vosn.net:995, direct SSL connect, sends \n\t\t\t   a CA certificate which is also used for encryption, but with \n\t\t\t   no keyUsage flags set.\n\tServer 11: POP: pop.gmail.com:995.  Formerly STARTTLS, now requires a \n\t\t\t   direct SSL connect.\n\tServer 12: POP: mail.rochester.edu:995, direct SSL connect (also sends \n\t\t\t   zero-length packets as a kludge for pre-TLS 1.1 chosen-IV \n\t\t\t   attacks).\n\tServer 13: SMTP: smtp.umn.edu:465, direct SSL connect.\n\tServer 14: POP3: pop3.live.com:995, direct SSL connect, returns a \n\t\t\t   malformed certificate.  Can also be accessed via \n\t\t\t   smtp.live.com, port 25 or 587 */\n\n#define STARTTLS_SERVER_NO\t11\n\ntypedef enum { PROTOCOL_NONE, PROTOCOL_SMTP, PROTOCOL_SMTP_DIRECT, \n\t\t\t   PROTOCOL_POP, PROTOCOL_IMAP, PROTOCOL_POP_DIRECT, \n\t\t\t   PROTOCOL_FTP\n\t\t\t } PROTOCOL_TYPE;\n\nstatic const struct {\n\tconst C_STR name;\n\tconst int port;\n\tPROTOCOL_TYPE protocol;\n\t} starttlsInfo[] = {\n\t{ NULL, 0 },\n\t/*  1 */ { TEXT( \"mailbox.ucsd.edu\" ), 25, PROTOCOL_SMTP },\n\t/*  2 */ { TEXT( \"pop.cae.wisc.edu\" ), 1110, PROTOCOL_POP },\n\t/*  3 */ { TEXT( \"smtpauth.cae.wisc.edu\" ), 25, PROTOCOL_SMTP },\n\t/*  4 */ { TEXT( \"send.columbia.edu\" ), 25, PROTOCOL_SMTP },\n\t/*  5 */ { TEXT( \"pop3.myrealbox.com\" ), 110, PROTOCOL_POP },\n\t/*  6 */ { TEXT( \"securepop.t-online.de\" ), 995, PROTOCOL_POP_DIRECT },\n\t/*  7 */ { TEXT( \"ftp.windsorchapel.net\" ), 21, PROTOCOL_FTP },\n\t/*  8 */ { TEXT( \"webmail.chm.tu-dresden.de\" ), 110, PROTOCOL_POP },\n\t/*  9 */ { TEXT( \"mailer.gwdg.de\" ), 25, PROTOCOL_SMTP },\n\t/* 10 */ { TEXT( \"mrdo.vosn.net\" ), 995, PROTOCOL_POP_DIRECT },\n\t/* 11 */ { TEXT( \"pop.gmail.com\" ), 995, PROTOCOL_POP_DIRECT },\n\t/* 12 */ { TEXT( \"mail.rochester.edu\" ), 995, PROTOCOL_POP_DIRECT },\n\t/* 13 */ { TEXT( \"smtp.umn.edu\" ), 465, PROTOCOL_SMTP_DIRECT },\n\t/* 14 */ { TEXT( \"pop3.live.com\" ), 995, PROTOCOL_POP_DIRECT },\n\t{ NULL, 0 }\n\t};\n\n/* Special-case handling for buggy/broken/odd servers */\n\n#if ( SSL_SERVER_NO == 7 ) || ( TLS12_SERVER_NO == 30 ) || \\\n\t( TLS12_SERVER_NO == 31 ) || ( STARTTLS_SERVER_NO == 8 )\n  #define BROKEN_SERVER_INVALID_CERT\n  #if defined( _MSC_VER ) || defined( __GNUC__ )\n \t#pragma message( \"  Building with reduced compliance level for buggy SSL/TLS server.\" )\n  #endif /* Warn about special features enabled */\n#endif /* Broken servers */\n#if ( SSL_SERVER_NO == 3 )\n  #define IS_HIGHVOLUME_SERVER\n#endif /* Servers with high result volume */\n\n/* If we're testing dual-thread handling of sessions, we need to provide a \n   forward declaration of the threading function since it's called from \n   within the SSL connect code */\n\n#ifdef WINDOWS_THREADS\n  unsigned __stdcall tlsServerDualThread2( void *dummy );\n#endif /* WINDOWS_THREADS */\n\n/* Large buffer size to test bulk data transfer capability for secure\n   sessions */\n\n#if defined( __MSDOS16__ ) || defined( __WIN16__ )\n  #define BULKDATA_BUFFER_SIZE\t20000\n#elif defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && \\\n\t  !defined( NDEBUG ) && 1\n  #define BULKDATA_BUFFER_SIZE\t300000L\n  #define USE_TIMING\t\t\t/* Report data-transfer time */\n#else\n  #define BULKDATA_BUFFER_SIZE\t300000L\n#endif /* 16-bit VC++ */\n\nstatic int checksumData( const void *data, const int dataLength )\n\t{\n\tconst BYTE *dataPtr = data;\n\tint sum1 = 0, sum2 = 0, i;\n\n\t/* Calculate a 16-bit Fletcher-like checksum of the data (it doesn't \n\t   really matter if it's not exactly right, as long as the behaviour is \n\t   the same for all data) */\n\tfor( i = 0; i < dataLength; i++ )\n\t\t{\n\t\tsum1 += dataPtr[ i ];\n\t\tsum2 += sum1;\n\t\t}\n\n\treturn( sum2 & 0xFFFF );\n\t}\n\nstatic BOOLEAN handleBulkBuffer( BYTE *buffer, const BOOLEAN isInit )\n\t{\n\tint checkSum, i;\n\n\t/* If we're initialising the buffer, fill it with [0...256]* followed by \n\t   a checksum of the buffer contents */\n\tif( isInit )\n\t\t{\n\t\tfor( i = 0; i < BULKDATA_BUFFER_SIZE - 2; i++ )\n\t\t\tbuffer[ i ] = i & 0xFF;\n\t\tcheckSum = checksumData( buffer, BULKDATA_BUFFER_SIZE - 2 );\n\t\tbuffer[ BULKDATA_BUFFER_SIZE - 2 ] = ( checkSum >> 8 ) & 0xFF;\n\t\tbuffer[ BULKDATA_BUFFER_SIZE - 1 ] = checkSum & 0xFF;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* We're being sent an initialised buffer, make sure that it's OK */\n\tfor( i = 0; i < BULKDATA_BUFFER_SIZE - 2; i++ )\n\t\t{\n\t\tif( buffer[ i ] != ( i & 0xFF )\t)\n\t\t\treturn( FALSE );\n\t\t}\n\tcheckSum = checksumData( buffer, BULKDATA_BUFFER_SIZE - 2 );\n\tif( buffer[ BULKDATA_BUFFER_SIZE - 2 ] != ( ( checkSum >> 8 ) & 0xFF ) || \\\n\t\tbuffer[ BULKDATA_BUFFER_SIZE - 1 ] != ( checkSum & 0xFF ) )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tLocal Socket Handling\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Testing this capability fully requires a lot of OS-specific juggling so \n   unless we're running under Windows or Linux we just supply the handle to \n   stdin, which will return a read/write error during the connect.  This \n   checks that the handle has been assigned corectly without requiring a lot \n   of OS-specific socket handling code.  Otherwise, we use a (very cut-down) \n   set of socket calls to set up a minimal socket.  Since there's very little \n   error-checking done, we don't treat a  failure as fatal */\n\n#ifdef USE_LOCAL_SOCKETS\n\nstatic BOOLEAN initSockets( void )\n\t{\n  #ifdef __WINDOWS__\n\tWSADATA wsaData;\n\n\tif( WSAStartup( 2, &wsaData ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't initialise sockets interface, line \"\n\t\t\t\t \"%d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n  #endif /* __WINDOWS__ */\n\n\treturn( TRUE );\n\t}\n\nstatic void endSockets( const SOCKET netSocket )\n\t{\n\tif( netSocket != 0 )\n\t\tclosesocket( netSocket );\n\n\t/* In theory we should be calling WSACleanup() at this point, however */\n  #ifdef __WINDOWS__\n\tWSACleanup();\n  #endif /* __WINDOWS__ */\n\t}\n\n/* Hand a socket over to cryptlib */\n\nstatic int setSocket( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t  const SOCKET netSocket )\n\t{\n  #if defined( _MSC_VER ) && defined( _M_X64 )\n\treturn( cryptSetAttribute( cryptSession, CRYPT_SESSINFO_NETWORKSOCKET, \n\t\t\t\t\t\t\t   ( int ) netSocket ) );\n  #else\n\treturn( cryptSetAttribute( cryptSession, CRYPT_SESSINFO_NETWORKSOCKET, \n\t\t\t\t\t\t\t   netSocket ) );\n  #endif /* 64-bit Windows */\n\t}\n\n/* Set up a client user-definde socket by negotiating through a STARTTLS */\n\nstatic int readLine( SOCKET netSocket, BYTE *buffer )\n\t{\n\tint bufPos, status = CRYPT_OK;\n\n\tfor( bufPos = 0; \\\n\t\t status >= 0 && bufPos < 1024 && \\\n\t\t\t( bufPos < 1 || buffer[ bufPos -1 ] != '\\n' );\n\t\t bufPos++ )\n\t\t{\n\t\tstatus = recv( netSocket, buffer + bufPos, 1, 0 );\n\t\t}\n\twhile( bufPos > 1 && isspace( buffer[ bufPos - 1 ] ) )\n\t\tbufPos--;\n\tif( bufPos >= 3 )\n\t\t{\n\t\twhile( bufPos > 1 && isspace( buffer[ bufPos - 1 ] ) )\n\t\t\tbufPos--;\n\t\tbuffer[ min( bufPos, 56 ) ] = '\\0';\n\t\t}\n\n\treturn( bufPos );\n\t}\n\nstatic SOCKET negotiateSTARTTLS( int *protocol )\n\t{\n\tSOCKET netSocket;\n\tstruct sockaddr_in serverAddr;\n\tstruct hostent *hostInfo;\n\tBYTE buffer[ 1024 ];\n\tint bufPos, status;\n\n\tfputs( \"Negotiating SMTP/POP/IMAP/FTP session through to TLS start...\\n\", \n\t\t   outputStream );\n\t*protocol = starttlsInfo[ STARTTLS_SERVER_NO ].protocol;\n\n\t/* Look up the server's IP address */\n\thostInfo = gethostbyname( starttlsInfo[ STARTTLS_SERVER_NO ].name );\n\tif( hostInfo == NULL )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't resolve hostname %s, line %d.\\n\", \n\t\t\t\t starttlsInfo[ STARTTLS_SERVER_NO ].name, __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Create a network socket to connect */\n\tnetSocket = socket( PF_INET, SOCK_STREAM, 0 );\n\tif( netSocket == INVALID_SOCKET )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't create socket, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* Connect to a generally-available server to test STARTTLS/STLS\n\t   functionality */\n\tmemset( &serverAddr, 0, sizeof( struct sockaddr_in ) );\n\tserverAddr.sin_family = AF_INET;\n\tserverAddr.sin_addr = *( ( struct in_addr * ) hostInfo->h_addr_list[ 0 ] );\n\tserverAddr.sin_port = htons( ( u_short ) starttlsInfo[ STARTTLS_SERVER_NO ].port );\n\tstatus = connect( netSocket, ( struct sockaddr * ) &serverAddr,\n\t\t\t\t\t  sizeof( struct sockaddr_in ) );\n\tif( status == SOCKET_ERROR )\n\t\t{\n\t\tclosesocket( netSocket );\n\t\tfprintf( outputStream, \"Couldn't connect socket, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t}\n\n\t/* If it's a direct connect, there's nothing left to do */\n\tif( *protocol == PROTOCOL_POP_DIRECT )\n\t\t{\n\t\t*protocol = PROTOCOL_POP;\n\t\treturn( netSocket );\n\t\t}\n\tif( *protocol == PROTOCOL_SMTP_DIRECT )\n\t\t{\n\t\t*protocol = PROTOCOL_SMTP;\n\t\treturn( netSocket );\n\t\t}\n\n\t/* Perform (very crude) SMTP/POP/IMAP negotiation to switch to TLS */\n\tbufPos = readLine( netSocket, buffer );\n\tif( bufPos < 3 || ( strncmp( buffer, \"220\", 3 ) && \\\n\t\t\t\t\t\tstrncmp( buffer, \"+OK\", 3 ) && \\\n\t\t\t\t\t\tstrncmp( buffer, \"OK\", 2 ) ) )\n\t\t{\n\t\tclosesocket( netSocket );\n\t\tfprintf( outputStream, \"Got response '%s', line %d.\\n\", buffer, \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t}\n\tfprintf( outputStream, \"  Server said: '%s'\\n\", buffer );\n\tassert( ( *protocol == PROTOCOL_SMTP && !strncmp( buffer, \"220\", 3 ) ) || \\\n\t\t\t( *protocol == PROTOCOL_POP && !strncmp( buffer, \"+OK\", 3 ) ) || \\\n\t\t\t( *protocol == PROTOCOL_IMAP && !strncmp( buffer, \"OK\", 2 ) ) || \\\n\t\t\t( *protocol == PROTOCOL_FTP && !strncmp( buffer, \"220\", 3 ) ) || \\\n\t\t\t*protocol == PROTOCOL_NONE );\n\tswitch( *protocol )\n\t\t{\n\t\tcase PROTOCOL_POP:\n\t\t\tsend( netSocket, \"STLS\\r\\n\", 6, 0 );\n\t\t\tfputs( \"  We said: 'STLS'\", outputStream );\n\t\t\tbreak;\n\n\t\tcase PROTOCOL_IMAP:\n\t\t\t/* It's possible for some servers that we may need to explicitly \n\t\t\t   send a CAPABILITY command first to enable STARTTLS:\n\t\t\t\ta001 CAPABILITY\n\t\t\t\t> CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED\n\t\t\t\t> OK CAPABILITY completed */\n\t\t\tsend( netSocket, \"a001 STARTTLS\\r\\n\", 15, 0 );\n\t\t\tfputs( \"  We said: 'STARTTLS'\", outputStream );\n\t\t\tbreak;\n\n\t\tcase PROTOCOL_SMTP:\n\t\t\tsend( netSocket, \"EHLO foo.bar.com\\r\\n\", 18, 0 );\n\t\t\tfputs( \"  We said: 'EHLO foo.bar.com'\", outputStream );\n\t\t\tdo\n\t\t\t\t{\n\t\t\t\tbufPos = readLine( netSocket, buffer );\n\t\t\t\tif( bufPos < 3 || strncmp( buffer, \"250\", 3 ) )\n\t\t\t\t\t{\n\t\t\t\t\tclosesocket( netSocket );\n\t\t\t\t\tfprintf( outputStream, \"Got response '%s', line %d.\\n\", \n\t\t\t\t\t\t\t buffer, __LINE__ );\n\t\t\t\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t\t\t\t}\n\t\t\t\tfprintf( outputStream, \"  Server said: '%s'\\n\", buffer );\n\t\t\t\t}\n\t\t\twhile( !strncmp( buffer, \"250-\", 4 ) );\n\t\t\tsend( netSocket, \"STARTTLS\\r\\n\", 10, 0 );\n\t\t\tfputs( \"  We said: 'STARTTLS'\", outputStream );\n\t\t\tbreak;\n\n\t\tcase PROTOCOL_FTP:\n\t\t\tsend( netSocket, \"AUTH TLS\\r\\n\", 10, 0 );\n\t\t\tfputs( \"  We said: 'AUTH TLS'\", outputStream );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tassert( FALSE );\n\t\t}\n\tbufPos = readLine( netSocket, buffer );\n\tif( bufPos < 3 || ( strncmp( buffer, \"220\", 3 ) && \\\n\t\t\t\t\t\tstrncmp( buffer, \"+OK\", 3 ) && \\\n\t\t\t\t\t\tstrncmp( buffer, \"OK\", 2 ) && \\\n\t\t\t\t\t\tstrncmp( buffer, \"234\", 3 ) ) )\n\t\t{\n\t\tfprintf( outputStream, \"Got response '%s', line %d.\\n\", buffer, \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t}\n\tfprintf( outputStream, \"  Server said: '%s'\\n\", buffer );\n\treturn( netSocket );\n\t}\n\n/* Set up a server using user-defined sockets */\n\nstatic SOCKET createServerSocket( void )\n\t{\n\tSOCKET netSocket;\n\tstruct sockaddr_in serverInfo;\n\tint status;\n\n\tfputs( \"Creating user-defined local server socket...\", outputStream );\n\n\t/* Connect to a generally-available server to test STARTTLS/STLS\n\t   functionality */\n\tmemset( &serverInfo, 0, sizeof( struct sockaddr_in ) );\n\tserverInfo.sin_family = AF_INET;\n#ifdef __WINDOWS__\n\tserverInfo.sin_port = htons( 443 );\n#else\n\tserverInfo.sin_port = htons( 4443 );\n#endif /* OS-specific port handling */\n\tserverInfo.sin_addr.s_addr = inet_addr( \"127.0.0.1\" );\n\tnetSocket = socket( PF_INET, SOCK_STREAM, 0 );\n\tif( netSocket == INVALID_SOCKET )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't create socket, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tstatus = bind( netSocket, ( struct sockaddr* ) &serverInfo, \n\t\t\t\t   sizeof( struct sockaddr_in ) );\n\tif( status == SOCKET_ERROR )\n\t\t{\n\t\tclosesocket( netSocket );\n\t\tfprintf( outputStream, \"Couldn't bind to 127.0.0.1, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t}\n\tstatus = listen( netSocket, 5 );\n\tif( status == SOCKET_ERROR )\n\t\t{\n\t\tclosesocket( netSocket );\n\t\tfprintf( outputStream, \"Couldn't listen on local socket, line %d.\\n\", \n\t\t\t\t __LINE__ );\n\t\treturn( CRYPT_OK );\t\t/* Signal non-fatal error */\n\t\t}\n\treturn( netSocket );\n\t}\n\nstatic SOCKET connectServerSocket( SOCKET netSocket )\n\t{\n\tSOCKET connectedSocket;\n\tSOCKADDR_STORAGE clientAddr;\n\tSIZE_TYPE clientAddrLen = sizeof( SOCKADDR_STORAGE );\n\tconst int trueValue = 1;\n\n\tconnectedSocket = accept( netSocket, ( struct sockaddr * ) &clientAddr,\n\t\t\t\t\t\t\t  &clientAddrLen);\n\tclosesocket( netSocket );\n\tif( connectedSocket == SOCKET_ERROR )\n\t\t{\n\t\tfprintf( outputStream, \"Error receiving incoming connection on local \"\n\t\t\t\t \"socket, line %d.\\n\", __LINE__ );\n\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tsetsockopt( connectedSocket, DISABLE_NAGLE_LEVEL, DISABLE_NAGLE_OPTION, \n\t\t\t\t( void * ) &trueValue, sizeof( int ) );\n\n\treturn( connectedSocket );\n\t}\n#else\n\nstatic int setPseudoSocket( const CRYPT_SESSION cryptSession )\n\t{\n#if defined( DDNAME_IO )\n\t/* The fileno() function doesn't work for DDNAMEs */\n\treturn( cryptSetAttribute( cryptSession, CRYPT_SESSINFO_NETWORKSOCKET, \n\t\t\t\t\t\t\t   0 ) );\n#elif defined( __WIN16__ ) || defined( _WIN32_WCE )\n\treturn( cryptSetAttribute( cryptSession, CRYPT_SESSINFO_NETWORKSOCKET, \n\t\t\t\t\t\t\t   1 ) );\n#else\n\treturn( cryptSetAttribute( cryptSession, CRYPT_SESSINFO_NETWORKSOCKET, \n\t\t\t\t\t\t\t   fileno( stdin ) ) );\n#endif /* System-specific pseudo-socket handling */\n\t}\n\n#endif /* #ifdef USE_LOCAL_SOCKETS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSSL/TLS Test Code\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Establish an SSL/TLS session */\n\nstatic int connectSSLTLS( const CRYPT_SESSION_TYPE sessionType,\n\t\t\t\t\t\t  const SSL_TEST_TYPE testType, const int version,\n\t\t\t\t\t\t  const int sessionID, const BOOLEAN localSession )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tconst BOOLEAN isServer = ( sessionType == CRYPT_SESSION_SSL_SERVER ) ? \\\n\t\t\t\t\t\t\t   TRUE : FALSE;\n\tconst BOOLEAN isErrorTest = ( testType >= SSL_TEST_CORRUPT_HANDSHAKE && \\\n\t\t\t\t\t\t\t\t  testType < SSL_TEST_LAST ) ? \\\n\t\t\t\t\t\t\t\t  TRUE : FALSE;\n\tconst char *versionStr[] = { \"SSLv3\", \"TLS 1.0\", \"TLS 1.1\", \"TLS 1.2\", \"TLS 1.3\" };\n\tconst C_STR serverName = ( testType == SSL_TEST_STARTTLS ) ? \\\n\t\t\t\t\t\t\t\tstarttlsInfo[ STARTTLS_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t ( testType == SSL_TEST_WEBSOCKETS ) ? \\\n\t\t\t\t\t\t\t\tsslInfo[ WS_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t ( testType == SSL_TEST_EAPTTLS ) ? \\\n\t\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t ( version == 0 ) ? \\\n\t\t\t\t\t\t\t\tsslInfo[ SSL_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t ( version == 1 ) ? \\\n\t\t\t\t\t\t\t\tsslInfo[ TLS_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t ( version == 2 ) ? \\\n\t\t\t\t\t\t\t\tsslInfo[ TLS11_SERVER_NO ].name : \\\n\t\t\t\t\t\t\t\tsslInfo[ TLS12_SERVER_NO ].name;\n\tBYTE *bulkBuffer = NULL;\t/* Needed for bogus uninit-value warnings */\n#ifdef USE_LOCAL_SOCKETS\n\tSOCKET netSocket;\n#endif /* USE_LOCAL_SOCKETS */\n#ifdef USE_TIMING\n\tHIRES_TIME timeVal;\n#endif /* USE_TIMING */\n\tchar buffer[ FILEBUFFER_SIZE ];\n#ifdef BROKEN_SERVER_INVALID_CERT\n\tint complianceLevel;\n#endif /* SSL servers with b0rken certs */\n\tint bytesCopied, protocol = PROTOCOL_SMTP, status;\n\n\t/* If it's a BadSSL test then the test type determines the server name */\n\tif( testType >= SSL_TEST_BADSSL_DH512 && \\\n\t\ttestType <= SSL_TEST_BADSSL_LONGNAME2 )\n\t\t{\n\t\tint i;\n\n\t\tfor( i = 0; badSslInfo[ i ].testType != 0; i++ )\n\t\t\t{\n\t\t\tif( badSslInfo[ i ].testType == testType )\n\t\t\t\t{\n\t\t\t\tserverName = badSslInfo[ i ].path;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\tif( badSslInfo[ i ].testType == 0 )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* If this is a local session, synchronise the client and server */\n\tif( localSession )\n\t\t{\n\t\tif( isServer )\n\t\t\t{\n\t\t\t/* Acquire the init mutex */\n\t\t\tacquireMutex();\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* We're the client, wait for the server to finish initialising */\n\t\t\tif( waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Timed out waiting for server to \"\n\t\t\t\t\t\t \"initialise, line %d.\\n\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* If this is the dual-thread server test and we're the second server \n\t   thread, skip the portions that have already been handled by the first \n\t   thread */\n#ifdef WINDOWS_THREADS\n\tif( isServer && testType == SSL_TEST_DUALTHREAD && sessionID == 0 )\n\t\tgoto dualThreadContinue;\n#endif /* WINDOWS_THREADS */\n\n\tif( sessionID != CRYPT_UNUSED )\n\t\tfprintf( outputStream, \"%02d: \", sessionID );\n\tfprintf( outputStream, \n\t\t\t \"%sTesting %s%s session%s...\\n\", isServer ? \"SVR: \" : \"\",\n\t\t\t localSession ? \"local \" : \"\", versionStr[ version ],\n\t\t\t ( testType == SSL_TEST_CLIENTCERT ) ? \" with client certs\" : \\\n\t\t\t ( testType == SSL_TEST_CLIENTCERT_MANUAL ) ? \" with manual verification of client cert\" : \\\n\t\t\t ( testType == SSL_TEST_STARTTLS || \\\n\t\t\t   testType == SSL_TEST_LOCALSERVER ) ? \" with local socket\" : \\\n\t\t\t ( testType == SSL_TEST_BULKTRANSER ) ? \" for bulk data transfer\" : \\\n\t\t\t ( testType == SSL_TEST_PSK ) ? \" with shared key\" : \\\n\t\t\t ( testType == SSL_TEST_PSK_CLIONLY ) ? \" with client-only PSK\" : \\\n\t\t\t ( testType == SSL_TEST_PSK_SVRONLY ) ? \" with server-only PSK\" : \\\n\t\t\t ( testType == SSL_TEST_ECC ) ? \" with P256 ECC crypto\" : \\\n\t\t\t ( testType == SSL_TEST_ECC_P384 ) ? \" with P384 ECC crypto\" : \\\n\t\t\t ( testType == SSL_TEST_WEBSOCKETS ) ? \" with WebSockets\" : \\\n\t\t\t ( testType == SSL_TEST_EAPTTLS ) ? \" with EAP-TTLS\" : \\\n\t\t\t ( testType >= SSL_TEST_BADSSL_DH512 && \\\n\t\t\t   testType <= SSL_TEST_BADSSL_LONGNAME2 ) ? \" with BadSSL checking\" : \\\n\t\t\t isErrorTest ? \" with checking for error handling\" : \"\" );\n#ifndef NO_SESSION_CACHE\n\tif( isServer )\n\t\t{\n\t\tfputs( \"  Warning: Session cache is active, subsequent sessions won't \"\n\t\t\t   \"use\\n  the full handshake.\", outputStream );\n\t\t}\n#endif /* NO_SESSION_CACHE */\n\tif( !isServer && !localSession )\n\t\tfprintf( outputStream, \"  Remote host: %s.\\n\", serverName );\n\n\t/* Create the SSL/TLS session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, sessionType );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSL/TLS session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptCreateSession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, \n\t\t\t\t\t\t\t\tversion );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\tif( version == 0 )\n\t\t\t{\n\t\t\tfputs( \"  (Couldn't enable use of SSLv3, continuing on the \"\n\t\t\t\t   \"assumption that it's\\n   disabled in this build).\\n\\n\", \n\t\t\t\t   outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptSetAttribute() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tif( isServer && isErrorTest )\n\t\t{\n\t\tcryptSetFaultType( ( testType == SSL_TEST_CORRUPT_HANDSHAKE ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_CORRUPT_HANDSHAKE : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_CORRUPT_DATA ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_CORRUPT_DATA : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_CORRUPT_MAC ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_CORRUPT_MAC : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_CORRUPT_FINISHED ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_SSL_CORRUPT_FINISHED : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_CORRUPT_IV ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_SSL_CORRUPT_IV : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_WRONGCERT ) ? \\\n\t\t\t\t\t\t\t FAULT_SESSION_WRONGCERT : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_BADSIG_HASH ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_HASH : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_BADSIG_SIG ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_SIG : \\\n\t\t\t\t\t\t   ( testType == SSL_TEST_BADSIG_DATA ) ? \\\n\t\t\t\t\t\t\t FAULT_BADSIG_DATA : \\\n\t\t\t\t\t\t\t FAULT_NONE );\n\t\t}\n#endif /* CONFIG_FAULTS && Debug */\n\n\t/* If we're doing a bulk data transfer, set up the necessary buffer */\n\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t{\n\t\tif( ( bulkBuffer = malloc( BULKDATA_BUFFER_SIZE ) ) == NULL )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Failed to allocated %ld bytes, \"\n\t\t\t\t\t \"line %d.\\n\", BULKDATA_BUFFER_SIZE, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( isServer )\n\t\t\thandleBulkBuffer( bulkBuffer, TRUE );\n\t\t}\n\n\t/* Set up the server information and activate the session */\n\tif( isServer )\n\t\t{\n\t\tCRYPT_CONTEXT privateKey;\n\n\t\tif( testType != SSL_TEST_LOCALSERVER )\n\t\t\t{\n\t\t\tif( !setLocalConnect( cryptSession, 443 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( testType != SSL_TEST_PSK && \\\n\t\t\ttestType != SSL_TEST_PSK_SVRONLY && \\\n\t\t\ttestType != SSL_TEST_DUALTHREAD )\n\t\t\t{\n\t\t\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\t\t\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\t\t\tvoid *fileNamePtr = filenameBuffer;\n\n\t\t\t/* We don't add a private key if we're doing TLS-PSK, to test \n\t\t\t   TLS-PSK's abiltiy to work without a PKC */\n\t\t\tif( testType == SSL_TEST_ECC || testType == SSL_TEST_ECC_P384 )\n\t\t\t\t{\n\t\t\t\tfilenameFromTemplate( filenameBuffer, \n\t\t\t\t\t\t\t\t\t  SERVER_ECPRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t\t\t\t  ( testType == SSL_TEST_ECC_P384 ) ? \\\n\t\t\t\t\t\t\t\t\t\t384 : 256 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tfilenameFromTemplate( filenameBuffer, \n\t\t\t\t\t\t\t\t\t  SERVER_PRIVKEY_FILE_TEMPLATE, 1 );\n\t\t\t\t}\n#ifdef UNICODE_STRINGS\n\t\t\tmbstowcs( wcBuffer, filenameBuffer, \n\t\t\t\t\t  strlen( filenameBuffer ) + 1 );\n\t\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\t\tstatus = getPrivateKey( &privateKey, fileNamePtr,\n\t\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t\t\t\tprivateKey );\n\t\t\t\tcryptDestroyContext( privateKey );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && testType == SSL_TEST_CLIENTCERT )\n\t\t\t{\n\t\t\tCRYPT_KEYSET cryptKeyset;\n\n\t\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tDATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t\tCRYPT_KEYOPT_READONLY );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"SVR: Client certificate keyset open \"\n\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_KEYSET,\n\t\t\t\t\t\t\t\t\t\tcryptKeyset );\n\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && testType == SSL_TEST_CLIENTCERT_MANUAL )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSL_OPTIONS,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SSLOPTION_MANUAL_CERTCHECK );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && testType == SSL_TEST_LOCALSERVER )\n\t\t\t{\n#ifdef USE_LOCAL_SOCKETS\n\t\t\t/* Try and set up a local server socket.  Since the socket type \n\t\t\t   can be unsigned, we have to force it to signed to perform the\n\t\t\t   error check on it.\n\t\t\t   \n\t\t\t   We don't treat most types of failure as fatal since there are \n\t\t\t   a great many minor things that can go wrong that we don't \n\t\t\t   want to have to handle without writing half an MUA */\n\t\t\tif( !initSockets() )\n\t\t\t\treturn( FALSE );\n\t\t\tnetSocket = createServerSocket();\n\t\t\tif( ( signed ) netSocket <= 0 )\n\t\t\t\t{\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\tendSockets( 0 );\n\t\t\t\tif( netSocket == CRYPT_OK )\n\t\t\t\t\t{\n\t\t\t\t\tfputs( \"This is a nonfatal error (a great many other \"\n\t\t\t\t\t\t   \"things can go wrong while\\nsetting up the server \"\n\t\t\t\t\t\t   \"socket).\\n\\n\", outputStream );\n\t\t\t\t\treturn( TRUE );\n\t\t\t\t\t}\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* We can't send the socket to cryptlib at this point because \n\t\t\t   it's only a generic listening socket, not the connected \n\t\t\t   socket that's created from the listening socket, so we have \n\t\t\t   to defer that until later */\n#else\n\t\t\tstatus = setPseudoSocket( cryptSession );\n#endif /* OS-specific local socket handling */\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* We're the client */\n\t\tif( testType == SSL_TEST_STARTTLS )\n\t\t\t{\n#ifdef USE_LOCAL_SOCKETS\n\t\t\t/* Try and negotiate a STARTTLS session.  Since the socket type \n\t\t\t   can be unsigned, we have to force it to signed to perform the\n\t\t\t   error check on it.\n\t\t\t   \n\t\t\t   We don't treat most types of failure as fatal since there are \n\t\t\t   a great many minor things that can go wrong that we don't \n\t\t\t   want to have to handle without writing half an MUA */\n\t\t\tif( !initSockets() )\n\t\t\t\treturn( FALSE );\n\t\t\tnetSocket = negotiateSTARTTLS( &protocol );\n\t\t\tif( ( signed ) netSocket <= 0 )\n\t\t\t\t{\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\tendSockets( 0 );\n\t\t\t\tif( netSocket == CRYPT_OK )\n\t\t\t\t\t{\n\t\t\t\t\tfputs( \"This is a nonfatal error (a great many other \"\n\t\t\t\t\t\t   \"things can go wrong while\\nnegotiating through \"\n\t\t\t\t\t\t   \"to the TLS upgrade).\\n\\n\", outputStream );\n\t\t\t\t\treturn( TRUE );\n\t\t\t\t\t}\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = setSocket( cryptSession, netSocket );\n#else\n\t\t\tstatus = setPseudoSocket( cryptSession );\n#endif /* OS-specific local socket handling */\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( localSession )\n\t\t\t\t{\n\t\t\t\tif( !setLocalConnect( cryptSession, 443 ) )\n\t\t\t\t\t{\n\t\t\t\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\t\t\t\tfree( bulkBuffer );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tif( LOCAL_HOST_NAME[ 0 ] != 'l' )\n\t\t\t\t\t{\n\t\t\t\t\t/* We're performing a connect to the local host under a \n\t\t\t\t\t   name other than \"localhost\", disable host-name\n\t\t\t\t\t   verification */\n\t\t\t\t\tcryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS,\n\t\t\t\t\t\t\t\t\t   CRYPT_SSLOPTION_DISABLE_NAMEVERIFY );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_NAME, serverName,\n\t\t\t\t\t\t\t\tparamStrlen( serverName ) );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && \\\n\t\t\t( testType == SSL_TEST_CLIENTCERT || \\\n\t\t\t  testType == SSL_TEST_CLIENTCERT_MANUAL ) )\n\t\t\t{\n\t\t\tCRYPT_CONTEXT privateKey;\n\n\t\t\t/* Depending on which server we're testing against we need to \n\t\t\t   use different private keys */\n#if ( TLS12_SERVER_NO == 30 && 0 )\n\t\t\tgetPrivateKey( &privateKey, SSL_CLI_PRIVKEY_FILE, \n\t\t\t\t\"cc47650c403654f6fe439e5c88a2e6c2_66335081-ee61-4aa8-862d-a423d58\",\n\t\t\t\tTEST_PRIVKEY_PASSWORD );\n#else\n\t\t\tstatus = getPrivateKey( &privateKey, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n#endif /* Different keys for different servers */\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tCRYPT_KEYSET cryptKeyset;\n\t\t\t\tint localStatus;\n\n\t\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\n\t\t\t\t/* In addition to adding the key to the session, we also try \n\t\t\t\t   adding it to the server's key database in case it's not \n\t\t\t\t   present yet */\n\t\t\t\tlocalStatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tDATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t\tCRYPT_KEYOPT_NONE );\n\t\t\t\tif( cryptStatusOK( localStatus ) )\n\t\t\t\t\t{\n\t\t\t\t\tlocalStatus = cryptAddPublicKey( cryptKeyset, \n\t\t\t\t\t\t\t\t\t\t\t\t\t privateKey );\n\t\t\t\t\tcryptKeysetClose( cryptKeyset );\n\t\t\t\t\tif( cryptStatusError( localStatus ) && \\\n\t\t\t\t\t\tlocalStatus != CRYPT_ERROR_DUPLICATE )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/* The key isn't already present (or we'd get a\n\t\t\t\t\t\t   CRYPT_ERROR_DUPLICATE), but also couldn't be \n\t\t\t\t\t\t   added, there's some sort of problem */\n\t\t\t\t\t\tfprintf( outputStream, \"Attempt to add client \"\n\t\t\t\t\t\t\t\t \"certificate to server access-control \"\n\t\t\t\t\t\t\t\t \"database failed\\n  with error code %d, \"\n\t\t\t\t\t\t\t\t \"line %d.\\n\", localStatus, __LINE__ );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tcryptDestroyContext( privateKey );\n\t\t\t\t}\n\t\t\t}\n#if 0\t/* Optional proxy for net access */\n\t\tstatus = cryptSetAttributeString( CRYPT_UNUSED,\n\t\t\t\t\t\t\t\tCRYPT_OPTION_NET_HTTP_PROXY, \"[Autodetect]\",\n\t\t\t\t\t\t\t\t12 );\n#endif /* 0 */\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t( testType == SSL_TEST_PSK || \\\n\t\t  ( isServer && testType == SSL_TEST_PSK_SVRONLY ) || \\\n\t\t  ( !isServer && testType == SSL_TEST_PSK_CLIONLY ) ) )\n\t\t{\n\t\t/* If we're testing the no-PSK handling, only the server is \n\t\t   expecting TLS-PSK, so the client isn't supplied with a \n\t\t   password */\n\t\tif( cryptStatusOK( status ) && isServer && testType == SSL_TEST_PSK )\n\t\t\t{\n\t\t\t/* If we're testing PSK, add several preceding usernames and \n\t\t\t   passwords */\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"before1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"before1\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"before1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"before1\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"before2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"before2\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"before2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"before2\" ) ) );\n\t\t\t}\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, SSL_USER_NAME,\n\t\t\t\t\t\t\t\tparamStrlen( SSL_USER_NAME ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, SSL_PASSWORD,\n\t\t\t\t\t\t\t\tparamStrlen( SSL_PASSWORD ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) && isServer && testType == SSL_TEST_PSK )\n\t\t\t{\n\t\t\t/* If we're testing PSK, add several succeeding usernames and\n\t\t\t   passwords */\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"after1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"after1\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"after1\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"after1\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, TEXT( \"after2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"after2\" ) ) );\n\t\t\tcryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, TEXT( \"after2\" ),\n\t\t\t\t\t\t\t\tparamStrlen( TEXT( \"after2\" ) ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\ttestType == SSL_TEST_WEBSOCKETS )\n\t\t{\n#if WS_SERVER_NO != 49\n\t\t/* The use of WebSockets can be selected implicitly via a \"wss://\" \n\t\t   URL or explicitly by setting the CRYPT_SESSINFO_SUBPROTOCOL \n\t\t   attribute, for non-loopback tests we use ixplicit selection but\n\t\t   for the loopback tests, where we're just connecting to \n\t\t   \"localhost\", we have to explicitly select WebSockets */\n\t\tif( localSession )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SSL_SUBPROTOCOL, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SUBPROTOCOL_WEBSOCKETS );\n\t\t\t}\n#endif /* Loopback websockets server */\n#if WS_SERVER_NO != 50 && WS_SERVER_NO != 51 && WS_SERVER_NO != 52\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSL_WSPROTOCOL, \n\t\t\t\t\t\t\t\t\t\t\t  \"mqtt\", 4 );\n\t\t\t}\n#endif /* WebSockets servers that don't acknowledge the protocol type */\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\ttestType == SSL_TEST_EAPTTLS )\n\t\t{\n#if EAP_SERVER_NO == 56\n\t\t/* The local test server uses a self-signed cert with a generic host \n\t\t   name, so we have to disable certificate name verification in \n\t\t   order to continue */\n\t\tcryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS, \n\t\t\t\t\t\t   CRYPT_SSLOPTION_DISABLE_NAMEVERIFY );\n#endif /* EAP_SERVER_NO == 56 */\n\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\tCRYPT_SESSINFO_SSL_SUBPROTOCOL, \n\t\t\t\t\t\t\tCRYPT_SUBPROTOCOL_EAPTTLS );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME, \n\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].userName,\n\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].userName ) );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\tCRYPT_SESSINFO_PASSWORD, \n\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].password,\n\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].password ) );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( testType == SSL_TEST_STARTTLS || \\\n\t\t\t( isServer && testType == SSL_TEST_LOCALSERVER ) )\n\t\t\t{\n#ifdef USE_LOCAL_SOCKETS\n\t\t\tendSockets( netSocket );\n#else\n\t\t\t/* Creating a socket in a portable manner is too difficult so \n\t\t\t   we've passed in a stdio handle, this should return an error \n\t\t\t   since it's not a blocking socket */\n\t\t\treturn( TRUE );\n#endif /* USE_LOCAL_SOCKETS */\n\t\t\t}\n\t\tfprintf( outputStream, \"cryptSetAttribute/AttributeString() \"\n\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\tfree( bulkBuffer );\n\t\treturn( FALSE );\n\t\t}\n#ifdef BROKEN_SERVER_INVALID_CERT\n\tfputs( \"(Setting certificate compliance level to oblivious to deal with \"\n\t\t   \"broken server).\", outputStream );\n\tcryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   &complianceLevel );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );\n#endif /* SSL servers with b0rken certs */\n#ifdef BROKEN_SERVER_WRONG_CERT\n\tfputs( \"(Disabling certificate name checking to deal with broken \"\n\t\t   \"server).\", outputStream );\n\tcryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS, \n\t\t\t\t\t   CRYPT_SSLOPTION_DISABLE_NAMEVERIFY );\n#endif /* SSL servers with the wrong cert for the domain */\n\tif( localSession )\n\t\t{\n\t\t/* If we're running a local loopback test, display additional \n\t\t   information indicating when the session is activated, since \n\t\t   the multithreaded tests may not get to this point until long \n\t\t   after the threads are started */\n\t\tif( sessionID != CRYPT_UNUSED )\n\t\t\tfprintf( outputStream, \"%02d: \", sessionID );\n\t\tfprintf( outputStream, \"%sActivating %s session...\\n\", \n\t\t\t\t isServer ? \"SVR: \" : \"\", versionStr[ version ] );\n\n\t\t/* For the loopback test we also increase the connection timeout to \n\t\t   a higher-than-normal level, since this gives us more time for \n\t\t   tracing through the code when debugging */\n\t\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_CONNECTTIMEOUT, \n\t\t\t\t\t\t   120 );\n\n\t\tif( isServer )\n\t\t\t{\n\t\t\t/* Tell the client that we're ready to go */\n\t\t\treleaseMutex();\n\n\t\t\t/* Connect the server socket and send it to the session before \n\t\t\t   activating it.  This is a bit of a problem during the \n\t\t\t   loopback testing because we're in a race condition with the \n\t\t\t   client, we can't activate the session until the client has \n\t\t\t   connected, but we can't call connectServerSocket() before \n\t\t\t   releasing the mutex since it's a blocking call.  To deal \n\t\t\t   with this we have the client sleep for awhile after the mutex \n\t\t\t   is released in the hope that the server gets into \n\t\t\t   connectServerSocket() before the client has time to set up \n\t\t\t   its session and connect */\n\t\t\tif( testType == SSL_TEST_LOCALSERVER )\n\t\t\t\t{\n#ifdef USE_LOCAL_SOCKETS\n\t\t\t\tnetSocket = connectServerSocket( netSocket );\n\t\t\t\tif( ( signed ) netSocket <= 0 )\n\t\t\t\t\t{\n\t\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\t\tendSockets( 0 );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tstatus = setSocket( cryptSession, netSocket );\n#endif /* USE_LOCAL_SOCKETS */\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* See the comment above */\n\t\t\tif( testType == SSL_TEST_LOCALSERVER )\n\t\t\t\tdelayThread( 1 );\n\t\t\t}\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n#ifdef BROKEN_SERVER_INVALID_CERT\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,\n\t\t\t\t\t   complianceLevel );\n#endif /* SSL server with b0rken certs */\n\tif( isServer && testType != SSL_TEST_PSK_CLIONLY && \\\n\t\t\t\t\ttestType != SSL_TEST_PSK_SVRONLY )\n\t\t{\n\t\t/* We don't check the return status for this since the session may \n\t\t   be disconnected before we get the client info, which would cause \n\t\t   us to bail out before we display the error info */\n\t\tif( sessionID != CRYPT_UNUSED )\n\t\t\tfprintf( outputStream, \"%02d: \", sessionID );\n\t\tprintConnectInfo( cryptSession );\n\t\t}\n\tif( isServer && testType == SSL_TEST_CLIENTCERT_MANUAL && \\\n\t\tstatus == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCertChain;\n\n\t\t/* Allow the auth.and complete the handshake */\n\t\tfputs( \"SVR: Manually verifying client certificate...\\n\", \n\t\t\t   outputStream );\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptCertChain );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* In a real-world situation we'd check the certificate at this\n\t\t\t   point, for now we just destroy it again and tell the server\n\t\t\t   to continue */\n\t\t\tcryptDestroyCert( cryptCertChain );\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, TRUE );\n\t\t\t}\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_ACTIVE, TRUE );\n\t\t\t}\n\t\t}\n#ifdef WINDOWS_THREADS\n\tif( isServer && testType == SSL_TEST_DUALTHREAD && \\\n\t\tstatus == CRYPT_ENVELOPE_RESOURCE )\n\t\t{\n\t\tstatic CRYPT_SESSION localCryptSession = 0;\n\t\tunsigned threadID;\n\n\t\t/* Start a second thread to complete the handshake and exit */\n\t\tlocalCryptSession = cryptSession;\n\t\t_beginthreadex( NULL, 0, tlsServerDualThread2, NULL, 0, &threadID );\n\t\treturn( TRUE );\n\n\t\t/* The second thread continues from here */\ndualThreadContinue:\n\t\tassert( localSession > 0 );\n\t\tcryptSession = localCryptSession;\n\n\t\t/* Allow the auth.and complete the handshake */\n\t\tfputs( \"SVR: Confirming authentication to client...\", \n\t\t\t   outputStream );\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, TRUE );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_ACTIVE, TRUE );\n\t\t\t}\n\t\t}\n#endif /* WINDOWS_THREADS */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tchar strBuffer[ 128 ];\n\n\t\tif( testType == SSL_TEST_STARTTLS || \\\n\t\t\t( isServer && testType == SSL_TEST_LOCALSERVER ) )\n\t\t\t{\n#ifdef USE_LOCAL_SOCKETS\n\t\t\tendSockets( netSocket );\n#else\n\t\t\t/* If we're using a dummy local socket, we'll get a R/W error at \n\t\t\t   this point since it's not connected to anything, so we \n\t\t\t   intercept it before it gets any further */\n\t\t\tif( status == CRYPT_ERROR_READ || status == CRYPT_ERROR_WRITE )\n\t\t\t\t{\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n#endif /* USE_LOCAL_SOCKETS */\n\t\t\t}\n\t\tif( sessionID != CRYPT_UNUSED )\n\t\t\tfprintf( outputStream, \"%02d: \", sessionID );\n\t\tsprintf( strBuffer, \"%sAttempt to activate %s%s session\",\n\t\t\t\t isServer ? \"SVR: \" : \"\", localSession ? \"local \" : \"\",\n\t\t\t\t versionStr[ version ] );\n\t\tprintExtError( cryptSession, strBuffer, status, __LINE__ );\n\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\tfree( bulkBuffer );\n\t\tif( !isServer && isServerDown( cryptSession, status ) )\n\t\t\t{\n\t\t\tfputs( \"  (Server could be down, faking it and \"\n\t\t\t\t   \"continuing...)\\n\\n\", outputStream );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\t\tif( isErrorTest || testType == SSL_TEST_PSK_CLIONLY || \\\n\t\t\ttestType == SSL_TEST_PSK_SVRONLY )\n\t\t\t{\n\t\t\tif( isErrorTest )\n\t\t\t\t{\n\t\t\t\tif( isServer )\n\t\t\t\t\t{\n\t\t\t\t\t/* The corrupt-handshake test is detcted by the server \n\t\t\t\t\t   before the client even though the server has sent out\n\t\t\t\t\t   a corrupted message because the client sends their \n\t\t\t\t\t   Finished message first, and that contains the overall\n\t\t\t\t\t   handshake MAC which is different for the client.  In\n\t\t\t\t\t   addition this can be reported as a CRYPT_ERROR_BADDATA\n\t\t\t\t\t   depending on where the corruption is caught */\n\t\t\t\t\tif( testType == SSL_TEST_CORRUPT_HANDSHAKE && \\\n\t\t\t\t\t\tstatus != CRYPT_ERROR_SIGNATURE && \\\n\t\t\t\t\t\tstatus != CRYPT_ERROR_BADDATA )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfprintf( outputStream, \"Test returned status %d, \"\n\t\t\t\t\t\t\t\t \"should have been %d or %d.\\n\", status, \n\t\t\t\t\t\t\t\t CRYPT_ERROR_SIGNATURE, \n\t\t\t\t\t\t\t\t CRYPT_ERROR_BADDATA );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( testType != SSL_TEST_CORRUPT_HANDSHAKE && \\\n\t\t\t\t\t\ttestType != SSL_TEST_CORRUPT_FINISHED && \\\n\t\t\t\t\t\ttestType != SSL_TEST_CORRUPT_IV && \\\n\t\t\t\t\t\ttestType != SSL_TEST_CORRUPT_MAC && \\\n\t\t\t\t\t\tstatus != CRYPT_ERROR_SIGNATURE && \\\n\t\t\t\t\t\tstatus != CRYPT_ERROR_BADDATA )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfprintf( outputStream, \"Test returned status %d, \"\n\t\t\t\t\t\t\t\t \"should have been %d or %d.\\n\", status, \n\t\t\t\t\t\t\t\t CRYPT_ERROR_SIGNATURE,\n\t\t\t\t\t\t\t\t CRYPT_ERROR_BADDATA );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t/* These tests are supposed to fail, so if this happens then the \n\t\t\t   overall test has succeeded */\n\t\t\tfputs( \"  (This test checks error handling, so the failure \"\n\t\t\t\t   \"response is correct).\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\t\tif( ( testType == SSL_TEST_NORMAL || \\\n\t\t\t  testType == SSL_TEST_STARTTLS ) && ( version == 0 ) )\n\t\t\t{\n\t\t\tfputs( \"  (This test checks SSLv3 functionality, which fewer and \"\n\t\t\t\t   \"fewer servers\\n   support, assuming that the test \"\n\t\t\t\t   \"failure was due to SSLv3 support being\\n   disabled on \"\n\t\t\t\t   \"the server).\\n\\n\", outputStream );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The error tests should cause handshake failures, so getting to this \n\t   point is an error */\n\tif( isErrorTest && testType != SSL_TEST_CORRUPT_DATA )\n\t\t{\n\t\tcryptDestroySession( cryptSession );\n\t\tfputs( \"  (This test should have led to a handshake failure but \"\n\t\t\t   \"didn't, test has\\n   failed).\\n\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* The CLIONLY/SVRONLY test is supposed to fail, if this doesn't happen \n\t   then there's a problem */\n#ifdef NO_SESSION_CACHE\n\tif( testType == SSL_TEST_PSK_CLIONLY || \\\n\t\ttestType == SSL_TEST_PSK_SVRONLY )\n\t\t{\n\t\tfprintf( outputStream, \"%sTLS-PSK handshake without password should \"\n\t\t\t\t \"have failed but succeeded,\\nline %d.\\n\",\n\t\t\t\t isServer ? \"SVR: \" : \"\", __LINE__  );\n\t\treturn( FALSE );\n\t\t}\n#endif /* NO_SESSION_CACHE */\n\n\t/* If we're testing session resumption and there's a server key present \n\t   then we didn't actually resume the session */\n#ifndef NO_SESSION_CACHE\n\tif( testType == SSL_TEST_RESUME )\n\t\t{\n\t\tCRYPT_CONTEXT serverKey;\n\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&serverKey );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tcryptDestroyContext( serverKey );\n\t\t\tfprintf( outputStream, \"%sSession resumption didn't actually \"\n\t\t\t\t\t \"resume a previous session, line %d.\\n\", \n\t\t\t\t\t isServer ? \"SVR: \" : \"\", __LINE__  );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n#endif /* !NO_SESSION_CACHE */\n\n\t/* Report the session security info */\n\tif( testType != SSL_TEST_MULTITHREAD )\n\t\t{\n\t\tconst BOOLEAN isFirstSession = \\\n\t\t\t( testType == SSL_TEST_NORMAL && version == 0 ) ? TRUE : FALSE;\n\t\tint actualVersion;\n\n#ifdef NO_SESSION_CACHE\n\t\tif( !printSecurityInfo( cryptSession, isServer,\n\t\t\t\t( testType != SSL_TEST_PSK && testType != SSL_TEST_RESUME ), \n\t\t\t\t( !isServer && testType != SSL_TEST_PSK && \\\n\t\t\t\t\t\t\t   testType != SSL_TEST_RESUME ),\n\t\t\t\t( isServer && ( testType == SSL_TEST_CLIENTCERT || \\\n\t\t\t\t\t\t\t\ttestType == SSL_TEST_CLIENTCERT_MANUAL ) ) ) )\n\t\t\t{\n\t\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\t\tfree( bulkBuffer );\n\t\t\treturn( FALSE );\n\t\t\t}\n#else\n\t\tif( !printSecurityInfo( cryptSession, isServer, isFirstSession,\n\t\t\t\t\t\t\t\t!isServer && isFirstSession, FALSE ) )\n\t\t\t{\n\t\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\t\tfree( bulkBuffer );\n\t\t\treturn( FALSE );\n\t\t\t}\n#endif /* NO_SESSION_CACHE */\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,\n\t\t\t\t\t\t\t\t\t&actualVersion );\n\t\tif( cryptStatusOK( status ) && actualVersion != version )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Warning: Expected to connect using %s \"\n\t\t\t\t\t \"but only connected using %s.\\n\", versionStr[ version ],\n\t\t\t\t\t versionStr[ actualVersion ] );\n\t\t\t}\n\t\t}\n#ifdef NO_SESSION_CACHE\n\tif( ( !localSession && !isServer && testType != SSL_TEST_PSK ) ||\n\t\t( localSession && isServer && \\\n\t\t  ( testType == SSL_TEST_CLIENTCERT || \\\n\t\t\ttestType == SSL_TEST_CLIENTCERT_MANUAL ) ) )\n#else\n\tif( !localSession && !isServer && testType != SSL_TEST_PSK )\n#endif /* NO_SESSION_CACHE */\n\t\t{\n\t\tCRYPT_CERTIFICATE cryptCertificate;\n\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&cryptCertificate );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"%sCouldn't get %s certificate, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", isServer ? \"SVR: \" : \"\", \n\t\t\t\t\t isServer ? \"client\" : \"server\", status, __LINE__ );\n\t\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\t\tfree( bulkBuffer );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfputs( localSession ? \"SVR: Client certificate details are:\" : \\\n\t\t\t\t\t\t\t  \"Server certificate details are:\", \n\t\t\t\t\t\t\t  outputStream );\n\t\tprintCertChainInfo( cryptCertificate );\n\t\tcryptDestroyCert( cryptCertificate );\n\t\t}\n\tif( isServer && testType == SSL_TEST_PSK )\n\t\t{\n\t\tC_CHR userNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 ];\n\t\tint length;\n\n\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t  userNameBuffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: Couldn't read client user name, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n#ifdef UNICODE_STRINGS\n\t\tuserNameBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"SVR: Client user name = '%S'.\\n\", \n\t\t\t\t userNameBuffer );\n#else\n\t\tuserNameBuffer[ length ] = '\\0';\n\t\tfprintf( outputStream, \"SVR: Client user name = '%s'.\\n\", \n\t\t\t\t userNameBuffer );\n#endif /* UNICODE_STRINGS */\n#ifdef NO_SESSION_CACHE\n\t\tif( length != ( int ) paramStrlen( SSL_USER_NAME ) || \\\n\t\t\tmemcmp( userNameBuffer, SSL_USER_NAME, \\\n\t\t\t\t\tparamStrlen( SSL_USER_NAME ) ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: User name was '%s', should have \"\n\t\t\t\t\t \"been '%s', line %d.\\n\", userNameBuffer, SSL_USER_NAME, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n#else\n\t\tif( length < 8 || memcmp( userNameBuffer, \"[Resumed\", 8 ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"SVR: User name was '%s', should have \"\n\t\t\t\t\t \"been an indication that\\n     the session was \"\n\t\t\t\t\t \"resumed, line %d.\\n\", userNameBuffer, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n#endif /* NO_SESSION_CACHE */\n\t\t}\n\n\t/* Send data over the SSL/TLS link.  If we're doing a bulk transfer \n\t   we use fully asynchronous I/O to verify the timeout handling in \n\t   the session code */\n#if defined( IS_HIGHVOLUME_SERVER )\n\t/* This server has a large amount of data on it, used to test high-\n\t   latency bulk transfers, so we set a larger timeout for the read */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t\t\t15 );\n#elif defined USE_TIMING\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t\t\t5 );\n#else\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_OPTION_NET_READTIMEOUT,\n\t\t\t\t\t\t\t\t( testType == SSL_TEST_BULKTRANSER ) ? 0 : 5 );\n#endif /* IS_HIGHVOLUME_SERVER */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t\tfree( bulkBuffer );\n\t\tprintExtError( cryptSession, isServer ? \\\n\t\t\t\t\t   \"SVR: Session timeout set\" : \"Session timeout set\", \n\t\t\t\t\t   status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( testType == SSL_TEST_BULKTRANSER )\n\t\t{\n#ifdef USE_TIMING\n\t\tint timeMS;\n\n\t\ttimeVal = timeDiff( 0 );\n#endif /* USE_TIMING */\n\t\tif( isServer )\n\t\t\t{\n\t\t\tlong byteCount = 0;\n\n\t\t\tdo\n\t\t\t\t{\n\t\t\t\tstatus = cryptPushData( cryptSession, bulkBuffer + byteCount,\n\t\t\t\t\t\t\t\t\t\tBULKDATA_BUFFER_SIZE - byteCount,\n\t\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\t\t\tbyteCount += bytesCopied;\n\t\t\t\t}\n\t\t\twhile( ( cryptStatusOK( status ) || \\\n\t\t\t\t\t status == CRYPT_ERROR_TIMEOUT ) && \\\n\t\t\t\t   byteCount < BULKDATA_BUFFER_SIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession,\n\t\t\t\t\t\t\t   \"SVR: Send of bulk data to client\", status,\n\t\t\t\t\t\t\t   __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession,\n\t\t\t\t\t\t\t   \"SVR: Flush of bulk data to client\", status,\n\t\t\t\t\t\t\t   __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( byteCount != BULKDATA_BUFFER_SIZE )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Only sent %ld of %ld bytes, \"\n\t\t\t\t\t\t \"line %d.\\n\", byteCount, BULKDATA_BUFFER_SIZE, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tlong byteCount = 0;\n\n\t\t\tdo\n\t\t\t\t{\n\t\t\t\tstatus = cryptPopData( cryptSession, bulkBuffer + byteCount,\n\t\t\t\t\t\t\t\t\t   BULKDATA_BUFFER_SIZE - byteCount,\n\t\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\t\tbyteCount += bytesCopied;\n\t\t\t\t}\n\t\t\twhile( ( cryptStatusOK( status ) || \\\n\t\t\t\t\t status == CRYPT_ERROR_TIMEOUT ) && \\\n\t\t\t\t   byteCount < BULKDATA_BUFFER_SIZE );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tchar strBuffer[ 256 ];\n\n\t\t\t\tsprintf( strBuffer, \"Read of bulk data from server aborted \"\n\t\t\t\t\t\t\t\t\t\"after %ld of %ld bytes were read\\n(last \"\n\t\t\t\t\t\t\t\t\t\"read = %d bytes), transfer\",\n\t\t\t\t\t\t\t\t\tbyteCount, BULKDATA_BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\tbytesCopied );\n\t\t\t\tprintExtError( cryptSession, strBuffer, status, __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( byteCount != BULKDATA_BUFFER_SIZE )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Only received %ld of %ld bytes, \"\n\t\t\t\t\t\t \"line %d.\\n\", byteCount, BULKDATA_BUFFER_SIZE, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !handleBulkBuffer( bulkBuffer, FALSE ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Received buffer contents don't \"\n\t\t\t\t\t\t \"match sent buffer contents, line %d.\", __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n#ifdef USE_TIMING\n\t\ttimeVal = timeDiff( timeVal ); \n\t\tfprintf( outputStream, \"Time for %s transfer: \", \n\t\t\t\t isServer ? \"server-to-client\" : \"client-to-server\" );\n\t\ttimeMS = timeDisplay( timeVal );\n\t\tfprintf( outputStream, \"Data rate = %d kBytes/second.\\n\", \n\t\t\t\t ( int ) ( BULKDATA_BUFFER_SIZE / timeMS ) );\n#endif /* USE_TIMING */\n\t\tfree( bulkBuffer );\n\t\t}\n\telse\n\t\t{\n\t\t/* It's a standard transfer, send/receive and HTTP request/response. \n\t\t   We clean up if we exit due to an error, if we're running a local \n\t\t   loopback test the client and server threads can occasionally lose \n\t\t   sync, which isn't a fatal error but can turn into a \n\t\t   CRYPT_ERROR_INCOMPLETE once all the tests are finished */\n\t\tif( isServer )\n\t\t\t{\n\t\t\tBYTE textBuffer[ 1024 ];\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( resume )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 819 )\n#endif /* IBM medium iron */\n\t\t\tconst char serverReply[] = \\\n\t\t\t\t\"HTTP/1.0 200 OK\\n\"\n\t\t\t\t\"Date: Fri, 7 June 2018 20:02:07 GMT\\n\"\n\t\t\t\t\"Server: cryptlib SSL/TLS test\\n\"\n\t\t\t\t\"Content-Type: text/html\\n\"\n\t\t\t\t\"Connection: Close\\n\"\n\t\t\t\t\"\\n\"\n\t\t\t\t\"<!DOCTYPE HTML SYSTEM \\\"html.dtd\\\">\\n\"\n\t\t\t\t\"<html>\\n\"\n\t\t\t\t\"<head>\\n\"\n\t\t\t\t\"<title>cryptlib %s test page</title>\\n\"\n\t\t\t\t\"<body>\\n\"\n\t\t\t\t\"Test message from the cryptlib %s server.<p>\\n\"\n\t\t\t\t\"</body>\\n\"\n\t\t\t\t\"</html>\\n\";\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\t\t\tint bytesToSend;\n\n\t\t\t/* Print the text of the request from the client */\n\t\t\tstatus = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,\n\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession, \"SVR: Attempt to read data \"\n\t\t\t\t\t\t\t   \"from client\", status, __LINE__ );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbuffer[ bytesCopied ] = '\\0';\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\tif( testType != SSL_TEST_MULTITHREAD )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"---- Client sent %d bytes ----\\n\", \n\t\t\t\t\t\t bytesCopied );\n\t\t\t\tfputs( buffer, outputStream );\n\t\t\t\tfputs( \"---- End of output ----\", outputStream );\n\t\t\t\t}\n\n\t\t\t/* Send a reply */\n\t\t\tbytesToSend = sprintf( textBuffer, serverReply, \n\t\t\t\t\t\t\t\t   versionStr[ version ], \n\t\t\t\t\t\t\t\t   versionStr[ version ] );\n\t\t\tstatus = cryptPushData( cryptSession, textBuffer, bytesToSend, \n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\tif( cryptStatusError( status ) || bytesCopied != bytesToSend )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession, \"Attempt to send data to \"\n\t\t\t\t\t\t\t   \"client\", status, __LINE__ );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Wait for the data to be flushed through to the client before \n\t\t\t   we close the session */\n\t\t\tdelayThread( 1 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tBYTE fetchString[ 256 ];\n\t\t\tint fetchStringLen;\n\n\t\t\t/* Send a fetch request to the server */\n\t\t\tif( testType == SSL_TEST_STARTTLS )\n\t\t\t\t{\n\t\t\t\tswitch( protocol )\n\t\t\t\t\t{\n\t\t\t\t\tcase PROTOCOL_SMTP:\n\t\t\t\t\t\tstrcpy( fetchString, \"EHLO foo.bar.com\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PROTOCOL_POP:\n\t\t\t\t\t\tstrcpy( fetchString, \"CAPA\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PROTOCOL_IMAP:\n\t\t\t\t\t\tstrcpy( fetchString, \"a003 CAPABILITY\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tstrcpy( fetchString, \"USER test\\r\\n\" );\n\t\t\t\t\t}\n\t\t\t\tfetchStringLen = strlen( fetchString );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( testType == SSL_TEST_EAPTTLS )\n\t\t\t\t\t{\n#if 0\n\t\t\t\t\tBYTE eapChallenge[ 64 ];\n\t\t\t\t\tint eapChallengeLength;\n\n\t\t\t\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSL_EAPCHALLENGE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  eapChallenge, &eapChallengeLength );\n\t\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tstatus = createTTLSAVPMSCHAPv2( fetchString, &fetchStringLen,\n\t\t\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].userName,\n\t\t\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].userName ),\n\t\t\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].password,\n\t\t\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].password ),\n\t\t\t\t\t\t\t\t\teapChallenge );\n\t\t\t\t\t\t}\n#if 0\n\t\t\t\t\tstatic const BYTE ttlsAVP[] = {\n\t\t/*  0 */\t\t\"\\x00\\x00\\x00\\x01\\x40\\x00\\x00\\x0Ctest\"\t/* RADIUS User-Name */\n\t\t/* 12 */\t\t\"\\x00\\x00\\x00\\x0B\\xC0\\x00\\x00\\x1C\\x00\\x00\\x01\\x37\"\n\t\t/* 24 */\t\t\t\"****************\"\t\t\t\t\t/* RADIUS MS-CHAP-Challenge */\n\t\t/* 40 */\t\t\"\\x00\\x00\\x00\\x19\\xC0\\x00\\x00\\x3E\\x00\\x00\\x01\\x37\"\n\t\t/* 52 */\t\t\t\"\\xFF\\x00\"\t\t\t\t\t\t\t/* RADIUS MS-CHAP-Response */\n\t\t/* 54 */\t\t\t\"****************\"\t\t\t\t\t\t/* Peer-Challange */\n\t\t/* 70 */\t\t\t\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\t\t/* RFU */\n\t\t/* 78 */\t\t\t\"************************\"\t\t\t\t/* Response */\n\t\t\t\t\t\t};\n\t\t\t\t\tBYTE eapChallenge[ 64 ];\n\t\t\t\t\tint eapChallengeLength;\n\n\t\t\t\t\tfetchStringLen = sizeof( ttlsAVP ) - 1;\n\t\t\t\t\tmemcpy( fetchString, ttlsAVP, fetchStringLen );\n\n\t\t\t\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SSL_EAPCHALLENGE, \n\t\t\t\t\t\t\t\t\t\t\t\t\t  eapChallenge, &eapChallengeLength );\n\t\t\t\t\tmemcpy( fetchString + 24, eapChallenge, 16 );\t\t/* MS-CHAP challenge */\n\t\t\t\t\tfetchString[ 52 ] = eapChallenge[ 16 ];\t\t\t\t/* MS-CHAP ident */\n\t\t\t\t\tmemcpy( fetchString + 54, eapChallenge + 16, 16 );\t/* MS-CHAP peer challenge */\n\t\t\t\t\tstatus = createMSCHAPv2Response( eapChallenge,\n\t\t\t\t\t\t\t\teapChallenge + 16,\n\t\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].userName,\n\t\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].userName ),\n\t\t\t\t\t\t\t\tsslInfo[ EAP_SERVER_NO ].password,\n\t\t\t\t\t\t\t\tparamStrlen( sslInfo[ EAP_SERVER_NO ].password ),\n\t\t\t\t\t\t\t\tfetchString + 78 );\n#endif\n#endif\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tsprintf( fetchString, \"GET %s HTTP/1.0\\r\\n\\r\\n\",\n\t\t\t\t\t\t\t sslInfo[ SSL_SERVER_NO ].path );\n\t\t\t\t\tfetchStringLen = strlen( fetchString );\n\t\t\t\t\t}\n\t\t\t\t}\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToAscii( fetchString, fetchString );\n#endif /* EBCDIC systems */\n\t\t\tstatus = cryptPushData( cryptSession, fetchString,\n\t\t\t\t\t\t\t\t\tfetchStringLen, &bytesCopied );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\tif( cryptStatusError( status ) || bytesCopied != fetchStringLen )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession, \"Attempt to send data to \"\n\t\t\t\t\t\t\t   \"server\", status, __LINE__ );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Print the text of the reply from the server */\n\t\t\tstatus = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,\n\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintExtError( cryptSession, \"Attempt to read data from \"\n\t\t\t\t\t\t\t   \"server\", status, __LINE__ );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\tif( isErrorTest )\n\t\t\t\t\t{\n\t\t\t\t\t/* These tests are supposed to fail, so if this happens \n\t\t\t\t\t   then the overall test has succeeded */\n\t\t\t\t\tfputs( \"  (This test checks error handling, so the \"\n\t\t\t\t\t\t   \"failure response is correct).\\n\\n\", outputStream );\n\t\t\t\t\treturn( TRUE );\n\t\t\t\t\t}\n\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* The error tests should cause protocol failures, so getting to \n\t\t\t   this point is an error */\n\t\t\tif( isErrorTest )\n\t\t\t\t{\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\tfputs( \"  (This test should have led to a protocol failure \"\n\t\t\t\t\t   \"but didn't, test has\\n   failed).\\n\", outputStream );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\tif( bytesCopied == 0 && testType != SSL_TEST_STARTTLS )\n\t\t\t\t{\n\t\t\t\t/* We've set a 5s timeout, we should get at least some \n\t\t\t\t   data, however we allow this for the STARTTLS tests since \n\t\t\t\t   the servers can exhibit all sorts of odd behaviour that \n\t\t\t\t   we can't do much about with the partial client that we \n\t\t\t\t   have here */\n\t\t\t\tfputs( \"Server returned no data in response to our request.\", \n\t\t\t\t\t   outputStream );\n\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbuffer[ min( bytesCopied, 4096 ) ] = '\\0';\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\tif( testType != SSL_TEST_MULTITHREAD )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"---- Server sent %d bytes ----\\n\", \n\t\t\t\t\t\t bytesCopied );\n\t\t\t\tfputs( buffer, outputStream );\n\t\t\t\tif( bytesCopied > 4096 )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"  (Further %d bytes data \"\n\t\t\t\t\t\t\t \"omitted)\\n\", bytesCopied - 4096 );\n\t\t\t\t\t}\n\t\t\t\tfputs( \"---- End of output ----\", outputStream );\n\t\t\t\t}\n\n\t\t\t/* If it's the EAP test, we need to acknowledge the server's \n\t\t\t   response */\n\t\t\tif( testType == SSL_TEST_EAPTTLS )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_AUTHRESPONSE, \n\t\t\t\t\t\t\t\t\t\t\tTRUE );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintExtError( cryptSession, \"Attempt to acknowledge \"\n\t\t\t\t\t\t\t\t   \"EAP auth\", status, __LINE__ );\n\t\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\n#ifdef IS_HIGHVOLUME_SERVER\n\t\t\t/* If we're reading a lot of data, more may have arrived in the \n\t\t\t   meantime */\n\t\t\tstatus = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,\n\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tif( status == CRYPT_ERROR_READ )\n\t\t\t\t\t{\n\t\t\t\t\t/* Since this is HTTP, the other side can close the \n\t\t\t\t\t   connection with no further warning, even though SSL \n\t\t\t\t\t   says you shouldn't really do this */\n\t\t\t\t\tfputs( \"Remote system closed connection.\", \n\t\t\t\t\t\t   outputStream );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tprintExtError( cryptSession, \"Attempt to read data from \"\n\t\t\t\t\t\t\t\t   \"server\", status, __LINE__ );\n\t\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tbuffer[ bytesCopied ] = '\\0';\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\t\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\t\tif( testType != SSL_TEST_MULTITHREAD )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"---- Server sent further %d \"\n\t\t\t\t\t\t\t \"bytes ----\\n\", bytesCopied );\n\t\t\t\t\tfputs( buffer, outputStream );\n\t\t\t\t\tfputs( \"---- End of output ----\", outputStream );\n\t\t\t\t\t}\n\t\t\t\t}\n#endif /* IS_HIGHVOLUME_SERVER */\n\n\t\t\t/* If it's a chatty protocol, exchange some more pleasantries */\n\t\t\tif( testType == SSL_TEST_STARTTLS )\n\t\t\t\t{\n\t\t\t\tswitch( protocol )\n\t\t\t\t\t{\n\t\t\t\t\tcase PROTOCOL_SMTP:\n\t\t\t\t\t\tstrcpy( fetchString, \"QUIT\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PROTOCOL_POP:\n\t\t\t\t\t\tstrcpy( fetchString, \"USER test\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PROTOCOL_IMAP:\n\t\t\t\t\t\tstrcpy( fetchString, \"a004 LOGIN test\\r\\n\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tstrcpy( fetchString, \"QUIT\\r\\n\" );\n\t\t\t\t\t}\n\t\t\t\tfetchStringLen = strlen( fetchString );\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\t\tbufferToAscii( fetchString, fetchString );\n#endif /* EBCDIC systems */\n\t\t\t\tstatus = cryptPushData( cryptSession, fetchString,\n\t\t\t\t\t\t\t\t\t\tfetchStringLen, &bytesCopied );\n\t\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t\tstatus = cryptFlushData( cryptSession );\n\t\t\t\tif( cryptStatusError( status ) || bytesCopied != fetchStringLen )\n\t\t\t\t\t{\n\t\t\t\t\tprintExtError( cryptSession, \"Attempt to send data to \"\n\t\t\t\t\t\t\t\t   \"server\", status, __LINE__ );\n\t\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tstatus = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintExtError( cryptSession, \"Attempt to read data from \"\n\t\t\t\t\t\t\t\t   \"server\", status, __LINE__ );\n\t\t\t\t\tcryptDestroySession( cryptSession );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbuffer[ bytesCopied ] = '\\0';\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n\t\t\t\tbufferToEbcdic( buffer, buffer );\n#endif /* EBCDIC systems */\n\t\t\t\tif( testType != SSL_TEST_MULTITHREAD )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"---- Server sent %d bytes ----\\n\", \n\t\t\t\t\t\t\t bytesCopied );\n\t\t\t\t\tfputs( buffer, outputStream );\n\t\t\t\t\tfputs( \"---- End of output ----\", outputStream );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptDestroySession() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n#ifdef USE_LOCAL_SOCKETS\n\tif( testType == SSL_TEST_STARTTLS || \\\n\t\t( isServer && testType == SSL_TEST_LOCALSERVER ) )\n\t\t{\n\t\tendSockets( netSocket );\n\t\t}\n#endif /* USE_LOCAL_SOCKETS */\n\n\tif( sessionID != CRYPT_UNUSED )\n\t\tfprintf( outputStream, \"%02d: \", sessionID );\n\tfprintf( outputStream, \"%s%s session succeeded.\\n\", \n\t\t\t isServer ? \"SVR: \" : \"\", versionStr[ version ] );\n\tif( testType != SSL_TEST_MULTITHREAD )\n\t\tfputc( '\\n', outputStream );\n\treturn( TRUE );\n\t}\n\nint testSessionSSL( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_NORMAL, 0, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionSSLLocalSocket( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_STARTTLS, 0, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionSSLClientCert( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_CLIENTCERT, 0, CRYPT_UNUSED, FALSE ) );\n\t}\n\nint testSessionSSLServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 0, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionSSLServerCached( void )\n\t{\n\tint status;\n\n\t/* Run the server twice to check session cacheing.  Testing this \n\t   requires manual reconnection with a browser to localhost, since it's \n\t   too complex to handle easily via a loopback test.  Note that with \n\t   MSIE this will require three lots of connects rather than two, \n\t   because it handles an unknown certificate by doing a resume, which \n\t   consumes two lots of sessions, and then the third one is the actual \n\t   session resume */\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 0, CRYPT_UNUSED, FALSE );\n\tif( status > 0 )\n\t\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 0, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionSSLServerClientCert( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_CLIENTCERT, 0, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\nint testSessionTLS( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_NORMAL, 1, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLSLocalSocket( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_STARTTLS, 1, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLSSharedKey( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_PSK, 1, CRYPT_UNUSED, FALSE ) );\n\t}\n\nint testSessionTLSServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 1, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionTLSServerSharedKey( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_PSK, 1, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\nint testSessionTLS11( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_NORMAL, 2, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLS11Server( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 2, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\nint testSessionTLS12( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_NORMAL, 3, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLS12ClientCert( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_CLIENTCERT, 3, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLS12Server( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_NORMAL, 3, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionTLS12ServerClientCertManual( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_CLIENTCERT_MANUAL, 3, CRYPT_UNUSED, TRUE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\nint testSessionTLS12WebSockets( void )\n\t{\n\treturn( connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_WEBSOCKETS, 3, CRYPT_UNUSED, FALSE ) );\n\t}\nint testSessionTLS12WebSocketsServer( void )\n\t{\n\tint status;\n\n\tcreateMutex();\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_WEBSOCKETS, 3, CRYPT_UNUSED, FALSE );\n\tdestroyMutex();\n\n\treturn( status );\n\t}\n\nint testSessionTLSBadSSL( void )\n\t{\n\tFILE *origOutputStream = outputStream;\n\tint i;\n\n\tfputs( \"Running BadSSL tests...\\n\", outputStream );\n\toutputStream = fopen( DEVNULL, \"w\" );\n\tassert( outputStream != NULL );\n\n\tfor( i = 0; badSslInfo[ i ].testType != 0; i++ )\n\t\t{\n\t\tint status;\n\n\t\tfprintf( origOutputStream, \"Testing %s.\\n\", badSslInfo[ i ].path );\n\n\t\t/* With a debug build of cryptlib, SSL_TEST_BADSSL_DHSMALLSUBGROUP \n\t\t   will raise an assertion, so we only run it on non-debug builds */\n#ifndef NDEBUG\n\t\tif( badSslInfo[ i ].testType == SSL_TEST_BADSSL_DHSMALLSUBGROUP )\n\t\t\t{\n\t\t\tfputs( \"Skipping SSL_TEST_BADSSL_DHSMALLSUBGROUP in debug \"\n\t\t\t\t   \"build.\", outputStream );\n\t\t\tcontinue;\n\t\t\t}\n#endif /* NDEBUG */\n\t\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, badSslInfo[ i ].testType, \n\t\t\t\t\t\t\t\t3, CRYPT_UNUSED, FALSE );\n\t\tif( status != badSslInfo[ i ].result )\n\t\t\t{\n\t\t\t/* If ECDH/ECDSA aren't enabled then the ECC P256 test will fail */\n\t\t\tif( cryptStatusError( cryptQueryCapability( CRYPT_ALGO_ECDSA, NULL ) ) || \\\n\t\t\t\tcryptStatusError( cryptQueryCapability( CRYPT_ALGO_ECDH, NULL ) ) )\n\t\t\t\t{\n\t\t\t\tif( badSslInfo[ i ].testType == SSL_TEST_BADSSL_ECC256 )\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#ifndef USE_GCM\n\t\t\t/* This site seems to have a bug in the \n\t\t\t   TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 suite, producing a Bad\n\t\t\t   record MAC alert when a CBC suite (rather than GCM) is used, \n\t\t\t   so we ignore errors when GCM isn't enabled */\n\t\t\tif( badSslInfo[ i ].testType == SSL_TEST_BADSSL_RSA2048 || \\\n\t\t\t\tbadSslInfo[ i ].testType == SSL_TEST_BADSSL_NOCN || \\\n\t\t\t\tbadSslInfo[ i ].testType == SSL_TEST_BADSSL_NOSUBJECT || \\\n\t\t\t\tbadSslInfo[ i ].testType == SSL_TEST_BADSSL_LONGNAME1 || \\\n\t\t\t\tbadSslInfo[ i ].testType == SSL_TEST_BADSSL_LONGNAME2 )\n\t\t\t\tcontinue;\n#endif /* USE_GCM */\n\n\t\t\toutputStream = origOutputStream;\n\t\t\tfprintf( outputStream, \"BadSSL test '%s' failed,\\ngot result \"\n\t\t\t\t\t \"%d, should have been %d.\\n\", badSslInfo[ i ].path,\n\t\t\t\t\t status, badSslInfo[ i ].result );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\toutputStream = origOutputStream;\n\n\tfprintf( outputStream, \"BadSSL tests succeeded.\\n\\n\" );\n\treturn( TRUE );\n\t}\n\n/* Perform a client/server loopback test */\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall sslServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, argValue, 0, CRYPT_UNUSED, \n\t\t\t\t   TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nstatic int sslClientServer( const SSL_TEST_TYPE testType )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = testType, status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, sslServerThread, &arg, 0, \n\t\t\t\t\t\t\t\t\t\t &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, testType, 0, CRYPT_UNUSED, \n\t\t\t\t\t\t\tTRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\nint testSessionSSLClientServer( void )\n\t{\n\treturn( sslClientServer( SSL_TEST_NORMAL ) );\n\t}\nint testSessionSSLClientCertClientServer( void )\n\t{\n\treturn( sslClientServer( SSL_TEST_CLIENTCERT ) );\n\t}\n\nunsigned __stdcall tlsServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, argValue, 1, CRYPT_UNUSED, \n\t\t\t\t   TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nstatic int tlsClientServer( const SSL_TEST_TYPE testType )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = testType, status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tlsServerThread, &arg, 0, \n\t\t\t\t\t\t\t\t\t\t &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, testType, 1, CRYPT_UNUSED, \n\t\t\t\t\t\t\tTRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\nint testSessionTLSClientServer( void )\n\t{\n\treturn( tlsClientServer( SSL_TEST_NORMAL ) );\n\t}\nint testSessionTLSSharedKeyClientServer( void )\n\t{\n\treturn( tlsClientServer( SSL_TEST_PSK ) );\n\t}\nint testSessionTLSNoSharedKeyClientServer( void )\n\t{\n\tif( !tlsClientServer( SSL_TEST_PSK_CLIONLY ) )\n\t\treturn( FALSE );\n\treturn( tlsClientServer( SSL_TEST_PSK_SVRONLY ) );\n\t}\nint testSessionTLSBulkTransferClientServer( void )\n\t{\n\treturn( tlsClientServer( SSL_TEST_BULKTRANSER ) );\n\t}\nint testSessionTLSLocalServerSocketClientServer( void )\n\t{\n\treturn( tlsClientServer( SSL_TEST_LOCALSERVER ) );\n\t}\n\nunsigned __stdcall tls11ServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, argValue, 2, CRYPT_UNUSED, \n\t\t\t\t   TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nstatic int tls11ClientServer( const SSL_TEST_TYPE testType )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = testType, status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tls11ServerThread, &arg, 0, \n\t\t\t\t\t\t\t\t\t\t &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, testType, 2, CRYPT_UNUSED, \n\t\t\t\t\t\t\tTRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\nint testSessionTLS11ClientServer( void )\n\t{\n\treturn( tls11ClientServer( SSL_TEST_NORMAL ) );\n\t}\nint testSessionTLS11ClientCertClientServer( void )\n\t{\n\treturn( tls11ClientServer( SSL_TEST_CLIENTCERT ) );\n\t}\nint testSessionTLS11ResumeClientServer( void )\n\t{\n\t/* Note that this function has to be called after one of the standard \n\t   TLS-connect functions has been called, since it checks for the \n\t   ability to resume a previously-cached session */\n\treturn( tls11ClientServer( SSL_TEST_RESUME ) );\n\t}\n\nunsigned __stdcall tls12ServerThread( void *arg )\n\t{\n\tconst int argValue = *( ( int * ) arg );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, argValue, 3, CRYPT_UNUSED, \n\t\t\t\t   TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nstatic int tls12ClientServer( const SSL_TEST_TYPE testType )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint arg = testType, status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tls12ServerThread, &arg, 0, \n\t\t\t\t\t\t\t\t\t\t &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, testType, 3, CRYPT_UNUSED, \n\t\t\t\t\t\t\tTRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\nint testSessionTLS12ClientServer( void )\n\t{\n\treturn( tls12ClientServer( SSL_TEST_NORMAL ) );\n\t}\nint testSessionTLS12ClientServerEccKey( void )\n\t{\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, \\\n\t\t\t\t\t\t\t  NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"ECC is disabled in this build of cryptlib, skipping TLS ECC \"\n\t\t\t   \"test.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\treturn( tls12ClientServer( SSL_TEST_ECC ) );\n\t}\nint testSessionTLS12ClientServerEcc384Key( void )\n\t{\n\tif( cryptQueryCapability( CRYPT_ALGO_ECDSA, \\\n\t\t\t\t\t\t\t  NULL ) == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tfputs( \"ECC is disabled in this build of cryptlib, skipping TLS ECC \"\n\t\t\t   \"test.\\n\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\treturn( tls12ClientServer( SSL_TEST_ECC_P384 ) );\n\t}\nint testSessionTLS12ClientCertClientServer( void )\n\t{\n\treturn( tls12ClientServer( SSL_TEST_CLIENTCERT ) );\n\t}\nint testSessionTLS12ClientCertManualClientServer( void )\n\t{\n\treturn( tls12ClientServer( SSL_TEST_CLIENTCERT_MANUAL ) );\n\t}\nint testSessionTLS12WebSocketsClientServer( void )\n\t{\n\treturn( tls12ClientServer( SSL_TEST_WEBSOCKETS ) );\n\t}\n\nunsigned __stdcall tlsServerDualThread2( void *dummy )\n\t{\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_DUALTHREAD, 1, 0, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nunsigned __stdcall tlsServerDualThread1( void *dummy )\n\t{\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_DUALTHREAD, 1, CRYPT_UNUSED, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nint testSessionTLSClientServerDualThread( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tint status;\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, tlsServerDualThread1,\n\t\t\t\t\t\t\t\t\t\t NULL, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tstatus = connectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_PSK, 1, CRYPT_UNUSED, TRUE );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\nunsigned __stdcall tlsServerMultiThread( void *threadIdPtr )\n\t{\n\tint threadID = *( ( int * ) threadIdPtr );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL_SERVER, SSL_TEST_MULTITHREAD, 1, threadID, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nunsigned __stdcall tlsClientMultiThread( void *threadIdPtr )\n\t{\n\tint threadID = *( ( int * ) threadIdPtr );\n\n\tconnectSSLTLS( CRYPT_SESSION_SSL, SSL_TEST_MULTITHREAD, 1, threadID, TRUE );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\nint testSessionTLSClientServerMultiThread( void )\n\t{\n\treturn( multiThreadDispatch( tlsClientMultiThread, \n\t\t\t\t\t\t\t\t tlsServerMultiThread, MAX_NO_THREADS ) );\n\t}\n\nint testSessionSSLClientServerDebugCheck( void )\n\t{\n#if defined( CONFIG_FAULTS ) && !defined( NDEBUG )\n\tcryptSetFaultType( FAULT_NONE );\n\n\t/* SSL tests */\n\tif( !sslClientServer( SSL_TEST_CORRUPT_HANDSHAKE ) )\n\t\treturn( FALSE );\t/* Detect corruption of handshake data */\n\tif( !sslClientServer( SSL_TEST_CORRUPT_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !sslClientServer( SSL_TEST_CORRUPT_MAC ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !sslClientServer( SSL_TEST_CORRUPT_FINISHED ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !sslClientServer( SSL_TEST_WRONGCERT ) )\n\t\treturn( FALSE );\t/* Detect wrong key for server */\n\tif( !sslClientServer( SSL_TEST_BADSIG_HASH ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\tif( !sslClientServer( SSL_TEST_BADSIG_SIG ) )\n\t\treturn( FALSE );\t/* Detect corruption of DH signature */\n\tif( !sslClientServer( SSL_TEST_BADSIG_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\n\t/* TLS 1.0 tests */\n\tif( !tlsClientServer( SSL_TEST_CORRUPT_HANDSHAKE ) )\n\t\treturn( FALSE );\t/* Detect corruption of handshake data */\n\tif( !tlsClientServer( SSL_TEST_CORRUPT_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !tlsClientServer( SSL_TEST_CORRUPT_MAC ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !tlsClientServer( SSL_TEST_CORRUPT_FINISHED ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !tlsClientServer( SSL_TEST_WRONGCERT ) )\n\t\treturn( FALSE );\t/* Detect wrong key for server */\n\tif( !tlsClientServer( SSL_TEST_BADSIG_HASH ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\tif( !tlsClientServer( SSL_TEST_BADSIG_SIG ) )\n\t\treturn( FALSE );\t/* Detect corruption of DH signature */\n\tif( !tlsClientServer( SSL_TEST_BADSIG_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\n\t/* TLS 1.2 tests */\n\tif( !tls12ClientServer( SSL_TEST_CORRUPT_HANDSHAKE ) )\n\t\treturn( FALSE );\t/* Detect corruption of handshake data */\n\tif( !tls12ClientServer( SSL_TEST_CORRUPT_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of payload data */\n\tif( !tls12ClientServer( SSL_TEST_CORRUPT_MAC ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !tls12ClientServer( SSL_TEST_CORRUPT_FINISHED ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !tls12ClientServer( SSL_TEST_CORRUPT_IV ) )\n\t\treturn( FALSE );\t/* Detect corruption of IV */\n\tif( !tls12ClientServer( SSL_TEST_WRONGCERT ) )\n\t\treturn( FALSE );\t/* Detect wrong key for server */\n\tif( !tls12ClientServer( SSL_TEST_BADSIG_HASH ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\tif( !tls12ClientServer( SSL_TEST_BADSIG_SIG ) )\n\t\treturn( FALSE );\t/* Detect corruption of DH signature */\n\tif( !tls12ClientServer( SSL_TEST_BADSIG_DATA ) )\n\t\treturn( FALSE );\t/* Detect corruption of signed DH params */\n\tcryptSetFaultType( FAULT_NONE );\n#endif /* CONFIG_FAULTS && Debug */\n\treturn( TRUE );\n\t}\n#endif /* WINDOWS_THREADS */\n\n#endif /* TEST_SESSION || TEST_SESSION_LOOPBACK */\n"
  },
  {
    "path": "deps/cl345/test/stress.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tcryptlib Test Code\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2004\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\t/* For algorithm usage */\n#include \"misc/consts.h\"\t/* For DEFAULT_CRYPT_ALGO */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* EBCDIC systems */\n\n/* Define the following to perform a smoke test on the cryptlib kernel.\n   This includes:\n\n\tStress test 1: Create 12K objects and read/write some attributes\n\tStress test 2: Create and destroy 20K objects in alternating pairs.\n\tData processing test: Encrypt/hash/MAC a buffer in a variable number\n\t\tof variable-size blocks, then decrypt/hash/MAC with different\n\t\tblocks and make sure the results match.\n\tKernel check test: Run through every possible object type and attribute\n\t\tmaking sure we don't trigger any assertions.\n\tSimple threading stress test: DES-encrypt 100 data blocks in threads.\n\tComplex threading stress test: Encrypted and signed enveloping.\n\tThreading continuous test: Envelope data in threads until interrupted.\n\n   Note that these are exhaustive tests that check large numbers of objects\n   or parameter types and combinations so they can take some time to run to\n   completion */\n\n/* #define SMOKE_TEST /**/\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tStress Test\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef SMOKE_TEST\n\n#define NO_OBJECTS\t14000\t\t/* Can't exceed MAX_OBJECTS in cryptkrn.h */\n\nstatic void testStressObjects1( void )\n\t{\n\tCRYPT_HANDLE *handleArray = malloc( NO_OBJECTS * sizeof( CRYPT_HANDLE ) );\n\tBYTE hash[ CRYPT_MAX_HASHSIZE ];\n\tint i, length, status;\n\n\tprintf( \"Running object stress test 1.\" );\n\tassert( handleArray  != NULL );\n\tfor( i = 0; i < NO_OBJECTS; i++ )\n\t\t{\n\t\tstatus = cryptCreateContext( &handleArray[ i ], CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptCreateContext() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\n\t\t/* Destroy an earlier object to make sure that there are gaps in the\n\t\t   LFSR coverage */\n\t\tif( i > 1000 && ( i % 500 ) == 0 )\n\t\t\t{\n\t\t\tstatus = cryptDestroyContext( handleArray[ i - 600 ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tprintf( \"cryptDestroyContext() #%d failed with status %d.\\n\", \n\t\t\t\t\t\ti, status );\n\t\t\thandleArray[ i - 600 ] = -1;\n\t\t\t}\n\t\t}\n\tprintf( \".\" );\n\tfor( i = 0; i < NO_OBJECTS; i++ )\n\t\t{\n\t\tif( handleArray[ i ] == -1 )\n\t\t\tcontinue;\n\t\tstatus = cryptEncrypt( handleArray[ i ], \"12345678\", 8 );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptEncrypt() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\t}\n\tprintf( \".\" );\n\tfor( i = 0; i < NO_OBJECTS; i++ )\n\t\t{\n\t\tif( handleArray[ i ] == -1 )\n\t\t\tcontinue;\n\t\tstatus = cryptEncrypt( handleArray[ i ], \"\", 0 );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptEncrypt() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\t}\n\tprintf( \".\" );\n\tfor( i = 0; i < NO_OBJECTS; i++ )\n\t\t{\n\t\tif( handleArray[ i ] == -1 )\n\t\t\tcontinue;\n\t\tstatus = cryptGetAttributeString( handleArray[ i ],\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_HASHVALUE, hash, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptEncrypt() (len.0) #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\t}\n\tprintf( \".\" );\n\tfor( i = 0; i < NO_OBJECTS; i++ )\n\t\t{\n\t\tif( handleArray[ i ] == -1 )\n\t\t\tcontinue;\n\t\tstatus = cryptDestroyContext( handleArray[ i ] );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptDestroyContext() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\t}\n\tfree( handleArray );\n\tputs( \".\" );\n\t}\n\nstatic void testStressObjects2( void )\n\t{\n\tCRYPT_HANDLE handleArray[ 2 ];\n\tBYTE hash[ CRYPT_MAX_HASHSIZE ];\n\tint handleIndex = 0;\n\tint i, length, status;\n\n\tprintf( \"Running object stress test 2.\" );\n\thandleArray[ 0 ] = handleArray[ 1 ] = -1;\n\tfor( i = 0; i < 20000; i++ )\n\t\t{\n\t\tCRYPT_CONTEXT cryptContext;\n\n\t\tif( handleArray[ handleIndex ] != -1 )\n\t\t\t{\n\t\t\tstatus = cryptDestroyContext( handleArray[ handleIndex ] );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tprintf( \"cryptDestroyContext() #%d failed with status %d.\\n\", \n\t\t\t\t\t\ti, status );\n\t\t\t}\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA1 );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptCreateContext() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\thandleArray[ handleIndex ] = cryptContext;\n\n\t\thandleIndex = ( handleIndex + 1 ) & 1;\n\n\t\tif( handleArray[ handleIndex ] != -1 )\n\t\t\t{\n\t\t\tstatus = cryptEncrypt( handleArray[ handleIndex ], \"12345678\", 8 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tprintf( \"cryptEncrypt() #%d failed with status %d.\\n\", \n\t\t\t\t\t\ti, status );\n\t\t\tstatus = cryptEncrypt( handleArray[ handleIndex ], \"\", 0 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tprintf( \"cryptEncrypt() #%d failed with status %d.\\n\", \n\t\t\t\t\t\ti, status );\n\t\t\tstatus = cryptGetAttributeString( handleArray[ handleIndex ],\n\t\t\t\t\t\t\t\t\tCRYPT_CTXINFO_HASHVALUE, hash, &length );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\tprintf( \"cryptEncrypt() (len.0) #%d failed with status %d.\\n\", \n\t\t\t\t\t\ti, status );\n\t\t\t}\n\t\t}\n\tfor( i = 0; i < 2; i++ )\n\t\t{\n\t\tstatus = cryptDestroyContext( handleArray[ i ] );\n\t\tif( cryptStatusError( status ) )\n\t\t\tprintf( \"cryptDestroyContext() #%d failed with status %d.\\n\", \n\t\t\t\t\ti, status );\n\t\t}\n\tputs( \".\" );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tData Processing Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Data processing test */\n\n#define DATABUFFER_SIZE\t\t2048\n#define MAX_BLOCKS\t\t\t16\n\n#define roundUp( size, roundSize ) \\\n\t( ( ( size ) + ( ( roundSize ) - 1 ) ) & ~( ( roundSize ) - 1 ) )\n\n#ifdef __WINDOWS__\n  typedef int ( __stdcall *CRYPT_FUNCTION )( const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t\t\t\t\t void *data, const int length );\n#else\n  typedef int ( *CRYPT_FUNCTION )( const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t\t   void *data, const int length );\n#endif /* __WINDOWS__ */\n\nstatic int processData( const CRYPT_CONTEXT cryptContext, BYTE *buffer,\n\t\t\t\t\t\tconst int noBlocks, const int blockSize,\n\t\t\t\t\t\tCRYPT_FUNCTION cryptFunction, const BOOLEAN isHash )\n\t{\n\tint offset = 0, i, status;\n\n\t/* Encrypt the data in variable-length blocks.  The technique for\n\t   selecting lengths isn't perfect since it tends to put large blocks\n\t   at the start and small ones at the end, but it's good enough for\n\t   general testing */\n\tfor( i = 0; i < noBlocks - 1; i++ )\n\t\t{\n\t\tint noBytes = rand() % ( DATABUFFER_SIZE - offset - \\\n\t\t\t\t\t\t\t\t ( blockSize * ( noBlocks - i  ) ) );\n\t\tif( !noBytes )\n\t\t\tnoBytes = 1;\n\t\tif( blockSize > 1 )\n\t\t\tnoBytes = roundUp( noBytes, blockSize );\n\t\tstatus = cryptFunction( cryptContext, buffer + offset, noBytes );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\toffset += noBytes;\n\t\t}\n\tstatus = cryptFunction( cryptContext, buffer + offset,\n\t\t\t\t\t\t\tDATABUFFER_SIZE - offset );\n\tif( cryptStatusOK( status ) && isHash )\n\t\tstatus = cryptFunction( cryptContext, \"\", 0 );\n\treturn( status );\n\t}\n\nstatic int testProcessing( const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t\t\t   const CRYPT_MODE_TYPE cryptMode,\n\t\t\t\t\t\t   const CRYPT_QUERY_INFO cryptQueryInfo )\n\t{\n\tBYTE buffer1[ DATABUFFER_SIZE ], buffer2[ DATABUFFER_SIZE ];\n\tBYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];\n\tconst int blockSize = ( cryptMode == CRYPT_MODE_ECB || \\\n\t\t\t\t\t\t\tcryptMode == CRYPT_MODE_CBC ) ? \\\n\t\t\t\t\t\t  cryptQueryInfo.blockSize : 1;\n\tconst BOOLEAN isHash = ( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \\\n\t\t\t\t\t\t\t cryptAlgo <= CRYPT_ALGO_LAST_HASH ) || \\\n\t\t\t\t\t\t   ( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \\\n\t\t\t\t\t\t\t cryptAlgo <= CRYPT_ALGO_LAST_MAC );\n\tint length1, length2, i;\n\n\t/* Initialise the buffers with a known data pattern */\n\tmemset( buffer1, '*', DATABUFFER_SIZE );\n\tmemcpy( buffer1, \"12345678\", 8 );\n\tmemcpy( buffer2, buffer1, DATABUFFER_SIZE );\n\n\t/* Process the data using various block sizes */\n\tprintf( \"Testing algorithm %d, mode %d, for %d-byte buffer with\\n  block \"\n\t\t\t\"count \", cryptAlgo, ( cryptMode == CRYPT_UNUSED ) ? 0 : cryptMode,\n\t\t\tDATABUFFER_SIZE );\n\tfor( i = 1; i <= MAX_BLOCKS; i++ )\n\t\t{\n\t\tCRYPT_CONTEXT cryptContext;\n\t\tint status;\n\n\t\tmemcpy( buffer1, buffer2, DATABUFFER_SIZE );\n\t\tprintf( \"%d%s \", i, ( i == MAX_BLOCKS ) ? \".\" : \",\" );\n\n\t\t/* Encrypt the data with random block sizes */\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( cryptMode != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t\t\t\t\t\tcryptMode );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( cryptMode != CRYPT_MODE_ECB && cryptAlgo != CRYPT_ALGO_RC4 )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\"1234567887654321\", cryptQueryInfo.blockSize );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptQueryInfo.keySize )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\"12345678876543211234567887654321\",\n\t\t\t\t\t\t\t\tcryptQueryInfo.keySize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = processData( cryptContext, buffer1, i, blockSize,\n\t\t\t\t\t\t\t  cryptEncrypt, isHash );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_HASHVALUE, hash1, &length1 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = cryptDestroyContext( cryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Decrypt the data again with random block sizes */\n\t\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED, cryptAlgo );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( cryptMode != CRYPT_UNUSED )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptContext, CRYPT_CTXINFO_MODE,\n\t\t\t\t\t\t\t\t\t\tcryptMode );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\tif( cryptMode != CRYPT_MODE_ECB && cryptAlgo != CRYPT_ALGO_RC4 )\n\t\t\t\t{\n\t\t\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_IV,\n\t\t\t\t\t\t\t\t\"1234567887654321\", cryptQueryInfo.blockSize );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\treturn( status );\n\t\t\t\t}\n\t\t\t}\n\t\tif( cryptQueryInfo.keySize )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\"12345678876543211234567887654321\",\n\t\t\t\t\t\t\t\tcryptQueryInfo.keySize );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = processData( cryptContext, buffer1, i, blockSize,\n\t\t\t\t\t\t\t  isHash ? cryptEncrypt : cryptDecrypt, isHash );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )\n\t\t\t{\n\t\t\tstatus = cryptGetAttributeString( cryptContext,\n\t\t\t\t\t\t\t\tCRYPT_CTXINFO_HASHVALUE, hash2, &length2 );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\treturn( status );\n\t\t\t}\n\t\tstatus = cryptDestroyContext( cryptContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\n\t\t/* Make sure the values match */\n\t\tif( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )\n\t\t\t{\n\t\t\tif( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Hash value of identical buffers differs.\" );\n\t\t\t\treturn( -1234 );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tif( memcmp( buffer1, buffer2, DATABUFFER_SIZE ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"Decrypted data != encrypted data for algorithm %d.\\n\",\n\t\t\t\t\t\tcryptAlgo );\n\t\t\t\treturn( -1234 );\n\t\t\t\t}\n\t\t}\n\tprintf( \"\\n\" );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic void testDataProcessing( void )\n\t{\n\tCRYPT_QUERY_INFO cryptQueryInfo;\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tint errorCount = 0, status;\n\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_CONVENTIONAL;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo,\n\t\t\t\t\t\t\t\t\t\t\t\t &cryptQueryInfo ) ) )\n\t\t\t{\n\t\t\tif( cryptAlgo != CRYPT_ALGO_RC4 )\n\t\t\t\t{\n\t\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_MODE_ECB,\n\t\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"\\nAlgorithm %d ECB mode processing failed with \"\n\t\t\t\t\t\t\t\"status %d.\\n\", cryptAlgo, status );\n\t\t\t\t\terrorCount++;\n\t\t\t\t\t}\n\t\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_MODE_CBC,\n\t\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"\\nAlgorithm %d CBC mode processing failed with \"\n\t\t\t\t\t\t\t\"status %d.\\n\", cryptAlgo, status );\n\t\t\t\t\terrorCount++;\n\t\t\t\t\t}\n\t\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_MODE_GCM,\n\t\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"\\nAlgorithm %d GCM mode processing failed with \"\n\t\t\t\t\t\t\t\"status %d.\\n\", cryptAlgo, status );\n\t\t\t\t\terrorCount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_MODE_CFB,\n\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"\\nAlgorithm %d CFB mode processing failed with \"\n\t\t\t\t\t\t\"status %d.\\n\", cryptAlgo, status );\n\t\t\t\terrorCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_HASH;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_HASH; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, &cryptQueryInfo ) ) )\n\t\t\t{\n\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"\\nAlgorithm %d processing failed with status %d.\\n\",\n\t\t\t\t\t\tcryptAlgo, status );\n\t\t\t\terrorCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_MAC;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_MAC; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, &cryptQueryInfo ) ) )\n\t\t\t{\n\t\t\tstatus = testProcessing( cryptAlgo, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t cryptQueryInfo );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tprintf( \"\\nAlgorithm %d processing failed with status %d.\\n\",\n\t\t\t\t\t\tcryptAlgo, status );\n\t\t\t\terrorCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( errorCount )\n\t\tprintf( \"%d errors detected.\\n\", errorCount );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tKernel Check Test\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Kernel check test */\n\nstatic void smokeTestAttributes( const CRYPT_HANDLE cryptHandle )\n\t{\n\tint attribute;\n\n\tprintf( \".\" );\n\tfor( attribute = CRYPT_ATTRIBUTE_NONE; attribute < 8000; attribute++ )\n\t\t{\n\t\tchar buffer[ 1024 ];\n\t\tint value;\n\n\t\tcryptGetAttribute( cryptHandle, attribute, &value );\n\t\tcryptGetAttributeString( cryptHandle, attribute, buffer, &value );\n\t\t}\n\tcryptDestroyObject( cryptHandle );\n\t}\n\nstatic void testKernelChecks( void )\n\t{\n\tCRYPT_HANDLE cryptHandle;\n\tint subType;\n\n\tprintf( \"Running kernel smoke test:\\n  Contexts\" );\n\tfor( subType = 0; subType < 500; subType++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptCreateContext( &cryptHandle, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t\t   subType ) ) )\n\t\t\tsmokeTestAttributes( cryptHandle );\n\t\t}\n\tprintf( \"\\n  Certs\" );\n\tfor( subType = 0; subType < 500; subType++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptCreateCert( &cryptHandle, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t\tsubType ) ) )\n\t\t\tsmokeTestAttributes( cryptHandle );\n\t\t}\n\tprintf( \"\\n  Envelopes\" );\n\tfor( subType = 0; subType < 500; subType++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptCreateEnvelope( &cryptHandle, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t\t\tsubType ) ) )\n\t\t\tsmokeTestAttributes( cryptHandle );\n\t\t}\n\tprintf( \"\\n  Sessions\" );\n\tfor( subType = 0; subType < 500; subType++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptCreateSession( &cryptHandle, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t\t   subType ) ) )\n\t\t\tsmokeTestAttributes( cryptHandle );\n\t\t}\n\tprintf( \"\\n\" );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSimple Threading Stress Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Multi-threaded processing stress test.  In order to add a little\n   nondeterminism on single-threaded machines, we need to add some sleep()\n   calls between crypto operations.  Even this isn't perfect, there's no\n   real way to guarantee that they aren't simply executed in round-robin\n   fashion with only one thread in the kernel at a time without modifying\n   the kernel to provide diagnostic info */\n\n#ifdef WINDOWS_THREADS\n\n#define NO_SIMPLE_THREADS\t45\n\nstatic void randSleep( void )\n\t{\n\tSleep( ( rand() % 150 ) + 1 );\n\t}\n\nunsigned __stdcall processDataThread( void *arg )\n\t{\n\tCRYPT_CONTEXT cryptContext;\n\tBYTE buffer[ 1024 ];\n\tint threadNo = ( int ) arg;\n\tint status;\n\n\trandSleep();\n\tmemset( buffer, '*', 1024 );\n\tstatus = cryptCreateContext( &cryptContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\trandSleep();\n\t\tstatus = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_KEY,\n\t\t\t\t\t\t\t\t\t\t  \"123456781234567812345678\", 24 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\trandSleep();\n\t\tstatus = cryptEncrypt( cryptContext, buffer, 1024 );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\trandSleep();\n\t\tstatus = cryptDestroyContext( cryptContext );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\tprintf( \"\\nEncryption failed with status %d.\\n\", status );\n\telse\n\t\tprintf( \"%d \", threadNo );\n\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nstatic void testStressThreadsSimple( void )\n\t{\n\tHANDLE hThreadArray[ NO_SIMPLE_THREADS ];\n\tint i;\n\n\t/* Start the threads */\n\tfor( i = 0; i < NO_SIMPLE_THREADS; i++ )\n\t\t{\n\t\tunsigned threadID;\n\n\t\thThreadArray[ i ] = ( HANDLE ) \\\n\t\t\t_beginthreadex( NULL, 0, &processDataThread, ( void * ) i, 0,\n\t\t\t\t\t\t\t&threadID );\n\t\tif( hThreadArray[ i ] == 0 )\n\t\t\tprintf( \"Thread %d couldn't be created.\\n\", i );\n\t\t}\n\tprintf( \"Threads completed: \" );\n\n\t/* Wait for all the threads to complete */\n\tif( WaitForMultipleObjects( NO_SIMPLE_THREADS, hThreadArray, TRUE,\n\t\t\t\t\t\t\t\t15000 ) == WAIT_TIMEOUT )\n\t\tputs( \"\\nNot all threads completed in 15s.\" );\n\telse\n\t\tputs( \".\" );\n\tfor( i = 0; i < NO_SIMPLE_THREADS; i++ )\n\t\tCloseHandle( hThreadArray[ i ] );\n\t}\n#endif /* WINDOWS_THREADS */\n\n#if defined( UNIX_THREADS ) || defined( WINDOWS_THREADS )\n\n#ifdef UNIX_THREADS\n  void *envelopeDataThread( void *arg )\n#else\n  unsigned __stdcall envelopeDataThread( void *arg )\n#endif /* Different threading models */\n\t{\n\tstatic const char *envData = \"qwertyuiopasdfghjklzxcvbnm\";\n\tBYTE fileBuffer[ BUFFER_SIZE ];\n\tconst unsigned uThread = ( unsigned ) arg;\n\tconst time_t startTime = time( NULL );\n\tint count, status;\n\n\tprintf( \"Thread %ud started.\\n\", uThread );\n\tfflush( stdout );\n\n\tfilenameFromTemplate( fileBuffer, CERT_FILE_TEMPLATE, 13 );\n\n\tfor( count = 0; count < 150; count++ )\n\t\t{\n\t\tCRYPT_ENVELOPE cryptEnvelope;\n\t\tCRYPT_CERTIFICATE cryptCert;\n\t\tBYTE envBuffer[ BUFFER_SIZE ];\n\t\tint bytesCopied;\n\n\t\t/* Create the cert and envelope and add the cert to the envelope */\n\t\tstatus = importCertFile( &cryptCert, fileBuffer );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CRYPTLIB );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope,\n\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PUBLICKEY, cryptCert );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\n\t\t/* Envelope data and destroy the envelope */\n\t\tstatus = cryptPushData( cryptEnvelope, envData, strlen( envData ),\n\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPushData( cryptEnvelope, NULL, 0, NULL );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPopData( cryptEnvelope, envBuffer, BUFFER_SIZE,\n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptDestroyEnvelope( cryptEnvelope );\n\t\tif( cryptStatusError( status ) )\n\t\t\tbreak;\n\t\tprintf( \"%c\", uThread + '0' );\n\t\t}\n\n\tprintf( \"Thread %u exited after %d seconds.\\n\", uThread,\n\t\t\ttime( NULL ) - startTime );\n\tfflush( stdout );\n#ifdef UNIX_THREADS\n\tpthread_exit( NULL );\n#else\n\t_endthreadex( 0 );\n#endif /* Different threading models */\n\treturn( 0 );\n\t}\n\nstatic void testContinuousThreads( void )\n\t{\n\tunsigned threadID1, threadID2;\n#ifdef UNIX_THREADS\n\tpthread_t thread1, thread2;\n#else\n\tHANDLE hThread1, hThread2;\n#endif /* Different threading models */\n\n\tcryptAddRandom( \"xyzzy\", 5 );\n#ifdef UNIX_THREADS\n\tpthread_create( &thread1, NULL, envelopeDataThread, ( void * ) 1 );\n\tpthread_create( &thread2, NULL, envelopeDataThread, ( void * ) 2 );\n#else\n\thThread1 = ( HANDLE ) _beginthreadex( NULL, 0, envelopeDataThread,\n\t\t\t\t\t\t\t\t\t\t  ( void * ) 1, 0, &threadID1 );\n\thThread2 = ( HANDLE ) _beginthreadex( NULL, 0, envelopeDataThread,\n\t\t\t\t\t\t\t\t\t\t  ( void * ) 2, 0, &threadID2 );\n#endif /* Different threading models */\n\tdelayThread( 30 );\n\tprintf( \"Hit a key...\" );\n\tfflush( stdout );\n\tgetchar();\n\tcryptEnd();\n\texit( EXIT_SUCCESS );\n\t}\n#endif /* UNIX_THREADS || WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tComplex Threading Stress Test\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Unlike the previous test, there's enough nondeterminism added in this one\n   that things go out of sync all by themselves */\n\n#ifdef WINDOWS_THREADS\n\n#define NO_COMPLEX_THREADS\t4\n\nunsigned __stdcall signTest( void *arg ) \n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CONTEXT privateKeyContext;\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE buffer[ 1024 ];\n\tconst int count = *( ( int * ) arg );\n\tint bytesCopied, i, status;\n\n\tprintf( \"SignTest %d.\\n\", count );\n\n\tfor( i = 0; i < count; i++ ) \n\t\t{\n\t\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_KEYSET_FILE, TEST_PRIVKEY_FILE, \n\t\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY);\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptGetPrivateKey( cryptKeyset, &privateKeyContext, \n\t\t\t\t\t\t\t\t\t\t CRYPT_KEYID_NAME, RSA_PRIVKEY_LABEL, \n\t\t\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CMS );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_SIGNATURE, \n\t\t\t\t\t\t\t\t\t\tprivateKeyContext );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPushData( cryptEnvelope, \"message\", 7, \n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptEnvelope );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPopData( cryptEnvelope, buffer, 1024, \n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptDestroyContext( privateKeyContext );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptKeysetClose( cryptKeyset );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptDestroyEnvelope( cryptEnvelope );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t_endthreadex( status );\n\t\t\treturn( 0 );\n\t\t\t}\n\t\t}\n\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nunsigned __stdcall encTest( void *arg ) \n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tCRYPT_CERTIFICATE cryptCert;\n\tBYTE buffer[ 1024 ];\n\tconst int count = *( ( int * ) arg );\n\tint bytesCopied, i, status;\n\n\tprintf( \"EncTest %d.\\n\", count );\n\n\tfor( i = 0; i < count; i++ ) \n\t\t{\n\t\tFILE *filePtr;\n\t\tint certSize;\n\n\t\tif( ( filePtr = fopen( \"testdata/cert5.der\", \"rb\" ) ) != NULL ) \n\t\t\t{\n\t\t\tcertSize = fread( buffer, 1, 1024, filePtr );\n\t\t\tfclose( filePtr );\n\t\t\t}\n\n\t\tstatus = cryptImportCert( buffer, certSize, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  &cryptCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_FORMAT_CMS );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptSetAttribute( cryptEnvelope, \n\t\t\t\t\t\t\t\t\t\tCRYPT_ENVINFO_PUBLICKEY, cryptCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPushData( cryptEnvelope, buffer, 200, \n\t\t\t\t\t\t\t\t\t&bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptEnvelope );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptPopData( cryptEnvelope, buffer, 1024, \n\t\t\t\t\t\t\t\t   &bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptDestroyCert( cryptCert );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptDestroyEnvelope( cryptEnvelope );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\t_endthreadex( status );\n\t\t\treturn( 0 );\n\t\t\t}\n\t\t}\n\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testStressThreadsComplex( void ) \n\t{\n\tHANDLE hThreads[ NO_COMPLEX_THREADS ];\n\tint i;\n\n\tcryptAddRandom( NULL, CRYPT_RANDOM_SLOWPOLL );\n\n\tfor( i = 0; i < 1000; i++ )\n\t\t{\n\t\tunsigned dwThreadId;\n\t\tint j;\n\n\t\thThreads[ 0 ] = ( HANDLE ) \\\n\t\t\t_beginthreadex( NULL, 0, encTest, &i, 0, &dwThreadId );\n\t\thThreads[ 1 ] = ( HANDLE ) \\\n\t\t\t_beginthreadex( NULL, 0, signTest, &i, 0, &dwThreadId );\n\t\thThreads[ 2 ] = ( HANDLE ) \\\n\t\t\t_beginthreadex( NULL, 0, encTest, &i, 0, &dwThreadId );\n\t\thThreads[ 3 ] = ( HANDLE ) \\\n\t\t\t_beginthreadex( NULL, 0, signTest, &i, 0, &dwThreadId );\n\n\t\tWaitForMultipleObjects( NO_COMPLEX_THREADS, hThreads, TRUE, \n\t\t\t\t\t\t\t\tINFINITE );\n\t\n\t\tfor( j = 0; j < NO_COMPLEX_THREADS; j++ ) \n\t\t\tCloseHandle( hThreads[ j ] );\n\t\t}\n\n\treturn 0;\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tTest Interface\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\nvoid smokeTest( void )\n\t{\n\ttestDataProcessing();\n\ttestKernelChecks();\n\ttestStressObjects1();\n\ttestStressObjects2();\n#if defined( UNIX_THREADS ) || defined( WINDOWS_THREADS )\n\ttestStressThreadsSimple();\n\ttestStressThreadsComplex();\n#endif /* UNIX_THREADS || WINDOWS_THREADS */\n\t}\n#endif /* SMOKE_TEST */\n"
  },
  {
    "path": "deps/cl345/test/suiteb.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Suite B Test Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 2009-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\t\t/* For arg-parsing */\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n#ifdef CONFIG_SUITEB_TESTS\n\n/* Test-specific flags to control details of each test */\n\n#define TESTFLAG_SENDHTTPREQ\t\t0x01\t/* Send HTTP req.over TLS link */\n#define TESTFLAG_GENERIC\t\t\t0x02\t/* Don't print \"A.x.y.z\" for test */\n\n/* Special kludge function in cryptapi.c to enable nonstandard behaviour for\n   Suite B tests.  The definitions below are copined from session/ssl.h */\n\ntypedef enum {\n\tSUITEB_TEST_NONE,\t\t\t/* No special test behaviour */\n\tSUITEB_TEST_CLIINVALIDCURVE,/* Client sends non-Suite B curve */\n\tSUITEB_TEST_SVRINVALIDCURVE,/* Server sends non-Suite B curve */\n\tSUITEB_TEST_BOTHCURVES,\t\t/* Client must send P256 and P384 as supp.curves */\n\tSUITEB_TEST_BOTHSIGALGOS,\t/* Client must send SHA256 and SHA384 as sig.algos */\n\tSUITEB_TEST_LAST\n\t} SUITEB_TEST_VALUE;\n\nC_RET cryptSuiteBTestConfig( C_IN int magicValue );\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSuite B Test Definitions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Defines to make the table entries smaller and/or easier to understand */\n\n#define SECLVL_128\t\tCRYPT_SSLOPTION_SUITEB_128\n#define SECLVL_256\t\tCRYPT_SSLOPTION_SUITEB_256\n#define SECLVL_BOTH\t\tSECLVL_128\t/* For 5430bis, \"128\" now imples \"128+256\" */\n#define FORCE_TLS12\t\tCRYPT_SSLOPTION_MINVER_TLS12\n\n#define P521\t\t\t521\t\t/* For invalid-curve tests */\n#define P384\t\t\t384\n#define P256\t\t\t256\n\n/* Some entries are aliases for other entries, to make this easier to \n   specify we use the following define to fill in the unused fields */\n\n#define ALIAS\t\t\t0, 0, 0, 0, 0, 0\n#define ALIAS_SPECIAL\t0, 0, 0, 0, 0\n\n/* Special-case handling situations */\n\ntypedef enum { \n\tSPECIAL_NONE,\n\n\t/* Client tests */\n\t/* Client must reject invalid curve (in the form of server key) from server */\n\tSPECIAL_SVR_INVALIDCURVE,\n\t/* Client must send sig_algo extensions for both P256 and P384 curves */\n\tSPECIAL_BOTH_SIGALGO,\n\t/* Client must send supported_curves extension for both P256 and P384 \n\t   curves */\n\tSPECIAL_BOTH_SUPPCURVES,\n\t/* Client/server must send TLS alert due to protocol violation */\n\tSPECIAL_CLI_TLSALERT,\n\tSPECIAL_SVR_TLSALERT,\n\t\n\t/* Server tests */\n\t/* Server must reject invalid supported-elliptic-curve ext.from client */\n\tSPECIAL_CLI_INVALIDCURVE,\n\t/* Server must send supported_sig_algo ext for both P256 and P384 */\n\tSPECIAL_BOTH_SUPPALGO,\n\tSPECIAL_LAST\n\t} SPECIAL_HANDLING_TYPE;\n\n/* A table that defines the conditions for the various tests.  Note that \n   some of the test requirements are handled internally by cryptlib so \n   they're not explicitly tested here, as a result some of the entries may \n   appear to be duplicates */\n\ntypedef struct {\n\tconst char *testName;\n\n\tconst int clientOptions;\n\tconst int clientAuthKeySizeBits;\t/* 0 = no client auth.used */\n\n\tconst int serverOptions;\n\tconst int serverKeySizeBits;\n\n\tconst BOOLEAN result;\n\tconst SPECIAL_HANDLING_TYPE handlingType;\n\n\tconst char *aliasTestName;\n\t} SUITEB_TEST_INFO;\n\nstatic const SUITEB_TEST_INFO clientTestInfo[] = {\n\t\t{ NULL,\t\t\t0,\t\t\t\t0,\t\t0,\t\t\t\t0,\t\t0 },\n\t\t/* ------------------------------- Client Tests ------------------------------- */\n\t\t/* Test\t\t\tClient parm\tClient key\tServer parm\tServer key\tResult\tSpecial */\n\t\t/* ----\t\t\t-----------\t----------\t-----------\t----------\t------\t------- */\n/* 1*/\t{ \"A.1.1.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/* 2*/\t{ \"A.1.1.2\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP521,\tFALSE,\tSPECIAL_SVR_INVALIDCURVE },\n/* 3*/\t{ \"A.1.2.1\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/* 4*/\t{ \"A.1.2.2\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP521,\tFALSE,\tSPECIAL_SVR_INVALIDCURVE },\n/* 5*/\t{ \"A.1.3.1\", ALIAS, \"A.1.1.1\" },\n/* 6*/\t{ \"A.1.4.1\", ALIAS, \"A.1.1.1\" },\n/* 7*/\t{ \"A.1.5.1\", ALIAS_SPECIAL, SPECIAL_CLI_TLSALERT, \"A.1.1.2\" },\n/* 8*/\t{ \"A.1.5.2\", ALIAS_SPECIAL, SPECIAL_CLI_TLSALERT, \"A.1.2.2\" },\n/* 9*/\t{ \"A.1.6.1\", ALIAS, \"A.1.4.1\" },\n/*10*/\t{ \"A.1.7.1\",\tSECLVL_128,\t\tP256,\tSECLVL_BOTH,\tP384,\tTRUE },\n/*11*/\t{ \"A.1.7.2\",\tSECLVL_BOTH,\tP384,\tSECLVL_128,\t\tP256,\tTRUE },\n/*12*/\t{ \"A.1.8.1\", ALIAS, \"A.1.1.1\" },\n/*13*/\t{ \"A.1.9.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_BOTH,\tP384,\tTRUE },\n/*14*/\t{ \"A.1.10.1\", ALIAS, \"A.1.2.1\" },\n/*15*/\t{ \"A.1.11.1\", ALIAS, \"A.1.2.1\" },\n/*16*/\t{ \"A.1.12.1\", ALIAS, \"A.1.1.1\" },\n/*17*/\t{ \"A.1.13.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128 | FORCE_TLS12,\tP256,\tTRUE },\n/*18*/\t{ \"A.1.14.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/*19*/\t{ \"A.1.15.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/*20*/\t{ \"A.1.16.1\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/*21*/\t{ \"A.1.17.1\", ALIAS, \"A.1.14.1\" },\n/*22*/\t{ \"A.1.18.1\", ALIAS, \"A.1.14.1\" },\n/*23*/\t{ \"A.1.19.1\", ALIAS, \"A.1.1.1\" },\n/*24*/\t{ \"A.1.20.1\", ALIAS, \"A.1.1.1\" },\n/*25*/\t{ \"A.1.21.1\", ALIAS, \"A.1.2.1\" },\n/*26*/\t{ \"A.1.22.1\", ALIAS, \"A.1.1.1\" },\n/*27*/\t{ \"A.1.21.2\", ALIAS, \"A.1.2.1\" },\n/*28*/\t{ \"A.1.24.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/*29*/\t{ \"A.1.24.2\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/*30*/\t{ \"A.1.25.1\", ALIAS, \"A.1.24.1\" },\n/*31*/\t{ \"A.1.26.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP384,\tTRUE,\tSPECIAL_BOTH_SUPPCURVES },\n/*32*/\t{ \"A.1.27.1\", ALIAS, \"A.1.24.2\" },\n/*33*/\t{ \"A.1.28.1\", ALIAS, \"A.1.1.1\" },\n/*34*/\t{ \"A.1.29.1\", ALIAS, \"A.2.8.1\" },\t\t// Wrong, should be an A.1.x ref.\n/*35*/\t{ \"A.1.30.1\", ALIAS, \"A.1.2.1\" },\n/*36*/\t{ \"A.1.31.1\", ALIAS, \"A.1.1.1\" },\n/*37*/\t{ \"A.1.32.1\", ALIAS, \"A.1.1.1\" },\n/*38*/\t{ \"A.1.33.1\", ALIAS, \"A.1.7.1\" },\n/*39*/\t{ \"A.1.34.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/*40*/\t{ \"A.1.34.2\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/*41*/\t{ \"A.1.35.1\", ALIAS, \"A.1.34.1\" },\n/*42*/\t{ \"A.1.36.1\",\tSECLVL_BOTH,\t\t0,\tSECLVL_BOTH,\tP384,\tTRUE,\tSPECIAL_BOTH_SIGALGO },\n/*43*/\t{ \"A.1.37.1\", ALIAS, \"A.1.34.2\" },\n/*44*/\t{ \"A.1.39.1\",\tSECLVL_128,\t\tP256,\tSECLVL_128,\t\tP256,\tTRUE },\n/*45*/\t{ \"A.1.39.2\",\tSECLVL_256,\t\tP384,\tSECLVL_256,\t\tP384,\tTRUE },\n/*46*/\t{ \"A.1.40.1\", ALIAS, \"A.1.39.1\" },\n/*47*/\t{ \"A.1.41.1\", ALIAS, \"A.1.39.2\" },\n\t\t/* ----\t\t\t-----------\t----------\t-----------\t----------\t------\t------- */\n\t\t/* Test\t\t\tClient parm\tClient key\tServer parm\tServer key\tResult\tSpecial */\n\t\t/* ------------------------------- Client Tests ------------------------------- */\n\t\t{ NULL }, { NULL }\n\t\t};\n\nstatic const SUITEB_TEST_INFO serverTestInfo[] = {\n\t\t{ NULL,\t\t\t0,\t\t\t\t0,\t\t0,\t\t\t\t0,\t\t0 },\n\t\t/* ------------------------------- Server Tests ------------------------------- */\n\t\t/* Test\t\t\tClient parm\tClient key\tServer parm\tServer key\tResult\tSpecial */\n\t\t/* ----\t\t\t-----------\t----------\t-----------\t----------\t------\t------- */\n/* 1*/\t{ \"A.2.1.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/* 2*/\t{ \"A.2.1.2\",\tSECLVL_256,\t\t0,\t\tSECLVL_128,\t\tP256,\tFALSE,\tSPECIAL_CLI_INVALIDCURVE },\n/* 3*/\t{ \"A.2.2.1\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/* 4*/\t{ \"A.2.2.2\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tFALSE,\tSPECIAL_CLI_INVALIDCURVE },\n/* 5*/\t{ \"A.2.5.1\", ALIAS, \"A.2.1.2\" },\n/* 6*/\t{ \"A.2.5.1\", ALIAS, \"A.2.2.2\" },\n/* 7*/\t{ \"A.2.3.1\", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, \"A.2.1.2\" },\n/* 8*/\t{ \"A.2.4.1\", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, \"A.2.2.2\" },\n/* 9*/\t{ \"A.2.6.1\",\tSECLVL_128,\t\tP384,\tSECLVL_BOTH,\tP256,\tTRUE },\n/*10*/\t{ \"A.2.6.2\",\tSECLVL_128,\t\tP256,\tSECLVL_BOTH,\tP384,\tTRUE },\n/*11*/\t{ \"A.2.7.1\", ALIAS, \"A.2.1.1\" },\n/*12*/\t{ \"A.2.8.1\",\tSECLVL_128,\t\tP384,\tSECLVL_BOTH,\tP256,\tTRUE },\n/*13*/\t{ \"A.2.9.1\", ALIAS, \"A.2.2.1\" },\n/*14*/\t{ \"A.2.10.1\", ALIAS, \"A.2.2.1\" },\n/*15*/\t{ \"A.2.11.1\", ALIAS, \"A.2.6.1\" },\n/*16*/\t{ \"A.2.12.1\",\tSECLVL_128 | FORCE_TLS12, 0, SECLVL_128, P256,\tTRUE },\n/*17*/\t{ \"A.2.13.1\",\tSECLVL_BOTH,\t0,\t\tSECLVL_128,\t\tP256,\tTRUE },\n/*18*/\t{ \"A.2.14.1\",\tSECLVL_256,\t\t0,\t\tSECLVL_256,\t\tP384,\tTRUE },\n/*19*/\t{ \"A.2.15.1\", ALIAS, \"A.2.1.1\" },\n/*20*/\t{ \"A.2.16.1\", ALIAS, \"A.2.1.1\" },\n/*21*/\t{ \"A.2.17.1\", ALIAS, \"A.2.2.1\" },\n/*22*/\t{ \"A.2.18.1\", ALIAS, \"A.2.1.1\" },\n/*23*/\t{ \"A.2.18.2\", ALIAS, \"A.2.2.1\" },\n/*24*/\t{ \"A.2.20.1\", ALIAS, \"A.2.1.1\" },\n/*25*/\t{ \"A.2.21.1\", ALIAS, \"A.2.8.1\" },\n/*26*/\t{ \"A.2.22.1\", ALIAS, \"A.2.2.1\" },\n/*27*/\t{ \"A.2.23.1\",\tSECLVL_128,\t\t0,\t\tSECLVL_BOTH,\tP256,\tFALSE,\tSPECIAL_CLI_INVALIDCURVE },\n/*28*/\t{ \"A.2.24.1\", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, \"A.2.23.1\" },\n/*29*/\t{ \"A.2.26.1\",\tSECLVL_128,\t\tP256,\tSECLVL_128,\t\tP256,\tTRUE },\n/*30*/\t{ \"A.2.26.2\",\tSECLVL_256,\t\tP384,\tSECLVL_256,\t\tP384,\tTRUE },\n/*31*/\t{ \"A.2.27.1\", ALIAS, \"A.2.26.1\" },\n/*32*/\t{ \"A.2.28.1\",\tSECLVL_BOTH,\tP256,\tSECLVL_BOTH,\tP256,\tTRUE,\tSPECIAL_BOTH_SUPPALGO },\n/*33*/\t{ \"A.2.29.1\", ALIAS, \"A.2.26.2\" },\n/*34*/\t{ \"A.2.30.1\", ALIAS, \"A.2.1.1\" },\n/*35*/\t{ \"A.2.30.2\", ALIAS, \"A.2.1.2\" },\n/*36*/\t{ \"A.2.31.1\", ALIAS, \"A.2.30.1\" },\n/*37*/\t{ \"A.2.32.1\", ALIAS, \"A.2.30.1\" },\n/*38*/\t{ \"A.2.33.1\", ALIAS, \"A.2.30.2\" },\n\t\t/* ----\t\t\t-----------\t----------\t-----------\t----------\t------\t------- */\n\t\t/* Test\t\t\tClient parm\tClient key\tServer parm\tServer key\tResult\tSpecial */\n\t\t/* ------------------------------- Server Tests ------------------------------- */\n\n\t{ NULL }, { NULL }\n\t};\n\n#define SUITEB_FIRST_CLIENT\t\t1\n#define SUITEB_LAST_CLIENT\t\t48\n#define SUITEB_FIRST_SERVER\t\t1\n#define SUITEB_LAST_SERVER\t\t38\n\n/* Display the test numbers and their corresponding test names */\n\nstatic int showTest( const SUITEB_TEST_INFO *testInfoPtr )\n\t{\n\tint i;\n\n\tfor( i = 0; i < 6; i++ )\n\t\t{\n\t\tif( testInfoPtr->testName == NULL )\n\t\t\treturn( FALSE );\n\t\tprintf( \"    %8s\", testInfoPtr->testName );\n\t\ttestInfoPtr++;\n\t\t}\n\tputchar( '\\n' );\n\n\treturn( TRUE );\n\t}\n\nstatic void showTestInfo( void )\n\t{\n\tint i;\n\n\tputs( \"  Suite B client tests:\" );\n\tfor( i = 1; clientTestInfo[ i ].testName != NULL; i += 6 )\n\t\t{\n\t\tif( !showTest( &clientTestInfo[ i ] ) )\n\t\t\t{\n\t\t\tprintf( \"\\n\" );\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tputs( \"\\n  Suite B server tests:\" );\n\tfor( i = 1; serverTestInfo[ i ].testName != NULL; i += 6 )\n\t\t{\n\t\tif( !showTest( &serverTestInfo[ i ] ) )\n\t\t\t{\n\t\t\tprintf( \"\\n\" );\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n/* Look up the test number corresponding to a test name.  Returns +ve for a \n   client test, -ve for a server test, 0 for no-match */\n\nstatic int lookupTestNo( const char *testName )\n\t{\n\tint i;\n\n\tfor( i = 1; clientTestInfo[ i ].testName != NULL; i++ )\n\t\t{\n\t\tif( !strcmp( testName + 1, clientTestInfo[ i ].testName + 1 ) )\n\t\t\treturn( i );\n\t\t}\n\tfor( i = 1; serverTestInfo[ i ].testName != NULL; i++ )\n\t\t{\n\t\tif( !strcmp( testName + 1, serverTestInfo[ i ].testName + 1 ) )\n\t\t\treturn( -i );\n\t\t}\n\n\treturn( 0 );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSuite B TLS Routines Test\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Find an alias for an existing test */\n\nstatic const SUITEB_TEST_INFO *findAliasTest( const SUITEB_TEST_INFO *testInfo,\n\t\t\t\t\t\t\t\t\t\t\t  const char *testName )\n\t{\n\tint i;\n\n\tfor( i = 0; testInfo[ i ].testName != NULL; i++ )\n\t\t{\n\t\tif( !strcmp( testInfo[ i ].testName, testName ) )\n\t\t\treturn( &testInfo[ i ] );\n\t\t}\n\n\tassert( 0 );\n\treturn( NULL );\n\t}\n\n/* Establish a Suite B server session */\n\nstatic int suitebServer( const int testNo, const char *hostName, \n\t\t\t\t\t\t const int port, const int flags,\n\t\t\t\t\t\t const BOOLEAN isServerTest )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT privateKey;\n\tconst SUITEB_TEST_INFO *testInfoPtr = isServerTest ? \\\n\t\t\t\t\t&serverTestInfo[ testNo ] : &clientTestInfo[ testNo ];\n\tconst char *testName = testInfoPtr->testName;\n\tconst BOOLEAN isLoopbackTest = \\\n\t\t\t( !strcmp( hostName, \"localhost\" ) && port == 0 ) ? TRUE : FALSE;\n\tconst BOOLEAN sendHTTP = \\\n\t\t\t( flags & TESTFLAG_SENDHTTPREQ ) ? TRUE : FALSE;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\tSPECIAL_HANDLING_TYPE handlingTypeAlt = SPECIAL_NONE;\n\tvoid *fileNamePtr = filenameBuffer;\n\tint status;\n\n\t/* Make sure that we've been given a valid test number to run */\n\tif( isServerTest )\n\t\t{\n\t\tif( testNo < SUITEB_FIRST_SERVER || testNo > SUITEB_LAST_SERVER )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( testNo < SUITEB_FIRST_CLIENT || testNo > SUITEB_LAST_CLIENT )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's an alias for another test, select the base test */\n\tif( testInfoPtr->aliasTestName != NULL )\n\t\t{\n\t\thandlingTypeAlt = testInfoPtr->handlingType;\n\t\ttestInfoPtr = findAliasTest( isServerTest ? \\\n\t\t\t\t\t\t\t\t&serverTestInfo[ 1 ] : &clientTestInfo[ 1 ],\n\t\t\t\t\t\t\t\ttestInfoPtr->aliasTestName );\n\t\tif( testInfoPtr == NULL )\n\t\t\t{\n\t\t\tassert( 0 );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Acquire the init mutex */\n\tacquireMutex();\n\tcryptSuiteBTestConfig( SUITEB_TEST_NONE );\t/* Clear any custom config */\n\n\tprintf( \"SVR: Running Suite B server \" );\n\tif( flags & TESTFLAG_GENERIC )\n\t\tprintf( \"as generic test server.\\n\" );\n\telse\n\t\tprintf( \"with test %s.\\n\", testInfoPtr->testName );\n\n\t/* Create the SSL/TLS session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_SESSION_SSL_SERVER );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSL/TLS session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, 3 );\n\tif( cryptStatusOK( status ) && testInfoPtr->serverOptions != 0 )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS, \n\t\t\t\t\t\t\t\t\ttestInfoPtr->serverOptions );\n\t\t}\n\tif( testInfoPtr->clientAuthKeySizeBits > 0 ) \n\t\t{\n\t\t/* Tell the test code to expect a client certificate */\n\t\tcryptSuiteBTestConfig( 1000 );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set up the server information */\n\tif( isLoopbackTest )\n\t\t{\n\t\t/* We're running the loopback test, set up a local connect */\n\t\tif( !setLocalConnect( cryptSession, 443 ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  hostName, strlen( hostName ) );\n\t\tif( cryptStatusOK( status ) && port != 0 && port != 443 )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_PORT, port );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptSetAttribute()/cryptSetAttributeString() failed \"\n\t\t\t\t\t\"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Set any custom server configuration that may be required.  We have to \n\t   do this before we set the server key since some of the tests involve\n\t   invalid server keys */\n\tswitch( testInfoPtr->handlingType )\n\t\t{\n\t\tcase SPECIAL_SVR_INVALIDCURVE:\n\t\t\t/* Server sends non-Suite B curve */\n\t\t\tstatus = cryptSuiteBTestConfig( SUITEB_TEST_SVRINVALIDCURVE );\n\t\t\tbreak;\n\n\t\tcase SPECIAL_BOTH_SUPPCURVES:\n\t\t\t/* Client must send both P256 and P384 in supported curves \n\t\t\t   extension */\n\t\t\tstatus = cryptSuiteBTestConfig( SUITEB_TEST_BOTHCURVES );\n\t\t\tbreak;\n\n\t\tcase SPECIAL_BOTH_SIGALGO:\n\t\t\t/* Client must send both SHA256 and SHA384 in signature algos\n\t\t\t   extension */\n\t\t\tstatus = cryptSuiteBTestConfig( SUITEB_TEST_BOTHSIGALGOS );\n\t\t\tbreak;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Custom config set failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the server key */\n\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t  testInfoPtr->serverKeySizeBits );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\tstatus = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_PRIVATEKEY,\n\t\t\t\t\t\t\t\t\tprivateKey );\n\t\tcryptDestroyContext( privateKey );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"SVR: cryptSetAttribute/AttributeString() failed with error \"\n\t\t\t\t\"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* For the loopback test we also increase the connection timeout to a \n\t   higher-than-normal level, since this gives us more time for tracing \n\t   through the code when debugging */\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_CONNECTTIMEOUT, 120 );\n\n\t/* Tell the client that we're ready to go */\n\treleaseMutex();\n\n\t/* Activate the server session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( ( testInfoPtr->result && !cryptStatusOK( status ) ) || \\\n\t\t( !testInfoPtr->result && !cryptStatusError( status ) ) )\n\t\t{\n\t\tif( testInfoPtr->result )\n\t\t\t{\n\t\t\tprintf( \"SVR: Test %s failed, should have succeeded.\\n\",\n\t\t\t\t\ttestName );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tprintf( \"SVR: Test %s succeeded, should have failed.\\n\",\n\t\t\t\t\ttestName );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"SVR: Failure reason is:\", status, \n\t\t\t\t\t\t   __LINE__ );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform any custom post-activation checking that may be required */\n\tif( testInfoPtr->handlingType != 0 || handlingTypeAlt != 0 )\n\t\t{\n\t\tconst SPECIAL_HANDLING_TYPE handlingType = \\\n\t\t\t\t( handlingTypeAlt != 0 ) ? handlingTypeAlt : \\\n\t\t\t\t\t\t\t\t\t\t   testInfoPtr->handlingType;\n\t\tBYTE buffer[ 1024 ];\n\t\tint length;\n\n\t\tswitch( handlingType )\n\t\t\t{\n\t\t\tcase SPECIAL_CLI_TLSALERT:\n\t\t\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORMESSAGE, buffer, \n\t\t\t\t\t\t\t\t\t&length );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\tmemcmp( buffer, \"Received TLS alert\", 18 ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"SVR: Test %s should have returned a TLS alert \"\n\t\t\t\t\t\t\t\"but didn't.\\n\", testName );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t/* If we're being asked to send HTTP data, return a basic HTML page */\n\tif( sendHTTP )\n\t\t{\n\t\tconst char serverReply[] = \\\n\t\t\t\"HTTP/1.0 200 OK\\n\"\n\t\t\t\"Date: Fri, 7 September 2010 20:02:07 GMT\\n\"\n\t\t\t\"Server: cryptlib Suite B test\\n\"\n\t\t\t\"Content-Type: text/html\\n\"\n\t\t\t\"Connection: Close\\n\"\n\t\t\t\"\\n\"\n\t\t\t\"<!DOCTYPE HTML SYSTEM \\\"html.dtd\\\">\\n\"\n\t\t\t\"<html>\\n\"\n\t\t\t\"<head>\\n\"\n\t\t\t\"<title>cryptlib Suite B test page</title>\\n\"\n\t\t\t\"<body>\\n\"\n\t\t\t\"Test message from the cryptlib Suite B server.<p>\\n\"\n\t\t\t\"</body>\\n\"\n\t\t\t\"</html>\\n\";\n\t\tchar buffer[ FILEBUFFER_SIZE ];\n\t\tint bytesCopied;\n\n\t\t/* Print the text of the request from the client */\n\t\tstatus = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,\n\t\t\t\t\t\t\t   &bytesCopied );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"SVR: Attempt to read data from \"\n\t\t\t\t\t\t   \"client\", status, __LINE__ );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tbuffer[ bytesCopied ] = '\\0';\n\t\tprintf( \"---- Client sent %d bytes ----\\n\", bytesCopied );\n\t\tputs( buffer );\n\t\tputs( \"---- End of output ----\" );\n\n\t\t/* Send a reply */\n\t\tstatus = cryptPushData( cryptSession, serverReply,\n\t\t\t\t\t\t\t\tsizeof( serverReply ) - 1, &bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptSession );\n\t\tif( cryptStatusError( status ) || \\\n\t\t\tbytesCopied != sizeof( serverReply ) - 1 )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"Attempt to send data to client\", \n\t\t\t\t\t\t   status, __LINE__ );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tprintf( \"SVR: Suite B server test %s succeeded.\\n\", testName );\n\n\treturn( TRUE );\n\t}\n\n/* Establish a Suite B client session */\n\nstatic int suitebClient( const int testNo, const char *hostName, \n\t\t\t\t\t\t const int port, const int flags,\n\t\t\t\t\t\t const BOOLEAN isServerTest )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tconst SUITEB_TEST_INFO *testInfoPtr = isServerTest ? \\\n\t\t\t\t\t&serverTestInfo[ testNo ] : &clientTestInfo[ testNo ];\n\tconst BOOLEAN isLoopbackTest = \\\n\t\t\t( !strcmp( hostName, \"localhost\" ) && port == 0 ) ? TRUE : FALSE;\n\tconst BOOLEAN sendHTTP = \\\n\t\t\t( flags & TESTFLAG_SENDHTTPREQ ) ? TRUE : FALSE;\n\tconst char *testName = testInfoPtr->testName;\n\tSPECIAL_HANDLING_TYPE handlingTypeAlt = SPECIAL_NONE;\n\tint status;\n\n\t/* Make sure that we've been given a valid test number to run */\n\tif( isServerTest )\n\t\t{\n\t\tif( testNo < SUITEB_FIRST_SERVER || testNo > SUITEB_LAST_SERVER )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tif( testNo < SUITEB_FIRST_CLIENT || testNo > SUITEB_LAST_CLIENT )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* If it's an alias for another test, select the base test */\n\tif( testInfoPtr->aliasTestName != NULL )\n\t\t{\n\t\thandlingTypeAlt = testInfoPtr->handlingType;\n\t\ttestInfoPtr = findAliasTest( isServerTest ? \\\n\t\t\t\t\t\t\t\t&serverTestInfo[ 1 ] : &clientTestInfo[ 1 ],\n\t\t\t\t\t\t\t\ttestInfoPtr->aliasTestName );\n\t\tif( testInfoPtr == NULL )\n\t\t\t{\n\t\t\tassert( 0 );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Wait for the server to finish initialising */\n\tif( waitMutex() == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tprintf( \"Timed out waiting for server to initialise, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( !isLoopbackTest )\n\t\t{\n\t\t/* Clear any custom config, provided we're not running a loopback \n\t\t   test, in which case we'd be overwriting the options that have \n\t\t   already been set by the server */\n\t\tcryptSuiteBTestConfig( SUITEB_TEST_NONE );\n\t\t}\n\n\tprintf( \"Running Suite B client \" );\n\tif( flags & TESTFLAG_GENERIC )\n\t\tprintf( \"as generic test client.\\n\" );\n\telse\n\t\tprintf( \"with test %s.\\n\", testInfoPtr->testName );\n\n\t/* Create the SSL/TLS session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t CRYPT_SESSION_SSL );\n\tif( status == CRYPT_ERROR_PARAM3 )\t/* SSL/TLS session access not available */\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptCreateSession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, 3 );\n\tif( cryptStatusOK( status ) && testInfoPtr->clientOptions != 0 )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS, \n\t\t\t\t\t\t\t\t\ttestInfoPtr->clientOptions );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Set up the client information */\n\tif( isLoopbackTest )\n\t\t{\n\t\t/* We're running the loopback test, set up a local connect */\n\t\tif( !setLocalConnect( cryptSession, 443 ) )\n\t\t\treturn( FALSE );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  hostName, strlen( hostName ) );\n\t\tif( cryptStatusOK( status ) && port != 0 && port != 443 )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_SERVER_PORT, port );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintf( \"cryptSetAttribute()/cryptSetAttributeString() failed \"\n\t\t\t\t\t\"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\ttestInfoPtr->clientAuthKeySizeBits > 0 )\n\t\t{\n\t\tCRYPT_CONTEXT privateKey;\n\t\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\t\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\t\tvoid *fileNamePtr = filenameBuffer;\n\n\t\t/* Depending on which server we're testing against we need to use \n\t\t   different private keys */\n\t\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t\t  testInfoPtr->clientAuthKeySizeBits );\n#ifdef UNICODE_STRINGS\n\t\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\t\tfileNamePtr = wcBuffer;\n#endif /* UNICODE_STRINGS */\n\t\tstatus = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\tTEST_PRIVKEY_PASSWORD );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_PRIVATEKEY, privateKey );\n\t\t\tcryptDestroyContext( privateKey );\n\t\t\t}\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptSetAttribute/AttributeString() failed with error code \"\n\t\t\t\t\"%d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* For the loopback test we also increase the connection timeout to a \n\t   higher-than-normal level, since this gives us more time for tracing \n\t   through the code when debugging */\n\tcryptSetAttribute( cryptSession, CRYPT_OPTION_NET_CONNECTTIMEOUT, 120 );\n\n\t/* Set any custom client configuration that may be required */\n\tswitch( testInfoPtr->handlingType )\n\t\t{\n\t\tcase SPECIAL_CLI_INVALIDCURVE:\n\t\t\t/* Client sends non-Suite B curve */\n\t\t\tstatus = cryptSuiteBTestConfig( SUITEB_TEST_CLIINVALIDCURVE );\n\t\t\tbreak;\n\n\t\tcase SPECIAL_BOTH_SUPPALGO:\n\t\t\t/* Client must send supported_curves extension for both P256 \n\t\t\t   and P384 curves */\n\t\t\tstatus = cryptSuiteBTestConfig( SUITEB_TEST_BOTHSIGALGOS );\n\t\t\tbreak;\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Custom config set failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Activate the client session */\n\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );\n\tif( ( testInfoPtr->result && !cryptStatusOK( status ) ) || \\\n\t\t( !testInfoPtr->result && !cryptStatusError( status ) ) )\n\t\t{\n\t\tif( testInfoPtr->result )\n\t\t\tprintf( \"Test %s failed, should have succeeded.\\n\", testName );\n\t\telse\n\t\t\tprintf( \"Test %s succeeded, should have failed.\\n\", testName );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"Failure reason is:\", status, \n\t\t\t\t\t\t   __LINE__ );\n\t\t\t}\n\t\tcryptDestroySession( cryptSession );\n\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Perform any custom post-activation checking that may be required */\n\tif( testInfoPtr->handlingType != 0 || handlingTypeAlt != 0 )\n\t\t{\n\t\tconst SPECIAL_HANDLING_TYPE handlingType = \\\n\t\t\t\t( handlingTypeAlt != 0 ) ? handlingTypeAlt : \\\n\t\t\t\t\t\t\t\t\t\t   testInfoPtr->handlingType;\n\t\tBYTE buffer[ 1024 ];\n\t\tint length;\n\n\t\tswitch( handlingType )\n\t\t\t{\n\t\t\tcase SPECIAL_CLI_INVALIDCURVE:\n\t\t\tcase SPECIAL_BOTH_SUPPALGO:\n\t\t\t\t/* Handled by checking whether the session activation \n\t\t\t\t   failed/succeeded */\n\t\t\t\tbreak;\n\n\t\t\tcase SPECIAL_SVR_TLSALERT:\n\t\t\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_ERRORMESSAGE, buffer, \n\t\t\t\t\t\t\t\t\t&length );\n\t\t\t\tif( cryptStatusError( status ) || \\\n\t\t\t\t\tmemcmp( buffer, \"Received TLS alert\", 18 ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Test %s should have returned a TLS alert but \"\n\t\t\t\t\t\t\t\"didn't.\\n\", testName );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase SPECIAL_SVR_INVALIDCURVE:\n\t\t\t\t/* Handled/checked on the server */\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tassert( 0 );\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* If we're being asked to send HTTP data, send a basic GET */\n\tif( sendHTTP )\n\t\t{\n\t\tconst char *fetchString = \"GET / HTTP/1.0\\r\\n\\r\\n\";\n\t\tconst int fetchStringLen = sizeof( fetchString ) - 1;\n\t\tint bytesCopied;\n\n\t\tstatus = cryptPushData( cryptSession, fetchString,\n\t\t\t\t\t\t\t\tfetchStringLen, &bytesCopied );\n\t\tif( cryptStatusOK( status ) )\n\t\t\tstatus = cryptFlushData( cryptSession );\n\t\tif( cryptStatusError( status ) || bytesCopied != fetchStringLen )\n\t\t\t{\n\t\t\tprintExtError( cryptSession, \"Attempt to send data to server\", \n\t\t\t\t\t\t   status, __LINE__ );\n\t\t\tcryptDestroySession( cryptSession );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\n\t/* Clean up */\n\tstatus = cryptDestroySession( cryptSession );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptDestroySession() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tprintf( \"Suite B client test %s succeeded.\\n\", testName );\n\n\treturn( TRUE );\n\t}\n\nstatic int suitebTest( const BOOLEAN isServer, const int testNo, \n\t\t\t\t\t   const char *hostName, const int port, \n\t\t\t\t\t   const int flags )\n\t{\n\tBOOLEAN isServerTest = FALSE;\n\tint value = testNo, status;\n\n\tif( value < 0 )\n\t\t{\n\t\tisServerTest = TRUE;\n\t\tvalue = -value;\n\t\t}\n\n\t/* Set up default argument values if required */\n\tif( hostName == NULL )\n\t\thostName = \"localhost\";\n\n\t/* Run the test client or server */\n\tcreateMutex();\n\tif( isServer )\n\t\tstatus = suitebServer( value, hostName, port, flags, \n\t\t\t\t\t\t\t   isServerTest );\n\telse\n\t\tstatus = suitebClient( value, hostName, port, flags, \n\t\t\t\t\t\t\t   isServerTest );\n\tdestroyMutex();\n\treturn( status );\n\t}\n\n#ifdef WINDOWS_THREADS\n\nunsigned __stdcall suitebServerThread( void *arg )\n\t{\n\tBOOLEAN isServerTest = FALSE;\n\tint value = *( ( int * ) arg );\n\n\tif( value < 0 )\n\t\t{\n\t\tisServerTest = TRUE;\n\t\tvalue = -value;\n\t\t}\n\tsuitebServer( value, \"localhost\", 0, FALSE, isServerTest );\n\t_endthreadex( 0 );\n\treturn( 0 );\n\t}\n\nint testSessionSuiteBClientServer( void )\n\t{\n\tHANDLE hThread;\n\tunsigned threadID;\n\tBOOLEAN isServerTest = FALSE;\n\tint value = -1, status;\t/* +ve = client, -ve = server */\n\n\t/* Start the server */\n\tcreateMutex();\n\thThread = ( HANDLE ) _beginthreadex( NULL, 0, suitebServerThread,\n\t\t\t\t\t\t\t\t\t\t &value, 0, &threadID );\n\tSleep( 1000 );\n\n\t/* Connect to the local server */\n\tif( value < 0 )\n\t\t{\n\t\tisServerTest = TRUE;\n\t\tvalue = -value;\n\t\t}\n\tstatus = suitebClient( value, \"localhost\", 0, FALSE, isServerTest );\n\twaitForThread( hThread );\n\tdestroyMutex();\n\treturn( status );\n\t}\n#endif /* WINDOWS_THREADS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSuite B Keygen\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generate an ECDSA private key and certificate request */\n\nstatic const CERT_DATA certRequestData[] = {\n\t/* Identification information */\n\t{ CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( \"NZ\" ) },\n\t{ CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( \"Dave's Wetaburgers\" ) },\n\t{ CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( \"localhost\" ) },\n\n\t{ CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }\n\t};\n\nstatic int generateKey( const int keyBits, const char *certRequestFileName )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCertRequest;\n\tCRYPT_CONTEXT cryptKey;\n\tFILE *filePtr;\n\tBYTE certBuffer[ BUFFER_SIZE ];\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tvoid *fileNamePtr = filenameBuffer;\n\tint length, count = 0, status;\n\n\t/* Generate a key to certify.  We can't just reuse the built-in test key\n\t   because this has already been used as the CA key and the keyset code\n\t   won't allow it to be added to a keyset as both a CA key and user key,\n\t   so we have to generate a new one */\n\tstatus = cryptCreateContext( &cryptKey, CRYPT_UNUSED, CRYPT_ALGO_ECDSA );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSetAttribute( cryptKey, CRYPT_CTXINFO_KEYSIZE, \n\t\t\t\t\t\t\t\t\tkeyBits >> 3 );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptKey, CRYPT_CTXINFO_LABEL,\n\t\t\t\t\t\t\t\t\t\t  USER_PRIVKEY_LABEL,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( USER_PRIVKEY_LABEL ) );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptGenerateKey( cryptKey );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Key generation failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the certificate request for the new key */\n\tstatus = cryptCreateCert( &cryptCertRequest, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTREQUEST );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptCertRequest,\n\t\t\t\t\tCRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptKey );\n\t\t}\n\tif( cryptStatusOK( status ) && \\\n\t\t!addCertFields( cryptCertRequest, certRequestData, __LINE__ ) )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( status ) )\n\t\tstatus = cryptSignCert( cryptCertRequest, cryptKey );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &length,\n\t\t\t\t\t\t\t\t  CRYPT_CERTFORMAT_CERTIFICATE, \n\t\t\t\t\t\t\t\t  cryptCertRequest );\n\t\tcryptDestroyCert( cryptCertRequest );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Certificate request creation failed with error code %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( ( filePtr = fopen( certRequestFileName, \"wb\" ) ) != NULL )\n\t\t{\n\t\tcount = fwrite( certBuffer, 1, length, filePtr );\n\t\tfclose( filePtr );\n\t\t}\n\tif( filePtr == NULL || count < length )\n\t\t{\n\t\tprintf( \"Couldn't write certificate request to disk, line %d.\\n\", \n\t\t\t\t__LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Create the keyset and add the private key to it */\n\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t  keyBits );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  fileNamePtr, CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"cryptKeysetOpen() failed with error code %d, line %d.\\n\",\n\t\t\t\tstatus, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptAddPrivateKey( cryptKeyset, cryptKey,\n\t\t\t\t\t\t\t\t TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintExtError( cryptKeyset, \"cryptAddPrivateKey()\", status, \n\t\t\t\t\t   __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( cryptKey );\n\tcryptKeysetClose( cryptKeyset );\n\n\treturn( TRUE );\n\t}\n\n/* Add an ECDSA certificate to a previously-generated key */\n\nstatic int updateKey( const int keyBits, const char *certFileName )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tCRYPT_CERTIFICATE cryptCert;\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tvoid *fileNamePtr = filenameBuffer;\n\tint status;\n\n\t/* Import the certificate from the file */\n\tstatus = importCertFile( &cryptCert, certFileName );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't import certificate from file, status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the certificate to the file */\n\tfilenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, \n\t\t\t\t\t\t  keyBits );\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  fileNamePtr, CRYPT_KEYOPT_NONE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptAddPublicKey( cryptKeyset, cryptCert );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Couldn't update private key with certificate, status %d, \"\n\t\t\t\t\"line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tSuite B Test Application\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Show usage and exit */\n\nstatic void usageExit( void )\n\t{\n\tputs( \"Usage: testlib c|s [-h hostname] [-p port] [-s] <test>\" );\n\n\tputs( \"  Operation type:\" );\n\tputs( \"    c = Run test as the client.\" );\n\tputs( \"    s = Run test as the server.\" );\n\tputs( \"    <test> = Test name, e.g. 'A.1.1.1', or '128'/'256' to run as a\" );\n\tputs( \"             generic 128/256-bit client or server.\" );\n\tputs( \"\" );\n\n\tputs( \"  Options:\" );\n\tputs( \"    -s = Send HTTP request.\" );\n\tputs( \"    -h <hostname> = Host name (default localhost).\" );\n\tputs( \"    -p <port> = Port (default 443 or 4443).\" );\n\tputs( \"    -- = End of arg list.\" );\n\tputs( \"\" );\n\tshowTestInfo();\n\tputs( \"\" );\n\n\tputs( \"  Keygen commands:\" );\n\tputs( \"\" );\n\tputs( \"    kg [256|384] <cert-request filename>\" );\n\tputs( \"      = Generate 256/384-bit key and PKCS #10 cert request.\" );\n\tputs( \"    ka [256|384] <certificate filename>\" );\n\tputs( \"      = Add issued certificate to previously-generated 256/384-bit key.\" );\n\tputs( \"\" );\n\n\texit( EXIT_FAILURE );\n\t}\n\n/* Process command-line arguments */\n\nstatic int processArgs( int argc, char **argv, int *testNo, \n\t\t\t\t\t\tconst char **stringArg, int *intArg, \n\t\t\t\t\t\tBOOLEAN *isServer, BOOLEAN *sendHTTPheader )\n\t{\n\tconst char *argPtr = argv[ 0 ];\n\tBOOLEAN moreArgs = TRUE;\n\tint value;\n\n\t/* Clear return values */\n\t*testNo = *intArg = 0;\n\t*stringArg = NULL;\n\t*isServer = *sendHTTPheader = FALSE;\n\n\t/* No args means display a usage message */\n\tif( argc <= 0 )\n\t\tusageExit();\n\n\t/* Process the main command */\n\tswitch( tolower( *argPtr ) )\n\t\t{\n\t\tcase 'c':\n\t\t\t*isServer = FALSE;\n\t\t\targv++; argc--;\n\t\t\tbreak;\n\t\t\n\t\tcase 's':\n\t\t\t*isServer = TRUE;\n\t\t\targv++; argc--;\n\t\t\tbreak;\n\n\t\tcase 'k':\n\t\t\tswitch( tolower( argPtr[ 1 ] ) )\n\t\t\t\t{\n\t\t\t\tcase 'g':\n\t\t\t\t\t*testNo = -1;\t/* Generate key */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'a':\n\t\t\t\t\t*testNo = -2;\t/* Add certificate */\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tprintf( \"Error: Unknown key management option '%c'.\\n\", \n\t\t\t\t\t\t\targPtr[ 1 ] );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Get the key size */\n\t\t\targv++; argc--;\n\t\t\tif( argc <= 0 )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Missing key size.\" );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\targPtr = argv[ 0 ];\n\t\t\tvalue = -1;\n\t\t\tif( *argPtr == '2' || *argPtr == '3' )\n\t\t\t\tvalue = atoi( argv[ 0 ] );\n\t\t\tif( value != 256 && value != 384 )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Key size must be '256' or '384'.\" );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t*intArg = value;\n\n\t\t\t/* Get the filename */\n\t\t\targv++; argc--;\n\t\t\tif( argc <= 0 )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Missing file name.\" );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t*stringArg = argv[ 0 ];\n\t\t\tif( *testNo == -2 )\n\t\t\t\t{\n\t\t\t\tFILE *filePtr;\n\n\t\t\t\t/* Make sure that the specified input file exists */\n\t\t\t\tfilePtr = fopen( argv[ 0 ], \"rb\" );\n\t\t\t\tif( filePtr == NULL )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Error: Can't open '%s'.\\n\", argv[ 0 ] );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tfclose( filePtr );\n\t\t\t\t}\n\n\t\t\t/* Make sure that's all */\n\t\t\targv++; argc--;\n\t\t\tif( argc != 0 )\n\t\t\t\t{\n\t\t\t\tprintf( \"Error: Spurious option '%s'.\\n\", argv[ 0 ] );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tusageExit();\n\t\t}\n\n\t/* Process any additional arguments */\n\twhile( argc > 0 && moreArgs )\n\t\t{\n\t\targPtr = argv[ 0 ];\n\t\tif( *argPtr == '1' || *argPtr == '2' )\n\t\t\t{\n\t\t\t/* The user has asked to run as a generic 128/256-bit client or \n\t\t\t   server, map it to an equivalent test number */\n\t\t\tvalue = atoi( argPtr );\n\t\t\tif( value != 128 && value != 256 )\n\t\t\t\t{\n\t\t\t\tputs( \"Error: Generic client/server type must be '128' \"\n\t\t\t\t\t  \"or '256'.\" );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( value == 128 )\n\t\t\t\targPtr = \"A.1.1.1\";\n\t\t\telse\n\t\t\t\targPtr = \"A.1.2.1\";\n\t\t\t}\n\t\tif( *argPtr == 'a' || *argPtr == 'A' )\n\t\t\t{\n\t\t\tint value;\n\n\t\t\tif( *testNo != 0 )\n\t\t\t\tusageExit();\n\n\t\t\t/* Perform a basic validity test that the argument is in the \n\t\t\t   format \"A.[12].[1-3]\" */\n\t\t\tif( argPtr[ 1 ] != '.' || \\\n\t\t\t\t( argPtr[ 2 ] != '1' && argPtr[ 2 ] != '2' ) || \\\n\t\t\t\targPtr[ 3 ] != '.' || \\\n\t\t\t\t( argPtr[ 4 ] < '1' || argPtr[ 4 ] > '3' ) )\n\t\t\t\tusageExit();\n\t\t\tvalue = lookupTestNo( argPtr );\n\t\t\tif( value == 0 )\n\t\t\t\t{\n\t\t\t\tprintf( \"Error: Unknown test type '%s'.\\n\", argPtr );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t*testNo = value;\n\t\t\targv++;\n\t\t\targc--;\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( *argPtr != '-' )\n\t\t\t{\n\t\t\tprintf( \"Error: Unknown argument '%s'.\\n\", argPtr );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\targPtr++;\n\t\twhile( *argPtr )\n\t\t\t{\n\t\t\tswitch( toupper( *argPtr ) )\n\t\t\t\t{\n\t\t\t\tcase '-':\n\t\t\t\t\tmoreArgs = FALSE;\t/* GNU-style end-of-args flag */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'H':\n\t\t\t\t\tif( *stringArg != NULL )\n\t\t\t\t\t\tusageExit();\n\t\t\t\t\targv++; argc--;\n\t\t\t\t\tif( argc <= 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tputs( \"Error: Missing host name\" );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\t*stringArg = argv[ 0 ];\n\t\t\t\t\targPtr = \"\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'P':\n\t\t\t\t\tif( *intArg != 0 )\n\t\t\t\t\t\tusageExit();\n\t\t\t\t\targv++; argc--;\n\t\t\t\t\tif( argc <= 0 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tputs( \"Error: Missing port number\" );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\tvalue = atoi( argv[ 0 ] );\n\t\t\t\t\tif( value < 20 || value > 64000 )\n\t\t\t\t\t\tusageExit();\n\t\t\t\t\t*intArg = value;\n\t\t\t\t\targPtr = \"\";\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'S':\n\t\t\t\t\tif( *sendHTTPheader != FALSE )\n\t\t\t\t\t\tusageExit();\n\t\t\t\t\t*sendHTTPheader = TRUE;\n\t\t\t\t\targPtr++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tprintf( \"Error: Unknown argument '%c'.\\n\", *argPtr );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\t}\n\t\targv++;\n\t\targc--;\n\t\t}\n\tif( *testNo == 0 )\n\t\t{\n\t\tputs( \"Error: Missing test name\" );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* The main entry point for the Suite B test application */\n\nint suiteBMain( int argc, char **argv )\n\t{\n\tconst char *stringArg;\n\tBOOLEAN isServer, sendHTTPheader;\n\tint testNo, intArg, status;\n\tvoid testSystemSpecific1( void );\n\tvoid testSystemSpecific2( void );\n\n\tprintf( \"testlib - cryptlib %d-bit Suite B test framework.\\n\", \n\t\t\t( int ) sizeof( long ) * 8 );\t/* Cast for gcc */\n\tputs( \"Copyright Peter Gutmann 1995 - 2011.\" );\n\tputs( \"\" );\n\n\t/* Skip the program name and process any command-line arguments */\n\targv++; argc--;\n\tstatus = processArgs( argc, argv, &testNo, &stringArg, &intArg, \n\t\t\t\t\t\t  &isServer, &sendHTTPheader );\n\tif( !status )\n\t\texit( EXIT_FAILURE );\n\n\t/* Make sure that various system-specific features are set right */\n\ttestSystemSpecific1();\n\n\t/* Initialise cryptlib */\n\tstatus = cryptInit();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptInit() failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* In order to avoid having to do a randomness poll for every test run,\n\t   we bypass the randomness-handling by adding some junk.  This is only\n\t   enabled when cryptlib is built in debug mode so it won't work with \n\t   any production systems */\n\tcryptAddRandom( \"xyzzy\", 5 );\n\n\t/* Perform a general sanity check to make sure that the self-test is\n\t   being run the right way */\n\tif( !checkFileAccess() )\n\t\texit( EXIT_FAILURE );\n\n\t/* Make sure that further system-specific features that require cryptlib \n\t   to be initialised to check are set right */\n\ttestSystemSpecific2();\n\n\t/* If the test number is negative, it's a special-case non-test \n\t   operation */\n\tif( testNo < 0 )\n\t\t{\n\t\tswitch( testNo )\n\t\t\t{\n\t\t\tcase -1:\n\t\t\t\tstatus = generateKey( intArg, stringArg );\n\t\t\t\tif( status == TRUE )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Wrote %d-bit certificate request to \"\n\t\t\t\t\t\t\t\"file '%s'.\\n\\n\", intArg, stringArg );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase -2:\n\t\t\t\tstatus = updateKey( intArg, stringArg );\n\t\t\t\tif( status == TRUE )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Updated %d-bit key with certificate from \"\n\t\t\t\t\t\t\t\"file '%s'.\\n\\n\", intArg, stringArg );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\t/* Run the selected test */\n\t\tstatus = suitebTest( isServer, testNo, stringArg, intArg, \n\t\t\t\t\t\t\t sendHTTPheader );\n\t\t}\n\n\t/* Clean up and exit */\n\tcryptEnd();\n\treturn( ( status == TRUE ) ? EXIT_SUCCESS : EXIT_FAILURE );\n\t}\n#endif /* CONFIG_SUITEB_TESTS */\n"
  },
  {
    "path": "deps/cl345/test/test.h",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tcryptlib Test Routines Header File\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2018\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Define the following to enable/disable various blocks of tests.  Note\n   that the self-test uses a sizeable amount of automatic data, on 16-bit\n   systems it'll probably be necessary to run each test individually rather\n   than in groups as arranged below */\n\n#if 1\n#define TEST_SELFTEST\t\t/* Perform internal self-test */\n#define TEST_LOWLEVEL\t\t/* Test low-level functions */\n#define TEST_RANDOM\t\t\t/* Test randomness functions */\n#define TEST_CONFIG\t\t\t/* Test configuration functions */\n#define TEST_MIDLEVEL\t\t/* Test high-level encr/sig.functions */\n#endif /* 0 */\n#if 1\n#define TEST_CERT\t\t\t/* Test certificate management functions */\n#define TEST_KEYSET\t\t\t/* Test keyset read functions */\n#define TEST_CERTPROCESS\t/* Test certificate handling/CA management */\n#endif /* 0 */\n#if 1\n#define TEST_HIGHLEVEL\t\t/* Test high-level encr/sig.functions */\n#define TEST_ENVELOPE\t\t/* Test enveloping functions */\n#endif /* 0 */\n#if 0\n/* The crypto device tests are disabled by default since relatively few \n   users will have a crypto device set up so leaving them enabled would just \n   produce a cascade of device-not-present warnings */\n#define TEST_DEVICE\t\t\t/* Test device functions */\n#endif /* 0 */\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && !defined( NDEBUG ) && 0\n  /* We enable the device test under VC++ 6.0 debug so that it gets tested\n     in at least one configuration */\n  #define TEST_DEVICE\n#endif /* VC++ 6.0 debug */\n#if 1\n#define TEST_SESSION\t\t/* Test session functions */\n#define TEST_SESSION_LOOPBACK/* Test session functions via local loopback */\n/*#define TEST_USER\t\t\t// Test user management functions */\n#endif /* 0 */\n\n/* If device tests are enabled then we need to re-enable low-level and \n   envelope tests if they're not enabled, since the code is used by the\n   device tests */\n\n#if defined( TEST_DEVICE )\n  #ifndef TEST_LOWLEVEL\n\t#define TEST_LOWLEVEL\n  #endif /* TEST_LOWLEVEL */\n  #ifndef TEST_ENVELOPE\n\t#define TEST_ENVELOPE\n  #endif /* TEST_ENVELOPE */\n#endif /* Low-level and envelope tests are called by the device tests */\n\n/* Some of the device tests can be rather slow, the following defines disable\n   these tests for speed reasons.  Note that the Fortezza test can be further\n   cut down by not performing the CAW test (which erases any existing data on\n   the card), this is turned off by default in testdev.c */\n\n/* #define TEST_DEVICE_FORTEZZA */\n\n/* DH and KEA can't be tested because they use cryptlib-internal mechanisms,\n   however by using a custom-modified cryptlib it's possible to test at\n   least part of the DH implementation.  If the following is defined, the\n   DH key load will be tested */\n\n/* #define TEST_DH */\n\n/* To test the code under Windows CE:\n\n\t- If PB can't start the emulator, start it manually via Tools | Configure\n\t  Platform Manager | StandardSDK Emulator | Properties | Test.\n\t- Before running the self-test for the first time, from the emulator\n\t  select Folder Sharing, share the test subdirectory, which will appear\n\t  as \\\\Storage Card\\ (sharing it while an app is running may crash the\n\t  emulator).\n\t- If eVC++ can't connect to the emulator, enable the WCE Config toolbar,\n\t  frob all the settings (which have only one option anyway).  VC++ will\n\t  rebuild everything (with exactly the same settings as before), and\n\t  then it'll work.\n\t- Only cl32ce.dll can be run in the debugger, test32ce.exe fails with\n\t  some unknown error code.\n\t- To test the randomness polling in the emulated environment, first run\n\t  the Remote Kernel Tracker, which installs the ToolHelp DLL (this isn't\n\t  installed by default) */\n\n/* When commenting out code for testing, the following macro displays a\n   warning that the behaviour has been changed as well as the location of\n   the change */\n\n#define KLUDGE_WARN( str )\t\\\n\t\tfprintf( outputStream, \"Kludging \" str \", file \" __FILE__ \", \\\n\t\t\t\t line %d.\\n\", __LINE__ )\n\n/* Include universally-needed headers */\n\n#if defined( _WIN32_WCE ) && _WIN32_WCE < 400\n  #define assert( x )\n#else\n  #include <assert.h>\n#endif /* Systems without assert() */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n/* Various useful types */\n\n#define BOOLEAN\tint\n#define BYTE\tunsigned char\n#ifndef TRUE\n  #define FALSE\t0\n  #define TRUE\t!FALSE\n#endif /* TRUE */\n\n/* Sentinel value used to denote non-data/non-values */\n\n#define SENTINEL\t\t-1000\n\n/* A dummy initialistion value used to deal with false-positive compiler \n   warnings */\n\n#ifndef DUMMY_INIT\n  #define DUMMY_INIT\t= 0\n#endif /* DUMMY_INIT */\n\n/* There are a few OSes broken enough not to define the standard exit codes\n   (SunOS springs to mind) so we define some sort of equivalent here just\n   in case */\n\n#ifndef EXIT_SUCCESS\n  #define EXIT_SUCCESS\t0\n  #define EXIT_FAILURE\t!EXIT_SUCCESS\n#endif /* EXIT_SUCCESS */\n\n/* Although min() and max() aren't in the ANSI standard, most compilers have\n   them in one form or another, but just enough don't that we need to define \n   them ourselves in some cases */\n\n#if !defined( min )\n  #ifdef MIN\n\t#define min\t\tMIN\n\t#define max\t\tMAX\n  #else\n\t#define min( a, b )\t( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )\n\t#define max( a, b )\t( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )\n  #endif /* Various min/max macros */\n#endif /* !min/max */\n\n/* If we're using a 16-bit compiler, record this */\n\n#if defined( __MSDOS__ ) && !defined( __MSDOS32__ )\n  #define __MSDOS16__\n#endif /* 16-bit DOS */\n#if defined( _MSC_VER ) && ( _MSC_VER <= 800 )\n  #define __WIN16__\n#endif /* 16-bit Windows */\n\n/* It's useful to know if we're running under Windows to enable Windows-\n   specific processing */\n\n#if defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \\\n\tdefined( _WIN32_WCE )\n  #define __WINDOWS__\n#endif /* _WINDOWS || WIN32 || _WIN32 */\n\n/* If we're running in an environment with a Unicode API, we have to be able\n   to function with both Unicode and ASCII strings */\n\n#ifdef __WINDOWS__\n  #if defined( _WIN32_WCE )\n\t#undef TEXT\n\t#define TEXT( x )\t\t\t\tL ## x\n\t#define paramStrlen( x )\t\t( wcslen( x ) * sizeof( wchar_t ) )\n\t#define paramStrcmp( x, y )\t\twcscmp( x, y )\n\t#define UNICODE_STRINGS\n  #elif ( defined( WIN32 ) || defined( _WIN32 ) ) && 0\n\t/* Facility to test WinCE Unicode handling under Win32 */\n\t#undef TEXT\n\t#define TEXT( x )\t\t\t\tL ## x\n\t#define paramStrlen( x )\t\t( wcslen( x ) * sizeof( wchar_t ) )\n\t#define paramStrcmp( x, y )\t\twcscmp( x, y )\n\t#define UNICODE_STRINGS\n  #else\n\t#undef TEXT\t\t\t\t\t\t/* Already defined in windows.h */\n\t#define TEXT( x )\t\t\t\tx\n\t#define paramStrlen( x )\t\tstrlen( x )\n\t#define paramStrcmp( x, y )\t\tstrcmp( x, y )\n  #endif /* Windows variants */\n#else\n  #define TEXT( x )\t\t\t\t\tx\n  #define paramStrlen( x )\t\t\tstrlen( x )\n  #define paramStrcmp( x, y )\t\tstrcmp( x, y )\n#endif /* Unicode vs. ASCII API */\n\n/* In certain memory-starved environments we have to kludge things to help\n   the compiler along.  The following define tells the compiler to move BSS\n   data outside the default data segment */\n\n#if defined( _MSC_VER ) && ( _MSC_VER <= 800 )\n  #define FAR_DATA\t\t\tfar\n#else\n  #define FAR_DATA\n#endif /* Win16 */\n\n/* VS 2005 and newer warn if we use non-TR 24731 stdlib functions, since \n   this is only for the test code we disable the warnings.  In addition\n   VS in 64-bit mode warns about size_t (e.g. from calling strlen()) <-> \n   int conversion */\n\n#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )\n  #pragma warning( disable: 4267 )\t/* int <-> size_t */\n  #pragma warning( disable: 4996 )\t/* Non-TR 24731 stdlib use */\n#endif /* VC++ 2005 or newer */\n\n/* Format specifiers for printing time_t's */\n\n#if defined( _MSC_VER ) && defined( _M_X64 )\n  /* Win64, time_t is 64 bits */\n  #define TIMET_FORMAT\t\"%lld\"\n#elif defined( _MSC_VER ) && ( _MSC_VER >= 1700 )\n  /* VS 2012 and newer, time_t is 64 bits */\n  #define TIMET_FORMAT\t\"%lld\"\n#else\n  #define TIMET_FORMAT\t\"%ld\"\n#endif /* Environment-specific time_t size */\n\n/* Generic buffer size and dynamically-allocated file I/O buffer size.  The\n   generic buffer has to be of a reasonable size so that we can handle \n   S/MIME signature chains, the file buffer should be less than the 16-bit \n   INT_MAX for testing on 16-bit machines and less than 32K for testing on \n   the (16-bit DOS-derived) Watcom C 10 */\n\n#if defined( __MSDOS16__ ) || defined( __WIN16__ )\n  #define BUFFER_SIZE\t\t\t4096\n  #define FILEBUFFER_SIZE\t\t30000\n#elif defined( __QNX__ ) && defined( __WATCOMC__ ) && ( __WATCOMC__ < 1100 )\n  #define BUFFER_SIZE\t\t\t8192\n  #define FILEBUFFER_SIZE\t\t30000\n#else\n  #define BUFFER_SIZE\t\t\t16384\n  #define FILEBUFFER_SIZE\t\t40960\n#endif /* __MSDOS__ && __TURBOC__ */\n#define FILENAME_BUFFER_SIZE\t512\n\n/* Explicit includes needed by Palm OS, see the comment in crypt.h for more\n   details */\n\n#ifdef __PALMSOURCE__\n  #include <ctype.h>\n  #include <string.h>\n#endif /* __PALMSOURCE__ */\n\n/* The ability to get rid of annoying warnings via the project file in BC++\n   5.0x is completely broken, the only way to do this is via pragmas in the\n   source code */\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x550 )\n  #pragma warn -ucp\t\t\t\t\t\t/* Signed/unsigned char assignment */\n#endif /* Broken BC++ 5.0x warning handling */\n\n/* Helper function to make tracking down errors on systems with no console a\n   bit less painful */\n\n#ifdef _WIN32_WCE\n  #define printf\twcPrintf\n  #define puts\t\twcPuts\n\n  void wcPrintf( const char *format, ... );\n  void wcPuts( const char *string );\n#endif /* Console-less environments */\n\n/* Try and detect OSes that have threading support, this is needed for some\n   operations like sleep calls */\n\n#if( ( defined( _AIX ) || defined( __APPLE__ ) || defined( __FreeBSD__ ) || \\\n\t   defined( __NetBSD__ ) || defined( __linux__ ) || \\\n\t   ( defined( sun ) && ( OSVERSION > 4 ) ) ) && !defined( NO_THREADS ) )\n  #define UNIX_THREADS\n\n  /* We need to include pthread.h at this point because any number of other\n     include files perform all sorts of peculiar and unnatural acts in order\n     to make their functions (transparently) thread-safe, triggered by the\n     detection of values defined in pthread.h.  Because of this we need to\n     include it here as a rubber chicken before other files are pulled in\n     even though it's not explicitly needed */\n  #include <pthread.h>\n#endif /* AIX || OS/X || Linux || Slowaris */\n#if ( defined( WIN32 ) || defined( _WIN32 ) ) && !defined( _WIN32_WCE )\n  /* We don't test the loopback functionality under WinCE because the\n\t _beginthreadx() vs. CreateThread() issue (normally hidden in\n\t cryptos.h) causes all sorts of problems */\n  #define WINDOWS_THREADS\n  #include <process.h>\n#endif /* Win32 */\n#if defined( __IBMC__ ) && defined( __OS2__ )\n  #define OS2_THREADS\n#endif /* OS/2 */\n\n/* Compiler-version check values needed when we pull in config.h */\n\n#ifdef __WINDOWS__\n  /* For checking for debug-only capabilities */\n  #define _OSSPEC_DEFINED\n  #if !defined( __WIN32__ ) && ( defined( WIN32 ) || defined( _WIN32 ) )\n\t#define __WIN32__\n  #elif !defined( __WIN64__ ) defined( _M_X64 )\n\t#define __WIN64__\n  #endif /* Win32/Win64 */\n  #define _OSSPEC_DEFINED\n  #define VC_16BIT( version )\t\t( version <= 800 )\n  #define VC_LE_VC6( version )\t\t( version <= 1200 )\n  #define VC_LT_2005( version )\t\t( version < 1400 )\n  #define VC_GE_2005( version )\t\t( version >= 1400 )\n  #define VC_GE_2010( version )\t\t( version >= 1600 )\n  #define VC_GE_2017( version )\t\t( version >= 1910 )\n#else\n  #define VC_16BIT( version )\t\t0\n  #define VC_LE_VC6( version )\t\t0\n  #define VC_LT_2005( version )\t\t0\n  #define VC_GE_2005( version )\t\t0\n  #define VC_GE_2010( version )\t\t0\n  #define VC_GE_2017( version )\t\t0\n#endif /* __WINDOWS__ */\n\n/* The loopback sessions require threading support so we only enable their\n   use if this is present */\n\n#if defined( TEST_SESSION_LOOPBACK ) && !defined( WINDOWS_THREADS )\n  #undef TEST_SESSION_LOOPBACK\n#endif /* OSes with threading support */\n\n/* Define various portable data types and functions needed for the threaded\n   loopback tests */\n\n#if defined( WINDOWS_THREADS )\n  #define THREAD_HANDLE\t\tHANDLE\n  #define THREAD_EXIT()\t\t_endthreadex( 0 ); return( 0 )\n  #define THREAD_SELF()\t\tGetCurrentThreadId()\n  typedef unsigned ( __stdcall *THREAD_FUNC )( void *arg );\n#elif defined( UNIX_THREADS )\n  #define THREAD_HANDLE\t\tpthread_t\n  #define THREAD_EXIT()\t\tpthread_exit( ( void * ) 0 ); return( 0 )\n  #define THREAD_SELF()\t\tpthread_self()\n  typedef void * ( *THREAD_FUNC )( void *arg );\n#else\n  #define THREAD_HANDLE\t\tint\n  #define THREAD_EXIT()\n  #define THREAD_SELF()\t\t0\n  typedef void ( *THREAD_FUNC )( void *arg );\n#endif /* OS-specific threading functions */\n\n/* The maximum number of threads that we can fire up in the multithreaded \n   tests */\n\n#define MAX_NO_THREADS\t\t10\n\n/* Try and detect OSes that have widechar support */\n\n#if ( defined( __WINDOWS__ ) && \\\n\t  !( defined( __WIN16__ ) || defined( __BORLANDC__ ) ) )\n  #define HAS_WIDECHAR\n#endif /* Windows with widechar support */\n#if defined( __linux__ ) || \\\n\t( defined( sun ) && ( OSVERSION > 4 ) ) || defined( __osf__ )\n  #include <wchar.h>\n  #define HAS_WIDECHAR\n#endif /* Unix with widechar support */\n\n/* If we're running on an EBCDIC system, ensure that we're compiled in \n   EBCDIC mode to test the conversion of character strings */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* If we're compiling under QNX, make enums a fixed size rather than using\n   the variable-length values that the Watcom compiler defaults to */\n\n#if defined( __QNX__ ) && defined( __WATCOMC__ )\n  #pragma enum int\n#endif /* QNX and Watcom C */\n\n/* In some cases we may want to disable the displaying of output, for example\n   if we're wrapping a lower-level test in a higher-level one.  The following\n   variable is used to control where output is sent */\n\nextern FILE *outputStream;\n#ifdef __WINDOWS__\n  #define DEVNULL\t\"nul:\"\n#else\n  #define DEVNULL\t\"/dev/null\"\n#endif /* OS-specific /dev/null output */\n\n\n/* Since the handling of filenames can get unwieldy when we have large\n   numbers of similar files, we use a function to map a filename template\n   and number into an actual filename rather the having to use huge\n   numbers of defines */\n\n#ifdef UNICODE_STRINGS\n  void filenameFromTemplate( char *buffer, const wchar_t *fileTemplate,\n\t\t\t\t\t\t\t const int count );\n  void filenameParamFromTemplate( wchar_t *buffer,\n\t\t\t\t\t\t\t\t  const wchar_t *fileTemplate,\n\t\t\t\t\t\t\t\t  const int count );\n  const char *convertFileName( const C_STR fileName );\n#else\n  #define filenameFromTemplate( buffer, fileTemplate, count ) \\\n\t\t  sprintf( buffer, fileTemplate, count )\n  #define filenameParamFromTemplate( buffer, fileTemplate, count ) \\\n\t\t  sprintf( buffer, fileTemplate, count )\n  #define convertFileName( fileName )\tfileName\n#endif /* Unicode vs. ASCII */\n\n/* Helper functions for limited environments that are missing full stdlib\n   support */\n\n#if defined( _WIN32_WCE ) && _WIN32_WCE < 500\n  int remove( const char *pathname );\n#endif /* WinCE < 5.x */\n\n/* A structure that allows us to specify a collection of extension\n   components.  This is used when adding a collection of extensions to a\n   cert */\n\ntypedef enum { IS_VOID, IS_NUMERIC, IS_STRING, IS_WCSTRING,\n\t\t\t   IS_TIME } COMPONENT_TYPE;\n\ntypedef struct {\n\tconst CRYPT_ATTRIBUTE_TYPE type;/* Extension component ID */\n\tconst COMPONENT_TYPE componentType;\t/* Component type */\n\tconst int numericValue;\t\t\t/* Value if numeric */\n\tconst void *stringValue;\t\t/* Value if string */\n\tconst time_t timeValue;\t\t\t/* Value if time */\n\t} CERT_DATA;\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\tNaming\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Pull in the OS-specific file names for the test data */\n\n#ifdef _MSC_VER\n  #include \"filename.h\"\n#else\n  #include \"test/filename.h\"\n#endif /* Braindamaged MSC include handling */\n\n/* When we're using common code to handle a variety of key file types for\n   key read/encryption/signing tests, we need to distinguish between the\n   different key files to use.  The following types are handled in the test\n   code */\n\ntypedef enum { KEYFILE_NONE, KEYFILE_X509, KEYFILE_X509_ALT, KEYFILE_PGP, \n\t\t\t   KEYFILE_PGP_SPECIAL, KEYFILE_OPENPGP_HASH, \n\t\t\t   KEYFILE_OPENPGP_AES, KEYFILE_OPENPGP_AES_KEYID, \n\t\t\t   KEYFILE_OPENPGP_CAST, KEYFILE_OPENPGP_RSA, \n\t\t\t   KEYFILE_OPENPGP_MULT, KEYFILE_NAIPGP, \n\t\t\t   KEYFILE_OPENPGP_PARTIAL, KEYFILE_OPENPGP_BOUNCYCASTLE,\n\t\t\t   KEYFILE_OPENPGP_ECC \n\t\t\t } KEYFILE_TYPE;\n\n/* When we're testing certificate chain handling, we need to deal with \n   various test certificates.  The following types define which test\n   certificate we're using */\n\ntypedef enum {\n\tCHAINTEST_NOCERT,\t\t\t/* No certificate */\n\tCHAINTEST_LEAF,\t\t\t\t/* Leaf certificate */\n\tCHAINTEST_ISSUER,\t\t\t/* Issuer of leaf (= intermed.CA) */\n\tCHAINTEST_ROOT,\t\t\t\t/* Root certificate */\n\tCHAINTEST_CHAIN,\t\t\t/* Full certificate chain */\n\tCHAINTEST_CHAIN_NOROOT,\t\t/* Chain without root certificate */\n\tCHAINTEST_CHAIN_NOLEAF\t\t/* Chain without leaf certificate */\n\t} CHAINTEST_CERT_TYPE;\n\n/* The generic password used for password-based encryption, and another one \n   for private key storage */\n\n#define TEST_PASSWORD\t\t\tTEXT( \"password\" )\n#define TEST_PRIVKEY_PASSWORD\tTEXT( \"test\" )\n\n/* The database keyset type and name.  Under Windoze we use ODBC, for\n   anything else we use the first database which is enabled by a preprocessor\n   define, defaulting to an internal plugin (which doesn't have to be\n   available, if it's not present we continue after printing a warning) */\n\n#if defined( _MSC_VER )\n  #define DATABASE_KEYSET_TYPE\tCRYPT_KEYSET_ODBC\n  #define CERTSTORE_KEYSET_TYPE\tCRYPT_KEYSET_ODBC_STORE\n#elif defined( DBX_DATABASE )\n  #define DATABASE_KEYSET_TYPE\tCRYPT_KEYSET_DATABASE\n  #define CERTSTORE_KEYSET_TYPE\tCRYPT_KEYSET_DATABASE_STORE\n#elif defined( DBX_PLUGIN )\n  #define DATABASE_KEYSET_TYPE\tCRYPT_KEYSET_PLUGIN\n  #define CERTSTORE_KEYSET_TYPE\tCRYPT_KEYSET_PLUGIN_STORE\n#else\n  #define DATABASE_KEYSET_TYPE\tCRYPT_KEYSET_DATABASE\n  #define CERTSTORE_KEYSET_TYPE\tCRYPT_KEYSET_DATABASE_STORE\n#endif /* Various database backends */\n#define DATABASE_KEYSET_NAME\t\tTEXT( \"testkeys\" )\n#define DATABASE_KEYSET_NAME_ASCII\t\"testkeys\"\n#define CERTSTORE_KEYSET_NAME\t\tTEXT( \"testcertstore\" )\n#define CERTSTORE_KEYSET_NAME_ASCII\t\"testcertstore\"\n#define DATABASE_PLUGIN_KEYSET_NAME\tTEXT( \"localhost:6500\" )\n#define DATABASE_PLUGIN_KEYSET_NAME_ASCII\t\"localhost:6500\"\n\n/* The HTTP keyset names (actually URLs for pages containing a cert and\n   CRL).  We can't get either Verisign or Thawte root certs because both\n   require you to provide all sorts of personal information and click on a\n   legal agreement before you can download them (!!!), so we use the CAcert\n   root instead */\n\n#define HTTP_KEYSET_CERT_NAME\tTEXT( \"www.cacert.org/certs/root.der\" )\n#define HTTP_KEYSET_CRL_NAME\tTEXT( \"crl.verisign.com/Class1Individual.crl\" )\n#define HTTP_KEYSET_HUGECRL_NAME TEXT( \"crl.verisign.com/RSASecureServer.crl\" )\n\n/* Assorted default server names and authentication information, and the PKI\n   SRV server (redirecting to mail.cryptoapps.com:8080).  There are so many\n   TSP, OCSP, and CMP servers, and they never stay around for long, that we\n   allow remapping in the functions where the secure session tests are\n   performed */\n\n#define SSH_USER_NAME\t\t\tTEXT( \"ssh_test_user\" )\n#define SSH_PASSWORD\t\t\tTEXT( \"ssh_test_password\" )\n#define SSL_USER_NAME\t\t\tTEXT( \"ssl_test_user\" )\n#define SSL_PASSWORD\t\t\tTEXT( \"ssl_test_password\" )\n#define PKI_SRV_NAME\t\t\tTEXT( \"_pkiboot._tcp.cryptoapps.com\" )\n#define TSP_DEFAULTSERVER_NAME\tTEXT( \"http://timestamping.edelweb.fr/service/tsp\" )\n\n/* Labels for the various public-key objects.  These are needed when the\n   underlying implementation creates persistent objects (eg keys held in PKCS\n   #11 tokens) that need to be identified */\n\n#define RSA_PUBKEY_LABEL\t\tTEXT( \"Test RSA public key\" )\n#define RSA_PRIVKEY_LABEL\t\tTEXT( \"Test RSA private key\" )\n#define RSA_BIG_PRIVKEY_LABEL\tTEXT( \"Test RSA big private key\" )\n#define DSA_PUBKEY_LABEL\t\tTEXT( \"Test DSA sigcheck key\" )\n#define DSA_PRIVKEY_LABEL\t\tTEXT( \"Test DSA signing key\" )\n#define ELGAMAL_PUBKEY_LABEL\tTEXT( \"Test Elgamal public key\" )\n#define ELGAMAL_PRIVKEY_LABEL\tTEXT( \"Test Elgamal private key\" )\n#define DH_KEY1_LABEL\t\t\tTEXT( \"Test DH key #1\" )\n#define DH_KEY2_LABEL\t\t\tTEXT( \"Test DH key #2\" )\n#define ECDSA_PUBKEY_LABEL\t\tTEXT( \"Test ECDSA sigcheck key\" )\n#define ECDSA_PRIVKEY_LABEL\t\tTEXT( \"Test ECDSA signing key\" )\n#define CA_PRIVKEY_LABEL\t\tTEXT( \"Test RSA private key\" )\n#define USER_PRIVKEY_LABEL\t\tTEXT( \"Test user key\" )\n#define USER_EMAIL\t\t\t\tTEXT( \"dave@wetaburgers.com\" )\n#define DUAL_SIGNKEY_LABEL\t\tTEXT( \"Test signing key\" )\n#define DUAL_ENCRYPTKEY_LABEL\tTEXT( \"Test encryption key\" )\n#define SYMMETRIC_KEY_LABEL\t\tTEXT( \"Test symmetric key\" )\n\n/* The loopback address, used so that we don't inadvertently open up outside \n   ports.  In order to allow testing against non-cryptlib-loopback and/or \n   outside clients we optionally allow it to be set to an explicit address.  \n   This can be either an explicit IPv4 localhost (since Windows 7 will bind \n   to both IPv4 and IPv6 INADDR_ANY addresses when given \"localhost\" as an \n   argument and refuses connections on the IPv4 interface, only connecting \n   on the IPv6 one), or an explicit address for external clients.\n   \n   In addition to the standard loopback address, we allow a URI specifier to\n   enable the use of additional protocols layered over the base protocol */\n\n#ifdef UNICODE_STRINGS\n  #define LOCAL_HOST_NAME\t\t\t\"localhost\"\n  #define NATIVE_LOCAL_HOST_NAME\tL\"localhost\"\n  #define LOCAL_HOST_NAME_LAYERED\t\"wss://localhost\"\n  #define NATIVE_LOCAL_HOST_NAME_LAYERED L\"wss://localhost\"\n#else\n  #define LOCAL_HOST_NAME\t\t\t\"localhost\"\n  #define NATIVE_LOCAL_HOST_NAME\tLOCAL_HOST_NAME\n  #define LOCAL_HOST_NAME_LAYERED\t\"wss://localhost\"\n  #define NATIVE_LOCAL_HOST_NAME_LAYERED LOCAL_HOST_NAME_LAYERED\n#endif /* UNICODE_STRINGS */\n#if 0\n  #undef LOCAL_HOST_NAME\n  #define LOCAL_HOST_NAME\t\t\t\"127.0.0.1\"\n  #define NATIVE_LOCAL_HOST_NAME\tLOCAL_HOST_NAME\n#endif /* 0 */\n#if 0\n  /* Define a fixed IP address, for running test servers */\n  #undef LOCAL_HOST_NAME\n  #define LOCAL_HOST_NAME\t\t\t\"82.94.251.197\"\n  #define NATIVE_LOCAL_HOST_NAME\tLOCAL_HOST_NAME\n  #define LOCAL_PORT_NAME\t\t\t8443\n#endif /* 0 */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in utils.c */\n\n#if defined( UNIX_THREADS ) || defined( WINDOWS_THREADS ) || defined( OS2_THREADS )\n  void delayThread( const int seconds );\n#else\n  #define delayThread( x )\n#endif /* Systems with threading support */\nCRYPT_ALGO_TYPE selectCipher( const CRYPT_ALGO_TYPE algorithm );\nvoid printHex( const char *prefix, const BYTE *value, const int length );\nconst C_STR getKeyfileName( const KEYFILE_TYPE type,\n\t\t\t\t\t\t\tconst BOOLEAN isPrivKey );\nconst C_STR getKeyfilePassword( const KEYFILE_TYPE type );\nconst C_STR getKeyfileUserID( const KEYFILE_TYPE type,\n\t\t\t\t\t\t\t  const BOOLEAN isPrivKey );\nvoid printErrorAttributeInfo( const CRYPT_CERTIFICATE certificate );\nint displayAttributes( const CRYPT_HANDLE cryptHandle );\nint printCertInfo( const CRYPT_CERTIFICATE certificate );\nint printCertChainInfo( const CRYPT_CERTIFICATE certChain );\nvoid printExtError( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\tconst char *functionName, const int functionStatus,\n\t\t\t\t\tconst int lineNo );\nint readFileData( const char *fileName, const char *description,\n\t\t\t\t  BYTE *buffer, const int bufSize, const int minFileSize,\n\t\t\t\t  const BOOLEAN silent );\nint importCertFile( CRYPT_CERTIFICATE *cryptCert, const C_STR fileName );\nint importCertFromTemplate( CRYPT_CERTIFICATE *cryptCert,\n\t\t\t\t\t\t\tconst C_STR fileTemplate, const int number );\nint exportCertFile( const char *fileName, \n\t\t\t\t\tconst CRYPT_CERTIFICATE certificate,\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE formatType );\nint addCertFields( const CRYPT_CERTIFICATE certificate,\n\t\t\t\t   const CERT_DATA *certData, const int lineNo );\nint checkFileAccess( void );\nint checkNetworkAccess( void );\nint checkLibraryIsDebug( void );\nint compareData( const void *origData, const int origDataLength,\n\t\t\t\t const void *recovData, const int recovDataLength );\nint getPublicKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t  const C_STR keyName );\nint getPrivateKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t   const C_STR keyName, const C_STR password );\nvoid debugDump( const char *fileName, const void *data,\n\t\t\t\tconst int dataLength );\nint printConnectInfo( const CRYPT_SESSION cryptSession );\nint printSecurityInfo( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t   const BOOLEAN showFingerprint,\n\t\t\t\t\t   const BOOLEAN showServerKeyInfo,\n\t\t\t\t\t   const BOOLEAN showClientCertInfo );\nint printFingerprint( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t  const BOOLEAN isServer );\nBOOLEAN setLocalConnect( const CRYPT_SESSION cryptSession, const int port );\nBOOLEAN isServerDown( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t  const int errorStatus );\nint activatePersistentServerSession( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t\t\t\t const BOOLEAN showOperationType );\n\n/* Threading support functions, in utils.c */\n\nvoid createMutex( void );\nvoid acquireMutex( void );\nvoid releaseMutex( void );\nint waitMutex( void );\nvoid destroyMutex( void );\n#if defined( WINDOWS_THREADS )\n  void waitForThread( const HANDLE hThread );\n#elif defined( UNIX_THREADS )\n  void waitForThread( const pthread_t hThread );\n#else\n  void waitForThread( const int hThread );\n#endif /* Systems with threading support */\nint multiThreadDispatch( THREAD_FUNC clientFunction,\n\t\t\t\t\t\t THREAD_FUNC serverFunction, const int noThreads );\n\n/* Exit with an error message, in utils.c.  attrErrorExit() prints the\n   locus and type, extErrorExit() prints the extended error code and\n   message */\n\nBOOLEAN attrErrorExit( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   const char *functionName, const int errorCode,\n\t\t\t\t\t   const int lineNumber );\nBOOLEAN extErrorExit( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t  const char *functionName, const int errorCode,\n\t\t\t\t\t  const int lineNumber );\n\n/* Prototypes for functions in certs.c */\n\nBOOLEAN certErrorExit( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   const char *functionName, const int errorCode,\n\t\t\t\t\t   const int lineNumber );\nint setRootTrust( const CRYPT_CERTIFICATE cryptCertChain,\n\t\t\t\t  BOOLEAN *oldTrustValue, const BOOLEAN newTrustValue );\n\n/* Prototypes for functions in lowlvl.c */\n\nBOOLEAN loadDHKey( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t   CRYPT_CONTEXT *cryptContext );\nBOOLEAN loadRSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *decryptContext,\n\t\t\t\t\t\t   const C_STR cryptContextLabel,\n\t\t\t\t\t\t   const C_STR decryptContextLabel,\n\t\t\t\t\t\t   const BOOLEAN useLargeKey,\n\t\t\t\t\t\t   const BOOLEAN useMinimalKey );\nBOOLEAN loadRSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t CRYPT_CONTEXT *decryptContext );\nBOOLEAN loadRSAContextsLarge( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t  CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t  CRYPT_CONTEXT *decryptContext );\nBOOLEAN loadDSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *signContext,\n\t\t\t\t\t\t   const C_STR sigCheckContextLabel,\n\t\t\t\t\t\t   const C_STR signContextLabel );\nBOOLEAN loadDSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t CRYPT_CONTEXT *signContext );\nBOOLEAN loadElgamalContexts( CRYPT_CONTEXT *cryptContext,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *decryptContext );\nBOOLEAN loadDHContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\tCRYPT_CONTEXT *cryptContext1,\n\t\t\t\t\t\tCRYPT_CONTEXT *cryptContext2 );\nBOOLEAN loadECDSAContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t   CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t   CRYPT_CONTEXT *signContext );\nBOOLEAN loadECDSAContextsEx( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *sigCheckContext,\n\t\t\t\t\t\t\t CRYPT_CONTEXT *signContext,\n\t\t\t\t\t\t\t const C_STR sigCheckContextLabel,\n\t\t\t\t\t\t\t const C_STR signContextLabel );\nvoid destroyContexts( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t\t  const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t  const CRYPT_CONTEXT decryptContext );\nint testLowlevel( const CRYPT_DEVICE cryptDevice,\n\t\t\t\t  const CRYPT_ALGO_TYPE cryptAlgo,\n\t\t\t\t  const BOOLEAN checkOnly );\nint testCrypt( const CRYPT_CONTEXT cryptContext, \n\t\t\t   const CRYPT_CONTEXT decryptContext,\n\t\t\t   const CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer, \n\t\t\t   const BOOLEAN isDevice, const BOOLEAN noWarnFail );\nint testRSAMinimalKey( void );\n\n/* Prototypes for functions in envelope.c */\n\nint testEnvelopePKCCryptEx( const CRYPT_CONTEXT cryptContext, \n\t\t\t\t\t\t\tconst CRYPT_HANDLE decryptKeyset );\nint testCMSEnvelopeSignEx( const CRYPT_CONTEXT signContext );\nint testCMSEnvelopePKCCryptEx( const CRYPT_HANDLE encryptContext,\n\t\t\t\t\t\t\t   const CRYPT_HANDLE decryptKeyset,\n\t\t\t\t\t\t\t   const C_STR password, const C_STR recipient );\n\n/* Prototypes for functions in sreqresp.c */\n\nint testSessionTSPServerEx( const CRYPT_CONTEXT privKeyContext );\n\n/* Prototypes for functions in s_scep.c */\n\nint pkiGetUserInfo( C_STR userID, C_STR issuePW, C_STR revPW, \n\t\t\t\t\tconst C_STR userName );\nint pkiServerInit( CRYPT_CONTEXT *cryptPrivateKey, \n\t\t\t\t   CRYPT_KEYSET *cryptCertStore, const C_STR keyFileName,\n\t\t\t\t   const C_STR keyLabel, const CERT_DATA *pkiUserData,\n\t\t\t\t   const CERT_DATA *pkiUserAltData, \n\t\t\t\t   const CERT_DATA *pkiUserCAData, \n\t\t\t\t   const CERT_DATA *pkiUserRAData, \n\t\t\t\t   const char *protocolName );\n\n/* Prototypes for functions in testfunc.c */\n\nvoid checkCreateDatabaseKeysets( void );\n\n/* Prototypes for functions in eap.c */\n\nint createTTLSAVPMSCHAPv2( BYTE *ttlsAVP, int *ttlsAVPlength,\n\t\t\t\t\t\t   const void *userName, const int userNameLength,\n\t\t\t\t\t\t   const void *password, const int passwordLength,\n\t\t\t\t\t\t   const void *eapChallenge );\n\n/* Function used for testing, in cryptapi.c */\n\n#ifndef NDEBUG\n\nC_RET cryptSetFaultType( C_IN int type );\nC_RET cryptSetMemFaultCount( C_IN int number );\nC_RET cryptDelayRandom( C_IN CRYPT_CONTEXT signContext,\n\t\t\t\t\t\tC_IN CRYPT_CONTEXT hashContext );\nC_RET cryptFuzzInit( C_IN CRYPT_SESSION cryptSession,\n\t\t\t\t\t C_IN CRYPT_CONTEXT cryptContext ); \nC_RET cryptSetFuzzData( C_IN CRYPT_SESSION cryptSession, \n\t\t\t\t\t\tC_IN void *data, C_IN int dataLength,\n\t\t\t\t\t\tC_IN CRYPT_SUBPROTOCOL_TYPE subProtocolType );\nC_RET cryptFuzzSpecial( C_IN CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\tC_IN void *data, C_IN int dataLength,\n\t\t\t\t\t\tC_IN int isServer );\n#endif /* NDEBUG */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTiming Support\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Since high-precision timing is rather OS-dependent, we only enable this\n   under Windows or Unix where we've got guaranteed high-res timer access */\n\n#if ( defined( __WINDOWS__ ) && defined( _MSC_VER ) ) || \\\n\t( defined( __UNIX__ ) && defined( __GNUC__ ) )\n\n#define USE_TIMING\n\n/* Normally we use 32-bit time values, however there's also (partial)\n   support for 64-bit signed values on systems that support this.  This\n   isn't normally needed though because timeDiff() deals with overflow/\n   wraparound */\n\n#define USE_32BIT_TIME\n\n#if defined( USE_32BIT_TIME )\n  typedef unsigned long HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%lX\"\n#elif defined( _MSC_VER )\n  typedef __int64 HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%llX\"\n#elif defined( __GNUC__ )\n  typedef long long HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%llX\"\n#else\n  typedef unsigned long HIRES_TIME;\n  #define HIRES_FORMAT_SPECIFIER\t\"%lX\"\n#endif /* 32/64-bit time values */\n\n/* Timing support functions.  Call as:\n\n\tHIRES_TIME timeVal;\n\n\ttimeVal = timeDiff( 0 );\n\tfunction_to_time();\n\tresult = ( int ) timeDiff( timeVal ); */\n\nHIRES_TIME timeDiff( HIRES_TIME startTime );\nint timeDisplay( HIRES_TIME time );\nint testTimingAttackConv( void );\nint testTimingAttackPKC( void );\n\n#endif /* Windows with MSVC or Unix with gcc */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Prototypes for functions in highlvl.c */\n\nint testLargeBufferEncrypt( void );\nint testDeriveKey( void );\nint testRandomRoutines( void );\nint testConventionalExportImport( void );\nint testMACExportImport( void );\nint testKeyExportImport( void );\nint testSignData( void );\nint testKeygen( void );\nint testKeyExportImportCMS( void );\nint testSignDataCMS( void );\nint testMidLevelDebugCheck( void );\n\n/* Prototypes for functions in devices.c */\n\nint testDevices( void );\nint testUser( void );\n\n/* Prototypes for functions in keyfile.c */\n\nint testGetPGPPublicKey( void );\nint testGetPGPPrivateKey( void );\nint testReadWriteFileKey( void );\nint testReadWriteAltFileKey( void );\nint testReadWritePGPFileKey( void );\nint testImportFileKey( void );\nint testReadFilePublicKey( void );\nint testAddTrustedCert( void );\nint testAddGloballyTrustedCert( void );\nint testDeleteFileKey( void );\nint testChangeFileKeyPassword( void );\nint testUpdateFileCert( void );\nint testWriteFileCertChain( void );\nint testWriteFileLongCertChain( void );\nint testReadFileCert( void );\nint testReadFileCertPrivkey( void );\nint testReadFileCertChain( void );\nint testReadCorruptedKey( void );\nint testSingleStepFileCert( void );\nint testSingleStepAltFileCert( void );\nint testDoubleCertFile( void );\nint testRenewedCertFile( void );\nint testReadWriteAltFileCert( void );\nint testReadAltFileKey( void );\nint testReadMiscFile( void );\n\n/* Prototypes for functions in keydbx.c */\n\nint testWriteCert( void );\nint testReadCert( void );\nint testKeysetQuery( void );\nint testWriteCertDbx( void );\nint testWriteCertLDAP( void );\nint testReadCertLDAP( void );\nint testReadCertURL( void );\nint testReadCertHTTP( void );\n\n/* Prototypes for functions in envelope.c */\n\nint testEnvelopeData( void );\nint testEnvelopeDataLargeBuffer( void );\nint testEnvelopeDataVariable( void );\nint testEnvelopeDataMultiple( void );\nint testEnvelopeCompress( void );\nint testPGPEnvelopeCompressedDataImport( void );\nint testEnvelopeSessionCrypt( void );\nint testEnvelopeSessionCryptLargeBuffer( void );\nint testEnvelopeSessionCryptVariable( void );\nint testEnvelopeSessionCryptMultiple( void );\nint testEnvelopeCrypt( void );\nint testEnvelopePasswordCrypt( void );\nint testEnvelopePasswordCryptBoundary( void );\nint testEnvelopePasswordCryptImport( void );\nint testPGPEnvelopePasswordCryptImport( void );\nint testEnvelopePKCCrypt( void );\nint testEnvelopePKCCryptAlgo( void );\nint testEnvelopePKCCryptMulti( void );\nint testEnvelopePKCIterated( void );\nint testPGPEnvelopePKCCryptImport( void );\nint testEnvelopeSign( void );\nint testEnvelopeSignAlgos( void );\nint testEnvelopeSignHashUpgrade( void );\nint testEnvelopeSignOverflow( void );\nint testEnvelopeSignIndef( void );\nint testPGPEnvelopeSignedDataImport( void );\nint testEnvelopeAuthenticate( void );\nint testEnvelopeAuthEnc( void );\nint testCMSEnvelopePKCCrypt( void );\nint testCMSEnvelopePKCCryptDoubleCert( void );\nint testCMSEnvelopePKCCryptImport( void );\nint testCMSEnvelopeSign( void );\nint testCMSEnvelopeDualSign( void );\nint testCMSEnvelopeDetachedSig( void );\nint testPGPEnvelopeDetachedSig( void );\nint testCMSEnvelopeRefCount( void );\nint testCMSEnvelopeSignedDataImport( void );\nint testEnvelopeCMSDebugCheck( void );\nint testEnvelopePGPDebugCheck( void );\n\n/* Prototypes for functions in certs.c */\n\nint testBasicCert( void );\nint testCACert( void );\nint testXyzzyCert( void );\nint testTextStringCert( void );\nint testComplexCert( void );\nint testAltnameCert( void );\nint testCertExtension( void );\nint testCustomDNCert( void );\nint testCertAttributeHandling( void );\nint testSETCert( void );\nint testAttributeCert( void );\nint testCRL( void );\nint testComplexCRL( void );\nint testCertChain( void );\nint testCAConstraints( void );\nint testCertRequest( void );\nint testCertRequestAttrib( void );\nint testComplexCertRequest( void );\nint testCRMFRequest( void );\nint testComplexCRMFRequest( void );\nint testRevRequest( void );\nint testCMSAttributes( void );\nint testRTCSReqResp( void );\nint testOCSPReqResp( void );\nint testPKIUser( void );\nint testCertImport( void );\nint testCertImportECC( void );\nint testCertReqImport( void );\nint testCRLImport( void );\nint testCertChainImport( void );\nint testOCSPImport( void );\nint testBase64CertImport( void );\nint testBase64CertChainImport( void );\nint testMiscImport( void );\nint testNonchainCert( void );\nint testCertComplianceLevel( void );\nint testCertChainHandling( void );\nint testPathProcessing( void );\nint testPKCS1Padding( void );\nint testCertProcess( void );\nint testCertManagement( void );\n\n/* Prototypes for functions in scert.c (the EnvTSP one is actually in with\n   the enveloping code because the only way to fully exercise the TS\n   functionality is by using it to timestamp an S/MIME signature) */\n\nint testSessionSCEP( void );\nint testSessionSCEPCACert( void );\nint testSessionSCEPServer( void );\nint testSessionCMP( void );\nint testSessionCMPServer( void );\nint testSessionPNPPKI( void );\nint testSessionEnvTSP( void );\n\n/* Prototypes for functions in sreqresp.c */\n\nint testSessionHTTPCertstoreServer( void );\nint testSessionRTCS( void );\nint testSessionRTCSServer( void );\nint testSessionOCSP( void );\nint testSessionOCSPServer( void );\nint testSessionTSP( void );\nint testSessionTSPServer( void );\n\n/* Prototypes for functions in ssh.c */\n\nint testSessionUrlParse( void );\nint testSessionAttributes( void );\nint testSessionSSH( void );\nint testSessionSSHPubkeyAuth( void );\nint testSessionSSHPubkeyAuthWrongKey( void );\nint testSessionSSHPubkeyAuthWrongName( void );\nint testSessionSSHClientServerPubkeyAuthPassword( void );\nint testSessionSSHPortforward( void );\nint testSessionSSHExec( void );\nint testSessionSSH_SFTP( void );\nint testSessionSSHServer( void );\nint testSessionSSHServerPubkeyAuth( void );\nint testSessionSSH_SFTPServer( void );\n\n/* Prototypes for functions in ssl.c */\n\nint testSessionSSL( void );\nint testSessionSSLLocalSocket( void );\nint testSessionSSLClientCert( void );\nint testSessionSSLServer( void );\nint testSessionSSLServerCached( void );\nint testSessionSSLServerClientCert( void );\nint testSessionTLS( void );\nint testSessionTLSLocalSocket( void );\nint testSessionTLSSharedKey( void );\nint testSessionTLSServer( void );\nint testSessionTLSServerSharedKey( void );\nint testSessionTLSEAPTTLS( void );\nint testSessionTLS11( void );\nint testSessionTLS11Server( void );\nint testSessionTLS12( void );\nint testSessionTLSBadSSL( void );\nint testSessionTLS12Server( void );\nint testSessionTLS12ClientCert( void );\nint testSessionTLS12ServerClientCertManual( void );\nint testSessionTLS12WebSockets( void );\nint testSessionTLS12WebSocketsServer( void );\nint testSessionTLS12EAPTTLS( void );\nint testSessionTLS12EAPTTLSServer( void );\n\n/* Functions to test local client/server sessions.  These require threading\n   support since they run the client and server in different threads */\n\n#ifdef TEST_SESSION_LOOPBACK\n  int testSessionSSHClientServer( void );\n  int testSessionSSHClientServerDsaKey( void );\n  int testSessionSSHClientServerEccKey( void );\n  int testSessionSSHClientServerFingerprint( void );\n  int testSessionSSHClientServerPubkeyAuth( void );\n  int testSessionSSHClientServerPubkeyAuthWrongKey( void );\n  int testSessionSSHClientServerPubkeyAuthWrongName( void );\n  int testSessionSSHClientServerSFTP( void );\n  int testSessionSSHClientServerPortForward( void );\n  int testSessionSSHClientServerExec( void );\n  int testSessionSSHClientServerMultichannel( void );\n  int testSessionSSHClientServerDualThread( void );\n  int testSessionSSHClientServerMultiThread( void );\n  int testSessionSSHClientServerDebugCheck( void );\n  int testSessionSSLClientServer( void );\n  int testSessionSSLClientCertClientServer( void );\n  int testSessionTLSClientServer( void );\n  int testSessionTLSSharedKeyClientServer( void );\n  int testSessionTLSNoSharedKeyClientServer( void );\n  int testSessionTLSBulkTransferClientServer( void );\n  int testSessionTLSLocalServerSocketClientServer( void );\n  int testSessionTLS11ClientServer( void );\n  int testSessionTLS11ClientCertClientServer( void );\n  int testSessionTLS11ResumeClientServer( void );\n  int testSessionTLS12ClientServer( void );\n  int testSessionTLS12ClientServerEccKey( void );\n  int testSessionTLS12ClientServerEcc384Key( void );\n  int testSessionTLS12ClientCertClientServer( void );\n  int testSessionTLS12ClientCertManualClientServer( void );\n  int testSessionTLS12WebSocketsClientServer( void );\n  int testSessionTLSClientServerDualThread( void );\n  int testSessionTLSClientServerMultiThread( void );\n  int testSessionSSLClientServerDebugCheck( void );\n  int testSessionHTTPCertstoreClientServer( void );\n  int testSessionRTCSClientServer( void );\n  int testSessionOCSPClientServer( void );\n  int testSessionOCSPMulticertClientServer( void );\n  int testSessionTSPClientServer( void );\n  int testSessionTSPClientServerPersistent( void );\n  int testSessionSCEPClientServer( void );\n  int testSessionSCEPAltAlgoClientServer( void );\n  int testSessionSCEPCustomExtClientServer( void );\n  int testSessionSCEPSHA2ClientServer( void );\n  int testSessionSCEPCACertClientServer( void );\n  int testSessionSCEPRenewClientServer( void );\n  int testSessionSCEPClientServerDebugCheck( void );\n  int testSessionCMPClientServer( void );\n  int testSessionCMPAltAlgoClientServer( void );\n  int testSessionCMPSHA2ClientServer( void );\n  int testSessionCMPPKIBootClientServer( void );\n  int testSessionCMPRAClientServer( void );\n  int testSessionCMPFailClientServer( void );\n  int testSessionPNPPKIClientServer( void );\n  int testSessionPNPPKIDeviceClientServer( void );\n  int testSessionPNPPKICAClientServer( void );\n  int testSessionPNPPKIIntermedCAClientServer( void );\n  int testSessionCMPClientServerDebugCheck( void );\n  int testSessionSuiteBClientServer( void );\n#endif /* TEST_SESSION_LOOPBACK */\n\n/* Umbrella tests for the above functions */\n\nBOOLEAN testSelfTest( void );\nBOOLEAN testLowLevel( void );\nBOOLEAN testRandom( void );\nBOOLEAN testConfig( void );\nBOOLEAN testDevice( void );\nBOOLEAN testMidLevel( void );\nBOOLEAN testHighLevel( void );\nBOOLEAN testCert( void );\nBOOLEAN testCertMgmt( void );\nBOOLEAN testKeysetFile( void );\nBOOLEAN testKeysetDatabase( void );\nBOOLEAN testEnveloping( void );\nBOOLEAN testSessions( void );\nBOOLEAN testSessionsLoopback( void );\nBOOLEAN testUsers( void );\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( resume )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 819 )\n#endif /* IBM medium iron */\n"
  },
  {
    "path": "deps/cl345/test/testfunc.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tcryptlib Test Code\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2016\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The tests that use databases and certificate stores require that the user \n   set up a suitable ODBC data source (at least when running under Windows), \n   to automate this process we try and create the data source if it isn't \n   present.\n   \n   This is complicated by the fact that the universal default MSJET database \n   driver doesn't have a 64-bit version so it's not possible to use it under \n   Vista/Windows 7 x64.  To work around this we fall back to the SQL Server\n   driver, which replaces MSJET on x64 systems */\n\n#if defined( _MSC_VER ) && defined( _WIN32 ) && !defined( _WIN32_WCE )\n\n#define DATABASE_AUTOCONFIG\n\n#include <odbcinst.h>\n\n/* Default MS Access database */\n\n#define DRIVER_NAME\t\t\t\tTEXT( \"Microsoft Access Driver (*.MDB)\" )\n#define DATABASE_ATTR_NAME\t\t\"DSN=\" DATABASE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\"DBQ=\"\n#define DATABASE_ATTR_CREATE\t\"DSN=\" DATABASE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\"CREATE_DB=\"\n#define DATABASE_ATTR_TAIL\t\tDATABASE_KEYSET_NAME_ASCII \".mdb#\"\n#define CERTSTORE_ATTR_NAME\t\t\"DSN=\" CERTSTORE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\"DBQ=\"\n#define CERTSTORE_ATTR_CREATE\t\"DSN=\" CERTSTORE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\"CREATE_DB=\"\n#define CERTSTORE_ATTR_TAIL\t\tCERTSTORE_KEYSET_NAME_ASCII \".mdb#\"\n\n/* Alternative 1, SQL Server */\n\n#define DRIVER_NAME_ALT_1\t\t\tTEXT( \"SQL Server\" )\n#define DATABASE_ATTR_NAME_ALT_1\t\"DSN=\" DATABASE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\t\"Server=localhost#\" \\\n\t\t\t\t\t\t\t\t\t\"Database=\"\n#define DATABASE_ATTR_CREATE_ALT_1\t\"\"\n#define DATABASE_ATTR_TAIL_ALT_1\tDATABASE_KEYSET_NAME_ASCII \"#\"\n#define CERTSTORE_ATTR_NAME_ALT_1\t\"DSN=\" CERTSTORE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\t\"Server=localhost#\" \\\n\t\t\t\t\t\t\t\t\t\"Database=\"\n#define CERTSTORE_ATTR_CREATE_ALT_1\t\"\"\n#define CERTSTORE_ATTR_TAIL_ALT_1\tCERTSTORE_KEYSET_NAME_ASCII \"#\"\n\n/* Alternative 2, SQLite */\n\n#define DRIVER_NAME_ALT_2\t\t\tTEXT( \"SQLite3 ODBC Driver\" )\n#define DATABASE_ATTR_NAME_ALT_2\t\"DSN=\" DATABASE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\t\"Database=\"\n#define DATABASE_ATTR_CREATE_ALT_2\t\"\"\n#define DATABASE_ATTR_TAIL_ALT_2\tDATABASE_KEYSET_NAME_ASCII \"#\"\n#define CERTSTORE_ATTR_NAME_ALT_2\t\"DSN=\" CERTSTORE_KEYSET_NAME_ASCII \"#\" \\\n\t\t\t\t\t\t\t\t\t\"DESCRIPTION=cryptlib test key database#\" \\\n\t\t\t\t\t\t\t\t\t\"Database=\"\n#define CERTSTORE_ATTR_CREATE_ALT_2\t\"\"\n#define CERTSTORE_ATTR_TAIL_ALT_2\tCERTSTORE_KEYSET_NAME_ASCII \"#\"\n\ntypedef enum { ODBC_SOURCE_ACCESS, ODBC_SOURCE_SQLSERVER, \n\t\t\t   ODBC_SOURCE_SQLITE } ODBC_SOURCE_TYPE;\n\nstatic void buildDBString( char *buffer, const char *attrName,\n\t\t\t\t\t\t   const char *attrTail, const char *path )\n\t{\n\tconst int attrNameSize = strlen( attrName );\n\tconst int attrTailSize = strlen( attrTail ) + 1;\n\tconst int pathSize = strlen( path );\n\tint dbStringLen, i;\n\n\t/* Build up the data-source control string */\n\tmemcpy( buffer, attrName, attrNameSize + 1 );\n\tmemcpy( buffer + attrNameSize, path, pathSize );\n\tif( attrTailSize > 0 )\n\t\t{\n\t\tmemcpy( buffer + attrNameSize + pathSize, attrTail, \n\t\t\t\tattrTailSize );\n\t\t}\n\tbuffer[ attrNameSize + pathSize + attrTailSize ] = '\\0';\n\n\t/* Finally, convert the strings to the weird embedded-null strings \n\t   required by SQLConfigDataSource() */\n\tdbStringLen = strlen( buffer );\n\tfor( i = 0; i < dbStringLen; i++ )\n\t\t{\n\t\tif( buffer[ i ] == '#' )\n\t\t\tbuffer[ i ] = '\\0';\n\t\t}\n\t}\n\nstatic void reportSqlError( const ODBC_SOURCE_TYPE sourceType )\n\t{\n\tDWORD dwErrorCode;\n\tWORD errorMessageLen;\n\tchar errorMessage[ 256 ];\n\t\t\n\tif( SQLInstallerError( 1, &dwErrorCode, errorMessage, 256, \n\t\t\t\t\t\t   &errorMessageLen ) != SQL_NO_DATA )\n\t\t{\n\t\tprintf( \"SQLConfigDataSource() returned error code %d,\\n  \"\n\t\t\t\t\"message '%s'.\\n\", dwErrorCode, errorMessage );\n#if defined( _M_X64 )\n\t\tif( sourceType == ODBC_SOURCE_ACCESS )\n\t\t\t{\n\t\t\tputs( \"  (This is probably because there's no appropriate \"\n\t\t\t\t  \"64-bit driver present,\\n  retrying the create with \"\n\t\t\t\t  \"an alternative driver...).\" );\n\t\t\t}\n#endif /* _M_X64 */\n\t\t}\n\telse\n\t\t{\n\t\tputs( \"SQLConfigDataSource() failed, no additional information \"\n\t\t\t  \"available\" );\n\t\t}\n\t}\n\nstatic BOOLEAN createDatabase( const char *driverName,\n\t\t\t\t\t\t\t   const char *keysetName, \n\t\t\t\t\t\t\t   const char *nameString, \n\t\t\t\t\t\t\t   const char *createString, \n\t\t\t\t\t\t\t   const char *trailerString,\n\t\t\t\t\t\t\t   const ODBC_SOURCE_TYPE sourceType )\n\t{\n\tchar tempPathBuffer[ 512 ];\n\tchar attrBuffer[ 1024 ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcAttrBuffer[ 1024 ];\n#endif /* UNICODE_STRINGS */\n\tint status;\n\n\tif( !GetTempPath( 512, tempPathBuffer ) )\n\t\tstrcpy( tempPathBuffer, \"C:\\\\Temp\\\\\" );\n\n\t/* Try and create the DSN.  For the default Access driver his is a two-\n\t   step process, first we create the DSN and then the underlying file \n\t   that contains the database.  For SQL Server it's simpler, the database\n\t   server already exists so all we have to do is create the database */\n\tswitch( sourceType )\n\t\t{\n\t\tcase ODBC_SOURCE_ACCESS:\n\t\t\tprintf( \"Database keyset '%s' not found, attempting to create\\n  \"\n\t\t\t\t\t\"data source (ODBC - MS Access)...\\n\", keysetName );\n\t\t\tbreak;\n\n\t\tcase ODBC_SOURCE_SQLSERVER:\n\t\t\tprintf( \"Attempting to create keyset '%s' using alternative\\n  \"\n\t\t\t\t\t\"data source (ODBC - SQL Server)...\\n\", keysetName );\n\t\t\tputs( \"  (Autoconfiguration of SQL Server data sources rather than \"\n\t\t\t\t  \"having them\\n  configured manually by an administrator can \"\n\t\t\t\t  \"be erratic, if cryptlib\\n  hangs while trying to access the \"\n\t\t\t\t  \"certificate database then you need to\\n  configure the SQL \"\n\t\t\t\t  \"Server data source manually).\" );\n\t\t\tbreak;\n\n\t\tcase ODBC_SOURCE_SQLITE:\n\t\t\tprintf( \"Database keyset '%s' not found, attempting to create\\n  \"\n\t\t\t\t\t\"data source (ODBC - SQLite)...\\n\", keysetName );\n\t\t\tbreak;\n\t\t}\n\tbuildDBString( attrBuffer, nameString, trailerString, tempPathBuffer );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcAttrBuffer, attrBuffer, strlen( attrBuffer ) + 1 );\n\tstatus = SQLConfigDataSource( NULL, ODBC_ADD_DSN, driverName, \n\t\t\t\t\t\t\t\t  wcAttrBuffer );\n#else\n\tstatus = SQLConfigDataSource( NULL, ODBC_ADD_DSN, driverName, \n\t\t\t\t\t\t\t\t  attrBuffer );\n#endif /* UNICODE_STRINGS */\n\tif( status != 1 )\n\t\t{\n\t\treportSqlError( sourceType );\n\t\treturn( FALSE );\n\t\t}\n\tif( sourceType != ODBC_SOURCE_ACCESS )\n\t\t{\n\t\t/* The server already exists and we're done */\n\t\treturn( TRUE );\n\t\t}\n\tbuildDBString( attrBuffer, createString, trailerString, tempPathBuffer );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcAttrBuffer, attrBuffer, strlen( attrBuffer ) + 1 );\n\tstatus = SQLConfigDataSource( NULL, ODBC_ADD_DSN, driverName, \n\t\t\t\t\t\t\t\t  wcAttrBuffer );\n#else\n\tstatus = SQLConfigDataSource( NULL, ODBC_ADD_DSN, driverName, \n\t\t\t\t\t\t\t\t  attrBuffer );\n#endif /* UNICODE_STRINGS */\n\tif( status != 1 )\n\t\t{\n\t\treportSqlError( sourceType );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nstatic void checkCreateDatabaseKeyset( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* Check whether the test certificate database can be opened.  This can \n\t   return a CRYPT_ARGERROR_PARAM3 as a normal condition since a freshly-\n\t   created database is empty and therefore can't be identified as a \n\t   certificate database until data is written to it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_KEYSET_ODBC, DATABASE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn;\n\t\t}\n\tif( status != CRYPT_ERROR_OPEN )\n\t\treturn;\n\n\t/* Create the database keyset */\n\tstatus = createDatabase( DRIVER_NAME, DATABASE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t DATABASE_ATTR_NAME, DATABASE_ATTR_CREATE, \n\t\t\t\t\t\t\t DATABASE_ATTR_TAIL, ODBC_SOURCE_ACCESS );\n\tif( status == FALSE )\n\t\t{\n\t\t/* The create with the default MS Access driver failed, fall back to \n\t\t   the SQL Server alternative */\n\t\tstatus = createDatabase( DRIVER_NAME_ALT_1, \n\t\t\t\t\t\t\t\t DATABASE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t\t DATABASE_ATTR_NAME_ALT_1, \n\t\t\t\t\t\t\t\t DATABASE_ATTR_CREATE_ALT_1, \n\t\t\t\t\t\t\t\t DATABASE_ATTR_TAIL_ALT_1, \n\t\t\t\t\t\t\t\t ODBC_SOURCE_SQLITE );\n\t\t}\n\tif( status == FALSE )\n\t\t{\n\t\t/* The create failed as well, try SQLite */\n\t\tstatus = createDatabase( DRIVER_NAME_ALT_2, \n\t\t\t\t\t\t\t\t DATABASE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t\t DATABASE_ATTR_NAME_ALT_2,\n\t\t\t\t\t\t\t\t DATABASE_ATTR_CREATE_ALT_2,\n\t\t\t\t\t\t\t\t DATABASE_ATTR_TAIL_ALT_2, \n\t\t\t\t\t\t\t\t ODBC_SOURCE_SQLSERVER );\n\t\t}\n\tputs( ( status == TRUE ) ? \"Data source creation succeeded.\" : \\\n\t\t  \"Data source creation failed.\\n\\nYou need to create the \"\n\t\t  \"keyset data source as described in the cryptlib manual\\n\"\n\t\t  \"for the database keyset tests to run.\" );\n\t}\n\nstatic void checkCreateDatabaseCertstore( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* Check whether the test certificate store database can be opened.  \n\t   This can return a CRYPT_ARGERROR_PARAM3 as a normal condition since a \n\t   freshly-created database is empty and therefore can't be identified \n\t   as a certificate store until data is written to it */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_KEYSET_ODBC_STORE, CERTSTORE_KEYSET_NAME,\n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn;\n\t\t}\n\tif( status != CRYPT_ERROR_OPEN )\n\t\treturn;\n\n\t/* Create the database keyset */\n\tstatus = createDatabase( DRIVER_NAME, CERTSTORE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t CERTSTORE_ATTR_NAME, CERTSTORE_ATTR_CREATE, \n\t\t\t\t\t\t\t CERTSTORE_ATTR_TAIL, FALSE );\n\tif( status == FALSE )\n\t\t{\n\t\t/* The create with the default MS Access driver failed, fall back to\n\t\t   the SQL Server alternative */\n\t\tstatus = createDatabase( DRIVER_NAME_ALT_1, CERTSTORE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_NAME_ALT_1, \n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_CREATE_ALT_1, \n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_TAIL_ALT_1, TRUE );\n\t\t}\n\tif( status == FALSE )\n\t\t{\n\t\t/* The create failed as well, try SQLite */\n\t\tstatus = createDatabase( DRIVER_NAME_ALT_2, CERTSTORE_KEYSET_NAME_ASCII,\n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_NAME_ALT_2,\n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_CREATE_ALT_2,\n\t\t\t\t\t\t\t\t CERTSTORE_ATTR_TAIL_ALT_2, TRUE );\n\t\t}\n\tputs( ( status == TRUE ) ? \"Data source creation succeeded.\\n\" : \\\n\t\t  \"Data source creation failed.\\n\\nYou need to create the \"\n\t\t  \"certificate store data source as described in the\\n\"\n\t\t  \"cryptlib manual for the certificate management tests to \"\n\t\t  \"run.\\n\" );\n\t}\n\nvoid checkCreateDatabaseKeysets( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* Create the databases */\n\tcheckCreateDatabaseKeyset();\n\tcheckCreateDatabaseCertstore();\n\n\t/* Create the keysets within the database */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t  DATABASE_KEYSET_TYPE, DATABASE_KEYSET_NAME, \n\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"Database keyset created within database '%s'.\\n\", \n\t\t\t\tDATABASE_KEYSET_NAME );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tprintf( \"Error %d creating keyset within '%s' database.\\n\", status, \n\t\t\t\t\tDATABASE_KEYSET_NAME );\n\t\t\t}\n\t\t}\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, \n\t\t\t\t\t\t\t  CERTSTORE_KEYSET_TYPE, CERTSTORE_KEYSET_NAME, \n\t\t\t\t\t\t\t  CRYPT_KEYOPT_CREATE );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tprintf( \"Certificate store keyset created within database '%s'.\\n\",\n\t\t\t\tCERTSTORE_KEYSET_NAME );\n\t\tcryptKeysetClose( cryptKeyset );\n\t\t}\n\telse\n\t\t{\n\t\tif( status != CRYPT_ERROR_DUPLICATE )\n\t\t\t{\n\t\t\tprintf( \"Error %d creating keyset within '%s' database.\\n\", status, \n\t\t\t\t\tCERTSTORE_KEYSET_NAME );\n\t\t\t}\n\t\t}\n\tputchar( '\\n' );\n\t}\n\n/* External-access function for situations where a database keyset is \n   needed, for example the PKI session tests */\n\nvoid initDatabaseKeysets( void )\n\t{\n\t/* Create the certificate store database if required */\n\tcheckCreateDatabaseCertstore();\n\t}\n#endif /* Win32 with VC++ */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTest Low-level Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_SELFTEST\n\n/* Test the cryptlib self-test routines */\n\nBOOLEAN testSelfTest( void )\n\t{\n\tint value, status;\n\n\t/* Perform the self-test.  First we write the value to true to force a\n\t   self-test, then we read it back to see whether it succeeded */\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_SELFTESTOK, \n\t\t\t\t\t\t\t\tTRUE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Attempt to perform cryptlib algorithm \"\n\t\t\t\t \"self-test failed with error code %d, line %d.\\n\", status, \n\t\t\t\t __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_SELFTESTOK, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) || value != TRUE )\n\t\t{\n\t\t/* Unfortunately all that we can report at this point is that the\n\t\t   self-test failed, we can't try each algorithm individually\n\t\t   because the self-test has disabled the failed one(s) */\n\t\tfprintf( outputStream, \"cryptlib algorithm self-test failed, line \"\n\t\t\t\t \"%d.\\n\", __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfputs( \"cryptlib algorithm self-test succeeded.\\n\\n\", outputStream );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testSelfTest( void )\n\t{\n\tfputs( \"Skipping test of self-test routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_SELFTEST */\n\n#ifdef TEST_LOWLEVEL\n\n/* Test the low-level encryption routines */\n\nBOOLEAN testLowLevel( void )\n\t{\n\tCRYPT_ALGO_TYPE cryptAlgo;\n\tBOOLEAN algosEnabled;\n\n\t/* Test the conventional encryption routines */\n\talgosEnabled = FALSE;\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_CONVENTIONAL;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, NULL ) ) )\n\t\t\t{\n\t\t\tif( !testLowlevel( CRYPT_UNUSED, cryptAlgo, FALSE ) )\n\t\t\t\treturn( FALSE );\n\t\t\talgosEnabled = TRUE;\n\t\t\t}\n\t\t}\n\tif( !algosEnabled )\n\t\tputs( \"(No conventional-encryption algorithms enabled).\" );\n\n\t/* Test the public-key encryption routines */\n\talgosEnabled = FALSE;\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_PKC;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_PKC; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, NULL ) ) )\n\t\t\t{\n\t\t\tif( !testLowlevel( CRYPT_UNUSED, cryptAlgo, FALSE ) )\n\t\t\t\treturn( FALSE );\n\t\t\talgosEnabled = TRUE;\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_RSA, NULL ) ) && \\\n\t\t!testRSAMinimalKey() )\n\t\treturn( FALSE );\n\tif( !algosEnabled )\n\t\tputs( \"(No public-key algorithms enabled).\" );\n\n\t/* Test the hash routines */\n\talgosEnabled = FALSE;\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_HASH;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_HASH; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, NULL ) ) )\n\t\t\t{\n\t\t\tif( !testLowlevel( CRYPT_UNUSED, cryptAlgo, FALSE ) )\n\t\t\t\treturn( FALSE );\n\t\t\talgosEnabled = TRUE;\n\t\t\t}\n\t\t}\n\tif( !algosEnabled )\n\t\tputs( \"(No hash algorithms enabled).\" );\n\n\t/* Test the MAC routines */\n\talgosEnabled = FALSE;\n\tfor( cryptAlgo = CRYPT_ALGO_FIRST_MAC;\n\t\t cryptAlgo <= CRYPT_ALGO_LAST_MAC; cryptAlgo++ )\n\t\t{\n\t\tif( cryptStatusOK( cryptQueryCapability( cryptAlgo, NULL ) ) )\n\t\t\t{\n\t\t\tif( !testLowlevel( CRYPT_UNUSED, cryptAlgo, FALSE ) )\n\t\t\t\treturn( FALSE );\n\t\t\talgosEnabled = TRUE;\n\t\t\t}\n\t\t}\n\tif( !algosEnabled )\n\t\tputs( \"(No MAC algorithms enabled).\" );\n\tprintf( \"\\n\" );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testLowLevel( void )\n\t{\n\tfputs( \"Skipping test of low-level encryption routines...\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_LOWLEVEL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tTest Randomness, Config, and Device Functions\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_RANDOM\n\n/* Test the randomness-gathering routines */\n\nBOOLEAN testRandom( void )\n\t{\n\tif( !testRandomRoutines() )\n\t\t{\n\t\tfputs( \"The self-test will proceed without using a strong random \"\n\t\t\t   \"number source.\\n\\n\", outputStream );\n\n\t\t/* Kludge the randomness routines so we can continue the self-tests */\n\t\tcryptAddRandom( \"xyzzy\", 5 );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testRandom( void )\n\t{\n\tfputs( \"Skipping test of randomness routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_RANDOM */\n\n#ifdef TEST_CONFIG\n\n/* The names of the configuration options we check for */\n\nstatic struct {\n\tconst CRYPT_ATTRIBUTE_TYPE option;\t/* Option */\n\tconst char *name;\t\t\t\t\t/* Option name */\n\tconst BOOLEAN isNumeric;\t\t\t/* Whether it's a numeric option */\n\t} configOption[] = {\n\t{ CRYPT_OPTION_INFO_DESCRIPTION, \"CRYPT_OPTION_INFO_DESCRIPTION\", FALSE },\n\t{ CRYPT_OPTION_INFO_COPYRIGHT, \"CRYPT_OPTION_INFO_COPYRIGHT\", FALSE },\n\t{ CRYPT_OPTION_INFO_MAJORVERSION, \"CRYPT_OPTION_INFO_MAJORVERSION\", TRUE },\n\t{ CRYPT_OPTION_INFO_MINORVERSION, \"CRYPT_OPTION_INFO_MINORVERSION\", TRUE },\n\t{ CRYPT_OPTION_INFO_STEPPING, \"CRYPT_OPTION_INFO_STEPPING\", TRUE },\n\n\t{ CRYPT_OPTION_ENCR_ALGO, \"CRYPT_OPTION_ENCR_ALGO\", TRUE },\n\t{ CRYPT_OPTION_ENCR_HASH, \"CRYPT_OPTION_ENCR_HASH\", TRUE },\n\t{ CRYPT_OPTION_ENCR_MAC, \"CRYPT_OPTION_ENCR_MAC\", TRUE },\n\n\t{ CRYPT_OPTION_PKC_ALGO, \"CRYPT_OPTION_PKC_ALGO\", TRUE },\n\t{ CRYPT_OPTION_PKC_KEYSIZE, \"CRYPT_OPTION_PKC_KEYSIZE\", TRUE },\n\n\t{ CRYPT_OPTION_KEYING_ALGO, \"CRYPT_OPTION_KEYING_ALGO\", TRUE },\n\t{ CRYPT_OPTION_KEYING_ITERATIONS, \"CRYPT_OPTION_KEYING_ITERATIONS\", TRUE },\n\n\t{ CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES, \"CRYPT_OPTION_CERT_SIGNUNRECOGNISEDATTRIBUTES\", TRUE },\n\t{ CRYPT_OPTION_CERT_VALIDITY, \"CRYPT_OPTION_CERT_VALIDITY\", TRUE },\n\t{ CRYPT_OPTION_CERT_UPDATEINTERVAL, \"CRYPT_OPTION_CERT_UPDATEINTERVAL\", TRUE },\n\t{ CRYPT_OPTION_CERT_COMPLIANCELEVEL, \"CRYPT_OPTION_CERT_COMPLIANCELEVEL\", TRUE },\n\t{ CRYPT_OPTION_CERT_REQUIREPOLICY, \"CRYPT_OPTION_CERT_REQUIREPOLICY\", TRUE },\n\n\t{ CRYPT_OPTION_CMS_DEFAULTATTRIBUTES, \"CRYPT_OPTION_CMS_DEFAULTATTRIBUTES\", TRUE },\n\n\t{ CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS, \"CRYPT_OPTION_KEYS_LDAP_OBJECTCLASS\", FALSE },\n\t{ CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE, \"CRYPT_OPTION_KEYS_LDAP_OBJECTTYPE\", TRUE },\n\t{ CRYPT_OPTION_KEYS_LDAP_FILTER, \"CRYPT_OPTION_KEYS_LDAP_FILTER\", FALSE },\n\t{ CRYPT_OPTION_KEYS_LDAP_CACERTNAME, \"CRYPT_OPTION_KEYS_LDAP_CACERTNAME\", FALSE },\n\t{ CRYPT_OPTION_KEYS_LDAP_CERTNAME, \"CRYPT_OPTION_KEYS_LDAP_CERTNAME\", FALSE },\n\t{ CRYPT_OPTION_KEYS_LDAP_CRLNAME, \"CRYPT_OPTION_KEYS_LDAP_CRLNAME\", FALSE },\n\t{ CRYPT_OPTION_KEYS_LDAP_EMAILNAME, \"CRYPT_OPTION_KEYS_LDAP_EMAILNAME\", FALSE },\n\n\t{ CRYPT_OPTION_DEVICE_PKCS11_DVR01, \"CRYPT_OPTION_DEVICE_PKCS11_DVR01\", FALSE },\n\t{ CRYPT_OPTION_DEVICE_PKCS11_DVR02, \"CRYPT_OPTION_DEVICE_PKCS11_DVR02\", FALSE },\n\t{ CRYPT_OPTION_DEVICE_PKCS11_DVR03, \"CRYPT_OPTION_DEVICE_PKCS11_DVR03\", FALSE },\n\t{ CRYPT_OPTION_DEVICE_PKCS11_DVR04, \"CRYPT_OPTION_DEVICE_PKCS11_DVR04\", FALSE },\n\t{ CRYPT_OPTION_DEVICE_PKCS11_DVR05, \"CRYPT_OPTION_DEVICE_PKCS11_DVR05\", FALSE },\n\t{ CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY, \"CRYPT_OPTION_DEVICE_PKCS11_HARDWAREONLY\", TRUE },\n\n\t{ CRYPT_OPTION_NET_SOCKS_SERVER, \"CRYPT_OPTION_NET_SOCKS_SERVER\", FALSE },\n\t{ CRYPT_OPTION_NET_SOCKS_USERNAME, \"CRYPT_OPTION_NET_SOCKS_USERNAME\", FALSE },\n\t{ CRYPT_OPTION_NET_HTTP_PROXY, \"CRYPT_OPTION_NET_HTTP_PROXY\", FALSE },\n\t{ CRYPT_OPTION_NET_CONNECTTIMEOUT, \"CRYPT_OPTION_NET_CONNECTTIMEOUT\", TRUE },\n\t{ CRYPT_OPTION_NET_READTIMEOUT, \"CRYPT_OPTION_NET_READTIMEOUT\", TRUE },\n\t{ CRYPT_OPTION_NET_WRITETIMEOUT, \"CRYPT_OPTION_NET_WRITETIMEOUT\", TRUE },\n\n\t{ CRYPT_OPTION_MISC_ASYNCINIT, \"CRYPT_OPTION_MISC_ASYNCINIT\", TRUE },\n\t{ CRYPT_OPTION_MISC_SIDECHANNELPROTECTION, \"CRYPT_OPTION_MISC_SIDECHANNELPROTECTION\", TRUE },\n\n\t{ CRYPT_ATTRIBUTE_NONE, NULL, 0 }\n\t};\n\n/* Test the configuration options routines */\n\nBOOLEAN testConfig( void )\n\t{\n\tint i, value, status;\n\n\tfor( i = 0; configOption[ i ].option != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t{\n\t\tC_CHR buffer[ 256 ];\n\t\tint length;\n\n\t\tif( configOption[ i ].isNumeric )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\tconfigOption[ i ].option, &value );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"%s appears to be \"\n\t\t\t\t\t\t \"disabled/unavailable in this build.\\n\", \n\t\t\t\t\t\t configOption[ i ].name );\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\tfprintf( outputStream, \"%s = %d.\\n\", configOption[ i ].name, \n\t\t\t\t\t value );\n\t\t\tcontinue;\n\t\t\t}\n\t\tstatus = cryptGetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t\t  configOption[ i ].option,\n\t\t\t\t\t\t\t\t\t\t  buffer, &length );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"%s appears to be disabled/unavailable \"\n\t\t\t\t\t \"in this build.\\n\", configOption[ i ].name );\n\t\t\tcontinue;\n\t\t\t}\n\t\tassert( length < 256 );\n#ifdef UNICODE_STRINGS\n\t\tbuffer[ length / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"%s = %S.\\n\", configOption[ i ].name, \n\t\t\t\t buffer );\n#else\n\t\tbuffer[ length ] = '\\0';\n\t\tfprintf( outputStream, \"%s = %s.\\n\", configOption[ i ].name, \n\t\t\t\t buffer );\n#endif /* UNICODE_STRINGS */\n\t\t}\n\tprintf( \"\\n\" );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testConfig( void )\n\t{\n\tputs( \"Skipping display of config options...\\n\" );\n\treturn( TRUE );\n\t}\n#endif /* TEST_CONFIG */\n\n#ifdef TEST_DEVICE\n\n/* Test the crypto device routines */\n\nBOOLEAN testDevice( void )\n\t{\n\tint status;\n\n\tstatus = testDevices();\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Handling for crypto devices doesn't appear to be enabled in \"\n\t\t\t  \"this build of\\ncryptlib.\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( !status )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testDevice( void )\n\t{\n\tfputs( \"Skipping test of crypto device routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_DEVICE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTest Mid/High-level Functions\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_MIDLEVEL\n\n/* Test the mid-level routines */\n\nBOOLEAN testMidLevel( void )\n\t{\n\tif( !testLargeBufferEncrypt() )\n\t\treturn( FALSE );\n\tif( !testDeriveKey() )\n\t\treturn( FALSE );\n\tif( !testConventionalExportImport() )\n\t\treturn( FALSE );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_HMAC_SHA1, NULL ) ) )\n\t\t{\n\t\t/* Only test the MAC functions of HMAC-SHA1 is enabled */\n\t\tif( !testMACExportImport() )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_RSA, NULL ) ) )\n\t\t{\n\t\t/* Only test the PKC functions if RSA is enabled */\n\t\tif( !testKeyExportImport() )\n\t\t\treturn( FALSE );\n\t\tif( !testSignData() )\n\t\t\treturn( FALSE );\n\t\tif( !testKeygen() )\n\t\t\treturn( FALSE );\n\t\t}\n\tif( !testMidLevelDebugCheck() )\n\t\treturn( FALSE );\n\t/* No need for putchar, mid-level functions leave a blank line at end */\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testMidLevel( void )\n\t{\n\tfputs( \"Skipping test of mid-level encryption routines...\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_MIDLEVEL */\n\n#ifdef TEST_HIGHLEVEL\n\n/* Test the high-level routines (these are similar to the mid-level routines \n   but rely on things like certificate management to work) */\n\nBOOLEAN testHighLevel( void )\n\t{\n\tif( !testKeyExportImportCMS() )\n\t\treturn( FALSE );\n\tif( !testSignDataCMS() )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testHighLevel( void )\n\t{\n\tfputs( \"Skipping test of high-level routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_HIGHLEVEL */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Certificates\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_CERT\n\n/* Test the certificate routines */\n\nBOOLEAN testCert( void )\n\t{\n\tif( !testBasicCert() )\n\t\treturn( FALSE );\n\tif( !testCACert() )\n\t\treturn( FALSE );\n\tif( !testXyzzyCert() )\n\t\treturn( FALSE );\n\tif( !testTextStringCert() )\n\t\treturn( FALSE );\n\tif( !testComplexCert() )\n\t\treturn( FALSE );\n\tif( !testAltnameCert() )\n\t\treturn( FALSE );\n\tif( !testCertExtension() )\n\t\treturn( FALSE );\n\tif( !testCustomDNCert() )\n\t\treturn( FALSE );\n\tif( !testSETCert() )\n\t\treturn( FALSE );\n\tif( !testAttributeCert() )\n\t\treturn( FALSE );\n\tif( !testCertRequest() )\n\t\treturn( FALSE );\n\tif( !testComplexCertRequest() )\n\t\treturn( FALSE );\n\tif( !testCertRequestAttrib() )\n\t\treturn( FALSE );\n\tif( !testCRMFRequest() )\n\t\treturn( FALSE );\n\tif( !testComplexCRMFRequest() )\n\t\treturn( FALSE );\n\tif( !testCRL() )\n\t\treturn( FALSE );\n\tif( !testComplexCRL() )\n\t\treturn( FALSE );\n\tif( !testRevRequest() )\n\t\treturn( FALSE );\n\tif( !testCertChain() )\n\t\treturn( FALSE );\n\tif( !testCAConstraints() )\n\t\treturn( FALSE );\n\tif( !testCMSAttributes() )\n\t\treturn( FALSE );\n\tif( !testOCSPReqResp() )\n\t\treturn( FALSE );\n\tif( !testCertImport() )\n\t\treturn( FALSE );\n\tif( !testCertImportECC() )\n\t\treturn( FALSE );\n\tif( !testCertReqImport() )\n\t\treturn( FALSE );\n\tif( !testCRLImport() )\n\t\treturn( FALSE );\n\tif( !testCertChainImport() )\n\t\treturn( FALSE );\n\tif( !testOCSPImport() )\n\t\treturn( FALSE );\n\tif( !testBase64CertImport() )\n\t\treturn( FALSE );\n\tif( !testBase64CertChainImport() )\n\t\treturn( FALSE );\n\tif( !testMiscImport() )\n\t\treturn( FALSE );\n\tif( !testNonchainCert() )\n\t\treturn( FALSE );\n\tif( !testCertComplianceLevel() )\n\t\treturn( FALSE );\n\tif( !testCertChainHandling() )\n\t\treturn( FALSE );\n\tif( !testPKCS1Padding() )\n\t\treturn( FALSE );\n#if 0\t/* This takes a while to run and produces a lot of output that won't\n\t\t   be meaningful to anyone other than cryptlib developers so it's\n\t\t   disabled by default */\n\tif( !testPathProcessing() )\n\t\treturn( FALSE );\n#endif /* 0 */\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testCert( void )\n\t{\n\tfputs( \"Skipping test of certificate routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_CERT */\n\n#ifdef TEST_CERTPROCESS\n\n/* Test the certificate processing and CA certificate management \n   functionality.  A side-effect of the certificate-management \n   functionality is that the OCSP EE test certificates are written \n   to the test data directory */\n\nBOOLEAN testCertMgmt( void )\n\t{\n\tint status;\n\n\tif( !testCertProcess() )\n\t\treturn( FALSE );\n\tstatus = testCertManagement();\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Handling for CA certificate stores doesn't appear to be \"\n\t\t\t  \"enabled in this\\nbuild of cryptlib, skipping the test of \"\n\t\t\t  \"the certificate management routines.\\n\" );\n\t\t}\n\telse\n\t\t{\n\t\tif( !status )\n\t\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testCertMgmt( void )\n\t{\n\tfputs( \"Skipping test of certificate handling/CA management...\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_CERTPROCESS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Keysets\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_KEYSET\n\n/* Test the file and database keyset read routines */\n\nBOOLEAN testKeysetFile( void )\n\t{\n\tif( !testGetPGPPublicKey() )\n\t\treturn( FALSE );\n\tif( !testGetPGPPrivateKey() )\n\t\treturn( FALSE );\n\tif( !testReadWriteFileKey() )\n\t\treturn( FALSE );\n\tif( !testReadWriteAltFileKey() )\n\t\treturn( FALSE );\n\tif( !testReadWritePGPFileKey() )\n\t\treturn( FALSE );\n\tif( !testImportFileKey() )\n\t\treturn( FALSE );\n\tif( !testReadFilePublicKey() )\n\t\treturn( FALSE );\n\tif( !testDeleteFileKey() )\n\t\treturn( FALSE );\n\tif( !testUpdateFileCert() )\n\t\treturn( FALSE );\n\tif( !testReadFileCert() )\n\t\treturn( FALSE );\n\tif( !testReadFileCertPrivkey() )\n\t\treturn( FALSE );\n\tif( !testWriteFileCertChain() )\n\t\treturn( FALSE );\n\tif( !testReadFileCertChain() )\n\t\treturn( FALSE );\n\tif( !testAddTrustedCert() )\n\t\treturn( FALSE );\n#if 0\t/* This changes the global config file and is disabled by default */\n\tif( !testAddGloballyTrustedCert() )\n\t\treturn( FALSE );\n#endif /* 0 */\n\tif( !testWriteFileLongCertChain() )\n\t\treturn( FALSE );\n\tif( !testSingleStepFileCert() )\n\t\treturn( FALSE );\n\tif( !testSingleStepAltFileCert() )\n\t\treturn( FALSE );\n\tif( !testDoubleCertFile() )\n\t\treturn( FALSE );\n\tif( !testRenewedCertFile() )\n\t\treturn( FALSE );\n\tif( !testReadAltFileKey() )\n\t\treturn( FALSE );\n\tif( !testReadMiscFile() )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\nBOOLEAN testKeysetDatabase( void )\n\t{\n\tint status;\n\n  #ifdef DATABASE_AUTOCONFIG\n\tcheckCreateDatabaseKeysets();\n  #endif /* DATABASE_AUTOCONFIG */\n\tstatus = testWriteCert();\n\tif( !status )\n\t\treturn( FALSE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Handling for certificate databases doesn't appear to be \"\n\t\t\t  \"enabled in this\\nbuild of cryptlib, skipping the test of \"\n\t\t\t  \"the certificate database routines.\\n\" );\n\t\t}\n\telse\n\t\t{\n\t\t/* The write succeeded, try and read back what we've written */\n\t\tif( !testReadCert() )\n\t\t\treturn( FALSE );\n\t\tif( !testKeysetQuery() )\n\t\t\treturn( FALSE );\n\t\t}\n\n\t/* For the following tests we may have read access but not write access,\n\t   so we test a read of known-present certs before trying a write -\n\t   unlike the local keysets we don't need to add a certificate before we \n\t   can try reading it */\n\tstatus = testReadCertLDAP();\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Handling for LDAP certificate directories doesn't appear to \"\n\t\t\t  \"be enabled in\\nthis build of cryptlib, skipping the test of \"\n\t\t\t  \"the certificate directory\\nroutines.\\n\" );\n\t\t}\n\telse\n\t\t{\n\t\t/* LDAP access can fail if the directory doesn't use the standard\n\t\t   du jour, so we don't treat a failure as a fatal error */\n\t\tif( status )\n\t\t\t{\n\t\t\t/* LDAP writes are even worse than LDAP reads, so we don't\n\t\t\t   treat failures here as fatal either */\n\t\t\t( void ) testWriteCertLDAP();\n\t\t\t}\n\t\t}\n\tstatus = testReadCertURL();\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Handling for fetching certificates from web pages doesn't \"\n\t\t\t  \"appear to be\\nenabled in this build of cryptlib, skipping \"\n\t\t\t  \"the test of the HTTP routines.\\n\" );\n\t\t}\n\telse\n\t\t{\n\t\t/* Being able to read a certificate from a web page is rather \n\t\t   different from access to an HTTP certificate store so we don't \n\t\t   treat an error here as fatal */\n\t\tif( status )\n\t\t\t( void ) testReadCertHTTP();\n\t\t}\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testKeysetFile( void )\n\t{\n\tfputs( \"Skipping test of file keyset read routines...\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n\nBOOLEAN testKeysetDatabase( void )\n\t{\n\tfputs( \"Skipping test of database keyset read routines...\\n\\n\", \n\t\t   outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_KEYSET */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Enveloping\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_ENVELOPE\n\n/* Test the enveloping routines */\n\nBOOLEAN testEnveloping( void )\n\t{\n\tif( !testEnvelopeData() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeDataLargeBuffer() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeDataVariable() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeDataMultiple() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeCompress() )\n\t\treturn( FALSE );\n\tif( !testPGPEnvelopeCompressedDataImport() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSessionCrypt() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSessionCryptLargeBuffer() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSessionCryptVariable() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSessionCryptMultiple() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeCrypt() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePasswordCrypt() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePasswordCryptBoundary() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePasswordCryptImport() )\n\t\treturn( FALSE );\n\tif( !testPGPEnvelopePasswordCryptImport() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePKCCrypt() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePKCCryptAlgo() )\n\t\treturn( FALSE );\n\tif( !testPGPEnvelopePKCCryptImport() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePKCIterated() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSign() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSignAlgos() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSignHashUpgrade() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSignOverflow() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeSignIndef() )\n\t\treturn( FALSE );\n\tif( !testPGPEnvelopeSignedDataImport() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeAuthenticate() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeAuthEnc() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopePKCCrypt() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopePKCCryptDoubleCert() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopePKCCryptImport() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopeSign() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopeDualSign() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopeDetachedSig() )\n\t\treturn( FALSE );\n\tif( !testPGPEnvelopeDetachedSig() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopeRefCount() )\n\t\treturn( FALSE );\n\tif( !testCMSEnvelopeSignedDataImport() )\n\t\treturn( FALSE );\n\tif( !testEnvelopeCMSDebugCheck() )\n\t\treturn( FALSE );\n\tif( !testEnvelopePGPDebugCheck() )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testEnveloping( void )\n\t{\n\tfputs( \"Skipping test of enveloping routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_ENVELOPE */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Sessions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_SESSION\n\n/* Test the session routines */\n\nBOOLEAN testSessions( void )\n\t{\n\tint status;\n\n\tstatus = testSessionUrlParse();\n\tif( !status )\n\t\treturn( FALSE );\n\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t{\n\t\tputs( \"Network access doesn't appear to be enabled in this build of \"\n\t\t\t  \"cryptlib,\\nskipping the test of the secure session routines.\\n\" );\n\t\treturn( TRUE );\n\t\t}\n\tif( !checkNetworkAccess() )\n\t\t{\n\t\tputs( \"Couldn't perform a test connect to a well-known site \"\n\t\t\t  \"(Amazon.com) which\\nindicates that external network access \"\n\t\t\t  \"isn't available.  Is this machine\\nsituated behind a \"\n\t\t\t  \"firewall?\\n\" );\n\t\treturn( FALSE );\n\t\t}\n\tif( !testSessionAttributes() )\n\t\treturn( FALSE );\n\tif( !testSessionSSH() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHPubkeyAuth() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHPortforward() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHExec() )\n\t\treturn( FALSE );\n\tif( !testSessionSSL() )\n\t\treturn( FALSE );\n\tif( !testSessionSSLLocalSocket() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSLocalSocket() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS11() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS12() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSBadSSL() )\n\t\treturn( FALSE );\n#if 0\t/* The MS test server used for the general TLS 1.2 tests requires \n\t\t   fairly extensive custom configuration of client certs and the\n\t\t   ability to do rehandshakes due to the oddball way that SChannel\n\t\t   handles client auth so we disable this test until another server \n\t\t   that does TLS 1.2 client auth less awkwardly appears */\n\tif( !testSessionTLS12ClientCert() )\n\t\treturn( FALSE );\n#endif /* 0 */\n\tif( !testSessionOCSP() )\n\t\treturn( FALSE );\n\tif( !testSessionTSP() )\n\t\treturn( FALSE );\n\tif( !testSessionEnvTSP() )\n\t\treturn( FALSE );\n\tif( !testSessionCMP() )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testSessions( void )\n\t{\n\tfputs( \"Skipping test of session routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_SESSION */\n\n#ifdef TEST_SESSION_LOOPBACK\n\n/* Test loopback client/server sessions.  These require a threaded OS and \n   are aliased to no-ops on non-threaded systems.  In addition there can be \n   synchronisation problems between the two threads if the server is delayed \n   for some reason, resulting in the client waiting for a socket that isn't \n   opened yet.  This isn't easy to fix without a lot of explicit intra-\n   thread synchronisation, if there's a problem it's easier to just re-run \n   the tests */\n\nBOOLEAN testSessionsLoopback( void )\n\t{\n  #ifdef DATABASE_AUTOCONFIG\n\tcheckCreateDatabaseKeysets();\t/* Needed for PKI tests */\n  #endif /* DATABASE_AUTOCONFIG */\n\tif( !testSessionSSHClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerDsaKey() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerEccKey() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerFingerprint() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerPubkeyAuth() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerPubkeyAuthWrongKey() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerPubkeyAuthWrongName() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerPubkeyAuthPassword() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerPortForward() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerExec() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerMultichannel() )\n\t\treturn( FALSE );\n\tif( !testSessionSSHClientServerDebugCheck() )\n\t\treturn( FALSE );\n\tif( !testSessionSSLClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSSLClientCertClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSSharedKeyClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSNoSharedKeyClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSBulkTransferClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLSLocalServerSocketClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS11ClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS11ClientCertClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS12ClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS12ClientCertClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS12ClientCertManualClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTLS12WebSocketsClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSSLClientServerDebugCheck() )\n\t\treturn( FALSE );\n\tif( !testSessionHTTPCertstoreClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionRTCSClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionOCSPClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionOCSPMulticertClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTSPClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionTSPClientServerPersistent() )\n\t\treturn( FALSE );\n\tif( !testSessionSCEPClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSCEPAltAlgoClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSCEPCACertClientServer() )\n\t\treturn( FALSE );\n#if 0\t/* Requires changes to the SCEP specification */\n\tif( !testSessionSCEPRenewClientServer() )\n\t\treturn( FALSE );\n#endif /* 0 */\n\tif( !testSessionSCEPSHA2ClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionSCEPClientServerDebugCheck() )\n\t\treturn( FALSE );\n\tif( !testSessionCMPClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionCMPAltAlgoClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionCMPSHA2ClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionCMPPKIBootClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionPNPPKIClientServer() )\n\t\treturn( FALSE );\n\tif( !testSessionPNPPKICAClientServer() )\n\t\treturn( FALSE );\n#if 0\t/* Full RA functionality not completely implemented yet */\n\tif( !testSessionCMPRAClientServer() )\n\t\treturn( FALSE );\n#endif /* 0 */\n#if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && \\\n\t!defined( NDEBUG ) && 1\n\t/* Causes CRYPT_ERROR_INCOMPLETE on cryptEnd() due to the error-induced \n\t   early-out resulting in the server thread waiting for further client \n\t   requests while the client finishes and calls cryptEnd() */\n\tif( !testSessionCMPFailClientServer() )\n\t\treturn( FALSE );\n\tfputs( \"Warning: This test will cause a CRYPT_ERROR_INCOMPLETE on \"\n\t\t   \"cryptEnd() due to\\n         an early-out thread exit, this is \"\n\t\t   \"not an actual error.\\n\", outputStream );\n#endif /* 1 */\n\tif( !testSessionCMPClientServerDebugCheck() )\n\t\treturn( FALSE );\n\n\t/* The final set of loopback tests, which spawn a large number of \n\t   threads, can be somewhat alarming due to the amount of message spew \n\t   that they produce so we only run them on one specific development \n\t   test machine */\n#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE ) && 0\n\t{\n\tchar name[ MAX_COMPUTERNAME_LENGTH + 1 ];\n\tint length = MAX_COMPUTERNAME_LENGTH + 1;\n\n\tif( GetComputerName( name, &length ) && length == 8 && \\\n\t\t!memcmp( name, \"LENOVOX1\", length ) )\n\t\t{\n\t\tif( !testSessionSSHClientServerDualThread() )\n\t\t\treturn( FALSE );\n\t\tif( !testSessionSSHClientServerMultiThread() )\n\t\t\treturn( FALSE );\n\t\tif( !testSessionTLSClientServerMultiThread() )\n\t\t\treturn( FALSE );\n\t\t}\n\t}\n#endif /* __WINDOWS__ && !WinCE */\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testSessionsLoopback( void )\n\t{\n\tfputs( \"Skipping test of session routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n#endif /* TEST_SESSION_LOOPBACK */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tTest Users\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef TEST_USER\n\n/* Test the user routines */\n\nBOOLEAN testUsers( void )\n\t{\n\tif( !testUser() )\n\t\treturn( FALSE );\n\n\treturn( TRUE );\n\t}\n#else\n\nBOOLEAN testUsers( void )\n\t{\n\tfputs( \"Skipping test of user routines...\\n\\n\", outputStream );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTest Memory Fault-injection\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Test error-handling code paths by forcing memory-allocation faults at\n   every location in which cryptlib allocates memory.  Note that this test\n   can only be run if all of the cryptlib self-tests complete successfully,\n   since it injects memory faults until the self-tests report success */\n\n/*#define TEST_MEMFAULT\t/* Undefine to perform memory-fault tests */\n\n#ifdef TEST_MEMFAULT\n\n#if !defined( TEST_SELFTEST ) || !defined( TEST_CERT ) || \\\n\t!defined( TEST_HIGHLEVEL )\n  #error Need to enable all tests for fault-allocation test.\n#endif /* Defines to indicate that all tests are enabled */\n\nBOOLEAN testInit( void )\n\t{\n\tint status;\n\n\tstatus = cryptInit();\n\treturn( cryptStatusError( status ) ? FALSE : TRUE );\n\t}\n\n#define FAULT_STARTFUNCTION\t0\n#define FAULT_STARTINDEX\t0\n\ntypedef int ( *FUNCTION_PTR )( void );\ntypedef struct {\n\tFUNCTION_PTR function;\n\tconst char *functionName;\n\t} FUNCTION_TBL;\n\n#define MK_FN( function )\t{ function, #function }\n\nstatic const FUNCTION_TBL functionTbl[] = {\n\tMK_FN( testInit ),\n\tMK_FN( testSelfTest ),\n\tMK_FN( testLowLevel ),\n\tMK_FN( testRandom ),\n\tMK_FN( testConfig ),\n\tMK_FN( testDevice ),\n\tMK_FN( testMidLevel ),\n\tMK_FN( testCert ),\n\tMK_FN( testKeysetFile ),\n\tMK_FN( testKeysetDatabase ),\n\tMK_FN( testCertMgmt ),\n\tMK_FN( testHighLevel ),\n\tMK_FN( testEnveloping ),\n\tMK_FN( testSessions ),\n\tMK_FN{ NULL )\n\t};\n\nstatic void testMemFault( void )\n\t{\n\tint functionIndex;\n\n\t/* Since we don't want to have tons of diagnostic output interspersed\n\t   with the mem-fault output, we redirect the diagnostic output to\n\t   /dev/null */\n\toutputStream = fopen( \"nul:\", \"w\" );\n\tassert( outputStream != NULL );\n\n\tputs( \"Testing memory fault injection...\" );\n\tfor( functionIndex = FAULT_STARTFUNCTION; \n\t\t functionTbl[ functionIndex ].function != NULL; \n\t\t functionIndex++ )\n\t\t{\n\t\tint memFaultIndex;\n\n\t\tfor( memFaultIndex = FAULT_STARTINDEX; memFaultIndex < 10000; \n\t\t\t memFaultIndex++ )\n\t\t\t{\n\t\t\tint status;\n\n\t\t\t/* If we're testing something other than the cryptInit() \n\t\t\t   functionality then we need to initialise cryptlib first */\n\t\t\tif( functionIndex != 0 )\n\t\t\t\t{\n\t\t\t\t/* Since we've already tested the init functionality, we \n\t\t\t\t   don't want to fault the init any more */\n\t\t\t\tcryptSetMemFaultCount( 10000 );\n\t\t\t\tstatus = cryptInit();\n\t\t\t\tassert( cryptStatusOK( status ) );\n\t\t\t\t}\n\n\t\t\t/* Tell the debug-allocator to return an out-of-memory condition \n\t\t\t   after the given number of allocations */\n\t\t\tprintf( \"%s: %d.\\r\", functionTbl[ functionIndex ].functionName, \n\t\t\t\t\tmemFaultIndex );\n\t\t\tcryptSetMemFaultCount( memFaultIndex );\n\n\t\t\t/* Call the test function, with a memory fault at the given \n\t\t\t   memory allocation number */\n\t\t\tstatus = functionTbl[ functionIndex ].function();\n\t\t\tif( status != TRUE )\n\t\t\t\t{\n\t\t\t\tif( functionIndex != 0 )\n\t\t\t\t\tcryptEnd();\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\tcryptEnd();\n\t\t\tbreak;\n\t\t\t}\n\t\tassert( memFaultIndex < 10000 );\n\t\tputchar( '\\n' );\n\t\t}\n\t}\n#endif /* TEST_MEMFAULT\t*/\n#endif /* TEST_USER */\n"
  },
  {
    "path": "deps/cl345/test/testlib.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tcryptlib Test Code\t\t\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1995-2018\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __Nucleus__ )\n  #include <nu_ctype.h>\n  #include <nu_string.h>\n#else\n  #include <ctype.h>\t/* For toupper() */\n#endif /* OS-specific includes */\n\n#define _SAFETY_DEFINED\n#if defined( __xlc__ ) || defined( __IBMC__ )\n  #define CONST_RETURN \n#else\n  #define CONST_RETURN\tconst\n#endif /* IBM mainframe compilers */\n#define DATAPTR\t\t\tint\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n\n/* Optionally include and activate the Visual Leak Detector library if\n   we're running a debug build under VC++ 6.0.  Note that this can't be\n   run at the same time as Bounds Checker, since the two interefere with\n   each other */\n\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && 0\n  #include \"binaries/vld.h\"\n#endif /* VC++ 6.0 */\n\n/* Microsoft broke the VS 2015 runtime libraries by moving some functions \n   inline, which results in compile problems when linking to the ODBC libs, \n   which call functions that aren't externally visible any more due to \n   inlining.  To fix this, we have to implicitly add \n   legacy_stdio_definitions.lib to avoid link errors with the ODBC libs */\n\n#if defined( _MSC_VER ) && ( _MSC_VER == 1900 )\n  #pragma comment( lib, \"legacy_stdio_definitions.lib\" )\n#endif /* VS 2015 */\n\n/* Optionally include the Intel Thread Checker API to control analysis */\n\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && 0\n  #define USE_TCHECK\n  #include \"../../../Intel/VTune/tcheck/Include/libittnotify.h\"\n  #include \"../../../Intel/VTune/Analyzer/Include/VtuneApi.h\"\n  #pragma comment( lib, \"C:/Program Files/Intel/VTune/Analyzer/Lib/libittnotify.lib\" )\n  #pragma comment( lib, \"C:/Program Files/Intel/VTune/Analyzer/Lib/VtuneApi.lib \" )\n  #define THREAD_DEBUG_SUSPEND()\t__itt_pause(); VTPause()\n  #define THREAD_DEBUG_RESUME()\t\tVTResume(); __itt_resume()\n#else\n  #define THREAD_DEBUG_SUSPEND()\n  #define THREAD_DEBUG_RESUME()\n#endif /* VC++ 6.0 with Intel Thread Checker */\n\n/* Warn about nonstandard build options */\n\n#if defined( CONFIG_SUITEB_TESTS ) && ( defined( _MSC_VER ) || defined( __GNUC__ ) )\n  #pragma message( \"  Building Suite B command-line test configuration.\" )\n#endif /* CONFIG_SUITEB_TESTS with VC++/gcc */\n\n/* Whether various keyset tests worked, the results are used later to test\n   other routines.  We initially set the key read result to TRUE in case the\n   keyset read tests are never called, so we can still trying reading the\n   keys in other tests */\n\nint keyReadOK = TRUE, doubleCertOK = FALSE;\n\n/* The output stream to which diagnostic output is sent */\n\nFILE *outputStream;\n\n/* There are some sizeable (for DOS) data structures used, so we increase the\n   stack size to allow for them */\n\n#if defined( __MSDOS16__ ) && defined( __TURBOC__ )\n  extern unsigned _stklen = 16384;\n#endif /* __MSDOS16__ && __TURBOC__ */\n\n/* Prototypes for general debug routines used to evaluate problems with certs\n   and envelopes from other apps */\n\nint xxxCertImport( const char *fileName );\nint xxxCertCheck( const char *certFileName, const char *caFileNameOpt );\nvoid xxxPubKeyRead( const char *fileName, const char *keyName );\nvoid xxxPrivKeyRead( const char *fileName, const char *keyName, const char *password );\nvoid xxxDataImport( const char *fileName );\nvoid xxxSignedDataImport( const char *fileName );\nvoid xxxEncryptedDataImport( const char *fileName, const char *keyset,\n\t\t\t\t\t\t\t const char *password );\nvoid xxxSignedEncryptedDataImport( const char *fileName, const char *keyset,\n\t\t\t\t\t\t\t\t   const char *password );\nvoid xxxEnvelopeTest( const char *certFileName, const char *outFile );\n\n/* Prototype for custom key-creation routines */\n\nint createTestKeys( void );\n\n/* Prototype for stress test interface routine */\n\nvoid smokeTest( void );\n\n/* Prototype for Suite B test entry point */\n\n#if defined( CONFIG_SUITEB_TESTS ) \n\nint suiteBMain( int argc, char **argv );\n\n#endif /* CONFIG_SUITEB_TESTS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* The pseudo-CLI VC++ output windows are closed when the program exits so \n   we have to explicitly wait to allow the user to read them */\n\n#if defined( __WINDOWS__ ) && !defined( NDEBUG )\n\nstatic void cleanExit( const int exitStatus )\n\t{\n\tputs( \"\\nHit a key...\" );\n\tgetchar();\n\texit( exitStatus );\n\t}\nstatic void cleanupAndExit( const int exitStatus )\n\t{\n\tint status;\n\n\tstatus = cryptEnd();\n\tif( status == CRYPT_ERROR_INCOMPLETE )\n\t\tputs( \"cryptEnd() failed with CRYPT_ERROR_INCOMPLETE.\" );\n\tcleanExit( exitStatus );\n\t}\n#else\n\nstatic void cleanExit( const int exitStatus )\n\t{\n\texit( exitStatus );\n\t}\nstatic void cleanupAndExit( const int exitStatus )\n\t{\n\tcryptEnd();\n\tcleanExit( exitStatus );\n\t}\n#endif /* __WINDOWS__ && !NDEBUG */\n\n/* Update the cryptlib config file.  This code can be used to set the\n   information required to load PKCS #11 device drivers:\n\n\t- Set the driver path in the CRYPT_OPTION_DEVICE_PKCS11_DVR01 setting\n\t  below.\n\t- Add a call to updateConfig() from somewhere (e.g.the test kludge function).\n\t- Run the test code until it calls updateConfig().\n\t- Remove the updateConfig() call, then run the test code as normal.\n\t  The testDevices() call will report the results of trying to use your\n\t  driver.\n\n  cryptlib's SafeLoadLibrary() will always load drivers from the Windows \n  system directory / %SystemDirectory% unless given an absolute path */\n\nstatic void updateConfig( void )\n\t{\n#if 0\n\tconst char *driverPath = \"acospkcs11.dll\";\t\t/* ACOS */\n\tconst char *driverPath = \"aetpkss1.dll\";\t\t/* AET */\n\tconst char *driverPath = \"aloaha_pkcs11.dll\";\t/* Aloaha */\n\tconst char *driverPath = \"etpkcs11.dll\";\t\t/* Aladdin eToken */\n\tconst char *driverPath = \"psepkcs11.dll\";\t\t/* A-Sign */\n\tconst char *driverPath = \"asepkcs.dll\";\t\t\t/* Athena */\n\tconst char *driverPath = \"c:/temp/bpkcs11.dll\";\t/* Bloomberg */\n\tconst char *driverPath = \"/usr/local/lib/libsc-hsm-pkcs11.so\";  /* CardContact under Unix */\t\n\tconst char *driverPath = \"cryst32.dll\";\t\t\t/* Chrysalis */\n\tconst char *driverPath = \"c:/program files/luna/cryst201.dll\";\t/* Chrysalis */\n\tconst char *driverPath = \"pkcs201n.dll\";\t\t/* Datakey */\n\tconst char *driverPath = \"dkck201.dll\";\t\t\t/* Datakey (for Entrust) */\n\tconst char *driverPath = \"dkck232.dll\";\t\t\t/* Datakey/iKey (NB: buggy, use 201) */\n\tconst char *driverPath = \"c:/program files/eracom/cprov sw/cryptoki.dll\";\t/* Eracom (old, OK) */\n\tconst char *driverPath = \"c:/program files (x86)/eracom/cprov sw/cryptoki.dll\";\t/* Eracom (old, OK) */\n\tconst char *driverPath = \"c:/program files/eracom/cprov runtime/cryptoki.dll\";\t/* Eracom (new, doesn't work) */\n\tconst char *driverPath = \"sadaptor.dll\";\t\t/* Eutron */\n\tconst char *driverPath = \"ngp11v211.dll\";\t\t/* Feitian Technology */\n\tconst char *driverPath = \"pk2priv.dll\";\t\t\t/* Gemplus */\n\tconst char *driverPath = \"c:/program files/gemplus/gclib.dll\";\t/* Gemplus */\n\tconst char *driverPath = \"cryptoki.dll\";\t\t/* IBM */\n\tconst char *driverPath = \"csspkcs11.dll\";\t\t/* IBM */\n\tconst char *driverPath = \"ibmpkcss.dll\";\t\t/* IBM */\n\tconst char *driverPath = \"id2cbox.dll\";\t\t\t/* ID2 */\n\tconst char *driverPath = \"cknfast.dll\";\t\t\t/* nCipher */\n\tconst char *driverPath = \"/opt/nfast/toolkits/pkcs11/libcknfast.so\";/* nCipher under Unix */\n\tconst char *driverPath = \"/usr/lib/libcknfast.so\";\t/* nCipher under Unix */\n\tconst char *driverPath = \"c:/program files/mozilla firefox/softokn3.dll\";/* Netscape */\n\tconst char *driverPath = \"nxpkcs11.dll\";\t\t/* Nexus */\n\tconst char *driverPath = \"AuCryptoki2-0.dll\";\t/* Oberthur */\n\tconst char *driverPath = \"opensc-pkcs11.dll\";\t/* OpenSC */\n\tconst char *driverPath = \"/usr/local/lib/opensc-pkcs11.so\";\t/* OpenSC under Unix */\n\tconst char *driverPath = \"micardoPKCS11.dll\";\t/* Orga Micardo */\n\tconst char *driverPath = \"cryptoki22.dll\";\t\t/* Rainbow HSM (for USB use Datakey dvr) */\n\tconst char *driverPath = \"p11card.dll\";\t\t\t/* Safelayer HSM (for USB use Datakey dvr) */\n\tconst char *driverPath = \"slbck.dll\";\t\t\t/* Schlumberger */\n\tconst char *driverPath = \"SetTokI.dll\";\t\t\t/* SeTec */\n\tconst char *driverPath = \"siecap11.dll\";\t\t/* Siemens */\n\tconst char *driverPath = \"c:/program files (x86)/SoftHSM2/lib/softhsm2.dll\";\t/* SoftHSM */\n\tconst char *driverPath = \"smartp11.dll\";\t\t/* SmartTrust */\n\tconst char *driverPath = \"SpyPK11.dll\";\t\t\t/* Spyrus */\n#endif /* 0 */\n\tconst char *driverPath = \"c:/program files (x86)/eracom/cprov sw/cryptoki.dll\";\t/* Eracom (old, OK) */\n\tint status;\n\n\tprintf( \"Updating cryptlib configuration to load PKCS #11 driver\\n  \"\n\t\t\t\"'%s'\\nas default driver...\", driverPath );\n\n\t/* Set the path for a PKCS #11 device driver.  We only enable one of\n\t   these at a time to speed the startup time */\n\tstatus = cryptSetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_DEVICE_PKCS11_DVR01,\n\t\t\t\t\t\t\t\t\t  driverPath, strlen( driverPath ) );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\n\\nError updating PKCS #11 device driver profile, \"\n\t\t\t\t\"status %d.\\n\", status );\n\t\tcleanupAndExit( EXIT_FAILURE );\n\t\t}\n\n\t/* Flush the updated options to disk */\n\tstatus = cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CONFIGCHANGED, \n\t\t\t\t\t\t\t\tFALSE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\n\\nError comitting device driver profile update to disk, \"\n\t\t\t\t\"status %d.\\n\", status );\n\t\tcleanupAndExit( EXIT_FAILURE );\n\t\t}\n\n\tputs( \" done.\\n\" );\n\tcleanupAndExit( EXIT_SUCCESS );\n\t}\n\n/* Add trusted certs to the config file and make sure that they're\n   persistent.  This can't be done in the normal self-test since it requires\n   that cryptlib be restarted as part of the test to re-read the config file,\n   and because it modifies the cryptlib config file */\n\nstatic void updateConfigCert( void )\n\t{\n\tCRYPT_CERTIFICATE trustedCert;\n\tint status;\n\n\t/* Import the first certificate, make it trusted, and commit the changes */\n\timportCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 1 );\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CONFIGCHANGED, FALSE );\n\tcryptDestroyCert( trustedCert );\n\tcryptEnd();\n\n\t/* Do the same with a second certificate.  At the conclusion of this, we \n\t   should have two trusted certificates on disk */\n\tstatus = cryptInit();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tputs( \"Couldn't reload cryptlib configuration.\" );\n\t\treturn;\n\t\t}\n\timportCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 2 );\n\tcryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, TRUE );\n\tcryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CONFIGCHANGED, FALSE );\n\tcryptDestroyCert( trustedCert );\n\tcryptEnd();\n\t}\n\n/* Check for a discrepancy between debug and release builds of the \n   library and self-test code */\n\n#ifdef NDEBUG\n  #define testIsRelease\t\tTRUE\n#else\n  #define testIsRelease\t\tFALSE\n#endif /* NDEBUG */\n\nstatic void checkDebugReleaseMismatch( void )\n\t{\n\tBOOLEAN libraryIsRelease = TRUE;\n\n\t/* Check whether cryptlib is running as a debug build */\n\tif( checkLibraryIsDebug() )\n\t\tlibraryIsRelease = FALSE;\n\n\t/* Warn about mismatches between debug and release mode library and test\n\t   code builds:\n\n\t\tLibrary\t\tTest code\tResult\n\t\t-------\t\t---------\t------\n\t\tDebug\t\tDebug\t\tOK\n\t\tDebug\t\tRelease\t\tSome unexpected results\n\t\tRelease\t\tDebug\t\tTests will fail\n\t\tRelease\t\tRelease\t\tOK */\n\tif( !libraryIsRelease && testIsRelease )\n\t\t{\n\t\tputs( \"\\nWarning: cryptlib has been built in debug mode but the \"\n\t\t\t  \"self-test code is\\n         build in release mode, some \"\n\t\t\t  \"self-tests may produce unexpected\\n         debug-only \"\n\t\t\t  \"results.\\n\\nHit a key...\" );\n\t\tgetchar();\n\t\t}\n\tif( libraryIsRelease && !testIsRelease )\n\t\t{\n\t\tputs( \"\\nWarning: cryptlib has been built in release mode but the \"\n\t\t\t  \"self-test code is\\n         built in debug mode, some \"\n\t\t\t  \"self-tests will fail due to the code\\n         trying to \"\n\t\t\t  \"exercise debug-only options.\\n\\nHit a key...\" );\n\t\tgetchar();\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tArgument Processing\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Flags for the tests that we want to perform */\n\n#define DO_SELFTEST\t\t\t\t0x0001\n#define DO_LOWLEVEL\t\t\t\t0x0002\n#define DO_RANDOM\t\t\t\t0x0004\n#define DO_CONFIG\t\t\t\t0x0008\n#define DO_DEVICE\t\t\t\t0x0010\n#define DO_MIDLEVEL\t\t\t\t0x0020\n#define DO_CERT\t\t\t\t\t0x0040\n#define DO_KEYSETFILE\t\t\t0x0080\n#define DO_KEYSETDBX\t\t\t0x0100\n#define DO_CERTPROCESS\t\t\t0x0200\n#define DO_HIGHLEVEL\t\t\t0x0400\n#define DO_ENVELOPE\t\t\t\t0x0800\n#define DO_SESSION\t\t\t\t0x1000\n#define DO_SESSIONLOOPBACK\t\t0x2000\n#define DO_USER\t\t\t\t\t0x4000\n\n#define DO_ALL\t\t\t\t\t0xFFFF\n\n/* Show usage and exit */\n\nstatic void usageExit( void )\n\t{\n\tputs( \"Usage: testlib [-abcdefhiklmoprstu]\" );\n\n\tputs( \"  Encryption function tests:\" );\n\tputs( \"       -l = Test low-level functions\" );\n\tputs( \"       -m = Test mid-level functions\" );\n\tputs( \"       -i = Test high-level functions\" );\n\tputs( \"\" );\n\n\tputs( \"  Subsystem tests:\" );\n\tputs( \"       -c = Test certificate subsystem\" );\n\tputs( \"       -d = Test device subsystem\" );\n\tputs( \"       -f = Test file keyset subsystem\" );\n\tputs( \"       -k = Test database keyset subsystem\" );\n\tputs( \"       -e = Test envelope subsystem\" );\n\tputs( \"       -s = Test session subsystem\" );\n\tputs( \"       -t = Test session subsystem via loopback interface\" );\n\tputs( \"       -u = Test user subsystem\" );\n\tputs( \"\" );\n\n\tputs( \"  Miscellaneous tests:\" );\n\tputs( \"       -r = Test entropy-gathering routines\" );\n\tputs( \"       -b = Perform built-in self-test\" );\n\tputs( \"       -o = Test configuration management routines\" );\n\tputs( \"       -p = Test certificate processing\" );\n\tputs( \"\" );\n\n\tputs( \"  Other options:\" );\n\tputs( \"       -a = All except networking tests, i.e. run only local tests\" );\n\tputs( \"       -h = Display this help text\" );\n\tputs( \"       -- = End of arg list\" );\n\tputs( \"\" );\n\n\tputs( \"Default is to test all cryptlib subsystems.\" );\n\texit( EXIT_FAILURE );\n\t}\n\n/* Process command-line arguments */\n\nstatic int processArgs( int argc, char **argv, int *argFlags, \n\t\t\t\t\t\tconst char **zCmdPtrPtr, const char **zArgPtrPtr )\n\t{\n\tconst char *zargPtr = NULL;\n\tBOOLEAN moreArgs = TRUE, isZArg = FALSE;\n\n\t/* Clear return values */\n\t*argFlags = 0;\n\t*zCmdPtrPtr = *zArgPtrPtr = NULL;\n\n\t/* No args means test everything */\n\tif( argc <= 0 )\n\t\t{\n\t\t*argFlags = DO_ALL;\n\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Check for arguments */\n\twhile( argc > 0 && ( *argv[ 0 ] == '-' || isZArg ) && moreArgs )\n\t\t{\n\t\tconst char *argPtr = argv[ 0 ] + 1;\n\n\t\t/* If the last argument was a -z one, this is the argument value \n\t\t   that goes with it */\n\t\tif( isZArg )\n\t\t\t{\n\t\t\tisZArg = FALSE;\n\t\t\t*zArgPtrPtr = argv[ 0 ];\n\t\t\targv++;\n\t\t\targc--;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\twhile( *argPtr )\n\t\t\t{\n\t\t\tswitch( toupper( *argPtr ) )\n\t\t\t\t{\n\t\t\t\tcase '-':\n\t\t\t\t\tmoreArgs = FALSE;\t/* GNU-style end-of-args flag */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'A':\n\t\t\t\t\t*argFlags = DO_ALL & ~( DO_SESSION | DO_SESSIONLOOPBACK );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'B':\n\t\t\t\t\t*argFlags |= DO_SELFTEST;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'C':\n\t\t\t\t\t*argFlags |= DO_CERT;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'D':\n\t\t\t\t\t*argFlags |= DO_DEVICE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'E':\n\t\t\t\t\t*argFlags |= DO_ENVELOPE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'F':\n\t\t\t\t\t*argFlags |= DO_KEYSETFILE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'H':\n\t\t\t\t\tusageExit();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'I':\n\t\t\t\t\t*argFlags |= DO_HIGHLEVEL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'K':\n\t\t\t\t\t*argFlags |= DO_KEYSETDBX;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'L':\n\t\t\t\t\t*argFlags |= DO_LOWLEVEL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'M':\n\t\t\t\t\t*argFlags |= DO_MIDLEVEL;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'O':\n\t\t\t\t\t*argFlags |= DO_CONFIG;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'P':\n\t\t\t\t\t*argFlags |= DO_CERTPROCESS;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'R':\n\t\t\t\t\t*argFlags |= DO_RANDOM;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'S':\n\t\t\t\t\t*argFlags |= DO_SESSION;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'T':\n\t\t\t\t\t*argFlags |= DO_SESSIONLOOPBACK;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'U':\n\t\t\t\t\t*argFlags |= DO_USER;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'Z':\n\t\t\t\t\tzargPtr = argPtr + 1;\n\t\t\t\t\tif( *zargPtr == '\\0' )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tputs( \"Error: Missing argument for -z option.\" );\n\t\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t\t}\n\t\t\t\t\twhile( argPtr[ 1 ] )\n\t\t\t\t\t\targPtr++;\t/* Skip rest of arg */\n\t\t\t\t\t*zCmdPtrPtr = zargPtr;\n\t\t\t\t\tisZArg = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tprintf( \"Error: Unknown argument '%c'.\\n\", *argPtr );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\targPtr++;\n\t\t\t}\n\t\targv++;\n\t\targc--;\n\t\t}\n\tif( argc > 0 )\n\t\t{\n\t\tprintf( \"Error: Unknown argument '%s'.\\n\", argv[ 0 ] );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tFuzzing Wrapper\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Wrapper for injecting fuzz data */\n\n#if defined( CONFIG_FUZZ ) && !defined( NDEBUG )\n\nvoid __afl_manual_init( void );\n\nstatic int fuzzSession( const int sessionType,\n\t\t\t\t\t\tconst char *fuzzFileName )\n\t{\n\tCRYPT_SESSION cryptSession;\n\tCRYPT_CONTEXT cryptPrivKey = CRYPT_UNUSED;\n\tBYTE buffer[ 4096 ];\n\tconst BOOLEAN isServer = \\\n\t\t\t( sessionType == CRYPT_SESSION_SSH_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_SSL_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_OCSP_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_RTCS_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_TSP_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_CMP_SERVER || \\\n\t\t\t  sessionType == CRYPT_SESSION_SCEP_SERVER ) ? \\\n\t\t\tTRUE : FALSE;\n\tconst BOOLEAN isSubprotocol = ( sessionType >= 5000 ) ? TRUE : FALSE;\n\tint length, status;\n\n\t/* Create the session */\n\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t isSubprotocol ? CRYPT_SESSION_SSL : \\\n\t\t\t\t\t\t\t\t\t\t\t\t sessionType );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Set up the various attributes needed to establish a minimal session */\n\tif( isServer )\n\t\t{\n\t\tif( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptPrivKey ) )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\telse\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t  \"localhost\", 9 );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\tif( sessionType == CRYPT_SESSION_SSL )\n\t\t\t{\n\t\t\t/* Set the version to match the fuzzing test data */\n\t\t\tcryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, 2 );\n\t\t\t}\n\t\t}\n\tif( sessionType == CRYPT_SESSION_SSH || \\\n\t\tsessionType == CRYPT_SESSION_CMP )\n\t\t{\n\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\t\t  SSH_USER_NAME,\n\t\t\t\t\t\t\t\t\t\t  paramStrlen( SSH_USER_NAME ) );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t\t  SSH_PASSWORD,\n\t\t\t\t\t\t\t\t\t\t\t  paramStrlen( SSH_PASSWORD ) );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\tif( sessionType == CRYPT_SESSION_CMP )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t\t\tCRYPT_REQUESTTYPE_INITIALISATION );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( status );\n\t\t}\n\n\t/* Perform any final session initialisation */\n\tcryptFuzzInit( cryptSession, cryptPrivKey );\n\n\t/* We're ready to go, start the forkserver and read the mutable data */\n#ifdef __llvm__\n\t__afl_manual_init();\n#endif /* __llvm__ */\n\tlength = readFileData( fuzzFileName, fuzzFileName, buffer, 4096, 32, \n\t\t\t\t\t\t   TRUE );\n\tif( length < 32 )\n\t\treturn( CRYPT_ERROR_READ );\n\n\t/* Perform the fuzzing */\n\t( void ) cryptSetFuzzData( cryptSession, buffer, length, \n\t\t\t\t\t\t\t   isSubprotocol ? CRYPT_SUBPROTOCOL_WEBSOCKETS : \\\n\t\t\t\t\t\t\t\t\t\t\t   CRYPT_SUBPROTOCOL_NONE );\n\tcryptDestroySession( cryptSession );\n\tif( cryptPrivKey != CRYPT_UNUSED )\n\t\tcryptDestroyContext( cryptPrivKey );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int fuzzFile( const char *fuzzFileName )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tBYTE buffer[ 4096 ];\n\tint length, status;\n\n\t/* Read the data to fuzz */\n\tlength = readFileData( fuzzFileName, fuzzFileName, buffer, 4096, 64, \n\t\t\t\t\t\t   TRUE );\n\tif( length < 64 )\n\t\treturn( CRYPT_ERROR_READ );\n\n\t/* Process the input file */\n\tstatus = cryptImportCert( buffer, length, CRYPT_UNUSED, &cryptCert );\n\tif( cryptStatusOK( status ) )\n\t\tcryptDestroyCert( cryptCert );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int fuzzEnvelope( const char *fuzzFileName )\n\t{\n\tCRYPT_ENVELOPE cryptEnvelope;\n\tBYTE buffer[ 4096 ];\n\tint length, bytesIn, status;\n\n\t/* Create the envelope */\n\tstatus = cryptCreateEnvelope( &cryptEnvelope, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t  CRYPT_FORMAT_AUTO );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* We're ready to go, start the forkserver and read the mutable data */\n#ifdef __llvm__\n\t__afl_manual_init();\n#endif /* __llvm__ */\n\tlength = readFileData( fuzzFileName, fuzzFileName, buffer, 4096, 64, \n\t\t\t\t\t\t   TRUE );\n\tif( length < 64 )\n\t\treturn( CRYPT_ERROR_READ );\n\n\t/* Process the input file */\n\t( void ) cryptPushData( cryptEnvelope, buffer, length, &bytesIn );\n\tcryptDestroyEnvelope( cryptEnvelope );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int fuzzKeyset( const char *fuzzFileName )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* Start the forkserver */\n#ifdef __llvm__\n\t__afl_manual_init();\n#endif /* __llvm__ */\n\n\t/* Process the input file */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  fuzzFileName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\tcryptKeysetClose( cryptKeyset );\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int fuzzSpecial( const int fuzzType, const char *fuzzFileName )\n\t{\n\tCRYPT_CONTEXT cryptPrivKey;\n\tCRYPT_SESSION cryptSession;\n\tBYTE buffer[ 8192 ];\n\tconst BOOLEAN isServer = ( fuzzType == 4002 ) ? TRUE : FALSE;\n\tconst int minLength = ( fuzzType == 4000 ) ? 2 : 16;\n\tint length, status;\n\n\t/* If we're fuzzing bignum ops, load the private key that we'll need */\n\tif( fuzzType == 4000 )\n\t\t{\n\t\tif( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptPrivKey ) )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\tif( fuzzType == 4001 )\n\t\t{\n\t\tstatus = cryptCreateSession( &cryptSession, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t CRYPT_SESSION_SSL );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( CRYPT_ERROR_FAILED );\n\t\t}\n\n\t/* We're ready to go, start the forkserver and read the mutable data */\n#ifdef __llvm__\n\t__afl_manual_init();\n#endif /* __llvm__ */\n\tlength = readFileData( fuzzFileName, fuzzFileName, buffer, 8192, \n\t\t\t\t\t\t   minLength, TRUE );\n\tif( length < minLength )\n\t\treturn( CRYPT_ERROR_READ );\n\n\t/* Process the input file */\n\tswitch( fuzzType )\n\t\t{\n\t\tcase 4000:\n\t\t\t{\n\t\t\tBYTE tmpBuffer[ 8192 ];\n\n#if 0\t\t/* We don't do an early-out in order to check that the bignum \n\t\t\t   code can actually reject all invalid input values */\n\t\t\t/* Any value that's larger than the modulus will be trivially \n\t\t\t   rejected so there's no point in trying to process it */\n\t\t\tif( buffer[ 0 ] > 0x9C )\n\t\t\t\t{\n\t\t\t\tcryptDestroyContext( cryptPrivKey );\n\t\t\t\treturn( CRYPT_OK );\n\t\t\t\t}\n#endif /* 0 */\n\n\t\t\tmemcpy( tmpBuffer, buffer, length );\n\t\t\tstatus = cryptDecrypt( cryptPrivKey, buffer, length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\tstatus = cryptEncrypt( cryptPrivKey, buffer, length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\t/* Make sure that we got back what we started with */\n\t\t\t\tassert( !memcmp( buffer, tmpBuffer, length ) );\n\t\t\t\t}\n\t\t\tcryptDestroyContext( cryptPrivKey );\n\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase 4001:\n\t\t\t( void ) cryptSetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t\t\t  buffer, length );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\t( void ) cryptFuzzSpecial( CRYPT_UNUSED, buffer, length, \n\t\t\t\t\t\t\t\t\t   isServer );\n\t\t\tbreak;\n\t\t}\n\n\treturn( CRYPT_OK );\n\t}\n\nstatic int fuzz( const char *cmd, const char *arg )\n\t{\n\tstatic const struct {\n\t\tconst char *fuzzTypeName;\n\t\tconst int fuzzType;\n\t\t} fuzzTypeMap[] = {\n\t\t{ \"base64\", 1000 }, { \"certificate\", 1001 },\n\t\t{ \"certchain\", 1002 }, { \"certreq\", 1002 },\n\t\t{ \"cms\", 2000 }, { \"pgp\", 2001 },\n\t\t{ \"pkcs12\", 3000 }, { \"pkcs15\", 3001 },\n\t\t{ \"pgppub\", 3002 }, { \"pgpsec\", 3003 },\n\t\t{ \"bignum\", 4000 }, { \"url\", 4001 }, \n\t\t{ \"http-req\", 4002 }, { \"http-resp\", 4003 },\n\t\t{ \"ssh-client\", CRYPT_SESSION_SSH },\n\t\t{ \"ssh-server\", CRYPT_SESSION_SSH_SERVER },\n\t\t{ \"ssl-client\", CRYPT_SESSION_SSL },\n\t\t{ \"ssl-server\", CRYPT_SESSION_SSL_SERVER },\n\t\t{ \"ocsp-client\", CRYPT_SESSION_OCSP },\n\t\t{ \"ocsp-server\", CRYPT_SESSION_OCSP_SERVER },\n\t\t{ \"rtcs-client\", CRYPT_SESSION_RTCS },\n\t\t{ \"rtcs-server\", CRYPT_SESSION_RTCS_SERVER },\n\t\t{ \"tsp-client\", CRYPT_SESSION_TSP },\n\t\t{ \"tsp-server\", CRYPT_SESSION_TSP_SERVER },\n\t\t{ \"scep-client\", CRYPT_SESSION_SCEP },\n\t\t{ \"scep-server\", CRYPT_SESSION_SCEP_SERVER },\n\t\t{ \"cmp-client\", CRYPT_SESSION_CMP },\n\t\t{ \"cmp-server\", CRYPT_SESSION_CMP_SERVER },\n\t\t{ \"websockets\", 5000 },\n\t\t{ NULL, 0 }\n\t\t};\n\tint i, fuzzType = -1, status;\n\n\t/* Test harness for code checking */\n#if defined( CONFIG_FUZZ ) && !defined( NDEBUG ) && defined( __WINDOWS__ ) && 1\n//\tcmd = \"base64\"; arg = \"test/fuzz/base64.dat\";\n//\tcmd = \"certificate\"; arg = \"test/fuzz/certificate.dat\";\n//\tcmd = \"certchain\"; arg = \"test/fuzz/certchain.dat\";\n//\tcmd = \"certreq\"; arg = \"test/fuzz/certreq.dat\";\n//\tcmd = \"cms\"; arg = \"test/fuzz/cms.dat\";\n//\tcmd = \"pgp\"; arg = \"test/fuzz/pgp.dat\";\n//\tcmd = \"pkcs12\"; arg = \"test/fuzz/pkcs12.dat\";\n//\tcmd = \"pkcs15\"; arg = \"test/fuzz/pkcs15.dat\";\n//\targ = \"pgppub\"; arg = \"test/fuzz/pgppub.dat\";\n//\targ = \"pgpsec\"; arg = \"test/fuzz/pgpsec.dat\";\n//\tcmd = \"ssl-client\"; arg = \"test/fuzz/ssl_svr.dat\";\n//\tcmd = \"ssl-server\"; arg = \"test/fuzz/ssl_cli.dat\";\n//\tcmd = \"ssh-client\"; arg = \"test/fuzz/ssh_svr.dat\";\n//\tcmd = \"ssh-server\"; arg = \"test/fuzz/ssh_cli.dat\";\n//\tcmd = \"ocsp-client\"; arg = \"test/fuzz/ocsp_svr.dat\";\n//\tcmd = \"ocsp-server\"; arg = \"test/fuzz/ocsp_cli.dat\";\n//\tcmd = \"tsp-client\"; arg = \"test/fuzz/tsp_svr.dat\";\n//\tcmd = \"tsp-server\"; arg = \"test/fuzz/tsp_cli.dat\";\n//\tcmd = \"cmp-client\"; arg = \"test/fuzz/cmp_svr.dat\";\n//\tcmd = \"cmp-server\"; arg = \"test/fuzz/cmp_cli.dat\";\n//\tcmd = \"scep-client\"; cmd = \"scep-server\"; See comments above\n//\tcmd = \"bignum\"; arg = \"test/fuzz/bignum.dat\";\n//\tcmd = \"url\"; arg = \"test/fuzz/url.dat\";\n//\tcmd = \"http-req\"; arg = \"test/fuzz/http_req.dat\";\n//\tcmd = \"http-resp\"; arg = \"test/fuzz/http_resp.dat\";\n\tcmd = \"websockets\"; arg = \"test/fuzz/websockets.dat\";\n#endif /* __WINDOWS__ test */\n\n\t/* Make sure that we've got an input arg */\n\tif( cmd == NULL )\n\t\t{\n\t\tprintf( \"Error: Missing argument fuzz type.\\n\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\tif( arg == NULL )\n\t\t{\n\t\tprintf( \"Error: Missing argument fuzz filename.\\n\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Figure out which type of fuzzing we're doing */\n\tfor( i = 0; fuzzTypeMap[ i ].fuzzTypeName != NULL; i++ )\n\t\t{\n\t\tif( !strcmp( fuzzTypeMap[ i ].fuzzTypeName, cmd ) )\n\t\t\t{\n\t\t\tfuzzType = fuzzTypeMap[ i ].fuzzType;\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n\tif( fuzzType == -1 )\n\t\t{\n\t\tprintf( \"Error: Invalid fuzz type '%s'.\\n\", cmd );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\tif( fuzzType == CRYPT_SESSION_SCEP || \\\n\t\tfuzzType == CRYPT_SESSION_SCEP_SERVER )\n\t\t{\n\t\t/* SCEP uses CMS envelopes, which are already handled directly by\n\t\t   the envelope fuzzing.  In addition SCEP clients need to decrypt \n\t\t   CMS messages returned by the server, encrypted to the certificate \n\t\t   that they've just generated, which can't be emulated with static \n\t\t   data */\n\t\tprintf( \"Error: SCEP uses CMS messages which are fuzzed via \"\n\t\t\t\t\"envelopes.\\n\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Fake out the randomness polling */\n\tstatus = cryptAddRandom( \"xyzzy\", 5 );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"Error: Randomness setup failed with status %d.\\n\", status );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Patch point for checking crashes */\n#if defined( __WINDOWS__ ) && 0\n\t{\n\tchar buffer[ 128 ];\n\n\tfor( i = 0; i < 200; i++ )\n\t\t{\n\t\tFILE *filePtr;\n\n\t\tsprintf( buffer, \"r:/%s/%06d.dat\", cmd, i );\n\t\tfilePtr = fopen( buffer, \"rb\" );\n\t\tif( filePtr == NULL )\n\t\t\t{\n\t\t\tputs( \"No more files, exiting.\" );\n\t\t\tbreak;\n\t\t\t}\n\t\tfclose( filePtr );\n\t\tprintf( \"Fuzzing %s file %d (%s).\\n\", cmd, i, buffer );\n\t\tif( fuzzType >= 1000 && fuzzType <= 1100 )\n\t\t\tstatus = fuzzFile( buffer );\n\t\telse \n\t\tif( fuzzType >= 2000 && fuzzType <= 2100 )\n\t\t\tstatus = fuzzEnvelope( buffer );\n\t\telse \n\t\tif( fuzzType >= 3000 && fuzzType <= 3100 )\n\t\t\tstatus = fuzzKeyset( buffer );\n\t\telse \n\t\tif( fuzzType >= 4000 && fuzzType <= 4100 )\n\t\t\tstatus = fuzzSpecial( fuzzType, buffer );\n\t\telse\n\t\t\tstatus = fuzzSession( fuzzType, buffer );\n\t\t}\n\tputs( \"Done.\" );\n\tif( i <= 0 )\n\t\t{\n\t\tputs( \"Warning: No input files processed.\" );\n\t\tgetchar();\n\t\t}\n\texit( EXIT_SUCCESS );\n\t}\n#endif /* __WINDOWS__ test */\n\n\t/* Fuzz the target file */\n\tif( fuzzType >= 1000 && fuzzType <= 1100 )\n\t\tstatus = fuzzFile( arg );\n\telse \n\tif( fuzzType >= 2000 && fuzzType <= 2100 )\n\t\tstatus = fuzzEnvelope( arg );\n\telse \n\tif( fuzzType >= 3000 && fuzzType <= 3100 )\n\t\tstatus = fuzzKeyset( arg );\n\telse\n\tif( fuzzType >= 4000 && fuzzType <= 4100 )\n\t\tstatus = fuzzSpecial( fuzzType, arg );\n\telse\n\tif( ( fuzzType > CRYPT_SESSION_NONE && \\\n\t\t  fuzzType < CRYPT_SESSION_LAST ) || \\\n\t\t( fuzzType >= 5000 && fuzzType <= 5100 ) )\n\t\tstatus = fuzzSession( fuzzType, arg );\n\telse\n\t\t{\n\t\tprintf( \"Error: Unknown fuzz type '%d'.\\n\", fuzzType );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* The fuzz init failed, make sure that the wrapper records this */\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\texit( EXIT_SUCCESS );\n\t}\n#endif /* CONFIG_FUZZ && debug mode */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc.Kludges\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Generic test code insertion point.  The following routine is called\n   before any of the other tests are run and can be used to handle special-\n   case tests that aren't part of the main test suite */\n\nvoid initDatabaseKeysets( void );\t/* Call before calling cert-mgt.code */\n\nstatic void testKludge( const char *cmd, const char *arg )\n\t{\n\t/* Fuzzing test harness.  This is a noreturn function */\n#ifdef CONFIG_FUZZ\n\tfuzz( cmd, arg );\n#endif /* CONFIG_FUZZ */\n\n\t/* Performance-testing test harness */\n#if 0\n\tvoid performanceTests( const CRYPT_DEVICE cryptDevice );\n\n\tperformanceTests( CRYPT_UNUSED );\n#endif /* 0 */\n\n\t/* Simple (brute-force) server code. NB: setLocalConnect() by default \n\t   will bind to localhost, to allow external connections and bind to a\n\t   particular IP address and port uncomment the alternative \n\t   LOCAL_HOST_NAME configuration in test/test.h.\n\n\t   This can still exit if the client triggers a check in the debug \n\t   build, which throws an exception and exits to the debugger rather \n\t   than returning an error code, so the whole can be wrapped in:\n\n\t\t#!/bin/bash\n\n\t\tuntil ./server_app ; do\n\t\t\techo \"Server died with exit code $?, respawning..\" >> log.txt\n\t\t\tsleep 1\n\t\tdone \n\t\t\n\t   to allow it to restart on a non-clean exit */\n#if 0\n\twhile( TRUE )\n\t\t{\n\t\tprintf( \"Running server session...\\n\" );\n\t\ttestSessionTLS12Server();\n\t\t}\n#endif /* 0 */\n\n\t/* Exit point for the test harnesses above, used when we don't want to \n\t   fall through to the main test code */\n#if 0\n\tcleanupAndExit( EXIT_SUCCESS );\n#endif /* 0 */\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMain Test Code\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Comprehensive cryptlib functionality test.  To get the following to run \n   under WinCE as a native console app it's necessary to change the entry \n   point in Settings | Link | Output from WinMainCRTStartup to the \n   undocumented mainACRTStartup, which calls main() rather than WinMain(), \n   however this only works if the system has a native console-mode driver \n   (most don't) */\n\nint main( int argc, char **argv )\n\t{\n\tconst char *zCmdPtr = NULL, *zArgPtr = NULL;\n\tconst char *endianStringPtr;\n\tBOOLEAN sessionTestError = FALSE, loopbackTestError = FALSE;\n\tint flags, status;\n\tvoid testSystemSpecific1( void );\n\tvoid testSystemSpecific2( void );\n\n\t/* If we're running in a special test mode, run the test code and \n\t   exit */\n#ifdef CONFIG_SUITEB_TESTS\n\treturn( suiteBMain( argc, argv ) );\n#endif /* CONFIG_SUITEB_TESTS */\n\n\t/* Print a general banner to let the user know what's going on */\n#if defined( DATA_LITTLEENDIAN ) || defined( CONFIG_DATA_LITTLEENDIAN )\n\tendianStringPtr = \"little-endian\";\n#elif defined( DATA_BIGENDIAN ) || defined( CONFIG_DATA_BIGENDIAN )\n\tendianStringPtr = \"big-endian\";\n#else\n\tif( *( ( long * ) \"\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" ) < 0 )\n\t\tendianStringPtr = \"big-endian\";\n\telse\n\t\tendianStringPtr = \"little-endian\";\n#endif /* Endianness */\n\tprintf( \"testlib - cryptlib %d-bit %s self-test framework.\\n\", \n\t\t\t( int ) sizeof( size_t ) * 8,\t\t/* Cast for gcc */\n\t\t\tendianStringPtr );\n\tputs( \"Copyright Peter Gutmann 1995 - 2019.\" );\n#ifdef CONFIG_FUZZ\n\tputs( \"\" );\n\tputs( \"Warning: This is a custom fuzzing build that operates in a nonstandard manner.\" );\n\tputs( \"         Not to be used in a standard test or production environment.\" );\n#endif /* CONFIG_FUZZ */\n\tputs( \"\" );\n\n\t/* Skip the program name and process any command-line arguments */\n\targv++; argc--;\n\tstatus = processArgs( argc, argv, &flags, &zCmdPtr, &zArgPtr );\n\tif( !status )\n\t\texit( EXIT_FAILURE );\n\n#ifdef USE_TCHECK\n\tTHREAD_DEBUG_SUSPEND();\n#endif /* USE_TCHECK */\n\n\t/* Make sure that various system-specific features are set right */\n\ttestSystemSpecific1();\n\n\t/* VisualAge C++ doesn't set the TZ correctly.  The check for this isn't\n\t   as simple as it would seem since most IBM compilers define the same\n\t   preprocessor values even though it's not documented anywhere, so we\n\t   have to enable the tzset() call for (effectively) all IBM compilers\n\t   and then disable it for ones other than VisualAge C++ */\n#if ( defined( __IBMC__ ) || defined( __IBMCPP__ ) ) && !defined( __VMCMS__ )\n\ttzset();\n#endif /* VisualAge C++ */\n\n\t/* Set up the output stream to which diagnostic output is sent */\n\toutputStream = stdout;\n\n\t/* Perform memory-allocation fault injection.  We have to do this before\n\t   we call cryptInit() since the init code itself is tested by the\n\t   memory fault-injection */\n#ifdef TEST_MEMFAULT\n\ttestMemFault();\n#endif /* TEST_MEMFAULT */\n\n\t/* Initialise cryptlib */\n\tprintf( \"Initialising cryptlib...\" );\n\tstatus = cryptInit();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tprintf( \"\\ncryptInit() failed with error code %d, line %d.\\n\", \n\t\t\t\tstatus, __LINE__ );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\tputs( \"done.\" );\n\n\t/* Check for a discrepancy between debug and release builds of the \n\t   library and self-test code */\n\tcheckDebugReleaseMismatch();\n\n\t/* In order to avoid having to do a randomness poll for every test run,\n\t   we bypass the randomness-handling by adding some junk.  This is only\n\t   enabled when cryptlib is built in debug mode so it won't work with \n\t   any production systems */\n#ifndef TEST_RANDOM\n  #if defined( __MVS__ ) || defined( __VMCMS__ )\n\t#pragma convlit( resume )\n\tcryptAddRandom( \"xyzzy\", 5 );\n\t#pragma convlit( suspend )\n  #else\n\tcryptAddRandom( \"xyzzy\", 5 );\n  #endif /* Special-case EBCDIC handling */\n#endif /* TEST_RANDOM */\n\n\t/* Perform a general sanity check to make sure that the self-test is\n\t   being run the right way */\n\tif( !checkFileAccess() )\n\t\t{\n\t\tcryptEnd();\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Make sure that further system-specific features that require cryptlib \n\t   to be initialised to check are set right */\n#ifndef _WIN32_WCE\n\ttestSystemSpecific2();\n#endif /* WinCE */\n\n#ifdef USE_TCHECK\n\tTHREAD_DEBUG_RESUME();\n#endif /* USE_TCHECK */\n\n\t/* For general testing purposes we can insert test code at this point to\n\t   test special cases that aren't covered in the general tests below */\n\ttestKludge( zCmdPtr, zArgPtr );\n\n#ifdef SMOKE_TEST\n\t/* Perform a general smoke test of the kernel */\n\tsmokeTest();\n#endif /* SMOKE_TEST */\n\n\t/* Test each block of cryptlib functionality */\n\tif( ( flags & DO_SELFTEST ) && !testSelfTest() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_LOWLEVEL ) && !testLowLevel() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_RANDOM ) && !testRandom() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_CONFIG ) && !testConfig() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_DEVICE ) && !testDevice() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_MIDLEVEL ) && !testMidLevel() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_CERT ) && !testCert() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_KEYSETFILE ) && !testKeysetFile() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_KEYSETDBX ) && !testKeysetDatabase() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_CERTPROCESS ) && !testCertMgmt() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_HIGHLEVEL ) && !testHighLevel() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_ENVELOPE ) && !testEnveloping() )\n\t\tgoto errorExit;\n\tif( ( flags & DO_SESSION ) && !testSessions() )\n\t\t{\n\t\tsessionTestError = TRUE;\n\t\tgoto errorExit;\n\t\t}\n\tif( ( flags & DO_SESSIONLOOPBACK ) && !testSessionsLoopback() )\n\t\t{\n\t\tloopbackTestError = TRUE;\n\t\tgoto errorExit;\n\t\t}\n\tif( ( flags & DO_USER  ) && !testUsers() )\n\t\tgoto errorExit;\n\n\t/* Shut down cryptlib */\n\tstatus = cryptEnd();\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_INCOMPLETE )\n\t\t\t{\n\t\t\tputs( \"cryptEnd() failed with error code CRYPT_ERROR_INCOMPLETE, \"\n\t\t\t\t  \"a code path in the\\nself-test code resulted in an error \"\n\t\t\t\t  \"return without a full cleanup of objects.\\nIf you were \"\n\t\t\t\t  \"running the multithreaded loopback tests this may be \"\n\t\t\t\t  \"because one\\nor more threads lost sync with other threads \"\n\t\t\t\t  \"and exited without cleaning up\\nits objects.  This \"\n\t\t\t\t  \"happens occasionally due to network timing issues or\\n\"\n\t\t\t\t  \"thread scheduling differences.\" );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tprintf( \"cryptEnd() failed with error code %d, line %d.\\n\", \n\t\t\t\t\tstatus, __LINE__ );\n\t\t\t}\n\t\tgoto errorExit1;\n\t\t}\n\n\tputs( \"All tests concluded successfully.\" );\n\treturn( EXIT_SUCCESS );\n\n\t/* All errors end up here */\nerrorExit:\n\tcryptEnd();\nerrorExit1:\n\tputs( \"\\nThe test was aborted due to an error being detected.  If you \"\n\t\t  \"want to report\\nthis problem, please provide as much information \"\n\t\t  \"as possible to allow it to\\nbe diagnosed, for example the call \"\n\t\t  \"stack, the location inside cryptlib where\\nthe problem occurred, \"\n\t\t  \"and the values of any variables that might be\\nrelevant.\" );\n\tif( sessionTestError )\n\t\t{\n\t\tputs( \"\\nThe error occurred during one of the network session tests, \"\n\t\t\t  \"if the error\\nmessage indicates a network-level problem such \"\n\t\t\t  \"as ECONNREFUSED, ECONNRESET,\\nor a timeout or read error then \"\n\t\t\t  \"this is either due to a transient\\nnetworking problem or a \"\n\t\t\t  \"firewall interfering with network connections.  This\\nisn't a \"\n\t\t\t  \"cryptlib error, and doesn't need to be reported.\" );\n\t\t}\n\tif( loopbackTestError )\n\t\t{\n\t\tputs( \"\\nThe error occurred during one of the multi-threaded network \"\n\t\t\t  \"loopback\\ntests, this was probably due to the different threads \"\n\t\t\t  \"losing synchronisation.\\nFor the secure sessions this usually \"\n\t\t\t  \"results in read/write, timeout, or\\nconnection-closed errors \"\n\t\t\t  \"when one thread is pre-empted for too long.  For the\\n\"\n\t\t\t  \"certificate-management sessions it usually results in an error \"\n\t\t\t  \"related to the\\nserver being pre-empted for too long by database \"\n\t\t\t  \"updates.  Since the self-\\ntest exists only to exercise \"\n\t\t\t  \"cryptlib's capabilities, it doesn't bother with\\ncomplex thread \"\n\t\t\t  \"synchronisation during the multi-threaded loopback tests.\\nThis \"\n\t\t\t  \"type of error is non-fatal, and should disappear if the test is \"\n\t\t\t  \"re-run.\" );\n\t\t}\n\n\tcleanExit( EXIT_FAILURE );\n\treturn( EXIT_FAILURE );\t\t/* Exists only to get rid of compiler warnings */\n\t}\n\n/* PalmOS wrapper for main() */\n\n#ifdef __PALMSOURCE__\n\n#include <CmnErrors.h>\n#include <CmnLaunchCodes.h>\n\nuint32_t PilotMain( uint16_t cmd, void *cmdPBP, uint16_t launchFlags )\n\t{\n\tswitch( cmd )\n\t\t{\n\t\tcase sysAppLaunchCmdNormalLaunch:\n\t\t\tmain( 0, NULL );\n\t\t}\n\n\treturn( errNone );\n\t}\n#endif /* __PALMSOURCE__ */\n\n/* Symbian wrapper for main() */\n\n#ifdef __SYMBIAN__\n\nGLDEF_C TInt E32Main( void )\n\t{\n\tmain( 0, NULL );\n\n\treturn( KErrNone );\n\t}\n\n#ifdef __WINS__\n\n/* Support functions for use under the Windows emulator */\n\nEXPORT_C TInt WinsMain( void )\n\t{\n\tE32Main();\n\n\treturn( KErrNone );\n\t}\n\nTInt E32Dll( TDllReason )\n\t{\n\t/* Entry point for the DLL loader */\n\treturn( KErrNone );\n\t}\n#endif /* __WINS__ */\n\n#endif /* __SYMBIAN__ */\n\n/* Test the system-specific defines in crypt.h.  This is the last function in\n   the file because we want to avoid any definitions in crypt.h messing with\n   the rest of the test.c code.\n\n   The following include is needed only so we can check whether the defines\n   are set right.  crypt.h should never be included in a program that uses\n   cryptlib */\n\n#undef __WINDOWS__\n#undef __WIN16__\n#undef __WIN32__\n#undef BOOLEAN\n#undef BYTE\n#undef FALSE\n#undef TRUE\n#define IN_STRING\t\t/* No-op out define normally in analyse.h */\n#ifdef HIRES_FORMAT_SPECIFIER\n  #undef HIRES_FORMAT_SPECIFIER\n  #define HIRES_TIME\tHIRES_TIME_ALT\t/* Rename typedef'd value */\n#endif /* HIRES_TIME */\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( resume )\n#endif /* Resume ASCII use on EBCDIC systems */\n#if defined( __ILEC400__ )\n  #pragma convert( 819 )\n#endif /* Resume ASCII use on EBCDIC systems */\n#ifdef _MSC_VER\n  #include \"../crypt.h\"\n#else\n  #include \"crypt.h\"\n#endif /* Braindamaged MSC include handling */\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  #pragma convlit( suspend )\n#endif /* Suspend ASCII use on EBCDIC systems */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* Suspend ASCII use on EBCDIC systems */\n#undef mktime\t\t/* Undo mktime() bugfix in crypt.h */\n\n#ifndef _WIN32_WCE\n\nstatic time_t testTime( const int year )\n\t{\n\tstruct tm theTime;\n\n\tmemset( &theTime, 0, sizeof( struct tm ) );\n\ttheTime.tm_isdst = -1;\n\ttheTime.tm_year = 100 + year;\n\ttheTime.tm_mon = 5;\n\ttheTime.tm_mday = 5;\n\ttheTime.tm_hour = 12;\n\ttheTime.tm_min = 13;\n\ttheTime.tm_sec = 14;\n\treturn( mktime( &theTime ) );\n\t}\n#endif /* !WinCE */\n\nvoid testSystemSpecific1( void )\n\t{\n#if 0\t/* See comment below */\n\tconst CRYPT_ATTRIBUTE_TYPE testType = -1;\n#endif /* 0 */\n\tunion {\n\t\tint intVal;\n        char charVal[ 4 ];\n\t\t} \n\tendiannessCheckValue = { 0x41414101 };\n#ifndef _WIN32_WCE\n\tint i;\n#endif /* WinCE */\n\n\t/* Make sure that we've got the endianness set right.  If the machine is\n\t   big-endian then the check value will be something other than 1, \n\t   otherwise it will be 1 */\n#ifdef DATA_LITTLEENDIAN\n\tif( endiannessCheckValue.charVal[ 0 ] != 1 )\n\t\t{\n\t\tputs( \"The CPU endianness define is set wrong in crypt.h, this \"\n\t\t\t  \"machine appears to be\\nbig-endian, not little-endian.  Edit \"\n\t\t\t  \"the file and rebuild cryptlib.\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n#else\n\tif( endiannessCheckValue.charVal[ 0 ] == 1 )\n\t\t{\n\t\tputs( \"The CPU endianness define is set wrong in crypt.h, this \"\n\t\t\t  \"machine appears to be\\nlittle-endian, not big-endian.  Edit \"\n\t\t\t  \"the file and rebuild cryptlib.\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n#endif /* DATA_LITTLEENDIAN */\n\n\t/* Make sure that the compiler doesn't use variable-size enums (done by, \n\t   for example, the PalmOS SDK for backwards compatibility with \n\t   architectural decisions made for 68K-based PalmPilots) */\n\tif( sizeof( CRYPT_ALGO_TYPE ) != sizeof( int ) || \\\n\t\tsizeof( CRYPT_MODE_TYPE ) != sizeof( int ) ||\n\t\tsizeof( CRYPT_ATTRIBUTE_TYPE ) != sizeof( int ) )\n\t\t{\n\t\tputs( \"The compiler you are using treats enumerated types as \"\n\t\t\t  \"variable-length non-\\ninteger values, making it impossible \"\n\t\t\t  \"to reliably pass the address of an\\nenum as a function \"\n\t\t\t  \"parameter.  To fix this you need to rebuild cryptlib\\nwith \"\n\t\t\t  \"the appropriate compiler option or pragma to ensure that\\n\"\n\t\t\t  \"sizeof( enum ) == sizeof( int ).\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n#if 0\t/* The ANSI C default is 'int' with signedness being unimportant, \n\t\t   MSVC defaults to signed, gcc defaults to unsigned, and cryptlib\n\t\t   works with either, so whatever the CodeSourcery build of gcc is\n\t\t   doing it's more serious than a simple signedness issue */\n\t/* Make sure that the compiler doesn't use unsigned enums (for example a \n\t   mutant CodeSourcery build of gcc for eCos does this) */\n\tif( testType >= 0 )\n\t\t{\n\t\tputs( \"The compiler you are using treats enumerated types as \"\n\t\t\t  \"unsigned values,\\nmaking it impossible to reliably use enums \"\n\t\t\t  \"in conjunction with standard\\n(signed) integers.  To fix this \"\n\t\t\t  \"you need to rebuild cryptlib with the\\nappropriate compiler \"\n\t\t\t  \"option or pragma to ensure that enumerated types\\nare signed \"\n\t\t\t  \"like standard data types.\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n#endif /* 0 */\n\n\t/* Make sure that mktime() works properly (there are some systems on\n\t   which it fails well before 2038) */\n#ifndef _WIN32_WCE\n\tfor( i = 10; i < 36; i ++ )\n\t\t{\n\t\tconst time_t theTime = testTime( i );\n\n\t\tif( theTime < 0 )\n\t\t\t{\n\t\t\tprintf( \"Warning: This system has a buggy mktime() that can't \"\n\t\t\t\t\t\"handle dates beyond %d.\\n         Some certificate tests \"\n\t\t\t\t\t\"will fail, and long-lived CA certificates\\n         won't \"\n\t\t\t\t\t\"be correctly imported.\\nPress a key...\\n\", 2000 + i );\n\t\t\tgetchar();\n\t\t\tbreak;\n\t\t\t}\n\t\t}\n#endif /* !WinCE */\n\n\t/* If we're compiling under Unix with threading support, make sure the\n\t   default thread stack size is sensible.  We don't perform the check for\n\t   UnixWare/SCO since this already has the workaround applied */\n#if defined( UNIX_THREADS ) && !defined( __SCO_VERSION__ )\n\t{\n\tpthread_attr_t attr;\n\tsize_t stackSize;\n\n\tpthread_attr_init( &attr );\n\tpthread_attr_getstacksize( &attr, &stackSize );\n    pthread_attr_destroy( &attr );\n  #if ( defined( sun ) && OSVERSION > 4 )\n\t/* Slowaris uses a special-case value of 0 (actually NULL) to indicate\n\t   the default stack size of 1MB (32-bit) or 2MB (64-bit), so we have to\n\t   handle this specially */\n\tif( stackSize < 32768 && stackSize != 0 )\n  #else\n\tif( stackSize < 32768 )\n  #endif /* Slowaris special-case handling */\n\t\t{\n\t\tprintf( \"The pthread stack size is defaulting to %ld bytes, which is \"\n\t\t\t\t\"too small for\\ncryptlib to run in.  To fix this, edit the \"\n\t\t\t\t\"thread-creation function macro in\\nthread.h and recompile \"\n\t\t\t\t\"cryptlib.\\n\", ( long ) stackSize );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\t}\n#endif /* UNIX_THREADS */\n\t}\n\n#ifndef _WIN32_WCE\t/* Windows CE doesn't support ANSI C time functions */\n\nvoid testSystemSpecific2( void )\n\t{\n\tCRYPT_CERTIFICATE cryptCert;\n\tconst time_t theTime = time( NULL ) - 5;\n\tint value = 0, status;\n\n\t/* Make sure that we're running at a standard compliance level */\n\tstatus = cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL, \n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusError( status ) || value != CRYPT_COMPLIANCELEVEL_STANDARD )\n\t\t{\n\t\tprintf( \"Warning: cryptlib has been configured to run at a \"\n\t\t\t\t\"nonstandard certificate\\n         compliance level %d, \"\n\t\t\t\t\"this will upset the results of the self-test\\n\t\t and \"\n\t\t\t\t\"may cause some tests to fail.\\n\", value );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Make sure that the cryptlib and non-cryptlib code use the same time_t\n\t   size (some systems are moving from 32- to 64-bit time_t, which can \n\t   lead to problems if the library and calling code are built with \n\t   different sizes) */\n\tstatus = cryptCreateCert( &cryptCert, CRYPT_UNUSED,\n\t\t\t\t\t\t\t  CRYPT_CERTTYPE_CERTIFICATE );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\t{\n\t\t\tputs( \"Couldn't create certificate object for time sanity-check \"\n\t\t\t\t  \"because certificate\\nuse has been disabled, skipping \"\n\t\t\t\t  \"time sanity check...\\n\" );\n\t\t\treturn;\n\t\t\t}\n\t\tputs( \"Couldn't create certificate object for time sanity-check.\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\tstatus = cryptSetAttributeString( cryptCert, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &theTime, sizeof( time_t ) );\n\tcryptDestroyCert( cryptCert );\n\tif( status == CRYPT_ERROR_PARAM4 )\n\t\t{\n\t\tprintf( \"Warning: This compiler is using a %ld-bit time_t data type, \"\n\t\t\t\t\"which appears to be\\n         different to the one that \"\n\t\t\t\t\"was used when cryptlib was built.  This\\n         situation \"\n\t\t\t\t\"usually occurs when the compiler allows the use of both\\n\"\n\t\t\t\t\"         32- and 64-bit time_t data types and different \"\n\t\t\t\t\"options were\\n         selected for building cryptlib and \"\n\t\t\t\t\"the test app.  To resolve this,\\n         ensure that both \"\n\t\t\t\t\"cryptlib and the code that calls it use the same\\n\"\n\t\t\t\t\"         time_t data type.\\n\", \n\t\t\t\t( long ) sizeof( time_t ) * 8 );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\t}\n#endif /* WinCE */\n"
  },
  {
    "path": "deps/cl345/test/utils.c",
    "content": "/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t  cryptlib Self-test Utility Routines\t\t\t\t\t*\n*\t\t\t\t\t\tCopyright Peter Gutmann 1997-2011\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#include <ctype.h>\n#include \"cryptlib.h\"\n#include \"test/test.h\"\n\n/* Various features can be disabled by configuration options, in order to \n   handle this we need to include the cryptlib config file so that we can \n   selectively disable some tests.\n   \n   Note that this checking isn't perfect, if cryptlib is built in release\n   mode but we include config.h here in debug mode then the defines won't\n   match up because the use of debug mode enables extra options that won't\n   be enabled in the release-mode cryptlib */\n#include \"misc/config.h\"\t/* For algorithm usage */\n#include \"misc/consts.h\"\t/* For DEFAULT_CRYPT_ALGO */\n\n#if defined( __MVS__ ) || defined( __VMCMS__ )\n  /* Suspend conversion of literals to ASCII. */\n  #pragma convlit( suspend )\n#endif /* IBM big iron */\n#if defined( __ILEC400__ )\n  #pragma convert( 0 )\n#endif /* IBM medium iron */\n#ifdef HAS_WIDECHAR\n  #include <wchar.h>\n#endif /* HAS_WIDECHAR */\n#ifndef NDEBUG\n  #include \"misc/config.h\"\n#endif /* NDEBUG */\n\n/* Define the following if cryptlib has been built without keyset support,\n   this loads a fixed key and attaches a pseudo-certificate to it */\n\n/* #define USE_PSEUDOCERTIFICATES */\n#if defined( USE_PSEUDOCERTIFICATES ) && ( defined( _MSC_VER ) || defined( __GNUC__ ) )\n  #pragma message( \"Building with pseudocertificate support\" )\n#endif /* USE_PSEUDOCERTIFICATES && VC++/gcc */\n\n/* The keys used with the test code have associated certs that expire at\n   some point.  The following value defines the number of days before the\n   expiry at which we start printing warnings */\n\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && !defined( NDEBUG )\n  #define EXPIRY_WARN_DAYS\t\t90\n#else\n  #define EXPIRY_WARN_DAYS\t\t30\n#endif /* VC 6 debug/development, give some advance warning */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tUtility Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifndef _WIN32_WCE\n\n/* Since ctime() adds a '\\n' to the string and may return NULL, we wrap it\n   in something that behaves as required */\n\nstatic char *getTimeString( const time_t theTime, const int bufNo )\n\t{\n\tstatic char timeString[ 2 ][ 64 ], *timeStringPtr;\n\n\tassert( bufNo == 0 || bufNo == 1 );\n\n\ttimeStringPtr = ctime( &theTime );\n\tif( timeStringPtr == NULL )\n\t\treturn( \"(Not available)\" );\n\tstrcpy( timeString[ bufNo ], timeStringPtr );\n\ttimeString[ bufNo ][ strlen( timeStringPtr ) - 1 ] = '\\0';\t/* Stomp '\\n' */\n\n\treturn( timeString[ bufNo ] );\n\t}\n#else\n  #define getTimeString( theTime, bufNo )\t\"(No time data available)\"\n#endif /* _WIN32_WCE */\n\n#if defined( _WIN32_WCE ) && _WIN32_WCE < 500\n\nint remove( const char *pathname )\n\t{\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n\n\tmbstowcs( wcBuffer, pathname, strlen( pathname ) + 1 );\n\tDeleteFile( wcBuffer );\n\n\treturn( 0 );\n\t}\n#endif /* WinCE < 5.x */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tGeneral Checking Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Windows-specific file accessibility check */\n\n#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE ) \n\n#pragma comment( lib, \"advapi32\" )\n\nstatic int checkFileAccessibleACL( const char *fileName )\n\t{\n\tBYTE sidBuffer[ 1024 ];\n\tSECURITY_DESCRIPTOR *pSID = ( void * ) sidBuffer;\n\tGENERIC_MAPPING gMapping;\n\tPRIVILEGE_SET psPrivilege;\n\tHANDLE hThreadToken;\n\tDWORD dwPrivilegeLength = sizeof( PRIVILEGE_SET );\n\tDWORD cbNeeded, dwGrantedAccess;\n\tBOOL fStatus; \n\n\tif( !GetFileSecurity( fileName, ( OWNER_SECURITY_INFORMATION | \\\n\t\t\t\t\t\t\t\t\t   GROUP_SECURITY_INFORMATION | \\\n\t\t\t\t\t\t\t\t\t   DACL_SECURITY_INFORMATION), \n\t\t\t\t\t\t   pSID, 1024, &cbNeeded ) )\n\t\t{\n\t\t/* We can't access file security information (presumably due to\n\t\t   insufficient permissions), there's a problem */\n\t\treturn( FALSE );\n\t\t}\n\tif( !ImpersonateSelf( SecurityImpersonation ) )\n\t\treturn( TRUE );\n\tif( !OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hThreadToken ) )\n\t\t{\n\t\tRevertToSelf();\n\t\treturn( TRUE );\n\t\t}\n\tif( !AccessCheck( pSID, hThreadToken, FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE, \n\t\t\t\t\t  &gMapping, &psPrivilege, &dwPrivilegeLength,\n\t\t\t\t\t  &dwGrantedAccess, &fStatus ) )\n\t\t{\n\t\tconst DWORD dwLastError = GetLastError();\n\n\t\tRevertToSelf();\n\t\tCloseHandle( hThreadToken );\n\n\t\t/* If it's FAT32 then there's nothing further to check */\n\t\tif( dwLastError == ERROR_NO_SECURITY_ON_OBJECT || \\\n\t\t\tdwLastError == ERROR_NOT_SUPPORTED )\n\t\t\treturn( TRUE );\n\n\t\treturn( FALSE );\n\t\t}\n\tRevertToSelf();\n\tCloseHandle( hThreadToken );\n\tif( !fStatus )\n\t\t{\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n#endif /* Windows versions with ACLs */\n\n/* Check that a file is accessible.  This is a generic sanity check to make\n   sure that access to keyset files is functioning */\n\nint checkFileAccess( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint length, failedFileNo = 0, status;\n\n\t/* First, check that the file actually exists so that we can return an\n\t   appropriate error message */\n\tif( ( filePtr = fopen( convertFileName( CA_PRIVKEY_FILE ),\n\t\t\t\t\t\t   \"rb\" ) ) == NULL )\n\t\tfailedFileNo = 1;\n\telse\n\t\tfclose( filePtr );\n\tif( failedFileNo == 0 )\n\t\t{\n\t\tif( ( filePtr = fopen( convertFileName( TEST_PRIVKEY_FILE ), \\\n\t\t\t\t\t\t\t   \"rb\" ) ) == NULL )\n\t\t\tfailedFileNo = 2;\n\t\telse\n\t\t\tfclose( filePtr );\n\t\t}\n\tif( failedFileNo > 0 )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't access cryptlib keyset file '%s'.  \"\n\t\t\t\t \"Please make sure\\nthat all the cryptlib files have been \"\n\t\t\t\t \"installed correctly, and the cryptlib\\nself-test is being \"\n\t\t\t\t \"run from the correct directory.\\n\", \n\t\t\t\t( failedFileNo == 1 ) ? CA_PRIVKEY_FILE : TEST_PRIVKEY_FILE );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Now check for accessibility problems due to filesystem permissions.\n\t   This can sometimes occur in odd situations for private-key files \n\t   (which are set up with fairly restrictive ACLs) when the files have \n\t   been copied from one filesystem to another with a different user,\n\t   so the ACLs grant access to the user on the source filesystem rather\n\t   than the destination filesystem (this requires a somewhat messed-\n\t   up copy, since the copier will have had access but the current \n\t   requester won't).\n\n\t   We check for access to two files, the CA private-key file that ships\n\t   with cryptlib and the user private-key file that's created when\n\t   cryptlib is run */\n#if defined( __WINDOWS__ ) && !defined( _WIN32_WCE ) \n\tif( !checkFileAccessibleACL( CA_PRIVKEY_FILE ) )\n\t\tfailedFileNo = 1;\n\telse\n\t\t{\n\t\tif( !checkFileAccessibleACL( TEST_PRIVKEY_FILE ) )\n\t\t\tfailedFileNo = 2;\n\t\t}\n\tif( failedFileNo > 0 )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't access %s cryptlib keyset file \"\n\t\t\t\t \"'%s'\\nfor read/write/delete.  This is probably due to a \"\n\t\t\t\t \"filesystem ACL issue\\nin which the current user has \"\n\t\t\t\t \"insufficient permissions to perform the\\nrequired file \"\n\t\t\t\t \"access.\\n\",\n\t\t\t\t( failedFileNo == 1 ) ? \"pre-generated\" : \"test-run generated\",\n\t\t\t\t( failedFileNo == 1 ) ? CA_PRIVKEY_FILE : TEST_PRIVKEY_FILE );\n\t\treturn( FALSE );\n\t\t}\n#endif /* Windows versions with ACLs */\n\n\t/* Now read the test files and see if there's any problem due to data \n\t   conversion evident */\n\tfilenameFromTemplate( buffer, TESTDATA_FILE_TEMPLATE, 1 );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't open binary data test file to check for data \"\n\t\t\t   \"conversion problems.\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tlength = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tif( length != 16 || \\\n\t\tmemcmp( buffer, \\\n\t\t\t\t\"\\x30\\x82\\x02\\x56\\x30\\x82\\x02\\x52\\x0D\\x0A\\x08\\x40\\x0A\\x74\\x71\\x7A\", 16 ) )\n\t\t{\n\t\tfputs( \"Binary data is corrupt, probably due to being unzipped or \"\n\t\t\t   \"copied onto the\\nsystem in a mode that tries to translate \"\n\t\t\t   \"text data during processing/copying.\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n#ifdef __UNIX__\n\tfilenameFromTemplate( buffer, TESTDATA_FILE_TEMPLATE, 2 );\n\tif( ( filePtr = fopen( buffer, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfputs( \"Couldn't open text data test file to check for data \"\n\t\t\t   \"conversion problems.\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n\tlength = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n\tif( length != 10 || memcmp( buffer, \"test\\ntest\\n\" , 10 ) )\n\t\t{\n\t\tfputs( \"Text data is still in CRLF-delimited format, probably due \"\n\t\t\t   \"to being unzipped\\nwithout the '-a' option to translate \"\n\t\t\t   \"text files for Unix systems.\", outputStream );\n\t\treturn( FALSE );\n\t\t}\n#endif /* __UNIX__ */\n\n\t/* The file exists and is accessible and was copied/installed correctly, \n\t   now try and open it using the cryptlib file access functions.  This\n\t   is a bit of a catch-22 because we're trying to at least open a keyset\n\t   before the self-test has verified the correct functioning of the\n\t   keyset-access code, but in almost all cases it's working OK and this\n\t   provides a useful general sanity-check, since the keyset code would\n\t   fail in any case when we get to it in the self-test */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  CA_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* If file keyset access isn't available, the inability to access\n\t\t   the keyset isn't an error */\n\t\tif( status == CRYPT_ERROR_NOTAVAIL )\n\t\t\treturn( TRUE );\n\n\t\tfprintf( outputStream, \"Couldn't access cryptlib keyset file '%s' \"\n\t\t\t\t \"even though the file\\nexists and is readable.  Please \"\n\t\t\t\t \"make sure that the cryptlib self-test is\\nbeing run from \"\n\t\t\t\t \"the correct directory.\\n\", CA_PRIVKEY_FILE );\n\t\treturn( FALSE );\n\t\t}\n\tcryptKeysetClose( cryptKeyset );\n\n\treturn( TRUE );\n\t}\n\n/* Check that external network sites are accessible, used to detect \n   potential problems with machines stuck behind firewalls */\n\nint checkNetworkAccess( void )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* First we try for Microsoft's NCSI (Network Connection Status Icon) \n\t   site, a canary site used by Windows to check for network connectivity\n\t   that has high availability and is unlikely to be blocked.  If that\n\t   fails we try for a well-known site, Amazon, as a fallback */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n\t\t\t\t\t\t\t  TEXT( \"http://www.msftncsi.com\" ), \n\t\t\t\t\t\t\t  CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn( TRUE );\n\t\t}\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_HTTP,\n\t\t\t\t\t\t\t  TEXT( \"www.amazon.com\" ), CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tcryptKeysetClose( cryptKeyset );\n\t\treturn( TRUE );\n\t\t}\n\n\treturn( FALSE );\n\t}\n\n/* Check whether cryptlib has been built in debug or release mode */\n\nint checkLibraryIsDebug( void )\n\t{\n\tC_CHR buffer[ 256 ];\n\tint length, status;\n\n\t/* Get the description string and see whether it mentions a debug \n\t   build */\n\tstatus = cryptGetAttributeString( CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t  CRYPT_OPTION_INFO_DESCRIPTION, \n\t\t\t\t\t\t\t\t\t  buffer, &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tbuffer[ length ] = '\\0';\n\tif( strstr( buffer, \"debug\" ) != NULL || \\\n\t\tstrstr( buffer, \"Debug\" ) != NULL )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tImport/Export Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Read data from a file */\n\nint readFileData( const char *fileName, const char *description,\n\t\t\t\t  BYTE *buffer, const int bufSize, const int minFileSize,\n\t\t\t\t  const BOOLEAN silent )\n\t{\n\tFILE *filePtr;\n\tint count;\n\n\tif( ( filePtr = fopen( fileName, \"rb\" ) ) == NULL )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't find %s file, skipping test of \"\n\t\t\t\t \"data import...\\n\", description );\n\t\treturn( 0 );\n\t\t}\n\tif( !silent )\n\t\tfprintf( outputStream, \"Testing %s import...\\n\", description );\n\tcount = fread( buffer, 1, bufSize, filePtr );\n\tfclose( filePtr );\n\tif( count >= bufSize )\n\t\t{\n\t\tfputs( \"The data buffer size is too small for the data.  To fix this, \"\n\t\t\t   \"either increase\\nthe BUFFER_SIZE value in \" __FILE__ \" and \"\n\t\t\t   \"recompile the code, or use the\\ntest code with dynamically-\"\n\t\t\t   \"allocated buffers.\", outputStream );\n\t\treturn( 0 );\t\t/* Skip this test and continue */\n\t\t}\n\tif( count < minFileSize )\n\t\t{\n\t\tfprintf( outputStream, \"Read failed, only read %d bytes, at least \"\n\t\t\t\t \"%d required.\\n\", count, minFileSize );\n\t\treturn( 0 );\t\t/* Skip this test and continue */\n\t\t}\n\tif( !silent )\n\t\tfprintf( outputStream, \"%s has size %d bytes.\\n\", description, count );\n\treturn( count );\n\t}\n\n/* Import a certificate object */\n\nint importCertFile( CRYPT_CERTIFICATE *cryptCert, const C_STR fileName )\n\t{\n\tFILE *filePtr;\n\tBYTE buffer[ BUFFER_SIZE ];\n\tint count;\n\n\tif( ( filePtr = fopen( convertFileName( fileName ), \"rb\" ) ) == NULL )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tcount = fread( buffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n    if( count == BUFFER_SIZE )\t/* Item too large for buffer */\n\t\treturn( CRYPT_ERROR_OVERFLOW );\n\n\t/* Import the certificate */\n\treturn( cryptImportCert( buffer, count, CRYPT_UNUSED, cryptCert ) );\n\t}\n\nint importCertFromTemplate( CRYPT_CERTIFICATE *cryptCert,\n\t\t\t\t\t\t\tconst C_STR fileTemplate, const int number )\n\t{\n\tBYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];\n#ifdef UNICODE_STRINGS\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n#endif /* UNICODE_STRINGS */\n\n\tfilenameFromTemplate( filenameBuffer, fileTemplate, number );\n#ifdef UNICODE_STRINGS\n\tmbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );\n\treturn( importCertFile( cryptCert, wcBuffer ) );\n#else\n\treturn( importCertFile( cryptCert, filenameBuffer ) );\n#endif /* UNICODE_STRINGS */\n\t}\n\n/* Export a certificate to a file in the given format */\n\nint exportCertFile( const char *fileName, \n\t\t\t\t\tconst CRYPT_CERTIFICATE certificate,\n\t\t\t\t\tconst CRYPT_CERTFORMAT_TYPE formatType )\n\t{\n\tFILE *filePtr;\n\tBYTE certBuffer[ BUFFER_SIZE ];\n\tint certLength, count, status;\n\n\t/* Export the certificate in the requested format */\n\tstatus = cryptExportCert( certBuffer, BUFFER_SIZE, &certLength, \n\t\t\t\t\t\t\t  formatType, certificate );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* Write it to a file */\n\tfilePtr = fopen( fileName, \"wb\" );\n\tif( filePtr == NULL )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tcount = fwrite( certBuffer, 1, certLength, filePtr );\n\tfclose( filePtr );\n\tif( count != certLength )\n\t\treturn( CRYPT_ERROR_WRITE );\n\n\treturn( CRYPT_OK );\n\t}\n\n/* Read a key from a key file */\n\n#ifndef USE_PSEUDOCERTIFICATES\n\nint getPublicKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t  const C_STR keyName )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\tint status;\n\n\t/* Read the key from the keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't open keyset '%s', status %d, \"\n\t\t\t\t \"line %d.\\n\", keysetName, status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetPublicKey( cryptKeyset, cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\tkeyName );\n\tif( cryptStatusError( status ) )\n\t\tprintExtError( cryptKeyset, \"cryptGetPublicKey\", status, __LINE__ );\n\tcryptKeysetClose( cryptKeyset );\n\treturn( status );\n\t}\n\nint getPrivateKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t   const C_STR keyName, const C_STR password )\n\t{\n\tCRYPT_KEYSET cryptKeyset;\n\ttime_t validFrom;\n#ifndef _WIN32_WCE\n\ttime_t validTo;\n#endif /* _WIN32_WCE */\n\tint dummy, status;\n\n\t/* Read the key from the keyset */\n\tstatus = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,\n\t\t\t\t\t\t\t  keysetName, CRYPT_KEYOPT_READONLY );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tstatus = cryptGetPrivateKey( cryptKeyset, cryptContext, CRYPT_KEYID_NAME,\n\t\t\t\t\t\t\t\t keyName, password );\n\tif( cryptStatusError( status ) )\n\t\tprintExtError( cryptKeyset, \"cryptGetPrivateKey\", status, __LINE__ );\n\tcryptKeysetClose( cryptKeyset );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\n\t/* If the key has a certificate attached, make sure it's still valid \n\t   before we hand it back to the self-test functions that will report \n\t   the problem as being with the self-test rather than with the \n\t   certificate.  We check not just the expiry date but also the expiry \n\t   interval to make sure that we don't get false positives on short-\n\t   validity certificates */\n\tstatus = cryptGetAttributeString( *cryptContext,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDFROM, &validFrom, &dummy );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\t/* There's no certificate there, this isn't an error */\n\t\treturn( CRYPT_OK );\n\t\t}\n#ifndef _WIN32_WCE\n\tstatus = cryptGetAttributeString( *cryptContext,\n\t\t\t\t\tCRYPT_CERTINFO_VALIDTO, &validTo, &dummy );\n\tif( cryptStatusError( status ) )\n\t\treturn( status );\n\tif( ( validTo - validFrom > ( 86400 * EXPIRY_WARN_DAYS ) ) && \\\n\t\tvalidTo - time( NULL ) <= ( 86400 * EXPIRY_WARN_DAYS ) )\n\t\t{\n\t\tconst time_t currentTime = time( NULL );\n\n\t\tfputs( \"                         ********************\", \n\t\t\t   outputStream );\n\t\tif( validTo <= currentTime )\n\t\t\t{\n\t\t\tfputs( \"Warning: This key has expired.  Certificate-related \"\n\t\t\t\t   \"operations will fail or\\n         result in error \"\n\t\t\t\t   \"messages from the test code.\", outputStream );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( validTo - currentTime <= 86400 )\n\t\t\t\t{\n\t\t\t\tfputs( \"Warning: This key expires today.  Certificate-\"\n\t\t\t\t\t   \"related operations may fail\\n         or result in \"\n\t\t\t\t\t   \"error messages from the test code.\", outputStream );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"Warning: This key will expire in \" \n\t\t\t\t\t\t TIMET_FORMAT \" days.  Certificate-related \"\n\t\t\t\t\t\t \"operations\\n         may fail or result in error \"\n\t\t\t\t\t\t \"messages from the test code.\\n\",\n\t\t\t\t\t\t( validTo - currentTime ) / 86400 );\n\t\t\t\t}\n\t\t\t}\n\t\tfputs( \"                         ********************\", \n\t\t\t   outputStream );\n\t\tfprintf( outputStream, \"Hit a key...\" );\n\t\tgetchar();\n\t\tfprintf( outputStream, \"\\r\" );\n\t\t}\n#endif /* _WIN32_WCE */\n\treturn( CRYPT_OK );\n\t}\n#else\n\nC_RET cryptCreateAttachedCert( C_IN CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t   C_IN void C_PTR certObject,\n\t\t\t\t\t\t\t   C_IN int certObjectLength );\n\n/* Import a certificate as a raw data object and attach it to a context as a \n   pseudo-certificate */\n\nstatic int addPseudoCertificate( const CRYPT_CONTEXT cryptContext,\n\t\t\t\t\t\t\t\t const int certNo )\n\t{\n\tFILE *filePtr;\n\tBYTE certBuffer[ BUFFER_SIZE ];\n\tchar filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\tint length = 0;\n\n\tfilenameFromTemplate( filenameBuffer, PSEUDOCERT_FILE_TEMPLATE, certNo );\n\tif( ( filePtr = fopen( filenameBuffer, \"rb\" ) ) == NULL )\n\t\treturn( CRYPT_ERROR_OPEN );\n\tlength = fread( certBuffer, 1, BUFFER_SIZE, filePtr );\n\tfclose( filePtr );\n    if( length <= 16 || length >= BUFFER_SIZE )\n\t\treturn( CRYPT_ERROR_READ );\n\treturn( cryptCreateAttachedCert( cryptContext, certBuffer, length ) );\n\t}\n\nint getPublicKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t  const C_STR keyName )\n\t{\n\t/* Load a fixed RSA public key and attached the pseudo-certificate */\n\tif( !loadRSAContexts( CRYPT_UNUSED, cryptContext, NULL ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\treturn( addPseudoCertificate( *cryptContext, 1 ) );\n\t}\n\nint getPrivateKey( CRYPT_CONTEXT *cryptContext, const C_STR keysetName,\n\t\t\t\t   const C_STR keyName, const C_STR password )\n\t{\n\t/* Load a fixed RSA public key and attached the pseudo-certificate */\n\tif( !loadRSAContexts( CRYPT_UNUSED, NULL, cryptContext ) )\n\t\treturn( CRYPT_ERROR_NOTAVAIL );\n\treturn( addPseudoCertificate( *cryptContext, 1 ) );\n\t}\n#endif /* USE_PSEUDOCERTIFICATES */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tKey File Access Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Key file and password-handling access routines */\n\nconst C_STR getKeyfileName( const KEYFILE_TYPE type,\n\t\t\t\t\t\t\tconst BOOLEAN isPrivKey )\n\t{\n\tstatic char filenameBuffer[ FILENAME_BUFFER_SIZE ];\n\n\tswitch( type )\n\t\t{\n\t\tcase KEYFILE_X509:\n\t\t\treturn( USER_PRIVKEY_FILE );\n\t\tcase KEYFILE_X509_ALT:\n\t\t\tfilenameFromTemplate( filenameBuffer, USER_PRIVKEY_FILE_TEMPLATE, 2 );\n\t\t\treturn( filenameBuffer );\n\t\tcase KEYFILE_PGP:\n\t\tcase KEYFILE_PGP_SPECIAL:\n\t\t\treturn( isPrivKey ? PGP_PRIVKEY_FILE : PGP_PUBKEY_FILE );\n\t\tcase KEYFILE_OPENPGP_HASH:\n\t\t\treturn( isPrivKey ? OPENPGP_PRIVKEY_HASH_FILE : OPENPGP_PUBKEY_HASH_FILE );\n\t\tcase KEYFILE_OPENPGP_AES:\n\t\tcase KEYFILE_OPENPGP_AES_KEYID:\n\t\t\treturn( isPrivKey ? OPENPGP_PRIVKEY_AES_FILE : OPENPGP_PUBKEY_AES_FILE );\n\t\tcase KEYFILE_OPENPGP_CAST:\n\t\t\treturn( OPENPGP_PRIVKEY_CAST_FILE );\n\t\tcase KEYFILE_OPENPGP_RSA:\n\t\t\treturn( isPrivKey ? OPENPGP_PRIVKEY_RSA_FILE : OPENPGP_PUBKEY_RSA_FILE );\n\t\tcase KEYFILE_OPENPGP_MULT:\n\t\t\treturn( OPENPGP_PUBKEY_MULT_FILE );\n\t\tcase KEYFILE_OPENPGP_PARTIAL:\n\t\t\treturn( OPENPGP_PRIVKEY_PART_FILE );\n\t\tcase KEYFILE_NAIPGP:\n\t\t\treturn( isPrivKey ? NAIPGP_PRIVKEY_FILE : NAIPGP_PUBKEY_FILE );\n\t\tcase KEYFILE_OPENPGP_BOUNCYCASTLE:\n\t\t\treturn( OPENPGP_PRIVKEY_BC_FILE );\n\t\tcase KEYFILE_OPENPGP_ECC:\n\t\t\treturn( isPrivKey ? OPENPGP_PRIVKEY_ECC_FILE : OPENPGP_PUBKEY_ECC_FILE );\n\t\t}\n\tassert( 0 );\n\treturn( TEXT( \"notfound\" ) );\n\t}\n\nconst C_STR getKeyfilePassword( const KEYFILE_TYPE type )\n\t{\n\tswitch( type )\n\t\t{\n\t\tcase KEYFILE_X509:\n\t\tcase KEYFILE_X509_ALT:\n\t\t\treturn( TEST_PRIVKEY_PASSWORD );\n\t\tcase KEYFILE_PGP:\n\t\tcase KEYFILE_OPENPGP_HASH:\n\t\tcase KEYFILE_OPENPGP_RSA:\n\t\tcase KEYFILE_OPENPGP_ECC:\n\t\t\treturn( TEXT( \"test1\" ) );\n\t\tcase KEYFILE_NAIPGP:\n\t\t\treturn( TEXT( \"test10\" ) );\n\t\tcase KEYFILE_OPENPGP_AES:\n\t\tcase KEYFILE_OPENPGP_AES_KEYID:\n\t\t\treturn( TEXT( \"testkey\" ) );\n\t\tcase KEYFILE_OPENPGP_CAST:\n\t\tcase KEYFILE_OPENPGP_BOUNCYCASTLE:\n\t\t\treturn( TEXT( \"test\" ) );\n\t\tcase KEYFILE_OPENPGP_PARTIAL:\n\t\t\treturn( TEXT( \"def\" ) );\n\t\t}\n\tassert( 0 );\n\treturn( TEXT( \"notfound\" ) );\n\t}\n\nconst C_STR getKeyfileUserID( const KEYFILE_TYPE type,\n\t\t\t\t\t\t\t  const BOOLEAN isPrivKey )\n\t{\n\t/* If possible we specify user IDs for keys in the middle of the keyring\n\t   to make sure that we test the ability to correctly handle multiple\n\t   keys */\n\tswitch( type )\n\t\t{\n\t\tcase KEYFILE_X509:\n\t\tcase KEYFILE_X509_ALT:\n\t\t\treturn( USER_PRIVKEY_LABEL );\n\t\tcase KEYFILE_PGP:\n\t\tcase KEYFILE_OPENPGP_BOUNCYCASTLE:\n\t\t\treturn( TEXT( \"test\" ) );\n\t\tcase KEYFILE_PGP_SPECIAL:\n\t\t\treturn( TEXT( \"suzuki\" ) );\n\t\tcase KEYFILE_NAIPGP:\n\t\t\treturn( isPrivKey ? TEXT( \"test\" ) : TEXT( \"test cryptlib\" ) );\n\t\tcase KEYFILE_OPENPGP_HASH:\n\t\tcase KEYFILE_OPENPGP_RSA:\n\t\tcase KEYFILE_OPENPGP_ECC:\n\t\t\treturn( TEXT( \"test1\" ) );\n\t\tcase KEYFILE_OPENPGP_MULT:\n\t\t\treturn( TEXT( \"NXX2502\" ) );\n\t\tcase KEYFILE_OPENPGP_AES:\n\t\t\treturn( TEXT( \"Max Mustermann\" ) );\n\t\tcase KEYFILE_OPENPGP_AES_KEYID:\n\t\t\treturn( TEXT( \"0xB97CA167C29E7D18\" ) );\n\t\tcase KEYFILE_OPENPGP_CAST:\n\t\t\treturn( TEXT( \"Trond\" ) );\n\t\t}\n\tassert( 0 );\n\treturn( TEXT( \"notfound\" ) );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOS Helper Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x310 )\n\n/* BC++ 3.x doesn't have mbstowcs() in the default library, and also defines\n   wchar_t as char (!!) so we fake it here */\n\nsize_t mbstowcs( char *pwcs, const char *s, size_t n )\n\t{\n\tmemcpy( pwcs, s, n );\n\treturn( n );\n\t}\n#endif /* BC++ 3.1 or lower */\n\n/* When using multiple threads we need to delay one thread for a small\n   amount of time, unfortunately there's no easy way to do this with pthreads\n   so we have to provide the following wrapper function that makes an\n   (implementation-specific) attempt at it */\n\n#if defined( UNIX_THREADS ) || defined( WINDOWS_THREADS ) || defined( OS2_THREADS )\n\n#if defined( UNIX_THREADS )\n  /* This include must be outside the function to avoid weird compiler errors\n\t on some systems */\n  #include <sys/time.h>\n#endif /* UNIX_THREADS */\n\nvoid delayThread( const int seconds )\n\t{\n#if defined( UNIX_THREADS )\n\tstruct timeval tv = { 0 };\n\n\t/* The following should put a thread to sleep for a second on most\n\t   systems since the select() should be a thread-safe one in the\n\t   presence of pthreads */\n\ttv.tv_sec = seconds;\n\tselect( 1, NULL, NULL, NULL, &tv );\n#elif defined( WINDOWS_THREADS )\n\tSleep( seconds * 1000 );\n#endif /* Threading system-specific delay functions */\n\t}\n#endif /* Systems with threading support */\n\n/* Helper functions to make tracking down errors on systems with no console\n   a bit less painful.  These just use the debug console as stdout */\n\n#ifdef _WIN32_WCE\n\nvoid wcPrintf( const char *format, ... )\n\t{\n\twchar_t wcBuffer[ 1024 ];\n\tchar buffer[ 1024 ];\n\tva_list argPtr;\n\n\tva_start( argPtr, format );\n\tvsprintf( buffer, format, argPtr );\n\tva_end( argPtr );\n\tmbstowcs( wcBuffer, buffer, strlen( buffer ) + 1 );\n\tNKDbgPrintfW( wcBuffer );\n\t}\n\nvoid wcPuts( const char *string )\n\t{\n\twcPrintf( \"%s\\n\", string );\n\t}\n#endif /* Console-less environments */\n\n/* Conversion functions used to get Unicode input into generic ASCII\n   output */\n\n#ifdef UNICODE_STRINGS\n\n/* Get a filename in an appropriate format for the C runtime library */\n\nconst char *convertFileName( const C_STR fileName )\n\t{\n\tstatic char fileNameBuffer[ FILENAME_BUFFER_SIZE ];\n\n\twcstombs( fileNameBuffer, fileName, wcslen( fileName ) + 1 );\n\treturn( fileNameBuffer );\n\t}\n\n/* Map a filename template to an actual filename, input in Unicode, output in\n   ASCII */\n\nvoid filenameFromTemplate( char *buffer, const wchar_t *fileTemplate,\n\t\t\t\t\t\t   const int count )\n\t{\n\twchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];\n\tint length;\n\n\tlength = _snwprintf( wcBuffer, FILENAME_BUFFER_SIZE, fileTemplate,\n\t\t\t\t\t\t count );\n\twcstombs( buffer, wcBuffer, length + 1 );\n\t}\n\nvoid filenameParamFromTemplate( wchar_t *buffer,\n\t\t\t\t\t\t\t\tconst wchar_t *fileTemplate,\n\t\t\t\t\t\t\t\tconst int count )\n\t{\n\t_snwprintf( buffer, FILENAME_BUFFER_SIZE, fileTemplate, count );\n\t}\n#endif /* UNICODE_STRINGS */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tThread Support Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#if defined( WINDOWS_THREADS )\n\nstatic HANDLE hMutex;\n\nvoid createMutex( void )\n\t{\n\thMutex = CreateMutex( NULL, FALSE, NULL );\n\t}\nvoid acquireMutex( void )\n\t{\n\tif( WaitForSingleObject( hMutex, 30000 ) == WAIT_TIMEOUT )\n\t\t{\n\t\tfputs( \"Warning: Couldn't acquire mutex after 30s wait.  Press a \"\n\t\t\t   \"key to continue.\", outputStream );\n\t\tgetchar();\n\t\t}\n\t}\nint waitMutex( void )\n\t{\n\tif( WaitForSingleObject( hMutex, 30000 ) == WAIT_TIMEOUT )\n\t\treturn( CRYPT_ERROR_TIMEOUT );\n\t\n\t/* Since this is merely a synchronisation operation in which a later \n\t   thread waits to catch up to an earlier one, we release the mutex again\n\t   so other threads can get in */\n\treleaseMutex();\n\treturn( CRYPT_OK );\n\t}\nvoid releaseMutex( void )\n\t{\n\tif( !ReleaseMutex( hMutex ) )\n\t\t{\n\t\tfputs( \"Warning: Couldn't release mutex.  Press a key to continue.\", \n\t\t\t   outputStream );\n\t\tgetchar();\n\t\t}\n\t}\nvoid destroyMutex( void )\n\t{\n\tCloseHandle( hMutex );\n\t}\n\nvoid waitForThread( const HANDLE hThread )\n\t{\n\tif( WaitForSingleObject( hThread, 15000 ) == WAIT_TIMEOUT )\n\t\t{\n\t\tfputs( \"Warning: Server thread is still active due to session \"\n\t\t\t   \"negotiation failure,\\n         this will cause an error \"\n\t\t\t   \"condition when cryptEnd() is called due\\n         to \"\n\t\t\t   \"resources remaining allocated, specifically because the \"\n\t\t\t   \"client\\n          thread will call cryptEnd() while the \"\n\t\t\t   \"server thread is still\\n         active, resulting in the \"\n\t\t\t   \"server thread object cleanup failing\\n         because \"\n\t\t\t   \"they've already been cleaned up in cryptEnd().  Press a \"\n\t\t\t   \"key\\n         to continue.\", outputStream );\n\t\tgetchar();\n\t\t}\n\tCloseHandle( hThread );\n\t}\n#elif defined( UNIX_THREADS )\n\nstatic pthread_mutex_t mutex;\n\nvoid createMutex( void )\n\t{\n\tpthread_mutex_init( &mutex, NULL );\n\t}\nvoid acquireMutex( void )\n\t{\n\tpthread_mutex_lock( &mutex );\n\t}\nint waitMutex( void )\n\t{\n\tpthread_mutex_lock( &mutex );\n\t\n\t/* Since this is merely a synchronisation operation in which a later \n\t   thread waits to catch up to an earlier one, we release the mutex again\n\t   so other threads can get in */\n\treleaseMutex();\n\treturn( CRYPT_OK );\n\t}\nvoid releaseMutex( void )\n\t{\n\tpthread_mutex_unlock( &mutex );\n\t}\nvoid destroyMutex( void )\n\t{\n\tpthread_mutex_destroy( &mutex );\n\t}\n\nvoid waitForThread( const pthread_t hThread )\n\t{\n\tif( pthread_join( hThread, NULL ) < 0 )\n\t\t{\n\t\tfputs( \"Warning: Server thread is still active due to session \"\n\t\t\t   \"negotiation failure,\\n         this will cause an error \"\n\t\t\t   \"condition when cryptEnd() is called due\\n         to \"\n\t\t\t   \"resources remaining allocated, specifically because the \"\n\t\t\t   \"client\\n          thread will call cryptEnd() while the \"\n\t\t\t   \"server thread is still\\n         active, resulting in the \"\n\t\t\t   \"server thread object cleanup failing\\n         because \"\n\t\t\t   \"they've already been cleaned up in cryptEnd().  Press a \"\n\t\t\t   \"key\\n         to continue.\", outputStream );\n\t\tgetchar();\n\t\t}\n\t}\n\n#else\n\nvoid createMutex( void )\n\t{\n\t}\nvoid acquireMutex( void )\n\t{\n\t}\nvoid releaseMutex( void )\n\t{\n\t}\nint waitMutex( void )\n\t{\n\treturn( CRYPT_OK );\n\t}\nvoid destroyMutex( void )\n\t{\n\t}\n#endif /* WINDOWS_THREADS */\n\n#if defined( WINDOWS_THREADS ) || defined( UNIX_THREADS )\n\n/* Dispatch multiple client and server threads and wait for them to exit */\n\nint multiThreadDispatch( THREAD_FUNC clientFunction,\n\t\t\t\t\t\t THREAD_FUNC serverFunction, const int noThreads )\n\t{\n\tTHREAD_HANDLE hClientThreads[ MAX_NO_THREADS ];\n\tTHREAD_HANDLE hServerThreads[ MAX_NO_THREADS ];\n\tint sessionID[ MAX_NO_THREADS ];\n\tint i;\n\n\tassert( noThreads <= MAX_NO_THREADS );\n\n\t/* Set up the session ID values */\t\n\tfor( i = 0; i < MAX_NO_THREADS; i++ )\n\t\tsessionID[ i ] = i;\n\n\t/* Start the sessions and wait for them initialise.  We have to wait for\n\t   some time since the multiple private key reads can take awhile */\n\tfor( i = 0; i < noThreads; i++ )\n\t\t{\n#ifdef WINDOWS_THREADS\n\t\tunsigned int threadID;\n\n\t\thServerThreads[ i ] = ( HANDLE ) \\\n\t\t\t\t\t\t_beginthreadex( NULL, 0, serverFunction,\n\t\t\t\t\t\t\t\t\t\t&sessionID[ i ], 0, &threadID );\n#else\n\t\tpthread_t threadHandle;\n\n\t\thServerThreads[ i ] = 0;\n\t\tif( pthread_create( &threadHandle, NULL, serverFunction,\n\t\t\t\t\t\t\t&sessionID[ i ] ) == 0 )\n\t\t\thServerThreads[ i ] = threadHandle;\n#endif /* Windows vs. pthreads */\n\t\t}\n\tdelayThread( 3 );\n\n\t/* Connect to the local server */\n\tfor( i = 0; i < noThreads; i++ )\n\t\t{\n#ifdef WINDOWS_THREADS\n\t\tunsigned int threadID;\n\n\t\thClientThreads[ i ] = ( HANDLE ) \\\n\t\t\t\t\t\t_beginthreadex( NULL, 0, clientFunction,\n\t\t\t\t\t\t\t\t\t\t&sessionID[ i ], 0, &threadID );\n#else\n\t\tpthread_t threadHandle;\n\n\t\thClientThreads[ i ] = 0;\n\t\tif( pthread_create( &threadHandle, NULL, clientFunction,\n\t\t\t\t\t\t\t&sessionID[ i ] ) == 0 )\n\t\t\thClientThreads[ i ] = threadHandle;\n#endif /* Windows vs. pthreads */\n\t\t}\n#ifdef WINDOWS_THREADS\n\tif( WaitForMultipleObjects( noThreads, hServerThreads, TRUE,\n\t\t\t\t\t\t\t\t60000 ) == WAIT_TIMEOUT || \\\n\t\tWaitForMultipleObjects( noThreads, hClientThreads, TRUE,\n\t\t\t\t\t\t\t\t60000 ) == WAIT_TIMEOUT )\n#else\n\t/* Posix doesn't have an ability to wait for multiple threads for mostly\n\t   religious reasons (\"That's not how we do things around here\") so we\n\t   just wait for two token threads */\n\tpthread_join( hServerThreads[ 0 ], NULL );\n\tpthread_join( hClientThreads[ 0 ], NULL );\n#endif /* Windows vs. pthreads */\n\t\t{\n\t\tfputs( \"Warning: Server threads are still active due to session \"\n\t\t\t   \"negotiation failure,\\n         this will cause an error \"\n\t\t\t   \"condition when cryptEnd() is called due\\n         to \"\n\t\t\t   \"resources remaining allocated.  Press a key to continue.\", \n\t\t\t   outputStream );\n\t\tgetchar();\n\t\t}\n#ifdef WINDOWS_THREADS\n\tfor( i = 0; i < noThreads; i++ )\n\t\t{\n\t\tif( hServerThreads[ i ] != 0 )\n\t\t\tCloseHandle( hServerThreads[ i ] );\n\t\t}\n\tfor( i = 0; i < noThreads; i++ )\n\t\t{\n\t\tif( hClientThreads[ i ] != 0 )\n\t\t\tCloseHandle( hClientThreads[ i ] );\n\t\t}\n#endif /* Windows vs. pthreads */\n\n\treturn( TRUE );\n\t}\n#endif /* Windows/Unix threads */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tTiming Support Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get high-resolution timing info */\n\n#ifdef USE_TIMING\n\n#ifdef __WINDOWS__ \n  /* This needs an explicit -lm on Unix systems so we only enable it for \n     Windows */\n  #define USE_SD\n  #include <math.h>\n#endif /* __WINDOWS__ */\n\n#ifdef USE_32BIT_TIME\n\nHIRES_TIME timeDiff( HIRES_TIME startTime )\n\t{\n\tHIRES_TIME timeLSB, timeDifference;\n\n#ifdef __WINDOWS__\n  #if defined( _MSC_VER ) && defined( _M_X64 )\n\tconst unsigned __int64 value = __rdtsc();\n\ttimeLSB = ( HIRES_TIME ) value;\n  #else\n\tLARGE_INTEGER performanceCount;\n\n\t/* Sensitive to context switches */\n\tQueryPerformanceCounter( &performanceCount );\n\ttimeLSB = performanceCount.LowPart;\n  #endif /* __WIN64__ */\n#else\n  #if 0\t/* Requires linking with librt, not always present */\n\tstruct timespec ts;\n\n\tclock_gettime( CLOCK_PROCESS_CPUTIME_ID, &ts );\n\ttimeLSB = ts.tv_nsec;\n  #else\n\tstruct timeval tv;\n\n\t/* Only accurate to about 1us */\n\tgettimeofday( &tv, NULL );\n\ttimeLSB = tv.tv_usec;\n  #endif /* 0 */\n#endif /* Windows vs.Unix high-res timing */\n\n\t/* If we're getting an initial time, return an absolute value */\n\tif( !startTime )\n\t\treturn( timeLSB );\n\n\t/* We're getting a time difference */\n\tif( startTime < timeLSB )\n\t\ttimeDifference = timeLSB - startTime;\n\telse\n\t\t{\n#ifdef __WINDOWS__\n\t\t/* Windows rolls over at INT_MAX */\n\t\ttimeDifference = ( 0xFFFFFFFFUL - startTime ) + 1 + timeLSB;\n#else\n\t\t/* gettimeofday() rolls over at 1M us */\n\t\ttimeDifference = ( 1000000L - startTime ) + timeLSB;\n#endif /* __WINDOWS__ */\n\t\t}\n\tif( timeDifference <= 0 )\n\t\t{\n\t\tfprintf( outputStream, \"Error: Time difference = \" \n\t\t\t\t HIRES_FORMAT_SPECIFIER \", startTime = \" \n\t\t\t\t HIRES_FORMAT_SPECIFIER \", endTime = \" \n\t\t\t\t HIRES_FORMAT_SPECIFIER \".\\n\",\n\t\t\t\ttimeDifference, startTime, timeLSB );\n\t\treturn( 1 );\n\t\t}\n\treturn( timeDifference );\n\t}\n#else\n\nHIRES_TIME timeDiff( HIRES_TIME startTime )\n\t{\n\tHIRES_TIME timeValue;\n\n#ifdef __WINDOWS__\n\tLARGE_INTEGER performanceCount;\n\n\t/* Sensitive to context switches */\n\tQueryPerformanceCounter( &performanceCount );\n\ttimeValue = performanceCount.QuadPart;\n#else\n  #if 1\n\ttimespec ts;\n\n\tclock_gettime( CLOCK_PROCESS_CPUTIME_ID, &ts );\n\ttimeValue = ( ( ( HIRES_TIME ) ts.tv_sec ) * 1000000000 ) | tv.tv_nsec;\n  #else\n\tstruct timeval tv;\n\n\t/* Only accurate to about 1us */\n\tgettimeofday( &tv, NULL );\n\ttimeValue = ( ( ( HIRES_TIME ) tv.tv_sec ) * 1000000 ) | tv.tv_usec;\n  #endif /* 0 */\n#endif /* Windows vs.Unix high-res timing */\n\n\tif( !startTime )\n\t\treturn( timeValue );\n\treturn( timeValue - startTime );\n\t}\n#endif /* USE_32BIT_TIME */\n\n/* Print timing info.  This gets a bit hairy because we're actually counting \n   low-level timer ticks rather than abstract thread times which means that \n   we'll be affected by things like context switches.  There are two \n   approaches to this:\n\n\t1. Take the fastest time, which will be the time least affected by \n\t   system overhead.\n\n\t2. Apply standard statistical techniques to weed out anomalies.  Since \n\t   this is just for testing purposes all we do is discard any results \n\t   out by more than 10%, which is crude but reasonably effective.  A \n\t   more rigorous approach is to discards results more than n standard \n\t   deviations out, but this gets screwed up by the fact that a single \n\t   context switch of 20K ticks can throw out results from an execution \n\t   time of only 50 ticks.  In any case (modulo context switches) the \n\t   fastest, 10%-out, and 2 SD out times are all within about 1% of each \n\t   other so all methods are roughly equally accurate */\n\nstatic int timeDisplayMean( HIRES_TIME *times, const int noTimes )\n\t{\n\tHIRES_TIME timeSum = 0, timeAvg, timeDelta;\n\tHIRES_TIME timeMin = 1000000L;\n\tHIRES_TIME timeCorrSum10 = 0;\n\tHIRES_TIME avgTime;\n#ifdef __WINDOWS__\n\tLARGE_INTEGER performanceCount;\n#endif /* __WINDOWS__ */\n#ifdef USE_SD\n\tHIRES_TIME timeCorrSumSD = 0;\n\tdouble stdDev;\n\tint timesCountSD = 0;\n#endif /* USE_SD */\n\tlong timeMS, ticksPerSec;\n\tconst int startIndex = ( noTimes == 1 ) ? 0 : 1;\n\t\t/* If we're using a multitude of readings we discard the first one,\n\t\t   which is always unusually high due to startup overhead */\n\tint i, timesCount10 = 0;\n\n\t/* Try and get the clock frequency */\n#ifdef __WINDOWS__\n\tQueryPerformanceFrequency( &performanceCount );\n\tticksPerSec = performanceCount.LowPart;\n#else\n\tticksPerSec = 1000000;\n#endif /* __WINDOWS__ */\n\tif( noTimes > 1 )\n\t\t{\n\t\tfprintf( outputStream, \"Times given in clock ticks of frequency \" );\n#ifdef __WINDOWS__\n\t\tfprintf( outputStream, \"%ld\", ticksPerSec );\n#else\n\t\tfprintf( outputStream, \"~1M\" );\n#endif /* __WINDOWS__ */\n\t\tfprintf( outputStream, \" ticks per second.\\n\\n\" );\n\t\t}\n\n\t/* Find the mean execution time */\n\tfor( i = startIndex; i < noTimes; i++ )\n\t\ttimeSum += times[ i ];\n\ttimeAvg = timeSum / noTimes;\n\ttimeDelta = timeAvg / 10;\t/* 10% variation */\n\n\t/* Find the fastest overall time */\n\tfor( i = startIndex; i < noTimes; i++ )\n\t\t{\n\t\tif( times[ i ] < timeMin )\n\t\t\ttimeMin = times[ i ];\n\t\t}\n\n\t/* Find the mean time, discarding anomalous results more than 10% out.  \n\t   We cast the values to longs in order to (portably) print them, if we \n\t   want to print the full 64-bit values we have to use nonstandard \n\t   extensions like \"%I64d\" (for Win32) */\n\tfor( i = startIndex; i < noTimes; i++ )\n\t\t{\n\t\tif( times[ i ] > timeAvg - timeDelta && \\\n\t\t\ttimes[ i ] < timeAvg + timeDelta )\n\t\t\t{\n\t\t\ttimeCorrSum10 += times[ i ];\n\t\t\ttimesCount10++;\n\t\t\t}\n\t\t}\n\tif( timesCount10 <= 0 )\n\t\t{\n\t\tfprintf( outputStream, \"Error: No times within +/-%ld of %ld.\\n\",\n\t\t\t\t( long ) timeDelta, ( long ) timeAvg );\n\t\treturn( -1 );\n\t\t}\n\tavgTime = timeCorrSum10 / timesCount10;\n\tif( noTimes > 1 )\n\t\t{\n\t\tfprintf( outputStream, \"Time: min.= %ld, avg.= %ld \", \n\t\t\t\t ( long ) timeMin, ( long ) avgTime );\n\t\t}\n\ttimeMS = ( avgTime * 1000 ) / ticksPerSec;\n#if 0\t/* Print difference to fastest time, usually only around 1% */\n\tfprintf( outputStream, \"(%4d)\", \n\t\t\t ( timeCorrSum10 / timesCount10 ) - timeMin );\n#endif /* 0 */\n\n#ifdef USE_SD\n\t/* Find the standard deviation */\n\tfor( i = startIndex; i < noTimes; i++ )\n\t\t{\n\t\tconst HIRES_TIME timeDev = times[ i ] - timeAvg;\n\n\t\ttimeCorrSumSD += ( timeDev * timeDev );\n\t\t}\n\tstdDev = timeCorrSumSD / noTimes;\n\tstdDev = sqrt( stdDev );\n\tfprintf( outputStream, \", SD = %ld\", ( long ) stdDev );\n\n\t/* Find the mean time, discarding anomalous results more than two \n\t   standard deviations out */\n\ttimeCorrSumSD = 0;\n\ttimeDelta = ( HIRES_TIME ) stdDev * 2;\n\tfor( i = startIndex; i < noTimes; i++ )\n\t\t{\n\t\tif( times[ i ] > timeAvg - timeDelta && \\\n\t\t\ttimes[ i ] < timeAvg + timeDelta )\n\t\t\t{\n\t\t\ttimeCorrSumSD += times[ i ];\n\t\t\ttimesCountSD++;\n\t\t\t}\n\t\t}\n\tif( timesCountSD == 0 )\n\t\ttimesCountSD++;\t/* Context switch, fudge it */\n\tfprintf( outputStream, \", corr.mean = %ld\", \n\t\t\t ( long ) ( timeCorrSumSD / timesCountSD ) );\n\n#if 0\t/* Print difference to fastest and mean times, usually only around\n\t\t   1% */\n\tfprintf( outputStream, \" (dF = %4d, dM = %4d)\\n\",\n\t\t\t ( timeCorrSumSD / timesCountSD ) - timeMin,\n\t\t\t abs( ( timeCorrSumSD / timesCountSD ) - \\\n\t\t\t\t  ( timeCorrSum10 / timesCount10 ) ) );\n#endif /* 0 */\n#endif /* USE_SD */\n\n\t/* Print the times in ms */\n\tif( noTimes > 1 )\n\t\tfprintf( outputStream, \"\\n  Per-op time = \" );\n\tif( timeMS <= 0 )\n\t\tfprintf( outputStream, \"< 1\" );\n\telse\n\t\tfprintf( outputStream, \"%ld\", timeMS );\n\tfprintf( outputStream, \" ms.\\n\" );\n\n\treturn( ( timeMS <= 0 ) ? 1 : timeMS );\n\t}\n\nint timeDisplay( HIRES_TIME timeValue )\n\t{\n\treturn( timeDisplayMean( &timeValue, 1 ) );\n\t}\n\n/* Timing-attack evaluation code */\n\nint testTimingAttackConv( void )\n\t{\n\tCRYPT_CONTEXT cryptContext, decryptContext;\n\tCRYPT_CONTEXT sessionKeyContext;\n\tHIRES_TIME times[ 1000 ];\n\tBYTE encryptedKeyBlob[ 1024 ];\n\tint length, i, status;\n\n\t/* Create the contexts needed for the decryption timing checks */\n\tstatus = cryptCreateContext( &sessionKeyContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = cryptGenerateKey( sessionKeyContext );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tstatus = loadRSAContexts( CRYPT_UNUSED, &cryptContext, &decryptContext );\n\tif( !status )\n\t\treturn( FALSE );\n\n\t/* Create the encrypted key blob */\n\tstatus = cryptExportKey( encryptedKeyBlob, 1024, &length, cryptContext, \n\t\t\t\t\t\t\t sessionKeyContext );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptExportKeyEx() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tif( length != 174 )\n\t\t{\n\t\tfprintf( outputStream, \"Encrypted key should be %d bytes, was %d, \"\n\t\t\t\t \"line %d.\\n\", 174, length, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tcryptDestroyContext( sessionKeyContext );\n\n\t/* Determine the time for the unmodified decrypt */\n#if 0\n\tfor( i = 0; i < 200; i++ )\n\t\t{\n\t\tHIRES_TIME timeVal;\n\n\t\tcryptCreateContext( &sessionKeyContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\tDEFAULT_CRYPT_ALGO );\n\t\ttimeVal = timeDiff( 0 );\n\t\tstatus = cryptImportKey( encryptedKeyBlob, length, decryptContext, \n\t\t\t\t\t\t\t\t sessionKeyContext );\n\t\ttimeVal = timeDiff( timeVal ); \n\t\tcryptDestroyContext( sessionKeyContext );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptImportKey() failed with status %s, \"\n\t\t\t\t\t \"line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\ttimes[ i ] = timeVal;\n\t\t}\n#if 0\n\tfprintf( outputStream, \"Time for unmodified decrypt:\\n\" );\n\tfor( i = 0; i < 200; i++ )\n\t\t{\n\t\tfprintf( outputStream, \"%5d \", times[ i ] );\n\t\tif( ( ( i + 1 ) % 10 ) == 0 )\n\t\t\tfprintf( outputStream, \"\\n\" );\n\t\t}\n#endif /* 0 */\n\ttimeDisplayMean( times, 200 );\n#endif /* 0 */\n\n\t/* Manipulate the encrypted blob and see what timing effect it has */\n\tfor( i = 0; i < 1000; i++ )\n\t\t{\n\t\tBYTE buffer[ 1024 ], *encryptedKeyPtr;\n\t\tHIRES_TIME timeVal;\n\n\t\t/* For the 1024-bit key the encrypted value in the blob ranges from\n\t\t   n + 46 to n + 173 (128 bytes, zero-based) */\n\t\tencryptedKeyPtr = buffer + 173;\n\t\tmemcpy( buffer, encryptedKeyBlob, length );\n\t\t*encryptedKeyPtr ^= 0x01;\n\t\tstatus = cryptCreateContext( &sessionKeyContext, CRYPT_UNUSED, \n\t\t\t\t\t\t\t\t\t DEFAULT_CRYPT_ALGO );\n\t\tif( cryptStatusError( status ) )\n\t\t\treturn( FALSE );\n\t\ttimeVal = timeDiff( 0 );\n\t\tstatus = cryptImportKey( buffer, length, decryptContext, \n\t\t\t\t\t\t\t\t sessionKeyContext );\n\t\ttimeVal = timeDiff( timeVal ); \n\t\tcryptDestroyContext( sessionKeyContext );\n\t\tif( !cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Corrupted import wasn't detected, \"\n\t\t\t\t\t \"line %d.\\n\", __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\ttimes[ i ] = timeVal;\n\t\t}\n#if 0\n\tfprintf( outputStream, \"Time for modified decrypt:\\n\" );\n\tfor( i = 0; i < 1000; i++ )\n\t\t{\n\t\tfprintf( outputStream, \"%5d \", times[ i ] );\n\t\tif( ( ( i + 1 ) % 10 ) == 0 )\n\t\t\tfprintf( outputStream, \"\\n\" );\n\t\t}\n#endif\n\ttimeDisplayMean( times, 1000 );\n\n\treturn( TRUE );\n\t}\n\n#define NO_SAMPLES\t\t100\n\nint insertCryptoDelay( void );\n\nint testTimingAttackPKC( void )\n\t{\n\tCRYPT_CONTEXT cryptContext, hashContext;\n\tHIRES_TIME times[ 1000 ];\n#ifdef __WINDOWS__\n\tLARGE_INTEGER performanceCount;\n#endif /* __WINDOWS__ */\n\tBYTE signature[ 1024 ];\n\tint length, i, status;\n\n#ifdef __WINDOWS__\n\tQueryPerformanceFrequency( &performanceCount ); \n\tprintf( \"Counter frequency = %ld.\\n\", performanceCount.LowPart );\n#endif /* __WINDOWS__ */\n\n\t/* Create the hash to be signed */\n\tstatus = cryptCreateContext( &hashContext, CRYPT_UNUSED,\n\t\t\t\t\t\t\t\t CRYPT_ALGO_SHA2 );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tcryptEncrypt( hashContext, \"12345678\", 8 );\n\tcryptEncrypt( hashContext, \"\", 0 );\n\n\t/* Get the private key needed for signing */\n\tstatus = getPrivateKey( &cryptContext, USER_PRIVKEY_FILE,\n\t\t\t\t\t\t\tUSER_PRIVKEY_LABEL, TEST_PRIVKEY_PASSWORD );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\n\t/* Determine the time for the non-dithered sign */\n\tfor( i = 0; i < NO_SAMPLES; i++ )\n\t\t{\n\t\tHIRES_TIME timeVal;\n\n\t\ttimeVal = timeDiff( 0 );\n#if 1\n\t\tstatus = cryptCreateSignature( signature, 1024, &length, \n\t\t\t\t\t\t\t\t\t   cryptContext, hashContext );\n  #if 0\n\t\tcryptDelayRandom( CRYPT_UNUSED, CRYPT_UNUSED );\n  #endif /* 0 */\n#else\n\t\t/* Raw RSA signature */\n\t\tcryptDelayRandom( cryptContext, hashContext );\n#endif /* 0 */\n\t\ttimeVal = timeDiff( timeVal ); \n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"cryptCreateSignature() failed with \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\ttimes[ i ] = timeVal;\n\t\t}\n\n\t/* Print the results, which can be graphed in CSV-delimited form at\n\t   https://www.socscistatistics.com/descriptive/histograms or in CRLF-\n\t   delimited form at https://www.wessa.net/rwasp_histogram.wasp */\n\tfor( i = 0; i < NO_SAMPLES; i++ )\n\t\t{\n\t\t/* 32/64-bit QPC: All = times[ i ].\n\t\t   64-bit rdtsc: All = times[ i ] / 50, delay = times[ i ] / 2 */\n\t\tprintf( \"%d, \", times[ i ] );\n\t\t}\n\tputchar( '\\n' );\n\ttimeDisplayMean( times, NO_SAMPLES );\n\n\treturn( TRUE );\n\t}\n#endif /* USE_TIMING */\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tError-handling Functions\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Print extended error attribute information */\n\nvoid printErrorAttributeInfo( const CRYPT_HANDLE cryptHandle )\n\t{\n\tstatic const char *errorTypeString[] = {\n\t\t\"CRYPT_ERRTYPE_NONE\", \"CRYPT_ERRTYPE_ATTR_SIZE\", \n\t\t\"CRYPT_ERRTYPE_ATTR_VALUE\", \"CRYPT_ERRTYPE_ATTR_ABSENT\",\n\t\t\"CRYPT_ERRTYPE_ATTR_PRESENT\", \"CRYPT_ERRTYPE_CONSTRAINT\",\n\t\t\"CRYPT_ERRTYPE_ISSUERCONSTRAINT\", \"NULL\", \"NULL\"\n\t\t};\n\tconst char *typeString = \"<<<Unknown>>>\";\n\tint errorType, errorLocus, status;\n\n\tstatus = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_ERRORTYPE,\n\t\t\t\t\t\t\t\t&errorType );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tif( errorType >= CRYPT_ERRTYPE_NONE && \\\n\t\t\terrorType < CRYPT_ERRTYPE_LAST )\n\t\t\ttypeString = errorTypeString[ errorType ];\n\t\t}\n\tstatus = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_ERRORLOCUS, \n\t\t\t\t\t\t\t\t&errorLocus );\n\tif( cryptStatusOK( status ) && errorType != CRYPT_ERRTYPE_NONE )\n\t\t{\n\t\tfprintf( outputStream, \"  Error info attributes report locus %d, \"\n\t\t\t\t \"type %d (%s).\\n\", errorLocus, errorType, typeString );\n\t\t}\n\t}\n\n/* Print extended object error information */\n\nvoid printExtError( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\tconst char *functionName, const int functionStatus,\n\t\t\t\t\tconst int lineNo )\n\t{\n\tchar errorMessage[ 512 ];\n\tint errorMessageLength, status;\n\n\tfprintf( outputStream, \"%s failed with error code %d, line %d.\\n\", \n\t\t\t functionName, functionStatus, lineNo );\n\tstatus = cryptGetAttributeString( cryptHandle, CRYPT_ATTRIBUTE_ERRORMESSAGE,\n\t\t\t\t\t\t\t\t\t  errorMessage, &errorMessageLength );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfputs( \"  No extended error information available.\\n\", \n\t\t\t   outputStream );\n\t\tprintErrorAttributeInfo( cryptHandle );\n\t\treturn;\n\t\t}\n\terrorMessage[ errorMessageLength ] = '\\0';\n\tfprintf( outputStream, \"  Error message = %s'%s'.\\n\",\n\t\t\t ( errorMessageLength > ( 80 - 21 ) ) ? \"\\n  \" : \"\", \n\t\t\t errorMessage );\n\tprintErrorAttributeInfo( cryptHandle );\n\t}\n\n/* Exit with an error message.  attrErrorExit() prints the locus and type,\n   extErrorExit() prints the extended error code and message */\n\nBOOLEAN attrErrorExit( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t   const char *functionName, const int errorCode,\n\t\t\t\t\t   const int lineNumber )\n\t{\n\tfprintf( outputStream, \"%s failed with error code %d, line %d.\\n\", \n\t\t\t functionName, errorCode, lineNumber );\n\tprintErrorAttributeInfo( cryptHandle );\n\treturn( FALSE );\n\t}\n\nBOOLEAN extErrorExit( const CRYPT_HANDLE cryptHandle,\n\t\t\t\t\t  const char *functionName, const int errorCode,\n\t\t\t\t\t  const int lineNumber )\n\t{\n\tprintExtError( cryptHandle, functionName, errorCode, lineNumber );\n\tcryptDestroyObject( cryptHandle );\n\treturn( FALSE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tMisc. Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Some algorithms can be disabled to eliminate patent problems or reduce the\n   size of the code.  The following functions are used to select generally\n   equivalent alternatives if the required algorithm isn't available.  These\n   selections make certain assumptions, namely that at least one of the\n   algorithms in the fallback chain is always available (which is guaranteed,\n   DEFAULT_CRYPT_ALGO is always present), and that they have the same general \n   properties as the algorithms they're replacing, which is also usually the \n   case, with CAST being a first-instance substitute for IDEA or RC2 and\n   then 3DES or AES as the fallback if CAST isn't available */\n\nCRYPT_ALGO_TYPE selectCipher( const CRYPT_ALGO_TYPE algorithm )\n\t{\n\tif( cryptStatusOK( cryptQueryCapability( algorithm, NULL ) ) )\n\t\treturn( algorithm );\n\tif( cryptStatusOK( cryptQueryCapability( CRYPT_ALGO_CAST, NULL ) ) )\n\t\treturn( CRYPT_ALGO_CAST );\n\treturn( DEFAULT_CRYPT_ALGO );\n\t}\n\n/* Print a hex string.  We assemble this as a single string and output it \n   in one go to void it being broken up by output from another thread */\n\nvoid printHex( const char *prefix, const BYTE *value, const int length )\n\t{\n\tchar buffer[ 4096 ];\n\tint pos = 0, i;\n\n\tfor( i = 0; i < min( length, 1024 ); i += 16 )\n\t\t{\n\t\tconst int innerLen = min( length - i, 16 );\n\t\tint j;\n\n\t\t/* In the following, the redundant \"%s\" is needed for gcc */\n\t\tpos += sprintf( buffer + pos, \"%s\", prefix );\n\t\tfor( j = 0; j < innerLen; j++ )\n\t\t\tpos += sprintf( buffer + pos, \"%02X \", value[ i + j ] );\n\t\tfor( ; j < 16; j++ )\n\t\t\tpos += sprintf( buffer + pos, \"   \" );\n\t\tfor( j = 0; j < innerLen; j++ )\n\t\t\t{\n\t\t\tconst BYTE ch = value[ i + j ];\n\n\t\t\tpos += sprintf( buffer + pos, \"%c\", isprint( ch ) ? ch : '.' );\n\t\t\t}\n\t\tpos += sprintf( buffer + pos, \"\\n\" );\n\t\t}\n\n\tfprintf( outputStream, \"%s\", buffer );\n\t}\n\n/* Add a collection of fields to a certificate */\n\nint addCertFields( const CRYPT_CERTIFICATE certificate,\n\t\t\t\t   const CERT_DATA *certData, const int lineNo )\n\t{\n\tCRYPT_ATTRIBUTE_TYPE prevAttribute = CRYPT_ATTRIBUTE_NONE;\n\tint i;\n\n\tfor( i = 0; certData[ i ].type != CRYPT_ATTRIBUTE_NONE; i++ )\n\t\t{\n\t\tBYTE buffer[ 256 ];\n\t\tint value, status;\n\n\t\tmemset( buffer, '*', 256 );\n\t\tswitch( certData[ i ].componentType )\n\t\t\t{\n\t\t\tcase IS_NUMERIC:\n\t\t\t\tstatus = cryptSetAttribute( certificate,\n\t\t\t\t\t\t\t\t\t\t\tcertData[ i ].type, \n\t\t\t\t\t\t\t\t\t\t\tcertData[ i ].numericValue );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"cryptSetAttribute() for entry \"\n\t\t\t\t\t\t\t \"%d, field ID %d, numeric value %d, \\n  failed \"\n\t\t\t\t\t\t\t \"with error code %d, line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type, certData[ i ].numericValue,\n\t\t\t\t\t\t\t status, lineNo );\n#ifdef USE_CERTLEVEL_PKIX_FULL\n\t\t\t\t\tif( certData[ i ].numericValue == CRYPT_CERTINFO_EXCLUDEDSUBTREES )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfprintf( outputStream, \"This may be due to a \"\n\t\t\t\t\t\t\t\t \"mismatch between the self-test code, \"\n\t\t\t\t\t\t\t\t \"built with a\\n\" \"compliance level of \"\n\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_PKIX_FULL, and \"\n\t\t\t\t\t\t\t\t \"cryptlib, probably\\n\" \"built with \"\n\t\t\t\t\t\t\t\t \"CRYPT_COMPLIANCELEVEL_STANDARD, which \"\n\t\t\t\t\t\t\t\t \"doesn't recognise this\\n\" \"attribute.\\n\" );\n\t\t\t\t\t\t}\n#endif /* USE_CERTLEVEL_PKIX_FULL */\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tstatus = cryptGetAttribute( certificate, \n\t\t\t\t\t\t\t\t\t\t\tcertData[ i ].type, &value );\n\t\t\t\tif( ( status == CRYPT_ERROR_NOTINITED || \\\n\t\t\t\t\t  cryptStatusOK( status ) ) && \\\n\t\t\t\t\tvalue != certData[ i ].numericValue && \\\n\t\t\t\t\tcertData[ i ].type == CRYPT_ATTRIBUTE_CURRENT )\n\t\t\t\t\t{\n\t\t\t\t\t/* It's a selection component, we may have been \n\t\t\t\t\t   selecting an entry in a not-yet-created attribute \n\t\t\t\t\t   (that'll be created on-demand) so when we try and \n\t\t\t\t\t   read back the current attribute we'll get back either\n\t\t\t\t\t   a non-inited error or whatever was last selected \n\t\t\t\t\t   that's actually present */\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Read back of numeric attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, failed, status %d, \"\n\t\t\t\t\t\t\t \"line %d.\\n\", i + 1, certData[ i ].type, status,\n\t\t\t\t\t\t\t lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\t}\n\t\t\t\tif( value != certData[ i ].numericValue )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Read back of numeric attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, failed,\\n  got %d, \"\n\t\t\t\t\t\t\t \"expected %d, line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type, value, \n\t\t\t\t\t\t\t certData[ i ].numericValue, lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase IS_STRING:\n\t\t\t\t{\n\t\t\t\tint valueLength = certData[ i ].numericValue ? \\\n\t\t\t\t\t\t\t\t\tcertData[ i ].numericValue : \\\n\t\t\t\t\t\t\t\t\tparamStrlen( certData[ i ].stringValue );\n\n\t\t\t\tstatus = cryptSetAttributeString( certificate, \n\t\t\t\t\t\t\t\t\t\t\t\t  certData[ i ].type, \n\t\t\t\t\t\t\t\t\t\t\t\t  certData[ i ].stringValue,\n\t\t\t\t\t\t\t\t\t\t\t\t  valueLength );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n#if defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && !defined( NDEBUG )\n\t\t\t\t\tif( status == CRYPT_ERROR_INVALID && \\\n\t\t\t\t\t\tparamStrlen( certData[ i ].stringValue ) == 2 && \\\n\t\t\t\t\t\t!memcmp( certData[ i ].stringValue, \"NZ\", 2 ) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t/* Warn about BoundsChecker-induced Heisenbugs */\n\t\t\t\t\t\tfputs( \"                         ********************\", \n\t\t\t\t\t\t\t   outputStream );\n\t\t\t\t\t\tfputs( \"If you're running this under BoundsChecker \"\n\t\t\t\t\t\t\t   \"you need to disable it to complete\\nthe test \"\n\t\t\t\t\t\t\t   \"since it causes errors in the certificate \"\n\t\t\t\t\t\t\t   \"string-checking code.  The\\nfollowing error \"\n\t\t\t\t\t\t\t   \"is caused by BoundsChecker, not by the \"\n\t\t\t\t\t\t\t   \"self-test failing.\", outputStream );\n\t\t\t\t\t\tfputs( \"                         ********************\", \n\t\t\t\t\t\t\t   outputStream );\n\t\t\t\t\t\t}\n#endif /* VC++ 6 */\n\t\t\t\t\tfprintf( outputStream, \"cryptSetAttributeString() for \"\n\t\t\t\t\t\t\t \"entry %d, field ID %d,\\n  string value '%s', \"\n\t\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type,\n\t\t\t\t\t\t\t ( char * ) certData[ i ].stringValue, status,\n\t\t\t\t\t\t\t lineNo );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tstatus = cryptGetAttributeString( certificate, \n\t\t\t\t\t\t\t\t\t\t\t\t  certData[ i ].type, buffer, \n\t\t\t\t\t\t\t\t\t\t\t\t  &value );\n\t\t\t\tif( status == CRYPT_ERROR_NOTFOUND && \\\n\t\t\t\t\tcertData[ i ].type == CRYPT_CERTINFO_RFC822NAME )\n\t\t\t\t\t{\n\t\t\t\t\t/* Adding this attribute from testAltnameCert() tests \n\t\t\t\t\t   the implicit selection of the subjectAltName when an\n\t\t\t\t\t   email address is added and the subjectName is \n\t\t\t\t\t   otherwise selected, since the selection of the\n\t\t\t\t\t   subjectAltName is invisible and only occurs while the\n\t\t\t\t\t   email address is being added, it can't be read back \n\t\t\t\t\t   without explicitly selecting the subjectAltName */\n\t\t\t\t\tstatus = CRYPT_OK;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusOK( status ) && \\\n\t\t\t\t\tcertData[ i ].type == CRYPT_CERTINFO_OTHERNAME_TYPEID && \\\n\t\t\t\t\t!memcmp( certData[ i ].stringValue, \"1 3 6 1 4\", 9 ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* This attribute is set as a text OID but read back in \n\t\t\t\t\t   binary form, so its effective content and length \n\t\t\t\t\t   changes across the set/get operation */\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Read back of string attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, failed, status %d, \"\n\t\t\t\t\t\t\t \"line %d.\\n\", i + 1, certData[ i ].type, status,\n\t\t\t\t\t\t\t lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif( value != valueLength || \\\n\t\t\t\t\tmemcmp( certData[ i ].stringValue, buffer, valueLength ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we're setting a multivalued attribute then when we \n\t\t\t\t\t   try and read it back we'll get the first instance, \n\t\t\t\t\t   not the on that we've just set.  We could handle this\n\t\t\t\t\t   by walking down the CRYPT_ATTRIBUTE_CURRENT_INSTANCE \n\t\t\t\t\t   list but since this is a basic self-test it's easier \n\t\t\t\t\t   to just hardcode the specific check and skip it */\n\t\t\t\t\tif( certData[ i ].type == CRYPT_CERTINFO_RFC822NAME && \\\n\t\t\t\t\t\tprevAttribute == CRYPT_CERTINFO_RFC822NAME )\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tbuffer[ valueLength ] = '\\0';\n\t\t\t\t\tfprintf( outputStream, \"Read back of string attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, failed,\\n  got '%s', \"\n\t\t\t\t\t\t\t \"expected '%s', line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type, buffer, \n\t\t\t\t\t\t\t ( char * ) certData[ i ].stringValue, lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n#ifdef HAS_WIDECHAR\n\t\t\tcase IS_WCSTRING:\n\t\t\t\tstatus = cryptSetAttributeString( certificate,\n\t\t\t\t\t\t\tcertData[ i ].type, certData[ i ].stringValue,\n\t\t\t\t\t\t\twcslen( certData[ i ].stringValue ) * sizeof( wchar_t ) );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"cryptSetAttributeString() for \"\n\t\t\t\t\t\t\t \"entry %d, field ID %d,\\n  wcString value '%s', \"\n\t\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type,\n\t\t\t\t\t\t\t ( char * ) certData[ i ].stringValue, status,\n\t\t\t\t\t\t\t lineNo );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n#endif /* HAS_WIDECHAR */\n\n\t\t\tcase IS_TIME:\n\t\t\t\tstatus = cryptSetAttributeString( certificate,\n\t\t\t\t\t\t\tcertData[ i ].type, &certData[ i ].timeValue,\n\t\t\t\t\t\t\tsizeof( time_t ) );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"cryptSetAttributeString() for \"\n\t\t\t\t\t\t\t \"entry %d, field ID %d,\\n  time value 0x\"\n\t\t\t\t\t\t\t TIMET_FORMAT \", failed with error code %d, \"\n\t\t\t\t\t\t\t \"line %d.\\n\", i + 1, certData[ i ].type, \n\t\t\t\t\t\t\t certData[ i ].timeValue, status, lineNo );\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tstatus = cryptGetAttributeString( certificate, \n\t\t\t\t\t\t\t\t\t\t\t\t  certData[ i ].type, buffer, \n\t\t\t\t\t\t\t\t\t\t\t\t  &value );\n\t\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Read back of time attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, failed, status %d, \"\n\t\t\t\t\t\t\t \"line %d.\\n\", i + 1, certData[ i ].type, status,\n\t\t\t\t\t\t\t lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\t}\n\t\t\t\tif( value != sizeof( time_t ) || \\\n\t\t\t\t\tmemcmp( &certData[ i ].timeValue, buffer, \n\t\t\t\t\t\t\tsizeof( time_t ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tfprintf( outputStream, \"Read back of time attribute \"\n\t\t\t\t\t\t\t \"for entry %d, field ID %d, returned different \"\n\t\t\t\t\t\t\t \"attribute value, line %d.\\n\", i + 1, \n\t\t\t\t\t\t\t certData[ i ].type, lineNo );\n\t\t\t\t\tstatus = CRYPT_ERROR_FAILED;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tassert( FALSE );\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tprintErrorAttributeInfo( certificate );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tprevAttribute = certData[ i ].type;\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Compare two blocks and data and check whether they're identical */\n\nint compareData( const void *origData, const int origDataLength,\n\t\t\t\t const void *recovData, const int recovDataLength )\n\t{\n\tif( origDataLength != recovDataLength )\n\t\t{\n\t\tfprintf( outputStream, \"Original length %d doesn't match recovered \"\n\t\t\t\t \"data length %d.\\n\", origDataLength, recovDataLength );\n\n\t\treturn( FALSE );\n\t\t}\n\tif( memcmp( origData, recovData, origDataLength ) )\n\t\t{\n\t\tfprintf( outputStream, \"Data of length %d doesn't match recovered \"\n\t\t\t\t \"data:\\n\", origDataLength );\n\t\tfprintf( outputStream, \"Original data:\\n\" );\n\t\tprintHex( \"  \", origData, min( origDataLength, 64 ) );\n\t\tfprintf( outputStream, \"Recovered data:\\n\" );\n\t\tprintHex( \"  \", recovData, min( origDataLength, 64 ) );\n\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tDebug Functions\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Write an object to a file for debugging purposes */\n\n#if defined( _MSC_VER ) && \\\n\t!( defined( _WIN32_WCE ) || defined( __PALMSOURCE__ ) )\n  #include <direct.h>\n  #include <io.h>\n#endif /* VC++ Win16/Win32 */\n\nvoid debugDump( const char *fileName, const void *data, const int dataLength )\n\t{\n\tFILE *filePtr;\n#ifdef __UNIX__\n\tconst char *tmpPath = getenv( \"TMPDIR\" );\n\tchar fileNameBuffer[ FILENAME_BUFFER_SIZE ];\n\tconst int tmpPathLen = ( tmpPath != NULL ) ? strlen( tmpPath ) : 0;\n#else\n\tchar fileNameBuffer[ 128 ];\n#endif /* __UNIX__ */\n\tconst int length = strlen( fileName );\n\tint count;\n\n\tfileNameBuffer[ 0 ] = '\\0';\n#if defined( _WIN32_WCE )\n\t/* Under WinCE we don't want to scribble a ton of data into flash every\n\t   time we're run so we don't try and do anything */\n\treturn;\n#elif ( defined( _MSC_VER ) && !defined( __PALMSOURCE__ ) )\n\t/* If the path isn't absolute, deposit it in a temp directory.  Note\n\t   that we have to use underscores in front of the Posix functions\n\t   because these were deprecated starting with VS 2005.  In addition we \n\t   have to explicitly exclude oldnames.lib (which usually isn't a \n\t   included in the libraries installed with VS) from the link, inclusion \n\t   of this is triggered by the compiler seeing the Posix or underscore-\n\t   Posix functions */\n  #if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )\n\t#pragma comment(linker, \"/nodefaultlib:oldnames.lib\")\n  #endif /* VC++ 2005 and newer misconfiguration */\n\tif( fileName[ 1 ] != ':' )\n\t\t{\n\t\t/* It's my code, I can use whatever paths I feel like */\n\t\tif( _access( \"d:/tmp/\", 6 ) == 0 )\n\t\t\t{\n\t\t\t/* There's a data partition available, dump the info there */\n\t\t\tif( _access( \"d:/tmp/\", 6 ) == -1 && \\\n\t\t\t\t!CreateDirectory( \"d:/tmp\", NULL ) )\n\t\t\t\treturn;\n\t\t\tstrcpy( fileNameBuffer, \"d:/tmp/\" );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* There's no separate data partition, everything's dumped into\n\t\t\t   the same partition */\n\t\t\tif( _access( \"c:/tmp/\", 6 ) == -1 && \\\n\t\t\t\t!CreateDirectory( \"c:/tmp\", NULL ) )\n\t\t\t\treturn;\n\t\t\tstrcpy( fileNameBuffer, \"c:/tmp/\" );\n\t\t\t}\n\t\t}\n#elif defined( __UNIX__ )\n\t/* If the path isn't absolute, deposit it in a temp directory */\n\tif( fileName[ 0 ] != '/' )\n\t\t{\n\t\tif( tmpPathLen > 3 && tmpPathLen < FILENAME_BUFFER_SIZE - 64 )\n\t\t\t{\n\t\t\tstrcpy( fileNameBuffer, tmpPath );\n\t\t\tif( fileNameBuffer[ tmpPathLen - 1 ] != '/' )\n\t\t\t\tstrcat( fileNameBuffer + tmpPathLen, \"/\" );\n\t\t\t}\n\t\telse\n\t\t\tstrcpy( fileNameBuffer, \"/tmp/\" );\n\t\t}\n#else\n\tfileNameBuffer[ 0 ] = '\\0';\n#endif /* OS-specific paths */\n\tstrcat( fileNameBuffer, fileName );\n\tif( length <= 3 || fileName[ length - 4 ] != '.' )\n\t\tstrcat( fileNameBuffer, \".der\" );\n\n#if defined( __VMCMS__ )\n\t{\n\tchar formatBuffer[ 32 ];\n\n\tsprintf( formatBuffer, \"wb, recfm=F, lrecl=%d, noseek\", dataLength );\n\tfilePtr = fopen( fileNameBuffer, formatBuffer );\n\t}\n\tif( filePtr == NULL )\n\t\treturn;\n#else\n\tif( ( filePtr = fopen( fileNameBuffer, \"wb\" ) ) == NULL )\n\t\treturn;\n#endif /* __VMCMS__ */\n\tcount = fwrite( data, 1, dataLength, filePtr );\n\tfclose( filePtr );\n\tif( count < length )\n\t\t{\n\t\tfprintf( outputStream, \"Warning: Couldn't dump '%s' to disk.\\n\", \n\t\t\t\t fileName );\n\t\tremove( fileName );\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tSession Functions\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Print information on the peer that we're talking to */\n\nint printConnectInfo( const CRYPT_SESSION cryptSession )\n\t{\n#ifndef UNICODE_STRINGS\n\ttime_t theTime;\n#endif /* UNICODE_STRINGS */\n\tC_CHR serverName[ 128 ];\n\tint serverNameLength, serverPort, status;\n\n\tstatus = cryptGetAttributeString( cryptSession, CRYPT_SESSINFO_CLIENT_NAME,\n\t\t\t\t\t\t\t\t\t  serverName, &serverNameLength );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_CLIENT_PORT, \n\t\t\t\t\t\t\t\t\t&serverPort );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n#ifdef UNICODE_STRINGS\n\tserverName[ serverNameLength / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\tfprintf( outputStream, \"SVR: Connect attempt from %S, port %d\", \n\t\t\t serverName, serverPort );\n#else\n\tserverName[ serverNameLength ] = '\\0';\n\ttime( &theTime );\n\tfprintf( outputStream, \"SVR: Connect attempt from %s, port %d, on %s.\\n\", \n\t\t\t serverName, serverPort, getTimeString( theTime, 0 ) );\n#endif /* UNICODE_STRINGS */\n\tfflush( stdout );\n\n\t/* Display all the attributes that we've got */\n\tstatus = displayAttributes( cryptSession );\n\tfflush( stdout );\n\treturn( status );\n\t}\n\n/* Print security info for the session */\n\nint printSecurityInfo( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t   const BOOLEAN isServer,\n\t\t\t\t\t   const BOOLEAN showFingerprint,\n\t\t\t\t\t   const BOOLEAN showServerKeyInfo,\n\t\t\t\t\t   const BOOLEAN showClientCertInfo )\n\t{\n\tint cryptAlgo, keySize DUMMY_INIT, version DUMMY_INIT, status;\n\n\t/* Print general security info */\n\tstatus = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_ALGO,\n\t\t\t\t\t\t\t\t&cryptAlgo );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_CTXINFO_KEYSIZE,\n\t\t\t\t\t\t\t\t\t&keySize );\n\t\t}\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_VERSION,\n\t\t\t\t\t\t\t\t\t&version );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"Couldn't get session security parameters, \"\n\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"%sSession is protected using algorithm %d with \"\n\t\t\t \"a %d bit key,\\n  protocol version %d.\\n\", \n\t\t\t isServer ? \"SVR: \" : \"\", cryptAlgo, keySize * 8, version );\n\tif( showServerKeyInfo || showClientCertInfo ) \n\t\t{\n\t\tCRYPT_CONTEXT serverKey;\n\n\t\tstatus = cryptGetAttribute( cryptSession, CRYPT_SESSINFO_RESPONSE,\n\t\t\t\t\t\t\t\t\t&serverKey );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( serverKey, CRYPT_CTXINFO_ALGO,\n\t\t\t\t\t\t\t\t\t\t&cryptAlgo );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tstatus = cryptGetAttribute( serverKey, CRYPT_CTXINFO_KEYSIZE,\n\t\t\t\t\t\t\t\t\t\t\t&keySize );\n\t\t\t\t}\n\t\t\tcryptDestroyContext( serverKey );\n\t\t\t}\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Couldn't get server security parameters, \"\n\t\t\t\t\t \"status %d, line %d.\\n\", status, __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tfprintf( outputStream, \"%s key uses algorithm %d, key size %d bits.\\n\", \n\t\t\t\t showClientCertInfo ? \"SVR: Client authentication\" : \"Server\", \n\t\t\t\t cryptAlgo, keySize * 8 );\n\t\t}\n\tfflush( stdout );\n\tif( isServer || !showFingerprint )\n\t\treturn( TRUE );\n\n\tstatus = printFingerprint( cryptSession, FALSE );\n\tfflush( stdout );\n\treturn( status );\n\t}\n\nint printFingerprint( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t  const BOOLEAN isServer )\n\t{\n\tBYTE fingerPrint[ CRYPT_MAX_HASHSIZE ];\n\tint length, status;\n\n\t/* Print the server key fingerprint */\n\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t\t  fingerPrint, &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptGetAttributeString() failed with error \"\n\t\t\t\t \"code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\tfprintf( outputStream, \"%sServer key fingerprint =\\n\", \n\t\t\t isServer ? \"SVR: \" : \"\" );\n\tprintHex( \"  \", fingerPrint, length );\n\n\treturn( TRUE );\n\t}\n\n/* Set up a client/server to connect locally.  For the client this simply \n   tells it where to connect, for the server this binds it to the local \n   (loopback) address so that we don't inadvertently open up outside ports \n   (admittedly they can't do much except run the hardcoded self-test, but \n   it's better not to do this at all) */\n\nBOOLEAN setLocalConnect( const CRYPT_SESSION cryptSession, const int port )\n\t{\n\tint status;\n\n\tif( LOCAL_HOST_NAME[ 0 ] != 'l' )\n\t\t{\n#ifdef LOCAL_PORT_NAME\n\t\tfprintf( outputStream, \"Warning: Enabling server on non-local \"\n\t\t\t\t \"interface '%s', port %d.\\n\", LOCAL_HOST_NAME, \n\t\t\t\t LOCAL_PORT_NAME );\n#else\n\t\tfputs( \"Warning: Enabling server on non-local interface '\" \n\t\t\t   LOCAL_HOST_NAME \"'.\", outputStream );\n#endif /* LOCAL_PORT_NAME */\n\t\t}\n\n\tstatus = cryptSetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\t  CRYPT_SESSINFO_SERVER_NAME,\n\t\t\t\t\t\t\t\t\t  NATIVE_LOCAL_HOST_NAME, \n\t\t\t\t\t\t\t\t\t  paramStrlen( NATIVE_LOCAL_HOST_NAME ) );\n#if defined( LOCAL_PORT_NAME )\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,\n\t\t\t\t\t\t\t\t\tLOCAL_PORT_NAME );\n\t\t}\n#elif defined( __UNIX__ )\n\t/* If we're running under Unix, set the port to a nonprivileged one so\n\t   that we don't have to run as root.  For anything other than very low-\n\t   numbered ports (e.g. SSH), the way we determine the port is to repeat\n\t   the first digit, so e.g. TSA on 318 becomes 3318, this seems to be\n\t   the method most commonly used */\n\tif( cryptStatusOK( status ) && port < 1024 )\n\t\t{\n\t\tif( port < 100 )\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,\n\t\t\t\t\t\t\t\t\t\tport + 4000 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SERVER_PORT,\n\t\t\t\t\t\t\t\t\t\t( ( port / 100 ) * 1000 ) + port );\n\t\t\t}\n\t\t}\n#endif /* Optional port settings */\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptSetAttribute/AttributeString() failed \"\n\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn( FALSE );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\n/* Check whether a remote server might be down, which is treated as a soft \n   fail rather than a hard-fail error condition */\n\nBOOLEAN isServerDown( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t  const int errorStatus )\n\t{\n\t/* If we get a straight connect error then we don't treat it as a \n\t   serious failure */\n\tif( errorStatus == CRYPT_ERROR_OPEN || \\\n\t\terrorStatus == CRYPT_ERROR_NOTFOUND )\n\t\treturn( TRUE );\n\n\t/* Under Unix a connection-refused will be reported as a \n\t   CRYPT_ERROR_PERMISSION (under Winsock it's just a generic open \n\t   error), and a failure to connect may also be reported via a timeout \n\t   as CRYPT_ERROR_TIMEOUT, so we check for these as alternatives to an \n\t   open error.  \n\t   \n\t   Note that some firewalls may allow a connect but then block reads, in \n\t   which case we'd need to check for the string \"Timeout on read\" as \n\t   well, however we don't enable this by default because some broken \n\t   servers may respond to unexpected PDUs by hanging or closing the \n\t   connection, which will also lead to a read timeout for a condition \n\t   that's more than just a transient network error */\n#ifdef __UNIX__\n\tif( errorStatus == CRYPT_ERROR_PERMISSION || \\\n\t\terrorStatus == CRYPT_ERROR_TIMEOUT )\n\t\t{\n\t\tchar errorMessage[ 512 ];\n\t\tint errorMessageLength, status;\n\n\t\tstatus = cryptGetAttributeString( cryptSession, \n\t\t\t\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_ERRORMESSAGE,\n\t\t\t\t\t\t\t\t\t\t  errorMessage, &errorMessageLength );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\terrorMessage[ errorMessageLength ] = '\\0';\n\t\t\tif( strstr( errorMessage, \"ECONNREFUSED\" ) != NULL || \\\n\t\t\t\tstrstr( errorMessage, \"ETIMEDOUT\" ) != NULL || \\\n\t\t\t\tstrstr( errorMessage, \"Timeout on connect\" ) != NULL )\n\t\t\t\t{\n\t\t\t\treturn( TRUE );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#endif /* __UNX__ */\n\n\treturn( FALSE );\n\t}\n\n/* Run a persistent server session, recycling the connection if the client\n   kept the link open */\n\nstatic void printOperationType( const CRYPT_SESSION cryptSession )\n\t{\n\tstruct {\n\t\tconst int operation; \n\t\tconst char *name;\n\t\t} operationTypeTbl[] = {\n\t\t{ CRYPT_REQUESTTYPE_NONE, \"(None)\" },\n\t\t{ CRYPT_REQUESTTYPE_INITIALISATION,\t\"ir\" },\n\t\t{ CRYPT_REQUESTTYPE_CERTIFICATE, \"cr\" },\n\t\t{ CRYPT_REQUESTTYPE_KEYUPDATE, \"kur\" },\n\t\t{ CRYPT_REQUESTTYPE_REVOCATION,\t\"rr\" },\n\t\t{ CRYPT_REQUESTTYPE_PKIBOOT, \"pkiBoot\" },\n\t\t{ -1, \"(Unknown)\" }\n\t\t};\n\tchar userID[ CRYPT_MAX_TEXTSIZE ];\n\tint userIDsize DUMMY_INIT, requestType, i, status;\n\n\tstatus = cryptGetAttribute( cryptSession,\n\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CMP_REQUESTTYPE,\n\t\t\t\t\t\t\t\t&requestType );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tstatus = cryptGetAttributeString( cryptSession,\n\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_USERNAME,\n\t\t\t\t\t\t\t\t\tuserID, &userIDsize );\n\t\t}\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"cryptGetAttribute/AttributeString() failed \"\n\t\t\t\t \"with error code %d, line %d.\\n\", status, __LINE__ );\n\t\treturn;\n\t\t}\n\tuserID[ userIDsize ] = '\\0';\n\tfor( i = 0; operationTypeTbl[ i ].operation != requestType && \\\n\t\t\t\toperationTypeTbl[ i ].operation != -1; i++ );\n\tfprintf( outputStream, \"SVR: Operation type was %d = %s, user '%s'.\\n\",\n\t\t\t requestType, operationTypeTbl[ i ].name, userID );\n\tfflush( stdout );\n\t}\n\nint activatePersistentServerSession( const CRYPT_SESSION cryptSession,\n\t\t\t\t\t\t\t\t\t const BOOLEAN showOperationType )\n\t{\n\tBOOLEAN connectionActive = FALSE;\n\tint status;\n\n\tdo\n\t\t{\n\t\t/* Activate the connection */\n\t\tstatus = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE,\n\t\t\t\t\t\t\t\t\tTRUE );\n\t\tif( status == CRYPT_ERROR_READ && connectionActive )\n\t\t\t{\n\t\t\t/* The other side closed the connection after a previous\n\t\t\t   successful transaction, this isn't an error */\n\t\t\treturn( CRYPT_OK );\n\t\t\t}\n\n\t\t/* Print connection info and check whether the connection is still\n\t\t   active.  If it is, we recycle the session so that we can process\n\t\t   another request */\n\t\tprintConnectInfo( cryptSession );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tif( showOperationType )\n\t\t\t\tprintOperationType( cryptSession );\n\t\t\tstatus = cryptGetAttribute( cryptSession, \n\t\t\t\t\t\t\t\t\t\tCRYPT_SESSINFO_CONNECTIONACTIVE,\n\t\t\t\t\t\t\t\t\t\t&connectionActive );\n\t\t\t}\n\t\t}\n\twhile( cryptStatusOK( status ) && connectionActive );\n\n\treturn( status );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tAttribute Dump Routines\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Print a list of all attributes present in an object.  We assemble this as \n   a single string and output it in one go to void it being broken up by \n   output from another thread */\n\nint displayAttributes( const CRYPT_HANDLE cryptHandle )\n\t{\n\tint status;\n\n\tif( cryptStatusError( \\\n\t\t\tcryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) ) )\n\t\treturn( TRUE );\n\n\tfputs( \"Attributes present (by cryptlib ID) are:\\n\", outputStream );\n\tdo\n\t\t{\n\t\tBOOLEAN firstAttr = TRUE;\n\t\tchar buffer[ 4096 ];\n\t\tint value, pos = 0;\n\n\t\tstatus = cryptGetAttribute( cryptHandle,\n\t\t\t\t\t\t\t\t\tCRYPT_ATTRIBUTE_CURRENT_GROUP, &value );\n\t\tif( cryptStatusError( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"\\nCurrent attribute group value read \"\n\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t __LINE__ );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tpos += sprintf( buffer + pos, \"  Attribute group %d, values =\", value );\n\t\tdo\n\t\t\t{\n\t\t\tstatus = cryptGetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t\t&value );\n\t\t\tif( cryptStatusError( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"\\nCurrent attribute value read \"\n\t\t\t\t\t\t \"failed with error code %d, line %d.\\n\", status, \n\t\t\t\t\t\t __LINE__ );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !firstAttr )\n\t\t\t\tpos += sprintf( buffer + pos, \",\" );\n\t\t\tpos += sprintf( buffer + pos, \" %d\", value );\n\t\t\tfirstAttr = FALSE;\n\t\t\t}\n\t\twhile( cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\tsprintf( buffer + pos, \".\\n\" );\n\t\tfprintf( outputStream, \"%s\", buffer );\n\t\t}\n\twhile( cryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\n\t/* Reset the cursor to the first attribute.  This is useful for things\n\t   like envelopes and sessions where the cursor points at the first\n\t   attribute that needs to be handled */\n\tcryptSetAttribute( cryptHandle, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t   CRYPT_CURSOR_FIRST );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tCertificate Dump Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Check whether a string may be a Unicode string */\n\nstatic BOOLEAN isUnicode( const BYTE *value, const int length )\n\t{\n\twchar_t wcValue[ 16 + 4 ];\n\n\t/* If it's an odd length or too short to reliably guess, report it as \n\t   non-Unicode */\n\tif( ( length % sizeof( wchar_t ) ) || length <= sizeof( wchar_t ) * 2 )\n\t\treturn( FALSE );\n\n\t/* If the first four characters are ASCII then it's unlikely that it'll\n\t   be Unicode */\n\tif( isprint( value[ 0 ] ) && isprint( value[ 1 ] ) && \\\n\t\tisprint( value[ 2 ] ) && isprint( value[ 3 ] ) )\n\t\treturn( FALSE );\n\n\t/* We need at least three widechars for the next check */\n\tif( length <= sizeof( wchar_t ) * 3 )\n\t\treturn( FALSE );\n\n\t/* Copy the byte-aligned value into a local wchar_t-aligned buffer for\n\t   analysis */\n\tmemcpy( wcValue, value, min( length, 16 ) );\n\n\t/* Check whether the first 3 widechars have identical high bytes.  This\n\t   isn't totally reliable (e.g. \"tanaka\" will give a false positive, \n\t   { 0x0160, 0x0069, 0x006B } will give a false negative) but it's close\n\t   enough */\n\tif( ( wcValue[ 0 ] & 0xFF00 ) == ( wcValue[ 1 ] & 0xFF00 ) && \\\n\t\t( wcValue[ 0 ] & 0xFF00 ) == ( wcValue[ 2 ] & 0xFF00 ) )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\n/* The following function performs many attribute accesses, rather than using\n   huge numbers of status checks we use the following macro to check each\n   attribute access */\n\n#define CHK( function ) \\\n\t\tstatus = function; \\\n\t\tif( cryptStatusError( status ) ) \\\n\t\t\treturn( certInfoErrorExit( #function, status, __LINE__ ) )\n\nstatic int certInfoErrorExit( const char *functionCall, const int status,\n\t\t\t\t\t\t\t  const int line )\n\t{\n\tfprintf( outputStream, \"\\n%s failed with status %d, line %d.\\n\", \n\t\t\t functionCall, status, line );\n\treturn( FALSE );\n\t}\n\n/* Print a DN or altName */\n\nstatic int printComponent( const CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t   const CRYPT_ATTRIBUTE_TYPE component,\n\t\t\t\t\t\t   const char *prefixString )\n\t{\n\tchar buffer[ 1024 + 1 ];\n\tint length, status;\n\n\tstatus = cryptGetAttributeString( certificate, component, NULL, \n\t\t\t\t\t\t\t\t\t  &length );\n\tif( cryptStatusError( status ) )\n\t\t{\n\t\tif( status == CRYPT_ERROR_NOTAVAIL && \\\n\t\t\tcomponent == CRYPT_CERTINFO_DN )\n\t\t\t{\n\t\t\t/* Report this special-case condition explicitly */\n\t\t\tfputs( \"  (Name contains characters that prevent it from being \"\n\t\t\t\t   \"represented as a\\n   text string).\\n\", outputStream ); \n\t\t\t}\n\t\treturn( FALSE );\n\t\t}\n\tif( length > 1024 )\n\t\t{\n\t\t/* This should never happen since the longest permitted component \n\t\t   string has 128 characters, but we check for it just in case */\n\t\tfputs( \"  (Name is too long to display, > 1K characters).\", \n\t\t\t   outputStream ); \n\t\treturn( FALSE );\n\t\t}\n\tstatus = cryptGetAttributeString( certificate, component, buffer, \n\t\t\t\t\t\t\t\t\t  &length );\n\tif( cryptStatusError( status ) )\n\t\treturn( FALSE );\n\tif( isUnicode( buffer, length ) )\n\t\t{\n\t\twchar_t wcBuffer[ 1024 + 1 ];\n\n\t\t/* Copy the byte-aligned value into a local wchar_t-aligned buffer \n\t\t   for display */\n\t\tmemcpy( wcBuffer, buffer, length );\n\t\twcBuffer[ length / sizeof( wchar_t ) ] = TEXT( '\\0' );\n\t\tfprintf( outputStream, \"  %s = %S.\\n\", prefixString, wcBuffer ); \n\t\treturn( TRUE );\n\t\t}\n\tbuffer[ length ] = '\\0'; \n\tfprintf( outputStream, \"  %s = %s.\\n\", prefixString, buffer ); \n\t\n\treturn( TRUE );\n\t}\n\nstatic int printComponents( const CRYPT_CERTIFICATE certificate,\n\t\t\t\t\t\t\tconst CRYPT_ATTRIBUTE_TYPE component,\n\t\t\t\t\t\t\tconst char *prefixString )\n\t{\n\tint status;\n\n\t/* Try and print the component if it's present */\n\tif( !printComponent( certificate, component, prefixString ) )\n\t\treturn( FALSE );\n\n\t/* If it's not a DN or altName component, we're done */\n\tif( !( component >= CRYPT_CERTINFO_COUNTRYNAME && \\\n\t\t   component <= CRYPT_CERTINFO_COMMONNAME ) && \\\n\t\t!( component >= CRYPT_CERTINFO_OTHERNAME_TYPEID && \\\n\t\t   component <= CRYPT_CERTINFO_REGISTEREDID ) )\n\t\treturn( TRUE );\n\n\t/* Check for further components, for multivalued components in altNames */\n\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT_INSTANCE, \n\t\t\t\t\t\t\tcomponent ) );\n\twhile( cryptSetAttribute( certificate,\n\t\t\t\t\t\t\t  CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK )\n\t\t{\n\t\tchar buffer[ 64 ];\n\n\t\tsprintf( buffer, \"  + %s\", prefixString );\n\t\tif( !printComponent( certificate, component, buffer ) )\n\t\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\nstatic void printDN( const CRYPT_CERTIFICATE certificate )\n\t{\n\tprintComponents( certificate, CRYPT_CERTINFO_DN, \"DN string\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_COUNTRYNAME, \"C\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_STATEORPROVINCENAME, \"S\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_LOCALITYNAME, \"L\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_ORGANIZATIONNAME, \"O\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, \"OU\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_COMMONNAME, \"CN\" );\n\t}\n\nstatic void printAltName( const CRYPT_CERTIFICATE certificate )\n\t{\n\tint status;\n\n\tprintComponents( certificate, CRYPT_CERTINFO_RFC822NAME, \"Email\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_DNSNAME, \"DNSName\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_EDIPARTYNAME_NAMEASSIGNER, \"EDI Nameassigner\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_EDIPARTYNAME_PARTYNAME, \"EDI Partyname\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, \"URL\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_IPADDRESS, \"IP\" );\n\tprintComponents( certificate, CRYPT_CERTINFO_REGISTEREDID, \"Registered ID\" );\n\tstatus = cryptSetAttribute( certificate, CRYPT_CERTINFO_DIRECTORYNAME,\n\t\t\t\t\t\t\t\tCRYPT_UNUSED );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"  altName DN is:\\n\" );\n\t\tprintDN( certificate );\n\t\t}\n\t}\n\n/* Print information on a certificate */\n\nint printCertInfo( const CRYPT_CERTIFICATE certificate )\n\t{\n\tCRYPT_CERTTYPE_TYPE certType;\n\tchar buffer[ 1024 ];\n\tint length, value, status;\n\n\tCHK( cryptGetAttribute( certificate, CRYPT_CERTINFO_CERTTYPE, &value ) );\n\tcertType = value;\n\n\t/* Display the issuer and subject DN */\n\tif( certType != CRYPT_CERTTYPE_CERTREQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_CERT && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\tcertType != CRYPT_CERTTYPE_RTCS_REQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_RTCS_RESPONSE && \\\n\t\tcertType != CRYPT_CERTTYPE_OCSP_REQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\tcertType != CRYPT_CERTTYPE_PKIUSER )\n\t\t{\n\t\tfputs( \"Certificate object issuer name is:\\n\", outputStream );\n\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ISSUERNAME ) );\n\t\tprintDN( certificate );\n\t\tif( cryptStatusOK( \\\n\t\t\t\tcryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUERALTNAME, &value ) ) )\n\t\t\t{\n\t\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ISSUERALTNAME ) );\n\t\t\tprintAltName( certificate );\n\t\t\t}\n\t\t}\n\tif( certType != CRYPT_CERTTYPE_CRL && \\\n\t\tcertType != CRYPT_CERTTYPE_REQUEST_REVOCATION && \\\n\t\tcertType != CRYPT_CERTTYPE_CMS_ATTRIBUTES && \\\n\t\tcertType != CRYPT_CERTTYPE_RTCS_REQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_RTCS_RESPONSE && \\\n\t\tcertType != CRYPT_CERTTYPE_OCSP_REQUEST && \\\n\t\tcertType != CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t{\n\t\tfputs( \"Certificate object subject name is:\\n\", outputStream );\n\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTNAME ) );\n\t\tprintDN( certificate );\n\t\tif( cryptStatusOK( \\\n\t\t\t\tcryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_SUBJECTALTNAME, &value ) ) )\n\t\t\t{\n\t\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTALTNAME ) );\n\t\t\tprintAltName( certificate );\n\t\t\t}\n\t\t}\n\n\t/* Display the validity information */\n#ifndef _WIN32_WCE\n\tif( certType == CRYPT_CERTTYPE_CERTCHAIN ||\n\t\tcertType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertType == CRYPT_CERTTYPE_ATTRIBUTE_CERT )\n\t\t{\n\t\ttime_t validFrom, validTo;\n\n\t\tCHK( cryptGetAttributeString( certificate, CRYPT_CERTINFO_VALIDFROM,\n\t\t\t\t\t\t\t\t\t  &validFrom, &length ) );\n\t\tCHK( cryptGetAttributeString( certificate, CRYPT_CERTINFO_VALIDTO,\n\t\t\t\t\t\t\t\t\t  &validTo, &length ) );\n\t\tfprintf( outputStream, \"Certificate is valid from %s to %s.\\n\", \n\t\t\t\t getTimeString( validFrom, 0 ),\n\t\t\t\t getTimeString( validTo, 1 ) );\n\t\t}\n\tif( certType == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t{\n\t\ttime_t thisUpdate, nextUpdate;\n\n\t\tstatus = cryptGetAttributeString( certificate, CRYPT_CERTINFO_THISUPDATE,\n\t\t\t\t\t\t\t\t\t\t  &thisUpdate, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\t/* RTCS basic responses only return a minimal valid/not valid\n\t\t\t   status so failing to find a time isn't an error */\n\t\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_NEXTUPDATE,\n\t\t\t\t\t\t\t\t\t\t\t  &nextUpdate, &length );\n\t\t\tif( cryptStatusOK( status ) )\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"OCSP source CRL time %s,\\n  next \"\n\t\t\t\t\t\t \"update %s.\\n\", getTimeString( thisUpdate, 0 ), \n\t\t\t\t\t\t getTimeString( nextUpdate, 1 ) );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tfprintf( outputStream, \"OCSP source CRL time %s.\\n\", \n\t\t\t\t\t\t getTimeString( thisUpdate, 0 ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( certType == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\ttime_t thisUpdate, nextUpdate;\n\n\t\tCHK( cryptGetAttributeString( certificate, CRYPT_CERTINFO_THISUPDATE,\n\t\t\t\t\t\t\t\t\t  &thisUpdate, &length ) );\n\t\tstatus = cryptGetAttributeString( certificate, CRYPT_CERTINFO_NEXTUPDATE,\n\t\t\t\t\t\t\t\t\t\t  &nextUpdate, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"CRL time %s,\\n  next update %s.\\n\", \n\t\t\t\t\t getTimeString( thisUpdate, 0 ), \n\t\t\t\t\t getTimeString( nextUpdate, 1 ) );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tfprintf( outputStream, \"CRL time %s.\\n\", \n\t\t\t\t\t getTimeString( thisUpdate, 0 ) );\n\t\t\t}\n\t\t}\n#endif /* _WIN32_WCE */\n\tif( certType == CRYPT_CERTTYPE_CRL || \\\n\t\tcertType == CRYPT_CERTTYPE_RTCS_RESPONSE || \\\n\t\tcertType == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t{\n\t\tint noEntries = 0;\n\n\t\t/* Count and display the entries */\n\t\tif( cryptSetAttribute( certificate, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) == CRYPT_OK )\n\t\t\t{\n\t\t\tfputs( \"Revocation/validity list information:\\n\", outputStream );\n\t\t\tdo\n\t\t\t\t{\n#ifndef _WIN32_WCE\n\t\t\t\ttime_t timeStamp = 0;\n#endif /* _WIN32_WCE */\n\t\t\t\tint revStatus, certStatus;\n\n\t\t\t\tnoEntries++;\n\n\t\t\t\t/* Extract response-specific status information */\n\t\t\t\tif( certType == CRYPT_CERTTYPE_RTCS_RESPONSE )\n\t\t\t\t\t{\n\t\t\t\t\tCHK( cryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTSTATUS, &certStatus ) );\n\t\t\t\t\t}\n\t\t\t\tif( certType == CRYPT_CERTTYPE_OCSP_RESPONSE )\n\t\t\t\t\t{\n\t\t\t\t\tCHK( cryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_REVOCATIONSTATUS, &revStatus ) );\n\t\t\t\t\t}\n#ifndef _WIN32_WCE\n\t\t\t\tif( certType == CRYPT_CERTTYPE_CRL || \\\n\t\t\t\t\t( certType == CRYPT_CERTTYPE_OCSP_RESPONSE && \\\n\t\t\t\t\t  revStatus == CRYPT_OCSPSTATUS_REVOKED ) || \\\n\t\t\t\t\t( certType == CRYPT_CERTTYPE_RTCS_RESPONSE && \\\n\t\t\t\t\t  certStatus == CRYPT_CERTSTATUS_NOTVALID ) )\n\t\t\t\t\t{\n\t\t\t\t\tCHK( cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_REVOCATIONDATE, &timeStamp,\n\t\t\t\t\t\t\t\t&length ) );\n\t\t\t\t\t}\n#endif /* _WIN32_WCE */\n\n\t\t\t\t/* Make sure we don't print excessive amounts of\n\t\t\t\t   information */\n\t\t\t\tif( noEntries >= 20 )\n\t\t\t\t\t{\n\t\t\t\t\tif( noEntries == 20 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfputs( \"  (Further entries exist, but won't be \"\n\t\t\t\t\t\t\t   \"printed).\\n\", outputStream );\n\t\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t/* Print details status info */\n\t\t\t\tswitch( certType )\n\t\t\t\t\t{\n\t\t\t\t\tcase CRYPT_CERTTYPE_RTCS_RESPONSE:\n\t\t\t\t\t\tfprintf( outputStream, \"  Certificate status = %d (%s).\\n\",\n\t\t\t\t\t\t\t\t certStatus,\n\t\t\t\t\t\t\t\t ( certStatus == CRYPT_CERTSTATUS_VALID ) ? \\\n\t\t\t\t\t\t\t\t\t\"valid\" : \\\n\t\t\t\t\t\t\t\t ( certStatus == CRYPT_CERTSTATUS_NOTVALID ) ? \\\n\t\t\t\t\t\t\t\t\t\"not valid\" : \\\n\t\t\t\t\t\t\t\t ( certStatus == CRYPT_CERTSTATUS_NONAUTHORITATIVE ) ? \\\n\t\t\t\t\t\t\t\t\t\"only non-authoritative response available\" : \\\n\t\t\t\t\t\t\t\t\t\"unknown\" );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CRYPT_CERTTYPE_OCSP_RESPONSE:\n\t\t\t\t\t\tfprintf( outputStream, \"  Entry %d, rev.status = %d \"\n\t\t\t\t\t\t\t\t \"(%s), rev.time %s.\\n\", noEntries, revStatus,\n\t\t\t\t\t\t\t\t ( revStatus == CRYPT_OCSPSTATUS_NOTREVOKED ) ? \\\n\t\t\t\t\t\t\t\t\t\"not revoked\" : \\\n\t\t\t\t\t\t\t\t ( revStatus == CRYPT_OCSPSTATUS_REVOKED ) ? \\\n\t\t\t\t\t\t\t\t\t\"revoked\" : \"unknown\",\n\t\t\t\t\t\t\t\t getTimeString( timeStamp, 0 ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CRYPT_CERTTYPE_CRL:\n\t\t\t\t\t\tfprintf( outputStream, \"  Entry %d, revocation \"\n\t\t\t\t\t\t\t\t \"time %s.\\n\", noEntries, \n\t\t\t\t\t\t\t\t getTimeString( timeStamp, 0 ) );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tassert( 0 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\twhile( cryptSetAttribute( certificate,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\t\t}\n\t\tfprintf( outputStream, \"Revocation/validity list has %d entr%s.\\n\", \n\t\t\t\t noEntries, ( noEntries == 1 ) ? \"y\" : \"ies\" );\n\t\t}\n\n\t/* Display the self-signed status and fingerprint */\n\tif( cryptStatusOK( cryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_SELFSIGNED, &value ) ) )\n\t\t{\n\t\tfprintf( outputStream, \"Certificate object is %sself-signed.\\n\",\n\t\t\t\t value ? \"\" : \"not \" );\n\t\t}\n\tif( certType == CRYPT_CERTTYPE_CERTIFICATE || \\\n\t\tcertType == CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tCHK( cryptGetAttributeString( certificate, \n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_FINGERPRINT_SHA1,\n\t\t\t\t\t\t\t\t\t  buffer, &length ) );\n\t\tfprintf( outputStream, \"Certificate fingerprint =\\n\" );\n\t\tprintHex( \"  \", buffer, length );\n\t\t}\n\n\t/* List the attribute types */\n\tif( !displayAttributes( certificate ) )\n\t\treturn( FALSE );\n\n\t/* Display common attributes */\n\tif( cryptStatusError( \\\n\t\t\tcryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t   CRYPT_CURSOR_FIRST ) ) )\n\t\t{\n\t\tfputs( \"  (No extensions/attributes).\\n\", outputStream );\n\t\treturn( TRUE );\n\t\t}\n\tfputs( \"Some of the common extensions/attributes are:\\n\", outputStream );\n\tif( certType == CRYPT_CERTTYPE_CRL )\n\t\t{\n\t\ttime_t theTime;\n\n\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST ) );\n\t\tstatus = cryptGetAttribute( certificate, CRYPT_CERTINFO_CRLNUMBER,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusOK( status ) && value )\n\t\t\tfprintf( outputStream, \"  crlNumber = %d.\\n\", value );\n\t\tstatus = cryptGetAttribute( certificate, CRYPT_CERTINFO_DELTACRLINDICATOR,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusOK( status ) && value )\n\t\t\tfprintf( outputStream, \"  deltaCRLIndicator = %d.\\n\", value );\n\t\tstatus = cryptGetAttribute( certificate, CRYPT_CERTINFO_CRLREASON,\n\t\t\t\t\t\t\t\t\t&value );\n\t\tif( cryptStatusOK( status ) && value )\n\t\t\tfprintf( outputStream, \"  crlReason = %d.\\n\", value );\n\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_INVALIDITYDATE, &theTime, &length );\n#ifndef _WIN32_WCE\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"  invalidityDate = %s.\\n\", \n\t\t\t\t\t getTimeString( theTime, 0 ) );\n\t\t\t}\n#endif /* _WIN32_WCE */\n\t\tif( cryptStatusOK( \\\n\t\t\t\tcryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\t   CRYPT_CERTINFO_ISSUINGDIST_FULLNAME, &value ) ) )\n\t\t\t{\n\t\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\tCRYPT_CERTINFO_ISSUINGDIST_FULLNAME ) );\n\t\t\tfputs( \"  issuingDistributionPoint is:\\n\", outputStream );\n\t\t\tprintDN( certificate );\n\t\t\tprintAltName( certificate );\n\t\t\t}\n\t\treturn( TRUE );\n\t\t}\n#ifndef _WIN32_WCE\n\tif( certType == CRYPT_CERTTYPE_CMS_ATTRIBUTES )\n\t\t{\n\t\ttime_t signingTime;\n\n\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_CMS_SIGNINGTIME,\n\t\t\t\t\t\t\t\t\t\t  &signingTime, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tfprintf( outputStream, \"Signing time %s.\\n\", \n\t\t\t\t\t getTimeString( signingTime, 0 ) );\n\t\t\t}\n\t\treturn( TRUE );\n\t\t}\n#endif /* _WIN32_WCE */\n\tif( certType == CRYPT_CERTTYPE_PKIUSER )\n\t\t{\n\t\tCHK( cryptGetAttributeString( certificate, CRYPT_CERTINFO_PKIUSER_ID,\n\t\t\t\t\t\t\t\t\t  buffer, &length ) );\n\t\tbuffer[ length ] ='\\0';\n\t\tfprintf( outputStream, \"  PKI user ID = %s.\\n\", buffer );\n\t\tCHK( cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD,\n\t\t\t\t\t\t\t\t\t  buffer, &length ) );\n\t\tbuffer[ length ] ='\\0';\n\t\tfprintf( outputStream, \"  PKI user issue password = %s.\\n\", \n\t\t\t\t buffer );\n\t\tCHK( cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\t\t\t  CRYPT_CERTINFO_PKIUSER_REVPASSWORD,\n\t\t\t\t\t\t\t\t\t  buffer, &length ) );\n\t\tbuffer[ length ] ='\\0';\n\t\tfprintf( outputStream, \"  PKI user revocation password = %s.\\n\", \n\t\t\t\t buffer );\n\t\treturn( TRUE );\n\t\t}\n\tstatus = cryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_KEYUSAGE, &value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\tstatic const struct { int flag; const char *name; } usageNames[] = {\n\t\t\t{ CRYPT_KEYUSAGE_DIGITALSIGNATURE, \"digSig\" },\n\t\t\t{ CRYPT_KEYUSAGE_NONREPUDIATION, \"nonRep\" },\n\t\t\t{ CRYPT_KEYUSAGE_KEYENCIPHERMENT, \"keyEnc\" },\n\t\t\t{ CRYPT_KEYUSAGE_DATAENCIPHERMENT, \"dataEnc\" },\n\t\t\t{ CRYPT_KEYUSAGE_KEYAGREEMENT, \"keyAgree\" },\n\t\t\t{ CRYPT_KEYUSAGE_KEYCERTSIGN, \"certSign\" },\n\t\t\t{ CRYPT_KEYUSAGE_CRLSIGN, \"crlSign\" },\n\t\t\t{ CRYPT_KEYUSAGE_ENCIPHERONLY, \"encOnly\" },\n\t\t\t{ CRYPT_KEYUSAGE_DECIPHERONLY, \"decOnly\" },\n\t\t\t{ CRYPT_KEYUSAGE_NONE, NULL }\n\t\t\t};\n\t\tBOOLEAN printedUsage = FALSE;\n\t\tint i;\n\n\t\tfprintf( outputStream, \"  keyUsage = %02X (\", value );\n\t\tfor( i = 0; usageNames[ i ].flag != CRYPT_KEYUSAGE_NONE; i++ )\n\t\t\t{\n\t\t\tif( usageNames[ i ].flag & value )\n\t\t\t\t{\n\t\t\t\tif( printedUsage )\n\t\t\t\t\tfprintf( outputStream, \", \" );\n\t\t\t\tfprintf( outputStream, \"%s\", usageNames[ i ].name );\n\t\t\t\tprintedUsage = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\tfputs( \").\\n\", outputStream );\n\t\t}\n\tstatus = cryptGetAttribute( certificate,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_EXTKEYUSAGE, &value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\tBOOLEAN firstTime = TRUE;\n\n\t\tfprintf( outputStream, \"  extKeyUsage types = \" );\n\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT_GROUP,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_EXTKEYUSAGE ) );\n\t\tdo\n\t\t\t{\n\t\t\tCHK( cryptGetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t\t&value ) );\n\t\t\tfprintf( outputStream, \"%s%d\", firstTime ? \"\" : \", \", value );\n\t\t\tfirstTime = FALSE;\n\t\t\t}\n\t\twhile( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\tfprintf( outputStream, \".\\n\" );\n\t\t}\n\tstatus = cryptGetAttribute( certificate, CRYPT_CERTINFO_CA, &value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\tfprintf( outputStream, \"  basicConstraints.cA = %s.\\n\", \n\t\t\t\t value ? \"True\" : \"False\" );\n\t\t}\n\tstatus = cryptGetAttribute( certificate, CRYPT_CERTINFO_PATHLENCONSTRAINT,\n\t\t\t\t\t\t\t\t&value );\n\tif( cryptStatusOK( status ) && value )\n\t\t{\n\t\tfprintf( outputStream, \"  basicConstraints.pathLenConstraint = %d.\\n\", \n\t\t\t\t value );\n\t\t}\n\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_SUBJECTKEYIDENTIFIER, buffer, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"  subjectKeyIdentifier =\\n\" );\n\t\tprintHex( \"  \", buffer, length );\n\t\t}\n\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_AUTHORITY_KEYIDENTIFIER, buffer, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tfprintf( outputStream, \"  authorityKeyIdentifier =\\n\" );\n\t\tprintHex( \"  \", buffer, length );\n\t\t}\n\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICYID, buffer, &length );\n\tif( cryptStatusOK( status ) )\n\t\t{\n\t\tbuffer[ length ] = '\\0';\n\t\tfprintf( outputStream, \n\t\t\t\t \"  certificatePolicies.policyInformation.policyIdentifier = %s.\\n\", \n\t\t\t\t buffer );\n\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICY_CPSURI, buffer, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tbuffer[ length ] = '\\0';\n\t\t\tfprintf( outputStream, \n\t\t\t\t\t \"  certificatePolicies.policyInformation.cpsURI = %s.\\n\", \n\t\t\t\t\t buffer );\n\t\t\t}\n\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICY_ORGANIZATION, buffer, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tbuffer[ length ] = '\\0';\n\t\t\tfprintf( outputStream, \n\t\t\t\t\t \"  certificatePolicies.policyInformation.organisation = %s.\\n\", \n\t\t\t\t\t buffer );\n\t\t\t}\n\t\tstatus = cryptGetAttributeString( certificate,\n\t\t\t\t\t\t\tCRYPT_CERTINFO_CERTPOLICY_EXPLICITTEXT, buffer, &length );\n\t\tif( cryptStatusOK( status ) )\n\t\t\t{\n\t\t\tbuffer[ length ] = '\\0';\n\t\t\tfprintf( outputStream, \n\t\t\t\t\t \"  certificatePolicies.policyInformation.explicitText = %s.\\n\", \n\t\t\t\t\t buffer );\n\t\t\t}\n\t\t}\n\tif( cryptStatusOK( \\\n\t\t\tcryptGetAttribute( certificate,\n\t\t\t\t\t\t\t   CRYPT_CERTINFO_CRLDIST_FULLNAME, &value ) ) )\n\t\t{\n\t\tCHK( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT,\n\t\t\t\t\t\t\t\tCRYPT_CERTINFO_CRLDIST_FULLNAME ) );\n\t\tfputs( \"  crlDistributionPoint is/are:\\n\", outputStream );\n\t\tdo\n\t\t\t{\n\t\t\tprintDN( certificate );\n\t\t\tprintAltName( certificate );\n\t\t\t}\n\t\twhile( cryptSetAttribute( certificate, CRYPT_ATTRIBUTE_CURRENT_INSTANCE,\n\t\t\t\t\t\t\t\t  CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\t\t}\n\n\treturn( TRUE );\n\t}\n\nint printCertChainInfo( const CRYPT_CERTIFICATE certChain )\n\t{\n\tint value, count, status;\n\n\t/* Make sure it really is a certificate chain */\n\tCHK( cryptGetAttribute( certChain, CRYPT_CERTINFO_CERTTYPE, &value ) );\n\tif( value != CRYPT_CERTTYPE_CERTCHAIN )\n\t\t{\n\t\tprintCertInfo( certChain );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* Display info on each certificate in the chain.  This uses the cursor\n\t   mechanism to select successive certificates in the chain from the \n\t   leaf up to the root */\n\tcount = 0;\n\tCHK( cryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST ) );\n\tdo\n\t\t{\n\t\tfprintf( outputStream, \"Certificate %d\\n-------------\\n\", count++ );\n\t\tprintCertInfo( certChain );\n\t\tfprintf( outputStream, \"\\n\" );\n\t\t}\n\twhile( cryptSetAttribute( certChain,\n\t\t\tCRYPT_CERTINFO_CURRENT_CERTIFICATE, CRYPT_CURSOR_NEXT ) == CRYPT_OK );\n\n\t/* Reset the cursor position in the chain */\n\tCHK( cryptSetAttribute( certChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE,\n\t\t\t\t\t\t\tCRYPT_CURSOR_FIRST ) );\n\n\treturn( TRUE );\n\t}\n"
  },
  {
    "path": "deps/cl345/test32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"Test32\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=Test32 - Win32 Fuzz\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"Test32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"Test32.mak\" CFG=\"Test32 - Win32 Fuzz\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"Test32 - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"Test32 - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"Test32 - Win32 Fuzz\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \".\\test32\"\n# PROP BASE Intermediate_Dir \".\\test32\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\binaries32_vc6\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"test32/\"\n# ADD F90 /I \"test32/\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /YX /c\n# ADD CPP /nologo /MD /W3 /O2 /I \".\\\\\" /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x1409 /d \"NDEBUG\"\n# ADD RSC /l 0x1409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 shell32.lib kernel32.lib user32.lib wsock32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# SUBTRACT LINK32 /incremental:yes\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \".\\test32\"\n# PROP BASE Intermediate_Dir \".\\test32\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \".\\binaries32_vc6\"\n# PROP Intermediate_Dir \".\\binaries32_vc6\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"test32/\"\n# ADD F90 /I \"test32/\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /YX /c\n# ADD CPP /nologo /MDd /W3 /Gm /Zi /Od /I \".\\\\\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"CONFIG_FAULTS\" /D \"CONFIG_DIRECT_API\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x1409 /d \"_DEBUG\"\n# ADD RSC /l 0x1409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386\n# ADD LINK32 kernel32.lib user32.lib wsock32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /fixed:no\n# SUBTRACT LINK32 /profile\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 Fuzz\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Test32___Win32_Fuzz\"\n# PROP BASE Intermediate_Dir \"Test32___Win32_Fuzz\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \".\\binaries32_vc6/\"\n# PROP Intermediate_Dir \".\\binaries32_vc6/\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nF90=fl32.exe\n# ADD BASE F90 /I \"test32/\"\n# ADD F90 /I \"test32/\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /Zi /Od /I \".\\\\\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"CONFIG_FAULTS\" /D \"CONFIG_DIRECT_API\" /FD /c\n# SUBTRACT BASE CPP /YX\n# ADD CPP /nologo /MDd /W3 /Gm /Zi /Od /I \".\\\\\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"CONFIG_FUZZ\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x1409 /d \"_DEBUG\"\n# ADD RSC /l 0x1409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib wsock32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /fixed:no\n# SUBTRACT BASE LINK32 /profile\n# ADD LINK32 kernel32.lib user32.lib wsock32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /fixed:no\n# SUBTRACT LINK32 /profile\n\n!ENDIF \n\n# Begin Target\n\n# Name \"Test32 - Win32 Release\"\n# Name \"Test32 - Win32 Debug\"\n# Name \"Test32 - Win32 Fuzz\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90\"\n# Begin Source File\n\nSOURCE=.\\test\\certimp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\certproc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\certs.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\devices.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\eap.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\envelope.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\highlvl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\keydbx.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\keyfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\loadkey.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\lowlvl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\s_cmp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\s_scep.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\sreqresp.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\ssh.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\ssl.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\stress.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\suiteb.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\testfunc.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\testlib.c\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\utils.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl;fi;fd\"\n# Begin Source File\n\nSOURCE=.\\cryptlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\filename.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\test.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe\"\n# End Group\n# Begin Source File\n\nSOURCE=.\\binaries32_vc6\\cl32.lib\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/cl345/test32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"Test32\"=.\\Test32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/cl345/test32.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25420.1\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Test32\", \"Test32.vcxproj\", \"{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{94F2A49F-90E1-4F46-B636-FA8736318641}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Win32 = Debug|Win32\n\t\tDebug|x64 = Debug|x64\n\t\tRelease|Win32 = Release|Win32\n\t\tRelease|x64 = Release|x64\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Debug|x64.ActiveCfg = Debug|x64\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Debug|x64.Build.0 = Debug|x64\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Release|Win32.Build.0 = Release|Win32\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Release|x64.ActiveCfg = Debug|x64\n\t\t{4C8EB25C-549F-42DA-9F6B-31A0758B5F6B}.Release|x64.Build.0 = Debug|x64\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/cl345/test32ce.vcp",
    "content": "# Microsoft eMbedded Visual Tools Project File - Name=\"Test32\" - Package Owner=<4>\n# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (WCE x86) Application\" 0x8301\n# TARGTYPE \"Win32 (WCE ARMV4) Application\" 0xa301\n# TARGTYPE \"Win32 (WCE SH3) Application\" 0x8101\n# TARGTYPE \"Win32 (WCE emulator) Application\" 0xa601\n# TARGTYPE \"Win32 (WCE MIPSIV) Application\" 0x9601\n\nCFG=Test32 - Win32 (WCE SH3) Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE\n!MESSAGE NMAKE /f \"test32ce.vcn\".\n!MESSAGE\n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE\n!MESSAGE NMAKE /f \"test32ce.vcn\" CFG=\"Test32 - Win32 (WCE SH3) Debug\"\n!MESSAGE\n!MESSAGE Possible choices for configuration are:\n!MESSAGE\n!MESSAGE \"Test32 - Win32 (WCE SH3) Release\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"Test32 - Win32 (WCE SH3) Debug\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"Test32 - Win32 (WCE MIPSIV) Release\" (based on \"Win32 (WCE MIPSIV) Application\")\n!MESSAGE \"Test32 - Win32 (WCE MIPSIV) Debug\" (based on \"Win32 (WCE MIPSIV) Application\")\n!MESSAGE \"Test32 - Win32 (WCE emulator) Release\" (based on \"Win32 (WCE emulator) Application\")\n!MESSAGE \"Test32 - Win32 (WCE emulator) Debug\" (based on \"Win32 (WCE emulator) Application\")\n!MESSAGE \"Test32 - Win32 (WCE ARMV4) Release\" (based on \"Win32 (WCE ARMV4) Application\")\n!MESSAGE \"Test32 - Win32 (WCE ARMV4) Debug\" (based on \"Win32 (WCE ARMV4) Application\")\n!MESSAGE \"Test32 - Win32 (WCE x86) Release\" (based on \"Win32 (WCE x86) Application\")\n!MESSAGE \"Test32 - Win32 (WCE x86) Debug\" (based on \"Win32 (WCE x86) Application\")\n!MESSAGE\n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n# PROP ATL_Project 2\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"SH3Rel\"\n# PROP BASE Intermediate_Dir \"SH3Rel\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"SH3Dbg\"\n# PROP BASE Intermediate_Dir \"SH3Dbg\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3 /align:4096\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"MIPSIVRel\"\n# PROP BASE Intermediate_Dir \"MIPSIVRel\"\n# PROP BASE CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /QMmips4 /QMn32 /QMFPE /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /QMmips4 /QMn32 /QMFPE /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"MIPSIVDbg\"\n# PROP BASE Intermediate_Dir \"MIPSIVDbg\"\n# PROP BASE CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{0B2FE524-26C5-4194-8CEF-B1582DEB5A98}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /QMmips4 /QMn32 /QMFPE /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D \"_MIPS64\" /D \"R4000\" /D \"MIPSIV\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /QMmips4 /QMn32 /QMFPE /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPSFPU\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"emulatorRel\"\n# PROP BASE Intermediate_Dir \"emulatorRel\"\n# PROP BASE CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /YX /Gs8192 /GF /O2 /c\n# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /YX /Gs8192 /GF /O2 /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 $(CEx86Corelibc) coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"emulatorDbg\"\n# PROP BASE Intermediate_Dir \"emulatorDbg\"\n# PROP BASE CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{32E52003-403E-442D-BE48-DE10F8C6131D}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"$(CePlatform)\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d \"$(CePlatform)\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /YX /Gs8192 /GF /c\n# ADD CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /Gs8192 /GF /c\n# SUBTRACT CPP /YX /Yc /Yu\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /subsystem:console /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /MACHINE:IX86\n# ADD LINK32 $(CEx86Corelibc) coredll.lib /nologo /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /subsystem:console /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"ARMV4Rel\"\n# PROP BASE Intermediate_Dir \"ARMV4Rel\"\n# PROP BASE CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /O2 /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /O2 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"ARMV4Dbg\"\n# PROP BASE Intermediate_Dir \"ARMV4Dbg\"\n# PROP BASE CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"X86Rel\"\n# PROP BASE Intermediate_Dir \"X86Rel\"\n# PROP BASE CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /YX /Gs8192 /GF /O2 /c\n# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /YX /Gs8192 /GF /O2 /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 $(CEx86Corelibc) coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"X86Dbg\"\n# PROP BASE Intermediate_Dir \"X86Dbg\"\n# PROP BASE CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"binariesce\"\n# PROP Intermediate_Dir \"binariesce\"\n# PROP CPU_ID \"{D6518FF3-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"$(CePlatform)\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\n# ADD RSC /l 0x409 /d \"$(CePlatform)\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"_X86_\" /d \"x86\" /d \"_i386_\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /YX /Gs8192 /GF /c\n# ADD CPP /nologo /W3 /Zi /Od /I \".\\\\\" /D \"DEBUG\" /D \"_i386_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"i_386_\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /YX /Gs8192 /GF /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n# ADD LINK32 $(CEx86Corelibc) coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"mainACRTStartup\" /debug /nodefaultlib:\"OLDNAMES.lib\" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86\n\n!ENDIF\n\n# Begin Target\n\n# Name \"Test32 - Win32 (WCE SH3) Release\"\n# Name \"Test32 - Win32 (WCE SH3) Debug\"\n# Name \"Test32 - Win32 (WCE MIPSIV) Release\"\n# Name \"Test32 - Win32 (WCE MIPSIV) Debug\"\n# Name \"Test32 - Win32 (WCE emulator) Release\"\n# Name \"Test32 - Win32 (WCE emulator) Debug\"\n# Name \"Test32 - Win32 (WCE ARMV4) Release\"\n# Name \"Test32 - Win32 (WCE ARMV4) Debug\"\n# Name \"Test32 - Win32 (WCE x86) Release\"\n# Name \"Test32 - Win32 (WCE x86) Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=.\\test\\certimp.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nNODEP_CPP_CERTI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\certproc.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nNODEP_CPP_CERTP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTP=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\certs.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_CERTS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_CERTS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\devices.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_DEVIC=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_DEVIC=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\envelope.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_ENVEL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_ENVEL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\highlvl.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_HIGHL=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_HIGHL=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\keydbx.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYDB=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYDB=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\keyfile.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_KEYFI=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_KEYFI=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\loadkey.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOADK=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_LOADK=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\lowlvl.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_LOWLV=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_LOWLV=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\s_cmp.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nNODEP_CPP_S_CMP=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_S_CMP=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\s_scep.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nNODEP_CPP_S_SCE=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_S_SCE=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\sreqresp.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SREQR=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SREQR=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\ssh.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\crypt\\osconfig.h\"\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\crypt\\crypt.h\"\\\n\t\".\\cryptini.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\misc\\bn\\bn.h\"\\\n\t\".\\misc\\crypt.h\"\\\n\t\".\\misc\\misc\\misc_rw.h\"\\\n\t\".\\misc\\misc\\stream.h\"\\\n\t\".\\misc\\stream.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\misc\\misc_rw.c\"\\\n\t\".\\test\\misc_rw.c\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSH_C=\\\n\t\".\\bn\\bn.h\"\\\n\t\".\\crypt.h\"\\\n\t\".\\crypt\\osconfig.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\io\\stream.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\misc_rw.c\"\\\n\t\".\\misc\\misc_rw.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\misc\\pgp.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\t{$(INCLUDE)}\"stream.h\"\\\n\nNODEP_CPP_SSH_C=\\\n\t\".\\bn\\osconfig.h\"\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\misc\\bn.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\test\\misc_rw.c\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\ssl.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_SSL_C=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_SSL_C=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\stress.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_STRES=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_STRES=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\testlib.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\test\\binaries\\vld.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\testfunc.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\cryptini.h\"\\\n\t\".\\test\\crypt.h\"\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_TESTL=\\\n\t\".\\crypt.h\"\\\n\t\".\\cryptkrn.h\"\\\n\t\".\\cryptlib.h\"\\\n\t\".\\misc\\config.h\"\\\n\t\".\\misc\\consts.h\"\\\n\t\".\\misc\\int_api.h\"\\\n\t\".\\misc\\os_spec.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_TESTL=\\\n\t\".\\config.h\"\\\n\t\".\\consts.h\"\\\n\t\".\\int_api.h\"\\\n\t\".\\os_spec.h\"\\\n\t\".\\test\\binaries\\vld.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\utils.c\n\n!IF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Release\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE MIPSIV) Debug\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Release\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE emulator) Debug\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Release\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE ARMV4) Debug\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Release\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\nNODEP_CPP_UTILS=\\\n\t\".\\test\\cryptlib.h\"\\\n\t\".\\test\\test\\filename.h\"\\\n\t\".\\test\\test\\test.h\"\\\n\n\n!ELSEIF  \"$(CFG)\" == \"Test32 - Win32 (WCE x86) Debug\"\n\nDEP_CPP_UTILS=\\\n\t\".\\cryptlib.h\"\\\n\t\".\\test\\filename.h\"\\\n\t\".\\test\\test.h\"\\\n\n\n!ENDIF\n\n# End Source File\n# Begin Source File\n\nSOURCE=.\\binariesce\\cl32ce.lib\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=.\\cryptlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=.\\test\\test.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/cl345/test32ce.vcw",
    "content": "Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"Test32\"=.\\test32ce.vcp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/cl345/tools/GenPas.pl",
    "content": "#!/usr/bin/perl\n# script to translate th cryptlib C interface into a Delphi (Pascal) interface module\n# Copyright (C) 2003-2004 Wolfgang Gothier\n\n#####\n#       G E N P A S . P L   $Id: GenPas.pl 39 2010-10-21 16:28:47Z wogo $\n#       -----------------------------------------------------------------------\n#\n#       PERL script for translation of the cryptlib header file\n#            into a Delphi (R) interface file for Cryptlib (CL32.DLL).\n#\n#            This script does the translation of C-statements into\n#            Pascal (Delphi) code. (But only as much as is needed in \n#            cryptlib.h, -NOT- usable as general translation utility)\n#\n#       --------------------------------------------------------------------\n#\n#       SYNTAX:\n#           perl GenPas.pl <cryptlib.h>\n#\n#               cryptlib.h ... (optional) Pathname of crytlib header file\n#                              default is \"cryptlib.h\"\n#\n#               creates the Delphi interface file with same basic name \n#               and extension \".pas\" in the same directory as the source file\n#               default is \"cryptlib.pas\"\n#\n#####\nuse strict;\nuse warnings;\n\nuse File::stat;\nuse File::Basename;\n\nmy $FileName = shift @ARGV || 'cryptlib.h';\t\t# default filename is \"cryptlib.h\"\nmy %DEFINED = ( 1, 1,                         # ifdef 1 is to be included\n                \"USE_VENDOR_ALGOS\", 0 );\t\t\t# set to 1 to include #IFDEF USE_VENDOR_ALGOS\nmy $Startline = qr{^#endif\\s+\\/\\*\\s+_CRYPTLIB_DEFINED\\s+\\*\\/};\t# ignore all lines before this one\n\nmy ($FileBase, $Path, $Ext) = fileparse($FileName, qr{\\.[^.]*$});\ndie(\"\\\"usage: $0 cryptlib.h\\\"\\nParameter must be a C header file\\nStop\") unless ($Ext =~ m/^\\.h$/i) && -r $FileName;\nmy ($Infile, $Outfile) = ($Path.$FileBase.'.h', $Path.$FileBase.'.pas');\nmy $cryptlib_version;\n\nopen(INFILE, \"<$Infile\") or die \"Open error on $Infile: $!\";\nopen (OUTFILE, \">$Outfile\") or die \"Open error on $Outfile: $!\";\nprint \"Transforming \\\"$Infile\\\" into \\\"$Outfile\\\"\\n\";\nmy $Default = select(OUTFILE);\n\n# Ignore all input lines before (and including) $Startline (except version def)\nwhile (<INFILE>) {\n\t$cryptlib_version = $_ if m{#define\\s+CRYPTLIB_VERSION\\s+};\n\tlast if m/$Startline/;\n}\n\n# array to contain the preprocessed input lines:\nmy @source;\n\npush @source, PascalHeader($Infile);\npush @source, $cryptlib_version if $cryptlib_version;\n\nmy $INACTIVE = 0;\nmy $LEVEL = 0;\n# handle conditionals, include conditional code only if definition agrees with %DEFINED\nwhile (<INFILE>) { \n    # remove preprocessor symbols\n    s/C_CHECK_RETVAL//;\n    s/C_NONNULL_ARG\\s*\\(\\s*\\([ \\t0-9,]+\\s*\\)\\s*\\)//;\n\n    # remove tabs\n    1 while s/\\t/' ' x (length($&)*4 - length($`)%4)/e;\n\n    if (/^\\s*#if(\\s|def\\s)(\\w+)/) {\t\t\n        $LEVEL += 1;\n        $INACTIVE += 1 unless $DEFINED{$2};\n        next;\n    }\n    if (/^\\s*#if\\s\\(/) {\t\t#if (anyexpression) assumed always false\n        $LEVEL += 1;\n        $INACTIVE += 1;\n        next;\n    }\n    if (/^\\s*#ifndef\\s(\\w+)/) {\n        $LEVEL += 1;\n        $INACTIVE += 1 if $DEFINED{$1};\n        next;\n    }\n    if (/^\\s*#(else|elif)\\b/) {\n        $INACTIVE = 1-$INACTIVE;\n        next;\n    }\n    if (/^\\s*\\#endif\\b/) {\n        $LEVEL -= 1;\n        $INACTIVE = 0;\n        next;\n    }\n\n    push @source, $_ unless $INACTIVE;\n}\n\n# preprocessing finished, translation to pascal code follows\n\nmy $const=\"\\nconst\\n\";\nmy $type=\"\\ntype\\n\";\n\nwhile ($_ = shift @source) {\n\t\t# ignore special C++ handling\n    if (/#ifdef\\s+__cplusplus/) {\n        $_ = shift @source  while (!(/#endif/));\n        $_ = shift @source;\n    }\n    \n    # continued lines\n    if (s/\\\\$//) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete typedef / enum lines\n    if (/^\\s*(typedef\\s+enum|typedef\\s+struct|enum)\\s*\\{[^}]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete procedure calls\n    if (/^\\s*C_RET\\s+\\w+\\s*\\([^)]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n\t\t# lines are complete now, do the translation\n\n\t\t# constant definitions\n    if (s/^\\s*#define\\s+(\\w+)\\s+(\\w+|[+\\-0-9]+)/$const  $1 = $2;/) {\n        $const=\"\";\n        $type=\"\\ntype\\n\";\n    }\n    \n\t\t# constant definitions with parenthesis\n    if (s/^\\s*#define\\s+(\\w+)\\s+\\(\\s*(\\w+|[+\\-0-9]+)\\s*\\)/$const  $1 = $2;/) {\n        $const=\"\";\n        $type=\"\\ntype\\n\";\n    }\n    \n    # hex values\n    s{0x([0-9a-fA-F]+)}{\\$$1}g;\n    \n    # typedef struct\n    if (s!^(\\s*)typedef\\s+struct\\s*{([^}]*)}\\s*(\\w+)\\s*;!&typelist(split(/;/,$2))!e) {\n        $_ = \"$1$type  $3 = record  $_\\n  end;\\n\";\n        $type=\"\";\n        $const=\"\\nconst\\n\"\n    }\n\n\t\t# typedef enum ( with intermediate constant definitions )\n    if (s!^\\s*typedef\\s+enum\\s*{([^}]+=\\s*\\d+\\b[^}]+)}\\s*(\\w+);!&enumt(split(/\\n/,$1))!e) {\n        $_ = \"$type $2 = Integer;\\nconst\\n$_\\n\";\n        $const=\"\";\n        $type=\"\\ntype\\n\";\n    }\n\n\t\t# typedef enum\n    if (s/^\\s*typedef\\s+enum\\s*{([^}]+)}\\s*(\\w+);/$type  $2 = (  $1\\n  );/) {\n    \t\tmy $Typeis = $2;\n        my %redefs;\n        # check, if there are embedded redefinitions\n        while (s!\\s*(\\w+)\\s*=\\s*([_a-zA-Z]\\w+),!!g) { \n        \t\t$redefs{$1} = $2 if $1;\n        };\n        $type=\"\";\n        $const=\"\\nconst\\n\";\n        if (%redefs) {\n        \t\t# handle embedded redefinitions after type definition\n        \t\t$_ .= $const;\n        \t\t$const=\"\";\n        \t\t$type=\"\\ntype\\n\";\n        \t\tfor my $redef (keys %redefs) {\n        \t\t\t\t$_ .= \"  $redef: $Typeis = $redefs{$redef};\\n\";\n        \t\t}\n        }\n    }\n\n\t\t# \"simple\" typedef\n    if (s/^\\s*typedef\\s+(\\w+)\\s+(\\w+);/\"$type  $2 = \".&typeconv($1).\";\"/e) {\n        $type=\"\";\n        $const=\"\\nconst\\n\"\n    }\n\n\t\t# \"simple\" enum\n    if (s!^\\s*enum\\s*{([^}]+)}\\s*;!&enums(split(/,/,$1))!e) {\n        $_ = \"\\n$const$_\\n\";\n        $const=\"\";\n        $type=\"\\ntype\\n\";\n    }\n\n\t\t\n    s/(\\s*)#ifdef\\s+(\\w+)/$1\\{\\$IFDEF $2\\}/g;\n    s/(\\s*)#if\\s+0\\b/$1\\{\\$IFDEF false\\}/g;\n    s/(\\s*)#if\\s+1\\b/$1\\{\\$IFDEF true\\}/g;\n    s/(\\s*)#endif\\s*/$1\\{\\$ENDIF\\}\\t/g;\n    \n    # translate comments\n    s/\\/\\*\\*/{**/g;\n    s/\\/\\* /{  /g;\n    s/\\*\\*\\//**}/g;\n    s/\\ \\*\\//  }/g;\n    s/\\*\\//}/g;\n\n\t\t# functions without parameters\n    s/\\bC_RET\\s*(\\w+)\\s*\\(\\s*void\\s*\\)\\s*;/function $1: Integer;\\n{\\$IFDEF WIN32} stdcall; {\\$ELSE} cdecl; {\\$ENDIF} external cryptlibname;\\n\\n/;\n\n\t\t# function declarations with parameters\n    if (s/^\\s*C_RET\\s*(\\w+)\\s*\\(\\s*([^\\)]+)\\s*\\)\\s*;/&convpar(split(\\/\\,\\/,$2))/e) {\n        chomp($_);\n        $_ = \"function $1( $_ ): Integer;\\n{\\$IFDEF WIN32} stdcall; {\\$ELSE} cdecl; {\\$ENDIF} external cryptlibname;\\n\\n\";\n    }\n\n\t\t# C-macro definitions are ignored\n    if (s/\\s*#define\\s+(.*)/$1/) {\n        s/\\{/</g;\n        s/\\}/>/g;\n        s/\\s+$//;\n        $_ = \"{ C-macro not translated to Delphi code: \\n{   #define $_ }\\n\";\n    }\n\n\t\t# translation is done, output lines now\n    print \"$_\" if @source;\n}\nprint PascalFooter();\n\nselect($Default);\n\nexit;\n\n# subroutine definitions follow:\n\nsub PascalHeader {\n\tmy $Infile = shift;\n\tmy $fstat = stat($Infile) if (-f $Infile && -r $Infile) or die \"$Infile not readable\";\n\tmy $infile_size = $fstat->size;\n\tmy $infile_time = localtime($fstat->mtime);\n\tmy $filename = basename($Infile);\n\tmy $now = (localtime())[5]+1900;\nreturn <<ENDOFHEADER;\nunit cryptlib;\n\ninterface\n\n{****************************************************************************\n*                                                                           *\n*                     Cryptlib external API interface                       *\n*                    Copyright Peter Gutmann 1997-$now                      *\n*                                                                           *\n*        adapted for Delphi Version 5 (32 bit) and Kylix Version 3          *\n*                              by W. Gothier                                *\n****************************************************************************}\n\n\n{------------------------------------------------------------------------------\n\n This file has been created automatically by a perl script from the file:\n\n \"$filename\" dated $infile_time, filesize = $infile_size.\n\n Please check twice that the file matches the version of $filename\n in your cryptlib source! If this is not the right version, try to download an\n update from \"http://cryptlib.sogot.de/\". If the filesize or file creation\n date do not match, then please do not complain about problems.\n\n Published by W. Gothier, \n mailto: problems\\@cryptlib.sogot.de if you find errors in this file.\n\n-------------------------------------------------------------------------------}\n\n{\\$A+}  {Set Alignment on}\n{\\$F+}  {Force function calls to FAR}\n{\\$Z+}  {Force all enumeration values to Integer size}\n\nconst\n  {\\$IFDEF WIN32}\n    cryptlibname = 'CL32.DLL';  { dynamic linkname for Windows (Delphi) }\n  {\\$ELSE}\n    cryptlibname = 'libcl.so';  { library name for Unix/Linux  (Kylix) }\n                 { symbolic link should be used for libcl.so -> libcl.so.3.x.y }\n  {\\$ENDIF}\n\nENDOFHEADER\n\n}\n\nsub PascalFooter {\nreturn <<ENDFOOTER;\n\n\nimplementation\n\n{ no implementation code now }\n\nend.\nENDFOOTER\n}\n\n# subroutine to handle simple enum elements\nsub enums {\n    my $Index = 0; # startvalue = 0 for enum entries\n    my $_S;\n    foreach (@_) {\n        chomp;\n        s/^\\s+//;   # delete leading whitespace\n        s!/\\*!{!g; # translate comment brackets\n        s!\\*/!}!g;\n        if (m/(\\{[^\\}]*\\})?\\s*\\w+\\s*=\\s*(\\d+).*$/) {\n        \t\t# new value is being set, $index must be updated\n            $_S .= \"  $_;\\n\";\n            eval($Index = $2+1);\n        }\n        else {\n            $_S .= \"  $_ = \".$Index++.\";\\n\";\n        }\n    }\n    return $_S;\n}\n\n# subroutine to handle typedef enum ( with intermediate constant definitions )\nsub enumt {\n    my $INDEX = 0;\n    my $LINES = \"\";\n    my %VALS;\n    my $tmp;\n    my $comment;\n    LOOP: foreach (@_) {\n        chomp;\n        s/^\\s+//;\n        s/\\s+$//;\n        s/\\/\\*/{/g;\n        s/\\*\\//}/g;\n        # multiline comments\n        if ($comment or m!{[^}]*$!) {\n        \t\t$LINES .= \"  $_\\n\";\n        \t\t$comment = not m!}!;\n        \t\tnext LOOP if $comment;\n        \t\ts!.*}!!;\n        \t\tnext unless $_ eq \"\\n\";\n        }\n        # comment only line\n        if (m!{[^}]}$!) {\n        \t\t$LINES .= \"  $_\\n\";\n        \t\tnext LOOP;\n        }\n        # enumval = enumval +/- number\n        elsif (m/^(\\w+)\\s*=\\s*(\\w+)\\s*([-+])\\s*(\\d+),?(.*)$/) {\n            eval( $tmp = eval(\"$VALS{$2} $3 $4\") );\n            $LINES .= \"  $1 = $tmp;\";\n            $VALS{$1} = $tmp;\n            eval($INDEX = $tmp+1);\n            $_ = $5;\n            redo LOOP;\n        }\n        # enumval = number\n        elsif (m/^(\\w+)\\s*=\\s*(\\d+),?(.*)$/) {\n            $LINES .= \"  $1 = $2;\";\n            $VALS{$1} = $2;\n            eval($INDEX = $2+1);\n            $_ = $3;\n            redo LOOP;\n        }\n        # enumval = enumval\n        elsif (m/^\\s*(\\w+)\\s*=\\s*(\\w+),?(.*)$/) {\n            $tmp = $VALS{$2};\n            $LINES .= \"  $1 = $tmp; { = $2 }\";\n            $VALS{$1} = $tmp;\n            $_ = $3;\n            redo LOOP;\n        }\n        # enumval,\n        elsif (m/^\\s*(\\w+)\\,?(.*)$/) {\n            $LINES .= \"  $1 = $INDEX;\";\n            $VALS{$1} = $INDEX;\n            $INDEX += 1;\n            $_ = $2;\n            redo LOOP;\n        }\n        else { $LINES .= \"  $_\\n\" }\n    }\n    return $LINES;\n}\n\n# subroutine to translate struct elements into record elements\nsub typelist {\n    my $tmp = \"\";\n    foreach  (@_) {\n    \t\t# handle comment at start of splitted line\n        while ($_ =~ s!^(\\s*)/\\*(.+)\\*/!!s) {\n            $tmp .= $1.'{'.$2.'}';\n        }\n        # translate fields into arrays \n        if (s!^(\\s*)(.*)\\s+(\\w+)\\s*\\[\\s*(\\w+)\\s*\\]\\s*$!!) {\n            $tmp .= \"$1$3: array[0 .. $4-1] of \".&typeconv($2).\";\";\n        }\n        # translate normal elements\n        elsif (s!^(\\s*)(\\w+)\\s+(\\w+)\\s*$!!) {\n            $tmp .= \"$1$3: \".&typeconv($2).\";\";\n        }\n        # copy line, if nothing matched\n        else {\n\t\t\t$tmp .= $_;\n\t\t\t$tmp .= \";\" unless $_;\n\t\t}\n    }\n    return $tmp;\n}\n\n# subroutine transforms some C types to Delphi types\nsub typeconv {\n    my $param = shift;\n    return $param if $param =~ s/\\bint\\b/Integer/;\t\t\t\t\t#\tint    \t\t\t\t-> Integer\n    return $param if $param =~ s/\\bunsigned char\\b/byte/;\t\t# unsigned char\t-> byte\n    return $param if $param =~ s/\\bvoid\\s+C_PTR\\b/Pointer/;\t# void C_PTR\t\t-> Pointer\n    return $param if $param =~ s/\\bvoid\\b/Pointer/;\t\t\t\t\t# void\t\t\t\t\t-> Pointer\n    return $param if $param =~ s/\\bchar\\s+C_PTR\\b/PAnsiChar/;\t\t# char C_PTR\t\t-> PAnsiChar\n    return $param if $param =~ s/\\bC_STR\\b/PAnsiChar/;\t\t\t\t\t# char C_PTR\t\t-> PAnsiChar\n    return $param if $param =~ s/\\bC_CHR\\b/char/;\t\t\t\t\t\t# char C_PTR\t\t-> PAnsiChar\n    return $param;\n}\n\n# subroutine to convert a list or function parameters\nsub convpar {\n    my @tmp;\n    LOOP: \n    foreach (@_) {\n        push( @tmp, &convpar1($_) );\n    }\n    return join(\";\\n  \", @tmp);\n}\n\n# subroutine to translate C params to Delphi params\nsub convpar1 {\n    my $par = shift;\n    return \"const $3: $par\" if ($par =~ s/^\\s*(C_IN\\s+|C_IN_OPT\\s+)(.+)\\s+(\\w+)\\s*/&typeconv($2)/e);\n    return \"$2: $par\"       if ($par =~ s/^\\s*C_INOUT\\s+(.+)\\s+(\\w+)\\s*/&typeconv($1)/e);\n    return \"$par\"           if ($par =~ s/^\\s*(C_OUT\\s+|C_OUT_OPT\\s+)void\\s+C_PTR\\s+(\\w+)\\s*/$2: Pointer/);\n    return \"var $3: $par\"   if ($par =~ s/^\\s*(C_OUT\\s+|C_OUT_OPT\\s+)(.+)\\s+(?:C_PTR)?\\s+(\\w+)\\s*/&typeconv($2)/e);\n    return $par;\n}\n"
  },
  {
    "path": "deps/cl345/tools/GenPerl.pl",
    "content": "#!/usr/bin/perl\n# script to translate th cryptlib C interface into a Perl header interface module\n# Copyright (C) 2007 Alvaro Livraghi\n\n#####\n#       G E N P E R L . P L   Version 0.2 (last changes 2008-08-17)\n#       --------------------------------------------------------------------\n#       Based upon GenVB.pl by Wolfgang Gothier\n#\n#       PERL script for translation of the cryptlib header file\n#            into a Perl header file used by Perl interface package \n#            for Cryptlib (PerlCryptLib.pm).\n#\n#            This script does the translation of C-statements into\n#            Perl code. (But only as much as is needed in \n#            cryptlib.h, -NOT- usable as general translation utility)\n#\n#       --------------------------------------------------------------------\n#\n#       SYNTAX:\n#           perl GenPerl.pl <cryptlib.h> <PerlCryptLib.ph>\n#\n#               cryptlib.h ........ (optional) Pathname of crytlib header file\n#                                              default is \"cryptlib.h\"\n#               PerlCryptLib.ph ... (optional) Pathname of PerlCrytLib header file\n#                                              default is \"PerlCryptLib.ph\"\n#\n#               creates the Perl interface file with same basic name \n#               and extension \".ph\" in the same directory as the source file\n#               default is \"PerlCryptLib.ph\"\n#\n#####\n\nuse strict;\nuse warnings;\n\nuse File::stat;\nuse File::Basename;\nuse Data::Dumper;\n#use Tie::IxHash;\n\nmy $C = \"C\\t\";\nmy $PERL = \"PERL\\t\";\n\nmy $DEBUG = grep /^--debug$/, @ARGV;\t\t\t# print debug info on STDERR\nmy $inFileName  = shift @ARGV || 'cryptlib.h';\t# default filename is \"cryptlib.h\"\nmy %DEFINED = ( 1, 1,                     \t\t# ifdef 1 is to be included\n                \"USE_VENDOR_ALGOS\", 0 );\t\t# set to 1 to include #IFDEF USE_VENDOR_ALGOS\nmy $Startline = qr{^#define C_INOUT};\t\t\t# ignore all lines before this one\n\nmy ($inFileBase, $inPath, $inExt) = fileparse($inFileName, qr{\\.[^.]*$});\ndie(\"\\\"usage: $0 cryptlib.h\\\"\\nParameter must be a C header file\\nStop\") unless ($inExt =~ m/^\\.h$/i) && -r $inFileName;\n\nmy $outFileName = shift @ARGV || $inPath.'PerlCryptLib.ph';\t\t# default filename is \"PerlCryptLib.ph\"\nmy ($outFileBase, $outPath, $outExt) = fileparse($outFileName, qr{\\.[^.]*$});\n\nmy ($Infile, $Outfile) = ($inPath.$inFileBase.'.h', $outPath.$outFileBase.$outExt);\nmy $cryptlib_version;\n\nopen(INFILE, \"<$Infile\") or die \"Open error on $Infile: $!\";\nopen (OUTFILE, \">$Outfile\") or die \"Open error on $Outfile: $!\";\nprint \"Transforming \\\"$Infile\\\" into \\\"$Outfile\\\"\\n\";\nmy $Default = select(OUTFILE);\n\nprint STDERR qq[\n${C}#include <stdio.h>\n${C}#include <stdlib.h>\n${C}#include \"$Infile\"\n${C}int main(void) {\n] if $DEBUG;\n\nprint STDERR qq[\n${PERL}#!/usr/bin/perl -W\n${PERL}use strict;\n${PERL}use warnings;\n${PERL}require \"$Outfile\";\n] if $DEBUG;\n\n\n\n# Ignore all input lines before (and including) $Startline\nwhile (<INFILE>) {\n\t$cryptlib_version = $_ if m{#define\\s+CRYPTLIB_VERSION\\s+};\n\tlast if m/$Startline/;\n}\n\n# array to contain the preprocessed input lines:\nmy @source;\n\npush @source, PERLHeader($Infile);\npush @source, $cryptlib_version if $cryptlib_version;\n\nmy $INACTIVE = 0;\nmy $LEVEL = 0;\nmy $COMMENT = 0;\n# handle conditionals, include conditional code only if definition agrees with %DEFINED\nwhile (<INFILE>) { \n\n\t\t# remove tabs\n\t\t1 while s/\\t/' ' x (length($&)*4 - length($`)%4)/e;\n\n    if (/^\\s*#if(\\s|def\\s)(\\w+)/) {\n        $LEVEL += 1;\n        $INACTIVE += 1 unless $DEFINED{$2};\n        next;\n    }\n    if (/^\\s*#if\\s\\(/) {\t\t#if (anyexpression) assumed always false\n        $LEVEL += 1;\n        $INACTIVE += 1;\n        next;\n    }\n    if (/^\\s*#ifndef\\s(\\w+)/) {\n        $LEVEL += 1;\n        $INACTIVE += 1 if $DEFINED{$1};\n        next;\n    }\n    if (/^\\s*#(else|elif)\\b/) {\n        $INACTIVE = 1-$INACTIVE;\n        next;\n    }\n    if (/^\\s*\\#endif\\b/) {\n        $LEVEL -= 1;\n        $INACTIVE = 0;\n        next;\n    }\n\n    # translate comments\n    if (/\\/\\*(.*)\\*\\/\\s*$/) {\n        if ($1 !~ m(\\*/)) {\n            s!/\\*(.*)\\*/\\s*$!#$1\\n!\n        }\n    }\n\n    if ($COMMENT) {\n        $_ = \"#\".$_ unless s/^ /#/;\n        $COMMENT = 0 if s/\\*\\/\\s*$/\\n/;\n        s/\\*\\*$/***/;\n    }\n    $COMMENT = 1 if s/^(\\s*)\\/\\*\\*(.*)$/#**$1$2/;\n    $COMMENT = 1 if s/^(\\s*)\\/\\*(.*)$/#$1 $2/;\n\n    push @source, $_ unless $INACTIVE;\n}\n\n# preprocessing finished, translation to PERL code follows\n\nmy $Warn=\"\";\n\nwhile ($_ = shift @source) {\n\n\t# ignore special C++ handling\n    if (/#ifdef\\s+__cplusplus/) {\n        $_ = shift @source  while (!(/#endif/));\n        $_ = shift @source;\n    }\n    \n    # continued lines\n    if (s/\\\\$//) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # continued function declaration\n    if (s/\\,s*?$/,/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete typedef / enum lines\n    if (/^\\s*(typedef\\s+enum|typedef\\s+struct|enum)\\s*\\{[^}]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete procedure calls\n    if (/^\\s*C_RET\\s+\\w+\\s*\\([^)]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n\t# lines are complete now, do the translation\n\n    # hex values\n    #s{0x([0-9a-fA-F]+)}{&H$1}g;\n    \n\t# constant definitions\n\t#s/^\\s*#define\\s+(\\w+)\\s+(\\w+|[+\\-0-9]+|&H[0-9a-fA-F]+)/  Public Const $1 As Long = $2/;\n\t#s/^\\s*#define\\s+(\\w+)\\s+(\\w+|[+\\-0-9]+|&H[0-9a-fA-F]+)/\\tsub $1 { $2 }/;\n\ts/^\\s*#define\\s+(\\w+)\\s+\\(?\\s*(\\w+|[+\\-0-9]+|&H[0-9a-fA-F]+)\\s*\\)?\\s*/\\tsub $1 { $2 }\\n/;\n\n    # typedef struct\n    if (s!^(\\s*)typedef\\s+struct\\s*{([^}]*)}\\s*(\\w+)\\s*;!&typelist(split(/;/,$2))!e) {\n        $_ = \"sub $3\\n{\\n\\t{\\n$_\\t}\\n}\\n\";\n    }\n\n\t# typedef enum ( with intermediate constant definitions )\n    if (s!^\\s*typedef\\s+enum\\s*{([^}]+=\\s*\\d+\\b[^}]+)}\\s*(\\w+);!&enumt(split(/\\n/,$1))!e) {\n        $_ = \"##### BEGIN ENUM $2 $_##### END ENUM $2\\n\";\n    }\n\n\t# typedef enum\n    if (s!^\\s*typedef\\s+enum\\s*{([^}]+)}\\s*(\\w+);!&enumt(split(/\\n/,$1))!e) {\n        $_ = \"##### BEGIN ENUM $2\\n$_##### END ENUM $2\\n\";\n    }\n\n\t# \"simple\" typedef\n    s/^\\s*typedef\\s+(\\w+)\\s+(\\w+);/sub $2 { 0 }/;\n\n\t# \"simple\" enum\n    s!^\\s*enum\\s*{([^}]+)}\\s*;!&enums(split(/,/,$1))!e;\n\n\t# translate function declarations without params\n\tif ( s/(\\bC_RET\\s*\\w+\\s*\\(\\s*[^)]+\\s*\\)\\s*;)/#$1/ ) {\n\t\ts/\\n/\\n#/g;\n\t}\n\t\n\tif ( s/^(\\s*?)(C_CHECK_RETVAL|C_NONNULL_ARG)(.*?)/# $1$2$3/ ) {\n\t\ts/\\n/\\n#/g;\n\t}\n\n\t# C-macro definitions are ignored\n    if (s/\\s*#define\\s+(.*)/$1/) {\n        s/\\n/\\n#/g;\n        s/\\s+$//;\n        $_ = \"# C-macro not translated to Perl code but implemented apart: \\n#   #define $_\\n\";\n    }\n\n\t# translation is done, output lines now\n    print \"$_\" if @source;\n}\nprint PERLFooter();\n\nprint STDERR qq[\n${C}return 0;\n${C}}\n] if $DEBUG;\n\nprint STDERR qq[\n${PERL}exit(0);\n] if $DEBUG;\n\nselect($Default);\n\nexit 0;\n\n# subroutine definitions follow:\n\nsub PERLHeader {\n\tmy $Infile = shift;\n\tmy $fstat = stat($Infile) if (-f $Infile && -r $Infile) or die \"$Infile not readable\";\n\tmy $infile_size = $fstat->size;\n\tmy $infile_time = localtime($fstat->mtime);\n\tmy $filename = basename($Infile);\n\tmy $now = (localtime())[5]+1900;\nreturn <<ENDOFHEADER;\n\n# *****************************************************************************\n# *                                                                           *\n# *                        cryptlib External API Interface                    *\n# *                       Copyright Peter Gutmann 1997-$now                   *\n# *                                                                           *\n# *                 adapted for Perl Version 5.x  by Alvaro Livraghi          *\n# *****************************************************************************\n#\n#\n# ----------------------------------------------------------------------------\n#\n# This file has been created automatically by a perl script from the file:\n#\n# \"$filename\" dated $infile_time, filesize = $infile_size.\n#\n# Please check twice that the file matches the version of $filename\n# in your cryptlib source! If this is not the right version, try to download an\n# update from CPAN web site. If the filesize or file creation date do not match,\n# then please do not complain about problems.\n#\n# Published by Alvaro Livraghi, \n# mailto: perlcryptlib\\@gmail.com if you find errors in this file.\n#\n# -----------------------------------------------------------------------------\n#\n\nENDOFHEADER\n\n}\n\nsub PERLFooter {\nreturn <<ENDFOOTER;\n\n#\n# *****************************************************************************\n# *                                                                           *\n# *                    End of Perl Functions                                  *\n# *                                                                           *\n# *****************************************************************************\n#\n\n1; ##### End-of perl header file!\n\nENDFOOTER\n}\n\n# subroutine to handle simple enum elements\nsub enums {\n    my $Index = 0; # startvalue = 0 for enum entries\n    my $_S;\n    foreach (@_) {\n        chomp;\n        s/^\\s+//;   # delete leading whitespace\n        if (m/(\\w+)\\s*=\\s*(\\d+).*$/) {\n        \t\t# new value is being set, $index must be updated\n            $_S .= \"  sub $1 { $2 }\\n\";\n\t\t\tprint STDERR qq{${C}printf(\"$1: \\%d\\\\n\", $1);\\n} if $DEBUG;\n\t\t\tprint STDERR qq{${PERL}print \"$1: \", \\&$1(), \"\\\\n\";\\n} if $DEBUG;\n            eval($Index = $2+1);\n        }\n        else {\n            $_S .= \"  sub $_ { \".$Index++.\" }\\n\";\n\t\t\tprint STDERR qq{${C}printf(\"$_: \\%d\\\\n\", $_);\\n} if $DEBUG;\n\t\t\tprint STDERR qq{${PERL}print \"$_: \", \\&$_(), \"\\\\n\";\\n} if $DEBUG;\n        }\n    }\n    return $_S;\n}\n\n# subroutine to handle typedef enum ( with intermediate constant definitions )\nsub enumt {\n    my $LINES = \"\";\n    my $parval;\n\tmy $lastValue = 0;\n\t#tie my %values, 'Tie::IxHash', ();\n\tmy %values = ();\n\tmy @lines = @_;\n    foreach my $parval1 (@lines) {\n    \t#my ($val, $rem, $name, $value);\n\t\tmy ($val1, $rem) = split('#', $parval1, 2);\n\t\t$rem = '' unless $rem;\n\t\t$rem =~ s/^\\s*(.*?)\\s*$/$1/;\n\t\t$LINES .= ($rem ? \"\\t# $rem\" : '') . \"\\n\";\n\t\t$val1 = '' unless $val1;\n\t\t$val1 =~ s/^\\s*(.*?)\\s*$/$1/;\n\t\tnext unless $val1;\n    \tforeach $parval (split(',',$val1)) {\n    \t\tlast unless defined($parval);\n\t    \tmy ($val, $name, $value);\n\t\t\t($val = $parval) =~ s/^\\s*(.*?)\\s*$/$1/;\n\t\t\t#$val = '' unless $val;\n\t\t\t#$val =~ s/^\\s*(.*?)\\s*$/$1/;\n\t\t\tif ( $val ne '' ) {\n\t\t\t\t($name, $value) = split('=', $val, 2);\n\t\t\t\t$name = '' unless $name;\n\t\t\t\t$name =~ s/^\\s*(.*?)[\\s\\,]*$/$1/;\n\t\t\t\t$value = '' unless $value;\n\t\t\t\t$value =~ s/^\\s*(.*?)[\\s\\,]*$/$1/;\n\t\t\t\tif ( $value eq ''  ||  $value =~ /^\\d/ ) {\n\t\t\t\t\t$value = $lastValue unless $value;\n\t\t\t\t\t#$lastValue = $value + 1;\n\t\t\t\t} else {\n\t\t\t\t\t#$rem .= ' ==> ' . $value;\n\t\t\t\t\t#$lastValue = \n\t\t\t\t\t$value = eval( join(' ', map { exists($values{$_}) ? $values{$_} : $_ } split(/\\s+/,$value)) );\n\t\t\t\t}\n\t\t\t\t$lastValue = $value + 1;\n\t\t\t}\n\t\t\tif ( $name ) {\n\t\t\t\t#$lastValue = $value;\n\t\t\t\tforeach my $curname (split(',', $name)) {\n\t\t\t\t\t$curname =~ s/^\\s*(.*?)\\s*$/$1/;\n\t\t\t\t\t$values{$curname} = $value;\n\t\t\t        #$LINES .= ($curname ? \"\\tsub $curname { $value }\" : '') . ($rem ? \"\\t# $rem\" : '') . \"\\n\";\n\t\t\t        $LINES .= ($curname ? \"\\tsub $curname { $value }\" : '') . \"\\n\";\n\t\t\t\t\t#++$lastValue;\n\t\t\t\t\t#print STDERR \"$curname = $value\\n\";\n\t\t\t\t\tprint STDERR qq{${C}printf(\"$curname: \\%d\\\\n\", $curname);\\n} if $DEBUG;\n\t\t\t\t\tprint STDERR qq{${PERL}print \"$curname: \", \\&${curname}(), \"\\\\n\";\\n} if $DEBUG;\n\t\t\t\t}\n\t\t\t} else {\n\t\t        #$LINES .= ($rem ? \"\\t# $rem\" : '') . \"\\n\";\n\t\t\t}\n    \t}\n    }\n    #print STDERR Dumper(\\%values);\n    return $LINES;\n}\n#   handle the lines of a \"typedef struct { ... } structname\"\nsub typelist {\n    my $tmp = \"\";\n\tmy $first = 0;\n    foreach my $par (@_) {\n        while ($par =~ s/^(\\s*)\\#(.+)\\n(.*)/$3/) {   # embedded comments\n            $tmp .= \"\\t# $2\\n\";\n        }\n        if ($par =~ s/^(\\s*)(.*)\\s(\\w+)\\s*\\[\\s*(\\w+)\\s*\\]\\s*$//) {    # index conversion\n            $tmp .= $1 . (!$first++ ? ' ' : ',') . \"$3 => ' ' x $4\";\n        }\n        elsif ($par =~ s/^(\\s*)(.*)\\s(\\w+)\\s*$//) {  # normal conversion\n            $tmp .= $1 . (!$first++ ? ' ' : ',') . \"$3 => 0\";\n        }\n        else {$tmp .= $par}                          # leave it alone\n    }\n    return $tmp;\n}\n\n\n"
  },
  {
    "path": "deps/cl345/tools/GenVB.pl",
    "content": "#!/usr/bin/perl\n# script to translate th cryptlib C interface into a Visual Basic interface module\n# Copyright (C) 2003-2004 Wolfgang Gothier\n\n#####\n#       G E N V B . P L   $Id: GenVB.pl,v 1.3 2009/07/13 20:27:20 wogo Exp $\n#       --------------------------------------------------------------------\n#\n#       PERL script for translation of the cryptlib header file\n#            into a Visual Basic interface file for Cryptlib (CL32.DLL).\n#\n#            This script does the translation of C-statements into\n#            Visual Basic code. (But only as much as is needed in \n#            cryptlib.h, -NOT- usable as general translation utility)\n#\n#       --------------------------------------------------------------------\n#\n#       SYNTAX:\n#           perl GenVB.pl <cryptlib.h>\n#\n#               cryptlib.h ... (optional) Pathname of crytlib header file\n#                              default is \"cryptlib.h\"\n#\n#               creates the Visual Basic interface file with same basic name \n#               and extension \".bas\" in the same directory as the source file\n#               default is \"cryptlib.bas\"\n#\n#####\n\nuse strict;\nuse warnings;\n\nuse File::stat;\nuse File::Basename;\n\nmy $FileName = shift @ARGV || 'cryptlib.h';\t\t# default filename is \"cryptlib.h\"\nmy %DEFINED = ( 1, 1,                         # ifdef 1 is to be included\n                \"USE_VENDOR_ALGOS\", 0 );\t\t\t# set to 1 to include #IFDEF USE_VENDOR_ALGOS\nmy $Startline = qr{^#endif\\s+\\/\\*\\s+_CRYPTLIB_DEFINED\\s+\\*\\/};\t# ignore all lines before this one\n\nmy ($FileBase, $Path, $Ext) = fileparse($FileName, qr{\\.[^.]*$});\ndie(\"\\\"usage: $0 cryptlib.h\\\"\\nParameter must be a C header file\\nStop\") unless ($Ext =~ m/^\\.h$/i) && -r $FileName;\nmy ($Infile, $Outfile) = ($Path.$FileBase.'.h', $Path.$FileBase.'.bas');\nmy $cryptlib_version;\n\nopen(INFILE, \"<$Infile\") or die \"Open error on $Infile: $!\";\nopen (OUTFILE, \">$Outfile\") or die \"Open error on $Outfile: $!\";\nprint \"Transforming \\\"$Infile\\\" into \\\"$Outfile\\\"\\n\";\nmy $Default = select(OUTFILE);\n\n\n# Ignore all input lines before (and including) $Startline\nwhile (<INFILE>) {\n\t$cryptlib_version = $_ if m{#define\\s+CRYPTLIB_VERSION\\s+};\n\tlast if m/$Startline/;\n}\n\n# array to contain the preprocessed input lines:\nmy @source;\n\npush @source, VBHeader($Infile);\npush @source, $cryptlib_version if $cryptlib_version;\n\nmy $INACTIVE = 0;\nmy $LEVEL = 0;\nmy $COMMENT = 0;\n# handle conditionals, include conditional code only if definition agrees with %DEFINED\nwhile (<INFILE>) { \n    # remove preprocessor symbols\n    s/C_CHECK_RETVAL//;\n    s/C_NONNULL_ARG\\s*\\(\\s*\\([ \\t0-9,]+\\s*\\)\\s*\\)//;\n\n    # remove tabs\n    1 while s/\\t/' ' x (length($&)*4 - length($`)%4)/e;\n\n    if (/^\\s*#if(\\s|def\\s)(\\w+)/) {\n        $LEVEL += 1;\n        $INACTIVE += 1 unless $DEFINED{$2};\n        next;\n    }\n    if (/^\\s*#if\\s\\(/) {\t\t#if (anyexpression) assumed always false\n        $LEVEL += 1;\n        $INACTIVE += 1;\n        next;\n    }\n    if (/^\\s*#ifndef\\s(\\w+)/) {\n        $LEVEL += 1;\n        $INACTIVE += 1 if $DEFINED{$1};\n        next;\n    }\n    if (/^\\s*#(else|elif)\\b/) {\n        $INACTIVE = 1-$INACTIVE;\n        next;\n    }\n    if (/^\\s*\\#endif\\b/) {\n        $LEVEL -= 1;\n        $INACTIVE = 0;\n        next;\n    }\n                                          # translate comments\n    if (/\\/\\*(.*)\\*\\/\\s*$/) {\n        if ($1 !~ m(\\*/)) {\n            s!/\\*(.*)\\*/\\s*$!'$1\\n!\n        }\n    }\n\n    if ($COMMENT) {\n        $_ = \"'\".$_ unless s/^ /'/;\n        $COMMENT = 0 if s/\\*\\/\\s*$/\\n/;\n        s/\\*\\*$/***/;\n    }\n    $COMMENT = 1 if s/^(\\s*)\\/\\*\\*(.*)$/'**$1$2/;\n    $COMMENT = 1 if s/^(\\s*)\\/\\*(.*)$/'$1 $2/;\n\n    push @source, $_ unless $INACTIVE;\n}\n\n# preprocessing finished, translation to VB code follows\n\nmy $Warn=\"\";\n\nwhile ($_ = shift @source) {\n\t\t# ignore special C++ handling\n    if (/#ifdef\\s+__cplusplus/) {\n        $_ = shift @source  while (!(/#endif/));\n        $_ = shift @source;\n    }\n    \n    # continued lines\n    if (s/\\\\$//) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete typedef / enum lines\n    if (/^\\s*(typedef\\s+enum|typedef\\s+struct|enum)\\s*\\{[^}]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n    \n    # incomplete procedure calls\n    if (/^\\s*C_RET\\s+\\w+\\s*\\([^)]*$/) {\n        $_ .= shift @source;\n        redo if @source;\n    }\n\t\t# lines are complete now, do the translation\n\n    # hex values\n    s{0x([0-9a-fA-F]+)}{&H$1}g;\n    \n\t\t# constant definitions\n\t\ts/^\\s*#define\\s+(\\w+)\\s+(\\w+|[+\\-0-9]+|&H[0-9a-fA-F]+)/  Public Const $1 As Long = $2/;\n\t\ts/^\\s*#define\\s+(\\w+)\\s+\\(\\s*(\\w+|[+\\-0-9]+|&H[0-9a-fA-F]+)\\s*\\)/  Public Const $1 As Long = $2/;\n\n    # typedef struct\n    if (s!^(\\s*)typedef\\s+struct\\s*{([^}]*)}\\s*(\\w+)\\s*;!&typelist(split(/;/,$2))!e) {\n        $_ = \"$1Public Type $3 $_\\n$1End Type\\n\";\n    }\n\n\t\t# typedef enum ( with intermediate constant definitions )\n    if (s!^\\s*typedef\\s+enum\\s*{([^}]+=\\s*\\d+\\b[^}]+)}\\s*(\\w+);!&enumt(split(/\\n/,$1))!e) {\n        $_ = \"Public Enum $2\\n$_\".\"End Enum\\n\";\n    }\n\n\t\t# typedef enum\n    if (s!^\\s*typedef\\s+enum\\s*{([^}]+)}\\s*(\\w+);!&enumt(split(/\\n/,$1))!e) {\n        $_ = \"Public Enum $2\\n$_\".\"End Enum\\n\";\n    }\n\n\t\t# \"simple\" typedef\n    s/^\\s*typedef\\s+(\\w+)\\s+(\\w+);/\"REM  $2 = \".&typeconv($1)/e;       # ignore redefinitions\n\n\t\t# \"simple\" enum\n    s!^\\s*enum\\s*{([^}]+)}\\s*;!&enums(split(/,/,$1))!e;\n\n\t\t# translate function declarations without params\n\t\ts/\\bC_RET\\s*(\\w+)\\s*\\(\\s*void\\s*\\)\\s*;/Public Declare Function $1 Lib \\\"CL32.DLL\\\" () As Long\\n\\n/;\n\n\t\t# translate function declarations with params\n    if (s!^\\s*C_RET\\s*(\\w+)\\s*\\(\\s*([^)]+)\\s*\\)\\s*;!&convpar(split(/,/,$2))!e) {\n        chomp;\n        $_ = \"Public Declare Function $1 Lib \\\"CL32.DLL\\\" ($_) As Long\\n\\n\";\n        $_ = \"' ***Warning: function '$1' $Warn\\n$_\" if ($Warn);\n    }\n\t\t\n\t\t# C-macro definitions are ignored\n    if (s/\\s*#define\\s+(.*)/$1/) {\n        s/\\n/\\n'/g;\n        s/\\s+$//;\n        $_ = \"' C-macro not translated to Visual Basic code: \\n'   #define $_\\n\";\n    }\n\n\t\t# translation is done, output lines now\n    print \"$_\" if @source;\n}\nprint VBFooter();\n\nselect($Default);\n\nexit;\n\n# subroutine definitions follow:\n\nsub VBHeader {\n\tmy $Infile = shift;\n\tmy $fstat = stat($Infile) if (-f $Infile && -r $Infile) or die \"$Infile not readable\";\n\tmy $infile_size = $fstat->size;\n\tmy $infile_time = localtime($fstat->mtime);\n\tmy $filename = basename($Infile);\n\tmy $now = (localtime())[5]+1900;\nreturn <<ENDOFHEADER;\nAttribute VB_Name = \"CRYPTLIB\"\n\nOption Explicit\n\n'*****************************************************************************\n'*                                                                           *\n'*                        cryptlib External API Interface                    *\n'*                       Copyright Peter Gutmann 1997-$now                   *\n'*                                                                           *\n'*                 adapted for Visual Basic Version 6  by W. Gothier         *\n'*****************************************************************************\n\n\n'-----------------------------------------------------------------------------\n\n'This file has been created automatically by a perl script from the file:\n'\n'\"$filename\" dated $infile_time, filesize = $infile_size.\n'\n'Please check twice that the file matches the version of $filename\n'in your cryptlib source! If this is not the right version, try to download an\n'update from \"http://cryptlib.sogot.de/\". If the filesize or file creation\n'date do not match, then please do not complain about problems.\n'\n'Examples using Visual Basic are available on the same web address.\n'\n'Published by W. Gothier, \n'mailto: problems\\@cryptlib.sogot.de if you find errors in this file.\n\n'-----------------------------------------------------------------------------\n\nENDOFHEADER\n\n}\n\nsub VBFooter {\nreturn <<ENDFOOTER;\n\n'*****************************************************************************\n'*                                                                           *\n'*                    End of Visual Basic Functions                          *\n'*                                                                           *\n'****************************************************************************}\n\nENDFOOTER\n}\n\n# subroutine to handle simple enum elements\nsub enums {\n    my $Index = 0; # startvalue = 0 for enum entries\n    my $_S;\n    foreach (@_) {\n        chomp;\n        s/^\\s+//;   # delete leading whitespace\n        if (m/(\\w+)\\s*=\\s*(\\d+).*$/) {\n        \t\t# new value is being set, $index must be updated\n            $_S .= \"  Public Const $1 As Long = $2\\n\";\n            eval($Index = $2+1);\n        }\n        else {\n            $_S .= \"  Public Const $_ As Long = \".$Index++.\"\\n\";\n        }\n    }\n    return $_S;\n}\n\n# subroutine to handle typedef enum ( with intermediate constant definitions )\nsub enumt {\n    my $LINES = \"\";\n    my $parval;\n    my $newpar;\n    foreach $parval (@_) {\n        if ($parval =~ /^([^',]+)\\,\\s*([^'\\t \\n]+)/) {\n            $parval =~ s/^(\\s*)([^',]+)\\,\\s*(.*)$/$1$2/;\n            $newpar = \"$1$3\";\n        } \n        else { \n            $newpar = \"\" \n        }\n        $parval =~ s/\\,\\s*$//;\n        $parval =~ s/^(\\s*\\w+\\s*\\=\\s*[^']+\\s*)\\,/$1 /g;\n        $parval =~ s/^(\\s*\\w+\\s*)\\,/$1 /g;\n        $LINES .= \"$parval\\n\";\n        $parval = $newpar;\n        redo if $parval;\n    }\n    return $LINES;\n}\n#   handle the lines of a \"typedef struct { ... } structname\"\nsub typelist {\n    my $tmp = \"\";\n    foreach my $par (@_) {\n        while ($par =~ s/^(\\s*)\\'(.+)\\n(.*)/$3/) {   # embedded comments\n            $tmp .= \"$1'$2\\n\";\n        }\n        if ($par =~ s/^(\\s*)(.*)\\s(\\w+)\\s*\\[\\s*(\\w+)\\s*\\]\\s*$//) {    # index conversion\n            $tmp .= \"$1$3($4-1) As \".&typeconv($2);\n        }\n        elsif ($par =~ s/^(\\s*)(.*)\\s(\\w+)\\s*$//) {  # normal conversion\n            $tmp .= \"$1$3 As \".&typeconv($2);\n        }\n        else {$tmp .= $par}                          # leave it alone\n    }\n    return $tmp;\n}\n\n#   type conversion from C types to Visual Basic types\n#   only the types from cryptlib.h are handled !!!\nsub typeconv {\n    my $param = shift;\n    return $param if $param =~ s/\\bint\\b/Long/;\n    return $param if $param =~ s/\\bunsigned char\\b/Byte/;\n    return $param if $param =~ s/\\bchar\\s+C_PTR\\b/String/;\n    return $param if $param =~ s/\\bchar\\b/Byte/;\n    return $param if $param =~ s/\\bC_CHR\\b/Byte/;\t\t\t\t\t\t  # new cryptlib type C_CHR in current V3.1\n    return $param if $param =~ s/\\bvoid\\s+C_PTR\\b/String/;\n    return $param if $param =~ s/\\bC_STR\\b/String/;\t\t\t\t\t\t# new cryptlib type C_STR in current V3.1\n\n    return $param if $param =~ s/\\bCRYPT_CERTIFICATE\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_CONTEXT\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_DEVICE\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_ENVELOPE\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_KEYSET\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_SESSION\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_USER\\b/Long/;\n    return $param if $param =~ s/\\bCRYPT_HANDLE\\b/Long/;\n    return $param;\n}\n\n#   parameter conversion for parameter lists in procedure calls\nsub convpar {\n    my $tmp = '';\n    $Warn = \"\";\n    LOOP: foreach my $parval (@_) {\n        $tmp .= &convpar1($parval).\", _\\n\";\n    }\n    $tmp =~ s/, _\\n$//;\n    return $tmp;\n}\n\n#   conversion of a single parameter in a parameter list\nsub convpar1 {\n    my $par = shift;\n    if ($par =~ s/^\\s*(C_IN\\s+|C_IN_OPT\\s+)(.+)\\s+(\\w+)\\s*/&typeconv($2)/e) {\n        return \" ByVal $3 As $par\";\n    }\n    if ($par =~ s/^\\s*C_INOUT\\s+(.+)\\s+(\\w+)\\s*/&typeconv($1)/e) {\n        $Warn = \"will replace the String '$2'\";\n        return \" ByVal $2 As $par\";\n    }\n    if ($par =~ s/^\\s*(C_OUT\\s+|C_OUT_OPT\\s+)void\\s+C_PTR\\s+(\\w+)\\s*/$2/) {\n        $Warn = \"will modify the String '$par'\";\n        return \" ByVal $par As String\";\n    }\n    if ($par =~ s/^\\s*(C_OUT\\s+|C_OUT_OPT\\s+)(.+)\\s+C_PTR\\s+(\\w+)\\s*/&typeconv($2)/e) {\n        return \" ByRef $3 As $par\";\n    }\n    if ($par =~ s/^\\s*(C_OUT\\s+|C_OUT_OPT\\s+)(.+)\\s+(\\w+)\\s*/&typeconv($2)/e) {\n        return \" $3 As $par\";\n    }\n    return $par;\n}\n\n"
  },
  {
    "path": "deps/cl345/tools/buildall.sh",
    "content": "#!/bin/sh\n# Build all cryptlib modules\n#\n# Usage: buildall.sh [shared] [analyse|special] make compiler osname flags\n\nSHARED=0\nANALYSE=0\nISSPECIAL=0\n\n# Make sure that we've been given sufficient arguments.\n\nif [ \"$1\" = \"shared\" ] ; then\n\tSHARED=1 ;\n\tshift ;\nfi\nif [ \"$1\" = \"analyse\" ] ; then\n\tANALYSE=1 ;\n\tshift ;\nelif [ \"$1\" = \"special\" ] ; then\n\tISSPECIAL=1 ;\n\tshift ;\nfi\nif [ $# -lt 4 ] ; then\n\techo \"Usage: $0 [shared] [analyse|special] make compiler osname flags\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nMAKE=$1\nCC=$2\nOSNAME=$3\nshift 3\n\n# Additional constants from the makefile.\n\nMAJ=\"3\"\nMIN=\"4\"\nPLV=\"5\"\nPROJ=\"cl\"\nSHARED_OBJ_PATH=\"./shared-obj/\"\nif [ \"$OSNAME\" = \"Darwin\" ] ; then\n\tSLIBNAME=\"lib$PROJ.$MAJ.$MIN.dylib\" ;\nelse\n\tSLIBNAME=\"lib$PROJ.so.$MAJ.$MIN.$PLV\" ;\nfi\n\n# More SunOS braindamage, deal with with Sun's totally braindamaged handling\n# of compiler installs in which cc may be either a shell script telling you\n# that there's no compiler installed, an actual compiler, or gcc.  Also, if\n# it's an actual compiler than it may be some ancient version, with a newer\n# version hidden in a large range of Sun-specific directories whose naming\n# convention changes every 1-2 versions (seriously!).  Further also,\n# although there's supposed to be a link from /opt/SUNWspro/bin to the\n# current version's /bin, it's often some ancient version that was installed\n# years ago and the link never got updated.\n#\n# To deal with this insanity we use a list of possible paths to see whether\n# there's a recent version of the Sun compiler installed, walking down\n# through older and older installs until we either find something or run out\n# of paths to search on.  Once we find a hit, we check whether it matches cc.\n# If it does then we're done.  If not, we check whether it matches\n# /opt/SUNWspro/bin and tell the user to use that.  Finally, if neither\n# match then we tell them to use the path to the newer cc that we've found.\n#\n# First we need locations of the compiler, which for the list below goes\n# back to 2005.  Note how the locations change every few versions, as does\n# the software name: SPARCworks, SunSoft Workshop, Forte Developer, Sun ONE\n# Studio, Sun Studio, Oracle Solaris Studio, and Oracle Developer Suite.\n#\n# Note also that the 12.7 entry is speculative for the next release, it\n# didn't change from 12.5 to 12.6 so it's due for a change again.\n\nSUNCCPATHS=\"/opt/developerstudio12.7/bin/cc /opt/developerstudio12.6/bin/cc \\\n/opt/developerstudio12.5/bin/cc /opt/solarisstudio12.4/bin/cc \\\n/opt/solarisstudio12.3/bin/cc /opt/solstudio12.2/bin/cc \\\n/opt/studio/sunstudio12.1/bin/cc /opt/sunstudio12/bin/cc \\\n/opt/sunstudio11/SUNWspro/bin/cc /opt/sunstudio10/SUNWspro/bin/cc\"\nSUNCC=0\n\ncheckSunCompilerVersion()\n\t{\n\tCC=$1\n\tSUNCCPATH=$2\n\tSUNWSSTRING=\"\"\n\n\t# Get the compiler version info for each of the three possible locations\n\t# where a compiler could be hidden.\n\tCCSTRING=\"$($CC -V 2>&1 | grep \"Sun C\")\"\n\tSUNCCSTRING=\"$($SUNCCPATH -V 2>&1 | grep \"Sun C\")\"\n\tif [ -f /opt/SUNWspro/bin/cc ] ; then\n\t\tSUNWSSTRING=\"$(/opt/SUNWspro/bin/cc -V 2>&1 | grep \"Sun C\")\" ;\n\tfi\n\n\t# If $CC is the latest version, we're done.\n\tif [ \"$SUNCCSTRING\" = \"$CCSTRING\" ] ; then\n\t\tSUNCC=1 ;\n\t\treturn ;\n\tfi\n\n\t# $CC isn't the latest version, tell the user that they need to\n\t# explicitly enable use of a newer version.\n\tif [ \"$SUNCCSTRING\" = \"$SUNWSSTRING\" ] ; then\n\t\techo \"Sun Workshop compiler detected at /opt/SUNWspro/bin/cc but it's more recent\" >&2 ;\n\t\techo \"than $CC, rerun make with the path set to point to the compiler directories\" >&2 ;\n\t\techo \"at /opt/SUNWspro/bin.\" >&2 ;\n\telse\n\t\techo \"Sun Workshop compiler detected but it's not in the path, rerun make with the\" >&2 ;\n\t\techo \"path set to point to the compiler directories at \"$(dirname $SUNCCPATH)\".\" >&2 ;\n\tfi\n\texit 1;\n\t}\n\nif [ \"$OSNAME\" = \"SunOS\" ] ; then\n\tfor sunccpath in $SUNCCPATHS ; do\n\t\tif [ -f $sunccpath ] ; then\n\t\t\tcheckSunCompilerVersion $CC $sunccpath ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\tif [ $SUNCC -eq 0 ] && [ \"$($CC -v 2>&1 | grep -c \"gcc\")\" -gt 0 ] ; then\n\t\techo \"Sun compiler not detected but gcc is present, using that instead.\" >&2 ;\n\tfi\nfi\n\n# Get the compiler that we'll be using.  This takes the given $CC and\n# substitutes are more preferred one if available, unless $CC is a custom\n# compiler like a static source code analyser or fuzzer build.\n\nCC=\"$(./tools/getcompiler.sh $CC $OSNAME)\"\n\n# OS X Snow Leopard broke dlopen(), if it's called from a (sub-)thread then it\n# dies with a SIGTRAP.  Specifically, if you dlopen() a shared library linked\n# with CoreFoundation from a thread and the calling app wasn't linked with\n# CoreFoundation then the function CFInitialize() inside dlopen() checks if\n# the thread is the main thread and if it isn't it crashes with a SIGTRAP.\n#\n# This is now handled in cryptlib.c by disabling asynchronous driver binding,\n# the following check is left here in case this isn't sufficient.\n#\n#if [ $OSNAME = \"Darwin\" -a `sw_vers -productVersion | grep -c \"10\\.6\"` -gt 0 ] ; then\n#\techo \"This version of OS X Snow Leopard may have a buggy dlopen() that crashes\" ;\n#\techo \"with a SIGTRAP when called from a thread.  If the cryptlib self-test dies\" ;\n#\techo \"with the message 'Trace/BPT trap' then add:\" ;\n#\techo \"\" ;\n#\techo \"  #undef USE_THREADS\" ;\n#\techo \"\" ;\n#\techo \"at around line 40 of cryptlib.c and rebuild.  Note that this will disable\" ;\n#\techo \"the use of asynchronous driver binding, which may make startups a little\" ;\n#\techo \"slower.\" ;\n#\techo \"\" ;\n#fi\n\n# Detect various broken versions of gcc\n\nif [ \"$($CC -v 2>&1 | grep -c \"gcc\")\" -gt 0 ] ; then\n\n  # Older OS X boxes shipped with an incredibly buggy Apple-hacked version of\n  # gcc 4.0.1, cryptlib contains some workarounds for this but other bugs\n  # are too difficult to track down, so we have to declare it to be an\n  # unsupported environment.\n\n  if [ \"$OSNAME\" = \"Darwin\" ] && [ \"$($CC -dumpversion | grep -c \"4\\.0\\.1\")\" -gt 0 ] ; then\n\techo \"This version of OS X ships with an extremely buggy, Apple-hacked version of\" ;\n\techo \"gcc 4.0.1 that's more than a decade out of date.  Please upgrade to a newer \" ;\n\techo \"compiler to build cryptlib.\" ;\n\texit 1 ;\n  fi\n\n  # Slowaris 11 similarly shipped with a buggy version of gcc 4.8 (described\n  # as \"pretty much messed up at this point\" in\n  # https://mail-index.netbsd.org/pkgsrc-users/2014/08/27/msg020283.html) so\n  # we similarly have to declare it to be an unsupported environment.\n\n  if [ \"$OSNAME\" = \"SunOS\" ] && [ \"$($CC -dumpversion | grep -c \"4\\.8\")\" -gt 0 ] ; then\n\techo \"This version of Solaris ships with a buggy version of gcc 4.8 that produces\" ;\n\techo \"broken builds due to stack smashing protection (SSP) options being messed\" ;\n\techo \"up.  Please upgrade to a newer compiler, or even just something other than\" ;\n\techo \"gcc 4.6 or 4.8, to build cryptlib.\" ;\n\texit 1 ;\n  fi\n\nfi\n\n# Unicos has a broken uname so we override detection.\n\nif [ \"$(uname -m | cut -c 1-4)\" = 'CRAY' ] ; then\n\tOSNAME=\"CRAY\" ;\nfi\n\n# Get the compiler flags for the compiler and the OS version and make sure\n# that we got a valid result.  This check is necessary because sometimes\n# problems (typically sh bugs on some OSes) cause the script to bail out\n# without producing any output.  Since the resulting CFLAGS string is empty,\n# we add an extra character to the comparison string to avoid syntax errors.\n\nif [ $ANALYSE -gt 0 ] ; then\n\tCFLAGS=\"$(./tools/ccopts.sh analyse $CC $OSNAME)\" ;\nelif [ $ISSPECIAL -gt 0 ] ; then\n\tCFLAGS=\"$(./tools/ccopts.sh special $CC $OSNAME)\" ;\nelif [ $SHARED -gt 0 ] ; then\n\tCFLAGS=\"$(./tools/ccopts.sh shared $CC $OSNAME)\" ;\nelse\n\tCFLAGS=\"$(./tools/ccopts.sh $CC $OSNAME)\" ;\nfi\nif [ '$(CFLAGS)x' = 'x' ] ; then\n\techo \"$0: Couldn't get compiler flags via tools/ccopts.sh.\" >&2 ;\n\texit 1 ;\nfi\n\nOSVERSION=\"$(./tools/osversion.sh $OSNAME)\"\nif [ -z \"$OSVERSION\" ] || \\\n   [ \"$(echo $OSVERSION | grep -c '[^0-9]')\" -gt 0 ] ; then\n\techo \"$0: Couldn't correctly determine OS version string '$OSVERSION'.\" >&2 ;\n\texit 1 ;\nfi\n\n# Check whether we're doing a cross-compile and provide an early-out for\n# this special case.  Since $CROSSCOMPILE is usually a null value we add an\n# extra character to the comparison string to avoid syntax errors.\n\nif [ '$(CROSSCOMPILE)x' = '1x' ] ; then\n\techo \"Cross-compiling for OS target $OSNAME\" ;\n\tCFLAGS=\"$* $(./tools/ccopts-crosscompile.sh $CC $OSNAME) \\\n\t\t\t-DOSVERSION=$(./tools/osversion.sh $OSNAME)\" ;\n\tif [ $SHARED -gt 0 ] ; then\n\t\t$MAKE TARGET=\"$SLIBNAME\" OBJPATH=\"$SHARED_OBJ_PATH\" \"$CFLAGS\" \"$OSNAME\" ;\n\telse\n\t\t$MAKE \"$CFLAGS\" \"$OSNAME\" ;\n\tfi ;\nfi\n\n# Build cryptlib.\n\nif [ $SHARED -gt 0 ] ; then\n\t$MAKE CC=\"$CC\" LD=\"$CC\" TARGET=\"$SLIBNAME\" OBJPATH=\"$SHARED_OBJ_PATH\" \\\n\t\t  CFLAGS=\"$* $CFLAGS -DOSVERSION=$OSVERSION\" \"$OSNAME\" ;\nelse\n\t$MAKE CC=\"$CC\" LD=\"$CC\" CFLAGS=\"$* $CFLAGS -DOSVERSION=$OSVERSION\" \"$OSNAME\" ;\nfi\n"
  },
  {
    "path": "deps/cl345/tools/buildlib.sh",
    "content": "#!/bin/sh\n# Build the static library.\n#\n# Usage: buildlib.sh libname osname ar objfiles\n\nCROSSCOMPILE=0\n\n# Make sure that we've been given sufficient arguments.\n\nif [ $# -lt 4 ] ; then\n\techo \"Usage: $0 libname osname ar objfiles\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.  What's\n# left after this are the object file names.\n\nLIBNAME=$1\nOSNAME=$2\nAR=$3\nshift 3\n\n# The use of ar and ranlib is rather system-dependant.  Some ar's (e.g.OSF1)\n# create the .SYMDEF file by default, some require the 's' option, and some\n# require the use of ranlib altogether because ar doesn't recognise the 's'\n# option.  If we know what's required we use the appropriate form, otherwise\n# we first try 'ar rcs' (which works on most systems) and if that fails fall\n# back to 'ar rc' followed by ranlib.  QNX doesn't have either ranlib or the\n# 's' option to ar, so the best we can do is use 'ar rc'.  Finally, Unicos\n# has a weird ar that takes args in a nonstandard form.\n\ncase $OSNAME in\n\t'AIX'|'HP-UX'|'Linux'|'OSF1'|'UNIX_SV')\n\t\t$AR rcs \"$LIBNAME\" \"$@\" ;;\n\n\t'Atmel')\n\t\techo \"Need to set up Atmel link command\" ;;\n\n\t'BSD/OS'|'FreeBSD'|'iBSD'|'NetBSD'|'OpenBSD')\n\t\t$AR rc \"$LIBNAME\" \"$@\" ;\n\t\tranlib \"$LIBNAME\" ;;\n\n\t'CRAY')\n\t\t$AR -rc \"$LIBNAME\" \"$@\" ;;\n\n\t'PalmOS')\n\t\tpalib -add \"$LIBNAME\" \"$@\" ;\n\t\tpalink -nodebug -o palmcl.dll \"$LIBNAME\" ./static-obj/cryptsld.o \\\n\t\t\t\t-libpath \"d:/Palm\\\\\\ SDK/sdk-6/libraries/ARM_4T/Release/Default\" ;;\n\n\t'PalmOS-PRC')\n\t\tarm-palmos-ar rc \"$LIBNAME\" \"$@\" ;\n\t\tarm-palmos-ranlib \"$LIBNAME\" ;;\n\n\t'QNX')\n\t\t$AR rc \"$LIBNAME\" \"$@\" ;;\n\n\t'SunOS')\n\t\tif [ \"$(which ar | grep -c \"no ar\")\" = '1' ] ; then\n\t\t\t/usr/ccs/bin/ar rcs \"$LIBNAME\" \"$@\" ;\n\t\telse\n\t\t\t$AR rcs \"$LIBNAME\" \"$@\" ;\n\t\tfi ;;\n\n\t'ucLinux')\n\t\techo \"Need to set up ucLinux link command\" ;;\n\n\t*)\n\t\t$AR rcs \"$LIBNAME\" \"$@\" || \\\n\t\t( $AR rc \"$LIBNAME\" \"$@\" && ranlib \"$LIBNAME\" )\n\nesac\n"
  },
  {
    "path": "deps/cl345/tools/buildsharedlib.sh",
    "content": "#!/bin/sh\n# Build the shared library.\n#\n# Usage: buildsharedlib.sh [crosscompile] libname osname ld strip version objfiles...\n\nCROSSCOMPILE=0\n\n# Make sure that we've been given sufficient arguments.\n\nif [ \"$1\" = \"crosscompile\" ] ; then\n\tCROSSCOMPILE=1 ;\n\tshift ;\nfi\nif [ $# -lt 6 ] ; then\n\techo \"Usage: $0 [crosscompile] libname osname ld strip version objfiles...\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.  What's\n# left after this are the object file names.\n\nLIBNAME=$1\nOSNAME=$2\nLD=$3\nSTRIP=$4\nVERS=$5\nshift 5\n\n# The options need to be tuned for some systems since there's no standard\n# for shared libraries, and different versions of gcc also changed the way\n# that this was handled:\n#\n# AIX:\t\t\tAIX requires some weird voodoo which is unlike any other\n#\t\t\t\tsystem's way of doing it (probably done by the MVS team,\n#\t\t\t\tsee \"AIX Linking and Loading Mechanisms\" for a starter).\n#\t\t\t\tIn addition to this, the shared lib (during development)\n#\t\t\t\tmust be given permissions 750 to avoid loading it\n#\t\t\t\tpermanently into the shared memory segment (only root can\n#\t\t\t\tremove it).  The production shared library must have a\n#\t\t\t\t555 (or whatever) permission.  Finally, the library has to\n#\t\t\t\thave a \".a\" suffix (even though it's a shared lib), so we\n#\t\t\t\ttack this on after the $LIBNAME.\n#\n#\t\t\t\tThe various AIX options are: '-bnoentry' = don't look for a\n#\t\t\t\tmain(), '-bE' = export the symbols in cryptlib.exp,\n#\t\t\t\t'-bM:SRE' = make it a shared library.\n#\t\t\t\t$(LD) -ldl -bE:cryptlib.exp -bM:SRE -bnoentry\n# BeOS:\t\t\t$(LD) -nostart\n# Cygwin:\t\t$(LD) -L/usr/local/lib -lcygipc\n# HPUX:\t\t\tLink with gcc (to the GNU libs) if compiled with gcc,\n#\t\t\t\totherwise link with the standard compiler into the system\n#\t\t\t\tlibs.  If you're mixing GNU and system libs (e.g. cryptlib\n#\t\t\t\tbuilt with gcc and the calling app built with the HP cc),\n#\t\t\t\tyou may want to use '-static-libgcc' to avoid having to ship\n#\t\t\t\ta copy of glibc just for cryptlib.\n#\t\t\t\tNote that on some versions of PHUX stripping the shared lib.\n#\t\t\t\tmay prevent it from being linked, you may need to remove\n#\t\t\t\tthis command in that case.\n#\t\t\t\t$(LD) -shared -Wl,-soname,libcl.so.$(MAJ)\n# Solaris:\t\t$(LD) -G -ldl -o libcl.so.$(MAJ)\n#\n# An additional possibility under the *BSDs and Linux is:\n#\n# *BSDs:\t\t$(LD) -Bshareable -o libcl.so.$(MAJ)\n# Linux:\t\t$(LD) -Bshareable -ldl -o libcl.so.$(MAJ)\n\n# Set up any required variables\n\nLINKFILE=link.tmp\nLD_IS_GCC=0\n\n# Set up any linker-specific options\n\nif [ \"$($LD -v 2>&1 | grep -c gcc)\" -gt 0 ] ; then\n\tLD_IS_GCC=1 ;\n\tLDFLAGS=\"$LDFLAGS -shared -Wl,-soname,libcl.so.$VERS\" ;\nfi\n\n# Create the response file to hold the link command\n\nrm -f $LINKFILE\necho \"$@\" > $LINKFILE\n\n# Build the shared lib.  The use of x86 asm code causes some issues with\n# relocation, to avoid this we use the -Bsymbolic option with the linker,\n# which (explicitly) tells the linker to perform symbol lookup in the local\n# library first and (implicitly) gets rid of spurious relocations because\n# instead of having to perform intra-library references via the global\n# offset table using a call to a jump table based at %ebx, the linker\n# resolves the reference and uses a direct call as expected.  A nice\n# side-effect of this rewiring of indirect to direct calls is that it makes\n# it much harder to mess with library internals by getting your own symbols\n# referenced before the library-internal ones (for example by using\n# LD_PRELOAD), thus redirecting control flow to arbitrary external code.\n#\n# Note that the various multi-element string arguments $LDFLAGS,\n# $(cat $LINKFILE), and getlibs.sh can't be placed in quotes because that\n# would turn the output into a single string rather than a list of white-\n# space-delimited discrete strings.\n#\n# The Aches linker supports an alternative to GNU ld's @filename in the form\n# of -ffilename, but it requires the contents to be one per line rather than\n# a whitespace-delimited string so we use the cat $LINKFILE option instead.\n# Similarly, the PHUX linker has -c filename but requires one entry per line.\n# Slowaris doesn't support link files at all.\n#\n# iOS doesn't allow shared libraries because this would allow you to bypass\n# their walled garden, so we explicitly disallow them for iOS builds.\n\ncase $OSNAME in\n\t'AIX')\n\t\t$LD -o shrlibcl.o -bE:cryptlib.exp -bM:SRE -bnoentry -lpthread \\\n\t\t\t$(cat $LINKFILE) $(./tools/getlibs.sh $LD AIX $CROSSCOMPILE) ;\n\t\tar -q \"$LIBNAME.a\" shrlibcl.o ;\n\t\trm -f shrlibcl.o ;\n\t\tchmod 750 \"$LIBNAME.a\" ;;\n\n\t'Android')\n\t\t$LD -shared -o \"$LIBNAME\" @$LINKFILE \\\n\t\t\t$(./tools/getlibs.sh $LD Android $CROSSCOMPILE) ;\n\t\t$STRIP \"$LIBNAME\" ;;\n\n\t'BeOS' )\n\t\t$LD -nostart -o \"$LIBNAME\" @$LINKFILE \\\n\t\t\t$(./tools/getlibs.sh $LD BeOS $CROSSCOMPILE) ;\n\t\t$STRIP \"$LIBNAME\" ;;\n\n\t'HP-UX')\n\t\tif [ $LD_IS_GCC -gt 0 ] ; then\n\t\t\t$LD $LDFLAGS -o libcl.sl @$LINKFILE \\\n\t\t\t\t$(./tools/getlibs.sh $LD HP-UX $CROSSCOMPILE) ;\n\t\telse\n\t\t\t$LD -b -o libcl.sl $(cat $LINKFILE) \\\n\t\t\t\t$(./tools/getlibs.sh $LD HP-UX $CROSSCOMPILE) ;\n\t\tfi\n\t\t$STRIP libcl.sl ;;\n\n\t'iOS')\n\t\techo \"iOS doesn't allow shared libraries, you must use a static library.\" >&2 ;;\n\n\t'SunOS')\n\t\tif [ $LD_IS_GCC -gt 0 ] ; then\n\t\t\t$LD $LDFLAGS -o \"$LIBNAME\" @$LINKFILE \\\n\t\t\t\t$(./tools/getlibs.sh $LD SunOS $CROSSCOMPILE) ;\n\t\telse\n\t\t\t$LD -G -ldl -o \"$LIBNAME\" $(cat $LINKFILE) \\\n\t\t\t\t$(./tools/getlibs.sh $LD SunOS $CROSSCOMPILE) ;\n\t\tfi\n\t\t$STRIP \"$LIBNAME\" ;;\n\n\t*)\n\t\tif [ $LD_IS_GCC -gt 0 ] ; then\n\t\t\tif [ \"$(gcc -Wl,-Bsymbolic 2>&1 | grep -c unrecognized)\" = 0 ] ; then\n\t\t\t\t$LD $LDFLAGS -Wl,-Bsymbolic -o \"$LIBNAME\" @$LINKFILE \\\n\t\t\t\t\t$(./tools/getlibs.sh $LD $OSNAME $CROSSCOMPILE) ;\n\t\t\telse\n\t\t\t\t$LD $LDFLAGS -o \"$LIBNAME\" @$LINKFILE \\\n\t\t\t\t\t$(./tools/getlibs.sh $LD $OSNAME $CROSSCOMPILE) ;\n\t\t\tfi\n\t\telse\n\t\t\t$LD -shared -o \"$LIBNAME\" $(cat $LINKFILE) \\\n\t\t\t\t$(./tools/getlibs.sh $LD $OSNAME $CROSSCOMPILE) ;\n\t\tfi\n\t\tif [ \"$(which objdump)\" ] && [ \"$(objdump -p $LIBNAME | grep -c TEXTREL)\" -gt '0' ] ; then\n\t\t\techo \"Warning: Shared library still contains TEXTREL records.\" >&2 ;\n\t\tfi\n\t\t$STRIP \"$LIBNAME\" ;;\nesac\nrm -f $LINKFILE\n"
  },
  {
    "path": "deps/cl345/tools/ccopts-crosscompile.sh",
    "content": "#!/bin/sh\n# Obtain appropriate gcc options for building cryptlib during a cross-compile.\n# This is a stripped-down version of tools/ccopts.sh which only performs\n# those checks that are safe in a cross-compile build, which in general means\n# checking for gcc bugs, see tools/ccopts.sh for an explanation of what the\n# following does.\n\nCCARGS=\"$(./tools/getseed.sh)\"\n\nif [ $# -ne 1 ] ; then\n\techo \"$0: Missing compiler name.\" >&2 ;\n\texit 1 ;\nfi\nCC=$1\n\nGCC_VER=`$CC -dumpversion | tr -d  '.' | cut -c 1-2`\n\nif [ $GCC_VER -ge 40 ] ; then\n\tif [ `$CC -Wno-pointer-sign -S -o /dev/null -xc /dev/null > /dev/null 2>&1` ] ; then\n\t\tCCARGS=\"$CCARGS -Wno-pointer-sign\" ;\n\tfi ;\nfi\n\necho $CCARGS\n"
  },
  {
    "path": "deps/cl345/tools/ccopts.sh",
    "content": "#!/bin/sh\n# Obtain appropriate cc options for building cryptlib.\n#\n# Usage: ccopts.sh [shared] [analyse|special] compiler osname\n\nCCARGS=\"\"\nOSNAME=\"\"\nSHARED=0\nANALYSE=0\nISCLANG=0\nISCLANG_ANALYSER=0\nISSPECIAL=0\nISDEVELOPMENT=0\nHOSTNAME=\"\"\n\n# Make sure that we've been given sufficient arguments.\n\nif [ \"$1\" = \"shared\" ] ; then\n\tSHARED=1 ;\n\tshift ;\nfi\nif [ \"$1\" = \"analyse\" ] ; then\n\tANALYSE=1 ;\n\tshift ;\nelif [ \"$1\" = \"special\" ] ; then\n\tISSPECIAL=1 ;\n\tshift ;\nfi\nif [ $# -lt 2 ] ; then\n\techo \"Usage: $0 [shared] [analyse|special] osname compiler\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nCC=$1\nOSNAME=$2\nshift\nshift\n\n# Determine the CPU endianness by building and executing the endianness-\n# detection program.  Note that we have to use -s rather than the more\n# obvious -e since this doesn't exist under the Slowaris sh.\n\nif [ ! -s ./tools/endian ] ; then\n\tif [ \"$OSNAME\" = \"NONSTOP_KERNEL\" ] ; then\n\t\tc89 ./tools/endian.c -o ./tools/endian > /dev/null ;\n\telse\n\t\t$CC ./tools/endian.c -o ./tools/endian > /dev/null ;\n\tfi ;\n\tstrip tools/endian ;\n\tif [ ! -s ./tools/endian ] ; then\n\t\techo \"Couldn't build endianness-checking program ./tools/endian\" >&2 ;\n\t\texit 1 ;\n\tfi ;\nfi\n\nCCARGS=\"$(./tools/endian) $(./tools/getseed.sh $OSNAME)\"\n\n# Check whether we're building on one of the development systems, which\n# allows enabling various unsafe test-only options.  We have to be a bit\n# careful with the Gnu compile farm because it doesn't use FQDNs for the\n# machines, so we check as much as we can and (for the Gnu compile farm)\n# only allow machines on a whitelist to narrow down false positives.\n\ngetFQDNName()\n\t{\n\t# Check whether the hostname command is available.  It usually is, but\n\t# if it isn't then we fall back to the machine name via uname.\n\tif [ ! type hostname 2>/dev/null ] ; then\n\t\tHOSTNAME=\"$(uname -n)\" ;\n\t\treturn ;\n\tfi\n\n\t# Try and get the FQDN of the host.  This doesn't always work, in which\n\t# case we fall back to the bare host name.\n\tif [ \"$(hostname -f 2>/dev/null)\" ] ; then\n\t\tHOSTNAME=\"$(hostname -f)\" ;\n\telse\n\t\tHOSTNAME=\"$(hostname)\" ;\n\tfi\n\t}\n\ncheckForDevSystem()\n\t{\n\tTIMEZONE=$1\n\n\t# Check for development systems by FQDN\n\tgetFQDNName\n\tif [ \"$(echo $HOSTNAME | grep -c \"sitsshprd0[1-3]\\.its\\.auckland\\.ac\\.nz\")\" -gt 0 ] ; then\n\t\tISDEVELOPMENT=1 ;\n\t\treturn ;\n\tfi\n\tif [ \"$(echo $HOSTNAME | grep -c \"[a-z]*\\.cypherpunks\\.to\")\" -gt 0 ] ; then\n\t\tISDEVELOPMENT=1 ;\n\t\treturn ;\n\tfi\n\n\t# Check for development systems by whitelisted name\n\tif [ \"$(uname -n | grep -c \"gcc[0-9][0-9]\")\" -gt 0 ] ; then\n\t\tcase \"$(uname -n)\" in\n\t\t\t'gcc22'|'gcc45'|'gcc40'|'gcc70'|'gcc110'|'gcc113'|'gcc117'|'gcc119'|'gcc202')\n\t\t\t\tISDEVELOPMENT=1 ;\n\t\t\t\treturn ;;\n\t\tesac ;\n\tfi\n\n\t# Check for local development systems based on their location and\n\t# network address.  This is vulnerable to FPs, but should be reasonably\n\t# safe: Devices in the 192.168.1.2x range with gateway 192.168.1.1\n\t# located in NZ with specific device names.\n\tif [ $TIMEZONE != \"NZDT\" ] && [ $TIMEZONE != \"NZST\" ] ; then\n\t\treturn ;\n\tfi\n\tif [ ! \"$(ip addr show eth0)\" ] ; then\n\t\treturn ;\n\tfi\n\tif [ \"$(ip addr show eth0 | grep -c \"inet 192.168.1.2[012]0\")\" -le 0 ] ; then\n\t\treturn ;\n\tfi\n\tif [ \"$(ip route show default | grep -cF \"via 192.168.1.1\")\" -le 0 ] ; then\n\t\treturn ;\n\tfi\n\tif [ $HOSTNAME = \"ci20\" ] || [ $HOSTNAME = \"odroid\" ] || [ $HOSTNAME = \"odroid64\" ] ; then\n\t\tISDEVELOPMENT=1 ;\n\tfi\n\t}\n\nif [ \"$(uname -s)\" = \"Linux\" ] ; then\n\tcheckForDevSystem \"$(date +%Z)\" ;\nfi\n\n# Check whether we're running clang in a code-analysis mode.  Since some of\n# these require a build configuration specific to a development machine, we\n# only allow them to be enabled on a development system.\n#\n# Use of clang is a bit complicated because there's clang the compiler and\n# clang the static analyser, to deal with this we detect both the compiler\n# (via the \"clang\" string (general) or the \"LLVM\" string (Apple) in the\n# verbose info) and the analyser (via the \"ccc-analyzer\" string in the\n# verbose info).\n#\n# In addition the STACK analyser uses an ancient version of clang on a\n# static path which is accessed via a wrapper that looks like an equally\n# ancient vesion of gcc, so we detect it with a check for the static path\n# as part of $CC.\n\nif [ \"$($CC -v 2>&1 | grep -ci \"clang\")\" -gt 0 ] ; then\n\tISCLANG=1 ;\nfi\nif [ \"$(echo $CC | grep -ci \"stack-master\")\" -gt 0 ] ; then\n\tISCLANG=1 ;\nfi\nif [ \"$($CC -v 2>&1 | grep -c \"ccc-analyzer\")\" -gt 0 ] ; then\n\tISCLANG_ANALYSER=1 ;\nfi\nif [ $ISCLANG_ANALYSER -gt 0 ] ; then\n\tANALYSE=1 ;\n\tif [ -z \"$CCC_CC\" ] ; then\n\t\techo \"$0: Environment variable CCC_CC must be set to 'clang' for the analysis build.\" >&2 ;\n\t\texit 1 ;\n\tfi ;\n\tif [ $ISDEVELOPMENT -le 0 ] ; then\n\t\techo \"$0: clang must be run on a system designated as a development environment by changing the ISDEVELOPMENT in this script.\" >&2 ;\n\t\texit 1 ;\n\tfi ;\nfi\n\n# Determine whether various optional system features are installed and\n# enable their use if they're present.  Since these additional libs are\n# dynamically loaded, we only check for them on systems with dynamic\n# loading support.  We could also check for the presence of\n# /usr/include/dlfcn.h, but this can lead to false positives on systems\n# that have dummy a dlfcn.h for compatibility reasons.\n#\n# When indicating the presence of a subsystem, we set the HAS_xxx flag to\n# indicate its presence rather than unconditionally setting the USE_xxx\n# flag.  This allows the facility to be disabled in config.h if required.\n# An exception to this is if we're building on a development system in\n# which case we always enable it unconditionally.\n#\n# To allow these optional subsystems to be explicitly disabled, we also\n# check for the presence of the DISABLE_AUTODETECT flag and skip the\n# checking if this is set.\n\nDEVCRYPTOPATHS=\"/usr/include/crypto/cryptodev.h /usr/local/include/crypto/cryptodev.h\"\nNCIPHERPATHS=\"/opt/nfast/toolkits/pkcs11/libcknfast.so /usr/lib/libcknfast.so\"\nODBCPATHS=\"/usr/include/sql.h /usr/local/include/sql.h /usr/include/hpodbc/sql.h\"\nPKCS11PATHS=\"/usr/include/pkcs11.h /usr/include/security/pkcs11.h /usr/include/opensc/pkcs11.h /usr/local/include/pkcs11.h\"\nTPMPATHS=\"/usr/include/tss/tspi.h /usr/local/include/tss/tspi.h\"\n\nHASDYNLOAD=0\ncase $OSNAME in\n\t'Darwin'|'Linux'|'FreeBSD'|'OpenBSD'|'NetBSD')\n\t\tHASDYNLOAD=1 ;;\n\n\t'SunOS')\n\t\tif [ \"$(./tools/osversion.sh SunOS)\" -gt 4 ] ; then\n\t\t\tHASDYNLOAD=1 ;\n\t\tfi ;;\n\n\t'HP-UX')\n\t\tif [ \"$(./tools/osversion.sh HP-UX)\" -gt 10 ] ; then\n\t\t\tHASDYNLOAD=1 ;\n\t\tfi ;;\nesac\nif [ -z \"$DISABLE_AUTODETECT\" ] && [ $HASDYNLOAD -gt 0 ] ; then\n\n\t# ODBC support\n\tfor includepath in $ODBCPATHS ; do\n\t\tif [ -f $includepath ] ; then\n\t\t\techo \"ODBC interface detected, enabling ODBC support.\" >&2 ;\n\t\t\tCCARGS=\"$CCARGS -DHAS_ODBC -I\"$(dirname $includepath)\"\" ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\n\t# LDAP support\n\tif [ -f /usr/include/ldap.h ] ; then\n\t\techo \"LDAP interface detected, enabling LDAP support\" >&2 ;\n\t\tCCARGS=\"$CCARGS -DHAS_LDAP\" ;\n\t\tif [ $ISDEVELOPMENT -gt 0 ] ; then\n\t\t\tCCARGS=\"$CCARGS -DUSE_LDAP\" ;\n\t\tfi ;\n\tfi\n\n\t# PKCS #11 support\n\tfor includepath in $PKCS11PATHS ; do\n\t\tif [ -f $includepath ] ; then\n\t\t\techo \"PKCS #11 interface detected, enabling PKCS #11 support.\" >&2 ;\n\t\t\tCCARGS=\"$CCARGS -DHAS_PKCS11 -I\"$(dirname $includepath)\"\" ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\tfor includepath in $NCIPHERPATHS ; do\n\t\tif [ -f $includepath ] ; then\n\t\t\techo \"  (Enabling use of additional nCipher PKCS #11 extensions).\" >&2 ;\n\t\t\tCCARGS=\"$CCARGS -DNCIPHER_PKCS11\" ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\n\t# TPM support\n\tfor includepath in $TPMPATHS ; do\n\t\tif [ -f $includepath ] ; then\n\t\t\techo \"TPM interface detected, enabling TPM support.\" >&2 ;\n\t\t\tCCARGS=\"$CCARGS -DHAS_TPM -I\"$(dirname $includepath)\"\" ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\n\t# /dev/crypto support\n\tfor includepath in $DEVCRYPTOPATHS ; do\n\t\tif [ -f $includepath ] ; then\n\t\t\techo \"/dev/crypto interface detected, enabling crypto hardware support.\" >&2 ;\n\t\t\tCCARGS=\"$CCARGS -DHAS_DEVCRYPTO -I\"$(dirname $includepath)\"\" ;\n\t\t\tbreak ;\n\t\tfi\n\tdone\n\nfi\nif [ -f /usr/include/zlib.h ] ; then\n\techo \"  (Enabling use of system zlib).\" >&2 ;\n\tCCARGS=\"$CCARGS -DHAS_ZLIB\" ;\nfi\n\n# If we're building a development or analysis build, enable various unsafe\n# options that are normally disabled by default\n\nif [ $ANALYSE -gt 0 ] || [ $ISSPECIAL -gt 0 ] ; then\n\techo \"  (Enabling all source code options for analysis/instrumented build).\" >&2 ;\n\tCCARGS=\"$CCARGS -DUSE_ANALYSER\" ;\nelif [ $ISDEVELOPMENT -gt 0 ] ; then\n\techo \"  (Enabling additional source code options for development version).\" >&2 ;\n\tCCARGS=\"$CCARGS -DUSE_CERT_DNSTRING -DUSE_DNSSRV -DUSE_ECDSA -DUSE_ECDH\" ;\nfi\n\n# If we're building with the clang static analyser, set options specific to\n# that.  The standard clang uses gcc as a front-end with -Wall enabled so\n# we'd have to disable the false-positive-inducing options for that as per\n# the long comment at the end of this file for the -Wall debug build,\n# however we override the front-end type by setting the CCC_CC environment\n# variable to 'clang'.  Since almost all of the clang warnings are\n# undocumented outside of analysing the source code, we resort to enabling\n# all warnings with -Weverything and then disabling the false positive-\n# inducing ones.  These are:\n#\n#\t-Wno-gnu:\n#\t-Wno-language-extension-token: Use of a gcc'ism, which isn't a problem\n#\t\tin this case because clang detects as gcc in conditional-compilation\n#\t\tdirectives.\n#\n#\t-Wno-missing-field-initializers: Missing initialisers in structs.  This\n#\t\talso warns about things like the fairly common 'struct foo = { 0 }',\n#\t\twhich makes it too noisy for detecting problems.\n#\n#\t-Wno-missing-prototypes: Declaration of function without an earlier\n#\t\tprototype.\n#\n#\t-Wno-padded: Padding in structs.\n#\n#\t-Wno-pointer-sign: char * to unsigned char * and similar.\n#\n#\t-Wno-shorten-64-to-32: Warn about long -> int conversion, this has the\n#\t\tpotential to catch issues but at the moment leads to all false\n#\t\tpositives around things like the sizeofXXX() functions or stell(),\n#\t\tas well as anything involving size_t (e.g. strlen()), which return a\n#\t\tlong in general but are often used in cases where the range is an\n#\t\tint (or more generally a short).\n#\n#\t-Wno-sign-compare: Compare int to unsigned int and similar.\n#\n#\t-Wno-sign-conversion: int to unsigned int and similar.\n#\n#\t-Wno-switch:\n#\t-Wno-switch-enum: Unused enum values in a switch statement.  Since all\n#\t\tcryptlib attributes are declared from a single pool of enums but\n#\t\tonly the values for a particular object class are used in the\n#\t\tobject-specific code, this leads to huge numbers of warnings about\n#\t\tunhandled enum values in case statements.\n#\n#\t-Wno-unused-macros: Macro defined but not used.  This typically occurs\n#\t\twhen macros are used to define constants (e.g. cipher block sizes),\n#\t\tnot all of which are used in the code.\n\nif [ $ISCLANG_ANALYSER -gt 0 ] ; then\n\techo \"  (Enabling specific build options for clang).\" >&2 ;\n\tCCARGS=\"$CCARGS -Weverything\" ;\n\tCCARGS=\"$CCARGS -Wno-gnu -Wno-language-extension-token \\\n\t\t\t-Wno-missing-field-initializers -Wno-missing-prototypes \\\n\t\t\t-Wno-padded -Wno-pointer-sign -Wno-shorten-64-to-32 \\\n\t\t\t-Wno-sign-compare -Wno-sign-conversion -Wno-switch \\\n\t\t\t-Wno-switch-enum -Wno-unused-macros\" ;\nfi\n\n# clang (the compiler, not the static analyser) has a subset of the above\n# issues, since we're not using -Weverything for the pure compiler we only\n# need to disable the two enabled-by default false-positive-inducing ones,\n# -Wswitch and -Wpointer-sign.\n\nif [ $ISCLANG -gt 0 ] ; then\n\tCCARGS=\"$CCARGS -Wno-pointer-sign -Wno-switch\" ;\nfi\n\n# If we're using a newer version of clang, turn on stack buffer overflow\n# protection unless it's a special-case build.  Given cryptlib's built-in\n# protection mechanisms this shouldn't be necessary, but it can't hurt to\n# enable it anyway.\n#\n# Note that this is a weird flag in that it was supposedly added to clang\n# in 3.9 but not really supported until about 4.3, and then in clang\n# something, maybe 4.7 or so, was also added as a link flag, see\n# tools/getlibs.sh, so it's enabled here for clang 4.3 or newer and then in\n# tools/getlibs.sh also for clang 4.7 or newer.\n\nif [ $ISCLANG -gt 0 ] && [ $ISSPECIAL -eq 0 ] ; then\n\tCLANG_VER=\"$($CC -dumpversion | tr -d  '.' | cut -c 1-2)\" ;\n\tif [ $CLANG_VER -gt 42 ] ; then\n\t\tCCARGS=\"$CCARGS -fsanitize=safe-stack\" ;\n\tfi ;\nfi\n\n# The Sun compiler has its own set of problems, the biggest of which is\n# determining where it is and what it is (see comments elsewhere), but\n# another one is that some of the warning options changed across compiler\n# versions or possibly target types (there's no obvious pattern), so we have\n# to detect use of this compiler and then feed it the options to see which\n# one is accepted.\n\nif [ \"$OSNAME\" = \"SunOS\" ] && [ \"$($CC 2>&1 | grep -c \"cc -flags\")\" -gt 0 ] ; then\n\tCCARGS=\"$CCARGS -errtags=yes\" ;\n\ttouch suncctest.c ;\n\tif [ \"$($CC -erroff=E_ARG_INCOMPATIBLE_WITH_ARG suncctest.c 2>&1 | grep -c \"bad message\")\" -gt 0 ] ; then\n\t\tCCARGS=\"$CCARGS -erroff=E_ARG_INCOMPATIBLE_WITH_ARG_L\" ;\n\telse\n\t\tCCARGS=\"$CCARGS -erroff=E_ARG_INCOMPATIBLE_WITH_ARG\" ;\n\tfi ;\n\trm suncctest.c ;\nfi\n\n# If we're building a shared lib, set up the necessary additional cc args.\n# The IRIX cc and Cygwin/MinGW gcc (and for Cygwin specifically Cygwin-\n# native, not a cross-development toolchain hosted under Cygwin) don't\n# recognise -fPIC, but generate PIC by default anyway.  The PHUX compiler\n# requires +z for PIC, and Solaris cc requires -KPIC for PIC.  OS X\n# generates PIC by default, but doesn't mind having -fPIC specified anyway.\n# In addition it requires -fno-common for DYLIB use.\n#\n# For the PIC options, the only difference between -fpic and -fPIC is that\n# the latter generates large-displacement jumps while the former doesn't,\n# bailing out with an error if a large-displacement jump would be required.\n# As a side-effect, -fPIC code is slightly less efficient because of the use\n# of large-displacement jumps, so if you're tuning the code for size/speed\n# you can try -fpic to see if you get any improvement.\n\nif [ $SHARED -gt 0 ] ; then\n\tcase $OSNAME in\n\t\t'Darwin')\n\t\t\tCCARGS=\"$CCARGS -fPIC -fno-common\" ;;\n\n\t\t'CYGWIN_NT-5.0'|'CYGWIN_NT-5.1'|'CYGWIN_NT-6.1')\n\t\t\t;;\n\n\t\t'HP-UX')\n\t\t\tCCARGS=\"$CCARGS +z\" ;;\n\n\t\t'IRIX'|'IRIX64')\n\t\t\t;;\n\n\t\t'MINGW_NT-5.0'|'MINGW_NT-5.1'|'MINGW_NT-6.1')\n\t\t\t;;\n\n\t\t'SunOS')\n\t\t\tif [ \"$($CC -v 2>&1 | grep -c \"gcc\")\" = 0 ] ; then\n\t\t\t\tCCARGS=\"$CCARGS -KPIC\" ;\n\t\t\telse\n\t\t\t\tCCARGS=\"$CCARGS -fPIC\" ;\n\t\t\tfi ;;\n\n\t\t*)\n\t\t\tCCARGS=\"$CCARGS -fPIC\" ;;\n\tesac ;\nfi\n\n# Conversely, if we're building a static lib and the system requires it, set\n# up static lib-specific options.\n\nif [ $SHARED -eq 0 ] ; then\n\tcase $OSNAME in\n\n\t\t'BeOS')\n\t\t\tCCARGS=\"$CCARGS -D_STATIC_LINKING\" ;;\n\tesac ;\nfi\n\n# If the system supports recursive and/or robust mutexes, indicate that\n# they're available.  We don't use recursive mutexes by default because they\n# tend to be somewhat hit-and-miss but we at least indicate their presence\n# via a define.\n\nif [ -f /usr/include/pthread.h ] ; then\n\tif [ \"$(grep -c PTHREAD_MUTEX_RECURSIVE /usr/include/pthread.h)\" -gt 0 ] ; then\n\t\tCCARGS=\"$CCARGS -DHAS_RECURSIVE_MUTEX\" ;\n\tfi ;\n\tif [ \"$(grep -c PTHREAD_MUTEX_ROBUST /usr/include/pthread.h)\" -gt 0 ] ; then\n\t\tCCARGS=\"$CCARGS -DHAS_ROBUST_MUTEX\" ;\n\tfi ;\nfi\n\n# If we're not using gcc, we're done.  This isn't as simple as a straight\n# name comparison of cc vs. gcc, sometimes gcc is installed as cc so we\n# have to check whether the compiler is really gcc even if it's referred to\n# as cc.  In addition we have to be careful about which strings we check for\n# because i18n of the gcc -v output makes many strings highly mutable.  The\n# safest value to check for is \"gcc\", hopefully this won't yield any false\n# positives (apart from Aches, see below).\n#\n# To make things more entertaining, the Aches cc displays a manpage in\n# response to 'cc -v' (!!) and the manpage mentions a gcc-compatibility\n# feature so the compiler is misidentified as gcc.  In addition because\n# of clang's compatibility-with-gcc system clang can be misidentified as\n# gcc (or at least clang can appear as both clang and gcc, depending on\n# whether the check is for clang or gcc).\n#\n# To work around this we perform a special-case check for Aches and clang\n# and use a somewhat more direct check for gcc, which is likely to be\n# explicitily installed as 'gcc' rather than the system 'cc'.\n\nif [ \"$OSNAME\" = \"AIX\" ] ; then\n\tif [ $CC = \"xlc\" ] ; then\n\t\techo \"$CCARGS\" ;\n\t\texit 0 ;\n\tfi ;\n\tif [ \"$(which cc 2>&1 | grep -c \"gcc\")\" = 0 ] ; then\n\t\techo \"$CCARGS\" ;\n\t\texit 0 ;\n\tfi ;\nfi\nif [ $ISCLANG -gt 0 ] ; then\n\techo \"$CCARGS\" ;\n\texit 0 ;\nfi\n\nif [ \"$($CC -v 2>&1 | grep -c \"gcc\")\" = 0 ] ; then\n\techo \"$CCARGS\" ;\n\texit 0 ;\nfi\n\n# Find out which version of gcc we're using.  The check for the gcc version\n# is equally complicated by the fact that a (rare) few localised gcc's don't\n# use a consistent version number string.  Almost all versions print \"gcc\n# version\", but the French localisation has \"version gcc\" (we can't use just\n# \"gcc\" by itself since this appears elsewhere in the gcc -v output).\n#\n# To make things even more confusing, Apple's hacked-up gcc branch (before\n# they switched to clang) printed something like\n# \"PowerPC-Apple-Is-Great-I-Love-Darwin-4567-Hup234-gcc-x.y.z\", so any\n# simple attempt at extracting what looks like a version number will fail.\n# The only way to get around this is to look for the first set of numeric\n# values that follow the string \"gcc\" and use that as the version number.\n#\n# In order to avoid this mess we use the \"-dumpversion\" option, which has\n# worked since at least 2.7.2 although it wasn't actually documented until\n# the first 3.x releases).\n#\n# However, dumpversion has its own problems in that it lists major-version\n# releases as a single-digit number, '6' rather than '6.0', so if we find an\n# apparent version less than 20 we add a trailing zero to the string to make\n# the checks that follow work.\n\nGCC_VER=\"$($CC -dumpversion | tr -d  '.' | cut -c 1-2)\"\nif [ \"$GCC_VER\" -le 20 ] ; then\n\tGCC_VER=\"${GCC_VER}0\" ;\nfi\n\n# Try and determine the CPU type.  This is made more complex by a pile of\n# *BSE's which, along with antideluvian tools like an as that doesn't\n# recognise 486 opcodes, report the CPU type as i386.  Even sysctl reports\n# the CPU as being i386, so if we find this we assume it's some *BSE which\n# is actually running on a P4 or Athlon or something similar (unfortunately\n# there's no real way to detect this, but it's 99.9% likely that it's not\n# actually still running on an 80386).\n\nARCH=$(uname -m)\n\nif [ \"$ARCH\" = \"i386\" ] && [ \"$(uname | grep -c BSD)\" -gt 0 ] ; then\n\techo \"Warning: uname/sysctl reports that this machine is using an 80386 CPU (!!),\" >&2 ;\n\techo \"         continuing under the assumption that it's at least a Pentium.\" >&2 ;\n\techo >&2 ;\n\tARCH=\"i586\" ;\nfi\n\n# gcc changed its CPU architecture-specific tuning option from -mcpu to\n# -march in about 2003, so when using gcc to build for x86 systems (where\n# we specify the architecture as P5 rather than the default 386) we have\n# to use an intermediate build rule that changes the compiler arguments\n# based on compiler version info.  The reason for the change was to\n# distinguish -march (choice of instruction set used) from -mtune\n# (scheduling of instructions), so for example -march=pentium\n# -mtune=pentium4 would generate instructions from the pentium instruction\n# set but scheduled for the P4 CPU.  Usually -march=X also imples -mtune=X,\n# but newer versions of gcc allow an mtune=generic to tune for the most\n# widely-used current CPUs.  In particular, specifying -march=<oldest CPU\n# type to support> requires -mtune=generic otherwise it'll also -mtune for\n# the oldest CPU type rather than any current one.  To see what the current\n# setting is, use:\n#\n#\tgcc -Q --help=target\n#\n# For x86-64 it's -march=x86-64 -mtune=generic, the default config for gcc\n# on x86, which means that pretty much every instruction-set extension\n# beyond basic x64 is disabled.\n#\n# (The changeover is in fact somewhat messier than that, newer 2.9.x versions\n# (as well as 3.x onwards) recognised -march (depending on the CPU they\n# targeted and patch level) and all versions still recognise -mcpu, however\n# as of about 3.4.x the compiler complains about deprecated options whenever\n# it sees -mcpu used, which is why we use -march for 3.x and newer).\n#\n# As of version 4.2.0, gcc finally supports an option \"optimise for the\n# machine I'm building on\", eliminating the need to perform complex\n# guesswork for the CPU type, so if we're using any recent version we use\n# this by default.  If not, we fall back to guessing, but since it's not\n# really possible to determine the exact CPU type the only options that we\n# have (aside from the broken *BSE's reporting of \"80386\" mentioned above)\n# are \"586\" (generic pre-MMX(!!) Pentium), \"686\" (generic Pentium Pro), and\n# \"x86-64\" (generic x86-64).  The lowest common denominator is the generic\n# \"pentium\", which just means \"something better than the default 80386\",\n# unfortunately for x86-64 there's both no way to tell whose x86-64 we're\n# running on and no way to tell gcc that we want either generic Intel x86-64\n# or AMD x86-64.  The best that we can do is use \"opteron\", which is for\n# generic Opteron/Athlon64/K8/Athlon FX processors, but also works for\n# Intel's x86-64.\n#\n# Unfortunately handling of \"-march=native\" is pretty comprehensively broken\n# for the gcc 4.2 versions because of the hit-and-miss way that the\n# information is passed by the compiler driver to the compiler back-end.\n# Sometimes it works, sometimes it produces a \"bad value (native) for\n# -march= switch; bad value (native) for -mtune= switch\" error, and\n# sometimes it just bails out and falls back to \"-march=generic\" which\n# often produces very poor code.  As a result it's not safe to enable the\n# use of this option for anything before about gcc 4.5.\n#\n# For x86-64 we have to enable the use of PIC because of obscure linker\n# errors (\"relocation R_X86_64_32S can not be used when making a shared\n# object\") that crop up when building the shared-lib version, in the case\n# of x86-64 the use of PIC should have minimum overhead so it shouldn't be\n# a big deal.  As a convenient side-effect, this also enables the use of\n# ASLR where it's supported.\n\nif [ \"$ARCH\" = \"i586\" ] || [ \"$ARCH\" = \"i686\" ] || [ \"$ARCH\" = \"x86_64\" ] ; then\n\tif [ \"$GCC_VER\" -ge 45 ] ; then\n\t\tCCARGS=\"$CCARGS -march=native -mtune=generic\" ;\n\t\tif [ \"$ARCH\" = \"x86_64\" ] ; then\n\t\t\tCCARGS=\"$CCARGS -fPIC\" ;\n\t\tfi ;\n\telif [ \"$GCC_VER\" -ge 30 ] ; then\n\t\tcase $ARCH in\n\t\t\t'x86_64')\n\t\t\t\tCCARGS=\"$CCARGS -march=opteron -fPIC\" ;;\n\n\t\t\t'i686')\n\t\t\t\tCCARGS=\"$CCARGS -march=pentiumpro\" ;;\n\n\t\t\t*)\n\t\t\t\tCCARGS=\"$CCARGS -march=pentium\" ;;\n\t\tesac ;\n\telse\n\t\tCCARGS=\"$CCARGS -mcpu=pentium\" ;\n\tfi ;\nfi\n\n# gcc 4.x for 64-bit architectures has an optimiser bug that removes an\n# empty-list check in cryptlib's list-management code (this has been\n# verified for at least 4.0.x and 4.1.x for x86-64 and ppc64).  When running\n# the self-test, this is first detectable in cert/dn.c in the function\n# deleteComponent(), where the missing check for an empty list causes a\n# segfault when the code tries to access a nonexistent list element.\n# There's not much that we can do about this except warn the user.\n#\n# (Update: Rearranging some lines in the source causes the compiler to emit\n#  correct code, so hopefully this shouldn't be necessary any longer).\n#\n# In theory we should also use '-s' for read to turn off echoing of\n# keystrokes, however not all shells (e.g. Debian's stupid dash, which is\n# symlinked to /bin/sh in some distros) support this.\n#\n#if [ \"$GCC_VER\" -ge 40 -a '(' \"$ARCH\" = \"x86_64\" -o \"$ARCH\" = \"ppc64\" ')' ] ; then\n#\techo >&2 ;\n#\techo \"Warning: The version of gcc that this system uses has an optimiser bug in\" >&2 ;\n#\techo \"         its 64-bit code generation.  If the cryptlib self-test segfaults\" >&2 ;\n#\techo \"         during the certificate self-test, rebuild the code with -O2\" >&2 ;\n#\techo \"         instead of the current -O3.\" >&2 ;\n#\tread -n1 -p \"Hit a key...\" ;\n#\techo >&2 ;\n#fi\n\n# gcc 4.x changed the way that it performs optimisation so that -O3 often\n# results in the creation of far larger binaries than -O2, with ensuing poor\n# cache localisation properties.  In addition it enhances the triggering of\n# gcc optimiser bugs, something that seems to be particularly bad in 4.x.\n# While cryptlib contains numerous code-generation bug workarounds for gcc 4.x\n# (and 3.x, and 2.x), the potential performance problems with -O3 means that\n# it's better to just turn it off.\n#\n# (Update: Having optimisation set via this script rather than in the\n#  makefile purely for gcc is awkward because if we're building under the\n#  same OS but using clang then the optimisation level is never set.  Since\n#  newer versions of gcc might be less buggy than the awful 4.x series we\n#  go back to specifying the optimisation level in the makefile).\n#\n#if [ \"$OSNAME\" = \"Linux\" ] || [ \"$OSNAME\" = \"FreeBSD\" ] || \\\n#   [ \"$OSNAME\" = \"NetBSD\" ] || [ \"$OSNAME\" = \"OpenBSD\" ] || \\\n#   [ \"$OSNAME\" = \"Darwin\" ] ; then\n#\tif [ \"$GCC_VER\" -ge 40 ] ; then\n#\t\tCCARGS=\"$CCARGS -O2\" ;\n#\telse\n#\t\tCCARGS=\"$CCARGS -O3\" ;\n#\tfi ;\n#fi\n\n# Check for gcc 4.x with its stupid default setting of -Wpointer-sign,\n# which leads to endless warnings about signed vs.unsigned char problems -\n# you can't even call strlen() without getting warnings.\n#\n# Older versions of Solaris' sh can't handle the test below as a single line\n# so we have to break it apart into two lines.  In addition without the\n# backquotes the script will silently exit at this point (!!) so we quote the\n# argument to 'test'.\n#\n# Unfortunately enabling C99 with gcc (see below) also enables the C99\n# aliasing rules, or at least endless whiny warnings about potential\n# problems with C99 aliasing rules, reported as type punning by gcc 4.x.\n# Because of the way the cryptlib kernel works there's no way to work around\n# this (well, except for horrible kludges with unions) because it uses a\n# generic message-payload type that's always passed as a void *.  There's no\n# easy way to fix this, we could in theory perform a massive janitorial run-\n# through applying intermediate void casts between source and target (e.g.\n# '( struct foo * ) ( void * ) whatever') but this just masks the problem,\n# makes the code look ugly, and could quite well hide other problems because\n# of the make-it-go-away void cast.  Telling the compiler to shut is far\n# cleaner, since it doesn't seem to have any effect on the code generated\n# anyway.\n\nif [ \"$GCC_VER\" -ge 40 ] ; then\n\tif [ \"$($CC -Wno-pointer-sign -S -o /dev/null -xc /dev/null 2>&1 | grep -c \"unrecog\")\" -eq 0 ] ; then\n\t\tCCARGS=\"$CCARGS -Wno-pointer-sign\" ;\n\tfi ;\n\tCCARGS=\"$CCARGS -Wno-strict-aliasing\" ;\nfi\n\n# The gcc developers are of the opinion that once the compiler encounters\n# anything that can be classed as undefined behaviour (UB, e.g. an integer\n# addition) then the compiler is allowed to do anything it wants.  While\n# they very generously refrain from reformatting your hard drive, what they\n# do do is remove code that does things like check for integer overflow or\n# null pointers that may exist beyond the point where the UB can occur.\n# Compilers like MSVC assume that they're running on a two's-complement\n# machine and act accordingly, while gcc knows that it's also running on a\n# two's-complement machine but nevertheless can't exlude the theoretical\n# possibility that it's running on a one's-complement CDC 6600 from 1965 and\n# therefore can't assume two's-complement behaviour.\n#\n# gcc then allows you to extend the braindamage by specifying -ftrapv, which\n# generates a trap if overflow is encountered.  This means that gcc's\n# default behaviour is to be braindamaged, and if -ftrapv is specified, to\n# be braindamaged and then cause your app to crash.\n#\n# To get around this, we specify -fwrapv (yes, you really can assume that\n# you're on a two's-complement machine, which has been the case for\n# everything from the last half-century or so) and -fno-delete-null-pointer-\n# checks (behaviour that's so totally stupid that it's incredible that you\n# actually need to specify an option to fix it).\n#\n# There are actually two variants of the overflow-braindamage-limiting\n# mechanism, -fwrapv and -fno-strict-overflow, which do more or less the\n# same thing but in subtly different ways that no-one is quite clear on.\n# One explanation is that -fwrapv tells the compiler that integer overflow\n# wraps while -fno-strict-overflow tells the compiler that integer overflow\n# can happen, but not what happens (in other words it tells it not to remove\n# code based on this).  Since we know that we're running on a two's-\n# complement machine, we use -fwrapv to reflect this.\n\nif [ \"$GCC_VER\" -ge 40 ] ; then\n\tCCARGS=\"$CCARGS -fwrapv -fno-delete-null-pointer-checks\" ;\nfi\n\n# The AES code uses 64-bit data types, which older vesions of gcc don't\n# support (at least via limits.h) unless they're operating in C99 mode.  So\n# in order to have the AES auto-config work we have to explicitly run gcc\n# in C99 (or newer) mode, which isn't the default for the gcc 3.x and some\n# 4.6 versions.  Since the code also uses gcc extensions we have to specify\n# the mode as gcc + C99, not just C99.\n\nif [ \"$GCC_VER\" -ge 30 ] && [ \"$GCC_VER\" -le 46 ] ; then\n\tCCARGS=\"$CCARGS -std=gnu99\" ;\nfi\n\n# Use of static_assert() requires that gnu11 mode be enabled, this isn't\n# recognised by gcc 4.6, is recognised but not the default for gcc 4.7-4.9\n# (the alleged default is gnu90 but it actually seems to be gnu99), and is\n# the default for gcc 5.0 and above */\n\nif [ \"$GCC_VER\" -ge 47 ] && [ \"$GCC_VER\" -le 49 ] ; then\n\tCCARGS=\"$CCARGS -std=gnu11\" ;\nfi\n\n# Enable stack protection and extra checking for buffer overflows if it's\n# available.  This was introduced (in a slightly hit-and-miss fashion) in\n# later versions of gcc 4.1.x, to be on the safe side we only enable it\n# for gcc 4.2 and newer.  gcc 4.9 introduced a slightly more comprehensive\n# version so we use that if it's available.  Some people like to add\n# '--param=ssp-buffer-size=4' (the default size is 8), but this isn't\n# necessary for cryptlib since it doesn't allocate any 4-byte buffers.\n\nif [ \"$GCC_VER\" -ge 49 ] ; then\n\tCCARGS=\"$CCARGS -fstack-protector-strong -D_FORTIFY_SOURCE=2\" ;\nelif [ \"$GCC_VER\" -ge 42 ] ; then\n\tif [ \"$($CC -fstack-protector -S -o /dev/null -xc /dev/null 2>&1 | grep -c \"unrecog\")\" -eq 0 ] ; then\n\t\tCCARGS=\"$CCARGS -fstack-protector\" ;\n\tfi ;\n\tCCARGS=\"$CCARGS -D_FORTIFY_SOURCE=2\" ;\nfi\n\n# Newer versions of gcc support marking the stack as nonexecutable (e.g.\n# using the x86-64 NX bit), so if it's available we enable it.  This is\n# easier than the alternative of adding a:\n#\n# #if defined( __linux__ ) && defined( __ELF__ )\n#   .section .note.GNU-stack, \"\", %progbits\n# #endif\n#\n# to .S files since (a) we don't control most of the .S files and (b)\n# some of the code is inline asm in C functions.\n#\n# Unfortunately this isn't possible to check for easily, at best we can\n# do something like:\n#\n# if (echo|as --noexecstack -o /dev/null > /dev/null 2>&1); then\n#\tCCARGS=\"$CCARGS -Wa,--noexecstack\" ;\n# fi\n#\n# (which is necessary because no two assemblers have a consistent command-\n# line interface so that we can't even reliably get version information as\n# we can for gcc) but even this is problematic because even if the assembler\n# claims to support it actual handling is still rather hit-and-miss.\n\n# Enable additional compiler diagnostics if we're building on the usual\n# development box.  We only enable it on this one system to avoid having\n# users complain about getting warnings when they build it.\n#\n# The warnings are:\n#\n# -Waddress: Warn about suspicious use of memory addresses, e.g.\n#\t\t'x == \"abc\"'  (-Wall).\n#\n# -Waggregate-return: Warn about functions that return structs.  This isn't\n#\t\tused any more as of 3.4.4 due to the use of safe pointers, which are\n#\t\tscalar values.\n#\n# -Walloc-zero: Warn about call to malloc( 0 ).\n#\n# -Walloc-size-larger-than=value: Warn when a call to malloc() exceeds\n#\t\t'value', potentially caused by arithmetic overflow\n#\t\t(-Wall = -Walloc-size-larger-than=PTRDIFF_MAX).\n#\n# -Walloca: Warn about use of alloc().\n#\n# -Warray-bounds: Warn about out-of-bounds array accesses, requires the use\n#\t\tof -ftree-vrp (which is enabled for -O2 and above) (-Wall).\n#\n# -Wcast-align: Warn whenever a pointer is cast such that the required\n#\t\talignment of the target is increased, for example if a \"char *\" is\n#\t\tcast to an \"int *\".\n#\n# -Wchar-subscripts: Warn when an array has a char subscript (-Wall).\n#\n# -Wdangling-else: Warn about dangling else.\n#\n# -Wdeclaration-after-statement: Warn about a variable declaration found\n#\t\tafter a statement in a function (VC++ 6.0 complains about this too).\n#\n# -Wduplicate-decl-specifier: Warn about duplicate 'const', 'volatile' etc\n#\t\tin a declaration (-Wall).\n#\n# -Wduplicated-branches: Warn if an if/else as identical branches (no idea\n#\t\thow this differs from -Wduplicated-cond).\n#\n# -Wduplicated-cond: Warn about duplicate conditions in an if/else chain.\n#\n# -Wendif-labels: Warn if an endif is followed by text.\n#\n# -Wempty-body: Warn if an empty body occurs in and if/else or do/while.\n#\n# -Wextra: Extra warnings on top of -Wall\n#\n# -Wformat: Check calls to \"printf\" etc to make sure that the args supplied\n#\t\thave types appropriate to the format string (-Wall).\n#\n# -Wformat-nonliteral: Check whether a format string is not a string literal,\n#\t\ti.e. argPtr vs \"%s\".\n#\n# -Wformat-overflow: Check for problems with overflows in arguments to\n#\t\tsprintf().\n#\n# -Wformat-security: Check for potential security problems in format strings.\n#\n# -Wformat-truncation: Chek for problems with truncation in arguments to\n#\t\tsprintf() (-Wall).\n#\n# -Wimplicit-int: Warn about typeless variable declarations (-Wall).\n#\n# -Wimplicit-fallthrough=5: Warn about falling through a case statement in a\n#\t\tswitch without it being annotated as a fallthrough via an attribute\n#\t\t(-Wextra, but default is level 3, not level 5).\n#\n# -Winit-self: Warn if a value is initialised to itself, e.g. 'int i=i'.\n#\n# -Wjump-misses-init: Warn if a goto or switch misses initialisation of a\n#\t\tvariable.\n#\n# -Wlogical-op: Warn about suspicious use of logical operators in\n#\t\texpressions, e.g. '|' vs '||'.\n#\n# -Wlogical-not-parentheses: Warn about \"logical not\" used on the left hand\n#\t\tside operand of a comparison.\n#\n# -Wmemset-elt-size: Warn when size argument for memset() of array doesn't\n#\t\tinclude sizeof() the elemtns (-Wall).\n#\n# -Wmemset-transposed-args: Warn about memset( ..., n, 0 ) where\n#\t\tmemset( ..., 0, n ) was probably meant (-Wall).\n#\n# -Wmisleading-indentation: goto fail (-Wall).\n#\n# -Wmissing-braces: Warn if an array initialiser isn't fully bracketed, e.g.\n#\t\tint a[2][2] = { 0, 1, 2, 3 } (-Wall).\n#\n# -Wmissing-parameter-type: Warn if a function has a K&R-style declaration,\n#\t\tint foo() { ... } (-Wextra).\n#\n# -Wmultistatement-macros: Warn about macros that expand to multiple\n#\t\tstatements, causing problems if not enclosed in braces (-Wall).\n#\n# -Wnonnull: Warn about passing a null for function args tagged as being\n#\t\t__nonnull (-Wall).\n#\n# -Wnonnull-compare: Warn about checking an argument marked __nonnull for\n#\t\tNULL (-Wall).\n#\n# -Wnull-dereference: Guess at potential derefencing of null pointers, only\n#\t\tenabled if -fdelete-null-pointer-checks is active, which it is if\n#\t\toptimisation is enabled (note however that we disable this in order\n#\t\tto limit the braindamage that it causes, see the comment earlier).\n#\t\tThis option appears to be a grudging admission of the braindamage of\n#\t\texisting nonnull behaviour.\n#\n# -Wparentheses: Warn about missing parantheses where the resulting\n#\t\texpression is ambiguous (or at least nonobvious) (-Wall).\n#\n# -Wpointer-arith: Warn about anything that depends on the sizeof a\n#\t\tfunction type or of void.\n#\n# -Wredundant-decls: Warn if anything is declared more than once in the same\n#\t\tscope.\n#\n# -Wreturn-type: Warn about incorrect return type for function, e.g.\n#\t\treturn( 1 ) for void function (-Wall).\n#\n# -Wsequence-point: Warn about sequence point violations, e.g. a = a++ (-Wall).\n#\n# -Wshadow: Warn whenever a local variable shadows another local variable,\n#\t\tparameter or global variable (that is, a local of the same name as\n#\t\tan existing variable is declared in a nested scope).  Note that this\n#\t\tleads to some false positives as gcc treats forward declarations of\n#\t\tfunctions within earlier functions that have the same parameters as\n#\t\tthe function they're declared within as shadowing.  This can be\n#\t\tusually detected in the output by noting that a pile of supposedly\n#\t\tshadow declarations occur within a few lines of one another.\n#\n# -Wshift-count-negative: Warn about problems with shift counts (default).\n# -Wshift-count-overflow:\n#\n# -Wshift-negative-value: Warn about left-shifting a negative value.\n#\n# -Wshift-overflow: Warn about shift overflows.\n#\n# -Wsizeof-array-argument: Warn when the sizeof operator is applied to a\n#\t\tparameter that has been declared as an array in a function\n#\t\tdefinition.\n#\n# -Wsizeof-pointer-div: Warn about e.g. sizeof( ptr ) / sizeof(ptr[ 0 ])\n#\t\twhen ptr isn't an array (-Wall).\n#\n# -Wsizeof-pointer-memaccess: Warn about suspicious use of sizeof with some\n#\t\tstring and memory functions, e.g.\n#\t\tmemcpy( &foo, ptr, sizeof( &foo ) ) (-Wall)\n#\n# -Wstrict-overflow: Warn about potential integer overflow.  This is probably\n#\t\tnegated by the options to limit gcc's braindamaged handling of\n#\t\t(potential) overflow, see the comments earlier on for more on this.\n#\n# -Wstrict-prototypes: Warn if a function is declared or defined K&R-style.\n#\n# -Wstringop-overflow: Warn of string/mem functions that overflow the\n#\t\tdestination buffer (-W..=2, default).\n#\n# -Wstringop-truncation: Warn about string ops that truncate the operation,\n#\t\te.g. 'strncat( buf, \".txt\", 3 );' will only copy 3 of the 4 string\n#\t\tchars (-Wall).\n#\n# -Wswitch-bool: Warn whenever a switch statement has an index of boolean\n#\t\ttype.\n#\n# -Wswitch-unreachable: Warn whenever a switch statement has unreachable\n#\t\tcode, e.g. code before the first \"case:\" (default).\n#\n# -Wtautological-compare: Warn about self-comparison, e.g. if( i == i )\n#\t\t(-Wall).\n#\n# -Wtrampolines: Warn if trampolines are being generated, which requires an\n#\t\texecutable stack.  This is only done for nested functions:\n#\n#\t\tfoo( int x )\n#\t\t\t{\n#\t\t\tbar( int y )\n#\t\t\t\t{ };\n#\t\t\t}\n#\n#\t\twhich are a gcc-ism and not used anywhere, but we enable it anyway\n#\t\tjust in case.\n#\n# -Wtype-limits: Warn if a comparison is always true due to the limited\n#\t\trange of a data type, e.g. unsigned >= 0.\n#\n# -Wundef: Warn if undefined identifier is used in #if.\n#\n# -Wunused-const-variable: Warn of unused const variables.\n#\n# -Wunused-function: Warn if a static function isn't used (-Wall).\n#\n# -Wunused-label: Warn if a label isn't used (-Wall).\n#\n# -Wunused-variable: Warn if a local variable isn't used (-Wall).\n#\n# -Wunused-but-set-variable: Warn when a variable is assigned to but not\n#\t\tused (-Wall).\n#\n# -Wunused-local-typedefs: Warn about unused typedef (-Wall).\n#\n# -Wunused-value: Warn if a statement produces a result that isn't used,\n#\t\te.g. 'x[i]' as a standalone statement (-Wall).\n#\n# -Wundef: Warn if an undefined identifier is used in a #if.\n#\n# -Wunsafe-loop-optimizations: Warn if the compiler can't reason about loop\n#\t\tbounds.\n#\n# -Wvla: Warn if variable-length array is used.\n#\n# -Wwrite-strings: Warn on attempts to assign/use a constant string value\n#\t\twith a non-const pointer.\n#\n# -Wzero-as-null-pointer-constant: Warn if an explicit 0 or '\\0' is used\n#\t\tinstead of NULL.  Unfortunately this is currently valid (gcc 4.7)\n#\t\tonly for C++ so we can't use it.\n#\n# Note that some of these require the use of at least -O2 in order to be\n# detected because they require the use of various levels of data flow\n# analysis by the compiler.\n#\n# Finally, there are warnings that, as implemented by gcc, are more or less\n# useless due to excessive false positives, for example warning on nearly\n# every single stdlib function call.  See for example \"Twice the Bits, Twice\n# the Trouble\", Wressnegger et al, CCS'16, for more on this, which found\n# 45,000 false positives covering up the few actual issues.  Because they're\n# essentially useless due to the level of noise, we disable them (if they're\n# enabled through -Wall) or don't use them if they're optional.  VC++\n# provides a usable level of warnings about these issues so we rely on that:\n#\n# -Wconversion: Warn for potentially problematic conversions, e.g.\n#\t\t'unsigned foo = -1'.  This also warns for things like conversion\n#\t\tfrom int to long unsigned int/size_t, leading to avalanches of\n#\t\tpointless warnings.  For example pretty much every stdlib function\n#\t\tthat takes a length parameter anywhere produces a warning when a\n#\t\tgeneric int variable is converted to a size_t.\n#\n# -Wno-ignored-qualifiers: Use of const with by-value return, for example\n#\t\tin 'const DATAPTR dataptrAttributeMoveCursor( ... )'.  This was\n#\t\trequired starting with 3.4.4's use of safe pointers, see also the\n#\t\tcomment for -Waggregate-return.\n#\n# -Wno-missing-field-initializers: Warn about missing initialisers in structs.\n#\t\tThis also warns about things like the fairly common 'struct foo = { 0 }',\n#\t\twhich makes it too noisy for detecting problems (-Wextra).\n#\n# -Wno-nonnull-compare: An extension of the nonnull braindamage in which,\n#\t\talongside removing NULL checks, they're all warned about as well.\n#\n# -Wno-sign-compare: Warn about compares between signed and unsigned values.\n#\t\tThis leads to endless warnings about comparing a signed to an\n#\t\tunsigned value, particularly problematic when comparing an integer\n#\t\tto a CRYPT_xxx_yyy enum because enums are treated as unsigned so\n#\t\tevery comparison leads to a warning (-Wall, -Wextra).\n#\n# -Wno-switch: Warn about unused enum values in a switch statement.  Since\n#\t\tall cryptlib attributes are declared from a single pool of enums but\n#\t\tonly the values for a particular object class are used in the\n#\t\tobject-specific code, this leads to huge numbers of warnings about\n#\t\tunhandled enum values in case statements (-Wall).\n#\n# -Wuninitialized: Warn about used-before-initialised.  The detection of this\n#\t\tisn't very good, variables initialised conditionally always produce\n#\t\twarnings.\n#\n# -Wunreachable-code: The use of -O2/-O3 interacts badly with this due to\n#\t\tstatements rearranged by the optimiser being declared unreachable.\n#\t\tBecause of this the capability was removed in January 2010\n#\t\t(http://gcc.gnu.org/ml/gcc-patches/2009-11/msg00179.html), so while\n#\t\tthe compiler still accepts the option it silently ignores it (par\n#\t\tfor the course for gcc).\n#\n# Finally there's also -Wextra, which warns about even more potential\n# problems, at the cost of more false positives.\n#\n# In addition to the standard warnings we also enable the use of gcc\n# attributes warn_unused_result and nonnull, which are too broken (and in\n# the case of nonnull far too dangerous) to use in production code (see the\n# long comment in misc/analyse.h for details), and to catch the compiler\n# brokenness we undefine NDEBUG to enable the use of assertion checks that\n# will catch the problem.\n#\n# Alongside the warnings, we also enable various sanitisers if they're\n# available.  We can't use -fsanitize=thread because it's incompatible\n# with -fsanitize=address, not because of the compiler but because they\n# require different memory layouts in the runtime libraries.  In addition\n# the sanitizers require specific library support and since the clang/\n# fuzzing build incorporates them anyway it's easier not to bother:\n#\n#\tif [ \"$GCC_VER\" -ge 48 ] ; then\n#\t\techo \"  (Enabling additional compiler options for gcc 4.8.x).\" >&2 ;\n#\t\tCCARGS=\"$CCARGS -fsanitize=address -lasan\" ;\n#\tfi ;\n#\tif [ \"$GCC_VER\" -ge 49 ] ; then\n#\t\techo \"  (Enabling additional compiler options for gcc 4.9.x).\" >&2 ;\n#\t\tCCARGS=\"$CCARGS -fsanitize=undefined -lubsan\" ;\n#\tfi ;\n#\n# We also enable -finstrument-functions and -fexceptions if possible in\n# order to be able to print stack trace information when debugging.  We\n# can't enable it on x86-64 where SSE intrinsics are used for AES support\n# because then gcc in its infinite buggyness decides to instrument SSE\n# intrinsics, which aren't functions, and compilation fails with a string of\n# undefined-reference errors.\n\nif [ $ANALYSE -gt 0 ] ; then\n\tCCARGS=\"$CCARGS -DUSE_GCC_ATTRIBUTES\" ;\nelif [ $ISDEVELOPMENT -gt 0 ] ; then\n\techo \"  (Enabling unsafe compiler options for development version).\" >&2 ;\n\tCCARGS=\"$CCARGS -Wall -Wcast-align -Wdeclaration-after-statement \\\n\t\t\t\t\t-Wempty-body -Wextra -Wformat-nonliteral \\\n\t\t\t\t\t-Wformat-security -Winit-self -Wlogical-op \\\n\t\t\t\t\t-Wparentheses -Wpointer-arith -Wredundant-decls \\\n\t\t\t\t\t-Wshadow -Wstrict-overflow -Wstrict-prototypes \\\n\t\t\t\t\t-Wtype-limits -Wundef -Wvla\" ;\n\tCCARGS=\"$CCARGS -Wno-ignored-qualifiers -Wno-missing-field-initializers \\\n\t\t\t\t\t-Wno-switch -Wno-sign-compare\" ;\n\tCCARGS=\"$CCARGS -DUSE_GCC_ATTRIBUTES -UNDEBUG\" ;\n\tif [ \"$GCC_VER\" -ge 45 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 4.5.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Wlogical-op -Wjump-misses-init\" ;\n\tfi ;\n\tif [ \"$GCC_VER\" -ge 47 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 4.7.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Wtrampolines -Wunused-local-typedefs\" ;\n\tfi ;\n\tif [ \"$GCC_VER\" -ge 50 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 5.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Wlogical-not-parentheses -Wsizeof-array-argument \\\n\t\t\t\t\t\t-Wswitch-bool -Wmissing-parameter-type\" ;\n\tfi ;\n\tif [ \"$GCC_VER\" -ge 60 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 6.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Wshift-negative-value -Wshift-overflow \\\n\t\t\t\t\t\t-Wnull-dereference -Wduplicated-cond \\\n\t\t\t\t\t\t-Wno-nonnull-compare -Wundef\" ;\n\tfi ;\n\tif [ \"$GCC_VER\" -ge 70 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 7.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Walloca -Wduplicated-branches -Wmemset-elt-size \\\n\t\t\t\t\t\t-Wduplicate-decl-specifier -Wdangling-else \\\n\t\t\t\t\t\t-Walloc-size-larger-than=1000000 -Walloc-zero \\\n\t\t\t\t\t\t-Wformat-overflow -Wformat-truncation \\\n\t\t\t\t\t\t-Wimplicit-fallthrough=5 -Wunused-const-variable=1 \\\n\t\t\t\t\t\t-Wunsafe-loop-optimizations\" ;\n\tfi ;\n\tif [ \"$GCC_VER\" -ge 80 ] ; then\n\t\techo \"  (Enabling additional compiler options for gcc 8.x).\" >&2 ;\n\t\tCCARGS=\"$CCARGS -Wmultistatement-macros\" ;\n\tfi ;\n\tif [ \"$ARCH\" != \"x86_64\" ] ; then\n\t\tCCARGS=\"$CCARGS -finstrument-functions -fexceptions\" ;\n\tfi ;\nfi\n\n# Finally, report what we've found\n\necho \"$CCARGS\"\n"
  },
  {
    "path": "deps/cl345/tools/cryptlibConverter.py",
    "content": "import sys\nimport os\nimport stat\nimport re\n\n\n#Helper Functions\n#==========================================================================\n\ndef parseEnumContents(enumContents, nameSpace, debugString):\n    enumPattern = re.compile(r\"(CRYPT_[\\w_]*)\\s*(=.*?)?(\\Z|,|(?=/))\", re.DOTALL)     # %1 [= %2][,]\n    commentPattern = re.compile(r\"\\s*/\\*(.*)\\*/\")                                    # /* %1 */\n    counter = 0     #Keep track of the implicit enum value\n    enumTuples = [] #Build a list of (key, val, comment) tuples, one for each enum value\n\n    #Find the next \"enum value\"\n    enumMatch = enumPattern.search(enumContents)\n    while enumMatch:\n\n        #Extract the key and RHS value\n        rawKey, rawVal = enumMatch.groups()[:-1]\n\n        key = rawKey.rstrip()\n        if not key.startswith(\"CRYPT_\"):\n            raise \"enum'd value doesn't start with CRYPT_ \"+key\n        key = key.replace(\"CRYPT_\", \"\")\n\n        #Evaluate the RHS (if it exists) to get the value\n        if rawVal:\n            rhs = rawVal[1:].strip().replace(\"CRYPT_\", \"\")\n            val = eval(rhs, nameSpace)\n        #Otherwise the value is the implicit counter\n        else:\n            val = counter\n\n        #Extract the comment\n        commentMatch = commentPattern.match(enumContents, enumMatch.end())\n        if commentMatch:\n            rawComment = commentMatch.group(1)\n            comment = rawComment.strip()\n        else:\n            comment = \"\"\n\n        #Collect all the parsed values into a tuple\n        enumTuple = (key, str(val), comment)\n\n        #if comment:\n        #    print debugString+ \":\" + \" Parsed Element %s = %s /* %s */\" % enumTuple\n        #else:\n        #    print debugString+ \":\" + \" Parsed Element %s = %s\" % enumTuple[:-1]\n        #raw_input()\n\n        nameSpace[key] = val    #Add new enum value into namespace\n        counter = val + 1       #Increment implicit enum value\n\n        #Accumulate the parsed (key, val, comment) tuples\n        enumTuples.append(enumTuple)\n\n        #Get next enum value\n        enumMatch = enumPattern.search(enumContents, enumMatch.end())\n\n    return enumTuples\n\n#Parses a string of function parameters into a list of ParamStruct\nclass ParamStruct:\n    def __init__(self):\n        self.type = \"\"\n        self.isPtr = 0\n        self.isOut = 0\n        self.category = \"\"\n        self.name = \"\"\n        self.rawIndex = 0 # The index of this param in the initial, raw cryptlib header\n    def __str__(self):\n        return str( (self.type, self.isPtr, self.category, self.name, self.rawIndex) )\n\ndef parseFunctionParams(functionParams):\n    paramStructs = []\n    functionParams = functionParams.replace(\"\\n\", \"\") #Make one big line\n    functionParamsList = [e.strip() for e in functionParams.split(\",\")] #Break into a list of params\n    index = 0\n    for e in functionParamsList:\n        pieces = e.split(\" \")   #Separate each param into component pieces, ie [\"C_IN\", \"CRYPT_ALGO_TYPE\", \"cryptAlgo\"]\n        p = ParamStruct()\n        if len(pieces)==1 and pieces[0]==\"void\":\n            continue\n        elif len(pieces)==3:\n            if pieces[0] == \"C_OUT\":\n                p.isOut = 1\n            if pieces[0] == \"C_OUT_OPT\":\n                p.isOut = 1\n            if pieces[1] == \"C_STR\":\n                p.type = \"char\"\n                p.name = pieces[2]\n                p.isPtr = 1\n            else:\n                p.type = pieces[1]\n                p.name = pieces[2]\n                p.isPtr = 0\n        elif len(pieces)==4:    #Ie [\"C_OUT\", \"CRYPT_CONTEXT\", \"C_PTR\", \"cryptContext\"]\n            if pieces[0] == \"C_OUT\":\n                p.isOut = 1\n            if pieces[0] == \"C_OUT_OPT\":\n                p.isOut = 1\n            p.type = pieces[1]\n            if pieces[2] == \"C_PTR\":\n                p.isPtr = 1\n            else:\n                raise \"Expecting C_PTR in parseFunctionParams\"\n            p.name = pieces[3]\n        else:\n            raise \"parsing error in parseFunctionParams\"\n        if p.type in enumTypes:\n            p.category = \"enumType\"\n        elif p.type in intTypes:\n            p.category = \"intType\"\n        elif p.type in structTypes:\n            p.category = \"structType\"\n        elif p.type in rawTypes:\n            p.category = \"rawType\"\n        else:\n            raise \"unknown type error is parseFunctionParams\"\n        p.rawIndex = index\n        index += 1\n        paramStructs.append(p)\n    #for p in paramStructs:\n    #    print p.__dict__\n    #raw_input()\n    return paramStructs\n\n#Takes a string containing a JNI function parameters prototype list, and a list of ParamStructs\n#And injects names into the string and returns it\ndef expandFunctionPrototype(functionPrototype, newParamStructs):\n    functionPrototype = functionPrototype.replace(\"\\n\", \"\") #Make one big line\n    paramPrototypesList = [e.strip() for e in functionPrototype.split(\",\")] #Break into a list of params\n    paramNamesList = [\"env\", \"cryptClass\"] + [e.name for e in newParamStructs]\n    newFunctionParams = \"\"\n    for (p1, p2) in zip(paramPrototypesList, paramNamesList):\n        newFunctionParams += p1 + \" \" + p2 + \", \"\n    newFunctionParams = newFunctionParams[:-2]\n    return newFunctionParams\n\n\n\n\n\n\n#Main\n#=========================================================================\n#Execution starts here...\n#=========================================================================\nif len(sys.argv) != 4:\n    print \"cryptlibConverter.py <inFile> <outDir> <language>\"\n    sys.exit()\n\ninFile = sys.argv[1]\noutDir = sys.argv[2]\nlanguage = sys.argv[3]\n\nif not os.path.exists(outDir):\n    print \"Making output directory...\"\n    os.mkdir(outDir)\n\nif not language in (\"java\", \"python\", \"net\"):\n    print \"only java, python, and net are supported!\"\n    sys.exit()\n\nif language == \"java\":\n    #ENUM IDIOM\n    #typedefEnumTemplate = \"public static class %(typedefName)s\\n{public int getValue(){return m_value;}private %(typedefName)s(int value){m_value = value;}int m_value;}\"\n    #typedefEnumElementTemplate = \"public static final %(typedefName)s %(name)-NPADs = new %(typedefName)s(%(value)-VPADs);\"\n    #ENUMs as ints\n    typedefEnumTemplate = \"// %(typedefName)s\"\n    typedefEnumElementTemplate = \"public static final int %(name)-NPADs = %(value)-VPADs;\"\n\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" // %(comment)s\"\n    simpleEnumElementTemplate = \"public static final int %(name)-NPADs = %(value)-VPADs;\"\n    simpleEnumElementTemplateComment = simpleEnumElementTemplate + \" // %(comment)s\"\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = simpleEnumElementTemplate\n    defineTemplateComment = simpleEnumElementTemplateComment\n    exceptionPrefix = \"\"\"\npackage cryptlib;\n\npublic class CryptException extends Exception\n{\n    private int m_status;\n    private String m_message;\n    public CryptException(int status)\n    {\n        m_status = status;\n        String prefix = Integer.toString(status) + \": \";\n\n\"\"\"\n    exceptionPostfix = \"\"\"\\\n        m_message = prefix + \"Unknown Exception ?!?!\";\n    }\n\n    public int getStatus()\n    {\n        return m_status;\n    }\n\n    public String getMessage()\n    {\n        return m_message;\n    }\n};\"\"\"\n    exceptionTemplate = \"\"\"\\\n        if (m_status == crypt.%(name)s) {\n            m_message = prefix + \"%(comment)s\";\n            return; }\n\"\"\"\n    cryptQueryInfoString = \"\"\"\npackage cryptlib;\n\npublic class CRYPT_QUERY_INFO\n{\n    public String algoName;\n    public int blockSize;\n    public int minKeySize;\n    public int keySize;\n    public int maxKeySize;\n\n    public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)\n    {\n        algoName = newAlgoName;\n        blockSize = newBlockSize;\n        minKeySize = newMinKeySize;\n        keySize = newKeySize;\n        maxKeySize = newMaxKeySize;\n    }\n};\"\"\"\n    cryptObjectInfoString = \"\"\"\npackage cryptlib;\n\npublic class CRYPT_OBJECT_INFO\n{\n    public int objectType;\n    public int cryptAlgo;\n    public int cryptMode;\n    public int hashAlgo;\n    public byte[] salt;\n\n    public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)\n    {\n        objectType = newObjectType;\n        cryptAlgo = newCryptAlgo;\n        cryptMode = newCryptMode;\n        hashAlgo = newHashAlgo;\n        salt = newSalt;\n    }\n};\"\"\"\n    addFunctionWrappers = 1\n    wholeFunctionDeclaration = None\n    functionDeclaration = \"public static native \"\n    returnIntDeclaration = \"int \"\n    returnVoidDeclaration = \"void \"\n    paramsPrefix = \"(\"\n    paramsPostfix = \") throws CryptException;\"\n    paramWhiteSpace = \"\\t\\t\\t\\t\\t\\t\"\n    paramVoidPtrTemplate = \"java.nio.ByteBuffer %(name)s,\\n\"\n    addFunctionAlternate = 1\n    paramVoidPtrAlternate = (\"java.nio.ByteBuffer\", \"byte[]\")\n    paramCharPtrTemplate = \"String %(name)s,\\n\"\n    paramIntTemplate = \"int %(name)s,\\n\"\n    paramIntTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    #wrapperLengthTemplate = \"%s.capacity(), \"\n    #wrapperStringLengthTemplate = \"%s.length(), \"\n    wrapperLengthTemplate = \"%(1)s == null ? 0 : %(1)s.capacity(), \"\n    wrapperStringLengthTemplate = \"%(1)s == null ? 0 : %(1)s.getBytes().length, \"\n    wrapperStringReplace = (\"java.nio.ByteBuffer\", \"String\")\n    wrapperStringTemplate = '%(1)s == null ? null : %(1)s.getBytes()'\n    #ENUM IDIOM\n    #paramEnumTypeTemplate = \"%(type)s %(name)s,\\n\"\n    #ENUMs as ints\n    paramEnumTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    commentPrefix = \"//\"\n    classPrefix = \"package cryptlib;\\n\\nimport java.nio.*;\\n\\npublic class crypt\\n{\\n\"\n    classPostfix = \"\\n};\"\n    sFuncs = None\n    sInts = None\nelif language == \"python\":\n    typedefEnumTemplate = \"\"\n    #typedefEnumElementTemplate = \"%(name)-NPADs = %(value)-VPADs\"\n    typedefEnumElementTemplate = \"\"\"\\\n\n    v = Py_BuildValue(\"i\", CRYPT_%(name)s);\n    PyDict_SetItemString(moduleDict, \"CRYPT_%(name)s\", v);\n    Py_DECREF(v);\"\"\"\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" /* %(comment)s */\"\n    simpleEnumElementTemplate = typedefEnumElementTemplate\n    simpleEnumElementTemplateComment = typedefEnumElementTemplateComment\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = typedefEnumElementTemplate\n    defineTemplateComment = typedefEnumElementTemplateComment\n    exceptionPrefix = \"\"\n    exceptionPostfix = \"\"\n    exceptionTemplate = \"\"\"\\\n    else if (status == CRYPT_%(name)s)\n        o = Py_BuildValue(\"(is)\", CRYPT_%(name)s, \"%(comment)s\");\n\"\"\"\n    addFunctionWrappers = 0\n    wholeFunctionDeclaration = \"\"\"\\\nstatic PyObject* python_crypt%s(PyObject* self, PyObject* args)\n{\n}\n\"\"\"\n    moduleFunctionEntry = \"\\t{ \\\"crypt%s\\\", python_crypt%s, METH_VARARGS }, \"\n    pyBeforeExceptions = r\"\"\"\n#include <Python.h>\n#include \"../cryptlib.h\"\n\n\nstatic PyObject* cryptHandleClass;\nstatic PyObject* cryptQueryInfoClass;\nstatic PyObject* cryptObjectInfoClass;\nstatic PyObject *CryptException;\n\nstatic int getPointerWrite(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n        return 0;\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerRead(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n    {\n        PyErr_Clear();\n        /*See if it's a string object*/\n        /*This returns the length excluding the NULL if it's a string,\n          which is what we want*/\n        if (PyObject_AsCharBuffer(objPtr, (const char **)bytesPtrPtr, &size) == -1)\n            return 0;\n    }\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerReadNoLength(PyObject* objPtr, unsigned char** bytesPtrPtr)\n{\n    int length;\n    return getPointerRead(objPtr, bytesPtrPtr, &length);\n}\n\nstatic int getPointerWriteCheckIndices(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    int checkLength = *lengthPtr;\n\n    if (getPointerWrite(objPtr, bytesPtrPtr, lengthPtr) == 0)\n        return 0;\n\n    //If sequence is non-NULL and too short...\n    if (*bytesPtrPtr && (*lengthPtr < checkLength))\n    {\n        PyErr_SetString(PyExc_IndexError, \"A sequence passed to cryptlib was too small\");\n        return 0;\n    }\n    return 1;\n}\n\nstatic int getPointerReadString(PyObject* objPtr, char** charPtrPtr)\n{\n    Py_ssize_t length = 0;\n    char* newPtr = NULL;\n\n    if (objPtr == Py_None)\n    {\n        *charPtrPtr = NULL;\n        return 1;\n    }\n\n    /*See if it's a string or a buffer object*/\n    if (PyObject_AsCharBuffer(objPtr, charPtrPtr, &length) == -1)\n    {\n        /*See if it's an array*/\n        PyErr_Clear();\n        if (PyObject_AsWriteBuffer(objPtr, charPtrPtr, &length) == -1)\n            return 0;\n    }\n    /*This code isn't necessary for a string, but it is for arrays and buffers,\n      so we do it always anyway, since the PyObject_AsCharBuffer apparently doesn't\n      guarantee us null-terminated data, and this way releasePointerString() doesn't\n      have to differentiate */\n    newPtr = malloc(length+1);\n    if (newPtr == NULL)\n    {\n        PyErr_NoMemory();\n        return 0;\n    }\n    memcpy(newPtr, *charPtrPtr, length);\n    newPtr[length] = 0;\n    *charPtrPtr = newPtr;\n    return 1;\n}\n\nstatic void releasePointer(PyObject* objPtr, unsigned char* bytesPtr)\n{\n}\n\nstatic void releasePointerString(PyObject* objPtr, char* charPtr)\n{\n    free(charPtr);\n}\n\nstatic PyObject* processStatus(int status)\n{\n    PyObject* o = NULL;\n\n    /* If an error has already occurred, ignore the status and just fall through */\n    if (PyErr_Occurred())\n        return(NULL);\n\n    if (status >= CRYPT_OK)\n        return(Py_BuildValue(\"\"));\n\"\"\"\n    pyBeforeFuncs = \"\"\"\\\n    PyErr_SetObject(CryptException, o);\n    Py_DECREF(o);\n    return(NULL);\n}\n\nstatic int processStatusBool(int status)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        return(1);\n    }\n}\n\nstatic PyObject* processStatusReturnInt(int status, int returnValue)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o = Py_BuildValue(\"i\", returnValue);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptHandle(int status, int returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(i)\", returnValue);\n        o = PyObject_CallObject(cryptHandleClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptQueryInfo(int status, CRYPT_QUERY_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(siiii)\", returnValue.algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n        o = PyObject_CallObject(cryptQueryInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptObjectInfo(int status, CRYPT_OBJECT_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(iiiis#)\", returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, returnValue.salt, returnValue.saltSize);\n        o = PyObject_CallObject(cryptObjectInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\"\"\"\n    pyBeforeModuleFunctions = \"\"\"\n\nstatic PyMethodDef module_functions[] =\n{\n\"\"\"\n    pyBeforeInts = r\"\"\"    {0, 0}\n};\n\n#if PY_MAJOR_VERSION >= 3\nstatic struct PyModuleDef moduledef = {\n        PyModuleDef_HEAD_INIT,\n        \"cryptlib_py\",\n        NULL,\n        -1,\n        module_functions,\n        NULL,\n        NULL,\n        NULL,\n        NULL\n};\n#endif\n\nPyMODINIT_FUNC\n#if PY_MAJOR_VERSION >= 3\nPyInit_cryptlib_py(void)\n#else\ninitcryptlib_py(void)\n#endif\n\n{\n    PyObject* module;\n    #if PY_MAJOR_VERSION >= 3\n    module = PyModule_Create(&moduledef);\n    if (module == NULL){\n        return NULL;\n    }\n    #else\n    module = Py_InitModule(\"cryptlib_py\", module_functions);\n    #endif\n    \n    \n    PyObject* moduleDict;\n\n    PyObject* v = NULL;\n    PyObject *globalsDict;\n\n    moduleDict = PyModule_GetDict(module);\n\n    CryptException = PyErr_NewException(\"cryptlib_py.CryptException\", NULL, NULL);\n    PyDict_SetItemString(moduleDict, \"CryptException\", CryptException);\n\n    globalsDict = PyEval_GetGlobals();\n    PyRun_String(\n\"from array import *\\n\\\nimport types\\n\\\nclass CryptHandle:\\n\\\n    def __init__(self, value):\\n\\\n        self.__dict__['value'] = value\\n\\\n    def __int__(self):\\n\\\n        return self.value\\n\\\n    def __str__(self):\\n\\\n        return str(self.value)\\n\\\n    def __repr__(self):\\n\\\n        return str(self.value)\\n\\\n    def __getattr__(self, name):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        try:\\n\\\n            return cryptGetAttribute(self, nameVal)\\n\\\n        except CryptException:\\n\\\n            length = cryptGetAttributeString(self, nameVal, None)\\n\\\n            buf = array('c', '0' * length)\\n\\\n            length = cryptGetAttributeString(self, nameVal, buf)\\n\\\n            return ''.join(buf[:length])\\n\\\n    def __setattr__(self, name, value):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        if isinstance(value, types.IntType) or isinstance(value, CryptHandle):\\n\\\n            cryptSetAttribute(self, nameVal, value)\\n\\\n        else:\\n\\\n            cryptSetAttributeString(self, nameVal, value)\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n\n    PyRun_String(\n\"class CRYPT_QUERY_INFO:\\n\\\n    def __init__(self, algoName, blockSize, minKeySize, keySize, maxKeySize):\\n\\\n        self.algoName = algoName\\n\\\n        self.blockSize = blockSize\\n\\\n        self.minKeySize = minKeySize\\n\\\n        self.keySize = keySize\\n\\\n        self.maxKeySize = maxKeySize\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    PyRun_String(\n\"class CRYPT_OBJECT_INFO:\\n\\\n    def __init__(self, objectType, cryptAlgo, cryptMode, hashAlgo, salt):\\n\\\n        self.objectType = objectType\\n\\\n        self.cryptAlgo = cryptAlgo\\n\\\n        self.cryptMode = cryptMode\\n\\\n        self.hashAlgo = hashAlgo\\n\\\n        self.salt = salt\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    cryptHandleClass = PyMapping_GetItemString(moduleDict, \"CryptHandle\");\n    cryptQueryInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_QUERY_INFO\");\n    cryptObjectInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_OBJECT_INFO\");\n\n    Py_DECREF(globalsDict);\n\n\"\"\"\n    pyAfterInts = \"\"\"\n#if PY_MAJOR_VERSION >= 3\n    return module;\n#endif\n}\"\"\"\n\n    paramCharPtrTemplate = \"%(name)s, # string\\n\"\n    paramIntTemplate = \"%(name)s, # integer\\n\"\n    paramIntTypeTemplate = \"%(name)s, # %(type)s\\n\"\n    paramEnumTypeTemplate = \"%(name)s, # %(type)s\\n\"\n    commentPrefix = \"# \"  #pad to 2-characters for formatting consistency\n    classPrefix = \"class crypt:\\n\"\n    classPostfix= \"\"\n    outFile = os.path.join(outDir, \"cryptlib.py\")\n    sFuncs = \"\\n\"\n    sInts = \"\\n\"\n    sModFuncs = \"\"\n    setupPy = r\"\"\"#!/usr/bin/env python\n\nfrom distutils.core import setup, Extension\nimport sys\n\nif sys.platform == \"win32\":\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['../binaries'],\n                    libraries=['cl32'])\nelse:\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['..'],\n                    libraries=['cl'])\n\nsetup(name=\"cryptlib_py\", ext_modules=[ext])\n\"\"\"\n\nelif language == \"net\":\n    typedefEnumTemplate = \"// %(typedefName)s\"\n    typedefEnumElementTemplate = \"public const int %(name)-NPADs = %(value)-VPADs;\"\n\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" // %(comment)s\"\n    simpleEnumElementTemplate = \"public const int %(name)-NPADs = %(value)-VPADs;\"\n    simpleEnumElementTemplateComment = simpleEnumElementTemplate + \" // %(comment)s\"\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = simpleEnumElementTemplate\n    defineTemplateComment = simpleEnumElementTemplateComment\n    exceptionPrefix = \"\"\"\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_QUERY_INFO\n{\n    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String algoName;\n    public int blockSize;\n    public int minKeySize;\n    public int keySize;\n    public int maxKeySize;\n\n    public CRYPT_QUERY_INFO(){}\n\n    public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)\n    {\n        algoName = newAlgoName;\n        blockSize = newBlockSize;\n        minKeySize = newMinKeySize;\n        keySize = newKeySize;\n        maxKeySize = newMaxKeySize;\n    }\n}\n\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_OBJECT_INFO\n{\n    public int objectType;\n    public int cryptAlgo;\n    public int cryptMode;\n    public int hashAlgo;\n    [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]public byte[] salt;\n    public int saltSize;\n\n    public CRYPT_OBJECT_INFO()\n    {\n        salt = new byte[64];\n        saltSize = 64;\n    }\n\n    public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)\n    {\n        objectType = newObjectType;\n        cryptAlgo = newCryptAlgo;\n        cryptMode = newCryptMode;\n        hashAlgo = newHashAlgo;\n    }\n}\n\npublic class CryptException : ApplicationException\n{\n    public int Status { get { return (int)Data[\"Status\"]; } }\n\n    public int ExtraInfo { get { return (int)Data[\"ExtraInfo\"]; } }\n\n    public CryptException(int status)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n    }\n\n    public CryptException(int status, int extra)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n        Data.Add(\"ExtraInfo\", extra);\n    }\n\n    private static string convertMessage(int status)\n    {\n        String prefix = Convert.ToString(status) + \": \";\n        switch (status)\n        {\n\"\"\"\n    exceptionPostfix = \"\"\"\\\n            default: return prefix + \"Unknown Exception ?!?!\";\n        }\n    }\n}\"\"\"\n    exceptionTemplate = \"\"\"\\\n\t\tcase crypt.%(name)s: return prefix + \"%(comment)s\";\n\"\"\"\n    addFunctionWrappers = 1\n    wholeFunctionDeclaration = None\n    functionDeclaration = \"public static \"\n    returnIntDeclaration = \"int \"\n    returnVoidDeclaration = \"void \"\n    paramsPrefix = \"(\"\n    paramsPostfix = \");\"\n    paramWhiteSpace = \"\\t\\t\\t\\t\\t\\t\"\n    paramVoidPtrTemplate = \"byte[] %(name)s,\\n\"\n    addFunctionAlternate = 0\n    paramCharPtrTemplate = \"String %(name)s,\\n\"\n    paramIntTemplate = \"int %(name)s,\\n\"\n    paramIntTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    wrapperLengthTemplate = \"%(1)s == null ? 0 : %(1)s.Length, \"\n    wrapperStringLengthTemplate = \"%(1)s == null ? 0 : new UTF8Encoding().GetByteCount(%(1)s), \"\n    wrapperStringReplace = (\"byte[]\", \"String\")\n    wrapperStringTemplate = \"%(1)s == null ? null : new UTF8Encoding().GetBytes(%(1)s)\"\n    #ENUM IDIOM\n    #paramEnumTypeTemplate = \"%(type)s %(name)s,\\n\"\n    #ENUMs as ints\n    paramEnumTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    commentPrefix = \"//\"\n    classPrefix = \"\"\"using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace cryptlib\n{\n\npublic class crypt\n{\n    \"\"\"\n    classPostfix = \"\"\"\n    /* Helper Functions */\n\n    private static void processStatus(int status)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status);\n    }\n\n\n    private static void processStatus(int status, int extraInfo)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status, extraInfo);\n    }\n\n    private static void checkIndices(byte[] array, int sequenceOffset, int sequenceLength)\n    {\n        if (array == null)\n        {\n            if (sequenceOffset == 0)\n                return;\n            else\n                throw new IndexOutOfRangeException();\n        }\n\n        int arrayLength = array.Length;\n\n        if (sequenceOffset < 0 ||\n            sequenceOffset >= arrayLength ||\n            sequenceOffset + sequenceLength > arrayLength)\n            throw new IndexOutOfRangeException();\n    }\n\n    private static void getPointer(byte[] buffer, int bufferOffset, ref GCHandle bufferHandle, ref IntPtr bufferPtr)\n    {\n        if (buffer == null)\n            return;\n        bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);\n        bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset);\n    }\n\n    private static void releasePointer(GCHandle bufferHandle)\n    {\n        if (bufferHandle.IsAllocated)\n            bufferHandle.Free();\n    }\n}\n\"\"\"\n    sFuncs = None\n    sInts = None\n\n\n\ns = open(inFile).read()\ninFileTabSize = 4\n\n#Global variables\n#These accumulate information about the types in the input file\n#----------------------------------------------------------------\nnameSpace = {}  #Accumulate enum'd values here and use them to eval() the RHS of new ones\nenumTypes = []  #Accumulate typedef'd enum types here\nintTypes = []   #Accumulate typedef'd int types here\nstructTypes = []#Accumulate typedef'd struct types here\nrawTypes = [\"char\", \"int\", \"void\"]\nfunctionNames = [] #Accumulate function names here\nrawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)\nnewParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)\nnewReturnStructsDict = {}  #Accumulate function name -> ParamStruct of return parameter (of new java/python code)\nnewDiscardedStructsDict = {} #Accumulate function name -> ParamStruct of discarded parameter\nlengthIndicesDict = {} #Accumulate function name -> indices in newParamStructs of lengths (used for python)\noffsetIndicesDict= {} #Accumulate function name -> indices in newParamStructs of offsets (used for python)\nerrors = {}     #Dictionary mapping return values to exception objects\n\nprint \"Parsing input file and generating %s files...\" % language\n\n#Removing enclosing include guard\n#---------------------------------\ns = re.search(r\"#ifndef _CRYPTLIB_DEFINED\\n(.*)\\n#endif\", s, re.DOTALL).group(1)\n\n#Ignore anything before \"#define C_INOUT...\"\n#--------------------------------------------\ns = s[re.search(r\"#define C_INOUT.*?\\n\", s, re.DOTALL).end() : ]\n\n#Remove all conditionals\n#------------------------\nwhile 1:\n    endifMatch = re.search(r\"#endif.*?\\n\", s, re.DOTALL)\n    if endifMatch == None:\n        break\n    ifdefIndex = s.rfind(\"#if\", 0, endifMatch.start())\n    s = s[ : ifdefIndex] + s[endifMatch.end() : ]\ns = re.sub(r'\\n\\s*/\\*.*\\*/\\s*\\n', lambda match: '' if match.group(0).find('CRYPT_') >= 0 else match.group(0), s)\n\n#Delete lines used for extended function and function-parameter checking\n#like C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\n#--------------------------------------------\nfunctionParamterPattern = re.compile(r\"((C_CHECK_RETVAL|C_NONNULL_ARG\\s*\\(\\s*\\([ \\t0-9,]+\\s*\\)\\s*\\))\\s+(\\\\\\n)?)\", re.DOTALL)\nwhile 1:\n\tdeleteExtended = functionParamterPattern.search(s)\n\tif deleteExtended == None:\n\t\tbreak\n\ts = s[ : deleteExtended.start(1) ] + s[ deleteExtended.end(1) : ]\n\n\n#Replace typedef enums\n#----------------------\ntypedefEnumPattern = re.compile(r\"typedef[ \\t]+enum[ \\t]+{([^}]*)}\\s*(\\w*);\", re.DOTALL)   # typedef enum { %1 } %2;\n\n#Find the next typedef enum\ntypedefEnumMatch = typedefEnumPattern.search(s)\nwhile typedefEnumMatch:\n\n    #Extract its contents and type name\n    enumContents, typedefName = typedefEnumMatch.groups()\n    enumTypes.append(typedefName)\n\n    #Parse its contents\n    enumTuples = parseEnumContents(enumContents, nameSpace, \"typedef\")\n\n    #Determine the length to pad names to\n    namePad = str( max( [len(e[0]) for e in enumTuples] ) )\n    valuePad = str( max( [len(e[1]) for e in enumTuples] ) )\n\n    #Construct its output equivalent from language-specific string templates\n    newTypedefEnum = typedefEnumTemplate % vars()\n    for enumTuple in enumTuples:\n        name, value, comment = enumTuple\n        if not comment:\n            paddedTemplate = typedefEnumElementTemplate.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        else:\n            paddedTemplate = typedefEnumElementTemplateComment.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        if newTypedefEnum:\n            newTypedefEnum += \"\\n\"  #Don't always add this or we'll get extraneous newlines in python\n        newTypedefEnum += newEnum\n\n    #print \"Output Equivalent of Typedef Enum====\\n\", newTypedefEnum\n    #raw_input()\n\n    if sInts:\n        sInts += newTypedefEnum + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : typedefEnumMatch.start()] + newTypedefEnum + s[typedefEnumMatch.end() : ]\n\n    #Get next typedef\n    typedefEnumMatch = typedefEnumPattern.search(s, typedefEnumMatch.start() + len(newTypedefEnum))\n#print \"ENUMTYPES:\\n\",enumTypes\n\n#Replace simple enums\n#---------------------\n#This works on the theory that we've already replaced all typedef enums with\n#something that doesn't use the word \"enum\", so any remaining occurrences of\n#enum will belong to simple enums.\n\nsimpleEnumPattern = re.compile(r\"enum[ \\t]+{([^}]*)};\", re.DOTALL)            # enum { %1 };\n\n#Find the next simple enum\nsimpleEnumMatch = simpleEnumPattern.search(s)\nwhile simpleEnumMatch:\n\n    #Extract its contents\n    enumContents = simpleEnumMatch.group(1)\n\n    #Parse its contents\n    enumTuples = parseEnumContents(enumContents, nameSpace, \"simple\")\n\n    #Determine the length to pad names to\n    namePad = str( max( [len(e[0]) for e in enumTuples] ) )\n    valuePad = str( max( [len(e[1]) for e in enumTuples] ) )\n\n    #Construct its output equivalent from language-specific string templates\n    newSimpleEnum = \"\"\n    for enumTuple in enumTuples:\n        name, value, comment = enumTuple\n        if not comment:\n            paddedTemplate = simpleEnumElementTemplate.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        else:\n            paddedTemplate = simpleEnumElementTemplateComment.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        if newSimpleEnum:\n            newSimpleEnum += \"\\n\"   #Don't always add this or we'll get extraneous newlines in python\n        newSimpleEnum += newEnum\n\n    #print \"Output Equivalent of Simple Enum====\\n\", newSimpleEnum\n    #raw_input()\n\n    if sInts:\n        sInts += newSimpleEnum + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : simpleEnumMatch.start()] + newSimpleEnum + s[simpleEnumMatch.end() : ]\n\n    #Get next typedef\n    simpleEnumMatch = simpleEnumPattern.search(s, simpleEnumMatch.start() + len(newSimpleEnum))\n\n\n#Replace #define'd constants\n#----------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+(\\w+)[ \\t]+([-\\w]+)[ \\t]*(/\\*.*\\*/*)?\")    # #define %1 %2 [/*%3*/]\n\nexceptionString = exceptionPrefix\n\n#Find the next #define\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n\n    #Parse its contents\n    name, value, comment = defineMatch.groups()\n    if not name.startswith(\"CRYPT_\"):\n        raise \"name doesn't start with CRYPT_\"+name\n    name = name.replace(\"CRYPT_\", \"\")\n\n    #Construct its output equivalent from language-specific string templates\n    if not comment:\n        paddedTemplate = defineTemplate.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine =  paddedTemplate % vars()\n    else:\n        comment = comment[2:-2].strip()\n        paddedTemplate = defineTemplateComment.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine = paddedTemplate % vars()\n\n    #print \"define: \" + newDefine\n    #raw_input()\n\n    if sInts:\n        sInts += newDefine + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n\n    #Append to exception string if error\n    if name.startswith(\"ERROR_\") or name.startswith(\"ENVELOPE_RESOURCE\"):\n        exceptionString += exceptionTemplate % vars()\n\n    #Get next #define\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\nexceptionString += exceptionPostfix\n\n#Replace #define'd constants with parenthesis\n#--------------------------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+(\\w+)[ \\t]+\\([ \\t]*([-0-9]+)[ \\)]*\\)[ \\t]*(/\\*.*\\*/*)?\")    # #define %1 ( %2 ) [/*%3*/]\n\nexceptionString = exceptionPrefix\n\n#Find the next #define\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n\n    #Parse its contents\n    name, value, comment = defineMatch.groups()\n    if not name.startswith(\"CRYPT_\"):\n        raise \"name doesn't start with CRYPT_\"+name\n    name = name.replace(\"CRYPT_\", \"\")\n\n    #Construct its output equivalent from language-specific string templates\n    if not comment:\n        paddedTemplate = defineTemplate.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine =  paddedTemplate % vars()\n    else:\n        comment = comment[2:-2].strip()\n        paddedTemplate = defineTemplateComment.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine = paddedTemplate % vars()\n\n    #print \"define: \" + newDefine\n    #raw_input()\n\n    if sInts:\n        sInts += newDefine + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n\n    #Append to exception string if error\n    if name.startswith(\"ERROR_\") or name.startswith(\"ENVELOPE_RESOURCE\"):\n        exceptionString += exceptionTemplate % vars()\n\n    #Get next #define\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\nexceptionString += exceptionPostfix\n\n#Comment out #define'd macros\n#-----------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+[^(]+\\([^\\)]*\\)([^\\n]*\\\\\\n)*[^\\n]*\")\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n    #print \"defined macros:\", defineMatch.group()\n    #raw_input()\n    define = defineMatch.group()\n    newDefine = commentPrefix + \"CRYPTLIBCONVERTER - NOT SUPPORTED:\\n\" + define\n    newDefine = newDefine.replace(\"\\n\", \"\\n\"+commentPrefix)\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\n#Comment out typedef integer types\n#----------------------------------\ntypedefIntPattern = re.compile(r\"typedef[ \\t]+int[ \\t]+([^ \\t]*)[ \\t]*;[ \\t]*\\n\")\ntypedefIntMatch = typedefIntPattern.search(s)\nwhile typedefIntMatch:\n    typedefInt = typedefIntMatch.group()\n    typedefIntName = typedefIntMatch.group(1)\n    intTypes.append(typedefIntName)\n    #print \"typedef int:\", typedefInt\n    #raw_input()\n    newTypedefInt = commentPrefix + \"CRYPTLIBCONVERTER - NOT NEEDED: \" + typedefInt\n    s = s[ : typedefIntMatch.start()] + newTypedefInt + s[typedefIntMatch.end() : ]\n    typedefIntMatch = typedefIntPattern.search(s, typedefIntMatch.start() + len(newTypedefInt))\n#print \"INTTYPES:\\n\",intTypes\n\n#Comment out typedef structs\n#----------------------------\ntypedefStructPattern = re.compile(r\"typedef[ \\t]+struct[ \\t]\\{[^}]*}[ \\t]*([^;]+);\")\ntypedefStructMatch = typedefStructPattern.search(s)\nwhile typedefStructMatch:\n    typedefStruct = typedefStructMatch.group()\n    typedefStructName = typedefStructMatch.group(1)\n    structTypes.append(typedefStructName)\n    #print \"typedef struct:\", typedefStructName\n    #raw_input()\n    newTypedefStruct = commentPrefix + \"CRYPTLIBCONVERTER - NOT SUPPORTED:\\n\" + typedefStruct\n    newTypedefStruct = newTypedefStruct.replace(\"\\n\", \"\\n\"+commentPrefix)\n    s = s[ : typedefStructMatch.start()] + newTypedefStruct + s[typedefStructMatch.end() : ]\n    typedefStructMatch = typedefStructPattern.search(s, typedefStructMatch.start() + len(newTypedefStruct))\n#print \"STRUCTTYPES:\\n\",structTypes\n#raw_input()\n\n#Translate functions\n#--------------------\nfunctionPattern = re.compile(r\"C_RET[ \\t]+([^ \\t]+)[ \\t]*\\(([^\\)]*)\\);\", re.DOTALL)\nfunctionMatch = functionPattern.search(s)\nwhile functionMatch:\n    function = functionMatch.group()\n    functionName, functionParams = functionMatch.groups()\n    if not functionName.startswith(\"crypt\"):\n        raise \"name doesn't start with crypt\"+functionName\n    functionName = functionName[len(\"crypt\") : ]\n    functionNames.append(functionName)\n    #print \"function:\", functionName, functionParams\n    #raw_input()\n\n    #Parse its parameters\n    paramStructs = parseFunctionParams(functionParams)\n\n    #Add raw list of ParamStructs to dictionary\n    #This will be used later, when generating the .c glue code\n    rawParamStructsDict[functionName] = paramStructs\n\n    # Since java and python don't have pass-by-reference, what we do is migrate the\n    # output int parameter in certain functions into the return value.  If the function\n    # creates or returns values such as integers or a (void*, int*) pair, we record\n    # the indexes of the parameters to migrate.  We do this in functions like:\n    # cryptCreate*()            # return handle of new object\n    # cryptGetAttribute()       # return integer value of attribute\n    # cryptGetAttributeString() # convert (void*, int*) to python string or java byte array\n    # cryptExportKey()          # convert (void*, int*) \"\n    # cryptCreateSignature()    # convert (void*, int*)\n    # cryptKeysetOpen()         # return handle\n    # cryptGetPublicKey()       # return handle\n    # cryptGetPrivateKey()      # return handle\n    # cryptGetCertExtension()   # convert (void*, int) but DISCARD criticalFlag (the int* before)!\n    # cryptImportCert()         # return handle\n    # cryptExportCert()         # convert (void*, int)\n    # cryptCAGetItem()          # return handle\n    # cryptCACertManagement()   # return handle\n    # cryptPushData()           # return integer (# of bytes copied)\n    # cryptPopData()            # convert (void*, int*) even though they're not adjacent\n    discardIntIndex = -1\n    returnIntIndex = -1\n    returnVoidPtrIndex = -1\n    discardInLengthIndex1 = -1   # To discard input lengths, since python don't need these\n    discardInLengthIndex2 = -1\n\n    #Scan through looking for a void pointer preceded by \"keyIDtype\"\n    #Convert it into a char*\n    index = 1\n    for p in paramStructs[1:]:\n        p2 = paramStructs[index-1]\n        if p.isPtr and p.type==\"void\" and p2.type==\"CRYPT_KEYID_TYPE\":\n            p.type = \"char\"\n        index += 1\n\n    #Scan through looking for output int pointers (or structs)?!\n    #If there's two, we will migrate the second occurrence to the return value\n    #and discard the first so as to handle cryptGetCertExtension()\n    index = 0\n    for p in paramStructs:\n        if p.isOut and p.isPtr and (p.category==\"intType\" or p.type==\"int\" or p.category==\"structType\"):\n            if returnIntIndex != -1:\n                if discardIntIndex != -1:\n                    raise \"Found two returned ints to discard?!\"\n                discardIntIndex = returnIntIndex\n            returnIntIndex = index\n        index += 1\n\n    #Record the migrated return value's ParamStruct\n    if returnIntIndex != -1:\n        newReturnStructsDict[functionName] = paramStructs[returnIntIndex]\n\n    #Return the discarded value's ParamStruct\n    if discardIntIndex != -1:\n        newDiscardedStructsDict[functionName] = paramStructs[discardIntIndex]\n\n    #Copy the parsed parameters and remove those we're going to migrate or discard\n    newParamStructs = [paramStructs[count]\n                       for count in range(len(paramStructs))\n                       if count not in (discardIntIndex, returnIntIndex)]\n\n    #Indices of input offsets and lengths\n    offsetIndices = []\n    lengthIndices = []\n\n    #Scan through looking for void pointer, add an int offset\n    index = 0\n    while 1:\n        if index >= len(newParamStructs):\n            break\n        p = newParamStructs[index]\n        if p.isPtr and p.type==\"void\":\n            newp = ParamStruct()\n            newp.type = \"int\"\n            newp.isPtr = 0\n            newp.isOut = 0\n            newp.category = \"rawType\"\n            newp.name = p.name+\"Offset\"\n            newParamStructs = newParamStructs[:index+1] + [newp] + newParamStructs[index+1:]\n            offsetIndices.append(index+1)\n            if not p.isOut and len(newParamStructs)> index+2 and newParamStructs[index+2].type == \"int\":\n                lengthIndices.append(index+2)\n        index += 1\n\n    #Add processed list of ParamStructs to dictionary\n    #This will be used later, when generating the .c glue code\n    newParamStructsDict[functionName] = newParamStructs\n    lengthIndicesDict[functionName] = lengthIndices\n    offsetIndicesDict[functionName] = offsetIndices\n\n    #Used for Python\n    if wholeFunctionDeclaration:\n        newFunction = wholeFunctionDeclaration % functionName\n        if sFuncs:\n            sFuncs += newFunction + \"\\n\"\n        else: assert(0)\n        sModFuncs += (moduleFunctionEntry % (functionName, functionName)) + \"\\n\"\n    else: #Java\n\n        #Construct new function declaration from language-specific templates\n        newFunction = functionDeclaration\n        if returnIntIndex != -1:\n            if newReturnStructsDict.get(functionName).category == \"structType\":\n                newFunction += newReturnStructsDict.get(functionName).type + \" \"\n            else:\n                newFunction += returnIntDeclaration\n        else:\n            newFunction += returnVoidDeclaration\n        newFunction += functionName + paramsPrefix\n        if len(newParamStructs):\n            newFunction += \"\\n\" + paramWhiteSpace\n        if offsetIndices or lengthIndices:\n            newFunctionWrapper = newFunction\n            newFunctionWrapperArgs = \"\"\n        else:\n            newFunctionWrapper = None\n        #At this point I'm just getting lazy.  Basically, we automatically generate\n        #String wrappers for function that take void* input parameters.  Encrypt and\n        #Decrypt take void* in/out parameters.  We should be smart enough to detect\n        #these and not generate wrappers for them, but instead, since we don't otherwise\n        #differentiate between C_IN and C_INOUT, we just hardcodedly exclude these\n        #from having String wrappers\n        if offsetIndices and lengthIndices and functionName not in (\"Encrypt\", \"Decrypt\"):\n            newFunctionStringWrapper = newFunction\n            newFunctionStringWrapperArgs = \"\"\n        else:\n            newFunctionStringWrapper = None\n            newFunctionStringWrapperArgs = \"\"\n        index = 0\n        for p in newParamStructs:\n            if p.category == \"rawType\" and p.type == \"void\" and p.isPtr:\n                template = paramVoidPtrTemplate\n                previousBufferName = p.name\n            elif p.category == \"rawType\" and p.type == \"char\" and p.isPtr:\n                template = paramCharPtrTemplate\n            elif p.category == \"rawType\" and p.type == \"int\" and not p.isPtr:\n                template = paramIntTemplate\n            elif p.category == \"intType\" and not p.isPtr:\n                template = paramIntTypeTemplate\n            elif p.category == \"enumType\" and not p.isPtr:\n                template = paramEnumTypeTemplate\n            #elif p.category == \"structType\"\n            else:\n                raise \"Unrecognized parameter type! \" + str(p)\n\n            #Strip out commas from the last param template, kind of a hack..\n            if index == len(newParamStructs)-1:\n                template = template[:].replace(\",\", \"\")\n\n            #Update the main function with this new param\n            newFunction += template % vars(p)\n            newFunction += paramWhiteSpace\n\n            #Update the wrapper function with this new param\n            #If this is not a special param...\n            if addFunctionWrappers and newFunctionWrapper and \\\n                index not in offsetIndices and index not in lengthIndices:\n                #Determine if this is the last param in the wrapper function\n                anyMoreParams = [e for e in range(index+1, len(newParamStructs))\n                                 if e not in offsetIndices and e not in lengthIndices]\n\n                #Update the wrapper function's param list\n                if not anyMoreParams:\n                    template = template[:].replace(\",\", \"\")\n                newFunctionWrapper += template % vars(p)\n                newFunctionWrapper += paramWhiteSpace\n\n                #Update the wrapper function's args that it uses to call the main function\n                newFunctionWrapperArgs += p.name\n                newFunctionWrapperArgs += \", \"\n\n                #Do the same things for the string wrapper\n                if newFunctionStringWrapper:\n                    newFunctionStringWrapper += template % vars(p)\n                    newFunctionStringWrapper += paramWhiteSpace\n                    if p.type==\"void\" and p.isPtr and not p.isOut:\n                        newFunctionStringWrapperArgs += wrapperStringTemplate % {\"1\":p.name};\n                    else:\n                        newFunctionStringWrapperArgs += p.name\n                    newFunctionStringWrapperArgs += \", \"\n            else:\n                #If this is a special param (an offset or length)...\n                if index in offsetIndices:\n                    newFunctionWrapperArgs += \"0, \"\n                    newFunctionStringWrapperArgs += \"0, \"\n                elif index in lengthIndices:\n                    newFunctionWrapperArgs += wrapperLengthTemplate % {\"1\":previousBufferName}\n                    newFunctionStringWrapperArgs += wrapperStringLengthTemplate % {\"1\":previousBufferName}\n            index += 1\n\n        #Add final postfix of ); to the main and wrapper param lists\n        newFunction += paramsPostfix\n        if newFunctionWrapper:\n            newFunctionWrapper += paramsPostfix\n        if newFunctionStringWrapper:\n            newFunctionStringWrapper += paramsPostfix\n\n        #If this function takes a void* parameter, and we want to convert this\n        #into two different versions, duplicate and modify the version here\n        if addFunctionAlternate:\n            if newFunction.find(paramVoidPtrAlternate[0]) != -1:\n                newFunction += \"\\n\" + newFunction.replace(*paramVoidPtrAlternate)\n\n        #If we've prepared a wrapper function to eliminate need for offset[, length]:\n        if addFunctionWrappers and newFunctionWrapper:\n            newFunctionWrapper = newFunctionWrapper.replace(\"native \", \"\")\n            newFunctionWrapper = newFunctionWrapper[:-1] + \" { return %s(%s); }\" % (functionName, newFunctionWrapperArgs[:-2])\n            if returnIntIndex == -1:\n                newFunctionWrapper = newFunctionWrapper.replace(\"return \", \"\")\n            #Duplicate and modify the wrapper function\n            if addFunctionAlternate:\n                newFunctionWrapper2 = newFunctionWrapper.replace(*paramVoidPtrAlternate)\n                newFunctionWrapper2 = newFunctionWrapper2.replace(\"capacity()\", \"length\")\n                newFunctionWrapper += \"\\n\" + newFunctionWrapper2\n            newFunction += \"\\n\" + newFunctionWrapper\n        if addFunctionWrappers and newFunctionStringWrapper:\n            newFunctionStringWrapper = newFunctionStringWrapper.replace(\"native \", \"\")\n            newFunctionStringWrapper = newFunctionStringWrapper[:-1] + \" { return %s(%s); }\" % (functionName, newFunctionStringWrapperArgs[:-2])\n            newFunctionStringWrapper = newFunctionStringWrapper.replace(*wrapperStringReplace)\n            if returnIntIndex == -1:\n                newFunctionStringWrapper = newFunctionStringWrapper.replace(\"return \", \"\")\n            newFunction += \"\\n\" + newFunctionStringWrapper\n\n        #Add a special-case string accessor for GetAttributeString() to Java and .NET\n        if functionName == \"GetAttributeString\" and language == \"java\":\n            newFunction += \"\"\"\npublic static String GetAttributeString(\n                    int cryptHandle, // CRYPT_HANDLE\n                    int attributeType // CRYPT_ATTRIBUTE_TYPE\n                    ) throws CryptException\n                    {\n                        int length = GetAttributeString(cryptHandle, attributeType, (byte[])null);\n                        byte[] bytes = new byte[length];\n                        length = GetAttributeString(cryptHandle, attributeType, bytes);\n                        return new String(bytes, 0, length);\n                    }\n\"\"\"\n        elif functionName == \"GetAttributeString\" and language == \"net\":\n            newFunction += \"\"\"\npublic static String GetAttributeString(\n                    int cryptHandle, // CRYPT_HANDLE\n                    int attributeType // CRYPT_ATTRIBUTE_TYPE\n                    )\n                    {\n                        int length = GetAttributeString(cryptHandle, attributeType, null);\n                        byte[] bytes = new byte[length];\n                        length = GetAttributeString(cryptHandle, attributeType, bytes);\n                        return new UTF8Encoding().GetString(bytes, 0, length);\n                    }\n\"\"\"\n        #Add special-case functions for cryptAddRandom(), since it allows NULL as a\n        #first parameter, and a pollType constant in place of the length\n        elif functionName == \"AddRandom\":\n            if language == \"java\":\n                newFunction += \"\"\"\npublic static native void AddRandom(\n                    int pollType\n                    ) throws CryptException;\n\"\"\"\n            elif language == \"net\":\n                newFunction += \"\"\"\npublic static void AddRandom(\n                    int pollType\n                    );\n\"\"\"\n\n        # Add an extra linebreak between functions\n        # This isn't in cryptlib.h, but it makes the converted files more readable\n        if s[functionMatch.end()+1] != \"\\n\":\n            newFunction += \"\\n\"\n\n    s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n    functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n#Translate comments\n#-------------------\nif language != \"java\" and language != \"net\":\n    while 1:\n        match = re.search(r\"/\\*(.*?)\\*/\", s, re.DOTALL)\n        if match == None:\n            break\n        #print match.group()\n        #raw_input()\n        commentStrings = (commentPrefix + match.group(1) + \"  \").split(\"\\n\")\n        newComment = commentStrings[0]\n        for commentString in commentStrings[1:]:\n            if commentString.startswith(\"\\t\"):\n                newComment += \"\\n\" + commentPrefix + (\" \" * (inFileTabSize-2)) + commentString[1:]\n            elif commentString.startswith(\"  \"):\n                newComment += \"\\n\" + commentPrefix + commentString[1:]\n            else:\n                newComment += \"\\n\" + commentPrefix + commentString\n            #print \"building up:\\n\", newComment\n            #raw_input()\n        idx = commentString.find(\"\\n\")\n        s = s[ : match.start()] + newComment + s[match.end() : ]\n\n#Indent each line by one tab\n#---------------------------\ns = s.replace(\"\\n\", \"\\n\\t\")\n\n#Write out file(s)\n#Then generate the .h/.c files necessary for language integration\n#At this point it's easier to just hardcode constants and have\n#separate python and java codepaths\n#---------------\nif language==\"java\":\n\n    #Add enclosing class syntax\n    #---------------------------\n    s = classPrefix + s + classPostfix\n\n    os.chdir(outDir)\n    if not os.path.exists(\"cryptlib\"):\n        os.mkdir(\"./cryptlib\")\n    os.chdir(\"./cryptlib\")\n\n    print \"Writing java files...\"\n    f = open(\"crypt.java\", \"w\")\n    f.write(s)\n    f.close()\n    f = open(\"CryptException.java\", \"w\")\n    f.write(exceptionString)\n    f.close()\n    f = open(\"CRYPT_QUERY_INFO.java\", \"w\")\n    f.write(cryptQueryInfoString)\n    f.close()\n    f = open(\"CRYPT_OBJECT_INFO.java\", \"w\")\n    f.write(cryptObjectInfoString)\n    f.close()\n\n\n    print \"Compiling java files...\"\n    print os.popen4(\"javac -classpath .. crypt.java\")[1].read()                    #Compile java file\n    print os.popen4(\"javac -classpath .. CryptException.java\")[1].read()           #Compile java file\n    print os.popen4(\"javac -classpath .. CRYPT_QUERY_INFO.java\")[1].read()         #Compile java file\n    print os.popen4(\"javac -classpath .. CRYPT_OBJECT_INFO.java\")[1].read()        #Compile java file\n\n    os.chdir(\"..\")\n\n    print \"Generating jar file...\"\n    print os.popen4(\"jar cf cryptlib.jar cryptlib/crypt.class cryptlib/CryptException.class cryptlib/CRYPT_QUERY_INFO.class cryptlib/CRYPT_OBJECT_INFO.class cryptlib\")[1].read()\n\n    print \"Generating JNI header file...\"\n    print os.popen4(\"javah -classpath . -o cryptlib_jni.h -jni cryptlib.crypt\")[1].read()    #Generate C header\n\n    s = open(\"cryptlib_jni.h\").read()\n    os.remove(\"cryptlib_jni.h\")\n\n    print \"Generating JNI source file...\"\n\n    #Now we take cryptlib_jni.h and derive the .c file from it\n\n    #Strip off headers and footers\n    #startIndex = s.find(\"/*\\n * Class\")\n    #endIndex = s.find(\"#ifdef\", startIndex)\n    #s = s[startIndex : endIndex]\n\n    startIndex = s.find(\"#undef\")\n    endIndex = s.find(\"/*\\n * Class\", startIndex)\n    sold = s\n    s = s[startIndex : endIndex]\n\n    startIndex = endIndex\n    endIndex = sold.find(\"#ifdef\", startIndex)\n    s2 = sold[startIndex : endIndex]\n\n    #Add includes and helper functions\n    #Note that we assume \"cryptlib.h\" is one directory behind us\n    s = r\"\"\"\n#include \"../crypt.h\"\n\n#ifdef USE_JAVA\n\n#include <jni.h>\n#include <stdio.h>  //printf\n#include <stdlib.h> //malloc, free\n\n%s\n\n/* Helper Functions */\n\nint processStatus(JNIEnv *env, jint status)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jthrowable obj;\n\n    if (status >= cryptlib_crypt_OK)\n        return 1;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CryptException\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatus - no class?!\\n\");\n        return 0;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(I)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatus - no constructor?!\\n\");\n        return 0;\n    }\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, status);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatus - no object?!\\n\");\n        return 0;\n    }\n\n    if ((*env)->Throw(env, obj) < 0)\n    {\n        printf(\"java_jni.c:processStatus - failed to throw?!\\n\");\n        return 0;\n    }\n    return 0;\n}\n\njobject processStatusReturnCryptQueryInfo(JNIEnv *env, int status, CRYPT_QUERY_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jstring algoName;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_QUERY_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(Ljava/lang/String;IIII)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    algoName = (*env)->NewStringUTF(env, returnValue.algoName);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\njobject processStatusReturnCryptObjectInfo(JNIEnv *env, int status, CRYPT_OBJECT_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jbyteArray salt;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_OBJECT_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(IIII[B)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    salt = (*env)->NewByteArray(env, returnValue.saltSize);\n    (*env)->SetByteArrayRegion(env, salt, 0, returnValue.saltSize, returnValue.salt);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, salt);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\nint checkIndicesArray(JNIEnv *env, jbyteArray array, int sequenceOffset, int sequenceLength)\n{\n    jsize arrayLength;\n    jclass exClass;\n\n    if (array == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    arrayLength = (*env)->GetArrayLength(env, array);\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= arrayLength ||\n        sequenceOffset + sequenceLength > arrayLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerArray(JNIEnv* env, jbyteArray array, jbyte** bytesPtrPtr)\n{\n    jboolean isCopy;\n\n    if (array == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetByteArrayElements(env, array, &isCopy);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        printf(\"java_jni.c:getPointer - failed to get elements of array?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerArray(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    (*env)->ReleaseByteArrayElements(env, array, bytesPtr, 0);\n}\n\nint checkIndicesNIO(JNIEnv *env, jobject byteBuffer, int sequenceOffset, int sequenceLength)\n{\n    jlong byteBufferLength;\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer);\n    if (byteBufferLength == -1)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass,\n\"Either a non-direct ByteBuffer was passed or your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= byteBufferLength ||\n        sequenceOffset + sequenceLength > byteBufferLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerNIO(JNIEnv* env, jobject byteBuffer, jbyte** bytesPtrPtr)\n{\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetDirectBufferAddress(env, byteBuffer);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:getPointerNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"Your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:getPointerNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerNIO(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n}\n\nint getPointerString(JNIEnv* env, jstring str, jbyte** bytesPtrPtr)\n{\n   jboolean isCopy;\n   jsize strLength;\n   const jbyte* rawBytesPtr;\n   jclass exClass;\n#ifdef __WINCE__\n   int status;\n#endif // __WINCE__\n\n\n   if (str == NULL)\n   {\n       (*bytesPtrPtr) = NULL;\n       return 1;\n   }\n\n   rawBytesPtr = (*env)->GetStringUTFChars(env, str, &isCopy);\n\n   if (rawBytesPtr == NULL)\n   {\n       printf(\"java_jni.c:getPointerString - failed to get elements of String?!\\n\");\n       return 0;\n   }\n\n   strLength = (*env)->GetStringUTFLength(env, str);\n\n#ifdef __WINCE__\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength*2+2); // this is unicode, therefore \\0 is two bytes long\n#else\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength+1);\n#endif // __WINCE__\n\n   if (*bytesPtrPtr == NULL)\n   {\n       exClass = (*env)->FindClass(env, \"java/lang/OutOfMemoryError\");\n       if (exClass == 0)\n           printf(\"java_jni.c:getPointerString - no class?!\\n\");\n       else\n       if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n           printf(\"java_jni.c:getPointerString - failed to throw?!\\n\");\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n\n#ifdef __WINCE__\n   status = asciiToUnicode (*bytesPtrPtr, strLength*2+2, rawBytesPtr, strLength+1);\n   if (status == CRYPT_ERROR_BADDATA) {\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n#else\n   memcpy(*bytesPtrPtr, rawBytesPtr, strLength);\n   (*bytesPtrPtr)[strLength] = 0;\n#endif // __WINCE__\n\n   (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n\n   return 1;\n}\n\nvoid releasePointerString(JNIEnv* env, jstring str, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    free(bytesPtr);\n}\n\n%s\n\n#endif /* USE_JAVA */\n\"\"\" % (s, s2)\n\n    functionPattern = re.compile(r\"JNIEXPORT ([^ \\t]+) JNICALL Java_cryptlib_crypt_([^ \\t\\n]+)\\n[ \\t]*\\(([^\\)]*)\\);\")\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.groups()\n\n        #Extract the returnType, name, and prototype for this function\n        function = functionMatch.group()\n        functionReturnType, functionName, functionPrototype = functionMatch.groups()\n\n        #Handle special-case AddRandom(pollType) function\n        if functionName == \"AddRandom__I\":\n            p = ParamStruct()\n            p.type = \"int\"\n            p.isPtr = 0\n            p.isOut = 0\n            p.category = \"intType\"\n            p.name = \"NULL\"\n            p.rawIndex = 0\n            p2 = ParamStruct()\n            p2.type = \"int\"\n            p2.isPtr = 0\n            p2.isOut = 0\n            p2.category = \"intType\"\n            p2.name = \"pollType\"\n            p2.rawIndex = 1\n            rawParamStructs = [p,p2]\n            newParamStructs = [p2,p2]\n            voidTag = \"Array\"\n            functionName = functionName.split(\"__\")[0]\n            returnName = None\n            discardName = None\n        else:\n            #Strip JNI decoration off function name\n            #But record which variety of tagged helper functions to use\n            if functionName.find(\"__\") != -1:\n                if functionName.find(\"ByteBuffer\") != -1:\n                    voidTag = \"NIO\"\n                else:\n                    voidTag = \"Array\"\n                functionName = functionName.split(\"__\")[0]\n\n            #Look up the parameters we've previously determined for this function\n            rawParamStructs = rawParamStructsDict[functionName]\n            newParamStructs = newParamStructsDict[functionName]\n            if newReturnStructsDict.get(functionName):\n                returnName = newReturnStructsDict.get(functionName).name\n                returnType = newReturnStructsDict.get(functionName).type\n                returnCategory = newReturnStructsDict.get(functionName).category\n            else:\n                returnName = None\n\n            if newDiscardedStructsDict.get(functionName):\n                discardName = newDiscardedStructsDict.get(functionName).name\n            else:\n                discardName = None\n\n        #for p in newParamStructs: print \"     \"+str(p)\n\n        #Substitute parameter names into the function prototype\n        newFunctionParams = expandFunctionPrototype(functionPrototype, newParamStructs)\n        startIndex = functionMatch.start(3) - functionMatch.start()\n        endIndex = functionMatch.end(3) - functionMatch.start()\n        function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]\n\n        newFunctionBody = \"\\nint status = 0;\\n\"\n\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"&\"\n            if p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr + %sOffset, \" % (p.name, p.name)\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"intType\" or returnType==\"int\":\n                newFunctionBody += \"jint %s = 0;\\n\" % returnName\n            else:\n                newFunctionBody += returnType +\" %s;\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"jint %s = 0;\\n\" % discardName\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                newFunctionBody += \"jbyte* \" + n + \"Ptr = 0;\\n\"\n            newFunctionBody += \"\\n\"\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"if (!getPointerString(env, %(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr + %sOffset\" % (n,n), \"NULL\")\n                    newFunctionBody += \"if (!processStatus(env, crypt%s(%s)))\\n\\tgoto finish;\\n\" % (functionName, argumentsWithNull)\n                newFunctionBody += \"\\n\"\n            elif functionName.find(\"PopData\") != -1:\n                newFunctionBody += \"//CryptPopData is a special case that doesn't have the length querying call\\n\\n\"\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    newFunctionBody += \"if (!checkIndices%(voidTag)s(env, %(n)s, %(n)sOffset, %(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            for n in voidArrayNames:\n                newFunctionBody += \"if (!getPointer%(voidTag)s(env, %(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n\n        if newFunctionBody[-2] != \"\\n\":\n            newFunctionBody += \"\\n\"\n        newFunctionBody += \"status = crypt%s(%s);\\n\\n\" % (functionName, arguments)\n\n        if arrayNames:\n            newFunctionBody += \"finish:\\n\"\n        if arrayNames:\n            for n in voidArrayNames:\n                newFunctionBody += \"releasePointer%(voidTag)s(env, %(n)s, %(n)sPtr);\\n\" % vars()\n            for n in charArrayNames:\n                newFunctionBody += \"releasePointerString(env, %(n)s, %(n)sPtr);\\n\" % vars()\n\n        #newFunctionBody += \"processStatus(env, status);\\n\"\n\n        #if returnName:\n        #    newFunctionBody += \"return(%s);\\n\" % returnName\n        if returnName:\n            if returnCategory == \"intType\" or returnType == \"int\":\n                newFunctionBody += \"processStatus(env, status);\\n\"\n                newFunctionBody += \"return(%s);\\n\" % returnName\n            elif returnType == \"CRYPT_QUERY_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptQueryInfo(env, status, %s));\\n\" % returnName\n            elif returnType == \"CRYPT_OBJECT_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptObjectInfo(env, status, %s));\\n\" % returnName\n        else:\n            newFunctionBody += \"processStatus(env, status);\\n\"\n\n        newFunctionBody = newFunctionBody[:-1] #Strip off last \\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\");\n        newFunction = function[:-1]+\"\\n{\" + newFunctionBody + \"\\n}\"\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    f = open(\"java_jni.c\", \"w\")\n    f.write(s)\n    f.close()\n\n\n\nelif language == \"python\":\n    os.chdir(outDir)\n\n    #print sInts\n    #raw_input()\n    #print sFuncs\n    #raw_input()\n\n    moduleFunctions = \"\"\n    s =         pyBeforeExceptions + exceptionString + pyBeforeFuncs + sFuncs + \\\n                pyBeforeModuleFunctions + moduleFunctions + sModFuncs + \\\n                pyBeforeInts + sInts + \\\n                pyAfterInts\n\n    #print s\n    #raw_input()\n    functionPattern = re.compile(r\"static PyObject\\* python_crypt([^\\(]+)[^{]+{([^}]*)}\", re.DOTALL)\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.group()\n        #print functionMatch.groups()\n        #raw_input()\n\n        #Most of the code in this loop is copied-then-modified from the java code above, ugly..\n        voidTag = \"\"\n\n        #Extract the function name and body\n        functionName, functionBody = functionMatch.groups()\n\n        #Look up the parameters we've previously determined for this function\n        rawParamStructs = rawParamStructsDict[functionName]\n        newParamStructs = newParamStructsDict[functionName]\n        lengthIndices = lengthIndicesDict[functionName]\n        offsetIndices = offsetIndicesDict[functionName]\n        #print functionName, lengthIndices, offsetIndices\n        #raw_input()\n        if newReturnStructsDict.get(functionName):\n            returnName = newReturnStructsDict.get(functionName).name\n            returnType = newReturnStructsDict.get(functionName).type\n            returnCategory = newReturnStructsDict.get(functionName).category\n        else:\n            returnName = None\n        if newDiscardedStructsDict.get(functionName):\n            discardName = newDiscardedStructsDict.get(functionName).name\n        else:\n            discardName = None\n\n        newFunctionBody = \"\\nint status = 0;\\n\"\n\n        #Arguments to pass to the C cryptlib function\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"&\"\n            if p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr, \" % (p.name)\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"intType\" or returnType==\"int\":\n                newFunctionBody += \"int %s = 0;\\n\" % returnName\n            else:\n                newFunctionBody += returnType +\" %s;\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"int %s = 0;\\n\" % discardName\n        #Declare variables to parse args tuple into\n        index = 0\n        for p in newParamStructs:\n            if index not in offsetIndices:       #Python doesn't use the offsets\n                if p.isPtr:\n                    newFunctionBody += \"PyObject* %s = NULL;\\n\" % p.name\n                else:\n                    newFunctionBody += \"int %s = 0;\\n\" % p.name\n            index += 1\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                newFunctionBody += \"unsigned char* \" + n + \"Ptr = 0;\\n\"\n            newFunctionBody += \"\\n\"\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n\n        #Parse the input arguments from the python user\n        #Arguments to parse from the python args tuple\n        if newParamStructs:\n            parseFormatString = \"\"\n            parseArgsList = []\n            index = 0\n            for p in newParamStructs:\n                if index not in lengthIndices and index not in offsetIndices:\n                    if p.isPtr and p.type==\"char\":\n                        parseFormatString += \"O\"\n                        parseArgsList.append(\"&\" + p.name)\n                    elif p.isPtr and p.type==\"void\":\n                        parseFormatString += \"O\"\n                        parseArgsList.append(\"&\" + p.name)\n                    else:\n                        parseFormatString += \"i\"\n                        parseArgsList.append(\"&\" + p.name)\n\n                index += 1\n\n            if newFunctionBody[-2] != \"\\n\":\n                newFunctionBody += \"\\n\"\n\n\n            if functionName == \"AddRandom\":\n                newFunctionBody += \"\"\"\\\n//Special case to handle SLOWPOLL / FASTPOLL values\nif (PyArg_ParseTuple(args, \"i\", &randomDataLength))\n    return processStatus(cryptAddRandom(NULL, randomDataLength));\\n\\n\"\"\"\n\n            newFunctionBody += \"\"\"\\\nif (!PyArg_ParseTuple(args, \"%s\", %s))\n    return(NULL);\\n\\n\"\"\" % (parseFormatString, \", \".join(parseArgsList))\n            #for p in newParamStructs:\n            #    print p.name,\n\n        if arrayNames:\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"if (!getPointerReadString(%(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr\" % (n), \"NULL\")\n                    newFunctionBody += \"if (!processStatusBool(crypt%s(%s)))\\n\\tgoto finish;\\n\" % (functionName, argumentsWithNull)\n                newFunctionBody += \"\\n\"\n            elif functionName.find(\"PopData\") != -1:\n                newFunctionBody += \"//CryptPopData is a special case that doesn't have the length querying call\\n\\n\"\n\n            #Go through and get the pointers for translated void*\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    #Determine the name of its length parameter\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #QueryObject, CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    if n in outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                        newFunctionBody += \"if (!getPointerWriteCheckIndices%(voidTag)s(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                    else:\n                        if lengthName == \"1\": #Handle the #CheckSignature/ImportKey case\n                            newFunctionBody += \"if (!getPointerReadNoLength%(voidTag)s(%(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                        else:\n                            #If the pointer is C_IN and not C_INOUT\n                            #(we check against Encrypt/Decrypt directory for this latter check)\n                            #We only need it for reading, not writing\n                            if n not in outVoidArrayNames and functionName not in (\"Encrypt\", \"Decrypt\"):\n                                newFunctionBody += \"if (!getPointerRead(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                            else:\n                                newFunctionBody += \"if (!getPointerWrite(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n\n        if newFunctionBody[-2] != \"\\n\":\n            newFunctionBody += \"\\n\"\n        newFunctionBody += \"status = crypt%s(%s);\\n\\n\" % (functionName, arguments)\n\n        if arrayNames:\n            newFunctionBody += \"finish:\\n\"\n        if arrayNames:\n            for n in voidArrayNames:\n                newFunctionBody += \"releasePointer(%(n)s, %(n)sPtr);\\n\" % vars()\n            for n in charArrayNames:\n                newFunctionBody += \"releasePointerString(%(n)s, %(n)sPtr);\\n\" % vars()\n\n        if returnName:\n            if returnCategory == \"intType\":\n                newFunctionBody += \"return(processStatusReturnCryptHandle(status, %s));\" % returnName\n            elif returnType == \"CRYPT_QUERY_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptQueryInfo(status, %s));\" % returnName\n            elif returnType == \"CRYPT_OBJECT_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptObjectInfo(status, %s));\" % returnName\n            elif returnType == \"int\":\n                newFunctionBody += \"return(processStatusReturnInt(status, %s));\" % returnName\n        else:\n            newFunctionBody += \"return(processStatus(status));\"\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\")\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start(2)] + newFunctionBody + \"\\n\" + s[functionMatch.end(2) : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    f = open(\"python.c\", \"w\")\n    f.write(s)\n    f.close()\n\n\n    f = open(\"setup.py\", \"w\")\n    f.write(setupPy)\n    f.close()\n\nelif language == \"net\":\n    flagForAddRandomHack = 0\n\n    #functionPattern = re.compile(r\"public static ([^ \\t]+) ([^ \\t\\n]+)\\([ \\t\\n]*\\(([^\\)]*)\\) throws CryptException;\")\n    functionPattern = re.compile(r\"public static ([^ \\t]+) ([^ \\t\\n]+)\\([ \\t\\n]*([^\\)]*)\\);\")\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.groups()\n\n        #Extract the returnType, name, and prototype for this function\n        function = functionMatch.group()\n        functionReturnType, functionName, functionPrototype = functionMatch.groups()\n\n        #Handle special-case AddRandom(pollType) function\n        if functionName == \"AddRandom\":\n            flagForAddRandomHack += 1\n        if flagForAddRandomHack == 2:\n            p = ParamStruct()\n            p.type = \"int\"\n            p.isPtr = 0\n            p.isOut = 0\n            p.category = \"intType\"\n            p.name = \"IntPtr.Zero\"\n            p.rawIndex = 0\n            p2 = ParamStruct()\n            p2.type = \"int\"\n            p2.isPtr = 0\n            p2.isOut = 0\n            p2.category = \"intType\"\n            p2.name = \"pollType\"\n            p2.rawIndex = 1\n            rawParamStructs = [p,p2]\n            newParamStructs = [p2,p2]\n            voidTag = \"Array\"\n            functionName = functionName.split(\"__\")[0]\n            returnName = None\n            discardName = None\n            flagForAddRandomHack = None\n        else:\n            #Look up the parameters we've previously determined for this function\n            rawParamStructs = rawParamStructsDict[functionName]\n            newParamStructs = newParamStructsDict[functionName]\n            if newReturnStructsDict.get(functionName):\n                returnName = newReturnStructsDict.get(functionName).name\n                returnType = newReturnStructsDict.get(functionName).type\n                returnCategory = newReturnStructsDict.get(functionName).category\n            else:\n                returnName = None\n            if newDiscardedStructsDict.get(functionName):\n                discardName = newDiscardedStructsDict.get(functionName).name\n            else:\n                discardName = None\n\n        #for p in newParamStructs: print \"     \"+str(p)\n\n        #Substitute parameter names into the function prototype\n        newFunctionParams = functionPrototype #expandFunctionPrototype(functionPrototype, newParamStructs)\n        startIndex = functionMatch.start(3) - functionMatch.start()\n        endIndex = functionMatch.end(3) - functionMatch.start()\n        function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]\n\n        newFunctionBody = \"\\n\"\n\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"%sPtr, \" % p.name\n            elif p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr, \" % p.name\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"structType\":\n                newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(%s)));\\n\" % (returnName, returnType)\n                newFunctionBody += \"%s %s = new %s();\\n\" % (returnType, returnName, returnType)\n            else:\n                newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(4);\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(4);\\n\" % discardName\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                #newFunctionBody += \"jbyte* \" + n + \"Ptr = 0;\\n\"\n                newFunctionBody += \"GCHandle %sHandle = new GCHandle();\\nIntPtr %sPtr = IntPtr.Zero;\\n\" % (n,n)\n                if n in charArrayNames:\n                    newFunctionBody += \"byte[] %sArray = new UTF8Encoding().GetBytes(%s);\\n\" % (n,n)\n\n            newFunctionBody += \"try\\n{\\n\"\n\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"getPointer(%(n)sArray, 0, ref %(n)sHandle, ref %(n)sPtr);\\n\" % vars()\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr + %sOffset\" % (n,n), \"NULL\")\n                    newFunctionBody += \"processStatus(wrapped_%s(%s));\\n\" % (functionName, argumentsWithNull)\n                    newFunctionBody += \"int %s = Marshal.ReadInt32(%sPtr);\\n\" % (returnName, returnName)\n            elif functionName.find(\"PopData\") != -1 or functionName.find(\"PushData\") != -1:\n                newFunctionBody += \"int %s = 0;\\n\" % returnName\n\t\tnewFunctionBody += \"int status;\\n\"\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    newFunctionBody += \"checkIndices(%(n)s, %(n)sOffset, %(lengthName)s);\\n\" % vars()\n            for n in voidArrayNames:\n                newFunctionBody += \"getPointer(%(n)s, %(n)sOffset, ref %(n)sHandle, ref %(n)sPtr);\\n\" % vars()\n        elif returnName:\n            newFunctionBody += \"try\\n{\\n\"\n\n\tif functionName.find(\"PopData\") == -1 and functionName.find(\"PushData\") == -1:\n\t\tnewFunctionBody += \"processStatus(wrapped_%s(%s));\\n\" % (functionName, arguments)\n\telse:\n\t\tnewFunctionBody += \"status = wrapped_%s(%s);\\n\" % (functionName, arguments)\n\t\tnewFunctionBody += \"%s = Marshal.ReadInt32(%sPtr);\\n\" % (returnName, returnName)\n\t\tnewFunctionBody += \"processStatus(status, %s);\\n\" %returnName\n\n        #if newFunctionBody[-2] != \"\\n\":\n        #    newFunctionBody += \"\\n\"\n        if returnName:\n            if returnCategory == \"structType\":\n                newFunctionBody += \"Marshal.PtrToStructure(%sPtr, %s);\\n\" % (returnName, returnName)\n                newFunctionBody += \"return %s;\\n\" % returnName\n            else:\n\t\t\t\tif functionName.find(\"PopData\") == -1 and functionName.find(\"PushData\") == -1:\n\t\t\t\t\tnewFunctionBody += \"return Marshal.ReadInt32(%sPtr);\\n\" % returnName\n\t\t\t\telse:\n\t\t\t\t\tnewFunctionBody += \"return %s;\\n\" %returnName\n\n        if arrayNames or returnName:\n            newFunctionBody += \"}\\nfinally\\n{\\n\"\n            if returnName:\n                newFunctionBody += \"Marshal.FreeHGlobal(%sPtr);\\n\" % returnName\n            if arrayNames:\n                for n in voidArrayNames:\n                    newFunctionBody += \"releasePointer(%(n)sHandle);\\n\" % vars()\n                for n in charArrayNames:\n                    newFunctionBody += \"releasePointer(%(n)sHandle);\\n\" % vars()\n            newFunctionBody += \"}\\n\"\n\n        #Add tabs to lines inside brackets:\n        lines = newFunctionBody.split(\"\\n\")\n        brackets = 0\n        for count in range(len(lines)):\n            line = lines[count]\n            if line.startswith(\"}\"):\n                brackets -= 1\n            lines[count] = (\"\\t\" * brackets) + line\n            if line.startswith(\"{\"):\n                brackets += 1\n        newFunctionBody = \"\\n\".join(lines)\n\n        newFunctionBody = newFunctionBody[:-1] #Strip off last \\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\");\n        newFunction = function[:-1]+\"\\n{\" + newFunctionBody + \"\\n}\"\n        newFunction = newFunction.replace(\"\\n\", \"\\n\\t\");\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    #Add enclosing class syntax\n    #---------------------------\n    s = classPrefix + s\n\n    for functionName in functionNames:\n        rawParamStructs = rawParamStructsDict[functionName]\n        parameters = \"\"\n        for p in rawParamStructs:\n            if p.isPtr:\n                parameters += \"IntPtr %s, \" % p.name\n            else:\n                parameters += \"int %s, \" % p.name\n        parameters = parameters[:-2]\n\n        s += '\\t[DllImport(\"cl32.dll\", EntryPoint=\"crypt%s\")]\\n\\tprivate static extern int wrapped_%s(%s);\\n\\n' % (functionName, functionName, parameters)\n        functionNames = [] #Accumulate function names here\n        #rawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)\n        #newParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)\n\n\n\n    s += classPostfix + exceptionString + \"\\n\\n}\"\n\n    os.chdir(outDir)\n    print \"Writing .NET file...\"\n    f = open(\"cryptlib.cs\", \"w\")\n    f.write(s)\n    f.close()\n\n\n"
  },
  {
    "path": "deps/cl345/tools/cryptlibConverter.py3",
    "content": "#!/usr/bin/python3\n\n# ported to python3 by Ralf Senderek 5.10.2018\n\nimport sys\nimport os\nimport stat\nimport re\n\nprint (\"\\nUsing python3 to compile files for java, python2, python3 and net\\n\")\n\n#Helper Functions\n#==========================================================================\n\ndef parseEnumContents(enumContents, nameSpace, debugString):\n    enumPattern = re.compile(r\"(CRYPT_[\\w_]*)\\s*(=.*?)?(\\Z|,|(?=/))\", re.DOTALL)     # %1 [= %2][,]\n    commentPattern = re.compile(r\"\\s*/\\*(.*)\\*/\")                                    # /* %1 */\n    counter = 0     #Keep track of the implicit enum value\n    enumTuples = [] #Build a list of (key, val, comment) tuples, one for each enum value\n\n    #Find the next \"enum value\"\n    enumMatch = enumPattern.search(enumContents)\n    while enumMatch:\n\n        #Extract the key and RHS value\n        rawKey, rawVal = enumMatch.groups()[:-1]\n\n        key = rawKey.rstrip()\n        if not key.startswith(\"CRYPT_\"):\n            raise \"enum'd value doesn't start with CRYPT_ \"+key\n        key = key.replace(\"CRYPT_\", \"\")\n\n        #Evaluate the RHS (if it exists) to get the value\n        if rawVal:\n            rhs = rawVal[1:].strip().replace(\"CRYPT_\", \"\")\n            val = eval(rhs, nameSpace)\n        #Otherwise the value is the implicit counter\n        else:\n            val = counter\n\n        #Extract the comment\n        commentMatch = commentPattern.match(enumContents, enumMatch.end())\n        if commentMatch:\n            rawComment = commentMatch.group(1)\n            comment = rawComment.strip()\n        else:\n            comment = \"\"\n\n        #Collect all the parsed values into a tuple\n        enumTuple = (key, str(val), comment)\n\n        #if comment:\n        #    print debugString+ \":\" + \" Parsed Element %s = %s /* %s */\" % enumTuple\n        #else:\n        #    print debugString+ \":\" + \" Parsed Element %s = %s\" % enumTuple[:-1]\n        #raw_input()\n\n        nameSpace[key] = val    #Add new enum value into namespace\n        counter = val + 1       #Increment implicit enum value\n\n        #Accumulate the parsed (key, val, comment) tuples\n        enumTuples.append(enumTuple)\n\n        #Get next enum value\n        enumMatch = enumPattern.search(enumContents, enumMatch.end())\n\n    return enumTuples\n\n#Parses a string of function parameters into a list of ParamStruct\nclass ParamStruct:\n    def __init__(self):\n        self.type = \"\"\n        self.isPtr = 0\n        self.isOut = 0\n        self.category = \"\"\n        self.name = \"\"\n        self.rawIndex = 0 # The index of this param in the initial, raw cryptlib header\n    def __str__(self):\n        return str( (self.type, self.isPtr, self.category, self.name, self.rawIndex) )\n\ndef parseFunctionParams(functionParams):\n    paramStructs = []\n    functionParams = functionParams.replace(\"\\n\", \"\") #Make one big line\n    functionParamsList = [e.strip() for e in functionParams.split(\",\")] #Break into a list of params\n    index = 0\n    for e in functionParamsList:\n        pieces = e.split(\" \")   #Separate each param into component pieces, ie [\"C_IN\", \"CRYPT_ALGO_TYPE\", \"cryptAlgo\"]\n        p = ParamStruct()\n        if len(pieces)==1 and pieces[0]==\"void\":\n            continue\n        elif len(pieces)==3:\n            if pieces[0] == \"C_OUT\":\n                p.isOut = 1\n            if pieces[0] == \"C_OUT_OPT\":\n                p.isOut = 1\n            if pieces[1] == \"C_STR\":\n                p.type = \"char\"\n                p.name = pieces[2]\n                p.isPtr = 1\n            else:\n                p.type = pieces[1]\n                p.name = pieces[2]\n                p.isPtr = 0\n        elif len(pieces)==4:    #Ie [\"C_OUT\", \"CRYPT_CONTEXT\", \"C_PTR\", \"cryptContext\"]\n            if pieces[0] == \"C_OUT\":\n                p.isOut = 1\n            if pieces[0] == \"C_OUT_OPT\":\n                p.isOut = 1\n            p.type = pieces[1]\n            if pieces[2] == \"C_PTR\":\n                p.isPtr = 1\n            else:\n                raise \"Expecting C_PTR in parseFunctionParams\"\n            p.name = pieces[3]\n        else:\n            raise \"parsing error in parseFunctionParams\"\n        if p.type in enumTypes:\n            p.category = \"enumType\"\n        elif p.type in intTypes:\n            p.category = \"intType\"\n        elif p.type in structTypes:\n            p.category = \"structType\"\n        elif p.type in rawTypes:\n            p.category = \"rawType\"\n        else:\n            raise \"unknown type error is parseFunctionParams\"\n        p.rawIndex = index\n        index += 1\n        paramStructs.append(p)\n    #for p in paramStructs:\n    #    print p.__dict__\n    #raw_input()\n    return paramStructs\n\n#Takes a string containing a JNI function parameters prototype list, and a list of ParamStructs\n#And injects names into the string and returns it\ndef expandFunctionPrototype(functionPrototype, newParamStructs):\n    functionPrototype = functionPrototype.replace(\"\\n\", \"\") #Make one big line\n    paramPrototypesList = [e.strip() for e in functionPrototype.split(\",\")] #Break into a list of params\n    paramNamesList = [\"env\", \"cryptClass\"] + [e.name for e in newParamStructs]\n    newFunctionParams = \"\"\n    for (p1, p2) in zip(paramPrototypesList, paramNamesList):\n        newFunctionParams += p1 + \" \" + p2 + \", \"\n    newFunctionParams = newFunctionParams[:-2]\n    return newFunctionParams\n\n\n\n\n\n\n#Main\n#=========================================================================\n#Execution starts here...\n#=========================================================================\nif len(sys.argv) != 4:\n    print (\"cryptlibConverter.py <inFile> <outDir> <language>\")\n    sys.exit()\n\ninFile = sys.argv[1]\noutDir = sys.argv[2]\nlanguage = sys.argv[3]\n\nif not os.path.exists(outDir):\n    print (\"Making output directory...\")\n    os.mkdir(outDir)\n\nif not language in (\"java\", \"python\", \"net\"):\n    print (\"only java, python, and net are supported!\")\n    sys.exit()\n\nif language == \"java\":\n    #ENUM IDIOM\n    #typedefEnumTemplate = \"public static class %(typedefName)s\\n{public int getValue(){return m_value;}private %(typedefName)s(int value){m_value = value;}int m_value;}\"\n    #typedefEnumElementTemplate = \"public static final %(typedefName)s %(name)-NPADs = new %(typedefName)s(%(value)-VPADs);\"\n    #ENUMs as ints\n    typedefEnumTemplate = \"// %(typedefName)s\"\n    typedefEnumElementTemplate = \"public static final int %(name)-NPADs = %(value)-VPADs;\"\n\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" // %(comment)s\"\n    simpleEnumElementTemplate = \"public static final int %(name)-NPADs = %(value)-VPADs;\"\n    simpleEnumElementTemplateComment = simpleEnumElementTemplate + \" // %(comment)s\"\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = simpleEnumElementTemplate\n    defineTemplateComment = simpleEnumElementTemplateComment\n    exceptionPrefix = \"\"\"\npackage cryptlib;\n\npublic class CryptException extends Exception\n{\n    private int m_status;\n    private String m_message;\n    public CryptException(int status)\n    {\n        m_status = status;\n        String prefix = Integer.toString(status) + \": \";\n\n\"\"\"\n    exceptionPostfix = \"\"\"\\\n        m_message = prefix + \"Unknown Exception ?!?!\";\n    }\n\n    public int getStatus()\n    {\n        return m_status;\n    }\n\n    public String getMessage()\n    {\n        return m_message;\n    }\n};\"\"\"\n    exceptionTemplate = \"\"\"\\\n        if (m_status == crypt.%(name)s) {\n            m_message = prefix + \"%(comment)s\";\n            return; }\n\"\"\"\n    cryptQueryInfoString = \"\"\"\npackage cryptlib;\n\npublic class CRYPT_QUERY_INFO\n{\n    public String algoName;\n    public int blockSize;\n    public int minKeySize;\n    public int keySize;\n    public int maxKeySize;\n\n    public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)\n    {\n        algoName = newAlgoName;\n        blockSize = newBlockSize;\n        minKeySize = newMinKeySize;\n        keySize = newKeySize;\n        maxKeySize = newMaxKeySize;\n    }\n};\"\"\"\n    cryptObjectInfoString = \"\"\"\npackage cryptlib;\n\npublic class CRYPT_OBJECT_INFO\n{\n    public int objectType;\n    public int cryptAlgo;\n    public int cryptMode;\n    public int hashAlgo;\n    public byte[] salt;\n\n    public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)\n    {\n        objectType = newObjectType;\n        cryptAlgo = newCryptAlgo;\n        cryptMode = newCryptMode;\n        hashAlgo = newHashAlgo;\n        salt = newSalt;\n    }\n};\"\"\"\n    addFunctionWrappers = 1\n    wholeFunctionDeclaration = None\n    functionDeclaration = \"public static native \"\n    returnIntDeclaration = \"int \"\n    returnVoidDeclaration = \"void \"\n    paramsPrefix = \"(\"\n    paramsPostfix = \") throws CryptException;\"\n    paramWhiteSpace = \"\\t\\t\\t\\t\\t\\t\"\n    paramVoidPtrTemplate = \"java.nio.ByteBuffer %(name)s,\\n\"\n    addFunctionAlternate = 1\n    paramVoidPtrAlternate = (\"java.nio.ByteBuffer\", \"byte[]\")\n    paramCharPtrTemplate = \"String %(name)s,\\n\"\n    paramIntTemplate = \"int %(name)s,\\n\"\n    paramIntTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    #wrapperLengthTemplate = \"%s.capacity(), \"\n    #wrapperStringLengthTemplate = \"%s.length(), \"\n    wrapperLengthTemplate = \"%(1)s == null ? 0 : %(1)s.capacity(), \"\n    wrapperStringLengthTemplate = \"%(1)s == null ? 0 : %(1)s.getBytes().length, \"\n    wrapperStringReplace = (\"java.nio.ByteBuffer\", \"String\")\n    wrapperStringTemplate = '%(1)s == null ? null : %(1)s.getBytes()'\n    #ENUM IDIOM\n    #paramEnumTypeTemplate = \"%(type)s %(name)s,\\n\"\n    #ENUMs as ints\n    paramEnumTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    commentPrefix = \"//\"\n    classPrefix = \"package cryptlib;\\n\\nimport java.nio.*;\\n\\npublic class crypt\\n{\\n\"\n    classPostfix = \"\\n};\"\n    sFuncs = None\n    sInts = None\nelif language == \"python\":\n    typedefEnumTemplate = \"\"\n    #typedefEnumElementTemplate = \"%(name)-NPADs = %(value)-VPADs\"\n    typedefEnumElementTemplate = \"\"\"\\\n\n    v = Py_BuildValue(\"i\", CRYPT_%(name)s);\n    PyDict_SetItemString(moduleDict, \"CRYPT_%(name)s\", v);\n    Py_DECREF(v);\"\"\"\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" /* %(comment)s */\"\n    simpleEnumElementTemplate = typedefEnumElementTemplate\n    simpleEnumElementTemplateComment = typedefEnumElementTemplateComment\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = typedefEnumElementTemplate\n    defineTemplateComment = typedefEnumElementTemplateComment\n    exceptionPrefix = \"\"\n    exceptionPostfix = \"\"\n    exceptionTemplate = \"\"\"\\\n    else if (status == CRYPT_%(name)s)\n        o = Py_BuildValue(\"(is)\", CRYPT_%(name)s, \"%(comment)s\");\n\"\"\"\n    addFunctionWrappers = 0\n    wholeFunctionDeclaration = \"\"\"\\\nstatic PyObject* python_crypt%s(PyObject* self, PyObject* args)\n{\n}\n\"\"\"\n    moduleFunctionEntry = \"\\t{ \\\"crypt%s\\\", python_crypt%s, METH_VARARGS }, \"\n    pyBeforeExceptions = r\"\"\"\n#include <Python.h>\n#include \"../cryptlib.h\"\n\n\nstatic PyObject* cryptHandleClass;\nstatic PyObject* cryptQueryInfoClass;\nstatic PyObject* cryptObjectInfoClass;\nstatic PyObject *CryptException;\n\nstatic int getPointerWrite(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n        return 0;\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerRead(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    if (objPtr == Py_None)\n    {\n        *bytesPtrPtr = NULL;\n        *lengthPtr = 0;\n        return 1;\n    }\n\n    Py_ssize_t size = 0;\n\n    /*See if it's an array object*/\n    if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)\n    {\n        PyErr_Clear();\n        /*See if it's a string object*/\n        /*This returns the length excluding the NULL if it's a string,\n          which is what we want*/\n        if (PyObject_AsCharBuffer(objPtr, (const char **)bytesPtrPtr, &size) == -1)\n            return 0;\n    }\n    *lengthPtr = size;\n    return 1;\n}\n\nstatic int getPointerReadNoLength(PyObject* objPtr, unsigned char** bytesPtrPtr)\n{\n    int length;\n    return getPointerRead(objPtr, bytesPtrPtr, &length);\n}\n\nstatic int getPointerWriteCheckIndices(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)\n{\n    int checkLength = *lengthPtr;\n\n    if (getPointerWrite(objPtr, bytesPtrPtr, lengthPtr) == 0)\n        return 0;\n\n    //If sequence is non-NULL and too short...\n    if (*bytesPtrPtr && (*lengthPtr < checkLength))\n    {\n        PyErr_SetString(PyExc_IndexError, \"A sequence passed to cryptlib was too small\");\n        return 0;\n    }\n    return 1;\n}\n\nstatic int getPointerReadString(PyObject* objPtr, char** charPtrPtr)\n{\n    Py_ssize_t length = 0;\n    char* newPtr = NULL;\n\n    if (objPtr == Py_None)\n    {\n        *charPtrPtr = NULL;\n        return 1;\n    }\n\n    /*See if it's a string or a buffer object*/\n    if (PyObject_AsCharBuffer(objPtr, charPtrPtr, &length) == -1)\n    {\n        /*See if it's an array*/\n        PyErr_Clear();\n        if (PyObject_AsWriteBuffer(objPtr, charPtrPtr, &length) == -1)\n            return 0;\n    }\n    /*This code isn't necessary for a string, but it is for arrays and buffers,\n      so we do it always anyway, since the PyObject_AsCharBuffer apparently doesn't\n      guarantee us null-terminated data, and this way releasePointerString() doesn't\n      have to differentiate */\n    newPtr = malloc(length+1);\n    if (newPtr == NULL)\n    {\n        PyErr_NoMemory();\n        return 0;\n    }\n    memcpy(newPtr, *charPtrPtr, length);\n    newPtr[length] = 0;\n    *charPtrPtr = newPtr;\n    return 1;\n}\n\nstatic void releasePointer(PyObject* objPtr, unsigned char* bytesPtr)\n{\n}\n\nstatic void releasePointerString(PyObject* objPtr, char* charPtr)\n{\n    free(charPtr);\n}\n\nstatic PyObject* processStatus(int status)\n{\n    PyObject* o = NULL;\n\n    /* If an error has already occurred, ignore the status and just fall through */\n    if (PyErr_Occurred())\n        return(NULL);\n\n    if (status >= CRYPT_OK)\n        return(Py_BuildValue(\"\"));\n\"\"\"\n    pyBeforeFuncs = \"\"\"\\\n    PyErr_SetObject(CryptException, o);\n    Py_DECREF(o);\n    return(NULL);\n}\n\nstatic int processStatusBool(int status)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        return(1);\n    }\n}\n\nstatic PyObject* processStatusReturnInt(int status, int returnValue)\n{\n    PyObject* o = processStatus(status);\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o = Py_BuildValue(\"i\", returnValue);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptHandle(int status, int returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(i)\", returnValue);\n        o = PyObject_CallObject(cryptHandleClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptQueryInfo(int status, CRYPT_QUERY_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(siiii)\", returnValue.algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n        o = PyObject_CallObject(cryptQueryInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\nstatic PyObject* processStatusReturnCryptObjectInfo(int status, CRYPT_OBJECT_INFO returnValue)\n{\n    PyObject* o2;\n    PyObject* o = processStatus(status);\n\n    if (o == NULL)\n        return(0);\n    else\n    {\n        Py_DECREF(o);\n        o2  = Py_BuildValue(\"(iiiis#)\", returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, returnValue.salt, returnValue.saltSize);\n        o = PyObject_CallObject(cryptObjectInfoClass, o2);\n        Py_DECREF(o2);\n        return(o);\n    }\n}\n\"\"\"\n    pyBeforeModuleFunctions = \"\"\"\n\nstatic PyMethodDef module_functions[] =\n{\n\"\"\"\n    pyBeforeInts = r\"\"\"    {0, 0}\n};\n\n#if PY_MAJOR_VERSION >= 3\nstatic struct PyModuleDef moduledef = {\n        PyModuleDef_HEAD_INIT,\n        \"cryptlib_py\",\n        NULL,\n        -1,\n        module_functions,\n        NULL,\n        NULL,\n        NULL,\n        NULL\n};\n#endif\n\nPyMODINIT_FUNC\n#if PY_MAJOR_VERSION >= 3\nPyInit_cryptlib_py(void)\n#else\ninitcryptlib_py(void)\n#endif\n\n{\n    PyObject* module;\n    #if PY_MAJOR_VERSION >= 3\n    module = PyModule_Create(&moduledef);\n    if (module == NULL){\n        return NULL;\n    }\n    #else\n    module = Py_InitModule(\"cryptlib_py\", module_functions);\n    #endif\n    \n    \n    PyObject* moduleDict;\n\n    PyObject* v = NULL;\n    PyObject *globalsDict;\n\n    moduleDict = PyModule_GetDict(module);\n\n    CryptException = PyErr_NewException(\"cryptlib_py.CryptException\", NULL, NULL);\n    PyDict_SetItemString(moduleDict, \"CryptException\", CryptException);\n\n    globalsDict = PyEval_GetGlobals();\n    PyRun_String(\n\"from array import *\\n\\\nimport types\\n\\\nclass CryptHandle:\\n\\\n    def __init__(self, value):\\n\\\n        self.__dict__['value'] = value\\n\\\n    def __int__(self):\\n\\\n        return self.value\\n\\\n    def __str__(self):\\n\\\n        return str(self.value)\\n\\\n    def __repr__(self):\\n\\\n        return str(self.value)\\n\\\n    def __getattr__(self, name):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        try:\\n\\\n            return cryptGetAttribute(self, nameVal)\\n\\\n        except CryptException:\\n\\\n            length = cryptGetAttributeString(self, nameVal, None)\\n\\\n            buf = array('c', '0' * length)\\n\\\n            length = cryptGetAttributeString(self, nameVal, buf)\\n\\\n            return ''.join(buf[:length])\\n\\\n    def __setattr__(self, name, value):\\n\\\n        name = name.upper()\\n\\\n        if not name.startswith('CRYPT_'):\\n\\\n            name = 'CRYPT_' + name\\n\\\n        nameVal = globals()[name]\\n\\\n        if isinstance(value, types.IntType) or isinstance(value, CryptHandle):\\n\\\n            cryptSetAttribute(self, nameVal, value)\\n\\\n        else:\\n\\\n            cryptSetAttributeString(self, nameVal, value)\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n\n    PyRun_String(\n\"class CRYPT_QUERY_INFO:\\n\\\n    def __init__(self, algoName, blockSize, minKeySize, keySize, maxKeySize):\\n\\\n        self.algoName = algoName\\n\\\n        self.blockSize = blockSize\\n\\\n        self.minKeySize = minKeySize\\n\\\n        self.keySize = keySize\\n\\\n        self.maxKeySize = maxKeySize\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    PyRun_String(\n\"class CRYPT_OBJECT_INFO:\\n\\\n    def __init__(self, objectType, cryptAlgo, cryptMode, hashAlgo, salt):\\n\\\n        self.objectType = objectType\\n\\\n        self.cryptAlgo = cryptAlgo\\n\\\n        self.cryptMode = cryptMode\\n\\\n        self.hashAlgo = hashAlgo\\n\\\n        self.salt = salt\\n\",\n    Py_file_input, globalsDict, moduleDict);\n\n    cryptHandleClass = PyMapping_GetItemString(moduleDict, \"CryptHandle\");\n    cryptQueryInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_QUERY_INFO\");\n    cryptObjectInfoClass = PyMapping_GetItemString(moduleDict, \"CRYPT_OBJECT_INFO\");\n\n    Py_DECREF(globalsDict);\n\n\"\"\"\n    pyAfterInts = \"\"\"\n#if PY_MAJOR_VERSION >= 3\n    return module;\n#endif\n}\"\"\"\n\n    paramCharPtrTemplate = \"%(name)s, # string\\n\"\n    paramIntTemplate = \"%(name)s, # integer\\n\"\n    paramIntTypeTemplate = \"%(name)s, # %(type)s\\n\"\n    paramEnumTypeTemplate = \"%(name)s, # %(type)s\\n\"\n    commentPrefix = \"# \"  #pad to 2-characters for formatting consistency\n    classPrefix = \"class crypt:\\n\"\n    classPostfix= \"\"\n    outFile = os.path.join(outDir, \"cryptlib.py\")\n    sFuncs = \"\\n\"\n    sInts = \"\\n\"\n    sModFuncs = \"\"\n    setupPy = r\"\"\"#!/usr/bin/env python\n\nfrom distutils.core import setup, Extension\nimport sys\n\nif sys.platform == \"win32\":\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['../binaries'],\n                    libraries=['cl32'])\nelse:\n    ext = Extension(\"cryptlib_py\",\n                    sources=[\"python.c\"],\n                    library_dirs=['..'],\n                    libraries=['cl'])\n\nsetup(name=\"cryptlib_py\", ext_modules=[ext])\n\"\"\"\n\nelif language == \"net\":\n    typedefEnumTemplate = \"// %(typedefName)s\"\n    typedefEnumElementTemplate = \"public const int %(name)-NPADs = %(value)-VPADs;\"\n\n    typedefEnumElementTemplateComment = typedefEnumElementTemplate + \" // %(comment)s\"\n    simpleEnumElementTemplate = \"public const int %(name)-NPADs = %(value)-VPADs;\"\n    simpleEnumElementTemplateComment = simpleEnumElementTemplate + \" // %(comment)s\"\n    defineNPad = \"40\"\n    defineVPad = \"4\"\n    defineTemplate = simpleEnumElementTemplate\n    defineTemplateComment = simpleEnumElementTemplateComment\n    exceptionPrefix = \"\"\"\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_QUERY_INFO\n{\n    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String algoName;\n    public int blockSize;\n    public int minKeySize;\n    public int keySize;\n    public int maxKeySize;\n\n    public CRYPT_QUERY_INFO(){}\n\n    public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)\n    {\n        algoName = newAlgoName;\n        blockSize = newBlockSize;\n        minKeySize = newMinKeySize;\n        keySize = newKeySize;\n        maxKeySize = newMaxKeySize;\n    }\n}\n\n[StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]\npublic class CRYPT_OBJECT_INFO\n{\n    public int objectType;\n    public int cryptAlgo;\n    public int cryptMode;\n    public int hashAlgo;\n    [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]public byte[] salt;\n    public int saltSize;\n\n    public CRYPT_OBJECT_INFO()\n    {\n        salt = new byte[64];\n        saltSize = 64;\n    }\n\n    public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)\n    {\n        objectType = newObjectType;\n        cryptAlgo = newCryptAlgo;\n        cryptMode = newCryptMode;\n        hashAlgo = newHashAlgo;\n    }\n}\n\npublic class CryptException : ApplicationException\n{\n    public int Status { get { return (int)Data[\"Status\"]; } }\n\n    public int ExtraInfo { get { return (int)Data[\"ExtraInfo\"]; } }\n\n    public CryptException(int status)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n    }\n\n    public CryptException(int status, int extra)\n        : base(convertMessage(status))\n    {\n        Data.Add(\"Status\", status);\n        Data.Add(\"ExtraInfo\", extra);\n    }\n\n    private static string convertMessage(int status)\n    {\n        String prefix = Convert.ToString(status) + \": \";\n        switch (status)\n        {\n\"\"\"\n    exceptionPostfix = \"\"\"\\\n            default: return prefix + \"Unknown Exception ?!?!\";\n        }\n    }\n}\"\"\"\n    exceptionTemplate = \"\"\"\\\n\t\tcase crypt.%(name)s: return prefix + \"%(comment)s\";\n\"\"\"\n    addFunctionWrappers = 1\n    wholeFunctionDeclaration = None\n    functionDeclaration = \"public static \"\n    returnIntDeclaration = \"int \"\n    returnVoidDeclaration = \"void \"\n    paramsPrefix = \"(\"\n    paramsPostfix = \");\"\n    paramWhiteSpace = \"\\t\\t\\t\\t\\t\\t\"\n    paramVoidPtrTemplate = \"byte[] %(name)s,\\n\"\n    addFunctionAlternate = 0\n    paramCharPtrTemplate = \"String %(name)s,\\n\"\n    paramIntTemplate = \"int %(name)s,\\n\"\n    paramIntTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    wrapperLengthTemplate = \"%(1)s == null ? 0 : %(1)s.Length, \"\n    wrapperStringLengthTemplate = \"%(1)s == null ? 0 : new UTF8Encoding().GetByteCount(%(1)s), \"\n    wrapperStringReplace = (\"byte[]\", \"String\")\n    wrapperStringTemplate = \"%(1)s == null ? null : new UTF8Encoding().GetBytes(%(1)s)\"\n    #ENUM IDIOM\n    #paramEnumTypeTemplate = \"%(type)s %(name)s,\\n\"\n    #ENUMs as ints\n    paramEnumTypeTemplate = \"int %(name)s, // %(type)s\\n\"\n    commentPrefix = \"//\"\n    classPrefix = \"\"\"using System;\nusing System.Runtime.InteropServices;\nusing System.Text;\n\nnamespace cryptlib\n{\n\npublic class crypt\n{\n    \"\"\"\n    classPostfix = \"\"\"\n    /* Helper Functions */\n\n    private static void processStatus(int status)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status);\n    }\n\n\n    private static void processStatus(int status, int extraInfo)\n    {\n        if (status < crypt.OK)\n            throw new CryptException(status, extraInfo);\n    }\n\n    private static void checkIndices(byte[] array, int sequenceOffset, int sequenceLength)\n    {\n        if (array == null)\n        {\n            if (sequenceOffset == 0)\n                return;\n            else\n                throw new IndexOutOfRangeException();\n        }\n\n        int arrayLength = array.Length;\n\n        if (sequenceOffset < 0 ||\n            sequenceOffset >= arrayLength ||\n            sequenceOffset + sequenceLength > arrayLength)\n            throw new IndexOutOfRangeException();\n    }\n\n    private static void getPointer(byte[] buffer, int bufferOffset, ref GCHandle bufferHandle, ref IntPtr bufferPtr)\n    {\n        if (buffer == null)\n            return;\n        bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);\n        bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset);\n    }\n\n    private static void releasePointer(GCHandle bufferHandle)\n    {\n        if (bufferHandle.IsAllocated)\n            bufferHandle.Free();\n    }\n}\n\"\"\"\n    sFuncs = None\n    sInts = None\n\n\n\ns = open(inFile).read()\ninFileTabSize = 4\n\n#Global variables\n#These accumulate information about the types in the input file\n#----------------------------------------------------------------\nnameSpace = {}  #Accumulate enum'd values here and use them to eval() the RHS of new ones\nenumTypes = []  #Accumulate typedef'd enum types here\nintTypes = []   #Accumulate typedef'd int types here\nstructTypes = []#Accumulate typedef'd struct types here\nrawTypes = [\"char\", \"int\", \"void\"]\nfunctionNames = [] #Accumulate function names here\nrawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)\nnewParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)\nnewReturnStructsDict = {}  #Accumulate function name -> ParamStruct of return parameter (of new java/python code)\nnewDiscardedStructsDict = {} #Accumulate function name -> ParamStruct of discarded parameter\nlengthIndicesDict = {} #Accumulate function name -> indices in newParamStructs of lengths (used for python)\noffsetIndicesDict= {} #Accumulate function name -> indices in newParamStructs of offsets (used for python)\nerrors = {}     #Dictionary mapping return values to exception objects\n\nprint (\"Parsing input file and generating %s files...\" % language)\n\n#Removing enclosing include guard\n#---------------------------------\ns = re.search(r\"#ifndef _CRYPTLIB_DEFINED\\n(.*)\\n#endif\", s, re.DOTALL).group(1)\n\n#Ignore anything before \"#define C_INOUT...\"\n#--------------------------------------------\ns = s[re.search(r\"#define C_INOUT.*?\\n\", s, re.DOTALL).end() : ]\n\n#Remove all conditionals\n#------------------------\nwhile 1:\n    endifMatch = re.search(r\"#endif.*?\\n\", s, re.DOTALL)\n    if endifMatch == None:\n        break\n    ifdefIndex = s.rfind(\"#if\", 0, endifMatch.start())\n    s = s[ : ifdefIndex] + s[endifMatch.end() : ]\ns = re.sub(r'\\n\\s*/\\*.*\\*/\\s*\\n', lambda match: '' if match.group(0).find('CRYPT_') >= 0 else match.group(0), s)\n\n#Delete lines used for extended function and function-parameter checking\n#like C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \\\n#--------------------------------------------\nfunctionParamterPattern = re.compile(r\"((C_CHECK_RETVAL|C_NONNULL_ARG\\s*\\(\\s*\\([ \\t0-9,]+\\s*\\)\\s*\\))\\s+(\\\\\\n)?)\", re.DOTALL)\nwhile 1:\n\tdeleteExtended = functionParamterPattern.search(s)\n\tif deleteExtended == None:\n\t\tbreak\n\ts = s[ : deleteExtended.start(1) ] + s[ deleteExtended.end(1) : ]\n\n\n#Replace typedef enums\n#----------------------\ntypedefEnumPattern = re.compile(r\"typedef[ \\t]+enum[ \\t]+{([^}]*)}\\s*(\\w*);\", re.DOTALL)   # typedef enum { %1 } %2;\n\n#Find the next typedef enum\ntypedefEnumMatch = typedefEnumPattern.search(s)\nwhile typedefEnumMatch:\n\n    #Extract its contents and type name\n    enumContents, typedefName = typedefEnumMatch.groups()\n    enumTypes.append(typedefName)\n\n    #Parse its contents\n    enumTuples = parseEnumContents(enumContents, nameSpace, \"typedef\")\n\n    #Determine the length to pad names to\n    namePad = str( max( [len(e[0]) for e in enumTuples] ) )\n    valuePad = str( max( [len(e[1]) for e in enumTuples] ) )\n\n    #Construct its output equivalent from language-specific string templates\n    newTypedefEnum = typedefEnumTemplate % vars()\n    for enumTuple in enumTuples:\n        name, value, comment = enumTuple\n        if not comment:\n            paddedTemplate = typedefEnumElementTemplate.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        else:\n            paddedTemplate = typedefEnumElementTemplateComment.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        if newTypedefEnum:\n            newTypedefEnum += \"\\n\"  #Don't always add this or we'll get extraneous newlines in python\n        newTypedefEnum += newEnum\n\n    #print \"Output Equivalent of Typedef Enum====\\n\", newTypedefEnum\n    #raw_input()\n\n    if sInts:\n        sInts += newTypedefEnum + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : typedefEnumMatch.start()] + newTypedefEnum + s[typedefEnumMatch.end() : ]\n\n    #Get next typedef\n    typedefEnumMatch = typedefEnumPattern.search(s, typedefEnumMatch.start() + len(newTypedefEnum))\n#print \"ENUMTYPES:\\n\",enumTypes\n\n#Replace simple enums\n#---------------------\n#This works on the theory that we've already replaced all typedef enums with\n#something that doesn't use the word \"enum\", so any remaining occurrences of\n#enum will belong to simple enums.\n\nsimpleEnumPattern = re.compile(r\"enum[ \\t]+{([^}]*)};\", re.DOTALL)            # enum { %1 };\n\n#Find the next simple enum\nsimpleEnumMatch = simpleEnumPattern.search(s)\nwhile simpleEnumMatch:\n\n    #Extract its contents\n    enumContents = simpleEnumMatch.group(1)\n\n    #Parse its contents\n    enumTuples = parseEnumContents(enumContents, nameSpace, \"simple\")\n\n    #Determine the length to pad names to\n    namePad = str( max( [len(e[0]) for e in enumTuples] ) )\n    valuePad = str( max( [len(e[1]) for e in enumTuples] ) )\n\n    #Construct its output equivalent from language-specific string templates\n    newSimpleEnum = \"\"\n    for enumTuple in enumTuples:\n        name, value, comment = enumTuple\n        if not comment:\n            paddedTemplate = simpleEnumElementTemplate.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        else:\n            paddedTemplate = simpleEnumElementTemplateComment.replace(\"NPAD\", namePad).replace(\"VPAD\", valuePad)\n            newEnum = paddedTemplate % vars()\n        if newSimpleEnum:\n            newSimpleEnum += \"\\n\"   #Don't always add this or we'll get extraneous newlines in python\n        newSimpleEnum += newEnum\n\n    #print \"Output Equivalent of Simple Enum====\\n\", newSimpleEnum\n    #raw_input()\n\n    if sInts:\n        sInts += newSimpleEnum + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : simpleEnumMatch.start()] + newSimpleEnum + s[simpleEnumMatch.end() : ]\n\n    #Get next typedef\n    simpleEnumMatch = simpleEnumPattern.search(s, simpleEnumMatch.start() + len(newSimpleEnum))\n\n\n#Replace #define'd constants\n#----------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+(\\w+)[ \\t]+([-\\w]+)[ \\t]*(/\\*.*\\*/*)?\")    # #define %1 %2 [/*%3*/]\n\nexceptionString = exceptionPrefix\n\n#Find the next #define\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n\n    #Parse its contents\n    name, value, comment = defineMatch.groups()\n    if not name.startswith(\"CRYPT_\"):\n        raise \"name doesn't start with CRYPT_\"+name\n    name = name.replace(\"CRYPT_\", \"\")\n\n    #Construct its output equivalent from language-specific string templates\n    if not comment:\n        paddedTemplate = defineTemplate.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine =  paddedTemplate % vars()\n    else:\n        comment = comment[2:-2].strip()\n        paddedTemplate = defineTemplateComment.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine = paddedTemplate % vars()\n\n    #print \"define: \" + newDefine\n    #raw_input()\n\n    if sInts:\n        sInts += newDefine + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n\n    #Append to exception string if error\n    if name.startswith(\"ERROR_\") or name.startswith(\"ENVELOPE_RESOURCE\"):\n        exceptionString += exceptionTemplate % vars()\n\n    #Get next #define\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\nexceptionString += exceptionPostfix\n\n#Replace #define'd constants with parenthesis\n#--------------------------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+(\\w+)[ \\t]+\\([ \\t]*([-0-9]+)[ \\)]*\\)[ \\t]*(/\\*.*\\*/*)?\")    # #define %1 ( %2 ) [/*%3*/]\n\nexceptionString = exceptionPrefix\n\n#Find the next #define\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n\n    #Parse its contents\n    name, value, comment = defineMatch.groups()\n    if not name.startswith(\"CRYPT_\"):\n        raise \"name doesn't start with CRYPT_\"+name\n    name = name.replace(\"CRYPT_\", \"\")\n\n    #Construct its output equivalent from language-specific string templates\n    if not comment:\n        paddedTemplate = defineTemplate.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine =  paddedTemplate % vars()\n    else:\n        comment = comment[2:-2].strip()\n        paddedTemplate = defineTemplateComment.replace(\"NPAD\", defineNPad).replace(\"VPAD\", defineVPad)\n        newDefine = paddedTemplate % vars()\n\n    #print \"define: \" + newDefine\n    #raw_input()\n\n    if sInts:\n        sInts += newDefine + \"\\n\"\n\n    #Substitute the output equivalent for the input\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n\n    #Append to exception string if error\n    if name.startswith(\"ERROR_\") or name.startswith(\"ENVELOPE_RESOURCE\"):\n        exceptionString += exceptionTemplate % vars()\n\n    #Get next #define\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\nexceptionString += exceptionPostfix\n\n#Comment out #define'd macros\n#-----------------------------\ndefinePattern = re.compile(r\"#define[ \\t]+[^(]+\\([^\\)]*\\)([^\\n]*\\\\\\n)*[^\\n]*\")\ndefineMatch = definePattern.search(s)\nwhile defineMatch:\n    #print \"defined macros:\", defineMatch.group()\n    #raw_input()\n    define = defineMatch.group()\n    newDefine = commentPrefix + \"CRYPTLIBCONVERTER - NOT SUPPORTED:\\n\" + define\n    newDefine = newDefine.replace(\"\\n\", \"\\n\"+commentPrefix)\n    s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]\n    defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))\n\n#Comment out typedef integer types\n#----------------------------------\ntypedefIntPattern = re.compile(r\"typedef[ \\t]+int[ \\t]+([^ \\t]*)[ \\t]*;[ \\t]*\\n\")\ntypedefIntMatch = typedefIntPattern.search(s)\nwhile typedefIntMatch:\n    typedefInt = typedefIntMatch.group()\n    typedefIntName = typedefIntMatch.group(1)\n    intTypes.append(typedefIntName)\n    #print \"typedef int:\", typedefInt\n    #raw_input()\n    newTypedefInt = commentPrefix + \"CRYPTLIBCONVERTER - NOT NEEDED: \" + typedefInt\n    s = s[ : typedefIntMatch.start()] + newTypedefInt + s[typedefIntMatch.end() : ]\n    typedefIntMatch = typedefIntPattern.search(s, typedefIntMatch.start() + len(newTypedefInt))\n#print \"INTTYPES:\\n\",intTypes\n\n#Comment out typedef structs\n#----------------------------\ntypedefStructPattern = re.compile(r\"typedef[ \\t]+struct[ \\t]\\{[^}]*}[ \\t]*([^;]+);\")\ntypedefStructMatch = typedefStructPattern.search(s)\nwhile typedefStructMatch:\n    typedefStruct = typedefStructMatch.group()\n    typedefStructName = typedefStructMatch.group(1)\n    structTypes.append(typedefStructName)\n    #print \"typedef struct:\", typedefStructName\n    #raw_input()\n    newTypedefStruct = commentPrefix + \"CRYPTLIBCONVERTER - NOT SUPPORTED:\\n\" + typedefStruct\n    newTypedefStruct = newTypedefStruct.replace(\"\\n\", \"\\n\"+commentPrefix)\n    s = s[ : typedefStructMatch.start()] + newTypedefStruct + s[typedefStructMatch.end() : ]\n    typedefStructMatch = typedefStructPattern.search(s, typedefStructMatch.start() + len(newTypedefStruct))\n#print \"STRUCTTYPES:\\n\",structTypes\n#raw_input()\n\n#Translate functions\n#--------------------\nfunctionPattern = re.compile(r\"C_RET[ \\t]+([^ \\t]+)[ \\t]*\\(([^\\)]*)\\);\", re.DOTALL)\nfunctionMatch = functionPattern.search(s)\nwhile functionMatch:\n    function = functionMatch.group()\n    functionName, functionParams = functionMatch.groups()\n    if not functionName.startswith(\"crypt\"):\n        raise \"name doesn't start with crypt\"+functionName\n    functionName = functionName[len(\"crypt\") : ]\n    functionNames.append(functionName)\n    #print \"function:\", functionName, functionParams\n    #raw_input()\n\n    #Parse its parameters\n    paramStructs = parseFunctionParams(functionParams)\n\n    #Add raw list of ParamStructs to dictionary\n    #This will be used later, when generating the .c glue code\n    rawParamStructsDict[functionName] = paramStructs\n\n    # Since java and python don't have pass-by-reference, what we do is migrate the\n    # output int parameter in certain functions into the return value.  If the function\n    # creates or returns values such as integers or a (void*, int*) pair, we record\n    # the indexes of the parameters to migrate.  We do this in functions like:\n    # cryptCreate*()            # return handle of new object\n    # cryptGetAttribute()       # return integer value of attribute\n    # cryptGetAttributeString() # convert (void*, int*) to python string or java byte array\n    # cryptExportKey()          # convert (void*, int*) \"\n    # cryptCreateSignature()    # convert (void*, int*)\n    # cryptKeysetOpen()         # return handle\n    # cryptGetPublicKey()       # return handle\n    # cryptGetPrivateKey()      # return handle\n    # cryptGetCertExtension()   # convert (void*, int) but DISCARD criticalFlag (the int* before)!\n    # cryptImportCert()         # return handle\n    # cryptExportCert()         # convert (void*, int)\n    # cryptCAGetItem()          # return handle\n    # cryptCACertManagement()   # return handle\n    # cryptPushData()           # return integer (# of bytes copied)\n    # cryptPopData()            # convert (void*, int*) even though they're not adjacent\n    discardIntIndex = -1\n    returnIntIndex = -1\n    returnVoidPtrIndex = -1\n    discardInLengthIndex1 = -1   # To discard input lengths, since python don't need these\n    discardInLengthIndex2 = -1\n\n    #Scan through looking for a void pointer preceded by \"keyIDtype\"\n    #Convert it into a char*\n    index = 1\n    for p in paramStructs[1:]:\n        p2 = paramStructs[index-1]\n        if p.isPtr and p.type==\"void\" and p2.type==\"CRYPT_KEYID_TYPE\":\n            p.type = \"char\"\n        index += 1\n\n    #Scan through looking for output int pointers (or structs)?!\n    #If there's two, we will migrate the second occurrence to the return value\n    #and discard the first so as to handle cryptGetCertExtension()\n    index = 0\n    for p in paramStructs:\n        if p.isOut and p.isPtr and (p.category==\"intType\" or p.type==\"int\" or p.category==\"structType\"):\n            if returnIntIndex != -1:\n                if discardIntIndex != -1:\n                    raise \"Found two returned ints to discard?!\"\n                discardIntIndex = returnIntIndex\n            returnIntIndex = index\n        index += 1\n\n    #Record the migrated return value's ParamStruct\n    if returnIntIndex != -1:\n        newReturnStructsDict[functionName] = paramStructs[returnIntIndex]\n\n    #Return the discarded value's ParamStruct\n    if discardIntIndex != -1:\n        newDiscardedStructsDict[functionName] = paramStructs[discardIntIndex]\n\n    #Copy the parsed parameters and remove those we're going to migrate or discard\n    newParamStructs = [paramStructs[count]\n                       for count in range(len(paramStructs))\n                       if count not in (discardIntIndex, returnIntIndex)]\n\n    #Indices of input offsets and lengths\n    offsetIndices = []\n    lengthIndices = []\n\n    #Scan through looking for void pointer, add an int offset\n    index = 0\n    while 1:\n        if index >= len(newParamStructs):\n            break\n        p = newParamStructs[index]\n        if p.isPtr and p.type==\"void\":\n            newp = ParamStruct()\n            newp.type = \"int\"\n            newp.isPtr = 0\n            newp.isOut = 0\n            newp.category = \"rawType\"\n            newp.name = p.name+\"Offset\"\n            newParamStructs = newParamStructs[:index+1] + [newp] + newParamStructs[index+1:]\n            offsetIndices.append(index+1)\n            if not p.isOut and len(newParamStructs)> index+2 and newParamStructs[index+2].type == \"int\":\n                lengthIndices.append(index+2)\n        index += 1\n\n    #Add processed list of ParamStructs to dictionary\n    #This will be used later, when generating the .c glue code\n    newParamStructsDict[functionName] = newParamStructs\n    lengthIndicesDict[functionName] = lengthIndices\n    offsetIndicesDict[functionName] = offsetIndices\n\n    #Used for Python\n    if wholeFunctionDeclaration:\n        newFunction = wholeFunctionDeclaration % functionName\n        if sFuncs:\n            sFuncs += newFunction + \"\\n\"\n        else: assert(0)\n        sModFuncs += (moduleFunctionEntry % (functionName, functionName)) + \"\\n\"\n    else: #Java\n\n        #Construct new function declaration from language-specific templates\n        newFunction = functionDeclaration\n        if returnIntIndex != -1:\n            if newReturnStructsDict.get(functionName).category == \"structType\":\n                newFunction += newReturnStructsDict.get(functionName).type + \" \"\n            else:\n                newFunction += returnIntDeclaration\n        else:\n            newFunction += returnVoidDeclaration\n        newFunction += functionName + paramsPrefix\n        if len(newParamStructs):\n            newFunction += \"\\n\" + paramWhiteSpace\n        if offsetIndices or lengthIndices:\n            newFunctionWrapper = newFunction\n            newFunctionWrapperArgs = \"\"\n        else:\n            newFunctionWrapper = None\n        #At this point I'm just getting lazy.  Basically, we automatically generate\n        #String wrappers for function that take void* input parameters.  Encrypt and\n        #Decrypt take void* in/out parameters.  We should be smart enough to detect\n        #these and not generate wrappers for them, but instead, since we don't otherwise\n        #differentiate between C_IN and C_INOUT, we just hardcodedly exclude these\n        #from having String wrappers\n        if offsetIndices and lengthIndices and functionName not in (\"Encrypt\", \"Decrypt\"):\n            newFunctionStringWrapper = newFunction\n            newFunctionStringWrapperArgs = \"\"\n        else:\n            newFunctionStringWrapper = None\n            newFunctionStringWrapperArgs = \"\"\n        index = 0\n        for p in newParamStructs:\n            if p.category == \"rawType\" and p.type == \"void\" and p.isPtr:\n                template = paramVoidPtrTemplate\n                previousBufferName = p.name\n            elif p.category == \"rawType\" and p.type == \"char\" and p.isPtr:\n                template = paramCharPtrTemplate\n            elif p.category == \"rawType\" and p.type == \"int\" and not p.isPtr:\n                template = paramIntTemplate\n            elif p.category == \"intType\" and not p.isPtr:\n                template = paramIntTypeTemplate\n            elif p.category == \"enumType\" and not p.isPtr:\n                template = paramEnumTypeTemplate\n            #elif p.category == \"structType\"\n            else:\n                raise \"Unrecognized parameter type! \" + str(p)\n\n            #Strip out commas from the last param template, kind of a hack..\n            if index == len(newParamStructs)-1:\n                template = template[:].replace(\",\", \"\")\n\n            #Update the main function with this new param\n            newFunction += template % vars(p)\n            newFunction += paramWhiteSpace\n\n            #Update the wrapper function with this new param\n            #If this is not a special param...\n            if addFunctionWrappers and newFunctionWrapper and \\\n                index not in offsetIndices and index not in lengthIndices:\n                #Determine if this is the last param in the wrapper function\n                anyMoreParams = [e for e in range(index+1, len(newParamStructs))\n                                 if e not in offsetIndices and e not in lengthIndices]\n\n                #Update the wrapper function's param list\n                if not anyMoreParams:\n                    template = template[:].replace(\",\", \"\")\n                newFunctionWrapper += template % vars(p)\n                newFunctionWrapper += paramWhiteSpace\n\n                #Update the wrapper function's args that it uses to call the main function\n                newFunctionWrapperArgs += p.name\n                newFunctionWrapperArgs += \", \"\n\n                #Do the same things for the string wrapper\n                if newFunctionStringWrapper:\n                    newFunctionStringWrapper += template % vars(p)\n                    newFunctionStringWrapper += paramWhiteSpace\n                    if p.type==\"void\" and p.isPtr and not p.isOut:\n                        newFunctionStringWrapperArgs += wrapperStringTemplate % {\"1\":p.name};\n                    else:\n                        newFunctionStringWrapperArgs += p.name\n                    newFunctionStringWrapperArgs += \", \"\n            else:\n                #If this is a special param (an offset or length)...\n                if index in offsetIndices:\n                    newFunctionWrapperArgs += \"0, \"\n                    newFunctionStringWrapperArgs += \"0, \"\n                elif index in lengthIndices:\n                    newFunctionWrapperArgs += wrapperLengthTemplate % {\"1\":previousBufferName}\n                    newFunctionStringWrapperArgs += wrapperStringLengthTemplate % {\"1\":previousBufferName}\n            index += 1\n\n        #Add final postfix of ); to the main and wrapper param lists\n        newFunction += paramsPostfix\n        if newFunctionWrapper:\n            newFunctionWrapper += paramsPostfix\n        if newFunctionStringWrapper:\n            newFunctionStringWrapper += paramsPostfix\n\n        #If this function takes a void* parameter, and we want to convert this\n        #into two different versions, duplicate and modify the version here\n        if addFunctionAlternate:\n            if newFunction.find(paramVoidPtrAlternate[0]) != -1:\n                newFunction += \"\\n\" + newFunction.replace(*paramVoidPtrAlternate)\n\n        #If we've prepared a wrapper function to eliminate need for offset[, length]:\n        if addFunctionWrappers and newFunctionWrapper:\n            newFunctionWrapper = newFunctionWrapper.replace(\"native \", \"\")\n            newFunctionWrapper = newFunctionWrapper[:-1] + \" { return %s(%s); }\" % (functionName, newFunctionWrapperArgs[:-2])\n            if returnIntIndex == -1:\n                newFunctionWrapper = newFunctionWrapper.replace(\"return \", \"\")\n            #Duplicate and modify the wrapper function\n            if addFunctionAlternate:\n                newFunctionWrapper2 = newFunctionWrapper.replace(*paramVoidPtrAlternate)\n                newFunctionWrapper2 = newFunctionWrapper2.replace(\"capacity()\", \"length\")\n                newFunctionWrapper += \"\\n\" + newFunctionWrapper2\n            newFunction += \"\\n\" + newFunctionWrapper\n        if addFunctionWrappers and newFunctionStringWrapper:\n            newFunctionStringWrapper = newFunctionStringWrapper.replace(\"native \", \"\")\n            newFunctionStringWrapper = newFunctionStringWrapper[:-1] + \" { return %s(%s); }\" % (functionName, newFunctionStringWrapperArgs[:-2])\n            newFunctionStringWrapper = newFunctionStringWrapper.replace(*wrapperStringReplace)\n            if returnIntIndex == -1:\n                newFunctionStringWrapper = newFunctionStringWrapper.replace(\"return \", \"\")\n            newFunction += \"\\n\" + newFunctionStringWrapper\n\n        #Add a special-case string accessor for GetAttributeString() to Java and .NET\n        if functionName == \"GetAttributeString\" and language == \"java\":\n            newFunction += \"\"\"\npublic static String GetAttributeString(\n                    int cryptHandle, // CRYPT_HANDLE\n                    int attributeType // CRYPT_ATTRIBUTE_TYPE\n                    ) throws CryptException\n                    {\n                        int length = GetAttributeString(cryptHandle, attributeType, (byte[])null);\n                        byte[] bytes = new byte[length];\n                        length = GetAttributeString(cryptHandle, attributeType, bytes);\n                        return new String(bytes, 0, length);\n                    }\n\"\"\"\n        elif functionName == \"GetAttributeString\" and language == \"net\":\n            newFunction += \"\"\"\npublic static String GetAttributeString(\n                    int cryptHandle, // CRYPT_HANDLE\n                    int attributeType // CRYPT_ATTRIBUTE_TYPE\n                    )\n                    {\n                        int length = GetAttributeString(cryptHandle, attributeType, null);\n                        byte[] bytes = new byte[length];\n                        length = GetAttributeString(cryptHandle, attributeType, bytes);\n                        return new UTF8Encoding().GetString(bytes, 0, length);\n                    }\n\"\"\"\n        #Add special-case functions for cryptAddRandom(), since it allows NULL as a\n        #first parameter, and a pollType constant in place of the length\n        elif functionName == \"AddRandom\":\n            if language == \"java\":\n                newFunction += \"\"\"\npublic static native void AddRandom(\n                    int pollType\n                    ) throws CryptException;\n\"\"\"\n            elif language == \"net\":\n                newFunction += \"\"\"\npublic static void AddRandom(\n                    int pollType\n                    );\n\"\"\"\n\n        # Add an extra linebreak between functions\n        # This isn't in cryptlib.h, but it makes the converted files more readable\n        if s[functionMatch.end()+1] != \"\\n\":\n            newFunction += \"\\n\"\n\n    s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n    functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n#Translate comments\n#-------------------\nif language != \"java\" and language != \"net\":\n    while 1:\n        match = re.search(r\"/\\*(.*?)\\*/\", s, re.DOTALL)\n        if match == None:\n            break\n        #print match.group()\n        #raw_input()\n        commentStrings = (commentPrefix + match.group(1) + \"  \").split(\"\\n\")\n        newComment = commentStrings[0]\n        for commentString in commentStrings[1:]:\n            if commentString.startswith(\"\\t\"):\n                newComment += \"\\n\" + commentPrefix + (\" \" * (inFileTabSize-2)) + commentString[1:]\n            elif commentString.startswith(\"  \"):\n                newComment += \"\\n\" + commentPrefix + commentString[1:]\n            else:\n                newComment += \"\\n\" + commentPrefix + commentString\n            #print \"building up:\\n\", newComment\n            #raw_input()\n        idx = commentString.find(\"\\n\")\n        s = s[ : match.start()] + newComment + s[match.end() : ]\n\n#Indent each line by one tab\n#---------------------------\ns = s.replace(\"\\n\", \"\\n\\t\")\n\n#Write out file(s)\n#Then generate the .h/.c files necessary for language integration\n#At this point it's easier to just hardcode constants and have\n#separate python and java codepaths\n#---------------\nif language==\"java\":\n\n    #Add enclosing class syntax\n    #---------------------------\n    s = classPrefix + s + classPostfix\n\n    os.chdir(outDir)\n    if not os.path.exists(\"cryptlib\"):\n        os.mkdir(\"./cryptlib\")\n    os.chdir(\"./cryptlib\")\n\n    print (\"Writing java files...\")\n    f = open(\"crypt.java\", \"w\")\n    f.write(s)\n    f.close()\n    f = open(\"CryptException.java\", \"w\")\n    f.write(exceptionString)\n    f.close()\n    f = open(\"CRYPT_QUERY_INFO.java\", \"w\")\n    f.write(cryptQueryInfoString)\n    f.close()\n    f = open(\"CRYPT_OBJECT_INFO.java\", \"w\")\n    f.write(cryptObjectInfoString)\n    f.close()\n\n\n    print (\"Compiling java files...\")\n    print (os.popen(\"javac -classpath .. crypt.java\").read())                    #Compile java file\n    print (os.popen(\"javac -classpath .. CryptException.java\").read())           #Compile java file\n    print (os.popen(\"javac -classpath .. CRYPT_QUERY_INFO.java\").read())         #Compile java file\n    print (os.popen(\"javac -classpath .. CRYPT_OBJECT_INFO.java\").read())        #Compile java file\n\n    os.chdir(\"..\")\n\n    print (\"Generating jar file...\")\n    print (os.popen(\"jar cf cryptlib.jar cryptlib/crypt.class cryptlib/CryptException.class cryptlib/CRYPT_QUERY_INFO.class cryptlib/CRYPT_OBJECT_INFO.class cryptlib\").read())\n\n    print (\"Generating JNI header file...\")\n    print (os.popen(\"javah -classpath . -o cryptlib_jni.h -jni cryptlib.crypt\").read())    #Generate C header\n\n    s = open(\"cryptlib_jni.h\").read()\n    os.remove(\"cryptlib_jni.h\")\n\n    print (\"Generating JNI source file...\")\n\n    #Now we take cryptlib_jni.h and derive the .c file from it\n\n    #Strip( off headers and footers\n    #startIndex = s.find(\"/*\\n * Class\")\n    #endIndex = s.find(\"#ifdef\", startIndex)\n    #s = s[startIndex : endIndex]\n\n    startIndex = s.find(\"#undef\")\n    endIndex = s.find(\"/*\\n * Class\", startIndex)\n    sold = s\n    s = s[startIndex : endIndex]\n\n    startIndex = endIndex\n    endIndex = sold.find(\"#ifdef\", startIndex)\n    s2 = sold[startIndex : endIndex]\n\n    #Add includes and helper functions\n    #Note that we assume \"cryptlib.h\" is one directory behind us\n    s = r\"\"\"\n#include \"../crypt.h\"\n\n#ifdef USE_JAVA\n\n#include <jni.h>\n#include <stdio.h>  //printf\n#include <stdlib.h> //malloc, free\n\n%s\n\n/* Helper Functions */\n\nint processStatus(JNIEnv *env, jint status)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jthrowable obj;\n\n    if (status >= cryptlib_crypt_OK)\n        return 1;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CryptException\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatus - no class?!\\n\");\n        return 0;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(I)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatus - no constructor?!\\n\");\n        return 0;\n    }\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, status);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatus - no object?!\\n\");\n        return 0;\n    }\n\n    if ((*env)->Throw(env, obj) < 0)\n    {\n        printf(\"java_jni.c:processStatus - failed to throw?!\\n\");\n        return 0;\n    }\n    return 0;\n}\n\njobject processStatusReturnCryptQueryInfo(JNIEnv *env, int status, CRYPT_QUERY_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jstring algoName;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_QUERY_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(Ljava/lang/String;IIII)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    algoName = (*env)->NewStringUTF(env, returnValue.algoName);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptQueryInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\njobject processStatusReturnCryptObjectInfo(JNIEnv *env, int status, CRYPT_OBJECT_INFO returnValue)\n{\n    jclass exClass;\n    jmethodID exConstructor;\n    jbyteArray salt;\n    jobject obj;\n\n    if (status < cryptlib_crypt_OK)\n        return NULL;\n\n    exClass = (*env)->FindClass(env, \"cryptlib/CRYPT_OBJECT_INFO\");\n    if (exClass == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no class?!\\n\");\n        return NULL;\n    }\n\n    exConstructor = (*env)->GetMethodID(env, exClass, \"<init>\", \"(IIII[B)V\");\n    if (exConstructor == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no constructor?!\\n\");\n        return NULL;\n    }\n\n    salt = (*env)->NewByteArray(env, returnValue.saltSize);\n    (*env)->SetByteArrayRegion(env, salt, 0, returnValue.saltSize, returnValue.salt);\n\n    obj = (*env)->NewObject(env, exClass, exConstructor, returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, salt);\n    if (obj == 0)\n    {\n        printf(\"java_jni.c:processStatusReturnCryptObjectInfo - no object?!\\n\");\n        return NULL;\n    }\n\n    return obj;\n}\n\nint checkIndicesArray(JNIEnv *env, jbyteArray array, int sequenceOffset, int sequenceLength)\n{\n    jsize arrayLength;\n    jclass exClass;\n\n    if (array == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    arrayLength = (*env)->GetArrayLength(env, array);\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= arrayLength ||\n        sequenceOffset + sequenceLength > arrayLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesArray - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesArray - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerArray(JNIEnv* env, jbyteArray array, jbyte** bytesPtrPtr)\n{\n    jboolean isCopy;\n\n    if (array == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetByteArrayElements(env, array, &isCopy);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        printf(\"java_jni.c:getPointer - failed to get elements of array?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerArray(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    (*env)->ReleaseByteArrayElements(env, array, bytesPtr, 0);\n}\n\nint checkIndicesNIO(JNIEnv *env, jobject byteBuffer, int sequenceOffset, int sequenceLength)\n{\n    jlong byteBufferLength;\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        if (sequenceOffset == 0)\n            return 1;\n        else\n        {\n            exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n            if (exClass == 0)\n                printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n            else\n            if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n                printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n            return 0;\n        }\n    }\n\n    byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer);\n    if (byteBufferLength == -1)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass,\n\"Either a non-direct ByteBuffer was passed or your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n\n    if (sequenceOffset < 0 ||\n        sequenceOffset >= byteBufferLength ||\n        sequenceOffset + sequenceLength > byteBufferLength)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/ArrayIndexOutOfBoundsException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:checkIndicesNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n            printf(\"java_jni.c:checkIndicesNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nint getPointerNIO(JNIEnv* env, jobject byteBuffer, jbyte** bytesPtrPtr)\n{\n    jclass exClass;\n\n    if (byteBuffer == NULL)\n    {\n        (*bytesPtrPtr) = NULL;\n        return 1;\n    }\n\n    (*bytesPtrPtr) = (*env)->GetDirectBufferAddress(env, byteBuffer);\n\n    if (*bytesPtrPtr == NULL)\n    {\n        exClass = (*env)->FindClass(env, \"java/lang/UnsupportedOperationException\");\n        if (exClass == 0)\n            printf(\"java_jni.c:getPointerNIO - no class?!\\n\");\n        else\n        if ((*env)->ThrowNew(env, exClass, \"Your JVM doesn't support JNI access to direct ByteBuffers\") < 0)\n            printf(\"java_jni.c:getPointerNIO - failed to throw?!\\n\");\n        return 0;\n    }\n    return 1;\n}\n\nvoid releasePointerNIO(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)\n{\n}\n\nint getPointerString(JNIEnv* env, jstring str, jbyte** bytesPtrPtr)\n{\n   jboolean isCopy;\n   jsize strLength;\n   const jbyte* rawBytesPtr;\n   jclass exClass;\n#ifdef __WINCE__\n   int status;\n#endif // __WINCE__\n\n\n   if (str == NULL)\n   {\n       (*bytesPtrPtr) = NULL;\n       return 1;\n   }\n\n   rawBytesPtr = (*env)->GetStringUTFChars(env, str, &isCopy);\n\n   if (rawBytesPtr == NULL)\n   {\n       printf(\"java_jni.c:getPointerString - failed to get elements of String?!\\n\");\n       return 0;\n   }\n\n   strLength = (*env)->GetStringUTFLength(env, str);\n\n#ifdef __WINCE__\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength*2+2); // this is unicode, therefore \\0 is two bytes long\n#else\n   (*bytesPtrPtr) = (jbyte*)malloc(strLength+1);\n#endif // __WINCE__\n\n   if (*bytesPtrPtr == NULL)\n   {\n       exClass = (*env)->FindClass(env, \"java/lang/OutOfMemoryError\");\n       if (exClass == 0)\n           printf(\"java_jni.c:getPointerString - no class?!\\n\");\n       else\n       if ((*env)->ThrowNew(env, exClass, \"\") < 0)\n           printf(\"java_jni.c:getPointerString - failed to throw?!\\n\");\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n\n#ifdef __WINCE__\n   status = asciiToUnicode (*bytesPtrPtr, strLength*2+2, rawBytesPtr, strLength+1);\n   if (status == CRYPT_ERROR_BADDATA) {\n       (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n       return 0;\n   }\n#else\n   memcpy(*bytesPtrPtr, rawBytesPtr, strLength);\n   (*bytesPtrPtr)[strLength] = 0;\n#endif // __WINCE__\n\n   (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);\n\n   return 1;\n}\n\nvoid releasePointerString(JNIEnv* env, jstring str, jbyte* bytesPtr)\n{\n    if (bytesPtr == NULL)\n        return;\n    free(bytesPtr);\n}\n\n%s\n\n#endif /* USE_JAVA */\n\"\"\" % (s, s2)\n\n    functionPattern = re.compile(r\"JNIEXPORT ([^ \\t]+) JNICALL Java_cryptlib_crypt_([^ \\t\\n]+)\\n[ \\t]*\\(([^\\)]*)\\);\")\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.groups()\n\n        #Extract the returnType, name, and prototype for this function\n        function = functionMatch.group()\n        functionReturnType, functionName, functionPrototype = functionMatch.groups()\n\n        #Handle special-case AddRandom(pollType) function\n        if functionName == \"AddRandom__I\":\n            p = ParamStruct()\n            p.type = \"int\"\n            p.isPtr = 0\n            p.isOut = 0\n            p.category = \"intType\"\n            p.name = \"NULL\"\n            p.rawIndex = 0\n            p2 = ParamStruct()\n            p2.type = \"int\"\n            p2.isPtr = 0\n            p2.isOut = 0\n            p2.category = \"intType\"\n            p2.name = \"pollType\"\n            p2.rawIndex = 1\n            rawParamStructs = [p,p2]\n            newParamStructs = [p2,p2]\n            voidTag = \"Array\"\n            functionName = functionName.split(\"__\")[0]\n            returnName = None\n            discardName = None\n        else:\n            #Strip JNI decoration off function name\n            #But record which variety of tagged helper functions to use\n            if functionName.find(\"__\") != -1:\n                if functionName.find(\"ByteBuffer\") != -1:\n                    voidTag = \"NIO\"\n                else:\n                    voidTag = \"Array\"\n                functionName = functionName.split(\"__\")[0]\n\n            #Look up the parameters we've previously determined for this function\n            rawParamStructs = rawParamStructsDict[functionName]\n            newParamStructs = newParamStructsDict[functionName]\n            if newReturnStructsDict.get(functionName):\n                returnName = newReturnStructsDict.get(functionName).name\n                returnType = newReturnStructsDict.get(functionName).type\n                returnCategory = newReturnStructsDict.get(functionName).category\n            else:\n                returnName = None\n\n            if newDiscardedStructsDict.get(functionName):\n                discardName = newDiscardedStructsDict.get(functionName).name\n            else:\n                discardName = None\n\n        #for p in newParamStructs: print \"     \"+str(p)\n\n        #Substitute parameter names into the function prototype\n        newFunctionParams = expandFunctionPrototype(functionPrototype, newParamStructs)\n        startIndex = functionMatch.start(3) - functionMatch.start()\n        endIndex = functionMatch.end(3) - functionMatch.start()\n        function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]\n\n        newFunctionBody = \"\\nint status = 0;\\n\"\n\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"&\"\n            if p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr + %sOffset, \" % (p.name, p.name)\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"intType\" or returnType==\"int\":\n                newFunctionBody += \"jint %s = 0;\\n\" % returnName\n            else:\n                newFunctionBody += returnType +\" %s;\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"jint %s = 0;\\n\" % discardName\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                newFunctionBody += \"jbyte* \" + n + \"Ptr = 0;\\n\"\n            newFunctionBody += \"\\n\"\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"if (!getPointerString(env, %(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr + %sOffset\" % (n,n), \"NULL\")\n                    newFunctionBody += \"if (!processStatus(env, crypt%s(%s)))\\n\\tgoto finish;\\n\" % (functionName, argumentsWithNull)\n                newFunctionBody += \"\\n\"\n            elif functionName.find(\"PopData\") != -1:\n                newFunctionBody += \"//CryptPopData is a special case that doesn't have the length querying call\\n\\n\"\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    newFunctionBody += \"if (!checkIndices%(voidTag)s(env, %(n)s, %(n)sOffset, %(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            for n in voidArrayNames:\n                newFunctionBody += \"if (!getPointer%(voidTag)s(env, %(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n\n        if newFunctionBody[-2] != \"\\n\":\n            newFunctionBody += \"\\n\"\n        newFunctionBody += \"status = crypt%s(%s);\\n\\n\" % (functionName, arguments)\n\n        if arrayNames:\n            newFunctionBody += \"finish:\\n\"\n        if arrayNames:\n            for n in voidArrayNames:\n                newFunctionBody += \"releasePointer%(voidTag)s(env, %(n)s, %(n)sPtr);\\n\" % vars()\n            for n in charArrayNames:\n                newFunctionBody += \"releasePointerString(env, %(n)s, %(n)sPtr);\\n\" % vars()\n\n        #newFunctionBody += \"processStatus(env, status);\\n\"\n\n        #if returnName:\n        #    newFunctionBody += \"return(%s);\\n\" % returnName\n        if returnName:\n            if returnCategory == \"intType\" or returnType == \"int\":\n                newFunctionBody += \"processStatus(env, status);\\n\"\n                newFunctionBody += \"return(%s);\\n\" % returnName\n            elif returnType == \"CRYPT_QUERY_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptQueryInfo(env, status, %s));\\n\" % returnName\n            elif returnType == \"CRYPT_OBJECT_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptObjectInfo(env, status, %s));\\n\" % returnName\n        else:\n            newFunctionBody += \"processStatus(env, status);\\n\"\n\n        newFunctionBody = newFunctionBody[:-1] #Strip off last \\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\");\n        newFunction = function[:-1]+\"\\n{\" + newFunctionBody + \"\\n}\"\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    f = open(\"java_jni.c\", \"w\")\n    f.write(s)\n    f.close()\n\n\n\nelif language == \"python\":\n    os.chdir(outDir)\n\n    #print sInts\n    #raw_input()\n    #print sFuncs\n    #raw_input()\n\n    moduleFunctions = \"\"\n    s =         pyBeforeExceptions + exceptionString + pyBeforeFuncs + sFuncs + \\\n                pyBeforeModuleFunctions + moduleFunctions + sModFuncs + \\\n                pyBeforeInts + sInts + \\\n                pyAfterInts\n\n    #print s\n    #raw_input()\n    functionPattern = re.compile(r\"static PyObject\\* python_crypt([^\\(]+)[^{]+{([^}]*)}\", re.DOTALL)\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.group()\n        #print functionMatch.groups()\n        #raw_input()\n\n        #Most of the code in this loop is copied-then-modified from the java code above, ugly..\n        voidTag = \"\"\n\n        #Extract the function name and body\n        functionName, functionBody = functionMatch.groups()\n\n        #Look up the parameters we've previously determined for this function\n        rawParamStructs = rawParamStructsDict[functionName]\n        newParamStructs = newParamStructsDict[functionName]\n        lengthIndices = lengthIndicesDict[functionName]\n        offsetIndices = offsetIndicesDict[functionName]\n        #print functionName, lengthIndices, offsetIndices\n        #raw_input()\n        if newReturnStructsDict.get(functionName):\n            returnName = newReturnStructsDict.get(functionName).name\n            returnType = newReturnStructsDict.get(functionName).type\n            returnCategory = newReturnStructsDict.get(functionName).category\n        else:\n            returnName = None\n        if newDiscardedStructsDict.get(functionName):\n            discardName = newDiscardedStructsDict.get(functionName).name\n        else:\n            discardName = None\n\n        newFunctionBody = \"\\nint status = 0;\\n\"\n\n        #Arguments to pass to the C cryptlib function\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"&\"\n            if p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr, \" % (p.name)\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"intType\" or returnType==\"int\":\n                newFunctionBody += \"int %s = 0;\\n\" % returnName\n            else:\n                newFunctionBody += returnType +\" %s;\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"int %s = 0;\\n\" % discardName\n        #Declare variables to parse args tuple into\n        index = 0\n        for p in newParamStructs:\n            if index not in offsetIndices:       #Python doesn't use the offsets\n                if p.isPtr:\n                    newFunctionBody += \"PyObject* %s = NULL;\\n\" % p.name\n                else:\n                    newFunctionBody += \"int %s = 0;\\n\" % p.name\n            index += 1\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                newFunctionBody += \"unsigned char* \" + n + \"Ptr = 0;\\n\"\n            newFunctionBody += \"\\n\"\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n\n        #Parse the input arguments from the python user\n        #Arguments to parse from the python args tuple\n        if newParamStructs:\n            parseFormatString = \"\"\n            parseArgsList = []\n            index = 0\n            for p in newParamStructs:\n                if index not in lengthIndices and index not in offsetIndices:\n                    if p.isPtr and p.type==\"char\":\n                        parseFormatString += \"O\"\n                        parseArgsList.append(\"&\" + p.name)\n                    elif p.isPtr and p.type==\"void\":\n                        parseFormatString += \"O\"\n                        parseArgsList.append(\"&\" + p.name)\n                    else:\n                        parseFormatString += \"i\"\n                        parseArgsList.append(\"&\" + p.name)\n\n                index += 1\n\n            if newFunctionBody[-2] != \"\\n\":\n                newFunctionBody += \"\\n\"\n\n\n            if functionName == \"AddRandom\":\n                newFunctionBody += \"\"\"\\\n//Special case to handle SLOWPOLL / FASTPOLL values\nif (PyArg_ParseTuple(args, \"i\", &randomDataLength))\n    return processStatus(cryptAddRandom(NULL, randomDataLength));\\n\\n\"\"\"\n\n            newFunctionBody += \"\"\"\\\nif (!PyArg_ParseTuple(args, \"%s\", %s))\n    return(NULL);\\n\\n\"\"\" % (parseFormatString, \", \".join(parseArgsList))\n            #for p in newParamStructs:\n            #    print p.name,\n\n        if arrayNames:\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"if (!getPointerReadString(%(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                newFunctionBody += \"\\n\"\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr\" % (n), \"NULL\")\n                    newFunctionBody += \"if (!processStatusBool(crypt%s(%s)))\\n\\tgoto finish;\\n\" % (functionName, argumentsWithNull)\n                newFunctionBody += \"\\n\"\n            elif functionName.find(\"PopData\") != -1:\n                newFunctionBody += \"//CryptPopData is a special case that doesn't have the length querying call\\n\\n\"\n\n            #Go through and get the pointers for translated void*\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    #Determine the name of its length parameter\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #QueryObject, CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    if n in outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                        newFunctionBody += \"if (!getPointerWriteCheckIndices%(voidTag)s(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                    else:\n                        if lengthName == \"1\": #Handle the #CheckSignature/ImportKey case\n                            newFunctionBody += \"if (!getPointerReadNoLength%(voidTag)s(%(n)s, &%(n)sPtr))\\n\\tgoto finish;\\n\" % vars()\n                        else:\n                            #If the pointer is C_IN and not C_INOUT\n                            #(we check against Encrypt/Decrypt directory for this latter check)\n                            #We only need it for reading, not writing\n                            if n not in outVoidArrayNames and functionName not in (\"Encrypt\", \"Decrypt\"):\n                                newFunctionBody += \"if (!getPointerRead(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n                            else:\n                                newFunctionBody += \"if (!getPointerWrite(%(n)s, &%(n)sPtr, &%(lengthName)s))\\n\\tgoto finish;\\n\" % vars()\n\n        if newFunctionBody[-2] != \"\\n\":\n            newFunctionBody += \"\\n\"\n        newFunctionBody += \"status = crypt%s(%s);\\n\\n\" % (functionName, arguments)\n\n        if arrayNames:\n            newFunctionBody += \"finish:\\n\"\n        if arrayNames:\n            for n in voidArrayNames:\n                newFunctionBody += \"releasePointer(%(n)s, %(n)sPtr);\\n\" % vars()\n            for n in charArrayNames:\n                newFunctionBody += \"releasePointerString(%(n)s, %(n)sPtr);\\n\" % vars()\n\n        if returnName:\n            if returnCategory == \"intType\":\n                newFunctionBody += \"return(processStatusReturnCryptHandle(status, %s));\" % returnName\n            elif returnType == \"CRYPT_QUERY_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptQueryInfo(status, %s));\" % returnName\n            elif returnType == \"CRYPT_OBJECT_INFO\":\n                newFunctionBody += \"return(processStatusReturnCryptObjectInfo(status, %s));\" % returnName\n            elif returnType == \"int\":\n                newFunctionBody += \"return(processStatusReturnInt(status, %s));\" % returnName\n        else:\n            newFunctionBody += \"return(processStatus(status));\"\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\")\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start(2)] + newFunctionBody + \"\\n\" + s[functionMatch.end(2) : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    f = open(\"python.c\", \"w\")\n    f.write(s)\n    f.close()\n\n\n    f = open(\"setup.py\", \"w\")\n    f.write(setupPy)\n    f.close()\n\nelif language == \"net\":\n    flagForAddRandomHack = 0\n\n    #functionPattern = re.compile(r\"public static ([^ \\t]+) ([^ \\t\\n]+)\\([ \\t\\n]*\\(([^\\)]*)\\) throws CryptException;\")\n    functionPattern = re.compile(r\"public static ([^ \\t]+) ([^ \\t\\n]+)\\([ \\t\\n]*([^\\)]*)\\);\")\n    functionMatch = functionPattern.search(s)\n    while functionMatch:\n        #print functionMatch.groups()\n\n        #Extract the returnType, name, and prototype for this function\n        function = functionMatch.group()\n        functionReturnType, functionName, functionPrototype = functionMatch.groups()\n\n        #Handle special-case AddRandom(pollType) function\n        if functionName == \"AddRandom\":\n            flagForAddRandomHack += 1\n        if flagForAddRandomHack == 2:\n            p = ParamStruct()\n            p.type = \"int\"\n            p.isPtr = 0\n            p.isOut = 0\n            p.category = \"intType\"\n            p.name = \"IntPtr.Zero\"\n            p.rawIndex = 0\n            p2 = ParamStruct()\n            p2.type = \"int\"\n            p2.isPtr = 0\n            p2.isOut = 0\n            p2.category = \"intType\"\n            p2.name = \"pollType\"\n            p2.rawIndex = 1\n            rawParamStructs = [p,p2]\n            newParamStructs = [p2,p2]\n            voidTag = \"Array\"\n            functionName = functionName.split(\"__\")[0]\n            returnName = None\n            discardName = None\n            flagForAddRandomHack = None\n        else:\n            #Look up the parameters we've previously determined for this function\n            rawParamStructs = rawParamStructsDict[functionName]\n            newParamStructs = newParamStructsDict[functionName]\n            if newReturnStructsDict.get(functionName):\n                returnName = newReturnStructsDict.get(functionName).name\n                returnType = newReturnStructsDict.get(functionName).type\n                returnCategory = newReturnStructsDict.get(functionName).category\n            else:\n                returnName = None\n            if newDiscardedStructsDict.get(functionName):\n                discardName = newDiscardedStructsDict.get(functionName).name\n            else:\n                discardName = None\n\n        #for p in newParamStructs: print \"     \"+str(p)\n\n        #Substitute parameter names into the function prototype\n        newFunctionParams = functionPrototype #expandFunctionPrototype(functionPrototype, newParamStructs)\n        startIndex = functionMatch.start(3) - functionMatch.start()\n        endIndex = functionMatch.end(3) - functionMatch.start()\n        function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]\n\n        newFunctionBody = \"\\n\"\n\n        arguments = \"\"\n        for p in rawParamStructs:\n            if p.name == returnName or p.name == discardName:\n                arguments += \"%sPtr, \" % p.name\n            elif p.isPtr and p.type==\"void\":\n                arguments += \"%sPtr, \" % p.name\n            elif p.isPtr and p.type==\"char\":\n                arguments += \"%sPtr, \" % p.name\n            else:\n                arguments += p.name + \", \"\n        arguments = arguments[:-2]\n\n        if returnName:\n            if returnCategory == \"structType\":\n                newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(%s)));\\n\" % (returnName, returnType)\n                newFunctionBody += \"%s %s = new %s();\\n\" % (returnType, returnName, returnType)\n            else:\n                newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(4);\\n\" % returnName\n        if discardName:\n            newFunctionBody += \"IntPtr %sPtr = Marshal.AllocHGlobal(4);\\n\" % discardName\n\n        #If we have arrays, add the code to handle them\n        arrayNames          = [p.name for p in newParamStructs if p.isPtr]\n        charArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"char\"]\n        voidArrayNames      = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\"]\n        outVoidArrayNames   = [p.name for p in newParamStructs if p.isPtr and p.type==\"void\" and p.isOut]\n        if arrayNames:\n            #Declare C pointers to retrieve array contents\n            for n in arrayNames:\n                #newFunctionBody += \"jbyte* \" + n + \"Ptr = 0;\\n\"\n                newFunctionBody += \"GCHandle %sHandle = new GCHandle();\\nIntPtr %sPtr = IntPtr.Zero;\\n\" % (n,n)\n                if n in charArrayNames:\n                    newFunctionBody += \"byte[] %sArray = new UTF8Encoding().GetBytes(%s);\\n\" % (n,n)\n\n            newFunctionBody += \"try\\n{\\n\"\n\n            #Retrieve the contents for strings\n            #We need to do this first cause in one case this char* is needed as an argument\n            if charArrayNames:\n                for n in charArrayNames:\n                    newFunctionBody += \"getPointer(%(n)sArray, 0, ref %(n)sHandle, ref %(n)sPtr);\\n\" % vars()\n            #Query the length of output data\n            #CryptPopData is the only exception that produces output data\n            #but doesn't require this cause an explicit length is passed in\n            if outVoidArrayNames and functionName.find(\"PopData\") == -1:\n                for n in outVoidArrayNames:\n                    argumentsWithNull = arguments.replace(\"%sPtr + %sOffset\" % (n,n), \"NULL\")\n                    newFunctionBody += \"processStatus(wrapped_%s(%s));\\n\" % (functionName, argumentsWithNull)\n                    newFunctionBody += \"int %s = Marshal.ReadInt32(%sPtr);\\n\" % (returnName, returnName)\n            elif functionName.find(\"PopData\") != -1 or functionName.find(\"PushData\") != -1:\n                newFunctionBody += \"int %s = 0;\\n\" % returnName\n                newFunctionBody += \"int status;\\n\"\n            if voidArrayNames:\n                for n in voidArrayNames:\n                    index = [p.name for p in newParamStructs].index(n)\n                    if n in outVoidArrayNames:\n                        lengthName = returnName\n                    else:\n                        if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != \"rawType\" or newParamStructs[index+2].type != \"int\":\n                            lengthName = \"1\" #CheckSignature and ImportKey don't have a length, so we can't do a good check!\n                        else:\n                            lengthName = newParamStructs[index+2].name\n                    newFunctionBody += \"checkIndices(%(n)s, %(n)sOffset, %(lengthName)s);\\n\" % vars()\n            for n in voidArrayNames:\n                newFunctionBody += \"getPointer(%(n)s, %(n)sOffset, ref %(n)sHandle, ref %(n)sPtr);\\n\" % vars()\n        elif returnName:\n            newFunctionBody += \"try\\n{\\n\"\n\n        if functionName.find(\"PopData\") == -1 and functionName.find(\"PushData\") == -1:\n                newFunctionBody += \"processStatus(wrapped_%s(%s));\\n\" % (functionName, arguments)\n        else:\n                newFunctionBody += \"status = wrapped_%s(%s);\\n\" % (functionName, arguments)\n                newFunctionBody += \"%s = Marshal.ReadInt32(%sPtr);\\n\" % (returnName, returnName)\n                newFunctionBody += \"processStatus(status, %s);\\n\" %returnName\n\n        #if newFunctionBody[-2] != \"\\n\":\n        #    newFunctionBody += \"\\n\"\n        if returnName:\n            if returnCategory == \"structType\":\n                newFunctionBody += \"Marshal.PtrToStructure(%sPtr, %s);\\n\" % (returnName, returnName)\n                newFunctionBody += \"return %s;\\n\" % returnName\n            else:\n                                if functionName.find(\"PopData\") == -1 and functionName.find(\"PushData\") == -1:\n                                        newFunctionBody += \"return Marshal.ReadInt32(%sPtr);\\n\" % returnName\n                                else:\n                                        newFunctionBody += \"return %s;\\n\" %returnName\n\n        if arrayNames or returnName:\n            newFunctionBody += \"}\\nfinally\\n{\\n\"\n            if returnName:\n                newFunctionBody += \"Marshal.FreeHGlobal(%sPtr);\\n\" % returnName\n            if arrayNames:\n                for n in voidArrayNames:\n                    newFunctionBody += \"releasePointer(%(n)sHandle);\\n\" % vars()\n                for n in charArrayNames:\n                    newFunctionBody += \"releasePointer(%(n)sHandle);\\n\" % vars()\n            newFunctionBody += \"}\\n\"\n\n        #Add tabs to lines inside brackets:\n        lines = newFunctionBody.split(\"\\n\")\n        brackets = 0\n        for count in range(len(lines)):\n            line = lines[count]\n            if line.startswith(\"}\"):\n                brackets -= 1\n            lines[count] = (\"\\t\" * brackets) + line\n            if line.startswith(\"{\"):\n                brackets += 1\n        newFunctionBody = \"\\n\".join(lines)\n\n        newFunctionBody = newFunctionBody[:-1] #Strip off last \\n\n        newFunctionBody = newFunctionBody.replace(\"\\n\", \"\\n\\t\");\n        newFunction = function[:-1]+\"\\n{\" + newFunctionBody + \"\\n}\"\n        newFunction = newFunction.replace(\"\\n\", \"\\n\\t\");\n\n        #Substitute the output equivalent for the input\n        s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]\n\n        #Get next function\n        functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))\n\n    #Add enclosing class syntax\n    #---------------------------\n    s = classPrefix + s\n\n    for functionName in functionNames:\n        rawParamStructs = rawParamStructsDict[functionName]\n        parameters = \"\"\n        for p in rawParamStructs:\n            if p.isPtr:\n                parameters += \"IntPtr %s, \" % p.name\n            else:\n                parameters += \"int %s, \" % p.name\n        parameters = parameters[:-2]\n\n        s += '\\t[DllImport(\"cl32.dll\", EntryPoint=\"crypt%s\")]\\n\\tprivate static extern int wrapped_%s(%s);\\n\\n' % (functionName, functionName, parameters)\n        functionNames = [] #Accumulate function names here\n        #rawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)\n        #newParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)\n\n\n\n    s += classPostfix + exceptionString + \"\\n\\n}\"\n\n    os.chdir(outDir)\n    print (\"Writing .NET file...\")\n    f = open(\"cryptlib.cs\", \"w\")\n    f.write(s)\n    f.close()\n\n\n"
  },
  {
    "path": "deps/cl345/tools/dumpasn1.c",
    "content": "/* ASN.1 data display code, copyright Peter Gutmann\n   <pgut001@cs.auckland.ac.nz>, based on ASN.1 dump program by David Kemp,\n   with contributions from various people including Matthew Hamrick, Bruno\n   Couillard, Hallvard Furuseth, Geoff Thorpe, David Boyce, John Hughes,\n   'Life is hard, and then you die', Hans-Olof Hermansson, Tor Rustad,\n   Kjetil Barvik, James Sweeny, Chris Ridd, David Lemley, John Tobey, James\n   Manger, Igor Perminov, and several other people whose names I've\n   misplaced.\n\n   Available from http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c. Last\n   updated 12 February 2019 (version 20190212, if you prefer it that way,\n   see also UPDATE_STRING below).  To build under Windows, use \n   'cl /MD dumpasn1.c'.  To build on OS390 or z/OS, use \n   '/bin/c89 -D OS390 -o dumpasn1 dumpasn1.c'.\n\n   This code grew slowly over time without much design or planning, and with\n   extra features being tacked on as required.  It's not representative of my\n   normal coding style, and should only be used as a debugging/diagnostic\n   tool and not in a production environment (I'm not sure how you'd use\n   it in production anyway, but felt I should point that out).  cryptlib,\n   http://www.cs.auckland.ac.nz/~pgut001/cryptlib/, does a much better job of\n   checking ASN.1 than this does, since dumpasn1 is a display program written\n   to accept the widest possible range of input and not a compliance checker.\n   In other words it will bend over backwards to even accept invalid data,\n   since a common use for it is to try and locate encoding problems that lead\n   to invalid encoded data.  While it will warn about some types of common\n   errors, the fact that dumpasn1 will display an ASN.1 data item doesn't mean\n   that the item is valid.\n\n   dumpasn1 requires a config file dumpasn1.cfg to be present in the same\n   location as the program itself or in a standard directory where binaries\n   live (it will run without it but will display a warning message, you can\n   configure the path either by hardcoding it in or using an environment\n   variable as explained further down).  The config file is available from\n   http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg.\n\n   This code assumes that the input data is binary, having come from a MIME-\n   aware mailer or been piped through a decoding utility if the original\n   format used base64 encoding.  If you need to decode it, it's recommended\n   that you use a utility like uudeview, which will strip virtually any kind\n   of encoding (MIME, PEM, PGP, whatever) to recover the binary original.\n\n   You can use this code in whatever way you want, as long as you don't try\n   to claim you wrote it.\n\n   (Someone asked for clarification on what this means, treat it as a very\n   mild form of the BSD license in which you're not required to include LONG\n   LEGAL DISCLAIMERS IN ALL CAPS but just a small note in a corner somewhere\n   (e.g. the back of a manual) that you're using the dumpasn1 code.  And if\n   you do use it, please make sure you're using a recent version, I\n   occasionally see screen shots from incredibly ancient versions that are\n   nowhere near as good as what current versions produce).\n\n   Editing notes: Tabs to 4, phasers to malky (and in case anyone wants to\n   complain about that, see \"Program Indentation and Comprehensiblity\",\n   Richard Miara, Joyce Musselman, Juan Navarro, and Ben Shneiderman,\n   Communications of the ACM, Vol.26, No.11 (November 1983), p.861) */\n\n#include <ctype.h>\n#include <limits.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#ifdef OS390\n  #include <unistd.h>\n#endif /* OS390 */\n\n/* The update string, printed as part of the help screen */\n\n#define UPDATE_STRING\t\"12 February 2019\"\n\n/* Useful defines */\n\n#ifndef TRUE\n  #define FALSE\t0\n  #define TRUE\t( !FALSE )\n#endif /* TRUE */\n#ifndef BYTE\n  typedef unsigned char\t\tBYTE;\n#endif /* BYTE */\n\n/* Tandem Guardian NonStop Kernel options */\n\n#ifdef __TANDEM\n  #pragma nolist\t\t/* Spare us the source listing, no GUI... */\n  #pragma nowarn (1506)\t/* Implicit type conversion: int to char etc */\n#endif /* __TANDEM */\n\n/* SunOS 4.x doesn't define seek codes or exit codes or FILENAME_MAX (it does\n   define _POSIX_MAX_PATH, but in funny locations and to different values\n   depending on which include file you use).  Strictly speaking this code\n   isn't right since we need to use PATH_MAX, however not all systems define\n   this, some use _POSIX_PATH_MAX, and then there are all sorts of variations\n   and other defines that you have to check, which require about a page of\n   code to cover each OS, so we just use max( FILENAME_MAX, 512 ) which\n   should work for everything */\n\n#ifndef SEEK_SET\n  #define SEEK_SET\t\t\t0\n  #define SEEK_CUR\t\t\t2\n#endif /* No fseek() codes defined */\n#ifndef EXIT_FAILURE\n  #define EXIT_FAILURE\t\t1\n  #define EXIT_SUCCESS\t\t( !EXIT_FAILURE )\n#endif /* No exit() codes defined */\n#ifndef FILENAME_MAX\n  #define FILENAME_MAX\t\t512\n#else\n  #if FILENAME_MAX < 128\n\t#undef FILENAME_MAX\n\t#define FILENAME_MAX\t512\n  #endif /* FILENAME_MAX < 128 */\n#endif /* FILENAME_MAX */\n\n/* Under Windows we can do special-case handling for paths and Unicode\n   strings (although in practice it can't really handle much except\n   latin-1) */\n\n#if ( defined( _WINDOWS ) || defined( WIN32 ) || defined( _WIN32 ) || \\\n\t  defined( __WIN32__ ) )\n  #include <windows.h>\n  #include <io.h>\t\t\t\t\t/* For _setmode() */\n  #include <fcntl.h>\t\t\t\t/* For _setmode() codes */\n  #ifndef _O_U16TEXT\n\t#define _O_U16TEXT\t\t0x20000\t/* _setmode() code */\n  #endif /* !_O_U16TEXT */\n  #define __WIN32__\n#endif /* Win32 */\n\n/* Under Unix we can do special-case handling for paths and Unicode strings.\n   Detecting Unix systems is a bit tricky but the following should find most\n   versions.  This define implicitly assumes that the system has wchar_t\n   support, but this is almost always the case except for very old systems,\n   so it's best to default to allow-all rather than deny-all */\n\n#if defined( linux ) || defined( __linux__ ) || defined( sun ) || \\\n\tdefined( __bsdi__ ) || defined( __FreeBSD__ ) || defined( __NetBSD__ ) || \\\n\tdefined( __OpenBSD__ ) || defined( __hpux ) || defined( _M_XENIX ) || \\\n\tdefined( __osf__ ) || defined( _AIX ) || defined( __MACH__ )\n  #define __UNIX__\n#endif /* Every commonly-used Unix */\n#if defined( linux ) || defined( __linux__ )\n  #ifndef __USE_ISOC99\n\t#define __USE_ISOC99\n  #endif /* __USE_ISOC99 */\n  #include <wchar.h>\n#endif /* Linux */\n\n/* For IBM mainframe OSes we use the Posix environment, so it looks like\n   Unix */\n\n#ifdef OS390\n  #define __OS390__\n  #define __UNIX__\n#endif /* OS390 / z/OS */\n\n/* Tandem NSK: Don't tangle with Tandem OSS, which is almost UNIX */\n\n#ifdef __TANDEM\n  #ifdef _GUARDIAN_TARGET\n\t#define __TANDEM_NSK__\n  #else\n\t#define __UNIX__\n  #endif /* _GUARDIAN_TARGET */\n#endif /* __TANDEM */\n\n/* Some OSes don't define the min() macro */\n\n#ifndef min\n  #define min(a,b)\t\t( ( a ) < ( b ) ? ( a ) : ( b ) )\n#endif /* !min */\n\n/* Macros to avoid problems with sign extension */\n\n#define byteToInt( x )\t( ( BYTE ) ( x ) )\n\n/* Turn off pointless VC++ warnings */\n\n#ifdef _MSC_VER\n  #pragma warning( disable: 4018 )\n#endif /* VC++ */\n\n/* When we dump a nested data object encapsulated within a larger object, the\n   length is initially set to a magic value which is adjusted to the actual\n   length once we start parsing the object */\n\n#define LENGTH_MAGIC\t177545L\n\n/* Tag classes */\n\n#define CLASS_MASK\t\t0xC0\t/* Bits 8 and 7 */\n#define UNIVERSAL\t\t0x00\t/* 0 = Universal (defined by ITU X.680) */\n#define APPLICATION\t\t0x40\t/* 1 = Application */\n#define CONTEXT\t\t\t0x80\t/* 2 = Context-specific */\n#define PRIVATE\t\t\t0xC0\t/* 3 = Private */\n\n/* Encoding type */\n\n#define FORM_MASK\t\t0x20\t/* Bit 6 */\n#define PRIMITIVE\t\t0x00\t/* 0 = primitive */\n#define CONSTRUCTED\t\t0x20\t/* 1 = constructed */\n\n/* Universal tags */\n\n#define TAG_MASK\t\t0x1F\t/* Bits 5 - 1 */\n#define EOC\t\t\t\t0x00\t/*  0: End-of-contents octets */\n#define BOOLEAN\t\t\t0x01\t/*  1: Boolean */\n#define INTEGER\t\t\t0x02\t/*  2: Integer */\n#define BITSTRING\t\t0x03\t/*  2: Bit string */\n#define OCTETSTRING\t\t0x04\t/*  4: Byte string */\n#define NULLTAG\t\t\t0x05\t/*  5: NULL */\n#define OID\t\t\t\t0x06\t/*  6: Object Identifier */\n#define OBJDESCRIPTOR\t0x07\t/*  7: Object Descriptor */\n#define EXTERNAL\t\t0x08\t/*  8: External */\n#define REAL\t\t\t0x09\t/*  9: Real */\n#define ENUMERATED\t\t0x0A\t/* 10: Enumerated */\n#define EMBEDDED_PDV\t0x0B\t/* 11: Embedded Presentation Data Value */\n#define UTF8STRING\t\t0x0C\t/* 12: UTF8 string */\n#define SEQUENCE\t\t0x10\t/* 16: Sequence/sequence of */\n#define SET\t\t\t\t0x11\t/* 17: Set/set of */\n#define NUMERICSTRING\t0x12\t/* 18: Numeric string */\n#define PRINTABLESTRING\t0x13\t/* 19: Printable string (ASCII subset) */\n#define T61STRING\t\t0x14\t/* 20: T61/Teletex string */\n#define VIDEOTEXSTRING\t0x15\t/* 21: Videotex string */\n#define IA5STRING\t\t0x16\t/* 22: IA5/ASCII string */\n#define UTCTIME\t\t\t0x17\t/* 23: UTC time */\n#define GENERALIZEDTIME\t0x18\t/* 24: Generalized time */\n#define GRAPHICSTRING\t0x19\t/* 25: Graphic string */\n#define VISIBLESTRING\t0x1A\t/* 26: Visible string (ASCII subset) */\n#define GENERALSTRING\t0x1B\t/* 27: General string */\n#define UNIVERSALSTRING\t0x1C\t/* 28: Universal string */\n#define BMPSTRING\t\t0x1E\t/* 30: Basic Multilingual Plane/Unicode string */\n\n/* Length encoding */\n\n#define LEN_XTND  0x80\t\t/* Indefinite or long form */\n#define LEN_MASK  0x7F\t\t/* Bits 7 - 1 */\n\n/* Various special-case operations to perform on strings */\n\ntypedef enum {\n\tSTR_NONE,\t\t\t\t/* No special handling */\n\tSTR_UTCTIME,\t\t\t/* Check it's UTCTime */\n\tSTR_GENERALIZED,\t\t/* Check it's GeneralizedTime */\n\tSTR_PRINTABLE,\t\t\t/* Check it's a PrintableString */\n\tSTR_IA5,\t\t\t\t/* Check it's an IA5String */\n\tSTR_LATIN1,\t\t\t\t/* Read and display string as latin-1 */\n\tSTR_UTF8,\t\t\t\t/* Read and display string as UTF8 */\n\tSTR_BMP,\t\t\t\t/* Read and display string as Unicode */\n\tSTR_BMP_REVERSED\t\t/* STR_BMP with incorrect endianness */\n\t} STR_OPTION;\n\n/* Structure to hold info on an ASN.1 item */\n\ntypedef struct {\n\tint id;\t\t\t\t\t\t/* Tag class + primitive/constructed */\n\tint tag;\t\t\t\t\t/* Tag */\n\tlong length;\t\t\t\t/* Data length */\n\tint indefinite;\t\t\t\t/* Item has indefinite length */\n\tint nonCanonical;\t\t\t/* Non-canonical length encoding used */\n\tBYTE header[ 16 ];\t\t\t/* Tag+length data */\n\tint headerSize;\t\t\t\t/* Size of tag+length */\n\t} ASN1_ITEM;\n\n/* Configuration options */\n\nstatic int printDots = FALSE;\t\t/* Whether to print dots to align columns */\nstatic int doPure = FALSE;\t\t\t/* Print data without LHS info column */\nstatic int doDumpHeader = FALSE;\t/* Dump tag+len in hex (level = 0, 1, 2) */\nstatic int extraOIDinfo = FALSE;\t/* Print extra information about OIDs */\nstatic int doHexValues = FALSE;\t\t/* Display size, offset in hex not dec.*/\nstatic int useStdin = FALSE;\t\t/* Take input from stdin */\nstatic int zeroLengthAllowed = FALSE;/* Zero-length items allowed */\nstatic int dumpText = FALSE;\t\t/* Dump text alongside hex data */\nstatic int printAllData = FALSE;\t/* Whether to print all data in long blocks */\nstatic int checkEncaps = TRUE;\t\t/* Print encaps.data in BIT/OCTET STRINGs */\nstatic int checkCharset = TRUE;\t\t/* Check val.of char strs.hidden in OCTET STRs */\n#ifndef __OS390__\nstatic int reverseBitString = TRUE;\t/* Print BIT STRINGs in natural order */\n#else\nstatic int reverseBitString = FALSE;/* Natural order on OS390 is the same as ASN.1 */\n#endif /* __OS390__ */\nstatic int rawTimeString = FALSE;\t/* Print raw time strings */\nstatic int shallowIndent = FALSE;\t/* Perform shallow indenting */\nstatic int outputWidth = 80;\t\t/* 80-column display */\nstatic int maxNestLevel = 100;\t\t/* Maximum nesting level for which to display output */\nstatic int doOutlineOnly = FALSE;\t/* Only display constructed-object outline */\n\n/* Formatting information used for the fixed informational column to the\n   left of the displayed data */\n\nstatic int infoWidth = 4;\nstatic const char *indentStringTbl[] = {\n\tNULL, NULL, NULL,\n\t\"       : \",\t\t\t/* \"xxx xxx: \" (3) */\n\t\"         : \",\t\t\t/* \"xxxx xxxx: \" (4) */\n\t\"           : \",\t\t/* \"xxxxx xxxxx: \" (5) */\n\t\"             : \",\t\t/* \"xxxxxx xxxxxx: \" (6) */\n\t\"               : \",\t/* \"xxxxxxx xxxxxxx: \" (7) */\n\t\"                 : \",\t/* \"xxxxxxxx xxxxxxxx: \" (8) */\n\t\"\", \"\", \"\", \"\"\n\t};\nstatic const char *lenTbl[] = {\n\tNULL, NULL, NULL,\n\t\"%3ld %3ld: \", \"%4ld %4ld: \", \"%5ld %5ld: \",\n\t\"%6ld %6ld: \", \"%7ld %7ld: \", \"%8ld %8ld: \",\n\t\"\", \"\", \"\", \"\"\n\t};\nstatic const char *lenIndefTbl[] = {\n\tNULL, NULL, NULL,\n\t\"%3ld NDF: \", \"%4ld NDEF: \", \"%5ld INDEF: \",\n\t\"%6ld INDEF : \", \"%7ld INDEF  : \", \"%8ld INDEF   : \",\n\t\"\", \"\", \"\", \"\"\n\t};\nstatic const char *lenHexTbl[] = {\n\tNULL, NULL, NULL,\n\t\"%03lX %3lX: \", \"%04lX %4lX: \", \"%05lX %5lX: \",\n\t\"%06lX %6lX: \", \"%07lX %7lX: \", \"%08lX %8lX: \",\n\t\"\", \"\", \"\", \"\"\n\t};\nstatic const char *lenHexIndefTbl[] = {\n\tNULL, NULL, NULL,\n\t\"%03lX NDF: \", \"%04lX NDEF: \", \"%05lX INDEF: \",\n\t\"%06lX INDEF : \", \"%07lX INDEF  : \", \"%08lX INDEF   : \",\n\t\"\", \"\", \"\", \"\"\n\t};\n\n#define INDENT_SIZE\t\t( infoWidth + 1 + infoWidth + 1 + 1 )\n#define INDENT_STRING\tindentStringTbl[ infoWidth ]\n#define LEN\t\t\t\tlenTbl[ infoWidth ]\n#define LEN_INDEF\t\tlenIndefTbl[ infoWidth ]\n#define LEN_HEX\t\t\tlenHexTbl[ infoWidth ]\n#define LEN_HEX_INDEF\tlenHexIndefTbl[ infoWidth ]\n\n/* Error and warning information */\n\nstatic int noErrors = 0;\t\t\t/* Number of errors found */\nstatic int noWarnings = 0;\t\t\t/* Number of warnings */\n\n/* Position in the input stream */\n\nstatic int fPos = 0;\t\t\t\t/* Absolute position in data */\n\n/* The output stream */\n\nstatic FILE *output;\t\t\t\t/* Output stream */\n\n/* OID data sizes.  Because of Microsoft's \"encode random noise and call it\n   an OID\" approach, we maintain two size limits, a sane one and one capable\n   of holding the random-noise OID data, which we warn about */\n\n#define MAX_OID_SIZE\t\t40\n#define MAX_SANE_OID_SIZE\t32\n\n/* Information on an ASN.1 Object Identifier */\n\ntypedef struct tagOIDINFO {\n\tstruct tagOIDINFO *next;\t\t/* Next item in list */\n\tBYTE oid[ MAX_OID_SIZE ];\n\tint oidLength;\n\tchar *comment, *description;\t/* Name, rank, serial number */\n\tint warn;\t\t\t\t\t\t/* Whether to warn if OID encountered */\n\t} OIDINFO;\n\nstatic OIDINFO *oidList = NULL;\n\n/* If the config file isn't present in the current directory, we search the\n   following paths (this is needed for Unix with dumpasn1 somewhere in the\n   path, since this doesn't set up argv[0] to the full path).  Anything\n   beginning with a '$' uses the appropriate environment variable.  In\n   addition under Unix we also walk down $PATH looking for it */\n\n#ifdef __TANDEM_NSK__\n  #define CONFIG_NAME\t\t\"asn1cfg\"\n#else\n  #define CONFIG_NAME\t\t\"dumpasn1.cfg\"\n#endif /* __TANDEM_NSK__ */\n\n#if defined( __TANDEM_NSK__ )\n\nstatic const char *configPaths[] = {\n\t\"$system.security\", \"$system.system\",\n\n\tNULL\n\t};\n\n#elif defined( __WIN32__ )\n\nstatic const char *configPaths[] = {\n\t/* Windoze absolute paths (yeah, this code has been around for awhile,\n\t   why do you ask?) */\n\t\"c:\\\\windows\\\\\", \"c:\\\\winnt\\\\\",\n\n\t/* It's my program, I'm allowed to hardcode in strange paths that no-one\n\t   else uses */\n\t\"c:\\\\program files\\\\bin\\\\\",\n\t\"c:\\\\program files (x86)\\\\bin\\\\\",\n\n\t/* This one seems to be popular as well */\n\t\"c:\\\\program files\\\\utilities\\\\\",\n\t\"c:\\\\program files (x86)\\\\utilities\\\\\",\n\n\t/* General environment-based paths */\n\t\"$DUMPASN1_PATH/\",\n\n\tNULL\n\t};\n\n#elif defined( __OS390__ )\n\nstatic const char *configPaths[] = {\n\t/* General environment-based paths */\n\t\"$DUMPASN1_PATH/\",\n\n\tNULL\n\t};\n\n#else\n\nstatic const char *configPaths[] = {\n  #ifndef DEBIAN\n\t/* Unix absolute paths */\n\t\"/usr/bin/\", \"/usr/local/bin/\", \"/etc/dumpasn1/\",\n\n\t/* Unix environment-based paths */\n\t\"$HOME/\", \"$HOME/bin/\",\n\n\t/* It's my program, I'm allowed to hardcode in strange paths that no-one\n\t   else uses */\n\t\"$HOME/BIN/\",\n  #else\n\t/* Debian has specific places where you're supposed to dump things.  Note\n\t   the dot after $HOME, since config files are supposed to start with a\n\t   dot for Debian */\n\t\"$HOME/.\", \"/etc/dumpasn1/\",\n  #endif /* DEBIAN-specific paths */\n\n\t/* General environment-based paths */\n\t\"$DUMPASN1_PATH/\",\n\n\tNULL\n\t};\n#endif /* OS-specific search paths */\n\n#define isEnvTerminator( c )\t\\\n\t( ( ( c ) == '/' ) || ( ( c ) == '.' ) || ( ( c ) == '$' ) || \\\n\t  ( ( c ) == '\\0' ) || ( ( c ) == '~' ) )\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tObject Identification/Description Routines\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Return descriptive strings for universal tags */\n\nstatic char *idstr( const int tagID )\n\t{\n\tswitch( tagID )\n\t\t{\n\t\tcase EOC:\n\t\t\treturn( \"End-of-contents octets\" );\n\t\tcase BOOLEAN:\n\t\t\treturn( \"BOOLEAN\" );\n\t\tcase INTEGER:\n\t\t\treturn( \"INTEGER\" );\n\t\tcase BITSTRING:\n\t\t\treturn( \"BIT STRING\" );\n\t\tcase OCTETSTRING:\n\t\t\treturn( \"OCTET STRING\" );\n\t\tcase NULLTAG:\n\t\t\treturn( \"NULL\" );\n\t\tcase OID:\n\t\t\treturn( \"OBJECT IDENTIFIER\" );\n\t\tcase OBJDESCRIPTOR:\n\t\t\treturn( \"ObjectDescriptor\" );\n\t\tcase EXTERNAL:\n\t\t\treturn( \"EXTERNAL\" );\n\t\tcase REAL:\n\t\t\treturn( \"REAL\" );\n\t\tcase ENUMERATED:\n\t\t\treturn( \"ENUMERATED\" );\n\t\tcase EMBEDDED_PDV:\n\t\t\treturn( \"EMBEDDED PDV\" );\n\t\tcase UTF8STRING:\n\t\t\treturn( \"UTF8String\" );\n\t\tcase SEQUENCE:\n\t\t\treturn( \"SEQUENCE\" );\n\t\tcase SET:\n\t\t\treturn( \"SET\" );\n\t\tcase NUMERICSTRING:\n\t\t\treturn( \"NumericString\" );\n\t\tcase PRINTABLESTRING:\n\t\t\treturn( \"PrintableString\" );\n\t\tcase T61STRING:\n\t\t\treturn( \"TeletexString\" );\n\t\tcase VIDEOTEXSTRING:\n\t\t\treturn( \"VideotexString\" );\n\t\tcase IA5STRING:\n\t\t\treturn( \"IA5String\" );\n\t\tcase UTCTIME:\n\t\t\treturn( \"UTCTime\" );\n\t\tcase GENERALIZEDTIME:\n\t\t\treturn( \"GeneralizedTime\" );\n\t\tcase GRAPHICSTRING:\n\t\t\treturn( \"GraphicString\" );\n\t\tcase VISIBLESTRING:\n\t\t\treturn( \"VisibleString\" );\n\t\tcase GENERALSTRING:\n\t\t\treturn( \"GeneralString\" );\n\t\tcase UNIVERSALSTRING:\n\t\t\treturn( \"UniversalString\" );\n\t\tcase BMPSTRING:\n\t\t\treturn( \"BMPString\" );\n\t\tdefault:\n\t\t\treturn( \"Unknown (Reserved)\" );\n\t\t}\n\t}\n\n/* Return information on an object identifier */\n\nstatic OIDINFO *getOIDinfo( const BYTE *oid, const int oidLength )\n\t{\n\tconst BYTE oidByte = oid[ 1 ];\n\tOIDINFO *oidPtr;\n\n\tfor( oidPtr = oidList; oidPtr != NULL; oidPtr = oidPtr->next )\n\t\t{\n\t\tif( oidLength != oidPtr->oidLength - 2 )\n\t\t\tcontinue;\t/* Quick-reject check */\n\t\tif( oidByte != oidPtr->oid[ 2 + 1 ] )\n\t\t\tcontinue;\t/* Quick-reject check */\n\t\tif( !memcmp( oidPtr->oid + 2, oid, oidLength ) )\n\t\t\treturn( oidPtr );\n\t\t}\n\n\treturn( NULL );\n\t}\n\n/* Add an OID attribute */\n\nstatic int addAttribute( char **buffer, char *attribute )\n\t{\n\tif( ( *buffer = ( char * ) malloc( strlen( attribute ) + 1 ) ) == NULL )\n\t\t{\n\t\tputs( \"Out of memory.\" );\n\t\treturn( FALSE );\n\t\t}\n\tstrcpy( *buffer, attribute );\n\treturn( TRUE );\n\t}\n\n/* Table to identify valid string chars (taken from cryptlib).  Note that\n   IA5String also allows control chars, but we warn about these since\n   finding them in a certificate is a sign that there's something\n   seriously wrong */\n\n#define P\t1\t\t\t\t\t\t/* PrintableString */\n#define I\t2\t\t\t\t\t\t/* IA5String */\n#define PI\t3\t\t\t\t\t\t/* IA5String and PrintableString */\n\nstatic int charFlags[] = {\n\t/* 00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F */\n\t\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\n\t/* 10  11  12  13  14  15  16  17  18  19  1A  1B  1C  1D  1E  1F */\n\t\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\t0,\n\t/*\t\t!\t\"\t#\t$\t%\t&\t'\t(\t)\t*\t+\t,\t-\t.\t/ */\n\t   PI,\tI,\tI,\tI,\tI,\tI,\tI, PI, PI, PI,\tI, PI, PI, PI, PI, PI,\n\t/*\t0\t1\t2\t3\t4\t5\t6\t7\t8\t9\t:\t;\t<\t=\t>\t? */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI, PI,\tI, PI,\n\t/*\t@\tA\tB\tC\tD\tE\tF\tG\tH\tI\tJ\tK\tL\tM\tN\tO */\n\t\tI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\n\t/*\tP\tQ\tR\tS\tT\tU\tV\tW\tX\tY\tZ\t[\t\\\t]\t^ _ */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI,\tI,\tI,\tI,\n\t/*\t`\ta\tb\tc\td\te\tf\tg\th\ti\tj\tk\tl\tm\tn\to */\n\t\tI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\n\t/*\tp\tq\tr\ts\tt\tu\tv\tw\tx\ty\tz\t{\t|\t}\t~  DL */\n\t   PI, PI, PI, PI, PI, PI, PI, PI, PI, PI, PI,\tI,\tI,\tI,\tI,\t0\n\t};\n\nstatic int isPrintable( int ch )\n\t{\n\tif( ch >= 128 || !( charFlags[ ch ] & P ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\nstatic int isIA5( int ch )\n\t{\n\tif( ch >= 128 || !( charFlags[ ch ] & I ) )\n\t\treturn( FALSE );\n\treturn( TRUE );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tConfig File Read Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Files coming from DOS/Windows systems may have a ^Z (the CP/M EOF char)\n   at the end, so we need to filter this out */\n\n#define CPM_EOF\t0x1A\t\t/* ^Z = CPM EOF char */\n\n/* The maximum input line length */\n\n#define MAX_LINESIZE\t512\n\n/* Read a line of text from the config file */\n\nstatic int lineNo;\n\nstatic int readLine( FILE *file, char *buffer )\n\t{\n\tint bufCount = 0, ch;\n\n\t/* Skip whitespace */\n\twhile( ( ( ch = getc( file ) ) == ' ' || ch == '\\t' ) && !feof( file ) );\n\n\t/* Get a line into the buffer */\n\twhile( ch != '\\r' && ch != '\\n' && ch != CPM_EOF && !feof( file ) )\n\t\t{\n\t\t/* Check for an illegal char in the data.  Note that we don't just\n\t\t   check for chars with high bits set because these are legal in\n\t\t   non-ASCII strings */\n\t\tif( !isprint( ch ) )\n\t\t\t{\n\t\t\tprintf( \"Bad character '%c' in config file line %d.\\n\",\n\t\t\t\t\tch, lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\t/* Check to see if it's a comment line */\n\t\tif( ch == '#' && !bufCount )\n\t\t\t{\n\t\t\t/* Skip comment section and trailing whitespace */\n\t\t\twhile( ch != '\\r' && ch != '\\n' && ch != CPM_EOF && !feof( file ) )\n\t\t\t\tch = getc( file );\n\t\t\tbreak;\n\t\t\t}\n\n\t\t/* Make sure that the line is of the correct length */\n\t\tif( bufCount > MAX_LINESIZE )\n\t\t\t{\n\t\t\tprintf( \"Config file line %d too long.\\n\", lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse\n\t\t\tif( ch )\t/* Can happen if we read a binary file */\n\t\t\t\tbuffer[ bufCount++ ] = ch;\n\n\t\t/* Get next character */\n\t\tch = getc( file );\n\t\t}\n\n\t/* If we've just passed a CR, check for a following LF */\n\tif( ch == '\\r' )\n\t\t{\n\t\tif( ( ch = getc( file ) ) != '\\n' )\n\t\t\tungetc( ch, file );\n\t\t}\n\n\t/* Skip trailing whitespace and add der terminador */\n\twhile( bufCount > 0 &&\n\t\t   ( ( ch = buffer[ bufCount - 1 ] ) == ' ' || ch == '\\t' ) )\n\t\tbufCount--;\n\tbuffer[ bufCount ] = '\\0';\n\n\t/* Handle special-case of ^Z if file came off an MSDOS system */\n\tif( ch == CPM_EOF )\n\t\t{\n\t\twhile( !feof( file ) )\n\t\t\t{\n\t\t\t/* Keep going until we hit the true EOF (or some sort of error) */\n\t\t\t( void ) getc( file );\n\t\t\t}\n\t\t}\n\n\treturn( ferror( file ) ? FALSE : TRUE );\n\t}\n\n/* Process an OID specified as space-separated decimal or hex digits */\n\nstatic int processOID( OIDINFO *oidInfo, char *string )\n\t{\n\tBYTE binaryOID[ MAX_OID_SIZE ];\n\tlong value;\n\tint firstValue = -1, valueIndex = 0, oidIndex = 3;\n\n\tmemset( binaryOID, 0, MAX_OID_SIZE );\n\tbinaryOID[ 0 ] = OID;\n\twhile( *string && oidIndex < MAX_OID_SIZE )\n\t\t{\n\t\tif( oidIndex >= MAX_OID_SIZE - 4 )\n\t\t\t{\n\t\t\tprintf( \"Excessively long OID in config file line %d.\\n\",\n\t\t\t\t\tlineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( sscanf( string, \"%8ld\", &value ) != 1 || value < 0 )\n\t\t\t{\n\t\t\tprintf( \"Invalid value in config file line %d.\\n\", lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\tif( valueIndex == 0 )\n\t\t\t{\n\t\t\tfirstValue = value;\n\t\t\tvalueIndex++;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( valueIndex == 1 )\n\t\t\t\t{\n\t\t\t\tif( firstValue < 0 || firstValue > 2 || value < 0 || \\\n\t\t\t\t\t( ( firstValue < 2 && value > 39 ) || \\\n\t\t\t\t\t  ( firstValue == 2 && value > 175 ) ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Invalid value in config file line %d.\\n\",\n\t\t\t\t\t\t\tlineNo );\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t\t}\n\t\t\t\tbinaryOID[ 2 ] = ( firstValue * 40 ) + ( int ) value;\n\t\t\t\tvalueIndex++;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tint hasHighBits = FALSE;\n\n\t\t\t\tif( value >= 0x200000L )\t\t\t\t\t/* 2^21 */\n\t\t\t\t\t{\n\t\t\t\t\tbinaryOID[ oidIndex++ ] = 0x80 | ( int ) ( value >> 21 );\n\t\t\t\t\tvalue %= 0x200000L;\n\t\t\t\t\thasHighBits = TRUE;\n\t\t\t\t\t}\n\t\t\t\tif( ( value >= 0x4000 ) || hasHighBits )\t/* 2^14 */\n\t\t\t\t\t{\n\t\t\t\t\tbinaryOID[ oidIndex++ ] = 0x80 | ( int ) ( value >> 14 );\n\t\t\t\t\tvalue %= 0x4000;\n\t\t\t\t\thasHighBits = TRUE;\n\t\t\t\t\t}\n\t\t\t\tif( ( value >= 0x80 ) || hasHighBits )\t\t/* 2^7 */\n\t\t\t\t\t{\n\t\t\t\t\tbinaryOID[ oidIndex++ ] = 0x80 | ( int ) ( value >> 7 );\n\t\t\t\t\tvalue %= 128;\n\t\t\t\t\t}\n\t\t\t\tbinaryOID[ oidIndex++ ] = ( int ) value;\n\t\t\t\t}\n\t\t\t}\n\t\twhile( *string && isdigit( byteToInt( *string ) ) )\n\t\t\tstring++;\n\t\tif( *string && *string++ != ' ' )\n\t\t\t{\n\t\t\tprintf( \"Invalid OID string in config file line %d.\\n\", lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\tbinaryOID[ 1 ] = oidIndex - 2;\n\tmemcpy( oidInfo->oid, binaryOID, oidIndex );\n\toidInfo->oidLength = oidIndex;\n\n\treturn( TRUE );\n\t}\n\nstatic int processHexOID( OIDINFO *oidInfo, char *string )\n\t{\n\tint value, index = 0;\n\n\twhile( *string && index < MAX_OID_SIZE - 1 )\n\t\t{\n\t\tif( sscanf( string, \"%4x\", &value ) != 1 || value < 0 || value > 255 )\n\t\t\t{\n\t\t\tprintf( \"Invalid hex value in config file line %d.\\n\", lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\toidInfo->oid[ index++ ] = value;\n\t\tstring += 2;\n\t\tif( *string && *string++ != ' ' )\n\t\t\t{\n\t\t\tprintf( \"Invalid hex string in config file line %d.\\n\", lineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\t\t}\n\toidInfo->oid[ index ] = 0;\n\toidInfo->oidLength = index;\n\tif( index >= MAX_OID_SIZE - 1 )\n\t\t{\n\t\tprintf( \"OID value in config file line %d too long.\\n\", lineNo );\n\t\treturn( FALSE );\n\t\t}\n\treturn( TRUE );\n\t}\n\n/* Read a config file */\n\nstatic int readConfig( const char *path, const int isDefaultConfig )\n\t{\n\tOIDINFO dummyOID = { NULL, \"Dummy\", 0, \"Dummy\", \"Dummy\", 1 }, *oidPtr;\n\tFILE *file;\n\tint seenHexOID = FALSE;\n\tchar buffer[ MAX_LINESIZE ];\n\tint status;\n\n\t/* Try and open the config file */\n\tif( ( file = fopen( path, \"rb\" ) ) == NULL )\n\t\t{\n\t\t/* If we can't open the default config file, issue a warning but\n\t\t   continue anyway */\n\t\tif( isDefaultConfig )\n\t\t\t{\n\t\t\tputs( \"Cannot open config file 'dumpasn1.cfg', which should be in the same\" );\n\t\t\tputs( \"directory as the dumpasn1 program, a standard system directory, or\" );\n\t\t\tputs( \"in a location pointed to by the DUMPASN1_PATH environment variable.\" );\n\t\t\tputs( \"Operation will continue without the ability to display Object \" );\n\t\t\tputs( \"Identifier information.\" );\n\t\t\tputs( \"\" );\n\t\t\tputs( \"If the config file is located elsewhere, you can set the environment\" );\n\t\t\tputs( \"variable DUMPASN1_PATH to the path to the file.\" );\n\t\t\treturn( TRUE );\n\t\t\t}\n\n\t\tprintf( \"Cannot open config file '%s'.\\n\", path );\n\t\treturn( FALSE );\n\t\t}\n\n\t/* Add the new config entries at the appropriate point in the OID list */\n\tif( oidList == NULL )\n\t\toidPtr = &dummyOID;\n\telse\n\t\tfor( oidPtr = oidList; oidPtr->next != NULL; oidPtr = oidPtr->next );\n\n\t/* Read each line in the config file */\n\tlineNo = 1;\n\twhile( ( status = readLine( file, buffer ) ) == TRUE && !feof( file ) )\n\t\t{\n\t\t/* If it's a comment line, skip it */\n\t\tif( !*buffer )\n\t\t\t{\n\t\t\tlineNo++;\n\t\t\tcontinue;\n\t\t\t}\n\n\t\t/* Check for an attribute tag */\n\t\tif( !strncmp( buffer, \"OID = \", 6 ) )\n\t\t\t{\n\t\t\t/* Make sure that all of the required attributes for the current\n\t\t\t   OID are present */\n\t\t\tif( oidPtr->description == NULL )\n\t\t\t\t{\n\t\t\t\tprintf( \"OID ending on config file line %d has no \"\n\t\t\t\t\t\t\"description attribute.\\n\", lineNo - 1 );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Allocate storage for the new OID */\n\t\t\tif( ( oidPtr->next = ( OIDINFO * ) malloc( sizeof( OIDINFO ) ) ) == NULL )\n\t\t\t\t{\n\t\t\t\tputs( \"Out of memory.\" );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\toidPtr = oidPtr->next;\n\t\t\tif( oidList == NULL )\n\t\t\t\toidList = oidPtr;\n\t\t\tmemset( oidPtr, 0, sizeof( OIDINFO ) );\n\n\t\t\t/* Add the new OID */\n\t\t\tif( !strncmp( buffer + 6, \"06\", 2 ) )\n\t\t\t\t{\n\t\t\t\tseenHexOID = TRUE;\n\t\t\t\tif( !processHexOID( oidPtr, buffer + 6 ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !processOID( oidPtr, buffer + 6 ) )\n\t\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\n\t\t\t/* Check that this OID isn't already present in the OID list.\n\t\t\t   This is a quick-and-dirty n^2 algorithm so it's not enabled\n\t\t\t   by default */\n#if 0\n\t\t\t{\n\t\t\tOIDINFO *oidCursor;\n\n\t\t\tfor( oidCursor = oidList; oidCursor->next != NULL; oidCursor = oidCursor->next )\n\t\t\t\t{\n\t\t\t\tif( oidCursor->oidLength == oidPtr->oidLength && \\\n\t\t\t\t\t!memcmp( oidCursor->oid, oidPtr->oid, oidCursor->oidLength ) )\n\t\t\t\t\t{\n\t\t\t\t\tprintf( \"Duplicate OID '%s' at line %d.\\n\",\n\t\t\t\t\t\t\tbuffer, lineNo );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif /* 0 */\n\t\t\t}\n\t\telse if( !strncmp( buffer, \"Description = \", 14 ) )\n\t\t\t{\n\t\t\tif( oidPtr->description != NULL )\n\t\t\t\t{\n\t\t\t\tprintf( \"Duplicate OID description in config file line %d.\\n\",\n\t\t\t\t\t\tlineNo );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !addAttribute( &oidPtr->description, buffer + 14 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse if( !strncmp( buffer, \"Comment = \", 10 ) )\n\t\t\t{\n\t\t\tif( oidPtr->comment != NULL )\n\t\t\t\t{\n\t\t\t\tprintf( \"Duplicate OID comment in config file line %d.\\n\",\n\t\t\t\t\t\tlineNo );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\tif( !addAttribute( &oidPtr->comment, buffer + 10 ) )\n\t\t\t\treturn( FALSE );\n\t\t\t}\n\t\telse if( !strncmp( buffer, \"Warning\", 7 ) )\n\t\t\t{\n\t\t\tif( oidPtr->warn )\n\t\t\t\t{\n\t\t\t\tprintf( \"Duplicate OID warning in config file line %d.\\n\",\n\t\t\t\t\t\tlineNo );\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\toidPtr->warn = TRUE;\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tprintf( \"Unrecognised attribute '%s', line %d.\\n\", buffer,\n\t\t\t\t\tlineNo );\n\t\t\treturn( FALSE );\n\t\t\t}\n\n\t\tlineNo++;\n\t\t}\n\tfclose( file );\n\n\t/* If we're processing an old-style config file, tell the user to\n\t   upgrade */\n\tif( seenHexOID )\n\t\t{\n\t\tputs( \"\\nWarning: Use of old-style hex OIDs detected in \"\n\t\t\t  \"configuration file, please\\n         update your dumpasn1 \"\n\t\t\t  \"configuration file.\\n\" );\n\t\t}\n\n\treturn( status );\n\t}\n\n/* Check for the existence of a config file path (access() isn't available\n   on all systems) */\n\nstatic int testConfigPath( const char *path )\n\t{\n\tFILE *file;\n\n\t/* Try and open the config file */\n\tif( ( file = fopen( path, \"rb\" ) ) == NULL )\n\t\treturn( FALSE );\n\tfclose( file );\n\n\treturn( TRUE );\n\t}\n\n/* Build a config path by substituting environment strings for $NAMEs */\n\nstatic void buildConfigPath( char *path, const char *pathTemplate )\n\t{\n\tchar pathBuffer[ FILENAME_MAX ], newPath[ FILENAME_MAX ];\n\tint pathLen, pathPos = 0, newPathPos = 0;\n\n\t/* Add the config file name at the end */\n\tstrcpy( pathBuffer, pathTemplate );\n\tstrcat( pathBuffer, CONFIG_NAME );\n\tpathLen = strlen( pathBuffer );\n\n\twhile( pathPos < pathLen )\n\t\t{\n\t\tchar *strPtr;\n\t\tint substringSize;\n\n\t\t/* Find the next $ and copy the data before it to the new path */\n\t\tif( ( strPtr = strstr( pathBuffer + pathPos, \"$\" ) ) != NULL )\n\t\t\tsubstringSize = ( int ) ( ( strPtr - pathBuffer ) - pathPos );\n\t\telse\n\t\t\tsubstringSize = pathLen - pathPos;\n\t\tif( substringSize > 0 )\n\t\t\t{\n\t\t\tmemcpy( newPath + newPathPos, pathBuffer + pathPos,\n\t\t\t\t\tsubstringSize );\n\t\t\t}\n\t\tnewPathPos += substringSize;\n\t\tpathPos += substringSize;\n\n\t\t/* Get the environment string for the $NAME */\n\t\tif( strPtr != NULL )\n\t\t\t{\n\t\t\tchar envName[ MAX_LINESIZE ], *envString;\n\t\t\tint i;\n\n\t\t\t/* Skip the '$', find the end of the $NAME, and copy the name\n\t\t\t   into an internal buffer */\n\t\t\tpathPos++;\t/* Skip the $ */\n\t\t\tfor( i = 0; !isEnvTerminator( pathBuffer[ pathPos + i ] ); i++ );\n\t\t\tmemcpy( envName, pathBuffer + pathPos, i );\n\t\t\tenvName[ i ] = '\\0';\n\n\t\t\t/* Get the env.string and copy it over */\n\t\t\tif( ( envString = getenv( envName ) ) != NULL )\n\t\t\t\t{\n\t\t\t\tconst int envStrLen = strlen( envString );\n\n\t\t\t\tif( newPathPos + envStrLen < FILENAME_MAX - 2 )\n\t\t\t\t\t{\n\t\t\t\t\tmemcpy( newPath + newPathPos, envString, envStrLen );\n\t\t\t\t\tnewPathPos += envStrLen;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tpathPos += i;\n\t\t\t}\n\t\t}\n\tnewPath[ newPathPos ] = '\\0';\t/* Add der terminador */\n\n\t/* Copy the new path to the output */\n\tstrcpy( path, newPath );\n\t}\n\n/* Read the global config file */\n\nstatic int readGlobalConfig( const char *path )\n\t{\n\tchar buffer[ FILENAME_MAX ];\n\tchar *searchPos = ( char * ) path, *namePos, *lastPos = NULL;\n#ifdef __UNIX__\n\tchar *envPath;\n#endif /* __UNIX__ */\n#ifdef __WIN32__\n\tchar filePath[ _MAX_PATH ];\n\tDWORD count;\n#endif /* __WIN32__ */\n\tint i;\n\n\t/* First, try and find the config file in the same directory as the\n\t   executable by walking down the path until we find the last occurrence\n\t   of the program name.  This requires that argv[0] be set up properly,\n\t   which isn't the case if Unix search paths are being used and is a\n\t   bit hit-and-miss under Windows where the contents of argv[0] depend\n\t   on how the program is being executed.  To avoid this we perform some\n\t   Windows-specific processing to try and find the path to the\n\t   executable if we can't otherwise find it */\n\tdo\n\t\t{\n\t\tnamePos = lastPos;\n\t\tlastPos = strstr( searchPos, \"dumpasn1\" );\n\t\tif( lastPos == NULL )\n\t\t\tlastPos = strstr( searchPos, \"DUMPASN1\" );\n\t\tsearchPos = lastPos + 1;\n\t\t}\n\twhile( lastPos != NULL );\n#ifdef __UNIX__\n\tif( namePos == NULL && ( namePos = strrchr( path, '/' ) ) != NULL )\n\t\t{\n\t\tconst int endPos = ( int ) ( namePos - path ) + 1;\n\n\t\t/* If the executable isn't called dumpasn1, we won't be able to find\n\t\t   it with the above code, fall back to looking for directory\n\t\t   separators.  This requires a system where the only separator is\n\t\t   the directory separator (ie it doesn't work for Windows or most\n\t\t   mainframe environments) */\n\t\tif( endPos < FILENAME_MAX - 13 )\n\t\t\t{\n\t\t\tmemcpy( buffer, path, endPos );\n\t\t\tstrcpy( buffer + endPos, CONFIG_NAME );\n\t\t\tif( testConfigPath( buffer ) )\n\t\t\t\treturn( readConfig( buffer, TRUE ) );\n\t\t\t}\n\n\t\t/* That didn't work, try the absolute locations and $PATH */\n\t\tnamePos = NULL;\n\t\t}\n#endif /* __UNIX__ */\n\tif( strlen( path ) < FILENAME_MAX - 13 && namePos != NULL )\n\t\t{\n\t\tstrcpy( buffer, path );\n\t\tstrcpy( buffer + ( int ) ( namePos - ( char * ) path ), CONFIG_NAME );\n\t\tif( testConfigPath( buffer ) )\n\t\t\treturn( readConfig( buffer, TRUE ) );\n\t\t}\n\n\t/* Now try each of the possible absolute locations for the config file */\n\tfor( i = 0; configPaths[ i ] != NULL; i++ )\n\t\t{\n\t\tbuildConfigPath( buffer, configPaths[ i ] );\n\t\tif( testConfigPath( buffer ) )\n\t\t\treturn( readConfig( buffer, TRUE ) );\n\t\t}\n\n#ifdef __UNIX__\n\t/* On Unix systems we can also search for the config file on $PATH */\n\tif( ( envPath = getenv( \"PATH\" ) ) != NULL )\n\t\t{\n\t\tchar *pathPtr = strtok( envPath, \":\" );\n\n\t\tdo\n\t\t\t{\n\t\t\tsprintf( buffer, \"%s/%s\", pathPtr, CONFIG_NAME );\n\t\t\tif( testConfigPath( buffer ) )\n\t\t\t\treturn( readConfig( buffer, TRUE ) );\n\t\t\tpathPtr = strtok( NULL, \":\" );\n\t\t\t}\n\t\twhile( pathPtr != NULL );\n\t\t}\n#endif /* __UNIX__ */\n#ifdef __WIN32__\n\t/* Under Windows we can use GetModuleFileName() to find the location of\n\t   the program */\n\tcount = GetModuleFileName ( NULL, filePath, _MAX_PATH );\n\tif( count > 0 )\n\t\t{\n\t\tchar *progNameStart = strrchr( filePath, '\\\\' );\n\t\tif( progNameStart != NULL && \\\n\t\t\t( progNameStart - filePath ) < _MAX_PATH - 13 )\n\t\t\t{\n\t\t\t/* Replace the program name with the config file name */\n\t\t\tstrcpy( progNameStart + 1, CONFIG_NAME );\n\t\t\tif( testConfigPath( filePath ) )\n\t\t\t\treturn( readConfig( filePath, TRUE ) );\n\t\t\t}\n\t\t}\n#endif /*__WIN32__*/\n\n\n\t/* Default to just the config name (which should fail as it was the\n\t   first entry in configPaths[]).  readConfig() will display the\n\t   appropriate warning */\n\treturn( readConfig( CONFIG_NAME, TRUE ) );\n\t}\n\n/* Free the in-memory config data */\n\nstatic void freeConfig( void )\n\t{\n\tOIDINFO *oidPtr = oidList;\n\n\twhile( oidPtr != NULL )\n\t\t{\n\t\tOIDINFO *oidCursor = oidPtr;\n\n\t\toidPtr = oidPtr->next;\n\t\tif( oidCursor->comment != NULL )\n\t\t\tfree( oidCursor->comment );\n\t\tif( oidCursor->description != NULL )\n\t\t\tfree( oidCursor->description );\n\t\tfree( oidCursor );\n\t\t}\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\tOutput/Formatting Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n#ifdef __OS390__\n\nstatic int asciiToEbcdic( const int ch )\n\t{\n\tchar convBuffer[ 2 ];\n\n\tconvBuffer[ 0 ] = ch;\n\tconvBuffer[ 1 ] = '\\0';\n\t__atoe( convBuffer ); /* Convert ASCII to EBCDIC for 390 */\n\treturn( convBuffer[ 0 ] );\n\t}\n#endif /* __OS390__ */\n\n/* Output formatted text */\n\nstatic int printString( const int level, const char *format, ... )\n\t{\n\tva_list argPtr;\n\tint length;\n\n\tif( level >= maxNestLevel )\n\t\treturn( 0 );\n\tva_start( argPtr, format );\n\tlength = vfprintf( output, format, argPtr );\n\tva_end( argPtr );\n\n\treturn( length );\n\t}\n\n/* Indent a string by the appropriate amount */\n\nstatic void doIndent( const int level )\n\t{\n\tint i;\n\n\tif( level >= maxNestLevel )\n\t\treturn;\n\tfor( i = 0; i < level; i++ )\n\t\t{\n\t\tfprintf( output, printDots ? \". \" : \\\n\t\t\t\t\t\t shallowIndent ? \" \" : \"  \" );\n\t\t}\n\t}\n\n/* Complain about an error in the ASN.1 object */\n\nstatic void complain( const char *message, const int messageParam,\n\t\t\t\t\t  const int level )\n\t{\n\tif( level < maxNestLevel )\n\t\t{\n\t\tif( !doPure )\n\t\t\tfprintf( output, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 1 );\n\t\t}\n\tfputs( \"Error: \", output );\n\tfprintf( output, message, messageParam );\n\tfputs( \".\\n\", output );\n\tnoErrors++;\n\t}\n\nstatic void complainLength( const ASN1_ITEM *item, const int level )\n\t{\n#if 0\n\t/* This is a general error so we don't indent the message to the level\n\t   of the item */\n#else\n\tif( level < maxNestLevel )\n\t\t{\n\t\tif( !doPure )\n\t\t\tfprintf( output, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 1 );\n\t\t}\n#endif /* 0 */\n\tfprintf( output, \"Error: %s has invalid length %ld.\\n\",\n\t\t\t idstr( item->tag ), item->length );\n\tnoErrors++;\n\t}\n\nstatic void complainLengthCanonical( const ASN1_ITEM *item, const int level )\n\t{\n\tint i;\n\n#if 0\n\t/* This is a general error so we don't indent the message to the level\n\t   of the item */\n#else\n\tif( level < maxNestLevel )\n\t\t{\n\t\tif( !doPure )\n\t\t\tfprintf( output, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 1 );\n\t\t}\n#endif /* 0 */\n\tfputs( \"Error: Length '\", output );\n\tfor( i = item->nonCanonical; i < item->headerSize; i++ )\n\t\t{\n\t\tfprintf( output, \"%02X\", item->header[ i ] );\n\t\tif( i < item->headerSize - 1 )\n\t\t\tfputc( ' ', output );\n\t\t}\n\tfputs( \"' has non-canonical encoding.\\n\", output );\n\tnoErrors++;\n\t}\n\nstatic void complainInt( const BYTE *intValue, const int level )\n\t{\n\tif( level < maxNestLevel )\n\t\t{\n\t\tif( !doPure )\n\t\t\tfprintf( output, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 1 );\n\t\t}\n\tfprintf( output, \"Error: Integer '%02X %02X ...' has non-DER encoding.\\n\",\n\t\t\t intValue[ 0 ], intValue[ 1 ] );\n\tnoErrors++;\n\t}\n\nstatic void complainEOF( const int level, const int missingBytes )\n\t{\n\tprintString( level, \"%c\", '\\n' );\n\tcomplain( ( missingBytes > 1 ) ? \\\n\t\t\t\t\"Unexpected EOF, %d bytes missing\" : \\\n\t\t\t\t\"Unexpected EOF, 1 byte missing\", missingBytes, level );\n\t}\n\n/* Adjust the nesting-level value to make sure that we don't go off the edge\n   of the screen via doIndent() when we're displaying a text or hex dump of\n   data */\n\nstatic int adjustLevel( const int level, const int maxLevel )\n\t{\n\t/* If we've been passed a very large pseudo-level to disable output then\n\t   we don't try and override this */\n\tif( level >= 1000 )\n\t\treturn( level );\n\n\t/* If we've exceeded the maximum level for display, cap the value at\n\t   maxLevel to make sure that we don't end up indenting output off the\n\t   edge of the screen */\n\tif( level > maxLevel )\n\t\treturn( maxLevel );\n\n\treturn( level );\n\t}\n\n#if defined( __WIN32__ ) || defined( __UNIX__ ) || defined( __OS390__ )\n\n/* Try and display to display a Unicode character.  This is pretty hit and\n   miss, and if it fails nothing is displayed.  To try and detect this we\n   use wcstombs() to see if anything can be displayed, if it can't we drop\n   back to trying to display the data as non-Unicode */\n\nstatic int displayUnicode( const wchar_t wCh, const int level )\n\t{\n\tchar outBuf[ 8 ];\n\tint outLen;\n\n\t/* Check whether we can display this character */\n\toutLen = wcstombs( outBuf, &wCh, 8 );\n\tif( outLen < 1 )\n\t\t{\n\t\t/* Tell the caller that this can't be displayed as Unicode */\n\t\treturn( FALSE );\n\t\t}\n\n#if defined( __WIN32__ )\n\tif( level < maxNestLevel )\n\t\t{\n\t\tint oldmode;\n\n\t\t/* To output Unicode to the Win32 console we need to switch the\n\t\t   output stream to Unicode-16 mode, but the following may also\n\t\t   depend on which code page is currently set for the console, which\n\t\t   font is being used, and the phase of the moon (including the moons\n\t\t   for Mars and Jupiter) */\n\t\tfflush( output );\n\t\toldmode = _setmode( fileno( output ), _O_U16TEXT );\n\t\tfputwc( wCh, output );\n\t\t_setmode( fileno( output ), oldmode );\n\t\t}\n#elif defined( __UNIX__ ) && !( defined( __MACH__ ) || defined( __OpenBSD__ ) )\n\t/* Unix environments are even more broken than Win32, like Win32 the\n\t   output differentiates between char and widechar output, but there's\n\t   no easy way to deal with this.  In theory fwide() can set it, but\n\t   it's a one-way function, once we've set it a particular way we can't\n\t   go back (exactly what level of braindamage it takes to have an\n\t   implementation function like this is a mystery).  Other sources\n\t   suggest using setlocale() tricks, printf() with \"%lc\" or \"%ls\" as the\n\t   format specifier, and others, but none of these seem to work properly\n\t   either */\n\tif( level < maxNestLevel )\n\t\t{\n#if 0\n\t\tsetlocale( LC_ALL, \"\" );\n\t\tfputwc( wCh, output );\n#elif 1\n\t\t/* This (and the \"%ls\" variant below) seem to be the least broken\n\t\t   options */\n\t\tfprintf( output, \"%lc\", wCh );\n#elif 0\n\t\twchar_t wChString[ 2 ];\n\n\t\twChString[ 0 ] = wCh;\n\t\twChString[ 1 ] = 0;\n\t\tfprintf( output, \"%ls\", wChString );\n#else\n\t\tif( fwide( output, 1 ) > 0 )\n\t\t\t{\n\t\t\tfputwc( wCh, output );\n\t\t\tfwide( output, -1 );\n\t\t\t}\n\t\telse\n\t\t\tfputc( wCh, output );\n#endif\n\t\t}\n#else\n  #ifdef __OS390__\n\tif( level < maxNestLevel )\n\t\t{\n\t\tchar *p;\n\n\t\t/* This could use some improvement */\n\t\tfor( p = outBuf; *p != '\\0'; p++ )\n\t\t\t*p = asciiToEbcdic( *p );\n\t\t}\n  #endif /* IBM ASCII -> EBCDIC conversion */\n\tprintString( level, \"%s\", outBuf );\n#endif /* OS-specific charset handling */\n\n\treturn( TRUE );\n\t}\n#endif /* __WIN32__ || __UNIX__ || __OS390__ */\n\n/* Display an integer value */\n\nstatic void printValue( FILE *inFile, const int valueLength,\n\t\t\t\t\t    const int level )\n\t{\n\tBYTE intBuffer[ 2 ];\n\tlong value;\n\tint warnNegative = FALSE, warnNonDER = FALSE, i;\n\n\tvalue = getc( inFile );\n\tif( value == EOF )\n\t\t{\n\t\tcomplainEOF( level, valueLength );\n\t\treturn;\n\t\t}\n\tif( value & 0x80 )\n\t\twarnNegative = TRUE;\n\tfor( i = 0; i < valueLength - 1; i++ )\n\t\t{\n\t\tconst int ch = getc( inFile );\n\n\t\tif( ch == EOF )\n\t\t\t{\n\t\t\tcomplainEOF( level, valueLength - i );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* Check for the first 9 bits being identical */\n\t\tif( i == 0 )\n\t\t\t{\n\t\t\tif( ( value == 0x00 ) && ( ( ch & 0x80 ) == 0x00 ) )\n\t\t\t\twarnNonDER = TRUE;\n\t\t\tif( ( value == 0xFF ) && ( ( ch & 0x80 ) == 0x80 ) )\n\t\t\t\twarnNonDER = TRUE;\n\t\t\tif( warnNonDER )\n\t\t\t\t{\n\t\t\t\tintBuffer[ 0 ] = ( int ) value;\n\t\t\t\tintBuffer[ 1 ] = ch;\n\t\t\t\t}\n\t\t\t}\n\t\tvalue = ( value << 8 ) | ch;\n\t\t}\n\tfPos += valueLength;\n\n\t/* Display the integer value and any associated warnings.  Note that\n\t   this will display an incorrectly-encoded integer as a negative value\n\t   rather than the unsigned value that was probably intended to\n\t   emphasise that it's incorrect */\n\tprintString( level, \" %ld\\n\", value );\n\tif( warnNonDER )\n\t\tcomplainInt( intBuffer, level );\n\tif( warnNegative )\n\t\tcomplain( \"Integer is encoded as a negative value\", 0, level );\n\t}\n\n/* Dump data as a string of hex digits up to a maximum of 128 bytes */\n\nstatic void dumpHex( FILE *inFile, long length, int level,\n\t\t\t\t\t const int isInteger )\n\t{\n\tconst int lineLength = ( dumpText ) ? 8 : 16;\n\tconst int displayHeaderLength = ( ( doPure ) ? 0 : INDENT_SIZE ) + 2;\n\tBYTE intBuffer[ 2 ];\n\tchar printable[ 9 ];\n\tlong noBytes = length;\n\tint warnPadding = FALSE, warnNegative = isInteger, singleLine = FALSE;\n\tint displayLength = displayHeaderLength, prevCh = -1, i;\n\n\tmemset( printable, 0, 9 );\n\n\tdisplayLength += ( length < lineLength ) ? ( length * 3 ) : \\\n\t\t\t\t\t\t\t\t\t\t\t   ( lineLength * 3 );\n\n\t/* Check if the size of the displayed data (LHS status info + hex data)\n\t   plus the indent-level of spaces will fit into a single line behind\n\t   the initial label, e.g. \"INTEGER\" */\n\tif( displayHeaderLength + ( level * 2 ) + ( length * 3 ) < outputWidth )\n\t\tsingleLine = TRUE;\n\n\t/* By default we only output a maximum of 128 bytes to avoid dumping\n\t   huge amounts of data, however if what's left is a partial lines'\n\t   worth then we output that as well to avoid displaying a line of text\n\t   indicating that less than a lines' worth of data remains to be\n\t   displayed */\n\tif( noBytes >= 128 + lineLength && !printAllData )\n\t\tnoBytes = 128;\n\n\t/* Make sure that the indent level doesn't push the text off the edge of\n\t   the screen */\n\tlevel = adjustLevel( level, ( outputWidth - displayLength ) / 2 );\n\tfor( i = 0; i < noBytes; i++ )\n\t\t{\n\t\tint ch;\n\n\t\tif( !( i % lineLength ) )\n\t\t\t{\n\t\t\tif( singleLine )\n\t\t\t\tprintString( level, \"%c\", ' ' );\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( dumpText )\n\t\t\t\t\t{\n\t\t\t\t\t/* If we're dumping text alongside the hex data, print\n\t\t\t\t\t   the accumulated text string */\n\t\t\t\t\tprintString( level, \"%s\", \"    \" );\n\t\t\t\t\tprintString( level, \"%s\", printable );\n\t\t\t\t\t}\n\t\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\t\tif( !doPure )\n\t\t\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\t\t\tdoIndent( level + 1 );\n\t\t\t\t}\n\t\t\t}\n\t\tch = getc( inFile );\n\t\tif( ch == EOF )\n\t\t\t{\n\t\t\tcomplainEOF( level, length - i );\n\t\t\treturn;\n\t\t\t}\n\t\tprintString( level, \"%s%02X\", ( i % lineLength ) ? \" \" : \"\", ch );\n\t\tprintable[ i % 8 ] = ( ch >= ' ' && ch < 127 ) ? ch : '.';\n\t\tfPos++;\n\n\t\t/* If we need to check for negative values, check this now */\n\t\tif( i == 0 )\n\t\t\t{\n\t\t\tprevCh = ch;\n\t\t\tif( !( ch & 0x80 ) )\n\t\t\t\twarnNegative = FALSE;\n\t\t\t}\n\t\tif( i == 1 )\n\t\t\t{\n\t\t\t/* Check for the first 9 bits being identical */\n\t\t\tif( ( prevCh == 0x00 ) && ( ( ch & 0x80 ) == 0x00 ) )\n\t\t\t\twarnPadding = TRUE;\n\t\t\tif( ( prevCh == 0xFF ) && ( ( ch & 0x80 ) == 0x80 ) )\n\t\t\t\twarnPadding = TRUE;\n\t\t\tif( warnPadding )\n\t\t\t\t{\n\t\t\t\tintBuffer[ 0 ] = prevCh;\n\t\t\t\tintBuffer[ 1 ] = ch;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( dumpText )\n\t\t{\n\t\t/* Print any remaining text */\n\t\ti %= lineLength;\n\t\tprintable[ i ] = '\\0';\n\t\twhile( i < lineLength )\n\t\t\t{\n\t\t\tprintString( level, \"%s\", \"   \" );\n\t\t\ti++;\n\t\t\t}\n\t\tprintString( level, \"%s\", \"    \" );\n\t\tprintString( level, \"%s\", printable );\n\t\t}\n\tif( length >= 128 + lineLength && !printAllData )\n\t\t{\n\t\tlength -= 128;\n\t\tprintString( level, \"%c\", '\\n' );\n\t\tif( !doPure )\n\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 5 );\n\t\tprintString( level, \"[ Another %ld bytes skipped ]\", length );\n\t\tfPos += length;\n\t\tif( useStdin )\n\t\t\t{\n\t\t\tint ch;\n\n\t\t\twhile( length-- )\n\t\t\t\t{\n\t\t\t\tch = getc( inFile );\n\t\t\t\tif( ch == EOF )\n\t\t\t\t\t{\n\t\t\t\t\tcomplainEOF( level, length - i );\n\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tfseek( inFile, length, SEEK_CUR );\n\t\t}\n\tprintString( level, \"%c\", '\\n' );\n\n\tif( isInteger )\n\t\t{\n\t\tif( warnPadding )\n\t\t\tcomplainInt( intBuffer, level );\n\t\tif( warnNegative )\n\t\t\tcomplain( \"Integer is encoded as a negative value\", 0, level );\n\t\t}\n\t}\n\n/* Convert a binary OID to its string equivalent */\n\nstatic int oidToString( char *textOID, int *textOIDlength,\n\t\t\t\t\t\tconst BYTE *oid, const int oidLength )\n\t{\n\tBYTE uuidBuffer[ 32 ];\n\tlong value;\n\tint length = 0, uuidBufPos = -1, uuidBitCount = 5, i;\n\tint validEncoding = TRUE, isUUID = FALSE;\n\n\tfor( i = 0, value = 0; i < oidLength; i++ )\n\t\t{\n\t\tconst BYTE data = oid[ i ];\n\t\tconst long valTmp = value << 7;\n\n\t\t/* Pick apart the encoding.  We keep going after hitting an encoding\n\t\t   error at the start of an arc because the overall length is\n\t\t   bounded and we may still be able to recover something worth\n\t\t   printing */\n\t\tif( value == 0 && data == 0x80 )\n\t\t\t{\n\t\t\t/* Invalid leading zero value, 0x80 & 0x7F == 0 */\n\t\t\tvalidEncoding = FALSE;\n\t\t\t}\n\t\tif( isUUID )\n\t\t\t{\n\t\t\tvalue = 1;\t/* Set up dummy value since we're bypassing normal read */\n\t\t\tif( uuidBitCount == 0 )\n\t\t\t\tuuidBuffer[ uuidBufPos ] = data << 1;\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( uuidBufPos >= 0 )\n\t\t\t\t\tuuidBuffer[ uuidBufPos ] |= ( data & 0x7F ) >> ( 7 - uuidBitCount );\n\t\t\t\tuuidBufPos++;\n\t\t\t\tif( uuidBitCount < 7 )\n\t\t\t\t\tuuidBuffer[ uuidBufPos ] = data << ( uuidBitCount + 1 );\n\t\t\t\t}\n\t\t\tuuidBitCount++;\n\t\t\tif( uuidBitCount > 7 )\n\t\t\t\tuuidBitCount = 0;\n\t\t\tif( !( data & 0x80 ) )\n\t\t\t\t{\n\t\t\t\t/* The following check isn't completely accurate since we\n\t\t\t\t   could have less than 16 bytes present if there are\n\t\t\t\t   leading zeroes, however to handle this properly we'd\n\t\t\t\t   have to decode the entire value as a bignum and then\n\t\t\t\t   format it appropriately, and given the fact that the use\n\t\t\t\t   of these things is practically nonexistent it's probably\n\t\t\t\t   not worth the code space to deal with this */\n\t\t\t\tif( uuidBufPos != 16 )\n\t\t\t\t\t{\n\t\t\t\t\tvalidEncoding = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tlength += sprintf( textOID + length,\n\t\t\t\t\t\t\t\t   \" { %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x }\",\n\t\t\t\t\t\t\t\t   uuidBuffer[ 0 ], uuidBuffer[ 1 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 2 ], uuidBuffer[ 3 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 4 ], uuidBuffer[ 5 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 6 ], uuidBuffer[ 7 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 8 ], uuidBuffer[ 9 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 10 ], uuidBuffer[ 11 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 12 ], uuidBuffer[ 13 ],\n\t\t\t\t\t\t\t\t   uuidBuffer[ 14 ], uuidBuffer[ 15 ] );\n\t\t\t\tvalue = 0;\n\t\t\t\t}\n\t\t\tcontinue;\n\t\t\t}\n\t\tif( value >= ( LONG_MAX >> 7 ) || \\\n\t\t\tvalTmp >= LONG_MAX - ( data & 0x7F ) )\n\t\t\t{\n\t\t\tvalidEncoding = FALSE;\n\t\t\tbreak;\n\t\t\t}\n\t\tvalue = valTmp | ( data & 0x7F );\n\t\tif( value < 0 || value > LONG_MAX / 2 )\n\t\t\t{\n\t\t\tvalidEncoding = FALSE;\n\t\t\tbreak;\n\t\t\t}\n\t\tif( !( data & 0x80 ) )\n\t\t\t{\n\t\t\tif( length == 0 )\n\t\t\t\t{\n\t\t\t\tlong x, y;\n\n\t\t\t\t/* The first two levels are encoded into one byte since the\n\t\t\t\t   root level has only 3 nodes (40*x + y), however if x =\n\t\t\t\t   joint-iso-itu-t(2) then y may be > 39, so we have to add\n\t\t\t\t   special-case handling for this */\n\t\t\t\tx = value / 40;\n\t\t\t\ty = value % 40;\n\t\t\t\tif( x > 2 )\n\t\t\t\t\t{\n\t\t\t\t\t/* Handle special case for large y if x == 2 */\n\t\t\t\t\ty += ( x - 2 ) * 40;\n\t\t\t\t\tx = 2;\n\t\t\t\t\t}\n\t\t\t\tif( x < 0 || x > 2 || y < 0 || \\\n\t\t\t\t\t( ( x < 2 && y > 39 ) || \\\n\t\t\t\t\t  ( x == 2 && ( y > 50 && y != 100 ) ) ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* If x = 0 or 1 then y has to be 0...39, for x = 3\n\t\t\t\t\t   it can take any value but there are no known\n\t\t\t\t\t   assigned values over 50 except for one contrived\n\t\t\t\t\t   example in X.690 which sets y = 100, so if we see\n\t\t\t\t\t   something outside this range it's most likely an\n\t\t\t\t\t   encoding error rather than some bizarre new ID\n\t\t\t\t\t   that's just appeared */\n\t\t\t\t\tvalidEncoding = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tlength = sprintf( textOID, \"%ld %ld\", x, y );\n\n\t\t\t\t/* A totally stupid ITU facility lets people register UUIDs\n\t\t\t\t   as OIDs (see http://www.itu.int/ITU-T/asn1/uuid.html), if\n\t\t\t\t   we find one of these, which live under the arc '2 25' =\n\t\t\t\t   0x69 we have to continue decoding the OID as a UUID\n\t\t\t\t   instead of a standard OID */\n\t\t\t\tif( data == 0x69 )\n\t\t\t\t\tisUUID = TRUE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\tlength += sprintf( textOID + length, \" %ld\", value );\n\t\t\tvalue = 0;\n\t\t\t}\n\t\t}\n\tif( value != 0 )\n\t\t{\n\t\t/* We stopped in the middle of a continued value */\n\t\tvalidEncoding = FALSE;\n\t\t}\n\ttextOID[ length ] = '\\0';\n\t*textOIDlength = length;\n\n\treturn( validEncoding );\n\t}\n\n/* Dump a bitstring, reversing the bits into the standard order in the\n   process */\n\nstatic void dumpBitString( FILE *inFile, const int length, const int unused,\n\t\t\t\t\t\t   const int level )\n\t{\n\tunsigned int bitString = 0, currentBitMask = 0x80, remainderMask = 0xFF;\n\tint bitFlag, value = 0, noBits, bitNo = -1, i;\n\tchar *errorStr = NULL;\n\n\tif( unused < 0 || unused > 7 )\n\t\tcomplain( \"Invalid number %d of unused bits\", unused, level );\n\tnoBits = ( length * 8 ) - unused;\n\n\t/* ASN.1 bitstrings start at bit 0, so we need to reverse the order of\n\t   the bits if necessary */\n\tif( length > 0 )\n\t\t{\n\t\tbitString = fgetc( inFile );\n\t\tif( bitString == EOF )\n\t\t\t{\n\t\t\tnoBits = 0;\n\t\t\terrorStr = \"Truncated BIT STRING data\";\n\t\t\t}\n\t\tfPos++;\n\t\t}\n\tfor( i = noBits - 8; i > 0; i -= 8 )\n\t\t{\n\t\tconst int ch = fgetc( inFile );\n\n\t\tif( ch == EOF )\n\t\t\t{\n\t\t\terrorStr = \"Truncated BIT STRING data\";\n\t\t\tbreak;\n\t\t\t}\n\t\tbitString = ( bitString << 8 ) | ch;\n\t\tcurrentBitMask <<= 8;\n\t\tremainderMask = ( remainderMask << 8 ) | 0xFF;\n\t\tfPos++;\n\t\t}\n\tif( errorStr != NULL )\n\t\t{\n\t\tprintString( level, \"%c\", '\\n' );\n\t\tcomplain( errorStr, 0, level );\n\t\treturn;\n\t\t}\n\tif( reverseBitString )\n\t\t{\n\t\tfor( i = 0, bitFlag = 1; i < noBits; i++ )\n\t\t\t{\n\t\t\tif( bitString & currentBitMask )\n\t\t\t\tvalue |= bitFlag;\n\t\t\tif( !( bitString & remainderMask ) && errorStr == NULL )\n\t\t\t\t{\n\t\t\t\t/* The last valid bit should be a one bit */\n\t\t\t\terrorStr = \"Spurious zero bits in bitstring\";\n\t\t\t\t}\n\t\t\tbitFlag <<= 1;\n\t\t\tbitString <<= 1;\n\t\t\t}\n\t\tif( noBits < sizeof( int ) && \\\n\t\t\t( ( remainderMask << noBits ) & value ) && \\\n\t\t\terrorStr != NULL )\n\t\t\t{\n\t\t\t/* There shouldn't be any bits set after the last valid one.  We\n\t\t\t   have to do the noBits check to avoid a fencepost error when\n\t\t\t   there's exactly 32 bits */\n\t\t\terrorStr = \"Spurious one bits in bitstring\";\n\t\t\t}\n\t\t}\n\telse\n\t\tvalue = bitString;\n\n\t/* Now that it's in the right order, dump it.  If there's only one bit\n\t   set (which is often the case for bit flags) we also print the bit\n\t   number to save users having to count the zeroes to figure out which\n\t   flag is set */\n\tprintString( level, \"%c\", '\\n' );\n\tif( !doPure )\n\t\tprintString( level, \"%s\", INDENT_STRING );\n\tdoIndent( level + 1 );\n\tprintString( level, \"%c\", '\\'' );\n\tif( reverseBitString )\n\t\tcurrentBitMask = 1 << ( noBits - 1 );\n\tfor( i = 0; i < noBits; i++ )\n\t\t{\n\t\tif( value & currentBitMask )\n\t\t\t{\n\t\t\tbitNo = ( bitNo == -1 ) ? ( noBits - 1 ) - i : -2;\n\t\t\tprintString( level, \"%c\", '1' );\n\t\t\t}\n\t\telse\n\t\t\tprintString( level, \"%c\", '0' );\n\t\tcurrentBitMask >>= 1;\n\t\t}\n\tif( bitNo >= 0 )\n\t\tprintString( level, \"'B (bit %d)\\n\", bitNo );\n\telse\n\t\tprintString( level, \"%s\", \"'B\\n\" );\n\n\tif( errorStr != NULL )\n\t\tcomplain( errorStr, 0, level );\n\t}\n\n/* Display data as a text string up to a maximum of 240 characters (8 lines\n   of 48 chars to match the hex limit of 8 lines of 16 bytes) with special\n   treatement for control characters and other odd things that can turn up\n   in BMPString and UniversalString types.\n\n   If the string is less than 40 chars in length, we try to print it on the\n   same line as the rest of the text (even if it wraps), otherwise we break\n   it up into 48-char chunks in a somewhat less nice text-dump format */\n\nstatic void displayString( FILE *inFile, long length, int level,\n\t\t\t\t\t\t   const STR_OPTION strOption )\n\t{\n\tchar timeStr[ 64 ];\n\tlong noBytes = length;\n\tint lineLength = 48, i;\n\tint firstTime = TRUE, doTimeStr = FALSE, warnIA5 = FALSE;\n\tint warnPrintable = FALSE, warnTime = FALSE, warnBMP = FALSE;\n\n\tif( noBytes > 384 && !printAllData )\n\t\tnoBytes = 384;\t/* Only output a maximum of 384 bytes */\n\tif( strOption == STR_UTCTIME || strOption == STR_GENERALIZED )\n\t\t{\n\t\tif( ( strOption == STR_UTCTIME && length != 13 ) || \\\n\t\t\t( strOption == STR_GENERALIZED && length != 15 ) )\n\t\t\twarnTime = TRUE;\n\t\telse\n\t\t\tdoTimeStr = rawTimeString ? FALSE : TRUE;\n\t\t}\n\tif( !doTimeStr && length <= 40 )\n\t\tprintString( level, \"%s\", \" '\" );\t/* Print string on same line */\n\tlevel = adjustLevel( level, ( doPure ) ? 15 : 8 );\n\tfor( i = 0; i < noBytes; i++ )\n\t\t{\n\t\tint ch;\n\n\t\t/* If the string is longer than 40 chars, break it up into multiple\n\t\t   sections */\n\t\tif( length > 40 && !( i % lineLength ) )\n\t\t\t{\n\t\t\tif( !firstTime )\n\t\t\t\tprintString( level, \"%c\", '\\'' );\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tif( !doPure )\n\t\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\t\tdoIndent( level + 1 );\n\t\t\tprintString( level, \"%c\", '\\'' );\n\t\t\tfirstTime = FALSE;\n\t\t\t}\n\t\tch = getc( inFile );\n\t\tif( ch == EOF )\n\t\t\t{\n\t\t\tcomplainEOF( level, noBytes - i );\n\t\t\treturn;\n\t\t\t}\n#if defined( __WIN32__ ) || defined( __UNIX__ ) || defined( __OS390__ )\n\t\tif( strOption == STR_BMP )\n\t\t\t{\n\t\t\tif( i == noBytes - 1 && ( noBytes & 1 ) )\n\t\t\t\t{\n\t\t\t\t/* Odd-length BMP string, complain */\n\t\t\t\twarnBMP = TRUE;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tconst wchar_t wCh = ( ch << 8 ) | getc( inFile );\n\n\t\t\t\tif( displayUnicode( wCh, level ) )\n\t\t\t\t\t{\n\t\t\t\t\tlineLength++;\n\t\t\t\t\ti++;\t/* We've read two characters for a wchar_t */\n\t\t\t\t\tfPos += 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t/* The value can't be displayed as Unicode, fall back to\n\t\t\t\t   displaying it as normal text */\n\t\t\t\tungetc( wCh & 0xFF, inFile );\n\t\t\t\t}\n\t\t\t}\n\t\tif( strOption == STR_UTF8 && ( ch & 0x80 ) )\n\t\t\t{\n\t\t\tconst int secondCh = getc( inFile );\n\t\t\twchar_t wCh;\n\n\t\t\t/* It's a multibyte UTF8 character, read it as a widechar */\n\t\t\tif( ( ch & 0xE0 ) == 0xC0 )\t\t/* 111xxxxx -> 110xxxxx */\n\t\t\t\t{\n\t\t\t\t/* 2-byte character in the range 0x80...0x7FF */\n\t\t\t\twCh = ( ( ch & 0x1F ) << 6 ) | ( secondCh & 0x3F );\n\t\t\t\ti++;\t\t/* We've read 2 characters */\n\t\t\t\tfPos += 2;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( ( ch & 0xF0 ) == 0xE0 )\t/* 1111xxxx -> 1110xxxx */\n\t\t\t\t\t{\n\t\t\t\t\tconst int thirdCh = getc( inFile );\n\n\t\t\t\t\t/* 3-byte character in the range 0x800...0xFFFF */\n\t\t\t\t\twCh = ( ( ch & 0x1F ) << 12 ) | \\\n\t\t\t\t\t\t  ( ( secondCh & 0x3F ) << 6 ) | \\\n\t\t\t\t\t\t  ( thirdCh & 0x3F );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\twCh = '.';\n\t\t\t\ti += 2;\t\t/* We've read 3 characters */\n\t\t\t\tfPos += 3;\n\t\t\t\t}\n\t\t\tif( !displayUnicode( wCh, level ) )\n\t\t\t\tprintString( level, \"%c\", '.' );\n\t\t\tlineLength++;\n\t\t\tcontinue;\n\t\t\t}\n#endif /* __WIN32__ || __UNIX__ || __OS390__ */\n\t\tswitch( strOption )\n\t\t\t{\n\t\t\tcase STR_PRINTABLE:\n\t\t\tcase STR_IA5:\n\t\t\tcase STR_LATIN1:\n\t\t\t\tif( strOption == STR_PRINTABLE && !isPrintable( ch ) )\n\t\t\t\t\twarnPrintable = TRUE;\n\t\t\t\tif( strOption == STR_IA5 && !isIA5( ch ) )\n\t\t\t\t\twarnIA5 = TRUE;\n\t\t\t\tif( strOption == STR_LATIN1 )\n\t\t\t\t\t{\n\t\t\t\t\tif( !isprint( ch & 0x7F ) )\n\t\t\t\t\t\tch = '.';\t/* Convert non-ASCII to placeholders */\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif( !isprint( ch ) )\n\t\t\t\t\t\tch = '.';\t/* Convert non-ASCII to placeholders */\n\t\t\t\t\t}\n#ifdef __OS390__\n\t\t\t\tch = asciiToEbcdic( ch );\n#endif /* __OS390__ */\n\t\t\t\tbreak;\n\n\t\t\tcase STR_UTCTIME:\n\t\t\tcase STR_GENERALIZED:\n\t\t\t\tif( !isdigit( ch ) && ch != 'Z' )\n\t\t\t\t\t{\n\t\t\t\t\twarnTime = TRUE;\n\t\t\t\t\tif( !isprint( ch ) )\n\t\t\t\t\t\tch = '.';\t/* Convert non-ASCII to placeholders */\n\t\t\t\t\t}\n#ifdef __OS390__\n\t\t\t\tch = asciiToEbcdic( ch );\n#endif /* __OS390__ */\n\t\t\t\tbreak;\n\n\t\t\tcase STR_BMP_REVERSED:\n\t\t\t\tif( i == noBytes - 1 && ( noBytes & 1 ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Odd-length BMP string, complain */\n\t\t\t\t\twarnBMP = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t/* Wrong-endianness BMPStrings (Microsoft Unicode) can't be\n\t\t\t\t   handled through the usual widechar-handling mechanism\n\t\t\t\t   above since the first widechar looks like an ASCII char\n\t\t\t\t   followed by a null terminator, so we just treat them as\n\t\t\t\t   ASCII chars, skipping the following zero byte.  This is\n\t\t\t\t   safe since the code that detects reversed BMPStrings\n\t\t\t\t   has already checked that every second byte is zero */\n\t\t\t\tgetc( inFile );\n\t\t\t\ti++;\n\t\t\t\tfPos++;\n\t\t\t\t/* Fall through */\n\n\t\t\tdefault:\n\t\t\t\tif( !isprint( ch ) )\n\t\t\t\t\tch = '.';\t/* Convert control chars to placeholders */\n#ifdef __OS390__\n\t\t\t\tch = asciiToEbcdic( ch );\n#endif /* __OS390__ */\n\t\t\t}\n\t\tif( doTimeStr )\n\t\t\ttimeStr[ i ] = ch;\n\t\telse\n\t\t\tprintString( level, \"%c\", ch );\n\t\tfPos++;\n\t\t}\n\tif( length > 384 && !printAllData )\n\t\t{\n\t\tlength -= 384;\n\t\tprintString( level, \"%s\", \"'\\n\" );\n\t\tif( !doPure )\n\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\tdoIndent( level + 5 );\n\t\tprintString( level, \"[ Another %ld characters skipped ]\", length );\n\t\tfPos += length;\n\t\twhile( length-- )\n\t\t\t{\n\t\t\tint ch = getc( inFile );\n\n\t\t\tif( ch == EOF )\n\t\t\t\t{\n\t\t\t\tcomplainEOF( level, length );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tif( strOption == STR_PRINTABLE && !isPrintable( ch ) )\n\t\t\t\twarnPrintable = TRUE;\n\t\t\tif( strOption == STR_IA5 && !isIA5( ch ) )\n\t\t\t\twarnIA5 = TRUE;\n\t\t\t}\n\t\t}\n\telse\n\t\t{\n\t\tif( doTimeStr )\n\t\t\t{\n\t\t\tconst char *timeStrPtr = ( strOption == STR_UTCTIME ) ? \\\n\t\t\t\t\t\t\t\t\t timeStr : timeStr + 2;\n\n\t\t\tprintString( level, \" %c%c/%c%c/\",\n\t\t\t\t\t\t timeStrPtr[ 4 ], timeStrPtr[ 5 ],\n\t\t\t\t\t\t timeStrPtr[ 2 ], timeStrPtr[ 3 ] );\n\t\t\tif( strOption == STR_UTCTIME )\n\t\t\t\t{\n\t\t\t\tprintString( level, \"%s\",\n\t\t\t\t\t\t\t ( timeStr[ 0 ] < '5' ) ? \"20\" : \"19\" );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tprintString( level, \"%c%c\", timeStr[ 0 ], timeStr[ 1 ] );\n\t\t\t\t}\n\t\t\tprintString( level, \"%c%c %c%c:%c%c:%c%c GMT\",\n\t\t\t\t\t\t timeStrPtr[ 0 ], timeStrPtr[ 1 ], timeStrPtr[ 6 ],\n\t\t\t\t\t\t timeStrPtr[ 7 ], timeStrPtr[ 8 ], timeStrPtr[ 9 ],\n\t\t\t\t\t\t timeStrPtr[ 10 ], timeStrPtr[ 11 ] );\n\t\t\t}\n\t\telse\n\t\t\tprintString( level, \"%c\", '\\'' );\n\t\t}\n\tprintString( level, \"%c\", '\\n' );\n\n\t/* Display any problems we encountered */\n\tif( warnPrintable )\n\t\tcomplain( \"PrintableString contains illegal character(s)\", 0, level );\n\tif( warnIA5 )\n\t\tcomplain( \"IA5String contains illegal character(s)\", 0, level );\n\tif( warnTime )\n\t\tcomplain( \"Time is encoded incorrectly\", 0, level );\n\tif( warnBMP )\n\t\tcomplain( \"BMPString has missing final byte/half character\", 0, level );\n\t}\n\n/****************************************************************************\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\tASN.1 Parsing Routines\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n****************************************************************************/\n\n/* Get an ASN.1 object's tag and length.  Returns TRUE for an item\n   available, FALSE for end-of-data, and a negative value for an invalid\n   data */\n\nstatic int getItem( FILE *inFile, ASN1_ITEM *item )\n\t{\n\tint tag, length, index = 0;\n\n\tmemset( item, 0, sizeof( ASN1_ITEM ) );\n\titem->indefinite = FALSE;\n\ttag = item->header[ index++ ] = fgetc( inFile );\n\tif( tag == EOF )\n\t\treturn( FALSE );\n\tfPos++;\n\titem->id = tag & ~TAG_MASK;\n\ttag &= TAG_MASK;\n\tif( tag == TAG_MASK )\n\t\t{\n\t\tint value;\n\n\t\t/* Long tag encoded as sequence of 7-bit values.  This doesn't try to\n\t\t   handle tags > INT_MAX, it'd be pretty peculiar ASN.1 if it had to\n\t\t   use tags this large */\n\t\ttag = 0;\n\t\tdo\n\t\t\t{\n\t\t\tvalue = fgetc( inFile );\n\t\t\tif( value == EOF )\n\t\t\t\treturn( FALSE );\n\t\t\ttag = ( tag << 7 ) | ( value & 0x7F );\n\t\t\titem->header[ index++ ] = value;\n\t\t\tfPos++;\n\t\t\t}\n\t\twhile( value & LEN_XTND && index < 5 && !feof( inFile ) );\n\t\tif( index >= 5 )\n\t\t\treturn( FALSE );\n\t\t}\n\titem->tag = tag;\n\tlength = fgetc( inFile );\n\tif( length == EOF )\n\t\treturn( FALSE );\n\tfPos++;\n\titem->header[ index++ ] = length;\n\titem->headerSize = index;\n\tif( length & LEN_XTND )\n\t\t{\n\t\tconst int lengthStart = index;\n\t\tint i;\n\n\t\tlength &= LEN_MASK;\n\t\tif( length > 4 )\n\t\t\t{\n\t\t\t/* Impossible length value, probably because we've run into\n\t\t\t   the weeds */\n\t\t\treturn( -1 );\n\t\t\t}\n\t\titem->headerSize += length;\n\t\titem->length = 0;\n\t\tif( !length )\n\t\t\titem->indefinite = TRUE;\n\t\tfor( i = 0; i < length; i++ )\n\t\t\t{\n\t\t\tint ch = fgetc( inFile );\n\n\t\t\tif( ch == EOF )\n\t\t\t\t{\n\t\t\t\tfPos += length - i;\n\t\t\t\treturn( FALSE );\n\t\t\t\t}\n\t\t\titem->length = ( item->length << 8 ) | ch;\n\t\t\titem->header[ i + index ] = ch;\n\t\t\t}\n\t\tfPos += length;\n\n\t\t/* Check for the length being less then 128, which means it\n\t\t   shouldn't be encoded as a long length */\n\t\tif( !item->indefinite && item->length < 128 )\n\t\t\titem->nonCanonical = lengthStart;\n\n\t\t/* Check for the first 9 bits of the length being identical and\n\t\t   if they are, remember where the encoded non-canonical length\n\t\t   starts */\n\t\tif( item->headerSize - lengthStart > 1 )\n\t\t\t{\n\t\t\tif( ( item->header[ lengthStart ] == 0x00 ) && \\\n\t\t\t\t( ( item->header[ lengthStart + 1 ] & 0x80 ) == 0x00 ) )\n\t\t\t\titem->nonCanonical = lengthStart - 1;\n\t\t\tif( ( item->header[ lengthStart ] == 0xFF ) && \\\n\t\t\t\t( ( item->header[ lengthStart + 1 ] & 0x80 ) == 0x80 ) )\n\t\t\t\titem->nonCanonical = lengthStart - 1;\n\t\t\t}\n\t\t}\n\telse\n\t\titem->length = length;\n\n\treturn( TRUE );\n\t}\n\n/* Check whether a BIT STRING or OCTET STRING encapsulates another object */\n\nstatic int checkEncapsulate( FILE *inFile, const int length )\n\t{\n\tASN1_ITEM nestedItem;\n\tconst int currentPos = fPos;\n\tint diffPos, status;\n\n\t/* If we're not looking for encapsulated objects, return */\n\tif( !checkEncaps )\n\t\treturn( FALSE );\n\n\t/* An item of length < 2 can never have encapsulated data.  Even for\n\t   length 2 it can only be an encapsulated NULL, which is somewhat odd,\n\t   but no doubt there's some PKI protocol somewhere that does this */\n\tif( length < 2 )\n\t\treturn( FALSE );\n\n\t/* Read the details of the next item in the input stream */\n\tstatus = getItem( inFile, &nestedItem );\n\tdiffPos = fPos - currentPos;\n\tfPos = currentPos;\n\tfseek( inFile, -diffPos, SEEK_CUR );\n\tif( status <= 0 )\n\t\treturn( FALSE );\n\n\t/* If it's not a standard tag class, don't try and dig down into it */\n\tif( ( nestedItem.id & CLASS_MASK ) != UNIVERSAL && \\\n\t\t( nestedItem.id & CLASS_MASK ) != CONTEXT )\n\t\treturn( FALSE );\n\n\t/* There is one special-case situation that overrides the check below,\n\t   which is when the nested content is indefinite-length.  This is\n\t   rather tricky to check for because we'd need to read some distance\n\t   ahead into the stream to be able to safely decide whether we've got\n\t   true nested content or a false positive, for now we require that\n\t   the nested content has to be a SEQUENCE containing valid ASN.1 at\n\t   the start, giving about 24 bits of checking.  There's a small risk\n\t   of false negatives for encapsulated primitive items, but since\n\t   they're primitive it should be relatively easy to make out the\n\t   contents inside the OCTET STRING */\n\tif( nestedItem.tag == SEQUENCE && nestedItem.indefinite )\n\t\t{\n\t\t/* Skip the indefinite-length SEQUENCE and make sure that it's\n\t\t   followed by a valid item */\n\t\tstatus = getItem( inFile, &nestedItem );\n\t\tif( status > 0 )\n\t\t\tstatus = getItem( inFile, &nestedItem );\n\t\tdiffPos = fPos - currentPos;\n\t\tfPos = currentPos;\n\t\tfseek( inFile, -diffPos, SEEK_CUR );\n\t\tif( status <= 0 )\n\t\t\treturn( FALSE );\n\n\t\t/* If the tag on the nest item looks vaguely valid, assume that we've\n\t\t   go nested content */\n\t\tif( ( nestedItem.tag <= 0 || nestedItem.tag > 0x31 ) || \\\n\t\t\t( nestedItem.length >= length ) )\n\t\t\treturn( FALSE );\n\t\treturn( TRUE );\n\t\t}\n\n\t/* If it doesn't fit exactly within the current item it's not an\n\t   encapsulated object */\n\tif( nestedItem.length != length - diffPos )\n\t\treturn( FALSE );\n\n\t/* If it doesn't have a valid-looking tag, don't try and go any further */\n\tif( nestedItem.tag <= 0 || nestedItem.tag > 0x31 )\n\t\treturn( FALSE );\n\n\t/* Now things get a bit complicated because it's possible to get some\n\t   (very rare) false positives, for example if a NUMERICSTRING of\n\t   exactly the right length is nested within an OCTET STRING, since\n\t   numeric values all look like constructed tags of some kind.  To\n\t   handle this we look for nested constructed items that should really\n\t   be primitive */\n\tif( ( nestedItem.id & FORM_MASK ) == PRIMITIVE )\n\t\treturn( TRUE );\n\n\t/* It's constructed, make sure that it's something for which it makes\n\t   sense as a constructed object.  At worst this will give some false\n\t   negatives for really wierd objects (nested constructed strings inside\n\t   OCTET STRINGs), but these should probably never occur anyway */\n\tif( nestedItem.tag == SEQUENCE || \\\n\t\tnestedItem.tag == SET )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\n/* Check whether a zero-length item is OK */\n\nstatic int zeroLengthOK( const ASN1_ITEM *item )\n\t{\n\t/* An implicitly-tagged NULL can have a zero length.  An occurrence of this\n\t   type of item is almost always an error, however OCSP uses a weird status\n\t   encoding that encodes result values in tags and then has to use a NULL\n\t   value to indicate that there's nothing there except the tag that encodes\n\t   the status, so we allow this as well if zero-length content is explicitly\n\t   enabled */\n\tif( zeroLengthAllowed && ( item->id & CLASS_MASK ) == CONTEXT )\n\t\treturn( TRUE );\n\n\t/* If we can't recognise the type from the tag, reject it */\n\tif( ( item->id & CLASS_MASK ) != UNIVERSAL )\n\t\treturn( FALSE );\n\n\t/* The following types are zero-length by definition */\n\tif( item->tag == EOC || item->tag == NULLTAG )\n\t\treturn( TRUE );\n\n\t/* A real with a value of zero has zero length */\n\tif( item->tag == REAL )\n\t\treturn( TRUE );\n\n\t/* Everything after this point requires input from the user to say that\n\t   zero-length data is OK (usually it's not, so we flag it as a\n\t   problem) */\n\tif( !zeroLengthAllowed )\n\t\treturn( FALSE );\n\n\t/* String types can have zero length except for the Unrestricted\n\t   Character String type ([UNIVERSAL 29]) which has to have at least one\n\t   octet for the CH-A/CH-B index */\n\tif( item->tag == OCTETSTRING || item->tag == NUMERICSTRING || \\\n\t\titem->tag == PRINTABLESTRING || item->tag == T61STRING || \\\n\t\titem->tag == VIDEOTEXSTRING || item->tag == VISIBLESTRING || \\\n\t\titem->tag == IA5STRING || item->tag == GRAPHICSTRING || \\\n\t\titem->tag == GENERALSTRING || item->tag == UNIVERSALSTRING || \\\n\t\titem->tag == BMPSTRING || item->tag == UTF8STRING || \\\n\t\titem->tag == OBJDESCRIPTOR )\n\t\treturn( TRUE );\n\n\t/* SEQUENCE and SET can be zero if there are absent optional/default\n\t   components */\n\tif( item->tag == SEQUENCE || item->tag == SET )\n\t\treturn( TRUE );\n\n\treturn( FALSE );\n\t}\n\n/* Check whether the next item looks like text */\n\nstatic STR_OPTION checkForText( FILE *inFile, const int length )\n\t{\n\tchar buffer[ 16 ];\n\tint isBMP = FALSE, isUnicode = FALSE;\n\tint sampleLength = min( length, 16 ), i;\n\n\t/* If the sample is very short, we're more careful about what we\n\t   accept */\n\tif( sampleLength < 4 )\n\t\t{\n\t\t/* If the sample size is too small, don't try anything */\n\t\tif( sampleLength <= 2 )\n\t\t\treturn( STR_NONE );\n\n\t\t/* For samples of 3-4 characters we only allow ASCII text.  These\n\t\t   short strings are used in some places (eg PKCS #12 files) as\n\t\t   IDs */\n\t\tsampleLength = fread( buffer, 1, sampleLength, inFile );\n\t\tif( sampleLength <= 0 )\n\t\t\treturn( STR_NONE );\n\t\tfseek( inFile, -sampleLength, SEEK_CUR );\n\t\tfor( i = 0; i < sampleLength; i++ )\n\t\t\t{\n\t\t\tconst int ch = byteToInt( buffer[ i ] );\n\n\t\t\tif( !( isalpha( ch ) || isdigit( ch ) || isspace( ch ) ) )\n\t\t\t\treturn( STR_NONE );\n\t\t\t}\n\t\treturn( STR_IA5 );\n\t\t}\n\n\t/* Check for ASCII-looking text */\n\tsampleLength = fread( buffer, 1, sampleLength, inFile );\n\tif( sampleLength <= 0 )\n\t\treturn( STR_NONE );\n\tfseek( inFile, -sampleLength, SEEK_CUR );\n\tif( isdigit( byteToInt( buffer[ 0 ] ) ) && \\\n\t\t( length == 13 || length == 15 ) && \\\n\t\tbuffer[ length - 1 ] == 'Z' )\n\t\t{\n\t\t/* It looks like a time string, make sure that it really is one */\n\t\tfor( i = 0; i < length - 1; i++ )\n\t\t\t{\n\t\t\tif( !isdigit( byteToInt( buffer[ i ] ) ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( i == length - 1 )\n\t\t\treturn( ( length == 13 ) ? STR_UTCTIME : STR_GENERALIZED );\n\t\t}\n\tfor( i = 0; i < sampleLength; i++ )\n\t\t{\n\t\t/* If even bytes are zero, it could be a BMPString.  Initially\n\t\t   we set isBMP to FALSE, if it looks like a BMPString we set it to\n\t\t   TRUE, if we then encounter a nonzero byte it's neither an ASCII\n\t\t   nor a BMPString */\n\t\tif( !( i & 1 ) )\n\t\t\t{\n\t\t\tif( !buffer[ i ] )\n\t\t\t\t{\n\t\t\t\t/* If we thought we were in a Unicode string but we've found a\n\t\t\t\t   zero byte where it'd occur in a BMP string, it's neither a\n\t\t\t\t   Unicode nor BMP string */\n\t\t\t\tif( isUnicode )\n\t\t\t\t\treturn( STR_NONE );\n\n\t\t\t\t/* We've collapsed the eigenstate (in an earlier incarnation\n\t\t\t\t   isBMP could take values of -1, 0, or 1, with 0 being\n\t\t\t\t   undecided, in which case this comment made a bit more\n\t\t\t\t   sense) */\n\t\t\t\tif( i < sampleLength - 2 )\n\t\t\t\t\t{\n\t\t\t\t\t/* If the last char(s) are zero but preceding ones\n\t\t\t\t\t   weren't, don't treat it as a BMP string.  This can\n\t\t\t\t\t   happen when storing a null-terminated string if the\n\t\t\t\t\t   implementation gets the length wrong and stores the\n\t\t\t\t\t   null as well */\n\t\t\t\t\tisBMP = TRUE;\n\t\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t/* If we thought we were in a BMPString but we've found a\n\t\t\t\t   nonzero byte where there should be a zero, it's neither\n\t\t\t\t   an ASCII nor BMP string */\n\t\t\t\tif( isBMP )\n\t\t\t\t\treturn( STR_NONE );\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\t/* Just to make it tricky, Microsoft stuff Unicode strings into\n\t\t\t   some places (to avoid having to convert them to BMPStrings,\n\t\t\t   presumably) so we have to check for these as well */\n\t\t\tif( !buffer[ i ] )\n\t\t\t\t{\n\t\t\t\tif( isBMP )\n\t\t\t\t\treturn( STR_NONE );\n\t\t\t\tisUnicode = TRUE;\n\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( isUnicode )\n\t\t\t\t\treturn( STR_NONE );\n\t\t\t\t}\n\t\t\t}\n\t\tif( buffer[ i ] < 0x20 || buffer[ i ] > 0x7E )\n\t\t\treturn( STR_NONE );\n\t\t}\n\n\t/* It looks like a text string */\n\treturn( isUnicode ? STR_BMP_REVERSED : isBMP ? STR_BMP : STR_IA5 );\n\t}\n\n/* Dump the header bytes for an object, useful for vgrepping the original\n   object from a hex dump */\n\nstatic void dumpHeader( FILE *inFile, const ASN1_ITEM *item, const int level )\n\t{\n\tint extraLen = 24 - item->headerSize, i;\n\n\t/* Dump the tag and length bytes */\n\tif( !doPure )\n\t\tprintString( level, \"%s\", \"    \" );\n\tprintString( level, \"<%02X\", *item->header );\n\tfor( i = 1; i < item->headerSize; i++ )\n\t\tprintString( level, \" %02X\", item->header[ i ] );\n\n\t/* If we're asked for more, dump enough extra data to make up 24 bytes.\n\t   This is somewhat ugly since it assumes we can seek backwards over the\n\t   data, which means it won't always work on streams */\n\tif( extraLen > 0 && doDumpHeader > 1 )\n\t\t{\n\t\t/* Make sure that we don't print too much data.  This doesn't work\n\t\t   for indefinite-length data, we don't try and guess the length with\n\t\t   this since it involves picking apart what we're printing */\n\t\tif( extraLen > item->length && !item->indefinite )\n\t\t\textraLen = ( int ) item->length;\n\n\t\tfor( i = 0; i < extraLen; i++ )\n\t\t\t{\n\t\t\tconst int ch = fgetc( inFile );\n\n\t\t\tif( ch == EOF )\n\t\t\t\t{\n\t\t\t\t/* Exit loop and get fseek() offset correct */\n\t\t\t\textraLen = i;\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tprintString( level, \" %02X\", ch );\n\t\t\t}\n\t\tfseek( inFile, -extraLen, SEEK_CUR );\n\t\t}\n\n\tprintString( level, \"%s\", \">\\n\" );\n\t}\n\n/* Print a constructed ASN.1 object */\n\nstatic int printAsn1( FILE *inFile, const int level, long length,\n\t\t\t\t\t  const int isIndefinite );\n\nstatic void markConstructed( const int level, const ASN1_ITEM *item )\n\t{\n\t/* If it's a type that's not normally constructed, tag it as such */\n\tif( item->id == BOOLEAN || item->id == INTEGER || \\\n\t\titem->id == BITSTRING || item->id == OCTETSTRING || \\\n\t\titem->id == ENUMERATED\t|| item->id == UTF8STRING || \\\n\t\t( item->id >= NUMERICSTRING && item->id <= BMPSTRING ) )\n\t\tprintString( level, \"%s\", \" (constructed)\" );\n\t}\n\nstatic void printConstructed( FILE *inFile, int level, const ASN1_ITEM *item )\n\t{\n\tint result;\n\n\t/* Special case for zero-length objects */\n\tif( !item->length && !item->indefinite )\n\t\t{\n\t\tprintString( level, \"%s\", \" {}\\n\" );\n\t\tif( item->nonCanonical )\n\t\t\tcomplainLengthCanonical( item, level );\n\t\treturn;\n\t\t}\n\n\tprintString( level, \"%s\", \" {\\n\" );\n\tif( item->nonCanonical )\n\t\tcomplainLengthCanonical( item, level );\n\tresult = printAsn1( inFile, level + 1, item->length, item->indefinite );\n\tif( result )\n\t\t{\n\t\tfprintf( output, \"Error: Inconsistent object length, %d byte%s \"\n\t\t\t\t \"difference.\\n\", result, ( result > 1 ) ? \"s\" : \"\" );\n\t\tnoErrors++;\n\t\t}\n\tif( !doPure )\n\t\tprintString( level, \"%s\", INDENT_STRING );\n\tprintString( level, \"%s\", ( printDots ) ? \". \" : \"  \" );\n\tdoIndent( level );\n\tprintString( level, \"%s\", \"}\\n\" );\n\t}\n\n/* Print a single ASN.1 object */\n\nstatic void printASN1object( FILE *inFile, ASN1_ITEM *item, int level )\n\t{\n\tOIDINFO *oidInfo;\n\tSTR_OPTION stringType;\n\tBYTE buffer[ MAX_OID_SIZE ];\n\tconst int nonOutlineObject = \\\n\t\t\t( doOutlineOnly && ( item->id & FORM_MASK ) != CONSTRUCTED ) ? \\\n\t\t\tTRUE : FALSE;\n\n\tif( ( item->id & CLASS_MASK ) != UNIVERSAL )\n\t\t{\n\t\tstatic const char *const classtext[] =\n\t\t\t{ \"UNIVERSAL \", \"APPLICATION \", \"\", \"PRIVATE \" };\n\n\t\t/* Print the object type */\n\t\tif( !nonOutlineObject )\n\t\t\t{\n\t\t\tprintString( level, \"[%s%d]\",\n\t\t\t\t\t\t classtext[ ( item->id & CLASS_MASK ) >> 6 ], item->tag );\n\t\t\t}\n\n\t\t/* Perform a sanity check */\n\t\tif( ( item->tag != NULLTAG ) && ( item->length < 0 ) )\n\t\t\t{\n\t\t\tint i;\n\n\t\t\tfflush( stdout );\n\t\t\tfprintf( stderr, \"\\nError: Object has bad length field, tag = %02X, \"\n\t\t\t\t\t \"length = %lX, value =\", item->tag, item->length );\n\t\t\tfprintf( stderr, \"<%02X\", *item->header );\n\t\t\tfor( i = 1; i < item->headerSize; i++ )\n\t\t\t\tfprintf( stderr, \" %02X\", item->header[ i ] );\n\t\t\tfputs( \">.\\n\", stderr );\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\n\t\tif( !item->length && !item->indefinite && !zeroLengthOK( item ) )\n\t\t\t{\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tcomplain( \"Object has zero length\", 0, level );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* If it's constructed, print the various fields in it */\n\t\tif( ( item->id & FORM_MASK ) == CONSTRUCTED )\n\t\t\t{\n\t\t\tmarkConstructed( level, item );\n\t\t\tprintConstructed( inFile, level, item );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* It'sprimitive, if we're only displaying the ASN.1 in outline\n\t\t   form, supress the display by dumping it with a nesting level that\n\t\t   ensures it won't get output (this clears the data from the input\n\t\t   without displaying it) */\n\t\tif( nonOutlineObject )\n\t\t\t{\n\t\t\tdumpHex( inFile, item->length, 1000, FALSE );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* It's primitive, if it's a seekable stream try and determine\n\t\t   whether it's text so we can display it as such */\n\t\tif( !useStdin && \\\n\t\t\t( stringType = checkForText( inFile, item->length ) ) != STR_NONE )\n\t\t\t{\n\t\t\t/* It looks like a text string, dump it as text */\n\t\t\tdisplayString( inFile, item->length, level, stringType );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\treturn;\n\t\t\t}\n\n\t\t/* This could be anything, dump it as hex data */\n\t\tdumpHex( inFile, item->length, level, FALSE );\n\t\tif( item->nonCanonical )\n\t\t\tcomplainLengthCanonical( item, level );\n\n\t\treturn;\n\t\t}\n\n\t/* Print the object type */\n\tif( !doOutlineOnly || ( item->id & FORM_MASK ) == CONSTRUCTED )\n\t\tprintString( level, \"%s\", idstr( item->tag ) );\n\n\t/* Perform a sanity check */\n\tif( ( item->tag != NULLTAG ) && ( item->length < 0 ) )\n\t\t{\n\t\tint i;\n\n\t\tfflush( stdout );\n\t\tfprintf( stderr, \"\\nError: Object has bad length field, tag = %02X, \"\n\t\t\t\t \"length = %lX, value =\", item->tag, item->length );\n\t\tfprintf( stderr, \"<%02X\", *item->header );\n\t\tfor( i = 1; i < item->headerSize; i++ )\n\t\t\tfprintf( stderr, \" %02X\", item->header[ i ] );\n\t\tfputs( \">.\\n\", stderr );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* If it's constructed, print the various fields in it */\n\tif( ( item->id & FORM_MASK ) == CONSTRUCTED )\n\t\t{\n\t\tmarkConstructed( level, item );\n\t\tprintConstructed( inFile, level, item );\n\t\treturn;\n\t\t}\n\n\t/* It's primitive */\n\tif( doOutlineOnly )\n\t\t{\n\t\t/* If we're only displaying the ASN.1 in outline form, set an\n\t\t   artificially high nesting level that ensures it won't get output\n\t\t   (this clears the data from the input without displaying it) */\n\t\tlevel = 1000;\n\t\t}\n\tif( !item->length && !zeroLengthOK( item ) )\n\t\t{\n\t\tprintString( level, \"%c\", '\\n' );\n\t\tcomplain( \"Object has zero length\", 0, level );\n\t\tif( item->nonCanonical )\n\t\t\tcomplainLengthCanonical( item, level );\n\t\treturn;\n\t\t}\n\tswitch( item->tag )\n\t\t{\n\t\tcase BOOLEAN:\n\t\t\t{\n\t\t\tint ch;\n\n\t\t\tif( item->length != 1 )\n\t\t\t\tcomplainLength( item, level );\n\t\t\tch = getc( inFile );\n\t\t\tif( ch == EOF )\n\t\t\t\t{\n\t\t\t\tcomplainEOF( level, 1 );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tprintString( level, \" %s\\n\", ch ? \"TRUE\" : \"FALSE\" );\n\t\t\tif( ch != 0 && ch != 0xFF )\n\t\t\t\t{\n\t\t\t\tcomplain( \"BOOLEAN '%02X' has non-DER encoding\", ch,\n\t\t\t\t\t\t  level );\n\t\t\t\t}\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tfPos++;\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase INTEGER:\n\t\tcase ENUMERATED:\n\t\t\tif( item->length > 4 )\n\t\t\t\t{\n\t\t\t\tdumpHex( inFile, item->length, level, TRUE );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tprintValue( inFile, item->length, level );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\t\t}\n\t\t\tbreak;\n\n\t\tcase BITSTRING:\n\t\t\t{\n\t\t\tint ch;\n\n\t\t\tif( item->length < 2 )\n\t\t\t\tcomplainLength( item, level );\n\t\t\tif( ( ch = getc( inFile ) ) != 0 )\n\t\t\t\t{\n\t\t\t\tif( ch == EOF )\n\t\t\t\t\t{\n\t\t\t\t\tcomplainEOF( level, item->length );\n\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\tprintString( level, \" %d unused bit%s\",\n\t\t\t\t\t\t\t ch, ( ch != 1 ) ? \"s\" : \"\" );\n\t\t\t\t}\n\t\t\tfPos++;\n\t\t\tif( !--item->length && !ch )\n\t\t\t\t{\n\t\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\t\tcomplain( \"Object has zero length\", 0, level );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tif( item->length <= sizeof( int ) )\n\t\t\t\t{\n\t\t\t\t/* It's short enough to be a bit flag, dump it as a sequence\n\t\t\t\t   of bits */\n\t\t\t\tdumpBitString( inFile, ( int ) item->length, ch, level );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t/* Fall through to dump it as an octet string */\n\t\t\t}\n\n\t\tcase OCTETSTRING:\n\t\t\tif( checkEncapsulate( inFile, item->length ) )\n\t\t\t\t{\n\t\t\t\t/* It's something encapsulated inside the string, print it as\n\t\t\t\t   a constructed item */\n\t\t\t\tprintString( level, \"%s\", \", encapsulates\" );\n\t\t\t\tprintConstructed( inFile, level, item );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( !useStdin && !dumpText && \\\n\t\t\t\t( stringType = checkForText( inFile, item->length ) ) != STR_NONE )\n\t\t\t\t{\n\t\t\t\t/* If we'd be doing a straight hex dump and it looks like\n\t\t\t\t   encapsulated text, display it as such.  If the user has\n\t\t\t\t   overridden character set type checking and it's a string\n\t\t\t\t   type for which we normally perform type checking, we reset\n\t\t\t\t   its type to none */\n\t\t\t\tdisplayString( inFile, item->length, level, \\\n\t\t\t\t\t( !checkCharset && ( stringType == STR_IA5 || \\\n\t\t\t\t\t\t\t\t\t\t stringType == STR_PRINTABLE ) ) ? \\\n\t\t\t\t\tSTR_NONE : stringType );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\t\treturn;\n\t\t\t\t}\n\t\t\tdumpHex( inFile, item->length, level, FALSE );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\n\t\tcase OID:\n\t\t\t{\n\t\t\tchar textOID[ 128 ];\n\t\t\tint length, isValid;\n\n\t\t\t/* Hierarchical Object Identifier */\n\t\t\tif( item->length <= 0 || item->length >= MAX_OID_SIZE )\n\t\t\t\t{\n\t\t\t\tfflush( stdout );\n\t\t\t\tfprintf( stderr, \"\\nError: Object identifier length %ld too \"\n\t\t\t\t\t\t \"large.\\n\", item->length );\n\t\t\t\texit( EXIT_FAILURE );\n\t\t\t\t}\n\t\t\tlength = fread( buffer, 1, ( size_t ) item->length, inFile );\n\t\t\tfPos += item->length;\n\t\t\tif( item->length < 3 )\n\t\t\t\t{\n\t\t\t\tfputs( \".\\n\", output );\n\t\t\t\tcomplainLength( item, level );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( length < item->length )\n\t\t\t\t{\n\t\t\t\tfputs( \".\\n\", output );\n\t\t\t\tcomplain( \"Invalid OID data\", 0, level );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif( ( oidInfo = getOIDinfo( buffer, ( int ) item->length ) ) != NULL )\n\t\t\t\t{\n\t\t\t\t/* Convert the binary OID to text form */\n\t\t\t\tisValid = oidToString( textOID, &length, buffer,\n\t\t\t\t\t\t\t\t\t   ( int ) item->length );\n\n\t\t\t\t/* Check if LHS status info + indent + \"OID \" string + oid\n\t\t\t\t   name + \"(\" + oid value + \")\" will wrap */\n\t\t\t\tif( ( ( doPure ) ? 0 : INDENT_SIZE ) + ( level * 2 ) + 18 + \\\n\t\t\t\t\tstrlen( oidInfo->description ) + 2 + length >= outputWidth )\n\t\t\t\t\t{\n\t\t\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\t\t\tif( !doPure )\n\t\t\t\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\t\t\t\tdoIndent( level + 1 );\n\t\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tprintString( level, \"%c\", ' ' );\n\t\t\t\tprintString( level, \"%s (%s)\\n\", oidInfo->description, textOID );\n\n\t\t\t\t/* Display extra comments about the OID if required */\n\t\t\t\tif( extraOIDinfo && oidInfo->comment != NULL )\n\t\t\t\t\t{\n\t\t\t\t\tif( !doPure )\n\t\t\t\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\t\t\t\tdoIndent( level + 1 );\n\t\t\t\t\tprintString( level, \"(%s)\\n\", oidInfo->comment );\n\t\t\t\t\t}\n\t\t\t\tif( !isValid )\n\t\t\t\t\tcomplain( \"OID has invalid encoding\", 0, level );\n\t\t\t\tif( item->nonCanonical )\n\t\t\t\t\tcomplainLengthCanonical( item, level );\n\n\t\t\t\t/* If there's a warning associated with this OID, remember\n\t\t\t\t   that there was a problem */\n\t\t\t\tif( oidInfo->warn )\n\t\t\t\t\tnoWarnings++;\n\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t/* Print the OID as a text string */\n\t\t\tisValid = oidToString( textOID, &length, buffer,\n\t\t\t\t\t\t\t\t   ( int ) item->length );\n\t\t\tprintString( level, \" '%s'\\n\", textOID );\n\t\t\tif( item->length > MAX_SANE_OID_SIZE )\n\t\t\t\t{\n\t\t\t\t/* This only occurs with Microsoft's \"encode random noise\n\t\t\t\t   and call it an OID\" values, so we warn about the fact\n\t\t\t\t   that it's not really an OID */\n\t\t\t\tcomplain( \"OID contains random garbage\", 0, level );\n\t\t\t\t}\n\t\t\tif( !isValid )\n\t\t\t\tcomplain( \"OID has invalid encoding\", 0, level );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\t\t}\n\n\t\tcase EOC:\n\t\t\tprintString( level, \"<<EOC>> %c\", '\\n' );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\n\t\tcase NULLTAG:\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\n\t\tcase OBJDESCRIPTOR:\n\t\tcase GRAPHICSTRING:\n\t\tcase VISIBLESTRING:\n\t\tcase GENERALSTRING:\n\t\tcase UNIVERSALSTRING:\n\t\tcase NUMERICSTRING:\n\t\tcase VIDEOTEXSTRING:\n\t\tcase PRINTABLESTRING:\n\t\t\tdisplayString( inFile, item->length, level, STR_PRINTABLE );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase UTF8STRING:\n\t\t\tdisplayString( inFile, item->length, level, STR_UTF8 );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase BMPSTRING:\n\t\t\tdisplayString( inFile, item->length, level, STR_BMP );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase UTCTIME:\n\t\t\tdisplayString( inFile, item->length, level, STR_UTCTIME );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase GENERALIZEDTIME:\n\t\t\tdisplayString( inFile, item->length, level, STR_GENERALIZED );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase IA5STRING:\n\t\t\tdisplayString( inFile, item->length, level, STR_IA5 );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\t\tcase T61STRING:\n\t\t\tdisplayString( inFile, item->length, level, STR_LATIN1 );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tbreak;\n\n\t\tcase SEQUENCE:\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tcomplain( \"SEQUENCE has invalid primitive encoding\", 0, level );\n\t\t\tbreak;\n\n\t\tcase SET:\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tcomplain( \"SET has invalid primitive encoding\", 0, level );\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tprintString( level, \"%c\", '\\n' );\n\t\t\tif( !doPure )\n\t\t\t\tprintString( level, \"%s\", INDENT_STRING );\n\t\t\tdoIndent( level + 1 );\n\t\t\tprintString( level, \"%s\",\n\t\t\t\t\t\t \"Unrecognised primitive, hex value is:\");\n\t\t\tdumpHex( inFile, item->length, level, FALSE );\n\t\t\tif( item->nonCanonical )\n\t\t\t\tcomplainLengthCanonical( item, level );\n\t\t\tnoErrors++;\t\t/* Treat it as an error */\n\t\t}\n\t}\n\n/* Print a complex ASN.1 object */\n\nstatic long processObjectStart( FILE *inFile, const ASN1_ITEM *item )\n\t{\n\tlong length = LENGTH_MAGIC;\n\n\t/* If the length isn't known and the item has a definite length, set the\n\t   length to the item's length */\n\tif( !item->indefinite )\n\t\t{\n\t\tlength = item->headerSize + item->length;\n\n\t\t/* We can also adjust the width of the informational data column to\n\t\t   maximise the amount of screen real estate (for lengths less than\n\t\t   the default of four) or get rid of oversized columns (for lengths\n\t\t   greater than four) */\n\t\tif( length < 1000 )\n\t\t\tinfoWidth = 3;\n\t\telse\n\t\tif( length > 9999999 )\n\t\t\tinfoWidth = 8;\n\t\telse\n\t\tif( length > 999999 )\n\t\t\tinfoWidth = 7;\n\t\telse\n\t\tif( length > 99999 )\n\t\t\tinfoWidth = 6;\n\t\telse\n\t\tif( length > 9999 )\n\t\t\tinfoWidth = 5;\n\t\t}\n\n\t/* If the input isn't seekable, turn off some options that require the\n\t   use of fseek().  This check isn't perfect (some streams are slightly\n\t   seekable due to buffering) but it's better than nothing */\n\tif( fseek( inFile, -item->headerSize, SEEK_CUR ) )\n\t\t{\n\t\tuseStdin = TRUE;\n\t\tcheckEncaps = FALSE;\n\t\tputs( \"Warning: Input is non-seekable, some functionality has been \"\n\t\t\t  \"disabled.\" );\n\n\t\treturn( length );\n\t\t}\n\n\t/* If it looks like we've been given a text file, typically due to the\n\t   input being base64-encoded, check whether it is all text */\n\tif( ( isalnum( item->header[ 0 ] ) && isalnum( item->header[ 1 ] ) ) || \\\n\t\t  ( item->header[ 0 ] == '-' && item->header[ 1 ] == '-' ) )\n\t\t{\n\t\tBYTE buffer[ 4 ];\n\t\tint count, i;\n\n\t\tcount = fread( buffer, 1, 4, inFile );\n\t\tfor( i = 0; i < count; i++ )\n\t\t\t{\n\t\t\tif( buffer[ i ] != '-' && !isalnum( buffer[ i ] ) )\n\t\t\t\tbreak;\n\t\t\t}\n\t\tif( i >= 4 && \\\n\t\t\titem->header[ 0 ] == 0x30 || item->header[ 0 ] == 0x31 )\n\t\t\t{\n\t\t\t/* Special-case handling for situations that would produce a \n\t\t\t   false positive, items containing nested SEQUENCE (0x30)/SET \n\t\t\t   (0x31) of an appropriate length will look like ASCII since\n\t\t\t   the encoding is 0x30 0xXX 0x30 0xXX 0x30 0xXX, e.g. \"0g0e0c\",\n\t\t\t   so we check for the pattern [0|1] alnum [0|1] alnum ... */\n\t\t\tif( buffer[ 2 ] == 0x30 || buffer[ 2 ] == 0x31 )\n\t\t\t\t{\n\t\t\t\t/* It's at least 0x30 0xXX 0x30 0xXX, assume it's binary.\n\t\t\t\t   This can lead to a minute number of false negatives, but \n\t\t\t\t   that's OK since (a) it's no any normal encoding format \n\t\t\t\t   for ASN.1 binary data and (b) all it'll do is produce\n\t\t\t\t   an attempt to decode text as ASN.1 */\n\t\t\t\ti = 0;\n\t\t\t\t}\n\t\t\t}\n\t\tif( i >= 4 )\n\t\t\t{\n\t\t\tfputs( \"Error: This file appears to be a base64-encoded text \"\n\t\t\t\t   \"file, not binary data.\\n\", stderr );\n\t\t\tfputs( \"       In order to display it you first need to decode \"\n\t\t\t\t   \"it into its\\n\", stderr );\n\t\t\tfputs( \"       binary form.\\n\", stderr );\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\t\tfseek( inFile, -4, SEEK_CUR );\n\t\t}\n\n\t/* Undo the fseek() that we used to determine whether the input was\n\t   seekable */\n\tfseek( inFile, item->headerSize, SEEK_CUR );\n\n\treturn( length );\n\t}\n\nstatic int printAsn1( FILE *inFile, const int level, long length,\n\t\t\t\t\t  const int isIndefinite )\n\t{\n\tASN1_ITEM item;\n\tlong lastPos = fPos;\n\tint seenEOC = FALSE, status;\n\n\t/* Special-case for zero-length objects */\n\tif( !length && !isIndefinite )\n\t\treturn( 0 );\n\n\twhile( ( status = getItem( inFile, &item ) ) > 0 )\n\t\t{\n\t\tint nonOutlineObject = FALSE;\n\n\t\t/* Perform various special checks the first time that we're called */\n\t\tif( length == LENGTH_MAGIC )\n\t\t\tlength = processObjectStart( inFile, &item );\n\n\t\t/* Dump the header as hex data if requested */\n\t\tif( doDumpHeader )\n\t\t\tdumpHeader( inFile, &item, level );\n\n\t\t/* If we're displaying the ASN.1 outline only and it's not a\n\t\t   constructed object, don't display anything */\n\t\tif( doOutlineOnly && ( item.id & FORM_MASK ) != CONSTRUCTED )\n\t\t\tnonOutlineObject = TRUE;\n\n\t\t/* Print the offset and length, unless we're in pure ASN.1-only\n\t\t   output mode or we're displaying the outline only and it's not\n\t\t   a constructed object */\n\t\tif( item.header[ 0 ] == EOC )\n\t\t\t{\n\t\t\tseenEOC = TRUE;\n\t\t\tif( !isIndefinite)\n\t\t\t\tcomplain( \"Spurious EOC in definite-length item\", 0, level );\n\t\t\t}\n\t\tif( !doPure && !nonOutlineObject )\n\t\t\t{\n\t\t\tif( item.indefinite )\n\t\t\t\t{\n\t\t\t\tprintString( level, ( doHexValues ) ? \\\n\t\t\t\t\t\t\t\tLEN_HEX_INDEF : LEN_INDEF, lastPos );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( !seenEOC )\n\t\t\t\t\t{\n\t\t\t\t\tprintString( level, ( doHexValues ) ? \\\n\t\t\t\t\t\t\t\t\tLEN_HEX : LEN, lastPos, item.length );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t/* Print details on the item */\n\t\tif( !seenEOC )\n\t\t\t{\n\t\t\tif( !nonOutlineObject )\n\t\t\t\tdoIndent( level );\n\t\t\tprintASN1object( inFile, &item, level );\n\t\t\t}\n\n\t\t/* If it was an indefinite-length object (no length was ever set) and\n\t\t   we've come back to the top level, exit */\n\t\tif( length == LENGTH_MAGIC )\n\t\t\treturn( 0 );\n\n\t\tlength -= fPos - lastPos;\n\t\tlastPos = fPos;\n\t\tif( isIndefinite )\n\t\t\t{\n\t\t\tif( seenEOC )\n\t\t\t\treturn( 0 );\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tif( length <= 0 )\n\t\t\t\t{\n\t\t\t\tif( length < 0 )\n\t\t\t\t\treturn( ( int ) -length );\n\t\t\t\treturn( 0 );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tif( length == 1 )\n\t\t\t\t\t{\n\t\t\t\t\tconst int ch = fgetc( inFile );\n\n\t\t\t\t\t/* If we've run out of input but there should be more\n\t\t\t\t\t   present, let the caller know */\n\t\t\t\t\tif( ch == EOF )\n\t\t\t\t\t\treturn( 1 );\n\n\t\t\t\t\t/* No object can be one byte long, try and recover.  This\n\t\t\t\t\t   only works sometimes because it can be caused by\n\t\t\t\t\t   spurious data in an OCTET STRING hole or an incorrect\n\t\t\t\t\t   length encoding.  The following workaround tries to\n\t\t\t\t\t   recover from spurious data by skipping the byte if\n\t\t\t\t\t   it's zero or a non-basic-ASN.1 tag, but keeping it if\n\t\t\t\t\t   it could be valid ASN.1 */\n\t\t\t\t\tif( ch > 0 && ch <= 0x31 )\n\t\t\t\t\t\tungetc( ch, inFile );\n\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\tfPos++;\n\t\t\t\t\t\treturn( 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tif( status == -1 )\n\t\t{\n\t\tint i;\n\n\t\tfflush( stdout );\n\t\tfprintf( stderr, \"\\nError: Invalid data encountered at position \"\n\t\t\t\t \"%d:\", fPos );\n\t\tfor( i = 0; i < item.headerSize; i++ )\n\t\t\tfprintf( stderr, \" %02X\", item.header[ i ] );\n\t\tfprintf( stderr, \".\\n\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* If we see an EOF and there's supposed to be more data present,\n\t   complain */\n\tif( length && length != LENGTH_MAGIC )\n\t\t{\n\t\tfprintf( output, \"Error: Inconsistent object length, %ld byte%s \"\n\t\t\t\t \"difference.\\n\", length, ( length > 1 ) ? \"s\" : \"\" );\n\t\tnoErrors++;\n\t\t}\n\treturn( 0 );\n\t}\n\n/* Show usage and exit */\n\nstatic void usageExit( void )\n\t{\n\tputs( \"DumpASN1 - ASN.1 object dump/syntax check program.\" );\n\tputs( \"Copyright Peter Gutmann 1997 - 2016.  Last updated \" UPDATE_STRING \".\" );\n\tputs( \"\" );\n\n\tputs( \"Usage: dumpasn1 [-acdefghilmoprstuvwxz] <file>\" );\n\tputs( \"  Input options:\" );\n\tputs( \"       - = Take input from stdin (some options may not work properly)\" );\n\tputs( \"       -<number> = Start <number> bytes into the file\" );\n\tputs( \"       -- = End of arg list\" );\n\tputs( \"       -c<file> = Read Object Identifier info from alternate config file\" );\n\tputs( \"            (values will override equivalents in global config file)\" );\n\tputs( \"\" );\n\n\tputs( \"  Output options:\" );\n\tputs( \"       -f<file> = Dump object at offset -<number> to file (allows data to be\" );\n\tputs( \"            extracted from encapsulating objects)\" );\n\tputs( \"       -w<number> = Set width of output, default = 80 columns\" );\n\tputs( \"\" );\n\n\tputs( \"  Display options:\" );\n\tputs( \"       -a = Print all data in long data blocks, not just the first 128 bytes\" );\n\tputs( \"       -d = Print dots to show column alignment\" );\n\tputs( \"       -g = Display ASN.1 structure outline only (no primitive objects)\" );\n\tputs( \"       -h = Hex dump object header (tag+length) before the decoded output\" );\n\tputs( \"       -hh = Same as -h but display more of the object as hex data\" );\n\tputs( \"       -i = Use shallow indenting, for deeply-nested objects\" );\n\tputs( \"       -l = Long format, display extra info about Object Identifiers\" );\n\tputs( \"       -m<number>  = Maximum nesting level for which to display content\" );\n\tputs( \"       -p = Pure ASN.1 output without encoding information\" );\n\tputs( \"       -t = Display text values next to hex dump of data\" );\n\tputs( \"       -v = Verbose mode, equivalent to -ahlt\" );\n\tputs( \"\" );\n\n\tputs( \"  Format options:\" );\n\tputs( \"       -e = Don't print encapsulated data inside OCTET/BIT STRINGs\" );\n\tputs( \"       -r = Print bits in BIT STRING as encoded in reverse order\" );\n\tputs( \"       -u = Don't format UTCTime/GeneralizedTime string data\" );\n\tputs( \"       -x = Display size and offset in hex not decimal\" );\n\tputs( \"\" );\n\n\tputs( \"  Checking options:\" );\n\tputs( \"       -o = Don't check validity of character strings hidden in octet strings\" );\n\tputs( \"       -s = Syntax check only, don't dump ASN.1 structures\" );\n\tputs( \"       -z = Allow zero-length items\" );\n\tputs( \"\" );\n\n\tputs( \"Warnings generated by deprecated OIDs require the use of '-l' to be displayed.\" );\n\tputs( \"Program return code is the number of errors found or EXIT_SUCCESS.\" );\n\texit( EXIT_FAILURE );\n\t}\n\nint main( int argc, char *argv[] )\n\t{\n\tFILE *inFile, *outFile = NULL;\n#ifdef __WIN32__\n\tCONSOLE_SCREEN_BUFFER_INFO csbiInfo;\n#endif /* __WIN32__ */\n#ifdef __OS390__\n\tchar pathPtr[ FILENAME_MAX ];\n#else\n\tchar *pathPtr = argv[ 0 ];\n#endif /* __OS390__ */\n\tlong offset = 0;\n\tint moreArgs = TRUE, doCheckOnly = FALSE;\n\n#ifdef __OS390__\n\tmemset( pathPtr, '\\0', sizeof( pathPtr ) );\n\tgetcwd( pathPtr, sizeof( pathPtr ) );\n\tstrcat( pathPtr, \"/\" );\n#endif /* __OS390__ */\n\n\t/* Skip the program name */\n\targv++; argc--;\n\n\t/* Display usage if no args given */\n\tif( argc < 1 )\n\t\tusageExit();\n\toutput = stdout;\t/* Needs to be assigned at runtime */\n\n\t/* Get the output width.  Under Unix there's no safe way to do this, so\n\t   we default to 80 columns */\n#ifdef __WIN32__\n\tif( GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ),\n\t\t\t\t\t\t\t\t\t&csbiInfo ) )\n\t\toutputWidth = csbiInfo.dwSize.X;\n#endif /* __WIN32__ */\n\n\t/* Check for arguments */\n\twhile( argc && *argv[ 0 ] == '-' && moreArgs )\n\t\t{\n\t\tchar *argPtr = argv[ 0 ] + 1;\n\n\t\tif( !*argPtr )\n\t\t\tuseStdin = TRUE;\n\t\twhile( *argPtr )\n\t\t\t{\n\t\t\tif( isdigit( byteToInt( *argPtr ) ) )\n\t\t\t\t{\n\t\t\t\toffset = atol( argPtr );\n\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tswitch( toupper( byteToInt( *argPtr ) ) )\n\t\t\t\t{\n\t\t\t\tcase '-':\n\t\t\t\t\tmoreArgs = FALSE;\t/* GNU-style end-of-args flag */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'A':\n\t\t\t\t\tprintAllData = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'C':\n\t\t\t\t\tif( !readConfig( argPtr + 1, FALSE ) )\n\t\t\t\t\t\texit( EXIT_FAILURE );\n\t\t\t\t\twhile( argPtr[ 1 ] )\n\t\t\t\t\t\targPtr++;\t/* Skip rest of arg */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'D':\n\t\t\t\t\tprintDots = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'E':\n\t\t\t\t\tcheckEncaps = FALSE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'F':\n\t\t\t\t\tif( ( outFile = fopen( argPtr + 1, \"wb\" ) ) == NULL )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tperror( argPtr + 1 );\n\t\t\t\t\t\texit( EXIT_FAILURE );\n\t\t\t\t\t\t}\n\t\t\t\t\twhile( argPtr[ 1 ] )\n\t\t\t\t\t\targPtr++;\t/* Skip rest of arg */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'G':\n\t\t\t\t\tdoOutlineOnly = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'H':\n\t\t\t\t\tdoDumpHeader++;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'I':\n\t\t\t\t\tshallowIndent = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'L':\n\t\t\t\t\textraOIDinfo = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'M':\n\t\t\t\t\tmaxNestLevel = atoi( argPtr + 1 );\n\t\t\t\t\tif( maxNestLevel < 1 || maxNestLevel > 100 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tputs( \"Invalid maximum nesting level.\" );\n\t\t\t\t\t\texit( EXIT_FAILURE );\n\t\t\t\t\t\t}\n\t\t\t\t\twhile( argPtr[ 1 ] )\n\t\t\t\t\t\targPtr++;\t/* Skip rest of arg */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'O':\n\t\t\t\t\tcheckCharset = FALSE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'P':\n\t\t\t\t\tdoPure = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'R':\n\t\t\t\t\treverseBitString = !reverseBitString;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'S':\n\t\t\t\t\tdoCheckOnly = TRUE;\n#if defined( __WIN32__ )\n\t\t\t\t\t/* Under Windows we can't fclose( stdout ) because the\n\t\t\t\t\t   VC++ runtime reassigns the stdout handle to the next\n\t\t\t\t\t   open file (which is valid) but then scribbles stdout\n\t\t\t\t\t   garbage all over it for files larger than about 16K\n\t\t\t\t\t   (which isn't), so we have to make sure that the\n\t\t\t\t\t   stdout handle is pointed to something somewhere */\n\t\t\t\t\t( void ) freopen( \"nul\", \"w\", stdout );\n#elif defined( __UNIX__ )\n\t\t\t\t\t/* Safety feature in case any Unix libc is as broken\n\t\t\t\t\t   as the Win32 version */\n\t\t\t\t\t( void ) freopen( \"/dev/null\", \"w\", stdout );\n#else\n\t\t\t\t\tfclose( stdout );\n#endif /* OS-specific bypassing of stdout */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'T':\n\t\t\t\t\tdumpText = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'U':\n\t\t\t\t\trawTimeString = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'V':\n\t\t\t\t\tprintAllData = doDumpHeader = TRUE;\n\t\t\t\t\textraOIDinfo = dumpText = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'W':\n\t\t\t\t\toutputWidth = atoi( argPtr + 1 );\n\t\t\t\t\tif( outputWidth < 40 || outputWidth > 500 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\tputs( \"Invalid output width.\" );\n\t\t\t\t\t\texit( EXIT_FAILURE );\n\t\t\t\t\t\t}\n\t\t\t\t\twhile( argPtr[ 1 ] )\n\t\t\t\t\t\targPtr++;\t/* Skip rest of arg */\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'X':\n\t\t\t\t\tdoHexValues = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'Z':\n\t\t\t\t\tzeroLengthAllowed = TRUE;\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tprintf( \"Unknown argument '%c'.\\n\", *argPtr );\n\t\t\t\t\treturn( EXIT_SUCCESS );\n\t\t\t\t}\n\t\t\targPtr++;\n\t\t\t}\n\t\targv++;\n\t\targc--;\n\t\t}\n\n\t/* We can't use options that perform an fseek() if reading from stdin */\n\tif( useStdin && ( doDumpHeader || outFile != NULL ) )\n\t\t{\n\t\tputs( \"Can't use -f or -h when taking input from stdin\" );\n\t\texit( EXIT_FAILURE );\n\t\t}\n\n\t/* Check args and read the config file.  We don't bother weeding out\n\t   dups during the read because (a) the linear search would make the\n\t   process n^2, (b) during the dump process the search will terminate on\n\t   the first match so dups aren't that serious, and (c) there should be\n\t   very few dups present */\n\tif( argc != 1 && !useStdin )\n\t\tusageExit();\n\tif( !readGlobalConfig( pathPtr ) )\n\t\texit( EXIT_FAILURE );\n\n\t/* Dump the given file */\n\tif( useStdin )\n\t\tinFile = stdin;\n\telse\n\t\t{\n\t\tif( ( inFile = fopen( argv[ 0 ], \"rb\" ) ) == NULL )\n\t\t\t{\n\t\t\tperror( argv[ 0 ] );\n\t\t\tfreeConfig();\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\t\t}\n\tif( useStdin )\n\t\t{\n\t\twhile( offset-- )\n\t\t\tgetc( inFile );\n\t\t}\n\telse\n\t\tfseek( inFile, offset, SEEK_SET );\n\tif( outFile != NULL )\n\t\t{\n\t\tASN1_ITEM item;\n\t\tlong length;\n\t\tint i, status;\n\n\t\t/* Make sure that there's something there, and that it has a\n\t\t   definite length */\n\t\tstatus = getItem( inFile, &item );\n\t\tif( status == -1 )\n\t\t\t{\n\t\t\tputs( \"Non-ASN.1 data encountered.\" );\n\t\t\tfreeConfig();\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\t\tif( status == 0 )\n\t\t\t{\n\t\t\tputs( \"Nothing to read.\" );\n\t\t\tfreeConfig();\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\t\tif( item.indefinite )\n\t\t\t{\n\t\t\tputs( \"Cannot process indefinite-length item.\" );\n\t\t\tfreeConfig();\n\t\t\texit( EXIT_FAILURE );\n\t\t\t}\n\n\t\t/* Copy the item across, first the header and then the data */\n\t\tfor( i = 0; i < item.headerSize; i++ )\n\t\t\tputc( item.header[ i ], outFile );\n\t\tfor( length = 0; length < item.length && !feof( inFile ); length++ )\n\t\t\tputc( getc( inFile ), outFile );\n\t\tfclose( outFile );\n\n\t\tfseek( inFile, offset, SEEK_SET );\n\t\t}\n\tprintAsn1( inFile, 0, LENGTH_MAGIC, 0 );\n\tif( !useStdin && offset == 0 )\n\t\t{\n\t\tBYTE buffer[ 16 ];\n\t\tlong position = ftell( inFile );\n\n\t\t/* If we're dumping a standalone ASN.1 object and there's further\n\t\t   data appended to it, warn the user of its existence.  This is a\n\t\t   bit hit-and-miss since there may or may not be additional EOCs\n\t\t   present, dumpasn1 always stops once it knows that the data should\n\t\t   end (without trying to read any trailing EOCs) because data from\n\t\t   some sources has the EOCs truncated, and most apps know that they\n\t\t   have to stop at min( data_end, EOCs ).  To avoid false positives,\n\t\t   we skip at least 4 EOCs worth of data and if there's still more\n\t\t   present, we complain */\n\t\t( void ) fread( buffer, 1, 8, inFile );\t\t/* Skip 4 EOCs */\n\t\tif( !feof( inFile ) )\n\t\t\t{\n\t\t\tfprintf( output, \"Warning: Further data follows ASN.1 data at \"\n\t\t\t\t\t \"position %ld.\\n\", position );\n\t\t\tnoWarnings++;\n\t\t\t}\n\t\t}\n\tfclose( inFile );\n\tfreeConfig();\n\n\t/* Print a summary of warnings/errors if it's required or appropriate */\n\tif( !doPure )\n\t\t{\n\t\tfflush( stdout );\n\t\tif( !doCheckOnly )\n\t\t\tfputc( '\\n', stderr );\n\t\tfprintf( stderr, \"%d warning%s, %d error%s.\\n\", noWarnings,\n\t\t\t\t( noWarnings != 1 ) ? \"s\" : \"\", noErrors,\n\t\t\t\t( noErrors != 1 ) ? \"s\" : \"\" );\n\t\t}\n\n\treturn( ( noErrors ) ? noErrors : EXIT_SUCCESS );\n\t}\n"
  },
  {
    "path": "deps/cl345/tools/dumpasn1.cfg",
    "content": "# dumpasn1 Object Identifier configuration file, available from\n# http://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg.  Last updated 11\n# June 2018, or 20180611 if you want it that way.  This file is read by\n# dumpasn1.c and is used to display information on Object Identifiers found\n# in ASN.1 objects.  This is merely a list of things that you might\n# conceivably find in use somewhere, and should in no way be taken as a\n# guide to which OIDs to use - many of these will never been seen in the\n# wild, or should be shot on sight if encountered.\n#\n# The format of this file is as follows:\n#\n# - All blank lines and lines beginning with a '#' are ignored.\n#\n# - OIDs are described by a set of attributes, of which at least the 'OID'\n#\tand 'Description' must be present.  Optional attributes are a 'Comment'\n#\tand a 'Warning' (to indicate that dumpasn1 will display a warning if\n#\tthis OID is encountered).\n#\n# - Attributes are listed one per line.  The first attribute should be an\n#\t'OID' attribute since this is used to denote the start of a new OID\n#\tdescription.  The other attributes may be given in any order.\n#\n# - Offical attribute names vary widely depending on who's creating them.\n#\tIn an attempt to avoid a confusing mass of naming styles (in particular\n#\tthe more recent fashion trend of naming OIDs following formulae like\n#\tstandard-group-name-algorithm-mechanism-subalgorithm-more-standards-\n#\tmore-algorithms-I'd-like-to-thank-the-academy-etc rather than older forms\n#\tlike rsaWithSHA1 has lead to extremely noisy and hard-to-decipher names),\n#\tthis file aims for consistency by normalising the naming for attributes,\n#\thowever this means that the name used here may not entirely match the\n#\tactual name.\n#\n# See the rest of this file for examples of what an OID description should\n# look like.\n\n# Deutsche Telekom/Telesec\n\nOID = 0 2 262 1 10\nComment = Deutsche Telekom\nDescription = Telesec\n\nOID = 0 2 262 1 10 0\nComment = Telesec\nDescription = extension\n\nOID = 0 2 262 1 10 1\nComment = Telesec\nDescription = mechanism\n\nOID = 0 2 262 1 10 1 0\nComment = Telesec mechanism\nDescription = authentication\n\nOID = 0 2 262 1 10 1 0 1\nComment = Telesec authentication\nDescription = passwordAuthentication\n\nOID = 0 2 262 1 10 1 0 2\nComment = Telesec authentication\nDescription = protectedPasswordAuthentication\n\nOID = 0 2 262 1 10 1 0 3\nComment = Telesec authentication\nDescription = oneWayX509Authentication\n\nOID = 0 2 262 1 10 1 0 4\nComment = Telesec authentication\nDescription = twoWayX509Authentication\n\nOID = 0 2 262 1 10 1 0 5\nComment = Telesec authentication\nDescription = threeWayX509Authentication\n\nOID = 0 2 262 1 10 1 0 6\nComment = Telesec authentication\nDescription = oneWayISO9798Authentication\n\nOID = 0 2 262 1 10 1 0 7\nComment = Telesec authentication\nDescription = twoWayISO9798Authentication\n\nOID = 0 2 262 1 10 1 0 8\nComment = Telesec authentication\nDescription = telekomAuthentication\n\nOID = 0 2 262 1 10 1 1\nComment = Telesec mechanism\nDescription = signature\n\nOID = 0 2 262 1 10 1 1 1\nComment = Telesec mechanism\nDescription = md4WithRSAAndISO9697\n\nOID = 0 2 262 1 10 1 1 2\nComment = Telesec mechanism\nDescription = md4WithRSAAndTelesecSignatureStandard\n\nOID = 0 2 262 1 10 1 1 3\nComment = Telesec mechanism\nDescription = md5WithRSAAndISO9697\n\nOID = 0 2 262 1 10 1 1 4\nComment = Telesec mechanism\nDescription = md5WithRSAAndTelesecSignatureStandard\n\n# PKCS #1 signature with RIPEMD-160\nOID = 0 2 262 1 10 1 1 5\nComment = Telesec mechanism\nDescription = ripemd160WithRSAAndTelekomSignatureStandard\n\n# RIPEMD-160 with raw RSA (ie no padding, just 160 bytes encrypted) signature\nOID = 0 2 262 1 10 1 1 9\nComment = Telesec signature\nDescription = hbciRsaSignature\n\nOID = 0 2 262 1 10 1 2\nComment = Telesec mechanism\nDescription = encryption\n\n# Specially recommended by the NSA for German use\nOID = 0 2 262 1 10 1 2 0\nComment = Telesec encryption\nDescription = none\n\nOID = 0 2 262 1 10 1 2 1\nComment = Telesec encryption\nDescription = rsaTelesec\n\nOID = 0 2 262 1 10 1 2 2\nComment = Telesec encryption\nDescription = des\n\nOID = 0 2 262 1 10 1 2 2 1\nComment = Telesec encryption\nDescription = desECB\n\nOID = 0 2 262 1 10 1 2 2 2\nComment = Telesec encryption\nDescription = desCBC\n\nOID = 0 2 262 1 10 1 2 2 3\nComment = Telesec encryption\nDescription = desOFB\n\nOID = 0 2 262 1 10 1 2 2 4\nComment = Telesec encryption\nDescription = desCFB8\n\nOID = 0 2 262 1 10 1 2 2 5\nComment = Telesec encryption\nDescription = desCFB64\n\nOID = 0 2 262 1 10 1 2 3\nComment = Telesec encryption\nDescription = des3\n\nOID = 0 2 262 1 10 1 2 3 1\nComment = Telesec encryption\nDescription = des3ECB\n\nOID = 0 2 262 1 10 1 2 3 2\nComment = Telesec encryption\nDescription = des3CBC\n\nOID = 0 2 262 1 10 1 2 3 3\nComment = Telesec encryption\nDescription = des3OFB\n\nOID = 0 2 262 1 10 1 2 3 4\nComment = Telesec encryption\nDescription = des3CFB8\n\nOID = 0 2 262 1 10 1 2 3 5\nComment = Telesec encryption\nDescription = des3CFB64\n\nOID = 0 2 262 1 10 1 2 4\nComment = Telesec encryption\nDescription = magenta\n\nOID = 0 2 262 1 10 1 2 5\nComment = Telesec encryption\nDescription = idea\n\nOID = 0 2 262 1 10 1 2 5 1\nComment = Telesec encryption\nDescription = ideaECB\n\nOID = 0 2 262 1 10 1 2 5 2\nComment = Telesec encryption\nDescription = ideaCBC\n\nOID = 0 2 262 1 10 1 2 5 3\nComment = Telesec encryption\nDescription = ideaOFB\n\nOID = 0 2 262 1 10 1 2 5 4\nComment = Telesec encryption\nDescription = ideaCFB8\n\nOID = 0 2 262 1 10 1 2 5 5\nComment = Telesec encryption\nDescription = ideaCFB64\n\nOID = 0 2 262 1 10 1 3\nComment = Telesec mechanism\nDescription = oneWayFunction\n\nOID = 0 2 262 1 10 1 3 1\nComment = Telesec one-way function\nDescription = md4\n\nOID = 0 2 262 1 10 1 3 2\nComment = Telesec one-way function\nDescription = md5\n\nOID = 0 2 262 1 10 1 3 3\nComment = Telesec one-way function\nDescription = sqModNX509\n\nOID = 0 2 262 1 10 1 3 4\nComment = Telesec one-way function\nDescription = sqModNISO\n\nOID = 0 2 262 1 10 1 3 5\nComment = Telesec one-way function\nDescription = ripemd128\n\nOID = 0 2 262 1 10 1 3 6\nComment = Telesec one-way function\nDescription = hashUsingBlockCipher\n\nOID = 0 2 262 1 10 1 3 7\nComment = Telesec one-way function\nDescription = mac\n\nOID = 0 2 262 1 10 1 3 8\nComment = Telesec one-way function\nDescription = ripemd160\n\nOID = 0 2 262 1 10 1 4\nComment = Telesec mechanism\nDescription = fecFunction\n\nOID = 0 2 262 1 10 1 4 1\nComment = Telesec mechanism\nDescription = reedSolomon\n\nOID = 0 2 262 1 10 2\nComment = Telesec\nDescription = module\n\nOID = 0 2 262 1 10 2 0\nComment = Telesec module\nDescription = algorithms\n\nOID = 0 2 262 1 10 2 1\nComment = Telesec module\nDescription = attributeTypes\n\nOID = 0 2 262 1 10 2 2\nComment = Telesec module\nDescription = certificateTypes\n\nOID = 0 2 262 1 10 2 3\nComment = Telesec module\nDescription = messageTypes\n\nOID = 0 2 262 1 10 2 4\nComment = Telesec module\nDescription = plProtocol\n\nOID = 0 2 262 1 10 2 5\nComment = Telesec module\nDescription = smeAndComponentsOfSme\n\nOID = 0 2 262 1 10 2 6\nComment = Telesec module\nDescription = fec\n\nOID = 0 2 262 1 10 2 7\nComment = Telesec module\nDescription = usefulDefinitions\n\nOID = 0 2 262 1 10 2 8\nComment = Telesec module\nDescription = stefiles\n\nOID = 0 2 262 1 10 2 9\nComment = Telesec module\nDescription = sadmib\n\nOID = 0 2 262 1 10 2 10\nComment = Telesec module\nDescription = electronicOrder\n\nOID = 0 2 262 1 10 2 11\nComment = Telesec module\nDescription = telesecTtpAsymmetricApplication\n\nOID = 0 2 262 1 10 2 12\nComment = Telesec module\nDescription = telesecTtpBasisApplication\n\nOID = 0 2 262 1 10 2 13\nComment = Telesec module\nDescription = telesecTtpMessages\n\nOID = 0 2 262 1 10 2 14\nComment = Telesec module\nDescription = telesecTtpTimeStampApplication\n\nOID = 0 2 262 1 10 3\nComment = Telesec\nDescription = objectClass\n\nOID = 0 2 262 1 10 3 0\nComment = Telesec object class\nDescription = telesecOtherName\n\nOID = 0 2 262 1 10 3 1\nComment = Telesec object class\nDescription = directory\n\nOID = 0 2 262 1 10 3 2\nComment = Telesec object class\nDescription = directoryType\n\nOID = 0 2 262 1 10 3 3\nComment = Telesec object class\nDescription = directoryGroup\n\nOID = 0 2 262 1 10 3 4\nComment = Telesec object class\nDescription = directoryUser\n\nOID = 0 2 262 1 10 3 5\nComment = Telesec object class\nDescription = symmetricKeyEntry\n\nOID = 0 2 262 1 10 4\nComment = Telesec\nDescription = package\n\nOID = 0 2 262 1 10 5\nComment = Telesec\nDescription = parameter\n\nOID = 0 2 262 1 10 6\nComment = Telesec\nDescription = nameBinding\n\nOID = 0 2 262 1 10 7\nComment = Telesec\nDescription = attribute\n\nOID = 0 2 262 1 10 7 0\nComment = Telesec attribute\nDescription = applicationGroupIdentifier\n\nOID = 0 2 262 1 10 7 1\nComment = Telesec attribute\nDescription = certificateType\n\nOID = 0 2 262 1 10 7 2\nComment = Telesec attribute\nDescription = telesecCertificate\n\nOID = 0 2 262 1 10 7 3\nComment = Telesec attribute\nDescription = certificateNumber\n\nOID = 0 2 262 1 10 7 4\nComment = Telesec attribute\nDescription = certificateRevocationList\n\nOID = 0 2 262 1 10 7 5\nComment = Telesec attribute\nDescription = creationDate\n\nOID = 0 2 262 1 10 7 6\nComment = Telesec attribute\nDescription = issuer\n\nOID = 0 2 262 1 10 7 7\nComment = Telesec attribute\nDescription = namingAuthority\n\nOID = 0 2 262 1 10 7 8\nComment = Telesec attribute\nDescription = publicKeyDirectory\n\nOID = 0 2 262 1 10 7 9\nComment = Telesec attribute\nDescription = securityDomain\n\nOID = 0 2 262 1 10 7 10\nComment = Telesec attribute\nDescription = subject\n\nOID = 0 2 262 1 10 7 11\nComment = Telesec attribute\nDescription = timeOfRevocation\n\nOID = 0 2 262 1 10 7 12\nComment = Telesec attribute\nDescription = userGroupReference\n\nOID = 0 2 262 1 10 7 13\nComment = Telesec attribute\nDescription = validity\n\nOID = 0 2 262 1 10 7 14\nComment = Telesec attribute\nDescription = zert93\n\n# It really is called that\nOID = 0 2 262 1 10 7 15\nComment = Telesec attribute\nDescription = securityMessEnv\n\nOID = 0 2 262 1 10 7 16\nComment = Telesec attribute\nDescription = anonymizedPublicKeyDirectory\n\nOID = 0 2 262 1 10 7 17\nComment = Telesec attribute\nDescription = telesecGivenName\n\nOID = 0 2 262 1 10 7 18\nComment = Telesec attribute\nDescription = nameAdditions\n\nOID = 0 2 262 1 10 7 19\nComment = Telesec attribute\nDescription = telesecPostalCode\n\nOID = 0 2 262 1 10 7 20\nComment = Telesec attribute\nDescription = nameDistinguisher\n\nOID = 0 2 262 1 10 7 21\nComment = Telesec attribute\nDescription = telesecCertificateList\n\nOID = 0 2 262 1 10 7 22\nComment = Telesec attribute\nDescription = teletrustCertificateList\n\nOID = 0 2 262 1 10 7 23\nComment = Telesec attribute\nDescription = x509CertificateList\n\nOID = 0 2 262 1 10 7 24\nComment = Telesec attribute\nDescription = timeOfIssue\n\nOID = 0 2 262 1 10 7 25\nComment = Telesec attribute\nDescription = physicalCardNumber\n\nOID = 0 2 262 1 10 7 26\nComment = Telesec attribute\nDescription = fileType\n\nOID = 0 2 262 1 10 7 27\nComment = Telesec attribute\nDescription = ctlFileIsArchive\n\nOID = 0 2 262 1 10 7 28\nComment = Telesec attribute\nDescription = emailAddress\n\nOID = 0 2 262 1 10 7 29\nComment = Telesec attribute\nDescription = certificateTemplateList\n\nOID = 0 2 262 1 10 7 30\nComment = Telesec attribute\nDescription = directoryName\n\nOID = 0 2 262 1 10 7 31\nComment = Telesec attribute\nDescription = directoryTypeName\n\nOID = 0 2 262 1 10 7 32\nComment = Telesec attribute\nDescription = directoryGroupName\n\nOID = 0 2 262 1 10 7 33\nComment = Telesec attribute\nDescription = directoryUserName\n\nOID = 0 2 262 1 10 7 34\nComment = Telesec attribute\nDescription = revocationFlag\n\nOID = 0 2 262 1 10 7 35\nComment = Telesec attribute\nDescription = symmetricKeyEntryName\n\nOID = 0 2 262 1 10 7 36\nComment = Telesec attribute\nDescription = glNumber\n\nOID = 0 2 262 1 10 7 37\nComment = Telesec attribute\nDescription = goNumber\n\nOID = 0 2 262 1 10 7 38\nComment = Telesec attribute\nDescription = gKeyData\n\nOID = 0 2 262 1 10 7 39\nComment = Telesec attribute\nDescription = zKeyData\n\nOID = 0 2 262 1 10 7 40\nComment = Telesec attribute\nDescription = ktKeyData\n\nOID = 0 2 262 1 10 7 41\nComment = Telesec attribute\nDescription = ktKeyNumber\n\nOID = 0 2 262 1 10 7 51\nComment = Telesec attribute\nDescription = timeOfRevocationGen\n\nOID = 0 2 262 1 10 7 52\nComment = Telesec attribute\nDescription = liabilityText\n\nOID = 0 2 262 1 10 8\nComment = Telesec\nDescription = attributeGroup\n\nOID = 0 2 262 1 10 9\nComment = Telesec\nDescription = action\n\nOID = 0 2 262 1 10 10\nComment = Telesec\nDescription = notification\n\nOID = 0 2 262 1 10 11\nComment = Telesec\nDescription = snmp-mibs\n\nOID = 0 2 262 1 10 11 1\nComment = Telesec SNMP MIBs\nDescription = securityApplication\n\nOID = 0 2 262 1 10 12\nComment = Telesec\nDescription = certAndCrlExtensionDefinitions\n\n# ISIS-MTT SigG-Profile: Indicates that an attribute certificate\n# exists, which limits the usability of this public key certificate.\nOID = 0 2 262 1 10 12 0\nComment = Telesec cert/CRL extension\nDescription = liabilityLimitationFlag\n\nOID = 0 2 262 1 10 12 1\nComment = Telesec cert/CRL extension\nDescription = telesecCertIdExt\n\nOID = 0 2 262 1 10 12 2\nComment = Telesec cert/CRL extension\nDescription = Telesec policyIdentifier\n\nOID = 0 2 262 1 10 12 3\nComment = Telesec cert/CRL extension\nDescription = telesecPolicyQualifierID\n\nOID = 0 2 262 1 10 12 4\nComment = Telesec cert/CRL extension\nDescription = telesecCRLFilteredExt\n\nOID = 0 2 262 1 10 12 5\nComment = Telesec cert/CRL extension\nDescription = telesecCRLFilterExt\n\nOID = 0 2 262 1 10 12 6\nComment = Telesec cert/CRL extension\nDescription = telesecNamingAuthorityExt\n\n# BSI e-Pass (TR-03110/TR-03111).  TA = Terminal Authentication (Passport\n# PKI with monthly global cert updates), CA = Chip Authentication\n# (Auth using static [EC]DH), PACE = Password Authenticated Connection\n# Establishment, RI = Restricted Information Protocol, Eid = eID\n# Smartcard Application, PT = Privileged Terminal, IS = Inspection\n# System, AT = Authentication Terminal, ST = Signature Terminal.\n\nOID = 0 4 0 127 0 7\nComment = BSI TR-03110/TR-03111\nDescription = bsi\n\nOID = 0 4 0 127 0 7 1\nComment = BSI TR-03111\nDescription = bsiEcc\n\nOID = 0 4 0 127 0 7 1 1\nComment = BSI TR-03111\nDescription = bsifieldType\n\nOID = 0 4 0 127 0 7 1 1 1\nComment = BSI TR-03111\nDescription = bsiPrimeField\n\nOID = 0 4 0 127 0 7 1 1 2\nComment = BSI TR-03111\nDescription = bsiCharacteristicTwoField\n\nOID = 0 4 0 127 0 7 1 1 2 2\nComment = BSI TR-03111\nDescription = bsiECTLVKeyFormat\n\nOID = 0 4 0 127 0 7 1 1 2 2 1\nComment = BSI TR-03111\nDescription = bsiECTLVPublicKey\n\nOID = 0 4 0 127 0 7 1 1 2 3\nComment = BSI TR-03111\nDescription = bsiCharacteristicTwoBasis\n\nOID = 0 4 0 127 0 7 1 1 2 3 1\nComment = BSI TR-03111\nDescription = bsiGnBasis\n\nOID = 0 4 0 127 0 7 1 1 2 3 2\nComment = BSI TR-03111\nDescription = bsiTpBasis\n\nOID = 0 4 0 127 0 7 1 1 2 3 3\nComment = BSI TR-03111\nDescription = bsiPpBasis\n\nOID = 0 4 0 127 0 7 1 1 4 1\nComment = BSI TR-03111\nDescription = bsiEcdsaSignatures\n\nOID = 0 4 0 127 0 7 1 1 4 1 1\nComment = BSI TR-03111\nDescription = bsiEcdsaWithSHA1\n\nOID = 0 4 0 127 0 7 1 1 4 1 2\nComment = BSI TR-03111\nDescription = bsiEcdsaWithSHA224\n\nOID = 0 4 0 127 0 7 1 1 4 1 3\nComment = BSI TR-03111\nDescription = bsiEcdsaWithSHA256\n\nOID = 0 4 0 127 0 7 1 1 4 1 4\nComment = BSI TR-03111\nDescription = bsiEcdsaWithSHA384\n\nOID = 0 4 0 127 0 7 1 1 4 1 5\nComment = BSI TR-03111\nDescription = bsiEcdsaWithSHA512\n\nOID = 0 4 0 127 0 7 1 1 4 1 6\nComment = BSI TR-03111\nDescription = bsiEcdsaWithRIPEMD160\n\nOID = 0 4 0 127 0 7 1 1 5 1 1\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDF\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 1\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithSHA1\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 2\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithSHA224\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 3\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithSHA256\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 4\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithSHA384\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 5\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithSHA512\n\nOID = 0 4 0 127 0 7 1 1 5 1 1 6\nComment = BSI TR-03111\nDescription = bsiEckaEgX963KDFWithRIPEMD160\n\nOID = 0 4 0 127 0 7 1 1 5 1 2\nComment = BSI TR-03111\nDescription = bsiEckaEgSessionKDF\n\nOID = 0 4 0 127 0 7 1 1 5 1 2 1\nComment = BSI TR-03111\nDescription = bsiEckaEgSessionKDFWith3DES\n\nOID = 0 4 0 127 0 7 1 1 5 1 2 2\nComment = BSI TR-03111\nDescription = bsiEckaEgSessionKDFWithAES128\n\nOID = 0 4 0 127 0 7 1 1 5 1 2 3\nComment = BSI TR-03111\nDescription = bsiEckaEgSessionKDFWithAES192\n\nOID = 0 4 0 127 0 7 1 1 5 1 2 4\nComment = BSI TR-03111\nDescription = bsiEckaEgSessionKDFWithAES256\n\nOID = 0 4 0 127 0 7 1 1 5 2\nComment = BSI TR-03111\nDescription = bsiEckaDH\n\nOID = 0 4 0 127 0 7 1 1 5 2 1\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDF\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 1\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithSHA1\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 2\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithSHA224\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 3\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithSHA256\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 4\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithSHA384\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 5\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithSHA512\n\nOID = 0 4 0 127 0 7 1 1 5 2 1 6\nComment = BSI TR-03111\nDescription = bsiEckaDHX963KDFWithRIPEMD160\n\nOID = 0 4 0 127 0 7 1 1 5 2 2\nComment = BSI TR-03111\nDescription = bsiEckaDHSessionKDF\n\nOID = 0 4 0 127 0 7 1 1 5 2 2 1\nComment = BSI TR-03111\nDescription = bsiEckaDHSessionKDFWith3DES\n\nOID = 0 4 0 127 0 7 1 1 5 2 2 2\nComment = BSI TR-03111\nDescription = bsiEckaDHSessionKDFWithAES128\n\nOID = 0 4 0 127 0 7 1 1 5 2 2 3\nComment = BSI TR-03111\nDescription = bsiEckaDHSessionKDFWithAES192\n\nOID = 0 4 0 127 0 7 1 1 5 2 2 4\nComment = BSI TR-03111\nDescription = bsiEckaDHSessionKDFWithAES256\n\nOID = 0 4 0 127 0 7 1 2\nComment = BSI TR-03111\nDescription = bsiEcKeyType\n\nOID = 0 4 0 127 0 7 1 2 1\nComment = BSI TR-03111\nDescription = bsiEcPublicKey\n\nOID = 0 4 0 127 0 7 1 5 1\nComment = BSI TR-03111\nDescription = bsiKaeg\n\nOID = 0 4 0 127 0 7 1 5 1 1\nComment = BSI TR-03111\nDescription = bsiKaegWithX963KDF\n\nOID = 0 4 0 127 0 7 1 5 1 2\nComment = BSI TR-03111\nDescription = bsiKaegWith3DESKDF\n\nOID = 0 4 0 127 0 7 2 2 1\nComment = BSI TR-03110. Formerly known as bsiCA, now moved to ...2.2.3.x\nDescription = bsiPK\n\nOID = 0 4 0 127 0 7 2 2 1 1\nComment = BSI TR-03110. Formerly known as bsiCA_DH, now moved to ...2.2.3.x\nDescription = bsiPK_DH\n\nOID = 0 4 0 127 0 7 2 2 1 2\nComment = BSI TR-03110. Formerly known as bsiCA_ECDH, now moved to ...2.2.3.x\nDescription = bsiPK_ECDH\n\nOID = 0 4 0 127 0 7 2 2 2\nComment = BSI TR-03110\nDescription = bsiTA\n\nOID = 0 4 0 127 0 7 2 2 2 1\nComment = BSI TR-03110\nDescription = bsiTA_RSA\n\nOID = 0 4 0 127 0 7 2 2 2 1 1\nComment = BSI TR-03110\nDescription = bsiTA_RSAv1_5_SHA1\n\nOID = 0 4 0 127 0 7 2 2 2 1 2\nComment = BSI TR-03110\nDescription = bsiTA_RSAv1_5_SHA256\n\nOID = 0 4 0 127 0 7 2 2 2 1 3\nComment = BSI TR-03110\nDescription = bsiTA_RSAPSS_SHA1\n\nOID = 0 4 0 127 0 7 2 2 2 1 4\nComment = BSI TR-03110\nDescription = bsiTA_RSAPSS_SHA256\n\nOID = 0 4 0 127 0 7 2 2 2 1 5\nComment = BSI TR-03110\nDescription = bsiTA_RSAv1_5_SHA512\n\nOID = 0 4 0 127 0 7 2 2 2 1 6\nComment = BSI TR-03110\nDescription = bsiTA_RSAPSS_SHA512\n\nOID = 0 4 0 127 0 7 2 2 2 2\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA\n\nOID = 0 4 0 127 0 7 2 2 2 2 1\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA_SHA1\n\nOID = 0 4 0 127 0 7 2 2 2 2 2\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA_SHA224\n\nOID = 0 4 0 127 0 7 2 2 2 2 3\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA_SHA256\n\nOID = 0 4 0 127 0 7 2 2 2 2 4\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA_SHA384\n\nOID = 0 4 0 127 0 7 2 2 2 2 5\nComment = BSI TR-03110\nDescription = bsiTA_ECDSA_SHA512\n\nOID = 0 4 0 127 0 7 2 2 3\nComment = BSI TR-03110\nDescription = bsiCA\n\nOID = 0 4 0 127 0 7 2 2 3 1\nComment = BSI TR-03110\nDescription = bsiCA_DH\n\nOID = 0 4 0 127 0 7 2 2 3 1 1\nComment = BSI TR-03110\nDescription = bsiCA_DH_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 3 1 2\nComment = BSI TR-03110\nDescription = bsiCA_DH_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 3 1 3\nComment = BSI TR-03110\nDescription = bsiCA_DH_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 3 1 4\nComment = BSI TR-03110\nDescription = bsiCA_DH_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 3 2\nComment = BSI TR-03110\nDescription = bsiCA_ECDH\n\nOID = 0 4 0 127 0 7 2 2 3 2 1\nComment = BSI TR-03110\nDescription = bsiCA_ECDH_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 3 2 2\nComment = BSI TR-03110\nDescription = bsiCA_ECDH_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 3 2 3\nComment = BSI TR-03110\nDescription = bsiCA_ECDH_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 3 2 4\nComment = BSI TR-03110\nDescription = bsiCA_ECDH_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 4\nComment = BSI TR-03110\nDescription = bsiPACE\n\nOID = 0 4 0 127 0 7 2 2 4 1\nComment = BSI TR-03110\nDescription = bsiPACE_DH_GM\n\nOID = 0 4 0 127 0 7 2 2 4 1 1\nComment = BSI TR-03110\nDescription = bsiPACE_DH_GM_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 4 1 2\nComment = BSI TR-03110\nDescription = bsiPACE_DH_GM_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 4 1 3\nComment = BSI TR-03110\nDescription = bsiPACE_DH_GM_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 4 1 4\nComment = BSI TR-03110\nDescription = bsiPACE_DH_GM_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 4 2\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_GM\n\nOID = 0 4 0 127 0 7 2 2 4 2 1\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_GM_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 4 2 2\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_GM_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 4 2 3\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_GM_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 4 2 4\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_GM_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 4 3\nComment = BSI TR-03110\nDescription = bsiPACE_DH_IM\n\nOID = 0 4 0 127 0 7 2 2 4 3 1\nComment = BSI TR-03110\nDescription = bsiPACE_DH_IM_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 4 3 2\nComment = BSI TR-03110\nDescription = bsiPACE_DH_IM_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 4 3 3\nComment = BSI TR-03110\nDescription = bsiPACE_DH_IM_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 4 3 4\nComment = BSI TR-03110\nDescription = bsiPACE_DH_IM_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 4 4\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_IM\n\nOID = 0 4 0 127 0 7 2 2 4 4 1\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_IM_3DES_CBC_CBC\n\nOID = 0 4 0 127 0 7 2 2 4 4 2\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_IM_AES_CBC_CMAC_128\n\nOID = 0 4 0 127 0 7 2 2 4 4 3\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_IM_AES_CBC_CMAC_192\n\nOID = 0 4 0 127 0 7 2 2 4 4 4\nComment = BSI TR-03110\nDescription = bsiPACE_ECDH_IM_AES_CBC_CMAC_256\n\nOID = 0 4 0 127 0 7 2 2 5\nComment = BSI TR-03110\nDescription = bsiRI\n\nOID = 0 4 0 127 0 7 2 2 5 1\nComment = BSI TR-03110\nDescription = bsiRI_DH\n\nOID = 0 4 0 127 0 7 2 2 5 1 1\nComment = BSI TR-03110\nDescription = bsiRI_DH_SHA1\n\nOID = 0 4 0 127 0 7 2 2 5 1 2\nComment = BSI TR-03110\nDescription = bsiRI_DH_SHA224\n\nOID = 0 4 0 127 0 7 2 2 5 1 3\nComment = BSI TR-03110\nDescription = bsiRI_DH_SHA256\n\nOID = 0 4 0 127 0 7 2 2 5 1 4\nComment = BSI TR-03110\nDescription = bsiRI_DH_SHA384\n\nOID = 0 4 0 127 0 7 2 2 5 1 5\nComment = BSI TR-03110\nDescription = bsiRI_DH_SHA512\n\nOID = 0 4 0 127 0 7 2 2 5 2\nComment = BSI TR-03110\nDescription = bsiRI_ECDH\n\nOID = 0 4 0 127 0 7 2 2 5 2 1\nComment = BSI TR-03110\nDescription = bsiRI_ECDH_SHA1\n\nOID = 0 4 0 127 0 7 2 2 5 2 2\nComment = BSI TR-03110\nDescription = bsiRI_ECDH_SHA224\n\nOID = 0 4 0 127 0 7 2 2 5 2 3\nComment = BSI TR-03110\nDescription = bsiRI_ECDH_SHA256\n\nOID = 0 4 0 127 0 7 2 2 5 2 4\nComment = BSI TR-03110\nDescription = bsiRI_ECDH_SHA384\n\nOID = 0 4 0 127 0 7 2 2 5 2 5\nComment = BSI TR-03110\nDescription = bsiRI_ECDH_SHA512\n\nOID = 0 4 0 127 0 7 2 2 6\nComment = BSI TR-03110\nDescription = bsiCardInfo\n\nOID = 0 4 0 127 0 7 2 2 7\nComment = BSI TR-03110\nDescription = bsiEidSecurity\n\nOID = 0 4 0 127 0 7 2 2 8\nComment = BSI TR-03110\nDescription = bsiPT\n\nOID = 0 4 0 127 0 7 3 1 2\nComment = BSI TR-03110\nDescription = bsiEACRoles\n\nOID = 0 4 0 127 0 7 3 1 2 1\nComment = BSI TR-03110\nDescription = bsiEACRolesIS\n\nOID = 0 4 0 127 0 7 3 1 2 2\nComment = BSI TR-03110\nDescription = bsiEACRolesAT\n\nOID = 0 4 0 127 0 7 3 1 2 3\nComment = BSI TR-03110\nDescription = bsiEACRolesST\n\nOID = 0 4 0 127 0 7 3 1 3\nComment = BSI TR-03110\nDescription = bsiTAv2ce\n\nOID = 0 4 0 127 0 7 3 1 3 1\nComment = BSI TR-03110\nDescription = bsiTAv2ceDescription\n\nOID = 0 4 0 127 0 7 3 1 3 1 1\nComment = BSI TR-03110\nDescription = bsiTAv2ceDescriptionPlainText\n\nOID = 0 4 0 127 0 7 3 1 3 1 2\nComment = BSI TR-03110\nDescription = bsiTAv2ceDescriptionIA5String\n\nOID = 0 4 0 127 0 7 3 1 3 1 3\nComment = BSI TR-03110\nDescription = bsiTAv2ceDescriptionOctetString\n\nOID = 0 4 0 127 0 7 3 1 3 2\nComment = BSI TR-03110\nDescription = bsiTAv2ceTerminalSector\n\nOID = 0 4 0 127 0 7 3 1 4\nComment = BSI TR-03110\nDescription = bsiAuxData\n\nOID = 0 4 0 127 0 7 3 1 4 1\nComment = BSI TR-03110\nDescription = bsiAuxDataBirthday\n\nOID = 0 4 0 127 0 7 3 1 4 2\nComment = BSI TR-03110\nDescription = bsiAuxDataExpireDate\n\nOID = 0 4 0 127 0 7 3 1 4 3\nComment = BSI TR-03110\nDescription = bsiAuxDataCommunityID\n\nOID = 0 4 0 127 0 7 3 1 5\nComment = BSI TR-03110\nDescription = bsiDefectList\n\nOID = 0 4 0 127 0 7 3 1 5 1\nComment = BSI TR-03110\nDescription = bsiDefectAuthDefect\n\nOID = 0 4 0 127 0 7 3 1 5 1 1\nComment = BSI TR-03110\nDescription = bsiDefectCertRevoked\n\nOID = 0 4 0 127 0 7 3 1 5 1 2\nComment = BSI TR-03110\nDescription = bsiDefectCertReplaced\n\nOID = 0 4 0 127 0 7 3 1 5 1 3\nComment = BSI TR-03110\nDescription = bsiDefectChipAuthKeyRevoked\n\nOID = 0 4 0 127 0 7 3 1 5 1 4\nComment = BSI TR-03110\nDescription = bsiDefectActiveAuthKeyRevoked\n\nOID = 0 4 0 127 0 7 3 1 5 2\nComment = BSI TR-03110\nDescription = bsiDefectEPassportDefect\n\nOID = 0 4 0 127 0 7 3 1 5 2 1\nComment = BSI TR-03110\nDescription = bsiDefectEPassportDGMalformed\n\nOID = 0 4 0 127 0 7 3 1 5 2 2\nComment = BSI TR-03110\nDescription = bsiDefectSODInvalid\n\nOID = 0 4 0 127 0 7 3 1 5 3\nComment = BSI TR-03110\nDescription = bsiDefectEIDDefect\n\nOID = 0 4 0 127 0 7 3 1 5 3 1\nComment = BSI TR-03110\nDescription = bsiDefectEIDDGMalformed\n\nOID = 0 4 0 127 0 7 3 1 5 3 2\nComment = BSI TR-03110\nDescription = bsiDefectEIDIntegrity\n\nOID = 0 4 0 127 0 7 3 1 5 4\nComment = BSI TR-03110\nDescription = bsiDefectDocumentDefect\n\nOID = 0 4 0 127 0 7 3 1 5 4 1\nComment = BSI TR-03110\nDescription = bsiDefectCardSecurityMalformed\n\nOID = 0 4 0 127 0 7 3 1 5 4 2\nComment = BSI TR-03110\nDescription = bsiDefectChipSecurityMalformed\n\nOID = 0 4 0 127 0 7 3 1 5 4 3\nComment = BSI TR-03110\nDescription = bsiDefectPowerDownReq\n\nOID = 0 4 0 127 0 7 3 1 6\nComment = BSI TR-03110\nDescription = bsiListContentDescription\n\nOID = 0 4 0 127 0 7 3 2 1\nComment = BSI TR-03110\nDescription = bsiSecurityObject\n\nOID = 0 4 0 127 0 7 3 2 2\nComment = BSI TR-03110\nDescription = bsiBlackList\n\nOID = 0 4 0 127 0 7 3 4 2 2\nComment = BSI TR-03109\nDescription = bsiSignedUpdateDeviceAdmin\n\nOID = 0 4 0 127 0 7 4 1 1 1\nComment = BSI TR-03109\nDescription = bsiCertReqMsgs\n\nOID = 0 4 0 127 0 7 4 1 1 2\nComment = BSI TR-03109\nDescription = bsiCertReqMsgswithOuterSignature\n\nOID = 0 4 0 127 0 7 4 1 1 3\nComment = BSI TR-03109\nDescription = bsiAuthorizedCertReqMsgs\n\nOID = 0 4 0 127 0 7 4 1 2 2\nComment = BSI TR-03109\nDescription = bsiSignedRevReqs\n\n# ETSI TS 101 862 V1.3.3 (2006-01), Qualified certificate profile\n\nOID = 0 4 0 1862\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcsProfile\n\nOID = 0 4 0 1862 1\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcs\n\nOID = 0 4 0 1862 1 1\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcsCompliance\n\nOID = 0 4 0 1862 1 2\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcsLimitValue\n\nOID = 0 4 0 1862 1 3\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcsRetentionPeriod\n\nOID = 0 4 0 1862 1 4\nComment = ETSI TS 101 862 qualified certificates\nDescription = etsiQcsQcSSCD\n\n# RFC 1274 (X.500 attribute collection from the UK, thus the weird OID).\n\nOID = 0 9 2342 19200300 100 1 1\nComment = Some oddball X.500 attribute collection\nDescription = userID\n\nOID = 0 9 2342 19200300 100 1 3\nComment = Some oddball X.500 attribute collection\nDescription = rfc822Mailbox\n\n# RFC 2247, How to Kludge an FQDN as a DN (or words to that effect), another\n# fine product of the UK (also present in the above mentioned RFC 1274).\n\nOID = 0 9 2342 19200300 100 1 25\nComment = Men are from Mars, this OID is from Pluto\nDescription = domainComponent\n\n# ISO standards\n\nOID = 1 0 10118 3 0 49\nComment = ISO 10118-3 hash function\nDescription = ripemd160\n\nOID = 1 0 10118 3 0 50\nComment = ISO 10118-3 hash function\nDescription = ripemd128\n\nOID = 1 0 10118 3 0 55\nComment = ISO 10118-3 hash function\nDescription = whirlpool\n\n# Queensland Government PKI\n\nOID = 1 2 36 1 3 1 1 1\nComment = Queensland Government PKI\nDescription = qgpki\n\nOID = 1 2 36 1 3 1 1 1 1\nComment = QGPKI policies\nDescription = qgpkiPolicies\n\nOID = 1 2 36 1 3 1 1 1 1 1\nComment = QGPKI policy\nDescription = qgpkiMedIntermedCA\n\nOID = 1 2 36 1 3 1 1 1 1 1 1\nComment = QGPKI policy\nDescription = qgpkiMedIntermedIndividual\n\nOID = 1 2 36 1 3 1 1 1 1 1 2\nComment = QGPKI policy\nDescription = qgpkiMedIntermedDeviceControl\n\nOID = 1 2 36 1 3 1 1 1 1 1 3\nComment = QGPKI policy\nDescription = qgpkiMedIntermedDevice\n\nOID = 1 2 36 1 3 1 1 1 1 1 4\nComment = QGPKI policy\nDescription = qgpkiMedIntermedAuthorisedParty\n\nOID = 1 2 36 1 3 1 1 1 1 1 5\nComment = QGPKI policy\nDescription = qgpkiMedIntermedDeviceSystem\n\nOID = 1 2 36 1 3 1 1 1 1 2\nComment = QGPKI policy\nDescription = qgpkiMedIssuingCA\n\nOID = 1 2 36 1 3 1 1 1 1 2 1\nComment = QGPKI policy\nDescription = qgpkiMedIssuingIndividual\n\nOID = 1 2 36 1 3 1 1 1 1 2 2\nComment = QGPKI policy\nDescription = qgpkiMedIssuingDeviceControl\n\nOID = 1 2 36 1 3 1 1 1 1 2 3\nComment = QGPKI policy\nDescription = qgpkiMedIssuingDevice\n\nOID = 1 2 36 1 3 1 1 1 1 2 4\nComment = QGPKI policy\nDescription = qgpkiMedIssuingAuthorisedParty\n\nOID = 1 2 36 1 3 1 1 1 1 2 5\nComment = QGPKI policy\nDescription = qgpkiMedIssuingClientAuth\n\nOID = 1 2 36 1 3 1 1 1 1 2 6\nComment = QGPKI policy\nDescription = qgpkiMedIssuingServerAuth\n\nOID = 1 2 36 1 3 1 1 1 1 2 7\nComment = QGPKI policy\nDescription = qgpkiMedIssuingDataProt\n\nOID = 1 2 36 1 3 1 1 1 1 2 8\nComment = QGPKI policy\nDescription = qgpkiMedIssuingTokenAuth\n\nOID = 1 2 36 1 3 1 1 1 1 3\nComment = QGPKI policy\nDescription = qgpkiBasicIntermedCA\n\nOID = 1 2 36 1 3 1 1 1 1 3 1\nComment = QGPKI policy\nDescription = qgpkiBasicIntermedDeviceSystem\n\nOID = 1 2 36 1 3 1 1 1 1 4\nComment = QGPKI policy\nDescription = qgpkiBasicIssuingCA\n\nOID = 1 2 36 1 3 1 1 1 1 4 1\nComment = QGPKI policy\nDescription = qgpkiBasicIssuingClientAuth\n\nOID = 1 2 36 1 3 1 1 1 1 4 2\nComment = QGPKI policy\nDescription = qgpkiBasicIssuingServerAuth\n\nOID = 1 2 36 1 3 1 1 1 1 4 3\nComment = QGPKI policy\nDescription = qgpkiBasicIssuingDataSigning\n\nOID = 1 2 36 1 3 1 1 1 2\nComment = QGPKI assurance level\nDescription = qgpkiAssuranceLevel\n\nOID = 1 2 36 1 3 1 1 1 2 1\nComment = QGPKI assurance level\nDescription = qgpkiAssuranceRudimentary\n\nOID = 1 2 36 1 3 1 1 1 2 2\nComment = QGPKI assurance level\nDescription = qgpkiAssuranceBasic\n\nOID = 1 2 36 1 3 1 1 1 2 3\nComment = QGPKI assurance level\nDescription = qgpkiAssuranceMedium\n\nOID = 1 2 36 1 3 1 1 1 2 4\nComment = QGPKI assurance level\nDescription = qgpkiAssuranceHigh\n\nOID = 1 2 36 1 3 1 1 1 3\nComment = QGPKI policies\nDescription = qgpkiCertFunction\n\nOID = 1 2 36 1 3 1 1 1 3 1\nComment = QGPKI policies\nDescription = qgpkiFunctionIndividual\n\nOID = 1 2 36 1 3 1 1 1 3 2\nComment = QGPKI policies\nDescription = qgpkiFunctionDevice\n\nOID = 1 2 36 1 3 1 1 1 3 3\nComment = QGPKI policies\nDescription = qgpkiFunctionAuthorisedParty\n\nOID = 1 2 36 1 3 1 1 1 3 4\nComment = QGPKI policies\nDescription = qgpkiFunctionDeviceControl\n\nOID = 1 2 36 1 3 1 2\nComment = Queensland Police PKI\nDescription = qpspki\n\nOID = 1 2 36 1 3 1 2 1\nComment = Queensland Police PKI\nDescription = qpspkiPolicies\n\nOID = 1 2 36 1 3 1 2 1 2\nComment = Queensland Police PKI\nDescription = qpspkiPolicyBasic\n\nOID = 1 2 36 1 3 1 2 1 3\nComment = Queensland Police PKI\nDescription = qpspkiPolicyMedium\n\nOID = 1 2 36 1 3 1 2 1 4\nComment = Queensland Police PKI\nDescription = qpspkiPolicyHigh\n\nOID = 1 2 36 1 3 1 3 2\nComment = Queensland Transport PKI\nDescription = qtmrpki\n\nOID = 1 2 36 1 3 1 3 2 1\nComment = Queensland Transport PKI\nDescription = qtmrpkiPolicies\n\nOID = 1 2 36 1 3 1 3 2 2\nComment = Queensland Transport PKI\nDescription = qtmrpkiPurpose\n\nOID = 1 2 36 1 3 1 3 2 2 1\nComment = Queensland Transport PKI purpose\nDescription = qtmrpkiIndividual\n\nOID = 1 2 36 1 3 1 3 2 2 2\nComment = Queensland Transport PKI purpose\nDescription = qtmrpkiDeviceControl\n\nOID = 1 2 36 1 3 1 3 2 2 3\nComment = Queensland Transport PKI purpose\nDescription = qtmrpkiDevice\n\nOID = 1 2 36 1 3 1 3 2 2 4\nComment = Queensland Transport PKI purpose\nDescription = qtmrpkiAuthorisedParty\n\nOID = 1 2 36 1 3 1 3 2 2 5\nComment = Queensland Transport PKI purpose\nDescription = qtmrpkiDeviceSystem\n\nOID = 1 2 36 1 3 1 3 2 3\nComment = Queensland Transport PKI\nDescription = qtmrpkiDevice\n\nOID = 1 2 36 1 3 1 3 2 3 1\nComment = Queensland Transport PKI device\nDescription = qtmrpkiDriverLicense\n\nOID = 1 2 36 1 3 1 3 2 3 2\nComment = Queensland Transport PKI device\nDescription = qtmrpkiIndustryAuthority\n\nOID = 1 2 36 1 3 1 3 2 3 3\nComment = Queensland Transport PKI device\nDescription = qtmrpkiMarineLicense\n\nOID = 1 2 36 1 3 1 3 2 3 4\nComment = Queensland Transport PKI device\nDescription = qtmrpkiAdultProofOfAge\n\nOID = 1 2 36 1 3 1 3 2 3 5\nComment = Queensland Transport PKI device\nDescription = qtmrpkiSam\n\nOID = 1 2 36 1 3 1 3 2 4\nComment = Queensland Transport PKI\nDescription = qtmrpkiAuthorisedParty\n\nOID = 1 2 36 1 3 1 3 2 4 1\nComment = Queensland Transport PKI authorised party\nDescription = qtmrpkiTransportInspector\n\nOID = 1 2 36 1 3 1 3 2 4 2\nComment = Queensland Transport PKI authorised party\nDescription = qtmrpkiPoliceOfficer\n\nOID = 1 2 36 1 3 1 3 2 4 3\nComment = Queensland Transport PKI authorised party\nDescription = qtmrpkiSystem\n\nOID = 1 2 36 1 3 1 3 2 4 4\nComment = Queensland Transport PKI authorised party\nDescription = qtmrpkiLiquorLicensingInspector\n\nOID = 1 2 36 1 3 1 3 2 4 5\nComment = Queensland Transport PKI authorised party\nDescription = qtmrpkiMarineEnforcementOfficer\n\n# Australian Government\n\nOID = 1 2 36 1 333 1\nComment = Australian Government corporate taxpayer ID\nDescription = australianBusinessNumber\n\n# Signet\n#\n# Australia uses the corporate tax identifier (ABN) as de facto unique\n# identifiers in OIDs, thus the bizarre fourth value.  See also Certs\n# Australia below and other Australian corporate OIDs.\n\nOID = 1 2 36 68980861 1 1 2\nComment = Signet CA\nDescription = signetPersonal\n\nOID = 1 2 36 68980861 1 1 3\nComment = Signet CA\nDescription = signetBusiness\n\nOID = 1 2 36 68980861 1 1 4\nComment = Signet CA\nDescription = signetLegal\n\nOID = 1 2 36 68980861 1 1 10\nComment = Signet CA\nDescription = signetPilot\n\nOID = 1 2 36 68980861 1 1 11\nComment = Signet CA\nDescription = signetIntraNet\n\nOID = 1 2 36 68980861 1 1 20\nComment = Signet CA\nDescription = signetPolicy\n\n# Certificates Australia.\n\nOID = 1 2 36 75878867 1 100 1 1\nComment = Certificates Australia CA\nDescription = certificatesAustraliaPolicy\n\n# China GM Standards Committee\n\nOID = 1 2 156 10197 1\nComment = China GM Standards Committee\nDescription = gmtCryptographicAlgorithm\n\nOID = 1 2 156 10197 1 100\nComment = China GM Standards Committee\nDescription = gmtBlockCipher\n\nOID = 1 2 156 10197 1 102\nComment = China GM Standards Committee\nDescription = sm1Cipher\n\nOID = 1 2 156 10197 1 103\nComment = China GM Standards Committee\nDescription = ssf33Cipher\n\nOID = 1 2 156 10197 1 104\nComment = China GM Standards Committee\nDescription = sm4Cipher\n\nOID = 1 2 156 10197 1 200\nComment = China GM Standards Committee\nDescription = gmtStreamCipher\n\nOID = 1 2 156 10197 1 201\nComment = China GM Standards Committee\nDescription = zucCipher\n\nOID = 1 2 156 10197 1 300\nComment = China GM Standards Committee\nDescription = gmtPublicKeyCryptography\n\nOID = 1 2 156 10197 1 301\nComment = China GM Standards Committee\nDescription = sm2ECC\n\nOID = 1 2 156 10197 1 301 1\nComment = China GM Standards Committee\nDescription = sm2-1DigitalSignature\n\nOID = 1 2 156 10197 1 301 2\nComment = China GM Standards Committee\nDescription = sm2-2KeyExchange\n\nOID = 1 2 156 10197 1 301 3\nComment = China GM Standards Committee\nDescription = sm2-3PublicKeyEncryption\n\nOID = 1 2 156 10197 1 302\nComment = China GM Standards Committee\nDescription = gmtSM9IBE\n\nOID = 1 2 156 10197 1 302 1\nComment = China GM Standards Committee\nDescription = sm9-1DigitalSignature\n\nOID = 1 2 156 10197 1 302 2\nComment = China GM Standards Committee\nDescription = sm9-2KeyExchange\n\nOID = 1 2 156 10197 1 302 3\nComment = China GM Standards Committee\nDescription = sm9-3PublicKeyEncryption\n\nOID = 1 2 156 10197 1 400\nComment = China GM Standards Committee\nDescription = gmtHashAlgorithm\n\nOID = 1 2 156 10197 1 401\nComment = China GM Standards Committee\nDescription = sm3Hash\n\nOID = 1 2 156 10197 1 401 1\nComment = China GM Standards Committee\nDescription = sm3HashWithoutKey\n\nOID = 1 2 156 10197 1 401 2\nComment = China GM Standards Committee\nDescription = sm3HashWithKey\n\nOID = 1 2 156 10197 1 500\nComment = China GM Standards Committee\nDescription = gmtDigestSigning\n\nOID = 1 2 156 10197 1 501\nComment = China GM Standards Committee\nDescription = sm2withSM3\n\nOID = 1 2 156 10197 1 504\nComment = China GM Standards Committee\nDescription = rsaWithSM3\n\nOID = 1 2 156 10197 4 3\nComment = China GM Standards Committee\nDescription = gmtCertificateAuthority\n\nOID = 1 2 156 10197 6\nComment = China GM Standards Committee\nDescription = gmtStandardClass\n\nOID = 1 2 156 10197 6 1\nComment = China GM Standards Committee\nDescription = gmtFoundationClass\n\nOID = 1 2 156 10197 6 1 1\nComment = China GM Standards Committee\nDescription = gmtAlgorithmClass\n\nOID = 1 2 156 10197 6 1 1 1\nComment = China GM Standards Committee\nDescription = zucStandard\n\nOID = 1 2 156 10197 6 1 1 2\nComment = China GM Standards Committee\nDescription = sm4Standard\n\nOID = 1 2 156 10197 6 1 1 3\nComment = China GM Standards Committee\nDescription = sm2Standard\n\nOID = 1 2 156 10197 6 1 1 4\nComment = China GM Standards Committee\nDescription = sm3Standard\n\nOID = 1 2 156 10197 6 1 2\nComment = China GM Standards Committee\nDescription = gmtIDClass\n\nOID = 1 2 156 10197 6 1 2 1\nComment = China GM Standards Committee\nDescription = gmtCryptoID\n\nOID = 1 2 156 10197 6 1 3\nComment = China GM Standards Committee\nDescription = gmtOperationModes\n\nOID = 1 2 156 10197 6 1 4\nComment = China GM Standards Committee\nDescription = gmtSecurityMechanism\n\nOID = 1 2 156 10197 6 1 4 1\nComment = China GM Standards Committee\nDescription = gmtSM2Specification\n\nOID = 1 2 156 10197 6 1 4 2\nComment = China GM Standards Committee\nDescription = gmtSM2CryptographicMessageSyntax\n\nOID = 1 2 156 10197 6 2\nComment = China GM Standards Committee\nDescription = gmtDeviceClass\n\nOID = 1 2 156 10197 6 3\nComment = China GM Standards Committee\nDescription = gmtServiceClass\n\nOID = 1 2 156 10197 6 4\nComment = China GM Standards Committee\nDescription = gmtInfrastructure\n\nOID = 1 2 156 10197 6 5\nComment = China GM Standards Committee\nDescription = gmtTestingClass\n\nOID = 1 2 156 10197 6 5 1\nComment = China GM Standards Committee\nDescription = gmtRandomTestingClass\n\nOID = 1 2 156 10197 6 6\nComment = China GM Standards Committee\nDescription = gmtManagementClass\n\n# Mitsubishi\n\nOID = 1 2 392 200011 61 1 1 1\nComment = Mitsubishi security algorithm\nDescription = mitsubishiSecurityAlgorithm\n\nOID = 1 2 392 200011 61 1 1 1 1\nComment = Mitsubishi security algorithm\nDescription = misty1-cbc\n\n# Korean Information Security Agency\n\nOID = 1 2 410 200004 1\nComment = KISA algorithm\nDescription = kisaAlgorithm\n\nOID = 1 2 410 200004 1 1\nComment = Korean DSA\nDescription = kcdsa\n\nOID = 1 2 410 200004 1 2\nComment = Korean hash algorithm\nDescription = has160\n\nOID = 1 2 410 200004 1 3\nComment = Korean SEED algorithm, ECB mode\nDescription = seedECB\n\nOID = 1 2 410 200004 1 4\nComment = Korean SEED algorithm, CBC mode\nDescription = seedCBC\n\nOID = 1 2 410 200004 1 5\nComment = Korean SEED algorithm, OFB mode\nDescription = seedOFB\n\nOID = 1 2 410 200004 1 6\nComment = Korean SEED algorithm, CFB mode\nDescription = seedCFB\n\nOID = 1 2 410 200004 1 7\nComment = Korean SEED algorithm, MAC mode\nDescription = seedMAC\n\nOID = 1 2 410 200004 1 8\nComment = Korean signature algorithm\nDescription = kcdsaWithHAS160\n\nOID = 1 2 410 200004 1 9\nComment = Korean signature algorithm\nDescription = kcdsaWithSHA1\n\nOID = 1 2 410 200004 1 10\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithHAS160AndSEED-ECB\n\nOID = 1 2 410 200004 1 11\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithHAS160AndSEED-CBC\n\nOID = 1 2 410 200004 1 12\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithHAS160AndSEED-CFB\n\nOID = 1 2 410 200004 1 13\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithHAS160AndSEED-OFB\n\nOID = 1 2 410 200004 1 14\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithSHA1AndSEED-ECB\n\nOID = 1 2 410 200004 1 15\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithSHA1AndSEED-CBC\n\nOID = 1 2 410 200004 1 16\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithSHA1AndSEED-CFB\n\nOID = 1 2 410 200004 1 17\nComment = Korean SEED algorithm, PBE key derivation\nDescription = pbeWithSHA1AndSEED-OFB\n\nOID = 1 2 410 200004 1 20\nComment = Korean signature algorithm\nDescription = rsaWithHAS160\n\nOID = 1 2 410 200004 1 21\nComment = Korean DSA\nDescription = kcdsa1\n\nOID = 1 2 410 200004 2\nComment = KISA NPKI certificate policies\nDescription = npkiCP\n\nOID = 1 2 410 200004 2 1\nComment = KISA NPKI certificate policies\nDescription = npkiSignaturePolicy\n\nOID = 1 2 410 200004 3\nComment = KISA NPKI key usage\nDescription = npkiKP\n\nOID = 1 2 410 200004 4\nComment = KISA NPKI attribute\nDescription = npkiAT\n\nOID = 1 2 410 200004 5\nComment = KISA NPKI licensed CA\nDescription = npkiLCA\n\nOID = 1 2 410 200004 5 1\nComment = KISA NPKI licensed CA\nDescription = npkiSignKorea\n\nOID = 1 2 410 200004 5 2\nComment = KISA NPKI licensed CA\nDescription = npkiSignGate\n\nOID = 1 2 410 200004 5 3\nComment = KISA NPKI licensed CA\nDescription = npkiNcaSign\n\nOID = 1 2 410 200004 6\nComment = KISA NPKI otherName\nDescription = npkiON\n\nOID = 1 2 410 200004 7\nComment = KISA NPKI application\nDescription = npkiAPP\n\nOID = 1 2 410 200004 7 1\nComment = KISA NPKI application\nDescription = npkiSMIME\n\nOID = 1 2 410 200004 7 1 1\nComment = KISA NPKI application\nDescription = npkiSMIMEAlgo\n\nOID = 1 2 410 200004 7 1 1 1\nComment = KISA NPKI application\nDescription = npkiCmsSEEDWrap\n\nOID = 1 2 410 200004 10\nComment = KISA NPKI\nDescription = npki\n\nOID = 1 2 410 200004 10 1\nComment = KISA NPKI attribute\nDescription = npkiAttribute\n\nOID = 1 2 410 200004 10 1 1\nComment = KISA NPKI attribute\nDescription = npkiIdentifyData\n\n# Duplicates 1 2 410 200004 10 1 1 4\nOID = 1 2 410 200004 10 1 1 1\nComment = KISA NPKI attribute\nDescription = npkiVID\n\nOID = 1 2 410 200004 10 1 1 2\nComment = KISA NPKI attribute\nDescription = npkiEncryptedVID\n\nOID = 1 2 410 200004 10 1 1 3\nComment = KISA NPKI attribute\nDescription = npkiRandomNum\n\n# Duplicates 1 2 410 200004 10 1 1 1\nOID = 1 2 410 200004 10 1 1 4\nComment = KISA NPKI attribute\nDescription = npkiVID\n\n# Korean National Security Research Institute\n\nOID = 1 2 410 200046 1 1\nComment = ARIA algorithm modes\nDescription = aria1AlgorithmModes\n\nOID = 1 2 410 200046 1 1 1\nComment = ARIA algorithm modes\nDescription = aria128-ecb\n\nOID = 1 2 410 200046 1 1 2\nComment = ARIA algorithm modes\nDescription = aria128-cbc\n\nOID = 1 2 410 200046 1 1 3\nComment = ARIA algorithm modes\nDescription = aria128-cfb\n\nOID = 1 2 410 200046 1 1 4\nComment = ARIA algorithm modes\nDescription = aria128-ofb\n\nOID = 1 2 410 200046 1 1 5\nComment = ARIA algorithm modes\nDescription = aria128-ctr\n\nOID = 1 2 410 200046 1 1 6\nComment = ARIA algorithm modes\nDescription = aria192-ecb\n\nOID = 1 2 410 200046 1 1 7\nComment = ARIA algorithm modes\nDescription = aria192-cbc\n\nOID = 1 2 410 200046 1 1 8\nComment = ARIA algorithm modes\nDescription = aria192-cfb\n\nOID = 1 2 410 200046 1 1 9\nComment = ARIA algorithm modes\nDescription = aria192-ofb\n\nOID = 1 2 410 200046 1 1 10\nComment = ARIA algorithm modes\nDescription = aria192-ctr\n\nOID = 1 2 410 200046 1 1 11\nComment = ARIA algorithm modes\nDescription = aria256-ecb\n\nOID = 1 2 410 200046 1 1 12\nComment = ARIA algorithm modes\nDescription = aria256-cbc\n\nOID = 1 2 410 200046 1 1 13\nComment = ARIA algorithm modes\nDescription = aria256-cfb\n\nOID = 1 2 410 200046 1 1 14\nComment = ARIA algorithm modes\nDescription = aria256-ofb\n\nOID = 1 2 410 200046 1 1 15\nComment = ARIA algorithm modes\nDescription = aria256-ctr\n\nOID = 1 2 410 200046 1 1 21\nComment = ARIA algorithm modes\nDescription = aria128-cmac\n\nOID = 1 2 410 200046 1 1 22\nComment = ARIA algorithm modes\nDescription = aria192-cmac\n\nOID = 1 2 410 200046 1 1 23\nComment = ARIA algorithm modes\nDescription = aria256-cmac\n\nOID = 1 2 410 200046 1 1 31\nComment = ARIA algorithm modes\nDescription = aria128-ocb2\n\nOID = 1 2 410 200046 1 1 32\nComment = ARIA algorithm modes\nDescription = aria192-ocb2\n\nOID = 1 2 410 200046 1 1 33\nComment = ARIA algorithm modes\nDescription = aria256-ocb2\n\nOID = 1 2 410 200046 1 1 34\nComment = ARIA algorithm modes\nDescription = aria128-gcm\n\nOID = 1 2 410 200046 1 1 35\nComment = ARIA algorithm modes\nDescription = aria192-gcm\n\nOID = 1 2 410 200046 1 1 36\nComment = ARIA algorithm modes\nDescription = aria256-gcm\n\nOID = 1 2 410 200046 1 1 37\nComment = ARIA algorithm modes\nDescription = aria128-ccm\n\nOID = 1 2 410 200046 1 1 38\nComment = ARIA algorithm modes\nDescription = aria192-ccm\n\nOID = 1 2 410 200046 1 1 39\nComment = ARIA algorithm modes\nDescription = aria256-ccm\n\nOID = 1 2 410 200046 1 1 40\nComment = ARIA algorithm modes\nDescription = aria128-keywrap\n\nOID = 1 2 410 200046 1 1 41\nComment = ARIA algorithm modes\nDescription = aria192-keywrap\n\nOID = 1 2 410 200046 1 1 42\nComment = ARIA algorithm modes\nDescription = aria256-keywrap\n\nOID = 1 2 410 200046 1 1 43\nComment = ARIA algorithm modes\nDescription = aria128-keywrapWithPad\n\nOID = 1 2 410 200046 1 1 44\nComment = ARIA algorithm modes\nDescription = aria192-keywrapWithPad\n\nOID = 1 2 410 200046 1 1 45\nComment = ARIA algorithm modes\nDescription = aria256-keywrapWithPad\n\n# GOST algorithm identifiers, assigned by CryptoPRO (tm) in RFCs and\n# implementations\n\nOID = 1 2 643 2 2 3\nComment = GOST R 34.10-2001 + GOST R 34.11-94 signature\nDescription = gostSignature\n\nOID = 1 2 643 2 2 4\nComment = GOST R 34.10-94 + GOST R 34.11-94 signature. Obsoleted by GOST R 34.10-2001\nDescription = gost94Signature\nWarning\n\nOID = 1 2 643 2 2 19\nComment = GOST R 34.10-2001 (ECC) public key\nDescription = gostPublicKey\n\nOID = 1 2 643 2 2 20\nComment = GOST R 34.10-94 public key. Obsoleted by GOST R 34.10-2001\nDescription = gost94PublicKey\nWarning\n\nOID = 1 2 643 2 2 21\nComment = GOST 28147-89 (symmetric key block cipher)\nDescription = gostCipher\n\nOID = 1 2 643 2 2 31 0\nComment = Test params for GOST 28147-89\nDescription = testCipherParams\n\nOID = 1 2 643 2 2 31 1\nComment = CryptoPro params A (default, variant 'Verba-O') for GOST 28147-89\nDescription = cryptoProCipherA\n\nOID = 1 2 643 2 2 31 2\nComment = CryptoPro params B (variant 1) for GOST 28147-89\nDescription = cryptoProCipherB\n\nOID = 1 2 643 2 2 31 3\nComment = CryptoPro params C (variant 2) for GOST 28147-89\nDescription = cryptoProCipherC\n\nOID = 1 2 643 2 2 31 4\nComment = CryptoPro params D (variant 3) for GOST 28147-89\nDescription = cryptoProCipherD\n\nOID = 1 2 643 2 2 31 5\nComment = Oscar-1.1 params for GOST 28147-89\nDescription = oscar11Cipher\n\nOID = 1 2 643 2 2 31 6\nComment = Oscar-1.0 params for GOST 28147-89\nDescription = oscar10Cipher\n\nOID = 1 2 643 2 2 31 7\nComment = RIC-1 params for GOST 28147-89\nDescription = ric1Cipher\n\nOID = 1 2 643 2 2 31 12\nComment = TC26 params 2 for GOST 28147-89\nDescription = tc26CipherA\n\nOID = 1 2 643 2 2 31 13\nComment = TC26 params 1 for GOST 28147-89\nDescription = tc26CipherB\n\nOID = 1 2 643 2 2 31 14\nComment = TC26 params 3 for GOST 28147-89\nDescription = tc26CipherC\n\nOID = 1 2 643 2 2 31 15\nComment = TC26 params 4 for GOST 28147-89\nDescription = tc26CipherD\n\nOID = 1 2 643 2 2 31 16\nComment = TC26 params 5 for GOST 28147-89\nDescription = tc26CipherE\n\nOID = 1 2 643 2 2 31 17\nComment = TC26 params 6 for GOST 28147-89\nDescription = tc26CipherF\n\nOID = 1 2 643 7 1 2 5 1 1\nComment = TC26 params Z for GOST 28147-89\nDescription = tc26CipherZ\n\nOID = 1 2 643 2 2 9\nComment = GOST R 34.11-94 digest\nDescription = gostDigest\n\nOID = 1 2 643 2 2 30 0\nComment = Test params for GOST R 34.11-94\nDescription = testDigestParams\n\nOID = 1 2 643 2 2 30 1\nComment = CryptoPro digest params A (default, variant 'Verba-O') for GOST R 34.11-94\nDescription = cryptoProDigestA\n\nOID = 1 2 643 2 2 30 2\nComment = CryptoPro digest params B (variant 1) for GOST R 34.11-94\nDescription = cryptoProDigestB\n\nOID = 1 2 643 2 2 30 3\nComment = CryptoPro digest params C (variant 2) for GOST R 34.11-94\nDescription = cryptoProDigestC\n\nOID = 1 2 643 2 2 30 4\nComment = CryptoPro digest params D (variant 3) for GOST R 34.11-94\nDescription = cryptoProDigestD\n\nOID = 1 2 643 2 2 32 2\nComment = CryptoPro sign params A (default, variant 'Verba-O') for GOST R 34.10-94\nDescription = cryptoPro94SignA\n\nOID = 1 2 643 2 2 32 3\nComment = CryptoPro sign params B (variant 1) for GOST R 34.10-94\nDescription = cryptoPro94SignB\n\nOID = 1 2 643 2 2 32 4\nComment = CryptoPro sign params C (variant 2) for GOST R 34.10-94\nDescription = cryptoPro94SignC\n\nOID = 1 2 643 2 2 32 5\nComment = CryptoPro sign params D (variant 3) for GOST R 34.10-94\nDescription = cryptoPro94SignD\n\nOID = 1 2 643 2 2 33 1\nComment = CryptoPro sign params XA (variant 1) for GOST R 34.10-94\nDescription = cryptoPro94SignXA\n\nOID = 1 2 643 2 2 33 2\nComment = CryptoPro sign params XB (variant 2) for GOST R 34.10-94\nDescription = cryptoPro94SignXB\n\nOID = 1 2 643 2 2 33 3\nComment = CryptoPro sign params XC (variant 3) for GOST R 34.10-94\nDescription = cryptoPro94SignXC\n\nOID = 1 2 643 2 2 35 0\nComment = Test elliptic curve for GOST R 34.10-2001\nDescription = testSignParams\n\nOID = 1 2 643 2 2 35 1\nComment = CryptoPro ell.curve A for GOST R 34.10-2001\nDescription = cryptoProSignA\n\nOID = 1 2 643 2 2 35 2\nComment = CryptoPro ell.curve B for GOST R 34.10-2001\nDescription = cryptoProSignB\n\nOID = 1 2 643 2 2 35 3\nComment = CryptoPro ell.curve C for GOST R 34.10-2001\nDescription = cryptoProSignC\n\nOID = 1 2 643 2 2 36 0\nComment = CryptoPro ell.curve XA for GOST R 34.10-2001\nDescription = cryptoProSignXA\n\nOID = 1 2 643 2 2 36 1\nComment = CryptoPro ell.curve XB for GOST R 34.10-2001\nDescription = cryptoProSignXB\n\nOID = 1 2 643 7 1 2 1 1 1\nComment = CryptoPro ell.curve A for GOST R 34.10-2012 256 bit\nDescription = cryptoPro2012Sign256A\n\nOID = 1 2 643 7 1 2 1 2 1\nComment = CryptoPro ell.curve A (default) for GOST R 34.10-2012 512 bit\nDescription = cryptoPro2012Sign512A\n\nOID = 1 2 643 7 1 2 1 2 2\nComment = CryptoPro ell.curve B for GOST R 34.10-2012 512 bit\nDescription = cryptoPro2012Sign512B\n\nOID = 1 2 643 7 1 2 1 2 3\nComment = CryptoPro ell.curve C for GOST R 34.10-2012 512 bit\nDescription = cryptoPro2012Sign512C\n\nOID = 1 2 643 2 2 14 0\nComment = Do not mesh state of GOST 28147-89 cipher\nDescription = nullMeshing\n\nOID = 1 2 643 2 2 14 1\nComment = CryptoPro meshing of state of GOST 28147-89 cipher\nDescription = cryptoProMeshing\n\nOID = 1 2 643 2 2 10\nComment = HMAC with GOST R 34.11-94\nDescription = hmacGost\n\nOID = 1 2 643 2 2 13 0\nComment = Wrap key using GOST 28147-89 key\nDescription = gostWrap\n\nOID = 1 2 643 2 2 13 1\nComment = Wrap key using diversified GOST 28147-89 key\nDescription = cryptoProWrap\n\nOID = 1 2 643 2 2 96\nComment = Wrap key using ECC DH on GOST R 34.10-2001 keys (VKO)\nDescription = cryptoProECDHWrap\n\nOID = 1 2 643 7 1 1 1 1\nComment = GOST R 34.10-2012 256 bit public key\nDescription = gost2012PublicKey256\n\nOID = 1 2 643 7 1 1 1 2\nComment = GOST R 34.10-2012 512 bit public key\nDescription = gost2012PublicKey512\n\nOID = 1 2 643 7 1 1 2 2\nComment = GOST R 34.11-2012 256 bit digest\nDescription = gost2012Digest256\n\nOID = 1 2 643 7 1 1 2 3\nComment = GOST R 34.11-2012 512 bit digest\nDescription = gost2012Digest512\n\nOID = 1 2 643 7 1 1 3 2\nComment = GOST R 34.10-2012 256 bit signature\nDescription = gost2012Signature256\n\nOID = 1 2 643 7 1 1 3 3\nComment = GOST R 34.10-2012 512 bit signature\nDescription = gost2012Signature512\n\nOID = 1 2 643 7 1 1 6 1\nComment = CryptoPro ECC DH algorithm for GOST R 34.10-2012 256 bit key\nDescription = cryptoProECDH256\n\nOID = 1 2 643 7 1 1 6 2\nComment = CryptoPro ECC DH algorithm for GOST R 34.10-2012 512 bit key\nDescription = cryptoProECDH512\n\n# SEIS\n\nOID = 1 2 752 34 1\nComment = SEIS Project\nDescription = seis-cp\n\nOID = 1 2 752 34 1 1\nComment = SEIS Project certificate policies\nDescription = SEIS high-assurance policyIdentifier\n\nOID = 1 2 752 34 1 2\nComment = SEIS Project certificate policies\nDescription = SEIS GAK policyIdentifier\n\nOID = 1 2 752 34 2\nComment = SEIS Project\nDescription = SEIS pe\n\nOID = 1 2 752 34 3\nComment = SEIS Project\nDescription = SEIS at\n\nOID = 1 2 752 34 3 1\nComment = SEIS Project attribute\nDescription = SEIS at-personalIdentifier\n\n# ANSI X9.57\n\nOID = 1 2 840 10040 1\nComment = ANSI X9.57\nDescription = module\n\nOID = 1 2 840 10040 1 1\nComment = ANSI X9.57 module\nDescription = x9f1-cert-mgmt\n\nOID = 1 2 840 10040 2\nComment = ANSI X9.57\nDescription = holdinstruction\n\nOID = 1 2 840 10040 2 1\nComment = ANSI X9.57 hold instruction\nDescription = holdinstruction-none\n\nOID = 1 2 840 10040 2 2\nComment = ANSI X9.57 hold instruction\nDescription = callissuer\n\nOID = 1 2 840 10040 2 3\nComment = ANSI X9.57 hold instruction\nDescription = reject\n\nOID = 1 2 840 10040 2 4\nComment = ANSI X9.57 hold instruction\nDescription = pickupToken\n\nOID = 1 2 840 10040 3\nComment = ANSI X9.57\nDescription = attribute\n\nOID = 1 2 840 10040 3 1\nComment = ANSI X9.57 attribute\nDescription = countersignature\n\nOID = 1 2 840 10040 3 2\nComment = ANSI X9.57 attribute\nDescription = attribute-cert\n\nOID = 1 2 840 10040 4\nComment = ANSI X9.57\nDescription = algorithm\n\nOID = 1 2 840 10040 4 1\nComment = ANSI X9.57 algorithm\nDescription = dsa\n\nOID = 1 2 840 10040 4 2\nComment = ANSI X9.57 algorithm\nDescription = dsa-match\n\nOID = 1 2 840 10040 4 3\nComment = ANSI X9.57 algorithm\nDescription = dsaWithSha1\n\n# ANSI X9.62\n\nOID = 1 2 840 10045 1\nComment = ANSI X9.62. This OID is also assigned as ecdsa-with-SHA1\nDescription = fieldType\n\nOID = 1 2 840 10045 1 1\nComment = ANSI X9.62 field type\nDescription = prime-field\n\nOID = 1 2 840 10045 1 2\nComment = ANSI X9.62 field type\nDescription = characteristic-two-field\n\nOID = 1 2 840 10045 1 2 3\nComment = ANSI X9.62 field type\nDescription = characteristic-two-basis\n\nOID = 1 2 840 10045 1 2 3 1\nComment = ANSI X9.62 field basis\nDescription = onBasis\n\nOID = 1 2 840 10045 1 2 3 2\nComment = ANSI X9.62 field basis\nDescription = tpBasis\n\nOID = 1 2 840 10045 1 2 3 3\nComment = ANSI X9.62 field basis\nDescription = ppBasis\n\n# The definition for the following OID is somewhat confused, and is given as\n# keyType, publicKeyType, and public-key-type, all within 4 lines of text.\n# ecPublicKey is defined using the ID publicKeyType, so this is what's used\n# here.\nOID = 1 2 840 10045 2\nComment = ANSI X9.62\nDescription = publicKeyType\n\nOID = 1 2 840 10045 2 1\nComment = ANSI X9.62 public key type\nDescription = ecPublicKey\n\nOID = 1 2 840 10045 3 0 1\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb163v1\n\nOID = 1 2 840 10045 3 0 2\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb163v2\n\nOID = 1 2 840 10045 3 0 3\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb163v3\n\nOID = 1 2 840 10045 3 0 5\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb191v1\n\nOID = 1 2 840 10045 3 0 6\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb191v2\n\nOID = 1 2 840 10045 3 0 7\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb191v3\n\nOID = 1 2 840 10045 3 0 10\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb208w1\n\nOID = 1 2 840 10045 3 0 11\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb239v1\n\nOID = 1 2 840 10045 3 0 12\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb239v2\n\nOID = 1 2 840 10045 3 0 13\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb239v3\n\nOID = 1 2 840 10045 3 0 16\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb272w1\n\nOID = 1 2 840 10045 3 0 18\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb359v1\n\nOID = 1 2 840 10045 3 0 19\nComment = ANSI X9.62 named elliptic curve\nDescription = c2pnb368w1\n\nOID = 1 2 840 10045 3 0 20\nComment = ANSI X9.62 named elliptic curve\nDescription = c2tnb431r1\n\nOID = 1 2 840 10045 3 1 1\nComment = ANSI X9.62 named elliptic curve\nDescription = prime192v1\n\nOID = 1 2 840 10045 3 1 2\nComment = ANSI X9.62 named elliptic curve\nDescription = prime192v2\n\nOID = 1 2 840 10045 3 1 3\nComment = ANSI X9.62 named elliptic curve\nDescription = prime192v3\n\nOID = 1 2 840 10045 3 1 4\nComment = ANSI X9.62 named elliptic curve\nDescription = prime239v1\n\nOID = 1 2 840 10045 3 1 5\nComment = ANSI X9.62 named elliptic curve\nDescription = prime239v2\n\nOID = 1 2 840 10045 3 1 6\nComment = ANSI X9.62 named elliptic curve\nDescription = prime239v3\n\nOID = 1 2 840 10045 3 1 7\nComment = ANSI X9.62 named elliptic curve\nDescription = prime256v1\n\nOID = 1 2 840 10045 4 1\nComment = ANSI X9.62 ECDSA algorithm with SHA1\nDescription = ecdsaWithSHA1\n\nOID = 1 2 840 10045 4 2\nComment = ANSI X9.62 ECDSA algorithm with Recommended\nDescription = ecdsaWithRecommended\n\nOID = 1 2 840 10045 4 3\nComment = ANSI X9.62 ECDSA algorithm with Specified\nDescription = ecdsaWithSpecified\n\nOID = 1 2 840 10045 4 3 1\nComment = ANSI X9.62 ECDSA algorithm with SHA224\nDescription = ecdsaWithSHA224\n\nOID = 1 2 840 10045 4 3 2\nComment = ANSI X9.62 ECDSA algorithm with SHA256\nDescription = ecdsaWithSHA256\n\nOID = 1 2 840 10045 4 3 3\nComment = ANSI X9.62 ECDSA algorithm with SHA384\nDescription = ecdsaWithSHA384\n\nOID = 1 2 840 10045 4 3 4\nComment = ANSI X9.62 ECDSA algorithm with SHA512\nDescription = ecdsaWithSHA512\n\n# ANSI X9.42\n\nOID = 1 2 840 10046 1\nComment = ANSI X9.42\nDescription = fieldType\n\nOID = 1 2 840 10046 1 1\nComment = ANSI X9.42 field type\nDescription = gf-prime\n\nOID = 1 2 840 10046 2\nComment = ANSI X9.42\nDescription = numberType\n\nOID = 1 2 840 10046 2 1\nComment = ANSI X9.42 number type\nDescription = dhPublicKey\n\nOID = 1 2 840 10046 3\nComment = ANSI X9.42\nDescription = scheme\n\nOID = 1 2 840 10046 3 1\nComment = ANSI X9.42 scheme\nDescription = dhStatic\n\nOID = 1 2 840 10046 3 2\nComment = ANSI X9.42 scheme\nDescription = dhEphem\n\nOID = 1 2 840 10046 3 3\nComment = ANSI X9.42 scheme\nDescription = dhHybrid1\n\nOID = 1 2 840 10046 3 4\nComment = ANSI X9.42 scheme\nDescription = dhHybrid2\n\nOID = 1 2 840 10046 3 5\nComment = ANSI X9.42 scheme\nDescription = mqv2\n\nOID = 1 2 840 10046 3 6\nComment = ANSI X9.42 scheme\nDescription = mqv1\n\n# ASTM 31.20\n\nOID = 1 2 840 10065 2 2\nComment = ASTM 31.20\nDescription = ?\n\nOID = 1 2 840 10065 2 3\nComment = ASTM 31.20\nDescription = healthcareLicense\n\nOID = 1 2 840 10065 2 3 1 1\nComment = ASTM 31.20 healthcare license type\nDescription = license?\n\n# IEC 62351-8\n\nOID = 1 2 840 10070\nComment = IEC 62351\nDescription = iec62351\n\nOID = 1 2 840 10070 8\nComment = IEC 62351-8\nDescription = iec62351_8\n\nOID = 1 2 840 10070 8 1\nComment = IEC 62351-8\nDescription = iecUserRoles\n\n# Nortel Secure Networks/Entrust\n\nOID = 1 2 840 113533 7\nDescription = nsn\n\nOID = 1 2 840 113533 7 65\nDescription = nsn-ce\n\nOID = 1 2 840 113533 7 65 0\nComment = Nortel Secure Networks ce\nDescription = entrustVersInfo\n\nOID = 1 2 840 113533 7 66\nDescription = nsn-alg\n\nOID = 1 2 840 113533 7 66 3\nComment = Nortel Secure Networks alg\nDescription = cast3CBC\n\nOID = 1 2 840 113533 7 66 10\nComment = Nortel Secure Networks alg\nDescription = cast5CBC\n\nOID = 1 2 840 113533 7 66 11\nComment = Nortel Secure Networks alg\nDescription = cast5MAC\n\nOID = 1 2 840 113533 7 66 12\nComment = Nortel Secure Networks alg\nDescription = pbeWithMD5AndCAST5-CBC\n\nOID = 1 2 840 113533 7 66 13\nComment = Nortel Secure Networks alg\nDescription = passwordBasedMac\n\nOID = 1 2 840 113533 7 67\nDescription = nsn-oc\n\nOID = 1 2 840 113533 7 67 0\nComment = Nortel Secure Networks oc\nDescription = entrustUser\n\nOID = 1 2 840 113533 7 68\nDescription = nsn-at\n\nOID = 1 2 840 113533 7 68 0\nComment = Nortel Secure Networks at\nDescription = entrustCAInfo\n\nOID = 1 2 840 113533 7 68 10\nComment = Nortel Secure Networks at\nDescription = attributeCertificate\n\n# PKCS #1\n\nOID = 1 2 840 113549 1 1\nDescription = pkcs-1\n\nOID = 1 2 840 113549 1 1 1\nComment = PKCS #1\nDescription = rsaEncryption\n\nOID = 1 2 840 113549 1 1 2\nComment = PKCS #1\nDescription = md2WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 3\nComment = PKCS #1\nDescription = md4WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 4\nComment = PKCS #1\nDescription = md5WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 5\nComment = PKCS #1\nDescription = sha1WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 7\nComment = PKCS #1\nDescription = rsaOAEP\n\n# This is also used with PSS so it's given the more general label 'pkcs1-XXX'\n# rather than 'rsaOAEP-XXX'.\nOID = 1 2 840 113549 1 1 8\nComment = PKCS #1\nDescription = pkcs1-MGF\n\nOID = 1 2 840 113549 1 1 9\nComment = PKCS #1\nDescription = rsaOAEP-pSpecified\n\nOID = 1 2 840 113549 1 1 10\nComment = PKCS #1\nDescription = rsaPSS\n\nOID = 1 2 840 113549 1 1 11\nComment = PKCS #1\nDescription = sha256WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 12\nComment = PKCS #1\nDescription = sha384WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 13\nComment = PKCS #1\nDescription = sha512WithRSAEncryption\n\nOID = 1 2 840 113549 1 1 14\nComment = PKCS #1\nDescription = sha224WithRSAEncryption\n\n# There is some confusion over the identity of the following OID.  The OAEP\n# one is more recent but independant vendors have already used the RIPEMD\n# one, however it's likely that the SET usage will claim to be more\n# authoritative so we report it as that.\nOID = 1 2 840 113549 1 1 6\nComment = PKCS #1. This OID may also be assigned as ripemd160WithRSAEncryption\nDescription = rsaOAEPEncryptionSET\n# ripemd160WithRSAEncryption (1 2 840 113549 1 1 6)\n\n# BSAFE/PKCS #2 (obsolete)\n\nOID = 1 2 840 113549 1 2\nComment = Obsolete BSAFE OID\nDescription = bsafeRsaEncr\nWarning\n\n# PKCS #3\n\nOID = 1 2 840 113549 1 3\nDescription = pkcs-3\n\nOID = 1 2 840 113549 1 3 1\nComment = PKCS #3\nDescription = dhKeyAgreement\n\n# PKCS #5\n\nOID = 1 2 840 113549 1 5\nDescription = pkcs-5\n\nOID = 1 2 840 113549 1 5 1\nComment = PKCS #5\nDescription = pbeWithMD2AndDES-CBC\n\nOID = 1 2 840 113549 1 5 3\nComment = PKCS #5\nDescription = pbeWithMD5AndDES-CBC\n\nOID = 1 2 840 113549 1 5 4\nComment = PKCS #5\nDescription = pbeWithMD2AndRC2-CBC\n\nOID = 1 2 840 113549 1 5 6\nComment = PKCS #5\nDescription = pbeWithMD5AndRC2-CBC\n\nOID = 1 2 840 113549 1 5 9\nComment = PKCS #5, used in BSAFE only\nDescription = pbeWithMD5AndXOR\nWarning\n\nOID = 1 2 840 113549 1 5 10\nComment = PKCS #5\nDescription = pbeWithSHAAndDES-CBC\n\nOID = 1 2 840 113549 1 5 12\nComment = PKCS #5 v2.0\nDescription = pkcs5PBKDF2\n\nOID = 1 2 840 113549 1 5 13\nComment = PKCS #5 v2.0\nDescription = pkcs5PBES2\n\nOID = 1 2 840 113549 1 5 14\nComment = PKCS #5 v2.0\nDescription = pkcs5PBMAC1\n\n# PKCS #7\n\nOID = 1 2 840 113549 1 7\nDescription = pkcs-7\n\nOID = 1 2 840 113549 1 7 1\nComment = PKCS #7\nDescription = data\n\nOID = 1 2 840 113549 1 7 2\nComment = PKCS #7\nDescription = signedData\n\nOID = 1 2 840 113549 1 7 3\nComment = PKCS #7\nDescription = envelopedData\n\nOID = 1 2 840 113549 1 7 4\nComment = PKCS #7\nDescription = signedAndEnvelopedData\n\nOID = 1 2 840 113549 1 7 5\nComment = PKCS #7\nDescription = digestedData\n\nOID = 1 2 840 113549 1 7 6\nComment = PKCS #7\nDescription = encryptedData\n\nOID = 1 2 840 113549 1 7 7\nComment = PKCS #7 experimental\nDescription = dataWithAttributes\nWarning\n\nOID = 1 2 840 113549 1 7 8\nComment = PKCS #7 experimental\nDescription = encryptedPrivateKeyInfo\nWarning\n\n# PKCS #9\n\nOID = 1 2 840 113549 1 9\nDescription = pkcs-9\n\nOID = 1 2 840 113549 1 9 1\nComment = PKCS #9. Deprecated, use an altName extension instead\nDescription = emailAddress\n\nOID = 1 2 840 113549 1 9 2\nComment = PKCS #9\nDescription = unstructuredName\n\nOID = 1 2 840 113549 1 9 3\nComment = PKCS #9\nDescription = contentType\n\nOID = 1 2 840 113549 1 9 4\nComment = PKCS #9\nDescription = messageDigest\n\nOID = 1 2 840 113549 1 9 5\nComment = PKCS #9\nDescription = signingTime\n\nOID = 1 2 840 113549 1 9 6\nComment = PKCS #9\nDescription = countersignature\n\nOID = 1 2 840 113549 1 9 7\nComment = PKCS #9\nDescription = challengePassword\n\nOID = 1 2 840 113549 1 9 8\nComment = PKCS #9\nDescription = unstructuredAddress\n\nOID = 1 2 840 113549 1 9 9\nComment = PKCS #9\nDescription = extendedCertificateAttributes\n\nOID = 1 2 840 113549 1 9 10\nComment = PKCS #9 experimental\nDescription = issuerAndSerialNumber\nWarning\n\nOID = 1 2 840 113549 1 9 11\nComment = PKCS #9 experimental\nDescription = passwordCheck\nWarning\n\nOID = 1 2 840 113549 1 9 12\nComment = PKCS #9 experimental\nDescription = publicKey\nWarning\n\nOID = 1 2 840 113549 1 9 13\nComment = PKCS #9\nDescription = signingDescription\n\nOID = 1 2 840 113549 1 9 14\nComment = PKCS #9 via CRMF\nDescription = extensionRequest\n\n# PKCS #9 for use with S/MIME\n\nOID = 1 2 840 113549 1 9 15\nComment = PKCS #9. This OID was formerly assigned as symmetricCapabilities, then reassigned as SMIMECapabilities, then renamed to the current name\nDescription = sMIMECapabilities\n\nOID = 1 2 840 113549 1 9 15 1\nComment = sMIMECapabilities\nDescription = preferSignedData\n\nOID = 1 2 840 113549 1 9 15 2\nComment = sMIMECapabilities\nDescription = canNotDecryptAny\n\nOID = 1 2 840 113549 1 9 15 3\nComment = sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 1) instead\nDescription = receiptRequest\nWarning\n\nOID = 1 2 840 113549 1 9 15 4\nComment = sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 1 1) instead\nDescription = receipt\nWarning\n\nOID = 1 2 840 113549 1 9 15 5\nComment = sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 4) instead\nDescription = contentHints\nWarning\n\nOID = 1 2 840 113549 1 9 15 6\nComment = sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 3) instead\nDescription = mlExpansionHistory\nWarning\n\nOID = 1 2 840 113549 1 9 16\nComment = PKCS #9\nDescription = id-sMIME\n\nOID = 1 2 840 113549 1 9 16 0\nComment = id-sMIME\nDescription = id-mod\n\nOID = 1 2 840 113549 1 9 16 0 1\nComment = S/MIME Modules\nDescription = id-mod-cms\n\nOID = 1 2 840 113549 1 9 16 0 2\nComment = S/MIME Modules\nDescription = id-mod-ess\n\nOID = 1 2 840 113549 1 9 16 0 3\nComment = S/MIME Modules\nDescription = id-mod-oid\n\nOID = 1 2 840 113549 1 9 16 0 4\nComment = S/MIME Modules\nDescription = id-mod-msg-v3\n\nOID = 1 2 840 113549 1 9 16 0 5\nComment = S/MIME Modules\nDescription = id-mod-ets-eSignature-88\n\nOID = 1 2 840 113549 1 9 16 0 6\nComment = S/MIME Modules\nDescription = id-mod-ets-eSignature-97\n\nOID = 1 2 840 113549 1 9 16 0 7\nComment = S/MIME Modules\nDescription = id-mod-ets-eSigPolicy-88\n\nOID = 1 2 840 113549 1 9 16 0 8\nComment = S/MIME Modules\nDescription = id-mod-ets-eSigPolicy-88\n\n# S/MIME content types\n\nOID = 1 2 840 113549 1 9 16 1\nComment = S/MIME\nDescription = contentType\n\nOID = 1 2 840 113549 1 9 16 1 1\nComment = S/MIME Content Types\nDescription = receipt\n\nOID = 1 2 840 113549 1 9 16 1 2\nComment = S/MIME Content Types\nDescription = authData\n\nOID = 1 2 840 113549 1 9 16 1 3\nComment = S/MIME Content Types\nDescription = publishCert\n\nOID = 1 2 840 113549 1 9 16 1 4\nComment = S/MIME Content Types\nDescription = tSTInfo\n\nOID = 1 2 840 113549 1 9 16 1 5\nComment = S/MIME Content Types\nDescription = tDTInfo\n\nOID = 1 2 840 113549 1 9 16 1 6\nComment = S/MIME Content Types\nDescription = contentInfo\n\nOID = 1 2 840 113549 1 9 16 1 7\nComment = S/MIME Content Types\nDescription = dVCSRequestData\n\nOID = 1 2 840 113549 1 9 16 1 8\nComment = S/MIME Content Types\nDescription = dVCSResponseData\n\nOID = 1 2 840 113549 1 9 16 1 9\nComment = S/MIME Content Types\nDescription = compressedData\n\nOID = 1 2 840 113549 1 9 16 1 10\nComment = S/MIME Content Types\nDescription = scvpCertValRequest\n\nOID = 1 2 840 113549 1 9 16 1 11\nComment = S/MIME Content Types\nDescription = scvpCertValResponse\n\nOID = 1 2 840 113549 1 9 16 1 12\nComment = S/MIME Content Types\nDescription = scvpValPolRequest\n\nOID = 1 2 840 113549 1 9 16 1 13\nComment = S/MIME Content Types\nDescription = scvpValPolResponse\n\nOID = 1 2 840 113549 1 9 16 1 14\nComment = S/MIME Content Types\nDescription = attrCertEncAttrs\n\nOID = 1 2 840 113549 1 9 16 1 15\nComment = S/MIME Content Types\nDescription = tSReq\n\nOID = 1 2 840 113549 1 9 16 1 16\nComment = S/MIME Content Types\nDescription = firmwarePackage\n\nOID = 1 2 840 113549 1 9 16 1 17\nComment = S/MIME Content Types\nDescription = firmwareLoadReceipt\n\nOID = 1 2 840 113549 1 9 16 1 18\nComment = S/MIME Content Types\nDescription = firmwareLoadError\n\nOID = 1 2 840 113549 1 9 16 1 19\nComment = S/MIME Content Types\nDescription = contentCollection\n\nOID = 1 2 840 113549 1 9 16 1 20\nComment = S/MIME Content Types\nDescription = contentWithAttrs\n\nOID = 1 2 840 113549 1 9 16 1 21\nComment = S/MIME Content Types\nDescription = encKeyWithID\n\nOID = 1 2 840 113549 1 9 16 1 22\nComment = S/MIME Content Types\nDescription = encPEPSI\n\nOID = 1 2 840 113549 1 9 16 1 23\nComment = S/MIME Content Types\nDescription = authEnvelopedData\n\nOID = 1 2 840 113549 1 9 16 1 24\nComment = S/MIME Content Types\nDescription = routeOriginAttest\n\nOID = 1 2 840 113549 1 9 16 1 25\nComment = S/MIME Content Types\nDescription = symmetricKeyPackage\n\nOID = 1 2 840 113549 1 9 16 1 26\nComment = S/MIME Content Types\nDescription = rpkiManifest\n\nOID = 1 2 840 113549 1 9 16 1 27\nComment = S/MIME Content Types\nDescription = asciiTextWithCRLF\n\nOID = 1 2 840 113549 1 9 16 1 28\nComment = S/MIME Content Types\nDescription = xml\n\nOID = 1 2 840 113549 1 9 16 1 29\nComment = S/MIME Content Types\nDescription = pdf\n\nOID = 1 2 840 113549 1 9 16 1 30\nComment = S/MIME Content Types\nDescription = postscript\n\nOID = 1 2 840 113549 1 9 16 1 31\nComment = S/MIME Content Types\nDescription = timestampedData\n\nOID = 1 2 840 113549 1 9 16 1 32\nComment = S/MIME Content Types\nDescription = asAdjacencyAttest\nWarning\n\nOID = 1 2 840 113549 1 9 16 1 33\nComment = S/MIME Content Types\nDescription = rpkiTrustAnchor\n\nOID = 1 2 840 113549 1 9 16 1 34\nComment = S/MIME Content Types\nDescription = trustAnchorList\n\n# S/MIME attributes\n\nOID = 1 2 840 113549 1 9 16 2\nComment = S/MIME\nDescription = authenticatedAttributes\n\nOID = 1 2 840 113549 1 9 16 2 1\nComment = S/MIME Authenticated Attributes\nDescription = receiptRequest\n\nOID = 1 2 840 113549 1 9 16 2 2\nComment = S/MIME Authenticated Attributes\nDescription = securityLabel\n\nOID = 1 2 840 113549 1 9 16 2 3\nComment = S/MIME Authenticated Attributes\nDescription = mlExpandHistory\n\nOID = 1 2 840 113549 1 9 16 2 4\nComment = S/MIME Authenticated Attributes\nDescription = contentHint\n\nOID = 1 2 840 113549 1 9 16 2 5\nComment = S/MIME Authenticated Attributes\nDescription = msgSigDigest\n\nOID = 1 2 840 113549 1 9 16 2 6\nComment = S/MIME Authenticated Attributes.  Obsolete\nDescription = encapContentType\nWarning\n\nOID = 1 2 840 113549 1 9 16 2 7\nComment = S/MIME Authenticated Attributes\nDescription = contentIdentifier\n\nOID = 1 2 840 113549 1 9 16 2 8\nComment = S/MIME Authenticated Attributes.  Obsolete\nDescription = macValue\nWarning\n\nOID = 1 2 840 113549 1 9 16 2 9\nComment = S/MIME Authenticated Attributes\nDescription = equivalentLabels\n\nOID = 1 2 840 113549 1 9 16 2 10\nComment = S/MIME Authenticated Attributes\nDescription = contentReference\n\nOID = 1 2 840 113549 1 9 16 2 11\nComment = S/MIME Authenticated Attributes\nDescription = encrypKeyPref\n\nOID = 1 2 840 113549 1 9 16 2 12\nComment = S/MIME Authenticated Attributes\nDescription = signingCertificate\n\nOID = 1 2 840 113549 1 9 16 2 13\nComment = S/MIME Authenticated Attributes\nDescription = smimeEncryptCerts\n\nOID = 1 2 840 113549 1 9 16 2 14\nComment = S/MIME Authenticated Attributes\nDescription = timeStampToken\n\nOID = 1 2 840 113549 1 9 16 2 15\nComment = S/MIME Authenticated Attributes\nDescription = sigPolicyId\n\nOID = 1 2 840 113549 1 9 16 2 16\nComment = S/MIME Authenticated Attributes\nDescription = commitmentType\n\nOID = 1 2 840 113549 1 9 16 2 17\nComment = S/MIME Authenticated Attributes\nDescription = signerLocation\n\nOID = 1 2 840 113549 1 9 16 2 18\nComment = S/MIME Authenticated Attributes\nDescription = signerAttr\n\nOID = 1 2 840 113549 1 9 16 2 19\nComment = S/MIME Authenticated Attributes\nDescription = otherSigCert\n\nOID = 1 2 840 113549 1 9 16 2 20\nComment = S/MIME Authenticated Attributes\nDescription = contentTimestamp\n\nOID = 1 2 840 113549 1 9 16 2 21\nComment = S/MIME Authenticated Attributes\nDescription = certificateRefs\n\nOID = 1 2 840 113549 1 9 16 2 22\nComment = S/MIME Authenticated Attributes\nDescription = revocationRefs\n\nOID = 1 2 840 113549 1 9 16 2 23\nComment = S/MIME Authenticated Attributes\nDescription = certValues\n\nOID = 1 2 840 113549 1 9 16 2 24\nComment = S/MIME Authenticated Attributes\nDescription = revocationValues\n\nOID = 1 2 840 113549 1 9 16 2 25\nComment = S/MIME Authenticated Attributes\nDescription = escTimeStamp\n\nOID = 1 2 840 113549 1 9 16 2 26\nComment = S/MIME Authenticated Attributes\nDescription = certCRLTimestamp\n\nOID = 1 2 840 113549 1 9 16 2 27\nComment = S/MIME Authenticated Attributes\nDescription = archiveTimeStamp\n\nOID = 1 2 840 113549 1 9 16 2 28\nComment = S/MIME Authenticated Attributes\nDescription = signatureType\n\nOID = 1 2 840 113549 1 9 16 2 29\nComment = S/MIME Authenticated Attributes\nDescription = dvcsDvc\n\nOID = 1 2 840 113549 1 9 16 2 30\nComment = S/MIME Authenticated Attributes\nDescription = cekReference\n\nOID = 1 2 840 113549 1 9 16 2 31\nComment = S/MIME Authenticated Attributes\nDescription = maxCEKDecrypts\n\nOID = 1 2 840 113549 1 9 16 2 32\nComment = S/MIME Authenticated Attributes\nDescription = kekDerivationAlg\n\nOID = 1 2 840 113549 1 9 16 2 33\nComment = S/MIME Authenticated Attributes.  Obsolete\nDescription = intendedRecipients\nWarning\n\nOID = 1 2 840 113549 1 9 16 2 34\nComment = S/MIME Authenticated Attributes\nDescription = cmcUnsignedData\n\nOID = 1 2 840 113549 1 9 16 2 35\nComment = S/MIME Authenticated Attributes\nDescription = fwPackageID\n\nOID = 1 2 840 113549 1 9 16 2 36\nComment = S/MIME Authenticated Attributes\nDescription = fwTargetHardwareIDs\n\nOID = 1 2 840 113549 1 9 16 2 37\nComment = S/MIME Authenticated Attributes\nDescription = fwDecryptKeyID\n\nOID = 1 2 840 113549 1 9 16 2 38\nComment = S/MIME Authenticated Attributes\nDescription = fwImplCryptAlgs\n\nOID = 1 2 840 113549 1 9 16 2 39\nComment = S/MIME Authenticated Attributes\nDescription = fwWrappedFirmwareKey\n\nOID = 1 2 840 113549 1 9 16 2 40\nComment = S/MIME Authenticated Attributes\nDescription = fwCommunityIdentifiers\n\nOID = 1 2 840 113549 1 9 16 2 41\nComment = S/MIME Authenticated Attributes\nDescription = fwPkgMessageDigest\n\nOID = 1 2 840 113549 1 9 16 2 42\nComment = S/MIME Authenticated Attributes\nDescription = fwPackageInfo\n\nOID = 1 2 840 113549 1 9 16 2 43\nComment = S/MIME Authenticated Attributes\nDescription = fwImplCompressAlgs\n\nOID = 1 2 840 113549 1 9 16 2 44\nComment = S/MIME Authenticated Attributes\nDescription = etsAttrCertificateRefs\n\nOID = 1 2 840 113549 1 9 16 2 45\nComment = S/MIME Authenticated Attributes\nDescription = etsAttrRevocationRefs\n\nOID = 1 2 840 113549 1 9 16 2 46\nComment = S/MIME Authenticated Attributes\nDescription = binarySigningTime\n\nOID = 1 2 840 113549 1 9 16 2 47\nComment = S/MIME Authenticated Attributes\nDescription = signingCertificateV2\n\nOID = 1 2 840 113549 1 9 16 2 48\nComment = S/MIME Authenticated Attributes\nDescription = etsArchiveTimeStampV2\n\nOID = 1 2 840 113549 1 9 16 2 49\nComment = S/MIME Authenticated Attributes\nDescription = erInternal\n\nOID = 1 2 840 113549 1 9 16 2 50\nComment = S/MIME Authenticated Attributes\nDescription = erExternal\n\nOID = 1 2 840 113549 1 9 16 2 51\nComment = S/MIME Authenticated Attributes\nDescription = multipleSignatures\n\n# S/MIME algorithms\n\nOID = 1 2 840 113549 1 9 16 3 1\nComment = S/MIME Algorithms. Obsolete\nDescription = esDHwith3DES\nWarning\n\nOID = 1 2 840 113549 1 9 16 3 2\nComment = S/MIME Algorithms. Obsolete\nDescription = esDHwithRC2\nWarning\n\nOID = 1 2 840 113549 1 9 16 3 3\nComment = S/MIME Algorithms. Obsolete\nDescription = 3desWrap\nWarning\n\nOID = 1 2 840 113549 1 9 16 3 4\nComment = S/MIME Algorithms. Obsolete\nDescription = rc2Wrap\nWarning\n\nOID = 1 2 840 113549 1 9 16 3 5\nComment = S/MIME Algorithms\nDescription = esDH\n\nOID = 1 2 840 113549 1 9 16 3 6\nComment = S/MIME Algorithms\nDescription = cms3DESwrap\n\nOID = 1 2 840 113549 1 9 16 3 7\nComment = S/MIME Algorithms\nDescription = cmsRC2wrap\n\nOID = 1 2 840 113549 1 9 16 3 8\nComment = S/MIME Algorithms\nDescription = zlib\n\nOID = 1 2 840 113549 1 9 16 3 9\nComment = S/MIME Algorithms\nDescription = pwriKEK\n\nOID = 1 2 840 113549 1 9 16 3 10\nComment = S/MIME Algorithms\nDescription = ssDH\n\nOID = 1 2 840 113549 1 9 16 3 11\nComment = S/MIME Algorithms\nDescription = hmacWith3DESwrap\n\nOID = 1 2 840 113549 1 9 16 3 12\nComment = S/MIME Algorithms\nDescription = hmacWithAESwrap\n\nOID = 1 2 840 113549 1 9 16 3 13\nComment = S/MIME Algorithms.  Experimental\nDescription = md5XorExperiment\nWarning\n\nOID = 1 2 840 113549 1 9 16 3 14\nComment = S/MIME Algorithms\nDescription = rsaKEM\n\nOID = 1 2 840 113549 1 9 16 3 15\nComment = S/MIME Algorithms\nDescription = authEnc128\n\nOID = 1 2 840 113549 1 9 16 3 16\nComment = S/MIME Algorithms\nDescription = authEnc256\n\nOID = 1 2 840 113549 1 9 16 3 19\nComment = S/MIME Algorithms\nDescription = ecdhHKDF-SHA256\n\nOID = 1 2 840 113549 1 9 16 3 20\nComment = S/MIME Algorithms\nDescription = ecdhHKDF-SHA384\n\nOID = 1 2 840 113549 1 9 16 3 21\nComment = S/MIME Algorithms\nDescription = ecdhHKDF-SHA512\n\n# S/MIME miscellaneous\n\nOID = 1 2 840 113549 1 9 16 4 1\nComment = S/MIME Certificate Distribution\nDescription = certDist-ldap\n\nOID = 1 2 840 113549 1 9 16 5 1\nComment = S/MIME Signature Policy Qualifiers\nDescription = sigPolicyQualifier-spuri x\n\nOID = 1 2 840 113549 1 9 16 5 2\nComment = S/MIME Signature Policy Qualifiers\nDescription = sigPolicyQualifier-spUserNotice\n\nOID = 1 2 840 113549 1 9 16 6 1\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfOrigin\n\nOID = 1 2 840 113549 1 9 16 6 2\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfReceipt\n\nOID = 1 2 840 113549 1 9 16 6 3\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfDelivery\n\nOID = 1 2 840 113549 1 9 16 6 4\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfSender\n\nOID = 1 2 840 113549 1 9 16 6 5\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfApproval\n\nOID = 1 2 840 113549 1 9 16 6 6\nComment = S/MIME Commitment Type Identifiers\nDescription = proofOfCreation\n\nOID = 1 2 840 113549 1 9 16 8 1\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glUseKEK\n\nOID = 1 2 840 113549 1 9 16 8 2\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glDelete\n\nOID = 1 2 840 113549 1 9 16 8 3\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glAddMember\n\nOID = 1 2 840 113549 1 9 16 8 4\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glDeleteMember\n\nOID = 1 2 840 113549 1 9 16 8 5\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glRekey\n\nOID = 1 2 840 113549 1 9 16 8 6\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glAddOwner\n\nOID = 1 2 840 113549 1 9 16 8 7\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glRemoveOwner\n\nOID = 1 2 840 113549 1 9 16 8 8\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glkCompromise\n\nOID = 1 2 840 113549 1 9 16 8 9\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glkRefresh\n\nOID = 1 2 840 113549 1 9 16 8 10\nComment = S/MIME Symmetric Key Distribution Attributes.  Obsolete\nDescription = glFailInfo\nWarning\n\nOID = 1 2 840 113549 1 9 16 8 11\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glaQueryRequest\n\nOID = 1 2 840 113549 1 9 16 8 12\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glaQueryResponse\n\nOID = 1 2 840 113549 1 9 16 8 13\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glProvideCert\n\nOID = 1 2 840 113549 1 9 16 8 14\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glUpdateCert\n\nOID = 1 2 840 113549 1 9 16 8 15\nComment = S/MIME Symmetric Key Distribution Attributes\nDescription = glKey\n\nOID = 1 2 840 113549 1 9 16 9\nComment = S/MIME\nDescription = signatureTypeIdentifier\n\nOID = 1 2 840 113549 1 9 16 9 1\nComment = S/MIME Signature Type Identifier\nDescription = originatorSig\n\nOID = 1 2 840 113549 1 9 16 9 2\nComment = S/MIME Signature Type Identifier\nDescription = domainSig\n\nOID = 1 2 840 113549 1 9 16 9 3\nComment = S/MIME Signature Type Identifier\nDescription = additionalAttributesSig\n\nOID = 1 2 840 113549 1 9 16 9 4\nComment = S/MIME Signature Type Identifier\nDescription = reviewSig\n\nOID = 1 2 840 113549 1 9 16 11\nComment = S/MIME\nDescription = capabilities\n\nOID = 1 2 840 113549 1 9 16 11 1\nComment = S/MIME Capability\nDescription = preferBinaryInside\n\n# PKCS #9 for use with PKCS #12\n\nOID = 1 2 840 113549 1 9 20\nComment = PKCS #9 via PKCS #12\nDescription = friendlyName (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 21\nComment = PKCS #9 via PKCS #12\nDescription = localKeyID (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 22\nComment = PKCS #9 via PKCS #12\nDescription = certTypes (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 22 1\nComment = PKCS #9 via PKCS #12\nDescription = x509Certificate (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 22 2\nComment = PKCS #9 via PKCS #12\nDescription = sdsiCertificate (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 23\nComment = PKCS #9 via PKCS #12\nDescription = crlTypes (for PKCS #12)\n\nOID = 1 2 840 113549 1 9 23 1\nComment = PKCS #9 via PKCS #12\nDescription = x509Crl (for PKCS #12)\n\n# PKCS #9, another set of branches used for accumulating further cruft\n\nOID = 1 2 840 113549 1 9 24\nComment = PKCS #9/RFC 2985\nDescription = pkcs9objectClass\n\nOID = 1 2 840 113549 1 9 25\nComment = PKCS #9/RFC 2985\nDescription = pkcs9attributes\n\nOID = 1 2 840 113549 1 9 25 1\nComment = PKCS #9/RFC 2985 attribute\nDescription = pkcs15Token\n\nOID = 1 2 840 113549 1 9 25 2\nComment = PKCS #9/RFC 2985 attribute\nDescription = encryptedPrivateKeyInfo\n\nOID = 1 2 840 113549 1 9 25 3\nComment = PKCS #9/RFC 2985 attribute\nDescription = randomNonce\n\nOID = 1 2 840 113549 1 9 25 4\nComment = PKCS #9/RFC 2985 attribute\nDescription = sequenceNumber\n\nOID = 1 2 840 113549 1 9 25 5\nComment = PKCS #9/RFC 2985 attribute\nDescription = pkcs7PDU\n\nOID = 1 2 840 113549 1 9 26\nComment = PKCS #9/RFC 2985\nDescription = pkcs9syntax\n\nOID = 1 2 840 113549 1 9 27\nComment = PKCS #9/RFC 2985\nDescription = pkcs9matchingRules\n\n# Miscellaneous further RFCs using the 1 2 840 113549 1 9 ... arc\n\nOID = 1 2 840 113549 1 9 52\nComment = RFC 6211\nDescription = cmsAlgorithmProtection\n\n# PKCS #12.  Note that current PKCS #12 implementations tend to be strange and\n# peculiar, with implementors misusing OIDs or basing their work on earlier PFX\n# drafts or defining their own odd OIDs.  In addition the PFX/PKCS #12 spec\n# itself is full of errors and inconsistencies and a number of OIDs have been\n# redefined in different drafts (often multiple times), which doesn't make the\n# implementors job any easier.\n\nOID = 1 2 840 113549 1 12\nDescription = pkcs-12\n\nOID = 1 2 840 113549 1 12 1\nComment = This OID was formerly assigned as PKCS #12 modeID\nDescription = pkcs-12-PbeIds\n\nOID = 1 2 840 113549 1 12 1 1\nComment = PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OfflineTransportMode\nDescription = pbeWithSHAAnd128BitRC4\n\nOID = 1 2 840 113549 1 12 1 2\nComment = PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OnlineTransportMode\nDescription = pbeWithSHAAnd40BitRC4\n\nOID = 1 2 840 113549 1 12 1 3\nComment = PKCS #12 PbeIds\nDescription = pbeWithSHAAnd3-KeyTripleDES-CBC\n\nOID = 1 2 840 113549 1 12 1 4\nComment = PKCS #12 PbeIds\nDescription = pbeWithSHAAnd2-KeyTripleDES-CBC\n\nOID = 1 2 840 113549 1 12 1 5\nComment = PKCS #12 PbeIds\nDescription = pbeWithSHAAnd128BitRC2-CBC\n\nOID = 1 2 840 113549 1 12 1 6\nComment = PKCS #12 PbeIds\nDescription = pbeWithSHAAnd40BitRC2-CBC\n\nOID = 1 2 840 113549 1 12 2\nComment = Deprecated\nDescription = pkcs-12-ESPVKID\nWarning\n\nOID = 1 2 840 113549 1 12 2 1\nComment = PKCS #12 ESPVKID. Deprecated, use (1 2 840 113549 1 12 3 5) instead\nDescription = pkcs-12-PKCS8KeyShrouding\nWarning\n\n# The following appear to have been redefined yet again at 12 10 in the latest\n# PKCS #12 spec.\nOID = 1 2 840 113549 1 12 3\nDescription = pkcs-12-BagIds\n\nOID = 1 2 840 113549 1 12 3 1\nComment = PKCS #12 BagIds\nDescription = pkcs-12-keyBagId\n\nOID = 1 2 840 113549 1 12 3 2\nComment = PKCS #12 BagIds\nDescription = pkcs-12-certAndCRLBagId\n\nOID = 1 2 840 113549 1 12 3 3\nComment = PKCS #12 BagIds\nDescription = pkcs-12-secretBagId\n\nOID = 1 2 840 113549 1 12 3 4\nComment = PKCS #12 BagIds\nDescription = pkcs-12-safeContentsId\n\nOID = 1 2 840 113549 1 12 3 5\nComment = PKCS #12 BagIds\nDescription = pkcs-12-pkcs-8ShroudedKeyBagId\n\nOID = 1 2 840 113549 1 12 4\nComment = Deprecated\nDescription = pkcs-12-CertBagID\nWarning\n\nOID = 1 2 840 113549 1 12 4 1\nComment = PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-X509CertCRLBag\nDescription = pkcs-12-X509CertCRLBagID\n\nOID = 1 2 840 113549 1 12 4 2\nComment = PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-SDSICertBag\nDescription = pkcs-12-SDSICertBagID\n\n# The following are from PFX.  The ... 5 1 values have been reassigned to OIDs\n# with incompatible algorithms at ... 1, the 5 2 values seem to have vanished.\nOID = 1 2 840 113549 1 12 5\nDescription = pkcs-12-OID\nWarning\n\nOID = 1 2 840 113549 1 12 5 1\nComment = PKCS #12 OID. Deprecated, use the partially compatible (1 2 840 113549 1 12 1) OIDs instead\nDescription = pkcs-12-PBEID\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 1\nComment = PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 1) instead\nDescription = pkcs-12-PBEWithSha1And128BitRC4\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 2\nComment = PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 2) instead\nDescription = pkcs-12-PBEWithSha1And40BitRC4\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 3\nComment = PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 3) or (1 2 840 113549 1 12 1 4) instead\nDescription = pkcs-12-PBEWithSha1AndTripleDESCBC\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 4\nComment = PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 5) instead\nDescription = pkcs-12-PBEWithSha1And128BitRC2CBC\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 5\nComment = PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 6) instead\nDescription = pkcs-12-PBEWithSha1And40BitRC2CBC\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 6\nComment = PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 1) or (1 2 840 113549 1 12 1 2) instead\nDescription = pkcs-12-PBEWithSha1AndRC4\nWarning\n\nOID = 1 2 840 113549 1 12 5 1 7\nComment = PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 5) or (1 2 840 113549 1 12 1 6) instead\nDescription = pkcs-12-PBEWithSha1AndRC2CBC\nWarning\n\nOID = 1 2 840 113549 1 12 5 2\nComment = PKCS #12 OID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-EnvelopingID\n\nOID = 1 2 840 113549 1 12 5 2 1\nComment = PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-RSAEncryptionWith128BitRC4\nWarning\n\nOID = 1 2 840 113549 1 12 5 2 2\nComment = PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-RSAEncryptionWith40BitRC4\nWarning\n\nOID = 1 2 840 113549 1 12 5 2 3\nComment = PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-RSAEncryptionWithTripleDES\nWarning\n\nOID = 1 2 840 113549 1 12 5 3\nComment = PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-SignatureID\nWarning\n\nOID = 1 2 840 113549 1 12 5 3 1\nComment = PKCS #12 OID SignatureID. Deprecated, use the conventional PKCS #1 OIDs instead\nDescription = pkcs-12-RSASignatureWithSHA1Digest\nWarning\n\n# Yet *another* redefinition of the PKCS #12 \"bag\" ID's, now in a different\n# order than the last redefinition at ... 12 3.\nOID = 1 2 840 113549 1 12 10\nDescription = pkcs-12Version1\n\nOID = 1 2 840 113549 1 12 10 1\nDescription = pkcs-12BadIds\n\nOID = 1 2 840 113549 1 12 10 1 1\nComment = PKCS #12 BagIds\nDescription = pkcs-12-keyBag\n\nOID = 1 2 840 113549 1 12 10 1 2\nComment = PKCS #12 BagIds\nDescription = pkcs-12-pkcs-8ShroudedKeyBag\n\nOID = 1 2 840 113549 1 12 10 1 3\nComment = PKCS #12 BagIds\nDescription = pkcs-12-certBag\n\nOID = 1 2 840 113549 1 12 10 1 4\nComment = PKCS #12 BagIds\nDescription = pkcs-12-crlBag\n\nOID = 1 2 840 113549 1 12 10 1 5\nComment = PKCS #12 BagIds\nDescription = pkcs-12-secretBag\n\nOID = 1 2 840 113549 1 12 10 1 6\nComment = PKCS #12 BagIds\nDescription = pkcs-12-safeContentsBag\n\n# PKCS #15\n\nOID = 1 2 840 113549 1 15 1\nComment = PKCS #15\nDescription = pkcs15modules\n\nOID = 1 2 840 113549 1 15 2\nComment = PKCS #15\nDescription = pkcs15attributes\n\nOID = 1 2 840 113549 1 15 3\nComment = PKCS #15\nDescription = pkcs15contentType\n\nOID = 1 2 840 113549 1 15 3 1\nComment = PKCS #15 content type\nDescription = pkcs15content\n\n# RSADSI digest algorithms\n\nOID = 1 2 840 113549 2\nDescription = digestAlgorithm\n\nOID = 1 2 840 113549 2 2\nComment = RSADSI digestAlgorithm\nDescription = md2\n\nOID = 1 2 840 113549 2 4\nComment = RSADSI digestAlgorithm\nDescription = md4\n\nOID = 1 2 840 113549 2 5\nComment = RSADSI digestAlgorithm\nDescription = md5\n\nOID = 1 2 840 113549 2 7\nComment = RSADSI digestAlgorithm\nDescription = hmacWithSHA1\n\nOID = 1 2 840 113549 2 8\nComment = RSADSI digestAlgorithm\nDescription = hmacWithSHA224\n\nOID = 1 2 840 113549 2 9\nComment = RSADSI digestAlgorithm\nDescription = hmacWithSHA256\n\nOID = 1 2 840 113549 2 10\nComment = RSADSI digestAlgorithm\nDescription = hmacWithSHA384\n\nOID = 1 2 840 113549 2 11\nComment = RSADSI digestAlgorithm\nDescription = hmacWithSHA512\n\n# RSADSI encryption algorithms\n\nOID = 1 2 840 113549 3\nDescription = encryptionAlgorithm\n\nOID = 1 2 840 113549 3 2\nComment = RSADSI encryptionAlgorithm\nDescription = rc2CBC\n\nOID = 1 2 840 113549 3 3\nComment = RSADSI encryptionAlgorithm\nDescription = rc2ECB\n\nOID = 1 2 840 113549 3 4\nComment = RSADSI encryptionAlgorithm\nDescription = rc4\n\nOID = 1 2 840 113549 3 5\nComment = RSADSI encryptionAlgorithm\nDescription = rc4WithMAC\n\nOID = 1 2 840 113549 3 6\nComment = RSADSI encryptionAlgorithm\nDescription = desx-CBC\n\nOID = 1 2 840 113549 3 7\nComment = RSADSI encryptionAlgorithm\nDescription = des-EDE3-CBC\n\nOID = 1 2 840 113549 3 8\nComment = RSADSI encryptionAlgorithm\nDescription = rc5CBC\n\nOID = 1 2 840 113549 3 9\nComment = RSADSI encryptionAlgorithm\nDescription = rc5-CBCPad\n\nOID = 1 2 840 113549 3 10\nComment = RSADSI encryptionAlgorithm. Formerly called CDMFCBCPad\nDescription = desCDMF\n\n# Identrus\n\nOID = 1 2 840 114021 1 6 1\nComment = Identrus\nDescription = Identrus unknown policyIdentifier\n\nOID = 1 2 840 114021 4 1\nComment = Identrus\nDescription = identrusOCSP\n\n# Microsoft (both 1 2 840 and 1 3 6 1 4 1 arcs)\n\nOID = 1 2 840 113556 1 2 241\nComment = Microsoft Exchange Server - attribute\nDescription = deliveryMechanism\n\nOID = 1 2 840 113556 1 2 281\nComment = Microsoft Cert Template - attribute\nDescription = ntSecurityDescriptor\n\nOID = 1 2 840 113556 1 3 0\nComment = Microsoft Exchange Server - object class\nDescription = site-Addressing\n\nOID = 1 2 840 113556 1 3 13\nComment = Microsoft Exchange Server - object class\nDescription = classSchema\n\nOID = 1 2 840 113556 1 3 14\nComment = Microsoft Exchange Server - object class\nDescription = attributeSchema\n\nOID = 1 2 840 113556 1 3 17\nComment = Microsoft Exchange Server - object class\nDescription = mailbox-Agent\n\nOID = 1 2 840 113556 1 3 22\nComment = Microsoft Exchange Server - object class\nDescription = mailbox\n\nOID = 1 2 840 113556 1 3 23\nComment = Microsoft Exchange Server - object class\nDescription = container\n\nOID = 1 2 840 113556 1 3 46\nComment = Microsoft Exchange Server - object class\nDescription = mailRecipient\n\nOID = 1 2 840 113556 1 4 145\nComment = Microsoft Cert Template - attribute\nDescription = revision\n\nOID = 1 2 840 113556 1 4 1327\nComment = Microsoft Cert Template - attribute\nDescription = pKIDefaultKeySpec\n\nOID = 1 2 840 113556 1 4 1328\nComment = Microsoft Cert Template - attribute\nDescription = pKIKeyUsage\n\nOID = 1 2 840 113556 1 4 1329\nComment = Microsoft Cert Template - attribute\nDescription = pKIMaxIssuingDepth\n\nOID = 1 2 840 113556 1 4 1330\nComment = Microsoft Cert Template - attribute\nDescription = pKICriticalExtensions\n\nOID = 1 2 840 113556 1 4 1331\nComment = Microsoft Cert Template - attribute\nDescription = pKIExpirationPeriod\n\nOID = 1 2 840 113556 1 4 1332\nComment = Microsoft Cert Template - attribute\nDescription = pKIOverlapPeriod\n\nOID = 1 2 840 113556 1 4 1333\nComment = Microsoft Cert Template - attribute\nDescription = pKIExtendedKeyUsage\n\nOID = 1 2 840 113556 1 4 1334\nComment = Microsoft Cert Template - attribute\nDescription = pKIDefaultCSPs\n\nOID = 1 2 840 113556 1 4 1335\nComment = Microsoft Cert Template - attribute\nDescription = pKIEnrollmentAccess\n\nOID = 1 2 840 113556 1 4 1429\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-RA-Signature\n\nOID = 1 2 840 113556 1 4 1430\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Enrollment-Flag\n\nOID = 1 2 840 113556 1 4 1431\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Private-Key-Flag\n\nOID = 1 2 840 113556 1 4 1432\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Certificate-Name-Flag\n\nOID = 1 2 840 113556 1 4 1433\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Minimal-Key-Size\n\nOID = 1 2 840 113556 1 4 1434\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Template-Schema-Version\n\nOID = 1 2 840 113556 1 4 1435\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Template-Minor-Revision\n\nOID = 1 2 840 113556 1 4 1436\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Cert-Template-OID\n\nOID = 1 2 840 113556 1 4 1437\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Supersede-Templates\n\nOID = 1 2 840 113556 1 4 1438\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-RA-Policies\n\nOID = 1 2 840 113556 1 4 1439\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Certificate-Policy\n\nOID = 1 2 840 113556 1 4 1674\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-Certificate-Application-Policy\n\nOID = 1 2 840 113556 1 4 1675\nComment = Microsoft Cert Template - attribute\nDescription = msPKI-RA-Application-Policies\n\nOID = 1 2 840 113556 4 3\nComment = Microsoft\nDescription = microsoftExcel\n\nOID = 1 2 840 113556 4 4\nComment = Microsoft\nDescription = titledWithOID\n\nOID = 1 2 840 113556 4 5\nComment = Microsoft\nDescription = microsoftPowerPoint\n\n# Adobe\n\nOID = 1 2 840 113583 1\nComment = Adobe Acrobat\nDescription = adobeAcrobat\n\nOID = 1 2 840 113583 1 1\nComment = Adobe Acrobat security\nDescription = acrobatSecurity\n\nOID = 1 2 840 113583 1 1 1\nComment = Adobe Acrobat security\nDescription = pdfPassword\n\nOID = 1 2 840 113583 1 1 2\nComment = Adobe Acrobat security\nDescription = pdfDefaultSigningCredential\n\nOID = 1 2 840 113583 1 1 3\nComment = Adobe Acrobat security\nDescription = pdfDefaultEncryptionCredential\n\nOID = 1 2 840 113583 1 1 4\nComment = Adobe Acrobat security\nDescription = pdfPasswordTimeout\n\nOID = 1 2 840 113583 1 1 5\nComment = Adobe Acrobat security\nDescription = pdfAuthenticDocumentsTrust\n\nOID = 1 2 840 113583 1 1 6\nComment = Adobe Acrobat security\nDescription = pdfDynamicContentTrust\nWarning\n\nOID = 1 2 840 113583 1 1 7\nComment = Adobe Acrobat security\nDescription = pdfUbiquityTrust\n\nOID = 1 2 840 113583 1 1 8\nComment = Adobe Acrobat security\nDescription = pdfRevocationInfoArchival\n\nOID = 1 2 840 113583 1 1 9\nComment = Adobe Acrobat security\nDescription = pdfX509Extension\n\nOID = 1 2 840 113583 1 1 9 1\nComment = Adobe Acrobat security\nDescription = pdfTimeStamp\n\nOID = 1 2 840 113583 1 1 9 2\nComment = Adobe Acrobat security\nDescription = pdfArchiveRevInfo\n\nOID = 1 2 840 113583 1 1 10\nComment = Adobe Acrobat security\nDescription = pdfPPLKLiteCredential\n\nOID = 1 2 840 113583 1 2\nComment = Adobe Acrobat CPS\nDescription = acrobatCPS\n\nOID = 1 2 840 113583 1 2 1\nComment = Adobe Acrobat CPS\nDescription = pdfAuthenticDocumentsCPS\n\nOID = 1 2 840 113583 1 2 2\nComment = Adobe Acrobat CPS\nDescription = pdfTestCPS\n\nOID = 1 2 840 113583 1 2 3\nComment = Adobe Acrobat CPS\nDescription = pdfUbiquityCPS\n\nOID = 1 2 840 113583 1 2 4\nComment = Adobe Acrobat CPS\nDescription = pdfAdhocCPS\n\nOID = 1 2 840 113583 1 7\nComment = Adobe Acrobat ubiquity\nDescription = acrobatUbiquity\n\nOID = 1 2 840 113583 1 7 1\nComment = Adobe Acrobat ubiquity\nDescription = pdfUbiquitySubRights\n\n# The following arc is explicitly reserved for extensions that don't fall\n# under 1 2 840 113583 1 1 9.  In other words someone at Adobe either made\n# an editing error or codified an OID-encoding error.\nOID = 1 2 840 113583 1 9\nComment = Adobe Acrobat X.509 extension\nDescription = acrobatExtension\n\n# Another Adobe(?)\n\nOID = 1 2 840 113628 114 1 7\nComment = Adobe\nDescription = adobePKCS7\n\n# Apple\n\nOID = 1 2 840 113635 100\nComment = Apple\nDescription = appleDataSecurity\n\nOID = 1 2 840 113635 100 1\nComment = Apple\nDescription = appleTrustPolicy\n\nOID = 1 2 840 113635 100 1 1\nComment = Apple trust policy\nDescription = appleISignTP\n\nOID = 1 2 840 113635 100 1 2\nComment = Apple trust policy\nDescription = appleX509Basic\n\nOID = 1 2 840 113635 100 1 3\nComment = Apple trust policy\nDescription = appleSSLPolicy\n\nOID = 1 2 840 113635 100 1 4\nComment = Apple trust policy\nDescription = appleLocalCertGenPolicy\n\nOID = 1 2 840 113635 100 1 5\nComment = Apple trust policy\nDescription = appleCSRGenPolicy\n\nOID = 1 2 840 113635 100 1 6\nComment = Apple trust policy\nDescription = appleCRLPolicy\n\nOID = 1 2 840 113635 100 1 7\nComment = Apple trust policy\nDescription = appleOCSPPolicy\n\nOID = 1 2 840 113635 100 1 8\nComment = Apple trust policy\nDescription = appleSMIMEPolicy\n\nOID = 1 2 840 113635 100 1 9\nComment = Apple trust policy\nDescription = appleEAPPolicy\n\nOID = 1 2 840 113635 100 1 10\nComment = Apple trust policy\nDescription = appleSWUpdateSigningPolicy\n\nOID = 1 2 840 113635 100 1 11\nComment = Apple trust policy\nDescription = appleIPSecPolicy\n\nOID = 1 2 840 113635 100 1 12\nComment = Apple trust policy\nDescription = appleIChatPolicy\n\nOID = 1 2 840 113635 100 1 13\nComment = Apple trust policy\nDescription = appleResourceSignPolicy\n\nOID = 1 2 840 113635 100 1 14\nComment = Apple trust policy\nDescription = applePKINITClientPolicy\n\nOID = 1 2 840 113635 100 1 15\nComment = Apple trust policy\nDescription = applePKINITServerPolicy\n\nOID = 1 2 840 113635 100 1 16\nComment = Apple trust policy\nDescription = appleCodeSigningPolicy\n\nOID = 1 2 840 113635 100 1 17\nComment = Apple trust policy\nDescription = applePackageSigningPolicy\n\nOID = 1 2 840 113635 100 2\nComment = Apple\nDescription = appleSecurityAlgorithm\n\nOID = 1 2 840 113635 100 2 1\nComment = Apple security algorithm\nDescription = appleFEE\n\nOID = 1 2 840 113635 100 2 2\nComment = Apple security algorithm\nDescription = appleASC\n\nOID = 1 2 840 113635 100 2 3\nComment = Apple security algorithm\nDescription = appleFEE_MD5\n\nOID = 1 2 840 113635 100 2 4\nComment = Apple security algorithm\nDescription = appleFEE_SHA1\n\nOID = 1 2 840 113635 100 2 5\nComment = Apple security algorithm\nDescription = appleFEED\n\nOID = 1 2 840 113635 100 2 6\nComment = Apple security algorithm\nDescription = appleFEEDEXP\n\nOID = 1 2 840 113635 100 2 7\nComment = Apple security algorithm\nDescription = appleECDSA\n\nOID = 1 2 840 113635 100 3\nComment = Apple\nDescription = appleDotMacCertificate\n\n# There are lots more subtypes under the following arcs, who knows\n# what they're used for or whether they've ever been used at all.\n\nOID = 1 2 840 113635 100 3 1\nComment = Apple dotMac certificate\nDescription = appleDotMacCertificateRequest\n\nOID = 1 2 840 113635 100 3 2\nComment = Apple dotMac certificate\nDescription = appleDotMacCertificateExtension\n\nOID = 1 2 840 113635 100 3 3\nComment = Apple dotMac certificate\nDescription = appleDotMacCertificateRequestValues\n\nOID = 1 2 840 113635 100 4\nComment = Apple\nDescription = appleExtendedKeyUsage\n\nOID = 1 2 840 113635 100 4 1\nComment = Apple extended key usage\nDescription = appleCodeSigning\n\nOID = 1 2 840 113635 100 4 1 1\nComment = Apple extended key usage\nDescription = appleCodeSigningDevelopment\n\nOID = 1 2 840 113635 100 4 1 2\nComment = Apple extended key usage\nDescription = appleSoftwareUpdateSigning\n\nOID = 1 2 840 113635 100 4 1 3\nComment = Apple extended key usage\nDescription = appleCodeSigningThirdParty\n\nOID = 1 2 840 113635 100 4 1 4\nComment = Apple extended key usage\nDescription = appleResourceSigning\n\nOID = 1 2 840 113635 100 4 2\nComment = Apple extended key usage\nDescription = appleIChatSigning\n\nOID = 1 2 840 113635 100 4 3\nComment = Apple extended key usage\nDescription = appleIChatEncryption\n\nOID = 1 2 840 113635 100 4 4\nComment = Apple extended key usage\nDescription = appleSystemIdentity\n\nOID = 1 2 840 113635 100 4 5\nComment = Apple extended key usage\nDescription = appleCryptoEnv\n\nOID = 1 2 840 113635 100 4 5 1\nComment = Apple extended key usage\nDescription = appleCryptoProductionEnv\n\nOID = 1 2 840 113635 100 4 5 2\nComment = Apple extended key usage\nDescription = appleCryptoMaintenanceEnv\n\nOID = 1 2 840 113635 100 4 5 3\nComment = Apple extended key usage\nDescription = appleCryptoTestEnv\n\nOID = 1 2 840 113635 100 4 5 4\nComment = Apple extended key usage\nDescription = appleCryptoDevelopmentEnv\n\nOID = 1 2 840 113635 100 4 6\nComment = Apple extended key usage\nDescription = appleCryptoQoS\n\nOID = 1 2 840 113635 100 4 6 1\nComment = Apple extended key usage\nDescription = appleCryptoTier0QoS\n\nOID = 1 2 840 113635 100 4 6 2\nComment = Apple extended key usage\nDescription = appleCryptoTier1QoS\n\nOID = 1 2 840 113635 100 4 6 3\nComment = Apple extended key usage\nDescription = appleCryptoTier2QoS\n\nOID = 1 2 840 113635 100 4 6 4\nComment = Apple extended key usage\nDescription = appleCryptoTier3QoS\n\nOID = 1 2 840 113635 100 5\nComment = Apple\nDescription = appleCertificatePolicies\n\nOID = 1 2 840 113635 100 5 1\nComment = Apple\nDescription = appleCertificatePolicyID\n\nOID = 1 2 840 113635 100 5 2\nComment = Apple\nDescription = appleDotMacCertificatePolicyID\n\nOID = 1 2 840 113635 100 5 3\nComment = Apple\nDescription = appleADCCertificatePolicyID\n\nOID = 1 2 840 113635 100 6\nComment = Apple\nDescription = appleCertificateExtensions\n\nOID = 1 2 840 113635 100 6 1\nComment = Apple certificate extension\nDescription = appleCertificateExtensionCodeSigning\n\nOID = 1 2 840 113635 100 6 1 1\nComment = Apple certificate extension\nDescription = appleCertificateExtensionAppleSigning\n\nOID = 1 2 840 113635 100 6 1 2\nComment = Apple certificate extension\nDescription = appleCertificateExtensionADCDeveloperSigning\n\nOID = 1 2 840 113635 100 6 1 3\nComment = Apple certificate extension\nDescription = appleCertificateExtensionADCAppleSigning\n\n# More Microsoft under the IETF arc\n\nOID = 1 3 6 1 4 1 311 2 1 4\nComment = Microsoft code signing\nDescription = spcIndirectDataContext\n\nOID = 1 3 6 1 4 1 311 2 1 10\nComment = Microsoft code signing. Also known as policyLink\nDescription = spcAgencyInfo\n\nOID = 1 3 6 1 4 1 311 2 1 11\nComment = Microsoft code signing\nDescription = spcStatementType\n\nOID = 1 3 6 1 4 1 311 2 1 12\nComment = Microsoft code signing\nDescription = spcSpOpusInfo\n\nOID = 1 3 6 1 4 1 311 2 1 14\nComment = Microsoft\nDescription = certReqExtensions\n\nOID = 1 3 6 1 4 1 311 2 1 15\nComment = Microsoft code signing\nDescription = spcPEImageData\n\nOID = 1 3 6 1 4 1 311 2 1 18\nComment = Microsoft code signing\nDescription = spcRawFileData\n\nOID = 1 3 6 1 4 1 311 2 1 19\nComment = Microsoft code signing\nDescription = spcStructuredStorageData\n\nOID = 1 3 6 1 4 1 311 2 1 20\nComment = Microsoft code signing. Formerly \"link extension\" aka \"glue extension\"\nDescription = spcJavaClassData (type 1)\n\nOID = 1 3 6 1 4 1 311 2 1 21\nComment = Microsoft\nDescription = individualCodeSigning\n\nOID = 1 3 6 1 4 1 311 2 1 22\nComment = Microsoft\nDescription = commercialCodeSigning\n\nOID = 1 3 6 1 4 1 311 2 1 25\nComment = Microsoft code signing. Also known as \"glue extension\"\nDescription = spcLink (type 2)\n\nOID = 1 3 6 1 4 1 311 2 1 26\nComment = Microsoft code signing\nDescription = spcMinimalCriteriaInfo\n\nOID = 1 3 6 1 4 1 311 2 1 27\nComment = Microsoft code signing\nDescription = spcFinancialCriteriaInfo\n\nOID = 1 3 6 1 4 1 311 2 1 28\nComment = Microsoft code signing.  Also known as \"glue extension\"\nDescription = spcLink (type 3)\n\nOID = 1 3 6 1 4 1 311 2 1 29\nComment = Microsoft code signing\nDescription = spcHashInfoObjID\n\nOID = 1 3 6 1 4 1 311 2 1 30\nComment = Microsoft code signing\nDescription = spcSipInfoObjID\n\nOID = 1 3 6 1 4 1 311 2 2\nComment = Microsoft CTL\nDescription = ctl\n\nOID = 1 3 6 1 4 1 311 2 2 1\nComment = Microsoft CTL\nDescription = ctlTrustedCodesigningCAList\n\nOID = 1 3 6 1 4 1 311 2 2 2\nComment = Microsoft CTL\nDescription = ctlTrustedClientAuthCAList\n\nOID = 1 3 6 1 4 1 311 2 2 3\nComment = Microsoft CTL\nDescription = ctlTrustedServerAuthCAList\n\nOID = 1 3 6 1 4 1 311 3 2 1\nComment = Microsoft code signing\nDescription = timestampRequest\n\nOID = 1 3 6 1 4 1 311 10 1\nComment = Microsoft contentType\nDescription = certTrustList\n\nOID = 1 3 6 1 4 1 311 10 1 1\nComment = Microsoft contentType\nDescription = sortedCtl\n\nOID = 1 3 6 1 4 1 311 10 2\nComment = Microsoft\nDescription = nextUpdateLocation\n\nOID = 1 3 6 1 4 1 311 10 3 1\nComment = Microsoft enhanced key usage\nDescription = certTrustListSigning\n\nOID = 1 3 6 1 4 1 311 10 3 2\nComment = Microsoft enhanced key usage\nDescription = timeStampSigning\n\nOID = 1 3 6 1 4 1 311 10 3 3\nComment = Microsoft enhanced key usage\nDescription = serverGatedCrypto\n\nOID = 1 3 6 1 4 1 311 10 3 3 1\nComment = Microsoft\nDescription = serialized\n\nOID = 1 3 6 1 4 1 311 10 3 4\nComment = Microsoft enhanced key usage\nDescription = encryptedFileSystem\n\nOID = 1 3 6 1 4 1 311 10 3 5\nComment = Microsoft enhanced key usage\nDescription = whqlCrypto\n\nOID = 1 3 6 1 4 1 311 10 3 6\nComment = Microsoft enhanced key usage\nDescription = nt5Crypto\n\nOID = 1 3 6 1 4 1 311 10 3 7\nComment = Microsoft enhanced key usage\nDescription = oemWHQLCrypto\n\nOID = 1 3 6 1 4 1 311 10 3 8\nComment = Microsoft enhanced key usage\nDescription = embeddedNTCrypto\n\nOID = 1 3 6 1 4 1 311 10 3 9\nComment = Microsoft enhanced key usage\nDescription = rootListSigner\n\nOID = 1 3 6 1 4 1 311 10 3 10\nComment = Microsoft enhanced key usage\nDescription = qualifiedSubordination\n\nOID = 1 3 6 1 4 1 311 10 3 11\nComment = Microsoft enhanced key usage\nDescription = keyRecovery\n\nOID = 1 3 6 1 4 1 311 10 3 12\nComment = Microsoft enhanced key usage\nDescription = documentSigning\n\nOID = 1 3 6 1 4 1 311 10 3 13\nComment = Microsoft enhanced key usage\nDescription = lifetimeSigning\n\nOID = 1 3 6 1 4 1 311 10 3 14\nComment = Microsoft enhanced key usage\nDescription = mobileDeviceSoftware\n\nOID = 1 3 6 1 4 1 311 10 3 15\nComment = Microsoft enhanced key usage\nDescription = smartDisplay\n\nOID = 1 3 6 1 4 1 311 10 3 16\nComment = Microsoft enhanced key usage\nDescription = cspSignature\n\nOID = 1 3 6 1 4 1 311 10 3 4 1\nComment = Microsoft enhanced key usage\nDescription = efsRecovery\n\nOID = 1 3 6 1 4 1 311 10 4 1\nComment = Microsoft attribute\nDescription = yesnoTrustAttr\n\nOID = 1 3 6 1 4 1 311 10 5 1\nComment = Microsoft enhanced key usage\nDescription = drm\n\nOID = 1 3 6 1 4 1 311 10 5 2\nComment = Microsoft enhanced key usage\nDescription = drmIndividualization\n\nOID = 1 3 6 1 4 1 311 10 6 1\nComment = Microsoft enhanced key usage\nDescription = licenses\n\nOID = 1 3 6 1 4 1 311 10 6 2\nComment = Microsoft enhanced key usage\nDescription = licenseServer\n\nOID = 1 3 6 1 4 1 311 10 7 1\nComment = Microsoft attribute\nDescription = keyidRdn\n\nOID = 1 3 6 1 4 1 311 10 8 1\nComment = Microsoft attribute\nDescription = removeCertificate\n\nOID = 1 3 6 1 4 1 311 10 9 1\nComment = Microsoft attribute\nDescription = crossCertDistPoints\n\nOID = 1 3 6 1 4 1 311 10 10 1\nComment = Microsoft\nDescription = cmcAddAttributes\n\nOID = 1 3 6 1 4 1 311 10 11\nComment = Microsoft\nDescription = certPropIdPrefix\n\nOID = 1 3 6 1 4 1 311 10 11 4\nComment = Microsoft\nDescription = certMd5HashPropId\n\nOID = 1 3 6 1 4 1 311 10 11 20\nComment = Microsoft\nDescription = certKeyIdentifierPropId\n\nOID = 1 3 6 1 4 1 311 10 11 28\nComment = Microsoft\nDescription = certIssuerSerialNumberMd5HashPropId\n\nOID = 1 3 6 1 4 1 311 10 11 29\nComment = Microsoft\nDescription = certSubjectNameMd5HashPropId\n\nOID = 1 3 6 1 4 1 311 10 12 1\nComment = Microsoft attribute\nDescription = anyApplicationPolicy\n\nOID = 1 3 6 1 4 1 311 12\nComment = Microsoft attribute\nDescription = catalog\n\nOID = 1 3 6 1 4 1 311 12 1 1\nComment = Microsoft attribute\nDescription = catalogList\n\nOID = 1 3 6 1 4 1 311 12 1 2\nComment = Microsoft attribute\nDescription = catalogListMember\n\nOID = 1 3 6 1 4 1 311 12 2 1\nComment = Microsoft attribute\nDescription = catalogNameValueObjID\n\nOID = 1 3 6 1 4 1 311 12 2 2\nComment = Microsoft attribute\nDescription = catalogMemberInfoObjID\n\n# Certificate signing a renewal request\nOID = 1 3 6 1 4 1 311 13 1\nComment = Microsoft attribute\nDescription = renewalCertificate\n\n# Name-and-value string pairs\nOID = 1 3 6 1 4 1 311 13 2 1\nComment = Microsoft attribute\nDescription = enrolmentNameValuePair\n\n# CAPI cert enrolment CSP, contains a BMPString describing the CAPI level and\n# a BIT STRING blob containing a key spec\nOID = 1 3 6 1 4 1 311 13 2 2\nComment = Microsoft attribute\nDescription = enrolmentCSP\n\n# Windows OS version\nOID = 1 3 6 1 4 1 311 13 2 3\nComment = Microsoft attribute\nDescription = osVersion\n\n# This is just the normal issuerAndSerialNumber but with a MS-specific OID.\n# Apparently it's used for CryptEncode/DecodeObject, whatever that is.\nOID = 1 3 6 1 4 1 311 16 4\nComment = Microsoft attribute\nDescription = microsoftRecipientInfo\n\nOID = 1 3 6 1 4 1 311 17 1\nComment = Microsoft attribute\nDescription = pkcs12KeyProviderNameAttr\n\nOID = 1 3 6 1 4 1 311 17 2\nComment = Microsoft attribute\nDescription = localMachineKeyset\n\nOID = 1 3 6 1 4 1 311 17 3\nComment = Microsoft attribute\nDescription = pkcs12ExtendedAttributes\n\nOID = 1 3 6 1 4 1 311 20 1\nComment = Microsoft\nDescription = autoEnrollCtlUsage\n\nOID = 1 3 6 1 4 1 311 20 2\nComment = Microsoft CAPICOM certificate template, V1\nDescription = enrollCerttypeExtension\n\nOID = 1 3 6 1 4 1 311 20 2 1\nComment = Microsoft enhanced key usage\nDescription = enrollmentAgent\n\nOID = 1 3 6 1 4 1 311 20 2 2\nComment = Microsoft enhanced key usage\nDescription = smartcardLogon\n\nOID = 1 3 6 1 4 1 311 20 2 3\nComment = Microsoft UPN\nDescription = universalPrincipalName\n\nOID = 1 3 6 1 4 1 311 20 3\nComment = Microsoft\nDescription = certManifold\n\n# Win2K CA certificate key/cert counter, high 16 bits = key index, low 16 bits\n# = cert index.  Key index is inc'd when a CA gets a new key, cert index is\n# inc'd when a CA gets a new cert (ie recertifies a current key).  This\n# extension has two purposes, as a hint to rebuild key/cert lists when a Win2K\n# CA is restored, and as a poster boy for the kind of crap that people are\n# shovelling into certs that has no place there\nOID = 1 3 6 1 4 1 311 21 1\nComment = Microsoft attribute.  Also known as certsrvCaVersion\nDescription = cAKeyCertIndexPair\n\nOID = 1 3 6 1 4 1 311 21 2\nComment = Microsoft\nDescription = certSrvPreviousCertHash\n\nOID = 1 3 6 1 4 1 311 21 3\nComment = Microsoft\nDescription = crlVirtualBase\n\nOID = 1 3 6 1 4 1 311 21 4\nComment = Microsoft\nDescription = crlNextPublish\n\n# EKU: Encryption certificate for sending the private key to the CA\nOID = 1 3 6 1 4 1 311 21 5\nComment = Microsoft extended key usage\nDescription = caExchange\nWarning\n\n# EKU: keyRecovery\nOID = 1 3 6 1 4 1 311 21 6\nComment = Microsoft extended key usage\nDescription = keyRecovery\nWarning\n\nOID = 1 3 6 1 4 1 311 21 7\nComment = Microsoft CAPICOM certificate template, V2\nDescription = certificateTemplate\n\n# This one is at least as bad as cAKeyCertIndexPair: The first part of\n# the arc, 1 3 6 1 4 1 311 21 8, is fixed, then 6 32-bit values are\n# randomly generated and appended to create the full semi-random OID.\n# Obviously it's not possible to usefully display these things...\n# Comment = Microsoft braindamage\n# Description = autoEnrollEFS (1 3 6 1 4 1 311 21 8 x x x x x x)\n\nOID = 1 3 6 1 4 1 311 21 9\nComment = Microsoft\nDescription = rdnDummySigner\n\nOID = 1 3 6 1 4 1 311 21 10\nComment = Microsoft\nDescription = applicationCertPolicies\n\nOID = 1 3 6 1 4 1 311 21 11\nComment = Microsoft\nDescription = applicationPolicyMappings\n\nOID = 1 3 6 1 4 1 311 21 12\nComment = Microsoft\nDescription = applicationPolicyConstraints\n\n# Encrypted private key\nOID = 1 3 6 1 4 1 311 21 13\nComment = Microsoft attribute\nDescription = archivedKey\n\nOID = 1 3 6 1 4 1 311 21 14\nComment = Microsoft\nDescription = crlSelfCDP\n\nOID = 1 3 6 1 4 1 311 21 15\nComment = Microsoft\nDescription = requireCertChainPolicy\n\nOID = 1 3 6 1 4 1 311 21 16\nComment = Microsoft\nDescription = archivedKeyCertHash\n\nOID = 1 3 6 1 4 1 311 21 17\nComment = Microsoft\nDescription = issuedCertHash\n\nOID = 1 3 6 1 4 1 311 21 19\nComment = Microsoft\nDescription = dsEmailReplication\n\n# Identity of the client application/ActiveX control, user, and machine\n# that generated the request\nOID = 1 3 6 1 4 1 311 21 20\nComment = Microsoft attribute\nDescription = requestClientInfo\n\n# Hash of private key\nOID = 1 3 6 1 4 1 311 21 21\nComment = Microsoft attribute\nDescription = encryptedKeyHash\n\nOID = 1 3 6 1 4 1 311 21 22\nComment = Microsoft\nDescription = certsrvCrossCaVersion\n\nOID = 1 3 6 1 4 1 311 25 1\nComment = Microsoft\nDescription = ntdsReplication\n\nOID = 1 3 6 1 4 1 311 31 1\nComment = Microsoft attribute\nDescription = productUpdate\n\n# EKU: Health (= proof of compliance with system security policy) certificate\n# (This may also be a policy OID rather than an EKU OID)\nOID = 1 3 6 1 4 1 311 47 1 1\nComment = Microsoft extended key usage\nDescription = systemHealth\n\n# EKU: Extended health (= proof of compliance with system security policy)\n# certificate   This is an interesting example of the triumph of politics\n# over security, the \"Health\" key usage is meant to indicate compliance with\n# a system or corporate security policy, and this key usage is for systems\n# that don't comply with the policy but that need a \"Health\" certificate\n# anyway\nOID = 1 3 6 1 4 1 311 47 1 3\nComment = Microsoft extended key usage\nDescription = systemHealthLoophole\n\nOID = 1 3 6 1 4 1 311 60 1 1\nComment = Microsoft policy attribute\nDescription = rootProgramFlags\n\nOID = 1 3 6 1 4 1 311 61 1 1\nComment = Microsoft enhanced key usage\nDescription = kernelModeCodeSigning\n\nOID = 1 3 6 1 4 1 311 60 2 1 1\nComment = Microsoft (???)\nDescription = jurisdictionOfIncorporationL\n\nOID = 1 3 6 1 4 1 311 60 2 1 2\nComment = Microsoft (???)\nDescription = jurisdictionOfIncorporationSP\n\nOID = 1 3 6 1 4 1 311 60 2 1 3\nComment = Microsoft (???)\nDescription = jurisdictionOfIncorporationC\n\nOID = 1 3 6 1 4 1 311 88\nComment = Microsoft attribute\nDescription = capiCom\n\nOID = 1 3 6 1 4 1 311 88 1\nComment = Microsoft attribute\nDescription = capiComVersion\n\nOID = 1 3 6 1 4 1 311 88 2\nComment = Microsoft attribute\nDescription = capiComAttribute\n\nOID = 1 3 6 1 4 1 311 88 2 1\nComment = Microsoft attribute\nDescription = capiComDocumentName\n\nOID = 1 3 6 1 4 1 311 88 2 2\nComment = Microsoft attribute\nDescription = capiComDocumentDescription\n\nOID = 1 3 6 1 4 1 311 88 3\nComment = Microsoft attribute\nDescription = capiComEncryptedData\n\nOID = 1 3 6 1 4 1 311 88 3 1\nComment = Microsoft attribute\nDescription = capiComEncryptedContent\n\n# Ascom Systech\n\nOID = 1 3 6 1 4 1 188 7 1 1\nComment = Ascom Systech\nDescription = ascom\n\nOID = 1 3 6 1 4 1 188 7 1 1 1\nComment = Ascom Systech\nDescription = ideaECB\n\nOID = 1 3 6 1 4 1 188 7 1 1 2\nComment = Ascom Systech\nDescription = ideaCBC\n\nOID = 1 3 6 1 4 1 188 7 1 1 3\nComment = Ascom Systech\nDescription = ideaCFB\n\nOID = 1 3 6 1 4 1 188 7 1 1 4\nComment = Ascom Systech\nDescription = ideaOFB\n\n# UNINETT\n\nOID = 1 3 6 1 4 1 2428 10 1 1\nComment = UNINETT PCA\nDescription = UNINETT policyIdentifier\n\n# ICE-TEL\n\nOID = 1 3 6 1 4 1 2712 10\nComment = ICE-TEL CA\nDescription = ICE-TEL policyIdentifier\n\nOID = 1 3 6 1 4 1 2786 1 1 1\nComment = ICE-TEL CA policy\nDescription = ICE-TEL Italian policyIdentifier\n\n# cryptlib\n\nOID = 1 3 6 1 4 1 3029 1 1 1\nComment = cryptlib encryption algorithm\nDescription = blowfishECB\n\nOID = 1 3 6 1 4 1 3029 1 1 2\nComment = cryptlib encryption algorithm\nDescription = blowfishCBC\n\nOID = 1 3 6 1 4 1 3029 1 1 3\nComment = cryptlib encryption algorithm\nDescription = blowfishCFB\n\nOID = 1 3 6 1 4 1 3029 1 1 4\nComment = cryptlib encryption algorithm\nDescription = blowfishOFB\n\nOID = 1 3 6 1 4 1 3029 1 2 1\nComment = cryptlib public-key algorithm\nDescription = elgamal\n\nOID = 1 3 6 1 4 1 3029 1 2 1 1\nComment = cryptlib public-key algorithm\nDescription = elgamalWithSHA-1\n\nOID = 1 3 6 1 4 1 3029 1 2 1 2\nComment = cryptlib public-key algorithm\nDescription = elgamalWithRIPEMD-160\n\nOID = 1 3 6 1 4 1 3029 3 1 1\nComment = cryptlib attribute type\nDescription = cryptlibPresenceCheck\n\nOID = 1 3 6 1 4 1 3029 3 1 2\nComment = cryptlib attribute type\nDescription = pkiBoot\n\nOID = 1 3 6 1 4 1 3029 3 1 4\nComment = cryptlib attribute type\nDescription = crlExtReason\n\nOID = 1 3 6 1 4 1 3029 3 1 5\nComment = cryptlib attribute type\nDescription = keyFeatures\n\nOID = 1 3 6 1 4 1 3029 4 1\nComment = cryptlib\nDescription = cryptlibContent\n\nOID = 1 3 6 1 4 1 3029 4 1 1\nComment = cryptlib content type\nDescription = cryptlibConfigData\n\nOID = 1 3 6 1 4 1 3029 4 1 2\nComment = cryptlib content type\nDescription = cryptlibUserIndex\n\nOID = 1 3 6 1 4 1 3029 4 1 3\nComment = cryptlib content type\nDescription = cryptlibUserInfo\n\nOID = 1 3 6 1 4 1 3029 4 1 4\nComment = cryptlib content type\nDescription = rtcsRequest\n\nOID = 1 3 6 1 4 1 3029 4 1 5\nComment = cryptlib content type\nDescription = rtcsResponse\n\nOID = 1 3 6 1 4 1 3029 4 1 6\nComment = cryptlib content type\nDescription = rtcsResponseExt\n\nOID = 1 3 6 1 4 1 3029 42 11172 1\nComment = cryptlib special MPEG-of-cat OID\nDescription = mpeg-1\n\n# Hex OID = 06 0A 2B 06 01 04 01 97 36 DD 24 36, TSA policy that's needed\n# because TSP requires a policy OID in responses.  This is the 'snooze\n# policy, \"Anything that arrives, we sign\".\nOID = 1 3 6 1 4 1 3029 54 11940 54\nComment = cryptlib TSA policy\nDescription = TSA policy \"Anything that arrives, we sign\"\n\n# Hex OID = 06 0C 2B 06 01 04 01 97 55 58 59 5A 5A 59, last values are\n# 'xyzzy'.\nOID = 1 3 6 1 4 1 3029 88 89 90 90 89\nComment = cryptlib certificate policy\nDescription = xYZZY policyIdentifier\n\n# PGP Inc.\n\nOID = 1 3 6 1 4 1 3401 8 1 1\nComment = PGP key information\nDescription = pgpExtension\n\n# EDI messaging for TMN Interactive Agents\n\nOID = 1 3 6 1 4 1 3576 7\nComment = TMN EDI for Interactive Agents\nDescription = eciaAscX12Edi\n\nOID = 1 3 6 1 4 1 3576 7 1\nComment = TMN EDI for Interactive Agents\nDescription = plainEDImessage\n\nOID = 1 3 6 1 4 1 3576 7 2\nComment = TMN EDI for Interactive Agents\nDescription = signedEDImessage\n\nOID = 1 3 6 1 4 1 3576 7 5\nComment = TMN EDI for Interactive Agents\nDescription = integrityEDImessage\n\nOID = 1 3 6 1 4 1 3576 7 65\nComment = TMN EDI for Interactive Agents\nDescription = iaReceiptMessage\n\nOID = 1 3 6 1 4 1 3576 7 97\nComment = TMN EDI for Interactive Agents\nDescription = iaStatusMessage\n\nOID = 1 3 6 1 4 1 3576 8\nComment = TMN EDI for Interactive Agents\nDescription = eciaEdifact\n\nOID = 1 3 6 1 4 1 3576 9\nComment = TMN EDI for Interactive Agents\nDescription = eciaNonEdi\n\n# Globalsign\n\nOID = 1 3 6 1 4 1 4146\nComment = Globalsign\nDescription = Globalsign\n\nOID = 1 3 6 1 4 1 4146 1\nComment = Globalsign\nDescription = globalsignPolicy\n\n# Present in the EV policy OID collection at the end of this list\n#OID = 1 3 6 1 4 1 4146 1 1\n#Comment = Globalsign policy\n#Description = globalsignEVPolicy\n\nOID = 1 3 6 1 4 1 4146 1 10\nComment = Globalsign policy\nDescription = globalsignDVPolicy\n\nOID = 1 3 6 1 4 1 4146 1 20\nComment = Globalsign policy\nDescription = globalsignOVPolicy\n\nOID = 1 3 6 1 4 1 4146 1 30\nComment = Globalsign policy\nDescription = globalsignTSAPolicy\n\nOID = 1 3 6 1 4 1 4146 1 40\nComment = Globalsign policy\nDescription = globalsignClientCertPolicy\n\nOID = 1 3 6 1 4 1 4146 1 50\nComment = Globalsign policy\nDescription = globalsignCodeSignPolicy\n\nOID = 1 3 6 1 4 1 4146 1 60\nComment = Globalsign policy\nDescription = globalsignRootSignPolicy\n\nOID = 1 3 6 1 4 1 4146 1 70\nComment = Globalsign policy\nDescription = globalsignTrustedRootPolicy\n\nOID = 1 3 6 1 4 1 4146 1 80\nComment = Globalsign policy\nDescription = globalsignEDIClientPolicy\n\nOID = 1 3 6 1 4 1 4146 1 81\nComment = Globalsign policy\nDescription = globalsignEDIServerPolicy\n\nOID = 1 3 6 1 4 1 4146 1 90\nComment = Globalsign policy\nDescription = globalsignTPMRootPolicy\n\nOID = 1 3 6 1 4 1 4146 1 95\nComment = Globalsign policy\nDescription = globalsignOCSPPolicy\n\n# EdelWeb, http://timestamping.edelweb.fr\n\nOID = 1 3 6 1 4 1 5309 1\nComment = EdelWeb policy\nDescription = edelWebPolicy\n\nOID = 1 3 6 1 4 1 5309 1 2\nComment = EdelWeb policy\nDescription = edelWebCustomerPolicy\n\nOID = 1 3 6 1 4 1 5309 1 2 1\nComment = EdelWeb policy\nDescription = edelWebClepsydrePolicy\n\nOID = 1 3 6 1 4 1 5309 1 2 2\nComment = EdelWeb policy\nDescription = edelWebExperimentalTSAPolicy\n\nOID = 1 3 6 1 4 1 5309 1 2 3\nComment = EdelWeb policy\nDescription = edelWebOpenEvidenceTSAPolicy\n\n# Timeproof (www.timeproof.de)\n\nOID = 1 3 6 1 4 1 5472\nComment = enterprise\nDescription = timeproof\n\nOID = 1 3 6 1 4 1 5472 1\nComment = timeproof\nDescription = tss\n\nOID = 1 3 6 1 4 1 5472 1 1\nComment = timeproof TSS\nDescription = tss80\n\nOID = 1 3 6 1 4 1 5472 1 2\nComment = timeproof TSS\nDescription = tss380\n\nOID = 1 3 6 1 4 1 5472 1 3\nComment = timeproof TSS\nDescription = tss400\n\n# MEDePass\n\nOID = 1 3 6 1 4 1 5770 0 3\nComment = MEDePass\nDescription = secondaryPractices\n\nOID = 1 3 6 1 4 1 5770 0 4\nComment = MEDePass\nDescription = physicianIdentifiers\n\n# Comodo (formerly WoTrust) CA\n\nOID = 1 3 6 1 4 1 6449 1 2 1 3 1\nComment = Comodo CA\nDescription = comodoPolicy\n\nOID = 1 3 6 1 4 1 6449 1 2 2 15\nComment = WoTrust (Comodo) CA\nDescription = wotrustPolicy\n\n# This is actually called \"unknownKeyUsage\" but that's rather misleading,\n# since it's used for Comodo's Certified Delivery Service receive facility\n# we label it as such.\nOID = 1 3 6 1 4 1 6449 1 3 5 2\nComment = Comodo CA\nDescription = comodoCertifiedDeliveryService\n\nOID = 1 3 6 1 4 1 6449 2 1 1\nComment = Comodo CA\nDescription = comodoTimestampingPolicy\n\n# TU Darmstadt ValidityModel\n# http://www.cdc.informatik.tu-darmstadt.de/TI/Forschung/FlexiPKI/validitymodel/index.html\n\nOID = 1 3 6 1 4 1 8301 3 5 1\nComment = TU Darmstadt ValidityModel\nDescription = validityModelChain\n\nOID = 1 3 6 1 4 1 8301 3 5 2\nComment = ValidityModel\nDescription = validityModelShell\n\n# Chilean Government\n\nOID = 1 3 6 1 4 1 8231 1\nComment = Chilean Government national unique roll number\nDescription = rolUnicoNacional\n\n# GNU (GPG) Project\n\nOID = 1 3 6 1 4 1 11591\nComment = GNU Project (see http://www.gnupg.org/oids.html)\nDescription = gnu\n\nOID = 1 3 6 1 4 1 11591 1\nComment = GNU Radius\nDescription = gnuRadius\n\nOID = 1 3 6 1 4 1 11591 3\nComment = GNU Radar\nDescription = gnuRadar\n\nOID = 1 3 6 1 4 1 11591 12\nComment = GNU digest algorithm\nDescription = gnuDigestAlgorithm\n\nOID = 1 3 6 1 4 1 11591 12 2\nComment = GNU digest algorithm\nDescription = tiger\n\nOID = 1 3 6 1 4 1 11591 13\nComment = GNU encryption algorithm\nDescription = gnuEncryptionAlgorithm\n\nOID = 1 3 6 1 4 1 11591 13 2\nComment = GNU encryption algorithm\nDescription = serpent\n\nOID = 1 3 6 1 4 1 11591 13 2 1\nComment = GNU encryption algorithm\nDescription = serpent128_ECB\n\nOID = 1 3 6 1 4 1 11591 13 2 2\nComment = GNU encryption algorithm\nDescription = serpent128_CBC\n\nOID = 1 3 6 1 4 1 11591 13 2 3\nComment = GNU encryption algorithm\nDescription = serpent128_OFB\n\nOID = 1 3 6 1 4 1 11591 13 2 4\nComment = GNU encryption algorithm\nDescription = serpent128_CFB\n\nOID = 1 3 6 1 4 1 11591 13 2 21\nComment = GNU encryption algorithm\nDescription = serpent192_ECB\n\nOID = 1 3 6 1 4 1 11591 13 2 22\nComment = GNU encryption algorithm\nDescription = serpent192_CBC\n\nOID = 1 3 6 1 4 1 11591 13 2 23\nComment = GNU encryption algorithm\nDescription = serpent192_OFB\n\nOID = 1 3 6 1 4 1 11591 13 2 24\nComment = GNU encryption algorithm\nDescription = serpent192_CFB\n\nOID = 1 3 6 1 4 1 11591 13 2 41\nComment = GNU encryption algorithm\nDescription = serpent256_ECB\n\nOID = 1 3 6 1 4 1 11591 13 2 42\nComment = GNU encryption algorithm\nDescription = serpent256_CBC\n\nOID = 1 3 6 1 4 1 11591 13 2 43\nComment = GNU encryption algorithm\nDescription = serpent256_OFB\n\nOID = 1 3 6 1 4 1 11591 13 2 44\nComment = GNU encryption algorithm\nDescription = serpent256_CFB\n\nOID = 1 3 6 1 4 1 11591 15 1\nComment = GNU encryption algorithm\nDescription = curve25519\n\nOID = 1 3 6 1 4 1 11591 15 2\nComment = GNU encryption algorithm\nDescription = curve448\n\nOID = 1 3 6 1 4 1 11591 15 3\nComment = GNU encryption algorithm\nDescription = curve25519ph\n\nOID = 1 3 6 1 4 1 11591 15 4\nComment = GNU encryption algorithm\nDescription = curve448ph\n\n# Northrop Grumman Mission Systems\n\nOID = 1 3 6 1 4 1 16334 509 1 1\nComment = Northrop Grumman extended key usage\nDescription = Northrop Grumman extKeyUsage?\n\nOID = 1 3 6 1 4 1 16334 509 2 1\nComment = Northrop Grumman policy\nDescription = ngcClass1\n\nOID = 1 3 6 1 4 1 16334 509 2 2\nComment = Northrop Grumman policy\nDescription = ngcClass2\n\nOID = 1 3 6 1 4 1 16334 509 2 3\nComment = Northrop Grumman policy\nDescription = ngcClass3\n\n# Safenet\n\nOID = 1 3 6 1 4 1 23629 1 4 2 1 1\nComment = SafeNet\nDescription = safenetUsageLimit\n\nOID = 1 3 6 1 4 1 23629 1 4 2 1 2\nComment = SafeNet\nDescription = safenetEndDate\n\nOID = 1 3 6 1 4 1 23629 1 4 2 1 3\nComment = SafeNet\nDescription = safenetStartDate\n\nOID = 1 3 6 1 4 1 23629 1 4 2 1 4\nComment = SafeNet\nDescription = safenetAdminCert\n\nOID = 1 3 6 1 4 1 23629 1 4 2 2 1\nComment = SafeNet\nDescription = safenetKeyDigest\n\n# PKIX\n\nOID = 1 3 6 1 5 5 7\nDescription = pkix\n\nOID = 1 3 6 1 5 5 7 0 12\nComment = PKIX\nDescription = attributeCert\n\nOID = 1 3 6 1 5 5 7 1\nComment = PKIX\nDescription = privateExtension\n\nOID = 1 3 6 1 5 5 7 1 1\nComment = PKIX private extension\nDescription = authorityInfoAccess\n\nOID = 1 3 6 1 5 5 7 1 2\nComment = PKIX private extension\nDescription = biometricInfo\n\nOID = 1 3 6 1 5 5 7 1 3\nComment = PKIX private extension\nDescription = qcStatements\n\nOID = 1 3 6 1 5 5 7 1 4\nComment = PKIX private extension\nDescription = acAuditIdentity\n\nOID = 1 3 6 1 5 5 7 1 5\nComment = PKIX private extension\nDescription = acTargeting\n\nOID = 1 3 6 1 5 5 7 1 6\nComment = PKIX private extension\nDescription = acAaControls\n\nOID = 1 3 6 1 5 5 7 1 7\nComment = PKIX private extension\nDescription = ipAddrBlocks\n\nOID = 1 3 6 1 5 5 7 1 8\nComment = PKIX private extension\nDescription = autonomousSysIds\n\nOID = 1 3 6 1 5 5 7 1 9\nComment = PKIX private extension\nDescription = routerIdentifier\n\nOID = 1 3 6 1 5 5 7 1 10\nComment = PKIX private extension\nDescription = acProxying\n\nOID = 1 3 6 1 5 5 7 1 11\nComment = PKIX private extension\nDescription = subjectInfoAccess\n\nOID = 1 3 6 1 5 5 7 1 12\nComment = PKIX private extension\nDescription = logoType\n\nOID = 1 3 6 1 5 5 7 1 13\nComment = PKIX private extension\nDescription = wlanSSID\n\nOID = 1 3 6 1 5 5 7 1 14\nComment = PKIX private extension\nDescription = proxyCertInfo\n\nOID = 1 3 6 1 5 5 7 1 15\nComment = PKIX private extension\nDescription = acPolicies\n\nOID = 1 3 6 1 5 5 7 1 16\nComment = PKIX private extension\nDescription = certificateWarranty\n\n# Never used, and the name is confusing.\n#OID = 1 3 6 1 5 5 7 1 17\n#Comment = PKIX private extension\n#Description = sim\n\nOID = 1 3 6 1 5 5 7 1 18\nComment = PKIX private extension\nDescription = cmsContentConstraints\n\nOID = 1 3 6 1 5 5 7 1 19\nComment = PKIX private extension\nDescription = otherCerts\n\nOID = 1 3 6 1 5 5 7 1 20\nComment = PKIX private extension\nDescription = wrappedApexContinKey\n\nOID = 1 3 6 1 5 5 7 1 21\nComment = PKIX private extension\nDescription = clearanceConstraints\n\nOID = 1 3 6 1 5 5 7 1 22\nComment = PKIX private extension\nDescription = skiSemantics\n\nOID = 1 3 6 1 5 5 7 1 23\nComment = PKIX private extension\nDescription = noSecrecyAfforded\n\nOID = 1 3 6 1 5 5 7 1 24\nComment = PKIX private extension\nDescription = tlsFeature\n\nOID = 1 3 6 1 5 5 7 1 25\nComment = PKIX private extension\nDescription = manufacturerUsageDescription\n\nOID = 1 3 6 1 5 5 7 1 26\nComment = PKIX private extension\nDescription = tnAuthList\n\nOID = 1 3 6 1 5 5 7 1 27\nComment = PKIX private extension\nDescription = jwtClaimConstraints\n\nOID = 1 3 6 1 5 5 7 1 28\nComment = PKIX private extension\nDescription = ipAddrBlocksV2\n\nOID = 1 3 6 1 5 5 7 1 29\nComment = PKIX private extension\nDescription = autonomousSysIdsV2\n\nOID = 1 3 6 1 5 5 7 1 30\nComment = PKIX private extension\nDescription = manufacturerUsageDescriptionSigner\n\nOID = 1 3 6 1 5 5 7 1 31\nComment = PKIX private extension\nDescription = acmeIdentifier\n\nOID = 1 3 6 1 5 5 7 2\nComment = PKIX\nDescription = policyQualifierIds\n\nOID = 1 3 6 1 5 5 7 2 1\nComment = PKIX policy qualifier\nDescription = cps\n\nOID = 1 3 6 1 5 5 7 2 2\nComment = PKIX policy qualifier\nDescription = unotice\n\nOID = 1 3 6 1 5 5 7 2 3\nComment = PKIX policy qualifier\nDescription = textNotice\n\nOID = 1 3 6 1 5 5 7 3\nComment = PKIX\nDescription = keyPurpose\n\nOID = 1 3 6 1 5 5 7 3 1\nComment = PKIX key purpose\nDescription = serverAuth\n\nOID = 1 3 6 1 5 5 7 3 2\nComment = PKIX key purpose\nDescription = clientAuth\n\nOID = 1 3 6 1 5 5 7 3 3\nComment = PKIX key purpose\nDescription = codeSigning\n\nOID = 1 3 6 1 5 5 7 3 4\nComment = PKIX key purpose\nDescription = emailProtection\n\nOID = 1 3 6 1 5 5 7 3 5\nComment = PKIX key purpose\nDescription = ipsecEndSystem\n\nOID = 1 3 6 1 5 5 7 3 6\nComment = PKIX key purpose\nDescription = ipsecTunnel\n\nOID = 1 3 6 1 5 5 7 3 7\nComment = PKIX key purpose\nDescription = ipsecUser\n\nOID = 1 3 6 1 5 5 7 3 8\nComment = PKIX key purpose\nDescription = timeStamping\n\nOID = 1 3 6 1 5 5 7 3 9\nComment = PKIX key purpose\nDescription = ocspSigning\n\nOID = 1 3 6 1 5 5 7 3 10\nComment = PKIX key purpose\nDescription = dvcs\n\nOID = 1 3 6 1 5 5 7 3 11\nComment = PKIX key purpose\nDescription = sbgpCertAAServerAuth\n\nOID = 1 3 6 1 5 5 7 3 13\nComment = PKIX key purpose\nDescription = eapOverPPP\n\nOID = 1 3 6 1 5 5 7 3 14\nComment = PKIX key purpose\nDescription = eapOverLAN\n\nOID = 1 3 6 1 5 5 7 4\nComment = PKIX\nDescription = cmpInformationTypes\n\nOID = 1 3 6 1 5 5 7 4 1\nComment = PKIX CMP information\nDescription = caProtEncCert\n\nOID = 1 3 6 1 5 5 7 4 2\nComment = PKIX CMP information\nDescription = signKeyPairTypes\n\nOID = 1 3 6 1 5 5 7 4 3\nComment = PKIX CMP information\nDescription = encKeyPairTypes\n\nOID = 1 3 6 1 5 5 7 4 4\nComment = PKIX CMP information\nDescription = preferredSymmAlg\n\nOID = 1 3 6 1 5 5 7 4 5\nComment = PKIX CMP information\nDescription = caKeyUpdateInfo\n\nOID = 1 3 6 1 5 5 7 4 6\nComment = PKIX CMP information\nDescription = currentCRL\n\nOID = 1 3 6 1 5 5 7 4 7\nComment = PKIX CMP information\nDescription = unsupportedOIDs\n\nOID = 1 3 6 1 5 5 7 4 10\nComment = PKIX CMP information\nDescription = keyPairParamReq\n\nOID = 1 3 6 1 5 5 7 4 11\nComment = PKIX CMP information\nDescription = keyPairParamRep\n\nOID = 1 3 6 1 5 5 7 4 12\nComment = PKIX CMP information\nDescription = revPassphrase\n\nOID = 1 3 6 1 5 5 7 4 13\nComment = PKIX CMP information\nDescription = implicitConfirm\n\nOID = 1 3 6 1 5 5 7 4 14\nComment = PKIX CMP information\nDescription = confirmWaitTime\n\nOID = 1 3 6 1 5 5 7 4 15\nComment = PKIX CMP information\nDescription = origPKIMessage\n\nOID = 1 3 6 1 5 5 7 4 16\nComment = PKIX CMP information\nDescription = suppLangTags\n\nOID = 1 3 6 1 5 5 7 5\nComment = PKIX\nDescription = crmfRegistration\n\nOID = 1 3 6 1 5 5 7 5 1\nComment = PKIX CRMF registration\nDescription = regCtrl\n\nOID = 1 3 6 1 5 5 7 5 1 1\nComment = PKIX CRMF registration control\nDescription = regToken\n\nOID = 1 3 6 1 5 5 7 5 1 2\nComment = PKIX CRMF registration control\nDescription = authenticator\n\nOID = 1 3 6 1 5 5 7 5 1 3\nComment = PKIX CRMF registration control\nDescription = pkiPublicationInfo\n\nOID = 1 3 6 1 5 5 7 5 1 4\nComment = PKIX CRMF registration control\nDescription = pkiArchiveOptions\n\nOID = 1 3 6 1 5 5 7 5 1 5\nComment = PKIX CRMF registration control\nDescription = oldCertID\n\nOID = 1 3 6 1 5 5 7 5 1 6\nComment = PKIX CRMF registration control\nDescription = protocolEncrKey\n\nOID = 1 3 6 1 5 5 7 5 1 7\nComment = PKIX CRMF registration control\nDescription = altCertTemplate\n\nOID = 1 3 6 1 5 5 7 5 1 8\nComment = PKIX CRMF registration control\nDescription = wtlsTemplate\n\nOID = 1 3 6 1 5 5 7 5 2\nComment = PKIX CRMF registration\nDescription = utf8Pairs\n\nOID = 1 3 6 1 5 5 7 5 2 1\nComment = PKIX CRMF registration control\nDescription = utf8Pairs\n\nOID = 1 3 6 1 5 5 7 5 2 2\nComment = PKIX CRMF registration control\nDescription = certReq\n\nOID = 1 3 6 1 5 5 7 6\nComment = PKIX\nDescription = algorithms\n\nOID = 1 3 6 1 5 5 7 6 1\nComment = PKIX algorithm\nDescription = des40\n\nOID = 1 3 6 1 5 5 7 6 2\nComment = PKIX algorithm\nDescription = noSignature\n\nOID = 1 3 6 1 5 5 7 6 3\nComment = PKIX algorithm\nDescription = dh-sig-hmac-sha1\n\nOID = 1 3 6 1 5 5 7 6 4\nComment = PKIX algorithm\nDescription = dh-pop\n\nOID = 1 3 6 1 5 5 7 7\nComment = PKIX\nDescription = cmcControls\n\nOID = 1 3 6 1 5 5 7 8\nComment = PKIX\nDescription = otherNames\n\nOID = 1 3 6 1 5 5 7 8 1\nComment = PKIX other name\nDescription = personalData\n\nOID = 1 3 6 1 5 5 7 8 2\nComment = PKIX other name\nDescription = userGroup\n\nOID = 1 3 6 1 5 5 7 8 5\nComment = PKIX other name\nDescription = xmppAddr\n\nOID = 1 3 6 1 5 5 7 9\nComment = PKIX qualified certificates\nDescription = personalData\n\nOID = 1 3 6 1 5 5 7 9 1\nComment = PKIX personal data\nDescription = dateOfBirth\n\nOID = 1 3 6 1 5 5 7 9 2\nComment = PKIX personal data\nDescription = placeOfBirth\n\nOID = 1 3 6 1 5 5 7 9 3\nComment = PKIX personal data\nDescription = gender\n\nOID = 1 3 6 1 5 5 7 9 4\nComment = PKIX personal data\nDescription = countryOfCitizenship\n\nOID = 1 3 6 1 5 5 7 9 5\nComment = PKIX personal data\nDescription = countryOfResidence\n\nOID = 1 3 6 1 5 5 7 10\nComment = PKIX\nDescription = attributeCertificate\n\nOID = 1 3 6 1 5 5 7 10 1\nComment = PKIX attribute certificate extension\nDescription = authenticationInfo\n\nOID = 1 3 6 1 5 5 7 10 2\nComment = PKIX attribute certificate extension\nDescription = accessIdentity\n\nOID = 1 3 6 1 5 5 7 10 3\nComment = PKIX attribute certificate extension\nDescription = chargingIdentity\n\nOID = 1 3 6 1 5 5 7 10 4\nComment = PKIX attribute certificate extension\nDescription = group\n\nOID = 1 3 6 1 5 5 7 10 5\nComment = PKIX attribute certificate extension\nDescription = role\n\nOID = 1 3 6 1 5 5 7 10 6\nComment = PKIX attribute-certificate extension\nDescription = wlanSSID\n\nOID = 1 3 6 1 5 5 7 11\nComment = PKIX qualified certificates\nDescription = personalData\n\nOID = 1 3 6 1 5 5 7 11 1\nComment = PKIX qualified certificates\nDescription = pkixQCSyntax-v1\n\nOID = 1 3 6 1 5 5 7 14 2\nComment = PKIX policies\nDescription = resourceCertificatePolicy\n\nOID = 1 3 6 1 5 5 7 20\nComment = PKIX qualified certificates\nDescription = logo\n\nOID = 1 3 6 1 5 5 7 20 1\nComment = PKIX\nDescription = logoLoyalty\n\nOID = 1 3 6 1 5 5 7 20 2\nComment = PKIX\nDescription = logoBackground\n\n# OCSP\n\nOID = 1 3 6 1 5 5 7 48 1\nComment = PKIX\nDescription = ocsp\n\nOID = 1 3 6 1 5 5 7 48 1 1\nComment = OCSP\nDescription = ocspBasic\n\nOID = 1 3 6 1 5 5 7 48 1 2\nComment = OCSP\nDescription = ocspNonce\n\nOID = 1 3 6 1 5 5 7 48 1 3\nComment = OCSP\nDescription = ocspCRL\n\nOID = 1 3 6 1 5 5 7 48 1 4\nComment = OCSP\nDescription = ocspResponse\n\nOID = 1 3 6 1 5 5 7 48 1 5\nComment = OCSP\nDescription = ocspNoCheck\n\nOID = 1 3 6 1 5 5 7 48 1 6\nComment = OCSP\nDescription = ocspArchiveCutoff\n\nOID = 1 3 6 1 5 5 7 48 1 7\nComment = OCSP\nDescription = ocspServiceLocator\n\n# Subject/AuthorityInfo types (OCSP is already listed above)\n\nOID = 1 3 6 1 5 5 7 48 2\nComment = PKIX subject/authority info access descriptor\nDescription = caIssuers\n\nOID = 1 3 6 1 5 5 7 48 3\nComment = PKIX subject/authority info access descriptor\nDescription = timeStamping\n\nOID = 1 3 6 1 5 5 7 48 4\nComment = PKIX subject/authority info access descriptor\nDescription = dvcs\n\nOID = 1 3 6 1 5 5 7 48 5\nComment = PKIX subject/authority info access descriptor\nDescription = caRepository\n\nOID = 1 3 6 1 5 5 7 48 7\nComment = PKIX subject/authority info access descriptor\nDescription = signedObjectRepository\n\nOID = 1 3 6 1 5 5 7 48 10\nComment = PKIX subject/authority info access descriptor\nDescription = rpkiManifest\n\nOID = 1 3 6 1 5 5 7 48 11\nComment = PKIX subject/authority info access descriptor\nDescription = signedObject\n\n# ISAKMP\n\nOID = 1 3 6 1 5 5 8 1 1\nComment = ISAKMP HMAC algorithm\nDescription = hmacMD5\n\nOID = 1 3 6 1 5 5 8 1 2\nComment = ISAKMP HMAC algorithm\nDescription = hmacSHA\n\nOID = 1 3 6 1 5 5 8 1 3\nComment = ISAKMP HMAC algorithm\nDescription = hmacTiger\n\nOID = 1 3 6 1 5 5 8 2 2\nComment = IKE ???\nDescription = iKEIntermediate\n\n# DEC (via ECMA)\n\nOID = 1 3 12 2 1011 7 1\nComment = DASS algorithm\nDescription = decEncryptionAlgorithm\n\nOID = 1 3 12 2 1011 7 1 2\nComment = DASS encryption algorithm\nDescription = decDEA\n\nOID = 1 3 12 2 1011 7 2\nComment = DASS algorithm\nDescription = decHashAlgorithm\n\nOID = 1 3 12 2 1011 7 2 1\nComment = DASS hash algorithm\nDescription = decMD2\n\nOID = 1 3 12 2 1011 7 2 2\nComment = DASS hash algorithm\nDescription = decMD4\n\nOID = 1 3 12 2 1011 7 3\nComment = DASS algorithm\nDescription = decSignatureAlgorithm\n\nOID = 1 3 12 2 1011 7 3 1\nComment = DASS signature algorithm\nDescription = decMD2withRSA\n\nOID = 1 3 12 2 1011 7 3 2\nComment = DASS signature algorithm\nDescription = decMD4withRSA\n\nOID = 1 3 12 2 1011 7 3 3\nComment = DASS signature algorithm\nDescription = decDEAMAC\n\n# NIST Open Systems Environment (OSE) Implementor's Workshop (OIW),\n# specialising in oddball and partially-defunct OIDs\n\nOID = 1 3 14 2 26 5\nComment = Unsure about this OID\nDescription = sha\n\nOID = 1 3 14 3 2 1 1\nComment = X.509. Unsure about this OID\nDescription = rsa\n\nOID = 1 3 14 3 2 2\nComment = Oddball OIW OID\nDescription = md4WitRSA\n\nOID = 1 3 14 3 2 3\nComment = Oddball OIW OID\nDescription = md5WithRSA\n\nOID = 1 3 14 3 2 4\nComment = Oddball OIW OID\nDescription = md4WithRSAEncryption\n\nOID = 1 3 14 3 2 2 1\nComment = X.509. Deprecated\nDescription = sqmod-N\nWarning\n\nOID = 1 3 14 3 2 3 1\nComment = X.509. Deprecated\nDescription = sqmod-NwithRSA\nWarning\n\nOID = 1 3 14 3 2 6\nDescription = desECB\n\nOID = 1 3 14 3 2 7\nDescription = desCBC\n\nOID = 1 3 14 3 2 8\nDescription = desOFB\n\nOID = 1 3 14 3 2 9\nDescription = desCFB\n\nOID = 1 3 14 3 2 10\nDescription = desMAC\n\nOID = 1 3 14 3 2 11\nComment = ISO 9796-2, also X9.31 Part 1\nDescription = rsaSignature\n\nOID = 1 3 14 3 2 12\nComment = OIW?, supposedly from an incomplete version of SDN.701 (doesn't match final SDN.701)\nDescription = dsa\nWarning\n\nOID = 1 3 14 3 2 13\nComment = Oddball OIW OID.  Incorrectly used by JDK 1.1 in place of (1 3 14 3 2 27)\n# Their response was that they know it's wrong, but noone uses SHA0 so it won't\n# cause any problems, right?\nDescription = dsaWithSHA\nWarning\n\n# The various md<x>WithRSASignature OIDs are for the ANSI X9.31 draft and use\n# ISO 9796-2 padding rules.  This work was derailed during the PKP brouhaha and\n# is still in progress (and probably will remain so)\nOID = 1 3 14 3 2 14\nComment = Oddball OIW OID using 9796-2 padding rules\nDescription = mdc2WithRSASignature\n\nOID = 1 3 14 3 2 15\nComment = Oddball OIW OID using 9796-2 padding rules\nDescription = shaWithRSASignature\n\nOID = 1 3 14 3 2 16\nComment = Oddball OIW OID. Deprecated, use a plain DH OID instead\nDescription = dhWithCommonModulus\nWarning\n\nOID = 1 3 14 3 2 17\nComment = Oddball OIW OID. Mode is ECB\nDescription = desEDE\n\nOID = 1 3 14 3 2 18\nComment = Oddball OIW OID\nDescription = sha\n\nOID = 1 3 14 3 2 19\nComment = Oddball OIW OID, DES-based hash, planned for X9.31 Part 2\nDescription = mdc-2\n\nOID = 1 3 14 3 2 20\nComment = Oddball OIW OID.  Deprecated, use a plain DSA OID instead\nDescription = dsaCommon\nWarning\n\nOID = 1 3 14 3 2 21\nComment = Oddball OIW OID.  Deprecated, use a plain dsaWithSHA OID instead\nDescription = dsaCommonWithSHA\nWarning\n\nOID = 1 3 14 3 2 22\nComment = Oddball OIW OID\nDescription = rsaKeyTransport\n\nOID = 1 3 14 3 2 23\nComment = Oddball OIW OID\nDescription = keyed-hash-seal\n\nOID = 1 3 14 3 2 24\nComment = Oddball OIW OID using 9796-2 padding rules\nDescription = md2WithRSASignature\n\nOID = 1 3 14 3 2 25\nComment = Oddball OIW OID using 9796-2 padding rules\nDescription = md5WithRSASignature\n\nOID = 1 3 14 3 2 26\nComment = OIW\nDescription = sha1\n\n# Yet another multiply-assigned OID\nOID = 1 3 14 3 2 27\nComment = OIW. This OID may also be assigned as ripemd-160\nDescription = dsaWithSHA1\n\nOID = 1 3 14 3 2 28\nComment = OIW\nDescription = dsaWithCommonSHA1\n\nOID = 1 3 14 3 2 29\nComment = Oddball OIW OID\nDescription = sha-1WithRSAEncryption\n\nOID = 1 3 14 3 3 1\nComment = Oddball OIW OID\nDescription = simple-strong-auth-mechanism\n\nOID = 1 3 14 7 2 1 1\nComment = Unsure about this OID\nDescription = ElGamal\n\nOID = 1 3 14 7 2 3 1\nComment = Unsure about this OID\nDescription = md2WithRSA\n\nOID = 1 3 14 7 2 3 2\nComment = Unsure about this OID\nDescription = md2WithElGamal\n\n# Teletrust\n\nOID = 1 3 36 1\nComment = Teletrust document\nDescription = document\n\nOID = 1 3 36 1 1\nComment = Teletrust document\nDescription = finalVersion\n\nOID = 1 3 36 1 2\nComment = Teletrust document\nDescription = draft\n\nOID = 1 3 36 2\nComment = Teletrust sio\nDescription = sio\n\nOID = 1 3 36 2 1\nComment = Teletrust sio\nDescription = sedu\n\nOID = 1 3 36 3\nComment = Teletrust algorithm\nDescription = algorithm\n\nOID = 1 3 36 3 1\nComment = Teletrust algorithm\nDescription = encryptionAlgorithm\n\nOID = 1 3 36 3 1 1\nComment = Teletrust encryption algorithm\nDescription = des\n\nOID = 1 3 36 3 1 1 1\nComment = Teletrust encryption algorithm\nDescription = desECB_pad\n\nOID = 1 3 36 3 1 1 1 1\nComment = Teletrust encryption algorithm\nDescription = desECB_ISOpad\n\nOID = 1 3 36 3 1 1 2 1\nComment = Teletrust encryption algorithm\nDescription = desCBC_pad\n\nOID = 1 3 36 3 1 1 2 1 1\nComment = Teletrust encryption algorithm\nDescription = desCBC_ISOpad\n\nOID = 1 3 36 3 1 3\nComment = Teletrust encryption algorithm\nDescription = des_3\n\nOID = 1 3 36 3 1 3 1 1\nComment = Teletrust encryption algorithm. EDE triple DES\nDescription = des_3ECB_pad\n\nOID = 1 3 36 3 1 3 1 1 1\nComment = Teletrust encryption algorithm. EDE triple DES\nDescription = des_3ECB_ISOpad\n\nOID = 1 3 36 3 1 3 2 1\nComment = Teletrust encryption algorithm. EDE triple DES\nDescription = des_3CBC_pad\n\nOID = 1 3 36 3 1 3 2 1 1\nComment = Teletrust encryption algorithm. EDE triple DES\nDescription = des_3CBC_ISOpad\n\nOID = 1 3 36 3 1 2\nComment = Teletrust encryption algorithm\nDescription = idea\n\nOID = 1 3 36 3 1 2 1\nComment = Teletrust encryption algorithm\nDescription = ideaECB\n\nOID = 1 3 36 3 1 2 1 1\nComment = Teletrust encryption algorithm\nDescription = ideaECB_pad\n\nOID = 1 3 36 3 1 2 1 1 1\nComment = Teletrust encryption algorithm\nDescription = ideaECB_ISOpad\n\nOID = 1 3 36 3 1 2 2\nComment = Teletrust encryption algorithm\nDescription = ideaCBC\n\nOID = 1 3 36 3 1 2 2 1\nComment = Teletrust encryption algorithm\nDescription = ideaCBC_pad\n\nOID = 1 3 36 3 1 2 2 1 1\nComment = Teletrust encryption algorithm\nDescription = ideaCBC_ISOpad\n\nOID = 1 3 36 3 1 2 3\nComment = Teletrust encryption algorithm\nDescription = ideaOFB\n\nOID = 1 3 36 3 1 2 4\nComment = Teletrust encryption algorithm\nDescription = ideaCFB\n\nOID = 1 3 36 3 1 4\nComment = Teletrust encryption algorithm\nDescription = rsaEncryption\n\nOID = 1 3 36 3 1 4 512 17\nComment = Teletrust encryption algorithm\nDescription = rsaEncryptionWithlmod512expe17\n\nOID = 1 3 36 3 1 5\nComment = Teletrust encryption algorithm\nDescription = bsi-1\n\nOID = 1 3 36 3 1 5 1\nComment = Teletrust encryption algorithm\nDescription = bsi_1ECB_pad\n\nOID = 1 3 36 3 1 5 2\nComment = Teletrust encryption algorithm\nDescription = bsi_1CBC_pad\n\nOID = 1 3 36 3 1 5 2 1\nComment = Teletrust encryption algorithm\nDescription = bsi_1CBC_PEMpad\n\nOID = 1 3 36 3 2\nComment = Teletrust algorithm\nDescription = hashAlgorithm\n\nOID = 1 3 36 3 2 1\nComment = Teletrust hash algorithm\nDescription = ripemd160\n\nOID = 1 3 36 3 2 2\nComment = Teletrust hash algorithm\nDescription = ripemd128\n\nOID = 1 3 36 3 2 3\nComment = Teletrust hash algorithm\nDescription = ripemd256\n\nOID = 1 3 36 3 2 4\nComment = Teletrust hash algorithm\nDescription = mdc2singleLength\n\nOID = 1 3 36 3 2 5\nComment = Teletrust hash algorithm\nDescription = mdc2doubleLength\n\nOID = 1 3 36 3 3\nComment = Teletrust algorithm\nDescription = signatureAlgorithm\n\nOID = 1 3 36 3 3 1\nComment = Teletrust signature algorithm\nDescription = rsaSignature\n\nOID = 1 3 36 3 3 1 1\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1\n\n# What *were* they thinking?\nOID = 1 3 36 3 3 1 1 512 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l512_l2\nOID = 1 3 36 3 3 1 1 640 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l640_l2\nOID = 1 3 36 3 3 1 1 768 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l768_l2\nOID = 1 3 36 3 3 1 1 896 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l896_l2\nOID = 1 3 36 3 3 1 1 1024 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l1024_l2\nOID = 1 3 36 3 3 1 1 512 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l512_l3\nOID = 1 3 36 3 3 1 1 640 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l640_l3\nOID = 1 3 36 3 3 1 1 768 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l768_l3\nOID = 1 3 36 3 3 1 1 896 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l896_l3\nOID = 1 3 36 3 3 1 1 1024 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l1024_l3\nOID = 1 3 36 3 3 1 1 512 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l512_l5\nOID = 1 3 36 3 3 1 1 640 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l640_l5\nOID = 1 3 36 3 3 1 1 768 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l768_l5\nOID = 1 3 36 3 3 1 1 896 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l896_l5\nOID = 1 3 36 3 3 1 1 1024 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l1024_l5\nOID = 1 3 36 3 3 1 1 512 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l512_l9\nOID = 1 3 36 3 3 1 1 640 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l640_l9\nOID = 1 3 36 3 3 1 1 768 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l768_l9\nOID = 1 3 36 3 3 1 1 896 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l896_l9\nOID = 1 3 36 3 3 1 1 1024 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l1024_l9\nOID = 1 3 36 3 3 1 1 512 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l512_l11\nOID = 1 3 36 3 3 1 1 640 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l640_l11\nOID = 1 3 36 3 3 1 1 768 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l768_l11\nOID = 1 3 36 3 3 1 1 896 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l896_l11\nOID = 1 3 36 3 3 1 1 1024 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithsha1_l1024_l11\n\nOID = 1 3 36 3 3 1 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160\n\nOID = 1 3 36 3 3 1 2 512 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l512_l2\nOID = 1 3 36 3 3 1 2 640 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l640_l2\nOID = 1 3 36 3 3 1 2 768 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l768_l2\nOID = 1 3 36 3 3 1 2 896 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l896_l2\nOID = 1 3 36 3 3 1 2 1024 2\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l1024_l2\nOID = 1 3 36 3 3 1 2 512 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l512_l3\nOID = 1 3 36 3 3 1 2 640 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l640_l3\nOID = 1 3 36 3 3 1 2 768 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l768_l3\nOID = 1 3 36 3 3 1 2 896 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l896_l3\nOID = 1 3 36 3 3 1 2 1024 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l1024_l3\nOID = 1 3 36 3 3 1 2 512 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l512_l5\nOID = 1 3 36 3 3 1 2 640 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l640_l5\nOID = 1 3 36 3 3 1 2 768 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l768_l5\nOID = 1 3 36 3 3 1 2 896 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l896_l5\nOID = 1 3 36 3 3 1 2 1024 5\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l1024_l5\nOID = 1 3 36 3 3 1 2 512 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l512_l9\nOID = 1 3 36 3 3 1 2 640 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l640_l9\nOID = 1 3 36 3 3 1 2 768 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l768_l9\nOID = 1 3 36 3 3 1 2 896 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l896_l9\nOID = 1 3 36 3 3 1 2 1024 9\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l1024_l9\nOID = 1 3 36 3 3 1 2 512 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l512_l11\nOID = 1 3 36 3 3 1 2 640 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l640_l11\nOID = 1 3 36 3 3 1 2 768 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l768_l11\nOID = 1 3 36 3 3 1 2 896 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l896_l11\nOID = 1 3 36 3 3 1 2 1024 11\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithripemd160_l1024_l11\n\nOID = 1 3 36 3 3 1 3\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithrimpemd128\n\nOID = 1 3 36 3 3 1 4\nComment = Teletrust signature algorithm\nDescription = rsaSignatureWithrimpemd256\n\nOID = 1 3 36 3 3 2\nComment = Teletrust signature algorithm\nDescription = ecsieSign\n\nOID = 1 3 36 3 3 2 1\nComment = Teletrust signature algorithm\nDescription = ecsieSignWithsha1\n\nOID = 1 3 36 3 3 2 2\nComment = Teletrust signature algorithm\nDescription = ecsieSignWithripemd160\n\nOID = 1 3 36 3 3 2 3\nComment = Teletrust signature algorithm\nDescription = ecsieSignWithmd2\n\nOID = 1 3 36 3 3 2 4\nComment = Teletrust signature algorithm\nDescription = ecsieSignWithmd5\n\n# Brainpool ECC Curves.  Note that these fall under the Teletrust ECC\n# signature algorithm arc (ecsieSign, 1 3 36 3 3 2) but they're listed\n# separately here because they were standardised under the Brainpool\n# initiative.\n\nOID = 1 3 36 3 3 2 8 1 1 1\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP160r1\n\nOID = 1 3 36 3 3 2 8 1 1 2\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP160t1\n\nOID = 1 3 36 3 3 2 8 1 1 3\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP192r1\n\nOID = 1 3 36 3 3 2 8 1 1 4\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP192t1\n\nOID = 1 3 36 3 3 2 8 1 1 5\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP224r1\n\nOID = 1 3 36 3 3 2 8 1 1 6\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP224t1\n\nOID = 1 3 36 3 3 2 8 1 1 7\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP256r1\n\nOID = 1 3 36 3 3 2 8 1 1 8\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP256t1\n\nOID = 1 3 36 3 3 2 8 1 1 9\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP320r1\n\nOID = 1 3 36 3 3 2 8 1 1 10\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP320t1\n\nOID = 1 3 36 3 3 2 8 1 1 11\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP384r1\n\nOID = 1 3 36 3 3 2 8 1 1 12\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP384t1\n\nOID = 1 3 36 3 3 2 8 1 1 13\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP512r1\n\nOID = 1 3 36 3 3 2 8 1 1 14\nComment = ECC Brainpool Standard Curves and Curve Generation\nDescription = brainpoolP512t1\n\nOID = 1 3 36 3 4\nComment = Teletrust algorithm\nDescription = signatureScheme\n\nOID = 1 3 36 3 4 1\nComment = Teletrust signature scheme\nDescription = sigS_ISO9796-1\n\nOID = 1 3 36 3 4 2\nComment = Teletrust signature scheme\nDescription = sigS_ISO9796-2\n\nOID = 1 3 36 3 4 2 1\nComment = Teletrust signature scheme. Unsure what this is supposed to be\nDescription = sigS_ISO9796-2Withred\n\nOID = 1 3 36 3 4 2 2\nComment = Teletrust signature scheme. Unsure what this is supposed to be\nDescription = sigS_ISO9796-2Withrsa\n\nOID = 1 3 36 3 4 2 3\nComment = Teletrust signature scheme. 9796-2 with random number in padding field\nDescription = sigS_ISO9796-2Withrnd\n\nOID = 1 3 36 4\nComment = Teletrust attribute\nDescription = attribute\n\nOID = 1 3 36 5\nComment = Teletrust policy\nDescription = policy\n\nOID = 1 3 36 6\nComment = Teletrust API\nDescription = api\n\nOID = 1 3 36 6 1\nComment = Teletrust API\nDescription = manufacturer-specific_api\n\nOID = 1 3 36 6 1 1\nComment = Teletrust API\nDescription = utimaco-api\n\nOID = 1 3 36 6 2\nComment = Teletrust API\nDescription = functionality-specific_api\n\nOID = 1 3 36 7\nComment = Teletrust key management\nDescription = keymgmnt\n\nOID = 1 3 36 7 1\nComment = Teletrust key management\nDescription = keyagree\n\nOID = 1 3 36 7 1 1\nComment = Teletrust key management\nDescription = bsiPKE\n\nOID = 1 3 36 7 2\nComment = Teletrust key management\nDescription = keytrans\n\nOID = 1 3 36 7 2 1\nComment = Teletrust key management. 9796-2 with key stored in hash field\nDescription = encISO9796-2Withrsa\n\nOID = 1 3 36 8 1 1\nComment = Teletrust policy\nDescription = Teletrust SigGConform policyIdentifier\n\nOID = 1 3 36 8 2 1\nComment = Teletrust extended key usage\nDescription = directoryService\n\nOID = 1 3 36 8 3 1\nComment = Teletrust attribute\nDescription = dateOfCertGen\n\nOID = 1 3 36 8 3 2\nComment = Teletrust attribute\nDescription = procuration\n\nOID = 1 3 36 8 3 3\nComment = Teletrust attribute\nDescription = admission\n\nOID = 1 3 36 8 3 4\nComment = Teletrust attribute\nDescription = monetaryLimit\n\nOID = 1 3 36 8 3 5\nComment = Teletrust attribute\nDescription = declarationOfMajority\n\nOID = 1 3 36 8 3 6\nComment = Teletrust attribute\nDescription = integratedCircuitCardSerialNumber\n\nOID = 1 3 36 8 3 7\nComment = Teletrust attribute\nDescription = pKReference\n\nOID = 1 3 36 8 3 8\nComment = Teletrust attribute\nDescription = restriction\n\nOID = 1 3 36 8 3 9\nComment = Teletrust attribute\nDescription = retrieveIfAllowed\n\nOID = 1 3 36 8 3 10\nComment = Teletrust attribute\nDescription = requestedCertificate\n\n# The following are left in German because there's no clear\n# equivalent for many of the terms in English.  Tut mir sorry.\n# (Note that they actually genderise the OIDs, which is quite\n# bizarre since they're simply role identifiers.  Being\n# courteous, they let the, um, female OIDs go first).\nOID = 1 3 36 8 3 11\nComment = Teletrust attribute\nDescription = namingAuthorities\n\nOID = 1 3 36 8 3 11 1\nComment = Teletrust naming authorities\nDescription = rechtWirtschaftSteuern\n\nOID = 1 3 36 8 3 11 1 1\nComment = Teletrust ProfessionInfo\nDescription = rechtsanwaeltin\n\nOID = 1 3 36 8 3 11 1 2\nComment = Teletrust ProfessionInfo\nDescription = rechtsanwalt\n\nOID = 1 3 36 8 3 11 1 3\nComment = Teletrust ProfessionInfo\nDescription = rechtsBeistand\n\nOID = 1 3 36 8 3 11 1 4\nComment = Teletrust ProfessionInfo\nDescription = steuerBeraterin\n\nOID = 1 3 36 8 3 11 1 5\nComment = Teletrust ProfessionInfo\nDescription = steuerBerater\n\nOID = 1 3 36 8 3 11 1 6\nComment = Teletrust ProfessionInfo\nDescription = steuerBevollmaechtigte\n\nOID = 1 3 36 8 3 11 1 7\nComment = Teletrust ProfessionInfo\nDescription = steuerBevollmaechtigter\n\nOID = 1 3 36 8 3 11 1 8\nComment = Teletrust ProfessionInfo\nDescription = notarin\n\nOID = 1 3 36 8 3 11 1 9\nComment = Teletrust ProfessionInfo\nDescription = notar\n\nOID = 1 3 36 8 3 11 1 10\nComment = Teletrust ProfessionInfo\nDescription = notarVertreterin\n\nOID = 1 3 36 8 3 11 1 11\nComment = Teletrust ProfessionInfo\nDescription = notarVertreter\n\nOID = 1 3 36 8 3 11 1 12\nComment = Teletrust ProfessionInfo\nDescription = notariatsVerwalterin\n\nOID = 1 3 36 8 3 11 1 13\nComment = Teletrust ProfessionInfo\nDescription = notariatsVerwalter\n\nOID = 1 3 36 8 3 11 1 14\nComment = Teletrust ProfessionInfo\nDescription = wirtschaftsPrueferin\n\nOID = 1 3 36 8 3 11 1 15\nComment = Teletrust ProfessionInfo\nDescription = wirtschaftsPruefer\n\nOID = 1 3 36 8 3 11 1 16\nComment = Teletrust ProfessionInfo\nDescription = vereidigteBuchprueferin\n\nOID = 1 3 36 8 3 11 1 17\nComment = Teletrust ProfessionInfo\nDescription = vereidigterBuchpruefer\n\nOID = 1 3 36 8 3 11 1 18\nComment = Teletrust ProfessionInfo\nDescription = patentAnwaeltin\n\nOID = 1 3 36 8 3 11 1 19\nComment = Teletrust ProfessionInfo\nDescription = patentAnwalt\n\nOID = 1 3 36 8 3 12\nComment = Teletrust OCSP attribute (obsolete)\nDescription = certInDirSince\nWarning\n\nOID = 1 3 36 8 3 13\nComment = Teletrust OCSP attribute\nDescription = certHash\n\nOID = 1 3 36 8 3 14\nComment = Teletrust attribute\nDescription = nameAtBirth\n\nOID = 1 3 36 8 3 15\nComment = Teletrust attribute\nDescription = additionalInformation\n\nOID = 1 3 36 8 4 1\nComment = Teletrust OtherName attribute\nDescription = personalData\n\nOID = 1 3 36 8 4 8\nComment = Teletrust attribute certificate attribute\nDescription = restriction\n\nOID = 1 3 36 8 5 1 1 1\nComment = Teletrust signature algorithm\nDescription = rsaIndicateSHA1\n\nOID = 1 3 36 8 5 1 1 2\nComment = Teletrust signature algorithm\nDescription = rsaIndicateRIPEMD160\n\nOID = 1 3 36 8 5 1 1 3\nComment = Teletrust signature algorithm\nDescription = rsaWithSHA1\n\nOID = 1 3 36 8 5 1 1 4\nComment = Teletrust signature algorithm\nDescription = rsaWithRIPEMD160\n\nOID = 1 3 36 8 5 1 2 1\nComment = Teletrust signature algorithm\nDescription = dsaExtended\n\nOID = 1 3 36 8 5 1 2 2\nComment = Teletrust signature algorithm\nDescription = dsaWithRIPEMD160\n\nOID = 1 3 36 8 6 1\nComment = Teletrust signature attributes\nDescription = cert\n\nOID = 1 3 36 8 6 2\nComment = Teletrust signature attributes\nDescription = certRef\n\nOID = 1 3 36 8 6 3\nComment = Teletrust signature attributes\nDescription = attrCert\n\nOID = 1 3 36 8 6 4\nComment = Teletrust signature attributes\nDescription = attrRef\n\nOID = 1 3 36 8 6 5\nComment = Teletrust signature attributes\nDescription = fileName\n\nOID = 1 3 36 8 6 6\nComment = Teletrust signature attributes\nDescription = storageTime\n\nOID = 1 3 36 8 6 7\nComment = Teletrust signature attributes\nDescription = fileSize\n\nOID = 1 3 36 8 6 8\nComment = Teletrust signature attributes\nDescription = location\n\nOID = 1 3 36 8 6 9\nComment = Teletrust signature attributes\nDescription = sigNumber\n\nOID = 1 3 36 8 6 10\nComment = Teletrust signature attributes\nDescription = autoGen\n\nOID = 1 3 36 8 7 1 1\nComment = Teletrust presentation types\nDescription = ptAdobeILL\n\nOID = 1 3 36 8 7 1 2\nComment = Teletrust presentation types\nDescription = ptAmiPro\n\nOID = 1 3 36 8 7 1 3\nComment = Teletrust presentation types\nDescription = ptAutoCAD\n\nOID = 1 3 36 8 7 1 4\nComment = Teletrust presentation types\nDescription = ptBinary\n\nOID = 1 3 36 8 7 1 5\nComment = Teletrust presentation types\nDescription = ptBMP\n\nOID = 1 3 36 8 7 1 6\nComment = Teletrust presentation types\nDescription = ptCGM\n\nOID = 1 3 36 8 7 1 7\nComment = Teletrust presentation types\nDescription = ptCorelCRT\n\nOID = 1 3 36 8 7 1 8\nComment = Teletrust presentation types\nDescription = ptCorelDRW\n\nOID = 1 3 36 8 7 1 9\nComment = Teletrust presentation types\nDescription = ptCorelEXC\n\nOID = 1 3 36 8 7 1 10\nComment = Teletrust presentation types\nDescription = ptCorelPHT\n\nOID = 1 3 36 8 7 1 11\nComment = Teletrust presentation types\nDescription = ptDraw\n\nOID = 1 3 36 8 7 1 12\nComment = Teletrust presentation types\nDescription = ptDVI\n\nOID = 1 3 36 8 7 1 13\nComment = Teletrust presentation types\nDescription = ptEPS\n\nOID = 1 3 36 8 7 1 14\nComment = Teletrust presentation types\nDescription = ptExcel\n\nOID = 1 3 36 8 7 1 15\nComment = Teletrust presentation types\nDescription = ptGEM\n\nOID = 1 3 36 8 7 1 16\nComment = Teletrust presentation types\nDescription = ptGIF\n\nOID = 1 3 36 8 7 1 17\nComment = Teletrust presentation types\nDescription = ptHPGL\n\nOID = 1 3 36 8 7 1 18\nComment = Teletrust presentation types\nDescription = ptJPEG\n\nOID = 1 3 36 8 7 1 19\nComment = Teletrust presentation types\nDescription = ptKodak\n\nOID = 1 3 36 8 7 1 20\nComment = Teletrust presentation types\nDescription = ptLaTeX\n\nOID = 1 3 36 8 7 1 21\nComment = Teletrust presentation types\nDescription = ptLotus\n\nOID = 1 3 36 8 7 1 22\nComment = Teletrust presentation types\nDescription = ptLotusPIC\n\nOID = 1 3 36 8 7 1 23\nComment = Teletrust presentation types\nDescription = ptMacPICT\n\nOID = 1 3 36 8 7 1 24\nComment = Teletrust presentation types\nDescription = ptMacWord\n\nOID = 1 3 36 8 7 1 25\nComment = Teletrust presentation types\nDescription = ptMSWfD\n\nOID = 1 3 36 8 7 1 26\nComment = Teletrust presentation types\nDescription = ptMSWord\n\nOID = 1 3 36 8 7 1 27\nComment = Teletrust presentation types\nDescription = ptMSWord2\n\nOID = 1 3 36 8 7 1 28\nComment = Teletrust presentation types\nDescription = ptMSWord6\n\nOID = 1 3 36 8 7 1 29\nComment = Teletrust presentation types\nDescription = ptMSWord8\n\nOID = 1 3 36 8 7 1 30\nComment = Teletrust presentation types\nDescription = ptPDF\n\nOID = 1 3 36 8 7 1 31\nComment = Teletrust presentation types\nDescription = ptPIF\n\nOID = 1 3 36 8 7 1 32\nComment = Teletrust presentation types\nDescription = ptPostscript\n\nOID = 1 3 36 8 7 1 33\nComment = Teletrust presentation types\nDescription = ptRTF\n\nOID = 1 3 36 8 7 1 34\nComment = Teletrust presentation types\nDescription = ptSCITEX\n\nOID = 1 3 36 8 7 1 35\nComment = Teletrust presentation types\nDescription = ptTAR\n\nOID = 1 3 36 8 7 1 36\nComment = Teletrust presentation types\nDescription = ptTarga\n\nOID = 1 3 36 8 7 1 37\nComment = Teletrust presentation types\nDescription = ptTeX\n\nOID = 1 3 36 8 7 1 38\nComment = Teletrust presentation types\nDescription = ptText\n\nOID = 1 3 36 8 7 1 39\nComment = Teletrust presentation types\nDescription = ptTIFF\n\nOID = 1 3 36 8 7 1 40\nComment = Teletrust presentation types\nDescription = ptTIFF-FC\n\nOID = 1 3 36 8 7 1 41\nComment = Teletrust presentation types\nDescription = ptUID\n\nOID = 1 3 36 8 7 1 42\nComment = Teletrust presentation types\nDescription = ptUUEncode\n\nOID = 1 3 36 8 7 1 43\nComment = Teletrust presentation types\nDescription = ptWMF\n\nOID = 1 3 36 8 7 1 44\nComment = Teletrust presentation types\nDescription = ptWordPerfect\n\nOID = 1 3 36 8 7 1 45\nComment = Teletrust presentation types\nDescription = ptWPGrph\n\n# Thawte\n\nOID = 1 3 101 1 4\nComment = Thawte\nDescription = thawte-ce\n\nOID = 1 3 101 1 4 1\nComment = Thawte certificate extension\nDescription = strongExtranet\n\n# Symantec, who seem to have taken over the Thawte arc via Verisign.\n\nOID = 1 3 101 110\nComment = ECDH 25519 key agreement algorithm\nDescription = curveX25519\n\nOID = 1 3 101 111\nComment = ECDH 448 key agreement algorithm\nDescription = curveX448\n\nOID = 1 3 101 112\nComment = EdDSA 25519 signature algorithm\nDescription = curveEd25519\n\nOID = 1 3 101 113\nComment = EdDSA 448 signature algorithm\nDescription = curveEd448\n\nOID = 1 3 101 114\nComment = EdDSA 25519 pre-hash signature algorithm\nDescription = curveEd25519ph\n\nOID = 1 3 101 115\nComment = EdDSA 448 pre-hash signature algorithm\nDescription = curveEd448ph\n\n# SECG (Standards for Efficient Cryptography Group), who are just\n# Certicom \"All your curves are belong to us\" named elliptic curves\n\nOID = 1 3 132 0 1\nComment = SECG (Certicom) named elliptic curve\nDescription = sect163k1\n\nOID = 1 3 132 0 2\nComment = SECG (Certicom) named elliptic curve\nDescription = sect163r1\n\nOID = 1 3 132 0 3\nComment = SECG (Certicom) named elliptic curve\nDescription = sect239k1\n\nOID = 1 3 132 0 4\nComment = SECG (Certicom) named elliptic curve\nDescription = sect113r1\n\nOID = 1 3 132 0 5\nComment = SECG (Certicom) named elliptic curve\nDescription = sect113r2\n\nOID = 1 3 132 0 6\nComment = SECG (Certicom) named elliptic curve\nDescription = secp112r1\n\nOID = 1 3 132 0 7\nComment = SECG (Certicom) named elliptic curve\nDescription = secp112r2\n\nOID = 1 3 132 0 8\nComment = SECG (Certicom) named elliptic curve\nDescription = secp160r1\n\nOID = 1 3 132 0 9\nComment = SECG (Certicom) named elliptic curve\nDescription = secp160k1\n\nOID = 1 3 132 0 10\nComment = SECG (Certicom) named elliptic curve\nDescription = secp256k1\n\nOID = 1 3 132 0 15\nComment = SECG (Certicom) named elliptic curve\nDescription = sect163r2\n\nOID = 1 3 132 0 16\nComment = SECG (Certicom) named elliptic curve\nDescription = sect283k1\n\nOID = 1 3 132 0 17\nComment = SECG (Certicom) named elliptic curve\nDescription = sect283r1\n\nOID = 1 3 132 0 22\nComment = SECG (Certicom) named elliptic curve\nDescription = sect131r1\n\nOID = 1 3 132 0 23\nComment = SECG (Certicom) named elliptic curve\nDescription = sect131r2\n\nOID = 1 3 132 0 24\nComment = SECG (Certicom) named elliptic curve\nDescription = sect193r1\n\nOID = 1 3 132 0 25\nComment = SECG (Certicom) named elliptic curve\nDescription = sect193r2\n\nOID = 1 3 132 0 26\nComment = SECG (Certicom) named elliptic curve\nDescription = sect233k1\n\nOID = 1 3 132 0 27\nComment = SECG (Certicom) named elliptic curve\nDescription = sect233r1\n\nOID = 1 3 132 0 28\nComment = SECG (Certicom) named elliptic curve\nDescription = secp128r1\n\nOID = 1 3 132 0 29\nComment = SECG (Certicom) named elliptic curve\nDescription = secp128r2\n\nOID = 1 3 132 0 30\nComment = SECG (Certicom) named elliptic curve\nDescription = secp160r2\n\nOID = 1 3 132 0 31\nComment = SECG (Certicom) named elliptic curve\nDescription = secp192k1\n\nOID = 1 3 132 0 32\nComment = SECG (Certicom) named elliptic curve\nDescription = secp224k1\n\nOID = 1 3 132 0 33\nComment = SECG (Certicom) named elliptic curve\nDescription = secp224r1\n\nOID = 1 3 132 0 34\nComment = SECG (Certicom) named elliptic curve\nDescription = secp384r1\n\nOID = 1 3 132 0 35\nComment = SECG (Certicom) named elliptic curve\nDescription = secp521r1\n\nOID = 1 3 132 0 36\nComment = SECG (Certicom) named elliptic curve\nDescription = sect409k1\n\nOID = 1 3 132 0 37\nComment = SECG (Certicom) named elliptic curve\nDescription = sect409r1\n\nOID = 1 3 132 0 38\nComment = SECG (Certicom) named elliptic curve\nDescription = sect571k1\n\nOID = 1 3 132 0 39\nComment = SECG (Certicom) named elliptic curve\nDescription = sect571r1\n\nOID = 1 3 132 1 11 1\nComment = SECG (Certicom) elliptic curve key agreement\nDescription = ecdhX963KDF-SHA256\n\nOID = 1 3 132 1 11 2\nComment = SECG (Certicom) elliptic curve key agreement\nDescription = ecdhX963KDF-SHA384\n\nOID = 1 3 132 1 11 3\nComment = SECG (Certicom) elliptic curve key agreement\nDescription = ecdhX963KDF-SHA512\n\n# X9.84\n\nOID = 1 3 133 16 840 9 84\nComment = X9.84\nDescription = x984\n\nOID = 1 3 133 16 840 9 84 0\nComment = X9.84\nDescription = x984Module\n\nOID = 1 3 133 16 840 9 84 0 1\nComment = X9.84 Module\nDescription = x984Biometrics\n\nOID = 1 3 133 16 840 9 84 0 2\nComment = X9.84 Module\nDescription = x984CMS\n\nOID = 1 3 133 16 840 9 84 0 3\nComment = X9.84 Module\nDescription = x984Identifiers\n\nOID = 1 3 133 16 840 9 84 1\nComment = X9.84\nDescription = x984Biometric\n\nOID = 1 3 133 16 840 9 84 1 0\nComment = X9.84 Biometric\nDescription = biometricUnknownType\n\nOID = 1 3 133 16 840 9 84 1 1\nComment = X9.84 Biometric\nDescription = biometricBodyOdor\n\nOID = 1 3 133 16 840 9 84 1 2\nComment = X9.84 Biometric\nDescription = biometricDNA\n\nOID = 1 3 133 16 840 9 84 1 3\nComment = X9.84 Biometric\nDescription = biometricEarShape\n\nOID = 1 3 133 16 840 9 84 1 4\nComment = X9.84 Biometric\nDescription = biometricFacialFeatures\n\nOID = 1 3 133 16 840 9 84 1 5\nComment = X9.84 Biometric\nDescription = biometricFingerImage\n\nOID = 1 3 133 16 840 9 84 1 6\nComment = X9.84 Biometric\nDescription = biometricFingerGeometry\n\nOID = 1 3 133 16 840 9 84 1 7\nComment = X9.84 Biometric\nDescription = biometricHandGeometry\n\nOID = 1 3 133 16 840 9 84 1 8\nComment = X9.84 Biometric\nDescription = biometricIrisFeatures\n\nOID = 1 3 133 16 840 9 84 1 9\nComment = X9.84 Biometric\nDescription = biometricKeystrokeDynamics\n\nOID = 1 3 133 16 840 9 84 1 10\nComment = X9.84 Biometric\nDescription = biometricPalm\n\nOID = 1 3 133 16 840 9 84 1 11\nComment = X9.84 Biometric\nDescription = biometricRetina\n\nOID = 1 3 133 16 840 9 84 1 12\nComment = X9.84 Biometric\nDescription = biometricSignature\n\nOID = 1 3 133 16 840 9 84 1 13\nComment = X9.84 Biometric\nDescription = biometricSpeechPattern\n\nOID = 1 3 133 16 840 9 84 1 14\nComment = X9.84 Biometric\nDescription = biometricThermalImage\n\nOID = 1 3 133 16 840 9 84 1 15\nComment = X9.84 Biometric\nDescription = biometricVeinPattern\n\nOID = 1 3 133 16 840 9 84 1 16\nComment = X9.84 Biometric\nDescription = biometricThermalFaceImage\n\nOID = 1 3 133 16 840 9 84 1 17\nComment = X9.84 Biometric\nDescription = biometricThermalHandImage\n\nOID = 1 3 133 16 840 9 84 1 18\nComment = X9.84 Biometric\nDescription = biometricLipMovement\n\nOID = 1 3 133 16 840 9 84 1 19\nComment = X9.84 Biometric\nDescription = biometricGait\n\nOID = 1 3 133 16 840 9 84 3\nComment = X9.84\nDescription = x984MatchingMethod\n\nOID = 1 3 133 16 840 9 84 4\nComment = X9.84\nDescription = x984FormatOwner\n\nOID = 1 3 133 16 840 9 84 4 0\nComment = X9.84 Format Owner\nDescription = x984CbeffOwner\n\nOID = 1 3 133 16 840 9 84 4 1\nComment = X9.84 Format Owner\nDescription = x984IbiaOwner\n\nOID = 1 3 133 16 840 9 84 4 1 1\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerSAFLINK\n\nOID = 1 3 133 16 840 9 84 4 1 2\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerBioscrypt\n\nOID = 1 3 133 16 840 9 84 4 1 3\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerVisionics\n\nOID = 1 3 133 16 840 9 84 4 1 4\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerInfineonTechnologiesAG\n\nOID = 1 3 133 16 840 9 84 4 1 5\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerIridianTechnologies\n\nOID = 1 3 133 16 840 9 84 4 1 6\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerVeridicom\n\nOID = 1 3 133 16 840 9 84 4 1 7\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerCyberSIGN\n\nOID = 1 3 133 16 840 9 84 4 1 8\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnereCryp\n\nOID = 1 3 133 16 840 9 84 4 1 9\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerFingerprintCardsAB\n\nOID = 1 3 133 16 840 9 84 4 1 10\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerSecuGen\n\nOID = 1 3 133 16 840 9 84 4 1 11\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerPreciseBiometric\n\nOID = 1 3 133 16 840 9 84 4 1 12\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerIdentix\n\nOID = 1 3 133 16 840 9 84 4 1 13\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerDERMALOG\n\nOID = 1 3 133 16 840 9 84 4 1 14\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerLOGICO\n\nOID = 1 3 133 16 840 9 84 4 1 15\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerNIST\n\nOID = 1 3 133 16 840 9 84 4 1 16\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerA3Vision\n\nOID = 1 3 133 16 840 9 84 4 1 17\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerNEC\n\nOID = 1 3 133 16 840 9 84 4 1 18\nComment = X9.84 IBIA Format Owner\nDescription = ibiaOwnerSTMicroelectronics\n\n# X.520.  X.500v4 added encrypted versions of most of these attributes\n# at n+2 (i.e. foo = 2 4 5 1, encryptedFoo = 2 4 5 1 2), this smells\n# like a horrible kludge for something and probably isn't used, so we\n# don't define them all here.\n\nOID = 2 5 4 0\nComment = X.520 DN component\nDescription = objectClass\n\nOID = 2 5 4 1\nComment = X.520 DN component\nDescription = aliasedEntryName\n\nOID = 2 5 4 2\nComment = X.520 DN component\nDescription = knowledgeInformation\n\nOID = 2 5 4 3\nComment = X.520 DN component\nDescription = commonName\n\nOID = 2 5 4 4\nComment = X.520 DN component\nDescription = surname\n\nOID = 2 5 4 5\nComment = X.520 DN component\nDescription = serialNumber\n\nOID = 2 5 4 6\nComment = X.520 DN component\nDescription = countryName\n\nOID = 2 5 4 7\nComment = X.520 DN component\nDescription = localityName\n\nOID = 2 5 4 7 1\nComment = X.520 DN component\nDescription = collectiveLocalityName\n\nOID = 2 5 4 8\nComment = X.520 DN component\nDescription = stateOrProvinceName\n\nOID = 2 5 4 8 1\nComment = X.520 DN component\nDescription = collectiveStateOrProvinceName\n\nOID = 2 5 4 9\nComment = X.520 DN component\nDescription = streetAddress\n\nOID = 2 5 4 9 1\nComment = X.520 DN component\nDescription = collectiveStreetAddress\n\nOID = 2 5 4 10\nComment = X.520 DN component\nDescription = organizationName\n\nOID = 2 5 4 10 1\nComment = X.520 DN component\nDescription = collectiveOrganizationName\n\nOID = 2 5 4 11\nComment = X.520 DN component\nDescription = organizationalUnitName\n\nOID = 2 5 4 11 1\nComment = X.520 DN component\nDescription = collectiveOrganizationalUnitName\n\nOID = 2 5 4 12\nComment = X.520 DN component\nDescription = title\n\nOID = 2 5 4 13\nComment = X.520 DN component\nDescription = description\n\nOID = 2 5 4 14\nComment = X.520 DN component\nDescription = searchGuide\n\nOID = 2 5 4 15\nComment = X.520 DN component\nDescription = businessCategory\n\nOID = 2 5 4 16\nComment = X.520 DN component\nDescription = postalAddress\n\nOID = 2 5 4 16 1\nComment = X.520 DN component\nDescription = collectivePostalAddress\n\nOID = 2 5 4 17\nComment = X.520 DN component\nDescription = postalCode\n\nOID = 2 5 4 17 1\nComment = X.520 DN component\nDescription = collectivePostalCode\n\nOID = 2 5 4 18\nComment = X.520 DN component\nDescription = postOfficeBox\n\nOID = 2 5 4 18 1\nComment = X.520 DN component\nDescription = collectivePostOfficeBox\n\nOID = 2 5 4 19\nComment = X.520 DN component\nDescription = physicalDeliveryOfficeName\n\nOID = 2 5 4 19 1\nComment = X.520 DN component\nDescription = collectivePhysicalDeliveryOfficeName\n\nOID = 2 5 4 20\nComment = X.520 DN component\nDescription = telephoneNumber\n\nOID = 2 5 4 20 1\nComment = X.520 DN component\nDescription = collectiveTelephoneNumber\n\nOID = 2 5 4 21\nComment = X.520 DN component\nDescription = telexNumber\n\nOID = 2 5 4 21 1\nComment = X.520 DN component\nDescription = collectiveTelexNumber\n\nOID = 2 5 4 22\nComment = X.520 DN component\nDescription = teletexTerminalIdentifier\n\nOID = 2 5 4 22 1\nComment = X.520 DN component\nDescription = collectiveTeletexTerminalIdentifier\n\nOID = 2 5 4 23\nComment = X.520 DN component\nDescription = facsimileTelephoneNumber\n\nOID = 2 5 4 23 1\nComment = X.520 DN component\nDescription = collectiveFacsimileTelephoneNumber\n\nOID = 2 5 4 24\nComment = X.520 DN component\nDescription = x121Address\n\nOID = 2 5 4 25\nComment = X.520 DN component\nDescription = internationalISDNNumber\n\nOID = 2 5 4 25 1\nComment = X.520 DN component\nDescription = collectiveInternationalISDNNumber\n\nOID = 2 5 4 26\nComment = X.520 DN component\nDescription = registeredAddress\n\nOID = 2 5 4 27\nComment = X.520 DN component\nDescription = destinationIndicator\n\nOID = 2 5 4 28\nComment = X.520 DN component\nDescription = preferredDeliveryMehtod\n\nOID = 2 5 4 29\nComment = X.520 DN component\nDescription = presentationAddress\n\nOID = 2 5 4 30\nComment = X.520 DN component\nDescription = supportedApplicationContext\n\nOID = 2 5 4 31\nComment = X.520 DN component\nDescription = member\n\nOID = 2 5 4 32\nComment = X.520 DN component\nDescription = owner\n\nOID = 2 5 4 33\nComment = X.520 DN component\nDescription = roleOccupant\n\nOID = 2 5 4 34\nComment = X.520 DN component\nDescription = seeAlso\n\nOID = 2 5 4 35\nComment = X.520 DN component\nDescription = userPassword\n\nOID = 2 5 4 36\nComment = X.520 DN component\nDescription = userCertificate\n\nOID = 2 5 4 37\nComment = X.520 DN component\nDescription = caCertificate\n\nOID = 2 5 4 38\nComment = X.520 DN component\nDescription = authorityRevocationList\n\nOID = 2 5 4 39\nComment = X.520 DN component\nDescription = certificateRevocationList\n\nOID = 2 5 4 40\nComment = X.520 DN component\nDescription = crossCertificatePair\n\nOID = 2 5 4 41\nComment = X.520 DN component\nDescription = name\n\nOID = 2 5 4 42\nComment = X.520 DN component\nDescription = givenName\n\nOID = 2 5 4 43\nComment = X.520 DN component\nDescription = initials\n\nOID = 2 5 4 44\nComment = X.520 DN component\nDescription = generationQualifier\n\nOID = 2 5 4 45\nComment = X.520 DN component\nDescription = uniqueIdentifier\n\nOID = 2 5 4 46\nComment = X.520 DN component\nDescription = dnQualifier\n\nOID = 2 5 4 47\nComment = X.520 DN component\nDescription = enhancedSearchGuide\n\nOID = 2 5 4 48\nComment = X.520 DN component\nDescription = protocolInformation\n\nOID = 2 5 4 49\nComment = X.520 DN component\nDescription = distinguishedName\n\nOID = 2 5 4 50\nComment = X.520 DN component\nDescription = uniqueMember\n\nOID = 2 5 4 51\nComment = X.520 DN component\nDescription = houseIdentifier\n\nOID = 2 5 4 52\nComment = X.520 DN component\nDescription = supportedAlgorithms\n\nOID = 2 5 4 53\nComment = X.520 DN component\nDescription = deltaRevocationList\n\nOID = 2 5 4 54\nComment = X.520 DN component\nDescription = dmdName\n\nOID = 2 5 4 55\nComment = X.520 DN component\nDescription = clearance\n\nOID = 2 5 4 56\nComment = X.520 DN component\nDescription = defaultDirQop\n\nOID = 2 5 4 57\nComment = X.520 DN component\nDescription = attributeIntegrityInfo\n\nOID = 2 5 4 58\nComment = X.520 DN component\nDescription = attributeCertificate\n\nOID = 2 5 4 59\nComment = X.520 DN component\nDescription = attributeCertificateRevocationList\n\nOID = 2 5 4 60\nComment = X.520 DN component\nDescription = confKeyInfo\n\nOID = 2 5 4 61\nComment = X.520 DN component\nDescription = aACertificate\n\nOID = 2 5 4 62\nComment = X.520 DN component\nDescription = attributeDescriptorCertificate\n\nOID = 2 5 4 63\nComment = X.520 DN component\nDescription = attributeAuthorityRevocationList\n\nOID = 2 5 4 64\nComment = X.520 DN component\nDescription = familyInformation\n\nOID = 2 5 4 65\nComment = X.520 DN component\nDescription = pseudonym\n\nOID = 2 5 4 66\nComment = X.520 DN component\nDescription = communicationsService\n\nOID = 2 5 4 67\nComment = X.520 DN component\nDescription = communicationsNetwork\n\nOID = 2 5 4 68\nComment = X.520 DN component\nDescription = certificationPracticeStmt\n\nOID = 2 5 4 69\nComment = X.520 DN component\nDescription = certificatePolicy\n\nOID = 2 5 4 70\nComment = X.520 DN component\nDescription = pkiPath\n\nOID = 2 5 4 71\nComment = X.520 DN component\nDescription = privPolicy\n\nOID = 2 5 4 72\nComment = X.520 DN component\nDescription = role\n\nOID = 2 5 4 73\nComment = X.520 DN component\nDescription = delegationPath\n\nOID = 2 5 4 74\nComment = X.520 DN component\nDescription = protPrivPolicy\n\nOID = 2 5 4 75\nComment = X.520 DN component\nDescription = xMLPrivilegeInfo\n\nOID = 2 5 4 76\nComment = X.520 DN component\nDescription = xmlPrivPolicy\n\nOID = 2 5 4 82\nComment = X.520 DN component\nDescription = permission\n\n# X.500 object classes\n\nOID = 2 5 6 0\nComment = X.520 objectClass\nDescription = top\n\nOID = 2 5 6 1\nComment = X.520 objectClass\nDescription = alias\n\nOID = 2 5 6 2\nComment = X.520 objectClass\nDescription = country\n\nOID = 2 5 6 3\nComment = X.520 objectClass\nDescription = locality\n\nOID = 2 5 6 4\nComment = X.520 objectClass\nDescription = organization\n\nOID = 2 5 6 5\nComment = X.520 objectClass\nDescription = organizationalUnit\n\nOID = 2 5 6 6\nComment = X.520 objectClass\nDescription = person\n\nOID = 2 5 6 7\nComment = X.520 objectClass\nDescription = organizationalPerson\n\nOID = 2 5 6 8\nComment = X.520 objectClass\nDescription = organizationalRole\n\nOID = 2 5 6 9\nComment = X.520 objectClass\nDescription = groupOfNames\n\nOID = 2 5 6 10\nComment = X.520 objectClass\nDescription = residentialPerson\n\nOID = 2 5 6 11\nComment = X.520 objectClass\nDescription = applicationProcess\n\nOID = 2 5 6 12\nComment = X.520 objectClass\nDescription = applicationEntity\n\nOID = 2 5 6 13\nComment = X.520 objectClass\nDescription = dSA\n\nOID = 2 5 6 14\nComment = X.520 objectClass\nDescription = device\n\nOID = 2 5 6 15\nComment = X.520 objectClass\nDescription = strongAuthenticationUser\n\nOID = 2 5 6 16\nComment = X.520 objectClass\nDescription = certificateAuthority\n\nOID = 2 5 6 17\nComment = X.520 objectClass\nDescription = groupOfUniqueNames\n\nOID = 2 5 6 21\nComment = X.520 objectClass\nDescription = pkiUser\n\nOID = 2 5 6 22\nComment = X.520 objectClass\nDescription = pkiCA\n\n# X.500 algorithms\n\nOID = 2 5 8 1 1\nComment = X.500 algorithms.  Ambiguous, since no padding rules specified\nDescription = rsa\nWarning\n\n# X.509.  Some of the smaller values are from early X.509 drafts with\n# cross-pollination from X9.55 and are now deprecated.  Alternative OIDs are\n# marked if these are known.  In some cases there are multiple generations of\n# superseded OIDs\n\nOID = 2 5 29 1\nComment = X.509 extension.  Deprecated, use 2 5 29 35 instead\nDescription = authorityKeyIdentifier\nWarning\n\nOID = 2 5 29 2\nComment = X.509 extension.  Obsolete, use keyUsage/extKeyUsage instead\nDescription = keyAttributes\nWarning\n\nOID = 2 5 29 3\nComment = X.509 extension.  Deprecated, use 2 5 29 32 instead\nDescription = certificatePolicies\nWarning\n\nOID = 2 5 29 4\nComment = X.509 extension.  Obsolete, use keyUsage/extKeyUsage instead\nDescription = keyUsageRestriction\nWarning\n\nOID = 2 5 29 5\nComment = X.509 extension.  Deprecated, use 2 5 29 33 instead\nDescription = policyMapping\nWarning\n\nOID = 2 5 29 6\nComment = X.509 extension.  Obsolete, use nameConstraints instead\nDescription = subtreesConstraint\nWarning\n\nOID = 2 5 29 7\nComment = X.509 extension.  Deprecated, use 2 5 29 17 instead\nDescription = subjectAltName\nWarning\n\nOID = 2 5 29 8\nComment = X.509 extension.  Deprecated, use 2 5 29 18 instead\nDescription = issuerAltName\nWarning\n\nOID = 2 5 29 9\nComment = X.509 extension\nDescription = subjectDirectoryAttributes\n\nOID = 2 5 29 10\nComment = X.509 extension.  Deprecated, use 2 5 29 19 instead\nDescription = basicConstraints\nWarning\n\nOID = 2 5 29 11\nComment = X.509 extension.  Deprecated, use 2 5 29 30 instead\nDescription = nameConstraints\nWarning\n\nOID = 2 5 29 12\nComment = X.509 extension.  Deprecated, use 2 5 29 36 instead\nDescription = policyConstraints\nWarning\n\nOID = 2 5 29 13\nComment = X.509 extension.  Deprecated, use 2 5 29 19 instead\nDescription = basicConstraints\nWarning\n\nOID = 2 5 29 14\nComment = X.509 extension\nDescription = subjectKeyIdentifier\n\nOID = 2 5 29 15\nComment = X.509 extension\nDescription = keyUsage\n\nOID = 2 5 29 16\nComment = X.509 extension\nDescription = privateKeyUsagePeriod\n\nOID = 2 5 29 17\nComment = X.509 extension\nDescription = subjectAltName\n\nOID = 2 5 29 18\nComment = X.509 extension\nDescription = issuerAltName\n\nOID = 2 5 29 19\nComment = X.509 extension\nDescription = basicConstraints\n\nOID = 2 5 29 20\nComment = X.509 extension\nDescription = cRLNumber\n\nOID = 2 5 29 21\nComment = X.509 extension\nDescription = cRLReason\n\nOID = 2 5 29 22\nComment = X.509 extension.  Deprecated, alternative OID uncertain\nDescription = expirationDate\nWarning\n\nOID = 2 5 29 23\nComment = X.509 extension\nDescription = instructionCode\n\nOID = 2 5 29 24\nComment = X.509 extension\nDescription = invalidityDate\n\nOID = 2 5 29 25\nComment = X.509 extension.  Deprecated, use 2 5 29 31 instead\nDescription = cRLDistributionPoints\nWarning\n\nOID = 2 5 29 26\nComment = X.509 extension.  Deprecated, use 2 5 29 28 instead\nDescription = issuingDistributionPoint\nWarning\n\nOID = 2 5 29 27\nComment = X.509 extension\nDescription = deltaCRLIndicator\n\nOID = 2 5 29 28\nComment = X.509 extension\nDescription = issuingDistributionPoint\n\nOID = 2 5 29 29\nComment = X.509 extension\nDescription = certificateIssuer\n\nOID = 2 5 29 30\nComment = X.509 extension\nDescription = nameConstraints\n\nOID = 2 5 29 31\nComment = X.509 extension\nDescription = cRLDistributionPoints\n\nOID = 2 5 29 32\nComment = X.509 extension\nDescription = certificatePolicies\n\nOID = 2 5 29 32 0\nComment = X.509 certificate policy\nDescription = anyPolicy\n\nOID = 2 5 29 33\nComment = X.509 extension\nDescription = policyMappings\n\nOID = 2 5 29 34\nComment = X.509 extension.  Deprecated, use 2 5 29 36 instead\nDescription = policyConstraints\nWarning\n\nOID = 2 5 29 35\nComment = X.509 extension\nDescription = authorityKeyIdentifier\n\nOID = 2 5 29 36\nComment = X.509 extension\nDescription = policyConstraints\n\nOID = 2 5 29 37\nComment = X.509 extension\nDescription = extKeyUsage\n\nOID = 2 5 29 37 0\nComment = X.509 extended key usage\nDescription = anyExtendedKeyUsage\n\nOID = 2 5 29 38\nComment = X.509 extension\nDescription = authorityAttributeIdentifier\n\nOID = 2 5 29 39\nComment = X.509 extension\nDescription = roleSpecCertIdentifier\n\nOID = 2 5 29 40\nComment = X.509 extension\nDescription = cRLStreamIdentifier\n\nOID = 2 5 29 41\nComment = X.509 extension\nDescription = basicAttConstraints\n\nOID = 2 5 29 42\nComment = X.509 extension\nDescription = delegatedNameConstraints\n\nOID = 2 5 29 43\nComment = X.509 extension\nDescription = timeSpecification\n\nOID = 2 5 29 44\nComment = X.509 extension\nDescription = cRLScope\n\nOID = 2 5 29 45\nComment = X.509 extension\nDescription = statusReferrals\n\nOID = 2 5 29 46\nComment = X.509 extension\nDescription = freshestCRL\n\nOID = 2 5 29 47\nComment = X.509 extension\nDescription = orderedList\n\nOID = 2 5 29 48\nComment = X.509 extension\nDescription = attributeDescriptor\n\nOID = 2 5 29 49\nComment = X.509 extension\nDescription = userNotice\n\nOID = 2 5 29 50\nComment = X.509 extension\nDescription = sOAIdentifier\n\nOID = 2 5 29 51\nComment = X.509 extension\nDescription = baseUpdateTime\n\nOID = 2 5 29 52\nComment = X.509 extension\nDescription = acceptableCertPolicies\n\nOID = 2 5 29 53\nComment = X.509 extension\nDescription = deltaInfo\n\nOID = 2 5 29 54\nComment = X.509 extension\nDescription = inhibitAnyPolicy\n\nOID = 2 5 29 55\nComment = X.509 extension\nDescription = targetInformation\n\nOID = 2 5 29 56\nComment = X.509 extension\nDescription = noRevAvail\n\nOID = 2 5 29 57\nComment = X.509 extension\nDescription = acceptablePrivilegePolicies\n\nOID = 2 5 29 58\nComment = X.509 extension\nDescription = toBeRevoked\n\nOID = 2 5 29 59\nComment = X.509 extension\nDescription = revokedGroups\n\nOID = 2 5 29 60\nComment = X.509 extension\nDescription = expiredCertsOnCRL\n\nOID = 2 5 29 61\nComment = X.509 extension\nDescription = indirectIssuer\n\nOID = 2 5 29 62\nComment = X.509 extension\nDescription = noAssertion\n\nOID = 2 5 29 63\nComment = X.509 extension\nDescription = aAissuingDistributionPoint\n\nOID = 2 5 29 64\nComment = X.509 extension\nDescription = issuedOnBehalfOf\n\nOID = 2 5 29 65\nComment = X.509 extension\nDescription = singleUse\n\nOID = 2 5 29 66\nComment = X.509 extension\nDescription = groupAC\n\nOID = 2 5 29 67\nComment = X.509 extension\nDescription = allowedAttAss\n\nOID = 2 5 29 68\nComment = X.509 extension\nDescription = attributeMappings\n\nOID = 2 5 29 69\nComment = X.509 extension\nDescription = holderNameConstraints\n\n# Spanish Government?\n\nOID = 2 16 724 1 2 2 4 1\nComment = Spanish Government PKI?\nDescription = personalDataInfo\n\n# DMS\n\nOID = 2 16 840 1 101 2 1 1 1\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsSignatureAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 2\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicSignatureAlgorithm, this OID is better known as dsaWithSHA-1.\nDescription = fortezzaSignatureAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 3\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsConfidentialityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 4\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicConfidentialityAlgorithm\nDescription = fortezzaConfidentialityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 5\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsIntegrityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 6\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicIntegrityAlgorithm\nDescription = fortezzaIntegrityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 7\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsTokenProtectionAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 8\nComment = SDN.700 INFOSEC algorithms.  Formerly know as mosaicTokenProtectionAlgorithm\nDescription = fortezzaTokenProtectionAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 9\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsKeyManagementAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 10\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicKeyManagementAlgorithm\nDescription = fortezzaKeyManagementAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 11\nComment = SDN.700 INFOSEC algorithms\nDescription = sdnsKMandSigAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 12\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicKMandSigAlgorithm\nDescription = fortezzaKMandSigAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 13\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteASignatureAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 14\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteAConfidentialityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 15\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteAIntegrityAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 16\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteATokenProtectionAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 17\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteAKeyManagementAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 18\nComment = SDN.700 INFOSEC algorithms\nDescription = suiteAKMandSigAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 19\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicUpdatedSigAlgorithm\nDescription = fortezzaUpdatedSigAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 20\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicKMandUpdSigAlgorithms\nDescription = fortezzaKMandUpdSigAlgorithms\n\nOID = 2 16 840 1 101 2 1 1 21\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicUpdatedIntegAlgorithm\nDescription = fortezzaUpdatedIntegAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 22\nComment = SDN.700 INFOSEC algorithms.  Formerly known as mosaicKeyEncryptionAlgorithm\nDescription = keyExchangeAlgorithm\n\nOID = 2 16 840 1 101 2 1 1 23\nComment = SDN.700 INFOSEC algorithms\nDescription = fortezzaWrap80Algorithm\n\nOID = 2 16 840 1 101 2 1 1 24\nComment = SDN.700 INFOSEC algorithms\nDescription = kEAKeyEncryptionAlgorithm\n\nOID = 2 16 840 1 101 2 1 2 1\nComment = SDN.700 INFOSEC format\nDescription = rfc822MessageFormat\n\nOID = 2 16 840 1 101 2 1 2 2\nComment = SDN.700 INFOSEC format\nDescription = emptyContent\n\nOID = 2 16 840 1 101 2 1 2 3\nComment = SDN.700 INFOSEC format\nDescription = cspContentType\n\nOID = 2 16 840 1 101 2 1 2 42\nComment = SDN.700 INFOSEC format\nDescription = mspRev3ContentType\n\nOID = 2 16 840 1 101 2 1 2 48\nComment = SDN.700 INFOSEC format\nDescription = mspContentType\n\nOID = 2 16 840 1 101 2 1 2 49\nComment = SDN.700 INFOSEC format\nDescription = mspRekeyAgentProtocol\n\nOID = 2 16 840 1 101 2 1 2 50\nComment = SDN.700 INFOSEC format\nDescription = mspMMP\n\nOID = 2 16 840 1 101 2 1 2 66\nComment = SDN.700 INFOSEC format\nDescription = mspRev3-1ContentType\n\nOID = 2 16 840 1 101 2 1 2 72\nComment = SDN.700 INFOSEC format\nDescription = forwardedMSPMessageBodyPart\n\nOID = 2 16 840 1 101 2 1 2 73\nComment = SDN.700 INFOSEC format\nDescription = mspForwardedMessageParameters\n\nOID = 2 16 840 1 101 2 1 2 74\nComment = SDN.700 INFOSEC format\nDescription = forwardedCSPMsgBodyPart\n\nOID = 2 16 840 1 101 2 1 2 75\nComment = SDN.700 INFOSEC format\nDescription = cspForwardedMessageParameters\n\nOID = 2 16 840 1 101 2 1 2 76\nComment = SDN.700 INFOSEC format\nDescription = mspMMP2\n\nOID = 2 16 840 1 101 2 1 3 1\nComment = SDN.700 INFOSEC policy\nDescription = sdnsSecurityPolicy\n\nOID = 2 16 840 1 101 2 1 3 2\nComment = SDN.700 INFOSEC policy\nDescription = sdnsPRBAC\n\nOID = 2 16 840 1 101 2 1 3 3\nComment = SDN.700 INFOSEC policy\nDescription = mosaicPRBAC\n\nOID = 2 16 840 1 101 2 1 3 10\nComment = SDN.700 INFOSEC policy\nDescription = siSecurityPolicy\n\nOID = 2 16 840 1 101 2 1 3 10 0\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siNASP\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 1\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siELCO\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 2\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siTK\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 3\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siDSAP\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 4\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siSSSS\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 5\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siDNASP\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 6\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siBYEMAN\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 7\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siREL-US\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 8\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siREL-AUS\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 9\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siREL-CAN\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 10\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siREL_UK\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 11\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siREL-NZ\nWarning\n\nOID = 2 16 840 1 101 2 1 3 10 12\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = siGeneric\nWarning\n\nOID = 2 16 840 1 101 2 1 3 11\nComment = SDN.700 INFOSEC policy\nDescription = genser\n\nOID = 2 16 840 1 101 2 1 3 11 0\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = genserNations\nWarning\n\nOID = 2 16 840 1 101 2 1 3 11 1\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = genserComsec\nWarning\n\nOID = 2 16 840 1 101 2 1 3 11 2\nComment = SDN.700 INFOSEC policy (obsolete)\nDescription = genserAcquisition\nWarning\n\nOID = 2 16 840 1 101 2 1 3 11 3\nComment = SDN.700 INFOSEC policy\nDescription = genserSecurityCategories\n\nOID = 2 16 840 1 101 2 1 3 11 3 0\nComment = SDN.700 INFOSEC GENSER policy\nDescription = genserTagSetName\n\nOID = 2 16 840 1 101 2 1 3 12\nComment = SDN.700 INFOSEC policy\nDescription = defaultSecurityPolicy\n\nOID = 2 16 840 1 101 2 1 3 13\nComment = SDN.700 INFOSEC policy\nDescription = capcoMarkings\n\nOID = 2 16 840 1 101 2 1 3 13 0\nComment = SDN.700 INFOSEC policy CAPCO markings\nDescription = capcoSecurityCategories\n\nOID = 2 16 840 1 101 2 1 3 13 0 1\nComment = SDN.700 INFOSEC policy CAPCO markings\nDescription = capcoTagSetName1\n\nOID = 2 16 840 1 101 2 1 3 13 0 2\nComment = SDN.700 INFOSEC policy CAPCO markings\nDescription = capcoTagSetName2\n\nOID = 2 16 840 1 101 2 1 3 13 0 3\nComment = SDN.700 INFOSEC policy CAPCO markings\nDescription = capcoTagSetName3\n\nOID = 2 16 840 1 101 2 1 3 13 0 4\nComment = SDN.700 INFOSEC policy CAPCO markings\nDescription = capcoTagSetName4\n\nOID = 2 16 840 1 101 2 1 5 1\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = sdnsKeyManagementCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 2\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = sdnsUserSignatureCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 3\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = sdnsKMandSigCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 4\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = fortezzaKeyManagementCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 5\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = fortezzaKMandSigCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 6\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = fortezzaUserSignatureCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 7\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = fortezzaCASignatureCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 8\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = sdnsCASignatureCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 10\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = auxiliaryVector\nWarning\n\nOID = 2 16 840 1 101 2 1 5 11\nComment = SDN.700 INFOSEC attributes\nDescription = mlReceiptPolicy\n\nOID = 2 16 840 1 101 2 1 5 12\nComment = SDN.700 INFOSEC attributes\nDescription = mlMembership\n\nOID = 2 16 840 1 101 2 1 5 13\nComment = SDN.700 INFOSEC attributes\nDescription = mlAdministrators\n\nOID = 2 16 840 1 101 2 1 5 14\nComment = SDN.700 INFOSEC attributes\nDescription = alid\n\nOID = 2 16 840 1 101 2 1 5 20\nComment = SDN.700 INFOSEC attributes\nDescription = janUKMs\n\nOID = 2 16 840 1 101 2 1 5 21\nComment = SDN.700 INFOSEC attributes\nDescription = febUKMs\n\nOID = 2 16 840 1 101 2 1 5 22\nComment = SDN.700 INFOSEC attributes\nDescription = marUKMs\n\nOID = 2 16 840 1 101 2 1 5 23\nComment = SDN.700 INFOSEC attributes\nDescription = aprUKMs\n\nOID = 2 16 840 1 101 2 1 5 24\nComment = SDN.700 INFOSEC attributes\nDescription = mayUKMs\n\nOID = 2 16 840 1 101 2 1 5 25\nComment = SDN.700 INFOSEC attributes\nDescription = junUKMs\n\nOID = 2 16 840 1 101 2 1 5 26\nComment = SDN.700 INFOSEC attributes\nDescription = julUKMs\n\nOID = 2 16 840 1 101 2 1 5 27\nComment = SDN.700 INFOSEC attributes\nDescription = augUKMs\n\nOID = 2 16 840 1 101 2 1 5 28\nComment = SDN.700 INFOSEC attributes\nDescription = sepUKMs\n\nOID = 2 16 840 1 101 2 1 5 29\nComment = SDN.700 INFOSEC attributes\nDescription = octUKMs\n\nOID = 2 16 840 1 101 2 1 5 30\nComment = SDN.700 INFOSEC attributes\nDescription = novUKMs\n\nOID = 2 16 840 1 101 2 1 5 31\nComment = SDN.700 INFOSEC attributes\nDescription = decUKMs\n\nOID = 2 16 840 1 101 2 1 5 40\nComment = SDN.700 INFOSEC attributes\nDescription = metaSDNSckl\n\nOID = 2 16 840 1 101 2 1 5 41\nComment = SDN.700 INFOSEC attributes\nDescription = sdnsCKL\n\nOID = 2 16 840 1 101 2 1 5 42\nComment = SDN.700 INFOSEC attributes\nDescription = metaSDNSsignatureCKL\n\nOID = 2 16 840 1 101 2 1 5 43\nComment = SDN.700 INFOSEC attributes\nDescription = sdnsSignatureCKL\n\nOID = 2 16 840 1 101 2 1 5 44\nComment = SDN.700 INFOSEC attributes\nDescription = sdnsCertificateRevocationList\n\nOID = 2 16 840 1 101 2 1 5 45\nComment = SDN.700 INFOSEC attributes (superseded)\nDescription = fortezzaCertificateRevocationList\nWarning\n\nOID = 2 16 840 1 101 2 1 5 46\nComment = SDN.700 INFOSEC attributes\nDescription = fortezzaCKL\n\nOID = 2 16 840 1 101 2 1 5 47\nComment = SDN.700 INFOSEC attributes\nDescription = alExemptedAddressProcessor\n\nOID = 2 16 840 1 101 2 1 5 48\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = guard\nWarning\n\nOID = 2 16 840 1 101 2 1 5 49\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = algorithmsSupported\nWarning\n\nOID = 2 16 840 1 101 2 1 5 50\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = suiteAKeyManagementCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 51\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = suiteAKMandSigCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 52\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = suiteAUserSignatureCertificate\nWarning\n\nOID = 2 16 840 1 101 2 1 5 53\nComment = SDN.700 INFOSEC attributes\nDescription = prbacInfo\n\nOID = 2 16 840 1 101 2 1 5 54\nComment = SDN.700 INFOSEC attributes\nDescription = prbacCAConstraints\n\nOID = 2 16 840 1 101 2 1 5 55\nComment = SDN.700 INFOSEC attributes\nDescription = sigOrKMPrivileges\n\nOID = 2 16 840 1 101 2 1 5 56\nComment = SDN.700 INFOSEC attributes\nDescription = commPrivileges\n\nOID = 2 16 840 1 101 2 1 5 57\nComment = SDN.700 INFOSEC attributes\nDescription = labeledAttribute\n\nOID = 2 16 840 1 101 2 1 5 58\nComment = SDN.700 INFOSEC attributes (obsolete)\nDescription = policyInformationFile\nWarning\n\nOID = 2 16 840 1 101 2 1 5 59\nComment = SDN.700 INFOSEC attributes\nDescription = secPolicyInformationFile\n\nOID = 2 16 840 1 101 2 1 5 60\nComment = SDN.700 INFOSEC attributes\nDescription = cAClearanceConstraint\n\nOID = 2 16 840 1 101 2 1 7 1\nComment = SDN.700 INFOSEC extensions\nDescription = cspExtns\n\nOID = 2 16 840 1 101 2 1 7 1 0\nComment = SDN.700 INFOSEC extensions\nDescription = cspCsExtn\n\nOID = 2 16 840 1 101 2 1 8 1\nComment = SDN.700 INFOSEC security category\nDescription = mISSISecurityCategories\n\nOID = 2 16 840 1 101 2 1 8 2\nComment = SDN.700 INFOSEC security category\nDescription = standardSecurityLabelPrivileges\n\nOID = 2 16 840 1 101 2 1 10 1\nComment = SDN.700 INFOSEC privileges\nDescription = sigPrivileges\n\nOID = 2 16 840 1 101 2 1 10 2\nComment = SDN.700 INFOSEC privileges\nDescription = kmPrivileges\n\nOID = 2 16 840 1 101 2 1 10 3\nComment = SDN.700 INFOSEC privileges\nDescription = namedTagSetPrivilege\n\nOID = 2 16 840 1 101 2 1 11 1\nComment = SDN.700 INFOSEC certificate policy\nDescription = ukDemo\n\nOID = 2 16 840 1 101 2 1 11 2\nComment = SDN.700 INFOSEC certificate policy\nDescription = usDODClass2\n\nOID = 2 16 840 1 101 2 1 11 3\nComment = SDN.700 INFOSEC certificate policy\nDescription = usMediumPilot\n\nOID = 2 16 840 1 101 2 1 11 4\nComment = SDN.700 INFOSEC certificate policy\nDescription = usDODClass4\n\nOID = 2 16 840 1 101 2 1 11 5\nComment = SDN.700 INFOSEC certificate policy\nDescription = usDODClass3\n\nOID = 2 16 840 1 101 2 1 11 6\nComment = SDN.700 INFOSEC certificate policy\nDescription = usDODClass5\n\nOID = 2 16 840 1 101 2 1 12 0\nComment = SDN.700 INFOSEC test objects\nDescription = testSecurityPolicy\n\nOID = 2 16 840 1 101 2 1 12 0 1\nComment = SDN.700 INFOSEC test objects\nDescription = tsp1\n\nOID = 2 16 840 1 101 2 1 12 0 1 0\nComment = SDN.700 INFOSEC test objects\nDescription = tsp1SecurityCategories\n\nOID = 2 16 840 1 101 2 1 12 0 1 0 0\nComment = SDN.700 INFOSEC test objects\nDescription = tsp1TagSetZero\n\nOID = 2 16 840 1 101 2 1 12 0 1 0 1\nComment = SDN.700 INFOSEC test objects\nDescription = tsp1TagSetOne\n\nOID = 2 16 840 1 101 2 1 12 0 1 0 2\nComment = SDN.700 INFOSEC test objects\nDescription = tsp1TagSetTwo\n\nOID = 2 16 840 1 101 2 1 12 0 2\nComment = SDN.700 INFOSEC test objects\nDescription = tsp2\n\nOID = 2 16 840 1 101 2 1 12 0 2 0\nComment = SDN.700 INFOSEC test objects\nDescription = tsp2SecurityCategories\n\nOID = 2 16 840 1 101 2 1 12 0 2 0 0\nComment = SDN.700 INFOSEC test objects\nDescription = tsp2TagSetZero\n\nOID = 2 16 840 1 101 2 1 12 0 2 0 1\nComment = SDN.700 INFOSEC test objects\nDescription = tsp2TagSetOne\n\nOID = 2 16 840 1 101 2 1 12 0 2 0 2\nComment = SDN.700 INFOSEC test objects\nDescription = tsp2TagSetTwo\n\n# At least someone there has a sense of humour :-)\nOID = 2 16 840 1 101 2 1 12 0 3\nComment = SDN.700 INFOSEC test objects\nDescription = kafka\n\nOID = 2 16 840 1 101 2 1 12 0 3 0\nComment = SDN.700 INFOSEC test objects\nDescription = kafkaSecurityCategories\n\nOID = 2 16 840 1 101 2 1 12 0 3 0 1\nComment = SDN.700 INFOSEC test objects\nDescription = kafkaTagSetName1\n\nOID = 2 16 840 1 101 2 1 12 0 3 0 2\nComment = SDN.700 INFOSEC test objects\nDescription = kafkaTagSetName2\n\nOID = 2 16 840 1 101 2 1 12 0 3 0 3\nComment = SDN.700 INFOSEC test objects\nDescription = kafkaTagSetName3\n\nOID = 2 16 840 1 101 2 1 12 1 1\nComment = SDN.700 INFOSEC test objects\nDescription = tcp1\n\n# NIST (?)\n\nOID = 2 16 840 1 101 3 1\nComment = CSOR GAK\nDescription = slabel\nWarning\n\nOID = 2 16 840 1 101 3 2\nComment = NIST\nDescription = pki\nWarning\n\nOID = 2 16 840 1 101 3 2 1\nComment = NIST policies\nDescription = NIST policyIdentifier\nWarning\n\nOID = 2 16 840 1 101 3 2 1 3 1\nComment = Federal Bridge CA Policy\nDescription = fbcaRudimentaryPolicy\n\nOID = 2 16 840 1 101 3 2 1 3 2\nComment = Federal Bridge CA Policy\nDescription = fbcaBasicPolicy\n\nOID = 2 16 840 1 101 3 2 1 3 3\nComment = Federal Bridge CA Policy\nDescription = fbcaMediumPolicy\n\nOID = 2 16 840 1 101 3 2 1 3 4\nComment = Federal Bridge CA Policy\nDescription = fbcaHighPolicy\n\nOID = 2 16 840 1 101 3 2 1 48 1\nComment = NIST PKITS policies\nDescription = nistTestPolicy1\n\nOID = 2 16 840 1 101 3 2 1 48 2\nComment = NIST PKITS policies\nDescription = nistTestPolicy2\n\nOID = 2 16 840 1 101 3 2 1 48 3\nComment = NIST PKITS policies\nDescription = nistTestPolicy3\n\nOID = 2 16 840 1 101 3 2 1 48 4\nComment = NIST PKITS policies\nDescription = nistTestPolicy4\n\nOID = 2 16 840 1 101 3 2 1 48 5\nComment = NIST PKITS policies\nDescription = nistTestPolicy5\n\nOID = 2 16 840 1 101 3 2 1 48 6\nComment = NIST PKITS policies\nDescription = nistTestPolicy6\n\nOID = 2 16 840 1 101 3 2 2\nComment = CSOR GAK extended key usage\nDescription = gak\nWarning\n\nOID = 2 16 840 1 101 3 2 2 1\nComment = CSOR GAK extended key usage\nDescription = kRAKey\nWarning\n\nOID = 2 16 840 1 101 3 2 3\nComment = CSOR GAK extensions\nDescription = extensions\nWarning\n\nOID = 2 16 840 1 101 3 2 3 1\nComment = CSOR GAK extensions\nDescription = kRTechnique\nWarning\n\nOID = 2 16 840 1 101 3 2 3 2\nComment = CSOR GAK extensions\nDescription = kRecoveryCapable\nWarning\n\nOID = 2 16 840 1 101 3 2 3 3\nComment = CSOR GAK extensions\nDescription = kR\nWarning\n\nOID = 2 16 840 1 101 3 2 4\nComment = CSOR GAK\nDescription = keyRecoverySchemes\nWarning\n\nOID = 2 16 840 1 101 3 2 5\nComment = CSOR GAK\nDescription = krapola\nWarning\n\nOID = 2 16 840 1 101 3 3\nComment = CSOR GAK\nDescription = arpa\nWarning\n\n# CSOR (NIST) Algorithms\n\nOID = 2 16 840 1 101 3 4\nComment = NIST Algorithm\nDescription = nistAlgorithm\n\nOID = 2 16 840 1 101 3 4 1\nComment = NIST Algorithm\nDescription = aes\n\nOID = 2 16 840 1 101 3 4 1 1\nComment = NIST Algorithm\nDescription = aes128-ECB\n\nOID = 2 16 840 1 101 3 4 1 2\nComment = NIST Algorithm\nDescription = aes128-CBC\n\nOID = 2 16 840 1 101 3 4 1 3\nComment = NIST Algorithm\nDescription = aes128-OFB\n\nOID = 2 16 840 1 101 3 4 1 4\nComment = NIST Algorithm\nDescription = aes128-CFB\n\nOID = 2 16 840 1 101 3 4 1 5\nComment = NIST Algorithm\nDescription = aes128-wrap\n\nOID = 2 16 840 1 101 3 4 1 6\nComment = NIST Algorithm\nDescription = aes128-GCM\n\nOID = 2 16 840 1 101 3 4 1 7\nComment = NIST Algorithm\nDescription = aes128-CCM\n\nOID = 2 16 840 1 101 3 4 1 8\nComment = NIST Algorithm\nDescription = aes128-wrap-pad\n\nOID = 2 16 840 1 101 3 4 1 21\nComment = NIST Algorithm\nDescription = aes192-ECB\n\nOID = 2 16 840 1 101 3 4 1 22\nComment = NIST Algorithm\nDescription = aes192-CBC\n\nOID = 2 16 840 1 101 3 4 1 23\nComment = NIST Algorithm\nDescription = aes192-OFB\n\nOID = 2 16 840 1 101 3 4 1 24\nComment = NIST Algorithm\nDescription = aes192-CFB\n\nOID = 2 16 840 1 101 3 4 1 25\nComment = NIST Algorithm\nDescription = aes192-wrap\n\nOID = 2 16 840 1 101 3 4 1 26\nComment = NIST Algorithm\nDescription = aes192-GCM\n\nOID = 2 16 840 1 101 3 4 1 27\nComment = NIST Algorithm\nDescription = aes192-CCM\n\nOID = 2 16 840 1 101 3 4 1 28\nComment = NIST Algorithm\nDescription = aes192-wrap-pad\n\nOID = 2 16 840 1 101 3 4 1 41\nComment = NIST Algorithm\nDescription = aes256-ECB\n\nOID = 2 16 840 1 101 3 4 1 42\nComment = NIST Algorithm\nDescription = aes256-CBC\n\nOID = 2 16 840 1 101 3 4 1 43\nComment = NIST Algorithm\nDescription = aes256-OFB\n\nOID = 2 16 840 1 101 3 4 1 44\nComment = NIST Algorithm\nDescription = aes256-CFB\n\nOID = 2 16 840 1 101 3 4 1 45\nComment = NIST Algorithm\nDescription = aes256-wrap\n\nOID = 2 16 840 1 101 3 4 1 46\nComment = NIST Algorithm\nDescription = aes256-GCM\n\nOID = 2 16 840 1 101 3 4 1 47\nComment = NIST Algorithm\nDescription = aes256-CCM\n\nOID = 2 16 840 1 101 3 4 1 48\nComment = NIST Algorithm\nDescription = aes256-wrap-pad\n\nOID = 2 16 840 1 101 3 4 2\nComment = NIST Algorithm\nDescription = hashAlgos\n\nOID = 2 16 840 1 101 3 4 2 1\nComment = NIST Algorithm\nDescription = sha-256\n\nOID = 2 16 840 1 101 3 4 2 2\nComment = NIST Algorithm\nDescription = sha-384\n\nOID = 2 16 840 1 101 3 4 2 3\nComment = NIST Algorithm\nDescription = sha-512\n\nOID = 2 16 840 1 101 3 4 2 4\nComment = NIST Algorithm\nDescription = sha-224\n\n# The spec for these is incorrect, listing both as ... 1.  Presumably one\n# of them is meant to be ...2.\nOID = 2 16 840 1 101 3 4 3 1\nComment = NIST Algorithm\nDescription = dsaWithSha224\n\nOID = 2 16 840 1 101 3 4 3 2\nComment = NIST Algorithm\nDescription = dsaWithSha256\n\n# Novell\n\nOID = 2 16 840 1 113719 1 2 8\nComment = Novell\nDescription = novellAlgorithm\n\nOID = 2 16 840 1 113719 1 2 8 22\nComment = Novell encryption algorithm\nDescription = desCbcIV8\n\nOID = 2 16 840 1 113719 1 2 8 23\nComment = Novell encryption algorithm\nDescription = desCbcPadIV8\n\nOID = 2 16 840 1 113719 1 2 8 24\nComment = Novell encryption algorithm\nDescription = desEDE2CbcIV8\n\nOID = 2 16 840 1 113719 1 2 8 25\nComment = Novell encryption algorithm\nDescription = desEDE2CbcPadIV8\n\nOID = 2 16 840 1 113719 1 2 8 26\nComment = Novell encryption algorithm\nDescription = desEDE3CbcIV8\n\nOID = 2 16 840 1 113719 1 2 8 27\nComment = Novell encryption algorithm\nDescription = desEDE3CbcPadIV8\n\nOID = 2 16 840 1 113719 1 2 8 28\nComment = Novell encryption algorithm\nDescription = rc5CbcPad\n\nOID = 2 16 840 1 113719 1 2 8 29\nComment = Novell signature algorithm\nDescription = md2WithRSAEncryptionBSafe1\n\nOID = 2 16 840 1 113719 1 2 8 30\nComment = Novell signature algorithm\nDescription = md5WithRSAEncryptionBSafe1\n\nOID = 2 16 840 1 113719 1 2 8 31\nComment = Novell signature algorithm\nDescription = sha1WithRSAEncryptionBSafe1\n\nOID = 2 16 840 1 113719 1 2 8 32\nComment = Novell digest algorithm\nDescription = lmDigest\n\nOID = 2 16 840 1 113719 1 2 8 40\nComment = Novell digest algorithm\nDescription = md2\n\nOID = 2 16 840 1 113719 1 2 8 50\nComment = Novell digest algorithm\nDescription = md5\n\nOID = 2 16 840 1 113719 1 2 8 51\nComment = Novell signature algorithm\nDescription = ikeHmacWithSHA1-RSA\n\nOID = 2 16 840 1 113719 1 2 8 52\nComment = Novell signature algorithm\nDescription = ikeHmacWithMD5-RSA\n\nOID = 2 16 840 1 113719 1 2 8 69\nComment = Novell encryption algorithm\nDescription = rc2CbcPad\n\nOID = 2 16 840 1 113719 1 2 8 82\nComment = Novell digest algorithm\nDescription = sha-1\n\nOID = 2 16 840 1 113719 1 2 8 92\nComment = Novell encryption algorithm\nDescription = rc2BSafe1Cbc\n\nOID = 2 16 840 1 113719 1 2 8 95\nComment = Novell digest algorithm\nDescription = md4\n\nOID = 2 16 840 1 113719 1 2 8 130\nComment = Novell keyed hash\nDescription = md4Packet\n\nOID = 2 16 840 1 113719 1 2 8 131\nComment = Novell encryption algorithm\nDescription = rsaEncryptionBsafe1\n\nOID = 2 16 840 1 113719 1 2 8 132\nComment = Novell encryption algorithm\nDescription = nwPassword\n\nOID = 2 16 840 1 113719 1 2 8 133\nComment = Novell encryption algorithm\nDescription = novellObfuscate-1\n\nOID = 2 16 840 1 113719 1 9\nComment = Novell\nDescription = pki\n\nOID = 2 16 840 1 113719 1 9 4\nComment = Novell PKI\nDescription = pkiAttributeType\n\nOID = 2 16 840 1 113719 1 9 4 1\nComment = Novell PKI attribute type\nDescription = securityAttributes\n\nOID = 2 16 840 1 113719 1 9 4 2\nComment = Novell PKI attribute type\nDescription = relianceLimit\n\n# Netscape\n\nOID = 2 16 840 1 113730 1\nComment = Netscape\nDescription = cert-extension\n\nOID = 2 16 840 1 113730 1 1\nComment = Netscape certificate extension\nDescription = netscape-cert-type\n\nOID = 2 16 840 1 113730 1 2\nComment = Netscape certificate extension\nDescription = netscape-base-url\n\nOID = 2 16 840 1 113730 1 3\nComment = Netscape certificate extension\nDescription = netscape-revocation-url\n\nOID = 2 16 840 1 113730 1 4\nComment = Netscape certificate extension\nDescription = netscape-ca-revocation-url\n\nOID = 2 16 840 1 113730 1 7\nComment = Netscape certificate extension\nDescription = netscape-cert-renewal-url\n\nOID = 2 16 840 1 113730 1 8\nComment = Netscape certificate extension\nDescription = netscape-ca-policy-url\n\nOID = 2 16 840 1 113730 1 9\nComment = Netscape certificate extension\nDescription = HomePage-url\n\nOID = 2 16 840 1 113730 1 10\nComment = Netscape certificate extension\nDescription = EntityLogo\n\nOID = 2 16 840 1 113730 1 11\nComment = Netscape certificate extension\nDescription = UserPicture\n\nOID = 2 16 840 1 113730 1 12\nComment = Netscape certificate extension\nDescription = netscape-ssl-server-name\n\nOID = 2 16 840 1 113730 1 13\nComment = Netscape certificate extension\nDescription = netscape-comment\n\nOID = 2 16 840 1 113730 2\nComment = Netscape\nDescription = data-type\n\nOID = 2 16 840 1 113730 2 1\nComment = Netscape data type\nDescription = dataGIF\n\nOID = 2 16 840 1 113730 2 2\nComment = Netscape data type\nDescription = dataJPEG\n\nOID = 2 16 840 1 113730 2 3\nComment = Netscape data type\nDescription = dataURL\n\nOID = 2 16 840 1 113730 2 4\nComment = Netscape data type\nDescription = dataHTML\n\nOID = 2 16 840 1 113730 2 5\nComment = Netscape data type\nDescription = certSequence\n\nOID = 2 16 840 1 113730 2 6\nComment = Netscape certificate extension\nDescription = certURL\n\nOID = 2 16 840 1 113730 3\nComment = Netscape\nDescription = directory\n\nOID = 2 16 840 1 113730 3 1\nComment = Netscape directory\nDescription = ldapDefinitions\n\nOID = 2 16 840 1 113730 3 1 1\nComment = Netscape LDAP definitions\nDescription = carLicense\n\nOID = 2 16 840 1 113730 3 1 2\nComment = Netscape LDAP definitions\nDescription = departmentNumber\n\nOID = 2 16 840 1 113730 3 1 3\nComment = Netscape LDAP definitions\nDescription = employeeNumber\n\nOID = 2 16 840 1 113730 3 1 4\nComment = Netscape LDAP definitions\nDescription = employeeType\n\nOID = 2 16 840 1 113730 3 2 2\nComment = Netscape LDAP definitions\nDescription = inetOrgPerson\n\nOID = 2 16 840 1 113730 4 1\nComment = Netscape\nDescription = serverGatedCrypto\n\n# Verisign\n\n# Country, zip, date of birth (age), and gender of cert owner (CZAG) in\n# obfuscated form\nOID = 2 16 840 1 113733 1 6 3\nComment = Verisign extension\nDescription = verisignCZAG\n\n# Text string used in certs issued to Netscape InBox customers\nOID = 2 16 840 1 113733 1 6 6\nComment = Verisign extension\nDescription = verisignInBox\n\nOID = 2 16 840 1 113733 1 6 11\nComment = Verisign extension\nDescription = verisignOnsiteJurisdictionHash\n\nOID = 2 16 840 1 113733 1 6 13\nComment = Verisign extension\nDescription = Unknown Verisign VPN extension\n\n# Contains DUN, among other things\nOID = 2 16 840 1 113733 1 6 15\nComment = Verisign extension\nDescription = verisignServerID\n\nOID = 2 16 840 1 113733 1 7 1 1\nComment = Verisign policy\nDescription = verisignCertPolicies95Qualifier1\n\nOID = 2 16 840 1 113733 1 7 1 1 1\nComment = Verisign policy (obsolete)\nDescription = verisignCPSv1notice\n\n# DN contains non-verified subscriber information\nOID = 2 16 840 1 113733 1 7 1 1 2\nComment = Verisign policy (obsolete)\nDescription = verisignCPSv1nsi\n\nOID = 2 16 840 1 113733 1 8 1\nComment = Verisign\nDescription = verisignISSStrongCrypto\n\n# SCEP\n\nOID = 2 16 840 1 113733 1\nComment = Verisign extension\nDescription = pki\n\nOID = 2 16 840 1 113733 1 9\nComment = Verisign PKI extension\nDescription = pkcs7Attribute\n\nOID = 2 16 840 1 113733 1 9 2\nComment = Verisign PKCS #7 attribute\nDescription = messageType\n\nOID = 2 16 840 1 113733 1 9 3\nComment = Verisign PKCS #7 attribute\nDescription = pkiStatus\n\nOID = 2 16 840 1 113733 1 9 4\nComment = Verisign PKCS #7 attribute\nDescription = failInfo\n\nOID = 2 16 840 1 113733 1 9 5\nComment = Verisign PKCS #7 attribute\nDescription = senderNonce\n\nOID = 2 16 840 1 113733 1 9 6\nComment = Verisign PKCS #7 attribute\nDescription = recipientNonce\n\nOID = 2 16 840 1 113733 1 9 7\nComment = Verisign PKCS #7 attribute\nDescription = transID\n\n# Supposedly the attribute for X.509v3 extensions in PKCS #10 requests,\n# but everyone seems to use the RSA OID instead\nOID = 2 16 840 1 113733 1 9 8\nComment = Verisign PKCS #7 attribute.  Use PKCS #9 extensionRequest instead\nDescription = extensionReq\nWarning\n\n# Intel.  Intel's BIOS-signing certificates contain the following OID\n# values:\n#\n# 2 16 840 1 113741 2 1 3 1\n# 2 16 840 1 113741 3 1 1 1 1 2 1\n# 2 16 840 1 113741 3 1 1 1 2 1 1\n# 2 16 840 1 113741 3 1 1 2 2 1 1\n# 2 16 840 1 113741 3 1 1 2 1 1 1 1\n#\n# None of these are documented anywhere, in fact the entire '3' arc isn't\n# documented.\n\nOID = 2 16 840 1 113741 2\nComment = Intel CDSA\nDescription = intelCDSA\n\n# DigiCert\n\nOID = 2 16 840 1 114412 1\nComment = Digicert CA policy\nDescription = digiCertNonEVCerts\n\nOID = 2 16 840 1 114412 1 1\nComment = Digicert CA policy\nDescription = digiCertOVCert\n\nOID = 2 16 840 1 114412 1 2\nComment = Digicert CA policy\nDescription = digiCertDVCert\n\nOID = 2 16 840 1 114412 1 11\nComment = Digicert CA policy\nDescription = digiCertFederatedDeviceCert\n\nOID = 2 16 840 1 114412 1 3 0 1\nComment = Digicert CA policy\nDescription = digiCertGlobalCAPolicy\n\nOID = 2 16 840 1 114412 1 3 0 2\nComment = Digicert CA policy\nDescription = digiCertHighAssuranceEVCAPolicy\n\nOID = 2 16 840 1 114412 1 3 0 3\nComment = Digicert CA policy\nDescription = digiCertGlobalRootCAPolicy\n\nOID = 2 16 840 1 114412 1 3 0 4\nComment = Digicert CA policy\nDescription = digiCertAssuredIDRootCAPolicy\n\nOID = 2 16 840 1 114412 2 2\nComment = Digicert CA policy\nDescription = digiCertEVCert\n\nOID = 2 16 840 1 114412 2 3\nComment = Digicert CA policy\nDescription = digiCertObjectSigningCert\n\nOID = 2 16 840 1 114412 2 3 1\nComment = Digicert CA policy\nDescription = digiCertCodeSigningCert\n\nOID = 2 16 840 1 114412 2 3 2\nComment = Digicert CA policy\nDescription = digiCertEVCodeSigningCert\n\nOID = 2 16 840 1 114412 2 3 11\nComment = Digicert CA policy\nDescription = digiCertKernelCodeSigningCert\n\nOID = 2 16 840 1 114412 2 3 21\nComment = Digicert CA policy\nDescription = digiCertDocumentSigningCert\n\nOID = 2 16 840 1 114412 2 4\nComment = Digicert CA policy\nDescription = digiCertClientCert\n\nOID = 2 16 840 1 114412 2 4 1 1\nComment = Digicert CA policy\nDescription = digiCertLevel1PersonalClientCert\n\nOID = 2 16 840 1 114412 2 4 1 2\nComment = Digicert CA policy\nDescription = digiCertLevel1EnterpriseClientCert\n\nOID = 2 16 840 1 114412 2 4 2\nComment = Digicert CA policy\nDescription = digiCertLevel2ClientCert\n\nOID = 2 16 840 1 114412 2 4 3 1\nComment = Digicert CA policy\nDescription = digiCertLevel3USClientCert\n\nOID = 2 16 840 1 114412 2 4 3 2\nComment = Digicert CA policy\nDescription = digiCertLevel3CBPClientCert\n\nOID = 2 16 840 1 114412 2 4 4 1\nComment = Digicert CA policy\nDescription = digiCertLevel4USClientCert\n\nOID = 2 16 840 1 114412 2 4 4 2\nComment = Digicert CA policy\nDescription = digiCertLevel4CBPClientCert\n\nOID = 2 16 840 1 114412 2 4 5 1\nComment = Digicert CA policy\nDescription = digiCertPIVHardwareCert\n\nOID = 2 16 840 1 114412 2 4 5 2\nComment = Digicert CA policy\nDescription = digiCertPIVCardAuthCert\n\nOID = 2 16 840 1 114412 2 4 5 3\nComment = Digicert CA policy\nDescription = digiCertPIVContentSigningCert\n\nOID = 2 16 840 1 114412 4 31\nComment = Digicert CA policy\nDescription = digiCertGridClassicCert\n\nOID = 2 16 840 1 114412 4 31 5\nComment = Digicert CA policy\nDescription = digiCertGridIntegratedCert\n\n# There's another arc for grid stuff around 2 16 840 1 114412 31 *\n# so the following probably isn't a typo.\nOID = 2 16 840 1 114412 31 4 31 1\nComment = Digicert CA policy\nDescription = digiCertGridHostCert\n\n# SET\n\nOID = 2 23 42 0\nComment = SET\nDescription = contentType\n\nOID = 2 23 42 0 0\nComment = SET contentType\nDescription = panData\n\nOID = 2 23 42 0 1\nComment = SET contentType\nDescription = panToken\n\nOID = 2 23 42 0 2\nComment = SET contentType\nDescription = panOnly\n\n# And on and on and on for another 80-odd OIDs that I'm not going to type in\n\nOID = 2 23 42 1\nComment = SET\nDescription = msgExt\n\nOID = 2 23 42 2\nComment = SET\nDescription = field\n\nOID = 2 23 42 2 0\nComment = SET field\nDescription = fullName\n\nOID = 2 23 42 2 1\nComment = SET field\nDescription = givenName\n\nOID = 2 23 42 2 2\nComment = SET field\nDescription = familyName\n\nOID = 2 23 42 2 3\nComment = SET field\nDescription = birthFamilyName\n\nOID = 2 23 42 2 4\nComment = SET field\nDescription = placeName\n\nOID = 2 23 42 2 5\nComment = SET field\nDescription = identificationNumber\n\nOID = 2 23 42 2 6\nComment = SET field\nDescription = month\n\nOID = 2 23 42 2 7\nComment = SET field\nDescription = date\n\nOID = 2 23 42 2 8\nComment = SET field\nDescription = address\n\nOID = 2 23 42 2 9\nComment = SET field\nDescription = telephone\n\nOID = 2 23 42 2 10\nComment = SET field\nDescription = amount\n\nOID = 2 23 42 2 11\nComment = SET field\nDescription = accountNumber\n\nOID = 2 23 42 2 12\nComment = SET field\nDescription = passPhrase\n\nOID = 2 23 42 3\nComment = SET\nDescription = attribute\n\nOID = 2 23 42 3 0\nComment = SET attribute\nDescription = cert\n\nOID = 2 23 42 3 0 0\nComment = SET cert attribute\nDescription = rootKeyThumb\n\nOID = 2 23 42 3 0 1\nComment = SET cert attribute\nDescription = additionalPolicy\n\nOID = 2 23 42 4\nComment = SET\nDescription = algorithm\n\nOID = 2 23 42 5\nComment = SET\nDescription = policy\n\nOID = 2 23 42 5 0\nComment = SET policy\nDescription = root\n\nOID = 2 23 42 6\nComment = SET\nDescription = module\n\nOID = 2 23 42 7\nComment = SET\nDescription = certExt\n\nOID = 2 23 42 7 0\nComment = SET cert extension\nDescription = hashedRootKey\n\nOID = 2 23 42 7 1\nComment = SET cert extension\nDescription = certificateType\n\nOID = 2 23 42 7 2\nComment = SET cert extension\nDescription = merchantData\n\nOID = 2 23 42 7 3\nComment = SET cert extension\nDescription = cardCertRequired\n\nOID = 2 23 42 7 4\nComment = SET cert extension\nDescription = tunneling\n\nOID = 2 23 42 7 5\nComment = SET cert extension\nDescription = setExtensions\n\nOID = 2 23 42 7 6\nComment = SET cert extension\nDescription = setQualifier\n\nOID = 2 23 42 8\nComment = SET\nDescription = brand\n\nOID = 2 23 42 8 1\nComment = SET brand\nDescription = IATA-ATA\n\nOID = 2 23 42 8 4\nComment = SET brand\nDescription = VISA\n\nOID = 2 23 42 8 5\nComment = SET brand\nDescription = MasterCard\n\nOID = 2 23 42 8 30\nComment = SET brand\nDescription = Diners\n\nOID = 2 23 42 8 34\nComment = SET brand\nDescription = AmericanExpress\n\nOID = 2 23 42 8 6011\nComment = SET brand\nDescription = Novus\n\nOID = 2 23 42 9\nComment = SET\nDescription = vendor\n\nOID = 2 23 42 9 0\nComment = SET vendor\nDescription = GlobeSet\n\nOID = 2 23 42 9 1\nComment = SET vendor\nDescription = IBM\n\nOID = 2 23 42 9 2\nComment = SET vendor\nDescription = CyberCash\n\nOID = 2 23 42 9 3\nComment = SET vendor\nDescription = Terisa\n\nOID = 2 23 42 9 4\nComment = SET vendor\nDescription = RSADSI\n\nOID = 2 23 42 9 5\nComment = SET vendor\nDescription = VeriFone\n\nOID = 2 23 42 9 6\nComment = SET vendor\nDescription = TrinTech\n\nOID = 2 23 42 9 7\nComment = SET vendor\nDescription = BankGate\n\nOID = 2 23 42 9 8\nComment = SET vendor\nDescription = GTE\n\nOID = 2 23 42 9 9\nComment = SET vendor\nDescription = CompuSource\n\nOID = 2 23 42 9 10\nComment = SET vendor\nDescription = Griffin\n\nOID = 2 23 42 9 11\nComment = SET vendor\nDescription = Certicom\n\nOID = 2 23 42 9 12\nComment = SET vendor\nDescription = OSS\n\nOID = 2 23 42 9 13\nComment = SET vendor\nDescription = TenthMountain\n\nOID = 2 23 42 9 14\nComment = SET vendor\nDescription = Antares\n\nOID = 2 23 42 9 15\nComment = SET vendor\nDescription = ECC\n\nOID = 2 23 42 9 16\nComment = SET vendor\nDescription = Maithean\n\nOID = 2 23 42 9 17\nComment = SET vendor\nDescription = Netscape\n\nOID = 2 23 42 9 18\nComment = SET vendor\nDescription = Verisign\n\nOID = 2 23 42 9 19\nComment = SET vendor\nDescription = BlueMoney\n\nOID = 2 23 42 9 20\nComment = SET vendor\nDescription = Lacerte\n\nOID = 2 23 42 9 21\nComment = SET vendor\nDescription = Fujitsu\n\nOID = 2 23 42 9 22\nComment = SET vendor\nDescription = eLab\n\nOID = 2 23 42 9 23\nComment = SET vendor\nDescription = Entrust\n\nOID = 2 23 42 9 24\nComment = SET vendor\nDescription = VIAnet\n\nOID = 2 23 42 9 25\nComment = SET vendor\nDescription = III\n\nOID = 2 23 42 9 26\nComment = SET vendor\nDescription = OpenMarket\n\nOID = 2 23 42 9 27\nComment = SET vendor\nDescription = Lexem\n\nOID = 2 23 42 9 28\nComment = SET vendor\nDescription = Intertrader\n\nOID = 2 23 42 9 29\nComment = SET vendor\nDescription = Persimmon\n\nOID = 2 23 42 9 30\nComment = SET vendor\nDescription = NABLE\n\nOID = 2 23 42 9 31\nComment = SET vendor\nDescription = espace-net\n\nOID = 2 23 42 9 32\nComment = SET vendor\nDescription = Hitachi\n\nOID = 2 23 42 9 33\nComment = SET vendor\nDescription = Microsoft\n\nOID = 2 23 42 9 34\nComment = SET vendor\nDescription = NEC\n\nOID = 2 23 42 9 35\nComment = SET vendor\nDescription = Mitsubishi\n\nOID = 2 23 42 9 36\nComment = SET vendor\nDescription = NCR\n\nOID = 2 23 42 9 37\nComment = SET vendor\nDescription = e-COMM\n\nOID = 2 23 42 9 38\nComment = SET vendor\nDescription = Gemplus\n\nOID = 2 23 42 10\nComment = SET\nDescription = national\n\nOID = 2 23 42 10 392\nComment = SET national\nDescription = Japan\n\n# WAP\n\nOID = 2 23 43 1 4\nComment = WAP WTLS\nDescription = wTLS-ECC\n\nOID = 2 23 43 1 4 1\nComment = WAP WTLS\nDescription = wTLS-ECC-curve1\n\nOID = 2 23 43 1 4 6\nComment = WAP WTLS\nDescription = wTLS-ECC-curve6\n\nOID = 2 23 43 1 4 8\nComment = WAP WTLS\nDescription = wTLS-ECC-curve8\n\nOID = 2 23 43 1 4 9\nComment = WAP WTLS\nDescription = wTLS-ECC-curve9\n\n# TCPA\n\nOID = 2 23 133\nComment = TCPA\nDescription = tCPA\n\nOID = 2 23 133 1\nComment = TCPA\nDescription = tcpaSpecVersion\n\nOID = 2 23 133 2\nComment = TCPA\nDescription = tcpaAttribute\n\nOID = 2 23 133 2 1\nComment = TCPA Attribute\nDescription = tcpaTpmManufacturer\n\nOID = 2 23 133 2 2\nComment = TCPA Attribute\nDescription = tcpaTpmModel\n\nOID = 2 23 133 2 3\nComment = TCPA Attribute\nDescription = tcpaTpmVersion\n\nOID = 2 23 133 2 4\nComment = TCPA Attribute\nDescription = tcpaPlatformManufacturer\n\nOID = 2 23 133 2 5\nComment = TCPA Attribute\nDescription = tcpaPlatformModel\n\nOID = 2 23 133 2 6\nComment = TCPA Attribute\nDescription = tcpaPlatformVersion\n\nOID = 2 23 133 2 7\nComment = TCPA Attribute\nDescription = tcpaComponentManufacturer\n\nOID = 2 23 133 2 8\nComment = TCPA Attribute\nDescription = tcpaComponentModel\n\nOID = 2 23 133 2 9\nComment = TCPA Attribute\nDescription = tcpaComponentVersion\n\nOID = 2 23 133 2 10\nComment = TCPA Attribute\nDescription = tcpaSecurityQualities\n\nOID = 2 23 133 2 11\nComment = TCPA Attribute\nDescription = tcpaTpmProtectionProfile\n\nOID = 2 23 133 2 12\nComment = TCPA Attribute\nDescription = tcpaTpmSecurityTarget\n\nOID = 2 23 133 2 13\nComment = TCPA Attribute\nDescription = tcpaFoundationProtectionProfile\n\nOID = 2 23 133 2 14\nComment = TCPA Attribute\nDescription = tcpaFoundationSecurityTarget\n\nOID = 2 23 133 2 15\nComment = TCPA Attribute\nDescription = tcpaTpmIdLabel\n\nOID = 2 23 133 3\nComment = TCPA\nDescription = tcpaProtocol\n\nOID = 2 23 133 3 1\nComment = TCPA Protocol\nDescription = tcpaPrttTpmIdProtocol\n\n# PostSignum.\n\nOID = 2 23 134 1 4 2 1\nComment = PostSignum CA\nDescription = postSignumRootQCA\n\nOID = 2 23 134 1 2 2 3\nComment = PostSignum CA\nDescription = postSignumPublicCA\n\nOID = 2 23 134 1 2 1 8 210\nComment = PostSignum CA\nDescription = postSignumCommercialServerPolicy\n\n# ICAO.  Technically this OID is called \"SOD\" but displaying that as a name\n# will just bugger up people's understanding of the data.  Newer versions of\n# the spec call it ldsSecurityObject but that's a bit too vague to indicate\n# what it really is.\n\nOID = 2 23 136 1 1 1\nComment = ICAO MRTD\nDescription = mRTDSignatureData\n\n# Draft SET.  These were invented for testing in pre-1.0 drafts but have\n# been used nonetheless by implementors\n\nOID = 2 54 1775 2\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = hashedRootKey\nWarning\n\nOID = 2 54 1775 3\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = certificateType\nWarning\n\nOID = 2 54 1775 4\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = merchantData\nWarning\n\nOID = 2 54 1775 5\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = cardCertRequired\nWarning\n\nOID = 2 54 1775 6\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = tunneling\nWarning\n\nOID = 2 54 1775 7\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = setQualifier\nWarning\n\nOID = 2 54 1775 99\nComment = SET.  Deprecated, use (2 23 42 7 0) instead\nDescription = setData\nWarning\n\n# EV certificate policies.  There's no official record of what all the EV\n# policy OIDs are, it seems to be defined as \"whatever the browsers will\n# accept as EV\".  This is taken from\n# http://en.wikipedia.org/wiki/Extended_Validation_Certificate, there's also\n# a list in Chromium, the ev_root_ca_metadata list, but this contains\n# errors (e.g. the value \"1.3.6.1.4.1.6449.1.2.1.5.1\" [sic] is recorded as\n# being for both AddTrust and Comodo).\n#\n# The OIDs are collected here in owner-name alphabetical order rather than\n# scattering them throughout this list in OID order to make it easier to\n# track what's already present.\n\nOID = 1 2 40 0 17 1 22\nComment = A-Trust CA Root\nDescription = A-Trust EV policy\n\n# This appears to be an error in Chromium's ev_root_ca_metadata.\n# OTOH this OID was also used by UTN-Userfirst, which is now\n# Comodo.\n#OID = 1 3 6 1 4 1 6449 1 2 1 5 1\n#Comment = AddTrust External CA Root\n#Description = AddTrust EV policy\n\nOID = 1 3 6 1 4 1 34697 2 1\nComment = AffirmTrust Commercial\nDescription = AffirmTrust EV policy\n\nOID = 1 3 6 1 4 1 34697 2 2\nComment = AffirmTrust Networking\nDescription = AffirmTrust EV policy\n\nOID = 1 3 6 1 4 1 34697 2 3\nComment = AffirmTrust Premium\nDescription = AffirmTrust EV policy\n\nOID = 1 3 6 1 4 1 34697 2 4\nComment = AffirmTrust Premium ECC\nDescription = AffirmTrust EV policy\n\nOID = 2 16 578 1 26 1 3 3\nComment = BuyPass Class 3 EV\nDescription = BuyPass EV policy\n\nOID = 1 3 6 1 4 1 17326 10 14 2 1 2\nComment = Camerfirma CA Root\nDescription = Camerfirma EV policy\n\nOID = 1 3 6 1 4 1 17326 10 8 12 1 2\nComment = Camerfirma CA Root\nDescription = Camerfirma EV policy\n\nOID = 1 3 6 1 4 1 22234 2 5 2 3 1\nComment = CertPlus Class 2 Primary CA (formerly Keynectis)\nDescription = CertPlus EV policy\n\nOID = 1 3 6 1 4 1 6449 1 2 1 5 1\nComment = COMODO Certification Authority\nDescription = Comodo EV policy\n\nOID = 1 3 6 1 4 1 6334 1 100 1\nComment = Cybertrust Global Root (now Verizon Business)\nDescription = Cybertrust EV policy\n\nOID = 1 3 6 1 4 1 4788 2 202 1\nComment = D-TRUST Root Class 3 CA 2 EV 2009\nDescription = D-TRUST EV policy\n\nOID = 2 16 840 1 114412 2 1\nComment = DigiCert High Assurance EV Root CA\nDescription = DigiCert EV policy\n\nOID = 2 16 528 1 1001 1 1 1 12 6 1 1 1\nComment = DigiNotar Root CA\nDescription = DigiNotar EV policy\n\nOID = 2 16 840 1 114028 10 1 2\nComment = Entrust Root Certification Authority\nDescription = Entrust EV policy\n\nOID = 1 3 6 1 4 1 14370 1 6\nComment = GeoTrust Primary Certification Authority (formerly Equifax)\nDescription = GeoTrust EV policy\n\nOID = 1 3 6 1 4 1 4146 1 1\nComment = GlobalSign\nDescription = GlobalSign EV policy\n\nOID = 2 16 840 1 114413 1 7 23 3\nComment = GoDaddy Class 2 Certification Authority (formerly ValiCert)\nDescription = GoDaddy EV policy\n\nOID = 1 3 6 1 4 1 14777 6 1 1\nComment = Certificado de Servidor Seguro SSL EV\nDescription = Izenpe EV policy\n\nOID = 1 3 6 1 4 1 14777 6 1 2\nComment = Certificado de Sede Electronica EV\nDescription = Izenpe EV policy\n\nOID = 1 3 6 1 4 1 782 1 2 1 8 1\nComment = Network Solutions Certificate Authority\nDescription = Network Solutions EV policy\n\nOID = 1 3 6 1 4 1 8024 0 2 100 1 2\nComment = QuoVadis Root CA 2\nDescription = QuoVadis EV policy\n\nOID = 1 2 392 200091 100 721 1\nComment = Security Communication RootCA1\nDescription = Security Communication (SECOM) EV policy\n\nOID = 2 16 840 1 114414 1 7 23 3\nComment = Starfield Class 2 Certification Authority\nDescription = Starfield EV policy\n\nOID = 1 3 6 1 4 1 23223 1 1 1\nComment = StartCom Certification Authority\nDescription = StartCom EV policy\n\nOID = 2 16 756 1 89 1 2 1 1\nComment = SwissSign Gold CA - G2\nDescription = SwissSign EV policy\n\nOID = 1 3 6 1 4 1 7879 13 24 1\nComment = T-TeleSec GlobalRoot Class 3\nDescription = T-TeleSec EV policy\n\nOID = 2 16 840 1 113733 1 7 48 1\nComment = Thawte Premium Server CA\nDescription = Thawte EV policy\n\nOID = 2 16 840 1 114404 1 1 2 4 1\nComment = TrustWave CA, formerly SecureTrust, before that XRamp\nDescription = TrustWave EV policy\n\nOID = 1 3 6 1 4 1 40869 1 1 22 3\nComment = TWCA Root Certification Authority\nDescription = TWCA EV policy\n\nOID = 2 16 840 1 113733 1 7 23 6\nComment = VeriSign Class 3 Public Primary Certification Authority\nDescription = VeriSign EV policy\n\nOID = 2 16 840 1 114171 500 9\nComment = Wells Fargo WellsSecure Public Root Certificate Authority\nDescription = Wells Fargo EV policy\n\n# End of Fahnenstange\n"
  },
  {
    "path": "deps/cl345/tools/endian.c",
    "content": "/* This is a lowest-common-denominator program which should compile under\n   the default cc on any system, no matter how primitive (even the SunOS\n   one - note the use of 1970s-vintage octal escapes).  This is necessary\n   because it's compiled before we can try and select a decent compiler via\n   the makefile */\n\n#include <stdio.h>\n#include <stdlib.h>\n\nint main()\n\t{\n\tif( *( long * ) \"\\200\\0\\0\\0\\0\\0\\0\\0\" < 0 )\n\t\tprintf( \"-DDATA_BIGENDIAN\" );\n\telse\n\t\tprintf( \"-DDATA_LITTLEENDIAN\" );\n\n\treturn( 0 );\n\t}\n"
  },
  {
    "path": "deps/cl345/tools/fuzz.sh",
    "content": "#!/bin/bash\n# Fuzz cryptlib (via the spcially-built testlib).\n\nINPUT_DIR_PARENT=afl-in\nOUTPUT_DIR_PARENT=afl-out\nPROGNAME_SRC=./testlib\nPROGNAME=./fuzz-clib\nFUZZER=../afl-2*/afl-fuzz\nFUZZTYPES=\"base64 certificate certchain certreq cms pgp pkcs12 pkcs15 pgppub \\\n\t\t   pgpsec ssl-client ssl-server ssh-client ssh-server tsp-client \\\n\t\t   tsp-server ocsp-client ocsp-server rtcs-client rtcs-server bignum \\\n\t\t   url http-req http-resp websockets\"\nFUZZTYPE=$1\nDIRNAME=${FUZZTYPE}\nINPUT_DIR=${INPUT_DIR_PARENT}/${DIRNAME}\nOUTPUT_DIR=${OUTPUT_DIR_PARENT}/${DIRNAME}\nNO_CPUS=`getconf _NPROCESSORS_ONLN`\n\n# Without ASAN the fuzzing uses -m 200 to give 200MB of memory which for\n# some reason is needed by AFL, with ASAN it needs to be -m none to set no\n# limit.\n\nMEMORY_LIMIT=none\n\n# Make sure that we've been given sufficient arguments.\n\nif [ -z \"$1\" ] ; then\n\techo \"$0: Missing option.  Valid options are:\" >&2\n\techo \"    clean                   - Clean up working files.\" >&2\n\techo \"    resume <type>           - Resume from previous run.\" >&2\n\techo \"    stats                   - Show fuzzing stats.\" >&2\n\techo \"    package                 - Package results in ~/afl.zip.\" >&2\n\techo \"\"  >&2\n\techo \"    base64                  - Fuzz base64 decoding.\" >&2\n\techo \"    certificate/certchain   - Fuzz certificate/cert.chain.\" >&2\n\techo \"    certreq                 - Fuzz cert.request.\" >&2\n\techo \"    cms/pgp                 - Fuzz CMS/PGP message.\" >&2\n\techo \"    pkcs12/pkcs15           - Fuzz PKCS #12/#15 keyset.\" >&2\n\techo \"    pgppub/pgpsec           - Fuzz PGP pub/priv.keyset.\" >&2\n\techo \"    ssl-client/ssl-server   - Fuzz SSL client/server.\" >&2\n\techo \"    ssh-client/ssh-server   - Fuzz SSH client/server.\" >&2\n\techo \"    tsp-client/tsp-server   - Fuzz TSP client/server.\" >&2\n\techo \"    ocsp-client/ocsp-server - Fuzz OCSP client/server.\" >&2\n\techo \"    rtcs-client/rtcs-server - Fuzz RTCS client/server.\" >&2\n\techo \"    (SCEP is fuzzed via CMS envelopes).\" >&2\n\techo \"    bignum                  - Fuzz bignum ops.\" >&2\n\techo \"    url                     - Fuzz URL parsing.\" >&2\n\techo \"    http-req/http-resp      - Fuzz HTTP request/response.\" >&2\n\techo \"    websockets              - Fuzz WebSockets.\" >&2\n\texit 1\nfi\n\n# Make sure that we don't try and fuzz non-fuzzable protocols\n\nif [ \"$1\" = \"scep-client\" -o \"$1\" = \"scep-server\" ] ; then\n\techo \"$0: SCEP uses CMS messages which are fuzzed via envelopes.\" >&2 ;\n\texit 1\nfi\n\n# If we're doing a cleanup, delete input and output files and exit\n\nif [ \"$1\" = \"clean\" ] ; then\n\techo \"Cleaning up...\"\n\tshift\n\tif [ -z \"$1\" ] ; then\n\t\techo \"$0: Missing option to clean up.\" >&2\n\t\texit 1\n\tfi\n\trm -r ./${INPUT_DIR_PARENT}/$1\n\trm -r ./${OUTPUT_DIR_PARENT}/$1\n\texit 0\nfi\n\n# If we're showing stats, cat the fuzzer_stats files and exit\n\nshow_stats()\n\t{\n\tDIR=./${OUTPUT_DIR_PARENT}/$1\n\n\tif [ ! -d ${DIR} ] ; then\n\t\treturn 0 ;\n\tfi\n\techo Stats for $1...\n\tgrep cycles_done ${DIR}/fuzzer_stats\n\tgrep execs_done ${DIR}/fuzzer_stats\n\tgrep execs_per_sec ${DIR}/fuzzer_stats\n\tgrep unique_crashes ${DIR}/fuzzer_stats\n\tgrep unique_hangs ${DIR}/fuzzer_stats\n\techo\n\t}\n\nif [ \"$1\" = \"stats\" ] ; then\n\tfor FUZZTYPE in ${FUZZTYPES} ; do\n\t\tshow_stats ${FUZZTYPE}\n\tdone\n\texit 0\nfi\n\n# If we're packaging up results, bundle everything up and exit\n\npackage()\n\t{\n\tDIR=./${OUTPUT_DIR_PARENT}/$1\n\n\tif [ ! -d ${DIR} ] ; then\n\t\treturn 0\n\tfi\n\tmkdir /tmp/$1\n\tfor file in ${DIR}/crashes/id* ; do\n\t\toutFile=\"${file#*:}\"\n\t\tcp ${file} /tmp/$1/${outFile:0:6}.dat\n\tdone\n\tcd /tmp\n\tzip -o9 ~/afl.zip ./$1/*\n\tcd -\n\trm -r /tmp/$1\n\t}\n\nif [ \"$1\" = \"package\" ] ; then\n\tif [ -f ~/afl.zip ] ; then\n\t\trm ~/afl.zip\n\tfi\n\tfor FUZZTYPE in ${FUZZTYPES} ; do\n\t\tpackage ${FUZZTYPE}\n\tdone\n\techo Results saved to ~/afl.zip\n\texit 0\nfi\n\n# Create various directories\n\nmkdir_opt()\n\t{\n\tDIR=$1\n\tOPTION=$2\n\n\t# Try and create the directory\n\tif [ ! -d ${DIR} ] ; then\n\t\tmkdir ${DIR}\n\t\treturn 0\n\tfi\n\tif [ -z \"$OPTION\" ] ; then\n\t\treturn 0\n\tfi\n\n\t# It already exists, handle it as per the caller's instructions\n\tcase $OPTION in\n\t\t'clear-dup')\n\t\t\techo \"Warning: Input directory ${DIR} already exists, clearing files\" ;\n\t\t\trm ${DIR}/*.dat > /dev/null ;;\n\n\t\t'warn-dup')\n\t\t\techo \"Warning: Output directory ${DIR} already exists, were you\" ;\n\t\t\techo \"         meaning to continue a previous run?\" ;;\n\n\t\t*)\n\t\t\techo \"$0: Invalid mkdir_opt type $1.\" >&2 ;\n\t\t\texit 1 ;;\n\tesac\n\t}\n\nmkdir_opt ${INPUT_DIR_PARENT}\nmkdir_opt ${OUTPUT_DIR_PARENT}\n\n# If we're resuming from an aborted previous session, it's handled\n# specially.\n\nif [ \"$1\" = \"resume\" ] ; then\n\tshift\n\tif [ -z \"$1\" ] ; then\n\t\techo \"$0: Missing resume option.  Usage: '$0 resume <type>'\" >&2\n\t\texit 1\n\tfi\n\techo \"$0: Resuming fuzzing '$1' from previous session\"\n\tFUZZTYPE=$1\n\tOUTPUT_DIR=${OUTPUT_DIR_PARENT}/$1\n\tnohup ${FUZZER} -m ${MEMORY_LIMIT} -i - -o ${OUTPUT_DIR} ${PROGNAME} -z${FUZZTYPE} @@ &\n#\tnohup ${FUZZER} -m ${MEMORY_LIMIT} -i - -o ${OUTPUT_DIR} ${PROGNAME} -z${FUZZTYPE} @@ > /dev/null 2>&1 &\n\texit 0\nfi\n\n# Set up files and directories\n\nFILEPATH=\"test/fuzz/\"\ncase $1 in\n\t# Sessions reverse the argument, so to fuzz the xxx client we use\n\t# data from the xxx server.\n\t'ssh-client')\n\t\tFILENAME=${FILEPATH}ssh_svr.dat ;;\n\n\t'ssh-server')\n\t\tFILENAME=${FILEPATH}ssh_cli.dat ;;\n\n\t'ssl-client')\n\t\tFILENAME=${FILEPATH}ssl_svr.dat ;;\n\n\t'ssl-server')\n\t\tFILENAME=${FILEPATH}ssl_cli.dat ;;\n\n\t'tsp-client')\n\t\tFILENAME=${FILEPATH}tsp_svr.dat ;;\n\n\t'tsp-server')\n\t\tFILENAME=${FILEPATH}tsp_cli.dat ;;\n\n\t'ocsp-client')\n\t\tFILENAME=${FILEPATH}ocsp_svr.dat ;;\n\n\t'ocsp-server')\n\t\tFILENAME=${FILEPATH}ocsp_cli.dat ;;\n\n\t'rtcs-client')\n\t\tFILENAME=${FILEPATH}rtcs_svr.dat ;;\n\n\t'rtcs-server')\n\t\tFILENAME=${FILEPATH}rtcs_cli.dat ;;\n\n\t# HTTP uses underscores instead of dashes for the filename so can't\n\t# be handled by the default handler below.\n\t'http-req')\n\t\tFILENAME=${FILEPATH}http_req.dat ;;\n\n\t'http-resp')\n\t\tFILENAME=${FILEPATH}http_resp.dat ;;\n\n\t# Everything else uses the argument as the data source.\n\t*)\n\t\tFILENAME=${FILEPATH}$1.dat ;;\nesac\nif [ ! -f ${FILENAME} ] ; then\n\techo \"$0: Couldn't find data file ${FILENAME}.\" >&2\n\texit 1\nfi\nmkdir_opt ${INPUT_DIR} clear-dup\nmkdir_opt ${OUTPUT_DIR} warn-dup\ncp ${FILENAME} ${INPUT_DIR}\nif [ ! -x  ${PROGNAME} ] ; then\n\tcp ${PROGNAME_SRC} ${PROGNAME}\nfi\n\n# Run the fuzzer.  This takes files from ${INPUT_DIR} and pastes them into\n# the '@@' location, with output in ${OUTPUT_DIR}/hangs and\n# ${OUTPUT_DIR}/crashes.  If there are problems with timeouts, add something\n# like -t 1000 (1s in ms).\n#\n# To start a single-instance fuzzer:\n# nohup ${FUZZER} -m ${MEMORY_LIMIT} -i ${INPUT_DIR} -o ${OUTPUT_DIR} ${PROGNAME} -z${FUZZTYPE} @@ &\n#\n# This writes initial output to nohup.log, to make it completely silent\n# append \"> /dev/null 2>&1\".\n#\n# In theory afl can run across multiple CPU cores with multiple instances, one\n# per core, but this doesn't seem to work properly.  If it gets sorted out then\n# the master is started with -M, the slaves with -S.\n\nnohup ${FUZZER} -m ${MEMORY_LIMIT} -t 1000 -i ${INPUT_DIR} -o ${OUTPUT_DIR} ${PROGNAME} -z${FUZZTYPE} @@ &\nexit 0\n\necho \"Running on ${NO_CPUS} CPUs\"\n${FUZZER} -m ${MEMORY_LIMIT} -i ${INPUT_DIR} -o ${OUTPUT_DIR} -M fuzzer1 ${PROGNAME} -z${FUZZTYPE} @@ &\n\nif [ $NO_CPUS -gt 1 ] ; then\n\tfor i in `seq 2 $NUM_FUZZERS` ; do\n\t\t${FUZZER} -m ${MEMORY_LIMIT} -i ${INPUT_DIR} -o ${OUTPUT_DIR} -S fuzzer${i} ${PROGNAME} -z${FUZZTYPE} @@ &\n\tdone\nfi\n"
  },
  {
    "path": "deps/cl345/tools/getcompiler.sh",
    "content": "#!/bin/sh\n# Get the compiler to use to build cryptlib\n#\n# Usage: getcompiler.sh compiler osname\n\n# Make sure that we've been given sufficient arguments.\n\nif [ $# -lt 2 ] ; then\n\techo \"Usage: $0 compiler osname\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nCC=$1\nOSNAME=$2\nshift 2\n\n# If we're explicitly building with a compiler wrapper that provides\n# extended functionality, don't try and select another compiler.\n\ncase \"$CC\" in\n\t*\"stack-master\"*|*\"afl-clang\"*|*\"afl-gcc\"*|*\"hfuzz-clang\"*|*\"ccc-analyzer\"*)\n\t\techo \"$CC\" ;\n\t\texit 0 ;\nesac\n\n# Some systems (Aches, PHUX, Slowaris) have the development tools as\n# optional components, or the tools suck so much that everyone used\n# something else instead, typically gcc.\n#\n# We used to override the native tools with gcc if possible but don't any\n# more for two reasons, firstly some of the native tools now suck a bit\n# less, and secondly with the general move by everything that could move to\n# x86 most users still on Aches/PHUX/Slowaris are there because they've\n# invested heavily in the whole ecosystem, so will be using the native tools\n# rather than adding gcc.  In some cases this is actually essential, for\n# example under AIX mixing gcc-created and IBM-sourced components isn't a\n# good idea.  For these reasons we use the system compiler rather than gcc\n# if it's available.\n\nif [ \"$OSNAME\" = \"HP-UX\" ] ; then\n\tif command -v clang > /dev/null ; then\n\t\techo \"clang\" ;\n\t\texit 0 ;\n\tfi\n\tif command -v gcc > /dev/null ; then\n\t\techo \"gcc\" ;\n\t\texit 0 ;\n\tfi\nfi\n\n# If it's Aches or Slowaris then the compiler is hidden somewhere weird\n# because it's not installed by default (for Slowaris it's particularly bad,\n# see the long comment in buildall.sh), so we try and use that if possible\n# for the reason given above.\n\nif [ \"$OSNAME\" = \"SunOS\" ] ; then\n\tif [ $($CC -V 2>&1 | grep -c \"Sun C\") -gt 0 ] ; then\n\t\techo $CC ;\n\t\texit 0 ;\n\tfi\nfi\nif [ \"$OSNAME\" = \"AIX\" ] ; then\n\tif command -v xlc > /dev/null ; then\n\t\techo \"xlc\" ;\n\t\texit 0 ;\n\tfi\nfi\n\n# If we've got clang installed, default to that.\n\n#############################################################################\n#\n# *** WWIV Patch 2023-12-22 rushfan ***\n#\n# Don't use clang since the rest of WWIV uses gcc and that causes issues linking in libcl.a\n#\n#\n#if command -v clang > /dev/null ; then\n#\techo \"clang\" ;\n#\texit 0 ;\n#fi\n\n# If cc is gcc, use that.\n\nif [ \"$($CC -v 2>&1 | grep -c \"gcc\")\" -gt 0 ] ; then\n\techo \"gcc\" ;\n\texit 0 ;\nfi\n\n# Use whatever the native cc is\n\necho \"$CC\"\n"
  },
  {
    "path": "deps/cl345/tools/getlibs.sh",
    "content": "#!/bin/sh\n# Get a list of the system libraries that need to be linked with cryptlib.\n#\n# Usage: getlibs.sh [special] compiler osname [crosscompile]\n\nLDARGS=\"\"\nISSPECIAL=0\nCROSSCOMPILE=0\n\n# Make sure that we've been given sufficient arguments.\n\nif [ \"$1\" = \"special\" ] ; then\n    ISSPECIAL=1 ;\n    shift ;\nfi\nif [ $# -lt 2 ] ; then\n\techo \"Usage: $0 getlibs.sh [special] compiler osname [crosscompile]\" >&2 ;\n\texit 1 ;\nfi\nif [ ! -z \"$3\" ] ; then\n\tCROSSCOMPILE=$3 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nCC=$1\nOSNAME=$2\nshift\nshift\n\n# Get the compiler build options, which affect the linker options.\n\nif [ $ISSPECIAL -eq 0 ] ; then\n\tBUILDOPTS=\"$(./tools/ccopts.sh $CC $OSNAME 2>&1)\" ;\nelse\n\tBUILDOPTS=\"$(./tools/ccopts.sh special $CC $OSNAME 2>&1)\" ;\nfi\n\nhasSubstring()\n\t{\n\tSTRING=$1\n\tSUBSTRING=$2\n\n\t# Check whether SUBSTRING is present in STRING by checking whether it\n\t# matches the pattern ' * $SUBSTRING * '.\n    case \"$STRING\" in\n\t\t*\"$SUBSTRING\"*)\n\t\t\treturn 0 ;;\n\tesac\n\n\treturn 1\n\t}\n\n# If we're using a newer version of clang, we'll have been compiled with\n# specific compiler options that need to be passed down to the linker.\n# See the comment in tools/ccopts.sh on why we need to check the version\n# number used to enable this flag rather than just checking for the presence\n# of the flag in the compile options.\n\nif hasSubstring \"$BUILDOPTS\" \"sanitize=safe-stack\" ; then\n\tCLANG_VER=\"$(clang -dumpversion | tr -d  '.' | cut -c 1-2)\" ;\n\tif [ $CLANG_VER -gt 47 ] ; then\n\t\tLDARGS=\"$LDARGS -fsanitize=safe-stack\" ;\n\tfi ;\nfi\n\n# Add any libraries needed by optional components.  In the case of zlib use\n# this is a real pain because some Linux distros require that you use\n# potentially out-of-date system-provided libraries if they're present\n# rather than your own, up-to-date code.\n\nif hasSubstring \"$BUILDOPTS\" \"HAS_TPM\" ; then\n\tLDARGS=\"$LDARGS -ltspi\" ;\nfi\nif hasSubstring \"$BUILDOPTS\" \"HAS_ZLIB\" ; then\n\tLDARGS=\"$LDARGS -lz\" ;\nfi\n\n# Some OS's require the linking of additional special libraries, either into\n# the executable for the static-lib version or into the library itself for\n# the shared-lib version.  The OS's and their libraries are:\n#\n#\tAIX 4.x:\t\t\t\t\t-lc_r -lpthreads\n#\tAIX 5.x:\t\t\t\t\t-lc_r -lpthreads -lbsd\n#\tBeOS:\t\t\t\t\t\tNone\n#\tBeOS with BONE:\t\t\t\t-lbind -lsocket\n#\tBSDI:\t\t\t\t\t\t-lgcc\n#\tCray Unicos:\t\t\t\t-lpthread\n#\tCygwin:\t\t\t\t\t\tNone\n#\tFreeBSD:\t\t\t\t\tSee note for -lc_r, -lpthread\n#\tIrix:\t\t\t\t\t\t-lw\n#\tLinux:\t\t\t\t\t\t-lresolv -lpthread (-ldl see note)\n#\tNetBSD:\t\t\t\t\t\t-lpthread\n#\tMVS:\t\t\t\t\t\tNone\n#\tNCR MP-RAS (threads):\t\t-Xdce -lnsl -lsocket -lc89 -lresolv -lpthread\n#\tNCR MP-RAS (!threads):\t\t-K xpg42 -lnsl -lsocket -lc89 -lresolv\n#\tOSF1/DEC Unix:\t\t\t\t-lresolv -lpthread\n#\tOS X (Darwin):\t\t\t\t-lresolv\n#\tPHUX 9.x, 10.x:\t\t\t\tNone\n#\tPHUX 11.x:\t\t\t\t\t-lpthread\n#\tSunOS 4.x:\t\t\t\t\t-ldl -lnsl -lposix4\n#\tSunOS 5.5 and 5.6:\t\t\t-lw -lsocket -lkstat -lnsl -lposix4 -lthread\n#\tSolaris 7+ (SunOS 5.7+):\t-lw -lresolv -lsocket -lkstat -lrt -lnsl -lthread\n#\tTandem OSS/NSK:\t\t\t\tNone\n#\tUnixWare (SCO):\t\t\t\t-lsocket\n#\n# Comments:\n#\n#\t-lbsd = flock() support via BSD compatibility layer for Aches.\n#\t-lc_r = libc extended with re-entrant functions needed for threading.\n#\t\t\tThis is required by FreeBSD 5.1-RELEASE but not FreeBSD 5.1-\n#\t\t\tCURRENT, which has the standard libc re-entrant.  Because there's\n#\t\t\tno easy way to tell what we're running under (they both have the\n#\t\t\tsame version numbers) we'd have to use it for both, however by\n#\t\t\tusing -pthread during the compile we can tell the compiler to\n#\t\t\tsort the mess out for us - it'll link against libc_r or libc as\n#\t\t\tappropriate.\n#\t-ldl = dload() support for dynamically loaded PKCS #11 drivers.  Some\n#\t\t\tDebian releases require that the use of this library be\n#\t\t\texplicitly specified, although there's no discernable pattern\n#\t\t\tfor when this might be required (or even any easy way to detect\n#\t\t\tDebian), so we unconditionally include it under Linux if libdl\n#\t\t\texists.  Note that on some Linux systems it's hidden in\n#\t\t\t/usr/lib32 or /usr/lib64 so we check for multiple locations,\n#\t\t\tand then Ubuntu makes it even worse by hiding it in even more\n#\t\t\tplaces like /usr/lib/i386-linux-gnu/libdl.so.\n#\t\t\tIf this continues then it may be easier to just assume that\n#\t\t\tLinux, or at least Ubuntu, always has libdl present.  As a\n#\t\t\tsomewhat safer alternative we first try ldconfig, and only then\n#\t\t\tfall back to hardcoded locations.\n#\t-lgcc = Extra gcc support lib needed for BSDI, which ships with gcc but\n#\t\t\tnot the proper libs for it.\n#\t-lkstat = kstat functions for Solaris randomness gathering.\n#\t-lsocket = Resolver functions.\n#\t-lnsl = Socket support for Slowaris, which doesn't have it in libc.\n#   -lposix4 = Solaris 2.5 and 2.6 library for sched_yield.\n#\t-lresolv = Resolver functions.\n# \t-lrt = Solaris 2.7 and above realtime library for sched_yield().\n#\t-lssp = gcc additional library needed in some cases when\n#\t\t\t-f-stack-protector is used.\n#\t-lthread/lpthread/lpthreads = pthreads support.  Note that this generally\n#\t\t\thas to be linked as late as possible (and in particular after the\n#\t\t\timplied -lc) because libpthread overrides non-thread-safe and stub\n#\t\t\tfunctions in libraries linked earlier on with thread-safe\n#\t\t\talternatives.\n#\t-lw = Widechar support.\n\nOSVERSION=\"$(./tools/osversion.sh $OSNAME)\"\ncase $OSNAME in\n\t'AIX')\n\t\tLDARGS=\"$LDARGS -lc_r -lpthreads\" ;\n\t\tif [ $OSVERSION -gt 4 ] ; then\n\t\t\tLDARGS=\"$LDARGS -lbsd\" ;\n\t\tfi ;;\n\n\t'BeOS')\n\t\tif [ -f /system/lib/libbind.so ] ; then\n\t\t\tLDARGS=\"$LDARGS -lbind -lsocket\" ;\n\t\tfi ;;\n\n\t'BSD/OS')\n\t\tLDARGS=\"$LDARGS -lgcc\" ;;\n\n\t'CRAY')\n\t\tLDARGS=\"$LDARGS -lpthread\" ;;\n\n\t'Darwin')\n\t\tLDARGS=\"$LDARGS -lresolv\" ;;\n\n\t'FreeBSD'|'NetBSD')\n\t\tLDARGS=\"$LDARGS -lpthread\" ;;\n\n\t'HP-UX')\n\t\tif [ $OSVERSION -ge 10 ] ; then\n\t\t\tLDARGS=\"$LDARGS -lpthread\" ;\n\t\tfi ;;\n\n\t'IRIX'|'IRIX64')\n\t\tLDARGS=\"$LDARGS -lw\" ;;\n\n\t'Linux')\n\t\tLDARGS=\"$LDARGS -lresolv -lpthread\" ;\n\t\tif [ -x /sbin/ldconfig ] && \\\n\t\t   [ \"$(/sbin/ldconfig -p | grep -c 'libdl\\.so')\" -gt 0 ] ; then\n\t\t\tLDARGS=\"$LDARGS -ldl\" ;\n\t\telif [ -f /usr/lib/libdl.so ] || \\\n\t\t\t [ -f /usr/lib32/libdl.so ] || \\\n\t\t\t [ -f /usr/lib64/libdl.so ] || \\\n\t\t\t [ -f /usr/lib/i386-linux-gnu/libdl.so ] ; then\n\t\t\tLDARGS=\"$LDARGS -ldl\" ;\n\t\tfi ;;\n\n\t'OSF1')\n\t\tLDARGS=\"$LDARGS -lresolv -lpthread\" ;;\n\n\t'SunOS')\n\t\tif [ $OSVERSION -le 4 ] ; then\n\t\t\tLDARGS=\"$LDARGS -ldl -lnsl -lposix4\" ;\n\t\telif [ $OSVERSION -le 6 ] ; then\n\t\t\tLDARGS=\"$LDARGS -lw -lsocket -lkstat -lnsl -lposix4 -lthread\" ;\n\t\telse\n\t\t\tLDARGS=\"$LDARGS -lw -lresolv -lsocket -lkstat -lrt -lnsl -lthread\" ;\n\t\tfi ;;\n\n\t'UNIX_SV')\n\t\tLDARGS=\"$LDARGS -K xpg42 -lnsl -lsocket -lc89 -lresolv\" ;;\n\n\t'UnixWare')\n\t\tLDARGS=\"$LDARGS -lsocket\" ;;\nesac\n\n# Finally, report what we've found\n\necho \"$LDARGS\""
  },
  {
    "path": "deps/cl345/tools/getseed.sh",
    "content": "#!/bin/sh\n# Get a (non-cryptographic) random seed for compilation\n#\n# Usage: getseed.sh osname\n\nOSNAME=\"\"\nIS64BIT=0\n\n# Make sure that we've been given sufficient arguments.\n\nif [ $# -lt 1 ] ; then\n\techo \"Usage: $0 osname\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nOSNAME=$1\nshift\n\n# Try and determine whether we need to output a 32- or 64-bit value.  This\n# is somewhat crude since it gives the kernel architecture and we could be\n# building an arch-a application on an arch-b kernel (typically x86 on x64).\n# In addition if we fall back to the default uname -m this assumes that the\n# hardware name has some indicator of 64-bit-ness in it.  In general this\n# check errs on the side of caution, leaving the value at 32 bits if we're\n# not sure.\n\ncase $OSNAME in\n\t'AIX')\n\t\tif [ \"$(getconf KERNEL_BITMODE)\" = \"64\" ] ; then\n\t\t\tIS64BIT=1 ;\n\t\tfi ;;\n\n\t'HP-UX')\n\t\tif [ \"$(getconf KERNEL_BITS)\" = \"64\" ] ; then\n\t\t\tIS64BIT=1 ;\n\t\tfi ;;\n\n\t'SunOS')\n\t\tif [ \"$(isainfo -b)\" = \"64\" ] ; then\n\t\t\tIS64BIT=1 ;\n\t\tfi ;;\n\n\t*)\n\t\tif [ \"$(uname -m | grep '64')\" != \"\" ] ; then\n\t\t\tIS64BIT=1 ;\n\t\tfi ;;\nesac\n\n# Print a machine-word-sized /dev/random value as a hex string.\n\nformatDevRandomOutput()\n\t{\n\tSEEDVALUE=\"\"\n\n\t# Get the seed value as a hex string.\n\tif [ $IS64BIT -gt 0 ] ; then\n\t\tSEEDVALUE=\"$(od -An -N8 -tx1 < /dev/urandom | tr -d ' \\t\\n')\" ;\n\telse\n\t\tSEEDVALUE=\"$(od -An -N4 -tx1 < /dev/urandom | tr -d ' \\t\\n')\" ;\n\tfi ;\n\n\t# Display the seed value.\n\techo \"-DFIXED_SEED=0x\"$SEEDVALUE ;\n\t}\n\nif [ -e /dev/urandom ] ; then\n\tformatDevRandomOutput ;\n\texit 0 ;\nfi\n\n# There's no /dev/random, fall back to a random-ish alternative.\n\nif [ $(which last) ] ; then\n\tSOURCE=\"last -50\" ;\nelse\n\tSOURCE=\"uptime\" ;\nfi\nif [ $(which md5sum) ] ; then\n\tprintf -- \"-DFIXED_SEED=0x\" ;\n\tif [ $IS64BIT -gt 0 ] ; then\n\t\techo $($SOURCE | md5sum | cut -c1-16) ;\n\telse\n\t\techo $($SOURCE | md5sum | cut -c1-8) ;\n\tfi ;\n\texit 0 ;\nfi\n"
  },
  {
    "path": "deps/cl345/tools/mkhdr.sh",
    "content": "#!/bin/bash\n# Create the headers/interface files for non-C languages from the cryptlib\n# C header file.\n\n# Create the Delphi and VB headers.\n\nperl tools/GenPas.pl\nperl tools/GenVB.pl\nmv -f cryptlib.?as bindings\n\n# Create the Perl headers\n\nperl tools/GenPerl.pl\nmv -f PerlCryptLib.ph bindings\n\n# Create the Java, Python, and .NET interface.  We use python3 if available,\n# otherwise fall back to python2.\n\nif [ -x /usr/bin/python3 ];then\n     python3 tools/cryptlibConverter.py3 cryptlib.h bindings java\n     python3 tools/cryptlibConverter.py3 cryptlib.h bindings python\n     python3 tools/cryptlibConverter.py3 cryptlib.h bindings net\nelse\n     python2 tools/cryptlibConverter.py cryptlib.h bindings java\n     python2 tools/cryptlibConverter.py cryptlib.h bindings python\n     python2 tools/cryptlibConverter.py cryptlib.h bindings net\nfi\n\n# Bundle everything up for download.  We have to send the pushd output to\n# /dev/null since bash performs an implicit 'dirs' if the pushd/popd\n# succeeds.\n\nrm -f bindings.zip\npushd bindings > /dev/null\nzip -qo9 ../bindings cryptlib.bas cryptlib.cs cryptlib.jar cryptlib.pas java_jni.c PerlCryptLib.* Makefile.PL python.c setup.py\npopd > /dev/null\n\n# Tell the user what we've done\n\necho \"Updated language bindings have been moved to file 'bindings.zip'.\"\necho\n"
  },
  {
    "path": "deps/cl345/tools/osversion.sh",
    "content": "#!/bin/sh\n# Obtain the OS version.\n#\n# Usage: osversion.sh osname\n\nOSVERSION=\"\"\n\n# Make sure that we've been given sufficient arguments.\n\nif [ $# -ne 1 ] ; then\n\techo \"Usage: $0 osname\" >&2 ;\n\texit 1 ;\nfi\n\n# Juggle the args around to get them the way that we want them.\n\nOSNAME=$1\nshift\n\n# Determine the OS version.  The means of doing this varies wildly across\n# OSes.  We also check for the various cross-compile environments and return\n# either an appropriate version number (defaulting to '1' if there's no real\n# distinction between versions) or an error code if there's no useful\n# default available, in which case use requires manual editing of the config\n# as we can't automatically detect the OS version.\n\ncase $OSNAME in\n\t# Aches has a broken uname that reports the OS minor version with\n\t# uname -r instead of the major version.  The alternative command\n\t# oslevel reports the full version number, which we can extract in\n\t# the standard manner.\n\t'AIX')\n\t\tOSVERSION=\"$(oslevel | cut -d'.' -f1)\" ;;\n\n\t'AMX')\n\t\tOSVERSION=\"1\" ;;\n\n\t'Atmel')\n\t\tOSVERSION=\"1\" ;;\n\n\t'BeOS')\n\t\tOSVERSION=\"$(uname -r | sed 's/^[A-Z]//' | cut -b 1)\" ;;\n\n\t'CHORUS')\n\t\tOSVERSION=\"5\" ;;\n\n\t'eCOS')\n\t\tOSVERSION=\"1\" ;;\n\n\t# PHUX returns the version as something like 'B.11.11', so we have to\n\t# carefully extract the thing that looks most like a version number from\n\t# this.  Coming up with a regex for this (as for the Slowaris version\n\t# extraction) is a bit too complex, so we use pattern-matching for one-\n\t# and two-digit version values.\n\t'HP-UX')\n\t\tcase \"$(uname -r)\" in\n\t\t\t*.0?.*)\n\t\t\t\tOSVERSION=\"$(uname -r | tr -d '[A-Za-z*]\\.' | cut -c 2)\" ;;\n\t\t\t*.1?.*)\n\t\t\t\tOSVERSION=\"$(uname -r | tr -d '[A-Za-z*]\\.' | cut -c 1,2)\" ;;\n\t\tesac ;;\n\n\t'MinGW')\n\t\tOSVERSION=\"5\" ;;\n\n\t'PalmOS'|'PalmOS-PRC')\n\t\tOSVERSION=\"6\" ;;\n\n\t# QNX uses -v instead of -r for the version, and also has a broken 'cut'.\n\t'QNX')\n\t\tOSVERSION=\"$(uname -v | sed 's/^[A-Z]//' | cut -c 1)\" ;;\n\n\t# Slowaris uses bizarre version numbering, going up to (SunOS) 4.x\n\t# normally, then either using (Slowaris) 2.5/2.6/2.7 to mean Solaris\n\t# 5/6/7, or using (at least) 5.7 to also mean Solaris 7.  After\n\t# Solaris 8 it's more consistent (although still weird), with the\n\t# version numbers being 5.8, 5.9, 5.10.  To handle this mess we check\n\t# for versions below 5.x, which are handled normally, and above that\n\t# use a complex regex to derive the version number.\n\t#\n\t# As with many other aspects of Slowaris, its shell is too antedeluvian\n\t# to recognise the \"$( ... )\" syntax, so we have to use the ` ... `\n\t# syntax instead.\n\t'SunOS')\n\t\tif [ `uname -r | cut -b 1` -lt 5 ] ; then\n\t\t\tOSVERSION=`uname -r | cut -b 1` ;\n\t\telse\n\t\t\tOSVERSION=`uname -r | sed -e 's/[0-9]*\\.\\([0-9]*\\).*/\\1/'` ;\n\t\tfi ;;\n\n\t'ucLinux')\n\t\tOSVERSION=\"2\" ;;\n\n\t'UCOS')\n\t\tOSVERSION=\"2\" ;;\n\n\t'VxWorks')\n\t\tOSVERSION=\"1\" ;;\n\n\t'XMK')\n\t\tOSVERSION=\"3\" ;;\n\n\t# Some Unix variants have version numbers (or pseudo-version-numbers)\n\t# greater than ten, so instead of the basic $(uname -r | cut -c 1) we\n\t# have to check for multi-digit groups as the version number.\n\t*)\n\t\tOSVERSION=\"$(uname -r | grep -E -o '[0-9]+' | head -1)\" ;;\nesac\necho \"$OSVERSION\"\n"
  },
  {
    "path": "deps/cl345/tools/patterns.sed",
    "content": "/#include/! s/MD5_/CRYPT_MD5_/g\n/#include/! s/md5_/CRYPT_md5_/g\n/#include/! s/SHA1_/CRYPT_SHA1_/g\n/#include/! s/RIPEMD160_/CRYPT_RIPEMD160_/g\n/#include/! s/ripemd160_/CRYPT_ripemd160_/g\n/#include/! s/RC4/CRYPT_RC4/g\n/#include/! s/idea_/CRYPT_idea_/g\n/#include/! s/BF_/CRYPT_BF_/g\n/#include/! s/CAST_/CRYPT_CAST_/g\n/#include/! s/BN_/CRYPT_BN_/g\n/#include/! s/bn_/CRYPT_bn_/g\n/#include/! s/zlibVersion/CRYPT_zlibVersion/g\n/#include/! s/zlibCompileFlags/CRYPT_zlibCompileFlags/g\n/#include/! s/deflate/CRYPT_deflate/g\n/#include/! s/inflate/CRYPT_inflate/g\n/#include/! s/compress/CRYPT_compress/g\n/#include/! s/uncompress/CRYPT_uncompress/g\n/#include/! s/gz/CRYPT_gz/g\n/#include/! s/adler32/CRYPT_adler32/g\n/#include/! s/crc32/CRYPT_crc32/g\n/#include/! s/t_##m##n/CRYPT_t_##m##n/g\n/#include/! s/ec_GF/CRYPT_ec_GF/g\n"
  },
  {
    "path": "deps/cl345/tools/rename.sh",
    "content": "#!/bin/sh\n# Move all OpenSSL symbols into their own namespace to avoid conflicts if\n# linking with both cryptlib and OpenSSL.  The Mac version of sed is somewhat\n# special and needs its own custom invocation.  In addition since a few of\n# the test files have non-ASCII character sets and that also upsets the Mac\n# sed, we have to switch to 8859-1 for those.  We use en_US because it's\n# likely to be present on most systems.\n\nreplace_patterns() {\n    echo $1\n    if file $1 | grep --quiet \"ISO-8859\"; then\n        if [ \"$(uname)\" = \"Darwin\" ] ; then\n            LANG=en_US.iso88591 sed -i '' -f tools/patterns.sed $1\n        else\n            LANG=en_US.iso88591 sed -i -f tools/patterns.sed $1\n        fi\n    else\n        if [ \"$(uname)\" = \"Darwin\" ] ; then\n            LANG=C sed -i '' -f tools/patterns.sed $1\n        else\n            LANG=C sed -i -f tools/patterns.sed $1\n        fi\n    fi\n}\n\nexport -f replace_patterns\n\nfind ./ -name '*.h' -type f -exec bash -c 'replace_patterns \"$0\"' {} \\;\nfind ./ -name '*.c' -type f -exec bash -c 'replace_patterns \"$0\"' {} \\;\n"
  },
  {
    "path": "deps/cl345/tools/xcode.sh",
    "content": "#!/bin/sh\n# Find paths and names for various Xcode development tools.  This is\n# sufficiently complex, and changes frequently enough, that Apple provides\n# a tool \"xcrun\" to query the system for various Xcode-related names and\n# paths.  We either pass the output of this back to the caller or extract\n# what's being requested from something that xcrun gives us.\n#\n# Usage: xcode.sh servicename [sdkname]\n\nRESPONSE=\"\"\nSERVICENAME=\"\"\nSDKNAME=\"\"\n\n# Make sure that we've been given either a single argument consisting of the\n# requested service name or the service name and an SDK name.\n\nif [ -z \"$1\" ] ; then\n\techo \"Usage: $0 servicename [sdkname]\" >&2 ;\n\texit 1 ;\nfi\nSERVICENAME=$1\nif [ $# -eq 2 ] ; then\n\tSDKNAME=\"--sdk $2\" ;\nfi\n\n# Find the path to the SDK tools.  xcrun looks for an executable, not a\n# directory name, so we look for cc and then strip back the last component\n# to get the path to cc, which is also the path to the other tools.\n\nIOS_TOOLS_PATH=\"$(xcrun $SDKNAME -find cc | sed 's%/[^/]*$%/%')\"\n\n# Report the requested Xcode service/information type.\n\ncase $SERVICENAME in\n\t'ar')\n\t\tRESPONSE=\"$(xcrun $SDKNAME -find ar)\" ;;\n\n\t'bitcode-arg')\n\t\t# Return the command-line argument used for embedding bitcode,\n\t\t# (LLVM IR that's JIT-compiled to the appropriate iOS platform when\n\t\t# run).  This option isn't always available so we extract it from\n\t\t# the LLVM help page by searching for the specific string\n\t\t# \"embed-bitcode \" (note the space, since embed-bitcode-xxxx's also\n\t\t# exist) and returning it if the compiler documents its support.\n\t\tRESPONSE=\"$($IOS_TOOLS_PATH/cc --help | grep \"embed-bitcode \" | sed 's/^[[:space:]]*//' | sed 's/ .*//')\" ;;\n\n\t'cc')\n\t\tRESPONSE=\"$(xcrun $SDKNAME -find cc)\" ;;\n\n\t'ld')\n\t\tRESPONSE=\"$(xcrun $SDKNAME -find ld)\" ;;\n\n\t'osversion')\n\t\tRESPONSE=\"$(xcrun $SDKNAME --show-sdk-version | sed 's/[.].*//')\" ;;\n\n\t'strip')\n\t\tRESPONSE=\"$(xcrun $SDKNAME -find strip)\" ;;\n\n\t'sysroot')\n\t\tRESPONSE=\"$(xcrun $SDKNAME --show-sdk-path)\" ;;\n\n\t'sdkversion')\n\t\tRESPONSE=\"$(xcrun $SDKNAME --show-sdk-version)\" ;;\n\n\t*)\n\t\techo \"Unknown service $SERVICENAME\" ;\n\t\texit 1 ;;\nesac\n\n# Finally, report what we've found\n\necho \"$RESPONSE\"\n"
  },
  {
    "path": "deps/cl345/ubsan_blacklist.txt",
    "content": "# The SHA-2 code relies on bits being shifted off the end of a word\nsrc:crypt/sha2.c\n"
  },
  {
    "path": "deps/cl345/zlib/adler32.c",
    "content": "/* adler32.c -- compute the Adler-32 checksum of a data stream\n * Copyright (C) 1995-2011, 2016 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#if defined( __MVS__ )\t/* pcg */\n  /* MVS control section (CSECT) names default to the file name and cannot\n\t match any extern function name in the file.  This only applies to the\n\t CSECT compiler option.  Without a csect name, when maintenance is\n\t applied to an MVS program the newly introduced csect is ordered ahead\n\t of the previos csects.  With csect names, the new csect replaces the\n\t old csect.  So without csect names, as maintenance is applied\n\t throughout the life of the executable, the executable size\n\t continually increases--not a good thing.\n\n\t These files required the pragma since they contained external function\n\t names that matched the file names, which is the default csect name\n\t generated by the compiler with the csect option.  You cannot have the\n\t same externally visible name defined for two different entities */\n  #pragma csect( CODE, \"adler32C\" )\n  #pragma csect( STATIC, \"adler32S\" )\n  #pragma csect( TEST, \"adler32T\" )\n#endif /* __MVS__ */\n\n#define ZLIB_INTERNAL\t/* pcg */\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n#else\n  #include \"zlib/zutil.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\nlocal uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));\n\n#define BASE 65521U     /* largest prime smaller than 65536 */\n#define NMAX 5552\n/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */\n\n#define DO1(buf,i)  {adler += (buf)[i]; sum2 += adler;}\n#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);\n#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);\n#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);\n#define DO16(buf)   DO8(buf,0); DO8(buf,8);\n\n/* use NO_DIVIDE if your processor does not do division in hardware --\n   try it both ways to see which is faster */\n#ifdef NO_DIVIDE\n/* note that this assumes BASE is 65521, where 65536 % 65521 == 15\n   (thank you to John Reiser for pointing this out) */\n#  define CHOP(a) \\\n    do { \\\n        unsigned long tmp = a >> 16; \\\n        a &= 0xffffUL; \\\n        a += (tmp << 4) - tmp; \\\n    } while (0)\n#  define MOD28(a) \\\n    do { \\\n        CHOP(a); \\\n        if (a >= BASE) a -= BASE; \\\n    } while (0)\n#  define MOD(a) \\\n    do { \\\n        CHOP(a); \\\n        MOD28(a); \\\n    } while (0)\n#  define MOD63(a) \\\n    do { /* this assumes a is not negative */ \\\n        z_off64_t tmp = a >> 32; \\\n        a &= 0xffffffffL; \\\n        a += (tmp << 8) - (tmp << 5) + tmp; \\\n        tmp = a >> 16; \\\n        a &= 0xffffL; \\\n        a += (tmp << 4) - tmp; \\\n        tmp = a >> 16; \\\n        a &= 0xffffL; \\\n        a += (tmp << 4) - tmp; \\\n        if (a >= BASE) a -= BASE; \\\n    } while (0)\n#else\n#  define MOD(a) a %= BASE\n#  define MOD28(a) a %= BASE\n#  define MOD63(a) a %= BASE\n#endif\n\n/* ========================================================================= */\nuLong ZEXPORT adler32_z( uLong adler, const Bytef *buf, z_size_t len )\t/* pcg */\n{\n    unsigned long sum2;\n    unsigned n;\n\n    /* split Adler-32 into component sums */\n    sum2 = (adler >> 16) & 0xffff;\n    adler &= 0xffff;\n\n    /* in case user likes doing a byte at a time, keep it fast */\n    if (len == 1) {\n        adler += buf[0];\n        if (adler >= BASE)\n            adler -= BASE;\n        sum2 += adler;\n        if (sum2 >= BASE)\n            sum2 -= BASE;\n        return adler | (sum2 << 16);\n    }\n\n    /* initial Adler-32 value (deferred check for len == 1 speed) */\n    if (buf == Z_NULL)\n        return 1L;\n\n    /* in case short lengths are provided, keep it somewhat fast */\n    if (len < 16) {\n        while (len--) {\n            adler += *buf++;\n            sum2 += adler;\n        }\n        if (adler >= BASE)\n            adler -= BASE;\n        MOD28(sum2);            /* only added so many BASE's */\n        return adler | (sum2 << 16);\n    }\n\n    /* do length NMAX blocks -- requires just one modulo operation */\n    while (len >= NMAX) {\n        len -= NMAX;\n        n = NMAX / 16;          /* NMAX is divisible by 16 */\n        do {\n            DO16(buf);          /* 16 sums unrolled */\n            buf += 16;\n        } while (--n);\n        MOD(adler);\n        MOD(sum2);\n    }\n\n    /* do remaining bytes (less than NMAX, still just one modulo) */\n    if (len) {                  /* avoid modulos if none remaining */\n        while (len >= 16) {\n            len -= 16;\n            DO16(buf);\n            buf += 16;\n        }\n        while (len--) {\n            adler += *buf++;\n            sum2 += adler;\n        }\n        MOD(adler);\n        MOD(sum2);\n    }\n\n    /* return recombined sums */\n    return adler | (sum2 << 16);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT adler32( uLong adler, const Bytef *buf, uInt len )\t/* pcg */\n{\n    return adler32_z(adler, buf, len);\n}\n\n/* ========================================================================= */\nlocal uLong adler32_combine_( uLong adler1, uLong adler2, z_off64_t len2 )\t\t/* pcg */\n{\n    unsigned long sum1;\n    unsigned long sum2;\n    unsigned rem;\n\n    /* for negative len, return invalid adler32 as a clue for debugging */\n    if (len2 < 0)\n        return 0xffffffffUL;\n\n    /* the derivation of this formula is left as an exercise for the reader */\n    MOD63(len2);                /* assumes len2 >= 0 */\n    rem = (unsigned)len2;\n    sum1 = adler1 & 0xffff;\n    sum2 = rem * sum1;\n    MOD(sum2);\n    sum1 += (adler2 & 0xffff) + BASE - 1;\n    sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;\n    if (sum1 >= BASE) sum1 -= BASE;\n    if (sum1 >= BASE) sum1 -= BASE;\n    if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);\n    if (sum2 >= BASE) sum2 -= BASE;\n    return sum1 | (sum2 << 16);\n}\n\n/* ========================================================================= */\nuLong ZEXPORT adler32_combine( uLong adler1, uLong adler2, z_off_t len2 )\t/* pcg */\n{\n    return adler32_combine_(adler1, adler2, len2);\n}\n\nuLong ZEXPORT adler32_combine64( uLong adler1, uLong adler2, z_off64_t len2 )\t/* pcg */\n{\n    return adler32_combine_(adler1, adler2, len2);\n}\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/deflate.c",
    "content": "/* deflate.c -- compress data using the deflation algorithm\n * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n *  ALGORITHM\n *\n *      The \"deflation\" process depends on being able to identify portions\n *      of the input text which are identical to earlier input (within a\n *      sliding window trailing behind the input currently being processed).\n *\n *      The most straightforward technique turns out to be the fastest for\n *      most input files: try all possible matches and select the longest.\n *      The key feature of this algorithm is that insertions into the string\n *      dictionary are very simple and thus fast, and deletions are avoided\n *      completely. Insertions are performed at each input character, whereas\n *      string matches are performed only when the previous match ends. So it\n *      is preferable to spend more time in matches to allow very fast string\n *      insertions and avoid deletions. The matching algorithm for small\n *      strings is inspired from that of Rabin & Karp. A brute force approach\n *      is used to find longer strings when a small match has been found.\n *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze\n *      (by Leonid Broukhis).\n *         A previous version of this file used a more sophisticated algorithm\n *      (by Fiala and Greene) which is guaranteed to run in linear amortized\n *      time, but has a larger average cost, uses more memory and is patented.\n *      However the F&G algorithm may be faster for some highly redundant\n *      files if the parameter max_chain_length (described below) is too large.\n *\n *  ACKNOWLEDGEMENTS\n *\n *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and\n *      I found it in 'freeze' written by Leonid Broukhis.\n *      Thanks to many people for bug reports and testing.\n *\n *  REFERENCES\n *\n *      Deutsch, L.P.,\"DEFLATE Compressed Data Format Specification\".\n *      Available in http://tools.ietf.org/html/rfc1951\n *\n *      A description of the Rabin and Karp algorithm is given in the book\n *         \"Algorithms\" by R. Sedgewick, Addison-Wesley, p252.\n *\n *      Fiala,E.R., and Greene,D.H.\n *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595\n *\n */\n\n/* @(#) $Id$ */\n\n#if defined( __MVS__ )\t/* pcg */\n  /* MVS control section (CSECT) names default to the file name and cannot\n\t match any extern function name in the file.  This only applies to the\n\t CSECT compiler option.  Without a csect name, when maintenance is\n\t applied to an MVS program the newly introduced csect is ordered ahead\n\t of the previos csects.  With csect names, the new csect replaces the\n\t old csect.  So without csect names, as maintenance is applied\n\t throughout the life of the executable, the executable size\n\t continually increases--not a good thing.\n\n\t These files required the pragma since they contained external function\n\t names that matched the file names, which is the default csect name\n\t generated by the compiler with the csect option.  You cannot have the\n\t same externally visible name defined for two different entities */\n  #pragma csect( CODE, \"deflateC\" )\n  #pragma csect( STATIC, \"deflateS\" )\n  #pragma csect( TEST, \"deflateT\" )\n#endif /* __MVS__ */\n\n#if defined( INC_ALL )\n  #include \"deflate.h\"\n#else\n  #include \"zlib/deflate.h\"\n#endif /* Compiler-specific includes */\n\n/* Re-enable use of malloc() - pcg */\n\n#undef Z_SOLO\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\nconst char deflate_copyright[] =\n   \" deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler \";\n/*\n  If you use the zlib library in a product, an acknowledgment is welcome\n  in the documentation of your product. If for some reason you cannot\n  include such an acknowledgment, I would appreciate that you keep this\n  copyright string in the executable of your product.\n */\n\n/* ===========================================================================\n *  Function prototypes.\n */\ntypedef enum {\n    need_more,      /* block not completed, need more input or more output */\n    block_done,     /* block flush performed */\n    finish_started, /* finish started, need only more output at next deflate */\n    finish_done     /* finish done, accept no more input or output */\n} block_state;\n\ntypedef block_state (*compress_func) OF((deflate_state *s, int flush));\n/* Compression function. Returns the block state after the call. */\n\nlocal int deflateStateCheck      OF((z_streamp strm));\nlocal void slide_hash     OF((deflate_state *s));\nlocal void fill_window    OF((deflate_state *s));\nlocal block_state deflate_stored OF((deflate_state *s, int flush));\nlocal block_state deflate_fast   OF((deflate_state *s, int flush));\n#ifndef FASTEST\nlocal block_state deflate_slow   OF((deflate_state *s, int flush));\n#endif\nlocal block_state deflate_rle    OF((deflate_state *s, int flush));\nlocal block_state deflate_huff   OF((deflate_state *s, int flush));\nlocal void lm_init        OF((deflate_state *s));\nlocal void putShortMSB    OF((deflate_state *s, uInt b));\nlocal void flush_pending  OF((z_streamp strm));\nlocal unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));\n#ifdef ASMV\n#  pragma message(\"Assembler code may have bugs -- use at your own risk\")\n      void match_init OF((void)); /* asm code initialization */\n      uInt longest_match  OF((deflate_state *s, IPos cur_match));\n#else\nlocal uInt longest_match  OF((deflate_state *s, IPos cur_match));\n#endif\n\n#ifdef ZLIB_DEBUG\nlocal  void check_match OF((deflate_state *s, IPos start, IPos match,\n                            int length));\n#endif\n\n/* ===========================================================================\n * Local data\n */\n\n#define NIL 0\n/* Tail of hash chains */\n\n#ifndef TOO_FAR\n#  define TOO_FAR 4096\n#endif\n/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */\n\n/* Values for max_lazy_match, good_match and max_chain_length, depending on\n * the desired pack level (0..9). The values given below have been tuned to\n * exclude worst case performance for pathological files. Better values may be\n * found for specific files.\n */\ntypedef struct config_s {\n   ush good_length; /* reduce lazy search above this match length */\n   ush max_lazy;    /* do not perform lazy search above this match length */\n   ush nice_length; /* quit search above this match length */\n   ush max_chain;\n   compress_func func;\n} config;\n\n#ifdef FASTEST\nlocal const config configuration_table[2] = {\n/*      good lazy nice chain */\n/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */\n/* 1 */ {4,    4,  8,    4, deflate_fast}}; /* max speed, no lazy matches */\n#else\nlocal const config configuration_table[10] = {\n/*      good lazy nice chain */\n/* 0 */ {0,    0,  0,    0, deflate_stored},  /* store only */\n/* 1 */ {4,    4,  8,    4, deflate_fast}, /* max speed, no lazy matches */\n/* 2 */ {4,    5, 16,    8, deflate_fast},\n/* 3 */ {4,    6, 32,   32, deflate_fast},\n\n/* 4 */ {4,    4, 16,   16, deflate_slow},  /* lazy matches */\n/* 5 */ {8,   16, 32,   32, deflate_slow},\n/* 6 */ {8,   16, 128, 128, deflate_slow},\n/* 7 */ {8,   32, 128, 256, deflate_slow},\n/* 8 */ {32, 128, 258, 1024, deflate_slow},\n/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */\n#endif\n\n/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4\n * For deflate_fast() (levels <= 3) good is ignored and lazy has a different\n * meaning.\n */\n\n/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */\n#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0))\n\n/* ===========================================================================\n * Update a hash value with the given input byte\n * IN  assertion: all calls to UPDATE_HASH are made with consecutive input\n *    characters, so that a running hash key can be computed from the previous\n *    key instead of complete recalculation each time.\n */\n#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)\n\n\n/* ===========================================================================\n * Insert string str in the dictionary and set match_head to the previous head\n * of the hash chain (the most recent string with same hash key). Return\n * the previous length of the hash chain.\n * If this file is compiled with -DFASTEST, the compression level is forced\n * to 1, and no hash chains are maintained.\n * IN  assertion: all calls to INSERT_STRING are made with consecutive input\n *    characters and the first MIN_MATCH bytes of str are valid (except for\n *    the last MIN_MATCH-1 bytes of the input file).\n */\n#ifdef FASTEST\n#define INSERT_STRING(s, str, match_head) \\\n   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \\\n    match_head = s->head[s->ins_h], \\\n    s->head[s->ins_h] = (Pos)(str))\n#else\n#define INSERT_STRING(s, str, match_head) \\\n   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \\\n    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \\\n    s->head[s->ins_h] = (Pos)(str))\n#endif\n\n/* ===========================================================================\n * Initialize the hash table (avoiding 64K overflow for 16 bit systems).\n * prev[] will be initialized on the fly.\n */\n#define CLEAR_HASH(s) \\\n    s->head[s->hash_size-1] = NIL; \\\n    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));\n\n/* ===========================================================================\n * Slide the hash table when sliding the window down (could be avoided with 32\n * bit values at the expense of memory usage). We slide even when level == 0 to\n * keep the hash table consistent if we switch back to level > 0 later.\n */\nlocal void slide_hash( deflate_state *s )\t/* pcg */\n{\n    unsigned n, m;\n    Posf *p;\n    uInt wsize = s->w_size;\n\n    n = s->hash_size;\n    p = &s->head[n];\n    do {\n        m = *--p;\n        *p = (Pos)(m >= wsize ? m - wsize : NIL);\n    } while (--n);\n    n = wsize;\n#ifndef FASTEST\n    p = &s->prev[n];\n    do {\n        m = *--p;\n        *p = (Pos)(m >= wsize ? m - wsize : NIL);\n        /* If n is not on any hash chain, prev[n] is garbage but\n         * its value will never be used.\n         */\n    } while (--n);\n#endif\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateInit_( z_streamp strm, int level, const char *version, int stream_size )\t/* pcg */\n{\n    return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,\n                         Z_DEFAULT_STRATEGY, version, stream_size);\n    /* To do: ignore strm->next_in if we use it as window */\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateInit2_( z_streamp strm, int  level, int  method, int  windowBits,\n    int  memLevel, int  strategy, const char *version, int stream_size )\t/* pcg */\n{\n    deflate_state *s;\n    int wrap = 1;\n    static const char my_version[] = ZLIB_VERSION;\n\n    ushf *overlay;\n    /* We overlay pending_buf and d_buf+l_buf. This works since the average\n     * output size for (length,distance) codes is <= 24 bits.\n     */\n\n    if (version == Z_NULL || version[0] != my_version[0] ||\n        stream_size != sizeof(z_stream)) {\n        return Z_VERSION_ERROR;\n    }\n    if (strm == Z_NULL) return Z_STREAM_ERROR;\n\n    strm->msg = Z_NULL;\n    if (strm->zalloc == (alloc_func)0) {\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zalloc = zcalloc;\n        strm->opaque = (voidpf)0;\n#endif\n    }\n    if (strm->zfree == (free_func)0)\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zfree = zcfree;\n#endif\n\n#ifdef FASTEST\n    if (level != 0) level = 1;\n#else\n    if (level == Z_DEFAULT_COMPRESSION) level = 6;\n#endif\n\n    if (windowBits < 0) { /* suppress zlib wrapper */\n        wrap = 0;\n        windowBits = -windowBits;\n    }\n#ifdef GZIP\n    else if (windowBits > 15) {\n        wrap = 2;       /* write gzip wrapper instead */\n        windowBits -= 16;\n    }\n#endif\n    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||\n        windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||\n        strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) {\n        return Z_STREAM_ERROR;\n    }\n    if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */\n    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));\n    if (s == Z_NULL) return Z_MEM_ERROR;\n    strm->state = (struct internal_state FAR *)s;\n    s->strm = strm;\n    s->status = INIT_STATE;     /* to pass state test in deflateReset() */\n\n    s->wrap = wrap;\n    s->gzhead = Z_NULL;\n    s->w_bits = (uInt)windowBits;\n    s->w_size = 1 << s->w_bits;\n    s->w_mask = s->w_size - 1;\n\n    s->hash_bits = (uInt)memLevel + 7;\n    s->hash_size = 1 << s->hash_bits;\n    s->hash_mask = s->hash_size - 1;\n    s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);\n\n    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));\n    s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));\n    s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));\n\n    s->high_water = 0;      /* nothing written to s->window yet */\n\n    s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */\n\n    overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);\n    s->pending_buf = (uchf *) overlay;\n    s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);\n\n    if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||\n        s->pending_buf == Z_NULL) {\n        s->status = FINISH_STATE;\n        strm->msg = ERR_MSG(Z_MEM_ERROR);\n        deflateEnd (strm);\n        return Z_MEM_ERROR;\n    }\n    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);\n    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;\n\n    s->level = level;\n    s->strategy = strategy;\n    s->method = (Byte)method;\n\n    return deflateReset(strm);\n}\n\n/* =========================================================================\n * Check for a valid deflate stream state. Return 0 if ok, 1 if not.\n */\nlocal int deflateStateCheck ( z_streamp strm )\t/* pcg */\n{\n    deflate_state *s;\n    if (strm == Z_NULL ||\n        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)\n        return 1;\n    s = strm->state;\n    if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE &&\n#ifdef GZIP\n                                           s->status != GZIP_STATE &&\n#endif\n                                           s->status != EXTRA_STATE &&\n                                           s->status != NAME_STATE &&\n                                           s->status != COMMENT_STATE &&\n                                           s->status != HCRC_STATE &&\n                                           s->status != BUSY_STATE &&\n                                           s->status != FINISH_STATE))\n        return 1;\n    return 0;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateSetDictionary ( z_streamp strm, const Bytef *dictionary, uInt  dictLength )\t/* pcg */\n{\n    deflate_state *s;\n    uInt str, n;\n    int wrap;\n    unsigned avail;\n    z_const unsigned char *next;\n\n    if (deflateStateCheck(strm) || dictionary == Z_NULL)\n        return Z_STREAM_ERROR;\n    s = strm->state;\n    wrap = s->wrap;\n    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)\n        return Z_STREAM_ERROR;\n\n    /* when using zlib wrappers, compute Adler-32 for provided dictionary */\n    if (wrap == 1)\n        strm->adler = adler32(strm->adler, dictionary, dictLength);\n    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */\n\n    /* if dictionary would fill window, just replace the history */\n    if (dictLength >= s->w_size) {\n        if (wrap == 0) {            /* already empty otherwise */\n            CLEAR_HASH(s);\n            s->strstart = 0;\n            s->block_start = 0L;\n            s->insert = 0;\n        }\n        dictionary += dictLength - s->w_size;  /* use the tail */\n        dictLength = s->w_size;\n    }\n\n    /* insert dictionary into window and hash */\n    avail = strm->avail_in;\n    next = strm->next_in;\n    strm->avail_in = dictLength;\n    strm->next_in = (z_const Bytef *)dictionary;\n    fill_window(s);\n    while (s->lookahead >= MIN_MATCH) {\n        str = s->strstart;\n        n = s->lookahead - (MIN_MATCH-1);\n        do {\n            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);\n#ifndef FASTEST\n            s->prev[str & s->w_mask] = s->head[s->ins_h];\n#endif\n            s->head[s->ins_h] = (Pos)str;\n            str++;\n        } while (--n);\n        s->strstart = str;\n        s->lookahead = MIN_MATCH-1;\n        fill_window(s);\n    }\n    s->strstart += s->lookahead;\n    s->block_start = (long)s->strstart;\n    s->insert = s->lookahead;\n    s->lookahead = 0;\n    s->match_length = s->prev_length = MIN_MATCH-1;\n    s->match_available = 0;\n    strm->next_in = next;\n    strm->avail_in = avail;\n    s->wrap = wrap;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateGetDictionary ( z_streamp strm, Bytef *dictionary, uInt  *dictLength )\t/* pcg */\n{\n    deflate_state *s;\n    uInt len;\n\n    if (deflateStateCheck(strm))\n        return Z_STREAM_ERROR;\n    s = strm->state;\n    len = s->strstart + s->lookahead;\n    if (len > s->w_size)\n        len = s->w_size;\n    if (dictionary != Z_NULL && len)\n        zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len);\n    if (dictLength != Z_NULL)\n        *dictLength = len;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateResetKeep ( z_streamp strm )\t/* pcg */\n{\n    deflate_state *s;\n\n    if (deflateStateCheck(strm)) {\n        return Z_STREAM_ERROR;\n    }\n\n    strm->total_in = strm->total_out = 0;\n    strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */\n    strm->data_type = Z_UNKNOWN;\n\n    s = (deflate_state *)strm->state;\n    s->pending = 0;\n    s->pending_out = s->pending_buf;\n\n    if (s->wrap < 0) {\n        s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */\n    }\n    s->status =\n#ifdef GZIP\n        s->wrap == 2 ? GZIP_STATE :\n#endif\n        s->wrap ? INIT_STATE : BUSY_STATE;\n    strm->adler =\n#ifdef GZIP\n        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :\n#endif\n        adler32(0L, Z_NULL, 0);\n    s->last_flush = Z_NO_FLUSH;\n\n    _tr_init(s);\n\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateReset ( z_streamp strm )\n{\n    int ret;\n\n    ret = deflateResetKeep(strm);\n    if (ret == Z_OK)\n        lm_init(strm->state);\n    return ret;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateSetHeader ( z_streamp strm, gz_headerp head )\t/* pcg */\n{\n    if (deflateStateCheck(strm) || strm->state->wrap != 2)\n        return Z_STREAM_ERROR;\n    strm->state->gzhead = head;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflatePending ( z_streamp strm, unsigned *pending, int *bits )\t/* pcg */\n{\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    if (pending != Z_NULL)\n        *pending = strm->state->pending;\n    if (bits != Z_NULL)\n        *bits = strm->state->bi_valid;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflatePrime ( z_streamp strm, int bits, int value )\t/* pcg */\n{\n    deflate_state *s;\n    int put;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))\n        return Z_BUF_ERROR;\n    do {\n        put = Buf_size - s->bi_valid;\n        if (put > bits)\n            put = bits;\n        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);\n        s->bi_valid += put;\n        _tr_flush_bits(s);\n        value >>= put;\n        bits -= put;\n    } while (bits);\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateParams( z_streamp strm, int level, int strategy )\t/* pcg */\n{\n    deflate_state *s;\n    compress_func func;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n\n#ifdef FASTEST\n    if (level != 0) level = 1;\n#else\n    if (level == Z_DEFAULT_COMPRESSION) level = 6;\n#endif\n    if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {\n        return Z_STREAM_ERROR;\n    }\n    func = configuration_table[s->level].func;\n\n    if ((strategy != s->strategy || func != configuration_table[level].func) &&\n        s->high_water) {\n        /* Flush the last buffer: */\n        int err = deflate(strm, Z_BLOCK);\n        if (err == Z_STREAM_ERROR)\n            return err;\n        if (strm->avail_out == 0)\n            return Z_BUF_ERROR;\n    }\n    if (s->level != level) {\n        if (s->level == 0 && s->matches != 0) {\n            if (s->matches == 1)\n                slide_hash(s);\n            else\n                CLEAR_HASH(s);\n            s->matches = 0;\n        }\n        s->level = level;\n        s->max_lazy_match   = configuration_table[level].max_lazy;\n        s->good_match       = configuration_table[level].good_length;\n        s->nice_match       = configuration_table[level].nice_length;\n        s->max_chain_length = configuration_table[level].max_chain;\n    }\n    s->strategy = strategy;\n    return Z_OK;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateTune( z_streamp strm, int good_length, int max_lazy, \n    int nice_length, int max_chain )\t/* pcg */\n{\n    deflate_state *s;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n    s = strm->state;\n    s->good_match = (uInt)good_length;\n    s->max_lazy_match = (uInt)max_lazy;\n    s->nice_match = nice_length;\n    s->max_chain_length = (uInt)max_chain;\n    return Z_OK;\n}\n\n/* =========================================================================\n * For the default windowBits of 15 and memLevel of 8, this function returns\n * a close to exact, as well as small, upper bound on the compressed size.\n * They are coded as constants here for a reason--if the #define's are\n * changed, then this function needs to be changed as well.  The return\n * value for 15 and 8 only works for those exact settings.\n *\n * For any setting other than those defaults for windowBits and memLevel,\n * the value returned is a conservative worst case for the maximum expansion\n * resulting from using fixed blocks instead of stored blocks, which deflate\n * can emit on compressed data for some combinations of the parameters.\n *\n * This function could be more sophisticated to provide closer upper bounds for\n * every combination of windowBits and memLevel.  But even the conservative\n * upper bound of about 14% expansion does not seem onerous for output buffer\n * allocation.\n */\nuLong ZEXPORT deflateBound( z_streamp strm, uLong sourceLen )\t/* pcg */\n{\n    deflate_state *s;\n    uLong complen, wraplen;\n\n    /* conservative upper bound for compressed data */\n    complen = sourceLen +\n              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;\n\n    /* if can't get parameters, return conservative bound plus zlib wrapper */\n    if (deflateStateCheck(strm))\n        return complen + 6;\n\n    /* compute wrapper length */\n    s = strm->state;\n    switch (s->wrap) {\n    case 0:                                 /* raw deflate */\n        wraplen = 0;\n        break;\n    case 1:                                 /* zlib wrapper */\n        wraplen = 6 + (s->strstart ? 4 : 0);\n        break;\n#ifdef GZIP\n    case 2:                                 /* gzip wrapper */\n        wraplen = 18;\n        if (s->gzhead != Z_NULL) {          /* user-supplied gzip header */\n            Bytef *str;\n            if (s->gzhead->extra != Z_NULL)\n                wraplen += 2 + s->gzhead->extra_len;\n            str = s->gzhead->name;\n            if (str != Z_NULL)\n                do {\n                    wraplen++;\n                } while (*str++);\n            str = s->gzhead->comment;\n            if (str != Z_NULL)\n                do {\n                    wraplen++;\n                } while (*str++);\n            if (s->gzhead->hcrc)\n                wraplen += 2;\n        }\n        break;\n#endif\n    default:                                /* for compiler happiness */\n        wraplen = 6;\n    }\n\n    /* if not default parameters, return conservative bound */\n    if (s->w_bits != 15 || s->hash_bits != 8 + 7)\n        return complen + wraplen;\n\n    /* default settings: return tight bound for that case */\n    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +\n           (sourceLen >> 25) + 13 - 6 + wraplen;\n}\n\n/* =========================================================================\n * Put a short in the pending buffer. The 16-bit value is put in MSB order.\n * IN assertion: the stream state is correct and there is enough room in\n * pending_buf.\n */\nlocal void putShortMSB ( deflate_state *s, uInt b )\t/* pcg */\n{\n    put_byte(s, (Byte)(b >> 8));\n    put_byte(s, (Byte)(b & 0xff));\n}\n\n/* =========================================================================\n * Flush as much pending output as possible. All deflate() output, except for\n * some deflate_stored() output, goes through this function so some\n * applications may wish to modify it to avoid allocating a large\n * strm->next_out buffer and copying into it. (See also read_buf()).\n */\nlocal void flush_pending( z_streamp strm )\t/* pcg */\n{\n    unsigned len;\n    deflate_state *s = strm->state;\n\n    _tr_flush_bits(s);\n    len = s->pending;\n    if (len > strm->avail_out) len = strm->avail_out;\n    if (len == 0) return;\n\n    zmemcpy(strm->next_out, s->pending_out, len);\n    strm->next_out  += len;\n    s->pending_out  += len;\n    strm->total_out += len;\n    strm->avail_out -= len;\n    s->pending      -= len;\n    if (s->pending == 0) {\n        s->pending_out = s->pending_buf;\n    }\n}\n\n/* ===========================================================================\n * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1].\n */\n#define HCRC_UPDATE(beg) \\\n    do { \\\n        if (s->gzhead->hcrc && s->pending > (beg)) \\\n            strm->adler = crc32(strm->adler, s->pending_buf + (beg), \\\n                                s->pending - (beg)); \\\n    } while (0)\n\n/* ========================================================================= */\nint ZEXPORT deflate ( z_streamp strm, int flush )\t/* pcg */\n{\n    int old_flush; /* value of flush param for previous deflate call */\n    deflate_state *s;\n\n    if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) {\n        return Z_STREAM_ERROR;\n    }\n    s = strm->state;\n\n    if (strm->next_out == Z_NULL ||\n        (strm->avail_in != 0 && strm->next_in == Z_NULL) ||\n        (s->status == FINISH_STATE && flush != Z_FINISH)) {\n        ERR_RETURN(strm, Z_STREAM_ERROR);\n    }\n    if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);\n\n    old_flush = s->last_flush;\n    s->last_flush = flush;\n\n    /* Flush as much pending output as possible */\n    if (s->pending != 0) {\n        flush_pending(strm);\n        if (strm->avail_out == 0) {\n            /* Since avail_out is 0, deflate will be called again with\n             * more output space, but possibly with both pending and\n             * avail_in equal to zero. There won't be anything to do,\n             * but this is not an error situation so make sure we\n             * return OK instead of BUF_ERROR at next call of deflate:\n             */\n            s->last_flush = -1;\n            return Z_OK;\n        }\n\n    /* Make sure there is something to do and avoid duplicate consecutive\n     * flushes. For repeated and useless calls with Z_FINISH, we keep\n     * returning Z_STREAM_END instead of Z_BUF_ERROR.\n     */\n    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&\n               flush != Z_FINISH) {\n        ERR_RETURN(strm, Z_BUF_ERROR);\n    }\n\n    /* User must not provide more input after the first FINISH: */\n    if (s->status == FINISH_STATE && strm->avail_in != 0) {\n        ERR_RETURN(strm, Z_BUF_ERROR);\n    }\n\n    /* Write the header */\n    if (s->status == INIT_STATE) {\n        /* zlib header */\n        uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;\n        uInt level_flags;\n\n        if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)\n            level_flags = 0;\n        else if (s->level < 6)\n            level_flags = 1;\n        else if (s->level == 6)\n            level_flags = 2;\n        else\n            level_flags = 3;\n        header |= (level_flags << 6);\n        if (s->strstart != 0) header |= PRESET_DICT;\n        header += 31 - (header % 31);\n\n        putShortMSB(s, header);\n\n        /* Save the adler32 of the preset dictionary: */\n        if (s->strstart != 0) {\n            putShortMSB(s, (uInt)(strm->adler >> 16));\n            putShortMSB(s, (uInt)(strm->adler & 0xffff));\n        }\n        strm->adler = adler32(0L, Z_NULL, 0);\n        s->status = BUSY_STATE;\n\n        /* Compression must start with an empty pending buffer */\n        flush_pending(strm);\n        if (s->pending != 0) {\n            s->last_flush = -1;\n            return Z_OK;\n        }\n    }\n#ifdef GZIP\n    if (s->status == GZIP_STATE) {\n        /* gzip header */\n        strm->adler = crc32(0L, Z_NULL, 0);\n        put_byte(s, 31);\n        put_byte(s, 139);\n        put_byte(s, 8);\n        if (s->gzhead == Z_NULL) {\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, 0);\n            put_byte(s, s->level == 9 ? 2 :\n                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?\n                      4 : 0));\n            put_byte(s, OS_CODE);\n            s->status = BUSY_STATE;\n\n            /* Compression must start with an empty pending buffer */\n            flush_pending(strm);\n            if (s->pending != 0) {\n                s->last_flush = -1;\n                return Z_OK;\n            }\n        }\n        else {\n            put_byte(s, (s->gzhead->text ? 1 : 0) +\n                     (s->gzhead->hcrc ? 2 : 0) +\n                     (s->gzhead->extra == Z_NULL ? 0 : 4) +\n                     (s->gzhead->name == Z_NULL ? 0 : 8) +\n                     (s->gzhead->comment == Z_NULL ? 0 : 16)\n                     );\n            put_byte(s, (Byte)(s->gzhead->time & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));\n            put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));\n            put_byte(s, s->level == 9 ? 2 :\n                     (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?\n                      4 : 0));\n            put_byte(s, s->gzhead->os & 0xff);\n            if (s->gzhead->extra != Z_NULL) {\n                put_byte(s, s->gzhead->extra_len & 0xff);\n                put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);\n            }\n            if (s->gzhead->hcrc)\n                strm->adler = crc32(strm->adler, s->pending_buf,\n                                    s->pending);\n            s->gzindex = 0;\n            s->status = EXTRA_STATE;\n        }\n    }\n    if (s->status == EXTRA_STATE) {\n        if (s->gzhead->extra != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex;\n            while (s->pending + left > s->pending_buf_size) {\n                uInt copy = s->pending_buf_size - s->pending;\n                zmemcpy(s->pending_buf + s->pending,\n                        s->gzhead->extra + s->gzindex, copy);\n                s->pending = s->pending_buf_size;\n                HCRC_UPDATE(beg);\n                s->gzindex += copy;\n                flush_pending(strm);\n                if (s->pending != 0) {\n                    s->last_flush = -1;\n                    return Z_OK;\n                }\n                beg = 0;\n                left -= copy;\n            }\n            zmemcpy(s->pending_buf + s->pending,\n                    s->gzhead->extra + s->gzindex, left);\n            s->pending += left;\n            HCRC_UPDATE(beg);\n            s->gzindex = 0;\n        }\n        s->status = NAME_STATE;\n    }\n    if (s->status == NAME_STATE) {\n        if (s->gzhead->name != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            int val;\n            do {\n                if (s->pending == s->pending_buf_size) {\n                    HCRC_UPDATE(beg);\n                    flush_pending(strm);\n                    if (s->pending != 0) {\n                        s->last_flush = -1;\n                        return Z_OK;\n                    }\n                    beg = 0;\n                }\n                val = s->gzhead->name[s->gzindex++];\n                put_byte(s, val);\n            } while (val != 0);\n            HCRC_UPDATE(beg);\n            s->gzindex = 0;\n        }\n        s->status = COMMENT_STATE;\n    }\n    if (s->status == COMMENT_STATE) {\n        if (s->gzhead->comment != Z_NULL) {\n            ulg beg = s->pending;   /* start of bytes to update crc */\n            int val;\n            do {\n                if (s->pending == s->pending_buf_size) {\n                    HCRC_UPDATE(beg);\n                    flush_pending(strm);\n                    if (s->pending != 0) {\n                        s->last_flush = -1;\n                        return Z_OK;\n                    }\n                    beg = 0;\n                }\n                val = s->gzhead->comment[s->gzindex++];\n                put_byte(s, val);\n            } while (val != 0);\n            HCRC_UPDATE(beg);\n        }\n        s->status = HCRC_STATE;\n    }\n    if (s->status == HCRC_STATE) {\n        if (s->gzhead->hcrc) {\n            if (s->pending + 2 > s->pending_buf_size) {\n                flush_pending(strm);\n                if (s->pending != 0) {\n                    s->last_flush = -1;\n                    return Z_OK;\n                }\n            }\n            put_byte(s, (Byte)(strm->adler & 0xff));\n            put_byte(s, (Byte)((strm->adler >> 8) & 0xff));\n            strm->adler = crc32(0L, Z_NULL, 0);\n        }\n        s->status = BUSY_STATE;\n\n        /* Compression must start with an empty pending buffer */\n        flush_pending(strm);\n        if (s->pending != 0) {\n            s->last_flush = -1;\n            return Z_OK;\n        }\n    }\n#endif\n\n    /* Start a new block or continue the current one.\n     */\n    if (strm->avail_in != 0 || s->lookahead != 0 ||\n        (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {\n        block_state bstate;\n\n        bstate = s->level == 0 ? deflate_stored(s, flush) :\n                 s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :\n                 s->strategy == Z_RLE ? deflate_rle(s, flush) :\n                 (*(configuration_table[s->level].func))(s, flush);\n\n        if (bstate == finish_started || bstate == finish_done) {\n            s->status = FINISH_STATE;\n        }\n        if (bstate == need_more || bstate == finish_started) {\n            if (strm->avail_out == 0) {\n                s->last_flush = -1; /* avoid BUF_ERROR next call, see above */\n            }\n            return Z_OK;\n            /* If flush != Z_NO_FLUSH && avail_out == 0, the next call\n             * of deflate should use the same flush parameter to make sure\n             * that the flush is complete. So we don't have to output an\n             * empty block here, this will be done at next call. This also\n             * ensures that for a very small output buffer, we emit at most\n             * one empty block.\n             */\n        }\n        if (bstate == block_done) {\n            if (flush == Z_PARTIAL_FLUSH) {\n                _tr_align(s);\n            } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */\n                _tr_stored_block(s, (char*)0, 0L, 0);\n                /* For a full flush, this empty block will be recognized\n                 * as a special marker by inflate_sync().\n                 */\n                if (flush == Z_FULL_FLUSH) {\n                    CLEAR_HASH(s);             /* forget history */\n                    if (s->lookahead == 0) {\n                        s->strstart = 0;\n                        s->block_start = 0L;\n                        s->insert = 0;\n                    }\n                }\n            }\n            flush_pending(strm);\n            if (strm->avail_out == 0) {\n              s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */\n              return Z_OK;\n            }\n        }\n    }\n\n    if (flush != Z_FINISH) return Z_OK;\n    if (s->wrap <= 0) return Z_STREAM_END;\n\n    /* Write the trailer */\n#ifdef GZIP\n    if (s->wrap == 2) {\n        put_byte(s, (Byte)(strm->adler & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 8) & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 16) & 0xff));\n        put_byte(s, (Byte)((strm->adler >> 24) & 0xff));\n        put_byte(s, (Byte)(strm->total_in & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));\n        put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));\n    }\n    else\n#endif\n    {\n        putShortMSB(s, (uInt)(strm->adler >> 16));\n        putShortMSB(s, (uInt)(strm->adler & 0xffff));\n    }\n    flush_pending(strm);\n    /* If avail_out is zero, the application will call deflate again\n     * to flush the rest.\n     */\n    if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */\n    return s->pending != 0 ? Z_OK : Z_STREAM_END;\n}\n\n/* ========================================================================= */\nint ZEXPORT deflateEnd ( z_streamp strm )\t/* pcg */\n{\n    int status;\n\n    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;\n\n    status = strm->state->status;\n\n    /* Deallocate in reverse order of allocations: */\n    TRY_FREE(strm, strm->state->pending_buf);\n    TRY_FREE(strm, strm->state->head);\n    TRY_FREE(strm, strm->state->prev);\n    TRY_FREE(strm, strm->state->window);\n\n    ZFREE(strm, strm->state);\n    strm->state = Z_NULL;\n\n    return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;\n}\n\n/* =========================================================================\n * Copy the source state to the destination state.\n * To simplify the source, this is not supported for 16-bit MSDOS (which\n * doesn't have enough memory anyway to duplicate compression states).\n */\nint ZEXPORT deflateCopy ( z_streamp dest, z_streamp source )\t/* pcg */\n{\n#ifdef MAXSEG_64K\n    return Z_STREAM_ERROR;\n#else\n    deflate_state *ds;\n    deflate_state *ss;\n    ushf *overlay;\n\n\n    if (deflateStateCheck(source) || dest == Z_NULL) {\n        return Z_STREAM_ERROR;\n    }\n\n    ss = source->state;\n\n    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));\n\n    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));\n    if (ds == Z_NULL) return Z_MEM_ERROR;\n    dest->state = (struct internal_state FAR *) ds;\n    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));\n    ds->strm = dest;\n\n    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));\n    ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));\n    ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));\n    overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);\n    ds->pending_buf = (uchf *) overlay;\n\n    if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||\n        ds->pending_buf == Z_NULL) {\n        deflateEnd (dest);\n        return Z_MEM_ERROR;\n    }\n    /* following zmemcpy do not work for 16-bit MSDOS */\n    zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));\n    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));\n    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));\n    zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);\n\n    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);\n    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);\n    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;\n\n    ds->l_desc.dyn_tree = ds->dyn_ltree;\n    ds->d_desc.dyn_tree = ds->dyn_dtree;\n    ds->bl_desc.dyn_tree = ds->bl_tree;\n\n    return Z_OK;\n#endif /* MAXSEG_64K */\n}\n\n/* ===========================================================================\n * Read a new buffer from the current input stream, update the adler32\n * and total number of bytes read.  All deflate() input goes through\n * this function so some applications may wish to modify it to avoid\n * allocating a large strm->next_in buffer and copying from it.\n * (See also flush_pending()).\n */\nlocal unsigned read_buf( z_streamp strm, Bytef *buf, unsigned size )\t/* pcg */\n{\n    unsigned len = strm->avail_in;\n\n    if (len > size) len = size;\n    if (len == 0) return 0;\n\n    strm->avail_in  -= len;\n\n    zmemcpy(buf, strm->next_in, len);\n    if (strm->state->wrap == 1) {\n        strm->adler = adler32(strm->adler, buf, len);\n    }\n#ifdef GZIP\n    else if (strm->state->wrap == 2) {\n        strm->adler = crc32(strm->adler, buf, len);\n    }\n#endif\n    strm->next_in  += len;\n    strm->total_in += len;\n\n    return len;\n}\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new zlib stream\n */\nlocal void lm_init ( deflate_state *s )\t/* pcg */\n{\n    s->window_size = (ulg)2L*s->w_size;\n\n    CLEAR_HASH(s);\n\n    /* Set the default configuration parameters:\n     */\n    s->max_lazy_match   = configuration_table[s->level].max_lazy;\n    s->good_match       = configuration_table[s->level].good_length;\n    s->nice_match       = configuration_table[s->level].nice_length;\n    s->max_chain_length = configuration_table[s->level].max_chain;\n\n    s->strstart = 0;\n    s->block_start = 0L;\n    s->lookahead = 0;\n    s->insert = 0;\n    s->match_length = s->prev_length = MIN_MATCH-1;\n    s->match_available = 0;\n    s->ins_h = 0;\n#ifndef FASTEST\n#ifdef ASMV\n    match_init(); /* initialize the asm code */\n#endif\n#endif\n}\n\n#ifndef FASTEST\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n * OUT assertion: the match length is not greater than s->lookahead.\n */\n#ifndef ASMV\n/* For 80x86 and 680x0, an optimized version will be provided in match.asm or\n * match.S. The code will be functionally equivalent.\n */\nlocal uInt longest_match( deflate_state *s, IPos cur_match )\t/* pcg */\n{\n    unsigned chain_length = s->max_chain_length;/* max hash chain length */\n    register Bytef *scan = s->window + s->strstart; /* current string */\n    register Bytef *match;                      /* matched string */\n    register int len;                           /* length of current match */\n    int best_len = (int)s->prev_length;         /* best match length so far */\n    int nice_match = s->nice_match;             /* stop if match long enough */\n    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\n        s->strstart - (IPos)MAX_DIST(s) : NIL;\n    /* Stop when cur_match becomes <= limit. To simplify the code,\n     * we prevent matches with the string of window index 0.\n     */\n    Posf *prev = s->prev;\n    uInt wmask = s->w_mask;\n\n#ifdef UNALIGNED_OK\n    /* Compare two bytes at a time. Note: this is not always beneficial.\n     * Try with and without -DUNALIGNED_OK to check.\n     */\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;\n    register ush scan_start = *(ushf*)scan;\n    register ush scan_end   = *(ushf*)(scan+best_len-1);\n#else\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH;\n    register Byte scan_end1  = scan[best_len-1];\n    register Byte scan_end   = scan[best_len];\n#endif\n\n    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n     * It is easy to get rid of this optimization if necessary.\n     */\n    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n    /* Do not waste too much time if we already have a good match: */\n    if (s->prev_length >= s->good_match) {\n        chain_length >>= 2;\n    }\n    /* Do not look for matches beyond the end of the input. This is necessary\n     * to make deflate deterministic.\n     */\n    if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead;\n\n    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n    do {\n        Assert(cur_match < s->strstart, \"no future\");\n        match = s->window + cur_match;\n\n        /* Skip to next match if the match length cannot increase\n         * or if the match length is less than 2.  Note that the checks below\n         * for insufficient lookahead only occur occasionally for performance\n         * reasons.  Therefore uninitialized memory will be accessed, and\n         * conditional jumps will be made that depend on those values.\n         * However the length of the match is limited to the lookahead, so\n         * the output of deflate is not affected by the uninitialized values.\n         */\n#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)\n        /* This code assumes sizeof(unsigned short) == 2. Do not use\n         * UNALIGNED_OK if your compiler uses a different size.\n         */\n        if (*(ushf*)(match+best_len-1) != scan_end ||\n            *(ushf*)match != scan_start) continue;\n\n        /* It is not necessary to compare scan[2] and match[2] since they are\n         * always equal when the other bytes match, given that the hash keys\n         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at\n         * strstart+3, +5, ... up to strstart+257. We check for insufficient\n         * lookahead only every 4th comparison; the 128th check will be made\n         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is\n         * necessary to put more guard bytes at the end of the window, or\n         * to check more often for insufficient lookahead.\n         */\n        Assert(scan[2] == match[2], \"scan[2]?\");\n        scan++, match++;\n        do {\n        } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&\n                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&\n                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&\n                 *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&\n                 scan < strend);\n        /* The funny \"do {}\" generates better code on most compilers */\n\n        /* Here, scan <= window+strstart+257 */\n        Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n        if (*scan == *match) scan++;\n\n        len = (MAX_MATCH - 1) - (int)(strend-scan);\n        scan = strend - (MAX_MATCH-1);\n\n#else /* UNALIGNED_OK */\n\n        if (match[best_len]   != scan_end  ||\n            match[best_len-1] != scan_end1 ||\n            *match            != *scan     ||\n            *++match          != scan[1])      continue;\n\n        /* The check at best_len-1 can be removed because it will be made\n         * again later. (This heuristic is not always a win.)\n         * It is not necessary to compare scan[2] and match[2] since they\n         * are always equal when the other bytes match, given that\n         * the hash keys are equal and that HASH_BITS >= 8.\n         */\n        scan += 2, match++;\n        Assert(*scan == *match, \"match[2]?\");\n\n        /* We check for insufficient lookahead only every 8th comparison;\n         * the 256th check will be made at strstart+258.\n         */\n        do {\n        } while (*++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 scan < strend);\n\n        Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n        len = MAX_MATCH - (int)(strend - scan);\n        scan = strend - MAX_MATCH;\n\n#endif /* UNALIGNED_OK */\n\n        if (len > best_len) {\n            s->match_start = cur_match;\n            best_len = len;\n            if (len >= nice_match) break;\n#ifdef UNALIGNED_OK\n            scan_end = *(ushf*)(scan+best_len-1);\n#else\n            scan_end1  = scan[best_len-1];\n            scan_end   = scan[best_len];\n#endif\n        }\n    } while ((cur_match = prev[cur_match & wmask]) > limit\n             && --chain_length != 0);\n\n    if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\n    return s->lookahead;\n}\n#endif /* ASMV */\n\n#else /* FASTEST */\n\n/* ---------------------------------------------------------------------------\n * Optimized version for FASTEST only\n */\nlocal uInt longest_match( deflate_state *s, IPos cur_match )\t/* pcg */\n{\n    register Bytef *scan = s->window + s->strstart; /* current string */\n    register Bytef *match;                       /* matched string */\n    register int len;                           /* length of current match */\n    register Bytef *strend = s->window + s->strstart + MAX_MATCH;\n\n    /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n     * It is easy to get rid of this optimization if necessary.\n     */\n    Assert(s->hash_bits >= 8 && MAX_MATCH == 258, \"Code too clever\");\n\n    Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, \"need lookahead\");\n\n    Assert(cur_match < s->strstart, \"no future\");\n\n    match = s->window + cur_match;\n\n    /* Return failure if the match length is less than 2:\n     */\n    if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;\n\n    /* The check at best_len-1 can be removed because it will be made\n     * again later. (This heuristic is not always a win.)\n     * It is not necessary to compare scan[2] and match[2] since they\n     * are always equal when the other bytes match, given that\n     * the hash keys are equal and that HASH_BITS >= 8.\n     */\n    scan += 2, match += 2;\n    Assert(*scan == *match, \"match[2]?\");\n\n    /* We check for insufficient lookahead only every 8th comparison;\n     * the 256th check will be made at strstart+258.\n     */\n    do {\n    } while (*++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             *++scan == *++match && *++scan == *++match &&\n             scan < strend);\n\n    Assert(scan <= s->window+(unsigned)(s->window_size-1), \"wild scan\");\n\n    len = MAX_MATCH - (int)(strend - scan);\n\n    if (len < MIN_MATCH) return MIN_MATCH - 1;\n\n    s->match_start = cur_match;\n    return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;\n}\n\n#endif /* FASTEST */\n\n#ifdef ZLIB_DEBUG\n\n#define EQUAL 0\n/* result of memcmp for equal strings */\n\n/* ===========================================================================\n * Check that the match at match_start is indeed a match.\n */\nlocal void check_match( deflate_state *s, IPos start, match, int length )\t/* pcg */\n{\n    /* check that the match is indeed a match */\n    if (zmemcmp(s->window + match,\n                s->window + start, length) != EQUAL) {\n        fprintf(stderr, \" start %u, match %u, length %d\\n\",\n                start, match, length);\n        do {\n            fprintf(stderr, \"%c%c\", s->window[match++], s->window[start++]);\n        } while (--length != 0);\n        z_error(\"invalid match\");\n    }\n    if (z_verbose > 1) {\n        fprintf(stderr,\"\\\\[%d,%d]\", start-match, length);\n        do { putc(s->window[start++], stderr); } while (--length != 0);\n    }\n}\n#else\n#  define check_match(s, start, match, length)\n#endif /* ZLIB_DEBUG */\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n *    At least one byte has been read, or avail_in == 0; reads are\n *    performed for at least two bytes (required for the zip translate_eol\n *    option -- not supported here).\n */\nlocal void fill_window( deflate_state *s )\t/* pcg */\n{\n    unsigned n;\n    unsigned more;    /* Amount of free space at the end of the window. */\n    uInt wsize = s->w_size;\n\n    Assert(s->lookahead < MIN_LOOKAHEAD, \"already enough lookahead\");\n\n    do {\n        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);\n\n        /* Deal with !@#$% 64K limit: */\n        if (sizeof(int) <= 2) {\n            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {\n                more = wsize;\n\n            } else if (more == (unsigned)(-1)) {\n                /* Very unlikely, but possible on 16 bit machine if\n                 * strstart == 0 && lookahead == 1 (input done a byte at time)\n                 */\n                more--;\n            }\n        }\n\n        /* If the window is almost full and there is insufficient lookahead,\n         * move the upper half to the lower one to make room in the upper half.\n         */\n        if (s->strstart >= wsize+MAX_DIST(s)) {\n\n            zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more);\n            s->match_start -= wsize;\n            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */\n            s->block_start -= (long) wsize;\n            slide_hash(s);\n            more += wsize;\n        }\n        if (s->strm->avail_in == 0) break;\n\n        /* If there was no sliding:\n         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n         *    more == window_size - lookahead - strstart\n         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n         * => more >= window_size - 2*WSIZE + 2\n         * In the BIG_MEM or MMAP case (not yet supported),\n         *   window_size == input_size + MIN_LOOKAHEAD  &&\n         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n         * Otherwise, window_size == 2*WSIZE so more >= 2.\n         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n         */\n        Assert(more >= 2, \"more < 2\");\n\n        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);\n        s->lookahead += n;\n\n        /* Initialize the hash value now that we have some input: */\n        if (s->lookahead + s->insert >= MIN_MATCH) {\n            uInt str = s->strstart - s->insert;\n            s->ins_h = s->window[str];\n            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);\n#if MIN_MATCH != 3\n            Call UPDATE_HASH() MIN_MATCH-3 more times\n#endif\n            while (s->insert) {\n                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);\n#ifndef FASTEST\n                s->prev[str & s->w_mask] = s->head[s->ins_h];\n#endif\n                s->head[s->ins_h] = (Pos)str;\n                str++;\n                s->insert--;\n                if (s->lookahead + s->insert < MIN_MATCH)\n                    break;\n            }\n        }\n        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,\n         * but this is not important since only literal bytes will be emitted.\n         */\n\n    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);\n\n    /* If the WIN_INIT bytes after the end of the current data have never been\n     * written, then zero those bytes in order to avoid memory check reports of\n     * the use of uninitialized (or uninitialised as Julian writes) bytes by\n     * the longest match routines.  Update the high water mark for the next\n     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match\n     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.\n     */\n    if (s->high_water < s->window_size) {\n        ulg curr = s->strstart + (ulg)(s->lookahead);\n        ulg init;\n\n        if (s->high_water < curr) {\n            /* Previous high water mark below current data -- zero WIN_INIT\n             * bytes or up to end of window, whichever is less.\n             */\n            init = s->window_size - curr;\n            if (init > WIN_INIT)\n                init = WIN_INIT;\n            zmemzero(s->window + curr, (unsigned)init);\n            s->high_water = curr + init;\n        }\n        else if (s->high_water < (ulg)curr + WIN_INIT) {\n            /* High water mark at or above current data, but below current data\n             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up\n             * to end of window, whichever is less.\n             */\n            init = (ulg)curr + WIN_INIT - s->high_water;\n            if (init > s->window_size - s->high_water)\n                init = s->window_size - s->high_water;\n            zmemzero(s->window + s->high_water, (unsigned)init);\n            s->high_water += init;\n        }\n    }\n\n    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,\n           \"not enough room for search\");\n}\n\n/* ===========================================================================\n * Flush the current block, with given end-of-file flag.\n * IN assertion: strstart is set to the end of the current match.\n */\n#define FLUSH_BLOCK_ONLY(s, last) { \\\n   _tr_flush_block(s, (s->block_start >= 0L ? \\\n                   (charf *)&s->window[(unsigned)s->block_start] : \\\n                   (charf *)Z_NULL), \\\n                (ulg)((long)s->strstart - s->block_start), \\\n                (last)); \\\n   s->block_start = s->strstart; \\\n   flush_pending(s->strm); \\\n   Tracev((stderr,\"[FLUSH]\")); \\\n}\n\n/* Same but force premature exit if necessary. */\n#define FLUSH_BLOCK(s, last) { \\\n   FLUSH_BLOCK_ONLY(s, last); \\\n   if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \\\n}\n\n/* Maximum stored block length in deflate format (not including header). */\n#define MAX_STORED 65535\n\n/* Minimum of a and b. */\n#define MIN(a, b) ((a) > (b) ? (b) : (a))\n\n/* ===========================================================================\n * Copy without compression as much as possible from the input stream, return\n * the current block state.\n *\n * In case deflateParams() is used to later switch to a non-zero compression\n * level, s->matches (otherwise unused when storing) keeps track of the number\n * of hash table slides to perform. If s->matches is 1, then one hash table\n * slide will be done when switching. If s->matches is 2, the maximum value\n * allowed here, then the hash table will be cleared, since two or more slides\n * is the same as a clear.\n *\n * deflate_stored() is written to minimize the number of times an input byte is\n * copied. It is most efficient with large input and output buffers, which\n * maximizes the opportunites to have a single copy from next_in to next_out.\n */\nlocal block_state deflate_stored( deflate_state *s, int flush )\t/* pcg */\n{\n    /* Smallest worthy block size when not flushing or finishing. By default\n     * this is 32K. This can be as small as 507 bytes for memLevel == 1. For\n     * large input and output buffers, the stored block size will be larger.\n     */\n    unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size);\n\n    /* Copy as many min_block or larger stored blocks directly to next_out as\n     * possible. If flushing, copy the remaining available input to next_out as\n     * stored blocks, if there is enough space.\n     */\n    unsigned len, left, have, last = 0;\n    unsigned used = s->strm->avail_in;\n    do {\n        /* Set len to the maximum size block that we can copy directly with the\n         * available input data and output space. Set left to how much of that\n         * would be copied from what's left in the window.\n         */\n        len = MAX_STORED;       /* maximum deflate stored block length */\n        have = (s->bi_valid + 42) >> 3;         /* number of header bytes */\n        if (s->strm->avail_out < have)          /* need room for header */\n            break;\n            /* maximum stored block length that will fit in avail_out: */\n        have = s->strm->avail_out - have;\n        left = s->strstart - s->block_start;    /* bytes left in window */\n        if (len > (ulg)left + s->strm->avail_in)\n            len = left + s->strm->avail_in;     /* limit len to the input */\n        if (len > have)\n            len = have;                         /* limit len to the output */\n\n        /* If the stored block would be less than min_block in length, or if\n         * unable to copy all of the available input when flushing, then try\n         * copying to the window and the pending buffer instead. Also don't\n         * write an empty block when flushing -- deflate() does that.\n         */\n        if (len < min_block && ((len == 0 && flush != Z_FINISH) ||\n                                flush == Z_NO_FLUSH ||\n                                len != left + s->strm->avail_in))\n            break;\n\n        /* Make a dummy stored block in pending to get the header bytes,\n         * including any pending bits. This also updates the debugging counts.\n         */\n        last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0;\n        _tr_stored_block(s, (char *)0, 0L, last);\n\n        /* Replace the lengths in the dummy stored block with len. */\n        s->pending_buf[s->pending - 4] = len;\n        s->pending_buf[s->pending - 3] = len >> 8;\n        s->pending_buf[s->pending - 2] = ~len;\n        s->pending_buf[s->pending - 1] = ~len >> 8;\n\n        /* Write the stored block header bytes. */\n        flush_pending(s->strm);\n\n#ifdef ZLIB_DEBUG\n        /* Update debugging counts for the data about to be copied. */\n        s->compressed_len += len << 3;\n        s->bits_sent += len << 3;\n#endif\n\n        /* Copy uncompressed bytes from the window to next_out. */\n        if (left) {\n            if (left > len)\n                left = len;\n            zmemcpy(s->strm->next_out, s->window + s->block_start, left);\n            s->strm->next_out += left;\n            s->strm->avail_out -= left;\n            s->strm->total_out += left;\n            s->block_start += left;\n            len -= left;\n        }\n\n        /* Copy uncompressed bytes directly from next_in to next_out, updating\n         * the check value.\n         */\n        if (len) {\n            read_buf(s->strm, s->strm->next_out, len);\n            s->strm->next_out += len;\n            s->strm->avail_out -= len;\n            s->strm->total_out += len;\n        }\n    } while (last == 0);\n\n    /* Update the sliding window with the last s->w_size bytes of the copied\n     * data, or append all of the copied data to the existing window if less\n     * than s->w_size bytes were copied. Also update the number of bytes to\n     * insert in the hash tables, in the event that deflateParams() switches to\n     * a non-zero compression level.\n     */\n    used -= s->strm->avail_in;      /* number of input bytes directly copied */\n    if (used) {\n        /* If any input was used, then no unused input remains in the window,\n         * therefore s->block_start == s->strstart.\n         */\n        if (used >= s->w_size) {    /* supplant the previous history */\n            s->matches = 2;         /* clear hash */\n            zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);\n            s->strstart = s->w_size;\n        }\n        else {\n            if (s->window_size - s->strstart <= used) {\n                /* Slide the window down. */\n                s->strstart -= s->w_size;\n                zmemcpy(s->window, s->window + s->w_size, s->strstart);\n                if (s->matches < 2)\n                    s->matches++;   /* add a pending slide_hash() */\n            }\n            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);\n            s->strstart += used;\n        }\n        s->block_start = s->strstart;\n        s->insert += MIN(used, s->w_size - s->insert);\n    }\n    if (s->high_water < s->strstart)\n        s->high_water = s->strstart;\n\n    /* If the last block was written to next_out, then done. */\n    if (last)\n        return finish_done;\n\n    /* If flushing and all input has been consumed, then done. */\n    if (flush != Z_NO_FLUSH && flush != Z_FINISH &&\n        s->strm->avail_in == 0 && (long)s->strstart == s->block_start)\n        return block_done;\n\n    /* Fill the window with any remaining input. */\n    have = s->window_size - s->strstart - 1;\n    if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {\n        /* Slide the window down. */\n        s->block_start -= s->w_size;\n        s->strstart -= s->w_size;\n        zmemcpy(s->window, s->window + s->w_size, s->strstart);\n        if (s->matches < 2)\n            s->matches++;           /* add a pending slide_hash() */\n        have += s->w_size;          /* more space now */\n    }\n    if (have > s->strm->avail_in)\n        have = s->strm->avail_in;\n    if (have) {\n        read_buf(s->strm, s->window + s->strstart, have);\n        s->strstart += have;\n    }\n    if (s->high_water < s->strstart)\n        s->high_water = s->strstart;\n\n    /* There was not enough avail_out to write a complete worthy or flushed\n     * stored block to next_out. Write a stored block to pending instead, if we\n     * have enough input for a worthy block, or if flushing and there is enough\n     * room for the remaining input as a stored block in the pending buffer.\n     */\n    have = (s->bi_valid + 42) >> 3;         /* number of header bytes */\n        /* maximum stored block length that will fit in pending: */\n    have = MIN(s->pending_buf_size - have, MAX_STORED);\n    min_block = MIN(have, s->w_size);\n    left = s->strstart - s->block_start;\n    if (left >= min_block ||\n        ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH &&\n         s->strm->avail_in == 0 && left <= have)) {\n        len = MIN(left, have);\n        last = flush == Z_FINISH && s->strm->avail_in == 0 &&\n               len == left ? 1 : 0;\n        _tr_stored_block(s, (charf *)s->window + s->block_start, len, last);\n        s->block_start += len;\n        flush_pending(s->strm);\n    }\n\n    /* We've done all we can with the available input and output. */\n    return last ? finish_started : need_more;\n}\n\n/* ===========================================================================\n * Compress as much as possible from the input stream, return the current\n * block state.\n * This function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nlocal block_state deflate_fast( deflate_state *s, int flush )\t/* pcg */\n{\n    IPos hash_head;       /* head of the hash chain */\n    int bflush;           /* set if current block must be flushed */\n\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (s->lookahead < MIN_LOOKAHEAD) {\n            fill_window(s);\n            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* Insert the string window[strstart .. strstart+2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n        hash_head = NIL;\n        if (s->lookahead >= MIN_MATCH) {\n            INSERT_STRING(s, s->strstart, hash_head);\n        }\n\n        /* Find the longest match, discarding those <= prev_length.\n         * At this point we have always match_length < MIN_MATCH\n         */\n        if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n            s->match_length = longest_match (s, hash_head);\n            /* longest_match() sets match_start */\n        }\n        if (s->match_length >= MIN_MATCH) {\n            check_match(s, s->strstart, s->match_start, s->match_length);\n\n            _tr_tally_dist(s, s->strstart - s->match_start,\n                           s->match_length - MIN_MATCH, bflush);\n\n            s->lookahead -= s->match_length;\n\n            /* Insert new strings in the hash table only if the match length\n             * is not too large. This saves time but degrades compression.\n             */\n#ifndef FASTEST\n            if (s->match_length <= s->max_insert_length &&\n                s->lookahead >= MIN_MATCH) {\n                s->match_length--; /* string at strstart already in table */\n                do {\n                    s->strstart++;\n                    INSERT_STRING(s, s->strstart, hash_head);\n                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n                     * always MIN_MATCH bytes ahead.\n                     */\n                } while (--s->match_length != 0);\n                s->strstart++;\n            } else\n#endif\n            {\n                s->strstart += s->match_length;\n                s->match_length = 0;\n                s->ins_h = s->window[s->strstart];\n                UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);\n#if MIN_MATCH != 3\n                Call UPDATE_HASH() MIN_MATCH-3 more times\n#endif\n                /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not\n                 * matter since it will be recomputed at next deflate call.\n                 */\n            }\n        } else {\n            /* No match, output a literal byte */\n            Tracevv((stderr,\"%c\", s->window[s->strstart]));\n            _tr_tally_lit (s, s->window[s->strstart], bflush);\n            s->lookahead--;\n            s->strstart++;\n        }\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->last_lit)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n\n#ifndef FASTEST\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nlocal block_state deflate_slow( deflate_state *s, int flush )\t/* pcg */\n{\n    IPos hash_head;          /* head of hash chain */\n    int bflush;              /* set if current block must be flushed */\n\n    /* Process the input block. */\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (s->lookahead < MIN_LOOKAHEAD) {\n            fill_window(s);\n            if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* Insert the string window[strstart .. strstart+2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n        hash_head = NIL;\n        if (s->lookahead >= MIN_MATCH) {\n            INSERT_STRING(s, s->strstart, hash_head);\n        }\n\n        /* Find the longest match, discarding those <= prev_length.\n         */\n        s->prev_length = s->match_length, s->prev_match = s->match_start;\n        s->match_length = MIN_MATCH-1;\n\n        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&\n            s->strstart - hash_head <= MAX_DIST(s)) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n            s->match_length = longest_match (s, hash_head);\n            /* longest_match() sets match_start */\n\n            if (s->match_length <= 5 && (s->strategy == Z_FILTERED\n#if TOO_FAR <= 32767\n                || (s->match_length == MIN_MATCH &&\n                    s->strstart - s->match_start > TOO_FAR)\n#endif\n                )) {\n\n                /* If prev_match is also MIN_MATCH, match_start is garbage\n                 * but we will ignore the current match anyway.\n                 */\n                s->match_length = MIN_MATCH-1;\n            }\n        }\n        /* If there was a match at the previous step and the current\n         * match is not better, output the previous match:\n         */\n        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {\n            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;\n            /* Do not insert strings in hash table beyond this. */\n\n            check_match(s, s->strstart-1, s->prev_match, s->prev_length);\n\n            _tr_tally_dist(s, s->strstart -1 - s->prev_match,\n                           s->prev_length - MIN_MATCH, bflush);\n\n            /* Insert in hash table all strings up to the end of the match.\n             * strstart-1 and strstart are already inserted. If there is not\n             * enough lookahead, the last two strings are not inserted in\n             * the hash table.\n             */\n            s->lookahead -= s->prev_length-1;\n            s->prev_length -= 2;\n            do {\n                if (++s->strstart <= max_insert) {\n                    INSERT_STRING(s, s->strstart, hash_head);\n                }\n            } while (--s->prev_length != 0);\n            s->match_available = 0;\n            s->match_length = MIN_MATCH-1;\n            s->strstart++;\n\n            if (bflush) FLUSH_BLOCK(s, 0);\n\n        } else if (s->match_available) {\n            /* If there was no match at the previous position, output a\n             * single literal. If there was a match but the current match\n             * is longer, truncate the previous match to a single literal.\n             */\n            Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n            _tr_tally_lit(s, s->window[s->strstart-1], bflush);\n            if (bflush) {\n                FLUSH_BLOCK_ONLY(s, 0);\n            }\n            s->strstart++;\n            s->lookahead--;\n            if (s->strm->avail_out == 0) return need_more;\n        } else {\n            /* There is no previous match to compare with, wait for\n             * the next step to decide.\n             */\n            s->match_available = 1;\n            s->strstart++;\n            s->lookahead--;\n        }\n    }\n    Assert (flush != Z_NO_FLUSH, \"no flush?\");\n    if (s->match_available) {\n        Tracevv((stderr,\"%c\", s->window[s->strstart-1]));\n        _tr_tally_lit(s, s->window[s->strstart-1], bflush);\n        s->match_available = 0;\n    }\n    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->last_lit)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n#endif /* FASTEST */\n\n/* ===========================================================================\n * For Z_RLE, simply look for runs of bytes, generate matches only of distance\n * one.  Do not maintain a hash table.  (It will be regenerated if this run of\n * deflate switches away from Z_RLE.)\n */\nlocal block_state deflate_rle( deflate_state *s, int flush )\t/* pcg */\n{\n    int bflush;             /* set if current block must be flushed */\n    uInt prev;              /* byte at distance one to match */\n    Bytef *scan, *strend;   /* scan goes up to strend for length of run */\n\n    for (;;) {\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the longest run, plus one for the unrolled loop.\n         */\n        if (s->lookahead <= MAX_MATCH) {\n            fill_window(s);\n            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {\n                return need_more;\n            }\n            if (s->lookahead == 0) break; /* flush the current block */\n        }\n\n        /* See how many times the previous byte repeats */\n        s->match_length = 0;\n        if (s->lookahead >= MIN_MATCH && s->strstart > 0) {\n            scan = s->window + s->strstart - 1;\n            prev = *scan;\n            if (prev == *++scan && prev == *++scan && prev == *++scan) {\n                strend = s->window + s->strstart + MAX_MATCH;\n                do {\n                } while (prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         prev == *++scan && prev == *++scan &&\n                         scan < strend);\n                s->match_length = MAX_MATCH - (uInt)(strend - scan);\n                if (s->match_length > s->lookahead)\n                    s->match_length = s->lookahead;\n            }\n            Assert(scan <= s->window+(uInt)(s->window_size-1), \"wild scan\");\n        }\n\n        /* Emit match if have run of MIN_MATCH or longer, else emit literal */\n        if (s->match_length >= MIN_MATCH) {\n            check_match(s, s->strstart, s->strstart - 1, s->match_length);\n\n            _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);\n\n            s->lookahead -= s->match_length;\n            s->strstart += s->match_length;\n            s->match_length = 0;\n        } else {\n            /* No match, output a literal byte */\n            Tracevv((stderr,\"%c\", s->window[s->strstart]));\n            _tr_tally_lit (s, s->window[s->strstart], bflush);\n            s->lookahead--;\n            s->strstart++;\n        }\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = 0;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->last_lit)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n\n/* ===========================================================================\n * For Z_HUFFMAN_ONLY, do not look for matches.  Do not maintain a hash table.\n * (It will be regenerated if this run of deflate switches away from Huffman.)\n */\nlocal block_state deflate_huff( deflate_state *s, int flush )\t/* pcg */\n{\n    int bflush;             /* set if current block must be flushed */\n\n    for (;;) {\n        /* Make sure that we have a literal to write. */\n        if (s->lookahead == 0) {\n            fill_window(s);\n            if (s->lookahead == 0) {\n                if (flush == Z_NO_FLUSH)\n                    return need_more;\n                break;      /* flush the current block */\n            }\n        }\n\n        /* Output a literal byte */\n        s->match_length = 0;\n        Tracevv((stderr,\"%c\", s->window[s->strstart]));\n        _tr_tally_lit (s, s->window[s->strstart], bflush);\n        s->lookahead--;\n        s->strstart++;\n        if (bflush) FLUSH_BLOCK(s, 0);\n    }\n    s->insert = 0;\n    if (flush == Z_FINISH) {\n        FLUSH_BLOCK(s, 1);\n        return finish_done;\n    }\n    if (s->last_lit)\n        FLUSH_BLOCK(s, 0);\n    return block_done;\n}\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/deflate.h",
    "content": "/* deflate.h -- internal compression state\n * Copyright (C) 1995-2016 Jean-loup Gailly\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* @(#) $Id$ */\n\n#ifndef DEFLATE_H\n#define DEFLATE_H\n\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n#else\n  #include \"zlib/zutil.h\"\n#endif /* Compiler-specific includes */\n\n/* define NO_GZIP when compiling if you want to disable gzip header and\n   trailer creation by deflate().  NO_GZIP would be used to avoid linking in\n   the crc code when it is not needed.  For shared libraries, gzip encoding\n   should be left enabled. */\n#ifndef NO_GZIP\n#  define GZIP\n#endif\n\n/* ===========================================================================\n * Internal compression state.\n */\n\n#define LENGTH_CODES 29\n/* number of length codes, not counting the special END_BLOCK code */\n\n#define LITERALS  256\n/* number of literal bytes 0..255 */\n\n#define L_CODES (LITERALS+1+LENGTH_CODES)\n/* number of Literal or Length codes, including the END_BLOCK code */\n\n#define D_CODES   30\n/* number of distance codes */\n\n#define BL_CODES  19\n/* number of codes used to transfer the bit lengths */\n\n#define HEAP_SIZE (2*L_CODES+1)\n/* maximum heap size */\n\n#define MAX_BITS 15\n/* All codes must not exceed MAX_BITS bits */\n\n#define Buf_size 16\n/* size of bit buffer in bi_buf */\n\n#define INIT_STATE    42    /* zlib header -> BUSY_STATE */\n#ifdef GZIP\n#  define GZIP_STATE  57    /* gzip header -> BUSY_STATE | EXTRA_STATE */\n#endif\n#define EXTRA_STATE   69    /* gzip extra block -> NAME_STATE */\n#define NAME_STATE    73    /* gzip file name -> COMMENT_STATE */\n#define COMMENT_STATE 91    /* gzip comment -> HCRC_STATE */\n#define HCRC_STATE   103    /* gzip header CRC -> BUSY_STATE */\n#define BUSY_STATE   113    /* deflate -> FINISH_STATE */\n#define FINISH_STATE 666    /* stream complete */\n/* Stream status */\n\n\n/* Data structure describing a single value and its code string. */\ntypedef struct ct_data_s {\n    union {\n        ush  freq;       /* frequency count */\n        ush  code;       /* bit string */\n    } fc;\n    union {\n        ush  dad;        /* father node in Huffman tree */\n        ush  len;        /* length of bit string */\n    } dl;\n} FAR ct_data;\n\n#define Freq fc.freq\n#define Code fc.code\n#define Dad  dl.dad\n#define Len  dl.len\n\ntypedef struct static_tree_desc_s  static_tree_desc;\n\ntypedef struct tree_desc_s {\n    ct_data *dyn_tree;           /* the dynamic tree */\n    int     max_code;            /* largest code with non zero frequency */\n    const static_tree_desc *stat_desc;  /* the corresponding static tree */\n} FAR tree_desc;\n\ntypedef ush Pos;\ntypedef Pos FAR Posf;\ntypedef unsigned IPos;\n\n/* A Pos is an index in the character window. We use short instead of int to\n * save space in the various tables. IPos is used only for parameter passing.\n */\n\ntypedef struct internal_state {\n    z_streamp strm;      /* pointer back to this zlib stream */\n    int   status;        /* as the name implies */\n    Bytef *pending_buf;  /* output still pending */\n    ulg   pending_buf_size; /* size of pending_buf */\n    Bytef *pending_out;  /* next pending byte to output to the stream */\n    ulg   pending;       /* nb of bytes in the pending buffer */\n    int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */\n    gz_headerp  gzhead;  /* gzip header information to write */\n    ulg   gzindex;       /* where in extra, name, or comment */\n    Byte  method;        /* can only be DEFLATED */\n    int   last_flush;    /* value of flush param for previous deflate call */\n\n                /* used by deflate.c: */\n\n    uInt  w_size;        /* LZ77 window size (32K by default) */\n    uInt  w_bits;        /* log2(w_size)  (8..16) */\n    uInt  w_mask;        /* w_size - 1 */\n\n    Bytef *window;\n    /* Sliding window. Input bytes are read into the second half of the window,\n     * and move to the first half later to keep a dictionary of at least wSize\n     * bytes. With this organization, matches are limited to a distance of\n     * wSize-MAX_MATCH bytes, but this ensures that IO is always\n     * performed with a length multiple of the block size. Also, it limits\n     * the window size to 64K, which is quite useful on MSDOS.\n     * To do: use the user input buffer as sliding window.\n     */\n\n    ulg window_size;\n    /* Actual size of window: 2*wSize, except when the user input buffer\n     * is directly used as sliding window.\n     */\n\n    Posf *prev;\n    /* Link to older string with same hash index. To limit the size of this\n     * array to 64K, this link is maintained only for the last 32K strings.\n     * An index in this array is thus a window index modulo 32K.\n     */\n\n    Posf *head; /* Heads of the hash chains or NIL. */\n\n    uInt  ins_h;          /* hash index of string to be inserted */\n    uInt  hash_size;      /* number of elements in hash table */\n    uInt  hash_bits;      /* log2(hash_size) */\n    uInt  hash_mask;      /* hash_size-1 */\n\n    uInt  hash_shift;\n    /* Number of bits by which ins_h must be shifted at each input\n     * step. It must be such that after MIN_MATCH steps, the oldest\n     * byte no longer takes part in the hash key, that is:\n     *   hash_shift * MIN_MATCH >= hash_bits\n     */\n\n    long block_start;\n    /* Window position at the beginning of the current output block. Gets\n     * negative when the window is moved backwards.\n     */\n\n    uInt match_length;           /* length of best match */\n    IPos prev_match;             /* previous match */\n    int match_available;         /* set if previous match exists */\n    uInt strstart;               /* start of string to insert */\n    uInt match_start;            /* start of matching string */\n    uInt lookahead;              /* number of valid bytes ahead in window */\n\n    uInt prev_length;\n    /* Length of the best match at previous step. Matches not greater than this\n     * are discarded. This is used in the lazy match evaluation.\n     */\n\n    uInt max_chain_length;\n    /* To speed up deflation, hash chains are never searched beyond this\n     * length.  A higher limit improves compression ratio but degrades the\n     * speed.\n     */\n\n    uInt max_lazy_match;\n    /* Attempt to find a better match only when the current match is strictly\n     * smaller than this value. This mechanism is used only for compression\n     * levels >= 4.\n     */\n#   define max_insert_length  max_lazy_match\n    /* Insert new strings in the hash table only if the match length is not\n     * greater than this length. This saves time but degrades compression.\n     * max_insert_length is used only for compression levels <= 3.\n     */\n\n    int level;    /* compression level (1..9) */\n    int strategy; /* favor or force Huffman coding*/\n\n    uInt good_match;\n    /* Use a faster search when the previous match is longer than this */\n\n    int nice_match; /* Stop searching when current match exceeds this */\n\n                /* used by trees.c: */\n    /* Didn't use ct_data typedef below to suppress compiler warning */\n    struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */\n    struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */\n    struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */\n\n    struct tree_desc_s l_desc;               /* desc. for literal tree */\n    struct tree_desc_s d_desc;               /* desc. for distance tree */\n    struct tree_desc_s bl_desc;              /* desc. for bit length tree */\n\n    ush bl_count[MAX_BITS+1];\n    /* number of codes at each bit length for an optimal tree */\n\n    int heap[2*L_CODES+1];      /* heap used to build the Huffman trees */\n    int heap_len;               /* number of elements in the heap */\n    int heap_max;               /* element of largest frequency */\n    /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n     * The same heap array is used to build all trees.\n     */\n\n    uch depth[2*L_CODES+1];\n    /* Depth of each subtree used as tie breaker for trees of equal frequency\n     */\n\n    uchf *l_buf;          /* buffer for literals or lengths */\n\n    uInt  lit_bufsize;\n    /* Size of match buffer for literals/lengths.  There are 4 reasons for\n     * limiting lit_bufsize to 64K:\n     *   - frequencies can be kept in 16 bit counters\n     *   - if compression is not successful for the first block, all input\n     *     data is still in the window so we can still emit a stored block even\n     *     when input comes from standard input.  (This can also be done for\n     *     all blocks if lit_bufsize is not greater than 32K.)\n     *   - if compression is not successful for a file smaller than 64K, we can\n     *     even emit a stored file instead of a stored block (saving 5 bytes).\n     *     This is applicable only for zip (not gzip or zlib).\n     *   - creating new Huffman trees less frequently may not provide fast\n     *     adaptation to changes in the input data statistics. (Take for\n     *     example a binary file with poorly compressible code followed by\n     *     a highly compressible string table.) Smaller buffer sizes give\n     *     fast adaptation but have of course the overhead of transmitting\n     *     trees more frequently.\n     *   - I can't count above 4\n     */\n\n    uInt last_lit;      /* running index in l_buf */\n\n    ushf *d_buf;\n    /* Buffer for distances. To simplify the code, d_buf and l_buf have\n     * the same number of elements. To use different lengths, an extra flag\n     * array would be necessary.\n     */\n\n    ulg opt_len;        /* bit length of current block with optimal trees */\n    ulg static_len;     /* bit length of current block with static trees */\n    uInt matches;       /* number of string matches in current block */\n    uInt insert;        /* bytes at end of window left to insert */\n\n#ifdef ZLIB_DEBUG\n    ulg compressed_len; /* total bit length of compressed file mod 2^32 */\n    ulg bits_sent;      /* bit length of compressed data sent mod 2^32 */\n#endif\n\n    ush bi_buf;\n    /* Output buffer. bits are inserted starting at the bottom (least\n     * significant bits).\n     */\n    int bi_valid;\n    /* Number of valid bits in bi_buf.  All bits above the last valid bit\n     * are always zero.\n     */\n\n    ulg high_water;\n    /* High water mark offset in window for initialized bytes -- bytes above\n     * this are set to zero in order to avoid memory check warnings when\n     * longest match routines access bytes past the input.  This is then\n     * updated to the new high water mark.\n     */\n\n} FAR deflate_state;\n\n/* Output a byte on the stream.\n * IN assertion: there is enough room in pending_buf.\n */\n#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);}\n\n\n#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)\n/* Minimum amount of lookahead, except at the end of the input file.\n * See deflate.c for comments about the MIN_MATCH+1.\n */\n\n#define MAX_DIST(s)  ((s)->w_size-MIN_LOOKAHEAD)\n/* In order to simplify the code, particularly on 16 bit machines, match\n * distances are limited to MAX_DIST instead of WSIZE.\n */\n\n#define WIN_INIT MAX_MATCH\n/* Number of bytes after end of data in window to initialize in order to avoid\n   memory checker errors from longest match routines */\n\n        /* in trees.c */\nvoid ZLIB_INTERNAL _tr_init OF((deflate_state *s));\nint ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));\nvoid ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,\n                        ulg stored_len, int last));\nvoid ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));\nvoid ZLIB_INTERNAL _tr_align OF((deflate_state *s));\nvoid ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,\n                        ulg stored_len, int last));\n\n#define d_code(dist) \\\n   ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])\n/* Mapping from a distance to a distance code. dist is the distance - 1 and\n * must not have side effects. _dist_code[256] and _dist_code[257] are never\n * used.\n */\n\n#ifndef ZLIB_DEBUG\n/* Inline versions of _tr_tally for speed: */\n\n#if defined(GEN_TREES_H) || !defined(STDC)\n  extern uch ZLIB_INTERNAL _length_code[];\n  extern uch ZLIB_INTERNAL _dist_code[];\n#else\n  extern const uch ZLIB_INTERNAL _length_code[];\n  extern const uch ZLIB_INTERNAL _dist_code[];\n#endif\n\n# define _tr_tally_lit(s, c, flush) \\\n  { uch cc = (c); \\\n    s->d_buf[s->last_lit] = 0; \\\n    s->l_buf[s->last_lit++] = cc; \\\n    s->dyn_ltree[cc].Freq++; \\\n    flush = (s->last_lit == s->lit_bufsize-1); \\\n   }\n# define _tr_tally_dist(s, distance, length, flush) \\\n  { uch len = (uch)(length); \\\n    ush dist = (ush)(distance); \\\n    s->d_buf[s->last_lit] = dist; \\\n    s->l_buf[s->last_lit++] = len; \\\n    dist--; \\\n    s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \\\n    s->dyn_dtree[d_code(dist)].Freq++; \\\n    flush = (s->last_lit == s->lit_bufsize-1); \\\n  }\n#else\n# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)\n# define _tr_tally_dist(s, distance, length, flush) \\\n              flush = _tr_tally(s, distance, length)\n#endif\n\n#endif /* DEFLATE_H */\n"
  },
  {
    "path": "deps/cl345/zlib/inffast.c",
    "content": "/* inffast.c -- fast decoding\n * Copyright (C) 1995-2017 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n  #include \"inftrees.h\"\n  #include \"inflate.h\"\n  #include \"inffast.h\"\n#else\n  #include \"zlib/zutil.h\"\n  #include \"zlib/inftrees.h\"\n  #include \"zlib/inflate.h\"\n  #include \"zlib/inffast.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\n#ifdef ASMINF\n#  pragma message(\"Assembler code may have bugs -- use at your own risk\")\n#else\n\n/*\n   Decode literal, length, and distance codes and write out the resulting\n   literal and match bytes until either not enough input or output is\n   available, an end-of-block is encountered, or a data error is encountered.\n   When large enough input and output buffers are supplied to inflate(), for\n   example, a 16K input buffer and a 64K output buffer, more than 95% of the\n   inflate execution time is spent in this routine.\n\n   Entry assumptions:\n\n        state->mode == LEN\n        strm->avail_in >= 6\n        strm->avail_out >= 258\n        start >= strm->avail_out\n        state->bits < 8\n\n   On return, state->mode is one of:\n\n        LEN -- ran out of enough output space or enough available input\n        TYPE -- reached end of block code, inflate() to interpret next block\n        BAD -- error in block data\n\n   Notes:\n\n    - The maximum input bits used by a length/distance pair is 15 bits for the\n      length code, 5 bits for the length extra, 15 bits for the distance code,\n      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.\n      Therefore if strm->avail_in >= 6, then there is enough input to avoid\n      checking for available input while decoding.\n\n    - The maximum bytes that a single length/distance pair can output is 258\n      bytes, which is the maximum length that can be coded.  inflate_fast()\n      requires strm->avail_out >= 258 for each loop to avoid checking for\n      output space.\n */\nvoid ZLIB_INTERNAL inflate_fast( z_streamp strm, unsigned start )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    z_const unsigned char FAR *in;      /* local strm->next_in */\n    z_const unsigned char FAR *last;    /* have enough input while in < last */\n    unsigned char FAR *out;     /* local strm->next_out */\n    unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */\n    unsigned char FAR *end;     /* while out < end, enough space available */\n#ifdef INFLATE_STRICT\n    unsigned dmax;              /* maximum distance from zlib header */\n#endif\n    unsigned wsize;             /* window size or zero if not using window */\n    unsigned whave;             /* valid bytes in the window */\n    unsigned wnext;             /* window write index */\n    unsigned char FAR *window;  /* allocated sliding window, if wsize != 0 */\n    unsigned long hold;         /* local strm->hold */\n    unsigned bits;              /* local strm->bits */\n    code const FAR *lcode;      /* local strm->lencode */\n    code const FAR *dcode;      /* local strm->distcode */\n    unsigned lmask;             /* mask for first level of length codes */\n    unsigned dmask;             /* mask for first level of distance codes */\n    code here;                  /* retrieved table entry */\n    unsigned op;                /* code bits, operation, extra bits, or */\n                                /*  window position, window bytes to copy */\n    unsigned len;               /* match length, unused bytes */\n    unsigned dist;              /* match distance */\n    unsigned char FAR *from;    /* where to copy match from */\n\n    /* copy state to local variables */\n    state = (struct inflate_state FAR *)strm->state;\n    in = strm->next_in;\n    last = in + (strm->avail_in - 5);\n    out = strm->next_out;\n    beg = out - (start - strm->avail_out);\n    end = out + (strm->avail_out - 257);\n#ifdef INFLATE_STRICT\n    dmax = state->dmax;\n#endif\n    wsize = state->wsize;\n    whave = state->whave;\n    wnext = state->wnext;\n    window = state->window;\n    hold = state->hold;\n    bits = state->bits;\n    lcode = state->lencode;\n    dcode = state->distcode;\n    lmask = (1U << state->lenbits) - 1;\n    dmask = (1U << state->distbits) - 1;\n\n    /* decode literals and length/distances until end-of-block or not enough\n       input data or output space */\n    do {\n        if (bits < 15) {\n            hold += (unsigned long)(*in++) << bits;\n            bits += 8;\n            hold += (unsigned long)(*in++) << bits;\n            bits += 8;\n        }\n        here = lcode[hold & lmask];\n      dolen:\n        op = (unsigned)(here.bits);\n        hold >>= op;\n        bits -= op;\n        op = (unsigned)(here.op);\n        if (op == 0) {                          /* literal */\n            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n                    \"inflate:         literal '%c'\\n\" :\n                    \"inflate:         literal 0x%02x\\n\", here.val));\n            *out++ = (unsigned char)(here.val);\n        }\n        else if (op & 16) {                     /* length base */\n            len = (unsigned)(here.val);\n            op &= 15;                           /* number of extra bits */\n            if (op) {\n                if (bits < op) {\n                    hold += (unsigned long)(*in++) << bits;\n                    bits += 8;\n                }\n                len += (unsigned)hold & ((1U << op) - 1);\n                hold >>= op;\n                bits -= op;\n            }\n            Tracevv((stderr, \"inflate:         length %u\\n\", len));\n            if (bits < 15) {\n                hold += (unsigned long)(*in++) << bits;\n                bits += 8;\n                hold += (unsigned long)(*in++) << bits;\n                bits += 8;\n            }\n            here = dcode[hold & dmask];\n          dodist:\n            op = (unsigned)(here.bits);\n            hold >>= op;\n            bits -= op;\n            op = (unsigned)(here.op);\n            if (op & 16) {                      /* distance base */\n                dist = (unsigned)(here.val);\n                op &= 15;                       /* number of extra bits */\n                if (bits < op) {\n                    hold += (unsigned long)(*in++) << bits;\n                    bits += 8;\n                    if (bits < op) {\n                        hold += (unsigned long)(*in++) << bits;\n                        bits += 8;\n                    }\n                }\n                dist += (unsigned)hold & ((1U << op) - 1);\n#ifdef INFLATE_STRICT\n                if (dist > dmax) {\n                    strm->msg = (char *)\"invalid distance too far back\";\n                    state->mode = BAD;\n                    break;\n                }\n#endif\n                hold >>= op;\n                bits -= op;\n                Tracevv((stderr, \"inflate:         distance %u\\n\", dist));\n                op = (unsigned)(out - beg);     /* max distance in output */\n                if (dist > op) {                /* see if copy from window */\n                    op = dist - op;             /* distance back in window */\n                    if (op > whave) {\n                        if (state->sane) {\n                            strm->msg =\n                                (char *)\"invalid distance too far back\";\n                            state->mode = BAD;\n                            break;\n                        }\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n                        if (len <= op - whave) {\n                            do {\n                                *out++ = 0;\n                            } while (--len);\n                            continue;\n                        }\n                        len -= op - whave;\n                        do {\n                            *out++ = 0;\n                        } while (--op > whave);\n                        if (op == 0) {\n                            from = out - dist;\n                            do {\n                                *out++ = *from++;\n                            } while (--len);\n                            continue;\n                        }\n#endif\n                    }\n                    from = window;\n                    if (wnext == 0) {           /* very common case */\n                        from += wsize - op;\n                        if (op < len) {         /* some from window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = out - dist;  /* rest from output */\n                        }\n                    }\n                    else if (wnext < op) {      /* wrap around window */\n                        from += wsize + wnext - op;\n                        op -= wnext;\n                        if (op < len) {         /* some from end of window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = window;\n                            if (wnext < len) {  /* some from start of window */\n                                op = wnext;\n                                len -= op;\n                                do {\n                                    *out++ = *from++;\n                                } while (--op);\n                                from = out - dist;      /* rest from output */\n                            }\n                        }\n                    }\n                    else {                      /* contiguous in window */\n                        from += wnext - op;\n                        if (op < len) {         /* some from window */\n                            len -= op;\n                            do {\n                                *out++ = *from++;\n                            } while (--op);\n                            from = out - dist;  /* rest from output */\n                        }\n                    }\n                    while (len > 2) {\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        len -= 3;\n                    }\n                    if (len) {\n                        *out++ = *from++;\n                        if (len > 1)\n                            *out++ = *from++;\n                    }\n                }\n                else {\n                    from = out - dist;          /* copy direct from output */\n                    do {                        /* minimum length is three */\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        *out++ = *from++;\n                        len -= 3;\n                    } while (len > 2);\n                    if (len) {\n                        *out++ = *from++;\n                        if (len > 1)\n                            *out++ = *from++;\n                    }\n                }\n            }\n            else if ((op & 64) == 0) {          /* 2nd level distance code */\n                here = dcode[here.val + (hold & ((1U << op) - 1))];\n                goto dodist;\n            }\n            else {\n                strm->msg = (char *)\"invalid distance code\";\n                state->mode = BAD;\n                break;\n            }\n        }\n        else if ((op & 64) == 0) {              /* 2nd level length code */\n            here = lcode[here.val + (hold & ((1U << op) - 1))];\n            goto dolen;\n        }\n        else if (op & 32) {                     /* end-of-block */\n            Tracevv((stderr, \"inflate:         end of block\\n\"));\n            state->mode = TYPE;\n            break;\n        }\n        else {\n            strm->msg = (char *)\"invalid literal/length code\";\n            state->mode = BAD;\n            break;\n        }\n    } while (in < last && out < end);\n\n    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n    len = bits >> 3;\n    in -= len;\n    bits -= len << 3;\n    hold &= (1U << bits) - 1;\n\n    /* update state and return */\n    strm->next_in = in;\n    strm->next_out = out;\n    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));\n    strm->avail_out = (unsigned)(out < end ?\n                                 257 + (end - out) : 257 - (out - end));\n    state->hold = hold;\n    state->bits = bits;\n    return;\n}\n\n/*\n   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):\n   - Using bit fields for code structure\n   - Different op definition to avoid & for extra bits (do & for table bits)\n   - Three separate decoding do-loops for direct, window, and wnext == 0\n   - Special case for distance > 1 copies to do overlapped load and store copy\n   - Explicit branch predictions (based on measured branch probabilities)\n   - Deferring match copy and interspersed it with decoding subsequent codes\n   - Swapping literal/length else\n   - Swapping window/direct else\n   - Larger unrolled copy loops (three is about right)\n   - Moving len -= 3 statement into middle of loop\n */\n\n#endif /* !ASMINF */\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/inffast.h",
    "content": "/* inffast.h -- header to use inffast.c\n * Copyright (C) 1995-2003, 2010 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\nvoid ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));\n"
  },
  {
    "path": "deps/cl345/zlib/inffixed.h",
    "content": "    /* inffixed.h -- table for decoding fixed codes\n     * Generated automatically by makefixed().\n     */\n\n    /* WARNING: this file should *not* be used by applications.\n       It is part of the implementation of this library and is\n       subject to change. Applications should only use zlib.h.\n     */\n\n    static const code lenfix[512] = {\n        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},\n        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},\n        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},\n        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},\n        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},\n        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},\n        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},\n        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},\n        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},\n        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},\n        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},\n        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},\n        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},\n        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},\n        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},\n        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},\n        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},\n        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},\n        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},\n        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},\n        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},\n        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},\n        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},\n        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},\n        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},\n        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},\n        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},\n        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},\n        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},\n        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},\n        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},\n        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},\n        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},\n        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},\n        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},\n        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},\n        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},\n        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},\n        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},\n        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},\n        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},\n        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},\n        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},\n        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},\n        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},\n        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},\n        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},\n        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},\n        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},\n        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},\n        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},\n        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},\n        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},\n        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},\n        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},\n        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},\n        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},\n        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},\n        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},\n        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},\n        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},\n        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},\n        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},\n        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},\n        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},\n        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},\n        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},\n        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},\n        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},\n        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},\n        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},\n        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},\n        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},\n        {0,9,255}\n    };\n\n    static const code distfix[32] = {\n        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},\n        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},\n        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},\n        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},\n        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},\n        {22,5,193},{64,5,0}\n    };\n"
  },
  {
    "path": "deps/cl345/zlib/inflate.c",
    "content": "/* inflate.c -- zlib decompression\n * Copyright (C) 1995-2016 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n * Change history:\n *\n * 1.2.beta0    24 Nov 2002\n * - First version -- complete rewrite of inflate to simplify code, avoid\n *   creation of window when not needed, minimize use of window when it is\n *   needed, make inffast.c even faster, implement gzip decoding, and to\n *   improve code readability and style over the previous zlib inflate code\n *\n * 1.2.beta1    25 Nov 2002\n * - Use pointers for available input and output checking in inffast.c\n * - Remove input and output counters in inffast.c\n * - Change inffast.c entry and loop from avail_in >= 7 to >= 6\n * - Remove unnecessary second byte pull from length extra in inffast.c\n * - Unroll direct copy to three copies per loop in inffast.c\n *\n * 1.2.beta2    4 Dec 2002\n * - Change external routine names to reduce potential conflicts\n * - Correct filename to inffixed.h for fixed tables in inflate.c\n * - Make hbuf[] unsigned char to match parameter type in inflate.c\n * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)\n *   to avoid negation problem on Alphas (64 bit) in inflate.c\n *\n * 1.2.beta3    22 Dec 2002\n * - Add comments on state->bits assertion in inffast.c\n * - Add comments on op field in inftrees.h\n * - Fix bug in reuse of allocated window after inflateReset()\n * - Remove bit fields--back to byte structure for speed\n * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths\n * - Change post-increments to pre-increments in inflate_fast(), PPC biased?\n * - Add compile time option, POSTINC, to use post-increments instead (Intel?)\n * - Make MATCH copy in inflate() much faster for when inflate_fast() not used\n * - Use local copies of stream next and avail values, as well as local bit\n *   buffer and bit count in inflate()--for speed when inflate_fast() not used\n *\n * 1.2.beta4    1 Jan 2003\n * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings\n * - Move a comment on output buffer sizes from inffast.c to inflate.c\n * - Add comments in inffast.c to introduce the inflate_fast() routine\n * - Rearrange window copies in inflate_fast() for speed and simplification\n * - Unroll last copy for window match in inflate_fast()\n * - Use local copies of window variables in inflate_fast() for speed\n * - Pull out common wnext == 0 case for speed in inflate_fast()\n * - Make op and len in inflate_fast() unsigned for consistency\n * - Add FAR to lcode and dcode declarations in inflate_fast()\n * - Simplified bad distance check in inflate_fast()\n * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new\n *   source file infback.c to provide a call-back interface to inflate for\n *   programs like gzip and unzip -- uses window as output buffer to avoid\n *   window copying\n *\n * 1.2.beta5    1 Jan 2003\n * - Improved inflateBack() interface to allow the caller to provide initial\n *   input in strm.\n * - Fixed stored blocks bug in inflateBack()\n *\n * 1.2.beta6    4 Jan 2003\n * - Added comments in inffast.c on effectiveness of POSTINC\n * - Typecasting all around to reduce compiler warnings\n * - Changed loops from while (1) or do {} while (1) to for (;;), again to\n *   make compilers happy\n * - Changed type of window in inflateBackInit() to unsigned char *\n *\n * 1.2.beta7    27 Jan 2003\n * - Changed many types to unsigned or unsigned short to avoid warnings\n * - Added inflateCopy() function\n *\n * 1.2.0        9 Mar 2003\n * - Changed inflateBack() interface to provide separate opaque descriptors\n *   for the in() and out() functions\n * - Changed inflateBack() argument and in_func typedef to swap the length\n *   and buffer address return values for the input function\n * - Check next_in and next_out for Z_NULL on entry to inflate()\n *\n * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.\n */\n\n#if defined( __MVS__ )\t/* pcg */\n  /* MVS control section (CSECT) names default to the file name and cannot\n\t match any extern function name in the file.  This only applies to the\n\t CSECT compiler option.  Without a csect name, when maintenance is\n\t applied to an MVS program the newly introduced csect is ordered ahead\n\t of the previos csects.  With csect names, the new csect replaces the\n\t old csect.  So without csect names, as maintenance is applied\n\t throughout the life of the executable, the executable size\n\t continually increases--not a good thing.\n\n\t These files required the pragma since they contained external function\n\t names that matched the file names, which is the default csect name\n\t generated by the compiler with the csect option.  You cannot have the\n\t same externally visible name defined for two different entities */\n  #pragma csect( CODE, \"inflateC\" )\n  #pragma csect( STATIC, \"inflateS\" )\n  #pragma csect( TEST, \"inflateT\" )\n#endif /* __MVS__ */\n\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n  #include \"inftrees.h\"\n  #include \"inflate.h\"\n  #include \"inffast.h\"\n#else\n  #include \"zlib/zutil.h\"\n  #include \"zlib/inftrees.h\"\n  #include \"zlib/inflate.h\"\n  #include \"zlib/inffast.h\"\n#endif /* Compiler-specific includes */\n\n/* Re-enable use of malloc() - pcg */\n\n#undef Z_SOLO\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\n#ifdef MAKEFIXED\n#  ifndef BUILDFIXED\n#    define BUILDFIXED\n#  endif\n#endif\n\n/* function prototypes */\nlocal int inflateStateCheck OF((z_streamp strm));\nlocal void fixedtables OF((struct inflate_state FAR *state));\nlocal int updatewindow OF((z_streamp strm, const unsigned char FAR *end,\n                           unsigned copy));\n#ifdef BUILDFIXED\n   void makefixed OF((void));\n#endif\nlocal unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,\n                              unsigned len));\n\nlocal int inflateStateCheck( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    if (strm == Z_NULL ||\n        strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)\n        return 1;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state == Z_NULL || state->strm != strm ||\n        state->mode < HEAD || state->mode > SYNC)\n        return 1;\n    return 0;\n}\n\nint ZEXPORT inflateResetKeep( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    strm->total_in = strm->total_out = state->total = 0;\n    strm->msg = Z_NULL;\n    if (state->wrap)        /* to support ill-conceived Java test suite */\n        strm->adler = state->wrap & 1;\n    state->mode = HEAD;\n    state->last = 0;\n    state->havedict = 0;\n    state->dmax = 32768U;\n    state->head = Z_NULL;\n    state->hold = 0;\n    state->bits = 0;\n    state->lencode = state->distcode = state->next = state->codes;\n    state->sane = 1;\n    state->back = -1;\n    Tracev((stderr, \"inflate: reset\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateReset( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    state->wsize = 0;\n    state->whave = 0;\n    state->wnext = 0;\n    return inflateResetKeep(strm);\n}\n\nint ZEXPORT inflateReset2( z_streamp strm, int windowBits )\t/* pcg */\n{\n    int wrap;\n    struct inflate_state FAR *state;\n\n    /* get the state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* extract wrap request from windowBits parameter */\n    if (windowBits < 0) {\n        wrap = 0;\n        windowBits = -windowBits;\n    }\n    else {\n        wrap = (windowBits >> 4) + 5;\n#ifdef GUNZIP\n        if (windowBits < 48)\n            windowBits &= 15;\n#endif\n    }\n\n    /* set number of window bits, free window if different */\n    if (windowBits && (windowBits < 8 || windowBits > 15))\n        return Z_STREAM_ERROR;\n    if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {\n        ZFREE(strm, state->window);\n        state->window = Z_NULL;\n    }\n\n    /* update state and reset the rest of it */\n    state->wrap = wrap;\n    state->wbits = (unsigned)windowBits;\n    return inflateReset(strm);\n}\n\nint ZEXPORT inflateInit2_( z_streamp strm, int windowBits, const char *version, \n    int stream_size )\t/* pcg */\n{\n    int ret;\n    struct inflate_state FAR *state;\n\n    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||\n        stream_size != (int)(sizeof(z_stream)))\n        return Z_VERSION_ERROR;\n    if (strm == Z_NULL) return Z_STREAM_ERROR;\n    strm->msg = Z_NULL;                 /* in case we return an error */\n    if (strm->zalloc == (alloc_func)0) {\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zalloc = zcalloc;\n        strm->opaque = (voidpf)0;\n#endif\n    }\n    if (strm->zfree == (free_func)0)\n#ifdef Z_SOLO\n        return Z_STREAM_ERROR;\n#else\n        strm->zfree = zcfree;\n#endif\n    state = (struct inflate_state FAR *)\n            ZALLOC(strm, 1, sizeof(struct inflate_state));\n    if (state == Z_NULL) return Z_MEM_ERROR;\n    Tracev((stderr, \"inflate: allocated\\n\"));\n    strm->state = (struct internal_state FAR *)state;\n    state->strm = strm;\n    state->window = Z_NULL;\n    state->mode = HEAD;     /* to pass state test in inflateReset2() */\n    ret = inflateReset2(strm, windowBits);\n    if (ret != Z_OK) {\n        ZFREE(strm, state);\n        strm->state = Z_NULL;\n    }\n    return ret;\n}\n\nint ZEXPORT inflateInit_( z_streamp strm, const char *version, int stream_size )\t/* pcg */\n{\n    return inflateInit2_(strm, DEF_WBITS, version, stream_size);\n}\n\nint ZEXPORT inflatePrime( z_streamp strm, int bits, int value )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (bits < 0) {\n        state->hold = 0;\n        state->bits = 0;\n        return Z_OK;\n    }\n    if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;\n    value &= (1L << bits) - 1;\n    state->hold += (unsigned)value << state->bits;\n    state->bits += (uInt)bits;\n    return Z_OK;\n}\n\n/*\n   Return state with length and distance decoding tables and index sizes set to\n   fixed code decoding.  Normally this returns fixed tables from inffixed.h.\n   If BUILDFIXED is defined, then instead this routine builds the tables the\n   first time it's called, and returns those tables the first time and\n   thereafter.  This reduces the size of the code by about 2K bytes, in\n   exchange for a little execution time.  However, BUILDFIXED should not be\n   used for threaded applications, since the rewriting of the tables and virgin\n   may not be thread-safe.\n */\nlocal void fixedtables( struct inflate_state FAR *state )\t/* pcg */\n{\n#ifdef BUILDFIXED\n    static int virgin = 1;\n    static code *lenfix, *distfix;\n    static code fixed[544];\n\n    /* build fixed huffman tables if first call (may not be thread safe) */\n    if (virgin) {\n        unsigned sym, bits;\n        static code *next;\n\n        /* literal/length table */\n        sym = 0;\n        while (sym < 144) state->lens[sym++] = 8;\n        while (sym < 256) state->lens[sym++] = 9;\n        while (sym < 280) state->lens[sym++] = 7;\n        while (sym < 288) state->lens[sym++] = 8;\n        next = fixed;\n        lenfix = next;\n        bits = 9;\n        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);\n\n        /* distance table */\n        sym = 0;\n        while (sym < 32) state->lens[sym++] = 5;\n        distfix = next;\n        bits = 5;\n        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);\n\n        /* do this just once */\n        virgin = 0;\n    }\n#else /* !BUILDFIXED */\n#   include \"inffixed.h\"\n#endif /* BUILDFIXED */\n    state->lencode = lenfix;\n    state->lenbits = 9;\n    state->distcode = distfix;\n    state->distbits = 5;\n}\n\n#ifdef MAKEFIXED\n#include <stdio.h>\n\n/*\n   Write out the inffixed.h that is #include'd above.  Defining MAKEFIXED also\n   defines BUILDFIXED, so the tables are built on the fly.  makefixed() writes\n   those tables to stdout, which would be piped to inffixed.h.  A small program\n   can simply call makefixed to do this:\n\n    void makefixed(void);\n\n    int main(void)\n    {\n        makefixed();\n        return 0;\n    }\n\n   Then that can be linked with zlib built with MAKEFIXED defined and run:\n\n    a.out > inffixed.h\n */\nvoid makefixed( void )\t/* pcg */\n{\n    unsigned low, size;\n    struct inflate_state state;\n\n    fixedtables(&state);\n    puts(\"    /* inffixed.h -- table for decoding fixed codes\");\n    puts(\"     * Generated automatically by makefixed().\");\n    puts(\"     */\");\n    puts(\"\");\n    puts(\"    /* WARNING: this file should *not* be used by applications.\");\n    puts(\"       It is part of the implementation of this library and is\");\n    puts(\"       subject to change. Applications should only use zlib.h.\");\n    puts(\"     */\");\n    puts(\"\");\n    size = 1U << 9;\n    printf(\"    static const code lenfix[%u] = {\", size);\n    low = 0;\n    for (;;) {\n        if ((low % 7) == 0) printf(\"\\n        \");\n        printf(\"{%u,%u,%d}\", (low & 127) == 99 ? 64 : state.lencode[low].op,\n               state.lencode[low].bits, state.lencode[low].val);\n        if (++low == size) break;\n        putchar(',');\n    }\n    puts(\"\\n    };\");\n    size = 1U << 5;\n    printf(\"\\n    static const code distfix[%u] = {\", size);\n    low = 0;\n    for (;;) {\n        if ((low % 6) == 0) printf(\"\\n        \");\n        printf(\"{%u,%u,%d}\", state.distcode[low].op, state.distcode[low].bits,\n               state.distcode[low].val);\n        if (++low == size) break;\n        putchar(',');\n    }\n    puts(\"\\n    };\");\n}\n#endif /* MAKEFIXED */\n\n/*\n   Update the window with the last wsize (normally 32K) bytes written before\n   returning.  If window does not exist yet, create it.  This is only called\n   when a window is already in use, or when output has been written during this\n   inflate call, but the end of the deflate stream has not been reached yet.\n   It is also called to create a window for dictionary data when a dictionary\n   is loaded.\n\n   Providing output buffers larger than 32K to inflate() should provide a speed\n   advantage, since only the last 32K of output is copied to the sliding window\n   upon return from inflate(), and since all distances after the first 32K of\n   output will fall in the output data, making match copies simpler and faster.\n   The advantage may be dependent on the size of the processor's data caches.\n */\nlocal int updatewindow( z_streamp strm, const Bytef *end, unsigned copy )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    unsigned dist;\n\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* if it hasn't been done already, allocate space for the window */\n    if (state->window == Z_NULL) {\n        state->window = (unsigned char FAR *)\n                        ZALLOC(strm, 1U << state->wbits,\n                               sizeof(unsigned char));\n        if (state->window == Z_NULL) return 1;\n    }\n\n    /* if window not in use yet, initialize */\n    if (state->wsize == 0) {\n        state->wsize = 1U << state->wbits;\n        state->wnext = 0;\n        state->whave = 0;\n    }\n\n    /* copy state->wsize or less output bytes into the circular window */\n    if (copy >= state->wsize) {\n        zmemcpy(state->window, end - state->wsize, state->wsize);\n        state->wnext = 0;\n        state->whave = state->wsize;\n    }\n    else {\n        dist = state->wsize - state->wnext;\n        if (dist > copy) dist = copy;\n        zmemcpy(state->window + state->wnext, end - copy, dist);\n        copy -= dist;\n        if (copy) {\n            zmemcpy(state->window, end - copy, copy);\n            state->wnext = copy;\n            state->whave = state->wsize;\n        }\n        else {\n            state->wnext += dist;\n            if (state->wnext == state->wsize) state->wnext = 0;\n            if (state->whave < state->wsize) state->whave += dist;\n        }\n    }\n    return 0;\n}\n\n/* Macros for inflate(): */\n\n/* check function to use adler32() for zlib or crc32() for gzip */\n#ifdef GUNZIP\n#  define UPDATE(check, buf, len) \\\n    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))\n#else\n#  define UPDATE(check, buf, len) adler32(check, buf, len)\n#endif\n\n/* check macros for header crc */\n#ifdef GUNZIP\n#  define CRC2(check, word) \\\n    do { \\\n        hbuf[0] = (unsigned char)(word); \\\n        hbuf[1] = (unsigned char)((word) >> 8); \\\n        check = crc32(check, hbuf, 2); \\\n    } while (0)\n\n#  define CRC4(check, word) \\\n    do { \\\n        hbuf[0] = (unsigned char)(word); \\\n        hbuf[1] = (unsigned char)((word) >> 8); \\\n        hbuf[2] = (unsigned char)((word) >> 16); \\\n        hbuf[3] = (unsigned char)((word) >> 24); \\\n        check = crc32(check, hbuf, 4); \\\n    } while (0)\n#endif\n\n/* Load registers with state in inflate() for speed */\n#define LOAD() \\\n    do { \\\n        put = strm->next_out; \\\n        left = strm->avail_out; \\\n        next = strm->next_in; \\\n        have = strm->avail_in; \\\n        hold = state->hold; \\\n        bits = state->bits; \\\n    } while (0)\n\n/* Restore state from registers in inflate() */\n#define RESTORE() \\\n    do { \\\n        strm->next_out = put; \\\n        strm->avail_out = left; \\\n        strm->next_in = next; \\\n        strm->avail_in = have; \\\n        state->hold = hold; \\\n        state->bits = bits; \\\n    } while (0)\n\n/* Clear the input bit accumulator */\n#define INITBITS() \\\n    do { \\\n        hold = 0; \\\n        bits = 0; \\\n    } while (0)\n\n/* Get a byte of input into the bit accumulator, or return from inflate()\n   if there is no input available. */\n#define PULLBYTE() \\\n    do { \\\n        if (have == 0) goto inf_leave; \\\n        have--; \\\n        hold += (unsigned long)(*next++) << bits; \\\n        bits += 8; \\\n    } while (0)\n\n/* Assure that there are at least n bits in the bit accumulator.  If there is\n   not enough available input to do that, then return from inflate(). */\n#define NEEDBITS(n) \\\n    do { \\\n        while (bits < (unsigned)(n)) \\\n            PULLBYTE(); \\\n    } while (0)\n\n/* Return the low n bits of the bit accumulator (n < 16) */\n#define BITS(n) \\\n    ((unsigned)hold & ((1U << (n)) - 1))\n\n/* Remove n bits from the bit accumulator */\n#define DROPBITS(n) \\\n    do { \\\n        hold >>= (n); \\\n        bits -= (unsigned)(n); \\\n    } while (0)\n\n/* Remove zero to seven bits as needed to go to a byte boundary */\n#define BYTEBITS() \\\n    do { \\\n        hold >>= bits & 7; \\\n        bits -= bits & 7; \\\n    } while (0)\n\n/*\n   inflate() uses a state machine to process as much input data and generate as\n   much output data as possible before returning.  The state machine is\n   structured roughly as follows:\n\n    for (;;) switch (state) {\n    ...\n    case STATEn:\n        if (not enough input data or output space to make progress)\n            return;\n        ... make progress ...\n        state = STATEm;\n        break;\n    ...\n    }\n\n   so when inflate() is called again, the same case is attempted again, and\n   if the appropriate resources are provided, the machine proceeds to the\n   next state.  The NEEDBITS() macro is usually the way the state evaluates\n   whether it can proceed or should return.  NEEDBITS() does the return if\n   the requested bits are not available.  The typical use of the BITS macros\n   is:\n\n        NEEDBITS(n);\n        ... do something with BITS(n) ...\n        DROPBITS(n);\n\n   where NEEDBITS(n) either returns from inflate() if there isn't enough\n   input left to load n bits into the accumulator, or it continues.  BITS(n)\n   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops\n   the low n bits off the accumulator.  INITBITS() clears the accumulator\n   and sets the number of available bits to zero.  BYTEBITS() discards just\n   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()\n   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.\n\n   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return\n   if there is no input available.  The decoding of variable length codes uses\n   PULLBYTE() directly in order to pull just enough bytes to decode the next\n   code, and no more.\n\n   Some states loop until they get enough input, making sure that enough\n   state information is maintained to continue the loop where it left off\n   if NEEDBITS() returns in the loop.  For example, want, need, and keep\n   would all have to actually be part of the saved state in case NEEDBITS()\n   returns:\n\n    case STATEw:\n        while (want < need) {\n            NEEDBITS(n);\n            keep[want++] = BITS(n);\n            DROPBITS(n);\n        }\n        state = STATEx;\n    case STATEx:\n\n   As shown above, if the next state is also the next case, then the break\n   is omitted.\n\n   A state may also return if there is not enough output space available to\n   complete that state.  Those states are copying stored data, writing a\n   literal byte, and copying a matching string.\n\n   When returning, a \"goto inf_leave\" is used to update the total counters,\n   update the check value, and determine whether any progress has been made\n   during that inflate() call in order to return the proper return code.\n   Progress is defined as a change in either strm->avail_in or strm->avail_out.\n   When there is a window, goto inf_leave will update the window with the last\n   output written.  If a goto inf_leave occurs in the middle of decompression\n   and there is no window currently, goto inf_leave will create one and copy\n   output to the window for the next call of inflate().\n\n   In this implementation, the flush parameter of inflate() only affects the\n   return code (per zlib.h).  inflate() always writes as much as possible to\n   strm->next_out, given the space available and the provided input--the effect\n   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers\n   the allocation of and copying into a sliding window until necessary, which\n   provides the effect documented in zlib.h for Z_FINISH when the entire input\n   stream available.  So the only thing the flush parameter actually does is:\n   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it\n   will return Z_BUF_ERROR if it has not reached the end of the stream.\n */\n\nint ZEXPORT inflate( z_streamp strm, int flush )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    z_const unsigned char FAR *next;    /* next input */\n    unsigned char FAR *put;     /* next output */\n    unsigned have, left;        /* available input and output */\n    unsigned long hold;         /* bit buffer */\n    unsigned bits;              /* bits in bit buffer */\n    unsigned in, out;           /* save starting available input and output */\n    unsigned copy;              /* number of stored or match bytes to copy */\n    unsigned char FAR *from;    /* where to copy match bytes from */\n    code here;                  /* current decoding table entry */\n    code last;                  /* parent table entry */\n    unsigned len;               /* length to copy for repeats, bits to drop */\n    int ret;                    /* return code */\n#ifdef GUNZIP\n    unsigned char hbuf[4];      /* buffer for gzip header crc calculation */\n#endif\n    static const unsigned short order[19] = /* permutation of code lengths */\n        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n    if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||\n        (strm->next_in == Z_NULL && strm->avail_in != 0))\n        return Z_STREAM_ERROR;\n\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */\n    LOAD();\n    in = have;\n    out = left;\n    ret = Z_OK;\n    for (;;)\n        switch (state->mode) {\n        case HEAD:\n            if (state->wrap == 0) {\n                state->mode = TYPEDO;\n                break;\n            }\n            NEEDBITS(16);\n#ifdef GUNZIP\n            if ((state->wrap & 2) && hold == 0x8b1f) {  /* gzip header */\n                if (state->wbits == 0)\n                    state->wbits = 15;\n                state->check = crc32(0L, Z_NULL, 0);\n                CRC2(state->check, hold);\n                INITBITS();\n                state->mode = FLAGS;\n                break;\n            }\n            state->flags = 0;           /* expect zlib header */\n            if (state->head != Z_NULL)\n                state->head->done = -1;\n            if (!(state->wrap & 1) ||   /* check if zlib header allowed */\n#else\n            if (\n#endif\n                ((BITS(8) << 8) + (hold >> 8)) % 31) {\n                strm->msg = (char *)\"incorrect header check\";\n                state->mode = BAD;\n                break;\n            }\n            if (BITS(4) != Z_DEFLATED) {\n                strm->msg = (char *)\"unknown compression method\";\n                state->mode = BAD;\n                break;\n            }\n            DROPBITS(4);\n            len = BITS(4) + 8;\n            if (state->wbits == 0)\n                state->wbits = len;\n            if (len > 15 || len > state->wbits) {\n                strm->msg = (char *)\"invalid window size\";\n                state->mode = BAD;\n                break;\n            }\n            state->dmax = 1U << len;\n            Tracev((stderr, \"inflate:   zlib header ok\\n\"));\n            strm->adler = state->check = adler32(0L, Z_NULL, 0);\n            state->mode = hold & 0x200 ? DICTID : TYPE;\n            INITBITS();\n            break;\n#ifdef GUNZIP\n        case FLAGS:\n            NEEDBITS(16);\n            state->flags = (int)(hold);\n            if ((state->flags & 0xff) != Z_DEFLATED) {\n                strm->msg = (char *)\"unknown compression method\";\n                state->mode = BAD;\n                break;\n            }\n            if (state->flags & 0xe000) {\n                strm->msg = (char *)\"unknown header flags set\";\n                state->mode = BAD;\n                break;\n            }\n            if (state->head != Z_NULL)\n                state->head->text = (int)((hold >> 8) & 1);\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC2(state->check, hold);\n            INITBITS();\n            state->mode = TIME;\n        case TIME:\n            NEEDBITS(32);\n            if (state->head != Z_NULL)\n                state->head->time = hold;\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC4(state->check, hold);\n            INITBITS();\n            state->mode = OS;\n        case OS:\n            NEEDBITS(16);\n            if (state->head != Z_NULL) {\n                state->head->xflags = (int)(hold & 0xff);\n                state->head->os = (int)(hold >> 8);\n            }\n            if ((state->flags & 0x0200) && (state->wrap & 4))\n                CRC2(state->check, hold);\n            INITBITS();\n            state->mode = EXLEN;\n        case EXLEN:\n            if (state->flags & 0x0400) {\n                NEEDBITS(16);\n                state->length = (unsigned)(hold);\n                if (state->head != Z_NULL)\n                    state->head->extra_len = (unsigned)hold;\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    CRC2(state->check, hold);\n                INITBITS();\n            }\n            else if (state->head != Z_NULL)\n                state->head->extra = Z_NULL;\n            state->mode = EXTRA;\n        case EXTRA:\n            if (state->flags & 0x0400) {\n                copy = state->length;\n                if (copy > have) copy = have;\n                if (copy) {\n                    if (state->head != Z_NULL &&\n                        state->head->extra != Z_NULL) {\n                        len = state->head->extra_len - state->length;\n                        zmemcpy(state->head->extra + len, next,\n                                len + copy > state->head->extra_max ?\n                                state->head->extra_max - len : copy);\n                    }\n                    if ((state->flags & 0x0200) && (state->wrap & 4))\n                        state->check = crc32(state->check, next, copy);\n                    have -= copy;\n                    next += copy;\n                    state->length -= copy;\n                }\n                if (state->length) goto inf_leave;\n            }\n            state->length = 0;\n            state->mode = NAME;\n        case NAME:\n            if (state->flags & 0x0800) {\n                if (have == 0) goto inf_leave;\n                copy = 0;\n                do {\n                    len = (unsigned)(next[copy++]);\n                    if (state->head != Z_NULL &&\n                            state->head->name != Z_NULL &&\n                            state->length < state->head->name_max)\n                        state->head->name[state->length++] = (Bytef)len;\n                } while (len && copy < have);\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    state->check = crc32(state->check, next, copy);\n                have -= copy;\n                next += copy;\n                if (len) goto inf_leave;\n            }\n            else if (state->head != Z_NULL)\n                state->head->name = Z_NULL;\n            state->length = 0;\n            state->mode = COMMENT;\n        case COMMENT:\n            if (state->flags & 0x1000) {\n                if (have == 0) goto inf_leave;\n                copy = 0;\n                do {\n                    len = (unsigned)(next[copy++]);\n                    if (state->head != Z_NULL &&\n                            state->head->comment != Z_NULL &&\n                            state->length < state->head->comm_max)\n                        state->head->comment[state->length++] = (Bytef)len;\n                } while (len && copy < have);\n                if ((state->flags & 0x0200) && (state->wrap & 4))\n                    state->check = crc32(state->check, next, copy);\n                have -= copy;\n                next += copy;\n                if (len) goto inf_leave;\n            }\n            else if (state->head != Z_NULL)\n                state->head->comment = Z_NULL;\n            state->mode = HCRC;\n        case HCRC:\n            if (state->flags & 0x0200) {\n                NEEDBITS(16);\n                if ((state->wrap & 4) && hold != (state->check & 0xffff)) {\n                    strm->msg = (char *)\"header crc mismatch\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n            }\n            if (state->head != Z_NULL) {\n                state->head->hcrc = (int)((state->flags >> 9) & 1);\n                state->head->done = 1;\n            }\n            strm->adler = state->check = crc32(0L, Z_NULL, 0);\n            state->mode = TYPE;\n            break;\n#endif\n        case DICTID:\n            NEEDBITS(32);\n            strm->adler = state->check = ZSWAP32(hold);\n            INITBITS();\n            state->mode = DICT;\n        case DICT:\n            if (state->havedict == 0) {\n                RESTORE();\n                return Z_NEED_DICT;\n            }\n            strm->adler = state->check = adler32(0L, Z_NULL, 0);\n            state->mode = TYPE;\n        case TYPE:\n            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;\n        case TYPEDO:\n            if (state->last) {\n                BYTEBITS();\n                state->mode = CHECK;\n                break;\n            }\n            NEEDBITS(3);\n            state->last = BITS(1);\n            DROPBITS(1);\n            switch (BITS(2)) {\n            case 0:                             /* stored block */\n                Tracev((stderr, \"inflate:     stored block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = STORED;\n                break;\n            case 1:                             /* fixed block */\n                fixedtables(state);\n                Tracev((stderr, \"inflate:     fixed codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = LEN_;             /* decode codes */\n                if (flush == Z_TREES) {\n                    DROPBITS(2);\n                    goto inf_leave;\n                }\n                break;\n            case 2:                             /* dynamic block */\n                Tracev((stderr, \"inflate:     dynamic codes block%s\\n\",\n                        state->last ? \" (last)\" : \"\"));\n                state->mode = TABLE;\n                break;\n            case 3:\n                strm->msg = (char *)\"invalid block type\";\n                state->mode = BAD;\n            }\n            DROPBITS(2);\n            break;\n        case STORED:\n            BYTEBITS();                         /* go to byte boundary */\n            NEEDBITS(32);\n            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {\n                strm->msg = (char *)\"invalid stored block lengths\";\n                state->mode = BAD;\n                break;\n            }\n            state->length = (unsigned)hold & 0xffff;\n            Tracev((stderr, \"inflate:       stored length %u\\n\",\n                    state->length));\n            INITBITS();\n            state->mode = COPY_;\n            if (flush == Z_TREES) goto inf_leave;\n        case COPY_:\n            state->mode = COPY;\n        case COPY:\n            copy = state->length;\n            if (copy) {\n                if (copy > have) copy = have;\n                if (copy > left) copy = left;\n                if (copy == 0) goto inf_leave;\n                zmemcpy(put, next, copy);\n                have -= copy;\n                next += copy;\n                left -= copy;\n                put += copy;\n                state->length -= copy;\n                break;\n            }\n            Tracev((stderr, \"inflate:       stored end\\n\"));\n            state->mode = TYPE;\n            break;\n        case TABLE:\n            NEEDBITS(14);\n            state->nlen = BITS(5) + 257;\n            DROPBITS(5);\n            state->ndist = BITS(5) + 1;\n            DROPBITS(5);\n            state->ncode = BITS(4) + 4;\n            DROPBITS(4);\n#ifndef PKZIP_BUG_WORKAROUND\n            if (state->nlen > 286 || state->ndist > 30) {\n                strm->msg = (char *)\"too many length or distance symbols\";\n                state->mode = BAD;\n                break;\n            }\n#endif\n            Tracev((stderr, \"inflate:       table sizes ok\\n\"));\n            state->have = 0;\n            state->mode = LENLENS;\n        case LENLENS:\n            while (state->have < state->ncode) {\n                NEEDBITS(3);\n                state->lens[order[state->have++]] = (unsigned short)BITS(3);\n                DROPBITS(3);\n            }\n            while (state->have < 19)\n                state->lens[order[state->have++]] = 0;\n            state->next = state->codes;\n            state->lencode = (const code FAR *)(state->next);\n            state->lenbits = 7;\n            ret = inflate_table(CODES, state->lens, 19, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid code lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       code lengths ok\\n\"));\n            state->have = 0;\n            state->mode = CODELENS;\n        case CODELENS:\n            while (state->have < state->nlen + state->ndist) {\n                for (;;) {\n                    here = state->lencode[BITS(state->lenbits)];\n                    if ((unsigned)(here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                if (here.val < 16) {\n                    DROPBITS(here.bits);\n                    state->lens[state->have++] = here.val;\n                }\n                else {\n                    if (here.val == 16) {\n                        NEEDBITS(here.bits + 2);\n                        DROPBITS(here.bits);\n                        if (state->have == 0) {\n                            strm->msg = (char *)\"invalid bit length repeat\";\n                            state->mode = BAD;\n                            break;\n                        }\n                        len = state->lens[state->have - 1];\n                        copy = 3 + BITS(2);\n                        DROPBITS(2);\n                    }\n                    else if (here.val == 17) {\n                        NEEDBITS(here.bits + 3);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 3 + BITS(3);\n                        DROPBITS(3);\n                    }\n                    else {\n                        NEEDBITS(here.bits + 7);\n                        DROPBITS(here.bits);\n                        len = 0;\n                        copy = 11 + BITS(7);\n                        DROPBITS(7);\n                    }\n                    if (state->have + copy > state->nlen + state->ndist) {\n                        strm->msg = (char *)\"invalid bit length repeat\";\n                        state->mode = BAD;\n                        break;\n                    }\n                    while (copy--)\n                        state->lens[state->have++] = (unsigned short)len;\n                }\n            }\n\n            /* handle error breaks in while */\n            if (state->mode == BAD) break;\n\n            /* check for end-of-block code (better have one) */\n            if (state->lens[256] == 0) {\n                strm->msg = (char *)\"invalid code -- missing end-of-block\";\n                state->mode = BAD;\n                break;\n            }\n\n            /* build code tables -- note: do not change the lenbits or distbits\n               values here (9 and 6) without reading the comments in inftrees.h\n               concerning the ENOUGH constants, which depend on those values */\n            state->next = state->codes;\n            state->lencode = (const code FAR *)(state->next);\n            state->lenbits = 9;\n            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),\n                                &(state->lenbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid literal/lengths set\";\n                state->mode = BAD;\n                break;\n            }\n            state->distcode = (const code FAR *)(state->next);\n            state->distbits = 6;\n            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,\n                            &(state->next), &(state->distbits), state->work);\n            if (ret) {\n                strm->msg = (char *)\"invalid distances set\";\n                state->mode = BAD;\n                break;\n            }\n            Tracev((stderr, \"inflate:       codes ok\\n\"));\n            state->mode = LEN_;\n            if (flush == Z_TREES) goto inf_leave;\n        case LEN_:\n            state->mode = LEN;\n        case LEN:\n            if (have >= 6 && left >= 258) {\n                RESTORE();\n                inflate_fast(strm, out);\n                LOAD();\n                if (state->mode == TYPE)\n                    state->back = -1;\n                break;\n            }\n            state->back = 0;\n            for (;;) {\n                here = state->lencode[BITS(state->lenbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if (here.op && (here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->lencode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n                state->back += last.bits;\n            }\n            DROPBITS(here.bits);\n            state->back += here.bits;\n            state->length = (unsigned)here.val;\n            if ((int)(here.op) == 0) {\n                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n                        \"inflate:         literal '%c'\\n\" :\n                        \"inflate:         literal 0x%02x\\n\", here.val));\n                state->mode = LIT;\n                break;\n            }\n            if (here.op & 32) {\n                Tracevv((stderr, \"inflate:         end of block\\n\"));\n                state->back = -1;\n                state->mode = TYPE;\n                break;\n            }\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid literal/length code\";\n                state->mode = BAD;\n                break;\n            }\n            state->extra = (unsigned)(here.op) & 15;\n            state->mode = LENEXT;\n        case LENEXT:\n            if (state->extra) {\n                NEEDBITS(state->extra);\n                state->length += BITS(state->extra);\n                DROPBITS(state->extra);\n                state->back += state->extra;\n            }\n            Tracevv((stderr, \"inflate:         length %u\\n\", state->length));\n            state->was = state->length;\n            state->mode = DIST;\n        case DIST:\n            for (;;) {\n                here = state->distcode[BITS(state->distbits)];\n                if ((unsigned)(here.bits) <= bits) break;\n                PULLBYTE();\n            }\n            if ((here.op & 0xf0) == 0) {\n                last = here;\n                for (;;) {\n                    here = state->distcode[last.val +\n                            (BITS(last.bits + last.op) >> last.bits)];\n                    if ((unsigned)(last.bits + here.bits) <= bits) break;\n                    PULLBYTE();\n                }\n                DROPBITS(last.bits);\n                state->back += last.bits;\n            }\n            DROPBITS(here.bits);\n            state->back += here.bits;\n            if (here.op & 64) {\n                strm->msg = (char *)\"invalid distance code\";\n                state->mode = BAD;\n                break;\n            }\n            state->offset = (unsigned)here.val;\n            state->extra = (unsigned)(here.op) & 15;\n            state->mode = DISTEXT;\n        case DISTEXT:\n            if (state->extra) {\n                NEEDBITS(state->extra);\n                state->offset += BITS(state->extra);\n                DROPBITS(state->extra);\n                state->back += state->extra;\n            }\n#ifdef INFLATE_STRICT\n            if (state->offset > state->dmax) {\n                strm->msg = (char *)\"invalid distance too far back\";\n                state->mode = BAD;\n                break;\n            }\n#endif\n            Tracevv((stderr, \"inflate:         distance %u\\n\", state->offset));\n            state->mode = MATCH;\n        case MATCH:\n            if (left == 0) goto inf_leave;\n            copy = out - left;\n            if (state->offset > copy) {         /* copy from window */\n                copy = state->offset - copy;\n                if (copy > state->whave) {\n                    if (state->sane) {\n                        strm->msg = (char *)\"invalid distance too far back\";\n                        state->mode = BAD;\n                        break;\n                    }\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n                    Trace((stderr, \"inflate.c too far\\n\"));\n                    copy -= state->whave;\n                    if (copy > state->length) copy = state->length;\n                    if (copy > left) copy = left;\n                    left -= copy;\n                    state->length -= copy;\n                    do {\n                        *put++ = 0;\n                    } while (--copy);\n                    if (state->length == 0) state->mode = LEN;\n                    break;\n#endif\n                }\n                if (copy > state->wnext) {\n                    copy -= state->wnext;\n                    from = state->window + (state->wsize - copy);\n                }\n                else\n                    from = state->window + (state->wnext - copy);\n                if (copy > state->length) copy = state->length;\n            }\n            else {                              /* copy from output */\n                from = put - state->offset;\n                copy = state->length;\n            }\n            if (copy > left) copy = left;\n            left -= copy;\n            state->length -= copy;\n            do {\n                *put++ = *from++;\n            } while (--copy);\n            if (state->length == 0) state->mode = LEN;\n            break;\n        case LIT:\n            if (left == 0) goto inf_leave;\n            *put++ = (unsigned char)(state->length);\n            left--;\n            state->mode = LEN;\n            break;\n        case CHECK:\n            if (state->wrap) {\n                NEEDBITS(32);\n                out -= left;\n                strm->total_out += out;\n                state->total += out;\n                if ((state->wrap & 4) && out)\n                    strm->adler = state->check =\n                        UPDATE(state->check, put - out, out);\n                out = left;\n                if ((state->wrap & 4) && (\n#ifdef GUNZIP\n                     state->flags ? hold :\n#endif\n                     ZSWAP32(hold)) != state->check) {\n                    strm->msg = (char *)\"incorrect data check\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n                Tracev((stderr, \"inflate:   check matches trailer\\n\"));\n            }\n#ifdef GUNZIP\n            state->mode = LENGTH;\n        case LENGTH:\n            if (state->wrap && state->flags) {\n                NEEDBITS(32);\n                if (hold != (state->total & 0xffffffffUL)) {\n                    strm->msg = (char *)\"incorrect length check\";\n                    state->mode = BAD;\n                    break;\n                }\n                INITBITS();\n                Tracev((stderr, \"inflate:   length matches trailer\\n\"));\n            }\n#endif\n            state->mode = DONE;\n        case DONE:\n            ret = Z_STREAM_END;\n            goto inf_leave;\n        case BAD:\n            ret = Z_DATA_ERROR;\n            goto inf_leave;\n        case MEM:\n            return Z_MEM_ERROR;\n        case SYNC:\n        default:\n            return Z_STREAM_ERROR;\n        }\n\n    /*\n       Return from inflate(), updating the total counts and the check value.\n       If there was no progress during the inflate() call, return a buffer\n       error.  Call updatewindow() to create and/or update the window state.\n       Note: a memory error from inflate() is non-recoverable.\n     */\n  inf_leave:\n    RESTORE();\n    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&\n            (state->mode < CHECK || flush != Z_FINISH)))\n        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {\n            state->mode = MEM;\n            return Z_MEM_ERROR;\n        }\n    in -= strm->avail_in;\n    out -= strm->avail_out;\n    strm->total_in += in;\n    strm->total_out += out;\n    state->total += out;\n    if ((state->wrap & 4) && out)\n        strm->adler = state->check =\n            UPDATE(state->check, strm->next_out - out, out);\n    strm->data_type = (int)state->bits + (state->last ? 64 : 0) +\n                      (state->mode == TYPE ? 128 : 0) +\n                      (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);\n    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)\n        ret = Z_BUF_ERROR;\n    return ret;\n}\n\nint ZEXPORT inflateEnd( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    if (inflateStateCheck(strm))\n        return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->window != Z_NULL) ZFREE(strm, state->window);\n    ZFREE(strm, strm->state);\n    strm->state = Z_NULL;\n    Tracev((stderr, \"inflate: end\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateGetDictionary( z_streamp strm, Bytef *dictionary, uInt *dictLength )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n\n    /* copy dictionary */\n    if (state->whave && dictionary != Z_NULL) {\n        zmemcpy(dictionary, state->window + state->wnext,\n                state->whave - state->wnext);\n        zmemcpy(dictionary + state->whave - state->wnext,\n                state->window, state->wnext);\n    }\n    if (dictLength != Z_NULL)\n        *dictLength = state->whave;\n    return Z_OK;\n}\n\nint ZEXPORT inflateSetDictionary( z_streamp strm, const Bytef *dictionary, uInt dictLength )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    unsigned long dictid;\n    int ret;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (state->wrap != 0 && state->mode != DICT)\n        return Z_STREAM_ERROR;\n\n    /* check for correct dictionary identifier */\n    if (state->mode == DICT) {\n        dictid = adler32(0L, Z_NULL, 0);\n        dictid = adler32(dictid, dictionary, dictLength);\n        if (dictid != state->check)\n            return Z_DATA_ERROR;\n    }\n\n    /* copy dictionary to window using updatewindow(), which will amend the\n       existing dictionary if appropriate */\n    ret = updatewindow(strm, dictionary + dictLength, dictLength);\n    if (ret) {\n        state->mode = MEM;\n        return Z_MEM_ERROR;\n    }\n    state->havedict = 1;\n    Tracev((stderr, \"inflate:   dictionary set\\n\"));\n    return Z_OK;\n}\n\nint ZEXPORT inflateGetHeader( z_streamp strm, gz_headerp head )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    /* check state */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;\n\n    /* save header structure */\n    state->head = head;\n    head->done = 0;\n    return Z_OK;\n}\n\n/*\n   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found\n   or when out of input.  When called, *have is the number of pattern bytes\n   found in order so far, in 0..3.  On return *have is updated to the new\n   state.  If on return *have equals four, then the pattern was found and the\n   return value is how many bytes were read including the last byte of the\n   pattern.  If *have is less than four, then the pattern has not been found\n   yet and the return value is len.  In the latter case, syncsearch() can be\n   called again with more data and the *have state.  *have is initialized to\n   zero for the first call.\n */\nlocal unsigned syncsearch( unsigned FAR *have, const unsigned char FAR *buf, unsigned len )\t/* pcg */\n{\n    unsigned got;\n    unsigned next;\n\n    got = *have;\n    next = 0;\n    while (next < len && got < 4) {\n        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))\n            got++;\n        else if (buf[next])\n            got = 0;\n        else\n            got = 4 - got;\n        next++;\n    }\n    *have = got;\n    return next;\n}\n\nint ZEXPORT inflateSync( z_streamp strm )\t/* pcg */\n{\n    unsigned len;               /* number of bytes to look at or looked at */\n    unsigned long in, out;      /* temporary to save total_in and total_out */\n    unsigned char buf[4];       /* to restore bit buffer to byte string */\n    struct inflate_state FAR *state;\n\n    /* check parameters */\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;\n\n    /* if first time, start search in bit buffer */\n    if (state->mode != SYNC) {\n        state->mode = SYNC;\n        state->hold <<= state->bits & 7;\n        state->bits -= state->bits & 7;\n        len = 0;\n        while (state->bits >= 8) {\n            buf[len++] = (unsigned char)(state->hold);\n            state->hold >>= 8;\n            state->bits -= 8;\n        }\n        state->have = 0;\n        syncsearch(&(state->have), buf, len);\n    }\n\n    /* search available input */\n    len = syncsearch(&(state->have), strm->next_in, strm->avail_in);\n    strm->avail_in -= len;\n    strm->next_in += len;\n    strm->total_in += len;\n\n    /* return no joy or set up to restart inflate() on a new block */\n    if (state->have != 4) return Z_DATA_ERROR;\n    in = strm->total_in;  out = strm->total_out;\n    inflateReset(strm);\n    strm->total_in = in;  strm->total_out = out;\n    state->mode = TYPE;\n    return Z_OK;\n}\n\n/*\n   Returns true if inflate is currently at the end of a block generated by\n   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\n   implementation to provide an additional safety check. PPP uses\n   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored\n   block. When decompressing, PPP checks that at the end of input packet,\n   inflate is waiting for these length bytes.\n */\nint ZEXPORT inflateSyncPoint( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    return state->mode == STORED && state->bits == 0;\n}\n\nint ZEXPORT inflateCopy( z_streamp dest, z_streamp source )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    struct inflate_state FAR *copy;\n    unsigned char FAR *window;\n    unsigned wsize;\n\n    /* check input */\n    if (inflateStateCheck(source) || dest == Z_NULL)\n        return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)source->state;\n\n    /* allocate space */\n    copy = (struct inflate_state FAR *)\n           ZALLOC(source, 1, sizeof(struct inflate_state));\n    if (copy == Z_NULL) return Z_MEM_ERROR;\n    window = Z_NULL;\n    if (state->window != Z_NULL) {\n        window = (unsigned char FAR *)\n                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));\n        if (window == Z_NULL) {\n            ZFREE(source, copy);\n            return Z_MEM_ERROR;\n        }\n    }\n\n    /* copy state */\n    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));\n    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));\n    copy->strm = dest;\n    if (state->lencode >= state->codes &&\n        state->lencode <= state->codes + ENOUGH - 1) {\n        copy->lencode = copy->codes + (state->lencode - state->codes);\n        copy->distcode = copy->codes + (state->distcode - state->codes);\n    }\n    copy->next = copy->codes + (state->next - state->codes);\n    if (window != Z_NULL) {\n        wsize = 1U << state->wbits;\n        zmemcpy(window, state->window, wsize);\n    }\n    copy->window = window;\n    dest->state = (struct internal_state FAR *)copy;\n    return Z_OK;\n}\n\nint ZEXPORT inflateUndermine( z_streamp strm, int subvert )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n    state->sane = !subvert;\n    return Z_OK;\n#else\n    (void)subvert;\n    state->sane = 1;\n    return Z_DATA_ERROR;\n#endif\n}\n\nint ZEXPORT inflateValidate( z_streamp strm, int check )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;\n    state = (struct inflate_state FAR *)strm->state;\n    if (check)\n        state->wrap |= 4;\n    else\n        state->wrap &= ~4;\n    return Z_OK;\n}\n\nlong ZEXPORT inflateMark( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n\n    if (inflateStateCheck(strm))\n        return -(1L << 16);\n    state = (struct inflate_state FAR *)strm->state;\n    return (long)(((unsigned long)((long)state->back)) << 16) +\n        (state->mode == COPY ? state->length :\n            (state->mode == MATCH ? state->was - state->length : 0));\n}\n\nunsigned long ZEXPORT inflateCodesUsed( z_streamp strm )\t/* pcg */\n{\n    struct inflate_state FAR *state;\n    if (inflateStateCheck(strm)) return (unsigned long)-1;\n    state = (struct inflate_state FAR *)strm->state;\n    return (unsigned long)(state->next - state->codes);\n}\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/inflate.h",
    "content": "/* inflate.h -- internal inflate state definition\n * Copyright (C) 1995-2016 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* define NO_GZIP when compiling if you want to disable gzip header and\n   trailer decoding by inflate().  NO_GZIP would be used to avoid linking in\n   the crc code when it is not needed.  For shared libraries, gzip decoding\n   should be left enabled. */\n#ifndef NO_GZIP\n#  define GUNZIP\n#endif\n\n/* Possible inflate modes between inflate() calls */\ntypedef enum {\n    HEAD = 16180,   /* i: waiting for magic header */\n    FLAGS,      /* i: waiting for method and flags (gzip) */\n    TIME,       /* i: waiting for modification time (gzip) */\n    OS,         /* i: waiting for extra flags and operating system (gzip) */\n    EXLEN,      /* i: waiting for extra length (gzip) */\n    EXTRA,      /* i: waiting for extra bytes (gzip) */\n    NAME,       /* i: waiting for end of file name (gzip) */\n    COMMENT,    /* i: waiting for end of comment (gzip) */\n    HCRC,       /* i: waiting for header crc (gzip) */\n    DICTID,     /* i: waiting for dictionary check value */\n    DICT,       /* waiting for inflateSetDictionary() call */\n        TYPE,       /* i: waiting for type bits, including last-flag bit */\n        TYPEDO,     /* i: same, but skip check to exit inflate on new block */\n        STORED,     /* i: waiting for stored size (length and complement) */\n        COPY_,      /* i/o: same as COPY below, but only first time in */\n        COPY,       /* i/o: waiting for input or output to copy stored block */\n        TABLE,      /* i: waiting for dynamic block table lengths */\n        LENLENS,    /* i: waiting for code length code lengths */\n        CODELENS,   /* i: waiting for length/lit and distance code lengths */\n            LEN_,       /* i: same as LEN below, but only first time in */\n            LEN,        /* i: waiting for length/lit/eob code */\n            LENEXT,     /* i: waiting for length extra bits */\n            DIST,       /* i: waiting for distance code */\n            DISTEXT,    /* i: waiting for distance extra bits */\n            MATCH,      /* o: waiting for output space to copy string */\n            LIT,        /* o: waiting for output space to write literal */\n    CHECK,      /* i: waiting for 32-bit check value */\n    LENGTH,     /* i: waiting for 32-bit length (gzip) */\n    DONE,       /* finished check, done -- remain here until reset */\n    BAD,        /* got a data error -- remain here until reset */\n    MEM,        /* got an inflate() memory error -- remain here until reset */\n    SYNC        /* looking for synchronization bytes to restart inflate() */\n} inflate_mode;\n\n/*\n    State transitions between above modes -\n\n    (most modes can go to BAD or MEM on error -- not shown for clarity)\n\n    Process header:\n        HEAD -> (gzip) or (zlib) or (raw)\n        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->\n                  HCRC -> TYPE\n        (zlib) -> DICTID or TYPE\n        DICTID -> DICT -> TYPE\n        (raw) -> TYPEDO\n    Read deflate blocks:\n            TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK\n            STORED -> COPY_ -> COPY -> TYPE\n            TABLE -> LENLENS -> CODELENS -> LEN_\n            LEN_ -> LEN\n    Read deflate codes in fixed or dynamic block:\n                LEN -> LENEXT or LIT or TYPE\n                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN\n                LIT -> LEN\n    Process trailer:\n        CHECK -> LENGTH -> DONE\n */\n\n/* State maintained between inflate() calls -- approximately 7K bytes, not\n   including the allocated sliding window, which is up to 32K bytes. */\nstruct inflate_state {\n    z_streamp strm;             /* pointer back to this zlib stream */\n    inflate_mode mode;          /* current inflate mode */\n    int last;                   /* true if processing last block */\n    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip,\n                                   bit 2 true to validate check value */\n    int havedict;               /* true if dictionary provided */\n    int flags;                  /* gzip header method and flags (0 if zlib) */\n    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */\n    unsigned long check;        /* protected copy of check value */\n    unsigned long total;        /* protected copy of output count */\n    gz_headerp head;            /* where to save gzip header information */\n        /* sliding window */\n    unsigned wbits;             /* log base 2 of requested window size */\n    unsigned wsize;             /* window size or zero if not using window */\n    unsigned whave;             /* valid bytes in the window */\n    unsigned wnext;             /* window write index */\n    unsigned char FAR *window;  /* allocated sliding window, if needed */\n        /* bit accumulator */\n    unsigned long hold;         /* input bit accumulator */\n    unsigned bits;              /* number of bits in \"in\" */\n        /* for string and stored block copying */\n    unsigned length;            /* literal or length of data to copy */\n    unsigned offset;            /* distance back to copy string from */\n        /* for table and code decoding */\n    unsigned extra;             /* extra bits needed */\n        /* fixed and dynamic code tables */\n    code const FAR *lencode;    /* starting table for length/literal codes */\n    code const FAR *distcode;   /* starting table for distance codes */\n    unsigned lenbits;           /* index bits for lencode */\n    unsigned distbits;          /* index bits for distcode */\n        /* dynamic table building */\n    unsigned ncode;             /* number of code length code lengths */\n    unsigned nlen;              /* number of length code lengths */\n    unsigned ndist;             /* number of distance code lengths */\n    unsigned have;              /* number of code lengths in lens[] */\n    code FAR *next;             /* next available space in codes[] */\n    unsigned short lens[320];   /* temporary storage for code lengths */\n    unsigned short work[288];   /* work area for code table building */\n    code codes[ENOUGH];         /* space for code tables */\n    int sane;                   /* if false, allow invalid distance too far */\n    int back;                   /* bits back of last unprocessed length/lit */\n    unsigned was;               /* initial length of match */\n};\n"
  },
  {
    "path": "deps/cl345/zlib/inftrees.c",
    "content": "/* inftrees.c -- generate Huffman trees for efficient decoding\n * Copyright (C) 1995-2017 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n  #include \"inftrees.h\"\n#else\n  #include \"zlib/zutil.h\"\n  #include \"zlib/inftrees.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\n#define MAXBITS 15\n\nconst char inflate_copyright[] =\n   \" inflate 1.2.11 Copyright 1995-2017 Mark Adler \";\n/*\n  If you use the zlib library in a product, an acknowledgment is welcome\n  in the documentation of your product. If for some reason you cannot\n  include such an acknowledgment, I would appreciate that you keep this\n  copyright string in the executable of your product.\n */\n\n/*\n   Build a set of tables to decode the provided canonical Huffman code.\n   The code lengths are lens[0..codes-1].  The result starts at *table,\n   whose indices are 0..2^bits-1.  work is a writable array of at least\n   lens shorts, which is used as a work area.  type is the type of code\n   to be generated, CODES, LENS, or DISTS.  On return, zero is success,\n   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table\n   on return points to the next available entry's address.  bits is the\n   requested root table index bits, and on return it is the actual root\n   table index bits.  It will differ if the request is greater than the\n   longest code or if it is less than the shortest code.\n */\nint ZLIB_INTERNAL inflate_table( codetype type, unsigned short FAR *lens, unsigned codes,\n    code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work )\t/* pcg */\n{\n    unsigned len;               /* a code's length in bits */\n    unsigned sym;               /* index of code symbols */\n    unsigned min, max;          /* minimum and maximum code lengths */\n    unsigned root;              /* number of index bits for root table */\n    unsigned curr;              /* number of index bits for current table */\n    unsigned drop;              /* code bits to drop for sub-table */\n    int left;                   /* number of prefix codes available */\n    unsigned used;              /* code entries in table used */\n    unsigned huff;              /* Huffman code */\n    unsigned incr;              /* for incrementing code, index */\n    unsigned fill;              /* index for replicating entries */\n    unsigned low;               /* low bits for current root entry */\n    unsigned mask;              /* mask for low root bits */\n    code here;                  /* table entry for duplication */\n    code FAR *next;             /* next available space in table */\n    const unsigned short FAR *base;     /* base value table to use */\n    const unsigned short FAR *extra;    /* extra bits table to use */\n    unsigned match;             /* use base and extra for symbol >= match */\n    unsigned short count[MAXBITS+1];    /* number of codes of each length */\n    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */\n    static const unsigned short lbase[31] = { /* Length codes 257..285 base */\n        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};\n    static const unsigned short lext[31] = { /* Length codes 257..285 extra */\n        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};\n    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */\n        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n        8193, 12289, 16385, 24577, 0, 0};\n    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */\n        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n        28, 28, 29, 29, 64, 64};\n\n    /*\n       Process a set of code lengths to create a canonical Huffman code.  The\n       code lengths are lens[0..codes-1].  Each length corresponds to the\n       symbols 0..codes-1.  The Huffman code is generated by first sorting the\n       symbols by length from short to long, and retaining the symbol order\n       for codes with equal lengths.  Then the code starts with all zero bits\n       for the first code of the shortest length, and the codes are integer\n       increments for the same length, and zeros are appended as the length\n       increases.  For the deflate format, these bits are stored backwards\n       from their more natural integer increment ordering, and so when the\n       decoding tables are built in the large loop below, the integer codes\n       are incremented backwards.\n\n       This routine assumes, but does not check, that all of the entries in\n       lens[] are in the range 0..MAXBITS.  The caller must assure this.\n       1..MAXBITS is interpreted as that code length.  zero means that that\n       symbol does not occur in this code.\n\n       The codes are sorted by computing a count of codes for each length,\n       creating from that a table of starting indices for each length in the\n       sorted table, and then entering the symbols in order in the sorted\n       table.  The sorted table is work[], with that space being provided by\n       the caller.\n\n       The length counts are used for other purposes as well, i.e. finding\n       the minimum and maximum length codes, determining if there are any\n       codes at all, checking for a valid set of lengths, and looking ahead\n       at length counts to determine sub-table sizes when building the\n       decoding tables.\n     */\n\n    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n    for (len = 0; len <= MAXBITS; len++)\n        count[len] = 0;\n    for (sym = 0; sym < codes; sym++)\n        count[lens[sym]]++;\n\n    /* bound code lengths, force root to be within code lengths */\n    root = *bits;\n    for (max = MAXBITS; max >= 1; max--)\n        if (count[max] != 0) break;\n    if (root > max) root = max;\n    if (max == 0) {                     /* no symbols to code at all */\n        here.op = (unsigned char)64;    /* invalid code marker */\n        here.bits = (unsigned char)1;\n        here.val = (unsigned short)0;\n        *(*table)++ = here;             /* make a table to force an error */\n        *(*table)++ = here;\n        *bits = 1;\n        return 0;     /* no symbols, but wait for decoding to report error */\n    }\n    for (min = 1; min < max; min++)\n        if (count[min] != 0) break;\n    if (root < min) root = min;\n\n    /* check for an over-subscribed or incomplete set of lengths */\n    left = 1;\n    for (len = 1; len <= MAXBITS; len++) {\n        left <<= 1;\n        left -= count[len];\n        if (left < 0) return -1;        /* over-subscribed */\n    }\n    if (left > 0 && (type == CODES || max != 1))\n        return -1;                      /* incomplete set */\n\n    /* generate offsets into symbol table for each length for sorting */\n    offs[1] = 0;\n    for (len = 1; len < MAXBITS; len++)\n        offs[len + 1] = offs[len] + count[len];\n\n    /* sort symbols by length, by symbol order within each length */\n    for (sym = 0; sym < codes; sym++)\n        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;\n\n    /*\n       Create and fill in decoding tables.  In this loop, the table being\n       filled is at next and has curr index bits.  The code being used is huff\n       with length len.  That code is converted to an index by dropping drop\n       bits off of the bottom.  For codes where len is less than drop + curr,\n       those top drop + curr - len bits are incremented through all values to\n       fill the table with replicated entries.\n\n       root is the number of index bits for the root table.  When len exceeds\n       root, sub-tables are created pointed to by the root entry with an index\n       of the low root bits of huff.  This is saved in low to check for when a\n       new sub-table should be started.  drop is zero when the root table is\n       being filled, and drop is root when sub-tables are being filled.\n\n       When a new sub-table is needed, it is necessary to look ahead in the\n       code lengths to determine what size sub-table is needed.  The length\n       counts are used for this, and so count[] is decremented as codes are\n       entered in the tables.\n\n       used keeps track of how many table entries have been allocated from the\n       provided *table space.  It is checked for LENS and DIST tables against\n       the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n       the initial root table size constants.  See the comments in inftrees.h\n       for more information.\n\n       sym increments through all symbols, and the loop terminates when\n       all codes of length max, i.e. all codes, have been processed.  This\n       routine permits incomplete codes, so another loop after this one fills\n       in the rest of the decoding tables with invalid code markers.\n     */\n\n    /* set up for code type */\n    switch (type) {\n    case CODES:\n        base = extra = work;    /* dummy value--not used */\n        match = 20;\n        break;\n    case LENS:\n        base = lbase;\n        extra = lext;\n        match = 257;\n        break;\n    default:    /* DISTS */\n        base = dbase;\n        extra = dext;\n        match = 0;\n    }\n\n    /* initialize state for loop */\n    huff = 0;                   /* starting code */\n    sym = 0;                    /* starting code symbol */\n    len = min;                  /* starting code length */\n    next = *table;              /* current table to fill in */\n    curr = root;                /* current table index bits */\n    drop = 0;                   /* current bits to drop from code for index */\n    low = (unsigned)(-1);       /* trigger new sub-table when len > root */\n    used = 1U << root;          /* use root table entries */\n    mask = used - 1;            /* mask for comparing low */\n\n    /* check available table space */\n    if ((type == LENS && used > ENOUGH_LENS) ||\n        (type == DISTS && used > ENOUGH_DISTS))\n        return 1;\n\n    /* process all codes and make table entries */\n    for (;;) {\n        /* create table entry */\n        here.bits = (unsigned char)(len - drop);\n        if (work[sym] + 1U < match) {\n            here.op = (unsigned char)0;\n            here.val = work[sym];\n        }\n        else if (work[sym] >= match) {\n            here.op = (unsigned char)(extra[work[sym] - match]);\n            here.val = base[work[sym] - match];\n        }\n        else {\n            here.op = (unsigned char)(32 + 64);         /* end of block */\n            here.val = 0;\n        }\n\n        /* replicate for those indices with low len bits equal to huff */\n        incr = 1U << (len - drop);\n        fill = 1U << curr;\n        min = fill;                 /* save offset to next table */\n        do {\n            fill -= incr;\n            next[(huff >> drop) + fill] = here;\n        } while (fill != 0);\n\n        /* backwards increment the len-bit code huff */\n        incr = 1U << (len - 1);\n        while (huff & incr)\n            incr >>= 1;\n        if (incr != 0) {\n            huff &= incr - 1;\n            huff += incr;\n        }\n        else\n            huff = 0;\n\n        /* go to next symbol, update count, len */\n        sym++;\n        if (--(count[len]) == 0) {\n            if (len == max) break;\n            len = lens[work[sym]];\n        }\n\n        /* create new sub-table if needed */\n        if (len > root && (huff & mask) != low) {\n            /* if first time, transition to sub-tables */\n            if (drop == 0)\n                drop = root;\n\n            /* increment past last table */\n            next += min;            /* here min is 1 << curr */\n\n            /* determine length of next table */\n            curr = len - drop;\n            left = (int)(1 << curr);\n            while (curr + drop < max) {\n                left -= count[curr + drop];\n                if (left <= 0) break;\n                curr++;\n                left <<= 1;\n            }\n\n            /* check for enough space */\n            used += 1U << curr;\n            if ((type == LENS && used > ENOUGH_LENS) ||\n                (type == DISTS && used > ENOUGH_DISTS))\n                return 1;\n\n            /* point entry in root table to sub-table */\n            low = huff & mask;\n            (*table)[low].op = (unsigned char)curr;\n            (*table)[low].bits = (unsigned char)root;\n            (*table)[low].val = (unsigned short)(next - *table);\n        }\n    }\n\n    /* fill in remaining table entry if code is incomplete (guaranteed to have\n       at most one remaining entry, since if the code is incomplete, the\n       maximum code length that was allowed to get this far is one bit) */\n    if (huff != 0) {\n        here.op = (unsigned char)64;            /* invalid code marker */\n        here.bits = (unsigned char)(len - drop);\n        here.val = (unsigned short)0;\n        next[huff] = here;\n    }\n\n    /* set return parameters */\n    *table += used;\n    *bits = root;\n    return 0;\n}\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/inftrees.h",
    "content": "/* inftrees.h -- header to use inftrees.c\n * Copyright (C) 1995-2005, 2010 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* Structure for decoding tables.  Each entry provides either the\n   information needed to do the operation requested by the code that\n   indexed that table entry, or it provides a pointer to another\n   table that indexes more bits of the code.  op indicates whether\n   the entry is a pointer to another table, a literal, a length or\n   distance, an end-of-block, or an invalid code.  For a table\n   pointer, the low four bits of op is the number of index bits of\n   that table.  For a length or distance, the low four bits of op\n   is the number of extra bits to get after the code.  bits is\n   the number of bits in this code or part of the code to drop off\n   of the bit buffer.  val is the actual byte to output in the case\n   of a literal, the base length or distance, or the offset from\n   the current table to the next table.  Each entry is four bytes. */\ntypedef struct {\n    unsigned char op;           /* operation, extra bits, table bits */\n    unsigned char bits;         /* bits in this part of the code */\n    unsigned short val;         /* offset in table or code value */\n} code;\n\n/* op values as set by inflate_table():\n    00000000 - literal\n    0000tttt - table link, tttt != 0 is the number of table index bits\n    0001eeee - length or distance, eeee is the number of extra bits\n    01100000 - end of block\n    01000000 - invalid code\n */\n\n/* Maximum size of the dynamic table.  The maximum number of code structures is\n   1444, which is the sum of 852 for literal/length codes and 592 for distance\n   codes.  These values were found by exhaustive searches using the program\n   examples/enough.c found in the zlib distribtution.  The arguments to that\n   program are the number of symbols, the initial root table size, and the\n   maximum bit length of a code.  \"enough 286 9 15\" for literal/length codes\n   returns returns 852, and \"enough 30 6 15\" for distance codes returns 592.\n   The initial root table size (9 or 6) is found in the fifth argument of the\n   inflate_table() calls in inflate.c and infback.c.  If the root table size is\n   changed, then these maximum sizes would be need to be recalculated and\n   updated. */\n#define ENOUGH_LENS 852\n#define ENOUGH_DISTS 592\n#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)\n\n/* Type of code to build for inflate_table() */\ntypedef enum {\n    CODES,\n    LENS,\n    DISTS\n} codetype;\n\nint ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,\n                             unsigned codes, code FAR * FAR *table,\n                             unsigned FAR *bits, unsigned short FAR *work));\n"
  },
  {
    "path": "deps/cl345/zlib/trees.c",
    "content": "/* trees.c -- output deflated data using Huffman coding\n * Copyright (C) 1995-2017 Jean-loup Gailly\n * detect_data_type() function provided freely by Cosmin Truta, 2006\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/*\n *  ALGORITHM\n *\n *      The \"deflation\" process uses several Huffman trees. The more\n *      common source values are represented by shorter bit sequences.\n *\n *      Each code tree is stored in a compressed form which is itself\n * a Huffman encoding of the lengths of all the code strings (in\n * ascending order by source values).  The actual code strings are\n * reconstructed from the lengths in the inflate process, as described\n * in the deflate specification.\n *\n *  REFERENCES\n *\n *      Deutsch, L.P.,\"'Deflate' Compressed Data Format Specification\".\n *      Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc\n *\n *      Storer, James A.\n *          Data Compression:  Methods and Theory, pp. 49-50.\n *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.\n *\n *      Sedgewick, R.\n *          Algorithms, p290.\n *          Addison-Wesley, 1983. ISBN 0-201-06672-6.\n */\n\n/* @(#) $Id$ */\n\n/* #define GEN_TREES_H */\n\n#if defined( INC_ALL )\n  #include \"deflate.h\"\n#else\n  #include \"zlib/deflate.h\"\n#endif /* Compiler-specific includes */\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\n#ifdef ZLIB_DEBUG\n#  include <ctype.h>\n#endif\n\n/* ===========================================================================\n * Constants\n */\n\n#define MAX_BL_BITS 7\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\n#define END_BLOCK 256\n/* end of block literal code */\n\n#define REP_3_6      16\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\n#define REPZ_3_10    17\n/* repeat a zero length 3-10 times  (3 bits of repeat count) */\n\n#define REPZ_11_138  18\n/* repeat a zero length 11-138 times  (7 bits of repeat count) */\n\nlocal const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */\n   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};\n\nlocal const int extra_dbits[D_CODES] /* extra bits for each distance code */\n   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};\n\nlocal const int extra_blbits[BL_CODES]/* extra bits for each bit length code */\n   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};\n\nlocal const uch bl_order[BL_CODES]\n   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\n/* ===========================================================================\n * Local data. These are initialized only once.\n */\n\n#define DIST_CODE_LEN  512 /* see definition of array dist_code below */\n\n#if defined(GEN_TREES_H) || !defined(STDC)\n/* non ANSI compilers may not accept trees.h */\n\nlocal ct_data static_ltree[L_CODES+2];\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see _tr_init\n * below).\n */\n\nlocal ct_data static_dtree[D_CODES];\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nuch _dist_code[DIST_CODE_LEN];\n/* Distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nuch _length_code[MAX_MATCH-MIN_MATCH+1];\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nlocal int base_length[LENGTH_CODES];\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nlocal int base_dist[D_CODES];\n/* First normalized distance for each code (0 = distance of 1) */\n\n#else\n#  include \"trees.h\"\n#endif /* GEN_TREES_H */\n\nstruct static_tree_desc_s {\n    const ct_data *static_tree;  /* static tree or NULL */\n    const intf *extra_bits;      /* extra bits for each code or NULL */\n    int     extra_base;          /* base index for extra_bits */\n    int     elems;               /* max number of elements in the tree */\n    int     max_length;          /* max bit length for the codes */\n};\n\nlocal const static_tree_desc  static_l_desc =\n{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};\n\nlocal const static_tree_desc  static_d_desc =\n{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};\n\nlocal const static_tree_desc  static_bl_desc =\n{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};\n\n/* ===========================================================================\n * Local (static) routines in this file.\n */\n\nlocal void tr_static_init OF((void));\nlocal void init_block     OF((deflate_state *s));\nlocal void pqdownheap     OF((deflate_state *s, ct_data *tree, int k));\nlocal void gen_bitlen     OF((deflate_state *s, tree_desc *desc));\nlocal void gen_codes      OF((ct_data *tree, int max_code, ushf *bl_count));\nlocal void build_tree     OF((deflate_state *s, tree_desc *desc));\nlocal void scan_tree      OF((deflate_state *s, ct_data *tree, int max_code));\nlocal void send_tree      OF((deflate_state *s, ct_data *tree, int max_code));\nlocal int  build_bl_tree  OF((deflate_state *s));\nlocal void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,\n                              int blcodes));\nlocal void compress_block OF((deflate_state *s, const ct_data *ltree,\n                              const ct_data *dtree));\nlocal int  detect_data_type OF((deflate_state *s));\nlocal unsigned bi_reverse OF((unsigned value, int length));\nlocal void bi_windup      OF((deflate_state *s));\nlocal void bi_flush       OF((deflate_state *s));\n\n#ifdef GEN_TREES_H\nlocal void gen_trees_header OF((void));\n#endif\n\n#ifndef ZLIB_DEBUG\n#  define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)\n   /* Send a code of the given tree. c and tree must not have side effects */\n\n#else /* !ZLIB_DEBUG */\n#  define send_code(s, c, tree) \\\n     { if (z_verbose>2) fprintf(stderr,\"\\ncd %3d \",(c)); \\\n       send_bits(s, tree[c].Code, tree[c].Len); }\n#endif\n\n/* ===========================================================================\n * Output a short LSB first on the stream.\n * IN assertion: there is enough room in pendingBuf.\n */\n#define put_short(s, w) { \\\n    put_byte(s, (uch)((w) & 0xff)); \\\n    put_byte(s, (uch)((ush)(w) >> 8)); \\\n}\n\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\n#ifdef ZLIB_DEBUG\nlocal void send_bits      OF((deflate_state *s, int value, int length));\n\nlocal void send_bits( deflate_state *s, int value, int length )\t/* pcg */\n{\n    Tracevv((stderr,\" l %2d v %4x \", length, value));\n    Assert(length > 0 && length <= 15, \"invalid length\");\n    s->bits_sent += (ulg)length;\n\n    /* If not enough room in bi_buf, use (valid) bits from bi_buf and\n     * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))\n     * unused bits in value.\n     */\n    if (s->bi_valid > (int)Buf_size - length) {\n        s->bi_buf |= (ush)value << s->bi_valid;\n        put_short(s, s->bi_buf);\n        s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);\n        s->bi_valid += length - Buf_size;\n    } else {\n        s->bi_buf |= (ush)value << s->bi_valid;\n        s->bi_valid += length;\n    }\n}\n#else /* !ZLIB_DEBUG */\n\n#define send_bits(s, value, length) \\\n{ int len = length;\\\n  if (s->bi_valid > (int)Buf_size - len) {\\\n    int val = (int)value;\\\n    s->bi_buf |= (ush)val << s->bi_valid;\\\n    put_short(s, s->bi_buf);\\\n    s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\\\n    s->bi_valid += len - Buf_size;\\\n  } else {\\\n    s->bi_buf |= (ush)(value) << s->bi_valid;\\\n    s->bi_valid += len;\\\n  }\\\n}\n#endif /* ZLIB_DEBUG */\n\n\n/* the arguments must not have side effects */\n\n/* ===========================================================================\n * Initialize the various 'constant' tables.\n */\nlocal void tr_static_init( void )\t/* pcg */\n{\n#if defined(GEN_TREES_H) || !defined(STDC)\n    static int static_init_done = 0;\n    int n;        /* iterates over tree elements */\n    int bits;     /* bit counter */\n    int length;   /* length value */\n    int code;     /* code value */\n    int dist;     /* distance index */\n    ush bl_count[MAX_BITS+1];\n    /* number of codes at each bit length for an optimal tree */\n\n    if (static_init_done) return;\n\n    /* For some embedded targets, global variables are not initialized: */\n#ifdef NO_INIT_GLOBAL_POINTERS\n    static_l_desc.static_tree = static_ltree;\n    static_l_desc.extra_bits = extra_lbits;\n    static_d_desc.static_tree = static_dtree;\n    static_d_desc.extra_bits = extra_dbits;\n    static_bl_desc.extra_bits = extra_blbits;\n#endif\n\n    /* Initialize the mapping length (0..255) -> length code (0..28) */\n    length = 0;\n    for (code = 0; code < LENGTH_CODES-1; code++) {\n        base_length[code] = length;\n        for (n = 0; n < (1<<extra_lbits[code]); n++) {\n            _length_code[length++] = (uch)code;\n        }\n    }\n    Assert (length == 256, \"tr_static_init: length != 256\");\n    /* Note that the length 255 (match length 258) can be represented\n     * in two different ways: code 284 + 5 bits or code 285, so we\n     * overwrite length_code[255] to use the best encoding:\n     */\n    _length_code[length-1] = (uch)code;\n\n    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n    dist = 0;\n    for (code = 0 ; code < 16; code++) {\n        base_dist[code] = dist;\n        for (n = 0; n < (1<<extra_dbits[code]); n++) {\n            _dist_code[dist++] = (uch)code;\n        }\n    }\n    Assert (dist == 256, \"tr_static_init: dist != 256\");\n    dist >>= 7; /* from now on, all distances are divided by 128 */\n    for ( ; code < D_CODES; code++) {\n        base_dist[code] = dist << 7;\n        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {\n            _dist_code[256 + dist++] = (uch)code;\n        }\n    }\n    Assert (dist == 256, \"tr_static_init: 256+dist != 512\");\n\n    /* Construct the codes of the static literal tree */\n    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;\n    n = 0;\n    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;\n    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;\n    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;\n    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;\n    /* Codes 286 and 287 do not exist, but we must include them in the\n     * tree construction to get a canonical Huffman tree (longest code\n     * all ones)\n     */\n    gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);\n\n    /* The static distance tree is trivial: */\n    for (n = 0; n < D_CODES; n++) {\n        static_dtree[n].Len = 5;\n        static_dtree[n].Code = bi_reverse((unsigned)n, 5);\n    }\n    static_init_done = 1;\n\n#  ifdef GEN_TREES_H\n    gen_trees_header();\n#  endif\n#endif /* defined(GEN_TREES_H) || !defined(STDC) */\n}\n\n/* ===========================================================================\n * Genererate the file trees.h describing the static trees.\n */\n#ifdef GEN_TREES_H\n#  ifndef ZLIB_DEBUG\n#    include <stdio.h>\n#  endif\n\n#  define SEPARATOR(i, last, width) \\\n      ((i) == (last)? \"\\n};\\n\\n\" :    \\\n       ((i) % (width) == (width)-1 ? \",\\n\" : \", \"))\n\nvoid gen_trees_header( void )\t/* pcg */\n{\n    FILE *header = fopen(\"trees.h\", \"w\");\n    int i;\n\n    Assert (header != NULL, \"Can't open trees.h\");\n    fprintf(header,\n            \"/* header created automatically with -DGEN_TREES_H */\\n\\n\");\n\n    fprintf(header, \"local const ct_data static_ltree[L_CODES+2] = {\\n\");\n    for (i = 0; i < L_CODES+2; i++) {\n        fprintf(header, \"{{%3u},{%3u}}%s\", static_ltree[i].Code,\n                static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));\n    }\n\n    fprintf(header, \"local const ct_data static_dtree[D_CODES] = {\\n\");\n    for (i = 0; i < D_CODES; i++) {\n        fprintf(header, \"{{%2u},{%2u}}%s\", static_dtree[i].Code,\n                static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));\n    }\n\n    fprintf(header, \"const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\\n\");\n    for (i = 0; i < DIST_CODE_LEN; i++) {\n        fprintf(header, \"%2u%s\", _dist_code[i],\n                SEPARATOR(i, DIST_CODE_LEN-1, 20));\n    }\n\n    fprintf(header,\n        \"const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\\n\");\n    for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {\n        fprintf(header, \"%2u%s\", _length_code[i],\n                SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));\n    }\n\n    fprintf(header, \"local const int base_length[LENGTH_CODES] = {\\n\");\n    for (i = 0; i < LENGTH_CODES; i++) {\n        fprintf(header, \"%1u%s\", base_length[i],\n                SEPARATOR(i, LENGTH_CODES-1, 20));\n    }\n\n    fprintf(header, \"local const int base_dist[D_CODES] = {\\n\");\n    for (i = 0; i < D_CODES; i++) {\n        fprintf(header, \"%5u%s\", base_dist[i],\n                SEPARATOR(i, D_CODES-1, 10));\n    }\n\n    fclose(header);\n}\n#endif /* GEN_TREES_H */\n\n/* ===========================================================================\n * Initialize the tree data structures for a new zlib stream.\n */\nvoid ZLIB_INTERNAL _tr_init( deflate_state *s )\t/* pcg */\n{\n    tr_static_init();\n\n    s->l_desc.dyn_tree = s->dyn_ltree;\n    s->l_desc.stat_desc = &static_l_desc;\n\n    s->d_desc.dyn_tree = s->dyn_dtree;\n    s->d_desc.stat_desc = &static_d_desc;\n\n    s->bl_desc.dyn_tree = s->bl_tree;\n    s->bl_desc.stat_desc = &static_bl_desc;\n\n    s->bi_buf = 0;\n    s->bi_valid = 0;\n#ifdef ZLIB_DEBUG\n    s->compressed_len = 0L;\n    s->bits_sent = 0L;\n#endif\n\n    /* Initialize the first block of the first file: */\n    init_block(s);\n}\n\n/* ===========================================================================\n * Initialize a new block.\n */\nlocal void init_block( deflate_state *s )\t/* pcg */\n{\n    int n; /* iterates over tree elements */\n\n    /* Initialize the trees. */\n    for (n = 0; n < L_CODES;  n++) s->dyn_ltree[n].Freq = 0;\n    for (n = 0; n < D_CODES;  n++) s->dyn_dtree[n].Freq = 0;\n    for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;\n\n    s->dyn_ltree[END_BLOCK].Freq = 1;\n    s->opt_len = s->static_len = 0L;\n    s->last_lit = s->matches = 0;\n}\n\n#define SMALLEST 1\n/* Index within the heap array of least frequent node in the Huffman tree */\n\n\n/* ===========================================================================\n * Remove the smallest element from the heap and recreate the heap with\n * one less element. Updates heap and heap_len.\n */\n#define pqremove(s, tree, top) \\\n{\\\n    top = s->heap[SMALLEST]; \\\n    s->heap[SMALLEST] = s->heap[s->heap_len--]; \\\n    pqdownheap(s, tree, SMALLEST); \\\n}\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\n#define smaller(tree, n, m, depth) \\\n   (tree[n].Freq < tree[m].Freq || \\\n   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nlocal void pqdownheap( deflate_state *s, ct_data *tree, int k )\t/* pcg */\n{\n    int v = s->heap[k];\n    int j = k << 1;  /* left son of k */\n    while (j <= s->heap_len) {\n        /* Set j to the smallest of the two sons: */\n        if (j < s->heap_len &&\n            smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {\n            j++;\n        }\n        /* Exit if v is smaller than both sons */\n        if (smaller(tree, v, s->heap[j], s->depth)) break;\n\n        /* Exchange v with the smallest son */\n        s->heap[k] = s->heap[j];  k = j;\n\n        /* And continue down the tree, setting j to the left son of k */\n        j <<= 1;\n    }\n    s->heap[k] = v;\n}\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n *    above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n *     array bl_count contains the frequencies for each bit length.\n *     The length opt_len is updated; static_len is also updated if stree is\n *     not null.\n */\nlocal void gen_bitlen( deflate_state *s, tree_desc *desc )\t/* pcg */\n{\n    ct_data *tree        = desc->dyn_tree;\n    int max_code         = desc->max_code;\n    const ct_data *stree = desc->stat_desc->static_tree;\n    const intf *extra    = desc->stat_desc->extra_bits;\n    int base             = desc->stat_desc->extra_base;\n    int max_length       = desc->stat_desc->max_length;\n    int h;              /* heap index */\n    int n, m;           /* iterate over the tree elements */\n    int bits;           /* bit length */\n    int xbits;          /* extra bits */\n    ush f;              /* frequency */\n    int overflow = 0;   /* number of elements with bit length too large */\n\n    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;\n\n    /* In a first pass, compute the optimal bit lengths (which may\n     * overflow in the case of the bit length tree).\n     */\n    tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */\n\n    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {\n        n = s->heap[h];\n        bits = tree[tree[n].Dad].Len + 1;\n        if (bits > max_length) bits = max_length, overflow++;\n        tree[n].Len = (ush)bits;\n        /* We overwrite tree[n].Dad which is no longer needed */\n\n        if (n > max_code) continue; /* not a leaf node */\n\n        s->bl_count[bits]++;\n        xbits = 0;\n        if (n >= base) xbits = extra[n-base];\n        f = tree[n].Freq;\n        s->opt_len += (ulg)f * (unsigned)(bits + xbits);\n        if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);\n    }\n    if (overflow == 0) return;\n\n    Tracev((stderr,\"\\nbit length overflow\\n\"));\n    /* This happens for example on obj2 and pic of the Calgary corpus */\n\n    /* Find the first bit length which could increase: */\n    do {\n        bits = max_length-1;\n        while (s->bl_count[bits] == 0) bits--;\n        s->bl_count[bits]--;      /* move one leaf down the tree */\n        s->bl_count[bits+1] += 2; /* move one overflow item as its brother */\n        s->bl_count[max_length]--;\n        /* The brother of the overflow item also moves one step up,\n         * but this does not affect bl_count[max_length]\n         */\n        overflow -= 2;\n    } while (overflow > 0);\n\n    /* Now recompute all bit lengths, scanning in increasing frequency.\n     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n     * lengths instead of fixing only the wrong ones. This idea is taken\n     * from 'ar' written by Haruhiko Okumura.)\n     */\n    for (bits = max_length; bits != 0; bits--) {\n        n = s->bl_count[bits];\n        while (n != 0) {\n            m = s->heap[--h];\n            if (m > max_code) continue;\n            if ((unsigned) tree[m].Len != (unsigned) bits) {\n                Tracev((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n                s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq;\n                tree[m].Len = (ush)bits;\n            }\n            n--;\n        }\n    }\n}\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n *     zero code length.\n */\nlocal void gen_codes ( ct_data *tree, int max_code, ushf *bl_count )\t/* pcg */\n{\n    ush next_code[MAX_BITS+1]; /* next code value for each bit length */\n    unsigned code = 0;         /* running code value */\n    int bits;                  /* bit index */\n    int n;                     /* code index */\n\n    /* The distribution counts are first used to generate the code values\n     * without bit reversal.\n     */\n    for (bits = 1; bits <= MAX_BITS; bits++) {\n        code = (code + bl_count[bits-1]) << 1;\n        next_code[bits] = (ush)code;\n    }\n    /* Check that the bit counts in bl_count are consistent. The last code\n     * must be all ones.\n     */\n    Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,\n            \"inconsistent bit counts\");\n    Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n    for (n = 0;  n <= max_code; n++) {\n        int len = tree[n].Len;\n        if (len == 0) continue;\n        /* Now reverse the bits */\n        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);\n\n        Tracecv(tree != static_ltree, (stderr,\"\\nn %3d %c l %2d c %4x (%x) \",\n             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));\n    }\n}\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n *     and corresponding code. The length opt_len is updated; static_len is\n *     also updated if stree is not null. The field max_code is set.\n */\nlocal void build_tree( deflate_state *s, tree_desc *desc )\t/* pcg */\n{\n    ct_data *tree         = desc->dyn_tree;\n    const ct_data *stree  = desc->stat_desc->static_tree;\n    int elems             = desc->stat_desc->elems;\n    int n, m;          /* iterate over heap elements */\n    int max_code = -1; /* largest code with non zero frequency */\n    int node;          /* new node being created */\n\n    /* Construct the initial heap, with least frequent element in\n     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n     * heap[0] is not used.\n     */\n    s->heap_len = 0, s->heap_max = HEAP_SIZE;\n\n    for (n = 0; n < elems; n++) {\n        if (tree[n].Freq != 0) {\n            s->heap[++(s->heap_len)] = max_code = n;\n            s->depth[n] = 0;\n        } else {\n            tree[n].Len = 0;\n        }\n    }\n\n    /* The pkzip format requires that at least one distance code exists,\n     * and that at least one bit should be sent even if there is only one\n     * possible code. So to avoid special checks later on we force at least\n     * two codes of non zero frequency.\n     */\n    while (s->heap_len < 2) {\n        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);\n        tree[node].Freq = 1;\n        s->depth[node] = 0;\n        s->opt_len--; if (stree) s->static_len -= stree[node].Len;\n        /* node is 0 or 1 so it does not have extra bits */\n    }\n    desc->max_code = max_code;\n\n    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n     * establish sub-heaps of increasing lengths:\n     */\n    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);\n\n    /* Construct the Huffman tree by repeatedly combining the least two\n     * frequent nodes.\n     */\n    node = elems;              /* next internal node of the tree */\n    do {\n        pqremove(s, tree, n);  /* n = node of least frequency */\n        m = s->heap[SMALLEST]; /* m = node of next least frequency */\n\n        s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */\n        s->heap[--(s->heap_max)] = m;\n\n        /* Create a new node father of n and m */\n        tree[node].Freq = tree[n].Freq + tree[m].Freq;\n        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?\n                                s->depth[n] : s->depth[m]) + 1);\n        tree[n].Dad = tree[m].Dad = (ush)node;\n#ifdef DUMP_BL_TREE\n        if (tree == s->bl_tree) {\n            fprintf(stderr,\"\\nnode %d(%d), sons %d(%d) %d(%d)\",\n                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);\n        }\n#endif\n        /* and insert the new node in the heap */\n        s->heap[SMALLEST] = node++;\n        pqdownheap(s, tree, SMALLEST);\n\n    } while (s->heap_len >= 2);\n\n    s->heap[--(s->heap_max)] = s->heap[SMALLEST];\n\n    /* At this point, the fields freq and dad are set. We can now\n     * generate the bit lengths.\n     */\n    gen_bitlen(s, (tree_desc *)desc);\n\n    /* The field len is now set, we can generate the bit codes */\n    gen_codes ((ct_data *)tree, max_code, s->bl_count);\n}\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree.\n */\nlocal void scan_tree ( deflate_state *s, ct_data *tree, int max_code )\t/* pcg */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    if (nextlen == 0) max_count = 138, min_count = 3;\n    tree[max_code+1].Len = (ush)0xffff; /* guard */\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n+1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            s->bl_tree[curlen].Freq += count;\n        } else if (curlen != 0) {\n            if (curlen != prevlen) s->bl_tree[curlen].Freq++;\n            s->bl_tree[REP_3_6].Freq++;\n        } else if (count <= 10) {\n            s->bl_tree[REPZ_3_10].Freq++;\n        } else {\n            s->bl_tree[REPZ_11_138].Freq++;\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nlocal void send_tree ( deflate_state *s, ct_data *tree, int max_code )\t/* pcg */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    /* tree[max_code+1].Len = -1; */  /* guard already set */\n    if (nextlen == 0) max_count = 138, min_count = 3;\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n+1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            do { send_code(s, curlen, s->bl_tree); } while (--count != 0);\n\n        } else if (curlen != 0) {\n            if (curlen != prevlen) {\n                send_code(s, curlen, s->bl_tree); count--;\n            }\n            Assert(count >= 3 && count <= 6, \" 3_6?\");\n            send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);\n\n        } else if (count <= 10) {\n            send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);\n\n        } else {\n            send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nlocal int build_bl_tree( deflate_state *s )\t/* pcg */\n{\n    int max_blindex;  /* index of last bit length code of non zero freq */\n\n    /* Determine the bit length frequencies for literal and distance trees */\n    scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);\n    scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);\n\n    /* Build the bit length tree: */\n    build_tree(s, (tree_desc *)(&(s->bl_desc)));\n    /* opt_len now includes the length of the tree representations, except\n     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n     */\n\n    /* Determine the number of bit length codes to send. The pkzip format\n     * requires that at least 4 bit length codes be sent. (appnote.txt says\n     * 3 but the actual value used is 4.)\n     */\n    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {\n        if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;\n    }\n    /* Update opt_len to include the bit length tree and counts */\n    s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4;\n    Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\",\n            s->opt_len, s->static_len));\n\n    return max_blindex;\n}\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nlocal void send_all_trees( deflate_state *s, int lcodes, int dcodes, int blcodes )\t/* pcg */\n{\n    int rank;                    /* index in bl_order */\n\n    Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n    Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n            \"too many codes\");\n    Tracev((stderr, \"\\nbl counts: \"));\n    send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */\n    send_bits(s, dcodes-1,   5);\n    send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */\n    for (rank = 0; rank < blcodes; rank++) {\n        Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);\n    }\n    Tracev((stderr, \"\\nbl tree: sent %ld\", s->bits_sent));\n\n    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */\n    Tracev((stderr, \"\\nlit tree: sent %ld\", s->bits_sent));\n\n    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */\n    Tracev((stderr, \"\\ndist tree: sent %ld\", s->bits_sent));\n}\n\n/* ===========================================================================\n * Send a stored block\n */\nvoid ZLIB_INTERNAL _tr_stored_block( deflate_state *s, charf *buf, ulg stored_len, int last )\t/* pcg */\n{\n    send_bits(s, (STORED_BLOCK<<1)+last, 3);    /* send block type */\n    bi_windup(s);        /* align on byte boundary */\n    put_short(s, (ush)stored_len);\n    put_short(s, (ush)~stored_len);\n    zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);\n    s->pending += stored_len;\n#ifdef ZLIB_DEBUG\n    s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;\n    s->compressed_len += (stored_len + 4) << 3;\n    s->bits_sent += 2*16;\n    s->bits_sent += stored_len<<3;\n#endif\n}\n\n/* ===========================================================================\n * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)\n */\nvoid ZLIB_INTERNAL _tr_flush_bits( deflate_state *s )\t/* pcg */\n{\n    bi_flush(s);\n}\n\n/* ===========================================================================\n * Send one empty static block to give enough lookahead for inflate.\n * This takes 10 bits, of which 7 may remain in the bit buffer.\n */\nvoid ZLIB_INTERNAL _tr_align( deflate_state *s )\t/* pcg */\n{\n    send_bits(s, STATIC_TREES<<1, 3);\n    send_code(s, END_BLOCK, static_ltree);\n#ifdef ZLIB_DEBUG\n    s->compressed_len += 10L; /* 3 for block type, 7 for EOB */\n#endif\n    bi_flush(s);\n}\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and write out the encoded block.\n */\nvoid ZLIB_INTERNAL _tr_flush_block( deflate_state *s, charf *buf, ulg stored_len, int last )\t/* pcg */\n{\n    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */\n    int max_blindex = 0;  /* index of last bit length code of non zero freq */\n\n    /* Build the Huffman trees unless a stored block is forced */\n    if (s->level > 0) {\n\n        /* Check if the file is binary or text */\n        if (s->strm->data_type == Z_UNKNOWN)\n            s->strm->data_type = detect_data_type(s);\n\n        /* Construct the literal and distance trees */\n        build_tree(s, (tree_desc *)(&(s->l_desc)));\n        Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", s->opt_len,\n                s->static_len));\n\n        build_tree(s, (tree_desc *)(&(s->d_desc)));\n        Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", s->opt_len,\n                s->static_len));\n        /* At this point, opt_len and static_len are the total bit lengths of\n         * the compressed block data, excluding the tree representations.\n         */\n\n        /* Build the bit length tree for the above two trees, and get the index\n         * in bl_order of the last bit length code to send.\n         */\n        max_blindex = build_bl_tree(s);\n\n        /* Determine the best encoding. Compute the block lengths in bytes. */\n        opt_lenb = (s->opt_len+3+7)>>3;\n        static_lenb = (s->static_len+3+7)>>3;\n\n        Tracev((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u \",\n                opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,\n                s->last_lit));\n\n        if (static_lenb <= opt_lenb) opt_lenb = static_lenb;\n\n    } else {\n        Assert(buf != (char*)0, \"lost buf\");\n        opt_lenb = static_lenb = stored_len + 5; /* force a stored block */\n    }\n\n#ifdef FORCE_STORED\n    if (buf != (char*)0) { /* force stored block */\n#else\n    if (stored_len+4 <= opt_lenb && buf != (char*)0) {\n                       /* 4: two words for the lengths */\n#endif\n        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n         * Otherwise we can't have processed more than WSIZE input bytes since\n         * the last block flush, because compression would have been\n         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n         * transform a block into a stored block.\n         */\n        _tr_stored_block(s, buf, stored_len, last);\n\n#ifdef FORCE_STATIC\n    } else if (static_lenb >= 0) { /* force static trees */\n#else\n    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {\n#endif\n        send_bits(s, (STATIC_TREES<<1)+last, 3);\n        compress_block(s, (const ct_data *)static_ltree,\n                       (const ct_data *)static_dtree);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 3 + s->static_len;\n#endif\n    } else {\n        send_bits(s, (DYN_TREES<<1)+last, 3);\n        send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,\n                       max_blindex+1);\n        compress_block(s, (const ct_data *)s->dyn_ltree,\n                       (const ct_data *)s->dyn_dtree);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 3 + s->opt_len;\n#endif\n    }\n    Assert (s->compressed_len == s->bits_sent, \"bad compressed size\");\n    /* The above check is made mod 2^32, for files larger than 512 MB\n     * and uLong implemented on 32 bits.\n     */\n    init_block(s);\n\n    if (last) {\n        bi_windup(s);\n#ifdef ZLIB_DEBUG\n        s->compressed_len += 7;  /* align on byte boundary */\n#endif\n    }\n    Tracev((stderr,\"\\ncomprlen %lu(%lu) \", s->compressed_len>>3,\n           s->compressed_len-7*last));\n}\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nint ZLIB_INTERNAL _tr_tally ( deflate_state *s, unsigned dist, unsigned lc )\t/* pcg */\n{\n    s->d_buf[s->last_lit] = (ush)dist;\n    s->l_buf[s->last_lit++] = (uch)lc;\n    if (dist == 0) {\n        /* lc is the unmatched char */\n        s->dyn_ltree[lc].Freq++;\n    } else {\n        s->matches++;\n        /* Here, lc is the match length - MIN_MATCH */\n        dist--;             /* dist = match distance - 1 */\n        Assert((ush)dist < (ush)MAX_DIST(s) &&\n               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n               (ush)d_code(dist) < (ush)D_CODES,  \"_tr_tally: bad match\");\n\n        s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;\n        s->dyn_dtree[d_code(dist)].Freq++;\n    }\n\n#ifdef TRUNCATE_BLOCK\n    /* Try to guess if it is profitable to stop the current block here */\n    if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {\n        /* Compute an upper bound for the compressed length */\n        ulg out_length = (ulg)s->last_lit*8L;\n        ulg in_length = (ulg)((long)s->strstart - s->block_start);\n        int dcode;\n        for (dcode = 0; dcode < D_CODES; dcode++) {\n            out_length += (ulg)s->dyn_dtree[dcode].Freq *\n                (5L+extra_dbits[dcode]);\n        }\n        out_length >>= 3;\n        Tracev((stderr,\"\\nlast_lit %u, in %ld, out ~%ld(%ld%%) \",\n               s->last_lit, in_length, out_length,\n               100L - out_length*100L/in_length));\n        if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;\n    }\n#endif\n    return (s->last_lit == s->lit_bufsize-1);\n    /* We avoid equality with lit_bufsize because of wraparound at 64K\n     * on 16 bit machines and because stored blocks are restricted to\n     * 64K-1 bytes.\n     */\n}\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nlocal void compress_block( deflate_state *s, const ct_data *ltree, const ct_data *dtree )\t/* pcg */\n{\n    unsigned dist;      /* distance of matched string */\n    int lc;             /* match length or unmatched char (if dist == 0) */\n    unsigned lx = 0;    /* running index in l_buf */\n    unsigned code;      /* the code to send */\n    int extra;          /* number of extra bits to send */\n\n    if (s->last_lit != 0) do {\n        dist = s->d_buf[lx];\n        lc = s->l_buf[lx++];\n        if (dist == 0) {\n            send_code(s, lc, ltree); /* send a literal byte */\n            Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n        } else {\n            /* Here, lc is the match length - MIN_MATCH */\n            code = _length_code[lc];\n            send_code(s, code+LITERALS+1, ltree); /* send the length code */\n            extra = extra_lbits[code];\n            if (extra != 0) {\n                lc -= base_length[code];\n                send_bits(s, lc, extra);       /* send the extra length bits */\n            }\n            dist--; /* dist is now the match distance - 1 */\n            code = d_code(dist);\n            Assert (code < D_CODES, \"bad d_code\");\n\n            send_code(s, code, dtree);       /* send the distance code */\n            extra = extra_dbits[code];\n            if (extra != 0) {\n                dist -= (unsigned)base_dist[code];\n                send_bits(s, dist, extra);   /* send the extra distance bits */\n            }\n        } /* literal or match pair ? */\n\n        /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */\n        Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,\n               \"pendingBuf overflow\");\n\n    } while (lx < s->last_lit);\n\n    send_code(s, END_BLOCK, ltree);\n}\n\n/* ===========================================================================\n * Check if the data type is TEXT or BINARY, using the following algorithm:\n * - TEXT if the two conditions below are satisfied:\n *    a) There are no non-portable control characters belonging to the\n *       \"black list\" (0..6, 14..25, 28..31).\n *    b) There is at least one printable character belonging to the\n *       \"white list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n * - The following partially-portable control characters form a\n *   \"gray list\" that is ignored in this detection algorithm:\n *   (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n * IN assertion: the fields Freq of dyn_ltree are set.\n */\nlocal int detect_data_type( deflate_state *s )\t/* pcg */\n{\n    /* black_mask is the bit mask of black-listed bytes\n     * set bits 0..6, 14..25, and 28..31\n     * 0xf3ffc07f = binary 11110011111111111100000001111111\n     */\n    unsigned long black_mask = 0xf3ffc07fUL;\n    int n;\n\n    /* Check for non-textual (\"black-listed\") bytes. */\n    for (n = 0; n <= 31; n++, black_mask >>= 1)\n        if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))\n            return Z_BINARY;\n\n    /* Check for textual (\"white-listed\") bytes. */\n    if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0\n            || s->dyn_ltree[13].Freq != 0)\n        return Z_TEXT;\n    for (n = 32; n < LITERALS; n++)\n        if (s->dyn_ltree[n].Freq != 0)\n            return Z_TEXT;\n\n    /* There are no \"black-listed\" or \"white-listed\" bytes:\n     * this stream either is empty or has tolerated (\"gray-listed\") bytes only.\n     */\n    return Z_BINARY;\n}\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nlocal unsigned bi_reverse( unsigned code, int len )\t/* pcg */\n{\n    register unsigned res = 0;\n    do {\n        res |= code & 1;\n        code >>= 1, res <<= 1;\n    } while (--len > 0);\n    return res >> 1;\n}\n\n/* ===========================================================================\n * Flush the bit buffer, keeping at most 7 bits in it.\n */\nlocal void bi_flush( deflate_state *s )\t/* pcg */\n{\n    if (s->bi_valid == 16) {\n        put_short(s, s->bi_buf);\n        s->bi_buf = 0;\n        s->bi_valid = 0;\n    } else if (s->bi_valid >= 8) {\n        put_byte(s, (Byte)s->bi_buf);\n        s->bi_buf >>= 8;\n        s->bi_valid -= 8;\n    }\n}\n\n/* ===========================================================================\n * Flush the bit buffer and align the output on a byte boundary\n */\nlocal void bi_windup( deflate_state *s )\t/* pcg */\n{\n    if (s->bi_valid > 8) {\n        put_short(s, s->bi_buf);\n    } else if (s->bi_valid > 0) {\n        put_byte(s, (Byte)s->bi_buf);\n    }\n    s->bi_buf = 0;\n    s->bi_valid = 0;\n#ifdef ZLIB_DEBUG\n    s->bits_sent = (s->bits_sent+7) & ~7;\n#endif\n}\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/trees.h",
    "content": "/* header created automatically with -DGEN_TREES_H */\n\nlocal const ct_data static_ltree[L_CODES+2] = {\n{{ 12},{  8}}, {{140},{  8}}, {{ 76},{  8}}, {{204},{  8}}, {{ 44},{  8}},\n{{172},{  8}}, {{108},{  8}}, {{236},{  8}}, {{ 28},{  8}}, {{156},{  8}},\n{{ 92},{  8}}, {{220},{  8}}, {{ 60},{  8}}, {{188},{  8}}, {{124},{  8}},\n{{252},{  8}}, {{  2},{  8}}, {{130},{  8}}, {{ 66},{  8}}, {{194},{  8}},\n{{ 34},{  8}}, {{162},{  8}}, {{ 98},{  8}}, {{226},{  8}}, {{ 18},{  8}},\n{{146},{  8}}, {{ 82},{  8}}, {{210},{  8}}, {{ 50},{  8}}, {{178},{  8}},\n{{114},{  8}}, {{242},{  8}}, {{ 10},{  8}}, {{138},{  8}}, {{ 74},{  8}},\n{{202},{  8}}, {{ 42},{  8}}, {{170},{  8}}, {{106},{  8}}, {{234},{  8}},\n{{ 26},{  8}}, {{154},{  8}}, {{ 90},{  8}}, {{218},{  8}}, {{ 58},{  8}},\n{{186},{  8}}, {{122},{  8}}, {{250},{  8}}, {{  6},{  8}}, {{134},{  8}},\n{{ 70},{  8}}, {{198},{  8}}, {{ 38},{  8}}, {{166},{  8}}, {{102},{  8}},\n{{230},{  8}}, {{ 22},{  8}}, {{150},{  8}}, {{ 86},{  8}}, {{214},{  8}},\n{{ 54},{  8}}, {{182},{  8}}, {{118},{  8}}, {{246},{  8}}, {{ 14},{  8}},\n{{142},{  8}}, {{ 78},{  8}}, {{206},{  8}}, {{ 46},{  8}}, {{174},{  8}},\n{{110},{  8}}, {{238},{  8}}, {{ 30},{  8}}, {{158},{  8}}, {{ 94},{  8}},\n{{222},{  8}}, {{ 62},{  8}}, {{190},{  8}}, {{126},{  8}}, {{254},{  8}},\n{{  1},{  8}}, {{129},{  8}}, {{ 65},{  8}}, {{193},{  8}}, {{ 33},{  8}},\n{{161},{  8}}, {{ 97},{  8}}, {{225},{  8}}, {{ 17},{  8}}, {{145},{  8}},\n{{ 81},{  8}}, {{209},{  8}}, {{ 49},{  8}}, {{177},{  8}}, {{113},{  8}},\n{{241},{  8}}, {{  9},{  8}}, {{137},{  8}}, {{ 73},{  8}}, {{201},{  8}},\n{{ 41},{  8}}, {{169},{  8}}, {{105},{  8}}, {{233},{  8}}, {{ 25},{  8}},\n{{153},{  8}}, {{ 89},{  8}}, {{217},{  8}}, {{ 57},{  8}}, {{185},{  8}},\n{{121},{  8}}, {{249},{  8}}, {{  5},{  8}}, {{133},{  8}}, {{ 69},{  8}},\n{{197},{  8}}, {{ 37},{  8}}, {{165},{  8}}, {{101},{  8}}, {{229},{  8}},\n{{ 21},{  8}}, {{149},{  8}}, {{ 85},{  8}}, {{213},{  8}}, {{ 53},{  8}},\n{{181},{  8}}, {{117},{  8}}, {{245},{  8}}, {{ 13},{  8}}, {{141},{  8}},\n{{ 77},{  8}}, {{205},{  8}}, {{ 45},{  8}}, {{173},{  8}}, {{109},{  8}},\n{{237},{  8}}, {{ 29},{  8}}, {{157},{  8}}, {{ 93},{  8}}, {{221},{  8}},\n{{ 61},{  8}}, {{189},{  8}}, {{125},{  8}}, {{253},{  8}}, {{ 19},{  9}},\n{{275},{  9}}, {{147},{  9}}, {{403},{  9}}, {{ 83},{  9}}, {{339},{  9}},\n{{211},{  9}}, {{467},{  9}}, {{ 51},{  9}}, {{307},{  9}}, {{179},{  9}},\n{{435},{  9}}, {{115},{  9}}, {{371},{  9}}, {{243},{  9}}, {{499},{  9}},\n{{ 11},{  9}}, {{267},{  9}}, {{139},{  9}}, {{395},{  9}}, {{ 75},{  9}},\n{{331},{  9}}, {{203},{  9}}, {{459},{  9}}, {{ 43},{  9}}, {{299},{  9}},\n{{171},{  9}}, {{427},{  9}}, {{107},{  9}}, {{363},{  9}}, {{235},{  9}},\n{{491},{  9}}, {{ 27},{  9}}, {{283},{  9}}, {{155},{  9}}, {{411},{  9}},\n{{ 91},{  9}}, {{347},{  9}}, {{219},{  9}}, {{475},{  9}}, {{ 59},{  9}},\n{{315},{  9}}, {{187},{  9}}, {{443},{  9}}, {{123},{  9}}, {{379},{  9}},\n{{251},{  9}}, {{507},{  9}}, {{  7},{  9}}, {{263},{  9}}, {{135},{  9}},\n{{391},{  9}}, {{ 71},{  9}}, {{327},{  9}}, {{199},{  9}}, {{455},{  9}},\n{{ 39},{  9}}, {{295},{  9}}, {{167},{  9}}, {{423},{  9}}, {{103},{  9}},\n{{359},{  9}}, {{231},{  9}}, {{487},{  9}}, {{ 23},{  9}}, {{279},{  9}},\n{{151},{  9}}, {{407},{  9}}, {{ 87},{  9}}, {{343},{  9}}, {{215},{  9}},\n{{471},{  9}}, {{ 55},{  9}}, {{311},{  9}}, {{183},{  9}}, {{439},{  9}},\n{{119},{  9}}, {{375},{  9}}, {{247},{  9}}, {{503},{  9}}, {{ 15},{  9}},\n{{271},{  9}}, {{143},{  9}}, {{399},{  9}}, {{ 79},{  9}}, {{335},{  9}},\n{{207},{  9}}, {{463},{  9}}, {{ 47},{  9}}, {{303},{  9}}, {{175},{  9}},\n{{431},{  9}}, {{111},{  9}}, {{367},{  9}}, {{239},{  9}}, {{495},{  9}},\n{{ 31},{  9}}, {{287},{  9}}, {{159},{  9}}, {{415},{  9}}, {{ 95},{  9}},\n{{351},{  9}}, {{223},{  9}}, {{479},{  9}}, {{ 63},{  9}}, {{319},{  9}},\n{{191},{  9}}, {{447},{  9}}, {{127},{  9}}, {{383},{  9}}, {{255},{  9}},\n{{511},{  9}}, {{  0},{  7}}, {{ 64},{  7}}, {{ 32},{  7}}, {{ 96},{  7}},\n{{ 16},{  7}}, {{ 80},{  7}}, {{ 48},{  7}}, {{112},{  7}}, {{  8},{  7}},\n{{ 72},{  7}}, {{ 40},{  7}}, {{104},{  7}}, {{ 24},{  7}}, {{ 88},{  7}},\n{{ 56},{  7}}, {{120},{  7}}, {{  4},{  7}}, {{ 68},{  7}}, {{ 36},{  7}},\n{{100},{  7}}, {{ 20},{  7}}, {{ 84},{  7}}, {{ 52},{  7}}, {{116},{  7}},\n{{  3},{  8}}, {{131},{  8}}, {{ 67},{  8}}, {{195},{  8}}, {{ 35},{  8}},\n{{163},{  8}}, {{ 99},{  8}}, {{227},{  8}}\n};\n\nlocal const ct_data static_dtree[D_CODES] = {\n{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},\n{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},\n{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},\n{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},\n{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},\n{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}\n};\n\nconst uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n 0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,\n 8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,\n10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,\n13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,\n18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,\n23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29\n};\n\nconst uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n 0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,\n13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,\n17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,\n19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,\n22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,\n23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28\n};\n\nlocal const int base_length[LENGTH_CODES] = {\n0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,\n64, 80, 96, 112, 128, 160, 192, 224, 0\n};\n\nlocal const int base_dist[D_CODES] = {\n    0,     1,     2,     3,     4,     6,     8,    12,    16,    24,\n   32,    48,    64,    96,   128,   192,   256,   384,   512,   768,\n 1024,  1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576\n};\n\n"
  },
  {
    "path": "deps/cl345/zlib/zconf.h",
    "content": "/* zconf.h -- configuration of the zlib compression library\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#ifndef ZCONF_H\n#define ZCONF_H\n\n/* Disable use of gz* functions and optional add-ons that we don't need - pcg */\n\n#define Z_SOLO\n\n/*\n * If you *really* need a unique prefix for all types and library functions,\n * compile with -DZ_PREFIX. The \"standard\" zlib should be compiled without it.\n * Even better than compiling with -DZ_PREFIX would be to use configure to set\n * this permanently in zconf.h using \"./configure --zprefix\".\n */\n#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */\n#  define Z_PREFIX_SET\n\n/* all linked symbols and init macros */\n#  define _dist_code            z__dist_code\n#  define _length_code          z__length_code\n#  define _tr_align             z__tr_align\n#  define _tr_flush_bits        z__tr_flush_bits\n#  define _tr_flush_block       z__tr_flush_block\n#  define _tr_init              z__tr_init\n#  define _tr_stored_block      z__tr_stored_block\n#  define _tr_tally             z__tr_tally\n#  define adler32               z_adler32\n#  define adler32_combine       z_adler32_combine\n#  define adler32_combine64     z_adler32_combine64\n#  define adler32_z             z_adler32_z\n#  ifndef Z_SOLO\n#    define compress              z_compress\n#    define compress2             z_compress2\n#    define compressBound         z_compressBound\n#  endif\n#  define crc32                 z_crc32\n#  define crc32_combine         z_crc32_combine\n#  define crc32_combine64       z_crc32_combine64\n#  define crc32_z               z_crc32_z\n#  define deflate               z_deflate\n#  define deflateBound          z_deflateBound\n#  define deflateCopy           z_deflateCopy\n#  define deflateEnd            z_deflateEnd\n#  define deflateGetDictionary  z_deflateGetDictionary\n#  define deflateInit           z_deflateInit\n#  define deflateInit2          z_deflateInit2\n#  define deflateInit2_         z_deflateInit2_\n#  define deflateInit_          z_deflateInit_\n#  define deflateParams         z_deflateParams\n#  define deflatePending        z_deflatePending\n#  define deflatePrime          z_deflatePrime\n#  define deflateReset          z_deflateReset\n#  define deflateResetKeep      z_deflateResetKeep\n#  define deflateSetDictionary  z_deflateSetDictionary\n#  define deflateSetHeader      z_deflateSetHeader\n#  define deflateTune           z_deflateTune\n#  define deflate_copyright     z_deflate_copyright\n#  define get_crc_table         z_get_crc_table\n#  ifndef Z_SOLO\n#    define gz_error              z_gz_error\n#    define gz_intmax             z_gz_intmax\n#    define gz_strwinerror        z_gz_strwinerror\n#    define gzbuffer              z_gzbuffer\n#    define gzclearerr            z_gzclearerr\n#    define gzclose               z_gzclose\n#    define gzclose_r             z_gzclose_r\n#    define gzclose_w             z_gzclose_w\n#    define gzdirect              z_gzdirect\n#    define gzdopen               z_gzdopen\n#    define gzeof                 z_gzeof\n#    define gzerror               z_gzerror\n#    define gzflush               z_gzflush\n#    define gzfread               z_gzfread\n#    define gzfwrite              z_gzfwrite\n#    define gzgetc                z_gzgetc\n#    define gzgetc_               z_gzgetc_\n#    define gzgets                z_gzgets\n#    define gzoffset              z_gzoffset\n#    define gzoffset64            z_gzoffset64\n#    define gzopen                z_gzopen\n#    define gzopen64              z_gzopen64\n#    ifdef _WIN32\n#      define gzopen_w              z_gzopen_w\n#    endif\n#    define gzprintf              z_gzprintf\n#    define gzputc                z_gzputc\n#    define gzputs                z_gzputs\n#    define gzread                z_gzread\n#    define gzrewind              z_gzrewind\n#    define gzseek                z_gzseek\n#    define gzseek64              z_gzseek64\n#    define gzsetparams           z_gzsetparams\n#    define gztell                z_gztell\n#    define gztell64              z_gztell64\n#    define gzungetc              z_gzungetc\n#    define gzvprintf             z_gzvprintf\n#    define gzwrite               z_gzwrite\n#  endif\n#  define inflate               z_inflate\n#  define inflateBack           z_inflateBack\n#  define inflateBackEnd        z_inflateBackEnd\n#  define inflateBackInit       z_inflateBackInit\n#  define inflateBackInit_      z_inflateBackInit_\n#  define inflateCodesUsed      z_inflateCodesUsed\n#  define inflateCopy           z_inflateCopy\n#  define inflateEnd            z_inflateEnd\n#  define inflateGetDictionary  z_inflateGetDictionary\n#  define inflateGetHeader      z_inflateGetHeader\n#  define inflateInit           z_inflateInit\n#  define inflateInit2          z_inflateInit2\n#  define inflateInit2_         z_inflateInit2_\n#  define inflateInit_          z_inflateInit_\n#  define inflateMark           z_inflateMark\n#  define inflatePrime          z_inflatePrime\n#  define inflateReset          z_inflateReset\n#  define inflateReset2         z_inflateReset2\n#  define inflateResetKeep      z_inflateResetKeep\n#  define inflateSetDictionary  z_inflateSetDictionary\n#  define inflateSync           z_inflateSync\n#  define inflateSyncPoint      z_inflateSyncPoint\n#  define inflateUndermine      z_inflateUndermine\n#  define inflateValidate       z_inflateValidate\n#  define inflate_copyright     z_inflate_copyright\n#  define inflate_fast          z_inflate_fast\n#  define inflate_table         z_inflate_table\n#  ifndef Z_SOLO\n#    define uncompress            z_uncompress\n#    define uncompress2           z_uncompress2\n#  endif\n#  define zError                z_zError\n#  ifndef Z_SOLO\n#    define zcalloc               z_zcalloc\n#    define zcfree                z_zcfree\n#  endif\n#  define zlibCompileFlags      z_zlibCompileFlags\n#  define zlibVersion           z_zlibVersion\n\n/* all zlib typedefs in zlib.h and zconf.h */\n#  define Byte                  z_Byte\n#  define Bytef                 z_Bytef\n#  define alloc_func            z_alloc_func\n#  define charf                 z_charf\n#  define free_func             z_free_func\n#  ifndef Z_SOLO\n#    define gzFile                z_gzFile\n#  endif\n#  define gz_header             z_gz_header\n#  define gz_headerp            z_gz_headerp\n#  define in_func               z_in_func\n#  define intf                  z_intf\n#  define out_func              z_out_func\n#  define uInt                  z_uInt\n#  define uIntf                 z_uIntf\n#  define uLong                 z_uLong\n#  define uLongf                z_uLongf\n#  define voidp                 z_voidp\n#  define voidpc                z_voidpc\n#  define voidpf                z_voidpf\n\n/* all zlib structs in zlib.h and zconf.h */\n#  define gz_header_s           z_gz_header_s\n#  define internal_state        z_internal_state\n\n#endif\n\n#if defined(__MSDOS__) && !defined(MSDOS)\n#  define MSDOS\n#endif\n#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)\n#  define OS2\n#endif\n#if defined(_WINDOWS) && !defined(WINDOWS)\n#  define WINDOWS\n#endif\n#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)\n#  ifndef WIN32\n#    define WIN32\n#  endif\n#endif\n#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)\n#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)\n#    ifndef SYS16BIT\n#      define SYS16BIT\n#    endif\n#  endif\n#endif\n\n/*\n * Compile with -DMAXSEG_64K if the alloc function cannot allocate more\n * than 64k bytes at a time (needed on systems with 16-bit int).\n */\n#ifdef SYS16BIT\n#  define MAXSEG_64K\n#endif\n#ifdef MSDOS\n#  define UNALIGNED_OK\n#endif\n\n#ifdef __STDC_VERSION__\n#  ifndef STDC\n#    define STDC\n#  endif\n#  if __STDC_VERSION__ >= 199901L\n#    ifndef STDC99\n#      define STDC99\n#    endif\n#  endif\n#endif\n#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))\n#  define STDC\n#endif\n#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))\n#  define STDC\n#endif\n\n#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */\n#  define STDC\n#endif\n\n#ifndef STDC\n#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */\n#    define const       /* note: need a more gentle solution here */\n#  endif\n#endif\n\n#if defined(ZLIB_CONST) && !defined(z_const)\n#  define z_const const\n#else\n#  define z_const\n#endif\n\n#ifdef Z_SOLO\n   typedef unsigned long z_size_t;\n#else\n#  define z_longlong long long\n#  if defined(NO_SIZE_T)\n     typedef unsigned NO_SIZE_T z_size_t;\n#  elif defined(STDC)\n#    include <stddef.h>\n     typedef size_t z_size_t;\n#  else\n     typedef unsigned long z_size_t;\n#  endif\n#  undef z_longlong\n#endif\n\n/* Maximum value for memLevel in deflateInit2 */\n#ifndef MAX_MEM_LEVEL\n#  ifdef MAXSEG_64K\n#    define MAX_MEM_LEVEL 8\n#  else\n#    define MAX_MEM_LEVEL 9\n#  endif\n#endif\n\n/* Maximum value for windowBits in deflateInit2 and inflateInit2.\n * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files\n * created by gzip. (Files created by minigzip can still be extracted by\n * gzip.)\n */\n#ifndef MAX_WBITS\n#  define MAX_WBITS   15 /* 32K LZ77 window */\n#endif\n\n/* The memory requirements for deflate are (in bytes):\n            (1 << (windowBits+2)) +  (1 << (memLevel+9))\n that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)\n plus a few kilobytes for small objects. For example, if you want to reduce\n the default memory requirements from 256K to 128K, compile with\n     make CFLAGS=\"-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7\"\n Of course this will generally degrade compression (there's no free lunch).\n\n   The memory requirements for inflate are (in bytes) 1 << windowBits\n that is, 32K for windowBits=15 (default value) plus about 7 kilobytes\n for small objects.\n*/\n\n                        /* Type declarations */\n\n#ifndef OF /* function prototypes */\n#  ifdef STDC\n#    define OF(args)  args\n#  else\n#    define OF(args)  ()\n#  endif\n#endif\n\n#ifndef Z_ARG /* function prototypes for stdarg */\n#  if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#    define Z_ARG(args)  args\n#  else\n#    define Z_ARG(args)  ()\n#  endif\n#endif\n\n/* The following definitions for FAR are needed only for MSDOS mixed\n * model programming (small or medium model with some far allocations).\n * This was tested only with MSC; for other MSDOS compilers you may have\n * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,\n * just define FAR to be empty.\n */\n#ifdef SYS16BIT\n#  if defined(M_I86SM) || defined(M_I86MM)\n     /* MSC small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef _MSC_VER\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#  if (defined(__SMALL__) || defined(__MEDIUM__))\n     /* Turbo C small or medium model */\n#    define SMALL_MEDIUM\n#    ifdef __BORLANDC__\n#      define FAR _far\n#    else\n#      define FAR far\n#    endif\n#  endif\n#endif\n\n#if defined(WINDOWS) || defined(WIN32)\n   /* If building or using zlib as a DLL, define ZLIB_DLL.\n    * This is not mandatory, but it offers a little performance increase.\n    */\n#  ifdef ZLIB_DLL\n#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))\n#      ifdef ZLIB_INTERNAL\n#        define ZEXTERN extern __declspec(dllexport)\n#      else\n#        define ZEXTERN extern __declspec(dllimport)\n#      endif\n#    endif\n#  endif  /* ZLIB_DLL */\n   /* If building or using zlib with the WINAPI/WINAPIV calling convention,\n    * define ZLIB_WINAPI.\n    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.\n    */\n#  ifdef ZLIB_WINAPI\n#    ifdef FAR\n#      undef FAR\n#    endif\n#    include <windows.h>\n     /* No need for _export, use ZLIB.DEF instead. */\n     /* For complete Windows compatibility, use WINAPI, not __stdcall. */\n#    define ZEXPORT WINAPI\n#    ifdef WIN32\n#      define ZEXPORTVA WINAPIV\n#    else\n#      define ZEXPORTVA FAR CDECL\n#    endif\n#  endif\n#endif\n\n#if defined (__BEOS__)\n#  ifdef ZLIB_DLL\n#    ifdef ZLIB_INTERNAL\n#      define ZEXPORT   __declspec(dllexport)\n#      define ZEXPORTVA __declspec(dllexport)\n#    else\n#      define ZEXPORT   __declspec(dllimport)\n#      define ZEXPORTVA __declspec(dllimport)\n#    endif\n#  endif\n#endif\n\n#ifndef ZEXTERN\n#  define ZEXTERN extern\n#endif\n#ifndef ZEXPORT\n#  define ZEXPORT\n#endif\n#ifndef ZEXPORTVA\n#  define ZEXPORTVA\n#endif\n\n#ifndef FAR\n#  define FAR\n#endif\n\n#if !defined(__MACTYPES__)\ntypedef unsigned char  Byte;  /* 8 bits */\n#endif\ntypedef unsigned int   uInt;  /* 16 bits or more */\ntypedef unsigned long  uLong; /* 32 bits or more */\n\n#ifdef SMALL_MEDIUM\n   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */\n#  define Bytef Byte FAR\n#else\n   typedef Byte  FAR Bytef;\n#endif\ntypedef char  FAR charf;\ntypedef int   FAR intf;\ntypedef uInt  FAR uIntf;\ntypedef uLong FAR uLongf;\n\n#ifdef STDC\n   typedef void const *voidpc;\n   typedef void FAR   *voidpf;\n   typedef void       *voidp;\n#else\n   typedef Byte const *voidpc;\n   typedef Byte FAR   *voidpf;\n   typedef Byte       *voidp;\n#endif\n\n#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)\n#  include <limits.h>\n#  if (UINT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned\n#  elif (ULONG_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned long\n#  elif (USHRT_MAX == 0xffffffffUL)\n#    define Z_U4 unsigned short\n#  endif\n#endif\n\n#ifdef Z_U4\n   typedef Z_U4 z_crc_t;\n#else\n   typedef unsigned long z_crc_t;\n#endif\n\n#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_UNISTD_H\n#endif\n\n#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */\n#  define Z_HAVE_STDARG_H\n#endif\n\n#ifdef STDC\n#  ifndef Z_SOLO\n#    include <sys/types.h>      /* for off_t */\n#  endif\n#endif\n\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\n#    include <stdarg.h>         /* for va_list */\n#  endif\n#endif\n\n#ifdef _WIN32\n#  ifndef Z_SOLO\n#    include <stddef.h>         /* for wchar_t */\n#  endif\n#endif\n\n/* a little trick to accommodate both \"#define _LARGEFILE64_SOURCE\" and\n * \"#define _LARGEFILE64_SOURCE 1\" as requesting 64-bit operations, (even\n * though the former does not conform to the LFS document), but considering\n * both \"#undef _LARGEFILE64_SOURCE\" and \"#define _LARGEFILE64_SOURCE 0\" as\n * equivalently requesting no 64-bit operations\n */\n#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1\n#  undef _LARGEFILE64_SOURCE\n#endif\n\n#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)\n#  define Z_HAVE_UNISTD_H\n#endif\n#ifndef Z_SOLO\n#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)\n#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */\n#    ifdef VMS\n#      include <unixio.h>       /* for off_t */\n#    endif\n#    ifndef z_off_t\n#      define z_off_t off_t\n#    endif\n#  endif\n#endif\n\n#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0\n#  define Z_LFS64\n#endif\n\n#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)\n#  define Z_LARGE64\n#endif\n\n#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)\n#  define Z_WANT64\n#endif\n\n#if !defined(SEEK_SET) && !defined(Z_SOLO)\n#  define SEEK_SET        0       /* Seek from beginning of file.  */\n#  define SEEK_CUR        1       /* Seek from current position.  */\n#  define SEEK_END        2       /* Set file pointer to EOF plus \"offset\" */\n#endif\n\n#ifndef z_off_t\n#  define z_off_t long\n#endif\n\n#if !defined(_WIN32) && defined(Z_LARGE64)\n#  define z_off64_t off64_t\n#else\n#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)\n#    define z_off64_t __int64\n#  else\n#    define z_off64_t z_off_t\n#  endif\n#endif\n\n/* MVS linker does not support external names larger than 8 bytes */\n#if defined(__MVS__)\n  #pragma map(deflateInit_,\"DEIN\")\n  #pragma map(deflateInit2_,\"DEIN2\")\n  #pragma map(deflateEnd,\"DEEND\")\n  #pragma map(deflateBound,\"DEBND\")\n  #pragma map(inflateInit_,\"ININ\")\n  #pragma map(inflateInit2_,\"ININ2\")\n  #pragma map(inflateEnd,\"INEND\")\n  #pragma map(inflateSync,\"INSY\")\n  #pragma map(inflateSetDictionary,\"INSEDI\")\n  #pragma map(compressBound,\"CMBND\")\n  #pragma map(inflate_table,\"INTABL\")\n  #pragma map(inflate_fast,\"INFA\")\n  #pragma map(inflate_copyright,\"INCOPY\")\n#endif\n\n#endif /* ZCONF_H */\n"
  },
  {
    "path": "deps/cl345/zlib/zlib.h",
    "content": "/* zlib.h -- interface of the 'zlib' general purpose compression library\n  version 1.2.11, January 15th, 2017\n\n  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  Jean-loup Gailly        Mark Adler\n  jloup@gzip.org          madler@alumni.caltech.edu\n\n\n  The data format used by the zlib library is described by RFCs (Request for\n  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950\n  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).\n*/\n\n#ifndef ZLIB_H\n#define ZLIB_H\n\n#if defined( INC_ALL )\n  #include \"config.h\"\n  #include \"zconf.h\"\n#else\n  #include \"misc/config.h\"\n  #include \"zlib/zconf.h\"\n#endif /* Compiler-specific includes */\n\n/* Disable gzip header inclusion and crc32 code - pcg */\n\n#define NO_GZIP\n#define NO_GUNZIP\n\n/* VxWorks includes its own internal copy of zlib so we need to correct \n   clashing global symbols in order to avoid link errors */\n\n#ifdef __VxWorks__\n  #define inflate\t\t\t\tcl_inflate\n  #define inflate_copyright\t\tcl_inflate_copyright\n  #define zlibVersion\t\t\tcl_zlibVersion\n#endif /* __VxWorks__ */\n\n/* Also need to disable attempt to include errno.h, this is never used so\n   it's easiest to edit it out of zutil.h - pcg */\n\n#if defined( ZLIB_INTERNAL ) && defined( _MSC_VER )\n  /* cryptlib is built with the highest warning level, disable some of the\n     more irritating warnings produced by the zlib code.  In theory we\n\t could also disable warnings about K&R style declarations with\n\t '#pragma warning( disable: 4131 )', but we need to catch and manually\n\t fix all of these for the PalmOS gcc, so we leave them enabled - pcg */\n  #pragma warning( disable: 4127 )\t/* Conditional is constant: while( TRUE ) */\n  #pragma warning( disable: 4244 )\t/* int <-> unsigned char/short */\n#endif /* zlib-internal code under VC++ */\n\n/* For some totally insane reason zlib uses 1970s-vintage K&R-style function \n   declarations internally, requiring manual editing of every single internal \n   function prototype in every single zlib file in order for it to compile \n   - pcg */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ZLIB_VERSION \"1.2.11\"\n#define ZLIB_VERNUM 0x12b0\n#define ZLIB_VER_MAJOR 1\n#define ZLIB_VER_MINOR 2\n#define ZLIB_VER_REVISION 11\n#define ZLIB_VER_SUBREVISION 0\n\n/*\n    The 'zlib' compression library provides in-memory compression and\n  decompression functions, including integrity checks of the uncompressed data.\n  This version of the library supports only one compression method (deflation)\n  but other algorithms will be added later and will have the same stream\n  interface.\n\n    Compression can be done in a single step if the buffers are large enough,\n  or can be done by repeated calls of the compression function.  In the latter\n  case, the application must provide more input and/or consume the output\n  (providing more output space) before each call.\n\n    The compressed data format used by default by the in-memory functions is\n  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped\n  around a deflate stream, which is itself documented in RFC 1951.\n\n    The library also supports reading and writing files in gzip (.gz) format\n  with an interface similar to that of stdio using the functions that start\n  with \"gz\".  The gzip format is different from the zlib format.  gzip is a\n  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.\n\n    This library can optionally read and write gzip and raw deflate streams in\n  memory as well.\n\n    The zlib format was designed to be compact and fast for use in memory\n  and on communications channels.  The gzip format was designed for single-\n  file compression on file systems, has a larger header than zlib to maintain\n  directory information, and uses a different, slower check method than zlib.\n\n    The library does not install any signal handler.  The decoder checks\n  the consistency of the compressed data, so the library should never crash\n  even in the case of corrupted input.\n*/\n\ntypedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));\ntypedef void   (*free_func)  OF((voidpf opaque, voidpf address));\n\nstruct internal_state;\n\ntypedef struct z_stream_s {\n    z_const Bytef *next_in;     /* next input byte */\n    uInt     avail_in;  /* number of bytes available at next_in */\n    uLong    total_in;  /* total number of input bytes read so far */\n\n    Bytef    *next_out; /* next output byte will go here */\n    uInt     avail_out; /* remaining free space at next_out */\n    uLong    total_out; /* total number of bytes output so far */\n\n    z_const char *msg;  /* last error message, NULL if no error */\n    struct internal_state FAR *state; /* not visible by applications */\n\n    alloc_func zalloc;  /* used to allocate the internal state */\n    free_func  zfree;   /* used to free the internal state */\n    voidpf     opaque;  /* private data object passed to zalloc and zfree */\n\n    int     data_type;  /* best guess about the data type: binary or text\n                           for deflate, or the decoding state for inflate */\n    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */\n    uLong   reserved;   /* reserved for future use */\n} z_stream;\n\ntypedef z_stream FAR *z_streamp;\n\n/*\n     gzip header information passed to and from zlib routines.  See RFC 1952\n  for more details on the meanings of these fields.\n*/\ntypedef struct gz_header_s {\n    int     text;       /* true if compressed data believed to be text */\n    uLong   time;       /* modification time */\n    int     xflags;     /* extra flags (not used when writing a gzip file) */\n    int     os;         /* operating system */\n    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */\n    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */\n    uInt    extra_max;  /* space at extra (only when reading header) */\n    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */\n    uInt    name_max;   /* space at name (only when reading header) */\n    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */\n    uInt    comm_max;   /* space at comment (only when reading header) */\n    int     hcrc;       /* true if there was or will be a header crc */\n    int     done;       /* true when done reading gzip header (not used\n                           when writing a gzip file) */\n} gz_header;\n\ntypedef gz_header FAR *gz_headerp;\n\n/*\n     The application must update next_in and avail_in when avail_in has dropped\n   to zero.  It must update next_out and avail_out when avail_out has dropped\n   to zero.  The application must initialize zalloc, zfree and opaque before\n   calling the init function.  All other fields are set by the compression\n   library and must not be updated by the application.\n\n     The opaque value provided by the application will be passed as the first\n   parameter for calls of zalloc and zfree.  This can be useful for custom\n   memory management.  The compression library attaches no meaning to the\n   opaque value.\n\n     zalloc must return Z_NULL if there is not enough memory for the object.\n   If zlib is used in a multi-threaded application, zalloc and zfree must be\n   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are\n   Z_NULL on entry to the initialization function, they are set to internal\n   routines that use the standard library functions malloc() and free().\n\n     On 16-bit systems, the functions zalloc and zfree must be able to allocate\n   exactly 65536 bytes, but will not be required to allocate more than this if\n   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers\n   returned by zalloc for objects of exactly 65536 bytes *must* have their\n   offset normalized to zero.  The default allocation function provided by this\n   library ensures this (see zutil.c).  To reduce memory requirements and avoid\n   any allocation of 64K objects, at the expense of compression ratio, compile\n   the library with -DMAX_WBITS=14 (see zconf.h).\n\n     The fields total_in and total_out can be used for statistics or progress\n   reports.  After compression, total_in holds the total size of the\n   uncompressed data and may be saved for use by the decompressor (particularly\n   if the decompressor wants to decompress everything in a single step).\n*/\n\n                        /* constants */\n\n#define Z_NO_FLUSH      0\n#define Z_PARTIAL_FLUSH 1\n#define Z_SYNC_FLUSH    2\n#define Z_FULL_FLUSH    3\n#define Z_FINISH        4\n#define Z_BLOCK         5\n#define Z_TREES         6\n/* Allowed flush values; see deflate() and inflate() below for details */\n\n#define Z_OK            0\n#define Z_STREAM_END    1\n#define Z_NEED_DICT     2\n#define Z_ERRNO        (-1)\n#define Z_STREAM_ERROR (-2)\n#define Z_DATA_ERROR   (-3)\n#define Z_MEM_ERROR    (-4)\n#define Z_BUF_ERROR    (-5)\n#define Z_VERSION_ERROR (-6)\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\n\n#define Z_NO_COMPRESSION         0\n#define Z_BEST_SPEED             1\n#define Z_BEST_COMPRESSION       9\n#define Z_DEFAULT_COMPRESSION  (-1)\n/* compression levels */\n\n#define Z_FILTERED            1\n#define Z_HUFFMAN_ONLY        2\n#define Z_RLE                 3\n#define Z_FIXED               4\n#define Z_DEFAULT_STRATEGY    0\n/* compression strategy; see deflateInit2() below for details */\n\n#define Z_BINARY   0\n#define Z_TEXT     1\n#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */\n#define Z_UNKNOWN  2\n/* Possible values of the data_type field for deflate() */\n\n#define Z_DEFLATED   8\n/* The deflate compression method (the only one supported in this version) */\n\n#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */\n\n#define zlib_version zlibVersion()\n/* for compatibility with versions < 1.0.2 */\n\n\n                        /* basic functions */\n\nZEXTERN const char * ZEXPORT zlibVersion OF((void));\n/* The application can compare zlibVersion and ZLIB_VERSION for consistency.\n   If the first character differs, the library code actually used is not\n   compatible with the zlib.h header file used by the application.  This check\n   is automatically made by deflateInit and inflateInit.\n */\n\n/*\nZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));\n\n     Initializes the internal stream state for compression.  The fields\n   zalloc, zfree and opaque must be initialized before by the caller.  If\n   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default\n   allocation functions.\n\n     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:\n   1 gives best speed, 9 gives best compression, 0 gives no compression at all\n   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION\n   requests a default compromise between speed and compression (currently\n   equivalent to level 6).\n\n     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if level is not a valid compression level, or\n   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible\n   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null\n   if there is no error message.  deflateInit does not perform any compression:\n   this will be done by deflate().\n*/\n\n\nZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));\n/*\n    deflate compresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n    The detailed semantics are as follows.  deflate performs one or both of the\n  following actions:\n\n  - Compress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), next_in and avail_in are updated and\n    processing will resume at this point for the next call of deflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  This action is forced if the parameter flush is non zero.\n    Forcing flush frequently degrades the compression ratio, so this parameter\n    should be set only when necessary.  Some output may be provided even if\n    flush is zero.\n\n    Before the call of deflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating avail_in or avail_out accordingly; avail_out should\n  never be zero before the call.  The application can consume the compressed\n  output when it wants, for example when the output buffer is full (avail_out\n  == 0), or after each call of deflate().  If deflate returns Z_OK and with\n  zero avail_out, it must be called again after making room in the output\n  buffer because there might be more output pending. See deflatePending(),\n  which can be used if desired to determine whether or not there is more ouput\n  in that case.\n\n    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to\n  decide how much data to accumulate before producing output, in order to\n  maximize compression.\n\n    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is\n  flushed to the output buffer and the output is aligned on a byte boundary, so\n  that the decompressor can get all input data available so far.  (In\n  particular avail_in is zero after the call if enough output space has been\n  provided before the call.) Flushing may degrade compression for some\n  compression algorithms and so it should be used only when necessary.  This\n  completes the current deflate block and follows it with an empty stored block\n  that is three bits plus filler bits to the next byte, followed by four bytes\n  (00 00 ff ff).\n\n    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the\n  output buffer, but the output is not aligned to a byte boundary.  All of the\n  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.\n  This completes the current deflate block and follows it with an empty fixed\n  codes block that is 10 bits long.  This assures that enough bytes are output\n  in order for the decompressor to finish the block before the empty fixed\n  codes block.\n\n    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as\n  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to\n  seven bits of the current block are held to be written as the next byte after\n  the next deflate block is completed.  In this case, the decompressor may not\n  be provided enough bits at this point in order to complete decompression of\n  the data provided so far to the compressor.  It may need to wait for the next\n  block to be emitted.  This is for advanced applications that need to control\n  the emission of deflate blocks.\n\n    If flush is set to Z_FULL_FLUSH, all output is flushed as with\n  Z_SYNC_FLUSH, and the compression state is reset so that decompression can\n  restart from this point if previous compressed data has been damaged or if\n  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade\n  compression.\n\n    If deflate returns with avail_out == 0, this function must be called again\n  with the same value of the flush parameter and more output space (updated\n  avail_out), until the flush is complete (deflate returns with non-zero\n  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that\n  avail_out is greater than six to avoid repeated flush markers due to\n  avail_out == 0 on return.\n\n    If the parameter flush is set to Z_FINISH, pending input is processed,\n  pending output is flushed and deflate returns with Z_STREAM_END if there was\n  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this\n  function must be called again with Z_FINISH and more output space (updated\n  avail_out) but no more input data, until it returns with Z_STREAM_END or an\n  error.  After deflate has returned Z_STREAM_END, the only possible operations\n  on the stream are deflateReset or deflateEnd.\n\n    Z_FINISH can be used in the first deflate call after deflateInit if all the\n  compression is to be done in a single step.  In order to complete in one\n  call, avail_out must be at least the value returned by deflateBound (see\n  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough\n  output space is provided, deflate will not return Z_STREAM_END, and it must\n  be called again as described above.\n\n    deflate() sets strm->adler to the Adler-32 checksum of all input read\n  so far (that is, total_in bytes).  If a gzip stream is being generated, then\n  strm->adler will be the CRC-32 checksum of the input read so far.  (See\n  deflateInit2 below.)\n\n    deflate() may update strm->data_type if it can make a good guess about\n  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is\n  considered binary.  This field is only for information purposes and does not\n  affect the compression algorithm in any manner.\n\n    deflate() returns Z_OK if some progress has been made (more input\n  processed or more output produced), Z_STREAM_END if all input has been\n  consumed and all output has been produced (only when flush is set to\n  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example\n  if next_in or next_out was Z_NULL or the state was inadvertently written over\n  by the application), or Z_BUF_ERROR if no progress is possible (for example\n  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and\n  deflate() can be called again with more input and more output space to\n  continue compressing.\n*/\n\n\nZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the\n   stream state was inconsistent, Z_DATA_ERROR if the stream was freed\n   prematurely (some input or output was discarded).  In the error case, msg\n   may be set but then points to a static string (which must not be\n   deallocated).\n*/\n\n\n/*\nZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));\n\n     Initializes the internal stream state for decompression.  The fields\n   next_in, avail_in, zalloc, zfree and opaque must be initialized before by\n   the caller.  In the current version of inflate, the provided input is not\n   read or consumed.  The allocation of a sliding window will be deferred to\n   the first call of inflate (if the decompression does not complete on the\n   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates\n   them to use default allocation functions.\n\n     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit does not perform any decompression.\n   Actual decompression will be done by inflate().  So next_in, and avail_in,\n   next_out, and avail_out are unused and unchanged.  The current\n   implementation of inflateInit() does not process any header information --\n   that is deferred until inflate() is called.\n*/\n\n\nZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));\n/*\n    inflate decompresses as much data as possible, and stops when the input\n  buffer becomes empty or the output buffer becomes full.  It may introduce\n  some output latency (reading input without producing any output) except when\n  forced to flush.\n\n  The detailed semantics are as follows.  inflate performs one or both of the\n  following actions:\n\n  - Decompress more input starting at next_in and update next_in and avail_in\n    accordingly.  If not all input can be processed (because there is not\n    enough room in the output buffer), then next_in and avail_in are updated\n    accordingly, and processing will resume at this point for the next call of\n    inflate().\n\n  - Generate more output starting at next_out and update next_out and avail_out\n    accordingly.  inflate() provides as much output as possible, until there is\n    no more input data or no more space in the output buffer (see below about\n    the flush parameter).\n\n    Before the call of inflate(), the application should ensure that at least\n  one of the actions is possible, by providing more input and/or consuming more\n  output, and updating the next_* and avail_* values accordingly.  If the\n  caller of inflate() does not provide both available input and available\n  output space, it is possible that there will be no progress made.  The\n  application can consume the uncompressed output when it wants, for example\n  when the output buffer is full (avail_out == 0), or after each call of\n  inflate().  If inflate returns Z_OK and with zero avail_out, it must be\n  called again after making room in the output buffer because there might be\n  more output pending.\n\n    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,\n  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much\n  output as possible to the output buffer.  Z_BLOCK requests that inflate()\n  stop if and when it gets to the next deflate block boundary.  When decoding\n  the zlib or gzip format, this will cause inflate() to return immediately\n  after the header and before the first block.  When doing a raw inflate,\n  inflate() will go ahead and process the first block, and will return when it\n  gets to the end of that block, or when it runs out of data.\n\n    The Z_BLOCK option assists in appending to or combining deflate streams.\n  To assist in this, on return inflate() always sets strm->data_type to the\n  number of unused bits in the last byte taken from strm->next_in, plus 64 if\n  inflate() is currently decoding the last block in the deflate stream, plus\n  128 if inflate() returned immediately after decoding an end-of-block code or\n  decoding the complete header up to just before the first byte of the deflate\n  stream.  The end-of-block will not be indicated until all of the uncompressed\n  data from that block has been written to strm->next_out.  The number of\n  unused bits may in general be greater than seven, except when bit 7 of\n  data_type is set, in which case the number of unused bits will be less than\n  eight.  data_type is set as noted here every time inflate() returns for all\n  flush options, and so can be used to determine the amount of currently\n  consumed input in bits.\n\n    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the\n  end of each deflate block header is reached, before any actual data in that\n  block is decoded.  This allows the caller to determine the length of the\n  deflate block header for later use in random access within a deflate block.\n  256 is added to the value of strm->data_type when inflate() returns\n  immediately after reaching the end of the deflate block header.\n\n    inflate() should normally be called until it returns Z_STREAM_END or an\n  error.  However if all decompression is to be performed in a single step (a\n  single call of inflate), the parameter flush should be set to Z_FINISH.  In\n  this case all pending input is processed and all pending output is flushed;\n  avail_out must be large enough to hold all of the uncompressed data for the\n  operation to complete.  (The size of the uncompressed data may have been\n  saved by the compressor for this purpose.)  The use of Z_FINISH is not\n  required to perform an inflation in one step.  However it may be used to\n  inform inflate that a faster approach can be used for the single inflate()\n  call.  Z_FINISH also informs inflate to not maintain a sliding window if the\n  stream completes, which reduces inflate's memory footprint.  If the stream\n  does not complete, either because not all of the stream is provided or not\n  enough output space is provided, then a sliding window will be allocated and\n  inflate() can be called again to continue the operation as if Z_NO_FLUSH had\n  been used.\n\n     In this implementation, inflate() always flushes as much output as\n  possible to the output buffer, and always uses the faster approach on the\n  first call.  So the effects of the flush parameter in this implementation are\n  on the return value of inflate() as noted below, when inflate() returns early\n  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of\n  memory for a sliding window when Z_FINISH is used.\n\n     If a preset dictionary is needed after this call (see inflateSetDictionary\n  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary\n  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets\n  strm->adler to the Adler-32 checksum of all output produced so far (that is,\n  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described\n  below.  At the end of the stream, inflate() checks that its computed Adler-32\n  checksum is equal to that saved by the compressor and returns Z_STREAM_END\n  only if the checksum is correct.\n\n    inflate() can decompress and check either zlib-wrapped or gzip-wrapped\n  deflate data.  The header type is detected automatically, if requested when\n  initializing with inflateInit2().  Any information contained in the gzip\n  header is not retained unless inflateGetHeader() is used.  When processing\n  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output\n  produced so far.  The CRC-32 is checked against the gzip trailer, as is the\n  uncompressed length, modulo 2^32.\n\n    inflate() returns Z_OK if some progress has been made (more input processed\n  or more output produced), Z_STREAM_END if the end of the compressed data has\n  been reached and all uncompressed output has been produced, Z_NEED_DICT if a\n  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\n  corrupted (input stream not conforming to the zlib format or incorrect check\n  value, in which case strm->msg points to a string with a more specific\n  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example\n  next_in or next_out was Z_NULL, or the state was inadvertently written over\n  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR\n  if no progress was possible or if there was not enough room in the output\n  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and\n  inflate() can be called again with more input and more output space to\n  continue decompressing.  If Z_DATA_ERROR is returned, the application may\n  then call inflateSync() to look for a good compression block if a partial\n  recovery of the data is to be attempted.\n*/\n\n\nZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));\n/*\n     All dynamically allocated data structures for this stream are freed.\n   This function discards any unprocessed input and does not flush any pending\n   output.\n\n     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state\n   was inconsistent.\n*/\n\n\n                        /* Advanced functions */\n\n/*\n    The following functions are needed only in some special applications.\n*/\n\n/*\nZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,\n                                     int  level,\n                                     int  method,\n                                     int  windowBits,\n                                     int  memLevel,\n                                     int  strategy));\n\n     This is another version of deflateInit with more compression options.  The\n   fields next_in, zalloc, zfree and opaque must be initialized before by the\n   caller.\n\n     The method parameter is the compression method.  It must be Z_DEFLATED in\n   this version of the library.\n\n     The windowBits parameter is the base two logarithm of the window size\n   (the size of the history buffer).  It should be in the range 8..15 for this\n   version of the library.  Larger values of this parameter result in better\n   compression at the expense of memory usage.  The default value is 15 if\n   deflateInit is used instead.\n\n     For the current implementation of deflate(), a windowBits value of 8 (a\n   window size of 256 bytes) is not supported.  As a result, a request for 8\n   will result in 9 (a 512-byte window).  In that case, providing 8 to\n   inflateInit2() will result in an error when the zlib header with 9 is\n   checked against the initialization of inflate().  The remedy is to not use 8\n   with deflateInit2() with this initialization, or at least in that case use 9\n   with inflateInit2().\n\n     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits\n   determines the window size.  deflate() will then generate raw deflate data\n   with no zlib header or trailer, and will not compute a check value.\n\n     windowBits can also be greater than 15 for optional gzip encoding.  Add\n   16 to windowBits to write a simple gzip header and trailer around the\n   compressed data instead of a zlib wrapper.  The gzip header will have no\n   file name, no extra data, no comment, no modification time (set to zero), no\n   header crc, and the operating system will be set to the appropriate value,\n   if the operating system was determined at compile time.  If a gzip stream is\n   being written, strm->adler is a CRC-32 instead of an Adler-32.\n\n     For raw deflate or gzip encoding, a request for a 256-byte window is\n   rejected as invalid, since only the zlib header provides a means of\n   transmitting the window size to the decompressor.\n\n     The memLevel parameter specifies how much memory should be allocated\n   for the internal compression state.  memLevel=1 uses minimum memory but is\n   slow and reduces compression ratio; memLevel=9 uses maximum memory for\n   optimal speed.  The default value is 8.  See zconf.h for total memory usage\n   as a function of windowBits and memLevel.\n\n     The strategy parameter is used to tune the compression algorithm.  Use the\n   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a\n   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no\n   string match), or Z_RLE to limit match distances to one (run-length\n   encoding).  Filtered data consists mostly of small values with a somewhat\n   random distribution.  In this case, the compression algorithm is tuned to\n   compress them better.  The effect of Z_FILTERED is to force more Huffman\n   coding and less string matching; it is somewhat intermediate between\n   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as\n   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The\n   strategy parameter only affects the compression ratio but not the\n   correctness of the compressed output even if it is not set appropriately.\n   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler\n   decoder for special applications.\n\n     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid\n   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is\n   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is\n   set to null if there is no error message.  deflateInit2 does not perform any\n   compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the compression dictionary from the given byte sequence\n   without producing any compressed output.  When using the zlib format, this\n   function must be called immediately after deflateInit, deflateInit2 or\n   deflateReset, and before any call of deflate.  When doing raw deflate, this\n   function must be called either before any call of deflate, or immediately\n   after the completion of a deflate block, i.e. after all input has been\n   consumed and all output has been delivered when using any of the flush\n   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The\n   compressor and decompressor must use exactly the same dictionary (see\n   inflateSetDictionary).\n\n     The dictionary should consist of strings (byte sequences) that are likely\n   to be encountered later in the data to be compressed, with the most commonly\n   used strings preferably put towards the end of the dictionary.  Using a\n   dictionary is most useful when the data to be compressed is short and can be\n   predicted with good accuracy; the data can then be compressed better than\n   with the default empty dictionary.\n\n     Depending on the size of the compression data structures selected by\n   deflateInit or deflateInit2, a part of the dictionary may in effect be\n   discarded, for example if the dictionary is larger than the window size\n   provided in deflateInit or deflateInit2.  Thus the strings most likely to be\n   useful should be put at the end of the dictionary, not at the front.  In\n   addition, the current implementation of deflate will use at most the window\n   size minus 262 bytes of the provided dictionary.\n\n     Upon return of this function, strm->adler is set to the Adler-32 value\n   of the dictionary; the decompressor may later use this value to determine\n   which dictionary has been used by the compressor.  (The Adler-32 value\n   applies to the whole dictionary even if only a subset of the dictionary is\n   actually used by the compressor.) If a raw deflate was requested, then the\n   Adler-32 value is not computed and strm->adler is not set.\n\n     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent (for example if deflate has already been called for this stream\n   or if not at a block boundary for raw deflate).  deflateSetDictionary does\n   not perform any compression: this will be done by deflate().\n*/\n\nZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by deflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If deflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similary, if dictLength is Z_NULL, then it is not set.\n\n     deflateGetDictionary() may return a length less than the window size, even\n   when more than the window size in input has been provided. It may return up\n   to 258 bytes less in that case, due to how zlib's implementation of deflate\n   manages the sliding window and lookahead for matches, where matches can be\n   up to 258 bytes long. If the application needs the last window-size bytes of\n   input, then that would need to be saved by the application outside of zlib.\n\n     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when several compression strategies will be\n   tried, for example when there are several ways of pre-processing the input\n   data with a filter.  The streams that will be discarded should then be freed\n   by calling deflateEnd.  Note that deflateCopy duplicates the internal\n   compression state which can be quite large, so this strategy is slow and can\n   consume lots of memory.\n\n     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to deflateEnd followed by deflateInit, but\n   does not free and reallocate the internal compression state.  The stream\n   will leave the compression level and any other attributes that may have been\n   set unchanged.\n\n     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,\n                                      int level,\n                                      int strategy));\n/*\n     Dynamically update the compression level and compression strategy.  The\n   interpretation of level and strategy is as in deflateInit2().  This can be\n   used to switch between compression and straight copy of the input data, or\n   to switch to a different kind of input data requiring a different strategy.\n   If the compression approach (which is a function of the level) or the\n   strategy is changed, and if any input has been consumed in a previous\n   deflate() call, then the input available so far is compressed with the old\n   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches\n   for the compression levels 0, 1..3, and 4..9 respectively.  The new level\n   and strategy will take effect at the next call of deflate().\n\n     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does\n   not have enough output space to complete, then the parameter change will not\n   take effect.  In this case, deflateParams() can be called again with the\n   same parameters and more output space to try again.\n\n     In order to assure a change in the parameters on the first try, the\n   deflate stream should be flushed using deflate() with Z_BLOCK or other flush\n   request until strm.avail_out is not zero, before calling deflateParams().\n   Then no more input data should be provided before the deflateParams() call.\n   If this is done, the old level and strategy will be applied to the data\n   compressed before deflateParams(), and the new level and strategy will be\n   applied to the the data compressed after deflateParams().\n\n     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream\n   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if\n   there was not enough output space to complete the compression of the\n   available input data before a change in the strategy or approach.  Note that\n   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return\n   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be\n   retried with more output space.\n*/\n\nZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,\n                                    int good_length,\n                                    int max_lazy,\n                                    int nice_length,\n                                    int max_chain));\n/*\n     Fine tune deflate's internal compression parameters.  This should only be\n   used by someone who understands the algorithm used by zlib's deflate for\n   searching for the best matching string, and even then only by the most\n   fanatic optimizer trying to squeeze out the last compressed bit for their\n   specific input data.  Read the deflate.c source code for the meaning of the\n   max_lazy, good_length, nice_length, and max_chain parameters.\n\n     deflateTune() can be called after deflateInit() or deflateInit2(), and\n   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.\n */\n\nZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,\n                                       uLong sourceLen));\n/*\n     deflateBound() returns an upper bound on the compressed size after\n   deflation of sourceLen bytes.  It must be called after deflateInit() or\n   deflateInit2(), and after deflateSetHeader(), if used.  This would be used\n   to allocate an output buffer for deflation in a single pass, and so would be\n   called before deflate().  If that first deflate() call is provided the\n   sourceLen input bytes, an output buffer allocated to the size returned by\n   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed\n   to return Z_STREAM_END.  Note that it is possible for the compressed size to\n   be larger than the value returned by deflateBound() if flush options other\n   than Z_FINISH or Z_NO_FLUSH are used.\n*/\n\nZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,\n                                       unsigned *pending,\n                                       int *bits));\n/*\n     deflatePending() returns the number of bytes and bits of output that have\n   been generated, but not yet provided in the available output.  The bytes not\n   provided would be due to the available output space having being consumed.\n   The number of bits of output not provided are between 0 and 7, where they\n   await more bits to join them in order to fill out a full byte.  If pending\n   or bits are Z_NULL, then those values are not set.\n\n     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n */\n\nZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     deflatePrime() inserts bits in the deflate output stream.  The intent\n   is that this function is used to start off the deflate output with the bits\n   leftover from a previous deflate stream when appending to it.  As such, this\n   function can only be used for raw deflate, and must be used before the first\n   deflate() call after a deflateInit2() or deflateReset().  bits must be less\n   than or equal to 16, and that many of the least significant bits of value\n   will be inserted in the output.\n\n     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough\n   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     deflateSetHeader() provides gzip header information for when a gzip\n   stream is requested by deflateInit2().  deflateSetHeader() may be called\n   after deflateInit2() or deflateReset() and before the first call of\n   deflate().  The text, time, os, extra field, name, and comment information\n   in the provided gz_header structure are written to the gzip header (xflag is\n   ignored -- the extra flags are set according to the compression level).  The\n   caller must assure that, if not Z_NULL, name and comment are terminated with\n   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are\n   available there.  If hcrc is true, a gzip header crc is included.  Note that\n   the current versions of the command-line version of gzip (up through version\n   1.3.x) do not support header crc's, and will report that it is a \"multi-part\n   gzip file\" and give up.\n\n     If deflateSetHeader is not used, the default gzip header has text false,\n   the time set to zero, and os set to 255, with no extra, name, or comment\n   fields.  The gzip header is returned to the default state by deflateReset().\n\n     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,\n                                     int  windowBits));\n\n     This is another version of inflateInit with an extra parameter.  The\n   fields next_in, avail_in, zalloc, zfree and opaque must be initialized\n   before by the caller.\n\n     The windowBits parameter is the base two logarithm of the maximum window\n   size (the size of the history buffer).  It should be in the range 8..15 for\n   this version of the library.  The default value is 15 if inflateInit is used\n   instead.  windowBits must be greater than or equal to the windowBits value\n   provided to deflateInit2() while compressing, or it must be equal to 15 if\n   deflateInit2() was not used.  If a compressed stream with a larger window\n   size is given as input, inflate() will return with the error code\n   Z_DATA_ERROR instead of trying to allocate a larger window.\n\n     windowBits can also be zero to request that inflate use the window size in\n   the zlib header of the compressed stream.\n\n     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits\n   determines the window size.  inflate() will then process raw deflate data,\n   not looking for a zlib or gzip header, not generating a check value, and not\n   looking for any check values for comparison at the end of the stream.  This\n   is for use with other formats that use the deflate compressed data format\n   such as zip.  Those formats provide their own check values.  If a custom\n   format is developed using the raw deflate format for compressed data, it is\n   recommended that a check value such as an Adler-32 or a CRC-32 be applied to\n   the uncompressed data as is done in the zlib, gzip, and zip formats.  For\n   most applications, the zlib format should be used as is.  Note that comments\n   above on the use in deflateInit2() applies to the magnitude of windowBits.\n\n     windowBits can also be greater than 15 for optional gzip decoding.  Add\n   32 to windowBits to enable zlib and gzip decoding with automatic header\n   detection, or add 16 to decode only the gzip format (the zlib format will\n   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a\n   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see\n   below), inflate() will not automatically decode concatenated gzip streams.\n   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state\n   would need to be reset to continue decoding a subsequent gzip stream.\n\n     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the\n   version assumed by the caller, or Z_STREAM_ERROR if the parameters are\n   invalid, such as a null pointer to the structure.  msg is set to null if\n   there is no error message.  inflateInit2 does not perform any decompression\n   apart from possibly reading the zlib header if present: actual decompression\n   will be done by inflate().  (So next_in and avail_in may be modified, but\n   next_out and avail_out are unused and unchanged.) The current implementation\n   of inflateInit2() does not process any header information -- that is\n   deferred until inflate() is called.\n*/\n\nZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,\n                                             const Bytef *dictionary,\n                                             uInt  dictLength));\n/*\n     Initializes the decompression dictionary from the given uncompressed byte\n   sequence.  This function must be called immediately after a call of inflate,\n   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor\n   can be determined from the Adler-32 value returned by that call of inflate.\n   The compressor and decompressor must use exactly the same dictionary (see\n   deflateSetDictionary).  For raw inflate, this function can be called at any\n   time to set the dictionary.  If the provided dictionary is smaller than the\n   window and there is already data in the window, then the provided dictionary\n   will amend what's there.  The application must insure that the dictionary\n   that was used for compression is provided.\n\n     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\n   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is\n   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\n   expected one (incorrect Adler-32 value).  inflateSetDictionary does not\n   perform any decompression: this will be done by subsequent calls of\n   inflate().\n*/\n\nZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,\n                                             Bytef *dictionary,\n                                             uInt  *dictLength));\n/*\n     Returns the sliding dictionary being maintained by inflate.  dictLength is\n   set to the number of bytes in the dictionary, and that many bytes are copied\n   to dictionary.  dictionary must have enough space, where 32768 bytes is\n   always enough.  If inflateGetDictionary() is called with dictionary equal to\n   Z_NULL, then only the dictionary length is returned, and nothing is copied.\n   Similary, if dictLength is Z_NULL, then it is not set.\n\n     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the\n   stream state is inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));\n/*\n     Skips invalid compressed data until a possible full flush point (see above\n   for the description of deflate with Z_FULL_FLUSH) can be found, or until all\n   available input is skipped.  No output is provided.\n\n     inflateSync searches for a 00 00 FF FF pattern in the compressed data.\n   All full flush points have this pattern, but not all occurrences of this\n   pattern are full flush points.\n\n     inflateSync returns Z_OK if a possible full flush point has been found,\n   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point\n   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.\n   In the success case, the application may save the current current value of\n   total_in which indicates where valid compressed data was found.  In the\n   error case, the application may repeatedly call inflateSync, providing more\n   input each time, until success or end of the input data.\n*/\n\nZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,\n                                    z_streamp source));\n/*\n     Sets the destination stream as a complete copy of the source stream.\n\n     This function can be useful when randomly accessing a large stream.  The\n   first pass through the stream can periodically record the inflate state,\n   allowing restarting inflate at those points when randomly accessing the\n   stream.\n\n     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent\n   (such as zalloc being Z_NULL).  msg is left unchanged in both source and\n   destination.\n*/\n\nZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));\n/*\n     This function is equivalent to inflateEnd followed by inflateInit,\n   but does not free and reallocate the internal decompression state.  The\n   stream will keep attributes that may have been set by inflateInit2.\n\n     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL).\n*/\n\nZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,\n                                      int windowBits));\n/*\n     This function is the same as inflateReset, but it also permits changing\n   the wrap and window size requests.  The windowBits parameter is interpreted\n   the same as it is for inflateInit2.  If the window size is changed, then the\n   memory allocated for the window is freed, and the window will be reallocated\n   by inflate() if needed.\n\n     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent (such as zalloc or state being Z_NULL), or if\n   the windowBits parameter is invalid.\n*/\n\nZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,\n                                     int bits,\n                                     int value));\n/*\n     This function inserts bits in the inflate input stream.  The intent is\n   that this function is used to start inflating at a bit position in the\n   middle of a byte.  The provided bits will be used before any bytes are used\n   from next_in.  This function should only be used with raw inflate, and\n   should be used before the first inflate() call after inflateInit2() or\n   inflateReset().  bits must be less than or equal to 16, and that many of the\n   least significant bits of value will be inserted in the input.\n\n     If bits is negative, then the input stream bit buffer is emptied.  Then\n   inflatePrime() can be called again to put bits in the buffer.  This is used\n   to clear out bits leftover after feeding inflate a block description prior\n   to feeding inflate codes.\n\n     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\nZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));\n/*\n     This function returns two values, one in the lower 16 bits of the return\n   value, and the other in the remaining upper bits, obtained by shifting the\n   return value down 16 bits.  If the upper value is -1 and the lower value is\n   zero, then inflate() is currently decoding information outside of a block.\n   If the upper value is -1 and the lower value is non-zero, then inflate is in\n   the middle of a stored block, with the lower value equaling the number of\n   bytes from the input remaining to copy.  If the upper value is not -1, then\n   it is the number of bits back from the current bit position in the input of\n   the code (literal or length/distance pair) currently being processed.  In\n   that case the lower value is the number of bytes already emitted for that\n   code.\n\n     A code is being processed if inflate is waiting for more input to complete\n   decoding of the code, or if it has completed decoding but is waiting for\n   more output space to write the literal or match data.\n\n     inflateMark() is used to mark locations in the input data for random\n   access, which may be at bit positions, and to note those cases where the\n   output of a code may span boundaries of random access blocks.  The current\n   location in the input stream can be determined from avail_in and data_type\n   as noted in the description for the Z_BLOCK flush parameter for inflate.\n\n     inflateMark returns the value noted above, or -65536 if the provided\n   source stream state was inconsistent.\n*/\n\nZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,\n                                         gz_headerp head));\n/*\n     inflateGetHeader() requests that gzip header information be stored in the\n   provided gz_header structure.  inflateGetHeader() may be called after\n   inflateInit2() or inflateReset(), and before the first call of inflate().\n   As inflate() processes the gzip stream, head->done is zero until the header\n   is completed, at which time head->done is set to one.  If a zlib stream is\n   being decoded, then head->done is set to -1 to indicate that there will be\n   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be\n   used to force inflate() to return immediately after header processing is\n   complete and before any actual data is decompressed.\n\n     The text, time, xflags, and os fields are filled in with the gzip header\n   contents.  hcrc is set to true if there is a header CRC.  (The header CRC\n   was valid if done is set to one.) If extra is not Z_NULL, then extra_max\n   contains the maximum number of bytes to write to extra.  Once done is true,\n   extra_len contains the actual extra field length, and extra contains the\n   extra field, or that field truncated if extra_max is less than extra_len.\n   If name is not Z_NULL, then up to name_max characters are written there,\n   terminated with a zero unless the length is greater than name_max.  If\n   comment is not Z_NULL, then up to comm_max characters are written there,\n   terminated with a zero unless the length is greater than comm_max.  When any\n   of extra, name, or comment are not Z_NULL and the respective field is not\n   present in the header, then that field is set to Z_NULL to signal its\n   absence.  This allows the use of deflateSetHeader() with the returned\n   structure to duplicate the header.  However if those fields are set to\n   allocated memory, then the application will need to save those pointers\n   elsewhere so that they can be eventually freed.\n\n     If inflateGetHeader is not used, then the header information is simply\n   discarded.  The header is always checked for validity, including the header\n   CRC if present.  inflateReset() will reset the process to discard the header\n   information.  The application would need to call inflateGetHeader() again to\n   retrieve the header from the next gzip stream.\n\n     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source\n   stream state was inconsistent.\n*/\n\n/*\nZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,\n                                        unsigned char FAR *window));\n\n     Initialize the internal stream state for decompression using inflateBack()\n   calls.  The fields zalloc, zfree and opaque in strm must be initialized\n   before the call.  If zalloc and zfree are Z_NULL, then the default library-\n   derived memory allocation routines are used.  windowBits is the base two\n   logarithm of the window size, in the range 8..15.  window is a caller\n   supplied buffer of that size.  Except for special applications where it is\n   assured that deflate was used with small window sizes, windowBits must be 15\n   and a 32K byte window must be supplied to be able to decompress general\n   deflate streams.\n\n     See inflateBack() for the usage of these routines.\n\n     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of\n   the parameters are invalid, Z_MEM_ERROR if the internal state could not be\n   allocated, or Z_VERSION_ERROR if the version of the library does not match\n   the version of the header file.\n*/\n\ntypedef unsigned (*in_func) OF((void FAR *,\n                                z_const unsigned char FAR * FAR *));\ntypedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));\n\nZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,\n                                    in_func in, void FAR *in_desc,\n                                    out_func out, void FAR *out_desc));\n/*\n     inflateBack() does a raw inflate with a single call using a call-back\n   interface for input and output.  This is potentially more efficient than\n   inflate() for file i/o applications, in that it avoids copying between the\n   output and the sliding window by simply making the window itself the output\n   buffer.  inflate() can be faster on modern CPUs when used with large\n   buffers.  inflateBack() trusts the application to not change the output\n   buffer passed by the output function, at least until inflateBack() returns.\n\n     inflateBackInit() must be called first to allocate the internal state\n   and to initialize the state with the user-provided window buffer.\n   inflateBack() may then be used multiple times to inflate a complete, raw\n   deflate stream with each call.  inflateBackEnd() is then called to free the\n   allocated state.\n\n     A raw deflate stream is one with no zlib or gzip header or trailer.\n   This routine would normally be used in a utility that reads zip or gzip\n   files and writes out uncompressed files.  The utility would decode the\n   header and process the trailer on its own, hence this routine expects only\n   the raw deflate stream to decompress.  This is different from the default\n   behavior of inflate(), which expects a zlib header and trailer around the\n   deflate stream.\n\n     inflateBack() uses two subroutines supplied by the caller that are then\n   called by inflateBack() for input and output.  inflateBack() calls those\n   routines until it reads a complete deflate stream and writes out all of the\n   uncompressed data, or until it encounters an error.  The function's\n   parameters and return types are defined above in the in_func and out_func\n   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the\n   number of bytes of provided input, and a pointer to that input in buf.  If\n   there is no input available, in() must return zero -- buf is ignored in that\n   case -- and inflateBack() will return a buffer error.  inflateBack() will\n   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].\n   out() should return zero on success, or non-zero on failure.  If out()\n   returns non-zero, inflateBack() will return with an error.  Neither in() nor\n   out() are permitted to change the contents of the window provided to\n   inflateBackInit(), which is also the buffer that out() uses to write from.\n   The length written by out() will be at most the window size.  Any non-zero\n   amount of input may be provided by in().\n\n     For convenience, inflateBack() can be provided input on the first call by\n   setting strm->next_in and strm->avail_in.  If that input is exhausted, then\n   in() will be called.  Therefore strm->next_in must be initialized before\n   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called\n   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in\n   must also be initialized, and then if strm->avail_in is not zero, input will\n   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].\n\n     The in_desc and out_desc parameters of inflateBack() is passed as the\n   first parameter of in() and out() respectively when they are called.  These\n   descriptors can be optionally used to pass any information that the caller-\n   supplied in() and out() functions need to do their job.\n\n     On return, inflateBack() will set strm->next_in and strm->avail_in to\n   pass back any unused input that was provided by the last in() call.  The\n   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR\n   if in() or out() returned an error, Z_DATA_ERROR if there was a format error\n   in the deflate stream (in which case strm->msg is set to indicate the nature\n   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.\n   In the case of Z_BUF_ERROR, an input or output error can be distinguished\n   using strm->next_in which will be Z_NULL only if in() returned an error.  If\n   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning\n   non-zero.  (in() will always be called before out(), so strm->next_in is\n   assured to be defined if out() returns non-zero.)  Note that inflateBack()\n   cannot return Z_OK.\n*/\n\nZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));\n/*\n     All memory allocated by inflateBackInit() is freed.\n\n     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream\n   state was inconsistent.\n*/\n\nZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));\n/* Return flags indicating compile-time options.\n\n    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:\n     1.0: size of uInt\n     3.2: size of uLong\n     5.4: size of voidpf (pointer)\n     7.6: size of z_off_t\n\n    Compiler, assembler, and debug options:\n     8: ZLIB_DEBUG\n     9: ASMV or ASMINF -- use ASM code\n     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention\n     11: 0 (reserved)\n\n    One-time table building (smaller code, but not thread-safe if true):\n     12: BUILDFIXED -- build static block decoding tables when needed\n     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed\n     14,15: 0 (reserved)\n\n    Library content (indicates missing functionality):\n     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking\n                          deflate code when not needed)\n     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect\n                    and decode gzip streams (to avoid linking crc code)\n     18-19: 0 (reserved)\n\n    Operation variations (changes in library functionality):\n     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate\n     21: FASTEST -- deflate algorithm with only one, lowest compression level\n     22,23: 0 (reserved)\n\n    The sprintf variant used by gzprintf (zero is best):\n     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format\n     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!\n     26: 0 = returns value, 1 = void -- 1 means inferred string length returned\n\n    Remainder:\n     27-31: 0 (reserved)\n */\n\n#ifndef Z_SOLO\n\n                        /* utility functions */\n\n/*\n     The following utility functions are implemented on top of the basic\n   stream-oriented functions.  To simplify the interface, some default options\n   are assumed (compression level and memory usage, standard memory allocation\n   functions).  The source code of these utility functions can be modified if\n   you need special options.\n*/\n\nZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,\n                                 const Bytef *source, uLong sourceLen));\n/*\n     Compresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.  compress() is equivalent to compress2() with a level\n   parameter of Z_DEFAULT_COMPRESSION.\n\n     compress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer.\n*/\n\nZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,\n                                  const Bytef *source, uLong sourceLen,\n                                  int level));\n/*\n     Compresses the source buffer into the destination buffer.  The level\n   parameter has the same meaning as in deflateInit.  sourceLen is the byte\n   length of the source buffer.  Upon entry, destLen is the total size of the\n   destination buffer, which must be at least the value returned by\n   compressBound(sourceLen).  Upon exit, destLen is the actual size of the\n   compressed data.\n\n     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\n   memory, Z_BUF_ERROR if there was not enough room in the output buffer,\n   Z_STREAM_ERROR if the level parameter is invalid.\n*/\n\nZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));\n/*\n     compressBound() returns an upper bound on the compressed size after\n   compress() or compress2() on sourceLen bytes.  It would be used before a\n   compress() or compress2() call to allocate the destination buffer.\n*/\n\nZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,\n                                   const Bytef *source, uLong sourceLen));\n/*\n     Decompresses the source buffer into the destination buffer.  sourceLen is\n   the byte length of the source buffer.  Upon entry, destLen is the total size\n   of the destination buffer, which must be large enough to hold the entire\n   uncompressed data.  (The size of the uncompressed data must have been saved\n   previously by the compressor and transmitted to the decompressor by some\n   mechanism outside the scope of this compression library.) Upon exit, destLen\n   is the actual size of the uncompressed data.\n\n     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not\n   enough memory, Z_BUF_ERROR if there was not enough room in the output\n   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In\n   the case where there is not enough room, uncompress() will fill the output\n   buffer with the uncompressed data up to that point.\n*/\n\nZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,\n                                    const Bytef *source, uLong *sourceLen));\n/*\n     Same as uncompress, except that sourceLen is a pointer, where the\n   length of the source is *sourceLen.  On return, *sourceLen is the number of\n   source bytes consumed.\n*/\n\n                        /* gzip file access functions */\n\n/*\n     This library supports reading and writing files in gzip (.gz) format with\n   an interface similar to that of stdio, using the functions that start with\n   \"gz\".  The gzip format is different from the zlib format.  gzip is a gzip\n   wrapper, documented in RFC 1952, wrapped around a deflate stream.\n*/\n\ntypedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */\n\n/*\nZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));\n\n     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as\n   in fopen (\"rb\" or \"wb\") but can also include a compression level (\"wb9\") or\n   a strategy: 'f' for filtered data as in \"wb6f\", 'h' for Huffman-only\n   compression as in \"wb1h\", 'R' for run-length encoding as in \"wb1R\", or 'F'\n   for fixed code compression as in \"wb9F\".  (See the description of\n   deflateInit2 for more information about the strategy parameter.)  'T' will\n   request transparent writing or appending with no compression and not using\n   the gzip format.\n\n     \"a\" can be used instead of \"w\" to request that the gzip stream that will\n   be written be appended to the file.  \"+\" will result in an error, since\n   reading and writing to the same gzip file is not supported.  The addition of\n   \"x\" when writing will create the file exclusively, which fails if the file\n   already exists.  On systems that support it, the addition of \"e\" when\n   reading or writing will set the flag to close the file on an execve() call.\n\n     These functions, as well as gzip, will read and decode a sequence of gzip\n   streams in a file.  The append function of gzopen() can be used to create\n   such a file.  (Also see gzflush() for another way to do this.)  When\n   appending, gzopen does not test whether the file begins with a gzip stream,\n   nor does it look for the end of the gzip streams to begin appending.  gzopen\n   will simply append a gzip stream to the existing file.\n\n     gzopen can be used to read a file which is not in gzip format; in this\n   case gzread will directly read from the file without decompression.  When\n   reading, this will be detected automatically by looking for the magic two-\n   byte gzip header.\n\n     gzopen returns NULL if the file could not be opened, if there was\n   insufficient memory to allocate the gzFile state, or if an invalid mode was\n   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).\n   errno can be checked to determine if the reason gzopen failed was that the\n   file could not be opened.\n*/\n\nZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));\n/*\n     gzdopen associates a gzFile with the file descriptor fd.  File descriptors\n   are obtained from calls like open, dup, creat, pipe or fileno (if the file\n   has been previously opened with fopen).  The mode parameter is as in gzopen.\n\n     The next call of gzclose on the returned gzFile will also close the file\n   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor\n   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,\n   mode);.  The duplicated descriptor should be saved to avoid a leak, since\n   gzdopen does not close fd if it fails.  If you are using fileno() to get the\n   file descriptor from a FILE *, then you will have to use dup() to avoid\n   double-close()ing the file descriptor.  Both gzclose() and fclose() will\n   close the associated file descriptor, so they need to have different file\n   descriptors.\n\n     gzdopen returns NULL if there was insufficient memory to allocate the\n   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not\n   provided, or '+' was provided), or if fd is -1.  The file descriptor is not\n   used until the next gz* read, write, seek, or close operation, so gzdopen\n   will not detect if fd is invalid (unless fd is -1).\n*/\n\nZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));\n/*\n     Set the internal buffer size used by this library's functions.  The\n   default buffer size is 8192 bytes.  This function must be called after\n   gzopen() or gzdopen(), and before any other calls that read or write the\n   file.  The buffer memory allocation is always deferred to the first read or\n   write.  Three times that size in buffer space is allocated.  A larger buffer\n   size of, for example, 64K or 128K bytes will noticeably increase the speed\n   of decompression (reading).\n\n     The new buffer size also affects the maximum length for gzprintf().\n\n     gzbuffer() returns 0 on success, or -1 on failure, such as being called\n   too late.\n*/\n\nZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));\n/*\n     Dynamically update the compression level or strategy.  See the description\n   of deflateInit2 for the meaning of these parameters.  Previously provided\n   data is flushed before the parameter change.\n\n     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not\n   opened for writing, Z_ERRNO if there is an error writing the flushed data,\n   or Z_MEM_ERROR if there is a memory allocation error.\n*/\n\nZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));\n/*\n     Reads the given number of uncompressed bytes from the compressed file.  If\n   the input file is not in gzip format, gzread copies the given number of\n   bytes into the buffer directly from the file.\n\n     After reaching the end of a gzip stream in the input, gzread will continue\n   to read, looking for another gzip stream.  Any number of gzip streams may be\n   concatenated in the input file, and will all be decompressed by gzread().\n   If something other than a gzip stream is encountered after a gzip stream,\n   that remaining trailing garbage is ignored (and no error is returned).\n\n     gzread can be used to read a gzip file that is being concurrently written.\n   Upon reaching the end of the input, gzread will return with the available\n   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then\n   gzclearerr can be used to clear the end of file indicator in order to permit\n   gzread to be tried again.  Z_OK indicates that a gzip stream was completed\n   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the\n   middle of a gzip stream.  Note that gzread does not return -1 in the event\n   of an incomplete gzip stream.  This error is deferred until gzclose(), which\n   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip\n   stream.  Alternatively, gzerror can be used before gzclose to detect this\n   case.\n\n     gzread returns the number of uncompressed bytes actually read, less than\n   len for end of file, or -1 for error.  If len is too large to fit in an int,\n   then nothing is read, -1 is returned, and the error state is set to\n   Z_STREAM_ERROR.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,\n                                     gzFile file));\n/*\n     Read up to nitems items of size size from file to buf, otherwise operating\n   as gzread() does.  This duplicates the interface of stdio's fread(), with\n   size_t request and return types.  If the library defines size_t, then\n   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned\n   integer type that can contain a pointer.\n\n     gzfread() returns the number of full items read of size size, or zero if\n   the end of the file was reached and a full item could not be read, or if\n   there was an error.  gzerror() must be consulted if zero is returned in\n   order to determine if there was an error.  If the multiplication of size and\n   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing\n   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.\n\n     In the event that the end of file is reached and only a partial item is\n   available at the end, i.e. the remaining uncompressed data length is not a\n   multiple of size, then the final partial item is nevetheless read into buf\n   and the end-of-file flag is set.  The length of the partial item read is not\n   provided, but could be inferred from the result of gztell().  This behavior\n   is the same as the behavior of fread() implementations in common libraries,\n   but it prevents the direct use of gzfread() to read a concurrently written\n   file, reseting and retrying on end-of-file, when size is not 1.\n*/\n\nZEXTERN int ZEXPORT gzwrite OF((gzFile file,\n                                voidpc buf, unsigned len));\n/*\n     Writes the given number of uncompressed bytes into the compressed file.\n   gzwrite returns the number of uncompressed bytes written or 0 in case of\n   error.\n*/\n\nZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,\n                                      z_size_t nitems, gzFile file));\n/*\n     gzfwrite() writes nitems items of size size from buf to file, duplicating\n   the interface of stdio's fwrite(), with size_t request and return types.  If\n   the library defines size_t, then z_size_t is identical to size_t.  If not,\n   then z_size_t is an unsigned integer type that can contain a pointer.\n\n     gzfwrite() returns the number of full items written of size size, or zero\n   if there was an error.  If the multiplication of size and nitems overflows,\n   i.e. the product does not fit in a z_size_t, then nothing is written, zero\n   is returned, and the error state is set to Z_STREAM_ERROR.\n*/\n\nZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));\n/*\n     Converts, formats, and writes the arguments to the compressed file under\n   control of the format string, as in fprintf.  gzprintf returns the number of\n   uncompressed bytes actually written, or a negative zlib error code in case\n   of error.  The number of uncompressed bytes written is limited to 8191, or\n   one less than the buffer size given to gzbuffer().  The caller should assure\n   that this limit is not exceeded.  If it is exceeded, then gzprintf() will\n   return an error (0) with nothing written.  In this case, there may also be a\n   buffer overflow with unpredictable consequences, which is possible only if\n   zlib was compiled with the insecure functions sprintf() or vsprintf()\n   because the secure snprintf() or vsnprintf() functions were not available.\n   This can be determined using zlibCompileFlags().\n*/\n\nZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));\n/*\n     Writes the given null-terminated string to the compressed file, excluding\n   the terminating null character.\n\n     gzputs returns the number of characters written, or -1 in case of error.\n*/\n\nZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));\n/*\n     Reads bytes from the compressed file until len-1 characters are read, or a\n   newline character is read and transferred to buf, or an end-of-file\n   condition is encountered.  If any characters are read or if len == 1, the\n   string is terminated with a null character.  If no characters are read due\n   to an end-of-file or len < 1, then the buffer is left untouched.\n\n     gzgets returns buf which is a null-terminated string, or it returns NULL\n   for end-of-file or in case of error.  If there was an error, the contents at\n   buf are indeterminate.\n*/\n\nZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));\n/*\n     Writes c, converted to an unsigned char, into the compressed file.  gzputc\n   returns the value that was written, or -1 in case of error.\n*/\n\nZEXTERN int ZEXPORT gzgetc OF((gzFile file));\n/*\n     Reads one byte from the compressed file.  gzgetc returns this byte or -1\n   in case of end of file or error.  This is implemented as a macro for speed.\n   As such, it does not do all of the checking the other functions do.  I.e.\n   it does not check to see if file is NULL, nor whether the structure file\n   points to has been clobbered or not.\n*/\n\nZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));\n/*\n     Push one character back onto the stream to be read as the first character\n   on the next read.  At least one character of push-back is allowed.\n   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will\n   fail if c is -1, and may fail if a character has been pushed but not read\n   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the\n   output buffer size of pushed characters is allowed.  (See gzbuffer above.)\n   The pushed character will be discarded if the stream is repositioned with\n   gzseek() or gzrewind().\n*/\n\nZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));\n/*\n     Flushes all pending output into the compressed file.  The parameter flush\n   is as in the deflate() function.  The return value is the zlib error number\n   (see function gzerror below).  gzflush is only permitted when writing.\n\n     If the flush parameter is Z_FINISH, the remaining data is written and the\n   gzip stream is completed in the output.  If gzwrite() is called again, a new\n   gzip stream will be started in the output.  gzread() is able to read such\n   concatenated gzip streams.\n\n     gzflush should be called only when strictly necessary because it will\n   degrade compression if called too often.\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,\n                                   z_off_t offset, int whence));\n\n     Sets the starting position for the next gzread or gzwrite on the given\n   compressed file.  The offset represents a number of bytes in the\n   uncompressed data stream.  The whence parameter is defined as in lseek(2);\n   the value SEEK_END is not supported.\n\n     If the file is opened for reading, this function is emulated but can be\n   extremely slow.  If the file is opened for writing, only forward seeks are\n   supported; gzseek then compresses a sequence of zeroes up to the new\n   starting position.\n\n     gzseek returns the resulting offset location as measured in bytes from\n   the beginning of the uncompressed stream, or -1 in case of error, in\n   particular if the file is opened for writing and the new starting position\n   would be before the current position.\n*/\n\nZEXTERN int ZEXPORT    gzrewind OF((gzFile file));\n/*\n     Rewinds the given file. This function is supported only for reading.\n\n     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));\n\n     Returns the starting position for the next gzread or gzwrite on the given\n   compressed file.  This position represents a number of bytes in the\n   uncompressed data stream, and is zero when starting, even if appending or\n   reading a gzip stream from the middle of a file using gzdopen().\n\n     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)\n*/\n\n/*\nZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));\n\n     Returns the current offset in the file being read or written.  This offset\n   includes the count of bytes that precede the gzip stream, for example when\n   appending or when using gzdopen() for reading.  When reading, the offset\n   does not include as yet unused buffered input.  This information can be used\n   for a progress indicator.  On error, gzoffset() returns -1.\n*/\n\nZEXTERN int ZEXPORT gzeof OF((gzFile file));\n/*\n     Returns true (1) if the end-of-file indicator has been set while reading,\n   false (0) otherwise.  Note that the end-of-file indicator is set only if the\n   read tried to go past the end of the input, but came up short.  Therefore,\n   just like feof(), gzeof() may return false even if there is no more data to\n   read, in the event that the last read request was for the exact number of\n   bytes remaining in the input file.  This will happen if the input file size\n   is an exact multiple of the buffer size.\n\n     If gzeof() returns true, then the read functions will return no more data,\n   unless the end-of-file indicator is reset by gzclearerr() and the input file\n   has grown since the previous end of file was detected.\n*/\n\nZEXTERN int ZEXPORT gzdirect OF((gzFile file));\n/*\n     Returns true (1) if file is being copied directly while reading, or false\n   (0) if file is a gzip stream being decompressed.\n\n     If the input file is empty, gzdirect() will return true, since the input\n   does not contain a gzip stream.\n\n     If gzdirect() is used immediately after gzopen() or gzdopen() it will\n   cause buffers to be allocated to allow reading the file to determine if it\n   is a gzip file.  Therefore if gzbuffer() is used, it should be called before\n   gzdirect().\n\n     When writing, gzdirect() returns true (1) if transparent writing was\n   requested (\"wT\" for the gzopen() mode), or false (0) otherwise.  (Note:\n   gzdirect() is not needed when writing.  Transparent writing must be\n   explicitly requested, so the application already knows the answer.  When\n   linking statically, using gzdirect() will include all of the zlib code for\n   gzip file reading and decompression, which may not be desired.)\n*/\n\nZEXTERN int ZEXPORT    gzclose OF((gzFile file));\n/*\n     Flushes all pending output if necessary, closes the compressed file and\n   deallocates the (de)compression state.  Note that once file is closed, you\n   cannot call gzerror with file, since its structures have been deallocated.\n   gzclose must not be called more than once on the same file, just as free\n   must not be called more than once on the same allocation.\n\n     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a\n   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the\n   last read ended in the middle of a gzip stream, or Z_OK on success.\n*/\n\nZEXTERN int ZEXPORT gzclose_r OF((gzFile file));\nZEXTERN int ZEXPORT gzclose_w OF((gzFile file));\n/*\n     Same as gzclose(), but gzclose_r() is only for use when reading, and\n   gzclose_w() is only for use when writing or appending.  The advantage to\n   using these instead of gzclose() is that they avoid linking in zlib\n   compression or decompression code that is not used when only reading or only\n   writing respectively.  If gzclose() is used, then both compression and\n   decompression code will be included the application when linking to a static\n   zlib library.\n*/\n\nZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));\n/*\n     Returns the error message for the last error which occurred on the given\n   compressed file.  errnum is set to zlib error number.  If an error occurred\n   in the file system and not in the compression library, errnum is set to\n   Z_ERRNO and the application may consult errno to get the exact error code.\n\n     The application must not modify the returned string.  Future calls to\n   this function may invalidate the previously returned string.  If file is\n   closed, then the string previously returned by gzerror will no longer be\n   available.\n\n     gzerror() should be used to distinguish errors from end-of-file for those\n   functions above that do not distinguish those cases in their return values.\n*/\n\nZEXTERN void ZEXPORT gzclearerr OF((gzFile file));\n/*\n     Clears the error and end-of-file flags for file.  This is analogous to the\n   clearerr() function in stdio.  This is useful for continuing to read a gzip\n   file that is being written concurrently.\n*/\n\n#endif /* !Z_SOLO */\n\n                        /* checksum functions */\n\n/*\n     These functions are not related to compression but are exported\n   anyway because they might be useful in applications using the compression\n   library.\n*/\n\nZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));\n/*\n     Update a running Adler-32 checksum with the bytes buf[0..len-1] and\n   return the updated checksum.  If buf is Z_NULL, this function returns the\n   required initial value for the checksum.\n\n     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed\n   much faster.\n\n   Usage example:\n\n     uLong adler = adler32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       adler = adler32(adler, buffer, length);\n     }\n     if (adler != original_adler) error();\n*/\n\nZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,\n                                    z_size_t len));\n/*\n     Same as adler32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,\n                                          z_off_t len2));\n\n     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1\n   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for\n   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of\n   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note\n   that the z_off_t type (like off_t) is a signed integer.  If len2 is\n   negative, the result has no meaning or utility.\n*/\n\nZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));\n/*\n     Update a running CRC-32 with the bytes buf[0..len-1] and return the\n   updated CRC-32.  If buf is Z_NULL, this function returns the required\n   initial value for the crc.  Pre- and post-conditioning (one's complement) is\n   performed within this function so it shouldn't be done by the application.\n\n   Usage example:\n\n     uLong crc = crc32(0L, Z_NULL, 0);\n\n     while (read_buffer(buffer, length) != EOF) {\n       crc = crc32(crc, buffer, length);\n     }\n     if (crc != original_crc) error();\n*/\n\nZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,\n                                  z_size_t len));\n/*\n     Same as crc32(), but with a size_t length.\n*/\n\n/*\nZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));\n\n     Combine two CRC-32 check values into one.  For two sequences of bytes,\n   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were\n   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32\n   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and\n   len2.\n*/\n\n\n                        /* various hacks, don't look :) */\n\n/* deflateInit and inflateInit are macros to allow checking the zlib version\n * and the compiler's view of z_stream:\n */\nZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,\n                                     const char *version, int stream_size));\nZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,\n                                      int windowBits, int memLevel,\n                                      int strategy, const char *version,\n                                      int stream_size));\nZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,\n                                      const char *version, int stream_size));\nZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,\n                                         unsigned char FAR *window,\n                                         const char *version,\n                                         int stream_size));\n#ifdef Z_PREFIX_SET\n#  define z_deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define z_inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define z_inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#else\n#  define deflateInit(strm, level) \\\n          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit(strm) \\\n          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \\\n          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\\\n                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))\n#  define inflateInit2(strm, windowBits) \\\n          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \\\n                        (int)sizeof(z_stream))\n#  define inflateBackInit(strm, windowBits, window) \\\n          inflateBackInit_((strm), (windowBits), (window), \\\n                           ZLIB_VERSION, (int)sizeof(z_stream))\n#endif\n\n#ifndef Z_SOLO\n\n/* gzgetc() macro and its supporting function and exposed data structure.  Note\n * that the real internal state is much larger than the exposed structure.\n * This abbreviated structure exposes just enough for the gzgetc() macro.  The\n * user should not mess with these exposed elements, since their names or\n * behavior could change in the future, perhaps even capriciously.  They can\n * only be used by the gzgetc() macro.  You have been warned.\n */\nstruct gzFile_s {\n    unsigned have;\n    unsigned char *next;\n    z_off64_t pos;\n};\nZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */\n#ifdef Z_PREFIX_SET\n#  undef z_gzgetc\n#  define z_gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#else\n#  define gzgetc(g) \\\n          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))\n#endif\n\n/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or\n * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if\n * both are true, the application gets the *64 functions, and the regular\n * functions are changed to 64 bits) -- in case these are set on systems\n * without large file support, _LFS64_LARGEFILE must also be true\n */\n#ifdef Z_LARGE64\n   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));\n   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));\n   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));\n   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));\n#endif\n\n#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)\n#  ifdef Z_PREFIX_SET\n#    define z_gzopen z_gzopen64\n#    define z_gzseek z_gzseek64\n#    define z_gztell z_gztell64\n#    define z_gzoffset z_gzoffset64\n#    define z_adler32_combine z_adler32_combine64\n#    define z_crc32_combine z_crc32_combine64\n#  else\n#    define gzopen gzopen64\n#    define gzseek gzseek64\n#    define gztell gztell64\n#    define gzoffset gzoffset64\n#    define adler32_combine adler32_combine64\n#    define crc32_combine crc32_combine64\n#  endif\n#  ifndef Z_LARGE64\n     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));\n     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));\n     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));\n     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));\n     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\n     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\n#  endif\n#else\n   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));\n   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));\n   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));\n   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n#endif\n\n#else /* Z_SOLO */\n\n   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));\n   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));\n\n#endif /* !Z_SOLO */\n\n/* undocumented functions */\nZEXTERN const char   * ZEXPORT zError           OF((int));\nZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));\nZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));\nZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));\nZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));\nZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));\nZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));\nZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));\n#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)\nZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,\n                                            const char *mode));\n#endif\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifndef Z_SOLO\nZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,\n                                                  const char *format,\n                                                  va_list va));\n#  endif\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* ZLIB_H */\n"
  },
  {
    "path": "deps/cl345/zlib/zutil.c",
    "content": "/* zutil.c -- target dependent utility functions for the compression library\n * Copyright (C) 1995-2017 Jean-loup Gailly\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* @(#) $Id$ */\n\n#include <stdlib.h>\t\t/* For malloc()/free() - pcg */\n#if defined( INC_ALL )\n  #include \"zutil.h\"\n#else\n  #include \"zlib/zutil.h\"\n#endif /* Compiler-specific includes */\n\n/* Re-enable use of malloc() - pcg */\n\n#undef Z_SOLO\n\n#if defined( USE_COMPRESSION ) && !defined( HAS_ZLIB )\n\nz_const char * const z_errmsg[10] = {\n    (z_const char *)\"need dictionary\",     /* Z_NEED_DICT       2  */\n    (z_const char *)\"stream end\",          /* Z_STREAM_END      1  */\n    (z_const char *)\"\",                    /* Z_OK              0  */\n    (z_const char *)\"file error\",          /* Z_ERRNO         (-1) */\n    (z_const char *)\"stream error\",        /* Z_STREAM_ERROR  (-2) */\n    (z_const char *)\"data error\",          /* Z_DATA_ERROR    (-3) */\n    (z_const char *)\"insufficient memory\", /* Z_MEM_ERROR     (-4) */\n    (z_const char *)\"buffer error\",        /* Z_BUF_ERROR     (-5) */\n    (z_const char *)\"incompatible version\",/* Z_VERSION_ERROR (-6) */\n    (z_const char *)\"\"\n};\n\n\nconst char * ZEXPORT zlibVersion( void )\t/* pcg */\n{\n    return ZLIB_VERSION;\n}\n\nuLong ZEXPORT zlibCompileFlags( void )\t/* pcg */\n{\n    uLong flags;\n\n    flags = 0;\n    switch ((int)(sizeof(uInt))) {\n    case 2:     break;\n    case 4:     flags += 1;     break;\n    case 8:     flags += 2;     break;\n    default:    flags += 3;\n    }\n    switch ((int)(sizeof(uLong))) {\n    case 2:     break;\n    case 4:     flags += 1 << 2;        break;\n    case 8:     flags += 2 << 2;        break;\n    default:    flags += 3 << 2;\n    }\n    switch ((int)(sizeof(voidpf))) {\n    case 2:     break;\n    case 4:     flags += 1 << 4;        break;\n    case 8:     flags += 2 << 4;        break;\n    default:    flags += 3 << 4;\n    }\n    switch ((int)(sizeof(z_off_t))) {\n    case 2:     break;\n    case 4:     flags += 1 << 6;        break;\n    case 8:     flags += 2 << 6;        break;\n    default:    flags += 3 << 6;\n    }\n#ifdef ZLIB_DEBUG\n    flags += 1 << 8;\n#endif\n#if defined(ASMV) || defined(ASMINF)\n    flags += 1 << 9;\n#endif\n#ifdef ZLIB_WINAPI\n    flags += 1 << 10;\n#endif\n#ifdef BUILDFIXED\n    flags += 1 << 12;\n#endif\n#ifdef DYNAMIC_CRC_TABLE\n    flags += 1 << 13;\n#endif\n#ifdef NO_GZCOMPRESS\n    flags += 1L << 16;\n#endif\n#ifdef NO_GZIP\n    flags += 1L << 17;\n#endif\n#ifdef PKZIP_BUG_WORKAROUND\n    flags += 1L << 20;\n#endif\n#ifdef FASTEST\n    flags += 1L << 21;\n#endif\n#if defined(STDC) || defined(Z_HAVE_STDARG_H)\n#  ifdef NO_vsnprintf\n    flags += 1L << 25;\n#    ifdef HAS_vsprintf_void\n    flags += 1L << 26;\n#    endif\n#  else\n#    ifdef HAS_vsnprintf_void\n    flags += 1L << 26;\n#    endif\n#  endif\n#else\n    flags += 1L << 24;\n#  ifdef NO_snprintf\n    flags += 1L << 25;\n#    ifdef HAS_sprintf_void\n    flags += 1L << 26;\n#    endif\n#  else\n#    ifdef HAS_snprintf_void\n    flags += 1L << 26;\n#    endif\n#  endif\n#endif\n    return flags;\n}\n\n#ifdef ZLIB_DEBUG\n#include <stdlib.h>\n#  ifndef verbose\n#    define verbose 0\n#  endif\nint ZLIB_INTERNAL z_verbose = verbose;\n\nvoid ZLIB_INTERNAL z_error ( char *m )\t/* pcg */\n{\n    fprintf(stderr, \"%s\\n\", m);\n    exit(1);\n}\n#endif\n\n/* exported to allow conversion of error code to string for compress() and\n * uncompress()\n */\nconst char * ZEXPORT zError( int err )\t/* pcg */\n{\n    return ERR_MSG(err);\n}\n\n#if defined(_WIN32_WCE)\n    /* The Microsoft C Run-Time Library for Windows CE doesn't have\n     * errno.  We define it as a global variable to simplify porting.\n     * Its value is always 0 and should not be used.\n     */\n    int errno = 0;\n#endif\n\n#ifndef HAVE_MEMCPY\n\nvoid ZLIB_INTERNAL zmemcpy( Bytef* dest, const Bytef* source, uInt  len )\t/* pcg */\n{\n    if (len == 0) return;\n    do {\n        *dest++ = *source++; /* ??? to be unrolled */\n    } while (--len != 0);\n}\n\nint ZLIB_INTERNAL zmemcmp( const Bytef* s1, const Bytef* s2, uInt  len )\t/* pcg */\n{\n    uInt j;\n\n    for (j = 0; j < len; j++) {\n        if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;\n    }\n    return 0;\n}\n\nvoid ZLIB_INTERNAL zmemzero( Bytef* dest, uInt  len )\t/* pcg */\n{\n    if (len == 0) return;\n    do {\n        *dest++ = 0;  /* ??? to be unrolled */\n    } while (--len != 0);\n}\n#endif\n\n#ifndef Z_SOLO\n\n#ifdef SYS16BIT\n\n#ifdef __TURBOC__\n/* Turbo C in 16-bit mode */\n\n#  define MY_ZCALLOC\n\n/* Turbo C malloc() does not allow dynamic allocation of 64K bytes\n * and farmalloc(64K) returns a pointer with an offset of 8, so we\n * must fix the pointer. Warning: the pointer must be put back to its\n * original form in order to free it, use zcfree().\n */\n\n#define MAX_PTR 10\n/* 10*64K = 640K */\n\nlocal int next_ptr = 0;\n\ntypedef struct ptr_table_s {\n    voidpf org_ptr;\n    voidpf new_ptr;\n} ptr_table;\n\nlocal ptr_table table[MAX_PTR];\n/* This table is used to remember the original form of pointers\n * to large buffers (64K). Such pointers are normalized with a zero offset.\n * Since MSDOS is not a preemptive multitasking OS, this table is not\n * protected from concurrent access. This hack doesn't work anyway on\n * a protected system like OS/2. Use Microsoft C instead.\n */\n\nvoidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)\n{\n    voidpf buf;\n    ulg bsize = (ulg)items*size;\n\n    (void)opaque;\n\n    /* If we allocate less than 65520 bytes, we assume that farmalloc\n     * will return a usable pointer which doesn't have to be normalized.\n     */\n    if (bsize < 65520L) {\n        buf = farmalloc(bsize);\n        if (*(ush*)&buf != 0) return buf;\n    } else {\n        buf = farmalloc(bsize + 16L);\n    }\n    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;\n    table[next_ptr].org_ptr = buf;\n\n    /* Normalize the pointer to seg:0 */\n    *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;\n    *(ush*)&buf = 0;\n    table[next_ptr++].new_ptr = buf;\n    return buf;\n}\n\nvoid ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)\n{\n    int n;\n\n    (void)opaque;\n\n    if (*(ush*)&ptr != 0) { /* object < 64K */\n        farfree(ptr);\n        return;\n    }\n    /* Find the original pointer */\n    for (n = 0; n < next_ptr; n++) {\n        if (ptr != table[n].new_ptr) continue;\n\n        farfree(table[n].org_ptr);\n        while (++n < next_ptr) {\n            table[n-1] = table[n];\n        }\n        next_ptr--;\n        return;\n    }\n    Assert(0, \"zcfree: ptr not found\");\n}\n\n#endif /* __TURBOC__ */\n\n\n#ifdef M_I86\n/* Microsoft C in 16-bit mode */\n\n#  define MY_ZCALLOC\n\n#if (!defined(_MSC_VER) || (_MSC_VER <= 600))\n#  define _halloc  halloc\n#  define _hfree   hfree\n#endif\n\nvoidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)\n{\n    (void)opaque;\n    return _halloc((long)items, size);\n}\n\nvoid ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)\n{\n    (void)opaque;\n    _hfree(ptr);\n}\n\n#endif /* M_I86 */\n\n#endif /* SYS16BIT */\n\n\n#ifndef MY_ZCALLOC /* Any system without a special alloc function */\n\n#if 0\t\t\t\t\t/* No idea why zlib wants to do its own nonstandard\n\t\t\t\t\t\t   prototype of malloc() - pcg */\n#ifndef STDC\nextern voidp  malloc OF((uInt size));\nextern voidp  calloc OF((uInt items, uInt size));\nextern void   free   OF((voidpf ptr));\n#endif\n#endif /* 0 */\n\n#ifdef __Nucleus__\t\t/* pcg */\n  /* Nucleus uses a wrapper for the OS-internal allocation functions rather \n\t than calling malloc()/free(), so we just map those calls to the \n\t standard cryptlib allocator (which calls down to the Nucleus OS-\n\t internal function) */\n  #define malloc\tclAlloc\n  #define free\t\tclFree\n#endif /* Nucleus */\n\nvoidpf ZLIB_INTERNAL zcalloc ( voidpf opaque, unsigned items, unsigned size )\t/* pcg */\n{\n    (void)opaque;\n    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :\n                              (voidpf)calloc(items, size);\n}\n\nvoid ZLIB_INTERNAL zcfree ( voidpf opaque, voidpf ptr )\t/* pcg */\n{\n    (void)opaque;\n    free(ptr);\n}\n\n#endif /* MY_ZCALLOC */\n\n#endif /* !Z_SOLO */\n\n#endif /* USE_COMPRESSION && !HAS_ZLIB */\n"
  },
  {
    "path": "deps/cl345/zlib/zutil.h",
    "content": "/* zutil.h -- internal interface and configuration of the compression library\n * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n/* WARNING: this file should *not* be used by applications. It is\n   part of the implementation of the compression library and is\n   subject to change. Applications should only use zlib.h.\n */\n\n/* @(#) $Id$ */\n\n#ifndef ZUTIL_H\n#define ZUTIL_H\n\n#ifdef HAVE_HIDDEN\n#  define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))\n#else\n#  define ZLIB_INTERNAL\n#endif\n\n#if defined( INC_ALL )\n  #include \"zlib.h\"\n#else\n  #include \"zlib/zlib.h\"\n#endif /* Compiler-specific includes */\n\n#if defined(STDC) && !defined(Z_SOLO)\n#  if !(defined(_WIN32_WCE) && defined(_MSC_VER))\n#    include <stddef.h>\n#  endif\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n\n#if 0\t/* pcg */\n#if defined( Z_SOLO ) && !defined( _M_X64 )\n   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */\n#endif\n#endif /* 0 */\n\n#ifndef local\n#  define local static\n#endif\n/* since \"static\" is used to mean two completely different things in C, we\n   define \"local\" for the non-static meaning of \"static\", for readability\n   (compile with -Dlocal if your debugger can't find static symbols) */\n\ntypedef unsigned char  uch;\ntypedef uch FAR uchf;\ntypedef unsigned short ush;\ntypedef ush FAR ushf;\ntypedef unsigned long  ulg;\n\nextern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */\n/* (size given to avoid silly warnings with Visual C++) */\n\n#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]\n\n#define ERR_RETURN(strm,err) \\\n  return (strm->msg = ERR_MSG(err), (err))\n/* To be used only when the state is known to be valid */\n\n        /* common constants */\n\n#ifndef DEF_WBITS\n#  define DEF_WBITS MAX_WBITS\n#endif\n/* default windowBits for decompression. MAX_WBITS is for compression only */\n\n#if MAX_MEM_LEVEL >= 8\n#  define DEF_MEM_LEVEL 8\n#else\n#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#endif\n/* default memLevel */\n\n#define STORED_BLOCK 0\n#define STATIC_TREES 1\n#define DYN_TREES    2\n/* The three kinds of block type */\n\n#define MIN_MATCH  3\n#define MAX_MATCH  258\n/* The minimum and maximum match lengths */\n\n#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */\n\n        /* target dependencies */\n\n#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))\n#  define OS_CODE  0x00\n#  ifndef Z_SOLO\n#    if defined(__TURBOC__) || defined(__BORLANDC__)\n#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))\n         /* Allow compilation with ANSI keywords only enabled */\n         void _Cdecl farfree( void *block );\n         void *_Cdecl farmalloc( unsigned long nbytes );\n#      else\n#        include <alloc.h>\n#      endif\n#    else /* MSC or DJGPP */\n#      include <malloc.h>\n#    endif\n#  endif\n#endif\n\n#ifdef AMIGA\n#  define OS_CODE  1\n#endif\n\n#if defined(VAXC) || defined(VMS)\n#  define OS_CODE  2\n#  define F_OPEN(name, mode) \\\n     fopen((name), (mode), \"mbc=60\", \"ctx=stm\", \"rfm=fix\", \"mrs=512\")\n#endif\n\n#ifdef __370__\n#  if __TARGET_LIB__ < 0x20000000\n#    define OS_CODE 4\n#  elif __TARGET_LIB__ < 0x40000000\n#    define OS_CODE 11\n#  else\n#    define OS_CODE 8\n#  endif\n#endif\n\n#if defined(ATARI) || defined(atarist)\n#  define OS_CODE  5\n#endif\n\n#ifdef OS2\n#  define OS_CODE  6\n#  if defined(M_I86) && !defined(Z_SOLO)\n#    include <malloc.h>\n#  endif\n#endif\n\n#if defined(MACOS) || defined(TARGET_OS_MAC)\n#  define OS_CODE  7\n#  ifndef Z_SOLO\n#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os\n#      include <unix.h> /* for fdopen */\n#    else\n#      ifndef fdopen\n#        define fdopen(fd,mode) NULL /* No fdopen() */\n#      endif\n#    endif\n#  endif\n#endif\n\n#ifdef __acorn\n#  define OS_CODE 13\n#endif\n\n#if defined(WIN32) && !defined(__CYGWIN__)\n#  define OS_CODE  10\n#endif\n\n#ifdef _BEOS_\n#  define OS_CODE  16\n#endif\n\n#ifdef __TOS_OS400__\n#  define OS_CODE 18\n#endif\n\n#ifdef __APPLE__\n#  define OS_CODE 19\n#endif\n\n#if defined(_BEOS_) || defined(RISCOS)\n#  define fdopen(fd,mode) NULL /* No fdopen() */\n#endif\n\n#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX\n#  if defined(_WIN32_WCE)\n#    define fdopen(fd,mode) NULL /* No fdopen() */\n#    ifndef _PTRDIFF_T_DEFINED\n       typedef int ptrdiff_t;\n#      define _PTRDIFF_T_DEFINED\n#    endif\n#  else\n#    define fdopen(fd,type)  _fdopen(fd,type)\n#  endif\n#endif\n\n#if defined(__BORLANDC__) && !defined(MSDOS)\n  #pragma warn -8004\n  #pragma warn -8008\n  #pragma warn -8066\n#endif\n\n/* provide prototypes for these when building zlib without LFS */\n#if !defined(_WIN32) && \\\n    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)\n    ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));\n    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));\n#endif\n\n        /* common defaults */\n\n#ifndef OS_CODE\n#  define OS_CODE  3     /* assume Unix */\n#endif\n\n#ifndef F_OPEN\n#  define F_OPEN(name, mode) fopen((name), (mode))\n#endif\n\n         /* functions */\n\n#if defined(pyr) || defined(Z_SOLO)\n#  define NO_MEMCPY\n#endif\n#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)\n /* Use our own functions for small and medium model with MSC <= 5.0.\n  * You may have to use the same strategy for Borland C (untested).\n  * The __SC__ check is for Symantec.\n  */\n#  define NO_MEMCPY\n#endif\n#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)\n#  define HAVE_MEMCPY\n#endif\n#ifdef HAVE_MEMCPY\n#  ifdef SMALL_MEDIUM /* MSDOS small or medium model */\n#    define zmemcpy _fmemcpy\n#    define zmemcmp _fmemcmp\n#    define zmemzero(dest, len) _fmemset(dest, 0, len)\n#  else\n#    define zmemcpy memcpy\n#    define zmemcmp memcmp\n#    define zmemzero(dest, len) memset(dest, 0, len)\n#  endif\n#else\n   void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));\n   int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));\n   void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));\n#endif\n\n/* Diagnostic functions */\n#ifdef ZLIB_DEBUG\n#  include <stdio.h>\n   extern int ZLIB_INTERNAL z_verbose;\n   extern void ZLIB_INTERNAL z_error OF((char *m));\n#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}\n#  define Trace(x) {if (z_verbose>=0) fprintf x ;}\n#  define Tracev(x) {if (z_verbose>0) fprintf x ;}\n#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}\n#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}\n#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}\n#else\n#  define Assert(cond,msg)\n#  define Trace(x)\n#  define Tracev(x)\n#  define Tracevv(x)\n#  define Tracec(c,x)\n#  define Tracecv(c,x)\n#endif\n\n#ifndef XXX_Z_SOLO_XXX\t\t/* Disable in order to use malloc() - pcg */\n   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,\n                                    unsigned size));\n   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));\n#endif\n\n#define ZALLOC(strm, items, size) \\\n           (*((strm)->zalloc))((strm)->opaque, (items), (size))\n#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))\n#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}\n\n/* Reverse the bytes in a 32-bit value */\n#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \\\n                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))\n\n#endif /* ZUTIL_H */\n"
  },
  {
    "path": "deps/infozip/infozip/infozip.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.22823.1\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unzip\", \"..\\unzip60\\win32\\vc8\\unzip.vcxproj\", \"{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"zip\", \"..\\zip30\\win32\\vc6\\zip.vcxproj\", \"{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tASM Debug|Win32 = ASM Debug|Win32\n\t\tASM Release|Win32 = ASM Release|Win32\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Release|Win32.Build.0 = Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Release|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/infozip/unzip60/BUGS",
    "content": "Bogus bugs (not our fault!):\n---------------------------\n\n By far THE BIGGEST source of bug reports to Info-ZIP/zip-bugs is the\n incorrect transfer of zipfiles (or of the UnZip executable itself).\n ALWAYS TRANSFER IN BINARY MODE!  This includes ftp transfers and *both*\n ends of a Kermit connection (\"set file type binary\").  If your copy\n isn't exactly the same size as the original, you made a mistake.\n\n Another common source of errors such as \"compression method 8 not sup-\n ported\" is the existence of an old version of UnZip somewhere in your\n path.  Make sure you're using the version you think you're using; give\n the full path explicitly if necessary.  Executing \"unzip\" without any\n options will print a help screen, at the top of which is the UnZip\n version number and release date; and executing \"unzip -v\" without any\n zipfile or other options will give information about what compiler was\n used, the target operating system, any special UnZip options, and the\n date of compilation--only for version 5.11 and later, though!  (Also,\n under Unix C shell and some Bourne shells, \"which unzip\" will print\n the path of the unzip you're actually using.  Under OS/2 and MS-DOS,\n whch21gr.zip [on Simtel mirror sites] will do the same thing; in addi-\n tion, \"which -a unzip\" will show *all* copies of \"unzip\" in your path.)\n\n\nBugs (real and/or imagined):\n---------------------------\n\n - [OS/2 DLL] when trying to use the REXX function UzUnZipToStem to extract a\n    file with `&' in its name, the DLL crashes (but UzUnZipToVar still works)\n    [Daniel H, 961215]\n - UnZip has problems with archives bigger than 2GB; it may print \"note: didn't\n    find end-of-central-dir signature at end of central dir\" (harmless) or\n    may not be able to seek to member files [James Lemley 970107, Iris Spaniol\n    970206, ...]\n\n      Fixed with Zip64 support in UnZip 6.0\n\n - fix overwrite behavior:  hidden/system problems?; etc.\n - 32-bit DOS UnZip still unable to set volume labels?\n - 32-bit DOS UnZip under OS/2 doesn't extract all wildcard zipfiles?\n    [DOS box:  unzip386 (ver 5.12) x:\\32bit\\unix\\emx09a\\*.zip, Hobbes 3/95]\n - 32-bit DOS UnZip under OS/2 doesn't set timestamp when overwriting files\n    on HPFS partition? (go32 and pmode/w both; emx/rsx OK) [Eberhard Mattes\n    950726]\n - USE_FWRITE still causes occasional CRC errors when extracting on Pyramid?\n    [Kevin Fritz 931102]\n - still NT/W95 bug with \"unzip -v d:*.zip\" not matching properly? [Steve S\n    940527]\n    980427: bug no longer exists, Opendir() must have been corrected by someone\n\n - when ^Z received in no-echo mode, echo is not restored (works OK if\n    resume, however)\n - signal() handler disabled after first use with one of BSD/SysV?\n - MKS Korn shell:  unzip assumes the MKS-style command-line environment\n    options are relevant to it, but this is not the case if unzip was called\n    by another program (e.g., from a .BAT file).  A fix for this exists for\n    Borland compilers but not for MSC, Watcom, djgpp, etc.\n - OS/2:  for paths with one long component, the .LONGNAME EA may be saved for\n    all components (waste of disk space):  how to check??\n - VMS:  for extracting to other directories, only the VMS-style \"-d [.foo]\"\n    format is accepted; \"-d foo\" should also be allowed.  Long filenames are\n    not automatically truncated to 39.39.\n - Novell Netware:  Netware drives may clear the archive bit on extracted\n    files under OS/2 and/or MS-DOS.  UnZip always *tries* to set the archive\n    bit, however.  [pynq@uchicago, 940527]\n - DEC Ultrix:  on long zipfiles, unzip will sometimes fail (bad CRC, not always\n    reproducible); this is apparently due either to a hardware bug (cache mem)\n    or OS bug (page faults?) [Igor, Jean-loup, bottom of BUGS.long]\n - funzip/more/decryption/no-echo bug:  race condition(?) causes terminal to\n    be \"reset\" to no-echo state\n - Macintosh (100200), Atari (020000) external file attributes not interpreted\n    correctly (both unzip and zipinfo)\n - pkbug error:  zipfile with incorrect csize and/or ucsize--check for end of\n    compressed (csize) data in uncompression routines:\n      unreduce.c:    while (((outpos + outcnt) < ucsize) && (!zipeof)) {\n    [James Birdsall, Mark, bottom of BUGS.long]\n - OS/2:  directory EAs not restored if directory exists [Kai Uwe, KG27515@uark]\n    (subsequent note:  no way to determine which EAs are newer ==> cannot\n    restore without user input)\n    (update: as of UnZip 5.30, option -o forces restoring of directory EAs)\n - MS-DOS:  Borland executables don't allow other than 80-column, 25/43/50-line\n    screen modes (Borland bug) [Michael Stillwell]\n"
  },
  {
    "path": "deps/infozip/unzip60/COPYING.OLD",
    "content": "__________________________________________________________________________\n\n  This is the Info-ZIP file COPYING (for UnZip), last updated 17 Jul 2000.\n__________________________________________________________________________\n\n   FIRST NOTE:\n   This file contains some details about the copyright history of\n   contributions to the UnZip project.\n   Additionally, it summarises some exceptions to the general BSD-like\n   copyright found in LICENSE that covers our generic code and most of\n   the system specific ports.\n   Please read LICENSE first to find out what is allowed to do with\n   Info-ZIP's UnZip code.\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n   There are currently two explicit copyrights on portions of UnZip\n   code (at least, of which Info-ZIP is aware):\n   Jim Luther's Mac OS File Manager interface code; and Christopher Evans'\n   MacBinaryIII coding code (for the MacOS port)..  These copyrights\n   are discussed in more detail below.\n\n   All remaining code is now (starting with UnZip version 5.41) covered\n   by the new Info-ZIP license. For details, please read the acompaning\n   file LICENSE. The terms and conditions in this license supersede the\n   copyright conditions of the contributions by Igor Mandrichenko\n   (vms/vms.c), Greg Roelofs (zipinfo.c, new version of unshrink.c),\n   Mike White (Windows DLL code in \"windll/*\"), Steve P. Miller (Pocket\n   UnZip GUI \"wince/*\"), and Mark Adler (inflate/explode decompresseion\n   core routines, previously put into the public domain). All these\n   Info-ZIP contributors (or \"primary\" authors) have permitted us to\n   replace their copyright notes by the Info-ZIP License.\n\n   Frequently Asked Questions regarding (re)distribution of Zip and UnZip\n   are near the end of this file.\n\n   There are no known patents on any of the code in UnZip.  Unisys\n   claims a patent on LZW encoding and on LZW decoding _in an apparatus\n   that performs LZW encoding_, but the patent appears to exempt a stand-\n   alone decoder (as in UnZip's unshrink.c).  Unisys has publicly claimed\n   otherwise, but the issue has never been tested in court.  Since this\n   point is unclear, unshrinking is not enabled by default.  It is the\n   responsibility of the user to make his or her peace with Unisys and\n   its licensing requirements.  (unshrink.c may be removed from future\n   releases altogether.)\n__________________________________________________________________________\n\n   The original unzip source code has been extensively modified and\n   almost entirely rewritten (changes include random zipfile access\n   rather than sequential; replacement of unimplode() with explode();\n   replacement of old unshrink() with new (unrelated) unshrink(); re-\n   placement of output routines; addition of inflate(), wildcards,\n   filename-mapping, text translation, ...; etc.).  As far as we can\n   tell, only the core code of the unreduce method remained substantially\n   similar to Mr. Smith's original source.  As of UnZip 5.42, the complete\n   core code is now covered by the Info-ZIP Licence.  Therefore, support\n   for the reduce method has been removed.\n   The drop of the reduce method should only affect some test archives,\n   reducing was never used in any publically distributed Zip program.\n   For pathologic cases where support for reduced archive entries is\n   needed, the unreduce code copyrighted by Samuel H. Smith is available\n   as a separate distribution (the restricted copyright of this code is\n   cited below in the \"historical\" section).\n\n   The following copyright applies to the Mac OS File Manager interface code\n   (macos/source/macstuff.[ch]), distributed with UnZip 5.4 and later:\n\n     * MoreFiles\n     *\n     * A collection of File Manager and related routines\n     *\n     * by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)\n     * with significant code contributions by Nitin Ganatra\n     * (Apple Macintosh Developer Technical Support Emeritus)\n     * Copyright  1992-1998 Apple Computer, Inc.\n     * Portions copyright  1995 Jim Luther\n     * All rights reserved.\n     * The Package \"More Files\" is distributed under the following\n     * license terms:\n     *\n     *          \"You may incorporate this sample code into your\n     *           applications without restriction, though the\n     *           sample code has been provided \"AS IS\" and the\n     *           responsibility for its operation is 100% yours.\n     *           However, what you are not permitted to do is to\n     *           redistribute the source as \"DSC Sample Code\" after\n     *           having made changes. If you're going to\n     *           redistribute the source, we require that you make\n     *           it clear in the source that the code was descended\n     *           from Apple Sample Code, but that you've made\n     *           changes.\"\n\n   The usage terms of this copyright note are compatible with the\n   Info-ZIP license, they do not add further restrictions.\n\n\n   The following copyright applies to the Mac OS \"macbin3\" decoding code\n   (extra field compatibility with ZipIt):\n\n     *  MacBinaryIII.h\n     *\n     *  Copyright 1997 Christopher Evans (cevans@poppybank.com)\n     *\n     *  Basic encoding and decoding of Macintosh files to the\n     *  MacBinary III spec.\n     * ----------------------------------------------------------------------\n     * This source is copyrighted by Christopher Evans (cevans@poppybank.com)\n     * (available at ftp://ftp.lazerware.com/MacBinaryIII_src_C.sit\n     * homepage of Leonard Rosenthol  leonardr@netcom.com)\n\n  This copyright note does not contain any usage terms.  So, we assume\n  that this code is freely reusable until we are proved wrong...\n\n--------------------------------------------------------------------------\n\n   The remaining copyright notes have been superseeded by the new\n   Info-ZIP license, with explicit permission from the respective\n   original authors.  They are cited here for historical reasons,\n   only:\n\n   The following copyright applies to the full-featured unreduce.c\n   (now distributed separately):\n\n     * Copyright 1989 Samuel H. Smith;  All rights reserved\n     *\n     * Do not distribute modified versions without my permission.\n     * Do not remove or alter this notice or any other copyright notice.\n     * If you use this in your own program you must distribute source code.\n     * Do not use any of this in a commercial product.\n\n   Regarding the first stipulation, Mr. Smith was tracked down in southern\n   California some years back [Samuel H. Smith, The Tool Shop; as of mid-\n   May 1994, (213) 851-9969 (voice), (213) 887-2127(?) (subscription BBS),\n   71150.2731@compuserve.com]:\n\n   \"He says that he thought that whoever contacted him understood that\n    he has no objection to the Info-ZIP group's inclusion of his code.\n    His primary concern is that it remain freely distributable, he said.\"\n\n   Despite the fact that our \"normal\" code has been entirely rewritten\n   and by default no longer contains any of Mr. Smith's code, Info-ZIP\n   remains indebted and grateful to him.  We hope he finds our contribu-\n   tions as useful as we have his.\n\n   Note that the third and fourth stipulations still apply to any com-\n   pany that wishes to incorporate the unreduce code into its products;\n   if you wish to do so, you must contact Mr. Smith directly regarding\n   licensing.\n\n  -----\n\n   The following copyright applied to most of the VMS code in vms.c,\n   distributed with UnZip version 4.2 and later:\n\n     * Copyright (c) 1992-93 Igor Mandrichenko.\n     * Permission is granted to any individual or institution to use, copy,\n     * or redistribute this software so long as all of the original files\n     * are included unmodified and that this copyright notice is retained.\n\n  -----\n\n   The following copyright applied to the new version of unshrink.c,\n   distributed with UnZip version 5.2 and later:\n\n     * Copyright (c) 1994 Greg Roelofs.\n     * Permission is granted to any individual/institution/corporate\n     * entity to use, copy, redistribute or modify this software for\n     * any purpose whatsoever, subject to the conditions noted in the\n     * Frequently Asked Questions section below, plus one additional\n     * condition:  namely, that my name not be removed from the source\n     * code.  (Other names may, of course, be added as modifications\n     * are made.)  Corporate legal staff (like at IBM :-) ) who have\n     * problems understanding this can contact me through Zip-Bugs...\n\n  -----\n\n   The following copyright applied to the Windows DLL code (windll/*),\n   distributed with UnZip version 5.2 and later:\n\n     * Copyright (c) 1996 Mike White.\n     * Permission is granted to any individual or institution to use,\n     * copy, or redistribute this software so long as all of the original\n     * files are included, that it is not sold for profit, and that this\n     * copyright notice is retained.\n\n  -----\n\n   The following copyright applied to the Windows CE GUI port, ``Pocket\n   UnZip,'' distributed with UnZip version 5.3 and later:\n\n     * All the source files for Pocket UnZip, except for components\n     * written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n     * Miller.  The product \"Pocket UnZip\" itself is property of the\n     * author and cannot be altered in any way without written consent\n     * from Steve P. Miller.\n\n  -----\n\n   The remaining code was written by many people associated with the\n   Info-ZIP group, with large contributions from (but not limited to):\n   Greg Roelofs (overall program logic, ZipInfo, unshrink, filename\n   mapping/portability, etc.), Mark Adler (inflate, explode, funzip),\n   Kai Uwe Rommel (OS/2), John Bush and Paul Kienitz (Amiga), Antoine\n   Verheijen (Macintosh), Hunter Goatley (more VMS), Mike White (Windows\n   DLLs), Christian Spieler (overall logic, optimization, VMS, etc.) and\n   others.  See the file CONTRIBS in the source distribution for a much\n   more complete list of contributors.\n   The decompression core code for the deflate method (inflate.[ch],\n   explode.c) was originally written by Mark Adler who submitted it\n   as public domain code.\n\n--------------------------------------------------------------------------\n"
  },
  {
    "path": "deps/infozip/unzip60/Contents",
    "content": "Contents of the UnZip 6.00 source archive.  The OS-specific subdirectories\nat the end contain their own Contents listings:\n\n  Contents      this file\n  README        what UnZip is; general information\n  LICENSE       Info-ZIP license; terms for using and distributing UnZip\n  COPYING.OLD   historic copyrights and distribution policy (obsolete)\n  INSTALL       how to compile and install UnZip and related utilities\n  WHERE         where Zip/UnZip and encryption/decryption support can be found\n  History.600   new features and fixes of the last major release\n  ToDo          rough priority list of new features to be added in next release\n  BUGS          known bugs, problems, and (possible) other features to be added\n  unzip.txt     UnZip manual page, human-readable format\n  unzipsfx.txt  UnZipSFX manual page, human-readable format\n  zipinfo.txt   ZipInfo manual page, human-readable format\n  zipgrep.txt   ZipGrep manual page, human-readable format\n  funzip.txt    fUnZip manual page, human-readable format\n  file_id.diz   BBS-oriented file describing this archive\n  testmake.zip  test archive for checking whether newly compiled UnZip works\n  api.c         generic DLL entry points, support functions (required for DLLs)\n  apihelp.c     API help text for DLL versions (currently OS/2 only)\n  consts.h      global, initialized variables that never change (required)\n  crc32.c       code for calculation 32bit CRC of a string buffer (required*)\n  crc32.h       declarations for the crc-32 code (required*)\n  crc_i386.S    fast assembler replacement for crc32() (Intel 386 and newer)\n  crypt.c       de-/encryption routines (required*)\n  crypt.h       de-/encryption header file (required*)\n  ebcdic.h      static lookup table for ASCII <-> EBCDIC translation (required)\n  envargs.c     code to read options from environment variables (required)\n  explode.c     code for exploding (required)\n  extract.c     high-level extraction and decryption code (required)\n  fileio.c      file manipulation and password code (required)\n  funzip.c      filter unzip:  extracts in a pipe from stdin to stdout\n  gbloffs.c     helper program to retrieve offsets of globals struct members\n  globals.c     code to support global variables with reentrancy (required)\n  globals.h     definition of global structure G (required)\n  inflate.c     code for inflating (required*)\n  inflate.h     header file for inflating (required*)\n  list.c        UnZip listing routines, non-ZipInfo mode (required)\n  match.c       pattern-matching code for filename wildcards (required)\n  process.c     zipfile headers code (required)\n  timezone.c    timezone and timestamp functions (required)\n  timezone.h    header file for interface to \"internal\" tz functions (required)\n  ttyio.c       code for handling nonecho tty input: password, pager (required)\n  ttyio.h       header file for nonecho tty input: password, pager (required)\n  ubz2err.c     callback handler for fatal bzip2 errors (bzip2 support only)\n  unreduce.c    code for unreducing (required)\n  unshrink.c    code for unshrinking (required)\n  unzip.c       UnZip main(), usage and options code (required)\n  unzip.h       public half of main UnZip header file (required*)\n  unzipstb.c    minimal UnZip \"stub\" file demonstrating use of DLL versions\n  unzpriv.h     private (internal) half of main UnZip header file (required*)\n  unzvers.h     header with UnZip/UnZipSFX and ZipInfo version info (required)\n  zip.h         dummy header for use with crypt.c (required*)\n  zipinfo.c     UnZip listing routines, ZipInfo mode (required)\n  acorn/        support files for compiling under Acorn RISC OS\n  amiga/        support files for compiling under AmigaDOS\n  aosvs/        support files for compiling under Data General AOS/VS\n  atari/        support files for compiling under Atari TOS\n  atheos/       support files for compiling under AtheOS/Syllable\n  beos/         support files for compiling under BeOS\n  cmsmvs/       support files for compiling under VM/CMS and MVS\n  flexos/       support files for compiling under FlexOS\n  human68k/     support files for compiling under X68000/Human68K\n  macos/        support files for compiling under Macintosh OS\n  msdos/        support files for compiling under MS-DOS\n  netware/      support files for compiling for Novell Netware NLM\n  os2/          support files for compiling under OS/2 (includes DLL stuff)\n  qdos/         support files for compiling under SMS/QDOS\n  tandem/       support files for compiling under Tandem NSK\n  theos/        support files for compiling under Theos\n  tops20/       support files for compiling under TOPS-20\n  unix/         support files for compiling under Unix\n  vms/          support files for compiling under VMS\n  win32/        support files for compiling under Windows 9x and Windows NT\n  wince/        support files for compiling under Windows CE (GUI version)\n  windll/       support files for compiling Windows 3.x/9x/NT DLLs\n  bzip2/        subfolder for source of externally supplied bzip2 extension\n  man/          nroff man-page sources for the main user documentation\n  proginfo/     programming docs, additional technical info, contributor list\n\nFiles marked \"required*\" are also needed to compile fUnZip.  The normal\nUnZip makefile targets now make both UnZipSFX and fUnZip, except in a few\ncases; ZipInfo is now incorporated into UnZip (see zipinfo.txt for usage).\n"
  },
  {
    "path": "deps/infozip/unzip60/History.600",
    "content": "UnZip, version 6.00, 20 April 2009\n\nFeatures added (or removed):\n\n6.00a ():\n - Many changes by Myles\n\n6.00b (12 Nov 04):\n - Added dll changes from Mike White.  [Mike White (MW), Ed Gordon (EG)]\n - Added Unix Large File Support but must be enabled manually.  [EG]\n - Humble beginnings of adding configure script to Unix port to\n    autoconfigure large file support.  [EG]\n - VMS changes, including large file support, better handling of\n   -V and new -VV options, revised build procedures, and\n   documentation updates.  [Steven Schweda (SMS)]\n - file_size added to process.c to handle files sizes larger\n   than 2 GiB more cleanly when no large file support.  [SMS]\n - Large file debugging on Unix and VMS.  [SMS, EG]\n - Split w32i64.h with large file includes for dll [EG]\n\n6.00c (1 Feb 05):\n - Various Amiga and Win32 changes (see files).  [Paul Kienitz (PK)]\n - Add NOSHARE compile option for VMS.  [SMS]\n - Updates to windll (list.c, structs.h, uzexampl.c, uzexampl.h, windll.aps,\n   windll.c, windll.h, windll.rc, windll.txt, sfxwiz.c) to add VB support\n   for Zip64 to dll [MW]\n\n6.00c (14 Feb 05):\n - Added ODS5 extended file name support for VMS.  (Eight-bit-only, no\n   Unicode.)  Zip name character \"?\" is mapped to VMS name character\n   \"/\".  ODS2 file names are now explicitly upper-case. [SMC]\n - New VMS option, -2 (/ODS2), forces ODS2-compatible file names even\n   when the destination file system is ODS5. [SMC]\n - New VMS option, -Y (/DOT_VERSION), causes archived file name endings\n   of \".nnn\" (where \"nnn\" is a decimal number) to be treated as if they\n   were VMS version numbers (\";nnn\").  Example: \"a.b.3\" -> \"a.b;3\". [SMC]\n\n6.00c8 (08 May 05):\n - Added optional BZIP2 support, using the free BZIP2 library. Enabled\n    by defining the compile time option USE_BZIP2. [Johnny Lee]\n - Revised optional ZLIB support to use the new zlib 1.2.x callback interface\n    when available (significant performance gain, now faster than UnZip's\n    built-in decompression code) [Christian Spieler]\n - Added interface into zlib's unsupported \"inflate9\" callback code (a contri-\n    buted extension in zlib 1.2.x), for extracting Deflate64 entries. Enabled\n    by defining the compile time option HAVE_ZL_INFLAT64. [Christian Spieler]\n - windll: added separate entry point Wiz_SingleEntryUnzipList for VB support,\n    changed Wiz_SingleEntryUnzip back to 5.x version [Christian Spieler]\n\n6.00c9 (15 May 05):\n - NO feature changes.\n\n6.00c10 (21 May 05):\n - WinCE port: Adapted PocketUnzip to UnZip6 code and enabled Zip64 support\n    for the WIN32 (non-WinCE) targets. [Chr. Spieler]\n\n6.00c11 (23 May 05):\n - NO feature changes.\n\n6.00c12 (15 Aug 05):\n - windll/csharp: new example project for .NET framework 1.1, written in C#.\n    (currently unsupported by the Info-ZIP group) [Adrian Maull]\n - MSDOS port: added warning message when used in an (32/64-bit) Windows\n    virtual MSDOS process; currently only shown when an error or warning\n    occured.  [Johnny Lee, Chr. Spieler]\n\n6.00c13 (02 Oct 05), 6.00c14 (15 Nov 05), 6.00c15(17 Nov 05):\n - NO feature changes.\n\n6.00c (19 Nov 05):\n - NO feature changes.\n\n6.00d01 (04 Mar 07):\n - unix/unix.c: when extracting directory entries, keep a SGID attribute\n    inherited from the parent dir (to allow content created in these new\n    directories to inherit the parent's GID), unless the directory entry was\n    created on UNIX, and UnZip was requested to restore UID/GID or SUID/SGID.\n    [Matthew Seitz, Chr. Spieler]\n - process.c, modified info message handling for timestamping operation mode\n    to be more consistent with message handling of other operations: suppress\n    summary message only when qflag > 1 in process_zipfiles(); added time-stamp\n    success message to do_seekable() in non-quiet mode; moved message strings\n    to Far string constants.  [Steven M. Schweda, Chr. Spieler]\n - process.c - process_zipfiles(): suppress the \"cannot find any wildcard\n     match ...\" warning message for (qflag >= 3).  [Chr. Spieler]\n - vms/vms.c: added support for delayed restoration of directory attributes\n     [Steven M. Schweda]\n - vms/vms.c - return_VMS(): implemented official HP-assigned facility code\n    in the calculation of UnZip's (non-success) VMS exit status codes.\n    [Steven M. Schweda]\n - vms/vms.c, vms/cmdline.c vms/unz_cli.cld, unzip.c, unzip.h: added \"-S\"\n    option to change output record format into Stream-LF for text files when\n    extracted in \"convert text-files\" mode.  [Steven M. Schweda]\n - unzpriv.h, extract.c, unix/unix.c, atari/atari.c, atheos/atheos.c,\n    beos/beos.c: added separate pInfo flag to record symlink entries, moved\n    symlink detection code into mapattr(), added VMS to the list of hosts known\n    to support symbolic links.  [Steven M. Schweda, Christian Spieler]\n - VMS: added support to extract \"symlink\" entries as symbolic links (requires\n    up-to-date version of OpenVMS).  [Steven M. Schweda, Chr. Spieler]\n - unzip.1: added description of new VMS-specific \"-S\" option. [Chr. Spieler]\n - unzip_cli.help, unzip_def.rnh: updated exit codes documentation, added new\n    option (-S resp. /TEXT=STMLF).  [Steven M. Schweda, Chr. Spieler]\n - unzip_cli.help, unzip_def.rnh: completed resp. added description of new\n    VMS-specific options (-Y, -2).  [Chr. Spieler]\n - process.c: added preliminary (alpha-state) support for reading of Unicode\n    Path extra field that now sets globals unipath_filename and\n    unipath_escapedfilename (not yet functional).  [EG]\n\n6.00d02 (08 Mar 07), 6.00d03 (10 Mar 07), 6.00d04 (11 Mar 07):\n - NO feature changes.\n\n6.00d05 (31 Mar 07):\n - win32/vc6: added VC6 project files for compiling UnZip with support for\n    bzip2 decompression.  [Chr. Spieler]\n - INSTALL, unix/Makefile, unix/configure: support compiling of UnZip with\n    integrated bzip2 decompression capability, added check for presence of\n    bzip2 library sources to configure script, updated bzip2-related\n    documentation in INSTALL.  [Chr. Spieler]\n\n6.00d06 (02 Dec 07):\n - VMS: added support for displaying UnZip exit code error messages through\n    the VMS built-in message facility; new vms/UNZIP_MSG.MSG message string\n    source, modified vms/descrip.mms makefile.  [Steven M. Schweda]\n - UNIX: added new \"-^\" command line option that switches off the control\n    character filter for extracted filenames.  [Chr. Spieler]\n - UNIX: added support for restoring attributes and UID/GID for symbolic\n    links when appropiate OS support is provided.  [Chr. Spieler]\n\n6.00d07 (26 Dec 07):\n - New \"-D\" option which allows skipping of timestamp restoration for extracted\n    directory entry or for all files (\"-DD\").  [Chr. Spieler]\n - windll: added support for new -D (-DD) option to dll interface, updated\n    the documentation.  [Chr. Spieler]\n\n6.00d08 (29 Dec 07):\n - On VMS, the default is now to not restore directory timestamps (consistent\n    with BACKUP); \"-D\" skips all timestamp restorations, \"--D\" enables\n    timestamp restoration for all entries.  [Chr. Spieler, Steven M. Schweda]\n\n6.00d09 (06 Jan 08):\n - NO feature changes.\n\n6.00d10 (10 Feb 08):\n - partial integration of Ed Gordon's UNICODE_SUPPORT code (W9x-ANSI mode only\n    for now) seems to be finished.  [Ed Gordon, C. Spieler]\n - zipinfo.c: added support for \"UTF-8 path\" extra field display to zi_long().\n    [Chr. Spieler]\n\n6.00d11 (16 Feb 08):\n - ATheOS, BeOS, Tandem, Unix: experimental extension of \"Ux\" extra field to\n    allow restoration of 32-bit UID & GID values (affected generic sources:\n    unzpriv.h and process.c).  [Chr. Spieler]\n\n6.00d (17 Feb 08):\n - NO feature changes.\n\n6.00e01 (21 Feb 08):\n - NO feature changes.\n\n6.00e02 (08 Mar 08):\n - ATheOS, BeOS, Tandem, Unix: removed experimental 32-bit extension of \"Ux\"\n    extra field (affected generic sources: process.c).  [Chr. Spieler]\n\n6.00e03 (29 Mar 08):\n - general (ebcdic.h, process.c, unpriv.h): modified infrastructure to make\n    OEM<-->ISO translation configurable at runtime.  [Chr. Spieler]\n - MSDOS (doscfg.h, msdos.c): OEM<-->ISO configured at runtime, depending on\n    system codepage (enabled for 437, 850, 858; disabled for 932, 936, 949,\n    950, 874, 1258; currently also disabled for all other OEM codepages because\n    of missing translation tables).  [Chr. Spieler]\n\n6.00e04 (27 Apr 08):\n - NO feature changes.\n\n6.00e05 (09 Sep 08):\n - unzip.c: added framework for verbose multi-page online help, called by\n    option \"-hh\".  [Ed Gordon]\n - process.c, unzpriv.h, unix/unix.c: added support for new IZUNIX3 extra field\n    providing 32-bit UID/GID data.  [Ed Gordon, Chr. Spieler]\n - unzip.c - uz_opts(): do not exit immediately after recognizing help screen\n    request; this allows to specify the pager option after the explicit help\n    request.  [Chr. Spieler]\n\n6.00e06 (13 Sep 08):\n - NO feature changes.\n\n6.00e (04 Jan 09):\n - unzip.h: enable -B option for Unix, OS/2, and Win32.  [EG, Chr. Spieler]\n\n6.00f (11 Jan 09):\n - NO feature changes.\n\n6.00g01 (08 Jan 09), 6.00g02 (25 Jan 09), 6.00g03 (10 Feb 09),\n6.00g04 (16 Feb 09), 6.00g (28 Feb 09),\n6.00h01 (09 Mar 09), 6.00h02 (16 Apr 09), 6.00h03 (17 Apr 09),\n6.00 (20 Apr 09):\n - NO feature changes.\n\nBugs fixed:\n\n6.00b (12 Nov 04):\n - Output bug fixes to account for sizes > 2 GiB and < 4 GiB.  [EG]\n - Bug fixes in ZipInfo.  [EG]\n - Reverted unix.c to an older version to make\n    calls to defer_dir_attribs compatible.  Also needed to rework\n    win32.c to make compatible.  Probably broke NT but haven't tested.\n    Need to trace out and fix.  [EG]\n\n6.00c (1 Feb 05):\n - Various bug fixes (see files gbloffs.c, process.c, unzpriv.h, amiga/amiga.h,\n    amiga/filedate.c, amiga/flate.a, amiga/makefile.azt, and win32/w32cfg.h).\n    [PK]\n - Some type changes in globals.h.  [SMS]\n\n6.00c (14 Feb 05):\n - Disambiguated some identical VMS error messages. [SMC]\n\n6.00c8 (08 May 05):\n - extract.c, unzip.c, unzpriv.h: Some tweaks and corrections to the optional\n    BZIP2 support [Christian Spieler]\n - VMS, cmdline.c unz_cli.cld: fixed the completely broken addition of\n    the /ODS2 and /DOT_VERSION options [Christian Spieler]\n - Merged in all additions and fixes of the UnZip 5.5x code tree from\n    UnZip 5.50i up to UnZip 5.52 release.  Removed History.5?? files.\n    Removed all History.600 entries that have been covered by fixes from\n    the UnZip 5.5x code.\n    For detailed ChangeLog see History.550, History.551, and History.552,\n    as found in unzip552.zip source distribution and the UnZipHist.zip\n    ChangeLog archive.  [Christian Spieler]\n - crypt.[ch]: updated to 2.10 (synchronized with zip 2.31) [Christian Spieler]\n - envargs.c: do not declare getenv() for \"modern\" compilers [Cosmin Truta]\n - extract.c: better echo message for CR or LF at overwrite prompt [Cosmin?]\n - fileio.c: added specific message for SIGILL in handler()  [Chr. Spieler]\n - process.c: fixed code of optional USE_STRM_INPUT variant [Chr. Spieler]\n - VMS, vms.c: requires \"-vv\" instead of only \"-v\" to enable VMS diagnostic\n    output (enable DIAG_FLAG for vflag >= 3, only; DIAG output is not available\n    for the unzip modi \"extract to disk\" and \"zipinfo\") [Christian Spieler]\n - VMS cli interface: added (undocumented) option modified /FULL=DIAGNOSTICS to\n    control \"-vv\" diagnostic messages [Steven M Schweda, Christian Spieler]\n - WIN32/MSDOS (maybe others): fixed abort exception handling for CTRL-BREAK\n    [Christian Spieler]\n - revised ecrec64 search logic: ecrec64 need not be present when one of\n    the ecrec fields is filled with all 1's.  [Christian Spieler]\n - added user-defined types for 8-byte and 4-byte Zip archive (unsigned)\n    quantities [Christian Spieler]\n - MSDOS 32-bit port revitalized [Christian Spieler]\n - windll: changed interface definition to be independent of compile/feature\n    configuration [Christian Spieler]\n - man/unzip.1: Typo corrections [anonymous DEBIAN contribution, Santiago Vila]\n - man/unzip.1: removed duplicated quotes from VMS example in environment\n    variable section [Steven M. Schweda]\n\n6.00c9 (15 May 05):\n - zipinfo.c, list.c: fix the structure check for correct end-of-central dir\n    to be aware of Zip64 extensions [Christian Spieler]\n - windll, sfxgui: synchronize function definitions with changed windll\n    interface [Mike White]\n - extract.c, fileio.c, process.c: fixed USE_STRM_INPUT variant of file\n    position seeking [Christian Spieler]\n - process.c - file_size(): changed scope into static; added non-USE_STRM_INPUT\n    variant that uses zlseek instead of zfseeko and zftello; do not include in\n    SFX stub; do not compile function definition when not used [Chr. Spieler]\n - unzpriv.h: revised and cleaned up setup definitions for zstat, zfstat and\n    other 64-bit configuration macros [Christian Spieler]\n - win32/w32cfg.h: revised automatic ZIP64 support enabling logic and compiler-\n    specific configuration; turned off ZIP64 support for lcc and BorlandC\n    because of missing LARGE_FILE support; verified LARGE_FILE support for\n    Watcom C and MinGW [Chr. Spieler]\n - win32/win32.c: fixed type specification in zstat_win32() [Chr. Spieler]\n - win32/win32i64.c: do not include seek replacement functions when not needed\n    [Christian Spieler]\n - zipinfo.c: adapted verbose printouts to longer number printings of Zip64-\n    enabled UnZip; fixed extra-space detection in zi_long() by moving the\n    extra-field read in front of the offset comparison [Christian Spieler]\n\n6.00c10 (21 May 05):\n - zipinfo.c - zi_long(): fixed expression for detecting 64-bit local entry\n    offset [Chr. Spieler]\n - process.c - find_ecrec64(): added type-casts to shut up conversion warnings,\n    removed code that clobbered the ecrec signature \"pseudo-constant\" by\n    overwriting it with the ecrec64 signature (this bug broke the reentrancy\n    of the dll code) [Chr. Spieler]\n - win32/win32.c, unzpriv.h: adapted SetFileSize for 64-bit offsets[C. Spieler]\n - extract.c, fileio.c, process.c: removed unneeded (FILE *) type-casts in\n    calls to zfseeko() and zftello() [Chr. Spieler]\n - extract.c, list.c, zipinfo.c, unzpriv.h: use symbolic constants for the\n    16-bit and 64-bit masks in the checks for zip entry count consistency\n    [Steven M. Schweda, Chr. Spieler]\n - process.c: reorganized the extended Zip filesize-checking code (for > 2GB\n    detection) by moving it behind the open_infile () call and using the\n    already opened global zipfile handle [Steven M. Schweda, Chr. Spieler]\n - fileio.c: allow output redirection to memory when ZIP64_SUPPORT is enabled\n    [Chr. Spieler]\n - windll: synchronized uzexampl.c and uzexampl.h with current windll interface\n    declarations [Chr. Spieler]\n\n6.00c11 (23 May 05):\n - process.c: fixed bugs in last filesize-checking revision (added missing\n    semi-colon, synchronized file_size() call with its prototype declaration\n    [Steven M. Schweda, Chr. Spieler]\n\n6.00c12 (15 Aug 05):\n - VMS port: updated the dependency build routines (*.mms, *.com) and the VMS\n    install documentation (INSTALL) [Steven M. Schweda]\n - api.c - redirect_outfile(): initialize check_conversion variable in the\n    non-textmode case [Chr. Spieler]\n - process.c, extract.c: moved the crctab initialization and check of the\n    extraction root dir from do_seekable() further down the call tree into\n    extract_or_test_files() [Chr. Spieler]\n - extract.c - extract_or_test_entrylist(): moved central-vs-local consistency\n    checks behind the local Zip64-e.f. code [Chr. Spieler]\n - fileio.c - do_string() bugfix: do not call getZip64Data() when previous\n    allocation of extra field buffer has failed [Chr. Spieler]\n - inflate.c - inflate_dynamic(): free table-decoding huft-tree when exiting\n    prematurely from the literal/distance tree data reading because of invalid\n    compressed data [Rudolf Lechleitner, Chr. Spieler]\n - unzip.c - uz_opts(): local variable \"error\" should only take boolean values,\n    no PK error codes (cosmetic correction) [Chr. Spieler]\n - vms/vms.c, process.c: modified handling of VMS do_wild() lookup errors to\n    give more helpful messages to the end user [Steven M. Schweda]\n - unix/zipgrep: fixed security hole by handling shell metacharacters like '|'\n    and '&' properly when they occurred in input file names [Greg Roelofs]\n - match.c: copied and adapted optimization for \"*fixedstring\" patterns from\n    the Zip code into recmatch(); provided two local helper functions isshexp()\n    and namecmp() for this optimization [Johnny Lee, Chr. Spieler]\n - Where: used the newer version from UnZip 5.52 [Chr. Spieler]\n\n6.00c13 (02 Oct 05):\n - AOS/VS, Atari, AtheOS, BeOS, UNIX: fixed symlink code by avoiding fclose()\n    on NULL handle in extract.c [Dan Yefimov]\n - AOS/VS, Atari, AtheOS, BeOS, UNIX (and unzpriv.h, fileio.c): modified the\n    symlink code to use the opened outfile handle for re-reading the symlink\n    target data; modified open_outfile to allow read access on outfile handle\n    (security fix against \"ToCToU\" vulnerability) [Chr. Spieler]\n - UNIX (unix.c, Makefile, configure): fixed \"ToCToU\" security vulnerability\n    in close_outfile by using fchown() & fchmod() instead of chown() & chmod()\n    (only when available); added check for function existence to configure\n    [Dan Yefimov, Matthias Scheler, Chr. Spieler]\n - fileio.c - open_outfile(): deny access for group&world to currently open\n    outfile on all systems that support umask() (AOS/VS, Atari, AtheOS, BeOS,\n    QDOS, Tandem, UNIX) [Chr. Spieler]\n - unzpriv.h, fileio.c - open_outfile(): open outfile in \"write update\" mode\n    when supporting symlinks or QLZIP extensions; these features require the\n    ability to reread the opened outfile [Chr. Spieler]\n - fileio.c: added WriteTxtErr() macro to allow differenciating between\n    text-mode write function calls (in UzpMessagePrnt()) and binary write calls\n    (everywhere else) [Chr. Spieler]\n - fileio.c, VMS only: use fprintf() instead of (f)write in WriteTxtErr(), to\n    work around RMS record handling problem (e.g. when using PIPE to redirect\n    messages) [Steven M. Schweda]\n - UNIX port: revised unix/configure and unix/Makefile for better integration\n    of automatic configuration in the build procedure [Chr. Spieler]\n\n6.00c14 (15 Nov 05):\n - VMS, descrip.mms: repaired CLEAN_ALL target which did not always delete\n    all expected files  [Steven M. Schweda]\n - unzip.c, fixes for online help screen: corrected \"-v\" description and moved\n    it from modifier section into options section, added description of \"-T\"\n    option, removed the \"DLL && API_DOC\"-only description of the \"-A extended\n    API help\" option [Chr. Spieler, Steven M. Schweda]\n - man/unzip.1: minor corrections in wording of \"-v\" option description\n    [Chr. Spieler, Steven M. Schweda]\n\n6.00c15 (17 Nov 05):\n - vms/vms.c: fixed do_wild() logic error introduced in August 2005,\n    sys$search fails (at least on VAX) when not preceeded by a sys$parse\n    call with \"syntax-check-only\" flag cleared [Steven M. Schweda]\n - process.c: cosmetic change in process_zipfiles() to shut-up gcc warning\n    on non-UNIX (non-QDOS) systems [Chr. Spieler]\n\n6.00c (19 Nov 05):\n - extract.c, bzip2 support: fixed missing \";\" error (was only a problem\n    when enabling BZIP2 support without LARGE_FILE support); added some\n    (cosmetic) typecasts to shut up compiler warnings [Steven M. Schweda]\n - VMS support for BZIP2 decompression: updated make procedures and scripts,\n    added \"find_bzip2_dir\" helper script and bzlib.h include file wrapper\n    [Steven M. Schweda]\n\n6.00d01 (04 Mar 07):\n - extract.c: replaced local wsize variable (DLL only) by reference to the\n    \"global\" variable G._wsize [Chr. Spieler]\n - unzpriv.h: use fputs() instead of fprintf() as output function in the\n    FUNZIP variant of the Info() macro, to prevent misinterpreting format\n    specifiers in the sprintf() output. [Martin Pitt, ubuntu]\n - unix/unix.c: added detailed compiler version info for SunPro cc, HP cc,\n    DEC cc. [Steven M. Schweda]\n - vms/descrip.mms: added support for architecture detection macro symbols\n    built into newer versions of MMK (a MMS clone).  [Steven M. Schweda]\n - fileio.c - is_vms_varlen_txt(): commented out the currently unused code for\n    determining the VMS fileorg setting. [Steven M. Schweda]\n - extract.c - extract_or_test_files(): the \"back at endsig\" checking code\n    is not used for the SFX stub. [Steven M. Schweda]\n - win32: changed all Win32-API calls with string parameters to explicitely use\n    the ANSI variant; this removes the dependency on the UNICODE and _UNICODE\n    compile flags being undefined.  [NN, Chr. Spieler]\n - zipinfo.c: on WIN32, archive filename display must be fed through codepage\n    translation. [Chr. Spieler]\n - zipinfo.c - zipinfo(): repaired several memory leaks when the listing loop\n    is stopped prematurely because of inner errors. [Chr. Spieler]\n - crc32.c, crc32.h, crc_i386.S, crc_i386.asm, crc_i386.c: comprehensive\n    revision of crc32 calculation, implementing the optimized algorithms from\n    the zlib source code which depend on specific machine architecture\n    characteristics (removed crctab.c, added crc32.h).  [Chr. Spieler]\n - crypt.c, crypt.h: adapted to the modifications of crc32.  [Chr. Spieler]\n - msdos, win32, vms, unix: enabled optimized crc32 algorithms on i386, VAX,\n    and AXP architectures.  [Chr. Spieler]\n - win32/nt.c: tried to fix mutex handle leak in Initialize().\n    [Johnny Lee, Chr. Spieler]\n - vms/vms.c - check_format(): added system error message to sys$open failure\n    message. [Steven M. Schweda]\n - wince/intrface.cpp - checkdir(): corrected typo ('0' should be '\\0')\n    [Shawn Carey]\n - wince/wcemain.c - WinMain(): correct the removal code for enclosing argument\n    quotes. [Shawn Carey, Chr. Spieler]\n - os2, win32 - checkdir(): fixed buffer overflow security bug for FAT-style\n    buildpath, optimized code by removing overflow checks inside the copy loops\n    [Johnny Lee, Chr. Spieler]\n - win32/win32.c - VFatFileTime2utime(): fixed return data generation in error\n    branch for the \"input time stamp cannot be converted to local time\" case\n    [Steve Youngs]\n - added new compression methods and e.f. IDs from PKWARE Appnote 6.3.0 as of\n    2006-09-29  [Chr. Spieler]\n - extract.c - extract_or_test_files(): remove dead branch in the code section\n    handling archive test summary messages.  [Chr. Spieler]\n - fileio.c - zstrnicmp(): added (uch) typecasts to comparison, to improve\n    \"compatibility\" with \"extended ASCII characters\".  [Chr. Spieler]\n - vms: use CRTL-supplied function strncasecmp() for STRNICMP() when available.\n    [Steven M. Schweda, Chr. Spieler]\n - vms/vms.c, vms/vms.h: for better synchronisation with upcoming UnZip 6 code,\n    the macros for masking the \"ODS2 vs. ODS5\" support differences have been\n    cleanded up and ported back to the 5.5x VMS code.  [Chr. Spieler]\n - ubz2err.c: new source file to isolate the bzip2 \"fatal error\" callback\n    routine in its own module; this allows easy replacement of this routine\n    when the UnZip package is used as a static library (e.g. for WiZ with\n    bzip2 support).  [Chr. Spieler]\n - general: added new ubz2err.c module to the make procedures of ports that\n    (might) support bzip2.  [Chr. Spieler]\n - crypt.c: optimized crypt-keys handling for Big-Endian systems using the\n    optimized CRC32 code by introducing a local copy of the crc32 table\n    containing byte-swapped values.  [Chr. Spieler]\n - extract.c, unzpriv.h: modified calling interface of find_compr_idx() to\n    use unsigned instead of ush.  [Steven M. Schweda, Chr. Spieler]\n - vms/vms.c: added missing include of crc32.h header, added missing fab, nam\n    variable declarations to checkdir().  [Steven M. Schweda]\n - vms/make_unz.com, vms/link_unz.com: avoid link problems with sticky\n    dev:[dir] spec from externally supplied bzip2 lib.  [Steven M. Schweda]\n - vms/vms.[ch]: changed \"ODS2 vs. ODS5\" masking macros back to pre-5.53d\n    style. [Steven M. Schweda]\n - vms: updated/corrected build procedures to handle modified bzip2 support.\n    [Steven M. Schweda]\n - typo correction \"explicitly\" in various files.  [Steven M. Schweda]\n - cosmetic documentation change: use the \"bzip\" name all-lowercase when\n    applied to the \"library\".  [Steven M. Schweda, Chr. Spieler]\n - vms/vms.c - return_VMS(): corrected mapping of PK_WARN to VMS status code\n    severity level \"Warning\" (fixed regression bug introduced in UnZip 5.32).\n    [Steven M. Schweda]\n - process.c: preliminary fixed Zip64 support to match 4.5 AppNote, removing\n    the 76 byte error [EG]\n\n6.00d02 (08 Mar 07):\n - extract.c: corrected typo (missing \";\") in SYMLINKS code. [Steven M.Schweda]\n - VMS: updated MMS/MMK scripts (adapt for case-sensitive ODS5 and changed/new\n    source/header files).  [Steven M. Schweda]\n - vms/vms.c: provide RMS resp. QIO re-read functionality for SYMLINKS support.\n    [Steven M. Schweda]\n - vms/vms.c: revised SYMLINKS support (no special symlinks handling in -c, -p\n    piping output mode, fixed buffer overflow security holes, moved symlink\n    post-processing from close_outfile into the mode-specific subroutines,\n    for \"-V archived\" entries the symlink target spec is only read back when\n    needed for informational display purpose).  [Christian Spieler]\n\n6.00d03 (10 Mar 07):\n - vms/vms.c: modified style of static function declarations into \"independent\"\n    lines (on request of Steven M. Schweda).  [Chr. Spieler]\n - vms/vms.c: checked compilation, removed typos and wrong-named variables\n    [Chr. Spieler]\n\n6.00d04 (11 Mar 07):\n - vms/vms.c: used \"better self-documenting\" names for qio status structures,\n    corrected/enhanced some error messages (unified formatting, specified\n    \"location\" in code).  [Steven M. Schweda]\n - unix/Makefile: added some (preliminary) support for compiling with optional\n    bzip2 decompression capability (mostly copied from msdos/Makefile.dj2,\n    is not yet tested).  [Chr. Spieler]\n - process.c: added additional consistency checks to find_ecrec64().\n - extract.c, list.c, zipinfo.c: reviewed the \"central dir processing complete\"\n    check to take into account the new status semantics from find_ecrec64().\n    [Chr. Spieler]\n\n6.00d05 (31 Mar 07):\n - Win32 port: added VC6 project files for \"minimal\" bz2lib and unzip with\n    bzip2 support.  [Chr. Spieler]\n - list.c: added missing \"PPMd\" entry to array of known compression methods.\n    [Chr. Spieler]\n - vms/vms.c: close a potential buffer overflow hole in symlinks handling code.\n    [Chr. Spieler]\n - inflate.c - inflate_dynamic(): fixed erroneous huft_free() calls for\n    unallocated memory when processing invalid data.  [Chr. Spieler]\n - crc32.[ch], crc_i386.S: added updated files that were accidentally missed\n    in update 6.0d01.  [Chr. Spieler]\n - bz2lib renamed to bzip2 at request from Ed Gordon and Steven M. Schweda,\n    updated affected makefiles (MS-DOS, Unix, Win32).  [Chr. Spieler]\n - renamed \"Novell\" port to \"Netware\" for clarity.  [Chr. Spieler]\n - win32.c - close_outfile(): on WinNT, truncate outfile to actual bytes\n    written before close; otherwise, preallocated disk space does not get freed\n    when extraction failed or was interrupted.  [Chr. Spieler]\n - process.c: corrected bugs in ecloc64 and ecrec64 recognition code.\n    [Ed Gordon]\n - process.c: some cleanup in debugging code (changed TTrace() to Trace() in\n    non-timestamp-related code portions.  [Chr. Spieler]\n - unzip.h: updated license text to last version of License.  [Chr. Spieler]\n\n6.00d06 (02 Dec 07):\n - bzip2/makbz2iz.msc, bzip2/makbz2iz.wat: hide individual commands of the\n    `clean' target.  [Chr. Spieler]\n - extract.c: corrected \"extracted\" message for bzipped entries to \"bunzipped\"\n    [Steven M. Schweda]\n - unzpriv.h: removed \"suspicious\" explicit mask from Zip64 version of\n    MASK_ZUCN64 preprocessor constant.  [Steven M. Schweda]\n - extract.c - fnfilter(): added check against internal buffer overflow.\n    [Chr. Spieler]\n - unzpriv.h, fileio.c, win32/w32cfg.h, wince/wcecfg.h: repaired the MBCS\n    definition for the CLEN() macro; this macro is assumed to return a strictly\n    positive byte count.  [Kazuki Matsuda, Chr. Spieler]\n - unix/zipgrep: return the correct exit code from egrep even in cases where\n    the egrep output is further piped through sed.  [Niklas Klein]\n - vms/vms.c: corrected case of the \"__ia64\" predefined preprocessor symbol.\n    [Steven M. Schweda]\n - bzip2/descrbz2.mms: added make Info-ZIP specific VMS make script, as a\n    starting point for integrated bzip2 compilation support in a similar\n    way to other OS (Win32, Unix). (not yet working, requires more work to\n    get completed and debugged...).  [Chr. Spieler]\n - win32/makefile.bc, win32/makefile.gcc, win32/makefile.wat: completed clean\n    target functionality.  [Chr. Spieler]\n - win32, wince: added workaround to keep Visual Studio 2005 C compiler quiet.\n    [N.N.]\n - unzpriv.h, extract.c, list.c, zipinfo.c: added \"WavPack\" (supported by\n    WinZip 11+) to list of recognized compression types.  [Christian Spieler]\n - win32/nt.c: prevent calling IsValidAcl() with a NULL Acl pointer, to fix\n    false 'EA security check' failures.  [Will Menninger]\n - renamed proginfo/extra.fld into proginfo/extrafld.txt, to synchronize with\n    Zip3.  [Chr. Spieler]\n - process.c: added second try to find the EOCD64 record, to compensate for\n    (SFX-stub) bytes prepended to the archive without adjustment of the offset\n    records in the Zip file structures.  [Will Menninger, Ed Gordon]\n - fileio.c, process.c: replaced spurious use of Z_OFF_T by zoff_t.\n    [Chr. Spieler]\n - win32/win32.c - utime2VFatFileTime(): initialize the wMillisecond field of\n    the SYSTEMTIME structure to 0 to ensure deterministic time conversion.\n    [N.N.]\n - explode.c: corrected type for data stream size variables from zoff_t into\n    zusz_t.  [Chr. Spieler]\n - unix/configure, unix/Makefile: made automatic detection & compilation of\n    bzip2 support working for the 'generic' target.  [Chr. Spieler]\n\n6.00d07 (26 Dec 07):\n - fileio.c: old-style function head for fzofft().  [Steven M. Schweda]\n - acorn/makefile: updated to support bzip2 decompression (change was missed\n    for 6.00d06).  [Chr. Spieler]\n - unix/configure: added/modified cc optimization checks [Steven M. Schweda]\n - unix/unix.c: added detailed IBM C version reporting to version().\n    [Steven M. Schweda]\n - unix/unxcfg.h: use __hpux instead of __HP_cc to determine UTIMEBUF\n    configuration [Steven M. Schweda]\n - unzip.h, unzip.c: removed IZ_COMPERR runtime error code. This code was only\n    used in compile-time assertions of development code and did never get into\n    a production environment.  [Chr. Spieler]\n - vms/vms.c, vms/UNZIP_MSG.MSG, vms/unzip_def.rnh, vms/unzip_cli.help: removed\n    IZ_COMPERR support and documentation; debugging code should not be\n    mentioned in end-user documentation.  [Chr. Spieler]\n - unzpriv.h: use __hpux instead of __HP_cc to determine support of \"long long\"\n    type for HP (bundled ??) compiler.  [Steven M. Schweda]\n    >>> This change may be wrong?? \"long long\" support is a compiler feature,\n        not a runtime library feature!  [Chr. Spieler] <<<\n - VMS: added message file build to make procedures (missed change from\n    6.00d06).  [Steven M. Schweda]\n - wince/wcemain.c: added missing modifications from unz553d beta (25 Dec 06),\n    see also \"wince/wcemain.c\" changelog entry for 6.00d01.  [Chr. Spieler]\n - fileio.c - uzmbclen(): corrected return type definition.  [Chr. Spieler]\n - win32/nt.c: added some typecasts in Initialize() to get newer gcc quiet.\n    [Chr. Spieler]\n - win32/win32.c: added some superfluous variable initializations to prevent\n    gcc compiler warnings.  [Chr. Spieler]\n - bzip2/descrbz2.mms: made MMS description file work (at least on OpenVMS 8.3\n    IA64 testdrive account).  [Chr. Spieler]\n - vms/descrip_src.mms: modified bzip2 support so that it works with the\n    library created by bzip2/descrbz2.mms, using the original bzip2 1.0.4\n    sources.  [Chr. Spieler]\n\n6.00d08 (29 Dec 07):\n - bzip2/descrbz2.mms: modified compile options to create a library which is\n    binary compatible with the results of the SMS-specific deviated bzip2\n    distribution for VMS.  [Chr. Spieler]\n - bzip2/buildbz2.com: new VMS DCL build script for the bzip2 \"BZ_NO_STDIO\"\n    library used by the bzip2 support in  UnZip.  [Chr. Spieler]\n - vms/descrip.mms, vms/descrip_src.mms: changed back so that the SMS-specific\n    deviated bzip2 source package works again; added/completed support for\n    standalone bzip2-included build using bzip2/descrbz2.mms.  [Chr. Spieler]\n - vms/make_unz.com, vms/link_unz.com: removed these obsolete files, they have\n    been replaced by vms/build_unzip.com.  [Chr. Spieler]\n - vms/build_unzip.com: added support for compiling bzip2-enabled programs\n    in \"standalone\" source setup, using bzip2/buildbz2.com for creating the\n    bz2 object library.  [Chr. Spieler]\n - updated the UNICODE_SUPPORT code from Ed Gordon's work (6.00d05t, excluding\n    the win32-wide specific code).  This code is unfinished, besides other\n    issues there is a memory leak to be fixed.  [Ed Gordon, Chr. Spieler]\n - unzip.c: Added \"static\" to test_buf definition in the \"NEXTBYTE operation\n    test\" code block of main function unzip().  [SMS]\n - unzpriv.h: Added <locale.h>-related stuff from 6.00d05t (SMS), with some\n    corrections.  [Steven M. Schweda, Chr. Spieler]\n\n6.00d09 (06 Jan 08):\n - unzip.c: corrected parser code for \"negated -D\" option.  [Steven M. Schweda]\n - man/unzip.1: extended explanation of the VMS-specific differences in the\n    \"-D\" option behaviour for clarity.  [Steven M. Schweda]\n - vms/unzip_cli.cld, vms/cmdline.c: corrections and refinements applied to\n    the CLI parsing code for the new \"-D\" option.  [Steven M. Schweda]\n - vms/INSTALL.VMS: added/updated build description aspects concerning optional\n    bzip2 support.  [Steven M. Schweda]\n - vms/unzip_cli.help: clarified description of the changed and extended\n    /RESTORE qualifier.  [Steven M. Schweda]\n - vms/vms.c, vms/vms.h, vms/cmdline.c, ttyio.c: Added defines to translate all\n    used system routine names to uppercase, to allow using /NAMES=AS_IS with\n    the broken header files of older DECC distributions.  [Steven M. Schweda]\n\n6.00d10 (10 Feb 08):\n - globals.h, process.c, fileio.c: fix memory leak concerning filename_full\n    handling (UNICODE_SUPPORT code).  [Chr. Spieler]\n - ubz2err.c: renamed formal parameter \"errcode\" into \"bzerrcode\" to work\n    around a bug in MS Visual C++ 9.0 (2008).  [Chr. Spieler]\n - VMS: small cleanups to CLI code.  [Steven Schweda, Chr. Spieler]\n - vms/vmscfg.h: added missing cma$tis_errno_get_addr uppercase define for\n    broken compiler distributions.  [Steven Schweda, Chr. Spieler]\n - vms/descrip_mkdeps.com: Added CLEAN and CLEAN_ALL targets.  [Steven Schweda]\n - win32, windll: added MS VC++ 8.0 project files.  [Chr. Spieler]\n - win32/Makefile: removed dependency on ntwin32.mak, for better compatibility\n    with VC++ 8.0 Express Edition.  [Chr. Spieler]\n - api.c: moved <setjmp.h> include down behind \"unzip.h\" include to shut up\n    \"depreciation\" warnings with VC++ 8.0 and newer.  [Chr. Spieler]\n - windll/struct.h: added D_flag support to option structure.  [Chr. Spieler]\n - windll/vb/vbunzip.bas: corrected UZDLLPAss callback function interface,\n    adapted to recent DLL interface changes.  [Johnny Lee, Chr. Spieler]\n - windll: removed \"DESCRIPTION\" clause from all module definition files;\n    newest VC++ version does no longer tolerate it.  [Chr. Spieler]\n - unzip.h: enable H_flag and U_flag for UNIX, VMS, WIN32 (those systems that\n    are currently supposed to support UTF8 names); unzip.h must not depend on\n    internal configuration settings like UNICODE_SUPPORT.  [Chr. Spieler]\n\n6.00d11 (16 Feb 08):\n - vms/cmdline.c: canceled name-change for local variable 'restore_date'\n    (was incomplete in 6.00d10 and broke compilation).  [Chr. Spieler]\n - unzpriv.h: removed \"fixed\" allocation of space for the two string\n    delimiters from the definition of type slinkentry. [Steven M. Schweda]\n - unix/unix.c - set_symlnk_attribs(): modified usage of typecasts to remove\n    some compiler warnings.  [Steven M. Schweda]\n - aosvs, atari, atheos, beos, unix, vms - close_outfile(): Increased the\n    allocation size for the slnk_entry structure by 2 for the two '\\0'\n    end-of-string markers.  [Chr. Spieler]\n - unix/Makefile: modified bzip2 lib target to be only applicable to the\n    bzip2 subdir of the UnZip distribution.  [Chr. Spieler]\n - unix/configure: extended bzip2 support check from Zip's configure to better\n    support \"externally\" supplied bzip2 libraries.  [St. Schweda, Chr. Spieler]\n - vms/descrip_src.mms, bzip2/descrbz2.mms: cleaned up VMS MMS support for\n    integrated build of bzip2-enabled UnZip executables.  [Chr. Spieler]\n - msdos, unix, vms, win32: at request from SMS, changed all occurrences of\n    \"DIR_BZ2LIB\" symbol in build scripts for the directory of the bzip2 library\n    sources (and often also binaries) into \"IZ_BZIP2\", for synchronization\n    with Zip.  [Chr. Spieler]\n\n6.00d (17 Feb 08):\n - win32/Makefile: fixed configuration variations of bzip2 support when using\n    non-standard build options regarding rtl linking; added documentation\n    section for the supported build variant flags on the nmake command line.\n    [Chr. Spieler]\n\n6.00e01 (17 Feb 08):\n - unzpriv.h: re-added \"fixed\" allocation of space for the first of two string\n    delimiters from the definition of type slinkentry, the \"buf[]\" structure\n    member is not accepted by some older compilers. [Chr. Spieler]\n - aosvs, atari, atheos, beos, unix, vms - close_outfile(): Reduced the\n    allocation size for the slnk_entry structure by 1, one of the two '\\0'\n    end-of-string markers is again part of the structure.  [Chr. Spieler]\n - unix/configure: export CC and IZ_BZIP2 symbols to flags, to feed their\n    current settings to the child make process without having to use special\n    make command qualifiers.  [Steven M. Schweda, Chr. Spieler]\n\n6.00e02 (08 Mar 08):\n - unix/unix.c - close_outfile(): added missing semicolon in the SYMLINKS code\n    for the non-SET_SYMLINK_ATTRIBS case.  [Steven M. Schweda]\n - unzip.c: removed extra \"credit to Myles Bennet\" note from startup screen\n    for space considerations; added credit note to README and referenced\n    Myles Bennet in proginfo/CONTRIBS.  [Chr. Spieler]\n - vms/vms.c: fixed dir separator find logic in vms_path_fixdown() for cases\n    where directory name contains a '.' or '[' itself.  [Steven M. Schweda]\n - crc32.h: replaced explicit inclusion of zip.h by a note that this header\n    should be read after zip.h resp. unzip.h.  [Steven M. Schweda, C. Spieler]\n - unix/configure, unix/Makefile: cleaned up auto-configured build procedure.\n    * pass the \"configure\"-selected C optimizations to the bzip2 build process.\n    * clean only affects the unzip-specific bzip2 subdirectory.\n    * let make display the bzip2 clean subprocess call.\n    [Steven M. Schweda]\n - unzip.c, unzip.h, zipinfo.c, fileio.c - UNICODE_SUPPORT, revised the\n    options to control UTF-8 handling:\n    * removed the -H option\n    * modified -U option syntax: -U forces to escape all non-ASCII UTF-8 chars,\n      -UU must be used now to entirely disable UTF-8 support.\n    [Chr. Spieler]\n - windll/windll.{c|txt}: added U_flag to option stucture.  [Chr. Spieler]\n - man/unzip.1, man/zipinfo.1: added description of the new UTF-8 related\n    syntax for the -U option.  [Chr. Spieler]\n - win32/w32cfg.h, wince/wcecfg.h: enabled UNICODE_SUPPORT by default.\n    [Chr. Spieler]\n - win32/Makefile: adapted to modified UNICODE_SUPPORT default.  [Chr. Spieler]\n - wince/intrface.cpp - close_outfile(): moved local (wide string) copy of\n    filename outside of conditional \"set timestamps\" block.  [Chr. Spieler]\n - unzpriv.h: do never include <wchar.h> here for the wince port (_WIN32_WCE or\n    POCKET_UNZIP), this must be handled elsewhere for C++.  [Chr. Spieler]\n - unzip.c: removed the -U option description from the introductory screen for\n    WIN32 because of lacking space. Maybe, these \"debugging\" options should not\n    be shown there at all.  [Chr. Spieler]\n\n6.00e03 (29 Mar 08):\n - unix/configure: corrected detection of ANSI C vs. bundled C compiler on\n    HP-UX.  [Steven M. Schweda]\n - VMS, unzip.c: help screen extended to show correct \"-D\" semantics for the\n    special VMS defaults.  [Steven M. Schweda]\n - unix/Makefile: added \"generic_gcc\" target, using auto-configuration with\n    GNU compiler.  [Steven M. Schweda]\n - unzip.c: renamed error message constant for clarity.  [Chr. Spieler]\n - unshrink.c: revision to fix long-standing decompression bug, added boundary\n    checks to detect invalid compressed data.  [Santiago Vila, Chr. Spieler]\n - extract.c: added error message handling for \"invalid data\" errors from\n    unshrink().  [Chr. Spieler]\n - process.c, unzpriv.h: disabled compilation of unused UNICODE_SUPPORT helper\n    function.  [Chr. Spieler]\n - process.c, win32/win32.c: added special win32-only version of the\n    wide_to_local_string() helper function to work around \"ANSI vs. OEM\"\n    codepage problems with non-Microsoft C-runtime libraries.  [Chr. Spieler]\n - zipinfo.c - zipinfo(): corrected \"back at end-of-cdir\" check (synchronized\n    it with the corresponding list_files() code).  [Chr. Spieler]\n - fileio.c - do_string(): closed UNICODE_SUPPORT related memory leaks\n    (free allocated utf8 buffers when no longer used).  [Chr. Spieler]\n - vms/vms.c - set_direc_attribs(): do not restore any size info from the\n    (PK-style) extra field record attributes settings.  The new directory\n    created during extraction may contain fewer (restored) entries than the\n    original source folder, so that the old non-matching size data would\n    result in corrupted interal directory structures.  [Steven M. Schweda]\n\n6.00e04 (27 Apr 08):\n - vms/vms.c - set_direc_attribs(): fixed NAM[L] initialization for the\n    \"normal\" non-VMS-attributes case.  [Steven M. Schweda]\n - vms/NOTES.TXT updated (version copied from zip30h05).  [Steven M. Schweda]\n - unzip.c, vms/NOTES.TXT: added SYMLINKS to the special compilation options\n    reported by show_version_info(); updated Symbolic Links section in\n    NOTES.TXT.  [Chr. Spieler]\n - INSTALL: added documentation for the new UNICODE_SUPPORT related options.\n    [Chr. Spieler]\n - README: added anouncement of the new UTF-8 coded entry names support.\n    [Chr. Spieler]\n - fileio.c, process.c, unzip.c, globals.h, unzpriv.h, win32/w32cfg.h,\n    wince/wcecfg.h : revised the UNICODE_SUPPORT code, added direct support for\n    UTF-8 being the native MBCS char encoding, allowed separate activation of\n    the \"UTF-8 is native character coding\" and the \"translate UTF-8 <==> native\n    extended-ASCII via Unicoded wchar_t\" support methods.  [Chr. Spieler]\n - unix/configure, unix/Makefile: extended configure script to support\n    automatic selection of UNICODE_SUPPORT support on capable systems,\n    completed configuration support for the linking step.  [Chr. Spieler]\n - unix/unxcfg.h: changed interdependency rules of LARGE_FILE_SUPPORT and\n    ZIP64_SUPPORT to prevent unsupported symbol combinations.  [Chr. Spieler]\n - man/unzip.1: extended description of -U option to mention the #Lxxxxxx\n    escape format for characters beyond the basic unicode page.  [Chr. Spieler]\n - proginfo/extrafld.txt: updated wording and line wrapping of Info-ZIP\n    Unicode extra fields.  [Chr. Spieler]\n\n6.00e05 (09 Sep 08):\n - unix/unix.c - version(): added OS info support for Mac OS X (including a\n    note for the recognized CPU architecture).  [Steven M. Schweda]\n - unix/configure: check for Mac OS X special linker options is only executed\n    on systems that have been identified as Mac OS X.  [Steven M. Schweda]\n - unix/Makefile: moved \"solaris\" targets into new \"autoconfig generic\" group\n    of machine target aliases.  [Steven M. Schweda, Chr. Spieler]\n - extract.c, fileio.c: use \"sizeof(G.answerbuf)\" as length argument in fgets()\n    calls, for better robustness and \"in-code\" documentation.  [Chr. Spieler]\n - extract.c - extract_or_test_entrylist(): fixed handling of \\n in response\n    to \"overwrite (y/n/r)\" prompt.  [Steven M. Schweda, Chr. Spieler]\n - extract.c, special version of \"replace file\" prompt for VMS to take into\n    account that VMS normally created a new version instead of overwriting\n    an existing file.  [Steven M. Schweda]\n - unzpriv.h: for VMS, undefine the PATH_MAX definition provided by <limits.h>,\n    because it does not take into account long name support of ODS-5 volumes.\n    [Steven M. Schweda]\n - VMS: added zlib.h and infback9.h jacket headers for support of using zlib\n    as inflate decompression code; revised build procedures for zlib support\n    (build_unzip.com, descrip.mms, descrip_src.mms).  [Steven M. Schweda]\n - inflate.c: corrected condition when to include \"infback9.h\" for Deflate64\n    support with zlib 1.2.x.  [Chr. Spieler]\n - extract.c: standardized wording of error messages in SET_DIR_ATTRIBS code.\n    [Steven M. Schweda]\n - vms/vms.c - set_direc_attribs(): ensure that the FAB block used is properly\n    initialized.  [Steven M. Schweda]\n - aosvs, atari, atheos, beos, unix - mapname(): for all \"unix-like\" ports, the\n    reserved file names \".\" and \"..\" are mapped to \"_\" resp. \"__\".\n    [Steven M. Schweda, Chr. Spieler]\n - list.c - changed listing layout to emit four-digit years for file\n    date-time-stamps.  [Ed Gordon, Chr. Spieler]\n - process.c - find_ecrec(): fixed zipfile comment handling within the Zip64-\n    compatible end-of-central-dir records scanning, to take into account that\n    the file pointer is no longer at the zipfile end when the eocdrec scanning\n    has finished.  [Chr. Spieler]\n - process.c, zipinfo.c: revised and reorganized zipinfo log header output;\n    the zip archive comment has to be reported before all of the eocdir info\n    could be collected.  [Chr. Spieler]\n - man/unzipsfx.1 - Debian patches 4461_002 and 5293_009 fixing text errors;\n    correct spelling of similarly and additional per debian patch; correct\n     wrong formatting command \\P to \\fP.  [sanvila]\n - vms/build_unzip.com: fixed integrated bzlib build support.  [Chr. Spieler]\n\n6.00e06 (13 Sep 08):\n - unix/unix.c - set_symlnk_attribs(): removed erronous surplus line with only\n    \"if\" on it. [Steven M. Schweda]\n - vms/descrip_deps.mms: restored correct file which was accidentally\n    overwritten by vms/descrip_src.mms.  [Steven M. Schweda]\n - vms/build_unzip.com: optimized the distinction between \"compile destination\n    subdir\" for integrated BZIP2 compilation (should distinguish between the\n    different compilers supported for VAX) and \"external library dir\" for\n    user-supplied BZIP2 (and ZLIB) libraries (user-supplied library is expected\n    to work with any supported compiler on VAX, so no dependency on the\n    specific compiler used).  [Steven M. Schweda]\n - unzip.c: replaced tab characters in output messages by appropiate number of\n    spaces (assuming standard tab spacing of 8 chars), to prevent mis-formatted\n    output on terminals with non-standard tabstop settings.  [S. M. Schweda]\n - unix/unix.c\n    * set_symlnk_attribs(): fixed uid/gid size check before calling lchown();\n    * set_direc_attribs(): repared wrongly inserted patch and fixed uid/gid\n      size check before calling chown().  [Chr. Spieler]\n - vms/vms.c: fixed user-query code for existing files on VMS when extracting\n    in \"-V\" mode (retaining version numbers); fixed some problems with exotic\n    extended ODS5 file names, and files named \".\".  [Steven M. Schweda]\n - vms/cmdline.c, vms/unz_cli.cld: extended CLI to support the new extended\n    meaning of the -o flag (-oo => \"overwrite ALL existing\" when retaining\n    version numbers (\"-V\") and extracting archive members with attached version\n    number (new /EXISTING option).  [Steven M. Schweda]\n - extract.c - extract_or_test_entrylist(): added code to skip the generic user\n    query \"overwrite (y/n/r)?\" when extracting an entry with attached version\n    number in \"-V\" (keep version number) mode.  [Steven M. Schweda, C. Spieler]\n - vms/unzip_cli.help, vms/unzip_hlp.rnh: updated documentation to reflect the\n    UI extension to handle VMS-specific \"overwrite or new version\" settings.\n    [Steven M. Schweda]\n - unzip.c: added VMS specific -n and -o (-oo) option description sections\n    to online help screen definitions.  [Steven M. Schweda]\n - vms/cmdline.c: corrected some small formatting issues in online help output.\n    [Chr. Spieler]\n - vms/unzip_cli.help, vms/unzip_hlp.rnh: corrected a few typos and updated the\n    help screen for the \"unix-style\" commands in the CLI help.  [Chr. Spieler]\n - vms/vms.c, extract.c, unzpriv.h: fixed the the error handling of the VMS-\n    specific \"newver/overwrite/skip\" query by extending the return code range\n    of open_output() for VMS, without any new global data.  [Chr. Spieler]\n\n6.00e (04 Jan 09):\n - fileio.c: changed tmpstat from struct stat to z_stat.  [EG]\n - unzip.c: expanded extended help to include unzip and zipinfo options.  [EG]\n - man/unzip.1: updated multi-part archive information; minor additions\n    to authors activities list.  [EG]\n - fileio.c: added strerror(errno) output to CannotCreateFile message.  [SMS]\n - unix/unix.c: add more detailed error message using strerror() when a\n    file error occurs.  [SMS]\n - unix/zipgrep - add additional information to top.  Clean up some lines and\n    add commments.  Added code to handle backslashes in archive file names,\n    and shell-special characters in the pattern. Changed to use \"sed\" for all\n    escaping of shell-special characters. Tried to get the exit status to\n    follow the status of egrep in the complex (default) situation, using only\n    standard Bourne shell features, and to exit early if egrep returns\n    status 2 (error).  [SMS]\n - vms/unzip_cli.help - VMS help updates.  [SMS]\n - vms/unzip_def.rnh - synchronized option description with unzip_cli.help.\n    [Chr. Spieler]\n - fileio.c: extend backup number range from 65535 to 99999 on 32-bit systems;\n    fixed limit detection on 16-bit systems.  [Chr. Spieler]\n - zipinfo.c: changed date layout of \"short\" (one-line) zipinfo modes to always\n    use ISO-style YMD order.  [Chr. Spieler]\n - unix/configure: added a simple compiler test to check for a working C\n    compiler setup.  [Steven M. Schweda]\n - cmsmvs/vmmvs.h: removed __EBCDIC preprocessor symbol definition (not used\n    anywhere in UnZip, breaks compilation on Z-OS).  [\"Lutz\", Chr. Spieler]\n - unix/makefile - moved -L link option earlier in unzip$E rule.  [Lutz]\n - unzip.c - Remove \"s\" from \"permits\" in SYMLINKS feature message.  [SMS]\n - vms/vms.c: simplified the scheme to escape non-last dots, for compatibility\n    with modifications in Zip 3.1.  [SMS]\n - vms/vms.c, vms/vms.h, function create_qio_output(): revised NMCTL flag\n    handling (\"overwrite or create-new\" code) to be VAXC compatible.  [SMS]\n - extract.c - extract_or_test_entrylist(): removed '\\n in middle of WINDLL\n    \"file exists ... skipping\" message to get it displayed on one line.  [EG]\n - man/unzip.1, INSTALL: updated/corrected documentation for the UNIXBACKUP\n    feature and the description of its -B qualifier.  [Chr. Spieler]\n - proginfo/ziplimits.txt: updated discussion of program implementation limits\n    to the state of \"released\" Zip 3.0 and UnZip 6.0.  [EG, Chr. Spieler]\n - README, Bugs, ToDo: updated and syncronized documentation for release\n    candidate.  [Chr. Spieler]\n - windll/structs.h: added structure version id field at the \"top\" of the\n    \"DCL\" options struct.  [EG]\n - windll/structs.h: added UZ_DCL_STRUCTVER preprocessor symbol, holding the\n    currently valid version id of the DCL structure definition.  [Chr. Spieler]\n - windll/windll.c - Wiz_SetOpts(): exit function if version id of passed in\n    \"DCL\" structure is not equal to the expected setting.  [EG, Chr. Spieler]\n - windll/unexampl.c: synchronized with recent WinDLL option structure\n    addition.  [EG, Chr. Spieler]\n - windll/vc?/exampl/c_dll_ex.[dsp|vcproj]: new Visual Studio project files\n    for building the WinDLL C usage example uzexampl.exe.  [EG, Chr. Spieler]\n - windll/vb/vbunzip.bas: changed DLL interface to use UZxxx_I32 variants of\n    callback functions that split 64-bit values into high and low part 32-bit\n    integers that can be handled by VB(A)5/6.  Inside the VB code, low and\n    high parts are added up in Currency type variables. Converted \\ to / in\n    duplicate file message.  Fixed MsgBox flags concatenation.  Added support\n    for new OverwriteAll checkbox.  [EG]\n - windll/vb/vbunzip.frm: added OverwriteAll checkbox, added resizing to\n    txtMsgOut output box.  [EG]\n - windll/vb/vbunzip.frm, windll/vb/vbunzip.bas: cleaned up and completed the\n    recent modifications, resynchronized with WinDLL interface with UnZip 6.0\n    master source, removed all modification incompatible with VB5, fixed the\n    UZDLLServ_I32() callback calling interface, used Double instead of\n    Currency as Int64 summation type to prevent potential numeric overflow\n    issues.  [Chr. Spieler]\n\n6.00f (11 Jan 09):\n - INSTALL: added notes on the difference between \"old\" Macintosh OS and\n    current Apple Mac OS/X, which is supported as a BSD Unix port .  [EG]\n - unzip.c - help_extended(): added some documentation about funzip and\n    unzipsfx stub.  [EG]\n - windll/csharp/: updated C# example to match the current Zip64-compatible\n    WinDLL API, revised string parameter marshalling, initialized/resetted\n    job statistic counters, added OverwriteAll checkbox.  [Chr. Spieler]\n - win32/Makefile: the DLL example frontend is now compiled with the same\n    runtime library settings as the DLL binary.  [Chr. Spieler]\n - LICENSE: updated to version 2009-Jan-2, which removes the requirement to\n    provide the LICENSE in documentation with distribution of binaries when\n    the redistributed programs support display of the LICENSE by some command\n    line option.  [EG]\n - vms/vms.h, vms/vms.c: moved \"lowercase to uppercase mapping\" define of\n    sys$setdfprot from vms.c into vms.h in front of the starlet.h include,\n    where all the other name case mappings are located.  [Steven M. Schweda]\n - vms/vms.c: made the declaration of sys$setdfprot() always active when\n    the SETDFPROT symbol is defined.  [Chr. Spieler]\n - unix/unix.c: added strerror(errno) output to various \"Cannot...\" I/O error\n    messages (in checkdir(), close_outfile(), set_symlnk_attribs()).\n    [Steven M. Schweda, Chr. Spieler]\n - fileio.c - open_outfile(): added strerror(errno) output to the error\n    messages \"cannot rename ...\" and \"cannot delete ...\".  [Chr. Spieler]\n - fileio.c - do_string(): corrected string length passed to win_fprintf()\n    (comment string may get shortened by CRLF->LF translation). [Chr. Spieler]\n - beos/beos.c, beos/beocfg.h, aosvs/aosvs.c, win32/win32.c: extended various\n    \"Cannot...\" I/O error messages with strerror(errno) output, to synchronize\n    code with current state of the Unix port.  [Chr. Spieler]\n - unzip.c, unzpriv.h, unix/configure: added better check for UTF-8 codeset\n    using nl_langinfo() function, as suggested on the sourceforge.net forum;\n    added nl_langinfo() to the \"function existence\" checks in the configure\n    script.  [Chr. Spieler]\n - wince/intrface.cpp: added missing wide_to_local_string() function from\n    win32.c (is [currently] needed in process.c).  [Chr. Spieler]\n\n6.00g01 (18 Jan 09):\n - extract.c, windll/structs.h, windll/windll.txt: added a bufsize parameter\n    to the \"replace()\" callback function, updated UZ_DCL_STRUCTVER setting to\n    0x600.  [Chr. Spieler]\n - windll/uzexampl.c, windll/csharp/Unzip.cs, windll/vb/vbunzip.bas,\n   windll/guisfx/sfxwiz.c, wince/intrface.cpp: adapted frontend code to the\n    \"replace()\" callback function signature change; updated DCL.StructVersID\n    setting to reflect the change in the DLL code; added check against password\n    buffer overflow (not in uzexampl.c).  [Chr. Spieler]\n - windll/vb/vbunzip.frm: removed obsolete comment.  [EG]\n - windll/csharp/ReadMeCS.txt: added note on problem with Visual Studio 8.0\n    and 9.0 when used with unzip32.dll that was linked against the Visual\n    Studio version of the MS C runtime dll.  [Chr. Spieler]\n - unix/Makefile: consistent use of \"$E\" for executable filename extension;\n    fixed dependency of binary builds on system specific config header; added\n    dependency of autoconfigured \"generic\" builds on the configure result.\n    [Chr. Spieler]\n - unzip.c: added hint to \"unzip -hh\" extended help display to the short help\n    screen.  [Chr. Spieler]\n - unzip.c - help_extended(): removed superfluous \"]\", corrected availability\n    info for the \"-B\" option.  [EG, Chr. Spieler]\n - man/unzip.1, unzip.c, vms/unzip_def.rnh, vms/unzip_cli.help - modified\n    description of -X option for VMS to emphasize that this option controls\n    restoration of ACL protection info, whereas the standard S/O/G/W access\n    restrictions get always restored.  [SMS, H. Goatley, Chr. Spieler]\n - unzip.h, api.c, unzipstb.c, unzvers.h, windll/windll.txt,\n   windll/vb/vbunzip.bas:\n    revised and extended the \"version info retrieve\" function calls, added\n    version identifier for the \"last incompatible API change\", fixed version\n    structure size handling, updated API documentation.  [Chr. Spieler]\n - windll/windll.c - UnzipAllocMemory(): fixed operator precedence bug by\n    adding explicit parenteses.  [Chr. Spieler]\n - win32/Makefile.wat: added missing rule for crc32f.obj.  [Chr. Spieler]\n - unzip.c - uz_opts(): corrected parameter list for call of help_extended().\n    [Chr. Spieler]\n - unix/Makefile: adapted linux_shlib and linux_shlibz targets to work with\n    the changed organisation of the assembler CRC code.  [Chr. Spieler]\n\n6.00g02 (25 Jan 09):\n - History.600, unzpriv.h, unix/unix.c: corrected/unified spelling of\n    \"dependent\" and \"dependence\".  [Steven M. Schweda]\n - api.c - UzpVersion2(): added forgotten setting of dllapimin version info\n    (similar to UzpVersion()).  [Chr. Spieler]\n - unzipstb.c, windll/uzexampl.c, windll/uzexampl.h: extended DLL version\n    display to report the new \"DLL API\" version info; added compatibility\n    checks for version of loaded dll, using the recently added additional\n    API version info.  [Chr. Spieler]\n - windll/uzexampl.c: changed program return values to follow common usage\n    (0 for no error, -1 for fatal abort, unzipdll return code otherwise).\n    [Chr. Spieler]\n - windll/vb/VBReadMe.txt, windll/vb/vbunzip.bas: revised and extended\n    documentation of unzip32.dll search process flow, added warning note\n    explaining the unexpected \"dll not found\" errors when running the VB code\n    inside the VB IDE.  [Chr. Spieler]\n - windll/vb/vbunzip.bas: added version/api compatibility checks for the\n    loaded unzip32.dll, aborting the program in case of any detected\n    incompatibility.  [Chr. Spieler]\n\n6.00g03 (10 Feb 09):\n - README, History.600: documented support for new 32-bit UID/GID extra field\n    on Unix.  [Ed Gordon, Chr. Spieler]\n - unzip.h: added \"old lib swprintf\" compatibility clause for Pocket-UnZip\n    (WinCE) to support current Visual Studio versions 8 and 9. [Chr. Spieler]\n - wince/wcecfg.h: switched off UNIX_BACKUP for WinCE (rename() function not\n    available on Windows CE); moved the (none-WCE) configuration setup for\n    Zip64 support to the end (behind all header includes).  [Chr. Spieler]\n - wince/wince.h: added guard against redefinition of isalpha() macro.\n    [Chr. Spieler]\n - wince/intrface.cpp - win_fprintf(): reordered local loop counter variable\n    declaration to achieve compatibility with standard C++ (without breaking\n    the non-standard MS VC++ 6.0 variant).  [Chr. Spieler]\n - extract.c, list.c, process.c, zipinfo.c: replaced strncmp() by memcmp()\n    when comparing against \"binary\" signatures.  [Chr. Spieler]\n - process.c - wide_to_escape_string(): fixed a \"write to unallocated memory\"\n    bug.  [Chr. Spieler]\n\n6.00g04 (16 Feb 09):\n - unzpriv.h: mapped zfseeko and zftello to C rtl supplied functions for MS\n    C runtime of VC 8.0 or newer.  [Chr. Spieler]\n - win32/win32i64.c: revised zfseeko() code to correctly clear the eof state\n    (and for \"MSVC 6.0 or newer\" rtl environments: manipulate internal flag\n    to prevent clearing a ferror() state).  [Chr. Spieler]\n - windll/vc5/, windll/vc6/, windll/vc8/: added \"link against static C rtl\"\n    configurations to the unzip32 dll and c_example projects.  [Chr. Spieler]\n - win32/vc8/, windll/vc8/: removed \"UpdateFromVC600\" property sheet settings,\n    they are not needed.  [Chr. Spieler]\n - windll/guisfx/sfxwiz.c: added compatiblity preprocessor switches to shut up\n    MS VC 8 (and newer) complaining about depreciated standard C functions.\n    [Chr. Spieler]\n - INSTALL, windll/Contents: added notes about different runtime configurations\n    (linking against C rtl dll vs. static C rtl lib) when building the UnZip\n    DLL.  [Chr. Spieler]\n\n6.00g (28 Feb 09):\n - unzip.c: cleaned up the UTF-8 check according to the code found in the\n    latest Zip 3.1 beta, removed the \"switch to UTF-8 codeset\" code because\n    it proved to not work as expected.  [Ed Gordon, Chr. Spieler]\n - win32/w32cfg.h: use rtl-provided MBCS functions for MinGW32 when compiled\n    and linked against msvcrt.dll.  [Chr. Spieler]\n - extract.c - fnfilter(): added \"enhanced\" non-printable charcode filtering\n    when a locale-aware isprint() implementation is available (controlled by\n    the preprocessor symbol HAVE_WORKING_ISPRINT).  [Chr. Spieler]\n - win32: enabled \"enhanced\" fnfilter() filtering for compiler environments\n    using MSVC 6.0 (or newer) runtime, and for Borland C.  [Chr. Spieler]\n - vms: enabled \"enhanced\" fnfilter() filtering using isprint(), may get\n   disabled by defining the NO_WORKING_ISPRINT symbol.  [Chr. Spieler]\n - unix/unxcfg.h: enabled \"enhanced\" fnfilter() filtering when setlocale() is\n    available (NO_SETLOCALE is not defined).  [Chr. Spieler]\n - unix/configure: added NO_SETLOCALE define when setlocale() check fails.\n    [Chr. Spieler]\n - INSTALL: added documentation of NO_SETLOCALE and HAVE_WORKING_ISPRINT resp.\n    NO_WORKING_ISPRINT symbols.  [Chr. Spieler]\n - general: unified spelling of \"wildcard\".  [Chr. Spieler]\n\n6.00h01 (09 Mar 09):\n - vms/vms.c: added missing case-translation define for sys$getdvi(), for\n    support of /NAMES=AS_IS with older DECC distributions.  [Steven M. Schweda]\n - vms/build_unzip.com, vms/descrip.mms, vms/descrip_src.mms: resolved a\n    /NAME=AS_IS case issue by changing the linking command for bzip2-enabled\n    builds to read the unzip code library twice (before and after the bzip2\n    object library) to resolve the bzip2 error callback, instead of explicitely\n    loading the callback function.  [Steven M. Schweda]\n - vms/NOTES.TXT: cleaned up wording of the Symbolic Links section. [SMS]\n - extract.c, fileio.c, process.c, unzpriv.h: fixed recognition of \"native\n    UTF-8\" general purpose flag bit 11 when processing local header, added\n    check against mismatching central vs. local GPFlag bit 11 (not for SFX)\n    with warning display (suppressible by -q command qualifier).  [C. Spieler]\n\n6.00h02 (16 Apr 09):\n - extract.c: fixed evaluation sequence of check expression by adding correct\n    pairs of parentheses.  [EG, SMS]\n - unix/configure: added working check for lchmod.  [SMS]\n - unzip.c: added compile option display for MBCS support.  [Chr. Spieler]\n - unzpriv.h, unix/unxcfg.h, win32/w32cfg.h: the new preprocessor symbol\n    NO_MBCS allows to explicitely disable MBCS support.  [Chr. Spieler]\n - INSTALL: documented _MBCS and NO_MBCS preprocessor symbols.  [Chr. Spieler]\n - unix/configure: added checks for MBCS support.  [Chr. Spieler]\n\n6.00h03 (17 Apr 09):\n - unzpriv.h: added missing OF() macro to uzmbclen() prototype.  [SMS]\n - man/*.1: changed revision info to intended release date.  [Chr. Spieler]\n\n6.00 (20 Apr 09):\n - unzpriv.h, fileio.c: removed superfluous \"define indirection\" zlstat,\n    link attributes do never ever need 64-bit treatment.  [Chr. Spieler]\n - man/unzip.1, ToDo: added remark to DECRYPTION section on still missing\n    support for UTF-8 encoded passwords on systems like Windows, that are\n    Unicode-aware without using UTF-8 as native character encoding; added\n    ToDo note about fixing UTF-8 password handling in the next release.\n    [Chr. Spieler]\n - updated release dates (History.600, README, unzvers.h, all man pages),\n    changed all relevant files from BETA into release state.  [Chr. Spieler]\n\n==================\n\nThese changes occurred in beta versions 6.00a to 6.00.  This list may have\nleft out some bugfixes and even some features...void where prohibited, your\nmileage may vary, etc., etc.\n"
  },
  {
    "path": "deps/infozip/unzip60/INSTALL",
    "content": "__________________________________________________________________________\n\n  This is the Info-ZIP file INSTALL (for UnZip), last updated 16 Apr 2009.\n__________________________________________________________________________\n\n  Yes, this is a rather long file, but don't be intimidated:  much of its\n  length is due to coverage of multiple operating systems and of optional\n  customization features, large portions of which may be skipped.\n__________________________________________________________________________\n\n\n\nTo compile UnZip, UnZipSFX and/or fUnZip (quick-start instructions):\n========================================\n\n(1) Unpack everything into a work directory somewhere, and make sure you're\n    in the main UnZip directory (the one with this file in it).\n    * (See note below concerning line termination format used in the source\n       distribution)\n\n(2) Copy the appropriate makefile into the current directory, except under\n    OS/2.\n\n(3) Run your \"make\" utility on the makefile (e.g., \"nmake -f makefile.msc\").\n\n(4) Try out your new UnZip the way you would any new utility:  read the\n    docs first.\n\n    Ah ha ha ha!!  Oh, that kills me.  But seriously...  For VMS, see the\n    Install section below or [.vms]README. for details.\n\n    For DOS and other OSes without explicit timezone support (i.e., everybody\n    but Unix, Windows 95 and NT), make sure the \"TZ\" environment variable is\n    set to a valid and reasonable value; see your compiler docs for details.\n\n(*) The unzip sources as well as other Info-ZIP source archives are packaged\n    in Unix format. All text files use single LF (Ascii 0x0a) characters as\n    line terminators.  On systems that use different conventions for plain text\n    files (e.g.:DOS,Win9x,WinNT,OS/2 -> combined CR+LF; MacOS -> single CR),\n    some utilities (editors, compilers, etc.) may not accept source files\n    with LF line terminators.\n    For these systems, we recommend to use Info-ZIP's UnZip utility for\n    extraction of our distribution archives, applying the command option\n    \"-a\" (= translate text files to native format) in the extraction command.\n    In case this procedure is not applicable, an appropiate third-party\n    conversion utility may be used to achieve the desired line termination\n    style (examples: \"flip\", available for Unix, DOS, OS/2; or \"tr\" on Unix).\n\n\nTo compile UnZip, UnZipSFX and/or fUnZip (detailed instructions):\n========================================\n\n(1) Unpack *.c and *.h (the actual source files), preserving the directory\n    structure (e.g., ./unix/unix.c).  The sole exception is TOPS-20, where\n    tops20/* should be unpacked into the current directory, but TOPS-20\n    is no longer fully supported anyway.\n\n    As of UnZip 5.41, full decryption support has been integrated in the\n    UnZip source distribution.  If you wish to compile binaries without\n    decryption support, you must define the preprocessor flag NO_CRYPT.\n    For many environments, you may add this flag to the custom compilation\n    flags supplied by the environment variable LOCAL_UNZIP.  For more\n    details, see the make procedures and accompanied documentation for your\n    particular target OS.\n\n    As of UnZip 5.53, support for the bzip2 compression algorithm has been\n    added to UnZip. However, this support requires the original sources of\n    the bzip2 compression library which have to be aquired separately;\n    see \"http://www.bzip.org/\" for further reference.\n\n\n(2) Choose the appropriate makefile based on the description in the Con-\n    tents file for your OS (that is, there's only one for Unix or OS/2, but\n    MS-DOS and several other OSes have several, depending on the compiler).\n    Copy it into the current directory and rename if necessary or desired.\n    (Some makefiles can be invoked in place; see (5) below.)\n\n    Don't be afraid to read the makefile!  Many options will be explained only\n    in the comments contained therein.  The defaults may not quite suit your\n    system.  When making changes, remember that some \"make\" utilities expect\n    tabs as part of the makefile syntax.  Failure with cryptic error messages\n    will result if your editor quietly replaces those tabs with spaces.\n\n    Special point of confusion:  some non-MSDOS makefiles contain MS-DOS\n    targets (useful for cross-compilations). An example is the OS/2 makefile\n    os2/makefile.os2 that contains the gccdos target for DOS emx+gcc and\n    some more DOS related targets for Watcom C and MSC. But since version 5.3,\n    the msdos subdirectory contains makefiles for all supported DOS compilers.\n    [The old djgpp, djgpp1 and gcc_dos targets in unix/Makefile have been\n    removed in 5.3; use msdos/makefile.dj* instead.]\n\n    Extra-special point of confusion:  makefile.os2 expects to remain in\n    the os2 subdirectory.  Invoke it via \"nmake -f os2/makefile.os2 gcc\",\n    for example.\n\n\n(3) If you want a non-standard version of UnZip, define one or more of the\n    following optional macros, either by adding them to the LOCAL_UNZIP\n    environment variable or by editing your makefile as appropriate.  The\n    syntax differs from compiler to compiler, but macros are often defined\n    via \"-DMACRO_NAME\" or similar (for one called MACRO_NAME).  Note that\n    some of these may not be fully supported in future releases (or even\n    in the current release).  Note also that very short command lines in\n    MS-DOS (128 characters) may place severe limits on how many of these\n    can be used; if need be, the definitions can be placed at the top of\n    unzip.h instead (it is included in all source files)--for example,\n    \"#define MACRO_NAME\", one macro per line.\n\n      DOSWILD   (MS-DOS only)\n        Treat trailing \"*.*\" like Unix \"*\" (i.e., matches anything); treat\n        trailing \"*.\" as match for files without a dot (i.e., matches any-\n        thing, as long as no dots in name).  Special treatment only occurs\n        if patterns are at end of arguments; i.e., \"a*.*\" matches all files\n        starting with \"a\", but \"*.*c\" matches all files ending in \"c\" *only*\n        if they have a dot somewhere before the \"c\".  [The default method of\n        specifying files without a dot would be \"* -x *.*\", making use of\n        UnZip's exclude-files option.]  The matching is actually the same as\n        Unix, if you assume that undotted filenames really have an invisible\n        dot at the end, which is how DOS and related systems treat filenames\n        in general.  All other regular expressions (including \"?\" and\n        \"[range_of_chars]\") retain their Unix-like behavior.\n\n      WILD_STOP_AT_DIR   (incompatible with WINDLL!)\n        Enables an additional option \"-W\".  When this qualifier is specified,\n        the pattern matching routine is modified so that both '?' (single-char\n        wildcard) and '*' (multi-char wildcard) do not match the directory\n        separator character '/'. Examples:\n          \"*.c\" matches \"foo.c\" but not \"mydir/foo.c\"\n          \"*/*.c\" matches \"bar/foo.c\" but not \"baz/bar/foo.c\"\n          \"??*/*\" matches \"ab/foo\" and \"abc/foo\" but not \"a/foo\" or \"a/b/foo\"\n        To enable matching across directory separator chars, two consecutive\n        multi-char wildcards \"**\" should be specified.\n        This modified behaviour is equivalent to the pattern matching style\n        used by the shells of some of UnZip's supported target OSs (one\n        example is Acorn RISC OS).\n\n      VMSWILD   (VMS only)\n        Use parentheses rather than brackets to delimit sets (ranges), and\n        use '%' instead of '?' as the single-character wildcard for internal\n        filename matching.  (External matching of zipfile names always uses\n        the standard VMS wildcard facilities; character sets are disallowed.)\n\n      VMSCLI   (VMS only)\n        Use VMS-style \"slash options\" (/FOOBAR) instead of the default Unix-\n        style hyphenated options (-f).  This capability does not affect options\n        stored in environment variables (UNZIP_OPTS or ZIPINFO_OPTS); those use\n        the Unix style regardless.  Beginning with UnZip 5.32, the supplied\n        VMS build methods generate both VMS-style and default \"UNIX-style\"\n        executables; you should NOT add VMSCLI to the custom options.\n\n      CHECK_VERSIONS   (VMS only)\n        UnZip \"extra fields\" are used to store VMS (RMS) filesystem info,\n        and the format of this information may differ in various versions\n        of VMS.  Defining this option will enable UnZip warnings when the\n        stored extra-field VMS version(s) do(es) not match the version of\n        VMS currently being used.  This is a common occurrence in zipfiles\n        received from other sites, but since the format of the filesystem\n        does not seem to have changed in years (including on Alpha and\n        IA64 systems), the warnings are not enabled by default.\n\n      RETURN_CODES   (VMS only)\n        VMS interprets return codes according to a rigid set of guidelines,\n        which means it misinterprets normal UnZip return codes as all sorts\n        of really nasty errors.  Therefore VMS UnZip returns an alternate set\n        of return codes; since these may be difficult to interpret, define\n        RETURN_CODES for human-readable explanations.\n\n      VMS_TEXT_CONV   (everybody except VMS)\n        VMS Stream_LF-format text files archived with the \"-V\" option\n        (/VMS), but NOT with -VV (/VMS=ALL), should be fine when extracted\n        on other systems.  Stream_LF-files archived with -VV should be\n        readable as well, but they may get some junk appended.\n        Text files with other formats (like the default VFC, with its\n        embedded byte counts) may be only semi-readable at best when\n        extracted on other systems.  Defining this option enables UnZip's\n        -aa option to detect and convert VMS VFC-record text files into\n        native text format.  Non-VMS UnZips now use a rudimentary VMS extra\n        field analyser to relyably determine such text files. (Earlier\n        versions of UnZip applied some heuristics instead.)\n        Therefore this option is now enabled by default for the main program\n        (but not the SFX stub), because it can be extremely useful on those\n        rare occasions when a VMS text file must be extracted as normal text.\n\n      USE_DJGPP_ENV   (MS-DOS DJGPP 2.0x only)\n        Regular DJGPP v2.0x compiled programs which use ENVIRONMENT are\n        able to read from the file \"djgpp.env\" as well as those set in the\n        environment.  This adds about 1KB to the size of the executable.\n        This option is disabled by default in Info-ZIP source. If you are\n        able to use \"djgpp.env\" and don't like to clutter the environment\n        with many special purpose variables, you may want to compile with\n        this option set.\n\n      USE_DJGPP_GLOB  (MS-DOS DJGPP 2.0x only)\n        If you like to get UnZip binaries that handle command line arguments\n        similar to Unix tools which are run in an Unix shell, you might want\n        to set this compilation option.  This option enables the support for\n        globbing command line arguments containing wildcards that is built\n        into the DJGPP startup code.  When using a binary compiled with this\n        option, you may have to enclose wildcard arguments in double quotes\n        to get them passed to the program unmodified.  Enabling this option\n        is not recommended, because it results in Info-Zip binaries that do\n        not behave as expected for MS-DOS programs.\n\n      USE_VFAT  (MS-DOS only, for using same executable under DOS and Win95/NT)\n        djgpp 2.x and emx/gcc+RSX 5.1 can detect when they are running under a\n        Win32 DOS box and will accordingly enable long-filename support.  For\n        now only djgpp 2.x and emx/gcc with RSX 5.1 or later have this feature\n        (and it is defined by default in msdos/makefile.dj2 and makefile.emx),\n        but if/when other compilers build in similar support, define this\n        macro to enable its use.  See also msdos/doscfg.h.  [Note that djgpp\n        2.0's LFN support is flaky; users should upgrade to 2.01 or later.]\n\n      NO_W32TIMES_IZFIX (Win32 including WinDLL, and WinCE)\n        By specifying this option, you can disable Info-ZIP's special timestamp\n        adjustment to get stable time stamps on NTFS disks that do not change\n        depending on the current time being normal vs. daylight saving time.\n        When this option is set, UnZip behaves exactly like other programs;\n        file timestamps on NTFS partitions are created so that their >current<\n        local time representation displayed by directory listings (cmd.exe\n        \"dir\" command or Windows Explorer listings) is the same as shown by\n        UnZip's listing. But the actual UTC timestamp values stored in the\n        NTFS file attributes vary depending on whether extraction is done\n        at summer or winter time.\n        This option is not recommended because it sacrifies the timestamp\n        comparison checks when extracting or modifying archives in \"update\n        only newer\" mode.\n        However, for environments where consistency of >displayed< dates\n        of files extracted to NTFS vs. FAT disks is considered more important\n        than correctly working update/freshen tasks of Zip&UnZip, this\n        option may be used.\n        >> DO NOT DISTRIBUTE OR PUBLISH executables that were compiled with\n        this option! <<\n\n      NOTIMESTAMP\n        This option disables the -T option, which basically does exactly what\n        Zip's -go options do (i.e., set the timestamp of the zipfile to that of\n        the newest file in the archive without rewriting the archive).  Unlike\n        Zip, however, UnZip supports wildcard specifications for the archive\n        name; for example, \"unzip -T *.zip\" will set the dates of all zipfiles\n        in the current directory.  (UnZip's option is also much faster.)\n\n      DATE_FORMAT=DF_DMY or DF_MDY or DF_YMD\n        This option controls the order in which date components are printed\n        in non-ZipInfo-mode listings:  day-month-year or month-day-year or\n        year-month-day.\n        For DOS, FlexOS, OS2, Theos and Win32, the format is automatically\n        obtained from the operating system; most others default to DF_MDY.\n\n      DATE_SEPCHAR='-' or '.' or '/' etc.\n        This option controls the character that separates the date components\n        shown in (non-ZipInfo-mode) listings.  The Win32 port obtains the\n        separator automatically from the operating system's locale settings;\n        all others default to '-'.\n\n      ACORN_FTYPE_NFS  (needs support for long filenames with embedded commas)\n        This option enables a -F option that instructs UnZip to interpret the\n        filetype information extracted from Acorn RiscOS extra field blocks.\n        The filetype IDs are translated into \"NFS filetype extensions\" and\n        appended to the names of the extracted files. This feature facilitates\n        maintenance of Unix-based NFS volumes that are exported to Acorn RiscOS\n        systems.\n\n      QLZIP  (Unix only)\n        Add some support for QDOS extra fields. This option enables Unix\n        UnZip to append \"datalen info\" to QDOS exec type files in the same\n        format as used by QDOS cross-compilers on Unix or the qltools v2.2(+).\n\n      UNIXBACKUP   (default on OS/2, Unix, Win32)\n        This option enables a -B option that instructs UnZip to rename files\n        that would normally be overwritten.  The renamed files are given a\n        tilde suffix and a unique sequence number (`~#####').  Note that\n        previously renamed files may be overwritten without notice, even\n        if the -n option is given.\n        On target ports where UNIXBACKUP is enabled by default, the negated\n        option NO_UNIXBACKUP may be used to disable this feature.\n\n      OS2_EAS\n        List the sizes of OS/2 EAs and ACLs for each file as two extra columns\n        in \"unzip -l\" output.  This is primarily useful for OS/2 systems, but\n        because zipfiles are portable, OS2_EAS can be defined for any system.\n        (May be extended someday to show sizes of Mac resource forks, RISCOS\n        and VMS file info, etc.)\n\n      DELETE_IF_FULL  (anybody with unlink() function)\n        If a write error is encountered (most likely due to a full disk),\n        enabling this option will cause the incomplete file to be deleted\n        instead of closed normally.  This is particularly useful for the\n        Windows CE port, which must generally contend with extremely limited\n        resources.\n\n      ASM_CRC   (Amiga/Aztec C; many x86 systems:  DOS, OS/2, Win32, Unix)\n        Use an assembler routine to calculate the CRC for each file (speed).\n\n      ASM_INFLATECODES   (Amiga/Aztec C only, for now)\n        Use an assembler version of inflate_codes() for speed.\n\n      OLD_EXDIR\n        No longer supported.\n\n      SFX_EXDIR\n        Enable the \"-d <extract_dir>\" option for UnZipSFX.  This is now\n        enabled by default (since UnZip 5.5) to facilitate use with\n        automated installation scripts and the like.  For disabling\n        this feature, see the NO_SFX_EXDIR option.\n\n      NO_SFX_EXDIR\n        Disables the \"-d <extract_dir>\" option for UnZipSFX to generate the\n        smallest possible executable stub.  (Prior to the UnZip 5.5 release,\n        this was the default.)\n\n      CHEAP_SFX_AUTORUN\n        Enable a simple \"run command after extraction\" feature for\n        the (command line) UnZipSFX stub.  This feature is currently\n        incompatible with the \"-d <extract_dir>\" command line option,\n        therefore CHEAP_SFX_AUTORUN implicitely sets the NO_SFX_EXDIR\n        option.\n\n      NO_ZIPINFO\n        Compile without ZipInfo mode (-Z) enabled; makes a smaller executable\n        because many text strings are left out.  Automatically enabled for\n        some small-model compiles under MS-DOS and OS/2, so ordinarily there\n        is no need to specify this explicitly.  (Note that even with this\n        defined, the resulting executable may still be too big to extract\n        some zipfiles correctly, if compiled with the small memory model.)\n\n      USE_DEFLATE64 (default for UnZip and fUnZip)\n      NO_DEFLATE64 (default for UnZipSFX stub)\n        The \"deflate64\" algorithm from PKZIP 4.0 (or newer) is an enhanced\n        variant of the deflate algorithm that achieves slightly better\n        compression ratios on highly redundant data.  Normally, UnZip should\n        be compiled with support for this compression algorithm enabled.\n        However, this results in significantly larger memory requirements\n        to run the program.  For 16-bit executables (DOS and OS/2), the\n        special memory management to support the 64k history buffer results\n        in a slight performance (= speed) penalty.  And for the SFX stub,\n        \"deflate64\" support might be unnessessary as long as the Info-ZIP\n        Zip utility does not support it (quite likely, this will never\n        get implemented).  So, the NO_DEFLATE64 option is provided to allow\n        exclusion of the deflate64 support.\n\n      USE_BZIP2 (requires additional external code distribution)\n       UnZip can optionally support the \"bzip2\" compression algorithm for\n       most ports on 32-bit (or higher) platforms. Currently, this support\n       is integrated in the Make procedures of MSDOS 32-bit (DJGPP), VMS,\n       Win32, and many Unix systems.\n       Prerequisites:\n       You have to obtain the bzip2 source distribution (version 1.03 or\n       higher) and extract it into the \"bzip2\" subdirectory.\n       Compilation:\n       - MSDOS, Win32: You have to supply the symbol definition\n         \"USEBZ2=1\" on the command line when you invoke the make program.\n       - Unix: The target \"generic\" automatically activates bzip2 support\n         when its configure script detects the presence of the bzip2 sources.\n         For other targets, there are two options:\n         a) Use the command\n            \"make -f unix/Makefile D_USE_BZ2=-DUSE_BZIP2 L_BZ2=-lbz2 \\\n                   LIBBZ2=bzip2/libbz2.a YourTarget\"\n           (Do not use the continuation line and replace YourTarget with\n           the appropiate target name.)\n         b) Edit the Makefile and remove the comment signs from the lines\n            that define the macros D_USE_BZ2, L_BZ2, and LIBBZ2 (at about\n            line 84 ff.).\n       - VMS: The MMS/MMK build program should automatically activate the\n         bzip2 support when it detects the presence of the bzip2 sources.\n\n      MULT_VOLUME (experimental for 5.5x, do NOT use in production versions!)\n      NO_MULT_VOLUME (default)\n        The symbol MULT_VOLUME is used to flag code portions needed for\n        support of multi-volume archives. For now, this flag MUST NOT be\n        used to compile a production versions of UnZip. This flag has been\n        introduced to allow integration of experimental code for multi-volume\n        support in the master source tree. This feature will become a default\n        option in the future 6.1 release of UnZip.\n\n      LZW_CLEAN\n      USE_UNSHRINK (now default, as of January 2005)\n        The \"shrinking\" algorithm from PKZIP 1.0 is an LZW variant.  Unisys\n        patented the Lempel-Ziv-Welch algorithm in 1985 and has publicly\n        claimed that decompression is covered by it.  (IBM also patented the\n        same thing in a filing 3 weeks prior to Unisys's.)  In 2004, the\n        Unisys and IBM patents expired worldwide, so unshrinking is now\n        enabled again by default.  If you do not wish to include the LZW\n        method, you may still disable it by defining LZW_CLEAN.\n        (Unshrinking was used by PKZIP 1.0 and 1.1, and Zip 1.0 and 1.1.\n        All newer archives use only the deflation method.)\n\n      COPYRIGHT_CLEAN   (now default)\n      USE_SMITH_CODE\n        The last chunk of code in UnZip that was blatantly derived from Sam\n        Smith's unzip 2.0 (as in, \"substantially similar\") is in unreduce.c.\n        Since reducing was only used by very early PKZIP beta versions (0.9x),\n        support for it is now omitted by default (COPYRIGHT_CLEAN).  To in-\n        clude unreducing capability, define USE_SMITH_CODE and replace the\n        stub unreduce.c source file by the separatly distributed full source\n        code module.  Note that this subjects UnZip to any and all restrictions\n        in Smith's copyright; see the UnZip COPYING.OLD file for details.\n\n      USE_CRYPT\n        Enable decryption support for all binaries.  The default setting\n        is to disable decryption support for the SFX stub to keep its size\n        as small as possible. For other binaries of the UnZip distribution,\n        decryption support is enabled by default.\n\n      NO_CRYPT\n        Disable decryption support for all binaries.\n\n      PASSWD_FROM_STDIN   (with full crypt sources only; Unix, VMS only)\n        Used to allow the password on encrypted files to be read from stdin\n        rather than the default stderr.  This was useful for those who wished\n        to automate the testing or decoding of encrypted archives (say, in a\n        shell script via ``echo \"password\" | unzip -tq archive''), but as of\n        version 5.3, UnZip has a -P option for passing a password directly to\n        the program.  PASSWD_FROM_STDIN will therefore probably be phased out\n        in future versions.  Note that the same security warnings given in the\n        description of the -P option apply here as well.\n\n      UNICODE_SUPPORT\n        Enable restoring from UTF-8 encoded paths.  These paths are stored\n        in extra fields in a backward-compatible way so that archives with\n        UTF-8 paths still work on zips and unzips that don't support Unicode.\n        This support follows the recent additions to the PKWare AppNote for\n        Unicode support, except that Unicode comments on systems where UTF-8\n        is not the current character set is not implemented in this release.\n\n        Internally, Unicode support can be achieved by three methods:\n        a) The charset encoding used by the system is already UTF-8, so\n           the program just has to select the UTF-8 versions of the stored\n           filenames for file name handling.\n           This method is enabled by setting the symbol UTF8_MAYBE_NATIVE;\n           this activates code to check for native UTF-8 encoding in the\n           locale settings.\n        b) The operating system and the compilation environment support\n           \"wide character\" data in Unicode encoding (UCS-2/UTF-16 or UCS-4),\n           which are used to translate between UTF-8 and the native\n           extended-ASCII character encoding.\n           The code for this method is activated by setting the preprocessor\n           symbol UNICODE_WCHAR.\n           It may be activated together with UTF8_MAYBE_NATIVE to provide\n           more versatile Unicode support and additional \"debugging\" options\n           for checking the correct recognition of non-ASCII Unicode\n           characters.\n        c) The operating system and the compilation environment allow to use\n           unicode-encoded \"wide character\" data for native text strings\n           support.\n           Complete support for this method requires a throughout revision\n           of the UnZip code. All internal string handling and text output\n           needs to be ported to use wchar_t character storage.\n           This porting is still in an experimental stage and not ready\n           for general distribution.\n\n        On some ports UNICODE_SUPPORT is set automatically:\n        - WIN32 (and WinCE) use method b) by defining UNICODE_SUPPORT and\n          UNICODE_WCHAR.\n        - On Unix, the automatic configuration script enables UNICODE_WCHAR\n          if ISO-10646 compatible wide characters are supported and\n          UTF8_MAYBE_NATIVE if the locale detection call is available.\n        For these ports, setting NO_UNICODE_SUPPORT forces deactivation of\n        the Unicode support.\n\n      NO_SETLOCALE (for Unix)\n        On Unix, it is now assumed that <locale.h> and the setlocale function\n        are available, to setup locale-aware filtering of displayed filenames.\n        The option NO_SETLOCALE allows to disable the dependency on <locale.h>\n        and setlocale() on systems where this assumption is invalid (and the\n        auto-configuring make target \"generic\" cannot be used for capabilities\n        detection).\n\n      _MBCS\n      NO_MBCS\n       Enable multi-byte character set support.  This is the default for the\n       Human68k system (originated from Japan) and for Win32 (here only DBCS\n       \"double-byte character set\" support).  The MBCS support should also be\n       enabled on systems which are capable of using UTF-8 as native charset.\n       For MBCS support, the C runtime library must supply implementations\n       for the mblen() function and the MB_CUR_MAX runtime macro/function.\n       The NO_MBCS symbol allows to explicitely disable MBCS support for\n       testing purpose, or when MBCS support does not work as expected.\n\n      HAVE_WORKING_ISPRINT\n      NO_WORKING_ISPRINT\n        The symbol HAVE_WORKING_ISPRINT enables enhanced non-printable chars\n        filtering for filenames in the fnfilter() function.  On some systems\n        (Unix, VMS, some Win32 compilers), this setting is enabled by default.\n        In cases where isprint() flags printable extended characters as\n        unprintable, defining NO_WORKING_ISPRINT allows to disable the enhanced\n        filtering capability in fnfilter().  (The ASCII control codes 0x01 to\n        0x1f are always escaped on ASCII systems.)\n\n      DEBUG\n        Used for debugging purposes; enables Trace() statements.  Generally\n        it's best to compile only one or two modules this way.\n\n      DEBUG_TIME\n        Used for debugging the timezone code in fileio.c; enables TTrace()\n        statements.  This code is only used for the freshen/update options\n        (-f and -u), and non-Unix compilers often get it wrong.\n\n\n(4) If you regularly compile new versions of UnZip and always want the same\n    non-standard option(s), you may wish to add it (them) to the LOCAL_UNZIP\n    environment variable (assuming it's supported in your makefile).  Under\n    MS-DOS, for example, add this to AUTOEXEC.BAT:\n\n        set LOCAL_UNZIP=-DDOSWILD -DDATE_FORMAT=DF_DMY\n\n    You can also use the variable to hold special compiler options (e.g.,\n    -FPi87 for Microsoft C, if the x87 libraries are the only ones on your\n    disk and they follow Microsoft's default naming conventions; MSC also\n    supports the CL environment variable, however).\n\n\n(5) Run the make utility on your chosen makefile:\n\n      Unix\n        For most systems it's possible to invoke the makefile in place, at\n        the possible cost of an ignorable warning; do \"make -f unix/Makefile\n        list\" to get a list of possible system targets, and then \"make -f\n        unix/Makefile target\" for your chosen target.  The \"generic\" target\n        works for most systems, but if it fails with a message about ftime()\n        unresolved or timezone redefined, do \"make clean\", \"make help\", and\n        then either \"make generic2\" or \"make generic3\" as instructed.  If all\n        else fails, read the makefile itself; it contains numerous comments.\n        (One of these days we'll make a configure script that automates this\n        procedure better.)\n\n      VMS (OpenVMS):\n        On VMS, two build methods are provided: a command procedure, and\n        description files for MMS or MMK.  Both methods must be run from\n        the main directory, not the [.VMS] subdirectory.\n\n        A simple build using the command procedure looks like this:\n             @ [.VMS]BUILD_UNZIP.COM\n\n        A simple build using MMS or MMK looks like this:\n             MMS /DESCRIP = [.VMS]DESCRIP.MMS      ! Or, with MMK, ...\n             MMK /DESCRIP = [.VMS]DESCRIP.MMS\n\n        Various options for each build method are explained in comments in\n        the main builder file, either BUILD_UNZIP.COM or DESCRIP.MMS.\n\n        Here are some more complex build examples:\n\n        o Build with the large-file option enabled (non-VAX only):\n\n             @ [.VMS]BUILD_UNZIP LARGE\n          or:\n             MMS /DESC = [.VMS] /MACRO = LARGE=1\n\n        o Re-link the executables (small-file and large-file):\n\n             @ [.VMS]BUILD_UNZIP LINK\n             @ [.VMS]BUILD_UNZIP LARGE LINK\n          or\n             MMK /DESC = [.VMS] CLEAN_EXE  ! Deletes existing executables.\n             MMK /DESC = [.VMS]            ! Builds new executables.\n             MMK /DESC = [.VMS] /MACRO = LARGE=1 CLEAN_EXE\n             MMK /DESC = [.VMS] /MACRO = LARGE=1\n\n        o Build a large-file product from scratch, for debug, getting\n          compiler listings and link maps:\n\n             mms /desc = [.vms] clean\n             mms /desc = [.vms] /macro = (DBG=1, LARGE=1. LIST=1)\n\n        On VAX, the builders attempt to cope with the various available C\n        compilers: DEC/Compaq/HP C, VAX C, or GNU C.  If DEC/Compaq/HP C is\n        not available or not desired, comments in the relevant builder file\n        explain the command-line options used to select a different\n        compiler.\n\n        System-architecture-specific files (like objects and executables)\n        are placed in separate directories, such as [.ALPHA], [.IA64], or\n        [.VAX].  Large-file products get their own directories, [.ALPHAL]\n        or [.IA64L].  On VAX, VAX C products are placed in [.VAXV], GNU C\n        products in [.VAXG].  Each product builder announces what the\n        destination directory will be when it is run.\n\n        Common files, such as the help libraries (UNZIP.HLP for the\n        default UNIX-like command-line interface, UNZIP_CLI.HLP for the\n        VMS-like command-line interface), are placed in the main\n        directory.  With a mixed-architecture VMS cluster, the same main\n        directory on a shared disk may may be used by all system types.\n        (Using the NOHELP option with BUILD_UNZIP.COM can keep it from\n        making the same help files repeatedly.)\n\n        Some further information may be found in the files\n        [.VMS]README. and [.VMS]00BINARY.VMS, though much of what's\n        there is now obsolete.\n\n      MS-DOS\n        See the msdos\\Contents file for notes regarding which makefile(s) to\n        use with which compiler.  In summary:  pick one of msdos\\makefile.*\n        as appropriate, or (as noted above) use the OS/2 gccdos target for\n        emx+gcc.  There is also an mscdos cross-compilation target in\n        os2\\makefile.os2 and a sco_dos cross-compilation target in the Unix\n        makefile.  For Watcom 16-bit or 32-bit versions, see the comments in\n        the OS/2 section below.\n\n        After choosing the appropriate makefile and editing as necessary or\n        desired, invoke the corresponding make utility.  Microsoft's NMAKE\n        and the free dmake and GNU make utilities are generally the most\n        versatile.  The makefiles in the msdos directory can be invoked in\n        place (\"nmake -f msdos\\makefile.msc\", for example).\n\n      OS/2\n        Either GNU make, nmake or dmake may be used with the OS/2 makefile;\n        all are freely available on the net.  Do \"nmake -f os2\\makefile.os2\",\n        for example, to get a list of supported targets.  More generally,\n        read the comments at the top of the makefile for an explanation of\n        the differences between some of the same-compiler targets.\n\n      Win32 (WinNT or Win9x)\n        For creating Win32 executables, the Microsoft Visual C++ compiler\n        platforms from version 2.x up to 8.0 (Visual Studio .Net C++ 2005)\n        are supported.  Recent build test have been run on VC++ 6.0, 7.1\n        and 8.0.  The linker of newer Microsoft Visual C++ versions (beginning\n        with Visual C++ 2008 - [VC++ 9.0]) create executables that are marked\n        to run on Windows 2000 and newer, only.  Although these Visual C++\n        environments may succeed in building Win32 Info-ZIP executables,\n        they cannot (and must not) be used to create binaries for public\n        distribution.\n        Alternative compilers for the Intel platforms are OpenWatcom C++,\n        GNU C (preferably the mingw32 port, CygWin and emx/rsxnt may also\n        work), Borland C++, or lcc-win32.\n        DEC C/C++ for NT/Alpha may or may not still work.\n        For the Watcom compiler, use WMAKE and win32\\makefile.wat; for the\n        Microsoft compilers, use NMAKE and win32\\Makefile; for mingw32 and\n        CygWin, GNU Make and win32\\Makefile.gcc should do the job.\n        With emx+gcc, a good choice is GNUMake 3.75 (or higher) from the\n        djgpp V2 distribution used on win32\\Makefile.emx.\n\n        The unzip32.dll WinDLL executables can be built using the appropiate\n        Makefile in the win32\\ subdirectory, or by using the Microsoft Visual\n        C++ project files supplied below the windll subdirectory.  Besides the\n        MSC compilers, gcc-mingw32, Watcom C and Borland C allow to build the\n        Windows UnZip DLL.  By default, the Makefiles for compilers that use\n        the Microsoft C runtime are configured to link against the shared\n        multithreading C runtime DLL.  Depending on the intended usage for\n        unzip32.dll, a statically linked dll might be more suitable.  The\n        make scripts for MSC support build variants with static linking; you\n        should look up the configuration switch DLLSTANDALONE in the MSC\n        Makefile or the \"Static...\" build configurations in the Visual Studio\n        project files.\n\n      WinCE (WinCE or WinNT)\n        Only Microsoft Visual C++ 5.0, 6.0 or Visual C++ embedded 3.0 or later\n        are supported.  Use the appropiate version of the included project\n        files and check wince\\README for details.\n\n      AmigaDOS\n        SAS/Lattice C and Manx Aztec C are supported.  For SAS C 6.x do \"smake\n        -f amiga/smakefile all\"; for Aztec C do \"make -f amiga/makefile.azt\n        all\".  The Aztec C version supports assembly-language versions of two\n        routines; these are enabled by default.\n\n      Atari TOS\n        Turbo C is no longer supported; use gcc and the MiNT libraries, and\n        do \"make\".  Note that all versions of gcc prior to 2.5.8 have a bug\n        affecting 68000-based machines (optimizer adds 68020 instructions).\n        See atari\\README for comments on using other compilers.\n\n      Macintosh\n        Metrowerks CodeWarrior Pro 4 with Universal Interfaces 3.1 is the only\n        currently supported compiler, although the Mac Programmer's Workbench\n        (MPW) and Think C were supported at one time and still have some hooks.\n        Other Compilers may work too, no compiler specific instructions\n        (pragma, header, macros, ...) were used in the code.\n        For CodeWarrior Pro 4, un-BinHex the CodeWarrior project file and\n        UnZip resource file (using Stuffit Expander or BinHex 4.0 or later),\n        then open the project and click on the compile button.\n        See \":macos:Contents\" for the possible project targets.\n        Link order of the standard libraries is very important: Link all\n        sources first and all standard libraries last.\n\n      Acorn (RISC OS)\n        Extract the files from the archive and place in standard 'Acorn' C\n        form (i.e., *.c, *.h and *.s become c.*, h.* and s.*, respectively),\n        either using the UNZIP$EXTS environment variable and a pre-built UnZip\n        binary, or using Spark[FS] and doing it manually.  Then copy the\n        Acorn.Makefile to the main UnZip directory and either type 'amu' or\n        use the desktop make utility.\n\n      VM/CMS\n        Unpack all the files and transfer them with ASCII -> EBCDIC conver-\n        sion to an appropriate directory/minidisk/whatever, then execute\n        UNZVMC to compile and link all the sources.  This may require C/370\n        version 2.1 or later and certain `nucleus extensions,' although\n        UnZip 5.3 has been reported to compile fine with the `ADCYCLE C/370\n        v1.2 compiler.'  Note that it will abend without access to the C/370\n        runtime library.  See the README.CMS file for more details.\n\n      MVS\n        Unpack all the files and transfer them to an appropriate PDS with\n        ASCII -> EBCDIC conversion enabled, then edit UNZMVSC.JOB as required,\n        and execute it to compile and link all the sources.  C/370 2.1 or\n        later is required.  See README.MVS for further details.  [This is a\n        new port and may need a little more work even to compile.]\n\n      Human68K\n        [This is a Japanese machine and OS.]  It appears that GNU make and\n        gcc are required; presumably just do \"gmake -f human68k/Makefile.gcc\"\n        to build everything.  This port has not been tested since the 5.12\n        release.\n\n      TOPS-20\n        [No longer fully supported due to new, unported features, although\n        patches are always accepted.]  Unpack all files into the current\n        directory only (including those in the zipfile's tops20 directory),\n        then use make.mic and \"do make\".\n\n      BeOS\n        You can run the BeOS makefile in place by typing \"make -f\n        beos/Makefile\".  In fact, this is how the author tests it.\n\n    Running the appropriate make utility should produce three executables on\n    most systems, one for UnZip/ZipInfo, one for UnZipSFX, and one for fUnZip.\n    (VMS is one prominent exception:  fUnZip makes no sense on it.  The Amiga\n    produces a fourth executable called MakeSFX, which is necessary because\n    Amiga self-extracting archives cannot be created by simple concatenation.\n    If necessary the source amiga/makesfx.c can be compiled on other systems.)\n    Read any OS-specific README files for notes on setting things up for\n    normal use (especially for VMS) and for warnings about known quirks and\n    bugs in various compilers (especially for MS-DOS).\n\n    Also note that many OSes require a timezone variable to be set correctly\n    (often \"TZ\"); Unix and VMS generally do so by default, Win95/NT do if set\n    up properly, but other OSes generally do not.  See the discussion of the\n    -f and -u options in the UnZip man page (or unzip.txt).  BeOS doesn't\n    currently support timezone information at all, but this will probably be\n    added soon.\n\n    Then test your new UnZip on a few archives and let us know if there are\n    problems (but *please* first make certain that the archives aren't actu-\n    ally corrupted and that you didn't make one of the silly mistakes dis-\n    cussed in the documentation).  If possible, double-check any problems\n    with PKUNZIP or with a previous version of UnZip prior to reporting a\n    \"bug.\"  The zipfile itself may be damaged.\n\n\n\nTo install:\n===========\n\nUnix\n  The default prefix for the installation location is /usr/local (things\n  go into the bin and man/man1 subdirectories beneath the prefix), and\n  the default man-page extension is \"1\" (corresponding to man/man1, above).\n  To install as per the defaults, do \"make install\"; otherwise do \"make\n  prefix=/your/path manext=your_extension install\".  (For Intel Unix flavors\n  where the assembler CRC routines were used [ASM_CRC], use the install_asm\n  target instead of the regular install target.)  For example, to install\n  in your home directory with \"l\" as the man-page extension (for \"local\"),\n  do \"make prefix=$HOME manext=l install\".  Permissions will be 755 for the\n  executables and 644 for the man pages.  In general root must perform in-\n  stallation into a public directory.  Do \"rehash\" if your shell requires\n  it in order to find the new executables.\n\nVMS\n  To complete the installation, the executables may be left in place,\n  or moved (or copied) to a convenient place.  While other methods\n  (like DCL$PATH) exist, most users define symbols to make the UnZip\n  executables available as foreign commands.  These symbol definitions\n  may be placed in a user's SYS$LOGIN:LOGIN.COM, or in a more central\n  location, like SYS$MANAGER:SYLOGIN.COM.  Typical symbol definitions\n  might look like these:\n\n     UNZIP :== $ dev:[dir]UNZIP.EXE             ! UNIX-like command line.\n  or:\n     UNZIP :== $ dev:[dir]UNZIP_CLI.EXE         ! VMS-like command line.\n\n  For convenience, a ZIPINFO symbol could also be defined, so:\n\n     ZIPINFO :== $ dev:[dir]UNZIP.EXE \"\"\"-Z\"\"\"\n\n  On a non-VAX system, different symbols could be defined for the\n  small-file and large-file programs.  For example:\n\n     UNZIPS  :== $ dev:[dir.ALPHA]UNZIP.EXE     ! UNZIPS = small-file UnZip.\n     UNZIP*L :== $ dev:[dir.ALPHAL]UNZIP.EXE    ! UNZIP[L] = large-file UnZip.\n\n  The builders create help text files, UNZIP.HLP and UNZIP_CLI.HLP.\n  These may be incorporated into an existing help library, or a separate\n  UnZip help library may be created using commands like these, using\n  either UNZIP.HLP (as shown) or UNZIP_CLI.HLP:\n\n      $ LIBRARY /HELP dev:[dir]existing_library.HLB UNZIP.HLP\n\n      $ LIBRARY /CREATE /HELP UNZIP.HLB UNZIP.HLP\n\n  UnZip help may then be accessed from a separate UnZip help library\n  using a command like:\n\n          $ HELP /LIBRARY = device:[directory]UNZIP.HLB\n\n  For greater ease, the user (or system manager) may define a\n  HLP$LIBRARY logical name to allow the HELP utility to find the UnZip\n  help library automatically.  See HELP HELP /USERLIBRARY for more\n  details.   The command procedure HLP_LIB_NEXT.COM may be used to\n  determine the next available HLP$LIBRARY logical name, and could be\n  adapted to define a HLP$LIBRARY logical name for an UnZip help library.\n\n  The kit includes MAKESFX.COM, a command procedure intended to simplify\n  creating a self-extracting archive.  It may be helpful to install this\n  procedure near the UnZip executables.  MAKESFX.COM expects another\n  symbol definition, like one of these:\n\n     UNZIPSFX :== $ dev:[dir]UNZIPSFX.EXE       ! UNIX-like command line.\n  or:\n     UNZIPSFX :== $ dev:[dir]UNZIPSFX_CLI.EXE   ! VMS-like command line.\n\n  Again here, on a non-VAX system, either a small-file or a large-file\n  UNZIPSFX program may be used.  (MAKESFX.COM could be modified to allow\n  a run-time choice to be made.)\n\nOS/2, MS-DOS, NT, Atari, Amiga\n  Move or copy unzip.exe (or unzip.ttp, or UnZip, or whatever) to a direc-\n  tory in your path; also possibly copy the UnZip executable to zipinfo.exe\n  (or ii.exe), or else create an alias or a batch/command file for ZipInfo\n  (\"@unzip -Z %1 %2 %3 %4 %5 %6 %7 %8 %9\" under MS-DOS).  The latter is only\n  relevant if NO_ZIPINFO was *not* defined, obviously...  Under djgpp 2.x,\n  zipinfo.exe is a 2K stub symbolically linked to unzip.exe.\n\nAcorn RISC OS\n  Copy the executables unzip, funzip and zipinfo to somewhere in your\n  Run$Path.  See your Welcome manual if you don't know about Run$Path.\n\nBeOS\n  The default prefix for the installation location is /boot/usr/local\n  (things go into the bin and man/man1 subdirectories beneath the prefix),\n  and the default man-page extension is \"1\" (corresponding to the man/man1,\n  above).  Of course, these Unix man-pages aren't useful until someone ports\n  something that can format them... plain text versions are also installed\n  with an extension of \".txt\".  To install, do a \"make install\", or to\n  change the prefix, do \"make prefix=/your/path install\".  For example, to\n  install in /boot/bin, do \"make prefix=/boot/bin install\".\n\nMacintosh\n  (This port is for Macintosh OS before Mac OS X.  See Unix Apple below for\n  Mac OS X and later.)\n  MacZip requires at least System 7 and a Macintosh with a minimum of a\n  Motorola 68020 or PowerPC 601 processor. Other configurations may work\n  but it is not tested at all.\n  The application (MacZip) is distributed as a combination of zip and unzip\n  in one program. The offical release is a fat binary with both regular 68K\n  and native PowerPC versions included.\n  Move the executable(s) somewhere--for example, drag it (or them) to your\n  Applications folder.  For easy access, make an alias in the Launcher Control\n  Panel or directly on your desktop.\n  This port supports also Apple-event.So you can install it in your\n  WWW-Browser as a helper-app.\n  Look into \"macos/README.TXT\" (or \":macos:README.TXT\" on Mac) for further\n  info.\n\nMacintosh OS X (Unix Apple)\n  Mac OS X and later are based on BSD Unix and are supported by the Unix\n  port.  See the Unix port for details.  Though support is currently\n  minimal, we plan to support additional Mac OS X features, such as resource\n  forks, in future releases.\n\nHuman68K, TOPS-20, AOS/VS, MVS, VM/CMS, etc.\n  Dunno, sorry...\n"
  },
  {
    "path": "deps/infozip/unzip60/LICENSE",
    "content": "This is version 2009-Jan-02 of the Info-ZIP license.\nThe definitive version of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and\na copy at http://www.info-zip.org/pub/infozip/license.html.\n\n\nCopyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n\n   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n   Rich Wales, Mike White.\n\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held liable\nfor any direct, indirect, incidental, special or consequential damages\narising out of the use of or inability to use this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  Additional documentation is not needed\n       for executables where a command line license option provides these and\n       a note regarding this option is in the executable's startup banner.  The\n       sole exception to this condition is redistribution of a standard\n       UnZipSFX binary (including SFXWiz) as part of a self-extracting archive;\n       that is permitted without inclusion of this license, as long as the\n       normal SFX banner has not been removed from the binary or disabled.\n\n    3. Altered versions--including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP--must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases--including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n\n    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"\n       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its\n       own source and binary releases.\n"
  },
  {
    "path": "deps/infozip/unzip60/README",
    "content": "This is the README file for the 20 April 2009 public release of the\nInfo-ZIP group's portable UnZip zipfile-extraction program (and related\nutilities).\n\nunzip60.zip       portable UnZip, version 6.0, source code distribution\nunzip60.tar.Z     same as above, but compress'd tar format\nunzip60.tar.gz    same as above, but gzip'd tar format\n\n__________________________________________________________________________\n\nBEFORE YOU ASK:  UnZip, its companion utility Zip, and related utilities\nand support files can be found in many places; read the file \"WHERE\" for\nfurther details.  To contact the authors with suggestions, bug reports,\nor fixes, continue reading this file (README) and, if this is part of a\nsource distribution, the file \"ZipPorts\" in the proginfo directory.  Also\nin source distributions:  read \"BUGS\" for a list of known bugs, non-bugs\nand possible future bugs; INSTALL for instructions on how to build UnZip;\nand \"Contents\" for a commented listing of all the distributed files.\n__________________________________________________________________________\n\n\nGENERAL INFO\n------------\nUnZip is an extraction utility for archives compressed in .zip format (also\ncalled \"zipfiles\").  Although highly compatible both with PKWARE's PKZIP\nand PKUNZIP utilities for MS-DOS and with Info-ZIP's own Zip program, our\nprimary objectives have been portability and non-MSDOS functionality.\n\nThis version of UnZip has been ported to a stupendous array of hardware--\nfrom micros to supercomputers--and operating systems:  Unix (many flavors),\nVMS, OS/2 (including DLL version), Windows NT and Windows 95 (including DLL\nversion), Windows CE (GUI version), Windows 3.x (including DLL version),\nMS-DOS, AmigaDOS, Atari TOS, Acorn RISC OS, BeOS, Macintosh (GUI version),\nSMS/QDOS, MVS, VM/CMS, FlexOS, Tandem NSK, Human68k (mostly), AOS/VS (partly)\nand TOPS-20 (partly).  UnZip features not found in PKUNZIP include source\ncode; default extraction of directory trees (with a switch to defeat this,\nrather than the reverse); system-specific extended file attributes; and, of\ncourse, the ability to run under most of your favorite operating systems.\nPlus, it's free. :-)\n\nFor source distributions, see the main Contents file for a list of what's\nincluded, and read INSTALL for instructions on compiling (including OS-\nspecific comments).  The individual operating systems' Contents files (for\nexample, vms/Contents) may list important compilation info in addition to\nexplaining what files are what, so be sure to read them.  Some of the ports\nhave their own, special README files, so be sure to look for those, too.\n\nSee unzip.1 or unzip.txt for usage (or the corresponding UnZipSFX, ZipInfo,\nfUnZip and ZipGrep docs).  For VMS, unzip_def.rnh or unzip_cli.help may be\ncompiled into unzip.hlp and installed as a normal VMS help entry; see\nvms/descrip.mms.\n\n\nCHANGES AND NEW FEATURES\n------------------------\nUnZip 6.0 finally supports nowadays \"large\" files of sizes > 2 GiB!\nThis is the first release containing support for the PKWARE Zip64\nenhancements.\nMajor changes are:\n   - Support PKWARE ZIP64 extensions, allowing Zip archives and Zip archive\n     entries larger than 4 GiBytes and more than 65536 entries within a single\n     Zip archive. This support is currently only available for Unix,\n     OpenVMS and Win32/Win64.\n   - Support for bzip2 compression method.\n   - Support for UTF-8 encoded entry names, both through PKWARE's \"General\n     Purpose Flags Bit 11\" indicator and Info-ZIP's new \"up\" unicode path\n     extra field.  (Currently, on Windows the UTF-8 handling is limited to\n     the character subset contained in the configured non-unicode \"system\n     code page\".)\n   - Added \"wrong implementation used\" warning to error messages of the MSDOS\n     port when used under Win32, in an attempt to reduce false bug reports.\n   - Fixed \"Time of Creation/Time of Use\" vulnerability when setting attributes\n     of extracted files, for Unix and Unix-like ports.\n   - Fixed memory leak when processing invalid deflated data.\n   - Fixed long-standing bug in unshrink (partial_clear), added boundary checks\n     against invalid compressed data.\n   - On Unix, keep inherited SGID attribute bit for extracted directories\n     unless restoration of owner/group id or SUID/SGID/Tacky attributes was\n     requested.\n   - On Unix, allow extracted filenames to contain embedded control characters\n     when explicitly requested by specifying the new command line option \"-^\".\n   - On Unix, support restoration of symbolic link attributes.\n   - On Unix, support restoration of 32-bit UID/GID data using the new \"ux\"\n     IZUNIX3 extra field introduced with Zip 3.0.\n   - Support for ODS5 extended filename syntax on new OpenVMS systems.\n   - Support symbolic links zipped up on VMS.\n   - On VMS (only 8.x or better), support symbolic link creation.\n   - On VMS, support option to create converted text files in Stream_LF format.\n   - New -D option to suppress restoration of timestamps for extracted\n     directory entries (on those ports that support setting of directory\n     timestamps).  By specifying \"-DD\", this new option also allows to suppress\n     timestamp restoration for ALL extracted files on all UnZip ports which\n     support restoration of timestamps.\n     On VMS, the default behaviour is now to skip restoration of directory\n     timestamps; here, \"--D\" restores ALL timestamps, \"-D\" restores none.\n   - On OS/2, Win32, and Unix, the (previously optional) feature UNIXBACKUP\n     to allow saving backup copies of overwritten files on extraction is now\n     enabled by default.\n\nFor the UnZip 6.0 release, we want to give special credit to Myles Bennet,\nwho started the job of supporting ZIP64 extensions and Large-File (> 2GiB)\nand provided a first (alpha-state) port.\n\nThe 5.52 maintenance release fixes a few minor problems found in the 5.51\nrelease, closes some more security holes, adds a new AtheOS port, and\ncontains a Win32 extra-field code cleanup that was not finished earlier.\nThe most important changes are:\n\n   - (re)enabled unshrinking support by default, the LZW patents have expired\n   - fixed an extraction size bug for encrypted stored entries (12 excess bytes\n     were written with 5.51)\n   - fixed false \"uncompressed size mismatch\" messages when extracting\n     encrypted archive entries\n   - do not restore SUID/SGID/Tacky attribute bits on Unix (BeOS, AtheOS)\n     unless explicitely requested by new \"-K\" command line qualifier\n   - optional support for \"-W\" qualifier to modify the pattern matching syntax\n     (with -W: \"*\" stops at directory delimiter, \"**\" matches unlimited)\n   - prevent buffer overflow caused by bogus extra-long Zipfile specification\n   - performance enhancements for VMS port\n   - fixed windll interface handling of its extraction mode qualifiers\n     nfflag, ExtractOnlyNewer, noflag, PromptToOverwrite; added detailed\n     explanation of their meanings and interactions to the windll documentation\n\nThe 5.51 maintenance release adds a command-line CE port, intended for\nbatch processing. With the integration of this port, the pUnZip port\nhas been revised and \"revitalized\".\nThe most important changes for the general public are a number of\nbug fixes, mostly related to security issues:\n\n   - repair a serious bug in the textmode output conversion code for the 16-bit\n     ports (16-bit MSDOS, OS/2 1.x, some variants of AMIGA, possibly others)\n     which was introduced by the Deflate64 support of release 5.5\n   - fix a long standing bug in the the inflate decompression method that\n     prevented correct extraction in some rare cases\n   - fixed holes in parent dir traversal security code (e.g.: \".^C.\" slipped\n     through the previous version of the check code)\n   - fixed security hole: check naming consistency in local and central header\n   - fixed security hole: prevent extracted symlinks from redirecting file\n     extraction paths\n\nThe main addition in the 5.5 release is support for PKWARE's new Deflate64(tm)\nalgorithm, which appeared first in PKZIP 4.0 (published November 2000).\nAs usual, some other bugfixes and clean-ups have been integrated:\n\n   - support for Deflate64 (Zip compression method #9)\n   - support for extracting VMS variable length record text files on\n     any system\n   - optional \"cheap autorun\" feature for the SFX stub\n   - security fixes:\n     * strip leading slash from stored pathspecs,\n     * remove \"../\" parent dir path components from extracted file names\n   - new option \"-:\" to allow verbatim extraction of file names containing\n     \"../\" parent dir path specs\n   - fixed file handle leak for the DLL code\n   - repaired OS2 & WinNT ACL extraction which was broken in 5.42\n\nThe 5.42 maintenance release fixes more bugs and cleans up the redistribution\nconditions:\n\n   - removal of unreduce.c and amiga/timelib.c code to get rid of the last\n     distribution restrictions beyond the BSD-like Info-ZIP LICENSE\n   - new generic timelib replacement (currently used by AMIGA port)\n   - more reasonable mapping rules of UNIX \"leading-dot\" filenames to the\n     DOS 8.3 name convention\n   - repaired screensize detection in MORE paging code\n     (was broken for DOS/OS2/WIN32 in 5.41)\n\nThe 5.41 maintenance release adds another new port and fixes some bugs.\n\n   - new BSD-like LICENSE\n   - new Novell Netware NLM port\n   - supports extraction of archives with more than 64k entries\n   - attribute handling of VMS port was broken in UnZip 5.4\n   - decryption support integrated in the main source distribution\n\nThe 5.4 release adds new ports, again. Other important items are changes\nto the listing format, new supplemental features and several bug fixes\n(especially concerning time-stamp handling...):\n\n   - new IBM OS/390 port, a UNIX derivate (POSIX with EBCDIC charset)\n   - complete revision of the MacOS port\n   - changed listing formats to enlarge the file size fields for more digits\n   - added capability to restore directory attributes on MSDOS, OS/2, WIN32\n   - enabled support of symbolic links on BeOS\n   - Unix: optional Acorn filetype support, useful for volumes exported via NFS\n   - several changes/additions to the DLL API\n   - GUI SFX stub for Win16 (Windows 3.1) and Win32 (Windows 9x, Windows NT)\n   - new free GCC compiler environments supported on WIN32\n   - many time-zone handling bug fixes for WIN32, AMIGA, ...\n\nThe 5.32 release adds two new ports and a fix for at least one relatively\nserious bug:\n\n   - new FlexOS port\n   - new Tandem NSK port\n   - new Visual BASIC support (compatibility with the Windows DLLs)\n   - new -T option (set zipfile timestamp) for virtually all ports\n   - fix for timestamps beyond 2038 (e.g., 2097; crashed under DOS/Win95/NT)\n   - fix for undetected \"dangling\" symbolic links (i.e., no pointee)\n   - fix for VMS indexed-file extraction problem (stored with Zip 2.0 or 2.1)\n   - further performance optimizations\n\nThe 5.31 release included nothing but small bug-fixes and typo corrections,\nwith the exception of some minor performance tweaks.\n\nThe 5.3 release added still more ports and more cross-platform portability\nfeatures:\n\n   - new BeOS port\n   - new SMS/QDOS port\n   - new Windows CE graphical port\n   - VM/CMS port fully updated and tested\n   - MVS port fully updated and tested\n   - updated Windows DLL port, with WiZ GUI spun off to a separate package\n   - full Universal Time (UTC or GMT) support for trans-timezone consistency\n   - cross-platform support for 8-bit characters (ISO Latin-1, OEM code pages)\n   - support for NT security descriptors (ACLs)\n   - support for overwriting OS/2 directory EAs if -o option given\n   - updated Solaris/SVR4 package facility\n\nWhat is (still!) not added is multi-part archive support (a.k.a. \"diskette\nspanning\", though we really mean archive splitting and not the old diskette\nspanning) and a unified and more powerful DLL interface.  These are the two\nhighest priorities for the 6.x releases.  Work on the former is almost\ncertain to have commenced by the time you read this.  This time we mean it!\nYou betcha. :-)\n\nAlthough the DLLs are still basically a mess, the Windows DLLs (16- and 32-\nbit) now have some documentation and a small example application.  Note that\nthey should now be compatible with C/C++, Visual BASIC and Delphi.  Weirder\nlanguages (FoxBase, etc.) are probably Right Out.\n\n\nINTERNET RESOURCES\n------------------\n\nInfo-ZIP's web site is at http://www.info-zip.org/pub/infozip/\nand contains the most up-to-date information about coming releases,\nlinks to binaries, and common problems.\n(See http://www.info-zip.org/pub/infozip/FAQ.html for the latter.)\nFiles may also be retrieved via ftp://ftp.info-zip.org/pub/infozip/ .\nThanks to LEO (Munich, Germany) for previously hosting our primary site.\n\n\nDISTRIBUTION\n------------\nIf you have a question regarding redistribution of Info-ZIP software, either\nas is, as packaging for a commercial product, or as an integral part of a\ncommercial product, please read the Frequently Asked Questions (FAQ) section\nof the included COPYING file.  All Info-ZIP releases are now covered by\nthe Info-ZIP license.  See the file LICENSE.  The most current license\nshould be available at http://www.info-zip.org/license.html and\nftp://ftp.info-zip.org/pub/infozip/license.html.\n\nInsofar as C compilers are rare on some platforms and the authors only have\ndirect access to a subset of the supported systems, others may wish to pro-\nvide ready-to-run executables for new systems.  In general there is no prob-\nlem with this; we require only that such distributions include this README\nfile, the WHERE file, the LICENSE file (contains copyright/redistribution\ninformation), and the appropriate documentation files (unzip.txt and/or\nunzip.1 for UnZip, etc.).  If the local system provides a way to make self-\nextracting archives in which both the executables and text files can be\nstored together, that's best (in particular, use UnZipSFX if at all possible,\neven if it's a few kilobytes bigger than the alternatives); otherwise we\nsuggest a bare UnZip executable and a separate zipfile containing the re-\nmaining text and binary files.  If another archiving method is in common\nuse on the target system (for example, Zoo or LHa), that may also be used.\n\n\nBUGS AND NEW PORTS:  CONTACTING INFO-ZIP\n----------------------------------------\nAll bug reports and patches (context diffs only, please!) should be\nsubmitted either through the new Info-ZIP Discussion Forum at\nhttp://www.info-zip.org/board/board.pl or through the Info-ZIP SourceForge\nsite at http://sourceforge.net/projects/infozip/.  The forum allows file\nattachments while SourceForge provides a place to post patches.  The old\nZip-Bugs@lists.wku.edu e-mail address for the Info-ZIP authors was\ndiscontinued after heavy continuous spam, as was the QuickTopic discussion\nforum.  The above methods are public, but we also can be reached directly\nusing the web reply page at http://www.info-zip.org/zip-bug.html.  If you\nneed to send us files privately, contact us first for instructions.\n\n\"Dumb questions\" that aren't adequately answered in the documentation\nshould also be directed to Zip-Bugs rather than to a global forum such\nas Usenet.  (Kindly make certain that your question *isn't* answered by\nthe documentation, however--a great deal of effort has gone into making\nit clear and complete.)\n\nSuggestions for new features can be discussed on the new Discussion Forum.\nA new mailing list for Info-ZIP beta testers and interested parties may\nbe created someday, but for now any issues found in the betas should use\nthe forum.  We make no promises to act on all suggestions or even all\npatches, but if it is something that is manifestly useful, sending the\nrequired patches to Zip-Bugs directly (as per the instructions in the\nZipPorts file) is likely to produce a quicker response than asking us to\ndo it--the authors are always ridiculously short on time.  (Please do\nNOT send patches or encoded zipfiles to the Info-ZIP list.  Please DO\nread the ZipPorts file before sending any large patch.  It would be\ndifficult to over-emphasize this point...)\n\nIf you are considering a port, not only should you read the ZipPorts file,\nbut also please check in with Zip-Bugs BEFORE getting started, since the\ncode is constantly being updated behind the scenes.  (For example, VxWorks,\nVMOS and Netware ports were once claimed to be under construction, although\nwe have yet to see any up-to-date patches.)  We will arrange to send you the\nlatest sources.  The alternative is the possibility that your hard work will\nbe tucked away in a subdirectory and mostly ignored, or completely ignored\nif someone else has already done the port (and you'd be surprised how often\nthis has happened).\n\n\nBETA TESTING:  JOINING INFO-ZIP\n-------------------------------\nIf you'd like to keep up to date with our UnZip (and companion Zip utility)\ndevelopment, join the ranks of beta testers, add your own thoughts and\ncontributions, or simply lurk, you may join one of our mailing lists.\nThere is an announcements-only list (Info-ZIP-announce) and a general\ndiscussion/testing list (Info-ZIP). You must be a subscriber to post, and\nyou can subscribe via the links on our Frequently Asked Questions page:\n\n        http://www.info-zip.org/pub/infozip/FAQ.html#lists\n\n(Please note that as of late May 2004, the lists are unavailable pending\na move to a new site; we hope to have them restored shortly.  In the\ninterim ...)  Feel free to use our bug-reporting web page for bug reports\nand to ask questions not answered on the FAQ page above:\n\n        http://www.info-zip.org/zip-bug.html\n\nFor now the best option is to monitor and contribute to the various threads\non the new discussion forum site at:\n\n      http://www.info-zip.org/board/board.pl\n\nThe second best way to contribute is through the various features at\nSourceForge, such as the bug posting areas.\n\nThere is also a closed mailing list for internal discussions of our core\ndevelopment team. This list is now kept secret to prevent us from being\nflooded with spam messages.\n\n\n-- Greg Roelofs (sometimes known as Cave Newt), principal UnZip developer\n   guy, with inspiration from David Kirschbaum, was Author of this text.\n\n-- Christian Spieler (shorthand: SPC), current UnZip maintenance coordinator,\n   applied the most recent changes, with Ed Gordon providing a few additions.\n"
  },
  {
    "path": "deps/infozip/unzip60/ToDo",
    "content": "================================\nFor UnZip 6.1/who knows:\n================================\n\n   o add extraction support for other compression algorithms used by new\n     PKZIP, WinZIP, 7-Zip versions\n     - LZMA, compression type 14 (most important, because of its efficiency)\n     - PPMd, compression type 98 (maybe, less important)\n     - WavPacked, compression type 97 (maybe, less important)\n\n       LZMA is first-level priority for 6.1, other formats may be taken\n       into consideration\n\n   o add support for reading AES encrypted archives\n     - WinZIP format (priority 1)\n     - PKZip format (priority 2)\n\n        top level item for 6.1\n\n   o add multi-part zipfile handling\n\n        major feature for 6.x!\n\n        could happen for 6.1\n\n   o better support for multilingual uses and different codepages;\n     support unicode (UTF-8 coded) filenames and comment texts\n\n        a requested feature getting more and more important,\n        - partially done for the Windows port in 6.0\n          (support restricted for chars of the current system codepage)\n        - partially done (beta state) for Unix\n          (requires native codepage to be UTF-8)\n\n   o complete support for UTF-8 coded entry names (and comments)\n     - add new \"win32_wide\" port to extend unicode support on Windows\n       beyond the restrictions of the current (ANSI) system codepage\n     - revise/extend the WinDLL interface to allow passing of \"wide\"\n       string argument data\n     - add simple built-in character translation between UTF-8 and the\n       old (ISO-8851-1 / IBM850) code pages to allow old systems without\n       standard UTF-8 support to read UTF-8 encoded archives.\n     - extend the built-in translation tables to support other language\n       regions besides \"Western_Latin1\" (e.g. Russian-kyrillic, Japanese,\n       Chinese)\n     - streamline the multilingual codepage and UTF-8 support for the UNIX\n       port (standard codepage translation facility?, like WideChar<->AnsiCP\n       translation functions under MS Windows)\n\n        should happen for 6.1\n        (there is internal alpha-state code for better \"wide\" support on\n        Windows available at the time of the 6.0 release)\n\n   o revise the \"extended charcodes\" handling in decryption password to\n     support UTF-8 encoding on Unicode-aware systems where the \"native\"\n     character coding is NOT UTF-8 (e.g. Windows).\n\n   o revise the command line interface for more compatibility with Zip'\n     command parser\n     - implement the versatile command parser from Zip 3.0.\n     - add \"long option\" definitions for all existing options; revise\n       the UnZip user manual to document the long-option alternatives.\n     - add support for reading the \"process these entries\" and the \"skip\n       these entries\" pattern lists from a file (or from separate files ?).\n     - add a (long) option to switch off UnZip's internal pattern matching\n       on filename arguments.\n\n        probably in 6.1,\n        (first prototype of the revised command parser was available at the\n        time of the 6.0 release)\n\n   o add command line options for miscellaneous features requested by users\n     and/or development team members:\n     - display the Info-ZIP software license\n     - more fine-tuning for file attributes set/restored at extraction, like:\n       set/clear archive attribute on DOS/OS2/WIN32;\n       apply/skip standard or user-defined umask filter on UNIX (& Unix-alike)\n     - additional time-stamp related processing filters\n     - more listing display modifications\n     - overriding the default date-time display style\n     - ...\n\n     All these options are of minor importance and/or would collide with\n     existing \"one-character\" options.  The current UnZip maintainer does not\n     want to reserve any of the few not-yet-occupied short option characters.\n     for one of these features.   So, any implementation effort for items\n     of this feature wish-list has to be delayed until the \"long option\"\n     support of the revised command line parser becomes available.\n\n       some option may get implemented in 6.1\n\n   o support for\n     and/or development team members:\n\n   o add new low-level, binary API; rewrite \"normal\" (command-line) UnZip\n     to use it\n\n        maybe soon (maybe 6.1)\n\n   o MSDOS/WIN32/others: detection of \"reserved\" names (= names of character\n     devices, or system extensions that look like a characters device driver)\n     at runtime; with the goal of emitting \"meaningful\" error messages and/or\n     rename queries.\n     (Currently, these reserved names are catched as \"non-deletable files\".\n      On MSDOS and WIN32, when the RTL stat() function allows to identify\n      character devices, the \"reserved\" names are automatically prefixed with\n      an underscore.)\n\n   o redesign \"file exists -- is newer/older -- overwrite/skip/rename\"\n     logic in extract.c and the corresponding system specific mapname()\n     services; to prevent superfluous decryption key prompts for entry\n     that will be skipped, later.\n\n   o rewrite to use fread/fseek/etc.  [eventually: test\n     write(bytes) vs. fwrite(words), especially on Crays/Alphas]\n\n        soon (probably in conjunction with multi-part handling)\n\n   o incorporate new backfill version of inflate()\n\n        wait for zlib version\n\n   o check NEXTBYTE for EOF in crypt.c, funzip.c and explode.c, too\n\n        whenever\n\n   o add option to force completely non-interactive operation (no queries\n     for overwrite/rename, password, etc.); also allow some sort of non-\n     interactive password provision?  (file? command-line? env. variable?)\n\n        someday?\n\n   o add testing of extra fields (if have CRC)\n\n        later\n\n   o rewrite to allow use as a filter\n\n        way, way later...\n\n   o add Unix hard-link support?\n\n        way, way later...\n\n   o add \".ini\" file support as a (more elaborate) alternative to the presently\n     supported preconfiguring abilities via special environment variables\n     (UNZIP on many systems...)?\n\n        way, way later (if ever)...\n\n   o add option to search zipfile contents for a string and print the\n     results? (\"zipgrep\" option--e.g., unzip -g or unzip -S) (easy for\n     fixed strings, hard for wildcards/true regex's)\n\n        way, way later, if at all...probably use libregex\n\n   o add -y \"display symlinks\" option to zipinfo?  various sorting options?\n     (-St date/time, -Sn name)?\n\n        who knows\n\n   o add \"in-depth\" option to zipinfo? (check local headers against\n     central, etc.)--make it a better debugging tool (or just create\n     zipfix)\n\n        who knows (zip -F, -FF already exist)\n\nSome maintenance or OS specific topics for 6.0 release:\n\n   * add \"unix-style-path -> partitioned-dataset filename\" conversion\n     to MVS port\n\n   * should we add support for (null) entry names (empty entry name field), to\n     conform to the PKWARE specification?\n\n\n=======================================\n\nRequested features:\n\n - extract or exclude on basis of UID [Armin Bub, Armin.Bub@bk.bosch.de, 970904]\n\n=======================================\n\n   o miscellaneous little stuff:  whenever\n     --------------------------\n\n - change DOS -f/-u stuff to use DOS API for getting filetimes, not stat()\n\n - add (-N?) option to lose all user input and/or switch to \"(*input)()\"\n   function, replaceable by UzpAltMain() param\n - add -@ option to read from stdin (zip) or from file (PKZIP)?  (go32 built-in)\n - add -oo option to overwrite OS/2 and DOS system and hidden files, too\n - add option to compute MD5 checksum on files and/or on entire zipfile?\n\n - decide whether to use WinGUI \"skipping\" diagnostics in extract.c\n - combine \"y/n/A/N\" query/response stuff into unified section with query\n    function(s) (InputFn?)\n - disable ^V code in remaining mapname() routines\n\n - change filename-matching logic so case-insensitive if case-sensitive fails?\n\n - allow multiple dir creation with -d option? [Bob Maynard]\n\n - use gcc -pg, gprof to do profiling on unzip\n\n - Doug Patriarche (doug.patriarche.bvdhp01@nt.com) Northern Telecom Canada Ltd.\n    \"I need to do a port of zip/unzip for Wind River Systems' VxWorks OS\"\n    [GRR:  15 March 95 -> \"early June\"]\n\n\nFeatures from old BUGS file (mostly duplicates of other entries above):\n\n - ignore case for internal filename match on non-Unix systems, unless file-\n    specs enclosed in single quotes\n - modify to decompress input stream if part of a pipe, but continue using\n    central directory if not (BIG job!)--extended local header capability\n - add zipinfo option(s) to sort alphabetically, by date/time, in reverse, etc.\n - when listing filenames, use '?' for non-printables? [Thomas Wolff, 92.6.1]\n - add zipinfo \"in-depth\" option? (check local vs. central filenames, etc.)\n - create zipcat program to concatenate zipfiles\n - add -oo option (overwrite and override)?  no user queries (if bad password,\n    skip file; if disk full, take default action; if VMS special on non-VMS,\n    unpack anyway; etc.)\n - add -Q[Q[Q]] option (quiet mode on comments, cautions, warnings and errors)?\n    forget -oo, or make synonym?  Default level -Q?\n"
  },
  {
    "path": "deps/infozip/unzip60/WHERE",
    "content": "__________________________________________________________________________\n\n   This is the Info-ZIP file ``WHERE,'' last updated on 29 March 2008.\n__________________________________________________________________________\n\n   The latest version of this file can be found online at:\n\n           ftp://ftp.info-zip.org/pub/infozip/doc/WHERE\n\n   Note that some ftp sites may not yet have the latest versions of Zip\n   and UnZip when you read this.  The latest versions always appear in\n   ftp://ftp.info-zip.org/pub/infozip/ (and subdirectories thereof) first,\n   except for encryption binaries, which always appear in\n   ftp://ftp.icce.rug.nl/infozip/ (and subdirectories) first.\n\n   IF YOU FIND AN ERROR:  please let us know!  We don't have time to\n   check each and every site personally (or even collectively), so any\n   number of the sites listed below may have moved or disappeared en-\n   tirely.  E-mail to Zip-Bugs@lists.wku.edu and we'll update this file.\n__________________________________________________________________________\n\n\nInfo-ZIP's home WWW site is listed on Yahoo and is at:\n\n   ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html  (master version)\n   http://ftp.info-zip.org/pub/infozip/              (master version)\n   http://www.info-zip.org/\n\nNote that the old sites at http://www.cdrom.com/pub/infozip/ and\nhttp://www.freesoftware.com/pub/infozip are PERMANENTLY BROKEN.  They\ncannot be updated or removed, apparently.\n\nThe Zip and UnZip pages have links to most known mirror sites carrying our\nsource and/or binary distributions, and they generally are more up-to-date\nand have better information than what you are reading:\n\n   ftp://ftp.info-zip.org/pub/infozip/Zip.html\n   ftp://ftp.info-zip.org/pub/infozip/UnZip.html\n\nThe related zlib package by Info-ZIP's Jean-loup Gailly and Mark Adler is at:\n\n   http://www.zlib.net/\n\nSource-code archives for Info-ZIP's portable Zip, UnZip, and related\nutilities:\n\n   zip30.zip         Zip 3.0 (deflation, bzip2, ZIP64 large archives, multi-\n                     volume splits; includes zipnote/zipsplit/zipcloak)\n   zip30.tar.Z       ditto, compress'd tar format\n\n   zip232.zip        Zip 2.32 (deflation; includes zipnote/zipsplit/zipcloak)\n   zip232.tar.Z      ditto, compress'd tar format\n\n   zip11.zip         Zip 1.1 (shrinking, implosion; compatible w. PKUNZIP 1.1)\n   zip11.tar.Z       ditto, compress'd tar format\n\n   unzip60.zip       UnZip 6.0 (all methods[*]; unzip/funzip/unzipsfx/zipgrep)\n   unzip60.tar.gz    ditto, gzip'd tar format\n   unzip60.tar.Z     ditto, compress'd tar format\n\n   unred60.zip       UnZip 6.0 add-on, contains copyrighted unreduce support\n\n   zcrypt29.zip      encryption support for Zip 2.3[**]\n   zcrypt10.zip      encryption support for Zip 1.1\n\n   MacZip106src.zip  contains all the GUI stuff and the project files to build\n                     the MacZip main-app.  To build MacZip successfully, both\n                     the Zip 3.0 and UnZip 6.0 sources are required, too.\n\n   wiz601.zip        WiZ 6.01, Windows 9x/NT GUI front-end for Info-ZIP's DLLs,\n                     as well as the source code and project files for the DLLs,\n                     and static libraries.\n\n[*] Unreducing is disabled by default, but is available as add-on.\n    As of July 2004, Unisys's LZW patent was expired worldwide, and\n    unshrinking is turned on by default since the release of UnZip 5.52.\n    See UnZip's INSTALL file for details.\n\n[**] As of January 2000, US export regulations were amended to allow export\n     of free encryption source code from the US.  As of June 2002, these\n     regulations were further relaxed to allow export of encryption binaries\n     associated with free encryption source code.  The Zip 2.31, UnZip 5.52\n     and Wiz 5.02 archives now include full crypto source code.  As of the\n     Zip 2.31 release, all official binaries include encryption support; the\n     former \"zcr\" archives ceased to exist.\n     (Note that restrictions may still exist in other countries, of course.)\n\nExecutables archives (and related files) for Info-ZIP's software; not all\nof these will be immediately available due to lack of access to appropriate\nsystems on the part of Info-ZIP members.\n\n   zip###x.zip       MSDOS executables and docs\n   zip###x1.zip      OS/2 1.x (16-bit) executables and docs\n   zip###x2.zip      OS/2 2/3/4.x (32-bit) executables and docs\n   zip###xA.zip      Amiga executables and docs\n   zip###xB.zip      BeOS executables and docs\n   zip###xC.zip      VM/CMS executable and docs\n   zip###xK.zip      Tandem NSK executables and docs\n   zip###xM.xmit     MVS classic executable\n   zip###xM-docs.zip MVS classic port, docs only\n   zip###dN.zip      WinNT/Win9x (Intel) DLL, header files, docs\n   zip###xN.zip      WinNT/Win9x (Intel) executables and docs\n   zip###xN-axp.zip  WinNT (Alpha AXP) executables and docs\n   zip###xN-mip.zip  WinNT (MIPS R4000) executables and docs\n   zip###xN-ppc.zip  WinNT (PowerPC) executables and docs\n   zip###xO.zip      IBM OS/390 Open Edition binaries and docs\n   zip###xQ.zip      SMS/QDOS executables and docs\n   zip###xR.zip      Acorn RISC OS executables and docs\n   zip###xT.zip      Atari TOS executables and docs\n   zip###-vms-axp-obj.zip\n                     VMS (Alpha AXP) object libs, link procedure and docs\n   zip###-vms-axp-exe.zip\n                     VMS (Alpha AXP) executables for VMS 6.1 or later and docs\n   zip###-vms-vax-decc-obj.zip\n                     VMS (VAX) object libs (new DEC C), link procedure and docs\n   zip###-vms-vax-decc-exe.zip\n                     VMS (VAX) executables (DEC C) for VMS 6.1 or later; docs\n   zip###-vms-vax-vaxc-obj.zip\n                     VMS (VAX) object libs (old VAX C), link procedure and docs\n   zip###x.hqx       Macintosh BinHex'd executables and docs\n\n   unz###x.exe       MSDOS self-extracting executable (16-bit unzip, ..., docs)\n   unz###x3.exe      MSDOS self-extracting executable (16-, 32-bit unzip, docs)\n   unz###x1.exe      OS/2 1.x (16-bit) self-extracting executables and docs\n   unz###x2.exe      OS/2 2/3/4.x (32-bit) self-extracting executables and docs\n   unz###d2.zip      OS/2 2/3/4.x (32-bit) DLL, header file, demo exe and docs\n   unz###xA.ami      Amiga self-extracting executables and docs\n   unz###xA.lha      Amiga executables and docs, LHa archive\n   unz###xB.sfx      BeOS self-extracting executables and docs\n   unz###xB.tar.gz   BeOS executables and docs, gzip'd tar archive\n   unz###xC.mod      VM/CMS executable module in \"packed\" format\n   unz###xC-docs.zip VM/CMS docs, only\n   unz###xF.zip      FlexOS executable and docs\n   unz###xK.zip      Tandem NSK executable and docs\n   unz###xM.xmit     MVS classic executable\n   unz###xM-docs.zip MVS classic port, docs only\n   unz###dN.zip      NT4/W2K/XP/2K3/W9x (32-bit Intel) DLL, header files, docs\n   unz###xN.exe      NT/2K/XP/2K3/W9x self-extracting i386 executables and docs\n   unz###xN-axp.exe  WinNT (Alpha AXP) self-extracting executables and docs\n   unz###xN-mip.exe  WinNT (MIPS R4000) self-extracting executables and docs\n   unz###xN-ppc.exe  WinNT (PowerPC) self-extracting executables and docs\n   unz###xQ.sfx      SMS/QDOS self-extracting executables and docs\n   unz###xO.tar.Z    IBM OS/390 Open edition (Unix-like), exes and docs\n   unz###xR.exe      Acorn RISC OS self-extracting executables and docs\n   unz###xR.spk      Acorn RISC OS Spark'd executables and docs\n   unz###xT.tos      Atari TOS self-extracting executables and docs\n   unz###x-vms-axp-obj.bck    VMS backup saveset,\n                     contains UnZip (Alpha) obj libs, link procedure, docs\n   unz###x-vms-axp-obj.exe    VMS (Alpha AXP) SFX archive (statically linked),\n                     contains UnZip (Alpha) obj libs, link procedure, docs\n   unz###x-vms-axp-exe.exe    VMS (Alpha AXP) SFX archive (dynamically linked),\n                     contains UnZip (Alpha AXP, DEC C) executables and docs,\n                     smaller than object archive, but requires VMS 6.1\n   unz###x-vms-vax-decc-obj.bck   VMS backup saveset,\n                     contains UnZip (new DEC C) obj libs, link procedure, docs\n   unz###x-vms-vax-decc-obj.exe   VMS (VAX) SFX archive (statically linked),\n                     contains UnZip (new DEC C) obj libs, link procedure, docs\n   unz###x-vms-vax-decc-exe.exe   VMS (VAX) SFX archive (dynamically linked),\n                     contains UnZip (new DEC C) executables and docs,\n                     smaller than object archive, but requires VMS 6.1\n   unz###x-vms-vax-vaxc-obj.bck   VMS backup saveset,\n                     contains UnZip (old VAX C) obj libs, link procedure, docs\n   unz###x-vms-vax-vaxc-obj.exe   VMS (VAX) SFX archive (statically linked),\n                     contains UnZip (old VAX C) obj libs, link procedure, docs\n   unz###x.hqx       Macintosh BinHex'd executables and docs for unzip\n  (unz###x.tar.{Z,gz}  Unix exes/docs for Solaris 2.x, SCO Unix, Linux, etc.,\n                     depending on directory/location; generally only provided\n                     in cases where the OS does *not* ship with a bundled C\n                     compiler)\n\n   MacZip106nc.hqx   Macintosh combined Zip&UnZip application with GUI,\n                     executables and docs (no encryption)\n   MacZip106c.hqx    Macintosh combined Zip&UnZip application with GUI,\n                     executables and docs (with encryption)\n\n   wiz###xN.exe      WiZ #.## 32-bit (Win9x/NT/2K/XP/2K3) app+docs (self-extr.)\n\n   UnzpHist.zip      complete changes-history of UnZip and its precursors\n   ZipHist.zip       complete changes-history of Zip\n\nftp/web sites for the US-exportable sources and executables:\n\n   NOTE:  Look for the Info-ZIP file names given above (not PKWARE or third-\n   party stuff) in the following locations.  Some sites like to use slightly\n   different names, such as zip-#.##.tar.gz instead of zip###.tar.Z.\n\n   http://sourceforge.net/project/showfiles.php?group_id=118012\n                                               [THE INFO-ZIP SOURCES HOME SITE]\n\n   ftp://ftp.info-zip.org/pub/infozip/                 [THE INFO-ZIP HOME SITE]\n   ftp://sunsite.doc.ic.ac.uk/packages/zip/    [MIRRORS THE INFO-ZIP HOME SITE]\n   ftp://unix.hensa.ac.uk/mirrors/uunet/pub/archiving/zip/\n\n   ftp://ftp.cmdl.noaa.gov/aerosol/doc/archiver/{all,dos,os2,mac,vax_alpha}/\n   ftp://garbo.uwasa.fi/pc/arcers/                    [AND OTHER GARBO MIRRORS]\n   ftp://garbo.uwasa.fi/unix/arcers/                  [AND OTHER GARBO MIRRORS]\n   ftp://ftp.elf.stuba.sk/pub/pc/pack/                [AND OTHER STUBA MIRRORS]\n   ftp://ftp-os2.cdrom.com/pub/os2/archiver/\n   ftp://ftp-os2.nmsu.edu/os2/archiver/\n   ftp://ftp.informatik.tu-muenchen.de/pub/comp/os/os2/archiver/\n   ftp://sumex-aim.stanford.edu/info-mac/cmp/\n   ftp://ftp.wustl.edu/pub/aminet/util/arc/          [AND OTHER AMINET MIRRORS]\n   ftp://atari.archive.umich.edu/pub/Archivers/       [AND OTHER UMICH MIRRORS]\n   http://www.umich.edu/~archive/atari/Archivers/\n   ftp://jake.educom.com.au/pub/infozip/acorn/                  [Acorn RISC OS]\n   http://www.sitec.net/maczip/                                   [MacZip port]\n\nftp/web sites for the encryption and decryption sources and/or executables:\n\n   Outside the US:\n      ftp://ftp.info-zip.org/pub/infozip/   [THE INFO-ZIP HOME SITE]\n      ftp://ftp.icce.rug.nl/infozip/        [THE INFO-ZIP ENCRYPTION HOME SITE]\n      ftp://ftp.elf.stuba.sk/pub/pc/pack/\n      ftp://garbo.uwasa.fi/pc/arcers/\n      ftp://ftp.inria.fr/system/arch-compr/\n      ftp://ftp.leo.org/pub/comp/os/os2/leo/archiver/\n        (mail server at ftp-mailer@ftp.leo.org)\n\n      ftp://ftp.win.tue.nl/pub/compression/zip/\n      ftp://ftp.uni-erlangen.de/pub/pc/msdos/arc-utils/zip/\n\n\nThe primary distribution site for the MacZip port can be found at:\n\n   http://www.sitec.net/maczip/\n\nftp sites for VMS-format Zip and UnZip packages (sources, object files and\nexecutables, no encryption/decryption--see also \"Mail servers\" section below):\n\n   ftp.spc.edu [192.107.46.27] and ftp.wku.edu:\n\n   [.MACRO32]AAAREADME.TXT\n   [.MACRO32.SAVESETS]UNZIP.BCK  or  UNZIP.ZIP  (if already have older version)\n   [.MACRO32.SAVESETS]ZIP.ZIP\n\nTo find other ftp/web sites:\n\n   The \"archie\" ftp database utility can be used to find an ftp site near\n   you (although the command-line versions always seem to find old ver-\n   sions...the `FTPsearch' server at http://ftpsearch.ntnu.no/ftpsearch\n   --formerly `Archie 95'--is quite up-to-date, however).  Or check a stan-\n   dard WWW search engine like AltaVista (http://www.altavista.digital.com/)\n   or Yahoo (http://www.yahoo.com/).  If you don't know how to use these,\n   DON'T ASK US--read the web sites' help pages or check the Usenet groups\n   news.announce.newusers or news.answers or some such, or ask your system\n   administrator.\n\nMail servers:\n\n   To get the encryption sources by e-mail, send the following commands\n   to ftp-mailer@informatik.tu-muenchen.de:\n\n      get /pub/comp/os/os2/archiver/zcrypt29.zip\n      quit\n\n   To get the VMS Zip/UnZip package by e-mail, send the following\n   commands in the body of a mail message to fileserv@wku.edu (the\n   \"HELP\" command is also accepted):\n\n      SEND FILESERV_TOOLS\n      SEND UNZIP\n      SEND ZIP\n\n   To get Atari executables by e-mail, send a message to\n   atari@atari.archive.umich.edu for information about the mail server.\n__________________________________________________________________________\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/Contents",
    "content": "Contents of the \"acorn\" subdirectory for UnZip 5.4 and later:\n\n  acorn.c.acorn     Acorn-specific resources\n  acorn.c.riscos    mainly file-handling routines for FileCore-based filesystems\n  acorn.Contents    this file\n  acorn.GMakeFile   Makefile for gcc\n  acorn.h.riscos\n  acorn.h.swiven\n  acorn.makefile    Makefile script for default Acorn C compiler\n  acorn.README      notes about Acorn-specific features\n  acorn.RunMe1st    Obey file to move files into suitable place for compilation\n                    on RISC OS machines\n  acorn.s.swiven    SWI veneers\n  acorn.srcrename   small executable that converts files from Unix style to\n                    RISC OS style, used by RunMe1st\n\nNotes:\n\n  Use the \"RunMe1st\" file (it is an Obey file) to convert all the files from\n  \"filename/[chs]\" to \"[chs].filename\" (so that UnZip could be easily compiled\n  under RISC OS). It will also set the correct makefile.\n\n  To compile just set the CSD to the main UnZip directory and run 'amu'.\n\n  Currently only the Acorn C V5 compiler has been tested but probably also\n  Acorn C V4 and the Acorn Assembler V2 will be able to compile UnZip.\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/GMakefile",
    "content": "# Makefile for UnZip, UnZipSFX, ZipInfo and fUnZip (5.53 or later)\n# using gcc 2.95.4 (or later).\n# You may look at <URL:http://hard-mofo.dsvr.net/gcc/> for an up-to-date\n# gcc port.\n\nCC   = gcc -mlibscl\nBIND = $(CC)\nAS   = $(CC) -c\nASM  = as\nSQUEEZE = squeeze -v\nE    =\n\n# flags\n#   CFLAGS    flags for C compile\n#   LFLAGS1   flags after output file spec, before obj file list\n#   LFLAGS2   flags after obj file list (libraries, etc)\n#\nLIB      =\nCFLAGS   = -O2 -mthrowback -DNO_STRNICMP\nASMFLAGS = -throwback -objasm -upper\nLFLAGS1  =\nLFLAGS2  = $(LIB)\n\n# object file lists\nOBJS1 = o.unzip o.crc32 o.crypt o.envargs o.explode\nOBJS2 = o.extract o.fileio o.globals o.inflate o.list o.match\nOBJS3 = o.process o.ttyio o.unreduce o.unshrink o.zipinfo\nOBJS  = $(OBJS1) $(OBJS2) $(OBJS3) o.riscos o.swiven o.acorn\nOBJF  = o.funzip o.crc32 o.cryptf o.globalsf o.inflatef o.ttyiof \\\n\to.riscos o.swiven\nOBJX  = o.unzipsfx o.crc32  o.crypt_ o.extract_ o.fileio_ o.globals_ \\\n\to.inflate_ o.match_ o.process_ o.ttyio_ o.acorn_ o.swiven o.riscos_\n\nUNZIP_H = h.unzip h.unzpriv h.globals acorn.h.riscos acorn.h.swiven\n\nall:\t  unzip funzip unzipsfx\n\n\ninstall:  unzip funzip unzipsfx\n\t$(SQUEEZE) unzip %.unzip\n\t$(SQUEEZE) funzip %.funzip\n\t$(SQUEEZE) unzipsfx unzipsfx\n\tcopy %.unzip %.zipinfo ~CVF\n\n# rules for unzip and funzip\no.crc32:\tc.crc32 $(UNZIP_H) h.zip h.crc32\n\t$(CC) $(CFLAGS) -c c.crc32 -o o.crc32\no.crypt:\tc.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio\n\t$(CC) $(CFLAGS) -c c.crypt -o o.crypt\no.envargs:\tc.envargs $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.envargs -o o.envargs\no.explode:\tc.explode $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.explode -o o.explode\no.extract:\tc.extract $(UNZIP_H) h.crc32 h.crypt\n\t$(CC) $(CFLAGS) -c c.extract -o o.extract\no.fileio:\tc.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic\n\t$(CC) $(CFLAGS) -c c.fileio -o o.fileio\no.funzip:\tc.funzip $(UNZIP_H) h.crc32 h.crypt h.ttyio\n\t$(CC) $(CFLAGS) -c c.funzip -o o.funzip\no.globals:\tc.globals $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.globals -o o.globals\no.inflate:\tc.inflate h.inflate $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.inflate -o o.inflate\no.list:\t\tc.list $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.list -o o.list\no.match:\tc.match $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.match -o o.match\no.process:\tc.process $(UNZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -c c.process -o o.process\no.ttyio:\tc.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio\n\t$(CC) $(CFLAGS) -c c.ttyio -o o.ttyio\no.unreduce:\tc.unreduce $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.unreduce -o o.unreduce\no.unshrink:\tc.unshrink $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.unshrink -o o.unshrink\no.unzip:\tc.unzip $(UNZIP_H) h.crypt h.unzvers h.consts\n\t$(CC) $(CFLAGS) -c c.unzip -o o.unzip\no.zipinfo:\tc.zipinfo $(UNZIP_H)\n\t$(CC) $(CFLAGS) -c c.zipinfo -o o.zipinfo\n\no.crypt_:\tc.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio\n\t$(CC) $(CFLAGS) -DSFX -c c.crypt -o o.crypt_\no.extract_:\tc.extract $(UNZIP_H) h.crc32 h.crypt\n\t$(CC) $(CFLAGS) -DSFX -c c.extract -o o.extract_\no.fileio_:\tc.fileio $(UNZIP_H) h.crc32 h.crypt h.ttyio h.ebcdic\n\t$(CC) $(CFLAGS) -DSFX -c c.fileio -o o.fileio_\no.globals_:\tc.globals $(UNZIP_H)\n\t$(CC) $(CFLAGS) -DSFX -c c.globals -o o.globals_\no.inflate_:\tc.inflate h.inflate $(UNZIP_H) h.crypt\n\t$(CC) $(CFLAGS) -DSFX -c c.inflate -o o.inflate_\no.match_:\tc.match $(UNZIP_H)\n\t$(CC) $(CFLAGS) -DSFX -c c.match -o o.match_\no.process_:\tc.process $(UNZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -DSFX -c c.process -o o.process_\no.ttyio_:\tc.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio\n\t$(CC) $(CFLAGS) -DSFX -c c.ttyio -o o.ttyio_\n\no.unzipsfx:\tc.unzip $(UNZIP_H) h.crypt h.unzvers h.consts\n\t$(CC) $(CFLAGS) -DSFX -c c.unzip -o o.unzipsfx\n\no.cryptf:\tc.crypt $(UNZIP_H) h.zip h.crypt h.crc32 h.ttyio\n\t$(CC) $(CFLAGS) -DFUNZIP -c c.crypt -o o.cryptf\no.globalsf:\tc.globals $(UNZIP_H)\n\t$(CC) $(CFLAGS) -DFUNZIP -c c.globals -o o.globalsf\no.inflatef:\tc.inflate h.inflate $(UNZIP_H) h.crypt\n\t$(CC) $(CFLAGS) -DFUNZIP -c c.inflate -o o.inflatef\no.ttyiof:\tc.ttyio $(UNZIP_H) h.zip h.crypt h.ttyio\n\t$(CC) $(CFLAGS) -DFUNZIP -c c.ttyio -o o.ttyiof\n\no.acorn:\tacorn.c.acorn $(UNZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c acorn.c.acorn\no.acorn_:\tacorn.c.acorn $(UNZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.acorn_ acorn.c.acorn\n\no.riscos:\tacorn.c.riscos $(UNZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c acorn.c.riscos\no.riscos_:\tacorn.c.riscos $(UNZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c -DSFX -DSFX_EXDIR -o o.riscos_ acorn.c.riscos\n\no.swiven:\tacorn.s.swiven\n\t$(ASM) $(ASMFLAGS) acorn.s.swiven -o o.swiven\n\nunzip:\t  $(OBJS)\n\t  $(BIND) -o unzip$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)\nfunzip:\t  $(OBJF)\n\t  $(BIND) -o funzip$(E) $(LFLAGS1) $(OBJF) $(LFLAGS2)\nunzipsfx: $(OBJX)\n\t  $(BIND) -o unzipsfx$(E) $(LFLAGS1) $(OBJX) $(LFLAGS2)\n\nclean:\n\tremove unzip\n\tremove funzip\n\tremove zipinfo\n\tremove unzipsfx\n\tcreate o.!fake! 0\n\twipe o.* ~cf\n\n# end of Makefile\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/ReadMe",
    "content": "Acorn-specific usage instructions\n---------------------------------\n\nAs zipfiles can come from a variety of sources apart from Acorn machines,\nconsideration had to be given to the handling of dot-extensions, e.g.\n\"DOSFILE.TXT\", \"unix-filename.tar.gz\". These are extracted as \"DOSFILE/TXT\"\nand \"unix-filename/tar/gz\"; their names may or may not be truncated,\ndepending on where the files are being created: what filing system and, for\nFilecore-based filing systems such as ADFS or an IDEFS or SCSIFS, which\ndisk/partition format (names will not be truncated if you're using E+ or F+).\n\nWhere truncation occurs, you must be REALLY careful about extracting files\nfrom archives. The files\n\n    dummy_source.c and dummy_source.h\n\nwill both be extracted as\n\n    dummy_sour\n\nUnZip will prompt you for confirmation of the over-writing of these files,\nbut you must be really careful unless you wish to lose files! Also, because\nUnZip is a unix-ported program, the filenames are CASE SENSITIVE.\n\n    *unzip new/zip newfile\n\nwill extract 'newfile', but not 'NewFile', 'NEWFILE' or any other\ncombinations. However, you can use the -C option to force operations to\ndisregard the case of filenames.\n\nThe Acorn UnZip port has an additional feature to cope with the extraction of\nfiles containing 'c' code. As you may be aware, Acorn Desktop C requires all\nfiles called \"foo.c\" to be renamed to \"c.foo\", ie \"foo\" in a directory called\n\"c\".\n\nThere are two ways of using this feature.\n\n- The old way: use a colon-separated environment variable named \"Unzip$Exts\".\n\n  Any extensions found in this variable will be extracted to directories\n  named after the extension, with the extension stripped. For example:\n\n    *Set Unzip$Exts \"c:h:o:s\"\n    *unzip foo/zip\n\n- The new way: use the -/ option. For example:\n\n  Any extensions found in the parameter for this option will be extracted to\n  directories named after the extension, with the extension stripped. For\n  example:\n\n    *unzip -/c:h:o:s foo/zip\n\nIf foo/zip contains a file named \"foo.c\", this file will be written as \"foo\"\nin directory \"c\". This can be used to include \"c:h:o:s:txt\" to pull all the\ntext files out to a separate directory.\n\nUnZip fully supports SparkFS Extra Field. This means that zipfiles created\nwith SparkFS or Zip (on RISC OS) will be correctly unzipped, including\nfiletypes.\n\nUnZipSFX can be used to create self-extracting archives. To use it, just\ncreate a common zipfile using Zip (or SparkFS), then load the UnZipSFX\nexecutable into an editor (eg. Edit, Zap), go with the caret the end of the\nfile (using CTRL-CursorDown) and drag the zipfile to the editor window (in\nother words, append the zipfile to the UnZipSFX executable). Now, saving the\nresulting file (with filetype Absolute (&FF8)), you have a self-extracting\narchive (ie. double-clicking on it will unzip the contents of the original\nzipfile to the currently selected directory).\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/RunMe1st",
    "content": "| This Obey file prepares the UnZip port for a Desktop C re-compile.\n| Run it and it will copy all the needed files into the correct\n| place.\n\n| Set the correct type of 'srcrename' so that the only requirement\n| for the user is to set 'RunMe1st' to Obey\nSetType <Obey$Dir>.srcrename FF8\n\n| Run 'srcrename' on the main UnZip directory with recursion enabled\n/<Obey$Dir>.srcrename -r -e c:h:s:o <Obey$Dir>.^\n\n| Create the 'o' directory\nCDir <Obey$Dir>.^.o\n\n| Put the Makefile in its correct place and set the correct filetype\nSetType <Obey$Dir>.makefile FE1\nCopy <Obey$Dir>.makefile <Obey$Dir>.^.makefile ~C ~V F\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/acorn.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  acorn.c\n\n  RISCOS-specific routines for use with Info-ZIP's UnZip 5.2 and later.\n\n  Contains:  do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             mkdir()\n             setRISCOSexfield()\n             printRISCOSexfield()\n             close_outfile()\n             stamp_file()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"^.unzip.h\"\n#include \"riscos.h\"\n\n#define FTYPE_FFF (1<<17)      /* set filetype to &FFF when extracting */\n\n#ifdef WILD_STOP_AT_DIR\n#  define WESEP     , (oU.W_flag ? '.' : '\\0')\n#else\n#  define WESEP\n#endif\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\nstatic int has_mimemap = -1;   /* used in mimemap() */\n\nextern int mkdir(const char *path, int mode);\nstatic int has_NFS_ext(const char *name);\nstatic void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark);\n#ifdef DEBUG\nstatic void printRISCOSexfield(int isdir, ZCONST void *extra_field);\n#endif\nstatic int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);\nstatic int mimemap(const char *name);\n\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = (ZCONST char *)strrchr(wildspec, '.')) ==\n            (ZCONST char *)NULL)\n        {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                if (file->d_name[0] == '/' && wildname[0] != '/')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL)\n        if (match(file->d_name, wildname, 0 WESEP)) {   /* 0 == case sens. */\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n\n    closedir(wild_dir); /* have read at least one dir entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n/**************************/\n/* Function has_NFS_ext() */\n/**************************/\n\nstatic int has_NFS_ext(const char* name)\n{\n  int i = strlen(name) - 4;\n\n  return (i >= 0 && name[i] == ',' && (i > 0 || name[i-1]=='/') &&\n          isxdigit(name[i+1]) && isxdigit(name[i+2]) && isxdigit(name[i+3]));\n} /* end function has_NFS_ext() */\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case ACORN_:\n        case UNIX_:\n        case VMS_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                break;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                   VMS (and probably others ??) leave 0 in the upper 16-bit\n                   part of the external_file_attributes field. Instead, they\n                   store file permission attributes in some extra field.\n                   As a work-around, we search for the presence of one of\n                   these extra fields and fall back to the MSDOS compatible\n                   part of external_file_attributes if one of the known\n                   e.f. types has been detected.\n                   Later, we might implement extraction of the permission\n                   bits from the VMS extra field. But for now, the work-around\n                   should be sufficient to provide \"readable\" extracted files.\n                   (For ASI Unix e.f., an experimental remap of the e.f.\n                   mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    break;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                break;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    G.pInfo->file_attr&=0xFFFF;\n\n    G.pInfo->file_attr|=(0xFFDu<<20);\n\n    if (has_NFS_ext(G.filename)) {\n      int ftype=strtol(G.filename+strlen(G.filename)-3,NULL,16)&0xFFF;\n\n      G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (ftype<<20);\n    } else {\n      int type = mimemap(G.filename);\n      if (type == -1)\n        type = (G.crec.internal_file_attributes & 1) ? 0xFFF : 0xFFD;\n      G.pInfo->file_attr = (G.pInfo->file_attr & 0x000FFFFF) | (type<<20);\n    }\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n/************************/\n/*  Function mimemap()  */\n/************************/\n\nstatic int mimemap(const char *name)\n{\n  const char *ext = name;\n  int type;\n\n  if (has_mimemap < 0)\n    has_mimemap =\n    !(SWI_OS_CLI(\"%RMEnsure MimeMap 0.05 RMLoad System:Modules.Network.MimeMap\")\n      || SWI_OS_CLI(\"%RMEnsure MimeMap 0.05\"));\n\n  if (!has_mimemap)\n    return -1; /* no MimeMap module; fall back on text flag test */\n\n  do {\n    while (*ext && *ext!='.')\n      ext++;\n    if (!*ext)\n      return -1; /* no suitable extension; fallback */\n    type = SWI_MimeMap_Translate(ext++);\n  } while (type == -1);\n\n  return type;\n}\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n    char *checkswap=NULL;          /* pointer the the extension to check */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in RISCOS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                checkswap=NULL;  /* reset checking at start of new leafname */\n                break;\n\n            case '.':\n                *pp++ = '/';\n                checkswap=pp;\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n            case ' ':             /* change spaces to hard-spaces */\n                *pp++ = 160;      /* (ISO 8859-1 Latin-1 codepage) */\n                break;\n\n            /* The following substitutions, unless stated otherwise, follow\n             * those for DOSFS. They translate special symbols into other\n             * characters which have no special meaning to RISC OS. */\n            case '#': *pp++ = '?'; break;   /* single-char wildcard */\n            case '&': *pp++ = '+'; break;\n            case '@': *pp++ = '='; break;\n            case '%': *pp++ = ';'; break;\n            case '$': *pp++ = '<'; break;\n            case '^': *pp++ = '>'; break;   /* parent-dir reference */\n\n            /* The following substitutions deal with the remaining special\n             * symbols. ('.' is handled above.) */\n            case '*': *pp++ = 0xD7; break;  /* Latin-1 'multiply' */\n            case '\"': *pp++ = '~'; break;\n            case ':': *pp++ = ';'; break;\n            case '\\\\': *pp++ = '/'; break;\n            case '|': *pp++ = 0xA6; break;  /* Latin-1 'broken bar' */\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    if (checkswap!=NULL) {\n        if (checkext(checkswap)) {\n            if ((error = checkdir(__G__ checkswap, APPEND_DIR)) > 1)\n                return error;\n            *(checkswap-1)=0;    /* remove extension from pathcomp */\n        }\n    }\n\n    if (!uO.acorn_nfs_ext && has_NFS_ext(pathcomp)) {\n      /* remove the filetype extension unless requested otherwise */\n      /* the filetype should be already set by mapattr() */\n      pathcomp[strlen(pathcomp)-4]=0;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check: need to append '/', at least one-char name, '\\0' */\n        if ((end-buildpath) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n        if (stat(buildpath, &G.statbuf)) {      /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                fflush(stderr);\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '.';    /************* was '/' *************/\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == '.') {    /****** was '/' ********/\n                tmproot[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || isshexp(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[rootlen++] = '.';   /*********** was '/' *************/\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/********************/\n/* Function mkdir() */\n/********************/\n\nint mkdir(path, mode)\n    const char *path;\n    int mode;   /* ignored */\n/*\n * returns:   0 - successful\n *           -1 - failed (errno not set, however)\n */\n{\n    return (SWI_OS_File_8((char *)path) == NULL)? 0 : -1;\n}\n\n\n\n\n/*********************************/\n/* extra_field-related functions */\n/*********************************/\n\nstatic void setRISCOSexfield(ZCONST char *path, ZCONST void *ef_spark)\n{\n  if (ef_spark!=NULL) {\n    extra_block *block=(extra_block *)ef_spark;\n    SWI_OS_File_1((char *)path,block->loadaddr,block->execaddr,block->attr);\n  }\n}\n\n#ifdef DEBUG\nstatic void printRISCOSexfield(int isdir, ZCONST void *extra_field)\n{\n extra_block *block=(extra_block *)extra_field;\n printf(\"\\n  This file has RISC OS file informations in the local extra field.\\n\");\n\n if (isdir) {\n/*   I prefer not to print this string... should change later... */\n/*   printf(\"  The file is a directory.\\n\");*/\n } else if ((block->loadaddr & 0xFFF00000) != 0xFFF00000) {\n   printf(\"  Load address: %.8X\\n\",block->loadaddr);\n   printf(\"  Exec address: %.8X\\n\",block->execaddr);\n } else {\n   /************* should change this to use OS_FSControl 18 to get filetype string ************/\n   char tmpstr[16];\n   char ftypestr[32];\n   int flen;\n   sprintf(tmpstr,\"File$Type_%03x\",(block->loadaddr & 0x000FFF00) >> 8);\n   if (SWI_OS_ReadVarVal(tmpstr,ftypestr,32,&flen)==NULL) {\n     ftypestr[flen]=0;\n     printf(\"  Filetype: %s (&%.3X)\\n\",ftypestr,(block->loadaddr & 0x000FFF00) >> 8);\n   } else {\n     printf(\"  Filetype: &%.3X\\n\",(block->loadaddr & 0x000FFF00) >> 8);\n   }\n }\n printf(\"  Access: \");\n if (block->attr & (1<<3))\n   printf(\"L\");\n if (block->attr & (1<<0))\n   printf(\"W\");\n if (block->attr & (1<<1))\n   printf(\"R\");\n printf(\"/\");\n if (block->attr & (1<<4))\n   printf(\"w\");\n if (block->attr & (1<<5))\n   printf(\"r\");\n printf(\"\\n\\n\");\n}\n#endif /* DEBUG */\n\n\n/**********************************************/\n/* internal help function for time conversion */\n/**********************************************/\nstatic int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut)\n{\n   unsigned timlo;      /* 3 lower bytes of acorn file-time plus carry byte */\n   unsigned timhi;      /* 2 high bytes of acorn file-time */\n\n   timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U;\n   timhi = ((unsigned)ut >> 24);\n   timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);\n   if (timhi & 0xffff0000U)\n       return 1;        /* calculation overflow, do not change time */\n\n   /* insert the five time bytes into loadaddr and execaddr variables */\n   *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);\n   *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU);\n\n   return 0;            /* subject to future extension to signal overflow */\n}\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n  zvoid *spark_ef;\n\n  fclose(G.outfile);\n\n  if ((spark_ef = getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n      != NULL) {\n    setRISCOSexfield(G.filename, spark_ef);\n  } else {\n    unsigned int loadaddr, execaddr;\n    int attr;\n    int mode=G.pInfo->file_attr&0xffff;   /* chmod equivalent mode */\n\n    time_t m_time;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                              G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n             & EB_UT_FL_MTIME))\n        {\n            TTrace((stderr, \"close_outfile:  Unix e.f. modif. time = %ld\\n\",\n              z_utime.mtime));\n            m_time = z_utime.mtime;\n        } else\n#endif /* USE_EF_UT_TIME */\n            m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n\n    /* set the file's time-stamp and attributes */\n    SWI_OS_File_5(G.filename, NULL, &loadaddr, NULL, NULL, &attr);\n\n    if (uO.D_flag <= 1)\n        /* set the file's modification time */\n        uxtime2acornftime(&execaddr, &loadaddr, m_time);\n\n    loadaddr = (loadaddr & 0xfff000ffU) |\n               ((G.pInfo->file_attr&0xfff00000) >> 12);\n\n    attr=(attr&0xffffff00) | ((mode&0400) >> 8) | ((mode&0200) >> 6) |\n                             ((mode&0004) << 2) | ((mode&0002) << 4);\n\n    SWI_OS_File_1(G.filename, loadaddr, execaddr, attr);\n  }\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    unsigned int loadaddr, execaddr;\n    int attr;\n\n    /* set the file's modification time */\n    if (SWI_OS_File_5((char *)fname, NULL, &loadaddr, NULL, NULL, &attr)\n        != NULL)\n        return -1;\n\n    if (uxtime2acornftime(&execaddr, &loadaddr, modtime) != 0)\n        return -1;\n\n    return (SWI_OS_File_1((char *)fname, loadaddr, execaddr, attr) == NULL) ?\n           0 : -1;\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  ifdef __CC_NORCROFT\n      \"Norcroft \", \"cc\",\n#  else\n      \"cc\", \"\",\n#  endif\n#endif\n\n      \"RISC OS\",\n\n      \" (Acorn Computers Ltd)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/riscos.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* riscos.c */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n/* #define NO_UNZIPH_STUFF */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"riscos.h\"\n\n#define MAXEXT 16\n\nchar *exts2swap = NULL; /* Extensions to swap (actually, directory names) */\n\nint stat(char *filename,struct stat *res)\n{\n int attr;              /* object attributes */\n unsigned int load;     /* load address */\n unsigned int exec;     /* exec address */\n int type;              /* type: 0 not found, 1 file, 2 dir, 3 image */\n\n if (!res)\n   return -1;\n\n if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL)\n   return -1;\n\n if (type==0)\n   return -1;\n\n res->st_dev=0;\n res->st_ino=0;\n res->st_nlink=0;\n res->st_uid=1;\n res->st_gid=1;\n res->st_rdev=0;\n res->st_blksize=1024;\n\n res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) |\n                ((attr & 0020) >> 2) | ((attr & 0040) >> 4);\n\n switch (type) {\n   case 1:                        /* File */\n    res->st_mode |= S_IFREG;\n    break;\n   case 2:                        /* Directory */\n    res->st_mode |= S_IFDIR | 0700;\n    break;\n   case 3:                        /* Image file */\n    if (uO.scanimage)\n      res->st_mode |= S_IFDIR | 0700;\n    else\n      res->st_mode |= S_IFREG;\n    break;\n }\n\n if ((((unsigned int) load) >> 20) == 0xfff) {     /* date stamped file */\n   register unsigned int t1, t2, tc;\n\n   t1 = (unsigned int) (exec);\n   t2 = (unsigned int) (load & 0xff);\n\n   tc = 0x6e996a00U;\n   if (t1 < tc)\n     t2--;\n   t1 -= tc;\n   t2 -= 0x33;          /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */\n\n   t1 = (t1 / 100) + (t2 * 42949673U);  /* 0x100000000 / 100 = 42949672.96 */\n   t1 -= (t2 / 25);             /* compensate for .04 error */\n\n   res->st_atime = res->st_mtime = res->st_ctime = t1;\n }\n else\n   res->st_atime = res->st_mtime = res->st_ctime = 0;\n\n return 0;\n}\n\n#ifndef SFX\n\nDIR *opendir(char *dirname)\n{\n DIR *thisdir;\n int type;\n int attr;\n os_error *er;\n\n thisdir=(DIR *)malloc(sizeof(DIR));\n if (thisdir==NULL)\n   return NULL;\n\n thisdir->dirname=(char *)malloc(strlen(dirname)+1);\n if (thisdir->dirname==NULL) {\n   free(thisdir);\n   return NULL;\n }\n\n strcpy(thisdir->dirname,dirname);\n if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.')\n   thisdir->dirname[strlen(thisdir->dirname)-1]=0;\n\n if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL ||\n     type<=1 || (type==3 && !uO.scanimage))\n {\n   free(thisdir->dirname);\n   free(thisdir);\n   return NULL;\n }\n\n thisdir->buf=malloc(DIR_BUFSIZE);\n if (thisdir->buf==NULL) {\n   free(thisdir->dirname);\n   free(thisdir);\n   return NULL;\n }\n\n thisdir->size=DIR_BUFSIZE;\n thisdir->offset=0;\n thisdir->read=0;\n\n return thisdir;\n}\n\nstruct dirent *readdir(DIR *d)\n{\n static struct dirent dent;\n\n if (d->read==0) {    /* no more objects read in the buffer */\n   if (d->offset==-1) {    /* no more objects to read */\n     return NULL;\n   }\n\n   d->read=255;\n   if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL)\n     return NULL;\n\n   if (d->read==0) {\n     d->offset=-1;\n     return NULL;\n   }\n   d->read--;\n   d->act=(char *)d->buf;\n }\n else {     /* some object is ready in buffer */\n   d->read--;\n   d->act=(char *)(d->act+strlen(d->act)+1);\n }\n\n strcpy(dent.d_name,d->act);\n dent.d_namlen=strlen(dent.d_name);\n\n /* If we're returning the last item, check if there are any more.\n  * If there are, nothing will happen; if not, then d->offset = -1 */\n if (!d->read)\n   SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,0,NULL);\n\n return &dent;\n}\n\nvoid closedir(DIR *d)\n{\n if (d->buf!=NULL)\n   free(d->buf);\n if (d->dirname!=NULL)\n   free(d->dirname);\n free(d);\n}\n\nint unlink(f)\nchar *f;                /* file to delete */\n/* Delete the file *f, returning non-zero on failure. */\n{\n os_error *er;\n char canon[256];\n int size=255;\n\n er=SWI_OS_FSControl_37(f,canon,&size);\n if (er==NULL) {\n   er=SWI_OS_FSControl_27(canon,0x100);\n }\n else {\n   er=SWI_OS_FSControl_27(f,0x100);\n }\n return (int)er;\n}\n\nint rmdir(char *d)\n{\n int objtype;\n char *s;\n int len;\n\n len = strlen(d);\n if ((s = malloc(len + 1)) == NULL)\n   return -1;\n\n strcpy(s,d);\n if (s[len-1]=='.')\n   s[len-1]=0;\n\n if (SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL)!=NULL) {\n   free(s);\n   return -1;\n }\n if (objtype<2 || (!uO.scanimage && objtype==3)) {\n/* this is a file or it doesn't exist */\n   free(s);\n   return -1;\n }\n if (SWI_OS_File_6(s)!=NULL) {\n   free(s);\n   return -1;\n }\n free(s);\n return 0;\n}\n\n#endif /* !SFX */\n\nint chmod(char *file, int mode)\n{\n/*************** NOT YET IMPLEMENTED!!!!!! ******************/\n/* I don't know if this will be needed or not... */\n file=file;\n mode=mode;\n return 0;\n}\n\nvoid setfiletype(char *fname,int ftype)\n{\n char str[256];\n sprintf(str,\"SetType %s &%3.3X\",fname,ftype);\n SWI_OS_CLI(str);\n}\n\nvoid getRISCOSexts(char *envstr)\n{\n char *envptr;                               /* value returned by getenv */\n\n envptr = getenv(envstr);\n if (envptr == NULL || *envptr == 0) return;\n\n exts2swap=malloc(1+strlen(envptr));\n if (exts2swap == NULL)\n   return;\n\n strcpy(exts2swap, envptr);\n}\n\nint checkext(char *suff)\n{\n register char *extptr = exts2swap ? exts2swap : \"\";\n register char *suffptr;\n register int e,s;\n\n while(*extptr) {\n   suffptr=suff;\n   e=*extptr; s=*suffptr;\n   while (e && e!=':' && s && s!='.' && s!='/' && e==s) {\n     e=*++extptr; s=*++suffptr;\n   }\n   if (e==':') e=0;\n   if (s=='.' || s=='/') s=0;\n   if (!e && !s) {\n     return 1;\n   }\n   while(*extptr!=':' && *extptr!='\\0')    /* skip to next extension */\n     extptr++;\n   if (*extptr!='\\0')\n     extptr++;\n }\n return 0;\n}\n\nvoid swapext(char *name, char *exptr)\n{\n char ext[MAXEXT];\n register char *p1=exptr+1;\n register char *p2=ext;\n int extchar=*exptr;\n\n while(*p1 && *p1!='.' && *p1!='/')\n   *p2++=*p1++;\n *p2=0;\n p2=exptr-1;\n p1--;\n while(p2 >= name)\n   *p1--=*p2--;\n p1=name;\n p2=ext;\n while(*p2)\n   *p1++=*p2++;\n *p1=(extchar=='/'?'.':'/');\n}\n\nvoid remove_prefix(void)\n{\n SWI_DDEUtils_Prefix(NULL);\n}\n\nvoid set_prefix(void)\n{\n char *pref;\n int size=0;\n\n if (SWI_OS_FSControl_37(\"@\",pref,&size)!=NULL)\n   return;\n\n size=1-size;\n\n if (pref=malloc(size),pref!=NULL) {\n if (SWI_OS_FSControl_37(\"@\",pref,&size)!=NULL) {\n   free(pref);\n   return;\n }\n\n if (SWI_DDEUtils_Prefix(pref)==NULL) {\n   atexit(remove_prefix);\n }\n\n free(pref);\n }\n}\n\n#ifdef localtime\n#  undef localtime\n#endif\n\n#ifdef gmtime\n#  undef gmtime\n#endif\n\n/* Acorn's implementation of localtime() and gmtime()\n * doesn't consider the timezone offset, so we have to\n * add it before calling the library functions\n */\n\nstruct tm *riscos_localtime(const time_t *timer)\n{\n time_t localt=*timer;\n\n localt+=SWI_Read_Timezone()/100;\n\n return localtime(&localt);\n}\n\nstruct tm *riscos_gmtime(const time_t *timer)\n{\n time_t localt=*timer;\n\n localt+=SWI_Read_Timezone()/100;\n\n return gmtime(&localt);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/riscos.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* riscos.h */\n\n#ifndef __riscos_h\n#define __riscos_h\n\n#include <time.h>\n\ntypedef struct {\n  int errnum;\n  char errmess[252];\n} os_error;\n\n#ifndef __swiven_h\n#  include \"swiven.h\"\n#endif\n\n#define MAXPATHLEN 256\n#define MAXFILENAMELEN 64  /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */\n#define DIR_BUFSIZE 1024   /* this should be enough to read a whole E-Format directory */\n\nstruct stat {\n  unsigned int st_dev;\n  int st_ino;\n  unsigned int st_mode;\n  int st_nlink;\n  unsigned short st_uid;\n  unsigned short st_gid;\n  unsigned int st_rdev;\n  unsigned int st_size;\n  unsigned int st_blksize;\n  time_t st_atime;\n  time_t st_mtime;\n  time_t st_ctime;\n};\n\ntypedef struct {\n  char *dirname;\n  void *buf;\n  int size;\n  char *act;\n  int offset;\n  int read;\n} DIR;\n\n\nstruct dirent {\n  unsigned int d_off;          /* offset of next disk directory entry */\n  int d_fileno;                /* file number of entry */\n  size_t d_reclen;             /* length of this record */\n  size_t d_namlen;             /* length of d_name */\n  char d_name[MAXFILENAMELEN]; /* name */\n};\n\ntypedef struct {\n  unsigned int load_addr;\n  unsigned int exec_addr;\n  int lenght;\n  int attrib;\n  int objtype;\n  char name[13];\n} riscos_direntry;\n\ntypedef struct {\n  short         ID;\n  short         size;\n  int           ID_2;\n  unsigned int  loadaddr;\n  unsigned int  execaddr;\n  int           attr;\n  int           zero;\n} extra_block;\n\n\n#define S_IFMT  0770000\n\n#define S_IFDIR 0040000\n#define S_IFREG 0100000  /* 0200000 in UnixLib !?!?!?!? */\n\n#ifndef S_IEXEC\n#  define S_IEXEC  0000100\n#  define S_IWRITE 0000200\n#  define S_IREAD  0000400\n#endif\n\n#ifndef NO_UNZIPH_STUFF\n#  include <time.h>\n#  if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP))\n#    define NO_STRNICMP\n#  endif\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_DMY\n#  endif\n#  define lenEOL 1\n#  define PutNativeEOL  *q++ = native(LF);\n#  define USE_STRM_INPUT\n#  define USE_FWRITE\n#  define PIPE_ERROR (errno == 9999)    /* always false */\n#  define isatty(x) (TRUE)   /* used in funzip.c to find if stdin redirected:\n     should find a better way, now just work as if stdin never redirected */\n#  define USE_EF_UT_TIME\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#    define TIMESTAMP\n#  endif\n#  define localtime riscos_localtime\n#  define gmtime riscos_gmtime\n#endif /* !NO_UNZIPH_STUFF */\n\n#define _raw_getc() SWI_OS_ReadC()\n\nextern char *exts2swap; /* Extensions to swap */\n\nint stat(char *filename,struct stat *res);\nDIR *opendir(char *dirname);\nstruct dirent *readdir(DIR *d);\nvoid closedir(DIR *d);\nint unlink(char *f);\nint rmdir(char *d);\nint chmod(char *file, int mode);\nvoid setfiletype(char *fname,int ftype);\nvoid getRISCOSexts(char *envstr);\nint checkext(char *suff);\nvoid swapext(char *name, char *exptr);\nvoid remove_prefix(void);\nvoid set_prefix(void);\nstruct tm *riscos_localtime(const time_t *timer);\nstruct tm *riscos_gmtime(const time_t *timer);\n\n#endif /* !__riscos_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/swiven.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* swiven.h */\n\n#ifndef __swiven_h\n#define __swiven_h\n\nos_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);\n/* copy */\n\nos_error *SWI_OS_FSControl_27(char *filename, int actionmask);\n/* wipe */\n\nos_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,\n                        int *offset, int size, char *match);\n/* read dir */\n\nos_error *SWI_OS_File_1(char *filename, unsigned int loadaddr,\n                        unsigned int execaddr, int attrib);\n/* write file attributes */\n\nos_error *SWI_OS_File_5(char *filename, int *objtype, unsigned int *loadaddr,\n                        unsigned int *execaddr, int *length, int *attrib);\n/* read file info */\n\nos_error *SWI_OS_File_6(char *filename);\n/* delete */\n\nos_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);\n/* create an empty file */\n\nos_error *SWI_OS_File_8(char *dirname);\n/* create a directory */\n\nos_error *SWI_OS_File_18(char *filename, int filetype);\n/* set a file's type */\n\nos_error *SWI_OS_CLI(char *cmd);\n/* execute a command */\n\nint SWI_OS_ReadC(void);\n/* get a key from the keyboard buffer */\n\nos_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);\n/* reads an OS varibale */\n\nos_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);\n/* reads the path of a specified directory */\n\nos_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);\n/* canonicalise path */\n\nos_error *SWI_DDEUtils_Prefix(char *dir);\n/* sets the 'prefix' directory */\n\nint SWI_Read_Timezone(void);\n/* returns the timezone offset (centiseconds) */\n\nint SWI_MimeMap_Translate(const char *ext);\n/* given a filename extn, returns the filetype (or -1 if no match).\n * Uses the MimeMap module */\n\n#endif /* !__swiven_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/acorn/swiven.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in unzip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; SWI veneers used by Zip/Unzip\n;\n\nr0\t\tRN\t0\nr1\t\tRN\t1\nr2\t\tRN\t2\nr3\t\tRN\t3\nr4\t\tRN\t4\nr5\t\tRN\t5\nr6\t\tRN\t6\nr7\t\tRN\t7\nr8\t\tRN\t8\nr9\t\tRN\t9\nr10\t\tRN\t10\nr11\t\tRN\t11\nr12\t\tRN\t12\nsp\t\tRN\t13\nlr\t\tRN\t14\npc\t\tRN\t15\n\nsl\t\tRN\t10\nfp\t\tRN\t11\nip\t\tRN\t12\n\n\nXOS_Bit\t\t\t\tEQU &020000\n\nOS_GBPB\t\t\t\tEQU &00000C\nOS_File\t\t\t\tEQU &000008\nOS_FSControl\t\t\tEQU &000029\nOS_CLI\t\t\t\tEQU &000005\nOS_ReadC\t\t\tEQU &000004\nOS_ReadVarVal\t\t\tEQU &000023\nDDEUtils_Prefix\t\t\tEQU &042580\nTerritory_ReadCurrentTimeZone\tEQU &043048\nMimeMap_Translate\t\tEQU &050B00\n\n\tMACRO\n\tSTARTCODE $name\n\tEXPORT $name\n$name\n\tMEND\n\n\n\t\tAREA\t|C$$code|, CODE, READONLY\n\n; os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);\n\n\tSTARTCODE SWI_OS_FSControl_26\n\n\tMOV\tip, lr\n\n\tMOV\tr3, r2\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #26\n\n\tSWI\tOS_FSControl + XOS_Bit\n\n\tMOVVC\tr0, #0\n\n\tMOVS\tpc, ip\n\n\n; os_error *SWI_OS_FSControl_27(char *filename, int actionmask);\n\n\tSTARTCODE SWI_OS_FSControl_27\n\n\tMOV\tip, lr\n\n\tMOV\tr3, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #27\n\n\tSWI\tOS_FSControl + XOS_Bit\n\n\tMOVVC\tr0, #0\n\n\tMOVS\tpc, ip\n\n\n; os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,\n;\t\t\t  int *offset, int size, char *match);\n\n\tSTARTCODE SWI_OS_GBPB_9\n\n\tMOV\tip, sp\n\tSTMFD\tsp!, {r2-r6,lr}\n\tLDMIA\tip, {r5,r6}\n\tLDR\tr4, [r3]\n\tLDR\tr3, [r2]\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #9\n\tSWI\tOS_GBPB + XOS_Bit\n\tLDMVSFD sp!, {r2-r6,pc}^\n\tMOV\tr0, #0\n\tLDMFD\tsp, {r5,r6}\n\tSTR\tr3, [r5]\n\tSTR\tr4, [r6]\n\tLDMFD\tsp!, {r2-r6,pc}^\n\n\n; os_error *SWI_OS_File_1(char *filename, int loadaddr, int execaddr, int attrib);\n\n\tSTARTCODE SWI_OS_File_1\n\n\tSTMFD\tsp!, {r5,lr}\n\tMOV\tr5, r3\n\tMOV\tr3, r2\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #1\n\tSWI\tOS_File + XOS_Bit\n\tMOVVC\tr0, #0\n\tLDMFD\tsp!, {r5,pc}^\n\n\n\n; os_error *SWI_OS_File_5(char *filename, int *objtype, int *loadaddr,\n;\t\t\t  int *execaddr, int *length, int *attrib);\n\n\tSTARTCODE SWI_OS_File_5\n\n\tSTMFD\tsp!, {r1-r5,lr}\n\tMOV\tr1, r0\n\tMOV\tr0, #5\n\tSWI\tOS_File + XOS_Bit\n\tLDMVSFD sp!, {r1-r5,pc}^\n\tLDR\tlr, [sp]\n\tTEQ\tlr, #0\n\tSTRNE\tr0, [lr]\n\tLDR\tlr, [sp, #4]\n\tTEQ\tlr ,#0\n\tSTRNE\tr2, [lr]\n\tLDR\tlr, [sp, #8]\n\tTEQ\tlr, #0\n\tSTRNE\tr3, [lr]\n\tLDR\tlr, [sp ,#24]\n\tTEQ\tlr, #0\n\tSTRNE\tr4, [lr]\n\tLDR\tlr, [sp ,#28]\n\tTEQ\tlr, #0\n\tSTRNE\tr5, [lr]\n\tMOV\tr0, #0\n\tLDMFD\tsp!, {r1-r5,pc}^\n\n\n; os_error *SWI_OS_File_6(char *filename);\n\n\tSTARTCODE SWI_OS_File_6\n\n\tSTMFD\tsp!, {r4-r5,lr}\n\tMOV\tr1, r0\n\tMOV\tr0, #6\n\tSWI\tOS_File + XOS_Bit\n\tMOVVC\tr0, #0\n\tLDMFD\tsp!, {r4-r5,pc}^\n\n\n; os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);\n\n\tSTARTCODE SWI_OS_File_7\n\n\tSTMFD\tsp!, {r4-r5,lr}\n\tMOV\tr5, r3\n\tMOV\tr4, #0\n\tMOV\tr3, r2\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #7\n\tSWI\tOS_File + XOS_Bit\n\tMOVVC\tr0, #0\n\tLDMFD\tsp!, {r4-r5,pc}^\n\n\n; os_error *SWI_OS_File_8(char *dirname);\n\n\tSTARTCODE SWI_OS_File_8\n\n\tSTMFD\tsp!, {r4,lr}\n\tMOV\tr1, r0\n\tMOV\tr4, #0\n\tMOV\tr0, #8\n\tSWI\tOS_File + XOS_Bit\n\tMOVVC\tr0, #0\n\tLDMFD\tsp!, {r4,pc}^\n\n\n; os_error *SWI_OS_File_18(char *filename, int filetype);\n\n\tSTARTCODE SWI_OS_File_18\n\n\tSTMFD\tsp!, {r4-r5,lr}\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #18\n\tSWI\tOS_File + XOS_Bit\n\tMOVVC\tr0, #0\n\tLDMFD\tsp!, {r4-r5,pc}^\n\n\n; os_error *SWI_OS_CLI(char *cmd);\n\n\tSTARTCODE SWI_OS_CLI\n\n\tMOV\tip, lr\n\tSWI\tOS_CLI + XOS_Bit\n\tMOVVC\tr0, #0\n\tMOVS\tpc, ip\n\n\n; int SWI_OS_ReadC(void);\n\n\tSTARTCODE SWI_OS_ReadC\n\n\tMOV\tip, lr\n\tSWI\tOS_ReadC + XOS_Bit\n\tMOVS\tpc, ip\n\n\n; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);\n\n\tSTARTCODE SWI_OS_ReadVarVal\n\n\tSTMFD\tsp!, {r4,lr}\n\tMOV\tip, r3\n\tMOV\tr3, #0\n\tMOV\tr4, #0\n\tSWI\tOS_ReadVarVal + XOS_Bit\n\tLDMVSFD\tsp!, {r4,pc}^\n\tTEQ\tip, #0\n\tSTRNE\tr2, [ip]\n\tMOV\tr0, #0\n\tLDMFD\tsp!, {r4,pc}^\n\n\n; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);\n\n\tSTARTCODE SWI_OS_FSControl_54\n\n\tSTMFD\tsp!, {r3-r6,lr}\n\tLDR\tr5, [r3]\n\tMOV\tr3, r2\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #54\n\tSWI\tOS_FSControl + XOS_Bit\n\tLDMVSFD sp!, {r3-r6,pc}^\n\tMOV\tr0, #0\n\tLDMFD\tsp!, {r3}\n\tSTR\tr5, [r3]\n\tLDMFD\tsp!, {r4-r6,pc}^\n\n\n; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);\n\n\tSTARTCODE SWI_OS_FSControl_37\n\n\tSTMFD\tsp!, {r2,r3-r5,lr}\n\tLDR\tr5, [r2]\n\tMOV\tr3, #0\n\tMOV\tr4, #0\n\tMOV\tr2, r1\n\tMOV\tr1, r0\n\tMOV\tr0, #37\n\tSWI\tOS_FSControl + XOS_Bit\n\tLDMVSFD sp!, {r2,r3-r5,pc}^\n\tMOV\tr0, #0\n\tLDMFD\tsp!, {r2}\n\tSTR\tr5, [r2]\n\tLDMFD\tsp!, {r3-r5,pc}^\n\n\n; os_error *SWI_DDEUtils_Prefix(char *dir);\n\n\tSTARTCODE SWI_DDEUtils_Prefix\n\n\tMOV\tip, lr\n\tSWI\tDDEUtils_Prefix + XOS_Bit\n\tMOVVC\tr0, #0\n\tMOVS\tpc, ip\n\n; int SWI_Read_Timezone(void);\n\n\tSTARTCODE SWI_Read_Timezone\n\n\tMOV\tip, lr\n\tSWI\tTerritory_ReadCurrentTimeZone + XOS_Bit\n\tMOVVC\tr0, r1\n\tMOVVS\tr0, #0\n\tMOVS\tpc, ip\n\n\n; int SWI_MimeMap_Translate(char *ext);\n\n\tSTARTCODE SWI_MimeMap_Translate\n\tMOV\tip,lr\n\tMOV\tr1, r0\n\tMOV\tr0, #3\n\tMOV\tr2, #0\n\tSWI\tMimeMap_Translate + XOS_Bit\n\tMOVVC\tr0, r3\n\tMVNVS\tr0, #0 ; return -1 on error\n\tMOVS\tpc, ip\n\n\n\tEND\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/Contents",
    "content": "Contents of the \"amiga\" directory for UnZip 5.5 and later:\n\n  Contents      this file\n  amiga.c       Amiga-specific file I/O routines\n  amiga.h       Amiga-specific header file\n  filedate.c    SetFileDate clone for OS 1.3, and other low-level resources\n\n  smakefile     SAS/C makefile for UnZip, fUnZip, and UnZipSFX\n\n  makefile.azt  Aztec C makefile for UnZip, fUnZip, and UnZipSFX\n  stat.c        stat() emulation for Aztec, along with opendir()/readdir()/etc\n  z-stat.h      replacement stat.h header file for use with stat.c\n  crc_68.a      assembler version of crc32.c\n  flate.a       assembler version of inflate_codes() (define ASM_INFLATECODES)\n\n  makesfx.c     source for MakeSFX, without which UnZipSFX is not usable\n\nNotes:\n\n  The crc_68.a source file is not currently used by the SAS/C makefile,\n  nor is flate.a; as of UnZip 5.2 neither of these wants args in\n  registers.\n\n  The DICE makefile has been removed since no one is supporting that\n  compiler anymore.\n\n  As of UnZip 5.2, if you have AmigaDOS 2.1 or newer and have set your\n  timezone in the Locale preferences editor, this will be an adequate\n  substitute for setting TZ.  If you do not set TZ to your current timezone,\n  files will be restored with times corrsponding to \"EST5EDT\", U.S. Eastern\n  time.  See ../proginfo/timezone.txt for directions on how to set the\n  TZ variable.\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/amiga.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*------------------------------------------------------------------------\n\n  amiga.c\n\n  Amiga-specific routines for use with Info-ZIP's UnZip 5.1 and later.\n  See History.5xx for revision history.\n\n  Contents:   do_wild()\n              mapattr()\n              mapname()\n              checkdir()\n              close_outfile()\n              stamp_file()\n              _abort()                (Aztec C only)\n             [dateformat()]           (currently not used)\n              screensize()\n              version()\n\n  ------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#ifdef AZTEC_C\n#  define NO_FCNTL_H\n#endif\n#include \"unzip.h\"\n#include \"unzvers.h\"\n\n/* Globular varibundus -- now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h */\n\n/* static int created_dir; */      /* used in mapname(), checkdir() */\n/* static int renamed_fullpath; */ /* ditto */\n\n#define PERMS   0777\n#define MKDIR(path,mode) mkdir(path)\n\n#ifndef S_ISCRIPT          /* not having one implies you have none */\n#  define S_IARCHIVE 0020  /* not modified since this bit was last set */\n#  define S_IREAD    0010  /* can be opened for reading */\n#  define S_IWRITE   0004  /* can be opened for writing */\n#  define S_IDELETE  0001  /* can be deleted */\n#endif /* S_ISCRIPT */\n\n#ifndef S_IRWD\n#  define S_IRWD     0015  /* useful combo of Amiga privileges */\n#endif /* !S_IRWD */\n\n#ifndef S_IHIDDEN\n#  define S_IHIDDEN  0200  /* hidden supported in future AmigaDOS (someday) */\n#endif /* !S_HIDDEN */\n\n#ifndef SFX\n/* Make sure the number here matches unzvers.h in the *EXACT* form */\n/* UZ_MAJORVER \".\" UZ_MINORVER UZ_PATCHLEVEL vvvv  No non-digits!  */\nconst char version_id[]  = \"\\0$VER: UnZip \" UZ_VER_STRING \" (\"\n#include \"env:VersionDate\"\n   \")\\r\\n\";\n#endif /* SFX */\n\n\nstatic int ispattern(ZCONST char *p)\n{\n    register char c;\n    while (c = *p++)\n        if (c == '\\\\') {\n            if (!*++p)\n                return FALSE;\n        } else if (c == '?' || c == '*')\n            return TRUE;\n        else if (c == '[') {\n            for (;;) {\n                if (!(c = *p++))\n                    return FALSE;\n                else if (c == '\\\\') {\n                    if (!*++p)\n                        return FALSE;\n                } else if (c == ']')\n                    return TRUE;\n            }\n        }\n    return FALSE;\n}\n\n/**********************/\n/* Function do_wild() */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h:\n    static DIR *wild_dir = NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall = FALSE, dirnamelen;\n*/\n    struct dirent *file;\n    BPTR lok = 0;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.notfirstcall) {      /* first call:  must initialize everything */\n        G.notfirstcall = TRUE;\n\n        /* avoid needless readdir() scans: */\n        if (!ispattern(wildspec) ||\n                (lok = Lock((char *)wildspec, ACCESS_READ))) {\n            if (lok) UnLock(lok);       /* ^^ we ignore wildcard chars if */\n            G.dirnamelen = 0;           /* the name matches a real file   */\n            strncpy(G.matchname, wildspec, FILNAMSIZ);\n            G.matchname[FILNAMSIZ-1] = '\\0';\n            return G.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL &&\n            (G.wildname = (ZCONST char *)strrchr(wildspec, ':')) == NULL) {\n            G.dirname = \"\";             /* current dir */\n            G.dirnamelen = 0;\n            G.wildname = wildspec;\n        } else {\n            ++G.wildname;     /* point at character after '/' or ':' */\n            G.dirnamelen = G.wildname - wildspec;\n            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) {\n                Info(slide, 1, ((char *)slide,\n                     \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(G.matchname, wildspec, FILNAMSIZ);\n                G.matchname[FILNAMSIZ-1] = '\\0';\n                return G.matchname; /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.dirname, wildspec, G.dirnamelen);\n            G.dirname[G.dirnamelen] = '\\0';\n        }\n\n        if ((G.wild_dir = opendir(G.dirname)) != NULL) {\n            while ((file = readdir(G.wild_dir)) != NULL) {\n                if (match(file->d_name, G.wildname, 1 WISEP)) {/* ignore case */\n                    strcpy(G.matchname, G.dirname);\n                    strcpy(G.matchname + G.dirnamelen, file->d_name);\n                    return G.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(G.wild_dir);\n            G.wild_dir = NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.matchname, wildspec, FILNAMSIZ);\n        G.matchname[FILNAMSIZ-1] = '\\0';\n        return G.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (G.wild_dir == NULL) {\n        G.notfirstcall = FALSE;    /* nothing left to try -- reset */\n        if (G.dirnamelen > 0)\n            free(G.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(G.wild_dir)) != NULL)\n        if (match(file->d_name, G.wildname, 1 WISEP)) { /* 1 == ignore case */\n            /* strcpy(G.matchname, dirname); */\n            strcpy(G.matchname + G.dirnamelen, file->d_name);\n            return G.matchname;\n        }\n\n    closedir(G.wild_dir);  /* have read at least one dir entry; nothing left */\n    G.wild_dir = NULL;\n    G.notfirstcall = FALSE; /* reset for new wildspec */\n    if (G.dirnamelen > 0)\n        free(G.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)      /* Amiga version */\n    __GDEF\n{\n    ulg  tmp = G.crec.external_file_attributes;\n\n\n    /* Amiga attributes = hsparwed = hidden, script, pure, archive,\n     * read, write, execute, delete */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            if ((tmp & 1) == (tmp>>18 & 1))\n                tmp ^= 0x000F0000;      /* PKAZip compatibility kluge */\n            /* turn off archive bit for restored Amiga files */\n            G.pInfo->file_attr = (unsigned)((tmp>>16) & (~S_IARCHIVE));\n            break;\n\n        case UNIX_:   /* preserve read, write, execute:  use logical-OR of */\n        case VMS_:    /* user, group, and other; if writable, set delete bit */\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            {\n              unsigned uxattr = (unsigned)(tmp >> 16);\n              int r = FALSE;\n\n              if (uxattr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                   VMS (and probably others ??) leave 0 in the upper 16-bit\n                   part of the external_file_attributes field. Instead, they\n                   store file permission attributes in some extra field.\n                   As a work-around, we search for the presence of one of\n                   these extra fields and fall back to the MSDOS compatible\n                   part of external_file_attributes if one of the known\n                   e.f. types has been detected.\n                   Later, we might implement extraction of the permission\n                   bits from the VMS extra field. But for now, the work-around\n                   should be sufficient to provide \"readable\" extracted files.\n                   (For ASI Unix e.f., an experimental remap of the e.f.\n                   mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            uxattr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n              }\n              if (!r) {\n                uxattr = (( uxattr>>6 | uxattr>>3 | uxattr) & 07) << 1;\n                G.pInfo->file_attr = (unsigned)(uxattr&S_IWRITE ?\n                                                uxattr|S_IDELETE : uxattr);\n                break;\n              }\n            }\n            /* fall through! */\n\n        /* all other platforms:  assume read-only bit in DOS half of attribute\n         * word is set correctly ==> will become READ or READ+WRITE+DELETE */\n        case FS_FAT_:\n        case FS_HPFS_:  /* can add S_IHIDDEN check to MSDOS/OS2/NT eventually */\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            G.pInfo->file_attr = (unsigned)(tmp&1? S_IREAD : S_IRWD);\n            break;\n\n    } /* end switch (host-OS-created-by) */\n\n    G.pInfo->file_attr &= 0xff;   /* mask off all but lower eight bits */\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];   /* path-component buffer */\n    char *pp, *cp=NULL;         /* character pointers */\n    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */\n    int killed_ddot = FALSE;    /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;   /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in AmigaDOS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.created_dir = FALSE;      /* not yet */\n\n    /* user gave full pathname:  don't prepend G.rootpath */\n#ifndef OLD_AMIGA_RENAMED\n    G.renamed_fullpath = (renamed &&\n                          (*G.filename == '/' || *G.filename == ':'));\n#else\n    /* supress G.rootpath even when user gave a relative pathname */\n# if 1\n    G.renamed_fullpath = (renamed && strpbrk(G.filename, \":/\");\n# else\n    G.renamed_fullpath = (renamed &&\n                          (strchr(G.filename, ':') || strchr(G.filename, '/')));\n# endif\n#endif\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;         /* keep for now; remove VMS \";##\" */\n                *pp++ = (char)workch;  /*  later, if requested */\n                break;\n\n            default:\n                /* allow ISO European characters in filenames: */\n                if (isprint(workch) || (160 <= workch && workch <= 255))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    error = (error & ~MPN_MASK) | checkdir(__G__ pathcomp, APPEND_NAME);\n    if ((error & MPN_MASK) == MPN_INF_TRUNC) {\n        /* GRR:  OK if truncated here:  warn and continue */\n        /* (warn in checkdir?) */\n    }\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in amiga.h: */\n/*  static int rootlen = 0; */   /* length of rootpath */\n/*  static char *rootpath;  */   /* user's \"extract-to\" directory */\n/*  static char *buildpath; */   /* full path (so far) to extracted file */\n/*  static char *end;       */   /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  check path length after each segment:  warn about truncation */\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.build_end = *pathcomp++) != '\\0')\n            ++G.build_end;\n        /* Truncate components over 30 chars? Nah, the filesystem handles it. */\n        if ((G.build_end-G.buildpath) > FILNAMSIZ-3)       /* room for \"/a\\0\" */\n            too_long = TRUE;                    /* check if extracting dir? */\n        if (SSTAT(G.buildpath, &G.statbuf)) {   /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpath)));\n                free(G.buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (MKDIR(G.buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpath), FnFilter1(G.filename)));\n                free(G.buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(G.buildpath), FnFilter1(G.filename)));\n            free(G.buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(G.buildpath)));\n            free(G.buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.build_end++ = '/';\n        *G.build_end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    G.buildpath.  Not our responsibility to worry whether pathcomp has room.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, G.buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(G.buildpath);\n        G.buildpath = G.build_end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.build_end = *pathcomp++) != '\\0') {\n            ++G.build_end;\n            if ((G.build_end-G.buildpath) >= FILNAMSIZ) {\n                *--G.build_end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(G.buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((G.rootlen > 0) && !G.renamed_fullpath) {\n            strcpy(G.buildpath, G.rootpath);\n            G.build_end = G.buildpath + G.rootlen;\n        } else {\n            *G.buildpath = '\\0';\n            G.build_end = G.buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in G.rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            G.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.rootlen = strlen(pathcomp)) > 0) {\n            if (stat(pathcomp, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode)) {\n                /* path does not exist */\n                if (!G.create_dirs) {\n                    G.rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning pathcomp\n                 * to create more than one level, but why really necessary?) */\n                if (MKDIR(pathcomp, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(pathcomp)));\n                    G.rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            if ((G.rootpath = (char *)malloc(G.rootlen+2)) == NULL) {\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(G.rootpath, pathcomp);\n            if (G.rootpath[G.rootlen-1] != ':' && G.rootpath[G.rootlen-1] != '/')\n                G.rootpath[G.rootlen++] = '/';\n            G.rootpath[G.rootlen] = '\\0';\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free G.rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            free(G.rootpath);\n            G.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/**************************************/\n/* Function close_outfile() */\n/**************************************/\n/* this part differs slightly with Zip */\n/*-------------------------------------*/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    time_t m_time;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n    LONG FileDate();\n\n    if (uO.cflag)               /* can't set time or filenote on stdout */\n        return;\n\n  /* close the file *before* setting its time under AmigaDOS */\n\n    fclose(G.outfile);\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                              G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n             & EB_UT_FL_MTIME))\n        {\n            TTrace((stderr, \"close_outfile:  Unix e.f. modif. time = %ld\\n\",\n                             z_utime.mtime));\n            m_time = z_utime.mtime;\n        } else {\n            /* Convert DOS time to time_t format */\n            m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n        }\n#else /* !USE_EF_UT_TIME */\n        /* Convert DOS time to time_t format */\n        m_time = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n#endif /* ?USE_EF_UT_TIME */\n\n#ifdef DEBUG\n        Info(slide, 1, ((char *)slide, \"\\nclose_outfile(): m_time=%s\\n\",\n             ctime(&m_time)));\n#endif\n\n        if (!FileDate(G.filename, &m_time))\n            Info(slide, 1, ((char *)slide,\n                 \"warning:  cannot set the time for %s\\n\", G.filename));\n    }\n\n    /* set file perms after closing (not done at creation)--see mapattr() */\n\n    chmod(G.filename, G.pInfo->file_attr);\n\n    /* give it a filenote from the zipfile comment, if appropriate */\n\n    if (uO.N_flag && G.filenotes[G.filenote_slot]) {\n        SetComment(G.filename, G.filenotes[G.filenote_slot]);\n        free(G.filenotes[G.filenote_slot]);\n        G.filenotes[G.filenote_slot] = NULL;\n    }\n\n} /* end function close_outfile() */\n\n\n#ifdef TIMESTAMP\n\n/*************************/\n/* Function stamp_file() */\n/*************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    time_t m_time;\n    LONG FileDate();\n\n    m_time = modtime;\n    return (FileDate((char *)fname, &m_time));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n#ifndef __SASC\n/********************************************************************/\n/* Load filedate as a separate external file; it's used by Zip, too.*/\n/*                                                                  */\n#  include \"amiga/filedate.c\"                                    /* */\n/*                                                                  */\n/********************************************************************/\n\n/********************* do linewise with stat.c **********************/\n\n#  include \"amiga/stat.c\"\n/* this is the exact same stat.c used by Zip */\n#endif /* !__SASC */\n/* SAS/C makes separate object modules of these; there is less  */\n/* trouble that way when redefining standard library functions. */\n\n#include <stdio.h>\n\nvoid _abort(void)               /* called when ^C is pressed */\n{\n    /* echon(); */\n    close_leftover_open_dirs();\n    fflush(stdout);\n    fputs(\"\\n^C\\n\", stderr);\n    exit(1);\n}\n\n\n/************************************************************/\n/* function screensize() -- uses sendpkt() from filedate.c: */\n/************************************************************/\n\n#include <devices/conunit.h>\n#include <dos/dosextens.h>\n#include <exec/memory.h>\n#include <clib/exec_protos.h>\n\nextern long sendpkt(struct MsgPort *pid, long action, long *args, long nargs);\n\nint screensize(int *ttrows, int *ttcols)\n{\n    BPTR fh = Output();\n    if (fh && IsInteractive(fh)) {\n        struct ConUnit *conunit = NULL;\n        void *conp = ((struct FileHandle *) (fh << 2))->fh_Type;\n        struct InfoData *ind = AllocMem(sizeof(*ind), MEMF_PUBLIC);\n        long argp = ((unsigned long) ind) >> 2;\n\n        if (ind && conp && sendpkt(conp, ACTION_DISK_INFO, &argp, 1))\n            conunit = (void *) ((struct IOStdReq *) ind->id_InUse)->io_Unit;\n        if (ind)\n            FreeMem(ind, sizeof(*ind));\n        if (conunit) {\n            if (ttrows) *ttrows = conunit->cu_YMax + 1;\n            if (ttcols) *ttcols = conunit->cu_XMax + 1;\n            return 0;     /* success */\n        }\n    }\n    if (ttrows) *ttrows = INT_MAX;\n    if (ttcols) *ttcols = INT_MAX;\n    return 1;             /* failure */\n}\n\n\n#ifdef AMIGA_VOLUME_LABELS\n/* This function is for if we someday implement -$ on the Amiga. */\n#  include <dos/dosextens.h>\n#  include <dos/filehandler.h>\n#  include <clib/macros.h>\n\nBOOL is_floppy(ZCONST char *path)\n{\n    BOOL okay = FALSE;\n    char devname[32], *debna;\n    ushort i;\n    BPTR lok = Lock((char *)path, ACCESS_READ), pok;\n    struct FileSysStartupMsg *fart;\n    struct DeviceNode *debb, devlist = (void *) BADDR((struct DosInfo *)\n                                BADDR(DOSBase->dl_Root->rn_Info)->di_DevInfo);\n    if (!lok)\n        return FALSE;                   /* should not happen */\n    if (pok = ParentDir((char *)path)) {\n        UnLock(lok);\n        UnLock(pok);\n        return FALSE;                   /* it's not a root directory path */\n    }\n    Forbid();\n    for (debb = devlist; debb; debb = BADDR(debb->dn_Next))\n        if (debb->dn_Type == DLT_DEVICE && (debb->dn_Task == lick->fl_Task))\n            if (fart = BADDR(debb->dn_Startup)) {\n                debna = (char *) BADDR(fart->fssm_Device) + 1;\n                if ((i = debna[-1]) > 31) i = 30;\n                strncpy(devname, debna, i);\n                devname[i] = 0;\n                okay = !strcmp(devname, \"trackdisk.device\")\n                                || !strcmp(devname, \"mfm.device\")\n                                || !strcmp(devname, \"messydisk.device\");\n                break;  /* We only support obvious floppy drives, not tricky */\n            }           /* things like removable cartrige hard drives, or    */\n    Permit();           /* any unusual kind of floppy device driver.         */\n    return okay;\n}\n#endif /* AMIGA_VOLUME_LABELS */\n\n\n#ifndef SFX\n\n# if 0\n/* As far as I can tell, all the locales AmigaDOS 2.1 knows about all */\n/* happen to use DF_MDY ordering, so there's no point in using this.  */\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\n#include <clib/locale_protos.h>\n#ifdef AZTEC_C\n#  include <pragmas/locale_lib.h>\n#endif\n\nint dateformat()\n{\n/*---------------------------------------------------------------------------\n    For those operating systems which support it, this function returns a\n    value which tells how national convention says that numeric dates are\n    displayed.  Return values are DF_YMD, DF_DMY and DF_MDY (the meanings\n    should be fairly obvious).\n  ---------------------------------------------------------------------------*/\n    struct Library *LocaleBase;\n    struct Locale *ll;\n    int result = DF_MDY;        /* the default */\n\n    if ((LocaleBase = OpenLibrary(\"locale.library\", 0))) {\n        if (ll = OpenLocale(NULL)) {\n            uch *f = ll->loc_ShortDateFormat;\n            /* In this string, %y|%Y is year, %b|%B|%h|%m is month, */\n            /* %d|%e is day day, and %D|%x is short for mo/da/yr.   */\n            if (!strstr(f, \"%D\") && !strstr(f, \"%x\")) {\n                uch *da, *mo, *yr;\n                if (!(mo = strstr(f, \"%b\")) && !(mo = strstr(f, \"%B\"))\n                                    && !(mo = strstr(f, \"%h\")))\n                    mo = strstr(f, \"%m\");\n                if (!(da = strstr(f, \"%d\")))\n                    da = strstr(f, \"%e\");\n                if (!(yr = strstr(f, \"%y\")))\n                    yr = strstr(f, \"%Y\");\n                if (yr && yr < mo)\n                    result = DF_YMD;\n                else if (da && da < mo)\n                    result = DF_DMY;\n            }\n            CloseLocale(ll);\n        }\n        CloseLibrary(LocaleBase);\n    }\n    return result;\n}\n\n# endif /* 0 */\n\n\n/************************/\n/*  Function version()  */\n/************************/\n\n\n/* NOTE:  the following include depends upon the environment\n *        variable $Workbench to be set correctly.  (Set by\n *        default, by kickstart during startup)\n */\nint WBversion = (int)\n#include \"ENV:Workbench\"\n;\n\nvoid version(__G)\n   __GDEF\n{\n/* Define buffers. */\n\n   char buf1[16];  /* compiler name */\n   char buf2[16];  /* revstamp */\n   char buf3[16];  /* OS */\n   char buf4[16];  /* Date */\n/*   char buf5[16];  /* Time */\n\n/* format \"with\" name strings */\n\n#ifdef AMIGA\n# ifdef __SASC\n   strcpy(buf1,\"SAS/C \");\n# else\n#  ifdef LATTICE\n    strcpy(buf1,\"Lattice C \");\n#  else\n#   ifdef AZTEC_C\n     strcpy(buf1,\"Manx Aztec C \");\n#   else\n     strcpy(buf1,\"UNKNOWN \");\n#   endif\n#  endif\n# endif\n/* \"under\" */\n  sprintf(buf3,\"AmigaDOS v%d\",WBversion);\n#else\n  strcpy(buf1,\"Unknown compiler \");\n  strcpy(buf3,\"Unknown OS\");\n#endif\n\n/* Define revision, date, and time strings.\n * NOTE:  Do not calculate run time, be sure to use time compiled.\n * Pass these strings via your makefile if undefined.\n */\n\n#if defined(__VERSION__) && defined(__REVISION__)\n  sprintf(buf2,\"version %d.%d\",__VERSION__,__REVISION__);\n#else\n# ifdef __VERSION__\n  sprintf(buf2,\"version %d\",__VERSION__);\n# else\n  sprintf(buf2,\"unknown version\");\n# endif\n#endif\n\n#ifdef __DATE__\n  sprintf(buf4,\" on %s\",__DATE__);\n#else\n  strcpy(buf4,\" unknown date\");\n#endif\n\n/******\n#ifdef __TIME__\n  sprintf(buf5,\" at %s\",__TIME__);\n#else\n  strcpy(buf5,\" unknown time\");\n#endif\n******/\n\n/* Print strings using \"CompiledWith\" mask defined in unzip.c (used by all).\n *  (\"Compiled with %s%s for %s%s%s%s.\")\n */\n\n   printf(LoadFarString(CompiledWith),\n     buf1,\n     buf2,\n     buf3,\n     buf4,\n     \"\",    /* buf5 not used */\n     \"\" );  /* buf6 not used */\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/amiga.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* amiga.h\n *\n * Globular definitions that affect all of AmigaDom.\n *\n * Originally included in unzip.h, extracted for simplicity and eeze of\n * maintenance by John Bush.\n *\n * THIS FILE IS #INCLUDE'd by unzpriv.h\n *\n */\n\n#ifndef __amiga_amiga_h\n#define __amiga_amiga_h\n\n#include \"amiga/z-stat.h\"     /* substitute for <stat.h> and <direct.h> */\n#include <limits.h>\n#ifndef NO_FCNTL_H\n#  include <fcntl.h>\n#else\n   int mkdir(const char *_name);\n#endif\n\n/* we only have dinky old-sk00l 32 bit filesystems */\n#ifdef LARGE_FILE_SUPPORT\n#  undef LARGE_FILE_SUPPORT\n#endif\n\ntypedef long        zoff_t;\n#define ZOFF_T_DEFINED\ntypedef struct stat z_stat;\n#define Z_STAT_DEFINED\n\n#ifdef AZTEC_C                       /* Manx Aztec C, 5.0 or newer only */\n#  include <clib/dos_protos.h>\n#  include <pragmas/dos_lib.h>           /* do inline dos.library calls */\n#  define O_BINARY 0\n#  define direct dirent\n\n#  ifndef IZTZ_DEFINESTDGLOBALS\n#    define IZTZ_DEFINESTDGLOBALS\n#  endif\n\n#  define DECLARE_TIMEZONE\n#  define ASM_INFLATECODES\n#  define ASM_CRC\n\n   /* This compiler environment supplies a flat 32-bit address space    */\n   /* where C rtl functions are capable of handling large (32-bit-wide) */\n   /* allocations and I/O.  But, for speed on old 68000 CPUs, standard  */\n   /* ints are 16-bits wide per default.  (\"size_t\" is defined as       */\n   /* \"unsigned long\" in this case.)  The Deflate64 support requires    */\n   /* the variables for handling the decompression buffer to hold       */\n   /* 32-bit wide integers.  The INT_16BIT symbol defined below forces  */\n   /* the declarations of these variables to use \"unsigned long\" type.  */\n#  ifndef _INT32\n#    define INT_16BIT                   /* or deflate64 stuff will fail */\n#  endif\n\n/* Note that defining REENTRANT will not eliminate all global/static */\n/* variables.  The functions we use from c.lib, including stdio, are */\n/* not reentrant.  Neither are the stuff in amiga/stat.c or the time */\n/* functions in amiga/filedate.c, because they just augment c.lib.   */\n/* If you want a fully reentrant and reexecutable \"pure\" UnZip with  */\n/* Aztec C, assemble and link in the startup module purify.a by Paul */\n/* Kienitz.  REENTRANT should be used just to reduce memory waste.   */\n#endif /* AZTEC_C */\n\n\n#ifdef __SASC\n/* NOTE: SAS/C COMPILATION HAS BEEN UNSUPPORTED THROUGH MANY UNZIP VERSIONS. */\n/* (Which is too bad, because it would probably perform better than Aztec.)  */\n\n/* includes */\n#  include <sys/types.h>\n#  include <sys/dir.h>\n#  include <dos.h>\n#  include <exec/memory.h>\n#  include <exec/execbase.h>\n#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))\n                            /* on 68020 or higher processors it is faster   */\n#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */\n#  endif                    /* to access functions of the exec.library      */\n#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */\n#  include <proto/dos.h>\n#  include <proto/locale.h>\n\n#  ifdef DEBUG\n#    include <sprof.h>      /* profiler header file */\n#  endif\n#  if ( (!defined(O_BINARY)) && defined(O_RAW))\n#    define O_BINARY O_RAW\n#  endif\n#  if (defined(_SHORTINT) && !defined(USE_FWRITE))\n#    define USE_FWRITE      /* define if write() returns 16-bit int */\n#  endif\n#  if (!defined(REENTRANT) && !defined(FUNZIP))\n#    define REENTRANT      /* define if unzip is going to be pure */\n#  endif\n#  if defined(REENTRANT) && defined(DYNALLOC_CRCTAB)\n#    undef DYNALLOC_CRCTAB\n#  endif\n#  ifdef MWDEBUG\n#    include <stdio.h>      /* both stdio.h and stdlib.h must be included */\n#    include <stdlib.h>     /* before memwatch.h                          */\n#    include \"memwatch.h\"\n#    undef getenv\n#  endif /* MWDEBUG */\n#  ifndef IZTZ_SETLOCALTZINFO\n     /*  XXX !!  We have really got to find a way to operate without these. */\n#    define IZTZ_SETLOCALTZINFO\n#  endif\n#endif /* SASC */\n\n\n#define MALLOC_WORK\n#define USE_EF_UT_TIME\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n\n#ifndef IZTZ_GETLOCALETZINFO\n#  define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone\n#endif\n/* the amiga port uses Info-ZIP's own timezone library, which includes\n * a \"working\" mktime() implementation\n */\n#ifndef HAVE_MKTIME\n#  define HAVE_MKTIME\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#define AMIGA_FILENOTELEN 80\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT     DF_MDY\n#endif\n#define lenEOL            1\n#define PutNativeEOL      *q++ = native(LF);\n#define PIPE_ERROR        0\n\n#ifdef GLOBAL         /* crypt.c usage conflicts with AmigaDOS headers */\n#  undef GLOBAL\n#endif\n\n/* Funkshine Prough Toe Taipes */\n\nextern int real_timezone_is_set;\nvoid tzset(void);\n#define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set)\n\nint Agetch(void);               /* getch() like function, in amiga/filedate.c */\nLONG FileDate(char *, time_t[]);\nint screensize(int *ttrows, int *ttcols);\nvoid _abort(void);              /* ctrl-C trap */\n\n#define SCREENSIZE(ttrows, ttcols) screensize(ttrows, ttcols)\n#define SCREENWIDTH 80\n#define SCREENLWRAP 1\n#define TABSIZE     8\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    int filenote_slot;\\\n    char *(filenotes[DIR_BLKSIZ]);\\\n    int created_dir, renamed_fullpath, rootlen;\\\n    char *rootpath, *buildpath, *build_end;\\\n    DIR *wild_dir;\\\n    ZCONST char *wildname;\\\n    char *dirname, matchname[FILNAMSIZ];\\\n    int dirnamelen, notfirstcall;\n\n/* filenotes[] and filenote_slot are for the -N option that restores      */\n/*    comments of Zip archive entries as AmigaDOS filenotes.  The others  */\n/*    are used by functions in amiga/amiga.c only.                        */\n/* created_dir and renamed_fullpath are used by mapname() and checkdir(). */\n/* rootlen, rootpath, buildpath, and build_end are used by checkdir().    */\n/* wild_dir, dirname, wildname, matchname[], dirnamelen and notfirstcall  */\n/*    are used by do_wild().                                              */\n#endif /* __amiga_amiga_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/filedate.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Low-level Amiga routines shared between Zip and UnZip.\n *\n * Contains:  FileDate()\n *            getenv()          [replaces inadequate standard library version]\n *            setenv()          [SAS/C only, replaces standard library version]\n *            set_TZ()          [SAS/C only]\n *            GetPlatformLocalTimezone() [callback from timezone.c tzset()]\n *            time()\n *            sendpkt()\n *            Agetch()\n *\n * The first five are used by most Info-ZIP programs except fUnZip.\n * The last two are used by all except the non-CRYPT version of fUnZip.\n * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...\n * sendpkt() is used by Agetch() and FileDate(), and by screensize() in\n * amiga/amiga.c (UnZip); time() is used only by Zip.\n */\n\n\n/* HISTORY/CHANGES\n *  2 Sep 92, Greg Roelofs, Original coding.\n *  6 Sep 92, John Bush, Incorporated into UnZip 5.1\n *  6 Sep 92, John Bush, Interlude \"FileDate()\" defined, which calls or\n *            redefines SetFileDate() depending upon AMIGADOS2 definition.\n * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining\n *            revision via OpenLibrary() call.  Now only one version of\n *            the program runs on both platforms (1.3.x vs. 2.x)\n * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing\n *            to take time_t input instead of struct DateStamp.\n *            Arg passing made to conform with utime().\n * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some\n *            lint-ish errors; simplified test for AmigaDOS version.\n * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and\n *            UnZip's \"More\" prompt -- simplifies crypt.h and avoids\n *            use of library code redundant with sendpkt().  Made it\n *            available to fUnZip, which does not use FileDate().\n * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current\n *            timezone from the Locale preferences.  These exist only under\n *            AmigaDOS 2.1 and up, but it is probably correctly set on more\n *            Amigas than the TZ environment variable is.  We check that\n *            only if TZ is not validly set.  We do not parse daylight\n *            savings syntax except to check for presence vs. absence of a\n *            DST part; United States rules are assumed.  This is better\n *            than the tzset()s in the Amiga compilers' libraries do.\n * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level\n *            sendpkt() (when FileDate(), Agetch() or windowheight() is used),\n *            and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).\n * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved\n *            stuff around for clarity.\n * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the\n *            new tzset(), because Aztec's is hopelessly broken.  Also\n *            gmtime(), which localtime() calls.\n * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.\n * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns\n *            local time instead of GMT.  That's why their localtime() was bad,\n *            because it assumed time_t was already local, and gmtime() was\n *            the one that checked TZ.\n * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.\n *            Currently, the UnZip sources do not make use of time() (and do\n *            not supply the working mktime() replacement, either!).\n * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that\n *            was previously embedded in tzset(), for reliable global test\n *            of whether TZ is set or not.\n * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.\n *  7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.\n *  4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.\n * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding\n *            mkgmtime() so localtime() could be used.\n * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;\n *            the Zip sources supply this function as part of util.c.\n * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved\n *            set_TZ() to time_lib.c.\n * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.\n * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).\n * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.\n * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.\n * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to\n *            Amiga file-time directly.\n * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().\n * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined\n *            header inclusion sequence that resolves all header dependencies.\n * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license,\n *            moved set_TZ() back here, replaced minimal tzset() and localtime()\n *            with new versions derived from GNU glibc source.  Gave locale_TZ()\n *            reasonable European defaults for daylight savings.\n * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL\n *            virus, replaced with similar functions based on the public domain\n *            timezone code at ftp://elsie.nci.nih.gov/pub.  As with the GNU\n *            stuff, support for timezone files and leap seconds was removed.\n * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate\n *            platform-independent module 'timezone.c'.\n * 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions\n *            back in here, from 'timezone.c'.\n * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include \"timezone.h\"\n *            and \"symbolic\" preprocessor constants for time calculations.\n * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation\n *            for Zip utilities (when \"defined(UTIL)\")\n */\n\n#ifndef __amiga_filedate_c\n#define __amiga_filedate_c\n\n\n#include \"zip.h\"\n#include <ctype.h>\n#include <errno.h>\n\n#include <exec/types.h>\n#include <exec/execbase.h>\n#include <exec/memory.h>\n#include <dos/dosextens.h>\n\n#ifdef AZTEC_C\n#  include <libraries/dos.h>\n#  include <libraries/dosextens.h>\n#  include <clib/exec_protos.h>\n#  include <clib/dos_protos.h>\n#  include <clib/locale_protos.h>\n#  include <pragmas/exec_lib.h>\n#  include <pragmas/dos_lib.h>\n#  include <pragmas/locale_lib.h>\n#  define ESRCH  ENOENT\n#  define EOSERR EIO\n#endif\n\n#ifdef __SASC\n#  include <stdlib.h>\n#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))\n                            /* on 68020 or higher processors it is faster   */\n#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */\n#  endif                    /* to access functions of the exec.library      */\n#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */\n#  include <proto/dos.h>\n#  include <proto/locale.h>\n#  ifdef DEBUG\n#     include <sprof.h>\n#  endif\n#  ifdef MWDEBUG\n#    include <stdio.h>      /* include both before memwatch.h again just */\n#    include <stdlib.h>     /* to be safe */\n#    include \"memwatch.h\"\n#  endif /* MWDEBUG */\n#endif /* __SASC */\n\n#include \"crypt.h\"            /* just so we can tell if CRYPT is supported */\n\n\n#if (!defined(FUNZIP) && !defined(UTIL))\n\n#include \"timezone.h\"         /* for AMIGA-specific timezone callbacks */\n\n#ifndef SUCCESS\n#  define SUCCESS (-1L)\n#  define FAILURE 0L\n#endif\n\n#define ReqVers 36L        /* required library version for SetFileDate() */\n#define ENVSIZE 100        /* max space allowed for an environment var   */\n\nextern struct ExecBase *SysBase;\n\n#ifndef min\n#  define min(a, b)  ((a) < (b) ? (a) : (b))\n#  define max(a, b)  ((a) < (b) ? (b) : (a))\n#endif\n\n#if defined(ZIP) || defined(HAVE_MKTIME)\nstatic const unsigned short ydays[] =\n    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };\n#else\nextern const unsigned short ydays[];  /* in unzip's fileio.c */\n#endif\n\n#define LEAP(y)     (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n#define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y)))\n/* Number of leap years from 1978 to `y' (not including `y' itself). */\n#define ANLEAP(y)   (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)\n#define SECSPERMIN  60\n#define MINSPERHOUR 60\n#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)\n#define SECSPERDAY  86400L\n\n/* prototypes */\nchar *getenv(const char *var);\n#ifdef __SASC\n/*  XXX !!  We have really got to find a way to operate without these. */\nint setenv(const char *var, const char *value, int overwrite);\nvoid set_TZ(long time_zone, int day_light);\n#endif\n\nLONG FileDate(char *filename, time_t u[]);\nLONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\nint Agetch(void);\n\n/* =============================================================== */\n\n/***********************/\n/* Function filedate() */\n/***********************/\n\n/*  FileDate() (originally utime.c), by Paul Wells.  Modified by John Bush\n *  and others (see also sendpkt() comments, below); NewtWare SetFileDate()\n *  clone cheaply ripped off from utime().\n */\n\n/* DESCRIPTION\n * This routine chooses between 2 methods to set the file date on AMIGA.\n * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36\n * and higher).  Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()\n * must be accomplished by constructing a message packet and sending it\n * to the file system handler of the file to be stamped.\n *\n * The system's ROM version is extracted from the external system Library\n * base.\n *\n * NOTE:  although argument passing conforms with utime(), note the\n *        following differences:\n *          - Return value is boolean success/failure.\n *          - If a structure or array is passed, only the first value\n *            is used, which *may* correspond to date accessed and not\n *            date modified.\n */\n\nLONG FileDate(filename, u)\n    char *filename;\n    time_t u[];\n{\n    LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);\n    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n    struct MsgPort *taskport;\n    BPTR dirlock, lock;\n    struct FileInfoBlock *fib;\n    LONG pktargs[4];\n    UBYTE *ptr;\n    long ret;\n\n    struct DateStamp pDate;\n    struct tm *ltm;\n    int years;\n\n    tzset();\n    /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):\n     * 8 years and 2 leapdays difference from Unix time.\n     */\n    ltm = localtime(&u[0]);\n    years = ltm->tm_year + 1900;\n    if (years < 1978)\n        pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;\n    else {\n        pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) +\n                        YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1);\n        pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;\n        pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;\n    }\n\n    if (SysBase->LibNode.lib_Version >= ReqVers)\n    {\n        return (SetFileDate(filename,&pDate));  /* native routine at 2.0+ */\n    }\n    else  /* !(SysBase->lib_Version >=ReqVers) */\n    {\n        if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )\n        {\n            errno = ESRCH;          /* no such process */\n            return FAILURE;\n        }\n\n        if( !(lock = Lock(filename,SHARED_LOCK)) )\n        {\n            errno = ENOENT;         /* no such file */\n            return FAILURE;\n        }\n\n        if( !(fib = (struct FileInfoBlock *)AllocMem(\n            (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )\n        {\n            errno = ENOMEM;         /* insufficient memory */\n            UnLock(lock);\n            return FAILURE;\n        }\n\n        if( Examine(lock,fib)==FAILURE )\n        {\n            errno = EOSERR;         /* operating system error */\n            UnLock(lock);\n            FreeMem(fib,(long)sizeof(*fib));\n            return FAILURE;\n        }\n\n        dirlock = ParentDir(lock);\n        ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);\n        strcpy((ptr+1),fib->fib_FileName);\n        *ptr = strlen(fib->fib_FileName);\n        FreeMem(fib,(long)sizeof(*fib));\n        UnLock(lock);\n\n        /* now fill in argument array */\n\n        pktargs[0] = 0;\n        pktargs[1] = (LONG)dirlock;\n        pktargs[2] = (LONG)&ptr[0] >> 2;\n        pktargs[3] = (LONG)&pDate;\n\n        errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);\n\n        FreeMem(ptr,64L);\n        UnLock(dirlock);\n\n        return SUCCESS;\n    }  /* ?(SysBase->lib_Version >= ReqVers) */\n} /* FileDate() */\n\n\nchar *getenv(const char *var)         /* not reentrant! */\n{\n    static char space[ENVSIZE];\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    char *ret = NULL;\n\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (SysBase->LibNode.lib_Version >= ReqVers) {\n        if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0)\n            ret = space;\n    } else {                    /* early AmigaDOS, get env var the crude way */\n        BPTR hand, foot, spine;\n        int z = 0;\n        if (foot = Lock(\"ENV:\", ACCESS_READ)) {\n            spine = CurrentDir(foot);\n            if (hand = Open((char *) var, MODE_OLDFILE)) {\n                z = Read(hand, space, ENVSIZE - 1);\n                Close(hand);\n            }\n            UnLock(CurrentDir(spine));\n        }\n        if (z > 0) {\n            space[z] = '\\0';\n            ret = space;\n        }\n    }\n    me->pr_WindowPtr = old_window;\n    return ret;\n}\n\n#ifdef __SASC\nint setenv(const char *var, const char *value, int overwrite)\n{\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    int ret = -1;\n\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (SysBase->LibNode.lib_Version >= ReqVers)\n        ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR);\n    else {\n        BPTR hand, foot, spine;\n        long len = value ? strlen(value) : 0;\n        if (foot = Lock(\"ENV:\", ACCESS_READ)) {\n            spine = CurrentDir(foot);\n            if (len) {\n                if (hand = Open((char *) var, MODE_NEWFILE)) {\n                    ret = Write(hand, (char *) value, len + 1) >= len;\n                    Close(hand);\n                }\n            } else\n                ret = DeleteFile((char *) var);\n            UnLock(CurrentDir(spine));\n        }\n    }\n    me->pr_WindowPtr = old_window;\n    return ret;\n}\n\n/* Stores data from timezone and daylight to ENV:TZ.                  */\n/* ENV:TZ is required to exist by some other SAS/C library functions, */\n/* like stat() or fstat().                                            */\nvoid set_TZ(long time_zone, int day_light)\n{\n    char put_tz[MAXTIMEZONELEN];  /* string for putenv: \"TZ=aaabbb:bb:bbccc\" */\n    int offset;\n    void *exists;     /* dummy ptr to see if global envvar TZ already exists */\n    exists = (void *)getenv(TZ_ENVVAR);\n    /* see if there is already an envvar TZ_ENVVAR. If not, create it */\n    if (exists == NULL) {\n        /* create TZ string by pieces: */\n        sprintf(put_tz, \"GMT%+ld\", time_zone / 3600L);\n        if (time_zone % 3600L) {\n            offset = (int) labs(time_zone % 3600L);\n            sprintf(put_tz + strlen(put_tz), \":%02d\", offset / 60);\n            if (offset % 60)\n                sprintf(put_tz + strlen(put_tz), \":%02d\", offset % 60);\n        }\n        if (day_light)\n            strcat(put_tz,\"DST\");\n        setenv(TZ_ENVVAR, put_tz, 1);\n    }\n}\n#endif /* __SASC */\n\n/* set state as well as possible from settings found in locale.library */\nint GetPlatformLocalTimezone(sp, fill_tzstate_from_rules)\n     register struct state * ZCONST sp;\n     void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                     ZCONST struct rule * ZCONST start,\n                                     ZCONST struct rule * ZCONST end);\n{\n    struct Library *LocaleBase;\n    struct Locale *ll;\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    BPTR eh;\n    int z, valid = FALSE;\n\n    /* read timezone from locale.library if TZ envvar missing */\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (LocaleBase = OpenLibrary(\"locale.library\", 0)) {\n        if (ll = OpenLocale(NULL)) {\n            z = ll->loc_GMTOffset;    /* in minutes */\n            if (z == -300) {\n                if (eh = Lock(\"ENV:sys/locale.prefs\", ACCESS_READ)) {\n                    UnLock(eh);\n                    valid = TRUE;\n                } else\n                    z = 300; /* bug: locale not initialized, default bogus! */\n            } else\n                valid = TRUE;\n            if (valid) {\n                struct rule startrule, stoprule;\n\n                sp->timecnt = 0;\n                sp->typecnt = 1;\n                sp->charcnt = 2;\n                sp->chars[0] = sp->chars[1] = '\\0';\n                sp->ttis[0].tt_abbrind = 0;\n                sp->ttis[1].tt_abbrind = 1;\n                sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR;\n                sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR;\n                sp->ttis[0].tt_isdst = 0;\n                sp->ttis[1].tt_isdst = 1;\n                stoprule.r_type = MONTH_NTH_DAY_OF_WEEK;\n                stoprule.r_day = 0;\n                stoprule.r_week = 5;\n                stoprule.r_mon = 10;\n                stoprule.r_time = 2 * SECSPERHOUR;\n                startrule = stoprule;\n                startrule.r_mon = 4;\n                startrule.r_week = 1;\n                if (z >= -180 && z < 150) {\n                    /* At this point we make a really gratuitous assumption: */\n                    /* if the time zone could be Europe, we use the European */\n                    /* Union rules without checking what country we're in.   */\n                    /* The AmigaDOS locale country codes do not, at least in */\n                    /* 2.x versions of the OS, recognize very many countries */\n                    /* outside of Europe and North America.                  */\n                    sp->typecnt = 2;\n                    startrule.r_mon = 3;   /* one week earlier than US DST */\n                    startrule.r_week = 5;\n                } else if (z >= 150 && z <= 480 &&\n                           /* no DST in alaska, hawaii */\n                           (ll->loc_CountryCode == 0x55534100 /*\"USA\"*/ ||\n                            ll->loc_CountryCode == 0x43414E00 /*\"CAN\"*/))\n                    sp->typecnt = 2;\n                    /* We check the country code for U.S. or Canada because */\n                    /* most of Latin America has no DST.  Even in these two */\n                    /* countries there are some exceptions...               */\n                /* else if...  Feel free to add more cases here! */\n\n                if (sp->typecnt > 1)\n                    (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);\n            }\n            CloseLocale(ll);\n        }\n        CloseLibrary(LocaleBase);\n    }\n    me->pr_WindowPtr = old_window;\n    return valid;\n}\n\n#ifdef ZIP\ntime_t time(time_t *tp)\n{\n    time_t t;\n    struct DateStamp ds;\n    DateStamp(&ds);\n    t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60\n                                      + (ds.ds_Days + 2922) * SECSPERDAY;\n    t = mktime(gmtime(&t));\n    /* gmtime leaves ds in the local timezone, mktime converts it to GMT */\n    if (tp) *tp = t;\n    return t;\n}\n#endif /* ZIP */\n\n#endif /* !FUNZIP && !UTIL */\n\n\n#if CRYPT || !defined(FUNZIP)\n\n/*  sendpkt.c\n *  by A. Finkel, P. Lindsay, C. Sheppner\n *  returns Res1 of the reply packet\n */\n/*\n#include <exec/types.h>\n#include <exec/memory.h>\n#include <libraries/dos.h>\n#include <libraries/dosextens.h>\n#include <proto/exec.h>\n#include <proto/dos.h>\n*/\n\nLONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n\nLONG sendpkt(pid,action,args,nargs)\nstruct MsgPort *pid;           /* process identifier (handler message port) */\nLONG action,                   /* packet type (desired action)              */\n     *args,                    /* a pointer to argument list                */\n     nargs;                    /* number of arguments in list               */\n{\n\n    struct MsgPort *replyport, *CreatePort(UBYTE *, long);\n    void DeletePort(struct MsgPort *);\n    struct StandardPacket *packet;\n    LONG count, *pargs, res1;\n\n    replyport = CreatePort(NULL,0L);\n    if( !replyport ) return(0);\n\n    packet = (struct StandardPacket *)AllocMem(\n            (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);\n    if( !packet )\n    {\n        DeletePort(replyport);\n        return(0);\n    }\n\n    packet->sp_Msg.mn_Node.ln_Name  = (char *)&(packet->sp_Pkt);\n    packet->sp_Pkt.dp_Link          = &(packet->sp_Msg);\n    packet->sp_Pkt.dp_Port          = replyport;\n    packet->sp_Pkt.dp_Type          = action;\n\n    /* copy the args into the packet */\n    pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of 1st argument */\n    for( count=0; count<nargs; count++ )\n        pargs[count] = args[count];\n\n    PutMsg(pid,(struct Message *)packet);   /* send packet */\n\n    WaitPort(replyport);\n    GetMsg(replyport);\n\n    res1 = packet->sp_Pkt.dp_Res1;\n\n    FreeMem((char *)packet,(long)sizeof(*packet));\n    DeletePort(replyport);\n\n    return(res1);\n\n} /* sendpkt() */\n\n#endif /* CRYPT || !FUNZIP */\n\n\n#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))\n\n/* Agetch() reads one raw keystroke -- uses sendpkt() */\n\nint Agetch(void)\n{\n    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n    struct Task *me = FindTask(NULL);\n    struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);\n    BPTR fh = cli->cli_StandardInput;   /* this is immune to < redirection */\n    void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;\n    char longspace[8];\n    long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */\n    UBYTE c;\n\n    *flag = 1;\n    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);         /* assume success */\n    Read(fh, &c, 1);\n    *flag = 0;\n    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);\n    if (c == 3)                                         /* ^C in input */\n        Signal(me, SIGBREAKF_CTRL_C);\n    return c;\n}\n\n#endif /* CRYPT || (UNZIP && !FUNZIP) */\n\n#endif /* __amiga_filedate_c*/\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/makefile.azt",
    "content": "# Makefile for UnZip 5.53 using Manx Aztec C 5.2, last revised 25 Dec 06.\n# Define EXTRA=xxx on the Make command line for e.g. -dUSE_UNSHRINK.\n\nEXTRA =\n\nDEFINES = -d AMIGA $(EXTRA)\nVERNUMS = -d __VERSION__=5 -d __REVISION__=2\n\nCC = cc\nLD = ln\n\nLDLIBS = -lc16\n\n# release version:\n# ----------------\nCFLAGS = -ps -wcpr0u -sabfmnpu $(DEFINES)\n# -ps means short ints, -wcpr0u is type checking, -sabfmnpu is optimizations..\n# Option flags MORE and ASM_* are now set in the Aztec section of amiga/amiga.h;\n# it's cleaner, and that way any changes forces a recompile.\nLDFLAGS = +q -m\n# Linker arg -m suppresses warnings about overriding c.lib functions.\n\n# debug version:\n# --------------\nCFLAGD = -ps -wcpr0u -bs -s0f0n $(DEFINES)\n# -bs is include source debugging info, -s0f0n is avoid hard-to-debug optimizations\nLDFLAGD = +q -m -g -w\n# -g activates source-level debugging (a .dbg file), -w saves assembly-level symbols\n\n# the directory for object files:\nO = obA/\n\nOBJS = $(O)unzip.o $(O)envargs.o $(O)process.o $(O)extract.o \\\n         $(O)explode.o $(O)ubz2err.o $(O)unshrink.o $(O)unreduce.o \\\n         $(O)inflate.o $(O)match.o $(O)zipinfo.o $(O)list.o $(O)globals.o \\\n         $(O)crypt.o $(O)ttyio.o $(O)fileio.o $(O)crc32.o $(O)timezone.o \\\n         $(O)amiga.o $(O)crc_68.o $(O)flate.o\n\nXOBJS = $(O)unzip.xo $(O)process.xo $(O)extract.xo $(O)ubz2err.xo \\\n         $(O)inflate.xo $(O)match.xo $(O)globals.xo $(O)crypt.xo \\\n         $(O)ttyio.xo $(O)fileio.xo $(O)crc32.xo $(O)timezone.xo \\\n         $(O)amiga.xo $(O)crc_68.o $(O)flate.xo\n\nFOBJS = $(O)funzip.o $(O)inflate.fo $(O)crypt.fo $(O)ttyio.fo $(O)globals.fo \\\n         $(O)crc32.fo $(O)filedate.fo $(O)crc_68.o $(O)flate.fo\n\nDBJS = $(O)unzip.od $(O)envargs.od $(O)process.od \\\n         $(O)extract.od $(O)explode.od $(O)unshrink.od $(O)unreduce.od \\\n         $(O)inflate.od $(O)match.od $(O)zipinfo.od $(O)list.od $(O)globals.od \\\n         $(O)crypt.od $(O)ttyio.od $(O)fileio.od $(O)crc32.od $(O)timezone.od \\\n         $(O)amiga.od $(O)crc_68.o $(O)flate.o\n\nXDBJS = $(O)unzip.xd $(O)process.xd $(O)extract.xd \\\n         $(O)inflate.xd $(O)match.xd $(O)globals.xd $(O)crypt.xd \\\n         $(O)ttyio.xd $(O)fileio.xd $(O)crc32.xd $(O)timezone.xd \\\n         $(O)amiga.xd $(O)crc_68.o $(O)flate.xo\n\nFDBJS = $(O)funzip.od $(O)inflate.fd $(O)crypt.fd $(O)ttyio.fd $(O)globals.fd \\\n         $(O)crc32.fd $(O)filedate.fd $(O)crc_68.o $(O)flate.fo\n\n\n.c.o :\n\t$(CC) -o $@ $(CFLAGS) $*.c\n\n.c.xo:\n\t$(CC) -o $@ -d SFX $(CFLAGS) $*.c\n\n.c.fo:\n\t$(CC) -o $@ -d FUNZIP $(CFLAGS) $*.c\n\n.c.od :\n\t$(CC) -o $@ $(CFLAGD) $*.c\n\n.c.xd:\n\t$(CC) -o $@ -d SFX $(CFLAGD) $*.c\n\n.c.fd:\n\t$(CC) -o $@ -d FUNZIP $(CFLAGD) $*.c\n\n# HERE WE GO:\n\nall : Unzip UnzipSFX fUnzip MakeSFX\n\nu : Unzip\n\nf : fUnzip\n\nx : UnzipSFX\n\nm : MakeSFX\n\ndall: Unzip.dbg UnzipSFX.dbg fUnzip.dbg MakeSFX.dbg\n\nud : Unzip.dbg\n\nfd : fUnzip.dbg\n\nxd : UnzipSFX.dbg\n\nmd : MakeSFX.dbg\n\n\nUnzip :     $(OBJS)\n\t$(LD) $(LDFLAGS) -o Unzip $(OBJS) $(LDLIBS)\n\t-@delete Unzip.dbg\n\nUnzipSFX :  $(XOBJS) MakeSFX\n\t$(LD) $(LDFLAGS) -o UnzipSFX $(XOBJS) $(LDLIBS)\n\t-@delete UnzipSFX.dbg\n\nfUnzip :    $(FOBJS)\n\t$(LD) $(LDFLAGS) -o fUnzip $(FOBJS) $(LDLIBS)\n\t-@delete fUnzip.dbg\n\nMakeSFX :   amiga/makesfx.c\n\t$(CC) $(CFLAGS) -o t:makesfx.o amiga/makesfx.c\n\t$(LD) $(LDFLAGS) -o MakeSFX t:makesfx.o $(LDLIBS)\n\t-@delete MakeSFX.dbg\n\t-@delete t:makesfx.o\n\n\nUnzip.dbg :     $(DBJS)\n\t$(LD) $(LDFLAGD) -o Unzip $(DBJS) $(LDLIBS)\n\nUnzipSFX.dbg :  $(XDBJS) MakeSFX.dbg\n\t$(LD) $(LDFLAGD) -o UnzipSFX $(XDBJS) $(LDLIBS)\n\nfUnzip.dbg :    $(FDBJS)\n\t$(LD) $(LDFLAGD) -o fUnzip $(FDBJS) $(LDLIBS)\n\nMakeSFX.dbg :   amiga/makesfx.c\n\t$(CC) $(CFLAGD) -o t:makesfx.o amiga/makesfx.c\n\t$(LD) $(LDFLAGD) -o MakeSFX t:makesfx.o $(LDLIBS)\n\t-@delete t:makesfx.o\n\n\nclean :\n\t-delete $(OBJS)\n\t-delete $(XOBJS)\n\t-delete $(FOBJS)\n\t-delete $(DBJS)\n\t-delete $(XDBJS)\n\t-delete $(FDBJS)\n\t-delete amiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs\n\ncleaner : clean\n\t-delete UnZip fUnZip UnZipSFX MakeSFX *.dbg\n\n# header dependencies:\n\n$(OBJS) $(XOBJS) $(FOBJS) : unzip.h unzpriv.h globals.h \\\n                             amiga/amiga.h amiga/z-stat.h\n$(DBJS) $(XDBJS) $(FDBJS) : unzip.h unzpriv.h globals.h \\\n                             amiga/amiga.h amiga/z-stat.h\n\n$(O)crypt.o  $(O)crypt.fo $(O)timezone.o  $(O)ttyio.o  $(O)ttyio.fo : zip.h\n$(O)crypt.od $(O)crypt.fd $(O)timezone.od $(O)ttyio.od $(O)ttyio.fd : zip.h\n\n$(O)inflate.o $(O)inflate.fo $(O)inflate.od $(O)inflate.fd : inflate.h\n\n$(O)fileio.o $(O)fileio.od : ebcdic.h\n\n$(O)funzip.o $(O)funzip.od : crc32.h\n$(O)crc32.o  $(O)crc32.fo $(O)crc32.xo : crc32.h\n$(O)crc32.od $(O)crc32.fd $(O)crc32.xd : crc32.h\n$(O)crypt.o  $(O)crypt.fo $(O)crypt.xo : crc32.h\n$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crc32.h\n$(O)extract.o $(O)extract.xo $(O)extract.od $(O)extract.xd : crc32.h\n$(O)fileio.o $(O)fileio.xo $(O)fileio.od $(O)fileio.xd : crc32.h\n$(O)process.o $(O)process.xo $(O)process.od $(O)process.xd : crc32.h\n\n$(O)crypt.o  $(O)crypt.fo $(O)crypt.xo : crypt.h\n$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : crypt.h\n$(O)ttyio.o  $(O)ttyio.fo $(O)ttyio.xo : crypt.h\n$(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : crypt.h\n$(O)unzip.o  $(O)unzip.xo $(O)funzip.o  : crypt.h\n$(O)unzip.od $(O)unzip.xd $(O)funzip.od : crypt.h\n$(O)fileio.o  $(O)fileio.xo $(O)extract.o  $(O)extract.xo : crypt.h\n$(O)fileio.od $(O)fileio.xd $(O)extract.od $(O)extract.xd : crypt.h\n$(O)inflate.o  $(O)inflate.fo $(O)inflate.xo $(O)filedate.fo : crypt.h\n$(O)inflate.od $(O)inflate.fd $(O)inflate.xd $(O)filedate.fd : crypt.h\namiga/gbloffs amiga/Fgbloffs amiga/Xgbloffs : crypt.h\n\n$(O)crypt.o  $(O)crypt.fo $(O)crypt.xo : ttyio.h\n$(O)crypt.od $(O)crypt.fd $(O)crypt.xd : ttyio.h\n$(O)ttyio.o  $(O)ttyio.fo $(O)ttyio.xo : ttyio.h\n$(O)ttyio.od $(O)ttyio.fd $(O)ttyio.xd : ttyio.h\n$(O)funzip.o  $(O)fileio.o  $(O)fileio.xo : ttyio.h\n$(O)funzip.od $(O)fileio.od $(O)fileio.xd : ttyio.h\n\n$(O)timezone.o  $(O)timezone.xo $(O)amiga.o  $(O)amiga.xo : timezone.h\n$(O)timezone.od $(O)timezone.xd $(O)amiga.od $(O)amiga.xd : timezone.h\n\n$(O)unzip.o $(O)unzip.xo $(O)unzip.od $(O)unzip.xd : unzvers.h consts.h\n\n\n# Special case object files:\n\n$(O)amiga.o : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) -o $(O)amiga.o $(CFLAGS) $(VERNUMS) amiga/amiga.c\n\n$(O)amiga.xo : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h\n\t$(CC) -o $(O)amiga.xo $(CFLAGS) $(VERNUMS) -d SFX amiga/amiga.c\n\n$(O)amiga.od : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) -o $(O)amiga.od $(CFLAGD) $(VERNUMS) amiga/amiga.c\n\n$(O)amiga.xd : amiga/filedate.c amiga/stat.c amiga/amiga.c unzvers.h\n\t$(CC) -o $(O)amiga.xd $(CFLAGD) $(VERNUMS) -d SFX amiga/amiga.c\n\n$(O)crc_68.o : amiga/crc_68.a\n\tas -n -o $(O)crc_68.o amiga/crc_68.a\n# no debug version of crc_68\n\n$(O)filedate.fo : amiga/filedate.c\n\t$(CC) -o $(O)filedate.fo -d FUNZIP $(CFLAGS) amiga/filedate.c\n\n$(O)filedate.fd : amiga/filedate.c\n\t$(CC) -o $(O)filedate.fd -d FUNZIP $(CFLAGD) amiga/filedate.c\n\n# The file t:G_offs.a is generated on the fly by programs we compile\n# and then run, and then it's included into amiga/flate.a to provide\n# definitions for it.  There are no debug versions of flate.o.\n\n$(O)flate.o : amiga/flate.a amiga/gbloffs\n\tamiga/gbloffs > t:G_offs.a\n\tas -n -o $(O)flate.o -eINT16 amiga/flate.a\n\t-@delete t:G_offs.a\n\n$(O)flate.fo : amiga/flate.a amiga/Fgbloffs\n\tamiga/Fgbloffs > t:G_offs.a\n\tas -n -o $(O)flate.fo -eINT16 -eFUNZIP -eAZTEC amiga/flate.a\n\t-@delete t:G_offs.a\n\n$(O)flate.xo : amiga/flate.a amiga/Xgbloffs\n\tamiga/Xgbloffs > t:G_offs.a\n\tas -n -o $(O)flate.xo -eINT16 -eSFX amiga/flate.a\n\t-@delete t:G_offs.a\n\n# Here are the programs that generate different versions of G_offs.a:\n\namiga/gbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h\n\t$(CC) -o t:gbloffs.o $(CFLAGS) gbloffs.c\n\t$(LD) $(LDFLAGS) -o amiga/gbloffs t:gbloffs.o $(LDLIBS)\n\t-@delete t:gbloffs.o\n\namiga/Fgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h\n\t$(CC) -o t:gbloffs.o $(CFLAGS) -d FUNZIP gbloffs.c\n\t$(LD) $(LDFLAGS) -o amiga/Fgbloffs t:gbloffs.o $(LDLIBS)\n\t-@delete t:gbloffs.o\n\namiga/Xgbloffs : gbloffs.c unzip.h unzpriv.h globals.h amiga/amiga.h crypt.h\n\t$(CC) -o t:gbloffs.o $(CFLAGS) -d SFX gbloffs.c\n\t$(LD) $(LDFLAGS) -o amiga/Xgbloffs t:gbloffs.o $(LDLIBS)\n\t-@delete t:gbloffs.o\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/makesfx.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* MakeSFX: join UnZipSFX and a .zip archive into a single self-extracting   */\n/* Amiga program.  On most systems simple concatenation does the job but for */\n/* the Amiga a special tool is needed.  By Paul Kienitz, no rights reserved. */\n/* This program is written portably, so if anyone really wants to they can   */\n/* produce Amiga self-extracting programs on a non-Amiga.  We are careful    */\n/* not to mix Motorola-format longwords read from files with native long     */\n/* integers.  Not necessarily limited to use with only the Zip format --     */\n/* just combine any archive with any self-extractor program that is capable  */\n/* of reading a HUNK_DEBUG section at the end as an archive.                 */\n\n#include <stat.h>\n#include <string.h>\n#include <stdio.h>\n#include <stdlib.h>\n#ifdef __SASC\n#  include <proto/dos.h>\n#  ifdef DEBUG\n#    include <sprof.h>\n#  endif\n#endif /* __SASC */\n#ifdef AZTEC_C\n#  include <dos/dos.h>\n#  include <clib/dos_protos.h>\n#endif /* AZTEC_C */\n\ntypedef unsigned long ulg;\ntypedef unsigned char uch;\ntypedef unsigned short bool;\n#define false 0\n#define true  1\n\n/* the following are extracted from Commodore include file dos/doshunks.h: */\n#define HUNK_NAME       1000L\n#define HUNK_CODE       1001L\n#define HUNK_DATA       1002L\n#define HUNK_BSS        1003L\n#define HUNK_RELOC32    1004L\n#define HUNK_SYMBOL     1008L\n#define HUNK_DEBUG      1009L\n#define HUNK_END        1010L\n#define HUNK_HEADER     1011L\n#define HUNK_OVERLAY    1013L\n#define HUNK_BREAK      1014L\n\n/* Convert a big-endian (Motorola) sequence of four bytes to a longword: */\n#define CHARS2LONG(b)   (((ulg)(b)[0] << 24) | ((ulg)(b)[1] << 16) | \\\n                         ((ulg)(b)[2] << 8) | ((ulg)(b)[3]))\n/* b must be (uch *) in each of these.  Now the reverse: */\n#define LONG2CHARS(b,l) ((b)[0] = (uch)((l) >> 24), (b)[1] = (uch)((l) >> 16),\\\n                         (b)[2] = (uch)((l) >> 8), (b)[3] = (uch)(l))\n\n#define COPYBUFFER      16384\n\nulg totalwritten = 0;\n\n\nbool CopyData(FILE *out, FILE *inn, ulg archivesize,\n              char *outname, char *inname)\n{\n    static uch buf[COPYBUFFER];\n    ulg written;\n    size_t chunk;\n\n    if (archivesize) {\n        LONG2CHARS(buf, HUNK_DEBUG);\n        written = (archivesize + 3) / 4;\n        LONG2CHARS(buf + 4, written);\n        if (fwrite(buf, 1, 8, out) < 8) {\n            printf(\"Error writing in-between data to %s\\n\", outname);\n            return false;\n        }\n        totalwritten += 8;\n    }\n    written = 0;\n    do {\n        chunk = fread(buf, 1, COPYBUFFER, inn);\n        if (ferror(inn)) {\n            printf(\"Error reading data from %s\\n\", inname);\n            return false;\n        }\n        if (!archivesize && !written) {   /* true only for first block read */\n            if (CHARS2LONG(buf) != HUNK_HEADER) {\n                printf(\"%s is not an Amiga executable.\\n\", inname);\n                return false;\n            }\n        }\n        if (fwrite(buf, 1, chunk, out) < chunk) {\n            printf(\"Error writing %s to %s\\n\", archivesize ? \"archive data\" :\n                                               \"self-extractor code\", outname);\n            return false;\n        }\n        written += chunk;\n        totalwritten += chunk;\n    } while (!feof(inn));\n    if (archivesize) {\n        if (written != archivesize) {\n            printf(\"Wrong number of bytes copied from archive %s\\n\", outname);\n            return false;\n        }\n        LONG2CHARS(buf, 0);\n        chunk = 3 - (written + 3) % 4;\n        LONG2CHARS(buf + chunk, HUNK_END);\n        chunk += 4;\n        if (fwrite(buf, 1, chunk, out) < chunk) {\n            printf(\"Error writing end-marker data to %s\\n\", outname);\n            return false;\n        }\n        totalwritten += chunk;\n    }\n    return true;\n}\n\n\nvoid main(int argc, char **argv)\n{\n    FILE *out, *arch, *tool;\n    char *toolname = argv[3];\n    struct stat ss;\n    int ret;\n    ulg archivesize;\n\n    if (argc < 3 || argc > 4) {\n        printf(\"Usage: %s <result-file> <zip-archive> [<self-extractor-\"\n               \"program>]\\nThe third arg defaults to \\\"UnZipSFX\\\" in the\"\n               \" current dir or C:.\\n\", argv[0]);\n        exit(20);\n    }\n    if (!(arch = fopen(argv[2], \"rb\"))) {\n        printf(\"Could not find archive file %s\\n\", argv[2]);\n        exit(10);\n    }\n    if (stat(argv[2], &ss) || !(archivesize = ss.st_size)) {\n        fclose(arch);\n        printf(\"Could not check size of archive %s, or file is empty.\\n\",\n               argv[2]);\n        exit(10);\n    }\n    if (argc < 4)\n        toolname = \"UnZipSFX\";\n    if (!(tool = fopen(toolname, \"rb\"))) {\n        BPTR lk = Lock(\"C:\", ACCESS_READ);\n        BPTR ocd = lk ? CurrentDir(lk) : 0;\n        if (!(tool = fopen(toolname, \"rb\"))) {\n            fclose(arch);\n            printf(\"Could not find self-extractor program %s\\n\", toolname);\n            if (lk)\n                UnLock(CurrentDir(ocd));\n            exit(10);\n        }\n        if (lk)\n            UnLock(CurrentDir(ocd));\n    }\n    if (!(out = fopen(argv[1], \"wb\"))) {\n        fclose(arch);\n        fclose(tool);\n        printf(\"Could not create output file %s\\n\", argv[1]);\n        exit(10);\n    }\n    ret = CopyData(out, tool, 0, argv[1], toolname)\n          && CopyData(out, arch, archivesize, argv[1], argv[2]) ? 0 : 10;\n    fclose(out);\n    fclose(arch);\n    fclose(tool);\n    if (ret) {\n        printf(\"Deleting %s\\n\", argv[1]);\n        remove(argv[1]);\n    } else\n        printf(\"%s successfully written, size %lu bytes.\\n\",\n                argv[1], totalwritten);\n    exit(ret);\n}\n\n\n#if (defined(AZTEC_C) && defined(MCH_AMIGA))\nvoid _wb_parse(void) { }        /* avoid unneeded infrastructure */\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/smakefile",
    "content": "#===========================================================================\n# Makefile for UnZip, ZipInfo, fUnZip, MakeSFX      AMIGA SAS/C Version 6.58\n# Version:  5.53                                    last revised:  25 Dec 06\n#===========================================================================\n# from John Bush <john.bush@east.sun.com>\n#            or: <JBush@bix.com>\n\n# updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40)\n# by Haidinger Walter <walthaid@unix.ict.tuwien.ac.at>\n\n# additional supplements and maintenance by Paul Kienitz\n\n# This makefile should work with at least AmigaDOS 2.04 (V37)  (not tested)\n# and will probably not work with AmigaDOS 1.3 (V34)\n\n# If you have any improvements, critics or else please feel free to mail.\n# Any response is appreciated. Haidinger Walter <walthaid@unix.ict.tuwien.ac.at>\n\n# Available targets:\n# all           builds all executables below\n# unzip         builds unzip executable\n# unzipsfx      builds unzipsfx executable\n# funzip        builds funzip executable\n# makesfx       builds makesfx executable\n# clean         remove all files created by the compilation\n# spotless      like clean target but removes binaries too\n\n\n##########################\n# USER MACRO DEFINITIONS #\n##########################\n\n# Set the processor to generate code for UnZip and fUnZip. Specify one of:\n# ANY 68000 68010 68020 68030 68040 68060  (Default: ANY or 68000)\n\n# Use of the assembly versions is not supported yet since some of the asm\n# source file do not assemble with 68000 instructions.\n# Any help is appreciated of course.\n\nCUSECPU = ANY\n\n# Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+\n# The utility.library is *not* used for UnZipSFX to ensure maximum portability\n# between the different Amiga systems (minimal config: 68000 and OS 1.2).\n# You can change this by adding the $(LUTIL) macro in the UnZipSFX linking\n# rules (See below: Final output targets, UnZipSFX:).\n# WARNINGS when using the utility library:\n# 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher.\n# 2. You *need not* compile/link with short-integers using the\n#    utility.library. It will crash your machine. See Libraries below.\n#\n# Default: commented (not used)\n#\n#CUTIL = UTILLIB DEFINE=_UTILLIB\n#LUTIL = WITH SC:LIB/utillib.with    # include necessary linker defines\n\n\n# Choose one stack-handling method (default=faster)\n# StackExtend: Dynamic runtime stack extension. You won't notice stack overflows.\n# StackCheck: On a stack overflow a requester appears which allows you to exit.\n# Note that either stack watching will slow down your executable because of the\n# extra code run on each function entry. On the other hand, you won't crash\n# anymore due to stack overflows. However, you should not have *any* stack\n# problems with info-zip if you raise your stack to 20000 (which I'd\n# recommend as a minimum default stack for all applications) or more using the\n# shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup.\n# BTW: Typing 'Stack' prints your current stack size.\n#\nCSTACK = NOSTACKCHECK STACKEXTEND     # slow, but always works\n#CSTACK = STACKCHECK NOSTACKEXTEND    # slow, requester & graceful exit\n#CSTACK = NOSTACKCHECK NOSTACKEXTEND  # faster but relies on larger stack (>=10K)\n\n#\n# LIBRARIES\n# ---------\n\n# Choose one DATAOPTS , SASLIB and LSTARTUP\n# Always comment/uncomment all macros of a set.\n\n# Library to use with near data and 2-byte integers\n# Notes: o  slower than 4-byte integers with 68000 cpu\n#        o  *not* recommended due to poor overall performance\n#        o  see comment in amiga/osdep.h\n#DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA\n#SASLIB   = scs\n#LSTARTUP = cres.o\n\n# Library to use with near data and 4-byte integers (DEFAULT)\n# *** use this with the utility.library ***\nDATAOPTS = DATA=NEAR DEF=_NEAR_DATA\nSASLIB   = sc\nLSTARTUP = cres.o\n\n# Library to use with far data and 2-byte integers\n# use if DYN_ALLOC is not defined\n# old default - far data always works but is slower\n#DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA\n#SASLIB   = scsnb\n#LSTARTUP = c.o\n\n# Library to use with far data and 4-byte integers\n# if everything else fails: try this\n#DATAOPTS = DATA=FAR DEF=_FAR_DATA\n#SASLIB   = scnb\n#LSTARTUP = c.o\n\n\n#\n# DEBUGGING\n# ---------\n\n# Default: No debugging information added.\n# The two macros below will be overwritten if you choose to add\n# debug info, therefore need to comment.\nCDBG = NODEBUG NOPROFILE NOCOVERAGE    # default: no debug info\nLDBG = STRIPDEBUG                      # default: no debug info\n\n# Compiler and loader debug flags.  Uncomment as needed.  Recomment when done.\n# Optimization disabled for faster compilation (by using NOOPT)\n#CDBG1 = DEF=DEBUG DEF=DEBUG_TIME     # enables Info-ZIP's debug output\n\n# Enable profiling and coverage when desired. Option COVERAGE commented\n# seperately because running coverage may corrupt your drive in case of a\n# system crash since a file 'cover.dat' is created in your working directory.\n# Note that the use of COVERAGE forces the use of the c.o startup module.\n#CDBG2 = PROFILE\n#CDBG3 = COVERAGE        # must use c.o startup code:\n#LSTARTUP = c.o          # Uncomment *only* when you use COVERAGE\n\n# *Uncomment* _HERE_ macros CDBG and LDBG to include debugging information\n#CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT\n#LDBG = ADDSYM\n# Optional use of memwatch.library which can be found in your\n# sc:extras/memlib directory. Please read the short docs (memlib.doc).\n# Note that memlib has a small bug: MWTerm() displays always the first entry.\n# Get the latest version from aminet (dev/debug/memlib.lha) or\n# contact me to get the patch. Uncomment all macros to use.\n#CMEMLIB  = DEFINE=MWDEBUG=1       # define to enable library\n#LMEMLIB  = SC:LIB/memwatch.lib    # path to library\n#LSTARTUP = c.o                    # must use c.o with memlib!\n\n\n#\n# MAPPING\n# -------\n\n# Map filenames used when mapping (no need to comment)\n#\nMAPFS = unzip.map               # UnZip    map filename\nMAPFX = unzipsfx.map            # UnZipSFX map filename\nMAPFF = funzip.map              # fUnZip   map filename\nMAPFM = makesfx.map             # MakeSFX  map filename\n\n# Map file output: Uncomment to highlight and bold headings.\n#\n#MAPFSTYLE = FANCY\n\n# Map flags for each EXECUTABLE. Uncomment to enable mapping.\n# For map options please refer to:\n# SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map\n# Default: all options enabled: f,h,l,o,s,x\n#                                 |-> options start here\n#LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x   # UnZip    maps\n#LMAPX = $(MAPFSTYLE) MAP $(MAPFX) f,h,l,o,s,x   # UnZipSFX maps\n#LMAPF = $(MAPFSTYLE) MAP $(MAPFF) f,h,l,o,s,x   # fUnZip   maps\n#LMAPM = $(MAPFSTYLE) MAP $(MAPFM) f,h,l,o,s,x   # MakeSFX  maps\n\n\n#\n# LISTINGS\n# --------\n\n# Listfile-extensions for each executable (enter *with* dot)\n#\nLISTEXTS = .lst         # extension for UnZip and MakeSFX listfiles\nLISTEXTX = .xlst        # extension for UnZipSFX listfiles\nLISTEXTF = .flst        # extension for fUnZip listfiles\n\n\n# List files and cross references for each OBJECT.\n# Add/remove flags as needed. All listed by default.\n# Use LISTINCLUDES only to determine the dependencies for smake\n#\nCLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES\nCXREFOPT = XHEAD XSYS\n#\n# Uncomment to enable listing (default: commented)\n# *** WARNING: List files require *lots* of disk space!\n#\n#CLIST = LIST $(CLISTOPT)\n#CXREF = XREF $(CXREFOPT)\n\n\n#\n# SUPPRESSED COMPILER WARNINGS\n# ----------------------------\n\n# Compiler warnings to ignore\n#\n# Warning 105 : module does not define any externally-known symbols\n# Warning 304 : Dead assignment eliminated...\n# Note    306 : ...function inlined...\n# Warning 317 : possibly uninitialized variable...\n# Comment to enable.\n#\nCIGNORE = IGNORE=105,304,306,317\n\n\n#\n# OBJECT EXTENSIONS\n#\n\n# Extensions used for objects of each executeable.\n# Transformation rules require unique extensions.\n# Enter *with* dot.\n#\nO  = .o         # general extension for objects\nOX = .xo        # extension for special UnZipSFX objects\nOF = .fo        # extension for special fUnZip objects\n\n\n# Filename used to store converted options from environment variable\n# LOCAL_UNZIP. Default: scoptions_local_unzip\n#\nCWITHOPT = scoptions_local_unzip\n\n\n# Filenames to store compiler options to prevent command line overflow\n#\n# Options file for UnZip and fUnZip\nCFILEC = scoptions-unzip\n# Options file for UnZipSFX\nCFILEX = scoptions-unzipsfx\n# Special options for MakeSFX\nCFILEM = scoptions-makesfx\n\n\n# Temp filenames for object lists to load using linker \"WITH\" command.\n#\nOBJLISTS = unzip_objlist.with            # UnZip    object list\nOBJLISTX = unzipsfx_objlist.with         # UnZipSFX object list\nOBJLISTF = funzip_objlist.with           # fUnZip   object list\nOBJLISTM = makesfx_objlist.with          # MakeSFX  object list\n\n\n# Filenames to store linker options\n#\nLWITHS = unzip.lnk                       # UnZip    linker options\nLWITHX = unzipsfx.lnk                    # UnZipSFX linker options\nLWITHF = funzip.lnk                      # fUnZip   linker options\nLWITHM = makesfx.lnk                     # MakeSFX  linker options\n\n\n######################################\n#  NOTHING TO CHANGE BEYOND HERE ... #\n######################################\n\n\n# Compiler definitions\n#\nCC = sc\n#\n# Optimizer flags\n#\nOPTPASSES = 6     # set number of global optimizer passes\n#\nOPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED\nOPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES)\nOPT  = $(OPT1) $(OPT2)\n\n# Compiler flags\n#\n# cpu flags for UnZip and fUnZip\nCCPUOPTSF = CPU=$(CUSECPU) $(CUTIL)\n# cpu flags for UnzipSFX and MakeSFX (ensures portability to all Amigas)\nCCPUOPTXM = CPU=ANY\n\nCDEFINES = $(CMEMLIB) $(CDEFINES) DEF=AMIGA DEF=PROTO\nCOPTIONS = CODE=NEAR NMINC VERBOSE STRINGMERGE PARAMETERS=BOTH\nCOPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF)\nCOPTIONS = $(COPTIONS) $(CSTACK) STRICT UNSCHAR NOICONS\nCOPTIONS = $(COPTIONS) $(CIGNORE) $(OPT) $(CDBG)\n# common compiler flags\nCFLAGSC  = $(CDEFINES) $(DATAOPTS) $(COPTIONS)\n# special compiler flags with $(DATAOPTS) excluded\nCFLAGSS  = $(CDEFINES) $(COPTIONS)\n\n# Linker definitions\n#  See SASLIB definition above\n#\nLD = slink\n# special linker flags for UnZip to create pure (i.e. resident) binary.\nLDFLAGSS = FROM SC:LIB/$(LSTARTUP)\n# common linker flags for all other executeables\nLDFLAGSC = FROM SC:LIB/c.o\n\nLDFLAGS2 = NOICONS $(LDBG)\n# special linker flags to select library set above\nLIBFLAGSS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib\n# common linker flags\nLIBFLAGSC = LIB $(LMEMLIB) SC:LIB/sc.lib SC:LIB/amiga.lib\n\n\n##################\n# TARGET OBJECTS #\n##################\n\n\n# UnZip Objects\nOBJS1 = unzip$(O) crc32$(O) crypt$(O) envargs$(O) explode$(O)\nOBJS2 = extract$(O) fileio$(O) globals$(O) list$(O) inflate$(O) match$(O)\nOBJS3 = process$(O) ttyio$(O) ubz2err$(O) unreduce$(O) unshrink$(O) zipinfo$(O)\nOBJSA = amiga$(O) timezone$(O)\nOBJS  = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJSA)\n\n# UnZipSFX Objects\nOBJX1 = unzip$(OX) extract$(OX) inflate$(OX) match$(OX) process$(OX)\nOBJXI = crypt$(OX) crc32$(OX) fileio$(OX) globals$(OX) ttyio$(OX) ubz2err$(OX)\nOBJXA = amiga$(OX) timezone$(OX)\nOBJX  = $(OBJX1) $(OBJXI) $(OBJXA)\n\n# fUnZip Objects\nOBJF1 = funzip$(O)\nOBJF2 = crc32$(OF) crypt$(OF) globals$(OF) inflate$(OF) ttyio$(OF)\nOBJFA = filedate$(OF) stat$(O)\nOBJF  = $(OBJF1) $(OBJF2) $(OBJFA)\n\n# MakeSFX Objects\nOBJM = makesfx$(O)\n\n# Common header files\nUNZIP_H1 = unzip.h unzpriv.h globals.h\nUNZIP_HA = amiga/amiga.h amiga/z-stat.h\nUNZIP_H  = $(UNZIP_H1) $(UNZIP_HA)\n\n# Output targets\nUNZIPS = UnZip UnZipSFX fUnZip MakeSFX\n\n\n#######################################\n# DEFAULT TARGET AND PROCESSING RULES #\n#######################################\n\nall: request flush $(UNZIPS)\n\n# UnZip transformation rules\n#\n.c$(O) :\n        $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c\n\n# UnZipSFX transformation rules\n#\n.c$(OX):\n        $(CC) DEF=SFX WITH=$(CFILEC) LISTFILE=$>$(LISTEXTX) OBJNAME=$@ $*.c\n\n# fUnZip transformation rules\n#\n.c$(OF):\n        $(CC) DEF=FUNZIP WITH=$(CFILEC) LISTFILE=$>$(LISTEXTF) OBJNAME=$@ $*.c\n\n\n#########################\n# Final output targets. #\n#########################\n\nunzip:    local_unzip CommonFlags $(OBJS)\n          @Echo \"$(OBJS)\" >$(OBJLISTS)\n          Type $(OBJLISTS)\n# -----\n# Note:   Change $(LDFLAGSS) to $(LDFLAGSC) if DYN_ALLOC is *not* defined.\n# -----\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGSS) \" \\\n                \"$(LDFLAGS2) $(LMAPS)\" >$(LWITHS)\n          Type $(LWITHS)\n          $(LD) TO UnZip    WITH $(LWITHS)\n\nfunzip:   local_unzip CommonFlags $(OBJF)\n          @Echo \"$(OBJF)\" >$(OBJLISTF)\n          Type $(OBJLISTF)\n          @Echo \"$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTF) $(LIBFLAGSS) \" \\\n                \"$(LDFLAGS2) $(LMAPF)\" >$(LWITHF)\n          Type $(LWITHF)\n          $(LD) TO fUnZip   WITH $(LWITHF)\n\nunzipsfx: local_unzip SFXFlags $(OBJX)\n          @Echo \"$(OBJX)\" >$(OBJLISTX)\n          Type $(OBJLISTX)\n# ----\n# Note:   Insert $(LUTIL) here, to use utility library with UnZipSFX.\n# -----                      vvvvvvv\n          @Echo \"$(LDFLAGSC)          WITH $(OBJLISTX) $(LIBFLAGSS) \" \\\n                \"$(LDFLAGS2) $(LMAPX)\" >$(LWITHX)\n          Type $(LWITHX)\n          $(LD) TO UnZipSFX WITH $(LWITHX)\n\n\nmakesfx:  MakeSFXFlags $(OBJM)\n          @Echo \"$(OBJM)\" >$(OBJLISTM)\n          Type $(OBJLISTM)\n          @Echo \"$(LDFLAGSC) $(LUTIL) WITH $(OBJLISTM) $(LIBFLAGSC) \" \\\n                \"$(LDFLAGS2) $(LMAPM)\" >$(LWITHM)\n          Type $(LWITHM)\n          # never use short-integers with MakeSFX !\n          $(LD) TO MakeSFX  WITH $(LWITHM)\n\nclean:\n        -Delete >nil: $(OBJS) quiet\n        -Delete >nil: $(OBJX) quiet\n        -Delete >nil: $(OBJF) quiet\n        -Delete >nil: $(OBJM) quiet\n        -Delete >nil: $(OBJLISTS) $(OBJLISTX) $(OBJLISTF) $(OBJLISTM) quiet\n        -Delete >nil: $(MAPFS) $(MAPFX) $(MAPFF) $(MAPFM) quiet\n        -Delete >nil: \\#?$(LISTEXTS) \\#?$(LISTEXTX) \\#?$(LISTEXTF) quiet\n        -Delete >nil: $(CWITHOPT) $(CFILEC) $(CFILEX) $(CFILEM) quiet\n        -Delete >nil: SCOPTIONS SASCOPTS quiet\n        -Delete >nil: $(LWITHS) $(LWITHX) $(LWITHF) $(LWITHM) quiet\n        -Delete >nil: \\#?.q.?? \\#?.tmp \\#?.cov quiet\n\nspotless: clean\n        -Delete >nil: $(UNZIPS) quiet\n\n\n# UnZip dependencies:\n# (objects not needed by Amiga port are commented)\n\n# special rule for adding Amiga internal version number to UnZip\namiga$(O):          amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h env:Workbench\nstat$(O):           amiga/stat.c     amiga/z-stat.h\nfiledate$(O):       amiga/filedate.c crypt.h timezone.h\napi$(O):            api.c      $(UNZIP_H) unzvers.h #zlib.h\napihelp$(O):        apihelp.c  $(UNZIP_H) unzvers.h\ncrc32$(O):          crc32.c    $(UNZIP_H) zip.h crc32.h\ncrypt$(O):          crypt.c    $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs$(O):        envargs.c  $(UNZIP_H)\nexplode$(O):        explode.c  $(UNZIP_H)\nextract$(O):        extract.c  $(UNZIP_H) crc32.h crypt.h\nfileio$(O):         fileio.c   $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(O):        globals.c  $(UNZIP_H)\ninflate$(O):        inflate.c  $(UNZIP_H) inflate.h #zlib.h\nlist$(O):           list.c     $(UNZIP_H)\nmatch$(O):          match.c    $(UNZIP_H)\nprocess$(O):        process.c  $(UNZIP_H) crc32.h\ntimezone$(O):       timezone.c $(UNZIP_H) zip.h timezone.h\nttyio$(O):          ttyio.c    $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(O):        ubz2err.c  $(UNZIP_H)\nunreduce$(O):       unreduce.c $(UNZIP_H)\nunshrink$(O):       unshrink.c $(UNZIP_H)\nunzip$(O):          unzip.c    $(UNZIP_H) crypt.h unzvers.h consts.h #zlib.h\n#unzipstb$(O):       unzipstb.c $(UNZIP_H) unzvers.h\nzipinfo$(O):        zipinfo.c  $(UNZIP_H)\n\n\n# UnZipSFX dependencies:\n#\n# special rule for adding Amiga internal version number to UnZipSFX\namiga$(OX):      amiga/amiga.c amiga/filedate.c amiga/stat.c $(UNZIP_H) crypt.h timezone.h\nunzip$(OX):      unzip.c    $(UNZIP_H) crypt.h unzvers.h consts.h\ncrc32$(OX):      crc32.c    $(UNZIP_H) zip.h crc32.h\ncrypt$(OX):      crypt.c    $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nextract$(OX):    extract.c  $(UNZIP_H) crc32.h crypt.h\nfileio$(OX):     fileio.c   $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(OX):    globals.c  $(UNZIP_H)\ninflate$(OX):    inflate.c  $(UNZIP_H) inflate.h #zlib.h\nmatch$(OX):      match.c    $(UNZIP_H)\nprocess$(OX):    process.c  $(UNZIP_H) crc32.h\ntimezone$(OX):   timezone.c $(UNZIP_H) zip.h timezone.h\nttyio$(OX):      ttyio.c    $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OX):    ubz2err.c  $(UNZIP_H)\n\n\n# fUnZip dependencies:\n#\nfunzip$(O):      funzip.c   $(UNZIP_H) crc32.h crypt.h ttyio.h\ncrc32$(OF):      crc32.c    $(UNZIP_H) zip.h crc32.h\ncrypt$(OF):      crypt.c    $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nglobals$(OF):    globals.c  $(UNZIP_H)\ninflate$(OF):    inflate.c  $(UNZIP_H) inflate.h crypt.h #zlib.h\nttyio$(OF):      ttyio.c    $(UNZIP_H) zip.h crypt.h ttyio.h\nfiledate$(OF):   amiga/filedate.c crypt.h\n\n\n# MakeSFX dependencies\n#\n# special transformation rules to never use shortintegers:\nmakesfx$(O):      amiga/makesfx.c\n        $(CC) WITH=$(CFILEM) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c\n\n\n########################\n# DEPENDECIES END HERE #\n########################\n\n# flush all libraries to provide more mem for compilation\nflush:\n        @Avail flush >nil:\n\n# write common compiler flags to file and echo to user\nCommonFlags:\n        @Echo \"$(CFLAGSC)\" \"$(CCPUOPTSF)\" >$(CFILEC)\n        @Type \"$(CWITHOPT)\"              >>$(CFILEC)\n        -Type $(CFILEC)\n\nSFXFlags:\n        @Echo \"$(CFLAGSC)\" \"$(CCPUOPTXM)\" >$(CFILEX)\n        @Type \"$(CWITHOPT)\"              >>$(CFILEX)\n        -Type $(CFILEX)\n\n# write special MakeSFX flags\nMakeSFXFlags:\n        @Echo \"$(CFLAGSS) $(CCPUOPTXM) DATA=NEAR NOSHORTINTEGERS\" >$(CFILEM)\n        # not really needed but if someday used:\n        @Type \"$(CWITHOPT)\" >>$(CFILEM)\n        -Type $(CFILEM)\n\n\n# special rule for adding Amiga internal version number to amiga.c\namiga$(O):\n        rx > env:VersionDate \"say '\"\"'translate(date('E'),'.','/')'\"\"'\"\n        $(CC) WITH=$(CFILEC) LISTFILE=$>$(LISTEXTS) OBJNAME=$@ $*.c\n        -Delete env:VersionDate\n\n\n# needed in amiga/amiga.c\n# should be set in startup-sequence, but just in case:\n# (only works with OS 2.04 and above)\n\nenv\\:WorkBench:\n        @Execute < < (Workbench_smk.tmp)\n           FailAt 21\n           If not exists ENV:Workbench\n              Version >nil:\n              SetEnv Workbench $$Workbench\n           Endif\n        <\n\n\n# #################\n# ### LOCAL_UNZIP ###\n# #################\n#\n# Read environment variable LOCAL_UNZIP and convert options from old Lattice\n# v5 to new SAS/C v6 format. You may also use the new DEFINE= syntax but\n# be sure not to mix v5 and v6 options, otherwise lctosc will be confused.\n#\n# e.g.: to define FOO_ONE and FOO_TWO enter:\n#\n# SetEnv LOCAL_UNZIP \"-DFOO_ONE -DFOO_TWO\"\n#\n# To make this permanent, i.e. survive an reboot, put the statement into\n# your startup-sequence or (for AmigaDOS 2.0 or higher only) make sure\n# LOCAL_UNZIP is stored in the ENVARC: directory too. To do this, simply\n# copy the file from ENV: to ENVARC:\n#   Copy ENV:LOCAL_UNZIP ENVARC:\n#\n# For a list of all valid non-standard compilation options see the INSTALL\n# file in the root zip tree. Please read the notes there before using the\n# non-standard options.\n#\n# e.g.: To use the non-standard timezone environment variable \"INFOZIP_TZ\"\n#\t(or another arbitary name) instead of \"TZ\", type in your shell:\n#\n#\tSetenv LOCAL_UNZIP \"-DTZ_ENVVAR=*\"INFOZIP_TZ*\"\"\n#\n# Note that you need to escape the quotes of INFOZIP_TZ with leading stars.\n# To verify that LOCAL_UNZIP has been saved correctly, use the Getenv command:\n#\n#\tGetenv LOCAL_UNZIP\n#\n# ...should display:\n#\n#\t-DTZ_ENVVAR=\"INFOZIP_TZ\"\n#\n\nlocal_unzip:\n        @Execute < < (Local_UnZip_smk.tmp)\n           Failat 21\n           Echo \"\"\n           If exists ENV:LOCAL_UNZIP\n              Echo \"Using environment variable LOCAL_UNZIP !\"\n              Echo \"LOCAL_UNZIP: \" NOLINE\n              GetEnv LOCAL_UNZIP\n              Copy >NIL: ENV:LOCAL_UNZIP SASCOPTS\n           Else\n              Echo \"You could use envvar LOCAL_UNZIP to set your special compilation options.\"\n              Echo \"See the makefile for more information (LOCAL_UNZIP section).\"\n              Delete >nil: SASCOPTS quiet\n           Endif\n           Echo \"\"\n           ; Do not remove the lctosc command! If LOCAL_UNZIP is unset, an\n           ; empty file is created which needed by CommonFlags !\n           ; Moreover, lctosc also accepts new v6 options, i.e. only changes\n           ; known v5 options. Try `lctosc -Dfoo' and `lctosc DEFINE=foo'.\n           ; However, you *must not* mix v5 and v6 options!\n           lctosc > $(CWITHOPT)\n           ; Now make sure that env:sc/scoptions are NOT used\n           ; we just create an empty file. The options are stored elsewhere.\n           Echo > SCOPTIONS \"\" NOLINE\n        <\n\n\n\n# Echo request to the user\n#\nrequest:\n        @Echo \"\"\n        @Echo \" This makefile is for use with SAS/C version 6.58.\"\n        @Echo \" If you still have an older version, please upgrade!\"\n        @Echo \" Patches are available on the Aminet under biz/patch/sc\\#?.\"\n        @Echo \"\"\n        @Echo \" Just a simple request...\"\n        @Echo \" Please give me a mail that you compiled whether you encounter any errors\"\n        @Echo \" or not. I'd just like to know how many Amiga users actually make use of\"\n        @Echo \" this makefile.\"\n        @Echo \" If you mail me, I'll put you on my mailing-list and notify you whenever\"\n        @Echo \" new versions of Info-Zip are released.\"\n        @Echo \" Have a look at the makefile for changes like CPU type, UtilLib, Stack, etc.\"\n        @Echo \" Feel free to mail comments, suggestions, critics...\"\n        @Echo \" Enjoy Info-Zip !\"\n        @Echo \" Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>\"\n        @Echo \"\"\n\n# Echo help in case of an error\n#\n.ONERROR:\n        @Echo \"\"\n        @Echo \"[sigh] An error running this makefile was detected.\"\n        @Echo \"This message may also appear if you interrupted smake by pressing CTRL-C.\"\n        @Echo \"Contact Info-ZIP authors at Zip-Bugs@lists.wku.edu or me for help.\"\n        @Echo \"Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>\"\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/stat.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Here we have a handmade stat() function because Aztec's c.lib stat() */\n/* does not support an st_mode field, which we need... also a chmod().  */\n\n/* This stat() is by Paul Wells, modified by Paul Kienitz. */\n/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01  */\n/* Adapted for SAS/C 6.5x by Haidinger Walter */\n\n/* POLICY DECISION: We will not attempt to remove global variables from */\n/* this source file for Aztec C.  These routines are essentially just   */\n/* augmentations of Aztec's c.lib, which is itself not reentrant.  If   */\n/* we want to produce a fully reentrant UnZip, we will have to use a    */\n/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */\n\n#ifndef __amiga_stat_c\n#define __amiga_stat_c\n\n#include <exec/types.h>\n#include <exec/memory.h>\n#include \"amiga/z-stat.h\"             /* fake version of stat.h */\n#include <string.h>\n\n#ifdef AZTEC_C\n#  include <libraries/dos.h>\n#  include <libraries/dosextens.h>\n#  include <clib/exec_protos.h>\n#  include <clib/dos_protos.h>\n#  include <pragmas/exec_lib.h>\n#  include <pragmas/dos_lib.h>\n#endif\n#ifdef __SASC\n#  include <sys/dir.h>               /* SAS/C dir function prototypes */\n#  include <sys/types.h>\n#  include <proto/exec.h>\n#  include <proto/dos.h>\n#endif\n\n#ifndef SUCCESS\n#  define SUCCESS (-1)\n#  define FAILURE (0)\n#endif\n\n\nvoid close_leftover_open_dirs(void);    /* prototype */\n\nstatic DIR *dir_cleanup_list = NULL;    /* for resource tracking */\n\n/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */\nvoid close_leftover_open_dirs(void)\n{\n    while (dir_cleanup_list)\n        closedir(dir_cleanup_list);\n}\n\n\nunsigned short disk_not_mounted;\n\nextern int stat(const char *file, struct stat *buf);\n\nstat(file,buf)\nconst char *file;\nstruct stat *buf;\n{\n\n        struct FileInfoBlock *inf;\n        BPTR lock;\n        time_t ftime;\n        struct tm local_tm;\n\n        if( (lock = Lock((char *)file,SHARED_LOCK))==0 )\n                /* file not found */\n                return(-1);\n\n        if( !(inf = (struct FileInfoBlock *)AllocMem(\n                (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )\n        {\n                UnLock(lock);\n                return(-1);\n        }\n\n        if( Examine(lock,inf)==FAILURE )\n        {\n                FreeMem((char *)inf,(long)sizeof(*inf));\n                UnLock(lock);\n                return(-1);\n        }\n\n        /* fill in buf */\n        buf->st_dev         =\n        buf->st_nlink       =\n        buf->st_uid         =\n        buf->st_gid         =\n        buf->st_rdev        = 0;\n        buf->st_ino         = inf->fib_DiskKey;\n        buf->st_blocks      = inf->fib_NumBlocks;\n        buf->st_size        = inf->fib_Size;\n\n        /* now the date.  AmigaDOS has weird datestamps---\n         *      ds_Days is the number of days since 1-1-1978;\n         *      however, as Unix wants date since 1-1-1970...\n         */\n\n        ftime =\n                (inf->fib_Date.ds_Days * 86400 )                +\n                (inf->fib_Date.ds_Minute * 60 )                 +\n                (inf->fib_Date.ds_Tick / TICKS_PER_SECOND )     +\n                (86400 * 8 * 365 )                              +\n                (86400 * 2 );  /* two leap years */\n\n        /* tzset(); */  /* this should be handled by mktime(), instead */\n        /* ftime += timezone; */\n        local_tm = *gmtime(&ftime);\n        local_tm.tm_isdst = -1;\n        ftime = mktime(&local_tm);\n\n        buf->st_ctime =\n        buf->st_atime =\n        buf->st_mtime = ftime;\n\n        buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR);\n\n        /* lastly, throw in the protection bits */\n        buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF);\n\n        FreeMem((char *)inf, (long)sizeof(*inf));\n        UnLock((BPTR)lock);\n\n        return(0);\n\n}\n\nint fstat(int handle, struct stat *buf)\n{\n    /* fake some reasonable values for stdin */\n    buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG);\n    buf->st_size = -1;\n    buf->st_mtime = time(&buf->st_mtime);\n    return 0;\n}\n\n\n/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */\n\nDIR *opendir(const char *path)\n{\n    DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC);\n    if (!dd) return NULL;\n    if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) {\n        disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED;\n        FreeMem(dd, sizeof(DIR));\n        return NULL;\n    } else\n        disk_not_mounted = 0;\n    if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) {\n        UnLock(dd->d_parentlock);\n        FreeMem(dd, sizeof(DIR));\n        return NULL;\n    }\n    dd->d_cleanuplink = dir_cleanup_list;       /* track them resources */\n    if (dir_cleanup_list)\n        dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink;\n    dd->d_cleanupparent = &dir_cleanup_list;\n    dir_cleanup_list = dd;\n    return dd;\n}\n\nvoid closedir(DIR *dd)\n{\n    if (dd) {\n        if (dd->d_cleanuplink)\n            dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent;\n        *(dd->d_cleanupparent) = dd->d_cleanuplink;\n        if (dd->d_parentlock)\n            UnLock(dd->d_parentlock);\n        FreeMem(dd, sizeof(DIR));\n    }\n}\n\nstruct dirent *readdir(DIR *dd)\n{\n    return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL);\n}\n\n\n#ifdef AZTEC_C\n\nint rmdir(const char *path)\n{\n    return (DeleteFile((char *)path) ? 0 : IoErr());\n}\n\nint chmod(const char *filename, int bits)       /* bits are as for st_mode */\n{\n    long protmask = (bits & 0xFF) ^ 0xF;\n    return !SetProtection((char *)filename, protmask);\n}\n\n\n/* This here removes unnecessary bulk from the executable with Aztec: */\nvoid _wb_parse(void)  { }\n\n/* fake a unix function that does not apply to amigados: */\nint umask(void)  { return 0; }\n\n\n#  include <signal.h>\n\n/* C library signal() messes up debugging yet adds no actual usefulness */\ntypedef void (*__signal_return_type)(int);\n__signal_return_type signal()  { return SIG_ERR; }\n\n\n/* The following replaces Aztec's argv-parsing function for compatibility with\nUnix-like syntax used on other platforms.  It also fixes the problem the\nstandard _cli_parse() has of accepting only lower-ascii characters. */\n\nint _argc, _arg_len;\nchar **_argv, *_arg_lin;\n\nvoid _cli_parse(struct Process *pp, long alen, register UBYTE *aptr)\n{\n    register UBYTE *cp;\n    register struct CommandLineInterface *cli;\n    register short c;\n    register short starred = 0;\n#  ifdef PRESTART_HOOK\n    void Prestart_Hook(void);\n#  endif\n\n    cli = (struct CommandLineInterface *) (pp->pr_CLI << 2);\n    cp = (UBYTE *) (cli->cli_CommandName << 2);\n    _arg_len = cp[0] + alen + 2;\n    if (!(_arg_lin = AllocMem((long) _arg_len, 0L)))\n        return;\n    c = cp[0];\n    strncpy(_arg_lin, cp + 1, c);\n    _arg_lin[c] = 0;\n    for (cp = _arg_lin + c + 1; alen && (*aptr < '\\n' || *aptr > '\\r'); alen--)\n        *cp++ = *aptr++;\n    *cp = 0;\n    aptr = cp = _arg_lin + c + 1;\n    for (_argc = 1; ; _argc++) {\n        while (*cp == ' ' || *cp == '\\t')\n            cp++;\n        if (!*cp)\n            break;\n        if (*cp == '\"') {\n            cp++;\n            while (c = *cp++) {\n                if (c == '\"' && !starred) {\n                    *aptr++ = 0;\n                    starred = 0;\n                    break;\n                } else if (c == '\\\\' && !starred)\n                    starred = 1;\n                else {\n                    *aptr++ = c;\n                    starred = 0;\n                }\n            }\n        } else {\n            while ((c = *cp++) && c != ' ' && c != '\\t')\n                *aptr++ = c;\n            *aptr++ = 0;\n        }\n        if (c == 0)\n            --cp;\n    }\n    *aptr = 0;\n    if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) {\n        _argc = 0;\n        return;\n    }\n    for (c = 0, cp = _arg_lin; c < _argc; c++) {\n        _argv[c] = cp;\n        cp += strlen(cp) + 1;\n    }\n    _argv[c] = NULL;\n#  ifdef PRESTART_HOOK\n    Prestart_Hook();\n#  endif\n}\n\n#endif /* AZTEC_C */\n\n#endif /* __amiga_stat_c */\n"
  },
  {
    "path": "deps/infozip/unzip60/amiga/z-stat.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __amiga_z_stat_h\n#define __amiga_z_stat_h\n\n/* Since older versions of the Lattice C compiler for Amiga, and all current */\n/* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */\n/* function or provide one inadequate for unzip (Aztec's has no st_mode      */\n/* field), we provide our own stat() function in stat.c by Paul Wells, and   */\n/* this fake stat.h file by Paul Kienitz.  Paul Wells originally used the    */\n/* Lattice stat.h but that does not work for Aztec and is not distributable  */\n/* with this package, so I made a separate one.  This has to be pulled into  */\n/* unzip.h when compiling an Amiga version, as \"amiga/z-stat.h\".             */\n\n/* We also provide here a \"struct dirent\" for use with opendir() & readdir() */\n/* functions included in amiga/stat.c.  If you use amiga/stat.c, this must   */\n/* be included wherever you use either readdir() or stat().                  */\n\n#ifdef AZTEC_C\n#  define __STAT_H\n#else  /* __SASC */\n/* do not include the following header, replacement definitions are here */\n#  define _STAT_H      /* do not include SAS/C <stat.h> */\n#  define _DIRENT_H    /* do not include SAS/C <dirent.h> */\n#  define _SYS_DIR_H   /* do not include SAS/C <sys/dir.h> */\n#  define _COMMIFMT_H  /* do not include SAS/C <sys/commifmt.h> */\n#  include <dos.h>\n#endif\n#include <libraries/dos.h>\n#include <time.h>\n\n\nstruct stat {\n    unsigned short st_mode;\n    time_t st_ctime, st_atime, st_mtime;\n    long st_size;\n    long st_ino;\n    long st_blocks;\n    short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev;\n};\n\n#define S_IFDIR  (1<<11)\n#define S_IFREG  (1<<10)\n\n#if 0\n   /* these values here are totally random: */\n#  define S_IFLNK  (1<<14)\n#  define S_IFSOCK (1<<13)\n#  define S_IFCHR  (1<<8)\n#  define S_IFIFO  (1<<7)\n#  define S_IFMT   (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK)\n#else\n#  define S_IFMT   (S_IFDIR|S_IFREG)\n#endif\n\n#define S_IHIDDEN    (1<<7)\n#define S_ISCRIPT    (1<<6)\n#define S_IPURE      (1<<5)\n#define S_IARCHIVE   (1<<4)\n#define S_IREAD      (1<<3)\n#define S_IWRITE     (1<<2)\n#define S_IEXECUTE   (1<<1)\n#define S_IDELETE    (1<<0)\n\nint stat(const char *name, struct stat *buf);\nint fstat(int handle, struct stat *buf);      /* returns dummy values */\n\ntypedef struct dirent {\n    struct dirent       *d_cleanuplink,\n                       **d_cleanupparent;\n    BPTR                 d_parentlock;\n    struct FileInfoBlock d_fib;\n} DIR;\n#define                  d_name  d_fib.fib_FileName\n\nextern unsigned short disk_not_mounted;         /* flag set by opendir() */\n\nDIR *opendir(const char *);\nvoid closedir(DIR *);\nvoid close_leftover_open_dirs(void);    /* call this if aborted in mid-run */\nstruct dirent *readdir(DIR *);\nint umask(void);\n\n#ifdef AZTEC_C\nint rmdir(const char *);\nint chmod(const char *filename, int bits);\n#endif\n\n#endif /* __amiga_z_stat_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/aosvs/Contents",
    "content": "Contents of the \"aosvs\" subdirectory for UnZip 5.3 and later:\n\n  Contents      this file\n  README        compilation notes, history, etc.\n  make_unz.cli  command script to make UnZip only (not UnZipSFX or fUnZip)\n  aosvs.c       AOS/VS-specific support routines\n  aosvs.h       AOS/VS-specific typedefs and header stuff\n"
  },
  {
    "path": "deps/infozip/unzip60/aosvs/README",
    "content": "[e-mail excerpt from Dave Lovelace explaining AOS/VS port, compiler, etc.]\n\n> From: Dave Lovelace <davel@cyberspace.org>\n> Subject: Re: zip on Data General AOS/VS\n> Date: Wed, 17 May 1995 11:02:03 -0400 (EDT)\n>\n> The diffs for zip & unzip are both in the same file.  I've also included the\n> extra source files which I wrote, the CLI macros which I used to compile\n> & link the things, & my own history of what I did.  Note that some of the\n> changes I made reversed earlier changes, & this was written for my own\n> use (or for others here if I leave or die or something).  I hope it will help.\n>\n> This was compiled using DG's C compiler for AOS/VS, rev 4.10.  It has been\n> compiled only on an MV-5500 running AOS/VS rev 7.70, but the resulting\n> programs have been distributed & run on several different MVs running various\n> versions of AOS/VS, so it should be fairly independent of at least minor rev\n> variations.  To the best of my knowledge it has *not* been tested under\n> AOS/VS II, & I really don't know anything about that environment; possibly\n> the special AOS/VS file info I'm storing in the extra field will have some\n> different format there.\n\n\n\n[README/history info from Dave Lovelace]\n\nIn modifying this for use on AOS/VS, I found only a few changes\nwere needed for DG C 4.10:\n\n2. There was a bug in the inflate() code, because memset()\n   was being called with a non-char pointer.  Pretty obviously\n   the other systems where this was used do not have char pointers\n   different from other pointers.  IT IS QUITE POSSIBLE THAT OTHER\n   BUGS OF THIS SORT EXIST.  Testing did not uncover any.\n3. In fileio.c, it appears that utime() is being called correctly,\n   but it does not set the file's time and always returns failure.\n   Since the AOS/VS tar and cpio programs provided by DG also suffer\n   from the fault of not setting file times, I must conclude that\n   this is by design.  At any rate, I modified the code (with\n   compilation conditional on a macro AOS_VS) to not say \"error\"\n   when this occurs.\n\nOne change which I think would be desirable: if the filename isn't\nalready a relative or absolute pathname (specifying a unique location),\nthe program follows the searchlist under AOS/VS.  It will unexpectedly\nreplace files anywhere in your searchlist.  (If you don't use the\n-o option, it will ask you first, but not tell you where the file\nto be replaced resides.)  I suspect this could be handled by prepending\n./ to any filenames which don't already begin with /.  (I haven't\nchecked how this would work inside the program.  Possibly this\ncould be done in every case - I don't think PKZIP ever stores an\nabsolute pathname.)\n\nTo see the compile options I used, look at the file MAKE.AOS_VS.CLI\nYou may of course need to change the searchlist to use that macro.\n\n ------------------------------------------------------------------\n15-dec-93\nI fixed some of the above things, introducing new problems.  It now\nwon't follow the searchlist - but the logic prevents it from creating\ndirectories (if they aren't explicitly in the ZIP, anyway).  But\nUNZIP now sets the creation time to the time stored in the ZIP, and\nZIP now stores that instead of the TLM.  I had to introduce an\nextra module, with some code of my own and some other public domain\ncode, to accomplish this.\n\n ------------------------------------------------------------------\n 1-jun-94\nI found an additional bug: the header was causing void to be #define'd\nas int, and prototypes weren't being used.  I changed UNZIP.H and\nadded a define of PROTO to the MAKE.AOS_VS.CLI and REMAKE.CLI macros.\n\nI found and fixed the bug that prevented the (creation) times from\nbeing set on files with explicit paths.  (The Unix-style paths didn't\nwork as inputs to the AOS/VS ?CREATE system call.)\n\nAdditional known bugs:\n\n1. I have not yet located the source of the bug that prevents the\n   date/time from being set (also ACLs etc.) when an existing file\n   is overwritten.  For some reason the call to delete & recreate\n   the file is not being reached.\n\n2. We need to do something in ZIP to store (as comments?) the file's\n   type and ACL, and then here in UNZIP extract these and apply\n   them.  This is not going to be trivial to make foolproof, but\n   it's badly needed.\n\n ------------------------------------------------------------------\n 2-jun-94\nI fixed #1 above.  The compiler was checking whether UNIX was defined,\nand it wasn't.  It appears that *some* of the places UNIX is used are\nthings we can't get along with, so I changed the code to check for\nAOS_VS as well.  It seems to work just fine.\n\nI also introduced a function zvs_credir() to create a directory\n(as opposed to a CPD, though it can create CPDs to with the proper\nfile-type parameter).  Directories in a path which are being created\nwill now be directories instead of CPDs.\n\nThe big change that's needed now is to have ZIP store (somehow)\nthe file's ACL and file type, and then to have UNZIP use this\ninformation to recreate the file as it was before ZIPping.  Ideally,\nZIP should also store links and CPD max-block info as well.  Planned\nstrategy: either in the name field but after the name, or in a comment,\nstore the packet returned by ?FSTAT (using sys_fstat()), and then\nuse this packet for the ?CREATE call in zvs_create().\n\n ------------------------------------------------------------------\n22-Jul-94\nThe changes to use the extra-field field for AOS/VS file info are in\nplace.  In general, if a ZIPfile was created with the current rev of\nZIP.PR, the files should be restored with file type, ACL, etc. OK.\nI didn't test to make sure element size & max index levels come\nthrough OK, but I think they should.\n\nUnix symbolic links are now UNZIPped OK, but ZIP.PR isn't yet able\nto ZIP links.  When it is, UNZIP should be ready.\n\nIn general UNZIP now ignores the searchlist fairly well, but not\nperfectly.  If the directory of a file you're UNZIPping can be\nreferenced elsewhere in the searchlist, UNZIP will find the file\nthere.  (For example, if the file UDD/BBASIC/ZZPGSUBSET.SR is in\nthe ZIPfile, and : is in your searchlist, then UDD and UDD:BBASIC\nwill be created under your current directory, but UNZIP will still\nfind :UDD:BBASIC:ZZPGSUBSET.SR instead of =UDD:BBASIC:ZZPGSUBSET.SR.\n\nFilenames (which are now stored in uppercase by ZIP.PR) must be\nmatched exactly if specified.  This applies to Unix path structure\nas well as case.\n\n ------------------------------------------------------------------\n 4-Aug-94\nI fixed a bug which caused (for links only) the Unix pathname to\nbe put through ux_to_vs_name twice.  The result was that a path\nsuch as    dir1/dir2/fname    went first to    :dir1:dir2:fname    and\nthen to    dir1?dir2?fname.\n\nI also added the /NOSEA switch to the cc/link lines in the macros\nMAKE.AOS_VS.CLI and REMAKE.CLI.  This should prevent any confusion\nover whether a file exists somewhere other than relative to the current\ndir.  This would disable calls to system() from using the searchlist,\nbut in this program I think they're all useless & hopefully inactive\nanyway.\n\n ------------------------------------------------------------------\n"
  },
  {
    "path": "deps/infozip/unzip60/aosvs/aosvs.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  aosvs.c\n\n  AOS/VS-specific routines for use with Info-ZIP's UnZip 5.2 and later.\n[GRR:  copied from unix.c -> undoubtedly has unnecessary stuff: delete at will]\n\n  Contains:  readdir()\n             do_wild()\n             open_outfile()\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             version()             <-- GRR:  needs work!  (Unix, not AOS/VS)\n             zvs_create()\n             zvs_credir()\n             ux_to_vs_name()\n             dgdate()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"aosvs/aosvs.h\"\n#include <packets/create.h>\n#include <sys_calls.h>\n#include <paru.h>\n\n#define symlink(resname,linkname) \\\n  zvs_create(linkname,-1L,-1L,-1L,ux_to_vs_name(vs_resname,resname),$FLNK,-1,-1)\n                                             *  file type */\n\n#ifdef DIRENT\n#  include <dirent.h>\n#else\n#  ifdef SYSV\n#    ifdef SYSNDIR\n#      include <sys/ndir.h>\n#    else\n#      include <ndir.h>\n#    endif\n#  else /* !SYSV */\n#    ifndef NO_SYSDIR\n#      include <sys/dir.h>\n#    endif\n#  endif /* ?SYSV */\n#  ifndef dirent\n#    define dirent direct\n#  endif\n#endif /* ?DIRENT */\n\nstatic int            created_dir;          /* used in mapname(), checkdir() */\nstatic int            renamed_fullpath;     /* ditto */\n\nstatic ZEXTRAFLD      zzextrafld;           /* buffer for extra field containing\n                                             *  ?FSTAT packet & ACL buffer */\nstatic char           vs_resname[2*$MXPL];\nstatic char           vs_path[2*$MXPL];     /* buf for AOS/VS pathname */\nstatic char           Vs_path[512];         /* should be big enough [GRR: ?] */\nstatic P_CTIM         zztimeblock;          /* time block for file creation */\nstatic ZVSCREATE_STRU zzcreatepacket;       /* packet for sys_create(), any\n\n\n/***************************/\n/* Strings used in aosvs.c */\n/***************************/\n\nstatic ZCONST char Far CannotDeleteOldFile[] =\n  \"error:  cannot delete old %s\\n\";\nstatic ZCONST char Far CannotCreateFile[] = \"error:  cannot create %s\\n\";\n\n\n#ifndef SFX\n#ifdef NO_DIR                  /* for AT&T 3B1 */\n\n#define opendir(path) fopen(path,\"r\")\n#define closedir(dir) fclose(dir)\ntypedef FILE DIR;\n\n/*\n *  Apparently originally by Rich Salz.\n *  Cleaned up and modified by James W. Birdsall.\n */\nstruct dirent *readdir(dirp)\n    DIR *dirp;\n{\n    static struct dirent entry;\n\n    if (dirp == NULL)\n        return NULL;\n\n    for (;;)\n        if (fread(&entry, sizeof (struct dirent), 1, dirp) == 0)\n            return (struct dirent *)NULL;\n        else if (entry.d_ino)\n            return &entry;\n\n} /* end function readdir() */\n\n#endif /* NO_DIR */\n\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 ==  case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n\n/***************************/\n/* Function open_outfile() */\n/***************************/\n\nint open_outfile(__G)           /* return 1 if fail */\n    __GDEF\n{\n    int errc = 1;    /* init to show no success with AOS/VS info */\n    long dmm, ddd, dyy, dhh, dmin, dss;\n\n\n#ifdef DLL\n    if (G.redirect_data)\n        return redirect_outfile(__G)==FALSE;\n#endif\n\n    if (stat(G.filename, &G.statbuf) == 0 && unlink(G.filename) < 0) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotDeleteOldFile),\n          FnFilter1(G.filename)));\n        return 1;\n    }\n\n/*---------------------------------------------------------------------------\n    If the file didn't already exist, we created it earlier.  But we just\n    deleted it, which we still had to do in case we are overwriting an exis-\n    ting file.  So we must create it now, again, to set the creation time\n    properly.  (The creation time is the best functional approximation of\n    the Unix mtime.  Really!)\n\n    If we stored this with an AOS/VS Zip that set the extra field to contain\n    the ?FSTAT packet and the ACL, we should use info from the ?FSTAT call\n    now.  Otherwise (or if that fails), we should create anyway as best we\n    can from the normal Zip info.\n\n    In theory, we should look through an entire series of extra fields that\n    might exist for the same file, but we're not going to bother.  If we set\n    up other types of extra fields, or if other environments we run into may\n    add their own stuff to existing entries in Zip files, we'll have to.\n\n    Note that all the packet types for sys_fstat() are the same size & mostly\n    have the same structure, with some fields being unused, etc.  Ditto for\n    sys_create().  Thus, we assume a normal one here, not a dir/cpd or device\n    or IPC file, & make little adjustments as necessary.  We will set ACLs\n    later (to reduce the chance of lacking access to what we create now); note\n    that for links the resolution name should be stored in the ACL field (once\n    we get Zip recognizing links OK).\n  ---------------------------------------------------------------------------*/\n\n    if (G.extra_field != NULL) {\n        memcpy((char *) &zzextrafld, G.extra_field, sizeof(zzextrafld));\n        if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id,\n                    sizeof(zzextrafld.extra_header_id))  &&\n            !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel),\n                    sizeof(zzextrafld.extra_sentinel))\n        {\n            zzcreatepacket.norm_create_packet.cftyp_format =\n              zzextrafld.fstat_packet.norm_fstat_packet.styp_format;\n            zzcreatepacket.norm_create_packet.cftyp_entry =\n              zzextrafld.fstat_packet.norm_fstat_packet.styp_type;\n\n            /* for DIRS/CPDs, the next one will give the hash frame size; for\n             * IPCs it will give the port number */\n            zzcreatepacket.norm_create_packet.ccps =\n              zzextrafld.fstat_packet.norm_fstat_packet.scps;\n\n            zzcreatepacket.norm_create_packet.ctim = &zztimeblock;\n            zztimeblock.tcth = zzextrafld.fstat_packet.norm_fstat_packet.stch;\n\n            /* access & modification times default to current */\n            zztimeblock.tath.long_time = zztimeblock.tmth.long_time = -1;\n\n            /* give it current process's ACL unless link; then give it\n             * resolution name */\n            zzcreatepacket.norm_create_packet.cacp = (char *)(-1);\n\n            if (zzcreatepacket.norm_create_packet.cftyp_entry == $FLNK)\n                zzcreatepacket.norm_create_packet.cacp = zzextrafld.aclbuf;\n\n            zzcreatepacket.dir_create_packet.cmsh =\n              zzextrafld.fstat_packet.dir_fstat_packet.scsh;\n            if (zzcreatepacket.norm_create_packet.cftyp_entry != $FCPD) {\n                /* element size for normal files */\n                zzcreatepacket.norm_create_packet.cdel =\n                  zzextrafld.fstat_packet.norm_fstat_packet.sdeh;\n            }\n            zzcreatepacket.norm_create_packet.cmil =\n              zzextrafld.fstat_packet.norm_fstat_packet.smil;\n\n            if ((errc = sys_create(ux_to_vs_name(vs_path, G.filename),\n                 &zzcreatepacket)) != 0)\n                Info(slide, 0x201, ((char *)slide,\n                  \"error creating %s with AOS/VS info -\\n\\\n                  will try again with ordinary Zip info\\n\",\n                  FnFilter1(G.filename)));\n        }\n    }\n\n    /* do it the hard way if no AOS/VS info was stored or if we had problems */\n    if (errc) {\n        /* skip restoring time stamps on user's request */\n        if (uO.D_flag <= 1) {\n            dyy = (G.lrec.last_mod_dos_datetime >> 25) + 1980;\n            dmm = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f;\n            ddd = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;\n            dhh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;\n            dmin = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;\n            dss = (G.lrec.last_mod_dos_datetime << 1) & 0x3e;\n        }\n\n        if (zvs_create(G.filename,\n            (uO.D_flag <= 1\n             ? (((ulg)dgdate(dmm, ddd, dyy)) << 16) |\n               (dhh*1800L + dmin*30L + dss/2L)\n             : -1L),\n            -1L, -1L, (char *) -1, -1, -1, -1))\n        {\n            Info(slide, 0x201, ((char *)slide, \"error: %s: cannot create\\n\",\n              FnFilter1(G.filename)));\n            return 1;\n        }\n    }\n\n    Trace((stderr, \"open_outfile:  doing fopen(%s) for writing\\n\",\n      FnFilter1(G.filename)));\n    if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename)));\n        return 1;\n    }\n    Trace((stderr, \"open_outfile:  fopen(%s) for writing succeeded\\n\",\n      FnFilter1(G.filename)));\n\n#ifdef USE_FWRITE\n#ifdef _IOFBF  /* make output fully buffered (works just about like write()) */\n    setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);\n#else\n    setbuf(G.outfile, (char *)slide);\n#endif\n#endif /* USE_FWRITE */\n    return 0;\n\n} /* end function open_outfile() */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                return 0;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap from the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                return 0;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in Unix */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n#ifdef MTS\n            case ' ':             /* change spaces to underscore under */\n                *pp++ = '_';      /*  MTS; leave as spaces under Unix */\n                break;\n#endif\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    /* On UNIX (and compatible systems), \".\" and \"..\" are reserved for\n     * directory navigation and cannot be used as regular file names.\n     * These reserved one-dot and two-dot names are mapped to \"_\" and \"__\".\n     */\n    if (strcmp(pathcomp, \".\") == 0)\n        *pathcomp = '_';\n    else if (strcmp(pathcomp, \"..\") == 0)\n        strcpy(pathcomp, \"__\");\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n#if 0  /*========== NOTES ==========*/\n\n  extract-to dir:      a:path/\n  buildpath:           path1/path2/ ...   (NULL-terminated)\n  pathcomp:                filename\n\n  mapname():\n    loop over chars in zipfile member name\n      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?\n        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)\n        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)\n        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)\n    finally add filename itself and check for existence? (could use with rename)\n        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)\n    checkdir(name, GETPATH)     -->  copy path to name and free space\n\n#endif /* 0 */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check: need to append '/', at least one-char name, '\\0' */\n        if ((end-buildpath) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n        /* for AOS/VS, try to create so as to not use searchlist: */\n        if ( /*SSTAT(buildpath, &G.statbuf)*/ 1) {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            /* create the directory */\n            if (zvs_credir(buildpath,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1) == -1)\n            {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath),\n                  strerror(errno),\n                  FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == '/') {\n                tmproot[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (zvs_credir(tmproot,-1L,-1L,-1L,(char *) -1,-1,0L,-1,-1)\n                    == -1)\n                {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\\\n           %s\\n\",\n                      FnFilter1(tmproot), strerror(errno)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[rootlen++] = '/';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate storage for a symlink control\n    structure, put the uncompressed \"data\" and other required info in it, and\n    add the structure to the \"deferred symlinks\" chain.  Since we know it's a\n    symbolic link to start with, we shouldn't have to worry about overflowing\n    unsigned ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SYMLINKS\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n        /* size of the symlink entry is the sum of\n         *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n         *  system specific attribute data size (might be 0),\n         *  and the lengths of name and link target.\n         */\n        extent slnk_entrysize = (sizeof(slinkentry) + 1) +\n                                ucsize + strlen(G.filename);\n        slinkentry *slnk_entry;\n\n        if (slnk_entrysize < ucsize) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n\n        if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: no mem\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n        slnk_entry->next = NULL;\n        slnk_entry->targetlen = ucsize;\n        slnk_entry->attriblen = 0;      /* don't set attributes for symlinks */\n        slnk_entry->target = slnk_entry->buf;\n        slnk_entry->fname = slnk_entry->target + ucsize + 1;\n        strcpy(slnk_entry->fname, G.filename);\n\n        /* move back to the start of the file to re-read the \"link data\" */\n        rewind(G.outfile);\n\n        if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed\\n\",\n              FnFilter1(G.filename)));\n            free(slnk_entry);\n            fclose(G.outfile);\n            return;\n        }\n        fclose(G.outfile);                  /* close \"link\" file for good... */\n        slnk_entry->target[ucsize] = '\\0';\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"-> %s \",\n              FnFilter1(slnk_entry->target)));\n        /* add this symlink record to the list of deferred symlinks */\n        if (G.slink_last != NULL)\n            G.slink_last->next = slnk_entry;\n        else\n            G.slink_head = slnk_entry;\n        G.slink_last = slnk_entry;\n        return;\n    }\n#endif /* SYMLINKS */\n\n    fclose(G.outfile);\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n/*---------------------------------------------------------------------------\n    AOS/VS only allows setting file times at creation but has its own permis-\n    sions scheme which is better invoked here if the necessary information\n    was in fact stored.  In theory, we should look through an entire series\n    of extra fields that might exist for the same file, but we're not going\n    to bother.  If we set up other types of extra fields, or if we run into\n    other environments that add their own stuff to existing entries in ZIP\n    files, we'll have to.  NOTE:  already copied extra-field stuff into\n    zzextrafld structure when file was created.\n  ---------------------------------------------------------------------------*/\n\n    if (G.extra_field != NULL) {\n        if (!memcmp(ZEXTRA_HEADID, zzextrafld.extra_header_id,\n                    sizeof(zzextrafld.extra_header_id))  &&\n            !memcmp(ZEXTRA_SENTINEL, zzextrafld.extra_sentinel,\n                    sizeof(zzextrafld.extra_sentinel))  &&\n            zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK)\n            /* (AOS/VS links don't have ACLs) */\n        {\n            /* vs_path was set (in this case) when we created the file */\n            if (sys_sacl(vs_path, zzextrafld.aclbuf)) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"error: cannot set ACL for %s\\n\", FnFilter1(G.filename)));\n                perror(\"sys_sacl()\");\n            }\n        }\n    }\n} /* end function close_outfile() */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n#if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE))\n    char cc_namebuf[40];\n    char cc_versbuf[40];\n#else\n#if (defined(CRAY) && defined(_RELEASE))\n    char cc_versbuf[40];\n#endif\n#endif\n#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))\n    char os_namebuf[40];\n#else\n#if defined(__NetBSD__)\n    char os_namebuf[40];\n#endif\n#endif\n\n    /* Pyramid, NeXT have problems with huge macro expansion, too:  no Info() */\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n#  ifdef NX_CURRENT_COMPILER_RELEASE\n      (sprintf(cc_namebuf, \"NeXT DevKit %d.%02d \",\n        NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100),\n       cc_namebuf),\n      (strlen(__VERSION__) > 8)? \"(gcc)\" :\n        (sprintf(cc_versbuf, \"(gcc %s)\", __VERSION__), cc_versbuf),\n#  else\n      \"gcc \", __VERSION__,\n#  endif\n#else\n#  if defined(CRAY) && defined(_RELEASE)\n      \"cc \", (sprintf(cc_versbuf, \"version %d\", _RELEASE), cc_versbuf),\n#  else\n#  ifdef __VERSION__\n#   ifndef IZ_CC_NAME\n#    define IZ_CC_NAME \"cc \"\n#   endif\n      IZ_CC_NAME, __VERSION__\n#  else\n#   ifndef IZ_CC_NAME\n#    define IZ_CC_NAME \"cc\"\n#   endif\n      IZ_CC_NAME, \"\",\n#  endif\n#  endif\n#endif /* ?__GNUC__ */\n\n#ifndef IZ_OS_NAME\n#  define IZ_OS_NAME \"Unix\"\n#endif\n      IZ_OS_NAME,\n\n#if defined(sgi) || defined(__sgi)\n      \" (Silicon Graphics IRIX)\",\n#else\n#ifdef sun\n#  ifdef sparc\n#    ifdef __SVR4\n      \" (Sun SPARC/Solaris)\",\n#    else /* may or may not be SunOS */\n      \" (Sun SPARC)\",\n#    endif\n#  else\n#  if defined(sun386) || defined(i386)\n      \" (Sun 386i)\",\n#  else\n#  if defined(mc68020) || defined(__mc68020__)\n      \" (Sun 3)\",\n#  else /* mc68010 or mc68000:  Sun 2 or earlier */\n      \" (Sun 2)\",\n#  endif\n#  endif\n#  endif\n#else\n#ifdef __hpux\n      \" (HP/UX)\",\n#else\n#ifdef __osf__\n      \" (DEC OSF/1)\",\n#else\n#ifdef _AIX\n      \" (IBM AIX)\",\n#else\n#ifdef aiws\n      \" (IBM RT/AIX)\",\n#else\n#if defined(CRAY) || defined(cray)\n#  ifdef _UNICOS\n      (sprintf(os_namebuf, \" (Cray UNICOS release %d)\", _UNICOS), os_namebuf),\n#  else\n      \" (Cray UNICOS)\",\n#  endif\n#else\n#if defined(uts) || defined(UTS)\n      \" (Amdahl UTS)\",\n#else\n#ifdef NeXT\n#  ifdef mc68000\n      \" (NeXTStep/black)\",\n#  else\n      \" (NeXTStep for Intel)\",\n#  endif\n#else              /* the next dozen or so are somewhat order-dependent */\n#ifdef LINUX\n#  ifdef __ELF__\n      \" (Linux ELF)\",\n#  else\n      \" (Linux a.out)\",\n#  endif\n#else\n#ifdef MINIX\n      \" (Minix)\",\n#else\n#ifdef M_UNIX\n      \" (SCO Unix)\",\n#else\n#ifdef M_XENIX\n      \" (SCO Xenix)\",\n#else\n#ifdef __NetBSD__\n#  ifdef NetBSD0_8\n      (sprintf(os_namebuf, \" (NetBSD 0.8%c)\", (char)(NetBSD0_8 - 1 + 'A')),\n       os_namebuf),\n#  else\n#  ifdef NetBSD0_9\n      (sprintf(os_namebuf, \" (NetBSD 0.9%c)\", (char)(NetBSD0_9 - 1 + 'A')),\n       os_namebuf),\n#  else\n#  ifdef NetBSD1_0\n      (sprintf(os_namebuf, \" (NetBSD 1.0%c)\", (char)(NetBSD1_0 - 1 + 'A')),\n       os_namebuf),\n#  else\n      (BSD4_4 == 0.5)? \" (NetBSD before 0.9)\" : \" (NetBSD 1.1 or later)\",\n#  endif\n#  endif\n#  endif\n#else\n#ifdef __FreeBSD__\n      (BSD4_4 == 0.5)? \" (FreeBSD 1.x)\" : \" (FreeBSD 2.0 or later)\",\n#else\n#ifdef __bsdi__\n      (BSD4_4 == 0.5)? \" (BSD/386 1.0)\" : \" (BSD/386 1.1 or later)\",\n#else\n#ifdef __386BSD__\n      (BSD4_4 == 1)? \" (386BSD, post-4.4 release)\" : \" (386BSD)\",\n#else\n#if defined(i486) || defined(__i486) || defined(__i486__)\n      \" (Intel 486)\",\n#else\n#if defined(i386) || defined(__i386) || defined(__i386__)\n      \" (Intel 386)\",\n#else\n#ifdef pyr\n      \" (Pyramid)\",\n#else\n#ifdef ultrix\n#  ifdef mips\n      \" (DEC/MIPS)\",\n#  else\n#  ifdef vax\n      \" (DEC/VAX)\",\n#  else /* __alpha? */\n      \" (DEC/Alpha)\",\n#  endif\n#  endif\n#else\n#ifdef gould\n      \" (Gould)\",\n#else\n#ifdef MTS\n      \" (MTS)\",\n#else\n#ifdef __convexc__\n      \" (Convex)\",\n#else\n      \"\",\n#endif /* Convex */\n#endif /* MTS */\n#endif /* Gould */\n#endif /* DEC */\n#endif /* Pyramid */\n#endif /* 386 */\n#endif /* 486 */\n#endif /* 386BSD */\n#endif /* BSDI BSD/386 */\n#endif /* NetBSD */\n#endif /* FreeBSD */\n#endif /* SCO Xenix */\n#endif /* SCO Unix */\n#endif /* Minix */\n#endif /* Linux */\n#endif /* NeXT */\n#endif /* Amdahl */\n#endif /* Cray */\n#endif /* RT/AIX */\n#endif /* AIX */\n#endif /* OSF/1 */\n#endif /* HP/UX */\n#endif /* Sun */\n#endif /* SGI */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n\n\n/* ===================================================================\n * ZVS_CREATE()\n * Function to create a file with specified times.  The times should be sent\n * as long ints in DG time format; use -1 to set to the current times.  You\n * may also specify a pointer to the ACL, the file type (see PARU.H, and do\n * not specify dirs or links), the element size, and the max index level.\n * For all of these parameters you may use -1 to specify the default.\n *\n * Returns 0 if no error, or the error code returned by ?CREATE.\n *\n *    HISTORY:\n *        15-dec-93 dbl\n *        31-may-94 dbl: added call to convert pathname to AOS/VS\n *\n *\n */\n\nint zvs_create(ZCONST char *fname, long cretim, long modtim, long acctim,\n               char *pacl, int ftyp, int eltsize, int maxindlev)\n{\n    P_CREATE    pcr_stru;\n    P_CTIM      pct_stru;\n\n    pcr_stru.cftyp_format = 0;           /* unspecified record format */\n    if (ftyp == -1)                      /* default file type to UNX */\n        pcr_stru.cftyp_entry = $FUNX;\n    else\n        pcr_stru.cftyp_entry = ftyp;\n    pcr_stru.ctim = &pct_stru;\n    pcr_stru.cacp = pacl;\n    pcr_stru.cdel = eltsize;\n    pcr_stru.cmil = maxindlev;\n\n    pct_stru.tcth.long_time = cretim;\n    pct_stru.tath.long_time = acctim;\n    pct_stru.tmth.long_time = modtim;\n\n    return (sys_create(ux_to_vs_name(Vs_path, fname), &pcr_stru));\n\n} /* end zvs_create() */\n\n\n\n/* ===================================================================\n * ZVS_CREDIR()\n * Function to create a dir as specified.  The times should be sent\n * as long ints in DG time format; use -1 to set to the current times.  You\n * may also specify a pointer to the ACL, the file type (either $FDIR or $FCPD; see PARU.H),\n * the max # blocks (if a CPD), the hash frame size, and the max index level.\n * For all of these parameters (except for the CPD's maximum blocks),\n * you may use -1 to specify the default.\n *\n * (The System Call Dictionary says both that you may specify a\n * maximum-index-level value up to the maximum, with 0 for a contiguous\n * directory, and that 3 is always used for this whatever you specify.)\n *\n * If you specify anything other than CPD for the file type, DIR will\n * be used.\n *\n * Returns 0 if no error, or the error code returned by ?CREATE.\n *\n *    HISTORY:\n *        1-jun-94 dbl\n *\n *\n */\n\nint zvs_credir(ZCONST char *dname, long cretim, long modtim, long acctim,\n               char *pacl, int ftyp, long maxblocks, int hashfsize,\n               int maxindlev)\n{\n    P_CREATE_DIR    pcr_stru;\n    P_CTIM          pct_stru;\n\n    if (ftyp != $FCPD)                      /* default file type to UNX */\n        pcr_stru.cftyp_entry = $FDIR;\n    else\n    {\n        pcr_stru.cftyp_entry = ftyp;\n        pcr_stru.cmsh = maxblocks;\n    }\n\n    pcr_stru.ctim = &pct_stru;\n    pcr_stru.cacp = pacl;\n    pcr_stru.chfs = hashfsize;\n    pcr_stru.cmil = maxindlev;\n\n    pct_stru.tcth.long_time = cretim;\n    pct_stru.tath.long_time = acctim;\n    pct_stru.tmth.long_time = modtim;\n\n    return (sys_create(ux_to_vs_name(Vs_path, dname), &pcr_stru));\n\n} /* end zvs_credir() */\n\n\n\n/* ===================================================================\n * UX_TO_VS_NAME() - makes a somewhat dumb pass at converting a Unix\n *           filename to an AOS/VS filename.  This should\n *           be just about adequate to handle the results\n *           of similarly-simple AOS/VS-to-Unix conversions\n *           in the ZIP program.  It does not guarantee a\n *           legal AOS/VS filename for every Unix filename;\n *           conspicuous examples would be names with\n *           embedded ./ and ../ (which will receive no\n *           special treatment).\n *\n *       RETURNS: pointer to the result (which is an input parameter)\n *\n *       NOTE: calling code is responsible for making sure\n *           the output buffer is big enough!\n *\n *       HISTORY:\n *           31-may-94 dbl\n *\n */\nchar *ux_to_vs_name(char *outname, ZCONST char *inname)\n{\n    ZCONST char *ip=inname, *op=outname;\n\n\n    if (ip[0] == '.') {\n        if (ip[1] == '/') {\n            *(op++) = '=';\n            ip += 2;\n        } else if (ip[1] == '.'  &&  ip[2] == '/') {\n            *(op++) = '^';\n            ip += 3;\n        }\n    }\n\n    do {\n        if (*ip == '/')\n            *(op++) = ':';\n        else if (strchr(\n           \"0123456789_$?.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\",\n           *ip) != NULL)\n        {\n            *(op++) = *ip;\n        } else\n            *(op++) = '?';\n\n    } while (*(ip++) != '\\0');\n\n    return outname;\n\n} /* end ux_to_vs_name() */\n\n\n\n/* =================================================================== */\n\n/* DGDATE\n   Two functions do encode/decode dates in DG system format.\n\n   Usage:\n    long value,year,month,day;\n\n    value=dgdate(month,day,year);\n    undgdate(value,&month,&day,&year);   [GRR:  not used in UnZip: removed]\n\n   Notes:\n\n   1. DG date functions only work on dates within the range\n      Jan 1, 1968 through Dec 31, 2099.  I have tested these\n      functions through the same range with exact agreement.\n      For dates outside of that range, the DG system calls\n      may return different values than these functions.\n\n   2. dgundate() accepts values between 0 and 48213 inclusive.\n      These correspond to 12/31/1967 and 12/31/2099.\n\n   3. Both functions assume the data is in the native OS byte\n      order.  So if you're reading or writing these fields from\n      a file that has been passed between AOS/VS and PC-DOS you\n      will need to swap byte order.\n\n   4. With reference to byte order, the entire range of values\n      supported by these functions will fit into an unsigned\n      short int.  In most cases the input or output will be\n      in that variable type.  You are better off casting the\n      value to/from unsigned short so you only need to concern\n      yourself with swapping two bytes instead of four.\n\n  Written by: Stanley J. Gula\n              US&T, Inc.\n              529 Main Street, Suite 1\n              Indian Orchard, MA 01151\n              (413)-543-3672\n              Copyright (c) 1990 US&T, Inc.\n              All rights reserved.\n\n              I hereby release these functions into the public\n              domain.  You may use these routines freely as long\n              as the US&T copyright remains intact in the source\n              code.\n\n              Stanley J. Gula     July 24, 1990\n*/\n\nlong motable[13]={0,31,59,90,120,151,181,212,243,273,304,334,365};\n\nlong yrtable[132]={\n      366,  731, 1096, 1461, 1827, 2192, 2557, 2922, 3288, 3653,\n     4018, 4383, 4749, 5114, 5479, 5844, 6210, 6575, 6940, 7305,\n     7671, 8036, 8401, 8766, 9132, 9497, 9862,10227,10593,10958,\n    11323,11688,12054,12419,12784,13149,13515,13880,14245,14610,\n    14976,15341,15706,16071,16437,16802,17167,17532,17898,18263,\n    18628,18993,19359,19724,20089,20454,20820,21185,21550,21915,\n    22281,22646,23011,23376,23742,24107,24472,24837,25203,25568,\n    25933,26298,26664,27029,27394,27759,28125,28490,28855,29220,\n    29586,29951,30316,30681,31047,31412,31777,32142,32508,32873,\n    33238,33603,33969,34334,34699,35064,35430,35795,36160,36525,\n    36891,37256,37621,37986,38352,38717,39082,39447,39813,40178,\n    40543,40908,41274,41639,42004,42369,42735,43100,43465,43830,\n    44196,44561,44926,45291,45657,46022,46387,46752,47118,47483,\n    47848,48213};\n\n/* Given y,m,d return # of days since 12/31/67 */\nlong int dgdate(short mm, short dd, short yy)\n{\n    long int temp;\n    short ytmp;\n\n    if (mm<1 || mm>12 || dd<1 || dd>31 || yy<1968 || yy>2099)\n        return 0L;\n\n    /* Figure in whole years since 1968 + whole months plus days */\n    temp=365L*(long)(yy-1968) + motable[mm-1] + (long)dd;\n\n    /* Adjust for leap years - note we don't account for skipped leap\n       year in years divisible by 1000 but not by 4000.  We're correct\n       through the year 2099 */\n    temp+=(yy-1965)/4;\n\n    /* Correct for this year */\n    /* In leap years, if date is 3/1 or later, bump */\n    if ((yy%4==0) && (mm>2))\n        temp++;\n\n    return temp;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/aosvs/aosvs.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  aosvs.h\n\n  AOS/VS-specific header file for use with Info-ZIP's UnZip 5.2 and later.\n\n  ---------------------------------------------------------------------------*/\n\n\n/* stuff to set up for system calls (?FSTAT & ?SACL) and the extra field */\n\n#include <paru.h>                   /* parameter definitions */\n#include <packets/filestatus.h>     /* AOS/VS ?FSTAT packet defs */\n#include <packets/create.h>         /* AOS/VS ?CREATE packet defs */\n#include <sys_calls.h>              /* AOS/VS system call interface */\n\n#define ZEXTRA_HEADID   \"VS\"\n#define ZEXTRA_SENTINEL \"FCI\"\n#define ZEXTRA_REV      ((uch)10)   /* change/use this in later revs */\n\n\n/* functions defined in zvs_create.c */\n\nextern int   zvs_create(ZCONST char *fname, long cretim, long modtim,\n                        long acctim, char *pacl, int ftyp, int eltsize,\n                        int maxindlev);\nextern int   zvs_credir(ZCONST char *dname, long cretim, long modtim,\n                        long acctim, char *pacl, int ftyp, long maxblocks,\n                        int hashfsize, int maxindlev);\nextern long  dgdate(short mm, short dd, short yy);\nextern char  *ux_to_vs_name(char *outname, ZCONST char *inname);\n\n\n/* could probably avoid the unions - all elements in each one are the same\n * size, and we're going to assume this */\n\ntypedef union zvsfstat_stru {\n    P_FSTAT       norm_fstat_packet;      /* normal fstat packet */\n    P_FSTAT_DIR   dir_fstat_packet;       /* DIR/CPD fstat packet */\n    P_FSTAT_UNIT  unit_fstat_packet;      /* unit (device) fstat packet */\n    P_FSTAT_IPC   ipc_fstat_packet;       /* IPC file fstat packet */\n} ZVSFSTAT_STRU;\n\ntypedef union zvscreate_stru {\n    P_CREATE      norm_create_packet;     /* normal create packet */\n    P_CREATE_DIR  dir_create_packet;      /* DIR/CPD create packet */\n    P_CREATE_IPC  ipc_create_packet;      /* IPC file create packet */\n} ZVSCREATE_STRU;\n\n\ntypedef struct zextrafld {\n    char            extra_header_id[2];   /* set to VS - in theory, an int */\n    char            extra_data_size[2];   /* size of rest (little-endian) */\n    char            extra_sentinel[4];    /* set to FCI w/ trailing null */\n    uch             extra_rev;            /* set to 10 for rev 1.0 */\n    ZVSFSTAT_STRU   fstat_packet;         /* the fstat packet */\n    char            aclbuf[$MXACL];       /* the raw ACL */\n} ZEXTRAFLD;\n"
  },
  {
    "path": "deps/infozip/unzip60/aosvs/make_unz.cli",
    "content": "push\nprompt pop\nsearchlist :c_4.10 :c_4.10:lang_rt [!searchlist]\ncc/link/NOUNX/NOSEA SYSV/DEFINE TERMIO/DEFINE AOS_VS/DEFINE=1 PROTO/DEFINE S_IFLNK/DEFINE=0120000 TIME.H/INCLUDE <unzip crc32 crypt envargs explode extract fileio globals inflate list match process ttyio ubz2err unreduce unshrink zipinfo aosvs>.c\npop\n"
  },
  {
    "path": "deps/infozip/unzip60/api.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  api.c\n\n  This module supplies an UnZip engine for use directly from C/C++\n  programs.  The functions are:\n\n    ZCONST UzpVer *UzpVersion(void);\n    unsigned UzpVersion2(UzpVer2 *version)\n    int UzpMain(int argc, char *argv[]);\n    int UzpAltMain(int argc, char *argv[], UzpInit *init);\n    int UzpValidate(char *archive, int AllCodes);\n    void UzpFreeMemBuffer(UzpBuffer *retstr);\n    int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,\n                         UzpCB *UsrFuncts, UzpBuffer *retstr);\n\n  non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):\n    int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,\n                UzpCB *UsrFuncts);\n\n  OS/2 only (for now):\n    int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],\n          char *cpExclude[]);\n\n  You must define `DLL' in order to include the API extensions.\n\n  ---------------------------------------------------------------------------*/\n\n\n#ifdef OS2\n#  define  INCL_DOSMEMMGR\n#  include <os2.h>\n#endif\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#endif\n#include \"unzvers.h\"\n#include <setjmp.h>\n\n#ifdef DLL      /* This source file supplies DLL-only interface code. */\n\n#ifndef POCKET_UNZIP    /* WinCE pUnZip defines this elsewhere. */\njmp_buf dll_error_return;\n#endif\n\n/*---------------------------------------------------------------------------\n    Documented API entry points\n  ---------------------------------------------------------------------------*/\n\n\nZCONST UzpVer * UZ_EXP UzpVersion()     /* returns pointer to const struct */\n{\n    static ZCONST UzpVer version = {    /* doesn't change between calls */\n        /* structure size */\n        UZPVER_LEN,\n        /* version flags */\n#ifdef BETA\n# ifdef ZLIB_VERSION\n        3,\n# else\n        1,\n# endif\n#else\n# ifdef ZLIB_VERSION\n        2,\n# else\n        0,\n# endif\n#endif\n        /* betalevel and date strings */\n        UZ_BETALEVEL, UZ_VERSION_DATE,\n        /* zlib_version string */\n#ifdef ZLIB_VERSION\n        ZLIB_VERSION,\n#else\n        NULL,\n#endif\n        /*== someday each of these may have a separate patchlevel: ==*/\n        /* unzip version */\n        {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},\n        /* zipinfo version */\n        {ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, 0},\n        /* os2dll version (retained for backward compatibility) */\n        {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},\n        /* windll version (retained for backward compatibility)*/\n        {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},\n#ifdef OS2DLL\n        /* os2dll API minimum compatible version*/\n        {UZ_OS2API_COMP_MAJOR, UZ_OS2API_COMP_MINOR, UZ_OS2API_COMP_REVIS, 0}\n#else /* !OS2DLL */\n#ifdef WINDLL\n        /* windll API minimum compatible version*/\n        {UZ_WINAPI_COMP_MAJOR, UZ_WINAPI_COMP_MINOR, UZ_WINAPI_COMP_REVIS, 0}\n#else /* !WINDLL */\n        /* generic DLL API minimum compatible version*/\n        {UZ_GENAPI_COMP_MAJOR, UZ_GENAPI_COMP_MINOR, UZ_GENAPI_COMP_REVIS, 0}\n#endif /* ?WINDLL */\n#endif /* ?OS2DLL */\n    };\n\n    return &version;\n}\n\nunsigned UZ_EXP UzpVersion2(UzpVer2 *version)\n{\n\n    if (version->structlen != sizeof(UzpVer2))\n        return sizeof(UzpVer2);\n\n#ifdef BETA\n    version->flag = 1;\n#else\n    version->flag = 0;\n#endif\n    strcpy(version->betalevel, UZ_BETALEVEL);\n    strcpy(version->date, UZ_VERSION_DATE);\n\n#ifdef ZLIB_VERSION\n    /* Although ZLIB_VERSION is a compile-time constant, we implement an\n       \"overrun-safe\" copy because its actual value is not under our control.\n     */\n    strncpy(version->zlib_version, ZLIB_VERSION,\n            sizeof(version->zlib_version) - 1);\n    version->zlib_version[sizeof(version->zlib_version) - 1] = '\\0';\n    version->flag |= 2;\n#else\n    version->zlib_version[0] = '\\0';\n#endif\n\n    /* someday each of these may have a separate patchlevel: */\n    version->unzip.major = UZ_MAJORVER;\n    version->unzip.minor = UZ_MINORVER;\n    version->unzip.patchlevel = UZ_PATCHLEVEL;\n\n    version->zipinfo.major = ZI_MAJORVER;\n    version->zipinfo.minor = ZI_MINORVER;\n    version->zipinfo.patchlevel = UZ_PATCHLEVEL;\n\n    /* these are retained for backward compatibility only: */\n    version->os2dll.major = UZ_MAJORVER;\n    version->os2dll.minor = UZ_MINORVER;\n    version->os2dll.patchlevel = UZ_PATCHLEVEL;\n\n    version->windll.major = UZ_MAJORVER;\n    version->windll.minor = UZ_MINORVER;\n    version->windll.patchlevel = UZ_PATCHLEVEL;\n\n#ifdef OS2DLL\n    /* os2dll API minimum compatible version*/\n    version->dllapimin.major = UZ_OS2API_COMP_MAJOR;\n    version->dllapimin.minor = UZ_OS2API_COMP_MINOR;\n    version->dllapimin.patchlevel = UZ_OS2API_COMP_REVIS;\n#else /* !OS2DLL */\n#ifdef WINDLL\n    /* windll API minimum compatible version*/\n    version->dllapimin.major = UZ_WINAPI_COMP_MAJOR;\n    version->dllapimin.minor = UZ_WINAPI_COMP_MINOR;\n    version->dllapimin.patchlevel = UZ_WINAPI_COMP_REVIS;\n#else /* !WINDLL */\n    /* generic DLL API minimum compatible version*/\n    version->dllapimin.major = UZ_GENAPI_COMP_MAJOR;\n    version->dllapimin.minor = UZ_GENAPI_COMP_MINOR;\n    version->dllapimin.patchlevel = UZ_GENAPI_COMP_REVIS;\n#endif /* ?WINDLL */\n#endif /* ?OS2DLL */\n    return 0;\n}\n\n\n\n\n\n#ifndef SFX\n#ifndef WINDLL\n\nint UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)\n{\n    int r, (*dummyfn)();\n\n\n    CONSTRUCTGLOBALS();\n\n    if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)\n        G.message = init->msgfn;\n\n    if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)\n        G.input = init->inputfn;\n\n    if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)\n        G.mpause = init->pausefn;\n\n    if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)\n        (*init->userfn)();    /* allow void* arg? */\n\n    r = unzip(__G__ argc, argv);\n    DESTROYGLOBALS();\n    RETURN(r);\n}\n\n#endif /* !WINDLL */\n\n\n\n\n#ifndef __16BIT__\n\nvoid UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)\n{\n    if (retstr != NULL && retstr->strptr != NULL) {\n        free(retstr->strptr);\n        retstr->strptr = NULL;\n        retstr->strlength = 0;\n    }\n}\n\n\n\n\n#ifndef WINDLL\n\nstatic int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));\n\nstatic int UzpDLL_Init(pG, UsrFuncts)\nzvoid *pG;\nUzpCB *UsrFuncts;\n{\n    int (*dummyfn)();\n\n    if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&\n        UsrFuncts->msgfn)\n        ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;\n    else\n        return FALSE;\n\n    if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&\n        UsrFuncts->inputfn)\n        ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;\n\n    if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&\n        UsrFuncts->pausefn)\n        ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;\n\n    if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&\n        UsrFuncts->passwdfn)\n        ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;\n\n    if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&\n        UsrFuncts->statrepfn)\n        ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;\n\n    return TRUE;\n}\n\n\nint UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,\n    UzpCB *UsrFuncts, UzpBuffer *retstr)\n{\n    int r;\n#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))\n    char *intern_zip, *intern_file;\n#endif\n\n    CONSTRUCTGLOBALS();\n#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))\n    intern_zip = (char *)malloc(strlen(zip)+1);\n    if (intern_zip == NULL) {\n       DESTROYGLOBALS();\n       return PK_MEM;\n    }\n    intern_file = (char *)malloc(strlen(file)+1);\n    if (intern_file == NULL) {\n       DESTROYGLOBALS();\n       free(intern_zip);\n       return PK_MEM;\n    }\n    ISO_TO_INTERN(zip, intern_zip);\n    ISO_TO_INTERN(file, intern_file);\n#   define zip intern_zip\n#   define file intern_file\n#endif\n    /* Copy those options that are meaningful for UzpUnzipToMemory, instead of\n     * a simple \"memcpy(G.UzO, optflgs, sizeof(UzpOpts));\"\n     */\n    uO.pwdarg = optflgs->pwdarg;\n    uO.aflag = optflgs->aflag;\n    uO.C_flag = optflgs->C_flag;\n    uO.qflag = optflgs->qflag;  /* currently,  overridden in unzipToMemory */\n\n    if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {\n       DESTROYGLOBALS();\n       return PK_BADERR;\n    }\n    G.redirect_data = 1;\n\n    r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);\n\n    DESTROYGLOBALS();\n#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))\n#  undef file\n#  undef zip\n    free(intern_file);\n    free(intern_zip);\n#endif\n    if (!r && retstr->strlength) {\n       free(retstr->strptr);\n       retstr->strptr = NULL;\n    }\n    return r;\n}\n#endif /* !WINDLL */\n#endif /* !__16BIT__ */\n\n\n\n\n\n#ifdef OS2DLL\n\nint UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],\n                char *cpExclude[])\n{\n    int r;\n\n    CONSTRUCTGLOBALS();\n    uO.qflag = 2;\n    uO.vflag = 1;\n    uO.C_flag = 1;\n    G.wildzipfn = name;\n    G.process_all_files = TRUE;\n    if (cpInclude) {\n        char **ptr = cpInclude;\n\n        while (*ptr != NULL) ptr++;\n        G.filespecs = ptr - cpInclude;\n        G.pfnames = cpInclude, G.process_all_files = FALSE;\n    }\n    if (cpExclude) {\n        char **ptr = cpExclude;\n\n        while (*ptr != NULL) ptr++;\n        G.xfilespecs = ptr - cpExclude;\n        G.pxnames = cpExclude, G.process_all_files = FALSE;\n    }\n\n    G.processExternally = callBack;\n    r = process_zipfiles(__G)==0;\n    DESTROYGLOBALS();\n    return r;\n}\n\n#endif /* OS2DLL */\n#endif /* !SFX */\n\n\n\n\n/*---------------------------------------------------------------------------\n    Helper functions\n  ---------------------------------------------------------------------------*/\n\n\nvoid setFileNotFound(__G)\n    __GDEF\n{\n    G.filenotfound++;\n}\n\n\n#ifndef SFX\n\nint unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)\n{\n    int r;\n    char *incname[2];\n\n    if ((zip == NULL) || (strlen(zip) > ((WSIZE>>2) - 160)))\n        return PK_PARAM;\n    if ((file == NULL) || (strlen(file) > ((WSIZE>>2) - 160)))\n        return PK_PARAM;\n\n    G.process_all_files = FALSE;\n    G.extract_flag = TRUE;\n    uO.qflag = 2;\n    G.wildzipfn = zip;\n\n    G.pfnames = incname;\n    incname[0] = file;\n    incname[1] = NULL;\n    G.filespecs = 1;\n\n    r = process_zipfiles(__G);\n    if (retstr) {\n        retstr->strptr = (char *)G.redirect_buffer;\n        retstr->strlength = G.redirect_size;\n    }\n    return r;                   /* returns `PK_???' error values */\n}\n\n#endif /* !SFX */\n\n/*\n    With the advent of 64 bit support, for now I am assuming that\n    if the size of the file is greater than an unsigned long, there\n    will simply not be enough memory to handle it, and am returning\n    FALSE.\n*/\nint redirect_outfile(__G)\n     __GDEF\n{\n#ifdef ZIP64_SUPPORT\n    __int64 check_conversion;\n#endif\n\n    if (G.redirect_size != 0 || G.redirect_buffer != NULL)\n        return FALSE;\n\n#ifndef NO_SLIDE_REDIR\n    G.redirect_slide = !G.pInfo->textmode;\n#endif\n#if (lenEOL != 1)\n    if (G.pInfo->textmode) {\n        G.redirect_size = (ulg)(G.lrec.ucsize * lenEOL);\n        if (G.redirect_size < G.lrec.ucsize)\n            G.redirect_size = (ulg)((G.lrec.ucsize > (ulg)-2L) ?\n                                    G.lrec.ucsize : -2L);\n#ifdef ZIP64_SUPPORT\n        check_conversion = G.lrec.ucsize * lenEOL;\n#endif\n    } else\n#endif\n    {\n        G.redirect_size = (ulg)G.lrec.ucsize;\n#ifdef ZIP64_SUPPORT\n        check_conversion = (__int64)G.lrec.ucsize;\n#endif\n    }\n\n#ifdef ZIP64_SUPPORT\n    if ((__int64)G.redirect_size != check_conversion)\n        return FALSE;\n#endif\n\n#ifdef __16BIT__\n    if ((ulg)((extent)G.redirect_size) != G.redirect_size)\n        return FALSE;\n#endif\n#ifdef OS2\n    DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,\n      PAG_READ|PAG_WRITE|PAG_COMMIT);\n    G.redirect_pointer = G.redirect_buffer;\n#else\n    G.redirect_pointer =\n      G.redirect_buffer = malloc((extent)(G.redirect_size+1));\n#endif\n    if (!G.redirect_buffer)\n        return FALSE;\n    G.redirect_pointer[G.redirect_size] = '\\0';\n    return TRUE;\n}\n\n\n\nint writeToMemory(__GPRO__ ZCONST uch *rawbuf, extent size)\n{\n    int errflg = FALSE;\n\n    if ((uch *)rawbuf != G.redirect_pointer) {\n        extent redir_avail = (G.redirect_buffer + G.redirect_size) -\n                             G.redirect_pointer;\n\n        /* Check for output buffer overflow */\n        if (size > redir_avail) {\n           /* limit transfer data to available space, set error return flag */\n           size = redir_avail;\n           errflg = TRUE;\n        }\n        memcpy(G.redirect_pointer, rawbuf, size);\n    }\n    G.redirect_pointer += size;\n    return errflg;\n}\n\n\n\n\nint close_redirect(__G)\n     __GDEF\n{\n    if (G.pInfo->textmode) {\n        *G.redirect_pointer = '\\0';\n        G.redirect_size = (ulg)(G.redirect_pointer - G.redirect_buffer);\n        if ((G.redirect_buffer =\n             realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {\n            G.redirect_size = 0;\n            return EOF;\n        }\n    }\n    return 0;\n}\n\n\n\n\n#ifndef SFX\n#ifndef __16BIT__\n#ifndef WINDLL\n\n/* Purpose: Determine if file in archive contains the string szSearch\n\n   Parameters: archive  = archive name\n               file     = file contained in the archive. This cannot be\n                          a wildcard to be meaningful\n               pattern  = string to search for\n               cmd      = 0 - case-insensitive search\n                          1 - case-sensitve search\n                          2 - case-insensitive, whole words only\n                          3 - case-sensitive, whole words only\n               SkipBin  = if true, skip any files that have control\n                          characters other than CR, LF, or tab in the first\n                          100 characters.\n\n   Returns:    TRUE if a match is found\n               FALSE if no match is found\n               -1 on error\n\n   Comments: This does not pretend to be as useful as the standard\n             Unix grep, which returns the strings associated with a\n             particular pattern, nor does it search past the first\n             matching occurrence of the pattern.\n */\n\nint UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,\n                   int SkipBin, UzpCB *UsrFuncts)\n{\n    int retcode = FALSE, compare;\n    ulg i, j, patternLen, buflen;\n    char * sz, *p;\n    UzpOpts flgopts;\n    UzpBuffer retstr;\n\n    memzero(&flgopts, sizeof(UzpOpts));         /* no special options */\n\n    if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {\n       return -1;   /* not enough memory, file not found, or other error */\n    }\n\n    if (SkipBin) {\n        if (retstr.strlength < 100)\n            buflen = retstr.strlength;\n        else\n            buflen = 100;\n        for (i = 0; i < buflen; i++) {\n            if (iscntrl(retstr.strptr[i])) {\n                if ((retstr.strptr[i] != 0x0A) &&\n                    (retstr.strptr[i] != 0x0D) &&\n                    (retstr.strptr[i] != 0x09))\n                {\n                    /* OK, we now think we have a binary file of some sort */\n                    free(retstr.strptr);\n                    return FALSE;\n                }\n            }\n        }\n    }\n\n    patternLen = strlen(pattern);\n\n    if (retstr.strlength < patternLen) {\n        free(retstr.strptr);\n        return FALSE;\n    }\n\n    sz = malloc(patternLen + 3); /* add two in case doing whole words only */\n    if (cmd > 1) {\n        strcpy(sz, \" \");\n        strcat(sz, pattern);\n        strcat(sz, \" \");\n    } else\n        strcpy(sz, pattern);\n\n    if ((cmd == 0) || (cmd == 2)) {\n        for (i = 0; i < strlen(sz); i++)\n            sz[i] = toupper(sz[i]);\n        for (i = 0; i < retstr.strlength; i++)\n            retstr.strptr[i] = toupper(retstr.strptr[i]);\n    }\n\n    for (i = 0; i < (retstr.strlength - patternLen); i++) {\n        p = &retstr.strptr[i];\n        compare = TRUE;\n        for (j = 0; j < patternLen; j++) {\n            /* We cannot do strncmp here, as we may be dealing with a\n             * \"binary\" file, such as a word processing file, or perhaps\n             * even a true executable of some sort. */\n            if (p[j] != sz[j]) {\n                compare = FALSE;\n                break;\n            }\n        }\n        if (compare == TRUE) {\n            retcode = TRUE;\n            break;\n        }\n    }\n\n    free(sz);\n    free(retstr.strptr);\n\n    return retcode;\n}\n#endif /* !WINDLL */\n#endif /* !__16BIT__ */\n\n\n\nint UZ_EXP UzpValidate(char *archive, int AllCodes)\n{\n    int retcode;\n    CONSTRUCTGLOBALS();\n\n    uO.jflag = 1;\n    uO.tflag = 1;\n    uO.overwrite_none = 0;\n    G.extract_flag = (!uO.zipinfo_mode &&\n                      !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag\n#ifdef TIMESTAMP\n                      && !uO.T_flag\n#endif\n                     );\n\n    uO.qflag = 2;                        /* turn off all messages */\n    G.fValidate = TRUE;\n    G.pfnames = (char **)&fnames[0];    /* assign default filename vector */\n\n    if (archive == NULL) {      /* something is screwed up:  no filename */\n        DESTROYGLOBALS();\n        retcode = PK_NOZIP;\n        goto exit_retcode;\n    }\n\n    if (strlen(archive) >= FILNAMSIZ) {\n       /* length of supplied archive name exceed the system's filename limit */\n       DESTROYGLOBALS();\n       retcode = PK_PARAM;\n       goto exit_retcode;\n    }\n\n    G.wildzipfn = (char *)malloc(FILNAMSIZ);\n    strcpy(G.wildzipfn, archive);\n#if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))\n    _ISO_INTERN(G.wildzipfn);\n#endif\n\n#ifdef WINDLL\n    Wiz_NoPrinting(TRUE);\n#endif\n\n    G.process_all_files = TRUE;         /* for speed */\n\n    if (setjmp(dll_error_return) != 0) {\n#ifdef WINDLL\n        Wiz_NoPrinting(FALSE);\n#endif\n        free(G.wildzipfn);\n        DESTROYGLOBALS();\n        retcode = PK_BADERR;\n        goto exit_retcode;\n    }\n\n    retcode = process_zipfiles(__G);\n\n    free(G.wildzipfn);\n#ifdef WINDLL\n    Wiz_NoPrinting(FALSE);\n#endif\n    DESTROYGLOBALS();\n\n    /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an\n       archive, we should still be able to see the files inside it,\n       even if we can't decode them for some reason.\n\n       We also still want to be able to get at files even if there is\n       something odd about the zip archive, hence allow PK_WARN,\n       PK_FIND, IZ_UNSUP as well as PK_ERR\n     */\n\nexit_retcode:\n    if (AllCodes)\n        return retcode;\n\n    if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||\n        (retcode == IZ_UNSUP) || (retcode == PK_FIND))\n        return TRUE;\n    else\n        return FALSE;\n}\n\n#endif /* !SFX */\n#endif /* DLL */\n"
  },
  {
    "path": "deps/infozip/unzip60/apihelp.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* apihelp.c */\n\n#ifdef API_DOC\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"unzvers.h\"\n\n\nAPIDocStruct APIDoc[] = {\n    {\n        \"UZPVERSION\"  , \"UzpVersion\"  ,\n        \"UzpVer *UzpVersion(void);\",\n        \"Get version numbers of the API and the underlying UnZip code.\\n\\n\"\n        \"\\t\\tThis is used for comparing the version numbers of the run-time\\n\"\n        \"\\t\\tDLL code with those expected from the unzip.h at compile time.\\n\"\n        \"\\t\\tIf the version numbers do not match, there may be compatibility\\n\"\n        \"\\t\\tproblems with further use of the DLL.\\n\\n\"\n        \"  Example:\\t/* Check the major version number of the DLL code. */\\n\"\n        \"\\t\\tUzpVer *pVersion;\\n\"\n        \"\\t\\tpVersion = UzpVersion();\\n\"\n        \"\\t\\tif (pVersion->unzip.major != UZ_MAJORVER)\\n\"\n        \"\\t\\t  fprintf(stderr, \\\"error: using wrong version of DLL\\\\n\\\");\\n\\n\"\n        \"\\t\\tSee unzip.h for details and unzipstb.c for an example.\\n\"\n    },\n\n    {\n        \"UZPMAIN\"  , \"UzpMain\"  ,\n        \"int UzpMain(int argc, char *argv[]);\",\n        \"Provide a direct entry point to the command line interface.\\n\\n\"\n        \"\\t\\tThis is used by the UnZip stub but you can use it in your\\n\"\n        \"\\t\\town program as well.  Output is sent to stdout.\\n\"\n        \"\\t\\t0 on return indicates success.\\n\\n\"\n        \"  Example:\\t/* Extract 'test.zip' silently, junking paths. */\\n\"\n        \"\\t\\tchar *argv[] = { \\\"-q\\\", \\\"-j\\\", \\\"test.zip\\\" };\\n\"\n        \"\\t\\tint argc = 3;\\n\"\n        \"\\t\\tif (UzpMain(argc,argv))\\n\"\n        \"\\t\\t  printf(\\\"error: unzip failed\\\\n\\\");\\n\\n\"\n        \"\\t\\tSee unzip.h for details.\\n\"\n    },\n\n    {\n        \"UZPALTMAIN\"  , \"UzpAltMain\"  ,\n        \"int UzpAltMain(int argc, char *argv[], UzpInit *init);\",\n        \"Provide a direct entry point to the command line interface,\\n\"\n        \"optionally installing replacement I/O handler functions.\\n\\n\"\n        \"\\t\\tAs with UzpMain(), output is sent to stdout by default.\\n\"\n        \"\\t\\t`InputFn *inputfn' is not yet implemented.  0 on return\\n\"\n        \"\\t\\tindicates success.\\n\\n\"\n        \"  Example:\\t/* Replace normal output and `more' functions. */\\n\"\n        \"\\t\\tchar *argv[] = { \\\"-q\\\", \\\"-j\\\", \\\"test.zip\\\" };\\n\"\n        \"\\t\\tint argc = 3;\\n\"\n        \"\\t\\tUzpInit init = { 16, MyMessageFn, NULL, MyPauseFn };\\n\"\n        \"\\t\\tif (UzpAltMain(argc,argv,&init))\\n\"\n        \"\\t\\t  printf(\\\"error: unzip failed\\\\n\\\");\\n\\n\"\n        \"\\t\\tSee unzip.h for details.\\n\"\n    },\n\n    {\n        \"UZPUNZIPTOMEMORY\", \"UzpUnzipToMemory\",\n        \"int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\",\n        \"Pass the name of the zip file and the name of the file\\n\"\n        \"\\t\\tyou wish to extract.  UzpUnzipToMemory will create a\\n\"\n        \"\\t\\tbuffer and return it in *retstr;  0 on return indicates\\n\"\n        \"\\t\\tfailure.\\n\\n\"\n        \"\\t\\tSee unzip.h for details.\\n\"\n    },\n\n    {\n        \"UZPFILETREE\", \"UzpFileTree\",\n        \"int UzpFileTree(char *name, cbList(callBack),\\n\"\n        \"\\t\\t\\tchar *cpInclude[], char *cpExclude[]);\",\n        \"Pass the name of the zip file, a callback function, an\\n\"\n        \"\\t\\tinclude and exclude file list. UzpFileTree calls the\\n\"\n        \"\\t\\tcallback for each valid file found in the zip file.\\n\"\n        \"\\t\\t0 on return indicates failure.\\n\\n\"\n        \"\\t\\tSee unzip.h for details.\\n\"\n    },\n\n    { 0 }\n};\n\n\nstatic int function_help OF((__GPRO__ APIDocStruct *doc, char *fname));\n\n\n\nstatic int function_help(__G__ doc, fname)\n    __GDEF\n    APIDocStruct *doc;\n    char *fname;\n{\n    strcpy(slide, fname);\n    /* strupr(slide);    non-standard */\n    while (doc->compare && STRNICMP(doc->compare,slide,strlen(fname)))\n        doc++;\n    if (!doc->compare)\n        return 0;\n    else\n        Info(slide, 0, ((char *)slide,\n          \"  Function:\\t%s\\n\\n  Syntax:\\t%s\\n\\n  Purpose:\\t%s\",\n          doc->function, doc->syntax, doc->purpose));\n\n    return 1;\n}\n\n\n\nvoid APIhelp(__G__ argc, argv)\n    __GDEF\n    int argc;\n    char **argv;\n{\n    if (argc > 1) {\n        struct APIDocStruct *doc;\n\n        if (function_help(__G__ APIDoc, argv[1]))\n            return;\n#ifdef SYSTEM_API_DETAILS\n        if (function_help(__G__ SYSTEM_API_DETAILS, argv[1]))\n            return;\n#endif\n        Info(slide, 0, ((char *)slide,\n          \"%s is not a documented command.\\n\\n\u0007\", argv[1]));\n    }\n\n    Info(slide, 0, ((char *)slide, \"\\\nThis API provides a number of external C and REXX functions for handling\\n\\\nzipfiles in OS/2.  Programmers are encouraged to expand this API.\\n\\\n\\n\\\nC functions: -- See unzip.h for details\\n\\\n  UzpVer *UzpVersion(void);\\n\\\n  int UzpMain(int argc, char *argv[]);\\n\\\n  int UzpAltMain(int argc, char *argv[], UzpInit *init);\\n\\\n  int UzpUnzipToMemory(char *zip, char *file, UzpBuffer *retstr);\\n\\\n  int UzpFileTree(char *name, cbList(callBack),\\n\\\n                  char *cpInclude[], char *cpExclude[]);\\n\\n\"));\n\n#ifdef SYSTEM_API_BRIEF\n    Info(slide, 0, ((char *)slide, SYSTEM_API_BRIEF));\n#endif\n\n    Info(slide, 0, ((char *)slide,\n      \"\\nFor more information, type 'unzip -A <function-name>'\\n\"));\n}\n\n#endif /* API_DOC */\n"
  },
  {
    "path": "deps/infozip/unzip60/atari/Contents",
    "content": "Contents of the \"atari\" sub-archive for UnZip 5.3 and later:\n\n  Contents      this file\n  README.old    old notes on compiling UnZip, from author of Atari port\n  Makefile.old  makefile for GNU C compiler and MiNT libraries\n  Makefile      newer, Unix-based makefile (lots of unnecessary baggage :-( )\n  make_unz.mup  script file for invoking makefile(s)?\n  atari.c       Atari-specific routines\n\nThe maintainers of the Atari port have fallen behind in their duties; the\ncode *probably* compiles, but it has not been tested recently.  Feel free\nto send zip-bugs e-mail about this sorry state of affairs.\n"
  },
  {
    "path": "deps/infozip/unzip60/atari/Makefile.old",
    "content": "#==============================================================================\n# Makefile for UnZip, UnZipSFX and fUnZip:  Atari ST             Chris Herborth\n# Version:  UnZip 5.20+, MiNT, GNU C                           25 December 2006\n#==============================================================================\n\n# Based on the original unix Makefile and modified by Chris Herborth\n# (cherborth@semprini.waterloo-rdp.on.ca), Nov.13/93.\n\n# Be sure to test your new UnZip (and UnZipSFX and fUnZip); successful com-\n# pilation does not always imply a working program.\n\n\n#####################\n# MACRO DEFINITIONS #\n#####################\n\n# Defaults most systems use (use LOCAL_UNZIP in environment to add flags,\n# such as -DDOSWILD).\n\n# UnZip flags\n# NOTE: 'cgcc' is my cross-compiler; you'll probably use 'gcc' instead.\nCC = cgcc\nLD = cgcc\nLOC = $(LOCAL_UNZIP) -ansi -D__MINT__ -U__STRICT_ANSI__\n\nCF = -mbaserel -mpcrel -O2 -fomit-frame-pointer -I. $(LOC)\n# CF = -O -I. $(LOC)\n# CF = -mbaserel -O -I. $(LOC)\nLF = -mbaserel -mpcrel -o unzip.ttp\nLF2 = -s -lbiio\n\n# UnZipSFX flags\nXC = -DSFX\nXL = -mbaserel -mpcrel -o unzipsfx.ttp\nXL2 = $(LF2)\n\n# fUnZip flags\nFC = -DFUNZIP\nFL = -mbaserel -mpcrel -o funzip.ttp\nFL2 = $(LF2)\n\n# general-purpose stuff\nCP = cp\nLN = ln -s\nRM = rm -f\nE = .ttp\nO = .o\nM = atari\nSHELL = /bin/sh\n\n# object files\nOBJS1 = unzip$O crc32$O crypt$O envargs$O explode$O\nOBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O\nOBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O\nOBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O\nLOBJS = $(OBJS)\nOBJX = unzipsfx$O crc32$O crypt_$O extract_$O fileio_$O \\\n\tglobals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O\nOBJF = funzip$O crc32$O cryptf$O globalsf$O inflatef$O ttyiof$O\n\nUNZIP_H = unzip.h unzpriv.h globals.h\n\n# installation\nINSTALL = cp#\tprobably can change this to 'install' if you have it\n# on some systems, manext=l and MANDIR=/usr/man/man$(manext) may be appropriate\nmanext = 1\nMANDIR = /usr/local/man/man$(manext)#\twhere to install man pages\nBINDIR = /usr/local/bin#\t\twhere to install executables\n#\nUNZIPS = unzip$E funzip$E unzipsfx$E zipinfo$E\nMANS = unzip.$(manext) unzipsfx.$(manext) zipinfo.$(manext) funzip.$(manext)\nDOCS = unzip.txt unzipsfx.txt zipinfo.txt funzip.txt\n# this is a little ugly...\nINSTALLED = $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E $(BINDIR)/funzip$E \\\n\t$(BINDIR)/unzipsfx$E $(MANDIR)/unzipsfx.$(manext) \\\n\t$(MANDIR)/unzip.$(manext) $(MANDIR)/zipinfo.$(manext) \\\n\t$(MANDIR)/funzip.$(manext)\n\n###############################################\n# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #\n###############################################\n\n.c$O:\n\t$(CC) -c $(CF) $*.c\n\n\nall:\t\tunzips\nunzips:\t\t$(UNZIPS)\ndocs:\t\t$(DOCS)\nunzipsman:\tunzips docs\nunzipsdocs:\tunzips docs\n\n\nclean:\n\trm -f $(OBJS) $(OBJF) $(OBJX) $(UNZIPS)\n\ninstall:\t$(UNZIPS) $(MANS)\n\t$(INSTALL) $(UNZIPS) $(BINDIR)\n\t$(LN) $(BINDIR)/unzip$E $(BINDIR)/zipinfo$E\n\t$(INSTALL) man/unzip.1 $(MANDIR)/unzip.$(manext)\n\t$(INSTALL) man/unzipsfx.1 $(MANDIR)/unzipsfx.$(manext)\n\t$(INSTALL) man/zipinfo.1 $(MANDIR)/zipinfo.$(manext)\n\t$(INSTALL) man/funzip.1 $(MANDIR)/funzip.$(manext)\n\n# alternatively, could use zip method:  -cd $(BINDIR); rm -f $(UNZIPS)  [etc.]\nuninstall:\n\trm -f $(INSTALLED)\n\n\nunzip$E:\t$(OBJS)\t\t\t# add `&' if parallel makes supported\n\t$(LD) $(LF) $(LOBJS) $(LF2)\n\nunzipsfx$E:\t$(OBJX)\t\t\t# add `&' if parallel makes supported\n\t$(LD) $(XL) $(OBJX) $(XL2)\n\nfunzip$E:\t$(OBJF)\t\t\t# add `&' if parallel makes supported\n\t$(LD) $(FL) $(OBJF) $(FL2)\n\nzipinfo$E:\tunzip$E\n\t@echo\\\n '  This is a Unix-inspired target.  If your filesystem does not support'\n\t@echo\\\n '  symbolic links, copy unzip.ttp to zipinfo.ttp rather than linking it,'\n\t@echo\\\n '  or else invoke as \"unzip -Z\".'\n\t$(LN) unzip$E zipinfo$E\n\n\ncrc32$O:\tcrc32.c $(UNZIP_H) zip.h crc32.h\ncrypt$O:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs$O:\tenvargs.c $(UNZIP_H)\nexplode$O:\texplode.c $(UNZIP_H)\nextract$O:\textract.c $(UNZIP_H) crc32.h crypt.h\nfileio$O:\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfunzip$O:\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\nglobals$O:\tglobals.c $(UNZIP_H)\ninflate$O:\tinflate.c inflate.h $(UNZIP_H)\nlist$O:\t\tlist.c $(UNZIP_H)\nmatch$O:\tmatch.c $(UNZIP_H)\nprocess$O:\tprocess.c $(UNZIP_H) crc32.h\nttyio$O:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$O:\tubz2err.c $(UNZIP_H)\nunreduce$O:\tunreduce.c $(UNZIP_H)\nunshrink$O:\tunshrink.c $(UNZIP_H)\nunzip$O:\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo$O:\tzipinfo.c $(UNZIP_H)\n\n# unzipsfx only\ncrypt_$O:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CP) crypt.c crypt_.c\n\t$(CC) -c $(CF) $(XC) crypt_.c\n\t$(RM) crypt_.c\n\nextract_$O:\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CP) extract.c extract_.c\n\t$(CC) -c $(CF) $(XC) extract_.c\n\t$(RM) extract_.c\n\nfileio_$O:\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CP) fileio.c fileio_.c\n\t$(CC) -c $(CF) $(XC) fileio_.c\n\t$(RM) fileio_.c\n\nglobals_$O:\tglobals.c $(UNZIP_H)\n\t$(CP) globals.c globals_.c\n\t$(CC) -c $(CF) $(XC) globals_.c\n\t$(RM) globals_.c\n\ninflate_$O:\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CP) inflate.c inflate_.c\n\t$(CC) -c $(CF) $(XC) inflate_.c\n\t$(RM) inflate_.c\n\nmatch_$O:\tmatch.c $(UNZIP_H)\n\t$(CP) match.c match_.c\n\t$(CC) -c $(CF) $(XC) match_.c\n\t$(RM) match_.c\n\nprocess_$O:\tprocess.c $(UNZIP_H) crc32.h\n\t$(CP) process.c process_.c\n\t$(CC) -c $(CF) $(XC) process_.c\n\t$(RM) process_.c\n\nttyio_$O:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CP) ttyio.c ttyio_.c\n\t$(CC) -c $(CF) $(XC) ttyio_.c\n\t$(RM) ttyio_.c\n\nubz2err_$O:\tubz2err.c $(UNZIP_H)\n\t$(CP) ubz2err.c ubz2err_.c\n\t$(CC) -c $(CF) $(XC) ubz2err_.c\n\t$(RM) ubz2err_.c\n\nunzipsfx$O:\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CP) unzip.c unzip_.c\n\t$(CC) -c $(CF) $(XC) unzip_.c\n\t$(RM) unzip_.c\n\n\n# funzip only\ncryptf$O:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CP) crypt.c cryptf.c\n\t$(CC) -c $(CF) $(FC) cryptf.c\n\t$(RM) cryptf.c\n\nglobalsf$O:\tglobals.c $(UNZIP_H)\n\t$(CP) globals.c globalsf.c\n\t$(CC) -c $(CF) $(FC) globalsf.c\n\t$(RM) globalsf.c\n\ninflatef$O:\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CP) inflate.c inflatef.c\n\t$(CC) -c $(CF) $(FC) inflatef.c\n\t$(RM) inflatef.c\n\nttyiof$O:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CP) ttyio.c ttyiof.c\n\t$(CC) -c $(CF) $(FC) ttyiof.c\n\t$(RM) ttyiof.c\n\n\n# system-specific code\natari$O:\tatari/atari.c $(UNZIP_H)\t\t# Atari only\n\t$(CC) -c $(CF) atari/atari.c\n\natari_$O:\tatari/atari.c $(UNZIP_H)\t\t# unzipsfx only\n\t$(CP) atari/atari.c atari_.c\n\t$(CC) -c $(CF) $(XC) atari_.c\n\t$(RM) atari_.c\n"
  },
  {
    "path": "deps/infozip/unzip60/atari/README.old",
    "content": "Here it is...  the UnZip 5.1 port for the Atari ST/TT/Falcon!\n\nThis took me longer than I expected thanks to a difference between the\nMiNT library and most UNIX libraries...  symlinks are 0x16000\ninstead of 0xa000...  I'm told this isn't even defined in POSIX, so I\ncan't really complain.  At least we've got a filesystem that can use\nsymlinks!\n\nThis port requires GNU C and allows you to build an unzip/zipinfo/funzip\nthat supports long filenames (on appropriate filesystems, thanks to the\nMiNT library), as well as symlinks.  It also does \"proper\" (ie, DOS-style)\ntranslation of text-file end-of-line characters.  The programs also build\nas shared-text binaries, so you can start unzipping several files at once\nin the background and only a small part of unzip will be duplicated in\nmemory.\n\nI build unzip with the MiNT library, GNU C 2.5.8 (2.5.7 and lower have a\nrather sever problem in the optimiser that affects 68000 code only; it\nadds 68020-only instructions to the 68000 code).  Oh, and I tested it\nextensively under MiNT's minix filesystem as well as the bogus DOS\nfilesystem that \"normal\" Atari partitions have.\n\nThe Makefile won't need any editing if you want to built unzip et al. on\na minix filesystem; if you want to install it on a DOS filesystem, use\n\"cp\" instead of \"ln\" for zipinfo.  [Or, to save disk space, make a script/\ncommand-file which invokes \"unzip -Z ...\". --CN]  This is such a good\nidea that I'm annoyed that Greg thought of it and I didn't...  ;-)  If\nyou're using a shell worth your while, you can alias zipinfo to\n'unzip -Z' and then forget all about this paragraph.\n\nIf you want to compile this using Turbo C (aka Pure C in North America)\nyou're on your own...  That's ok, I'll make a nice binary version of\nunzip available as soon as the official 5.1 version is released (give or\ntake a few days).\n\nEnjoy!  Cave Newt should be given kudos for keeping this monster easy to\nport...  ;-)  [Hah!  But thanks anyway. :-) --CN]\n\nPLEASE email me to tell me if you've uploaded the source or binary\nversions of Unzip 5.x to any BBS systems or commercial online systems so\nwe can update the WHERE file!\n\n-Chris Herborth-\n"
  },
  {
    "path": "deps/infozip/unzip60/atari/atari.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  atari.c\n\n  Atari-specific routines for use with Info-ZIP's UnZip 5.1 and later.\n\n  Contains:  readdir()\n             do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             mkdir()\n             close_outfile()\n             stamp_file()        [optional feature]\n             version()\n\n  Due to the amazing MiNT library being very, very close to BSD unix's\n  library, I'm using the unix.c as a base for this.  Note:  If you're not\n  going to compile this with the MiNT libraries (for GNU C, Turbo C, Pure C,\n  Lattice C, or Heat & Serve C), you're going to be in for some nasty work.\n  Most of the modifications in this file were made by Chris Herborth\n  (cherborth@semprini.waterloo-rdp.on.ca) and /should/ be marked with [cjh].\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include <dirent.h>            /* MiNTlibs has dirent [cjh] */\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting:  dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\", file->d_name));\n                if (file->d_name[0] == '.' && wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                    /* Need something here for TOS filesystem? [cjh] */\n                if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        /* May need special TOS handling here. [cjh] */\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\", file->d_name));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 = case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    int r;\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            r = FALSE;\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap of the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n            }\n            if (!r) {\n#ifdef SYMLINKS\n                /* Check if the file is a (POSIX-compatible) symbolic link.\n                 * We restrict symlink support to those \"made-by\" hosts that\n                 * are known to support symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   SYMLINK_HOST(G.pInfo->hostnum);\n#endif\n                return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) {\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n#ifdef SYMLINKS\n                /* Entries \"made by FS_FAT_\" could have been zipped on a\n                 * system that supports POSIX-style symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   (G.pInfo->hostnum == FS_FAT_);\n#endif\n                return 0;\n            }\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels on Atari */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n#ifdef MTS\n            case ' ':             /* change spaces to underscore under */\n                *pp++ = '_';      /*  MTS; leave as spaces under Unix */\n                break;\n#endif\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    /* On UNIX (and compatible systems), \".\" and \"..\" are reserved for\n     * directory navigation and cannot be used as regular file names.\n     * These reserved one-dot and two-dot names are mapped to \"_\" and \"__\".\n     */\n    if (strcmp(pathcomp, \".\") == 0)\n        *pathcomp = '_';\n    else if (strcmp(pathcomp, \"..\") == 0)\n        strcpy(pathcomp, \"__\");\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n#if 0  /*========== NOTES ==========*/\n\n  extract-to dir:      a:path/\n  buildpath:           path1/path2/ ...   (NULL-terminated)\n  pathcomp:                filename\n\n  mapname():\n    loop over chars in zipfile member name\n      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?\n        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)\n        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)\n        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)\n    finally add filename itself and check for existence? (could use with rename)\n        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)\n    checkdir(name, GETPATH)     -->  copy path to name and free space\n\n#endif /* 0 */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n/* SHORT_NAMES required for TOS, but it has to co-exist for minix fs... [cjh] */\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+\n                                        (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\", pathcomp));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == '/') {\n                tmproot[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (stat(tmproot, &G.statbuf) ||\n                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[rootlen++] = '/';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n#ifdef USE_EF_UT_TIME\n    unsigned eb_izux_flg;\n    iztimes zt;\n#endif\n    ztimbuf tp;\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate storage for a symlink control\n    structure, put the uncompressed \"data\" and other required info in it, and\n    add the structure to the \"deferred symlinks\" chain.  Since we know it's a\n    symbolic link to start with, we shouldn't have to worry about overflowing\n    unsigned ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n    /* symlinks allowed on minix filesystems [cjh]\n     * Hopefully this will work properly... We won't bother to try if\n     * MiNT isn't present; the symlink should fail if we're on a TOS\n     * filesystem.\n     * BUG: should we copy the original file to the \"symlink\" if the\n     *      link fails?\n     */\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n        /* size of the symlink entry is the sum of\n         *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n         *  system specific attribute data size (might be 0),\n         *  and the lengths of name and link target.\n         */\n        extent slnk_entrysize = (sizeof(slinkentry) + 1) +\n                                ucsize + strlen(G.filename);\n        slinkentry *slnk_entry;\n\n        if (slnk_entrysize < ucsize) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n\n        if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: no mem\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n        slnk_entry->next = NULL;\n        slnk_entry->targetlen = ucsize;\n        slnk_entry->attriblen = 0;      /* don't set attributes for symlinks */\n        slnk_entry->target = slnk_entry->buf;\n        slnk_entry->fname = slnk_entry->target + ucsize + 1;\n        strcpy(slnk_entry->fname, G.filename);\n\n        /* move back to the start of the file to re-read the \"link data\" */\n        rewind(G.outfile);\n\n        if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed\\n\",\n              FnFilter1(G.filename)));\n            free(slnk_entry);\n            fclose(G.outfile);\n            return;\n        }\n        fclose(G.outfile);                  /* close \"link\" file for good... */\n        slnk_entry->target[ucsize] = '\\0';\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"-> %s \",\n              FnFilter1(slnk_entry->target)));\n        /* add this symlink record to the list of deferred symlinks */\n        if (G.slink_last != NULL)\n            G.slink_last->next = slnk_entry;\n        else\n            G.slink_head = slnk_entry;\n        G.slink_last = slnk_entry;\n        return;\n    }\n\n    fclose(G.outfile);\n\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.\n  ---------------------------------------------------------------------------*/\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        eb_izux_flg = (G.extra_field\n#ifdef IZ_CHECK_TZ\n                       && G.tz_is_valid\n#endif\n                       ? ef_scan_for_izux(G.extra_field,\n                           G.lrec.extra_field_length, 0,\n                           G.lrec.last_mod_dos_datetime, &zt, NULL)\n                       : 0);\n        if (eb_izux_flg & EB_UT_FL_MTIME) {\n            tp.modtime = zt.mtime;\n            TTrace((stderr,\n              \"\\nclose_outfile:  Unix e.f. modif. time = %ld\\n\",\n              tp.modtime));\n        } else {\n            tp.modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n        }\n        if (eb_izux_flg & EB_UT_FL_ATIME) {\n            tp.actime = zt.atime;\n            TTrace((stderr,\n              \"close_outfile:  Unix e.f. access time = %ld\\n\",\n              tp.actime));\n        } else {\n            tp.actime = tp.modtime;\n            TTrace((stderr,\n              \"\\nclose_outfile:  modification/access times = %ld\\n\",\n              tp.modtime));\n        }\n#else /* !USE_EF_UT_TIME */\n        tp.actime = tp.modtime\n          = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n\n        TTrace((stderr, \"\\nclose_outfile:  modification/access times = %ld\\n\",\n          tp.modtime));\n#endif /* ?USE_EF_UT_TIME */\n\n        /* set the file's access and modification times */\n        if (utime(G.filename, &tp))\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  cannot set the time for %s\\n\",\n              FnFilter1(G.filename)));\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    ztimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n#ifdef __TURBOC__\n    char buf[40];\n#endif\n\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n#  ifdef __TURBOC__\n      \"Turbo C\", (sprintf(buf, \" (0x%04x = %d)\", __TURBOC__, __TURBOC__), buf),\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#  endif\n#endif\n\n#ifdef __MINT__\n      \"Atari TOS/MiNT\",\n#else\n      \"Atari TOS\",\n#endif\n\n      \" (Atari ST/TT/Falcon030)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/atari/make_unz.mup",
    "content": "#rm -f *.o *.ttp *.sym\n#make370 SHELL=/bin/mupfel.ttp CFLAGS=\" -O -DATARI\" unzips\nmake370 SHELL=/bin/mupfel.ttp CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.ttp unzip.ttp LF2=\nmake370 SHELL=/bin/mupfel.ttp CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.sym unzip.sym LF2=\"-B/bin/sym-\"\n#make370 SHELL=/bin/mupfel.ttp CFLAGS=\"-O -DATARI\" -n unzips > make_all.mup\n#fixstk 32K pgp.ttp\nprgflags 017 007 *.ttp\n\n"
  },
  {
    "path": "deps/infozip/unzip60/atheos/Contents",
    "content": "Contents of the \"atheos\" sub-directory for UnZip 5.52 and later:\n\n  Contents      this file\n  README        notes from the author of the AtheOS port\n  Makefile      makefile for building UnZip\n  athcfg.h      AtheOS-specific configuration settings\n  atheos.c      AtheOS-specific routines (similar to the BeOS/Unix ones)\n  atheos.h      structures for the AtheOS extra field\n\n- Ruslan Nickolaev (nruslan@hotbox.ru)\n"
  },
  {
    "path": "deps/infozip/unzip60/atheos/README",
    "content": "UnZip 5.51 for AtheOS/Syllable\n\nThis port is based on both BeOS and UNIX versions.\nAs BeOS version it can extract specific file attributes.\n\nTODO\n----\nThere is only one thing to be fixed:\n write_attr() should return count of bytes written. However that's a bug\n related with AFS only.\n\nPlease report any bugs to Zip-Bugs@lists.wku.edu.\nIf this bug related with AtheOS/Syllable only, you can mail me directly:\n nruslan@hotbox.ru.\n- Ruslan Nickolaev (nruslan@hotbox.ru)\n  Sep 06/2004\n"
  },
  {
    "path": "deps/infozip/unzip60/atheos/athcfg.h",
    "content": "/*\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    AtheOS/Syllable specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __athcfg_h\n#define __athcfg_h\n\n   /* ensure that Unix-specific code portions are excluded */\n#ifdef UNIX\n#  undef UNIX\n#endif\n#include <sys/types.h>          /* off_t, time_t, dev_t, ... */\n#include <sys/stat.h>\n#include <sys/param.h>\n#include <fcntl.h>              /* O_BINARY for open() w/o CR/LF translation */\n#include <limits.h>\n#include <time.h>\n#include <unistd.h>\n#include <utime.h>\n\n#define GOT_UTIMBUF\n#define DIRENT\n#if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP))\n#  define NO_STRNICMP\n#endif\n#define INT_SPRINTF\n#define SYMLINKS\n\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT DF_MDY    /* GRR:  customize with locale.h somehow? */\n#endif\n#define lenEOL          1\n#define PutNativeEOL    *q++ = native(LF);\n#define SCREENSIZE(ttrows, ttcols)  screensize(ttrows, ttcols)\n#define SCREENWIDTH     80\n#define SCREENLWRAP     1\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n#define SET_SYMLINK_ATTRIBS\n#define SET_DIR_ATTRIB\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n#define RESTORE_UIDGID\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    int created_dir, renamed_fullpath;\\\n    char *rootpath, *buildpath, *end;\\\n    ZCONST char *wildname;\\\n    char *dirname, matchname[FILNAMSIZ];\\\n    int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n    zvoid *wild_dir;\n\n/* created_dir, and renamed_fullpath are used by both mapname() and    */\n/*    checkdir().                                                      */\n/* rootlen, rootpath, buildpath and end are used by checkdir().        */\n/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */\n/*    and notfirstcall are used by do_wild().                          */\n\n#endif /* !__athcfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/atheos/atheos.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  atheos.c by Ruslan Nickolaev (nruslan@hotbox.ru)\n\n  AtheOS-specific routines for use with Info-ZIP's UnZip 5.51 and later.\n  (based on beos/beos.c and unix/unix.c)\n\n  Contains:  do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             stamp_file()\n             version()\n             scanAtheOSexfield()\n             set_file_attrs()\n             setAtheOSexfield()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include \"atheos.h\"\n#include <errno.h>             /* Just make sure we've got a few things... */\n#include <sys/types.h>\n#include <fcntl.h>\n#include <dirent.h>\n#include <atheos/fs_attribs.h>\n\nstatic unsigned filtattr OF((__GPRO__ unsigned perms));\nstatic uch *scanAtheOSexfield  OF((const uch *ef_ptr, unsigned ef_len));\nstatic int  set_file_attrs( const char *, const unsigned char *, const off_t );\nstatic void setAtheOSexfield   OF((const char *path, uch *extra_field));\n\n#ifdef SET_DIR_ATTRIB\ntypedef struct uxdirattr {      /* struct for holding unix style directory */\n    struct uxdirattr *next;     /*  info until can be sorted and set at end */\n    char *fn;                   /* filename of directory */\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } u;\n    unsigned perms;             /* same as min_info.file_attr */\n    int have_uidgid;            /* flag */\n    ulg uidgid[2];\n    char fnbuf[1];              /* buffer stub for directory name */\n} uxdirattr;\n#define UxAtt(d)  ((uxdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\n/* static int created_dir;      */      /* used in mapname(), checkdir() */\n/* static int renamed_fullpath; */      /* ditto */\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in athcfg.h:\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n*/\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.notfirstcall) {  /* first call:  must initialize everything */\n        G.notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(G.matchname, wildspec, FILNAMSIZ);\n            G.matchname[FILNAMSIZ-1] = '\\0';\n            G.have_dirname = FALSE;\n            G.wild_dir = NULL;\n            return G.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) {\n            G.dirname = \".\";\n            G.dirnamelen = 1;\n            G.have_dirname = FALSE;\n            G.wildname = wildspec;\n        } else {\n            ++G.wildname;     /* point at character after '/' */\n            G.dirnamelen = G.wildname - wildspec;\n            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(G.matchname, wildspec, FILNAMSIZ);\n                G.matchname[FILNAMSIZ-1] = '\\0';\n                return G.matchname; /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.dirname, wildspec, G.dirnamelen);\n            G.dirname[G.dirnamelen] = '\\0';   /* terminate for strcpy below */\n            G.have_dirname = TRUE;\n        }\n\n        if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) {\n            while ((file = readdir((DIR *)G.wild_dir)) !=\n                   (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && G.wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (G.have_dirname) {\n                        strcpy(G.matchname, G.dirname);\n                        strcpy(G.matchname+G.dirnamelen, file->d_name);\n                    } else\n                        strcpy(G.matchname, file->d_name);\n                    return G.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir((DIR *)G.wild_dir);\n            G.wild_dir = (zvoid *)NULL;\n        }\n        Trace((stderr, \"do_wild:  opendir(%s) returns NULL\\n\",\n          FnFilter1(G.dirname)));\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.matchname, wildspec, FILNAMSIZ);\n        G.matchname[FILNAMSIZ-1] = '\\0';\n        return G.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if ((DIR *)G.wild_dir == (DIR *)NULL) {\n        G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */\n        if (G.have_dirname)\n            free(G.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && G.wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (G.have_dirname) {\n                /* strcpy(G.matchname, G.dirname); */\n                strcpy(G.matchname+G.dirnamelen, file->d_name);\n            } else\n                strcpy(G.matchname, file->d_name);\n            return G.matchname;\n        }\n    }\n\n    closedir((DIR *)G.wild_dir);  /* at least one entry read; nothing left */\n    G.wild_dir = (zvoid *)NULL;\n    G.notfirstcall = FALSE;       /* reset for new wildspec */\n    if (G.have_dirname)\n        free(G.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n#ifndef S_ISUID\n# define S_ISUID        0004000 /* set user id on execution */\n#endif\n#ifndef S_ISGID\n# define S_ISGID        0002000 /* set group id on execution */\n#endif\n#ifndef S_ISVTX\n# define S_ISVTX        0001000 /* save swapped text even after use */\n#endif\n\n/************************/\n/*  Function filtattr() */\n/************************/\n/* This is used to clear or keep the SUID and GID bits on file permissions.\n * It's possible that a file in an archive could have one of these bits set\n * and, unknown to the person unzipping, could allow others to execute the\n * file as the user or group.  The new option -K bypasses this check.\n */\n\nstatic unsigned filtattr(__G__ perms)\n    __GDEF\n    unsigned perms;\n{\n    /* keep setuid/setgid/tacky perms? */\n    if (!uO.K_flag)\n        perms &= ~(S_ISUID | S_ISGID | S_ISVTX);\n\n    return (0xffff & perms);\n} /* end function filtattr() */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    int r;\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case ATHEOS_:\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            r = FALSE;\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap of the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n            }\n            if (!r) {\n#ifdef SYMLINKS\n                /* Check if the file is a (POSIX-compatible) symbolic link.\n                 * We restrict symlink support to those \"made-by\" hosts that\n                 * are known to support symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   SYMLINK_HOST(G.pInfo->hostnum);\n#endif\n                return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) {\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n#ifdef SYMLINKS\n                /* Entries \"made by FS_FAT_\" could have been zipped on a\n                 * system that supports POSIX-style symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   (G.pInfo->hostnum == FS_FAT_);\n#endif\n                return 0;\n            }\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in AtheOS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.created_dir = FALSE;      /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    G.renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n\n            if (!uO.J_flag) {   /* Handle the AtheOS extra field if present. */\n                void *ptr = scanAtheOSexfield(G.extra_field,\n                                              G.lrec.extra_field_length);\n                if (ptr) {\n                    setAtheOSexfield( G.filename, ptr );\n                }\n            }\n\n#ifndef NO_CHMOD\n            /* set approx. dir perms (make sure can still read/write in dir) */\n            if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr) | 0700))\n                perror(\"chmod (directory attributes) error\");\n#endif\n\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        if (!uO.J_flag) {   /* Handle the AtheOS extra field if present. */\n            void *ptr = scanAtheOSexfield(G.extra_field,\n                                          G.lrec.extra_field_length);\n            if (ptr) {\n                setAtheOSexfield(G.filename, ptr);\n            }\n        }\n\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    /* On UNIX (and compatible systems), \".\" and \"..\" are reserved for\n     * directory navigation and cannot be used as regular file names.\n     * These reserved one-dot and two-dot names are mapped to \"_\" and \"__\".\n     */\n    if (strcmp(pathcomp, \".\") == 0)\n        *pathcomp = '_';\n    else if (strcmp(pathcomp, \"..\") == 0)\n        strcpy(pathcomp, \"__\");\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n /* static int rootlen = 0; */  /* length of rootpath */\n /* static char *rootpath;  */  /* user's \"extract-to\" directory */\n /* static char *buildpath; */  /* full path (so far) to extracted file */\n /* static char *end;       */  /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0')\n            ++G.end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((G.end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check: need to append '/', at least one-char name, '\\0' */\n        if ((G.end-G.buildpath) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n        if (SSTAT(G.buildpath, &G.statbuf)) {   /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpath)));\n                free(G.buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(G.buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpath), FnFilter1(G.filename)));\n                free(G.buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(G.buildpath), FnFilter1(G.filename)));\n            free(G.buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(G.buildpath)));\n            free(G.buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.end++ = '/';\n        *G.end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    G.buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, G.buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(G.buildpath);\n        G.buildpath = G.end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0') {\n            ++G.end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((G.end-old_end) > FILENAME_MAX)    /* GRR:  proper constant? */\n                *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((G.end-G.buildpath) >= FILNAMSIZ) {\n                *--G.end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(G.buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+\n                                          (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((G.rootlen > 0) && !G.renamed_fullpath) {\n            strcpy(G.buildpath, G.rootpath);\n            G.end = G.buildpath + G.rootlen;\n        } else {\n            *G.buildpath = '\\0';\n            G.end = G.buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            G.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) {\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[G.rootlen-1] == '/') {\n                tmproot[--G.rootlen] = '\\0';\n            }\n            if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                  !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[G.rootlen++] = '/';\n            tmproot[G.rootlen] = '\\0';\n            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n                free(tmproot);\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            free(G.rootpath);\n            G.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\nstatic int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2]));\n\nstatic int get_extattribs(__G__ pzt, z_uidgid)\n    __GDEF\n    iztimes *pzt;\n    ulg z_uidgid[2];\n{\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.  On the other hand, we\n    then have to check for restoration of UID/GID.\n  ---------------------------------------------------------------------------*/\n    int have_uidgid_flg;\n    unsigned eb_izux_flg;\n\n    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                   (G.tz_is_valid ? pzt : NULL),\n#else\n                   pzt,\n#endif\n                   z_uidgid) : 0);\n    if (eb_izux_flg & EB_UT_FL_MTIME) {\n        TTrace((stderr, \"\\nget_extattribs:  Unix e.f. modif. time = %ld\\n\",\n          pzt->mtime));\n    } else {\n        pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n    if (eb_izux_flg & EB_UT_FL_ATIME) {\n        TTrace((stderr, \"get_extattribs:  Unix e.f. access time = %ld\\n\",\n          pzt->atime));\n    } else {\n        pzt->atime = pzt->mtime;\n        TTrace((stderr, \"\\nget_extattribs:  modification/access times = %ld\\n\",\n          pzt->mtime));\n    }\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    have_uidgid_flg =\n#ifdef RESTORE_UIDGID\n            (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));\n#else\n            0;\n#endif\n    return have_uidgid_flg;\n}\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        struct utimbuf t2;      /* modtime, actime */\n    } zt;\n    ulg z_uidgid[2];\n    int have_uidgid_flg;\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate storage for a symlink control\n    structure, put the uncompressed \"data\" and other required info in it, and\n    add the structure to the \"deferred symlinks\" chain.  Since we know it's a\n    symbolic link to start with, we shouldn't have to worry about overflowing\n    unsigned ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SYMLINKS\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n        unsigned AtheOSef_len = 0;\n        extent slnk_entrysize;\n        uch *AtheOS_exfld = NULL;\n        slinkentry *slnk_entry;\n\n        if (!uO.J_flag) {\n            /* attributes for symlinks are supported too */\n            AtheOS_exfld = scanAtheOSexfield(G.extra_field,\n                                             G.lrec.extra_field_length);\n            if (AtheOS_exfld) {\n                AtheOSef_len = makeword(EB_LEN + AtheOS_exfld) + EB_HEADSIZE;\n            }\n        }\n\n        /* size of the symlink entry is the sum of\n         *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n         *  system specific attribute data size (might be 0),\n         *  and the lengths of name and link target.\n         */\n        slnk_entrysize = (sizeof(slinkentry) + 1) + AtheOSef_len +\n                         ucsize + strlen(G.filename);\n\n        if (slnk_entrysize < ucsize) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n\n        if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: no mem\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n        slnk_entry->next = NULL;\n        slnk_entry->targetlen = ucsize;\n        slnk_entry->attriblen = AtheOSef_len;\n        slnk_entry->target = slnk_entry->buf + AtheOSef_len;\n        slnk_entry->fname = slnk_entry->target + ucsize + 1;\n        strcpy(slnk_entry->fname, G.filename);\n        if (AtheOSef_len > 0)\n            /* AtheOS_exfld should not be NULL because AtheOSef_len > 0 */\n            memcpy(slnk_entry->buf, AtheOS_exfld, AtheOSef_len);\n\n        /* move back to the start of the file to re-read the \"link data\" */\n        rewind(G.outfile);\n\n        if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed\\n\",\n              FnFilter1(G.filename)));\n            free(slnk_entry);\n            fclose(G.outfile);\n            return;\n        }\n        fclose(G.outfile);                  /* close \"link\" file for good... */\n        slnk_entry->target[ucsize] = '\\0';\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"-> %s \",\n              FnFilter1(slnk_entry->target)));\n        /* add this symlink record to the list of deferred symlinks */\n        if (G.slink_last != NULL)\n            G.slink_last->next = slnk_entry;\n        else\n            G.slink_head = slnk_entry;\n        G.slink_last = slnk_entry;\n        return;\n    }\n#endif /* SYMLINKS */\n\n    fclose(G.outfile);\n\n    /* handle the AtheOS extra field if present */\n    if (!uO.J_flag) {\n        void *ptr = scanAtheOSexfield(G.extra_field,\n                                      G.lrec.extra_field_length);\n\n        if (ptr) {\n            setAtheOSexfield(G.filename, ptr);\n        }\n    }\n\n    have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    if (have_uidgid_flg) {\n        TTrace((stderr, \"close_outfile:  restoring Unix UID/GID info\\n\"));\n        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))\n        {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot set UID %lu and/or GID %lu for %s\\n\",\n                  z_uidgid[0], z_uidgid[1], FnFilter1(G.filename)));\n            else\n                Info(slide, 0x201, ((char *)slide,\n                  \" (warning) cannot set UID %lu and/or GID %lu\",\n                  z_uidgid[0], z_uidgid[1]));\n        }\n    }\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        /* set the file's access and modification times */\n        if (utime(G.filename, &(zt.t2))) {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot set times for %s\\n\",\n                  FnFilter1(G.filename)));\n            else\n                Info(slide, 0x201, ((char *)slide,\n                  \" (warning) cannot set times\"));\n        }\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr)))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef SYMLINKS\nint set_symlnk_attribs(__G__ slnk_entry)\n    __GDEF\n    slinkentry *slnk_entry;\n{\n    if (slnk_entry->attriblen > 0)\n        setAtheOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);\n    /* currently, no error propagation... */\n    return PK_OK;\n}\n#endif /* SYMLINKS */\n\n\n\n\n#ifdef SET_DIR_ATTRIB\n/* messages of code for setting directory attributes */\nstatic ZCONST char Far DirlistUidGidFailed[] =\n  \"warning:  cannot set UID %lu and/or GID %lu for %s\\n\";\nstatic ZCONST char Far DirlistUtimeFailed[] =\n  \"warning:  cannot set modification, access times for %s\\n\";\n#  ifndef NO_CHMOD\n  static ZCONST char Far DirlistChmodFailed[] =\n    \"warning:  cannot set permissions for %s\\n\";\n#  endif\n\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    uxdirattr *d_entry;\n\n    d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename));\n    *pd = (direntry *)d_entry;\n    if (d_entry == (uxdirattr *)NULL) {\n        return PK_MEM;\n    }\n    d_entry->fn = d_entry->fnbuf;\n    strcpy(d_entry->fn, G.filename);\n\n    d_entry->perms = G.pInfo->file_attr;\n\n    d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3),\n                                          d_entry->uidgid);\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    int errval = PK_OK;\n\n    if (UxAtt(d)->have_uidgid &&\n        chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0],\n              (gid_t)UxAtt(d)->uidgid[1]))\n    {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(DirlistUidGidFailed),\n          UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n    /* Skip restoring directory time stamps on user' request. */\n    if (uO.D_flag <= 0) {\n        /* restore directory timestamps */\n        if (utime(d->fn, &UxAtt(d)->u.t2)) {\n            Info(slide, 0x201, ((char *)slide,\n              LoadFarString(DirlistUtimeFailed), FnFilter1(d->fn)));\n            if (!errval)\n                errval = PK_WARN;\n        }\n    }\n#ifndef NO_CHMOD\n    if (chmod(d->fn, filtattr(__G__ UxAtt(d)->perms))) {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(DirlistChmodFailed), FnFilter1(d->fn)));\n        /* perror(\"chmod (file attributes) error\"); */\n        if (!errval)\n            errval = PK_WARN;\n    }\n#endif /* !NO_CHMOD */\n    return errval;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    ztimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n      \"(unknown compiler) \",\"\",\n#endif\n      \"Syllable\",\n\n#if defined(i486) || defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__)\n      \" (x86)\",\n#else\n      \" (unknown platform)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n/*********************************/\n/* AtheOS extra field functions  */\n/*********************************/\n\n/*\n** Scan the extra fields in extra_field, and look for a AtheOS EF; return a\n** pointer to that EF, or NULL if it's not there.\n*/\nstatic uch *scanAtheOSexfield(const uch *ef_ptr, unsigned ef_len)\n{\n    while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) {\n        unsigned eb_id  = makeword(EB_ID + ef_ptr);\n        unsigned eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            Trace((stderr,\n              \"scanAtheOSexfield: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        if (eb_id == EF_ATHEOS && eb_len >= EB_BEOS_HLEN) {\n            return (uch *)ef_ptr;\n        }\n\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return NULL;\n}\n\n/* Used by setAtheOSexfield():\n\nSet a file/directory's attributes to the attributes passed in.\n\nIf set_file_attrs() fails, an error will be returned:\n\n     EOK - no errors occurred\n\n(other values will be whatever the failed function returned; no docs\nyet, or I'd list a few)\n*/\nstatic int set_file_attrs( const char *name,\n                           const unsigned char *attr_buff,\n                           const off_t attr_size )\n{\n    int                  retval = EOK;\n    unsigned char       *ptr;\n    const unsigned char *guard;\n    int                  fd;\n\n    ptr   = (unsigned char *)attr_buff;\n    guard = ptr + attr_size;\n\n    fd = open(name, O_RDWR | O_NOTRAVERSE);\n    if (fd < 0) {\n        return errno; /* should it be -fd ? */\n    }\n\n    while (ptr < guard) {\n        ssize_t              nError;\n        struct attr_info     fa_info;\n        const char          *attr_name;\n        unsigned char       *attr_data;\n\n        attr_name  = (char *)&(ptr[0]);\n        ptr       += strlen(attr_name) + 1;\n\n        /* The attr_info data is stored in little-endian format because the */\n        /* Intel i386 port was here first.                                  */\n        memcpy(&fa_info, ptr, sizeof(struct attr_info));\n        ptr     += sizeof(struct attr_info);\n\n        if (fa_info.ai_size < 0LL) {\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: skipping attribute with invalid length (%Ld)\\n\",\n                 fa_info.ai_size));\n            break;\n        }\n\n        attr_data  = ptr;\n        ptr       += fa_info.ai_size;\n\n        if (ptr > guard) {\n            /* We've got a truncated attribute. */\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: truncated attribute\\n\"));\n            break;\n        }\n\n        /* write_attr() doesn't return count of written bytes now (Syllable 0.5.3)... */\n        nError = write_attr(fd, attr_name, O_TRUNC, fa_info.ai_type,\n                            attr_data, 0, fa_info.ai_size);\n        if (nError < 0) {\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: error writing file attribute\\n\"));\n        }\n    }\n\n    close(fd);\n    return retval;\n}\n\nstatic void setAtheOSexfield(const char *path, uch *extra_field)\n{\n    uch *ptr       = extra_field;\n    ush  id        = 0;\n    ush  size      = 0;\n    ulg  full_size = 0;\n    uch  flags     = 0;\n    uch *attrbuff  = NULL;\n    int retval;\n\n    if( extra_field == NULL ) {\n        return;\n    }\n\n    /* Collect the data from the extra field buffer. */\n    id        = makeword(ptr);    ptr += 2;   /* we don't use this... */\n    size      = makeword(ptr);    ptr += 2;\n    full_size = makelong(ptr);    ptr += 4;\n    flags     = *ptr;             ptr++;\n\n    /* Do a little sanity checking. */\n    if (flags & EB_BE_FL_BADBITS) {\n        /* corrupted or unsupported */\n        Info(slide, 0x201, ((char *)slide,\n          \"Unsupported flags set for this AtheOS extra field, skipping.\\n\"));\n        return;\n    }\n    if (size <= EB_BEOS_HLEN) {\n        /* corrupted, unsupported, or truncated */\n        Info(slide, 0x201, ((char *)slide,\n             \"AtheOS extra field is %d bytes, should be at least %d.\\n\", size,\n             EB_BEOS_HLEN));\n        return;\n    }\n    if (full_size < (size - EB_BEOS_HLEN)) {\n        Info(slide, 0x201, ((char *)slide,\n             \"Skipping attributes: AtheOS extra field is %d bytes, \"\n             \"data size is %ld.\\n\", size - EB_BEOS_HLEN, full_size));\n        return;\n    }\n\n    /* Find the AtheOS file attribute data. */\n    if (flags & EB_BE_FL_UNCMPR) {\n        /* Uncompressed data */\n        attrbuff = ptr;\n    } else {\n        /* Compressed data */\n        attrbuff = (uch *)malloc( full_size );\n        if (attrbuff == NULL) {\n            /* No memory to uncompress attributes */\n            Info(slide, 0x201, ((char *)slide,\n                 \"Can't allocate memory to uncompress file attributes.\\n\"));\n            return;\n        }\n\n        retval = memextract(__G__ attrbuff, full_size,\n                            ptr, size - EB_BEOS_HLEN);\n        if( retval != PK_OK ) {\n            /* error uncompressing attributes */\n            Info(slide, 0x201, ((char *)slide,\n                 \"Error uncompressing file attributes.\\n\"));\n\n            /* Some errors here might not be so bad; we should expect */\n            /* some truncated data, for example.  If the data was     */\n            /* corrupt, we should _not_ attempt to restore the attrs  */\n            /* for this file... there's no way to detect what attrs   */\n            /* are good and which are bad.                            */\n            free (attrbuff);\n            return;\n        }\n    }\n\n    /* Now attempt to set the file attributes on the extracted file. */\n    retval = set_file_attrs(path, attrbuff, (off_t)full_size);\n    if (retval != EOK) {\n        Info(slide, 0x201, ((char *)slide,\n             \"Error writing file attributes.\\n\"));\n    }\n\n    /* Clean up, if necessary */\n    if (attrbuff != ptr) {\n        free(attrbuff);\n    }\n\n    return;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/atheos/atheos.h",
    "content": "/*\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* atheos.h -- A few handy things for the AtheOS port\n *\n * (c) 1997 Chris Herborth (chrish@qnx.com) - BeOS port\n * (c) 2004 Ruslan Nickolaev (nruslan@hotbox.ru) - AtheOS port\n *\n * This is covered under the usual Info-ZIP copyright\n */\n\n#ifndef _ATHEOS_H_\n#define _ATHEOS_H_\n\n#define EB_BE_FL_BADBITS    0xfe    /* bits currently undefined */\n\n/*\nAtheOS 'At' extra-field layout:\n(same structure as the BeOS 'Be' e.f. layout, only signature and internal\nconventions of the file attribute data are different...)\n\n'At'      - signature\nef_size   - size of data in this EF (little-endian unsigned short)\nfull_size - uncompressed data size (little-endian unsigned long)\nflag      - flags (byte)\n            flags & EB_BE_FL_UNCMPR     = the data is not compressed\n            flags & EB_BE_FL_BADBITS    = the data is corrupted or we\n                                          can't handle it properly\ndata      - compressed or uncompressed file attribute data\n\nIf flag & EB_BE_FL_UNCMPR, the data is not compressed; this optimisation is\nnecessary to prevent wasted space for files with small attributes. In this\ncase, there should be (ef_size - EB_BEOS_HLEN) bytes of data, and full_size\nshould equal (ef_size - EB_BEOS_HLEN).\n\nIf the data is compressed, there will be (ef_size - EB_BEOS_HLEN) bytes of\ncompressed data, and full_size bytes of uncompressed data.\n\nIf a file has absolutely no attributes, there will not be a 'At' extra field.\n\nThe uncompressed data is arranged like this:\n\nattr_name\\0 - C string\nstruct attr_info (fields in little-endian format)\nattr_data (length in attr_info.ai_size)\n*/\n\n#endif /* _ATHEOS_H_ */\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/Contents",
    "content": "Contents of the \"beos\" sub-directory for UnZip 5.52 and later:\n\n  Contents      this file\n  README        notes from the author of the BeOS port\n  Makefile      makefile for building UnZip (sorry, no project files)\n  beocfg.h      BeOS-specific configuration settings\n  beos.c        BeOS-specific routines (similar to the Unix ones)\n  beos.h        structures for the BeOS extra field\n  beosmain.cpp  BeOS-specific C++ routines\n  unzip.rsc     BeOS resources for UnZip\n  unzipsfx.rsc  BeOS resources for UnZipSFX\n\nThis port supports both Metrowerks CodeWarrior (PowerPC and x86) and GNU C.\n\n- Chris Herborth (chrish@qnx.com)\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/README",
    "content": "UnZip 5.4 for BeOS\n\nNOTE:\n\nIf you want to build UnZip 5.4 or later from the source, you'll need to\nhave the \"xres\" tool installed (unless you remove the \"xres\" lines in the\nbeos/Makefile).  This will cease to be a problem when BeOS R4 ships this\nfall.  Until then, you can get xres from\nftp://ftp.be.com/pub/experimental/tools/xres-102.zip.\n\nHISTORY\n\nUnZip 5.30 was the first official release of Info-ZIP's UnZip to support\nthe filesystem in BeOS.\n\nUnZip 5.31 added support for the new filesystem that appeared in the\nAdvanced Access Preview (aka DR9) Release of BeOS.\n\nUnZip 5.32 added several important bug fixes.\n\nUnZip 5.4:\n\n- supports BeOS on x86 hardware (and cross-compiling, if a compiler is\n  present)\n\n- ask the Registrar to assign a file type to files that don't have one\n\n- adds a new -J option on BeOS; this lets you extract the data for a file\n  without restoring its file attributes (handy if you stumble on really\n  old BeOS ZIP archives... from before BeOS Preview Release)\n\n- will restore attributes properly on symbolic links (you'll need\n  zip 2.21 or later to create ZIP files that store attributes for\n  symbolic links)\n\n*** WARNING ***\nYou may find some extremely old BeOS zip archives that store their\nfile attributes differently; these will be from DR8 and earlier (when\nBeOS copied the MacOS type/creator fields instead of using the current\nextremely flexible scheme).\n\nYou can still unpack the _data_ in older zip files, but you won't be\nable to recover the file attributes in those archives.  Use the -J option\nwith these files or you'll get \"compressed EA data missing\" and \"zipfile\nprobably corrupt\" errors, even though the data is intact!\n\nThe new scheme makes handling BeOS file attributes much more robust, and\nallows for possible future expansion without another round of\nincompatibilities.\n\nThat's life on the edge!\n*** WARNING ***\n\nThe new filesystem allows for huge files (up to several terabytes!) with\nhuge amounts of meta-data (up to several terabytes!).  The existing ZIP\nformat was designed when this much data on a personal computer was\nscience fiction; as a result, it's quite possible that large amounts of file\nattributes (more than maybe 100+K bytes) could be truncated.  Zip and UnZip\ntry to deal with this in a fairly sensible way, working on the assumption\nthat the data in the file is more important than the data in the file\nattributes.\n\nOne way to run into this problem is to mount an HFS volume and zip\nsome Mac files that have large resources attached to them.  This\nhappens more often than you'd expect; I've seen several 0-byte files that\nhad over four megabytes of resources.  Even more stupid, these resources\nwere _data_ (sound for a game), and could have been easily stored as\ndata...\n\nKNOWN BUGS\n\nNone! Yahoo!\n\nPlease report any bugs to Zip-Bugs@lists.wku.edu.\n\n- Chris Herborth (chrish@qnx.com)\n  November 2/1998\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/beocfg.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    BeOS specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __beocfg_h\n#define __beocfg_h\n\n#include <sys/types.h>          /* [cjh]:  This is pretty much a generic  */\n#include <sys/stat.h>           /* POSIX 1003.1 system; see beos/ for     */\n#include <fcntl.h>              /* extra code to deal with our extra file */\n#include <sys/param.h>          /* attributes. */\n#include <unistd.h>\n#include <utime.h>\n#define GOT_UTIMBUF\n#define DIRENT\n#include <time.h>\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT DF_MDY    /* GRR:  customize with locale.h somehow? */\n#endif\n#define lenEOL          1\n#define PutNativeEOL    *q++ = native(LF);\n#define SCREENSIZE(ttrows, ttcols)  screensize(ttrows, ttcols)\n#define SCREENWIDTH     80\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n#define SET_SYMLINK_ATTRIBS\n#define SET_DIR_ATTRIB\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n#define RESTORE_UIDGID\n#define NO_STRNICMP             /* not in the x86 headers at least */\n#define INT_SPRINTF\n#define SYMLINKS\n#define MAIN main_stub          /* now that we're using a wrapper... */\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    int created_dir, renamed_fullpath;\\\n    char *rootpath, *buildpath, *end;\\\n    ZCONST char *wildname;\\\n    char *dirname, matchname[FILNAMSIZ];\\\n    int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n    zvoid *wild_dir;\n\n/* created_dir, and renamed_fullpath are used by both mapname() and    */\n/*    checkdir().                                                      */\n/* rootlen, rootpath, buildpath and end are used by checkdir().        */\n/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */\n/*    and notfirstcall are used by do_wild().                          */\n\n#endif /* !__beocfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/beos.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  beos.c\n\n  BeOS-specific routines for use with Info-ZIP's UnZip 5.30 and later.\n  (based on unix/unix.c)\n\n  Contains:  do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             stamp_file()\n             version()\n             scanBeOSexfield()\n             set_file_attrs()\n             setBeOSexfield()\n             printBeOSexfield()\n             assign_MIME()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include \"beos.h\"\n#include <errno.h>             /* Just make sure we've got a few things... */\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n\n#include <dirent.h>\n\n/* For the new post-DR8 file attributes */\n#include <kernel/fs_attr.h>\n#include <support/byteorder.h>\n#include <storage/Mime.h>\n\nstatic unsigned filtattr OF((__GPRO__ unsigned perms));\nstatic uch *scanBeOSexfield  OF((const uch *ef_ptr, unsigned ef_len));\nstatic int  set_file_attrs( const char *, const unsigned char *, const off_t );\nstatic void setBeOSexfield   OF((const char *path, uch *extra_field));\n#ifdef BEOS_USE_PRINTEXFIELD\nstatic void printBeOSexfield OF((int isdir, uch *extra_field));\n#endif\n#ifdef BEOS_ASSIGN_FILETYPE\nstatic void assign_MIME( const char * );\n#endif\n\n#ifdef SET_DIR_ATTRIB\ntypedef struct uxdirattr {      /* struct for holding unix style directory */\n    struct uxdirattr *next;     /*  info until can be sorted and set at end */\n    char *fn;                   /* filename of directory */\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } u;\n    unsigned perms;             /* same as min_info.file_attr */\n    int have_uidgid;            /* flag */\n    ulg uidgid[2];\n    char fnbuf[1];              /* buffer stub for directory name */\n} uxdirattr;\n#define UxAtt(d)  ((uxdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\n/* static int created_dir;      */      /* used in mapname(), checkdir() */\n/* static int renamed_fullpath; */      /* ditto */\n\n\n/*****************************/\n/* Strings used multiple     */\n/* times in beos.c           */\n/*****************************/\n\n/* messages of code for setting file/directory attributes */\nstatic ZCONST char CannotSetItemUidGid[] =\n  \"warning:  cannot set UID %lu and/or GID %lu for %s\\n          %s\\n\";\nstatic ZCONST char CannotSetUidGid[] =\n  \" (warning) cannot set UID %lu and/or GID %lu\\n          %s\";\nstatic ZCONST char CannotSetItemTimestamps[] =\n  \"warning:  cannot set modif./access times for %s\\n          %s\\n\";\nstatic ZCONST char CannotSetTimestamps[] =\n  \" (warning) cannot set modif./access times\\n          %s\";\n\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in beocfg.h:\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n*/\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.notfirstcall) {  /* first call:  must initialize everything */\n        G.notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(G.matchname, wildspec, FILNAMSIZ);\n            G.matchname[FILNAMSIZ-1] = '\\0';\n            G.have_dirname = FALSE;\n            G.wild_dir = NULL;\n            return G.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) {\n            G.dirname = \".\";\n            G.dirnamelen = 1;\n            G.have_dirname = FALSE;\n            G.wildname = wildspec;\n        } else {\n            ++G.wildname;     /* point at character after '/' */\n            G.dirnamelen = G.wildname - wildspec;\n            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(G.matchname, wildspec, FILNAMSIZ);\n                G.matchname[FILNAMSIZ-1] = '\\0';\n                return G.matchname; /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.dirname, wildspec, G.dirnamelen);\n            G.dirname[G.dirnamelen] = '\\0';   /* terminate for strcpy below */\n            G.have_dirname = TRUE;\n        }\n\n        if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) {\n            while ((file = readdir((DIR *)G.wild_dir)) !=\n                   (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && G.wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (G.have_dirname) {\n                        strcpy(G.matchname, G.dirname);\n                        strcpy(G.matchname+G.dirnamelen, file->d_name);\n                    } else\n                        strcpy(G.matchname, file->d_name);\n                    return G.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir((DIR *)G.wild_dir);\n            G.wild_dir = (zvoid *)NULL;\n        }\n        Trace((stderr, \"do_wild:  opendir(%s) returns NULL\\n\",\n          FnFilter1(G.dirname)));\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.matchname, wildspec, FILNAMSIZ);\n        G.matchname[FILNAMSIZ-1] = '\\0';\n        return G.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if ((DIR *)G.wild_dir == (DIR *)NULL) {\n        G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */\n        if (G.have_dirname)\n            free(G.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && G.wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (G.have_dirname) {\n                /* strcpy(G.matchname, G.dirname); */\n                strcpy(G.matchname+G.dirnamelen, file->d_name);\n            } else\n                strcpy(G.matchname, file->d_name);\n            return G.matchname;\n        }\n    }\n\n    closedir((DIR *)G.wild_dir);  /* at least one entry read; nothing left */\n    G.wild_dir = (zvoid *)NULL;\n    G.notfirstcall = FALSE;       /* reset for new wildspec */\n    if (G.have_dirname)\n        free(G.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n#ifndef S_ISUID\n# define S_ISUID        0004000 /* set user id on execution */\n#endif\n#ifndef S_ISGID\n# define S_ISGID        0002000 /* set group id on execution */\n#endif\n#ifndef S_ISVTX\n# define S_ISVTX        0001000 /* save swapped text even after use */\n#endif\n\n/************************/\n/*  Function filtattr() */\n/************************/\n/* This is used to clear or keep the SUID and SGID bits on file permissions.\n * It's possible that a file in an archive could have one of these bits set\n * and, unknown to the person unzipping, could allow others to execute the\n * file as the user or group.  The new option -K bypasses this check.\n */\n\nstatic unsigned filtattr(__G__ perms)\n    __GDEF\n    unsigned perms;\n{\n    /* keep setuid/setgid/tacky perms? */\n    if (!uO.K_flag)\n        perms &= ~(S_ISUID | S_ISGID | S_ISVTX);\n\n    return (0xffff & perms);\n} /* end function filtattr() */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    int r;\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case BEOS_:\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case QDOS_:\n        case TANDEM_:\n            r = FALSE;\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap of the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n            }\n            if (!r) {\n#ifdef SYMLINKS\n                /* Check if the file is a (POSIX-compatible) symbolic link.\n                 * We restrict symlink support to those \"made-by\" hosts that\n                 * are known to support symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   SYMLINK_HOST(G.pInfo->hostnum);\n#endif\n                return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) {\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n#ifdef SYMLINKS\n                /* Entries \"made by FS_FAT_\" could have been zipped on a\n                 * system that supports POSIX-style symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   (G.pInfo->hostnum == FS_FAT_);\n#endif\n                return 0;\n            }\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in BeOS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.created_dir = FALSE;      /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    G.renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n\n            if (!uO.J_flag) {   /* Handle the BeOS extra field if present. */\n                void *ptr = scanBeOSexfield(G.extra_field,\n                                            G.lrec.extra_field_length);\n                if (ptr) {\n                    setBeOSexfield(G.filename, ptr);\n                }\n            }\n\n#ifndef NO_CHMOD\n            /* set approx. dir perms (make sure can still read/write in dir) */\n            if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr) | 0700))\n                perror(\"chmod (directory attributes) error\");\n#endif\n\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* TODO: should we re-write the BeOS extra field data in case it's */\n        /* changed?  The answer is yes. [Sept 1999 - cjh]                  */\n        if (!uO.J_flag) {   /* Handle the BeOS extra field if present. */\n            void *ptr = scanBeOSexfield(G.extra_field,\n                                        G.lrec.extra_field_length);\n            if (ptr) {\n                setBeOSexfield(G.filename, ptr);\n            }\n        }\n\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    /* On UNIX (and compatible systems), \".\" and \"..\" are reserved for\n     * directory navigation and cannot be used as regular file names.\n     * These reserved one-dot and two-dot names are mapped to \"_\" and \"__\".\n     */\n    if (strcmp(pathcomp, \".\") == 0)\n        *pathcomp = '_';\n    else if (strcmp(pathcomp, \"..\") == 0)\n        strcpy(pathcomp, \"__\");\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n /* static int rootlen = 0; */  /* length of rootpath */\n /* static char *rootpath;  */  /* user's \"extract-to\" directory */\n /* static char *buildpath; */  /* full path (so far) to extracted file */\n /* static char *end;       */  /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0')\n            ++G.end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((G.end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check: need to append '/', at least one-char name, '\\0' */\n        if ((G.end-G.buildpath) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n        if (SSTAT(G.buildpath, &G.statbuf)) {   /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpath)));\n                free(G.buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(G.buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpath),\n                  strerror(errno),\n                  FnFilter1(G.filename)));\n                free(G.buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(G.buildpath), FnFilter1(G.filename)));\n            free(G.buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(G.buildpath)));\n            free(G.buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.end++ = '/';\n        *G.end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    G.buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, G.buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(G.buildpath);\n        G.buildpath = G.end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0') {\n            ++G.end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((G.end-old_end) > FILENAME_MAX)    /* GRR:  proper constant? */\n                *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((G.end-G.buildpath) >= FILNAMSIZ) {\n                *--G.end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(G.buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+\n                                          (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((G.rootlen > 0) && !G.renamed_fullpath) {\n            strcpy(G.buildpath, G.rootpath);\n            G.end = G.buildpath + G.rootlen;\n        } else {\n            *G.buildpath = '\\0';\n            G.end = G.buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            G.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) {\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[G.rootlen-1] == '/') {\n                tmproot[--G.rootlen] = '\\0';\n            }\n            if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                  !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\\\n           %s\\n\",\n                      FnFilter1(tmproot), strerror(errno)));\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[G.rootlen++] = '/';\n            tmproot[G.rootlen] = '\\0';\n            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n                free(tmproot);\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            free(G.rootpath);\n            G.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\nstatic int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2]));\n\nstatic int get_extattribs(__G__ pzt, z_uidgid)\n    __GDEF\n    iztimes *pzt;\n    ulg z_uidgid[2];\n{\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.  On the other hand, we\n    then have to check for restoration of UID/GID.\n  ---------------------------------------------------------------------------*/\n    int have_uidgid_flg;\n    unsigned eb_izux_flg;\n\n    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                   (G.tz_is_valid ? pzt : NULL),\n#else\n                   pzt,\n#endif\n                   z_uidgid) : 0);\n    if (eb_izux_flg & EB_UT_FL_MTIME) {\n        TTrace((stderr, \"\\nget_extattribs:  Unix e.f. modif. time = %ld\\n\",\n          pzt->mtime));\n    } else {\n        pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n    if (eb_izux_flg & EB_UT_FL_ATIME) {\n        TTrace((stderr, \"get_extattribs:  Unix e.f. access time = %ld\\n\",\n          pzt->atime));\n    } else {\n        pzt->atime = pzt->mtime;\n        TTrace((stderr, \"\\nget_extattribs:  modification/access times = %ld\\n\",\n          pzt->mtime));\n    }\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    have_uidgid_flg =\n#ifdef RESTORE_UIDGID\n            (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));\n#else\n            0;\n#endif\n    return have_uidgid_flg;\n}\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } zt;\n    ulg z_uidgid[2];\n    int have_uidgid_flg;\n\n    have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate storage for a symlink control\n    structure, put the uncompressed \"data\" and other required info in it, and\n    add the structure to the \"deferred symlinks\" chain.  Since we know it's a\n    symbolic link to start with, we shouldn't have to worry about overflowing\n    unsigned ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SYMLINKS\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n        unsigned BeOSef_len = 0;\n        extent slnk_entrysize;\n        uch *BeOS_exfld;\n        slinkentry *slnk_entry;\n\n        if (!uO.J_flag) {\n            /* Symlinks can have attributes, too. */\n            BeOS_exfld = scanBeOSexfield(G.extra_field,\n                                         G.lrec.extra_field_length);\n            if (BeOS_exfld) {\n                BeOSef_len = makeword(EB_LEN + BeOS_exfld) + EB_HEADSIZE;\n            }\n        }\n\n        /* size of the symlink entry is the sum of\n         *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n         *  system specific attribute data size (might be 0),\n         *  and the lengths of name and link target.\n         */\n        slnk_entrysize = (sizeof(slinkentry) + 1) + BeOSef_len +\n                         ucsize + strlen(G.filename);\n\n        if (slnk_entrysize < ucsize) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n\n        if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: no mem\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n        slnk_entry->next = NULL;\n        slnk_entry->targetlen = ucsize;\n        slnk_entry->attriblen = BeOSef_len;\n        slnk_entry->target = slnk_entry->buf + BeOSef_len;\n        slnk_entry->fname = slnk_entry->target + ucsize + 1;\n        strcpy(slnk_entry->fname, G.filename);\n        if (BeOSef_len > 0)\n            memcpy(slnk_entry->buf, BeOS_exfld, BeOSef_len);\n\n        /* move back to the start of the file to re-read the \"link data\" */\n        rewind(G.outfile);\n\n        if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed\\n\",\n              FnFilter1(G.filename)));\n            free(slnk_entry);\n            fclose(G.outfile);\n            return;\n        }\n        fclose(G.outfile);                  /* close \"link\" file for good... */\n        slnk_entry->target[ucsize] = '\\0';\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"-> %s \",\n              FnFilter1(slnk_entry->target)));\n        /* add this symlink record to the list of deferred symlinks */\n        if (G.slink_last != NULL)\n            G.slink_last->next = slnk_entry;\n        else\n            G.slink_head = slnk_entry;\n        G.slink_last = slnk_entry;\n        return;\n    }\n#endif /* SYMLINKS */\n\n    fclose(G.outfile);\n\n    /* handle the BeOS extra field if present */\n    if (!uO.J_flag) {\n        void *ptr = scanBeOSexfield(G.extra_field,\n                                    G.lrec.extra_field_length);\n\n        if (ptr) {\n            setBeOSexfield(G.filename, ptr);\n#ifdef BEOS_ASSIGN_FILETYPE\n        } else {\n            /* Otherwise, ask the system to try assigning a MIME type. */\n            assign_MIME( G.filename );\n#endif\n        }\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr)))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    if (have_uidgid_flg\n        /* check that both uid and gid values fit into their data sizes */\n        && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0])\n        && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) {\n        TTrace((stderr, \"close_outfile:  restoring Unix UID/GID info\\n\"));\n        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))\n        {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,\n                  z_uidgid[0], z_uidgid[1], FnFilter1(G.filename),\n                  strerror(errno)));\n            else\n                Info(slide, 0x201, ((char *)slide, CannotSetUidGid,\n                  z_uidgid[0], z_uidgid[1], strerror(errno)));\n        }\n    }\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        /* set the file's access and modification times */\n        if (utime(G.filename, &(zt.t2))) {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,\n                  FnFilter1(G.filename), strerror(errno)));\n            else\n                Info(slide, 0x201, ((char *)slide, CannotSetTimestamps,\n                  strerror(errno)));\n        }\n    }\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef SYMLINKS\nint set_symlnk_attribs(__G__ slnk_entry)\n    __GDEF\n    slinkentry *slnk_entry;\n{\n    if (slnk_entry->attriblen > 0)\n        setBeOSexfield(slnk_entry->fname, (uch *)slnk_entry->buf);\n    /* currently, no error propagation... */\n    return PK_OK;\n} /* end function set_symlnk_attribs() */\n#endif /* SYMLINKS */\n\n\n\n\n#ifdef SET_DIR_ATTRIB\n/* messages of code for setting directory attributes */\n#  ifndef NO_CHMOD\n  static ZCONST char DirlistChmodFailed[] =\n    \"warning:  cannot set permissions for %s\\n          %s\\n\";\n#  endif\n\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    uxdirattr *d_entry;\n\n    d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename));\n    *pd = (direntry *)d_entry;\n    if (d_entry == (uxdirattr *)NULL) {\n        return PK_MEM;\n    }\n    d_entry->fn = d_entry->fnbuf;\n    strcpy(d_entry->fn, G.filename);\n\n    d_entry->perms = G.pInfo->file_attr;\n\n    d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3),\n                                          d_entry->uidgid);\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    int errval = PK_OK;\n\n    if (UxAtt(d)->have_uidgid &&\n        /* check that both uid and gid values fit into their data sizes */\n        ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) &&\n        ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) &&\n        chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0],\n              (gid_t)UxAtt(d)->uidgid[1]))\n    {\n        Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,\n          UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn),\n          strerror(errno)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n    /* Skip restoring directory time stamps on user' request. */\n    if (uO.D_flag <= 0) {\n        /* restore directory timestamps */\n        if (utime(d->fn, (const struct utimbuf *)&UxAtt(d)->u.t2)) {\n            Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,\n              FnFilter1(d->fn), strerror(errno)));\n            if (!errval)\n                errval = PK_WARN;\n        }\n    }\n#ifndef NO_CHMOD\n    if (chmod(d->fn, filtattr(__G__ UxAtt(d)->perms))) {\n        Info(slide, 0x201, ((char *)slide, DirlistChmodFailed,\n          FnFilter1(d->fn), strerror(errno)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n#endif /* !NO_CHMOD */\n    return errval;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    struct utimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n#if defined(__MWERKS__)\n      \"Metrowerks CodeWarrior\", \"\",\n#elif defined(__GNUC__)\n      \"GNU C \", __VERSION__,\n#else\n      \"(unknown compiler) \",\"\",\n#endif\n      \"BeOS \",\n\n#ifdef __POWERPC__\n      \"(PowerPC)\",\n#else\n# ifdef __INTEL__\n      \"(x86)\",\n# else\n      \"(unknown)\",   /* someday we may have other architectures... */\n# endif\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n/******************************/\n/* Extra field functions      */\n/******************************/\n\n/*\n** Scan the extra fields in extra_field, and look for a BeOS EF; return a\n** pointer to that EF, or NULL if it's not there.\n*/\nstatic uch *scanBeOSexfield(const uch *ef_ptr, unsigned ef_len)\n{\n    while( ef_ptr != NULL && ef_len >= EB_HEADSIZE ) {\n        unsigned eb_id  = makeword(EB_ID + ef_ptr);\n        unsigned eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            Trace((stderr,\n              \"scanBeOSexfield: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        if (eb_id == EF_BEOS && eb_len >= EB_BEOS_HLEN) {\n            return (uch *)ef_ptr;\n        }\n\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return NULL;\n}\n\n/* Used by setBeOSexfield():\n\nSet a file/directory's attributes to the attributes passed in.\n\nIf set_file_attrs() fails, an error will be returned:\n\n     EOK - no errors occurred\n\n(other values will be whatever the failed function returned; no docs\nyet, or I'd list a few)\n*/\nstatic int set_file_attrs( const char *name,\n                           const unsigned char *attr_buff,\n                           const off_t attr_size )\n{\n    int                  retval = EOK;\n    unsigned char       *ptr;\n    const unsigned char *guard;\n    int                  fd;\n\n    ptr   = (unsigned char *)attr_buff;\n    guard = ptr + attr_size;\n\n    fd = open(name, O_RDWR | O_NOTRAVERSE);\n    if (fd < 0) {\n        return errno; /* should it be -fd ? */\n    }\n\n    while (ptr < guard) {\n        ssize_t              wrote_bytes;\n        struct attr_info     fa_info;\n        const char          *attr_name;\n        unsigned char       *attr_data;\n\n        attr_name  = (char *)&(ptr[0]);\n        ptr       += strlen(attr_name) + 1;\n\n        /* The attr_info data is stored in big-endian format because the */\n        /* PowerPC port was here first.                                  */\n        memcpy(&fa_info, ptr, sizeof(struct attr_info));\n        fa_info.type = (uint32)B_BENDIAN_TO_HOST_INT32( fa_info.type );\n        fa_info.size = (off_t)B_BENDIAN_TO_HOST_INT64( fa_info.size );\n        ptr     += sizeof(struct attr_info);\n\n        if (fa_info.size < 0LL) {\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: skipping attribute with invalid length (%Ld)\\n\",\n                 fa_info.size));\n            break;\n        }\n\n        attr_data  = ptr;\n        ptr       += fa_info.size;\n\n        if (ptr > guard) {\n            /* We've got a truncated attribute. */\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: truncated attribute\\n\"));\n            break;\n        }\n\n        /* Wave the magic wand... this will swap Be-known types properly. */\n        (void)swap_data( fa_info.type, attr_data, fa_info.size,\n                         B_SWAP_BENDIAN_TO_HOST );\n\n        wrote_bytes = fs_write_attr(fd, attr_name, fa_info.type, 0,\n                                    attr_data, fa_info.size);\n        if (wrote_bytes != fa_info.size) {\n            Info(slide, 0x201, ((char *)slide,\n                 \"warning: wrote %ld attribute bytes of %ld\\n\",\n                 (unsigned long)wrote_bytes,(unsigned long)fa_info.size));\n        }\n    }\n\n    close(fd);\n\n    return retval;\n}\n\nstatic void setBeOSexfield(const char *path, uch *extra_field)\n{\n    uch *ptr       = extra_field;\n    ush  id        = 0;\n    ush  size      = 0;\n    ulg  full_size = 0;\n    uch  flags     = 0;\n    uch *attrbuff  = NULL;\n    int retval;\n\n    if( extra_field == NULL ) {\n        return;\n    }\n\n    /* Collect the data from the extra field buffer. */\n    id        = makeword(ptr);    ptr += 2;   /* we don't use this... */\n    size      = makeword(ptr);    ptr += 2;\n    full_size = makelong(ptr);    ptr += 4;\n    flags     = *ptr;             ptr++;\n\n    /* Do a little sanity checking. */\n    if (flags & EB_BE_FL_BADBITS) {\n        /* corrupted or unsupported */\n        Info(slide, 0x201, ((char *)slide,\n          \"Unsupported flags set for this BeOS extra field, skipping.\\n\"));\n        return;\n    }\n    if (size <= EB_BEOS_HLEN) {\n        /* corrupted, unsupported, or truncated */\n        Info(slide, 0x201, ((char *)slide,\n             \"BeOS extra field is %d bytes, should be at least %d.\\n\", size,\n             EB_BEOS_HLEN));\n        return;\n    }\n    if (full_size < (size - EB_BEOS_HLEN)) {\n        /* possible old archive? will this screw up on valid archives? */\n        Info(slide, 0x201, ((char *)slide,\n             \"Skipping attributes: BeOS extra field is %d bytes, \"\n             \"data size is %ld.\\n\", size - EB_BEOS_HLEN, full_size));\n        return;\n    }\n\n    /* Find the BeOS file attribute data. */\n    if (flags & EB_BE_FL_UNCMPR) {\n        /* Uncompressed data */\n        attrbuff = ptr;\n    } else {\n        /* Compressed data */\n        attrbuff = (uch *)malloc( full_size );\n        if (attrbuff == NULL) {\n            /* No memory to uncompress attributes */\n            Info(slide, 0x201, ((char *)slide,\n                 \"Can't allocate memory to uncompress file attributes.\\n\"));\n            return;\n        }\n\n        retval = memextract(__G__ attrbuff, full_size,\n                            ptr, size - EB_BEOS_HLEN);\n        if( retval != PK_OK ) {\n            /* error uncompressing attributes */\n            Info(slide, 0x201, ((char *)slide,\n                 \"Error uncompressing file attributes.\\n\"));\n\n            /* Some errors here might not be so bad; we should expect */\n            /* some truncated data, for example.  If the data was     */\n            /* corrupt, we should _not_ attempt to restore the attrs  */\n            /* for this file... there's no way to detect what attrs   */\n            /* are good and which are bad.                            */\n            free (attrbuff);\n            return;\n        }\n    }\n\n    /* Now attempt to set the file attributes on the extracted file. */\n    retval = set_file_attrs(path, attrbuff, (off_t)full_size);\n    if (retval != EOK) {\n        Info(slide, 0x201, ((char *)slide,\n             \"Error writing file attributes.\\n\"));\n    }\n\n    /* Clean up, if necessary */\n    if (attrbuff != ptr) {\n        free(attrbuff);\n    }\n\n    return;\n}\n\n#ifdef BEOS_USE_PRINTEXFIELD\nstatic void printBeOSexfield( int isdir, uch *extra_field )\n{\n    uch *ptr       = extra_field;\n    ush  id        = 0;\n    ush  size      = 0;\n    ulg  full_size = 0;\n    uch  flags     = 0;\n\n    /* Tell picky compilers to be quiet. */\n    isdir = isdir;\n\n    if( extra_field == NULL ) {\n        return;\n    }\n\n    /* Collect the data from the buffer. */\n    id        = makeword( ptr );    ptr += 2;\n    size      = makeword( ptr );    ptr += 2;\n    full_size = makelong( ptr );    ptr += 4;\n    flags     = *ptr;               ptr++;\n\n    if( id != EF_BEOS ) {\n        /* not a 'Be' field */\n        printf(\"\\t*** Unknown field type (0x%04x, '%c%c')\\n\", id,\n               (char)(id >> 8), (char)id);\n    }\n\n    if( flags & EB_BE_FL_BADBITS ) {\n        /* corrupted or unsupported */\n        printf(\"\\t*** Corrupted BeOS extra field:\\n\");\n        printf(\"\\t*** unknown bits set in the flags\\n\");\n        printf(\"\\t*** (Possibly created by an old version of zip for BeOS.\\n\");\n    }\n\n    if( size <= EB_BEOS_HLEN ) {\n        /* corrupted, unsupported, or truncated */\n        printf(\"\\t*** Corrupted BeOS extra field:\\n\");\n        printf(\"\\t*** size is %d, should be larger than %d\\n\", size,\n               EB_BEOS_HLEN );\n    }\n\n    if( flags & EB_BE_FL_UNCMPR ) {\n        /* Uncompressed data */\n        printf(\"\\tBeOS extra field data (uncompressed):\\n\");\n        printf(\"\\t\\t%ld data bytes\\n\", full_size);\n    } else {\n        /* Compressed data */\n        printf(\"\\tBeOS extra field data (compressed):\\n\");\n        printf(\"\\t\\t%d compressed bytes\\n\", size - EB_BEOS_HLEN);\n        printf(\"\\t\\t%ld uncompressed bytes\\n\", full_size);\n    }\n}\n#endif\n\n#ifdef BEOS_ASSIGN_FILETYPE\n/* Note: This will no longer be necessary in BeOS PR4; update_mime_info()    */\n/* will be updated to build its own absolute pathname if it's not given one. */\nstatic void assign_MIME( const char *file )\n{\n    char *fullname;\n    char buff[PATH_MAX], cwd_buff[PATH_MAX];\n    int retval;\n\n    if( file[0] == '/' ) {\n        fullname = (char *)file;\n    } else {\n        sprintf( buff, \"%s/%s\", getcwd( cwd_buff, PATH_MAX ), file );\n        fullname = buff;\n    }\n\n    retval = update_mime_info( fullname, FALSE, TRUE, TRUE );\n}\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/beos.h",
    "content": "/*\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* beos.h -- A few handy things for the BeOS port.     */\n/* (c) 1997 Chris Herborth (chrish@qnx.com)            */\n/* This is covered under the usual Info-ZIP copyright. */\n\n/* \"#define EF_BE_FL_UNCMPR 0x01\" has been moved into unzpriv.h */\n#define EB_BE_FL_BADBITS    0xfe    /* bits currently undefined */\n\n#define BEOS_ASSIGN_FILETYPE 1      /* call update_mime_info() */\n\n/*\nDR9 'Be' extra-field layout:\n\n'Be'      - signature\nef_size   - size of data in this EF (little-endian unsigned short)\nfull_size - uncompressed data size (little-endian unsigned long)\nflag      - flags (byte)\n            flags & EB_BE_FL_UNCMPR     = the data is not compressed\n            flags & EB_BE_FL_BADBITS    = the data is corrupted or we\n                                          can't handle it properly\ndata      - compressed or uncompressed file attribute data\n\nIf flag & EB_BE_FL_UNCMPR, the data is not compressed; this optimisation is\nnecessary to prevent wasted space for files with small attributes (which\nappears to be quite common on the Advanced Access DR9 release).  In this\ncase, there should be ( ef_size - EB_BEOS_HLEN ) bytes of data, and full_size\nshould equal ( ef_size - EB_BEOS_HLEN ).\n\nIf the data is compressed, there will be ( ef_size - EB_BEOS_HLEN ) bytes of\ncompressed data, and full_size bytes of uncompressed data.\n\nIf a file has absolutely no attributes, there will not be a 'Be' extra field.\n\nThe uncompressed data is arranged like this:\n\nattr_name\\0 - C string\nstruct attr_info (fields in big-endian format)\nattr_data (length in attr_info.size)\n*/\n"
  },
  {
    "path": "deps/infozip/unzip60/beos/beosmain.cpp",
    "content": "// -*- C++ -*-\n/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//\n// WARNING: This is C++, not C!  GNU C is not supported here!\n//\n// beos_init.cpp\n//\n// BeOS-specific C++ routines for use with Info-ZIP's UnZip 5.30 or later.\n//\n// This is necessary because we need to have an app_server connection to be\n// able to ask the system to assign a MIME type to an un-typed file.  Strange\n// but true (the update_mime_info() call needs to send/receive messages).\n//\n// If you're writing your own Zip application, you probably DO NOT want to\n// include this file!\n\n#include <app/Application.h>\n\n#ifdef SFX\nconst static char *unzip_signature = \"application/x-vnd.Info-ZIP.UnZipSFX\";\n#else\nconst static char *unzip_signature = \"application/x-vnd.Info-ZIP.UnZip\";\n#endif\n\nextern \"C\" int main_stub( int argc, char *argv[] );\n\nint main( int argc, char **argv )\n{\n    BApplication app( unzip_signature );\n\n    int retval = main_stub( argc, argv );\n\n    app.PostMessage( B_QUIT_REQUESTED );\n    app.Run();\n\n    return retval;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/00README.IZ",
    "content": "This folder is the root folder for the externally supplied bzip2 source code.\nAdditionally, this folder contains the following Info-ZIP-specific files:\n\n  00README.IZ   this file\n  Makebz2.iz    \"generic\" make script for the base bzip2 lib used in UnZip\n  makbz2iz.msc  make script for the bzip2 support, win32 port, MS VC++\n  makbz2iz.wat  make script for bzip2 support, msdos & win32, OpenWatcom C++\n  descrbz2.mms  MMS/MMK make script for OpenVMS\n  buildbz2.com  OpenVMS DCL procedure to build the base bz2 lib used in UnZip\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/Makebz2.iz",
    "content": "# Makefile for UnZip's bzip2 support library\n# Unix, and other ports using sufficiently unix-compatible\n# library naming conventions (e.g. misc. GCC ports)\n#\n# (c) 2006-2007 Info-ZIP\n# Last revision: Christian Spieler, 2007-Mar-31\n#\n# This Makefile is intended to be called from UnZip's main make procedure.\n\nSHELL=/bin/sh\n\n# To assist in cross-compiling\nCC=gcc\nAR=ar\nRANLIB=ranlib\nRM=rm -f\nLDFLAGS=\nO=.o\n\nCFLAGS=-Wall -Winline -O2 -g\nCCBZ2DEFS=-DBZ_NO_STDIO\n\n\nOBJS= blocksort$(O)  \\\n      huffman$(O)    \\\n      crctable$(O)   \\\n      randtable$(O)  \\\n      compress$(O)   \\\n      decompress$(O) \\\n      bzlib$(O)\n\n# How to compile sources\n.c$(O):\n\t$(CC) $(CFLAGS) $(CCBZ2DEFS) -o $@ -c $<\n\nall: libbz2.a\n\nlibbz2.a: $(OBJS)\n\t-@$(RM) libbz2.a\n\t$(AR) cq libbz2.a $(OBJS)\n\t-$(RANLIB) libbz2.a\n\nclean:\n\t$(RM) $(OBJS) libbz2.a\n\n$(OBJS): bzlib.h bzlib_private.h\n\nblocksort$(O): blocksort.c\nhuffman$(O): huffman.c\ncrctable$(O): crctable.c\nrandtable$(O): randtable.c\ncompress$(O): compress.c\ndecompress$(O): decompress.c\nbzlib$(O): bzlib.c\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/buildbz2.com",
    "content": "$! BUILDBZ2.COM\n$!\n$!     Build procedure for LIBBZ2_NS support library used with the\n$!     VMS versions of UnZip/ZipInfo and UnZipSFX\n$!\n$!     Last revised:  2007-12-29  CS.\n$!\n$!     Command args:\n$!     - select compiler environment: \"VAXC\", \"DECC\", \"GNUC\"\n$!     - select compiler listings: \"LIST\"  Note that the whole argument\n$!       is added to the compiler command, so more elaborate options\n$!       like \"LIST/SHOW=ALL\" (quoted or space-free) may be specified.\n$!     - supply additional compiler options: \"CCOPTS=xxx\"  Allows the\n$!       user to add compiler command options like /ARCHITECTURE or\n$!       /[NO]OPTIMIZE.  For example, CCOPTS=/ARCH=HOST/OPTI=TUNE=HOST\n$!       or CCOPTS=/DEBUG/NOOPTI.  These options must be quoted or\n$!       space-free.\n$!\n$!     To specify additional options, define the symbol LOCAL_BZIP2\n$!     as a comma-separated list of the C macros to be defined, and\n$!     then run BUILDBZ2.COM.  For example:\n$!\n$!             $ LOCAL_BZIP2 = \"RETURN_CODES\"\n$!             $ @ []BUILDBZ2.COM\n$!\n$!     If you edit this procedure to set LOCAL_BZIP2 here, be sure to\n$!     use only one \"=\", to avoid affecting other procedures.\n$!\n$!\n$ on error then goto error\n$ on control_y then goto error\n$ OLD_VERIFY = f$verify(0)\n$!\n$ edit := edit                  ! override customized edit commands\n$ say := write sys$output\n$!\n$!##################### Read settings from environment ########################\n$!\n$ if (f$type(LOCAL_BZIP2) .eqs. \"\")\n$ then\n$     local_bzip2 = \"\"\n$ else  ! Trim blanks and append comma if missing\n$     local_bzip2 = f$edit(local_bzip2, \"TRIM\")\n$     if (f$extract((f$length(local_bzip2) - 1), 1, local_bzip2) .nes. \",\")\n$     then\n$         local_bzip2 = local_bzip2 + \", \"\n$     endif\n$ endif\n$!\n$!##################### Customizing section #############################\n$!\n$ unzx_unx = \"UNZIP\"\n$ unzx_cli = \"UNZIP_CLI\"\n$ unzsfx_unx = \"UNZIPSFX\"\n$ unzsfx_cli = \"UNZIPSFX_CLI\"\n$!\n$ CCOPTS = \"\"\n$ LINKOPTS = \"/notraceback\"\n$ LISTING = \" /nolist\"\n$ MAY_USE_DECC = 1\n$ MAY_USE_GNUC = 0\n$!\n$! Process command line parameters requesting optional features.\n$!\n$ arg_cnt = 1\n$ argloop:\n$     current_arg_name = \"P''arg_cnt'\"\n$     curr_arg = f$edit( 'current_arg_name', \"UPCASE\")\n$     if (curr_arg .eqs. \"\") then goto argloop_out\n$!\n$     if (f$extract( 0, 5, curr_arg) .eqs. \"CCOPT\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         CCOPTS = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 4, curr_arg) .eqs. \"LIST\")\n$     then\n$         LISTING = \"/''curr_arg'\"      ! But see below for mods.\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"VAXC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"DECC\")\n$     then\n$         MAY_USE_DECC = 1\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"GNUC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 1\n$         goto argloop_end\n$     endif\n$!\n$     say \"Unrecognized command-line option: ''curr_arg'\"\n$     goto error\n$!\n$     argloop_end:\n$     arg_cnt = arg_cnt + 1\n$ goto argloop\n$ argloop_out:\n$!\n$!#######################################################################\n$!\n$! Find out current disk, directory, compiler and options\n$!\n$ workdir = f$environment(\"default\")\n$ here = f$parse(workdir, , , \"device\") + f$parse(workdir, , , \"directory\")\n$!\n$! Sense the host architecture (Alpha, Itanium, or VAX).\n$!\n$ if (f$getsyi(\"HW_MODEL\") .lt. 1024)\n$ then\n$     arch = \"VAX\"\n$ else\n$     if (f$getsyi(\"ARCH_TYPE\") .eq. 2)\n$     then\n$         arch = \"ALPHA\"\n$     else\n$         if (f$getsyi(\"ARCH_TYPE\") .eq. 3)\n$         then\n$             arch = \"IA64\"\n$         else\n$             arch = \"unknown_arch\"\n$         endif\n$     endif\n$ endif\n$!\n$ dest = arch\n$ cmpl = \"DEC/Compaq/HP C\"\n$ opts = \"\"\n$ if (arch .nes. \"VAX\")\n$ then\n$     HAVE_DECC_VAX = 0\n$     USE_DECC_VAX = 0\n$!\n$     if (MAY_USE_GNUC)\n$     then\n$         say \"GNU C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build UnZip.\"\n$         goto error\n$     endif\n$!\n$     if (.not. MAY_USE_DECC)\n$     then\n$         say \"VAX C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build UnZip.\"\n$         goto error\n$     endif\n$!\n$     cc = \"cc /standard=relax /prefix=all /ansi /names=(as_is)\"\n$     defs = \"''local_bzip2'\"\n$ else\n$     HAVE_DECC_VAX = (f$search(\"SYS$SYSTEM:DECC$COMPILER.EXE\") .nes. \"\")\n$     HAVE_VAXC_VAX = (f$search(\"SYS$SYSTEM:VAXC.EXE\") .nes. \"\")\n$     MAY_HAVE_GNUC = (f$trnlnm(\"GNU_CC\") .nes. \"\")\n$     if (HAVE_DECC_VAX .and. MAY_USE_DECC)\n$     then\n$         ! We use DECC:\n$         USE_DECC_VAX = 1\n$         cc = \"cc /decc /prefix=all /names=(as_is)\"\n$         defs = \"''local_bzip2'\"\n$     else\n$         ! We use VAXC (or GNU C):\n$         USE_DECC_VAX = 0\n$         defs = \"''local_bzip2'\"\n$         if ((.not. HAVE_VAXC_VAX .and. MAY_HAVE_GNUC) .or. MAY_USE_GNUC)\n$         then\n$             cc = \"gcc\"\n$             dest = \"''dest'G\"\n$             cmpl = \"GNU C\"\n$             opts = \"GNU_CC:[000000]GCCLIB.OLB /LIBRARY,\"\n$         else\n$             if (HAVE_DECC_VAX)\n$             then\n$                 cc = \"cc /vaxc\"\n$             else\n$                 cc = \"cc\"\n$             endif\n$             dest = \"''dest'V\"\n$             cmpl = \"VAX C\"\n$         endif\n$     endif\n$ endif\n$!\n$! Reveal the plan.  If compiling, set some compiler options.\n$!\n$     say \"Compiling bzip2 on ''arch' using ''cmpl'.\"\n$!\n$     DEF_NS = \"/define = (''defs'BZ_NO_STDIO, VMS)\"\n$!\n$! If [.'dest'] does not exist, either complain (link-only) or make it.\n$!\n$ if (f$search(\"''dest'.dir;1\") .eqs. \"\")\n$ then\n$     create /directory [.'dest']\n$ endif\n$!\n$! Arrange to get arch-specific list file placement, if listing, and if\n$! the user didn't specify a particular \"/LIST =\" destination.\n$!\n$     L = f$edit(LISTING, \"COLLAPSE\")\n$     if ((f$extract(0, 5, L) .eqs. \"/LIST\") .and. -\n       (f$extract(4, 1, L) .nes. \"=\"))\n$     then\n$         LISTING = \" /LIST = [.''dest']\" + f$extract(5, 1000, LISTING)\n$     endif\n$!\n$! Define compiler command.\n$!\n$     cc = cc + \" /include = ([])\" + LISTING + CCOPTS\n$!\n$! Show interesting facts.\n$!\n$ say \"   architecture = ''arch' (destination = [.''dest'])\"\n$ say \"   cc = ''cc'\"\n$ say \"\"\n$!\n$ tmp = f$verify( 1)    ! Turn echo on to see what's happening.\n$!\n$!------------------------------- BZip2 section ------------------------------\n$!\n$! Compile the sources.\n$!\n$     cc 'DEF_NS' /object = [.'dest']blocksort.OBJ blocksort.c\n$     cc 'DEF_NS' /object = [.'dest']huffman.OBJ huffman.c\n$     cc 'DEF_NS' /object = [.'dest']crctable.OBJ crctable.c\n$     cc 'DEF_NS' /object = [.'dest']randtable.OBJ randtable.c\n$     cc 'DEF_NS' /object = [.'dest']compress.OBJ compress.c\n$     cc 'DEF_NS' /object = [.'dest']decompress.OBJ decompress.c\n$     cc 'DEF_NS' /object = [.'dest']bzlib.OBJ bzlib.c\n$!\n$! Create the object library.\n$!\n$     if (f$search( \"[.''dest']LIBBZ2_NS.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']LIBBZ2_NS.OLB\n$!\n$     libr /object /replace [.'dest']LIBBZ2_NS.OLB -\n       [.'dest']blocksort.OBJ, -\n       [.'dest']huffman.OBJ, -\n       [.'dest']crctable.OBJ, -\n       [.'dest']randtable.OBJ, -\n       [.'dest']compress.OBJ, -\n       [.'dest']decompress.OBJ, -\n       [.'dest']bzlib.OBJ\n$!\n$! Restore the original default directory, deassign the temporary\n$! logical names, and restore the DCL verify status.\n$!\n$ error:\n$!\n$ if (f$type(here) .nes. \"\")\n$ then\n$     if (here .nes. \"\")\n$     then\n$         set default 'here'\n$     endif\n$ endif\n$!\n$ if (f$type(OLD_VERIFY) .nes. \"\")\n$ then\n$     tmp = f$verify(OLD_VERIFY)\n$ endif\n$!\n$ exit\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/descrbz2.mms",
    "content": "!==========================================================================\n! MMS description file for bzip2 support in UnZip 6              2008-02-16\n!==========================================================================\n!\n! To build the LIBBZ2_NS library, edit the USER CUSTOMIZATION\n! lines below to taste, then do\n!\tmms\n! or\n!\tmmk\n! if you use Matt's Make (free MMS-compatible make utility).\n!\n! In all other cases where you want to explicitly specify a makefile target,\n! you have to specify your compiling environment, too. These are:\n!\n!\t$ MMS/MACRO=(__ALPHA__=1)\t\t! Alpha AXP, (DEC C)\n!\t$ MMS/MACRO=(__IA64__=1)\t\t! IA64, (DEC C)\n!\t$ MMS/MACRO=(__DECC__=1)\t\t! VAX, using DEC C\n!\t$ MMS/MACRO=(__FORCE_VAXC__=1)\t\t! VAX, prefering VAXC over DECC\n!\t$ MMS/MACRO=(__VAXC__=1)\t\t! VAX, where VAXC is default\n!\t$ MMS/MACRO=(__GNUC__=1)\t\t! VAX, using GNU C\n!\n\n! To delete all .OBJ, .OLB, .EXE and .HLP files,\n!\tmms clean\n\n## The \"DO_THE_BUILD\" target does no longer work with current\n## releases of the MMS tool, sigh.\n#DO_THE_BUILD :\n#\t@ decc = f$search(\"SYS$SYSTEM:DECC$COMPILER.EXE\").nes.\"\"\n#\t@ axp = (f$getsyi(\"HW_MODEL\") .ge. 1024) .and. -\n#\t   (f$getsyi(\"HW_MODEL\") .lt. 4096)\n#\t@ i64 = f$getsyi(\"HW_MODEL\") .ge. 4096\n#\t@ macro = \"/MACRO=(\"\n#.IFDEF CCOPTS\n#\t@ macro = macro + \"\"\"CCOPTS=$(CCOPTS)\"\",\"\n#.ENDIF\n#\t@ if decc then macro = macro + \"__DECC__=1,\"\n#\t@ if axp then macro = macro + \"__ALPHA__=1,\"\n#\t@ if i64 then macro = macro + \"__IA64__=1,\"\n#\t@ if .not.(axp .or. i64 .or. decc) then macro = macro + \"__VAXC__=1,\"\n#\t@ macro = f$extract(0,f$length(macro)-1,macro)+ \")\"\n#\t$(MMS)$(MMSQUALIFIERS)'macro' DEFAULT\n\n# Define MMK architecture macros when using MMS.\n\n.IFDEF __MMK__                  # __MMK__\n.ELSE                           # __MMK__\nALPHA_X_ALPHA = 1\nIA64_X_IA64 = 1\nVAX_X_VAX = 1\n.IFDEF $(MMS$ARCH_NAME)_X_ALPHA     # $(MMS$ARCH_NAME)_X_ALPHA\n__ALPHA__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_ALPHA\n.IFDEF $(MMS$ARCH_NAME)_X_IA64      # $(MMS$ARCH_NAME)_X_IA64\n__IA64__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_IA64\n.IFDEF $(MMS$ARCH_NAME)_X_VAX       # $(MMS$ARCH_NAME)_X_VAX\n__VAX__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_VAX\n.ENDIF                          # __MMK__\n\n.IFDEF __ALPHA__                # __ALPHA__\nDEST = ALPHA\n#E = .AXP_EXE\n#O = .AXP_OBJ\n#A = .AXP_OLB\n.ELSE                           # __ALPHA__\n.IFDEF __IA64__                     # __IA64__\nDEST = IA64\n#E = .I64_EXE\n#O = .I64_OBJ\n#A = .I64_OLB\n.ELSE                               # __IA64__\n.IFDEF __DECC__                         # __DECC__\nDEST = VAX\n#E = .VAX_DECC_EXE\n#O = .VAX_DECC_OBJ\n#A = .VAX_DECC_OLB\n.ENDIF                                  # __DECC__\n.IFDEF __FORCE_VAXC__                   # __FORCE_VAXC__\n__VAXC__ = 1\n.ENDIF                                  # __FORCE_VAXC__\n.IFDEF __VAXC__                         # __VAXC__\nDEST = VAXV\n#E = .VAX_VAXC_EXE\n#O = .VAX_VAXC_OBJ\n#A = .VAX_VAXC_OLB\n.ENDIF                                  # __VAXC__\n.IFDEF __GNUC__                         # __GNUC__\nDEST = VAXG\n#E = .VAX_GNUC_EXE\n#O = .VAX_GNUC_OBJ\n#A = .VAX_GNUC_OLB\n.ENDIF                                  # __GNUC__\n.ENDIF                              # __IA64__\n.ENDIF                          # __ALPHA__\n.IFDEF O                        # O\n.ELSE                           # O\n!If EXE and OBJ extensions aren't defined, define them\nE = .EXE\nO = .OBJ\nA = .OLB\n.ENDIF                          # O\n\n.IFDEF SRCDIR\n.ELSE\nSRCDIR = []\n.ENDIF\n.IFDEF DSTDIR                   # DSTDIR\n.ELSE                           # DSTDIR\n.IFDEF DEST                       # DEST\nDSTDIR = [.$(DEST)]\n.ELSE                             # DEST\nDSTDIR = []\n.ENDIF                            # DEST\n.ENDIF                          # DSTDIR\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!! USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!!!!!!\n! add any common optional preprocessor flags (macros) here\n! (do not forget a trailing comma!!):\nCOMMON_DEFS =\n!!!!!!!!!!!!!!!!!!!!!!!! END OF USER CUSTOMIZATION !!!!!!!!!!!!!!!!!!!!!!!!\n\n.IFDEF __GNUC__\nCC = gcc\nLIBS = ,GNU_CC:[000000]GCCLIB.OLB/LIB\n.ELSE\nCC = cc\nLIBS =\n.ENDIF\n\nCFLAGS = /NOLIST\n\nOPTFILE = sys$disk:[.vms]vaxcshr.opt\n\n.IFDEF __ALPHA__                # __ALPHA__\nCC_OPTIONS = /STANDARD=RELAX/PREFIX=ALL/ANSI/NAMES=(AS_IS)\nCC_DEFS =\n.ELSE                           # __ALPHA__\n.IFDEF __IA64__                     # __IA64__\nCC_OPTIONS = /STANDARD=RELAX/PREFIX=ALL/ANSI/NAMES=(AS_IS)\nCC_DEFS =\n.ELSE                               # __IA64__\n.IFDEF __DECC__                         # __DECC__\nCC_OPTIONS = /DECC/STANDARD=RELAX/PREFIX=ALL/NAMES=(AS_IS)\nCC_DEFS =\n.ELSE                                   # __DECC__\n.IFDEF __FORCE_VAXC__                       # __FORCE_VAXC__\n!Select VAXC on systems where DEC C exists\nCC_OPTIONS = /VAXC\n.ELSE                                       # __FORCE_VAXC__\n!No flag allowed/needed on a pure VAXC system\nCC_OPTIONS =\n.ENDIF                                      # __FORCE_VAXC__\nCC_DEFS =\n.ENDIF                                  # __DECC__\n.ENDIF                              # __IA64__\n.ENDIF                          # __ALPHA__\n\n!\n! The .FIRST target is needed only if we're serious about building,\n! and then, only if BZIP2 support was requested.\n!\n.IFDEF MMSTARGETS               # MMSTARGETS\n.FIRST\n\t@ write sys$output \"   Destination: $(DSTDIR)\"\n\t@ write sys$output \"\"\n\tif (\"$(DEST)\" .nes. \"\") then -\n\t if (f$search(\"$(DEST).DIR;1\") .eqs. \"\") then -\n\t  create /directory $(DSTDIR)\n.ENDIF                          # MMSTARGETS\nCC_DEFS2 =\nCFLAGS_INCL = /INCLUDE = []\n\n.IFDEF __DEBUG__\nCDEB = /DEBUG/NOOPTIMIZE\n.ELSE\nCDEB =\n.ENDIF\n\nCFLAGS_ALL  = $(CC_OPTIONS) $(CFLAGS) $(CDEB) $(CFLAGS_INCL) -\n              /def=($(CC_DEFS) $(COMMON_DEFS) BZ_NO_STDIO, VMS) -\n              $(CCOPTS)\n\n\nOBJBZ2LIB = \\\n $(DSTDIR)blocksort$(O), \\\n $(DSTDIR)huffman$(O), \\\n $(DSTDIR)crctable$(O), \\\n $(DSTDIR)randtable$(O), \\\n $(DSTDIR)compress$(O), \\\n $(DSTDIR)decompress$(O), \\\n $(DSTDIR)bzlib$(O)\n\nOLBBZ2 = $(DSTDIR)LIBBZ2_NS$(A)\n\nBZIP2_H = $(SRCDIR)bzlib.h $(SRCDIR)bzlib_private.h\n\n!!!!!!!!!!!!!!!!!!! override default rules: !!!!!!!!!!!!!!!!!!!\n.suffixes :\n.suffixes : .ANL $(E) $(A) .MLB .HLB .TLB .FLB $(O) -\n\t    .FORM .BLI .B32 .C .c .COB -\n\t    .FOR .BAS .B16 .PLI .PEN .PAS .MAC .MAR .M64 .CLD .MSG .COR .DBL -\n\t    .RPG .SCN .IFDL .RBA .RC .RCO .RFO .RPA .SC .SCO .SFO .SPA .SPL -\n\t    .SQLADA .SQLMOD .RGK .RGC .MEM .RNO .HLP .RNH .L32 .REQ .R32 -\n\t    .L16 .R16 .TXT .H .FRM .MMS .DDL .COM .DAT .OPT .CDO .SDML .ADF -\n\t    .GDF .LDF .MDF .RDF .TDF\n\n$(O)$(A) :\n\tIf \"''F$Search(\"$(MMS$TARGET)\")'\" .EQS. \"\" Then $(LIBR)/Create $(MMS$TARGET)\n\t$(LIBR)$(LIBRFLAGS) $(MMS$TARGET) $(MMS$SOURCE)\n\n.c$(O) :\n\t$(CC) $(CFLAGS_ALL) /OBJ=$(MMS$TARGET) $(MMS$SOURCE)\n\n!!!!!!!!!!!!!!!!!! here starts the bzip2 specific part !!!!!!!!!!!\n\nDEFAULT default :\tCHK_DESTDIR $(OLBBZ2)\n\t@\t!\tDo nothing.\n\nCLEAN.COM clean.com :\n\t@ open/write tmp $(MMS$TARGET)\n\t@ write tmp \"$!\"\n\t@ write tmp \"$!\tClean.com --\tprocedure to delete files. It always returns success\"\n\t@ write tmp \"$!\t\t\tstatus despite any error or warnings. Also it extracts\"\n\t@ write tmp \"$!\t\t\tfilename from MMS \"\"module=file\"\" format.\"\n\t@ write tmp \"$!\"\n\t@ write tmp \"$ on control_y then goto ctly\"\n\t@ write tmp \"$ if p1.eqs.\"\"\"\" then exit 1\"\n\t@ write tmp \"$ i = -1\"\n\t@ write tmp \"$scan_list:\"\n\t@ write tmp \"$\ti = i+1\"\n\t@ write tmp \"$\titem = f$elem(i,\"\",\"\",p1)\"\n\t@ write tmp \"$\tif item.eqs.\"\"\"\" then goto scan_list\"\n\t@ write tmp \"$\tif item.eqs.\"\",\"\" then goto done\t\t! End of list\"\n\t@ write tmp \"$\titem = f$edit(item,\"\"trim\"\")\t\t! Clean of blanks\"\n\t@ write tmp \"$\twild = f$elem(1,\"\"=\"\",item)\"\n\t@ write tmp \"$\tshow sym wild\"\n\t@ write tmp \"$\tif wild.eqs.\"\"=\"\" then wild = f$elem(0,\"\"=\"\",item)\"\n\t@ write tmp \"$\tvers = f$parse(wild,,,\"\"version\"\",\"\"syntax_only\"\")\"\n\t@ write tmp \"$\tif vers.eqs.\"\";\"\" then wild = wild - \"\";\"\" + \"\";*\"\"\"\n\t@ write tmp \"$scan:\"\n\t@ write tmp \"$\t\tf = f$search(wild)\"\n\t@ write tmp \"$\t\tif f.eqs.\"\"\"\" then goto scan_list\"\n\t@ write tmp \"$\t\ton error then goto err\"\n\t@ write tmp \"$\t\ton warning then goto warn\"\n\t@ write tmp \"$\t\tdelete/log 'f'\"\n\t@ write tmp \"$warn:\"\n\t@ write tmp \"$err:\"\n\t@ write tmp \"$\t\tgoto scan\"\n\t@ write tmp \"$done:\"\n\t@ write tmp \"$ctly:\"\n\t@ write tmp \"$\texit 1\"\n\t@ close tmp\n\nCLEAN clean : clean.com\n\t@clean \"$(OBJBZ2LIB)\"\n\t@clean \"$(OLBBZ2)\"\n\t@- delete/noconfirm/nolog clean.com;*\n        @- if (\"$(DEST).dir\" .nes. \"\") then -\n\t   if (f$search(\"$(DEST).dir\") .nes. \"\") then -\n\t    set protect=w:d $(DEST).dir;*\n        @- if (\"$(DEST).dir\" .nes. \"\") then -\n\t   if (f$search(\"$(DEST).dir\") .nes. \"\") then -\n\t    delete/noconfirm $(DEST).dir;*\n\nCHK_DESTDIR chk_destdir :\n\t@ If (\"$(DEST)\" .NES. \"\") Then -\n\t   If \"''F$Search(\"$(DEST).DIR;1\")'\" .EQS. \"\" Then -\n\t    Create /directory $(DSTDIR)\n\n$(OLBBZ2)\t: $(OBJBZ2LIB)\n\tIf \"''F$Search(\"$(MMS$TARGET)\")'\" .EQS. \"\" Then $(LIBR)/Create $(MMS$TARGET)\n\t$(LIBR)$(LIBRFLAGS) $(MMS$TARGET) $(MMS$CHANGED_LIST)\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(OBJBZ2LIB)\t: $(BZIP2_H)\n\n$(DSTDIR)blocksort$(O)\t: $(SRCDIR)blocksort.c\n$(DSTDIR)huffman$(O)\t: $(SRCDIR)huffman.c\n$(DSTDIR)crctable$(O)\t: $(SRCDIR)crctable.c\n$(DSTDIR)randtable$(O)\t: $(SRCDIR)randtable.c\n$(DSTDIR)compress$(O)\t: $(SRCDIR)compress.c\n$(DSTDIR)decompress$(O)\t: $(SRCDIR)decompress.c\n$(DSTDIR)bzlib$(O)\t: $(SRCDIR)bzlib.c\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/makbz2iz.msc",
    "content": "# Makefile for UnZip's bzip2 support library\n# Win32 port, using Microsoft Visual C++ 6.0\n#\n# (c) 2006-2007 Info-ZIP\n# Last revision: Christian Spieler, 2007-Apr-03\n#\n# This Makefile is intended to be called from UnZip's main make procedure.\n\nCC=cl\nAR=link -lib\nCFLSYS = -ML -O2 -nologo\nCFLAGS= -D_WIN32 -DBZ_NO_STDIO $(CFLSYS)\n!ifndef BZROOTDIR\nBZROOTDIR=.\n!endif\nBZROOT=$(BZROOTDIR)/\n!ifndef BZOBDIR\nBZOBDIR=.\n!endif\nBZOB=$(BZOBDIR)/\nO=.obj\n\n\nOBJS= $(BZOB)blocksort$(O)  \\\n      $(BZOB)huffman$(O)    \\\n      $(BZOB)crctable$(O)   \\\n      $(BZOB)randtable$(O)  \\\n      $(BZOB)compress$(O)   \\\n      $(BZOB)decompress$(O) \\\n      $(BZOB)bzlib$(O)\n\nizlib: $(BZOBDIR) $(BZOB)bz2.lib\n\n$(BZOBDIR) :\n\t-mkdir $@\n\n$(BZOB)bz2.lib: $(OBJS)\n\t$(AR) $(OBJS) -out:$(BZOB)bz2.lib\n\nclean:\n\t-del $(BZOBDIR)\\*$(O)\n\t-del $(BZOBDIR)\\bz2.lib\n\n.c$(O):\n\t$(CC) $(CFLAGS) -c -Fo$@ $<\n\n$(OBJS) : $(BZROOT)bzlib.h $(BZROOT)bzlib_private.h\n\n$(BZOB)blocksort$(O) : $(BZROOT)blocksort.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)blocksort.c\n$(BZOB)huffman$(O) : $(BZROOT)huffman.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)huffman.c\n$(BZOB)crctable$(O) : $(BZROOT)crctable.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)crctable.c\n$(BZOB)randtable$(O) : $(BZROOT)randtable.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)randtable.c\n$(BZOB)compress$(O) : $(BZROOT)compress.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)compress.c\n$(BZOB)decompress$(O) : $(BZROOT)decompress.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)decompress.c\n$(BZOB)bzlib$(O) : $(BZROOT)bzlib.c\n\t$(CC) $(CFLAGS) -c -Fo$@ $(BZROOT)bzlib.c\n"
  },
  {
    "path": "deps/infozip/unzip60/bzip2/makbz2iz.wat",
    "content": "# Makefile for UnZip's bzip2 support library\n# MSDOS & Win32 ports, using OpenWatcom C++\n#\n# (c) 2006-2007 Info-ZIP\n# Last revision: Christian Spieler, 2007-Apr-03\n#\n# This Makefile is intended to be called from UnZip's main make procedure.\n\nCC=wcc386\nAR=lib386\nCFLSYS = -6r -zt -zq -wx -s -obhikl+rt -oe100 -zp8 -q\nCFLAGS= $(CFLSYS) -DBZ_NO_STDIO\n!ifndef BZROOTDIR\nBZROOTDIR=.\n!endif\nBZROOT=$(BZROOTDIR)\\\n!ifndef BZOBDIR\nBZOBDIR=.\n!endif\nBZOB=$(BZOBDIR)/\nO=.obj\n\n\nOBJS= $(BZOB)blocksort$(O)  &\n      $(BZOB)huffman$(O)    &\n      $(BZOB)crctable$(O)   &\n      $(BZOB)randtable$(O)  &\n      $(BZOB)compress$(O)   &\n      $(BZOB)decompress$(O) &\n      $(BZOB)bzlib$(O)\n\nizlib: $(BZOBDIR) $(BZOB)bz2.lib\n\n$(BZOBDIR) :\n\t-mkdir $@\n\n$(BZOB)bz2.lib: $(OBJS)\n\t$(AR) -nologo $(OBJS) -out:$(BZOB)bz2.lib\n\nclean:  .SYMBOLIC\n\t-del $(BZOBDIR)\\*$(O)\n\t-del $(BZOBDIR)\\bz2.lib\n\n.c$(O):\n\t$(CC) $(CFLAGS) -fo=$@ $<\n\n$(OBJS) : $(BZROOT)bzlib.h $(BZROOT)bzlib_private.h\n\n$(BZOB)blocksort$(O) : $(BZROOT)blocksort.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)blocksort.c\n$(BZOB)huffman$(O) : $(BZROOT)huffman.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)huffman.c\n$(BZOB)crctable$(O) : $(BZROOT)crctable.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)crctable.c\n$(BZOB)randtable$(O) : $(BZROOT)randtable.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)randtable.c\n$(BZOB)compress$(O) : $(BZROOT)compress.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)compress.c\n$(BZOB)decompress$(O) : $(BZROOT)decompress.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)decompress.c\n$(BZOB)bzlib$(O) : $(BZROOT)bzlib.c\n\t$(CC) $(CFLAGS) -Fo=$@ $(BZROOT)bzlib.c\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/INSTALL.CMS",
    "content": "-----------------------------------------------------------------------\n[Installation notes for VM/CMS port of UNZIP 5.32 and ZIP 2.2]\nAdditional notes from Ian E. Gorman (4/98):\n\nI have not fully tested ZIP and UNZIP in VM (for example, I have not\ntried all the options), so ZIP 2.2 for VM and UNZIP 5.32 for VM\nshould be regarded as beta versions.  Try them out before you decide\nthat you can depend on them.\n\nMost of the work for the VM port has been done by others, but I have\nmade some changes and compiled on a more recent version of VM/CMS.  It\nis possible that I have introduced new problems or undone some of the\nsolutions found by previous authors.\n\n\nInstallation\n============\n\nThe executables are stored in CMS \"PACK\" format instead of being\nstored in ZIP archives.  This format takes a little longer to\ndownload, but installation is slightly simpler.\n\n\nInstalling UNZIP\n----------------\n\nThe UNZIP executable is supplied as the binary file UNZIP.MOD, in the\nCMS \"PACK\" format.\n\nYou must get the UNZIP.MOD file on to your system as a binary file in\nfixed recording mode, block size 1024.\n\nIf you are using FTP in CMS, you can get the file in the correct\nformat with the LOCSITE and BINARY commands.  Assuming that the UNZIP\nexecutable is stored on the remote site as unz532vm.mod, you could\nissue the following commands\n\n    FTP where.ever.com\n    <enter user id and password and other stuff>\n    BINARY\n    LOCSITE FIX 1024\n    GET unz532vm.mod\n    QUIT\n\nIf you are using a 3270 terminal session to upload from a PC, you can\nupload the file in the correct format with the SEND command:\n\n    SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024\n\nIf your 3270 emulator does not have the SEND command, but is a GUI\napplication, it may allow you to upload from the menu bar.  If so,\nset your options to binary, VM/CMS, fixed record length, and a length\nof 1024 before you upload.\n\nWhen you get the PACKed file on your CMS minidisk, you convert it to\nan executable module by using the COPY command with the UNPACK option:\n\n    COPY unz532vm mod a unzip module a1 (UNPACK OLDDATE REPLACE\n\nYou can omit the OLDDATE and REPLACE options if you want to.\n\n\nInstalling ZIP\n--------------\n\nThe ZIP executable is supplied as the binary file ZIP.MOD, in the CMS\n\"PACK\" format.\n\nYou must get the ZIP.MOD file on to your system as a binary file in\nfixed recording mode, block size 1024.  Assuming that the file is\nstored as zip22vm.mod, you can get the file the same way you got the\nUNZIP.MOD file:\n\n    Using FTP:\n\n        FTP where.ever.com\n        <enter user id and password and other stuff>\n        BINARY\n        LOCSITE FIX 1024\n        GET zip22vm.mod\n        QUIT\n\n    Using 3270 file transfer:\n\n        SEND unz532vm.mod A: unz532vm mod a1 (RECFM F LRECL 1024\n\nWhen you get the PACKed file on your CMS minidisk, you convert it to\nan executable module by using the COPY command with the UNPACK option:\n\n    COPY zip22vm mod a zip module a1 (UNPACK OLDDATE REPLACE\n\n\nInstalling Documentation\n------------------------\n\nOnce you have UNZIP running, you can use it to extract documentation\nfrom ZIP archives.\n\nYou can transfer the ZIP archives to VMV/CMS as a binary file with any\nrecord length.  A record length of 1 will work fine:\n\n    via FTP:\n\n        FTP where.ever.com\n        <enter user id and password and other stuff>\n        BINARY\n        LOCSITE FIX 1\n        GET zip22vm.zip zipdoc.zip\n        GET unz532vm.zip unzipdoc.zip\n        QUIT\n\n    via 3270 session:\n\n        SEND zip22vm.zip A: unzipdoc zip a1 (RECFM F LRECL 1\n        SEND unz532vm.zip A: zipdoc zip a1 (RECFM F LRECL 1\n\nOnce you have the ZIP archives, extract the documentation to the minidisk of\nyour choice by using the -d option:\n\n    unzip -a -d A2 unzipdoc.zip\n    unzip -a -d A2 zipdoc.zip\n\nThe \"-a\" option is required because the documents are archived as\nASCII text files, but they must be converted to EBCDIC to read them\nin VM/CMS.\n\n\nNotes\n=====\n\nDifferent EBCDIC Character Sets\n-------------------------------\n\nThe documentation may look strange on your system, because UNZIP\ntranslates from ASCII to \"Open Systems\" EBCDIC (IBM-1047).  Unless\nyou are a software developer, you are probably using a different\nkind of EBCDIC (like US EBCDIC, IBM-037).  This causes some character\ncodes to display as different characters.  For example, the character\ncodes that display as square brackets in IBM-1047 will display as\ne-acute and a-grave in IBM-037.\n\nYou can use the IBM ICONV utility to translate documents from one\ncharacter set to another:\n\n    ICONV old doc a new doc a1 (FROMCODE IBM-1047 TOCODE IBM-037\n\n\nIND$FILE protocol\n-----------------\n\nThis is the method by which files are transferred via 3270 sessions\nbetween PC and mainframe.\n\nIf you know how to transfer files via 3270 session between PC and\nmainframe, you know as much as you need to know about IND$FILE.\n\nIf your mainframe has IND$FILE, and your 3270 emulator does file\ntransfers, you can use your emulator to transfer files between PC\nand mainframe.\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/README.CMS",
    "content": "Using ZIP and UNZIP on VM/CMS\n=============================\n\n\nInstalling executables\n----------------------\n\nThe following CMS MODULEs are available:\n   ZIP\n   ZIPNOTE\n   ZIPCLOAK\n   ZIPSPLIT\n   UNZIP\n\nIn addition to these, each MODULE file also has an EXEC with the same\nname.  These EXECs are front-ends to the MODULES that will attempt to\nset up the required runtime libraries before running the MODULE.\nAll the EXECs are identical.  Only their names are different.\nThey are stored as plain text files.\n\nThe CMS MODULE files have been packed using the COPYFILE command to\nallow their file format to be properly restored, since variable length\nbinary files will not currently unzip properly (see below for details).\nThe MODULEs are shipped with a filetype or extension of CMO (for CMS\nMODULE).  Their names may vary on the distribution disk to indicate\ntheir level, etc.\n\nTo restore them to executable MODULEs on CMS, do the following:\n   1. Upload them to CMS with a Fixed record length with LRECL 1024.\n      Example, from a DOS or OS/2 window, type this:\n         SEND unzip.cmo A:unzip module a (RECFM F LRECL 1024\n\n      Example, using FTP from CMS, type this:\n         BINARY FIXED 1024\n         GET unzip.cmo unzip.module.a\n\n      Note:  Replace \"unzip.cmo\" with the actual name.\n\n   2. Use COPYFILE to unpack the file.\n      Example, in CMS type this:\n         COPYFILE UNZIP MODULE A (UNPACK REPLACE OLDDATE\n\n   3. Repeat steps 1-2 for each of the programs.\n\n   4. Build the ZIPINFO module by typing this:\n         COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE\n\n   5. Upload the EXECs to CMS as text files (with ASCII-to-EBCDIC\n      translation).\n      Example, from a DOS or OS/2 window, type this:\n         SEND unzip.exc A:unzip exec a (CRLF\n\n      Example, using FTP from CMS, type this:\n         GET unzip.exc unzip.exec.a\n\n   6. Repeat steps 4 for each of the EXECs.\n\n\nPreparing the environment\n-------------------------\n\nThe executables provided were compiled with IBM C 3.1.0 and\nrequire the the Language Environment (LE) runtime libraries.\n\nTo provide access to the runtime libraries:\n   1. Link to the disk containing the Language Environment files,\n      if necessary.\n\n   2. Use the command \"GLOBAL LOADLIB SCEERUN\"\n\n   These commands can be placed in your PROFILE EXEC.\n\n   Note:  EXECs have been provided called ZIP, UNZIP, etc. that\n   issue the GLOBAL LOADLIB statement.  This was done to alleviate\n   frustration of users that don't have the GLOBAL LOADLIB statement\n   in their PROFILE EXEC.  These EXECs may require changing for\n   your system.\n\n   Unfortunately, there is no way, using IBM C, to produce a MODULE\n   that doesn't require a runtime library.\n\n\nTesting\n-------\n\nTo test the MODULEs, just type ZIP or UNZIP.  They should\nshow help information on using the commands.\n\nIf you see something like this:\n   DMSLIO201W The following names are undefined:\n    CEEEV003\n   DMSABE155T User abend 4093 called from 00DCD298 reason code 000003EB\n\nThen you don't have access to the proper runtime libraries, as\ndescribed above.\n\nHere is additional information on the ZIP and UNZIP programs that\nmay assist support personnel:\n   - Compiled with IBM C V3R1M0 on VM/ESA 2.2.0 with\n     CMS level 13 Service Level 702.\n\n   - Require the SCEERUN LOADLIB runtime library.  This is\n     part of the Language Environment (LE).\n\n   - Linked with options RMODE ANY AMODE ANY RLDSAVE.\n\nIf you continue to have trouble, report the problem to Zip-Bugs\n(see the bottom of this document).\n\n\n\nCompiling the source on VM/CMS\n------------------------------\n\nThe source has been successfully compiled previously using\nC/370 2.1 and 2.2.  The source has been recently compiled using\nIBM C 3.1.0 on VM/ESA 2.2.0 with CMS level 13.  I don't have\naccess to an MVS system so the code hasn't been tested there\nin a while.\n\n 1. Unzip the source files required for CMS.  The root-level files\n    inside the ZIP file and the files in the CMSMVS subdirectory are\n    needed.  Example (use both commands):\n       unzip -aj zip23.zip -x */*   -dc\n       unzip -aj zip23.zip cmsmvs/* -dc\n\n    This example unzips the files to the C-disk, while translating\n    character data and ignoring paths.\n\n    If you don't already have a working UNZIP MODULE on CMS you will\n    have to unzip the files on another system and transport them\n    to CMS.  All the required files are plain text so they can\n    be transferred with ASCII-to-EBCDIC translations.\n\n 2. Repeat step 1 with the zip file containing the UNZIP code.\n    Unzip the files to a different disk than the disk used for the ZIP\n    code.\n\n 3. To compile the ZIP code, run the supplied CCZIP EXEC.\n    To compile the UNZIP code, run the supplied CCUNZIP EXEC.\n\nNOTE:\nSome of the ZIP and UNZIP source files have the same name.  It is\nrecommended that you keep the source from each on separate disks and\nmove the disk you are building from ahead of the other in the search\norder.\n\nFor example, you may have a 192 disk with the ZIP source code and\na 193 disk with the UNZIP source code.  To compile ZIP, access\nthe 192 disk as B, then run CCZIP.  This will create the following\nmodules:  ZIP, ZIPNOTE, ZIPSPLIT, ZIPCLOAK.\n\nTo compile UNZIP, access 193 as B, then run CCUNZIP.  This will create\nthe following modules:  UNZIP, ZIPINFO (a copy of UNZIP).\n\n\n=========================================================================\n\n\nUsing ZIP/UNZIP\n---------------\n\nDocumentation for the commands is in MANUAL NONAME (for ZIP) and in\nUNZIP DOC UNZIP.  INFOZIP DOC describes the use of the -Z option of\nUNZIP.\n\nThe rest of this section explains special notes concerning the VM/CMS\nversion of ZIP and UNZIP.\n\n\nFilenames and directories\n-------------------------\n\n 1. Specifying filenames\n\n    a. When specifying CMS files, use filename.filetype.filemode format\n       (separate the three parts of the name with a period and use no\n       spaces).  Example:  profile.exec.a\n\n       Unfortunately, this prevents you from using ZIP from\n       FILELIST.  To unzip a zip file, however, you can type something\n       like this next to it in FILELIST:\n          unzip /n -d c\n\n       This will unzip the contents of the current file to a C-disk.\n\n    b. It is possible to use DD names with ZIP and UNZIP on CMS, though\n       it can be cumbersome.  Example:\n          filedef out disk myzip zip a\n          zip dd:out file1.txt file2.txt\n\n       While you can also use a DD name for the input files, ZIP\n       currently does not correctly resolve the filename and will\n       store something like \"dd:in\" inside the ZIP file.  A file stored\n       in this manor cannot easily be unzipped, as \"dd:in\" is an invalid\n       filename.\n\n    c. In places where a directory name would be used on a PC, such as\n       for the ZIP -b (work path) option or the UNZIP -d (destination\n       path) options, use a filemode letter for CMS.  For example,\n       to unzip files onto a C-disk, you might type something like this:\n          unzip myzip.zip -d c\n\n       Currently, ZIP uses the A-disk for work files.  When zipping\n       large files, you may want to specify a larger disk for work files.\n       This example will use a C-disk for work files.\n          zip -b C myzip.zip.c test.dat.a\n\n\n 2. Filename conversions\n\n    a. Filemode letters are never stored into the zip file or take from\n       a zip file.  Only the filename and filetype are used.\n       ZIP removes the filemode when storing the filename into the\n       zip file.  UNZIP assumes \"A\" for the filemode unless the -d\n       option is used.\n\n    b. When unzipping, any path names are removed from the fileid\n       and the last two period-separated words are used as the\n       filename and filetype.  These are truncated to a maximum of\n       eight characters, if necessary.  If the filetype (extension)\n       is missing, then UNZIP uses \"NONAME\" for the filetype.\n       Any '(' or ')' characters are removed from the fileid.\n\n    c. All files are created in upper-case.  Files in mixed-case\n       cannot currently be stored into a ZIP file.\n\n    d. Shared File System (SFS) directories are not supported.\n       Files are always accessed by fn.ft.fm.  To use an SFS disk,\n       Assign it a filemode, then it can be used.\n\n\n 3. Wildcards in file names\n\n    a. Wildcards are not supported in the zip filename.  The full\n       filename of the zip file must be given (but the .zip is not\n       necessary).  So, you can't do this:\n          unzip -t *.zip\n\n    b. Wildcards CAN be used with UNZIP to select (or exclude) files\n       inside a zip file.  Examples:\n          unzip myzip *.c          - Unzip all .c files.\n          unzip myzip *.c -x z*.c  - Unzip all .c files but those\n                                     starting with Z.\n\n    c. Wildcards cannot currently be used to select files with ZIP.\n       So, you can't do this:\n          zip -a myzip *.exec\n\n       I expect to fix this for CMS in the future.\n\n\n 4. File timestamps\n\n    a. The dates and times of files being zipped or unzipped are not\n       currently read or set.  When a file is zipped, the timestamp\n       inside the zip file will always be the current system date and\n       time.  Likewise, when unzipping, the date and time of files\n       being unzipped will always be the current system date/time.\n\n    b. Existing files are assumed to be newer than files inside a zip\n       file when using the -f freshen option of UNZIP.  This will prevent\n       overwriting files that may be newer than the files inside the\n       zip file, but also effectively prevents the -f option from working.\n\n\n 5. ASCII, EBCDIC, and binary data\n\n    Background\n    ----------\n    Most systems create data files as just a stream of bytes.  Record\n    breaks happen when certain characters (new line and/or carriage\n    return characters) are encountered in the data.  How to interpret\n    the data in a file is up to the user.  The system must be told\n    to either notice new line characters in the data or to assume\n    that the data in the file is binary data and should be read or\n    written as-is.\n\n    CMS and MVS are record-based systems.  All files are composed\n    of data records.  These can be stored in fixed-length files or\n    in variable length files.  With fixed-length files, each record\n    is the same length.  The record breaks are implied by the\n    LRECL (logical record length) attribute associated with the file.\n    With variable-length files, each record contains the length of\n    that record.  The separation of records are not part of the\n    data, but part of the file structure.\n\n    This means you can store any type of data in either type of file\n    structure without having to worry about the data being interpreted\n    as a record break.  Fixed-length files may have padding at the\n    end of the file to make up a full record.  Variable-length files\n    have no padding, but require extra record length data be stored\n    with the file data.\n\n    Storing fixed-length files into a zip file is simple, because all\n    the data can just be dumped into the zip file and the record\n    format (RECFM) and logical record length (LRECL) can be stored\n    in the extra data area of the zip file so they can be restored\n    when UNZIP is used.\n\n    Storing variable-length data is harder.  There is no place to put\n    the record length data needed for each record of the file.  This\n    data could be written to the zip file as the first two bytes of\n    each record and interpreted that way by UNZIP.  That would make\n    the data unusable on systems other than CMS and MVS, though.\n\n    Currently, there isn't a solution to this problem.  Each record is\n    written to the zip file and the record length information is\n    discarded.  Binary data stored in variable-length files can't be put\n    into a zip file then later unzipped back into the proper records.\n    This is fine for binary data that will be read as a stream of bytes\n    but not OK where the records matter, such as with CMS MODULEs.\n\n    If the data is text (character data), there is a solution.\n    This data can be converted into ASCII when it's stored into\n    a zip file.  The end of each record is now marked in the file\n    by new line characters.  Another advantage of this method is\n    that the data is now accessible to non-EBCDIC systems.  When\n    the data is unzipped on CMS or MVS, it is converted back into\n    EBCDIC and the records are recreated into a variable-length file.\n\n\n    So, here's what we have...\n\n    a. To store readable text data into a zip file that can be used\n       on other platforms, use the -a option with ZIP to convert the\n       data to ASCII.  These files will unzip into variable-length\n       files on CMS and should not contain binary data or corruption\n       may occur.\n\n    b. Files that were zipped on an ASCII-based system will be\n       automatically translated to EBCDIC when unzipped.  To prevent\n       this (to unzip binary data on CMS that was sent from an\n       ASCII-based system), use the -B option with UNZIP to force Binary\n       mode.  To zip binary files on CMS, use the -B option with ZIP to\n       force Binary mode.  This will prevent any data conversions from\n       taking place.\n\n    c. When using the ZIP program without specifying the \"-a\" or \"-B\"\n       option, ZIP defaults to \"native\" (EBCDIC) mode and tries to\n       preserve the file information (RECFM, LRECL, and BLKSIZE).  So\n       when you unzip a file zipped with ZIP under CMS or MVS, UNZIP\n       restores the file info.  The output will be fixed-length if the\n       original was fixed and variable-length if the original was\n       variable.\n\n    If UNZIP gives a \"write error (disk full?)\"  message, you may be\n    trying to unzip a binary file that was zipped as a text file\n    (without using the -B option)\n\n\n    Summary\n    -------\n    Here's how to ZIP the different types of files.\n\n    RECFM F text\n       Use the -a option with ZIP to convert to ASCII for use with other\n       platforms or no options for use on EBCDIC systems only.\n\n    RECFM V text\n       Use the -a option with ZIP to convert to ASCII for use with other\n       platforms or no options for use on EBCDIC systems only.\n\n\n    RECFM F binary\n       Use the -B option with ZIP (upper-case \"B\").\n\n    RECFM V binary\n       Use the -B option with ZIP.  Can be zipped OK but the record\n       structure is destroyed when unzipped.  This is OK for data files\n       read as binary streams but not OK for files such as CMS MODULEs.\n\n\n 6. Character Sets\n\n    If you are used to running UNZIP on systems like UNIX, DOS, OS/2 or\n    Windows, you will may have some problems with differences in the\n    character set.\n\n    There are a number of different EBCDIC code pages, like there are a\n    number of different ASCII code pages.  For example, there is a US\n    EBCDIC, a German EBCDIC, and a Swedish EBCDIC.  As long as you are\n    working with other people who use the same EBCDIC code page, you\n    will have no trouble.  If you work with people who use ASCII, or who\n    use a different EBCDIC code page, you may need to do some\n    translation.\n\n    UNZIP translates ASCII text files to and from Open Systems EBCDIC\n    (IBM-1047), which may not be the EBCDIC that you are using.  For\n    example, US EBCDIC (IBM-037) uses different character codes for\n    square brackets.  In such cases, you can use the ICONV utility\n    (supplied with IBM C) to translate between your EBCDIC character set\n    and IBM-1047.\n\n    If your installation does not use IBM-1047 EBCDIC, messages from\n    UNZIP may look a little odd.  For example, in a US EBCDIC\n    installation, an opening square bracket will become an i-acute and a\n    closing square bracket will become a u-grave.\n\n    The supplied ZIP and UNZIP EXECs attempt to correct this by setting\n    CMS INPUT and OUTPUT translations to adjust the display of left and\n    right brackets.  You may need to change this if brackets don't\n    display correctly on your system.\n\n\n 7. You can unzip using VM/CMS PIPELINES so unzip can be used as\n    a pipeline filter.  Example:\n       'PIPE COMMAND UNZIP -p test.zip george.test | Count Lines | Cons'\n\n\n\n\nPlease report all bugs and problems to:\n   Zip-Bugs@lists.wku.edu\n\n\n-----------------------------------------------------------------------\nOriginal CMS/MVS port by George Petrov.\ne-mail:  c888090@nlevdpsb.snads.philips.nl\ntel:     +31-40-781155\n\nPhilips C&P\nEindhoven\nThe Netherlands\n\n-----------------------------------------------------------------------\nAdditional fixes and README re-write (4/98) by Greg Hartwig.\ne-mail:  ghartwig@ix.netcom.com\n         ghartwig@vnet.ibm.com\n\n-----------------------------------------------------------------------\nAdditional notes from Ian E. Gorman.\ne-mail:  ian@iosphere.net\n\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/README.MVS",
    "content": "Thank you for trying this port of UNZIP for VM/CMS and MVS!\n\n                        Using under MVS:\n                    -------------------------\n\n1. To use the Info-ZIP's UNZIP under MVS you need:\n\n   - C/370 ver 2.1 compiler or another compatible compiler supporting\n     long names for function/variable names.\n\n2. To compile the program under MVS do :\n\n   - unzip all the files from unz54vm.zip file. They are stored as\n     ASCII format so you have to unzip them first on PC or other\n     system that already have UNZIP, and then upload them to the\n     mainframe with ASCII to EBCDIC conversion.\n\n   - Copy all the .C files in the PDS called USERID.UNZIP.C\n\n   - Copy all the .H files in the PDS called USERID.UNZIP.H\n\n   - adjust the job UNZMVSC.JOB to work on your site. Change USERID\n     to your userid.  You might need to change the CEE dataset names\n     to match your OS/390 system.\n\n   - Preallocate PDS datasets named: USERID.UNZIP.OBJ and\n     USERID.UNZIP.LOAD\n\n   - execute the job UNZMVSC to compile and link all the sources.\n\n   - if everything is ok you will get an UNZIP MODULE\n\n3. Using UNZIP\n\n   - Just read the UNZIP.TXT\n\n   - A few exceptions concerning MVS\n\n     3.0. There are different ways to invoke UNZIP.\n\n        - allocating UNZIP.LOAD dataset to your ISPLLIB if you\n          want to invoke UNZIP under ISPF.\n          Then just type UNZIP ...parms... to get it work\n\n        - You can also call it directly with :\n             TSO CALL 'userid.UNZIP.LOAD(UNZIP)' '...parms...'\n             (notice to quotes!)\n\n        - You can even call it from a batch job like:\n\n          //MYZIP    JOB  (account)\n          //STEP1    EXEC PGM=UNZIP,PARM='-l mytestz.zip *.c'\n          //STEPLIB  DD DSN=userid.UNZIP.LOAD,DISP=SHR\n          //SYSPRINT DD SYSOUT=*\n\n          This will list all the .c files from the zip file mytestz.zip\n\n     3.1. If the ZIP file has been zipped on an ASCII based system\n          it will be automatically translated to EBCDIC\n          ( I hope I got all those translation tables OK :-).\n          You can force ASCII to EBCDIC conversion with the -a flag.\n\n     3.2. The date/time of the output files is set to the\n          current system date/time - not according the date/time in\n          the zip file.\n\n     3.3. You can even unzip using TSO/E PIPELINES\n          so unzip can be used as pipeline filter:\n\n          'pipe cms unzip -p test.zip george.test | count lines | cons'\n          ( we do also a lot of pipethinking here ;-)\n\n     3.4. If you got also the ZIP program (see ZIP21VM.ZIP) you can\n          do zipping and unzipping without translating to ASCII\n          the ZIP also preserves the file informations (LRECL,BLKSIZE..)\n          So when you UNZIP a file zipped with ZIP under MVS it\n          restores the file info.\n\n          There currently some problems with file with RECFM=V*\n          I don't save the length of each record yet :-)\n\n     3.5. No wildcards are supported in the input zip name you have\n          to give the real name (.zip is not necessary)\n\n          So you CAN'T use things like: unzip -t *.zip\n\n     3.6. But you CAN use wildcards as filename selection like:\n          unzip -t myzip *.c  - OK or even\n          unzip -t myzip *.c -x z*.c  - to exclude all files matching\n                                        z*.c\n\n     3.7. You can unzip to a PDS using the -d parameter,\n          for example:\n\n           unzip -dmyzip myzip *.c\n\n          This will unzip all .c files that are in the zip file in a\n          PDS directory called MYZIP.C\n\n          BE AWARE that the extension of every files is being placed as\n          last identifier on the PDS name, so if you have a file in the\n          zipfile called 'testp.doc' and you use '-d mypds' the PDS\n          name will become 'mypds.doc(testp)'\n\n          Depending on which options IBM chose for C this week, unzip\n          may or may not prefix output files with your userid and/or\n          TSO prefix.  To prevent this, quote the filename to -d, for\n          example\n\n                //UNZIP   EXEC PGM=UNZIP,\n                // PARM='/-a -o ''userid.zip'' -d ''hlq.test'' *'\n                //STEPLIB  DD  DSN=USERID.UNZIP.LOAD,DISP=SHR\n                //SYSPRINT DD  SYSOUT=*\n                //SYSOUT   DD  SYSOUT=*\n\n          The above JCL converts from ASCII to EBCDIC (-a), always\n          overwrites existing members (-o), extracts from 'userid.zip',\n          writes to files starting with 'hlq.test', all members (*).\n          Note the double quotes because PARM= requires single quotes.\n\n     3.8. The rules for output DCBs are a little messy.  If the output\n          file already exists (remember the -d option) then unzip uses\n          the existing DCB and space values.\n\n          If the output file does not exist and the input zip came from\n          MVS then unzip makes its best attempt at preserving the\n          original DCB.  However there is not enough information stored\n          in the zip file to do this correctly for all file types, some\n          file types may be corrupted.\n\n          If the output file does not exist and the input zip does not\n          contain MVS DCB information then unzip uses RECFM=U,\n          LRECL=32760 for binary data, RECFM=V, LRECL=133 for text.\n          Text includes ASCII to EBCDIC conversion.  As soon as the\n          output file is created, unzip uses the same output DCB for\n          all following members, even if the input is a mixture of text\n          and binary.\n\n          In all cases, unzip has no built in parameters for space.\n          For a preallocated file this is not a problem.  If unzip\n          creates an output file you get a default space allocation\n          which is site dependent.\n\n          It is far better to preallocate the output files with the\n          correct space and DCB values then use the -d option to point\n          to those files.\n\n     3.9. All '+','_' or '-' signs are skipped from the filenames\n\n\nPlease repport all bugs and problems to :\n     Zip-Bugs@lists.wku.edu\n\nThat's all for now.\n\nHave fun!\n\n\nGeorge Petrov\ne-mail: c888090@nlevdpsb.snads.philips.nl\ntel: +31-40-781155\n\nPhilips C&P\nEindhoven\nThe Netherlands\n\nUpdated by:\n\nKeith Owens <kaos@ocs.com.au>\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/WHATSNEW.CMS",
    "content": "Important Changes made for ZIP 2.3b and UNZIP 5.33c executables:\n\n1. WARNING:  These executables have been compiled for the\n   Language Environment (LE).  You must now have access to the file\n   SCEERUN LOADLIB in order to run ZIP and UNZIP on CMS.  You no longer\n   need access to EDCLINK LOADLIB.  The provided ZIP and UNZIP EXECs\n   have been changed to issue a new GLOBAL LOADLIB command.  You may\n   need to modify these EXECs for your installation.  You may want to\n   change any GLOBAL LOADLIB command you may have in your PROFILE EXEC.\n\n   Versions could be made available for the older EDCLINK LOADLIB\n   runtimes upon request.\n\n2. ZIP files will now be variable length files rather than fixed\n   length files.\n\n3. Help information for ZIP and UNZIP has been changed to show\n   \"fm\" rather than \"path\" on CMS with certain options.\n\n4. README CMS has been entirely rewritten.  It now contains all\n   information for ZIP and UNZIP.\n\n-----------------------------------------------------------------------\nGreg Hartwig, April 1998.\ne-mail:  ghartwig@ix.netcom.com\n         ghartwig@vnet.ibm.com\n\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/ccunzip.exec",
    "content": "/* CCUNZIP  EXEC   Compile unzip 5.4 for VM/CMS                           */\n/*                 Author: George Petrov, 11 Apr 1995 (VMCOMPIL EXEC) */\n/* Modified for IBM C V3R1 by Ian E. Gorman, 2 Nov 1998\n   Facilities for compiling and testing were provided by\n      OmniMark Technologies Corporation, Ottawa, Canada\n*/\nAddress Command\nSignal On Error\n\n/* Allow longnames, compile re-entrant code.\n   global.c and vmmvs.c require EXTENDED features */\nCCopts = 'LONGNAME RENT LANGLVL(EXTENDED) NOEXECOPS'\n\n/* UNZIP options -- VM_CMS, REENTRANT */\nCCopts = CCopts 'DEFINE(VM_CMS,REENTRANT)'\n\n/* Link the load module to run in more or less than 16MB memory */\nLINKopts = 'AMODE ANY RMODE ANY RLDSAVE'\n\n\n'GLOBAL TXTLIB  SCEELKED CMSLIB'\n'GLOBAL LOADLIB SCEERUN'\n\n\n/* produce the TEXT (object) files */\nlinklist=''\nmodname='UNZIP'\nSay 'Building' modname 'MODULE...'\nCall Compile 'UNZIP'\nCall Compile 'CRC32'\nCall Compile 'CRYPT'\nCall Compile 'ENVARGS'\nCall Compile 'EXPLODE'\nCall Compile 'EXTRACT'\nCall Compile 'FILEIO'\nCall Compile 'GLOBALS'\nCall Compile 'INFLATE'\nCall Compile 'PROCESS'\nCall Compile 'LIST'\nCall Compile 'MATCH'\nCall Compile 'TTYIO'\nCall Compile 'UNREDUCE'\nCall Compile 'UNSHRINK'\nCall Compile 'ZIPINFO'\nCall Compile 'VMMVS'\n\nSay 'Linking...'\n'EXEC CMOD' linklist '(MODNAME' modname LINKopts\nSay modname 'built successfully.'\n\n\n/* Make ZIPINFO from UNZIP */\nmodname = 'ZIPINFO'\n'COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE REPLACE'\nSay modname 'built successfully.'\nSay 'Done.'\n\nExit rc\n\n\n\nerror:\nSay 'Error' rc 'during compilation!'\nSay 'Error in line' sigl':'\nSay '   'Sourceline(sigl)\nExit rc\n\n\n\nCompile:  Procedure Expose CCopts LINKopts linklist\nParse arg filename filetype filemode .\nIf filetype='' Then filetype='C'\nlinklist = linklist filename\n\nSay 'Compiling' filename filetype filemode '...'\n'EXEC CC' filename filetype filemode '('CCopts\nReturn rc\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/mc.exec",
    "content": "/* MAKECPIP EXEC      Make program to build a C/370 module           */\n/*                    Author: George Petrov, 29 Sep 1994             */\n\narg fn . '(' cparms                   /* Filter name                 */\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| frlab GLOBALS:'||,\n    '| drop',\n    '| strip',\n    '| var globals'\ncparms = cparms globals\nsay ''\nsay 'Compile options : 'cparms\nsay ''\nif pos('REB',cparms) > 0 then do\nparse var cparms cp1 'REB' . ' ' cp2  /* REBuild options specified ? */\ncparms = cp1||cp2\npipe1=,\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| nfind *'||,                    /* the makefile and compile    */\n    '| frlab TEXT:'||,                /* only the those who are      */\n    '| r: tolab MODULE:'||,           /* changed or never compiled   */\n    '| drop',\n    '| o: fanout',\n    '| chop before str /(/',\n    '| statew',\n    '| c: fanout',                    /* compiled                    */\n    '| specs /Compiling / 1 w1-3 n / .../ n',\n    '| cons'\nend\nelse do\npipe1=,\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| nfind *'||,                    /* the makefile and compile    */\n    '| frlab TEXT:'||,                /* only the those who are      */\n    '| r: tolab MODULE:'||,           /* changed or never compiled   */\n    '| drop',\n    '| o: fanout',\n    '| specs w1 1 /C/ nw w3 nw write w1 1 /TEXT A/ nw',\n    '| chop before str /(/',\n    '| statew',\n    '| change (57 66) / /0/',\n    '| sort 1.8 d',                  /* sort the date and time      */\n    '| uniq 1-17 singles',           /* if the first is a source    */\n    '| sort 1.8 d 64.2 d 57.2 d 60.2 d 66.8 d',    /* sort the date */\n    '| uniq 1-8 first',          /*    if the first is a source    */\n    '| locate 9.8 /C      /',         /* program then it has to be   */\n    '| c: fanout',                    /* compiled                    */\n    '| specs /Compiling / 1 w1-3 n / .../ n',\n    '| cons'\nend\npipe2= '?',\n    'r:',\n    '| drop',\n    '| specs w1 1',                 /* save the module name in var  */\n    '| var module',\n    '?',\n    'o:',\n    '| specs w1 1',\n    '| join * / /',\n    '| var texts',                  /* save all the text file names */\n    '?',                            /* for later include            */\n    'c:',\n    '| specs /CC / 1 w1-3 n /(NOTERM 'cparms'/ nw',   /* compile! */\n    '| err: cms | cons',\n    '?',\n    'err:',\n    '| nfind 0'||,\n    '| var err',\n    '| specs /----> Errors found! RC=/ 1 1-* n',\n    '| cons'\n/*  '| g: gate'*/\npipe1 pipe2\nsay ''\nif symbol('err') = 'VAR' & err ^= 0 then do\n      say 'Errors found in source files - link aborted! RC = 'err\n      exit err\nend\nsay 'Generating module 'module\n'pipe cms cmod' fn texts' | > 'fn' LINK A'\nexit rc\nerror:\nsay 'Error in REXX detected!'\nSay 'Syntax error on line' Sigl':' Sourceline(Sigl)\nSay 'Error was:' Errortext(RC)\nreturn rc\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/mvs.mki",
    "content": "# Makefile for the MVS (OS/390 Base) version of UNZIP 5.4\n# Produced for C/C++ V3R2 in OS/390 1.2.0 by Ian E. Gorman, 2 Nov 1998\n# Facilities for compiling and testing were made available by\n#     OmniMark Technologies Corporation, Ottawa, Canada\n\n# NOTES\n#\n# The only tabs in this file are in the first character of each recipe\n# line, where they are required by make.\n#\n# Run this makefile in OpenMVS (OS/390 POSIX) using source files in the\n# HFS file system.  You can write the load module to either HFS file\n# system or to a PDS in the native MVS file system.  The PDS must have\n# sufficient free space to hold the load module.\n#\n# To compile to a member of a PDS:\n#   make\n# or\n#   make unzip.mvs\n#\n# To compile a test version into the HFS file system:\n#   make hfs\n\n# UNZIP options -- MVS, REENTRANT\nZIPOPTS=-DMVS\n\n# directories\n\n# generic source code\nSRC=..\nSRC_P=$(SRC)/\n\n# source code for MVS\nCMSMVS=../cmsmvs\nCMSMVS_P=$(CMSMVS)/\n\n# include files\nINCLS=-I$(SRC) -I$(CMSMVS)\n\n# object files and load modules\nBLD_P=../mvs/\n\n# Other options\n\n# Suffixes (E and O must be different)\nE=\nO=.o\n\n# Need EXTENDED features for global.c and vmvms.c, so not using c89\nCC=cc\nCFLAGS=-D_OPEN_SYS $(ZIPOPTS) $(INCLS)\n\nLD=cc\nLDFLAGS=\n\n# Files\n\n# object (TEXT) files\nOBJECTS= $(BLD_P)unzip$(O) $(BLD_P)crc32$(O) \\\n   $(BLD_P)crypt$(O)    $(BLD_P)envargs$(O)  $(BLD_P)explode$(O) \\\n   $(BLD_P)extract$(O)  $(BLD_P)fileio$(O)   $(BLD_P)globals$(O) \\\n   $(BLD_P)inflate$(O)  $(BLD_P)process$(O)  $(BLD_P)list$(O) \\\n   $(BLD_P)match$(O)    $(BLD_P)ttyio$(O)    $(BLD_P)unreduce$(O) \\\n   $(BLD_P)unshrink$(O) $(BLD_P)zipinfo$(O)  $(BLD_P)vmmvs$(O)\n\n# Header files\nHFILES= $(SRC_P)consts.h $(SRC_P)crypt.h $(SRC_P)ebcdic.h \\\n    $(SRC_P)globals.h $(SRC_P)inflate.h \\\n    $(SRC_P)ttyio.h $(SRC_P)unzip.h $(SRC_P)unzpriv.h \\\n    $(SRC_P)unzvers.h $(SRC_P)zip.h $(CMSMVS_P)vmmvs.h \\\n    $(CMSMVS_P)vmstat.h\n\n# Rules\n\nall:  $(BLD_P)unzip.mvs$(E)\nhfs:  $(BLD_P)unzip$(E)\n\n# link\n\n$(BLD_P)unzip.mvs$(E):     $(OBJECTS)\n\t$(LD) -o \"//INFOZIP.LOAD(UNZIP)\" $(LDFLAGS) $^\n\techo \"tso call \\\"infozip(unzip)\\\" \\\"'\\\"\\\"\"\"$$\"\"@\"\"\\\"\\\"'\\\"\" > $%\n\tchmod a+x $%\n\n$(BLD_P)unzip$(E):     $(OBJECTS)\n\t$(LD) -o $% $(LDFLAGS) $^\n\n# compile\n\n$(BLD_P)api$(O):        $(SRC_P)api.c           $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)api.c\n\n$(BLD_P)apihelp$(O):    $(SRC_P)apihelp.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)apihelp.c\n\n$(BLD_P)crc32$(O):      $(SRC_P)crc32.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)crc32.c\n\n$(BLD_P)crypt$(O):      $(SRC_P)crypt.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)crypt.c\n\n$(BLD_P)envargs$(O):    $(SRC_P)envargs.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)envargs.c\n\n$(BLD_P)explode$(O):    $(SRC_P)explode.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)explode.c\n\n$(BLD_P)extract$(O):    $(SRC_P)extract.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)extract.c\n\n$(BLD_P)fileio$(O):     $(SRC_P)fileio.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)fileio.c\n\n$(BLD_P)funzip$(O):     $(SRC_P)funzip.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)funzip.c\n\n$(BLD_P)globals$(O):    $(SRC_P)globals.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)globals.c\n\n$(BLD_P)inflate$(O):    $(SRC_P)inflate.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)inflate.c\n\n$(BLD_P)list$(O):       $(SRC_P)list.c          $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)list.c\n\n$(BLD_P)match$(O):      $(SRC_P)match.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)match.c\n\n$(BLD_P)process$(O):    $(SRC_P)process.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)process.c\n\n$(BLD_P)ttyio$(O):      $(SRC_P)ttyio.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)ttyio.c\n\n$(BLD_P)unreduce$(O):   $(SRC_P)unreduce.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)unreduce.c\n\n$(BLD_P)unshrink$(O):   $(SRC_P)unshrink.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)unshrink.c\n\n$(BLD_P)unzip$(O):      $(SRC_P)unzip.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)unzip.c\n\n$(BLD_P)unzipstb$(O):   $(SRC_P)unzipstb.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)unzipstb.c\n\n$(BLD_P)zipinfo$(O):    $(SRC_P)zipinfo.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)zipinfo.c\n\n$(BLD_P)vmmvs$(O):      $(CMSMVS_P)vmmvs.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)vmmvs.c\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/unzip.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/unzip.makefile",
    "content": "* This is a comment\n* this makefile compiles filter UNZIP\n\nGLOBALS:\n   long def(VM_CMS)\nTEXT:\n   unzip c\n   crc32 c\n   crypt c\n   envargs c\n   explode c\n   extract c\n   fileio c\n   globals c\n   inflate c\n   list c\n   match c\n   process c\n   ttyio c\n   unreduce c\n   unshrink c\n   zipinfo c\n   vmmvs c\nMODULE:\n   unzip module\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/unzmvsc.job",
    "content": "//*\n//* LE COMPILE FOR UNZIP541.\n//* ALL STEPS SHOULD GET COND CODE 0 EXCEPT FOR PLINK.PLKED WHICH GETS 4.\n//*\n//CBC    JCLLIB ORDER=CBC.SCBCPRC\n//UNZIP EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(UNZIP)',\n//    OUTFILE='USERID.UNZIP.OBJ(UNZIP),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//CRC32 EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(CRC32)',\n//    OUTFILE='USERID.UNZIP.OBJ(CRC32),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//CRYPT EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(CRYPT)',\n//    OUTFILE='USERID.UNZIP.OBJ(CRYPT),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//ENVARGS EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(ENVARGS)',\n//    OUTFILE='USERID.UNZIP.OBJ(ENVARGS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//EXPLODE EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(EXPLODE)',\n//    OUTFILE='USERID.UNZIP.OBJ(EXPLODE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//EXTRACT EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(EXTRACT)',\n//    OUTFILE='USERID.UNZIP.OBJ(EXTRACT),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//FILEIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(FILEIO)',\n//    OUTFILE='USERID.UNZIP.OBJ(FILEIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//GLOBALS EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(GLOBALS)',\n//    OUTFILE='USERID.UNZIP.OBJ(GLOBALS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//INFLATE EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(INFLATE)',\n//    OUTFILE='USERID.UNZIP.OBJ(INFLATE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//LIST EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(LIST)',\n//    OUTFILE='USERID.UNZIP.OBJ(LIST),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//MATCH EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(MATCH)',\n//    OUTFILE='USERID.UNZIP.OBJ(MATCH),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//PROCESS EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(PROCESS)',\n//    OUTFILE='USERID.UNZIP.OBJ(PROCESS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//TTYIO EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(TTYIO)',\n//    OUTFILE='USERID.UNZIP.OBJ(TTYIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//UNREDUCE EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(UNREDUCE)',\n//    OUTFILE='USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//UNSHRINK EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(UNSHRINK)',\n//    OUTFILE='USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//ZIPINFO EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(ZIPINFO)',\n//    OUTFILE='USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//VMMVS EXEC EDCC,COND=(0,NE),CREGSIZ='0M',\n//    INFILE='USERID.UNZIP.C(VMMVS)',\n//    OUTFILE='USERID.UNZIP.OBJ(VMMVS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=USERID.UNZIP.H,DISP=SHR\n//PLINK   EXEC  PROC=EDCPL,COND=(4,LT),\n//    OUTFILE='USERID.UNZIP.LOAD(UNZIP),DISP=SHR',\n//    PPARM='NONCAL,MAP,MEMORY',\n//    LPARM='LIST,MAP,XREF'\n//SYSPRINT DD  SYSOUT=*\n//PLKED.SYSIN   DD  DSN=USERID.UNZIP.OBJ(UNZIP),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(CRC32),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(CRYPT),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(ENVARGS),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(EXPLODE),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(EXTRACT),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(FILEIO),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(GLOBALS),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(INFLATE),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(LIST),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(MATCH),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(PROCESS),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(TTYIO),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(UNREDUCE),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(UNSHRINK),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(ZIPINFO),DISP=SHR\n//              DD  DSN=USERID.UNZIP.OBJ(VMMVS),DISP=SHR\n//LKED.SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/unzvmc.exec",
    "content": "/* VMCOMPIL EXEC   Unzip compile for VM/CMS                           */\n/*                 Author : George Petrov, 11 Apr 1995                */\n\nsignal on error\n\nparms = '(long def(VM_CMS)'\n/* Add local options */\n/* \"TARGET(COMPAT)\" is required for V2.2 compiler */\nparms = parms 'TARGET(COMPAT) SOURCE'\n\n\nsay 'Compiling UNZIP C...'\n'cc unzip c 'parms\nsay 'Compiling CRC32 C...'\n'cc crc32 c 'parms\nsay 'Compiling CRYPT C...'\n'cc crypt c 'parms\nsay 'Compiling ENVARGS C...'\n'cc envargs c 'parms\nsay 'Compiling EXPLODE C...'\n'cc explode c 'parms\nsay 'Compiling EXTRACT C...'\n'cc extract c 'parms\nsay 'Compiling FILEIO C...'\n'cc fileio c 'parms\nsay 'Compiling GLOBALS C...'\n'cc globals c 'parms\nsay 'Compiling INFLATE C...'\n'cc inflate c 'parms\nsay 'Compiling PROCESS C...'\n'cc process c 'parms\nsay 'Compiling LIST C...'\n'cc list c 'parms\nsay 'Compiling MATCH C...'\n'cc match c 'parms\nsay 'Compiling TTYIO C...'\n'cc ttyio c 'parms\nsay 'Compiling UNREDUCE C...'\n'cc unreduce c 'parms\nsay 'Compiling UNSHRINK C...'\n'cc unshrink c 'parms\nsay 'Compiling ZIPINFO C...'\n'cc zipinfo c 'parms\nsay 'Compiling VMMVS C...'\n'cc vmmvs c 'parms\n\nsay 'Linking all files...'\n'cmod unzip unzip crc32 crypt envargs explode extract fileio globals',\n           'inflate list match process ttyio unreduce unshrink zipinfo vmmvs'\nsay 'All Done!'\nsay \"To run enter : UNZIP parms\"\nexit rc\n\nerror:\nsay 'Error during compilation!'\nexit rc\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/vmmvs.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vmmvs.c (for both VM/CMS and MVS)\n\n  Contains:  vmmvs_open_infile()\n             open_outfile()\n             close_outfile()\n             close_infile()\n             getVMMVSexfield()\n             do_wild()\n             mapattr()\n             mapname()\n             checkdir()\n             check_for_newer()\n             stat()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __VMMVS_C       /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n\n/********************************/\n/* Function vmmvs_open_infile() */\n/********************************/\n\nFILE *vmmvs_open_infile(__G)\n   __GDEF\n{\n   FILE *fzip;\n\n   G.tempfn = NULL;\n\n   fzip = fopen(G.zipfn, FOPR);\n\n#if 0\n   /* Let's try it without the convert for a while -- RG Hartwig */\n\n   if ((fzip = fopen(G.zipfn,\"rb,recfm=fb\")) == NULL) {\n      size_t cnt;\n      char *buf;\n      FILE *in, *out;\n\n      if ((buf = (char *)malloc(32768)) == NULL) return NULL;\n      if ((G.tempfn = tmpnam(NULL)) == NULL) return NULL;\n      if ((in = fopen(G.zipfn,\"rb\")) != NULL &&\n          (out = fopen(G.tempfn,\"wb,recfm=fb,lrecl=1\")) != NULL) {\n         Trace((stdout,\"Converting ZIP file to fixed record format...\\n\"));\n         while (!feof(in)) {\n            cnt = fread(buf,1,32768,in);\n            if (cnt) fwrite(buf,1,cnt,out);\n         }\n      }\n      else {\n         free(buf);\n         fclose(out);\n         fclose(in);\n         return NULL;\n      }\n      free(buf);\n      fclose(out);\n      fclose(in);\n\n      fzip = fopen(G.tempfn,\"rb,recfm=fb\");\n      if (fzip == NULL) return NULL;\n\n      /* Update the G.ziplen value since it might have changed after\n         the reformatting copy. */\n      fseek(fzip,0L,SEEK_SET);\n      fseek(fzip,0L,SEEK_END);\n      G.ziplen = ftell(fzip);\n   }\n\n#endif\n\n   return fzip;\n}\n\n\n/***************************/\n/* Function open_outfile() */\n/***************************/\n\nint open_outfile(__G)           /* return 1 if fail */\n    __GDEF\n{\n    char type[100];\n    char *mode = NULL;\n#ifdef MVS\n    /* Check if the output file already exists and do not overwrite its DCB */\n    char basefilename[PATH_MAX], *p;\n    FILE *exists;\n\n    /* Get the base file name, without any member name */\n    strcpy(basefilename, G.filename);\n    if ((p = strchr(basefilename, '(')) != NULL) {\n       if (basefilename[0] == '\\'')\n          *p++ = '\\'';\n       *p = '\\0';\n    }\n    exists = fopen(basefilename, FOPR);\n    if (exists) {\n       if (G.pInfo->textmode)\n           mode = FOPWTE;       /* Text file, existing */\n       else\n           mode = FOPWE;        /* Binary file, existing */\n       fclose(exists);\n    }\n    else   /* continued on next line */\n#endif /* MVS */\n    if (G.pInfo->textmode) {\n        if (mode == NULL)\n           mode = FOPWT;\n    } else if (G.lrec.extra_field_length > 0 && G.extra_field != NULL) {\n        unsigned lef_len = (unsigned)(G.lrec.extra_field_length);\n        uch *lef_buf = G.extra_field;\n\n        while (lef_len > EB_HEADSIZE) {\n            unsigned eb_id = makeword(&lef_buf[EB_ID]);\n            unsigned eb_dlen = makeword(&lef_buf[EB_LEN]);\n\n            if (eb_dlen > (lef_len - EB_HEADSIZE)) {\n                /* Discovered some extra field inconsistency! */\n                TTrace((stderr,\n                        \"open_outfile: block length %u > rest lef_size %u\\n\",\n                        eb_dlen, lef_len - EB_HEADSIZE));\n                break;\n            }\n\n            if ((eb_id == EF_VMCMS || eb_id == EF_MVS) &&\n                (getVMMVSexfield(type, lef_buf, eb_dlen) > 0)) {\n                mode = type;\n                break;\n            }\n\n            /* Skip this extra field block */\n            lef_buf += (eb_dlen + EB_HEADSIZE);\n            lef_len -= (eb_dlen + EB_HEADSIZE);\n        }\n    }\n    if (mode == NULL) mode = FOPW;\n\n    Trace((stderr, \"Output file='%s' opening with '%s'\\n\", G.filename, mode));\n    if ((G.outfile = fopen(G.filename, mode)) == NULL) {\n        Info(slide, 0x401, ((char *)slide, \"\\nerror:  cannot create %s\\n\",\n             FnFilter1(G.filename)));\n        Trace((stderr, \"error %d: '%s'\\n\", errno, strerror(errno)));\n        return 1;\n    }\n    return 0;\n} /* end function open_outfile() */\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n   __GDEF\n{\n   fclose(G.outfile);\n} /* end function close_outfile() */\n\n\n/***************************/\n/* Function close_infile() */\n/***************************/\n\nvoid close_infile(__G)\n   __GDEF\n{\n   fclose(G.zipfd);\n\n   /* If we're working from a temp file, erase it now */\n   if (G.tempfn)\n      remove(G.tempfn);\n\n} /* end function close_infile() */\n\n\n\n/******************************/\n/* Function getVMMVSexfield() */\n/******************************/\n\nextent getVMMVSexfield(type, ef_block, datalen)\n    char *type;\n    uch *ef_block;\n    unsigned datalen;\n{\n    fldata_t *fdata = (fldata_t *) &ef_block[4];\n\n    if (datalen < sizeof(fldata_t))\n        return 0;\n\n    strcpy(type, \"w\");\n    strcat(type,  fdata->__openmode == __TEXT   ? \"\"\n                 :fdata->__openmode == __BINARY ? \"b\"\n                 :fdata->__openmode == __RECORD ? \"b,type=record\"\n                 :                                \"\");\n    strcat(type, \",recfm=\");\n    strcat(type,  fdata->__recfmF? \"F\"\n                 :fdata->__recfmV? \"V\"\n                 :fdata->__recfmU? \"U\"\n                 :                 \"?\");\n    if (fdata->__recfmBlk) strcat(type, \"B\");\n    if (fdata->__recfmS)   strcat(type, \"S\");\n    if (fdata->__recfmASA) strcat(type, \"A\");\n    if (fdata->__recfmM)   strcat(type, \"M\");\n    sprintf(type+strlen(type), \",lrecl=%ld\", fdata->__recfmV\n                                              ? fdata->__maxreclen+4\n                                              : fdata->__maxreclen);\n#ifdef VM_CMS\n    /* For CMS, use blocksize for FB files only */\n    if (fdata->__recfmBlk)\n       sprintf(type+strlen(type), \",blksize=%ld\", fdata->__blksize);\n#else\n    /* For MVS, always use blocksize */\n    sprintf(type+strlen(type), \",blksize=%ld\", fdata->__blksize);\n#endif\n\n    return strlen(type);\n} /* end function getVMMVSexfield() */\n\n\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wld)\n    __GDEF\n    ZCONST char *wld;      /* only used first time on a given dir */\n{\n    static int First = 0;\n    static char filename[256];\n\n    if (First == 0) {\n       First = 1;\n       strncpy(filename, wld, sizeof(filename));\n       filename[sizeof(filename)-1] = '\\0';\n       return filename;\n    }\n    else\n       return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n/************************/\n/*  Function mapattr()  */\n/************************/\n\nint mapattr(__G)\n     __GDEF\n{\n    return 0;\n}\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char newname[FILNAMSIZ], *lbar;\n#ifdef MVS\n    char *pmember;\n#endif\n    int name_changed = MPN_OK;\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in CMS_MVS */\n\n#ifdef MVS\n    /* Remove bad characters for MVS from the filename */\n    while ((lbar = strpbrk(G.filename, \"_+-\")) != NULL) {\n       /* Must use memmove() here because data overlaps.  */\n       /* strcpy() gives undefined behavior in this case. */\n       memmove(lbar, lbar+1, strlen(lbar));\n       name_changed = MPN_INF_TRUNC;\n    }\n#endif\n\n    /* Remove bad characters for MVS/CMS from the filename */\n    while ((lbar = strpbrk(G.filename, \"()\")) != NULL) {\n       memmove(lbar, lbar+1, strlen(lbar));\n       name_changed = MPN_INF_TRUNC;\n    }\n\n#ifdef VM_CMS\n    if ((lbar = strrchr(G.filename, '/')) != NULL) {\n        strcpy(newname, lbar+1);\n        Trace((stderr, \"File '%s' renamed to '%s'\\n\", G.filename, newname));\n        strcpy(G.filename, newname);\n        name_changed = MPN_INF_TRUNC;\n    }\n#else /* MVS */\n    if ((pmember = strrchr(G.filename, '/')) == NULL)\n        pmember = G.filename;\n    else\n        pmember++;\n\n    /* search for extension in file name */\n    if ((lbar = strrchr(pmember, '.')) != NULL) {\n        *lbar++ = '\\0';\n        strcpy(newname, pmember);\n        strcpy(pmember, lbar);\n        strcat(pmember, \"(\");\n        strcat(pmember, newname);\n        strcat(pmember, \")\");\n    }\n\n    /* Remove all 'internal' dots '.', to prevent false consideration as\n     * MVS path delimiters! */\n    while ((lbar = strrchr(G.filename, '.')) != NULL) {\n        memmove(lbar, lbar+1, strlen(lbar));\n        name_changed = MPN_INF_TRUNC;\n    }\n\n    /* Finally, convert path delimiters from internal '/' to external '.' */\n    while ((lbar = strchr(G.filename, '/')) != NULL)\n        *lbar = '.';\n#endif /* ?VM_CMS */\n\n#ifndef MVS\n    if ((lbar = strchr(G.filename, '.')) == NULL) {\n        printf(\"WARNING: file '%s' has no extension - renamed to '%s.NONAME'\\n\"\\\n              ,G.filename, G.filename);\n       strcat(G.filename, \".NONAME\");\n       name_changed = MPN_INF_TRUNC;\n    }\n#endif\n    checkdir(__G__ G.filename, GETPATH);\n\n    return name_changed;\n\n} /* end function mapname() */\n\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;     /* length of rootpath */\n    static char *rootpath;      /* user's \"extract-to\" directory */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to\n    directory specification includes a drive letter (leading \"x:\"), it is\n    treated just as if it had a trailing '/'--that is, one directory level\n    will be created if the path doesn't exist, unless this is otherwise pro-\n    hibited (e.g., freshening).\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n        }\n        else if ((rootlen = strlen(pathcomp)) > 0) {\n            if ((rootpath = (char *)malloc(rootlen+1)) == NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(rootpath, pathcomp);\n            Trace((stderr, \"rootpath now = [%s]\\n\", rootpath));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        if (rootlen > 0) {\n#ifdef VM_CMS                     /* put the exdir after the filename */\n           strcat(pathcomp, \".\");       /* used as minidisk to be save on  */\n           strcat(pathcomp, rootpath);\n#else /* MVS */\n           char newfilename[PATH_MAX];\n           char *start_fname;\n           int quoted = 0;\n\n           strcpy(newfilename, rootpath);\n           if (newfilename[0] == '\\'') {\n              quoted = strlen(newfilename) - 1;\n              if (newfilename[quoted] == '\\'')\n                 newfilename[quoted] = '\\0';\n              else\n                 quoted = 0;\n           }\n           if (strchr(pathcomp, '(') == NULL) {\n              if ((start_fname = strrchr(pathcomp, '.')) == NULL) {\n                 start_fname = pathcomp;\n              }\n              else {\n                 *start_fname++ = '\\0';\n                 strcat(newfilename, \".\");\n                 strcat(newfilename, pathcomp);\n              }\n              strcat(newfilename, \"(\");\n              strcat(newfilename, start_fname);\n              strcat(newfilename, \")\");\n           }\n           else {\n              strcat(newfilename, \".\");\n              strcat(newfilename, pathcomp);\n           }\n           if (quoted)\n              strcat(newfilename, \"'\");\n           Trace((stdout, \"new dataset : %s\\n\", newfilename));\n           strcpy(pathcomp, newfilename);\n#endif /* ?VM_CMS */\n        }\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n/******************************/\n/* Function check_for_newer() */  /* used for overwriting/freshening/updating */\n/******************************/\n\nint check_for_newer(__G__ filename)  /* return 1 if existing file is newer */\n    __GDEF                           /*  or equal; 0 if older; -1 if doesn't */\n    char *filename;                  /*  exist yet */\n{\n    FILE *stream;\n\n    if ((stream = fopen(filename, FOPR)) != NULL) {\n       fclose(stream);\n       /* File exists, assume it is \"newer\" than archive entry. */\n       return EXISTS_AND_NEWER;\n    }\n    /* File does not exist. */\n    return DOES_NOT_EXIST;\n} /* end function check_for_newer() */\n\n\n/*********************/\n/*  Function stat()  */\n/*********************/\n\nint stat(const char *path, struct stat *buf)\n{\n   FILE *fp;\n   char fname[PATH_MAX];\n   time_t ltime;\n\n   if ((fp = fopen(path, FOPR)) != NULL) {\n      fldata_t fdata;\n      if (fldata( fp, fname, &fdata ) == 0) {\n         buf->st_dev  = fdata.__device;\n         buf->st_mode = *(short *)(&fdata);\n      }\n\n      /* Determine file size by seeking to EOF */\n      fseek(fp,0L,SEEK_END);\n      buf->st_size = ftell(fp);\n      fclose(fp);\n\n      /* set time fields in stat buf to current time. */\n      time(&ltime);\n      buf->st_atime =\n      buf->st_mtime =\n      buf->st_ctime = ltime;\n\n      /* File exists, return success */\n      return 0;\n   }\n   return 1;\n}\n\n\n\n#ifdef STAND_ALONE\n/***************************/\n/*  Function main_vmmvs()  */\n/***************************/\n\n/* This function is called as main() to parse arguments                */\n/* into argc and argv.  This is required for stand-alone               */\n/* execution.  This calls the \"real\" main() when done.                 */\n\nint MAIN_VMMVS(void)\n   {\n    int  argc=0;\n    char *argv[50];\n\n    int  iArgLen;\n    char argstr[256];\n    char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd;\n\n   /* Get address of extended parameter list from S/370 Register 0 */\n   pEPLIST = (char **)__xregs(0);\n\n   /* Null-terminate the argument string */\n   pCmdStart = *(pEPLIST+0);\n   pArgStart = *(pEPLIST+1);\n   pArgEnd   = *(pEPLIST+2);\n   iArgLen   = pArgEnd - pCmdStart + 1;\n\n   /* Make a copy of the command string */\n   memcpy(argstr, pCmdStart, iArgLen);\n   argstr[iArgLen] = '\\0';  /* Null-terminate */\n\n   /* Store first token (cmd) */\n   argv[argc++] = strtok(argstr, \" \");\n\n   /* Store the rest (args) */\n   while (argv[argc-1])\n      argv[argc++] = strtok(NULL, \" \");\n   argc--;  /* Back off last NULL entry */\n\n   /* Call \"real\" main() function */\n   return MAIN(argc, argv);\n}\n#endif  /* STAND_ALONE */\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n    char liblvlmsg [50+1];\n    char *compiler = \"?\";\n    char *platform = \"?\";\n    char complevel[64];\n\n    /* Map the runtime library level information */\n    union {\n       unsigned int iVRM;\n       struct {\n          unsigned int pd:4;    /* Product designation */\n          unsigned int vv:4;    /* Version             */\n          unsigned int rr:8;    /* Release             */\n          unsigned int mm:16;   /* Modification level  */\n       } xVRM;\n    } VRM;\n\n\n    /* Break down the runtime library level */\n    VRM.iVRM = __librel();\n    sprintf(liblvlmsg, \"Using runtime library level %s V%dR%dM%d\",\n            (VRM.xVRM.pd==1 ? \"LE\" : \"CE\"),\n            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);\n    /* Note:  LE = Language Environment, CE = Common Env. (C/370). */\n    /* This refers ONLY to the current runtimes, not the compiler. */\n\n\n#ifdef VM_CMS\n    platform = \"VM/CMS\";\n    #ifdef __IBMC__\n       compiler = \"IBM C\";\n    #else\n       compiler  = \"C/370\";\n    #endif\n#endif\n\n#ifdef MVS\n    platform = \"MVS\";\n    #ifdef __IBMC__\n       compiler = \"IBM C/C++\";\n    #else\n       compiler = \"C/370\";\n    #endif\n#endif\n\n#ifdef __COMPILER_VER__\n    VRM.iVRM = __COMPILER_VER__;\n    sprintf(complevel,\" V%dR%dM%d\",\n            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);\n#else\n#ifdef __IBMC__\n    sprintf(complevel,\" V%dR%d\", __IBMC__ / 100, (__IBMC__ % 100)/10);\n#else\n    complevel[0] = '\\0';\n#endif\n#endif\n\n\n    /* Output is in the form \"Compiled with %s%s for %s%s%s%s.\" */\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n    /* Add compiler name and level */\n    compiler, complevel,\n\n    /* Add compile environment */\n    platform,\n\n    /* Add timestamp */\n#ifdef __DATE__\n      \" on \" __DATE__\n#ifdef __TIME__\n      \" at \" __TIME__\n#endif\n#endif\n      \".\\n\", \"\",\n      liblvlmsg\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/vmmvs.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* vmmvs.h:  include file for both VM/CMS and MVS ports of UnZip */\n#ifndef __vmmvs_h               /* prevent multiple inclusions */\n#define __vmmvs_h\n\n#ifndef NULL\n#  define NULL (zvoid *)0\n#endif\n\n#ifdef MVS\n#  define _POSIX_SOURCE    /* tell MVS we want full definitions */\n#  define NO_STRNICMP      /* MVS has no strnicmp() */\n#  include <features.h>\n   /* MVS complains if a function has the same name as a csect. */\n#  if defined(__UNZIP_C)\n#    pragma csect(STATIC,\"unzip_s\")\n#  elif defined(__CRC32_C)\n#    pragma csect(STATIC,\"crc32_s\")\n#  elif defined(__ENVARGS_C)\n#    pragma csect(STATIC,\"envarg_s\")\n#  elif defined(__EXPLODE_C)\n#    pragma csect(STATIC,\"explod_s\")\n#  elif defined(__INFLATE_C)\n#    pragma csect(STATIC,\"inflat_s\")\n#  elif defined(__MATCH_C)\n#    pragma csect(STATIC,\"match_s\")\n#  elif defined(__UNREDUCE_C)\n#    pragma csect(STATIC,\"unredu_s\")\n#  elif defined(__UNSHRINK_C)\n#    pragma csect(STATIC,\"unshri_s\")\n#  elif defined(__ZIPINFO_C)\n#    pragma csect(STATIC,\"zipinf_s\")\n#  endif\n#endif /* MVS */\n\n#include <time.h>               /* the usual non-BSD time functions */\n#ifdef VM_CMS\n#  include \"vmstat.h\"\n#endif\n#ifdef MVS\n#  include <sys/stat.h>\n#endif\n\n#define PASSWD_FROM_STDIN\n                  /* Kludge until we know how to open a non-echo tty channel */\n\n#define EBCDIC\n/* In the context of Info-ZIP, a portable \"text\" mode file implies the use of\n   an ASCII-compatible (ISO 8859-1, or other extended ASCII) code page. */\n\n#ifdef MORE\n#  undef MORE\n#endif\n\n/* Workarounds for missing RTL functionality */\n#define isatty(t) 1\n\n#ifdef UNZIP                    /* definitions for UNZIP */\n\n#define INBUFSIZ 8192\n\n#define USE_STRM_INPUT\n#define USE_FWRITE\n\n#define PATH_MAX 128\n\n#ifndef QUERY_TRNEWLN\n#  define QUERY_TRNEWLN         /* terminate interaction queries with '\\n' */\n#endif\n\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT DF_MDY\n#endif\n#define lenEOL        1\n/* The use of \"ebcdic[LF]\" is not reliable; VM/CMS C/370 uses the\n * EBCDIC specific \"NL\" ('NewLine') control character (and not the EBCDIC\n * equivalent of the ASCII \"LF\" ('LineFeed')) as line terminator!\n * To work around this problem, we explicitely emit the C compiler's native\n * '\\n' line terminator.\n */\n#if 0\n#define PutNativeEOL  *q++ = native(LF);\n#else\n#define PutNativeEOL  *q++ = '\\n';\n#endif\n\n#endif /* UNZIP */\n\n#endif /* !__vmmvs_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/vmstat.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __vmstat_h\n#define __vmstat_h\n\n/* stat.h      definitions   */\n\n#ifndef _INO_T_DEFINED\ntypedef unsigned short ino_t;       /* i-node number (not used on DOS) */\n#define _INO_T_DEFINED\n#endif\n\n#ifndef _DEV_T_DEFINED\ntypedef short dev_t;                /* device code */\n#define _DEV_T_DEFINED\n#endif\n\n#ifndef _OFF_T_DEFINED\ntypedef long off_t;                 /* file offset value */\n#define _OFF_T_DEFINED\n#endif\n\n#ifndef _STAT_DEFINED\nstruct stat {\n  dev_t  st_dev;\n  ino_t  st_ino;\n  short  st_mode;\n  short  st_nlink;\n  int    st_uid;\n  int    st_gid;\n  off_t  st_size;\n  time_t st_atime;\n  time_t st_mtime;\n  time_t st_ctime;\n};\n#define _STAT_DEFINED\n#endif\n\nint stat(const char *path, struct stat *buf);\nint fstat(int fd, struct stat *buf);\n\n#define S_IFMT       0xFFFF\n#define _FLDATA(m)   (*(fldata_t *) &m)\n#define S_ISDIR(m)   (_FLDATA(m).__dsorgPDSdir)\n#define S_ISREG(m)   (_FLDATA(m).__dsorgPO | \\\n                      _FLDATA(m).__dsorgPDSmem | \\\n                      _FLDATA(m).__dsorgPS)\n#define S_ISBLK(m)   (_FLDATA(m).__recfmBlk)\n#define S_ISMEM(m)   (_FLDATA(m).__dsorgMem)\n\n#endif /* __vmstat_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/cmsmvs/zipinfo.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/unzip60/consts.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  consts.h\n\n  This file contains global, initialized variables that never change.  It is\n  included by unzip.c and windll/windll.c.\n\n  ---------------------------------------------------------------------------*/\n\n\n/* And'ing with mask_bits[n] masks the lower n bits */\nZCONST unsigned near mask_bits[17] = {\n    0x0000,\n    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,\n    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff\n};\n\nZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in unzvers.h */\n\n#ifndef SFX\n   ZCONST char Far EndSigMsg[] =\n   \"\\nnote:  didn't find end-of-central-dir signature at end of central dir.\\n\";\n#endif\n\nZCONST char Far CentSigMsg[] =\n  \"error:  expected central file header signature not found (file #%lu).\\n\";\nZCONST char Far SeekMsg[] =\n  \"error [%s]:  attempt to seek before beginning of zipfile\\n%s\";\nZCONST char Far FilenameNotMatched[] = \"caution: filename not matched:  %s\\n\";\nZCONST char Far ExclFilenameNotMatched[] =\n  \"caution: excluded filename not matched:  %s\\n\";\n\n#ifdef VMS\n  ZCONST char Far ReportMsg[] = \"\\\n  (please check that you have transferred or created the zipfile in the\\n\\\n  appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\\n\";\n#else\n  ZCONST char Far ReportMsg[] = \"\\\n  (please check that you have transferred or created the zipfile in the\\n\\\n  appropriate BINARY mode and that you have compiled UnZip properly)\\n\";\n#endif\n\n#ifndef SFX\n  ZCONST char Far Zipnfo[] = \"zipinfo\";\n  ZCONST char Far CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/crc32.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc32.c -- compute the CRC-32 of a data stream\n * Copyright (C) 1995 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n *\n * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster\n * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing\n * tables for updating the shift register in one step with three exclusive-ors\n * instead of four steps with four exclusive-ors.  This results about a factor\n * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.\n */\n\n/* $Id: crc32.c,v 2.0 2007/01/07 05:20:36 spc Exp $ */\n\n#define __CRC32_C       /* identifies this source module */\n\n#include \"zip.h\"\n\n#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#include \"crc32.h\"\n\n/* When only the table of precomputed CRC values is needed, only the basic\n   system-independent table containing 256 entries is created; any support\n   for \"unfolding\" optimization is disabled.\n */\n#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n#    undef IZ_CRCOPTIM_UNFOLDTBL\n#  endif\n#endif /* (USE_ZLIB || CRC_TABLE_ONLY) */\n\n#if defined(IZ_CRCOPTIM_UNFOLDTBL)\n#  define CRC_TBLS  4\n#else\n#  define CRC_TBLS  1\n#endif\n\n\n/*\n  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:\n  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.\n\n  Polynomials over GF(2) are represented in binary, one bit per coefficient,\n  with the lowest powers in the most significant bit.  Then adding polynomials\n  is just exclusive-or, and multiplying a polynomial by x is a right shift by\n  one.  If we call the above polynomial p, and represent a byte as the\n  polynomial q, also with the lowest power in the most significant bit (so the\n  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,\n  where a mod b means the remainder after dividing a by b.\n\n  This calculation is done using the shift-register method of multiplying and\n  taking the remainder.  The register is initialized to zero, and for each\n  incoming bit, x^32 is added mod p to the register if the bit is a one (where\n  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by\n  x (which is shifting right by one and adding x^32 mod p if the bit shifted\n  out is a one).  We start with the highest power (least significant bit) of\n  q and repeat for all eight bits of q.\n\n  The first (or only) table is simply the CRC of all possible eight bit values.\n  This is all the information needed to generate CRC's on data a byte-at-a-time\n  for all combinations of CRC register values and incoming bytes.\n  The remaining 3 tables (if IZ_CRCOPTIM_UNFOLDTBL is enabled) allow for\n  word-at-a-time CRC calculation, where a word is four bytes.\n*/\n\n#ifdef DYNAMIC_CRC_TABLE\n\n/* =========================================================================\n * Make the crc table. This function is needed only if you want to compute\n * the table dynamically.\n */\n\nlocal void make_crc_table OF((void));\n\n#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))\n   error: Dynamic allocation of CRC table not safe with reentrant code.\n#endif /* DYNALLOC_CRCTAB && REENTRANT */\n\n#ifdef DYNALLOC_CRCTAB\n   local ulg near *crc_table = NULL;\n# if 0          /* not used, since sizeof(\"near *\") <= sizeof(int) */\n   /* Use this section when access to a \"local int\" is faster than access to\n      a \"local pointer\" (e.g.: i86 16bit code with far pointers). */\n   local int crc_table_empty = 1;\n#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)\n#  define MARK_CRCTAB_FILLED    crc_table_empty = 0\n#  define MARK_CRCTAB_EMPTY     crc_table_empty = 1\n# else\n   /* Use this section on systems where the size of pointers and ints is\n      equal (e.g.: all 32bit systems). */\n#  define CRC_TABLE_IS_EMPTY    (crc_table == NULL)\n#  define MARK_CRCTAB_FILLED    crc_table = crctab_p\n#  define MARK_CRCTAB_EMPTY     crc_table = NULL\n# endif\n#else /* !DYNALLOC_CRCTAB */\n   local ulg near crc_table[CRC_TBLS*256];\n   local int crc_table_empty = 1;\n#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)\n#  define MARK_CRCTAB_FILLED    crc_table_empty = 0\n#endif /* ?DYNALLOC_CRCTAB */\n\n\nlocal void make_crc_table()\n{\n  ulg c;                /* crc shift register */\n  int n;                /* counter for all possible eight bit values */\n  int k;                /* byte being shifted into crc apparatus */\n#ifdef DYNALLOC_CRCTAB\n  ulg near *crctab_p;   /* temporary pointer to allocated crc_table area */\n#else /* !DYNALLOC_CRCTAB */\n# define crctab_p crc_table\n#endif /* DYNALLOC_CRCTAB */\n\n#ifdef COMPUTE_XOR_PATTERN\n  /* This piece of code has been left here to explain how the XOR pattern\n   * used in the creation of the crc_table values can be recomputed.\n   * For production versions of this function, it is more efficient to\n   * supply the resultant pattern at compile time.\n   */\n  ulg xor;              /* polynomial exclusive-or pattern */\n  /* terms of polynomial defining this crc (except x^32): */\n  static ZCONST uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};\n\n  /* make exclusive-or pattern from polynomial (0xedb88320L) */\n  xor = 0L;\n  for (n = 0; n < sizeof(p)/sizeof(uch); n++)\n    xor |= 1L << (31 - p[n]);\n#else\n# define xor 0xedb88320L\n#endif\n\n#ifdef DYNALLOC_CRCTAB\n  crctab_p = (ulg near *) nearmalloc (CRC_TBLS*256*sizeof(ulg));\n  if (crctab_p == NULL) {\n    ziperr(ZE_MEM, \"crc_table allocation\");\n  }\n#endif /* DYNALLOC_CRCTAB */\n\n  /* generate a crc for every 8-bit value */\n  for (n = 0; n < 256; n++) {\n    c = (ulg)n;\n    for (k = 8; k; k--)\n      c = c & 1 ? xor ^ (c >> 1) : c >> 1;\n    crctab_p[n] = REV_BE(c);\n  }\n\n#ifdef IZ_CRCOPTIM_UNFOLDTBL\n  /* generate crc for each value followed by one, two, and three zeros */\n  for (n = 0; n < 256; n++) {\n      c = crctab_p[n];\n      for (k = 1; k < 4; k++) {\n          c = CRC32(c, 0, crctab_p);\n          crctab_p[k*256+n] = c;\n      }\n  }\n#endif /* IZ_CRCOPTIM_UNFOLDTBL */\n\n  MARK_CRCTAB_FILLED;\n}\n\n#else /* !DYNAMIC_CRC_TABLE */\n\n#ifdef DYNALLOC_CRCTAB\n   error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.\n#endif\n\n/* ========================================================================\n * Table of CRC-32's of all single-byte values (made by make_crc_table)\n */\nlocal ZCONST ulg near crc_table[CRC_TBLS*256] = {\n# ifdef IZ_CRC_BE_OPTIMIZ\n    0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,\n    0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,\n    0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,\n    0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,\n    0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,\n    0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,\n    0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,\n    0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,\n    0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,\n    0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,\n    0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,\n    0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,\n    0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,\n    0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,\n    0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,\n    0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,\n    0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,\n    0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,\n    0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,\n    0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,\n    0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,\n    0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,\n    0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,\n    0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,\n    0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,\n    0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,\n    0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,\n    0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,\n    0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,\n    0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,\n    0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,\n    0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,\n    0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,\n    0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,\n    0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,\n    0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,\n    0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,\n    0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,\n    0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,\n    0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,\n    0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,\n    0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,\n    0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,\n    0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,\n    0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,\n    0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,\n    0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,\n    0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,\n    0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,\n    0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,\n    0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,\n    0x8def022dL\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n    ,\n    0x00000000L, 0x41311b19L, 0x82623632L, 0xc3532d2bL, 0x04c56c64L,\n    0x45f4777dL, 0x86a75a56L, 0xc796414fL, 0x088ad9c8L, 0x49bbc2d1L,\n    0x8ae8effaL, 0xcbd9f4e3L, 0x0c4fb5acL, 0x4d7eaeb5L, 0x8e2d839eL,\n    0xcf1c9887L, 0x5112c24aL, 0x1023d953L, 0xd370f478L, 0x9241ef61L,\n    0x55d7ae2eL, 0x14e6b537L, 0xd7b5981cL, 0x96848305L, 0x59981b82L,\n    0x18a9009bL, 0xdbfa2db0L, 0x9acb36a9L, 0x5d5d77e6L, 0x1c6c6cffL,\n    0xdf3f41d4L, 0x9e0e5acdL, 0xa2248495L, 0xe3159f8cL, 0x2046b2a7L,\n    0x6177a9beL, 0xa6e1e8f1L, 0xe7d0f3e8L, 0x2483dec3L, 0x65b2c5daL,\n    0xaaae5d5dL, 0xeb9f4644L, 0x28cc6b6fL, 0x69fd7076L, 0xae6b3139L,\n    0xef5a2a20L, 0x2c09070bL, 0x6d381c12L, 0xf33646dfL, 0xb2075dc6L,\n    0x715470edL, 0x30656bf4L, 0xf7f32abbL, 0xb6c231a2L, 0x75911c89L,\n    0x34a00790L, 0xfbbc9f17L, 0xba8d840eL, 0x79dea925L, 0x38efb23cL,\n    0xff79f373L, 0xbe48e86aL, 0x7d1bc541L, 0x3c2ade58L, 0x054f79f0L,\n    0x447e62e9L, 0x872d4fc2L, 0xc61c54dbL, 0x018a1594L, 0x40bb0e8dL,\n    0x83e823a6L, 0xc2d938bfL, 0x0dc5a038L, 0x4cf4bb21L, 0x8fa7960aL,\n    0xce968d13L, 0x0900cc5cL, 0x4831d745L, 0x8b62fa6eL, 0xca53e177L,\n    0x545dbbbaL, 0x156ca0a3L, 0xd63f8d88L, 0x970e9691L, 0x5098d7deL,\n    0x11a9ccc7L, 0xd2fae1ecL, 0x93cbfaf5L, 0x5cd76272L, 0x1de6796bL,\n    0xdeb55440L, 0x9f844f59L, 0x58120e16L, 0x1923150fL, 0xda703824L,\n    0x9b41233dL, 0xa76bfd65L, 0xe65ae67cL, 0x2509cb57L, 0x6438d04eL,\n    0xa3ae9101L, 0xe29f8a18L, 0x21cca733L, 0x60fdbc2aL, 0xafe124adL,\n    0xeed03fb4L, 0x2d83129fL, 0x6cb20986L, 0xab2448c9L, 0xea1553d0L,\n    0x29467efbL, 0x687765e2L, 0xf6793f2fL, 0xb7482436L, 0x741b091dL,\n    0x352a1204L, 0xf2bc534bL, 0xb38d4852L, 0x70de6579L, 0x31ef7e60L,\n    0xfef3e6e7L, 0xbfc2fdfeL, 0x7c91d0d5L, 0x3da0cbccL, 0xfa368a83L,\n    0xbb07919aL, 0x7854bcb1L, 0x3965a7a8L, 0x4b98833bL, 0x0aa99822L,\n    0xc9fab509L, 0x88cbae10L, 0x4f5def5fL, 0x0e6cf446L, 0xcd3fd96dL,\n    0x8c0ec274L, 0x43125af3L, 0x022341eaL, 0xc1706cc1L, 0x804177d8L,\n    0x47d73697L, 0x06e62d8eL, 0xc5b500a5L, 0x84841bbcL, 0x1a8a4171L,\n    0x5bbb5a68L, 0x98e87743L, 0xd9d96c5aL, 0x1e4f2d15L, 0x5f7e360cL,\n    0x9c2d1b27L, 0xdd1c003eL, 0x120098b9L, 0x533183a0L, 0x9062ae8bL,\n    0xd153b592L, 0x16c5f4ddL, 0x57f4efc4L, 0x94a7c2efL, 0xd596d9f6L,\n    0xe9bc07aeL, 0xa88d1cb7L, 0x6bde319cL, 0x2aef2a85L, 0xed796bcaL,\n    0xac4870d3L, 0x6f1b5df8L, 0x2e2a46e1L, 0xe136de66L, 0xa007c57fL,\n    0x6354e854L, 0x2265f34dL, 0xe5f3b202L, 0xa4c2a91bL, 0x67918430L,\n    0x26a09f29L, 0xb8aec5e4L, 0xf99fdefdL, 0x3accf3d6L, 0x7bfde8cfL,\n    0xbc6ba980L, 0xfd5ab299L, 0x3e099fb2L, 0x7f3884abL, 0xb0241c2cL,\n    0xf1150735L, 0x32462a1eL, 0x73773107L, 0xb4e17048L, 0xf5d06b51L,\n    0x3683467aL, 0x77b25d63L, 0x4ed7facbL, 0x0fe6e1d2L, 0xccb5ccf9L,\n    0x8d84d7e0L, 0x4a1296afL, 0x0b238db6L, 0xc870a09dL, 0x8941bb84L,\n    0x465d2303L, 0x076c381aL, 0xc43f1531L, 0x850e0e28L, 0x42984f67L,\n    0x03a9547eL, 0xc0fa7955L, 0x81cb624cL, 0x1fc53881L, 0x5ef42398L,\n    0x9da70eb3L, 0xdc9615aaL, 0x1b0054e5L, 0x5a314ffcL, 0x996262d7L,\n    0xd85379ceL, 0x174fe149L, 0x567efa50L, 0x952dd77bL, 0xd41ccc62L,\n    0x138a8d2dL, 0x52bb9634L, 0x91e8bb1fL, 0xd0d9a006L, 0xecf37e5eL,\n    0xadc26547L, 0x6e91486cL, 0x2fa05375L, 0xe836123aL, 0xa9070923L,\n    0x6a542408L, 0x2b653f11L, 0xe479a796L, 0xa548bc8fL, 0x661b91a4L,\n    0x272a8abdL, 0xe0bccbf2L, 0xa18dd0ebL, 0x62defdc0L, 0x23efe6d9L,\n    0xbde1bc14L, 0xfcd0a70dL, 0x3f838a26L, 0x7eb2913fL, 0xb924d070L,\n    0xf815cb69L, 0x3b46e642L, 0x7a77fd5bL, 0xb56b65dcL, 0xf45a7ec5L,\n    0x370953eeL, 0x763848f7L, 0xb1ae09b8L, 0xf09f12a1L, 0x33cc3f8aL,\n    0x72fd2493L\n    ,\n    0x00000000L, 0x376ac201L, 0x6ed48403L, 0x59be4602L, 0xdca80907L,\n    0xebc2cb06L, 0xb27c8d04L, 0x85164f05L, 0xb851130eL, 0x8f3bd10fL,\n    0xd685970dL, 0xe1ef550cL, 0x64f91a09L, 0x5393d808L, 0x0a2d9e0aL,\n    0x3d475c0bL, 0x70a3261cL, 0x47c9e41dL, 0x1e77a21fL, 0x291d601eL,\n    0xac0b2f1bL, 0x9b61ed1aL, 0xc2dfab18L, 0xf5b56919L, 0xc8f23512L,\n    0xff98f713L, 0xa626b111L, 0x914c7310L, 0x145a3c15L, 0x2330fe14L,\n    0x7a8eb816L, 0x4de47a17L, 0xe0464d38L, 0xd72c8f39L, 0x8e92c93bL,\n    0xb9f80b3aL, 0x3cee443fL, 0x0b84863eL, 0x523ac03cL, 0x6550023dL,\n    0x58175e36L, 0x6f7d9c37L, 0x36c3da35L, 0x01a91834L, 0x84bf5731L,\n    0xb3d59530L, 0xea6bd332L, 0xdd011133L, 0x90e56b24L, 0xa78fa925L,\n    0xfe31ef27L, 0xc95b2d26L, 0x4c4d6223L, 0x7b27a022L, 0x2299e620L,\n    0x15f32421L, 0x28b4782aL, 0x1fdeba2bL, 0x4660fc29L, 0x710a3e28L,\n    0xf41c712dL, 0xc376b32cL, 0x9ac8f52eL, 0xada2372fL, 0xc08d9a70L,\n    0xf7e75871L, 0xae591e73L, 0x9933dc72L, 0x1c259377L, 0x2b4f5176L,\n    0x72f11774L, 0x459bd575L, 0x78dc897eL, 0x4fb64b7fL, 0x16080d7dL,\n    0x2162cf7cL, 0xa4748079L, 0x931e4278L, 0xcaa0047aL, 0xfdcac67bL,\n    0xb02ebc6cL, 0x87447e6dL, 0xdefa386fL, 0xe990fa6eL, 0x6c86b56bL,\n    0x5bec776aL, 0x02523168L, 0x3538f369L, 0x087faf62L, 0x3f156d63L,\n    0x66ab2b61L, 0x51c1e960L, 0xd4d7a665L, 0xe3bd6464L, 0xba032266L,\n    0x8d69e067L, 0x20cbd748L, 0x17a11549L, 0x4e1f534bL, 0x7975914aL,\n    0xfc63de4fL, 0xcb091c4eL, 0x92b75a4cL, 0xa5dd984dL, 0x989ac446L,\n    0xaff00647L, 0xf64e4045L, 0xc1248244L, 0x4432cd41L, 0x73580f40L,\n    0x2ae64942L, 0x1d8c8b43L, 0x5068f154L, 0x67023355L, 0x3ebc7557L,\n    0x09d6b756L, 0x8cc0f853L, 0xbbaa3a52L, 0xe2147c50L, 0xd57ebe51L,\n    0xe839e25aL, 0xdf53205bL, 0x86ed6659L, 0xb187a458L, 0x3491eb5dL,\n    0x03fb295cL, 0x5a456f5eL, 0x6d2fad5fL, 0x801b35e1L, 0xb771f7e0L,\n    0xeecfb1e2L, 0xd9a573e3L, 0x5cb33ce6L, 0x6bd9fee7L, 0x3267b8e5L,\n    0x050d7ae4L, 0x384a26efL, 0x0f20e4eeL, 0x569ea2ecL, 0x61f460edL,\n    0xe4e22fe8L, 0xd388ede9L, 0x8a36abebL, 0xbd5c69eaL, 0xf0b813fdL,\n    0xc7d2d1fcL, 0x9e6c97feL, 0xa90655ffL, 0x2c101afaL, 0x1b7ad8fbL,\n    0x42c49ef9L, 0x75ae5cf8L, 0x48e900f3L, 0x7f83c2f2L, 0x263d84f0L,\n    0x115746f1L, 0x944109f4L, 0xa32bcbf5L, 0xfa958df7L, 0xcdff4ff6L,\n    0x605d78d9L, 0x5737bad8L, 0x0e89fcdaL, 0x39e33edbL, 0xbcf571deL,\n    0x8b9fb3dfL, 0xd221f5ddL, 0xe54b37dcL, 0xd80c6bd7L, 0xef66a9d6L,\n    0xb6d8efd4L, 0x81b22dd5L, 0x04a462d0L, 0x33cea0d1L, 0x6a70e6d3L,\n    0x5d1a24d2L, 0x10fe5ec5L, 0x27949cc4L, 0x7e2adac6L, 0x494018c7L,\n    0xcc5657c2L, 0xfb3c95c3L, 0xa282d3c1L, 0x95e811c0L, 0xa8af4dcbL,\n    0x9fc58fcaL, 0xc67bc9c8L, 0xf1110bc9L, 0x740744ccL, 0x436d86cdL,\n    0x1ad3c0cfL, 0x2db902ceL, 0x4096af91L, 0x77fc6d90L, 0x2e422b92L,\n    0x1928e993L, 0x9c3ea696L, 0xab546497L, 0xf2ea2295L, 0xc580e094L,\n    0xf8c7bc9fL, 0xcfad7e9eL, 0x9613389cL, 0xa179fa9dL, 0x246fb598L,\n    0x13057799L, 0x4abb319bL, 0x7dd1f39aL, 0x3035898dL, 0x075f4b8cL,\n    0x5ee10d8eL, 0x698bcf8fL, 0xec9d808aL, 0xdbf7428bL, 0x82490489L,\n    0xb523c688L, 0x88649a83L, 0xbf0e5882L, 0xe6b01e80L, 0xd1dadc81L,\n    0x54cc9384L, 0x63a65185L, 0x3a181787L, 0x0d72d586L, 0xa0d0e2a9L,\n    0x97ba20a8L, 0xce0466aaL, 0xf96ea4abL, 0x7c78ebaeL, 0x4b1229afL,\n    0x12ac6fadL, 0x25c6adacL, 0x1881f1a7L, 0x2feb33a6L, 0x765575a4L,\n    0x413fb7a5L, 0xc429f8a0L, 0xf3433aa1L, 0xaafd7ca3L, 0x9d97bea2L,\n    0xd073c4b5L, 0xe71906b4L, 0xbea740b6L, 0x89cd82b7L, 0x0cdbcdb2L,\n    0x3bb10fb3L, 0x620f49b1L, 0x55658bb0L, 0x6822d7bbL, 0x5f4815baL,\n    0x06f653b8L, 0x319c91b9L, 0xb48adebcL, 0x83e01cbdL, 0xda5e5abfL,\n    0xed3498beL\n    ,\n    0x00000000L, 0x6567bcb8L, 0x8bc809aaL, 0xeeafb512L, 0x5797628fL,\n    0x32f0de37L, 0xdc5f6b25L, 0xb938d79dL, 0xef28b4c5L, 0x8a4f087dL,\n    0x64e0bd6fL, 0x018701d7L, 0xb8bfd64aL, 0xddd86af2L, 0x3377dfe0L,\n    0x56106358L, 0x9f571950L, 0xfa30a5e8L, 0x149f10faL, 0x71f8ac42L,\n    0xc8c07bdfL, 0xada7c767L, 0x43087275L, 0x266fcecdL, 0x707fad95L,\n    0x1518112dL, 0xfbb7a43fL, 0x9ed01887L, 0x27e8cf1aL, 0x428f73a2L,\n    0xac20c6b0L, 0xc9477a08L, 0x3eaf32a0L, 0x5bc88e18L, 0xb5673b0aL,\n    0xd00087b2L, 0x6938502fL, 0x0c5fec97L, 0xe2f05985L, 0x8797e53dL,\n    0xd1878665L, 0xb4e03addL, 0x5a4f8fcfL, 0x3f283377L, 0x8610e4eaL,\n    0xe3775852L, 0x0dd8ed40L, 0x68bf51f8L, 0xa1f82bf0L, 0xc49f9748L,\n    0x2a30225aL, 0x4f579ee2L, 0xf66f497fL, 0x9308f5c7L, 0x7da740d5L,\n    0x18c0fc6dL, 0x4ed09f35L, 0x2bb7238dL, 0xc518969fL, 0xa07f2a27L,\n    0x1947fdbaL, 0x7c204102L, 0x928ff410L, 0xf7e848a8L, 0x3d58149bL,\n    0x583fa823L, 0xb6901d31L, 0xd3f7a189L, 0x6acf7614L, 0x0fa8caacL,\n    0xe1077fbeL, 0x8460c306L, 0xd270a05eL, 0xb7171ce6L, 0x59b8a9f4L,\n    0x3cdf154cL, 0x85e7c2d1L, 0xe0807e69L, 0x0e2fcb7bL, 0x6b4877c3L,\n    0xa20f0dcbL, 0xc768b173L, 0x29c70461L, 0x4ca0b8d9L, 0xf5986f44L,\n    0x90ffd3fcL, 0x7e5066eeL, 0x1b37da56L, 0x4d27b90eL, 0x284005b6L,\n    0xc6efb0a4L, 0xa3880c1cL, 0x1ab0db81L, 0x7fd76739L, 0x9178d22bL,\n    0xf41f6e93L, 0x03f7263bL, 0x66909a83L, 0x883f2f91L, 0xed589329L,\n    0x546044b4L, 0x3107f80cL, 0xdfa84d1eL, 0xbacff1a6L, 0xecdf92feL,\n    0x89b82e46L, 0x67179b54L, 0x027027ecL, 0xbb48f071L, 0xde2f4cc9L,\n    0x3080f9dbL, 0x55e74563L, 0x9ca03f6bL, 0xf9c783d3L, 0x176836c1L,\n    0x720f8a79L, 0xcb375de4L, 0xae50e15cL, 0x40ff544eL, 0x2598e8f6L,\n    0x73888baeL, 0x16ef3716L, 0xf8408204L, 0x9d273ebcL, 0x241fe921L,\n    0x41785599L, 0xafd7e08bL, 0xcab05c33L, 0x3bb659edL, 0x5ed1e555L,\n    0xb07e5047L, 0xd519ecffL, 0x6c213b62L, 0x094687daL, 0xe7e932c8L,\n    0x828e8e70L, 0xd49eed28L, 0xb1f95190L, 0x5f56e482L, 0x3a31583aL,\n    0x83098fa7L, 0xe66e331fL, 0x08c1860dL, 0x6da63ab5L, 0xa4e140bdL,\n    0xc186fc05L, 0x2f294917L, 0x4a4ef5afL, 0xf3762232L, 0x96119e8aL,\n    0x78be2b98L, 0x1dd99720L, 0x4bc9f478L, 0x2eae48c0L, 0xc001fdd2L,\n    0xa566416aL, 0x1c5e96f7L, 0x79392a4fL, 0x97969f5dL, 0xf2f123e5L,\n    0x05196b4dL, 0x607ed7f5L, 0x8ed162e7L, 0xebb6de5fL, 0x528e09c2L,\n    0x37e9b57aL, 0xd9460068L, 0xbc21bcd0L, 0xea31df88L, 0x8f566330L,\n    0x61f9d622L, 0x049e6a9aL, 0xbda6bd07L, 0xd8c101bfL, 0x366eb4adL,\n    0x53090815L, 0x9a4e721dL, 0xff29cea5L, 0x11867bb7L, 0x74e1c70fL,\n    0xcdd91092L, 0xa8beac2aL, 0x46111938L, 0x2376a580L, 0x7566c6d8L,\n    0x10017a60L, 0xfeaecf72L, 0x9bc973caL, 0x22f1a457L, 0x479618efL,\n    0xa939adfdL, 0xcc5e1145L, 0x06ee4d76L, 0x6389f1ceL, 0x8d2644dcL,\n    0xe841f864L, 0x51792ff9L, 0x341e9341L, 0xdab12653L, 0xbfd69aebL,\n    0xe9c6f9b3L, 0x8ca1450bL, 0x620ef019L, 0x07694ca1L, 0xbe519b3cL,\n    0xdb362784L, 0x35999296L, 0x50fe2e2eL, 0x99b95426L, 0xfcdee89eL,\n    0x12715d8cL, 0x7716e134L, 0xce2e36a9L, 0xab498a11L, 0x45e63f03L,\n    0x208183bbL, 0x7691e0e3L, 0x13f65c5bL, 0xfd59e949L, 0x983e55f1L,\n    0x2106826cL, 0x44613ed4L, 0xaace8bc6L, 0xcfa9377eL, 0x38417fd6L,\n    0x5d26c36eL, 0xb389767cL, 0xd6eecac4L, 0x6fd61d59L, 0x0ab1a1e1L,\n    0xe41e14f3L, 0x8179a84bL, 0xd769cb13L, 0xb20e77abL, 0x5ca1c2b9L,\n    0x39c67e01L, 0x80fea99cL, 0xe5991524L, 0x0b36a036L, 0x6e511c8eL,\n    0xa7166686L, 0xc271da3eL, 0x2cde6f2cL, 0x49b9d394L, 0xf0810409L,\n    0x95e6b8b1L, 0x7b490da3L, 0x1e2eb11bL, 0x483ed243L, 0x2d596efbL,\n    0xc3f6dbe9L, 0xa6916751L, 0x1fa9b0ccL, 0x7ace0c74L, 0x9461b966L,\n    0xf10605deL\n#  endif /* IZ_CRCOPTIM_UNFOLDTBL */\n# else /* !IZ_CRC_BE_OPTIMIZ */\n    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,\n    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,\n    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,\n    0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,\n    0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,\n    0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,\n    0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,\n    0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,\n    0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,\n    0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,\n    0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,\n    0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,\n    0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,\n    0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,\n    0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,\n    0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,\n    0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,\n    0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,\n    0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,\n    0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,\n    0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,\n    0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,\n    0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,\n    0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,\n    0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,\n    0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,\n    0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,\n    0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,\n    0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,\n    0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,\n    0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,\n    0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,\n    0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,\n    0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,\n    0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,\n    0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,\n    0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,\n    0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,\n    0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,\n    0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,\n    0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,\n    0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,\n    0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,\n    0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,\n    0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,\n    0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,\n    0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,\n    0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,\n    0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,\n    0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,\n    0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,\n    0x2d02ef8dL\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n    ,\n    0x00000000L, 0x191b3141L, 0x32366282L, 0x2b2d53c3L, 0x646cc504L,\n    0x7d77f445L, 0x565aa786L, 0x4f4196c7L, 0xc8d98a08L, 0xd1c2bb49L,\n    0xfaefe88aL, 0xe3f4d9cbL, 0xacb54f0cL, 0xb5ae7e4dL, 0x9e832d8eL,\n    0x87981ccfL, 0x4ac21251L, 0x53d92310L, 0x78f470d3L, 0x61ef4192L,\n    0x2eaed755L, 0x37b5e614L, 0x1c98b5d7L, 0x05838496L, 0x821b9859L,\n    0x9b00a918L, 0xb02dfadbL, 0xa936cb9aL, 0xe6775d5dL, 0xff6c6c1cL,\n    0xd4413fdfL, 0xcd5a0e9eL, 0x958424a2L, 0x8c9f15e3L, 0xa7b24620L,\n    0xbea97761L, 0xf1e8e1a6L, 0xe8f3d0e7L, 0xc3de8324L, 0xdac5b265L,\n    0x5d5daeaaL, 0x44469febL, 0x6f6bcc28L, 0x7670fd69L, 0x39316baeL,\n    0x202a5aefL, 0x0b07092cL, 0x121c386dL, 0xdf4636f3L, 0xc65d07b2L,\n    0xed705471L, 0xf46b6530L, 0xbb2af3f7L, 0xa231c2b6L, 0x891c9175L,\n    0x9007a034L, 0x179fbcfbL, 0x0e848dbaL, 0x25a9de79L, 0x3cb2ef38L,\n    0x73f379ffL, 0x6ae848beL, 0x41c51b7dL, 0x58de2a3cL, 0xf0794f05L,\n    0xe9627e44L, 0xc24f2d87L, 0xdb541cc6L, 0x94158a01L, 0x8d0ebb40L,\n    0xa623e883L, 0xbf38d9c2L, 0x38a0c50dL, 0x21bbf44cL, 0x0a96a78fL,\n    0x138d96ceL, 0x5ccc0009L, 0x45d73148L, 0x6efa628bL, 0x77e153caL,\n    0xbabb5d54L, 0xa3a06c15L, 0x888d3fd6L, 0x91960e97L, 0xded79850L,\n    0xc7cca911L, 0xece1fad2L, 0xf5facb93L, 0x7262d75cL, 0x6b79e61dL,\n    0x4054b5deL, 0x594f849fL, 0x160e1258L, 0x0f152319L, 0x243870daL,\n    0x3d23419bL, 0x65fd6ba7L, 0x7ce65ae6L, 0x57cb0925L, 0x4ed03864L,\n    0x0191aea3L, 0x188a9fe2L, 0x33a7cc21L, 0x2abcfd60L, 0xad24e1afL,\n    0xb43fd0eeL, 0x9f12832dL, 0x8609b26cL, 0xc94824abL, 0xd05315eaL,\n    0xfb7e4629L, 0xe2657768L, 0x2f3f79f6L, 0x362448b7L, 0x1d091b74L,\n    0x04122a35L, 0x4b53bcf2L, 0x52488db3L, 0x7965de70L, 0x607eef31L,\n    0xe7e6f3feL, 0xfefdc2bfL, 0xd5d0917cL, 0xcccba03dL, 0x838a36faL,\n    0x9a9107bbL, 0xb1bc5478L, 0xa8a76539L, 0x3b83984bL, 0x2298a90aL,\n    0x09b5fac9L, 0x10aecb88L, 0x5fef5d4fL, 0x46f46c0eL, 0x6dd93fcdL,\n    0x74c20e8cL, 0xf35a1243L, 0xea412302L, 0xc16c70c1L, 0xd8774180L,\n    0x9736d747L, 0x8e2de606L, 0xa500b5c5L, 0xbc1b8484L, 0x71418a1aL,\n    0x685abb5bL, 0x4377e898L, 0x5a6cd9d9L, 0x152d4f1eL, 0x0c367e5fL,\n    0x271b2d9cL, 0x3e001cddL, 0xb9980012L, 0xa0833153L, 0x8bae6290L,\n    0x92b553d1L, 0xddf4c516L, 0xc4eff457L, 0xefc2a794L, 0xf6d996d5L,\n    0xae07bce9L, 0xb71c8da8L, 0x9c31de6bL, 0x852aef2aL, 0xca6b79edL,\n    0xd37048acL, 0xf85d1b6fL, 0xe1462a2eL, 0x66de36e1L, 0x7fc507a0L,\n    0x54e85463L, 0x4df36522L, 0x02b2f3e5L, 0x1ba9c2a4L, 0x30849167L,\n    0x299fa026L, 0xe4c5aeb8L, 0xfdde9ff9L, 0xd6f3cc3aL, 0xcfe8fd7bL,\n    0x80a96bbcL, 0x99b25afdL, 0xb29f093eL, 0xab84387fL, 0x2c1c24b0L,\n    0x350715f1L, 0x1e2a4632L, 0x07317773L, 0x4870e1b4L, 0x516bd0f5L,\n    0x7a468336L, 0x635db277L, 0xcbfad74eL, 0xd2e1e60fL, 0xf9ccb5ccL,\n    0xe0d7848dL, 0xaf96124aL, 0xb68d230bL, 0x9da070c8L, 0x84bb4189L,\n    0x03235d46L, 0x1a386c07L, 0x31153fc4L, 0x280e0e85L, 0x674f9842L,\n    0x7e54a903L, 0x5579fac0L, 0x4c62cb81L, 0x8138c51fL, 0x9823f45eL,\n    0xb30ea79dL, 0xaa1596dcL, 0xe554001bL, 0xfc4f315aL, 0xd7626299L,\n    0xce7953d8L, 0x49e14f17L, 0x50fa7e56L, 0x7bd72d95L, 0x62cc1cd4L,\n    0x2d8d8a13L, 0x3496bb52L, 0x1fbbe891L, 0x06a0d9d0L, 0x5e7ef3ecL,\n    0x4765c2adL, 0x6c48916eL, 0x7553a02fL, 0x3a1236e8L, 0x230907a9L,\n    0x0824546aL, 0x113f652bL, 0x96a779e4L, 0x8fbc48a5L, 0xa4911b66L,\n    0xbd8a2a27L, 0xf2cbbce0L, 0xebd08da1L, 0xc0fdde62L, 0xd9e6ef23L,\n    0x14bce1bdL, 0x0da7d0fcL, 0x268a833fL, 0x3f91b27eL, 0x70d024b9L,\n    0x69cb15f8L, 0x42e6463bL, 0x5bfd777aL, 0xdc656bb5L, 0xc57e5af4L,\n    0xee530937L, 0xf7483876L, 0xb809aeb1L, 0xa1129ff0L, 0x8a3fcc33L,\n    0x9324fd72L\n    ,\n    0x00000000L, 0x01c26a37L, 0x0384d46eL, 0x0246be59L, 0x0709a8dcL,\n    0x06cbc2ebL, 0x048d7cb2L, 0x054f1685L, 0x0e1351b8L, 0x0fd13b8fL,\n    0x0d9785d6L, 0x0c55efe1L, 0x091af964L, 0x08d89353L, 0x0a9e2d0aL,\n    0x0b5c473dL, 0x1c26a370L, 0x1de4c947L, 0x1fa2771eL, 0x1e601d29L,\n    0x1b2f0bacL, 0x1aed619bL, 0x18abdfc2L, 0x1969b5f5L, 0x1235f2c8L,\n    0x13f798ffL, 0x11b126a6L, 0x10734c91L, 0x153c5a14L, 0x14fe3023L,\n    0x16b88e7aL, 0x177ae44dL, 0x384d46e0L, 0x398f2cd7L, 0x3bc9928eL,\n    0x3a0bf8b9L, 0x3f44ee3cL, 0x3e86840bL, 0x3cc03a52L, 0x3d025065L,\n    0x365e1758L, 0x379c7d6fL, 0x35dac336L, 0x3418a901L, 0x3157bf84L,\n    0x3095d5b3L, 0x32d36beaL, 0x331101ddL, 0x246be590L, 0x25a98fa7L,\n    0x27ef31feL, 0x262d5bc9L, 0x23624d4cL, 0x22a0277bL, 0x20e69922L,\n    0x2124f315L, 0x2a78b428L, 0x2bbade1fL, 0x29fc6046L, 0x283e0a71L,\n    0x2d711cf4L, 0x2cb376c3L, 0x2ef5c89aL, 0x2f37a2adL, 0x709a8dc0L,\n    0x7158e7f7L, 0x731e59aeL, 0x72dc3399L, 0x7793251cL, 0x76514f2bL,\n    0x7417f172L, 0x75d59b45L, 0x7e89dc78L, 0x7f4bb64fL, 0x7d0d0816L,\n    0x7ccf6221L, 0x798074a4L, 0x78421e93L, 0x7a04a0caL, 0x7bc6cafdL,\n    0x6cbc2eb0L, 0x6d7e4487L, 0x6f38fadeL, 0x6efa90e9L, 0x6bb5866cL,\n    0x6a77ec5bL, 0x68315202L, 0x69f33835L, 0x62af7f08L, 0x636d153fL,\n    0x612bab66L, 0x60e9c151L, 0x65a6d7d4L, 0x6464bde3L, 0x662203baL,\n    0x67e0698dL, 0x48d7cb20L, 0x4915a117L, 0x4b531f4eL, 0x4a917579L,\n    0x4fde63fcL, 0x4e1c09cbL, 0x4c5ab792L, 0x4d98dda5L, 0x46c49a98L,\n    0x4706f0afL, 0x45404ef6L, 0x448224c1L, 0x41cd3244L, 0x400f5873L,\n    0x4249e62aL, 0x438b8c1dL, 0x54f16850L, 0x55330267L, 0x5775bc3eL,\n    0x56b7d609L, 0x53f8c08cL, 0x523aaabbL, 0x507c14e2L, 0x51be7ed5L,\n    0x5ae239e8L, 0x5b2053dfL, 0x5966ed86L, 0x58a487b1L, 0x5deb9134L,\n    0x5c29fb03L, 0x5e6f455aL, 0x5fad2f6dL, 0xe1351b80L, 0xe0f771b7L,\n    0xe2b1cfeeL, 0xe373a5d9L, 0xe63cb35cL, 0xe7fed96bL, 0xe5b86732L,\n    0xe47a0d05L, 0xef264a38L, 0xeee4200fL, 0xeca29e56L, 0xed60f461L,\n    0xe82fe2e4L, 0xe9ed88d3L, 0xebab368aL, 0xea695cbdL, 0xfd13b8f0L,\n    0xfcd1d2c7L, 0xfe976c9eL, 0xff5506a9L, 0xfa1a102cL, 0xfbd87a1bL,\n    0xf99ec442L, 0xf85cae75L, 0xf300e948L, 0xf2c2837fL, 0xf0843d26L,\n    0xf1465711L, 0xf4094194L, 0xf5cb2ba3L, 0xf78d95faL, 0xf64fffcdL,\n    0xd9785d60L, 0xd8ba3757L, 0xdafc890eL, 0xdb3ee339L, 0xde71f5bcL,\n    0xdfb39f8bL, 0xddf521d2L, 0xdc374be5L, 0xd76b0cd8L, 0xd6a966efL,\n    0xd4efd8b6L, 0xd52db281L, 0xd062a404L, 0xd1a0ce33L, 0xd3e6706aL,\n    0xd2241a5dL, 0xc55efe10L, 0xc49c9427L, 0xc6da2a7eL, 0xc7184049L,\n    0xc25756ccL, 0xc3953cfbL, 0xc1d382a2L, 0xc011e895L, 0xcb4dafa8L,\n    0xca8fc59fL, 0xc8c97bc6L, 0xc90b11f1L, 0xcc440774L, 0xcd866d43L,\n    0xcfc0d31aL, 0xce02b92dL, 0x91af9640L, 0x906dfc77L, 0x922b422eL,\n    0x93e92819L, 0x96a63e9cL, 0x976454abL, 0x9522eaf2L, 0x94e080c5L,\n    0x9fbcc7f8L, 0x9e7eadcfL, 0x9c381396L, 0x9dfa79a1L, 0x98b56f24L,\n    0x99770513L, 0x9b31bb4aL, 0x9af3d17dL, 0x8d893530L, 0x8c4b5f07L,\n    0x8e0de15eL, 0x8fcf8b69L, 0x8a809decL, 0x8b42f7dbL, 0x89044982L,\n    0x88c623b5L, 0x839a6488L, 0x82580ebfL, 0x801eb0e6L, 0x81dcdad1L,\n    0x8493cc54L, 0x8551a663L, 0x8717183aL, 0x86d5720dL, 0xa9e2d0a0L,\n    0xa820ba97L, 0xaa6604ceL, 0xaba46ef9L, 0xaeeb787cL, 0xaf29124bL,\n    0xad6fac12L, 0xacadc625L, 0xa7f18118L, 0xa633eb2fL, 0xa4755576L,\n    0xa5b73f41L, 0xa0f829c4L, 0xa13a43f3L, 0xa37cfdaaL, 0xa2be979dL,\n    0xb5c473d0L, 0xb40619e7L, 0xb640a7beL, 0xb782cd89L, 0xb2cddb0cL,\n    0xb30fb13bL, 0xb1490f62L, 0xb08b6555L, 0xbbd72268L, 0xba15485fL,\n    0xb853f606L, 0xb9919c31L, 0xbcde8ab4L, 0xbd1ce083L, 0xbf5a5edaL,\n    0xbe9834edL\n   ,\n    0x00000000L, 0xb8bc6765L, 0xaa09c88bL, 0x12b5afeeL, 0x8f629757L,\n    0x37def032L, 0x256b5fdcL, 0x9dd738b9L, 0xc5b428efL, 0x7d084f8aL,\n    0x6fbde064L, 0xd7018701L, 0x4ad6bfb8L, 0xf26ad8ddL, 0xe0df7733L,\n    0x58631056L, 0x5019579fL, 0xe8a530faL, 0xfa109f14L, 0x42acf871L,\n    0xdf7bc0c8L, 0x67c7a7adL, 0x75720843L, 0xcdce6f26L, 0x95ad7f70L,\n    0x2d111815L, 0x3fa4b7fbL, 0x8718d09eL, 0x1acfe827L, 0xa2738f42L,\n    0xb0c620acL, 0x087a47c9L, 0xa032af3eL, 0x188ec85bL, 0x0a3b67b5L,\n    0xb28700d0L, 0x2f503869L, 0x97ec5f0cL, 0x8559f0e2L, 0x3de59787L,\n    0x658687d1L, 0xdd3ae0b4L, 0xcf8f4f5aL, 0x7733283fL, 0xeae41086L,\n    0x525877e3L, 0x40edd80dL, 0xf851bf68L, 0xf02bf8a1L, 0x48979fc4L,\n    0x5a22302aL, 0xe29e574fL, 0x7f496ff6L, 0xc7f50893L, 0xd540a77dL,\n    0x6dfcc018L, 0x359fd04eL, 0x8d23b72bL, 0x9f9618c5L, 0x272a7fa0L,\n    0xbafd4719L, 0x0241207cL, 0x10f48f92L, 0xa848e8f7L, 0x9b14583dL,\n    0x23a83f58L, 0x311d90b6L, 0x89a1f7d3L, 0x1476cf6aL, 0xaccaa80fL,\n    0xbe7f07e1L, 0x06c36084L, 0x5ea070d2L, 0xe61c17b7L, 0xf4a9b859L,\n    0x4c15df3cL, 0xd1c2e785L, 0x697e80e0L, 0x7bcb2f0eL, 0xc377486bL,\n    0xcb0d0fa2L, 0x73b168c7L, 0x6104c729L, 0xd9b8a04cL, 0x446f98f5L,\n    0xfcd3ff90L, 0xee66507eL, 0x56da371bL, 0x0eb9274dL, 0xb6054028L,\n    0xa4b0efc6L, 0x1c0c88a3L, 0x81dbb01aL, 0x3967d77fL, 0x2bd27891L,\n    0x936e1ff4L, 0x3b26f703L, 0x839a9066L, 0x912f3f88L, 0x299358edL,\n    0xb4446054L, 0x0cf80731L, 0x1e4da8dfL, 0xa6f1cfbaL, 0xfe92dfecL,\n    0x462eb889L, 0x549b1767L, 0xec277002L, 0x71f048bbL, 0xc94c2fdeL,\n    0xdbf98030L, 0x6345e755L, 0x6b3fa09cL, 0xd383c7f9L, 0xc1366817L,\n    0x798a0f72L, 0xe45d37cbL, 0x5ce150aeL, 0x4e54ff40L, 0xf6e89825L,\n    0xae8b8873L, 0x1637ef16L, 0x048240f8L, 0xbc3e279dL, 0x21e91f24L,\n    0x99557841L, 0x8be0d7afL, 0x335cb0caL, 0xed59b63bL, 0x55e5d15eL,\n    0x47507eb0L, 0xffec19d5L, 0x623b216cL, 0xda874609L, 0xc832e9e7L,\n    0x708e8e82L, 0x28ed9ed4L, 0x9051f9b1L, 0x82e4565fL, 0x3a58313aL,\n    0xa78f0983L, 0x1f336ee6L, 0x0d86c108L, 0xb53aa66dL, 0xbd40e1a4L,\n    0x05fc86c1L, 0x1749292fL, 0xaff54e4aL, 0x322276f3L, 0x8a9e1196L,\n    0x982bbe78L, 0x2097d91dL, 0x78f4c94bL, 0xc048ae2eL, 0xd2fd01c0L,\n    0x6a4166a5L, 0xf7965e1cL, 0x4f2a3979L, 0x5d9f9697L, 0xe523f1f2L,\n    0x4d6b1905L, 0xf5d77e60L, 0xe762d18eL, 0x5fdeb6ebL, 0xc2098e52L,\n    0x7ab5e937L, 0x680046d9L, 0xd0bc21bcL, 0x88df31eaL, 0x3063568fL,\n    0x22d6f961L, 0x9a6a9e04L, 0x07bda6bdL, 0xbf01c1d8L, 0xadb46e36L,\n    0x15080953L, 0x1d724e9aL, 0xa5ce29ffL, 0xb77b8611L, 0x0fc7e174L,\n    0x9210d9cdL, 0x2aacbea8L, 0x38191146L, 0x80a57623L, 0xd8c66675L,\n    0x607a0110L, 0x72cfaefeL, 0xca73c99bL, 0x57a4f122L, 0xef189647L,\n    0xfdad39a9L, 0x45115eccL, 0x764dee06L, 0xcef18963L, 0xdc44268dL,\n    0x64f841e8L, 0xf92f7951L, 0x41931e34L, 0x5326b1daL, 0xeb9ad6bfL,\n    0xb3f9c6e9L, 0x0b45a18cL, 0x19f00e62L, 0xa14c6907L, 0x3c9b51beL,\n    0x842736dbL, 0x96929935L, 0x2e2efe50L, 0x2654b999L, 0x9ee8defcL,\n    0x8c5d7112L, 0x34e11677L, 0xa9362eceL, 0x118a49abL, 0x033fe645L,\n    0xbb838120L, 0xe3e09176L, 0x5b5cf613L, 0x49e959fdL, 0xf1553e98L,\n    0x6c820621L, 0xd43e6144L, 0xc68bceaaL, 0x7e37a9cfL, 0xd67f4138L,\n    0x6ec3265dL, 0x7c7689b3L, 0xc4caeed6L, 0x591dd66fL, 0xe1a1b10aL,\n    0xf3141ee4L, 0x4ba87981L, 0x13cb69d7L, 0xab770eb2L, 0xb9c2a15cL,\n    0x017ec639L, 0x9ca9fe80L, 0x241599e5L, 0x36a0360bL, 0x8e1c516eL,\n    0x866616a7L, 0x3eda71c2L, 0x2c6fde2cL, 0x94d3b949L, 0x090481f0L,\n    0xb1b8e695L, 0xa30d497bL, 0x1bb12e1eL, 0x43d23e48L, 0xfb6e592dL,\n    0xe9dbf6c3L, 0x516791a6L, 0xccb0a91fL, 0x740cce7aL, 0x66b96194L,\n    0xde0506f1L\n#  endif /* IZ_CRCOPTIM_UNFOLDTBL */\n# endif /* ? IZ_CRC_BE_OPTIMIZ */\n};\n#endif /* ?DYNAMIC_CRC_TABLE */\n\n/* use \"OF((void))\" here to work around a Borland TC++ 1.0 problem */\n#ifdef USE_ZLIB\nZCONST uLongf *get_crc_table OF((void))\n#else\nZCONST ulg near *get_crc_table OF((void))\n#endif\n{\n#ifdef DYNAMIC_CRC_TABLE\n  if (CRC_TABLE_IS_EMPTY)\n    make_crc_table();\n#endif\n#ifdef USE_ZLIB\n  return (ZCONST uLongf *)crc_table;\n#else\n  return crc_table;\n#endif\n}\n\n#ifdef DYNALLOC_CRCTAB\nvoid free_crc_table()\n{\n  if (!CRC_TABLE_IS_EMPTY)\n  {\n    nearfree((ulg near *)crc_table);\n    MARK_CRCTAB_EMPTY;\n  }\n}\n#endif\n\n#ifndef USE_ZLIB\n#ifndef CRC_TABLE_ONLY\n#ifndef ASM_CRC\n\n#define DO1(crc, buf)  crc = CRC32(crc, *buf++, crc_32_tab)\n#define DO2(crc, buf)  DO1(crc, buf); DO1(crc, buf)\n#define DO4(crc, buf)  DO2(crc, buf); DO2(crc, buf)\n#define DO8(crc, buf)  DO4(crc, buf); DO4(crc, buf)\n\n#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ))\n\n# ifdef IZ_CRCOPTIM_UNFOLDTBL\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n        c = crc_32_tab[c & 0xff] ^ crc_32_tab[256+((c>>8) & 0xff)] ^ \\\n            crc_32_tab[2*256+((c>>16) & 0xff)] ^ crc_32_tab[3*256+(c>>24)]\n#  else /* !IZ_CRC_BE_OPTIMIZ */\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n        c = crc_32_tab[3*256+(c & 0xff)] ^ crc_32_tab[2*256+((c>>8) & 0xff)] \\\n           ^ crc_32_tab[256+((c>>16) & 0xff)] ^ crc_32_tab[c>>24]\n#  endif /* ?IZ_CRC_BE_OPTIMIZ */\n# else /* !IZ_CRCOPTIM_UNFOLDTBL */\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab)\n# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n\n# define DO_OPT16(crc, buf4) DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); \\\n                             DO_OPT4(crc, buf4); DO_OPT4(crc, buf4);\n\n#endif /* (IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n\n\n/* ========================================================================= */\nulg crc32(crc, buf, len)\n    ulg crc;                    /* crc shift register */\n    register ZCONST uch *buf;   /* pointer to bytes to pump through */\n    extent len;                 /* number of bytes in buf[] */\n/* Run a set of bytes through the crc shift register.  If buf is a NULL\n   pointer, then initialize the crc shift register contents instead.\n   Return the current crc in either case. */\n{\n  register z_uint4 c;\n  register ZCONST ulg near *crc_32_tab;\n\n  if (buf == NULL) return 0L;\n\n  crc_32_tab = get_crc_table();\n\n  c = (REV_BE((z_uint4)crc) ^ 0xffffffffL);\n\n#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ))\n  /* Align buf pointer to next DWORD boundary. */\n  while (len && ((ptrdiff_t)buf & 3)) {\n    DO1(c, buf);\n    len--;\n  }\n  {\n    ZCONST z_uint4 *buf4 = (ZCONST z_uint4 *)buf;\n    while (len >= 16) {\n      DO_OPT16(c, buf4);\n      len -= 16;\n    }\n    while (len >= 4) {\n      DO_OPT4(c, buf4);\n      len -= 4;\n    }\n    buf = (ZCONST uch *)buf4;\n  }\n#else /* !(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n#ifndef NO_UNROLLED_LOOPS\n  while (len >= 8) {\n    DO8(c, buf);\n    len -= 8;\n  }\n#endif /* !NO_UNROLLED_LOOPS */\n#endif /* ?(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n  if (len) do {\n    DO1(c, buf);\n  } while (--len);\n\n  return REV_BE(c) ^ 0xffffffffL;   /* (instead of ~c for 64-bit machines) */\n}\n#endif /* !ASM_CRC */\n#endif /* !CRC_TABLE_ONLY */\n#endif /* !USE_ZLIB */\n#endif /* !USE_ZLIB || USE_OWN_CRCTAB */\n"
  },
  {
    "path": "deps/infozip/unzip60/crc32.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc32.h -- compute the CRC-32 of a data stream\n * Copyright (C) 1995 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#ifndef __crc32_h\n#define __crc32_h       /* identifies this source module */\n\n/* This header should be read AFTER zip.h resp. unzip.h\n * (the latter with UNZIP_INTERNAL defined...).\n */\n\n#ifndef OF\n#  define OF(a) a\n#endif\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#ifdef DYNALLOC_CRCTAB\n   void     free_crc_table  OF((void));\n#endif\n#ifndef USE_ZLIB\n   ZCONST ulg near *get_crc_table  OF((void));\n#endif\n#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    undef IZ_CRC_BE_OPTIMIZ\n#  endif\n#else /* !(USE_ZLIB || CRC_TABLE_ONLY) */\n   ulg      crc32           OF((ulg crc, ZCONST uch *buf, extent len));\n#endif /* ?(USE_ZLIB || CRC_TABLE_ONLY) */\n\n#ifndef CRC_32_TAB\n#  define CRC_32_TAB     crc_32_tab\n#endif\n\n#ifdef CRC32\n#  undef CRC32\n#endif\n#ifdef IZ_CRC_BE_OPTIMIZ\n#  define CRC32UPD(c, crctab) (crctab[((c) >> 24)] ^ ((c) << 8))\n#  define CRC32(c, b, crctab) (crctab[(((int)(c) >> 24) ^ (b))] ^ ((c) << 8))\n#  define REV_BE(w) (((w)>>24)+(((w)>>8)&0xff00)+ \\\n                    (((w)&0xff00)<<8)+(((w)&0xff)<<24))\n#else\n#  define CRC32UPD(c, crctab) (crctab[((int)(c)) & 0xff] ^ ((c) >> 8))\n#  define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))\n#  define REV_BE(w) w\n#endif\n\n#endif /* !__crc32_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/crc_i386.S",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * crc_i386.S, optimized CRC calculation function for Zip and UnZip,\n * created by Paul Kienitz and Christian Spieler.  Last revised 07 Jan 2007.\n *\n * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm\n *              => overall 6% speedup in \"unzip -tq\" on 9MB zipfile (486-66)\n *\n * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide\n *              aligned reads for most of the data from buffer), can be\n *              disabled by defining the macro NO_32_BIT_LOADS\n *\n * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized\n *              CPUs (like the Pentium Pro, Pentium II, and probably some\n *              Pentium clones). This optimization is controlled by the\n *              preprocessor switch \"__686\" and is disabled by default.\n *              (This default is based on the assumption that most users\n *              do not yet work on a Pentium Pro or Pentium II machine ...)\n *\n * COS 050116:  Enabled the 686 build by default, because there are hardly any\n *              pre-686 CPUs in serious use nowadays. (See SPC 970402 above.)\n *\n * SPC 060103:  Updated code to incorporate newer optimizations found in zlib.\n *\n * SPC 070107:  Added conditional switch to deactivate crc32() compilation.\n *\n * FLAT memory model assumed.  Calling interface:\n *   - args are pushed onto the stack from right to left,\n *   - return value is given in the EAX register,\n *   - all other registers (with exception of EFLAGS) are preserved. (With\n *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving\n *     them nevertheless adds only 4 single byte instructions.)\n *\n * This source generates the function\n * ulg crc32(ulg crc, ZCONST uch *buf, extent len).\n *\n * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n * This results in shorter code at the expense of reduced performance.\n */\n\n/* This file is NOT used in conjunction with zlib, or when only creation of\n * the basic CRC_32_Table (for other purpose) is requested.\n */\n#if !defined(USE_ZLIB) && !defined(CRC_TABLE_ONLY)\n\n/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix\n * external symbols with an underline character '_'.\n */\n#if defined(NO_UNDERLINE) || defined(__ELF__)\n#  define _crc32            crc32\n#  define _get_crc_table    get_crc_table\n#endif\n/* Use 16-byte alignment if your assembler supports it. Warning: gas\n * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4\n * the parameter is a number of bytes.\n */\n#ifndef ALIGNMENT\n#  define ALIGNMENT .align 4,0x90\n#endif\n\n#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)\n\n/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).\n * Warning: it uses the AT&T syntax: mov source,dest\n * This file is only optional. If you want to use the C version,\n * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.\n */\n\n                .file   \"crc_i386.S\"\n\n#if !defined(PRE_686) && !defined(__686)\n   /* Optimize for Pentium Pro and compatible CPUs by default. */\n#  define __686\n#endif\n\n#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)\n#  undef USE_STACKFRAME\n#else\n   /* The default is to use standard stack frame entry, because it\n    * results in smaller code!\n    */\n#  ifndef USE_STD_STACKFRAME\n#    define USE_STD_STACKFRAME\n#  endif\n#endif\n\n#ifdef USE_STD_STACKFRAME\n#  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp\n#  define arg1  8(%ebp)\n#  define arg2  12(%ebp)\n#  define arg3  16(%ebp)\n#  define _STD_LEAVE    popl    %ebp\n#else /* !USE_STD_STACKFRAME */\n#  define _STD_ENTRY\n#  define arg1  24(%esp)\n#  define arg2  28(%esp)\n#  define arg3  32(%esp)\n#  define _STD_LEAVE\n#endif /* ?USE_STD_STACKFRAME */\n\n/*\n * These two (three) macros make up the loop body of the CRC32 cruncher.\n * registers modified:\n *   eax  : crc value \"c\"\n *   esi  : pointer to next data byte (or lword) \"buf++\"\n * registers read:\n *   edi  : pointer to base of crc_table array\n * scratch registers:\n *   ebx  : index into crc_table array\n *          (requires upper three bytes = 0 when __686 is undefined)\n */\n#ifndef __686   /* optimize for 386, 486, Pentium */\n#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\\\n                movb    %al, %bl                ;/* tmp = c & 0xFF  */\\\n                shrl    $8, %eax                ;/* c = (c >> 8)    */\\\n                xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */\n#else   /* __686 : optimize for Pentium Pro and compatible CPUs */\n#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\\\n                movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */\\\n                shrl    $8, %eax                ;/* c = (c >> 8)    */\\\n                xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */\n#endif  /* ?__686 */\n\n#define Do_CRC_byte             /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\\\n                xorb    (%esi), %al     ;/* c ^= *buf  */\\\n                incl    %esi            ;/* buf++      */\\\n                Do_CRC\n\n#define Do_CRC_byteof(ofs)      /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\\\n                xorb    ofs(%esi), %al  ;/* c ^= *buf  */\\\n                incl    %esi            ;/* buf++      */\\\n                Do_CRC\n\n#ifndef  NO_32_BIT_LOADS\n# ifdef IZ_CRCOPTIM_UNFOLDTBL\n   /* the edx register is needed in crc calculation */\n#  define SavLen arg3\n#  define UpdCRC_lword \\\n                movzbl  %al, %ebx               ; \\\n                movl    3072(%edi,%ebx,4), %edx ; \\\n                movzbl  %ah, %ebx               ; \\\n                shrl    $16, %eax               ; \\\n                xor     2048(%edi,%ebx,4), %edx ; \\\n                movzbl  %al, %ebx               ; \\\n                shrl    $8,%eax                 ; \\\n                xorl    1024(%edi,%ebx,4), %edx ; \\\n                movl    (%edi,%eax,4), %eax     ; \\\n                xorl    %edx,%eax               ;\n#  define UpdCRC_lword_sh(dwPtrIncr) \\\n                movzbl  %al, %ebx               ; \\\n                movl    3072(%edi,%ebx,4), %edx ; \\\n                movzbl  %ah, %ebx               ; \\\n                shrl    $16, %eax               ; \\\n                xor     2048(%edi,%ebx,4), %edx ; \\\n                movzbl  %al, %ebx               ; \\\n                addl    $4*(dwPtrIncr), %esi    ;/* ((ulg *)buf)+=dwPtrIncr */\\\n                shrl    $8,%eax                 ; \\\n                xorl    1024(%edi,%ebx,4), %edx ; \\\n                movl    (%edi,%eax,4),%eax      ; \\\n                xorl    %edx,%eax               ;\n# else /* !IZ_CRCOPTIM_UNFOLDTBL */\n   /* the edx register is not needed anywhere else */\n#  define SavLen %edx\n#  define UpdCRC_lword \\\n                Do_CRC \\\n                Do_CRC \\\n                Do_CRC \\\n                Do_CRC\n#  define UpdCRC_lword_sh(dwPtrIncr) \\\n                Do_CRC \\\n                Do_CRC \\\n                addl    $4*(dwPtrIncr), %esi    ;/* ((ulg *)buf)++   */\\\n                Do_CRC \\\n                Do_CRC\n# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n#define Do_CRC_lword \\\n                xorl    (%esi), %eax           ;/* c ^= *(ulg *)buf */\\\n                UpdCRC_lword_sh(1)              /* ... ((ulg *)buf)++ */\n#define Do_CRC_4lword \\\n                xorl    (%esi), %eax           ;/* c ^= *(ulg *)buf */\\\n                UpdCRC_lword \\\n                xorl    4(%esi), %eax          ;/* c ^= *((ulg *)buf+1) */\\\n                UpdCRC_lword \\\n                xorl    8(%esi), %eax          ;/* c ^= *((ulg *)buf+2) */\\\n                UpdCRC_lword \\\n                xorl    12(%esi), %eax         ;/* c ^= *((ulg *)buf]+3 */\\\n                UpdCRC_lword_sh(4)              /* ... ((ulg *)buf)+=4 */\n#endif  /* !NO_32_BIT_LOADS */\n\n\n                .text\n\n                .globl  _crc32\n\n_crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */\n                _STD_ENTRY\n                pushl   %edi\n                pushl   %esi\n                pushl   %ebx\n                pushl   %edx\n                pushl   %ecx\n\n                movl    arg2, %esi           /* 2nd arg: uch *buf            */\n                subl    %eax, %eax           /* > if (!buf)                  */\n                testl   %esi, %esi           /* >   return 0;                */\n                jz      .L_fine              /* > else {                     */\n                call    _get_crc_table\n                movl    %eax, %edi\n                movl    arg1, %eax           /* 1st arg: ulg crc             */\n#ifndef __686\n                subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */\n#endif\n                movl    arg3, %ecx           /* 3rd arg: extent len          */\n                notl    %eax                 /* >   c = ~crc;                */\n\n                testl   %ecx, %ecx\n#ifndef  NO_UNROLLED_LOOPS\n                jz      .L_bail\n#  ifndef  NO_32_BIT_LOADS\n                /* Assert now have positive length */\n.L_align_loop:\n                testl   $3, %esi        /* Align buf on lword boundary */\n                jz      .L_aligned_now\n                Do_CRC_byte\n                decl    %ecx\n                jnz     .L_align_loop\n.L_aligned_now:\n#  endif  /* !NO_32_BIT_LOADS */\n                movl    %ecx, SavLen         /* save current value of len */\n                shrl    $4, %ecx             /* ecx = len / 16   */\n                jz      .L_No_Sixteens\n/*  align loop head at start of 486 internal cache line !! */\n                ALIGNMENT\n.L_Next_Sixteen:\n#  ifndef NO_32_BIT_LOADS\n                 Do_CRC_4lword\n#  else   /* NO_32_BIT_LOADS */\n                 Do_CRC_byteof(0)\n                 Do_CRC_byteof(1)\n                 Do_CRC_byteof(2)\n                 Do_CRC_byteof(3)\n                 Do_CRC_byteof(4)\n                 Do_CRC_byteof(5)\n                 Do_CRC_byteof(6)\n                 Do_CRC_byteof(7)\n                 Do_CRC_byteof(8)\n                 Do_CRC_byteof(9)\n                 Do_CRC_byteof(10)\n                 Do_CRC_byteof(11)\n                 Do_CRC_byteof(12)\n                 Do_CRC_byteof(13)\n                 Do_CRC_byteof(14)\n                 Do_CRC_byteof(15)\n                 addl    $16,%esi        ;/* buf += 16 */\n#  endif  /* ?NO_32_BIT_LOADS */\n                decl    %ecx\n                jnz     .L_Next_Sixteen\n\n.L_No_Sixteens:\n                movl    SavLen, %ecx\n                andl    $15, %ecx         /* ecx = len % 16   */\n# ifndef NO_32_BIT_LOADS\n                shrl    $2,%ecx           /* ecx = len / 4    */\n                jz      .L_No_Fours\n.L_Next_Four:\n                Do_CRC_lword\n                decl    %ecx\n                jnz     .L_Next_Four\n.L_No_Fours:\n                movl    SavLen,%ecx\n                andl    $3,%ecx          /* ecx = len % 4 */\n# endif /* !NO_32_BIT_LOADS */\n#endif /* !NO_UNROLLED_LOOPS */\n                jz      .L_bail          /* > if (len)                       */\n/* align loop head at start of 486 internal cache line !! */\n                ALIGNMENT\n.L_loupe:                                /* >   do {                         */\n                 Do_CRC_byte             /*       c = CRC32(c,*buf++,crctab);*/\n                decl    %ecx             /* >   } while (--len);             */\n                jnz     .L_loupe\n\n.L_bail:                                 /* > }                              */\n                notl    %eax             /* > return ~c;                     */\n.L_fine:\n                popl    %ecx\n                popl    %edx\n                popl    %ebx\n                popl    %esi\n                popl    %edi\n                _STD_LEAVE\n                ret\n\n#else\n error: this asm version is for 386 only\n#endif /* i386 || _i386 || _I386 || __i386 */\n\n#endif /* !USE_ZLIB && !CRC_TABLE_ONLY */\n"
  },
  {
    "path": "deps/infozip/unzip60/crypt.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in (un)zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]\n\n  The main encryption/decryption source code for Info-Zip software was\n  originally written in Europe.  To the best of our knowledge, it can\n  be freely distributed in both source and object forms from any country,\n  including the USA under License Exception TSU of the U.S. Export\n  Administration Regulations (section 740.13(e)) of 6 June 2002.\n\n  NOTE on copyright history:\n  Previous versions of this source package (up to version 2.8) were\n  not copyrighted and put in the public domain.  If you cannot comply\n  with the Info-Zip LICENSE, you may want to look for one of those\n  public domain versions.\n */\n\n/*\n  This encryption code is a direct transcription of the algorithm from\n  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\n  file (appnote.txt) is distributed with the PKZIP program (even in the\n  version without encryption capabilities).\n */\n\n#define ZCRYPT_INTERNAL\n#include \"zip.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n\n#if CRYPT\n\n#ifndef FALSE\n#  define FALSE 0\n#endif\n\n#ifdef ZIP\n   /* For the encoding task used in Zip (and ZipCloak), we want to initialize\n      the crypt algorithm with some reasonably unpredictable bytes, see\n      the crypthead() function. The standard rand() library function is\n      used to supply these `random' bytes, which in turn is initialized by\n      a srand() call. The srand() function takes an \"unsigned\" (at least 16bit)\n      seed value as argument to determine the starting point of the rand()\n      pseudo-random number generator.\n      This seed number is constructed as \"Seed = Seed1 .XOR. Seed2\" with\n      Seed1 supplied by the current time (= \"(unsigned)time()\") and Seed2\n      as some (hopefully) nondeterministic bitmask. On many (most) systems,\n      we use some \"process specific\" number, as the PID or something similar,\n      but when nothing unpredictable is available, a fixed number may be\n      sufficient.\n      NOTE:\n      1.) This implementation requires the availability of the following\n          standard UNIX C runtime library functions: time(), rand(), srand().\n          On systems where some of them are missing, the environment that\n          incorporates the crypt routines must supply suitable replacement\n          functions.\n      2.) It is a very bad idea to use a second call to time() to set the\n          \"Seed2\" number! In this case, both \"Seed1\" and \"Seed2\" would be\n          (almost) identical, resulting in a (mostly) \"zero\" constant seed\n          number passed to srand().\n\n      The implementation environment defined in the \"zip.h\" header should\n      supply a reasonable definition for ZCR_SEED2 (an unsigned number; for\n      most implementations of rand() and srand(), only the lower 16 bits are\n      significant!). An example that works on many systems would be\n           \"#define ZCR_SEED2  (unsigned)getpid()\".\n      The default definition for ZCR_SEED2 supplied below should be regarded\n      as a fallback to allow successful compilation in \"beta state\"\n      environments.\n    */\n#  include <time.h>     /* time() function supplies first part of crypt seed */\n   /* \"last resort\" source for second part of crypt seed pattern */\n#  ifndef ZCR_SEED2\n#    define ZCR_SEED2 (unsigned)3141592654L     /* use PI as default pattern */\n#  endif\n#  ifdef GLOBAL         /* used in Amiga system headers, maybe others too */\n#    undef GLOBAL\n#  endif\n#  define GLOBAL(g) g\n#else /* !ZIP */\n#  define GLOBAL(g) G.g\n#endif /* ?ZIP */\n\n\n#ifdef UNZIP\n   /* char *key = (char *)NULL; moved to globals.h */\n#  ifndef FUNZIP\n     local int testp OF((__GPRO__ ZCONST uch *h));\n     local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key));\n#  endif\n#endif /* UNZIP */\n\n#ifndef UNZIP             /* moved to globals.h for UnZip */\n#  ifndef Z_UINT4_DEFINED\n#   if !defined(NO_LIMITS_H)\n#    if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL))\n       typedef unsigned int     z_uint4;\n#      define Z_UINT4_DEFINED\n#    else\n#    if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL))\n       typedef unsigned long    z_uint4;\n#      define Z_UINT4_DEFINED\n#    else\n#    if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL))\n       typedef unsigned short   z_uint4;\n#      define Z_UINT4_DEFINED\n#    endif\n#    endif\n#    endif\n#   endif /* !NO_LIMITS_H */\n#  endif /* !Z_UINT4_DEFINED */\n#  ifndef Z_UINT4_DEFINED\n     typedef ulg                z_uint4;\n#    define Z_UINT4_DEFINED\n#  endif\n   local z_uint4 keys[3];       /* keys defining the pseudo-random sequence */\n#endif /* !UNZIP */\n\n#ifndef Trace\n#  ifdef CRYPT_DEBUG\n#    define Trace(x) fprintf x\n#  else\n#    define Trace(x)\n#  endif\n#endif\n\n#include \"crc32.h\"\n\n#ifdef IZ_CRC_BE_OPTIMIZ\n   local z_uint4 near crycrctab[256];\n   local z_uint4 near *cry_crctb_p = NULL;\n   local z_uint4 near *crytab_init OF((__GPRO));\n#  define CRY_CRC_TAB  cry_crctb_p\n#  undef CRC32\n#  define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))\n#else\n#  define CRY_CRC_TAB  CRC_32_TAB\n#endif /* ?IZ_CRC_BE_OPTIMIZ */\n\n/***********************************************************************\n * Return the next byte in the pseudo-random sequence\n */\nint decrypt_byte(__G)\n    __GDEF\n{\n    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an\n                     * unpredictable manner on 16-bit systems; not a problem\n                     * with any known compiler so far, though */\n\n    temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;\n    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);\n}\n\n/***********************************************************************\n * Update the encryption keys with the next byte of plain text\n */\nint update_keys(__G__ c)\n    __GDEF\n    int c;                      /* byte of plain text */\n{\n    GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB);\n    GLOBAL(keys[1]) = (GLOBAL(keys[1])\n                       + (GLOBAL(keys[0]) & 0xff))\n                      * 134775813L + 1;\n    {\n      register int keyshift = (int)(GLOBAL(keys[1]) >> 24);\n      GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB);\n    }\n    return c;\n}\n\n\n/***********************************************************************\n * Initialize the encryption keys and the random header according to\n * the given password.\n */\nvoid init_keys(__G__ passwd)\n    __GDEF\n    ZCONST char *passwd;        /* password string with which to modify keys */\n{\n#ifdef IZ_CRC_BE_OPTIMIZ\n    if (cry_crctb_p == NULL) {\n        cry_crctb_p = crytab_init(__G);\n    }\n#endif\n    GLOBAL(keys[0]) = 305419896L;\n    GLOBAL(keys[1]) = 591751049L;\n    GLOBAL(keys[2]) = 878082192L;\n    while (*passwd != '\\0') {\n        update_keys(__G__ (int)*passwd);\n        passwd++;\n    }\n}\n\n\n/***********************************************************************\n * Initialize the local copy of the table of precomputed crc32 values.\n * Whereas the public crc32-table is optimized for crc32 calculations\n * on arrays of bytes, the crypt code needs the crc32 values in an\n * byte-order-independent form as 32-bit unsigned numbers. On systems\n * with Big-Endian byte order using the optimized crc32 code, this\n * requires inverting the byte-order of the values in the\n * crypt-crc32-table.\n */\n#ifdef IZ_CRC_BE_OPTIMIZ\nlocal z_uint4 near *crytab_init(__G)\n    __GDEF\n{\n    int i;\n\n    for (i = 0; i < 256; i++) {\n        crycrctab[i] = REV_BE(CRC_32_TAB[i]);\n    }\n    return crycrctab;\n}\n#endif\n\n\n#ifdef ZIP\n\n/***********************************************************************\n * Write encryption header to file zfile using the password passwd\n * and the cyclic redundancy check crc.\n */\nvoid crypthead(passwd, crc, zfile)\n    ZCONST char *passwd;         /* password string */\n    ulg crc;                     /* crc of file being encrypted */\n    FILE *zfile;                 /* where to write header */\n{\n    int n;                       /* index in random header */\n    int t;                       /* temporary */\n    int c;                       /* random byte */\n    uch header[RAND_HEAD_LEN];   /* random header */\n    static unsigned calls = 0;   /* ensure different random header each time */\n\n    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the\n     * output of rand() to get less predictability, since rand() is\n     * often poorly implemented.\n     */\n    if (++calls == 1) {\n        srand((unsigned)time(NULL) ^ ZCR_SEED2);\n    }\n    init_keys(passwd);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++) {\n        c = (rand() >> 7) & 0xff;\n        header[n] = (uch)zencode(c, t);\n    }\n    /* Encrypt random header (last two bytes is high word of crc) */\n    init_keys(passwd);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++) {\n        header[n] = (uch)zencode(header[n], t);\n    }\n    header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t);\n    header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t);\n    fwrite(header, 1, RAND_HEAD_LEN, f);\n}\n\n\n#ifdef UTIL\n\n/***********************************************************************\n * Encrypt the zip entry described by z from file source to file dest\n * using the password passwd.  Return an error code in the ZE_ class.\n */\nint zipcloak(z, source, dest, passwd)\n    struct zlist far *z;    /* zip entry to encrypt */\n    FILE *source, *dest;    /* source and destination files */\n    ZCONST char *passwd;    /* password string */\n{\n    int c;                  /* input byte */\n    int res;                /* result code */\n    ulg n;                  /* holds offset and counts size */\n    ush flag;               /* previous flags */\n    int t;                  /* temporary */\n    int ztemp;              /* temporary storage for zencode value */\n\n    /* Set encrypted bit, clear extended local header bit and write local\n       header to output file */\n    if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP;\n    z->off = n;\n    flag = z->flg;\n    z->flg |= 1,  z->flg &= ~8;\n    z->lflg |= 1, z->lflg &= ~8;\n    z->siz += RAND_HEAD_LEN;\n    if ((res = putlocal(z, dest)) != ZE_OK) return res;\n\n    /* Initialize keys with password and write random header */\n    crypthead(passwd, z->crc, dest);\n\n    /* Skip local header in input file */\n    if (fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext),\n              SEEK_CUR)) {\n        return ferror(source) ? ZE_READ : ZE_EOF;\n    }\n\n    /* Encrypt data */\n    for (n = z->siz - RAND_HEAD_LEN; n; n--) {\n        if ((c = getc(source)) == EOF) {\n            return ferror(source) ? ZE_READ : ZE_EOF;\n        }\n        ztemp = zencode(c, t);\n        putc(ztemp, dest);\n    }\n    /* Skip extended local header in input file if there is one */\n    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {\n        return ferror(source) ? ZE_READ : ZE_EOF;\n    }\n    if (fflush(dest) == EOF) return ZE_TEMP;\n\n    /* Update number of bytes written to output file */\n    tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz;\n\n    return ZE_OK;\n}\n\n/***********************************************************************\n * Decrypt the zip entry described by z from file source to file dest\n * using the password passwd.  Return an error code in the ZE_ class.\n */\nint zipbare(z, source, dest, passwd)\n    struct zlist far *z;  /* zip entry to encrypt */\n    FILE *source, *dest;  /* source and destination files */\n    ZCONST char *passwd;  /* password string */\n{\n#ifdef ZIP10\n    int c0                /* byte preceding the last input byte */\n#endif\n    int c1;               /* last input byte */\n    ulg offset;           /* used for file offsets */\n    ulg size;             /* size of input data */\n    int r;                /* size of encryption header */\n    int res;              /* return code */\n    ush flag;             /* previous flags */\n\n    /* Save position and skip local header in input file */\n    if ((offset = (ulg)ftell(source)) == (ulg)-1L ||\n        fseek(source, (long)((4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext),\n              SEEK_CUR)) {\n        return ferror(source) ? ZE_READ : ZE_EOF;\n    }\n    /* Initialize keys with password */\n    init_keys(passwd);\n\n    /* Decrypt encryption header, save last two bytes */\n    c1 = 0;\n    for (r = RAND_HEAD_LEN; r; r--) {\n#ifdef ZIP10\n        c0 = c1;\n#endif\n        if ((c1 = getc(source)) == EOF) {\n            return ferror(source) ? ZE_READ : ZE_EOF;\n        }\n        Trace((stdout, \" (%02x)\", c1));\n        zdecode(c1);\n        Trace((stdout, \" %02x\", c1));\n    }\n    Trace((stdout, \"\\n\"));\n\n    /* If last two bytes of header don't match crc (or file time in the\n     * case of an extended local header), back up and just copy. For\n     * pkzip 2.0, the check has been reduced to one byte only.\n     */\n#ifdef ZIP10\n    if ((ush)(c0 | (c1<<8)) !=\n        (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) {\n#else\n    if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) {\n#endif\n        if (fseek(source, offset, SEEK_SET)) {\n            return ferror(source) ? ZE_READ : ZE_EOF;\n        }\n        if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;\n        return ZE_MISS;\n    }\n\n    /* Clear encrypted bit and local header bit, and write local header to\n       output file */\n    if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP;\n    z->off = offset;\n    flag = z->flg;\n    z->flg &= ~9;\n    z->lflg &= ~9;\n    z->siz -= RAND_HEAD_LEN;\n    if ((res = putlocal(z, dest)) != ZE_OK) return res;\n\n    /* Decrypt data */\n    for (size = z->siz; size; size--) {\n        if ((c1 = getc(source)) == EOF) {\n            return ferror(source) ? ZE_READ : ZE_EOF;\n        }\n        zdecode(c1);\n        putc(c1, dest);\n    }\n    /* Skip extended local header in input file if there is one */\n    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {\n        return ferror(source) ? ZE_READ : ZE_EOF;\n    }\n    if (fflush(dest) == EOF) return ZE_TEMP;\n\n    /* Update number of bytes written to output file */\n    tempzn += (4 + LOCHEAD) + z->nam + z->ext + z->siz;\n\n    return ZE_OK;\n}\n\n\n#else /* !UTIL */\n\n/***********************************************************************\n * If requested, encrypt the data in buf, and in any case call fwrite()\n * with the arguments to zfwrite().  Return what fwrite() returns.\n *\n * A bug has been found when encrypting large files.  See trees.c\n * for details and the fix.\n */\nunsigned zfwrite(buf, item_size, nb, f)\n    zvoid *buf;                 /* data buffer */\n    extent item_size;           /* size of each item in bytes */\n    extent nb;                  /* number of items */\n    FILE *f;                    /* file to write to */\n{\n    int t;                      /* temporary */\n\n    if (key != (char *)NULL) {  /* key is the global password pointer */\n        ulg size;               /* buffer size */\n        char *p = (char*)buf;   /* steps through buffer */\n\n        /* Encrypt data in buffer */\n        for (size = item_size*(ulg)nb; size != 0; p++, size--) {\n            *p = (char)zencode(*p, t);\n        }\n    }\n    /* Write the buffer out */\n    return fwrite(buf, item_size, nb, f);\n}\n\n#endif /* ?UTIL */\n#endif /* ZIP */\n\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n\n/***********************************************************************\n * Get the password and set up keys for current zipfile member.\n * Return PK_ class error.\n */\nint decrypt(__G__ passwrd)\n    __GDEF\n    ZCONST char *passwrd;\n{\n    ush b;\n    int n, r;\n    uch h[RAND_HEAD_LEN];\n\n    Trace((stdout, \"\\n[incnt = %d]: \", GLOBAL(incnt)));\n\n    /* get header once (turn off \"encrypted\" flag temporarily so we don't\n     * try to decrypt the same data twice) */\n    GLOBAL(pInfo->encrypted) = FALSE;\n    defer_leftover_input(__G);\n    for (n = 0; n < RAND_HEAD_LEN; n++) {\n        b = NEXTBYTE;\n        h[n] = (uch)b;\n        Trace((stdout, \" (%02x)\", h[n]));\n    }\n    undefer_input(__G);\n    GLOBAL(pInfo->encrypted) = TRUE;\n\n    if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */\n        GLOBAL(newzip) = FALSE;\n        if (passwrd != (char *)NULL) { /* user gave password on command line */\n            if (!GLOBAL(key)) {\n                if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) ==\n                    (char *)NULL)\n                    return PK_MEM2;\n                strcpy(GLOBAL(key), passwrd);\n                GLOBAL(nopwd) = TRUE;  /* inhibit password prompting! */\n            }\n        } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */\n            free(GLOBAL(key));\n            GLOBAL(key) = (char *)NULL;\n        }\n    }\n\n    /* if have key already, test it; else allocate memory for it */\n    if (GLOBAL(key)) {\n        if (!testp(__G__ h))\n            return PK_COOL;   /* existing password OK (else prompt for new) */\n        else if (GLOBAL(nopwd))\n            return PK_WARN;   /* user indicated no more prompting */\n    } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)\n        return PK_MEM2;\n\n    /* try a few keys */\n    n = 0;\n    do {\n        r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1,\n                             GLOBAL(zipfn), GLOBAL(filename));\n        if (r == IZ_PW_ERROR) {         /* internal error in fetch of PW */\n            free (GLOBAL(key));\n            GLOBAL(key) = NULL;\n            return PK_MEM2;\n        }\n        if (r != IZ_PW_ENTERED) {       /* user replied \"skip\" or \"skip all\" */\n            *GLOBAL(key) = '\\0';        /*   We try the NIL password, ... */\n            n = 0;                      /*   and cancel fetch for this item. */\n        }\n        if (!testp(__G__ h))\n            return PK_COOL;\n        if (r == IZ_PW_CANCELALL)       /* User replied \"Skip all\" */\n            GLOBAL(nopwd) = TRUE;       /*   inhibit any further PW prompt! */\n    } while (n > 0);\n\n    return PK_WARN;\n\n} /* end function decrypt() */\n\n\n\n/***********************************************************************\n * Test the password.  Return -1 if bad, 0 if OK.\n */\nlocal int testp(__G__ h)\n    __GDEF\n    ZCONST uch *h;\n{\n    int r;\n    char *key_translated;\n\n    /* On systems with \"obscure\" native character coding (e.g., EBCDIC),\n     * the first test translates the password to the \"main standard\"\n     * character coding. */\n\n#ifdef STR_TO_CP1\n    /* allocate buffer for translated password */\n    if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)\n        return -1;\n    /* first try, test password translated \"standard\" charset */\n    r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key)));\n#else /* !STR_TO_CP1 */\n    /* first try, test password as supplied on the extractor's host */\n    r = testkey(__G__ h, GLOBAL(key));\n#endif /* ?STR_TO_CP1 */\n\n#ifdef STR_TO_CP2\n    if (r != 0) {\n#ifndef STR_TO_CP1\n        /* now prepare for second (and maybe third) test with translated pwd */\n        if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)\n            return -1;\n#endif\n        /* second try, password translated to alternate (\"standard\") charset */\n        r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key)));\n#ifdef STR_TO_CP3\n        if (r != 0)\n            /* third try, password translated to another \"standard\" charset */\n            r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key)));\n#endif\n#ifndef STR_TO_CP1\n        free(key_translated);\n#endif\n    }\n#endif /* STR_TO_CP2 */\n\n#ifdef STR_TO_CP1\n    free(key_translated);\n    if (r != 0) {\n        /* last resort, test password as supplied on the extractor's host */\n        r = testkey(__G__ h, GLOBAL(key));\n    }\n#endif /* STR_TO_CP1 */\n\n    return r;\n\n} /* end function testp() */\n\n\nlocal int testkey(__G__ h, key)\n    __GDEF\n    ZCONST uch *h;      /* decrypted header */\n    ZCONST char *key;   /* decryption password to test */\n{\n    ush b;\n#ifdef ZIP10\n    ush c;\n#endif\n    int n;\n    uch *p;\n    uch hh[RAND_HEAD_LEN]; /* decrypted header */\n\n    /* set keys and save the encrypted header */\n    init_keys(__G__ key);\n    memcpy(hh, h, RAND_HEAD_LEN);\n\n    /* check password */\n    for (n = 0; n < RAND_HEAD_LEN; n++) {\n        zdecode(hh[n]);\n        Trace((stdout, \" %02x\", hh[n]));\n    }\n\n    Trace((stdout,\n      \"\\n  lrec.crc= %08lx  crec.crc= %08lx  pInfo->ExtLocHdr= %s\\n\",\n      GLOBAL(lrec.crc32), GLOBAL(pInfo->crc),\n      GLOBAL(pInfo->ExtLocHdr) ? \"true\":\"false\"));\n    Trace((stdout, \"  incnt = %d  unzip offset into zipfile = %ld\\n\",\n      GLOBAL(incnt),\n      GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf))));\n\n    /* same test as in zipbare(): */\n\n#ifdef ZIP10 /* check two bytes */\n    c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1];\n    Trace((stdout,\n      \"  (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\\n\",\n      (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16),\n      ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff))));\n    if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ?\n                           ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) :\n                           (ush)(GLOBAL(lrec.crc32) >> 16)))\n        return -1;  /* bad */\n#else\n    b = hh[RAND_HEAD_LEN-1];\n    Trace((stdout, \"  b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\\n\",\n      b, (ush)(GLOBAL(lrec.crc32) >> 24),\n      ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff));\n    if (b != (GLOBAL(pInfo->ExtLocHdr) ?\n        ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff :\n        (ush)(GLOBAL(lrec.crc32) >> 24)))\n        return -1;  /* bad */\n#endif\n    /* password OK:  decrypt current buffer contents before leaving */\n    for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ?\n             (int)GLOBAL(csize) : GLOBAL(incnt),\n         p = GLOBAL(inptr); n--; p++)\n        zdecode(*p);\n    return 0;       /* OK */\n\n} /* end function testkey() */\n\n#endif /* UNZIP && !FUNZIP */\n\n#else /* !CRYPT */\n\n/* something \"externally visible\" to shut up compiler/linker warnings */\nint zcr_dummy;\n\n#endif /* ?CRYPT */\n"
  },
  {
    "path": "deps/infozip/unzip60/crypt.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in (un)zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n  crypt.h (full version) by Info-ZIP.   Last revised:  [see CR_VERSION_DATE]\n\n  The main encryption/decryption source code for Info-Zip software was\n  originally written in Europe.  To the best of our knowledge, it can\n  be freely distributed in both source and object forms from any country,\n  including the USA under License Exception TSU of the U.S. Export\n  Administration Regulations (section 740.13(e)) of 6 June 2002.\n\n  NOTE on copyright history:\n  Previous versions of this source package (up to version 2.8) were\n  not copyrighted and put in the public domain.  If you cannot comply\n  with the Info-Zip LICENSE, you may want to look for one of those\n  public domain versions.\n */\n\n#ifndef __crypt_h   /* don't include more than once */\n#define __crypt_h\n\n#ifdef CRYPT\n#  undef CRYPT\n#endif\n/*\n   Logic of selecting \"full crypt\" code:\n   a) default behaviour:\n      - dummy crypt code when compiling UnZipSFX stub, to minimize size\n      - full crypt code when used to compile Zip, UnZip and fUnZip\n   b) USE_CRYPT defined:\n      - always full crypt code\n   c) NO_CRYPT defined:\n      - never full crypt code\n   NO_CRYPT takes precedence over USE_CRYPT\n */\n#if defined(NO_CRYPT)\n#  define CRYPT  0  /* dummy version */\n#else\n#if defined(USE_CRYPT)\n#  define CRYPT  1  /* full version */\n#else\n#if !defined(SFX)\n#  define CRYPT  1  /* full version for zip and main unzip */\n#else\n#  define CRYPT  0  /* dummy version for unzip sfx */\n#endif\n#endif /* ?USE_CRYPT */\n#endif /* ?NO_CRYPT */\n\n#if CRYPT\n/* full version */\n\n#ifdef CR_BETA\n#  undef CR_BETA    /* this is not a beta release */\n#endif\n\n#define CR_MAJORVER        2\n#define CR_MINORVER        11\n#ifdef CR_BETA\n#  define CR_BETA_VER      \"c BETA\"\n#  define CR_VERSION_DATE  \"05 Jan 2007\"       /* last real code change */\n#else\n#  define CR_BETA_VER      \"\"\n#  define CR_VERSION_DATE  \"05 Jan 2007\"       /* last public release date */\n#  define CR_RELEASE\n#endif\n\n#ifndef __G         /* UnZip only, for now (DLL stuff) */\n#  define __G\n#  define __G__\n#  define __GDEF\n#  define __GPRO    void\n#  define __GPRO__\n#endif\n\n#if defined(MSDOS) || defined(OS2) || defined(WIN32)\n#  ifndef DOS_OS2_W32\n#    define DOS_OS2_W32\n#  endif\n#endif\n\n#if defined(DOS_OS2_W32) || defined(__human68k__)\n#  ifndef DOS_H68_OS2_W32\n#    define DOS_H68_OS2_W32\n#  endif\n#endif\n\n#if defined(VM_CMS) || defined(MVS)\n#  ifndef CMS_MVS\n#    define CMS_MVS\n#  endif\n#endif\n\n/* To allow combining of Zip and UnZip static libraries in a single binary,\n * the Zip and UnZip versions of the crypt core functions have to be named\n * differently.\n */\n#ifdef ZIP\n#  ifdef REALLY_SHORT_SYMS\n#    define decrypt_byte   zdcrby\n#  else\n#    define decrypt_byte   zp_decrypt_byte\n#  endif\n#  define  update_keys     zp_update_keys\n#  define  init_keys       zp_init_keys\n#else /* !ZIP */\n#  ifdef REALLY_SHORT_SYMS\n#    define decrypt_byte   dcrbyt\n#  endif\n#endif /* ?ZIP */\n\n#define IZ_PWLEN  80    /* input buffer size for reading encryption key */\n#ifndef PWLEN           /* for compatibility with previous zcrypt release... */\n#  define PWLEN IZ_PWLEN\n#endif\n#define RAND_HEAD_LEN  12       /* length of encryption random header */\n\n/* the crc_32_tab array has to be provided externally for the crypt calculus */\n\n/* encode byte c, using temp t.  Warning: c must not have side effects. */\n#define zencode(c,t)  (t=decrypt_byte(__G), update_keys(c), t^(c))\n\n/* decode byte c in place */\n#define zdecode(c)   update_keys(__G__ c ^= decrypt_byte(__G))\n\nint  decrypt_byte OF((__GPRO));\nint  update_keys OF((__GPRO__ int c));\nvoid init_keys OF((__GPRO__ ZCONST char *passwd));\n\n#ifdef ZIP\n   void crypthead OF((ZCONST char *, ulg, FILE *));\n#  ifdef UTIL\n     int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *));\n     int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *));\n#  else\n     unsigned zfwrite OF((zvoid *, extent, extent, FILE *));\n     extern char *key;\n#  endif\n#endif /* ZIP */\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n   int  decrypt OF((__GPRO__ ZCONST char *passwrd));\n#endif\n\n#ifdef FUNZIP\n   extern int encrypted;\n#  ifdef NEXTBYTE\n#    undef NEXTBYTE\n#  endif\n#  define NEXTBYTE \\\n   (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in))\n#endif /* FUNZIP */\n\n#else /* !CRYPT */\n/* dummy version */\n\n#define zencode\n#define zdecode\n\n#define zfwrite  fwrite\n\n#endif /* ?CRYPT */\n#endif /* !__crypt_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/ebcdic.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ebcdic.h\n\n  The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables,\n  from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking\n\n  NOTES:\n  <Paul_von_Behren@stortek.com> (OS/390 port 12/97)\n   These table no longer represent the standard mappings (for example in the\n   OS/390 iconv utility).  In order to follow current standards I remapped\n     ebcdic x0a to ascii x15    and\n     ebcdic x85 to ascii x25    (and vice-versa)\n   Without these changes, newlines in auto-convert text files appeared\n   as literal \\045.\n   I'm not sure what effect this remap would have on the MVS and CMS ports, so\n   I ifdef'd these changes.  Hopefully these ifdef's can be removed when the\n   MVS/CMS folks test the new mappings.\n\n  Christian Spieler <spieler@ikp.tu-darmstadt.de>, 27-Apr-1998\n   The problem mentioned by Paul von Behren was already observed previously\n   on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in\n   1996. At that point, the ebcdic tables were not changed since they seemed\n   to be an adopted standard (to my knowledge, these tables are still used\n   as presented in mainfraime KERMIT). Instead, the \"end-of-line\" conversion\n   feature of Zip's and UnZip's \"text-translation\" mode was used to force\n   correct mappings between ASCII and EBCDIC newline markers.\n   Before interchanging the ASCII mappings of the EBCDIC control characters\n   \"NL\" 0x25 and \"LF\" 0x15 according to the OS/390 setting, we have to\n   make sure that EBCDIC 0x15 is never used as line termination.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __ebcdic_h      /* prevent multiple inclusions */\n#define __ebcdic_h\n\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#ifdef EBCDIC\n#ifndef MTS             /* MTS uses a slightly \"special\" EBCDIC code page */\n\nZCONST uch ebcdic[] = {\n    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */\n#ifdef OS390\n    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#else\n    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#endif\n    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */\n    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */\n    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */\n    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */\n    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */\n    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */\n    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */\n    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */\n    0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,  /* 58 - 5F */\n    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */\n    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */\n    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */\n    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */\n#ifdef OS390\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,  /* 80 - 87 */\n#else\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */\n#endif\n    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */\n    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */\n    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */\n    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */\n    0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,  /* A8 - AF */\n    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */\n    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */\n    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */\n    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */\n    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */\n    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,  /* D8 - DF */\n    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */\n    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */\n    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */\n    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */\n};\n\n#if (defined(ZIP) || CRYPT)\nZCONST uch ascii[] = {\n    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */\n    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#ifdef OS390\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87,  /* 10 - 17 */\n#else\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */\n#endif\n    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n#ifdef OS390\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B,  /* 20 - 27 */\n#else\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */\n#endif\n    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */\n    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */\n    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */\n    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */\n    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */\n    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */\n    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,  /* 58 - 5F */\n    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */\n    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */\n    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */\n    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */\n    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */\n    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */\n    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */\n    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */\n    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */\n    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,  /* A8 - AF */\n    0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */\n    0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,  /* B8 - BF */\n    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */\n    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */\n    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */\n    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */\n    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */\n    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */\n    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */\n};\n#endif /* ZIP || CRYPT */\n\n#else /* MTS */\n\n/*\n * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1\n * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.\n */\n\nZCONST uch ebcdic[] = {\n    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */\n    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */\n    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */\n    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */\n    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */\n    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */\n    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */\n    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */\n    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */\n    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,  /* 58 - 5F */\n    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */\n    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */\n    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */\n    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */\n    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */\n    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */\n    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */\n    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */\n    0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC,  /* A8 - AF */\n    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */\n    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */\n    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */\n    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */\n    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */\n    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59,  /* D8 - DF */\n    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */\n    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */\n    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */\n    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */\n};\n\n#if (defined(ZIP) || CRYPT)\nZCONST uch ascii[] = {\n    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */\n    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */\n    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */\n    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */\n    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */\n    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */\n    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */\n    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */\n    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */\n    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,  /* 58 - 5F */\n    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */\n    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */\n    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */\n    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */\n    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */\n    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */\n    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */\n    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */\n    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */\n    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,  /* A8 - AF */\n    0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */\n    0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,  /* B8 - BF */\n    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */\n    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */\n    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */\n    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */\n    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */\n    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */\n    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */\n};\n#endif /* ZIP || CRYPT */\n\n#endif /* ?MTS */\n#endif /* EBCDIC */\n\n/*---------------------------------------------------------------------------\n\n  The following conversion tables translate between IBM PC CP 850\n  (OEM codepage) and the \"Western Europe & America\" Windows codepage 1252.\n  The Windows codepage 1252 contains the ISO 8859-1 \"Latin 1\" codepage,\n  with some additional printable characters in the range (0x80 - 0x9F),\n  that is reserved to control codes in the ISO 8859-1 character table.\n\n  The ISO <--> OEM conversion tables were constructed with the help\n  of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion\n  functions and have been checked against the CP850 and LATIN1 tables\n  provided in the MS-Kermit 3.14 distribution.\n\n  ---------------------------------------------------------------------------*/\n\n#ifdef IZ_ISO2OEM_ARRAY\nZCONST uch Far iso2oem_850[] = {\n    0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE,  /* 80 - 87 */\n    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */\n    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */\n    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */\n    0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,  /* A0 - A7 */\n    0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,  /* A8 - AF */\n    0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,  /* B0 - B7 */\n    0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,  /* B8 - BF */\n    0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,  /* C0 - C7 */\n    0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,  /* C8 - CF */\n    0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,  /* D0 - D7 */\n    0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,  /* D8 - DF */\n    0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,  /* E0 - E7 */\n    0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,  /* E8 - EF */\n    0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,  /* F0 - F7 */\n    0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98   /* F8 - FF */\n};\n#endif /* IZ_ISO2OEM_ARRAY */\n\n#ifdef IZ_OEM2ISO_ARRAY\nZCONST uch Far oem2iso_850[] = {\n    0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,  /* 80 - 87 */\n    0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,  /* 88 - 8F */\n    0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,  /* 90 - 97 */\n    0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83,  /* 98 - 9F */\n    0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,  /* A0 - A7 */\n    0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,  /* A8 - AF */\n    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0,  /* B0 - B7 */\n    0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B,  /* B8 - BF */\n    0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3,  /* C0 - C7 */\n    0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4,  /* C8 - CF */\n    0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE,  /* D0 - D7 */\n    0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF,  /* D8 - DF */\n    0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,  /* E0 - E7 */\n    0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,  /* E8 - EF */\n    0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,  /* F0 - F7 */\n    0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0   /* F8 - FF */\n};\n#endif /* IZ_OEM2ISO_ARRAY */\n\n/* The following pointers to the OEM<-->ISO translation tables are used\n   by the translation code portions.  They may get initialized at program\n   startup to point to the matching static translation tables, or to NULL\n   to disable OEM-ISO translation.\n   The compile-time initialization used here provides the backward compatible\n   setting, as can be found in UnZip 5.52 and earlier.\n   In case this mechanism will ever get used on a multithreading system that\n   allows different codepage setups for concurrently running threads, these\n   pointers should get moved into UnZip's thread-safe global data structure.\n */\n#ifdef IZ_ISO2OEM_ARRAY\nZCONST uch Far *iso2oem = iso2oem_850;  /* backward compatibility default */\n#endif /* IZ_ISO2OEM_ARRAY */\n#ifdef IZ_OEM2ISO_ARRAY\nZCONST uch Far *oem2iso = oem2iso_850;  /* backward compatibility default */\n#endif /* IZ_OEM2ISO_ARRAY */\n\n#if defined(THEOS) || defined(THEOS_SUPPORT)\n#  include \"theos/charconv.h\"\n#endif\n\n#endif /* __ebcdic_h  */\n"
  },
  {
    "path": "deps/infozip/unzip60/envargs.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*----------------------------------------------------------------*\n | envargs - add default options from environment to command line\n |----------------------------------------------------------------\n | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.\n | This program is in the public domain.\n |----------------------------------------------------------------\n | Minor program notes:\n |  1. Yes, the indirection is a tad complex\n |  2. Parentheses were added where not needed in some cases\n |     to make the action of the code less obscure.\n |----------------------------------------------------------------\n | UnZip notes: 24 May 92 (\"v1.4\"):\n |  1. #include \"unzip.h\" for prototypes (24 May 92)\n |  2. changed ch to type char (24 May 92)\n |  3. added an ifdef to avoid Borland warnings (24 May 92)\n |  4. included Rich Wales' mksargs() routine (for MS-DOS, maybe\n |     OS/2? NT?) (4 Dec 93)\n |  5. added alternate-variable string envstr2 (21 Apr 94)\n |  6. added support for quoted arguments (6 Jul 96)\n *----------------------------------------------------------------*/\n\n\n#define __ENVARGS_C     /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#ifdef __EMX__          /* emx isspace() returns TRUE on extended ASCII !! */\n#  define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c))\n#else\n#  define ISspace(c) isspace((unsigned)c)\n#endif /* ?__EMX__ */\n\n#if (!defined(RISCOS) && (!defined(MODERN) || defined(NO_STDLIB_H)))\nextern char *getenv();\n#endif\nstatic int count_args OF((ZCONST char *));\n\n\n/* envargs() returns PK-style error code */\n\nint envargs(Pargc, Pargv, envstr, envstr2)\n    int *Pargc;\n    char ***Pargv;\n    ZCONST char *envstr, *envstr2;\n{\n    char *envptr;       /* value returned by getenv */\n    char *bufptr;       /* copy of env info */\n    int argc = 0;       /* internal arg count */\n    register int ch;    /* spare temp value */\n    char **argv;        /* internal arg vector */\n    char **argvect;     /* copy of vector address */\n\n    /* see if anything in the environment */\n    if ((envptr = getenv(envstr)) != (char *)NULL)        /* usual var */\n        while (ISspace(*envptr))        /* must discard leading spaces */\n            envptr++;\n    if (envptr == (char *)NULL || *envptr == '\\0')\n        if ((envptr = getenv(envstr2)) != (char *)NULL)   /* alternate var */\n            while (ISspace(*envptr))\n                envptr++;\n    if (envptr == (char *)NULL || *envptr == '\\0')\n        return PK_OK;\n\n    bufptr = malloc(1 + strlen(envptr));\n    if (bufptr == (char *)NULL)\n        return PK_MEM;\n#if ((defined(WIN32) || defined(WINDLL)) && !defined(_WIN32_WCE))\n# ifdef WIN32\n    if (IsWinNT()) {\n        /* SPC: don't know codepage of 'real' WinNT console */\n        strcpy(bufptr, envptr);\n    } else {\n        /* Win95 environment is DOS and uses OEM character coding */\n        OEM_TO_INTERN(envptr, bufptr);\n    }\n# else /* !WIN32 */\n    /* DOS (Win 3.x) environment uses OEM codepage */\n    OEM_TO_INTERN(envptr, bufptr);\n# endif\n#else /* !((WIN32 || WINDLL) && !_WIN32_WCE) */\n    strcpy(bufptr, envptr);\n#endif /* ?((WIN32 || WINDLL) && !_WIN32_WCE) */\n\n    /* count the args so we can allocate room for them */\n    argc = count_args(bufptr);\n    /* allocate a vector large enough for all args */\n    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));\n    if (argv == (char **)NULL) {\n        free(bufptr);\n        return PK_MEM;\n    }\n    argvect = argv;\n\n    /* copy the program name first, that's always true */\n    *(argv++) = *((*Pargv)++);\n\n    /* copy the environment args next, may be changed */\n    do {\n#if defined(AMIGA) || defined(UNIX)\n        if (*bufptr == '\"') {\n            char *argstart = ++bufptr;\n\n            *(argv++) = argstart;\n            for (ch = *bufptr; ch != '\\0' && ch != '\\\"';\n                 ch = *PREINCSTR(bufptr))\n                if (ch == '\\\\' && bufptr[1] != '\\0')\n                    ++bufptr;           /* advance to char after backslash */\n            if (ch != '\\0')\n                *(bufptr++) = '\\0';     /* overwrite trailing \" */\n\n            /* remove escape characters */\n            while ((argstart = MBSCHR(argstart, '\\\\')) != (char *)NULL) {\n                strcpy(argstart, argstart + 1);\n                if (*argstart)\n                    ++argstart;\n            }\n        } else {\n            *(argv++) = bufptr;\n            while ((ch = *bufptr) != '\\0' && !ISspace(ch))\n                INCSTR(bufptr);\n            if (ch != '\\0')\n                *(bufptr++) = '\\0';\n        }\n#else\n#ifdef DOS_FLX_NLM_OS2_W32\n        /* we do not support backslash-quoting of quotes in quoted\n         * strings under DOS_FLX_NLM_OS2_W32, because backslashes are\n         * directory separators and double quotes are illegal in filenames */\n        if (*bufptr == '\"') {\n            *(argv++) = ++bufptr;\n            while ((ch = *bufptr) != '\\0' && ch != '\\\"')\n                INCSTR(bufptr);\n            if (ch != '\\0')\n                *(bufptr++) = '\\0';\n        } else {\n            *(argv++) = bufptr;\n            while ((ch = *bufptr) != '\\0' && !ISspace(ch))\n                INCSTR(bufptr);\n            if (ch != '\\0')\n                *(bufptr++) = '\\0';\n        }\n#else\n        *(argv++) = bufptr;\n        while ((ch = *bufptr) != '\\0' && !ISspace(ch))\n            INCSTR(bufptr);\n        if (ch != '\\0')\n            *(bufptr++) = '\\0';\n#endif /* ?DOS_FLX_NLM_OS2_W32 */\n#endif /* ?(AMIGA || UNIX) */\n        while ((ch = *bufptr) != '\\0' && ISspace(ch))\n            INCSTR(bufptr);\n    } while (ch);\n\n    /* now save old argc and copy in the old args */\n    argc += *Pargc;\n    while (--(*Pargc))\n        *(argv++) = *((*Pargv)++);\n\n    /* finally, add a NULL after the last arg, like Unix */\n    *argv = (char *)NULL;\n\n    /* save the values and return, indicating succes */\n    *Pargv = argvect;\n    *Pargc = argc;\n\n    return PK_OK;\n}\n\n\n\nstatic int count_args(s)\n    ZCONST char *s;\n{\n    int count = 0;\n    char ch;\n\n    do {\n        /* count and skip args */\n        ++count;\n#if defined(AMIGA) || defined(UNIX)\n        if (*s == '\\\"') {\n            for (ch = *PREINCSTR(s);  ch != '\\0' && ch != '\\\"';\n                 ch = *PREINCSTR(s))\n                if (ch == '\\\\' && s[1] != '\\0')\n                    ++s;\n            if (*s)\n                ++s;        /* trailing quote */\n        } else\n#else\n#ifdef DOS_FLX_NLM_OS2_W32\n        if (*s == '\\\"') {\n            ++s;                /* leading quote */\n            while ((ch = *s) != '\\0' && ch != '\\\"')\n                INCSTR(s);\n            if (*s)\n                ++s;        /* trailing quote */\n        } else\n#endif /* DOS_FLX_NLM_OS2_W32 */\n#endif /* ?(AMIGA || UNIX) */\n        while ((ch = *s) != '\\0' && !ISspace(ch))  /* note else-clauses above */\n            INCSTR(s);\n        while ((ch = *s) != '\\0' && ISspace(ch))\n            INCSTR(s);\n    } while (ch);\n\n    return count;\n}\n\n\n\n#ifdef TEST\n\nint main(argc, argv)\n    int argc;\n    char **argv;\n{\n    int err;\n\n    printf(\"Orig argv: %p\\n\", argv);\n    dump_args(argc, argv);\n    if ((err = envargs(&argc, &argv, \"ENVTEST\")) != PK_OK) {\n        perror(\"envargs:  cannot get memory for arguments\");\n        EXIT(err);\n    }\n    printf(\" New argv: %p\\n\", argv);\n    dump_args(argc, argv);\n}\n\n\n\nvoid dump_args(argc, argv)\n    int argc;\n    char *argv[];\n{\n    int i;\n\n    printf(\"\\nDump %d args:\\n\", argc);\n    for (i = 0; i < argc; ++i)\n        printf(\"%3d %s\\n\", i, argv[i]);\n}\n\n#endif /* TEST */\n\n\n\n#ifdef MSDOS   /* DOS_OS2?  DOS_OS2_W32? */\n\n/*\n * void mksargs(int *argcp, char ***argvp)\n *\n *    Substitutes the extended command line argument list produced by\n *    the MKS Korn Shell in place of the command line info from DOS.\n *\n *    The MKS shell gets around DOS's 128-byte limit on the length of\n *    a command line by passing the \"real\" command line in the envi-\n *    ronment.  The \"real\" arguments are flagged by prepending a tilde\n *    (~) to each one.\n *\n *    This \"mksargs\" routine creates a new argument list by scanning\n *    the environment from the beginning, looking for strings begin-\n *    ning with a tilde character.  The new list replaces the original\n *    \"argv\" (pointed to by \"argvp\"), and the number of arguments\n *    in the new list replaces the original \"argc\" (pointed to by\n *    \"argcp\").\n *\n *    Rich Wales\n */\nvoid mksargs(argcp, argvp)\n    int *argcp;\n    char ***argvp;\n{\n#ifndef MSC /* declared differently in MSC 7.0 headers, at least */\n#ifndef __WATCOMC__\n    extern char **environ;          /* environment */\n#endif\n#endif\n    char        **envp;             /* pointer into environment */\n    char        **newargv;          /* new argument list */\n    char        **argp;             /* pointer into new arg list */\n    int         newargc;            /* new argument count */\n\n    /* sanity check */\n    if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL)\n        return;\n\n    /* find out how many environment arguments there are */\n    for (envp = environ, newargc = 0;\n         *envp != NULL && (*envp)[0] == '~';\n         envp++, newargc++)\n        ;\n    if (newargc == 0)\n        return;     /* no environment arguments */\n\n    /* set up new argument list */\n    newargv = (char **) malloc(sizeof(char **) * (newargc+1));\n    if (newargv == NULL)\n        return;     /* malloc failed */\n\n    for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~';\n         *argp++ = &(*envp++)[1])\n        ;\n    *argp = NULL;   /* null-terminate the list */\n\n    /* substitute new argument list in place of old one */\n    *argcp = newargc;\n    *argvp = newargv;\n}\n\n#endif /* MSDOS */\n"
  },
  {
    "path": "deps/infozip/unzip60/explode.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* explode.c -- by Mark Adler\n   version c17d, 01 December 2007 */\n\n\n/* Copyright history:\n   - Starting with UnZip 5.41 of 16-April-2000, this source file\n     is covered by the Info-Zip LICENSE cited above.\n   - Prior versions of this source file, found in UnZip source packages\n     up to UnZip 5.40, were put in the public domain.\n     The original copyright note by Mark Adler was:\n         \"You can do whatever you like with this source file,\n         though I would prefer that if you modify it and\n         redistribute it that you include comments to that effect\n         with your name and the date.  Thank you.\"\n\n   History:\n   vers    date          who           what\n   ----  ---------  --------------  ------------------------------------\n    c1   30 Mar 92  M. Adler        explode that uses huft_build from inflate\n                                    (this gives over a 70% speed improvement\n                                    over the original unimplode.c, which\n                                    decoded a bit at a time)\n    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.\n    c3   10 Apr 92  M. Adler        added a little memory tracking if DEBUG\n    c4   11 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy()\n    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing\n                                    the 32K window size for specialized\n                                    applications.\n    c6   31 May 92  M. Adler        added typecasts to eliminate some warnings\n    c7   27 Jun 92  G. Roelofs      added more typecasts.\n    c8   17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch.\n    c9   19 Jul 93  J. Bush         added more typecasts (to return values);\n                                    made l[256] array static for Amiga.\n    c10   8 Oct 93  G. Roelofs      added used_csize for diagnostics; added\n                                    buf and unshrink arguments to flush();\n                                    undef'd various macros at end for Turbo C;\n                                    removed NEXTBYTE macro (now in unzip.h)\n                                    and bytebuf variable (not used); changed\n                                    memset() to memzero().\n    c11   9 Jan 94  M. Adler        fixed incorrect used_csize calculation.\n    c12   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines\n                                    to avoid bug in Encore compiler.\n    c13  25 Aug 94  M. Adler        fixed distance-length comment (orig c9 fix)\n    c14  22 Nov 95  S. Maxwell      removed unnecessary \"static\" on auto array\n    c15   6 Jul 96  W. Haidinger    added ulg typecasts to flush() calls.\n    c16   8 Feb 98  C. Spieler      added ZCONST modifiers to const tables\n                                    and #ifdef DEBUG around debugging code.\n    c16b 25 Mar 98  C. Spieler      modified DLL code for slide redirection.\n    c16d 05 Jul 99  C. Spieler      take care of flush() return values and\n                                    stop processing in case of errors\n    c17  04 Feb 01  C. Spieler      reorganized code to reduce repetitions\n                                    of large code parts; adapted huft decoding\n                                    to the changes in inflate's huft_build()\n                                    due to support of deflate64; fixed memory\n                                    leaks (huft tables were not free'd when\n                                    get_tree() failed).\n    c17b 16 Feb 02  C. Spieler      changed type of the \"extra lengths\" array\n                                    \"extra\" from ush into uch (to save space)\n    c17c 10 Aug 04  NN              file sizes use zoff_t.\n    c17d 01 Dec 07  C. Spieler      type for file sizes changed from zoff_t\n                                    into zusz_t.\n */\n\n\n/*\n   Explode imploded (PKZIP method 6 compressed) data.  This compression\n   method searches for as much of the current string of bytes (up to a length\n   of ~320) in the previous 4K or 8K bytes.  If it doesn't find any matches\n   (of at least length 2 or 3), it codes the next byte.  Otherwise, it codes\n   the length of the matched string and its distance backwards from the\n   current position.  Single bytes (\"literals\") are preceded by a one (a\n   single bit) and are either uncoded (the eight bits go directly into the\n   compressed stream for a total of nine bits) or Huffman coded with a\n   supplied literal code tree.  If literals are coded, then the minimum match\n   length is three, otherwise it is two.\n\n   There are therefore four kinds of imploded streams: 8K search with coded\n   literals (min match = 3), 4K search with coded literals (min match = 3),\n   8K with uncoded literals (min match = 2), and 4K with uncoded literals\n   (min match = 2).  The kind of stream is identified in two bits of a\n   general purpose bit flag that is outside of the compressed stream.\n\n   Distance-length pairs for matched strings are preceded by a zero bit (to\n   distinguish them from literals) and are always coded.  The distance comes\n   first and is either the low six (4K) or low seven (8K) bits of the\n   distance (uncoded), followed by the high six bits of the distance coded.\n   Then the length is six bits coded (0..63 + min match length), and if the\n   maximum such length is coded, then it's followed by another eight bits\n   (uncoded) to be added to the coded length.  This gives a match length\n   range of 2..320 or 3..321 bytes.\n\n   The literal, length, and distance codes are all represented in a slightly\n   compressed form themselves.  What is sent are the lengths of the codes for\n   each value, which is sufficient to construct the codes.  Each byte of the\n   code representation is the code length (the low four bits representing\n   1..16), and the number of values sequentially with that length (the high\n   four bits also representing 1..16).  There are 256 literal code values (if\n   literals are coded), 64 length code values, and 64 distance code values,\n   in that order at the beginning of the compressed stream.  Each set of code\n   values is preceded (redundantly) with a byte indicating how many bytes are\n   in the code description that follows, in the range 1..256.\n\n   The codes themselves are decoded using tables made by huft_build() from\n   the bit lengths.  That routine and its comments are in the inflate.c\n   module.\n */\n\n#define __EXPLODE_C     /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"      /* must supply slide[] (uch) array and NEXTBYTE macro */\n\n#ifndef WSIZE\n#  define WSIZE 0x8000  /* window size--must be a power of two, and */\n#endif                  /* at least 8K for zip's implode method */\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n#  define wszimpl (unsigned)(G._wsize)\n#else\n#  if defined(USE_DEFLATE64) && defined(INT_16BIT)\n#    define wszimpl (unsigned)(WSIZE>>1)\n#  else /* !(USE_DEFLATE64 && INT_16BIT) */\n#    define wszimpl WSIZE\n#  endif /* !(USE_DEFLATE64 && INT_16BIT) */\n#endif\n\n/* routines here */\nstatic int get_tree OF((__GPRO__ unsigned *l, unsigned n));\nstatic int explode_lit OF((__GPRO__ struct huft *tb, struct huft *tl,\n                           struct huft *td, unsigned bb, unsigned bl,\n                           unsigned bd, unsigned bdl));\nstatic int explode_nolit OF((__GPRO__ struct huft *tl, struct huft *td,\n                             unsigned bl, unsigned bd, unsigned bdl));\nint explode OF((__GPRO));\n\n\n/* The implode algorithm uses a sliding 4K or 8K byte window on the\n   uncompressed stream to find repeated byte strings.  This is implemented\n   here as a circular buffer.  The index is updated simply by incrementing\n   and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1).  Here, the 32K\n   buffer of inflate is used, and it works just as well to always have\n   a 32K circular buffer, so the index is anded with 0x7fff.  This is\n   done to allow the window to also be used as the output buffer. */\n/* This must be supplied in an external module useable like \"uch slide[8192];\"\n   or \"uch *slide;\", where the latter would be malloc'ed.  In unzip, slide[]\n   is actually a 32K area for use by inflate, which uses a 32K sliding window.\n */\n\n\n#define INVALID_CODE 99\n#define IS_INVALID_CODE(c)  ((c) == INVALID_CODE)\n\n/* Tables for length and distance */\nstatic ZCONST ush cplen2[] =\n        {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,\n        18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,\n        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};\nstatic ZCONST ush cplen3[] =\n        {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,\n        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,\n        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,\n        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};\nstatic ZCONST uch extra[] =\n        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        8};\nstatic ZCONST ush cpdist4[] =\n        {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,\n        769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,\n        1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,\n        2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,\n        2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,\n        3649, 3713, 3777, 3841, 3905, 3969, 4033};\nstatic ZCONST ush cpdist8[] =\n        {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,\n        1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,\n        2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,\n        4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,\n        5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,\n        7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};\n\n\n/* Macros for inflate() bit peeking and grabbing.\n   The usage is:\n\n        NEEDBITS(j)\n        x = b & mask_bits[j];\n        DUMPBITS(j)\n\n   where NEEDBITS makes sure that b has at least j bits in it, and\n   DUMPBITS removes the bits from b.  The macros use the variable k\n   for the number of bits in b.  Normally, b and k are register\n   variables for speed.\n */\n\n#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}\n#define DUMPBITS(n) {b>>=(n);k-=(n);}\n\n#define DECODEHUFT(htab, bits, mask) {\\\n  NEEDBITS((unsigned)(bits))\\\n  t = (htab) + ((~(unsigned)b)&(mask));\\\n  while (1) {\\\n    DUMPBITS(t->b)\\\n    if ((e=t->e) <= 32) break;\\\n    if (IS_INVALID_CODE(e)) return 1;\\\n    e &= 31;\\\n    NEEDBITS(e)\\\n    t = t->v.t + ((~(unsigned)b)&mask_bits[e]);\\\n  }\\\n}\n\n\nstatic int get_tree(__G__ l, n)\n     __GDEF\nunsigned *l;            /* bit lengths */\nunsigned n;             /* number expected */\n/* Get the bit lengths for a code representation from the compressed\n   stream.  If get_tree() returns 4, then there is an error in the data.\n   Otherwise zero is returned. */\n{\n  unsigned i;           /* bytes remaining in list */\n  unsigned k;           /* lengths entered */\n  unsigned j;           /* number of codes */\n  unsigned b;           /* bit length for those codes */\n\n\n  /* get bit lengths */\n  i = NEXTBYTE + 1;                     /* length/count pairs to read */\n  k = 0;                                /* next code */\n  do {\n    b = ((j = NEXTBYTE) & 0xf) + 1;     /* bits in code (1..16) */\n    j = ((j & 0xf0) >> 4) + 1;          /* codes with those bits (1..16) */\n    if (k + j > n)\n      return 4;                         /* don't overflow l[] */\n    do {\n      l[k++] = b;\n    } while (--j);\n  } while (--i);\n  return k != n ? 4 : 0;                /* should have read n of them */\n}\n\n\n\nstatic int explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl)\n     __GDEF\nstruct huft *tb, *tl, *td;      /* literal, length, and distance tables */\nunsigned bb, bl, bd;            /* number of bits decoded by those */\nunsigned bdl;                   /* number of distance low bits */\n/* Decompress the imploded data using coded literals and a sliding\n   window (of size 2^(6+bdl) bytes). */\n{\n  zusz_t s;             /* bytes to decompress */\n  register unsigned e;  /* table entry flag/number of extra bits */\n  unsigned n, d;        /* length and index for copy */\n  unsigned w;           /* current window position */\n  struct huft *t;       /* pointer to table entry */\n  unsigned mb, ml, md;  /* masks for bb, bl, and bd bits */\n  unsigned mdl;         /* mask for bdl (distance lower) bits */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  unsigned u;           /* true if unflushed */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* explode the coded data */\n  b = k = w = 0;                /* initialize bit buffer, window */\n  u = 1;                        /* buffer unflushed */\n  mb = mask_bits[bb];           /* precompute masks for speed */\n  ml = mask_bits[bl];\n  md = mask_bits[bd];\n  mdl = mask_bits[bdl];\n  s = G.lrec.ucsize;\n  while (s > 0)                 /* do until ucsize bytes uncompressed */\n  {\n    NEEDBITS(1)\n    if (b & 1)                  /* then literal--decode it */\n    {\n      DUMPBITS(1)\n      s--;\n      DECODEHUFT(tb, bb, mb)    /* get coded literal */\n      redirSlide[w++] = (uch)t->v.n;\n      if (w == wszimpl)\n      {\n        if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n          return retval;\n        w = u = 0;\n      }\n    }\n    else                        /* else distance/length */\n    {\n      DUMPBITS(1)\n      NEEDBITS(bdl)             /* get distance low bits */\n      d = (unsigned)b & mdl;\n      DUMPBITS(bdl)\n      DECODEHUFT(td, bd, md)    /* get coded distance high bits */\n      d = w - d - t->v.n;       /* construct offset */\n      DECODEHUFT(tl, bl, ml)    /* get coded length */\n      n = t->v.n;\n      if (e)                    /* get length extra bits */\n      {\n        NEEDBITS(8)\n        n += (unsigned)b & 0xff;\n        DUMPBITS(8)\n      }\n\n      /* do the copy */\n      s = (s > (zusz_t)n ? s - (zusz_t)n : 0);\n      do {\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n        if (G.redirect_slide) {\n          /* &= w/ wszimpl not needed and wrong if redirect */\n          if (d >= wszimpl)\n            return 1;\n          e = wszimpl - (d > w ? d : w);\n        } else\n#endif\n          e = wszimpl - ((d &= wszimpl-1) > w ? d : w);\n        if (e > n) e = n;\n        n -= e;\n        if (u && w <= d)\n        {\n          memzero(redirSlide + w, e);\n          w += e;\n          d += e;\n        }\n        else\n#ifndef NOMEMCPY\n          if (w - d >= e)       /* (this test assumes unsigned comparison) */\n          {\n            memcpy(redirSlide + w, redirSlide + d, e);\n            w += e;\n            d += e;\n          }\n          else                  /* do it slow to avoid memcpy() overlap */\n#endif /* !NOMEMCPY */\n            do {\n              redirSlide[w++] = redirSlide[d++];\n            } while (--e);\n        if (w == wszimpl)\n        {\n          if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n            return retval;\n          w = u = 0;\n        }\n      } while (n);\n    }\n  }\n\n  /* flush out redirSlide */\n  if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n    return retval;\n  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */\n  {                        /* sometimes read one too many:  k>>3 compensates */\n    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);\n    return 5;\n  }\n  return 0;\n}\n\n\n\nstatic int explode_nolit(__G__ tl, td, bl, bd, bdl)\n     __GDEF\nstruct huft *tl, *td;   /* length and distance decoder tables */\nunsigned bl, bd;        /* number of bits decoded by tl[] and td[] */\nunsigned bdl;           /* number of distance low bits */\n/* Decompress the imploded data using uncoded literals and a sliding\n   window (of size 2^(6+bdl) bytes). */\n{\n  zusz_t s;             /* bytes to decompress */\n  register unsigned e;  /* table entry flag/number of extra bits */\n  unsigned n, d;        /* length and index for copy */\n  unsigned w;           /* current window position */\n  struct huft *t;       /* pointer to table entry */\n  unsigned ml, md;      /* masks for bl and bd bits */\n  unsigned mdl;         /* mask for bdl (distance lower) bits */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  unsigned u;           /* true if unflushed */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* explode the coded data */\n  b = k = w = 0;                /* initialize bit buffer, window */\n  u = 1;                        /* buffer unflushed */\n  ml = mask_bits[bl];           /* precompute masks for speed */\n  md = mask_bits[bd];\n  mdl = mask_bits[bdl];\n  s = G.lrec.ucsize;\n  while (s > 0)                 /* do until ucsize bytes uncompressed */\n  {\n    NEEDBITS(1)\n    if (b & 1)                  /* then literal--get eight bits */\n    {\n      DUMPBITS(1)\n      s--;\n      NEEDBITS(8)\n      redirSlide[w++] = (uch)b;\n      if (w == wszimpl)\n      {\n        if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n          return retval;\n        w = u = 0;\n      }\n      DUMPBITS(8)\n    }\n    else                        /* else distance/length */\n    {\n      DUMPBITS(1)\n      NEEDBITS(bdl)             /* get distance low bits */\n      d = (unsigned)b & mdl;\n      DUMPBITS(bdl)\n      DECODEHUFT(td, bd, md)    /* get coded distance high bits */\n      d = w - d - t->v.n;       /* construct offset */\n      DECODEHUFT(tl, bl, ml)    /* get coded length */\n      n = t->v.n;\n      if (e)                    /* get length extra bits */\n      {\n        NEEDBITS(8)\n        n += (unsigned)b & 0xff;\n        DUMPBITS(8)\n      }\n\n      /* do the copy */\n      s = (s > (zusz_t)n ? s - (zusz_t)n : 0);\n      do {\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n        if (G.redirect_slide) {\n          /* &= w/ wszimpl not needed and wrong if redirect */\n          if (d >= wszimpl)\n            return 1;\n          e = wszimpl - (d > w ? d : w);\n        } else\n#endif\n          e = wszimpl - ((d &= wszimpl-1) > w ? d : w);\n        if (e > n) e = n;\n        n -= e;\n        if (u && w <= d)\n        {\n          memzero(redirSlide + w, e);\n          w += e;\n          d += e;\n        }\n        else\n#ifndef NOMEMCPY\n          if (w - d >= e)       /* (this test assumes unsigned comparison) */\n          {\n            memcpy(redirSlide + w, redirSlide + d, e);\n            w += e;\n            d += e;\n          }\n          else                  /* do it slow to avoid memcpy() overlap */\n#endif /* !NOMEMCPY */\n            do {\n              redirSlide[w++] = redirSlide[d++];\n            } while (--e);\n        if (w == wszimpl)\n        {\n          if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n            return retval;\n          w = u = 0;\n        }\n      } while (n);\n    }\n  }\n\n  /* flush out redirSlide */\n  if ((retval = flush(__G__ redirSlide, (ulg)w, 0)) != 0)\n    return retval;\n  if (G.csize + G.incnt + (k >> 3))   /* should have read csize bytes, but */\n  {                        /* sometimes read one too many:  k>>3 compensates */\n    G.used_csize = G.lrec.csize - G.csize - G.incnt - (k >> 3);\n    return 5;\n  }\n  return 0;\n}\n\n\n\nint explode(__G)\n     __GDEF\n/* Explode an imploded compressed stream.  Based on the general purpose\n   bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding\n   window.  Construct the literal (if any), length, and distance codes and\n   the tables needed to decode them (using huft_build() from inflate.c),\n   and call the appropriate routine for the type of data in the remainder\n   of the stream.  The four routines are nearly identical, differing only\n   in whether the literal is decoded or simply read in, and in how many\n   bits are read in, uncoded, for the low distance bits. */\n{\n  unsigned r;           /* return codes */\n  struct huft *tb;      /* literal code table */\n  struct huft *tl;      /* length code table */\n  struct huft *td;      /* distance code table */\n  unsigned bb;          /* bits for tb */\n  unsigned bl;          /* bits for tl */\n  unsigned bd;          /* bits for td */\n  unsigned bdl;         /* number of uncoded lower distance bits */\n  unsigned l[256];      /* bit lengths for codes */\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n  if (G.redirect_slide)\n    /* For 16-bit systems, it has already been checked at DLL entrance that\n     * the buffer size in G.redirect_size does not exceed unsigned range.\n     */\n    G._wsize = G.redirect_size, redirSlide = G.redirect_buffer;\n  else\n#if defined(USE_DEFLATE64) && defined(INT_16BIT)\n    /* For systems using 16-bit ints, reduce the used buffer size below\n     * the limit of \"unsigned int\" numbers range.\n     */\n    G._wsize = WSIZE>>1, redirSlide = slide;\n#else /* !(USE_DEFLATE64 && INT_16BIT) */\n    G._wsize = WSIZE, redirSlide = slide;\n#endif /* !(USE_DEFLATE64 && INT_16BIT) */\n#endif /* DLL && !NO_SLIDE_REDIR */\n\n  /* Tune base table sizes.  Note: I thought that to truly optimize speed,\n     I would have to select different bl, bd, and bb values for different\n     compressed file sizes.  I was surprised to find out that the values of\n     7, 7, and 9 worked best over a very wide range of sizes, except that\n     bd = 8 worked marginally better for large compressed sizes. */\n  bl = 7;\n  bd = (G.csize + G.incnt) > 200000L ? 8 : 7;\n\n#ifdef DEBUG\n  G.hufts = 0;                    /* initialize huft's malloc'ed */\n#endif\n\n  if (G.lrec.general_purpose_bit_flag & 4)\n  /* With literal tree--minimum match length is 3 */\n  {\n    bb = 9;                     /* base table size for literals */\n    if ((r = get_tree(__G__ l, 256)) != 0)\n      return (int)r;\n    if ((r = huft_build(__G__ l, 256, 256, NULL, NULL, &tb, &bb)) != 0)\n    {\n      if (r == 1)\n        huft_free(tb);\n      return (int)r;\n    }\n    if ((r = get_tree(__G__ l, 64)) != 0) {\n      huft_free(tb);\n      return (int)r;\n    }\n    if ((r = huft_build(__G__ l, 64, 0, cplen3, extra, &tl, &bl)) != 0)\n    {\n      if (r == 1)\n        huft_free(tl);\n      huft_free(tb);\n      return (int)r;\n    }\n  }\n  else\n  /* No literal tree--minimum match length is 2 */\n  {\n    tb = (struct huft *)NULL;\n    if ((r = get_tree(__G__ l, 64)) != 0)\n      return (int)r;\n    if ((r = huft_build(__G__ l, 64, 0, cplen2, extra, &tl, &bl)) != 0)\n    {\n      if (r == 1)\n        huft_free(tl);\n      return (int)r;\n    }\n  }\n\n  if ((r = get_tree(__G__ l, 64)) != 0) {\n    huft_free(tl);\n    if (tb != (struct huft *)NULL) huft_free(tb);\n    return (int)r;\n  }\n  if (G.lrec.general_purpose_bit_flag & 2)      /* true if 8K */\n  {\n    bdl = 7;\n    r = huft_build(__G__ l, 64, 0, cpdist8, extra, &td, &bd);\n  }\n  else                                          /* else 4K */\n  {\n    bdl = 6;\n    r = huft_build(__G__ l, 64, 0, cpdist4, extra, &td, &bd);\n  }\n  if (r != 0)\n  {\n    if (r == 1)\n      huft_free(td);\n    huft_free(tl);\n    if (tb != (struct huft *)NULL) huft_free(tb);\n    return (int)r;\n  }\n\n  if (tb != NULL) {\n    r = explode_lit(__G__ tb, tl, td, bb, bl, bd, bdl);\n    huft_free(tb);\n  } else {\n    r = explode_nolit(__G__ tl, td, bl, bd, bdl);\n  }\n\n  huft_free(td);\n  huft_free(tl);\n  Trace((stderr, \"<%u > \", G.hufts));\n  return (int)r;\n}\n\n/* so explode.c and inflate.c can be compiled together into one object: */\n#undef DECODEHUFT\n#undef NEEDBITS\n#undef DUMPBITS\n#undef wszimpl\n"
  },
  {
    "path": "deps/infozip/unzip60/extract.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  extract.c\n\n  This file contains the high-level routines (\"driver routines\") for extrac-\n  ting and testing zipfile members.  It calls the low-level routines in files\n  explode.c, inflate.c, unreduce.c and unshrink.c.\n\n  Contains:  extract_or_test_files()\n             store_info()\n             find_compr_idx()\n             extract_or_test_entrylist()\n             extract_or_test_member()\n             TestExtraField()\n             test_compr_eb()\n             memextract()\n             memflush()\n             extract_izvms_block()    (VMS or VMS_TEXT_CONV)\n             set_deferred_symlink()   (SYMLINKS only)\n             fnfilter()\n             dircomp()                (SET_DIR_ATTRIB only)\n             UZbunzip2()              (USE_BZIP2 only)\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __EXTRACT_C     /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#endif\n#include \"crc32.h\"\n#include \"crypt.h\"\n\n#define GRRDUMP(buf,len) { \\\n    int i, j; \\\n \\\n    for (j = 0;  j < (len)/16;  ++j) { \\\n        printf(\"        \"); \\\n        for (i = 0;  i < 16;  ++i) \\\n            printf(\"%02x \", (uch)(buf)[i+(j<<4)]); \\\n        printf(\"\\n        \"); \\\n        for (i = 0;  i < 16;  ++i) { \\\n            char c = (char)(buf)[i+(j<<4)]; \\\n \\\n            if (c == '\\n') \\\n                printf(\"\\\\n \"); \\\n            else if (c == '\\r') \\\n                printf(\"\\\\r \"); \\\n            else \\\n                printf(\" %c \", c); \\\n        } \\\n        printf(\"\\n\"); \\\n    } \\\n    if ((len) % 16) { \\\n        printf(\"        \"); \\\n        for (i = j<<4;  i < (len);  ++i) \\\n            printf(\"%02x \", (uch)(buf)[i]); \\\n        printf(\"\\n        \"); \\\n        for (i = j<<4;  i < (len);  ++i) { \\\n            char c = (char)(buf)[i]; \\\n \\\n            if (c == '\\n') \\\n                printf(\"\\\\n \"); \\\n            else if (c == '\\r') \\\n                printf(\"\\\\r \"); \\\n            else \\\n                printf(\" %c \", c); \\\n        } \\\n        printf(\"\\n\"); \\\n    } \\\n}\n\nstatic int store_info OF((__GPRO));\n#ifdef SET_DIR_ATTRIB\nstatic int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,\n                ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,\n                unsigned *pnum_dirs, direntry **pdirlist,\n                int error_in_archive));\n#else\nstatic int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,\n                ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,\n                int error_in_archive));\n#endif\nstatic int extract_or_test_member OF((__GPRO));\n#ifndef SFX\n   static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));\n   static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,\n        unsigned compr_offset,\n        int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,\n                              uch *eb_ucptr, ulg eb_ucsize)));\n#endif\n#if (defined(VMS) || defined(VMS_TEXT_CONV))\n   static void decompress_bits OF((uch *outptr, unsigned needlen,\n                                   ZCONST uch *bitptr));\n#endif\n#ifdef SYMLINKS\n   static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry));\n#endif\n#ifdef SET_DIR_ATTRIB\n   static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));\n#endif\n\n\n\n/*******************************/\n/*  Strings used in extract.c  */\n/*******************************/\n\nstatic ZCONST char Far VersionMsg[] =\n  \"   skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\\n\";\nstatic ZCONST char Far ComprMsgNum[] =\n  \"   skipping: %-22s  unsupported compression method %u\\n\";\n#ifndef SFX\n   static ZCONST char Far ComprMsgName[] =\n     \"   skipping: %-22s  `%s' method not supported\\n\";\n   static ZCONST char Far CmprNone[]       = \"store\";\n   static ZCONST char Far CmprShrink[]     = \"shrink\";\n   static ZCONST char Far CmprReduce[]     = \"reduce\";\n   static ZCONST char Far CmprImplode[]    = \"implode\";\n   static ZCONST char Far CmprTokenize[]   = \"tokenize\";\n   static ZCONST char Far CmprDeflate[]    = \"deflate\";\n   static ZCONST char Far CmprDeflat64[]   = \"deflate64\";\n   static ZCONST char Far CmprDCLImplode[] = \"DCL implode\";\n   static ZCONST char Far CmprBzip[]       = \"bzip2\";\n   static ZCONST char Far CmprLZMA[]       = \"LZMA\";\n   static ZCONST char Far CmprIBMTerse[]   = \"IBM/Terse\";\n   static ZCONST char Far CmprIBMLZ77[]    = \"IBM LZ77\";\n   static ZCONST char Far CmprWavPack[]    = \"WavPack\";\n   static ZCONST char Far CmprPPMd[]       = \"PPMd\";\n   static ZCONST char Far *ComprNames[NUM_METHODS] = {\n     CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,\n     CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode,\n     CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd\n   };\n   static ZCONST unsigned ComprIDs[NUM_METHODS] = {\n     STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4,\n     IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED,\n     BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED\n   };\n#endif /* !SFX */\nstatic ZCONST char Far FilNamMsg[] =\n  \"%s:  bad filename length (%s)\\n\";\n#ifndef SFX\n   static ZCONST char Far WarnNoMemCFName[] =\n     \"%s:  warning, no memory for comparison with local header\\n\";\n   static ZCONST char Far LvsCFNamMsg[] =\n     \"%s:  mismatching \\\"local\\\" filename (%s),\\n\\\n         continuing with \\\"central\\\" filename version\\n\";\n#endif /* !SFX */\n#if (!defined(SFX) && defined(UNICODE_SUPPORT))\n   static ZCONST char Far GP11FlagsDiffer[] =\n     \"file #%lu (%s):\\n\\\n         mismatch between local and central GPF bit 11 (\\\"UTF-8\\\"),\\n\\\n         continuing with central flag (IsUTF8 = %d)\\n\";\n#endif /* !SFX && UNICODE_SUPPORT */\nstatic ZCONST char Far WrnStorUCSizCSizDiff[] =\n  \"%s:  ucsize %s <> csize %s for STORED entry\\n\\\n         continuing with \\\"compressed\\\" size value\\n\";\nstatic ZCONST char Far ExtFieldMsg[] =\n  \"%s:  bad extra field length (%s)\\n\";\nstatic ZCONST char Far OffsetMsg[] =\n  \"file #%lu:  bad zipfile offset (%s):  %ld\\n\";\nstatic ZCONST char Far ExtractMsg[] =\n  \"%8sing: %-22s  %s%s\";\n#ifndef SFX\n   static ZCONST char Far LengthMsg[] =\n     \"%s  %s:  %s bytes required to uncompress to %s bytes;\\n    %s\\\n      supposed to require %s bytes%s%s%s\\n\";\n#endif\n\nstatic ZCONST char Far BadFileCommLength[] = \"%s:  bad file comment length\\n\";\nstatic ZCONST char Far LocalHdrSig[] = \"local header sig\";\nstatic ZCONST char Far BadLocalHdr[] = \"file #%lu:  bad local header\\n\";\nstatic ZCONST char Far AttemptRecompensate[] =\n  \"  (attempting to re-compensate)\\n\";\n#ifndef SFX\n   static ZCONST char Far BackslashPathSep[] =\n     \"warning:  %s appears to use backslashes as path separators\\n\";\n#endif\nstatic ZCONST char Far AbsolutePathWarning[] =\n  \"warning:  stripped absolute path spec from %s\\n\";\nstatic ZCONST char Far SkipVolumeLabel[] =\n  \"   skipping: %-22s  %svolume label\\n\";\n\n#ifdef SET_DIR_ATTRIB   /* messages of code for setting directory attributes */\n   static ZCONST char Far DirlistEntryNoMem[] =\n     \"warning:  cannot alloc memory for dir times/permissions/UID/GID\\n\";\n   static ZCONST char Far DirlistSortNoMem[] =\n     \"warning:  cannot alloc memory to sort dir times/perms/etc.\\n\";\n   static ZCONST char Far DirlistSetAttrFailed[] =\n     \"warning:  set times/attribs failed for %s\\n\";\n   static ZCONST char Far DirlistFailAttrSum[] =\n     \"     failed setting times/attribs for %lu dir entries\";\n#endif\n\n#ifdef SYMLINKS         /* messages of the deferred symlinks handler */\n   static ZCONST char Far SymLnkWarnNoMem[] =\n     \"warning:  deferred symlink (%s) failed:\\n\\\n          out of memory\\n\";\n   static ZCONST char Far SymLnkWarnInvalid[] =\n     \"warning:  deferred symlink (%s) failed:\\n\\\n          invalid placeholder file\\n\";\n   static ZCONST char Far SymLnkDeferred[] =\n     \"finishing deferred symbolic links:\\n\";\n   static ZCONST char Far SymLnkFinish[] =\n     \"  %-22s -> %s\\n\";\n#endif\n\n#ifndef WINDLL\n   static ZCONST char Far ReplaceQuery[] =\n# ifdef VMS\n     \"new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: \";\n# else\n     \"replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: \";\n# endif\n   static ZCONST char Far AssumeNone[] =\n     \" NULL\\n(EOF or read error, treating as \\\"[N]one\\\" ...)\\n\";\n   static ZCONST char Far NewNameQuery[] = \"new name: \";\n   static ZCONST char Far InvalidResponse[] =\n     \"error:  invalid response [%s]\\n\";\n#endif /* !WINDLL */\n\nstatic ZCONST char Far ErrorInArchive[] =\n  \"At least one %serror was detected in %s.\\n\";\nstatic ZCONST char Far ZeroFilesTested[] =\n  \"Caution:  zero files tested in %s.\\n\";\n\n#ifndef VMS\n   static ZCONST char Far VMSFormatQuery[] =\n     \"\\n%s:  stored in VMS format.  Extract anyway? (y/n) \";\n#endif\n\n#if CRYPT\n   static ZCONST char Far SkipCannotGetPasswd[] =\n     \"   skipping: %-22s  unable to get password\\n\";\n   static ZCONST char Far SkipIncorrectPasswd[] =\n     \"   skipping: %-22s  incorrect password\\n\";\n   static ZCONST char Far FilesSkipBadPasswd[] =\n     \"%lu file%s skipped because of incorrect password.\\n\";\n   static ZCONST char Far MaybeBadPasswd[] =\n     \"    (may instead be incorrect password)\\n\";\n#else\n   static ZCONST char Far SkipEncrypted[] =\n     \"   skipping: %-22s  encrypted (not supported)\\n\";\n#endif\n\nstatic ZCONST char Far NoErrInCompData[] =\n  \"No errors detected in compressed data of %s.\\n\";\nstatic ZCONST char Far NoErrInTestedFiles[] =\n  \"No errors detected in %s for the %lu file%s tested.\\n\";\nstatic ZCONST char Far FilesSkipped[] =\n  \"%lu file%s skipped because of unsupported compression or encoding.\\n\";\n\nstatic ZCONST char Far ErrUnzipFile[] = \"  error:  %s%s %s\\n\";\nstatic ZCONST char Far ErrUnzipNoFile[] = \"\\n  error:  %s%s\\n\";\nstatic ZCONST char Far NotEnoughMem[] = \"not enough memory to \";\nstatic ZCONST char Far InvalidComprData[] = \"invalid compressed data to \";\nstatic ZCONST char Far Inflate[] = \"inflate\";\n#ifdef USE_BZIP2\n  static ZCONST char Far BUnzip[] = \"bunzip\";\n#endif\n\n#ifndef SFX\n   static ZCONST char Far Explode[] = \"explode\";\n#ifndef LZW_CLEAN\n   static ZCONST char Far Unshrink[] = \"unshrink\";\n#endif\n#endif\n\n#if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))\n   static ZCONST char Far FileTruncated[] =\n     \"warning:  %s is probably truncated\\n\";\n#endif\n\nstatic ZCONST char Far FileUnknownCompMethod[] =\n  \"%s:  unknown compression method\\n\";\nstatic ZCONST char Far BadCRC[] = \" bad CRC %08lx  (should be %08lx)\\n\";\n\n      /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */\nchar ZCONST Far TruncEAs[] = \" compressed EA data missing (%d bytes)%s\";\nchar ZCONST Far TruncNTSD[] =\n  \" compressed WinNT security data missing (%d bytes)%s\";\n\n#ifndef SFX\n   static ZCONST char Far InconsistEFlength[] = \"bad extra-field entry:\\n \\\n     EF block length (%u bytes) exceeds remaining EF data (%u bytes)\\n\";\n   static ZCONST char Far InvalidComprDataEAs[] =\n     \" invalid compressed data for EAs\\n\";\n#  if (defined(WIN32) && defined(NTSD_EAS))\n     static ZCONST char Far InvalidSecurityEAs[] =\n       \" EAs fail security check\\n\";\n#  endif\n   static ZCONST char Far UnsuppNTSDVersEAs[] =\n     \" unsupported NTSD EAs version %d\\n\";\n   static ZCONST char Far BadCRC_EAs[] = \" bad CRC for extended attributes\\n\";\n   static ZCONST char Far UnknComprMethodEAs[] =\n     \" unknown compression method for EAs (%u)\\n\";\n   static ZCONST char Far NotEnoughMemEAs[] =\n     \" out of memory while inflating EAs\\n\";\n   static ZCONST char Far UnknErrorEAs[] =\n     \" unknown error on extended attributes\\n\";\n#endif /* !SFX */\n\nstatic ZCONST char Far UnsupportedExtraField[] =\n  \"\\nerror:  unsupported extra-field compression type (%u)--skipping\\n\";\nstatic ZCONST char Far BadExtraFieldCRC[] =\n  \"error [%s]:  bad extra-field CRC %08lx (should be %08lx)\\n\";\n\n\n\n\n\n/**************************************/\n/*  Function extract_or_test_files()  */\n/**************************************/\n\nint extract_or_test_files(__G)    /* return PK-type error code */\n     __GDEF\n{\n    unsigned i, j;\n    zoff_t cd_bufstart;\n    uch *cd_inptr;\n    int cd_incnt;\n    ulg filnum=0L, blknum=0L;\n    int reached_end;\n#ifndef SFX\n    int no_endsig_found;\n#endif\n    int error, error_in_archive=PK_COOL;\n    int *fn_matched=NULL, *xn_matched=NULL;\n    zucn_t members_processed;\n    ulg num_skipped=0L, num_bad_pwd=0L;\n    zoff_t old_extra_bytes = 0L;\n#ifdef SET_DIR_ATTRIB\n    unsigned num_dirs=0;\n    direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;\n#endif\n\n    /*\n     * First, two general initializations are applied. These have been moved\n     * here from process_zipfiles() because they are only needed for accessing\n     * and/or extracting the data content of the zip archive.\n     */\n\n    /* a) initialize the CRC table pointer (once) */\n    if (CRC_32_TAB == NULL) {\n        if ((CRC_32_TAB = get_crc_table()) == NULL) {\n            return PK_MEM;\n        }\n    }\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    /* b) check out if specified extraction root directory exists */\n    if (uO.exdir != (char *)NULL && G.extract_flag) {\n        G.create_dirs = !uO.fflag;\n        if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {\n            /* out of memory, or file in way */\n            return (error == MPN_NOMEM ? PK_MEM : PK_ERR);\n        }\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    The basic idea of this function is as follows.  Since the central di-\n    rectory lies at the end of the zipfile and the member files lie at the\n    beginning or middle or wherever, it is not very desirable to simply\n    read a central directory entry, jump to the member and extract it, and\n    then jump back to the central directory.  In the case of a large zipfile\n    this would lead to a whole lot of disk-grinding, especially if each mem-\n    ber file is small.  Instead, we read from the central directory the per-\n    tinent information for a block of files, then go extract/test the whole\n    block.  Thus this routine contains two small(er) loops within a very\n    large outer loop:  the first of the small ones reads a block of files\n    from the central directory; the second extracts or tests each file; and\n    the outer one loops over blocks.  There's some file-pointer positioning\n    stuff in between, but that's about it.  Btw, it's because of this jump-\n    ing around that we can afford to be lenient if an error occurs in one of\n    the member files:  we should still be able to go find the other members,\n    since we know the offset of each from the beginning of the zipfile.\n  ---------------------------------------------------------------------------*/\n\n    G.pInfo = G.info;\n\n#if CRYPT\n    G.newzip = TRUE;\n#endif\n#ifndef SFX\n    G.reported_backslash = FALSE;\n#endif\n\n    /* malloc space for check on unmatched filespecs (OK if one or both NULL) */\n    if (G.filespecs > 0  &&\n        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)\n        for (i = 0;  i < G.filespecs;  ++i)\n            fn_matched[i] = FALSE;\n    if (G.xfilespecs > 0  &&\n        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)\n        for (i = 0;  i < G.xfilespecs;  ++i)\n            xn_matched[i] = FALSE;\n\n/*---------------------------------------------------------------------------\n    Begin main loop over blocks of member files.  We know the entire central\n    directory is on this disk:  we would not have any of this information un-\n    less the end-of-central-directory record was on this disk, and we would\n    not have gotten to this routine unless this is also the disk on which\n    the central directory starts.  In practice, this had better be the ONLY\n    disk in the archive, but we'll add multi-disk support soon.\n  ---------------------------------------------------------------------------*/\n\n    members_processed = 0;\n#ifndef SFX\n    no_endsig_found = FALSE;\n#endif\n    reached_end = FALSE;\n    while (!reached_end) {\n        j = 0;\n#ifdef AMIGA\n        memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));\n#endif\n\n        /*\n         * Loop through files in central directory, storing offsets, file\n         * attributes, case-conversion and text-conversion flags until block\n         * size is reached.\n         */\n\n        while ((j < DIR_BLKSIZ)) {\n            G.pInfo = &G.info[j];\n\n            if (readbuf(__G__ G.sig, 4) == 0) {\n                error_in_archive = PK_EOF;\n                reached_end = TRUE;     /* ...so no more left to do */\n                break;\n            }\n            if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a new entry? */\n                /* no new central directory entry\n                 * -> is the number of processed entries compatible with the\n                 *    number of entries as stored in the end_central record?\n                 */\n                if ((members_processed\n                     & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))\n                    == G.ecrec.total_entries_central_dir) {\n#ifndef SFX\n                    /* yes, so look if we ARE back at the end_central record\n                     */\n                    no_endsig_found =\n                      ( (memcmp(G.sig,\n                                (G.ecrec.have_ecr64 ?\n                                 end_central64_sig : end_central_sig),\n                                4) != 0)\n                       && (!G.ecrec.is_zip64_archive)\n                       && (memcmp(G.sig, end_central_sig, 4) != 0)\n                      );\n#endif /* !SFX */\n                } else {\n                    /* no; we have found an error in the central directory\n                     * -> report it and stop searching for more Zip entries\n                     */\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(ReportMsg)));\n                    error_in_archive = PK_BADERR;\n                }\n                reached_end = TRUE;     /* ...so no more left to do */\n                break;\n            }\n            /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */\n            if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {\n                error_in_archive = error;   /* only PK_EOF defined */\n                reached_end = TRUE;     /* ...so no more left to do */\n                break;\n            }\n            if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=\n                 PK_COOL)\n            {\n                if (error > error_in_archive)\n                    error_in_archive = error;\n                if (error > PK_WARN) {  /* fatal:  no more left to do */\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(FilNamMsg),\n                      FnFilter1(G.filename), \"central\"));\n                    reached_end = TRUE;\n                    break;\n                }\n            }\n            if ((error = do_string(__G__ G.crec.extra_field_length,\n                EXTRA_FIELD)) != 0)\n            {\n                if (error > error_in_archive)\n                    error_in_archive = error;\n                if (error > PK_WARN) {  /* fatal */\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(ExtFieldMsg),\n                      FnFilter1(G.filename), \"central\"));\n                    reached_end = TRUE;\n                    break;\n                }\n            }\n#ifdef AMIGA\n            G.filenote_slot = j;\n            if ((error = do_string(__G__ G.crec.file_comment_length,\n                                   uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)\n#else\n            if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))\n                != PK_COOL)\n#endif\n            {\n                if (error > error_in_archive)\n                    error_in_archive = error;\n                if (error > PK_WARN) {  /* fatal */\n                    Info(slide, 0x421, ((char *)slide,\n                      LoadFarString(BadFileCommLength),\n                      FnFilter1(G.filename)));\n                    reached_end = TRUE;\n                    break;\n                }\n            }\n            if (G.process_all_files) {\n                if (store_info(__G))\n                    ++j;  /* file is OK; info[] stored; continue with next */\n                else\n                    ++num_skipped;\n            } else {\n                int   do_this_file;\n\n                if (G.filespecs == 0)\n                    do_this_file = TRUE;\n                else {  /* check if this entry matches an `include' argument */\n                    do_this_file = FALSE;\n                    for (i = 0; i < G.filespecs; i++)\n                        if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {\n                            do_this_file = TRUE;  /* ^-- ignore case or not? */\n                            if (fn_matched)\n                                fn_matched[i] = TRUE;\n                            break;       /* found match, so stop looping */\n                        }\n                }\n                if (do_this_file) {  /* check if this is an excluded file */\n                    for (i = 0; i < G.xfilespecs; i++)\n                        if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {\n                            do_this_file = FALSE; /* ^-- ignore case or not? */\n                            if (xn_matched)\n                                xn_matched[i] = TRUE;\n                            break;\n                        }\n                }\n                if (do_this_file) {\n                    if (store_info(__G))\n                        ++j;            /* file is OK */\n                    else\n                        ++num_skipped;  /* unsupp. compression or encryption */\n                }\n            } /* end if (process_all_files) */\n\n            members_processed++;\n\n        } /* end while-loop (adding files to current block) */\n\n        /* save position in central directory so can come back later */\n        cd_bufstart = G.cur_zipfile_bufstart;\n        cd_inptr = G.inptr;\n        cd_incnt = G.incnt;\n\n    /*-----------------------------------------------------------------------\n        Second loop:  process files in current block, extracting or testing\n        each one.\n      -----------------------------------------------------------------------*/\n\n        error = extract_or_test_entrylist(__G__ j,\n                        &filnum, &num_bad_pwd, &old_extra_bytes,\n#ifdef SET_DIR_ATTRIB\n                        &num_dirs, &dirlist,\n#endif\n                        error_in_archive);\n        if (error != PK_COOL) {\n            if (error > error_in_archive)\n                error_in_archive = error;\n            /* ...and keep going (unless disk full or user break) */\n            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {\n                /* clear reached_end to signal premature stop ... */\n                reached_end = FALSE;\n                /* ... and cancel scanning the central directory */\n                break;\n            }\n        }\n\n\n        /*\n         * Jump back to where we were in the central directory, then go and do\n         * the next batch of files.\n         */\n\n#ifdef USE_STRM_INPUT\n        zfseeko(G.zipfd, cd_bufstart, SEEK_SET);\n        G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n        G.cur_zipfile_bufstart =\n          zlseek(G.zipfd, cd_bufstart, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n        read(G.zipfd, (char *)G.inbuf, INBUFSIZ);  /* been here before... */\n        G.inptr = cd_inptr;\n        G.incnt = cd_incnt;\n        ++blknum;\n\n#ifdef TEST\n        printf(\"\\ncd_bufstart = %ld (%.8lXh)\\n\", cd_bufstart, cd_bufstart);\n        printf(\"cur_zipfile_bufstart = %ld (%.8lXh)\\n\", cur_zipfile_bufstart,\n          cur_zipfile_bufstart);\n        printf(\"inptr-inbuf = %d\\n\", G.inptr-G.inbuf);\n        printf(\"incnt = %d\\n\\n\", G.incnt);\n#endif\n\n    } /* end while-loop (blocks of files in central directory) */\n\n/*---------------------------------------------------------------------------\n    Process the list of deferred symlink extractions and finish up\n    the symbolic links.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SYMLINKS\n    if (G.slink_last != NULL) {\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred)));\n        while (G.slink_head != NULL) {\n           set_deferred_symlink(__G__ G.slink_head);\n           /* remove the processed entry from the chain and free its memory */\n           G.slink_last = G.slink_head;\n           G.slink_head = G.slink_last->next;\n           free(G.slink_last);\n       }\n       G.slink_last = NULL;\n    }\n#endif /* SYMLINKS */\n\n/*---------------------------------------------------------------------------\n    Go back through saved list of directories, sort and set times/perms/UIDs\n    and GIDs from the deepest level on up.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SET_DIR_ATTRIB\n    if (num_dirs > 0) {\n        sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));\n        if (sorted_dirlist == (direntry **)NULL) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(DirlistSortNoMem)));\n            while (dirlist != (direntry *)NULL) {\n                direntry *d = dirlist;\n\n                dirlist = dirlist->next;\n                free(d);\n            }\n        } else {\n            ulg ndirs_fail = 0;\n\n            if (num_dirs == 1)\n                sorted_dirlist[0] = dirlist;\n            else {\n                for (i = 0;  i < num_dirs;  ++i) {\n                    sorted_dirlist[i] = dirlist;\n                    dirlist = dirlist->next;\n                }\n                qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *),\n                  dircomp);\n            }\n\n            Trace((stderr, \"setting directory times/perms/attributes\\n\"));\n            for (i = 0;  i < num_dirs;  ++i) {\n                direntry *d = sorted_dirlist[i];\n\n                Trace((stderr, \"dir = %s\\n\", d->fn));\n                if ((error = set_direc_attribs(__G__ d)) != PK_OK) {\n                    ndirs_fail++;\n                    Info(slide, 0x201, ((char *)slide,\n                      LoadFarString(DirlistSetAttrFailed), d->fn));\n                    if (!error_in_archive)\n                        error_in_archive = error;\n                }\n                free(d);\n            }\n            free(sorted_dirlist);\n            if (!uO.tflag && QCOND2) {\n                if (ndirs_fail > 0)\n                    Info(slide, 0, ((char *)slide,\n                      LoadFarString(DirlistFailAttrSum), ndirs_fail));\n            }\n        }\n    }\n#endif /* SET_DIR_ATTRIB */\n\n/*---------------------------------------------------------------------------\n    Check for unmatched filespecs on command line and print warning if any\n    found.  Free allocated memory.  (But suppress check when central dir\n    scan was interrupted prematurely.)\n  ---------------------------------------------------------------------------*/\n\n    if (fn_matched) {\n        if (reached_end) for (i = 0;  i < G.filespecs;  ++i)\n            if (!fn_matched[i]) {\n#ifdef DLL\n                if (!G.redirect_data && !G.redirect_text)\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(FilenameNotMatched), G.pfnames[i]));\n                else\n                    setFileNotFound(__G);\n#else\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(FilenameNotMatched), G.pfnames[i]));\n#endif\n                if (error_in_archive <= PK_WARN)\n                    error_in_archive = PK_FIND;   /* some files not found */\n            }\n        free((zvoid *)fn_matched);\n    }\n    if (xn_matched) {\n        if (reached_end) for (i = 0;  i < G.xfilespecs;  ++i)\n            if (!xn_matched[i])\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));\n        free((zvoid *)xn_matched);\n    }\n\n/*---------------------------------------------------------------------------\n    Now, all locally allocated memory has been released.  When the central\n    directory processing has been interrupted prematurely, it is safe to\n    return immediately.  All completeness checks and summary messages are\n    skipped in this case.\n  ---------------------------------------------------------------------------*/\n    if (!reached_end)\n        return error_in_archive;\n\n/*---------------------------------------------------------------------------\n    Double-check that we're back at the end-of-central-directory record, and\n    print quick summary of results, if we were just testing the archive.  We\n    send the summary to stdout so that people doing the testing in the back-\n    ground and redirecting to a file can just do a \"tail\" on the output file.\n  ---------------------------------------------------------------------------*/\n\n#ifndef SFX\n    if (no_endsig_found) {                      /* just to make sure */\n        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));\n        Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));\n        if (!error_in_archive)       /* don't overwrite stronger error */\n            error_in_archive = PK_WARN;\n    }\n#endif /* !SFX */\n    if (uO.tflag) {\n        ulg num = filnum - num_bad_pwd;\n\n        if (uO.qflag < 2) {        /* GRR 930710:  was (uO.qflag == 1) */\n            if (error_in_archive)\n                Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),\n                  (error_in_archive == PK_WARN)? \"warning-\" : \"\", G.zipfn));\n            else if (num == 0L)\n                Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),\n                  G.zipfn));\n            else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L))\n                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),\n                  G.zipfn));\n            else\n                Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)\n                  , G.zipfn, num, (num==1L)? \"\":\"s\"));\n            if (num_skipped > 0L)\n                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),\n                  num_skipped, (num_skipped==1L)? \"\":\"s\"));\n#if CRYPT\n            if (num_bad_pwd > 0L)\n                Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)\n                  , num_bad_pwd, (num_bad_pwd==1L)? \"\":\"s\"));\n#endif /* CRYPT */\n        }\n    }\n\n    /* give warning if files not tested or extracted (first condition can still\n     * happen if zipfile is empty and no files specified on command line) */\n\n    if ((filnum == 0) && error_in_archive <= PK_WARN) {\n        if (num_skipped > 0L)\n            error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */\n        else\n            error_in_archive = PK_FIND;  /* no files found at all */\n    }\n#if CRYPT\n    else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)\n        error_in_archive = IZ_BADPWD;    /* bad passwd => all files skipped */\n#endif\n    else if ((num_skipped > 0L) && error_in_archive <= PK_WARN)\n        error_in_archive = IZ_UNSUP;     /* was PK_WARN; Jean-loup complained */\n#if CRYPT\n    else if ((num_bad_pwd > 0L) && !error_in_archive)\n        error_in_archive = PK_WARN;\n#endif\n\n    return error_in_archive;\n\n} /* end function extract_or_test_files() */\n\n\n\n\n\n/***************************/\n/*  Function store_info()  */\n/***************************/\n\nstatic int store_info(__G)   /* return 0 if skipping, 1 if OK */\n    __GDEF\n{\n#ifdef USE_BZIP2\n#  define UNKN_BZ2 (G.crec.compression_method!=BZIPPED)\n#else\n#  define UNKN_BZ2 TRUE       /* bzip2 unknown */\n#endif\n\n#ifdef USE_LZMA\n#  define UNKN_LZMA (G.crec.compression_method!=LZMAED)\n#else\n#  define UNKN_LZMA TRUE      /* LZMA unknown */\n#endif\n\n#ifdef USE_WAVP\n#  define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)\n#else\n#  define UNKN_WAVP TRUE      /* WavPack unknown */\n#endif\n\n#ifdef USE_PPMD\n#  define UNKN_PPMD (G.crec.compression_method!=PPMDED)\n#else\n#  define UNKN_PPMD TRUE      /* PPMd unknown */\n#endif\n\n#ifdef SFX\n#  ifdef USE_DEFLATE64\n#    define UNKN_COMPR \\\n     (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \\\n      && G.crec.compression_method>ENHDEFLATED \\\n      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n#  else\n#    define UNKN_COMPR \\\n     (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\\\n      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n#  endif\n#else\n#  ifdef COPYRIGHT_CLEAN  /* no reduced files */\n#    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \\\n                      G.crec.compression_method <= REDUCED4)\n#  else\n#    define UNKN_RED  FALSE  /* reducing not unknown */\n#  endif\n#  ifdef LZW_CLEAN  /* no shrunk files */\n#    define UNKN_SHR (G.crec.compression_method == SHRUNK)\n#  else\n#    define UNKN_SHR  FALSE  /* unshrinking not unknown */\n#  endif\n#  ifdef USE_DEFLATE64\n#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n     G.crec.compression_method==TOKENIZED || \\\n     (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n      && UNKN_WAVP && UNKN_PPMD))\n#  else\n#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n     G.crec.compression_method==TOKENIZED || \\\n     (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n      && UNKN_WAVP && UNKN_PPMD))\n#  endif\n#endif\n\n#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))\n    int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);\n#   define UNZVERS_SUPPORT  unzvers_support\n#else\n#   define UNZVERS_SUPPORT  UNZIP_VERSION\n#endif\n\n/*---------------------------------------------------------------------------\n    Check central directory info for version/compatibility requirements.\n  ---------------------------------------------------------------------------*/\n\n    G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */\n    G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */\n    G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */\n    G.pInfo->crc = G.crec.crc32;\n    G.pInfo->compr_size = G.crec.csize;\n    G.pInfo->uncompr_size = G.crec.ucsize;\n\n    switch (uO.aflag) {\n        case 0:\n            G.pInfo->textmode = FALSE;   /* bit field */\n            break;\n        case 1:\n            G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */\n            break;\n        default:  /* case 2: */\n            G.pInfo->textmode = TRUE;\n            break;\n    }\n\n    if (G.crec.version_needed_to_extract[1] == VMS_) {\n        if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {\n            if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n                Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n                  FnFilter1(G.filename), \"VMS\",\n                  G.crec.version_needed_to_extract[0] / 10,\n                  G.crec.version_needed_to_extract[0] % 10,\n                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));\n            return 0;\n        }\n#ifndef VMS   /* won't be able to use extra field, but still have data */\n        else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */\n            Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),\n              FnFilter1(G.filename)));\n            fgets(G.answerbuf, sizeof(G.answerbuf), stdin);\n            if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))\n                return 0;\n        }\n#endif /* !VMS */\n    /* usual file type:  don't need VMS to extract */\n    } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {\n        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n            Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n              FnFilter1(G.filename), \"PK\",\n              G.crec.version_needed_to_extract[0] / 10,\n              G.crec.version_needed_to_extract[0] % 10,\n              UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));\n        return 0;\n    }\n\n    if (UNKN_COMPR) {\n        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {\n#ifndef SFX\n            unsigned cmpridx;\n\n            if ((cmpridx = find_compr_idx(G.crec.compression_method))\n                < NUM_METHODS)\n                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),\n                  FnFilter1(G.filename),\n                  LoadFarStringSmall(ComprNames[cmpridx])));\n            else\n#endif\n                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),\n                  FnFilter1(G.filename),\n                  G.crec.compression_method));\n        }\n        return 0;\n    }\n#if (!CRYPT)\n    if (G.pInfo->encrypted) {\n        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n            Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),\n              FnFilter1(G.filename)));\n        return 0;\n    }\n#endif /* !CRYPT */\n\n#ifndef SFX\n    /* store a copy of the central header filename for later comparison */\n    if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),\n          FnFilter1(G.filename)));\n    } else\n        zfstrcpy(G.pInfo->cfilname, G.filename);\n#endif /* !SFX */\n\n    /* map whatever file attributes we have into the local format */\n    mapattr(__G);   /* GRR:  worry about return value later */\n\n    G.pInfo->diskstart = G.crec.disk_number_start;\n    G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;\n    return 1;\n\n} /* end function store_info() */\n\n\n\n\n\n#ifndef SFX\n/*******************************/\n/*  Function find_compr_idx()  */\n/*******************************/\n\nunsigned find_compr_idx(compr_methodnum)\n    unsigned compr_methodnum;\n{\n    unsigned i;\n\n    for (i = 0; i < NUM_METHODS; i++) {\n        if (ComprIDs[i] == compr_methodnum) break;\n    }\n    return i;\n}\n#endif /* !SFX */\n\n\n\n\n\n/******************************************/\n/*  Function extract_or_test_entrylist()  */\n/******************************************/\n\nstatic int extract_or_test_entrylist(__G__ numchunk,\n                pfilnum, pnum_bad_pwd, pold_extra_bytes,\n#ifdef SET_DIR_ATTRIB\n                pnum_dirs, pdirlist,\n#endif\n                error_in_archive)    /* return PK-type error code */\n    __GDEF\n    unsigned numchunk;\n    ulg *pfilnum;\n    ulg *pnum_bad_pwd;\n    zoff_t *pold_extra_bytes;\n#ifdef SET_DIR_ATTRIB\n    unsigned *pnum_dirs;\n    direntry **pdirlist;\n#endif\n    int error_in_archive;\n{\n    unsigned i;\n    int renamed, query;\n    int skip_entry;\n    zoff_t bufstart, inbuf_offset, request;\n    int error, errcode;\n\n/* possible values for local skip_entry flag: */\n#define SKIP_NO         0       /* do not skip this entry */\n#define SKIP_Y_EXISTING 1       /* skip this entry, do not overwrite file */\n#define SKIP_Y_NONEXIST 2       /* skip this entry, do not create new file */\n\n    /*-----------------------------------------------------------------------\n        Second loop:  process files in current block, extracting or testing\n        each one.\n      -----------------------------------------------------------------------*/\n\n    for (i = 0; i < numchunk; ++i) {\n        (*pfilnum)++;   /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */\n        G.pInfo = &G.info[i];\n#ifdef NOVELL_BUG_FAILSAFE\n        G.dne = FALSE;  /* assume file exists until stat() says otherwise */\n#endif\n\n        /* if the target position is not within the current input buffer\n         * (either haven't yet read far enough, or (maybe) skipping back-\n         * ward), skip to the target position and reset readbuf(). */\n\n        /* seek_zipf(__G__ pInfo->offset);  */\n        request = G.pInfo->offset + G.extra_bytes;\n        inbuf_offset = request % INBUFSIZ;\n        bufstart = request - inbuf_offset;\n\n        Trace((stderr, \"\\ndebug: request = %ld, inbuf_offset = %ld\\n\",\n          (long)request, (long)inbuf_offset));\n        Trace((stderr,\n          \"debug: bufstart = %ld, cur_zipfile_bufstart = %ld\\n\",\n          (long)bufstart, (long)G.cur_zipfile_bufstart));\n        if (request < 0) {\n            Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),\n              G.zipfn, LoadFarString(ReportMsg)));\n            error_in_archive = PK_ERR;\n            if (*pfilnum == 1 && G.extra_bytes != 0L) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(AttemptRecompensate)));\n                *pold_extra_bytes = G.extra_bytes;\n                G.extra_bytes = 0L;\n                request = G.pInfo->offset;  /* could also check if != 0 */\n                inbuf_offset = request % INBUFSIZ;\n                bufstart = request - inbuf_offset;\n                Trace((stderr, \"debug: request = %ld, inbuf_offset = %ld\\n\",\n                  (long)request, (long)inbuf_offset));\n                Trace((stderr,\n                  \"debug: bufstart = %ld, cur_zipfile_bufstart = %ld\\n\",\n                  (long)bufstart, (long)G.cur_zipfile_bufstart));\n                /* try again */\n                if (request < 0) {\n                    Trace((stderr,\n                      \"debug: recompensated request still < 0\\n\"));\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarStringSmall(SeekMsg),\n                      G.zipfn, LoadFarString(ReportMsg)));\n                    error_in_archive = PK_BADERR;\n                    continue;\n                }\n            } else {\n                error_in_archive = PK_BADERR;\n                continue;  /* this one hosed; try next */\n            }\n        }\n\n        if (bufstart != G.cur_zipfile_bufstart) {\n            Trace((stderr, \"debug: bufstart != cur_zipfile_bufstart\\n\"));\n#ifdef USE_STRM_INPUT\n            zfseeko(G.zipfd, bufstart, SEEK_SET);\n            G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n            G.cur_zipfile_bufstart =\n              zlseek(G.zipfd, bufstart, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n            if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)\n            {\n                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n                  *pfilnum, \"lseek\", (long)bufstart));\n                error_in_archive = PK_BADERR;\n                continue;   /* can still do next file */\n            }\n            G.inptr = G.inbuf + (int)inbuf_offset;\n            G.incnt -= (int)inbuf_offset;\n        } else {\n            G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;\n            G.inptr = G.inbuf + (int)inbuf_offset;\n        }\n\n        /* should be in proper position now, so check for sig */\n        if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */\n            Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n              *pfilnum, \"EOF\", (long)request));\n            error_in_archive = PK_BADERR;\n            continue;   /* but can still try next one */\n        }\n        if (memcmp(G.sig, local_hdr_sig, 4)) {\n            Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n              *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));\n            /*\n                GRRDUMP(G.sig, 4)\n                GRRDUMP(local_hdr_sig, 4)\n             */\n            error_in_archive = PK_ERR;\n            if ((*pfilnum == 1 && G.extra_bytes != 0L) ||\n                (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(AttemptRecompensate)));\n                if (G.extra_bytes) {\n                    *pold_extra_bytes = G.extra_bytes;\n                    G.extra_bytes = 0L;\n                } else\n                    G.extra_bytes = *pold_extra_bytes; /* third attempt */\n                if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||\n                    (readbuf(__G__ G.sig, 4) == 0)) {  /* bad offset */\n                    if (error != PK_BADERR)\n                      Info(slide, 0x401, ((char *)slide,\n                        LoadFarString(OffsetMsg), *pfilnum, \"EOF\",\n                        (long)request));\n                    error_in_archive = PK_BADERR;\n                    continue;   /* but can still try next one */\n                }\n                if (memcmp(G.sig, local_hdr_sig, 4)) {\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(OffsetMsg), *pfilnum,\n                      LoadFarStringSmall(LocalHdrSig), (long)request));\n                    error_in_archive = PK_BADERR;\n                    continue;\n                }\n            } else\n                continue;  /* this one hosed; try next */\n        }\n        if ((error = process_local_file_hdr(__G)) != PK_COOL) {\n            Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),\n              *pfilnum));\n            error_in_archive = error;   /* only PK_EOF defined */\n            continue;   /* can still try next one */\n        }\n#if (!defined(SFX) && defined(UNICODE_SUPPORT))\n        if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11))\n            != (G.pInfo->GPFIsUTF8 != 0)) {\n            if (QCOND2) {\n#  ifdef SMALL_MEM\n                char *temp_cfilnam = slide + (7 * (WSIZE>>3));\n\n                zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);\n#    define  cFile_PrintBuf  temp_cfilnam\n#  else\n#    define  cFile_PrintBuf  G.pInfo->cfilname\n#  endif\n                Info(slide, 0x421, ((char *)slide,\n                  LoadFarStringSmall2(GP11FlagsDiffer),\n                  *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8));\n#  undef    cFile_PrintBuf\n            }\n            if (error_in_archive < PK_WARN)\n                error_in_archive = PK_WARN;\n        }\n#endif /* !SFX && UNICODE_SUPPORT */\n        if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=\n             PK_COOL)\n        {\n            if (error > error_in_archive)\n                error_in_archive = error;\n            if (error > PK_WARN) {\n                Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),\n                  FnFilter1(G.filename), \"local\"));\n                continue;   /* go on to next one */\n            }\n        }\n        if (G.extra_field != (uch *)NULL) {\n            free(G.extra_field);\n            G.extra_field = (uch *)NULL;\n        }\n        if ((error =\n             do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)\n        {\n            if (error > error_in_archive)\n                error_in_archive = error;\n            if (error > PK_WARN) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(ExtFieldMsg),\n                  FnFilter1(G.filename), \"local\"));\n                continue;   /* go on */\n            }\n        }\n#ifndef SFX\n        /* Filename consistency checks must come after reading in the local\n         * extra field, so that a UTF-8 entry name e.f. block has already\n         * been processed.\n         */\n        if (G.pInfo->cfilname != (char Far *)NULL) {\n            if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {\n#  ifdef SMALL_MEM\n                char *temp_cfilnam = slide + (7 * (WSIZE>>3));\n\n                zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);\n#    define  cFile_PrintBuf  temp_cfilnam\n#  else\n#    define  cFile_PrintBuf  G.pInfo->cfilname\n#  endif\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarStringSmall2(LvsCFNamMsg),\n                  FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));\n#  undef    cFile_PrintBuf\n                zfstrcpy(G.filename, G.pInfo->cfilname);\n                if (error_in_archive < PK_WARN)\n                    error_in_archive = PK_WARN;\n            }\n            zffree(G.pInfo->cfilname);\n            G.pInfo->cfilname = (char Far *)NULL;\n        }\n#endif /* !SFX */\n        /* Size consistency checks must come after reading in the local extra\n         * field, so that any Zip64 extension local e.f. block has already\n         * been processed.\n         */\n        if (G.lrec.compression_method == STORED) {\n            zusz_t csiz_decrypted = G.lrec.csize;\n\n            if (G.pInfo->encrypted)\n                csiz_decrypted -= 12;\n            if (G.lrec.ucsize != csiz_decrypted) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarStringSmall2(WrnStorUCSizCSizDiff),\n                  FnFilter1(G.filename),\n                  FmZofft(G.lrec.ucsize, NULL, \"u\"),\n                  FmZofft(csiz_decrypted, NULL, \"u\")));\n                G.lrec.ucsize = csiz_decrypted;\n                if (error_in_archive < PK_WARN)\n                    error_in_archive = PK_WARN;\n            }\n        }\n\n#if CRYPT\n        if (G.pInfo->encrypted &&\n            (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {\n            if (error == PK_WARN) {\n                if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(SkipIncorrectPasswd),\n                      FnFilter1(G.filename)));\n                ++(*pnum_bad_pwd);\n            } else {  /* (error > PK_WARN) */\n                if (error > error_in_archive)\n                    error_in_archive = error;\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(SkipCannotGetPasswd),\n                  FnFilter1(G.filename)));\n            }\n            continue;   /* go on to next file */\n        }\n#endif /* CRYPT */\n\n        /*\n         * just about to extract file:  if extracting to disk, check if\n         * already exists, and if so, take appropriate action according to\n         * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper\n         * loop because we don't store the possibly renamed filename[] in\n         * info[])\n         */\n#ifdef DLL\n        if (!uO.tflag && !uO.cflag && !G.redirect_data)\n#else\n        if (!uO.tflag && !uO.cflag)\n#endif\n        {\n            renamed = FALSE;   /* user hasn't renamed output file yet */\n\nstartover:\n            query = FALSE;\n            skip_entry = SKIP_NO;\n            /* for files from DOS FAT, check for use of backslash instead\n             *  of slash as directory separator (bug in some zipper(s); so\n             *  far, not a problem in HPFS, NTFS or VFAT systems)\n             */\n#ifndef SFX\n            if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {\n                char *p=G.filename;\n\n                if (*p) do {\n                    if (*p == '\\\\') {\n                        if (!G.reported_backslash) {\n                            Info(slide, 0x21, ((char *)slide,\n                              LoadFarString(BackslashPathSep), G.zipfn));\n                            G.reported_backslash = TRUE;\n                            if (!error_in_archive)\n                                error_in_archive = PK_WARN;\n                        }\n                        *p = '/';\n                    }\n                } while (*PREINCSTR(p));\n            }\n#endif /* !SFX */\n\n            if (!renamed) {\n               /* remove absolute path specs */\n               if (G.filename[0] == '/') {\n                   Info(slide, 0x401, ((char *)slide,\n                        LoadFarString(AbsolutePathWarning),\n                        FnFilter1(G.filename)));\n                   if (!error_in_archive)\n                       error_in_archive = PK_WARN;\n                   do {\n                       char *p = G.filename + 1;\n                       do {\n                           *(p-1) = *p;\n                       } while (*p++ != '\\0');\n                   } while (G.filename[0] == '/');\n               }\n            }\n\n            /* mapname can create dirs if not freshening or if renamed */\n            error = mapname(__G__ renamed);\n            if ((errcode = error & ~MPN_MASK) != PK_OK &&\n                error_in_archive < errcode)\n                error_in_archive = errcode;\n            if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {\n                if (errcode == MPN_CREATED_DIR) {\n#ifdef SET_DIR_ATTRIB\n                    direntry *d_entry;\n\n                    error = defer_dir_attribs(__G__ &d_entry);\n                    if (d_entry == (direntry *)NULL) {\n                        /* There may be no dir_attribs info available, or\n                         * we have encountered a mem allocation error.\n                         * In case of an error, report it and set program\n                         * error state to warning level.\n                         */\n                        if (error) {\n                            Info(slide, 0x401, ((char *)slide,\n                                 LoadFarString(DirlistEntryNoMem)));\n                            if (!error_in_archive)\n                                error_in_archive = PK_WARN;\n                        }\n                    } else {\n                        d_entry->next = (*pdirlist);\n                        (*pdirlist) = d_entry;\n                        ++(*pnum_dirs);\n                    }\n#endif /* SET_DIR_ATTRIB */\n                } else if (errcode == MPN_VOL_LABEL) {\n#ifdef DOS_OS2_W32\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(SkipVolumeLabel),\n                      FnFilter1(G.filename),\n                      uO.volflag? \"hard disk \" : \"\"));\n#else\n                    Info(slide, 1, ((char *)slide,\n                      LoadFarString(SkipVolumeLabel),\n                      FnFilter1(G.filename), \"\"));\n#endif\n                } else if (errcode > MPN_INF_SKIP &&\n                           error_in_archive < PK_ERR)\n                    error_in_archive = PK_ERR;\n                Trace((stderr, \"mapname(%s) returns error code = %d\\n\",\n                  FnFilter1(G.filename), error));\n                continue;   /* go on to next file */\n            }\n\n#ifdef QDOS\n            QFilename(__G__ G.filename);\n#endif\n            switch (check_for_newer(__G__ G.filename)) {\n                case DOES_NOT_EXIST:\n#ifdef NOVELL_BUG_FAILSAFE\n                    G.dne = TRUE;   /* stat() says file DOES NOT EXIST */\n#endif\n                    /* freshen (no new files): skip unless just renamed */\n                    if (uO.fflag && !renamed)\n                        skip_entry = SKIP_Y_NONEXIST;\n                    break;\n                case EXISTS_AND_OLDER:\n#ifdef UNIXBACKUP\n                    if (!uO.B_flag)\n#endif\n                    {\n                        if (IS_OVERWRT_NONE)\n                            /* never overwrite:  skip file */\n                            skip_entry = SKIP_Y_EXISTING;\n                        else if (!IS_OVERWRT_ALL)\n                            query = TRUE;\n                    }\n                    break;\n                case EXISTS_AND_NEWER:             /* (or equal) */\n#ifdef UNIXBACKUP\n                    if ((!uO.B_flag && IS_OVERWRT_NONE) ||\n#else\n                    if (IS_OVERWRT_NONE ||\n#endif\n                        (uO.uflag && !renamed)) {\n                        /* skip if update/freshen & orig name */\n                        skip_entry = SKIP_Y_EXISTING;\n                    } else {\n#ifdef UNIXBACKUP\n                        if (!IS_OVERWRT_ALL && !uO.B_flag)\n#else\n                        if (!IS_OVERWRT_ALL)\n#endif\n                            query = TRUE;\n                    }\n                    break;\n            }\n#ifdef VMS\n            /* 2008-07-24 SMS.\n             * On VMS, if the file name includes a version number,\n             * and \"-V\" (\"retain VMS version numbers\", V_flag) is in\n             * effect, then the VMS-specific code will handle any\n             * conflicts with an existing file, making this query\n             * redundant.  (Implicit \"y\" response here.)\n             */\n            if (query && uO.V_flag) {\n                /* Not discarding file versions.  Look for one. */\n                int cndx = strlen(G.filename) - 1;\n\n                while ((cndx > 0) && (isdigit(G.filename[cndx])))\n                    cndx--;\n                if (G.filename[cndx] == ';')\n                    /* File version found; skip the generic query,\n                     * proceeding with its default response \"y\".\n                     */\n                    query = FALSE;\n            }\n#endif /* VMS */\n            if (query) {\n#ifdef WINDLL\n                switch (G.lpUserFunctions->replace != NULL ?\n                        (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) :\n                        IDM_REPLACE_NONE) {\n                    case IDM_REPLACE_RENAME:\n                        _ISO_INTERN(G.filename);\n                        renamed = TRUE;\n                        goto startover;\n                    case IDM_REPLACE_ALL:\n                        G.overwrite_mode = OVERWRT_ALWAYS;\n                        /* FALL THROUGH, extract */\n                    case IDM_REPLACE_YES:\n                        break;\n                    case IDM_REPLACE_NONE:\n                        G.overwrite_mode = OVERWRT_NEVER;\n                        /* FALL THROUGH, skip */\n                    case IDM_REPLACE_NO:\n                        skip_entry = SKIP_Y_EXISTING;\n                        break;\n                }\n#else /* !WINDLL */\n                extent fnlen;\nreprompt:\n                Info(slide, 0x81, ((char *)slide,\n                  LoadFarString(ReplaceQuery),\n                  FnFilter1(G.filename)));\n                if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin)\n                    == (char *)NULL) {\n                    Info(slide, 1, ((char *)slide,\n                      LoadFarString(AssumeNone)));\n                    *G.answerbuf = 'N';\n                    if (!error_in_archive)\n                        error_in_archive = 1;  /* not extracted:  warning */\n                }\n                switch (*G.answerbuf) {\n                    case 'r':\n                    case 'R':\n                        do {\n                            Info(slide, 0x81, ((char *)slide,\n                              LoadFarString(NewNameQuery)));\n                            fgets(G.filename, FILNAMSIZ, stdin);\n                            /* usually get \\n here:  better check for it */\n                            fnlen = strlen(G.filename);\n                            if (lastchar(G.filename, fnlen) == '\\n')\n                                G.filename[--fnlen] = '\\0';\n                        } while (fnlen == 0);\n#ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */\n                        _OEM_INTERN(G.filename);\n#endif\n                        renamed = TRUE;\n                        goto startover;   /* sorry for a goto */\n                    case 'A':   /* dangerous option:  force caps */\n                        G.overwrite_mode = OVERWRT_ALWAYS;\n                        /* FALL THROUGH, extract */\n                    case 'y':\n                    case 'Y':\n                        break;\n                    case 'N':\n                        G.overwrite_mode = OVERWRT_NEVER;\n                        /* FALL THROUGH, skip */\n                    case 'n':\n                        /* skip file */\n                        skip_entry = SKIP_Y_EXISTING;\n                        break;\n                    case '\\n':\n                    case '\\r':\n                        /* Improve echo of '\\n' and/or '\\r'\n                           (sizeof(G.answerbuf) == 10 (see globals.h), so\n                           there is enough space for the provided text...) */\n                        strcpy(G.answerbuf, \"{ENTER}\");\n                        /* fall through ... */\n                    default:\n                        /* usually get \\n here:  remove it for nice display\n                           (fnlen can be re-used here, we are outside the\n                           \"enter new filename\" loop) */\n                        fnlen = strlen(G.answerbuf);\n                        if (lastchar(G.answerbuf, fnlen) == '\\n')\n                            G.answerbuf[--fnlen] = '\\0';\n                        Info(slide, 1, ((char *)slide,\n                          LoadFarString(InvalidResponse), G.answerbuf));\n                        goto reprompt;   /* yet another goto? */\n                } /* end switch (*answerbuf) */\n#endif /* ?WINDLL */\n            } /* end if (query) */\n            if (skip_entry != SKIP_NO) {\n#ifdef WINDLL\n                if (skip_entry == SKIP_Y_EXISTING) {\n                    /* report skipping of an existing entry */\n                    Info(slide, 0, ((char *)slide,\n                      ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?\n                       \"Target file exists.  Skipping %s\\n\" :\n                       \"Target file newer.  Skipping %s\\n\"),\n                      FnFilter1(G.filename)));\n                }\n#endif /* WINDLL */\n                continue;\n            }\n        } /* end if (extracting to disk) */\n\n#ifdef DLL\n        if ((G.statreportcb != NULL) &&\n            (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,\n                              G.filename, NULL)) {\n            return IZ_CTRLC;        /* cancel operation by user request */\n        }\n#endif\n#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */\n        UserStop();\n#endif\n#ifdef AMIGA\n        G.filenote_slot = i;\n#endif\n        G.disk_full = 0;\n        if ((error = extract_or_test_member(__G)) != PK_COOL) {\n            if (error > error_in_archive)\n                error_in_archive = error;       /* ...and keep going */\n#ifdef DLL\n            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {\n#else\n            if (G.disk_full > 1) {\n#endif\n                return error_in_archive;        /* (unless disk full) */\n            }\n        }\n#ifdef DLL\n        if ((G.statreportcb != NULL) &&\n            (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,\n                              G.filename, (zvoid *)&G.lrec.ucsize)) {\n            return IZ_CTRLC;        /* cancel operation by user request */\n        }\n#endif\n#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */\n        UserStop();\n#endif\n    } /* end for-loop (i:  files in current block) */\n\n    return error_in_archive;\n\n} /* end function extract_or_test_entrylist() */\n\n\n\n\n\n/* wsize is used in extract_or_test_member() and UZbunzip2() */\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n#  define wsize G._wsize    /* wsize is a variable */\n#else\n#  define wsize WSIZE       /* wsize is a constant */\n#endif\n\n/***************************************/\n/*  Function extract_or_test_member()  */\n/***************************************/\n\nstatic int extract_or_test_member(__G)    /* return PK-type error code */\n     __GDEF\n{\n    char *nul=\"[empty] \", *txt=\"[text]  \", *bin=\"[binary]\";\n#ifdef CMS_MVS\n    char *ebc=\"[ebcdic]\";\n#endif\n    register int b;\n    int r, error=PK_COOL;\n\n\n/*---------------------------------------------------------------------------\n    Initialize variables, buffers, etc.\n  ---------------------------------------------------------------------------*/\n\n    G.bits_left = 0;\n    G.bitbuf = 0L;       /* unreduce and unshrink only */\n    G.zipeof = 0;\n    G.newfile = TRUE;\n    G.crc32val = CRCVAL_INITIAL;\n\n#ifdef SYMLINKS\n    /* If file is a (POSIX-compatible) symbolic link and we are extracting\n     * to disk, prepare to restore the link. */\n    G.symlnk = (G.pInfo->symlink &&\n                !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0));\n#endif /* SYMLINKS */\n\n    if (uO.tflag) {\n        if (!uO.qflag)\n            Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), \"test\",\n              FnFilter1(G.filename), \"\", \"\"));\n    } else {\n#ifdef DLL\n        if (uO.cflag && !G.redirect_data)\n#else\n        if (uO.cflag)\n#endif\n        {\n#if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))\n            G.outfile = freopen(\"\", \"wb\", stdout);   /* VAC++ ignores setmode */\n#else\n            G.outfile = stdout;\n#endif\n#ifdef DOS_FLX_NLM_OS2_W32\n#if (defined(__HIGHC__) && !defined(FLEXOS))\n            setmode(G.outfile, _BINARY);\n#else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */\n            setmode(fileno(G.outfile), O_BINARY);\n#endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */\n#           define NEWLINE \"\\r\\n\"\n#else /* !DOS_FLX_NLM_OS2_W32 */\n#           define NEWLINE \"\\n\"\n#endif /* ?DOS_FLX_NLM_OS2_W32 */\n#ifdef VMS\n            /* VMS:  required even for stdout! */\n            if ((r = open_outfile(__G)) != 0)\n                switch (r) {\n                  case OPENOUT_SKIPOK:\n                    return PK_OK;\n                  case OPENOUT_SKIPWARN:\n                    return PK_WARN;\n                  default:\n                    return PK_DISK;\n                }\n        } else if ((r = open_outfile(__G)) != 0)\n            switch (r) {\n              case OPENOUT_SKIPOK:\n                return PK_OK;\n              case OPENOUT_SKIPWARN:\n                return PK_WARN;\n              default:\n                return PK_DISK;\n            }\n#else /* !VMS */\n        } else if (open_outfile(__G))\n            return PK_DISK;\n#endif /* ?VMS */\n    }\n\n/*---------------------------------------------------------------------------\n    Unpack the file.\n  ---------------------------------------------------------------------------*/\n\n    defer_leftover_input(__G);    /* so NEXTBYTE bounds check will work */\n    switch (G.lrec.compression_method) {\n        case STORED:\n            if (!uO.tflag && QCOND2) {\n#ifdef SYMLINKS\n                if (G.symlnk)   /* can also be deflated, but rarer... */\n                    Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                      \"link\", FnFilter1(G.filename), \"\", \"\"));\n                else\n#endif /* SYMLINKS */\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  \"extract\", FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :\n                  bin)), uO.cflag? NEWLINE : \"\"));\n            }\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n            if (G.redirect_slide) {\n                wsize = G.redirect_size; redirSlide = G.redirect_buffer;\n            } else {\n                wsize = WSIZE; redirSlide = slide;\n            }\n#endif\n            G.outptr = redirSlide;\n            G.outcnt = 0L;\n            while ((b = NEXTBYTE) != EOF) {\n                *G.outptr++ = (uch)b;\n                if (++G.outcnt == wsize) {\n                    error = flush(__G__ redirSlide, G.outcnt, 0);\n                    G.outptr = redirSlide;\n                    G.outcnt = 0L;\n                    if (error != PK_COOL || G.disk_full) break;\n                }\n            }\n            if (G.outcnt) {        /* flush final (partial) buffer */\n                r = flush(__G__ redirSlide, G.outcnt, 0);\n                if (error < r) error = r;\n            }\n            break;\n\n#ifndef SFX\n#ifndef LZW_CLEAN\n        case SHRUNK:\n            if (!uO.tflag && QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  LoadFarStringSmall(Unshrink), FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : \"\"));\n            }\n            if ((r = unshrink(__G)) != PK_COOL) {\n                if (r < PK_DISK) {\n                    if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Unshrink),\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Unshrink)));\n                }\n                error = r;\n            }\n            break;\n#endif /* !LZW_CLEAN */\n\n#ifndef COPYRIGHT_CLEAN\n        case REDUCED1:\n        case REDUCED2:\n        case REDUCED3:\n        case REDUCED4:\n            if (!uO.tflag && QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  \"unreduc\", FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : \"\"));\n            }\n            if ((r = unreduce(__G)) != PK_COOL) {\n                /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */\n                error = r;\n            }\n            break;\n#endif /* !COPYRIGHT_CLEAN */\n\n        case IMPLODED:\n            if (!uO.tflag && QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  \"explod\", FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : \"\"));\n            }\n            if ((r = explode(__G)) != 0) {\n                if (r == 5) { /* treat 5 specially */\n                    int warning = ((zusz_t)G.used_csize <= G.lrec.csize);\n\n                    if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(LengthMsg),\n                          \"\", warning ? \"warning\" : \"error\",\n                          FmZofft(G.used_csize, NULL, NULL),\n                          FmZofft(G.lrec.ucsize, NULL, \"u\"),\n                          warning ? \"  \" : \"\",\n                          FmZofft(G.lrec.csize, NULL, \"u\"),\n                          \" [\", FnFilter1(G.filename), \"]\"));\n                    else\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(LengthMsg),\n                          \"\\n\", warning ? \"warning\" : \"error\",\n                          FmZofft(G.used_csize, NULL, NULL),\n                          FmZofft(G.lrec.ucsize, NULL, \"u\"),\n                          warning ? \"  \" : \"\",\n                          FmZofft(G.lrec.csize, NULL, \"u\"),\n                          \"\", \"\", \".\"));\n                    error = warning ? PK_WARN : PK_ERR;\n                } else if (r < PK_DISK) {\n                    if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Explode),\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipNoFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Explode)));\n                    error = ((r == 3) ? PK_MEM3 : PK_ERR);\n                } else {\n                    error = r;\n                }\n            }\n            break;\n#endif /* !SFX */\n\n        case DEFLATED:\n#ifdef USE_DEFLATE64\n        case ENHDEFLATED:\n#endif\n            if (!uO.tflag && QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  \"inflat\", FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : \"\"));\n            }\n#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */\n#  define UZinflate inflate\n#endif\n            if ((r = UZinflate(__G__\n                               (G.lrec.compression_method == ENHDEFLATED)))\n                != 0) {\n                if (r < PK_DISK) {\n                    if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Inflate),\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipNoFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(Inflate)));\n                    error = ((r == 3) ? PK_MEM3 : PK_ERR);\n                } else {\n                    error = r;\n                }\n            }\n            break;\n\n#ifdef USE_BZIP2\n        case BZIPPED:\n            if (!uO.tflag && QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),\n                  \"bunzipp\", FnFilter1(G.filename),\n                  (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?\n                  \"\" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : \"\"));\n            }\n            if ((r = UZbunzip2(__G)) != 0) {\n                if (r < PK_DISK) {\n                    if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(BUnzip),\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarStringSmall(ErrUnzipNoFile), r == 3?\n                          LoadFarString(NotEnoughMem) :\n                          LoadFarString(InvalidComprData),\n                          LoadFarStringSmall2(BUnzip)));\n                    error = ((r == 3) ? PK_MEM3 : PK_ERR);\n                } else {\n                    error = r;\n                }\n            }\n            break;\n#endif /* USE_BZIP2 */\n\n        default:   /* should never get to this point */\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));\n            /* close and delete file before return? */\n            undefer_input(__G);\n            return PK_WARN;\n\n    } /* end switch (compression method) */\n\n/*---------------------------------------------------------------------------\n    Close the file and set its date and time (not necessarily in that order),\n    and make sure the CRC checked out OK.  Logical-AND the CRC for 64-bit\n    machines (redundant on 32-bit machines).\n  ---------------------------------------------------------------------------*/\n\n#ifdef VMS                  /* VMS:  required even for stdout! (final flush) */\n    if (!uO.tflag)           /* don't close NULL file */\n        close_outfile(__G);\n#else\n#ifdef DLL\n    if (!uO.tflag && (!uO.cflag || G.redirect_data)) {\n        if (G.redirect_data)\n            FINISH_REDIRECT();\n        else\n            close_outfile(__G);\n    }\n#else\n    if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */\n        close_outfile(__G);\n#endif\n#endif /* VMS */\n\n            /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */\n\n\n    if (G.disk_full) {            /* set by flush() */\n        if (G.disk_full > 1) {\n#if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))\n            /* delete the incomplete file if we can */\n            if (unlink(G.filename) != 0)\n                Trace((stderr, \"extract.c:  could not delete %s\\n\",\n                  FnFilter1(G.filename)));\n#else\n            /* warn user about the incomplete file */\n            Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),\n              FnFilter1(G.filename)));\n#endif\n            error = PK_DISK;\n        } else {\n            error = PK_WARN;\n        }\n    }\n\n    if (error > PK_WARN) {/* don't print redundant CRC error if error already */\n        undefer_input(__G);\n        return error;\n    }\n    if (G.crc32val != G.lrec.crc32) {\n        /* if quiet enough, we haven't output the filename yet:  do it */\n        if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))\n            Info(slide, 0x401, ((char *)slide, \"%-22s \",\n              FnFilter1(G.filename)));\n        Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,\n          G.lrec.crc32));\n#if CRYPT\n        if (G.pInfo->encrypted)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));\n#endif\n        error = PK_ERR;\n    } else if (uO.tflag) {\n#ifndef SFX\n        if (G.extra_field) {\n            if ((r = TestExtraField(__G__ G.extra_field,\n                                    G.lrec.extra_field_length)) > error)\n                error = r;\n        } else\n#endif /* !SFX */\n        if (!uO.qflag)\n            Info(slide, 0, ((char *)slide, \" OK\\n\"));\n    } else {\n        if (QCOND2 && !error)   /* GRR:  is stdout reset to text mode yet? */\n            Info(slide, 0, ((char *)slide, \"\\n\"));\n    }\n\n    undefer_input(__G);\n    return error;\n\n} /* end function extract_or_test_member() */\n\n\n\n\n\n#ifndef SFX\n\n/*******************************/\n/*  Function TestExtraField()  */\n/*******************************/\n\nstatic int TestExtraField(__G__ ef, ef_len)\n    __GDEF\n    uch *ef;\n    unsigned ef_len;\n{\n    ush ebID;\n    unsigned ebLen;\n    unsigned eb_cmpr_offs = 0;\n    int r;\n\n    /* we know the regular compressed file data tested out OK, or else we\n     * wouldn't be here ==> print filename if any extra-field errors found\n     */\n    while (ef_len >= EB_HEADSIZE) {\n        ebID = makeword(ef);\n        ebLen = (unsigned)makeword(ef+EB_LEN);\n\n        if (ebLen > (ef_len - EB_HEADSIZE)) {\n           /* Discovered some extra field inconsistency! */\n            if (uO.qflag)\n                Info(slide, 1, ((char *)slide, \"%-22s \",\n                  FnFilter1(G.filename)));\n            Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),\n              ebLen, (ef_len - EB_HEADSIZE)));\n            return PK_ERR;\n        }\n\n        switch (ebID) {\n            case EF_OS2:\n            case EF_ACL:\n            case EF_MAC3:\n            case EF_BEOS:\n            case EF_ATHEOS:\n                switch (ebID) {\n                  case EF_OS2:\n                  case EF_ACL:\n                    eb_cmpr_offs = EB_OS2_HLEN;\n                    break;\n                  case EF_MAC3:\n                    if (ebLen >= EB_MAC3_HLEN &&\n                        (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))\n                         & EB_M3_FL_UNCMPR) &&\n                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))\n                        eb_cmpr_offs = 0;\n                    else\n                        eb_cmpr_offs = EB_MAC3_HLEN;\n                    break;\n                  case EF_BEOS:\n                  case EF_ATHEOS:\n                    if (ebLen >= EB_BEOS_HLEN &&\n                        (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&\n                        (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))\n                        eb_cmpr_offs = 0;\n                    else\n                        eb_cmpr_offs = EB_BEOS_HLEN;\n                    break;\n                }\n                if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))\n                    != PK_OK) {\n                    if (uO.qflag)\n                        Info(slide, 1, ((char *)slide, \"%-22s \",\n                          FnFilter1(G.filename)));\n                    switch (r) {\n                        case IZ_EF_TRUNC:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(TruncEAs),\n                              ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), \"\\n\"));\n                            break;\n                        case PK_ERR:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(InvalidComprDataEAs)));\n                            break;\n                        case PK_MEM3:\n                        case PK_MEM4:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(NotEnoughMemEAs)));\n                            break;\n                        default:\n                            if ((r & 0xff) != PK_ERR)\n                                Info(slide, 1, ((char *)slide,\n                                  LoadFarString(UnknErrorEAs)));\n                            else {\n                                ush m = (ush)(r >> 8);\n                                if (m == DEFLATED)            /* GRR KLUDGE! */\n                                    Info(slide, 1, ((char *)slide,\n                                      LoadFarString(BadCRC_EAs)));\n                                else\n                                    Info(slide, 1, ((char *)slide,\n                                      LoadFarString(UnknComprMethodEAs), m));\n                            }\n                            break;\n                    }\n                    return r;\n                }\n                break;\n\n            case EF_NTSD:\n                Trace((stderr, \"ebID: %i / ebLen: %u\\n\", ebID, ebLen));\n                r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :\n                    ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?\n                     (PK_WARN | 0x4000) :\n                     test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));\n                if (r != PK_OK) {\n                    if (uO.qflag)\n                        Info(slide, 1, ((char *)slide, \"%-22s \",\n                          FnFilter1(G.filename)));\n                    switch (r) {\n                        case IZ_EF_TRUNC:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(TruncNTSD),\n                              ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), \"\\n\"));\n                            break;\n#if (defined(WIN32) && defined(NTSD_EAS))\n                        case PK_WARN:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(InvalidSecurityEAs)));\n                            break;\n#endif\n                        case PK_ERR:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(InvalidComprDataEAs)));\n                            break;\n                        case PK_MEM3:\n                        case PK_MEM4:\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(NotEnoughMemEAs)));\n                            break;\n                        case (PK_WARN | 0x4000):\n                            Info(slide, 1, ((char *)slide,\n                              LoadFarString(UnsuppNTSDVersEAs),\n                              (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));\n                            r = PK_WARN;\n                            break;\n                        default:\n                            if ((r & 0xff) != PK_ERR)\n                                Info(slide, 1, ((char *)slide,\n                                  LoadFarString(UnknErrorEAs)));\n                            else {\n                                ush m = (ush)(r >> 8);\n                                if (m == DEFLATED)            /* GRR KLUDGE! */\n                                    Info(slide, 1, ((char *)slide,\n                                      LoadFarString(BadCRC_EAs)));\n                                else\n                                    Info(slide, 1, ((char *)slide,\n                                      LoadFarString(UnknComprMethodEAs), m));\n                            }\n                            break;\n                    }\n                    return r;\n                }\n                break;\n            case EF_PKVMS:\n                if (makelong(ef+EB_HEADSIZE) !=\n                    crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),\n                          (extent)(ebLen-4)))\n                    Info(slide, 1, ((char *)slide,\n                      LoadFarString(BadCRC_EAs)));\n                break;\n            case EF_PKW32:\n            case EF_PKUNIX:\n            case EF_ASIUNIX:\n            case EF_IZVMS:\n            case EF_IZUNIX:\n            case EF_VMCMS:\n            case EF_MVS:\n            case EF_SPARK:\n            case EF_TANDEM:\n            case EF_THEOS:\n            case EF_AV:\n            default:\n                break;\n        }\n        ef_len -= (ebLen + EB_HEADSIZE);\n        ef += (ebLen + EB_HEADSIZE);\n    }\n\n    if (!uO.qflag)\n        Info(slide, 0, ((char *)slide, \" OK\\n\"));\n\n    return PK_COOL;\n\n} /* end function TestExtraField() */\n\n\n\n\n\n/******************************/\n/*  Function test_compr_eb()  */\n/******************************/\n\n#ifdef PROTO\nstatic int test_compr_eb(\n    __GPRO__\n    uch *eb,\n    unsigned eb_size,\n    unsigned compr_offset,\n    int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,\n                          uch *eb_ucptr, ulg eb_ucsize))\n#else /* !PROTO */\nstatic int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)\n    __GDEF\n    uch *eb;\n    unsigned eb_size;\n    unsigned compr_offset;\n    int (*test_uc_ebdata)();\n#endif /* ?PROTO */\n{\n    ulg eb_ucsize;\n    uch *eb_ucptr;\n    int r;\n\n    if (compr_offset < 4)                /* field is not compressed: */\n        return PK_OK;                    /* do nothing and signal OK */\n\n    if ((eb_size < (EB_UCSIZE_P + 4)) ||\n        ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&\n         eb_size <= (compr_offset + EB_CMPRHEADLEN)))\n        return IZ_EF_TRUNC;               /* no compressed data! */\n\n    if (\n#ifdef INT_16BIT\n        (((ulg)(extent)eb_ucsize) != eb_ucsize) ||\n#endif\n        (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)\n        return PK_MEM4;\n\n    r = memextract(__G__ eb_ucptr, eb_ucsize,\n                   eb + (EB_HEADSIZE + compr_offset),\n                   (ulg)(eb_size - compr_offset));\n\n    if (r == PK_OK && test_uc_ebdata != NULL)\n        r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);\n\n    free(eb_ucptr);\n    return r;\n\n} /* end function test_compr_eb() */\n\n#endif /* !SFX */\n\n\n\n\n\n/***************************/\n/*  Function memextract()  */\n/***************************/\n\nint memextract(__G__ tgt, tgtsize, src, srcsize)  /* extract compressed */\n    __GDEF                                        /*  extra field block; */\n    uch *tgt;                                     /*  return PK-type error */\n    ulg tgtsize;                                  /*  level */\n    ZCONST uch *src;\n    ulg srcsize;\n{\n    zoff_t old_csize=G.csize;\n    uch   *old_inptr=G.inptr;\n    int    old_incnt=G.incnt;\n    int    r, error=PK_OK;\n    ush    method;\n    ulg    extra_field_crc;\n\n\n    method = makeword(src);\n    extra_field_crc = makelong(src+2);\n\n    /* compressed extra field exists completely in memory at this location: */\n    G.inptr = (uch *)src + (2 + 4);     /* method and extra_field_crc */\n    G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));\n    G.mem_mode = TRUE;\n    G.outbufptr = tgt;\n    G.outsize = tgtsize;\n\n    switch (method) {\n        case STORED:\n            memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);\n            G.outcnt = (ulg)G.csize;    /* for CRC calculation */\n            break;\n        case DEFLATED:\n#ifdef USE_DEFLATE64\n        case ENHDEFLATED:\n#endif\n            G.outcnt = 0L;\n            if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {\n                if (!uO.tflag)\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarStringSmall(ErrUnzipNoFile), r == 3?\n                      LoadFarString(NotEnoughMem) :\n                      LoadFarString(InvalidComprData),\n                      LoadFarStringSmall2(Inflate)));\n                error = (r == 3)? PK_MEM3 : PK_ERR;\n            }\n            if (G.outcnt == 0L)   /* inflate's final FLUSH sets outcnt */\n                break;\n            break;\n        default:\n            if (uO.tflag)\n                error = PK_ERR | ((int)method << 8);\n            else {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(UnsupportedExtraField), method));\n                error = PK_ERR;  /* GRR:  should be passed on up via SetEAs() */\n            }\n            break;\n    }\n\n    G.inptr = old_inptr;\n    G.incnt = old_incnt;\n    G.csize = old_csize;\n    G.mem_mode = FALSE;\n\n    if (!error) {\n        register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);\n\n        if (crcval != extra_field_crc) {\n            if (uO.tflag)\n                error = PK_ERR | (DEFLATED << 8);  /* kludge for now */\n            else {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,\n                  extra_field_crc));\n                error = PK_ERR;\n            }\n        }\n    }\n    return error;\n\n} /* end function memextract() */\n\n\n\n\n\n/*************************/\n/*  Function memflush()  */\n/*************************/\n\nint memflush(__G__ rawbuf, size)\n    __GDEF\n    ZCONST uch *rawbuf;\n    ulg size;\n{\n    if (size > G.outsize)\n        /* Here, PK_DISK is a bit off-topic, but in the sense of marking\n           \"overflow of output space\", its use may be tolerated. */\n        return PK_DISK;   /* more data than output buffer can hold */\n\n\n\n    memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);\n    G.outbufptr += (unsigned int)size;\n    G.outsize -= size;\n    G.outcnt += size;\n\n    return 0;\n\n} /* end function memflush() */\n\n\n\n\n\n#if (defined(VMS) || defined(VMS_TEXT_CONV))\n\n/************************************/\n/*  Function extract_izvms_block()  */\n/************************************/\n\n/*\n * Extracts block from p. If resulting length is less than needed, fill\n * extra space with corresponding bytes from 'init'.\n * Currently understands 3 formats of block compression:\n * - Simple storing\n * - Compression of zero bytes to zero bits\n * - Deflation (see memextract())\n * The IZVMS block data is returned in malloc'd space.\n */\nuch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen)\n    __GDEF\n    ZCONST uch *ebdata;\n    unsigned size;\n    unsigned *retlen;\n    ZCONST uch *init;\n    unsigned needlen;\n{\n    uch *ucdata;       /* Pointer to block allocated */\n    int cmptype;\n    unsigned usiz, csiz;\n\n    cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK);\n    csiz = size - EB_IZVMS_HLEN;\n    usiz = (cmptype == EB_IZVMS_BCSTOR ?\n            csiz : makeword(ebdata+EB_IZVMS_UCSIZ));\n\n    if (retlen)\n        *retlen = usiz;\n\n    if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL)\n        return NULL;\n\n    if (init && (usiz < needlen))\n        memcpy((char *)ucdata, (ZCONST char *)init, needlen);\n\n    switch (cmptype)\n    {\n        case EB_IZVMS_BCSTOR: /* The simplest case */\n            memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz);\n            break;\n        case EB_IZVMS_BC00:\n            decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN);\n            break;\n        case EB_IZVMS_BCDEFL:\n            memextract(__G__ ucdata, (ulg)usiz,\n                       ebdata+EB_IZVMS_HLEN, (ulg)csiz);\n            break;\n        default:\n            free(ucdata);\n            ucdata = NULL;\n    }\n    return ucdata;\n\n} /* end of extract_izvms_block */\n\n\n\n\n\n/********************************/\n/*  Function decompress_bits()  */\n/********************************/\n/*\n *  Simple uncompression routine. The compression uses bit stream.\n *  Compression scheme:\n *\n *  if (byte!=0)\n *      putbit(1),putbyte(byte)\n *  else\n *      putbit(0)\n */\nstatic void decompress_bits(outptr, needlen, bitptr)\n    uch *outptr;        /* Pointer into output block */\n    unsigned needlen;   /* Size of uncompressed block */\n    ZCONST uch *bitptr; /* Pointer into compressed data */\n{\n    ulg bitbuf = 0;\n    int bitcnt = 0;\n\n#define _FILL   {       bitbuf |= (*bitptr++) << bitcnt;\\\n                        bitcnt += 8;                    \\\n                }\n\n    while (needlen--)\n    {\n        if (bitcnt <= 0)\n            _FILL;\n\n        if (bitbuf & 1)\n        {\n            bitbuf >>= 1;\n            if ((bitcnt -= 1) < 8)\n                _FILL;\n            *outptr++ = (uch)bitbuf;\n            bitcnt -= 8;\n            bitbuf >>= 8;\n        }\n        else\n        {\n            *outptr++ = '\\0';\n            bitcnt -= 1;\n            bitbuf >>= 1;\n        }\n    }\n} /* end function decompress_bits() */\n\n#endif /* VMS || VMS_TEXT_CONV */\n\n\n\n\n\n#ifdef SYMLINKS\n/***********************************/\n/* Function set_deferred_symlink() */\n/***********************************/\n\nstatic void set_deferred_symlink(__G__ slnk_entry)\n    __GDEF\n    slinkentry *slnk_entry;\n{\n    extent ucsize = slnk_entry->targetlen;\n    char *linkfname = slnk_entry->fname;\n    char *linktarget = (char *)malloc(ucsize+1);\n\n    if (!linktarget) {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname)));\n        return;\n    }\n    linktarget[ucsize] = '\\0';\n    G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */\n    /* Check that the following conditions are all fulfilled:\n     * a) the placeholder file exists,\n     * b) the placeholder file contains exactly \"ucsize\" bytes\n     *    (read the expected placeholder content length + 1 extra byte, this\n     *    should return the expected content length),\n     * c) the placeholder content matches the link target specification as\n     *    stored in the symlink control structure.\n     */\n    if (!G.outfile ||\n        fread(linktarget, 1, ucsize+1, G.outfile) != ucsize ||\n        strcmp(slnk_entry->target, linktarget))\n    {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname)));\n        free(linktarget);\n        if (G.outfile)\n            fclose(G.outfile);\n        return;\n    }\n    fclose(G.outfile);                  /* close \"data\" file for good... */\n    unlink(linkfname);                  /* ...and delete it */\n    if (QCOND2)\n        Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish),\n          FnFilter1(linkfname), FnFilter2(linktarget)));\n    if (symlink(linktarget, linkfname))  /* create the real link */\n        perror(\"symlink error\");\n    free(linktarget);\n#ifdef SET_SYMLINK_ATTRIBS\n    set_symlnk_attribs(__G__ slnk_entry);\n#endif\n    return;                             /* can't set time on symlinks */\n\n} /* end function set_deferred_symlink() */\n#endif /* SYMLINKS */\n\n\n\n\n/*************************/\n/*  Function fnfilter()  */        /* here instead of in list.c for SFX */\n/*************************/\n\nchar *fnfilter(raw, space, size)   /* convert name to safely printable form */\n    ZCONST char *raw;\n    uch *space;\n    extent size;\n{\n#ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */\n    ZCONST uch *r=(ZCONST uch *)raw;\n    uch *s=space;\n    uch *slim=NULL;\n    uch *se=NULL;\n    int have_overflow = FALSE;\n\n    if (size > 0) {\n        slim = space + size\n#ifdef _MBCS\n                     - (MB_CUR_MAX - 1)\n#endif\n                     - 4;\n    }\n    while (*r) {\n        if (size > 0 && s >= slim && se == NULL) {\n            se = s;\n        }\n#ifdef QDOS\n        if (qlflag & 2) {\n            if (*r == '/' || *r == '.') {\n                if (se != NULL && (s > (space + (size-3)))) {\n                    have_overflow = TRUE;\n                    break;\n                }\n                ++r;\n                *s++ = '_';\n                continue;\n            }\n        } else\n#endif\n#ifdef HAVE_WORKING_ISPRINT\n# ifndef UZ_FNFILTER_REPLACECHAR\n    /* A convenient choice for the replacement of unprintable char codes is\n     * the \"single char wildcard\", as this character is quite unlikely to\n     * appear in filenames by itself.  The following default definition\n     * sets the replacement char to a question mark as the most common\n     * \"single char wildcard\"; this setting should be overridden in the\n     * appropiate system-specific configuration header when needed.\n     */\n#   define UZ_FNFILTER_REPLACECHAR      '?'\n# endif\n        if (!isprint(*r)) {\n            if (*r < 32) {\n                /* ASCII control codes are escaped as \"^{letter}\". */\n                if (se != NULL && (s > (space + (size-4)))) {\n                    have_overflow = TRUE;\n                    break;\n                }\n                *s++ = '^', *s++ = (uch)(64 + *r++);\n            } else {\n                /* Other unprintable codes are replaced by the\n                 * placeholder character. */\n                if (se != NULL && (s > (space + (size-3)))) {\n                    have_overflow = TRUE;\n                    break;\n                }\n                *s++ = UZ_FNFILTER_REPLACECHAR;\n                INCSTR(r);\n            }\n#else /* !HAVE_WORKING_ISPRINT */\n        if (*r < 32) {\n            /* ASCII control codes are escaped as \"^{letter}\". */\n            if (se != NULL && (s > (space + (size-4)))) {\n                have_overflow = TRUE;\n                break;\n            }\n            *s++ = '^', *s++ = (uch)(64 + *r++);\n#endif /* ?HAVE_WORKING_ISPRINT */\n        } else {\n#ifdef _MBCS\n            unsigned i = CLEN(r);\n            if (se != NULL && (s > (space + (size-i-2)))) {\n                have_overflow = TRUE;\n                break;\n            }\n            for (; i > 0; i--)\n                *s++ = *r++;\n#else\n            if (se != NULL && (s > (space + (size-3)))) {\n                have_overflow = TRUE;\n                break;\n            }\n            *s++ = *r++;\n#endif\n         }\n    }\n    if (have_overflow) {\n        strcpy((char *)se, \"...\");\n    } else {\n        *s = '\\0';\n    }\n\n#ifdef WINDLL\n    INTERN_TO_ISO((char *)space, (char *)space);  /* translate to ANSI */\n#else\n#if (defined(WIN32) && !defined(_WIN32_WCE))\n    /* Win9x console always uses OEM character coding, and\n       WinNT console is set to OEM charset by default, too */\n    INTERN_TO_OEM((char *)space, (char *)space);\n#endif /* (WIN32 && !_WIN32_WCE) */\n#endif /* ?WINDLL */\n\n    return (char *)space;\n\n#else /* NATIVE:  EBCDIC or whatever */\n    return (char *)raw;\n#endif\n\n} /* end function fnfilter() */\n\n\n\n\n#ifdef SET_DIR_ATTRIB\n/* must sort saved directories so can set perms from bottom up */\n\n/************************/\n/*  Function dircomp()  */\n/************************/\n\nstatic int Cdecl dircomp(a, b)  /* used by qsort(); swiped from Zip */\n    ZCONST zvoid *a, *b;\n{\n    /* order is significant:  this sorts in reverse order (deepest first) */\n    return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn);\n /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */\n}\n\n#endif /* SET_DIR_ATTRIB */\n\n\n#ifdef USE_BZIP2\n\n/**************************/\n/*  Function UZbunzip2()  */\n/**************************/\n\nint UZbunzip2(__G)\n__GDEF\n/* decompress a bzipped entry using the libbz2 routines */\n{\n    int retval = 0;     /* return code: 0 = \"no error\" */\n    int err=BZ_OK;\n    int repeated_buf_err;\n    bz_stream bstrm;\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    if (G.redirect_slide)\n        wsize = G.redirect_size, redirSlide = G.redirect_buffer;\n    else\n        wsize = WSIZE, redirSlide = slide;\n#endif\n\n    bstrm.next_out = (char *)redirSlide;\n    bstrm.avail_out = wsize;\n\n    bstrm.next_in = (char *)G.inptr;\n    bstrm.avail_in = G.incnt;\n\n    {\n        /* local buffer for efficiency */\n        /* $TODO Check for BZIP LIB version? */\n\n        bstrm.bzalloc = NULL;\n        bstrm.bzfree = NULL;\n        bstrm.opaque = NULL;\n\n        Trace((stderr, \"initializing bzlib()\\n\"));\n        err = BZ2_bzDecompressInit(&bstrm, 0, 0);\n\n        if (err == BZ_MEM_ERROR)\n            return 3;\n        else if (err != BZ_OK)\n            Trace((stderr, \"oops!  (BZ2_bzDecompressInit() err = %d)\\n\", err));\n    }\n\n#ifdef FUNZIP\n    while (err != BZ_STREAM_END) {\n#else /* !FUNZIP */\n    while (G.csize > 0) {\n        Trace((stderr, \"first loop:  G.csize = %ld\\n\", G.csize));\n#endif /* ?FUNZIP */\n        while (bstrm.avail_out > 0) {\n            err = BZ2_bzDecompress(&bstrm);\n\n            if (err == BZ_DATA_ERROR) {\n                retval = 2; goto uzbunzip_cleanup_exit;\n            } else if (err == BZ_MEM_ERROR) {\n                retval = 3; goto uzbunzip_cleanup_exit;\n            } else if (err != BZ_OK && err != BZ_STREAM_END)\n                Trace((stderr, \"oops!  (bzip(first loop) err = %d)\\n\", err));\n\n#ifdef FUNZIP\n            if (err == BZ_STREAM_END)    /* \"END-of-entry-condition\" ? */\n#else /* !FUNZIP */\n            if (G.csize <= 0L)          /* \"END-of-entry-condition\" ? */\n#endif /* ?FUNZIP */\n                break;\n\n            if (bstrm.avail_in == 0) {\n                if (fillinbuf(__G) == 0) {\n                    /* no \"END-condition\" yet, but no more data */\n                    retval = 2; goto uzbunzip_cleanup_exit;\n                }\n\n                bstrm.next_in = (char *)G.inptr;\n                bstrm.avail_in = G.incnt;\n            }\n            Trace((stderr, \"     avail_in = %u\\n\", bstrm.avail_in));\n        }\n        /* flush slide[] */\n        if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)\n            goto uzbunzip_cleanup_exit;\n        Trace((stderr, \"inside loop:  flushing %ld bytes (ptr diff = %ld)\\n\",\n          (long)(wsize - bstrm.avail_out),\n          (long)(bstrm.next_out-(char *)redirSlide)));\n        bstrm.next_out = (char *)redirSlide;\n        bstrm.avail_out = wsize;\n    }\n\n    /* no more input, so loop until we have all output */\n    Trace((stderr, \"beginning final loop:  err = %d\\n\", err));\n    repeated_buf_err = FALSE;\n    while (err != BZ_STREAM_END) {\n        err = BZ2_bzDecompress(&bstrm);\n        if (err == BZ_DATA_ERROR) {\n            retval = 2; goto uzbunzip_cleanup_exit;\n        } else if (err == BZ_MEM_ERROR) {\n            retval = 3; goto uzbunzip_cleanup_exit;\n        } else if (err != BZ_OK && err != BZ_STREAM_END) {\n            Trace((stderr, \"oops!  (bzip(final loop) err = %d)\\n\", err));\n            DESTROYGLOBALS();\n            EXIT(PK_MEM3);\n        }\n        /* final flush of slide[] */\n        if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0)\n            goto uzbunzip_cleanup_exit;\n        Trace((stderr, \"final loop:  flushing %ld bytes (ptr diff = %ld)\\n\",\n          (long)(wsize - bstrm.avail_out),\n          (long)(bstrm.next_out-(char *)redirSlide)));\n        bstrm.next_out = (char *)redirSlide;\n        bstrm.avail_out = wsize;\n    }\n#ifdef LARGE_FILE_SUPPORT\n    Trace((stderr, \"total in = %llu, total out = %llu\\n\",\n      (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32,\n      (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32));\n#else\n    Trace((stderr, \"total in = %lu, total out = %lu\\n\", bstrm.total_in_lo32,\n      bstrm.total_out_lo32));\n#endif\n\n    G.inptr = (uch *)bstrm.next_in;\n    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */\n\nuzbunzip_cleanup_exit:\n    err = BZ2_bzDecompressEnd(&bstrm);\n    if (err != BZ_OK)\n        Trace((stderr, \"oops!  (BZ2_bzDecompressEnd() err = %d)\\n\", err));\n\n    return retval;\n} /* end function UZbunzip2() */\n#endif /* USE_BZIP2 */\n"
  },
  {
    "path": "deps/infozip/unzip60/file_id.diz",
    "content": "Info-ZIP's UnZip 6.0: generic C sources\n  Complete C source code for Info-ZIP's\n  PKUNZIP-compatible .zip extractor, for\n  all supported compilers and platforms\n  (Unix, OS/2, MS-DOS, NT, VMS, Amiga,\n  Atari, Mac, Acorn, VM/CMS, etc.), plus\n  lots of pretty decent documentation.\nThis is FREE (but copyrighted) software.\nSee LICENSE for details on distribution\nand reuse.\n"
  },
  {
    "path": "deps/infozip/unzip60/fileio.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  fileio.c\n\n  This file contains routines for doing direct but relatively generic input/\n  output, file-related sorts of things, plus some miscellaneous stuff.  Most\n  of the stuff has to do with opening, closing, reading and/or writing files.\n\n  Contains:  open_input_file()\n             open_outfile()           (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM)\n             undefer_input()\n             defer_leftover_input()\n             readbuf()\n             readbyte()\n             fillinbuf()\n             seek_zipf()\n             flush()                  (non-VMS)\n             is_vms_varlen_txt()      (non-VMS, VMS_TEXT_CONV only)\n             disk_error()             (non-VMS)\n             UzpMessagePrnt()\n             UzpMessageNull()         (DLL only)\n             UzpInput()\n             UzpMorePause()\n             UzpPassword()            (non-WINDLL)\n             handler()\n             dos_to_unix_time()       (non-VMS, non-VM/CMS, non-MVS)\n             check_for_newer()        (non-VMS, non-OS/2, non-VM/CMS, non-MVS)\n             do_string()\n             makeword()\n             makelong()\n             makeint64()\n             fzofft()\n             str2iso()                (CRYPT && NEED_STR2ISO, only)\n             str2oem()                (CRYPT && NEED_STR2OEM, only)\n             memset()                 (ZMEM only)\n             memcpy()                 (ZMEM only)\n             zstrnicmp()              (NO_STRNICMP only)\n             zstat()                  (REGULUS only)\n             plastchar()              (_MBCS only)\n             uzmbclen()               (_MBCS && NEED_UZMBCLEN, only)\n             uzmbschr()               (_MBCS && NEED_UZMBSCHR, only)\n             uzmbsrchr()              (_MBCS && NEED_UZMBSRCHR, only)\n             fLoadFarString()         (SMALL_MEM only)\n             fLoadFarStringSmall()    (SMALL_MEM only)\n             fLoadFarStringSmall2()   (SMALL_MEM only)\n             zfstrcpy()               (SMALL_MEM only)\n             zfstrcmp()               (SMALL_MEM && !(SFX || FUNZIP) only)\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __FILEIO_C      /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#  include <setjmp.h>\n#endif\n#include \"crc32.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n\n/* setup of codepage conversion for decryption passwords */\n#if CRYPT\n#  if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))\n#    define IZ_ISO2OEM_ARRAY            /* pull in iso2oem[] table */\n#  endif\n#  if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))\n#    define IZ_OEM2ISO_ARRAY            /* pull in oem2iso[] table */\n#  endif\n#endif\n#include \"ebcdic.h\"   /* definition/initialization of ebcdic[] */\n\n\n/*\n   Note: Under Windows, the maximum size of the buffer that can be used\n   with any of the *printf calls is 16,384, so win_fprintf was used to\n   feed the fprintf clone no more than 16K chunks at a time. This should\n   be valid for anything up to 64K (and probably beyond, assuming your\n   buffers are that big).\n*/\n#ifdef WINDLL\n#  define WriteError(buf,len,strm) \\\n   (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))\n#else /* !WINDLL */\n#  ifdef USE_FWRITE\n#    define WriteError(buf,len,strm) \\\n     ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))\n#  else\n#    define WriteError(buf,len,strm) \\\n     ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))\n#  endif\n#endif /* ?WINDLL */\n\n/*\n   2005-09-16 SMS.\n   On VMS, when output is redirected to a file, as in a command like\n   \"PIPE UNZIP -v > X.OUT\", the output file is created with VFC record\n   format, and multiple calls to write() or fwrite() will produce multiple\n   records, even when there's no newline terminator in the buffer.\n   The result is unsightly output with spurious newlines.  Using fprintf()\n   instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt()\n   below, together seem to solve the problem.\n\n   According to the C RTL manual, \"The write and decc$record_write\n   functions always generate at least one record.\"  Also, \"[T]he fwrite\n   function always generates at least <number_items> records.\"  So,\n   \"fwrite(buf, len, 1, strm)\" is much better (\"1\" record) than\n   \"fwrite(buf, 1, len, strm)\" (\"len\" (1-character) records, _really_\n   ugly), but neither is better than write().  Similarly, \"The fflush\n   function always generates a record if there is unwritten data in the\n   buffer.\"  Apparently fprintf() buffers the stuff somewhere, and puts\n   out a record (only) when it sees a newline.\n*/\n#ifdef VMS\n#  define WriteTxtErr(buf,len,strm) \\\n   ((extent)fprintf(strm, \"%.*s\", len, buf) != (extent)(len))\n#else\n#  define WriteTxtErr(buf,len,strm)  WriteError(buf,len,strm)\n#endif\n\n#if (defined(USE_DEFLATE64) && defined(__16BIT__))\nstatic int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink));\n#endif\n#ifdef VMS_TEXT_CONV\nstatic int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len));\n#endif\nstatic int disk_error OF((__GPRO));\n\n\n/****************************/\n/* Strings used in fileio.c */\n/****************************/\n\nstatic ZCONST char Far CannotOpenZipfile[] =\n  \"error:  cannot open zipfile [ %s ]\\n        %s\\n\";\n\n#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))\n#if (!defined(TANDEM))\n#if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32))\n   static ZCONST char Far CannotDeleteOldFile[] =\n     \"error:  cannot delete old %s\\n        %s\\n\";\n#ifdef UNIXBACKUP\n   static ZCONST char Far CannotRenameOldFile[] =\n     \"error:  cannot rename old %s\\n        %s\\n\";\n   static ZCONST char Far BackupSuffix[] = \"~\";\n#endif\n#endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */\n#ifdef NOVELL_BUG_FAILSAFE\n   static ZCONST char Far NovellBug[] =\n     \"error:  %s: stat() says does not exist, but fopen() found anyway\\n\";\n#endif\n   static ZCONST char Far CannotCreateFile[] =\n     \"error:  cannot create %s\\n        %s\\n\";\n#endif /* !TANDEM */\n#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */\n\nstatic ZCONST char Far ReadError[] = \"error:  zipfile read error\\n\";\nstatic ZCONST char Far FilenameTooLongTrunc[] =\n  \"warning:  filename too long--truncating.\\n\";\n#ifdef UNICODE_SUPPORT\n   static ZCONST char Far UFilenameTooLongTrunc[] =\n     \"warning:  Converted unicode filename too long--truncating.\\n\";\n#endif\nstatic ZCONST char Far ExtraFieldTooLong[] =\n  \"warning:  extra field too long (%d).  Ignoring...\\n\";\n\n#ifdef WINDLL\n   static ZCONST char Far DiskFullQuery[] =\n     \"%s:  write error (disk full?).\\n\";\n#else\n   static ZCONST char Far DiskFullQuery[] =\n     \"%s:  write error (disk full?).  Continue? (y/n/^C) \";\n   static ZCONST char Far ZipfileCorrupt[] =\n     \"error:  zipfile probably corrupt (%s)\\n\";\n#  ifdef SYMLINKS\n     static ZCONST char Far FileIsSymLink[] =\n       \"%s exists and is a symbolic link%s.\\n\";\n#  endif\n#  ifdef MORE\n     static ZCONST char Far MorePrompt[] = \"--More--(%lu)\";\n#  endif\n   static ZCONST char Far QuitPrompt[] =\n     \"--- Press `Q' to quit, or any other key to continue ---\";\n   static ZCONST char Far HidePrompt[] = /* \"\\r                       \\r\"; */\n     \"\\r                                                         \\r\";\n#  if CRYPT\n#    ifdef MACOS\n       /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */\n       static ZCONST char Far PasswPrompt[] = \"[%s]\\n %s password: \";\n#    else\n       static ZCONST char Far PasswPrompt[] = \"[%s] %s password: \";\n#    endif\n     static ZCONST char Far PasswPrompt2[] = \"Enter password: \";\n     static ZCONST char Far PasswRetry[] = \"password incorrect--reenter: \";\n#  endif /* CRYPT */\n#endif /* !WINDLL */\n\n\n\n\n\n/******************************/\n/* Function open_input_file() */\n/******************************/\n\nint open_input_file(__G)    /* return 1 if open failed */\n    __GDEF\n{\n    /*\n     *  open the zipfile for reading and in BINARY mode to prevent cr/lf\n     *  translation, which would corrupt the bitstreams\n     */\n\n#ifdef VMS\n    G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS);\n#else /* !VMS */\n#ifdef MACOS\n    G.zipfd = open(G.zipfn, 0);\n#else /* !MACOS */\n#ifdef CMS_MVS\n    G.zipfd = vmmvs_open_infile(__G);\n#else /* !CMS_MVS */\n#ifdef USE_STRM_INPUT\n    G.zipfd = fopen(G.zipfn, FOPR);\n#else /* !USE_STRM_INPUT */\n    G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);\n#endif /* ?USE_STRM_INPUT */\n#endif /* ?CMS_MVS */\n#endif /* ?MACOS */\n#endif /* ?VMS */\n\n#ifdef USE_STRM_INPUT\n    if (G.zipfd == NULL)\n#else\n    /* if (G.zipfd < 0) */  /* no good for Windows CE port */\n    if (G.zipfd == -1)\n#endif\n    {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),\n          G.zipfn, strerror(errno)));\n        return 1;\n    }\n    return 0;\n\n} /* end function open_input_file() */\n\n\n\n\n#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))\n#if (!defined(TANDEM))\n\n/***************************/\n/* Function open_outfile() */\n/***************************/\n\nint open_outfile(__G)           /* return 1 if fail */\n    __GDEF\n{\n#ifdef DLL\n    if (G.redirect_data)\n        return (redirect_outfile(__G) == FALSE);\n#endif\n#ifdef QDOS\n    QFilename(__G__ G.filename);\n#endif\n#if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX))\n#ifdef BORLAND_STAT_BUG\n    /* Borland 5.0's stat() barfs if the filename has no extension and the\n     * file doesn't exist. */\n    if (access(G.filename, 0) == -1) {\n        FILE *tmp = fopen(G.filename, \"wb+\");\n\n        /* file doesn't exist, so create a dummy file to keep stat() from\n         * failing (will be over-written anyway) */\n        fputc('0', tmp);  /* just to have something in the file */\n        fclose(tmp);\n    }\n#endif /* BORLAND_STAT_BUG */\n#ifdef SYMLINKS\n    if (SSTAT(G.filename, &G.statbuf) == 0 ||\n        lstat(G.filename, &G.statbuf) == 0)\n#else\n    if (SSTAT(G.filename, &G.statbuf) == 0)\n#endif /* ?SYMLINKS */\n    {\n        Trace((stderr, \"open_outfile:  stat(%s) returns 0:  file exists\\n\",\n          FnFilter1(G.filename)));\n#ifdef UNIXBACKUP\n        if (uO.B_flag) {    /* do backup */\n            char *tname;\n            z_stat tmpstat;\n            int blen, flen, tlen;\n\n            blen = strlen(BackupSuffix);\n            flen = strlen(G.filename);\n            tlen = flen + blen + 6;    /* includes space for 5 digits */\n            if (tlen >= FILNAMSIZ) {   /* in case name is too long, truncate */\n                tname = (char *)malloc(FILNAMSIZ);\n                if (tname == NULL)\n                    return 1;                 /* in case we run out of space */\n                tlen = FILNAMSIZ - 1 - blen;\n                strcpy(tname, G.filename);    /* make backup name */\n                tname[tlen] = '\\0';\n                if (flen > tlen) flen = tlen;\n                tlen = FILNAMSIZ;\n            } else {\n                tname = (char *)malloc(tlen);\n                if (tname == NULL)\n                    return 1;                 /* in case we run out of space */\n                strcpy(tname, G.filename);    /* make backup name */\n            }\n            strcpy(tname+flen, BackupSuffix);\n\n            if (IS_OVERWRT_ALL) {\n                /* If there is a previous backup file, delete it,\n                 * otherwise the following rename operation may fail.\n                 */\n                if (SSTAT(tname, &tmpstat) == 0)\n                    unlink(tname);\n            } else {\n                /* Check if backupname exists, and, if it's true, try\n                 * appending numbers of up to 5 digits (or the maximum\n                 * \"unsigned int\" number on 16-bit systems) to the\n                 * BackupSuffix, until an unused name is found.\n                 */\n                unsigned maxtail, i;\n                char *numtail = tname + flen + blen;\n\n                /* take account of the \"unsigned\" limit on 16-bit systems: */\n                maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) );\n                switch (tlen - flen - blen - 1) {\n                    case 4: maxtail = 9999; break;\n                    case 3: maxtail = 999; break;\n                    case 2: maxtail = 99; break;\n                    case 1: maxtail = 9; break;\n                    case 0: maxtail = 0; break;\n                }\n                /* while filename exists */\n                for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);)\n                    sprintf(numtail,\"%u\", ++i);\n            }\n\n            if (rename(G.filename, tname) != 0) {   /* move file */\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotRenameOldFile),\n                  FnFilter1(G.filename), strerror(errno)));\n                free(tname);\n                return 1;\n            }\n            Trace((stderr, \"open_outfile:  %s now renamed into %s\\n\",\n              FnFilter1(G.filename), FnFilter2(tname)));\n            free(tname);\n        } else\n#endif /* UNIXBACKUP */\n        {\n#ifdef DOS_FLX_OS2_W32\n            if (!(G.statbuf.st_mode & S_IWRITE)) {\n                Trace((stderr,\n                  \"open_outfile:  existing file %s is read-only\\n\",\n                  FnFilter1(G.filename)));\n                chmod(G.filename, S_IREAD | S_IWRITE);\n                Trace((stderr, \"open_outfile:  %s now writable\\n\",\n                  FnFilter1(G.filename)));\n            }\n#endif /* DOS_FLX_OS2_W32 */\n#ifdef NLM\n            /* Give the file read/write permission (non-POSIX shortcut) */\n            chmod(G.filename, 0);\n#endif /* NLM */\n            if (unlink(G.filename) != 0) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotDeleteOldFile),\n                  FnFilter1(G.filename), strerror(errno)));\n                return 1;\n            }\n            Trace((stderr, \"open_outfile:  %s now deleted\\n\",\n              FnFilter1(G.filename)));\n        }\n    }\n#endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */\n#ifdef RISCOS\n    if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {\n        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename), strerror(errno)));\n        return 1;\n    }\n#endif /* RISCOS */\n#ifdef TOPS20\n    char *tfilnam;\n\n    if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)\n        return 1;\n    strcpy(tfilnam, G.filename);\n    upper(tfilnam);\n    enquote(tfilnam);\n    if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {\n        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),\n          tfilnam, strerror(errno)));\n        free(tfilnam);\n        return 1;\n    }\n    free(tfilnam);\n#else /* !TOPS20 */\n#ifdef MTS\n    if (uO.aflag)\n        G.outfile = zfopen(G.filename, FOPWT);\n    else\n        G.outfile = zfopen(G.filename, FOPW);\n    if (G.outfile == (FILE *)NULL) {\n        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename), strerror(errno)));\n        return 1;\n    }\n#else /* !MTS */\n#ifdef DEBUG\n    Info(slide, 1, ((char *)slide,\n      \"open_outfile:  doing fopen(%s) for reading\\n\", FnFilter1(G.filename)));\n    if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL)\n        Info(slide, 1, ((char *)slide,\n          \"open_outfile:  fopen(%s) for reading failed:  does not exist\\n\",\n          FnFilter1(G.filename)));\n    else {\n        Info(slide, 1, ((char *)slide,\n          \"open_outfile:  fopen(%s) for reading succeeded:  file exists\\n\",\n          FnFilter1(G.filename)));\n        fclose(G.outfile);\n    }\n#endif /* DEBUG */\n#ifdef NOVELL_BUG_FAILSAFE\n    if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),\n          FnFilter1(G.filename)));\n        fclose(G.outfile);\n        return 1;   /* with \"./\" fix in checkdir(), should never reach here */\n    }\n#endif /* NOVELL_BUG_FAILSAFE */\n    Trace((stderr, \"open_outfile:  doing fopen(%s) for writing\\n\",\n      FnFilter1(G.filename)));\n    {\n#if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)\n        mode_t umask_sav = umask(0077);\n#endif\n#if defined(SYMLINKS) || defined(QLZIP)\n        /* These features require the ability to re-read extracted data from\n           the output files. Output files are created with Read&Write access.\n         */\n        G.outfile = zfopen(G.filename, FOPWR);\n#else\n        G.outfile = zfopen(G.filename, FOPW);\n#endif\n#if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)\n        umask(umask_sav);\n#endif\n    }\n    if (G.outfile == (FILE *)NULL) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename), strerror(errno)));\n        return 1;\n    }\n    Trace((stderr, \"open_outfile:  fopen(%s) for writing succeeded\\n\",\n      FnFilter1(G.filename)));\n#endif /* !MTS */\n#endif /* !TOPS20 */\n\n#ifdef USE_FWRITE\n#ifdef DOS_NLM_OS2_W32\n    /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE):  bogus */\n    setbuf(G.outfile, (char *)NULL);   /* make output unbuffered */\n#else /* !DOS_NLM_OS2_W32 */\n#ifndef RISCOS\n#ifdef _IOFBF  /* make output fully buffered (works just about like write()) */\n    setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);\n#else\n    setbuf(G.outfile, (char *)slide);\n#endif\n#endif /* !RISCOS */\n#endif /* ?DOS_NLM_OS2_W32 */\n#endif /* USE_FWRITE */\n#ifdef OS2_W32\n    /* preallocate the final file size to prevent file fragmentation */\n    SetFileSize(G.outfile, G.lrec.ucsize);\n#endif\n    return 0;\n\n} /* end function open_outfile() */\n\n#endif /* !TANDEM */\n#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */\n\n\n\n\n\n/*\n * These functions allow NEXTBYTE to function without needing two bounds\n * checks.  Call defer_leftover_input() if you ever have filled G.inbuf\n * by some means other than readbyte(), and you then want to start using\n * NEXTBYTE.  When going back to processing bytes without NEXTBYTE, call\n * undefer_input().  For example, extract_or_test_member brackets its\n * central section that does the decompression with these two functions.\n * If you need to check the number of bytes remaining in the current\n * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.\n */\n\n/****************************/\n/* function undefer_input() */\n/****************************/\n\nvoid undefer_input(__G)\n    __GDEF\n{\n    if (G.incnt > 0)\n        G.csize += G.incnt;\n    if (G.incnt_leftover > 0) {\n        /* We know that \"(G.csize < MAXINT)\" so we can cast G.csize to int:\n         * This condition was checked when G.incnt_leftover was set > 0 in\n         * defer_leftover_input(), and it is NOT allowed to touch G.csize\n         * before calling undefer_input() when (G.incnt_leftover > 0)\n         * (single exception: see read_byte()'s  \"G.csize <= 0\" handling) !!\n         */\n        G.incnt = G.incnt_leftover + (int)G.csize;\n        G.inptr = G.inptr_leftover - (int)G.csize;\n        G.incnt_leftover = 0;\n    } else if (G.incnt < 0)\n        G.incnt = 0;\n} /* end function undefer_input() */\n\n\n\n\n\n/***********************************/\n/* function defer_leftover_input() */\n/***********************************/\n\nvoid defer_leftover_input(__G)\n    __GDEF\n{\n    if ((zoff_t)G.incnt > G.csize) {\n        /* (G.csize < MAXINT), we can safely cast it to int !! */\n        if (G.csize < 0L)\n            G.csize = 0L;\n        G.inptr_leftover = G.inptr + (int)G.csize;\n        G.incnt_leftover = G.incnt - (int)G.csize;\n        G.incnt = (int)G.csize;\n    } else\n        G.incnt_leftover = 0;\n    G.csize -= G.incnt;\n} /* end function defer_leftover_input() */\n\n\n\n\n\n/**********************/\n/* Function readbuf() */\n/**********************/\n\nunsigned readbuf(__G__ buf, size)   /* return number of bytes read into buf */\n    __GDEF\n    char *buf;\n    register unsigned size;\n{\n    register unsigned count;\n    unsigned n;\n\n    n = size;\n    while (size) {\n        if (G.incnt <= 0) {\n            if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)\n                return (n-size);\n            else if (G.incnt < 0) {\n                /* another hack, but no real harm copying same thing twice */\n                (*G.message)((zvoid *)&G,\n                  (uch *)LoadFarString(ReadError),  /* CANNOT use slide */\n                  (ulg)strlen(LoadFarString(ReadError)), 0x401);\n                return 0;  /* discarding some data; better than lock-up */\n            }\n            /* buffer ALWAYS starts on a block boundary:  */\n            G.cur_zipfile_bufstart += INBUFSIZ;\n            G.inptr = G.inbuf;\n        }\n        count = MIN(size, (unsigned)G.incnt);\n        memcpy(buf, G.inptr, count);\n        buf += count;\n        G.inptr += count;\n        G.incnt -= count;\n        size -= count;\n    }\n    return n;\n\n} /* end function readbuf() */\n\n\n\n\n\n/***********************/\n/* Function readbyte() */\n/***********************/\n\nint readbyte(__G)   /* refill inbuf and return a byte if available, else EOF */\n    __GDEF\n{\n    if (G.mem_mode)\n        return EOF;\n    if (G.csize <= 0) {\n        G.csize--;             /* for tests done after exploding */\n        G.incnt = 0;\n        return EOF;\n    }\n    if (G.incnt <= 0) {\n        if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {\n            return EOF;\n        } else if (G.incnt < 0) {  /* \"fail\" (abort, retry, ...) returns this */\n            /* another hack, but no real harm copying same thing twice */\n            (*G.message)((zvoid *)&G,\n              (uch *)LoadFarString(ReadError),\n              (ulg)strlen(LoadFarString(ReadError)), 0x401);\n            echon();\n#ifdef WINDLL\n            longjmp(dll_error_return, 1);\n#else\n            DESTROYGLOBALS();\n            EXIT(PK_BADERR);    /* totally bailing; better than lock-up */\n#endif\n        }\n        G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */\n        G.inptr = G.inbuf;\n        defer_leftover_input(__G);           /* decrements G.csize */\n    }\n\n#if CRYPT\n    if (G.pInfo->encrypted) {\n        uch *p;\n        int n;\n\n        /* This was previously set to decrypt one byte beyond G.csize, when\n         * incnt reached that far.  GRR said, \"but it's required:  why?\"  This\n         * was a bug in fillinbuf() -- was it also a bug here?\n         */\n        for (n = G.incnt, p = G.inptr;  n--;  p++)\n            zdecode(*p);\n    }\n#endif /* CRYPT */\n\n    --G.incnt;\n    return *G.inptr++;\n\n} /* end function readbyte() */\n\n\n\n\n\n#if defined(USE_ZLIB) || defined(USE_BZIP2)\n\n/************************/\n/* Function fillinbuf() */\n/************************/\n\nint fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */\n    __GDEF\n{\n    if (G.mem_mode ||\n                  (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)\n        return 0;\n    G.cur_zipfile_bufstart += INBUFSIZ;  /* always starts on a block boundary */\n    G.inptr = G.inbuf;\n    defer_leftover_input(__G);           /* decrements G.csize */\n\n#if CRYPT\n    if (G.pInfo->encrypted) {\n        uch *p;\n        int n;\n\n        for (n = G.incnt, p = G.inptr;  n--;  p++)\n            zdecode(*p);\n    }\n#endif /* CRYPT */\n\n    return G.incnt;\n\n} /* end function fillinbuf() */\n\n#endif /* USE_ZLIB || USE_BZIP2 */\n\n\n\n\n\n/************************/\n/* Function seek_zipf() */\n/************************/\n\nint seek_zipf(__G__ abs_offset)\n    __GDEF\n    zoff_t abs_offset;\n{\n/*\n *  Seek to the block boundary of the block which includes abs_offset,\n *  then read block into input buffer and set pointers appropriately.\n *  If block is already in the buffer, just set the pointers.  This function\n *  is used by do_seekable (process.c), extract_or_test_entrylist (extract.c)\n *  and do_string (fileio.c).  Also, a slightly modified version is embedded\n *  within extract_or_test_entrylist (extract.c).  readbyte() and readbuf()\n *  (fileio.c) are compatible.  NOTE THAT abs_offset is intended to be the\n *  \"proper offset\" (i.e., if there were no extra bytes prepended);\n *  cur_zipfile_bufstart contains the corrected offset.\n *\n *  Since seek_zipf() is never used during decompression, it is safe to\n *  use the slide[] buffer for the error message.\n *\n * returns PK error codes:\n *  PK_BADERR if effective offset in zipfile is negative\n *  PK_EOF if seeking past end of zipfile\n *  PK_OK when seek was successful\n */\n    zoff_t request = abs_offset + G.extra_bytes;\n    zoff_t inbuf_offset = request % INBUFSIZ;\n    zoff_t bufstart = request - inbuf_offset;\n\n    if (request < 0) {\n        Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),\n             G.zipfn, LoadFarString(ReportMsg)));\n        return(PK_BADERR);\n    } else if (bufstart != G.cur_zipfile_bufstart) {\n        Trace((stderr,\n          \"fpos_zip: abs_offset = %s, G.extra_bytes = %s\\n\",\n          FmZofft(abs_offset, NULL, NULL),\n          FmZofft(G.extra_bytes, NULL, NULL)));\n#ifdef USE_STRM_INPUT\n        zfseeko(G.zipfd, bufstart, SEEK_SET);\n        G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n        G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n        Trace((stderr,\n          \"       request = %s, (abs+extra) = %s, inbuf_offset = %s\\n\",\n          FmZofft(request, NULL, NULL),\n          FmZofft((abs_offset+G.extra_bytes), NULL, NULL),\n          FmZofft(inbuf_offset, NULL, NULL)));\n        Trace((stderr, \"       bufstart = %s, cur_zipfile_bufstart = %s\\n\",\n          FmZofft(bufstart, NULL, NULL),\n          FmZofft(G.cur_zipfile_bufstart, NULL, NULL)));\n        if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)\n            return(PK_EOF);\n        G.incnt -= (int)inbuf_offset;\n        G.inptr = G.inbuf + (int)inbuf_offset;\n    } else {\n        G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;\n        G.inptr = G.inbuf + (int)inbuf_offset;\n    }\n    return(PK_OK);\n} /* end function seek_zipf() */\n\n\n\n\n\n#ifndef VMS  /* for VMS use code in vms.c */\n\n/********************/\n/* Function flush() */   /* returns PK error codes: */\n/********************/   /* if tflag => always 0; PK_DISK if write error */\n\nint flush(__G__ rawbuf, size, unshrink)\n    __GDEF\n    uch *rawbuf;\n    ulg size;\n    int unshrink;\n#if (defined(USE_DEFLATE64) && defined(__16BIT__))\n{\n    int ret;\n\n    /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions\n     * cannot handle writes of 64k blocks at once.  For these systems, the\n     * blocks to flush are split into pieces of 32k or less.\n     */\n    while (size > 0x8000L) {\n        ret = partflush(__G__ rawbuf, 0x8000L, unshrink);\n        if (ret != PK_OK)\n            return ret;\n        size -= 0x8000L;\n        rawbuf += (extent)0x8000;\n    }\n    return partflush(__G__ rawbuf, size, unshrink);\n} /* end function flush() */\n\n\n/************************/\n/* Function partflush() */  /* returns PK error codes: */\n/************************/  /* if tflag => always 0; PK_DISK if write error */\n\nstatic int partflush(__G__ rawbuf, size, unshrink)\n    __GDEF\n    uch *rawbuf;        /* cannot be ZCONST, gets passed to (*G.message)() */\n    ulg size;\n    int unshrink;\n#endif /* USE_DEFLATE64 && __16BIT__ */\n{\n    register uch *p;\n    register uch *q;\n    uch *transbuf;\n#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))\n    ulg transbufsiz;\n#endif\n    /* static int didCRlast = FALSE;    moved to globals.h */\n\n\n/*---------------------------------------------------------------------------\n    Compute the CRC first; if testing or if disk is full, that's it.\n  ---------------------------------------------------------------------------*/\n\n    G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);\n\n#ifdef DLL\n    if ((G.statreportcb != NULL) &&\n        (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))\n        return IZ_CTRLC;        /* cancel operation by user request */\n#endif\n\n    if (uO.tflag || size == 0L)  /* testing or nothing to write:  all done */\n        return PK_OK;\n\n    if (G.disk_full)\n        return PK_DISK;         /* disk already full:  ignore rest of file */\n\n/*---------------------------------------------------------------------------\n    Write the bytes rawbuf[0..size-1] to the output device, first converting\n    end-of-lines and ASCII/EBCDIC as needed.  If SMALL_MEM or MED_MEM are NOT\n    defined, outbuf is assumed to be at least as large as rawbuf and is not\n    necessarily checked for overflow.\n  ---------------------------------------------------------------------------*/\n\n    if (!G.pInfo->textmode) {   /* write raw binary data */\n        /* GRR:  note that for standard MS-DOS compilers, size argument to\n         * fwrite() can never be more than 65534, so WriteError macro will\n         * have to be rewritten if size can ever be that large.  For now,\n         * never more than 32K.  Also note that write() returns an int, which\n         * doesn't necessarily limit size to 32767 bytes if write() is used\n         * on 16-bit systems but does make it more of a pain; however, because\n         * at least MSC 5.1 has a lousy implementation of fwrite() (as does\n         * DEC Ultrix cc), write() is used anyway.\n         */\n#ifdef DLL\n        if (G.redirect_data) {\n#ifdef NO_SLIDE_REDIR\n            if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR;\n#else\n            writeToMemory(__G__ rawbuf, (extent)size);\n#endif\n        } else\n#endif\n        if (!uO.cflag && WriteError(rawbuf, size, G.outfile))\n            return disk_error(__G);\n        else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))\n            return PK_OK;\n    } else {   /* textmode:  aflag is true */\n        if (unshrink) {\n            /* rawbuf = outbuf */\n            transbuf = G.outbuf2;\n#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))\n            transbufsiz = TRANSBUFSIZ;\n#endif\n        } else {\n            /* rawbuf = slide */\n            transbuf = G.outbuf;\n#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))\n            transbufsiz = OUTBUFSIZ;\n            Trace((stderr, \"\\ntransbufsiz = OUTBUFSIZ = %u\\n\",\n                   (unsigned)OUTBUFSIZ));\n#endif\n        }\n        if (G.newfile) {\n#ifdef VMS_TEXT_CONV\n            if (G.pInfo->hostnum == VMS_ && G.extra_field &&\n                is_vms_varlen_txt(__G__ G.extra_field,\n                                  G.lrec.extra_field_length))\n                G.VMS_line_state = 0;    /* 0: ready to read line length */\n            else\n                G.VMS_line_state = -1;   /* -1: don't treat as VMS text */\n#endif\n            G.didCRlast = FALSE;         /* no previous buffers written */\n            G.newfile = FALSE;\n        }\n\n#ifdef VMS_TEXT_CONV\n        if (G.VMS_line_state >= 0)\n        {\n            p = rawbuf;\n            q = transbuf;\n            while ((extent)(p-rawbuf) < (extent)size) {\n                switch (G.VMS_line_state) {\n\n                    /* 0: ready to read line length */\n                    case 0:\n                        G.VMS_line_length = 0;\n                        if ((extent)(p-rawbuf) == (extent)size-1) {\n                            /* last char */\n                            G.VMS_line_length = (unsigned)(*p++);\n                            G.VMS_line_state = 1;\n                        } else {\n                            G.VMS_line_length = makeword(p);\n                            p += 2;\n                            G.VMS_line_state = 2;\n                        }\n                        G.VMS_line_pad =\n                               ((G.VMS_line_length & 1) != 0); /* odd */\n                        break;\n\n                    /* 1: read one byte of length, need second */\n                    case 1:\n                        G.VMS_line_length += ((unsigned)(*p++) << 8);\n                        G.VMS_line_state = 2;\n                        break;\n\n                    /* 2: ready to read VMS_line_length chars */\n                    case 2:\n                        {\n                            extent remaining = (extent)size+(rawbuf-p);\n                            extent outroom;\n\n                            if (G.VMS_line_length < remaining) {\n                                remaining = G.VMS_line_length;\n                                G.VMS_line_state = 3;\n                            }\n\n                            outroom = transbuf+(extent)transbufsiz-q;\n                            if (remaining >= outroom) {\n                                remaining -= outroom;\n                                for (;outroom > 0; p++, outroom--)\n                                    *q++ = native(*p);\n#ifdef DLL\n                                if (G.redirect_data) {\n                                    if (writeToMemory(__G__ transbuf,\n                                          (extent)(q-transbuf))) return PK_ERR;\n                                } else\n#endif\n                                if (!uO.cflag && WriteError(transbuf,\n                                    (extent)(q-transbuf), G.outfile))\n                                    return disk_error(__G);\n                                else if (uO.cflag && (*G.message)((zvoid *)&G,\n                                         transbuf, (ulg)(q-transbuf), 0))\n                                    return PK_OK;\n                                q = transbuf;\n                                /* fall through to normal case */\n                            }\n                            G.VMS_line_length -= remaining;\n                            for (;remaining > 0; p++, remaining--)\n                                *q++ = native(*p);\n                        }\n                        break;\n\n                    /* 3: ready to PutNativeEOL */\n                    case 3:\n                        if (q > transbuf+(extent)transbufsiz-lenEOL) {\n#ifdef DLL\n                            if (G.redirect_data) {\n                                if (writeToMemory(__G__ transbuf,\n                                      (extent)(q-transbuf))) return PK_ERR;\n                            } else\n#endif\n                            if (!uO.cflag &&\n                                WriteError(transbuf, (extent)(q-transbuf),\n                                  G.outfile))\n                                return disk_error(__G);\n                            else if (uO.cflag && (*G.message)((zvoid *)&G,\n                                     transbuf, (ulg)(q-transbuf), 0))\n                                return PK_OK;\n                            q = transbuf;\n                        }\n                        PutNativeEOL\n                        G.VMS_line_state = G.VMS_line_pad ? 4 : 0;\n                        break;\n\n                    /* 4: ready to read pad byte */\n                    case 4:\n                        ++p;\n                        G.VMS_line_state = 0;\n                        break;\n                }\n            } /* end while */\n\n        } else\n#endif /* VMS_TEXT_CONV */\n\n    /*-----------------------------------------------------------------------\n        Algorithm:  CR/LF => native; lone CR => native; lone LF => native.\n        This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,\n        stream-oriented files, not record-oriented).\n      -----------------------------------------------------------------------*/\n\n        /* else not VMS text */ {\n            p = rawbuf;\n            if (*p == LF && G.didCRlast)\n                ++p;\n            G.didCRlast = FALSE;\n            for (q = transbuf;  (extent)(p-rawbuf) < (extent)size;  ++p) {\n                if (*p == CR) {           /* lone CR or CR/LF: treat as EOL  */\n                    PutNativeEOL\n                    if ((extent)(p-rawbuf) == (extent)size-1)\n                        /* last char in buffer */\n                        G.didCRlast = TRUE;\n                    else if (p[1] == LF)  /* get rid of accompanying LF */\n                        ++p;\n                } else if (*p == LF)      /* lone LF */\n                    PutNativeEOL\n                else\n#ifndef DOS_FLX_OS2_W32\n                if (*p != CTRLZ)          /* lose all ^Z's */\n#endif\n                    *q++ = native(*p);\n\n#if (defined(SMALL_MEM) || defined(MED_MEM))\n# if (lenEOL == 1)   /* don't check unshrink:  both buffers small but equal */\n                if (!unshrink)\n# endif\n                    /* check for danger of buffer overflow and flush */\n                    if (q > transbuf+(extent)transbufsiz-lenEOL) {\n                        Trace((stderr,\n                          \"p - rawbuf = %u   q-transbuf = %u   size = %lu\\n\",\n                          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));\n                        if (!uO.cflag && WriteError(transbuf,\n                            (extent)(q-transbuf), G.outfile))\n                            return disk_error(__G);\n                        else if (uO.cflag && (*G.message)((zvoid *)&G,\n                                 transbuf, (ulg)(q-transbuf), 0))\n                            return PK_OK;\n                        q = transbuf;\n                        continue;\n                    }\n#endif /* SMALL_MEM || MED_MEM */\n            }\n        }\n\n    /*-----------------------------------------------------------------------\n        Done translating:  write whatever we've got to file (or screen).\n      -----------------------------------------------------------------------*/\n\n        Trace((stderr, \"p - rawbuf = %u   q-transbuf = %u   size = %lu\\n\",\n          (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));\n        if (q > transbuf) {\n#ifdef DLL\n            if (G.redirect_data) {\n                if (writeToMemory(__G__ transbuf, (extent)(q-transbuf)))\n                    return PK_ERR;\n            } else\n#endif\n            if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf),\n                G.outfile))\n                return disk_error(__G);\n            else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,\n                (ulg)(q-transbuf), 0))\n                return PK_OK;\n        }\n    }\n\n    return PK_OK;\n\n} /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */\n\n\n\n\n\n#ifdef VMS_TEXT_CONV\n\n/********************************/\n/* Function is_vms_varlen_txt() */\n/********************************/\n\nstatic int is_vms_varlen_txt(__G__ ef_buf, ef_len)\n    __GDEF\n    uch *ef_buf;        /* buffer containing extra field */\n    unsigned ef_len;    /* total length of extra field */\n{\n    unsigned eb_id;\n    unsigned eb_len;\n    uch *eb_data;\n    unsigned eb_datlen;\n#define VMSREC_C_UNDEF  0\n#define VMSREC_C_VAR    2\n    uch vms_rectype = VMSREC_C_UNDEF;\n /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */\n\n#define VMSPK_ITEMID            0\n#define VMSPK_ITEMLEN           2\n#define VMSPK_ITEMHEADSZ        4\n\n#define VMSATR_C_RECATTR        4\n#define VMS_FABSIG              0x42414656      /* \"VFAB\" */\n/* offsets of interesting fields in VMS fabdef structure */\n#define VMSFAB_B_RFM            31      /* record format byte */\n#define VMSFAB_B_ORG            29      /* file organization byte */\n\n    if (ef_len == 0 || ef_buf == NULL)\n        return FALSE;\n\n    while (ef_len >= EB_HEADSIZE) {\n        eb_id = makeword(EB_ID + ef_buf);\n        eb_len = makeword(EB_LEN + ef_buf);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"is_vms_varlen_txt: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        switch (eb_id) {\n          case EF_PKVMS:\n            /* The PKVMS e.f. raw data part consists of:\n             * a) 4 bytes CRC checksum\n             * b) list of uncompressed variable-length data items\n             * Each data item is introduced by a fixed header\n             *  - 2 bytes data type ID\n             *  - 2 bytes <size> of data\n             *  - <size> bytes of actual attribute data\n             */\n\n            /* get pointer to start of data and its total length */\n            eb_data = ef_buf+(EB_HEADSIZE+4);\n            eb_datlen = eb_len-4;\n\n            /* test the CRC checksum */\n            if (makelong(ef_buf+EB_HEADSIZE) !=\n                crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen))\n            {\n                Info(slide, 1, ((char *)slide,\n                  \"[Warning: CRC error, discarding PKWARE extra field]\\n\"));\n                /* skip over the data analysis code */\n                break;\n            }\n\n            /* scan through the attribute data items */\n            while (eb_datlen > 4)\n            {\n                unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]);\n\n                /* check the item type word */\n                switch (makeword(&eb_data[VMSPK_ITEMID])) {\n                  case VMSATR_C_RECATTR:\n                    /* we have found the (currently only) interesting\n                     * data item */\n                    if (fldsize >= 1) {\n                        vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15;\n                     /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */\n                    }\n                    break;\n                  default:\n                    break;\n                }\n                /* skip to next data item */\n                eb_datlen -= fldsize + VMSPK_ITEMHEADSZ;\n                eb_data += fldsize + VMSPK_ITEMHEADSZ;\n            }\n            break;\n\n          case EF_IZVMS:\n            if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) {\n                if ((eb_data = extract_izvms_block(__G__\n                                                   ef_buf+EB_HEADSIZE, eb_len,\n                                                   &eb_datlen, NULL, 0))\n                    != NULL)\n                {\n                    if (eb_datlen >= VMSFAB_B_RFM+1) {\n                        vms_rectype = eb_data[VMSFAB_B_RFM] & 15;\n                     /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */\n                    }\n                    free(eb_data);\n                }\n            }\n            break;\n\n          default:\n            break;\n        }\n\n        /* Skip this extra field block */\n        ef_buf += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return (vms_rectype == VMSREC_C_VAR);\n\n} /* end function is_vms_varlen_txtfile() */\n\n#endif /* VMS_TEXT_CONV */\n\n\n\n\n/*************************/\n/* Function disk_error() */\n/*************************/\n\nstatic int disk_error(__G)\n    __GDEF\n{\n    /* OK to use slide[] here because this file is finished regardless */\n    Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),\n      FnFilter1(G.filename)));\n\n#ifndef WINDLL\n    fgets(G.answerbuf, sizeof(G.answerbuf), stdin);\n    if (*G.answerbuf == 'y')   /* stop writing to this file */\n        G.disk_full = 1;       /*  (outfile bad?), but new OK */\n    else\n#endif\n        G.disk_full = 2;       /* no:  exit program */\n\n    return PK_DISK;\n\n} /* end function disk_error() */\n\n#endif /* !VMS */\n\n\n\n\n\n/*****************************/\n/* Function UzpMessagePrnt() */\n/*****************************/\n\nint UZ_EXP UzpMessagePrnt(pG, buf, size, flag)\n    zvoid *pG;   /* globals struct:  always passed */\n    uch *buf;    /* preformatted string to be printed */\n    ulg size;    /* length of string (may include nulls) */\n    int flag;    /* flag bits */\n{\n    /* IMPORTANT NOTE:\n     *    The name of the first parameter of UzpMessagePrnt(), which passes\n     *    the \"Uz_Globs\" address, >>> MUST <<< be identical to the string\n     *    expansion of the __G__ macro in the REENTRANT case (see globals.h).\n     *    This name identity is mandatory for the LoadFarString() macro\n     *    (in the SMALL_MEM case) !!!\n     */\n    int error;\n    uch *q=buf, *endbuf=buf+(unsigned)size;\n#ifdef MORE\n    uch *p=buf;\n#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n    int islinefeed = FALSE;\n#endif\n#endif\n    FILE *outfp;\n\n\n/*---------------------------------------------------------------------------\n    These tests are here to allow fine-tuning of UnZip's output messages,\n    but none of them will do anything without setting the appropriate bit\n    in the flag argument of every Info() statement which is to be turned\n    *off*.  That is, all messages are currently turned on for all ports.\n    To turn off *all* messages, use the UzpMessageNull() function instead\n    of this one.\n  ---------------------------------------------------------------------------*/\n\n#if (defined(OS2) && defined(DLL))\n    if (MSG_NO_DLL2(flag))  /* if OS/2 DLL bit is set, do NOT print this msg */\n        return 0;\n#endif\n#ifdef WINDLL\n    if (MSG_NO_WDLL(flag))\n        return 0;\n#endif\n#ifdef WINDLL\n    if (MSG_NO_WGUI(flag))\n        return 0;\n#endif\n/*\n#ifdef ACORN_GUI\n    if (MSG_NO_AGUI(flag))\n        return 0;\n#endif\n */\n#ifdef DLL                 /* don't display message if data is redirected */\n    if (((Uz_Globs *)pG)->redirect_data &&\n        !((Uz_Globs *)pG)->redirect_text)\n        return 0;\n#endif\n\n    if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)\n        outfp = (FILE *)stderr;\n    else\n        outfp = (FILE *)stdout;\n\n#ifdef QUERY_TRNEWLN\n    /* some systems require termination of query prompts with '\\n' to force\n     * immediate display */\n    if (MSG_MNEWLN(flag)) {   /* assumes writable buffer (e.g., slide[]) */\n        *endbuf++ = '\\n';     /*  with room for one more char at end of buf */\n        ++size;               /*  (safe assumption:  only used for four */\n    }                         /*  short queries in extract.c and fileio.c) */\n#endif\n\n    if (MSG_TNEWLN(flag)) {   /* again assumes writable buffer:  fragile... */\n        if ((!size && !((Uz_Globs *)pG)->sol) ||\n            (size && (endbuf[-1] != '\\n')))\n        {\n            *endbuf++ = '\\n';\n            ++size;\n        }\n    }\n\n#ifdef MORE\n# ifdef SCREENSIZE\n    /* room for --More-- and one line of overlap: */\n#  if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n    SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width);\n#  else\n    SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL);\n#  endif\n    ((Uz_Globs *)pG)->height -= 2;\n# else\n    /* room for --More-- and one line of overlap: */\n    ((Uz_Globs *)pG)->height = SCREENLINES - 2;\n#  if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n    ((Uz_Globs *)pG)->width = SCREENWIDTH;\n#  endif\n# endif\n#endif /* MORE */\n\n    if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {\n        /* not at start of line:  want newline */\n#ifdef OS2DLL\n        if (!((Uz_Globs *)pG)->redirect_text) {\n#endif\n            putc('\\n', outfp);\n            fflush(outfp);\n#ifdef MORE\n            if (((Uz_Globs *)pG)->M_flag)\n            {\n#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n                ((Uz_Globs *)pG)->chars = 0;\n#endif\n                ++((Uz_Globs *)pG)->numlines;\n                ++((Uz_Globs *)pG)->lines;\n                if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)\n                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,\n                      LoadFarString(MorePrompt), 1);\n            }\n#endif /* MORE */\n            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&\n                !isatty(1) && isatty(2))\n            {\n                /* error output from testing redirected:  also send to stderr */\n                putc('\\n', stderr);\n                fflush(stderr);\n            }\n#ifdef OS2DLL\n        } else\n           REDIRECTC('\\n');\n#endif\n        ((Uz_Globs *)pG)->sol = TRUE;\n    }\n\n    /* put zipfile name, filename and/or error/warning keywords here */\n\n#ifdef MORE\n    if (((Uz_Globs *)pG)->M_flag\n#ifdef OS2DLL\n         && !((Uz_Globs *)pG)->redirect_text\n#endif\n                                                 )\n    {\n        while (p < endbuf) {\n            if (*p == '\\n') {\n#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n                islinefeed = TRUE;\n            } else if (SCREENLWRAP) {\n                if (*p == '\\r') {\n                    ((Uz_Globs *)pG)->chars = 0;\n                } else {\n#  ifdef TABSIZE\n                    if (*p == '\\t')\n                        ((Uz_Globs *)pG)->chars +=\n                            (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE));\n                    else\n#  endif\n                        ++((Uz_Globs *)pG)->chars;\n\n                    if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width)\n                        islinefeed = TRUE;\n                }\n            }\n            if (islinefeed) {\n                islinefeed = FALSE;\n                ((Uz_Globs *)pG)->chars = 0;\n#endif /* (SCREENWIDTH && SCREEN_LWRAP) */\n                ++((Uz_Globs *)pG)->numlines;\n                ++((Uz_Globs *)pG)->lines;\n                if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)\n                {\n                    if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0)\n                        return error;\n                    fflush(outfp);\n                    ((Uz_Globs *)pG)->sol = TRUE;\n                    q = p + 1;\n                    (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,\n                      LoadFarString(MorePrompt), 1);\n                }\n            }\n            INCSTR(p);\n        } /* end while */\n        size = (ulg)(p - q);   /* remaining text */\n    }\n#endif /* MORE */\n\n    if (size) {\n#ifdef OS2DLL\n        if (!((Uz_Globs *)pG)->redirect_text) {\n#endif\n            if ((error = WriteTxtErr(q, size, outfp)) != 0)\n                return error;\n#ifndef VMS     /* 2005-09-16 SMS.  See note at \"WriteTxtErr()\", above. */\n            fflush(outfp);\n#endif\n            if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&\n                !isatty(1) && isatty(2))\n            {\n                /* error output from testing redirected:  also send to stderr */\n                if ((error = WriteTxtErr(q, size, stderr)) != 0)\n                    return error;\n                fflush(stderr);\n            }\n#ifdef OS2DLL\n        } else {                /* GRR:  this is ugly:  hide with macro */\n            if ((error = REDIRECTPRINT(q, size)) != 0)\n                return error;\n        }\n#endif /* OS2DLL */\n        ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\\n');\n    }\n    return 0;\n\n} /* end function UzpMessagePrnt() */\n\n\n\n\n\n#ifdef DLL\n\n/*****************************/\n/* Function UzpMessageNull() */  /* convenience routine for no output at all */\n/*****************************/\n\nint UZ_EXP UzpMessageNull(pG, buf, size, flag)\n    zvoid *pG;    /* globals struct:  always passed */\n    uch *buf;     /* preformatted string to be printed */\n    ulg size;     /* length of string (may include nulls) */\n    int flag;     /* flag bits */\n{\n    return 0;\n\n} /* end function UzpMessageNull() */\n\n#endif /* DLL */\n\n\n\n\n\n/***********************/\n/* Function UzpInput() */   /* GRR:  this is a placeholder for now */\n/***********************/\n\nint UZ_EXP UzpInput(pG, buf, size, flag)\n    zvoid *pG;    /* globals struct:  always passed */\n    uch *buf;     /* preformatted string to be printed */\n    int *size;    /* (address of) size of buf and of returned string */\n    int flag;     /* flag bits (bit 0: no echo) */\n{\n    /* tell picky compilers to shut up about \"unused variable\" warnings */\n    pG = pG; buf = buf; flag = flag;\n\n    *size = 0;\n    return 0;\n\n} /* end function UzpInput() */\n\n\n\n\n\n#if (!defined(WINDLL) && !defined(MACOS))\n\n/***************************/\n/* Function UzpMorePause() */\n/***************************/\n\nvoid UZ_EXP UzpMorePause(pG, prompt, flag)\n    zvoid *pG;            /* globals struct:  always passed */\n    ZCONST char *prompt;  /* \"--More--\" prompt */\n    int flag;             /* 0 = any char OK; 1 = accept only '\\n', ' ', q */\n{\n    uch c;\n\n/*---------------------------------------------------------------------------\n    Print a prompt and wait for the user to press a key, then erase prompt\n    if possible.\n  ---------------------------------------------------------------------------*/\n\n    if (!((Uz_Globs *)pG)->sol)\n        fprintf(stderr, \"\\n\");\n    /* numlines may or may not be used: */\n    fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);\n    fflush(stderr);\n    if (flag & 1) {\n        do {\n            c = (uch)FGETCH(0);\n        } while (\n#ifdef THEOS\n                 c != 17 &&     /* standard QUIT key */\n#endif\n                 c != '\\r' && c != '\\n' && c != ' ' && c != 'q' && c != 'Q');\n    } else\n        c = (uch)FGETCH(0);\n\n    /* newline was not echoed, so cover up prompt line */\n    fprintf(stderr, LoadFarString(HidePrompt));\n    fflush(stderr);\n\n    if (\n#ifdef THEOS\n        (c == 17) ||            /* standard QUIT key */\n#endif\n        (ToLower(c) == 'q')) {\n        DESTROYGLOBALS();\n        EXIT(PK_COOL);\n    }\n\n    ((Uz_Globs *)pG)->sol = TRUE;\n\n#ifdef MORE\n    /* space for another screen, enter for another line. */\n    if ((flag & 1) && c == ' ')\n        ((Uz_Globs *)pG)->lines = 0;\n#endif /* MORE */\n\n} /* end function UzpMorePause() */\n\n#endif /* !WINDLL && !MACOS */\n\n\n\n\n#ifndef WINDLL\n\n/**************************/\n/* Function UzpPassword() */\n/**************************/\n\nint UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)\n    zvoid *pG;         /* pointer to UnZip's internal global vars */\n    int *rcnt;         /* retry counter */\n    char *pwbuf;       /* buffer for password */\n    int size;          /* size of password buffer */\n    ZCONST char *zfn;  /* name of zip archive */\n    ZCONST char *efn;  /* name of archive entry being processed */\n{\n#if CRYPT\n    int r = IZ_PW_ENTERED;\n    char *m;\n    char *prompt;\n\n#ifndef REENTRANT\n    /* tell picky compilers to shut up about \"unused variable\" warnings */\n    pG = pG;\n#endif\n\n    if (*rcnt == 0) {           /* First call for current entry */\n        *rcnt = 2;\n        if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {\n            sprintf(prompt, LoadFarString(PasswPrompt),\n                    FnFilter1(zfn), FnFilter2(efn));\n            m = prompt;\n        } else\n            m = (char *)LoadFarString(PasswPrompt2);\n    } else {                    /* Retry call, previous password was wrong */\n        (*rcnt)--;\n        prompt = NULL;\n        m = (char *)LoadFarString(PasswRetry);\n    }\n\n    m = getp(__G__ m, pwbuf, size);\n    if (prompt != (char *)NULL) {\n        free(prompt);\n    }\n    if (m == (char *)NULL) {\n        r = IZ_PW_ERROR;\n    }\n    else if (*pwbuf == '\\0') {\n        r = IZ_PW_CANCELALL;\n    }\n    return r;\n\n#else /* !CRYPT */\n    /* tell picky compilers to shut up about \"unused variable\" warnings */\n    pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;\n\n    return IZ_PW_ERROR;  /* internal error; function should never get called */\n#endif /* ?CRYPT */\n\n} /* end function UzpPassword() */\n\n\n\n\n\n/**********************/\n/* Function handler() */\n/**********************/\n\nvoid handler(signal)   /* upon interrupt, turn on echo and exit cleanly */\n    int signal;\n{\n    GETGLOBALS();\n\n#if !(defined(SIGBUS) || defined(SIGSEGV))      /* add a newline if not at */\n    (*G.message)((zvoid *)&G, slide, 0L, 0x41); /*  start of line (to stderr; */\n#endif                                          /*  slide[] should be safe) */\n\n    echon();\n\n#ifdef SIGBUS\n    if (signal == SIGBUS) {\n        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),\n          \"bus error\"));\n        DESTROYGLOBALS();\n        EXIT(PK_BADERR);\n    }\n#endif /* SIGBUS */\n\n#ifdef SIGILL\n    if (signal == SIGILL) {\n        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),\n          \"illegal instruction\"));\n        DESTROYGLOBALS();\n        EXIT(PK_BADERR);\n    }\n#endif /* SIGILL */\n\n#ifdef SIGSEGV\n    if (signal == SIGSEGV) {\n        Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),\n          \"segmentation violation\"));\n        DESTROYGLOBALS();\n        EXIT(PK_BADERR);\n    }\n#endif /* SIGSEGV */\n\n    /* probably ctrl-C */\n    DESTROYGLOBALS();\n#if defined(AMIGA) && defined(__SASC)\n    _abort();\n#endif\n    EXIT(IZ_CTRLC);       /* was EXIT(0), then EXIT(PK_ERR) */\n}\n\n#endif /* !WINDLL */\n\n\n\n\n#if (!defined(VMS) && !defined(CMS_MVS))\n#if (!defined(OS2) || defined(TIMESTAMP))\n\n#if (!defined(HAVE_MKTIME) || defined(WIN32))\n/* also used in amiga/filedate.c and win32/win32.c */\nZCONST ush ydays[] =\n    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };\n#endif\n\n/*******************************/\n/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */\n/*******************************/\n\ntime_t dos_to_unix_time(dosdatetime)\n    ulg dosdatetime;\n{\n    time_t m_time;\n\n#ifdef HAVE_MKTIME\n\n    ZCONST time_t now = time(NULL);\n    struct tm *tm;\n#   define YRBASE  1900\n\n    tm = localtime(&now);\n    tm->tm_isdst = -1;          /* let mktime determine if DST is in effect */\n\n    /* dissect date */\n    tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);\n    tm->tm_mon  = ((int)(dosdatetime >> 21) & 0x0f) - 1;\n    tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);\n\n    /* dissect time */\n    tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;\n    tm->tm_min  = (int)((unsigned)dosdatetime >> 5) & 0x3f;\n    tm->tm_sec  = (int)((unsigned)dosdatetime << 1) & 0x3e;\n\n    m_time = mktime(tm);\n    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */\n    TTrace((stderr, \"  final m_time  =       %lu\\n\", (ulg)m_time));\n\n#else /* !HAVE_MKTIME */\n\n    int yr, mo, dy, hh, mm, ss;\n#ifdef TOPS20\n#   define YRBASE  1900\n    struct tmx *tmx;\n    char temp[20];\n#else /* !TOPS20 */\n#   define YRBASE  1970\n    int leap;\n    unsigned days;\n    struct tm *tm;\n#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))\n#ifdef WIN32\n    TIME_ZONE_INFORMATION tzinfo;\n    DWORD res;\n#else /* ! WIN32 */\n#ifndef BSD4_4   /* GRR:  change to !defined(MODERN) ? */\n#if (defined(BSD) || defined(MTS) || defined(__GO32__))\n    struct timeb tbp;\n#else /* !(BSD || MTS || __GO32__) */\n#ifdef DECLARE_TIMEZONE\n    extern time_t timezone;\n#endif\n#endif /* ?(BSD || MTS || __GO32__) */\n#endif /* !BSD4_4 */\n#endif /* ?WIN32 */\n#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */\n#endif /* ?TOPS20 */\n\n\n    /* dissect date */\n    yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);\n    mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;\n    dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;\n\n    /* dissect time */\n    hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;\n    mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;\n    ss = (int)((unsigned)dosdatetime & 0x1f) * 2;\n\n#ifdef TOPS20\n    tmx = (struct tmx *)malloc(sizeof(struct tmx));\n    sprintf (temp, \"%02d/%02d/%02d %02d:%02d:%02d\", mo+1, dy+1, yr, hh, mm, ss);\n    time_parse(temp, tmx, (char *)0);\n    m_time = time_make(tmx);\n    free(tmx);\n\n#else /* !TOPS20 */\n\n/*---------------------------------------------------------------------------\n    Calculate the number of seconds since the epoch, usually 1 January 1970.\n  ---------------------------------------------------------------------------*/\n\n    /* leap = # of leap yrs from YRBASE up to but not including current year */\n    leap = ((yr + YRBASE - 1) / 4);   /* leap year base factor */\n\n    /* calculate days from BASE to this year and add expired days this year */\n    days = (yr * 365) + (leap - 492) + ydays[mo];\n\n    /* if year is a leap year and month is after February, add another day */\n    if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))\n        ++days;                 /* OK through 2199 */\n\n    /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */\n    m_time = (time_t)((unsigned long)(days + dy) * 86400L +\n                      (unsigned long)hh * 3600L +\n                      (unsigned long)(mm * 60 + ss));\n      /* - 1;   MS-DOS times always rounded up to nearest even second */\n    TTrace((stderr, \"dos_to_unix_time:\\n\"));\n    TTrace((stderr, \"  m_time before timezone = %lu\\n\", (ulg)m_time));\n\n/*---------------------------------------------------------------------------\n    Adjust for local standard timezone offset.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))\n#ifdef WIN32\n    /* account for timezone differences */\n    res = GetTimeZoneInformation(&tzinfo);\n    if (res != TIME_ZONE_ID_INVALID)\n    {\n    m_time += 60*(tzinfo.Bias);\n#else /* !WIN32 */\n#if (defined(BSD) || defined(MTS) || defined(__GO32__))\n#ifdef BSD4_4\n    if ( (dosdatetime >= DOSTIME_2038_01_18) &&\n         (m_time < (time_t)0x70000000L) )\n        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */\n    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */\n        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */\n    if ((tm = localtime(&m_time)) != (struct tm *)NULL)\n        m_time -= tm->tm_gmtoff;                /* sec. EAST of GMT: subtr. */\n#else /* !(BSD4_4 */\n    ftime(&tbp);                                /* get `timezone' */\n    m_time += tbp.timezone * 60L;               /* seconds WEST of GMT:  add */\n#endif /* ?(BSD4_4 || __EMX__) */\n#else /* !(BSD || MTS || __GO32__) */\n    /* tzset was already called at start of process_zipfiles() */\n    /* tzset(); */              /* set `timezone' variable */\n#ifndef __BEOS__                /* BeOS DR8 has no timezones... */\n    m_time += timezone;         /* seconds WEST of GMT:  add */\n#endif\n#endif /* ?(BSD || MTS || __GO32__) */\n#endif /* ?WIN32 */\n    TTrace((stderr, \"  m_time after timezone =  %lu\\n\", (ulg)m_time));\n\n/*---------------------------------------------------------------------------\n    Adjust for local daylight savings (summer) time.\n  ---------------------------------------------------------------------------*/\n\n#ifndef BSD4_4  /* (DST already added to tm_gmtoff, so skip tm_isdst) */\n    if ( (dosdatetime >= DOSTIME_2038_01_18) &&\n         (m_time < (time_t)0x70000000L) )\n        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */\n    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */\n        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */\n    TIMET_TO_NATIVE(m_time)     /* NOP unless MSC 7.0 or Macintosh */\n    if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)\n#ifdef WIN32\n        m_time += 60L * tzinfo.DaylightBias;    /* adjust with DST bias */\n    else\n        m_time += 60L * tzinfo.StandardBias;    /* add StdBias (normally 0) */\n#else\n        m_time -= 60L * 60L;    /* adjust for daylight savings time */\n#endif\n    NATIVE_TO_TIMET(m_time)     /* NOP unless MSC 7.0 or Macintosh */\n    TTrace((stderr, \"  m_time after DST =       %lu\\n\", (ulg)m_time));\n#endif /* !BSD4_4 */\n#ifdef WIN32\n    }\n#endif\n#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */\n#endif /* ?TOPS20 */\n\n#endif /* ?HAVE_MKTIME */\n\n    if ( (dosdatetime >= DOSTIME_2038_01_18) &&\n         (m_time < (time_t)0x70000000L) )\n        m_time = U_TIME_T_MAX;  /* saturate in case of (unsigned) overflow */\n    if (m_time < (time_t)0L)    /* a converted DOS time cannot be negative */\n        m_time = S_TIME_T_MAX;  /*  -> saturate at max signed time_t value */\n\n    return m_time;\n\n} /* end function dos_to_unix_time() */\n\n#endif /* !OS2 || TIMESTAMP */\n#endif /* !VMS && !CMS_MVS */\n\n\n\n#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))\n\n/******************************/\n/* Function check_for_newer() */  /* used for overwriting/freshening/updating */\n/******************************/\n\nint check_for_newer(__G__ filename)  /* return 1 if existing file is newer */\n    __GDEF                           /*  or equal; 0 if older; -1 if doesn't */\n    char *filename;                  /*  exist yet */\n{\n    time_t existing, archive;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n#ifdef AOS_VS\n    long    dyy, dmm, ddd, dhh, dmin, dss;\n\n\n    dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;\n    dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;\n    ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;\n    dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;\n    dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;\n    dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;\n\n    /* under AOS/VS, file times can only be set at creation time,\n     * with the info in a special DG format.  Make sure we can create\n     * it here - we delete it later & re-create it, whether or not\n     * it exists now.\n     */\n    if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |\n        (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))\n        return DOES_NOT_EXIST;\n#endif /* AOS_VS */\n\n    Trace((stderr, \"check_for_newer:  doing stat(%s)\\n\", FnFilter1(filename)));\n    if (SSTAT(filename, &G.statbuf)) {\n        Trace((stderr,\n          \"check_for_newer:  stat(%s) returns %d:  file does not exist\\n\",\n          FnFilter1(filename), SSTAT(filename, &G.statbuf)));\n#ifdef SYMLINKS\n        Trace((stderr, \"check_for_newer:  doing lstat(%s)\\n\",\n          FnFilter1(filename)));\n        /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */\n        if (lstat(filename, &G.statbuf) == 0) {\n            Trace((stderr,\n              \"check_for_newer:  lstat(%s) returns 0:  symlink does exist\\n\",\n              FnFilter1(filename)));\n            if (QCOND2 && !IS_OVERWRT_ALL)\n                Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),\n                  FnFilter1(filename), \" with no real file\"));\n            return EXISTS_AND_OLDER;   /* symlink dates are meaningless */\n        }\n#endif /* SYMLINKS */\n        return DOES_NOT_EXIST;\n    }\n    Trace((stderr, \"check_for_newer:  stat(%s) returns 0:  file exists\\n\",\n      FnFilter1(filename)));\n\n#ifdef SYMLINKS\n    /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */\n    if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {\n        Trace((stderr, \"check_for_newer:  %s is a symbolic link\\n\",\n          FnFilter1(filename)));\n        if (QCOND2 && !IS_OVERWRT_ALL)\n            Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),\n              FnFilter1(filename), \"\"));\n        return EXISTS_AND_OLDER;   /* symlink dates are meaningless */\n    }\n#endif /* SYMLINKS */\n\n    NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */\n\n#ifdef USE_EF_UT_TIME\n    /* The `Unix extra field mtime' should be used for comparison with the\n     * time stamp of the existing file >>>ONLY<<< when the EF info is also\n     * used to set the modification time of the extracted file.\n     */\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n         & EB_UT_FL_MTIME))\n    {\n        TTrace((stderr, \"check_for_newer:  using Unix extra field mtime\\n\"));\n        existing = G.statbuf.st_mtime;\n        archive  = z_utime.mtime;\n    } else {\n        /* round up existing filetime to nearest 2 seconds for comparison,\n         * but saturate in case of arithmetic overflow\n         */\n        existing = ((G.statbuf.st_mtime & 1) &&\n                    (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?\n                   G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;\n        archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n#else /* !USE_EF_UT_TIME */\n    /* round up existing filetime to nearest 2 seconds for comparison,\n     * but saturate in case of arithmetic overflow\n     */\n    existing = ((G.statbuf.st_mtime & 1) &&\n                (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?\n               G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;\n    archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n#endif /* ?USE_EF_UT_TIME */\n\n    TTrace((stderr, \"check_for_newer:  existing %lu, archive %lu, e-a %ld\\n\",\n      (ulg)existing, (ulg)archive, (long)(existing-archive)));\n\n    return (existing >= archive);\n\n} /* end function check_for_newer() */\n\n#endif /* !VMS && !OS2 && !CMS_MVS */\n\n\n\n\n\n/************************/\n/* Function do_string() */\n/************************/\n\nint do_string(__G__ length, option)   /* return PK-type error code */\n    __GDEF\n    unsigned int length;        /* without prototype, ush converted to this */\n    int option;\n{\n    unsigned comment_bytes_left;\n    unsigned int block_len;\n    int error=PK_OK;\n#ifdef AMIGA\n    char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */\n#endif\n\n\n/*---------------------------------------------------------------------------\n    This function processes arbitrary-length (well, usually) strings.  Four\n    major options are allowed:  SKIP, wherein the string is skipped (pretty\n    logical, eh?); DISPLAY, wherein the string is printed to standard output\n    after undergoing any necessary or unnecessary character conversions;\n    DS_FN, wherein the string is put into the filename[] array after under-\n    going appropriate conversions (including case-conversion, if that is\n    indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD,\n    wherein the `string' is assumed to be an extra field and is copied to\n    the (freshly malloced) buffer G.extra_field.  The third option should\n    be OK since filename is dimensioned at 1025, but we check anyway.\n\n    The string, by the way, is assumed to start at the current file-pointer\n    position; its length is given by 'length'.  So start off by checking the\n    length of the string:  if zero, we're already done.\n  ---------------------------------------------------------------------------*/\n\n    if (!length)\n        return PK_COOL;\n\n    switch (option) {\n\n#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))\n    /*\n     * Special case: See if the comment begins with an autorun command line.\n     * Save that and display (or skip) the remainder.\n     */\n\n    case CHECK_AUTORUN:\n    case CHECK_AUTORUN_Q:\n        comment_bytes_left = length;\n        if (length >= 10)\n        {\n            block_len = readbuf(__G__ (char *)G.outbuf, 10);\n            if (block_len == 0)\n                return PK_EOF;\n            comment_bytes_left -= block_len;\n            G.outbuf[block_len] = '\\0';\n            if (!strcmp((char *)G.outbuf, \"$AUTORUN$>\")) {\n                char *eol;\n                length -= 10;\n                block_len = readbuf(__G__ G.autorun_command,\n                                    MIN(length, sizeof(G.autorun_command)-1));\n                if (block_len == 0)\n                    return PK_EOF;\n                comment_bytes_left -= block_len;\n                G.autorun_command[block_len] = '\\0';\n                A_TO_N(G.autorun_command);\n                eol = strchr(G.autorun_command, '\\n');\n                if (!eol)\n                    eol = G.autorun_command + strlen(G.autorun_command) - 1;\n                length -= eol + 1 - G.autorun_command;\n                while (eol >= G.autorun_command && isspace(*eol))\n                    *eol-- = '\\0';\n#if (defined(WIN32) && !defined(_WIN32_WCE))\n                /* Win9x console always uses OEM character coding, and\n                   WinNT console is set to OEM charset by default, too */\n                INTERN_TO_OEM(G.autorun_command, G.autorun_command);\n#endif /* (WIN32 && !_WIN32_WCE) */\n            }\n        }\n        if (option == CHECK_AUTORUN_Q)  /* don't display the remainder */\n            length = 0;\n        /* seek to beginning of remaining part of comment -- rewind if */\n        /* displaying entire comment, or skip to end if discarding it  */\n        seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +\n                  (G.inptr - G.inbuf) + comment_bytes_left - length);\n        if (!length)\n            break;\n        /*  FALL THROUGH...  */\n#endif /* SFX && CHEAP_SFX_AUTORUN */\n\n    /*\n     * First normal case:  print string on standard output.  First set loop\n     * variables, then loop through the comment in chunks of OUTBUFSIZ bytes,\n     * converting formats and printing as we go.  The second half of the\n     * loop conditional was added because the file might be truncated, in\n     * which case comment_bytes_left will remain at some non-zero value for\n     * all time.  outbuf and slide are used as scratch buffers because they\n     * are available (we should be either before or in between any file pro-\n     * cessing).\n     */\n\n    case DISPLAY:\n    case DISPL_8:\n        comment_bytes_left = length;\n        block_len = OUTBUFSIZ;       /* for the while statement, first time */\n        while (comment_bytes_left > 0 && block_len > 0) {\n            register uch *p = G.outbuf;\n            register uch *q = G.outbuf;\n\n            if ((block_len = readbuf(__G__ (char *)G.outbuf,\n                   MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0)\n                return PK_EOF;\n            comment_bytes_left -= block_len;\n\n            /* this is why we allocated an extra byte for outbuf:  terminate\n             *  with zero (ASCIIZ) */\n            G.outbuf[block_len] = '\\0';\n\n            /* remove all ASCII carriage returns from comment before printing\n             * (since used before A_TO_N(), check for CR instead of '\\r')\n             */\n            while (*p) {\n                while (*p == CR)\n                    ++p;\n                *q++ = *p++;\n            }\n            /* could check whether (p - outbuf) == block_len here */\n            *q = '\\0';\n\n            if (option == DISPL_8) {\n                /* translate the text coded in the entry's host-dependent\n                   \"extended ASCII\" charset into the compiler's (system's)\n                   internal text code page */\n                Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,\n                                    G.pInfo->hostver, G.pInfo->HasUxAtt,\n                                    FALSE);\n#ifdef WINDLL\n                /* translate to ANSI (RTL internal codepage may be OEM) */\n                INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);\n#else /* !WINDLL */\n#if (defined(WIN32) && !defined(_WIN32_WCE))\n                /* Win9x console always uses OEM character coding, and\n                   WinNT console is set to OEM charset by default, too */\n                INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);\n#endif /* (WIN32 && !_WIN32_WCE) */\n#endif /* ?WINDLL */\n            } else {\n                A_TO_N(G.outbuf);   /* translate string to native */\n            }\n\n#ifdef WINDLL\n            /* ran out of local mem -- had to cheat */\n            win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf),\n                        (char *)G.outbuf);\n            win_fprintf((zvoid *)&G, stdout, 2, (char *)\"\\n\\n\");\n#else /* !WINDLL */\n#ifdef NOANSIFILT       /* GRR:  can ANSI be used with EBCDIC? */\n            (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);\n#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */\n            p = G.outbuf - 1;\n            q = slide;\n            while (*++p) {\n                int pause = FALSE;\n\n                if (*p == 0x1B) {          /* ASCII escape char */\n                    *q++ = '^';\n                    *q++ = '[';\n                } else if (*p == 0x13) {   /* ASCII ^S (pause) */\n                    pause = TRUE;\n                    if (p[1] == LF)        /* ASCII LF */\n                        *q++ = *++p;\n                    else if (p[1] == CR && p[2] == LF) {  /* ASCII CR LF */\n                        *q++ = *++p;\n                        *q++ = *++p;\n                    }\n                } else\n                    *q++ = *p;\n                if ((unsigned)(q-slide) > WSIZE-3 || pause) {   /* flush */\n                    (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);\n                    q = slide;\n                    if (pause && G.extract_flag) /* don't pause for list/test */\n                        (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);\n                }\n            }\n            (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);\n#endif /* ?NOANSIFILT */\n#endif /* ?WINDLL */\n        }\n        /* add '\\n' if not at start of line */\n        (*G.message)((zvoid *)&G, slide, 0L, 0x40);\n        break;\n\n    /*\n     * Second case:  read string into filename[] array.  The filename should\n     * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,\n     * just to be sure.\n     */\n\n    case DS_FN:\n    case DS_FN_L:\n#ifdef UNICODE_SUPPORT\n        /* get the whole filename as need it for Unicode checksum */\n        if (G.fnfull_bufsize <= length) {\n            extent fnbufsiz = FILNAMSIZ;\n\n            if (fnbufsiz <= length)\n                fnbufsiz = length + 1;\n            if (G.filename_full)\n                free(G.filename_full);\n            G.filename_full = malloc(fnbufsiz);\n            if (G.filename_full == NULL)\n                return PK_MEM;\n            G.fnfull_bufsize = fnbufsiz;\n        }\n        if (readbuf(__G__ G.filename_full, length) == 0)\n            return PK_EOF;\n        G.filename_full[length] = '\\0';      /* terminate w/zero:  ASCIIZ */\n\n        /* if needed, chop off end so standard filename is a valid length */\n        if (length >= FILNAMSIZ) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(FilenameTooLongTrunc)));\n            error = PK_WARN;\n            length = FILNAMSIZ - 1;\n        }\n        /* no excess size */\n        block_len = 0;\n        strncpy(G.filename, G.filename_full, length);\n        G.filename[length] = '\\0';      /* terminate w/zero:  ASCIIZ */\n#else /* !UNICODE_SUPPORT */\n        if (length >= FILNAMSIZ) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(FilenameTooLongTrunc)));\n            error = PK_WARN;\n            /* remember excess length in block_len */\n            block_len = length - (FILNAMSIZ - 1);\n            length = FILNAMSIZ - 1;\n        } else\n            /* no excess size */\n            block_len = 0;\n        if (readbuf(__G__ G.filename, length) == 0)\n            return PK_EOF;\n        G.filename[length] = '\\0';      /* terminate w/zero:  ASCIIZ */\n#endif /* ?UNICODE_SUPPORT */\n\n        /* translate the Zip entry filename coded in host-dependent \"extended\n           ASCII\" into the compiler's (system's) internal text code page */\n        Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver,\n                            G.pInfo->HasUxAtt, (option == DS_FN_L));\n\n        if (G.pInfo->lcflag)      /* replace with lowercase filename */\n            STRLOWER(G.filename, G.filename);\n\n        if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') {\n            char *p = G.filename+8;\n            while (*p++)\n                p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */\n        }\n\n        if (!block_len)         /* no overflow, we're done here */\n            break;\n\n        /*\n         * We truncated the filename, so print what's left and then fall\n         * through to the SKIP routine.\n         */\n        Info(slide, 0x401, ((char *)slide, \"[ %s ]\\n\", FnFilter1(G.filename)));\n        length = block_len;     /* SKIP the excess bytes... */\n        /*  FALL THROUGH...  */\n\n    /*\n     * Third case:  skip string, adjusting readbuf's internal variables\n     * as necessary (and possibly skipping to and reading a new block of\n     * data).\n     */\n\n    case SKIP:\n        /* cur_zipfile_bufstart already takes account of extra_bytes, so don't\n         * correct for it twice: */\n        seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +\n                  (G.inptr-G.inbuf) + length);\n        break;\n\n    /*\n     * Fourth case:  assume we're at the start of an \"extra field\"; malloc\n     * storage for it and read data into the allocated space.\n     */\n\n    case EXTRA_FIELD:\n        if (G.extra_field != (uch *)NULL)\n            free(G.extra_field);\n        if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) {\n            Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),\n              length));\n            /* cur_zipfile_bufstart already takes account of extra_bytes,\n             * so don't correct for it twice: */\n            seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +\n                      (G.inptr-G.inbuf) + length);\n        } else {\n            if (readbuf(__G__ (char *)G.extra_field, length) == 0)\n                return PK_EOF;\n            /* Looks like here is where extra fields are read */\n            getZip64Data(__G__ G.extra_field, length);\n#ifdef UNICODE_SUPPORT\n            G.unipath_filename = NULL;\n            if (G.UzO.U_flag < 2) {\n              /* check if GPB11 (General Purpuse Bit 11) is set indicating\n                 the standard path and comment are UTF-8 */\n              if (G.pInfo->GPFIsUTF8) {\n                /* if GPB11 set then filename_full is untruncated UTF-8 */\n                G.unipath_filename = G.filename_full;\n              } else {\n                /* Get the Unicode fields if exist */\n                getUnicodeData(__G__ G.extra_field, length);\n                if (G.unipath_filename && strlen(G.unipath_filename) == 0) {\n                  /* the standard filename field is UTF-8 */\n                  free(G.unipath_filename);\n                  G.unipath_filename = G.filename_full;\n                }\n              }\n              if (G.unipath_filename) {\n# ifdef UTF8_MAYBE_NATIVE\n                if (G.native_is_utf8\n#  ifdef UNICODE_WCHAR\n                    && (!G.unicode_escape_all)\n#  endif\n                   ) {\n                  strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1);\n                  /* make sure filename is short enough */\n                  if (strlen(G.unipath_filename) >= FILNAMSIZ) {\n                    G.filename[FILNAMSIZ - 1] = '\\0';\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(UFilenameTooLongTrunc)));\n                    error = PK_WARN;\n                  }\n                }\n#  ifdef UNICODE_WCHAR\n                else\n#  endif\n# endif /* UTF8_MAYBE_NATIVE */\n# ifdef UNICODE_WCHAR\n                {\n                  char *fn;\n\n                  /* convert UTF-8 to local character set */\n                  fn = utf8_to_local_string(G.unipath_filename,\n                                            G.unicode_escape_all);\n                  /* make sure filename is short enough */\n                  if (strlen(fn) >= FILNAMSIZ) {\n                    fn[FILNAMSIZ - 1] = '\\0';\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(UFilenameTooLongTrunc)));\n                    error = PK_WARN;\n                  }\n                  /* replace filename with converted UTF-8 */\n                  strcpy(G.filename, fn);\n                  free(fn);\n                }\n# endif /* UNICODE_WCHAR */\n                if (G.unipath_filename != G.filename_full)\n                  free(G.unipath_filename);\n                G.unipath_filename = NULL;\n              }\n            }\n#endif /* UNICODE_SUPPORT */\n        }\n        break;\n\n#ifdef AMIGA\n    /*\n     * Fifth case, for the Amiga only:  take the comment that would ordinarily\n     * be skipped over, and turn it into a 79 character string that will be\n     * attached to the file as a \"filenote\" after it is extracted.\n     */\n\n    case FILENOTE:\n        if ((block_len = readbuf(__G__ tmp_fnote, (unsigned)\n                                 MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0)\n            return PK_EOF;\n        if ((length -= block_len) > 0)  /* treat remainder as in case SKIP: */\n            seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes\n                      + (G.inptr - G.inbuf) + length);\n        /* convert multi-line text into single line with no ctl-chars: */\n        tmp_fnote[block_len] = '\\0';\n        while ((short int) --block_len >= 0)\n            if ((unsigned) tmp_fnote[block_len] < ' ')\n                if (tmp_fnote[block_len+1] == ' ')     /* no excess */\n                    strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1);\n                else\n                    tmp_fnote[block_len] = ' ';\n        tmp_fnote[AMIGA_FILENOTELEN - 1] = '\\0';\n        if (G.filenotes[G.filenote_slot])\n            free(G.filenotes[G.filenote_slot]);     /* should not happen */\n        G.filenotes[G.filenote_slot] = NULL;\n        if (tmp_fnote[0]) {\n            if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))\n                return PK_MEM;\n            strcpy(G.filenotes[G.filenote_slot], tmp_fnote);\n        }\n        break;\n#endif /* AMIGA */\n\n    } /* end switch (option) */\n\n    return error;\n\n} /* end function do_string() */\n\n\n\n\n\n/***********************/\n/* Function makeword() */\n/***********************/\n\nush makeword(b)\n    ZCONST uch *b;\n{\n    /*\n     * Convert Intel style 'short' integer to non-Intel non-16-bit\n     * host format.  This routine also takes care of byte-ordering.\n     */\n    return (ush)((b[1] << 8) | b[0]);\n}\n\n\n\n\n\n/***********************/\n/* Function makelong() */\n/***********************/\n\nulg makelong(sig)\n    ZCONST uch *sig;\n{\n    /*\n     * Convert intel style 'long' variable to non-Intel non-16-bit\n     * host format.  This routine also takes care of byte-ordering.\n     */\n    return (((ulg)sig[3]) << 24)\n         + (((ulg)sig[2]) << 16)\n         + (ulg)((((unsigned)sig[1]) << 8)\n               + ((unsigned)sig[0]));\n}\n\n\n\n\n\n/************************/\n/* Function makeint64() */\n/************************/\n\nzusz_t makeint64(sig)\n    ZCONST uch *sig;\n{\n#ifdef LARGE_FILE_SUPPORT\n    /*\n     * Convert intel style 'int64' variable to non-Intel non-16-bit\n     * host format.  This routine also takes care of byte-ordering.\n     */\n    return (((zusz_t)sig[7]) << 56)\n        + (((zusz_t)sig[6]) << 48)\n        + (((zusz_t)sig[4]) << 32)\n        + (zusz_t)((((ulg)sig[3]) << 24)\n                 + (((ulg)sig[2]) << 16)\n                 + (((unsigned)sig[1]) << 8)\n                 + (sig[0]));\n\n#else /* !LARGE_FILE_SUPPORT */\n\n    if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0)\n        return (zusz_t)0xffffffffL;\n    else\n        return (zusz_t)((((ulg)sig[3]) << 24)\n                      + (((ulg)sig[2]) << 16)\n                      + (((unsigned)sig[1]) << 8)\n                      + (sig[0]));\n\n#endif /* ?LARGE_FILE_SUPPORT */\n}\n\n\n\n\n\n/*********************/\n/* Function fzofft() */\n/*********************/\n\n/* Format a zoff_t value in a cylindrical buffer set. */\nchar *fzofft(__G__ val, pre, post)\n    __GDEF\n    zoff_t val;\n    ZCONST char *pre;\n    ZCONST char *post;\n{\n    /* Storage cylinder. (now in globals.h) */\n    /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/\n    /*static int fzofft_index = 0;*/\n\n    /* Temporary format string storage. */\n    char fmt[16];\n\n    /* Assemble the format string. */\n    fmt[0] = '%';\n    fmt[1] = '\\0';             /* Start after initial \"%\". */\n    if (pre == FZOFFT_HEX_WID)  /* Special hex width. */\n    {\n        strcat(fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex \".width\". */\n    {\n        strcat(fmt, \".\");\n        strcat(fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre != NULL)       /* Caller's prefix (width). */\n    {\n        strcat(fmt, pre);\n    }\n\n    strcat(fmt, FZOFFT_FMT);   /* Long or long-long or whatever. */\n\n    if (post == NULL)\n        strcat(fmt, \"d\");      /* Default radix = decimal. */\n    else\n        strcat(fmt, post);     /* Caller's radix. */\n\n    /* Advance the cylinder. */\n    G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM;\n\n    /* Write into the current chamber. */\n    sprintf(G.fzofft_buf[G.fzofft_index], fmt, val);\n\n    /* Return a pointer to this chamber. */\n    return G.fzofft_buf[G.fzofft_index];\n}\n\n\n\n\n#if CRYPT\n\n#ifdef NEED_STR2ISO\n/**********************/\n/* Function str2iso() */\n/**********************/\n\nchar *str2iso(dst, src)\n    char *dst;                          /* destination buffer */\n    register ZCONST char *src;          /* source string */\n{\n#ifdef INTERN_TO_ISO\n    INTERN_TO_ISO(src, dst);\n#else\n    register uch c;\n    register char *dstp = dst;\n\n    do {\n        c = (uch)foreign(*src++);\n        *dstp++ = (char)ASCII2ISO(c);\n    } while (c != '\\0');\n#endif\n\n    return dst;\n}\n#endif /* NEED_STR2ISO */\n\n\n#ifdef NEED_STR2OEM\n/**********************/\n/* Function str2oem() */\n/**********************/\n\nchar *str2oem(dst, src)\n    char *dst;                          /* destination buffer */\n    register ZCONST char *src;          /* source string */\n{\n#ifdef INTERN_TO_OEM\n    INTERN_TO_OEM(src, dst);\n#else\n    register uch c;\n    register char *dstp = dst;\n\n    do {\n        c = (uch)foreign(*src++);\n        *dstp++ = (char)ASCII2OEM(c);\n    } while (c != '\\0');\n#endif\n\n    return dst;\n}\n#endif /* NEED_STR2OEM */\n\n#endif /* CRYPT */\n\n\n#ifdef ZMEM  /* memset/memcmp/memcpy for systems without either them or */\n             /* bzero/bcmp/bcopy */\n             /* (no known systems as of 960211) */\n\n/*********************/\n/* Function memset() */\n/*********************/\n\nzvoid *memset(buf, init, len)\n    register zvoid *buf;        /* buffer location */\n    register int init;          /* initializer character */\n    register unsigned int len;  /* length of the buffer */\n{\n    zvoid *start;\n\n    start = buf;\n    while (len--)\n        *((char *)buf++) = (char)init;\n    return start;\n}\n\n\n\n/*********************/\n/* Function memcmp() */\n/*********************/\n\nint memcmp(b1, b2, len)\n    register ZCONST zvoid *b1;\n    register ZCONST zvoid *b2;\n    register unsigned int len;\n{\n    register int c;\n\n    if (len > 0) do {\n        if ((c = (int)(*((ZCONST unsigned char *)b1)++) -\n                 (int)(*((ZCONST unsigned char *)b2)++)) != 0)\n           return c;\n    } while (--len > 0)\n    return 0;\n}\n\n\n\n/*********************/\n/* Function memcpy() */\n/*********************/\n\nzvoid *memcpy(dst, src, len)\n    register zvoid *dst;\n    register ZCONST zvoid *src;\n    register unsigned int len;\n{\n    zvoid *start;\n\n    start = dst;\n    while (len-- > 0)\n        *((char *)dst)++ = *((ZCONST char *)src)++;\n    return start;\n}\n\n#endif /* ZMEM */\n\n\n\n\n#ifdef NO_STRNICMP\n\n/************************/\n/* Function zstrnicmp() */\n/************************/\n\nint zstrnicmp(s1, s2, n)\n    register ZCONST char *s1, *s2;\n    register unsigned n;\n{\n    for (; n > 0;  --n, ++s1, ++s2) {\n\n        if (ToLower(*s1) != ToLower(*s2))\n            /* test includes early termination of one string */\n            return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1;\n\n        if (*s1 == '\\0')   /* both strings terminate early */\n            return 0;\n    }\n    return 0;\n}\n\n#endif /* NO_STRNICMP */\n\n\n\n\n#ifdef REGULUS  /* returns the inode number on success(!)...argh argh argh */\n#  undef stat\n\n/********************/\n/* Function zstat() */\n/********************/\n\nint zstat(p, s)\n    ZCONST char *p;\n    struct stat *s;\n{\n    return (stat((char *)p,s) >= 0? 0 : (-1));\n}\n\n#endif /* REGULUS */\n\n\n\n\n#ifdef _MBCS\n\n/* DBCS support for Info-ZIP's zip  (mainly for japanese (-: )\n * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)\n * This code is public domain!   Date: 1998/12/20\n */\n\n/************************/\n/* Function plastchar() */\n/************************/\n\nchar *plastchar(ptr, len)\n    ZCONST char *ptr;\n    extent len;\n{\n    unsigned clen;\n    ZCONST char *oldptr = ptr;\n    while(*ptr != '\\0' && len > 0){\n        oldptr = ptr;\n        clen = CLEN(ptr);\n        ptr += clen;\n        len -= clen;\n    }\n    return (char *)oldptr;\n}\n\n\n#ifdef NEED_UZMBCLEN\n/***********************/\n/* Function uzmbclen() */\n/***********************/\n\nextent uzmbclen(ptr)\n    ZCONST unsigned char *ptr;\n{\n    int mbl;\n\n    mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX);\n    /* For use in code scanning through MBCS strings, we need a strictly\n       positive \"MB char bytes count\".  For our scanning purpose, it is not\n       not relevant whether the MB character is valid or not. And, the NUL\n       char '\\0' has a byte count of 1, but mblen() returns 0. So, we make\n       sure that the uzmbclen() return value is not less than 1.\n     */\n    return (extent)(mbl > 0 ? mbl : 1);\n}\n#endif /* NEED_UZMBCLEN */\n\n\n#ifdef NEED_UZMBSCHR\n/***********************/\n/* Function uzmbschr() */\n/***********************/\n\nunsigned char *uzmbschr(str, c)\n    ZCONST unsigned char *str;\n    unsigned int c;\n{\n    while(*str != '\\0'){\n        if (*str == c) {return (unsigned char *)str;}\n        INCSTR(str);\n    }\n    return NULL;\n}\n#endif /* NEED_UZMBSCHR */\n\n\n#ifdef NEED_UZMBSRCHR\n/************************/\n/* Function uzmbsrchr() */\n/************************/\n\nunsigned char *uzmbsrchr(str, c)\n    ZCONST unsigned char *str;\n    unsigned int c;\n{\n    unsigned char *match = NULL;\n    while(*str != '\\0'){\n        if (*str == c) {match = (unsigned char *)str;}\n        INCSTR(str);\n    }\n    return match;\n}\n#endif /* NEED_UZMBSRCHR */\n#endif /* _MBCS */\n\n\n\n\n\n#ifdef SMALL_MEM\n\n/*******************************/\n/*  Function fLoadFarString()  */   /* (and friends...) */\n/*******************************/\n\nchar *fLoadFarString(__GPRO__ const char Far *sz)\n{\n    (void)zfstrcpy(G.rgchBigBuffer, sz);\n    return G.rgchBigBuffer;\n}\n\nchar *fLoadFarStringSmall(__GPRO__ const char Far *sz)\n{\n    (void)zfstrcpy(G.rgchSmallBuffer, sz);\n    return G.rgchSmallBuffer;\n}\n\nchar *fLoadFarStringSmall2(__GPRO__ const char Far *sz)\n{\n    (void)zfstrcpy(G.rgchSmallBuffer2, sz);\n    return G.rgchSmallBuffer2;\n}\n\n\n\n\n#if (!defined(_MSC_VER) || (_MSC_VER < 600))\n/*************************/\n/*  Function zfstrcpy()  */   /* portable clone of _fstrcpy() */\n/*************************/\n\nchar Far * Far zfstrcpy(char Far *s1, const char Far *s2)\n{\n    char Far *p = s1;\n\n    while ((*s1++ = *s2++) != '\\0');\n    return p;\n}\n\n#if (!(defined(SFX) || defined(FUNZIP)))\n/*************************/\n/*  Function zfstrcmp()  */   /* portable clone of _fstrcmp() */\n/*************************/\n\nint Far zfstrcmp(const char Far *s1, const char Far *s2)\n{\n    int ret;\n\n    while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0\n           && *s2 != '\\0') {\n        ++s2; ++s1;\n    }\n    return ret;\n}\n#endif /* !(SFX || FUNZIP) */\n#endif /* !_MSC_VER || (_MSC_VER < 600) */\n\n#endif /* SMALL_MEM */\n"
  },
  {
    "path": "deps/infozip/unzip60/flexos/Contents",
    "content": "Contents of the \"flexos\" subdirectory for UnZip 5.32 and later:\n\n  Contents       this file\n  README         notes about limitations and assumptions of the FlexOS port\n  flexos.c       OS-dependent UnZip routines for FlexOS\n  flxcfg.h       OS-dependent configuration, included by unzpriv.h\n  hc.pro         profile for MetaWare High C\n  makefile       makefile for MetaWare High C, PAMAKE\n"
  },
  {
    "path": "deps/infozip/unzip60/flexos/README",
    "content": "This should be considered an initial port - there will probably be some\nbugs and non-functioning features.\n\nThe only functionality that has had any real testing is \"unzip filename\",\nanything else is basically untested.\n\nThis has been cross-compiled from DOS using Metaware's High C compiler\nand the DOS version of pamake (v3.0).  It should compile with the FlexOS\nhosted version of HighC, and the makefile could be converted to work\nwith the native FlexOS make.\n\nThe following considerations apply:\n\n)Compiled against and linked with portlib.\n)Used on FlexOS 286 v2.32\n)Volume labels are not supported - this is due to the way FlexOS decides\n if a drive has case-sensitive filenames based upon the contents of the\n volume label.\n)No special handling for case-sensitive media (see above).\n)Not using the PORTLIB wildarg routine (i.e., UnZip does its own globbing).\n)Based upon the MSDOS port.\n)Filenames are in FAT format.\n)The current version of getch is a cheat (simply using getchar()).  I\n should interrogate stdin and if it's a FlexOS console use special code\n to turn off echo and just read one char.\n)Only the basic MSDOS FAT file attributes are saved/restored.  There is\n currently no support for the FlexOS extended file attributes.\n)There is some code that should attempt to do the correct thing when a\n pathspec with a logical name definition is used (e.g., \"system:path/to/it\");\n however it again has not been stress-tested.\n)There is no special handling for floppy drives, there probably should\n be.\n)The dateformat is compiled in as DMY (shoot me I'm British),  I'm not\n sure if there is actually a way to get locale info.\n)The assembler speedups haven't yet been ported to ASM86 (should simply\n be a change of syntax)\n\n --\n D.Fawcus  17 July 1997\n"
  },
  {
    "path": "deps/infozip/unzip60/flexos/flexos.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  flexos.c\n\n  FlexOS-specific routines for use with Info-ZIP's UnZip 5.2 and later.\n\n  Based upon the MSDOS version of this file (msdos/msdos.c)\n\n  Contains:  do_wild()\n             mapattr()\n             mapname()\n             map2fat()\n             checkdir()\n             close_outfile()\n             dateformat()\n             version()\n             _wildarg()\n\n  ---------------------------------------------------------------------------*/\n\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include <flexif.h>\n\n/* The following should really be a static declaration,  but the compiler\n   complains (crappy compiler can't cope with a static forward declaration).\n */\nextern void map2fat OF((char *pathcomp, char *last_dot));\n\nstatic int created_dir;        /* used by mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\n/*****************************/\n/*  Strings used in flexos.c  */\n/*****************************/\n\n#ifndef SFX\n  static ZCONST char Far CantAllocateWildcard[] =\n    \"warning:  cannot allocate wildcard buffers\\n\";\n#endif\nstatic ZCONST char Far WarnDirTraversSkip[] =\n  \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\";\nstatic ZCONST char Far Creating[] = \"   creating: %s\\n\";\nstatic ZCONST char Far ConversionFailed[] =\n  \"mapname:  conversion of %s failed\\n\";\nstatic ZCONST char Far PathTooLong[] = \"checkdir error:  path too long: %s\\n\";\nstatic ZCONST char Far CantCreateDir[] = \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far DirIsntDirectory[] =\n  \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far PathTooLongTrunc[] =\n  \"checkdir warning:  path too long; truncating\\n                   %s\\n\\\n                -> %s\\n\";\n#if (!defined(SFX) || defined(SFX_EXDIR))\n   static ZCONST char Far CantCreateExtractDir[] =\n     \"checkdir:  cannot create extraction directory: %s\\n\";\n#endif\n\n#include <dirent.h>\n\n#ifndef SFX\n\n/************************/\n/*  Function do_wild()  */   /* identical to OS/2 version */\n/************************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;   /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    char *fnamestart;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL &&\n            (wildname = strrchr(wildspec, ':')) == (ZCONST char *)NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' or ':' */\n            dirnamelen = (int)(wildname - wildspec);\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(CantAllocateWildcard)));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n/* GRR:  cannot strip trailing char for opendir since might be \"d:/\" or \"d:\"\n *       (would have to check for \"./\" at end--let opendir handle it instead) */\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n        Trace((stderr, \"do_wild:  dirname = [%s]\\n\", FnFilter1(dirname)));\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            if (have_dirname) {\n                strcpy(matchname, dirname);\n                fnamestart = matchname + dirnamelen;\n            } else\n                fnamestart = matchname;\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                strcpy(fnamestart, file->d_name);\n                if (strrchr(fnamestart, '.') == (char *)NULL)\n                    strcat(fnamestart, \".\");\n                if (match(fnamestart, wildname, 1 WISEP) && /* 1=ignore case */\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(fnamestart, \".\") && strcmp(fnamestart, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    /* remove trailing dot */\n                    fnamestart += strlen(fnamestart) - 1;\n                    if (*fnamestart == '.')\n                        *fnamestart = '\\0';\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n#ifdef DEBUG\n        else {\n            Trace((stderr, \"do_wild:  opendir(%s) returns NULL\\n\",\n              FnFilter1(dirname)));\n        }\n#endif /* DEBUG */\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    if (have_dirname) {\n        /* strcpy(matchname, dirname); */\n        fnamestart = matchname + dirnamelen;\n    } else\n        fnamestart = matchname;\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        strcpy(fnamestart, file->d_name);\n        if (strrchr(fnamestart, '.') == (char *)NULL)\n            strcat(fnamestart, \".\");\n        if (match(fnamestart, wildname, 1 WISEP)) {     /* 1 == ignore case */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            /* remove trailing dot */\n            fnamestart += strlen(fnamestart) - 1;\n            if (*fnamestart == '.')\n                *fnamestart = '\\0';\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    /* set archive bit (file is not backed up): */\n    G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes & 7) | 32;\n    return 0;\n}\n\n\n\n/**********************/\n/* Function mapname() */\n/**********************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    char *last_dot=(char *)NULL;   /* last dot not converted to underscore */\n    int dotname = FALSE;           /* path component begins with dot? */\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* Cannot set disk volume labels in FlexOS */\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n    renamed_fullpath = FALSE;\n\n    if (renamed) {\n        cp = G.filename - 1;    /* point to beginning of renamed name... */\n        while (*++cp)\n            if (*cp == '\\\\')    /* convert backslashes to forward */\n                *cp = '/';\n        cp = G.filename;\n        /* use temporary rootpath if user gave full pathname */\n        if (G.filename[0] == '/') {\n            renamed_fullpath = TRUE;\n            pathcomp[0] = '/';  /* copy the '/' and terminate */\n            pathcomp[1] = '\\0';\n            ++cp;\n        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {\n            renamed_fullpath = TRUE;\n            pp = pathcomp;\n            *pp++ = *cp++;      /* copy the \"d:\" (+ '/', possibly) */\n            *pp++ = *cp++;\n            if (*cp == '/')\n                *pp++ = *cp++;  /* otherwise add \"./\"? */\n            *pp = '\\0';\n        }\n    }\n\n    /* pathcomp is ignored unless renamed_fullpath is TRUE: */\n    if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* initialize path buf */\n        return error;           /* ...unless no mem or vol label on hard disk */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (!renamed) {             /* cp already set if renamed */\n        if (uO.jflag)           /* junking directories */\n            cp = (char *)strrchr(G.filename, '/');\n        if (cp == (char *)NULL) /* no '/' or not junking dirs */\n            cp = G.filename;    /* point to internal zipfile-member pathname */\n        else\n            ++cp;               /* point to start of last component of path */\n    }\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                map2fat(pathcomp, last_dot);   /* 8.3 truncation (in place) */\n                last_dot = (char *)NULL;\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case '.':\n                if (pp == pathcomp) {     /* nothing appended yet... */\n                    if (*cp == '.' && cp[1] == '/') {   /* \"../\" */\n                        *pp++ = '.';      /* add first dot, unchanged... */\n                        ++cp;             /* skip second dot, since it will */\n                    } else {              /*  be \"added\" at end of if-block */\n                        *pp++ = '_';      /* FAT doesn't allow null filename */\n                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */\n                    }                     /*  (extra '_' now, \"dot\" below) */\n                } else if (dotname) {     /* found a second dot, but still */\n                    dotname = FALSE;      /*  have extra leading underscore: */\n                    *pp = '\\0';           /*  remove it by shifting chars */\n                    pp = pathcomp + 1;    /*  left one space (e.g., .p1.p2: */\n                    while (pp[1]) {       /*  __p1 -> _p1_p2 -> _p1.p2 when */\n                        *pp = pp[1];      /*  finished) [opt.:  since first */\n                        ++pp;             /*  two chars are same, can start */\n                    }                     /*  shifting at second position] */\n                }\n                last_dot = pp;    /* point at last dot so far... */\n                *pp++ = '_';      /* convert dot to underscore for now */\n                break;\n\n            /* drive names are not stored in zipfile, so no colons allowed;\n             *  no brackets or most other punctuation either (all of which\n             *  can appear in Unix-created archives; backslash is particularly\n             *  bad unless all necessary directories exist) */\n            case '[':          /* these punctuation characters forbidden */\n            case ']':          /*  only on plain FAT file systems */\n            case '+':\n            case ',':\n            case '=':\n            case ':':           /* special shell characters of command.com */\n            case '\\\\':          /*  (device and directory limiters, wildcard */\n            case '\"':           /*  characters, stdin/stdout redirection and */\n            case '<':           /*  pipe indicators and the quote sign) are */\n            case '>':           /*  never allowed in filenames on (V)FAT */\n            case '|':\n            case '*':\n            case '?':\n                *pp++ = '_';\n                break;\n\n            case ';':             /* start of VMS version? */\n                lastsemi = pp;\n                break;\n\n            case ' ':                      /* change spaces to underscores */\n                if (uO.sflag)              /*  only if requested */\n                    *pp++ = '_';\n                else\n                    *pp++ = (char)workch;\n                break;\n\n            default:\n                /* allow ASCII 255 and European characters in filenames: */\n                if (isprint(workch) || workch >= 127)\n                    *pp++ = (char)workch;\n\n        } /* end switch */\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(Creating),\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi;            /* semi-colon was omitted:  expect all #'s */\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    map2fat(pathcomp, last_dot);  /* 8.3 truncation (in place) */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/**********************/\n/* Function map2fat() */\n/**********************/\n\nstatic void map2fat(pathcomp, last_dot)\n    char *pathcomp, *last_dot;\n{\n    char *pEnd = pathcomp + strlen(pathcomp);\n\n/*---------------------------------------------------------------------------\n    Case 1:  filename has no dot, so figure out if we should add one.  Note\n    that the algorithm does not try to get too fancy:  if there are no dots\n    already, the name either gets truncated at 8 characters or the last un-\n    derscore is converted to a dot (only if more characters are saved that\n    way).  In no case is a dot inserted between existing characters.\n\n              GRR:  have problem if filename is volume label??\n\n  ---------------------------------------------------------------------------*/\n\n    /* pEnd = pathcomp + strlen(pathcomp); */\n    if (last_dot == (char *)NULL) {   /* no dots:  check for underscores... */\n        char *plu = strrchr(pathcomp, '_');   /* pointer to last underscore */\n\n        if (plu == (char *)NULL) {  /* no dots, no underscores:  truncate at */\n            if (pEnd > pathcomp+8)  /* 8 chars (could insert '.' and keep 11) */\n                *(pEnd = pathcomp+8) = '\\0';\n        } else if (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8) {\n            last_dot = plu;       /* be lazy:  drop through to next if-block */\n        } else if ((pEnd - pathcomp) > 8)    /* more fits into just basename */\n            pathcomp[8] = '\\0';    /* than if convert last underscore to dot */\n        /* else whole thing fits into 8 chars or less:  no change */\n    }\n\n/*---------------------------------------------------------------------------\n    Case 2:  filename has dot in it, so truncate first half at 8 chars (shift\n    extension if necessary) and second half at three.\n  ---------------------------------------------------------------------------*/\n\n    if (last_dot != (char *)NULL) {   /* one dot (or two, in the case of */\n        *last_dot = '.';              /*  \"..\") is OK:  put it back in */\n\n        if ((last_dot - pathcomp) > 8) {\n            char *p=last_dot, *q=pathcomp+8;\n            int i;\n\n            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */\n                *q++ = *p++;                   /*  shift extension left and */\n            *q = '\\0';                         /*  truncate/terminate it */\n        } else if ((pEnd - last_dot) > 4)\n            last_dot[4] = '\\0';                /* too many chars in extension */\n        /* else filename is fine as is:  no change */\n    }\n} /* end function map2fat() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (stat(buildpath, &G.statbuf))    /* path doesn't exist */\n        {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n              FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc),\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        /* allocate space for full filename, root path, and maybe \"./\" */\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) ==\n            (char *)NULL)\n            return MPN_NOMEM;\n        if (renamed_fullpath) {   /* pathcomp = valid data */\n            end = buildpath;\n            while ((*end = *pathcomp++) != '\\0')\n                ++end;\n        } else if (rootlen > 0) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.  Note that under FlexOS, if a candidate extract-to\n    directory specification includes a drive letter (leading \"x:\"), it is\n    treated just as if it had a trailing '/'--that is, one directory level\n    will be created if the path doesn't exist, unless this is otherwise pro-\n    hibited (e.g., freshening).\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            int had_trailing_pathsep=FALSE, add_dot=FALSE;\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\\\') {\n                tmproot[--rootlen] = '\\0';\n                had_trailing_pathsep = TRUE;\n            }\n            if (tmproot[rootlen-1] == ':') {\n                if (!had_trailing_pathsep)  /* i.e., original wasn't \"xxx:/\" */\n                    add_dot = TRUE;     /* relative path: add '.' before '/' */\n            } else if (rootlen > 0) &&  /* need not check \"xxx:.\" and \"xxx:/\" */\n                       (SSTAT(tmproot, &G.statbuf) ||\n                        !S_ISDIR(G.statbuf.st_mode))\n            {\n                /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* treat as stored file */\n                    return MPN_INF_SKIP;\n                }\n/* GRR:  scan for wildcard characters?  OS-dependent...\n * if find any, return MPN_INF_SKIP: treat as stored file(s) */\n                /* create directory (could add loop here scanning tmproot\n                 * to create more than one level, but really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      LoadFarString(CantCreateExtractDir),\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n                tmproot[rootlen++] = '.';\n            tmproot[rootlen++] = '/';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n /*\n  * FlexOS VERSION\n  *\n  * Set the output file date/time stamp according to information from the\n  * zipfile directory record for this member, then close the file and set\n  * its permissions (archive, hidden, read-only, system).  Aside from closing\n  * the file, this routine is optional (but most compilers support it).\n  */\n{\n    DISKFILE    df;\n    LONG        fnum;\n\n    struct {                /* date and time words */\n        union {             /* DOS file modification time word */\n            ush ztime;\n            struct {\n                unsigned zt_se : 5;\n                unsigned zt_mi : 6;\n                unsigned zt_hr : 5;\n            } _tf;\n        } _t;\n        union {             /* DOS file modification date word */\n            ush zdate;\n            struct {\n                unsigned zd_dy : 5;\n                unsigned zd_mo : 4;\n                unsigned zd_yr : 7;\n            } _df;\n        } _d;\n    } zt;\n\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    struct tm *t;\n#endif /* ?USE_EF_UT_TIME */\n\n    fclose(G.outfile);\n\n    if ((fnum = s_open(A_SET, G.filename)) < 0) {\n        Info(slide, 0x201, ((char *)slide,\n          \"warning:  cannot open %s to set the time\\n\",\n          FnFilter1(G.filename)));\n        return;\n    }\n\n    if (s_get(T_FILE, fnum, &df, DSKFSIZE) < 0) {\n        s_close(0, fnum);\n\n        Info(slide, 0x201, ((char *)slide,\n          \"warning:  cannot get info on %s\\n\", FnFilter1(G.filename)));\n        return;\n    }\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n\n/*---------------------------------------------------------------------------\n    Copy and/or convert time and date variables, if necessary; then fill in\n    the file time/date.\n  ---------------------------------------------------------------------------*/\n\n#ifdef USE_EF_UT_TIME\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n             G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME))\n        {\n            TTrace((stderr, \"close_outfile:  Unix e.f. modif. time = %ld\\n\",\n              z_utime.mtime));\n            t = localtime(&(z_utime.mtime));\n        } else\n            t = (struct tm *)NULL;\n        if (t != (struct tm *)NULL) {\n            if (t->tm_year < 80) {\n                df.df_modyear = 1980;\n                df.df_modmonth = 1;\n                df.df_modday = 1;\n                df.df_modhr = 0;\n                df.df_modmin = 0;\n                df.df_modsec = 0;\n            } else {\n                df.df_modyear = t->tm_year + 1900;\n                df.df_modmonth = t->tm_mon + 1;\n                df.df_modday = t->tm_mday;\n                df.df_modhr = t->tm_hour;\n                df.df_modmin = t->tm_min;\n                df.df_modsec = t->tm_sec;\n            }\n        } else\n#endif /* ?USE_EF_UX_TIME */\n        {\n            zt._t.ztime = (ush)(G.lrec.last_mod_dos_datetime) & 0xffff;\n            zt._d.zdate = (ush)(G.lrec.last_mod_dos_datetime >> 16);\n\n            df.df_modyear = 1980 + zt._d._df.zd_yr;\n            df.df_modmonth = zt._d._df.zd_mo;\n            df.df_modday = zt._d._df.zd_dy;\n            df.df_modhr = zt._t._tf.zt_hr;\n            df.df_modmin = zt._t._tf.zt_mi;\n            df.df_modsec = zt._t._tf.zt_se << 1;\n        }\n    }\n\n/*---------------------------------------------------------------------------\n    Fill in the file attributes.\n  ---------------------------------------------------------------------------*/\n\n    df.df_attr1 = (UBYTE)G.pInfo->file_attr;\n\n/*---------------------------------------------------------------------------\n    Now we try to set the attributes & date/time.\n  ---------------------------------------------------------------------------*/\n\n    if (s_set(T_FILE, fnum, &df, DSKFSIZE) < 0)\n        Info(slide, 0x201, ((char *)slide,\n          \"warning:  cannot set info for %s\\n\", FnFilter1(G.filename)));\n\n    s_close(0, fnum);\n} /* end function close_outfile() */\n\n#ifndef SFX\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\nint dateformat()\n{\n    return DF_DMY;   /* default for systems without locale info */\n}\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n            \"MetaWare High C\",\n            \"\",\n            \"FlexOS\",\n            \" (16-bit, big)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n}\n\n#endif /* !SFX */\n\n/************************/\n/*  Function _wildarg() */\n/************************/\n\n/* This prevents the PORTLIB startup code from preforming argument globbing */\n\n_wildarg() {}\n"
  },
  {
    "path": "deps/infozip/unzip60/flexos/flxcfg.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    FlexOS specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __flxcfg_h\n#define __flxcfg_h\n\n#define __16BIT__\n#define MED_MEM\n#define EXE_EXTENSION \".286\"\n\n#ifndef nearmalloc\n#  define nearmalloc malloc\n#  define nearfree free\n#endif\n\n#define CRTL_CP_IS_OEM\n\n#define near\n#define far\n\n#endif /* !__flxcfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/flexos/hc.pro",
    "content": "pragma Off(Floating_point);\npragma On(286);\npragma On(Literals_in_code);\npragma On(Warn);\npragma On(pointers_compatible);\npragma On(Callee_pops_when_possible);\n\npragma On(Auto_reg_alloc);\npragma On(Const_in_Code);\npragma On(Read_only_strings);\npragma On(Optimize_for_space);\n\npragma Off(Prototype_override_warnings);\npragma Off(Quiet);\npragma Off(Asm);\npragma Off(flexview);\n\n#define PORTLIB\n#define FLEXOS 1\n"
  },
  {
    "path": "deps/infozip/unzip60/funzip.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* funzip.c -- by Mark Adler */\n\n#define VERSION \"3.95 of 20 January 2009\"\n\n\n/* Copyright history:\n   - Starting with UnZip 5.41 of 16-April-2000, this source file\n     is covered by the Info-Zip LICENSE cited above.\n   - Prior versions of this source file, found in UnZip source packages\n     up to UnZip 5.40, were put in the public domain.\n     The original copyright note by Mark Adler was:\n         \"You can do whatever you like with this source file,\n         though I would prefer that if you modify it and\n         redistribute it that you include comments to that effect\n         with your name and the date.  Thank you.\"\n\n   History:\n   vers     date          who           what\n   ----   ---------  --------------  ------------------------------------\n   1.0    13 Aug 92  M. Adler        really simple unzip filter.\n   1.1    13 Aug 92  M. Adler        cleaned up somewhat, give help if\n                                     stdin not redirected, warn if more\n                                     zip file entries after the first.\n   1.2    15 Aug 92  M. Adler        added check of lengths for stored\n                                     entries, added more help.\n   1.3    16 Aug 92  M. Adler        removed redundant #define's, added\n                                     decryption.\n   1.4    27 Aug 92  G. Roelofs      added exit(0).\n   1.5     1 Sep 92  K. U. Rommel    changed read/write modes for OS/2.\n   1.6     6 Sep 92  G. Roelofs      modified to use dummy crypt.c and\n                                     crypt.h instead of -DCRYPT.\n   1.7    23 Sep 92  G. Roelofs      changed to use DOS_OS2; included\n                                     crypt.c under MS-DOS.\n   1.8     9 Oct 92  M. Adler        improved inflation error msgs.\n   1.9    17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch;\n                                     renamed inflate_entry() to inflate();\n                                     adapted to use new, in-place zdecode.\n   2.0    22 Oct 92  M. Adler        allow filename argument, prompt for\n                                     passwords and don't echo, still allow\n                                     command-line password entry, but as an\n                                     option.\n   2.1    23 Oct 92  J-l. Gailly     fixed crypt/store bug,\n                     G. Roelofs      removed crypt.c under MS-DOS, fixed\n                                     decryption check to compare single byte.\n   2.2    28 Oct 92  G. Roelofs      removed declaration of key.\n   2.3    14 Dec 92  M. Adler        replaced fseek (fails on stdin for SCO\n                                     Unix V.3.2.4).  added quietflg for\n                                     inflate.c.\n   3.0    11 May 93  M. Adler        added gzip support\n   3.1     9 Jul 93  K. U. Rommel    fixed OS/2 pipe bug (PIPE_ERROR)\n   3.2     4 Sep 93  G. Roelofs      moved crc_32_tab[] to tables.h; used FOPx\n                                     from unzip.h; nuked OUTB macro and outbuf;\n                                     replaced flush(); inlined FlushOutput();\n                                     renamed decrypt to encrypted\n   3.3    29 Sep 93  G. Roelofs      replaced ReadByte() with NEXTBYTE macro;\n                                     revised (restored?) flush(); added FUNZIP\n   3.4    21 Oct 93  G. Roelofs      renamed quietflg to qflag; changed outcnt,\n                     H. Gessau       second updcrc() arg and flush() arg to ulg;\n                                     added inflate_free(); added \"g =\" to null\n                                     getc(in) to avoid compiler warnings\n   3.5    31 Oct 93  H. Gessau       changed DOS_OS2 to DOS_NT_OS2\n   3.6     6 Dec 93  H. Gessau       added \"near\" to mask_bits[]\n   3.7     9 Dec 93  G. Roelofs      added extent typecasts to fwrite() checks\n   3.8    28 Jan 94  GRR/JlG         initialized g variable in main() for gcc\n   3.81   22 Feb 94  M. Hanning-Lee  corrected usage message\n   3.82   27 Feb 94  G. Roelofs      added some typecasts to avoid warnings\n   3.83   22 Jul 94  G. Roelofs      changed fprintf to macro for DLLs\n    -      2 Aug 94  -               public release with UnZip 5.11\n    -     28 Aug 94  -               public release with UnZip 5.12\n   3.84    1 Oct 94  K. U. Rommel    changes for Metaware High C\n   3.85   29 Oct 94  G. Roelofs      changed fprintf macro to Info\n   3.86    7 May 95  K. Davis        RISCOS patches;\n                     P. Kienitz      Amiga patches\n   3.87   12 Aug 95  G. Roelofs      inflate_free(), DESTROYGLOBALS fixes\n   3.88    4 Sep 95  C. Spieler      reordered macro to work around MSC 5.1 bug\n   3.89   22 Nov 95  PK/CS           ifdef'd out updcrc() for ASM_CRC\n   3.9    17 Dec 95  G. Roelofs      modified for USE_ZLIB (new fillinbuf())\n    -     30 Apr 96  -               public release with UnZip 5.2\n   3.91   17 Aug 96  G. Roelofs      main() -> return int (Peter Seebach)\n   3.92   13 Apr 97  G. Roelofs      minor cosmetic fixes to messages\n    -     22 Apr 97  -               public release with UnZip 5.3\n    -     31 May 97  -               public release with UnZip 5.31\n   3.93   20 Sep 97  G. Roelofs      minor cosmetic fixes to messages\n    -      3 Nov 97  -               public release with UnZip 5.32\n    -     28 Nov 98  -               public release with UnZip 5.4\n    -     16 Apr 00  -               public release with UnZip 5.41\n    -     14 Jan 01  -               public release with UnZip 5.42\n   3.94   20 Feb 01  C. Spieler      added support for Deflate64(tm)\n          23 Mar 02  C. Spieler      changed mask_bits[] type to \"unsigned\"\n */\n\n\n/*\n\n   All funzip does is take a zipfile from stdin and decompress the\n   first entry to stdout.  The entry has to be either deflated or\n   stored.  If the entry is encrypted, then the decryption password\n   must be supplied on the command line as the first argument.\n\n   funzip needs to be linked with inflate.o and crypt.o compiled from\n   the unzip source.  If decryption is desired, the full version of\n   crypt.c (and crypt.h) from zcrypt28.zip or later must be used.\n\n */\n\n#ifndef FUNZIP\n#  define FUNZIP\n#endif\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"crc32.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n\n#ifdef EBCDIC\n#  undef EBCDIC                 /* don't need ebcdic[] */\n#endif\n\n#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */\n#  define UZinflate inflate\n#endif\n\n/* PKZIP header definitions */\n#define ZIPMAG 0x4b50           /* two-byte zip lead-in */\n#define LOCREM 0x0403           /* remaining two bytes in zip signature */\n#define LOCSIG 0x04034b50L      /* full signature */\n#define LOCFLG 4                /* offset of bit flag */\n#define  CRPFLG 1               /*  bit for encrypted entry */\n#define  EXTFLG 8               /*  bit for extended local header */\n#define LOCHOW 6                /* offset of compression method */\n#define LOCTIM 8                /* file mod time (for decryption) */\n#define LOCCRC 12               /* offset of crc */\n#define LOCSIZ 16               /* offset of compressed size */\n#define LOCLEN 20               /* offset of uncompressed length */\n#define LOCFIL 24               /* offset of file name field length */\n#define LOCEXT 26               /* offset of extra field length */\n#define LOCHDR 28               /* size of local header, including LOCREM */\n#define EXTHDR 16               /* size of extended local header, inc sig */\n\n/* GZIP header definitions */\n#define GZPMAG 0x8b1f           /* two-byte gzip lead-in */\n#define GZPHOW 0                /* offset of method number */\n#define GZPFLG 1                /* offset of gzip flags */\n#define  GZPMUL 2               /* bit for multiple-part gzip file */\n#define  GZPISX 4               /* bit for extra field present */\n#define  GZPISF 8               /* bit for filename present */\n#define  GZPISC 16              /* bit for comment present */\n#define  GZPISE 32              /* bit for encryption */\n#define GZPTIM 2                /* offset of Unix file modification time */\n#define GZPEXF 6                /* offset of extra flags */\n#define GZPCOS 7                /* offset of operating system compressed on */\n#define GZPHDR 8                /* length of minimal gzip header */\n\n#ifdef THEOS\n/* Macros cause stack overflow in compiler */\nush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }\nulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }\n#else /* !THEOS */\n/* Macros for getting two-byte and four-byte header values */\n#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))\n#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))\n#endif /* ?THEOS */\n\n/* Function prototypes */\nstatic void err OF((int, char *));\n#if (defined(USE_DEFLATE64) && defined(__16BIT__))\nstatic int partflush OF((uch *rawbuf, unsigned w));\n#endif\nint main OF((int, char **));\n\n/* Globals */\nFILE *out;                      /* output file (*in moved to G struct) */\nulg outsiz;                     /* total bytes written to out */\nint encrypted;                  /* flag to turn on decryption */\n\n/* Masks for inflate.c */\nZCONST unsigned near mask_bits[17] = {\n    0x0000,\n    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,\n    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff\n};\n\n\n#ifdef USE_ZLIB\n\nint fillinbuf(__G)\n__GDEF\n/* Fill input buffer for pull-model inflate() in zlib.  Return the number of\n * bytes in inbuf. */\n{\n/*   GRR: check return value from fread(): same as read()?  check errno? */\n  if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0)\n    return 0;\n  G.inptr = G.inbuf;\n\n#if CRYPT\n  if (encrypted) {\n    uch *p;\n    int n;\n\n    for (n = G.incnt, p = G.inptr;  n--;  p++)\n      zdecode(*p);\n  }\n#endif /* CRYPT */\n\n  return G.incnt;\n\n}\n\n#endif /* USE_ZLIB */\n\n\nstatic void err(n, m)\nint n;\nchar *m;\n/* Exit on error with a message and a code */\n{\n  Info(slide, 1, ((char *)slide, \"funzip error: %s\\n\", m));\n  DESTROYGLOBALS();\n  EXIT(n);\n}\n\n\n#if (defined(USE_DEFLATE64) && defined(__16BIT__))\n\nstatic int partflush(rawbuf, w)\nuch *rawbuf;     /* start of buffer area to flush */\nextent w;       /* number of bytes to flush */\n{\n  G.crc32val = crc32(G.crc32val, rawbuf, (extent)w);\n  if (fwrite((char *)rawbuf,1,(extent)w,out) != (extent)w && !PIPE_ERROR)\n    err(9, \"out of space on stdout\");\n  outsiz += w;\n  return 0;\n}\n\n\nint flush(w)    /* used by inflate.c (FLUSH macro) */\nulg w;          /* number of bytes to flush */\n{\n    uch *rawbuf;\n    int ret;\n\n    /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions\n     * cannot handle writes of 64k blocks at once.  For these systems, the\n     * blocks to flush are split into pieces of 32k or less.\n     */\n    rawbuf = slide;\n    while (w > 0x8000L) {\n        ret = partflush(rawbuf, 0x8000);\n        if (ret != PK_OK)\n            return ret;\n        w -= 0x8000L;\n        rawbuf += (unsigned)0x8000;\n    }\n    return partflush(rawbuf, (extent)w);\n} /* end function flush() */\n\n#else /* !(USE_DEFLATE64 && __16BIT__) */\n\nint flush(w)    /* used by inflate.c (FLUSH macro) */\nulg w;          /* number of bytes to flush */\n{\n  G.crc32val = crc32(G.crc32val, slide, (extent)w);\n  if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR)\n    err(9, \"out of space on stdout\");\n  outsiz += w;\n  return 0;\n}\n\n#endif /* ?(USE_DEFLATE64 && __16BIT__) */\n\n\nint main(argc, argv)\nint argc;\nchar **argv;\n/* Given a zipfile on stdin, decompress the first entry to stdout. */\n{\n  ush n;\n  uch h[LOCHDR];                /* first local header (GZPHDR < LOCHDR) */\n  int g = 0;                    /* true if gzip format */\n  unsigned method = 0;          /* initialized here to shut up gcc warning */\n#if CRYPT\n  char *s = \" [-password]\";\n  char *p;                      /* password */\n#else /* !CRYPT */\n  char *s = \"\";\n#endif /* ?CRYPT */\n  CONSTRUCTGLOBALS();\n\n  /* skip executable name */\n  argc--;\n  argv++;\n\n#if CRYPT\n  /* get the command line password, if any */\n  p = (char *)NULL;\n  if (argc && **argv == '-')\n  {\n    argc--;\n    p = 1 + *argv++;\n  }\n#endif /* CRYPT */\n\n#ifdef MALLOC_WORK\n  /* The following expression is a cooked-down simplyfication of the\n     calculation for the work area size of UnZip (see unzip.c).  For\n     fUnZip, the work area does not need to match the granularity\n     of the complex unshrink structures, because it only supports\n     inflation.  But, like in UnZip, the zcalloc() wrapper function\n     is needed for the allocation, to support the 64kByte buffer on\n     16-bit systems.\n   */\n# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))\n# define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK )\n  G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);\n# undef UZ_SLIDE_CHUNK\n# undef UZ_NUMOF_CHUNKS\n#endif\n\n  /* if no file argument and stdin not redirected, give the user help */\n  if (argc == 0 && isatty(0))\n  {\n    Info(slide, 1, ((char *)slide, \"fUnZip (filter UnZip), version %s\\n\",\n      VERSION));\n    Info(slide, 1, ((char *)slide, \"usage: ... | funzip%s | ...\\n\", s));\n    Info(slide, 1, ((char *)slide, \"       ... | funzip%s > outfile\\n\", s));\n    Info(slide, 1, ((char *)slide, \"       funzip%s infile.zip > outfile\\n\",s));\n    Info(slide, 1, ((char *)slide, \"       funzip%s infile.gz > outfile\\n\", s));\n    Info(slide, 1, ((char *)slide, \"Extracts to stdout the gzip file or first\\\n zip entry of stdin or the given file.\\n\"));\n    DESTROYGLOBALS();\n    EXIT(3);\n  }\n\n  /* prepare to be a binary filter */\n  if (argc)\n  {\n    if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL)\n      err(2, \"cannot find input file\");\n  }\n  else\n  {\n#ifdef DOS_FLX_NLM_OS2_W32\n#if (defined(__HIGHC__) && !defined(FLEXOS))\n    setmode(stdin, _BINARY);\n#else\n    setmode(0, O_BINARY);  /* some buggy C libraries require BOTH setmode() */\n#endif                     /*  call AND the fdopen() in binary mode :-( */\n#endif /* DOS_FLX_NLM_OS2_W32 */\n\n#ifdef RISCOS\n    G.in = stdin;\n#else\n    if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)\n      err(2, \"cannot find stdin\");\n#endif\n  }\n\n#ifdef DOS_FLX_H68_NLM_OS2_W32\n#if (defined(__HIGHC__) && !defined(FLEXOS))\n  setmode(stdout, _BINARY);\n#else\n  setmode(1, O_BINARY);\n#endif\n#endif /* DOS_FLX_H68_NLM_OS2_W32 */\n\n#ifdef RISCOS\n  out = stdout;\n#else\n  if ((out = fdopen(1, FOPW)) == (FILE *)NULL)\n    err(2, \"cannot write to stdout\");\n#endif\n\n  /* read local header, check validity, and skip name and extra fields */\n  n = getc(G.in);  n |= getc(G.in) << 8;\n  if (n == ZIPMAG)\n  {\n    if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM)\n      err(3, \"invalid zipfile\");\n    switch (method = SH(h + LOCHOW)) {\n      case STORED:\n      case DEFLATED:\n#ifdef USE_DEFLATE64\n      case ENHDEFLATED:\n#endif\n        break;\n      default:\n        err(3, \"first entry not deflated or stored--cannot unpack\");\n        break;\n    }\n    for (n = SH(h + LOCFIL); n--; ) g = getc(G.in);\n    for (n = SH(h + LOCEXT); n--; ) g = getc(G.in);\n    g = 0;\n    encrypted = h[LOCFLG] & CRPFLG;\n  }\n  else if (n == GZPMAG)\n  {\n    if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR)\n      err(3, \"invalid gzip file\");\n    if ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED)\n      err(3, \"gzip file not deflated\");\n    if (h[GZPFLG] & GZPMUL)\n      err(3, \"cannot handle multi-part gzip files\");\n    if (h[GZPFLG] & GZPISX)\n    {\n      n = getc(G.in);  n |= getc(G.in) << 8;\n      while (n--) g = getc(G.in);\n    }\n    if (h[GZPFLG] & GZPISF)\n      while ((g = getc(G.in)) != 0 && g != EOF) ;\n    if (h[GZPFLG] & GZPISC)\n      while ((g = getc(G.in)) != 0 && g != EOF) ;\n    g = 1;\n    encrypted = h[GZPFLG] & GZPISE;\n  }\n  else\n    err(3, \"input not a zip or gzip file\");\n\n  /* if entry encrypted, decrypt and validate encryption header */\n  if (encrypted)\n#if CRYPT\n    {\n      ush i, e;\n\n      if (p == (char *)NULL) {\n        if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)\n          err(1, \"out of memory\");\n        else if ((p = getp(\"Enter password: \", p, IZ_PWLEN+1)) == (char *)NULL)\n          err(1, \"no tty to prompt for password\");\n      }\n      /* initialize crc_32_tab pointer for decryption */\n      CRC_32_TAB = get_crc_table();\n      /* prepare the decryption keys for extraction and check the password */\n      init_keys(p);\n      for (i = 0; i < RAND_HEAD_LEN; i++)\n        e = NEXTBYTE;\n      if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3]))\n        err(3, \"incorrect password for first entry\");\n    }\n#else /* !CRYPT */\n    err(3, \"cannot decrypt entry (need to recompile with full crypt.c)\");\n#endif /* ?CRYPT */\n\n  /* prepare output buffer and crc */\n  G.outptr = slide;\n  G.outcnt = 0L;\n  outsiz = 0L;\n  G.crc32val = CRCVAL_INITIAL;\n\n  /* decompress */\n  if (g || h[LOCHOW])\n  {                             /* deflated entry */\n    int r;\n\n#ifdef USE_ZLIB\n    /* need to allocate and prepare input buffer */\n    if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL)\n       err(1, \"out of memory\");\n#endif /* USE_ZLIB */\n    if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {\n      if (r == 3)\n        err(1, \"out of memory\");\n      else\n        err(4, \"invalid compressed data--format violated\");\n    }\n    inflate_free(__G);\n  }\n  else\n  {                             /* stored entry */\n    register ulg n;\n\n    n = LG(h + LOCLEN);\n#if CRYPT\n    if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {\n#else\n    if (n != LG(h + LOCSIZ)) {\n#endif\n      Info(slide, 1, ((char *)slide, \"len %ld, siz %ld\\n\", n, LG(h + LOCSIZ)));\n      err(4, \"invalid compressed data--length mismatch\");\n    }\n    while (n--) {\n      ush c = getc(G.in);\n#if CRYPT\n      if (encrypted)\n        zdecode(c);\n#endif\n      *G.outptr++ = (uch)c;\n#if (defined(USE_DEFLATE64) && defined(__16BIT__))\n      if (++G.outcnt == (WSIZE>>1))     /* do FlushOutput() */\n#else\n      if (++G.outcnt == WSIZE)    /* do FlushOutput() */\n#endif\n      {\n        G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);\n        if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt\n            && !PIPE_ERROR)\n          err(9, \"out of space on stdout\");\n        outsiz += G.outcnt;\n        G.outptr = slide;\n        G.outcnt = 0L;\n      }\n    }\n  }\n  if (G.outcnt)   /* flush one last time; no need to reset G.outptr/outcnt */\n  {\n    G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);\n    if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt\n        && !PIPE_ERROR)\n      err(9, \"out of space on stdout\");\n    outsiz += G.outcnt;\n  }\n  fflush(out);\n\n  /* if extended header, get it */\n  if (g)\n  {\n    if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8)\n      err(3, \"gzip file ended prematurely\");\n  }\n  else\n    if ((h[LOCFLG] & EXTFLG) &&\n        fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR)\n      err(3, \"zipfile ended prematurely\");\n\n  /* validate decompression */\n  if (LG(h + LOCCRC) != G.crc32val)\n    err(4, \"invalid compressed data--crc error\");\n  if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)\n    err(4, \"invalid compressed data--length error\");\n\n  /* check if there are more entries */\n  if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG)\n    Info(slide, 1, ((char *)slide,\n      \"funzip warning: zipfile has more than one entry--rest ignored\\n\"));\n\n  DESTROYGLOBALS();\n  RETURN (0);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/funzip.txt",
    "content": "FUNZIP(1L)                                                          FUNZIP(1L)\n\nNAME\n       funzip - filter for extracting from a ZIP archive in a pipe\n\nSYNOPSIS\n       funzip [-password] [input[.zip|.gz]]\n\nARGUMENTS\n       [-password]\n              Optional  password  to  be  used  if  ZIP  archive is encrypted.\n              Decryption may not be supported at some sites.  See  DESCRIPTION\n              for more details.\n\n       [input[.zip|.gz]]\n              Optional  input  archive file specification. See DESCRIPTION for\n              details.\n\nDESCRIPTION\n       funzip without a file argument acts as a filter; that  is,  it  assumes\n       that  a  ZIP archive (or a gzip'd(1) file) is being piped into standard\n       input, and it extracts the first member from  the  archive  to  stdout.\n       When  stdin comes from a tty device, funzip assumes that this cannot be\n       a stream of (binary) compressed data  and  shows  a  short  help  text,\n       instead.   If  there  is  a  file argument, then input is read from the\n       specified file instead of from stdin.\n\n       A password for encrypted zip files can be specified on the command line\n       (preceding  the  file  name,  if  any) by prefixing the password with a\n       dash.  Note that this constitutes a security risk on many systems; cur-\n       rently  running  processes are often visible via simple commands (e.g.,\n       ps(1) under Unix), and command-line histories  can  be  read.   If  the\n       first  entry  of the zip file is encrypted and no password is specified\n       on the command line, then the user is prompted for a password  and  the\n       password is not echoed on the console.\n\n       Given the limitation on single-member extraction, funzip is most useful\n       in conjunction with a secondary archiver program such as  tar(1).   The\n       following  section  includes  an example illustrating this usage in the\n       case of disk backups to tape.\n\nEXAMPLES\n       To use funzip to extract the first member file of the archive  test.zip\n       and to pipe it into more(1):\n\n           funzip test.zip | more\n\n       To  use  funzip  to  test the first member file of test.zip (any errors\n       will be reported on standard error):\n\n           funzip test.zip > /dev/null\n\n       To use zip and funzip in place of compress(1) and zcat(1) (or  gzip(1L)\n       and gzcat(1L)) for tape backups:\n\n           tar cf - . | zip -7 | dd of=/dev/nrst0 obs=8k\n           dd if=/dev/nrst0 ibs=8k | funzip | tar xf -\n\n       (where, for example, nrst0 is a SCSI tape drive).\n\nBUGS\n       When  piping  an encrypted file into more and allowing funzip to prompt\n       for password, the terminal may sometimes be reset to a  non-echo  mode.\n       This  is  apparently  due to a race condition between the two programs;\n       funzip changes the terminal mode to  non-echo  before  more  reads  its\n       state,  and  more  then  ``restores''  the terminal to this mode before\n       exiting.  To recover, run funzip on  the  same  file  but  redirect  to\n       /dev/null  rather  than piping into more; after prompting again for the\n       password, funzip will reset the terminal properly.\n\n       There is presently no way to extract any member but the  first  from  a\n       ZIP  archive.   This would be useful in the case where a ZIP archive is\n       included within another archive.  In the case where the first member is\n       a directory, funzip simply creates the directory and exits.\n\n       The  functionality  of  funzip should be incorporated into unzip itself\n       (future release).\n\nSEE ALSO\n       gzip(1L), unzip(1L), unzipsfx(1L), zip(1L), zipcloak(1L),  zipinfo(1L),\n       zipnote(1L), zipsplit(1L)\n\nURL\n       The Info-ZIP home page is currently at\n           http://www.info-zip.org/pub/infozip/\n       or\n           ftp://ftp.info-zip.org/pub/infozip/ .\n\nAUTHOR\n       Mark Adler (Info-ZIP)\n\nInfo-ZIP                     20 April 2009 (v3.95)                  FUNZIP(1L)\n"
  },
  {
    "path": "deps/infozip/unzip60/gbloffs.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Write out a fragment of assembly or C preprocessor source giving offsets\n * in \"Uz_Globs\" and \"struct huft\".  Used by Amiga and Human68k ports.\n */\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"crypt.h\"\n\n#ifndef REENTRANT\n  Uz_Globs G;\n#endif\n\nstatic int asm_setflag(const char *flagname);\nstatic int ccp_setflag(const char *flagname);\n\nstatic int asm_setflag(const char *flagname)\n{\n    static const char asm_flagdef[] = \"   IFND %s\\n%-15s EQU     1\\n   ENDC\\n\";\n    return printf(asm_flagdef, flagname, flagname);\n}\nstatic int ccp_setflag(const char *flagname)\n{\n    static const char ccp_flagdef[] = \"#ifndef %s\\n#  define %s\\n#endif\\n\";\n    return printf(ccp_flagdef, flagname, flagname);\n}\n\nint main(argc, argv)\n    int argc;\n    char **argv;\n{\n#ifdef REENTRANT\n    Uz_Globs *pG = NULL;\n#endif\n    struct huft *t = NULL;\n    static const char asm_offsdef[] = \"%-15s EQU     %lu\\n\";\n    static const char ccp_offsdef[] = \"#define %-15s %lu\\n\";\n\n    const char *out_format;\n    int (*set_flag)(const char *flagname);\n    int ccp_select = 0;\n\n    if (argc > 1 && argv[1] != NULL && !strcmp(argv[1], \"-ccp\"))\n      ccp_select = 1;\n\n    if (ccp_select) {\n        out_format = ccp_offsdef;\n        set_flag = ccp_setflag;\n    } else {\n        out_format = asm_offsdef;\n        set_flag = asm_setflag;\n    }\n\n    printf(out_format, \"h_e\", (ulg)&t->e - (ulg)t);\n    printf(out_format, \"h_b\", (ulg)&t->b - (ulg)t);\n    printf(out_format, \"h_v_n\", (ulg)&t->v.n - (ulg)t);\n    printf(out_format, \"h_v_t\", (ulg)&t->v.t - (ulg)t);\n    printf(out_format, \"SIZEOF_huft\", (ulg)sizeof(struct huft));\n\n    printf(out_format, \"bb\", (ulg)&G.bb - (ulg)&G);\n    printf(out_format, \"bk\", (ulg)&G.bk - (ulg)&G);\n    printf(out_format, \"wp\", (ulg)&G.wp - (ulg)&G);\n#ifdef FUNZIP\n    printf(out_format, \"in\", (ulg)&G.in - (ulg)&G);\n#else\n    printf(out_format, \"incnt\", (ulg)&G.incnt - (ulg)&G);\n    printf(out_format, \"inptr\", (ulg)&G.inptr - (ulg)&G);\n    printf(out_format, \"csize\", (ulg)&G.csize - (ulg)&G);\n    printf(out_format, \"mem_mode\", (ulg)&G.mem_mode - (ulg)&G);\n#endif\n    printf(out_format, \"redirslide\", (ulg)&redirSlide - (ulg)&G);\n    printf(out_format, \"SIZEOF_slide\", (ulg)sizeof(redirSlide));\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    printf(out_format, \"_wsize\", (ulg)&G._wsize - (ulg)&G);\n#endif /* DLL && !NO_SLIDE_REDIR */\n    printf(out_format, \"CRYPT\", (ulg)CRYPT);\n#ifdef FUNZIP\n    (*set_flag)(\"FUNZIP\");\n#endif\n#ifdef SFX\n    (*set_flag)(\"SFX\");\n#endif\n#ifdef REENTRANT\n    (*set_flag)(\"REENTRANT\");\n#endif\n#ifdef DLL\n    (*set_flag)(\"DLL\");\n# ifdef NO_SLIDE_REDIR\n    (*set_flag)(\"NO_SLIDE_REDIR\");\n# endif\n#endif\n#ifdef USE_DEFLATE64\n    (*set_flag)(\"USE_DEFLATE64\");\n#endif\n\n    return 0;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/globals.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  globals.c\n\n  Routines to allocate and initialize globals, with or without threads.\n\n  Contents:  registerGlobalPointer()\n             deregisterGlobalPointer()\n             getGlobalPointer()\n             globalsCtor()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#ifndef FUNZIP\n/* initialization of sigs is completed at runtime so unzip(sfx) executable\n * won't look like a zipfile\n */\nchar central_hdr_sig[4]   = {0, 0, 0x01, 0x02};\nchar local_hdr_sig[4]     = {0, 0, 0x03, 0x04};\nchar end_central_sig[4]   = {0, 0, 0x05, 0x06};\nchar end_central64_sig[4] = {0, 0, 0x06, 0x06};\nchar end_centloc64_sig[4] = {0, 0, 0x06, 0x07};\n/* extern char extd_local_sig[4] = {0, 0, 0x07, 0x08};  NOT USED YET */\n\nZCONST char *fnames[2] = {\"*\", NULL};   /* default filenames vector */\n#endif\n\n\n#ifndef REENTRANT\n   Uz_Globs G;\n#else /* REENTRANT */\n\n#  ifndef USETHREADID\n     Uz_Globs *GG;\n#  else /* USETHREADID */\n#    define THREADID_ENTRIES  0x40\n\n     int lastScan;\n     Uz_Globs  *threadPtrTable[THREADID_ENTRIES];\n     ulg        threadIdTable [THREADID_ENTRIES] = {\n         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,\n         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* Make sure there are */\n         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,    /* THREADID_ENTRIES 0s */\n         0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0\n     };\n\n     static ZCONST char Far TooManyThreads[] =\n       \"error:  more than %d simultaneous threads.\\n\\\n        Some threads are probably not calling DESTROYTHREAD()\\n\";\n     static ZCONST char Far EntryNotFound[] =\n       \"error:  couldn't find global pointer in table.\\n\\\n        Maybe somebody accidentally called DESTROYTHREAD() twice.\\n\";\n     static ZCONST char Far GlobalPointerMismatch[] =\n       \"error:  global pointer in table does not match pointer passed as\\\n parameter\\n\";\n\nstatic void registerGlobalPointer OF((__GPRO));\n\n\n\nstatic void registerGlobalPointer(__G)\n    __GDEF\n{\n    int scan=0;\n    ulg tid = GetThreadId();\n\n    while (threadIdTable[scan] && scan < THREADID_ENTRIES)\n        scan++;\n\n    if (scan == THREADID_ENTRIES) {\n        ZCONST char *tooMany = LoadFarString(TooManyThreads);\n        Info(slide, 0x421, ((char *)slide, tooMany, THREADID_ENTRIES));\n        free(pG);\n        EXIT(PK_MEM);   /* essentially memory error before we've started */\n    }\n\n    threadIdTable [scan] = tid;\n    threadPtrTable[scan] = pG;\n    lastScan = scan;\n}\n\n\n\nvoid deregisterGlobalPointer(__G)\n    __GDEF\n{\n    int scan=0;\n    ulg tid = GetThreadId();\n\n\n    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)\n        scan++;\n\n/*---------------------------------------------------------------------------\n    There are two things we can do if we can't find the entry:  ignore it or\n    scream.  The most likely reason for it not to be here is the user calling\n    this routine twice.  Since this could cause BIG problems if any globals\n    are accessed after the first call, we'd better scream.\n  ---------------------------------------------------------------------------*/\n\n    if (scan == THREADID_ENTRIES || threadPtrTable[scan] != pG) {\n        ZCONST char *noEntry;\n        if (scan == THREADID_ENTRIES)\n            noEntry = LoadFarString(EntryNotFound);\n        else\n            noEntry = LoadFarString(GlobalPointerMismatch);\n        Info(slide, 0x421, ((char *)slide, noEntry));\n        EXIT(PK_WARN);   /* programming error, but after we're all done */\n    }\n\n    threadIdTable [scan] = 0;\n    lastScan = scan;\n    free(threadPtrTable[scan]);\n}\n\n\n\nUz_Globs *getGlobalPointer()\n{\n    int scan=0;\n    ulg tid = GetThreadId();\n\n    while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES)\n        scan++;\n\n/*---------------------------------------------------------------------------\n    There are two things we can do if we can't find the entry:  ignore it or\n    scream.  The most likely reason for it not to be here is the user calling\n    this routine twice.  Since this could cause BIG problems if any globals\n    are accessed after the first call, we'd better scream.\n  ---------------------------------------------------------------------------*/\n\n    if (scan == THREADID_ENTRIES) {\n        ZCONST char *noEntry = LoadFarString(EntryNotFound);\n        fprintf(stderr, noEntry);  /* can't use Info w/o a global pointer */\n        EXIT(PK_ERR);   /* programming error while still working */\n    }\n\n    return threadPtrTable[scan];\n}\n\n#  endif /* ?USETHREADID */\n#endif /* ?REENTRANT */\n\n\n\nUz_Globs *globalsCtor()\n{\n#ifdef REENTRANT\n    Uz_Globs *pG = (Uz_Globs *)malloc(sizeof(Uz_Globs));\n\n    if (!pG)\n        return (Uz_Globs *)NULL;\n#endif /* REENTRANT */\n\n    /* for REENTRANT version, G is defined as (*pG) */\n\n    memzero(&G, sizeof(Uz_Globs));\n\n#ifndef FUNZIP\n#ifdef CMS_MVS\n    uO.aflag=1;\n    uO.C_flag=1;\n#endif\n#ifdef TANDEM\n    uO.aflag=1;     /* default to '-a' auto create Text Files as type 101 */\n#endif\n#ifdef VMS\n# if (!defined(NO_TIMESTAMPS))\n    uO.D_flag=1;    /* default to '-D', no restoration of dir timestamps */\n# endif\n#endif\n\n    uO.lflag=(-1);\n    G.wildzipfn = \"\";\n    G.pfnames = (char **)fnames;\n    G.pxnames = (char **)&fnames[1];\n    G.pInfo = G.info;\n    G.sol = TRUE;          /* at start of line */\n\n    G.message = UzpMessagePrnt;\n    G.input = UzpInput;           /* not used by anyone at the moment... */\n#if defined(WINDLL) || defined(MACOS)\n    G.mpause = NULL;              /* has scrollbars:  no need for pausing */\n#else\n    G.mpause = UzpMorePause;\n#endif\n    G.decr_passwd = UzpPassword;\n#endif /* !FUNZIP */\n\n#if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))\n#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))\n    G.echofd = -1;\n#endif /* !(MACOS || ATARI || VMS) */\n#endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */\n\n#ifdef SYSTEM_SPECIFIC_CTOR\n    SYSTEM_SPECIFIC_CTOR(__G);\n#endif\n\n#ifdef REENTRANT\n#ifdef USETHREADID\n    registerGlobalPointer(__G);\n#else\n    GG = &G;\n#endif /* ?USETHREADID */\n#endif /* REENTRANT */\n\n    return &G;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/globals.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  globals.h\n\n  There is usually no need to include this file since unzip.h includes it.\n\n  This header file is used by all of the UnZip source files.  It contains\n  a struct definition that is used to \"house\" all of the global variables.\n  This is done to allow for multithreaded environments (OS/2, NT, Win95,\n  Unix) to call UnZip through an API without a semaphore.  REENTRANT should\n  be defined for all platforms that require this.\n\n  GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!)\n  ------------------------------------------------------------\n\n  No, it's not C++, but it's as close as we can get with K&R.\n\n  The main() of each process that uses these globals must include the\n  CONSTRUCTGLOBALS; statement.  This will malloc enough memory for the\n  structure and initialize any variables that require it.  This must\n  also be done by any API function that jumps into the middle of the\n  code.\n\n  The DESTROYGLOBALS(); statement should be inserted before EVERY \"EXIT(n)\".\n  Naturally, it also needs to be put before any API returns as well.\n  In fact, it's much more important in API functions since the process\n  will NOT end, and therefore the memory WON'T automatically be freed\n  by the operating system.\n\n  USING VARIABLES FROM THE STRUCTURE\n  ----------------------------------\n\n  All global variables must now be prefixed with `G.' which is either a\n  global struct (in which case it should be the only global variable) or\n  a macro for the value of a local pointer variable that is passed from\n  function to function.  Yes, this is a pain.  But it's the only way to\n  allow full reentrancy.\n\n  ADDING VARIABLES TO THE STRUCTURE\n  ---------------------------------\n\n  If you make the inclusion of any variables conditional, be sure to only\n  check macros that are GUARANTEED to be included in every module.\n  For instance, newzip and pwdarg are needed only if CRYPT is TRUE,\n  but this is defined after unzip.h has been read.  If you are not careful,\n  some modules will expect your variable to be part of this struct while\n  others won't.  This will cause BIG problems. (Inexplicable crashes at\n  strange times, car fires, etc.)  When in doubt, always include it!\n\n  Note also that UnZipSFX needs a few variables that UnZip doesn't.  However,\n  it also includes some object files from UnZip.  If we were to conditionally\n  include the extra variables that UnZipSFX needs, the object files from\n  UnZip would not mesh with the UnZipSFX object files.  Result: we just\n  include the UnZipSFX variables every time.  (It's only an extra 4 bytes\n  so who cares!)\n\n  ADDING FUNCTIONS\n  ----------------\n\n  To support this new global struct, all functions must now conditionally\n  pass the globals pointer (pG) to each other.  This is supported by 5 macros:\n  __GPRO, __GPRO__, __G, __G__ and __GDEF.  A function that needs no other\n  parameters would look like this:\n\n    int extract_or_test_files(__G)\n      __GDEF\n    {\n       ... stuff ...\n    }\n\n  A function with other parameters would look like:\n\n    int memextract(__G__ tgt, tgtsize, src, srcsize)\n        __GDEF\n        uch *tgt, *src;\n        ulg tgtsize, srcsize;\n    {\n      ... stuff ...\n    }\n\n  In the Function Prototypes section of unzpriv.h, you should use __GPRO and\n  __GPRO__ instead:\n\n    int  uz_opts                   OF((__GPRO__ int *pargc, char ***pargv));\n    int  process_zipfiles          OF((__GPRO));\n\n  Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after\n  __GDEF.  I wish there was another way but I don't think there is.\n\n\n  TESTING THE CODE\n  -----------------\n\n  Whether your platform requires reentrancy or not, you should always try\n  building with REENTRANT defined if any functions have been added.  It is\n  pretty easy to forget a __G__ or a __GDEF and this mistake will only show\n  up if REENTRANT is defined.  All platforms should run with REENTRANT\n  defined.  Platforms that can't take advantage of it will just be paying\n  a performance penalty needlessly.\n\n  SIGNAL MADNESS\n  --------------\n\n  This whole pointer passing scheme falls apart when it comes to SIGNALs.\n  I handle this situation 2 ways right now.  If you define USETHREADID,\n  UnZip will include a 64-entry table.  Each entry can hold a global\n  pointer and thread ID for one thread.  This should allow up to 64\n  threads to access UnZip simultaneously.  Calling DESTROYGLOBALS()\n  will free the global struct and zero the table entry.  If somebody\n  forgets to call DESTROYGLOBALS(), this table will eventually fill up\n  and UnZip will exit with an error message.  A good way to test your\n  code to make sure you didn't forget a DESTROYGLOBALS() is to change\n  THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small.\n  Then make a small test program that calls your API a dozen times.\n\n  Those platforms that don't have threads still need to be able to compile\n  with REENTRANT defined to test and see if new code is correctly written\n  to work either way.  For these platforms, I simply keep a global pointer\n  called GG that points to the Globals structure.  Good enough for testing.\n\n  I believe that NT has thread level storage.  This could probably be used\n  to store a global pointer for the sake of the signal handler more cleanly\n  than my table approach.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __globals_h\n#define __globals_h\n\n#ifdef USE_ZLIB\n#  include \"zlib.h\"\n#  ifdef zlib_version           /* This name is used internally in unzip */\n#    undef zlib_version         /*  and must not be defined as a macro. */\n#  endif\n#endif\n\n#ifdef USE_BZIP2\n#  include \"bzlib.h\"\n#endif\n\n\n/*************/\n/*  Globals  */\n/*************/\n\ntypedef struct Globals {\n#ifdef DLL\n    zvoid *callerglobs; /* pointer to structure of pass-through global vars */\n#endif\n\n    /* command options of general use */\n    UzpOpts UzO;        /* command options of general use */\n\n#ifndef FUNZIP\n    /* command options specific to the high level command line interface */\n#ifdef MORE\n    int M_flag;         /* -M: built-in \"more\" function */\n#endif\n\n    /* internal flags and general globals */\n#ifdef MORE\n    int height;           /* check for SIGWINCH, etc., eventually... */\n    int lines;            /* count of lines displayed on current screen */\n# if (defined(SCREENWIDTH) && defined(SCREENLWRAP))\n    int width;\n    int chars;            /* count of screen characters in current line */\n# endif\n#endif /* MORE */\n#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))\n    int tz_is_valid;      /* indicates that timezone info can be used */\n#endif\n    int noargs;           /* did true command line have *any* arguments? */\n    unsigned filespecs;   /* number of real file specifications to be matched */\n    unsigned xfilespecs;  /* number of excluded filespecs to be matched */\n    int process_all_files;\n    int overwrite_mode;   /* 0 - query, 1 - always, 2 - never */\n    int create_dirs;      /* used by main(), mapname(), checkdir() */\n    int extract_flag;\n    int newzip;           /* reset in extract.c; used in crypt.c */\n    zoff_t   real_ecrec_offset;\n    zoff_t   expect_ecrec_offset;\n    zoff_t   csize;       /* used by decompr. (NEXTBYTE): must be signed */\n    zoff_t   used_csize;  /* used by extract_or_test_member(), explode() */\n\n#ifdef DLL\n     int fValidate;       /* true if only validating an archive */\n     int filenotfound;\n     int redirect_data;   /* redirect data to memory buffer */\n     int redirect_text;   /* redirect text output to buffer */\n# ifndef NO_SLIDE_REDIR\n     int redirect_slide;  /* redirect decompression area to mem buffer */\n#  if (defined(USE_DEFLATE64) && defined(INT_16BIT))\n     ulg _wsize;          /* size of sliding window exceeds \"unsigned\" range */\n#  else\n     unsigned _wsize;     /* sliding window size can be hold in unsigned */\n#  endif\n# endif\n     ulg redirect_size;            /* size of redirected output buffer */\n     uch *redirect_buffer;         /* pointer to head of allocated buffer */\n     uch *redirect_pointer;        /* pointer past end of written data */\n# ifndef NO_SLIDE_REDIR\n     uch *redirect_sldptr;         /* head of decompression slide buffer */\n# endif\n# ifdef OS2DLL\n     cbList(processExternally);    /* call-back list */\n# endif\n#endif /* DLL */\n\n    char **pfnames;\n    char **pxnames;\n    char sig[4];\n    char answerbuf[10];\n    min_info info[DIR_BLKSIZ];\n    min_info *pInfo;\n#endif /* !FUNZIP */\n    union work area;                /* see unzpriv.h for definition of work */\n\n#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\n    ZCONST ulg near *crc_32_tab;\n#else\n    ZCONST ulg Far *crc_32_tab;\n#endif\n    ulg       crc32val;             /* CRC shift reg. (was static in funzip) */\n\n#ifdef FUNZIP\n    FILE      *in;                  /* file descriptor of compressed stream */\n#endif\n    uch       *inbuf;               /* input buffer (any size is OK) */\n    uch       *inptr;               /* pointer into input buffer */\n    int       incnt;\n\n#ifndef FUNZIP\n    ulg       bitbuf;\n    int       bits_left;            /* unreduce and unshrink only */\n    int       zipeof;\n    char      *argv0;               /* used for NT and EXE_EXTENSION */\n    char      *wildzipfn;\n    char      *zipfn;    /* GRR:  WINDLL:  must nuke any malloc'd zipfn... */\n#ifdef USE_STRM_INPUT\n    FILE      *zipfd;               /* zipfile file descriptor */\n#else\n    int       zipfd;                /* zipfile file handle */\n#endif\n    zoff_t    ziplen;\n    zoff_t    cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */\n    zoff_t    extra_bytes;          /* used in unzip.c, misc.c */\n    uch       *extra_field;         /* Unix, VMS, Mac, OS/2, Acorn, ... */\n    uch       *hold;\n\n    local_file_hdr  lrec;          /* used in unzip.c, extract.c */\n    cdir_file_hdr   crec;          /* used in unzip.c, extract.c, misc.c */\n    ecdir_rec       ecrec;         /* used in unzip.c, extract.c */\n    z_stat   statbuf;              /* used by main, mapname, check_for_newer */\n\n    int      mem_mode;\n    uch      *outbufptr;           /* extract.c static */\n    ulg      outsize;              /* extract.c static */\n    int      reported_backslash;   /* extract.c static */\n    int      disk_full;\n    int      newfile;\n\n    int      didCRlast;            /* fileio static */\n    ulg      numlines;             /* fileio static: number of lines printed */\n    int      sol;                  /* fileio static: at start of line */\n    int      no_ecrec;             /* process static */\n#ifdef SYMLINKS\n    int      symlnk;\n    slinkentry *slink_head;        /* pointer to head of symlinks list */\n    slinkentry *slink_last;        /* pointer to last entry in symlinks list */\n#endif\n#ifdef NOVELL_BUG_FAILSAFE\n    int      dne;                  /* true if stat() says file doesn't exist */\n#endif\n\n    FILE     *outfile;\n    uch      *outbuf;\n    uch      *realbuf;\n\n#ifndef VMS                        /* if SMALL_MEM, outbuf2 is initialized in */\n    uch      *outbuf2;             /*  process_zipfiles() (never changes); */\n#endif                             /*  else malloc'd ONLY if unshrink and -a */\n#endif /* !FUNZIP */\n    uch      *outptr;\n    ulg      outcnt;               /* number of chars stored in outbuf */\n#ifndef FUNZIP\n    char     filename[FILNAMSIZ];  /* also used by NT for temporary SFX path */\n#ifdef UNICODE_SUPPORT\n    char     *filename_full;       /* the full path so Unicode checks work */\n    extent   fnfull_bufsize;       /* size of allocated filename buffer */\n    int      unicode_escape_all;\n    int      unicode_mismatch;\n#ifdef UTF8_MAYBE_NATIVE\n    int      native_is_utf8;       /* bool, TRUE => native charset == UTF-8 */\n#endif\n\n    int      unipath_version;      /* version of Unicode field */\n    ulg      unipath_checksum;     /* Unicode field checksum */\n    char     *unipath_filename;    /* UTF-8 path */\n#endif /* UNICODE_SUPPORT */\n\n#ifdef CMS_MVS\n    char     *tempfn;              /* temp file used; erase on close */\n#endif\n\n    char *key;         /* crypt static: decryption password or NULL */\n    int nopwd;         /* crypt static */\n#endif /* !FUNZIP */\n    z_uint4 keys[3];   /* crypt static: keys defining pseudo-random sequence */\n\n#if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS))\n#if (!defined(MACOS) && !defined(ATARI) && !defined(VMS))\n    int echofd;        /* ttyio static: file descriptor whose echo is off */\n#endif /* !(MACOS || ATARI || VMS) */\n#endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */\n\n    unsigned hufts;    /* track memory usage */\n\n#ifdef USE_ZLIB\n    int inflInit;             /* inflate static: zlib inflate() initialized */\n    z_stream dstrm;           /* inflate global: decompression stream */\n#else\n    struct huft *fixed_tl;              /* inflate static */\n    struct huft *fixed_td;              /* inflate static */\n    unsigned fixed_bl, fixed_bd;        /* inflate static */\n#ifdef USE_DEFLATE64\n    struct huft *fixed_tl64;            /* inflate static */\n    struct huft *fixed_td64;            /* inflate static */\n    unsigned fixed_bl64, fixed_bd64;    /* inflate static */\n    struct huft *fixed_tl32;            /* inflate static */\n    struct huft *fixed_td32;            /* inflate static */\n    unsigned fixed_bl32, fixed_bd32;    /* inflate static */\n    ZCONST ush *cplens;                 /* inflate static */\n    ZCONST uch *cplext;                 /* inflate static */\n    ZCONST uch *cpdext;                 /* inflate static */\n#endif\n    unsigned wp;              /* inflate static: current position in slide */\n    ulg bb;                   /* inflate static: bit buffer */\n    unsigned bk;              /* inflate static: bits count in bit buffer */\n#endif /* ?USE_ZLIB */\n\n#ifndef FUNZIP\n    /* cylindric buffer space for formatting zoff_t values (fileio static) */\n    char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];\n    int fzofft_index;\n\n#ifdef SMALL_MEM\n    char rgchBigBuffer[512];\n    char rgchSmallBuffer[96];\n    char rgchSmallBuffer2[160];  /* boosted to 160 for local3[] in unzip.c */\n#endif\n\n    MsgFn *message;\n    InputFn *input;\n    PauseFn *mpause;\n    PasswdFn *decr_passwd;\n    StatCBFn *statreportcb;\n#ifdef WINDLL\n    LPUSERFUNCTIONS lpUserFunctions;\n#endif\n\n    int incnt_leftover;       /* so improved NEXTBYTE does not waste input */\n    uch *inptr_leftover;\n\n#ifdef VMS_TEXT_CONV\n    unsigned VMS_line_length; /* so native VMS variable-length text files */\n    int      VMS_line_state;  /*  are readable on other platforms */\n    int      VMS_line_pad;\n#endif\n\n#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))\n    char autorun_command[FILNAMSIZ];\n#endif\n#endif /* !FUNZIP */\n\n#ifdef SYSTEM_SPECIFIC_GLOBALS\n    SYSTEM_SPECIFIC_GLOBALS\n#endif\n\n} Uz_Globs;  /* end of struct Globals */\n\n\n/***************************************************************************/\n\n\n#define CRC_32_TAB      G.crc_32_tab\n\n\nUz_Globs *globalsCtor   OF((void));\n\n/* pseudo constant sigs; they are initialized at runtime so unzip executable\n * won't look like a zipfile\n */\nextern char local_hdr_sig[4];\nextern char central_hdr_sig[4];\nextern char end_central_sig[4];\nextern char end_central32_sig[4];\nextern char end_central64_sig[4];\nextern char end_centloc64_sig[4];\n/* extern char extd_local_sig[4];  NOT USED YET */\n\n#ifdef REENTRANT\n#  define G                   (*(Uz_Globs *)pG)\n#  define __G                 pG\n#  define __G__               pG,\n#  define __GPRO              Uz_Globs *pG\n#  define __GPRO__            Uz_Globs *pG,\n#  define __GDEF              Uz_Globs *pG;\n#  ifdef  USETHREADID\n     extern int               lastScan;\n     void deregisterGlobalPointer OF((__GPRO));\n     Uz_Globs *getGlobalPointer   OF((void));\n#    define GETGLOBALS()      Uz_Globs *pG = getGlobalPointer()\n#    define DESTROYGLOBALS()  do {free_G_buffers(pG); \\\n                                  deregisterGlobalPointer(pG);} while (0)\n#  else\n     extern Uz_Globs          *GG;\n#    define GETGLOBALS()      Uz_Globs *pG = GG\n#    define DESTROYGLOBALS()  do {free_G_buffers(pG); free(pG);} while (0)\n#  endif /* ?USETHREADID */\n#  define CONSTRUCTGLOBALS()  Uz_Globs *pG = globalsCtor()\n#else /* !REENTRANT */\n   extern Uz_Globs            G;\n#  define __G\n#  define __G__\n#  define __GPRO              void\n#  define __GPRO__\n#  define __GDEF\n#  define GETGLOBALS()\n#  define CONSTRUCTGLOBALS()  globalsCtor()\n#  define DESTROYGLOBALS()\n#endif /* ?REENTRANT */\n\n#define uO              G.UzO\n\n#endif /* __globals_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/human68k/Contents",
    "content": "Contents of the \"human68k\" sub-archive for UnZip 5.50 and later:\n\n  Contents       this file\n  Makefile       (shorter) Makefile for GNU C on X680x0/Human68k\n  human68k.c     Human68k-specific routines for UnZip\n  crc_68.s       assembler version of crc32.c\n  flate.s        assembler version of inflate_codes() (define ASM_INFLATECODES)\n"
  },
  {
    "path": "deps/infozip/unzip60/human68k/crc_68.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_68 created by Paul Kienitz, last modified 04 Jan 96.\n;\n; Return an updated 32 bit CRC value, given the old value and a block of data.\n; The CRC table used to compute the value is gotten by calling get_crc_table().\n; This replaces the older updcrc() function used in Zip and fUnZip.  The\n; prototype of the function is:\n;\n;    ulg crc32(ulg crcval, uch *text, extent textlen);\n;\n; On the Amiga, type extent is always unsigned long, not unsigned int, because\n; int can be short or long at whim, but size_t is long.\n;\n; If using this source on a non-Amiga 680x0 system, note that we treat\n; a0/a1/d0/d1 as scratch registers not preserved across function calls.\n; We do not bother to support registerized arguments for crc32() -- the\n; textlen parm is usually large enough so that savings outside the loop\n; are pointless.\n;\n; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more\n; efficient on certain machines with dinky instruction caches ('020?), or for\n; processing short strings.  If loops are unrolled, the textlen parm must be\n; less than 512K; if not unrolled, it must be less than 64K.\n;\n; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.\n\n        xdef    _crc32          ; (ulg val, uch *buf, extent bufsize)\n\nDO_CRC0 MACRO\n        moveq  #0,ltemp\n        move.b (textbuf)+,ltemp\n        eor.b  crcval,ltemp\n        lsl.w  #2,ltemp\n        move.l (crc_table,ltemp.w),ltemp\n        lsr.l  #8,crcval\n        eor.l  ltemp,crcval\n        ENDM\n\n\nDO_CRC2 MACRO\n        move.b (textbuf)+,btemp\n        eor.b  crcval,btemp\n        lsr.l  #8,crcval\n        move.l (crc_table,btemp.w*4),ltemp\n        eor.l  ltemp,crcval\n        ENDM\n\ncrc_table       reg     a0      array of unsigned long\ncrcval          reg     d0      unsigned long initial value\ntextbuf         reg     a1      array of unsigned char\ntextbufsize     reg     d1      unsigned long (count of bytes in textbuf)\nbtemp           reg     d2\nltemp           reg     d3\n\n\n        xref    _get_crc_table  ; ulg *get_crc_table(void)\n\n\n\n        quad\n_crc32:\n        move.l  8(sp),d0\n        bne.s   valid\n;;;;;   moveq  #0,d0\n         rts\nvalid:  movem.l btemp/ltemp,-(sp)\n        jsr     _get_crc_table\n        movea.l d0,crc_table\n        move.l  12(sp),crcval\n        move.l  16(sp),textbuf\n        move.l  20(sp),textbufsize\n        not.l   crcval\n\n    ifdef   NO_UNROLLED_LOOPS\n\n    if CPU==68000\n        bra.s   decr\nloop:    DO_CRC0\ndecr:    dbra   textbufsize,loop\n        bra.s   done\n\n    else\ntwenty: moveq   #0,btemp\n        bra.s   decr2\nloop2:   DO_CRC2\ndecr2:   dbra   textbufsize,loop2\n    endif\n\n    ELSE    ; !NO_UNROLLED_LOOPS\n\n    if CPU==68000\n        moveq   #7,btemp\n        and     textbufsize,btemp\n        lsr.l   #3,textbufsize\n        bra     decr8\nloop8:   DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\ndecr8:   dbra   textbufsize,loop8\n        bra.s   decr1\nloop1:   DO_CRC0\ndecr1:   dbra   btemp,loop1\n        bra     done\n\n    else\ntwenty: moveq   #0,btemp\n        move.l  textbufsize,-(sp)\n        lsr.l   #3,textbufsize\n        bra     decr82\n         quad\nloop82:  DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\ndecr82:  dbra   textbufsize,loop82\n        moveq   #7,textbufsize\n        and.l   (sp)+,textbufsize\n        bra.s   decr12\nloop12:  DO_CRC2\ndecr12:  dbra   textbufsize,loop12\n    endif\n\n    ENDC    ; ?NO_UNROLLED_LOOPS\n\ndone:   movem.l (sp)+,btemp/ltemp\n        not.l   crcval\n;;;;;   move.l  crcval,d0               ; crcval already is d0\n        rts\n"
  },
  {
    "path": "deps/infozip/unzip60/human68k/flate.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in unzip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; flate.a created by Paul Kienitz, 20 June 94.  Last modified 23 Mar 2002.\n;\n; 68000 assembly language version of inflate_codes(), for Amiga.  Prototype:\n;\n;   int inflate_codes(__GPRO__ struct huft *tl, struct huft *td,\n;                     unsigned bl, unsigned bd);\n;\n; Where __GPRO__ expands to \"Uz_Globs *G,\" if REENTRANT is defined,\n; otherwise to nothing.  In the latter case G is a global variable.\n;\n; Define the symbol FUNZIP if this is for fUnZip.  It overrides REENTRANT.\n;\n; Define AZTEC to use the Aztec C macro version of getc() instead of the\n; library getc() with FUNZIP.  AZTEC is ignored if FUNZIP is not defined.\n;\n; Define NO_CHECK_EOF to not use the fancy paranoid version of NEEDBITS --\n; this is equivalent to removing the #define CHECK_EOF from inflate.c.\n;\n; Define INT16 if ints are short, otherwise it assumes ints are long.\n;\n; Define USE_DEFLATE64 if we're supporting Deflate64 decompression.\n;\n; Do NOT define WSIZE; it is always 32K or 64K depending on USE_DEFLATE64.\n;\n; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.\n\nX:              EQU     $7ffe\n\n                IFDEF   INT16\nMOVINT           MACRO  _1,_2\n        move.w          _1,_2\n                 ENDM\nINTSIZE equ     2\n                ELSE    ; !INT16\nMOVINT           MACRO  _1,_2\n        move.l          _1,_2\n                 ENDM\nINTSIZE equ     4\n                ENDC\n\n                IFDEF   REENTRANT\n                 IFNDEF FUNZIP\nREENT_G equ     1\n                 ENDC\n                ENDC\n\n; The following include file is generated from globals.h, and gives us equates\n; that give the offsets in Uz_Globs of the fields we use, which are:\n;       ulg bb\n;       unsigned int bk, wp\n;       (either array of unsigned char, or pointer to unsigned char) redirslide\n; For fUnZip:\n;       FILE *in\n; For regular UnZip but not fUnZip:\n;       int incnt, mem_mode\n;       long csize\n;       uch *inptr\n; It also defines a value SIZEOF_slide, which tells us whether the appropriate\n; slide field in G (either area.Slide or redirect_pointer) is a pointer or an\n; array instance.  It is 4 in the former case and a large value in the latter.\n; Lastly, this include will define CRYPT as 1 if appropriate.\n\n                IFDEF   FUNZIP\n        INCLUDE  human68k/G_offs_.mac\n                ELSE\n                 IFDEF  SFX\n        INCLUDE  human68k/G_offsf.mac\"\n                 ELSE\n        INCLUDE  human68k/G_offs.mac\n                 ENDC\n                ENDC\n\n; struct huft is defined as follows:\n;\n;   struct huft {\n;     uch e;                /* number of extra bits or operation */\n;     uch b;                /* number of bits in this code or subcode */\n;     union {\n;       ush n;              /* literal, length base, or distance base */\n;       struct huft *t;     /* pointer to next level of table */\n;     } v;\n;   };                      /* sizeof(struct huft) == 6 */\n;\n; The G_offs include defines offsets h_e, h_b, h_v_n, and h_v_t in this\n; struct, plus SIZEOF_huft.\n\n; G.bb is the global buffer that holds bits from the huffman code stream, which\n; we cache in the register variable b.  G.bk is the number of valid bits in it,\n; which we cache in k.  The macros NEEDBITS(n) and DUMPBITS(n) have side effects\n; on b and k.\n\n                IFDEF   REENT_G\nG_SIZE  equ     4\nG_PUSH           MACRO          ; this macro passes \"__G__\" to functions\n        move.l          G,-(sp)\n                 ENDM\n                ELSE\n        xref    _G              ; Uz_Globs\nG_SIZE  equ     0\nG_PUSH           MACRO\n        ds.b            0       ; does nothing; the assembler dislikes MACRO ENDM\n                 ENDM\n                ENDC    ; REENT_G\n\n;;      xref    _mask_bits      ; const unsigned mask_bits[17];\n                IFDEF   FUNZIP\n                 IF     CRYPT\n        xref    _encrypted      ; int -- boolean flag\n        xref    _update_keys    ; int update_keys(__GPRO__ int)\n        xref    _decrypt_byte   ; int decrypt_byte(__GPRO)\n                 ENDC   ; CRYPT\n                ELSE    ; !FUNZIP\n        xref    _memflush       ; int memflush(__GPRO__ uch *, ulg)\n        xref    _readbyte       ; int readbyte(__GPRO)\n                ENDC    ; FUNZIP\n\n        xref    _flush          ; if FUNZIP:  int flush(__GPRO__ ulg)\n                                ; else:  int flush(__GPRO__ uch *, ulg, int)\n\n; Here are our register variables.\n\nb       reg     d2              ; unsigned long\nk       reg     d3              ; unsigned short <= 32\ne       reg     d4              ; unsigned int, mostly used as unsigned char\nw       reg     d5              ; unsigned long (was short before deflate64)\nn       reg     d6              ; unsigned long (was short before deflate64)\nd       reg     d7              ; unsigned int, used as unsigned short\n\nt       reg     a2              ; struct huft *\nlmask   reg     a3              ; ulg *\nG       reg     a6              ; Uz_Globs *\n\n; Couple other items we need:\n\nsavregs reg     d2-d7/a2/a3/a6\n                IFDEF   USE_DEFLATE64\nWSIZE   equ     $10000          ; 64K... be careful not to treat as short!\n                ELSE\nWSIZE   equ     $08000          ; 32K... be careful not to treat as negative!\n                ENDC\nEOF     equ     -1\nINVALID equ     99\n\n; inflate_codes() returns one of the following status codes:\n;          0  OK\n;          1  internal inflate error or EOF on input stream\n;         the following return codes are passed through from FLUSH() errors\n;          50 (PK_DISK)   \"overflow of output space\"\n;          80 (IZ_CTRLC)  \"canceled by user's request\"\n\nRET_OK  equ     0\nRET_ERR equ     1\n\n                IFDEF   FUNZIP\n; This does getc(in).  LIBC version is based on #define getc(fp) in stdio.h\n\nGETC              MACRO\n        xref    _fgetc          ; int fgetc(FILE *)\n        move.l          in-X(G),-(sp)\n        jsr             _fgetc\n        addq.l          #4,sp\n                  ENDM\n                ENDC    ; FUNZIP\n\n; Input depends on the NEXTBYTE macro.  This exists in three different forms.\n; The first two are for fUnZip, with and without decryption.  The last is for\n; regular UnZip with or without decryption.  The resulting byte is returned\n; in d0 as a longword, and d1, a0, and a1 are clobbered.\n\n; FLUSH also has different forms for UnZip and fUnZip.  Arg must be a longword.\n; The same scratch registers are trashed.\n\n                IFDEF   FUNZIP\n\nNEXTBYTE         MACRO\n        move.l   d2,-(sp)\n        GETC\n                  IF    CRYPT\n        tst.w           _encrypted+INTSIZE-2    ; test low word if long\n        beq.s           @nbe\n        MOVINT          d0,-(sp)                ; save thru next call\n        G_PUSH\n        jsr             _decrypt_byte\n        eor.w           d0,G_SIZE+INTSIZE-2(sp) ; becomes arg to update_keys\n        jsr             _update_keys\n        addq            #INTSIZE+G_SIZE,sp\n@nbe:\n                  ENDC  ; !CRYPT\n                  IFEQ INTSIZE-2\n        ext.l           d0              ; assert -1 <= d0 <= 255\n                  ENDC\n        move.l   (sp)+,d2\n                 ENDM\n\nFLUSH            MACRO  _1\n        move.l          d2,-(sp)\n        move.l          _1,-(sp)\n        G_PUSH\n        jsr             _flush\n        addq            #4+G_SIZE,sp\n        move.l          (sp)+,d2\n                 ENDM\n\n                ELSE    ; !FUNZIP\n\nNEXTBYTE         MACRO\n        subq.w          #1,incnt+INTSIZE-2-X(G)   ; treat as short\n        bge.s           @nbs\n                IFNE INTSIZE-2\n        subq.w          #1,incnt-X(G)\n        bge.s           @nbs\n                ENDIF\n        move.l          d2,-(sp)\n        G_PUSH\n        jsr             _readbyte\n                  IFNE G_SIZE\n        addq            #G_SIZE,sp\n                  ENDC\n        move.l          (sp)+,d2\n                  IFEQ 2-INTSIZE\n        ext.l           d0            ; assert -1 <= d0 <= 255\n                  ENDC\n        bra.s           @nbe\n@nbs:   moveq           #0,d0\n        move.l          inptr-X(G),a0\n        move.b          (a0)+,d0\n        move.l          a0,inptr-X(G)\n@nbe:\n                 ENDM\n\nFLUSH            MACRO  _1\n        move.l          d2,-(sp)\n        clr.l           -(sp)                   ; unshrink flag: always false\n        move.l          _1,-(sp)                ; length\n                  IF    SIZEOF_slide>4\n        pea             redirslide-X(G)           ; buffer to flush\n                  ELSE\n        move.l          redirslide-X(G),-(sp)\n                  ENDC\n        G_PUSH\n        tst.w           mem_mode+INTSIZE-2-X(G)   ; test lower word if long\n        beq.s           @fm\n        jsr             _memflush               ; ignores the unshrink flag\n        bra.s           @fe\n@fm:    jsr             _flush\n@fe:    lea             8+INTSIZE+G_SIZE(sp),sp\n        move.l          (sp)+,d2\n                 ENDM\n\n                ENDC    ; ?FUNZIP\n\n; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form:\n;\n;   #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}\n;   #define DUMPBITS(n) {b>>=(n);k-=(n);}\n;\n; Without NO_CHECK_EOF, NEEDBITS reads like this:\n;\n;   {while((int)k<(int)(n)){int c=NEXTBYTE;\n;                           if(c==EOF){if((int)k>=0)break;return 1};\n;                           b|=((ulg)c)<<k;k+=8;}}\n;\n; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg to\n; the macro specifying the number of bits.  The arg can be a shortword memory\n; address, or d2-d7.  The result is copied into d1 as a word ready for masking.\n; DUMPBITS has no side effects; the arg must be a d-register (or immediate in\n; the range 1-8?) and only the lower byte is significant.\n\nNEEDBITS        MACRO   _1\n@nb:    cmp.w           _1,k            ; assert 0 < k <= 32 ... arg may be 0\n        bge.s           @ne             ; signed compare!\n@loop:\n        NEXTBYTE                        ; returns in d0.l\n                 IFNDEF NO_CHECK_EOF\n        cmp.w           #EOF,d0\n        bne.s           @nok\n        tst.w           k\n        bge.s           @ne\n        bra             error_return\n                 ENDC   ; !NO_CHECK_EOF\n@nok:   lsl.l           k,d0\n        or.l            d0,b\n        addq.w          #8,k\n        cmp.w           _1,k            ;bra.s @nb\n        bcs             @loop           ;\n@ne:    move.l          b,d1            ; return a copy of b in d1\n                ENDM\n\nDUMPBITS        MACRO   _1\n        lsr.l           _1,b            ; upper bits of _1 are ignored??\n        sub.b           _1,k\n                ENDM\n\n\n; This is a longword version of the mask_bits constant array:\nlongmasks:      dc.l    $00000000,$00000001,$00000003,$00000007,$0000000F\n                dc.l    $0000001F,$0000003F,$0000007F,$000000FF,$000001FF\n                dc.l    $000003FF,$000007FF,$00000FFF,$00001FFF,$00003FFF\n                dc.l    $00007FFF,$0000FFFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\n\n; ******************************************************************************\n; Here we go, finally:\n\n        xdef    _inflate_codes\n\n_inflate_codes:\n        link            a5,#-8\n        movem.l         savregs,-(sp)\n; 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18|20(a5) = bd... add 4 for REENT_G\n; -4(a5) = ml, -8(a5) = md, both unsigned long.\n; Here we cache some globals and args:\n                IFDEF   REENT_G\n        move.l          8(a5),G\n                ELSE\n        lea             _G,G            ; G is now a global instance\n                IFDEF   X\n        lea             (X,G),G\n                ENDIF\n                ENDC\n        lea             longmasks,lmask\n        move.l          bb-X(G),b\n        MOVINT          bk-X(G),k\n                IFDEF   INT16\n        moveq           #0,w            ; keep this usable as longword\n                ENDC\n        MOVINT          wp-X(G),w\n        moveq           #0,e            ; keep this usable as longword too\n        MOVINT          16+G_SIZE(a5),d0\n        asl.w           #2,d0\n        move.l          (lmask,d0.w),-4(a5)     ; ml = mask_bits[bl]\n        MOVINT          16+INTSIZE+G_SIZE(a5),d0\n        asl.w           #2,d0\n        move.l          (lmask,d0.w),-8(a5)     ; md = mask_bits[bd]\n\nmain_loop:\n        NEEDBITS        14+INTSIZE+G_SIZE(a5)   ; (unsigned) bl\n        and.l           -4(a5),d1               ; ml\n                IFNE SIZEOF_huft-8\n        mulu            #SIZEOF_huft,d1\n                ELSE\n        asl.l           #3,d1\n                ENDC\n        move.l          8+G_SIZE(a5),t          ; tl\n        add.l           d1,t\nnewtop:  move.b         h_b(t),d0\n         DUMPBITS       d0\n         move.b         h_e(t),e\n         cmp.b          #32,e                   ; is it a literal?\n         bne            nonlit                  ; no\n          move.w        h_v_n(t),d0             ; yes\n                IFGT SIZEOF_slide-4\n          lea           redirslide-X(G),a0\n                ELSE\n          move.l        redirslide-X(G),a0\n                ENDC\n          move.b        d0,(a0,w.l)             ; stick in the decoded byte\n          addq.l        #1,w\n          cmp.l         #WSIZE,w\n          blo           main_loop\n           FLUSH        w\n           ext.l        d0                      ; does a test as it casts long\n           bne          return\n           moveq        #0,w\n           bra          main_loop               ; break (newtop loop)\n\nnonlit:  cmp.b          #31,e                   ; is it a length?\n         beq            finish                  ; no, it's the end marker\n         bhi            nonleng                 ; no, it's something else\n          NEEDBITS      e                       ; yes: a duplicate string\n          move.w        e,d0\n          asl.w         #2,d0\n          and.l         (lmask,d0.w),d1\n          moveq         #0,n                    ; cast h_v_n(t) to long\n          move.w        h_v_n(t),n\n          add.l         d1,n                    ; length of block to copy\n          DUMPBITS      e\n          NEEDBITS      14+(2*INTSIZE)+G_SIZE(a5)   ; bd, lower word if long\n          and.l         -8(a5),d1                   ; md\n                IFNE SIZEOF_huft-8\n          mulu          #SIZEOF_huft,d1\n                ELSE\n          asl.l         #3,d1\n                ENDC\n          move.l        12+G_SIZE(a5),t                 ; td\n          add.l         d1,t\ndistop:    move.b       h_b(t),d0\n           DUMPBITS     d0\n           move.b       h_e(t),e\n           cmp.b        #32,e                   ; is it a literal?\n           blo.s        disbrk                  ; then stop doing this\n            cmp.b       #INVALID,e              ; is it bogus?\n            bne.s       disgo\n             bra        error_return            ; then fail\ndisgo:      and.w       #$001F,e\n            NEEDBITS    e\n            move.w      e,d0\n            asl.w       #2,d0\n            and.l       (lmask,d0.w),d1\n                IFNE SIZEOF_huft-8\n            mulu        #SIZEOF_huft,d1\n                ELSE\n            asl.l       #3,d1\n                ENDC\n            move.l      h_v_t(t),t\n            add.l       d1,t\n            bra         distop\ndisbrk:   NEEDBITS      e\n          move.l        e,d0\n          asl.w         #2,d0\n          and.l         (lmask,d0.w),d1\n          move.l        w,d\n          move.w        h_v_n(t),d0     ; assert top word of d0 is zero\n          sub.l         d0,d\n          sub.l         d1,d            ; distance back to copy the block\n          DUMPBITS      e\n\ndocopy:    move.l       #WSIZE,e        ; copy the duplicated string\n           and.l        #WSIZE-1,d      ; ...but first check if the length\n           cmp.l        d,w             ; will overflow the window...\n           blo.s        ddgw\n            sub.l       w,e\n           bra.s        dadw\nddgw:       sub.l       d,e\ndadw:      cmp.l        #$08000,e       ; also, only copy <= 32K, so we can\n           bls.s        dnox            ; use a dbra loop to do it\n            move.l      #$08000,e\ndnox:      cmp.l        n,e\n           bls.s        delen\n            move.l      n,e\ndelen:     sub.l        e,n             ; size of sub-block to copy in this pass\n                IF      SIZEOF_slide>4\n           lea          redirslide-X(G),a0\n                ELSE\n           move.l       redirslide-X(G),a0\n                ENDC\n           move.l       a0,a1\n           add.l        w,a0            ; w and d are valid longwords\n           add.l        d,a1\n; Now at this point we could do tests to see if we should use an optimized\n; large block copying method such as movem's, but since (a) such methods require\n; the source and destination to be compatibly aligned -- and odd bytes at each\n; end have to be handled separately, (b) it's only worth checking for if the\n; block is pretty large, and (c) most strings are only a few bytes long, we're\n; just not going to bother.  Therefore we check above to make sure we move at\n; most 32K in one sub-block, so a dbra loop can handle it.\ndshort:    move.l       e,d0\n           subq         #1,d0           ; assert >= 0\ndspin:      move.b      (a1)+,(a0)+\n            dbra        d0,dspin\n           add.l        e,w\n           add.l        e,d\n           cmp.l        #WSIZE,w\n           blo.s        dnfl\n            FLUSH       w\n            ext.l       d0              ; does a test as it casts to long\n            bne         return\n            moveq       #0,w\ndnfl:      tst.l        n               ; need to do more sub-blocks?\n           bne          docopy          ; yes\n          moveq         #0,e            ; restore zeroness in upper bytes of e\n          bra           main_loop       ; break (newtop loop)\n\nnonleng: cmp.w          #INVALID,e      ; bottom of newtop loop -- misc. code\n         bne.s          tailgo          ; invalid code?\n          bra           error_return    ; then fail\ntailgo:  and.w          #$001F,e\n         NEEDBITS       e\n         move.w         e,d0\n         asl.w          #2,d0\n         and.l          (lmask,d0.w),d1\n                IFNE SIZEOF_huft-8\n         mulu           #SIZEOF_huft,d1\n                ELSE\n         asl.l          #3,d1\n                ENDC\n         move.l         h_v_t(t),t\n         add.l          d1,t\n         bra            newtop\n\nfinish: MOVINT          w,wp-X(G)       ; done: restore cached globals\n        MOVINT          k,bk-X(G)\n        move.l          b,bb-X(G)\n        moveq           #RET_OK,d0      ; return \"no error\"\nreturn: movem.l         (sp)+,savregs\n        unlk            a5\n        rts\n\nerror_return:\n        moveq           #RET_ERR,d0     ; return \"error occured\"\n        bra             return\n"
  },
  {
    "path": "deps/infozip/unzip60/human68k/human68k.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  human68k.c\n\n  Human68k-specific routines for use with Info-ZIP's UnZip 5.41 and later.\n\n  Contains:  do_wild()\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             stamp_file()                   (TIMESTAMP only)\n             version()\n             main()                         (for UnZipSFX)\n\n  ---------------------------------------------------------------------------*/\n\n\n#include <dirent.h>\n#include <string.h>\n#include <sys/dos.h>\n#include <sys/xunistd.h>\n#ifdef HAVE_TWONCALL_H\n#include <twoncall.h>\n#endif\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#if defined (SFX) && defined (MAIN)\n#include <sys/xstart.h>\nint MAIN(int argc, char *argv[]);\n#endif\n\nstatic void map2fat(char *pathcomp, char *last_dot);\nstatic char *trunc_name(char *name, int maxlen);\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\nstatic char multi_period, special_char;\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            wild_dir = (DIR *)NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == NULL) {\n                Info(slide, 1, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strcpy(matchname, wildspec);\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n        Trace((stderr, \"do_wild:  dirname = [%s]\\n\", FnFilter1(dirname)));\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n#ifdef DEBUG\n        else {\n            Trace((stderr, \"do_wild:  Opendir(%s) returns NULL\\n\",\n              FnFilter1(dirname)));\n        }\n#endif /* DEBUG */\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 == case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg  tmp = G.crec.external_file_attributes;\n\n    switch (G.pInfo->hostnum) {\n        case UNIX_:\n            if (tmp & 0xff)\n                break;\n            /* fall through */\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n            G.pInfo->file_attr = _mode2dos(tmp >> 16);\n            return 0;\n        default:\n            break;\n    }\n\n    /* set archive bit (file is not backed up) */\n    if((tmp & 0x08) == 0)\n        tmp |= 0x20;\n    G.pInfo->file_attr = tmp & 0xff;\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/**********************/\n/* Function mapname() */\n/**********************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    char *last_dot=(char *)NULL;   /* last dot */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n#ifdef HAVE_TWONCALL_H\n    static char twentyone_flag;\n\n    /* Get TwentyOne options */\n    if (twentyone_flag == 0) {\n        twentyone_flag++;\n        if (GetTwentyOneID () == TWON_ID) {\n            int flags = GetTwentyOneOptions ();\n\n            if (flags & (1 << TWON_PERIOD_BIT))\n                multi_period = TRUE;\n            if (flags & (1 << TWON_SPECIAL_BIT))\n                special_char = TRUE;\n        }\n    }\n#endif\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n    renamed_fullpath = FALSE;\n\n    if (renamed) {\n        cp = G.filename - 1;    /* point to beginning of renamed name... */\n        while (*++cp)\n            if (*cp == '\\\\')    /* convert backslashes to forward */\n                *cp = '/';\n        cp = G.filename;\n        if ((G.filename[0] == '/')\n         || (isalpha(G.filename[0]) && G.filename[1] == ':')) {\n            /* user gave full pathname:  don't prepend rootpath */\n            renamed_fullpath = TRUE;\n        }\n    }\n\n    if ((error = checkdir(__G__ (char *)NULL, INIT)) != 0)\n        return error;           /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        if (_ismbblead((unsigned char)workch)) {\n            if (*cp) {\n                *pp++ = (char)workch;\n                *pp++ = (char)*cp++;\n            }\n            else\n                *pp++ = '_';\n            continue;\n        }\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                map2fat(pathcomp, last_dot);   /* 18.3 trunc. (in place) */\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            /* drive names are not stored in zipfile, so no colons allowed;\n             *  no brackets or most other punctuation either (all of which\n             *  can appear in Unix-created archives; backslash is particularly\n             *  bad unless all necessary directories exist) */\n\n            case '[':          /* these punctuation characters forbidden */\n            case ']':          /*  only on plain FAT file systems */\n            case '+':\n            case ',':\n            case '=':\n            case '<':\n            case '>':\n            case '|':\n            case '\\\"':\n            case '\\'':\n                if (!special_char)\n                    workch = '_';\n                *pp++ = (char)workch;\n                break;\n\n            case '-':\n                if (pp == pathcomp && !special_char)\n                    workch = '_';\n                *pp++ = (char)workch;\n                break;\n\n            case ':':\n            case '\\\\':\n            case '*':\n            case '?':\n                *pp++ = '_';\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                if (!special_char)\n                    workch = '_';\n                *pp++ = (char)workch;  /* keep for now; remove VMS \";##\" */\n                break;                 /*  later, if requested */\n\n            case ' ':                      /* change spaces to underscores */\n#if 0  /* do it always */\n                if (uO.sflag)              /*  only if requested */\n#endif\n                    workch = '_';\n                *pp++ = (char)workch;\n                break;\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || workch >= 128)\n                    *pp++ = (char)workch;\n\n        } /* end switch */\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    map2fat(pathcomp, last_dot);  /* 18.3 truncation (in place) */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    if (G.pInfo->vollabel) {    /* set the volume label now */\n        int fd;\n\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"  labelling: %s\\n\",\n              FnFilter1(G.filename)));\n        if ((fd = _dos_newfile(G.filename, G.pInfo->file_attr)) < 0) {\n            Info(slide, 1, ((char *)slide,\n              \"mapname:  error setting volume label\\n\"));\n            return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n        }\n        _dos_close(fd);\n        /* success:  skip the \"extraction\" quietly */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/**********************/\n/* Function map2fat() */\n/**********************/\n\nstatic void map2fat(pathcomp, last_dot)\n    char *pathcomp, *last_dot;\n{\n    char *np;\n\n    if (pathcomp == last_dot) {         /* dotfile(e.g. \".foo\") */\n        pathcomp = last_dot;\n        last_dot = (char *)NULL;\n    }\n\n    if (multi_period) {\n        if (strlen(pathcomp) <= 18)\n            return;\n    }\n    else {\n        char *p;\n\n        for (p = pathcomp; *p; p++)\n            if (*p == (char)'.' && p != last_dot)\n                *p = '_';\n    }\n\n    if (last_dot) {\n        *last_dot++ = '\\0';\n        trunc_name(last_dot, 3);\n    }\n    np = trunc_name(pathcomp, 18);\n    if (last_dot) {\n        *--last_dot = '.';\n        if (np)\n            strcpy(np, last_dot);\n    }\n\n} /* end function map2fat() */\n\nstatic char *trunc_name(char *name, int maxlen)\n{\n\n    if (strlen(name) <= maxlen)\n        return (char *)NULL;\n\n    do {\n        if (_ismbblead((unsigned char)*name)) {\n            if (--maxlen == 0)\n                break;\n            name++;\n        }\n        name++;\n        maxlen--;\n    } while (maxlen > 0);\n    *name = '\\0';\n\n    return name;\n}\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (SSTAT(buildpath, &G.statbuf))   /* path doesn't exist */\n        {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        /* allocate space for full filename, root path, and maybe \"./\" */\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) ==\n            (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n                has_drive = TRUE;   /* drive designator */\n            if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\\\') {\n                tmproot[--rootlen] = '\\0';\n                had_trailing_pathsep = TRUE;\n            }\n            if (has_drive && (rootlen == 2)) {\n                if (!had_trailing_pathsep)   /* i.e., original wasn't \"x:/\" */\n                    add_dot = TRUE;    /* relative path: add '.' before '/' */\n            } else if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                       !S_ISDIR(G.statbuf.st_mode))) /* path does not exist */\n            {\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n                tmproot[rootlen++] = '.';\n            tmproot[rootlen++] = '/';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n#if (defined(USE_EF_UT_TIME) || defined(TIMESTAMP))\n/* The following DOS date/time structure is machine-dependent as it\n * assumes \"little-endian\" byte order.  For MSDOS-specific code, which\n * is run on ix86 CPUs (or emulators), this assumption is valid; but\n * care should be taken when using this code as template for other ports.\n */\ntypedef union {\n    ulg z_dostime;\n    struct {                    /* date and time words */\n        ush ztime;              /* DOS file modification time word */\n        ush zdate;              /* DOS file modification date word */\n    } zft;\n    struct {                    /* DOS date/time components bitfield */\n        unsigned zt_se : 5;\n        unsigned zt_mi : 6;\n        unsigned zt_hr : 5;\n        unsigned zd_dy : 5;\n        unsigned zd_mo : 4;\n        unsigned zd_yr : 7;\n    } z_dtf;\n} dos_fdatetime;\n#endif /* USE_EF_UT_TIME || TIMESTAMP */\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        dos_fdatetime dos_dt;\n        iztimes z_utime;\n        struct tm *t;\n#endif /* USE_EF_UT_TIME */\n\n\n#ifdef USE_EF_UT_TIME\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                              G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n             & EB_UT_FL_MTIME))\n        {\n            TTrace((stderr, \"close_outfile:  Unix e.f. modif. time = %ld\\n\",\n              z_utime.mtime));\n            /* round up (down if \"up\" overflows) to even seconds */\n            if (z_utime.mtime & 1)\n                z_utime.mtime = (z_utime.mtime + 1 > z_utime.mtime) ?\n                                 z_utime.mtime + 1 : z_utime.mtime - 1;\n            TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7 or Macintosh */\n            t = localtime(&(z_utime.mtime));\n        } else\n            t = (struct tm *)NULL;\n        if (t != (struct tm *)NULL) {\n            if (t->tm_year < 80) {\n                dos_dt.z_dtf.zt_se = 0;\n                dos_dt.z_dtf.zt_mi = 0;\n                dos_dt.z_dtf.zt_hr = 0;\n                dos_dt.z_dtf.zd_dy = 1;\n                dos_dt.z_dtf.zd_mo = 1;\n                dos_dt.z_dtf.zd_yr = 0;\n            } else {\n                dos_dt.z_dtf.zt_se = t->tm_sec >> 1;\n                dos_dt.z_dtf.zt_mi = t->tm_min;\n                dos_dt.z_dtf.zt_hr = t->tm_hour;\n                dos_dt.z_dtf.zd_dy = t->tm_mday;\n                dos_dt.z_dtf.zd_mo = t->tm_mon + 1;\n                dos_dt.z_dtf.zd_yr = t->tm_year - 80;\n            }\n        } else {\n            dos_dt.z_dostime = G.lrec.last_mod_dos_datetime;\n        }\n        _dos_filedate(fileno(G.outfile), dos_dt.z_dostime);\n#else /* !USE_EF_UT_TIME */\n        _dos_filedate(fileno(G.outfile), G.lrec.last_mod_dos_datetime);\n#endif /* ?USE_EF_UT_TIME */\n    }\n\n    fclose(G.outfile);\n\n    _dos_chmod(G.filename, G.pInfo->file_attr);\n\n} /* end function close_outfile() */\n\n\n\n\n\n#ifdef TIMESTAMP\n\n/*************************/\n/* Function stamp_file() */\n/*************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    dos_fdatetime dos_dt;\n    time_t t_even;\n    struct tm *t;\n    int fd;                             /* file handle */\n\n    /* round up (down if \"up\" overflows) to even seconds */\n    t_even = ((modtime + 1 > modtime) ? modtime + 1 : modtime) & (~1);\n    TIMET_TO_NATIVE(t_even)             /* NOP unless MSC 7.0 or Macintosh */\n    t = localtime(&t_even);\n    if (t == (struct tm *)NULL)\n        return -1;                      /* time conversion error */\n    if (t->tm_year < 80) {\n        dos_dt.z_dtf.zt_se = 0;\n        dos_dt.z_dtf.zt_mi = 0;\n        dos_dt.z_dtf.zt_hr = 0;\n        dos_dt.z_dtf.zd_dy = 1;\n        dos_dt.z_dtf.zd_mo = 1;\n        dos_dt.z_dtf.zd_yr = 0;\n    } else {\n        dos_dt.z_dtf.zt_se = t->tm_sec >> 1;\n        dos_dt.z_dtf.zt_mi = t->tm_min;\n        dos_dt.z_dtf.zt_hr = t->tm_hour;\n        dos_dt.z_dtf.zd_dy = t->tm_mday;\n        dos_dt.z_dtf.zd_mo = t->tm_mon + 1;\n        dos_dt.z_dtf.zd_yr = t->tm_year - 80;\n    }\n    if (((fd = open((char *)fname, 0)) == -1) ||\n        (_dos_filedate(fd, dos_dt.z_dostime)))\n    {\n        if (fd != -1)\n            close(fd);\n        return -1;\n    }\n    close(fd);\n    return 0;\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#if 0\n    char buf[40];\n#endif\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#endif\n\n      \"Human68k\",\n#ifdef __MC68020__\n      \" (X68030)\",\n#else\n      \" (X680x0)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n#if defined (SFX) && defined (MAIN)\nint main(int argc, char *argv[])\n{\n    char argv0[92];\n\n    /* make true argv[0] (startup routine makes it inaccuracy) */\n    argv[0] = strcat (strcpy (argv0, _procp->exe_path), _procp->exe_name);\n\n    return MAIN(argc, argv);\n}\n#endif /* SFX && MAIN */\n"
  },
  {
    "path": "deps/infozip/unzip60/inflate.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* inflate.c -- by Mark Adler\n   version c17e, 30 Mar 2007 */\n\n\n/* Copyright history:\n   - Starting with UnZip 5.41 of 16-April-2000, this source file\n     is covered by the Info-Zip LICENSE cited above.\n   - Prior versions of this source file, found in UnZip source packages\n     up to UnZip 5.40, were put in the public domain.\n     The original copyright note by Mark Adler was:\n         \"You can do whatever you like with this source file,\n         though I would prefer that if you modify it and\n         redistribute it that you include comments to that effect\n         with your name and the date.  Thank you.\"\n\n   History:\n   vers    date          who           what\n   ----  ---------  --------------  ------------------------------------\n    a    ~~ Feb 92  M. Adler        used full (large, one-step) lookup table\n    b1   21 Mar 92  M. Adler        first version with partial lookup tables\n    b2   21 Mar 92  M. Adler        fixed bug in fixed-code blocks\n    b3   22 Mar 92  M. Adler        sped up match copies, cleaned up some\n    b4   25 Mar 92  M. Adler        added prototypes; removed window[] (now\n                                    is the responsibility of unzip.h--also\n                                    changed name to slide[]), so needs diffs\n                                    for unzip.c and unzip.h (this allows\n                                    compiling in the small model on MSDOS);\n                                    fixed cast of q in huft_build();\n    b5   26 Mar 92  M. Adler        got rid of unintended macro recursion.\n    b6   27 Mar 92  M. Adler        got rid of nextbyte() routine.  fixed\n                                    bug in inflate_fixed().\n    c1   30 Mar 92  M. Adler        removed lbits, dbits environment variables.\n                                    changed BMAX to 16 for explode.  Removed\n                                    OUTB usage, and replaced it with flush()--\n                                    this was a 20% speed improvement!  Added\n                                    an explode.c (to replace unimplod.c) that\n                                    uses the huft routines here.  Removed\n                                    register union.\n    c2    4 Apr 92  M. Adler        fixed bug for file sizes a multiple of 32k.\n    c3   10 Apr 92  M. Adler        reduced memory of code tables made by\n                                    huft_build significantly (factor of two to\n                                    three).\n    c4   15 Apr 92  M. Adler        added NOMEMCPY do kill use of memcpy().\n                                    worked around a Turbo C optimization bug.\n    c5   21 Apr 92  M. Adler        added the WSIZE #define to allow reducing\n                                    the 32K window size for specialized\n                                    applications.\n    c6   31 May 92  M. Adler        added some typecasts to eliminate warnings\n    c7   27 Jun 92  G. Roelofs      added some more typecasts (444:  MSC bug).\n    c8    5 Oct 92  J-l. Gailly     added ifdef'd code to deal with PKZIP bug.\n    c9    9 Oct 92  M. Adler        removed a memory error message (~line 416).\n    c10  17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch,\n                                    removed old inflate, renamed inflate_entry\n                                    to inflate, added Mark's fix to a comment.\n   c10.5 14 Dec 92  M. Adler        fix up error messages for incomplete trees.\n    c11   2 Jan 93  M. Adler        fixed bug in detection of incomplete\n                                    tables, and removed assumption that EOB is\n                                    the longest code (bad assumption).\n    c12   3 Jan 93  M. Adler        make tables for fixed blocks only once.\n    c13   5 Jan 93  M. Adler        allow all zero length codes (pkzip 2.04c\n                                    outputs one zero length code for an empty\n                                    distance tree).\n    c14  12 Mar 93  M. Adler        made inflate.c standalone with the\n                                    introduction of inflate.h.\n   c14b  16 Jul 93  G. Roelofs      added (unsigned) typecast to w at 470.\n   c14c  19 Jul 93  J. Bush         changed v[N_MAX], l[288], ll[28x+3x] arrays\n                                    to static for Amiga.\n   c14d  13 Aug 93  J-l. Gailly     de-complicatified Mark's c[*p++]++ thing.\n   c14e   8 Oct 93  G. Roelofs      changed memset() to memzero().\n   c14f  22 Oct 93  G. Roelofs      renamed quietflg to qflag; made Trace()\n                                    conditional; added inflate_free().\n   c14g  28 Oct 93  G. Roelofs      changed l/(lx+1) macro to pointer (Cray bug)\n   c14h   7 Dec 93  C. Ghisler      huft_build() optimizations.\n   c14i   9 Jan 94  A. Verheijen    set fixed_t{d,l} to NULL after freeing;\n                    G. Roelofs      check NEXTBYTE macro for EOF.\n   c14j  23 Jan 94  G. Roelofs      removed Ghisler \"optimizations\"; ifdef'd\n                                    EOF check.\n   c14k  27 Feb 94  G. Roelofs      added some typecasts to avoid warnings.\n   c14l   9 Apr 94  G. Roelofs      fixed split comments on preprocessor lines\n                                    to avoid bug in Encore compiler.\n   c14m   7 Jul 94  P. Kienitz      modified to allow assembler version of\n                                    inflate_codes() (define ASM_INFLATECODES)\n   c14n  22 Jul 94  G. Roelofs      changed fprintf to macro for DLL versions\n   c14o  23 Aug 94  C. Spieler      added a newline to a debug statement;\n                    G. Roelofs      added another typecast to avoid MSC warning\n   c14p   4 Oct 94  G. Roelofs      added (voidp *) cast to free() argument\n   c14q  30 Oct 94  G. Roelofs      changed fprintf macro to MESSAGE()\n   c14r   1 Nov 94  G. Roelofs      fixed possible redefinition of CHECK_EOF\n   c14s   7 May 95  S. Maxwell      OS/2 DLL globals stuff incorporated;\n                    P. Kienitz      \"fixed\" ASM_INFLATECODES macro/prototype\n   c14t  18 Aug 95  G. Roelofs      added UZinflate() to use zlib functions;\n                                    changed voidp to zvoid; moved huft_build()\n                                    and huft_free() to end of file\n   c14u   1 Oct 95  G. Roelofs      moved G into definition of MESSAGE macro\n   c14v   8 Nov 95  P. Kienitz      changed ASM_INFLATECODES to use a regular\n                                    call with __G__ instead of a macro\n    c15   3 Aug 96  M. Adler        fixed bomb-bug on random input data (Adobe)\n   c15b  24 Aug 96  M. Adler        more fixes for random input data\n   c15c  28 Mar 97  G. Roelofs      changed USE_ZLIB fatal exit code from\n                                    PK_MEM2 to PK_MEM3\n    c16  20 Apr 97  J. Altman       added memzero(v[]) in huft_build()\n   c16b  29 Mar 98  C. Spieler      modified DLL code for slide redirection\n   c16c  04 Apr 99  C. Spieler      fixed memory leaks when processing gets\n                                    stopped because of input data errors\n   c16d  05 Jul 99  C. Spieler      take care of FLUSH() return values and\n                                    stop processing in case of errors\n    c17  31 Dec 00  C. Spieler      added preliminary support for Deflate64\n   c17a  04 Feb 01  C. Spieler      complete integration of Deflate64 support\n   c17b  16 Feb 02  C. Spieler      changed type of \"extra bits\" arrays and\n                                    corresponding huft_build() parameter e from\n                                    ush into uch, to save space\n   c17c   9 Mar 02  C. Spieler      fixed NEEDBITS() \"read beyond EOF\" problem\n                                    with CHECK_EOF enabled\n   c17d  23 Jul 05  C. Spieler      fixed memory leaks in inflate_dynamic()\n                                    when processing invalid compressed literal/\n                                    distance table data\n   c17e  30 Mar 07  C. Spieler      in inflate_dynamic(), initialize tl and td\n                                    to prevent freeing unallocated huft tables\n                                    when processing invalid compressed data and\n                                    hitting premature EOF, do not reuse td as\n                                    temp work ptr during tables decoding\n */\n\n\n/*\n   Inflate deflated (PKZIP's method 8 compressed) data.  The compression\n   method searches for as much of the current string of bytes (up to a\n   length of 258) in the previous 32K bytes.  If it doesn't find any\n   matches (of at least length 3), it codes the next byte.  Otherwise, it\n   codes the length of the matched string and its distance backwards from\n   the current position.  There is a single Huffman code that codes both\n   single bytes (called \"literals\") and match lengths.  A second Huffman\n   code codes the distance information, which follows a length code.  Each\n   length or distance code actually represents a base value and a number\n   of \"extra\" (sometimes zero) bits to get to add to the base value.  At\n   the end of each deflated block is a special end-of-block (EOB) literal/\n   length code.  The decoding process is basically: get a literal/length\n   code; if EOB then done; if a literal, emit the decoded byte; if a\n   length then get the distance and emit the referred-to bytes from the\n   sliding window of previously emitted data.\n\n   There are (currently) three kinds of inflate blocks: stored, fixed, and\n   dynamic.  The compressor outputs a chunk of data at a time and decides\n   which method to use on a chunk-by-chunk basis.  A chunk might typically\n   be 32K to 64K, uncompressed.  If the chunk is uncompressible, then the\n   \"stored\" method is used.  In this case, the bytes are simply stored as\n   is, eight bits per byte, with none of the above coding.  The bytes are\n   preceded by a count, since there is no longer an EOB code.\n\n   If the data are compressible, then either the fixed or dynamic methods\n   are used.  In the dynamic method, the compressed data are preceded by\n   an encoding of the literal/length and distance Huffman codes that are\n   to be used to decode this block.  The representation is itself Huffman\n   coded, and so is preceded by a description of that code.  These code\n   descriptions take up a little space, and so for small blocks, there is\n   a predefined set of codes, called the fixed codes.  The fixed method is\n   used if the block ends up smaller that way (usually for quite small\n   chunks); otherwise the dynamic method is used.  In the latter case, the\n   codes are customized to the probabilities in the current block and so\n   can code it much better than the pre-determined fixed codes can.\n\n   The Huffman codes themselves are decoded using a multi-level table\n   lookup, in order to maximize the speed of decoding plus the speed of\n   building the decoding tables.  See the comments below that precede the\n   lbits and dbits tuning parameters.\n\n   GRR:  return values(?)\n           0  OK\n           1  incomplete table\n           2  bad input\n           3  not enough memory\n         the following return codes are passed through from FLUSH() errors\n           50 (PK_DISK)   \"overflow of output space\"\n           80 (IZ_CTRLC)  \"canceled by user's request\"\n */\n\n\n/*\n   Notes beyond the 1.93a appnote.txt:\n\n   1. Distance pointers never point before the beginning of the output\n      stream.\n   2. Distance pointers can point back across blocks, up to 32k away.\n   3. There is an implied maximum of 7 bits for the bit length table and\n      15 bits for the actual data.\n   4. If only one code exists, then it is encoded using one bit.  (Zero\n      would be more efficient, but perhaps a little confusing.)  If two\n      codes exist, they are coded using one bit each (0 and 1).\n   5. There is no way of sending zero distance codes--a dummy must be\n      sent if there are none.  (History: a pre 2.0 version of PKZIP would\n      store blocks with no distance codes, but this was discovered to be\n      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow\n      zero distance codes, which is sent as one code of zero bits in\n      length.\n   6. There are up to 286 literal/length codes.  Code 256 represents the\n      end-of-block.  Note however that the static length tree defines\n      288 codes just to fill out the Huffman codes.  Codes 286 and 287\n      cannot be used though, since there is no length base or extra bits\n      defined for them.  Similarily, there are up to 30 distance codes.\n      However, static trees define 32 codes (all 5 bits) to fill out the\n      Huffman codes, but the last two had better not show up in the data.\n   7. Unzip can check dynamic Huffman blocks for complete code sets.\n      The exception is that a single code would not be complete (see #4).\n   8. The five bits following the block type is really the number of\n      literal codes sent minus 257.\n   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits\n      (1+6+6).  Therefore, to output three times the length, you output\n      three codes (1+1+1), whereas to output four times the same length,\n      you only need two codes (1+3).  Hmm.\n  10. In the tree reconstruction algorithm, Code = Code + Increment\n      only if BitLength(i) is not zero.  (Pretty obvious.)\n  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)\n  12. Note: length code 284 can represent 227-258, but length code 285\n      really is 258.  The last length deserves its own, short code\n      since it gets used a lot in very redundant files.  The length\n      258 is special since 258 - 3 (the min match length) is 255.\n  13. The literal/length and distance code bit lengths are read as a\n      single stream of lengths.  It is possible (and advantageous) for\n      a repeat code (16, 17, or 18) to go across the boundary between\n      the two sets of lengths.\n  14. The Deflate64 (PKZIP method 9) variant of the compression algorithm\n      differs from \"classic\" deflate in the following 3 aspect:\n      a) The size of the sliding history window is expanded to 64 kByte.\n      b) The previously unused distance codes #30 and #31 code distances\n         from 32769 to 49152 and 49153 to 65536.  Both codes take 14 bits\n         of extra data to determine the exact position in their 16 kByte\n         range.\n      c) The last lit/length code #285 gets a different meaning. Instead\n         of coding a fixed maximum match length of 258, it is used as a\n         \"generic\" match length code, capable of coding any length from\n         3 (min match length + 0) to 65538 (min match length + 65535).\n         This means that the length code #285 takes 16 bits (!) of uncoded\n         extra data, added to a fixed min length of 3.\n      Changes a) and b) would have been transparent for valid deflated\n      data, but change c) requires to switch decoder configurations between\n      Deflate and Deflate64 modes.\n */\n\n\n#define PKZIP_BUG_WORKAROUND    /* PKZIP 1.93a problem--live with it */\n\n/*\n    inflate.h must supply the uch slide[WSIZE] array, the zvoid typedef\n    (void if (void *) is accepted, else char) and the NEXTBYTE,\n    FLUSH() and memzero macros.  If the window size is not 32K, it\n    should also define WSIZE.  If INFMOD is defined, it can include\n    compiled functions to support the NEXTBYTE and/or FLUSH() macros.\n    There are defaults for NEXTBYTE and FLUSH() below for use as\n    examples of what those functions need to do.  Normally, you would\n    also want FLUSH() to compute a crc on the data.  inflate.h also\n    needs to provide these typedefs:\n\n        typedef unsigned char uch;\n        typedef unsigned short ush;\n        typedef unsigned long ulg;\n\n    This module uses the external functions malloc() and free() (and\n    probably memset() or bzero() in the memzero() macro).  Their\n    prototypes are normally found in <string.h> and <stdlib.h>.\n */\n\n#define __INFLATE_C     /* identifies this source module */\n\n/* #define DEBUG */\n#define INFMOD          /* tell inflate.h to include code to be compiled */\n#include \"inflate.h\"\n\n\n/* marker for \"unused\" huft code, and corresponding check macro */\n#define INVALID_CODE 99\n#define IS_INVALID_CODE(c)  ((c) == INVALID_CODE)\n\n#ifndef WSIZE               /* default is 32K resp. 64K */\n#  ifdef USE_DEFLATE64\n#    define WSIZE   65536L  /* window size--must be a power of two, and */\n#  else                     /*  at least 64K for PKZip's deflate64 method */\n#    define WSIZE   0x8000  /* window size--must be a power of two, and */\n#  endif                    /*  at least 32K for zip's deflate method */\n#endif\n\n/* some buffer counters must be capable of holding 64k for Deflate64 */\n#if (defined(USE_DEFLATE64) && defined(INT_16BIT))\n#  define UINT_D64 ulg\n#else\n#  define UINT_D64 unsigned\n#endif\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n#  define wsize G._wsize    /* wsize is a variable */\n#else\n#  define wsize WSIZE       /* wsize is a constant */\n#endif\n\n\n#ifndef NEXTBYTE        /* default is to simply get a byte from stdin */\n#  define NEXTBYTE getchar()\n#endif\n\n#ifndef MESSAGE   /* only used twice, for fixed strings--NOT general-purpose */\n#  define MESSAGE(str,len,flag)  fprintf(stderr,(char *)(str))\n#endif\n\n#ifndef FLUSH           /* default is to simply write the buffer to stdout */\n#  define FLUSH(n) \\\n    (((extent)fwrite(redirSlide, 1, (extent)(n), stdout) == (extent)(n)) ? \\\n     0 : PKDISK)\n#endif\n/* Warning: the fwrite above might not work on 16-bit compilers, since\n   0x8000 might be interpreted as -32,768 by the library function.  When\n   support for Deflate64 is enabled, the window size is 64K and the\n   simple fwrite statement is definitely broken for 16-bit compilers. */\n\n#ifndef Trace\n#  ifdef DEBUG\n#    define Trace(x) fprintf x\n#  else\n#    define Trace(x)\n#  endif\n#endif\n\n\n/*---------------------------------------------------------------------------*/\n#ifdef USE_ZLIB\n\n/* Beginning with zlib version 1.2.0, a new inflate callback interface is\n   provided that allows tighter integration of the zlib inflate service\n   into unzip's extraction framework.\n   The advantages are:\n   - uses the windows buffer supplied by the unzip code; this saves one\n     copy process between zlib's internal decompression buffer and unzip's\n     post-decompression output buffer and improves performance.\n   - does not pull in unused checksum code (adler32).\n   The preprocessor flag NO_ZLIBCALLBCK can be set to force usage of the\n   old zlib 1.1.x interface, for testing purpose.\n */\n#ifdef USE_ZLIB_INFLATCB\n#  undef USE_ZLIB_INFLATCB\n#endif\n#if (defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1200 && !defined(NO_ZLIBCALLBCK))\n#  define USE_ZLIB_INFLATCB 1\n#else\n#  define USE_ZLIB_INFLATCB 0\n#endif\n\n/* Check for incompatible combinations of zlib and Deflate64 support. */\n#if defined(USE_DEFLATE64)\n# if !USE_ZLIB_INFLATCB\n  #error Deflate64 is incompatible with traditional (pre-1.2.x) zlib interface!\n# else\n   /* The Deflate64 callback function in the framework of zlib 1.2.x requires\n      the inclusion of the unsupported infback9 header file:\n    */\n#  include \"infback9.h\"\n# endif\n#endif /* USE_DEFLATE64 */\n\n\n#if USE_ZLIB_INFLATCB\n\nstatic unsigned zlib_inCB OF((void FAR *pG, unsigned char FAR * FAR * pInbuf));\nstatic int zlib_outCB OF((void FAR *pG, unsigned char FAR *outbuf,\n                          unsigned outcnt));\n\nstatic unsigned zlib_inCB(pG, pInbuf)\n    void FAR *pG;\n    unsigned char FAR * FAR * pInbuf;\n{\n    *pInbuf = G.inbuf;\n    return fillinbuf(__G);\n}\n\nstatic int zlib_outCB(pG, outbuf, outcnt)\n    void FAR *pG;\n    unsigned char FAR *outbuf;\n    unsigned outcnt;\n{\n#ifdef FUNZIP\n    return flush(__G__ (ulg)(outcnt));\n#else\n    return ((G.mem_mode) ? memflush(__G__ outbuf, (ulg)(outcnt))\n                         : flush(__G__ outbuf, (ulg)(outcnt), 0));\n#endif\n}\n#endif /* USE_ZLIB_INFLATCB */\n\n\n/*\n   GRR:  return values for both original inflate() and UZinflate()\n           0  OK\n           1  incomplete table(?)\n           2  bad input\n           3  not enough memory\n */\n\n/**************************/\n/*  Function UZinflate()  */\n/**************************/\n\nint UZinflate(__G__ is_defl64)\n    __GDEF\n    int is_defl64;\n/* decompress an inflated entry using the zlib routines */\n{\n    int retval = 0;     /* return code: 0 = \"no error\" */\n    int err=Z_OK;\n#if USE_ZLIB_INFLATCB\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    if (G.redirect_slide)\n        wsize = G.redirect_size, redirSlide = G.redirect_buffer;\n    else\n        wsize = WSIZE, redirSlide = slide;\n#endif\n\n    if (!G.inflInit) {\n        /* local buffer for efficiency */\n        ZCONST char *zlib_RtVersion = zlibVersion();\n\n        /* only need to test this stuff once */\n        if ((zlib_RtVersion[0] != ZLIB_VERSION[0]) ||\n            (zlib_RtVersion[2] != ZLIB_VERSION[2])) {\n            Info(slide, 0x21, ((char *)slide,\n              \"error:  incompatible zlib version (expected %s, found %s)\\n\",\n              ZLIB_VERSION, zlib_RtVersion));\n            return 3;\n        } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0)\n            Info(slide, 0x21, ((char *)slide,\n              \"warning:  different zlib version (expected %s, using %s)\\n\",\n              ZLIB_VERSION, zlib_RtVersion));\n\n        G.dstrm.zalloc = (alloc_func)Z_NULL;\n        G.dstrm.zfree = (free_func)Z_NULL;\n\n        G.inflInit = 1;\n    }\n\n#ifdef USE_DEFLATE64\n    if (is_defl64)\n    {\n        Trace((stderr, \"initializing inflate9()\\n\"));\n        err = inflateBack9Init(&G.dstrm, redirSlide);\n\n        if (err == Z_MEM_ERROR)\n            return 3;\n        else if (err != Z_OK) {\n            Trace((stderr, \"oops!  (inflateBack9Init() err = %d)\\n\", err));\n            return 2;\n        }\n\n        G.dstrm.next_in = G.inptr;\n        G.dstrm.avail_in = G.incnt;\n\n        err = inflateBack9(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G);\n        if (err != Z_STREAM_END) {\n            if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) {\n                Trace((stderr, \"oops!  (inflateBack9() err = %d)\\n\", err));\n                retval = 2;\n            } else if (err == Z_MEM_ERROR) {\n                retval = 3;\n            } else if (err == Z_BUF_ERROR) {\n                Trace((stderr, \"oops!  (inflateBack9() err = %d)\\n\", err));\n                if (G.dstrm.next_in == Z_NULL) {\n                    /* input failure */\n                    Trace((stderr, \"  inflateBack9() input failure\\n\"));\n                    retval = 2;\n                } else {\n                    /* output write failure */\n                    retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC);\n                }\n            } else {\n                Trace((stderr, \"oops!  (inflateBack9() err = %d)\\n\", err));\n                retval = 2;\n            }\n        }\n        if (G.dstrm.next_in != NULL) {\n            G.inptr = (uch *)G.dstrm.next_in;\n            G.incnt = G.dstrm.avail_in;\n        }\n\n        err = inflateBack9End(&G.dstrm);\n        if (err != Z_OK) {\n            Trace((stderr, \"oops!  (inflateBack9End() err = %d)\\n\", err));\n            if (retval == 0)\n                retval = 2;\n        }\n    }\n    else\n#endif /* USE_DEFLATE64 */\n    {\n        /* For the callback interface, inflate initialization has to\n           be called before each decompression call.\n         */\n        {\n            unsigned i;\n            int windowBits;\n            /* windowBits = log2(wsize) */\n            for (i = (unsigned)wsize, windowBits = 0;\n                 !(i & 1);  i >>= 1, ++windowBits);\n            if ((unsigned)windowBits > (unsigned)15)\n                windowBits = 15;\n            else if (windowBits < 8)\n                windowBits = 8;\n\n            Trace((stderr, \"initializing inflate()\\n\"));\n            err = inflateBackInit(&G.dstrm, windowBits, redirSlide);\n\n            if (err == Z_MEM_ERROR)\n                return 3;\n            else if (err != Z_OK) {\n                Trace((stderr, \"oops!  (inflateBackInit() err = %d)\\n\", err));\n                return 2;\n            }\n        }\n\n        G.dstrm.next_in = G.inptr;\n        G.dstrm.avail_in = G.incnt;\n\n        err = inflateBack(&G.dstrm, zlib_inCB, &G, zlib_outCB, &G);\n        if (err != Z_STREAM_END) {\n            if (err == Z_DATA_ERROR || err == Z_STREAM_ERROR) {\n                Trace((stderr, \"oops!  (inflateBack() err = %d)\\n\", err));\n                retval = 2;\n            } else if (err == Z_MEM_ERROR) {\n                retval = 3;\n            } else if (err == Z_BUF_ERROR) {\n                Trace((stderr, \"oops!  (inflateBack() err = %d)\\n\", err));\n                if (G.dstrm.next_in == Z_NULL) {\n                    /* input failure */\n                    Trace((stderr, \"  inflateBack() input failure\\n\"));\n                    retval = 2;\n                } else {\n                    /* output write failure */\n                    retval = (G.disk_full != 0 ? PK_DISK : IZ_CTRLC);\n                }\n            } else {\n                Trace((stderr, \"oops!  (inflateBack() err = %d)\\n\", err));\n                retval = 2;\n            }\n        }\n        if (G.dstrm.next_in != NULL) {\n            G.inptr = (uch *)G.dstrm.next_in;\n            G.incnt = G.dstrm.avail_in;\n        }\n\n        err = inflateBackEnd(&G.dstrm);\n        if (err != Z_OK) {\n            Trace((stderr, \"oops!  (inflateBackEnd() err = %d)\\n\", err));\n            if (retval == 0)\n                retval = 2;\n        }\n    }\n\n#else /* !USE_ZLIB_INFLATCB */\n    int repeated_buf_err;\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    if (G.redirect_slide)\n        wsize = G.redirect_size, redirSlide = G.redirect_buffer;\n    else\n        wsize = WSIZE, redirSlide = slide;\n#endif\n\n    G.dstrm.next_out = redirSlide;\n    G.dstrm.avail_out = wsize;\n\n    G.dstrm.next_in = G.inptr;\n    G.dstrm.avail_in = G.incnt;\n\n    if (!G.inflInit) {\n        unsigned i;\n        int windowBits;\n        /* local buffer for efficiency */\n        ZCONST char *zlib_RtVersion = zlibVersion();\n\n        /* only need to test this stuff once */\n        if (zlib_RtVersion[0] != ZLIB_VERSION[0]) {\n            Info(slide, 0x21, ((char *)slide,\n              \"error:  incompatible zlib version (expected %s, found %s)\\n\",\n              ZLIB_VERSION, zlib_RtVersion));\n            return 3;\n        } else if (strcmp(zlib_RtVersion, ZLIB_VERSION) != 0)\n            Info(slide, 0x21, ((char *)slide,\n              \"warning:  different zlib version (expected %s, using %s)\\n\",\n              ZLIB_VERSION, zlib_RtVersion));\n\n        /* windowBits = log2(wsize) */\n        for (i = (unsigned)wsize, windowBits = 0;\n             !(i & 1);  i >>= 1, ++windowBits);\n        if ((unsigned)windowBits > (unsigned)15)\n            windowBits = 15;\n        else if (windowBits < 8)\n            windowBits = 8;\n\n        G.dstrm.zalloc = (alloc_func)Z_NULL;\n        G.dstrm.zfree = (free_func)Z_NULL;\n\n        Trace((stderr, \"initializing inflate()\\n\"));\n        err = inflateInit2(&G.dstrm, -windowBits);\n\n        if (err == Z_MEM_ERROR)\n            return 3;\n        else if (err != Z_OK)\n            Trace((stderr, \"oops!  (inflateInit2() err = %d)\\n\", err));\n        G.inflInit = 1;\n    }\n\n#ifdef FUNZIP\n    while (err != Z_STREAM_END) {\n#else /* !FUNZIP */\n    while (G.csize > 0) {\n        Trace((stderr, \"first loop:  G.csize = %ld\\n\", G.csize));\n#endif /* ?FUNZIP */\n        while (G.dstrm.avail_out > 0) {\n            err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);\n\n            if (err == Z_DATA_ERROR) {\n                retval = 2; goto uzinflate_cleanup_exit;\n            } else if (err == Z_MEM_ERROR) {\n                retval = 3; goto uzinflate_cleanup_exit;\n            } else if (err != Z_OK && err != Z_STREAM_END)\n                Trace((stderr, \"oops!  (inflate(first loop) err = %d)\\n\", err));\n\n#ifdef FUNZIP\n            if (err == Z_STREAM_END)    /* \"END-of-entry-condition\" ? */\n#else /* !FUNZIP */\n            if (G.csize <= 0L)          /* \"END-of-entry-condition\" ? */\n#endif /* ?FUNZIP */\n                break;\n\n            if (G.dstrm.avail_in == 0) {\n                if (fillinbuf(__G) == 0) {\n                    /* no \"END-condition\" yet, but no more data */\n                    retval = 2; goto uzinflate_cleanup_exit;\n                }\n\n                G.dstrm.next_in = G.inptr;\n                G.dstrm.avail_in = G.incnt;\n            }\n            Trace((stderr, \"     avail_in = %u\\n\", G.dstrm.avail_in));\n        }\n        /* flush slide[] */\n        if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0)\n            goto uzinflate_cleanup_exit;\n        Trace((stderr, \"inside loop:  flushing %ld bytes (ptr diff = %ld)\\n\",\n          (long)(wsize - G.dstrm.avail_out),\n          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));\n        G.dstrm.next_out = redirSlide;\n        G.dstrm.avail_out = wsize;\n    }\n\n    /* no more input, so loop until we have all output */\n    Trace((stderr, \"beginning final loop:  err = %d\\n\", err));\n    repeated_buf_err = FALSE;\n    while (err != Z_STREAM_END) {\n        err = inflate(&G.dstrm, Z_PARTIAL_FLUSH);\n        if (err == Z_DATA_ERROR) {\n            retval = 2; goto uzinflate_cleanup_exit;\n        } else if (err == Z_MEM_ERROR) {\n            retval = 3; goto uzinflate_cleanup_exit;\n        } else if (err == Z_BUF_ERROR) {                /* DEBUG */\n#ifdef FUNZIP\n            Trace((stderr,\n                   \"zlib inflate() did not detect stream end\\n\"));\n#else\n            Trace((stderr,\n                   \"zlib inflate() did not detect stream end (%s, %s)\\n\",\n                   G.zipfn, G.filename));\n#endif\n            if ((!repeated_buf_err) && (G.dstrm.avail_in == 0)) {\n                /* when detecting this problem for the first time,\n                   try to provide one fake byte beyond \"EOF\"... */\n                G.dstrm.next_in = \"\";\n                G.dstrm.avail_in = 1;\n                repeated_buf_err = TRUE;\n            } else\n                break;\n        } else if (err != Z_OK && err != Z_STREAM_END) {\n            Trace((stderr, \"oops!  (inflate(final loop) err = %d)\\n\", err));\n            DESTROYGLOBALS();\n            EXIT(PK_MEM3);\n        }\n        /* final flush of slide[] */\n        if ((retval = FLUSH(wsize - G.dstrm.avail_out)) != 0)\n            goto uzinflate_cleanup_exit;\n        Trace((stderr, \"final loop:  flushing %ld bytes (ptr diff = %ld)\\n\",\n          (long)(wsize - G.dstrm.avail_out),\n          (long)(G.dstrm.next_out-(Bytef *)redirSlide)));\n        G.dstrm.next_out = redirSlide;\n        G.dstrm.avail_out = wsize;\n    }\n    Trace((stderr, \"total in = %lu, total out = %lu\\n\", G.dstrm.total_in,\n      G.dstrm.total_out));\n\n    G.inptr = (uch *)G.dstrm.next_in;\n    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */\n\nuzinflate_cleanup_exit:\n    err = inflateReset(&G.dstrm);\n    if (err != Z_OK)\n        Trace((stderr, \"oops!  (inflateReset() err = %d)\\n\", err));\n\n#endif /* ?USE_ZLIB_INFLATCB */\n    return retval;\n}\n\n\n/*---------------------------------------------------------------------------*/\n#else /* !USE_ZLIB */\n\n\n/* Function prototypes */\n#ifndef OF\n#  ifdef __STDC__\n#    define OF(a) a\n#  else\n#    define OF(a) ()\n#  endif\n#endif /* !OF */\nint inflate_codes OF((__GPRO__ struct huft *tl, struct huft *td,\n                      unsigned bl, unsigned bd));\nstatic int inflate_stored OF((__GPRO));\nstatic int inflate_fixed OF((__GPRO));\nstatic int inflate_dynamic OF((__GPRO));\nstatic int inflate_block OF((__GPRO__ int *e));\n\n\n/* The inflate algorithm uses a sliding 32K byte window on the uncompressed\n   stream to find repeated byte strings.  This is implemented here as a\n   circular buffer.  The index is updated simply by incrementing and then\n   and'ing with 0x7fff (32K-1). */\n/* It is left to other modules to supply the 32K area.  It is assumed\n   to be usable as if it were declared \"uch slide[32768];\" or as just\n   \"uch *slide;\" and then malloc'ed in the latter case.  The definition\n   must be in unzip.h, included above. */\n\n\n/* unsigned wp;  moved to globals.h */     /* current position in slide */\n\n/* Tables for deflate from PKZIP's appnote.txt. */\n/* - Order of the bit length code lengths */\nstatic ZCONST unsigned border[] = {\n        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n/* - Copy lengths for literal codes 257..285 */\n#ifdef USE_DEFLATE64\nstatic ZCONST ush cplens64[] = {\n        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3, 0, 0};\n        /* For Deflate64, the code 285 is defined differently. */\n#else\n#  define cplens32 cplens\n#endif\nstatic ZCONST ush cplens32[] = {\n        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};\n        /* note: see note #13 above about the 258 in this list. */\n/* - Extra bits for literal codes 257..285 */\n#ifdef USE_DEFLATE64\nstatic ZCONST uch cplext64[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\n        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 16, INVALID_CODE, INVALID_CODE};\n#else\n#  define cplext32 cplext\n#endif\nstatic ZCONST uch cplext32[] = {\n        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\n        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, INVALID_CODE, INVALID_CODE};\n\n/* - Copy offsets for distance codes 0..29 (0..31 for Deflate64) */\nstatic ZCONST ush cpdist[] = {\n        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND))\n        8193, 12289, 16385, 24577, 32769, 49153};\n#else\n        8193, 12289, 16385, 24577};\n#endif\n\n/* - Extra bits for distance codes 0..29 (0..31 for Deflate64) */\n#ifdef USE_DEFLATE64\nstatic ZCONST uch cpdext64[] = {\n        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\n        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\n        12, 12, 13, 13, 14, 14};\n#else\n#  define cpdext32 cpdext\n#endif\nstatic ZCONST uch cpdext32[] = {\n        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\n        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\n#ifdef PKZIP_BUG_WORKAROUND\n        12, 12, 13, 13, INVALID_CODE, INVALID_CODE};\n#else\n        12, 12, 13, 13};\n#endif\n\n#ifdef PKZIP_BUG_WORKAROUND\n#  define MAXLITLENS 288\n#else\n#  define MAXLITLENS 286\n#endif\n#if (defined(USE_DEFLATE64) || defined(PKZIP_BUG_WORKAROUND))\n#  define MAXDISTS 32\n#else\n#  define MAXDISTS 30\n#endif\n\n\n/* moved to consts.h (included in unzip.c), resp. funzip.c */\n#if 0\n/* And'ing with mask_bits[n] masks the lower n bits */\nZCONST unsigned near mask_bits[17] = {\n    0x0000,\n    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,\n    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff\n};\n#endif /* 0 */\n\n\n/* Macros for inflate() bit peeking and grabbing.\n   The usage is:\n\n        NEEDBITS(j)\n        x = b & mask_bits[j];\n        DUMPBITS(j)\n\n   where NEEDBITS makes sure that b has at least j bits in it, and\n   DUMPBITS removes the bits from b.  The macros use the variable k\n   for the number of bits in b.  Normally, b and k are register\n   variables for speed and are initialized at the beginning of a\n   routine that uses these macros from a global bit buffer and count.\n\n   In order to not ask for more bits than there are in the compressed\n   stream, the Huffman tables are constructed to only ask for just\n   enough bits to make up the end-of-block code (value 256).  Then no\n   bytes need to be \"returned\" to the buffer at the end of the last\n   block.  See the huft_build() routine.\n\n   Actually, the precautions mentioned above are not sufficient to\n   prevent fetches of bits beyound the end of the last block in every\n   case. When the last code fetched before the end-of-block code was\n   a very short distance code (shorter than \"distance-prefetch-bits\" -\n   \"end-of-block code bits\"), this last distance code fetch already\n   exausts the available data.  To prevent failure of extraction in this\n   case, the \"read beyond EOF\" check delays the raise of the \"invalid\n   data\" error until an actual overflow of \"used data\" is detected.\n   This error condition is only fulfilled when the \"number of available\n   bits\" counter k is found to be negative in the NEEDBITS() macro.\n\n   An alternate fix for that problem adjusts the size of the distance code\n   base table so that it does not exceed the length of the end-of-block code\n   plus the minimum length of a distance code. This alternate fix can be\n   enabled by defining the preprocessor symbol FIX_PAST_EOB_BY_TABLEADJUST.\n */\n\n/* These have been moved to globals.h */\n#if 0\nulg bb;                         /* bit buffer */\nunsigned bk;                    /* bits in bit buffer */\n#endif\n\n#ifndef CHECK_EOF\n#  define CHECK_EOF   /* default as of 5.13/5.2 */\n#endif\n\n#ifndef CHECK_EOF\n#  define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}\n#else\n# ifdef FIX_PAST_EOB_BY_TABLEADJUST\n#  define NEEDBITS(n) {while(k<(n)){int c=NEXTBYTE;\\\n    if(c==EOF){retval=1;goto cleanup_and_exit;}\\\n    b|=((ulg)c)<<k;k+=8;}}\n# else\n#  define NEEDBITS(n) {while((int)k<(int)(n)){int c=NEXTBYTE;\\\n    if(c==EOF){if((int)k>=0)break;retval=1;goto cleanup_and_exit;}\\\n    b|=((ulg)c)<<k;k+=8;}}\n# endif\n#endif\n\n#define DUMPBITS(n) {b>>=(n);k-=(n);}\n\n\n/*\n   Huffman code decoding is performed using a multi-level table lookup.\n   The fastest way to decode is to simply build a lookup table whose\n   size is determined by the longest code.  However, the time it takes\n   to build this table can also be a factor if the data being decoded\n   are not very long.  The most common codes are necessarily the\n   shortest codes, so those codes dominate the decoding time, and hence\n   the speed.  The idea is you can have a shorter table that decodes the\n   shorter, more probable codes, and then point to subsidiary tables for\n   the longer codes.  The time it costs to decode the longer codes is\n   then traded against the time it takes to make longer tables.\n\n   This results of this trade are in the variables lbits and dbits\n   below.  lbits is the number of bits the first level table for literal/\n   length codes can decode in one step, and dbits is the same thing for\n   the distance codes.  Subsequent tables are also less than or equal to\n   those sizes.  These values may be adjusted either when all of the\n   codes are shorter than that, in which case the longest code length in\n   bits is used, or when the shortest code is *longer* than the requested\n   table size, in which case the length of the shortest code in bits is\n   used.\n\n   There are two different values for the two tables, since they code a\n   different number of possibilities each.  The literal/length table\n   codes 286 possible values, or in a flat code, a little over eight\n   bits.  The distance table codes 30 possible values, or a little less\n   than five bits, flat.  The optimum values for speed end up being\n   about one bit more than those, so lbits is 8+1 and dbits is 5+1.\n   The optimum values may differ though from machine to machine, and\n   possibly even between compilers.  Your mileage may vary.\n */\n\n\n/* bits in base literal/length lookup table */\nstatic ZCONST unsigned lbits = 9;\n/* bits in base distance lookup table */\nstatic ZCONST unsigned dbits = 6;\n\n\n#ifndef ASM_INFLATECODES\n\nint inflate_codes(__G__ tl, td, bl, bd)\n     __GDEF\nstruct huft *tl, *td;   /* literal/length and distance decoder tables */\nunsigned bl, bd;        /* number of bits decoded by tl[] and td[] */\n/* inflate (decompress) the codes in a deflated (compressed) block.\n   Return an error code or zero if it all goes ok. */\n{\n  register unsigned e;  /* table entry flag/number of extra bits */\n  unsigned d;           /* index for copy */\n  UINT_D64 n;           /* length for copy (deflate64: might be 64k+2) */\n  UINT_D64 w;           /* current window position (deflate64: up to 64k) */\n  struct huft *t;       /* pointer to table entry */\n  unsigned ml, md;      /* masks for bl and bd bits */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* make local copies of globals */\n  b = G.bb;                       /* initialize bit buffer */\n  k = G.bk;\n  w = G.wp;                       /* initialize window position */\n\n\n  /* inflate the coded data */\n  ml = mask_bits[bl];           /* precompute masks for speed */\n  md = mask_bits[bd];\n  while (1)                     /* do until end of block */\n  {\n    NEEDBITS(bl)\n    t = tl + ((unsigned)b & ml);\n    while (1) {\n      DUMPBITS(t->b)\n\n      if ((e = t->e) == 32)     /* then it's a literal */\n      {\n        redirSlide[w++] = (uch)t->v.n;\n        if (w == wsize)\n        {\n          if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;\n          w = 0;\n        }\n        break;\n      }\n\n      if (e < 31)               /* then it's a length */\n      {\n        /* get length of block to copy */\n        NEEDBITS(e)\n        n = t->v.n + ((unsigned)b & mask_bits[e]);\n        DUMPBITS(e)\n\n        /* decode distance of block to copy */\n        NEEDBITS(bd)\n        t = td + ((unsigned)b & md);\n        while (1) {\n          DUMPBITS(t->b)\n          if ((e = t->e) < 32)\n            break;\n          if (IS_INVALID_CODE(e))\n            return 1;\n          e &= 31;\n          NEEDBITS(e)\n          t = t->v.t + ((unsigned)b & mask_bits[e]);\n        }\n        NEEDBITS(e)\n        d = (unsigned)w - t->v.n - ((unsigned)b & mask_bits[e]);\n        DUMPBITS(e)\n\n        /* do the copy */\n        do {\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n          if (G.redirect_slide) {\n            /* &= w/ wsize unnecessary & wrong if redirect */\n            if ((UINT_D64)d >= wsize)\n              return 1;         /* invalid compressed data */\n            e = (unsigned)(wsize - (d > (unsigned)w ? (UINT_D64)d : w));\n          }\n          else\n#endif\n            e = (unsigned)(wsize -\n                           ((d &= (unsigned)(wsize-1)) > (unsigned)w ?\n                            (UINT_D64)d : w));\n          if ((UINT_D64)e > n) e = (unsigned)n;\n          n -= e;\n#ifndef NOMEMCPY\n          if ((unsigned)w - d >= e)\n          /* (this test assumes unsigned comparison) */\n          {\n            memcpy(redirSlide + (unsigned)w, redirSlide + d, e);\n            w += e;\n            d += e;\n          }\n          else                  /* do it slowly to avoid memcpy() overlap */\n#endif /* !NOMEMCPY */\n            do {\n              redirSlide[w++] = redirSlide[d++];\n            } while (--e);\n          if (w == wsize)\n          {\n            if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;\n            w = 0;\n          }\n        } while (n);\n        break;\n      }\n\n      if (e == 31)              /* it's the EOB signal */\n      {\n        /* sorry for this goto, but we have to exit two loops at once */\n        goto cleanup_decode;\n      }\n\n      if (IS_INVALID_CODE(e))\n        return 1;\n\n      e &= 31;\n      NEEDBITS(e)\n      t = t->v.t + ((unsigned)b & mask_bits[e]);\n    }\n  }\ncleanup_decode:\n\n  /* restore the globals from the locals */\n  G.wp = (unsigned)w;             /* restore global window pointer */\n  G.bb = b;                       /* restore global bit buffer */\n  G.bk = k;\n\n\ncleanup_and_exit:\n  /* done */\n  return retval;\n}\n\n#endif /* ASM_INFLATECODES */\n\n\n\nstatic int inflate_stored(__G)\n     __GDEF\n/* \"decompress\" an inflated type 0 (stored) block. */\n{\n  UINT_D64 w;           /* current window position (deflate64: up to 64k!) */\n  unsigned n;           /* number of bytes in block */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* make local copies of globals */\n  Trace((stderr, \"\\nstored block\"));\n  b = G.bb;                       /* initialize bit buffer */\n  k = G.bk;\n  w = G.wp;                       /* initialize window position */\n\n\n  /* go to byte boundary */\n  n = k & 7;\n  DUMPBITS(n);\n\n\n  /* get the length and its complement */\n  NEEDBITS(16)\n  n = ((unsigned)b & 0xffff);\n  DUMPBITS(16)\n  NEEDBITS(16)\n  if (n != (unsigned)((~b) & 0xffff))\n    return 1;                   /* error in compressed data */\n  DUMPBITS(16)\n\n\n  /* read and output the compressed data */\n  while (n--)\n  {\n    NEEDBITS(8)\n    redirSlide[w++] = (uch)b;\n    if (w == wsize)\n    {\n      if ((retval = FLUSH(w)) != 0) goto cleanup_and_exit;\n      w = 0;\n    }\n    DUMPBITS(8)\n  }\n\n\n  /* restore the globals from the locals */\n  G.wp = (unsigned)w;             /* restore global window pointer */\n  G.bb = b;                       /* restore global bit buffer */\n  G.bk = k;\n\ncleanup_and_exit:\n  return retval;\n}\n\n\n/* Globals for literal tables (built once) */\n/* Moved to globals.h                      */\n#if 0\nstruct huft *fixed_tl = (struct huft *)NULL;\nstruct huft *fixed_td;\nint fixed_bl, fixed_bd;\n#endif\n\nstatic int inflate_fixed(__G)\n     __GDEF\n/* decompress an inflated type 1 (fixed Huffman codes) block.  We should\n   either replace this with a custom decoder, or at least precompute the\n   Huffman tables. */\n{\n  /* if first time, set up tables for fixed blocks */\n  Trace((stderr, \"\\nliteral block\"));\n  if (G.fixed_tl == (struct huft *)NULL)\n  {\n    int i;                /* temporary variable */\n    unsigned l[288];      /* length list for huft_build */\n\n    /* literal table */\n    for (i = 0; i < 144; i++)\n      l[i] = 8;\n    for (; i < 256; i++)\n      l[i] = 9;\n    for (; i < 280; i++)\n      l[i] = 7;\n    for (; i < 288; i++)          /* make a complete, but wrong code set */\n      l[i] = 8;\n    G.fixed_bl = 7;\n#ifdef USE_DEFLATE64\n    if ((i = huft_build(__G__ l, 288, 257, G.cplens, G.cplext,\n                        &G.fixed_tl, &G.fixed_bl)) != 0)\n#else\n    if ((i = huft_build(__G__ l, 288, 257, cplens, cplext,\n                        &G.fixed_tl, &G.fixed_bl)) != 0)\n#endif\n    {\n      G.fixed_tl = (struct huft *)NULL;\n      return i;\n    }\n\n    /* distance table */\n    for (i = 0; i < MAXDISTS; i++)      /* make an incomplete code set */\n      l[i] = 5;\n    G.fixed_bd = 5;\n#ifdef USE_DEFLATE64\n    if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, G.cpdext,\n                        &G.fixed_td, &G.fixed_bd)) > 1)\n#else\n    if ((i = huft_build(__G__ l, MAXDISTS, 0, cpdist, cpdext,\n                        &G.fixed_td, &G.fixed_bd)) > 1)\n#endif\n    {\n      huft_free(G.fixed_tl);\n      G.fixed_td = G.fixed_tl = (struct huft *)NULL;\n      return i;\n    }\n  }\n\n  /* decompress until an end-of-block code */\n  return inflate_codes(__G__ G.fixed_tl, G.fixed_td,\n                             G.fixed_bl, G.fixed_bd);\n}\n\n\n\nstatic int inflate_dynamic(__G)\n  __GDEF\n/* decompress an inflated type 2 (dynamic Huffman codes) block. */\n{\n  unsigned i;           /* temporary variables */\n  unsigned j;\n  unsigned l;           /* last length */\n  unsigned m;           /* mask for bit lengths table */\n  unsigned n;           /* number of lengths to get */\n  struct huft *tl = (struct huft *)NULL; /* literal/length code table */\n  struct huft *td = (struct huft *)NULL; /* distance code table */\n  struct huft *th;      /* temp huft table pointer used in tables decoding */\n  unsigned bl;          /* lookup bits for tl */\n  unsigned bd;          /* lookup bits for td */\n  unsigned nb;          /* number of bit length codes */\n  unsigned nl;          /* number of literal/length codes */\n  unsigned nd;          /* number of distance codes */\n  unsigned ll[MAXLITLENS+MAXDISTS]; /* lit./length and distance code lengths */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* make local bit buffer */\n  Trace((stderr, \"\\ndynamic block\"));\n  b = G.bb;\n  k = G.bk;\n\n\n  /* read in table lengths */\n  NEEDBITS(5)\n  nl = 257 + ((unsigned)b & 0x1f);      /* number of literal/length codes */\n  DUMPBITS(5)\n  NEEDBITS(5)\n  nd = 1 + ((unsigned)b & 0x1f);        /* number of distance codes */\n  DUMPBITS(5)\n  NEEDBITS(4)\n  nb = 4 + ((unsigned)b & 0xf);         /* number of bit length codes */\n  DUMPBITS(4)\n  if (nl > MAXLITLENS || nd > MAXDISTS)\n    return 1;                   /* bad lengths */\n\n\n  /* read in bit-length-code lengths */\n  for (j = 0; j < nb; j++)\n  {\n    NEEDBITS(3)\n    ll[border[j]] = (unsigned)b & 7;\n    DUMPBITS(3)\n  }\n  for (; j < 19; j++)\n    ll[border[j]] = 0;\n\n\n  /* build decoding table for trees--single level, 7 bit lookup */\n  bl = 7;\n  retval = huft_build(__G__ ll, 19, 19, NULL, NULL, &tl, &bl);\n  if (bl == 0)                  /* no bit lengths */\n    retval = 1;\n  if (retval)\n  {\n    if (retval == 1)\n      huft_free(tl);\n    return retval;              /* incomplete code set */\n  }\n\n\n  /* read in literal and distance code lengths */\n  n = nl + nd;\n  m = mask_bits[bl];\n  i = l = 0;\n  while (i < n)\n  {\n    NEEDBITS(bl)\n    j = (th = tl + ((unsigned)b & m))->b;\n    DUMPBITS(j)\n    j = th->v.n;\n    if (j < 16)                 /* length of code in bits (0..15) */\n      ll[i++] = l = j;          /* save last length in l */\n    else if (j == 16)           /* repeat last length 3 to 6 times */\n    {\n      NEEDBITS(2)\n      j = 3 + ((unsigned)b & 3);\n      DUMPBITS(2)\n      if ((unsigned)i + j > n) {\n        huft_free(tl);\n        return 1;\n      }\n      while (j--)\n        ll[i++] = l;\n    }\n    else if (j == 17)           /* 3 to 10 zero length codes */\n    {\n      NEEDBITS(3)\n      j = 3 + ((unsigned)b & 7);\n      DUMPBITS(3)\n      if ((unsigned)i + j > n) {\n        huft_free(tl);\n        return 1;\n      }\n      while (j--)\n        ll[i++] = 0;\n      l = 0;\n    }\n    else                        /* j == 18: 11 to 138 zero length codes */\n    {\n      NEEDBITS(7)\n      j = 11 + ((unsigned)b & 0x7f);\n      DUMPBITS(7)\n      if ((unsigned)i + j > n) {\n        huft_free(tl);\n        return 1;\n      }\n      while (j--)\n        ll[i++] = 0;\n      l = 0;\n    }\n  }\n\n\n  /* free decoding table for trees */\n  huft_free(tl);\n\n\n  /* restore the global bit buffer */\n  G.bb = b;\n  G.bk = k;\n\n\n  /* build the decoding tables for literal/length and distance codes */\n  bl = lbits;\n#ifdef USE_DEFLATE64\n  retval = huft_build(__G__ ll, nl, 257, G.cplens, G.cplext, &tl, &bl);\n#else\n  retval = huft_build(__G__ ll, nl, 257, cplens, cplext, &tl, &bl);\n#endif\n  if (bl == 0)                  /* no literals or lengths */\n    retval = 1;\n  if (retval)\n  {\n    if (retval == 1) {\n      if (!uO.qflag)\n        MESSAGE((uch *)\"(incomplete l-tree)  \", 21L, 1);\n      huft_free(tl);\n    }\n    return retval;              /* incomplete code set */\n  }\n#ifdef FIX_PAST_EOB_BY_TABLEADJUST\n  /* Adjust the requested distance base table size so that a distance code\n     fetch never tries to get bits behind an immediatly following end-of-block\n     code. */\n  bd = (dbits <= bl+1 ? dbits : bl+1);\n#else\n  bd = dbits;\n#endif\n#ifdef USE_DEFLATE64\n  retval = huft_build(__G__ ll + nl, nd, 0, cpdist, G.cpdext, &td, &bd);\n#else\n  retval = huft_build(__G__ ll + nl, nd, 0, cpdist, cpdext, &td, &bd);\n#endif\n#ifdef PKZIP_BUG_WORKAROUND\n  if (retval == 1)\n    retval = 0;\n#endif\n  if (bd == 0 && nl > 257)    /* lengths but no distances */\n    retval = 1;\n  if (retval)\n  {\n    if (retval == 1) {\n      if (!uO.qflag)\n        MESSAGE((uch *)\"(incomplete d-tree)  \", 21L, 1);\n      huft_free(td);\n    }\n    huft_free(tl);\n    return retval;\n  }\n\n  /* decompress until an end-of-block code */\n  retval = inflate_codes(__G__ tl, td, bl, bd);\n\ncleanup_and_exit:\n  /* free the decoding tables, return */\n  if (tl != (struct huft *)NULL)\n    huft_free(tl);\n  if (td != (struct huft *)NULL)\n    huft_free(td);\n  return retval;\n}\n\n\n\nstatic int inflate_block(__G__ e)\n  __GDEF\n  int *e;               /* last block flag */\n/* decompress an inflated block */\n{\n  unsigned t;           /* block type */\n  register ulg b;       /* bit buffer */\n  register unsigned k;  /* number of bits in bit buffer */\n  int retval = 0;       /* error code returned: initialized to \"no error\" */\n\n\n  /* make local bit buffer */\n  b = G.bb;\n  k = G.bk;\n\n\n  /* read in last block bit */\n  NEEDBITS(1)\n  *e = (int)b & 1;\n  DUMPBITS(1)\n\n\n  /* read in block type */\n  NEEDBITS(2)\n  t = (unsigned)b & 3;\n  DUMPBITS(2)\n\n\n  /* restore the global bit buffer */\n  G.bb = b;\n  G.bk = k;\n\n\n  /* inflate that block type */\n  if (t == 2)\n    return inflate_dynamic(__G);\n  if (t == 0)\n    return inflate_stored(__G);\n  if (t == 1)\n    return inflate_fixed(__G);\n\n\n  /* bad block type */\n  retval = 2;\n\ncleanup_and_exit:\n  return retval;\n}\n\n\n\nint inflate(__G__ is_defl64)\n    __GDEF\n    int is_defl64;\n/* decompress an inflated entry */\n{\n  int e;                /* last block flag */\n  int r;                /* result code */\n#ifdef DEBUG\n  unsigned h = 0;       /* maximum struct huft's malloc'ed */\n#endif\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n  if (G.redirect_slide)\n    wsize = G.redirect_size, redirSlide = G.redirect_buffer;\n  else\n    wsize = WSIZE, redirSlide = slide;   /* how they're #defined if !DLL */\n#endif\n\n  /* initialize window, bit buffer */\n  G.wp = 0;\n  G.bk = 0;\n  G.bb = 0;\n\n#ifdef USE_DEFLATE64\n  if (is_defl64) {\n    G.cplens = cplens64;\n    G.cplext = cplext64;\n    G.cpdext = cpdext64;\n    G.fixed_tl = G.fixed_tl64;\n    G.fixed_bl = G.fixed_bl64;\n    G.fixed_td = G.fixed_td64;\n    G.fixed_bd = G.fixed_bd64;\n  } else {\n    G.cplens = cplens32;\n    G.cplext = cplext32;\n    G.cpdext = cpdext32;\n    G.fixed_tl = G.fixed_tl32;\n    G.fixed_bl = G.fixed_bl32;\n    G.fixed_td = G.fixed_td32;\n    G.fixed_bd = G.fixed_bd32;\n  }\n#else /* !USE_DEFLATE64 */\n  if (is_defl64) {\n    /* This should not happen unless UnZip is built from object files\n     * compiled with inconsistent option setting.  Handle this by\n     * returning with \"bad input\" error code.\n     */\n    Trace((stderr, \"\\nThis inflate() cannot handle Deflate64!\\n\"));\n    return 2;\n  }\n#endif /* ?USE_DEFLATE64 */\n\n  /* decompress until the last block */\n  do {\n#ifdef DEBUG\n    G.hufts = 0;\n#endif\n    if ((r = inflate_block(__G__ &e)) != 0)\n      return r;\n#ifdef DEBUG\n    if (G.hufts > h)\n      h = G.hufts;\n#endif\n  } while (!e);\n\n  Trace((stderr, \"\\n%u bytes in Huffman tables (%u/entry)\\n\",\n         h * (unsigned)sizeof(struct huft), (unsigned)sizeof(struct huft)));\n\n#ifdef USE_DEFLATE64\n  if (is_defl64) {\n    G.fixed_tl64 = G.fixed_tl;\n    G.fixed_bl64 = G.fixed_bl;\n    G.fixed_td64 = G.fixed_td;\n    G.fixed_bd64 = G.fixed_bd;\n  } else {\n    G.fixed_tl32 = G.fixed_tl;\n    G.fixed_bl32 = G.fixed_bl;\n    G.fixed_td32 = G.fixed_td;\n    G.fixed_bd32 = G.fixed_bd;\n  }\n#endif\n\n  /* flush out redirSlide and return (success, unless final FLUSH failed) */\n  return (FLUSH(G.wp));\n}\n\n\n\nint inflate_free(__G)\n    __GDEF\n{\n  if (G.fixed_tl != (struct huft *)NULL)\n  {\n    huft_free(G.fixed_td);\n    huft_free(G.fixed_tl);\n    G.fixed_td = G.fixed_tl = (struct huft *)NULL;\n  }\n  return 0;\n}\n\n#endif /* ?USE_ZLIB */\n\n\n/*\n * GRR:  moved huft_build() and huft_free() down here; used by explode()\n *       and fUnZip regardless of whether USE_ZLIB defined or not\n */\n\n\n/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */\n#define BMAX 16         /* maximum bit length of any code (16 for explode) */\n#define N_MAX 288       /* maximum number of codes in any set */\n\n\nint huft_build(__G__ b, n, s, d, e, t, m)\n  __GDEF\n  ZCONST unsigned *b;   /* code lengths in bits (all assumed <= BMAX) */\n  unsigned n;           /* number of codes (assumed <= N_MAX) */\n  unsigned s;           /* number of simple-valued codes (0..s-1) */\n  ZCONST ush *d;        /* list of base values for non-simple codes */\n  ZCONST uch *e;        /* list of extra bits for non-simple codes */\n  struct huft **t;      /* result: starting table */\n  unsigned *m;          /* maximum lookup bits, returns actual */\n/* Given a list of code lengths and a maximum table size, make a set of\n   tables to decode that set of codes.  Return zero on success, one if\n   the given code set is incomplete (the tables are still built in this\n   case), two if the input is invalid (all zero length codes or an\n   oversubscribed set of lengths), and three if not enough memory.\n   The code with value 256 is special, and the tables are constructed\n   so that no bits beyond that code are fetched when that code is\n   decoded. */\n{\n  unsigned a;                   /* counter for codes of length k */\n  unsigned c[BMAX+1];           /* bit length count table */\n  unsigned el;                  /* length of EOB code (value 256) */\n  unsigned f;                   /* i repeats in table every f entries */\n  int g;                        /* maximum code length */\n  int h;                        /* table level */\n  register unsigned i;          /* counter, current code */\n  register unsigned j;          /* counter */\n  register int k;               /* number of bits in current code */\n  int lx[BMAX+1];               /* memory for l[-1..BMAX-1] */\n  int *l = lx+1;                /* stack of bits per table */\n  register unsigned *p;         /* pointer into c[], b[], or v[] */\n  register struct huft *q;      /* points to current table */\n  struct huft r;                /* table entry for structure assignment */\n  struct huft *u[BMAX];         /* table stack */\n  unsigned v[N_MAX];            /* values in order of bit length */\n  register int w;               /* bits before this table == (l * h) */\n  unsigned x[BMAX+1];           /* bit offsets, then code stack */\n  unsigned *xp;                 /* pointer into x */\n  int y;                        /* number of dummy codes added */\n  unsigned z;                   /* number of entries in current table */\n\n\n  /* Generate counts for each bit length */\n  el = n > 256 ? b[256] : BMAX; /* set length of EOB code, if any */\n  memzero((char *)c, sizeof(c));\n  p = (unsigned *)b;  i = n;\n  do {\n    c[*p]++; p++;               /* assume all entries <= BMAX */\n  } while (--i);\n  if (c[0] == n)                /* null input--all zero length codes */\n  {\n    *t = (struct huft *)NULL;\n    *m = 0;\n    return 0;\n  }\n\n\n  /* Find minimum and maximum length, bound *m by those */\n  for (j = 1; j <= BMAX; j++)\n    if (c[j])\n      break;\n  k = j;                        /* minimum code length */\n  if (*m < j)\n    *m = j;\n  for (i = BMAX; i; i--)\n    if (c[i])\n      break;\n  g = i;                        /* maximum code length */\n  if (*m > i)\n    *m = i;\n\n\n  /* Adjust last length count to fill out codes, if needed */\n  for (y = 1 << j; j < i; j++, y <<= 1)\n    if ((y -= c[j]) < 0)\n      return 2;                 /* bad input: more codes than bits */\n  if ((y -= c[i]) < 0)\n    return 2;\n  c[i] += y;\n\n\n  /* Generate starting offsets into the value table for each length */\n  x[1] = j = 0;\n  p = c + 1;  xp = x + 2;\n  while (--i) {                 /* note that i == g from above */\n    *xp++ = (j += *p++);\n  }\n\n\n  /* Make a table of values in order of bit lengths */\n  memzero((char *)v, sizeof(v));\n  p = (unsigned *)b;  i = 0;\n  do {\n    if ((j = *p++) != 0)\n      v[x[j]++] = i;\n  } while (++i < n);\n  n = x[g];                     /* set n to length of v */\n\n\n  /* Generate the Huffman codes and for each, make the table entries */\n  x[0] = i = 0;                 /* first Huffman code is zero */\n  p = v;                        /* grab values in bit order */\n  h = -1;                       /* no tables yet--level -1 */\n  w = l[-1] = 0;                /* no bits decoded yet */\n  u[0] = (struct huft *)NULL;   /* just to keep compilers happy */\n  q = (struct huft *)NULL;      /* ditto */\n  z = 0;                        /* ditto */\n\n  /* go through the bit lengths (k already is bits in shortest code) */\n  for (; k <= g; k++)\n  {\n    a = c[k];\n    while (a--)\n    {\n      /* here i is the Huffman code of length k bits for value *p */\n      /* make tables up to required level */\n      while (k > w + l[h])\n      {\n        w += l[h++];            /* add bits already decoded */\n\n        /* compute minimum size table less than or equal to *m bits */\n        z = (z = g - w) > *m ? *m : z;                  /* upper limit */\n        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */\n        {                       /* too few codes for k-w bit table */\n          f -= a + 1;           /* deduct codes from patterns left */\n          xp = c + k;\n          while (++j < z)       /* try smaller tables up to z bits */\n          {\n            if ((f <<= 1) <= *++xp)\n              break;            /* enough codes to use up j bits */\n            f -= *xp;           /* else deduct codes from patterns */\n          }\n        }\n        if ((unsigned)w + j > el && (unsigned)w < el)\n          j = el - w;           /* make EOB code end at table */\n        z = 1 << j;             /* table entries for j-bit table */\n        l[h] = j;               /* set table size in stack */\n\n        /* allocate and link in new table */\n        if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==\n            (struct huft *)NULL)\n        {\n          if (h)\n            huft_free(u[0]);\n          return 3;             /* not enough memory */\n        }\n#ifdef DEBUG\n        G.hufts += z + 1;         /* track memory usage */\n#endif\n        *t = q + 1;             /* link to list for huft_free() */\n        *(t = &(q->v.t)) = (struct huft *)NULL;\n        u[h] = ++q;             /* table starts after link */\n\n        /* connect to last table, if there is one */\n        if (h)\n        {\n          x[h] = i;             /* save pattern for backing up */\n          r.b = (uch)l[h-1];    /* bits to dump before this table */\n          r.e = (uch)(32 + j);  /* bits in this table */\n          r.v.t = q;            /* pointer to this table */\n          j = (i & ((1 << w) - 1)) >> (w - l[h-1]);\n          u[h-1][j] = r;        /* connect to last table */\n        }\n      }\n\n      /* set up table entry in r */\n      r.b = (uch)(k - w);\n      if (p >= v + n)\n        r.e = INVALID_CODE;     /* out of values--invalid code */\n      else if (*p < s)\n      {\n        r.e = (uch)(*p < 256 ? 32 : 31);  /* 256 is end-of-block code */\n        r.v.n = (ush)*p++;                /* simple code is just the value */\n      }\n      else\n      {\n        r.e = e[*p - s];        /* non-simple--look up in lists */\n        r.v.n = d[*p++ - s];\n      }\n\n      /* fill code-like entries with r */\n      f = 1 << (k - w);\n      for (j = i >> w; j < z; j += f)\n        q[j] = r;\n\n      /* backwards increment the k-bit code i */\n      for (j = 1 << (k - 1); i & j; j >>= 1)\n        i ^= j;\n      i ^= j;\n\n      /* backup over finished tables */\n      while ((i & ((1 << w) - 1)) != x[h])\n        w -= l[--h];            /* don't need to update q */\n    }\n  }\n\n\n  /* return actual size of base table */\n  *m = l[0];\n\n\n  /* Return true (1) if we were given an incomplete table */\n  return y != 0 && g != 1;\n}\n\n\n\nint huft_free(t)\nstruct huft *t;         /* table to free */\n/* Free the malloc'ed tables built by huft_build(), which makes a linked\n   list of the tables it made, with the links in a dummy first entry of\n   each table. */\n{\n  register struct huft *p, *q;\n\n\n  /* Go through linked list, freeing from the malloced (t[-1]) address. */\n  p = t;\n  while (p != (struct huft *)NULL)\n  {\n    q = (--p)->v.t;\n    free((zvoid *)p);\n    p = q;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/inflate.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* inflate.h for UnZip -- by Mark Adler\n   version c14f, 23 November 1995 */\n\n\n/* Copyright history:\n   - Starting with UnZip 5.41 of 16-April-2000, this source file\n     is covered by the Info-Zip LICENSE cited above.\n   - Prior versions of this source file, found in UnZip source packages\n     up to UnZip 5.40, were put in the public domain.\n     The original copyright note by Mark Adler was:\n         \"You can do whatever you like with this source file,\n         though I would prefer that if you modify it and\n         redistribute it that you include comments to that effect\n         with your name and the date.  Thank you.\"\n\n   History:\n   vers    date          who           what\n   ----  ---------  --------------  ------------------------------------\n    c14  12 Mar 93  M. Adler        made inflate.c standalone with the\n                                    introduction of inflate.h.\n    c14d 28 Aug 93  G. Roelofs      replaced flush/FlushOutput with new version\n    c14e 29 Sep 93  G. Roelofs      moved everything into unzip.h; added crypt.h\n    c14f 23 Nov 95  G. Roelofs      added UNZIP_INTERNAL to accommodate newly\n                                    split unzip.h\n */\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"     /* provides slide[], typedefs and macros */\n#ifdef FUNZIP\n#  include \"crypt.h\"   /* provides NEXTBYTE macro for crypt version of funzip */\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/list.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  list.c\n\n  This file contains the non-ZipInfo-specific listing routines for UnZip.\n\n  Contains:  list_files()\n             get_time_stamp()   [optional feature]\n             ratio()\n             fnprint()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#endif\n\n\n#ifdef TIMESTAMP\n   static int  fn_is_dir   OF((__GPRO));\n#endif\n\n#ifndef WINDLL\n   static ZCONST char Far CompFactorStr[] = \"%c%d%%\";\n   static ZCONST char Far CompFactor100[] = \"100%%\";\n\n#ifdef OS2_EAS\n   static ZCONST char Far HeadersS[]  =\n     \"  Length     EAs   ACLs     Date    Time    Name\";\n   static ZCONST char Far HeadersS1[] =\n     \"---------    ---   ----  ---------- -----   ----\";\n#else\n   static ZCONST char Far HeadersS[]  =\n     \"  Length      Date    Time    Name\";\n   static ZCONST char Far HeadersS1[] =\n     \"---------  ---------- -----   ----\";\n#endif\n\n   static ZCONST char Far HeadersL[]  =\n     \" Length   Method    Size  Cmpr    Date    Time   CRC-32   Name\";\n   static ZCONST char Far HeadersL1[] =\n     \"--------  ------  ------- ---- ---------- ----- --------  ----\";\n   static ZCONST char Far *Headers[][2] =\n     { {HeadersS, HeadersS1}, {HeadersL, HeadersL1} };\n\n   static ZCONST char Far CaseConversion[] =\n     \"%s (\\\"^\\\" ==> case\\n%s   conversion)\\n\";\n   static ZCONST char Far LongHdrStats[] =\n     \"%s  %-7s%s %4s %02u%c%02u%c%02u %02u:%02u %08lx %c\";\n   static ZCONST char Far LongFileTrailer[] =\n     \"--------          -------  ---                       \\\n     -------\\n%s         %s %4s                            %lu file%s\\n\";\n#ifdef OS2_EAS\n   static ZCONST char Far ShortHdrStats[] =\n     \"%s %6lu %6lu  %02u%c%02u%c%02u %02u:%02u  %c\";\n   static ZCONST char Far ShortFileTrailer[] =\n     \"---------  -----  -----                \\\n     -------\\n%s %6lu %6lu                     %lu file%s\\n\";\n   static ZCONST char Far OS2ExtAttrTrailer[] =\n     \"%lu file%s %lu bytes of OS/2 extended attributes attached.\\n\";\n   static ZCONST char Far OS2ACLTrailer[] =\n     \"%lu file%s %lu bytes of access control lists attached.\\n\";\n#else\n   static ZCONST char Far ShortHdrStats[] =\n     \"%s  %02u%c%02u%c%02u %02u:%02u  %c\";\n   static ZCONST char Far ShortFileTrailer[] =\n     \"---------                     -------\\n%s\\\n                     %lu file%s\\n\";\n#endif /* ?OS2_EAS */\n#endif /* !WINDLL */\n\n\n\n\n\n/*************************/\n/* Function list_files() */\n/*************************/\n\nint list_files(__G)    /* return PK-type error code */\n    __GDEF\n{\n    int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;\n#ifndef WINDLL\n    char sgn, cfactorstr[10];\n    int longhdr=(uO.vflag>1);\n#endif\n    int date_format;\n    char dt_sepchar;\n    ulg members=0L;\n    zusz_t j;\n    unsigned methnum;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    struct tm *t;\n#endif\n    unsigned yr, mo, dy, hh, mm;\n    zusz_t csiz, tot_csize=0L, tot_ucsize=0L;\n#ifdef OS2_EAS\n    ulg ea_size, tot_easize=0L, tot_eafiles=0L;\n    ulg acl_size, tot_aclsize=0L, tot_aclfiles=0L;\n#endif\n    min_info info;\n    char methbuf[8];\n    static ZCONST char dtype[]=\"NXFS\";  /* see zi_short() */\n    static ZCONST char Far method[NUM_METHODS+1][8] =\n        {\"Stored\", \"Shrunk\", \"Reduce1\", \"Reduce2\", \"Reduce3\", \"Reduce4\",\n         \"Implode\", \"Token\", \"Defl:#\", \"Def64#\", \"ImplDCL\", \"BZip2\",\n         \"LZMA\", \"Terse\", \"IBMLZ77\", \"WavPack\", \"PPMd\", \"Unk:###\"};\n\n\n\n/*---------------------------------------------------------------------------\n    Unlike extract_or_test_files(), this routine confines itself to the cen-\n    tral directory.  Thus its structure is somewhat simpler, since we can do\n    just a single loop through the entire directory, listing files as we go.\n\n    So to start off, print the heading line and then begin main loop through\n    the central directory.  The results will look vaguely like the following:\n\n Length   Method    Size  Ratio   Date   Time   CRC-32    Name (\"^\" ==> case\n--------  ------  ------- -----   ----   ----   ------    ----   conversion)\n   44004  Implode   13041  71%  11-02-89 19:34  8b4207f7  Makefile.UNIX\n    3438  Shrunk     2209  36%  09-15-90 14:07  a2394fd8 ^dos-file.ext\n   16717  Defl:X     5252  69%  11-03-97 06:40  1ce0f189  WHERE\n--------          -------  ---                            -------\n   64159            20502  68%                            3 files\n  ---------------------------------------------------------------------------*/\n\n    G.pInfo = &info;\n    date_format = DATE_FORMAT;\n    dt_sepchar = DATE_SEPCHAR;\n\n#ifndef WINDLL\n    if (uO.qflag < 2) {\n        if (uO.L_flag)\n            Info(slide, 0, ((char *)slide, LoadFarString(CaseConversion),\n              LoadFarStringSmall(Headers[longhdr][0]),\n              LoadFarStringSmall2(Headers[longhdr][1])));\n        else\n            Info(slide, 0, ((char *)slide, \"%s\\n%s\\n\",\n               LoadFarString(Headers[longhdr][0]),\n               LoadFarStringSmall(Headers[longhdr][1])));\n    }\n#endif /* !WINDLL */\n\n    for (j = 1L;;j++) {\n\n        if (readbuf(__G__ G.sig, 4) == 0)\n            return PK_EOF;\n        if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a CentDir entry? */\n            /* no new central directory entry\n             * -> is the number of processed entries compatible with the\n             *    number of entries as stored in the end_central record?\n             */\n            if (((j - 1) &\n                 (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))\n                == (ulg)G.ecrec.total_entries_central_dir)\n            {\n                /* \"j modulus 4T/64k\" matches the reported 64/16-bit-unsigned\n                 * number of directory entries -> probably, the regular\n                 * end of the central directory has been reached\n                 */\n                break;\n            } else {\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(CentSigMsg), j));\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(ReportMsg)));\n                return PK_BADERR;   /* sig not found */\n            }\n        }\n        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */\n        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)\n            return error;       /* only PK_EOF defined */\n\n        /*\n         * We could DISPLAY the filename instead of storing (and possibly trun-\n         * cating, in the case of a very long name) and printing it, but that\n         * has the disadvantage of not allowing case conversion--and it's nice\n         * to be able to see in the listing precisely how you have to type each\n         * filename in order for unzip to consider it a match.  Speaking of\n         * which, if member names were specified on the command line, check in\n         * with match() to see if the current file is one of them, and make a\n         * note of it if it is.\n         */\n\n        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=\n             PK_COOL)   /*  ^--(uses pInfo->lcflag) */\n        {\n            error_in_archive = error;\n            if (error > PK_WARN)   /* fatal:  can't continue */\n                return error;\n        }\n        if (G.extra_field != (uch *)NULL) {\n            free(G.extra_field);\n            G.extra_field = (uch *)NULL;\n        }\n        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))\n            != 0)\n        {\n            error_in_archive = error;\n            if (error > PK_WARN)      /* fatal */\n                return error;\n        }\n        if (!G.process_all_files) {   /* check if specified on command line */\n            unsigned i;\n\n            if (G.filespecs == 0)\n                do_this_file = TRUE;\n            else {  /* check if this entry matches an `include' argument */\n                do_this_file = FALSE;\n                for (i = 0; i < G.filespecs; i++)\n                    if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {\n                        do_this_file = TRUE;\n                        break;       /* found match, so stop looping */\n                    }\n            }\n            if (do_this_file) {  /* check if this is an excluded file */\n                for (i = 0; i < G.xfilespecs; i++)\n                    if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {\n                        do_this_file = FALSE;  /* ^-- ignore case in match */\n                        break;\n                    }\n            }\n        }\n        /*\n         * If current file was specified on command line, or if no names were\n         * specified, do the listing for this file.  Otherwise, get rid of the\n         * file comment and go back for the next file.\n         */\n\n        if (G.process_all_files || do_this_file) {\n\n#ifdef OS2DLL\n            /* this is used by UzpFileTree() to allow easy processing of lists\n             * of zip directory contents */\n            if (G.processExternally) {\n                if ((G.processExternally)(G.filename, &G.crec))\n                    break;\n                ++members;\n            } else {\n#endif\n#ifdef OS2_EAS\n            {\n                uch *ef_ptr = G.extra_field;\n                int ef_size, ef_len = G.crec.extra_field_length;\n                ea_size = acl_size = 0;\n\n                while (ef_len >= EB_HEADSIZE) {\n                    ef_size = makeword(&ef_ptr[EB_LEN]);\n                    switch (makeword(&ef_ptr[EB_ID])) {\n                        case EF_OS2:\n                            ea_size = makelong(&ef_ptr[EB_HEADSIZE]);\n                            break;\n                        case EF_ACL:\n                            acl_size = makelong(&ef_ptr[EB_HEADSIZE]);\n                            break;\n                    }\n                    ef_ptr += (ef_size + EB_HEADSIZE);\n                    ef_len -= (ef_size + EB_HEADSIZE);\n                }\n            }\n#endif\n#ifdef USE_EF_UT_TIME\n            if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n                G.tz_is_valid &&\n#endif\n                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,\n                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)\n                 & EB_UT_FL_MTIME))\n            {\n                TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0, Mac */\n                t = localtime(&(z_utime.mtime));\n            } else\n                t = (struct tm *)NULL;\n            if (t != (struct tm *)NULL) {\n                mo = (unsigned)(t->tm_mon + 1);\n                dy = (unsigned)(t->tm_mday);\n                yr = (unsigned)(t->tm_year + 1900);\n                hh = (unsigned)(t->tm_hour);\n                mm = (unsigned)(t->tm_min);\n            } else\n#endif /* USE_EF_UT_TIME */\n            {\n                yr = ((((unsigned)(G.crec.last_mod_dos_datetime >> 25) & 0x7f)\n                       + 1980));\n                mo = ((unsigned)(G.crec.last_mod_dos_datetime >> 21) & 0x0f);\n                dy = ((unsigned)(G.crec.last_mod_dos_datetime >> 16) & 0x1f);\n                hh = (((unsigned)G.crec.last_mod_dos_datetime >> 11) & 0x1f);\n                mm = (((unsigned)G.crec.last_mod_dos_datetime >> 5) & 0x3f);\n            }\n            /* permute date so it displays according to nat'l convention\n             * ('methnum' is not yet set, it is used as temporary buffer) */\n            switch (date_format) {\n                case DF_YMD:\n                    methnum = mo;\n                    mo = yr; yr = dy; dy = methnum;\n                    break;\n                case DF_DMY:\n                    methnum = mo;\n                    mo = dy; dy = methnum;\n            }\n\n            csiz = G.crec.csize;\n            if (G.crec.general_purpose_bit_flag & 1)\n                csiz -= 12;   /* if encrypted, don't count encryption header */\n            if ((cfactor = ratio(G.crec.ucsize, csiz)) < 0) {\n#ifndef WINDLL\n                sgn = '-';\n#endif\n                cfactor = (-cfactor + 5) / 10;\n            } else {\n#ifndef WINDLL\n                sgn = ' ';\n#endif\n                cfactor = (cfactor + 5) / 10;\n            }\n\n            methnum = find_compr_idx(G.crec.compression_method);\n            zfstrcpy(methbuf, method[methnum]);\n            if (G.crec.compression_method == DEFLATED ||\n                G.crec.compression_method == ENHDEFLATED) {\n                methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];\n            } else if (methnum >= NUM_METHODS) {\n                sprintf(&methbuf[4], \"%03u\", G.crec.compression_method);\n            }\n\n#if 0       /* GRR/Euro:  add this? */\n#if defined(DOS_FLX_NLM_OS2_W32) || defined(THEOS) || defined(UNIX)\n            for (p = G.filename;  *p;  ++p)\n                if (!isprint(*p))\n                    *p = '?';  /* change non-printable chars to '?' */\n#endif /* DOS_FLX_NLM_OS2_W32 || THEOS || UNIX */\n#endif /* 0 */\n\n#ifdef WINDLL\n            /* send data to application for formatting and printing */\n            if (G.lpUserFunctions->SendApplicationMessage != NULL)\n                (*G.lpUserFunctions->SendApplicationMessage)(G.crec.ucsize,\n                  csiz, (unsigned)cfactor, mo, dy, yr, hh, mm,\n                  (char)(G.pInfo->lcflag ? '^' : ' '),\n                  (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),\n                  (LPCSTR)methbuf, G.crec.crc32,\n                  (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));\n            else if (G.lpUserFunctions->SendApplicationMessage_i32 != NULL) {\n                unsigned long ucsize_lo, csiz_lo;\n                unsigned long ucsize_hi=0L, csiz_hi=0L;\n                ucsize_lo = (unsigned long)(G.crec.ucsize);\n                csiz_lo = (unsigned long)(csiz);\n#ifdef ZIP64_SUPPORT\n                ucsize_hi = (unsigned long)(G.crec.ucsize >> 32);\n                csiz_hi = (unsigned long)(csiz >> 32);\n#endif /* ZIP64_SUPPORT */\n                (*G.lpUserFunctions->SendApplicationMessage_i32)(ucsize_lo,\n                    ucsize_hi, csiz_lo, csiz_hi, (unsigned)cfactor,\n                    mo, dy, yr, hh, mm,\n                    (char)(G.pInfo->lcflag ? '^' : ' '),\n                    (LPCSTR)fnfilter(G.filename, slide, (WSIZE>>1)),\n                    (LPCSTR)methbuf, G.crec.crc32,\n                    (char)((G.crec.general_purpose_bit_flag & 1) ? 'E' : ' '));\n            }\n#else /* !WINDLL */\n            if (cfactor == 100)\n                sprintf(cfactorstr, LoadFarString(CompFactor100));\n            else\n                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);\n            if (longhdr)\n                Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),\n                  FmZofft(G.crec.ucsize, \"8\", \"u\"), methbuf,\n                  FmZofft(csiz, \"8\", \"u\"), cfactorstr,\n                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,\n                  G.crec.crc32, (G.pInfo->lcflag? '^':' ')));\n            else\n#ifdef OS2_EAS\n                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),\n                  FmZofft(G.crec.ucsize, \"9\", \"u\"), ea_size, acl_size,\n                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,\n                  (G.pInfo->lcflag? '^':' ')));\n#else\n                Info(slide, 0, ((char *)slide, LoadFarString(ShortHdrStats),\n                  FmZofft(G.crec.ucsize, \"9\", \"u\"),\n                  mo, dt_sepchar, dy, dt_sepchar, yr, hh, mm,\n                  (G.pInfo->lcflag? '^':' ')));\n#endif\n            fnprint(__G);\n#endif /* ?WINDLL */\n\n            if ((error = do_string(__G__ G.crec.file_comment_length,\n                                   QCOND? DISPL_8 : SKIP)) != 0)\n            {\n                error_in_archive = error;  /* might be just warning */\n                if (error > PK_WARN)       /* fatal */\n                    return error;\n            }\n            tot_ucsize += G.crec.ucsize;\n            tot_csize += csiz;\n            ++members;\n#ifdef OS2_EAS\n            if (ea_size) {\n                tot_easize += ea_size;\n                ++tot_eafiles;\n            }\n            if (acl_size) {\n                tot_aclsize += acl_size;\n                ++tot_aclfiles;\n            }\n#endif\n#ifdef OS2DLL\n            } /* end of \"if (G.processExternally) {...} else {...\" */\n#endif\n        } else {        /* not listing this file */\n            SKIP_(G.crec.file_comment_length)\n        }\n    } /* end for-loop (j: files in central directory) */\n\n/*---------------------------------------------------------------------------\n    Print footer line and totals (compressed size, uncompressed size, number\n    of members in zipfile).\n  ---------------------------------------------------------------------------*/\n\n    if (uO.qflag < 2\n#ifdef OS2DLL\n                     && !G.processExternally\n#endif\n                                            ) {\n        if ((cfactor = ratio(tot_ucsize, tot_csize)) < 0) {\n#ifndef WINDLL\n            sgn = '-';\n#endif\n            cfactor = (-cfactor + 5) / 10;\n        } else {\n#ifndef WINDLL\n            sgn = ' ';\n#endif\n            cfactor = (cfactor + 5) / 10;\n        }\n#ifdef WINDLL\n        /* pass the totals back to the calling application */\n        G.lpUserFunctions->TotalSizeComp = tot_csize;\n        G.lpUserFunctions->TotalSize = tot_ucsize;\n        G.lpUserFunctions->CompFactor = (ulg)cfactor;\n        G.lpUserFunctions->NumMembers = members;\n\n#else /* !WINDLL */\n        if (cfactor == 100)\n            sprintf(cfactorstr, LoadFarString(CompFactor100));\n        else\n            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);\n        if (longhdr) {\n            Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),\n              FmZofft(tot_ucsize, \"8\", \"u\"), FmZofft(tot_csize, \"8\", \"u\"),\n              cfactorstr, members, members==1? \"\":\"s\"));\n#ifdef OS2_EAS\n            if (tot_easize || tot_aclsize)\n                Info(slide, 0, ((char *)slide, \"\\n\"));\n            if (tot_eafiles && tot_easize)\n                Info(slide, 0, ((char *)slide, LoadFarString(OS2ExtAttrTrailer),\n                  tot_eafiles, tot_eafiles == 1? \" has\" : \"s have a total of\",\n                  tot_easize));\n            if (tot_aclfiles && tot_aclsize)\n                Info(slide, 0, ((char *)slide, LoadFarString(OS2ACLTrailer),\n                  tot_aclfiles,\n                  tot_aclfiles == 1 ? \" has\" : \"s have a total of\",\n                  tot_aclsize));\n#endif /* OS2_EAS */\n        } else\n#ifdef OS2_EAS\n            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),\n              FmZofft(tot_ucsize, \"9\", \"u\"), tot_easize, tot_aclsize,\n              members, members == 1 ? \"\" : \"s\"));\n#else\n            Info(slide, 0, ((char *)slide, LoadFarString(ShortFileTrailer),\n              FmZofft(tot_ucsize, \"9\", \"u\"),\n              members, members == 1 ? \"\" : \"s\"));\n#endif /* OS2_EAS */\n#endif /* ?WINDLL */\n    }\n\n    /* Skip the following checks in case of a premature listing break. */\n    if (error_in_archive <= PK_WARN) {\n\n/*---------------------------------------------------------------------------\n    Double check that we're back at the end-of-central-directory record.\n  ---------------------------------------------------------------------------*/\n\n        if ( (memcmp(G.sig,\n                     (G.ecrec.have_ecr64 ?\n                      end_central64_sig : end_central_sig),\n                     4) != 0)\n            && (!G.ecrec.is_zip64_archive)\n            && (memcmp(G.sig, end_central_sig, 4) != 0)\n           ) {          /* just to make sure again */\n            Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));\n            error_in_archive = PK_WARN;   /* didn't find sig */\n        }\n\n        /* Set specific return code when no files have been found. */\n        if (members == 0L && error_in_archive <= PK_WARN)\n            error_in_archive = PK_FIND;\n\n    }\n\n    return error_in_archive;\n\n} /* end function list_files() */\n\n\n\n\n\n#ifdef TIMESTAMP\n\n/************************/\n/* Function fn_is_dir() */\n/************************/\n\nstatic int fn_is_dir(__G)    /* returns TRUE if G.filename is directory */\n    __GDEF\n{\n    extent fn_len = strlen(G.filename);\n    register char   endc;\n\n    return  fn_len > 0 &&\n            ((endc = lastchar(G.filename, fn_len)) == '/' ||\n             (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/') &&\n              endc == '\\\\'));\n}\n\n\n\n\n\n/*****************************/\n/* Function get_time_stamp() */\n/*****************************/\n\nint get_time_stamp(__G__ last_modtime, nmember)  /* return PK-type error code */\n    __GDEF\n    time_t *last_modtime;\n    ulg *nmember;\n{\n    int do_this_file=FALSE, error, error_in_archive=PK_COOL;\n    ulg j;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n    min_info info;\n\n\n/*---------------------------------------------------------------------------\n    Unlike extract_or_test_files() but like list_files(), this function works\n    on information in the central directory alone.  Thus we have a single,\n    large loop through the entire directory, searching for the latest time\n    stamp.\n  ---------------------------------------------------------------------------*/\n\n    *last_modtime = 0L;         /* assuming no zipfile data older than 1970 */\n    *nmember = 0L;\n    G.pInfo = &info;\n\n    for (j = 1L;; j++) {\n\n        if (readbuf(__G__ G.sig, 4) == 0)\n            return PK_EOF;\n        if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a CentDir entry? */\n            if (((unsigned)(j - 1) & (unsigned)0xFFFF) ==\n                (unsigned)G.ecrec.total_entries_central_dir) {\n                /* \"j modulus 64k\" matches the reported 16-bit-unsigned\n                 * number of directory entries -> probably, the regular\n                 * end of the central directory has been reached\n                 */\n                break;\n            } else {\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(CentSigMsg), j));\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(ReportMsg)));\n                return PK_BADERR;   /* sig not found */\n            }\n        }\n        /* process_cdir_file_hdr() sets pInfo->lcflag: */\n        if ((error = process_cdir_file_hdr(__G)) != PK_COOL)\n            return error;       /* only PK_EOF defined */\n        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != PK_OK)\n        {        /*  ^-- (uses pInfo->lcflag) */\n            error_in_archive = error;\n            if (error > PK_WARN)   /* fatal:  can't continue */\n                return error;\n        }\n        if (G.extra_field != (uch *)NULL) {\n            free(G.extra_field);\n            G.extra_field = (uch *)NULL;\n        }\n        if ((error = do_string(__G__ G.crec.extra_field_length, EXTRA_FIELD))\n            != 0)\n        {\n            error_in_archive = error;\n            if (error > PK_WARN)      /* fatal */\n                return error;\n        }\n        if (!G.process_all_files) {   /* check if specified on command line */\n            unsigned i;\n\n            if (G.filespecs == 0)\n                do_this_file = TRUE;\n            else {  /* check if this entry matches an `include' argument */\n                do_this_file = FALSE;\n                for (i = 0; i < G.filespecs; i++)\n                    if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {\n                        do_this_file = TRUE;\n                        break;       /* found match, so stop looping */\n                    }\n            }\n            if (do_this_file) {  /* check if this is an excluded file */\n                for (i = 0; i < G.xfilespecs; i++)\n                    if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {\n                        do_this_file = FALSE;  /* ^-- ignore case in match */\n                        break;\n                    }\n            }\n        }\n\n        /* If current file was specified on command line, or if no names were\n         * specified, check the time for this file.  Either way, get rid of the\n         * file comment and go back for the next file.\n         * Directory entries are always ignored, to stay compatible with both\n         * Zip and PKZIP.\n         */\n        if ((G.process_all_files || do_this_file) && !fn_is_dir(__G)) {\n#ifdef USE_EF_UT_TIME\n            if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n                G.tz_is_valid &&\n#endif\n                (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,\n                                  G.crec.last_mod_dos_datetime, &z_utime, NULL)\n                 & EB_UT_FL_MTIME))\n            {\n                if (*last_modtime < z_utime.mtime)\n                    *last_modtime = z_utime.mtime;\n            } else\n#endif /* USE_EF_UT_TIME */\n            {\n                time_t modtime = dos_to_unix_time(G.crec.last_mod_dos_datetime);\n\n                if (*last_modtime < modtime)\n                    *last_modtime = modtime;\n            }\n            ++*nmember;\n        }\n        SKIP_(G.crec.file_comment_length)\n\n    } /* end for-loop (j: files in central directory) */\n\n/*---------------------------------------------------------------------------\n    Double check that we're back at the end-of-central-directory record.\n  ---------------------------------------------------------------------------*/\n\n    if (memcmp(G.sig, end_central_sig, 4)) {    /* just to make sure again */\n        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));\n        error_in_archive = PK_WARN;\n    }\n    if (*nmember == 0L && error_in_archive <= PK_WARN)\n        error_in_archive = PK_FIND;\n\n    return error_in_archive;\n\n} /* end function get_time_stamp() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n\n/********************/\n/* Function ratio() */    /* also used by ZipInfo routines */\n/********************/\n\nint ratio(uc, c)\n    zusz_t uc, c;\n{\n    zusz_t denom;\n\n    if (uc == 0)\n        return 0;\n    if (uc > 2000000L) {    /* risk signed overflow if multiply numerator */\n        denom = uc / 1000L;\n        return ((uc >= c) ?\n            (int) ((uc-c + (denom>>1)) / denom) :\n          -((int) ((c-uc + (denom>>1)) / denom)));\n    } else {             /* ^^^^^^^^ rounding */\n        denom = uc;\n        return ((uc >= c) ?\n            (int) ((1000L*(uc-c) + (denom>>1)) / denom) :\n          -((int) ((1000L*(c-uc) + (denom>>1)) / denom)));\n    }                            /* ^^^^^^^^ rounding */\n}\n\n\n\n\n\n/************************/\n/*  Function fnprint()  */    /* also used by ZipInfo routines */\n/************************/\n\nvoid fnprint(__G)    /* print filename (after filtering) and newline */\n    __GDEF\n{\n    char *name = fnfilter(G.filename, slide, (extent)(WSIZE>>1));\n\n    (*G.message)((zvoid *)&G, (uch *)name, (ulg)strlen(name), 0);\n    (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n\n} /* end function fnprint() */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/Contents",
    "content": "Contents of the \"macos\" sub-archive for UnZip 5.42 and later:\n\n  Contents          this file\n  README.TXT        Dirk Haase's infos on updated Macintosh ports of Zip/UnZip\n  HISTORY.TXT       Dirk Haase's MacOS specific ChangeLog\n\n  UnZp.h            config header used to build standalone app with GUI\n  UnZpLib.h         config header used to build a static library\n  UnZpSFX.h         config header used to build the SFX stub\n  UnZpSx.h          config header for building a standalone app. with MW Sioux\n  UnZpPrj.xml       Metrowerks CodeWarrior pro5 project file (xml export file)\n\n  source/        subdirectory containing all sources:\n                  a) UnZip specific code\n    macbin3.c       macbinary III code, used for extraction of ZipIt archives\n    macbin3.h       macbinary III header, macbinary docu + public prototyping\n    macos.c         Mac-specific filesystem code\n    maccfg.h        Mac-specific configuration and global declarations\n    macdir.c        Macintosh Posix-style directory emulation (\"dirent\")\n    macdir.h        header file for directory emulation\n    macscreen.c     screen functions to be used in standalone UnZip application\n    macstat.c       Macintosh stat() emulation\n    macstat.h       header file for stat() emulation\n    macunzip.c      Macintosh standalone version main function\n    sxunzip.c       main function for use with static library (SIOUX)\n    unzip_rc.hqx    UnZip resource file for standalone application (BinHex)\n\n                  b) general utilities shared between Zip and UnZip\n    charmap.h       character mapping tables ISO 8859-1 <--> MacRoman\n    getenv.c        simulation of unix compatible getenv() on MacOS\n    helpers.c       some helper functions\n    helpers.h\n    macstuff.h      wrapper to pull in some \"MoreFiles\" filemanager stuff\n    mactime.c       replacement for broken Metrowerks RTL time functions\n    mactime.h\n    pathname.c      functions for handling MacOS HFS path- /filenames\n    pathname.h\n\nThe new UnZpPrj.hqx project file should be \"un-BinHex'ed\" into UnZpPrj,\nwhich builds the following targets:\n        Unzip (68k)       -> standalone unzip for 68k\n        Unzip (PPC)       -> standalone unzip for PPC\n        Unzip Lib (68k)   -> static library 68k\n        Unzip Lib (PPC)   -> static library PPC\n        Unzip Sioux (68k) -> MW Sioux standoalone App, good for debugging\n        Unzip Sioux (PPC) -> MW Sioux standoalone App, good for debugging\n\n\nBefore you start a build on your Macintosh:\n\nExtract \"*.hqx\" and \"source:*.hqx\" first!\nAnd PLEASE, read the MacOS specific documentation in README.TXT!\n\n\nThe resource files and the compiler project files are in BinHex form because\nthey contain Macintosh resource forks.  The resource info cannot be\nmaintained when handling (e.g. repacking) the master source collection on\nnon-Macintosh systems.  The BinHex form is the traditional way for\ntransferring such files via non-Macintosh systems.\nIt's also the safest since it uses only printable characters.  The \".hqx\"\nfiles must be converted with StuffitExpander or BinHex 4.0 (or equivalent)\non a Macintosh system before using them.\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/HISTORY.TXT",
    "content": "A free Macintosh Port of Info-ZIP's\nZip and UnZip\nBy Dirk Haase, d_haase@sitec.net\nHome page: www.sitec.net/maczip\nMirror page:\nwww.haase-online.de/dirk/maczip\n================================\n\n\n\n\n\nRelease MacZip ver1.07 beta 1\n22. Februray 2001\n-----------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.42\n\n2) CHG: {zip} switch to latest beta release\n         zip 2.40a\n\n\n\n\n\nRelease MacZip ver1.06 final\n22. Februray 2001\n-----------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.42\n\n2) CHG: switch to latest release of Apples\n        Universal Interfaces 3.3.2\n\n3) CHG: switch to latest release of\n        Morefiles 1.5\n\n\n\n\nRelease MacZip ver1.06 beta 2\n02. August 2000\n---------------\n\n1) CHG: {unzip} switch to latest beta release\n         unzip 5.42d\n\n\n\n\n\nRelease MacZip ver1.06 beta 1\n27. July 2000\n-------------\n\n1) CHG: {zip} switch to latest beta release\n         unzip 2.30\n\n2) CHG: {unzip} switch to latest beta release\n         unzip 5.42c\n\n\n\n\n\nRelease MacZip ver1.05 final\n27. July 2000\n-------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.41\n\n2) FIX: {unzip} Fixed \"unique unzip folder\" foldername handling\n\n3) FIX: {unzip} added prototype crc32() in macbin3.c\n\n4) CHG: {unzip/zip} added exported Codewarrior project-file in xml-format\n\n5) ADD: {unzip} added extra-field recognition for Mac SmartZip in\n         zipinfo.c and unzpriv.h.\n\n\n\n\n\nRelease MacZip ver1.04 final\n25. January 2000\n----------------\n\n\nFinal release of MacZip. All parts now\nin final release state !!\n\n1) Switch to MW Codewarrior pro 5.3\n\n2) CHG: {zip} switch (back) to latest final release\n         unzip 2.30\n\n3) CHG: {unzip} switch (back) to latest final release\n         unzip 5.40\n\n\n\n\nRelease MacZip ver1.04 beta 3\n05. October 1999\n----------------\n\n1) CHG: {zip} switch to latest source level\n         unzip 2.30o beta release\n\n2) CHG: {unzip} switch to latest source level\n         unzip 5.41c beta release\n\n3) ADD: {console} added menu to print the license\n\n\n\n\nRelease MacZip ver1.04 beta 2\n02. June 1999\n--------------\n\n1) FIX: {unzip} added one more criteria to make the recognition\n         of macbinary more save.\n\n2) FIX: {unzip} sometimes, archive entries without any extra field\n         caused problems; the default setting of the extra field\n         was not set back to 'unknown' properly.\n\n3) FIX: {zip} Archive filename with invalid characters like '/' gets\n         renamed. However, I do not check the complete path - needs\n         some more work here.\n\n4) FIX: {zip} Filename match was case sensitive.\n\n6) CHG: {zip} switch to latest source level\n         unzip 2.30m beta release\n\n7) CHG: {unzip} switch to latest source level\n         unzip 5.41b beta release\n\n8) FIX: {zip/unzip 68k only) I have found a wrong compiler setting\n         for the 68k version. Because of this wrong setting the 68k\n         version crashed.\n\n\n\n\nRelease MacZip ver1.04 beta 1\n30. March 1999\n--------------\n\n1) CHG: {unzip) switch to latest source level\n         unzip 5.41a beta release\n\n2) ADD: {all} Added message logging support for Syslogd\n        by Brian Bergstrand. Syslogd can be found at\n        http://www.classicalguitar.net/brian/apps/syslogd/\n        This feature is 'under construction'.\n\n3) FIX: {all} many small fixes and code cleanups\n\n\n\n\nRelease MacZip ver1.03\n27. March 1999\n--------------\n\n1) CHG: {console} Like Stuffit Expander MacZip quits automatically when\n         used with drag'n drop or as Helper App (Web-Browser).\n\n2) CHG: {console} Since Macintosh users are used to be guided by their\n        software in order not to do something stupid, I added a check\n        to post an extra warning if the options -m and data fork only\n        are both checked.\n        This behavior can be disabled: See Applescript example and\n        \"maczip.env\".\n\n3) CHG: {zip} switch from immediate deletion to moving to the\n        trash. Immediate deletion is now an option in \"maczip.env\".\n\n4) CHG: {zip} enhanced progress display.\n\n5) CHG: {zip) switch to latest source level\n         zip 2.3l beta release\n\n6) CHG: {unzip} The zip archive contains file names greater than\n        31 characters. When MacZip tries to unzip the file, the\n        FSpCreate command fails because the filename length is to\n        long. MacZip correct this problem by trying to truncate\n        the file names to the 31 character limit.\n\n7) FIX: {zip/console} A couple of minor fixes\n\n8) CHG: {zip} Switched file-globbing to the Info-ZIP version.\n\n\n\n\nRelease MacZip ver1.02\n14. February 1999\n-----------------\n\n1) CHG: {zip} Changed the rule of file inclusion if switch '-X'\n        is set. Following conditions are checked:\n        a) if length of resource-fork is equal zero *and* the\n              length of     data-fork is equal zero include the file.\n        b) if length of resource-fork  greater zero *and* the\n              length of     data-fork is equal zero don't include the file.\n        c) if length of     data-fork  greater zero include the file.\n\n2) CHG: {Console} Some users are very confused by the buttons \"START PATH\"\n        and \"ZIP ARCHIVE\". Somehow, it wasn't clear what the intended\n        meaning was. I changed the buttons to more clear labels on\n        them like: \"file or folder to compress\" and \"location of\n        compressed file\"\n\n3) CHG: {Console} I changed the menu structure to be more intuitive.\n\n4) FIX: {Console} Found a nasty bug which sometimes caused crashes\n        when the Zip / Unzip Dialogbox was used.\n\n5) CHG: {Console} Handling of file dialog is now a bit more restricted:\n        e.g: it's not possible to select a file if you have to select\n        a folder.\n\n\n\n\nRelease MacZip ver1.01\n30. January 1999\n----------------------\n\n1) CHG: {console} The use of the \"Current App\" mechanism was clumsy\n        and forces the user into the Zip or Unzip modes. This kind\n        of modality is not so good for the command line. It's now\n        neccessary to enter zip or unzip to choose the action.\n\n2) FIX: {console} When Applescript sends quit to MacZip the script\n        that is running shows a spinning cursor and MacZip\n        does not quit.\n\n3) FIX: {console} MacZip gots accidentally the wrong creator code\n        (from BBedit)\n\n\n\n\nFinal Release MacZip ver1.0\n---------------------------\n\nReleased 21. January 1999\n\n\n\n\n9. Beta release 06.December.1998\n---------------------------------\n\n1) CHG: {console} The checkbox of Filedialog (for extract path and file path)\n        \"Show all files\" is now selected by default.\n\n2) CHG: {unzip/standalone} changed prototypes of mac[f]printf() to return\n        an int number (better ANSI conformance);\n\n3) FIX: {unzip} repaired \"stdout/stderr\" mode of macwrite(). So func\n        MacMessagePrnt() is now obsolete and removed.\n\n4) ADD: {zip/unzip} Compressed Mac3 extra-fields are now supported\n        (Thanks to Christian Spieler)\n\n5) ADD: {unzip} Extraction of ZipIt archive are now supported. This support\n        is not complete: Filenames are correct but folder names are only\n        restored with the public directory names.\n\n6) ADD: {zip/unzip} Improved documentation.\n\n7) FIX: {unzip} Function isZipfile() is completely rewritten.\n\n8) CHG: {zip/unzip) switch to latest source level\n        zip 2.3i beta and unzip 5.4 final release\n\n9) ADD: Applescript event \"do_cmd\".\n\nUnless there are big bugs found, this release will be the last\nbeta release. The final release will come out in January 1999.\n\n\n\n\n8. Beta release 20.November.1998\n---------------------------------\n\n1) CHG: {zip/unzip) switch to latest source level\n        zip 2.3h beta and unzip 5.4 final release\n\n2) ADD: {zip} Zip finds \"namelocked\" files also, if switch \"-S\"\n        is set.\n\n3) FIX: {unzip} Function isZipfile() fails if the zip archive\n        has a comment.\n\n4) CHG: {zip} added some small speed improvements to pattern matching and\n        isZipFile() function.\n\n5) FIX: {unzip} Display of comments is fixed.\n        UzpMessagePrnt() is replaced by MacMessagePrnt(). I do not care\n        about ansi-bombs. I'm not sure, so this fix may be changed later.\n\n6) RMV: {unzip} Buildin More capability is removed since it's already built\n        into the GUI-App.\n\n\n\n7. Beta release 09.November.1998\n---------------------------------\n\n1) CHG: {all} switched to Metrowerks Codewarrior Pro 4\n\n2) FIX: {unzip} Display of comments stored in the zip-file is\n        now fixed\n\n3) FIX: {zip} Fixed display of the zip help-screen.\n\n4) CHG: {zip/unzip} Changed special dir 'Re$0urce.Fk' to 'XtraStuf.mac'\n        (see entry at 13.June.1998 item 3). I found it more descriptive for\n        users outside the mac-community.\n\n5) CHG: {all} switched to MoreFiles 1.4.9.\n\n6) CHG: {console} changed behaivor of the file open dialog: The select\n        button is now always enabled.\n\n7) ADD: {all} Environment variables are now supported.\n         Basically, it is possible to add timezone (= TZ environment variable)\n         support here, but it's not yet implemented.\n         See \"MacZip.Env\" for further info.\n\n8) RMV: {console} Targets \"zip only\" and \"unzip only\" are removed.\n\n\n\n6. Beta release 09.September.1998\n---------------------------------\n\n\n1) CHG: {Zip/Unzip} Metrowerks Standardlibrary time funktions are\n        rather broken and incomplete so I was forced to rewrite the\n        funktions: mktime(), localtime(), gmtime() and time().\n\n2) ADD: {Console} Added Pause Funktion for screen output.\n        The Pause-Function is selfadjusting: Count of lines is depending\n        on the window size.\n\n3) CHG: Extra-Field layout is changed: All datas are now in little-endian\n        format (see appnote)\n\n4) ADD: {Console} Added an option to test the archive automatically\n        after zipping. This option is only via Zip-Dialogbox available\n        because it needs the unzip-module also.\n\n5) CHG: {Zip} code is now up to date with the latest beta 2.3f.\n\n6) ADD: {Console} Added (drag'n) drop support. Drop on the MacZip icon.\n        The following situations are supported:\n                    1. drop of one or more zipfiles (action = unzip)\n                       each archive will be extracted in a separate folder\n                    2. drop of a folder (action = zip -r )\n                       The complete folder (inclusive sub-folders)\n                       will be zipped\n        Not (yet) supported is currently: dropping more than one file\n        to compress. Workaround: Put all your files in one folder and\n        drop that folder on MacZip.\n        MacZip recognize zip-archives automatically.\n\n\n5. Beta release 21.Aug.1998\n----------------------------\n\n\n1) ADD: {Console} Userinterface has now a Statusbar to show the\n        Progress.\n\n2) ADD: {Console} It's now possible to stop the run of Zip/Unzip\n        with the well known shortcut [Command] + [.]\n\n3) CHG: {Console} Improved user-entry routine.\n\n4) ADD: {Zip/Unzip} Crypt-code added. It's now possible to\n        encrypt/decrypt archives.\n\n5) RMV: {Unzip} Removed the warning of PKZip/Mac archive.\n        Unzip gets confused with the extra field of PKZip/Mac. So I assume\n        the extra field isn't compatible with Info-ZIP's definition.\n\n6) CHG: switched to Metrowerks Codewarrior Pro 3\n        this includes:\n        - new Universal Interfaces 3.1 Headers\n        - improved codegeneration\n\n7) CHG: {Zip} code is now up to date with the latest beta 2.3e.\n\n8) CHG: {Unzip} changed function names wprintf, wgets .. to macprintf, macgets ..\n        to avoid naming conflict standart library.\n\n9) ADD: {Zip/Unzip} FXinfo, Mac-Pathname, file-dates and Finder-Comments\n        are now stored in the extra-field. Extra-field layout is\n        changed accordingly. Unzip uses now the filename stored in the\n        extra-field when unzipping.\n\n10) CHG: {Unzip} code is now up to date with the latest beta 5.33g.\n\n11) CHG: {Unzip} code is (again) up to date with the latest beta 5.33h.\n\n12) ADD: {Unzip} following switches were added:\n       -J     [MacOS  only] ignore mac extra info. All macintosh\n              info are not restored. Datafork and resource-fork\n              are restored separatly.\n\n       -i     [MacOS  only] ignore filenames stored in mac extra\n              field. Use the most compatible filename stored in\n              the public field.\n\n       -E     [MacOS  only] show mac extra field during restoring\n\n13) ADD: {Zip/Unzip} Charset MacRoman to ISO8859 Latin and vice versa\n\n14) RMV: {Zip} -N option removed. This MacZip crashes using this option.\n         I will fix it later.\n\n\nI think I'm very close for a final release of \"MacZip 1.0\" :-)\n\n\n\n4. Beta release 27.June.1998\n----------------------------\n\n26.June.1998\n------------\n\n1) FIX: {Zip} extra field size value was wrong.\n\n\n\n25.June.1998\n------------\n\n1) CHG: {Zip} code is now up to date with the latest beta 2.3d.\n        So both modules, zip & unzip, uses now latest beta.\n\n2) ADD: {Zip} added a UT extra-field for better compatibility.\n\n3) CHG: {Unzip} changed the code to find the mac extra-field.\n        Unzip has to look for a mac extra-field because\n        mac-archives has now two extra-fields (UT + M3).\n\n4) CHG: {Unzip} changed the method to move extra-field data to\n        the internal extra-structure.\n        Old method was just BlockMove of the ef_structptr to ef_memptr.\n        This method was dangerous because not all members of the\n        structure seamless aligned. There are may be some fill\n        bytes in the structure depending on the compiler setting.\n\n5) ADD: {Unzip} added a warning if unzipping a ZipIt/PKZip archive.\n        ZipIt/PKZip archives are usually additionally coded somehow.\n        InfoZip's Unzip will *not* decode the files. So extracted\n        files are may be not decoded. (see also 6. and 7.)\n\n6) ADD: ZipIt (the Shareware Tool) has now a new extra-field signature:\n        0x2705. Found in \"ZipIt 1.3.8\". I added a new macro: EF_ZIPIT2\n\n7) ADD: Added PKWare's extra-field signature: 0xCF77.\n        Found in \"PKZIP v2.03\". I added a new macro: EF_PKMAC\n\n8) ADD: {console} It's now possible to save all screen outputs\n        to the disk.\n\n9) RMV: {console} this is the first beta without expire-date.\n\n\n16.June.1998\n------------\n\n1) FIX: {Unzip/console} Extract path now defaults to current-dir if\n        no path is given.\n\n2> CHG: {Unzip} creates now a extract-folder by default. This behavior\n        differs to the commandline tool of Unzip on other platforms.\n        However, for a mac-user is this behavior more convenient.\n\n\n3. Beta release 15.June.1998\n----------------------------\n\n15.June.1998\n------------\n\n1) CHG: {unzip/zip} I changed the layout of the extra field\n        to support more data.\n\n\n14.June.1998\n------------\n\n1) FIX: {Unzip} adjusted time_t value with an correct offset value.\n\n2) FIX: {Unzip} removed all unused code based on unfinished ideas by\n        former porter(s).\n\n3) CHG: use of shared code izshr 032.\n\n13.June.1998\n------------\n\n1) FIX: {Unzip} Filenames are only converted when needed. When zipping\n        with the switch 'datafork only' the filenames are shorted which\n        was wrong.\n\n2) CHG: {Unzip} code is now up to date with the latest beta 5.33f.\n\n3) CHG: {Zip} Changed the naming rule of filenames from old Johnny Lee's\n        to my implementation. Johnny Lee's idea is based on change of the\n        filenames which cases several problems when unziping on a non mac\n        plattform. My idea is to add a special directory: 'Re$0urce.Fk'.\n        For the future: Zip will create archives according the new nameing\n        rule. However unzip will be compatible with old nameing rule.\n        See also 4.\n\n4} ADD: {Unzip} Added a new nameing rule for resource forks filename.\n        Resource forks are now stored in a special directory: 'Re$0urce.Fk'.\n        This naming rule make it easier to for other platforms to use\n        mac zip-files.\n\n\n\n11.June.1998\n------------\n1) FIX: {Zip} Internal file attribute is set to BINARY by default\n        when zipping resource forks otherwise Unzip will create\n        sometimes wrong resource-forks.\n\n2) CHG: {Unzip} code is now up to date with the latest beta 5.33e.\n\n\n\n\n2. Beta release 10.June.1998\n--------------------------\n\n1) FIX: {Unzip} Long pathname fix solved. Unzip is now able to extract\n        archives with path longer than 256 chars.\n\n2) CHG: {Unzip} removed all conversion from c-style string to\n        pascal-string (see fix 1)\n\n3) ADD: {Unzip} Finderinfo of folders are also restored.\n\n4) ADD: {Console} Added info about current path in the command-line box.\n\n5) FIX: {Console} Construction of the command-line of the unzip-dialog\n        box fixed.\n\n\n\nFirst beta release 06.June.1998\n-----------------------------\n\nno history.\nJust to many code was neccessary to build the first mac-port.\n\n\nStart of the port MacZip\nFebruary 1998\n\n\n--------------------------------------------------------------------------------\nLegende:\n\nFIX: fixes a bug\nCHG: inform about changed items.\nADD: added feature\nRMV: removed Item\n\n{Unzip}   -> only related to the Unzip-module\n{Zip}     -> only related to the Zip-module\n             These are just libraries and are linked into the console-app.\n\n{Console} -> only related to the Userinterface (not SIOUX)\n             MacOS has no tool like a command-line. So it's neccessary\n             to write wrapper around the command-line tools.\n\n\n\n\nDirk Haase\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/README.TXT",
    "content": "A free Macintosh Port of Info-ZIP's\nZip and UnZip\nBy Dirk Haase, d_haase@sitec.net\nHome page: www.sitec.net/maczip\nMirror page:\nwww.haase-online.de/dirk/maczip\n================================\n\n\n\nAbstract:\n---------\nMacZip is a cross-platform compatible tool that includes\nboth Zip (for compression) and UnZip (for extraction).\n\nZip is a compression and file packaging utility for Unix,\nVMS, MSDOS, OS/2, Windows 9x, Windows NT, Atari, Macintosh,\nAmiga, Acorn RISC OS, and other systems.\n\nUnZip unpacks zip archives. The Zip and UnZip programs can\nprocess archives produced by PKZIP, and PKZIP and PKUNZIP\ncan work with archives produced by zip. Zip version 2.2 is\ncompatible with PKZIP 2.04.\n\nIf you are new to MacZip please read first the file\n\"ReadMe.1st\".\n\n\n\nLicense:\n--------\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n\n\n\nRequirements\n------------\nMacZip requires at least System 7 and a Macintosh with a\nminimum of a Motorola 68020 or PowerPC 601 processor. Other\nconfigurations may work but it is not tested at all.\n\nThe application is distributed as a fat binary with both\nregular 68K and native PowerPC versions included.\n\n\n\nInstallation\n------------\nMove the executable(s) somewhere--for example, drag it (or\nthem) to your Applications folder.  For easy access, make an\nalias in the Launcher Control Panel or directly on your\ndesktop. The GUI is very simple. It was not my intention to\nmake a full-blown GUI, however I think it is comfortable\nenough to use it as regular tool.\n\nThis port supports also Apple-event. So you can install it\nin your WWW-Browser as a helper app.\n\nFor more Info about the contents of this package, take a\nlook into the \"macos/Contents\" (or :macos:Contents) file.\nSome notes on how to rebuild the Macintosh applications can\nbe found in INSTALL.\n\n\n\nUsage:\n------\n\nBasically there are four ways to start MacZip:\n\na) Drag'n Drop\nb) using the Dialog box (Menu: File -> Zip/Unzip):\n\nPlease read the file \"ReadMe.1st\"\nfor the description of the items a and b.\n\nc) Using the Command line (Menu: File->Command Line):\n   The Zip & UnZip tools are command line tools. So the\n   behavior is exactly the same like the Zip & UnZip tools on\n   Unix or Windows/DOS. This means, if you want to zip some\n   files, you have to write a command line like this: \"zip\n   [switches] path_to_zip_archive path_to_files_folders\"\n\n   - Go to \"File\", select \"Command Line\" and the\n     \"MacZip Entry box\" Dialog Box appears.\n\n   An example:\n\n   a: your zip may be created at\n           Macintosh HD:applications:archive.zip\n\n   b: your files may be found at\n           Macintosh HD:somewhere:my_folder_to_archive:*\n\n   Note: At the end of the path there must be a filename or\n         a wildcard !\n   (see Footnotes: 1 wildcard, 2 Mac path names)\n\n   So the command line should look like (one line!):\n\n   zip \"Macintosh HD:applications:archive.zip\" \"Macintosh HD:somewhere:my_folder_to_archive:*\"\n\n   - Click on \"Enter\" to start the task.\n\n   Since you can not set a default folder you have to enter\n   always a full qualified path names. Full-qualified path\n   names are path names including the Volume name ! (see\n   Footnote: 2 Mac path names)\n\n\n\nd) Using Applescript:\n\nThere is only one additional event defined: \"do_cmd\". You\ncan enter every valid command line. The first word must be\n\"zip\" or \"unzip\" to select the action (compress or\nextraction).\n\nSee sample Applescript:\n\n    tell application \"MacZip (PPC)\"\n        activate\n        with timeout of 90000 seconds\n            do_cmd \"zip -rjjN Volume:archive \\\"My Volume:*\\\" \"\n        end timeout\n    end tell\n\nThis script opens MacZip, brings it to the foreground on the\nMac, starts the zip action with the command line: zip -rjjN\nVolume:archive \"My Volume:*\" .\n\n\nA short introduction is also available online:\nhttp://www.sitec.net/maczip/How-To-Do/\n\nIt's possible to stop the run of Zip/Unzip with the well\nknown shortcut [Command] + [.].\n\n\n---------------------------------------------------------------------------\n\nThere are some Mac-specific switches available.\nZip Module:\n       -df    [MacOS] Include only data-fork of files zipped into\n              the  archive.   Good for exporting files to foreign\n              operating-systems.  Resource-forks will be  ignored\n              at all.\n\n       -jj    [MacOS] record Fullpath (+ Volname).  The  complete\n              path  including  volume  will be stored. By default\n              the relative path will be stored.\n\n       -S     [MSDOS, OS/2, WIN32 and ATARI] Include  system  and\n              hidden files.\n              [MacOS]  Includes finder invisible files, which are\n              ignored otherwise.\n\nUnzip Module:\n       -E     [MacOS only] display contents of MacOS extra  field\n              during restore operation.\n\n       -i     [MacOS only] ignore filenames stored in MacOS extra\n              fields.  Instead,  the  most  compatible   filename\n              stored in the generic part of the entry's header is\n              used.\n\n       -J     [MacOS only] ignore MacOS extra fields.  All Macin-\n              tosh  specific  info  is  skipped.  Data-fork   and\n              resource-fork are restored as separate files.\n\n\nSelect [File]->[Get Help on Zip/Unzip] for a complete list\nof switches.\n\n\n\nLimitations / Problems:\n-----------------------\n\n    - Aliases are not supported. I tried, but I got broken\n      aliases. This port will silently ignore all aliases.\n      It's on my to-do list for future releases.\n\n    - Zip needs much memory to compress many files: You may need\n      to increase the 'Preferred Size' in 'Get Info'. Values of 12\n      Megabytes or more are possible\n\n    - Unzip needs about 500 Kbytes of memory to unzip no matter\n      how many files were compressed and expanded.\n\n    - and finally one big macintosh-related problem:\n      This port has one weak point: It's based on path names.\n      As you may be already know: Path names are not unique on a Mac !\n      The main reason is that an attempt to implement support exact\n      saving of the MacOS specific internal file structures would\n      require a throughout rewrite of major parts of shared code,\n      probably sacrifying compatibility with other systems. I have\n      no solution at the moment. The port will just warn you if you\n      try zip from / to a volume which has a duplicate name.\n      MacZip has problems to find the archive or the files. My\n      (Big) recommendation: Name all your volumes with a unique\n      name and MacZip will run without any problem.\n\n\nKnown Bugs:\n\n    - crypted files in a zip archive are sometimes corrupt:\n      I get an error message: invalid compressed data to inflate.\n      Appearance of this error is purely be chance: I did a small\n      test: Unzipping an archive containing 3589 files 56 files\n      fails to unzip, so about 1.5%. Root cause is completely\n      unclear to me :(\n\nI strongly recommend to test your archive (e.g. unzip -t archive).\n\n\n\n\n\nZip Programs / Macintosh Extra-Data:\n-----------------------------------------\nA brief overview:\nCurrently, as far as I know, there are 6 Zip programs\navailable for the Macintosh platform. These programs build\n(of course) different variants of Zip files:\n\n    - Info-ZIP's first Port of Zip. Ported by Johnny Lee\n      This port is rather outdated and no longer supported (since 1992).\n      68K only. Only minimal Mac-info is stored\n      (Creator/Type, Finder attributes). Creator/Type: '????' / '????'\n      Until year 1998, only UnZip 5.32 survived.\n\n    - ZipIt by Tom Brown. This is Shareware and still supported I think.\n      ZipIt has a nice GUI, but I found it can't handle large Zip files\n      quite well. ZipIt compresses Macintosh files using the Mac Binary\n      format. So, transferring files to other platforms is not so easy.\n      Only minimal Mac-info is stored (Creator/Type, Finder attributes).\n      Mac filenames are changed to a most compatible filename.\n      Creator/Type: 'ZIP ' / 'ZIP '\n\n    - PKZIP/mac v2.03/210d. This is Shareware.\n      This Zip implementation for the Mac can be found on ASI's web site\n      (http://www.asizip.com/products/products.htm).  The name of this\n      program is misleading, it is NOT a product from PKWARE.  ASI's last\n      release version is v2.03, and they also offer a newer beta version\n      PKZIP/mac 210d. But even the Beta version is rather outdated (1995).\n      Only minimal Mac-info is stored (Creator/Type, Finder attributes).\n      The Zipfile format looks like incompatible to other platforms.\n      (More details about the compatibility issue can be found in\n      proginfo/3rdparty.bug!). Type: 'PKz1'\n      Mac filenames are restored without any change.\n\n    - Aladdin DropZip 1999, This is Shareware. Aladdin chose\n      the format of ZipIt. Therefore, it has the some drawbacks\n      like ZipIt.\n      Creator/Type: 'SITx' / 'ZIP '\n\n    - SmartZip 1.0 1999 - by Marco Bambini Vampire Software.\n      This is Shareware. SmartZip compresses Macintosh files using the\n      Mac Binary. Therefore, it has the same drawbacks like ZipIt.\n      Creator/Type: 'dZIP' / 'ZIP '\n\nand finally:\n    - Info-ZIP's latest Port of Zip. MacZip 1.0. Ported by me :-)\n      It is supported (of course) and up to date. Full set of macintosh\n      info is stored: Creator/Type, Finder attributes, Finder comments,\n      MacOS 8.0 Folder settings, Icon/Folder Positions ...\n      Mac filenames are restored without any change.\n      Creator/Type: 'IZip' / 'ZIP '\n\n\nCompatibility of my port; Extraction:\n   - Archives from Info-ZIP's first port (by Johnny Lee) are\n     still compatible.\n   - Extraction of ZipIt archives is supported. This support\n     is not complete: Filenames are correct but Directory names\n     are sometimes mangled to a DOS compatible form. Segmented\n     archives are not supported.\n   - PKZiP/mac archive files are extracted without resource-forks\n     and without any Finder info. I have no information about\n     that zip format.\n\nCompatibility of my port; Compression:\n   - My port supports only the new Info-ZIP format (introduced\n     with this port). Therefore archives created by MacZip 1.0\n     (March 1999) must be extracted with this version or later\n     releases of Info-ZIP's UnZip to restore the complete set of\n     Macintosh attributes.\n\nNote: This port is complete unrelated to the shareware ZipIt.\nEven more, handling of special Macintosh attributes is\nincompatible with ZipIt. This port (MacZip) may be used to\nextract archives created by ZipIt, but make sure that you\nget the result as you expected.\n\n\n\nMacintosh Files; File Forks:\n----------------------------\n\nAll Macintosh files comprise two forks, known as the data\nfork and the resource fork.  Unlike the bytes stored in the\nresource fork, the bytes in the data fork do not have to\nexhibit any particular internal structure. The application\nis responsible for interpreting the bytes in the data fork\nin whatever manner is appropriate. The bytes in the resource\nfork usually have a defined internal structure and contain\ndata object like menus, dialog boxes, icons and pictures.\nAlthough all Macintosh files contain both a data fork and a\nresource fork, one or both of these forks may be empty.\n\nMacZip stores data-forks and resource-forks separately. The\nZipfile format does not allow to store two archive entries\nusing exactly the same name. My solution is to modify the\nPath name of the resource-fork. All resource-fork names are\nprepended with a leading special directory named\n\"XtraStuf.mac\". So, when extracting on a Mac, you should\nnever see this directory \"XtraStuf.mac\" on your *disk*.\n\nOn all foreign systems that support directories in filenames\n(e.g.: OS/2, Unix, DOS/Windows, VMS) you will get a\ndirectory \"XtraStuf.mac\" when extracting MacZip archives.\nYou can delete the complete directory \"XtraStuf.mac\" since\nMac resources do not make much sense outside the MacOS\nworld.\n\n\n\nText encoding; Charsets of the Filenames:\n-----------------------------------------\n\nThe following information is only important if you plan to\ntransfer archives across different platforms/language systems:\n\nA typical Zip archive does not support different charsets.\nAll filenames stored in the public area (= accessible by\nforeign systems other than MacOS) must be coded in the\ncharset ISO-8859-1 (CP1252 in the Microsoft Windows world)\nor CP850 (DOSLatin1). The latter should only be used by Zip\nprograms that mark the archive entries as \"created under\nDOS\". Apart from Macs, the commonly used platforms either\nsupport ISO-8859-1 directly, or are compatible with it. To\nachieve maximum compatibility, MacZip convert filenames from\nthe Mac OS Roman character set to ISO-8859-1 and vice versa.\nBut not every char of the charset MacRoman has their\nequivalent in ISO-8859-1. To make the mapping in most cases\npossible, I chose most similar chars or at least the MIDDLE\nDOT.\n\nMac OS Roman character set is used for at least the\nfollowing Mac OS localizations: U.S., British, Canadian\nFrench, French, Swiss French, German, Swiss German, Italian,\nSwiss Italian, Dutch, Swedish, Norwegian, Danish, Finnish,\nSpanish, Catalan, Portuguese, Brazilian, and the default\nInternational system.\n\nIn all Mac OS encodings, character codes 0x00-0x7F are\nidentical to ASCII, except that\n  - in Mac OS Japanese, yen sign replaces reverse solidus\n  - in Mac OS Arabic, Farsi, and Hebrew, some of the\n    punctuation in this range is treated as having strong\n    left-right directionality, although the corresponding\n    Unicode characters have neutral directionality\nSo, for best compatibility, confine filenames to the standard\n7-bit ASCII character set.\n\nIf you generate a filename list of your archive (unzip -l),\nyou will see the converted filenames. Your can also extract\nthe archive with the switch '-i' (= ignore mac filenames),\nand test your result.\n\nThis MacZip port uses its own filename stored in the\narchive. At the moment, the filename will be not converted.\nHowever, I'm planning to add support for Unicode.\n\nCurrently, the following Mac OS encodings are NOT supported:\nJapanese, ChineseTrad, Korean, Arabic, Hebrew, Greek,\nCyrillic, Devanagari, Gurmukhi, Gujarati, Oriya, Bengali,\nTamil, Telugu Kannada, Malayalam, Sinhalese, Burmese, Khmer,\nThai, Laotian, Georgian, Armenian, ChineseSimp, Tibetan,\nMongolian, Ethiopic, Vietnamese, ExtArabic and finally:\nSymbol - this is the encoding for the font named \"Symbol\".\nDingbats - this is the encoding for the font named \"Zapf Dingbats\".\nIf you extract an archive coded with one of these\ncharsets you will probably get filenames with funny\ncharacters.\n\nThese problems apply only to filenames and NOT to the file\ncontent.\nof course: The content of the files will NEVER be converted !!\n\n\n\nFile-/Creator Type:\n-------------\n\nThis port uses the creator type 'IZip' and it is registered\nat Apple (since 08. March 1998). File types can not be\nregistered any more. This port uses 'ZIP ' for Zip archive\nfiles. The creator 'IZip' type should be used for all future\nversions of MacZip.\n\n\n\nHints for proper restoration of file-time stamps:\n-------------------------------------------------\n\nUnZip requires the host computer to have proper time zone\ninformation in order to handle certain tasks correctly (see\nunzip.txt).  To set the time zone on the Macintosh, go to\nthe Map Control Panel and enter the correct number of hours\n(and, in a few locales, minutes) offset from Universal\nTime/Greenwich Mean Time.  For example, the US Pacific time\nzone is -8 hours from UTC/GMT during standard (winter) time\nand -7 hours from UTC/GMT during Daylight Savings Time.  The\nUS Eastern time zone is -5 hours during the winter and -4\nhours during the summer.\n\nDiscussion of Daylight Savings Time\n-----------------------------------\nThe setting in the Date & Time control panel for Daylight\nSavings time is a universal setting. That is, it assumes\neverybody in the world is observing Daylight Savings time\nwhen its check box is selected.\n\nIf other areas of the world are not observing Daylight\nSavings time when the check box is selected in the Date &\nTime control panel, then the Map control panel will be off\nby an hour for all areas that are not recognizing Daylight\nSavings time.\n\nConversely, if you set the Map control panel to an area that\ndoes not observe Daylight Savings time and deselect/uncheck\nthe check box for Daylight Savings time in the Date & Time\ncontrol panel, then time in all areas celebrating Daylight\nSavings time will be off by an hour in the Map control\npanel.\n\nExample:\n     In the case of Hawaiians, sometimes they are three hours\n     behind Pacific Standard Time (PST) and sometimes two hours\n     behind Pacific Daylight Time (PDT). The Map control panel\n     can only calculate differences between time zones relative\n     to Greenwich Mean Time (GMT). Hawaii will always show up as\n     three hours past the Pacific time zone and five hours past\n     the Central time zone.\n\n     When Hawaiians are not observing Daylight Savings time, but\n     the rest of the country is, there is no combination of\n     settings in Map and Date & Time control panels which will\n     enable you to display Hawaiian local time correctly AND\n     concurrently display the correct time in other places that\n     do observe Daylight Savings time.\n\n     The knowledge about which countries observe Daylight Savings\n     time and which do not is not built into the Map control\n     panel, so it does not allow for such a complex calculation.\n\n     This same situation also occurs in other parts of the world\n     besides Hawaii. Phoenix, Arizona is an example of an area of\n     the U.S. which also does not observe Daylight Savings time.\n\nConclusion:\nMacZip only knows the GMT and DST offsets of the\ncurrent time, not for the time in question.\n\n\nProjects & Packages:\n--------------------\n\nA Note to version numbers: Version of MacZip is currently\n1.06 and is based on the zip code version 2.3 and unzip code\nversion 5.42. See About Box for current version and compiler\nbuild date.\n\nBecause of the amount of sources I splitted this port into\nseveral projects. See http://www.sitec.net/maczip for\nupdates.\n\n- core source parts:\n    unzxxx.zip\n    zipxxx.zip\n      These archives contains the main parts of the port. You can\n      build libraries and a standalone App with Metrowerks\n      standard console SIOUX. They contain only sources, no\n      executables. These archives are exact copies of the standard\n      Info-ZIP source distributions; they were only repackaged\n      under MacOS using MacZip, with one minor addition: For those\n      files that are stored in BinHex'ed format in the Info-ZIP\n      reference source archives, unpacked version that are ready\n      for use have been added.\n\n- additional source part:\n    MacZipxxx.zip: contains all the GUI stuff and the project\n      files to build the main-app.  Only sources of the GUI, no\n      zip or unzip code. To build MacZip successfully you will\n      need to also download the zip and unzip packages.\n\n- executables:\n    MacZipxxxnc.hqx: contains only executables and 'README.TXT',\n                     This version is without en-/decryption support !\n    MacZipxxxc.hqx:  contains only executables and 'README.TXT',\n                     This version supports en-/decryption !\n\n- encryption sources:\n    zcryptxx.zip: To build crypt versions of MacZip.\n    download from ftp://ftp.icce.rug.nl/infozip/ (and subdirectories)\n\n- documentation:\n    MacZipDocu.zip: contains some further docus about the algorithm,\n                    limits, Info-ZIP's appnote and a How-to-do Webpage.\n\n\nCredits:\n--------\n\nMacstuff.c and recurse.c: All the functions are from More Files.\nMore Files fixes many of the broken or underfunctional parts of\nthe file system. Thanks to Jim Luther. (see morefiles.doc)\n\n\n\n\n---------------------------------------------------------------------------\nFootnotes:\n\n1. wildcard:\n    The '*' is a wildcard and means 'all files'\n    Just in case you don't know wildcards:\n    '*' is a place holder for any character.\n    e.g.:\n    \"this*\" matches with \"this_file\" or  \"this_textfile\" but it\n    doesn't match with \"only_this_file\" or  \"first_this_textfile\"\n    \"*this*\" matches with \"this_file\" or  \"this_textfile\" AND\n    matches with \"only_this_file\" or  \"first_this_textfile\"\n\n\n2. Mac pathnames:\nThe following characteristics of Macintosh pathnames should\nbe noted:\n\n    A full pathname never begins with a colon, but must contain\n    at least one colon.\n    A partial pathname always begins with a colon separator except\n    in the case where the file partial pathname is a simple file or\n    directory name.\n    Single trailing separator colons in full or partial pathnames\n    are ignored except in the case of full pathnames to volumes.\n    In full pathnames to volumes, the trailing separator colon is\n    required.\n    Consecutive separator colons can be used to ascend a level\n    from a directory to its parent directory. Two consecutive\n    separator colons will ascend one level, three consecutive\n    separator colons will ascend two levels, and so on. Ascending\n    can only occur from a directory; not a file.\n\n\n\n\n\n---------------------------------------------------------------------------\n\nDirk Haase\n==========\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/UnZp.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  UnZp.h\n\n  This header-files is global to the project Unzip standalone.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define MACUNZIP_STANDALONE\n#define MACUNZIP\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing */\n#undef getc\n#undef getchar\n#undef putchar\n#undef putc\n\n#ifndef    TRUE\n#define    TRUE 1\n#endif  /* TRUE */\n#ifndef    FALSE\n#define    FALSE 0\n#endif  /* FALSE */\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n#include <Fonts.h>\n#include <ToolUtils.h>\n#include <Dialogs.h>\n#include <Devices.h>\n#include <StandardFile.h>\n\n\n\n\n/*\n#define MAC_DEBUG  1\n */\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                             \\\n    {                                                           \\\n    (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                       msg, __FILE__, __LINE__);                \\\n    }\n\n\n\n#define Assert_it(cond,msg,kind)                                    \\\n    {                                                               \\\n    if (!(cond))                                                    \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                           kind, msg, #cond, __FILE__, __LINE__);   \\\n        }                                                           \\\n    }\n\n\n\n#define AssertBool(b,msg) \\\n    Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) || \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg) \\\n    Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n               ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n               ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n               ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n               ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n               ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n               ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg) \\\n    Assert_it (((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), \\\n               msg,(\"AssertIntRange \"))\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else /* !MAC_DEBUG */\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif /* ?MAC_DEBUG */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/UnZpLib.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  UnZpLib.h\n\n  This header-files is global to the project UnZpLib.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define MacStaticLib\n#define MACUNZIP\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing (see printf.c)  */\n#undef getc\n#undef getchar\n#undef putchar\n#undef putc\n\n#ifndef    TRUE\n#define    TRUE 1\n#endif  /* TRUE */\n#ifndef    FALSE\n#define    FALSE 0\n#endif  /* FALSE */\n\n/*\n#define DEBUG_TIME\n */\n\n\n#define USE_EF_UT_TIME\n\n/* since we have no TZ environment variable on Macs\n   this option must be disabled */\n#undef IZ_CHECK_TZ\n\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n#include <Fonts.h>\n#include <ToolUtils.h>\n#include <Dialogs.h>\n#include <Devices.h>\n#include <StandardFile.h>\n\n\n/*\n#define MAC_DEBUG  1\n */\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                             \\\n    {                                                           \\\n    (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                       msg, __FILE__, __LINE__);                \\\n    }\n\n\n\n#define Assert_it(cond,msg,kind)                                    \\\n    {                                                               \\\n    if (!(cond))                                                    \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                           kind, msg, #cond, __FILE__, __LINE__);   \\\n        }                                                           \\\n    }\n\n\n\n#define AssertBool(b,msg) \\\n    Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) || \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg) \\\n    Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n               ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n               ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n               ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n               ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n               ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n               ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg) \\\n    Assert_it (((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), \\\n               msg,(\"AssertIntRange \"))\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else /* !MAC_DEBUG */\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif /* ?MAC_DEBUG */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/UnZpPrj.xml",
    "content": "<?xml version=\"1.0\"?>\r<?codewarrior exportversion=\"1.0\" ideversion=\"4.0\"?>\r<!DOCTYPE PROJECT [\r\r<!ELEMENT PROJECT (TARGETLIST, TARGETORDER, GROUPLIST, DESIGNLIST?)>\r<!ELEMENT TARGETLIST (TARGET+)>\r<!ELEMENT TARGET (NAME, SETTINGLIST, FILELIST?, LINKORDER?, SEGMENTLIST?, OVERLAYGROUPLIST?, SUBTARGETLIST?, SUBPROJECTLIST?)>\r<!ELEMENT NAME (#PCDATA)>\r<!ELEMENT USERSOURCETREETYPE (#PCDATA)>\r<!ELEMENT PATH (#PCDATA)>\r<!ELEMENT FILELIST (FILE*)>\r<!ELEMENT FILE (PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?, ROOTFILEREF?, FILEKIND?, FILEFLAGS?)>\r<!ELEMENT PATHTYPE (#PCDATA)>\r<!ELEMENT PATHROOT (#PCDATA)>\r<!ELEMENT ACCESSPATH (#PCDATA)>\r<!ELEMENT PATHFORMAT (#PCDATA)>\r<!ELEMENT ROOTFILEREF (PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?)>\r<!ELEMENT FILEKIND (#PCDATA)>\r<!ELEMENT FILEFLAGS (#PCDATA)>\r<!ELEMENT FILEREF (TARGETNAME?, PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?)>\r<!ELEMENT TARGETNAME (#PCDATA)>\r<!ELEMENT SETTINGLIST ((SETTING|PANELDATA)+)>\r<!ELEMENT SETTING (NAME?, (VALUE|(SETTING+)))>\r<!ELEMENT PANELDATA (NAME, VALUE)>\r<!ELEMENT VALUE (#PCDATA)>\r<!ELEMENT LINKORDER (FILEREF*)>\r<!ELEMENT SEGMENTLIST (SEGMENT+)>\r<!ELEMENT SEGMENT (NAME, ATTRIBUTES?, FILEREF*)>\r<!ELEMENT ATTRIBUTES (#PCDATA)>\r<!ELEMENT OVERLAYGROUPLIST (OVERLAYGROUP+)>\r<!ELEMENT OVERLAYGROUP (NAME, BASEADDRESS, OVERLAY*)>\r<!ELEMENT BASEADDRESS (#PCDATA)>\r<!ELEMENT OVERLAY (NAME, FILEREF*)>\r<!ELEMENT SUBTARGETLIST (SUBTARGET+)>\r<!ELEMENT SUBTARGET (TARGETNAME, ATTRIBUTES?)>\r<!ELEMENT SUBPROJECTLIST (SUBPROJECT+)>\r<!ELEMENT SUBPROJECT (FILEREF, SUBPROJECTTARGETLIST)>\r<!ELEMENT SUBPROJECTTARGETLIST (SUBPROJECTTARGET*)>\r<!ELEMENT SUBPROJECTTARGET (TARGETNAME, ATTRIBUTES?)>\r<!ELEMENT TARGETORDER (ORDEREDTARGET|ORDEREDDESIGN)*>\r<!ELEMENT ORDEREDTARGET (NAME)>\r<!ELEMENT ORDEREDDESIGN (NAME, ORDEREDTARGET+)>\r<!ELEMENT GROUPLIST (GROUP|FILEREF)*>\r<!ELEMENT GROUP (NAME, (GROUP|FILEREF)*)>\r<!ELEMENT DESIGNLIST (DESIGN+)>\r<!ELEMENT DESIGN (NAME, DESIGNDATA)>\r<!ELEMENT DESIGNDATA (#PCDATA)>\r]>\r<PROJECT>\r    <TARGETLIST>\r        <TARGET>\r            <NAME>Unzip Sioux (68k)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS 68K Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip Sioux (68k)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>OBJ </VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MPW Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.seg</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Large</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Unzip Sioux (68k)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1230662000</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>1024</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>512</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZpSx.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>a.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>64</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpSx.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Resource</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL Runtime68K.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MacOS.lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib68K (2i).Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <SEGMENTLIST>\r                <SEGMENT>\r                    <NAME>First Segment</NAME>\r                    <ATTRIBUTES>Protected, Locked</ATTRIBUTES>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>explode.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>extract.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>fileio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>list.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>match.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>zipinfo.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>process.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unshrink.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unreduce.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzpriv.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macdir.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crc32.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crypt.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>ttyio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>envargs.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>helpers.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>helpers.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstuff.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>pathname.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>pathname.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>maccfg.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>sxunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>UnZpSx.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>charmap.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSp_fopen.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>getenv.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>mactime.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.rc</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macos.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MSL Runtime68K.Lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MacOS.lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MathLib68K (2i).Lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>DirectoryCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FileCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSpCompat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FullPath.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>IterateDirectory.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreDesktopMgr.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFiles.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFilesExtras.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Optimization.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>OptimizationEnd.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Search.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </SEGMENT>\r            </SEGMENTLIST>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip Sioux (PPC)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS PPC Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip Sioux (PPC)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.s</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PPCAsm</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>XCOF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>XCOFF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Smart</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Toolbox68k.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22688</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZpSx.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>Inline</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>Unzip Sioux (PPC)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1230662000</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>2048</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>1024</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>512</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C++.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>InterfaceLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL RuntimePPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL SIOUX.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS>Debug</FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpSx.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Resource</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <LINKORDER>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpSx.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL SIOUX.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C++.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>InterfaceLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL RuntimePPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </LINKORDER>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip Lib (PPC)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS PPC Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip Lib (PPC)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.s</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PPCAsm</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>XCOF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>XCOFF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Smart</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Toolbox68k.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22688</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZpLib.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>Inline</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>P603e</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level4</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Library</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>Unzip Lib (PPC)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpLib.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <LINKORDER>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpLib.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </LINKORDER>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip Lib (68k)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS 68K Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip Lib (68k)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>OBJ </VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MPW Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.seg</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Large</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level4</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Library</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Unzip Lib (68k)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZpLib.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>a.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>64</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpLib.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <SEGMENTLIST>\r                <SEGMENT>\r                    <NAME>First Segment</NAME>\r                    <ATTRIBUTES>Protected, Locked</ATTRIBUTES>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>explode.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>extract.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>fileio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>list.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>match.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>zipinfo.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>process.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unshrink.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unreduce.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzpriv.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macdir.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>maccfg.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>sxunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>UnZpLib.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macos.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crypt.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>ttyio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>DirectoryCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FileCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSpCompat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FullPath.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>IterateDirectory.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreDesktopMgr.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFiles.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFilesExtras.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Optimization.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>OptimizationEnd.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Search.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </SEGMENT>\r            </SEGMENTLIST>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip (PPC)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS PPC Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip (PPC)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.s</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PPCAsm</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>XCOF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>XCOFF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Smart</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Toolbox68k.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22688</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZp.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>Inline</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>Unzip (PPC)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1230662000</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>2048</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>1024</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>512</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C++.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>InterfaceLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL RuntimePPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL SIOUX.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS>Debug</FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macscreen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZp.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Resource</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>console.stubs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <LINKORDER>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macscreen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZp.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C++.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>InterfaceLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL RuntimePPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL SIOUX.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>console.stubs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </LINKORDER>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip (68k)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS 68K Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip (68k)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>OBJ </VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MPW Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.seg</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Large</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level4</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Unzip (68k)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZp.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>Inline</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>Unzip (PPC)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1230662000</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>2048</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>1024</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>512</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macscreen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZp.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.rc</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Resource</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSp_fopen.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>console.stubs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL Runtime68K.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MacOS.lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib68K (2i).Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Library</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <SEGMENTLIST>\r                <SEGMENT>\r                    <NAME>First Segment</NAME>\r                    <ATTRIBUTES>Preloaded, Protected, Locked</ATTRIBUTES>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>envargs.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>explode.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>extract.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>fileio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>list.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>match.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>zipinfo.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>process.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unshrink.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unreduce.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzpriv.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macdir.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crc32.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crypt.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>ttyio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>helpers.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>helpers.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstuff.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>pathname.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>pathname.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>maccfg.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macscreen.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>sxunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>UnZp.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>mactime.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>charmap.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSp_fopen.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>getenv.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.rc</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macos.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>console.stubs.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MSL Runtime68K.Lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MacOS.lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MathLib68K (2i).Lib</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>DirectoryCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FileCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSpCompat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FullPath.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>IterateDirectory.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreDesktopMgr.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFiles.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFilesExtras.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Optimization.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>OptimizationEnd.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Search.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </SEGMENT>\r            </SEGMENTLIST>\r        </TARGET>\r        <TARGET>\r            <NAME>Unzip Lib (CFM68k)</NAME>\r            <SETTINGLIST>\r\r                <!-- Settings for \"Source Trees\" panel -->\r                <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Custom Keywords\" panel -->\r                <SETTING><NAME>CustomColor1</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor2</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor3</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>CustomColor4</NAME>\r                    <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>\r                    <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>\r                    <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Access Paths\" panel -->\r                <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>UserSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>::</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::izshr:macos:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:CHeaders:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:PascalInterfaces:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:::MoreFiles:Sources:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r                <SETTING><NAME>SystemSearchPaths</NAME>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MSL:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:MacOS Support:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>SearchPath</NAME>\r                            <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                            <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                            <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>\r                        </SETTING>\r                        <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Target Settings\" panel -->\r                <SETTING><NAME>Linker</NAME><VALUE>MacOS 68K Linker</VALUE></SETTING>\r                <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>Targetname</NAME><VALUE>Unzip Lib (CFM68k)</VALUE></SETTING>\r                <SETTING><NAME>OutputDirectory</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"File Mappings\" panel -->\r                <SETTING><NAME>FileMappings</NAME>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Lib Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>OBJ </VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MPW Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.seg</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE>PEF Import 68K</VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>\r                    </SETTING>\r                    <SETTING>\r                        <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>\r                        <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>\r                        <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>\r                        <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>\r                        <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>\r                    </SETTING>\r                </SETTING>\r\r                <!-- Settings for \"Build Extras\" panel -->\r                <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>\r                <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>\r                    0002000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    0000000000000000000000000000000000000000000000000000000000000000\r                    00000000000000000000000000000000\r                </VALUE></PANELDATA>\r\r                <!-- Settings for \"Debugger Target\" panel -->\r                <SETTING><NAME>LogSystemMessages</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>\r                <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>\r                <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>AltExePath</NAME>\r                    <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>\r                    <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>\r                    <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>\r                </SETTING>\r                <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>\r                <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>\r                <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>\r\r                <!-- Settings for \"68K CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Large</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"68K Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level4</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"68K Linker\" panel -->\r                <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"68K Project\" panel -->\r                <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Library</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>Unzip Lib (CFM68k)</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_size</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Compiler\" panel -->\r                <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>UnZpLib.h</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"C/C++ Warnings\" panel -->\r                <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"CFM68K\" panel -->\r                <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>\r                <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>\r\r                <!-- Settings for \"FTP Panel\" panel -->\r                <SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_password</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_uploadDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ftp_port</NAME><VALUE>21</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_SendBin</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWFTP_Post_ShouldLog</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Command Line\" panel -->\r                <SETTING><NAME>MWCommandLine_Java_clsName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWCommandLine_Java_args</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Language\" panel -->\r                <SETTING><NAME>MWJava_Language_optimize</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_warnDeprecated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitMap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileNames</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_strictFileHierarchy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_emitHeaders</NAME><VALUE>NoNativeHeaders</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_packageFilter</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genComments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Language_genHeaders</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Java MacOS Settings\" panel -->\r                <SETTING><NAME>MWJava_MacOS_type</NAME><VALUE>JBindery</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_grow</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_profile</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_verify</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useHttpProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFTPProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_useFirewallProxy</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outfile</NAME><VALUE>JBoundApp</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_outcreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_maxMem</NAME><VALUE>1048576</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_minMem</NAME><VALUE>524288</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_red</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_green</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_blue</NAME><VALUE>65535</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutType</NAME><VALUE>1464421956</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinType</NAME><VALUE>1853189228</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxyPort</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_httpProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_fTPProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_firewallProxy</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_merge</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_write_old_rsrcs</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_jbindrundebug</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdoutfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_MacOS_stdinfile</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"Java Output\" panel -->\r                <SETTING><NAME>MWJava_Output_outputtype</NAME><VALUE>JarFile</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_outfile</NAME><VALUE>JavaClasses.jar</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_ftype</NAME><VALUE>1514754080</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_fcreator</NAME><VALUE>1297570384</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_genManifest</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_trunctype</NAME><VALUE>Front</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_deleteClasses</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Output_consoleApp</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"Java Project\" panel -->\r                <SETTING><NAME>MWJava_Proj_projtype</NAME><VALUE>Applet</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_runtimeArgs</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_mainClassName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppCreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppName</NAME><VALUE>Internet Explorer</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_HTMLAppWin32Name</NAME><VALUE>Iexplore.exe</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_compress</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_useVM</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_workingDir</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmarguments</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJava_Proj_vmName</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"JavaDoc Project\" panel -->\r                <SETTING><NAME>MWJavaDoc_Proj_Version</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Depricated</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Author</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Index</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Tree</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_SunResolveToSame</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Shortnames</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_Folder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_GenerateAPILinks</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_scope</NAME><VALUE>Public</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_fcreator</NAME><VALUE>1297303877</VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_encodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_decodingName</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWJavaDoc_Proj_javaPackagePath</NAME><VALUE>http://java.sun.com/products/jdk/1.1/docs/api/</VALUE></SETTING>\r\r                <!-- Settings for \"MacOS Merge Panel\" panel -->\r                <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                    <SETTING><VALUE>\u0005a</VALUE></SETTING>\r                    <SETTING><VALUE></VALUE></SETTING>\r                </SETTING>\r\r                <!-- Settings for \"PPC CodeGen\" panel -->\r                <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Disassembler\" panel -->\r                <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Global Optimizer\" panel -->\r                <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>\r                <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Linker\" panel -->\r                <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>\r                <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>\r\r                <!-- Settings for \"PPC PEF\" panel -->\r                <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPC Project\" panel -->\r                <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>a.out</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>384</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>64</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22720</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"PPCAsm Panel\" panel -->\r                <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>\r\r                <!-- Settings for \"Rez Compiler\" panel -->\r                <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>\r                <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>\r            </SETTINGLIST>\r            <FILELIST>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macdir.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>maccfg.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>sxunzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>UnZpLib.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macos.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macbin3.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r                <FILE>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                    <FILEKIND>Text</FILEKIND>\r                    <FILEFLAGS></FILEFLAGS>\r                </FILE>\r            </FILELIST>\r            <SEGMENTLIST>\r                <SEGMENT>\r                    <NAME>First Segment</NAME>\r                    <ATTRIBUTES>Protected, Locked</ATTRIBUTES>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>explode.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>extract.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>fileio.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>list.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>globals.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>match.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>zipinfo.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>inflate.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>process.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unshrink.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unreduce.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>unzpriv.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macdir.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>maccfg.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>sxunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>UnZpLib.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macos.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>crypt.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>DirectoryCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FileCopy.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FSpCompat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>FullPath.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>IterateDirectory.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreDesktopMgr.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFiles.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>MoreFilesExtras.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Optimization.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>OptimizationEnd.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>Search.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </SEGMENT>\r            </SEGMENTLIST>\r        </TARGET>\r    </TARGETLIST>\r\r    <TARGETORDER>\r        <ORDEREDTARGET><NAME>Unzip Sioux (68k)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip Sioux (PPC)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip Lib (PPC)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip Lib (68k)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip (PPC)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip (68k)</NAME></ORDEREDTARGET>\r        <ORDEREDTARGET><NAME>Unzip Lib (CFM68k)</NAME></ORDEREDTARGET>\r    </TARGETORDER>\r\r    <GROUPLIST>\r        <GROUP><NAME>Sources</NAME>\r            <FILEREF>\r                <TARGETNAME>Unzip (PPC)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>UnZp.h</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r            <FILEREF>\r                <TARGETNAME>Unzip Lib (PPC)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>UnZpLib.h</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r            <FILEREF>\r                <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>UnZpSx.h</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r            <GROUP><NAME>Mac-Specific</NAME>\r                <GROUP><NAME>include</NAME>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>maccfg.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.h</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </GROUP>\r                <GROUP><NAME>source</NAME>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macos.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macbin3.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macdir.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macstat.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip (PPC)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>sxunzip.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                    <FILEREF>\r                        <TARGETNAME>Unzip (PPC)</TARGETNAME>\r                        <PATHTYPE>Name</PATHTYPE>\r                        <PATH>macscreen.c</PATH>\r                        <PATHFORMAT>MacOS</PATHFORMAT>\r                    </FILEREF>\r                </GROUP>\r            </GROUP>\r            <GROUP><NAME>UnZip_H</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzpriv.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <GROUP><NAME>shared code Unzip &amp; Zip</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>getenv.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>ttyio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crc32.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>crypt.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>helpers.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>mactime.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>macstuff.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>pathname.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>charmap.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <GROUP><NAME>ObjS1</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unzip.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>envargs.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>explode.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <GROUP><NAME>ObjS2</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>extract.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>fileio.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>list.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>globals.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>match.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>zipinfo.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>inflate.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <GROUP><NAME>ObjS3</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>process.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unshrink.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>unreduce.c</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r        </GROUP>\r        <GROUP><NAME>Mac Libraries</NAME>\r            <GROUP><NAME>68k</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL Runtime68K.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MacOS.lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib68K (2i).Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <GROUP><NAME>PPC</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>InterfaceLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MathLib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL RuntimePPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <FILEREF>\r                <TARGETNAME>Unzip (PPC)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>console.stubs.c</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r        </GROUP>\r        <GROUP><NAME>ANSI Libraries</NAME>\r            <GROUP><NAME>68k</NAME>\r            </GROUP>\r            <GROUP><NAME>PPC</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL C++.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (PPC)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MSL SIOUX.PPC.Lib</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r            <FILEREF>\r                <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>FSp_fopen.c</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r        </GROUP>\r        <GROUP><NAME>FAT Target Files</NAME>\r        </GROUP>\r        <GROUP><NAME>Resources</NAME>\r            <FILEREF>\r                <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                <PATHTYPE>Name</PATHTYPE>\r                <PATH>unzip.rc</PATH>\r                <PATHFORMAT>MacOS</PATHFORMAT>\r            </FILEREF>\r        </GROUP>\r        <GROUP><NAME>MoreFiles</NAME>\r            <GROUP><NAME>CHeaders</NAME>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>DirectoryCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FileCopy.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FSpCompat.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>FullPath.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>IterateDirectory.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreDesktopMgr.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFiles.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>MoreFilesExtras.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Optimization.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>OptimizationEnd.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r                <FILEREF>\r                    <TARGETNAME>Unzip Sioux (68k)</TARGETNAME>\r                    <PATHTYPE>Name</PATHTYPE>\r                    <PATH>Search.h</PATH>\r                    <PATHFORMAT>MacOS</PATHFORMAT>\r                </FILEREF>\r            </GROUP>\r        </GROUP>\r    </GROUPLIST>\r\r</PROJECT>\r"
  },
  {
    "path": "deps/infozip/unzip60/macos/UnZpSFX.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  UnZpSFX.h\n\n  This header-files is global to the project UnzipSFX standalone.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define MACUNZIP_STANDALONE\n#define MACUNZIP\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing */\n#undef getc\n#undef getchar\n#undef putchar\n#undef putc\n\n#ifndef    TRUE\n#define    TRUE 1\n#endif  /* TRUE */\n#ifndef    FALSE\n#define    FALSE 0\n#endif  /* FALSE */\n\n#define SFX\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n#include <Fonts.h>\n#include <ToolUtils.h>\n#include <Dialogs.h>\n#include <Devices.h>\n#include <StandardFile.h>\n\nint ratio(unsigned long uc,unsigned long c);\n void fnprint(void);\n\n\n/*\n#define MAC_DEBUG  1\n */\n\n\n\n#include <ctype.h>\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                             \\\n    {                                                           \\\n    (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                       msg, __FILE__, __LINE__);                \\\n    }\n\n\n\n#define Assert_it(cond,msg,kind)                                    \\\n    {                                                               \\\n    if (!(cond))                                                    \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                           kind, msg, #cond, __FILE__, __LINE__);   \\\n        }                                                           \\\n    }\n\n\n\n#define AssertBool(b,msg) \\\n    Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) || \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg) \\\n    Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n               ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n               ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n               ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n               ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n               ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n               ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg) \\\n    Assert_it (((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), \\\n               msg,(\"AssertIntRange \"))\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else /* !MAC_DEBUG */\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif /* ?MAC_DEBUG */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/UnZpSx.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  UnZpSx.h\n\n  This header-files is global to the project Unzip Sioux.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define USE_SIOUX\n#define MACUNZIP\n\n#ifndef    TRUE\n#define    TRUE 1\n#endif  /* TRUE */\n#ifndef    FALSE\n#define    FALSE 0\n#endif  /* FALSE */\n\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n#include <Fonts.h>\n#include <ToolUtils.h>\n#include <Dialogs.h>\n#include <Devices.h>\n#include <StandardFile.h>\n\n/*\n#define MAC_DEBUG  1\n */\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                             \\\n    {                                                           \\\n    (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                       msg, __FILE__, __LINE__);                \\\n    }\n\n\n\n#define Assert_it(cond,msg,kind)                                    \\\n    {                                                               \\\n    if (!(cond))                                                    \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                           kind, msg, #cond, __FILE__, __LINE__);   \\\n        }                                                           \\\n    }\n\n\n\n#define AssertBool(b,msg) \\\n    Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) || \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg) \\\n    Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n               ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n               ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n               ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n               ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n               ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n               ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg) \\\n    Assert_it (((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), \\\n               msg,(\"AssertIntRange \"))\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else /* !MAC_DEBUG */\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif /* ?MAC_DEBUG */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/charmap.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __macos_charmap_h\n#define __macos_charmap_h\n\n/*\n\nConversion table from MacOS Roman to\n\"Western Europe & America\" Windows codepage 1252\n\n     Notes on Mac OS Roman:\n     ----------------------\n\n       Mac OS Roman character set is used for at least the following Mac OS\n       localizations: U.S., British, Canadian French, French, Swiss\n       French, German, Swiss German, Italian, Swiss Italian, Dutch,\n       Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,\n       Portuguese, Brazilian, and the default International system.\n\n       Not every char of the charset MacRoman has their equivalent\n       in Windows CodePage1252.\n       To make the mapping in most cases possible, I choosed\n       most similar chars or at least the BULLET. Chars that\n       do not have a direct match are marked with '***'\n\n       The Windows codepage 1252 contains the ISO 8859-1 \"Latin 1\" codepage,\n       with some additional printable characters in the range (0x80 - 0x9F),\n       that is reserved to control codes in the ISO 8859-1 character table.\n\nIn all Mac OS encodings, character codes 0x00-0x7F are identical to ASCII\n\n*/\n\n\n\nZCONST unsigned char MacRoman_to_WinCP1252[128] = {\n/*  Win CP1252          UniCode  UniCode Names       */\n    0xC4    ,       /*  0x00C4  #LATIN CAPITAL LETTER A WITH DIAERESIS      */\n    0xC5    ,       /*  0x00C5  #LATIN CAPITAL LETTER A WITH RING ABOVE     */\n    0xC7    ,       /*  0x00C7  #LATIN CAPITAL LETTER C WITH CEDILLA        */\n    0xC9    ,       /*  0x00C9  #LATIN CAPITAL LETTER E WITH ACUTE      */\n    0xD1    ,       /*  0x00D1  #LATIN CAPITAL LETTER N WITH TILDE      */\n    0xD6    ,       /*  0x00D6  #LATIN CAPITAL LETTER O WITH DIAERESIS      */\n    0xDC    ,       /*  0x00DC  #LATIN CAPITAL LETTER U WITH DIAERESIS      */\n    0xE1    ,       /*  0x00E1  #LATIN SMALL LETTER A WITH ACUTE        */\n    0xE0    ,       /*  0x00E0  #LATIN SMALL LETTER A WITH GRAVE        */\n    0xE2    ,       /*  0x00E2  #LATIN SMALL LETTER A WITH CIRCUMFLEX       */\n    0xE4    ,       /*  0x00E4  #LATIN SMALL LETTER A WITH DIAERESIS        */\n    0xE3    ,       /*  0x00E3  #LATIN SMALL LETTER A WITH TILDE        */\n    0xE5    ,       /*  0x00E5  #LATIN SMALL LETTER A WITH RING ABOVE       */\n    0xE7    ,       /*  0x00E7  #LATIN SMALL LETTER C WITH CEDILLA      */\n    0xE9    ,       /*  0x00E9  #LATIN SMALL LETTER E WITH ACUTE        */\n    0xE8    ,       /*  0x00E8  #LATIN SMALL LETTER E WITH GRAVE        */\n    0xEA    ,       /*  0x00EA  #LATIN SMALL LETTER E WITH CIRCUMFLEX       */\n    0xEB    ,       /*  0x00EB  #LATIN SMALL LETTER E WITH DIAERESIS        */\n    0xED    ,       /*  0x00ED  #LATIN SMALL LETTER I WITH ACUTE        */\n    0xEC    ,       /*  0x00EC  #LATIN SMALL LETTER I WITH GRAVE        */\n    0xEE    ,       /*  0x00EE  #LATIN SMALL LETTER I WITH CIRCUMFLEX       */\n    0xEF    ,       /*  0x00EF  #LATIN SMALL LETTER I WITH DIAERESIS        */\n    0xF1    ,       /*  0x00F1  #LATIN SMALL LETTER N WITH TILDE        */\n    0xF3    ,       /*  0x00F3  #LATIN SMALL LETTER O WITH ACUTE        */\n    0xF2    ,       /*  0x00F2  #LATIN SMALL LETTER O WITH GRAVE        */\n    0xF4    ,       /*  0x00F4  #LATIN SMALL LETTER O WITH CIRCUMFLEX       */\n    0xF6    ,       /*  0x00F6  #LATIN SMALL LETTER O WITH DIAERESIS        */\n    0xF5    ,       /*  0x00F5  #LATIN SMALL LETTER O WITH TILDE        */\n    0xFA    ,       /*  0x00FA  #LATIN SMALL LETTER U WITH ACUTE        */\n    0xF9    ,       /*  0x00F9  #LATIN SMALL LETTER U WITH GRAVE        */\n    0xFB    ,       /*  0x00FB  #LATIN SMALL LETTER U WITH CIRCUMFLEX       */\n    0xFC    ,       /*  0x00FC  #LATIN SMALL LETTER U WITH DIAERESIS        */\n    0x86    ,       /*  0x2020  #DAGGER     */\n    0xB0    ,       /*  0x00B0  #DEGREE SIGN        */\n    0xA2    ,       /*  0x00A2  #CENT SIGN      */\n    0xA3    ,       /*  0x00A3  #POUND SIGN     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  #BULLET     */\n    0xB6    ,       /*  0x00B6  #PILCROW SIGN       */\n    0xDF    ,       /*  0x00DF  #LATIN SMALL LETTER SHARP S     */\n    0xAE    ,       /*  0x00AE  #REGISTERED SIGN        */\n    0xA9    ,       /*  0x00A9  #COPYRIGHT SIGN     */\n    0x99    ,       /*  0x2122  #TRADE MARK SIGN        */\n    0xB4    ,       /*  0x00B4  #ACUTE ACCENT       */\n    0xA8    ,       /*  0x00A8  #DIAERESIS      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xC6    ,       /*  0x00C6  #LATIN CAPITAL LETTER AE        */\n    0xD8    ,       /*  0x00D8  #LATIN CAPITAL LETTER O WITH STROKE     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xB1    ,       /*  0x00B1  #PLUS-MINUS SIGN        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x00A5  #YEN SIGN       */\n    0xB5    ,       /*  0x00B5  #MICRO SIGN     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xAA    ,       /*  0x00AA  #FEMININE ORDINAL INDICATOR     */\n    0xBA    ,       /*  0x00BA  #MASCULINE ORDINAL INDICATOR        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xE6    ,       /*  0x00E6  #LATIN SMALL LETTER AE      */\n    0xF8    ,       /*  0x00F8  #LATIN SMALL LETTER O WITH STROKE       */\n    0xBF    ,       /*  0x00BF  #INVERTED QUESTION MARK     */\n    0xA1    ,       /*  0x00A1  #INVERTED EXCLAMATION MARK      */\n    0xAC    ,       /*  0x00AC  #NOT SIGN       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x83    ,       /*  0x0192  #LATIN SMALL LETTER F WITH HOOK     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xAB    ,       /*  0x00AB  #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK      */\n    0xBB    ,       /*  0x00BB  #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK     */\n    0x85    ,       /*  0x2026  #HORIZONTAL ELLIPSIS        */\n    0xA0    ,       /*  0x00A0  #NO-BREAK SPACE     */\n    0xC0    ,       /*  0x00C0  #LATIN CAPITAL LETTER A WITH GRAVE      */\n    0xC3    ,       /*  0x00C3  #LATIN CAPITAL LETTER A WITH TILDE      */\n    0xD5    ,       /*  0x00D5  #LATIN CAPITAL LETTER O WITH TILDE      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x96    ,       /*  0x2013  #EN DASH        */\n    0x97    ,       /*  0x2014  #EM DASH        */\n    0x93    ,       /*  0x201C  #LEFT DOUBLE QUOTATION MARK     */\n    0x94    ,       /*  0x201D  #RIGHT DOUBLE QUOTATION MARK        */\n    0x91    ,       /*  0x2018  #LEFT SINGLE QUOTATION MARK     */\n    0x92    ,       /*  0x2019  #RIGHT SINGLE QUOTATION MARK        */\n    0xF7    ,       /*  0x00F7  #DIVISION SIGN      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xFF    ,       /*  0x00FF  #LATIN SMALL LETTER Y WITH DIAERESIS        */\n    0x9F    ,       /*  0x0178  #LATIN CAPITAL LETTER Y WITH DIAERESIS      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xA4    ,       /*  0x00A4  #CURRENCY SIGN      */\n    0x8B    ,       /*  0x2039  #SINGLE LEFT-POINTING ANGLE QUOTATION MARK      */\n    0x9B    ,       /*  0x203A  #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x87    ,       /*  0x2021  #DOUBLE DAGGER      */\n    0xB7    ,       /*  0x00B7  #MIDDLE DOT     */\n    0x82    ,       /*  0x201A  #SINGLE LOW-9 QUOTATION MARK        */\n    0x84    ,       /*  0x201E  #DOUBLE LOW-9 QUOTATION MARK        */\n    0x89    ,       /*  0x2030  #PER MILLE SIGN     */\n    0xC2    ,       /*  0x00C2  #LATIN CAPITAL LETTER A WITH CIRCUMFLEX     */\n    0xCA    ,       /*  0x00CA  #LATIN CAPITAL LETTER E WITH CIRCUMFLEX     */\n    0xC1    ,       /*  0x00C1  #LATIN CAPITAL LETTER A WITH ACUTE      */\n    0xCB    ,       /*  0x00CB  #LATIN CAPITAL LETTER E WITH DIAERESIS      */\n    0xC8    ,       /*  0x00C8  #LATIN CAPITAL LETTER E WITH GRAVE      */\n    0xCD    ,       /*  0x00CD  #LATIN CAPITAL LETTER I WITH ACUTE      */\n    0xCE    ,       /*  0x00CE  #LATIN CAPITAL LETTER I WITH CIRCUMFLEX     */\n    0xCF    ,       /*  0x00CF  #LATIN CAPITAL LETTER I WITH DIAERESIS      */\n    0xCC    ,       /*  0x00CC  #LATIN CAPITAL LETTER I WITH GRAVE      */\n    0xD3    ,       /*  0x00D3  #LATIN CAPITAL LETTER O WITH ACUTE      */\n    0xD4    ,       /*  0x00D4  #LATIN CAPITAL LETTER O WITH CIRCUMFLEX     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xD2    ,       /*  0x00D2  #LATIN CAPITAL LETTER O WITH GRAVE      */\n    0xDA    ,       /*  0x00DA  #LATIN CAPITAL LETTER U WITH ACUTE      */\n    0xDB    ,       /*  0x00DB  #LATIN CAPITAL LETTER U WITH CIRCUMFLEX     */\n    0xD9    ,       /*  0x00D9  #LATIN CAPITAL LETTER U WITH GRAVE      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x88    ,       /*  0x02C6  #MODIFIER LETTER CIRCUMFLEX ACCENT      */\n    0x98    ,       /*  0x02DC  #SMALL TILDE        */\n    0xAF    ,       /*  0x00AF  #MACRON     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xB8    ,       /*  0x00B8  #CEDILLA        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95            /*  0x2022  # ***  BULLET       */\n };\n\n\n\nZCONST unsigned char WinCP1252_to_MacRoman[128] = {\n/*  Mac Roman           UniCode  UniCode Names       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xE2    ,       /*  0x201A  # SINGLE LOW-9 QUOTATION MARK       */\n    0xC4    ,       /*  0x0192  # LATIN SMALL LETTER F WITH HOOK        */\n    0xE3    ,       /*  0x201E  # DOUBLE LOW-9 QUOTATION MARK       */\n    0xC9    ,       /*  0x2026  # HORIZONTAL ELLIPSIS       */\n    0xA0    ,       /*  0x2020  # DAGGER        */\n    0xE0    ,       /*  0x2021  # DOUBLE DAGGER     */\n    0xF6    ,       /*  0x02C6  # MODIFIER LETTER CIRCUMFLEX ACCENT     */\n    0xE4    ,       /*  0x2030  # PER MILLE SIGN        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xDC    ,       /*  0x2039  # SINGLE LEFT-POINTING ANGLE QUOTATION MARK     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD4    ,       /*  0x2018  # LEFT SINGLE QUOTATION MARK        */\n    0xD5    ,       /*  0x2019  # RIGHT SINGLE QUOTATION MARK       */\n    0xD2    ,       /*  0x201C  # LEFT DOUBLE QUOTATION MARK        */\n    0xD3    ,       /*  0x201D  # RIGHT DOUBLE QUOTATION MARK       */\n    0xA5    ,       /*  0x2022  # BULLET        */\n    0xD0    ,       /*  0x2013  # EN DASH       */\n    0xD1    ,       /*  0x2014  # EM DASH       */\n    0xF7    ,       /*  0x02DC  # SMALL TILDE       */\n    0xAA    ,       /*  0x2122  # TRADE MARK SIGN       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xDD    ,       /*  0x203A  # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD9    ,       /*  0x0178  # LATIN CAPITAL LETTER Y WITH DIAERESIS     */\n    0xCA    ,       /*  0x00A0  # NO-BREAK SPACE        */\n    0xC1    ,       /*  0x00A1  # INVERTED EXCLAMATION MARK     */\n    0xA2    ,       /*  0x00A2  # CENT SIGN     */\n    0xA3    ,       /*  0x00A3  # POUND SIGN        */\n    0xDB    ,       /*  0x00A4  # CURRENCY SIGN     */\n    0xB4    ,       /*  0x00A5  # YEN SIGN      */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAC    ,       /*  0x00A8  # DIAERESIS     */\n    0xA9    ,       /*  0x00A9  # COPYRIGHT SIGN        */\n    0xBB    ,       /*  0x00AA  # FEMININE ORDINAL INDICATOR        */\n    0xC7    ,       /*  0x00AB  # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK     */\n    0xC2    ,       /*  0x00AC  # NOT SIGN      */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA8    ,       /*  0x00AE  # REGISTERED SIGN       */\n    0xF8    ,       /*  0x00AF  # MACRON        */\n    0xA1    ,       /*  0x00B0  # DEGREE SIGN       */\n    0xB1    ,       /*  0x00B1  # PLUS-MINUS SIGN       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAB    ,       /*  0x00B4  # ACUTE ACCENT      */\n    0xB5    ,       /*  0x00B5  # MICRO SIGN        */\n    0xA6    ,       /*  0x00B6  # PILCROW SIGN      */\n    0xE1    ,       /*  0x00B7  # MIDDLE DOT        */\n    0xFC    ,       /*  0x00B8  # CEDILLA       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xBC    ,       /*  0x00BA  # MASCULINE ORDINAL INDICATOR       */\n    0xC8    ,       /*  0x00BB  # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xC0    ,       /*  0x00BF  # INVERTED QUESTION MARK        */\n    0xCB    ,       /*  0x00C0  # LATIN CAPITAL LETTER A WITH GRAVE     */\n    0xE7    ,       /*  0x00C1  # LATIN CAPITAL LETTER A WITH ACUTE     */\n    0xE5    ,       /*  0x00C2  # LATIN CAPITAL LETTER A WITH CIRCUMFLEX        */\n    0xCC    ,       /*  0x00C3  # LATIN CAPITAL LETTER A WITH TILDE     */\n    0x80    ,       /*  0x00C4  # LATIN CAPITAL LETTER A WITH DIAERESIS     */\n    0x81    ,       /*  0x00C5  # LATIN CAPITAL LETTER A WITH RING ABOVE        */\n    0xAE    ,       /*  0x00C6  # LATIN CAPITAL LETTER AE       */\n    0x82    ,       /*  0x00C7  # LATIN CAPITAL LETTER C WITH CEDILLA       */\n    0xE9    ,       /*  0x00C8  # LATIN CAPITAL LETTER E WITH GRAVE     */\n    0x83    ,       /*  0x00C9  # LATIN CAPITAL LETTER E WITH ACUTE     */\n    0xE6    ,       /*  0x00CA  # LATIN CAPITAL LETTER E WITH CIRCUMFLEX        */\n    0xE8    ,       /*  0x00CB  # LATIN CAPITAL LETTER E WITH DIAERESIS     */\n    0xED    ,       /*  0x00CC  # LATIN CAPITAL LETTER I WITH GRAVE     */\n    0xEA    ,       /*  0x00CD  # LATIN CAPITAL LETTER I WITH ACUTE     */\n    0xEB    ,       /*  0x00CE  # LATIN CAPITAL LETTER I WITH CIRCUMFLEX        */\n    0xEC    ,       /*  0x00CF  # LATIN CAPITAL LETTER I WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0x84    ,       /*  0x00D1  # LATIN CAPITAL LETTER N WITH TILDE     */\n    0xF1    ,       /*  0x00D2  # LATIN CAPITAL LETTER O WITH GRAVE     */\n    0xEE    ,       /*  0x00D3  # LATIN CAPITAL LETTER O WITH ACUTE     */\n    0xEF    ,       /*  0x00D4  # LATIN CAPITAL LETTER O WITH CIRCUMFLEX        */\n    0xCD    ,       /*  0x00D5  # LATIN CAPITAL LETTER O WITH TILDE     */\n    0x85    ,       /*  0x00D6  # LATIN CAPITAL LETTER O WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAF    ,       /*  0x00D8  # LATIN CAPITAL LETTER O WITH STROKE        */\n    0xF4    ,       /*  0x00D9  # LATIN CAPITAL LETTER U WITH GRAVE     */\n    0xF2    ,       /*  0x00DA  # LATIN CAPITAL LETTER U WITH ACUTE     */\n    0xF3    ,       /*  0x00DB  # LATIN CAPITAL LETTER U WITH CIRCUMFLEX        */\n    0x86    ,       /*  0x00DC  # LATIN CAPITAL LETTER U WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA7    ,       /*  0x00DF  # LATIN SMALL LETTER SHARP S        */\n    0x88    ,       /*  0x00E0  # LATIN SMALL LETTER A WITH GRAVE       */\n    0x87    ,       /*  0x00E1  # LATIN SMALL LETTER A WITH ACUTE       */\n    0x89    ,       /*  0x00E2  # LATIN SMALL LETTER A WITH CIRCUMFLEX      */\n    0x8B    ,       /*  0x00E3  # LATIN SMALL LETTER A WITH TILDE       */\n    0x8A    ,       /*  0x00E4  # LATIN SMALL LETTER A WITH DIAERESIS       */\n    0x8C    ,       /*  0x00E5  # LATIN SMALL LETTER A WITH RING ABOVE      */\n    0xBE    ,       /*  0x00E6  # LATIN SMALL LETTER AE     */\n    0x8D    ,       /*  0x00E7  # LATIN SMALL LETTER C WITH CEDILLA     */\n    0x8F    ,       /*  0x00E8  # LATIN SMALL LETTER E WITH GRAVE       */\n    0x8E    ,       /*  0x00E9  # LATIN SMALL LETTER E WITH ACUTE       */\n    0x90    ,       /*  0x00EA  # LATIN SMALL LETTER E WITH CIRCUMFLEX      */\n    0x91    ,       /*  0x00EB  # LATIN SMALL LETTER E WITH DIAERESIS       */\n    0x93    ,       /*  0x00EC  # LATIN SMALL LETTER I WITH GRAVE       */\n    0x92    ,       /*  0x00ED  # LATIN SMALL LETTER I WITH ACUTE       */\n    0x94    ,       /*  0x00EE  # LATIN SMALL LETTER I WITH CIRCUMFLEX      */\n    0x95    ,       /*  0x00EF  # LATIN SMALL LETTER I WITH DIAERESIS       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0x96    ,       /*  0x00F1  # LATIN SMALL LETTER N WITH TILDE       */\n    0x98    ,       /*  0x00F2  # LATIN SMALL LETTER O WITH GRAVE       */\n    0x97    ,       /*  0x00F3  # LATIN SMALL LETTER O WITH ACUTE       */\n    0x99    ,       /*  0x00F4  # LATIN SMALL LETTER O WITH CIRCUMFLEX      */\n    0x9B    ,       /*  0x00F5  # LATIN SMALL LETTER O WITH TILDE       */\n    0x9A    ,       /*  0x00F6  # LATIN SMALL LETTER O WITH DIAERESIS       */\n    0xD6    ,       /*  0x00F7  # DIVISION SIGN     */\n    0xBF    ,       /*  0x00F8  # LATIN SMALL LETTER O WITH STROKE      */\n    0x9D    ,       /*  0x00F9  # LATIN SMALL LETTER U WITH GRAVE       */\n    0x9C    ,       /*  0x00FA  # LATIN SMALL LETTER U WITH ACUTE       */\n    0x9E    ,       /*  0x00FB  # LATIN SMALL LETTER U WITH CIRCUMFLEX      */\n    0x9F    ,       /*  0x00FC  # LATIN SMALL LETTER U WITH DIAERESIS       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD8            /*  0x00FF  # LATIN SMALL LETTER Y WITH DIAERESIS       */\n };\n\n\n/*\n\nThe following characters has no equivalent\nto each other:\n\nMacCodes\n164 0xA4    0x00A7  # SECTION SIGN\n253 0xFD    0x02DD  # DOUBLE ACUTE ACCENT\n189 0xBD    0x03A9  # GREEK CAPITAL LETTER OMEGA\n185 0xB9    0x03C0  # GREEK SMALL LETTER PI\n255 0xFF    0x02C7  # CARON\n249 0xF9    0x02D8  # BREVE\n250 0xFA    0x02D9  # DOT ABOVE\n251 0xFB    0x02DA  # RING ABOVE\n254 0xFE    0x02DB  # OGONEK\n218 0xDA    0x2044  # FRACTION SLASH\n182 0xB6    0x2202  # PARTIAL DIFFERENTIAL\n198 0xC6    0x2206  # INCREMENT\n184 0xB8    0x220F  # N-ARY PRODUCT\n183 0xB7    0x2211  # N-ARY SUMMATION\n195 0xC3    0x221A  # SQUARE ROOT\n176 0xB0    0x221E  # INFINITY\n186 0xBA    0x222B  # INTEGRAL\n197 0xC5    0x2248  # ALMOST EQUAL TO\n173 0xAD    0x2260  # NOT EQUAL TO\n178 0xB2    0x2264  # LESS-THAN OR EQUAL TO\n179 0xB3    0x2265  # GREATER-THAN OR EQUAL TO\n215 0xD7    0x25CA  # LOZENGE\n240 0xF0    0xF8FF  # Apple logo\n222 0xDE    0xFB01  # LATIN SMALL LIGATURE FI\n223 0xDF    0xFB02  # LATIN SMALL LIGATURE FL\n245 0xF5    0x0131  # LATIN SMALL LETTER DOTLESS I\n206 0xCE    0x0152  # LATIN CAPITAL LIGATURE OE\n207 0xCF    0x0153  # LATIN SMALL LIGATURE OE\n\nWinCodes\n129 0x81            #UNDEFINED\n141 0x8D            #UNDEFINED\n143 0x8F            #UNDEFINED\n144 0x90            #UNDEFINED\n157 0x9D            #UNDEFINED\n167 0xA7    0x00A7  #SECTION SIGN\n173 0xAD    0x00AD  #SOFT HYPHEN\n178 0xB2    0x00B2  #SUPERSCRIPT TWO\n179 0xB3    0x00B3  #SUPERSCRIPT THREE\n185 0xB9    0x00B9  #SUPERSCRIPT ONE\n188 0xBC    0x00BC  #VULGAR FRACTION ONE QUARTER\n189 0xBD    0x00BD  #VULGAR FRACTION ONE HALF\n190 0xBE    0x00BE  #VULGAR FRACTION THREE QUARTERS\n208 0xD0    0x00D0  #LATIN CAPITAL LETTER ETH\n215 0xD7    0x00D7  #MULTIPLICATION SIGN\n221 0xDD    0x00DD  #LATIN CAPITAL LETTER Y WITH ACUTE\n222 0xDE    0x00DE  #LATIN CAPITAL LETTER THORN\n240 0xF0    0x00F0  #LATIN SMALL LETTER ETH\n253 0xFD    0x00FD  #LATIN SMALL LETTER Y WITH ACUTE\n254 0xFE    0x00FE  #LATIN SMALL LETTER THORN\n140 0x8C    0x0152  #LATIN CAPITAL LIGATURE OE\n156 0x9C    0x0153  #LATIN SMALL LIGATURE OE\n138 0x8A    0x0160  #LATIN CAPITAL LETTER S WITH CARON\n154 0x9A    0x0161  #LATIN SMALL LETTER S WITH CARON\n142 0x8E    0x017D  #LATIN CAPITAL LETTER Z WITH CARON\n158 0x9E    0x017E  #LATIN SMALL LETTER Z WITH CARON\n128 0x80    0x20AC  #EURO SIGN\n166 0xA6    0x00A6  #BROKEN BAR\n\n\n*/\n\n\n\n\n#endif /* !__macos_charmap_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/getenv.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n\nThis file implements the getenv() function.\n\n#  Background:\n#  Under Unix: Each Process (= running Program) has a set of\n#  associated variables. The variables are called enviroment\n#  variables and, together, constitute the process environment.\n#  These variables include the search path, the terminal type,\n#  and the user's login name.\n\n#  Unfortunatelly the MacOS has no equivalent. So we need\n#  a file to define the environment variables.\n#  Name of this file is \"MacZip.Env\". It can be placed\n#  in the current folder of MacZip or in the\n#  preference folder of the system disk.\n#  If MacZip founds the \"MacZip.Env\" file in the current\n#  the folder of MacZip the \"MacZip.Env\" file in the\n#  preference folder will be ignored.\n\n#  An environment variable has a name and a value:\n#  Name=Value\n#  Note: Spaces are significant:\n#  ZIPOPT=-r  and\n#  ZIPOPT = -r are different !!!\n\n\n */\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <time.h>\n#include <unix.h>\n#include <Files.h>\n#include <Folders.h>\n\n#include \"pathname.h\"\n#include \"helpers.h\"\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\nstatic char ListAllKeyValues = 0;\nstatic unsigned LineNumber   = 0;\nstatic char CompletePath[NAME_MAX];\nBoolean IgnoreEnvironment    = false;  /* used by dialog.c and initfunc.c\n                                          of the Mainapp */\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\ntypedef struct _EnviromentPair {\n    char *key;\n    char *value;\n} EnviromentPair;\n\n\n#define MAX_COMMAND 1024\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\n\nint get_char(FILE *file);\nvoid unget_char(int ch,FILE *file);\nint get_string(char *string,int size, FILE *file, char *terms);\nvoid skip_comments(FILE *file);\nchar *load_entry(FILE *file);\nchar *getenv(const char *name);\nEnviromentPair *ParseLine(char *line);\nOSErr FSpFindFolder_Name(short vRefNum, OSType folderType,\n                         Boolean createFolder,FSSpec *spec, unsigned char *name);\nFILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);\nvoid ShowAllKeyValues(void);\nvoid Set_LineNum(unsigned ln);\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/* get_string(str, max, file, termstr) : like fgets() but\n *      (1) has terminator string which should include \\n\n *      (2) will always leave room for the null\n *      (3) uses get_char() so LineNumber will be accurate\n *      (4) returns EOF or terminating character, whichever\n */\nint get_string(char *string, int size, FILE *file, char *terms)\n{\n    int ch;\n\n    while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {\n        if (size > 1) {\n            *string++ = (char) ch;\n            size--;\n        }\n    }\n\n    if (size > 0)\n        {\n        *string = '\\0';\n        }\n\n    return ch;\n}\n\n\n\n\nvoid Set_LineNum(unsigned ln)\n{\n LineNumber = ln;\n}\n\n\n\n/* get_char(file) : like getc() but increment LineNumber on newlines\n */\nint get_char(FILE *file)\n{\n    int ch;\n\n    ch = getc(file);\n    if (ch == '\\n')\n        {\n        Set_LineNum(LineNumber + 1);\n        }\n\n    return ch;\n}\n\n\n\n\n/* skip_comments(file) : read past comment (if any)\n */\nvoid skip_comments(FILE *file)\n{\n    int ch;\n\n    while (EOF != (ch = get_char(file)))\n        {\n        /* ch is now the first character of a line.\n         */\n\n        while (ch == ' ' || ch == '\\t')\n            {\n            ch = get_char(file);\n            }\n\n        if (ch == EOF)\n            {\n            break;\n            }\n\n        /* ch is now the first non-blank character of a line.\n         */\n\n        if (ch != '\\n' && ch != '#')\n            {\n            break;\n            }\n\n        /* ch must be a newline or comment as first non-blank\n         * character on a line.\n         */\n\n        while (ch != '\\n' && ch != EOF)\n            {\n            ch = get_char(file);\n            }\n\n        /* ch is now the newline of a line which we're going to\n         * ignore.\n         */\n    }\n\n    if (ch != EOF)\n        {\n        unget_char(ch, file);\n        }\n}\n\n\n\n\n/* unget_char(ch, file) : like ungetc but do LineNumber processing\n */\nvoid unget_char(int ch, FILE *file)\n{\n    ungetc(ch, file);\n    if (ch == '\\n')\n        {\n        Set_LineNum(LineNumber - 1);\n        }\n}\n\n\n/* this function reads one file entry -- the next -- from a file.\n*  it skips any leading blank lines, ignores comments, and returns\n*  NULL if for any reason the entry can't be read and parsed.\n*/\n\nchar *load_entry(FILE *file)\n{\n    int ch;\n    static char cmd[MAX_COMMAND];\n\n    skip_comments(file);\n\n    ch = get_string(cmd, MAX_COMMAND, file, \"\\n\");\n\n    if (ch == EOF)\n        {\n        return NULL;\n        }\n\n    return cmd;\n}\n\n\n\n\n\nEnviromentPair *ParseLine(char *line)\n{\nchar *tmpPtr;\nstatic EnviromentPair *Env;\nunsigned short length = strlen(line);\n\nEnv->key   = \"\";\nEnv->value = \"\";\n\nfor (tmpPtr = line; *tmpPtr; tmpPtr++)\n    {\n    if (*tmpPtr == '=')\n        {\n        *tmpPtr = 0;\n        Env->key = line;\n        if (strlen(Env->key) < length)\n            {\n            Env->value = ++tmpPtr;\n            }\n        return Env;\n        }\n    }\nreturn Env;\n}\n\n\n\n\n\nchar *getenv(const char *name)\n{\nFILE *fp;\nchar *LineStr = NULL;\nEnviromentPair *Env1;\nFSSpec spec;\nOSErr err;\n\nif (IgnoreEnvironment)\n    return NULL;  /* user wants to ignore the environment vars */\n\nif (name == NULL)\n    return NULL;\n\nGetCompletePath(CompletePath,\"MacZip.Env\",&spec,&err);\n\n/* try open the file in the current folder */\nfp = FSp_fopen(&spec,\"r\");\nif (fp == NULL)\n    { /* Okey, lets try open the file in the preference folder */\n    FSpFindFolder_Name(\n                   kOnSystemDisk,\n                   kPreferencesFolderType,\n                   kDontCreateFolder,\n                   &spec,\n                   \"\\pMacZip.Env\");\n    fp = FSp_fopen(&spec,\"r\");\n    if (fp == NULL)\n        {\n        return NULL; /* there is no enviroment-file */\n        }\n    }\n\nLineStr = load_entry(fp);\nwhile (LineStr != NULL)\n    {   /* parse the file line by line */\n    Env1 = ParseLine(LineStr);\n    if (strlen(Env1->value) > 0)\n        {       /* we found a key/value pair */\n        if (ListAllKeyValues)\n            printf(\"\\n   Line:%3d   [%s] = [%s]\",LineNumber,Env1->key,Env1->value);\n        if (stricmp(name,Env1->key) == 0)\n            {   /* we found the value of a given key */\n            return Env1->value;\n            }\n        }\n    LineStr = load_entry(fp);  /* read next line */\n    }\nfclose(fp);\n\nreturn NULL;\n}\n\n\n\n\n\nOSErr FSpFindFolder_Name(\n    short vRefNum,          /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec,           /* Pointer to resulting directory. */\n    unsigned char *name)    /* Name of the file in the folder */\n{\n    short foundVRefNum;\n    long foundDirID;\n    OSErr err;\n\n    err = FindFolder(vRefNum, folderType, createFolder,\n                     &foundVRefNum, &foundDirID);\n    if (err != noErr)\n        {\n        return err;\n        }\n\n    err = FSMakeFSSpec(foundVRefNum, foundDirID, name, spec);\n    return err;\n}\n\n\n\n\nvoid ShowAllKeyValues(void)\n{\nOSErr err;\nFSSpec spec;\nBoolean tmpIgnoreEnvironment = IgnoreEnvironment;\n\nListAllKeyValues = 1;\nIgnoreEnvironment = false;\n\nGetCompletePath(CompletePath,\"MacZip.Env\",&spec,&err);\nif (err != 0)\n    { /* Okey, lets try open the file in the preference folder */\n    FSpFindFolder_Name(\n                   kOnSystemDisk,\n                   kPreferencesFolderType,\n                   kDontCreateFolder,\n                   &spec,\n                   \"\\pMacZip.Env\");\n    GetFullPathFromSpec(CompletePath,&spec, &err);\n    if (err != 0)\n        {\n        return; /* there is no enviroment-file */\n        }\n    }\n\nprintf(\"\\nLocation of the current \\\"MacZip.Env\\\" file:\\n [%s]\",CompletePath);\n\nprintf(\"\\n\\nList of all environment variables\\n\");\ngetenv(\" \");\nprintf(\"\\n\\nEnd\\n\\n\");\n\n/* restore used variables */\nListAllKeyValues = 0;\nLineNumber = 0;\nIgnoreEnvironment = tmpIgnoreEnvironment;\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/helpers.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  helpers.c\n\n  Some useful functions Used by unzip and zip.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include \"zip.h\"\n#include <ctype.h>\n#include <time.h>\n#include <sound.h>\n\n#include \"macstuff.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\n\nextern int noisy;\nextern char MacPathEnd;\nextern char *zipfile;   /* filename of the Zipfile */\nextern char *tempzip;   /* Temporary zip file name */\nextern ZCONST unsigned char MacRoman_to_WinCP1252[128];\n\n\nstatic char         argStr[1024];\nstatic char         *argv[MAX_ARGS + 1];\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/*\n**  Copy a C string to a Pascal string\n**\n*/\n\nunsigned char *CToPCpy(unsigned char *pstr, char *cstr)\n{\n    register char *dptr;\n    register unsigned len;\n\n        len=0;\n        dptr=(char *)pstr+1;\n    while (len<255 && (*dptr++ = *cstr++)!='\\0') ++len;\n    *pstr= (unsigned char)len;\n  return pstr;\n}\n\n\n/*\n**  Copy a Pascal string to a C string\n**\n*/\n\nchar *PToCCpy(unsigned char *pstr, char *cstr)\n{\nstrncpy(cstr, (char *) &pstr[1], *pstr);\n    cstr[pstr[0]] = '\\0';  /* set endmarker for c-string */\nreturn cstr;\n}\n\n\n/*\n**  strcpy() and strcat() work-alikes which allow overlapping buffers.\n*/\n\nchar *sstrcpy(char *to,const char *from)\n{\n    memmove(to, from, 1+strlen(from));\n    return to;\n}\n\nchar *sstrcat(char *to,const char *from)\n{\n    sstrcpy(to + strlen(to), from);\n    return to;\n}\n\n\n\n/*\n**  Alloc memory and init it\n**\n*/\n\nchar *StrCalloc(unsigned short size)\n{\nchar *strPtr = NULL;\n\nif ((strPtr = calloc(size, sizeof(char))) == NULL)\n    printerr(\"StrCalloc failed:\", -1, size, __LINE__, __FILE__, \"\");\n\nAssert_it(strPtr,\"strPtr == NULL\",\"\")\nreturn strPtr;\n}\n\n\n\n/*\n**  Release only non NULL pointers\n**\n*/\n\nchar *StrFree(char *strPtr)\n{\n\nif (strPtr != NULL)\n    {\n    free(strPtr);\n    }\n\nreturn NULL;\n}\n\n\n\n\n/*\n**  Return a value in a binary string\n**\n*/\n\nchar *sBit2Str(unsigned short value)\n{\n  static char str[sizeof(value)*8];\n  int biz    = 16;\n  int strwid = 16;\n  int i, j;\n  char *tempPtr = str;\n\n      j = strwid - (biz + (biz >> 2)- (biz % 4 ? 0 : 1));\n\n      for (i = 0; i < j; i++) {\n            *tempPtr++ = ' ';\n      }\n      while (--biz >= 0)\n      {\n            *tempPtr++ = ((value >> biz) & 1) + '0';\n            if (!(biz % 4) && biz) {\n                  *tempPtr++ = ' ';\n            }\n      }\n      *tempPtr = '\\0';\n\n  return str;\n}\n\n\n\n\n/*\n**  Parse commandline style arguments\n**\n*/\n\nint ParseArguments(char *s, char ***arg)\n{\n    int  n = 1, Quote = 0;\n    char *p = s, *p1, c;\n\n    argv[0] = GetAppName();\n\n    *arg = argv;\n\n    p1 = (char *) argStr;\n    while ((c = *p++) != 0) {\n        if (c==' ') continue;\n        argv[n++] = p1;\n        if (n > MAX_ARGS)\n            return (n-1);\n        do {\n            if (c=='\\\\' && *p++)\n                c = *p++;\n            else\n                if ((c=='\"') || (c == '\\'')) {\n                    if (!Quote) {\n                        Quote = c;\n                        continue;\n                    }\n                    if (c == Quote) {\n                        Quote = 0;\n                        continue;\n                    }\n                }\n            *p1++ = c;\n        } while (*p && ((c = *p++) != ' ' || Quote));\n        *p1++ = '\\0';\n    }\n    return n;\n}\n\n\n\n/*\n**  Print commandline style arguments\n**\n*/\n\nvoid PrintArguments(int argc, char **argv)\n{\n\nprintf(\"\\n Arguments:\");\nprintf(\"\\n --------------------------\");\n\nwhile(--argc >= 0)\n    printf(\"\\n argc: %d  argv: [%s]\", argc, &*argv[argc]);\n\nprintf(\"\\n --------------------------\\n\\n\");\nreturn;\n}\n\n\n\n/*\n**  return some error-msg on file-system\n**\n*/\n\nint PrintUserHFSerr(int cond, int err, char *msg2)\n{\nchar *msg;\n\nif (cond != 0)\n    {\n    switch (err)\n        {\n         case -35:\n            msg = \"No such Volume\";\n         break;\n\n         case -56:\n            msg = \"No such Drive\";\n         break;\n\n         case -37:\n            msg = \"Bad Volume Name\";\n         break;\n\n         case -49:\n            msg = \"File is already open for writing\";\n         break;\n\n         case -43:\n            msg = \"Directory/File not found\";\n         break;\n\n         case -120:\n            msg = \"Directory/File not found or incomplete pathname\";\n         break;\n\n        default: return err;\n         }\n    fprintf(stderr, \"\\n\\n Error: %s ->%s\", msg, msg2);\n    exit(err);\n    }\n\nreturn 0;\n}\n\n\n\n/*\n**  Check mounted volumes and return number of volumes\n**  with the same name.\n*/\n\nshort CheckMountedVolumes(char *FullPath)\n{\nFSSpec  volumes[50];        /* 50 Volumes should be enough */\nchar VolumeName[257], volume[257];\nshort actVolCount, volIndex = 1, VolCount = 0;\nOSErr err;\nint i;\n\nGetVolumeFromPath(FullPath, VolumeName);\n\nerr = OnLine(volumes, 50, &actVolCount, &volIndex);\nprinterr(\"OnLine:\", (err != -35) && (err != 0), err, __LINE__, __FILE__, \"\");\n\nfor (i=0; i < actVolCount; i++)\n    {\n    PToCCpy(volumes[i].name,volume);\n    if (stricmp(volume, VolumeName) == 0) VolCount++;\n    }\nprinterr(\"OnLine: \", (VolCount == 0), VolCount, __LINE__, __FILE__, FullPath);\n\nreturn VolCount;\n}\n\n\n\n\n\n\n\n\n/*\n**  compares strings, ignoring differences in case\n**\n*/\n\nint stricmp(const char *p1, const char *p2)\n{\nint diff;\n\nwhile (*p1 && *p2)\n    {\n    if (*p1 != *p2)\n        {\n        if (isalpha(*p1) && isalpha(*p2))\n            {\n            diff = toupper(*p1) - toupper(*p2);\n            if (diff) return diff;\n            }\n            else break;\n        }\n        p1++;\n        p2++;\n    }\nreturn *p1 - *p2;\n}\n\n\n\n/*\n** Convert the MacOS-Strings (Filenames/Findercomments) to a most compatible.\n** These strings will be stored in the public area of the zip-archive.\n** Every foreign platform (outside macos) will access these strings\n** for extraction.\n*/\n\nvoid MakeCompatibleString(char *MacOS_Str,\n            const char SpcChar1, const char SpcChar2,\n            const char SpcChar3, const char SpcChar4,\n            short CurrTextEncodingBase)\n{\n    char *tmpPtr;\n    register uch curch;\n\n    Assert_it(MacOS_Str,\"MakeCompatibleString MacOS_Str == NULL\",\"\")\n    for (tmpPtr = MacOS_Str; (curch = *tmpPtr) != '\\0'; tmpPtr++)\n    {\n        if (curch == SpcChar1)\n            *tmpPtr = SpcChar2;\n        else\n        if (curch == SpcChar3)\n            *tmpPtr = SpcChar4;\n        else  /* default */\n        /* now convert from MacRoman to ISO-8859-1 */\n        /* but convert only if MacRoman is activ */\n            if ((CurrTextEncodingBase == kTextEncodingMacRoman) &&\n                (curch > 127))\n                   {\n                    *tmpPtr = (char)MacRoman_to_WinCP1252[curch - 128];\n                   }\n    }  /* end for */\n}\n\n\n\n\nBoolean CheckForSwitch(char *Switch, int argc, char **argv)\n{\n  char *p;              /* steps through option arguments */\n  int i;                /* arg counter, root directory flag */\n\n  for (i = 1; i < argc; i++)\n  {\n    if (argv[i][0] == '-')\n    {\n      if (argv[i][1])\n        {\n        for (p = argv[i]+1; *p; p++)\n            {\n            if (*p == Switch[0])\n                {\n                return true;\n                }\n            if ((Switch[1] != NULL) &&\n                ((*p == Switch[0]) && (*p == Switch[1])))\n                {\n                return true;\n                }\n            }\n         }\n     }\n  }\n\nreturn false;\n}\n\n\n\n\n\n\n\n#if (defined(USE_SIOUX) || defined(MACUNZIP_STANDALONE))\n\n/*\n**  checks the condition and returns an error-msg\n**  this function is for internal use only\n*/\n\nOSErr printerr(const char *msg, int cond, int err, int line, char *file,\n              const char *msg2)\n{\n\nif (cond != 0)\n    {\n    fprintf(stderr, \"\\nint err: %d: %s %d [%d/%s] {%s}\\n\", clock(), msg, err,\n            line, file, msg2);\n    }\n\nreturn cond;\n}\n\n\n/*\nfake-functions:\nNot Implemented for metrowerks SIOUX\n*/\n\nvoid leftStatusString(char *status)\n{\nstatus = status;\n}\n\n\nvoid rightStatusString(char *status)\n{\nstatus = status;\n}\n\n\n\nvoid DoWarnUserDupVol( char *FullPath )\n{\n  char VolName[257];\n  GetVolumeFromPath(FullPath,  VolName);\n\n  printf(\"\\n There are more than one volume that has the same name !!\\n\");\n\n  printf(\"\\n Volume: %s\\n\",VolName);\n\n  printf(\"\\n This port has one weak point:\");\n  printf(\"\\n It is based on pathnames. As you may be already know:\");\n  printf(\"\\n Pathnames are not unique on a Mac !\");\n  printf(\"\\n MacZip has problems to find the correct location of\");\n  printf(\"\\n the archive or the files.\\n\");\n\n  printf(\"\\n My (Big) recommendation:  Name all your volumes with an\");\n  printf(\"\\n unique name and MacZip will run without any problem.\");\n}\n\n\n\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/helpers.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef HELPERS_H\n#define HELPERS_H       1\n\n /* Convert a C string to a Pascal string */\nunsigned char *CToPCpy(unsigned char *pstr, char *cstr);\n\n /* Convert a Pascal string to a C string */\nchar *PToCCpy(unsigned char *pstr, char *cstr);\n\nchar *sstrcpy(char *to,const char *from);\nchar *sstrcat(char *to,const char *from);\n\nchar *StrCalloc(unsigned short size);\nchar *StrFree(char *strPtr);\n\nchar *sBit2Str(unsigned short value);\n\nvoid print_extra_info(void);\n\nint ParseArguments(char *s, char ***arg);\nvoid PrintArguments(int argc, char **argv);\n\nBoolean IsZipFile(char *name);\nOSErr printerr(const char *msg, int cond, int err, int line, char *file,\n               const char *msg2);\nint PrintUserHFSerr(int cond, int err, char *msg2);\n\nshort CheckMountedVolumes(char *FullPath);\nvoid DoWarnUserDupVol(char *path);\n\nvoid PrintFileInfo(void);\n\nint stricmp(const char *p1, const char *p2);\nvoid leftStatusString(char *status);\nvoid rightStatusString(char *status);\n\nBoolean isZipFile(FSSpec *fileToOpen);\n\nunsigned long MacFileDate_to_UTime(unsigned long mactime);\nBoolean CheckForSwitch(char *Switch, int argc, char **argv);\n\nvoid MakeCompatibleString(char *MacOS_Str,\n            const char SpcChar1, const char SpcChar2,\n            const char SpcChar3, const char SpcChar4,\n            short CurrTextEncodingBase);\n\n#define     MAX_ARGS    25\n\n#endif   /*  HELPERS_H   */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macbin3.c",
    "content": "/****************************************************************\n    MacBinaryIII.c\n\n    Copyright  1997 Christopher Evans (cevans@poppybank.com)\n\n    Basic encoding and decoding of Macintosh files to the\n    MacBinary III spec.\n\n This file is part of the MacBinaryIII_src_C.sit package\n see macbin3.h for more information\n\n****************************************************************/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdio.h>\n#include \"macbin3.h\"\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n/* source (the macbinary file) will be deleted */\n#define DELETE_MACBINARY_SOURCE\n\n/* enable encoding\n#define INCLUDE_ENCODE_MACBINARY         */\n\n/* enable decoding */\n#define INCLUDE_DECODE_MACBINARY\n\n/* include own CRC 32 Bit Calculation\n#define INCLUDE_CRC32CALC               */\n\n/* produce some helpful printouts for tracing\n#define TRACE_MACBINARY   */\n\n\n\n#define LONG_AT_OFFSET(data, offset) *((long *)((unsigned char *)&data[offset]))\n#define WORD_AT_OFFSET(data, offset) *((Word *)((unsigned char *)&data[offset]))\n#define BYTE_AT_OFFSET(data, offset) *((Byte *)((unsigned char *)&data[offset]))\n#define PTR_AT_OFFSET(data, offset)  ((Ptr)((unsigned char *)&data[offset]))\n\ntypedef     unsigned short      Word;\n\n#define kOldVersionOffset               0\n#define kFileNameLengthOffset           1\n#define kFileNameOffset                 2\n#define kFileTypeOffset                 65\n#define kFileCreatorOffset              69\n#define kFinderFlagsHiOffset            73\n#define kVersionCheckZero               74\n#define kFileVPositionOffset            75\n#define kFileHPositionOffset            77\n#define kFileFolderIDOffset             79\n#define kProtectedFlagOffset            81\n#define kVersionOneCheckZero            82\n#define kDataForkLengthOffset           83\n#define kResourceForkLengthOffset       87\n#define kFileCreationDateOffset         91\n#define kFileModificationDateOffset     95\n#define kGetInfoCommentLengthOffset     99\n#define kFinderFlagsLowOffset           101\n#define kMacbinarySigOffset             102\n#define kFilenameScriptOffset           106\n#define kExtendedFinderFlagsOffset      107\n#define kTotalFileLengthOffset          116\n#define kSecondaryHeaderLengthOffset    120\n#define kCurrentVersionOffset           122\n#define kMinimumVersionOffset           123\n#define kCRCOffset                      124\n\n#define kResourceForkMaxLen             (1024 * 1024 * 16)\n\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\n#ifdef INCLUDE_CRC32CALC\nstatic unsigned long crc_table[256] = {\n  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,\n  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,\n  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,\n  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,\n  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,\n  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,\n  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,\n  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,\n  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,\n  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,\n  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,\n  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,\n  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,\n  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,\n  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,\n  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,\n  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,\n  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,\n  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,\n  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,\n  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,\n  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,\n  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,\n  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,\n  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,\n  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,\n  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,\n  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,\n  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,\n  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,\n  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,\n  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,\n  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,\n  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,\n  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,\n  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,\n  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,\n  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,\n  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,\n  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,\n  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,\n  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,\n  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,\n  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,\n  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,\n  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,\n  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,\n  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,\n  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,\n  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,\n  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,\n  0x2d02ef8dL\n};\n#endif\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nstatic Boolean  HeaderIsMacBinary(char *header,\n                                  Word *version,\n                                  long maxDataLen);\nstatic Boolean FSpExists(FSSpec *file);\n#ifdef INCLUDE_CRC32CALC\nstatic unsigned long crc32(unsigned long seed, unsigned char *p, size_t len);\n#else\nextern unsigned long crc32(unsigned long seed, unsigned char *p, size_t len);\n#endif\nstatic OSErr GetDesktopComment(FSSpec *file, char*comment, long *length);\nstatic OSErr SetDesktopComment(FSSpec *file, char*comment, long length);\nstatic Handle  EncodeMacbinary(FSSpec *file);\nstatic OSErr   DecodeMacBinary(Handle data, FSSpec *destination);\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n#ifdef INCLUDE_CRC32CALC\n/* taken from the mcvert source code */\nstatic unsigned long crc32(unsigned long seed, unsigned char *p, size_t len)\n{\n    unsigned long hold;     /* crc computed so far */\n    size_t i;               /* index into data */\n\n    hold = seed;                   /* start with seed */\n    for (i = 0; i < len; i++, p++)\n        {\n        hold ^= (*p << 8);\n        hold  = (hold << 8) ^ crc_table[(unsigned char) (hold >> 8)];\n        }\n\n    return (hold);\n}               /* crc32() */\n#endif\n\n\n\nstatic Boolean FSpExists(FSSpec *file)\n{\n    FInfo   fndrInfo;\n\n    return FSpGetFInfo(file, &fndrInfo) == noErr;\n}\n\n\nstatic Boolean  HeaderIsMacBinary(char *header,\n                                  Word *version,\n                                  long maxDataLen)\n{\n    Boolean isIt = false;\n    unsigned long resourceForkLength, dataForkLength, df_rf_length;\n    short commentLength;\n    Byte    mbVersion;\n\n#ifdef TRACE_MACBINARY\nprintf(\"\\n\\n Function HeaderIsMacBinary(): \");\n#endif\n\n    if(LONG_AT_OFFSET(header, kMacbinarySigOffset) == 'mBIN')\n        {\n        isIt = true;\n        mbVersion = 130;\n        }\n    else\n        if(BYTE_AT_OFFSET(header, kVersionCheckZero) == 0 &&\n            BYTE_AT_OFFSET(header, kOldVersionOffset) == 0)\n            {\n            if(WORD_AT_OFFSET(header, kCRCOffset) ==\n               crc32(0, (unsigned char*) &header, 124))\n                {\n                isIt = true;\n                mbVersion = 129;\n                }\n            else\n                {\n                if(BYTE_AT_OFFSET(header, kVersionOneCheckZero) == 0)\n                    {\n                    isIt = true;\n                    mbVersion = 128;\n                    }\n                }\n            }\n\n#ifdef TRACE_MACBINARY\nprintf(\"\\n           mbVersion: %d\",mbVersion);\n#endif\n\n    resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset);\n    dataForkLength     = LONG_AT_OFFSET(header, kDataForkLengthOffset);\n    commentLength      = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset);\n    df_rf_length = dataForkLength + resourceForkLength;\n\n#ifdef TRACE_MACBINARY\nprintf(\"\\n  resourceForkLength: %d\",resourceForkLength);\nprintf(\"\\n      dataForkLength: %d\",dataForkLength);\nprintf(\"\\n       commentLength: %d\",commentLength);\nprintf(\"\\n        df_rf_length: %d\",df_rf_length);\nprintf(\"\\n                                                 1. isIt: bool: %d\",\n       isIt);\nprintf(\"\\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1       bool: %d\",\n       BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1);\nprintf(\"\\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31      bool: %d\",\n       BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31);\nprintf(\"\\n dataForkLength >= 0                                      bool: %d\",\n       dataForkLength >= 0);\nprintf(\"\\n resourceForkLength >= 0                                  bool: %d\",\n       resourceForkLength >= 0);\nprintf(\"\\n resourceForkLength <= 0x%8x                         bool: %d\",\n       kResourceForkMaxLen, resourceForkLength <= kResourceForkMaxLen);\nprintf(\"\\n dataForkLength     <= %8u                           bool: %d\",\n       maxDataLen, dataForkLength <= maxDataLen);\nprintf(\"\\n df_rf_length        > 0                                  bool: %d\",\n       df_rf_length > 0);\nprintf(\"\\n df_rf_length       <= %8u                           bool: %d\",\n       maxDataLen, df_rf_length <= maxDataLen);\n#endif\n\n    if(isIt                                                &&\n       BYTE_AT_OFFSET(header, kFileNameLengthOffset) >=  1 &&\n       BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 &&\n       dataForkLength     >= 0                             &&\n       resourceForkLength >= 0                             &&\n       resourceForkLength <= kResourceForkMaxLen           &&\n       df_rf_length       > 0                              &&\n       df_rf_length       <= maxDataLen)\n        {\n        isIt = true;\n        }\n    else\n        isIt = false;   /* something is wrong with the header */\n\n#ifdef TRACE_MACBINARY\nprintf(\"\\n                                                 2. isIt: bool: %d\",\n       isIt);\n#endif\n\n    if(version)\n        *version = mbVersion;\n    return isIt;\n}\n\n\n\nBoolean FSpIsMacBinary(FSSpec *file)\n{\n    char header[128];\n    short dfRefNum = 0;\n    OSErr   err;\n    long    size;\n    Boolean isIt = false;\n    CInfoPBRec  pb;\n    long maxDataLen;\n\n    memset(&pb, 0, sizeof(CInfoPBRec));\n    pb.hFileInfo.ioNamePtr   = file->name;\n    pb.hFileInfo.ioVRefNum   = file->vRefNum;\n    pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */\n    pb.hFileInfo.ioDirID     = file->parID;\n    err = PBGetCatInfo(&pb,false);\n    maxDataLen = pb.hFileInfo.ioFlLgLen;\n\n    memset(header, 0, 128);\n\n    err = FSpOpenDF(file, fsRdPerm, &dfRefNum);\n    if(!err)\n        {\n        err = GetEOF(dfRefNum, &size);\n        if(size > 128)\n            {\n            size = 128;\n            err = FSRead(dfRefNum, &size, &header);\n\n            if(err == noErr)\n                {\n                isIt = HeaderIsMacBinary(header, nil, maxDataLen);\n                }\n            }\n        FSClose(dfRefNum);\n        }\n    return isIt;\n}\n\n\n\n#ifdef INCLUDE_ENCODE_MACBINARY\n\nstatic OSErr    GetDesktopComment(FSSpec *file, char*comment, long *length)\n{\n    DTPBRec     pb;\n    OSErr       err;\n\n    pb.ioCompletion = nil;\n    pb.ioNamePtr = NULL;\n    pb.ioVRefNum = file->vRefNum;\n\n    err = PBDTGetPath(&pb);\n\n    if(err == noErr)\n        {\n        pb.ioNamePtr = file->name;\n        pb.ioDTBuffer = comment;\n        pb.ioDirID = file->parID;\n        err = PBDTGetComment(&pb, false);\n        *length = pb.ioDTActCount;\n        }\n    return err;\n}\n\n\n\n\nOSErr   EncodeMacbinaryFile(FSSpec *file)\n{\n    Handle data;\n    OSErr   err = paramErr;\n    short   dfRefNum;\n\n    data = EncodeMacbinary(file);\n\n    if(data)\n        {\n        if(file->name[0] > 27)\n            file->name[0] = 27;\n\n        PtoCstr(file->name);\n        strcat((char*)file->name, \".bin\");\n        CtoPstr((char *)file->name);\n\n        FSpDelete(file);\n        if(FSpCreate(file, 'dMB3', 'mBIN', smSystemScript) == noErr)\n            {\n            err = FSpOpenDF(file, fsWrPerm, &dfRefNum);\n            if(err == noErr)\n                {\n                long    inOutCount = GetHandleSize(data);\n\n                HLock(data);\n                err = FSWrite(dfRefNum,&inOutCount,*data);\n                HUnlock(data);\n                FSClose(dfRefNum);\n                }\n            }\n        DisposeHandle(data);\n        }\n    return err;\n}\n\n\n\n\n\nstatic Handle EncodeMacbinary(FSSpec *file)\n{\n    Handle result = nil;\n    FInfo   fndrInfo;\n    FXInfo  fndrXInfo;\n    OSErr   err;\n    CInfoPBRec  pb;\n    short   dfRefNum, rfRefNum;\n    long    ioCount;\n    char    buffer[128];\n    char    header[128];\n    char    comment[256];\n    long    resourceForkLength, dataForkLength, commentLength;\n\n    memset(&header, 0, sizeof(header));\n    err = FSpGetFInfo(file, &fndrInfo);\n\n    memset(&pb, 0, sizeof(CInfoPBRec));\n    pb.hFileInfo.ioNamePtr = file->name;\n    pb.hFileInfo.ioVRefNum = file->vRefNum;\n    pb.hFileInfo.ioFDirIndex = 0;           //query a file\n    pb.hFileInfo.ioDirID = file->parID;\n    err = PBGetCatInfo(&pb,false);\n\n    fndrXInfo = pb.hFileInfo.ioFlXFndrInfo;\n\n    BYTE_AT_OFFSET(header, kFileNameLengthOffset) = file->name[0];\n    BlockMoveData( &(file->name[1]),\n                   PTR_AT_OFFSET(header,\n                   kFileNameOffset),\n                   file->name[0]);\n    LONG_AT_OFFSET(header, kFileTypeOffset)    = fndrInfo.fdType;\n    LONG_AT_OFFSET(header, kFileCreatorOffset) = fndrInfo.fdCreator;\n\n    BYTE_AT_OFFSET(header, kFinderFlagsHiOffset) =\n                                          (fndrInfo.fdFlags & 0xFF00) >> 8;\n    BYTE_AT_OFFSET(header, kFinderFlagsLowOffset) =\n                                          (fndrInfo.fdFlags & 0x00FF);\n\n    WORD_AT_OFFSET(header, kFileVPositionOffset) = fndrInfo.fdLocation.v;\n    WORD_AT_OFFSET(header, kFileHPositionOffset) = fndrInfo.fdLocation.h;\n    WORD_AT_OFFSET(header, kFileFolderIDOffset)  = fndrInfo.fdFldr;\n\n    LONG_AT_OFFSET(header, kFileCreationDateOffset) = pb.hFileInfo.ioFlCrDat;\n    LONG_AT_OFFSET(header, kFileModificationDateOffset) =\n                                                      pb.hFileInfo.ioFlMdDat;\n\n    LONG_AT_OFFSET(header, kMacbinarySigOffset)        = 'mBIN';\n    BYTE_AT_OFFSET(header, kFilenameScriptOffset)      = fndrXInfo.fdScript;\n    BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset) = fndrXInfo.fdXFlags;\n\n    LONG_AT_OFFSET(header, kTotalFileLengthOffset) = 0;\n    WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset) = 0;\n\n    WORD_AT_OFFSET(header, kCurrentVersionOffset) = 130;\n    WORD_AT_OFFSET(header, kMinimumVersionOffset) = 129;\n\n    err = FSpOpenDF(file,fsRdPerm,&dfRefNum);\n    if(err == noErr)\n        {\n        err = GetEOF(dfRefNum,&dataForkLength);\n        LONG_AT_OFFSET(header, kDataForkLengthOffset) = dataForkLength;\n        }\n    else\n        {\n        dfRefNum = 0;\n        }\n\n    err = FSpOpenRF(file,fsRdPerm,&rfRefNum);\n    if(err == noErr)\n        {\n        err = GetEOF(rfRefNum,&resourceForkLength);\n        LONG_AT_OFFSET(header, kResourceForkLengthOffset) = resourceForkLength;\n        }\n    else\n        {\n        rfRefNum = 0;\n        }\n\n    memset(comment, 0, 256);\n    if(GetDesktopComment(file, comment, &commentLength) != noErr)\n        commentLength = 0;\n\n    WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset) = commentLength;\n    WORD_AT_OFFSET(header, kCRCOffset) =\n                                     crc32( 0, (unsigned char*) &header, 124);\n\n    result = TempNewHandle(0, &err);\n    if(result)\n        {\n        err = PtrAndHand(&header,result,128);\n\n        if(dfRefNum && dataForkLength)\n            {\n            err = noErr;\n            while(dataForkLength > 0 && err == noErr)\n                {\n                ioCount = 128;\n                err = FSRead(dfRefNum,&ioCount,&buffer);\n\n                if(err == noErr || err == eofErr)\n                    err = PtrAndHand(&buffer,result,128);\n\n                dataForkLength -= ioCount;\n                }\n            }\n\n        if(rfRefNum && resourceForkLength)\n            {\n            err = noErr;\n            while(resourceForkLength > 0 && err == noErr)\n                {\n                ioCount = 128;\n                err = FSRead(rfRefNum,&ioCount,&buffer);\n\n                if(err == noErr || err == eofErr)\n                    err = PtrAndHand(&buffer,result,128);\n\n                resourceForkLength -= ioCount;\n                }\n            }\n\n        if(commentLength)\n            {\n            PtrAndHand(&comment,result,commentLength);\n            }\n        }\n\n    if(rfRefNum)\n        FSClose(rfRefNum);\n\n    if(dfRefNum)\n        FSClose(dfRefNum);\n\n    return result;\n}\n\n#endif /* INCLUDE_ENCODE_MACBINARY */\n\n\n\n#ifdef INCLUDE_DECODE_MACBINARY\n\nstatic OSErr    SetDesktopComment(FSSpec *file, char*comment, long length)\n{\n    DTPBRec     pb;\n    OSErr       err;\n\n    pb.ioCompletion = nil;\n    pb.ioNamePtr = NULL;\n    pb.ioVRefNum = file->vRefNum;\n\n    err = PBDTGetPath(&pb);\n\n    if(err == noErr)\n        {\n        pb.ioNamePtr    = file->name;\n        pb.ioDTBuffer   = comment;\n        pb.ioDirID      = file->parID;\n        pb.ioDTReqCount = length;\n        err = PBDTSetComment(&pb, false);\n        }\n    return err;\n}\n\n\n\n\nOSErr   DecodeMacBinaryFile(FSSpec *source)\n{\n    Handle  data = nil;\n    OSErr   err;\n    short   dfRefNum = 0;\n    long    size;\n    FSSpec  McBin_source;\n\n    memcpy(McBin_source.name,source->name,source->name[0]+1);\n    McBin_source.vRefNum = source->vRefNum;\n    McBin_source.parID   = source->parID;\n\n    err = FSpOpenDF(source, fsRdPerm, &dfRefNum);\n    if(!err)\n        {\n        err = GetEOF(dfRefNum, &size);\n\n        data = TempNewHandle(size, &err);\n\n        if(data)\n            {\n            HLock(data);\n            err = FSRead(dfRefNum,&size,*data);\n            HUnlock(data);\n            }\n        FSClose(dfRefNum);\n        }\n\n    if(data && err == noErr)\n        {\n        err =  DecodeMacBinary(data, source);\n        DisposeHandle(data);\n        }\n\n#ifdef DELETE_MACBINARY_SOURCE\n    if (err == noErr)\n        err = FSpDelete(&McBin_source);\n#endif\n\n    return err;\n}\n\n\n\n\n\nstatic OSErr   DecodeMacBinary(Handle data, FSSpec *destination)\n{\n    Handle result = nil;\n    FInfo   fndrInfo;\n    OSErr   err;\n    CInfoPBRec  pb;\n    short   dfRefNum, rfRefNum;\n    long    ioCount;\n    char    header[128];\n    char    comment[256];\n    long    resourceForkLength, dataForkLength, commentLength;\n    Boolean isMacBinaryFile = false;\n    short   headerEnd = 128;\n    long    rfOffset;\n    long maxDataLen;\n\n    memset(&pb, 0, sizeof(CInfoPBRec));\n    pb.hFileInfo.ioNamePtr   = destination->name;\n    pb.hFileInfo.ioVRefNum   = destination->vRefNum;\n    pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */\n    pb.hFileInfo.ioDirID     = destination->parID;\n    err = PBGetCatInfo(&pb,false);\n    maxDataLen = pb.hFileInfo.ioFlLgLen;\n\n    HLock(data);\n    memcpy(header, *data, 128);\n\n     /* already checked with FSpIsMacBinary()    */\n    isMacBinaryFile = HeaderIsMacBinary(header, nil, maxDataLen);;\n\n    if(!isMacBinaryFile)\n        return paramErr;\n\n    if(WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset))\n        {\n        headerEnd = WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset);\n        headerEnd = (headerEnd + 127) & ~127L;\n        }\n\n    resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset);\n    dataForkLength     = LONG_AT_OFFSET(header, kDataForkLengthOffset);\n    commentLength      = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset);\n\n    memcpy( destination->name,\n            PTR_AT_OFFSET(header,\n            kFileNameLengthOffset),\n            BYTE_AT_OFFSET(header,\n            kFileNameLengthOffset));\n\n    fndrInfo.fdType    = LONG_AT_OFFSET(header, kFileTypeOffset);\n    fndrInfo.fdCreator = LONG_AT_OFFSET(header, kFileCreatorOffset);\n\n    fndrInfo.fdFlags = BYTE_AT_OFFSET(header, kFinderFlagsHiOffset);\n    fndrInfo.fdFlags << 8;\n    fndrInfo.fdFlags |= BYTE_AT_OFFSET(header, kFinderFlagsLowOffset);\n\n    fndrInfo.fdLocation.v = WORD_AT_OFFSET(header, kFileVPositionOffset);\n    fndrInfo.fdLocation.h = WORD_AT_OFFSET(header, kFileHPositionOffset);\n    fndrInfo.fdFldr       = WORD_AT_OFFSET(header, kFileFolderIDOffset);\n/*\n    index = 1;\n    checkFile = *destination;\n    while(FSpExists(&checkFile))\n        {\n        checkFile = *destination;\n\n        if(index < 10)\n            checkFile.name[++checkFile.name[0]] = '0' + index;\n        else\n            checkFile.name[++checkFile.name[0]] = ('a' - 10) + index;\n        index++;\n        }\n    *destination = checkFile;\n*/\n    err = FSpCreate(destination,\n                    fndrInfo.fdCreator,\n                    fndrInfo.fdType,\n                    smSystemScript);\n\n    dfRefNum = 0;\n    if(err == noErr)\n        {\n        err = FSpOpenDF(destination, fsRdWrPerm, &dfRefNum);\n        }\n\n    if(err == noErr && dfRefNum)\n        {\n        ioCount = dataForkLength;\n        err = FSWrite(dfRefNum,&ioCount,*data + headerEnd);\n        FSClose(dfRefNum);\n        }\n\n    rfRefNum = 0;\n    if(err == noErr)\n        {\n        err = FSpOpenRF(destination, fsRdWrPerm, &rfRefNum);\n        }\n\n    rfOffset = headerEnd + dataForkLength;\n    rfOffset = (rfOffset + 127) & ~127L;\n\n    if(err == noErr && rfRefNum)\n        {\n        ioCount = resourceForkLength;\n        err = FSWrite(rfRefNum,&ioCount,*data + rfOffset);\n        FSClose(rfRefNum);\n        }\n\n    rfOffset += resourceForkLength;\n    rfOffset = (rfOffset + 127) & ~127L;\n\n    if(err == noErr)\n       {\n        FSpSetFInfo(destination,&fndrInfo);\n\n        memset(&pb, 0, sizeof(CInfoPBRec));\n        pb.hFileInfo.ioNamePtr   = destination->name;\n        pb.hFileInfo.ioVRefNum   = destination->vRefNum;\n        pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */\n        pb.hFileInfo.ioDirID     = destination->parID;\n        err = PBGetCatInfo(&pb,false);\n\n        if(err == noErr)\n            {\n            pb.hFileInfo.ioDirID   = destination->parID;\n            pb.hFileInfo.ioFlCrDat =\n                          LONG_AT_OFFSET(header, kFileCreationDateOffset);\n            pb.hFileInfo.ioFlMdDat =\n                          LONG_AT_OFFSET(header, kFileModificationDateOffset);\n            pb.hFileInfo.ioFlXFndrInfo.fdXFlags =\n                          BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset);\n            pb.hFileInfo.ioFlXFndrInfo.fdScript =\n                          BYTE_AT_OFFSET(header, kFilenameScriptOffset);\n            err = PBSetCatInfo(&pb, false);\n            }\n\n        if(commentLength)\n            {\n            memcpy(comment,*data + rfOffset, commentLength);\n            SetDesktopComment(destination, comment, commentLength);\n            }\n\n        }\n    HUnlock(data);\n    return err;\n}\n\n#endif /*  INCLUDE_DECODE_MACBINARY  */\n\n\n\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macbin3.h",
    "content": "#ifndef __MCBINIII_H__\n#define __MCBINIII_H__\n\n\n/****************************************************************\n    MacBinaryIII.h\n\n    Copyright 1997 Christopher Evans (cevans@poppybank.com)\n\n    Basic encoding and decoding of Macintosh files to the\n    MacBinary III spec.\n****************************************************************/\n\n\n/*\n--------------------------------------------------------------------\nThis source is copyrighted by Christopher Evans (cevans@poppybank.com)\n(available at ftp://ftp.lazerware.com/MacBinaryIII_src_C.sit\n homepage of Leonard Rosenthol  leonardr@netcom.com)\n\n\n\nI made the following changes:\n    * renamed files MacBinaryIII.h / MacBinaryIII.c to\n      macbin3.c / macbin3.h\n    * removed pragmas:\n        #pragma once\n        #pragma options align=mac68k\n    * added 5 macros to make the migration into other projects easier:\n        DELETE_MACBINARY_SOURCE  -> delete the macbinary file after\n                                    decoding\n        INCLUDE_ENCODE_MACBINARY -> include the encode-part of the source\n        INCLUDE_DECODE_MACBINARY -> include the decode-part of the source\n        INCLUDE_CRC32CALC        -> include the CRC32 calculation\n        TRACE_MACBINARY          -> produce some diagnostic printouts\n    * changed the source layout to fit into a 80 col window\n    * removed non-ASCII characters from the sources\n    * renamed the function CalculateCRC() to crc32() and changed\n      the order of the arguments. So the crc32() func of the InfoZip\n      package can be used instead.\n    * moved module specific macros and protos to the mcbiniii.c\n    * added comments and enhanced the documention of the MacBinary Spec\n    * changed definition crc_table[] from short to unsigned long.\n    * improved the HeaderIsMacBinary() function to be more restrictive\n\nThe specification says:\n    \"Offsets 83 and 87, Long Word, (the length of the forks)\n    should be in the range of 0-$007FFFFF \"\nHowever, I do not understand the reason of this range. The data fork\ncan be much larger than $007FFFFF ( 2 Gigabytes! ) and the size of the\nresource fork can be until 16 MByte. ZipIt and Stuffit seems to be\nignore this limit.\nI changed this limit (see kResourceForkMaxLen), and I removed the\nmaximum check of the data fork.\n\nDirk Haase (d_haase@sitec.de); 05.Dec.1998\n\n--------------------------------------------------------------------\n\n\n\nMacBinary III\n\nMacBinary is a standard format for binary transfer of arbitrary Macintosh\ndocuments via a telecommunication link. It is intended for use both between\nMacintoshes and for use in uploading arbitrary Macintosh documents to remote\nsystems (where it is presumed that they will be stored as an exact image of\nthe data transmitted). It does this by combing both the resource and data\nforks (as well as the \"Finder Info\") of a standard Macintosh file into a\nsingle data fork only file that can be stored on non-Macintosh machines.\n\n\nThe format of the header for MacBinary III is as follows:\n Offset   Length         Contents\n 000      Byte           old version number, must be kept at zero for\n                         compatibility\n 001      Byte           Length of filename (must be in the range 1-31)\n 002      1 to 63 Bytes  filename (only \"length\" bytes are significant).\n 065      Long Word      file type (normally expressed as four characters)\n 069      Long Word      file creator (normally expressed as four\n                         characters)\n 073      Byte           original Finder flags\n                         Bit 7 - isAlias.\n                         Bit 6 - isInvisible.\n                         Bit 5 - hasBundle.\n                         Bit 4 - nameLocked.\n                         Bit 3 - isStationery.\n                         Bit 2 - hasCustomIcon.\n                         Bit 1 - reserved.\n                         Bit 0 - hasBeenInited.\n 074      Byte           zero fill, must be zero for compatibility\n 075      Word           file's vertical position within its window.\n 077      Word           file's horizontal position within its window.\n 079      Word           file's window or folder ID.\n 081      Byte           \"Protected\" flag (in low order bit).\n 082      Byte           zero fill, must be zero for compatibility\n 083      Long Word      Data Fork length (bytes, zero if no Data Fork).\n 087      Long Word      Resource Fork length (bytes, zero if no R.F.).\n 091      Long Word      File's creation date\n 095      Long Word      File's \"last modified\" date.\n 099      Word           length of Get Info comment to be sent after the\n                         resource fork (if implemented, see below).\n 101      Byte           Finder Flags, bits 0-7. (Bits 8-15 are already in\n                         byte 73)\n                         Bit 7    - hasNoInits\n                         Bit 6    - isShared\n                         Bit 5    - requiresSwitchLaunch\n                         Bit 4    - ColorReserved\n                         Bits 1-3 - color\n                         Bit 0    - isOnDesk\n *102     Long Word      signature for indentification purposes ('mBIN')\n *106     Byte           script of file name (from the fdScript field of an\n                         fxInfo record)\n *107     Byte           extended Finder flags (from the fdXFlags field of\n                         an fxInfo record)\n 108-115                 Unused (must be zeroed by creators, must be\n                         ignored by readers)\n 116      Long Word      Length of total files when packed files are\n                         unpacked. As of the writing of this document, this\n                         field has never been used.\n 120      Word           Length of a secondary header. If this is non-zero,\n                         skip this many bytes (rounded up to the next\n                         multiple of 128). This is for future expansion\n                         only, when sending files with MacBinary, this word\n                         should be zero.\n *122     Byte           Version number of MacBinary III that the uploading\n                         program is written for (the version is 130 for\n                         MacBinary III)\n 123      Byte           Minimum MacBinary version needed to read this file\n                         (set this value at 129 for backwards compatibility\n                         with MacBinary II)\n 124      Word           CRC of previous 124 bytes\n\n*These fields have changed for MacBinary III.\n\n   All values are stored in normal 68000 order, with Most Significant Byte\nappearing first then the file. Any bytes in the header not defined above\nshould be set to zero.\n\n*/\n\n\n/*\nPublic functions\n*/\n\nOSErr   EncodeMacbinaryFile(FSSpec *file);\nOSErr   DecodeMacBinaryFile(FSSpec *source);\nBoolean FSpIsMacBinary(FSSpec *file);\n\n\n#endif\n\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/maccfg.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    MACOS specific configuration and declarations:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __maccfg_h\n#define __maccfg_h\n\n\n/*****************************************************************************/\n/*  Macros, missing RTL declarations, compatibility typedefs                 */\n/*****************************************************************************/\n\n\n#if defined(__MWERKS__) && defined(macintosh)\n#  include <OSUtils.h>\n\n   typedef unsigned long mode_t;\n#  define _STAT\n\n#  if (defined(MacStaticLib) || defined(USE_SIOUX))\n#    define MAIN   UZ_EXP UzpMain   /* was UzpUnzip */\n#  else\n#    define MAIN   _dummy_main\n#  endif\n#endif\n\n#ifdef THINK_C\n#  ifndef __STDC__              /* if Think C hasn't defined __STDC__ ... */\n#    define __STDC__ 1          /*   make sure it's defined: it needs it */\n#  else\n#    if !__STDC__               /* sometimes __STDC__ is defined as 0; */\n#      undef __STDC__           /*   it needs to be 1 or required header */\n#      define __STDC__ 1        /*   files are not properly included. */\n#    endif /* !__STDC__ */\n#  endif\n#  define IOCompletionUPP   ProcPtr\n#  define CREATOR  'KAHL'\n#  define MAIN     _dummy_main\n#endif /* THINK_C */\n\n#ifdef MPW\n#  include <Errors.h>\n#  include <Files.h>\n#  include <Memory.h>\n#  include <Quickdraw.h>\n#  include <ToolUtils.h>\n#  ifndef QUERY_TRNEWLN\n#    define QUERY_TRNEWLN\n#  endif\n#  ifdef fileno\n#    undef fileno\n#  endif\n#  ifdef MCH_MACINTOSH\n#    define CREATOR     'Manx'\n#  else\n#    define CREATOR     'MPS '\n#  endif\n#endif /* MPW */\n\n#include <fcntl.h>              /* O_BINARY for open() w/o CR/LF translation */\n#define fileno(x)       ((x) == stdout ? 1 : ((x) == stderr ? 2 : (short)(x)))\n#define open            macopen\n#define close           macclose\n#define fclose(x)       macclose(fileno((x)))\n#define read            macread\n#define write           macwrite\n#define lseek           maclseek\n#define creat(x,y)      maccreat((x))\n#define stat            UZmacstat\n#define lstat           UZmacstat\n#define dup\n#ifndef MCH_MACINTOSH\n#  define NO_STRNICMP\n#endif\n\n#define DIR_END ':'\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT DF_MDY\n#endif\n#define lenEOL        1\n#define PutNativeEOL  *q++ = native(CR);\n#define NOANSIFILT  /* MWRKS C creates broken code for the ANSI-ESC filter */\n#define MALLOC_WORK\n#define INT_SPRINTF\n\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n\n#undef IZ_CHECK_TZ\n#undef MORE\n#undef DYNAMIC_CRC_TABLE\n\n\n#ifndef MPW\n#  ifndef MacStaticLib\n#    ifndef USE_SIOUX\n#      define fgets       macfgets\n#      define fflush(f)\n#      define fprintf     macfprintf\n#      define fputs(s,f)  macfprintf((f), \"%s\", (s))\n#      define printf      macprintf\n#      ifdef putc\n#        undef putc\n#      endif\n#      define putc(c,f)   macfprintf((f), \"%c\", (c))\n#    endif /* !USE_SIOUX */\n#  else\n#    ifdef putc\n#      undef putc\n#    endif\n#    define putc(c,f)   fprintf((f), \"%c\", (c))\n#  endif\n\n#  define isatty(f)     (((f) >= 0) || ((f) <= 2))\n#endif\n\n#ifndef isascii\n#  define isascii(c)    ((unsigned char)(c) <= 0x3F)\n#endif\n\n#include \"macstat.h\"\n#include \"macdir.h\"\n\n#ifdef CR\n#  undef  CR\n#endif\n\n\n#ifdef foreign\n#  undef foreign\n#endif\n#define foreign(c) ((c) & 0x80 ? MacRoman_to_WinCP1252[(c) & 0x7f] : (c))\n\n#ifdef native\n#  undef native\n#endif\n#define native(c)  ((c) & 0x80 ? WinCP1252_to_MacRoman[(c) & 0x7f] : (c))\n#define NATIVE \"MacRoman charset\"\n\n#ifdef _ISO_INTERN\n#  undef _ISO_INTERN\n#endif\n#define _ISO_INTERN(str1) {register uch *p;\\\n   for (p=(uch *)(str1); *p; p++)\\\n     *p = (*p & 0x80) ? WinCP1252_to_MacRoman[*p & 0x7f] : *p;}\n\n#ifdef _OEM_INTERN\n#  undef _OEM_INTERN\n#endif\n#ifndef IZ_OEM2ISO_ARRAY\n#  define IZ_OEM2ISO_ARRAY\n#endif\n#define _OEM_INTERN(str1) {register uch *p;\\\n   for (p=(uch *)(str1); *p; p++)\\\n     *p = (*p & 0x80) ? WinCP1252_to_MacRoman[oem2iso[*p & 0x7f]] : *p;}\n\n#ifdef __FILEIO_C       /* get the ISO8859-1 <--> MacROMAN conversion tables */\n#  include \"charmap.h\"\n#else\n   extern ZCONST uch WinCP1252_to_MacRoman[128];\n   extern ZCONST uch MacRoman_to_WinCP1252[128];\n#endif\n\n\n#define EB_M3_FL_NOCHANGE   0x02    /* filename will be not changed */\n/* other EB_M3 flags are defined in unzpriv.h */\n#define EB_MAC3_SIZE        (EB_HEADSIZE + EB_MAC3_HLEN)\n\n/*****************************************************************************/\n/*  Structure typedefs                                                       */\n/*****************************************************************************/\n\ntypedef struct _ZipExtraHdr {\n        ush header;               /*    2 bytes */\n        ush data;                 /*    2 bytes */\n} ZIP_EXTRA_HEADER;\n\n\n/* the following structure is a combination of the old and the new\n   extra-field definition; so it's *not* the definition of the extra-field  */\n\ntypedef struct _MacInfo {\n    unsigned char *filename;  /* for ZipIt ef */\n    ush         header;     /* tag for this extra block type  */\n    ush         data;       /* total data size for this block */\n    ulg         size;       /* uncompressed finder attribute data size */\n\n    ush         flags;      /* info bits:\n                                 bit 0   if set, file is a data fork\n                                 bit 1   if set, filename will be not changed\n                                 bit 2   if set, Attribs is uncompressed\n                                 bit 3   if set, date and times are in 64 bit;\n                                         if zero, date and times are in 32 bit\n                                 bit 4   if set, \"local time - UTC\" offsets are\n                                         omitted\n                                 bits 5-15       reserved; not tested;   */\n\n    ush         CompType;\n    ulg         CRCvalue;\n\n    CInfoPBRec  fpb;        /* Macintosh FInfo / FXInfo structure */\n    long        Cr_UTCoffs; /* difference \"local time - UTC\" for Creat-time */\n    long        Md_UTCoffs; /* difference \"local time - UTC\" for Modif-time */\n    long        Bk_UTCoffs; /* difference \"local time - UTC\" for Bckup-time */\n\n    short       TextEncodingBase;   /* TextEncodingBase (Charset) */\n    char       *FullPath;           /* Path of the current file */\n    char       *FinderComment;      /* Finder Comment of current file */\n} MACINFO;\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    short    giCursor;\\\n    CursHandle rghCursor[4];       /* status cursors */\n\n#define SYSTEM_SPECIFIC_CTOR    MacGlobalsInit\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nvoid    screenOpen      OF((char *));                         /* macscreen.c */\nvoid    screenControl   OF((char *, int));                    /* macscreen.c */\nvoid    screenDump      OF((char *, long));                   /* macscreen.c */\nvoid    screenUpdate    OF((WindowPtr));                      /* macscreen.c */\nvoid    screenClose     OF((void));                           /* macscreen.c */\nint     macgetch        OF((void));                           /* macscreen.c */\n\nint     macmkdir        OF((char *));                             /* macos.c */\nshort   macopen         OF((char *, short));                      /* macos.c */\nshort   maccreat        OF((char *));                             /* macos.c */\nshort   macread         OF((short, char *, unsigned));            /* macos.c */\nlong    macwrite        OF((short, char *, unsigned));            /* macos.c */\nshort   macclose        OF((short));                              /* macos.c */\nlong    maclseek        OF((short, long, short));                 /* macos.c */\nchar   *macfgets        OF((char *, int, FILE *));                /* macos.c */\nint     macfprintf      OF((FILE *, char *, ...));                /* macos.c */\nint     macprintf       OF((char *, ...));                        /* macos.c */\n\nulg    makePPClong(ZCONST uch *sig);\nush    makePPCword(ZCONST uch *b);\nvoid   UserStop(void);\n\n#endif /* !__maccfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macdir.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macdir.c\n\n *  This file provides dirent-style directory-reading procedures\n *  for V7 Unix systems that don't have such procedures.\n *\n *\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n\n#include    <Errors.h>\n#include    <Files.h>\n#include    <Strings.h>\n#include    <sound.h>\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"macdir.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\nint closedir(DIR *dPtr)\n{\n    free(dPtr);\n\n    return 0;\n}\n\n\nDIR *opendir(char *dirName)\n{\n    int fullPath;\n    unsigned pathLen;\n    char *s;\n    HParamBlockRec hPB;\n    CInfoPBRec cPB;\n    DIR *dPtr;\n    OSErr err;\n    FSSpec spec;\n    char CompletePath[NAME_MAX];\n\n    GetCompletePath(CompletePath, dirName, &spec, &err);\n    printerr(\"GetCompletePath\", err, err, __LINE__, __FILE__, dirName);\n\n    if (dirName == NULL || *dirName == '\\0' ||\n        (pathLen = strlen(dirName)) >= 256) {\n        errno = EINVAL;\n        return NULL;\n    }\n\n\n    /* Get information about volume. */\n    memset(&hPB, '\\0', sizeof(hPB));\n\n    if (((s = strchr(dirName, ':')) == NULL) || (*dirName == ':')) {\n        fullPath = false;\n    } else {\n        *(s + 1) = '\\0';\n        hPB.volumeParam.ioVolIndex = -1;\n        fullPath = true;\n    }\n\n    hPB.volumeParam.ioNamePtr = spec.name;\n\n    err = PBHGetVInfoSync(&hPB);\n\n    if ((err != noErr) || (hPB.volumeParam.ioVFSID != 0)) {\n        errno = ENOENT;\n        return NULL;\n    }\n\n    /* Get information about file. */\n\n    memset(&cPB, '\\0', sizeof(cPB));\n\n    if (fullPath)\n        cPB.hFileInfo.ioVRefNum = hPB.volumeParam.ioVRefNum;\n\n    cPB.hFileInfo.ioNamePtr = spec.name;\n\n    err = PBGetCatInfoSync(&cPB);\n\n    if (err != noErr) {\n        errno = (err == fnfErr) ? ENOENT : EIO;\n        return NULL;\n    }\n\n    if (!(cPB.hFileInfo.ioFlAttrib & ioDirMask)) {\n        errno = ENOTDIR;\n        return NULL;\n    }\n\n    /* Get space for, and fill in, DIR structure. */\n\n    if ((dPtr = (DIR *)malloc(sizeof(DIR))) == NULL) {\n        return NULL;\n    }\n\n    dPtr->ioVRefNum = cPB.dirInfo.ioVRefNum;\n    dPtr->ioDrDirID = cPB.dirInfo.ioDrDirID;\n    dPtr->ioFDirIndex = 1;\n    dPtr->flags = 0;\n\n    return dPtr;\n}\n\n\nstruct dirent *readdir(DIR *dPtr)\n{\n    struct dirent *dirPtr;\n    CInfoPBRec cPB;\n    char name[256];\n    OSErr err;\n\n    if (dPtr->flags) {\n        return NULL;\n    }\n\n    /* Get information about file. */\n\n    memset(&cPB, '\\0', sizeof(cPB));\n\n    cPB.hFileInfo.ioNamePtr = (StringPtr)name;\n    cPB.hFileInfo.ioFDirIndex = dPtr->ioFDirIndex;\n    cPB.hFileInfo.ioVRefNum = dPtr->ioVRefNum;\n    cPB.hFileInfo.ioDirID = dPtr->ioDrDirID;\n\n    err = PBGetCatInfoSync(&cPB);\n\n    if (err != noErr) {\n        dPtr->flags = 0xff;\n        errno = (err == fnfErr) ? ENOENT : EIO;\n        return NULL;\n    }\n\n    p2cstr((StringPtr)name);\n\n    dirPtr = &dPtr->currEntry;\n\n    dirPtr->d_fileno = dPtr->ioFDirIndex++;\n    dirPtr->d_namlen = strlen(name);\n    strcpy(dirPtr->d_name, name);\n    dirPtr->d_reclen = sizeof(struct dirent) - sizeof(dirPtr->d_name) +\n                       dirPtr->d_namlen;\n\n    return dirPtr;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macdir.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*****************************************************************\n *\n *                dirent.h\n *\n *****************************************************************/\n\n#ifndef __DIRENT_H\n#define __DIRENT_H\n\n#include <errno.h>\n\n#ifndef EINVAL\n#define EINVAL      9\n#endif\n\n#ifndef EIO\n#define EIO         10\n#endif\n\n#ifndef ENOTDIR\n#define ENOTDIR     20\n#endif\n\n#ifndef ENOENT\n#define ENOENT      39\n#endif\n\n#ifndef NAME_MAX\n#define NAME_MAX    1024\n#endif\n\nstruct dirent {\n    unsigned long   d_fileno;\n    short           d_reclen;\n    short           d_namlen;\n    char            d_name[NAME_MAX + 1];\n};\n\ntypedef struct {\n    short           ioFDirIndex;\n    short           ioVRefNum;\n    long            ioDrDirID;\n    short           flags;\n    struct dirent   currEntry;\n} DIR;\n\n#define direct dirent\n\nDIR *opendir(char *);\nstruct dirent *readdir(DIR *);\nvoid rewinddir(DIR *);\nint closedir(DIR *);\n\n#endif /* !__DIRENT_H */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macos.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macos.c\n\n  Macintosh-specific routines for use with Info-ZIP's UnZip 5.4 and later.\n\n  Contains:\n                    do_wild ()\n                    mapattr ()\n                    checkdir ()\n                    version ()\n                    macmkdir ()\n                    macopen ()\n                    maccreat ()\n                    macread ()\n                    macwrite ()\n                    macclose ()\n                    maclseek ()\n                    BuildMacFilename()\n                    SetFinderInfo ()\n                    isMacOSexfield ()\n                    makePPClong ()\n                    makePPCword ()\n                    PrintMacExtraInfo ()\n                    GetExtraFieldData ()\n                    DecodeMac3ExtraField ()\n                    DecodeJLEEextraField ()\n                    PrintTextEncoding ()\n                    MacGlobalsInit ()\n\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include <script.h>\n#include <sound.h>\n\n#include \"pathname.h\"\n#include \"helpers.h\"\n#include \"macstuff.h\"\n#include \"mactime.h\"\n#include \"macbin3.h\"\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n/* disable ZipIt support\n#define SwitchZIPITefSupportOff */\n\n#define read_only   file_attr       /* for readability only */\n#define EB_MAX_OF_VARDATA   1300    /* max possible datasize of extra-field */\n\n#ifdef WILD_STOP_AT_DIR\n#  define WESEP     , (oU.W_flag ? ':' : '\\0')\n#else\n#  define WESEP\n#endif\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\n/*  Note: sizeof() returns the size of this allusion\n          13 is current length of \"XtraStuf.mac:\"      */\nextern const char ResourceMark[13]; /* var is initialized in file pathname.c */\n\nBoolean MacUnzip_Noisy;            /* MacUnzip_Noisy is also used by console */\n\nMACINFO newExtraField;  /* contains all extra-field data */\nshort MacZipMode;\n\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\nstatic const char MacPathEnd = ':';   /* the Macintosh dir separator */\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\nstatic FSSpec CurrentFile;\n\nstatic Boolean OpenZipFile = true;\nstatic Boolean UseUT_ExtraField     = false;\nstatic Boolean IgnoreEF_Macfilename = false;\nstatic short fileSystemID;\n\nstatic uch *attrbuff = NULL;\nstatic uch *malloced_attrbuff = NULL;\n\nconst short HFS_fileSystem = 0;\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nextern char *GetUnZipInfoVersions(void);\n\nstatic OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi);\nstatic Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi);\nstatic uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,\n                             short *MacZipMode);\nstatic Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode);\nstatic void PrintMacExtraInfo(MACINFO *mi);\nstatic OSErr SetFileTime(__GPRO);\nstatic void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi);\nstatic void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi);\nstatic void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi);\nstatic char *PrintTextEncoding(short script);\nstatic void BuildMacFilename(void);\n\n/*****************************************************************************/\n/*  Constants (strings, etc.)                                                */\n/*****************************************************************************/\n\nstatic ZCONST char Far CannotCreateFile[] = \"error:  cannot create %s\\n\";\n\nstatic ZCONST char Far OutOfMemEF[] = \"Can't allocate memory to uncompress\"\\\n                                      \" file attributes.\\n\";\n\nstatic ZCONST char Far ErrUncmpEF[] = \"Error uncompressing file attributes.\\n\";\n\nstatic ZCONST char Far No64Time[]   = \"Don't support 64 bit Timevalues; get \"\\\n                                      \" a newer version of MacZip \\n\";\n\nstatic ZCONST char Far NoUniCode[]  = \"Don't support Unicoded Filenames; get\"\\\n                                      \" a newer version of MacZip\\n\";\n\nstatic ZCONST char Far ZitIt_EF[]   = \"warning: found ZipIt extra field  \"\\\n                                      \" -> file is probably not \"\\\n                                      \"usable!!\\n\";\n\nstatic ZCONST char Far CantAllocateWildcard[] =\n    \"warning:  cannot allocate wildcard buffers\\n\";\n\nstatic ZCONST char Far ErrNoTimeSet[] = \"error (%d): cannot set the time for\"\\\n                                        \" %s\\n\";\n\nstatic ZCONST char Far MacBinaryMsg[] = \"\\n   ... decoding MacBinary \";\n\nstatic ZCONST char Far WarnDirTraversSkip[] =\n  \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\";\n\nstatic ZCONST char Far Creating[] = \"   creating: %s\\n\";\n\nstatic ZCONST char Far ConversionFailed[] =\n  \"mapname:  conversion of %s failed\\n\";\n\nstatic ZCONST char Far PathTooLong[] = \"checkdir error:  path too long: %s\\n\";\n\nstatic ZCONST char Far CantCreateDir[] = \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\";\n\nstatic ZCONST char Far DirIsntDirectory[] =\n  \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\";\n\nstatic ZCONST char Far PathTooLongTrunc[] =\n  \"checkdir warning:  path too long; truncating\\n                   %s\\n\\\n                -> %s\\n\";\n\nstatic ZCONST char Far CantCreateExtractDir[] =\n  \"checkdir:  cannot create extraction directory: %s\\n\";\n\nstatic ZCONST char Far FilenameToLong[] =\n  \"Filename is to long; truncated: %s\\n\";\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n#ifndef SFX\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname;\n    static unsigned long dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        /* Folder names must always end with a colon */\n        if (uO.exdir[strlen(uO.exdir)-1] != ':') {\n            strcat(uO.exdir, \":\");\n        }\n\n        MacUnzip_Noisy = !uO.qflag;\n\n        if (MacUnzip_Noisy) printf(\"%s \\n\\n\", GetUnZipInfoVersions());\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = (ZCONST char *)strrchr(wildspec, ':')) ==\n            (ZCONST char *)NULL) {\n            dirname = \":\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after ':' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  LoadFarString(CantAllocateWildcard)));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL)\n        if (match(file->d_name, wildname, 0 WESEP)) {   /* 0 == case sens. */\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n\n/***************************/\n/* Function open_outfile() */\n/***************************/\n\nint open_outfile(__G)         /* return 1 if fail */\n    __GDEF\n{\n    short outfd, fDataFork = true;\n\n#ifdef DLL\n    if (G.redirect_data)\n        return (redirect_outfile(__G) == FALSE);\n#endif\n    Trace((stderr, \"open_outfile:  trying to open (%s) for writing\\n\",\n      FnFilter1(G.filename)));\n\n    if (!uO.aflag) {\n         /* unknown type documents */\n         /* all files are considered to be of type 'TEXT' and creator 'hscd' */\n         /* this is the default type for CDROM ISO-9660 without Apple extensions */\n        newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';\n        newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'hscd';\n    } else {\n     /* unknown text-files defaults to 'TEXT' */\n        newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';\n     /* Bare Bones BBEdit */\n        newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'R*ch';\n    }\n\n    BuildMacFilename();\n\n    if  (MacZipMode <= TomBrownZipIt2_EF)\n        {\n        fDataFork = true;\n        }\n    else\n        {\n        fDataFork = (newExtraField.flags & EB_M3_FL_DATFRK) ? TRUE : FALSE;\n        }\n\n\n    if ((outfd = maccreat(G.filename)) != -1) {\n        outfd = macopen(G.filename, (fDataFork) ? 1 : 2);\n    }\n\n    if (outfd == -1) {\n        G.outfile = (FILE *)NULL;\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename)));\n        return 1;\n    }\n    G.outfile = (FILE *)outfd;\n    Trace((stderr, \"open_outfile:  successfully opened (%s) for writing\\n\",\n      FnFilter1(G.filename)));\n\n    return 0;\n\n} /* end function open_outfile() */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    /* only care about read-only bit, so just look at MS-DOS side of attrs */\n    G.pInfo->read_only = (unsigned)(G.crec.external_file_attributes & 1);\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels on Macintosh */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL) {   /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n        if (renamed_fullpath)\n            ++cp;               /* skip over leading '/' */\n    } else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ':':\n                *pp++ = '/';      /* ':' is a pathseperator for HFS  */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;         /* keep for now; remove VMS \";##\" */\n                *pp++ = (char)workch;  /*  later, if requested */\n                break;\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(Creating),\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > NAME_MAX)\n            *(end = old_end + NAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > NAME_MAX-3)   /* need ':', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (macmkdir(buildpath) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n              FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = ':';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > NAME_MAX)\n                *(end = old_end + NAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= NAME_MAX) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  LoadFarString(PathTooLongTrunc),\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+2))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            end = buildpath;\n            if (!renamed_fullpath && !uO.jflag) {\n                *end++ = ':';           /* indicate relative path */\n            }\n            *end = '\\0';\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == ':') {\n                tmproot[--rootlen] = '\\0';     /* strip trailing delimiter */\n            }\n            if (rootlen > 0 && (stat(tmproot, &G.statbuf) ||\n                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (macmkdir(tmproot) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      LoadFarString(CantCreateExtractDir),\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[rootlen++] = ':';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    OSErr err;\n\n    if (fileno(G.outfile) == 1)\n        return;         /* don't attempt to close or set time on stdout */\n\n    err = (OSErr)fclose(G.outfile);\n\n    /* finally set FinderInfo */\n    if  (MacZipMode >= JohnnyLee_EF)\n        {\n        /* skip restoring time stamps on user's request */\n        err = SetFinderInfo(__G__ (uO.D_flag <= 1),\n                            &CurrentFile, &newExtraField);\n        printerr(\"close_outfile SetFinderInfo \", err, err,\n                 __LINE__, __FILE__, G.filename);\n        }\n    else  /* unknown extra field, set at least file time/dates */\n        {\n        /* skip restoring time stamps on user's request */\n        if (uO.D_flag <= 1)\n            err = SetFileTime(__G);\n        }\n\n#ifndef SwitchZIPITefSupportOff\n    if ((MacZipMode == TomBrownZipIt1_EF) ||\n        (MacZipMode == TomBrownZipIt2_EF))\n        {\n        if(FSpIsMacBinary(&CurrentFile))\n            {\n            Info(slide, 0, ((char *)slide, LoadFarString(MacBinaryMsg)));\n                err = DecodeMacBinaryFile(&CurrentFile);\n                printerr(\"close_outfile DecodeMacBinaryFile \", err, err,\n                  __LINE__, __FILE__, G.filename);\n            }\n        }\n#endif\n\n        /* set read-only perms if needed */\n    if ((err == noErr) && G.pInfo->read_only)\n        {\n        err = FSpSetFLock(&CurrentFile);\n        printerr(\"FSpSetFLock\",err,err,__LINE__,__FILE__,G.filename);\n        }\n\n    if (malloced_attrbuff != NULL)\n        {\n        attrbuff = malloced_attrbuff;\n        }\n\n} /* end function close_outfile() */\n\n\n\n\n/****************************/\n/* Function SetFileTime() */\n/****************************/\n\nstatic OSErr SetFileTime(__G)\n    __GDEF\n{\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    unsigned eb_izux_flg;\n#endif\n    OSErr err;\n    CInfoPBRec      fpb;\n\n    fpb.hFileInfo.ioNamePtr    = CurrentFile.name;\n    fpb.hFileInfo.ioVRefNum    = CurrentFile.vRefNum;\n    fpb.hFileInfo.ioDirID      = CurrentFile.parID;\n    fpb.hFileInfo.ioFDirIndex  = 0;\n\n    err = PBGetCatInfoSync((CInfoPBPtr)&fpb);\n    printerr(\"PBGetCatInfoSync\", err, err, __LINE__, __FILE__, G.filename);\n\n    if ((MacZipMode == UnKnown_EF) || UseUT_ExtraField ) {\n\n#ifdef USE_EF_UT_TIME\n        eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                                       G.lrec.last_mod_dos_datetime, &z_utime, NULL);\n\n        if (G.extra_field && (eb_izux_flg & EB_UT_FL_MTIME))\n            {\n            fpb.hFileInfo.ioFlMdDat = UnixFtime2MacFtime(z_utime.mtime);\n            fpb.hFileInfo.ioFlCrDat = UnixFtime2MacFtime(z_utime.ctime);\n            }\n\n#ifdef DEBUG_TIME\n            {\n            struct tm *tp = gmtime(&z_utime.ctime);\n            printf(\n              \"SetFileTime:  Unix e.f. creat. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\\n\",\n              tp->tm_year, tp->tm_mon+1, tp->tm_mday,\n              tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.ctime);\n            tp = gmtime(&z_utime.mtime);\n            printf(\n              \"SetFileTime:  Unix e.f. modif. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\\n\",\n              tp->tm_year, tp->tm_mon+1, tp->tm_mday,\n              tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.mtime);\n            }\n#endif /* DEBUG_TIME */\n\n\n        else /* no Unix time field found - use dostime  */\n#endif /* !USE_EF_UT_TIME */\n            {\n            TTrace((stderr, \"SetFileTime:  using DOS-Datetime ! \\n\",\n                    z_utime.mtime));\n            fpb.hFileInfo.ioFlMdDat = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n            UNIX_TO_MACOS(fpb.hFileInfo.ioFlMdDat);\n            fpb.hFileInfo.ioFlCrDat = fpb.hFileInfo.ioFlMdDat;\n            }\n\n     /* Restore ioDirID field in pb which was changed by PBGetCatInfoSync */\n        fpb.hFileInfo.ioDirID = CurrentFile.parID;\n\n        if (err == noErr)\n            {\n            err = PBSetCatInfoSync((CInfoPBPtr)&fpb);\n            printerr(\"PBSetCatInfoSync\",err,err,__LINE__,__FILE__,G.filename);\n            }\n        if (err != noErr)\n            Info(slide, 0x201, ((char *)slide, LoadFarString(ErrNoTimeSet),\n              FnFilter1(G.filename)));\n    }\n\nreturn err;\n} /* end function SetFileTime() */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n/*\nZCONST char Far CompiledWith[] =\n               \"Compiled with %s%s for %s%s%s%s.\\n\\n\"; */\n\nchar DateTime[50];\n\n#ifdef __MWERKS__\nchar CompVer[10];\nsprintf(CompVer, \"%x\", __MWERKS__);\n#endif\n\n    sprintf(DateTime,\"%s  %s\",__DATE__, __TIME__);\n\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __MWERKS__\n\n      \" Metrowerks CodeWarrior version \",CompVer,\n#else\n      \" \", \" \",\n#endif\n\n#ifdef __MC68K__\n      \" MC68K Processor\",\n#else\n      \" PowerPC Processor\",\n#endif\n\n#ifdef __DATE__\n\n      \"\\n compile time: \", DateTime, \"\"\n#else\n      \"\", \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n\n\n/***********************/\n/* Function macmkdir() */\n/***********************/\n\nint macmkdir(char *path)\n{\n    OSErr err = -1;\n    OSErr err_rc;\n    char CompletePath[NAME_MAX], CompletePath2[NAME_MAX];\n    Boolean isDirectory = false;\n    short CurrentFork;\n    unsigned pathlen;\n    long dirID;\n\n    AssertStr(path, path)\n\n    GetExtraFieldData(&MacZipMode, &newExtraField);\n\n    if (MacZipMode >= JohnnyLee_EF) {\n        RfDfFilen2Real(CompletePath, G.filename, MacZipMode,\n                       (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork);\n        if (CurrentFork == ResourceFork)\n            /* don't build a 'XtraStuf.mac:' dir  */\n            return 0;\n    }\n\n    if (!IgnoreEF_Macfilename)\n        {\n        pathlen = strlen(path);\n        strcpy(CompletePath, uO.exdir);\n        strcat(CompletePath, newExtraField.FullPath);\n        CompletePath[pathlen] = 0x00;\n        }\n    else\n        {\n        strcpy(CompletePath, path);\n        }\n\n    GetCompletePath(CompletePath2, CompletePath, &CurrentFile, &err);\n    printerr(\"GetCompletePath\", (err != -43) && (err != -120) && (err != 0),\n              err, __LINE__, __FILE__, CompletePath2);\n\n\n    err = FSpGetDirectoryID(&CurrentFile, &dirID, &isDirectory);\n    printerr(\"macmkdir FSpGetDirectoryID \", (err != -43) && (err != 0),\n             err, __LINE__, __FILE__, CompletePath2);\n\n    if (err != -43)     /* -43 = file/directory not found  */\n        return 0;\n    else {\n        HParamBlockRec    hpbr;\n\n        hpbr.fileParam.ioCompletion = NULL;\n        hpbr.fileParam.ioNamePtr    = CurrentFile.name;\n        hpbr.fileParam.ioVRefNum    = CurrentFile.vRefNum;\n        hpbr.fileParam.ioDirID      = CurrentFile.parID;\n        err = PBDirCreateSync(&hpbr);\n        printerr(\"macmkdir PBDirCreateSync \", err,\n                 err, __LINE__, __FILE__, CompletePath2);\n\n        /* finally set FinderInfo */\n        if  (MacZipMode >= JohnnyLee_EF)\n            {\n            err_rc = SetFinderInfo(__G__ (uO.D_flag <= 0),\n                                   &CurrentFile, &newExtraField);\n            printerr(\"macmkdir SetFinderInfo \", err_rc, err_rc,\n                      __LINE__, __FILE__, CompletePath2);\n            }\n    }\n\n    return (int)err;\n} /* macmkdir */\n\n\n\n\n/**********************/\n/* Function macopen() */\n/**********************/\n\nshort macopen(char *sz, short nFlags)\n{\n    OSErr   err;\n    char    chPerms = (!nFlags) ? fsRdPerm : fsRdWrPerm;\n    short   nFRefNum;\n\n    AssertStr(sz, sz)\n\n    /* we only need the filespec of the zipfile;\n       filespec of the other files (to be extracted) will be\n       determined by open_outfile() */\n    if (OpenZipFile)\n        {\n        char CompletePath[NAME_MAX];\n        FSSpec zipfile;\n        GetCompletePath(CompletePath, sz, &zipfile, &err);\n        printerr(\"GetCompletePath\", (err != -43) && (err != 0),\n                  err, __LINE__, __FILE__, sz);\n        if (CheckMountedVolumes(CompletePath) > 1)\n            DoWarnUserDupVol(CompletePath);\n        err = HOpen(zipfile.vRefNum, zipfile.parID, zipfile.name,\n                    chPerms, &nFRefNum);\n        printerr(\"Zipfile HOpen\", err, err, __LINE__, __FILE__, sz);\n        OpenZipFile = false;\n        }\n    else   /* open zipfile entries  */\n        {\n        if (nFlags > 1)\n            {\n            err = HOpenRF(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,\n                      chPerms, &nFRefNum);\n            printerr(\"HOpenRF\", (err != -43) && (err != 0) && (err != -54),\n                 err, __LINE__, __FILE__, sz);\n            }\n        else\n            {\n            err = HOpen(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,\n                    chPerms, &nFRefNum);\n            printerr(\"HOpen\", (err != -43) && (err != 0),\n                 err, __LINE__, __FILE__, sz);\n            }\n        }\n\n    if ( err || (nFRefNum == 1) )\n        {\n        printerr(\"macopen\", err, err, __LINE__, __FILE__,\n                 (char *) CurrentFile.name);\n        return -1;\n        }\n    else\n        {\n        if ( nFlags )\n            SetEOF( nFRefNum, 0 );\n        return nFRefNum;\n        }\n}\n\n\n\n\n\n/***********************/\n/* Function maccreat() */\n/***********************/\n\nshort maccreat(char *sz)\n{\n    OSErr   err;\n    char scriptTag = newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript;\n    static char Num = 0;\n\n    sz = sz;\n\n    /* Set fdScript in FXInfo\n     * The negative script constants (smSystemScript, smCurrentScript,\n     * and smAllScripts) don't make sense on disk.  So only use scriptTag\n     * if scriptTag >= smRoman (smRoman is 0).\n     * fdScript is valid if high bit is set (see IM-6, page 9-38)\n     */\n    scriptTag = (scriptTag >= smRoman) ?\n                ((char)scriptTag | (char)0x80) : (smRoman);\n    newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = scriptTag;\n\n    err = FSpCreate(&CurrentFile,\n                    newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,\n                    newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,\n                    newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);\n\n    /* -37 = bad filename; make the filename shorter and try again  */\n    /* filename must not be longer than 32 chars */\n    if (err == -37)\n        {\n        strcpy((char *)CurrentFile.name,\n                MakeFilenameShorter(P2CStr(CurrentFile.name)));\n        Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameToLong),\n          FnFilter1((char *)CurrentFile.name)));\n        C2PStr((char *)CurrentFile.name);\n        err = FSpCreate(&CurrentFile,\n                    newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,\n                    newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,\n                    newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);\n        }\n\n    err = printerr(\"FSpCreate maccreat \", (err != -48) && (err != 0),\n                   err, __LINE__, __FILE__, G.filename);\n\n    if (err == noErr)\n        return noErr;\n    else\n        return -1;\n}\n\n\n\n\n\n/**********************/\n/* Function macread() */\n/**********************/\n\nshort macread(short nFRefNum, char *pb, unsigned cb)\n{\n    long    lcb = cb;\n\n    (void)FSRead( nFRefNum, &lcb, pb );\n    return (short)lcb;\n}\n\n\n\n\n/***********************/\n/* Function macwrite() */\n/***********************/\n\nlong macwrite(short nFRefNum, char *pb, unsigned cb)\n{\n    long    lcb = cb;\n    OSErr   err = 0;\n    FILE    *stream;\n\n    if ( (nFRefNum == 1) || (nFRefNum == 2) )\n        {\n        stream = (nFRefNum == 1 ? stdout : stderr);\n        pb[cb] = '\\0';           /* terminate C-string */\n                                 /* assumes writable buffer (e.g., slide[]) */\n                                 /* with room for one more char at end of buf */\n        lcb = fprintf(stream, \"%s\", pb);\n        }\n    else\n        err = FSWrite( nFRefNum, &lcb, pb );\n\n    if (err != 0)\n        {\n        errno = ERANGE;\n        return -1;\n        }\n\n    return (long)lcb;\n}\n\n\n\n\n\n/***********************/\n/* Function macclose() */\n/***********************/\n\nshort macclose(short nFRefNum)\n{\nOSErr err;\n\nerr = FSClose( nFRefNum );\nprinterr(\"macclose FSClose \",err,err, __LINE__,__FILE__,G.filename);\n\n\nreturn err;\n}\n\n\n\n\n\n/***********************/\n/* Function maclseek() */\n/***********************/\n\nlong maclseek(short nFRefNum, long lib, short nMode)\n{\n    ParamBlockRec   pbr;\n\n    if (nMode == SEEK_SET)\n        nMode = fsFromStart;\n    else if (nMode == SEEK_CUR)\n        nMode = fsFromMark;\n    else if (nMode == SEEK_END)\n        nMode = fsFromLEOF;\n    pbr.ioParam.ioRefNum = nFRefNum;\n    pbr.ioParam.ioPosMode = nMode;\n    pbr.ioParam.ioPosOffset = lib;\n    (void)PBSetFPosSync(&pbr);\n    return pbr.ioParam.ioPosOffset;\n}\n\n\n\nstatic void BuildMacFilename(void)\n{\nchar CompletePath[NAME_MAX];\nchar ArchiveDir[NAME_MAX];\nunsigned exdirlen = strlen(uO.exdir);\nshort CurrentFork;\nOSErr err;\n\nGetExtraFieldData(&MacZipMode, &newExtraField);\n\nif (MacZipMode >= JohnnyLee_EF)\n    {\n    if (IgnoreEF_Macfilename)\n        {\n        strcpy(ArchiveDir, &G.filename[exdirlen+1]);\n        G.filename[exdirlen+1] = '\\0';\n        RfDfFilen2Real(ArchiveDir, ArchiveDir, MacZipMode,\n                      (newExtraField.flags & EB_M3_FL_DATFRK), &CurrentFork);\n        strcat(G.filename, ArchiveDir);\n        }\n    else\n        {        /* use the filename of mac extra-field */\n        G.filename[exdirlen] = '\\0';  /* cut resource-path */\n        strcat(G.filename,newExtraField.FullPath);\n        }\n    }\n\nGetCompletePath(CompletePath, G.filename, &CurrentFile, &err);\nprinterr(\"GetCompletePath BuildMacFilename \", (err != -43) && (err != 0),\n             err, __LINE__, __FILE__, CompletePath);\n\nerr = GetVolFileSystemID(C2PStr(CompletePath), CurrentFile.vRefNum,\n                         &fileSystemID);\nprinterr(\"GetVolFileSystemID BuildMacFilename \", err, err, __LINE__, __FILE__,\n          CompletePath);\n\nif (MacZipMode == TomBrownZipIt1_EF)\n    {\n    memcpy(CurrentFile.name, newExtraField.filename, newExtraField.filename[0]+1);\n    CurrentFile.name[0] = CurrentFile.name[0] - 1;\n    }\n\n}\n\n\n\n\n/* The following functions are dealing with the extra-field handling, only. */\n\n/****************************/\n/* Function SetFinderInfo() */\n/****************************/\n\nstatic OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi)\n{\n    OSErr err;\n    CInfoPBRec      fpb;\n\n    fpb.hFileInfo.ioNamePtr   = (StringPtr) &(spec->name);\n    fpb.hFileInfo.ioVRefNum   = spec->vRefNum;\n    fpb.hFileInfo.ioDirID     = spec->parID;\n    fpb.hFileInfo.ioFDirIndex = 0;\n\n    err = PBGetCatInfoSync(&fpb);\n    printerr(\"PBGetCatInfo SetFinderInfo \", err, err,\n             __LINE__, __FILE__, G.filename);\n\n    if  ((MacZipMode == JohnnyLee_EF) || (MacZipMode == NewZipMode_EF))\n    {\n        /* skip restoring time stamps on user's request */\n        if (SetTime && !UseUT_ExtraField) {\n            fpb.hFileInfo.ioFlCrDat = mi->fpb.hFileInfo.ioFlCrDat;\n            fpb.hFileInfo.ioFlMdDat = mi->fpb.hFileInfo.ioFlMdDat;\n        }\n\n        fpb.hFileInfo.ioFlFndrInfo   = mi->fpb.hFileInfo.ioFlFndrInfo;\n    }\n\n    if (MacZipMode == NewZipMode_EF)\n    {\n        if (uO.E_flag) PrintMacExtraInfo(mi);\n        fpb.hFileInfo.ioFlXFndrInfo  = mi->fpb.hFileInfo.ioFlXFndrInfo;\n\n        fpb.hFileInfo.ioFVersNum  = mi->fpb.hFileInfo.ioFVersNum;\n        fpb.hFileInfo.ioACUser    = mi->fpb.hFileInfo.ioACUser;\n\n        /* skip restoring time stamps on user's request */\n        if (SetTime && !UseUT_ExtraField) {\n            fpb.hFileInfo.ioFlBkDat = mi->fpb.hFileInfo.ioFlBkDat;\n#ifdef USE_EF_UT_TIME\n            if (!(mi->flags & EB_M3_FL_NOUTC))\n                {\n#ifdef DEBUG_TIME\n            {\n            printf(\"\\nSetFinderInfo:  Mac modif: %lu local -> UTOffset: \"\\\n                   \"%d before AdjustForTZmoveMac\\n\",\n              fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);\n            }\n#endif /* DEBUG_TIME */\n                fpb.hFileInfo.ioFlCrDat =\n                  AdjustForTZmoveMac(fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);\n                fpb.hFileInfo.ioFlMdDat =\n                  AdjustForTZmoveMac(fpb.hFileInfo.ioFlMdDat, mi->Md_UTCoffs);\n                fpb.hFileInfo.ioFlBkDat =\n                  AdjustForTZmoveMac(fpb.hFileInfo.ioFlBkDat, mi->Bk_UTCoffs);\n#ifdef DEBUG_TIME\n            {\n            printf(\"SetFinderInfo:  Mac modif: %lu local -> UTOffset: \"\\\n                   \"%d after AdjustForTZmoveMac\\n\",\n              fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);\n            }\n#endif /* DEBUG_TIME */\n\n                }\n#endif /* USE_EF_UT_TIME */\n        }\n\n        if ((mi->FinderComment) &&\n           (fileSystemID == HFS_fileSystem)) {\n            C2PStr(mi->FinderComment);\n            err = FSpDTSetComment(spec, (unsigned char *) mi->FinderComment);\n            printerr(\"FSpDTSetComment:\",err , err,\n                     __LINE__, __FILE__, mi->FullPath);\n        }\n    }\n\n    /* Restore ioDirID field in pb which was changed by PBGetCatInfo */\n    fpb.hFileInfo.ioDirID = spec->parID;\n    err = PBSetCatInfoSync(&fpb);\n\n    return err;\n} /* SetFinderInfo() */\n\n\n\n\n/*\n** Scan the extra fields in extra_field, and look for a MacOS EF; return a\n** pointer to that EF, or NULL if it's not there.\n*/\nstatic uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,\n                             short *MacZipMode)\n{\n    while (ef_ptr != NULL && ef_len >= EB_HEADSIZE) {\n        unsigned eb_id  = makeword(EB_ID  + ef_ptr);\n        unsigned eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            Trace((stderr,\n              \"scanMacOSexfield: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        if (isMacOSexfield(eb_id, eb_len, MacZipMode)) {\n            return ef_ptr;\n        }\n\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return NULL;\n}\n\n\n\n\nstatic Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode)\n{\nsize = size;\n\n    switch (id)\n        {\n        case EF_ZIPIT:\n            {           /* we do not (yet) support ZipIt's format completely */\n            *MacZipMode = TomBrownZipIt1_EF;\n            IgnoreEF_Macfilename = true;\n            return true;\n            }\n\n        case EF_ZIPIT2:\n            {           /* we do not (yet) support ZipIt's format completely */\n            *MacZipMode = TomBrownZipIt2_EF;\n            IgnoreEF_Macfilename = true;\n            return true;\n            }\n\n        case EF_MAC3:\n            {           /* the new maczip format */\n            *MacZipMode = NewZipMode_EF;\n            IgnoreEF_Macfilename = false;\n            return true;\n            }\n\n        case EF_JLMAC:\n            {           /* Johnny Lee's old maczip format */\n            *MacZipMode = JohnnyLee_EF;\n            IgnoreEF_Macfilename = true;\n            return true;\n            }\n\n        default:\n            {           /* any other format */\n            *MacZipMode = UnKnown_EF;\n            IgnoreEF_Macfilename = true;\n            return false;\n            }\n        }\n\n    return false;\n}\n\n\n\n\n/*\n** Return a unsigned long from a four-byte sequence\n** in big endian format\n*/\n\nulg makePPClong(ZCONST uch *sig)\n{\n    return (((ulg)sig[0]) << 24)\n         + (((ulg)sig[1]) << 16)\n         + (((ulg)sig[2]) << 8)\n         +  ((ulg)sig[3]);\n}\n\n\n\n\n/*\n** Return a unsigned short from a two-byte sequence\n** in big endian format\n*/\n\nush makePPCword(ZCONST uch *b)\n{\n    return (ush)((b[0] << 8) | b[1]);\n}\n\n\n\n\n/*\n** Print mac extra-field\n**\n*/\n\nstatic void PrintMacExtraInfo(MACINFO *mi)\n{\n#define MY_FNDRINFO fpb.hFileInfo.ioFlFndrInfo\n    DateTimeRec  MacTime;\n    static ZCONST char space[] = \"                                    \";\n    static ZCONST char line[]  = \"------------------------------------\"\\\n                                 \"------------------------------\";\n\n    printf(\"\\n\\n%s\", line);\n\n    printf(\"\\nFullPath      = [%s]\", mi->FullPath);\n    printf(\"\\nFinderComment = [%s]\", mi->FinderComment);\n    printf(\"\\nText Encoding Base (Filename)       \\\"%s\\\" \\n\",\n        PrintTextEncoding(mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript));\n\n    printf(\"\\nExtraField Flags :                  %s  0x%x  %4d\",\n             sBit2Str(mi->flags), mi->flags, mi->flags);\n\n    printf(\"\\n%sExtra Field is %s\", space,\n           (mi->flags & EB_M3_FL_UNCMPR ?\n            \"Uncompressed\" : \"Compressed\"));\n    printf(\"\\n%sFile Dates are in %u Bit\", space,\n           (mi->flags & EB_M3_FL_TIME64 ? 64 : 32));\n    printf(\"\\n%sFile UTC time adjustments are %ssupported\", space,\n           (mi->flags & EB_M3_FL_NOUTC ? \"not \" : \"\"));\n    printf(\"\\n%sFile Name is %schanged\", space,\n           (mi->flags & EB_M3_FL_NOCHANGE ? \"not \" : \"\"));\n    printf(\"\\n%sFile is a %s\\n\", space,\n           (mi->flags & EB_M3_FL_DATFRK ?\n            \"Datafork\" : \"Resourcefork\"));\n\n    /* not all type / creator codes are printable */\n    if (isprint((char)(mi->MY_FNDRINFO.fdType >> 24)) &&\n        isprint((char)(mi->MY_FNDRINFO.fdType >> 16)) &&\n        isprint((char)(mi->MY_FNDRINFO.fdType >> 8)) &&\n        isprint((char)mi->MY_FNDRINFO.fdType))\n    {\n        printf(\"\\nFile Type =                         [%c%c%c%c]  0x%lx\",\n            (char)(mi->MY_FNDRINFO.fdType >> 24),\n            (char)(mi->MY_FNDRINFO.fdType >> 16),\n            (char)(mi->MY_FNDRINFO.fdType >> 8),\n            (char)(mi->MY_FNDRINFO.fdType),\n            mi->MY_FNDRINFO.fdType);\n    }\n    else\n    {\n        printf(\"\\nFile Type =                                     0x%lx\",\n            mi->MY_FNDRINFO.fdType);\n    }\n\n    if (isprint((char)(mi->MY_FNDRINFO.fdCreator >> 24)) &&\n        isprint((char)(mi->MY_FNDRINFO.fdCreator >> 16)) &&\n        isprint((char)(mi->MY_FNDRINFO.fdCreator >> 8)) &&\n        isprint((char)mi->MY_FNDRINFO.fdCreator))\n    {\n        printf(\"\\nFile Creator =                      [%c%c%c%c]  0x%lx\",\n            (char)(mi->MY_FNDRINFO.fdCreator >> 24),\n            (char)(mi->MY_FNDRINFO.fdCreator >> 16),\n            (char)(mi->MY_FNDRINFO.fdCreator >> 8),\n            (char)(mi->MY_FNDRINFO.fdCreator),\n            mi->MY_FNDRINFO.fdCreator);\n    }\n    else\n    {\n        printf(\"\\nFile Creator =                                  0x%lx\",\n            mi->MY_FNDRINFO.fdCreator);\n    }\n\n    printf(\"\\n\\nDates (local time of archiving location):\");\n    SecondsToDate(mi->fpb.hFileInfo.ioFlCrDat, &MacTime);\n    printf(\"\\n    Created  =                      %4d/%2d/%2d %2d:%2d:%2d  \",\n           MacTime.year, MacTime.month, MacTime.day,\n           MacTime.hour, MacTime.minute, MacTime.second);\n    SecondsToDate(mi->fpb.hFileInfo.ioFlMdDat, &MacTime);\n    printf(\"\\n    Modified =                      %4d/%2d/%2d %2d:%2d:%2d  \",\n           MacTime.year, MacTime.month, MacTime.day,\n           MacTime.hour, MacTime.minute, MacTime.second);\n    SecondsToDate(mi->fpb.hFileInfo.ioFlBkDat, &MacTime);\n    printf(\"\\n    Backup   =                      %4d/%2d/%2d %2d:%2d:%2d  \",\n        MacTime.year, MacTime.month, MacTime.day,\n        MacTime.hour, MacTime.minute, MacTime.second);\n\n    if (!(mi->flags & EB_M3_FL_NOUTC)) {\n        printf(\"\\nGMT Offset of Creation time  =      %4ld sec  %2d h\",\n          mi->Cr_UTCoffs, (int)mi->Cr_UTCoffs / (60 * 60));\n        printf(\"\\nGMT Offset of Modification time  =  %4ld sec  %2d h\",\n          mi->Md_UTCoffs, (int)mi->Md_UTCoffs / (60 * 60));\n        printf(\"\\nGMT Offset of Backup time  =        %4ld sec  %2d h\",\n          mi->Bk_UTCoffs, (int)mi->Bk_UTCoffs / (60 * 60));\n    }\n\n    printf(\"\\n\\nFinder Flags :                      %s  0x%x  %4d\",\n        sBit2Str(mi->MY_FNDRINFO.fdFlags),\n        mi->MY_FNDRINFO.fdFlags,\n        mi->MY_FNDRINFO.fdFlags);\n\n    printf(\"\\nFinder Icon Position =              X: %4d\",\n        mi->MY_FNDRINFO.fdLocation.h);\n\n    printf(\"\\n                                    Y: %4d\",\n        mi->MY_FNDRINFO.fdLocation.v);\n\n    printf(\"\\n\\nText Encoding Base (System/MacZip)  \\\"%s\\\"\",\n        PrintTextEncoding(mi->TextEncodingBase));\n\n    printf(\"\\n%s\\n\", line);\n#undef MY_FNDRINFO\n}\n\n\n\n\n/*\n** Decode mac extra-field and assign the data to the structure\n**\n*/\n\nstatic Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi)\n{\nuch *ptr;\nint  retval = PK_OK;\n\nptr = scanMacOSexfield(G.extra_field, G.lrec.extra_field_length, MacZipMode);\n\n/* MacOS is no preemptive OS therefore do some (small) event-handling */\nUserStop();\n\nif (uO.J_flag)\n    {\n    *MacZipMode = UnKnown_EF;\n    IgnoreEF_Macfilename = true;\n    return false;\n    }\n\nif (ptr != NULL)\n{   /*   Collect the data from the extra field buffer. */\n    mi->header    = makeword(ptr);    ptr += 2;\n    mi->data      = makeword(ptr);    ptr += 2;\n\n    switch (*MacZipMode)\n        {\n        case NewZipMode_EF:\n           {\n            mi->size      =  makelong(ptr); ptr += 4;\n            mi->flags     =  makeword(ptr); ptr += 2;\n                             /* Type/Creator are always uncompressed */\n            mi->fpb.hFileInfo.ioFlFndrInfo.fdType    = makePPClong(ptr);\n            ptr += 4;\n            mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(ptr);\n            ptr += 4;\n\n            if (!(mi->flags & EB_M3_FL_UNCMPR))\n                {\n\n                retval = memextract(__G__ attrbuff, mi->size, ptr,\n                                    mi->data - EB_MAC3_HLEN);\n\n                if (retval != PK_OK)  /* error uncompressing attributes */\n                    {\n                    Info(slide, 0x201, ((char *)slide,\n                         LoadFarString(ErrUncmpEF)));\n                    *MacZipMode = UnKnown_EF;\n                    return false;     /* EF-Block unusable, ignore it */\n                    }\n\n                }\n             else\n                {   /* file attributes are uncompressed */\n                attrbuff = ptr;\n                }\n\n            DecodeMac3ExtraField(attrbuff, mi);\n\n            return true;\n            break;\n            }\n\n        case JohnnyLee_EF:\n            {\n            if (strncmp((char *)ptr, \"JLEE\", 4) == 0)\n                {   /* Johnny Lee's old MacZip e.f. was found */\n                attrbuff  = ptr + 4;\n                DecodeJLEEextraField(attrbuff, mi);\n                return true;\n                }\n            else\n                {   /* second signature did not match, ignore EF block */\n                *MacZipMode = UnKnown_EF;\n                return false;\n                }\n            break;\n            }\n\n\n        case TomBrownZipIt1_EF:\n        case TomBrownZipIt2_EF:\n            {\n            if (strncmp((char *)ptr, \"ZPIT\", 4) == 0)\n                {   /* Johnny Lee's old MacZip e.f. was found */\n                attrbuff  = ptr + 4;\n                DecodeZPITextraField(attrbuff, mi);\n                return true;\n                }\n            else\n                {   /* second signature did not match, ignore EF block */\n                *MacZipMode = UnKnown_EF;\n                return false;\n                }\n            break;\n            }\n\n\n        default:\n            {  /* just to make sure */\n            *MacZipMode = UnKnown_EF;\n            IgnoreEF_Macfilename = true;\n            return false;\n            break;\n            }\n        }\n}  /* if (ptr != NULL)  */\n\n/* no Mac extra field was found */\nreturn false;\n}\n\n\n\n\n/*\n** Assign the new Mac3 Extra-Field to the structure\n**\n*/\n\nstatic void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi)\n{               /* extra-field info of the new MacZip implementation */\n                /* compresssed extra-field starts here (if compressed) */\n\nAssert_it(buff, \"\", \"\");\n\nmi->fpb.hFileInfo.ioFlFndrInfo.fdFlags        =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v   =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h   =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdFldr         =  makeword(buff); buff += 2;\n\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdIconID      =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[0] =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[1] =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[2] =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdScript      = *buff;           buff += 1;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdXFlags      = *buff;           buff += 1;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdComment     =  makeword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlXFndrInfo.fdPutAway     =  makelong(buff); buff += 4;\n\nmi->fpb.hFileInfo.ioFVersNum                  = *buff;           buff += 1;\nmi->fpb.hFileInfo.ioACUser                    = *buff;           buff += 1;\n\n/*\nThis implementation does not use the 64 bit time values, therefore\nuse the UT extra field instead\n*/\nif (mi->flags & EB_M3_FL_TIME64)\n    {\n    Info(slide, 0x201, ((char *)slide, LoadFarString(No64Time)));\n    UseUT_ExtraField = true;\n    buff += 24; /* jump over the date values */\n    }\nelse\n    {\n    UseUT_ExtraField = false;\n    mi->fpb.hFileInfo.ioFlCrDat   =  makelong(buff); buff += 4;\n    mi->fpb.hFileInfo.ioFlMdDat   =  makelong(buff); buff += 4;\n    mi->fpb.hFileInfo.ioFlBkDat   =  makelong(buff); buff += 4;\n    }\n\nif (!(mi->flags & EB_M3_FL_NOUTC))\n    {\n    mi->Cr_UTCoffs =  makelong(buff); buff += 4;\n    mi->Md_UTCoffs =  makelong(buff); buff += 4;\n    mi->Bk_UTCoffs =  makelong(buff); buff += 4;\n    }\n\n/* TextEncodingBase type & values */\n/* (values 0-32 correspond to the Script Codes defined in \"Inside Macintosh\",\n    Text pages 6-52 and 6-53) */\nmi->TextEncodingBase =  makeword(buff); buff += 2;\n\nif (mi->TextEncodingBase >= kTextEncodingUnicodeV1_1)\n    {\n    Info(slide, 0x201, ((char *)slide, LoadFarString(NoUniCode)));\n    IgnoreEF_Macfilename = true;\n    }\n\nmi->FullPath      = (char *)buff; buff += strlen(mi->FullPath) + 1;\nmi->FinderComment = (char *)buff; buff += strlen(mi->FinderComment) + 1;\n\nif (uO.i_flag) IgnoreEF_Macfilename = true;\n\n}\n\n\n\n\n/*\n** Assign the new JLEE Extra-Field to the structure\n**\n*/\n\nstatic void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi)\n{ /*  extra-field info of Johnny Lee's old MacZip  */\n\nAssert_it(buff, \"\", \"\");\n\nmi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff); buff += 4;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff); buff += 4;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdFlags      = makePPCword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v = makePPCword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h = makePPCword(buff); buff += 2;\nmi->fpb.hFileInfo.ioFlFndrInfo.fdFldr       = makePPCword(buff); buff += 2;\n\nmi->fpb.hFileInfo.ioFlCrDat                =  makePPClong(buff); buff += 4;\nmi->fpb.hFileInfo.ioFlMdDat                =  makePPClong(buff); buff += 4;\nmi->flags                                  =  makePPClong(buff); buff += 4;\n\nnewExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;\n}\n\n\n\n\n/*\n** Assign the new JLEE Extra-Field to the structure\n**\n*/\n\nstatic void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi)\n{ /*  extra-field info of Johnny Lee's old MacZip  */\nunsigned char filelen;\n\nAssert_it(buff, \"\", \"\");\n\n#ifdef SwitchZIPITefSupportOff\nMacZipMode = UnKnown_EF;\nInfo(slide, 0x221, ((char *)slide,LoadFarString(ZitIt_EF)));\nreturn;\n#endif\n\nif (MacZipMode == TomBrownZipIt1_EF)\n    {\n    filelen = *buff;\n    newExtraField.filename = buff;\n    buff += 1;\n    buff += filelen;\n    mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);\n    buff += 4;\n    mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);\n    buff += 4;\n    }\nelse   /*  if (MacZipMode == TomBrownZipIt2_EF)  */\n    {\n    mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);\n    buff += 4;\n    mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);\n    buff += 4;\n    }\n\nnewExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;\n}\n\n\n\n/*\n** Return char* to describe the text encoding\n**\n*/\n\nstatic char *PrintTextEncoding(short script)\n{\nchar *info;\nstatic char buffer[14];\n/* TextEncodingBase type & values */\n/* (values 0-32 correspond to the Script Codes defined in\n   Inside Macintosh: Text pages 6-52 and 6-53 */\n\nswitch (script) {               /* Mac OS encodings*/\n    case kTextEncodingMacRoman:         info = \"Roman\";             break;\n    case kTextEncodingMacJapanese:      info = \"Japanese\";          break;\n    case kTextEncodingMacChineseTrad:   info = \"ChineseTrad\";       break;\n    case kTextEncodingMacKorean:        info = \"Korean\";            break;\n    case kTextEncodingMacArabic:        info = \"Arabic\";            break;\n    case kTextEncodingMacHebrew:        info = \"Hebrew\";            break;\n    case kTextEncodingMacGreek:         info = \"Greek\";             break;\n    case kTextEncodingMacCyrillic:      info = \"Cyrillic\";          break;\n    case kTextEncodingMacDevanagari:    info = \"Devanagari\";        break;\n    case kTextEncodingMacGurmukhi:      info = \"Gurmukhi\";          break;\n    case kTextEncodingMacGujarati:      info = \"Gujarati\";          break;\n    case kTextEncodingMacOriya:         info = \"Oriya\";             break;\n    case kTextEncodingMacBengali:       info = \"Bengali\";           break;\n    case kTextEncodingMacTamil:         info = \"Tamil\";             break;\n    case kTextEncodingMacTelugu:        info = \"Telugu\";            break;\n    case kTextEncodingMacKannada:       info = \"Kannada\";           break;\n    case kTextEncodingMacMalayalam:     info = \"Malayalam\";         break;\n    case kTextEncodingMacSinhalese:     info = \"Sinhalese\";         break;\n    case kTextEncodingMacBurmese:       info = \"Burmese\";           break;\n    case kTextEncodingMacKhmer:         info = \"Khmer\";             break;\n    case kTextEncodingMacThai:          info = \"Thai\";              break;\n    case kTextEncodingMacLaotian:       info = \"Laotian\";           break;\n    case kTextEncodingMacGeorgian:      info = \"Georgian\";          break;\n    case kTextEncodingMacArmenian:      info = \"Armenian\";          break;\n    case kTextEncodingMacChineseSimp:   info = \"ChineseSimp\";       break;\n    case kTextEncodingMacTibetan:       info = \"Tibetan\";           break;\n    case kTextEncodingMacMongolian:     info = \"Mongolian\";         break;\n    case kTextEncodingMacEthiopic:      info = \"Ethiopic\";          break;\n    case kTextEncodingMacCentralEurRoman: info = \"CentralEurRoman\"; break;\n    case kTextEncodingMacVietnamese:    info = \"Vietnamese\";        break;\n    case kTextEncodingMacExtArabic:     info = \"ExtArabic\";         break;\n\n    case kTextEncodingUnicodeV1_1:      info = \"Unicode V 1.1\";     break;\n    case kTextEncodingUnicodeV2_0:      info = \"Unicode V 2.0\";     break;\n\n    default:  {\n        sprintf(buffer,\"Code: 0x%x\",(short) script);\n        info = buffer;\n        break;\n        }\n    }\n\nreturn info;\n}\n\n\n\n/*\n** Init Globals\n**\n*/\n\nvoid   MacGlobalsInit(__GPRO)\n{\nnewExtraField.FullPath      = NULL;\nnewExtraField.FinderComment = NULL;\n\nOpenZipFile = true;\n\nMacZipMode = UnKnown_EF;\nIgnoreEF_Macfilename = true;\n\nif (malloced_attrbuff == NULL)\n    {\n    /* make room for extra-field */\n    attrbuff = (uch *)malloc(EB_MAX_OF_VARDATA);\n\n    if (attrbuff == NULL)\n        {             /* No memory to uncompress attributes */\n        Info(slide, 0x201, ((char *)slide, LoadFarString(OutOfMemEF)));\n        exit(PK_MEM);\n        }\n    else\n        {\n        malloced_attrbuff = attrbuff;\n        }\n    }\nelse\n    {\n    attrbuff = malloced_attrbuff;\n    }\n\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macscreen.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macscreen.c\n  This file is only linked into the standalone version (not SIOUX) of unzip.\n  Macintosh-GUI routines.\n\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <QuickDraw.h>\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define bufferSize      4096\n\n#define screenWindow    128\n\n#define pauseOption     0x0001\n#define scrollOption    0x0002\n\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\nstatic Rect scrollRect, pauseRect;\nstatic WindowPtr theWindow;\nstatic RgnHandle scrollRgn;\n\nstatic short fontHeight, fontWidth, screenHeight, screenWidth;\nstatic short currentPosition, maxPosition, pausePosition;\n\nstatic short *screenLength, startLine, endLine;\nstatic char *screenImage, **screenLine;\n\nstatic int screenOptions;\n\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nvoid screenOpen(char *);\nvoid screenControl(char *, int);\nvoid screenClose(void);\nvoid screenUpdate(WindowPtr);\nvoid screenDisplay(char *);\nvoid screenDump(char *, long);\n\nchar *macfgets(char *, int, FILE *);\nint  macfprintf(FILE *, char *, ...);\nint  macprintf(char *, ...);\nint  macgetch(void);\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\nvoid screenOpen(char *Title) {\n    FontInfo fontInfo;\n    int n;\n    short       fontFamID;\n\n    theWindow = GetNewWindow(screenWindow, nil, (WindowPtr)(-1));\n\n    if ((Title != NULL) && (*Title != '\\0')) {\n        c2pstr(Title);\n        SetWTitle(theWindow, (StringPtr)Title);\n        p2cstr((StringPtr)Title);\n    }\n\n    ShowWindow(theWindow);\n\n    SetPort(theWindow);\n    GetFNum( \"\\pMonaco\", &fontFamID );\n    TextFont(fontFamID);\n    TextSize(9);\n\n    GetFontInfo(&fontInfo);\n    fontHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;\n    fontWidth = fontInfo.widMax;\n\n    scrollRgn = NewRgn();\n\n    screenWidth = (theWindow->portRect.right - theWindow->portRect.left - 10) /\n        fontWidth;\n    screenHeight = (theWindow->portRect.bottom - theWindow->portRect.top) /\n        fontHeight;\n    maxPosition = screenHeight * fontHeight;\n    pausePosition = maxPosition - (currentPosition = fontHeight);\n\n    SetRect(&scrollRect, theWindow->portRect.left,\n            theWindow->portRect.top + fontInfo.descent,\n            theWindow->portRect.right,\n            theWindow->portRect.bottom);\n    SetRect(&pauseRect, theWindow->portRect.left,\n            pausePosition + fontInfo.descent,\n            theWindow->portRect.right,\n            theWindow->portRect.bottom);\n\n    MoveTo(5, currentPosition);\n\n    n = (sizeof(char *) + sizeof(short) + screenWidth) * screenHeight;\n\n    screenLine = (char **)NewPtr(n);\n\n    screenLength = (short *)&screenLine[screenHeight];\n    screenImage = (char *)&screenLength[screenHeight];\n\n    for (n = 0; n < screenHeight; n++) {\n        screenLine[n] = &screenImage[n * screenWidth];\n        screenLength[n] = 0;\n    }\n\n    startLine = endLine = 0;\n\n    screenOptions = 0;\n\n    return;\n}\n\n\n\n\nvoid screenControl(char *options, int setting) {\n    int n = 0;\n\n    while (*options) {\n        switch (*options) {\n        case 'p':\n            n |= pauseOption;\n            break;\n        case 's':\n            n |= scrollOption;\n            break;\n        default:\n            break;\n        }\n        options += 1;\n    }\n\n    if (setting == 0)\n        screenOptions &= (n ^ (-1));\n    else\n        screenOptions |= n;\n\n    if ((pausePosition = maxPosition - currentPosition) == 0)\n        pausePosition = maxPosition - fontHeight;\n\n    return;\n}\n\n\n\n\nvoid screenClose(void) {\n    DisposePtr((Ptr)screenLine);\n\n    DisposeWindow(theWindow);\n\n    return;\n}\n\n\n\n\nvoid screenUpdate(WindowPtr window) {\n    GrafPort *savePort;\n    int m, n;\n\n    if (window == theWindow) {\n        BeginUpdate(window);\n        if (!EmptyRgn(window->visRgn)) {\n            GetPort(&savePort);\n            SetPort(window);\n            n = startLine;\n            for (m = 1; ; m++) {\n                MoveTo(5, m * fontHeight);\n                if (screenLength[n] != 0)\n                    DrawText(screenLine[n], 0, screenLength[n]);\n                if (n == endLine) break;\n                if ((n += 1) == screenHeight) n = 0;\n            }\n            SetPort(savePort);\n        }\n        EndUpdate(window);\n    }\n\n    return;\n}\n\n\n\n\nstatic void screenNewline(void) {\n    MoveTo(5, currentPosition += fontHeight);\n    if (currentPosition > maxPosition) {\n        if (screenOptions & scrollOption) {\n            ScrollRect(&scrollRect, 0, -fontHeight, scrollRgn);\n            MoveTo(5, currentPosition = maxPosition);\n            if ((startLine += 1) == screenHeight) startLine = 0;\n        } else {\n            ScrollRect(&scrollRect, 0, -maxPosition + fontHeight, scrollRgn);\n            MoveTo(5, currentPosition = fontHeight + fontHeight);\n            startLine = endLine;\n        }\n    }\n    pausePosition -= fontHeight;\n\n    if ((endLine += 1) == screenHeight) endLine = 0;\n    screenLength[endLine] = 0;\n\n    return;\n}\n\n\n\n\nstatic char waitChar(void) {\n    WindowPtr whichWindow;\n    EventRecord theEvent;\n\n    for ( ; ; ) {\n        SystemTask();\n        if (GetNextEvent(everyEvent, &theEvent)) {\n            switch (theEvent.what) {\n            case keyDown:\n                if ((theEvent.modifiers & cmdKey) &&\n                    ((theEvent.message & charCodeMask) == '.'))\n                    ExitToShell();\n                return(theEvent.message & charCodeMask);\n            case mouseDown:\n                if (FindWindow(theEvent.where, &whichWindow) == inSysWindow)\n                    SystemClick(&theEvent, whichWindow);\n                break;\n            case updateEvt:\n                screenUpdate((WindowPtr)theEvent.message);\n                break;\n            }\n        }\n    }\n}\n\n\n\n\nstatic void screenPause(void) {\n    if (pausePosition == 0) {\n        if (screenOptions & pauseOption) {\n            DrawText(\"Press any key to continue ...\", 0, 29);\n            memcpy(screenLine[endLine], \"Press any key to continue ...\", 29);\n            screenLength[endLine] = 29;\n\n            (void)waitChar();\n\n            EraseRect(&pauseRect);\n            MoveTo(5, currentPosition);\n            screenLength[endLine] = 0;\n        }\n\n        pausePosition = maxPosition - fontHeight;\n    }\n\n    return;\n}\n\n\n\n\nvoid screenDisplay(char *s) {\n    GrafPort *savePort;\n    int m, n;\n    char *t;\n\n    GetPort(&savePort);\n    SetPort(theWindow);\n\n    while (*s) {\n        screenPause();\n\n        for (t = s; (*s) && (*s != '\\n') && (*s != '\\r'); s++)\n            ;  /* empty body */\n\n        if ((n = s - t) > (m = screenWidth - screenLength[endLine])) n = m;\n\n        if (n > 0) {\n            DrawText(t, 0, n);\n            memcpy(screenLine[endLine] + screenLength[endLine], t, n);\n            screenLength[endLine] += n;\n        }\n\n        if ((*s == '\\n') || (*s == '\\r')) {\n            screenNewline();\n            s += 1;\n        }\n    }\n\n    SetPort(savePort);\n\n    return;\n}\n\n\n\n\nvoid screenDump(char *s, long n) {\n    GrafPort *savePort;\n    int k, m;\n    char *t;\n\n    GetPort(&savePort);\n    SetPort(theWindow);\n\n    while (n) {\n        screenPause();\n\n        for (t = s; (n) && (*s != '\\n') && (*s != '\\r'); s++, n--)\n            ;  /* empty body */\n\n        if ((k = s - t) > (m = screenWidth - screenLength[endLine])) k = m;\n\n        if (k > 0) {\n            DrawText(t, 0, k);\n            memcpy(screenLine[endLine] + screenLength[endLine], t, k);\n            screenLength[endLine] += k;\n        }\n\n        if ((*s == '\\n') || (*s == '\\r')) {\n            screenNewline();\n            s += 1;\n            n -= 1;\n        }\n    }\n\n    SetPort(savePort);\n\n    return;\n}\n\n\n\n\nchar *macfgets(char *s, int n, FILE *stream) {\n    GrafPort *savePort;\n    char c, *t = s;\n\n    stream = stream;\n\n    GetPort(&savePort);\n    SetPort(theWindow);\n\n    for (n -= 1; (n > 0) && ((c = waitChar()) != '\\r'); n -= 1) {\n        DrawChar(*t++ = c);\n        if (screenLength[endLine] < screenWidth)\n            screenLine[endLine][screenLength[endLine]++] = c;\n    }\n\n    if (c == '\\r') screenNewline();\n\n    *t = '\\0';\n\n    SetPort(savePort);\n\n    return(s);\n}\n\n\n\n\nint macfprintf(FILE *stream, char *format, ...)\n{\n    char buffer[bufferSize];\n    va_list ap;\n    int rc;\n\n    stream = stream;\n\n    va_start(ap, format);\n    rc = vsprintf(buffer, format, ap);\n    va_end(ap);\n\n    screenDisplay(buffer);\n\n    return rc;\n}\n\n\n\n\nint macprintf(char *format, ...)\n{\n    char buffer[bufferSize];\n    va_list ap;\n    int rc;\n\n    va_start(ap, format);\n    rc = vsprintf(buffer, format, ap);\n    va_end(ap);\n\n    screenDisplay(buffer);\n\n    return rc;\n}\n\n\n\n/***********************/\n/* Function macgetch() */\n/***********************/\n\nint macgetch(void)\n{\n    WindowPtr whichWindow;\n    EventRecord theEvent;\n    char c;                     /* one-byte buffer for read() to use */\n\n    do {\n        SystemTask();\n        if (!GetNextEvent(everyEvent, &theEvent))\n            theEvent.what = nullEvent;\n        else {\n            switch (theEvent.what) {\n            case keyDown:\n                c = theEvent.message & charCodeMask;\n                break;\n            case mouseDown:\n                if (FindWindow(theEvent.where, &whichWindow) ==\n                    inSysWindow)\n                    SystemClick(&theEvent, whichWindow);\n                break;\n            case updateEvt:\n                screenUpdate((WindowPtr)theEvent.message);\n                break;\n            }\n        }\n    } while (theEvent.what != keyDown);\n\n    macprintf(\"*\");\n\n    return (int)c;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macstat.c",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macstat.c\n\n *  This file provides a unix like file-stat routine\n *  for V7 Unix systems that don't have such procedures.\n *\n *\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdio.h>\n#include <sound.h>\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include \"macstat.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n#include \"macstuff.h\"\n#include \"mactime.h\"\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nextern int errno;\nextern MACINFO newExtraField;  /* contains all extra-field data */\nextern short MacZipMode;\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\nint UZmacstat(const char *path, struct stat *buf)\n{\n    Boolean isDirectory;\n    long dirID;\n    char fullpath[NAME_MAX], UnmangledPath[NAME_MAX];\n    CInfoPBRec fpb;\n    HVolumeParam vpb;\n    FSSpec fileSpec;\n    OSErr err, err2;\n    short CurrentFork;\n\n    AssertStr(path,path)\n    Assert_it(buf,\"\",\"\")\n\n    memset(buf, 0, sizeof(struct stat));        /* zero out all fields */\n\n    RfDfFilen2Real(UnmangledPath, path, MacZipMode,\n                   (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork);\n    GetCompletePath(fullpath, path, &fileSpec, &err);\n    err2 = PrintUserHFSerr((err != -43) && (err != 0) && (err != -120),\n                           err, path);\n    printerr(\"GetCompletePath:\", err2, err2, __LINE__, __FILE__, path);\n\n    if (err != noErr) {\n        errno = err;\n        return -1;\n    }\n\n    /*\n     * Fill the fpb & vpb struct up with info about file or directory.\n     */\n\n    FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);\n    vpb.ioVRefNum = fpb.hFileInfo.ioVRefNum = fileSpec.vRefNum;\n    vpb.ioNamePtr = fpb.hFileInfo.ioNamePtr = fileSpec.name;\n    if (isDirectory) {\n        fpb.hFileInfo.ioDirID = fileSpec.parID;\n    } else {\n        fpb.hFileInfo.ioDirID = dirID;\n    }\n\n    fpb.hFileInfo.ioFDirIndex = 0;\n    err = PBGetCatInfo(&fpb, false);\n    if (err == noErr) {\n        vpb.ioVolIndex = 0;\n        err = PBHGetVInfoSync((HParmBlkPtr)&vpb);\n        if (err == noErr && buf != NULL) {\n            /*\n             * Files are always readable by everyone.\n             */\n            buf->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;\n\n            /*\n             * Use the Volume Info & File Info to fill out stat buf.\n             */\n            if (fpb.hFileInfo.ioFlAttrib & 0x10) {\n                buf->st_mode |= S_IFDIR;\n                buf->st_nlink = 2;\n            } else {\n                buf->st_nlink = 1;\n                if (fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) {\n                    buf->st_mode |= S_IFLNK;\n                } else {\n                    buf->st_mode |= S_IFREG;\n                }\n            }\n            if ((fpb.hFileInfo.ioFlAttrib & 0x10) ||\n                (fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')) {\n                /*\n                 * Directories and applications are executable by everyone.\n                 */\n\n                buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;\n            }\n            if ((fpb.hFileInfo.ioFlAttrib & 0x01) == 0) {\n                /*\n                 * If not locked, then everyone has write acces.\n                 */\n\n                buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;\n            }\n            buf->st_ino = fpb.hFileInfo.ioDirID;\n            buf->st_dev = fpb.hFileInfo.ioVRefNum;\n            buf->st_uid = -1;\n            buf->st_gid = -1;\n            buf->st_rdev = 0;\n\n            if (CurrentFork == ResourceFork)\n                buf->st_size = fpb.hFileInfo.ioFlRLgLen;\n            else\n                buf->st_size = fpb.hFileInfo.ioFlLgLen;\n\n            buf->st_blksize = vpb.ioVAlBlkSiz;\n            buf->st_blocks = (buf->st_size + buf->st_blksize - 1)\n                            / buf->st_blksize;\n\n            /*\n             * The times returned by the Mac file system are in the\n             * local time zone.  We convert them to GMT so that the\n             * epoch starts from GMT.  This is also consistent with\n             * what is returned from \"clock seconds\".\n             */\n\n            buf->st_mtime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlMdDat);\n            buf->st_ctime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlCrDat);\n            buf->st_atime = buf->st_ctime;         /* best guess */\n\n#ifdef DEBUG_TIME\n            {\n            struct tm *tp = localtime(&buf->st_mtime);\n            printf(\n              \"\\nUZmacstat: local buf->st_mtime is %ld = %d/%2d/%2d  %2d:%2d:%2d\",\n              buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday,\n              tp->tm_hour, tp->tm_min, tp->tm_sec);\n            tp = gmtime(&buf->st_mtime);\n            printf(\n              \"\\nUZmacstat: UTC   buf->st_mtime is %ld = %d/%2d/%2d  %2d:%2d:%2d\\n\",\n              buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday,\n              tp->tm_hour, tp->tm_min, tp->tm_sec);\n            }\n#endif /* DEBUG_TIME */\n        }\n    }\n\n    if (err != noErr) {\n        errno = err;\n    }\n\n    return (err == noErr ? 0 : -1);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macstat.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*****************************************************************\n *\n *                stat.h\n *\n *****************************************************************/\n\n#ifndef __macstat_h\n#define __macstat_h\n\n#include <time.h>\ntypedef long dev_t;\ntypedef long ino_t;\ntypedef long off_t;\n\n#define _STAT\n\nstruct stat {\n    dev_t    st_dev;\n    ino_t    st_ino;\n    unsigned short    st_mode;\n    short    st_nlink;\n    short    st_uid;\n    short    st_gid;\n    dev_t    st_rdev;\n    off_t    st_size;\n    time_t   st_atime, st_mtime, st_ctime;\n    long     st_blksize;\n    long     st_blocks;\n};\n\n#define S_IFMT     0xF000\n#define S_IFIFO    0x1000\n#define S_IFCHR    0x2000\n#define S_IFDIR    0x4000\n#define S_IFBLK    0x6000\n#define S_IFREG    0x8000\n#define S_IFLNK    0xA000\n#define S_IFSOCK   0xC000\n#define S_ISUID    0x800\n#define S_ISGID    0x400\n#define S_ISVTX    0x200\n#define S_IREAD    0x100\n#define S_IWRITE   0x80\n#define S_IEXEC    0x40\n\n#define S_IRUSR     00400\n#define S_IWUSR     00200\n#define S_IXUSR     00100\n#define S_IRWXU     (S_IRUSR | S_IWUSR | S_IXUSR)  /* = 00700 */\n\n#define S_IRGRP     00040\n#define S_IWGRP     00020\n#define S_IXGRP     00010\n#define S_IRWXG     (S_IRGRP | S_IWGRP | S_IXGRP)  /* = 00070 */\n\n#define S_IROTH     00004\n#define S_IWOTH     00002\n#define S_IXOTH     00001\n#define S_IRWXO     (S_IROTH | S_IWOTH | S_IXOTH)  /* = 00007 */\n\n\nextern int UZmacstat(const char *path, struct stat *buf);\n\n#endif /* !__macstat_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macstuff.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _MACSTUFF_H\n#define _MACSTUFF_H     1\n\n#include \"MoreFilesExtras.h\"\n#include \"MoreDesktopMgr.h\"\n#include \"MoreFiles.h\"\n#include \"FSpCompat.h\"\n#include \"FullPath.h\"\n\n#endif               /*  _MACSTUFF_H  */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/mactime.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* -----------------------------------------------------------------------------\n\nThe original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,\nmktime and time do not work correctly. The supplied link library mactime.c\ncontains replacement functions for them.\n\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n\n------------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n#include <OSUtils.h>\n\n#include \"mactime.h\"\n\n\n/*\nThe MacOS function GetDateTime returns  the\nnumber of seconds elapsed since midnight, January 1, 1904.\n*/\nconst unsigned long MacOS_2_Unix = 2082844800L;\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n\n#ifndef TEST_TIME_LIB\n#define my_gmtime    gmtime\n#define my_localtime localtime\n#define my_mktime    mktime\n#define my_time      time\n#endif\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n/* internal prototypes */\nstatic void clear_tm(struct tm * tm);\nstatic long GMTDelta(void);\nstatic Boolean DaylightSaving(void);\nstatic time_t GetTimeMac(void);\nstatic time_t Mactime(time_t *timer);\nstatic void   normalize(int *i,int *j,int norm);\nstatic struct tm *time2tm(const time_t *timer);\nstatic time_t tm2time(struct tm *tp);\n\n/* Because serial port and SLIP conflict with ReadXPram calls,\n   we cache the call here so we don't hang on calling ReadLocation()  */\nstatic void myReadLocation(MachineLocation * loc);\n\n\n/* prototypes for STD lib replacement functions */\nstruct tm *my_gmtime(const time_t *t);\nstruct tm *my_localtime(const time_t *t);\ntime_t my_mktime(struct tm *tp);\ntime_t my_time(time_t *t);\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n /*\n *  Mac file times are based on 1904 Jan 1 00:00 local time,\n *  not 1970 Jan 1 00:00 UTC.\n *  So we have to convert the time stamps into UNIX UTC\n *  compatible values.\n */\ntime_t MacFtime2UnixFtime(unsigned long macftime)\n{\n    long UTCoffset;\n\n    GetGMToffsetMac(macftime, &UTCoffset);\n    MACOS_TO_UNIX(macftime);\n    macftime -= UTCoffset;\n\n    return macftime;\n}\n\n\n /*\n *  Mac file times are based on 1904 Jan 1 00:00 local time,\n *  not 1970 Jan 1 00:00 UTC.\n *  So we have to convert the time stamps into MacOS local\n *  compatible values.\n */\nunsigned long UnixFtime2MacFtime(time_t unxftime)\n{\n    long UTCoffset;\n    unsigned long macftime = unxftime;\n\n    UNIX_TO_MACOS(macftime);\n    GetGMToffsetMac(macftime, &UTCoffset);\n    macftime += UTCoffset;\n\n    return macftime;\n}\n\n\n\n\n\n/*\n* This function convert a file-localtime to an another\n* file-localtime.\n*/\ntime_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)\n{\n    time_t MacGMTTime;\n    long UTCoffset;\n\n    /* convert macloctim into corresponding UTC value */\n    MacGMTTime = macloctim - s_gmtoffs;\n    GetGMToffsetMac(macloctim, &UTCoffset);\n\n    return (MacGMTTime + UTCoffset);\n} /* AdjustForTZmove() */\n\n\n\n\n/*\n * This function calculates the difference between the supplied Mac\n * ftime value (local time) and the corresponding UTC time in seconds.\n */\nBoolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)\n{\n\nmactime = mactime;\n/*\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n May be later I can include a support of GMT offset calculation for the\n time in question here.\n*/\n    *UTCoffset = GMTDelta();\n\n    return true;\n}\n\n\n\n\n\n\n\n/*****************************************************************************\n *  Standard Library Replacement Functions\n *  gmtime(), mktime(), localtime(), time()\n *\n *  The unix epoch is used here.\n *  These functions gmtime(), mktime(), localtime() and time()\n *  expects and returns unix times.\n *\n * At midnight Jan. 1, 1970 GMT, the local time was\n *    midnight Jan. 1, 1970 + GMTDelta().\n *\n *\n *****************************************************************************/\n\n\nstruct tm *my_gmtime(const time_t *timer)\n{\n    return time2tm(timer);\n}\n\n\n\n\nstruct tm *my_localtime(const time_t *timer)\n{\n    time_t maclocal;\n\n    maclocal = *timer;\n    maclocal += GMTDelta();\n\n    return time2tm(&maclocal);\n}\n\n\n\n\ntime_t my_mktime(struct tm *tp)\n{\n    time_t maclocal;\n\n    maclocal = tm2time(tp);\n    maclocal -= GMTDelta();\n\n    return maclocal;\n}\n\n\n\n\n\n\ntime_t my_time(time_t *time)\n{\ntime_t tmp_time;\n\nGetDateTime(&tmp_time);\n\nMACOS_TO_UNIX(tmp_time);\n\nif (time)\n    {\n    *time = tmp_time;\n    }\n\nreturn tmp_time;\n}\n\n\n\n/*****************************************************************************/\n/*  static module level functions\n/*****************************************************************************/\n\n\n/*\n * The geographic location and time zone information of a Mac\n * are stored in extended parameter RAM.  The ReadLocation\n * produdure uses the geographic location record, MachineLocation,\n * to read the geographic location and time zone information in\n * extended parameter RAM.\n *\n * Because serial port and SLIP conflict with ReadXPram calls,\n * we cache the call here.\n *\n * Caveat: this caching will give the wrong result if a session\n * extend across the DST changeover time, but\n * this function resets itself every 2 hours.\n */\nstatic void myReadLocation(MachineLocation * loc)\n{\n    static MachineLocation storedLoc;   /* InsideMac, OSUtilities, page 4-20  */\n    static time_t first_call = 0, last_call = 86400;\n\n    if ((last_call - first_call) > 7200)\n        {\n        GetDateTime(&first_call);\n        ReadLocation(&storedLoc);\n        }\n\n    GetDateTime(&last_call);\n    *loc = storedLoc;\n}\n\n\n\n\nstatic Boolean DaylightSaving(void)\n{\n    MachineLocation loc;\n    unsigned char dlsDelta;\n\n    myReadLocation(&loc);\n    dlsDelta =  loc.u.dlsDelta;\n\n    return (dlsDelta != 0);\n}\n\n\n\n\n/* current local time = GMTDelta() + GMT\n   GMT = local time - GMTDelta()    */\nstatic long GMTDelta(void)\n{\n    MachineLocation loc;\n    long gmtDelta;\n\n    myReadLocation(&loc);\n\n    /*\n     * On a Mac, the GMT value is in seconds east of GMT.  For example,\n     * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)\n     * east of GMT.  The gmtDelta field is a 3-byte value contained in a\n     * long word, so you must take care to get it properly.\n     */\n    gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;\n    if ((gmtDelta & 0x00800000) != 0)\n        {\n        gmtDelta |= 0xFF000000;\n        }\n\n    return gmtDelta;\n}\n\n\n\n/* This routine simulates stdclib time(), time in seconds since 1.1.1970\n   The time is in GMT  */\nstatic time_t GetTimeMac(void)\n{\n    unsigned long maclocal;\n\n\n    /*\n     * Get the current time expressed as the number of seconds\n     * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).\n     * On a Mac, current time accuracy is up to a second.\n     */\n\n    GetDateTime(&maclocal);     /* Get Mac local time  */\n    maclocal -= GMTDelta();     /* Get Mac GMT  */\n    MACOS_TO_UNIX(maclocal);\n\n    return maclocal;            /* return unix GMT  */\n}\n\n\n\n\n/*\n *  clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00\n */\n\nstatic void clear_tm(struct tm * tm)\n{\n    tm->tm_sec   =  0;\n    tm->tm_min   =  0;\n    tm->tm_hour  =  0;\n    tm->tm_mday  =  1;\n    tm->tm_mon   =  0;\n    tm->tm_year  =  0;\n    tm->tm_wday  =  1;\n    tm->tm_yday  =  0;\n    tm->tm_isdst = -1;\n}\n\n\nstatic void normalize(int *i,int *j,int norm)\n{\n  while(*i < 0)\n    {\n    *i += norm;\n    (*j)--;\n    }\n\n  while(*i >= norm)\n    {\n    *i -= norm;\n    (*j)++;\n    }\n}\n\n\n\n/*  Returns the GMT times  */\nstatic time_t Mactime(time_t *timer)\n{\n    time_t t = GetTimeMac();\n\n    if (timer != NULL)\n        *timer = t;\n\n    return t;\n}\n\n\n\n\nstatic struct tm *time2tm(const time_t *timer)\n{\n    DateTimeRec dtr;\n    MachineLocation loc;\n    time_t macLocal = *timer;\n\n    static struct tm statictime;\n    static const short monthday[12] =\n        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};\n\n    UNIX_TO_MACOS(macLocal);\n    SecondsToDate(macLocal, &dtr);\n\n    statictime.tm_sec  = dtr.second;         /* second, from 0 to 59 */\n    statictime.tm_min  = dtr.minute;         /* minute, from 0 to 59 */\n    statictime.tm_hour = dtr.hour;           /* hour, from 0 to 23 */\n    statictime.tm_mday = dtr.day;            /* day of the month, from 1 to 31 */\n    statictime.tm_mon  = dtr.month     - 1;  /* month, 1= January and 12 = December */\n    statictime.tm_year = dtr.year   - 1900;  /* year, ranging from 1904 to 2040 */\n    statictime.tm_wday = dtr.dayOfWeek - 1;  /* day of the week, 1 = Sun, 7 = Sat */\n\n    statictime.tm_yday = monthday[statictime.tm_mon]\n                         + statictime.tm_mday - 1;\n\n    if (2 < statictime.tm_mon && !(statictime.tm_year & 3))\n        {\n        ++statictime.tm_yday;\n        }\n\n    myReadLocation(&loc);\n    statictime.tm_isdst = DaylightSaving();\n\n    return(&statictime);\n}\n\n\n\n\n\nstatic time_t tm2time(struct tm *tp)\n{\ntime_t intMacTime;\nDateTimeRec  dtr;\n\n normalize(&tp->tm_sec, &tp->tm_min, 60);\n normalize(&tp->tm_min, &tp->tm_hour,60);\n normalize(&tp->tm_hour,&tp->tm_mday,24);\n normalize(&tp->tm_mon, &tp->tm_year,12);\n\n dtr.year    = tp->tm_year + 1900;  /* years since 1900 */\n dtr.month   = tp->tm_mon  +    1;  /* month, 0 = January and 11 = December */\n dtr.day     = tp->tm_mday;         /* day of the month, from 1 to 31 */\n dtr.hour    = tp->tm_hour;         /* hour, from 0 to 23 */\n dtr.minute  = tp->tm_min;          /* minute, from 0 to 59 */\n dtr.second  = tp->tm_sec;          /* second, from 0 to 59 */\n\n DateToSeconds(&dtr, &intMacTime);\n\n MACOS_TO_UNIX(intMacTime);\n\n return intMacTime;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/mactime.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _MACTIME_H_\n#define _MACTIME_H_\n/* -----------------------------------------------------------------------------\n\nThe original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,\nmktime and time do not work correctly. The supplied link library mactime.c\ncontains replacement functions for them.\n\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n\n------------------------------------------------------------------------------*/\n\n#include <time.h>\n#include <mactypes.h>\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n\n  /*\n   * ARGH.  Mac times are based on 1904 Jan 1 00:00, not 1970 Jan 1 00:00.\n   *  So we have to diddle time_t's appropriately:  add or subtract 66 years'\n   *  worth of seconds == number of days times 86400 == (66*365 regular days +\n   *  17 leap days ) * 86400 == (24090 + 17) * 86400 == 2082844800L seconds.\n   *  We hope time_t is an unsigned long (ulg) on the Macintosh...\n   */\n/*\nThis Offset is only used by MacFileDate_to_UTime()\n*/\n\n#define MACOS_TO_UNIX(x)  (x) -= (unsigned long)MacOS_2_Unix\n#define UNIX_TO_MACOS(x)  (x) += (unsigned long)MacOS_2_Unix\n\n/*\nThe MacOS function GetDateTime returns  the\nnumber of seconds elapsed since midnight, January 1, 1904.\n*/\nextern const unsigned long MacOS_2_Unix;\n\n\n/* prototypes for public utility functions */\ntime_t MacFtime2UnixFtime(unsigned long macftime);\nunsigned long UnixFtime2MacFtime(time_t unxftime);\ntime_t  AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs);\nBoolean GetGMToffsetMac(unsigned long macftime, long *UTCoffset);\n\n\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/macunzip.c",
    "content": "/*\n  Copyright (c) 1990-2006 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macunzip.c\n\n  Main-function for use with the standalone Unzip App.\n\n  ---------------------------------------------------------------------------*/\n\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"unzvers.h\"\n#include \"pathname.h\"\n#include \"helpers.h\"\n\n#include <Traps.h>\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define aboutAlert      128\n\n#define selectDialog    129\n#define okItem          1\n#define cancelItem      2\n#define editItem        3\n#define staticItem      4\n\n#define unzipMenuBar    128\n\n#define appleMenu       128\n#define aboutItem       1\n\n#define fileMenu        129\n#define extractItem     1\n#define infoItem        2\n#define listItem        3\n#define testItem        4\n#define commentItem     6\n#define freshenItem     8\n#define updateItem      9\n#define quitItem        11\n\n#define editMenu        130\n#define cutItem         1\n#define copyItem        2\n#define pasteItem       3\n\n#define modifierMenu    131\n#define excludeItem     1\n#define selectItem      2\n#define quietItem       9\n#define verboseItem     10\n\n#define screenMenu      132\n#define pauseItem       1\n#define scrollItem      2\n\n#define extractMenu     133\n#define screenItem      3\n#define junkItem        5\n\n#define caseMenu        134\n#define insensitiveItem 1\n#define lowercaseItem   2\n\n#define convertMenu     135\n#define autoItem        1\n#define binaryItem      2\n#define textItem        3\n\n#define overwriteMenu   136\n#define alwaysItem      1\n#define neverItem       2\n#define promptItem      3\n\n#define infoMenu        137\n#define prtCommentItem  2\n#define prtHeaderItem   3\n#define prtTotalsItem   4\n\n#define formatMenu      138\n#define filenameItem    1\n#define longItem        2\n#define mediumItem      3\n#define shortItem       4\n\n#define allFlags        0x000FFFFF\n\n#define quietFlag       0x00000001\n#define verboseFlag     0x00000002\n\n#define pauseFlag       0x00080000\n#define scrollFlag      0x00040000\n\n#define screenFlag      0x00000004\n#define junkFlag        0x00000008\n\n#define insensitiveFlag 0x00000010\n#define lowercaseFlag   0x00000020\n\n#define autoFlag        0x00000040\n#define textFlag        0x00000080\n\n#define neverFlag       0x00000100\n#define overwriteFlag   0x00000200\n\n#define prtCommentFlag  0x00000400\n#define prtHeaderFlag   0x00000800\n#define prtTotalsFlag   0x00001000\n\n#define filenameFlag    0x00002000\n#define longFlag        0x00004000\n#define mediumFlag      0x00008000\n#define shortFlag       0x00010000\n\n#define extractMask     0x000003FD\n#define infoMask        0x0001FE02\n#define listMask        0x00000001\n#define testMask        0x00000001\n#define commentMask     0x00000000\n#define freshenMask     0x000003FD\n#define updateMask      0x000003FD\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nchar UnzipVersion[32], ZipinfoVersion[32];\n\nlong modifiers, modifierMask;\n\nEventRecord myevent;\nMenuHandle appleHandle, modifierHandle, screenHandle, extractHandle;\nMenuHandle caseHandle, convertHandle, overwriteHandle, infoHandle;\nMenuHandle formatHandle;\nHandle menubar, itemHandle;\nshort itemType;\nRect itemRect;\n\nchar command;\nextern char fileList[256];\n\nBoolean stop;\n\nSysEnvRec sysRec;\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nstatic void domousedown(EventRecord *myevent);\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\nstatic Boolean TrapAvailable(machineType, trapNumber, trapType)\nshort machineType;\nshort trapNumber;\nTrapType trapType;\n{\n    if (machineType < 0)\n        return (false);\n\n    if ((trapType == ToolTrap) &&\n        (machineType > envMachUnknown) &&\n        (machineType < envMacII)) {\n        if ((trapNumber &= 0x03FF) > 0x01FF)\n            trapNumber = _Unimplemented;\n    }\n    return (NGetTrapAddress(trapNumber, trapType) !=\n#ifdef __MWERKS__\n        NGetTrapAddress(_Unimplemented, trapType));\n#else\n        GetTrapAddress(_Unimplemented));\n#endif\n}\n\n\n\n/*\n** excute menu-command\n**\n*/\n\nstatic void domenu(menucommand) long menucommand;\n{\n    short themenu, theitem;\n    DialogPtr thedialog;\n    Str255 name;\n    long check;\n\n    themenu = HiWord(menucommand);\n    theitem = LoWord(menucommand);\n\n    switch (themenu) {\n\n    case appleMenu:\n        if (theitem == aboutItem) {\n            ParamText((StringPtr)UnzipVersion, (StringPtr)ZipinfoVersion, nil, nil);\n            Alert(aboutAlert, nil);\n        } else {\n            GetMenuItemText(appleHandle, theitem, name);\n            theitem = OpenDeskAcc(name);\n        }\n        break;\n\n    case fileMenu:\n        switch (theitem) {\n        case extractItem:\n            if (modifiers & screenFlag)\n                command = 'c';\n            else\n                command = 'x';\n            modifierMask = extractMask;\n            break;\n        case infoItem:\n            command = 'Z';\n            modifierMask = infoMask;\n            break;\n        case listItem:\n            if (modifiers & verboseFlag)\n                command = 'v';\n            else\n                command = 'l';\n            modifierMask = listMask;\n            break;\n        case testItem:\n            command = 't';\n            modifierMask = testMask;\n            break;\n        case commentItem:\n            command = 'z';\n            modifierMask = commentMask;\n            break;\n        case freshenItem:\n            command = 'f';\n            modifierMask = freshenMask;\n            break;\n        case updateItem:\n            command = 'u';\n            modifierMask = updateMask;\n            break;\n        case quitItem:\n            stop = true;\n            break;\n        default:\n            break;\n        }\n        break;\n\n    case editMenu:\n        break;\n\n    case modifierMenu:\n        switch (theitem) {\n        case excludeItem:\n            check = -1;\n            break;\n        case selectItem:\n            thedialog = GetNewDialog(selectDialog, nil, (WindowPtr)(-1));\n            SetPort(thedialog);\n            do\n                ModalDialog(nil, &theitem);\n            while ((theitem != okItem) && (theitem != cancelItem));\n            if (theitem == okItem) {\n                GetDialogItem(thedialog, editItem, &itemType, &itemHandle,\n                              &itemRect);\n                GetDialogItemText(itemHandle, (StringPtr)&fileList);\n                p2cstr((StringPtr)fileList);\n            }\n            DisposeDialog(thedialog);\n            check = -1;\n            break;\n        case quietItem:\n            check = (modifiers ^= quietFlag) & quietFlag;\n            break;\n        case verboseItem:\n            check = (modifiers ^= verboseFlag) & verboseFlag;\n            break;\n        default:\n            break;\n        }\n        if (check == 0)\n            CheckItem(modifierHandle, theitem, false);\n        else if (check > 0)\n            CheckItem(modifierHandle, theitem, true);\n        break;\n\n    case screenMenu:\n        switch (theitem) {\n        case pauseItem:\n            check = (modifiers ^= pauseFlag) & pauseFlag;\n            screenControl(\"p\", check);\n            break;\n        case scrollItem:\n            check = (modifiers ^= scrollFlag) & scrollFlag;\n            screenControl(\"s\", check);\n            break;\n        default:\n            break;\n        }\n        if (check == 0)\n            CheckItem(screenHandle, theitem, false);\n        else if (check > 0)\n            CheckItem(screenHandle, theitem, true);\n        break;\n\n    case extractMenu:\n        switch (theitem) {\n        case screenItem:\n            check = (modifiers ^= screenFlag) & screenFlag;\n            break;\n        case junkItem:\n            check = (modifiers ^= junkFlag) & junkFlag;\n            break;\n        default:\n            break;\n        }\n        if (check == 0)\n            CheckItem(extractHandle, theitem, false);\n        else if (check > 0)\n            CheckItem(extractHandle, theitem, true);\n        break;\n\n    case caseMenu:\n        switch (theitem) {\n        case insensitiveItem:\n            check = (modifiers ^= insensitiveFlag) & insensitiveFlag;\n            break;\n        case lowercaseItem:\n            check = (modifiers ^= lowercaseFlag) & lowercaseFlag;\n            break;\n        default:\n            break;\n        }\n        if (check == 0)\n            CheckItem(caseHandle, theitem, false);\n        else if (check > 0)\n            CheckItem(caseHandle, theitem, true);\n        break;\n\n    case convertMenu:\n        switch (theitem) {\n        case autoItem:\n            CheckItem(convertHandle, autoItem, true);\n            CheckItem(convertHandle, binaryItem, false);\n            CheckItem(convertHandle, textItem, false);\n            modifiers &= (allFlags ^ textFlag);\n            modifiers |= autoFlag;\n            break;\n        case binaryItem:\n            CheckItem(convertHandle, autoItem, false);\n            CheckItem(convertHandle, binaryItem, true);\n            CheckItem(convertHandle, textItem, false);\n            modifiers &= (allFlags ^ (autoFlag | textFlag));\n            break;\n        case textItem:\n            CheckItem(convertHandle, autoItem, false);\n            CheckItem(convertHandle, binaryItem, false);\n            CheckItem(convertHandle, textItem, true);\n            modifiers &= (allFlags ^ autoFlag);\n            modifiers |= textFlag;\n            break;\n        default:\n            break;\n        }\n        break;\n\n    case overwriteMenu:\n        switch (theitem) {\n        case alwaysItem:\n            CheckItem(overwriteHandle, alwaysItem, true);\n            CheckItem(overwriteHandle, neverItem, false);\n            CheckItem(overwriteHandle, promptItem, false);\n            modifiers &= (allFlags ^ neverFlag);\n            modifiers |= overwriteFlag;\n            break;\n        case neverItem:\n            CheckItem(overwriteHandle, alwaysItem, false);\n            CheckItem(overwriteHandle, neverItem, true);\n            CheckItem(overwriteHandle, promptItem, false);\n            modifiers &= (allFlags ^ overwriteFlag);\n            modifiers |= neverFlag;\n            break;\n        case promptItem:\n            CheckItem(overwriteHandle, alwaysItem, false);\n            CheckItem(overwriteHandle, neverItem, false);\n            CheckItem(overwriteHandle, promptItem, true);\n            modifiers &= (allFlags ^ (neverFlag | overwriteFlag));\n            break;\n        default:\n            break;\n        }\n        break;\n\n    case infoMenu:\n        switch (theitem) {\n        case prtCommentItem:\n            check = (modifiers ^= prtCommentFlag) & prtCommentFlag;\n            break;\n        case prtHeaderItem:\n            check = (modifiers ^= prtHeaderFlag) & prtHeaderFlag;\n            break;\n        case prtTotalsItem:\n            check = (modifiers ^= prtTotalsFlag) & prtTotalsFlag;\n            break;\n        default:\n            break;\n        }\n        if (check == 0)\n            CheckItem(infoHandle, theitem, false);\n        else if (check > 0)\n            CheckItem(infoHandle, theitem, true);\n        break;\n\n    case formatMenu:\n        switch (theitem) {\n        case filenameItem:\n            CheckItem(formatHandle, filenameItem, true);\n            CheckItem(formatHandle, longItem, false);\n            CheckItem(formatHandle, mediumItem, false);\n            CheckItem(formatHandle, shortItem, false);\n            modifiers &= (allFlags ^ (longFlag | mediumFlag | shortFlag));\n            modifiers |= filenameFlag;\n            break;\n        case longItem:\n            CheckItem(formatHandle, filenameItem, false);\n            CheckItem(formatHandle, longItem, true);\n            CheckItem(formatHandle, mediumItem, false);\n            CheckItem(formatHandle, shortItem, false);\n            modifiers &= (allFlags ^ (filenameFlag | mediumFlag | shortFlag));\n            modifiers |= longFlag;\n            break;\n        case mediumItem:\n            CheckItem(formatHandle, filenameItem, false);\n            CheckItem(formatHandle, longItem, false);\n            CheckItem(formatHandle, mediumItem, true);\n            CheckItem(formatHandle, shortItem, false);\n            modifiers &= (allFlags ^ (filenameFlag | longFlag | shortFlag));\n            modifiers |= mediumFlag;\n            break;\n        case shortItem:\n            CheckItem(formatHandle, filenameItem, false);\n            CheckItem(formatHandle, longItem, false);\n            CheckItem(formatHandle, mediumItem, false);\n            CheckItem(formatHandle, shortItem, true);\n            modifiers &= (allFlags ^ (filenameFlag | longFlag | mediumFlag));\n            modifiers |= shortFlag;\n            break;\n        default:\n            break;\n        }\n        break;\n\n    default:\n        break;\n\n    }\n\n    HiliteMenu(0);\n    return;\n}\n\n\n\n/*\n** work with shortcuts\n**\n*/\n\nstatic void dokey(myevent) EventRecord *myevent;\n{\n    char code;\n\n    code = (char)(myevent->message & charCodeMask);\n\n    if (myevent->modifiers & cmdKey) {\n        if (myevent->what != autoKey) {\n            domenu(MenuKey(code));\n        }\n    }\n\n    return;\n}\n\n\n\n/*\n** work with mouse-events\n**\n*/\n\nstatic void domousedown(EventRecord *myevent)\n{\n    WindowPtr whichwindow;\n    long code;\n\n    code = FindWindow(myevent->where, &whichwindow);\n\n    switch (code) {\n\n    case inSysWindow:\n        SystemClick(myevent, whichwindow);\n        break;\n\n    case inMenuBar:\n        domenu(MenuSelect(myevent->where));\n        break;\n\n    }\n\n    return;\n}\n\n\n\n/*\n** Do a little event-handling and let the user stop\n** th current action\n*/\n\nvoid UserStop(void)\n{\n    EventRecord theEvent;\n\n    if ( WaitNextEvent( everyEvent, &theEvent, 0, nil )) {\n\n        switch (theEvent.what) {\n\n        case mouseDown:\n            domousedown( &theEvent );\n            break;\n\n        case autoKey:\n        case keyDown:\n            if ((theEvent.modifiers & cmdKey) &&\n                ((theEvent.message & charCodeMask) == '.'))\n            {\n                printf(\"\\n\\n <- User Canceled -> \\n\");\n                exit(1);  /* setjmp() must be already called  */\n            }\n            return;\n\n        } /*   switch (theEvent.what)   */\n    }  /*   if ( WaitNextEvent(...  */\n}\n\n\n\n/*\n** The Standalone Unzip starts here\n**\n*/\n\nint main(argc, argv) int argc; char *argv[];\n{\n    Uz_Globs saveGlobals;\n    Boolean haveEvent, useWNE;\n    short markChar;\n    char *ArchivePath, *ExtractPath;\n    OSErr err;\n\n    FlushEvents(everyEvent, 0);\n    InitGraf(&qd.thePort);\n    InitFonts();\n    InitWindows();\n    InitMenus();\n    TEInit();\n    InitDialogs(nil);\n    InitCursor();\n\n    CONSTRUCTGLOBALS();\n\n    sprintf(UnzipVersion, \"%d.%d%d%s of %s\", UZ_MAJORVER, UZ_MINORVER,\n        UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE);\n    sprintf(ZipinfoVersion, \"%d.%d%d%s of %s\", ZI_MAJORVER, ZI_MINORVER,\n        UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE);\n\n    c2pstr(UnzipVersion);\n    c2pstr(ZipinfoVersion);\n\n    SysEnvirons(1, &sysRec);\n    useWNE = TrapAvailable(sysRec.machineType, _WaitNextEvent, ToolTrap);\n\n    SetMenuBar(menubar = GetNewMBar(unzipMenuBar));\n    DisposeHandle(menubar);\n    InsertMenu(GetMenu(screenMenu), -1);\n    InsertMenu(GetMenu(extractMenu), -1);\n    InsertMenu(GetMenu(caseMenu), -1);\n    InsertMenu(GetMenu(convertMenu), -1);\n    InsertMenu(GetMenu(overwriteMenu), -1);\n    InsertMenu(GetMenu(infoMenu), -1);\n    InsertMenu(GetMenu(formatMenu), -1);\n    AppendResMenu(appleHandle = GetMenuHandle(appleMenu), 'DRVR');\n    modifierHandle = GetMenuHandle(modifierMenu);\n    screenHandle = GetMenuHandle(screenMenu);\n    extractHandle = GetMenuHandle(extractMenu);\n    caseHandle = GetMenuHandle(caseMenu);\n    convertHandle = GetMenuHandle(convertMenu);\n    overwriteHandle = GetMenuHandle(overwriteMenu);\n    infoHandle = GetMenuHandle(infoMenu);\n    formatHandle = GetMenuHandle(formatMenu);\n    DrawMenuBar();\n\n    screenOpen(\"Unzip\");\n\n    modifiers = 0;\n\n    GetItemMark(modifierHandle, quietItem, &markChar);\n    if (markChar) modifiers ^= quietFlag;\n    GetItemMark(modifierHandle, verboseItem, &markChar);\n    if (markChar) modifiers ^= verboseFlag;\n\n    GetItemMark(screenHandle, pauseItem, &markChar);\n    if (markChar) modifiers ^= pauseFlag;\n    screenControl(\"p\", markChar);\n    GetItemMark(screenHandle, scrollItem, &markChar);\n    if (markChar) modifiers ^= scrollFlag;\n    screenControl(\"s\", markChar);\n\n    GetItemMark(extractHandle, screenItem, &markChar);\n    if (markChar) modifiers ^= screenFlag;\n    GetItemMark(extractHandle, junkItem, &markChar);\n    if (markChar) modifiers ^= junkFlag;\n\n    GetItemMark(caseHandle, insensitiveItem, &markChar);\n    if (markChar) modifiers ^= insensitiveFlag;\n    GetItemMark(caseHandle, lowercaseItem, &markChar);\n    if (markChar) modifiers ^= lowercaseFlag;\n\n    GetItemMark(convertHandle, autoItem, &markChar);\n    if (markChar) modifiers ^= autoFlag;\n    GetItemMark(convertHandle, textItem, &markChar);\n    if (markChar) modifiers ^= textFlag;\n\n    if ((modifiers & (autoFlag | textFlag)) == (autoFlag | textFlag)) {\n        CheckItem(convertHandle, textItem, false);\n        modifiers &= (allFlags ^ textFlag);\n    } else if (modifiers & (autoFlag | textFlag))\n        CheckItem(convertHandle, binaryItem, false);\n    else\n        CheckItem(convertHandle, binaryItem, true);\n\n    GetItemMark(overwriteHandle, alwaysItem, &markChar);\n    if (markChar) modifiers ^= overwriteFlag;\n    GetItemMark(overwriteHandle, neverItem, &markChar);\n    if (markChar) modifiers ^= neverFlag;\n\n    if ((modifiers & (neverFlag | overwriteFlag)) == (neverFlag | overwriteFlag)) {\n        CheckItem(overwriteHandle, alwaysItem, false);\n        CheckItem(overwriteHandle, neverItem, false);\n        CheckItem(overwriteHandle, promptItem, true);\n        modifiers &= (allFlags ^ (neverFlag | overwriteFlag));\n    } else if (modifiers & (neverFlag | overwriteFlag))\n        CheckItem(overwriteHandle, promptItem, false);\n    else\n        CheckItem(overwriteHandle, promptItem, true);\n\n    GetItemMark(infoHandle, prtCommentItem, &markChar);\n    if (markChar) modifiers ^= prtCommentFlag;\n    GetItemMark(infoHandle, prtHeaderItem, &markChar);\n    if (markChar) modifiers ^= prtHeaderFlag;\n    GetItemMark(infoHandle, prtTotalsItem, &markChar);\n    if (markChar) modifiers ^= prtTotalsFlag;\n\n    GetItemMark(formatHandle, filenameItem, &markChar);\n    if (markChar) modifiers ^= filenameFlag;\n    GetItemMark(formatHandle, longItem, &markChar);\n    if (markChar) modifiers ^= longFlag;\n    GetItemMark(formatHandle, mediumItem, &markChar);\n    if (markChar) modifiers ^= mediumFlag;\n    GetItemMark(formatHandle, shortItem, &markChar);\n    if (markChar) modifiers ^= shortFlag;\n\n    if (modifiers & longFlag) {\n        CheckItem(formatHandle, filenameItem, false);\n        CheckItem(formatHandle, mediumItem, false);\n        CheckItem(formatHandle, shortItem, false);\n        modifiers &= (allFlags ^ (filenameFlag | mediumFlag | shortFlag));\n    } else if (modifiers & mediumFlag) {\n        CheckItem(formatHandle, filenameItem, false);\n        CheckItem(formatHandle, shortItem, false);\n        modifiers &= (allFlags ^ (filenameFlag | shortFlag));\n    } else if (modifiers & shortFlag) {\n        CheckItem(formatHandle, filenameItem, false);\n        modifiers &= (allFlags ^ filenameFlag);\n    }\n\n    command = ' ';\n\n    stop = false;\n    while (!stop) {\n        SetCursor(&qd.arrow);\n\n        if (useWNE) {\n            haveEvent = WaitNextEvent(everyEvent, &myevent, LONG_MAX, NULL);\n        } else {\n            SystemTask();\n            haveEvent = GetNextEvent(everyEvent, &myevent);\n        }\n\n        if (haveEvent) {\n            switch (myevent.what) {\n\n            case activateEvt:\n                break;\n\n            case keyDown:\n            case autoKey:\n                dokey(&myevent);\n                break;\n\n            case mouseDown:\n                domousedown(&myevent);\n                break;\n\n            case updateEvt:\n                screenUpdate((WindowPtr)myevent.message);\n                break;\n\n            case mouseUp:\n            case keyUp:\n                break;\n\n            default:\n                break;\n\n            }\n        }\n\n        if (command != ' ') {\n            char *s, **v, modifierString[32];\n            Point p;\n            int m, n;\n            SFTypeList          myTypes = {'TEXT', 'ZIP '};\n            StandardFileReply   myReply;\n\n            SetPt(&p, 40, 40);\n\n            StandardGetFile(nil, 2, myTypes, &myReply);\n\n            ArchivePath = StrCalloc(512);\n            ExtractPath = StrCalloc(512);\n\n            GetFullPathFromSpec(ArchivePath, &myReply.sfFile, &err);\n\n            strcpy(ExtractPath,ArchivePath);\n            FindNewExtractFolder(ExtractPath, false);\n\n            if (myReply.sfGood && (CheckMountedVolumes(ArchivePath) == 1)) {\n                modifierMask &= modifiers;\n\n                s = modifierString;\n\n                *s++ = '-';\n                if ((command != 'x') && (command != 'Z')) *s++ = command;\n\n                if (modifierMask) {\n                    if (modifierMask & (autoFlag | textFlag)) *s++ = 'a';\n                    if (modifierMask & textFlag) *s++ = 'a';\n                    if (modifierMask & insensitiveFlag) *s++ = 'C';\n                    if (modifierMask & junkFlag) *s++ = 'j';\n                    if (modifierMask & lowercaseFlag) *s++ = 'L';\n                    if (modifierMask & neverFlag) *s++ = 'n';\n                    if (modifierMask & overwriteFlag) *s++ = 'o';\n                    if (modifierMask & quietFlag) *s++ = 'q';\n                    if (modifierMask & verboseFlag) *s++ = 'v';\n\n                    if (modifierMask & prtCommentFlag) *s++ = 'z';\n                    if (modifierMask & prtHeaderFlag) *s++ = 'h';\n                    if (modifierMask & prtTotalsFlag) *s++ = 't';\n                    if (modifierMask & filenameFlag) *s++ = '2';\n                    if (modifierMask & longFlag) *s++ = 'l';\n                    if (modifierMask & mediumFlag) *s++ = 'm';\n                    if (modifierMask & shortFlag) *s++ = 's';\n                }\n\n                if (*(s - 1) == '-') s -= 1;\n\n                *s++ = 'd';\n                *s = '\\0';\n\n                v = (char **)malloc(sizeof(char *));\n                *v = \"unzip\";\n                argc = 1;\n\n                envargs(&argc, &v, NULL, NULL);\n\n                argv = (char **)malloc((argc + 3) * sizeof(char *));\n\n                argv[m = 0] = (command == 'Z') ? \"zipinfo\" : \"unzip\";\n                if (*modifierString) argv[++m] = modifierString;\n                argv[++m] = ExtractPath;\n                argv[++m] = ArchivePath;\n                for (n = 1; n < argc; n++) argv[n + m] = v[n];\n                argv[argc += m] = NULL;\n\n                free(v);\n\n                for (n = 0; argv[n] != NULL; n++) printf(\"%s \", argv[n]);\n                printf(\"...\\n\\n\");\n\n                memcpy(&saveGlobals, &G, sizeof(Uz_Globs));\n\n                unzip(__G__ argc, argv);\n\n                memcpy(&G, &saveGlobals, sizeof(Uz_Globs));\n\n                ArchivePath = StrFree(ArchivePath);\n                ExtractPath = StrFree(ExtractPath);\n\n                printf(\"\\nDone\\n\");\n            }\n\n            fileList[0] = '\\0';\n            command = ' ';\n        }\n    }\n\n    screenClose();\n\n    DESTROYGLOBALS();\n\n    ExitToShell();\n\nreturn 0;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/pathname.c",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  pathname.c\n\n  Function dealing with the pathname. Mostly C-string work.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <sound.h>\n\n#include \"pathname.h\"\n#include \"helpers.h\"\n#include \"macstuff.h\"\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nconst char  ResourceMark[] = \"XtraStuf.mac:\";  /* see also macos.c */\n\n\n#include \"zip.h\"\n\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpFindFolder --\n *\n *  This function is a version of the FindFolder function that\n *  returns the result as a FSSpec rather than a vRefNum and dirID.\n *\n * Results:\n *  Results will be simaler to that of the FindFolder function.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nOSErr\nFSpFindFolder(\n    short vRefNum,      /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec)       /* Pointer to resulting directory. */\n{\n    short foundVRefNum;\n    long foundDirID;\n    OSErr err;\n\n    err = FindFolder(vRefNum, folderType, createFolder,\n        &foundVRefNum, &foundDirID);\n    if (err != noErr) {\n    return err;\n    }\n\n    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, \"\\p\", spec);\n    return err;\n}\n\n\n/*\n**  return volumename from pathname\n**\n*/\n\nunsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)\n{\nconst char *VolEnd, *tmpPtr1;\nchar *tmpPtr2 = VolumeName;\n\nAssertStr(FullPath,\"GetVolumeFromPath\")\n\nfor (VolEnd = FullPath; *VolEnd != '\\0' && *VolEnd != ':'; VolEnd++)\n      ;\nif (*VolEnd == '\\0') return 0;\n\nfor (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)\n    {\n    *tmpPtr2++ = *tmpPtr1++;\n    }\n\n*tmpPtr2 = '\\0';\n\nreturn (unsigned short) strlen(VolumeName);\n}\n\n\n\n/***********************************/\n/* Function FindNewExtractFolder() */\n/***********************************/\n\nchar *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder)\n{\nchar buffer[NAME_MAX], *tmpPtr, *namePtr;\nchar *last_dotpos         = ExtractPath;\nshort count = 0, folderCount = 0;\nOSErr err;\nFSSpec Spec;\nlong theDirID;\nBoolean isDirectory;\nunsigned short namelen, pathlen = strlen(ExtractPath);\nunsigned long ext_length  = 0;\nunsigned long num_to_cut  = 0;\nlong firstpart_length = pathlen;\n\nAssertStr(ExtractPath,\"FindNewExtractFolder ExtractPath == NULL\")\n\nfor (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        {\n        folderCount++;\n        namePtr = tmpPtr;\n        }\n\nif (folderCount > 1) {\n    namelen = strlen(namePtr);\n} else {\n    namelen = strlen(ExtractPath);\n}\n\nif (uniqueFolder) {\n    for (count = 0; count < 99; count++)\n        {\n        memset(buffer,0,sizeof(buffer));\n\n        if (namelen >= 28)\n            ExtractPath[pathlen-2] = 0x0;\n        else\n            ExtractPath[pathlen-1] = 0x0;\n\n        sprintf(buffer,\"%s%d\",ExtractPath,count);\n        GetCompletePath(ExtractPath, buffer, &Spec,&err);\n        err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);\n        if (err == -43) break;\n        }\n} else {\n    /* Look for the last extension pos */\n    for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)\n        if (*tmpPtr == '.') last_dotpos = tmpPtr;\n\n    ext_length = strlen(last_dotpos);\n\n    if (ext_length < 6) {  /* up to 5 chars are treated as a */\n                           /* normal extension like \".html\" or \".class\"  */\n        int nameLength = last_dotpos - ExtractPath;\n        if (nameLength > 1) {\n            ExtractPath[nameLength] = 0x0;\n        } else {\n            ExtractPath[pathlen-1] = 0x0;\n        }\n    } else {\n        ExtractPath[pathlen-1] = 0x0;\n    }\n\n    GetCompletePath(ExtractPath, ExtractPath, &Spec,&err);\n}\n\n/* Foldernames must always end with a colon  */\nsstrcat(ExtractPath,\":\");\nreturn ExtractPath;\n}\n\n\n\n/*\n**  creates an archive file name\n**\n*/\n\nvoid createArchiveName(char *thePath)\n{\nchar *tmpPtr, *namePtr;\nshort folderCount = 0;\nunsigned short namelen, pathlen = strlen(thePath);\n\nif (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;\n\nfor (tmpPtr = thePath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        {\n        folderCount++;\n        namePtr = tmpPtr;\n        }\n\nnamelen = strlen(namePtr);\n\n    /* we have to eliminate illegal chars:\n     * The name space for Mac filenames and Zip filenames (unix style names)\n     * do both include all printable extended-ASCII characters.  The only\n     * difference we have to take care of is the single special character\n     * used as path delimiter:\n     * ':' on MacOS and '/' on Unix and '\\\\' on Dos.\n     * So, to convert between Mac filenames and Unix filenames without any\n     * loss of information, we simply interchange ':' and '/'.  Additionally,\n     * we try to convert the coding of the extended-ASCII characters into\n     * InfoZip's standard ISO 8859-1 codepage table.\n     */\n  MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);\n\n /* Avoid filenames like: \"Archive..zip\"  */\nif (thePath[pathlen-1] == '.')\n    {\n    thePath[pathlen-1] = 0;\n    }\n\nif (folderCount >= 1)\n    { /* path contains at least one folder */\n\n    if (namelen >= 28)\n        {\n        pathlen = pathlen-4;\n        }\n\n    thePath[pathlen]   = '.';\n    thePath[pathlen+1] = 'z';\n    thePath[pathlen+2] = 'i';\n    thePath[pathlen+3] = 'p';\n    thePath[pathlen+4] = 0x0;\n    return;\n    }\nelse\n    {  /* path contains no folder */\n    FindDesktopFolder(thePath);\n    createArchiveName(thePath);\n    }\n}\n\n\n\n/*\n** finds the desktop-folder on a volume with\n** largest amount of free-space.\n*/\n\nvoid FindDesktopFolder(char *Path)\n{\nchar buffer[255];\nFSSpec  volumes[50];        /* 50 Volumes should be enough */\nshort   actVolCount, volIndex = 1, VolCount = 0;\nOSErr   err;\nshort     i, foundVRefNum;\nFSSpec spec;\nUInt64 freeBytes;\nUInt64 totalBytes;\nUInt64 MaxFreeBytes;\n\nerr = OnLine(volumes, 50, &actVolCount, &volIndex);\nprinterr(\"OnLine:\", (err != -35) && (err != 0), err, __LINE__, __FILE__, \"\");\n\nMaxFreeBytes = 0;\n\nfor (i=0; i < actVolCount; i++)\n    {\n    XGetVInfo(volumes[i].vRefNum,\n              volumes[i].name,\n              &volumes[i].vRefNum,\n              &freeBytes,\n              &totalBytes);\n\n    if (MaxFreeBytes < freeBytes) {\n        MaxFreeBytes = freeBytes;\n        foundVRefNum = volumes[i].vRefNum;\n    }\n\n    if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) {\n        MaxFreeBytes = freeBytes;\n        foundVRefNum = volumes[i].vRefNum;\n    }\n\n}\n\n FSpFindFolder(foundVRefNum, kDesktopFolderType,\n            kDontCreateFolder,&spec);\n\n GetFullPathFromSpec(buffer, &spec , &err);\n sstrcat(buffer,Path);\n sstrcpy(Path,buffer);\n}\n\n\n/*\n**  return the path without the filename\n**\n*/\n\nchar *TruncFilename(char *DirPath, const char *FilePath)\n{\nchar *tmpPtr;\nchar *dirPtr = NULL;\n\nAssertStr(DirPath,\"TruncFilename\")\nAssert_it(Spec,\"TruncFilename\",\"\")\n\nsstrcpy(DirPath, FilePath);\n\nfor (tmpPtr = DirPath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        dirPtr = tmpPtr;\n\nif (dirPtr)\n    *++dirPtr = '\\0';\nelse\n    printerr(\"TruncFilename: FilePath has no Folders\", -1,\n         -1, __LINE__, __FILE__, FilePath);\n\nreturn DirPath;\n}\n\n\n\n/*\n**  return only filename\n**\n*/\n\nchar *GetFilename(char *FileName, const char *FilePath)\n{\nconst char *tmpPtr;\nconst char *dirPtr = NULL;\n\nAssert_it(FileName,\"GetFilename\",\"\")\nAssert_it(FilePath,\"GetFilename\",\"\")\n\nfor (tmpPtr = FilePath; *tmpPtr; tmpPtr++)\n    {\n    if (*tmpPtr == ':')\n        {\n        dirPtr = tmpPtr;\n        }\n    }\n\nif (dirPtr)\n    {\n    ++dirPtr;  /* jump over the ':' */\n    }\nelse\n    {\n    return strcpy(FileName, FilePath); /* FilePath has no Folders */\n    }\n\nreturn strcpy(FileName, dirPtr);\n}\n\n\n\n/*\n**  return fullpathname from folder/dir-id\n**\n*/\n\nchar *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,\n                        ConstStr255Param name, OSErr *err)\n{\nFSSpec      spec;\n\n    *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);\n    printerr(\"FSMakeFSSpecCompat:\", (*err != -43) && (*err != 0), *err,\n             __LINE__, __FILE__, \"\");\n    if ( (*err == noErr) || (*err == fnfErr) )\n        {\n        return GetFullPathFromSpec(CompletePath, &spec, err);\n        }\n\nreturn NULL;\n}\n\n\n\n/*\n**  convert real-filename to archive-filename\n**\n*/\n\nchar *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,\n                    short CurrentFork, short MacZipMode, Boolean DataForkOnly)\n{\n\nAssertStr(RealPath,\"Real2RfDfFilen\")\nAssertStr(RfDfFilen,\"Real2RfDfFilen\")\n\nif (DataForkOnly) /* make no changes */\n    {\n    return sstrcpy(RfDfFilen, RealPath);\n    }\n\nswitch (MacZipMode)\n    {\n    case JohnnyLee_EF:\n        {\n        sstrcpy(RfDfFilen, RealPath);\n        if (CurrentFork == DataFork)            /* data-fork  */\n            return sstrcat(RfDfFilen, \"d\");\n        if (CurrentFork == ResourceFork)        /* resource-fork */\n            return sstrcat(RfDfFilen, \"r\");\n        break;\n        }\n\n    case NewZipMode_EF:\n        {\n        switch (CurrentFork)\n            {\n            case DataFork:\n                {\n                sstrcpy(RfDfFilen, RealPath);\n                return RfDfFilen;  /* data-fork  */\n                break;\n                }\n            case ResourceFork:\n                {\n                sstrcpy(RfDfFilen, ResourceMark);\n                sstrcat(RfDfFilen, RealPath);  /* resource-fork */\n                return RfDfFilen;\n                break;\n                }\n            default:\n                {\n                printerr(\"Real2RfDfFilen:\", -1, -1,\n                         __LINE__, __FILE__, RealPath);\n                return NULL;  /* function should never reach this point */\n                }\n            }\n        break;\n        }\n    default:\n        {\n        printerr(\"Real2RfDfFilen:\", -1, -1, __LINE__, __FILE__, RealPath);\n        return NULL;  /* function should never reach this point */\n        }\n    }\n\nprinterr(\"Real2RfDfFilen:\", -1, -1, __LINE__, __FILE__, RealPath);\nreturn NULL;  /* function should never come reach this point */\n}\n\n\n\n/*\n**  convert archive-filename into a real filename\n**\n*/\n\nchar *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,\n                     Boolean DataForkOnly, short *CurrentFork)\n{\nshort   length;\nint     result;\n\nAssertStr(RfDfFilen,\"RfDfFilen2Real\")\n\nif (DataForkOnly ||\n    (MacZipMode == UnKnown_EF) ||\n    (MacZipMode < JohnnyLee_EF))\n    {\n    *CurrentFork = DataFork;\n    return sstrcpy(RealFn,RfDfFilen);\n    }\n\nresult = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);\nif (result == 0)\n    {\n    MacZipMode = NewZipMode_EF;\n    }\n\nswitch (MacZipMode)\n    {\n    case JohnnyLee_EF:\n        {\n        sstrcpy(RealFn, RfDfFilen);\n        length = strlen(RealFn);       /* determine Fork type */\n        if (RealFn[length-1] == 'd') *CurrentFork = DataFork;\n        else *CurrentFork = ResourceFork;\n        RealFn[length-1] = '\\0';       /* simply cut one char  */\n        return RealFn;\n        break;\n        }\n\n    case NewZipMode_EF:\n        {                                   /* determine Fork type */\n        result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);\n        if (result != 0)\n            {\n            *CurrentFork = DataFork;\n            sstrcpy(RealFn, RfDfFilen);\n            return RealFn;  /* data-fork  */\n            }\n        else\n            {\n            *CurrentFork = ResourceFork;\n            if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))\n                {\n                sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);\n                }\n            else RealFn[0] = '\\0';\n            return RealFn;  /* resource-fork */\n            }\n        break;\n        }\n    default:\n        {\n        *CurrentFork = NoFork;\n        printerr(\"RfDfFilen2Real():\", -1, MacZipMode,\n                 __LINE__, __FILE__, RfDfFilen);\n        return NULL;  /* function should never reach this point */\n        }\n    }\n\nprinterr(\"RfDfFilen2Real():\", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);\nreturn NULL;  /* function should never reach this point */\n}\n\n\n\n/*\n**  return the applications name (argv[0])\n**\n*/\n\nchar *GetAppName(void)\n{\nProcessSerialNumber psn;\nstatic Str255       AppName;\nProcessInfoRec      pinfo;\nOSErr               err;\n\nGetCurrentProcess(&psn);\npinfo.processName = AppName;\npinfo.processInfoLength = sizeof(pinfo);\npinfo.processAppSpec = NULL;\n\nerr = GetProcessInformation(&psn,&pinfo);\nAppName[AppName[0]+1] = 0x00;\n\nreturn (char *)&AppName[1];\n}\n\n\n\n/*\n**  return fullpathname from FSSpec\n**\n*/\n\nchar *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)\n{\nHandle hFullPath;\nshort len;\n\nAssert_it(Spec,\"GetFullPathFromSpec\",\"\")\n\n*err = FSpGetFullPath(Spec, &len, &hFullPath);\nprinterr(\"FSpGetFullPath:\", (*err != -43) && (*err != 0), *err,\n         __LINE__, __FILE__, \"\");\n\nmemmove(FullPath, (Handle) *hFullPath, len);\nFullPath[len] = '\\0';  /* make c-string */\n\nDisposeHandle((Handle)hFullPath);   /* we don't need it any more */\n\nprinterr(\"Warning path length exceeds limit: \", len >= NAME_MAX, len,\n         __LINE__, __FILE__, \" chars \");\n\nreturn FullPath;\n}\n\n\n\n\n/*\n* This function expands a given partial path to a complete path.\n* Path expansions are relative to the running app.\n* This function follows the notation:\n*   1. relative path:\n*       a: \":subfolder:filename\"    -> \":current folder:subfolder:filename\"\n*       b: \"::folder2:filename\"     -> folder2 is beside the current\n*                                      folder on the same level\n*       c: \"filename\"               -> in current folder\n*\n* An absolute path will be returned.\n\nThe following characteristics of Macintosh pathnames should be noted:\n\n       A full pathname never begins with a colon, but must contain at\n       least one colon.\n       A partial pathname always begins with a colon separator except in\n       the case where the file partial pathname is a simple file or\n       directory name.\n       Single trailing separator colons in full or partial pathnames are\n       ignored except in the case of full pathnames to volumes.\n       In full pathnames to volumes, the trailing separator colon is required.\n       Consecutive separator colons can be used to ascend a level from a\n       directory to its parent directory. Two consecutive separator colons\n       will ascend one level, three consecutive separator colons will ascend\n       two levels, and so on. Ascending can only occur from a directory;\n       not a file.\n*/\n\nchar *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,\n                      OSErr *err)\n{\nBoolean hasDirName = false;\nchar currentdir[NAME_MAX];\nchar *tmpPtr;\nunsigned short pathlen;\n\nAssertStr(name,\"GetCompletePath\")\nAssert_it(Spec,\"GetCompletePath\",\"\")\nAssert_it((CompletePath != name),\"GetCompletePath\",\"\")\n\nfor (tmpPtr = name; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':') hasDirName = true;\n\nif (name[0] != ':')   /* case c: path including volume name or only filename */\n    {\n    if (hasDirName)\n        {   /* okey, starts with volume name, so it must be a complete path */\n        sstrcpy(CompletePath, name);\n        }\n    else\n        {   /* only filename: add cwd and return */\n        getcwd(currentdir, NAME_MAX);\n        sstrcat(currentdir, name);\n        sstrcpy(CompletePath, currentdir);\n        }\n    }\nelse if (name[1] == ':')    /* it's case b: \"::folder2:filename\"  */\n    {\n    printerr(\"GetCompletePath \", -1, *err, __LINE__, __FILE__, \"not implemented\");\n            /* it's not yet implemented; do we really need this case ?*/\n    return NULL;\n    }\nelse                        /* it's case a: \":subfolder:filename\" */\n    {\n    getcwd(CompletePath, NAME_MAX);     /* we don't need a second colon */\n    CompletePath[strlen(CompletePath)-1] = '\\0';\n    sstrcat(CompletePath, name);\n    }\n\npathlen = strlen(CompletePath);\n*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);\n\nreturn CompletePath;\n}\n\n\n\nchar *MakeFilenameShorter(const char *LongFilename)\n{\nstatic char filename[35];  /* contents should be never longer than 32 chars */\nstatic unsigned char Num = 0; /* change the number for every call */\n                              /* this var will rollover without a problem */\nchar tempLongFilename[1024], charnum[5];\nchar *last_dotpos         = tempLongFilename;\nunsigned long full_length = strlen(LongFilename);\nunsigned long ext_length  = 0;\nunsigned long num_to_cut  = 0;\nlong firstpart_length;\nchar *tmpPtr;\nshort MaxLength = 31;\n\nif (full_length <= MaxLength) /* filename is not long */\n    {\n    return strcpy(filename,LongFilename);\n    }\n\nNum++;\nstrcpy(tempLongFilename,LongFilename);\n\n/* Look for the last extension pos */\nfor (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == '.') last_dotpos = tmpPtr;\n\next_length = strlen(last_dotpos);\nfirstpart_length = last_dotpos - tempLongFilename;\n\nif (ext_length > 6)  /* up to 5 chars are treated as a */\n    {                /* normal extension like \".html\" or \".class\"  */\n    firstpart_length = 0;\n    }\n\nnum_to_cut = full_length - MaxLength;\n\n/* number the files to make the names unique */\nsprintf(charnum,\"~%x\", Num);\nnum_to_cut += strlen(charnum);\n\nif (firstpart_length == 0)\n    {\n    firstpart_length = full_length;\n    tempLongFilename[firstpart_length - num_to_cut] = 0;\n    sprintf(filename,\"%s%s\", tempLongFilename, charnum);\n    }\nelse\n    {\n    tempLongFilename[firstpart_length - num_to_cut] = 0;\n    sprintf(filename,\"%s%s%s\", tempLongFilename, charnum, last_dotpos);\n    }\n\nreturn filename;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/pathname.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef PATHNAME_H\n#define PATHNAME_H 1\n\n\nchar *StripPartialDir(char *CompletePath,\n                      const char *PartialPath, const char *FullPath);\n\nchar *Real2RfDfFilen(char *RfDfFilen, const char *RealPath, short CurrentFork,\n                     short MacZipMode, Boolean DataForkOnly);\nchar *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,\n                     Boolean DataForkOnly, short *CurrentFork);\n\nunsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName);\nchar *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,\n                      OSErr *err);\nchar *TruncFilename(char *DirPath, const char *FilePath);\nchar *GetFilename(char *CompletePath, const char *name);\nchar *GetFullPathFromSpec(char *CompletePath, FSSpec *Spec, OSErr *err);\nchar *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,\n                        ConstStr255Param name, OSErr *err);\n\nchar *GetAppName(void);\nvoid createArchiveName(char *Path);\nvoid FindDesktopFolder(char *Path);\nchar *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder);\nOSErr FSpFindFolder(\n    short vRefNum,          /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec);          /* Pointer to resulting directory. */\n\nchar *MakeFilenameShorter(const char *LongFilename);\n\n/*\nRule: UnKnown_EF should always be zero.\n      JohnnyLee_EF, NewZipMode_EF should always greater than all\n      other definitions\n*/\n#define UnKnown_EF           0\n#define TomBrownZipIt1_EF   10\n#define TomBrownZipIt2_EF   20\n#define JohnnyLee_EF        30\n#define NewZipMode_EF       40\n\n\n\n#define ResourceFork    -1\n#define DataFork        1\n#define NoFork          0\n\n\n#ifndef NAME_MAX\n#define NAME_MAX    1024\n#endif\n\n#endif   /*  PATHNAME_H  */\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/sxunzip.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include \"unzvers.h\"\n#include <stdio.h>\n\n\n#ifdef USE_SIOUX\n#  include <sioux.h>\n#  include <signal.h>\n#  include <stdlib.h>\n#  include <console.h>\n#endif /* USE_SIOUX */\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nchar fileList[256];\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nint UzpMain(int argc,char **argv);\n\nchar *GetUnZipLocalVersion(void);\nchar *GetUnZipInfoVersions(void);\nint  macgetch(void);\nvoid UserStop(void);\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n#ifndef MacStaticLib\n#ifndef MACUNZIP_STANDALONE\n\n/*\nProgram execution starts here with Metrowerks SIOUX-Console */\nint main(int argc,char **argv)\n{\n    int return_code;\n\n    SIOUXSettings.asktosaveonclose = FALSE;\n    SIOUXSettings.showstatusline = TRUE;\n\n    SIOUXSettings.columns = 100;\n    SIOUXSettings.rows    = 40;\n\n    argc = ccommand(&argv);\n\n    return_code = UzpMain(argc,argv);\n\n    printf(\"\\n\\n Finish  %d\",return_code);\n\n    return return_code;\n}\n\n\n\nint macgetch(void)\n{\n    WindowPtr whichWindow;\n    EventRecord theEvent;\n    char c;                     /* one-byte buffer for read() to use */\n\n    do {\n        SystemTask();\n        if (!GetNextEvent(everyEvent, &theEvent))\n            theEvent.what = nullEvent;\n        else {\n            switch (theEvent.what) {\n            case keyDown:\n                c = theEvent.message & charCodeMask;\n                break;\n            case mouseDown:\n                if (FindWindow(theEvent.where, &whichWindow) ==\n                    inSysWindow)\n                    SystemClick(&theEvent, whichWindow);\n                break;\n            case updateEvt:\n                break;\n            }\n        }\n    } while (theEvent.what != keyDown);\n\n    printf(\"*\");\n    fflush(stdout);\n\n    return (int)c;\n}\n\n\n/* SIOUX needs no extra event handling */\nvoid UserStop(void)\n{\n}\n\n#endif  /*   #ifndef MACUNZIP_STANDALONE  */\n#endif  /*   #ifndef MacStaticLib   */\n\n\n\n\nchar *GetUnZipLocalVersion(void)\n{\nstatic char UnZipVersionLocal[50];\n\nmemset(UnZipVersionLocal,0,sizeof(UnZipVersionLocal));\n\nsprintf(UnZipVersionLocal, \"[%s %s]\", __DATE__, __TIME__);\n\nreturn UnZipVersionLocal;\n}\n\n\n\n\nchar *GetUnZipInfoVersions(void)\n{\nstatic char UnzipVersion[200];\n\nmemset(UnzipVersion,0,sizeof(UnzipVersion));\n\nsprintf(UnzipVersion, \"Unzip Module\\n%d.%d%d%s of %s\", UZ_MAJORVER,\n        UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE);\n\nreturn UnzipVersion;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/macos/source/unzip_rc.hqx",
    "content": "(This file must be converted with BinHex 4.0)\n:#d&bBfKTGQ8ZFfPd!&0*9%46593K!*!%%23!N!65[90*9#%!!J!!%24b6'&e!TN\n!N!-@QCN0!!KeERTTF#jbBaEf1!6lrh3!6%TU!*!$J!#3\"!8$bq6#IJ#3&!Y[!*!\n%rj!%8P053e*6483K!,'+E[HbPeU-!!!FrJ#3\"JVT!*!%KNX!N!MBC3`!&CjkAB5\nYAEECeXrEK!)``L9EH[`m0leZ$pK[bPfEGECTRT`1q\"0'1'%ARKUq$XpGhcEqDm,\n*FGHDf*-4Mh#bM``fZAf%Cq6jNGq%Gf56#5I()i``-Q+E8\"lEK*(EC%,**Z`f18D\n1NpYNXM*bE0+[E\"AiqVj*hqGQK\"ej6UDEE,*I-YTNX-P[XJ&H\"ddL4#+%2,fHN!#\n0m2Sq-Bc'B(8eT@q`L0,ClAYMACV4fd9IS-QiYVdUPCM9NNe'*%)E`Z(1aSKUUUE\nCX+Ya6$A-aQ$#4`D(\"MX(KlUlYK$b$[N,Q#ZIAjp,h1E)jTaQ@[5jj'aMm)dJT3H\n95'mLUJ-KVS(EL\"+,kC%'fV+0QYUXUNGTJfNCUBMP#$8fIKp8iG'!#TU0!+%25MZ\n4(ZiB9#-dSL9($G5K0+`B5V`$2\"e&SU\"\"'SBUGk3Kh)#Lf`pTb@G01S**TP(G3+m\nl(a#Y#4A*@X,5cBPYY&02cKMDq)4&hf[C[IYli+FVF,kq194e6$iQfckiZ6QilGR\nfl*Bl'c1\"mi3!2a1kFbal,'[RR)YSk%ipij-!A1i$G)lF',JfIq(%m6RILH2c&`D\nZ(ERKk2cGamE-PMZB!F`%U%\"@-$ZKU[VQIrVBd%bVNTZR@l0[jN!MPmZq1GfDh%b\nV0[c$ab5TB&fJ4fSKKk5il\"[i!FHKD4b5[L(l1j9%4)dacR0N)pNMaGI`[V%1d+e\n5['VR8&+0D0%C'Y9L+NdSFEA\"E+43QdR&XP3MJDLPde'9UY1@S83XG@`2kUmQ$A!\nrNqC)ZUX,m+mcr-I5ViJNXAB)C`k$Vj%QXNVUN@i3ZG$\"!ZhKF*q!$[@'+GIFfJX\nY!Q+TCl#lKe(5%-heG[Brik%3rejBI&q5bHqN0MI[Q0@I5'e9lidN`!Jph,b0MXj\n3hRYk`dh\"X'jBQTi`D81NNEEXhV8Ek800G(m6(BTVeN46-!LkV)-HKTi*j(jebTT\n5$*8UL6(@Vk*D!J)pGY5NLT@h&Ka53@%d08i003Nf65`E*@90k!C6JTkh(GKQfp6\n4e14d5a1%6HTB#V2f&'qHmRHDGZjBaEXM3N\"C\"8@6KS`I*bF!E3\"-(0Zf2jI@V@i\nIe9-@EkJAN5CYG`6HjYA(Y6ir)[G!H9Gema+q5!B)UF68A55pJ26\"#('43$9@$UZ\n)$$Y'eR4TCM+Qc%\"RMXI9\"&\"GMc8pKQT1U!Q+aNa'$)iNaa4,c61iP2aL5V2)Lc`\nCqb'AAJirP,[(0%XH5BcTj*!!SeI4QE,)+k#,m`$TK,5%&G05b8Z!G-C8aA!-r)*\n9KI#5qe2e3Ae-LfS`3p9d6dGLU6%h&@!'bM1Q`Y`M'%0Z(SFLKJTT(%LbaN!fR46\n%@P%X([-8@FdkJdXi+k4@3B*9'+Rd-CAeXjG8Be3h!9[,FY016ZC6ETFGV`iV+91\nPR)553B$d@#c2`(1FR#UB@-V1QNi&6DJ*8l1d5FfD)CY1NpT126%*j3!#2$QEjNQ\nG)`cGbA&)528!k%`C'P6CTM1NEP#0kj-U$([@\"1f(NF\"dV,H6q@)@bJDVfe1@(PF\nX,B*TmhGS#F@BB5eJ'+B(4hNh19-`iARhYmHQP\"PQYV*I\"4BLrV#Kaj-JcZ[J9A+\nf)&kX5(q2ES\"lXZNF#BB0Q#UG[X@k%fIX9a@FXYN)`aR$ZUA%h!`I)+F,rTEVUUi\nhB3S8CeFV-X'D4CmqT4S4e\",e`V1eMj`VZ\"%*UX%QK+1@53F5-9iJIATLR+AlS$U\nQTH+X\"SCJGR#U\"SBUk(%q!0JEbNNqkT0b)Cq8PRa!KAJG['ZPh%Fr*'rrmJKjpf`\n[@AJ,XAEblNF+@8K,8Xl9JKLed32c)RbK4c\"lKS6X-i55+[BqBfI)AL!$Y`+5k,j\nALkKYCq(056RE*YN[AZ5@00&$J5(mh`(rKCIjKmd++c8X*(%bJ1-V6[!+iRrQjim\n,#apcA'Lj1&GN12#bb(I`l-,#!QJc(F&R4rLk`U4V,f&dem-A--5mC$,4k15N[X!\n%-TGU5HBe[pm26-5cQ8Z3!#`JN!#lk)rBUff5m41r2jTNZ+Y(#-1C([TjMH0-MbF\nDFHlA``%+&[2e-*r&I+203Md`[&3[D!(2HH%$mqiF*`q&HR420LKJ3ACaF-D1Lhm\nXl,LiPd@ZRrIP,K(bYS[(SDmXcI\"mqUNJfJ!9$hNH6j&ImR@2RcIQmF9aS@8q!a\"\nLCiAr)+&Z[Y`-)qPj&l5G2*EiH3((MNdZ`rNYh-ZB#Nq!!!BSm!NmH!X&aFbL'K+\n%!VV1'`3kj`-6qH#5j2NVrV!JlrPcme2LHri+\"Hee#6HrprNLI&aIrkV24rAYC20\n[r5(2Ip*I4\"EFipCrZGkAcP)p21b2+mF'Lb9f@AQ&ch1@6p%brf&b22k6j$c+9eZ\np[Ilkl6UlEVlHVV&VlYE-eGYeYq[@Akqh!jr*[N#fhUkhiF%,I,J-`b#3!)1E\"3p\nTCh)KY6J@,8\"`\"6#-NB1cA5h%YReVr\"KfRFbYD*6(ij1e'-038ZYjm25j(jL0(#i\n$lU+F'()BNFhd5dA'#YXT0e%F'2''i\"@,D!#m1J61$VC1865X&b)1K\",1Qf'q9hV\nkHArhr4Ib)mTjTAiGF,P91AK\"$@GkCi4daM`SVq)-jq$1Z1[L!R\"a-4pl1%GF2m+\nLJ`I&b1RJ`!#mN!!Ga2-cp!0qILH3!-IC6S$MqCd!`r-l!DlRl33BRYm*Z(TL*q$\nk%6X\"efq\"AmErRFqPHLML6+@!)k')BlplJZIVhA%YC[S[*aAlC[%X#bcaEbk0%d[\nmXX!+[b4`Mem8@-j21BYPrXfPL@L*cc4+,G8jbrcbc2U9IQ%-,16K2VmJi2*,1i9\nlr1*1iEkr`NlK(Vqi8hMXMmhmMr2cN!\"IfKPmaIqI\"rAjCApic2F%([*GK8GmCkl\nl$rq,G8+Tc8XN!+YH'Ii9bHcA5c@m9@Piff45Ha8Q\")S[U0'd*1*em+iP&2EG&2E\nG&2EG&2EG&2EG&2EG6-I9%V(`d3a[+l`KmEB'B$*%r`%l#fm1AK[I0,cRiEhU[*!\n!V[qq`JGiYE2`fZ*&$#HYYY\"9fN`ED+XYfr)m[,Cm9jjM-IA63#JAZKU#Ef'KV,e\nmJ@Z(F(HHCRAQE-ECTPH-cJb(QCr9h\"8hCRX1L2QH!f+fjd!Fpac)a`(1dh0L2QM\n#QS6(h\"KcMRZ0jAeXH@TcF6&#HAa8+24\"E((,Z1JR,Llf(N8F##@FQh6eKHN(rXT\niSERaPPV%miTZcV%)5Yp#jFASYDdI!Q@cEjDX`Amc)(#ZFf4`#(la[G291p`(q1@\nZ[S&pS2(APh[lm9rGVIDq3Ib2jH0ri+5DM[iZq+NPIC2rN!#6GQJ4%hN(Y%KX&m5\nMJ'-m#rLh)Ii4i\"LrIl#MI4\"d,acXlKq\"$hPri$rYI)2iVm-G%Ab)9Ec!X,4Y3fY\nmQ@&c$2XC`iicl\"1'R8\"-qTDM!IkQ('d`ShXm(rq[ahP2HjKdhF-#Sr,LF!2AHkT\n$AKbr)I6fbB[DK-\"Dj-@*2Z'T&E#6R&H6!#c'HHYlS0*HjEa9VmZ,\"lSiEqeHm24\nccU[p,RKkKI-fe)$H\"jaA&38IdjbhCSqmq2T@iHmhS,G\"q$X(HMrP[!TH(aaM[lq\ni4X9EAUh)M8kY`+U$IIMM(m)U0c2X&,EA5S9Kmk3H-&jEC`M8PAmE`ml#TbRLeaK\nf'Rjh%MrlA`HrLm\"r!,S,1iHKdkb9&dFq+(ma@rSXY[aYbrf\"9Ia1YIchbIQq0$#\n98!hijQMU+51LrKm0!!YeERTTF(0QBbjbB`6lrh3!6%TU!*!$J!#3\"!8$bq5qFJ#\n3%4B!N!MrN!458e*$8P0&4#%!XBTZpl+A@GJ!!!Nf!*!'\"48!N!6(q`#3##3`)d3\n1)LTG595#b[aFefGjh@l'cV8kJ@fHHiB5P2Af)&[1-QPjVLHVETBc4L,Qdf2KF'\"\n@M\"[F-'SAciTchCMP9Ch8(HN1G%GDJY1)ER1JFEr[AU,qfNBdLf6$C,-cQfGjcr8\nbeLR&fY@%\"X)F'@jR5)ULa@TCBadcj-eF5l\"D`p5c-E-J0'M@k9#&8JBUD!i#K$i\n%&K$d((mhMl'BR1R9KBl!`T)ZTIh`G*-J5M5))DpihM$D3#%kj'`j-p0JDd6)3N,\n6KGHK[bI@T,JJPkQQCU6U@%$,$1Pb-Q@bIBe,PT`'2r1Sb%Sj`p&)Cc[5,QIADKX\nR2`$Hee85N!$8'&FX6J5G3%XGk5Tl,[b\"KMV5CI-M'4k6%d-X)5ZFU9+DeaUc',a\nA5DE*G9@J04VVjB`2QVS8-hPmUG$A85fq&XGf'Ji'JIH`m0@1qmMKX-BGhK,4q*'\n2bKfYMPq5kmL%UTV$iBim0,8pc'c0d(D-!24-DhG,Ud@T3lHN24#D2ST#rd,HiPD\n(Lcl[D\"V*(92pQU1TE0mD&8D%FaVU@1m3XfGVE0MR$@Zk+@ZU`@TMXeMMNX9,\"$h\n2apTm,*+@cC62ki8Zh4$6X41!R-d(c!&*jda5ipBmPXSUQNUPcf#51@E01m+K8*4\n0-TeRB0-UaUB`DkBdh9+#Q4i#YV9TS#rE2pMS3a[&ieQ4@S#p(2L&[[RcbZhT4`J\nS@Ja0(4*I5KF!$3FQ29XZpe[(a)VQALeVfJ[MH8&MjKB%lV1R6p5kZ-(9L[&@YpJ\nMr$ae%4@,k*kRGL\"C@*(2%kC4%H8#b5mB-3CP)k0)3pJmFp*F\"GAZ8GqUFb2&95D\n-@5fLpjT-A$,j'%18iXr-bLDGDBGK3CD1$(Hk@Z+bk9UMaM8kZk$(\"E)QVBFZlMX\n53#`jNQ&b@JXN6H'5AM#`dCS+b8[E0pfG@Pa1b,J4p#f$-58E(iN#c-\"iPR2XGBQ\n40j*MANcRL(&maPS-j+3GHD)K2b`1jZe8B@d'1q(1[*3@!CIJC+L-FfZI6H*kVfB\n!ml@b5D8GBj(EIZGB&jDb\"QFf#5@p!98UbKJ$he+km)J*GcV'J#4-P+L'E-VpXMP\n%*ee%P3&0lFFiJ)!B6TqG9&d3KZdN1i3VD6adjZXbTUc2,UVZjQQYRq1BU8Qa%%i\n#Dm&k+ZdmQN+R38eceY65NLR(4'a+[ka+qT!!Y3,bF6h)bYI3VL-Q(0k9cFU!0'5\nC9B3i@)JS`lU@cN\"FR)0TG2%4mID*9,CU1Yb6NbiKEeM(e56[,EUG4)D&5q++T#H\n-b-MA6%NC56L6,MVLVfZZI0T9)irLE9B65eR,)NXEi(T-D%Rc)UBeKLijiNB+5#q\n@%*jD9YDP+[D!C'PUdSTl()r,fE3e!hQi(Ha6J`G2aaR0rpA'(6-H\"XAN1*rFBJj\n\")$IB(Ze!2c[Bd389F[kkpT!!Z-rZEZlSaPiR0rP$3A&hEFTI@$XkrFhGiU)Dea*\nDJh[MN!\"pJ6&RNb1A'lR@@)'aTpKA(H90YV!kJ6&GVVq+RTcRrF,e9mQp0Sqm0DT\n\"[MkQ0p$e9r+b21B$62,%R1ckUp5$0Smp$Eci2$BD@,LY`@k#aMSk2jGc8C(Ep9I\nYLqN#`H2@J,I+AV6F)@$ef*F'c&8UmRJG@bXBf%r!@iRP%ihCdJ&V`#kj4Pa#J\"9\nMlM1!E3&@J+Q&I\"@r\"SEM24d6CiD24hkhZYe,Z'XGfMGEqjVUfLRb@KJrS()Gjk0\n9bqSarMi!*p!!!!:\n"
  },
  {
    "path": "deps/infozip/unzip60/man/Contents",
    "content": "Contents of the \"man\" subdirectory for UnZip 5.41 and later:\n\n  Contents      this file\n  funzip.1      fUnZip manual page, nroff format\n  unzip.1       UnZip manual page, nroff format\n  unzipsfx.1    UnZipSFX manual page, nroff format\n  zipgrep.1     ZipGrep manual page, nroff format\n  zipinfo.1     ZipInfo manual page, nroff format\n\nThis subdirectory contains the master source files for the UnZip user\ndocumentation. Although these documents are Unix man-page sources, they\nare of general interest and therefore stored separately.\nSome non-Unix systems may supply a man-page reader where they could be\nused; and they are the sources for the generic ASCII text document files.\n"
  },
  {
    "path": "deps/infozip/unzip60/man/funzip.1",
    "content": ".\\\"  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\"  See the accompanying file LICENSE, version 2009-Jan-02 or later\n.\\\"  (the contents of which are also included in unzip.h) for terms of use.\n.\\\"  If, for some reason, all these files are missing, the Info-ZIP license\n.\\\"  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\"\n.\\\" funzip.1 by Greg Roelofs and others.\n.\\\"\n.\\\" =========================================================================\n.\\\" define .EX/.EE (for multiline user-command examples; normal Courier font)\n.de EX\n.in +4n\n.nf\n.ft CW\n..\n.de EE\n.ft R\n.fi\n.in -4n\n..\n.\\\" =========================================================================\n.TH FUNZIP 1L \"20 April 2009 (v3.95)\" \"Info-ZIP\"\n.SH NAME\nfunzip \\- filter for extracting from a ZIP archive in a pipe\n.PD\n.SH SYNOPSIS\n\\fBfunzip\\fP [\\fB\\-password\\fP] [\\fIinput[.zip|.gz]\\fP]\n.\\\" =========================================================================\n.SH ARGUMENTS\n.IP [\\fI\\-password\\fP]\nOptional password to be used if ZIP archive is encrypted.  Decryption\nmay not be supported at some sites.  See DESCRIPTION for more details.\n.IP [\\fIinput[.zip|.gz]\\fP]\nOptional input archive file specification. See DESCRIPTION for details.\n.PD\n.\\\" =========================================================================\n.SH DESCRIPTION\n.I funzip\nwithout a file argument acts as a filter; that is, it assumes that a\nZIP archive (or a \\fIgzip\\fP'd(1) file) is being piped into\nstandard input, and it extracts the first member from the archive to stdout.\nWhen stdin comes from a tty device,\n.I funzip\nassumes that this cannot be a stream of (binary) compressed data and\nshows a short help text, instead.\nIf there is a file argument, then input is read from the specified file\ninstead of from stdin.\n.PP\nA password for encrypted zip files can be specified\non the command line (preceding the file name, if any) by prefixing the\npassword with a dash.  Note that this constitutes a security risk on many\nsystems; currently running processes are often visible via simple commands\n(e.g., \\fIps\\fP(1) under Unix), and command-line histories can be read.\nIf the first entry of the zip file is encrypted and\nno password is specified on the command line, then the user is prompted for\na password and the password is not echoed on the console.\n.PP\nGiven the limitation on single-member extraction, \\fIfunzip\\fP is most\nuseful in conjunction with a secondary archiver program such as \\fItar\\fP(1).\nThe following section includes an example illustrating this usage in the\ncase of disk backups to tape.\n.PD\n.\\\" =========================================================================\n.SH EXAMPLES\nTo use \\fIfunzip\\fP to extract the first member file of the archive test.zip\nand to pipe it into \\fImore\\fP(1):\n.PP\n.EX\nfunzip test.zip | more\n.EE\n.PP\nTo use \\fIfunzip\\fP to test the first member file of test.zip (any errors\nwill be reported on standard error):\n.PP\n.EX\nfunzip test.zip > /dev/null\n.EE\n.PP\nTo use \\fIzip\\fP and \\fIfunzip\\fP in place of \\fIcompress\\fP(1) and\n\\fIzcat\\fP(1) (or \\fIgzip\\fP(1L) and \\fIgzcat\\fP(1L)) for tape backups:\n.PP\n.EX\ntar cf \\- . | zip \\-7 | dd of=/dev/nrst0 obs=8k\ndd if=/dev/nrst0 ibs=8k | funzip | tar xf \\-\n.EE\n.PP\n(where, for example, nrst0 is a SCSI tape drive).\n.PD\n.\\\" =========================================================================\n.SH BUGS\nWhen piping an encrypted file into \\fImore\\fP and allowing \\fIfunzip\\fP\nto prompt for password, the terminal may sometimes be reset to a non-echo\nmode.  This is apparently due to a race condition between the two programs;\n\\fIfunzip\\fP changes the terminal mode to non-echo before \\fImore\\fP reads\nits state, and \\fImore\\fP then ``restores'' the terminal to this mode before\nexiting.  To recover, run \\fIfunzip\\fP on the same file but redirect to\n/dev/null rather than piping into more; after prompting again for the\npassword, \\fIfunzip\\fP will reset the terminal properly.\n.PP\nThere is presently no way to extract any member but the first from a ZIP\narchive.  This would be useful in the case where a ZIP archive is included\nwithin another archive.  In the case where the first member is a directory,\n\\fIfunzip\\fP simply creates the directory and exits.\n.PP\nThe functionality of \\fIfunzip\\fP should be incorporated into \\fIunzip\\fP\nitself (future release).\n.PD\n.\\\" =========================================================================\n.SH \"SEE ALSO\"\n\\fIgzip\\fP(1L), \\fIunzip\\fP(1L), \\fIunzipsfx\\fP(1L), \\fIzip\\fP(1L),\n\\fIzipcloak\\fP(1L), \\fIzipinfo\\fP(1L), \\fIzipnote\\fP(1L), \\fIzipsplit\\fP(1L)\n.PD\n.\\\" =========================================================================\n.SH URL\nThe Info-ZIP home page is currently at\n.EX\n\\fChttp://www.info-zip.org/pub/infozip/\\fR\n.EE\nor\n.EX\n\\fCftp://ftp.info-zip.org/pub/infozip/\\fR .\n.EE\n.PD\n.\\\" =========================================================================\n.SH AUTHOR\nMark Adler (Info-ZIP)\n"
  },
  {
    "path": "deps/infozip/unzip60/man/unzip.1",
    "content": ".\\\"  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\"  See the accompanying file LICENSE, version 2009-Jan-02 or later\n.\\\"  (the contents of which are also included in unzip.h) for terms of use.\n.\\\"  If, for some reason, all these files are missing, the Info-ZIP license\n.\\\"  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\"\n.\\\" unzip.1 by Greg Roelofs, Fulvio Marino, Jim van Zandt and others.\n.\\\"\n.\\\" =========================================================================\n.\\\" define .EX/.EE (for multiline user-command examples; normal Courier font)\n.de EX\n.in +4n\n.nf\n.ft CW\n..\n.de EE\n.ft R\n.fi\n.in -4n\n..\n.\\\" =========================================================================\n.TH UNZIP 1L \"20 April 2009 (v6.0)\" \"Info-ZIP\"\n.SH NAME\nunzip \\- list, test and extract compressed files in a ZIP archive\n.PD\n.SH SYNOPSIS\n\\fBunzip\\fP [\\fB\\-Z\\fP] [\\fB\\-cflptTuvz\\fP[\\fBabjnoqsCDKLMUVWX$/:^\\fP]]\n\\fIfile\\fP[\\fI.zip\\fP] [\\fIfile(s)\\fP\\ .\\|.\\|.]\n[\\fB\\-x\\fP\\ \\fIxfile(s)\\fP\\ .\\|.\\|.] [\\fB\\-d\\fP\\ \\fIexdir\\fP]\n.PD\n.\\\" =========================================================================\n.SH DESCRIPTION\n\\fIunzip\\fP will list, test, or extract files from a ZIP archive, commonly\nfound on MS-DOS systems.  The default behavior (with no options) is to extract\ninto the current directory (and subdirectories below it) all files from the\nspecified ZIP archive.  A companion program, \\fIzip\\fP(1L), creates ZIP\narchives; both programs are compatible with archives created by PKWARE's\n\\fIPKZIP\\fP and \\fIPKUNZIP\\fP for MS-DOS, but in many cases the program\noptions or default behaviors differ.\n.PD\n.\\\" =========================================================================\n.SH ARGUMENTS\n.TP\n.IR file [ .zip ]\nPath of the ZIP archive(s).  If the file specification is a wildcard,\neach matching file is processed in an order determined by the operating\nsystem (or file system).  Only the filename can be a wildcard; the path\nitself cannot.  Wildcard expressions are similar to those supported in\ncommonly used Unix shells (\\fIsh\\fP, \\fIksh\\fP, \\fIcsh\\fP) and may contain:\n.RS\n.IP *\nmatches a sequence of 0 or more characters\n.IP ?\nmatches exactly 1 character\n.IP [.\\|.\\|.]\nmatches any single character found inside the brackets; ranges are specified\nby a beginning character, a hyphen, and an ending character.  If an exclamation\npoint or a caret (`!' or `^') follows the left bracket, then the range of\ncharacters within the brackets is complemented (that is, anything \\fIexcept\\fP\nthe characters inside the brackets is considered a match).  To specify a\nverbatim left bracket, the three-character sequence ``[[]'' has to be used.\n.RE\n.IP\n(Be sure to quote any character that might otherwise be interpreted or\nmodified by the operating system, particularly under Unix and VMS.)  If no\nmatches are found, the specification is assumed to be a literal filename;\nand if that also fails, the suffix \\fC.zip\\fR is appended.  Note that\nself-extracting ZIP files are supported, as with any other ZIP archive;\njust specify the \\fC.exe\\fR suffix (if any) explicitly.\n.IP [\\fIfile(s)\\fP]\nAn optional list of archive members to be processed, separated by spaces.\n(VMS versions compiled with VMSCLI defined must delimit files with commas\ninstead.  See \\fB\\-v\\fP in \\fBOPTIONS\\fP below.)\nRegular expressions (wildcards) may be used to match multiple members; see\nabove.  Again, be sure to quote expressions that would otherwise be expanded\nor modified by the operating system.\n.IP [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP]\nAn optional list of archive members to be excluded from processing.\nSince wildcard characters normally match (`/') directory separators\n(for exceptions see the option \\fB\\-W\\fP), this option may be used\nto exclude any files that are in subdirectories.  For\nexample, ``\\fCunzip foo *.[ch] -x */*\\fR'' would extract all C source files\nin the main directory, but none in any subdirectories.  Without the \\fB\\-x\\fP\noption, all C source files in all directories within the zipfile would be\nextracted.\n.IP [\\fB\\-d\\fP\\ \\fIexdir\\fP]\nAn optional directory to which to extract files.  By default, all files\nand subdirectories are recreated in the current directory; the \\fB\\-d\\fP\noption allows extraction in an arbitrary directory (always assuming one\nhas permission to write to the directory).  This option need not appear\nat the end of the command line; it is also accepted before the zipfile\nspecification (with the normal options), immediately after the zipfile\nspecification, or between the \\fIfile(s)\\fP and the \\fB\\-x\\fP option.\nThe option and directory may be concatenated without any white space\nbetween them, but note that this may cause normal shell behavior to be\nsuppressed.  In particular, ``\\fC\\-d\\ ~\\fR'' (tilde) is expanded by Unix\nC shells into the name of the user's home directory, but ``\\fC\\-d~\\fR''\nis treated as a literal subdirectory ``\\fB~\\fP'' of the current directory.\n.\\\" =========================================================================\n.SH OPTIONS\nNote that, in order to support obsolescent hardware, \\fIunzip\\fP's usage\nscreen is limited to 22 or 23 lines and should therefore be considered\nonly a reminder of the basic \\fIunzip\\fP syntax rather than an exhaustive\nlist of all possible flags.  The exhaustive list follows:\n.TP\n.B \\-Z\n\\fIzipinfo\\fP(1L) mode.  If the first option on the command line is \\fB\\-Z\\fP,\nthe remaining options are taken to be \\fIzipinfo\\fP(1L) options.  See the\nappropriate manual page for a description of these options.\n.TP\n.B \\-A\n[OS/2, Unix DLL] print extended help for the DLL's programming interface (API).\n.TP\n.B \\-c\nextract files to stdout/screen (``CRT'').  This option is similar to the\n\\fB\\-p\\fP option except that the name of each file is printed as it is\nextracted, the \\fB\\-a\\fP option is allowed, and ASCII-EBCDIC conversion\nis automatically performed if appropriate.  This option is not listed in\nthe \\fIunzip\\fP usage screen.\n.TP\n.B \\-f\nfreshen existing files, i.e., extract only those files that\nalready exist on disk and that are newer than the disk copies.  By\ndefault \\fIunzip\\fP queries before overwriting, but the \\fB\\-o\\fP option\nmay be used to suppress the queries.  Note that under many operating systems,\nthe TZ (timezone) environment variable must be set correctly in order for\n\\fB\\-f\\fP and \\fB\\-u\\fP to work properly (under Unix the variable is usually\nset automatically).  The reasons for this are somewhat subtle but\nhave to do with the differences between DOS-format file times (always local\ntime) and Unix-format times (always in GMT/UTC) and the necessity to compare\nthe two.  A typical TZ value is ``PST8PDT'' (US Pacific time with automatic\nadjustment for Daylight Savings Time or ``summer time'').\n.TP\n.B \\-l\nlist archive files (short format).  The names, uncompressed file sizes and\nmodification dates and times of the specified files are printed, along\nwith totals for all files specified.  If UnZip was compiled with OS2_EAS\ndefined, the \\fB\\-l\\fP option also lists columns for the sizes of stored\nOS/2 extended attributes (EAs) and OS/2 access control lists (ACLs).  In\naddition, the zipfile comment and individual file comments (if any) are\ndisplayed.  If a file was archived from a single-case file system (for\nexample, the old MS-DOS FAT file system) and the \\fB\\-L\\fP option was given,\nthe filename is converted to lowercase and is prefixed with a caret (^).\n.TP\n.B \\-p\nextract files to pipe (stdout).  Nothing but the file data is sent to\nstdout, and the files are always extracted in binary format, just as they\nare stored (no conversions).\n.TP\n.B \\-t\ntest archive files.  This option extracts each specified file in memory\nand compares the CRC (cyclic redundancy check, an enhanced checksum) of\nthe expanded file with the original file's stored CRC value.\n.TP\n.B \\-T\n[most OSes] set the timestamp on the archive(s) to that of the newest file\nin each one.  This corresponds to \\fIzip\\fP's \\fB\\-go\\fP option except that\nit can be used on wildcard zipfiles (e.g., ``\\fCunzip \\-T \\e*.zip\\fR'') and\nis much faster.\n.TP\n.B \\-u\nupdate existing files and create new ones if needed.  This option performs\nthe same function as the \\fB\\-f\\fP option, extracting (with query) files\nthat are newer than those with the same name on disk, and in addition it\nextracts those files that do not already exist on disk.  See \\fB\\-f\\fP\nabove for information on setting the timezone properly.\n.TP\n.B \\-v\nlist archive files (verbose format) or show diagnostic version info.\nThis option has evolved and now behaves as both an option and a modifier.\nAs an option it has two purposes:  when a zipfile is specified with no\nother options, \\fB\\-v\\fP lists archive files verbosely, adding to the\nbasic \\fB\\-l\\fP info the compression method, compressed size,\ncompression ratio and 32-bit CRC.  In contrast to most of the competing\nutilities, \\fIunzip\\fP removes the 12 additional header bytes of\nencrypted entries from the compressed size numbers.  Therefore,\ncompressed size and compression ratio figures are independent of the entry's\nencryption status and show the correct compression performance.  (The complete\nsize of the encrypted compressed data stream for zipfile entries is reported\nby the more verbose \\fIzipinfo\\fP(1L) reports, see the separate manual.)\nWhen no zipfile is specified (that is, the complete command is simply\n``\\fCunzip \\-v\\fR''), a diagnostic screen is printed.  In addition to\nthe normal header with release date and version, \\fIunzip\\fP lists the\nhome Info-ZIP ftp site and where to find a list of other ftp and non-ftp\nsites; the target operating system for which it was compiled, as well\nas (possibly) the hardware on which it was compiled, the compiler and\nversion used, and the compilation date; any special compilation options\nthat might affect the program's operation (see also \\fBDECRYPTION\\fP below);\nand any options stored in environment variables that might do the same\n(see \\fBENVIRONMENT OPTIONS\\fP below).  As a modifier it works in\nconjunction with other options (e.g., \\fB\\-t\\fP) to produce more\nverbose or debugging output; this is not yet fully implemented\nbut will be in future releases.\n.TP\n.B \\-z\ndisplay only the archive comment.\n.PD\n.\\\" =========================================================================\n.SH MODIFIERS\n.TP\n.B \\-a\nconvert text files.  Ordinarily all files are extracted exactly as they\nare stored (as ``binary'' files).  The \\fB\\-a\\fP option causes files identified\nby \\fIzip\\fP as text files (those with the `t' label in \\fIzipinfo\\fP\nlistings, rather than `b') to be automatically extracted as such, converting\nline endings, end-of-file characters and the character set itself as necessary.\n(For example, Unix files use line feeds (LFs) for end-of-line (EOL) and\nhave no end-of-file (EOF) marker; Macintoshes use carriage returns (CRs)\nfor EOLs; and most PC operating systems use CR+LF for EOLs and control-Z for\nEOF.  In addition, IBM mainframes and the Michigan Terminal System use EBCDIC\nrather than the more common ASCII character set, and NT supports Unicode.)\nNote that \\fIzip\\fP's identification of text files is by no means perfect; some\n``text'' files may actually be binary and vice versa.  \\fIunzip\\fP therefore\nprints ``\\fC[text]\\fR'' or ``\\fC[binary]\\fR'' as a visual check for each file\nit extracts when using the \\fB\\-a\\fP option.  The \\fB\\-aa\\fP option forces\nall files to be extracted as text, regardless of the supposed file type.\nOn VMS, see also \\fB\\-S\\fP.\n.TP\n.B \\-b\n[general] treat all files as binary (no text conversions).  This is a shortcut\nfor \\fB\\-\\-\\-a\\fP.\n.TP\n.B \\-b\n[Tandem] force the creation files with filecode type 180 ('C') when\nextracting Zip entries marked as \"text\". (On Tandem, \\fB\\-a\\fP is enabled\nby default, see above).\n.TP\n.B \\-b\n[VMS] auto-convert binary files (see \\fB\\-a\\fP above) to fixed-length,\n512-byte record format.  Doubling the option (\\fB\\-bb\\fP) forces all files\nto be extracted in this format. When extracting to standard output\n(\\fB\\-c\\fP or \\fB\\-p\\fP option in effect), the default conversion of text\nrecord delimiters is disabled for binary (\\fB\\-b\\fP) resp. all (\\fB\\-bb\\fP)\nfiles.\n.TP\n.B \\-B\n[when compiled with UNIXBACKUP defined] save a backup copy of each\noverwritten file. The backup file is gets the name of the target file with\na tilde and optionally a unique sequence number (up to 5 digits) appended.\nThe sequence number is applied whenever another file with the original name\nplus tilde already exists.  When used together with the \"overwrite all\"\noption \\fB\\-o\\fP, numbered backup files are never created. In this case,\nall backup files are named as the original file with an appended tilde,\nexisting backup files are deleted without notice.\nThis feature works similarly to the default behavior of \\fIemacs\\fP(1)\nin many locations.\n.IP\nExample: the old copy of ``\\fCfoo\\fR'' is renamed to ``\\fCfoo~\\fR''.\n.IP\nWarning: Users should be aware that the \\fB-B\\fP option does not prevent\nloss of existing data under all circumstances.  For example, when\n\\fIunzip\\fP is run in overwrite-all mode, an existing ``\\fCfoo~\\fR'' file\nis deleted before \\fIunzip\\fP attempts to rename ``\\fCfoo\\fR'' to\n``\\fCfoo~\\fR''.  When this rename attempt fails (because of a file locks,\ninsufficient privileges, or ...), the extraction of ``\\fCfoo~\\fR'' gets\ncancelled, but the old backup file is already lost.  A similar scenario\ntakes place when the sequence number range for numbered backup files gets\nexhausted (99999, or 65535 for 16-bit systems).  In this case, the backup\nfile with the maximum sequence number is deleted and replaced by the new\nbackup version without notice.\n.TP\n.B \\-C\nuse case-insensitive matching for the selection of archive entries\nfrom the command-line list of extract selection patterns.\n\\fIunzip\\fP's philosophy is ``you get what you ask for'' (this is\nalso responsible for the \\fB\\-L\\fP/\\fB\\-U\\fP change; see the relevant\noptions below).  Because some file systems are fully case-sensitive\n(notably those under the Unix operating system) and because\nboth ZIP archives and \\fIunzip\\fP itself are portable across platforms,\n\\fIunzip\\fP's default behavior is to match both wildcard and literal\nfilenames case-sensitively.  That is, specifying ``\\fCmakefile\\fR''\non the command line will \\fIonly\\fP match ``makefile'' in the archive,\nnot ``Makefile'' or ``MAKEFILE'' (and similarly for wildcard specifications).\nSince this does not correspond to the behavior of many other\noperating/file systems (for example, OS/2 HPFS, which preserves\nmixed case but is not sensitive to it), the \\fB\\-C\\fP option may be\nused to force all filename matches to be case-insensitive.  In the\nexample above, all three files would then match ``\\fCmakefile\\fR''\n(or ``\\fCmake*\\fR'', or similar).  The \\fB\\-C\\fP option affects\nfile specs in both the normal file list and the excluded-file list (xlist).\n.IP\nPlease note that the \\fB\\-C\\fP option does neither affect the search for\nthe zipfile(s) nor the matching of archive entries to existing files on\nthe extraction path.  On a case-sensitive file system, \\fIunzip\\fP will\nnever try to overwrite a file ``FOO'' when extracting an entry ``foo''!\n.TP\n.B \\-D\nskip restoration of timestamps for extracted items.  Normally, \\fIunzip\\fP\ntries to restore all meta-information for extracted items that are supplied\nin the Zip archive (and do not require privileges or impose a security risk).\nBy specifying \\fB\\-D\\fP, \\fIunzip\\fP is told to suppress restoration of\ntimestamps for directories explicitly created from Zip archive entries.\nThis option only applies to ports that support setting timestamps for\ndirectories (currently ATheOS, BeOS, MacOS, OS/2, Unix, VMS, Win32, for other\n\\fIunzip\\fP ports, \\fB\\-D\\fP has no effect).\nThe duplicated option \\fB\\-DD\\fP forces suppression of timestamp restoration\nfor all extracted entries (files and directories).  This option results in\nsetting the timestamps for all extracted entries to the current time.\n.IP\nOn VMS, the default setting for this option is \\fB\\-D\\fP for consistency\nwith the behaviour of BACKUP: file timestamps are restored, timestamps of\nextracted directories are left at the current time.  To enable restoration\nof directory timestamps, the negated option \\fB\\--D\\fP should be specified.\nOn VMS, the option \\fB\\-D\\fP disables timestamp restoration for all extracted\nZip archive items.  (Here, a single \\fB\\-D\\fP on the command line combines\nwith the default \\fB\\-D\\fP to do what an explicit \\fB\\-DD\\fP does on other\nsystems.)\n.TP\n.B \\-E\n[MacOS only] display contents of MacOS extra field during restore operation.\n.TP\n.B \\-F\n[Acorn only] suppress removal of NFS filetype extension from stored filenames.\n.TP\n.B \\-F\n[non-Acorn systems supporting long filenames with embedded commas,\nand only if compiled with ACORN_FTYPE_NFS defined] translate\nfiletype information from ACORN RISC OS extra field blocks into a\nNFS filetype extension and append it to the names of the extracted files.\n(When the stored filename appears to already have an appended NFS filetype\nextension, it is replaced by the info from the extra field.)\n.TP\n.B \\-i\n[MacOS only] ignore filenames stored in MacOS extra fields. Instead, the\nmost compatible filename stored in the generic part of the entry's header\nis used.\n.TP\n.B \\-j\njunk paths.  The archive's directory structure is not recreated; all files\nare deposited in the extraction directory (by default, the current one).\n.TP\n.B \\-J\n[BeOS only] junk file attributes.  The file's BeOS file attributes are not\nrestored, just the file's data.\n.TP\n.B \\-J\n[MacOS only] ignore MacOS extra fields.  All Macintosh specific info\nis skipped. Data-fork and resource-fork are restored as separate files.\n.TP\n.B \\-K\n[AtheOS, BeOS, Unix only] retain SUID/SGID/Tacky file attributes.  Without\nthis flag, these attribute bits are cleared for security reasons.\n.TP\n.B \\-L\nconvert to lowercase any filename originating on an uppercase-only operating\nsystem or file system.  (This was \\fIunzip\\fP's default behavior in releases\nprior to 5.11; the new default behavior is identical to the old behavior with\nthe \\fB\\-U\\fP option, which is now obsolete and will be removed in a future\nrelease.)  Depending on the archiver, files archived under single-case\nfile systems (VMS, old MS-DOS FAT, etc.) may be stored as all-uppercase names;\nthis can be ugly or inconvenient when extracting to a case-preserving\nfile system such as OS/2 HPFS or a case-sensitive one such as under\nUnix.  By default \\fIunzip\\fP lists and extracts such filenames exactly as\nthey're stored (excepting truncation, conversion of unsupported characters,\netc.); this option causes the names of all files from certain systems to be\nconverted to lowercase.  The \\fB\\-LL\\fP option forces conversion of every\nfilename to lowercase, regardless of the originating file system.\n.TP\n.B \\-M\npipe all output through an internal pager similar to the Unix \\fImore\\fP(1)\ncommand.  At the end of a screenful of output, \\fIunzip\\fP pauses with a\n``\\-\\-More\\-\\-'' prompt; the next screenful may be viewed by pressing the\nEnter (Return) key or the space bar.  \\fIunzip\\fP can be terminated by\npressing the ``q'' key and, on some systems, the Enter/Return key.  Unlike\nUnix \\fImore\\fP(1), there is no forward-searching or editing capability.\nAlso, \\fIunzip\\fP doesn't notice if long lines wrap at the edge of the screen,\neffectively resulting in the printing of two or more lines and the likelihood\nthat some text will scroll off the top of the screen before being viewed.\nOn some systems the number of available lines on the screen is not detected,\nin which case \\fIunzip\\fP assumes the height is 24 lines.\n.TP\n.B \\-n\nnever overwrite existing files.  If a file already exists, skip the extraction\nof that file without prompting.  By default \\fIunzip\\fP queries before\nextracting any file that already exists; the user may choose to overwrite\nonly the current file, overwrite all files, skip extraction of the current\nfile, skip extraction of all existing files, or rename the current file.\n.TP\n.B \\-N\n[Amiga] extract file comments as Amiga filenotes.  File comments are created\nwith the \\-c option of \\fIzip\\fP(1L), or with the \\-N option of the Amiga port\nof \\fIzip\\fP(1L), which stores filenotes as comments.\n.TP\n.B \\-o\noverwrite existing files without prompting.  This is a dangerous option, so\nuse it with care.  (It is often used with \\fB\\-f\\fP, however, and is the only\nway to overwrite directory EAs under OS/2.)\n.IP \\fB\\-P\\fP\\ \\fIpassword\\fP\nuse \\fIpassword\\fP to decrypt encrypted zipfile entries (if any).  \\fBTHIS IS\nINSECURE!\\fP  Many multi-user operating systems provide ways for any user to\nsee the current command line of any other user; even on stand-alone systems\nthere is always the threat of over-the-shoulder peeking.  Storing the plaintext\npassword as part of a command line in an automated script is even worse.\nWhenever possible, use the non-echoing, interactive prompt to enter passwords.\n(And where security is truly important, use strong encryption such as Pretty\nGood Privacy instead of the relatively weak encryption provided by standard\nzipfile utilities.)\n.TP\n.B \\-q\nperform operations quietly (\\fB\\-qq\\fP = even quieter).  Ordinarily \\fIunzip\\fP\nprints the names of the files it's extracting or testing, the extraction\nmethods, any file or zipfile comments that may be stored in the archive,\nand possibly a summary when finished with each archive.  The \\fB\\-q\\fP[\\fBq\\fP]\noptions suppress the printing of some or all of these messages.\n.TP\n.B \\-s\n[OS/2, NT, MS-DOS] convert spaces in filenames to underscores.  Since all PC\noperating systems allow spaces in filenames, \\fIunzip\\fP by default extracts\nfilenames with spaces intact (e.g., ``\\fCEA\\ DATA.\\ SF\\fR'').  This can be\nawkward, however, since MS-DOS in particular does not gracefully support\nspaces in filenames.  Conversion of spaces to underscores can eliminate the\nawkwardness in some cases.\n.TP\n.B \\-S\n[VMS] convert text files (\\fB\\-a\\fP, \\fB\\-aa\\fP) into Stream_LF record format,\ninstead of the text-file default, variable-length record format.\n(Stream_LF is the default record format of VMS \\fIunzip\\fP. It is applied\nunless conversion (\\fB\\-a\\fP, \\fB\\-aa\\fP and/or \\fB\\-b\\fP, \\fB\\-bb\\fP) is\nrequested or a VMS-specific entry is processed.)\n.TP\n.B \\-U\n[UNICODE_SUPPORT only] modify or disable UTF-8 handling.\nWhen UNICODE_SUPPORT is available, the option \\fB\\-U\\fP forces \\fIunzip\\fP\nto escape all non-ASCII characters from UTF-8 coded filenames as ``#Uxxxx''\n(for UCS-2 characters, or ``#Lxxxxxx'' for unicode codepoints needing 3\noctets).  This option is mainly provided for debugging purpose when the\nfairly new UTF-8 support is suspected to mangle up extracted filenames.\n.IP\nThe option \\fB\\-UU\\fP allows to entirely disable the recognition of UTF-8\nencoded filenames.  The handling of filename codings within \\fIunzip\\fP falls\nback to the behaviour of previous versions.\n.IP\n[old, obsolete usage] leave filenames uppercase if\ncreated under MS-DOS, VMS, etc.  See \\fB\\-L\\fP above.\n.TP\n.B \\-V\nretain (VMS) file version numbers.  VMS files can be stored with a version\nnumber, in the format \\fCfile.ext;##\\fR.  By default the ``\\fC;##\\fR'' version\nnumbers are stripped, but this option allows them to be retained.  (On\nfile systems that limit filenames to particularly short lengths, the version\nnumbers may be truncated or stripped regardless of this option.)\n.TP\n.B \\-W\n[only when WILD_STOP_AT_DIR compile-time option enabled]\nmodifies the pattern matching routine so that both `?' (single-char wildcard)\nand `*' (multi-char wildcard) do not match the directory separator character\n`/'.  (The two-character sequence ``**'' acts as a multi-char wildcard that\nincludes the directory separator in its matched characters.)  Examples:\n.PP\n.EX\n    \"*.c\" matches \"foo.c\" but not \"mydir/foo.c\"\n    \"**.c\" matches both \"foo.c\" and \"mydir/foo.c\"\n    \"*/*.c\" matches \"bar/foo.c\" but not \"baz/bar/foo.c\"\n    \"??*/*\" matches \"ab/foo\" and \"abc/foo\"\n            but not \"a/foo\" or \"a/b/foo\"\n.EE\n.IP\nThis modified behaviour is equivalent to the pattern matching style\nused by the shells of some of UnZip's supported target OSs (one\nexample is Acorn RISC OS).  This option may not be available on systems\nwhere the Zip archive's internal directory separator character `/' is\nallowed as regular character in native operating system filenames.\n(Currently, UnZip uses the same pattern matching rules for both wildcard\nzipfile specifications and zip entry selection patterns in most ports.\nFor systems allowing `/' as regular filename character, the -W option\nwould not work as expected on a wildcard zipfile specification.)\n.TP\n.B \\-X\n[VMS, Unix, OS/2, NT, Tandem] restore owner/protection info (UICs and ACL\nentries) under VMS, or user and group info (UID/GID) under Unix, or access\ncontrol lists (ACLs) under certain network-enabled versions of OS/2\n(Warp Server with IBM LAN Server/Requester 3.0 to 5.0; Warp Connect with\nIBM Peer 1.0), or security ACLs under Windows NT.  In most cases this will\nrequire special system privileges, and doubling the option (\\fB\\-XX\\fP)\nunder NT instructs \\fIunzip\\fP to use privileges for extraction; but under\nUnix, for example, a user who belongs to several groups can restore files\nowned by any of those groups, as long as the user IDs match his or her own.\nNote that ordinary file attributes are always restored--this option applies\nonly to optional, extra ownership info available on some operating systems.\n[NT's access control lists do not appear to be especially compatible with\nOS/2's, so no attempt is made at cross-platform portability of access\nprivileges.  It is not clear under what conditions this would ever be\nuseful anyway.]\n.TP\n.B \\-Y\n[VMS] treat archived file name endings of ``.nnn'' (where ``nnn'' is a\ndecimal  number) as if they were VMS version numbers (``;nnn'').\n(The default is to treat them as file types.)  Example:\n.EX\n     \"a.b.3\" -> \"a.b;3\".\n.EE\n.TP\n.B \\-$\n.\\\" Amiga support possible eventually, but not yet\n[MS-DOS, OS/2, NT] restore the volume label if the extraction medium is\nremovable (e.g., a diskette).  Doubling the option (\\fB\\-$$\\fP) allows fixed\nmedia (hard disks) to be labelled as well.  By default, volume labels are\nignored.\n.IP \\fB\\-/\\fP\\ \\fIextensions\\fP\n[Acorn only] overrides the extension list supplied by Unzip$Ext environment\nvariable. During extraction, filename extensions that match one of the items\nin this extension list are swapped in front of the base name of the extracted\nfile.\n.TP\n.B \\-:\n[all but Acorn, VM/CMS, MVS, Tandem] allows to extract archive members into\nlocations outside of the current `` extraction root folder''. For security\nreasons, \\fIunzip\\fP normally removes ``parent dir'' path components\n(``../'') from the names of extracted file.  This safety feature (new for\nversion 5.50) prevents \\fIunzip\\fP from accidentally writing files to\n``sensitive'' areas outside the active extraction folder tree head.  The\n\\fB\\-:\\fP option lets \\fIunzip\\fP switch back to its previous, more liberal\nbehaviour, to allow exact extraction of (older) archives that used ``../''\ncomponents to create multiple directory trees at the level of the current\nextraction folder.  This option does not enable writing explicitly to the\nroot directory (``/'').  To achieve this, it is necessary to set the\nextraction target folder to root (e.g. \\fB\\-d / \\fP).  However, when the\n\\fB\\-:\\fP option is specified, it is still possible to implicitly write to\nthe root directory by specifying enough ``../'' path components within the\nzip archive.\nUse this option with extreme caution.\n.TP\n.B \\-^\n[Unix only] allow control characters in names of extracted ZIP archive\nentries.  On Unix, a file name may contain any (8-bit) character code with\nthe two exception '/' (directory delimiter) and NUL (0x00, the C string\ntermination indicator), unless the specific file system has more\nrestrictive conventions.  Generally, this allows to embed ASCII control\ncharacters (or even sophisticated control sequences) in file names, at least\non 'native' Unix file systems.  However, it may be highly suspicious to\nmake use of this Unix \"feature\".  Embedded control characters in file names\nmight have nasty side effects when displayed on screen by some listing code\nwithout sufficient filtering.  And, for ordinary users, it may be difficult\nto handle such file names (e.g. when trying to specify it for open, copy,\nmove, or delete operations).  Therefore, \\fIunzip\\fP applies a filter by\ndefault that removes potentially dangerous control characters from the\nextracted file names. The \\fB-^\\fP option allows to override this filter\nin the rare case that embedded filename control characters are to be\nintentionally restored.\n.TP\n.B \\-2\n[VMS] force unconditionally conversion of file names to ODS2-compatible\nnames.  The default is to exploit the destination file system, preserving\ncase and extended file name characters on an ODS5 destination file system;\nand applying the ODS2-compatibility file name filtering on an ODS2 destination\nfile system.\n.PD\n.\\\" =========================================================================\n.SH \"ENVIRONMENT OPTIONS\"\n\\fIunzip\\fP's default behavior may be modified via options placed in\nan environment variable.  This can be done with any option, but it\nis probably most useful with the \\fB\\-a\\fP, \\fB\\-L\\fP, \\fB\\-C\\fP, \\fB\\-q\\fP,\n\\fB\\-o\\fP, or \\fB\\-n\\fP modifiers:  make \\fIunzip\\fP auto-convert text\nfiles by default, make it convert filenames from uppercase systems to\nlowercase, make it match names case-insensitively, make it quieter,\nor make it always overwrite or never overwrite files as it extracts\nthem.  For example, to make \\fIunzip\\fP act as quietly as possible, only\nreporting errors, one would use one of the following commands:\n.TP\n  Unix Bourne shell:\nUNZIP=\\-qq; export UNZIP\n.TP\n  Unix C shell:\nsetenv UNZIP \\-qq\n.TP\n  OS/2 or MS-DOS:\nset UNZIP=\\-qq\n.TP\n  VMS (quotes for \\fIlowercase\\fP):\ndefine UNZIP_OPTS \"\\-qq\"\n.PP\nEnvironment options are, in effect, considered to be just like any other\ncommand-line options, except that they are effectively the first options\non the command line.  To override an environment option, one may use the\n``minus operator'' to remove it.  For instance, to override one of the\nquiet-flags in the example above, use the command\n.PP\n.EX\nunzip \\-\\-q[\\fIother options\\fP] zipfile\n.EE\n.PP\nThe first hyphen is the normal\nswitch character, and the second is a minus sign, acting on the q option.\nThus the effect here is to cancel one quantum of quietness.  To cancel\nboth quiet flags, two (or more) minuses may be used:\n.PP\n.EX\nunzip \\-t\\-\\-q zipfile\nunzip \\-\\-\\-qt zipfile\n.EE\n.PP\n(the two are equivalent).  This may seem awkward\nor confusing, but it is reasonably intuitive:  just ignore the first\nhyphen and go from there.  It is also consistent with the behavior of\nUnix \\fInice\\fP(1).\n.PP\nAs suggested by the examples above, the default variable names are UNZIP_OPTS\nfor VMS (where the symbol used to install \\fIunzip\\fP as a foreign command\nwould otherwise be confused with the environment variable), and UNZIP\nfor all other operating systems.  For compatibility with \\fIzip\\fP(1L),\nUNZIPOPT is also accepted (don't ask).  If both UNZIP and UNZIPOPT\nare defined, however, UNZIP takes precedence.  \\fIunzip\\fP's diagnostic\noption (\\fB\\-v\\fP with no zipfile name) can be used to check the values\nof all four possible \\fIunzip\\fP and \\fIzipinfo\\fP environment variables.\n.PP\nThe timezone variable (TZ) should be set according to the local timezone\nin order for the \\fB\\-f\\fP and \\fB\\-u\\fP to operate correctly.  See the\ndescription of \\fB\\-f\\fP above for details.  This variable may also be\nnecessary to get timestamps of extracted files to be set correctly.\nThe WIN32 (Win9x/ME/NT4/2K/XP/2K3) port of \\fIunzip\\fP gets the timezone\nconfiguration from the registry, assuming it is correctly set in the\nControl Panel.  The TZ variable is ignored for this port.\n.PD\n.\\\" =========================================================================\n.SH DECRYPTION\nEncrypted archives are fully supported by Info-ZIP software, but due to\nUnited States export restrictions, de-/encryption support might be disabled\nin your compiled binary.  However, since spring 2000, US export restrictions\nhave been liberated, and our source archives do now include full crypt code.\nIn case you need binary distributions with crypt support enabled, see the\nfile ``WHERE'' in any Info-ZIP source or binary distribution for locations\nboth inside and outside the US.\n.PP\nSome compiled versions of \\fIunzip\\fP may not support decryption.\nTo check a version for crypt support, either attempt to test or extract\nan encrypted archive, or else check \\fIunzip\\fP's diagnostic\nscreen (see the \\fB\\-v\\fP option above) for ``\\fC[decryption]\\fR'' as one\nof the special compilation options.\n.PP\nAs noted above, the \\fB\\-P\\fP option may be used to supply a password on\nthe command line, but at a cost in security.  The preferred decryption\nmethod is simply to extract normally; if a zipfile member is encrypted,\n\\fIunzip\\fP will prompt for the password without echoing what is typed.\n\\fIunzip\\fP continues to use the same password as long as it appears to be\nvalid, by testing a 12-byte header on each file.  The correct password will\nalways check out against the header, but there is a 1-in-256 chance that an\nincorrect password will as well.  (This is a security feature of the PKWARE\nzipfile format; it helps prevent brute-force attacks that might otherwise\ngain a large speed advantage by testing only the header.)  In the case that\nan incorrect password is given but it passes the header test anyway, either\nan incorrect CRC will be generated for the extracted data or else \\fIunzip\\fP\nwill fail during the extraction because the ``decrypted'' bytes do not\nconstitute a valid compressed data stream.\n.PP\nIf the first password fails the header check on some file, \\fIunzip\\fP will\nprompt for another password, and so on until all files are extracted.  If\na password is not known, entering a null password (that is, just a carriage\nreturn or ``Enter'') is taken as a signal to skip all further prompting.\nOnly unencrypted files in the archive(s) will thereafter be extracted.  (In\nfact, that's not quite true; older versions of \\fIzip\\fP(1L) and\n\\fIzipcloak\\fP(1L) allowed null passwords, so \\fIunzip\\fP checks each encrypted\nfile to see if the null password works.  This may result in ``false positives''\nand extraction errors, as noted above.)\n.PP\nArchives encrypted with 8-bit passwords (for example, passwords with accented\nEuropean characters) may not be portable across systems and/or other\narchivers.  This problem stems from the use of multiple encoding methods for\nsuch characters, including Latin-1 (ISO 8859-1) and OEM code page 850.\nDOS \\fIPKZIP\\fP 2.04g uses the OEM code page; Windows \\fIPKZIP\\fP 2.50\nuses Latin-1 (and is therefore incompatible with DOS \\fIPKZIP\\fP); Info-ZIP\nuses the OEM code page on DOS, OS/2 and Win3.x ports but ISO coding\n(Latin-1 etc.) everywhere else; and Nico Mak's \\fIWinZip\\fP 6.x does not\nallow 8-bit passwords at all.  \\fIUnZip\\fP 5.3 (or newer) attempts to use\nthe default character set first (e.g., Latin-1), followed by the alternate\none (e.g., OEM code page) to test passwords.  On EBCDIC systems, if both\nof these fail, EBCDIC encoding will be tested as a last resort.  (EBCDIC is\nnot tested on non-EBCDIC systems, because there are no known archivers\nthat encrypt using EBCDIC encoding.)  ISO character encodings other than\nLatin-1 are not supported.  The new addition of (partially) Unicode (resp.\nUTF-8) support in \\fIUnZip\\fP 6.0 has not yet been adapted to the encryption\npassword handling in \\fIunzip\\fP.  On systems that use UTF-8 as native\ncharacter encoding, \\fIunzip\\fP simply tries decryption with the native\nUTF-8 encoded password; the built-in attempts to check the password in\ntranslated encoding have not yet been adapted for UTF-8 support and\nwill consequently fail.\n.PD\n.\\\" =========================================================================\n.SH EXAMPLES\nTo use \\fIunzip\\fP to extract all members of the archive \\fIletters.zip\\fP\ninto the current directory and subdirectories below it, creating any\nsubdirectories as necessary:\n.PP\n.EX\nunzip letters\n.EE\n.PP\nTo extract all members of \\fIletters.zip\\fP into the current directory only:\n.PP\n.EX\nunzip -j letters\n.EE\n.PP\nTo test \\fIletters.zip\\fP, printing only a summary message indicating\nwhether the archive is OK or not:\n.PP\n.EX\nunzip -tq letters\n.EE\n.PP\nTo test \\fIall\\fP zipfiles in the current directory, printing only the\nsummaries:\n.PP\n.EX\nunzip -tq \\e*.zip\n.EE\n.PP\n(The backslash before the asterisk is only required if the shell expands\nwildcards, as in Unix; double quotes could have been used instead, as in\nthe source examples below.)\\ \\ To extract to standard output all members of\n\\fIletters.zip\\fP whose names end in \\fI.tex\\fP, auto-converting to the\nlocal end-of-line convention and piping the output into \\fImore\\fP(1):\n.PP\n.EX\nunzip \\-ca letters \\e*.tex | more\n.EE\n.PP\nTo extract the binary file \\fIpaper1.dvi\\fP to standard output and pipe it\nto a printing program:\n.PP\n.EX\nunzip \\-p articles paper1.dvi | dvips\n.EE\n.PP\nTo extract all FORTRAN and C source files--*.f, *.c, *.h, and Makefile--into\nthe /tmp directory:\n.PP\n.EX\nunzip source.zip \"*.[fch]\" Makefile -d /tmp\n.EE\n.PP\n(the double quotes are necessary only in Unix and only if globbing is turned\non).  To extract all FORTRAN and C source files, regardless of case (e.g.,\nboth *.c and *.C, and any makefile, Makefile, MAKEFILE or similar):\n.PP\n.EX\nunzip \\-C source.zip \"*.[fch]\" makefile -d /tmp\n.EE\n.PP\nTo extract any such files but convert any uppercase MS-DOS or VMS names to\nlowercase and convert the line-endings of all of the files to the local\nstandard (without respect to any files that might be marked ``binary''):\n.PP\n.EX\nunzip \\-aaCL source.zip \"*.[fch]\" makefile -d /tmp\n.EE\n.PP\nTo extract only newer versions of the files already in the current\ndirectory, without querying (NOTE:  be careful of unzipping in one timezone a\nzipfile created in another--ZIP archives other than those created by Zip 2.1\nor later contain no timezone information, and a ``newer'' file from an eastern\ntimezone may, in fact, be older):\n.PP\n.EX\nunzip \\-fo sources\n.EE\n.PP\nTo extract newer versions of the files already in the current directory and\nto create any files not already there (same caveat as previous example):\n.PP\n.EX\nunzip \\-uo sources\n.EE\n.PP\nTo display a diagnostic screen showing which \\fIunzip\\fP and \\fIzipinfo\\fP\noptions are stored in environment variables, whether decryption support was\ncompiled in, the compiler with which \\fIunzip\\fP was compiled, etc.:\n.PP\n.EX\nunzip \\-v\n.EE\n.PP\nIn the last five examples, assume that UNZIP or UNZIP_OPTS is set to -q.\nTo do a singly quiet listing:\n.PP\n.EX\nunzip \\-l file.zip\n.EE\n.PP\nTo do a doubly quiet listing:\n.PP\n.EX\nunzip \\-ql file.zip\n.EE\n.PP\n(Note that the ``\\fC.zip\\fR'' is generally not necessary.)  To do a standard\nlisting:\n.PP\n.EX\nunzip \\-\\-ql file.zip\n.EE\nor\n.EX\nunzip \\-l\\-q file.zip\n.EE\nor\n.EX\nunzip \\-l\\-\\-q file.zip\n.EE\n\\fR(Extra minuses in options don't hurt.)\n.PD\n.\\\" =========================================================================\n.SH TIPS\nThe current maintainer, being a lazy sort, finds it very useful to define\na pair of aliases:  \\fCtt\\fR for ``\\fCunzip \\-tq\\fR'' and \\fCii\\fR for\n``\\fCunzip \\-Z\\fR'' (or ``\\fCzipinfo\\fR'').  One may then simply type\n``\\fCtt zipfile\\fR'' to test an archive, something that is worth making a\nhabit of doing.  With luck \\fIunzip\\fP will report ``\\fCNo errors detected\nin compressed data of zipfile.zip\\fR,'' after which one may breathe a sigh\nof relief.\n.PP\nThe maintainer also finds it useful to set the UNZIP environment variable\nto ``\\fC\\-aL\\fR'' and is tempted to add ``\\fC\\-C\\fR'' as well.  His ZIPINFO\nvariable is set to ``\\fC\\-z\\fR''.\n.PD\n.\\\" =========================================================================\n.SH DIAGNOSTICS\nThe exit status (or error level) approximates the exit codes defined by PKWARE\nand takes on the following values, except under VMS:\n.RS\n.IP 0\nnormal; no errors or warnings detected.\n.IP 1\none or more warning errors were encountered, but processing completed\nsuccessfully anyway.  This includes zipfiles where one or more files\nwas skipped due to unsupported compression method or encryption with an\nunknown password.\n.IP 2\na generic error in the zipfile format was detected.  Processing may have\ncompleted successfully anyway; some broken zipfiles created by other\narchivers have simple work-arounds.\n.IP 3\na severe error in the zipfile format was detected.  Processing probably\nfailed immediately.\n.IP 4\n\\fIunzip\\fP was unable to allocate memory for one or more buffers during\nprogram initialization.\n.IP 5\n\\fIunzip\\fP was unable to allocate memory or unable to obtain a tty to read\nthe decryption password(s).\n.IP 6\n\\fIunzip\\fP was unable to allocate memory during decompression to disk.\n.IP 7\n\\fIunzip\\fP was unable to allocate memory during in-memory decompression.\n.IP 8\n[currently not used]\n.IP 9\nthe specified zipfiles were not found.\n.IP 10\ninvalid options were specified on the command line.\n.IP 11\nno matching files were found.\n.IP 50\nthe disk is (or was) full during extraction.\n.IP 51\nthe end of the ZIP archive was encountered prematurely.\n.IP 80\nthe user aborted \\fIunzip\\fP prematurely with control-C (or similar)\n.IP 81\ntesting or extraction of one or more files failed due to unsupported\ncompression methods or unsupported decryption.\n.IP 82\nno files were found due to bad decryption password(s).  (If even one file is\nsuccessfully processed, however, the exit status is 1.)\n.RE\n.PP\nVMS interprets standard Unix (or PC) return values as other, scarier-looking\nthings, so \\fIunzip\\fP instead maps them into VMS-style status codes.  The\ncurrent mapping is as follows:   1 (success) for normal exit, 0x7fff0001\nfor warning errors, and (0x7fff000? + 16*normal_unzip_exit_status) for all\nother errors, where the `?' is 2 (error) for \\fIunzip\\fP values 2, 9-11 and\n80-82, and 4 (fatal error) for the remaining ones (3-8, 50, 51).  In addition,\nthere is a compilation option to expand upon this behavior:  defining\nRETURN_CODES results in a human-readable explanation of what the error\nstatus means.\n.PD\n.\\\" =========================================================================\n.SH BUGS\nMulti-part archives are not yet supported, except in conjunction with\n\\fIzip\\fP.  (All parts must be concatenated together in order, and then\n``\\fCzip \\-F\\fR'' (for \\fIzip 2.x\\fP) or ``\\fCzip \\-FF\\fR'' (for\n\\fIzip 3.x\\fP) must be performed on the concatenated archive in order to\n``fix'' it.  Also, \\fIzip 3.0\\fP and later can combine multi-part (split)\narchives into a combined single-file archive using ``\\fCzip \\-s\\- inarchive\n-O outarchive\\fR''.  See the \\fIzip 3\\fP manual page for more information.)\nThis will definitely be corrected in the next major release.\n.PP\nArchives read from standard input are not yet supported, except with\n\\fIfunzip\\fP (and then only the first member of the archive can be extracted).\n.PP\nArchives encrypted with 8-bit passwords (e.g., passwords with accented\nEuropean characters) may not be portable across systems and/or other\narchivers.  See the discussion in \\fBDECRYPTION\\fP above.\n.PP\n\\fIunzip\\fP's \\fB\\-M\\fP (``more'') option tries to take into account automatic\nwrapping of long lines. However, the code may fail to detect the correct\nwrapping locations. First, TAB characters (and similar control sequences) are\nnot taken into account, they are handled as ordinary printable characters.\nSecond, depending on the actual system / OS port, \\fIunzip\\fP may not detect\nthe true screen geometry but rather rely on \"commonly used\" default dimensions.\nThe correct handling of tabs would require the implementation of a query for\nthe actual tabulator setup on the output console.\n.PP\nDates, times and permissions of stored directories are not restored except\nunder Unix. (On Windows NT and successors, timestamps are now restored.)\n.PP\n[MS-DOS] When extracting or testing files from an archive on a defective\nfloppy diskette, if the ``Fail'' option is chosen from DOS's ``Abort, Retry,\nFail?'' message, older versions of \\fIunzip\\fP may hang the system, requiring\na reboot.  This problem appears to be fixed, but control-C (or control-Break)\ncan still be used to terminate \\fIunzip\\fP.\n.PP\nUnder DEC Ultrix, \\fIunzip\\fP would sometimes fail on long zipfiles (bad CRC,\nnot always reproducible).  This was apparently due either to a hardware bug\n(cache memory) or an operating system bug (improper handling of page faults?).\nSince Ultrix has been abandoned in favor of Digital Unix (OSF/1), this may not\nbe an issue anymore.\n.PP\n[Unix] Unix special files such as FIFO buffers (named pipes), block devices\nand character devices are not restored even if they are somehow represented\nin the zipfile, nor are hard-linked files relinked.  Basically the only file\ntypes restored by \\fIunzip\\fP are regular files, directories and symbolic\n(soft) links.\n.PP\n[OS/2] Extended attributes for existing directories are only updated if the\n\\fB\\-o\\fP (``overwrite all'') option is given.  This is a limitation of the\noperating system; because directories only have a creation time associated\nwith them, \\fIunzip\\fP has no way to determine whether the stored attributes\nare newer or older than those on disk.  In practice this may mean a two-pass\napproach is required:  first unpack the archive normally (with or without\nfreshening/updating existing files), then overwrite just the directory entries\n(e.g., ``\\fCunzip -o foo */\\fR'').\n.PP\n[VMS] When extracting to another directory, only the \\fI[.foo]\\fP syntax is\naccepted for the \\fB\\-d\\fP option; the simple Unix \\fIfoo\\fP syntax is\nsilently ignored (as is the less common VMS \\fIfoo.dir\\fP syntax).\n.PP\n[VMS] When the file being extracted already exists, \\fIunzip\\fP's query only\nallows skipping, overwriting or renaming; there should additionally be a\nchoice for creating a new version of the file.  In fact, the ``overwrite''\nchoice does create a new version; the old version is not overwritten or\ndeleted.\n.PD\n.\\\" =========================================================================\n.SH \"SEE ALSO\"\n\\fIfunzip\\fP(1L), \\fIzip\\fP(1L), \\fIzipcloak\\fP(1L), \\fIzipgrep\\fP(1L),\n\\fIzipinfo\\fP(1L), \\fIzipnote\\fP(1L), \\fIzipsplit\\fP(1L)\n.PD\n.\\\" =========================================================================\n.SH URL\nThe Info-ZIP home page is currently at\n.EX\n\\fChttp://www.info-zip.org/pub/infozip/\\fR\n.EE\nor\n.EX\n\\fCftp://ftp.info-zip.org/pub/infozip/\\fR .\n.EE\n.PD\n.\\\" =========================================================================\n.SH AUTHORS\nThe primary Info-ZIP authors (current semi-active members of the Zip-Bugs\nworkgroup) are:  Ed Gordon (Zip, general maintenance, shared code, Zip64,\nWin32, Unix, Unicode); Christian Spieler (UnZip maintenance coordination,\nVMS, MS-DOS, Win32, shared code, general Zip and UnZip integration and\noptimization); Onno van der Linden (Zip); Mike White (Win32, Windows GUI,\nWindows DLLs); Kai Uwe Rommel (OS/2, Win32); Steven M. Schweda (VMS, Unix,\nsupport of new features); Paul Kienitz (Amiga, Win32, Unicode); Chris\nHerborth (BeOS, QNX, Atari); Jonathan Hudson (SMS/QDOS); Sergio Monesi\n(Acorn RISC OS); Harald Denker (Atari, MVS); John Bush (Solaris, Amiga);\nHunter Goatley (VMS, Info-ZIP Site maintenance); Steve Salisbury (Win32);\nSteve Miller (Windows CE GUI), Johnny Lee (MS-DOS, Win32, Zip64); and Dave\nSmith (Tandem NSK).\n.PP\nThe following people were former members of the Info-ZIP development group\nand provided major contributions to key parts of the current code:\nGreg ``Cave Newt'' Roelofs (UnZip, unshrink decompression);\nJean-loup Gailly (deflate compression);\nMark Adler (inflate decompression, fUnZip).\n.PP\nThe author of the original unzip code upon which Info-ZIP's was based\nis Samuel H. Smith; Carl Mascott did the first Unix port; and David P.\nKirschbaum organized and led Info-ZIP in its early days with Keith Petersen\nhosting the original mailing list at WSMR-SimTel20.  The full list of\ncontributors to UnZip has grown quite large; please refer to the CONTRIBS\nfile in the UnZip source distribution for a relatively complete version.\n.PD\n.\\\" =========================================================================\n.SH VERSIONS\n.ta \\w'vx.xxnn'u +\\w'fall 1989'u+3n\n.PD 0\n.IP \"v1.2\\t15 Mar 89\" \\w'\\t\\t'u\nSamuel H. Smith\n.IP \"v2.0\\t\\ 9 Sep 89\"\nSamuel H. Smith\n.IP \"v2.x\\tfall 1989\"\nmany Usenet contributors\n.IP \"v3.0\\t\\ 1 May 90\"\nInfo-ZIP (DPK, consolidator)\n.IP \"v3.1\\t15 Aug 90\"\nInfo-ZIP (DPK, consolidator)\n.IP \"v4.0\\t\\ 1 Dec 90\"\nInfo-ZIP (GRR, maintainer)\n.IP \"v4.1\\t12 May 91\"\nInfo-ZIP\n.IP \"v4.2\\t20 Mar 92\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.0\\t21 Aug 92\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.01\\t15 Jan 93\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.1\\t\\ 7 Feb 94\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.11\\t\\ 2 Aug 94\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.12\\t28 Aug 94\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.2\\t30 Apr 96\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.3\\t22 Apr 97\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.31\\t31 May 97\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.32\\t\\ 3 Nov 97\"\nInfo-ZIP (Zip-Bugs subgroup, GRR)\n.IP \"v5.4\\t28 Nov 98\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v5.41\\t16 Apr 00\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v5.42\\t14 Jan 01\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v5.5\\t17 Feb 02\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v5.51\\t22 May 04\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v5.52\\t28 Feb 05\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.IP \"v6.0\\t20 Apr 09\"\nInfo-ZIP (Zip-Bugs subgroup, SPC)\n.PD\n"
  },
  {
    "path": "deps/infozip/unzip60/man/unzipsfx.1",
    "content": ".\\\"  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\"  See the accompanying file LICENSE, version 2009-Jan-02 or later\n.\\\"  (the contents of which are also included in unzip.h) for terms of use.\n.\\\"  If, for some reason, all these files are missing, the Info-ZIP license\n.\\\"  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\"\n.\\\" unzipsfx.1 by Greg Roelofs\n.\\\"\n.\\\" =========================================================================\n.\\\" define .EX/.EE (for multiline user-command examples; normal Courier font)\n.de EX\n.in +4n\n.nf\n.ft CW\n..\n.de EE\n.ft R\n.fi\n.in -4n\n..\n.\\\" =========================================================================\n.TH UNZIPSFX 1L \"20 April 2009 (v6.0)\" \"Info-ZIP\"\n.SH NAME\nunzipsfx \\- self-extracting stub for prepending to ZIP archives\n.PD\n.SH SYNOPSIS\n\\fB<name of unzipsfx+archive combo>\\fP [\\fB\\-cfptuz\\fP[\\fBajnoqsCLV$\\fP]]\n[\\fIfile(s)\\fP\\ .\\|.\\|. [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP\\ .\\|.\\|.]]\n.PD\n.\\\" =========================================================================\n.SH DESCRIPTION\n\\fIunzipsfx\\fP is a modified version of \\fIunzip\\fP(1L) designed to be\nprepended to existing ZIP archives in order to form self-extracting archives.\nInstead of taking its first non-flag argument to be the zipfile(s) to be\nextracted, \\fIunzipsfx\\fP seeks itself under the name by which it was invoked\nand tests or extracts the contents of the appended archive.  Because the\nexecutable stub adds bulk to the archive (the whole purpose of which is to\nbe as small as possible), a number of the less-vital capabilities in regular\n\\fIunzip\\fP have been removed.  Among these are the usage (or help) screen,\nthe listing and diagnostic functions (\\fB\\-l\\fP and \\fB\\-v\\fP), the ability\nto decompress older compression formats (the ``reduce,'' ``shrink'' and\n``implode'' methods).  The ability to extract to a directory other than\nthe current one can be selected as a compile-time option, which is now enabled\nby default since UnZipSFX version 5.5.  Similarly, decryption is supported as\na compile-time option but should be avoided unless the attached archive\ncontains encrypted files. Starting with release 5.5, another compile-time\noption adds a simple ``run command after extraction'' feature.  This feature\nis currently incompatible with the ``extract to different directory''\nfeature and remains disabled by default.\n.PP\n\\fBNote that\nself-extracting archives made with\\fP \\fIunzipsfx\\fP \\fBare no more (or less)\nportable across different operating systems than is\nthe\\fP \\fIunzip\\fP \\fBexecutable itself.\\fP  In general a self-extracting\narchive made on\na particular Unix system, for example, will only self-extract under the same\nflavor of Unix.  Regular \\fIunzip\\fP may still be used to extract the\nembedded archive as with any normal zipfile, although it will generate\na harmless warning about extra bytes at the beginning of the zipfile.\n\\fIDespite this\\fP, however, the self-extracting archive is technically\n\\fInot\\fP a valid ZIP archive, and PKUNZIP may be unable to test or extract\nit.  This limitation is due to the simplistic manner in which the archive\nis created; the internal directory structure is not updated to reflect the\nextra bytes prepended to the original zipfile.\n.PD\n.\\\" =========================================================================\n.SH ARGUMENTS\n.IP [\\fIfile(s)\\fP]\nAn optional list of archive members to be processed.\nRegular expressions (wildcards) similar to those in Unix \\fIegrep\\fP(1)\nmay be used to match multiple members.  These wildcards may contain:\n.RS\n.IP *\nmatches a sequence of 0 or more characters\n.IP ?\nmatches exactly 1 character\n.IP [.\\|.\\|.]\nmatches any single character found inside the brackets; ranges are specified\nby a beginning character, a hyphen, and an ending character.  If an exclamation\npoint or a caret (`!' or `^') follows the left bracket, then the range of\ncharacters within the brackets is complemented (that is, anything \\fIexcept\\fP\nthe characters inside the brackets is considered a match).\n.RE\n.IP\n(Be sure to quote any character that might otherwise be interpreted or\nmodified by the operating system, particularly under Unix and VMS.)\n.IP [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP]\nAn optional list of archive members to be excluded from processing.\nSince wildcard characters match directory separators (`/'), this option\nmay be used to exclude any files that are in subdirectories.  For\nexample, ``\\fCfoosfx *.[ch] -x */*\\fR'' would extract all C source files\nin the main directory, but none in any subdirectories.  Without the \\fB\\-x\\fP\noption, all C source files in all directories within the zipfile would be\nextracted.\n.PP\nIf \\fIunzipsfx\\fP is compiled with SFX_EXDIR defined, the following option\nis also enabled:\n.IP [\\fB\\-d\\fP\\ \\fIexdir\\fP]\nAn optional directory to which to extract files.  By default, all files\nand subdirectories are recreated in the current directory; the \\fB\\-d\\fP\noption allows extraction in an arbitrary directory (always assuming one\nhas permission to write to the directory).  The option and directory may\nbe concatenated without any white space between them, but note that this\nmay cause normal shell behavior to be suppressed.  In particular,\n``\\fC\\-d\\ ~\\fR'' (tilde) is expanded by Unix C shells into the name\nof the user's home directory, but ``\\fC\\-d~\\fR'' is treated as a\nliteral subdirectory ``\\fB~\\fP'' of the current directory.\n.PD\n.\\\" =========================================================================\n.SH OPTIONS\n\\fIunzipsfx\\fP supports the following \\fIunzip\\fP(1L) options:  \\fB\\-c\\fP\nand \\fB\\-p\\fP (extract to standard output/screen), \\fB\\-f\\fP and \\fB\\-u\\fP\n(freshen and update existing files upon extraction), \\fB\\-t\\fP (test\narchive) and \\fB\\-z\\fP (print archive comment).  All normal listing options\n(\\fB\\-l\\fP, \\fB\\-v\\fP and \\fB\\-Z\\fP) have been removed, but the testing\noption (\\fB\\-t\\fP) may be used as a ``poor man's'' listing.  Alternatively,\nthose creating self-extracting archives may wish to include a short listing\nin the zipfile comment.\n.PP\nSee \\fIunzip\\fP(1L) for a more complete description of these options.\n.PD\n.\\\" =========================================================================\n.SH MODIFIERS\n\\fIunzipsfx\\fP currently supports all \\fIunzip\\fP(1L) modifiers:  \\fB\\-a\\fP\n(convert text files), \\fB\\-n\\fP (never overwrite), \\fB\\-o\\fP (overwrite\nwithout prompting), \\fB\\-q\\fP (operate quietly), \\fB\\-C\\fP (match names\ncase-insensitively), \\fB\\-L\\fP (convert uppercase-OS names to lowercase),\n\\fB\\-j\\fP (junk paths) and \\fB\\-V\\fP (retain version numbers); plus the\nfollowing operating-system specific options:  \\fB\\-X\\fP (restore VMS\nowner/protection info), \\fB\\-s\\fP (convert spaces in filenames to underscores\n[DOS, OS/2, NT]) and \\fB\\-$\\fP (restore volume label [DOS, OS/2, NT, Amiga]).\n.PP\n(Support for regular ASCII text-conversion may be removed in future versions,\nsince it is simple enough for the archive's creator to ensure that text\nfiles have the appropriate format for the local OS.  EBCDIC conversion will\nof course continue to be supported since the zipfile format implies ASCII\nstorage of text files.)\n.PP\nSee \\fIunzip\\fP(1L) for a more complete description of these modifiers.\n.PD\n.\\\" =========================================================================\n.SH \"ENVIRONMENT OPTIONS\"\n\\fIunzipsfx\\fP uses the same environment variables as \\fIunzip\\fP(1L) does,\nalthough this is likely to be an issue only for the person creating and\ntesting the self-extracting archive.  See \\fIunzip\\fP(1L) for details.\n.PD\n.\\\" =========================================================================\n.SH DECRYPTION\nDecryption is supported exactly as in \\fIunzip\\fP(1L); that is, interactively\nwith a non-echoing prompt for the password(s).  See \\fIunzip\\fP(1L) for\ndetails.  Once again, note that if the archive has no encrypted files there\nis no reason to use a version of \\fIunzipsfx\\fP with decryption support;\nthat only adds to the size of the archive.\n.PD\n.\\\" =========================================================================\n.SH AUTORUN COMMAND\nWhen \\fIunzipsfx\\fP was compiled with CHEAP_SFX_AUTORUN defined, a simple\n``command autorun'' feature is supported. You may enter a command into the\nZip archive comment, using the following format:\n.PP\n.EX\n$AUTORUN$>[command line string]\n.EE\n.PP\nWhen \\fIunzipsfx\\fP recognizes the ``$AUTORUN$>'' token at the beginning\nof the Zip archive comment, the remainder of the first line of the comment\n(until the first newline character) is passed as a shell command to the\noperating system using the C rtl ``system'' function. Before executing\nthe command, \\fIunzipsfx\\fP displays the command on the console and prompts\nthe user for confirmation.  When the user has switched off prompting by\nspecifying the \\fB-q\\fP option, autorun commands are never executed.\n.PP\nIn case the archive comment contains additional lines of text, the remainder\nof the archive comment following the first line is displayed normally, unless\nquiet operation was requested by supplying a \\fB-q\\fP option.\n.PD\n.\\\" =========================================================================\n.SH EXAMPLES\nTo create a self-extracting archive \\fIletters\\fP from a regular zipfile\n\\fIletters.zip\\fP and change the new archive's permissions to be\nworld-executable under Unix:\n.PP\n.EX\ncat unzipsfx letters.zip > letters\nchmod 755 letters\nzip -A letters\n.EE\n.PP\nTo create the same archive under MS-DOS, OS/2 or NT (note the use of the\n\\fB/b\\fP [binary] option to the \\fIcopy\\fP command):\n.PP\n.EX\ncopy /b unzipsfx.exe+letters.zip letters.exe\nzip -A letters.exe\n.EE\n.PP\nUnder VMS:\n.PP\n.EX\ncopy unzipsfx.exe,letters.zip letters.exe\nletters == \"$currentdisk:[currentdir]letters.exe\"\nzip -A letters.exe\n.EE\n.PP\n(The VMS \\fIappend\\fP command may also be used.  The second command installs\nthe new program as a ``foreign command'' capable of taking arguments.  The\nthird line assumes that Zip is already installed as a foreign command.)\nUnder AmigaDOS:\n.PP\n.EX\nMakeSFX letters letters.zip UnZipSFX\n.EE\n.PP\n(MakeSFX is included with the UnZip source distribution and with Amiga\nbinary distributions.  ``\\fCzip -A\\fR'' doesn't work on Amiga self-extracting\narchives.)\nTo test (or list) the newly created self-extracting archive:\n.PP\n.EX\nletters \\-t\n.EE\n.PP\nTo test \\fIletters\\fP quietly, printing only a summary message indicating\nwhether the archive is OK or not:\n.PP\n.EX\nletters \\-tqq\n.EE\n.PP\nTo extract the complete contents into the current directory, recreating all\nfiles and subdirectories as necessary:\n.PP\n.EX\nletters\n.EE\n.PP\nTo extract all \\fC*.txt\\fR files (in Unix quote the `*'):\n.PP\n.EX\nletters *.txt\n.EE\n.PP\nTo extract everything \\fIexcept\\fP the \\fC*.txt\\fR files:\n.PP\n.EX\nletters -x *.txt\n.EE\n.PP\nTo extract only the README file to standard output (the screen):\n.PP\n.EX\nletters -c README\n.EE\n.PP\nTo print only the zipfile comment:\n.PP\n.EX\nletters \\-z\n.EE\n.PD\n.\\\" =========================================================================\n.SH LIMITATIONS\nThe principle and fundamental limitation of \\fIunzipsfx\\fP is that it is\nnot portable across architectures or operating systems, and therefore\nneither are the resulting archives.  For some architectures there is\nlimited portability, however (e.g., between some flavors of Intel-based Unix).\n.PP\nAnother problem with the current implementation is that any archive\nwith ``junk'' prepended to the beginning technically is no longer a zipfile\n(unless \\fIzip\\fP(1) is used to adjust the zipfile offsets appropriately,\nas noted above).  \\fIunzip\\fP(1) takes note of the prepended bytes\nand ignores them since some file-transfer protocols, notably MacBinary, are\nalso known to prepend junk.  But PKWARE's archiver suite may not be able to\ndeal with the modified archive unless its offsets have been adjusted.\n.PP\n\\fIunzipsfx\\fP has no knowledge of the user's PATH, so in general an archive\nmust either be in the current directory when it is invoked, or else a full\nor relative path must be given.  If a user attempts to extract the archive\nfrom a directory in the PATH other than the current one, \\fIunzipsfx\\fP will\nprint a warning to the effect, ``can't find myself.''  This is always true\nunder Unix and may be true in some cases under MS-DOS, depending on the\ncompiler used (Microsoft C fully qualifies the program name, but other\ncompilers may not).  Under OS/2 and NT there are operating-system calls\navailable that provide the full path name, so the archive may be invoked\nfrom anywhere in the user's path.  The situation is not known for AmigaDOS,\nAtari TOS, MacOS, etc.\n.PP\nAs noted above, a number of the normal \\fIunzip\\fP(1L) functions have\nbeen removed in order to make \\fIunzipsfx\\fP smaller:  usage and diagnostic\ninfo, listing functions and extraction to other directories.  Also, only\nstored and deflated files are supported.  The latter limitation is mainly\nrelevant to those who create SFX archives, however.\n.PP\nVMS users must know how to set up self-extracting archives as foreign\ncommands in order to use any of \\fIunzipsfx\\fP's options.  This is not\nnecessary for simple extraction, but the command to do so then becomes,\ne.g., ``\\fCrun letters\\fR'' (to continue the examples given above).\n.PP\n\\fIunzipsfx\\fP on the Amiga requires the use of a special program, MakeSFX,\nin order to create working self-extracting archives; simple concatenation\ndoes not work.  (For technically oriented users, the attached archive is\ndefined as a ``debug hunk.'')  There may be compatibility problems between\nthe ROM levels of older Amigas and newer ones.\n.PP\nAll current bugs in \\fIunzip\\fP(1L) exist in \\fIunzipsfx\\fP as well.\n.PD\n.\\\" =========================================================================\n.SH DIAGNOSTICS\n\\fIunzipsfx\\fP's exit status (error level) is identical to that of\n\\fIunzip\\fP(1L); see the corresponding man page.\n.PD\n.\\\" =========================================================================\n.SH \"SEE ALSO\"\n\\fIfunzip\\fP(1L), \\fIunzip\\fP(1L), \\fIzip\\fP(1L), \\fIzipcloak\\fP(1L),\n\\fIzipgrep\\fP(1L), \\fIzipinfo\\fP(1L), \\fIzipnote\\fP(1L), \\fIzipsplit\\fP(1L)\n.PD\n.PD\n.\\\" =========================================================================\n.SH URL\nThe Info-ZIP home page is currently at\n.EX\n\\fChttp://www.info-zip.org/pub/infozip/\\fR\n.EE\nor\n.EX\n\\fCftp://ftp.info-zip.org/pub/infozip/\\fR .\n.EE\n.PD\n.\\\" =========================================================================\n.SH AUTHORS\nGreg Roelofs was responsible for the basic modifications to UnZip necessary\nto create UnZipSFX.  See \\fIunzip\\fP(1L) for the current list of Zip-Bugs\nauthors, or the file CONTRIBS in the UnZip source distribution for the\nfull list of Info-ZIP contributors.\n.PD\n"
  },
  {
    "path": "deps/infozip/unzip60/man/zipgrep.1",
    "content": ".\\\"  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\"  See the accompanying file LICENSE, version 2009-Jan-02 or later\n.\\\"  (the contents of which are also included in unzip.h) for terms of use.\n.\\\"  If, for some reason, all these files are missing, the Info-ZIP license\n.\\\"  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\"\n.\\\" zipgrep.1 by Greg Roelofs.\n.\\\"\n.\\\" =========================================================================\n.TH ZIPGREP 1L \"20 April 2009\" \"Info-ZIP\"\n.SH NAME\nzipgrep \\- search files in a ZIP archive for lines matching a pattern\n.PD\n.SH SYNOPSIS\n\\fBzipgrep\\fP [\\fBegrep_options\\fP] \\fIpattern\\fP\n\\fIfile\\fP[\\fI.zip\\fP] [\\fIfile(s)\\fP\\ .\\|.\\|.]\n[\\fB\\-x\\fP\\ \\fIxfile(s)\\fP\\ .\\|.\\|.]\n.PD\n.\\\" =========================================================================\n.SH DESCRIPTION\n\\fIzipgrep\\fP will search files within a ZIP archive for lines matching\nthe given string or pattern.  \\fIzipgrep\\fP is a shell script and requires\n\\fIegrep\\fP(1) and \\fIunzip\\fP(1L) to function.  Its output is identical to\nthat of \\fIegrep\\fP(1).\n.PD\n.\\\" =========================================================================\n.SH ARGUMENTS\n.TP\n.IP \\fIpattern\\fP\nThe pattern to be located within a ZIP archive.  Any string or regular\nexpression accepted by \\fIegrep\\fP(1) may be used.\n.IR file [ .zip ]\nPath of the ZIP archive.  (Wildcard expressions for the ZIP archive name are\nnot supported.)  If the literal filename is not found, the suffix \\fC.zip\\fR\nis appended.  Note that self-extracting ZIP files are supported, as with any\nother ZIP archive; just specify the \\fC.exe\\fR suffix (if any) explicitly.\n.IP [\\fIfile(s)\\fP]\nAn optional list of archive members to be processed, separated by spaces.\nIf no member files are specified, all members of the ZIP archive are searched.\nRegular expressions (wildcards) may be used to match multiple members:\n.RS\n.IP *\nmatches a sequence of 0 or more characters\n.IP ?\nmatches exactly 1 character\n.IP [.\\|.\\|.]\nmatches any single character found inside the brackets; ranges are specified\nby a beginning character, a hyphen, and an ending character.  If an exclamation\npoint or a caret (`!' or `^') follows the left bracket, then the range of\ncharacters within the brackets is complemented (that is, anything \\fIexcept\\fP\nthe characters inside the brackets is considered a match).\n.RE\n.IP\n(Be sure to quote any character that might otherwise be interpreted or\nmodified by the operating system.)\n.IP [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP]\nAn optional list of archive members to be excluded from processing.\nSince wildcard characters match directory separators (`/'), this option\nmay be used to exclude any files that are in subdirectories.  For\nexample, ``\\fCzipgrep grumpy foo *.[ch] -x */*\\fR'' would search for the\nstring ``grumpy'' in all C source files in the main directory of the ``foo''\narchive, but none in any subdirectories.  Without the \\fB\\-x\\fP\noption, all C source files in all directories within the zipfile would be\nsearched.\n.\\\" =========================================================================\n.SH OPTIONS\nAll options prior to the ZIP archive filename are passed to \\fIegrep\\fP(1).\n.PD\n.\\\" =========================================================================\n.SH \"SEE ALSO\"\n\\fIegrep\\fP(1), \\fIunzip\\fP(1L), \\fIzip\\fP(1L), \\fIfunzip\\fP(1L),\n\\fIzipcloak\\fP(1L), \\fIzipinfo\\fP(1L), \\fIzipnote\\fP(1L), \\fIzipsplit\\fP(1L)\n.PD\n.\\\" =========================================================================\n.SH URL\nThe Info-ZIP home page is currently at\n.EX\n\\fChttp://www.info-zip.org/pub/infozip/\\fR\n.EE\nor\n.EX\n\\fCftp://ftp.info-zip.org/pub/infozip/\\fR .\n.EE\n.PD\n.\\\" =========================================================================\n.SH AUTHORS\n\\fIzipgrep\\fP was written by Jean-loup Gailly.\n.PD\n"
  },
  {
    "path": "deps/infozip/unzip60/man/zipinfo.1",
    "content": ".\\\"  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\"  See the accompanying file LICENSE, version 2009-Jan-02 or later\n.\\\"  (the contents of which are also included in unzip.h) for terms of use.\n.\\\"  If, for some reason, all these files are missing, the Info-ZIP license\n.\\\"  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\"\n.\\\" zipinfo.1 by Greg Roelofs and others.\n.\\\"\n.\\\" =========================================================================\n.\\\" define .X macro (for long-line ZipInfo output examples; small Courier):\n.de X\n.nf\n.ft CW\n.ie n .ti -5\n.el \\{ .ti +2m\n.ps -1 \\}\n\\&\\\\$1\n.ie n .ti +5\n.el \\{ .ti -2m\n.ps +1 \\}\n.ft\n.fi\n..\n.\\\" define .EX/.EE (for multiline user-command examples; normal Courier font)\n.de EX\n.in +4n\n.nf\n.ft CW\n..\n.de EE\n.ft\n.fi\n.in -4n\n..\n.\\\" =========================================================================\n.TH ZIPINFO 1L \"20 April 2009 (v3.0)\" \"Info-ZIP\"\n.SH NAME\nzipinfo \\- list detailed information about a ZIP archive\n.PD\n.SH SYNOPSIS\n\\fBzipinfo\\fP [\\fB\\-12smlvhMtTz\\fP] \\fIfile\\fP[\\fI.zip\\fP]\n[\\fIfile(s)\\fP\\ .\\|.\\|.] [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP\\ .\\|.\\|.]\n.PP\n\\fBunzip\\fP \\fB\\-Z\\fP [\\fB\\-12smlvhMtTz\\fP] \\fIfile\\fP[\\fI.zip\\fP]\n[\\fIfile(s)\\fP\\ .\\|.\\|.] [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP\\ .\\|.\\|.]\n.PD\n.\\\" =========================================================================\n.SH DESCRIPTION\n\\fIzipinfo\\fP lists technical information about files in a ZIP archive, most\ncommonly found on MS-DOS systems.  Such information includes file access\npermissions, encryption status, type of compression, version and operating\nsystem or file system of compressing program, and the like.  The default\nbehavior (with no options) is\nto list single-line entries for each file in the archive, with header and\ntrailer lines providing summary information for the entire archive.  The\nformat is a cross between Unix ``\\fCls \\-l\\fR'' and ``\\fCunzip \\-v\\fR''\noutput.  See\n.B \"DETAILED DESCRIPTION\"\nbelow.  Note that \\fIzipinfo\\fP is the same program as \\fIunzip\\fP (under\nUnix, a link to it); on some systems, however, \\fIzipinfo\\fP support may\nhave been omitted when \\fIunzip\\fP was compiled.\n.PD\n.\\\" =========================================================================\n.SH ARGUMENTS\n.TP\n.IR file [ .zip ]\nPath of the ZIP archive(s).  If the file specification is a wildcard,\neach matching file is processed in an order determined by the operating\nsystem (or file system).  Only the filename can be a wildcard; the path\nitself cannot.  Wildcard expressions are similar to Unix \\fIegrep\\fP(1)\n(regular) expressions and may contain:\n.RS\n.IP *\nmatches a sequence of 0 or more characters\n.IP ?\nmatches exactly 1 character\n.IP [.\\|.\\|.]\nmatches any single character found inside the brackets; ranges are specified\nby a beginning character, a hyphen, and an ending character.  If an exclamation\npoint or a caret (`!' or `^') follows the left bracket, then the range of\ncharacters within the brackets is complemented (that is, anything \\fIexcept\\fP\nthe characters inside the brackets is considered a match).  To specify a\nverbatim left bracket, the three-character sequence ``[[]'' has to be used.\n.RE\n.IP\n(Be sure to quote any character that might otherwise be interpreted or\nmodified by the operating system, particularly under Unix and VMS.)  If no\nmatches are found, the specification is assumed to be a literal filename;\nand if that also fails, the suffix \\fC.zip\\fR is appended.  Note that\nself-extracting ZIP files are supported, as with any other ZIP archive;\njust specify the \\fC.exe\\fR suffix (if any) explicitly.\n.IP [\\fIfile(s)\\fP]\nAn optional list of archive members to be processed, separated by spaces.\n(VMS versions compiled with VMSCLI defined must delimit files with commas\ninstead.)\nRegular expressions (wildcards) may be used to match multiple members; see\nabove.  Again, be sure to quote expressions that would otherwise be expanded\nor modified by the operating system.\n.IP [\\fB\\-x\\fP\\ \\fIxfile(s)\\fP]\nAn optional list of archive members to be excluded from processing.\n.\\\" =========================================================================\n.SH OPTIONS\n.TP\n.B \\-1\nlist filenames only, one per line.  This option excludes all others; headers,\ntrailers and zipfile comments are never printed.  It is intended for use in\nUnix shell scripts.\n.TP\n.B \\-2\nlist filenames only, one per line, but allow headers (\\fB\\-h\\fP), trailers\n(\\fB\\-t\\fP) and zipfile comments (\\fB\\-z\\fP), as well.  This option may be\nuseful in cases where the stored filenames are particularly long.\n.TP\n.B \\-s\nlist zipfile info in short Unix ``\\fCls \\-l\\fR'' format.  This is the default\nbehavior; see below.\n.TP\n.B \\-m\nlist zipfile info in medium Unix ``\\fCls \\-l\\fR'' format.  Identical to the\n\\fB\\-s\\fP output, except that the compression factor, expressed as a\npercentage, is also listed.\n.TP\n.B \\-l\nlist zipfile info in long Unix ``\\fCls \\-l\\fR'' format.  As with \\fB\\-m\\fP\nexcept that the compressed size (in bytes) is printed instead of the\ncompression ratio.\n.TP\n.B \\-v\nlist zipfile information in verbose, multi-page format.\n.TP\n.B \\-h\nlist header line.  The archive name, actual size (in bytes) and total number\nof files is printed.\n.TP\n.B \\-M\npipe all output through an internal pager similar to the Unix \\fImore\\fP(1)\ncommand.  At the end of a screenful of output, \\fIzipinfo\\fP pauses with a\n``\\-\\-More\\-\\-'' prompt; the next screenful may be viewed by pressing the\nEnter (Return) key or the space bar.  \\fIzipinfo\\fP can be terminated by\npressing the ``q'' key and, on some systems, the Enter/Return key.  Unlike\nUnix \\fImore\\fP(1), there is no forward-searching or editing capability.\nAlso, \\fIzipinfo\\fP doesn't notice if long lines wrap at the edge of the\nscreen, effectively resulting in the printing of two or more lines and the\nlikelihood that some text will scroll off the top of the screen before being\nviewed.  On some systems the number of available lines on the screen is not\ndetected, in which case \\fIzipinfo\\fP assumes the height is 24 lines.\n.TP\n.B \\-t\nlist totals for files listed or for all files.  The number of files listed,\ntheir uncompressed and compressed total sizes , and their overall compression\nfactor is printed; or, if only the totals line is being printed, the values\nfor the entire archive are given.  The compressed total size does not include\nthe 12 additional header bytes of each encrypted entry. Note that the total\ncompressed (data) size will never match the actual zipfile size, since the\nlatter includes all of the internal zipfile headers in addition to the\ncompressed data.\n.TP\n.B \\-T\nprint the file dates and times in a sortable decimal format (yymmdd.hhmmss).\nThe default date format is a more standard, human-readable version with\nabbreviated month names (see examples below).\n.TP\n.B \\-U\n[UNICODE_SUPPORT only] modify or disable UTF-8 handling.\nWhen UNICODE_SUPPORT is available, the option \\fB\\-U\\fP forces \\fIunzip\\fP\nto escape all non-ASCII characters from UTF-8 coded filenames as ``#Uxxxx''.\nThis option is mainly provided for debugging purpose when the fairly new\nUTF-8 support is suspected to mangle up extracted filenames.\n.IP\nThe option \\fB\\-UU\\fP allows to entirely disable the recognition of UTF-8\nencoded filenames.  The handling of filename codings within \\fIunzip\\fP falls\nback to the behaviour of previous versions.\n.TP\n.B \\-z\ninclude the archive comment (if any) in the listing.\n.PD\n.\\\" =========================================================================\n.SH \"DETAILED DESCRIPTION\"\n.I zipinfo\nhas a number of modes, and its behavior can be rather difficult to fathom\nif one isn't familiar with Unix \\fIls\\fP(1) (or even if one is).  The default\nbehavior is to list files in the following format:\n.PP\n.X \"-rw-rws---  1.9 unx    2802 t- defX 11-Aug-91 13:48 perms.2660\"\n.PP\nThe last three fields are the modification date and time of\nthe file, and its name.  The case of the filename is respected; thus\nfiles that come from MS-DOS PKZIP are always capitalized.  If the file\nwas zipped with a stored directory name, that is also displayed as part\nof the filename.\n.PP\nThe second and third fields indicate that the file was zipped under\nUnix with version 1.9 of \\fIzip\\fP.  Since it comes from Unix, the file\npermissions at the beginning of the line are printed in Unix format.\nThe uncompressed file-size (2802 in this example) is the fourth field.\n.PP\nThe fifth field consists of two characters, either of which may take\non several values.  The first character may be either `t' or `b', indicating\nthat \\fIzip\\fP believes the file to be text or binary, respectively;\nbut if the file is encrypted, \\fIzipinfo\\fP\nnotes this fact by capitalizing the character (`T' or `B').  The second\ncharacter may also take on four values, depending on whether there is\nan extended local header and/or an ``extra field'' associated with the\nfile (fully explained in PKWare's APPNOTE.TXT, but basically analogous to\npragmas in ANSI C--i.e., they provide a standard way to include non-standard\ninformation in the archive).  If neither exists, the character\nwill be a hyphen (`\\-'); if there is an extended local header but no extra\nfield, `l'; if the reverse, `x'; and if both exist, `X'.  Thus the\nfile in this example is (probably) a text file, is not encrypted, and\nhas neither an extra field nor an extended local header associated with it.\nThe example below, on the other hand, is an encrypted binary file with an\nextra field:\n.PP\n.X \"RWD,R,R     0.9 vms     168 Bx shrk  9-Aug-91 19:15 perms.0644\"\n.PP\nExtra fields are used for various purposes (see discussion of the \\fB\\-v\\fP\noption below) including the storage of VMS file attributes, which is\npresumably the case here.  Note that the file attributes are listed in\nVMS format.  Some other possibilities for the host operating system (which\nis actually a misnomer--host file system is more correct) include\nOS/2 or NT with High Performance File System (HPFS), MS-DOS, OS/2 or NT\nwith File Allocation Table (FAT) file system, and Macintosh.  These are\ndenoted as follows:\n.PP\n.X \"-rw-a--     1.0 hpf    5358 Tl i4:3  4-Dec-91 11:33 longfilename.hpfs\"\n.X \"-r--ahs     1.1 fat    4096 b- i4:2 14-Jul-91 12:58 EA DATA. SF\"\n.X \"--w-------  1.0 mac   17357 bx i8:2  4-May-92 04:02 unzip.macr\"\n.PP\nFile attributes in the first two cases are indicated in a Unix-like format,\nwhere the seven subfields indicate whether the file:  (1) is a directory,\n(2) is readable (always true), (3) is writable, (4) is executable (guessed\non the basis of the extension--\\fI.exe\\fP, \\fI.com\\fP, \\fI.bat\\fP, \\fI.cmd\\fP\nand \\fI.btm\\fP files are assumed to be so), (5) has its archive bit set,\n(6) is hidden, and (7) is a system file.  Interpretation of Macintosh file\nattributes is unreliable because some Macintosh archivers don't store any\nattributes in the archive.\n.PP\nFinally, the sixth field indicates\nthe compression method and possible sub-method used.  There are six methods\nknown at present:  storing (no compression), reducing, shrinking, imploding,\ntokenizing (never publicly released), and deflating.  In addition, there are\nfour levels of reducing (1 through 4); four types of imploding (4K or 8K\nsliding dictionary, and 2 or 3 Shannon-Fano trees); and four levels of\ndeflating (superfast, fast, normal, maximum compression).  \\fIzipinfo\\fP\nrepresents these methods and their sub-methods as follows:  \\fIstor\\fP;\n\\fIre:1\\fP, \\fIre:2\\fP, etc.; \\fIshrk\\fP; \\fIi4:2\\fP, \\fIi8:3\\fP, etc.;\n\\fItokn\\fP; and \\fIdefS\\fP, \\fIdefF\\fP, \\fIdefN\\fP, and \\fIdefX\\fP.\n.PP\nThe medium and long listings are almost identical to the short format except\nthat they add information on the file's compression.  The medium format lists\nthe file's compression factor as a percentage indicating the amount of space\nthat has been ``removed'':\n.PP\n.X \"-rw-rws---  1.5 unx    2802 t- 81% defX 11-Aug-91 13:48 perms.2660\"\n.PP\nIn this example, the file has been compressed by more than a factor of\nfive; the compressed data are only 19% of the original size.  The long\nformat gives the compressed file's size in bytes, instead:\n.PP\n.X \"-rw-rws---  1.5 unx    2802 t-     538 defX 11-Aug-91 13:48 perms.2660\"\n.PP\nIn contrast to the \\fIunzip\\fP listings, the compressed size figures in\nthis listing format denote the complete size of compressed data, including\nthe 12 extra header bytes in case of encrypted entries.\n.PP\nAdding the \\fB\\-T\\fP option changes the file date and time to decimal\nformat:\n.PP\n.X \"-rw-rws---  1.5 unx    2802 t-     538 defX 910811.134804 perms.2660\"\n.PP\nNote that because of limitations in the MS-DOS format used to store file\ntimes, the seconds field is always rounded to the nearest even second.\nFor Unix files this is expected to change in the next major releases of\n\\fIzip\\fP(1L) and \\fIunzip\\fP.\n.PP\nIn addition to individual file information, a default zipfile listing\nalso includes header and trailer lines:\n.PP\n.X \"Archive:  OS2.zip   5453 bytes   5 files\"\n.X \",,rw,       1.0 hpf     730 b- i4:3 26-Jun-92 23:40 Contents\"\n.X \",,rw,       1.0 hpf    3710 b- i4:3 26-Jun-92 23:33 makefile.os2\"\n.X \",,rw,       1.0 hpf    8753 b- i8:3 26-Jun-92 15:29 os2unzip.c\"\n.X \",,rw,       1.0 hpf      98 b- stor 21-Aug-91 15:34 unzip.def\"\n.X \",,rw,       1.0 hpf      95 b- stor 21-Aug-91 17:51 zipinfo.def\"\n.X \"5 files, 13386 bytes uncompressed, 4951 bytes compressed:  63.0%\"\n.PP\nThe header line gives the name of the archive, its total size, and the\ntotal number of files; the trailer gives the number of files listed,\ntheir total uncompressed size, and their total compressed size (not\nincluding any of \\fIzip\\fP's internal overhead).  If, however, one or\nmore \\fIfile(s)\\fP are provided, the header and trailer lines are\nnot listed.  This behavior is also similar to that of Unix's ``\\fCls \\-l\\fR'';\nit may be overridden by specifying the \\fB\\-h\\fP and \\fB\\-t\\fP options\nexplicitly.\nIn such a case the listing format must also be specified explicitly,\nsince \\fB\\-h\\fP or \\fB\\-t\\fP (or both) in the absence of other options implies\nthat ONLY the header or trailer line (or both) is listed.  See the\n\\fBEXAMPLES\\fP section below for a semi-intelligible translation of this\nnonsense.\n.PP\nThe verbose listing is mostly self-explanatory.  It also lists file\ncomments and the zipfile comment, if any, and the type and number of bytes\nin any stored extra fields.  Currently known types of extra fields include\nPKWARE's authentication (``AV'') info; OS/2 extended attributes; VMS\nfilesystem info, both PKWARE and Info-ZIP versions; Macintosh resource\nforks; Acorn/Archimedes SparkFS info; and so on.  (Note\nthat in the case of OS/2 extended attributes--perhaps the most common\nuse of zipfile extra fields--the size of the stored EAs as reported by\n\\fIzipinfo\\fP may not match the number given by OS/2's \\fIdir\\fP command:\nOS/2 always reports the number of bytes required in 16-bit format, whereas\n\\fIzipinfo\\fP always reports the 32-bit storage.)\n.PP\nAgain, the compressed size figures of the individual entries include the\n12 extra header bytes for encrypted entries.  In contrast, the archive total\ncompressed size and the average compression ratio shown in the summary\nbottom line are calculated \\fBwithout\\fP the extra 12 header bytes of\nencrypted entries.\n.PD\n.\\\" =========================================================================\n.SH \"ENVIRONMENT OPTIONS\"\nModifying \\fIzipinfo\\fP's default behavior via options placed in\nan environment variable can be a bit complicated to explain, due to\n\\fIzipinfo\\fP's attempts to handle various defaults in an intuitive,\nyet Unix-like, manner.  (Try not to laugh.)  Nevertheless, there is some\nunderlying logic.  In brief,\nthere are three ``priority levels'' of options:  the default options;\nenvironment options, which can override or add to the defaults; and\nexplicit options given by the user, which can override or add to\neither of the above.\n.PP\nThe default listing format, as noted above, corresponds roughly\nto the \"\\fCzipinfo \\-hst\\fR\" command (except when individual zipfile members\nare specified).\nA user who prefers the long-listing format (\\fB\\-l\\fP) can make use of the\n\\fIzipinfo\\fP's environment variable to change this default:\n.TP\nUnix Bourne shell:\n\\f(CW\\&ZIPINFO=\\-l; export ZIPINFO\\fP\n.TP\nUnix C shell:\n\\f(CW\\&setenv ZIPINFO \\-l\\fP\n.TP\nOS/2 or MS-DOS:\n\\f(CW\\&set ZIPINFO=\\-l\\fP\n.TP\nVMS (quotes for \\fIlowercase\\fP):\n\\f(CW\\&define ZIPINFO_OPTS \"\\-l\"\\fP\n.EE\n.PP\nIf, in addition, the user dislikes the trailer line, \\fIzipinfo\\fP's\nconcept of ``negative options'' may be used to override the default\ninclusion of the line.  This is accomplished by preceding the undesired\noption with one or more minuses:  e.g., ``\\fC\\-l\\-t\\fR'' or ``\\fC\\-\\-tl\\fR'',\nin this example.  The first hyphen is the regular switch character, but the\none before the `t' is a minus sign.  The dual use of hyphens may seem a\nlittle awkward, but it's reasonably intuitive nonetheless:  simply ignore\nthe first hyphen and go from there.  It is also consistent with the behavior\nof the Unix command \\fInice\\fP(1).\n.PP\nAs suggested above, the default variable names are ZIPINFO_OPTS for VMS\n(where the symbol used to install \\fIzipinfo\\fP as a foreign command\nwould otherwise be confused with the environment variable), and ZIPINFO\nfor all other operating systems.  For compatibility with \\fIzip\\fP(1L),\nZIPINFOOPT is also accepted (don't ask).  If both ZIPINFO and ZIPINFOOPT\nare defined, however, ZIPINFO takes precedence.  \\fIunzip\\fP's diagnostic\noption (\\fB\\-v\\fP with no zipfile name) can be used to check the values\nof all four possible \\fIunzip\\fP and \\fIzipinfo\\fP environment variables.\n.PD\n.\\\" =========================================================================\n.SH EXAMPLES\nTo get a basic, short-format listing of the complete contents of a ZIP\narchive \\fIstorage.zip\\fP, with both header and totals lines, use only\nthe archive name as an argument to zipinfo:\n.PP\n.EX\nzipinfo storage\n.EE\n.PP\nTo produce a basic, long-format listing (not verbose), including header and\ntotals lines, use \\fB\\-l\\fP:\n.PP\n.EX\nzipinfo \\-l storage\n.EE\n.PP\nTo list the complete contents of the archive without header and totals\nlines, either negate the \\fB\\-h\\fP and \\fB\\-t\\fP options or else specify the\ncontents explicitly:\n.PP\n.EX\nzipinfo \\-\\-h\\-t storage\nzipinfo storage \\e*\n.EE\n.PP\n(where the backslash is required only if the shell would otherwise expand\nthe `*' wildcard, as in Unix when globbing is turned on--double quotes around\nthe asterisk would have worked as well).  To turn off the totals line by\ndefault, use the environment variable (C shell is assumed here):\n.PP\n.EX\nsetenv ZIPINFO \\-\\-t\nzipinfo storage\n.EE\n.PP\nTo get the full, short-format listing of the first example again, given\nthat the environment variable is set as in the previous example, it is\nnecessary to specify the \\fB\\-s\\fP option explicitly, since the \\fB\\-t\\fP\noption by itself implies that ONLY the footer line is to be printed:\n.PP\n.EX\nsetenv ZIPINFO \\-\\-t\nzipinfo \\-t storage            \\fR[only totals line]\\fP\nzipinfo \\-st storage           \\fR[full listing]\\fP\n.EE\n.PP\nThe \\fB\\-s\\fP option, like \\fB\\-m\\fP and \\fB\\-l\\fP, includes headers and\nfooters by default, unless otherwise specified.  Since the environment\nvariable specified no footers and that has a higher precedence than the\ndefault behavior of \\fB\\-s\\fP, an explicit \\fB\\-t\\fP option was necessary\nto produce the full listing.  Nothing was indicated about the header,\nhowever, so the \\fB\\-s\\fP option was sufficient.  Note that both the\n\\fB\\-h\\fP and \\fB\\-t\\fP options, when used by themselves or with\neach other, override any default listing of member files; only the header\nand/or footer are printed.  This behavior is useful when \\fIzipinfo\\fP is\nused with a wildcard zipfile specification; the contents of all zipfiles\nare then summarized with a single command.\n.PP\nTo list information on a single file within the archive, in medium format,\nspecify the filename explicitly:\n.PP\n.EX\nzipinfo \\-m storage unshrink.c\n.EE\n.PP\nThe specification of any member file, as in this example, will override\nthe default header and totals lines; only the single line of information\nabout the requested file will be printed.  This is intuitively what one\nwould expect when requesting information about a single file.  For multiple\nfiles, it is often useful to know the total compressed and uncompressed\nsize; in such cases \\fB\\-t\\fP may be specified explicitly:\n.PP\n.EX\nzipinfo \\-mt storage \"*.[ch]\" Mak\\e*\n.EE\n.PP\nTo get maximal information about the ZIP archive, use the verbose\noption.  It is usually wise to pipe the output into a filter such as\nUnix \\fImore\\fP(1) if the operating system allows it:\n.PP\n.EX\nzipinfo \\-v storage | more\n.EE\n.PP\nFinally, to see the most recently modified files in the archive, use\nthe \\fB\\-T\\fP option in conjunction with an external sorting utility\nsuch as Unix \\fIsort\\fP(1) (and \\fIsed\\fP(1) as well, in this example):\n.PP\n.EX\nzipinfo \\-T storage | sort -nr -k 7 | sed 15q\n.EE\n.PP\nThe \\fB\\-nr\\fP option to \\fIsort\\fP(1) tells it to sort numerically\nin reverse order rather than in textual order, and the \\fB\\-k\\ 7\\fP option\ntells it to sort on the seventh field.  This\nassumes the default short-listing format; if \\fB\\-m\\fP or \\fB\\-l\\fP is\nused, the proper \\fIsort\\fP(1) option would be \\fB\\-k\\ 8\\fP.\nOlder versions of \\fIsort\\fP(1) do not support the \\fB\\-k\\fP option,\nbut you can use the traditional \\fB\\+\\fP option instead, e.g.,\n\\fB\\+6\\fP instead of \\fB\\-k\\ 7\\fP.  The \\fIsed\\fP(1)\ncommand filters out all but the first 15 lines of the listing.  Future\nreleases of \\fIzipinfo\\fP may incorporate date/time and filename sorting\nas built-in options.\n.PD\n.\\\" =========================================================================\n.SH TIPS\nThe author finds it convenient to define an alias \\fIii\\fP for \\fIzipinfo\\fP\non systems that allow aliases (or, on other systems, copy/rename the\nexecutable, create a link or create a command file with the name \\fIii\\fP).\nThe \\fIii\\fP usage parallels the common \\fIll\\fP alias for long listings in\nUnix, and the similarity between the outputs of the two commands was\nintentional.\n.PD\n.\\\" =========================================================================\n.SH BUGS\nAs with \\fIunzip\\fP, \\fIzipinfo\\fP's \\fB\\-M\\fP (``more'') option is overly\nsimplistic in its handling of screen output; as noted above, it fails to detect\nthe wrapping of long lines and may thereby cause lines at the top of the screen\nto be scrolled off before being read.  \\fIzipinfo\\fP should detect and treat\neach occurrence of line-wrap as one additional line printed.  This requires\nknowledge of the screen's width as well as its height.  In addition,\n\\fIzipinfo\\fP should detect the true screen geometry on all systems.\n.PP\n\\fIzipinfo\\fP's listing-format behavior is unnecessarily complex and should\nbe simplified.  (This is not to say that it will be.)\n.PP\n.\\\" =========================================================================\n.SH \"SEE ALSO\"\n\\fIls\\fP(1), \\fIfunzip\\fP(1L), \\fIunzip\\fP(1L), \\fIunzipsfx\\fP(1L),\n\\fIzip\\fP(1L), \\fIzipcloak\\fP(1L), \\fIzipnote\\fP(1L), \\fIzipsplit\\fP(1L)\n.PD\n.\\\" =========================================================================\n.SH URL\nThe Info-ZIP home page is currently at\n.EX\n\\fChttp://www.info-zip.org/pub/infozip/\\fR\n.EE\nor\n.EX\n\\fCftp://ftp.info-zip.org/pub/infozip/\\fR .\n.EE\n.PD\n.\\\" =========================================================================\n.SH AUTHOR\nGreg ``Cave Newt'' Roelofs.  ZipInfo contains pattern-matching code\nby Mark Adler and fixes/improvements by many others.  Please refer to the\nCONTRIBS file in the UnZip source distribution for a more complete list.\n"
  },
  {
    "path": "deps/infozip/unzip60/match.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  match.c\n\n  The match() routine recursively compares a string to a \"pattern\" (regular\n  expression), returning TRUE if a match is found or FALSE if not.  This\n  version is specifically for use with unzip.c:  as did the previous match()\n  routines from SEA and J. Kercheval, it leaves the case (upper, lower, or\n  mixed) of the string alone, but converts any uppercase characters in the\n  pattern to lowercase if indicated by the global var pInfo->lcflag (which\n  is to say, string is assumed to have been converted to lowercase already,\n  if such was necessary).\n\n  GRR:  reversed order of text, pattern in matche() (now same as match());\n        added ignore_case/ic flags, Case() macro.\n\n  PaulK:  replaced matche() with recmatch() from Zip, modified to have an\n          ignore_case argument; replaced test frame with simpler one.\n\n  ---------------------------------------------------------------------------\n\n  Copyright on recmatch() from Zip's util.c (although recmatch() was almost\n  certainly written by Mark Adler...ask me how I can tell :-) ):\n\n     Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,\n     Kai Uwe Rommel and Igor Mandrichenko.\n\n     Permission is granted to any individual or institution to use, copy,\n     or redistribute this software so long as all of the original files are\n     included unmodified, that it is not sold for profit, and that this copy-\n     right notice is retained.\n\n  ---------------------------------------------------------------------------\n\n  Match the pattern (wildcard) against the string (fixed):\n\n     match(string, pattern, ignore_case, sepc);\n\n  returns TRUE if string matches pattern, FALSE otherwise.  In the pattern:\n\n     `*' matches any sequence of characters (zero or more)\n     `?' matches any single character\n     [SET] matches any character in the specified set,\n     [!SET] or [^SET] matches any character not in the specified set.\n\n  A set is composed of characters or ranges; a range looks like ``character\n  hyphen character'' (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the minimal set of\n  characters allowed in the [..] pattern construct.  Other characters are\n  allowed (i.e., 8-bit characters) if your system will support them.\n\n  To suppress the special syntactic significance of any of ``[]*?!^-\\'', in-\n  side or outside a [..] construct, and match the character exactly, precede\n  it with a ``\\'' (backslash).\n\n  Note that \"*.*\" and \"*.\" are treated specially under MS-DOS if DOSWILD is\n  defined.  See the DOSWILD section below for an explanation.  Note also\n  that with VMSWILD defined, '%' is used instead of '?', and sets (ranges)\n  are delimited by () instead of [].\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __MATCH_C       /* identifies this source module */\n\n/* define ToLower() in here (for Unix, define ToLower to be macro (using\n * isupper()); otherwise just use tolower() */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#ifndef THEOS   /* the Theos port defines its own variant of match() */\n\n#if 0  /* this is not useful until it matches Amiga names insensitively */\n#ifdef AMIGA        /* some other platforms might also want to use this */\n#  define ANSI_CHARSET       /* MOVE INTO UNZIP.H EVENTUALLY */\n#endif\n#endif /* 0 */\n\n#ifdef ANSI_CHARSET\n#  ifdef ToLower\n#    undef ToLower\n#  endif\n   /* uppercase letters are values 41 thru 5A, C0 thru D6, and D8 thru DE */\n#  define IsUpper(c) (c>=0xC0 ? c<=0xDE && c!=0xD7 : c>=0x41 && c<=0x5A)\n#  define ToLower(c) (IsUpper((uch) c) ? (unsigned) c | 0x20 : (unsigned) c)\n#endif\n#define Case(x)  (ic? ToLower(x) : (x))\n\n#ifdef VMSWILD\n#  define WILDCHAR   '%'\n#  define BEG_RANGE  '('\n#  define END_RANGE  ')'\n#else\n#  define WILDCHAR   '?'\n#  define BEG_RANGE  '['\n#  define END_RANGE  ']'\n#endif\n\n#if 0                /* GRR:  add this to unzip.h someday... */\n#if !(defined(MSDOS) && defined(DOSWILD))\n#ifdef WILD_STOP_AT_DIR\n#define match(s,p,ic,sc) (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic,sc) == 1)\n#else\n#define match(s,p,ic)    (recmatch((ZCONST uch *)p,(ZCONST uch *)s,ic) == 1)\n#endif\nint recmatch OF((ZCONST uch *pattern, ZCONST uch *string,\n                 int ignore_case __WDLPRO));\n#endif\n#endif /* 0 */\nstatic int recmatch OF((ZCONST uch *pattern, ZCONST uch *string,\n                        int ignore_case __WDLPRO));\nstatic char *isshexp OF((ZCONST char *p));\nstatic int namecmp OF((ZCONST char *s1, ZCONST char *s2));\n\n\n/* match() is a shell to recmatch() to return only Boolean values. */\n\nint match(string, pattern, ignore_case __WDL)\n    ZCONST char *string, *pattern;\n    int ignore_case;\n    __WDLDEF\n{\n#if (defined(MSDOS) && defined(DOSWILD))\n    char *dospattern;\n    int j = strlen(pattern);\n\n/*---------------------------------------------------------------------------\n    Optional MS-DOS preprocessing section:  compare last three chars of the\n    wildcard to \"*.*\" and translate to \"*\" if found; else compare the last\n    two characters to \"*.\" and, if found, scan the non-wild string for dots.\n    If in the latter case a dot is found, return failure; else translate the\n    \"*.\" to \"*\".  In either case, continue with the normal (Unix-like) match\n    procedure after translation.  (If not enough memory, default to normal\n    match.)  This causes \"a*.*\" and \"a*.\" to behave as MS-DOS users expect.\n  ---------------------------------------------------------------------------*/\n\n    if ((dospattern = (char *)malloc(j+1)) != NULL) {\n        strcpy(dospattern, pattern);\n        if (!strcmp(dospattern+j-3, \"*.*\")) {\n            dospattern[j-2] = '\\0';                    /* nuke the \".*\" */\n        } else if (!strcmp(dospattern+j-2, \"*.\")) {\n            char *p = MBSCHR(string, '.');\n\n            if (p) {   /* found a dot:  match fails */\n                free(dospattern);\n                return 0;\n            }\n            dospattern[j-1] = '\\0';                    /* nuke the end \".\" */\n        }\n        j = recmatch((uch *)dospattern, (uch *)string, ignore_case __WDL);\n        free(dospattern);\n        return j == 1;\n    } else\n#endif /* MSDOS && DOSWILD */\n    return recmatch((uch *)pattern, (uch *)string, ignore_case __WDL) == 1;\n}\n\n\n\nstatic int recmatch(p, s, ic __WDL)\n    ZCONST uch *p;        /* sh pattern to match */\n    ZCONST uch *s;        /* string to which to match it */\n    int ic;               /* true for case insensitivity */\n    __WDLDEF              /* directory sepchar for WildStopAtDir mode, or 0 */\n/* Recursively compare the sh pattern p with the string s and return 1 if\n * they match, and 0 or 2 if they don't or if there is a syntax error in the\n * pattern.  This routine recurses on itself no more deeply than the number\n * of characters in the pattern. */\n{\n    unsigned int c;       /* pattern char or start of range in [-] loop */\n\n    /* Get first character, the pattern for new recmatch calls follows */\n    c = *p; INCSTR(p);\n\n    /* If that was the end of the pattern, match if string empty too */\n    if (c == 0)\n        return *s == 0;\n\n    /* '?' (or '%') matches any character (but not an empty string). */\n    if (c == WILDCHAR)\n#ifdef WILD_STOP_AT_DIR\n        /* If uO.W_flag is non-zero, it won't match '/' */\n        return (*s && (!sepc || *s != (uch)sepc))\n               ? recmatch(p, s + CLEN(s), ic, sepc) : 0;\n#else\n        return *s ? recmatch(p, s + CLEN(s), ic) : 0;\n#endif\n\n    /* '*' matches any number of characters, including zero */\n#ifdef AMIGA\n    if (c == '#' && *p == '?')     /* \"#?\" is Amiga-ese for \"*\" */\n        c = '*', p++;\n#endif /* AMIGA */\n    if (c == '*') {\n#ifdef WILD_STOP_AT_DIR\n        if (sepc) {\n          /* check for single \"*\" or double \"**\" */\n#  ifdef AMIGA\n          if ((c = p[0]) == '#' && p[1] == '?') /* \"#?\" is Amiga-ese for \"*\" */\n            c = '*', p++;\n          if (c != '*') {\n#  else /* !AMIGA */\n          if (*p != '*') {\n#  endif /* ?AMIGA */\n            /* single \"*\": this doesn't match the dirsep character */\n            for (; *s && *s != (uch)sepc; INCSTR(s))\n                if ((c = recmatch(p, s, ic, sepc)) != 0)\n                    return (int)c;\n            /* end of pattern: matched if at end of string, else continue */\n            if (*p == '\\0')\n                return (*s == 0);\n            /* continue to match if at sepc in pattern, else give up */\n            return (*p == (uch)sepc || (*p == '\\\\' && p[1] == (uch)sepc))\n                   ? recmatch(p, s, ic, sepc) : 2;\n          }\n          /* \"**\": this matches slashes */\n          ++p;        /* move p behind the second '*' */\n          /* and continue with the non-W_flag code variant */\n        }\n#endif /* WILD_STOP_AT_DIR */\n        if (*p == 0)\n            return 1;\n        if (isshexp((ZCONST char *)p) == NULL) {\n            /* Optimization for rest of pattern being a literal string:\n             * If there are no other shell expression chars in the rest\n             * of the pattern behind the multi-char wildcard, then just\n             * compare the literal string tail.\n             */\n            ZCONST uch *srest;\n\n            srest = s + (strlen((ZCONST char *)s) - strlen((ZCONST char *)p));\n            if (srest - s < 0)\n                /* remaining literal string from pattern is longer than rest\n                 * of test string, there can't be a match\n                 */\n                return 0;\n            else\n              /* compare the remaining literal pattern string with the last\n               * bytes of the test string to check for a match\n               */\n#ifdef _MBCS\n            {\n                ZCONST uch *q = s;\n\n                /* MBCS-aware code must not scan backwards into a string from\n                 * the end.\n                 * So, we have to move forward by character from our well-known\n                 * character position s in the test string until we have\n                 * advanced to the srest position.\n                 */\n                while (q < srest)\n                  INCSTR(q);\n                /* In case the byte *srest is a trailing byte of a multibyte\n                 * character in the test string s, we have actually advanced\n                 * past the position (srest).\n                 * For this case, the match has failed!\n                 */\n                if (q != srest)\n                    return 0;\n                return ((ic\n                         ? namecmp((ZCONST char *)p, (ZCONST char *)q)\n                         : strcmp((ZCONST char *)p, (ZCONST char *)q)\n                        ) == 0);\n            }\n#else /* !_MBCS */\n                return ((ic\n                         ? namecmp((ZCONST char *)p, (ZCONST char *)srest)\n                         : strcmp((ZCONST char *)p, (ZCONST char *)srest)\n                        ) == 0);\n#endif /* ?_MBCS */\n        } else {\n            /* pattern contains more wildcards, continue with recursion... */\n            for (; *s; INCSTR(s))\n                if ((c = recmatch(p, s, ic __WDL)) != 0)\n                    return (int)c;\n            return 2;  /* 2 means give up--match will return false */\n        }\n    }\n\n    /* Parse and process the list of characters and ranges in brackets */\n    if (c == BEG_RANGE) {\n        int e;          /* flag true if next char to be taken literally */\n        ZCONST uch *q;  /* pointer to end of [-] group */\n        int r;          /* flag true to match anything but the range */\n\n        if (*s == 0)                            /* need a character to match */\n            return 0;\n        p += (r = (*p == '!' || *p == '^'));    /* see if reverse */\n        for (q = p, e = 0; *q; INCSTR(q))       /* find closing bracket */\n            if (e)\n                e = 0;\n            else\n                if (*q == '\\\\')      /* GRR:  change to ^ for MS-DOS, OS/2? */\n                    e = 1;\n                else if (*q == END_RANGE)\n                    break;\n        if (*q != END_RANGE)         /* nothing matches if bad syntax */\n            return 0;\n        for (c = 0, e = (*p == '-'); p < q; INCSTR(p)) {\n            /* go through the list */\n            if (!e && *p == '\\\\')               /* set escape flag if \\ */\n                e = 1;\n            else if (!e && *p == '-')           /* set start of range if - */\n                c = *(p-1);\n            else {\n                unsigned int cc = Case(*s);\n\n                if (*(p+1) != '-')\n                    for (c = c ? c : *p; c <= *p; c++)  /* compare range */\n                        if ((unsigned)Case(c) == cc) /* typecast for MSC bug */\n                            return r ? 0 : recmatch(q + 1, s + 1, ic __WDL);\n                c = e = 0;   /* clear range, escape flags */\n            }\n        }\n        return r ? recmatch(q + CLEN(q), s + CLEN(s), ic __WDL) : 0;\n                                        /* bracket match failed */\n    }\n\n    /* if escape ('\\\\'), just compare next character */\n    if (c == '\\\\' && (c = *p++) == 0)     /* if \\ at end, then syntax error */\n        return 0;\n\n    /* just a character--compare it */\n#ifdef QDOS\n    return QMatch(Case((uch)c), Case(*s)) ?\n           recmatch(p, s + CLEN(s), ic __WDL) : 0;\n#else\n    return Case((uch)c) == Case(*s) ?\n           recmatch(p, s + CLEN(s), ic __WDL) : 0;\n#endif\n\n} /* end function recmatch() */\n\n\n\nstatic char *isshexp(p)\nZCONST char *p;\n/* If p is a sh expression, a pointer to the first special character is\n   returned.  Otherwise, NULL is returned. */\n{\n    for (; *p; INCSTR(p))\n        if (*p == '\\\\' && *(p+1))\n            p++;\n        else if (*p == WILDCHAR || *p == '*' || *p == BEG_RANGE)\n            return (char *)p;\n    return NULL;\n} /* end function isshexp() */\n\n\n\nstatic int namecmp(s1, s2)\n    ZCONST char *s1, *s2;\n{\n    int d;\n\n    for (;;) {\n        d = (int)ToLower((uch)*s1)\n          - (int)ToLower((uch)*s2);\n\n        if (d || *s1 == 0 || *s2 == 0)\n            return d;\n\n        s1++;\n        s2++;\n    }\n} /* end function namecmp() */\n\n#endif /* !THEOS */\n\n\n\n\nint iswild(p)        /* originally only used for stat()-bug workaround in */\n    ZCONST char *p;  /*  VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */\n{                    /*  now used in process_zipfiles() as well */\n    for (; *p; INCSTR(p))\n        if (*p == '\\\\' && *(p+1))\n            ++p;\n#ifdef THEOS\n        else if (*p == '?' || *p == '*' || *p=='#'|| *p == '@')\n#else /* !THEOS */\n#ifdef VMS\n        else if (*p == '%' || *p == '*')\n#else /* !VMS */\n#ifdef AMIGA\n        else if (*p == '?' || *p == '*' || (*p=='#' && p[1]=='?') || *p == '[')\n#else /* !AMIGA */\n        else if (*p == '?' || *p == '*' || *p == '[')\n#endif /* ?AMIGA */\n#endif /* ?VMS */\n#endif /* ?THEOS */\n#ifdef QDOS\n            return (int)p;\n#else\n            return TRUE;\n#endif\n\n    return FALSE;\n\n} /* end function iswild() */\n\n\n\n\n\n#ifdef TEST_MATCH\n\n#define put(s) {fputs(s,stdout); fflush(stdout);}\n#ifdef main\n#  undef main\n#endif\n\nint main(int argc, char **argv)\n{\n    char pat[256], str[256];\n\n    for (;;) {\n        put(\"Pattern (return to exit): \");\n        gets(pat);\n        if (!pat[0])\n            break;\n        for (;;) {\n            put(\"String (return for new pattern): \");\n            gets(str);\n            if (!str[0])\n                break;\n            printf(\"Case sensitive: %s  insensitive: %s\\n\",\n              match(str, pat, 0) ? \"YES\" : \"NO\",\n              match(str, pat, 1) ? \"YES\" : \"NO\");\n        }\n    }\n    EXIT(0);\n}\n\n#endif /* TEST_MATCH */\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/Contents",
    "content": "Contents of the \"msdos\" subdirectory for UnZip 5.3 and later:\n\n  Contents       this file\n  README         notes about quirks in MS-DOS executables and compilers\n  crc_i86.asm    optimized 8086/80286 assembler version of generic crc32.c\n  doscfg.h       OS-dependent configuration, included by unzpriv.h\n  msdos.c        OS-dependent UnZip routines for MS-DOS\n  makefile.bc    makefile for Borland C++ and Turbo C++\n  makefile.msc   makefile for Microsoft C and make or nmake\n  makefile.tc    makefile for Turbo C and make\n  makefile.wat   makefile for Watcom C\n  makefile.dj1   makefile for GNU C, djgpp v1.12m4 port\n  makefile.dj2   makefile for GNU C, djgpp v2.x port\n  makefile.emx   makefile for GNU C, emx 0.9c port, gnu make\n\nNotes:\n\n(1) Two makefiles for djgpp/GNU make are provided, one for djgpp 1.12 and one\n    for djgpp v2.x.  In addition, the Unix makefile (unix/Makefile) contains\n    a djgpp v2.x target using the go32-gcc cross compiler on Linux.  Read the\n    appropriate makefile sections for details.\n\n(2) The makefile for emx+gcc has been used with GNU Make ports from DJGPP and\n    the GNUish MS-DOS project.  Other make utilities may work, too.  The\n    resulting executables require emx.exe or rsx.exe to run (akin to djgpp\n    1.x's go32.exe).\n\n(3) The OS/2 makefile includes several (cross compilation ?) targets to\n    generate MS-DOS executables which can be used with MSC 6.0 or later\n    (`mscdos', 16-bit), Watcom C/C++ 9.0 or later (`watcom16dos', 16-bit;\n    `watcomdos' and `pmodew', 32-bit) and emx+gcc 0.9c or later (`gccdos',\n    32-bit). These targets have only been tested in cross-compilation from\n    OS/2 to MS-DOS, but they may work on a plain MS-DOS system, when a proper\n    make utility is available.\n\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/README",
    "content": "Notes about MS-DOS executables and compilers:\n\n - Borland start-up code is reported to switch the screen mode auto-\n   matically if it's not 80 columns (or possibly 40) and either 25, 43\n   or 50 lines.  In particular, extended modes such as 100x40 are not\n   retained.\n\n - Borland start-up code also uses interrupt 1Ah, causing incorrect\n   behavior (including lock-ups) on some Japanese MS-DOS machines such\n   as the Fujitsu FMR series, which lack this interrupt.\n\n - Some(?) Borland compilers are apparently incapable of putting static\n   data into far memory; this means all of UnZip's strings are in near\n   memory, and there is not enough room to enable ZipInfo in the small\n   memory model.  The medium memory model is the default for now, but\n   it may be necessary in some cases to use the large model.\n\n - Older Borland compilers do not understand source files with Unix\n   line-endings (LF rather than CR/LF).  Use \"flip\" or a similar utility\n   to convert the line endings before compiling.\n\n - The Borland 5.00 compiler is simply too buggy to use on WizUnZip, both\n   16-bit and 32-bit versions, and we recommend avoiding it for now even\n   on the commmand-line version of UnZip.\n\n - Microsoft C 5.1 large-model code is more than an order of magnitude\n   slower than the identical code compiled with MSC 6 or 7 (a factor of\n   15 in our tests, actually).  This may be due to a lousy optimizer or\n   lousy libraries; regardless, since UnZip is hovering at the doorstep\n   of the large memory model, we recommend upgrading to a later version\n   of the compiler.\n\nFor these reasons, Info-ZIP's distributed versions of the 16-bit MS-DOS\nexecutables are compiled with MSC 6 or 7.\n\n - djgpp 2.x (currently 2.03) is no longer distributed with the go32 extender.\n   Instead, a 2K stub bound into the executable searches for a DPMI server;\n   if none is found, it loads the default DPMI server while executing UnZip.\n   Both djgpp 1.x and 2.x are capable of substituting a list of files in an\n   ASCII file (say, `foo') on the command line; for example, \"unzip archive\n   @foo\" will extract from `archive' all of the files listed in `foo'.  Note,\n   however, that djgpp 2.x is considerably slower than 1.x at file extraction\n   (roughly twice as slow, in fact); see proginfo/perform.dos in the UnZip 5.3\n   source distribution for details.\n\n - djgpp 2.0's long-filename support is somewhat flaky; users should upgrade\n   to version 2.01 instead.\n\n - The default wildcard (\"globbing\") behavior of djgpp 1.x/go32 is disabled\n   by default in UnZip, but this can be overridden if the GO32 environment\n   variable is set to \"glob\".  This will cause UnZip to fail with various\n   odd errors about \"filename not matched\" and the like; to avoid this, set\n   the GO32 variable to \"noglob\" or unset it altogether.  (The documented\n   method of avoiding this by quoting wildcards with single quotes was\n   buggy in djgpp 1.11 but is reported fixed in 1.12; not tested.)\n\n - djgpp 1.x's handling of timezones, necessary for the correct conversion of\n   MS-DOS file times to those used in the Unix-like C library, is completely\n   broken in djgpp 1.12 and probably earlier versions as well.  It is fixed\n   (or very close to it) in the 1.12m4 patch release and reportedly in the\n   2.x series, so be sure to use one of those when compiling.  Otherwise\n   UnZip's -f and -u (freshen/update) functions will not work correctly.\n   It is reportedly necessary to set the TZDIR environment variable correctly\n   with 1.12m4; for example, add `set TZDIR=c:/djgpp/zoneinfo' or similar to\n   autoexec.bat.\n\n - djgpp 1.x/go32 executables, when run in a DOS box under OS/2 *and* extrac-\n   ting to an HPFS disk *and* overwriting existing files (intentionally, that\n   is), do not set the files' timestamps correctly.  Instead, the timestamps\n   remain set to whatever the original files' stamps were.  This is a pretty\n   obscure bug, but it does *not* occur in the 16-bit version so it seems\n   to be go32's fault somehow.\n\n - According to notes found in another package, there was a known conflict\n   between djgpp 1.x's go32 extender and QEMM's DPMI; this was apparently\n   fixed in QEMM 7.04/QDPMI 1.05, but if you still have an older version\n   (1.03 or 1.01), add \"set GO32=nodpmi\" to your autoexec.bat to avoid the\n   conflict.)\n\n - [For Zip only, the djgpp/go32 extender goes nuts with the copying and/or\n   deletion of some sort of a temporary file (swap file?) after compression\n   is finished; this can take 30 seconds or more and really hurts perfor-\n   mance.  It doesn't affect UnZip, apparently.]\n\n - [Also apparently for Zip only, djgpp/go32 is reported to have problems\n   when EMM386 is set to NOEMS; it sometimes gives the error message, \"CPU\n   must be in REAL mode (not V86 mode) to run this program without VCPI.\n   (If you are using an EMS emulator, make sure that EMS isn't disabled)\"\n   Sometimes Zip works correctly, however, possibly due to other software\n   having been run previously.]\n\n - emx+gcc's DOS extender does not understand DPMI, and while there is an\n   alternative extender called RSX available (found in dpmigcc4.zip as of\n   August 1994), its setup is somewhat kludgy when the local memory manager\n   supports both DPMI and VCPI (or something else).  It's also not yet as\n   widely known or available as djgpp.\n\n - The free PMODE/W extender, used in conjunction with executables compiled\n   with Watcom C 10.x and run in an OS/2 DOS box, appears to use up some\n   critical DPMI resource and will fail to run after a few dozen executions\n   (\"PMODE/W: DPMI error\" and/or SYS 3176).  Some newer versions of PMODE/W,\n   in combination with \"unzip -v\" on certain zipfiles (e.g., APMTST.ZIP from\n   IBM/EWS), fail immediately (SYS 3176).  And on some OS/2 systems, *any*\n   use of the PMODE/W executables causes the machine to lock up.\n\n - PMODE/W is also reported to lock up pure DOS systems if QEMM is running.\n\n - At least older versions of PMODE/W, used in conjunction with Microsoft's\n   EMM386, cause UnZip to start up extremely slowly.  (This problem does not\n   occur with QEMM.)\n\nFor these reasons Info-ZIP's distributed 32-bit MS-DOS executables will\nbe compiled with djgpp 2.03, mainly because of its nice long-filename\nsupport when running in a Win32 DOS box.  The cwsdpmi DPMI server will be\nbundled if necessary.\n\nSPC 2000-04-16\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/crc_i86.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; Created by Christian Spieler, last modified 07 Jan 2007.\n;\n        TITLE   crc_i86.asm\n        NAME    crc_i86\n;\n; Optimized 8086 assembler version of the CRC32 calculation loop, intended\n; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions).\n; Supported compilers are Microsoft C (DOS real mode) and Borland C(++)\n; (Turbo C). Watcom C (16bit) should also work.\n; This module was inspired by a similar module for the Amiga (Paul Kienitz).\n;\n; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function\n; in crc32.c.\n;\n; In March/April 1997, the code has been revised to incorporate Rodney Brown's\n; ideas for optimized access to the data buffer. For 8086 real mode code,\n; the data buffer is now accessed by aligned word-wide read operations.\n; This new optimization may be turned off by defining the macro switch\n; NO_16_BIT_LOADS.\n;\n; In December 1998, the loop branch commands were changed from \"loop dest\"\n; into \"dec cx; jnz dest\". On modern systems (486 and newer), the latter\n; code is usually much faster (e.g. 1 clock cycle compared to 5 for \"loop\"\n; on Pentium MMX). For the 286, the penalty of \"dec cx; jnz\" is one clock\n; cycle (12 vs. 11 cycles); on an 8088 the cycle counts are 22 (dec cx; jnz)\n; vs. 18 (loop). I decided to optimize for newer CPU models by default, because\n; I expect that old 80286 or 8088 dinosaurier machines may be rarely used\n; nowadays. In case you want optimum performance for these old CPU models\n; you should define the OPTIMIZE_286_88 macro switch on the assembler's\n; command line.\n; Likewise, \"jcxz\" was replaced by \"jz\", because the latter is faster on\n; 486 and newer CPUs (without any penalty on 80286 and older CPU models).\n;\n; In January 2007, the \"hand-made\" memory model setup section has been guarded\n; against redefinition of @CodeSize and @DataSize symbols, to work around a\n; problem with current Open Watcom (version 1.6) wasm assembler.\n;\n; The code in this module should work with all kinds of C memory models\n; (except Borland's __HUGE__ model), as long as the following\n; restrictions are not violated:\n;\n; - The implementation assumes that the char buffer is confined to a\n;   64k segment. The pointer `s' to the buffer must be in a format that\n;   all bytes can be accessed by manipulating the offset part, only.\n;   This means:\n;   + no huge pointers\n;   + char buffer size < 64 kByte\n;\n; - Since the buffer size argument `n' is of type `size_t' (= unsigned short)\n;   for this routine, the char buffer size is limited to less than 64 kByte,\n;   anyway. So, the assumption above should be easily fulfilled.\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used,\n; or only the precomputed CRC_32_Table is needed.\n;\nifndef USE_ZLIB\nifndef CRC_TABLE_ONLY\n;\n; Setup of amount of assemble time informational messages:\n;\nifdef     DEBUG\n  VERBOSE_INFO EQU 1\nelse\n  ifdef _AS_MSG_\n    VERBOSE_INFO EQU 1\n  else\n    VERBOSE_INFO EQU 0\n  endif\nendif\n;\n; Selection of memory model, and initialization of memory model\n; related macros:\n;\nifndef __SMALL__\n  ifndef __COMPACT__\n    ifndef __MEDIUM__\n      ifndef __LARGE__\n        ifndef __HUGE__\n;         __SMALL__ EQU 1\n        endif\n      endif\n    endif\n  endif\nendif\n\nifdef __HUGE__\n; .MODEL Huge\n   ifndef @CodeSize\n    @CodeSize  EQU 1\n   endif\n   ifndef @DataSize\n    @DataSize  EQU 1\n   endif\n   Save_DS    EQU 1\n   if VERBOSE_INFO\n    if1\n      %out Assembling for C, Huge memory model\n    endif\n   endif\nelse\n   ifdef __LARGE__\n;      .MODEL Large\n      ifndef @CodeSize\n       @CodeSize  EQU 1\n      endif\n      ifndef @DataSize\n       @DataSize  EQU 1\n      endif\n      if VERBOSE_INFO\n       if1\n         %out Assembling for C, Large memory model\n       endif\n      endif\n   else\n      ifdef __COMPACT__\n;         .MODEL Compact\n         ifndef @CodeSize\n          @CodeSize  EQU 0\n         endif\n         ifndef @DataSize\n          @DataSize  EQU 1\n         endif\n         if VERBOSE_INFO\n          if1\n            %out Assembling for C, Compact memory model\n          endif\n         endif\n      else\n         ifdef __MEDIUM__\n;            .MODEL Medium\n            ifndef @CodeSize\n             @CodeSize  EQU 1\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Medium memory model\n             endif\n            endif\n         else\n;            .MODEL Small\n            ifndef @CodeSize\n             @CodeSize  EQU 0\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Small memory model\n             endif\n            endif\n         endif\n      endif\n   endif\nendif\n\nif @CodeSize\n        LCOD_OFS        EQU     2\nelse\n        LCOD_OFS        EQU     0\nendif\n\nIF @DataSize\n        LDAT_OFS        EQU     2\nelse\n        LDAT_OFS        EQU     0\nendif\n\nifdef Save_DS\n;                       (di,si,ds)+(size, return address)\n        SAVE_REGS       EQU     6+(4+LCOD_OFS)\nelse\n;                       (di,si)+(size, return address)\n        SAVE_REGS       EQU     4+(4+LCOD_OFS)\nendif\n\n;\n; Selection of the supported CPU instruction set and initialization\n; of CPU type related macros:\n;\nifdef __686\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on Pentium II/III/IV\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __586\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on Pentium\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __486\n        Use_286_code     EQU    1\n        Align_Size       EQU    4       ; dword alignment on 32 bit processors\n        Alig_PARA        EQU    1       ; paragraph aligned code segment\nelse\nifdef __386\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on 32 bit processors\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __286\n        Use_286_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\nifdef __186\n        Use_186_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nendif   ;?__186\nendif   ;?__286\nendif   ;?__386\nendif   ;?__486\nendif   ;?__586\nendif   ;?__686\n\nifdef Use_286_code\n        .286\n        Have_80x86      EQU     1\nelse\nifdef Use_186_code\n        .186\n        Have_80x86      EQU     1\nelse\n        .8086\n        Have_80x86      EQU     0\nendif   ;?Use_186_code\nendif   ;?Use_286_code\n\n;\n; Declare the segments used in this module:\n;\nif @CodeSize\nif Alig_PARA\nCRC32_TEXT      SEGMENT  PARA PUBLIC 'CODE'\nelse\nCRC32_TEXT      SEGMENT  WORD PUBLIC 'CODE'\nendif\nCRC32_TEXT      ENDS\nelse    ;!@CodeSize\nif Alig_PARA\n_TEXT   SEGMENT  PARA PUBLIC 'CODE'\nelse\n_TEXT   SEGMENT  WORD PUBLIC 'CODE'\nendif\n_TEXT   ENDS\nendif   ;?@CodeSize\n_DATA   SEGMENT  WORD PUBLIC 'DATA'\n_DATA   ENDS\n_BSS    SEGMENT  WORD PUBLIC 'BSS'\n_BSS    ENDS\nDGROUP  GROUP   _BSS, _DATA\nif @DataSize\n        ASSUME  DS: nothing, SS: DGROUP\nelse\n        ASSUME  DS: DGROUP, SS: DGROUP\nendif\n\nif @CodeSize\nEXTRN   _get_crc_table:FAR\nelse\nEXTRN   _get_crc_table:NEAR\nendif\n\n\nDo_CRC  MACRO\n        mov     bl,al\n        sub     bh,bh\nif Have_80x86\n        shl     bx,2\nelse\n        shl     bx,1\n        shl     bx,1\nendif\n        mov     al,ah\n        mov     ah,dl\n        mov     dl,dh\n        sub     dh,dh\n        xor     ax,WORD PTR [bx][si]\n        xor     dx,WORD PTR [bx+2][si]\n        ENDM\n;\nDo_1    MACRO\nif @DataSize\n        xor     al,BYTE PTR es:[di]\nelse\n        xor     al,BYTE PTR [di]\nendif\n        inc     di\n        Do_CRC\n        ENDM\n;\nDo_2    MACRO\nifndef NO_16_BIT_LOADS\nif @DataSize\n        xor     ax,WORD PTR es:[di]\nelse\n        xor     ax,WORD PTR [di]\nendif\n        add     di,2\n        Do_CRC\n        Do_CRC\nelse\n        Do_1\n        Do_1\nendif\n        ENDM\n;\nDo_4    MACRO\n        Do_2\n        Do_2\n        ENDM\n;\n\nIF @CodeSize\nCRC32_TEXT      SEGMENT\n        ASSUME  CS: CRC32_TEXT\nelse\n_TEXT   SEGMENT\n        ASSUME  CS: _TEXT\nendif\n; Line 37\n\n;\n;ulg crc32(ulg crc,\n;    ZCONST uch *buf,\n;    extent len)\n;\n        PUBLIC  _crc32\nif @CodeSize\n_crc32  PROC FAR\nelse\n_crc32  PROC NEAR\nendif\nif Have_80x86\n        enter   WORD PTR 0,0\nelse\n        push    bp\n        mov     bp,sp\nendif\n        push    di\n        push    si\nif @DataSize\n;       crc = 4+LCOD_OFS        DWORD (unsigned long)\n;       buf = 8+LCOD_OFS        DWORD PTR BYTE (uch *)\n;       len = 12+LCOD_OFS       WORD (unsigned int)\nelse\n;       crc = 4+LCOD_OFS        DWORD (unsigned long)\n;       buf = 8+LCOD_OFS        WORD PTR BYTE (uch *)\n;       len = 10+LCOD_OFS       WORD (unsigned int)\nendif\n;\nif @DataSize\n        mov     ax,WORD PTR [bp+8+LCOD_OFS]     ; buf\n        or      ax,WORD PTR [bp+10+LCOD_OFS]    ;     == NULL ?\nelse\n        cmp     WORD PTR [bp+8+LCOD_OFS],0      ; buf == NULL ?\nendif\n        jne     crc_update\n        sub     ax,ax                           ; crc = 0\n        cwd\nifndef NO_UNROLLED_LOOPS\n        jmp     fine\nelse\n        jmp     SHORT fine\nendif\n;\ncrc_update:\n        call     _get_crc_table\n;  When used with compilers that conform to the Microsoft/Borland standard\n;  C calling convention, model-dependent handling is not needed, because\n;   _get_crc_table returns NEAR pointer.\n;  But Watcom C is different and does not allow one to assume DS pointing to\n;  DGROUP. So, we load DS with DGROUP, to be safe.\n;if @DataSize\n;       push    ds\n;       mov     ds,dx\n;       ASSUME  DS: nothing\n;endif\n        mov     si,ax                           ;crc_table\nif @DataSize\n        push    ds\n        mov     ax,SEG DGROUP\n        mov     ds,ax\n        ASSUME  DS: DGROUP\nendif\n;\n        mov     ax,WORD PTR [bp+4+LCOD_OFS]     ;crc\n        mov     dx,WORD PTR [bp+6+LCOD_OFS]\n        not     ax\n        not     dx\nif @DataSize\n        les     di,DWORD PTR [bp+8+LCOD_OFS]    ;buf\n        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len\nelse\n        mov     di,WORD PTR [bp+8+LCOD_OFS]     ;buf\n        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len\nendif\n;\nifndef NO_UNROLLED_LOOPS\nifndef NO_16_BIT_LOADS\n        test    cx,cx\n        jnz     start\n        jmp     done\nstart:  test    di,1\n        jz      is_wordaligned\n        dec     cx\n        Do_1\n        mov     WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cx\nis_wordaligned:\nendif ; !NO_16_BIT_LOADS\nif Have_80x86\n        shr     cx,2\nelse\n        shr     cx,1\n        shr     cx,1\nendif\n        jz      No_Fours\n;\n        align   Align_Size              ; align destination of branch\nNext_Four:\n        Do_4\nifndef OPTIMIZE_286_88\n        dec     cx                      ; on 286, \"loop Next_Four\" needs 11\n        jnz     Next_Four               ;  clocks, one less than this code\nelse\n        loop    Next_Four\nendif\n;\nNo_Fours:\nif @DataSize\n        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len\nelse\n        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len\nendif\n        and     cx,00003H\nendif ; !NO_UNROLLED_LOOPS\n        jz      done\n;\n        align   Align_Size              ; align destination of branch\nNext_Byte:\n        Do_1\nifndef OPTIMIZE_286_88\n        dec     cx                      ; on 286, \"loop Next_Four\" needs 11\n        jnz     Next_Byte               ;  clocks, one less than this code\nelse\n        loop    Next_Four\nendif\n;\ndone:\nif @DataSize\n        pop     ds\n;       ASSUME  DS: DGROUP\n        ASSUME  DS: nothing\nendif\n        not     ax\n        not     dx\n;\nfine:\n        pop     si\n        pop     di\nif Have_80x86\n        leave\nelse\n        mov     sp,bp\n        pop     bp\nendif\n        ret\n\n_crc32  ENDP\n\nif @CodeSize\nCRC32_TEXT      ENDS\nelse\n_TEXT   ENDS\nendif\n;\nendif ;!CRC_TABLE_ONLY\nendif ;!USE_ZLIB\n;\nEND\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/doscfg.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    MS-DOS specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __doscfg_h\n#define __doscfg_h\n\n#include <dos.h>           /* for REGS macro (TC) or _dos_setftime (MSC) */\n\n#ifdef __TURBOC__          /* includes Power C */\n#  include <sys/timeb.h>   /* for structure ftime */\n#  ifndef __BORLANDC__     /* there appears to be a bug (?) in Borland's */\n#    include <mem.h>       /*  MEM.H related to __STDC__ and far poin-   */\n#  endif                   /*  ters. (dpk)  [mem.h included for memcpy]  */\n#endif\n\n#ifdef WINDLL\n#  if (defined(MSC) || defined(__WATCOMC__))\n#    include <sys/utime.h>\n#  else /* !(MSC || __WATCOMC__) ==> may be BORLANDC, or GNU environment */\n#    include <utime.h>\n#  endif /* ?(MSC || __WATCOMC__) */\n#endif\n\n#ifdef __WATCOMC__\n#  define DOS_STAT_BANDAID\n\n#  ifdef __386__\n#    ifndef WATCOMC_386\n#      define WATCOMC_386\n#    endif\n#    define __32BIT__\n#    undef far\n#    define far\n#    undef near\n#    define near\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  else /* !__386__ */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [ax dx] \\\n                                      modify [ax cx dx bx]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [ax] \\\n                                      modify [ax cx dx bx]\n#    endif /* !USE_ZLIB */\n#  endif /* ?__386__ */\n#endif /* __WATCOMC__ */\n\n#ifdef __EMX__\n#  ifndef __32BIT__\n#    define __32BIT__\n#  endif\n#  define far\n#  ifndef HAVE_MKTIME\n#    define HAVE_MKTIME\n#  endif\n#endif\n\n#if defined(__GO32__) || defined(__DJGPP__)    /* MS-DOS compiler, not OS/2 */\n#  ifndef __32BIT__\n#    define __32BIT__\n#  endif\n#  ifndef __GO32__\n#    define __GO32__\n#  endif\n#  ifndef HAVE_MKTIME\n#    define HAVE_MKTIME\n#  endif\n#  include <sys/timeb.h>           /* for structure ftime and ftime() */\n#  if (defined(__DJGPP__) && (__DJGPP__ > 1))\n#    include <unistd.h>            /* for prototypes for read/write etc. */\n#    include <dir.h>               /* for FA_LABEL */\n#    if ((__DJGPP__ == 2) && (__DJGPP_MINOR__ == 0))\n#      include <libc/dosio.h>      /* for _USE_LFN, djgpp 2.0 only */\n#    endif\n#    define USE_LFN _USE_LFN       /* runtime test:  support long filenames? */\n#  else\n     int setmode(int, int);        /* not in older djgpp's include files */\n#  endif\n#endif\n\n#ifndef __32BIT__\n#  define __16BIT__\n#endif\n\n#if (defined(M_I86CM) || defined(M_I86LM)) || defined(WINDLL)\n#  define MED_MEM\n#endif\n#if (defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__))\n#  define MED_MEM\n#endif\n#ifdef __16BIT__\n#  ifndef MED_MEM\n#    define SMALL_MEM\n#  endif\n#endif\n\n#define EXE_EXTENSION \".exe\"  /* OS/2 has GetLoadPath() function instead */\n\n#ifdef __16BIT__\n#  if defined(MSC) || defined(__WATCOMC__)\n#    include <malloc.h>\n#    define nearmalloc _nmalloc\n#    define nearfree _nfree\n#  endif\n#  if defined(__TURBOC__) && defined(DYNALLOC_CRCTAB)\n#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#      undef DYNALLOC_CRCTAB\n#    endif\n#  endif\n#  ifndef nearmalloc\n#    define nearmalloc malloc\n#    define nearfree free\n#  endif\n#  if defined(DEBUG) && defined(MSC) && (!defined(_MSC_VER) || _MSC_VER < 600)\n     /* for MSC 5.1, prevent macro expansion space overflow in DEBUG mode */\n#    define NO_DEBUG_IN_MACROS\n#  endif\n#  ifdef USE_DEFLATE64\n#    if (defined(M_I86TM) || defined(M_I86SM) || defined(M_I86MM))\n#      error Deflate64(tm) requires compact or large memory model\n#    endif\n#    if (defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__))\n#      error Deflate64(tm) requires compact or large memory model\n#    endif\n     /* the 64k history buffer for Deflate64 must be allocated specially */\n#    define MALLOC_WORK\n#    define MY_ZCALLOC\n#  endif\n#endif\n\n/* 32-bit MSDOS supports the 32-bit optimized CRC-32 C code */\n#ifdef IZ_CRC_BE_OPTIMIZ\n# undef IZ_CRC_BE_OPTIMIZ\n#endif\n#ifdef __32BIT__\n# if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ)\n#  define IZ_CRC_LE_OPTIMIZ\n# endif\n#else /* __16BIT__ does not support optimized C crc32 code */\n# ifdef IZ_CRC_LE_OPTIMIZ\n#  undef IZ_CRC_LE_OPTIMIZ\n# endif\n#endif\n\n/* another stat()/fopen() bug with some 16-bit compilers on Novell drives;\n * very dangerous (silently overwrites executables in other directories)\n */\n#define NOVELL_BUG_WORKAROUND\n\n/* enables additional test and message code that directs UnZip to fail safely\n * in case the \"workaround\" enabled above does not work as intended\n */\n#define NOVELL_BUG_FAILSAFE\n\n/* Some implementations of stat() tend to fail on \".\" in root directories\n * or on remote (root) directories specified by an UNC network path. This\n * patch of stat() is useful for at least the WATCOM compilers. The\n * stat_bandaid() wrapper detects stat failures on root directories and\n * fills in suitable values.\n */\n#ifdef DOS_STAT_BANDAID\n#  ifdef SSTAT\n#    undef SSTAT\n#  endif\n#  ifdef WILD_STAT_BUG\n#    define SSTAT(path,pbuf) (iswild(path) || stat_bandaid(path,pbuf))\n#  else\n#    define SSTAT stat_bandaid\n#  endif\n   int stat_bandaid(const char *path, struct stat *buf);\n#endif\n\n/* the TIMESTAMP feature is now supported on MSDOS, enable it per default */\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n/* The optional \"long filename\" support available with some MSDOS compiler\n * environments running under VFAT systems (Win95) is controlled with the\n * help of the two preprocessor symbols USE_VFAT and USE_LFN:\n *  - USE_VFAT is a compile time switch that selects the long filename\n *             semantics in mapname()\n *  - USE_LFN  is a macro equating to a boolean expression indicating\n *             whether long filenames are supported. If available, this\n *             macro should make use of a runtime function checking the\n *             LFN support.\n *\n * The code in msdos.c distinguishes three cases:\n * 1.) USE_VFAT is not defined:\n *     No support of LFN is included; filenames are mapped to 8+3 plain FAT\n *     syntax unconditionally.\n *     This is achieved by ``#define MAYBE_PLAIN_FAT'' to include the plain\n *     FAT name mapping code and by ``#undef USE_LFN'' to disable bypassing\n *     of the FAT mapping at runtime.\n * 2.) USE_VFAT is defined:\n *     Support for LFN is enabled.\n *  a) USE_LFN is undefined:\n *     There is no (runtime) check available to distinguish between OS\n *     environments that support VFAT extensions and those that do not.\n *     In this case, filenames are mapped to the more liberal VFAT LFN\n *     syntax unconditionally. The internal switch MAYBE_PLAIN_FAT remains\n *     undefined to exclude to \"map to plain FAT\" code parts.\n *  b) USE_LFN is defined (hopefully to a boolean runtime LFN check function):\n *     \"#define MAYBE_PLAIN_FAT\" is applied to include the plain FAT mapping\n *     code; the programs checks at runtime whether the OS supports LFN and\n *     uses the appropiate mapping syntax.\n */\n/* Some environments, like DJGPP v2, can support long filenames on VFAT\n * systems and DOS 8.3 filenames on FAT systems in the same executable.  If\n * such support is available, USE_LFN should be defined to an expression\n * that will return non-zero when long filenames API should be used, zero\n * otherwise.\n */\n#ifndef USE_VFAT\n#  ifdef USE_LFN\n#    undef USE_LFN\n#  endif\n#  ifndef MAYBE_PLAIN_FAT\n#    define MAYBE_PLAIN_FAT\n#  endif\n#else\n#  ifdef USE_LFN\n#    define MAYBE_PLAIN_FAT\n#  endif\n#endif\n\n#ifdef ACORN_FTYPE_NFS\n#  undef ACORN_FTYPE_NFS        /* no commas allowed in short filenames */\n#endif\n\n/* handlers for OEM <--> ANSI string conversions */\n#ifdef WINDLL\n#  if 1\n     /* C RTL's file system support assumes OEM-coded strings */\n#    ifdef CRTL_CP_IS_ISO\n#      undef CRTL_CP_IS_ISO\n#    endif\n#    ifndef CRTL_CP_IS_OEM\n#      define CRTL_CP_IS_OEM\n#    endif\n#  else\n     /* C RTL's file system support assumes ISO-coded strings */\n#    ifndef CRTL_CP_IS_ISO\n#      define CRTL_CP_IS_ISO\n#    endif\n#    ifdef CRTL_CP_IS_OEM\n#      undef CRTL_CP_IS_OEM\n#    endif\n#  endif /* ?(code page of 16bit Windows compilers) */\n   /* include Win API declarations only in sources where conversion is\n    * actually used (skip __EXTRACT_C, extract.c includes windll.h instead)\n    */\n#  if defined(__ENVARGS_C) || defined(__UNZIP_C) || defined(ZCRYPT_INTERNAL)\n#    include <windows.h>\n#  endif\n   /* use conversion functions of Windows API */\n#  ifdef CRTL_CP_IS_ISO\n#   define ISO_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#   define OEM_TO_INTERN(src, dst)  OemToAnsi(src, dst)\n#   define INTERN_TO_ISO(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#   define INTERN_TO_OEM(src, dst)  AnsiToOem(src, dst)\n#  endif\n#  ifdef CRTL_CP_IS_OEM\n#   define ISO_TO_INTERN(src, dst)  AnsiToOem(src, dst)\n#   define OEM_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#   define INTERN_TO_ISO(src, dst)  OemToAnsi(src, dst)\n#   define INTERN_TO_OEM(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  endif\n#  define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1)\n#  define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1)\n   /* UzpPassword supplies ANSI-coded string regardless of C RTL's native CP */\n#  define STR_TO_CP2(dst, src)  (AnsiToOem(src, dst), dst)\n   /* dummy defines to disable these functions, they are not needed */\n#  define STR_TO_ISO\n#  define STR_TO_OEM\n#else\n   /* use home-brewed conversion functions; internal charset is OEM */\n#  ifdef CRTL_CP_IS_ISO\n#    undef CRTL_CP_IS_ISO\n#  endif\n#  ifndef CRTL_CP_IS_OEM\n#    define CRTL_CP_IS_OEM\n#  endif\n#endif\n#ifndef NEED_ISO_OEM_INIT\n#  define NEED_ISO_OEM_INIT\n#endif\n\n/* SCREENLINES macros for 16-bit and djgpp compilers */\n#ifdef __16BIT__\n#  define SCREENLINES (int)(*((unsigned char far*)0x00400084L) + 1)\n#  define SCREENWIDTH (int)(*(unsigned short far*)0x0040004AL)\n#endif\n\n#if defined(__GO32__) || defined(__DJGPP__)    /* djgpp v1.x and v2.x */\n#  include <pc.h>\n#  define SCREENLINES ScreenRows()\n#  define SCREENWIDTH ScreenCols()\n#endif\n\n#ifdef __EMX__\n#  define SCREENWIDTH 80\n#  define SCREENSIZE(scrrows, scrcols)  screensize(scrrows, scrcols)\n   int screensize(int *tt_rows, int *tt_cols);\n#endif\n\n#ifdef WATCOMC_386\n#  define SCREENWIDTH 80\n#  define SCREENSIZE(scrrows, scrcols)  screensize(scrrows, scrcols)\n   int screensize(int *tt_rows, int *tt_cols);\n#endif\n\n#ifndef SCREENSIZE\n#  define SCREENSIZE(scrrows, scrcols) { \\\n        if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \\\n        if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; }\n#endif\n\n/* on the DOS console screen, line-wraps are always enabled */\n#define SCREENLWRAP 1\n#define TABSIZE 8\n\n#endif /* !__doscfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.bc",
    "content": "# Makefile for UnZip(SFX) and fUnZip for Borland C++ 2.x-4.x and Turbo C++ 1.0\n# Version: 5.53 and later        Alvin Koh, Jim Knoble, Christian Spieler, etc.\n#\n# Last revised:  29 Dec 05\n#\n# To compile with Turbo C++ 1.0, set the macro CC_REV to 1 at the command line\n# (make -fmsdos/makefile.bc -DCC_REV=1).\n\n\n#    GNU make doesn't like the return value from \"rem\"\n#STRIP=rem\nSTRIP=echo  Ignore this line.\n#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:\n#    (NOTE: upx needs a 386 or higher system to run the exe compressor)\n#STRIP=upx --8086 --best\n#    or\n#STRIP=lzexe\n#    or\n#STRIP=pklite\n#    This makes a big difference in .exe size (and possibly load time).\n\n\n#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)\n#    should be added to the environment via \"set LOCAL_UNZIP=-DFOO\" or added\n#    to the declaration of LOC here:\nLOC = $(LOCAL_UNZIP)\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n# (De)Select inclusion of optimized assembler CRC32 routine:\nUSE_ASMCRC = 1\n\n!if $(CC_REV) == 1\n# Turbo C++ 1.0\nCC = tcc\n!else\n# Borland C++ 2.0, 3.0, 3.1 ...\n! if !$(CC_REV)\nCC_REV = 3\n! endif\nCC = bcc\n!endif\n\nAS = tasm\n\n# \"near data\" model is sufficient for UnZip and ZipInfo, now that strings moved\n# switched to medium model; UnZip code has grown beyond the 64k limit.\n# since 5.42: switched to large model; medium model requires to much memory\n# to compile zipinfo, reported for BC++ 4.51 and TC++ 1.0\n# (compilation worked with 624k DOS memory and TC++ 1.0, but that much free\n# space requires an almost \"empty\" DOS system)\n# for 5.5: large or compact model required for Deflate64 support\nUNMODEL = l\t\t# large model for UnZip and ZipInfo\nASUNMODEL=__LARGE__\t# keep in sync with UNMODEL definition !!\n\nFUMODEL = c\t\t# need compact model for fUnZip with Deflate64 support\nASFUMODEL=__COMPACT__\t# keep in sync with FUMODEL definition !!\n\nSXMODEL = s\t\t# use small model for SFXUnZip (no Deflate64 support)\nASSXMODEL=__SMALL__\t# keep in sync with SXMODEL definition !!\n\n!if $(USE_ASMCRC)\nASMFLG = -DASM_CRC\nASMOBJS = crc_i86.obj\nASMOBJF = crc_i86_.obj\nASMOBJX = crc_i86x.obj\n!else\nASMFLG =\nASMOBJS =\nASMOBJF =\nASMOBJX =\n!endif\n\n\n# compiler flags\n\nASCPUFLAG = __$(CPU_TYP)86\n!if $(CPU_TYP) != 0\nCC_CPUFLG = -$(CPU_TYP)\n!endif\nASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC)\n!if $(CC_REV) == 1\n# Bug: TC ++ 1.0 ignores \"far\" on \"const\" strings, so const is disabled!\nCCOPTIM = -O -G -Z -a -d -DZCONST\nLDFLAGS = -lxncd\t\t# for tcc\n!else\nCCOPTIM = -O2\nLDFLAGS = -lxncd -l-P\t\t# for bcc\n!endif\nCFLAGS  = $(CCOPTIM) $(CC_CPUFLG) -ff- -k- -P-.C -I. $(ASMFLG) $(LOC)\nUNFLAGS = -m$(UNMODEL) $(CFLAGS)\nFUFLAGS = -m$(FUMODEL) $(CFLAGS) -K -d\nSXFLAGS = -m$(SXMODEL) $(CFLAGS)\n\n# implicit rules\n\n.asm.obj:\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) $<\n\n.c.obj:\n\t$(CC) -c $(UNFLAGS) {$< }\n\n# list macros\n\nOBJU1 = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj\nOBJU2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj\nOBJU3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj\nOBJUS = msdos.obj $(ASMOBJS)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS)\nOBJF  = funzip.obj crc32f.obj cryptf.obj globalsf.obj inflatef.obj \\\n\tttyiof.obj msdosf.obj $(ASMOBJF)\nOBJX1 = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj fileiox.obj\nOBJX2 = globalsx.obj inflatex.obj matchx.obj processx.obj ttyiox.obj\nOBJXS = msdosx.obj $(ASMOBJX)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJXS)\n\nUNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h\n\n# explicit rules\n\nall:    unzip.exe funzip.exe unzipsfx.exe\n\nunzip.exe:      $(OBJU)\n\t$(CC) -m$(UNMODEL) $(LDFLAGS) -eunzip.exe @&&|\n$(OBJU)\n|\n\t$(STRIP) unzip.exe\n\nfunzip.exe:     $(OBJF)\n\t$(CC) -m$(FUMODEL) $(LDFLAGS) -efunzip.exe @&&|\n$(OBJF)\n|\n\t$(STRIP) funzip.exe\n\nunzipsfx.exe:   $(OBJX)\n\t$(CC) -m$(SXMODEL) $(LDFLAGS) -eunzipsfx.exe @&&|\n$(OBJX)\n|\n\t$(STRIP) unzipsfx.exe\n\nclean:\n\trem Ignore any errors in the following...\n\t-del *.obj\n\t-del unzip.exe\n\t-del funzip.exe\n\t-del unzipsfx.exe\n\n# individual file dependencies\n\ncrc32.obj:      crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt.obj:      crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs.obj:    envargs.c $(UNZIP_H)\nexplode.obj:    explode.c $(UNZIP_H)\nextract.obj:    extract.c $(UNZIP_H) crc32.h crypt.h\nfileio.obj:     fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals.obj:    globals.c $(UNZIP_H)\ninflate.obj:    inflate.c inflate.h $(UNZIP_H)\nlist.obj:       list.c $(UNZIP_H)\nmatch.obj:      match.c $(UNZIP_H)\nprocess.obj:    process.c $(UNZIP_H) crc32.h\nttyio.obj:      ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nunreduce.obj:   unreduce.c $(UNZIP_H)\nunshrink.obj:   unshrink.c $(UNZIP_H)\nunzip.obj:      unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo.obj:    zipinfo.c $(UNZIP_H)\n\ncrc_i86.obj:    msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\\crc_i86.asm, $*.obj ;\n\ncrc_i86_.obj:   msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos\\crc_i86.asm, $*.obj ;\n\ncrc_i86x.obj:   msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASSXMODEL) msdos\\crc_i86.asm, $*.obj ;\n\nmsdos.obj:      msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(UNFLAGS) msdos/msdos.c\n\nfunzip.obj:     funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(FUFLAGS) funzip.c\n\ncrc32f.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -ocrc32f.obj crc32.c\n\ncryptf.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -ocryptf.obj crypt.c\n\nglobalsf.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -oglobalsf.obj globals.c\n\ninflatef.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -oinflatef.obj inflate.c\n\nttyiof.obj:     ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -ottyiof.obj ttyio.c\n\nmsdosf.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(FUFLAGS) -DFUNZIP -omsdosf.obj msdos/msdos.c\n\nunzipsfx.obj:   unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(SXFLAGS) -DSFX -ounzipsfx.obj unzip.c\n\ncrc32x.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(SXFLAGS) -DSFX -ocrc32x.obj crc32.c\n\ncryptx.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(SXFLAGS) -DSFX -ocryptx.obj crypt.c\n\nextractx.obj:   extract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(SXFLAGS) -DSFX -oextractx.obj extract.c\n\nfileiox.obj:    fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(SXFLAGS) -DSFX -ofileiox.obj fileio.c\n\nglobalsx.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -DSFX -oglobalsx.obj globals.c\n\ninflatex.obj:   inflate.c inflate.h $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -DSFX -oinflatex.obj inflate.c\n\nmatchx.obj:     match.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -DSFX -omatchx.obj match.c\n\nprocessx.obj:   process.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(SXFLAGS) -DSFX -oprocessx.obj process.c\n\nttyiox.obj:     ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(SXFLAGS) -DSFX -ottyiox.obj ttyio.c\n\nmsdosx.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -DSFX -omsdosx.obj msdos/msdos.c\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.dj1",
    "content": "# Makefile for Info-ZIP's unzip, zipinfo, funzip and unzipsfx\n# using djgpp v1.12m4.  Tested with unzip550 by Christian Spieler\n#\n# This Makefile is specifically tailored for GNU Make and GNU C and\n# may not work with a generic UNIX compatible Make utility.\n# Features use:\n# - pattern rules (%.o : %.c, etc.)\n# - GNUMake conditionals and functions  (ifeq, $(patsubst,,),...)\n#\n# To allow mixed use of real mode (16bit) vs. GO32 (32bit protected mode)\n# GNUMake utility and GCC driver, precautions have been taken to\n# limit command lines to the DOS 126 bytes limit.\n# In case you have an environment that supports long command lines\n# at all \"interface\" levels (e.g.: DJGPPv1 Gmake 3.71 and GO32 gcc.exe),\n# you may define the Makefile macro LONGARGS to take advantage of the\n# \"long command lines\" capability.\n# I have archived the fastest compilation (with LONGARGS support!) by\n# using both a real mode gnumake (private port) and the real mode\n# gcc.exe driver.\n#\n# The Makefile allows the optional creation of standalone exectutables.\n# This has the advantage that unzip.exe does not rely on any other file,\n# but results in much larger executables.\n#\n\n# Separators colon and <sp> are used in U**X, semi-colon and <sp> in DOS.\nVPATH=. msdos\n\nifdef NOASM\nUSE_ASMCRC=\nelse\nUSE_ASMCRC=1\nendif\n\n# UnZip flags\nLOC=-DDOS $(ASMFLG) $(LOCAL_UNZIP)\nCC=gcc\nLD=$(CC)\nCPPFLAGS=-I. $(LOC)\nASFLAGS=$(CPPFLAGS)\nCFLAGS=-Wall -O2 -m486 $(CPPFLAGS)\nFUN_FLAGS=$(CFLAGS) -DFUNZIP\nSFX_FLAGS=$(CFLAGS) -DSFX\nLDFLAGS=-s -v\nLIBS=-lpc\n\nSTRIP=strip\n\n# Define the STANDALONE macro to create executables which can be\n# used without any external extender file.\n# >>> NOTE: Either copy the go32 extender into your build directory, or\n# >>>       edit the STUBIFY macro and add the correct path to \"go32.exe\".\nifdef STANDALONE\nSTUBIFY=coff2exe -s go32.exe\nelse\nSTUBIFY=coff2exe\nendif\n\n# general-purpose stuff\n# If cp.exe is not found change to CP=copy /Y    .\nCP = cp -f\n# If install.exe is not found change to INSTALL=$(CP)   .\nINSTALL=install\n# The default value of RM is \"rm -f\"  .  If rm.exe is not found, uncomment\n# the following:\nRM=del\nE = .exe\nO = .o\nM=msdos\n\n# defaults for crc32 stuff and system dependent headers\nifdef USE_ASMCRC\nASMFLG = -DASM_CRC\nCRCA_O = crc_gcc$O\nelse\nASMFLG =\nCRCA_O =\nendif\n\n# object files\nOBJS1 = unzip$O crc32$O $(CRCA_O) crypt$O envargs$O explode$O\nOBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O\nOBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O\nOBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O\n\nOBJX1 = unzipsfx$O crc32_$O $(CRCA_O) crypt_$O extract_$O fileio_$O\nOBJX2 = globals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O\nOBJX = $(OBJX1) $(OBJX2)\n\nOBJF = funzip$O crc32-$O $(CRCA_O) crypt-$O globals-$O inflate-$O ttyio-$O\n\nOBJECTS_ALL = $(sort $(OBJS) $(OBJX) $(OBJF) crc_gcc$O)\n\n# Common header files included by all C sources:\nUNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h\n\n# executable files\nUNZIPS = unzip$E zipinfo$E funzip$E unzipsfx$E\n\n# pattern rules to compile the sources:\n%$O : %.c\n\t$(CC) $(CFLAGS) -c $< -o $@\n\n%-$O: %.c\n\t$(CC) $(FUN_FLAGS) -c $< -o $@\n\n%_$O: %.c\n\t$(CC) $(SFX_FLAGS) -c $< -o $@\n\n%sfx$O: %.c\n\t$(CC) $(SFX_FLAGS) -c $< -o $@\n\nall: unzips\n\nunzips:\tunzip$E zipinfo$E funzip$E unzipsfx$E\n\nunzip$E: $(OBJS)\nifdef LONGARGS\n\t$(LD) $(LDFLAGS) $(OBJS) $(LIBS) -o unzip\nelse\n\techo $(OBJS1) > unzip.rsp\n\techo $(OBJS2) >> unzip.rsp\n\techo $(OBJS3) $M$O >> unzip.rsp\n\techo $(LIBS) >> unzip.rsp\n\t$(LD) $(LDFLAGS) -o unzip @unzip.rsp\n\t$(RM) unzip.rsp\nendif\n\t$(STRIP) unzip\n\t$(STUBIFY) unzip\n\tstubedit $@ globbing=no\n\t$(RM) unzip\n\nzipinfo$E: unzip$E\n\tcoff2exe -g zipinfo\n\tstubedit $@ runfile=unzip globbing=no\n\nfunzip$E: $(OBJF)\n\t$(LD) $(LDFLAGS) $(OBJF) -o funzip\n\t$(STRIP) funzip\n\t$(STUBIFY) funzip\n\t$(RM) funzip\n\nunzipsfx$E: $(OBJX)\nifdef LONGARGS\n\t$(LD) $(LDFLAGS) $(OBJX) $(LIBS) -o unzipsfx\nelse\n\techo $(OBJX1) > unzipsfx.rsp\n\techo $(OBJX2) >> unzipsfx.rsp\n\techo $(LIBS) >> unzipsfx.rsp\n\t$(LD) $(LDFLAGS) -o unzipsfx @unzipsfx.rsp\n\t$(RM) unzipsfx.rsp\nendif\n\t$(STRIP) unzipsfx\n\t$(STUBIFY) unzipsfx\n\tstubedit $@ globbing=no\n\t$(RM) unzipsfx\n\n# explicit compilation instructions:\ncrc_gcc$O: crc_i386.S\t\t# 32bit, GNU AS\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\n# BIN_PATH may be defined in djgpp.env [make] or defined above.\ninstall:\n\t$(INSTALL) $(UNZIPS) $(BIN_PATH)\n\nuninstall:\n\tcd $(BIN_PATH); $(RM) $(UNZIPS)\n\nclean:\nifeq ($(firstword $(RM)), del)\n\t$(RM) *$O\n\t$(RM) *.zip\nelse\n\t$(RM) $(OBJECTS_ALL) *.zip\nendif\n\n# Source dependencies:\ncrc_gcc$O:      crc_i386.S\ncrc32$O:        crc32.c $(UNZIP_H) zip.h crc32.h\ncrc32-$O:       crc32.c $(UNZIP_H) zip.h crc32.h\ncrc32_$O:       crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt$O:        crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\ncrypt-$O:       crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\ncrypt_$O:       crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs$O:      envargs.c $(UNZIP_H)\nexplode$O:      explode.c $(UNZIP_H)\nextract$O:      extract.c $(UNZIP_H) crc32.h crypt.h\nextract_$O:     extract.c $(UNZIP_H) crc32.h crypt.h\nfileio$O:       fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfileio_$O:      fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfunzip$O:       funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\nglobals$O:      globals.c $(UNZIP_H)\nglobals-$O:     globals.c $(UNZIP_H)\nglobals_$O:     globals.c $(UNZIP_H)\ninflate$O:      inflate.c inflate.h $(UNZIP_H)\ninflate-$O:     inflate.c inflate.h $(UNZIP_H) crypt.h\ninflate_$O:     inflate.c inflate.h $(UNZIP_H)\nlist$O:         list.c $(UNZIP_H)\nmatch$O:        match.c $(UNZIP_H)\nmatch_$O:       match.c $(UNZIP_H)\nmsdos$O:        msdos/msdos.c $(UNZIP_H)\nmsdos_$O:       msdos/msdos.c $(UNZIP_H)\nprocess$O:      process.c $(UNZIP_H) crc32.h\nprocess_$O:     process.c $(UNZIP_H) crc32.h\nttyio$O:        ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nttyio-$O:       ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nttyio_$O:       ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$O:      ubz2err.c $(UNZIP_H)\nubz2err_$O:     ubz2err.c $(UNZIP_H)\nunreduce$O:     unreduce.c $(UNZIP_H)\nunshrink$O:     unshrink.c $(UNZIP_H)\nunzip$O:        unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nunzipsfx$O:     unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo$O:      zipinfo.c $(UNZIP_H)\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.dj2",
    "content": "# Makefile for Info-ZIP's UnZip, UnZipSFX and fUnZip using DJGPP v2.01 or\n# higher, by Frank Donahoe.                      Last updated: 21 Jul 2008\n\n# This Makefile is specifically tailored for GNU make and GNU C and\n# may not work with a generic Unix-compatible make utility.  The latest\n# make version is 3.78.1.  Thanks to Eli Zaretskii for generously responding\n# to questions with advice on the changes needed to make install work under\n# DJGPP version 2.0x.\n# Features used:\n# - pattern rules (%.o : %.c, etc.)\n# - GNU-specific conditionals and functions  (ifeq, $(patsubst,,),...)\n# - simply expanded variables (VAR := text)\n#\n# The stand-alone executable requires DPMI services to run.  If running\n# in a DOS window under Windows 3.1 or later, the dpmi server is auto-\n# matically present.  Under DOS, if a DPMI server is not loaded, the\n# program will look for \"cwsdpmi.exe.\"  If found, it will be loaded for\n# the duration of the program.\n#\n# cwsdpmi is a \"free\" dpmi server written by Charles W. Sandmann\n# (sandman@clio.rice.edu).  It may be found, among other sites, on SimTel\n# Net at the URL:\n#\n#   ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2misc/csdpmi?[b,s].zip\n#\n# and on its mirrors worldwide.  The latest version as of this writing is 5.\n# Archives with the b postscript contain the binaries.  An alternate server\n# is found, l.c., in the archive pmode??[b,s].zip.  The latest (20001022) is\n# v1.3.\n\n# Separators colon and <sp> are used in Unix, semi-colon and <sp> in DOS.\nVPATH=. msdos\n\nifdef NOASM\nUSE_ASMCRC=\nelse\nUSE_ASMCRC=1\nendif\n\n.PHONY : clean install uninstall\n\n# UnZip flags\n# LOCAL_UNZIP may be set in \"AUTOEXEC.BAT\" or defined in \"djgpp.env\" under\n# [make] as in the example below.  Or, if you habitually work in a DOS box\n# under Windows9x, right click on the MS-DOS icon, select properties, then\n# program, to find a slot called batch file, where you may specify the path\n# to a file which will set the variables of choice every time the box is\n# opened.\n# See, for example, DOSWILD, in the file INSTALL.\n\n# [make]\n# +BUTT=-mcpu=pentiumpro\n# +LOC=-W -Wall\n# +LOCAL_UNZIP=-DUSE_UNSHRINK\n\n# BUTT may be defined to specify the target system.  With gcc v2.95,\n# optimizing options like \"-mcpu=pentiumpro -march=pentiumpro\" are supported,\n# but the traditional \"-m386\" and \"-m486\" options of previous gcc 2.x\n# version will continue to work.\n# So if you are in the habit of compiling from source, programs for your\n# own use, it is well to consult gcc's manual for options suitable to\n# your processer and to set BUTT accordingly.  Consult INSTALL for\n# LOCAL_UNZIP.\n\nLOC=\nCC=gcc\nLD=$(CC)\nCPPFLAGS=-I. $(INC_BZ2LIB) -DDOS -DUSE_VFAT $(ASMFLG) $(LOCAL_UNZIP) $(LOC)\nASFLAGS=$(CPPFLAGS)\nCFLAGS=-Wall -O2 $(BUTT) $(CPPFLAGS)\n\n# See INSTALL for discussion of SFX_EXDIR.\n# EXDIR=-DSFX_EXDIR\n\nFUN_FLAGS=$(CFLAGS) -DFUNZIP\n\n# Include OFP for a modest decrease in size of unzipsfx.exe.\nOFP=-fomit-frame-pointer\n\nSFX_FLAGS=-Wall -O2 $(CPPFLAGS) -DSFX $(EXDIR) $(OFP)\nLDFLAGS=-s\n\n# general-purpose stuff\n# If cp.exe is not found change to CP=copy /Y    .\nCP = cp -fp\n# If install.exe is not found change to INSTALL=$(CP)   .  To prevent a\n# conflict with any of the many different \"install's\" that might be found\n# in the path, GNU install will be called as `ginstall'.  This also bypasses\n# a stub bug that cropped up with the install from fil316b.zip.\nINSTALL=ginstall\n# The default value of RM is \"rm -f\"  .  If rm.exe is not found, uncomment\n# the following:\n# RM=del\n# Laszlo Molnar who wrote DJ Packer and Markus F. X. J. Oberhumer who wrote\n# the compression library used by the DJ Packer have collaborated on the\n# Ultimate Packer for eXecutables, which has recently been released.  Look\n# for upx???d.zip at     http://upx.sourceforge.net/\n# As an alternative, look for \"djp.exe\", now two years old, in the archive\n# mlp107[b,s].zip, found in the same location as csdpmi?[b,s].zip (see above).\n# Do not add the option -s to djp.exe without making the required changes\n# to the target zipinfo$E.  Uncomment the three lines beginning with $(DJP)\n# or $(DJPSX).\n\n#DJP = djp -q\n#DJPSX = djp -q -s\nDJP = upx -qq --best\nDJPSX = $(DJP)\nE = .exe\nO = .o\nM=msdos\n\n# defaults for crc32 stuff and system dependent headers\nifdef USE_ASMCRC\nASMFLG = -DASM_CRC\nCRCA_O = crc_gcc$O\nelse\nASMFLG =\nCRCA_O =\nendif\n\n# optional inclusion of bzip2 decompression\nIZ_BZIP2 = bzip2\nifdef USEBZ2\nINC_BZ2LIB = -I$(IZ_BZIP2)\nLOCAL_UNZIP:=-DUSE_BZIP2 $(LOCAL_UNZIP)\nLD_BZ2LIB = -L$(IZ_BZIP2) -lbz2\nLIBBZIP2 = $(IZ_BZIP2)/libbz2.a\nelse\nINC_BZ2LIB =\nLD_BZ2LIB =\nLIBBZIP2 =\nendif\n\n# object files\nOBJS1 = unzip$O crc32$O $(CRCA_O) crypt$O envargs$O explode$O\nOBJS2 = extract$O fileio$O globals$O inflate$O list$O match$O\nOBJS3 = process$O ttyio$O ubz2err$O unreduce$O unshrink$O zipinfo$O\nOBJS = $(OBJS1) $(OBJS2) $(OBJS3) $M$O\n\nOBJX = unzipsfx$O crc32_$O $(CRCA_O) crypt_$O extract_$O fileio_$O \\\n\tglobals_$O inflate_$O match_$O process_$O ttyio_$O ubz2err_$O $M_$O\n\nOBJF = funzip$O crc32-$O $(CRCA_O) crypt-$O globals-$O inflate-$O ttyio-$O\n\nOBJECTS_ALL = $(sort $(OBJS) $(OBJX) $(OBJF) crc_gcc$O)\n\n# Common header files included by all C sources:\nUNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h\n\n# executable files\nUNZIPS = unzip$E zipinfo$E funzip$E unzipsfx$E\n\n# pattern rules to compile the sources:\n%$O : %.c\n\t$(CC) $(CFLAGS) -c $< -o $@\n\n%-$O: %.c\n\t$(CC) $(FUN_FLAGS) -c $< -o $@\n\n%_$O: %.c\n\t$(CC) $(SFX_FLAGS) -c $< -o $@\n\n%sfx$O: %.c\n\t$(CC) $(SFX_FLAGS) -c $< -o $@\n\nall: unzips\n\nunzips:\tunzip$E zipinfo$E funzip$E unzipsfx$E\n\nunzip$E: $(OBJS) $(LIBBZIP2)\n\t$(LD) $(LDFLAGS) $(OBJS) $(LD_BZ2LIB) -o $@\n#\t$(DJP) $@\n\nzipinfo$E: unzip$E\n\tstubify -g $@\n\tstubedit $@ runfile=unzip argv0=zipinfo\n\nfunzip$E: $(OBJF)\n\t$(LD) $(LDFLAGS) $(OBJF) -o $@\n#\t$(DJP) $@\n\nunzipsfx$E: $(OBJX)\n\t$(LD) $(LDFLAGS) $(OBJX) -o $@\n#\t$(DJPSX) $@\n\n# create/update the library for the optional bzip2 support:\n$(IZ_BZIP2)/libbz2.a:\n\t$(MAKE) -C $(IZ_BZIP2) -f Makebz2.iz CC=\"$(CC)\" RM=\"$(RM)\"\n\n# explicit compilation instructions:\n\ncrc_gcc$O: crc_i386.S\t\t# 32bit, GNU AS\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ $<\n\n# BIN_PATH may be defined in djgpp.env [make] or defined below.  If the\n# installation is to the directory containing gcc.exe etc. place the\n# following in djgpp.env:\n\n# [make]\n# +BIN_PATH=%\\DJDIR%\\bin\n\n# Even if so placed, it can be over-ridden here by, say:\n# BIN_PATH=c:\\usr\\bin\n\ninstall:\n\t-@if not exist $(BIN_PATH)\\nul mkdir $(BIN_PATH)\n\tcommand.com /c for %f in ($(UNZIPS)) do $(INSTALL) %f $(BIN_PATH) > NUL\n\nuninstall:\n\tcommand.com /c for %f in ($(UNZIPS)) do $(RM) $(BIN_PATH)\\%f > NUL\n\nclean:\n\t$(MAKE) -C $(IZ_BZIP2) -f Makebz2.iz CC=\"$(CC)\" RM=\"$(RM)\" clean\nifeq ($(firstword $(RM)), del)\n\t$(RM) *$O\n\t$(RM) *.~\n\t$(RM) *.exe\nelse\n\t$(RM) $(OBJECTS_ALL) *.~ *.exe\nendif\n\n# Source dependencies:\ncrc_gcc$O:      crc_i386.S\ncrc32$O:        crc32.c $(UNZIP_H) zip.h crc32.h\ncrc32-$O:       crc32.c $(UNZIP_H) zip.h crc32.h\ncrc32_$O:       crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt$O:        crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\ncrypt-$O:       crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\ncrypt_$O:       crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs$O:      envargs.c $(UNZIP_H)\nexplode$O:      explode.c $(UNZIP_H)\nextract$O:      extract.c $(UNZIP_H) crc32.h crypt.h\nextract_$O:     extract.c $(UNZIP_H) crc32.h crypt.h\nfileio$O:       fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfileio_$O:      fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfunzip$O:       funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\nglobals$O:      globals.c $(UNZIP_H)\nglobals-$O:     globals.c $(UNZIP_H)\nglobals_$O:     globals.c $(UNZIP_H)\ninflate$O:      inflate.c inflate.h $(UNZIP_H)\ninflate-$O:     inflate.c inflate.h $(UNZIP_H) crypt.h\ninflate_$O:     inflate.c inflate.h $(UNZIP_H)\nlist$O:         list.c $(UNZIP_H)\nmatch$O:        match.c $(UNZIP_H)\nmatch_$O:       match.c $(UNZIP_H)\nmsdos$O:        msdos/msdos.c $(UNZIP_H)\nmsdos_$O:       msdos/msdos.c $(UNZIP_H)\nprocess$O:      process.c $(UNZIP_H) crc32.h\nprocess_$O:     process.c $(UNZIP_H) crc32.h\nttyio$O:        ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nttyio-$O:       ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nttyio_$O:       ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$O:      ubz2err.c $(UNZIP_H)\nubz2err_$O:     ubz2err.c $(UNZIP_H)\nunreduce$O:     unreduce.c $(UNZIP_H)\nunshrink$O:     unshrink.c $(UNZIP_H)\nunzip$O:        unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nunzipsfx$O:     unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo$O:      zipinfo.c $(UNZIP_H)\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.emx",
    "content": "# Makefile for UnZip, fUnZip and UnZipSFX\n# for emx 0.9c / gcc under MS-DOS. Derived from makefile.os2\n# By E-Yen Tan (with mods by Christian Spieler).\n# Last updated 25 December 2006 (Christian Spieler).\n#\n# This makefile should work fine with GNU make and hopefully some others.\n# Tested with GNU make 3.71 gnuish 16-bit and djgpp 32-bit versions.\n\n#ifdef NOASM\n#AS_FLAGS =\n#else\nAS_FLAGS = -DASM_CRC\n#endif\n\nCP=copy\nRM=del\n\nCC=gcc -O -I. -m486\n\n# Version 5.1 of the RSX extender provides long file name support under\n# Windows 95. If you don't have Windows 95 or use a version of RSX prior\n# to 5.1 (or simply don't want LFN support) remove -DUSE_VFAT from CFLAGS.\n# Note that if you have a version of RSX prior to 5.1, you can still compile\n# with USE_VFAT enabled and upgrade RSX.EXE at a later stage.\n#\n# If you enable USE_VFAT then long file names under plain DOS will simply be\n# truncated to 8.3 format without mapping. See doscfg.h for details.\n#\nCFLAGS=-Wall -DMSDOS $(AS_FLAGS) $(LOCAL_UNZIP) -DUSE_VFAT\nNFLAGS=\nDLLFLAG=\nAS=gcc\nASFLAGS=-Di386\nLDFLAGS=-o ./\nLDFLAGS2=-Zsmall-conv -s\nOUT=-o\nOBJ=.o\n\n#ifdef NOASM\n#CRCA_O=\n#else\nCRCA_O=crc_gcc$(OBJ)\n#endif\nOBJUS=msdos$(OBJ)\nOBJXS=msdos_$(OBJ)\nOSDEP_H=msdos/doscfg.h\n\n\n# default settings for target dependent macros:\nDIRSEP = /\nAS_DIRSEP = /\n\nOBJU1 = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ)\nOBJU2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ)\nOBJU3 = inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ)\nOBJU4 = ubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJUS)\nOBJX1 = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_O) crypt_$(OBJ)\nOBJX2 = extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ)\nOBJX3 = match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS)\nOBJF  = funzip$(OBJ) crc32f$(OBJ) $(CRCA_O) cryptf$(OBJ) inflatef$(OBJ) \\\n\tglobalsf$(OBJ) ttyiof$(OBJ)\n\nUNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES:\t.c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ $<\n\n# targets\n\nall:\tunzip.exe funzip.exe unzipsfx.exe\n\n# This next bit is nasty, but is needed to overcome the MS-DOS command\n# line limit as response files for emx's gcc seem to only work if each\n# file is on a different line. DJGPP doesn't do this (if you are at all\n# interested).\n\nunzip.exe: $(OBJU)\n\t@ echo off\n#\t-@ $(RM) unzip.rsp\n#\t@ for %f in ($(OBJU1)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU2)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU3)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU4) $(OBJUS)) do echo %f >> unzip.rsp\n\t@ echo unzip$(OBJ) > unzip.rsp\n\t@ echo crc32$(OBJ)  >> unzip.rsp\n\t@ if not \"$(CRCA_O)\"==\"\" echo $(CRCA_O)  >> unzip.rsp\n\t@ echo crypt$(OBJ)  >> unzip.rsp\n\t@ echo envargs$(OBJ)  >> unzip.rsp\n\t@ echo explode$(OBJ)  >> unzip.rsp\n\t@ echo extract$(OBJ)  >> unzip.rsp\n\t@ echo fileio$(OBJ)  >> unzip.rsp\n\t@ echo globals$(OBJ)  >> unzip.rsp\n\t@ echo inflate$(OBJ)  >> unzip.rsp\n\t@ echo list$(OBJ)  >> unzip.rsp\n\t@ echo match$(OBJ)  >> unzip.rsp\n\t@ echo process$(OBJ)  >> unzip.rsp\n\t@ echo ttyio$(OBJ)  >> unzip.rsp\n\t@ echo ubz2err$(OBJ)  >> unzip.rsp\n\t@ echo unreduce$(OBJ)  >> unzip.rsp\n\t@ echo unshrink$(OBJ)  >> unzip.rsp\n\t@ echo zipinfo$(OBJ)  >> unzip.rsp\n\t@ echo msdos$(OBJ)  >> unzip.rsp\n\t$(CC) $(LDFLAGS)$@ $(DEF) @unzip.rsp $(LDFLAGS2)\n\t@ $(RM) unzip.rsp\n\nfunzip.exe: $(OBJF)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(LDFLAGS2)\n\nunzipsfx.exe:\t$(OBJX)\n\t@ echo off\n#\t-@ $(RM) unzipsfx.rsp\n#\t@ for %f in ($(OBJX1)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJX2)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJX3)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJXS)) do echo %f >> unzipsfx.rsp\n\t@ echo unzipsf_$(OBJ) > unzipsfx.rsp\n\t@ echo crc32_$(OBJ)  >> unzipsfx.rsp\n\t@ if not \"$(CRCA_O)\"==\"\" echo $(CRCA_O)  >> unzipsfx.rsp\n\t@ echo crypt_$(OBJ)  >> unzipsfx.rsp\n\t@ echo extract_$(OBJ)  >> unzipsfx.rsp\n\t@ echo fileio_$(OBJ)  >> unzipsfx.rsp\n\t@ echo globals_$(OBJ)  >> unzipsfx.rsp\n\t@ echo inflate_$(OBJ)  >> unzipsfx.rsp\n\t@ echo match_$(OBJ)  >> unzipsfx.rsp\n\t@ echo process_$(OBJ)  >> unzipsfx.rsp\n\t@ echo ttyio_$(OBJ)  >> unzipsfx.rsp\n\t@ echo ubz2err_$(OBJ)  >> unzipsfx.rsp\n\t@ echo msdos_$(OBJ)  >> unzipsfx.rsp\n\t$(CC) $(LDFLAGS)$@ $(DEF) @unzipsfx.rsp $(LDFLAGS2)\n\t@ $(RM) unzipsfx.rsp\n\n# dependencies\n\napihelp$(OBJ):\tapihelp.c $(UNZIP_H) unzvers.h\ncrc32$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\nenvargs$(OBJ):\tenvargs.c $(UNZIP_H)\nexplode$(OBJ):\texplode.c $(UNZIP_H)\nextract$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\nfileio$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(OBJ):\tglobals.c $(UNZIP_H)\ninflate$(OBJ):\tinflate.c $(UNZIP_H)\nlist$(OBJ):\tlist.c $(UNZIP_H)\nmatch$(OBJ):\tmatch.c $(UNZIP_H)\nprocess$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\nttyio$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OBJ):\tubz2err.c $(UNZIP_H)\nunreduce$(OBJ):\tunreduce.c $(UNZIP_H)\nunshrink$(OBJ):\tunshrink.c $(UNZIP_H)\nunzip$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\napi$(OBJ):\tapi.c $(UNZIP_H) unzvers.h\nzipinfo$(OBJ):\tzipinfo.c $(UNZIP_H)\n\nfunzip$(OBJ):\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\t# funzip only\n\t$(CC) -c $(CFLAGS) $(OUT)$@ funzip.c\n\nmsdos$(OBJ):\tmsdos/msdos.c $(UNZIP_H) unzvers.h\t\t# DOS only\n\t$(CC) -c $(CFLAGS) $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nmsdos_$(OBJ):\tmsdos/msdos.c $(UNZIP_H)\t\t\t# DOS unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c\n\ncrc_gcc$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\n# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set\ncrypt$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) $(OUT)$@ crypt.c\n\n# funzip specific section\ncrc32f$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c\n\ncryptf$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c\n\nglobalsf$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c\n\ninflatef$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c\n\nttyiof$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c\n\n# unzipsfx specific section\ncrc32_$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c\n\nextract_$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c\n\nfileio_$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c\n\nglobals_$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c\n\ninflate_$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c\n\nmatch_$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c\n\nprocess_$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c\n\nttyio_$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c\n\nubz2err_$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ubz2err.c\n\nunzipsf_$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.msc",
    "content": "#------------------------------------------------------------------------------\n# Makefile for UnZip 5.53 and later                     Greg Roelofs and others\n# Version:  Microsoft C (5.x and later)                               29 Dec 05\n#------------------------------------------------------------------------------\n\n# Users of MSC 6/7 and NMAKE can use the Unix Makefile (target msc_dos),\n# if desired.  This makefile works just fine, too, however.  OS/2 users\n# can cross-compile using os2/makefile.os2 (target mscdos).  Note that\n# there is possibly a bug in MSC 6 which screws up funzip (goes into\n# infinite loop? --this has not been confirmed in over a year...).  There\n# is definitely a bug (internal compiler error) in MSC 6.00 while com-\n# piling explode.c (fixed in 6.0a, 6.0ax, 6.0ax2, 7.*, 8.*).\n\n\n#    GNU make doesn't like the return value from \"rem\"\n#STRIP=rem\nSTRIP=echo  Ignore this line.\n#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:\n#    (NOTE: upx needs a 386 or higher system to run the exe compressor)\n#STRIP=upx --8086 --best\n#    or\n#STRIP=lzexe\n#    or\n#STRIP=pklite\n#    and remove /e from LDFLAGS.\n#    This makes a big difference in .exe size (and possibly load time).\n\n#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)\n#    should be added to the environment via \"set LOCAL_UNZIP=-DFOO\" or added\n#    to the declaration of LOC here:\nLOC = $(LOCAL_UNZIP)\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n#UNMODEL=M\t# medium model for UnZip\n# with MSC 5.1, 6.0 and 8.x, small model exceeds 64k code segment; use medium\n# deflate64 support requires large or compact model\nUNMODEL=L\t# large model for UnZip with Deflate64 support\nFUMODEL=C\t# compact model for fUnZip (Deflate64 support enabled)\nSXMODEL=S\t# small model for UnZipSFX (without Deflate64 support)\n\n# name of Flag to select memory model for assembler compiles, supported\n# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :\n# for MSC 5.1 and 8.x use:\nASUNMODEL=__LARGE__\t# keep in sync with UNMODEL definition !!\nASFUMODEL=__COMPACT__\t# keep in sync with FUMODEL definition !!\nASSXMODEL=__SMALL__\t# keep in sync with SXMODEL definition !!\n\n# Uncomment the following three macros to use the optimized CRC32 assembler\n# routine in UnZip and UnZipSFX:\nASMFLG = -DASM_CRC\nASMOBJS = crc_i86.obj\nASMOBJF = crc_i86_.obj\nASMOBJX = crc_i86x.obj\n\nASCPUFLAG = __$(CPU_TYP)86\n\nCC = cl\n# add -G2(3,4) for 286 (386, 486) and/or -FPi87 for 80x87:\nCC_GENFLAGS = -nologo -DMSC $(ASMFLG) $(LOC) -I. -G$(CPU_TYP)\nCC_SPEEDOPT = -Oait -Gs         # -Ox does not work for inflate.c\nCC_SIZEOPT  = -Oas -Gs\nCFLAGS_UN = -A$(UNMODEL) $(CC_GENFLAGS) $(CC_SPEEDOPT)\nCFLAGS_FU = -A$(FUMODEL) $(CC_GENFLAGS) $(CC_SPEEDOPT) -DFUNZIP\nCFLAGS_SX = -A$(SXMODEL) $(CC_GENFLAGS) $(CC_SIZEOPT) -DSFX\n\nAS = masm\nASFLAGS = -ml -D$(ASCPUFLAG) $(LOC)\n\nLD = Link\t# mixed case to disable special handling by GNU Make\n# remove /e if you have LZEXE or PKLITE:\nLDFLAGS = /nologo/noi/e/st:0x0c00/farcall/packcode\n# \"/farcall/packcode\" are only useful for `large code' memory models\n# but should be a \"no-op\" for small code models.\nLDFLAGS2 = ,$*\nLDFLAGS2_UN = $(LDFLAGS2);\nLDFLAGS2_FU = $(LDFLAGS2);\nLDFLAGS2_SX = $(LDFLAGS2);\n\nOBJS1 = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj\nOBJS2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj\nOBJS3 = process.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj\nOBJS4 = msdos.obj $(ASMOBJS)\nOBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4)\n\nOBJX1 = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj fileiox.obj\nOBJX2 = globalsx.obj inflatex.obj matchx.obj processx.obj ttyiox.obj\nOBJX3 = msdosx.obj $(ASMOBJX)\nOBJX = $(OBJX1) $(OBJX2) $(OBJX3)\n\nOBJF = funzip.obj crc32_.obj crypt_.obj globals_.obj inflate_.obj ttyio_.obj \\\n\tmsdos_.obj $(ASMOBJF)\n\nUNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h\n\n\ndefault:        unzip.exe funzip.exe unzipsfx.exe\n\n#clean:\n# As long as the brain damaged old ``Make'' utility from MSC 5.1 and earlier\n# (NMAKE from MSC 6.0 + would work !) remains supported, a \"clean\" target\n# cannot be inserted !!\n\n# pattern rules for implicit dependencies:\n.asm.obj:\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) $<, $@;\n\n.c.obj:\n\t$(CC) -c $(CFLAGS_UN) $*.c\n\n# individual dependencies and action rules:\ncrc_i86.obj:    msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos/crc_i86.asm, $@;\n\ncrc_i86_.obj:   msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos/crc_i86.asm, $@;\n\ncrc_i86x.obj:   msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASSXMODEL) msdos/crc_i86.asm, $@;\n\ncrc32.obj:      crc32.c $(UNZIP_H) zip.h crc32.h\n\ncrc32_.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_FU) -Focrc32_.obj crc32.c\n\ncrc32x.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_SX) -Focrc32x.obj crc32.c\n\ncrypt.obj:      crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h\n\ncrypt_.obj:     crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h\n\t$(CC) -c $(CFLAGS_FU) -Focrypt_.obj crypt.c\n\ncryptx.obj:     crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h\n\t$(CC) -c $(CFLAGS_SX) -Focryptx.obj crypt.c\n\nenvargs.obj:    envargs.c $(UNZIP_H)\n\nexplode.obj:    explode.c $(UNZIP_H)\n\nextract.obj:    extract.c $(UNZIP_H) crc32.h crypt.h\n\nextractx.obj:   extract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGS_SX) -Foextractx.obj extract.c\n\nfileio.obj:     fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\nfileiox.obj:    fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS_SX) -Fofileiox.obj fileio.c\n\nfunzip.obj:     funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS_FU) funzip.c\n\nglobals.obj:    globals.c $(UNZIP_H)\n\nglobals_.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_FU) -Foglobals_.obj globals.c\n\nglobalsx.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) -Foglobalsx.obj globals.c\n\ninflate.obj:    inflate.c inflate.h $(UNZIP_H)\n\ninflate_.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS_FU) -Foinflate_.obj inflate.c\n\ninflatex.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS_SX) -Foinflatex.obj inflate.c\n\nlist.obj:       list.c $(UNZIP_H)\n\nmatch.obj:      match.c $(UNZIP_H)\n\nmatchx.obj:     match.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) -Fomatchx.obj match.c\n\nmsdos.obj:      msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_UN) msdos/msdos.c\n\nmsdos_.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_FU) -Fomsdos_.obj msdos/msdos.c\n\nmsdosx.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) -Fomsdosx.obj msdos/msdos.c\n\nprocess.obj:    process.c $(UNZIP_H) crc32.h\n\nprocessx.obj:   process.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS_SX) -Foprocessx.obj process.c\n\nttyio.obj:      ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\n\nttyio_.obj:     ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\n\t$(CC) -c $(CFLAGS_FU) -Fottyio_.obj ttyio.c\n\nttyiox.obj:     ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\n\t$(CC) -c $(CFLAGS_SX) -Fottyiox.obj ttyio.c\n\nunreduce.obj:   unreduce.c $(UNZIP_H)\n\nunshrink.obj:   unshrink.c $(UNZIP_H)\n\nunzip.obj:      unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\nunzipsfx.obj:   unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS_SX) -Founzipsfx.obj unzip.c\n\nzipinfo.obj:    zipinfo.c $(UNZIP_H)\n\n\n# MS make:\n# -------\nunzip.exe:      $(OBJS)\n\techo $(OBJS1)+ > unzip.rsp\n\techo $(OBJS2)+ >> unzip.rsp\n\techo $(OBJS3)+ >> unzip.rsp\n\techo $(OBJS4) >> unzip.rsp\n\techo $(LDFLAGS2_UN) >> unzip.rsp\n\t$(LD) $(LDFLAGS) @unzip.rsp\n\tdel unzip.rsp\n\t$(STRIP) unzip.exe\n\nunzipsfx.exe:   $(OBJX)\n\techo $(OBJX1)+ > unzipsfx.rsp\n\techo $(OBJX2)+ >> unzipsfx.rsp\n\techo $(OBJX3) >> unzipsfx.rsp\n\techo $(LDFLAGS2_UN) >> unzipsfx.rsp\n\t$(LD) $(LDFLAGS) @unzipsfx.rsp\n\tdel unzipsfx.rsp\n\t$(STRIP) unzipsfx.exe\n\nfunzip.exe:     $(OBJF)\n\techo $(OBJF) > funzip.rsp\n\techo $(LDFLAGS2_FU) >> funzip.rsp\n\t$(LD) $(LDFLAGS) @funzip.rsp\n\tdel funzip.rsp\n\t$(STRIP) funzip.exe\n\n# better makes which know how to deal with 128-char limit on command line:\n# -----------------------------------------------------------------------\n#unzip.exe:      $(OBJS)\n#\t$(LD) $(LDFLAGS) $(OBJS) $(LDFLAGS2)\n#\t$(STRIP) unzip.exe\n#\n#unzipsfx.exe:   $(OBJX)\n#\t$(LD) $(LDFLAGS) $(OBJX) $(LDFLAGS2)\n#\t$(STRIP) unzipsfx.exe\n#\n#funzip.exe:     $(OBJF)\n#\t$(LD) $(LDFLAGS) $(OBJF) $(LDFLAGS2_FU)\n#\t$(STRIP) funzip.exe\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.tc",
    "content": "#------------------------------------------------------------------------------\n# Makefile for UnZip 5.53 and later                            Jean-loup Gailly\n# Version:  Turbo C (edit and use makefile.bc for Turbo C++)          29 Dec 05\n#------------------------------------------------------------------------------\n\n#    GNU make doesn't like the return value from \"rem\"\n#STRIP=rem\nSTRIP=echo  Ignore this line. :-)\n#    If you don't have LZEXE or PKLITE, get one of them. Then define:\n#STRIP=lzexe\n#    or\n#STRIP=pklite\n#    This makes a big difference in .exe size (and possibly load time).\n\n#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)\n#    should be added to the environment via \"set LOCAL_UNZIP=-DFOO\" or added\n#    to the declaration of LOC here:\nLOC = $(LOCAL_UNZIP)\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n# memory model for UnZip (conflicting reports on whether Turbo C can or\n# cannot put strings into far memory; for now assume it can and use small\n# model *with* ZipInfo enabled...if fails, either define NO_ZIPINFO or\n# use large model)   [GRR 940712:  sigh, no go--inflate fails.  Back to\n# large model...]\n#UNMODEL = s\nUNMODEL = l\n# funzip can use small-model (compact-model when including Deflate64 support)\nFUMODEL = c\n\n# name of Flag to select memory model for assembler compiles, supported\n# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :\nASUNMODEL=__LARGE__\t# keep in sync with UNMODEL definition !!\nASFUMODEL=__COMPACT__\t# keep in sync with FUMODEL definition !!\n\n# Uncomment the following three macros to use the optimized CRC32 assembler\n# routine in UnZip and UnZipSFX:\nASMFLG = -DASM_CRC\nASMOBJS = crc_i86.obj\nASMOBJF = crc_i86_.obj\n\nCC = tcc\n\nAS = tasm\n\nASCPUFLAG = __$(CPU_TYP)86\nASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC)\nCFLAGS = -O -Z -I. -DFar= $(ASMFLG) $(LOC)\nUCFLAGS = -m$(UNMODEL) $(CFLAGS)\nULDFLAGS = -m$(UNMODEL)\nFCFLAGS = -m$(FUMODEL) $(CFLAGS)\nFLDFLAGS = -m$(FUMODEL)\n\nLDFLAGS2 =\n\nOBJS = unzip.obj crc32.obj crypt.obj envargs.obj explode.obj \\\n\textract.obj fileio.obj globals.obj inflate.obj list.obj match.obj \\\n\tprocess.obj ttyio.obj unreduce.obj unshrink.obj zipinfo.obj \\\n\tmsdos.obj $(ASMOBJS)\n\nOBJX = unzipsfx.obj crc32x.obj cryptx.obj extractx.obj \\\n\tfileiox.obj globalsx.obj inflatex.obj matchx.obj processx.obj \\\n\tttyiox.obj \\\n\tmsdosx.obj $(ASMOBJS)\n\nOBJF = funzip.obj crc32_.obj crypt_.obj globals_.obj inflate_.obj ttyio_.obj \\\n\tmsdos_.obj $(ASMOBJF)\n\nUNZIP_H = unzip.h unzpriv.h globals.h msdos/doscfg.h\n\n\ndefault:        unzip.exe unzipsfx.exe funzip.exe\n\nclean:\n\trem Ignore any errors in the following...\n\tdel *.ob\n\tdel *.obu\n\tdel *.obj\n\tdel unzip.exe\n\tdel funzip.exe\n\tdel unzipsfx.exe\n\n.asm.obj:\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) $*.asm\n\n.c.obj:\n\t$(CC) -c $(UCFLAGS) $*.c\n\ncrc_i86.obj:    msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\\crc_i86.asm, $*.obj ;\n\ncrc_i86_.obj:   msdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) -D$(ASFUMODEL) msdos\\crc_i86.asm, $*.obj ;\n\ncrc32.obj:      crc32.c $(UNZIP_H) zip.h crc32.h\n\ncrc32_.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -ocrc32_.obj crc32.c\n\ncrypt.obj:      crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h\n\ncrypt_.obj:     crypt.c $(UNZIP_H) crypt.h crc32.h ttyio.h zip.h\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -ocrypt_.obj crypt.c\n\nenvargs.obj:    envargs.c $(UNZIP_H)\n\nexplode.obj:    explode.c $(UNZIP_H)\n\nextract.obj:    extract.c $(UNZIP_H) crc32.h crypt.h\n\nextractx.obj:   extract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(UCFLAGS) -DSFX -oextractx.obj extract.c\n\nfileio.obj:     fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\nfunzip.obj:     funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(FCFLAGS) funzip.c\n\nglobals.obj:    globals.c $(UNZIP_H)\n\nglobals_.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -oglobals_.obj globals.c\n\ninflate.obj:    inflate.c inflate.h $(UNZIP_H)\n\ninflate_.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -oinflate_.obj inflate.c\n\nlist.obj:       list.c $(UNZIP_H)\n\nmatch.obj:      match.c $(UNZIP_H)\n\nmsdos.obj:      msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(UCFLAGS) msdos/msdos.c\n\nmsdos_.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -omsdos_.obj msdos/msdos.c\n\nmsdosx.obj:     msdos/msdos.c $(UNZIP_H)\n\t$(CC) -c $(UCFLAGS) -DSFX -omsdos_.obj msdos/msdos.c\n\nprocess.obj:    process.c $(UNZIP_H) crc32.h\n\nprocessx.obj:   process.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(UCFLAGS) -DSFX -oprocess_.obj process.c\n\nttyio.obj:      ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\n\nttyio_.obj:     ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\n\t$(CC) -c $(FCFLAGS) -DFUNZIP -ottyio_.obj ttyio.c\n\nunreduce.obj:   unreduce.c $(UNZIP_H)\n\nunshrink.obj:   unshrink.c $(UNZIP_H)\n\nunzip.obj:      unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\nunzipsfx.obj:   unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(UCFLAGS) -DSFX -ounzipsfx.obj unzip.c\n\nzipinfo.obj:    zipinfo.c $(UNZIP_H)\n\n\n# Turbo Make, which cannot deal with the MS-DOS 128-byte limit:\n# ------------------------------------------------------------\nunzip.exe:      $(OBJS)\n\trem   Ignore any warnings in the following commands:\n\tdel *.ob\n\tren crc32_.obj *.ob\n\tren crc_i86_.obj *.ob\n\tren crypt_.obj *.ob\n\tren extract_.obj *.ob\n\tren funzip.obj *.ob\n\tren globals_.obj *.ob\n\tren inflate_.obj *.ob\n\tren msdos_.obj *.ob\n\tren process_.obj *.ob\n\tren ttyio_.obj *.ob\n\tren unzipsfx.obj *.ob\n\t$(CC) $(ULDFLAGS) -eunzip.exe *.obj\n\tren *.ob *.obj\n\t@$(STRIP) unzip.exe\n\n# GRR 970901\nunzipsfx.exe:      $(OBJX)\n\trem   Ignore any warnings in the following commands:\n\tdel *.ob\n\tren crc32_.obj *.ob\n\tren crc_i86_.obj *.ob\n\tren crypt_.obj *.ob\n\tren envargs.obj *.ob\n\tren explode.obj *.ob\n\tren extract.obj *.ob\n\tren funzip.obj *.ob\n\tren globals_.obj *.ob\n\tren inflate_.obj *.ob\n\tren list.obj *.ob\n\tren msdos.obj *.ob\n\tren process.obj *.ob\n\tren ttyio_.obj *.ob\n\tren unreduce.obj *.ob\n\tren unshrink.obj *.ob\n\tren unzip.obj *.ob\n\tren zipinfo.obj *.ob\n\t$(CC) $(ULDFLAGS) -eunzipsfx.exe *.obj\n\tren *.ob *.obj\n\t@$(STRIP) unzipsfx.exe\n\n# better makes that know how to deal with 128-char limit on command line:\n# ----------------------------------------------------------------------\n#unzip.exe:      $(OBJS)\n#\t$(CC) $(ULDFLAGS) $(OBJS) $(LDFLAGS2)\n#\t@$(STRIP) unzip.exe\n#\n#unzipsfx.exe:     $(OBJX)\n#\t$(CC) $(ULDFLAGS) $(OBJX) $(LDFLAGS2)\n#\t@$(STRIP) unzipsfx.exe\n\n# both makes:\n# ----------\nfunzip.exe:     $(OBJF)\n\t$(CC) $(FLDFLAGS) $(OBJF) $(LDFLAGS2)\n\t@$(STRIP) funzip.exe\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/makefile.wat",
    "content": "# WMAKE makefile for 16 bit MSDOS or 32 bit DOS extender (PMODE/W or DOS/4GW)\n# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 16 Feb 2008.\n# Makes UnZip.exe, fUnZip.exe, and UnZipSFX.exe.\n#\n# Invoke from UnZip source dir with \"WMAKE -F MSDOS\\MAKEFILE.WAT [targets]\".\n# To make the PMODE/W version use \"WMAKE PM=1 ...\"\n# To make the DOS/4GW version use \"WMAKE GW=1 ...\" (overrides PM=1)\n#   Note: specifying PM or GW without NOASM requires that the win32 source\n#   directory be present, so it can access the 32 bit assembly source.\n#   PMODE/W is recommended over DOS/4GW for best performance.\n# To build with debug info use \"WMAKE DEBUG=1 ...\"\n# To build with no assembly modules use \"WMAKE NOASM=1 ...\"\n# To omit unshrinking support use \"WMAKE NO_LZW=1 ...\"\n# To support unreducing, get the real unreduce.c and go \"WMAKE OFFEND_RMS=1 ...\"\n# To include support for bzip2 decompression (only for 32-bit), get the bzip2\n#  source distribution into the bzip2/ subfolder and start compilation\n#  with \"WMAKE PM=1 USEBZ2=1 ...\"\n#\n# Other options to be fed to the compiler can be specified in an environment\n# variable called LOCAL_UNZIP.\n\nvariation = $(%LOCAL_UNZIP)\n\n# Stifle annoying \"Delete this file?\" questions when errors occur:\n.ERASE\n\n.EXTENSIONS:\n.EXTENSIONS: .exe .obj .obx .c .h .asm\n\n# We maintain multiple sets of object files in different directories so that\n# we can compile msdos, dos/4gw, and win32 versions of UnZip without their\n# object files interacting.  The following var must be a directory name\n# ending with a backslash.  All object file names must include this macro\n# at the beginning, for example \"$(O)foo.obj\".\n\n!ifdef GW\nPM = 1      # both protected mode formats use the same object files\n!endif\n\n!ifdef DEBUG\n!  ifdef PM\nOBDIR = od32d\n!  else\nOBDIR = od16d\n!  endif\n!else\n!  ifdef PM\nOBDIR = ob32d\n!  else\nOBDIR = ob16d\n!  endif\n!endif\nO = $(OBDIR)\\   # comment here so backslash won't continue the line\n\n!ifdef NO_LZW\ncvars = $+$(cvars)$- -DLZW_CLEAN\navars = $+$(avars)$- -DLZW_CLEAN\n# \"$+$(foo)$-\" means expand foo as it has been defined up to now; normally,\n# this Make defers inner expansion until the outer macro is expanded.\n!endif\n!ifdef OFFEND_RMS\ncvars = $+$(cvars)$- -DUSE_SMITH_CODE\navars = $+$(avars)$- -DUSE_SMITH_CODE\n!endif\n\nIZ_BZIP2 = bzip2\n!ifdef USEBZ2\n!ifdef PM\ncvars = $+$(cvars)$- -DUSE_BZIP2 -I$(IZ_BZIP2)\nbz2errob = $(O)ubz2err.obj\nbz2errox = $(O)ubz2err.obj\nBZIPLIB = $(IZ_BZIP2)/$(OBDIR)/bz2.lib\nBZ2LNKLIB = lib {$(BZIPLIB)}\n!else\nbz2errob =\nbz2errox =\nBZIPLIB =\nBZ2LNKLIB =\n!endif\n!else\nbz2errob =\nbz2errox =\nBZIPLIB =\nBZ2LNKLIB =\n!endif\n\n# The assembly hot-spot code in crc_i[3]86.asm is optional.  This section\n# controls its usage.\n\n!ifdef NOASM\ncrcaob =\ncrcaof =\ncrcaox =\n!else   # !NOASM\ncvars = $+$(cvars)$- -DASM_CRC\n!  ifdef PM\ncrcaob = $(O)crc_i386.obj\ncrcaof = $(O)crc_i38f.obj\ncrcaox = $(O)crc_i386.obx\ncrc_s = win32\\crc_i386.asm   # requires that the win32 directory be present\n!  else\ncrcaob = $(O)crc_i86.obj\ncrcaof = $(O)crc_i8f.obj\ncrcaox = $(O)crc_i86.obx\ncrc_s = msdos\\crc_i86.asm\n!  endif\n!endif\n\n# Our object files: OBJ[A-C] is for UnZip, OBJX for UnZipSFX, OBJF for fUnZip:\n\nOBJA1 = $(O)unzip.obj $(O)crc32.obj $(crcaob) $(O)crypt.obj $(O)envargs.obj\nOBJA  = $(OBJA1) $(O)explode.obj $(O)extract.obj $(O)fileio.obj $(O)globals.obj\nOBJB2 = $(O)inflate.obj $(O)list.obj $(O)match.obj $(O)process.obj\nOBJB  = $(OBJB2) $(O)ttyio.obj $(bz2errob) $(O)unreduce.obj\nOBJC  = $(O)unshrink.obj $(O)zipinfo.obj $(O)msdos.obj\n\nOBJX2 = $(O)unzip.obx $(O)crc32.obx $(crcaox) $(O)crypt.obx $(O)extract.obx\nOBJX1 = $(OBJX2) $(O)fileio.obx $(O)globals.obx $(O)inflate.obx $(O)match.obx\nOBJX  = $(OBJX1) $(O)process.obx $(bz2errox) $(O)ttyio.obx $(O)msdos.obx\n\nOBJF1  = $(O)funzip.obj $(O)crc32f.obj $(crcaof) $(O)cryptf.obj $(O)globalsf.obj\nOBJF  = $(OBJF1) $(O)inflatef.obj $(O)ttyiof.obj $(O)msdosf.obj\n\n# Common header files included by all C sources:\n\nUNZIP_H = unzip.h unzpriv.h globals.h msdos\\doscfg.h\n\n# Now we have to pick out the proper compiler and options for it.  This gets\n# pretty complicated with the PM, GW, DEBUG, and NOASM options...\n\nlink   = wlink\nasm    = wasm\n\n!ifdef PM\ncc     = wcc386\n# Use Pentium Pro timings, flat memory, static strings in code, max strictness:\ncflags = -bt=DOS -mf -6r -zt -zq -wx\naflags = -bt=DOS -mf -3 -zq\ncflagf = $(cflags)\naflagf = $(aflags)\ncflagx = $(cflags)\naflagx = $(aflags)\n\n!  ifdef GW\nlflags = sys DOS4G\n!  else\n# THIS REQUIRES THAT PMODEW.EXE BE FINDABLE IN THE COMMAND PATH.\n# It does NOT require you to add a pmodew entry to wlink.lnk or wlsystem.lnk.\ndefaultlibs = libpath %WATCOM%\\lib386 libpath %WATCOM%\\lib386\\dos\nlflags = format os2 le op osname='PMODE/W' op stub=pmodew.exe $(defaultlibs)\n!  endif\n\n!else   # plain 16-bit DOS:\n\ncc     = wcc\n# Use plain 8086 code, large memory, static strings in code, max strictness:\ncflags = -bt=DOS -ml -0 -zt -zq -wx\naflags = -bt=DOS -ml -0 -zq\n# for fUnZip, Deflate64 support requires the compact memory model:\ncflagf = -bt=DOS -mc -0 -zt -zq -wx\naflagf = -bt=DOS -mc -0 -zq\n# for UnZipSFX (without Deflate64 support), use the small memory model:\ncflagx = -bt=DOS -ms -0 -zt -zq -wx\naflagx = -bt=DOS -ms -0 -zq\nlflags = sys DOS\n!endif  # !PM\n\ncvars  = $+$(cvars)$- -DMSDOS $(variation)\navars  = $+$(avars)$- $(variation)\n\n\n# Specify optimizations, or a nonoptimized debugging version:\n\n!ifdef DEBUG\ncdebug = -od -d2\ncdebux = -od -d2\nldebug = d w all op symf\n!else\n!  ifdef PM\ncdebug = -s -obhikl+rt -oe=100 -zp8\n# -oa helps slightly but might be dangerous.\n!  else\ncdebug = -s -oehiklrt\n!  endif\ncdebux = -s -obhiklrs\nldebug = op el\n!endif\n\n# How to compile sources:\n.c.obx:\n\t$(cc) $(cdebux) $(cflagx) $(cvars) -DSFX $[@ -fo=$@\n\n.c.obj:\n\t$(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@\n\n# Here we go!  By default, make all targets, except no UnZipSFX for PMODE:\n!ifdef PM\nall: UnZip.exe fUnZip.exe\n!else\nall: UnZip.exe fUnZip.exe UnZipSFX.exe\n!endif\n\n# Convenient shorthand options for single targets:\nu:   UnZip.exe     .SYMBOLIC\nf:   fUnZip.exe    .SYMBOLIC\nx:   UnZipSFX.exe  .SYMBOLIC\n\nUnZip.exe:\t$(OBDIR) $(OBJA) $(OBJB) $(OBJC) $(BZIPLIB)\n\tset WLK_VA=file {$(OBJA)}\n\tset WLK_VB=file {$(OBJB)}\n        set WLK_VC=file {$(OBJC)} $(BZ2LNKLIB)\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VA @WLK_VB @WLK_VC\n\tset WLK_VA=\n\tset WLK_VB=\n        set WLK_VC=\n# We use WLK_VA/WLK_VB/WLK_VC to keep the size of each command below 256 chars.\n\nUnZipSFX.exe:\t$(OBDIR) $(OBJX) $(BZIPLIB)\n\tset WLK_VX=file {$(OBJX)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VX\n\tset WLK_VX=\n\nfUnZip.exe:\t$(OBDIR) $(OBJF)\n\tset WLK_VF=file {$(OBJF)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VF\n\tset WLK_VF=\n\n\n# Source dependencies:\n\n#       for UnZip ...\n\n$(O)crc32.obj:    crc32.c $(UNZIP_H) zip.h crc32.h\n$(O)crypt.obj:    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n$(O)envargs.obj:  envargs.c $(UNZIP_H)\n$(O)explode.obj:  explode.c $(UNZIP_H)\n$(O)extract.obj:  extract.c $(UNZIP_H) crc32.h crypt.h\n$(O)fileio.obj:   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n$(O)globals.obj:  globals.c $(UNZIP_H)\n$(O)inflate.obj:  inflate.c inflate.h $(UNZIP_H)\n$(O)list.obj:     list.c $(UNZIP_H)\n$(O)match.obj:    match.c $(UNZIP_H)\n$(O)process.obj:  process.c $(UNZIP_H) crc32.h\n$(O)ttyio.obj:    ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n$(O)ubz2err.obj:  ubz2err.c $(UNZIP_H)\n$(O)unreduce.obj: unreduce.c $(UNZIP_H)\n$(O)unshrink.obj: unshrink.c $(UNZIP_H)\n$(O)unzip.obj:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n$(O)zipinfo.obj:  zipinfo.c $(UNZIP_H)\n\n#       for UnZipSFX ...\n\n$(O)crc32.obx:    crc32.c $(UNZIP_H) zip.h crc32.h\n$(O)crypt.obx:    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n$(O)extract.obx:  extract.c $(UNZIP_H) crc32.h crypt.h\n$(O)fileio.obx:   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n$(O)globals.obx:  globals.c $(UNZIP_H)\n$(O)inflate.obx:  inflate.c inflate.h $(UNZIP_H)\n$(O)match.obx:    match.c $(UNZIP_H)\n$(O)process.obx:  process.c $(UNZIP_H) crc32.h\n$(O)ttyio.obx:    ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n$(O)ubz2err.obx:  ubz2err.c $(UNZIP_H)\n$(O)unzip.obx:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\n# Special case object files:\n\n$(O)msdos.obj:    msdos\\msdos.c $(UNZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) msdos\\msdos.c -fo=$@\n\n$(O)msdos.obx:    msdos\\msdos.c $(UNZIP_H)\n\t$(cc) $(cdebux) $(cflagx) $(cvars) -DSFX msdos\\msdos.c -fo=$@\n\n!ifndef NOASM\n$(crcaob):        $(crc_s)\n\t$(asm) $(aflags) $(avars) $(crc_s) -fo=$@\n\n$(crcaof):        $(crc_s)\n\t$(asm) $(aflagf) $(avars) $(crc_s) -fo=$@\n\n$(crcaox):        $(crc_s)\n\t$(asm) $(aflagx) $(avars) $(crc_s) -fo=$@\n!endif\n\n# Variant object files for fUnZip, using $(cflagf):\n\n$(O)funzip.obj:   funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(cc) $(cdebux) $(cflagf) $(cvars) funzip.c -fo=$@\n\n$(O)crc32f.obj:   crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP crc32.c -fo=$@\n\n$(O)cryptf.obj:   crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP crypt.c -fo=$@\n\n$(O)globalsf.obj: globals.c $(UNZIP_H)\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP globals.c -fo=$@\n\n$(O)inflatef.obj: inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP inflate.c -fo=$@\n\n$(O)ttyiof.obj:   ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP ttyio.c -fo=$@\n\n$(O)msdosf.obj:    msdos\\msdos.c $(UNZIP_H)\n\t$(cc) $(cdebux) $(cflagf) $(cvars) -DFUNZIP msdos\\msdos.c -fo=$@\n\n# The bzip2 (de)compression library for BZIP2 support:\n$(IZ_BZIP2)/$(OBDIR)/bz2.lib : .ALWAYS .RECHECK\n\t$(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat CC=$(cc) AR=lib386 &\n\tCFLSYS=\"$(cdebug) $(cflags)\" &\n\tBZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)/$(OBDIR)\n\n# Creation of subdirectory for intermediate files\n$(OBDIR):\n\t-mkdir $@\n\n# Unwanted file removal:\n\nclean_bz2_lib: .SYMBOLIC\n\t$(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat &\n\tBZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)\\$(OBDIR) clean\n\nclean:     clean_bz2_lib  .SYMBOLIC\n\tdel $(O)*.ob?\n\ncleaner:   clean  .SYMBOLIC\n\tdel UnZip.exe\n\tdel fUnZip.exe\n\tdel UnZipSFX.exe\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/msc51opt.dif",
    "content": "Date: Mon, 28 Aug 1995 23:53:23 CET +0100\nFrom: \"Christian Spieler, Institut fuer Kernphysik, Schlossgartenstr. 9,\n      D-64289 Darmstadt\" <SPIELER@linac.ikp.physik.th-darmstadt.de>\nSubject: More MSC 5.1 related patches for UnZip 5.20f2\n\n\nD) I want to suggest two small patches to allow the use of\n   full optimization (including loop optimization) when compiling UnZip\n   with MSC (5.1, and probably newer). There are only two small pieces\n   of code (containing to deeply nested loops) that break MSC 5.1's loop\n   optimization. I have guarded these loops with \"#pragma loop_opt (off)\"\n   to allow loop optimization for the rest of the code. Here are the patches:\n\n===================== cut here ========================\ndiff -c ./inflate.c ./modif/inflate.c\n*** ./inflate.c\tThu Oct 05 14:57:38 1995\n--- ./modif/inflate.c\tThu Oct 05 14:58:24 1995\n***************\n*** 1162,1173 ****\n--- 1162,1179 ----\n          {                       /* too few codes for k-w bit table */\n            f -= a + 1;           /* deduct codes from patterns left */\n            xp = c + k;\n+ #if defined (MSC)\n+ #pragma loop_opt (off)\n+ #endif /* MS C compilers */\n            while (++j < z)       /* try smaller tables up to z bits */\n            {\n              if ((f <<= 1) <= *++xp)\n                break;            /* enough codes to use up j bits */\n              f -= *xp;           /* else deduct codes from patterns */\n            }\n+ #if defined (MSC)\n+ #pragma loop_opt ()\n+ #endif /* MS C compilers */\n          }\n          if ((unsigned)w + j > el && (unsigned)w < el)\n            j = el - w;           /* make EOB code end at table */\ndiff -c ./zipinfo.c ./modif/zipinfo.c\n*** ./zipinfo.c\tThu Oct 05 14:51:58 1995\n--- ./modif/zipinfo.c\tThu Oct 05 14:52:42 1995\n***************\n*** 1134,1145 ****\n--- 1134,1151 ----\n                      workspace[10] = 'E';\n  \n                  p = attribs;\n+ #if defined (MSC) && (!defined (_MSC_VER) || _MSC_VER < 600)\n+ #pragma loop_opt (off)\n+ #endif /* MS C, Version < 6.00 */\n                  for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */\n                      for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */\n                          if (workspace[k])\n                              *p++ = workspace[k];\n                      *p++ = ',';                     /* group separator */\n                  }\n+ #if defined (MSC) && (!defined (_MSC_VER) || _MSC_VER < 600)\n+ #pragma loop_opt ()\n+ #endif /* MS C, Version < 6.00 */\n                  *--p = ' ';   /* overwrite last comma */\n                  if ((p - attribs) < 12)\n                      sprintf(&attribs[12], \"%d.%d\", hostver/10, hostver%10);\n"
  },
  {
    "path": "deps/infozip/unzip60/msdos/msdos.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  msdos.c\n\n  MSDOS-specific routines for use with Info-ZIP's UnZip 5.3 and later.\n\n  Contains:  Opendir()                      (from zip)\n             Readdir()                      (from zip)\n             do_wild()\n             mapattr()\n             mapname()\n             maskDOSdevice()\n             map2fat()\n             checkdir()\n             isfloppy()\n             z_dos_chmod()\n             volumelabel()                  (non-djgpp, non-emx)\n             close_outfile()\n             stamp_file()                   (TIMESTAMP only)\n             prepare_ISO_OEM_translat()\n             dateformat()\n             version()\n             zcalloc()                      (16-bit, only)\n             zcfree()                       (16-bit, only)\n             _dos_getcountryinfo()          (djgpp 1.x, emx)\n            [_dos_getftime()                (djgpp 1.x, emx)   to be added]\n             _dos_setftime()                (djgpp 1.x, emx)\n             _dos_setfileattr()             (djgpp 1.x, emx)\n             _dos_getdrive()                (djgpp 1.x, emx)\n             _dos_creat()                   (djgpp 1.x, emx)\n             _dos_close()                   (djgpp 1.x, emx)\n             volumelabel()                  (djgpp, emx)\n             _dos_getcountryinfo()          (djgpp 2.x)\n             _is_executable()               (djgpp 2.x)\n             __crt0_glob_function()         (djgpp 2.x)\n             __crt0_load_environment_file() (djgpp 2.x)\n             dos_getcodepage()              (all, ASM system call)\n             screensize()                   (emx, Watcom 32-bit)\n             int86x_realmode()              (Watcom 32-bit)\n             stat_bandaid()                 (Watcom)\n\n  ---------------------------------------------------------------------------*/\n\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n/* fUnZip does not need anything from here except the zcalloc() & zcfree()\n * function pair (when Deflate64 support is enabled in 16-bit environment).\n */\n#ifndef FUNZIP\n\nstatic void maskDOSdevice(__GPRO__ char *pathcomp, char *last_dot);\n#ifdef MAYBE_PLAIN_FAT\n   static void map2fat OF((char *pathcomp, char *last_dot));\n#endif\nstatic int isfloppy OF((int nDrive));\nstatic int z_dos_chmod OF((__GPRO__ ZCONST char *fname, int attributes));\nstatic int volumelabel OF((ZCONST char *newlabel));\n#if (!defined(SFX) && !defined(WINDLL))\n   static int is_running_on_windows OF((void));\n#endif\nstatic int getdoscodepage OF((void));\n\nstatic int created_dir;        /* used by mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\nstatic unsigned nLabelDrive;   /* ditto, plus volumelabel() */\n\n\n\n/*****************************/\n/*  Strings used in msdos.c  */\n/*****************************/\n\n#ifndef SFX\n  static ZCONST char Far CantAllocateWildcard[] =\n    \"warning:  cannot allocate wildcard buffers\\n\";\n#endif\nstatic ZCONST char Far WarnDirTraversSkip[] =\n  \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\";\nstatic ZCONST char Far Creating[] = \"   creating: %s\\n\";\nstatic ZCONST char Far ConversionFailed[] =\n  \"mapname:  conversion of %s failed\\n\";\nstatic ZCONST char Far Labelling[] = \"labelling %c: %-22s\\n\";\nstatic ZCONST char Far ErrSetVolLabel[] =\n  \"mapname:  error setting volume label\\n\";\nstatic ZCONST char Far PathTooLong[] = \"checkdir error:  path too long: %s\\n\";\nstatic ZCONST char Far CantCreateDir[] = \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far DirIsntDirectory[] =\n  \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far PathTooLongTrunc[] =\n  \"checkdir warning:  path too long; truncating\\n                   %s\\n\\\n                -> %s\\n\";\n#if (!defined(SFX) || defined(SFX_EXDIR))\n   static ZCONST char Far CantCreateExtractDir[] =\n     \"checkdir:  cannot create extraction directory: %s\\n\";\n#endif\nstatic ZCONST char Far AttribsMayBeWrong[] =\n  \"\\nwarning:  file attributes may not be correct\\n\";\n#if (!defined(SFX) && !defined(WINDLL))\n   static ZCONST char Far WarnUsedOnWindows[] =\n     \"\\n%s warning: You are using the MSDOS version on Windows.\\n\"\n     \"Please try the native Windows version before reporting any problems.\\n\";\n#endif\n\n\n\n/****************************/\n/*  Macros used in msdos.c  */\n/****************************/\n\n#ifdef WATCOMC_386\n#  define WREGS(v,r) (v.w.r)\n#  define int86x int386x\n   static int int86x_realmode(int inter_no, union REGS *in,\n                              union REGS *out, struct SREGS *seg);\n#  define F_intdosx(ir,or,sr) int86x_realmode(0x21, ir, or, sr)\n#  define XXX__MK_FP_IS_BROKEN\n#else\n#  if (defined(__DJGPP__) && (__DJGPP__ >= 2))\n#   define WREGS(v,r) (v.w.r)\n#  else\n#   define WREGS(v,r) (v.x.r)\n#  endif\n#  define F_intdosx(ir,or,sr) intdosx(ir, or, sr)\n#endif\n\n#if (defined(__GO32__) || defined(__EMX__))\n#  include <dirent.h>        /* use readdir() */\n#  define MKDIR(path,mode)   mkdir(path,mode)\n#  define Opendir  opendir\n#  define Readdir  readdir\n#  define Closedir closedir\n#  define zdirent  dirent\n#  define zDIR     DIR\n#  ifdef __EMX__\n#    include <dos.h>\n#    define GETDRIVE(d)      d = _getdrive()\n#    define FA_LABEL         A_LABEL\n#  else\n#    define GETDRIVE(d)      _dos_getdrive(&d)\n#  endif\n#  if defined(_A_SUBDIR)     /* MSC dos.h and compatibles */\n#    define FSUBDIR          _A_SUBDIR\n#  elif defined(FA_DIREC)    /* Borland dos.h and compatible variants */\n#    define FSUBDIR          FA_DIREC\n#  elif defined(A_DIR)       /* EMX dir.h (and dirent.h) */\n#    define FSUBDIR          A_DIR\n#  else                      /* fallback definition */\n#    define FSUBDIR          0x10\n#  endif\n#  if defined(_A_VOLID)      /* MSC dos.h and compatibles */\n#    define FVOLID           _A_VOLID\n#  elif defined(FA_LABEL)    /* Borland dos.h and compatible variants */\n#    define FVOLID           FA_LABEL\n#  elif defined(A_LABEL)     /* EMX dir.h (and dirent.h) */\n#    define FVOLID           A_LABEL\n#  else\n#    define FVOLID           0x08\n#  endif\n#else /* !(__GO32__ || __EMX__) */\n#  define MKDIR(path,mode)   mkdir(path)\n#  ifdef __TURBOC__\n#    define FATTR            FA_HIDDEN+FA_SYSTEM+FA_DIREC\n#    define FVOLID           FA_LABEL\n#    define FSUBDIR          FA_DIREC\n#    define FFIRST(n,d,a)    findfirst(n,(struct ffblk *)d,a)\n#    define FNEXT(d)         findnext((struct ffblk *)d)\n#    define GETDRIVE(d)      d=getdisk()+1\n#    include <dir.h>\n#  else /* !__TURBOC__ */\n#    define FATTR            _A_HIDDEN+_A_SYSTEM+_A_SUBDIR\n#    define FVOLID           _A_VOLID\n#    define FSUBDIR          _A_SUBDIR\n#    define FFIRST(n,d,a)    _dos_findfirst(n,a,(struct find_t *)d)\n#    define FNEXT(d)         _dos_findnext((struct find_t *)d)\n#    define GETDRIVE(d)      _dos_getdrive(&d)\n#    include <direct.h>\n#  endif /* ?__TURBOC__ */\n   typedef struct zdirent {\n       char d_reserved[30];\n       char d_name[13];\n       int d_first;\n   } zDIR;\n   zDIR *Opendir OF((const char *));\n   struct zdirent *Readdir OF((zDIR *));\n#  define Closedir free\n\n\n\n\n#ifndef SFX\n\n/**********************/   /* Borland C++ 3.x has its own opendir/readdir */\n/* Function Opendir() */   /*  library routines, but earlier versions don't, */\n/**********************/   /*  so use ours regardless */\n\nzDIR *Opendir(name)\n    const char *name;           /* name of directory to open */\n{\n    zDIR *dirp;                 /* malloc'd return value */\n    char *nbuf;                 /* malloc'd temporary string */\n    extent len = strlen(name);  /* path length to avoid strlens and strcats */\n\n\n    if ((dirp = (zDIR *)malloc(sizeof(zDIR))) == (zDIR *)NULL)\n        return (zDIR *)NULL;\n    if ((nbuf = malloc(len + 6)) == (char *)NULL) {\n        free(dirp);\n        return (zDIR *)NULL;\n    }\n    strcpy(nbuf, name);\n    if (len > 0) {\n        if (nbuf[len-1] == ':') {\n            nbuf[len++] = '.';\n        } else if (nbuf[len-1] == '/' || nbuf[len-1] == '\\\\')\n            --len;\n    }\n    strcpy(nbuf+len, \"/*.*\");\n    Trace((stderr, \"Opendir:  nbuf = [%s]\\n\", FnFilter1(nbuf)));\n\n    if (FFIRST(nbuf, dirp, FATTR)) {\n        free((zvoid *)nbuf);\n        return (zDIR *)NULL;\n    }\n    free((zvoid *)nbuf);\n    dirp->d_first = 1;\n    return dirp;\n}\n\n\n\n\n\n/**********************/\n/* Function Readdir() */\n/**********************/\n\nstruct zdirent *Readdir(d)\n    zDIR *d;        /* directory stream from which to read */\n{\n    /* Return pointer to first or next directory entry, or NULL if end. */\n\n    if (d->d_first)\n        d->d_first = 0;\n    else\n        if (FNEXT(d))\n            return (struct zdirent *)NULL;\n    return (struct zdirent *)d;\n}\n\n#endif /* !SFX */\n#endif /* ?(__GO32__ || __EMX__) */\n\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function do_wild()  */   /* identical to OS/2 version */\n/************************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;   /* only used first time on a given dir */\n{\n    static zDIR *wild_dir = (zDIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    char *fnamestart;\n    struct zdirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            wild_dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL &&\n            (wildname = strrchr(wildspec, ':')) == (ZCONST char *)NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' or ':' */\n            dirnamelen = (int)(wildname - wildspec);\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(CantAllocateWildcard)));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n/* GRR:  can't strip trailing char for opendir since might be \"d:/\" or \"d:\"\n *       (would have to check for \"./\" at end--let opendir handle it instead) */\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n        Trace((stderr, \"do_wild:  dirname = [%s]\\n\", FnFilter1(dirname)));\n\n        if ((wild_dir = Opendir(dirname)) != (zDIR *)NULL) {\n            if (have_dirname) {\n                strcpy(matchname, dirname);\n                fnamestart = matchname + dirnamelen;\n            } else\n                fnamestart = matchname;\n            while ((file = Readdir(wild_dir)) != (struct zdirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                strcpy(fnamestart, file->d_name);\n                if (strrchr(fnamestart, '.') == (char *)NULL)\n                    strcat(fnamestart, \".\");\n                /* 1 == ignore case (for case-insensitive DOS-FS) */\n                if (match(fnamestart, wildname, 1 WISEP) &&\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(fnamestart, \".\") && strcmp(fnamestart, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    /* remove trailing dot */\n                    fnamestart += strlen(fnamestart) - 1;\n                    if (*fnamestart == '.')\n                        *fnamestart = '\\0';\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            Closedir(wild_dir);\n            wild_dir = (zDIR *)NULL;\n        }\n#ifdef DEBUG\n        else {\n            Trace((stderr, \"do_wild:  Opendir(%s) returns NULL\\n\",\n               FnFilter1(dirname)));\n        }\n#endif /* DEBUG */\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (zDIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    if (have_dirname) {\n        /* strcpy(matchname, dirname); */\n        fnamestart = matchname + dirnamelen;\n    } else\n        fnamestart = matchname;\n    while ((file = Readdir(wild_dir)) != (struct zdirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        strcpy(fnamestart, file->d_name);\n        if (strrchr(fnamestart, '.') == (char *)NULL)\n            strcat(fnamestart, \".\");\n        if (match(fnamestart, wildname, 1 WISEP)) { /* 1 == ignore case */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            /* remove trailing dot */\n            fnamestart += strlen(fnamestart) - 1;\n            if (*fnamestart == '.')\n                *fnamestart = '\\0';\n            return matchname;\n        }\n    }\n\n    Closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (zDIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    /* set archive bit for file entries (file is not backed up): */\n    G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |\n      (G.crec.external_file_attributes & FSUBDIR ? 0 : 32)) & 0xff;\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef MAYBE_PLAIN_FAT\n    char *last_dot=(char *)NULL;   /* last dot not converted to underscore */\n# ifdef USE_LFN\n    int use_lfn = USE_LFN;         /* file system supports long filenames? */\n# endif\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n    renamed_fullpath = FALSE;\n\n    if (renamed) {\n        cp = G.filename - 1;    /* point to beginning of renamed name... */\n        while (*++cp)\n            if (*cp == '\\\\')    /* convert backslashes to forward */\n                *cp = '/';\n        cp = G.filename;\n        /* use temporary rootpath if user gave full pathname */\n        if (G.filename[0] == '/') {\n            renamed_fullpath = TRUE;\n            pathcomp[0] = '/';  /* copy the '/' and terminate */\n            pathcomp[1] = '\\0';\n            ++cp;\n        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {\n            renamed_fullpath = TRUE;\n            pp = pathcomp;\n            *pp++ = *cp++;      /* copy the \"d:\" (+ '/', possibly) */\n            *pp++ = *cp++;\n            if (*cp == '/')\n                *pp++ = *cp++;  /* otherwise add \"./\"? */\n            *pp = '\\0';\n        }\n    }\n\n    /* pathcomp is ignored unless renamed_fullpath is TRUE: */\n    if ((error = checkdir(__G__ pathcomp, INIT)) != 0) /* initialize path buf */\n        return error;           /* ...unless no mem or vol label on hard disk */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (!renamed) {             /* cp already set if renamed */\n        if (uO.jflag)           /* junking directories */\n            cp = (char *)strrchr(G.filename, '/');\n        if (cp == (char *)NULL) /* no '/' or not junking dirs */\n            cp = G.filename;    /* point to internal zipfile-member pathname */\n        else\n            ++cp;               /* point to start of last component of path */\n    }\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n#ifdef MAYBE_PLAIN_FAT\n                maskDOSdevice(__G__ pathcomp, last_dot);\n#else\n                maskDOSdevice(__G__ pathcomp, NULL);\n#endif\n#ifdef MAYBE_PLAIN_FAT\n# ifdef USE_LFN\n                if (!use_lfn)\n# endif\n                {\n                    map2fat(pathcomp, last_dot);   /* 8.3 trunc. (in place) */\n                    last_dot = (char *)NULL;\n                }\n#endif\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n#ifdef MAYBE_PLAIN_FAT\n            case '.':\n# ifdef USE_LFN\n                if (use_lfn) {          /* LFN filenames may contain many */\n                    *pp++ = '.';        /*  dots, so simply copy it ... */\n                } else\n# endif\n                if (pp == pathcomp && *cp == '.' && cp[1] == '/') {\n                    /* nothing appended yet.., and found \"../\" */\n                    *pp++ = '.';        /*  add first dot, */\n                    *pp++ = '.';        /*  second dot, and */\n                    ++cp;               /*  skip over to the '/' */\n                } else {                /* found dot within path component */\n                    last_dot = pp;      /*  point at last dot so far... */\n                    *pp++ = '_';        /*  convert to underscore for now */\n                }\n                break;\n#endif /* MAYBE_PLAIN_FAT */\n\n            /* drive names are not stored in zipfile, so no colons allowed;\n             *  no brackets or most other punctuation either (all of which\n             *  can appear in Unix-created archives; backslash is particularly\n             *  bad unless all necessary directories exist) */\n#ifdef MAYBE_PLAIN_FAT\n            case '[':          /* these punctuation characters forbidden */\n            case ']':          /*  only on plain FAT file systems */\n            case '+':\n            case ',':\n            case '=':\n# ifdef USE_LFN\n                if (use_lfn)\n                    *pp++ = (char)workch;\n                else\n                    *pp++ = '_';\n                break;\n# endif\n#endif\n            case ':':           /* special shell characters of command.com */\n            case '\\\\':          /*  (device and directory limiters, wildcard */\n            case '\"':           /*  characters, stdin/stdout redirection and */\n            case '<':           /*  pipe indicators and the quote sign) are */\n            case '>':           /*  never allowed in filenames on (V)FAT */\n            case '|':\n            case '*':\n            case '?':\n                *pp++ = '_';\n                break;\n\n            case ';':             /* start of VMS version? */\n                lastsemi = pp;\n#ifdef MAYBE_PLAIN_FAT\n# ifdef USE_LFN\n                if (use_lfn)\n                    *pp++ = ';';  /* keep for now; remove VMS \";##\" later */\n# endif\n#else\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" later */\n#endif\n                break;\n\n#ifdef MAYBE_PLAIN_FAT\n            case ' ':                      /* change spaces to underscores */\n# ifdef USE_LFN\n                if (!use_lfn && uO.sflag)  /*  only if requested and NO lfn! */\n# else\n                if (uO.sflag)              /*  only if requested */\n# endif\n                    *pp++ = '_';\n                else\n                    *pp++ = (char)workch;\n                break;\n#endif /* MAYBE_PLAIN_FAT */\n\n            default:\n                /* allow ASCII 255 and European characters in filenames: */\n                if (isprint(workch) || workch >= 127)\n                    *pp++ = (char)workch;\n\n        } /* end switch */\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, LoadFarString(Creating),\n                  FnFilter1(G.filename)));\n            }\n\n            /* set file attributes: */\n            z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);\n\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        } else if (IS_OVERWRT_ALL) {\n            /* overwrite attributes of existing directory on user's request */\n\n            /* set file attributes: */\n            z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n#ifndef MAYBE_PLAIN_FAT\n        pp = lastsemi + 1;\n#else\n# ifdef USE_LFN\n        if (use_lfn)\n            pp = lastsemi + 1;\n        else\n            pp = lastsemi;        /* semi-colon was omitted:  expect all #'s */\n# else\n        pp = lastsemi;            /* semi-colon was omitted:  expect all #'s */\n# endif\n#endif\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n#ifdef MAYBE_PLAIN_FAT\n    maskDOSdevice(__G__ pathcomp, last_dot);\n#else\n    maskDOSdevice(__G__ pathcomp, NULL);\n#endif\n\n    if (G.pInfo->vollabel) {\n        if (strlen(pathcomp) > 11)\n            pathcomp[11] = '\\0';\n    } else {\n#ifdef MAYBE_PLAIN_FAT\n# ifdef USE_LFN\n        if (!use_lfn)\n            map2fat(pathcomp, last_dot);  /* 8.3 truncation (in place) */\n# else\n        map2fat(pathcomp, last_dot);  /* 8.3 truncation (in place) */\n# endif\n#endif\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    if (G.pInfo->vollabel) {    /* set the volume label now */\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, LoadFarString(Labelling),\n              (nLabelDrive + 'a' - 1),\n              FnFilter1(G.filename)));\n        if (volumelabel(G.filename)) {\n            Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel)));\n            return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n        }\n        /* success:  skip the \"extraction\" quietly */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n\n/****************************/\n/* Function maskDOSdevice() */\n/****************************/\n\nstatic void maskDOSdevice(__G__ pathcomp, last_dot)\n    __GDEF\n    char *pathcomp, *last_dot;\n{\n/*---------------------------------------------------------------------------\n    Put an underscore in front of the file name if the file name is a\n    DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to\n    extract such a file would fail at best and wedge us at worst.\n  ---------------------------------------------------------------------------*/\n#if !defined(S_IFCHR) && defined(_S_IFCHR)\n#  define S_IFCHR _S_IFCHR\n#endif\n#if !defined(S_ISCHR)\n# if defined(_S_ISCHR)\n#  define S_ISCHR(m) _S_ISCHR(m)\n# elif defined(S_IFCHR)\n#  define S_ISCHR(m) ((m) & S_IFCHR)\n# endif\n#endif\n\n#ifdef DEBUG\n    if (stat(pathcomp, &G.statbuf) == 0) {\n        Trace((stderr,\n               \"maskDOSdevice() stat(\\\"%s\\\", buf) st_mode result: %X, %o\\n\",\n               FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode));\n    } else {\n        Trace((stderr, \"maskDOSdevice() stat(\\\"%s\\\", buf) failed\\n\",\n               FnFilter1(pathcomp)));\n    }\n#endif\n    if (stat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) {\n        extent i;\n\n        /* pathcomp contains a name of a DOS character device (builtin or\n         * installed device driver).\n         * Prepend a '_' to allow creation of the item in the file system.\n         */\n        for (i = strlen(pathcomp) + 1; i > 0; --i)\n            pathcomp[i] = pathcomp[i - 1];\n        pathcomp[0] = '_';\n        if (last_dot != (char *)NULL)\n            last_dot++;\n    }\n} /* end function maskDOSdevice() */\n\n\n\n\n\n#ifdef MAYBE_PLAIN_FAT\n\n/**********************/\n/* Function map2fat() */\n/**********************/\n\nstatic void map2fat(pathcomp, last_dot)\n    char *pathcomp, *last_dot;\n{\n    char *pEnd = pathcomp + strlen(pathcomp);\n\n/*---------------------------------------------------------------------------\n    Case 1:  filename has no dot, so figure out if we should add one.  Note\n    that the algorithm does not try to get too fancy:  if there are no dots\n    already, the name either gets truncated at 8 characters or the last un-\n    derscore is converted to a dot (only if more characters are saved that\n    way).  In no case is a dot inserted between existing characters.\n\n              GRR:  have problem if filename is volume label??\n\n  ---------------------------------------------------------------------------*/\n\n    if (last_dot == (char *)NULL) {   /* no dots:  check for underscores... */\n        char *plu = strrchr(pathcomp, '_');   /* pointer to last underscore */\n\n        if ((plu != (char *)NULL) &&    /* found underscore: convert to dot? */\n            (MIN(plu - pathcomp, 8) + MIN(pEnd - plu - 1, 3) > 8)) {\n            last_dot = plu;       /* be lazy:  drop through to next if-block */\n        } else if ((pEnd - pathcomp) > 8)\n            /* no underscore; or converting underscore to dot would save less\n               chars than leaving everything in the basename */\n            pathcomp[8] = '\\0';     /* truncate at 8 chars */\n        /* else whole thing fits into 8 chars or less:  no change */\n    }\n\n/*---------------------------------------------------------------------------\n    Case 2:  filename has dot in it, so truncate first half at 8 chars (shift\n    extension if necessary) and second half at three.\n  ---------------------------------------------------------------------------*/\n\n    if (last_dot != (char *)NULL) {     /* one dot is OK: */\n        *last_dot = '.';                /* put the last back in */\n\n        if ((last_dot - pathcomp) > 8) {\n            char *p, *q;\n            int i;\n\n            p = last_dot;\n            q = last_dot = pathcomp + 8;\n            for (i = 0;  (i < 4) && *p;  ++i) /* too many chars in basename: */\n                *q++ = *p++;                  /*  shift extension left and */\n            *q = '\\0';                        /*  truncate/terminate it */\n        } else if ((pEnd - last_dot) > 4)\n            last_dot[4] = '\\0';               /* too many chars in extension */\n        /* else filename is fine as is:  no change */\n\n        if ((last_dot - pathcomp) > 0 && last_dot[-1] == ' ')\n            last_dot[-1] = '_';               /* NO blank in front of '.'! */\n    }\n} /* end function map2fat() */\n\n#endif /* MAYBE_PLAIN_FAT */\n\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n#ifdef MSC\n    int attrs;                /* work around MSC stat() bug */\n#endif\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n#ifdef MSC /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */\n        if (_dos_getfileattr(buildpath, &attrs) || stat(buildpath, &G.statbuf))\n#else\n        if (SSTAT(buildpath, &G.statbuf))   /* path doesn't exist */\n#endif\n        {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                /* path doesn't exist:  nothing to do */\n                return MPN_INF_SKIP;\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (MKDIR(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n              FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef NOVELL_BUG_WORKAROUND\n        if (end == buildpath && !G.pInfo->vollabel) {\n            /* work-around for Novell's \"overwriting executables\" bug:\n               prepend \"./\" to name when no path component is specified */\n            *end++ = '.';\n            *end++ = '/';\n        }\n#endif /* NOVELL_BUG_WORKAROUND */\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc),\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        /* allocate space for full filename, root path, and maybe \"./\" */\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+3)) ==\n            (char *)NULL)\n            return MPN_NOMEM;\n        if (G.pInfo->vollabel) {\n/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */\n            if (renamed_fullpath && pathcomp[1] == ':')\n                *buildpath = (char)ToLower(*pathcomp);\n            else if (!renamed_fullpath && rootlen > 1 && rootpath[1] == ':')\n                *buildpath = (char)ToLower(*rootpath);\n            else {\n                GETDRIVE(nLabelDrive);   /* assumed that a == 1, b == 2, etc. */\n                *buildpath = (char)(nLabelDrive - 1 + 'a');\n            }\n            nLabelDrive = *buildpath - 'a' + 1;        /* save for mapname() */\n            if (uO.volflag == 0 || *buildpath < 'a' || /* no label/bogus disk */\n               (uO.volflag == 1 && !isfloppy(nLabelDrive))) /* -$:  no fixed */\n            {\n                free(buildpath);\n                return MPN_VOL_LABEL;    /* skipping with message */\n            }\n            *buildpath = '\\0';\n            end = buildpath;\n        } else if (renamed_fullpath) {   /* pathcomp = valid data */\n            end = buildpath;\n            while ((*end = *pathcomp++) != '\\0')\n                ++end;\n        } else if (rootlen > 0) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to\n    directory specification includes a drive letter (leading \"x:\"), it is\n    treated just as if it had a trailing '/'--that is, one directory level\n    will be created if the path doesn't exist, unless this is otherwise pro-\n    hibited (e.g., freshening).\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+3)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n                has_drive = TRUE;   /* drive designator */\n            if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '\\\\') {\n                tmproot[--rootlen] = '\\0';\n                had_trailing_pathsep = TRUE;\n            }\n            if (has_drive && (rootlen == 2)) {\n                if (!had_trailing_pathsep)   /* i.e., original wasn't \"x:/\" */\n                    add_dot = TRUE;    /* relative path: add '.' before '/' */\n            } else if (rootlen > 0) {     /* need not check \"x:.\" and \"x:/\" */\n#ifdef MSC\n                /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */\n                if (_dos_getfileattr(tmproot, &attrs) ||\n                    SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n#else\n                if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n#endif\n                {\n                    /* path does not exist */\n                    if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                        free(tmproot);\n                        rootlen = 0;\n                        /* treat as stored file */\n                        return MPN_INF_SKIP;\n                    }\n/* GRR:  scan for wildcard characters?  OS-dependent...  if find any, return 2:\n * treat as stored file(s) */\n                    /* create directory (could add loop here scanning tmproot\n                     * to create more than one level, but really necessary?) */\n                    if (MKDIR(tmproot, 0777) == -1) {\n                        Info(slide, 1, ((char *)slide,\n                          LoadFarString(CantCreateExtractDir),\n                          FnFilter1(tmproot)));\n                        free(tmproot);\n                        rootlen = 0;\n                        /* path didn't exist, tried to create, failed: */\n                        /* file exists, or need 2+ subdir levels */\n                        return MPN_ERR_SKIP;\n                    }\n                }\n            }\n            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n                tmproot[rootlen++] = '.';\n            tmproot[rootlen++] = '/';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n\n/***********************/\n/* Function isfloppy() */\n/***********************/\n\nstatic int isfloppy(nDrive)  /* more precisely, is it removable? */\n    int nDrive;\n{\n    union REGS regs;\n\n    regs.h.ah = 0x44;\n    regs.h.al = 0x08;\n    regs.h.bl = (uch)nDrive;\n#ifdef __EMX__\n    _int86(0x21, &regs, &regs);\n    if (WREGS(regs,flags) & 1)\n#else\n    intdos(&regs, &regs);\n    if (WREGS(regs,cflag))        /* error:  do default a/b check instead */\n#endif\n    {\n        Trace((stderr,\n          \"error in DOS function 0x44 (AX = 0x%04x):  guessing instead...\\n\",\n          (unsigned int)(WREGS(regs,ax))));\n        return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;\n    } else\n        return WREGS(regs,ax)? FALSE : TRUE;\n}\n\n\n\n\n/**************************/\n/* Function z_dos_chmod() */\n/**************************/\n\nstatic int z_dos_chmod(__G__ fname, attributes)\n    __GDEF\n    ZCONST char *fname;\n    int attributes;\n{\n    char *name;\n    unsigned fnamelength;\n    int errv;\n\n    /* set file attributes:\n       The DOS `chmod' system call requires to mask out the\n       directory and volume_label attribute bits.\n       And, a trailing '/' has to be removed from the directory name,\n       the DOS `chmod' system call does not accept it. */\n    fnamelength = strlen(fname);\n    if (fnamelength > 1 && fname[fnamelength-1] == '/' &&\n        fname[fnamelength-2] != ':' &&\n        (name = (char *)malloc(fnamelength)) != (char *)NULL) {\n        strncpy(name, fname, fnamelength-1);\n        name[fnamelength-1] = '\\0';\n    } else {\n        name = (char *)fname;\n        fnamelength = 0;\n    }\n\n#if defined(__TURBOC__) || (defined(__DJGPP__) && (__DJGPP__ >= 2))\n#   if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0452))\n#     define Chmod  _rtl_chmod\n#   else\n#     define Chmod  _chmod\n#   endif\n    errv = (Chmod(name, 1, attributes & (~FSUBDIR & ~FVOLID)) !=\n            (attributes & (~FSUBDIR & ~FVOLID)));\n#   undef Chmod\n#else /* !(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */\n    errv = (_dos_setfileattr(name, attributes & (~FSUBDIR & ~FVOLID)) != 0);\n#endif /* ?(__TURBOC__ || (__DJGPP__ && __DJGPP__ >= 2)) */\n    if (errv)\n        Info(slide, 1, ((char *)slide, LoadFarString(AttribsMayBeWrong)));\n\n    if (fnamelength > 0)\n        free(name);\n    return errv;\n} /* end function z_dos_chmod() */\n\n\n\n\n#if (!defined(__GO32__) && !defined(__EMX__))\n\ntypedef struct dosfcb {\n    uch  flag;        /* ff to indicate extended FCB */\n    char res[5];      /* reserved */\n    uch  vattr;       /* attribute */\n    uch  drive;       /* drive (1=A, 2=B, ...) */\n    uch  vn[11];      /* file or volume name */\n    char dmmy[5];\n    uch  nn[11];      /* holds new name if renaming (else reserved) */\n    char dmmy2[9];\n} dos_fcb;\n\n/**************************/\n/* Function volumelabel() */\n/**************************/\n\nstatic int volumelabel(newlabel)\n    ZCONST char *newlabel;\n{\n#ifdef DEBUG\n    char *p;\n#endif\n    int len = strlen(newlabel);\n    int fcbseg, dtaseg, fcboff, dtaoff, retv;\n    dos_fcb  fcb, dta, far *pfcb=&fcb, far *pdta=&dta;\n    struct SREGS sregs;\n    union REGS regs;\n\n\n/*---------------------------------------------------------------------------\n    Label the diskette specified by nLabelDrive using FCB calls.  (Old ver-\n    sions of MS-DOS and OS/2 DOS boxes can't use DOS function 3Ch to create\n    labels.)  Must use far pointers for MSC FP_* macros to work; must pad\n    FCB filenames with spaces; and cannot include dot in 8th position.  May\n    or may not need to zero out FCBs before using; do so just in case.\n  ---------------------------------------------------------------------------*/\n\n#ifdef WATCOMC_386\n    int truseg;\n\n    memset(&sregs, 0, sizeof(sregs));\n    memset(&regs, 0, sizeof(regs));\n    /* PMODE/W does not support extended versions of any dos FCB functions, */\n    /* so we have to use brute force, allocating real mode memory for them. */\n    regs.w.ax = 0x0100;\n    regs.w.bx = (2 * sizeof(dos_fcb) + 15) >> 4;   /* size in paragraphs */\n    int386(0x31, &regs, &regs);            /* DPMI allocate DOS memory */\n    if (regs.w.cflag)\n        return DF_MDY;                     /* no memory, return default */\n    truseg = regs.w.dx;                    /* protected mode selector */\n    dtaseg = regs.w.ax;                    /* real mode paragraph */\n    fcboff = 0;\n    dtaoff = sizeof(dos_fcb);\n#ifdef XXX__MK_FP_IS_BROKEN\n    /* XXX  This code may not be trustworthy in general, though it is   */\n    /* valid with DOS/4GW and PMODE/w, which is all we support for now. */\n    regs.w.ax = 6;\n    regs.w.bx = truseg;\n    int386(0x31, &regs, &regs);            /* convert seg to linear address */\n    pfcb = (dos_fcb far *) (((ulg) regs.w.cx << 16) | regs.w.dx);\n    /* pfcb = (dos_fcb far *) ((ulg) dtaseg << 4); */\n    pdta = pfcb + 1;\n#else\n    pfcb = MK_FP(truseg, fcboff);\n    pdta = MK_FP(truseg, dtaoff);\n#endif\n    _fmemset((char far *)pfcb, 0, 2 * sizeof(dos_fcb));\n    /* we pass the REAL MODE paragraph to the dos interrupts: */\n    fcbseg = dtaseg;\n\n#else /* !WATCOMC_386 */\n\n    memset((char *)&dta, 0, sizeof(dos_fcb));\n    memset((char *)&fcb, 0, sizeof(dos_fcb));\n    fcbseg = FP_SEG(pfcb);\n    fcboff = FP_OFF(pfcb);\n    dtaseg = FP_SEG(pdta);\n    dtaoff = FP_OFF(pdta);\n#endif /* ?WATCOMC_386 */\n\n#ifdef DEBUG\n    for (p = (char *)&dta; (p - (char *)&dta) < sizeof(dos_fcb); ++p)\n        if (*p)\n            fprintf(stderr, \"error:  dta[%d] = %x\\n\", (p - (char *)&dta), *p);\n    for (p = (char *)&fcb; (p - (char *)&fcb) < sizeof(dos_fcb); ++p)\n        if (*p)\n            fprintf(stderr, \"error:  fcb[%d] = %x\\n\", (p - (char *)&fcb), *p);\n    printf(\"testing pointer macros:\\n\");\n    segread(&sregs);\n    printf(\"cs = %x, ds = %x, es = %x, ss = %x\\n\", sregs.cs, sregs.ds, sregs.es,\n      sregs.ss);\n#endif /* DEBUG */\n\n#if 0\n#ifdef __TURBOC__\n    bdosptr(0x1a, dta, DO_NOT_CARE);\n#else\n    (intdosx method below)\n#endif\n#endif /* 0 */\n\n    /* set the disk transfer address for subsequent FCB calls */\n    sregs.ds = dtaseg;\n    WREGS(regs,dx) = dtaoff;\n    Trace((stderr, \"segment:offset of pdta = %x:%x\\n\", dtaseg, dtaoff));\n    Trace((stderr, \"&dta = %lx, pdta = %lx\\n\", (ulg)&dta, (ulg)pdta));\n    regs.h.ah = 0x1a;\n    F_intdosx(&regs, &regs, &sregs);\n\n    /* fill in the FCB */\n    sregs.ds = fcbseg;\n    WREGS(regs,dx) = fcboff;\n    pfcb->flag = 0xff;          /* extended FCB */\n    pfcb->vattr = 0x08;         /* attribute:  disk volume label */\n    pfcb->drive = (uch)nLabelDrive;\n\n#ifdef DEBUG\n    Trace((stderr, \"segment:offset of pfcb = %x:%x\\n\",\n      (unsigned int)(sregs.ds),\n      (unsigned int)(WREGS(regs,dx))));\n    Trace((stderr, \"&fcb = %lx, pfcb = %lx\\n\", (ulg)&fcb, (ulg)pfcb));\n    Trace((stderr, \"(2nd check:  labelling drive %c:)\\n\", pfcb->drive-1+'A'));\n    if (pfcb->flag != fcb.flag)\n        fprintf(stderr, \"error:  pfcb->flag = %d, fcb.flag = %d\\n\",\n          pfcb->flag, fcb.flag);\n    if (pfcb->drive != fcb.drive)\n        fprintf(stderr, \"error:  pfcb->drive = %d, fcb.drive = %d\\n\",\n          pfcb->drive, fcb.drive);\n    if (pfcb->vattr != fcb.vattr)\n        fprintf(stderr, \"error:  pfcb->vattr = %d, fcb.vattr = %d\\n\",\n          pfcb->vattr, fcb.vattr);\n#endif /* DEBUG */\n\n    /* check for existing label */\n    Trace((stderr, \"searching for existing label via FCBs\\n\"));\n    regs.h.ah = 0x11;      /* FCB find first */\n#ifdef WATCOMC_386\n    _fstrncpy((char far *)&pfcb->vn, \"???????????\", 11);\n#else\n    strncpy((char *)fcb.vn, \"???????????\", 11);   /* i.e., \"*.*\" */\n#endif /* ?WATCOMC_386 */\n    Trace((stderr, \"fcb.vn = %lx\\n\", (ulg)fcb.vn));\n    Trace((stderr, \"regs.h.ah = %x, regs.x.dx = %04x, sregs.ds = %04x\\n\",\n      (unsigned int)(regs.h.ah), (unsigned int)(WREGS(regs,dx)),\n      (unsigned int)(sregs.ds)));\n    Trace((stderr, \"flag = %x, drive = %d, vattr = %x, vn = %s = %s.\\n\",\n      fcb.flag, fcb.drive, fcb.vattr, fcb.vn, pfcb->vn));\n    F_intdosx(&regs, &regs, &sregs);\n\n/*---------------------------------------------------------------------------\n    If not previously labelled, write a new label.  Otherwise just rename,\n    since MS-DOS 2.x has a bug that damages the FAT when the old label is\n    deleted.\n  ---------------------------------------------------------------------------*/\n\n    if (regs.h.al) {\n        Trace((stderr, \"no label found\\n\\n\"));\n        regs.h.ah = 0x16;                 /* FCB create file */\n#ifdef WATCOMC_386\n        _fstrncpy((char far *)pfcb->vn, newlabel, len);\n        if (len < 11)\n            _fstrncpy((char far *)(pfcb->vn+len), \"           \", 11-len);\n#else\n        strncpy((char *)fcb.vn, newlabel, len);\n        if (len < 11)   /* fill with spaces */\n            strncpy((char *)(fcb.vn+len), \"           \", 11-len);\n#endif\n        Trace((stderr, \"fcb.vn = %lx  pfcb->vn = %lx\\n\", (ulg)fcb.vn,\n          (ulg)pfcb->vn));\n        Trace((stderr, \"flag = %x, drive = %d, vattr = %x\\n\", fcb.flag,\n          fcb.drive, fcb.vattr));\n        Trace((stderr, \"vn = %s = %s.\\n\", fcb.vn, pfcb->vn));\n        F_intdosx(&regs, &regs, &sregs);\n        regs.h.ah = 0x10;                 /* FCB close file */\n        if (regs.h.al) {\n            Trace((stderr, \"unable to write volume name (AL = %x)\\n\",\n              (unsigned int)(regs.h.al)));\n            F_intdosx(&regs, &regs, &sregs);\n            retv = 1;\n        } else {\n            F_intdosx(&regs, &regs, &sregs);\n            Trace((stderr, \"new volume label [%s] written\\n\", newlabel));\n            retv = 0;\n        }\n    } else {\n        Trace((stderr, \"found old label [%s]\\n\\n\", dta.vn));  /* not term. */\n        regs.h.ah = 0x17;                 /* FCB rename */\n#ifdef WATCOMC_386\n        _fstrncpy((char far *)pfcb->vn, (char far *)pdta->vn, 11);\n        _fstrncpy((char far *)pfcb->nn, newlabel, len);\n        if (len < 11)\n            _fstrncpy((char far *)(pfcb->nn+len), \"           \", 11-len);\n#else\n        strncpy((char *)fcb.vn, (char *)dta.vn, 11);\n        strncpy((char *)fcb.nn, newlabel, len);\n        if (len < 11)                     /* fill with spaces */\n            strncpy((char *)(fcb.nn+len), \"           \", 11-len);\n#endif\n        Trace((stderr, \"fcb.vn = %lx  pfcb->vn = %lx\\n\", (ulg)fcb.vn,\n          (ulg)pfcb->vn));\n        Trace((stderr, \"fcb.nn = %lx  pfcb->nn = %lx\\n\", (ulg)fcb.nn,\n          (ulg)pfcb->nn));\n        Trace((stderr, \"flag = %x, drive = %d, vattr = %x\\n\", fcb.flag,\n          fcb.drive, fcb.vattr));\n        Trace((stderr, \"vn = %s = %s.\\n\", fcb.vn, pfcb->vn));\n        Trace((stderr, \"nn = %s = %s.\\n\", fcb.nn, pfcb->nn));\n        F_intdosx(&regs, &regs, &sregs);\n        if (regs.h.al) {\n            Trace((stderr, \"Unable to change volume name (AL = %x)\\n\",\n              (unsigned int)(regs.h.al)));\n            retv = 1;\n        } else {\n            Trace((stderr, \"volume label changed to [%s]\\n\", newlabel));\n            retv = 0;\n        }\n    }\n#ifdef WATCOMC_386\n    regs.w.ax = 0x0101;                    /* free dos memory */\n    regs.w.dx = truseg;\n    int386(0x31, &regs, &regs);\n#endif\n    return retv;\n\n} /* end function volumelabel() */\n\n#endif /* !__GO32__ && !__EMX__ */\n\n\n\n\n\n#if (defined(USE_EF_UT_TIME) || defined(TIMESTAMP))\n/* The following DOS date/time structure is machine-dependent as it\n * assumes \"little-endian\" byte order.  For MSDOS-specific code, which\n * is run on ix86 CPUs (or emulators), this assumption is valid; but\n * care should be taken when using this code as template for other ports.\n */\ntypedef union {\n    ulg z_dostime;\n# ifdef __TURBOC__\n    struct ftime ft;            /* system file time record */\n# endif\n    struct {                    /* date and time words */\n        ush ztime;              /* DOS file modification time word */\n        ush zdate;              /* DOS file modification date word */\n    } zft;\n    struct {                    /* DOS date/time components bitfield */\n        unsigned zt_se : 5;\n        unsigned zt_mi : 6;\n        unsigned zt_hr : 5;\n        unsigned zd_dy : 5;\n        unsigned zd_mo : 4;\n        unsigned zd_yr : 7;\n    } z_dtf;\n} dos_fdatetime;\n#endif /* USE_EF_UT_TIME || TIMESTAMP */\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n /*\n  * MS-DOS VERSION\n  *\n  * Set the output file date/time stamp according to information from the\n  * zipfile directory record for this member, then close the file and set\n  * its permissions (archive, hidden, read-only, system).  Aside from closing\n  * the file, this routine is optional (but most compilers support it).\n  */\n{\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        dos_fdatetime dos_dt;\n        iztimes z_utime;\n        struct tm *t;\n#endif /* USE_EF_UT_TIME */\n\n\n/*---------------------------------------------------------------------------\n        Copy and/or convert time and date variables, if necessary; then set\n        the file time/date.  WEIRD BORLAND \"BUG\":  if output is buffered,\n        and if run under at least some versions of DOS (e.g., 6.0), and if\n        files are smaller than DOS physical block size (i.e., 512 bytes) (?),\n        then files MAY NOT get timestamped correctly--apparently setftime()\n        occurs before any data are written to the file, and when file is\n        closed and buffers are flushed, timestamp is overwritten with\n        current time.  Even with a 32K buffer, this does not seem to occur\n        with larger files.  UnZip output is now unbuffered, but if it were\n        not, could still avoid problem by adding \"fflush(outfile)\" just\n        before setftime() call.  Weird, huh?\n  ---------------------------------------------------------------------------*/\n\n#ifdef USE_EF_UT_TIME\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                              G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n             & EB_UT_FL_MTIME))\n        {\n            TTrace((stderr, \"close_outfile:  Unix e.f. modif. time = %ld\\n\",\n              z_utime.mtime));\n            /* round up (down if \"up\" overflows) to even seconds */\n            if (z_utime.mtime & 1)\n                z_utime.mtime = (z_utime.mtime + 1 > z_utime.mtime) ?\n                                 z_utime.mtime + 1 : z_utime.mtime - 1;\n            TIMET_TO_NATIVE(z_utime.mtime) /* NOP unless MSC 7 or Macintosh */\n            t = localtime(&(z_utime.mtime));\n        } else\n            t = (struct tm *)NULL;\n        if (t != (struct tm *)NULL) {\n            if (t->tm_year < 80) {\n                dos_dt.z_dtf.zt_se = 0;\n                dos_dt.z_dtf.zt_mi = 0;\n                dos_dt.z_dtf.zt_hr = 0;\n                dos_dt.z_dtf.zd_dy = 1;\n                dos_dt.z_dtf.zd_mo = 1;\n                dos_dt.z_dtf.zd_yr = 0;\n            } else {\n                dos_dt.z_dtf.zt_se = t->tm_sec >> 1;\n                dos_dt.z_dtf.zt_mi = t->tm_min;\n                dos_dt.z_dtf.zt_hr = t->tm_hour;\n                dos_dt.z_dtf.zd_dy = t->tm_mday;\n                dos_dt.z_dtf.zd_mo = t->tm_mon + 1;\n                dos_dt.z_dtf.zd_yr = t->tm_year - 80;\n            }\n        } else {\n            dos_dt.z_dostime = G.lrec.last_mod_dos_datetime;\n        }\n# ifdef __TURBOC__\n        setftime(fileno(G.outfile), &dos_dt.ft);\n# else\n        _dos_setftime(fileno(G.outfile), dos_dt.zft.zdate, dos_dt.zft.ztime);\n# endif\n#else /* !USE_EF_UT_TIME */\n# ifdef __TURBOC__\n        setftime(fileno(G.outfile),\n                 (struct ftime *)(&(G.lrec.last_mod_dos_datetime)));\n# else\n        _dos_setftime(fileno(G.outfile),\n                      (ush)(G.lrec.last_mod_dos_datetime >> 16),\n                      (ush)(G.lrec.last_mod_dos_datetime));\n# endif\n#endif /* ?USE_EF_UT_TIME */\n    }\n\n/*---------------------------------------------------------------------------\n    And finally we can close the file...at least everybody agrees on how to\n    do *this*.  I think...  Also change the mode according to the stored file\n    attributes, since we didn't do that when we opened the dude.\n  ---------------------------------------------------------------------------*/\n\n    fclose(G.outfile);\n\n    z_dos_chmod(__G__ G.filename, G.pInfo->file_attr);\n\n} /* end function close_outfile() */\n\n\n\n\n\n#ifdef TIMESTAMP\n\n/*************************/\n/* Function stamp_file() */\n/*************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    dos_fdatetime dos_dt;\n    time_t t_even;\n    struct tm *t;\n    int fd;                             /* file handle */\n\n    /* round up (down if \"up\" overflows) to even seconds */\n    t_even = ((modtime + 1 > modtime) ? modtime + 1 : modtime) & (~1);\n    TIMET_TO_NATIVE(t_even)             /* NOP unless MSC 7.0 or Macintosh */\n    t = localtime(&t_even);\n    if (t == (struct tm *)NULL)\n        return -1;                      /* time conversion error */\n    if (t->tm_year < 80) {\n        dos_dt.z_dtf.zt_se = 0;\n        dos_dt.z_dtf.zt_mi = 0;\n        dos_dt.z_dtf.zt_hr = 0;\n        dos_dt.z_dtf.zd_dy = 1;\n        dos_dt.z_dtf.zd_mo = 1;\n        dos_dt.z_dtf.zd_yr = 0;\n    } else {\n        dos_dt.z_dtf.zt_se = t->tm_sec >> 1;\n        dos_dt.z_dtf.zt_mi = t->tm_min;\n        dos_dt.z_dtf.zt_hr = t->tm_hour;\n        dos_dt.z_dtf.zd_dy = t->tm_mday;\n        dos_dt.z_dtf.zd_mo = t->tm_mon + 1;\n        dos_dt.z_dtf.zd_yr = t->tm_year - 80;\n    }\n    if (((fd = open((char *)fname, 0)) == -1) ||\n# ifdef __TURBOC__\n        (setftime(fd, &dos_dt.ft)))\n# else\n        (_dos_setftime(fd, dos_dt.zft.zdate, dos_dt.zft.ztime)))\n# endif\n    {\n        if (fd != -1)\n            close(fd);\n        return -1;\n    }\n    close(fd);\n    return 0;\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\nvoid prepare_ISO_OEM_translat(__G)\n   __GDEF\n{\n    switch (getdoscodepage()) {\n    case 437:\n    case 850:\n    case 858:\n#ifdef IZ_ISO2OEM_ARRAY\n        iso2oem = iso2oem_850;\n#endif\n#ifdef IZ_OEM2ISO_ARRAY\n        oem2iso = oem2iso_850;\n#endif\n\n    case 932:   /* Japanese */\n    case 949:   /* Korean */\n    case 936:   /* Chinese, simple */\n    case 950:   /* Chinese, traditional */\n    case 874:   /* Thai */\n    case 1258:  /* Vietnamese */\n#ifdef IZ_ISO2OEM_ARRAY\n        iso2oem = NULL;\n#endif\n#ifdef IZ_OEM2ISO_ARRAY\n        oem2iso = NULL;\n#endif\n\n    default:\n#ifdef IZ_ISO2OEM_ARRAY\n       iso2oem = NULL;\n#endif\n#ifdef IZ_OEM2ISO_ARRAY\n       oem2iso = NULL;\n#endif\n    }\n} /* end function prepare_ISO_OEM_translat() */\n\n\n\n\n#ifndef SFX\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\nint dateformat()\n{\n\n/*---------------------------------------------------------------------------\n    For those operating systems that support it, this function returns a\n    value that tells how national convention says that numeric dates are\n    displayed.  Return values are DF_YMD, DF_DMY and DF_MDY (the meanings\n    should be fairly obvious).\n  ---------------------------------------------------------------------------*/\n\n#ifndef WINDLL\n    ush CountryInfo[18];\n#if (!defined(__GO32__) && !defined(__EMX__))\n    ush far *_CountryInfo = CountryInfo;\n    struct SREGS sregs;\n    union REGS regs;\n#ifdef WATCOMC_386\n    ush seg, para;\n\n    memset(&sregs, 0, sizeof(sregs));\n    memset(&regs, 0, sizeof(regs));\n    /* PMODE/W does not support an extended version of dos function 38,   */\n    /* so we have to use brute force, allocating real mode memory for it. */\n    regs.w.ax = 0x0100;\n    regs.w.bx = 3;                         /* 36 bytes rounds up to 48 */\n    int386(0x31, &regs, &regs);            /* DPMI allocate DOS memory */\n    if (regs.w.cflag)\n        return DF_MDY;                     /* no memory, return default */\n    seg = regs.w.dx;\n    para = regs.w.ax;\n\n#ifdef XXX__MK_FP_IS_BROKEN\n    /* XXX  This code may not be trustworthy in general, though it is\n     * valid with DOS/4GW and PMODE/w, which is all we support for now. */\n /* _CountryInfo = (ush far *) (para << 4); */ /* works for some extenders */\n    regs.w.ax = 6;\n    regs.w.bx = seg;\n    int386(0x31, &regs, &regs);            /* convert seg to linear address */\n    _CountryInfo = (ush far *) (((ulg) regs.w.cx << 16) | regs.w.dx);\n#else\n    _CountryInfo = (ush far *) MK_FP(seg, 0);\n#endif\n\n    sregs.ds = para;                       /* real mode paragraph */\n    regs.w.dx = 0;                         /* no offset from segment */\n    regs.w.ax = 0x3800;\n    int86x_realmode(0x21, &regs, &regs, &sregs);\n    CountryInfo[0] = regs.w.cflag ? 0 : _CountryInfo[0];\n    regs.w.ax = 0x0101;\n    regs.w.dx = seg;\n    int386(0x31, &regs, &regs);              /* DPMI free DOS memory */\n\n#else /* !WATCOMC_386 */\n\n    sregs.ds  = FP_SEG(_CountryInfo);\n    regs.x.dx = FP_OFF(_CountryInfo);\n    regs.x.ax = 0x3800;\n    intdosx(&regs, &regs, &sregs);\n#endif /* ?WATCOMC_386 */\n\n#else /* __GO32__ || __EMX__ */\n    _dos_getcountryinfo(CountryInfo);\n#endif /* ?(__GO32__ || __EMX__) */\n\n    switch(CountryInfo[0]) {\n        case 0:\n            return DF_MDY;\n        case 1:\n            return DF_DMY;\n        case 2:\n            return DF_YMD;\n    }\n#endif /* !WINDLL */\n\n    return DF_MDY;   /* default for systems without locale info */\n\n} /* end function dateformat() */\n\n\n\n\n#ifndef WINDLL\n\n/**************************************/\n/*  Function is_running_on_windows()  */\n/**************************************/\n\nstatic int is_running_on_windows(void)\n{\n    char *var = getenv(\"OS\");\n\n    /* if the OS env.var says 'Windows_NT' then */\n    /* we're likely running on a variant of WinNT */\n    if ((var != NULL) && (strcmp(\"Windows_NT\", var) == 0))\n        return TRUE;\n\n    /* if the windir env.var is non-null then */\n    /* we're likely running on a variant of Win9x */\n    /* DOS mode of Win9x doesn't define windir, only winbootdir */\n    /* NT's command.com can't see lowercase env. vars */\n    var = getenv(\"windir\");\n    if ((var != NULL) && (var[0] != '\\0'))\n        return TRUE;\n\n    return FALSE;\n}\n\n\n/**********************************/\n/*  Function check_for_windows()  */\n/**********************************/\n\nvoid check_for_windows(ZCONST char *app)\n{\n#ifdef SMALL_MEM\n    char msg_str[160];          /* enough space for two 79-char-lines  */\n\n    (void)zfstrcpy(msg_buf, WarnUsedOnWindows)\n#else\n#   define msg_str WarnUsedOnWindows\n#endif\n    /* Print a warning for users running under Windows */\n    /* to reduce bug reports due to running DOS version */\n    /* under Windows, when Windows version usually works correctly */\n    if (is_running_on_windows())\n        printf(msg_str, app);\n} /* end function check_for_windows() */\n\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#if defined(__DJGPP__) || defined(__WATCOMC__) || \\\n    (defined(_MSC_VER) && (_MSC_VER != 800))\n    char buf[80];\n#endif\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#if defined(__GNUC__)\n#  if defined(__DJGPP__)\n      (sprintf(buf, \"djgpp v%d.%02d / gcc \", __DJGPP__, __DJGPP_MINOR__), buf),\n#  elif defined(__GO32__)         /* __GO32__ is defined as \"1\" only (sigh) */\n      \"djgpp v1.x / gcc \",\n#  elif defined(__EMX__)          /* ...so is __EMX__ (double sigh) */\n      \"emx+gcc \",\n#  else\n      \"gcc \",\n#  endif\n      __VERSION__,\n#elif defined(__WATCOMC__)\n#  if (__WATCOMC__ % 10 != 0)\n      \"Watcom C/C++\", (sprintf(buf, \" %d.%02d\", __WATCOMC__ / 100,\n                               __WATCOMC__ % 100), buf),\n#  else\n      \"Watcom C/C++\", (sprintf(buf, \" %d.%d\", __WATCOMC__ / 100,\n                               (__WATCOMC__ % 100) / 10), buf),\n#  endif\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n      \"Borland C++\",\n#    if (__BORLANDC__ < 0x0200)\n        \" 1.0\",\n#    elif (__BORLANDC__ == 0x0200)   /* James:  __TURBOC__ = 0x0297 */\n        \" 2.0\",\n#    elif (__BORLANDC__ == 0x0400)\n        \" 3.0\",\n#    elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */\n        \" 3.1\",\n#    elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */\n        \" 4.0 or 4.02\",\n#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */\n        \" 4.5\",\n#    elif (__BORLANDC__ == 0x0500)\n        \" 5.0\",\n#    else\n        \" later than 5.0\",\n#    endif\n#  else\n      \"Turbo C\",\n#    if (__TURBOC__ > 0x0401)        /* Kevin:  3.0 -> 0x0401 */\n        \"++ later than 3.0\",\n#    elif (__TURBOC__ >= 0x0400)\n        \"++ 3.0\",\n#    elif (__TURBOC__ >= 0x0297)     /* see remark for Borland C++ 2.0 */\n        \"++ 2.0\",\n#    elif (__TURBOC__ == 0x0296)     /* [662] checked by SPC */\n        \"++ 1.01\",\n#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */\n        \"++ 1.0\",\n#    elif (__TURBOC__ == 0x0201)     /* Brian:  2.01 -> 0x0201 */\n        \" 2.01\",\n#    elif ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200)) /* James: 0x0200 */\n        \" 2.0\",\n#    elif (__TURBOC__ > 0x0100)\n        \" 1.5\",                      /* James:  0x0105? */\n#    else\n        \" 1.0\",                      /* James:  0x0100 */\n#    endif\n#  endif\n#elif defined(MSC)\n#  if defined(_QC) && !defined(_MSC_VER)\n      \"MS Quick C \", \"2.0 or earlier\",      /* _QC is defined as 1 */\n#  elif defined(_QC) && (_MSC_VER == 600)\n      \"MS Quick C \", \"2.5 (MSC 6.00)\",\n#  else\n      \"Microsoft C \",\n#    ifdef _MSC_VER\n#      if (_MSC_VER == 800)\n        \"8.0/8.0c (Visual C++ 1.0/1.5)\",\n#      else\n        (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf),\n#      endif\n#    else\n      \"5.1 or earlier\",\n#    endif\n#  endif\n#else\n      \"unknown compiler\", \"\",\n#endif /* ?compilers */\n\n      \"\\nMS-DOS\",\n\n#if (defined(__GNUC__) || defined(WATCOMC_386))\n      \" (32-bit)\",\n#else\n#  if defined(M_I86HM) || defined(__HUGE__)\n      \" (16-bit, huge)\",\n#  elif defined(M_I86LM) || defined(__LARGE__)\n      \" (16-bit, large)\",\n#  elif defined(M_I86MM) || defined(__MEDIUM__)\n      \" (16-bit, medium)\",\n#  elif defined(M_I86CM) || defined(__COMPACT__)\n      \" (16-bit, compact)\",\n#  elif defined(M_I86SM) || defined(__SMALL__)\n      \" (16-bit, small)\",\n#  elif defined(M_I86TM) || defined(__TINY__)\n      \" (16-bit, tiny)\",\n#  else\n      \" (16-bit)\",\n#  endif\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n                                /* MSC can't handle huge macro expansion */\n\n    /* temporary debugging code for Borland compilers only */\n#if (defined(__TURBOC__) && defined(DEBUG))\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__TURBOC__ = 0x%04x = %d)\\n\",\n      __TURBOC__, __TURBOC__));\n#ifdef __BORLANDC__\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__BORLANDC__ = 0x%04x)\\n\",\n      __BORLANDC__));\n#else\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__BORLANDC__ not defined)\\n\"));\n#endif\n#ifdef __TCPLUSPLUS__\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__TCPLUSPLUS__ = 0x%04x)\\n\",\n      __TCPLUSPLUS__));\n#else\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__TCPLUSPLUS__ not defined)\\n\"));\n#endif\n#ifdef __BCPLUSPLUS__\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__BCPLUSPLUS__ = 0x%04x)\\n\\n\",\n      __BCPLUSPLUS__));\n#else\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__BCPLUSPLUS__ not defined)\\n\\n\"));\n#endif\n#endif /* __TURBOC__ && DEBUG */\n\n} /* end function version() */\n\n#endif /* !WINDLL */\n#endif /* !SFX */\n\n#endif /* !FUNZIP */\n\n\n\n\n\n#ifdef MY_ZCALLOC       /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */\n\n#if defined(__TURBOC__) && !defined(OS2)\n#include <alloc.h>\n/* Turbo C malloc() does not allow dynamic allocation of 64K bytes\n * and farmalloc(64K) returns a pointer with an offset of 8, so we\n * must fix the pointer. Warning: the pointer must be put back to its\n * original form in order to free it, use zcfree().\n */\n\n#define MAX_PTR 2       /* reduced from 10 to save space */\n/* 10*64K = 640K */\n\nstatic int next_ptr = 0;\n\ntypedef struct ptr_table_s {\n    zvoid far *org_ptr;\n    zvoid far *new_ptr;\n} ptr_table;\n\nstatic ptr_table table[MAX_PTR];\n/* This table is used to remember the original form of pointers\n * to large buffers (64K). Such pointers are normalized with a zero offset.\n * Since MSDOS is not a preemptive multitasking OS, this table is not\n * protected from concurrent access. This hack doesn't work anyway on\n * a protected system like OS/2. Use Microsoft C instead.\n */\n\nzvoid far *zcalloc(unsigned items, unsigned size)\n{\n    zvoid far *buf;\n    ulg bsize = (ulg)items*size;\n\n    if (bsize < (65536L-16L)) {\n        buf = farmalloc(bsize);\n        if (*(ush*)&buf != 0) return buf;\n    } else {\n        buf = farmalloc(bsize + 16L);\n    }\n    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;\n    table[next_ptr].org_ptr = buf;\n\n    /* Normalize the pointer to seg:0 */\n    *((ush*)&buf+1) += ((ush)((uch*)buf-NULL) + 15) >> 4;\n    *(ush*)&buf = 0;\n    table[next_ptr++].new_ptr = buf;\n    return buf;\n}\n\nzvoid zcfree(zvoid far *ptr)\n{\n    int n;\n    if (*(ush*)&ptr != 0) { /* object < 64K */\n        farfree(ptr);\n        return;\n    }\n    /* Find the original pointer */\n    for (n = next_ptr - 1; n >= 0; n--) {\n        if (ptr != table[n].new_ptr) continue;\n\n        farfree(table[n].org_ptr);\n        while (++n < next_ptr) {\n            table[n-1] = table[n];\n        }\n        next_ptr--;\n        return;\n    }\n    Trace((stderr, \"zcfree: ptr not found!\\n\"));\n}\n#endif /* __TURBOC__ */\n\n#if defined(MSC) || defined(__WATCOMC__)\n#if (!defined(_MSC_VER) || (_MSC_VER < 700))\n#  define _halloc  halloc\n#  define _hfree   hfree\n#endif\n\nzvoid far *zcalloc(unsigned items, unsigned size)\n{\n    return (zvoid far *)_halloc((long)items, size);\n}\n\nzvoid zcfree(zvoid far *ptr)\n{\n    _hfree((void huge *)ptr);\n}\n#endif /* MSC || __WATCOMC__ */\n\n#endif /* MY_ZCALLOC */\n\n\n#ifndef FUNZIP\n\n#if (defined(__GO32__) || defined(__EMX__))\n\n#if (!defined(__DJGPP__) || (__DJGPP__ < 2) || \\\n     ((__DJGPP__ == 2) && (__DJGPP_MINOR__ < 2)))\nint volatile _doserrno;\n#endif /* not \"djgpp v2.02 or newer\" */\n\n#if (!defined(__DJGPP__) || (__DJGPP__ < 2))\n\nunsigned _dos_getcountryinfo(void *countrybuffer)\n{\n    asm(\"movl %0, %%edx\": : \"g\" (countrybuffer));\n    asm(\"movl $0x3800, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    asm(\"movl %%eax, %0\": \"=m\" (_doserrno));\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\nunsigned _dos_setftime(int fd, unsigned dosdate, unsigned dostime)\n{\n    asm(\"movl %0, %%ebx\": : \"g\" (fd));\n    asm(\"movl %0, %%ecx\": : \"g\" (dostime));\n    asm(\"movl %0, %%edx\": : \"g\" (dosdate));\n    asm(\"movl $0x5701, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    asm(\"movl %%eax, %0\": \"=m\" (_doserrno));\n    errno = EBADF;\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\nunsigned _dos_setfileattr(const char *name, unsigned attr)\n{\n#if 0   /* stripping of trailing '/' is not needed for unzip-internal use */\n    unsigned namlen = strlen(name);\n    char *i_name = alloca(namlen + 1);\n\n    strcpy(i_name, name);\n    if (namlen > 1 && i_name[namlen-1] == '/' && i_name[namlen-2] != ':')\n        i_name[namlen-1] = '\\0';\n    asm(\"movl %0, %%edx\": : \"g\" (i_name));\n#else\n    asm(\"movl %0, %%edx\": : \"g\" (name));\n#endif\n    asm(\"movl %0, %%ecx\": : \"g\" (attr));\n    asm(\"movl $0x4301, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    asm(\"movl %%eax, %0\": \"=m\" (_doserrno));\n    switch (_doserrno) {\n    case 2:\n    case 3:\n           errno = ENOENT;\n           break;\n    case 5:\n           errno = EACCES;\n           break;\n    }\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\nvoid _dos_getdrive(unsigned *d)\n{\n    asm(\"movl $0x1900, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    asm(\"xorb %ah, %ah\");\n    asm(\"incb %al\");\n    asm(\"movl %%eax, %0\": \"=a\" (*d));\n}\n\nunsigned _dos_creat(const char *path, unsigned attr, int *fd)\n{\n    asm(\"movl $0x3c00, %eax\");\n    asm(\"movl %0, %%edx\": :\"g\" (path));\n    asm(\"movl %0, %%ecx\": :\"g\" (attr));\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    asm(\"movl %%eax, %0\": \"=a\" (*fd));\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    _doserrno = *fd;\n    switch (_doserrno) {\n    case 3:\n           errno = ENOENT;\n           break;\n    case 4:\n           errno = EMFILE;\n           break;\n    case 5:\n           errno = EACCES;\n           break;\n    }\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\nunsigned _dos_close(int fd)\n{\n    asm(\"movl %0, %%ebx\": : \"g\" (fd));\n    asm(\"movl $0x3e00, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    asm (\"movl %%eax, %0\": \"=m\" (_doserrno));\n    if (_doserrno == 6) {\n          errno = EBADF;\n    }\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\n#endif /* !__DJGPP__ || (__DJGPP__ < 2) */\n\n\nstatic int volumelabel(ZCONST char *name)\n{\n    int fd;\n\n    return _dos_creat(name, FA_LABEL, &fd) ? fd : _dos_close(fd);\n}\n\n\n#if (defined(__DJGPP__) && (__DJGPP__ >= 2))\n\n#include <dpmi.h>               /* These includes for the country info */\n#include <go32.h>\n#include <sys/farptr.h>\n\n/* The above _dos_getcountryinfo function doesn't work with djgpp v2, presumably\n * because ds is not set correctly (does it really work at all?). Note that\n * this version only sets the date (ie. CountryInfo[0]).\n */\nunsigned _dos_getcountryinfo(void *countrybuffer)\n{\n   __dpmi_regs regs;\n\n   regs.x.ax = 0x3800;\n   regs.x.dx = __tb & 0x0f;\n   regs.x.ds = (__tb >> 4) & 0xffff;\n   _doserrno = __dpmi_int(0x21, &regs);\n\n   *(ush*)countrybuffer = _farpeekw(_dos_ds, __tb & 0xfffff);\n\n   return (unsigned)_doserrno;\n}\n\n\n/* Disable determination of \"x\" bit in st_mode field for [f]stat() calls. */\nint _is_executable (const char *path, int fhandle, const char *ext)\n{\n    return 0;\n}\n\n#ifndef USE_DJGPP_GLOB\n/* Prevent globbing of filenames.  This gives the same functionality as\n * \"stubedit <program> globbing=no\" did with DJGPP v1.\n */\nchar **__crt0_glob_function(char *_arg)\n{\n    return NULL;\n}\n#endif /* !USE_DJGPP_GLOB */\n\n#ifndef USE_DJGPP_ENV\n/* Reduce the size of the executable and remove the functionality to read\n * the program's environment from whatever $DJGPP points to.\n */\nvoid __crt0_load_environment_file(char *_app_name)\n{\n}\n#endif /* !USE_DJGPP_ENV */\n\n#endif /* __DJGPP__ >= 2 */\n#endif /* __GO32__ || __EMX__ */\n\n\n\nstatic int getdoscodepage(void)\n{\n    union REGS regs;\n\n    WREGS(regs,ax) = 0x6601;\n#ifdef __EMX__\n    _int86(0x21, &regs, &regs);\n    if (WREGS(regs,flags) & 1)\n#else\n    intdos(&regs, &regs);\n    if (WREGS(regs,cflag))\n#endif\n    {\n        Trace((stderr,\n          \"error in DOS function 0x66 (AX = 0x%04x): default to 850...\\n\",\n          (unsigned int)(WREGS(regs,ax))));\n        return 858;\n    } else\n        return WREGS(regs,bx);\n}\n\n\n\n#ifdef __EMX__\n#ifdef MORE\n\n/*************************/\n/* Function screensize() */\n/*************************/\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    int scr_dimen[2];           /* scr_dimen[0]: columns, src_dimen[1]: rows */\n\n    _scrsize(scr_dimen);\n    if (tt_rows != NULL) *tt_rows = scr_dimen[1];\n    if (tt_cols != NULL) *tt_cols = scr_dimen[0];\n    return 0;\n}\n\n#endif /* MORE */\n#endif /* __EMX__ */\n\n\n\n#ifdef WATCOMC_386\n#ifdef MORE\n#include <graph.h>\n\n/*************************/\n/* Function screensize() */\n/*************************/\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    struct videoconfig vc;\n\n    _getvideoconfig(&vc);\n    if (tt_rows != NULL) *tt_rows = (int)(vc.numtextrows);\n    if (tt_cols != NULL) *tt_cols = (int)(vc.numtextcols);\n    return 0;\n}\n\n#endif /* MORE */\n\n\nstatic struct RMINFO {\n    ulg edi, esi, ebp;\n    ulg reserved;\n    ulg ebx, edx, ecx, eax;\n    ush flags;\n    ush es,ds,fs,gs;\n    ush ip_ignored,cs_ignored;\n    ush sp,ss;\n};\n\n/* This function is used to call dos interrupts that may not be supported\n * by some particular 32-bit DOS extender.  It uses DPMI function 300h to\n * simulate a real mode call of the interrupt.  The caller is responsible\n * for providing real mode addresses of any buffer areas used.  The docs\n * for PMODE/W imply that this should not be necessary for calling the DOS\n * interrupts that it doesn't extend, but it crashes when this isn't used. */\n\nstatic int int86x_realmode(int inter_no, union REGS *in,\n                           union REGS *out, struct SREGS *seg)\n{\n    union REGS local;\n    struct SREGS localseg;\n    struct RMINFO rmi;\n    int r;\n\n    rmi.eax = in->x.eax;\n    rmi.ebx = in->x.ebx;\n    rmi.ecx = in->x.ecx;\n    rmi.edx = in->x.edx;\n    rmi.edi = in->x.edi;\n    rmi.esi = in->x.esi;\n    rmi.ebp = rmi.reserved = 0L;\n    rmi.es = seg->es;\n    rmi.ds = seg->ds;\n    rmi.fs = seg->fs;\n    rmi.gs = seg->gs;\n    rmi.sp = rmi.ss = rmi.ip_ignored = rmi.cs_ignored = rmi.flags = 0;\n    memset(&local, 0, sizeof(local));\n    memset(&localseg, 0, sizeof(localseg));\n    local.w.ax = 0x0300;\n    local.h.bl = inter_no;\n    local.h.bh = 0;\n    local.w.cx = 0;\n    localseg.es = FP_SEG(&rmi);\n    local.x.edi = FP_OFF(&rmi);\n    r = int386x(0x31, &local, &local, &localseg);\n    out->x.eax = rmi.eax;\n    out->x.ebx = rmi.ebx;\n    out->x.ecx = rmi.ecx;\n    out->x.edx = rmi.edx;\n    out->x.edi = rmi.edi;\n    out->x.esi = rmi.esi;\n    out->x.cflag = rmi.flags & INTR_CF;\n    return r;\n}\n\n#endif /* WATCOMC_386 */\n\n\n\n\n#ifdef DOS_STAT_BANDAID\n\n/* This papers over a bug in Watcom 10.6's standard library...sigh.\n * Apparently it applies to both the DOS and Win32 stat()s. */\n\nint stat_bandaid(const char *path, struct stat *buf)\n{\n    char newname[4];\n\n    if (!stat(path, buf))\n        return 0;\n    else if (!strcmp(path, \".\") || (path[0] && !strcmp(path + 1, \":.\"))) {\n        strcpy(newname, path);\n        newname[strlen(path) - 1] = '\\\\';   /* stat(\".\") fails for root! */\n        return stat(newname, buf);\n    } else\n        return -1;\n}\n\n#endif /* DOS_STAT_BANDAID */\n\n#endif /* !FUNZIP */\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/Contents",
    "content": "Contents of the \"netware\" subdirectory for UnZip 5.53 and later:\n\n  Contents       this file\n  README         notes about Novell NetWare port\n  makefile.wat   makefile for compiling unzip.nlm using Watcom C 11.0\n  nlmcfg.h       OS-dependent configuration, included by unzpriv.h\n  netware.c       OS-dependent UnZip routines for NetWare\n  unzip.build    Korn-shell build script\n  unzip.link     Watcom link directive file\n\nNotes:\n\nThis port is courtesy of Vance Baarda (Novell NetWare Server Install).\nIt is designed to compile with the Watcom C compiler.  See the README\nfor further info.\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/README",
    "content": "1) I used the Watcom version 11 compiler and the Novell NetWare SDK\n   from October 1998.  You can get the latest NetWare SDK (free).  Go to\n   http://developer.novell.com/ndk/netware.htm#C/C++ and look for \"NLM and\n   NetWare Libraries for C (including CLIB and XPlat)\"\n\n2) The unzip.nlm runs in the same address space as the NetWare OS.\n   In other words, if unzip.nlm crashes, the server will most likely crash.\n   Therefore, I recommend you do not load unzip.nlm on a server that your\n   company depends on for business until it's been thoroughly tested on a\n   test server.\n\n3) I've designed this unzip.nlm port to load on any version of NetWare\n   starting with NetWare 3.12.  However, I've tested it only on NetWare 5.0.\n   If unzip.nlm does not load or run correctly, try the following in\n   this order:\n\n        a) Load clibaux.nlm version 1.21a or later before loading\n           unzip.nlm.  The clibaux.nlm is part of the NetWare SDK package\n           mentioned above.  It's also part of the 3.x C library package\n           mentioned below.\n\n        b) On NetWare 3.x, install the latest 3.x C library modules.\n           Go to http://support.novell.com/misc/patlst.htm#nw and look for\n           \"NetWare 3.12/3.2 CLIB\".\n\n        c) On NetWare 4.10, install the latest 4.10 C library modules.\n           Go to http://support.novell.com/misc/patlst.htm#nw and look for\n           \"Updated modular CLIB and DSAPI\".\n\n        d) On NetWare 4.11 and 4.2, install the latest support pack.\n           Go to http://support.novell.com/misc/patlst.htm#nw and look for\n           \"NetWare 4 Support Pack\".\n\n4) This unzip.nlm assumes that support for the long name space (also\n   known as the OS/2 name space) has already been added to the current\n   working volume.  If it has not, and the zip archive contains files with\n   long names, then the fopen() for such files will just fail.  The code\n   does not attempt to rename the file to fit in a DOS-style name.  The same\n   problem would occur with long directory names.\n\n5) If unzip.nlm works correctly on NetWare 3.x (which it should,\n   but I've not tried it), it will create all files and directories with\n   all-uppercase names. The reason is that the NetWare 3.x C library does\n   not support creating mixed-case or lowercase file names, even in the long\n   (OS/2) name space.\n\n6) To change the current working volume and current working directory\n   in which unzip.nlm loads and runs, load unzip.nlm like this:\n\n        load unzip <unzip options> (CLIB_OPT)/P<volume>:<directory>\n\n   For example:\n\n        load unzip archive.zip (CLIB_OPT)/Pvol1:\\usr\\home\n\n   For more information on CLIB_OPT, go to http://developer.novell.com/search/\n   and enter \"CLIB_OPT\" in the \"Novell Developer Kit Search\" box.\n\n7) To find out more about clibaux.nlm, go to\n   http://developer.novell.com/search/ and enter \"clibaux\" in the \"Novell\n   Developer Kit Search\" box.\n\n\nVance Baarda\nNetWare Server Install\nNovell, Inc.\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/makefile.wat",
    "content": "#------------------------------------------------------------------------------\n# Makefile for UnZip 5.53 and later                      Mark Wright and others\n# Version:  Watcom C                                                  31 Mar 07\n#------------------------------------------------------------------------------\n\n\n# WARNING:  this is a hacked-up version of an ancient (1993) makefile.  It will\n#   not work without modifications to the UnZip 5.3 sources.  This makefile is\n#   (for now) included only for completeness and as a starting point for a real\n#   Novell Netware NLM port.  (This makefile was intended for Netware 3.11.)\n\n\n# Commands to execute before making any target\n# Set environment variables for compiler\n.BEFORE\n    @set inc386=\\watcom\\novh\n    @set wcg386=\\watcom\\binp\\wcl386.exe\n\n# Macro definitions\nNLMNAME = unzip\nDESCRIPTION = unzip utility\nVERSION = 5.5.3\nCOPYRIGHT = Copyright 1990-2007 Info-ZIP (www.info-zip.org).\nSCREENNAME = Info-ZIP's UnZip Utility\nCLIBIMP = \\watcom\\novi\\clib.imp\nOBJFILE = $NLMNAME.obj\nPRELUDE = \\watcom\\novi\\prelude.obj\n\n# Compile switches\n# d2    include full symbolic debugging information\n# 5s    generate 586 instructions, use stack-based argument-passing conventions\n# zdp   allows DS register to \"peg\" it to DGROUP\n# zq    \"quiet\" mode\n# NLM   produce Netware Loadable Module\n# DEBUG include debug info\n\nCC = wcc386\n# COMPILE = wcc386 -zq -d2 -3s -zdp -w4 -DNLM\n# COMPILE = wcc386 -zq -d2 -5s -zdp -w4 -DNLM $(LOCAL_UNZIP)\nCOMPILE = $(CC) -zq -olax -5s -zp1 -ei -ez -ri -w4 -DNLM -DN_PLAT_NLM -U_WIN32 $(LOCAL_UNZIP)\nLINK = wlink\nDESTDIR = target\n\n# All .obj files implicitly depend on .c files\n.c.obj :\n   @echo Compiling $[*.c\n   @$COMPILE $[*.c\n\n\nUNZIP_H = unzip.h unzpriv.h globals.h netware/nlmcfg.h\n\ncrc32.obj:      crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt.obj:      crypt.c $(UNZIP_H) crc32.h crypt.h ttyio.h zip.h\nenvargs.obj:    envargs.c $(UNZIP_H)\nexplode.obj:    explode.c $(UNZIP_H)\nextract.obj:    extract.c $(UNZIP_H) crc32.h crypt.h\nfileio.obj:     fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals.obj:    globals.c $(UNZIP_H)\ninflate.obj:    inflate.c inflate.h $(UNZIP_H)\nlist.obj:       list.c $(UNZIP_H)\nmatch.obj:      match.c $(UNZIP_H)\nprocess.obj:    process.c $(UNZIP_H) crc32.h\nttyio.obj:      ttyio.c $(UNZIP_H) crypt.h ttyio.h zip.h\nunreduce.obj:   unreduce.c $(UNZIP_H)\nunshrink.obj:   unshrink.c $(UNZIP_H)\nunzip.obj:      unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo.obj:    zipinfo.c $(UNZIP_H)\n\n# individual dependencies and action rules:\n#crc_i86.obj:    msdos\\crc_i86.asm\n#\t$(AS) $(ASFLAGS) -D$(ASUNMODEL) msdos\\crc_i86.asm, $@;\n\nnetware.obj:     netware/netware.c $(UNZIP_H)\n\t$(CC) -c -A$(UNMODEL) $(CFLAGS) netware/netware.c\n\n\nOBJ01 = unzip.obj\nOBJ02 = crc32.obj\nOBJ03 = crypt.obj\nOBJ04 = envargs.obj\nOBJ05 = explode.obj\nOBJ06 = extract.obj\nOBJ07 = fileio.obj\nOBJ08 = globals.obj\nOBJ09 = inflate.obj\nOBJ10 = list.obj\nOBJ11 = match.obj\nOBJ12 = process.obj\nOBJ13 = ttyio.obj\nOBJ14 = unreduce.obj\nOBJ15 = unshrink.obj\nOBJ16 = zipinfo.obj\nOBJ17 = netware.obj\n#OBJ18 = $(ASMOBJS)\nOBJS = $OBJFILE $OBJ01 $OBJ02 $OBJ03 $OBJ04 $OBJ05 $OBJ06 $OBJ07 $OBJ08 \\\n\t$OBJ09 $OBJ10 $OBJ11 $OBJ12 $OBJ13 $OBJ14 $OBJ15 $OBJ16 $OBJ17\n\n\n# if .obj or .lnk files are modified, link new .nlm and maybe copy to DESTDIR\n$NLMNAME.nlm : $OBJS\n   @echo Linking...\n   @$LINK @$NLMNAME\n#   @echo Copying $[*.nlm to $DESTDIR\n#   @copy $NLMNAME.nlm $DESTDIR\n\n\n# if makefile is modified, create new linker option file\n$NLMNAME.lnk : $NLMNAME.mak\n   @echo FORMAT   NOVELL NLM\t'$DESCRIPTION'\t >$NLMNAME.lnk\n   @echo OPTION   THREADNAME    '$NLMNAME'\t>>$NLMNAME.lnk\n   @echo OPTION   SCREENNAME '$SCREENNAME'\t>>$NLMNAME.lnk\n   @echo NAME $NLMNAME\t\t\t\t>>$NLMNAME.lnk\n   @echo OPTION   VERSION=$VERSION\t\t>>$NLMNAME.lnk\n   @echo OPTION   COPYRIGHT '$COPYRIGHT'\t>>$NLMNAME.lnk\n   @echo DEBUG    NOVELL                        >>$NLMNAME.lnk\n   @echo DEBUG    ALL                           >>$NLMNAME.lnk\n   @echo OPTION   NODEFAULTLIBS\t\t\t>>$NLMNAME.lnk\n   @echo OPTION   DOSSEG\t\t\t>>$NLMNAME.lnk\n   @echo OPTION   STACK=40000\t\t\t>>$NLMNAME.lnk\n   @echo OPTION   CASEEXACT\t\t\t>>$NLMNAME.lnk\n   @echo OPTION   PSEUDOPREEMPTION\t\t>>$NLMNAME.lnk\n   @echo OPTION   MAP\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $PRELUDE\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJFILE\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ01\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ02\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ03\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ04\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ05\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ06\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ07\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ08\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ09\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ10\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ11\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ12\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ13\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ14\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ15\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ16\t\t\t\t>>$NLMNAME.lnk\n   @echo FILE $OBJ17\t\t\t\t>>$NLMNAME.lnk\n   @echo MODULE   clib\t\t\t\t>>$NLMNAME.lnk\n   @echo IMPORT   @$CLIBIMP\t\t\t>>$NLMNAME.lnk\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/netware.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  netware.c\n\n  This file implements these functions for a NetWare Loadable Module (NLM):\n\n  Contains:  InitUnZipConsole()\n             do_wild()\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             stamp_file()\n             version()\n             screensize()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include <dirent.h>\n#include <nwdir.h>\n#include <nwnamspc.h>\n#include <nwconio.h>\n#include <nwthread.h>\n#include <nwadv.h>\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\n\n/*********************************/\n/*  Function InitUnZipConsole()  */\n/*********************************/\n\nvoid InitUnZipConsole()\n{\n    unsigned int myHandle = GetNLMHandle();\n    unsigned int *activeScreen =\n            ImportSymbol(myHandle, \"activeScreen\");\n    unsigned int *systemConsoleScreen =\n            ImportSymbol(myHandle, \"systemConsoleScreen\");\n    void (*pUseAccurateCaseForPaths)(int) =\n            ImportSymbol(myHandle, \"UseAccurateCaseForPaths\");\n\n    if (!activeScreen || !systemConsoleScreen ||\n            *activeScreen == *systemConsoleScreen)\n        CreateScreen(\"Info-ZIP UnZip Utility\", 0);\n    else\n        CreateScreen(\"System Console\", DONT_AUTO_ACTIVATE);\n\n    SetCurrentNameSpace(NW_NS_LONG);\n    if (pUseAccurateCaseForPaths)\n            pUseAccurateCaseForPaths(TRUE);\n\n    UnimportSymbol(myHandle, \"activeScreen\");\n    UnimportSymbol(myHandle, \"systemConsoleScreen\");\n    UnimportSymbol(myHandle, \"UseAccurateCaseForPaths\");\n}\n\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;      /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = strrchr(wildspec, '/')) == (ZCONST char *)NULL) {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 == case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;  /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                return 0;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap from the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                return 0;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n/**********************/\n/* Function mapname() */\n/**********************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in Netware */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n#if !defined(NO_CHMOD) && !defined(NLM)\n            /* In NetWare, chmod does not work on directories */\n            /* set approx. dir perms (make sure can still read/write in dir) */\n            if (chmod(G.filename, (0xffff & G.pInfo->file_attr) | 0700))\n                perror(\"chmod (directory attributes) error\");\n#endif\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                /* path doesn't exist:  nothing to do */\n                return MPN_INF_SKIP;\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+\n                                        (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            if (pathcomp[rootlen-1] == '/') {\n                pathcomp[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (stat(pathcomp, &G.statbuf) ||\n                !S_ISDIR(G.statbuf.st_mode)))       /* path does not exist */\n            {\n                if (!G.create_dirs /* || iswild(pathcomp) */ ) {\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here to scan pathcomp\n                 * and create more than one level, but why really necessary?) */\n                if (mkdir(pathcomp) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(pathcomp)));\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdirectory levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            if ((rootpath = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(rootpath, pathcomp);\n            rootpath[rootlen++] = '/';\n            rootpath[rootlen] = '\\0';\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    fclose(G.outfile);\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        WORD date = G.lrec.last_mod_dos_datetime >> 16;\n        WORD time = G.lrec.last_mod_dos_datetime & 0xffff;\n        static struct ModifyStructure changeBuffer;\n\n        /* set the file's access and modification times */\n        changeBuffer.MLastAccessedDate = date;\n        changeBuffer.MLastUpdatedDate = date;\n        changeBuffer.MLastUpdatedTime = time;\n        if (ChangeDirectoryEntry(G.filename, &changeBuffer,\n              MLastAccessedDateBit | MLastUpdatedDateBit | MLastUpdatedTimeBit,\n              0))\n        {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot set times for %s\\n\",\n                  FnFilter1(G.filename)));\n            else\n                Info(slide, 0x201, ((char *)slide,\n                  \" (warning) cannot set times\"));\n        }\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n\n} /* end function close_outfile() */\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    ztimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)\n    char buf[80];\n#endif\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#if defined(__GNUC__)\n#  ifdef __EMX__  /* __EMX__ is defined as \"1\" only (sigh) */\n      \"emx+gcc \", __VERSION__,\n#  else\n      \"gcc/2 \", __VERSION__,\n#  endif\n#elif defined(__WATCOMC__)\n      \"Watcom C\", (sprintf(buf, \" (__WATCOMC__ = %d)\", __WATCOMC__), buf),\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n      \"Borland C++\",\n#    if (__BORLANDC__ < 0x0460)\n        \" 1.0\",\n#    elif (__BORLANDC__ == 0x0460)\n        \" 1.5\",                     /* from Kai Uwe:  three less than DOS */\n#    else\n        \" 2.0\",                     /* (__BORLANDC__ == 0x0500)? */\n#    endif\n#  else\n      \"Turbo C\",                    /* these are probably irrelevant */\n#    if (__TURBOC__ >= 661)\n       \"++ 1.0 or later\",\n#    elif (__TURBOC__ == 661)\n       \" 3.0?\",\n#    elif (__TURBOC__ == 397)\n       \" 2.0\",\n#    else\n       \" 1.0 or 1.5?\",\n#    endif\n#  endif\n#elif defined(MSC)\n      \"Microsoft C \",\n#  ifdef _MSC_VER\n      (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf),\n#  else\n      \"5.1 or earlier\",\n#  endif\n#else\n      \"unknown compiler\", \"\",\n#endif /* ?compilers */\n\n      \"NetWare\",\n      \" (32-bit)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n                                /* MSC can't handle huge macro expansions */\n\n} /* end function version() */\n\n\n#ifdef MORE\n\n/*************************/\n/* Function screensize() */\n/*************************/\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    WORD height;\n    WORD width;\n\n    if (GetSizeOfScreen(&height, &width) == 0) {\n        if (tt_rows != NULL) *tt_rows = height;\n        if (tt_cols != NULL) *tt_cols = width;\n        return 0;       /* signal success */\n    } else {\n        if (tt_rows != NULL) *tt_rows = 25;\n        if (tt_cols != NULL) *tt_cols = 80;\n        return 1;       /* signal failure */\n    }\n}\n\n#endif /* MORE */\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/nlm_EOL.pat",
    "content": "diff -rc2 ./fileio.c e:fileio.c\n*** ./fileio.c\tSat Dec  4 19:58:26 1999\n--- e:fileio.c\tSat Dec  4 20:54:10 1999\n***************\n*** 85,88 ****\n--- 85,91 ----\n     (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))\n  #else /* !WINDLL */\n+ #ifdef NLM\n+ #  define WriteError(buf,len,strm) nlm_WriteError(buf, (extent)(len), strm)\n+ #else /* !NLM */\n  #  ifdef USE_FWRITE\n  #    define WriteError(buf,len,strm) \\\n***************\n*** 92,95 ****\n--- 95,99 ----\n       ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))\n  #  endif\n+ #endif /* ?NLM */\n  #endif /* ?WINDLL */\n  \ndiff -rc2 ./netware/nlmcfg.h e:netware/nlmcfg.h\n*** ./netware/nlmcfg.h\tSat Dec  4 20:39:20 1999\n--- e:netware/nlmcfg.h\tSat Dec  4 21:20:36 1999\n***************\n*** 21,25 ****\n  #  define lenEOL          2\n  #  define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}\n- #  define USE_FWRITE    /* write() fails to support textmode output */\n  #  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n  #    define TIMESTAMP\n--- 21,24 ----\n***************\n*** 30,32 ****\n--- 29,32 ----\n     void InitUnZipConsole OF((void));\n     int screenlines       OF((void));\n+    int nlm_WriteError    OF((uch *buf, extent len, FILE *strm));\n  #endif /* NLM */\ndiff -rc2 ./netware/netware.c e:netware/netware.c\n*** ./netware/netware.c\tSat Dec  4 21:11:52 1999\n--- e:netware/netware.c\tSat Dec  4 21:28:38 1999\n***************\n*** 22,25 ****\n--- 22,26 ----\n               version()\n               screenlines()\n+              nlm_WriteError()\n  \n    ---------------------------------------------------------------------------*/\n***************\n*** 821,822 ****\n--- 822,850 ----\n  \n  #endif /* MORE */\n+ \n+ \n+ /*******************************/\n+ /*  Function nlm_WriteError()  */\n+ /*******************************/\n+ \n+ int nlm_WriteError(buf, len, strm)\n+     uch *buf;\n+     extent len;\n+     FILE *strm;\n+ {\n+     /* The write() implementation in the Novell C RTL lacks support of\n+        text-mode streams (fails to translate '\\n' into \"CR-LF\" when\n+        writing to text-mode channels like the console).\n+        In contrast, fwrite() takes into account when an output stream\n+        was opened in text-mode, but fails to handle output of large\n+        buffers correctly.\n+        So, we have to use Unix I/O style write() when emitting data\n+        to \"regular\" files but switch over to stdio's fwrite() when\n+        writing to the console streams.\n+      */\n+     if ((strm == stdout)) || (file == stderr)) {\n+          return ((extent)fwrite((char *)buf, 1, len, strm) != len);\n+     } else {\n+          return ((extent)write(fileno(strm), (char *)buf, len) != len);\n+     }\n+ } /* end function nlm_WriteError() */\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/nlmcfg.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifdef NLM\n#  include <sys/types.h>\n#  include <sys/stat.h>\n#  include <fcntl.h>\n#  include <unistd.h>\n#  include <utime.h>\n#  include <nwfileio.h>\n#  define DIRENT\n#  include <time.h>\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_MDY\n#  endif\n#  define lenEOL          2\n#  define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}\n#  define USE_FWRITE    /* write() fails to support textmode output */\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#    define TIMESTAMP\n#  endif\n#  define MAIN main\n#  define DECLARE_TIMEZONE\n#  define SCREENWIDTH 80\n#  define SCREENSIZE(scrrows, scrcols)  screensize(scrrows, scrcols)\n   void InitUnZipConsole OF((void));\n   int screensize        OF((int *tt_rows, int *tt_cols));\n#endif /* NLM */\n"
  },
  {
    "path": "deps/infozip/unzip60/netware/unzip.link",
    "content": "format novell NLM 'unzip utility'\nname unzip\noption caseexact\noption copyright 'Copyright 1990-2005 Info-ZIP (www.info-zip.org).'\noption map = unzip.map\noption nodefaultlibs\noption quiet\noption screenname 'none'\noption stack = 32k\noption symfile = unzip.sym\noption threadname 'unzip'\noption version = 5.5.1\nmodule clib\nimport @c:/novell/ndk/nwsdk/imports/clib.imp\nimport @c:/novell/ndk/nwsdk/imports/nlmlib.imp\nimport @c:/novell/ndk/nwsdk/imports/threads.imp\nimport @c:/novell/ndk/nwsdk/imports/nit.imp\nfile crc32.obj\nfile crypt.obj\nfile envargs.obj\nfile explode.obj\nfile extract.obj\nfile fileio.obj\nfile globals.obj\nfile inflate.obj\nfile list.obj\nfile match.obj\nfile netware.obj\nfile process.obj\nfile ttyio.obj\nfile unreduce.obj\nfile unshrink.obj\nfile unzip.obj\nfile zipinfo.obj\nfile c:/novell/ndk/nwsdk/imports/nwpre.obj\n"
  },
  {
    "path": "deps/infozip/unzip60/new-cmdparser/unz6-newcmdparser-diffs.txt",
    "content": "diff -ru2 unz60e03/unzip.c u6e3_np/unzip.c\n--- unz60e03/unzip.c\tWed Mar 19 13:08:38 2008\n+++ u6e3_np/unzip.c\tMon Mar 24 14:16:58 2008\n@@ -128,4 +128,6 @@\n     \"error:  command line parameter #%d exceeds internal size limit\\n\";\n #endif /* !SFX */\n+static ZCONST char Far NoMemArgsList[] =\n+  \"error:  no memory for arguments list\";\n \n #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\n@@ -245,5 +247,5 @@\n    static ZCONST char Far local3[] = \"\\\n   -Y  treat \\\".nnn\\\" as \\\";nnn\\\" version         -2  force ODS2 names\\n\\\n-  --D restore dir (-D: no) timestamps        -M  pipe through \\\"more\\\" pager\\n\\\n+  -D- restore dir (-D: no) timestamps        -M  pipe through \\\"more\\\" pager\\n\\\n   (Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND.)\\\n \\n\\n\";\n@@ -251,5 +253,5 @@\n    static ZCONST char Far local3[] = \"\\n\\\n   -Y  treat \\\".nnn\\\" as \\\";nnn\\\" version         -2  force ODS2 names\\n\\\n-  --D restore dir (-D: no) timestamps\\n\\\n+  -D- restore dir (-D: no) timestamps\\n\\\n   (Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND.)\\\n \\n\\n\";\n@@ -694,5 +696,5 @@\n     char *p;\n #endif\n-#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))\n+#if ((defined(WIN32) && defined(__RSXNT__)) || !defined(SFX))\n     int i;\n #endif\n@@ -1053,4 +1055,45 @@\n      * 'forward slashes' for user's convenience (include zipfile name itself)\n      */\n+    {\n+        /* pfnames */\n+\n+        char **names;\n+\n+        for (names = G.pfnames; *names; names++) {\n+#ifdef __human68k__\n+            extern char *_toslash(char *);\n+            _toslash(*names);\n+#else /* !__human68k__ */\n+            char *q = *names;\n+\n+            while (*q != '\\0') {\n+                if (*q == '\\\\')\n+                    *q = '/';\n+                INCSTR(q);\n+            }\n+#endif /* ?__human68k__ */\n+        }\n+    }\n+    {\n+        /* G.wildzipfn */\n+\n+#ifdef __human68k__\n+        extern char *_toslash(char *);\n+        _toslash(*G.wildzipfn);\n+#else /* !__human68k__ */\n+        char *q = G.wildzipfn;\n+\n+        while (*q != '\\0') {\n+            if (*q == '\\\\')\n+                *q = '/';\n+            INCSTR(q);\n+        }\n+#endif /* ?__human68k__ */\n+    }\n+#endif /* DOS_FLX_H68_NLM_OS2_W32 */\n+\n+\n+#if 0\n+#ifdef DOS_FLX_H68_NLM_OS2_W32\n #ifdef SFX\n     for (G.pfnames = argv, i = argc;  i > 0;  --i) {\n@@ -1074,11 +1117,18 @@\n     }\n #endif /* DOS_FLX_H68_NLM_OS2_W32 */\n+#endif /* 0 */\n \n+/*\n #ifndef SFX\n     G.wildzipfn = *argv++;\n #endif\n+*/\n \n #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */\n \n+# if 0\n+    /* all this should be done in the options call now */\n+\n+\n     G.filespecs = argc;\n     G.xfilespecs = 0;\n@@ -1104,7 +1154,10 @@\n     } else\n         G.process_all_files = TRUE;      /* for speed */\n+# endif\n \n #else /* !SFX || SFX_EXDIR */             /* check for -x or -d */\n \n+# if 0\n+\n     G.filespecs = argc;\n     G.xfilespecs = 0;\n@@ -1118,9 +1171,9 @@\n         while (*++pp) {\n             Trace((stderr, \"pp - argv = %d\\n\", pp-argv));\n-#ifdef CMS_MVS\n+# ifdef CMS_MVS\n             if (!uO.exdir && STRNICMP(*pp, \"-d\", 2) == 0) {\n-#else\n+# else\n             if (!uO.exdir && strncmp(*pp, \"-d\", 2) == 0) {\n-#endif\n+# endif\n                 int firstarg = (pp == argv);\n \n@@ -1177,4 +1230,5 @@\n     } else\n         G.process_all_files = TRUE;      /* for speed */\n+# endif\n \n     if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */\n@@ -1260,4 +1314,269 @@\n \n \n+/*\n+  -------------------------------------------------------\n+  Command Line Options\n+  -------------------------------------------------------\n+\n+  Valid command line options.\n+\n+  The function get_option() uses this table to check if an\n+  option is valid and if it takes a value (also called an\n+  option parameter).  To add an option to unzip just add it\n+  to this table and add a case in the main switch to handle\n+  it.  If either shortopt or longopt not used set to \"\".\n+\n+   The fields:\n+       option_group - UZO for UnZip option, ZIO for ZipInfo option\n+       shortopt     - short option name (1 or 2 chars)\n+       longopt      - long option name\n+       value_type   - see zip.h for constants\n+       negatable    - option is negatable with trailing -\n+       ID           - unsigned long int returned for option\n+       name         - short description of option which is\n+                        returned on some errors and when options\n+                        are listed with -so option, can be NULL\n+*/\n+\n+/* Most option IDs are set to the shortopt char.  For\n+   multichar short options set to arbitrary unused constant. */\n+#define o_so            0x101\n+\n+\n+/* The below is from the old main command line code with a few changes.\n+   Note that UnZip and ZipInfo filter out their own options based on the\n+   option_group value, so the same option letter can be used for both. */\n+\n+static struct option_struct far options[] = {\n+\n+  /* UnZip options */\n+\n+  /* short longopt                      value_type        negatable\n+       ID    name */\n+#ifdef RISCOS\n+    {UZO, \"/\",  \"\",                     o_REQUIRED_VALUE, o_NEGATABLE,\n+       '/',  \"override Unzip$Exts\"},\n+#endif\n+    {UZO, \"a\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'a',  \"text conv (EOL char, ASCII->EBCDIC\"},\n+#if (defined(DLL) && defined(API_DOC))\n+    {UZO, \"A\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'A',  \"extended help for API\"},\n+#endif\n+    {UZO, \"b\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'b',  \"binary, no ASCII conversions\"},\n+#ifdef UNIXBACKUP\n+    {UZO, \"B\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'B',  \"back up existing files\"},\n+#endif\n+#ifdef CMS_MVS\n+    {UZO, \"B\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'b',  \"CMS/MVS binary\"},\n+#endif\n+    {UZO, \"c\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'c',  \"output to stdout\"},\n+#ifdef CMS_MVS\n+    /* for CMS_MVS map to lower case */\n+    {UZO, \"C\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'C',  \"CMS/MVS lower case\"},\n+#endif\n+#if (!defined(SFX) || defined(SFX_EXDIR))\n+    {UZO, \"d\",  \"\",                     o_REQUIRED_VALUE, o_NEGATABLE,\n+       'd',  \"extraction root directory\"},\n+#endif\n+#if (!defined(NO_TIMESTAMPS))\n+    {UZO, \"D\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'D',  \"don't restore dir (-DD: any) timestamps\"},\n+#endif\n+    {UZO, \"e\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'e',  \"extract (not used?)\"},\n+#ifdef MACOS\n+    {UZO, \"E\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'E',  \"display Mac e.f. when restoring\"},\n+#endif\n+    {UZO, \"f\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'f',  \"freshen (extract only newer files)\"},\n+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n+    {UZO, \"F\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'F',  \"Acorn filetype & NFS extension handling\"},\n+#endif\n+    {UZO, \"h\",  \"\",                     o_NO_VALUE,       o_NOT_NEGATABLE,\n+       'h',  \"help\"},\n+#ifdef MACOS\n+    {UZO, \"i\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'i',  \"ignore filenames stored in Mac ef\"},\n+#endif\n+    {UZO, \"j\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'j',  \"junk directories, extract names only\"},\n+#if (defined(ATH_BEO) || defined(MACOS))\n+    {UZO, \"J\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'J',  \"Junk AtheOS, BeOS or MacOS file attrs\"},\n+#endif\n+#ifdef ATH_BEO_UNX\n+    {UZO, \"K\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'K',  \"retain SUID/SGID/Tacky attrs\"},\n+#endif\n+#ifndef SFX\n+    {UZO, \"l\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+        'l',  \"listing verbosity\"},\n+#endif\n+#ifndef CMS_MVS\n+    {UZO, \"L\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'L',  \"convert (some) names to lower\"},\n+#endif\n+#ifdef MORE\n+# ifdef CMS_MVS\n+    {UZO, \"m\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'm',  \"pipe output through more\"},\n+# endif\n+    {UZO, \"M\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'M',  \"pipe output through more\"},\n+#endif /* MORE */\n+    {UZO, \"n\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'n',  \"never overwrite files (no prompting)\"},\n+#ifdef AMIGA\n+    {UZO, \"N\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'N',  \"restore comments as filenotes\"},\n+#endif\n+    {UZO, \"o\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'o',  \"overwrite files without prompting\"},\n+    {UZO, \"p\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'p',  \"pipe extraction to stdout, no messages\"},\n+#if CRYPT\n+    {UZO, \"P\",  \"\",                     o_REQUIRED_VALUE, o_NEGATABLE,\n+       'P',  \"password\"},\n+#endif\n+    {UZO, \"q\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'q',  \"quiet\"},\n+#ifdef QDOS\n+    {UZO, \"Q\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'Q',  \"QDOS flags\"},\n+#endif\n+#ifdef TANDEM\n+    {UZO, \"r\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'r',  \"remove file extensions\"},\n+#endif\n+#ifdef DOS_FLX_NLM_OS2_W32\n+    {UZO, \"s\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       's',  \"spaces to underscores\"},\n+#endif\n+#ifdef VMS\n+    {UZO, \"S\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'S',  \"VMS extract text as Stream LF\"},\n+#endif\n+    {UZO, \"t\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       't',  \"test\"},\n+#ifdef TIMESTAMP\n+    {UZO, \"T\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'T',  \"timestamps\"},\n+#endif\n+    {UZO, \"u\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'u',  \"update (extract only new/newer files)\"},\n+#ifdef UNICODE_SUPPORT\n+    {UZO, \"U\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'U',  \"escape non-ASCII Unicode, disable Unicode\"},\n+#else /* !UNICODE_SUPPORT */\n+# ifndef CMS_MVS\n+    {UZO, \"U\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'U',  \"names to lower case\"},\n+# endif /* !CMS_MVS */\n+#endif /* ?UNICODE_SUPPORT */\n+#ifndef SFX\n+    {UZO, \"v\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'v',  \"verbose\"},\n+#endif\n+#ifndef CMS_MVS\n+    {UZO, \"V\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'V',  \"don't strip VMS version numbers\"},\n+#endif\n+#ifdef WILD_STOP_AT_DIR\n+    {UZO, \"W\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'W',  \"wildcard * doesn't span /\"},\n+#endif\n+    {UZO, \"x\",  \"\",                     o_VALUE_LIST,     o_NOT_NEGATABLE,\n+       'x',  \"exclude this list of files\"},\n+#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))\n+    {UZO, \"X\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'X',  \"restore owner/prot or UID/GID or ACLs\"},\n+#endif\n+#ifdef VMS\n+    {UZO, \"Y\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'Y',  \"VMS treat .nnn as ;nnn version\"},\n+#endif\n+    {UZO, \"z\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'z',  \"display zipfile comment\"},\n+#ifndef SFX\n+    {UZO, \"Z\",  \"\",                     o_NO_VALUE,       o_NOT_NEGATABLE,\n+       'Z',  \"ZipInfo mode\"},\n+#endif\n+#ifdef VMS\n+    {UZO, \"2\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       '2',  \"Force ODS2-compliant names.\"},\n+#endif\n+#ifdef DOS_H68_OS2_W32\n+    {UZO, \"$\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       '$',  \"extract volume labels\"},\n+#endif\n+#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))\n+    {UZO, \":\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       ':',  \"don't skip ../ path elements\"},\n+#endif\n+#ifdef UNIX\n+    {UZO, \"^\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       '^',  \"allow control chars in filenames\"},\n+#endif\n+\n+#ifndef NO_ZIPINFO\n+  /* ZipInfo options */\n+\n+  /* short longopt                      value_type        negatable\n+       ID    name (help text) */\n+    {ZIO, \"1\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       '1',  \"shortest list\"},\n+    {ZIO, \"2\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       '2',  \"names and headers\"},\n+#ifndef CMS_MVS\n+    {ZIO, \"C\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'C',  \"ignore case\"},\n+#endif\n+    {ZIO, \"h\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'h',  \"header line\"},\n+    {ZIO, \"l\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'l',  \"longer listing\"},\n+    {ZIO, \"m\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'm',  \"medium listing\"},\n+#ifdef MORE\n+    {ZIO, \"M\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'M',  \"output like more\"},\n+#endif\n+    {ZIO, \"s\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       's',  \"shorter list\"},\n+    {ZIO, \"t\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       't',  \"totals line\"},\n+    {ZIO, \"T\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'T',  \"decimal time format\"},\n+#ifdef UNICODE_SUPPORT\n+    {ZIO, \"U\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'U',  \"escape non-ASCII Unicode, disable Unicode\"},\n+#endif\n+    {ZIO, \"v\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'v',  \"turbo-verbose listing\"},\n+#ifdef WILD_STOP_AT_DIR\n+    {ZIO, \"W\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'W',  \"wild stop at /\"},\n+#endif\n+    {ZIO, \"x\",  \"\",                     o_VALUE_LIST,     o_NOT_NEGATABLE,\n+       'x',  \"exclude this list of files\"},\n+    {ZIO, \"z\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'z',  \"print zipfile comment\"},\n+    {ZIO, \"Z\",  \"\",                     o_NO_VALUE,       o_NEGATABLE,\n+       'Z',  \"ZipInfo mode\"},\n+#endif /* !NO_ZIPINFO */\n+\n+    /* the end of the list */\n+    {0,   NULL, NULL,                   o_NO_VALUE,       o_NOT_NEGATABLE,\n+       0,    NULL} /* end has option_ID = 0 */\n+  };\n+\n \n \n@@ -1271,502 +1590,649 @@\n     char ***pargv;\n {\n-    char **argv, *s;\n-    int argc, c, error=FALSE, negative=0;\n+    char **args;\n+    int argc, error=FALSE;\n \n+    /* used by get_option */\n+    unsigned long option; /* option ID returned by get_option */\n+    int argcnt = 0;       /* current argcnt in args */\n+    int argnum = 0;       /* arg number */\n+    int optchar = 0;      /* option state */\n+    char *value = NULL;   /* non-option arg, option value or NULL */\n+    int negative = 0;     /* 1 = option negated */\n+    int fna = 0;          /* current first non-opt arg */\n+    int optnum = 0;       /* index in table */\n \n-    argc = *pargc;\n-    argv = *pargv;\n \n-    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {\n-        s = *argv + 1;\n-        while ((c = *s++) != 0) {    /* \"!= 0\":  prevent Turbo C warning */\n-#ifdef CMS_MVS\n-            switch (tolower(c))\n-#else\n-            switch (c)\n-#endif\n-            {\n-                case ('-'):\n-                    ++negative;\n-                    break;\n+    /* since get_option() returns xfiles and files one at a time, store them\n+       in linked lists until have them all */\n+\n+    int file_count = 0;\n+    struct file_list *next_file;\n+\n+    /* files to extract */\n+    int in_files_count = 0;\n+    struct file_list *in_files = NULL;\n+    struct file_list *next_in_files = NULL;\n+\n+    /* files to exclude in -x list */\n+    int in_xfiles_count = 0;\n+    struct file_list *in_xfiles = NULL;\n+    struct file_list *next_in_xfiles = NULL;\n+\n+    G.wildzipfn = NULL;\n+\n+    /* make copy of args that can use with insert_arg() used by get_option() */\n+    args = copy_args(*pargv, 0);\n+\n+\n+    /* Initialize lists */\n+    G.filespecs = 0;\n+    G.xfilespecs = 0;\n+\n+\n+    /*\n+    -------------------------------------------\n+    Process command line using get_option\n+    -------------------------------------------\n+\n+    Each call to get_option() returns either a command\n+    line option and possible value or a non-option argument.\n+    Arguments are permuted so that all options (-r, -b temp)\n+    are returned before non-option arguments (zipfile).\n+    Returns 0 when nothing left to read.\n+    */\n+\n+    /* set argnum = 0 on first call to init get_option */\n+    argnum = 0;\n+\n+    /* get_option returns the option ID and updates parameters:\n+           args    - usually same as argv if no argument file support\n+           argcnt  - current argc for args\n+           value   - char* to value (free() when done with it) or NULL if none\n+           negated - option was negated with trailing -\n+    */\n+\n+    while ((option = get_option(UZO, &args, &argcnt, &argnum,\n+                                &optchar, &value, &negative,\n+                                &fna, &optnum, 0)))\n+    {\n+        if(option == o_BAD_ERR) {\n+          return(PK_PARAM);\n+        }\n+\n+        switch (option)\n+        {\n #ifdef RISCOS\n-                case ('/'):\n-                    if (negative) {   /* negative not allowed with -/ swap */\n-                        Info(slide, 0x401, ((char *)slide,\n-                          \"error:  must give extensions list\"));\n-                        return(PK_PARAM);  /* don't extract here by accident */\n-                    }\n-                    exts2swap = s; /* override Unzip$Exts */\n-                    s += strlen(s);\n-                    break;\n-#endif\n-                case ('a'):\n-                    if (negative) {\n-                        uO.aflag = MAX(uO.aflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.aflag;\n-                    break;\n+            case ('/'):\n+                if (negative) {   /* negative not allowed with -/ swap */\n+                    Info(slide, 0x401, ((char *)slide,\n+                      \"error:  must give extensions list\"));\n+                    return(PK_PARAM);  /* don't extract here by accident */\n+                }\n+                exts2swap = value; /* override Unzip$Exts */\n+                break;\n+#endif\n+            case ('a'):\n+                if (negative) {\n+                    uO.aflag = MAX(uO.aflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.aflag;\n+                break;\n #if (defined(DLL) && defined(API_DOC))\n-                case ('A'):    /* extended help for API */\n-                    APIhelp(__G__ argc, argv);\n-                    *pargc = -1;  /* signal to exit successfully */\n-                    return 0;\n+            case ('A'):    /* extended help for API */\n+                APIhelp(__G__ argc, args);\n+                *pargc = -1;  /* signal to exit successfully */\n+                return 0;\n #endif\n-                case ('b'):\n-                    if (negative) {\n+            case ('b'):\n+                if (negative) {\n #if (defined(TANDEM) || defined(VMS))\n-                        uO.bflag = MAX(uO.bflag-negative,0);\n+                    uO.bflag = MAX(uO.bflag-negative,0);\n #endif\n-                        negative = 0;   /* do nothing:  \"-b\" is default */\n-                    } else {\n+                    negative = 0;   /* do nothing:  \"-b\" is default */\n+                } else {\n #ifdef VMS\n-                        if (uO.aflag == 0)\n-                           ++uO.bflag;\n+                    if (uO.aflag == 0)\n+                       ++uO.bflag;\n #endif\n #ifdef TANDEM\n-                        ++uO.bflag;\n+                    ++uO.bflag;\n #endif\n-                        uO.aflag = 0;\n-                    }\n-                    break;\n+                    uO.aflag = 0;\n+                }\n+                break;\n #ifdef UNIXBACKUP\n-                case ('B'): /* -B: back up existing files */\n-                    if (negative)\n-                        uO.B_flag = FALSE, negative = 0;\n-                    else\n-                        uO.B_flag = TRUE;\n-                    break;\n-#endif\n-                case ('c'):\n-                    if (negative) {\n-                        uO.cflag = FALSE, negative = 0;\n+            case ('B'): /* -B: back up existing files */\n+                if (negative)\n+                    uO.B_flag = FALSE, negative = 0;\n+                else\n+                    uO.B_flag = TRUE;\n+                break;\n+#endif\n+            case ('c'):\n+                if (negative) {\n+                    uO.cflag = FALSE, negative = 0;\n #ifdef NATIVE\n-                        uO.aflag = 0;\n+                    uO.aflag = 0;\n #endif\n-                    } else {\n-                        uO.cflag = TRUE;\n+                } else {\n+                    uO.cflag = TRUE;\n #ifdef NATIVE\n-                        uO.aflag = 2;   /* so you can read it on the screen */\n+                    uO.aflag = 2;   /* so you can read it on the screen */\n #endif\n #ifdef DLL\n-                        if (G.redirect_text)\n-                            G.redirect_data = 2;\n+                    if (G.redirect_text)\n+                        G.redirect_data = 2;\n #endif\n-                    }\n-                    break;\n+                }\n+                break;\n #ifndef CMS_MVS\n-                case ('C'):    /* -C:  match filenames case-insensitively */\n-                    if (negative)\n-                        uO.C_flag = FALSE, negative = 0;\n-                    else\n-                        uO.C_flag = TRUE;\n-                    break;\n+            case ('C'):    /* -C:  match filenames case-insensitively */\n+                if (negative)\n+                    uO.C_flag = FALSE, negative = 0;\n+                else\n+                    uO.C_flag = TRUE;\n+                break;\n #endif /* !CMS_MVS */\n #if (!defined(SFX) || defined(SFX_EXDIR))\n-                case ('d'):\n-                    if (negative) {   /* negative not allowed with -d exdir */\n+            case ('d'):\n+                if (negative) {   /* negative not allowed with -d exdir */\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(MustGiveExdir)));\n+                    return(PK_PARAM);  /* don't extract here by accident */\n+                }\n+                if (uO.exdir != (char *)NULL) {\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(OnlyOneExdir)));\n+                    return(PK_PARAM);    /* GRR:  stupid restriction? */\n+                } else {\n+                    /* first check for \"-dexdir\", then for \"-d exdir\" */\n+                    uO.exdir = value;\n+                    if (uO.exdir == NULL || *uO.exdir == '\\0') {\n                         Info(slide, 0x401, ((char *)slide,\n                           LoadFarString(MustGiveExdir)));\n-                        return(PK_PARAM);  /* don't extract here by accident */\n-                    }\n-                    if (uO.exdir != (char *)NULL) {\n-                        Info(slide, 0x401, ((char *)slide,\n-                          LoadFarString(OnlyOneExdir)));\n-                        return(PK_PARAM);    /* GRR:  stupid restriction? */\n-                    } else {\n-                        /* first check for \"-dexdir\", then for \"-d exdir\" */\n-                        uO.exdir = s;\n-                        if (*uO.exdir == '\\0') {\n-                            if (argc > 1) {\n-                                --argc;\n-                                uO.exdir = *++argv;\n-                                if (*uO.exdir == '-') {\n-                                    Info(slide, 0x401, ((char *)slide,\n-                                      LoadFarString(MustGiveExdir)));\n-                                    return(PK_PARAM);\n-                                }\n-                                /* else uO.exdir points at extraction dir */\n-                            } else {\n-                                Info(slide, 0x401, ((char *)slide,\n-                                  LoadFarString(MustGiveExdir)));\n-                                return(PK_PARAM);\n-                            }\n-                        }\n-                        /* uO.exdir now points at extraction dir (-dexdir or\n-                         *  -d exdir); point s at end of exdir to avoid mis-\n-                         *  interpretation of exdir characters as more options\n-                         */\n-                        if (*s != 0)\n-                            while (*++s != 0)\n-                                ;\n+                        return(PK_PARAM);\n                     }\n-                    break;\n+                    /* else uO.exdir points at extraction dir */\n+                }\n+                break;\n #endif /* !SFX || SFX_EXDIR */\n #if (!defined(NO_TIMESTAMPS))\n-                case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */\n-                    if (negative) {\n-                        uO.D_flag = MAX(uO.D_flag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        uO.D_flag++;\n-                    break;\n+            case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */\n+                if (negative) {\n+                    uO.D_flag = MAX(uO.D_flag-negative,0);\n+                    negative = 0;\n+                } else\n+                    uO.D_flag++;\n+                break;\n #endif /* (!NO_TIMESTAMPS) */\n-                case ('e'):    /* just ignore -e, -x options (extract) */\n-                    break;\n+            case ('e'):    /* just ignore -e, -x options (extract) */\n+                break;\n #ifdef MACOS\n-                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */\n-                    if( negative ) {\n-                        uO.E_flag = FALSE, negative = 0;\n-                    } else {\n-                        uO.E_flag = TRUE;\n-                    }\n-                    break;\n+            case ('E'): /* -E [MacOS] display Mac e.f. when restoring */\n+                if( negative ) {\n+                    uO.E_flag = FALSE, negative = 0;\n+                } else {\n+                    uO.E_flag = TRUE;\n+                }\n+                break;\n #endif /* MACOS */\n-                case ('f'):    /* \"freshen\" (extract only newer files) */\n-                    if (negative)\n-                        uO.fflag = uO.uflag = FALSE, negative = 0;\n-                    else\n-                        uO.fflag = uO.uflag = TRUE;\n-                    break;\n+            case ('f'):    /* \"freshen\" (extract only newer files) */\n+                if (negative)\n+                    uO.fflag = uO.uflag = FALSE, negative = 0;\n+                else\n+                    uO.fflag = uO.uflag = TRUE;\n+                break;\n #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n-                case ('F'):    /* Acorn filetype & NFS extension handling */\n-                    if (negative)\n-                        uO.acorn_nfs_ext = FALSE, negative = 0;\n-                    else\n-                        uO.acorn_nfs_ext = TRUE;\n-                    break;\n+            case ('F'):    /* Acorn filetype & NFS extension handling */\n+                if (negative)\n+                    uO.acorn_nfs_ext = FALSE, negative = 0;\n+                else\n+                    uO.acorn_nfs_ext = TRUE;\n+                break;\n #endif /* RISCOS || ACORN_FTYPE_NFS */\n-                case ('h'):    /* just print help message and quit */\n-                    *pargc = -1;\n-                    return USAGE(PK_OK);\n+            case ('h'):    /* just print help message and quit */\n+                *pargc = -1;\n+                return USAGE(PK_OK);\n #ifdef MACOS\n-                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */\n-                    if( negative ) {\n-                        uO.i_flag = FALSE, negative = 0;\n-                    } else {\n-                        uO.i_flag = TRUE;\n-                    }\n-                    break;\n+            case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */\n+                if( negative ) {\n+                    uO.i_flag = FALSE, negative = 0;\n+                } else {\n+                    uO.i_flag = TRUE;\n+                }\n+                break;\n #endif  /* MACOS */\n-                case ('j'):    /* junk pathnames/directory structure */\n-                    if (negative)\n-                        uO.jflag = FALSE, negative = 0;\n-                    else\n-                        uO.jflag = TRUE;\n-                    break;\n+            case ('j'):    /* junk pathnames/directory structure */\n+                if (negative)\n+                    uO.jflag = FALSE, negative = 0;\n+                else\n+                    uO.jflag = TRUE;\n+                break;\n #if (defined(ATH_BEO) || defined(MACOS))\n-                case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */\n-                    if( negative ) {\n-                        uO.J_flag = FALSE, negative = 0;\n-                    } else {\n-                        uO.J_flag = TRUE;\n-                    }\n-                    break;\n+            case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */\n+                if( negative ) {\n+                    uO.J_flag = FALSE, negative = 0;\n+                } else {\n+                    uO.J_flag = TRUE;\n+                }\n+                break;\n #endif /* ATH_BEO || MACOS */\n #ifdef ATH_BEO_UNX\n-                case ('K'):\n-                    if (negative) {\n-                        uO.K_flag = FALSE, negative = 0;\n-                    } else {\n-                        uO.K_flag = TRUE;\n-                    }\n-                    break;\n+            case ('K'):\n+                if (negative) {\n+                    uO.K_flag = FALSE, negative = 0;\n+                } else {\n+                    uO.K_flag = TRUE;\n+                }\n+                break;\n #endif /* ATH_BEO_UNX */\n #ifndef SFX\n-                case ('l'):\n-                    if (negative) {\n-                        uO.vflag = MAX(uO.vflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.vflag;\n-                    break;\n+            case ('l'):\n+                if (negative) {\n+                    uO.vflag = MAX(uO.vflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.vflag;\n+                break;\n #endif /* !SFX */\n #ifndef CMS_MVS\n-                case ('L'):    /* convert (some) filenames to lowercase */\n-                    if (negative) {\n-                        uO.L_flag = MAX(uO.L_flag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.L_flag;\n-                    break;\n+            case ('L'):    /* convert (some) filenames to lowercase */\n+                if (negative) {\n+                    uO.L_flag = MAX(uO.L_flag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.L_flag;\n+                break;\n #endif /* !CMS_MVS */\n #ifdef MORE\n #ifdef CMS_MVS\n-                case ('m'):\n+            case ('m'):\n #endif\n-                case ('M'):    /* send all screen output through \"more\" fn. */\n+            case ('M'):    /* send all screen output through \"more\" fn. */\n /* GRR:  eventually check for numerical argument => height */\n-                    if (negative)\n-                        G.M_flag = FALSE, negative = 0;\n-                    else\n-                        G.M_flag = TRUE;\n-                    break;\n+                if (negative)\n+                    G.M_flag = FALSE, negative = 0;\n+                else\n+                    G.M_flag = TRUE;\n+                break;\n #endif /* MORE */\n-                case ('n'):    /* don't overwrite any files */\n-                    if (negative)\n-                        uO.overwrite_none = FALSE, negative = 0;\n-                    else\n-                        uO.overwrite_none = TRUE;\n-                    break;\n+            case ('n'):    /* don't overwrite any files */\n+                if (negative)\n+                    uO.overwrite_none = FALSE, negative = 0;\n+                else\n+                    uO.overwrite_none = TRUE;\n+                break;\n #ifdef AMIGA\n-                case ('N'):    /* restore comments as filenotes */\n-                    if (negative)\n-                        uO.N_flag = FALSE, negative = 0;\n-                    else\n-                        uO.N_flag = TRUE;\n-                    break;\n+            case ('N'):    /* restore comments as filenotes */\n+                if (negative)\n+                    uO.N_flag = FALSE, negative = 0;\n+                else\n+                    uO.N_flag = TRUE;\n+                break;\n #endif /* AMIGA */\n-                case ('o'):    /* OK to overwrite files without prompting */\n-                    if (negative) {\n-                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.overwrite_all;\n-                    break;\n-                case ('p'):    /* pipes:  extract to stdout, no messages */\n-                    if (negative) {\n-                        uO.cflag = FALSE;\n-                        uO.qflag = MAX(uO.qflag-999,0);\n-                        negative = 0;\n-                    } else {\n-                        uO.cflag = TRUE;\n-                        uO.qflag += 999;\n-                    }\n-                    break;\n+            case ('o'):    /* OK to overwrite files without prompting */\n+                if (negative) {\n+                    uO.overwrite_all = MAX(uO.overwrite_all-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.overwrite_all;\n+                break;\n+            case ('p'):    /* pipes:  extract to stdout, no messages */\n+                if (negative) {\n+                    uO.cflag = FALSE;\n+                    uO.qflag = MAX(uO.qflag-999,0);\n+                    negative = 0;\n+                } else {\n+                    uO.cflag = TRUE;\n+                    uO.qflag += 999;\n+                }\n+                break;\n #if CRYPT\n-                /* GRR:  yes, this is highly insecure, but dozens of people\n-                 * have pestered us for this, so here we go... */\n-                case ('P'):\n-                    if (negative) {   /* negative not allowed with -P passwd */\n-                        Info(slide, 0x401, ((char *)slide,\n-                          LoadFarString(MustGivePasswd)));\n-                        return(PK_PARAM);  /* don't extract here by accident */\n-                    }\n-                    if (uO.pwdarg != (char *)NULL) {\n+            /* GRR:  yes, this is highly insecure, but dozens of people\n+             * have pestered us for this, so here we go... */\n+            case ('P'):\n+                if (negative) {   /* negative not allowed with -P passwd */\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(MustGivePasswd)));\n+                    return(PK_PARAM);  /* don't extract here by accident */\n+                }\n+                if (uO.pwdarg != (char *)NULL) {\n /*\n-                        GRR:  eventually support multiple passwords?\n+                    GRR:  eventually support multiple passwords?\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(OnlyOnePasswd)));\n+                    return(PK_PARAM);\n+*/\n+                } else {\n+                    /* first check for \"-Ppasswd\", then for \"-P passwd\" */\n+                    uO.pwdarg = value;\n+                    if (uO.pwdarg == NULL || *uO.pwdarg == '\\0') {\n                         Info(slide, 0x401, ((char *)slide,\n-                          LoadFarString(OnlyOnePasswd)));\n+                          LoadFarString(MustGivePasswd)));\n                         return(PK_PARAM);\n- */\n-                    } else {\n-                        /* first check for \"-Ppasswd\", then for \"-P passwd\" */\n-                        uO.pwdarg = s;\n-                        if (*uO.pwdarg == '\\0') {\n-                            if (argc > 1) {\n-                                --argc;\n-                                uO.pwdarg = *++argv;\n-                                if (*uO.pwdarg == '-') {\n-                                    Info(slide, 0x401, ((char *)slide,\n-                                      LoadFarString(MustGivePasswd)));\n-                                    return(PK_PARAM);\n-                                }\n-                                /* else pwdarg points at decryption password */\n-                            } else {\n-                                Info(slide, 0x401, ((char *)slide,\n-                                  LoadFarString(MustGivePasswd)));\n-                                return(PK_PARAM);\n-                            }\n-                        }\n-                        /* pwdarg now points at decryption password (-Ppasswd or\n-                         *  -P passwd); point s at end of passwd to avoid mis-\n-                         *  interpretation of passwd characters as more options\n-                         */\n-                        if (*s != 0)\n-                            while (*++s != 0)\n-                                ;\n+                        /* else pwdarg points at decryption password */\n                     }\n-                    break;\n+                }\n+                break;\n #endif /* CRYPT */\n-                case ('q'):    /* quiet:  fewer comments/messages */\n-                    if (negative) {\n-                        uO.qflag = MAX(uO.qflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.qflag;\n-                    break;\n+            case ('q'):    /* quiet:  fewer comments/messages */\n+                if (negative) {\n+                    uO.qflag = MAX(uO.qflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.qflag;\n+                break;\n #ifdef QDOS\n-                case ('Q'):   /* QDOS flags */\n-                    qlflag ^= strtol(s, &s, 10);\n-                    break;    /* we XOR this as we can config qlflags */\n+            case ('Q'):   /* QDOS flags */\n+                qlflag ^= strtol(value, &value, 10);\n+                break;    /* we XOR this as we can config qlflags */\n #endif\n #ifdef TANDEM\n-                case ('r'):    /* remove file extensions */\n-                    if (negative)\n-                        uO.rflag = FALSE, negative = 0;\n-                    else\n-                        uO.rflag = TRUE;\n-                    break;\n+            case ('r'):    /* remove file extensions */\n+                if (negative)\n+                    uO.rflag = FALSE, negative = 0;\n+                else\n+                    uO.rflag = TRUE;\n+                break;\n #endif /* TANDEM */\n #ifdef DOS_FLX_NLM_OS2_W32\n-                case ('s'):    /* spaces in filenames:  allow by default */\n-                    if (negative)\n-                        uO.sflag = FALSE, negative = 0;\n-                    else\n-                        uO.sflag = TRUE;\n-                    break;\n+            case ('s'):    /* spaces in filenames:  allow by default */\n+                if (negative)\n+                    uO.sflag = FALSE, negative = 0;\n+                else\n+                    uO.sflag = TRUE;\n+                break;\n #endif /* DOS_FLX_NLM_OS2_W32 */\n #ifdef VMS\n-                /* VMS:  extract \"text\" files in Stream_LF format (-a[a]) */\n-                case ('S'):\n-                    if (negative)\n-                        uO.S_flag = FALSE, negative = 0;\n-                    else\n-                        uO.S_flag = TRUE;\n-                    break;\n+            /* VMS:  extract \"text\" files in Stream_LF format (-a[a]) */\n+            case ('S'):\n+                if (negative)\n+                    uO.S_flag = FALSE, negative = 0;\n+                else\n+                    uO.S_flag = TRUE;\n+                break;\n #endif /* VMS */\n-                case ('t'):\n-                    if (negative)\n-                        uO.tflag = FALSE, negative = 0;\n-                    else\n-                        uO.tflag = TRUE;\n-                    break;\n+            case ('t'):\n+                if (negative)\n+                    uO.tflag = FALSE, negative = 0;\n+                else\n+                    uO.tflag = TRUE;\n+                break;\n #ifdef TIMESTAMP\n-                case ('T'):\n-                    if (negative)\n-                        uO.T_flag = FALSE, negative = 0;\n-                    else\n-                        uO.T_flag = TRUE;\n-                    break;\n-#endif\n-                case ('u'):    /* update (extract only new and newer files) */\n-                    if (negative)\n-                        uO.uflag = FALSE, negative = 0;\n-                    else\n-                        uO.uflag = TRUE;\n-                    break;\n+            case ('T'):\n+                if (negative)\n+                    uO.T_flag = FALSE, negative = 0;\n+                else\n+                    uO.T_flag = TRUE;\n+                break;\n+#endif\n+            case ('u'):    /* update (extract only new and newer files) */\n+                if (negative)\n+                    uO.uflag = FALSE, negative = 0;\n+                else\n+                    uO.uflag = TRUE;\n+                break;\n #ifdef UNICODE_SUPPORT\n-                case ('U'):    /* escape UTF-8, or disable UTF-8 support */\n-                    if (negative) {\n-                        uO.U_flag = MAX(uO.U_flag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        uO.U_flag++;\n-                    break;\n+            case ('U'):    /* escape UTF-8, or disable UTF-8 support */\n+                if (negative)\n+                    uO.U_flag = MAX(uO.U_flag - 1, 0);\n+                else\n+                    uO.U_flag++;\n+                break;\n #else /* !UNICODE_SUPPORT */\n #ifndef CMS_MVS\n-                case ('U'):    /* obsolete; to be removed in version 6.0 */\n-                    if (negative)\n-                        uO.L_flag = TRUE, negative = 0;\n-                    else\n-                        uO.L_flag = FALSE;\n-                    break;\n+            case ('U'):    /* obsolete; to be removed in version 6.0 */\n+                if (negative)\n+                    uO.L_flag = TRUE, negative = 0;\n+                else\n+                    uO.L_flag = FALSE;\n+                break;\n #endif /* !CMS_MVS */\n #endif /* ?UNICODE_SUPPORT */\n #ifndef SFX\n-                case ('v'):    /* verbose */\n-                    if (negative) {\n-                        uO.vflag = MAX(uO.vflag-negative,0);\n-                        negative = 0;\n-                    } else if (uO.vflag)\n-                        ++uO.vflag;\n-                    else\n-                        uO.vflag = 2;\n-                    break;\n+            case ('v'):    /* verbose */\n+                if (negative) {\n+                    uO.vflag = MAX(uO.vflag-negative,0);\n+                    negative = 0;\n+                } else if (uO.vflag)\n+                    ++uO.vflag;\n+                else\n+                    uO.vflag = 2;\n+                break;\n #endif /* !SFX */\n #ifndef CMS_MVS\n-                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */\n-                    if (negative)\n-                        uO.V_flag = FALSE, negative = 0;\n-                    else\n-                        uO.V_flag = TRUE;\n-                    break;\n+            case ('V'):    /* Version (retain VMS/DEC-20 file versions) */\n+                if (negative)\n+                    uO.V_flag = FALSE, negative = 0;\n+                else\n+                    uO.V_flag = TRUE;\n+                break;\n #endif /* !CMS_MVS */\n #ifdef WILD_STOP_AT_DIR\n-                case ('W'):    /* Wildcard interpretation (stop at '/'?) */\n-                    if (negative)\n-                        uO.W_flag = FALSE, negative = 0;\n-                    else\n-                        uO.W_flag = TRUE;\n-                    break;\n+            case ('W'):    /* Wildcard interpretation (stop at '/'?) */\n+                if (negative)\n+                    uO.W_flag = FALSE, negative = 0;\n+                else\n+                    uO.W_flag = TRUE;\n+                break;\n #endif /* WILD_STOP_AT_DIR */\n-                case ('x'):    /* extract:  default */\n-#ifdef SFX\n-                    /* when 'x' is the only option in this argument, and the\n-                     * next arg is not an option, assume this initiates an\n-                     * exclusion list (-x xlist):  terminate option-scanning\n-                     * and leave uz_opts with argv still pointing to \"-x\";\n-                     * the xlist is processed later\n-                     */\n-                    if (s - argv[0] == 2 && *s == '\\0' &&\n-                        argc > 1 && argv[1][0] != '-') {\n-                        /* break out of nested loops without \"++argv;--argc\" */\n-                        goto opts_done;\n+            case ('x'):    /* extract:  default */\n+                /* add -x file to linked list */\n+\n+                if (in_xfiles_count == 0) {\n+                    /* first entry */\n+                    if ((in_xfiles = (struct file_list *)\n+                                     malloc(sizeof(struct file_list))\n+                        ) == NULL) {\n+                        Info(slide, 0x401, ((char *)slide,\n+                          LoadFarString(NoMemArgsList)));\n+                        return PK_MEM;\n+                    }\n+                    in_xfiles->name = value;\n+                    in_xfiles->next = NULL;\n+                    next_in_xfiles = in_xfiles;\n+                } else {\n+                    /* add next entry */\n+                    if ((next_file = (struct file_list *)\n+                                     malloc(sizeof(struct file_list))\n+                        ) == NULL) {\n+                        Info(slide, 0x401, ((char *)slide,\n+                          LoadFarString(NoMemArgsList)));\n+                        return PK_MEM;\n                     }\n+                    next_in_xfiles->next = next_file;\n+                    next_file->name = value;\n+                    next_file->next = NULL;\n+                    next_in_xfiles = next_file;\n+                }\n+                in_xfiles_count++;\n+\n+#if 0\n+#ifdef SFX\n+                /* now get -x list one entry at a time */\n+\n+\n+\n+                /* when 'x' is the only option in this argument, and the\n+                 * next arg is not an option, assume this initiates an\n+                 * exclusion list (-x xlist):  terminate option-scanning\n+                 * and leave uz_opts with argv still pointing to \"-x\";\n+                 * the xlist is processed later\n+                 */\n+                if (s - argv[0] == 2 && *s == '\\0' &&\n+                    argc > 1 && argv[1][0] != '-') {\n+                    /* break out of nested loops without \"++argv;--argc\" */\n+                    goto opts_done;\n+                }\n #endif /* SFX */\n-                    break;\n+#endif\n+                break;\n #if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))\n-                case ('X'):   /* restore owner/protection info (need privs?) */\n-                    if (negative) {\n-                        uO.X_flag = MAX(uO.X_flag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.X_flag;\n-                    break;\n+            case ('X'):   /* restore owner/protection info (need privs?) */\n+                if (negative) {\n+                    uO.X_flag = MAX(uO.X_flag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.X_flag;\n+                break;\n #endif /* RESTORE_UIDGID || RESTORE_ACL */\n #ifdef VMS\n-                case ('Y'):    /* Treat \".nnn\" as \";nnn\" version. */\n-                    if (negative)\n-                        uO.Y_flag = FALSE, negative = 0;\n-                    else\n-                        uO.Y_flag = TRUE;\n-                    break;\n+            case ('Y'):    /* Treat \".nnn\" as \";nnn\" version. */\n+                if (negative)\n+                    uO.Y_flag = FALSE, negative = 0;\n+                else\n+                    uO.Y_flag = TRUE;\n+                break;\n #endif /* VMS */\n-                case ('z'):    /* display only the archive comment */\n-                    if (negative) {\n-                        uO.zflag = MAX(uO.zflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.zflag;\n-                    break;\n+            case ('z'):    /* display only the archive comment */\n+                if (negative) {\n+                    uO.zflag = MAX(uO.zflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.zflag;\n+                break;\n #ifndef SFX\n-                case ('Z'):    /* should have been first option (ZipInfo) */\n-                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));\n-                    error = TRUE;\n-                    break;\n+            case ('Z'):    /* should have been first option (ZipInfo) */\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));\n+                error = TRUE;\n+                break;\n #endif /* !SFX */\n #ifdef VMS\n-                case ('2'):    /* Force ODS2-compliant names. */\n-                    if (negative)\n-                        uO.ods2_flag = FALSE, negative = 0;\n-                    else\n-                        uO.ods2_flag = TRUE;\n-                    break;\n+            case ('2'):    /* Force ODS2-compliant names. */\n+                if (negative)\n+                    uO.ods2_flag = FALSE, negative = 0;\n+                else\n+                    uO.ods2_flag = TRUE;\n+                break;\n #endif /* VMS */\n #ifdef DOS_H68_OS2_W32\n-                case ('$'):\n-                    if (negative) {\n-                        uO.volflag = MAX(uO.volflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.volflag;\n-                    break;\n+            case ('$'):\n+                if (negative) {\n+                    uO.volflag = MAX(uO.volflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.volflag;\n+                break;\n #endif /* DOS_H68_OS2_W32 */\n #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))\n-                case (':'):    /* allow \"parent dir\" path components */\n-                    if (negative) {\n-                        uO.ddotflag = MAX(uO.ddotflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.ddotflag;\n-                    break;\n+            case (':'):    /* allow \"parent dir\" path components */\n+                if (negative) {\n+                    uO.ddotflag = MAX(uO.ddotflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.ddotflag;\n+                break;\n #endif /* !RISCOS && !CMS_MVS && !TANDEM */\n #ifdef UNIX\n-                case ('^'):    /* allow control chars in filenames */\n-                    if (negative) {\n-                        uO.cflxflag = MAX(uO.cflxflag-negative,0);\n-                        negative = 0;\n-                    } else\n-                        ++uO.cflxflag;\n-                    break;\n+            case ('^'):    /* allow control chars in filenames */\n+                if (negative) {\n+                    uO.cflxflag = MAX(uO.cflxflag-negative,0);\n+                    negative = 0;\n+                } else\n+                    ++uO.cflxflag;\n+                break;\n #endif /* UNIX */\n-                default:\n-                    error = TRUE;\n-                    break;\n-\n-            } /* end switch */\n-        } /* end while (not end of argument string) */\n-    } /* end while (not done with switches) */\n+            case o_NON_OPTION_ARG:\n+                /* not an option */\n+                /* no more options as permuting */\n+\n+\n+                if (G.wildzipfn == NULL) {\n+                    /* first non-option argument is zip file */\n+                    G.wildzipfn = value;\n+\n+                } else {\n+                    /* add include file to list */\n+                    if (in_files_count == 0) {\n+                        /* first entry */\n+                        if ((next_file = (struct file_list *)\n+                                         malloc(sizeof(struct file_list))\n+                            ) == NULL) {\n+                            Info(slide, 0x401, ((char *)slide,\n+                              LoadFarString(NoMemArgsList)));\n+                            return PK_MEM;\n+                        }\n+                        next_file->name = value;\n+                        next_file->next = NULL;\n+                        in_files = next_file;\n+                        next_in_files = next_file;\n+                    } else {\n+                        /* add next entry */\n+                        if ((next_file = (struct file_list *)\n+                                         malloc(sizeof(struct file_list))\n+                            ) == NULL) {\n+                            Info(slide, 0x401, ((char *)slide,\n+                              LoadFarString(NoMemArgsList)));\n+                            return PK_MEM;\n+                        }\n+                        next_in_files->next = next_file;\n+                        next_file->name = value;\n+                        next_file->next = NULL;\n+                        next_in_files = next_file;\n+                    }\n+                    in_files_count++;\n+                }\n+                break;\n+            default:\n+                error = TRUE;\n+                break;\n+\n+        } /* end switch */\n+    } /* get_option() */\n+\n+\n+    /* convert files and xfiles lists to arrays */\n+\n+    /* convert files list to array */\n+    if (in_files_count) {\n+      if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))\n+          ) == NULL) {\n+          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));\n+          return PK_MEM;\n+      }\n+      file_count = 0;\n+      for (next_file = in_files; next_file;) {\n+          G.pfnames[file_count] = next_file->name;\n+          in_files = next_file;\n+          next_file = next_file->next;\n+          free(in_files);\n+          file_count++;\n+      }\n+      G.pfnames[file_count] = NULL;\n+      G.filespecs = in_files_count;\n+    }\n+\n+    /* convert xfiles list to array */\n+    if (in_xfiles_count) {\n+      if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))\n+          ) == NULL) {\n+          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));\n+          return PK_MEM;\n+      }\n+      file_count = 0;\n+      for (next_file = in_xfiles; next_file;) {\n+          G.pxnames[file_count] = next_file->name;\n+          in_xfiles = next_file;\n+          next_file = next_file->next;\n+          free(in_xfiles);\n+          file_count++;\n+      }\n+      G.pxnames[file_count] = NULL;\n+      G.xfilespecs = in_xfiles_count;\n+    }\n+\n+    if (in_files_count || in_xfiles_count) {\n+        G.process_all_files = FALSE;\n+    } else {\n+        G.process_all_files = TRUE;      /* for speed */\n+    }\n+\n+\n+    /* it's possible the arg count could have been changed by get_option() */\n+    argc = arg_count(args);\n+\n+\n \n /*---------------------------------------------------------------------------\n@@ -1774,7 +2240,77 @@\n   ---------------------------------------------------------------------------*/\n \n+    if ((uO.cflag && (uO.tflag || uO.uflag)) ||\n+        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))\n+    {\n+        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));\n+        error = TRUE;\n+    }\n+    if (uO.aflag > 2)\n+        uO.aflag = 2;\n+#ifdef VMS\n+    if (uO.bflag > 2)\n+        uO.bflag = 2;\n+    /* Clear -s flag when converting text files. */\n+    if (uO.aflag <= 0)\n+        uO.S_flag = 0;\n+#endif /* VMS */\n+    if (uO.overwrite_all && uO.overwrite_none) {\n+        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));\n+        uO.overwrite_all = FALSE;\n+    }\n+#ifdef MORE\n+    if (G.M_flag && !isatty(1))  /* stdout redirected: \"more\" func. useless */\n+        G.M_flag = 0;\n+#endif\n+\n+#ifdef SFX\n+    if (error)\n+#else\n+    if ((G.wildzipfn == NULL) || error)\n+#endif\n+    {\n+        /* tell caller to exit */\n+        if (argc <= 2)\n+            argc = -1;\n+\n+        *pargc = argc;\n+        *pargv = args;\n+#ifndef SFX\n+        if (uO.vflag >= 2 && argc == -1) {              /* \"unzip -v\" */\n+            show_version_info(__G);\n+            return PK_OK;\n+        }\n+        if (!G.noargs && !error)\n+            error = TRUE;       /* had options (not -h or -v) but no zipfile */\n+#endif /* !SFX */\n+        return USAGE(error);\n+    }\n+\n #ifdef SFX\n-opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */\n+    /* print our banner unless we're being fairly quiet */\n+    if (uO.qflag < 2)\n+        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),\n+          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n+          LoadFarStringSmall(VersionDate)));\n+#ifdef BETA\n+    /* always print the beta warning:  no unauthorized distribution!! */\n+    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), \"\\n\",\n+      \"SFX\"));\n+#endif\n+#endif /* SFX */\n+\n+    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag\n+#ifdef TIMESTAMP\n+                                                     || uO.T_flag\n #endif\n+                                                                 )\n+        G.extract_flag = FALSE;\n+    else\n+        G.extract_flag = TRUE;\n+\n+#if 0\n+# ifdef SFX\n+opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */\n+# endif\n \n     if ((uO.cflag && (uO.tflag || uO.uflag)) ||\n@@ -1786,5 +2322,5 @@\n     if (uO.aflag > 2)\n         uO.aflag = 2;\n-#ifdef VMS\n+# ifdef VMS\n     if (uO.bflag > 2)\n         uO.bflag = 2;\n@@ -1792,23 +2328,23 @@\n     if (uO.aflag <= 0)\n         uO.S_flag = 0;\n-#endif /* VMS */\n+# endif /* VMS */\n     if (uO.overwrite_all && uO.overwrite_none) {\n         Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));\n         uO.overwrite_all = FALSE;\n     }\n-#ifdef MORE\n+# ifdef MORE\n     if (G.M_flag && !isatty(1))  /* stdout redirected: \"more\" func. useless */\n         G.M_flag = 0;\n-#endif\n+# endif\n \n-#ifdef SFX\n+# ifdef SFX\n     if (error)\n-#else\n+# else\n     if ((argc-- == 0) || error)\n-#endif\n+# endif\n     {\n         *pargc = argc;\n-        *pargv = argv;\n-#ifndef SFX\n+        *pargv = args;\n+# ifndef SFX\n         if (uO.vflag >= 2 && argc == -1) {              /* \"unzip -v\" */\n             show_version_info(__G);\n@@ -1817,9 +2353,9 @@\n         if (!G.noargs && !error)\n             error = TRUE;       /* had options (not -h or -v) but no zipfile */\n-#endif /* !SFX */\n+# endif /* !SFX */\n         return USAGE(error);\n     }\n \n-#ifdef SFX\n+# ifdef SFX\n     /* print our banner unless we're being fairly quiet */\n     if (uO.qflag < 2)\n@@ -1827,22 +2363,23 @@\n           UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n           LoadFarStringSmall(VersionDate)));\n-#ifdef BETA\n+# ifdef BETA\n     /* always print the beta warning:  no unauthorized distribution!! */\n     Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), \"\\n\",\n       \"SFX\"));\n-#endif\n-#endif /* SFX */\n+# endif\n+# endif /* SFX */\n \n     if (uO.cflag || uO.tflag || uO.vflag || uO.zflag\n-#ifdef TIMESTAMP\n+# ifdef TIMESTAMP\n                                                      || uO.T_flag\n-#endif\n+# endif\n                                                                  )\n         G.extract_flag = FALSE;\n     else\n         G.extract_flag = TRUE;\n+#endif\n \n     *pargc = argc;\n-    *pargv = argv;\n+    *pargv = args;\n     return PK_OK;\n \n@@ -2314,2 +2851,1366 @@\n #endif /* !SFX */\n #endif /* !WINDLL */\n+\n+\n+\n+\n+\n+\n+/*---------------------------------------------------------------\n+ *  Long option support\n+ *  8/23/2003\n+ *  Updated 3/1/2008 to support UnZip\n+ *\n+ *  Defines function get_option() to get and process the command\n+ *  line options and arguments from argv[].  The caller calls\n+ *  get_option() in a loop to get either one option and possible\n+ *  value or a non-option argument each loop.\n+ *\n+ *  This version has been modified to work with UnZip and ZipInfo.\n+ *  the major changes are removing the error returns, instead\n+ *  passing back error codes for errors, and supporting separate\n+ *  groups of options for UnZip and ZipInfo and selecting the option\n+ *  group by an argument.\n+ *\n+ *  This version does not include argument file support and can\n+ *  work directly on argv.  The argument file code complicates things and\n+ *  it seemed best to leave it out for now.  If argument file support\n+ *  (reading in command line arguments stored in a file and inserting into\n+ *  command line where @filename is found) is added later the arguments\n+ *  can change and a freeable copy of argv will be needed and can be\n+ *  created using copy_args in the left out code.\n+ *\n+ *  Supports short and long options as defined in the array options[]\n+ *  in zip.c, multiple short options in an argument (like -jlv), long\n+ *  option abbreviation (like --te for --temp-file if --te unique),\n+ *  short and long option values (like -b filename or --temp-file filename\n+ *  or --temp-file=filename), optional and required values, option negation\n+ *  by trailing - (like -S- to not include hidden and system files in MSDOS),\n+ *  value lists (like -x a b c), argument permuting (returning all options\n+ *  and values before any non-option arguments), and argument files (where\n+ *  any non-option non-value argument in form @path gets substituted with\n+ *  the white space separated arguments in the text file at path).  In this\n+ *  version argument file support has been removed to simplify development\n+ *  but may be added later.\n+ *\n+ *  E. Gordon\n+ */\n+\n+\n+/* message output - char casts are needed to handle constants */\n+#define oWARN(message) Info(slide, 0x401, ((char *)slide, (char *)message))\n+\n+\n+\n+/* Although the below provides some support for multibyte characters\n+   the proper thing to do may be to use wide characters and support\n+   Unicode.  May get to it soon.  Wide support would likely require\n+   the ability to convert the command line to wide strings, which most\n+   modern OS should support now.  EG\n+ */\n+\n+/* For now stay with multi-byte characters.  May support wide characters\n+   in Zip 3.1 and UnZip 6.1.\n+ */\n+\n+/* multibyte character set support\n+   Multibyte characters use typically two or more sequential bytes\n+   to represent additional characters than can fit in a single byte\n+   character set.  The code used here is based on the ANSI mblen function. */\n+#define MB_CLEN(ptr) CLEN(ptr)\n+#define MB_NEXTCHAR(ptr) PREINCSTR(ptr)\n+\n+\n+/* constants */\n+\n+/* function get_args_from_arg_file() can return this in depth parameter */\n+#define ARG_FILE_ERR -1\n+\n+/* internal settings for optchar */\n+#define SKIP_VALUE_ARG   -1\n+#define THIS_ARG_DONE    -2\n+#define START_VALUE_LIST -3\n+#define IN_VALUE_LIST    -4\n+#define NON_OPTION_ARG   -5\n+#define STOP_VALUE_LIST  -6\n+/* 7/25/04 EG */\n+#define READ_REST_ARGS_VERBATIM -7\n+\n+\n+/* global veriables */\n+\n+int enable_permute = 1;                     /* yes - return options first */\n+/* 7/25/04 EG */\n+int doubledash_ends_options = 1;            /* when -- what follows are not options */\n+\n+/* buffer for error messages (this sizing is a guess but must hold 2 paths) */\n+#define OPTIONERR_BUF_SIZE (80+ 2*FILENAME_MAX)\n+char optionerrbuf[OPTIONERR_BUF_SIZE + 1];\n+\n+/* error messages */\n+static ZCONST char Far op_not_neg_err[] =\n+   \"option %s not negatable\";\n+static ZCONST char Far op_req_val_err[] =\n+   \"option %s requires a value\";\n+static ZCONST char Far op_no_allow_val_err[] =\n+   \"option %s does not allow a value\";\n+static ZCONST char Far sh_op_not_sup_err[] =\n+   \"short option '%c' not supported\";\n+static ZCONST char Far oco_req_val_err[] =\n+   \"option %s requires one character value\";\n+static ZCONST char Far oco_no_mbc_err[] =\n+   \"option %s does not support multibyte values\";\n+static ZCONST char Far num_req_val_err[] =\n+   \"option %s requires number value\";\n+static ZCONST char Far long_op_ambig_err[] =\n+   \"long option '%s' ambiguous\";\n+static ZCONST char Far long_op_not_sup_err[] =\n+   \"long option '%s' not supported\";\n+\n+static ZCONST char Far no_arg_files_err[] = \"argument files not enabled\\n\";\n+\n+\n+/* below removed as only used for processing argument files */\n+\n+/* get_nextarg */\n+/* get_args_from_string */\n+/* get_args_from_arg_file */\n+\n+\n+/* copy error, option name, and option description if any to buf */\n+static int optionerr(options, buf, err, optind, islong)\n+  struct option_struct *options;\n+  char *buf;\n+  ZCONST char Far *err;\n+  int optind;\n+  int islong;\n+{\n+  char optname[50];\n+\n+  if (options[optind].name && options[optind].name[0] != '\\0') {\n+    sprintf(optname, \"'%s' (%s)\",\n+            LoadFarStringSmall2(islong ? options[optind].longopt\n+                                       : options[optind].shortopt),\n+            LoadFarStringSmall(options[optind].name));\n+  } else {\n+    sprintf(optname, \"'%s'\",\n+            LoadFarStringSmall2(islong ? options[optind].longopt\n+                                       : options[optind].shortopt));\n+  }\n+  sprintf(buf, LoadFarStringSmall(err), optname);\n+  return 0;\n+}\n+\n+\n+/* copy_args\n+ *\n+ * Copy arguments in args, allocating storage with malloc.\n+ * Copies until a NULL argument is found or until max_args args\n+ * including args[0] are copied.  Set max_args to 0 to copy\n+ * until NULL.  Always terminates returned args[] with NULL arg.\n+ *\n+ * Any argument in the returned args can be freed with free().  Any\n+ * freed argument should be replaced with either another string\n+ * allocated with malloc or by NULL if last argument so that free_args\n+ * will properly work.\n+ */\n+char **copy_args(args, max_args)\n+  char **args;\n+  int max_args;\n+{\n+  int j;\n+  char **new_args;\n+\n+  if (args == NULL) {\n+    return NULL;\n+  }\n+\n+  /* count args */\n+  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ;\n+\n+  if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) {\n+    oWARN(\"memory - ca\");\n+    return NULL;\n+  }\n+\n+  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) {\n+    if (args[j] == NULL) {\n+      /* null argument is end of args */\n+      new_args[j] = NULL;\n+      break;\n+    }\n+    if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) {\n+      free_args(new_args);\n+      oWARN(\"memory - ca\");\n+      return NULL;\n+    }\n+    strcpy(new_args[j], args[j]);\n+  }\n+  new_args[j] = NULL;\n+\n+  return new_args;\n+}\n+\n+\n+/* count args - count args in argv like array */\n+int arg_count(args)\n+  char **args;\n+{\n+  int i;\n+\n+  if (args == NULL) {\n+    return 0;\n+  }\n+\n+  for (i = 0; args[i]; i++) {\n+  }\n+  return i;\n+}\n+\n+\n+/* free args - free args created with one of these functions */\n+int free_args(args)\n+  char **args;\n+{\n+  int i;\n+\n+  if (args == NULL) {\n+    return 0;\n+  }\n+\n+  for (i = 0; args[i]; i++) {\n+    free(args[i]);\n+  }\n+  free(args);\n+  return i;\n+}\n+\n+\n+/* insert_arg\n+ *\n+ * Insert the argument arg into the array args before argument at_arg.\n+ * If at_arg = -1 then append to end.\n+ * Return the new count of arguments (argc).\n+ *\n+ * If free_args is true, this function frees the old args array\n+ * (but not the component strings).  DO NOT set free_args on original\n+ * argv but only on args allocated with malloc.\n+ */\n+\n+int insert_arg(pargs, arg, at_arg, free_args)\n+   char ***pargs;\n+   ZCONST char *arg;\n+   int at_arg;\n+   int free_args;\n+{\n+   char *newarg = NULL;\n+   char **args;\n+   char **newargs = NULL;\n+   int argnum;\n+   int newargnum;\n+   int argcnt;\n+   int newargcnt;\n+\n+   if (pargs == NULL) {\n+     return 0;\n+   }\n+   args = *pargs;\n+\n+   /* count args */\n+   if (args == NULL) {\n+     argcnt = 0;\n+   } else {\n+     for (argcnt = 0; args[argcnt]; argcnt++) ;\n+   }\n+   if (arg == NULL) {\n+     /* done */\n+     return argcnt;\n+   }\n+   if (at_arg == -1) {\n+     at_arg = argcnt;\n+   }\n+   newargcnt = argcnt + 1;\n+\n+   /* get storage for new args */\n+   if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL)\n+   {\n+     oWARN(\"memory - ia\");\n+     return 0;\n+   }\n+\n+   /* copy argument pointers from args to position at_arg, copy the new arg,\n+      then copy the rest of the args */\n+   argnum = 0;\n+   newargnum = 0;\n+   if (args) {\n+     for (; args[argnum] && argnum < at_arg; argnum++) {\n+       newargs[newargnum++] = args[argnum];\n+     }\n+   }\n+   /* copy new arg */\n+   if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) {\n+     oWARN(\"memory - ia\");\n+     return 0;\n+   }\n+   strcpy(newarg, arg);\n+\n+   newargs[newargnum++] = newarg;\n+   if (args) {\n+     for ( ; args[argnum]; argnum++) {\n+       newargs[newargnum++] = args[argnum];\n+     }\n+   }\n+   newargs[newargnum] = NULL;\n+\n+   /* free old args array but not component strings - this assumes that\n+      args was allocated with malloc as copy_args does.  DO NOT DO THIS\n+      on the original argv.\n+    */\n+   if (free_args)\n+     free(args);\n+\n+   *pargs = newargs;\n+\n+   return newargnum;\n+}\n+\n+/* ------------------------------------- */\n+\n+/* get_shortopt\n+ *\n+ * Get next short option from arg.  The state is stored in argnum, optchar, and\n+ * option_num so no static storage is used.  Returns the option_ID.\n+ *\n+ * parameters:\n+ *    option_group - either UZO for UnZip options or ZIO for ZipInfo options\n+ *    args         - argv array of arguments\n+ *    argnum       - index of current arg in args\n+ *    optchar      - pointer to index of next char to process.  Can be 0 or\n+ *                   const defined at top of this file like THIS_ARG_DONE\n+ *    negated      - on return pointer to int set to 1 if option negated\n+ *                   or 0 otherwise\n+ *    value        - on return pointer to string set to value of option if any\n+ *                   or NULL if none.  If value is returned then the caller\n+ *                   should free() it when not needed anymore.\n+ *    option_num   - pointer to index in options[] of returned option or\n+ *                   o_NO_OPTION_MATCH if none.  Do not change as used by\n+ *                   value lists.\n+ *    depth        - recursion depth (0 at top level, 1 or more in arg files)\n+ */\n+static unsigned long get_shortopt(option_group, args, argnum, optchar, negated,\n+                                  value, option_num, depth)\n+  int option_group;\n+  ZCONST char **args;\n+  int argnum;\n+  int *optchar;\n+  int *negated;\n+  char **value;\n+  int *option_num;\n+  int depth;\n+{\n+  ZCONST char *shortopt;\n+  int clen;\n+  ZCONST char *nextchar;\n+  ZCONST char *s;\n+  ZCONST char *start;\n+  int op;\n+  ZCONST char *arg;\n+  int match = -1;\n+\n+\n+  /* get arg */\n+  arg = args[argnum];\n+  /* current char in arg */\n+  nextchar = arg + (*optchar);\n+  clen = MB_CLEN(nextchar);\n+  /* next char in arg */\n+  (*optchar) +=  clen;\n+  /* get first char of short option */\n+  shortopt = arg + (*optchar);\n+  /* no value */\n+  *value = NULL;\n+\n+  if (*shortopt == '\\0') {\n+    /* no more options in arg */\n+    *optchar = 0;\n+    *option_num = o_NO_OPTION_MATCH;\n+    return 0;\n+  }\n+\n+  /* look for match in options */\n+  clen = MB_CLEN(shortopt);\n+  for (op = 0; options[op].option_ID; op++) {\n+    /* Only look at options in this option group */\n+    if (options[op].option_group == option_group) {\n+      s = options[op].shortopt;\n+      if (s && s[0] == shortopt[0]) {\n+        if (s[1] == '\\0' && clen == 1) {\n+          /* single char match */\n+          match = op;\n+        } else {\n+          /* 2 wide short opt.  Could support more chars but should use long opts instead */\n+          if (s[1] == shortopt[1]) {\n+            /* match 2 char short opt or 2 byte char */\n+            match = op;\n+            if (clen == 1) (*optchar)++;\n+            break;\n+          }\n+        }\n+      }\n+    }\n+  }\n+\n+  if (match > -1) {\n+    /* match */\n+    clen = MB_CLEN(shortopt);\n+    nextchar = arg + (*optchar) + clen;\n+    /* check for trailing dash negating option */\n+    if (*nextchar == '-') {\n+      /* negated */\n+      if (options[match].negatable == o_NOT_NEGATABLE) {\n+        if (options[match].value_type == o_NO_VALUE) {\n+          optionerr(options, optionerrbuf, op_not_neg_err, match, 0);\n+          if (depth > 0) {\n+            /* unwind */\n+            oWARN(optionerrbuf);\n+            return o_ARG_FILE_ERR;\n+          } else {\n+            oWARN(optionerrbuf);\n+            return o_BAD_ERR;\n+          }\n+        }\n+      } else {\n+        *negated = 1;\n+        /* set up to skip negating dash */\n+        (*optchar) += clen;\n+        clen = 1;\n+      }\n+    }\n+\n+    /* value */\n+    clen = MB_CLEN(arg + (*optchar));\n+    /* optional value, one char value, and number value must follow option */\n+    if (options[match].value_type == o_ONE_CHAR_VALUE) {\n+      /* one char value */\n+      if (arg[(*optchar) + clen]) {\n+        /* has value */\n+        if (MB_CLEN(arg + (*optchar) + clen) > 1) {\n+          /* multibyte value not allowed for now */\n+          optionerr(options, optionerrbuf, oco_no_mbc_err, match, 0);\n+          if (depth > 0) {\n+            /* unwind */\n+            oWARN(optionerrbuf);\n+            return o_ARG_FILE_ERR;\n+          } else {\n+            oWARN(optionerrbuf);\n+            return o_BAD_ERR;\n+          }\n+        }\n+        if ((*value = (char *) malloc(2)) == NULL) {\n+          oWARN(\"memory - gso\");\n+          return o_BAD_ERR;\n+        }\n+        (*value)[0] = *(arg + (*optchar) + clen);\n+        (*value)[1] = '\\0';\n+        *optchar += clen;\n+        clen = 1;\n+      } else {\n+        /* one char values require a value */\n+        optionerr(options, optionerrbuf, oco_req_val_err, match, 0);\n+        if (depth > 0) {\n+          oWARN(optionerrbuf);\n+          return o_ARG_FILE_ERR;\n+        } else {\n+          oWARN(optionerrbuf);\n+          return o_BAD_ERR;\n+        }\n+      }\n+    } else if (options[match].value_type == o_NUMBER_VALUE) {\n+      /* read chars until end of number */\n+      start = arg + (*optchar) + clen;\n+      if (*start == '+' || *start == '-') {\n+        start++;\n+      }\n+      s = start;\n+      for (; isdigit(*s); MB_NEXTCHAR(s)) ;\n+      if (s == start) {\n+        /* no digits */\n+        optionerr(options, optionerrbuf, num_req_val_err, match, 0);\n+        if (depth > 0) {\n+          oWARN(optionerrbuf);\n+          return o_ARG_FILE_ERR;\n+        } else {\n+          oWARN(optionerrbuf);\n+          return o_BAD_ERR;\n+        }\n+      }\n+      start = arg + (*optchar) + clen;\n+      if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) {\n+        oWARN(\"memory - gso\");\n+        return o_BAD_ERR;\n+      }\n+      *optchar += (int)(s - start);\n+      strncpy(*value, start, (int)(s - start));\n+      (*value)[(int)(s - start)] = '\\0';\n+      clen = MB_CLEN(s);\n+    } else if (options[match].value_type == o_OPTIONAL_VALUE) {\n+      /* optional value */\n+      /* This seemed inconsistent so now if no value attached to argument look\n+         to the next argument if that argument is not an option for option\n+         value - 11/12/04 EG */\n+      if (arg[(*optchar) + clen]) {\n+        /* has value */\n+        /* add support for optional = - 2/6/05 EG */\n+        if (arg[(*optchar) + clen] == '=') {\n+          /* skip = */\n+          clen++;\n+        }\n+        if (arg[(*optchar) + clen]) {\n+          if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))\n+              == NULL) {\n+            oWARN(\"memory - gso\");\n+            return o_BAD_ERR;\n+          }\n+          strcpy(*value, arg + (*optchar) + clen);\n+        }\n+        *optchar = THIS_ARG_DONE;\n+      } else if (args[argnum + 1] && args[argnum + 1][0] != '-') {\n+        /* use next arg for value */\n+        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {\n+          oWARN(\"memory - gso\");\n+          return o_BAD_ERR;\n+        }\n+        /* using next arg as value */\n+        strcpy(*value, args[argnum + 1]);\n+        *optchar = SKIP_VALUE_ARG;\n+      }\n+    } else if (options[match].value_type == o_REQUIRED_VALUE ||\n+               options[match].value_type == o_VALUE_LIST) {\n+      /* see if follows option */\n+      if (arg[(*optchar) + clen]) {\n+        /* has value following option as -ovalue */\n+        /* add support for optional = - 6/5/05 EG */\n+        if (arg[(*optchar) + clen] == '=') {\n+          /* skip = */\n+          clen++;\n+        }\n+        if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))\n+            == NULL) {\n+          oWARN(\"memory - gso\");\n+          return o_BAD_ERR;\n+        }\n+        strcpy(*value, arg + (*optchar) + clen);\n+        *optchar = THIS_ARG_DONE;\n+      } else {\n+        /* use next arg for value */\n+        if (args[argnum + 1]) {\n+          if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1))\n+              == NULL) {\n+            oWARN(\"memory - gso\");\n+            return o_BAD_ERR;\n+          }\n+          strcpy(*value, args[argnum + 1]);\n+          if (options[match].value_type == o_VALUE_LIST) {\n+            *optchar = START_VALUE_LIST;\n+          } else {\n+            *optchar = SKIP_VALUE_ARG;\n+          }\n+        } else {\n+          /* no value found */\n+          optionerr(options, optionerrbuf, op_req_val_err, match, 0);\n+          if (depth > 0) {\n+            oWARN(optionerrbuf);\n+            return o_ARG_FILE_ERR;\n+          } else {\n+            oWARN(optionerrbuf);\n+            return o_BAD_ERR;\n+          }\n+        }\n+      }\n+    }\n+\n+    *option_num = match;\n+    return options[match].option_ID;\n+  }\n+  sprintf(optionerrbuf, LoadFarStringSmall(sh_op_not_sup_err), *shortopt);\n+  if (depth > 0) {\n+    /* unwind */\n+    oWARN(optionerrbuf);\n+    return o_ARG_FILE_ERR;\n+  } else {\n+    oWARN(optionerrbuf);\n+    return o_BAD_ERR;\n+  }\n+  return 0;\n+}\n+\n+\n+/* get_longopt\n+ *\n+ * Get the long option in args array at argnum.\n+ * Parameters same as for get_shortopt.\n+ */\n+\n+static unsigned long get_longopt(option_group, args, argnum, optchar, negated,\n+                                 value, option_num, depth)\n+  int option_group;\n+  ZCONST char **args;\n+  int argnum;\n+  int *optchar;\n+  int *negated;\n+  char **value;\n+  int *option_num;\n+  int depth;\n+{\n+  char *longopt;\n+  char *lastchr;\n+  char *valuestart;\n+  int op;\n+  char *arg;\n+  int match = -1;\n+  *value = NULL;\n+\n+  if (args == NULL) {\n+    *option_num = o_NO_OPTION_MATCH;\n+    return 0;\n+  }\n+  if (args[argnum] == NULL) {\n+    *option_num = o_NO_OPTION_MATCH;\n+    return 0;\n+  }\n+  /* copy arg so can chop end if value */\n+  if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) {\n+    oWARN(\"memory - glo\");\n+    return o_BAD_ERR;\n+  }\n+  strcpy(arg, args[argnum]);\n+\n+  /* get option */\n+  longopt = arg + 2;\n+  /* no value */\n+  *value = NULL;\n+\n+  /* find = */\n+  for (lastchr = longopt, valuestart = longopt;\n+       *valuestart && *valuestart != '=';\n+       lastchr = valuestart, MB_NEXTCHAR(valuestart)) ;\n+  if (*valuestart) {\n+    /* found =value */\n+    *valuestart = '\\0';\n+    valuestart++;\n+  } else {\n+    valuestart = NULL;\n+  }\n+\n+  if (*lastchr == '-') {\n+    /* option negated */\n+    *negated = 1;\n+    *lastchr = '\\0';\n+  } else {\n+    *negated = 0;\n+  }\n+\n+  /* look for long option match */\n+  for (op = 0; options[op].option_ID; op++) {\n+    /* Only look at options in the option group */\n+    if (options[op].option_group == option_group) {\n+      if (options[op].longopt &&\n+          strcmp(LoadFarStringSmall(options[op].longopt), longopt) == 0) {\n+        /* exact match */\n+        match = op;\n+        break;\n+      }\n+      if (options[op].longopt &&\n+          strncmp(LoadFarStringSmall(options[op].longopt),\n+                  longopt, strlen(longopt)) == 0) {\n+        if (match > -1) {\n+          sprintf(optionerrbuf, LoadFarStringSmall(long_op_ambig_err),\n+                  longopt);\n+          free(arg);\n+          if (depth > 0) {\n+            /* unwind */\n+            oWARN(optionerrbuf);\n+            return o_ARG_FILE_ERR;\n+          } else {\n+            oWARN(optionerrbuf);\n+            return o_BAD_ERR;\n+          }\n+        }\n+        match = op;\n+      }\n+    }\n+  }\n+\n+  if (match == -1) {\n+    sprintf(optionerrbuf, LoadFarStringSmall(long_op_not_sup_err), longopt);\n+    free(arg);\n+    if (depth > 0) {\n+      oWARN(optionerrbuf);\n+      return o_ARG_FILE_ERR;\n+    } else {\n+      oWARN(optionerrbuf);\n+      return o_BAD_ERR;\n+    }\n+  }\n+\n+  /* one long option an arg */\n+  *optchar = THIS_ARG_DONE;\n+\n+  /* if negated then see if allowed */\n+  if (*negated && options[match].negatable == o_NOT_NEGATABLE) {\n+    optionerr(options, optionerrbuf, op_not_neg_err, match, 1);\n+    free(arg);\n+    if (depth > 0) {\n+      /* unwind */\n+      oWARN(optionerrbuf);\n+      return o_ARG_FILE_ERR;\n+    } else {\n+      oWARN(optionerrbuf);\n+      return o_BAD_ERR;\n+    }\n+  }\n+  /* get value */\n+  if (options[match].value_type == o_OPTIONAL_VALUE) {\n+    /* optional value in form option=value */\n+    if (valuestart) {\n+      /* option=value */\n+      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {\n+        free(arg);\n+        oWARN(\"memory - glo\");\n+        return o_BAD_ERR;\n+      }\n+      strcpy(*value, valuestart);\n+    }\n+  } else if (options[match].value_type == o_REQUIRED_VALUE ||\n+             options[match].value_type == o_NUMBER_VALUE ||\n+             options[match].value_type == o_ONE_CHAR_VALUE ||\n+             options[match].value_type == o_VALUE_LIST) {\n+    /* handle long option one char and number value as required value */\n+    if (valuestart) {\n+      /* option=value */\n+      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {\n+        free(arg);\n+        oWARN(\"memory - glo\");\n+        return o_BAD_ERR;\n+      }\n+      strcpy(*value, valuestart);\n+    } else {\n+      /* use next arg */\n+      if (args[argnum + 1]) {\n+        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {\n+          free(arg);\n+          oWARN(\"memory - glo\");\n+          return o_BAD_ERR;\n+        }\n+        /* using next arg as value */\n+        strcpy(*value, args[argnum + 1]);\n+        if (options[match].value_type == o_VALUE_LIST) {\n+          *optchar = START_VALUE_LIST;\n+        } else {\n+          *optchar = SKIP_VALUE_ARG;\n+        }\n+      } else {\n+        /* no value found */\n+        optionerr(options, optionerrbuf, op_req_val_err, match, 1);\n+        free(arg);\n+        if (depth > 0) {\n+          /* unwind */\n+          oWARN(optionerrbuf);\n+          return o_ARG_FILE_ERR;\n+        } else {\n+          oWARN(optionerrbuf);\n+          return o_BAD_ERR;\n+        }\n+      }\n+    }\n+  } else if (options[match].value_type == o_NO_VALUE) {\n+    /* this option does not accept a value */\n+    if (valuestart) {\n+      /* --option=value */\n+      optionerr(options, optionerrbuf, op_no_allow_val_err, match, 1);\n+      free(arg);\n+      if (depth > 0) {\n+        oWARN(optionerrbuf);\n+        return o_ARG_FILE_ERR;\n+      } else {\n+        oWARN(optionerrbuf);\n+        return o_BAD_ERR;\n+      }\n+    }\n+  }\n+  free(arg);\n+\n+  *option_num = match;\n+  return options[match].option_ID;\n+}\n+\n+\n+\n+/* get_option\n+ *\n+ * Main interface for user.  Use this function to get options, values and\n+ * non-option arguments from a command line provided in argv form.\n+ *\n+ * To use get_option() first define valid options by setting\n+ * the global variable options[] to an array of option_struct.  Also\n+ * either change defaults below or make variables global and set elsewhere.\n+ * Zip uses below defaults.\n+ *\n+ * Call get_option() to get an option (like -b or --temp-file) and any\n+ * value for that option (like filename for -b) or a non-option argument\n+ * (like archive name) each call.  If *value* is not NULL after calling\n+ * get_option() it is a returned value and the caller should either store\n+ * the char pointer or free() it before calling get_option() again to avoid\n+ * leaking memory.  If a non-option non-value argument is returned get_option()\n+ * returns o_NON_OPTION_ARG and value is set to the entire argument.\n+ * When there are no more arguments get_option() returns 0.\n+ *\n+ * The parameters argnum (after set to 0 on initial call),\n+ * optchar, first_nonopt_arg, option_num, and depth (after initial\n+ * call) are set and maintained by get_option() and should not be\n+ * changed.  The parameters argc, negated, and value are outputs and\n+ * can be used by the calling program.  get_option() returns either the\n+ * option_ID for the current option, a special value defined in\n+ * zip.h, or 0 when no more arguments.\n+ *\n+ * The value returned by get_option() is the ID value in the options\n+ * table.  This value can be duplicated in the table if different\n+ * options are really the same option.  The index into the options[]\n+ * table is given by option_num, though the ID should be used as\n+ * option numbers change when the table is changed.  The ID must\n+ * not be 0 for any option as this ends the table.  If get_option()\n+ * finds an option not in the table it calls oERR to post an\n+ * error and exit.  Errors also result if the option requires a\n+ * value that is missing, a value is present but the option does\n+ * not take one, and an option is negated but is not\n+ * negatable.  Non-option arguments return o_NON_OPTION_ARG\n+ * with the entire argument in value.\n+ *\n+ * For Zip and UnZip, permuting is on and all options and their values\n+ * are returned before any non-option arguments like archive name.\n+ *\n+ * The arguments \"-\" alone and \"--\" alone return as non-option arguments.\n+ * Note that \"-\" should not be used as part of a short option\n+ * entry in the table but can be used in the middle of long\n+ * options such as in the long option \"a-long-option\".  Now \"--\" alone\n+ * stops option processing, returning any arguments following \"--\" as\n+ * non-option arguments instead of options.\n+ *\n+ * Argument file support is removed from this version. It may be added later.\n+ *\n+ * After each call:\n+ *   argc       is set to the current size of args[] but should not change\n+ *                with argument file support removed,\n+ *   argnum     is the index of the current arg,\n+ *   value      is either the value of the returned option or non-option\n+ *                argument or NULL if option with no value,\n+ *   negated    is set if the option was negated by a trailing dash (-)\n+ *   option_num is set to either the index in options[] for the option or\n+ *                o_NO_OPTION_MATCH if no match.\n+ * Negation is checked before the value is read if the option is negatable so\n+ * that the - is not included in the value.  If the option is not negatable\n+ * but takes a value then the - will start the value.  If permuting then\n+ * argnum and first_nonopt_arg are unreliable and should not be used.\n+ *\n+ * Command line is read from left to right.  As get_option() finds non-option\n+ * arguments (arguments not starting with - and that are not values to options)\n+ * it moves later options and values in front of the non-option arguments.\n+ * This permuting is turned off by setting enable_permute to 0.  Then\n+ * get_option() will return options and non-option arguments in the order\n+ * found.  Currently permuting is only done after an argument is completely\n+ * processed so that any value can be moved with options they go with.  All\n+ * state information is stored in the parameters argnum, optchar,\n+ * first_nonopt_arg and option_num.  You should not change these after the\n+ * first call to get_option().  If you need to back up to a previous arg then\n+ * set argnum to that arg (remembering that args may have been permuted) and\n+ * set optchar = 0 and first_nonopt_arg to the first non-option argument if\n+ * permuting.  After all arguments are returned the next call to get_option()\n+ * returns 0.  The caller can then call free_args(args) if appropriate.\n+ *\n+ * get_option() accepts arguments in the following forms:\n+ *  short options\n+ *       of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single\n+ *       leading -, as in -abccdba.  In this example if 'b' is followed by 'a'\n+ *       it matches short option 'ba' else it is interpreted as short option\n+ *       b followed by another option.  The character - is not legal as a\n+ *       short option or as part of a 2 character short option.\n+ *\n+ *       If a short option has a value it immediately follows the option or\n+ *       if that option is the end of the arg then the next arg is used as\n+ *       the value.  So if short option e has a value, it can be given as\n+ *             -evalue\n+ *       or\n+ *             -e value\n+ *       and now\n+ *             -e=value\n+ *       but now that = is optional a leading = is stripped for the first.\n+ *       This change allows optional short option values to be defaulted as\n+ *             -e=\n+ *       Either optional or required values can be specified.  Optional values\n+ *       now use both forms as ignoring the later got confusing.  Any\n+ *       non-value short options can preceed a valued short option as in\n+ *             -abevalue\n+ *       Some value types (one_char and number) allow options after the value\n+ *       so if oc is an option that takes a character and n takes a number\n+ *       then\n+ *             -abocVccn42evalue\n+ *       returns value V for oc and value 42 for n.  All values are strings\n+ *       so programs may have to convert the \"42\" to a number.  See long\n+ *       options below for how value lists are handled.\n+ *\n+ *       Any short option can be negated by following it with -.  Any - is\n+ *       handled and skipped over before any value is read unless the option\n+ *       is not negatable but takes a value and then - starts the value.\n+ *\n+ *       If the value for an optional value is just =, then treated as no\n+ *       value.\n+ *\n+ *  long options\n+ *       of arbitrary length are assumed if an arg starts with -- but is not\n+ *       exactly --.  Long options are given one per arg and can be abbreviated\n+ *       if the abbreviation uniquely matches one of the long options.\n+ *       Exact matches always match before partial matches.  If ambiguous an\n+ *       error is generated.\n+ *\n+ *       Values are specified either in the form\n+ *             --longoption=value\n+ *       or can be the following arg if the value is required as in\n+ *             --longoption value\n+ *       Optional values to long options must be in the first form.\n+ *\n+ *       Value lists are specified by o_VALUE_LIST and consist of an option\n+ *       that takes a value followed by one or more value arguments.\n+ *       The two forms are\n+ *             --option=value\n+ *       or\n+ *             -ovalue\n+ *       for a single value or\n+ *             --option value1 value2 value3 ... --option2\n+ *       or\n+ *             -o value1 value2 value3 ...\n+ *       for a list of values.  The list ends at the next option, the\n+ *       end of the command line, or at a single \"@\" argument.\n+ *       Each value is treated as if it was preceeded by the option, so\n+ *             --option1 val1 val2\n+ *       with option1 value_type set to o_VALUE_LIST is the same as\n+ *             --option1=val1 --option1=val2\n+ *\n+ *       Long options can be negated by following the option with - as in\n+ *             --longoption-\n+ *       Long options with values can also be negated if this makes sense for\n+ *       the caller as:\n+ *             --longoption-=value\n+ *       If = is not followed by anything it is treated as no value.\n+ *\n+ *  @path\n+ *       Argument files support removed from this version.  It may be added\n+ *       back later.\n+ *\n+ *  non-option argument\n+ *       is any argument not given above.  If enable_permute is 1 then\n+ *       these are returned after all options, otherwise all options and\n+ *       args are returned in order.  Returns option ID o_NON_OPTION_ARG\n+ *       and sets value to the argument.\n+ *\n+ *\n+ * Arguments to get_option:\n+ *  int option_group       - either UZO for UnZip or ZIO for ZipInfo\n+ *  char ***pargs          - pointer to arg array in the argv form\n+ *  int *argc              - returns the current argc for args incl. args[0]\n+ *  int *argnum            - the index of the current argument (caller\n+ *                            should set = 0 on first call and not change\n+ *                            after that)\n+ *  int *optchar           - index of next short opt in arg or special\n+ *  int *first_nonopt_arg  - used by get_option to permute args\n+ *  int *negated           - option was negated (had trailing -)\n+ *  char *value            - value of option if any (free when done with it)\n+ *                            or NULL\n+ *  int *option_num        - the index in options of the last option returned\n+ *                            (can be o_NO_OPTION_MATCH)\n+ *  int recursion_depth    - current depth of recursion\n+ *                            (always set to 0 by caller)\n+ *                            (always 0 with argument files support removed)\n+ *\n+ *  Caller should only read the returned option ID and the value, negated,\n+ *  and option_num (if required) parameters after each call.\n+ *\n+ *  Ed Gordon\n+ *  8/24/2003 (last updated 3/1/2008 EG)\n+ *\n+ */\n+\n+unsigned long get_option(option_group, pargs, argc, argnum, optchar, value,\n+                         negated, first_nonopt_arg, option_num, recursion_depth)\n+  int option_group;\n+  char ***pargs;\n+  int *argc;\n+  int *argnum;\n+  int *optchar;\n+  char **value;\n+  int *negated;\n+  int *first_nonopt_arg;\n+  int *option_num;\n+  int recursion_depth;\n+{\n+  char **args;\n+  unsigned long option_ID;\n+\n+  int argcnt;\n+  int first_nonoption_arg;\n+  char *arg = NULL;\n+  int h;\n+  int optc;\n+  int argn;\n+  int j;\n+  int v;\n+  int read_rest_args_verbatim = 0;  /* 7/25/04 - ignore options and arg files for rest args */\n+\n+  /* caller should free value or assign it to another\n+     variable before calling get_option again. */\n+  *value = NULL;\n+\n+  /* if args is NULL then done */\n+  if (pargs == NULL) {\n+    *argc = 0;\n+    return 0;\n+  }\n+  args = *pargs;\n+  if (args == NULL) {\n+    *argc = 0;\n+    return 0;\n+  }\n+\n+  /* count args */\n+  for (argcnt = 0; args[argcnt]; argcnt++) ;\n+\n+  /* if no provided args then nothing to do */\n+  if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) {\n+    *argc = argcnt;\n+    /* return 0 to note that no args are left */\n+    return 0;\n+  }\n+\n+  *negated = 0;\n+  first_nonoption_arg = *first_nonopt_arg;\n+  argn = *argnum;\n+  optc = *optchar;\n+\n+  if (optc == READ_REST_ARGS_VERBATIM) {\n+    read_rest_args_verbatim = 1;\n+  }\n+\n+  if (argn == -1 || (recursion_depth == 0 && argn == 0)) {\n+    /* first call */\n+    /* if depth = 0 then args[0] is argv[0] so skip */\n+    *option_num = o_NO_OPTION_MATCH;\n+    optc = THIS_ARG_DONE;\n+    first_nonoption_arg = -1;\n+  }\n+\n+  /* if option_num is set then restore last option_ID in case continuing\n+     value list */\n+  option_ID = 0;\n+  if (*option_num != o_NO_OPTION_MATCH) {\n+    option_ID = options[*option_num].option_ID;\n+  }\n+\n+  /* get next option if any */\n+  for (;;)  {\n+    if (read_rest_args_verbatim) {\n+      /* rest of args after \"--\" are non-option args if doubledash_ends_options\n+         set */\n+      argn++;\n+      if (argn > argcnt || args[argn] == NULL) {\n+        /* done */\n+        option_ID = 0;\n+        break;\n+      }\n+      arg = args[argn];\n+      if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n+        oWARN(\"memory - go\");\n+        return o_BAD_ERR;\n+      }\n+      strcpy(*value, arg);\n+      *option_num = o_NO_OPTION_MATCH;\n+      option_ID = o_NON_OPTION_ARG;\n+      break;\n+\n+    /* permute non-option args after option args so options are returned\n+       first */\n+    } else if (enable_permute) {\n+      if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE ||\n+          optc == START_VALUE_LIST || optc == IN_VALUE_LIST ||\n+          optc == STOP_VALUE_LIST) {\n+        /* moved to new arg */\n+        if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {\n+          /* do the permuting - move non-options after this option */\n+          /* if option and value separate args or starting list skip option */\n+          if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) {\n+            v = 1;\n+          } else {\n+            v = 0;\n+          }\n+          for (h = first_nonoption_arg; h < argn; h++) {\n+            arg = args[first_nonoption_arg];\n+            for (j = first_nonoption_arg; j < argn + v; j++) {\n+              args[j] = args[j + 1];\n+            }\n+            args[j] = arg;\n+          }\n+          first_nonoption_arg += 1 + v;\n+        }\n+      }\n+    } else if (optc == NON_OPTION_ARG) {\n+      /* if not permuting then already returned arg */\n+      optc = THIS_ARG_DONE;\n+    }\n+\n+    /* value lists */\n+    if (optc == STOP_VALUE_LIST) {\n+      optc = THIS_ARG_DONE;\n+    }\n+\n+    if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) {\n+      if (optc == START_VALUE_LIST) {\n+        /* already returned first value */\n+        argn++;\n+        optc = IN_VALUE_LIST;\n+      }\n+      argn++;\n+      arg = args[argn];\n+      /* if end of args and still in list and there are non-option args then\n+         terminate list */\n+      if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST)\n+          && first_nonoption_arg > -1) {\n+        /* terminate value list with @ */\n+        /* this is only needed for argument files */\n+        /* but is also good for show command line so command lines with lists\n+           can always be read back in */\n+        argcnt = insert_arg(&args, \"@\", first_nonoption_arg, 1);\n+        argn++;\n+        if (first_nonoption_arg > -1) {\n+          first_nonoption_arg++;\n+        }\n+      }\n+\n+      arg = args[argn];\n+      if (arg && arg[0] == '@' && arg[1] == '\\0') {\n+          /* inserted arguments terminator */\n+          optc = STOP_VALUE_LIST;\n+          continue;\n+      } else if (arg && arg[0] != '-') {  /* not option */\n+        /* - and -- are not allowed in value lists unless escaped */\n+        /* another value in value list */\n+        if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {\n+          oWARN(\"memory - go\");\n+          return o_BAD_ERR;\n+        }\n+        strcpy(*value, args[argn]);\n+        break;\n+\n+      } else {\n+        argn--;\n+        optc = THIS_ARG_DONE;\n+      }\n+    }\n+\n+    /* move to next arg */\n+    if (optc == SKIP_VALUE_ARG) {\n+      argn += 2;\n+      optc = 0;\n+    } else if (optc == THIS_ARG_DONE) {\n+      argn++;\n+      optc = 0;\n+    }\n+    if (argn > argcnt) {\n+      break;\n+    }\n+    if (args[argn] == NULL) {\n+      /* done unless permuting and non-option args */\n+      if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {\n+        /* return non-option arguments at end */\n+        if (optc == NON_OPTION_ARG) {\n+          first_nonoption_arg++;\n+        }\n+        /* after first pass args are permuted but skipped over non-option\n+           args */\n+        /* swap so argn points to first non-option arg */\n+        j = argn;\n+        argn = first_nonoption_arg;\n+        first_nonoption_arg = j;\n+      }\n+      if (argn > argcnt || args[argn] == NULL) {\n+        /* done */\n+        option_ID = 0;\n+        break;\n+      }\n+    }\n+\n+    /* after swap first_nonoption_arg points to end which is NULL */\n+    if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) {\n+      /* only non-option args left */\n+      if (optc == NON_OPTION_ARG) {\n+        argn++;\n+      }\n+      if (argn > argcnt || args[argn] == NULL) {\n+        /* done */\n+        option_ID = 0;\n+        break;\n+      }\n+      if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {\n+        oWARN(\"memory - go\");\n+        return o_BAD_ERR;\n+      }\n+      strcpy(*value, args[argn]);\n+      optc = NON_OPTION_ARG;\n+      option_ID = o_NON_OPTION_ARG;\n+      break;\n+    }\n+\n+    arg = args[argn];\n+\n+    /* is it an option */\n+    if (arg[0] == '-') {\n+      /* option */\n+      if (arg[1] == '\\0') {\n+        /* arg = - */\n+        /* treat like non-option arg */\n+        *option_num = o_NO_OPTION_MATCH;\n+        if (enable_permute) {\n+          /* permute args to move all non-option args to end */\n+          if (first_nonoption_arg < 0) {\n+            first_nonoption_arg = argn;\n+          }\n+          argn++;\n+        } else {\n+          /* not permute args so return non-option args when found */\n+          if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n+            oWARN(\"memory - go\");\n+            return o_BAD_ERR;\n+          }\n+          strcpy(*value, arg);\n+          optc = NON_OPTION_ARG;\n+          option_ID = o_NON_OPTION_ARG;\n+          break;\n+        }\n+\n+      } else if (arg[1] == '-') {\n+        /* long option */\n+        if (arg[2] == '\\0') {\n+          /* arg = -- */\n+          if (doubledash_ends_options) {\n+            /* Now -- stops permuting and forces the rest of\n+               the command line to be read verbatim - 7/25/04 EG */\n+\n+            /* never permute args after -- and return as non-option args */\n+            if (first_nonoption_arg < 1) {\n+              /* -- is first non-option argument - 8/7/04 EG */\n+              argn--;\n+            } else {\n+              /* go back to start of non-option args - 8/7/04 EG */\n+              argn = first_nonoption_arg - 1;\n+            }\n+\n+            /* disable permuting and treat remaining arguments as not\n+               options */\n+            read_rest_args_verbatim = 1;\n+            optc = READ_REST_ARGS_VERBATIM;\n+\n+          } else {\n+            /* treat like non-option arg */\n+            *option_num = o_NO_OPTION_MATCH;\n+            if (enable_permute) {\n+              /* permute args to move all non-option args to end */\n+              if (first_nonoption_arg < 0) {\n+                first_nonoption_arg = argn;\n+              }\n+              argn++;\n+            } else {\n+              /* not permute args so return non-option args when found */\n+              if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n+                oWARN(\"memory - go\");\n+                return o_BAD_ERR;\n+              }\n+              strcpy(*value, arg);\n+              optc = NON_OPTION_ARG;\n+              option_ID = o_NON_OPTION_ARG;\n+              break;\n+            }\n+          }\n+\n+        } else {\n+          option_ID = get_longopt(option_group, (ZCONST char **)args, argn,\n+                                  &optc, negated,\n+                                  value, option_num, recursion_depth);\n+          if (option_ID == o_BAD_ERR) {\n+            return o_BAD_ERR;\n+          } else if (option_ID == o_ARG_FILE_ERR) {\n+            /* unwind as only get this if recursion_depth > 0 */\n+            return option_ID;\n+          }\n+          break;\n+        }\n+\n+      } else {\n+        /* short option */\n+        option_ID = get_shortopt(option_group, (ZCONST char **)args, argn,\n+                                 &optc, negated,\n+                                 value, option_num, recursion_depth);\n+\n+        if (option_ID == o_BAD_ERR) {\n+          return o_BAD_ERR;\n+        } else if (option_ID == o_ARG_FILE_ERR) {\n+          /* unwind as only get this if recursion_depth > 0 */\n+          return option_ID;\n+        }\n+\n+        if (optc == 0) {\n+          /* if optc = 0 then ran out of short opts this arg */\n+          optc = THIS_ARG_DONE;\n+        } else {\n+          break;\n+        }\n+      }\n+\n+#if 0\n+    /* argument file code left out\n+       so for now let filenames start with @\n+    */\n+\n+    } else if (allow_arg_files && arg[0] == '@') {\n+      /* arg file */\n+      oERR(PK_PARMS, no_arg_files_err);\n+#endif\n+\n+    } else {\n+      /* non-option */\n+      if (enable_permute) {\n+        /* permute args to move all non-option args to end */\n+        if (first_nonoption_arg < 0) {\n+          first_nonoption_arg = argn;\n+        }\n+        argn++;\n+      } else {\n+        /* no permute args so return non-option args when found */\n+        if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n+          oWARN(\"memory - go\");\n+          return o_BAD_ERR;\n+        }\n+        strcpy(*value, arg);\n+        *option_num = o_NO_OPTION_MATCH;\n+        optc = NON_OPTION_ARG;\n+        option_ID = o_NON_OPTION_ARG;\n+        break;\n+      }\n+\n+    }\n+  }\n+\n+  *pargs = args;\n+  *argc = argcnt;\n+  *first_nonopt_arg = first_nonoption_arg;\n+  *argnum = argn;\n+  *optchar = optc;\n+\n+  return option_ID;\n+}\ndiff -ru2 unz60e03/unzpriv.h u6e3_np/unzpriv.h\n--- unz60e03/unzpriv.h\tMon Mar 24 11:53:24 2008\n+++ u6e3_np/unzpriv.h\tMon Mar 24 14:13:02 2008\n@@ -1271,4 +1271,89 @@\n #endif\n \n+\n+/*--------------------------------------------------------------------\n+    Long option support\n+    23 August 2003\n+    Updated for UnZip 1 March 2008\n+    See unzip.c\n+  --------------------------------------------------------------------*/\n+\n+/* The below is for use in the caller-provided options table */\n+\n+/* option groups */\n+#define UZO 1   /* UnZip option */\n+#define ZIO 2   /* ZipInfo option */\n+\n+\n+/* value_type - value is always returned as a string. */\n+#define o_NO_VALUE        0   /* this option does not take a value */\n+#define o_REQUIRED_VALUE  1   /* this option requires a value */\n+#define o_OPTIONAL_VALUE  2   /* value is optional (see get_option() for details) */\n+#define o_VALUE_LIST      3   /* this option takes a list of values */\n+#define o_ONE_CHAR_VALUE  4   /* next char is value (does not end short opt string) */\n+#define o_NUMBER_VALUE    5   /* value is integer (does not end short opt string) */\n+\n+\n+/* negatable - a dash following the option (but before any value) sets negated. */\n+#define o_NOT_NEGATABLE   0   /* trailing '-' to negate either starts value or generates error */\n+#define o_NEGATABLE       1   /* trailing '-' sets negated to TRUE */\n+\n+\n+/* option_num can be this when option not in options table */\n+#define o_NO_OPTION_MATCH     -1\n+\n+/* special values returned by get_option - do not use these as option IDs */\n+#define o_NON_OPTION_ARG      ((unsigned long) 0xFFFF)    /* returned for non-option\n+                                                             args */\n+#define o_ARG_FILE_ERR        ((unsigned long) 0xFFFE)    /* internal recursion\n+                                                             return (user never sees) */\n+#define o_BAD_ERR             ((unsigned long) 0xFFFD)    /* bad error */\n+\n+/* options array is set in unzip.c */\n+struct option_struct {\n+  int option_group;         /* either UZO for UnZip or ZIO for ZipInfo syntax */\n+  char Far *shortopt;       /* pointer to short option string */\n+  char Far *longopt;        /* pointer to long option string */\n+  int  value_type;          /* from above */\n+  int  negatable;           /* from above */\n+  unsigned long option_ID;  /* value returned by get_option when this option\n+                               is found */\n+  char Far *name;           /* optional string for option returned on some\n+                               errors */\n+};\n+\n+/* structure used to create -x and include file lists */\n+struct file_list {\n+  char *name;\n+  struct file_list *next;\n+};\n+\n+\n+/* function prototypes */\n+\n+/* get the next option from args */\n+unsigned long get_option OF((int option_group,\n+                             char ***pargs, int *argc, int *argnum,\n+                             int *optchar,\n+                             char **value, int *negated, int *first_nonopt_arg,\n+                             int *option_num, int recursion_depth));\n+\n+/* copy args - copy an args array, allocating space as needed */\n+char **copy_args OF((char **args, int max_args));\n+\n+/* arg count - count args in argv like array */\n+int arg_count OF((char **args));\n+\n+/* free args - free args created with one of these functions */\n+int free_args OF((char **args));\n+\n+/* insert arg - copy an arg into args */\n+int insert_arg OF((char ***args, ZCONST char *arg, int insert_at,\n+                   int free_args));\n+\n+/*--------------------------------------------------------------------\n+    End of Long option support\n+  --------------------------------------------------------------------*/\n+\n /***********************************/\n /*  LARGE_FILE_SUPPORT             */\ndiff -ru2 unz60e03/vms/cmdline.c u6e3_np/vms/cmdline.c\n--- unz60e03/vms/cmdline.c\tTue Feb 12 01:37:42 2008\n+++ u6e3_np/vms/cmdline.c\tMon Mar 24 14:13:10 2008\n@@ -34,4 +34,6 @@\n **  Modified by:\n **\n+**      02-014          E. Gordon               10-Mar-2008 03:12\n+**              Modified to work with get_options().\n **      02-013          S. Schweda, C. Spieler  29-Dec-2007 03:34\n **              Extended /RESTORE qualifier to support timestamp restoration\n@@ -172,10 +174,10 @@\n $DESCRIPTOR(cli_text_auto,      \"TEXT.AUTO\");           /* -a */\n $DESCRIPTOR(cli_text_all,       \"TEXT.ALL\");            /* -aa */\n-$DESCRIPTOR(cli_text_none,      \"TEXT.NONE\");           /* ---a */\n+$DESCRIPTOR(cli_text_none,      \"TEXT.NONE\");           /* -a- */\n $DESCRIPTOR(cli_text_stmlf,     \"TEXT.STMLF\");          /* -S */\n $DESCRIPTOR(cli_binary,         \"BINARY\");              /* -b[b] */\n $DESCRIPTOR(cli_binary_auto,    \"BINARY.AUTO\");         /* -b */\n $DESCRIPTOR(cli_binary_all,     \"BINARY.ALL\");          /* -bb */\n-$DESCRIPTOR(cli_binary_none,    \"BINARY.NONE\");         /* ---b */\n+$DESCRIPTOR(cli_binary_none,    \"BINARY.NONE\");         /* -b- */\n $DESCRIPTOR(cli_case_insensitive,\"CASE_INSENSITIVE\");   /* -C */\n $DESCRIPTOR(cli_screen,         \"SCREEN\");              /* -c */\n@@ -202,5 +204,5 @@\n $DESCRIPTOR(cli_restore_own,    \"RESTORE.OWNER_PROT\");  /* -X */\n $DESCRIPTOR(cli_restore_date,   \"RESTORE.DATE\");        /* -DD */\n-$DESCRIPTOR(cli_restore_date_all, \"RESTORE.DATE.ALL\");  /* --D */\n+$DESCRIPTOR(cli_restore_date_all, \"RESTORE.DATE.ALL\");  /* -D- */\n $DESCRIPTOR(cli_restore_date_files, \"RESTORE.DATE.FILES\"); /* -D */\n $DESCRIPTOR(cli_dot_version,    \"DOT_VERSION\");         /* -Y */\n@@ -299,4 +301,6 @@\n **      SS$_ABORT       - Bad time value\n **\n+**  Modified to work with the get_option() command line parser.  10 March 2008\n+**\n */\n     register unsigned long status;\n@@ -419,5 +423,4 @@\n         if (status != CLI$_ABSENT) {\n             *ptr++ = '-';\n-            *ptr++ = '-';\n             *ptr++ = 'b';\n             if ((status & 1) &&\n@@ -427,4 +430,5 @@\n                     *ptr++ = 'b';\n             }\n+            *ptr++ = '-';\n         }\n \n@@ -436,5 +440,4 @@\n         if (status != CLI$_ABSENT) {\n             *ptr++ = '-';\n-            *ptr++ = '-';\n             *ptr++ = 'a';\n             if ((status & 1) &&\n@@ -446,4 +449,5 @@\n                     *ptr++ = 'S';\n             }\n+            *ptr++ = '-';\n         }\n \ndiff -ru2 unz60e03/zipinfo.c u6e3_np/zipinfo.c\n--- unz60e03/zipinfo.c\tMon Mar 24 14:23:54 2008\n+++ u6e3_np/zipinfo.c\tMon Mar 24 14:25:24 2008\n@@ -171,4 +171,6 @@\n static ZCONST char Far ZipfileCommTruncMsg[] =\n   \"\\ncaution:  zipfile comment truncated\\n\";\n+static ZCONST char Far NoMemArguments[] =\n+  \"envargs:  cannot get memory for arguments\";\n \n static ZCONST char Far CentralDirEntry[] =\n@@ -459,10 +461,48 @@\n     __GDEF\n {\n-    char   **argv, *s;\n-    int    argc, c, error=FALSE, negative=0;\n+    int    argc, error=FALSE;\n     int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */\n     int    tflag_slm=TRUE, tflag_2v=FALSE;\n     int    explicit_h=FALSE, explicit_t=FALSE;\n \n+    char **args;\n+\n+\n+    /* used by get_option */\n+    unsigned long option; /* option ID returned by get_option */\n+    int argcnt = 0;       /* current argcnt in args */\n+    int argnum = 0;       /* arg number */\n+    int optchar = 0;      /* option state */\n+    char *value = NULL;   /* non-option arg, option value or NULL */\n+    int negative = 0;     /* 1 = option negated */\n+    int fna = 0;          /* current first non-opt arg */\n+    int optnum = 0;       /* index in table */\n+\n+\n+    /* since get_option() returns xfiles and files one at a time, store them in\n+       linked lists until have them all */\n+\n+    int file_count;\n+    struct file_list *next_file;\n+\n+    /* files to extract */\n+    int in_files_count = 0;\n+    struct file_list *in_files = NULL;\n+    struct file_list *next_in_files = NULL;\n+\n+    /* files to exclude in -x list */\n+    int in_xfiles_count = 0;\n+    struct file_list *in_xfiles = NULL;\n+    struct file_list *next_in_xfiles = NULL;\n+\n+    G.wildzipfn = NULL;\n+\n+    /* make copy of args that can use with insert_arg() used by get_option() */\n+    args = copy_args(*pargv, 0);\n+\n+\n+    /* Initialize lists */\n+    G.filespecs = 0;\n+    G.xfilespecs = 0;\n \n #ifdef MACOS\n@@ -470,17 +510,41 @@\n #endif\n     G.extract_flag = FALSE;   /* zipinfo does not extract to disk */\n-    argc = *pargc;\n-    argv = *pargv;\n \n-    while (--argc > 0 && (*++argv)[0] == '-') {\n-        s = argv[0] + 1;\n-        while ((c = *s++) != 0) {    /* \"!= 0\":  prevent Turbo C warning */\n-            switch (c) {\n-                case '-':\n-                    ++negative;\n-                    break;\n+\n+    /*\n+    -------------------------------------------\n+    Process command line using get_option\n+    -------------------------------------------\n+\n+    Each call to get_option() returns either a command\n+    line option and possible value or a non-option argument.\n+    Arguments are permuted so that all options (-r, -b temp)\n+    are returned before non-option arguments (zipfile).\n+    Returns 0 when nothing left to read.\n+    */\n+\n+    /* set argnum = 0 on first call to init get_option */\n+    argnum = 0;\n+\n+    /* get_option returns the option ID and updates parameters:\n+           args    - usually same as argv if no argument file support\n+           argcnt  - current argc for args\n+           value   - char* to value (free() when done with it) or NULL if no value\n+           negated - option was negated with trailing -\n+    */\n+\n+    while ((option = get_option(ZIO, &args, &argcnt, &argnum,\n+                                &optchar, &value, &negative,\n+                                &fna, &optnum, 0)))\n+    {\n+        if(option == o_BAD_ERR) {\n+          return(PK_PARAM);\n+        }\n+\n+        switch (option)\n+        {\n                 case '1':      /* shortest listing:  JUST filenames */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 1;\n@@ -488,5 +552,5 @@\n                 case '2':      /* just filenames, plus headers if specified */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 2;\n@@ -495,5 +559,5 @@\n                 case ('C'):    /* -C:  match filenames case-insensitively */\n                     if (negative)\n-                        uO.C_flag = FALSE, negative = 0;\n+                        uO.C_flag = FALSE;\n                     else\n                         uO.C_flag = TRUE;\n@@ -502,5 +566,5 @@\n                 case 'h':      /* header line */\n                     if (negative)\n-                        hflag_2 = hflag_slmv = FALSE, negative = 0;\n+                        hflag_2 = hflag_slmv = FALSE;\n                     else {\n                         hflag_2 = hflag_slmv = explicit_h = TRUE;\n@@ -511,5 +575,5 @@\n                 case 'l':      /* longer form of \"ls -l\" type listing */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 5;\n@@ -517,5 +581,5 @@\n                 case 'm':      /* medium form of \"ls -l\" type listing */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 4;\n@@ -524,5 +588,5 @@\n                 case 'M':      /* send output through built-in \"more\" */\n                     if (negative)\n-                        G.M_flag = FALSE, negative = 0;\n+                        G.M_flag = FALSE;\n                     else\n                         G.M_flag = TRUE;\n@@ -531,5 +595,5 @@\n                 case 's':      /* default:  shorter \"ls -l\" type listing */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 3;\n@@ -537,5 +601,5 @@\n                 case 't':      /* totals line */\n                     if (negative)\n-                        tflag_2v = tflag_slm = FALSE, negative = 0;\n+                        tflag_2v = tflag_slm = FALSE;\n                     else {\n                         tflag_2v = tflag_slm = explicit_t = TRUE;\n@@ -546,5 +610,5 @@\n                 case ('T'):    /* use (sortable) decimal time format */\n                     if (negative)\n-                        uO.T_flag = FALSE, negative = 0;\n+                        uO.T_flag = FALSE;\n                     else\n                         uO.T_flag = TRUE;\n@@ -552,8 +616,7 @@\n #ifdef UNICODE_SUPPORT\n                 case ('U'):    /* escape UTF-8, or disable UTF-8 support */\n-                    if (negative) {\n-                        uO.U_flag = MAX(uO.U_flag-negative,0);\n-                        negative = 0;\n-                    } else\n+                    if (negative)\n+                        uO.U_flag = MAX(uO.U_flag - 1, 0);\n+                    else\n                         uO.U_flag++;\n                     break;\n@@ -561,5 +624,5 @@\n                 case 'v':      /* turbo-verbose listing */\n                     if (negative)\n-                        uO.lflag = -2, negative = 0;\n+                        uO.lflag = -2;\n                     else\n                         uO.lflag = 10;\n@@ -568,12 +631,36 @@\n                 case ('W'):    /* Wildcard interpretation (stop at '/'?) */\n                     if (negative)\n-                        uO.W_flag = FALSE, negative = 0;\n+                        uO.W_flag = FALSE;\n                     else\n                         uO.W_flag = TRUE;\n                     break;\n #endif /* WILD_STOP_AT_DIR */\n+                case ('x'):    /* extract:  default */\n+                    /* add -x file to linked list */\n+\n+                    if (in_xfiles_count == 0) {\n+                        /* first entry */\n+                        if ((in_xfiles = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {\n+                            Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+                            return PK_MEM;\n+                        }\n+                        in_xfiles->name = value;\n+                        in_xfiles->next = NULL;\n+                        next_in_xfiles = in_xfiles;\n+                    } else {\n+                        /* add next entry */\n+                        if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {\n+                            Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+                            return PK_MEM;\n+                        }\n+                        next_in_xfiles->next = next_file;\n+                        next_file->name = value;\n+                        next_file->next = NULL;\n+                        next_in_xfiles = next_file;\n+                    }\n+                    in_xfiles_count++;\n                 case 'z':      /* print zipfile comment */\n                     if (negative)\n-                        uO.zflag = negative = 0;\n+                        uO.zflag = 0;\n                     else\n                         uO.zflag = 1;\n@@ -581,13 +668,96 @@\n                 case 'Z':      /* ZipInfo mode:  ignore */\n                     break;\n+                case o_NON_OPTION_ARG:\n+                    /* not an option */\n+                    /* no more options as permuting */\n+\n+\n+                    if (G.wildzipfn == NULL) {\n+                        /* first non-option argument is zip file */\n+                        G.wildzipfn = value;\n+\n+                    } else {\n+                        /* add include file to list */\n+                        if (in_files_count == 0) {\n+                            /* first entry */\n+                            if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {\n+                                Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+                                return PK_MEM;\n+                            }\n+                            next_file->name = value;\n+                            next_file->next = NULL;\n+                            in_files = next_file;\n+                            next_in_files = next_file;\n+                        } else {\n+                            /* add next entry */\n+                            if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {\n+                                Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+                                return PK_MEM;\n+                            }\n+                            next_in_files->next = next_file;\n+                            next_file->name = value;\n+                            next_file->next = NULL;\n+                            next_in_files = next_file;\n+                        }\n+                        in_files_count++;\n+                    }\n+                    break;\n                 default:\n                     error = TRUE;\n                     break;\n-            }\n-        }\n+        } /* switch */\n+    } /* get_option() */\n+\n+    /* convert files and xfiles lists to arrays */\n+\n+    /* convert files list to array */\n+    if (in_files_count) {\n+      if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))) == NULL) {\n+          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+          return PK_MEM;\n+      }\n+      file_count = 0;\n+      for (next_file = in_files; next_file;) {\n+          G.pfnames[file_count] = next_file->name;\n+          in_files = next_file;\n+          next_file = next_file->next;\n+          free(in_files);\n+          file_count++;\n+      }\n+      G.pfnames[file_count] = NULL;\n+      G.filespecs = in_files_count;\n+    }\n+\n+    /* convert xfiles list to array */\n+    if (in_xfiles_count) {\n+      if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))) == NULL) {\n+          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));\n+          return PK_MEM;\n+      }\n+      file_count = 0;\n+      for (next_file = in_xfiles; next_file;) {\n+          G.pxnames[file_count] = next_file->name;\n+          in_xfiles = next_file;\n+          next_file = next_file->next;\n+          free(in_xfiles);\n+          file_count++;\n+      }\n+      G.pxnames[file_count] = NULL;\n+      G.xfilespecs = in_xfiles_count;\n     }\n-    if ((argc-- == 0) || error) {\n+\n+    if (in_files_count || in_xfiles_count) {\n+        G.process_all_files = FALSE;\n+    } else {\n+        G.process_all_files = TRUE;      /* for speed */\n+    }\n+\n+    /* it's possible the arg count could have been changed by get_option() */\n+    argc = arg_count(args);\n+\n+    if ((G.wildzipfn == NULL) || error) {\n+        argc = -1;      /* tell the caller to stop processing */\n         *pargc = argc;\n-        *pargv = argv;\n+        *pargv = args;\n         return USAGE(error);\n     }\n@@ -628,5 +798,5 @@\n \n     *pargc = argc;\n-    *pargv = argv;\n+    *pargv = args;\n     return 0;\n \n"
  },
  {
    "path": "deps/infozip/unzip60/os2/Contents",
    "content": "Contents of the \"os2\" subdirectory for UnZip 5.3 and later:\n\n  Contents      this file\n  makefile.os2  makefile for almost every compiler available under OS/2\n  os2.c         OS/2-specific support routines\n  os2data.h     OS/2-specific data declarations\n  os2cfg.h      OS/2-specific configuration, included in unzpriv.h\n  os2acl.c      OS/2-specific routines for access-control-list support\n  os2acl.h      OS/2-specific header file for access-control-list support\n  rexxapi.c     interface to integrate UnZip DLL in REXX API\n  rexxapi.def   OS/2 linker definition file for REXX API DLL\n  rexxhelp.c    help function for UnZip's REXX API DLL\n  rexxtest.cmd  REXX script for testing UnZip's REXX API DLL\n  stub.def      OS/2 linker definition file (generic UnZip DLL API)\n  unzip.def     OS/2 linker definition file\n  zip2exe.cmd   REXX script for creating self-extracting archives\n  zipgrep.cmd   really cool REXX script to search for strings in a zipfile\n  zgrepapi.cmd  new version of zipgrep.cmd; takes advantage of REXX API DLL\n\nThere is no support for the ancient Zortech and GCC/2 (Michael Johnson/Colin\nJensen) compilers.  The free emx+gcc is supported, as are roughly half a dozen\ncommercial compilers.\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/makefile.os2",
    "content": "# Makefile for UnZip, UnZipSFX and fUnZip                     03 January 2007\n#\n#  supported compilers:\n#  - Microsoft C, version 6.00 or higher, for use under OS/2 1.x (16-bit)\n#  - Watcom C/C++, version 9.0+, for use under OS/2 1.x or 2.x+ (16/32-bit)\n#  - emx+gcc, version 0.9c or higher, for use under OS/2 2.x+ (32-bit)\n#  - IBM C Set++, for use under OS/2 2.x+ (32-bit)\n#  - Borland C++, for use under OS/2 2.x+ (32-bit)\n#  - Metaware High C/C++, for use under OS/2 2.x+ (32-bit)\n#\n#  supported cross-compilers:\n#  - Microsoft C, version 6.0 or 7.0, for use under DOS (16-bit)\n#  - Watcom C/C++, version 9.0+, for use under DOS/Win95/NT (16/32-bit)\n#  - GNU gcc (emx), version 0.9c or higher, for use under DOS/Win95/NT (32-bit)\n#\n#  supported assemblers:\n#  - Microsoft MASM 6.00 with Microsoft C\n#  - Watcom WASM with Watcom C/C++\n#  - GNU as with GNU gcc\n\n# To use MASM 5.x instead of MASM 6.00:\n#  - set AS=\"masm -t -Ml\"\n#  - set ASEOL=\";\"\n\n# To use, enter \"{d,n}make -f os2/makefile.os2\" (this makefile depends on its\n# name being \"makefile.os2\", and it must be in the os2 subdirectory).\n\n# In case you want to use Watcom wmake instead, you have to switch wmake into\n# the \"MS nmake compatible\" mode by specifying the \"-ms\" option. Additionally,\n# it is required to override the MAKE macro definition for the recursive\n# invokation of wmake. An example:\n#   wmake -ms -f os2/makefile.os2 MAKE=\"wmake -ms\" watcom\n\n# Notes on Microsoft C 6.00 compilation for OS/2:\n#\n#   The resulting programs can be used under OS/2 protected mode only, not\n#   under DOS.  A larger stack has to be used for OS/2 because system calls\n#   use more stack than under DOS; 8k is recommended by Microsoft.\n\n# Notes on IBM C Set++, Watcom C/C++, Borland C++ or emx+gcc compilation:\n#\n#   The resulting programs can be used under protected mode of OS/2 2.x or\n#   higher only, not under OS/2 1.x and not under DOS.\n#\n#   The NFLAGS macro is used to work around an optimization bug in the IBM\n#   C++ Set compiler; this is fixed by CSD #4, so NFLAGS=\"\" can be used for\n#   all targets below.\n\n# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:\n#\n#   You need to add the following section to your \\watcom\\binb\\wlsystem.lnk\n#   file and also need to copy pmodew.exe to the same directory:\n#\n#   system begin pmodew\n#       option osname='PMODE/W'\n#       libpath %WATCOM%\\lib386\n#       libpath %WATCOM%\\lib386\\dos\n#       op stub=pmodew.exe\n#       format os2 le\n#   end\n#\n#   PMODE/W 1.16 or higher is required.  See also msdos/README for important\n#   notes about PMODE/W bugs.\n\ndefault:\n\t@echo \"Enter `$(MAKE) -f os2/makefile.os2 target' from the main\"\n\t@echo \"UnZip directory, where target is one of:\"\n\t@echo \"   msc mscdebug mscdos ibm ibmdyn ibmdebug ibmprof\"\n\t@echo \"   ibmdll ibmdyndll ibmdebugdll ibmprofdll\"\n\t@echo \"   metaware borland gcc gccdyn gccdebug gccdos gccwin32\"\n\t@echo \"   watcom watcom16 watcomdos watcom16dos pmodew watcomwin32\"\n\n# MS C 6.00 for OS/2, 16-bit (should figure out way to split unzip/funzip\n# compiles so former is always large model and latter always small model...)\nmsc:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"cl -nologo -AL -Ocegit -Gs -I. $(FP)\" \\\n\tCFLAGS=\"-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"-D__LARGE__ -D__286\" \\\n\tLDFLAGS=\"-F 2000 -Lp -Fe\" \\\n\tLDFLAGS2=\"-link /noe\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJF2=\"os2f.obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# MS C 6.00 for OS/2, debug version\nmscdebug:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"cl -nologo -AL -Zi -Od -I. $(FP)\" \\\n\tCFLAGS=\"-G2 -Zp1 -W3 -DOS2 -DMSC -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"ml -nologo -c -Zim -Cp\" \\\n\tASFLAGS=\"-D__LARGE__ -D__286\" \\\n\tLDFLAGS=\"-F 2000 -Lp -Fe\" \\\n\tLDFLAGS2=\"-link /noe\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJF2=\"os2f.obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# cross-compilation for MS-DOS with MS C 6.00 (same comment as above...formerly;\n# now unzip is large model again, because of DEFLATE_64 support)\nmscdos:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"cl -nologo -AL -Oaict -Gs -I. $(FP)\" \\\n\tCFLAGS=\"-Zp1 -W3 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"-D__LARGE__\" \\\n\tLDFLAGS=\"-F 0C00 -Lr -Fe\" \\\n\tLDFLAGS2=\"-link /noe /exe\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86\" \\\n\tOBJU2=\"msdos.obj\" \\\n\tOBJX2=\"msdos_.obj\" \\\n\tOBJF2=\"msdosf.obj\" \\\n\tOSDEP_H=\"msdos/doscfg.h\"\n\n# IBM C Set, statically linked runtime\nibm:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"icc -Q -O -Gs -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# IBM C Set, dynamically linked runtime\nibmdyn:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"icc -Q -O -Gs -Gd -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# IBM C Set, debug version\nibmdebug:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"icc -Q -Ti -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# IBM C Set, profiling version for PROFIT\nibmprof:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"icc -Q -O -Gs -Gh -Ti -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"cppopa3.obj\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"os2\\unzip.def\"\n\n# IBM C Set, statically linked runtime\nibmdll:\n\t$(MAKE) -f os2/makefile.os2 dll \\\n\tCC=\"icc -Q -O -Gs -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC\" \\\n\tLDFLAGS=\"-Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDLLDEF=\"os2\\rexxapi.def\" \\\n\tSTUBDEF=\"os2\\stub.def\" \\\n\tDEF=\"os2\\unzip.def\" \\\n\tAPILIB=\"REXX.lib\"\n\n# IBM C Set, dynamically linked runtime\nibmdyndll:\n\t$(MAKE) -f os2/makefile.os2 dll \\\n\tCC=\"icc -Q -O -Gs -Gd -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC\" \\\n\tLDFLAGS=\"-Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDLLDEF=\"os2\\rexxapi.def\" \\\n\tSTUBDEF=\"os2\\stub.def\" \\\n\tDEF=\"os2\\unzip.def\" \\\n\tAPILIB=\"REXX.lib\"\n\n# IBM C Set, debug version\nibmdebugdll:\n\t$(MAKE) -f os2/makefile.os2 dll \\\n\tCC=\"icc -Q -Ti -I.\" \\\n\tCFLAGS=\"-Sm -Sp1 -D__DEBUG_ALLOC__ -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC\" \\\n\tLDFLAGS=\"-Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDLLDEF=\"os2\\rexxapi.def\" \\\n\tSTUBDEF=\"os2\\stub.def\" \\\n\tDEF=\"os2\\unzip.def\" \\\n\tAPILIB=\"REXX.lib\"\n\n# IBM C Set, profiling version for PROFIT\nibmprofdll:\n\t$(MAKE) -f os2/makefile.os2 dll \\\n\tCC=\"icc -Q -O -Gs -Gh -Ti -I.\" \\\n\tCFLAGS=\"-Gm -Sm -Sp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"-Gm -Ge- -DDLL -DOS2DLL -DAPI_DOC\" \\\n\tLDFLAGS=\"-Fe\" \\\n\tLDFLAGS2=\"profit.obj\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tDLLDEF=\"os2\\rexxapi.def\" \\\n\tSTUBDEF=\"os2\\stub.def\" \\\n\tDEF=\"os2\\unzip.def\" \\\n\tAPILIB=\"REXX.lib\"\n\n# Watcom C/386 9.0 or higher\nwatcom:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl386 -bt=os2v2 -zq -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DOS2 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=os2v2 -zq -3 -mf\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=os2v2 -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tDEF=\"\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/286 9.0 or higher\nwatcom16:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl -bt=os2 -zq -ml -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=os2 -zq -2 -ml\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x2000 -x -l=os2 -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJF2=\"os2f.obj\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender\nwatcomdos:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl386 -bt=dos4g -zq -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=dos4g -zq -3 -mf\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=dos4g -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tOBJU2=\"msdos.obj\" \\\n\tOBJX2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/doscfg.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender\npmodew:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl386 -bt=dos4g -zq -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DMSDOS -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=dos4g -zq -3 -mf\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=pmodew -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tOBJU2=\"msdos.obj\" \\\n\tOBJX2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/doscfg.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/286 9.0 or higher, crosscompilation for DOS\nwatcom16dos:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl -bt=dos -zq -ml -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DMSDOS $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=dos -0 -ml\" \\\n\tASFLAGS=\"-D__LARGE__\" \\\n\tLDFLAGS=\"-k0xC00 -x -l=dos -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJU2=\"msdos.obj\" \\\n\tOBJX2=\"msdos_.obj\" \\\n\tOBJF2=\"msdosf.obj\" \\\n\tOSDEP_H=\"msdos/doscfg.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/386 9.0 or higher, crosscompilation for Win95/NT\nwatcomwin32:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"wcl386 -bt=NT -zq -Ox -s -I.\" \\\n\tCFLAGS=\"-Zp1 -DWIN32 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"wasm -bt=NT -zq -3 -mf\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=NT -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tOBJU2=\"win32.obj nt.obj\" \\\n\tOBJX2=\"win32_.obj nt_.obj\" \\\n\tOBJF2=\"win32f.obj\" \\\n\tDEF=\"\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# MetaWare High C/C++ 3.2\nmetaware:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"hc -O2 -I.\" \\\n\tCFLAGS=\"-D__32BIT__ -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-o \" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-o ./\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"-Hdef=os2\\unzip.def\"\n\n# Borland C++\nborland:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"bcc -O -I. -Ios2\" \\\n\tCFLAGS=\"-w- -D__cdecl -D__32BIT__ -DOS2 $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tLDFLAGS=\"-e\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"-sDos2\\unzip.def\"\n\n# emx, gcc, OMF format, statically linked C runtime\ngcc:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"gcc -Zomf -O -I.\" \\\n\tCFLAGS=\"-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"gcc -Zomf\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zsmall-conv -Zstack 320 -Zsys -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_gcc.obj\" \\\n\tDEF=\"os2/unzip.def\"\n\n# emx, gcc, OMF format, dynamically linked C runtime\ngccdyn:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"gcc -Zomf -O -I.\" \\\n\tCFLAGS=\"-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"gcc -Zomf\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zstack 320 -Zcrtdll -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_gcc.obj\" \\\n\tDEF=\"os2/unzip.def\"\n\n# emx, gcc, a.out format, with debug info for gdb\ngccdebug:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"gcc -g -I.\" \\\n\tCFLAGS=\"-Wall -DOS2 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"gcc -g\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\n# emx, gcc, a.out format, cross-compilation for MS-DOS\ngccdos:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"gcc -O -I.\" \\\n\tCFLAGS=\"-Wall -DMSDOS -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zsmall-conv -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJU2=\"msdos.o\" \\\n\tOBJX2=\"msdos_.o\" \\\n\tOSDEP_H=\"msdos/doscfg.h\"\n\n# emx, gcc, RSXNT, cross-compilation for Win32, statically linked C runtime\ngccwin32:\n\t$(MAKE) -f os2/makefile.os2 all \\\n\tCC=\"gcc -Zwin32 -O2 -I.\" \\\n\tCFLAGS=\"-Wall -DWIN32 -DASM_CRC $(LOCAL_UNZIP)\" \\\n\tNFLAGS=\"\" \\\n\tDLLFLAG=\"\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-Zsys -o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -Zsmall-conv -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJU2=\"win32.o nt.o\" \\\n\tOBJX2=\"win32_.o nt_.o\" \\\n\tOBJF2=\"win32f.o\" \\\n\tOSDEP_H=\"win32/w32cfg.h\"\n\n# variables\n\n# LOCAL_UNZIP = -DREENTRANT\n\n# default settings for target dependent macros:\nDIRSEP = /\nAS_DIRSEP = /\n\nOSDEP_H = os2/os2data.h os2/os2cfg.h\nCRCA_O  =\n\nOBJU  = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ) \\\n\texplode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) \\\n\tinflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) \\\n\tubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)\nOBJU2 = os2$(OBJ) os2acl$(OBJ)\nOBJX  = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_O) crypt_$(OBJ) \\\n        extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ) \\\n\tmatch_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ)\nOBJX2 = os2_$(OBJ) os2acl_$(OBJ)\nOBJDLL= api$(OBJ) apihelp$(OBJ) rexxhelp$(OBJ) rexxapi$(OBJ)\nOBJF  = funzip$(OBJ) crc32f$(OBJ) $(CRCA_O) cryptf$(OBJ) inflatef$(OBJ) \\\n\tglobalsf$(OBJ) ttyiof$(OBJ)\nOBJF2 =\n\nUNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES:\t.c .asm $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $<\n\n.asm$(OBJ):\n\t$(AS) $(ASFLAGS) $< $(ASEOL)\n\n# targets\n\nall:\tunzip.exe funzip.exe unzipsfx.exe\ndll:\tunzip32.dll unzip.stb funzip.exe unzipsfx.exe\n\nunzip.exe: $(OBJU) $(OBJU2)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJU) $(OBJU2) $(LDFLAGS2)\n\nfunzip.exe: $(OBJF) $(OBJF2)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(OBJF2) $(LDFLAGS2)\n\nunzipsfx.exe:\t$(OBJX) $(OBJX2)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJX) $(OBJX2) $(LDFLAGS2)\n\nunzip32.dll: $(DLLDEF) $(OBJU) $(OBJU2) $(OBJDLL)\n\t$(CC) $(DLLFLAG) $(LDFLAGS)$@ $(DLLDEF) $(OBJU) $(OBJDLL) $(OBJU2) $(APILIB) $(LDFLAGS2)\n\nunzip.stb: unzipstb$(OBJ) $(STUBDEF)\n\t$(CC) $(LDFLAGS)$@ $(STUBDEF) unzipstb$(OBJ) $(LDFLAGS2)\n\tcopy unzip.stb unzip.exe\n\n# dependencies\n\napihelp$(OBJ):\tapihelp.c $(UNZIP_H) unzvers.h\ncrc32$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\nenvargs$(OBJ):\tenvargs.c $(UNZIP_H)\nexplode$(OBJ):\texplode.c $(UNZIP_H)\nextract$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\nfileio$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(OBJ):\tglobals.c $(UNZIP_H)\ninflate$(OBJ):\tinflate.c $(UNZIP_H)\nlist$(OBJ):\tlist.c $(UNZIP_H)\nmatch$(OBJ):\tmatch.c $(UNZIP_H)\nprocess$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\nttyio$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OBJ):\tubz2err.c $(UNZIP_H)\nunreduce$(OBJ):\tunreduce.c $(UNZIP_H)\nunshrink$(OBJ):\tunshrink.c $(UNZIP_H)\nunzip$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\napi$(OBJ):\tapi.c $(UNZIP_H) unzvers.h\nzipinfo$(OBJ):\tzipinfo.c $(UNZIP_H)\n\nunzipstb$(OBJ):\tunzipstb.c\t\t\t\t\t# DLL version\n\t$(CC) -c $(CFLAGS) unzipstb.c\n\nmsdos$(OBJ):\tmsdos/msdos.c $(UNZIP_H) unzvers.h\t\t# DOS only\n\t$(CC) -c $(CFLAGS) msdos$(DIRSEP)msdos.c\n\nmsdos_$(OBJ):\tmsdos/msdos.c $(UNZIP_H)\t\t\t# DOS unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nmsdosf$(OBJ):\tmsdos/msdos.c $(UNZIP_H)\t\t\t# DOS funzip\n\t$(CC) -c $(CFLAGS) -DFUNZII $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nwin32$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h unzvers.h\t# Win32 only\n\t$(CC) -c $(CFLAGS) win32$(DIRSEP)win32.c\n\nnt$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\t\t# Win32 only\n\t$(CC) -c $(CFLAGS) win32$(DIRSEP)nt.c\n\nwin32_$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\t\t# Win32 unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)win32.c\n\nnt_$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\t\t# Win32 unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ win32$(DIRSEP)nt.c\n\nwin32f$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\t\t# Win32 funzip\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ win32$(DIRSEP)win32.c\n\nos2$(OBJ):\tos2/os2.c $(UNZIP_H) unzvers.h\t\t\t# OS/2 only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2.c\n\nos2_$(OBJ):\tos2/os2.c $(UNZIP_H)\t\t\t\t# OS/2 unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2.c\n\nos2f$(OBJ):\tos2/os2.c $(UNZIP_H)\t\t\t\t# OS/2 funzip\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ os2$(DIRSEP)os2.c\n\nos2acl$(OBJ):\tos2/os2acl.c $(UNZIP_H) unzvers.h\t\t# OS/2 only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)os2acl.c\n\nos2acl_$(OBJ):\tos2/os2acl.c $(UNZIP_H) unzvers.h\t\t# OS/2 unzipsfx\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ os2$(DIRSEP)os2acl.c\n\nrexxhelp$(OBJ):\tos2/rexxhelp.c\t\t\t\t\t# OS/2 DLL only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxhelp.c\n\nrexxapi$(OBJ):\tos2/rexxapi.c\t\t\t\t\t# OS/2 DLL only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) os2$(DIRSEP)rexxapi.c\n\ncrc_i86$(OBJ):\tmsdos/crc_i86.asm\t\t\t\t# 16bit only\n\t$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)\n\ncrc_i386$(OBJ):\twin32/crc_i386.asm\t\t\t\t# 32bit, MASM\n\t$(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)\n\ncrc_gcc$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\n# NFLAGS are solely used as work-around for optimization bug in IBM C++ Set\ncrypt$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(NFLAGS) crypt.c\n\n# funzip compilation section\nfunzip$(OBJ):\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) funzip.c\n\ncrc32f$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ crc32.c\n\ncryptf$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ crypt.c\n\nglobalsf$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ globals.c\n\ninflatef$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP $(OUT)$@ inflate.c\n\nttyiof$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(NFLAGS) -DFUNZIP $(OUT)$@ ttyio.c\n\n# unzipsfx compilation section\ncrc32_$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ crypt.c\n\nextract_$(OBJ):\textract.c $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ extract.c\n\nfileio_$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ fileio.c\n\nglobals_$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ globals.c\n\ninflate_$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ inflate.c\n\nmatch_$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ match.c\n\nprocess_$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ process.c\n\nttyio_$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ttyio.c\n\nubz2err_$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ ubz2err.c\n\nunzipsf_$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS) -DSFX $(OUT)$@ unzip.c\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/os2.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  os2.c\n\n  OS/2-specific routines for use with Info-ZIP's UnZip 5.1 and later.\n\n  This file contains the OS/2 versions of the file name/attribute/time/etc\n  code.  Most or all of the routines which make direct use of OS/2 system\n  calls (i.e., the non-lowercase routines) are Kai Uwe Rommel's.  The read-\n  dir() suite was written by Michael Rendell and ported to OS/2 by Kai Uwe;\n  it is in the public domain.\n\n  Contains:  GetCountryInfo()\n             SetFileSize()\n             GetFileTime()\n             SetFileTime()              (TIMESTAMP only)\n             stamp_file()               (TIMESTAMP only)\n             Utime2DosDateTime()\n             SetPathAttrTimes()\n             SetEAs()\n             GetLoadPath()\n             opendir()\n             closedir()\n             readdir()\n             [ seekdir() ]             not used\n             [ telldir() ]             not used\n             free_dircontents()\n             getdirent()\n             IsFileSystemFAT()\n             do_wild()\n             mapattr()\n             mapname()\n             checkdir()\n             isfloppy()\n             IsFileNameValid()\n             map2fat()\n             SetLongNameEA()\n             close_outfile()\n             check_for_newer()\n             dateformat()\n             version()\n             zcalloc()                      (16-bit, only)\n             zcfree()                       (16-bit, only)\n             InitNLS()\n             IsUpperNLS()\n             ToLowerNLS()\n             StringLower()\n             screensize()\n             DebugMalloc()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n/* fUnZip does not need anything from here except the zcalloc() & zcfree()\n * function pair (when Deflate64 support is enabled in 16-bit environment).\n */\n#ifndef FUNZIP\n\n#include \"os2acl.h\"\n\nextern ZCONST char Far TruncEAs[];\n\n/* local prototypes */\n\n#ifdef TIMESTAMP\n  static int SetFileTime(ZCONST char *name, ulg stamp);\n#endif\n#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)\n  static ulg Utime2DosDateTime  OF((time_t uxtime));\n#endif\nstatic int   getOS2filetimes    OF((__GPRO__\n                                    ulg *pM_dt, ulg *pA_dt, ulg *pC_dt));\nstatic void  SetPathAttrTimes   OF((__GPRO__ int flags, int dir));\nstatic int   SetEAs             OF((__GPRO__ const char *path,\n                                    void *ef_block));\nstatic int   SetACL             OF((__GPRO__ const char *path,\n                                    void *ef_block));\nstatic int   EvalExtraFields    OF((__GPRO__ const char *path,\n                                    void *extra_field, unsigned ef_len));\nstatic int   isfloppy           OF((int nDrive));\nstatic int   IsFileNameValid    OF((const char *name));\nstatic void  map2fat            OF((char *pathcomp, char **pEndFAT));\nstatic int   SetLongNameEA      OF((char *name, char *longname));\nstatic void  InitNLS            OF((void));\n\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\n\n/*****************************/\n/*  Strings used in os2.c  */\n/*****************************/\n\n#ifndef SFX\n  static ZCONST char Far CantAllocateWildcard[] =\n    \"warning:  cannot allocate wildcard buffers\\n\";\n#endif\nstatic ZCONST char Far WarnDirTraversSkip[] =\n  \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\";\nstatic ZCONST char Far Creating[] = \"   creating: %-22s \";\nstatic ZCONST char Far ConversionFailed[] =\n  \"mapname:  conversion of %s failed\\n\";\nstatic ZCONST char Far Labelling[] = \"labelling %c: %-22s\\n\";\nstatic ZCONST char Far ErrSetVolLabel[] =\n  \"mapname:  error setting volume label\\n\";\nstatic ZCONST char Far PathTooLong[] = \"checkdir error:  path too long: %s\\n\";\nstatic ZCONST char Far CantCreateDir[] = \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far DirIsntDirectory[] =\n  \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\";\nstatic ZCONST char Far PathTooLongTrunc[] =\n  \"checkdir warning:  path too long; truncating\\n                   %s\\n\\\n                -> %s\\n\";\n#if (!defined(SFX) || defined(SFX_EXDIR))\n   static ZCONST char Far CantCreateExtractDir[] =\n     \"checkdir:  cannot create extraction directory: %s\\n\";\n#endif\n\n#ifndef __GNUC__\n   /* all supported non-gcc compilers provide MSC/DOS style mkdir() */\n#  if (_MSC_VER >= 600) || defined(__IBMC__)\n#    include <direct.h>          /* have special MSC/IBM C mkdir prototype */\n#  else                          /* own prototype because dir.h conflicts? */\n     int mkdir(const char *path);\n#  endif\n#  define MKDIR(path,mode)   mkdir(path)\n#else\n    /* EMX and hopefully all other gcc ports support POSIX style mkdir() */\n#  define MKDIR(path,mode)   mkdir(path,mode)\n#endif\n\n\n#ifdef __32BIT__\n\nUSHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,\n                     USHORT usFunction, USHORT usCategory, HFILE hDevice)\n{\n  ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;\n  return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction,\n                              pParms, cbParms, &ulParmLengthInOut,\n                              pData, cbData, &ulDataLengthInOut);\n}\n\n#  define DosDevIOCtl DosDevIOCtl32\n#else\n#  define DosDevIOCtl DosDevIOCtl2\n#endif\n\n\ntypedef struct\n{\n  ush nID;\n  ush nSize;\n  ulg lSize;\n}\nEFHEADER, *PEFHEADER;\n\n\n#ifdef __32BIT__\n\n#define DosFindFirst(p1, p2, p3, p4, p5, p6) \\\n        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)\n\n#else\n\ntypedef struct\n{\n  ULONG oNextEntryOffset;\n  BYTE fEA;\n  BYTE cbName;\n  USHORT cbValue;\n  CHAR szName[1];\n}\nFEA2, *PFEA2;\n\ntypedef struct\n{\n  ULONG cbList;\n  FEA2 list[1];\n}\nFEA2LIST, *PFEA2LIST;\n\n#define DosQueryCurrentDisk DosQCurDisk\n#define DosQueryFSAttach(p1, p2, p3, p4, p5) \\\n        DosQFSAttach(p1, p2, p3, p4, p5, 0)\n#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \\\n        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)\n#define DosFindFirst(p1, p2, p3, p4, p5, p6) \\\n        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)\n#define DosMapCase DosCaseMap\n#define DosSetPathInfo(p1, p2, p3, p4, p5) \\\n        DosSetPathInfo(p1, p2, p3, p4, p5, 0)\n#define DosQueryPathInfo(p1, p2, p3, p4) \\\n        DosQPathInfo(p1, p2, p3, p4, 0)\n#define DosQueryFileInfo DosQFileInfo\n#define DosMapCase DosCaseMap\n#define DosQueryCtryInfo DosGetCtryInfo\n\n#endif /* !__32BIT__ */\n\n\n\n\n\n/*\n * @(#) dir.h 1.4 87/11/06   Public Domain.\n */\n\n#define A_RONLY    0x01\n#define A_HIDDEN   0x02\n#define A_SYSTEM   0x04\n#define A_LABEL    0x08\n#define A_DIR      0x10\n#define A_ARCHIVE  0x20\n\n\nconst int attributes = A_DIR | A_HIDDEN | A_SYSTEM;\n\n\nextern DIR *opendir(__GPRO__ ZCONST char *);\nextern struct direct *readdir(__GPRO__ DIR *);\nextern void seekdir(DIR *, long);\nextern long telldir(DIR *);\nextern void closedir(DIR *);\n#define rewinddir(dirp) seekdir(dirp, 0L)\n\nint IsFileSystemFAT(__GPRO__ ZCONST char *dir);\nchar *StringLower(char *szArg);\n\n\n\n\n/*\n * @(#)dir.c 1.4 87/11/06 Public Domain.\n */\n\n\n#ifndef S_IFMT\n#  define S_IFMT 0xF000\n#endif\n\n\n#ifndef SFX\n   static char *getdirent(__GPRO__ ZCONST char *);\n   static void free_dircontents(struct _dircontents *);\n#endif /* !SFX */\n\n\n\n\nint GetCountryInfo(void)\n{\n    COUNTRYINFO ctryi;\n    COUNTRYCODE ctryc;\n#ifdef __32BIT__\n    ULONG cbInfo;\n#else\n    USHORT cbInfo;\n#endif\n\n  ctryc.country = ctryc.codepage = 0;\n\n  if ( DosQueryCtryInfo(sizeof(ctryi), &ctryc, &ctryi, &cbInfo) != NO_ERROR )\n    return 0;\n\n  return ctryi.fsDateFmt;\n}\n\n\nint SetFileSize(FILE *file, ulg filesize)\n{\n#ifdef __32BIT__\n  return DosSetFileSize(fileno(file), (size_t)filesize) ? -1 : 0;\n#else\n  return 0;\n#endif\n}\n\n\nlong GetFileTime(ZCONST char *name)\n{\n#ifdef __32BIT__\n  FILESTATUS3 fs;\n#else\n  FILESTATUS fs;\n#endif\n  USHORT nDate, nTime;\n\n  if ( DosQueryPathInfo((PSZ) name, 1, (PBYTE) &fs, sizeof(fs)) )\n    return -1;\n\n  nDate = * (USHORT *) &fs.fdateLastWrite;\n  nTime = * (USHORT *) &fs.ftimeLastWrite;\n\n  return ((ULONG) nDate) << 16 | nTime;\n}\n\n\n#ifdef TIMESTAMP\n\nstatic int SetFileTime(ZCONST char *name, ulg stamp)   /* swiped from Zip */\n{\n  FILESTATUS fs;\n  USHORT fd, ft;\n\n  if (DosQueryPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))\n    return -1;\n\n  fd = (USHORT) (stamp >> 16);\n  ft = (USHORT) stamp;\n  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;\n  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;\n\n  if (DosSetPathInfo((PSZ) name, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0))\n    return -1;\n\n  return 0;\n}\n\n\nint stamp_file(ZCONST char *fname, time_t modtime)\n{\n    return SetFileTime(fname, Utime2DosDateTime(modtime));\n}\n\n#endif /* TIMESTAMP */\n\n\n/* The following DOS date/time structures are machine-dependent as they\n * assume \"little-endian\" byte order.  For OS/2-specific code, which\n * is run on x86 CPUs (or emulators?), this assumption is valid; but\n * care should be taken when using this code as template for other ports.\n */\ntypedef union {\n  ULONG timevalue;          /* combined value, useful for comparisons */\n  struct {\n    FTIME ft;               /* system file time record:\n                             *    USHORT twosecs : 5\n                             *    USHORT minutes : 6;\n                             *    USHORT hours   : 5;   */\n    FDATE fd;               /* system file date record:\n                             *    USHORT day     : 5\n                             *    USHORT month   : 4;\n                             *    USHORT year    : 7;   */\n  } _fdt;\n} F_DATE_TIME, *PF_DATE_TIME;\n\n\n#if defined(USE_EF_UT_TIME) || defined(TIMESTAMP)\n\nstatic ulg Utime2DosDateTime(uxtime)\n    time_t uxtime;\n{\n    F_DATE_TIME dosfiletime;\n    struct tm *t;\n\n    /* round up to even seconds */\n    /* round up (down if \"up\" overflows) to even seconds */\n    if (((ulg)uxtime) & 1)\n        uxtime = (uxtime + 1 > uxtime) ? uxtime + 1 : uxtime - 1;\n\n    t = localtime(&(uxtime));\n    if (t == (struct tm *)NULL) {\n        /* time conversion error; use current time instead, hoping\n           that localtime() does not reject it as well! */\n        time_t now = time(NULL);\n        t = localtime(&now);\n    }\n    if (t->tm_year < 80) {\n        dosfiletime._fdt.ft.twosecs = 0;\n        dosfiletime._fdt.ft.minutes = 0;\n        dosfiletime._fdt.ft.hours   = 0;\n        dosfiletime._fdt.fd.day     = 1;\n        dosfiletime._fdt.fd.month   = 1;\n        dosfiletime._fdt.fd.year    = 0;\n    } else {\n        dosfiletime._fdt.ft.twosecs = t->tm_sec >> 1;\n        dosfiletime._fdt.ft.minutes = t->tm_min;\n        dosfiletime._fdt.ft.hours   = t->tm_hour;\n        dosfiletime._fdt.fd.day     = t->tm_mday;\n        dosfiletime._fdt.fd.month   = t->tm_mon + 1;\n        dosfiletime._fdt.fd.year    = t->tm_year - 80;\n    }\n    return dosfiletime.timevalue;\n\n} /* end function Utime2DosDateTime() */\n\n#endif /* USE_EF_UT_TIME || TIMESTAMP */\n\n\nstatic int getOS2filetimes(__GPRO__ ulg *pM_dt, ulg *pA_dt, ulg *pC_dt)\n{\n#ifdef USE_EF_UT_TIME\n    unsigned eb_izux_flg;\n    iztimes z_utime;\n#endif\n\n    /* Copy and/or convert time and date variables, if necessary;   */\n    /* return a flag indicating which time stamps are available.    */\n#ifdef USE_EF_UT_TIME\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,\n          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n          &z_utime, NULL)) & EB_UT_FL_MTIME))\n    {\n        TTrace((stderr, \"getOS2filetimes: UT e.f. modif. time = %lu\\n\",\n                z_utime.mtime));\n        *pM_dt = Utime2DosDateTime(z_utime.mtime);\n        if (eb_izux_flg & EB_UT_FL_ATIME) {\n            TTrace((stderr, \"getOS2filetimes: UT e.f. access time = %lu\\n\",\n                    z_utime.atime));\n            *pA_dt = Utime2DosDateTime(z_utime.atime);\n        }\n        if (eb_izux_flg & EB_UT_FL_CTIME) {\n            TTrace((stderr, \"getOS2filetimes: UT e.f. creation time = %lu\\n\",\n                    z_utime.ctime));\n            *pC_dt = Utime2DosDateTime(z_utime.ctime);\n        } else {\n            /* no creation time value supplied, set it to modification time */\n            *pC_dt = *pM_dt;\n            eb_izux_flg |= EB_UT_FL_CTIME;\n        }\n        return (int)eb_izux_flg;\n    }\n#endif /* USE_EF_UT_TIME */\n    *pC_dt = *pM_dt = G.lrec.last_mod_dos_datetime;\n    TTrace((stderr, \"\\ngetOS2filetimes: DOS dir modific./creation time = %lu\\n\",\n            *pM_dt));\n    return (EB_UT_FL_MTIME | EB_UT_FL_CTIME);\n}\n\n\nstatic void SetPathAttrTimes(__GPRO__ int flags, int dir)\n{\n  HFILE hFile;\n#ifdef __32BIT__\n  ULONG nAction;\n#else\n  USHORT nAction;\n#endif\n  FILESTATUS fs;\n  USHORT nLength;\n  char szName[CCHMAXPATH];\n  ulg Mod_dt, Acc_dt, Cre_dt;\n  int gotTimes;\n\n  strcpy(szName, G.filename);\n  nLength = strlen(szName);\n  if (szName[nLength - 1] == '/')\n    szName[nLength - 1] = 0;\n\n  if (dir)\n  {\n    if ( DosQueryPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )\n      return;\n  }\n  else\n  {\n    /* for regular files, open them and operate on the file handle, to\n       work around certain network operating system bugs ... */\n\n    if ( DosOpen(szName, &hFile, &nAction, 0, 0,\n                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW,\n                 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, 0) )\n      return;\n\n    if ( DosQueryFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )\n      return;\n  }\n\n  if (uO.D_flag <= (dir ? 1 : 0)) {\n    /* set date/time stamps */\n    gotTimes = getOS2filetimes(__G__ &Mod_dt, &Acc_dt, &Cre_dt);\n    if (gotTimes & EB_UT_FL_MTIME) {\n      fs.fdateLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.fd;\n      fs.ftimeLastWrite = ((F_DATE_TIME *)&Mod_dt)->_fdt.ft;\n    }\n    if (gotTimes & EB_UT_FL_ATIME) {\n      fs.fdateLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.fd;\n      fs.ftimeLastAccess = ((F_DATE_TIME *)&Acc_dt)->_fdt.ft;\n    }\n    if (gotTimes & EB_UT_FL_CTIME) {\n      fs.fdateCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.fd;\n      fs.ftimeCreation = ((F_DATE_TIME *)&Cre_dt)->_fdt.ft;\n    }\n  }\n\n  if ( flags != -1 )\n    fs.attrFile = flags; /* hidden, system, archive, read-only */\n\n  if (dir)\n  {\n    DosSetPathInfo(szName, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);\n  }\n  else\n  {\n    DosSetFileInfo(hFile, FIL_STANDARD, (PBYTE) &fs, sizeof(fs));\n    DosClose(hFile);\n  }\n}\n\n\ntypedef struct\n{\n  ULONG cbList;               /* length of value + 22 */\n#ifdef __32BIT__\n  ULONG oNext;\n#endif\n  BYTE fEA;                   /* 0 */\n  BYTE cbName;                /* length of \".LONGNAME\" = 9 */\n  USHORT cbValue;             /* length of value + 4 */\n  BYTE szName[10];            /* \".LONGNAME\" */\n  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */\n  USHORT eaSize;              /* length of value */\n  BYTE szValue[CCHMAXPATH];\n}\nFEALST;\n\n\nstatic int SetEAs(__GPRO__ const char *path, void *ef_block)\n{                                               /* returns almost-PK errors */\n  EFHEADER *pEAblock = (PEFHEADER) ef_block;\n#ifdef __32BIT__\n  EAOP2 eaop;\n  PFEA2LIST pFEA2list;\n#else\n  EAOP eaop;\n  PFEALIST pFEAlist;\n  PFEA pFEA;\n  PFEA2LIST pFEA2list;\n  PFEA2 pFEA2;\n  ULONG nLength2;\n#endif\n  USHORT nLength;\n  char szName[CCHMAXPATH];\n  int error;\n\n  if ( ef_block == NULL || pEAblock -> nID != EF_OS2 )\n    return PK_OK;  /* not an OS/2 extra field:  assume OK */\n\n  if ( pEAblock->nSize < 4 || (pEAblock->lSize > 0L && pEAblock->nSize <= 10) )\n    return IZ_EF_TRUNC;  /* no compressed data! */\n\n  strcpy(szName, path);\n  nLength = strlen(szName);\n  if (szName[nLength - 1] == '/')\n    szName[nLength - 1] = 0;\n\n  if ( (pFEA2list = (PFEA2LIST) malloc((size_t) pEAblock -> lSize)) == NULL )\n    return PK_MEM4;\n\n  if ( (error = memextract(__G__ (uch *)pFEA2list, pEAblock->lSize,\n       (uch *)(pEAblock+1), (ulg)(pEAblock->nSize - 4))) != PK_OK )\n  {\n    free(pFEA2list);\n    return error;\n  }\n\n#ifdef __32BIT__\n  eaop.fpGEA2List = NULL;\n  eaop.fpFEA2List = pFEA2list;\n#else\n  pFEAlist  = (PVOID) pFEA2list;\n  pFEA2 = pFEA2list -> list;\n  pFEA  = pFEAlist  -> list;\n\n  do\n  {\n    nLength2 = pFEA2 -> oNextEntryOffset;\n    nLength = sizeof(FEA) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;\n\n    memcpy(pFEA, (PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), nLength);\n\n    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength2);\n    pFEA = (PFEA) ((PCH) pFEA + nLength);\n  }\n  while ( nLength2 != 0 );\n\n  pFEAlist -> cbList = (PCH) pFEA - (PCH) pFEAlist;\n\n  eaop.fpGEAList = NULL;\n  eaop.fpFEAList = pFEAlist;\n#endif\n\n  eaop.oError = 0;\n  DosSetPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &eaop, sizeof(eaop), 0);\n\n  if (!uO.tflag && QCOND2)\n    Info(slide, 0, ((char *)slide, \" (%ld bytes EAs)\", pFEA2list -> cbList));\n\n  free(pFEA2list);\n  return PK_COOL;\n}\n\n\nstatic int SetACL(__GPRO__ const char *path, void *ef_block)\n{                                               /* returns almost-PK errors */\n  EFHEADER *pACLblock = (PEFHEADER) ef_block;\n  char *szACL;\n  int error;\n\n  if ( ef_block == NULL || pACLblock -> nID != EF_ACL )\n    return PK_OK;  /* not an OS/2 extra field:  assume OK */\n\n  if (pACLblock->nSize < 4 || (pACLblock->lSize > 0L && pACLblock->nSize <= 10))\n    return IZ_EF_TRUNC;  /* no compressed data! */\n\n  if ( (szACL = malloc((size_t) pACLblock -> lSize)) == NULL )\n    return PK_MEM4;\n\n  if ( (error = memextract(__G__ (uch *)szACL, pACLblock->lSize,\n       (uch *)(pACLblock+1), (ulg)(pACLblock->nSize - 4))) != PK_OK )\n  {\n    free(szACL);\n    return error;\n  }\n\n  if (acl_set(NULL, path, szACL) == 0)\n    if (!uO.tflag && QCOND2)\n      Info(slide, 0, ((char *)slide, \" (%ld bytes ACL)\", strlen(szACL)));\n\n  free(szACL);\n  return PK_COOL;\n}\n\n\n#ifdef SFX\n\nchar *GetLoadPath(__GPRO)\n{\n#ifdef __32BIT__ /* generic for 32-bit API */\n  PTIB pptib;\n  PPIB pppib;\n  char *szPath;\n\n  DosGetInfoBlocks(&pptib, &pppib);\n  szPath = pppib -> pib_pchenv;\n#else /* 16-bit, note: requires large data model */\n  SEL selEnv;\n  USHORT offCmd;\n  char *szPath;\n\n  DosGetEnv(&selEnv, &offCmd);\n  szPath = MAKEP(selEnv, 0);\n#endif\n\n  while (*szPath) /* find end of process environment */\n    szPath = strchr(szPath, 0) + 1;\n\n  return szPath + 1; /* .exe file name follows environment */\n\n} /* end function GetLoadPath() */\n\n\n\n\n\n#else /* !SFX */\n\nDIR *opendir(__GPRO__ const char *name)\n{\n  struct stat statb;\n  DIR *dirp;\n  char c;\n  char *s;\n  struct _dircontents *dp;\n  char nbuf[MAXPATHLEN + 1];\n  int len;\n\n  strcpy(nbuf, name);\n  if ((len = strlen(nbuf)) == 0)\n    return NULL;\n\n  if ( ((c = nbuf[len - 1]) == '\\\\' || c == '/') && (len > 1) )\n  {\n    nbuf[len - 1] = 0;\n    --len;\n\n    if ( nbuf[len - 1] == ':' )\n    {\n      strcpy(nbuf+len, \"\\\\.\");\n      len += 2;\n    }\n  }\n  else\n    if ( nbuf[len - 1] == ':' )\n    {\n      strcpy(nbuf+len, \".\");\n      ++len;\n    }\n\n  /* GRR:  Borland and Watcom C return non-zero on wildcards... < 0 ? */\n  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)\n  {\n    Trace((stderr, \"opendir:  stat(%s) returns negative or not directory\\n\",\n      FnFilter1(nbuf)));\n    return NULL;\n  }\n\n  if ( (dirp = malloc(sizeof(DIR))) == NULL )\n    return NULL;\n\n  if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') )\n    strcpy(nbuf+len-1, \"*\");\n  else\n    if ( ((c = nbuf[len - 1]) == '\\\\' || c == '/') && (len == 1) )\n      strcpy(nbuf+len, \"*\");\n    else\n      strcpy(nbuf+len, \"\\\\*\");\n\n  /* len is no longer correct (but no longer needed) */\n  Trace((stderr, \"opendir:  nbuf = [%s]\\n\", FnFilter1(nbuf)));\n\n  dirp -> dd_loc = 0;\n  dirp -> dd_contents = dirp -> dd_cp = NULL;\n\n  if ((s = getdirent(__G__ nbuf)) == NULL)\n    return dirp;\n\n  do\n  {\n    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||\n        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )\n    {\n      if (dp)\n        free(dp);\n      free_dircontents(dirp -> dd_contents);\n\n      return NULL;\n    }\n\n    if (dirp -> dd_contents)\n    {\n      dirp -> dd_cp -> _d_next = dp;\n      dirp -> dd_cp = dirp -> dd_cp -> _d_next;\n    }\n    else\n      dirp -> dd_contents = dirp -> dd_cp = dp;\n\n    strcpy(dp -> _d_entry, s);\n    dp -> _d_next = NULL;\n\n    dp -> _d_size = G.os2.find.cbFile;\n    dp -> _d_mode = G.os2.find.attrFile;\n    dp -> _d_time = *(unsigned *) &(G.os2.find.ftimeLastWrite);\n    dp -> _d_date = *(unsigned *) &(G.os2.find.fdateLastWrite);\n  }\n  while ((s = getdirent(__G__ NULL)) != NULL);\n\n  dirp -> dd_cp = dirp -> dd_contents;\n\n  return dirp;\n}\n\n\nvoid closedir(DIR * dirp)\n{\n  free_dircontents(dirp -> dd_contents);\n  free(dirp);\n}\n\n\nstruct direct *readdir(__GPRO__ DIR * dirp)\n{\n  /* moved to os2data.h so it can be global */\n  /* static struct direct dp; */\n\n  if (dirp -> dd_cp == NULL)\n    return NULL;\n\n  G.os2.dp.d_namlen = G.os2.dp.d_reclen =\n    strlen(strcpy(G.os2.dp.d_name, dirp -> dd_cp -> _d_entry));\n\n  G.os2.dp.d_ino = 0;\n\n  G.os2.dp.d_size = dirp -> dd_cp -> _d_size;\n  G.os2.dp.d_mode = dirp -> dd_cp -> _d_mode;\n  G.os2.dp.d_time = dirp -> dd_cp -> _d_time;\n  G.os2.dp.d_date = dirp -> dd_cp -> _d_date;\n\n  dirp -> dd_cp = dirp -> dd_cp -> _d_next;\n  dirp -> dd_loc++;\n\n  return &G.os2.dp;\n}\n\n\n\n#if 0  /* not used in unzip; retained for possibly future use */\n\nvoid seekdir(DIR * dirp, long off)\n{\n  long i = off;\n  struct _dircontents *dp;\n\n  if (off >= 0)\n  {\n    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);\n\n    dirp -> dd_loc = off - (i + 1);\n    dirp -> dd_cp = dp;\n  }\n}\n\n\nlong telldir(DIR * dirp)\n{\n  return dirp -> dd_loc;\n}\n\n#endif /* 0 */\n\n\n\nstatic void free_dircontents(struct _dircontents * dp)\n{\n  struct _dircontents *odp;\n\n  while (dp)\n  {\n    if (dp -> _d_entry)\n      free(dp -> _d_entry);\n\n    dp = (odp = dp) -> _d_next;\n    free(odp);\n  }\n}\n\n\nstatic char *getdirent(__GPRO__ ZCONST char *dir)\n{\n  int done;\n  /* moved to os2data.h so it can be global */\n  /* static int lower; */\n\n  if (dir != NULL)\n  {                                    /* get first entry */\n    G.os2.hdir = HDIR_SYSTEM;\n    G.os2.count = 1;\n    done = DosFindFirst((PSZ) dir, &G.os2.hdir, attributes,\n                        &G.os2.find, sizeof(G.os2.find), &G.os2.count);\n    G.os2.lower = IsFileSystemFAT(__G__ dir);\n  }\n  else                                 /* get next entry */\n    done = DosFindNext(G.os2.hdir,\n                       &G.os2.find, sizeof(G.os2.find), &G.os2.count);\n\n  if (done == 0)\n  {\n    if ( G.os2.lower )\n      StringLower(G.os2.find.achName);\n    return G.os2.find.achName;\n  }\n  else\n  {\n    DosFindClose(G.os2.hdir);\n    return NULL;\n  }\n}\n\n\n\nint IsFileSystemFAT(__GPRO__ ZCONST char *dir)  /* FAT / HPFS detection */\n{\n  /* moved to os2data.h so they can be global */\n  /* static USHORT nLastDrive=(USHORT)(-1), nResult; */\n  ULONG lMap;\n  BYTE bData[64];\n  char bName[3];\n#ifdef __32BIT__\n  ULONG nDrive, cbData;\n  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;\n#else\n  USHORT nDrive, cbData;\n  PFSQBUFFER pData = (PFSQBUFFER) bData;\n#endif\n\n    /* We separate FAT and HPFS+other file systems here.\n       at the moment I consider other systems to be similar to HPFS,\n       i.e. support long file names and case sensitive */\n\n    if ( isalpha((uch)dir[0]) && (dir[1] == ':') )\n      nDrive = toupper(dir[0]) - '@';\n    else\n      DosQueryCurrentDisk(&nDrive, &lMap);\n\n    if ( nDrive == G.os2.nLastDrive )\n      return G.os2.nResult;\n\n    bName[0] = (char) (nDrive + '@');\n    bName[1] = ':';\n    bName[2] = 0;\n\n    G.os2.nLastDrive = nDrive;\n    cbData = sizeof(bData);\n\n    if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )\n      G.os2.nResult = !strcmp((char *) (pData -> szFSDName) + pData -> cbName,\n                              \"FAT\");\n    else\n      G.os2.nResult = FALSE;\n\n    /* End of this ugly code */\n    return G.os2.nResult;\n} /* end function IsFileSystemFAT() */\n\n\n\n\n\n/************************/\n/*  Function do_wild()  */\n/************************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n  /* moved to os2data.h so they can be global */\n#if 0\n  static DIR *wild_dir = NULL;\n  static ZCONST char *wildname;\n  static char *dirname, matchname[FILNAMSIZ];\n  static int notfirstcall=FALSE, have_dirname, dirnamelen;\n#endif\n    char *fnamestart;\n    struct direct *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.os2.notfirstcall) {  /* first call:  must initialize everything */\n        G.os2.notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(G.os2.matchname, wildspec, FILNAMSIZ);\n            G.os2.matchname[FILNAMSIZ-1] = '\\0';\n            G.os2.have_dirname = FALSE;\n            G.os2.wild_dir = NULL;\n            return G.os2.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.os2.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL &&\n            (G.os2.wildname = (ZCONST char *)strrchr(wildspec, ':')) == NULL) {\n            G.os2.dirname = \".\";\n            G.os2.dirnamelen = 1;\n            G.os2.have_dirname = FALSE;\n            G.os2.wildname = wildspec;\n        } else {\n            ++G.os2.wildname;     /* point at character after '/' or ':' */\n            G.os2.dirnamelen = G.os2.wildname - wildspec;\n            if ((G.os2.dirname = (char *)malloc(G.os2.dirnamelen+1)) == NULL) {\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(CantAllocateWildcard)));\n                strncpy(G.os2.matchname, wildspec, FILNAMSIZ);\n                G.os2.matchname[FILNAMSIZ-1] = '\\0';\n                return G.os2.matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.os2.dirname, wildspec, G.os2.dirnamelen);\n            G.os2.dirname[G.os2.dirnamelen] = '\\0';   /* terminate for strcpy below */\n            G.os2.have_dirname = TRUE;\n        }\n        Trace((stderr, \"do_wild:  dirname = [%s]\\n\",\n          FnFilter1(G.os2.dirname)));\n\n        if ((G.os2.wild_dir = opendir(__G__ G.os2.dirname)) != NULL) {\n            if (G.os2.have_dirname) {\n                strcpy(G.os2.matchname, G.os2.dirname);\n                fnamestart = G.os2.matchname + G.os2.dirnamelen;\n            } else\n                fnamestart = G.os2.matchname;\n            while ((file = readdir(__G__ G.os2.wild_dir)) != NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                strcpy(fnamestart, file->d_name);\n                if (strrchr(fnamestart, '.') == (char *)NULL)\n                    strcat(fnamestart, \".\");\n                if (match(fnamestart, G.os2.wildname, 1 WISEP) &&\n                                                      /* 1 == ignore case */\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(fnamestart, \".\") && strcmp(fnamestart, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    /* remove trailing dot */\n                    fnamestart += strlen(fnamestart) - 1;\n                    if (*fnamestart == '.')\n                        *fnamestart = '\\0';\n                    return G.os2.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(G.os2.wild_dir);\n            G.os2.wild_dir = NULL;\n        }\n#ifdef DEBUG\n        else {\n            Trace((stderr, \"do_wild:  opendir(%s) returns NULL\\n\",\n              FnFilter1(G.os2.dirname)));\n        }\n#endif /* DEBUG */\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.os2.matchname, wildspec, FILNAMSIZ);\n        G.os2.matchname[FILNAMSIZ-1] = '\\0';\n        return G.os2.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (G.os2.wild_dir == NULL) {\n        G.os2.notfirstcall = FALSE;  /* nothing left to try--reset */\n        if (G.os2.have_dirname)\n            free(G.os2.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    if (G.os2.have_dirname) {\n        /* strcpy(G.os2.matchname, G.os2.dirname); */\n        fnamestart = G.os2.matchname + G.os2.dirnamelen;\n    } else\n        fnamestart = G.os2.matchname;\n    while ((file = readdir(__G__ G.os2.wild_dir)) != NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        strcpy(fnamestart, file->d_name);\n        if (strrchr(fnamestart, '.') == (char *)NULL)\n            strcat(fnamestart, \".\");\n        if (match(fnamestart, G.os2.wildname, 1 WISEP)) { /* 1==ignore case */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            /* remove trailing dot */\n            fnamestart += strlen(fnamestart) - 1;\n            if (*fnamestart == '.')\n                *fnamestart = '\\0';\n            return G.os2.matchname;\n        }\n    }\n\n    closedir(G.os2.wild_dir);   /* have read at least one entry; nothing left */\n    G.os2.wild_dir = NULL;\n    G.os2.notfirstcall = FALSE; /* reset for new wildspec */\n    if (G.os2.have_dirname)\n        free(G.os2.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n/* scan extra fields for something we happen to know */\n\nstatic int EvalExtraFields(__GPRO__ const char *path,\n                           void *extra_field, unsigned ef_len)\n{\n  char *ef_ptr = extra_field;\n  PEFHEADER pEFblock;\n  int rc = PK_OK;\n\n  while (ef_len >= sizeof(EFHEADER))\n  {\n    pEFblock = (PEFHEADER) ef_ptr;\n\n    if (pEFblock -> nSize > (ef_len - EB_HEADSIZE))\n      return PK_ERR;            /* claimed EFblock length exceeds EF size! */\n\n    switch (pEFblock -> nID)\n    {\n    case EF_OS2:\n      rc = SetEAs(__G__ path, ef_ptr);\n      break;\n    case EF_ACL:\n      rc = (uO.X_flag) ? SetACL(__G__ path, ef_ptr) : PK_OK;\n      break;\n#if 0\n    case EF_IZUNIX:\n    case EF_PKUNIX:\n      /* handled elsewhere */\n      break;\n#endif\n    default:\n      TTrace((stderr,\"EvalExtraFields: unknown extra field block, ID=%d\\n\",\n              pEFblock -> nID));\n      break;\n    }\n\n    ef_ptr += (pEFblock -> nSize + EB_HEADSIZE);\n    ef_len -= (pEFblock -> nSize + EB_HEADSIZE);\n\n    if (rc != PK_OK)\n      break;\n  }\n\n  return rc;\n}\n\n\n\n/************************/\n/*  Function mapattr()  */\n/************************/\n\nint mapattr(__G)\n    __GDEF\n{\n    /* set archive bit (file is not backed up): */\n    G.pInfo->file_attr = (unsigned)(G.crec.external_file_attributes | 32) & 0xff;\n    return 0;\n}\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\n/*\n * There are presently two possibilities in OS/2:  the output filesystem is\n * FAT, or it is HPFS.  If the former, we need to map to FAT, obviously, but\n * we *also* must map to HPFS and store that version of the name in extended\n * attributes.  Either way, we need to map to HPFS, so the main mapname\n * routine does that.  In the case that the output file system is FAT, an\n * extra filename-mapping routine is called in checkdir().  While it should\n * be possible to determine the filesystem immediately upon entry to mapname(),\n * it is conceivable that the DOS APPEND utility could be added to OS/2 some-\n * day, allowing a FAT directory to be APPENDed to an HPFS drive/path.  There-\n * fore we simply check the filesystem at each path component.\n *\n * Note that when alternative IFSes become available/popular, everything will\n * become immensely more complicated.  For example, a Minix filesystem would\n * have limited filename lengths like FAT but no extended attributes in which\n * to store the longer versions of the names.  A BSD Unix filesystem would\n * support paths of length 1024 bytes or more, but it is not clear that FAT\n * EAs would allow such long .LONGNAME fields or that OS/2 would properly\n * restore such fields when moving files from FAT to the new filesystem.\n *\n * GRR:  some or all of the following chars should be checked in either\n *       mapname (HPFS) or map2fat (FAT), depending:  ,=^+'\"[]<>|\\t&\n */\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.os2.created_dir = FALSE;  /* not yet */\n    G.os2.renamed_fullpath = FALSE;\n    G.os2.fnlen = strlen(G.filename);\n\n/* GRR:  for VMS, convert to internal format now or later? or never? */\n    if (renamed) {\n        cp = G.filename - 1;    /* point to beginning of renamed name... */\n        while (*++cp)\n            if (*cp == '\\\\')    /* convert backslashes to forward */\n                *cp = '/';\n        cp = G.filename;\n        /* use temporary rootpath if user gave full pathname */\n        if (G.filename[0] == '/') {\n            G.os2.renamed_fullpath = TRUE;\n            pathcomp[0] = '/';  /* copy the '/' and terminate */\n            pathcomp[1] = '\\0';\n            ++cp;\n        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {\n            G.os2.renamed_fullpath = TRUE;\n            pp = pathcomp;\n            *pp++ = *cp++;      /* copy the \"d:\" (+ '/', possibly) */\n            *pp++ = *cp++;\n            if (*cp == '/')\n                *pp++ = *cp++;  /* otherwise add \"./\"? */\n            *pp = '\\0';\n        }\n    }\n\n    /* pathcomp is ignored unless renamed_fullpath is TRUE: */\n    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */\n        return error;           /* ...unless no mem or vol label on hard disk */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (!renamed) {             /* cp already set if renamed */\n        if (uO.jflag)           /* junking directories */\n/* GRR:  watch out for VMS version... */\n            cp = (char *)strrchr(G.filename, '/');\n        if (cp == (char *)NULL) /* no '/' or not junking dirs */\n            cp = G.filename;    /* point to internal zipfile-member pathname */\n        else\n            ++cp;               /* point to start of last component of path */\n    }\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ':':             /* drive never stored, so no colon allowed */\n            case '\\\\':            /* \"non-dos\" FSs may  allow '\\\\' as normal */\n                *pp++ = '_';      /*  character in filenames */\n                break;            /* -> map invalid chars to underscore */\n\n            case ';':             /* start of VMS version? */\n                lastsemi = pp;    /* remove VMS version later... */\n                *pp++ = ';';      /*  but keep semicolon for now */\n                break;\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            case ' ':             /* keep spaces unless specifically */\n                if (uO.sflag)     /*  requested to change to underscore */\n                    *pp++ = '_';\n                else\n                    *pp++ = ' ';\n                break;\n\n            default:\n                /* allow ASCII 255 and European characters in filenames: */\n                if (isprint(workch) || workch >= 127)\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[G.os2.fnlen-1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.os2.created_dir) {\n            if (QCOND2)\n                Info(slide, 0, ((char *)slide, LoadFarString(Creating),\n                  FnFilter1(G.filename)));\n            if (G.extra_field) { /* zipfile extra field has extended attribs */\n                int err = EvalExtraFields(__G__ G.filename, G.extra_field,\n                                          G.lrec.extra_field_length);\n\n                if (err == IZ_EF_TRUNC) {\n                    if (uO.qflag)\n                        Info(slide, 1, ((char *)slide, \"%-22s \",\n                          FnFilter1(G.filename)));\n                    Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),\n                      makeword(G.extra_field+2)-10, \"\\n\"));\n                } else if (!uO.qflag)\n                    (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n            } else if (!uO.qflag)\n                (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n\n            /* set date/time stamps */\n            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);\n\n            /* dir time already set */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n\n        } else if (G.extra_field && IS_OVERWRT_ALL) {\n            /* overwrite EAs of existing directory since user requested it */\n            int err = EvalExtraFields(__G__ G.filename, G.extra_field,\n                                      G.lrec.extra_field_length);\n\n            if (err == IZ_EF_TRUNC) {\n                Info(slide, 0x421, ((char *)slide, \"%-22s \",\n                  FnFilter1(G.filename)));\n                Info(slide, 0x401, ((char *)slide, LoadFarString(TruncEAs),\n                  makeword(G.extra_field+2)-10, \"\\n\"));\n            }\n\n            /* set date/time stamps (dirs only have creation times) */\n            SetPathAttrTimes(__G__ G.pInfo->file_attr & ~A_ARCHIVE, 1);\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \"###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;        /* semi-colon was kept:  expect #s after */\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n    Trace((stderr, \"mapname returns with filename = [%s] (error = %d)\\n\\n\",\n      FnFilter1(G.filename), error));\n\n    if (G.pInfo->vollabel) {    /* set the volume label now */\n        VOLUMELABEL FSInfoBuf;\n/* GRR:  \"VOLUMELABEL\" defined for IBM C and emx, but haven't checked MSC... */\n\n        strcpy(FSInfoBuf.szVolLabel, G.filename);\n        FSInfoBuf.cch = (BYTE)strlen(FSInfoBuf.szVolLabel);\n\n        if (!uO.qflag)\n            Info(slide, 0, ((char *)slide, LoadFarString(Labelling),\n              (char)(G.os2.nLabelDrive + 'a' - 1), FnFilter1(G.filename)));\n        if (DosSetFSInfo(G.os2.nLabelDrive, FSIL_VOLSER, (PBYTE)&FSInfoBuf,\n                         sizeof(VOLUMELABEL)))\n        {\n            Info(slide, 1, ((char *)slide, LoadFarString(ErrSetVolLabel)));\n            return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n        }\n        /* success:  skip the \"extraction\" quietly */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n  /* moved to os2data.h so they can be global */\n#if 0\n    static int rootlen = 0;      /* length of rootpath */\n    static char *rootpath;       /* user's \"extract-to\" directory */\n    static char *buildpathHPFS;  /* full path (so far) to extracted file, */\n    static char *buildpathFAT;   /*  both HPFS/EA (main) and FAT versions */\n    static char *endHPFS;        /* corresponding pointers to end of */\n    static char *endFAT;         /*  buildpath ('\\0') */\n#endif\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        char *p = pathcomp;\n        int longdirEA, too_long=FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.os2.endHPFS = *p++) != '\\0')     /* copy to HPFS filename */\n            ++G.os2.endHPFS;\n        if (IsFileNameValid(G.os2.buildpathHPFS)) {\n            longdirEA = FALSE;\n            p = pathcomp;\n            while ((*G.os2.endFAT = *p++) != '\\0')  /* copy to FAT filename, too */\n                ++G.os2.endFAT;\n        } else {\n            longdirEA = TRUE;\n/* GRR:  check error return? */\n            map2fat(pathcomp, &G.os2.endFAT);  /* map, put in FAT fn, update endFAT */\n        }\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check endHPFS-G.os2.buildpathHPFS after each append, set warning variable\n         * if within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check:  need to append '/', at least one-char name, '\\0' */\n        if ((G.os2.endHPFS-G.os2.buildpathHPFS) > FILNAMSIZ-3)\n            too_long = TRUE;                 /* check if extracting dir? */\n#ifdef MSC /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */\n        if (GetFileTime(G.os2.buildpathFAT) == -1 || stat(G.os2.buildpathFAT, &G.statbuf))\n#else\n        if (stat(G.os2.buildpathFAT, &G.statbuf))    /* path doesn't exist */\n#endif\n        {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.os2.buildpathHPFS);\n                free(G.os2.buildpathFAT);\n                /* path doesn't exist:  nothing to do */\n                return MPN_INF_SKIP;\n            }\n            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */\n                Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n                  FnFilter1(G.os2.buildpathHPFS)));\n                free(G.os2.buildpathHPFS);\n                free(G.os2.buildpathFAT);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (MKDIR(G.os2.buildpathFAT, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),\n                  FnFilter2(G.os2.buildpathFAT), FnFilter1(G.filename)));\n                free(G.os2.buildpathHPFS);\n                free(G.os2.buildpathFAT);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.os2.created_dir = TRUE;\n            /* only set EA if creating directory */\n/* GRR:  need trailing '/' before function call? */\n            if (longdirEA) {\n#ifdef DEBUG\n                int e =\n#endif\n                  SetLongNameEA(G.os2.buildpathFAT, pathcomp);\n                Trace((stderr, \"APPEND_DIR:  SetLongNameEA() returns %d\\n\", e));\n            }\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),\n              FnFilter2(G.os2.buildpathFAT), FnFilter1(G.filename)));\n            free(G.os2.buildpathHPFS);\n            free(G.os2.buildpathFAT);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),\n              FnFilter1(G.os2.buildpathHPFS)));\n            free(G.os2.buildpathHPFS);\n            free(G.os2.buildpathFAT);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.os2.endHPFS++ = '/';\n        *G.os2.endFAT++ = '/';\n        *G.os2.endHPFS = *G.os2.endFAT = '\\0';\n        Trace((stderr, \"buildpathHPFS now = [%s]\\n\",\n          FnFilter1(G.os2.buildpathHPFS)));\n        Trace((stderr, \"buildpathFAT now =  [%s]\\n\",\n          FnFilter1(G.os2.buildpathFAT)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want\n    filename to reflect name used on disk, not EAs; if full path is HPFS,\n    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        Trace((stderr, \"getting and freeing FAT path [%s]\\n\",\n          FnFilter1(G.os2.buildpathFAT)));\n        Trace((stderr, \"freeing HPFS path [%s]\\n\",\n          FnFilter1(G.os2.buildpathHPFS)));\n        strcpy(pathcomp, G.os2.buildpathFAT);\n        free(G.os2.buildpathFAT);\n        free(G.os2.buildpathHPFS);\n        G.os2.buildpathHPFS = G.os2.buildpathFAT = G.os2.endHPFS = G.os2.endFAT = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n        char *p = pathcomp;\n        int error = MPN_OK;\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        /* The buildpathHPFS buffer has been allocated large enough to\n         * hold the complete combined name, so there is no need to check\n         * for OS filename size limit overflow within the copy loop.\n         */\n        while ((*G.os2.endHPFS = *p++) != '\\0') {   /* copy to HPFS filename */\n            ++G.os2.endHPFS;\n        }\n        /* Now, check for OS filename size overflow.  When detected, the\n         * mapped HPFS name is truncated and a warning message is shown.\n         */\n        if ((G.os2.endHPFS-G.os2.buildpathHPFS) >= FILNAMSIZ) {\n            G.os2.buildpathHPFS[FILNAMSIZ-1] = '\\0';\n            Info(slide, 1, ((char *)slide, LoadFarString(PathTooLongTrunc),\n              FnFilter1(G.filename), FnFilter2(G.os2.buildpathHPFS)));\n            error = MPN_INF_TRUNC;  /* filename truncated */\n        }\n\n/* GRR:  how can longnameEA ever be set before this point???  we don't want\n * to save the original name to EAs if user renamed it, do we?\n *\n * if (!G.os2.longnameEA && ((G.os2.longnameEA = !IsFileNameValid(name)) != 0))\n */\n        /* The buildpathFAT buffer has the same allocated size as the\n         * buildpathHPFS buffer, so there is no need for an overflow check\n         * within the following copy loop, either.\n         */\n        if (G.pInfo->vollabel || IsFileNameValid(G.os2.buildpathHPFS)) {\n            G.os2.longnameEA = FALSE;\n            /* copy to FAT filename, too */\n            p = pathcomp;\n            while ((*G.os2.endFAT = *p++) != '\\0')\n                ++G.os2.endFAT;\n        } else {\n            G.os2.longnameEA = TRUE;\n            if ((G.os2.lastpathcomp = (char *)malloc(strlen(pathcomp)+1)) ==\n                (char *)NULL)\n            {\n                Info(slide, 1, ((char *)slide,\n                 \"checkdir warning:  cannot save longname EA: out of memory\\n\"));\n                G.os2.longnameEA = FALSE;\n                /* can't set .LONGNAME extended attribute */\n                error = MPN_INF_TRUNC;\n            } else           /* used and freed in close_outfile() */\n                strcpy(G.os2.lastpathcomp, pathcomp);\n            /* map, put in FAT fn, update endFAT */\n            map2fat(pathcomp, &G.os2.endFAT);\n        }\n\n        /* Check that the FAT path does not exceed the FILNAMSIZ limit, and\n         * truncate when neccessary.\n         * Note that truncation can only happen when the HPFS path (which is\n         * never shorter than the FAT path) has been already truncated.\n         * So, emission of the warning message and setting the error code\n         * has already happened.\n         */\n        if ((G.os2.endFAT-G.os2.buildpathFAT) >= FILNAMSIZ)\n            G.os2.buildpathFAT[FILNAMSIZ-1] = '\\0';\n        Trace((stderr, \"buildpathHPFS: %s\\nbuildpathFAT:  %s\\n\",\n          FnFilter1(G.os2.buildpathHPFS), FnFilter2(G.os2.buildpathFAT)));\n\n        return error;  /* could check for existence, prompt for new name... */\n\n    } /* end if (FUNCTION == APPEND_NAME) */\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpathHPFS and buildpathFAT to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+\n                                                  (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.os2.buildpathHPFS = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n#ifdef ACORN_FTYPE_NFS\n        if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+\n                                                 (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.os2.buildpathFAT = (char *)malloc(G.os2.fnlen+G.os2.rootlen+1))\n#endif\n            == (char *)NULL) {\n            free(G.os2.buildpathHPFS);\n            return MPN_NOMEM;\n        }\n        if (G.pInfo->vollabel) {  /* use root or renamed path, but don't store */\n/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */\n            if (G.os2.renamed_fullpath && pathcomp[1] == ':')\n                *G.os2.buildpathHPFS = (char)ToLower(*pathcomp);\n            else if (!G.os2.renamed_fullpath && G.os2.rootlen > 1 && G.os2.rootpath[1] == ':')\n                *G.os2.buildpathHPFS = (char)ToLower(*G.os2.rootpath);\n            else {\n                ULONG lMap;\n                DosQueryCurrentDisk(&G.os2.nLabelDrive, &lMap);\n                *G.os2.buildpathHPFS = (char)(G.os2.nLabelDrive - 1 + 'a');\n            }\n            G.os2.nLabelDrive = *G.os2.buildpathHPFS - 'a' + 1; /* save for mapname() */\n            if (uO.volflag == 0 || *G.os2.buildpathHPFS < 'a' ||  /* no labels/bogus? */\n                (uO.volflag == 1 && !isfloppy(G.os2.nLabelDrive))) { /* -$:  no fixed */\n                free(G.os2.buildpathHPFS);\n                free(G.os2.buildpathFAT);\n                return MPN_VOL_LABEL;   /* skipping with message */\n            }\n            *G.os2.buildpathHPFS = '\\0';\n        } else if (G.os2.renamed_fullpath)   /* pathcomp = valid data */\n            strcpy(G.os2.buildpathHPFS, pathcomp);\n        else if (G.os2.rootlen > 0)\n            strcpy(G.os2.buildpathHPFS, G.os2.rootpath);\n        else\n            *G.os2.buildpathHPFS = '\\0';\n        G.os2.endHPFS = G.os2.buildpathHPFS;\n        G.os2.endFAT = G.os2.buildpathFAT;\n        while ((*G.os2.endFAT = *G.os2.endHPFS) != '\\0') {\n            ++G.os2.endFAT;\n            ++G.os2.endHPFS;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.os2.buildpathHPFS)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to\n    directory specification includes a drive letter (leading \"x:\"), it is\n    treated just as if it had a trailing '/'--that is, one directory level\n    will be created if the path doesn't exist, unless this is otherwise pro-\n    hibited (e.g., freshening).\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            G.os2.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.os2.rootlen > 0)  /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.os2.rootlen = strlen(pathcomp)) > 0) {\n            int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(G.os2.rootlen+3)) == (char *)NULL) {\n                G.os2.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n                has_drive = TRUE;   /* drive designator */\n            if (tmproot[G.os2.rootlen-1] == '/') {\n                tmproot[--G.os2.rootlen] = '\\0';\n                had_trailing_pathsep = TRUE;\n            }\n            if (has_drive && (G.os2.rootlen == 2)) {\n                if (!had_trailing_pathsep)   /* i.e., original wasn't \"x:/\" */\n                    add_dot = TRUE;    /* relative path: add '.' before '/' */\n            } else if (G.os2.rootlen > 0) {   /* need not check \"x:.\" and \"x:/\" */\n#ifdef MSC      /* MSC 6.00 bug:  stat(non-existent-dir) == 0 [exists!] */\n                if (GetFileTime(tmproot) == -1 ||\n                    SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n#else\n                if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n#endif\n                {   /* path does not exist */\n                    if (!G.create_dirs                 /* || iswild(tmproot) */\n                                       ) {\n                        free(tmproot);\n                        G.os2.rootlen = 0;\n                        return MPN_INF_SKIP;    /* treat as stored file */\n                    }\n                    /* create directory (could add loop here scanning tmproot\n                     * to create more than one level, but really necessary?) */\n                    if (MKDIR(tmproot, 0777) == -1) {\n                        Info(slide, 1, ((char *)slide,\n                          LoadFarString(CantCreateExtractDir),\n                          FnFilter1(tmproot)));\n                        free(tmproot);\n                        G.os2.rootlen = 0;\n                        /* path didn't exist, tried to create, failed: */\n                        /* file exists, or need 2+ directory levels */\n                        return MPN_ERR_SKIP;\n                    }\n                }\n            }\n            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n                tmproot[G.os2.rootlen++] = '.';\n            tmproot[G.os2.rootlen++] = '/';\n            tmproot[G.os2.rootlen] = '\\0';\n            if ((G.os2.rootpath = realloc(tmproot, G.os2.rootlen+1)) == NULL) {\n                free(tmproot);\n                G.os2.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.os2.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.os2.rootlen > 0) {\n            free(G.os2.rootpath);\n            G.os2.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n/***********************/\n/* Function isfloppy() */   /* more precisely, is it removable? */\n/***********************/\n\nstatic int isfloppy(nDrive)\n    int nDrive;   /* 1 == A:, 2 == B:, etc. */\n{\n    uch ParmList[1] = {0};\n    uch DataArea[1] = {0};\n    char Name[3];\n    HFILE handle;\n#ifdef __32BIT__\n    ULONG rc;\n    ULONG action;\n#else\n    USHORT rc;\n    USHORT action;\n#endif\n\n\n    Name[0] = (char) (nDrive + 'A' - 1);\n    Name[1] = ':';\n    Name[2] = 0;\n\n    rc = DosOpen(Name, &handle, &action, 0L, FILE_NORMAL, FILE_OPEN,\n                 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |\n                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L);\n\n    if (rc == ERROR_NOT_READY)   /* must be removable */\n      return TRUE;\n    else if (rc) {   /* other error:  do default a/b heuristic instead */\n      Trace((stderr, \"error in DosOpen(DASD):  guessing...\\n\", rc));\n      return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;\n    }\n\n    rc = DosDevIOCtl(DataArea, sizeof(DataArea), ParmList, sizeof(ParmList),\n                     DSK_BLOCKREMOVABLE, IOCTL_DISK, handle);\n    DosClose(handle);\n\n    if (rc) {   /* again, just check for a/b */\n        Trace((stderr, \"error in DosDevIOCtl category IOCTL_DISK, function \"\n          \"DSK_BLOCKREMOVABLE\\n  (rc = 0x%04x):  guessing...\\n\", rc));\n        return (nDrive == 1 || nDrive == 2)? TRUE : FALSE;\n    } else {\n        return DataArea[0] ? FALSE : TRUE;\n    }\n} /* end function isfloppy() */\n\n\n\n\n\nstatic int IsFileNameValid(const char *name)\n{\n  HFILE hf;\n#ifdef __32BIT__\n  ULONG uAction;\n#else\n  USHORT uAction;\n#endif\n\n  switch( DosOpen((PSZ) name, &hf, &uAction, 0, 0, FILE_OPEN,\n                  OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )\n  {\n  case ERROR_INVALID_NAME:\n  case ERROR_FILENAME_EXCED_RANGE:\n    return FALSE;\n  case NO_ERROR:\n    DosClose(hf);\n  default:\n    return TRUE;\n  }\n}\n\n\n\n\n\n/**********************/\n/* Function map2fat() */\n/**********************/\n\nstatic void map2fat(pathcomp, pEndFAT)\n    char *pathcomp, **pEndFAT;\n{\n    char *ppc = pathcomp;          /* variable pointer to pathcomp */\n    char *pEnd = *pEndFAT;         /* variable pointer to buildpathFAT */\n    char *pBegin = *pEndFAT;       /* constant pointer to start of this comp. */\n    char *last_dot = (char *)NULL; /* last dot not converted to underscore */\n    int dotname = FALSE;           /* flag:  path component begins with dot */\n                                   /*  (\".\" and \"..\" don't count) */\n    register unsigned workch;      /* hold the character being tested */\n\n\n    /* Only need check those characters which are legal in HPFS but not\n     * in FAT:  to get here, must already have passed through mapname.\n     * (GRR:  oops, small bug--if char was quoted, no longer have any\n     * knowledge of that.)  Also must truncate path component to ensure\n     * 8.3 compliance...\n     */\n    while ((workch = (uch)*ppc++) != 0) {\n        switch (workch) {\n            case '[':               /* add  '\"'  '+'  ','  '='  ?? */\n            case ']':\n                *pEnd++ = '_';      /* convert brackets to underscores */\n                break;\n\n            case '.':\n                if (pEnd == *pEndFAT) {   /* nothing appended yet... */\n                    if (*ppc == '\\0')     /* don't bother appending a */\n                        break;            /*  \"./\" component to the path */\n                    else if (*ppc == '.' && ppc[1] == '\\0') {   /* \"../\" */\n                        *pEnd++ = '.';    /* add first dot, unchanged... */\n                        ++ppc;            /* skip second dot, since it will */\n                    } else {              /*  be \"added\" at end of if-block */\n                        *pEnd++ = '_';    /* FAT doesn't allow null filename */\n                        dotname = TRUE;   /*  bodies, so map .exrc -> _.exrc */\n                    }                     /*  (extra '_' now, \"dot\" below) */\n                } else if (dotname) {     /* found a second dot, but still */\n                    dotname = FALSE;      /*  have extra leading underscore: */\n                    *pEnd = '\\0';         /*  remove it by shifting chars */\n                    pEnd = *pEndFAT + 1;  /*  left one space (e.g., .p1.p2: */\n                    while (pEnd[1]) {     /*  __p1 -> _p1_p2 -> _p1.p2 when */\n                        *pEnd = pEnd[1];  /*  finished) [opt.:  since first */\n                        ++pEnd;           /*  two chars are same, can start */\n                    }                     /*  shifting at second position] */\n                }\n                last_dot = pEnd;    /* point at last dot so far... */\n                *pEnd++ = '_';      /* convert dot to underscore for now */\n                break;\n\n            default:\n                *pEnd++ = (char)workch;\n\n        } /* end switch */\n    } /* end while loop */\n\n    *pEnd = '\\0';                 /* terminate buildpathFAT */\n\n    /* NOTE:  keep in mind that pEnd points to the end of the path\n     * component, and *pEndFAT still points to the *beginning* of it...\n     * Also note that the algorithm does not try to get too fancy:\n     * if there are no dots already, the name either gets truncated\n     * at 8 characters or the last underscore is converted to a dot\n     * (only if more characters are saved that way).  In no case is\n     * a dot inserted between existing characters.\n     */\n    if (last_dot == (char *)NULL) {  /* no dots:  check for underscores... */\n        char *plu = strrchr(pBegin, '_');    /* pointer to last underscore */\n\n        if (plu == (char *)NULL) { /* no dots, no underscores:  truncate at 8 */\n            *pEndFAT += 8;         /* chars (could insert '.' and keep 11...) */\n            if (*pEndFAT > pEnd)\n                *pEndFAT = pEnd;   /* oops...didn't have 8 chars to truncate */\n            else\n                **pEndFAT = '\\0';\n        } else if (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8) {\n            last_dot = plu;        /* be lazy:  drop through to next if-block */\n        } else if ((pEnd - *pEndFAT) > 8) {\n            *pEndFAT += 8;         /* more fits into just basename than if */\n            **pEndFAT = '\\0';      /*  convert last underscore to dot */\n        } else\n            *pEndFAT = pEnd;       /* whole thing fits into 8 chars or less */\n    }\n\n    if (last_dot != (char *)NULL) {   /* one dot (or two, in the case of */\n        *last_dot = '.';              /*  \"..\") is OK:  put it back in */\n\n        if ((last_dot - pBegin) > 8) {\n            char *p, *q;\n            int i;\n\n            p = last_dot;\n            q = last_dot = pBegin + 8;\n            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */\n                *q++ = *p++;                   /*  shift \".ext\" left and */\n            *q = '\\0';                         /*  truncate/terminate it */\n            *pEndFAT = q;\n        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */\n            *pEndFAT = last_dot + 4;\n            **pEndFAT = '\\0';\n        } else\n            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */\n\n        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')\n            last_dot[-1] = '_';                /* NO blank in front of '.'! */\n    }\n} /* end function map2fat() */\n\n\n\n\n\nstatic int SetLongNameEA(char *name, char *longname)\n{\n  EAOP eaop;\n  FEALST fealst;\n\n  eaop.fpFEAList = (PFEALIST) &fealst;\n  eaop.fpGEAList = NULL;\n  eaop.oError = 0;\n\n  strcpy((char *) fealst.szName, \".LONGNAME\");\n  strcpy((char *) fealst.szValue, longname);\n\n  fealst.cbList  = sizeof(fealst) - CCHMAXPATH + strlen((char *) fealst.szValue);\n  fealst.cbName  = (BYTE) strlen((char *) fealst.szName);\n  fealst.cbValue = sizeof(USHORT) * 2 + strlen((char *) fealst.szValue);\n\n#ifdef __32BIT__\n  fealst.oNext   = 0;\n#endif\n  fealst.fEA     = 0;\n  fealst.eaType  = 0xFFFD;\n  fealst.eaSize  = strlen((char *) fealst.szValue);\n\n  return DosSetPathInfo(name, FIL_QUERYEASIZE,\n                        (PBYTE) &eaop, sizeof(eaop), 0);\n}\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\n           /* GRR:  need to return error level!! */\n\nvoid close_outfile(__G)   /* only for extracted files, not directories */\n    __GDEF\n{\n    fclose(G.outfile);\n\n    /* set extra fields, both stored-in-zipfile and .LONGNAME flavors */\n    if (G.extra_field) {    /* zipfile extra field may have extended attribs */\n        int err = EvalExtraFields(__G__ G.filename, G.extra_field,\n                                  G.lrec.extra_field_length);\n\n        if (err == IZ_EF_TRUNC) {\n            if (uO.qflag)\n                Info(slide, 1, ((char *)slide, \"%-22s \",\n                  FnFilter1(G.filename)));\n            Info(slide, 1, ((char *)slide, LoadFarString(TruncEAs),\n              makeword(G.extra_field+2)-10, uO.qflag? \"\\n\" : \"\"));\n        }\n    }\n\n    if (G.os2.longnameEA) {\n#ifdef DEBUG\n        int e =\n#endif\n          SetLongNameEA(G.filename, G.os2.lastpathcomp);\n        Trace((stderr, \"close_outfile:  SetLongNameEA() returns %d\\n\", e));\n        free(G.os2.lastpathcomp);\n    }\n\n    /* set date/time and permissions */\n    SetPathAttrTimes(__G__ G.pInfo->file_attr, 0);\n\n} /* end function close_outfile() */\n\n\n\n\n\n/******************************/\n/* Function check_for_newer() */\n/******************************/\n\nint check_for_newer(__G__ filename)   /* return 1 if existing file newer or equal; */\n    __GDEF\n    char *filename;             /*  0 if older; -1 if doesn't exist yet */\n{\n    ulg existing, archive;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n\n    if ((existing = (ulg)GetFileTime(filename)) == (ulg)-1)\n        return DOES_NOT_EXIST;\n\n#ifdef USE_EF_UT_TIME\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n         & EB_UT_FL_MTIME))\n    {\n        TTrace((stderr, \"check_for_newer:  using Unix extra field mtime\\n\"));\n        archive = Utime2DosDateTime(z_utime.mtime);\n    } else {\n        archive = G.lrec.last_mod_dos_datetime;\n    }\n#else /* !USE_EF_UT_TIME */\n    archive = G.lrec.last_mod_dos_datetime;\n#endif /* ?USE_EF_UT_TIME */\n\n    return (existing >= archive);\n} /* end function check_for_newer() */\n\n\n\n\n\n#ifndef SFX\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\nint dateformat()\n{\n/*-----------------------------------------------------------------------------\n  For those operating systems which support it, this function returns a value\n  which tells how national convention says that numeric dates are displayed.\n  Return values are DF_YMD, DF_DMY and DF_MDY.\n -----------------------------------------------------------------------------*/\n\n    switch (GetCountryInfo()) {\n        case 0:\n            return DF_MDY;\n        case 1:\n            return DF_DMY;\n        case 2:\n            return DF_YMD;\n    }\n    return DF_MDY;   /* default if error */\n\n} /* end function dateformat() */\n\n\n\n\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)\n    char buf[80];\n#endif\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#if defined(__GNUC__)\n#  ifdef __EMX__  /* __EMX__ is defined as \"1\" only (sigh) */\n      \"emx+gcc \", __VERSION__,\n#  else\n      \"gcc \", __VERSION__,\n#  endif\n#elif defined(__IBMC__)\n      \"IBM \",\n#  if (__IBMC__ < 200)\n      (sprintf(buf, \"C Set/2 %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  elif (__IBMC__ < 300)\n      (sprintf(buf, \"C Set++ %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  else\n      (sprintf(buf, \"Visual Age C++ %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  endif\n#elif defined(__WATCOMC__)\n      \"Watcom C\", (sprintf(buf, \" (__WATCOMC__ = %d)\", __WATCOMC__), buf),\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n      \"Borland C++\",\n#    if (__BORLANDC__ < 0x0460)\n        \" 1.0\",\n#    elif (__BORLANDC__ == 0x0460)\n        \" 1.5\",                     /* from Kai Uwe:  three less than DOS */\n#    else\n        \" 2.0\",                     /* (__BORLANDC__ == 0x0500)? */\n#    endif\n#  else\n      \"Turbo C\",                    /* these are probably irrelevant */\n#    if (__TURBOC__ >= 661)\n       \"++ 1.0 or later\",\n#    elif (__TURBOC__ == 661)\n       \" 3.0?\",\n#    elif (__TURBOC__ == 397)\n       \" 2.0\",\n#    else\n       \" 1.0 or 1.5?\",\n#    endif\n#  endif\n#elif defined(MSC)\n      \"Microsoft C \",\n#  ifdef _MSC_VER\n      (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf),\n#  else\n      \"5.1 or earlier\",\n#  endif\n#else\n      \"unknown compiler\", \"\",\n#endif /* ?compilers */\n\n      \"OS/2\",\n\n/* GRR:  does IBM C/2 identify itself as IBM rather than Microsoft? */\n#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))\n#  if defined(M_I86HM) || defined(__HUGE__)\n      \" (16-bit, huge)\",\n#  elif defined(M_I86LM) || defined(__LARGE__)\n      \" (16-bit, large)\",\n#  elif defined(M_I86MM) || defined(__MEDIUM__)\n      \" (16-bit, medium)\",\n#  elif defined(M_I86CM) || defined(__COMPACT__)\n      \" (16-bit, compact)\",\n#  elif defined(M_I86SM) || defined(__SMALL__)\n      \" (16-bit, small)\",\n#  elif defined(M_I86TM) || defined(__TINY__)\n      \" (16-bit, tiny)\",\n#  else\n      \" (16-bit)\",\n#  endif\n#else\n      \" (32-bit)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n                                /* MSC can't handle huge macro expansions */\n\n    /* temporary debugging code for Borland compilers only */\n    /* __TCPLUSPLUS__, __BCPLUSPLUS__ not defined for v1.5 */\n#if (defined(__TURBOC__) && defined(DEBUG))\n    Info(slide, 0, ((char *)slide, \"\\t(__TURBOC__ = 0x%04x = %d)\\n\", __TURBOC__,\n      __TURBOC__));\n#ifdef __BORLANDC__\n    Info(slide, 0, ((char *)slide, \"\\t(__BORLANDC__ = 0x%04x)\\n\",__BORLANDC__));\n#else\n    Info(slide, 0, ((char *)slide, \"\\tdebug(__BORLANDC__ not defined)\\n\"));\n#endif\n#endif /* __TURBOC__ && DEBUG */\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n#endif /* !FUNZIP */\n\n\n\n#ifdef MY_ZCALLOC       /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */\n\n#if defined(MSC) || defined(__WATCOMC__)\n#if (!defined(_MSC_VER) || (_MSC_VER < 700))\n#  define _halloc  halloc\n#  define _hfree   hfree\n#endif\n\nzvoid far *zcalloc (unsigned items, unsigned size)\n{\n    return (zvoid far *)_halloc((long)items, size);\n}\n\nzvoid zcfree (zvoid far *ptr)\n{\n    _hfree((void huge *)ptr);\n}\n#endif /* MSC || __WATCOMC__ */\n\n#endif /* MY_ZCALLOC */\n\n\n\n#ifndef FUNZIP\n\n/* This table can be static because it is pseudo-constant */\nstatic unsigned char cUpperCase[256], cLowerCase[256];\nstatic BOOL bInitialized=FALSE;\n\n/* Initialize the tables of upper- and lowercase characters, including\n   handling of country-dependent characters. */\n\nstatic void InitNLS(void)\n{\n  unsigned nCnt, nU;\n  COUNTRYCODE cc;\n\n  if (bInitialized == FALSE) {\n    bInitialized = TRUE;\n\n    for ( nCnt = 0; nCnt < 256; nCnt++ )\n      cUpperCase[nCnt] = cLowerCase[nCnt] = (unsigned char) nCnt;\n\n    cc.country = cc.codepage = 0;\n    DosMapCase(sizeof(cUpperCase), &cc, (PCHAR) cUpperCase);\n\n    for ( nCnt = 0; nCnt < 256; nCnt++ ) {\n      nU = cUpperCase[nCnt];\n      if (nU != nCnt && cLowerCase[nU] == (unsigned char) nU)\n        cLowerCase[nU] = (unsigned char) nCnt;\n    }\n\n    for ( nCnt = 'A'; nCnt <= 'Z'; nCnt++ )\n      cLowerCase[nCnt] = (unsigned char) (nCnt - 'A' + 'a');\n  }\n}\n\n\nint IsUpperNLS(int nChr)\n{\n  return (cUpperCase[nChr] == (unsigned char) nChr);\n}\n\n\nint ToLowerNLS(int nChr)\n{\n  return cLowerCase[nChr];\n}\n\n\nchar *StringLower(char *szArg)\n{\n  unsigned char *szPtr;\n\n  for ( szPtr = (unsigned char *) szArg; *szPtr; szPtr++ )\n    *szPtr = cLowerCase[*szPtr];\n  return szArg;\n}\n\n\n#ifdef MORE\nint screensize(int *tt_rows, int *tt_cols)\n{\n#ifdef __EMX__\n  int dst[2];\n  _scrsize(dst);\n  if (tt_rows != NULL) *tt_rows = dst[1];\n  if (tt_cols != NULL) *tt_cols = dst[0];\n#else\n  VIOMODEINFO vmi;\n  vmi.cb = sizeof(vmi);\n  VioGetMode(&vmi, 0);\n  if (tt_rows != NULL) *tt_rows = vmi.row;\n  if (tt_cols != NULL) *tt_cols = vmi.col;\n#endif\n  return 0;\n}\n#endif /* MORE */\n\n\n#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)\nvoid DebugMalloc(void)\n{\n  _dump_allocated(0); /* print out debug malloc memory statistics */\n}\n#endif\n\n\n#if defined(REENTRANT) && defined(USETHREADID)\nulg GetThreadId(void)\n{\n  PTIB   pptib;       /* Address of a pointer to the\n                         Thread Information Block */\n  PPIB   pppib;       /* Address of a pointer to the\n                         Process Information Block */\n\n  DosGetInfoBlocks(&pptib, &pppib);\n  return pptib->tib_ptib2->tib2_ultid;\n}\n#endif /* defined(REENTRANT) && defined(USETHREADID) */\n\n\nvoid os2GlobalsCtor(__GPRO)\n{\n  G.os2.nLastDrive = (USHORT)(-1);\n\n#ifdef OS2DLL\n  G.os2.rexx_mes = \"0\";\n#endif\n\n  InitNLS();\n}\n\n#endif /* !FUNZIP */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/os2acl.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* os2acl.c - access to OS/2 (LAN Server) ACLs\n *\n * Author:  Kai Uwe Rommel <rommel@ars.de>\n * Created: Mon Aug 08 1994\n *\n */\n\n/*\n * supported 32-bit compilers:\n * - emx+gcc\n * - IBM C Set++ 2.1 or newer\n * - Watcom C/C++ 10.0 or newer\n *\n * supported 16-bit compilers:\n * - MS C 6.00A\n * - Watcom C/C++ 10.0 or newer\n *\n * supported OS/2 LAN environments:\n * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)\n * - IBM Peer 1.0 (Warp Connect)\n */\n\n#ifdef KUR\n   static char *rcsid =\n   \"$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $\";\n   static char *rcsrev = \"$Revision: 1.3 $\";\n#endif\n\n/*\n * $Log: os2acl.c,v $\n * Revision 1.3  1996/04/03 19:18:27  rommel\n * minor fixes\n *\n * Revision 1.2  1996/03/30 22:03:52  rommel\n * avoid frequent dynamic allocation for every call\n * streamlined code\n *\n * Revision 1.1  1996/03/30 09:35:00  rommel\n * Initial revision\n *\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <malloc.h>\n\n#define INCL_NOPM\n#define INCL_DOS\n#define INCL_DOSERRORS\n#include <os2.h>\n\n#include \"os2/os2acl.h\"\n\n#define UNLEN 20\n\n#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)\n#define __32BIT__\n#endif\n\n#ifdef __32BIT__\ntypedef ULONG U_INT;\n#ifdef __EMX__\n#define PSTR16 _far16ptr\n#define PTR16(x) _emx_32to16(x)\n#else /* other 32-bit */\n#define PSTR16 PCHAR16\n#define PTR16(x) ((PCHAR16)(x))\n#endif\n#else /* 16-bit */\ntypedef USHORT U_INT;\n#define PSTR16 PSZ\n#define PTR16(x) (x)\n#endif\n\ntypedef struct access_list\n{\n  char acl_ugname[UNLEN+1];\n  char acl_pad;\n  USHORT acl_access;\n}\nACCLIST;\n\ntypedef struct access_info\n{\n  PSTR16 acc_resource_name;\n  USHORT acc_attr;\n  USHORT acc_count;\n}\nACCINFO;\n\nstatic ACCINFO *ai;\nstatic char *path, *data;\n\n#ifdef __32BIT__\n\n#ifdef __EMX__\n\nstatic USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);\nstatic USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nstatic USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);\n\nUSHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,\n                        PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+4+2+4+2+4);\n           _THUNK_FLAT (pszServer);\n           _THUNK_FLAT (pszResource);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_FLAT (pcbTotalAvail);\n           _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));\n}\n\nUSHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,\n                        PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+4+2+4+2+2);\n           _THUNK_FLAT (pszServer);\n           _THUNK_FLAT (pszResource);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_SHORT (sParmNum);\n           _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));\n}\n\nUSHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,\n                    PVOID pbBuffer, USHORT cbBuffer)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+2+4+2);\n           _THUNK_FLAT (pszServer);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));\n}\n\n#else /* other 32-bit */\n\nAPIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);\nAPIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nAPIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);\n\n#define _NetAccessGetInfo NetAccessGetInfo\n#define _NetAccessSetInfo NetAccessSetInfo\n#define _NetAccessAdd NetAccessAdd\n\n#if !defined(__IBMC__) || !defined(__TILED__)\n#define _tmalloc malloc\n#define _tfree free\n#endif\n\n#endif\n#else /* 16-bit */\n\nUSHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);\nUSHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nUSHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);\n\n#define _NetAccessGetInfo NetAccessGetInfo\n#define _NetAccessSetInfo NetAccessSetInfo\n#define _NetAccessAdd NetAccessAdd\n\n#define _tmalloc malloc\n#define _tfree free\n\n#define DosQueryProcAddr(handle, ord, name, funcptr) \\\n        DosGetProcAddr(handle, name, funcptr)\n#define DosQueryCurrentDir DosQCurDir\n#define DosQueryCurrentDisk DosQCurDisk\n\n#endif\n\n\nstatic BOOL acl_init(void)\n{\n  static BOOL initialized, netapi_avail;\n  HMODULE netapi;\n  char buf[256];\n\n  if (initialized)\n    return netapi_avail;\n\n  initialized = TRUE;\n\n  if (DosLoadModule(buf, sizeof(buf), \"NETAPI\", &netapi))\n    return FALSE;\n\n  if (DosQueryProcAddr(netapi, 0, \"NETACCESSGETINFO\", (PFN *) &_NetAccessGetInfo) ||\n      DosQueryProcAddr(netapi, 0, \"NETACCESSSETINFO\", (PFN *) &_NetAccessSetInfo) ||\n      DosQueryProcAddr(netapi, 0, \"NETACCESSADD\", (PFN *) &_NetAccessAdd))\n    return FALSE;\n\n#if defined(__WATCOMC__) && defined(__386__)\n  NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;\n  NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;\n  NetAccessAdd     = (PVOID) (ULONG) (PVOID16) NetAccessAdd;\n#endif\n\n  if ((path = _tmalloc(CCHMAXPATH)) == NULL)\n    return FALSE;\n  if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)\n    return FALSE;\n  if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)\n    return -1;\n\n  netapi_avail = TRUE;\n\n  return netapi_avail;\n}\n\nstatic void acl_mkpath(char *buffer, const char *source)\n{\n  char *ptr;\n  static char cwd[CCHMAXPATH];\n  static U_INT cwdlen;\n  U_INT cdrive;\n  ULONG drivemap;\n\n  if (isalpha((int)source[0]) && source[1] == ':')\n    buffer[0] = 0; /* fully qualified names */\n  else\n  {\n    if (cwd[0] == 0)\n    {\n      DosQueryCurrentDisk(&cdrive, &drivemap);\n      cwd[0] = (char)(cdrive + '@');\n      cwd[1] = ':';\n      cwd[2] = '\\\\';\n      cwdlen = sizeof(cwd) - 3;\n      DosQueryCurrentDir(0, cwd + 3, &cwdlen);\n      cwdlen = strlen(cwd);\n    }\n\n    if (source[0] == '/' || source[0] == '\\\\')\n    {\n      if (source[1] == '/' || source[1] == '\\\\')\n        buffer[0] = 0; /* UNC names */\n      else\n      {\n        strncpy(buffer, cwd, 2);\n        buffer[2] = 0;\n      }\n    }\n    else\n    {\n      strcpy(buffer, cwd);\n      if (cwd[cwdlen - 1] != '\\\\' && cwd[cwdlen - 1] != '/')\n        strcat(buffer, \"/\");\n    }\n  }\n\n  strcat(buffer, source);\n\n  for (ptr = buffer; *ptr; ptr++)\n    if (*ptr == '/')\n      *ptr = '\\\\';\n\n  if (ptr[-1] == '\\\\')\n    ptr[-1] = 0;\n\n  strupr(buffer);\n}\n\nstatic int acl_bin2text(char *data, char *text)\n{\n  ACCINFO *ai;\n  ACCLIST *al;\n  U_INT cnt, offs;\n\n  ai = (ACCINFO *) data;\n  al = (ACCLIST *) (data + sizeof(ACCINFO));\n\n  offs = sprintf(text, \"ACL1:%X,%d\\n\",\n                 ai -> acc_attr, ai -> acc_count);\n\n  for (cnt = 0; cnt < ai -> acc_count; cnt++)\n    offs += sprintf(text + offs, \"%s,%X\\n\",\n                    al[cnt].acl_ugname, al[cnt].acl_access);\n\n  return strlen(text);\n}\n\nint acl_get(char *server, const char *resource, char *buffer)\n{\n  USHORT datalen;\n  PSZ srv = NULL;\n  int rc;\n\n  if (!acl_init())\n    return -1;\n\n  if (server)\n    srv = server;\n\n  acl_mkpath(path, resource);\n  datalen = 0;\n\n  rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);\n\n  if (rc == 0)\n    acl_bin2text(data, buffer);\n\n  return rc;\n}\n\nstatic int acl_text2bin(char *data, char *text, char *path)\n{\n  ACCINFO *ai;\n  ACCLIST *al;\n  char *ptr, *ptr2;\n  U_INT cnt;\n\n  ai = (ACCINFO *) data;\n  ai -> acc_resource_name = PTR16(path);\n\n  if (sscanf(text, \"ACL1:%hX,%hd\",\n             &ai -> acc_attr, &ai -> acc_count) != 2)\n    return ERROR_INVALID_PARAMETER;\n\n  al = (ACCLIST *) (data + sizeof(ACCINFO));\n  ptr = strchr(text, '\\n') + 1;\n\n  for (cnt = 0; cnt < ai -> acc_count; cnt++)\n  {\n    ptr2 = strchr(ptr, ',');\n    strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);\n    al[cnt].acl_ugname[ptr2 - ptr] = 0;\n    sscanf(ptr2 + 1, \"%hx\", &al[cnt].acl_access);\n    ptr = strchr(ptr, '\\n') + 1;\n  }\n\n  return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);\n}\n\nint acl_set(char *server, const char *resource, char *buffer)\n{\n  USHORT datalen;\n  PSZ srv = NULL;\n\n  if (!acl_init())\n    return -1;\n\n  if (server)\n    srv = server;\n\n  acl_mkpath(path, resource);\n\n  ai -> acc_resource_name = PTR16(path);\n  ai -> acc_attr = 0;\n  ai -> acc_count = 0;\n\n  NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));\n  /* Ignore any errors, most probably because ACL already exists. */\n  /* In any such case, try updating the existing ACL. */\n\n  datalen = acl_text2bin(data, buffer, path);\n\n  return NetAccessSetInfo(srv, path, 1, data, datalen, 0);\n}\n\n/* end of os2acl.c */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/os2acl.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* os2acl.h\n *\n * Author:  Kai Uwe Rommel <rommel@ars.de>\n * Created: Fri Mar 29 1996\n */\n\n/* $Id: os2acl.h,v 1.1 1996/03/30 09:35:00 rommel Exp rommel $ */\n\n/*\n * $Log: os2acl.h,v $\n * Revision 1.1  1996/03/30 09:35:00  rommel\n * Initial revision\n *\n */\n\n#ifndef _OS2ACL_H\n#define _OS2ACL_H\n\n#define ACL_BUFFERSIZE 4096\n\nint acl_get(char *server, const char *resource, char *buffer);\nint acl_set(char *server, const char *resource, char *buffer);\n\n#endif /* _OS2ACL_H */\n\n/* end of os2acl.h */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/os2cfg.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    OS/2 specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __os2cfg_h\n#define __os2cfg_h\n\n#ifdef MSDOS\n#  include <dos.h>           /* for REGS macro (TC) or _dos_setftime (MSC) */\n#  ifdef __TURBOC__          /* includes Power C */\n#    include <sys/timeb.h>   /* for structure ftime */\n#    ifndef __BORLANDC__     /* there appears to be a bug (?) in Borland's */\n#      include <mem.h>       /*  MEM.H related to __STDC__ and far poin-   */\n#    endif                   /*  ters. (dpk)  [mem.h included for memcpy]  */\n#  endif\n#endif /* MSDOS */\n\n#ifdef __IBMC__\n#  define S_IFMT 0xF000\n#  define timezone _timezone            /* (underscore names work with    */\n#  define tzset _tzset                  /*  all versions of C Set)        */\n#  define PIPE_ERROR (errno == EERRSET || errno == EOS2ERR)\n#endif /* __IBMC__ */\n\n#ifdef __WATCOMC__\n#  ifdef __386__\n#    ifndef WATCOMC_386\n#      define WATCOMC_386\n#    endif\n#    define __32BIT__\n#    undef far\n#    define far\n#    undef near\n#    define near\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  else /* !__386__ */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [ax dx] \\\n                                      modify [ax cx dx bx]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [ax] \\\n                                      modify [ax cx dx bx]\n#    endif /* !USE_ZLIB */\n#  endif /* ?__386__ */\n#endif /* __WATCOMC__ */\n\n#ifdef __EMX__\n#  ifndef __32BIT__\n#    define __32BIT__\n#  endif\n#  define far\n#endif\n\n#ifndef __32BIT__\n#  define __16BIT__\n#endif\n\n#ifdef MSDOS\n#  undef MSDOS\n#endif\n\n#if defined(M_I86CM) || defined(M_I86LM)\n#  define MED_MEM\n#endif\n#if (defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__))\n#  define MED_MEM\n#endif\n#ifdef __16BIT__\n#  ifndef MED_MEM\n#    define SMALL_MEM\n#  endif\n#endif\n\n#ifdef __16BIT__\n# if defined(MSC) || defined(__WATCOMC__)\n#   include <malloc.h>\n#   define nearmalloc _nmalloc\n#   define nearfree _nfree\n# endif\n# if defined(__TURBOC__) && defined(DYNALLOC_CRCTAB)\n#   if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#     undef DYNALLOC_CRCTAB\n#   endif\n# endif\n# ifndef nearmalloc\n#   define nearmalloc malloc\n#   define nearfree free\n# endif\n# ifdef USE_DEFLATE64\n#   if (defined(M_I86TM) || defined(M_I86SM) || defined(M_I86MM))\n#     error Deflate64(tm) requires compact or large memory model\n#   endif\n#   if (defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__))\n#     error Deflate64(tm) requires compact or large memory model\n#   endif\n    /* the 64k history buffer for Deflate64 must be allocated specially */\n#   define MALLOC_WORK\n#   define MY_ZCALLOC\n# endif\n#endif\n\n/* TIMESTAMP is now supported on OS/2, so enable it by default */\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#ifndef RESTORE_ACL\n#  define RESTORE_ACL\n#endif\n\n#ifndef OS2_EAS\n#  define OS2_EAS    /* for -l and -v listings (list.c) */\n#endif\n\n#ifdef isupper\n#  undef isupper\n#endif\n#ifdef tolower\n#  undef tolower\n#endif\n#define isupper(x)   IsUpperNLS((unsigned char)(x))\n#define tolower(x)   ToLowerNLS((unsigned char)(x))\n#ifndef NO_STRNICMP     /* use UnZip's zstrnicmp(), because some compilers  */\n#  define NO_STRNICMP   /*  don't provide a NLS-aware strnicmp() function  */\n#endif\n\n#define USETHREADID\n\n/* handlers for OEM <--> ANSI string conversions */\n#ifndef _OS2_ISO_ANSI\n   /* use home-brewed conversion functions; internal charset is OEM */\n#  ifdef CRTL_CP_IS_ISO\n#    undef CRTL_CP_IS_ISO\n#  endif\n#  ifndef CRTL_CP_IS_OEM\n#    define CRTL_CP_IS_OEM\n#  endif\n#endif\n\n/* screen size detection */\n#define SCREENWIDTH 80\n#define SCREENSIZE(scrrows, scrcols)  screensize(scrrows, scrcols)\nint screensize(int *tt_rows, int *tt_cols);\n\n/* on the OS/2 console screen, line-wraps are always enabled */\n#define SCREENLWRAP 1\n\n#endif /* !__os2cfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/os2data.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  os2data.h\n\n  OS/2-specific structures and data to be included in the global data struc-\n  ture.\n\n  ---------------------------------------------------------------------------*/\n\n\n#define MAXNAMLEN  256\n#define MAXPATHLEN 256\n#define MAXLEN     256    /* temporary buffer length */\n#define IBUF_LEN   4096   /* input buffer length */\n\n#define INCL_NOPM\n#define INCL_VIO\n#define INCL_DOSNLS\n#define INCL_DOSPROCESS\n#define INCL_DOSDEVICES\n#define INCL_DOSDEVIOCTL\n#define INCL_DOSERRORS\n#define INCL_DOSMISC\n\n#if (defined(OS2DLL) && !defined(DLL))\n#  undef OS2DLL\n#endif\n\n#ifdef OS2DLL\n#  define INCL_REXXSAA\n#  include <rexxsaa.h>\n#endif\n\n#include <os2.h>\n\n\nstruct direct\n{\n  ino_t    d_ino;                   /* a bit of a farce */\n  int      d_reclen;                /* more farce */\n  int      d_namlen;                /* length of d_name */\n  char     d_name[MAXNAMLEN + 1];   /* null terminated */\n  /* nonstandard fields */\n  long     d_size;                  /* size in bytes */\n  unsigned d_mode;                  /* MS-DOS or OS/2 file attributes */\n  unsigned d_time;\n  unsigned d_date;\n};\n\n/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel).  The\n * find_first and find_next calls deliver these data without any extra cost.\n * If these data are needed, the fields save a lot of extra calls to stat()\n * (each stat() again performs a find_first call !).\n */\n\nstruct _dircontents\n{\n  char *_d_entry;\n  long _d_size;\n  unsigned _d_mode, _d_time, _d_date;\n  struct _dircontents *_d_next;\n};\n\ntypedef struct _dirdesc\n{\n  int  dd_id;                   /* uniquely identify each open directory */\n  long dd_loc;                  /* where we are in directory entry is this */\n  struct _dircontents *dd_contents;   /* pointer to contents of dir */\n  struct _dircontents *dd_cp;         /* pointer to current position */\n}\nDIR;\n\n\nstruct os2Global {\n\n#ifndef SFX\n   HDIR hdir;\n#ifdef __32BIT__\n   ULONG count;\n   FILEFINDBUF3 find;\n#else\n   USHORT count;\n   FILEFINDBUF find;\n#endif\n#endif /* !SFX */\n\n   int created_dir;        /* used by mapname(), checkdir() */\n   int renamed_fullpath;   /* ditto */\n   int fnlen;              /* ditto */\n#ifdef __32BIT__\n   ULONG nLabelDrive;      /* ditto */\n#else\n   USHORT nLabelDrive;\n#endif\n   int longnameEA;         /* checkdir(), close_outfile() */\n   char *lastpathcomp;     /* ditto */\n\n   struct direct dp;\n   int lower;\n   USHORT nLastDrive, nResult;\n\n   DIR *wild_dir;\n   ZCONST char *wildname;\n   char *dirname, matchname[FILNAMSIZ];\n   int notfirstcall, have_dirname, dirnamelen;\n\n   int rootlen;          /* length of rootpath */\n   char *rootpath;       /* user's \"extract-to\" directory */\n   char *buildpathHPFS;  /* full path (so far) to extracted file, */\n   char *buildpathFAT;   /*  both HPFS/EA (main) and FAT versions */\n   char *endHPFS;        /* corresponding pointers to end of */\n   char *endFAT;         /*  buildpath ('\\0') */\n\n#ifdef OS2DLL\n   char buffer[IBUF_LEN];\n   char output_var[MAXLEN];\n   char getvar_buf[MAXLEN];\n   int getvar_len;\n\n   int output_idx;\n   int stem_len;\n   int putchar_idx;\n   int rexx_error;\n   char *rexx_mes;\n\n   SHVBLOCK request;\n#endif\n};\n\n\n#define SYSTEM_SPECIFIC_GLOBALS struct os2Global os2;\n#define SYSTEM_SPECIFIC_CTOR    os2GlobalsCtor\n\n#ifdef OS2DLL\n#  ifdef API_DOC\n#    define SYSTEM_API_BRIEF    REXXBrief\n#    define SYSTEM_API_DETAILS  REXXDetails\n     extern char *REXXBrief;\n     extern APIDocStruct REXXDetails[];\n#  endif\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/rexxapi.c",
    "content": "/*\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/**********************************************************************\n*   REXXAPI.C                                                         *\n*                                                                     *\n*   This program adds a ZIP engine directly to the REXX language.     *\n*   The functions are:                                                *\n*       UZDropFuncs         -- Makes all functions in this package    *\n*                              unknown to REXX.                       *\n*       UZLoadFuncs         -- Makes all functions in this package    *\n*                              known to REXX so REXX programs may     *\n*                              call them.                             *\n*       UZFileTree          -- Searches for files matching a given    *\n*                              filespec, including files in           *\n*                              subdirectories.                        *\n*       UZUnZip             -- Unzip command-line entry point.        *\n*                              This is functionally equivalent to     *\n*                              using Unzip as an external program.    *\n*       UZUnZipToVar            -- Unzip one file to a variable       *\n*       UZUnZipToStem       -- Unzip files to a variable array        *\n*       UZVer               -- Returns the Unzip version number       *\n*                                                                     *\n**********************************************************************/\n/* Include files */\n\n#ifdef OS2DLL\n\n#define  INCL_DOS\n#define  INCL_DOSMEMMGR\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#define UNZIP_INTERNAL\n#include \"../unzip.h\"\n#include \"../unzvers.h\"\n\n\n/*********************************************************************/\n/*  Various definitions used by various functions.                   */\n/*********************************************************************/\n\nRexxFunctionHandler UZDropFuncs;\nRexxFunctionHandler UZLoadFuncs;\nRexxFunctionHandler UZFileTree;\nRexxFunctionHandler UZUnZip;\nRexxFunctionHandler UZUnZipToVar;\nRexxFunctionHandler UZUnZipToStem;\nRexxFunctionHandler UZVer;\nRexxFunctionHandler UZAPIVer;\n\n\nint SetOutputVar(__GPRO__ const char *name);\nint SetOutputVarStem(__GPRO__ const char *name);\nint SetOutputVarLength(__GPRO);\nint WriteToVariable(__GPRO__ const char *name, char *buffer, int len);\nint PrintToSubVariable(__GPRO__ int idx, const char *format,...);\nint PrintToVariable(__GPRO__ const char *name, const char *format,...);\nint _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr);\nint TextSetNext(__GPRO__ char *format, int len, int all);\n\n#define EZRXSTRING(r,p)  {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);}\n\n\n/*********************************************************************/\n/* RxFncTable                                                        */\n/*   Array of names of the UNZIPAPI functions.                       */\n/*   This list is used for registration and deregistration.          */\n/*********************************************************************/\n\nstatic PSZ  RxFncTable[] =\n   {\n      \"UZDropFuncs\",\n      \"UZLoadFuncs\",\n      \"UZFileSearch\",\n      \"UZFileTree\",\n      \"UZUnZip\",\n      \"UZUnZipToVar\",\n      \"UZUnZipToStem\",\n      \"UZVer\",\n   };\n\n/*********************************************************************/\n/* Numeric Error Return Strings                                      */\n/*********************************************************************/\n\n#define  NO_UTIL_ERROR    \"0\"          /* No error whatsoever        */\n#define  ERROR_NOMEM      \"2\"          /* Insufficient memory        */\n\n/*********************************************************************/\n/* Numeric Return calls                                              */\n/*********************************************************************/\n\n#define  INVALID_ROUTINE 40            /* Raise Rexx error           */\n#define  VALID_ROUTINE    0            /* Successful completion      */\n\n/*********************************************************************/\n/* Some useful macros                                                */\n/*********************************************************************/\n\n#define BUILDRXSTRING(t, s) { \\\n  strcpy((t)->strptr,(s));\\\n  (t)->strlength = strlen((s)); \\\n}\n\n\n/*********************************************************************/\n/****************  UNZIPAPI Supporting Functions  ********************/\n/****************  UNZIPAPI Supporting Functions  ********************/\n/****************  UNZIPAPI Supporting Functions  ********************/\n/*********************************************************************/\n\n\nint RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr)\n{\n  int ret = G.os2.rexx_error;\n  if (G.filenotfound)\n    G.os2.rexx_mes = \"file not found\";\n  if (*G.os2.rexx_mes != '0') {\n    if (retstr->strlength > 255) {\n      DosFreeMem(retstr->strptr);\n      retstr->strptr = NULL;\n    }\n  } else if (nodefault)\n    goto noBuild;\n  BUILDRXSTRING(retstr, G.os2.rexx_mes);\n noBuild:\n  DESTROYGLOBALS();\n  return ret;\n}\n\n/* Get a variable from REXX, return 0 if OK */\nint GetVariable(__GPRO__ const char *name)\n{\n  G.os2.request.shvnext = NULL;\n  EZRXSTRING(G.os2.request.shvname, name);\n  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;\n  G.os2.request.shvvalue.strptr = G.os2.buffer;\n  G.os2.request.shvvalue.strlength = IBUF_LEN;\n  G.os2.request.shvvaluelen = IBUF_LEN;\n  G.os2.request.shvcode = RXSHV_SYFET;\n  G.os2.request.shvret = 0;\n  switch (RexxVariablePool(&G.os2.request)) {\n  case RXSHV_MEMFL:\n    G.os2.rexx_mes = ERROR_NOMEM;\n    break;\n  case RXSHV_BADN:\n  case RXSHV_NEWV:\n    G.os2.request.shvvaluelen = 0;\n  case RXSHV_OK:\n    *(G.os2.buffer+G.os2.request.shvvaluelen) = 0;\n    return G.os2.request.shvvaluelen;\n  }\n  return 0;\n}\n\n\n/* Get REXX compound variable */\n/* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */\nint GetVariableIndex(__GPRO__ int index)\n{\n  sprintf(G.os2.getvar_buf+G.os2.getvar_len,\"%d\",index);\n  return GetVariable(__G__ G.os2.getvar_buf);\n}\n\n\n/* Transfer REXX array to standard C string array */\n/* Returns number of elements */\n/* User is responsible for calling KillStringArray */\n\nint CompoundToStringArray(__GPRO__ char ***pointer, const char *name)\n{\n  int count;\n  int total;\n  char **trav;\n\n  G.os2.getvar_len = strlen(name);\n  memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1);\n  if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.')\n    *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0;\n\n  if (GetVariableIndex(__G__ 0))\n    return 0;\n\n  total = atoi(G.os2.buffer);\n  *pointer = (char **)malloc((total+1)<<2);\n  trav = *pointer;\n  for (count = 1; count <= total; count++) {\n    GetVariableIndex(__G__ count);\n    trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1);\n    strcpy(trav[count-1],G.os2.buffer);\n  }\n  trav[count-1] = NULL;\n  return total;\n}\n\n\n/* Kill string array created by CompoundToStringArray */\n\nvoid KillStringArray(char **pointer)\n{\n  char **trav=pointer;\n  while (*trav != NULL) {\n    free(*trav);\n    trav++;\n  }\n  free(pointer);\n}\n\n\n/*************************************************************************\n* Function:  UZDropFuncs                                                 *\n*                                                                        *\n* Syntax:    call UZDropFuncs                                            *\n*                                                                        *\n* Return:    NO_UTIL_ERROR - Successful.                                 *\n*************************************************************************/\n\nULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[],\n                  CHAR *queuename, RXSTRING *retstr)\n{\n  INT     entries;                     /* Num of entries             */\n  INT     j;                           /* Counter                    */\n\n  if (numargs != 0)                    /* no arguments for this      */\n    return INVALID_ROUTINE;            /* raise an error             */\n\n  retstr->strlength = 0;               /* return a null string result*/\n\n  entries = sizeof(RxFncTable)/sizeof(PSZ);\n\n  for (j = 0; j < entries; j++)\n    RexxDeregisterFunction(RxFncTable[j]);\n\n  return VALID_ROUTINE;                /* no error on call           */\n}\n\n\n/*************************************************************************\n* Function:  UZFileTree                                                  *\n*                                                                        *\n* Syntax:    call UZFileTree zipfile, stem[, include-filespec]           *\n*                                [, exclude-filespec][, options]         *\n*                                                                        *\n* Params:    zipfile  - Name of zip file to search.                      *\n*            stem     - Name of stem var to store results in.            *\n*            include  - Filespec to search for (may include * and ?).    *\n*            exclude  - Filespec to exclude (may include * and ?).       *\n*            options  - Either of the following:                         *\n*                       'F' - Give file statistics.                      *\n*                          Length Date Time Name                         *\n*                       'Z' - Give zip statistics, too.                  *\n*                          Length Method Size Ratio Date Time CRC-32 Name*\n*                       Default is to return only filenames              *\n*                                                                        *\n* Return:    NO_UTIL_ERROR   - Successful.                               *\n*            ERROR_NOMEM     - Out of memory.                            *\n*************************************************************************/\n\nULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[],\n                 CHAR *queuename, RXSTRING *retstr)\n{\n                                       /* validate arguments         */\n  char *incname[2];\n  char *excname[2];\n  CONSTRUCTGLOBALS();\n\n  if (numargs < 2 || numargs > 5 ||\n      !RXVALIDSTRING(args[0]) ||\n      !RXVALIDSTRING(args[1]) ||\n      args[0].strlength > 255) {\n    DESTROYGLOBALS();\n    return INVALID_ROUTINE;            /* Invalid call to routine    */\n  }\n                                       /* initialize data area       */\n  SetOutputVarStem(__G__ args[1].strptr);\n  G.wildzipfn = args[0].strptr;\n  G.process_all_files = TRUE;\n\n  uO.lflag = 1;\n  uO.zipinfo_mode = TRUE;\n  uO.C_flag = 1;\n  G.extract_flag = FALSE;\n  uO.qflag = 2;\n\n  if (numargs >= 3 &&                  /* check third option         */\n      !RXNULLSTRING(args[2]) &&\n      args[2].strlength > 0) {            /* a zero length string isn't */\n    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {\n      G.pfnames = incname;\n      incname[0] = args[2].strptr;\n      incname[1] = NULL;\n      G.filespecs = 1;\n    }\n    G.process_all_files = FALSE;\n  }\n\n  if (numargs >= 4 &&                  /* check third option         */\n      !RXNULLSTRING(args[3]) &&\n      args[3].strlength > 0) {            /* a zero length string isn't */\n    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {\n      G.pxnames = excname;\n      excname[0] = args[3].strptr;\n      excname[1] = NULL;\n      G.xfilespecs = 1;\n    }\n    G.process_all_files = FALSE;\n  }\n\n  if (numargs == 5 &&                  /* check third option         */\n      !RXNULLSTRING(args[4]) &&\n      args[4].strlength > 0) {            /* a zero length string isn't */\n    int first = *args[4].strptr & 0x5f;\n\n    if (first == 'Z')\n      uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE;\n    else if (first == 'F')\n      uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE;\n  }\n\n  process_zipfiles(__G);\n  SetOutputVarLength(__G);\n  if (G.filespecs > 0 && G.pfnames != incname)\n    KillStringArray(G.pfnames);\n  if (G.xfilespecs > 0 && G.pxnames != excname)\n    KillStringArray(G.pxnames);\n  return RexxReturn(__G__ 0,retstr);        /* no error on call           */\n}\n\n\n/*************************************************************************\n* Function:  UZUnZipToVar                                                *\n*                                                                        *\n* Syntax:    call UZUnZipToVar zipfile, filespec [, stem]                *\n*                                                                        *\n* Params:    zipfile  - Name of zip file to search.                      *\n*            filespec - File to extract                                  *\n*            stem     - If you specify a stem variable, the file will be *\n*                       extracted to the variable, one line per index    *\n*                       In this case, 0 will be returned                 *\n*                                                                        *\n* Return:    Extracted file                                              *\n*            ERROR_NOMEM     - Out of memory.                            *\n*************************************************************************/\n\nULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[],\n                          CHAR *queuename, RXSTRING *retstr)\n{\n  CONSTRUCTGLOBALS();\n  UzpBuffer *ub = (UzpBuffer *)retstr;\n                                       /* validate arguments         */\n  if (numargs < 2 || numargs > 3 ||\n      !RXVALIDSTRING(args[0]) ||\n      !RXVALIDSTRING(args[1]) ||\n      args[0].strlength == 0 ||\n      args[1].strlength == 0) {\n    DESTROYGLOBALS();\n    return INVALID_ROUTINE;            /* Invalid call to routine    */\n  }\n\n  uO.C_flag = 1;\n  G.redirect_data=1;\n  if (numargs == 3) {\n    if (!RXVALIDSTRING(args[2]) ||\n        RXNULLSTRING(args[1]) ||\n        args[2].strlength == 0) {\n      DESTROYGLOBALS();\n      return INVALID_ROUTINE;            /* Invalid call to routine    */\n    }\n    SetOutputVarStem(__G__ args[2].strptr);\n    G.redirect_text = 0;\n    G.redirect_data++;\n  }\n  unzipToMemory(__G__ args[0].strptr, args[1].strptr,\n                G.redirect_data==1 ? ub : NULL);\n  return RexxReturn(__G__ G.redirect_data==1,retstr);\n}\n\n\n/*************************************************************************\n* Function:  UZUnZipToStem                                               *\n*                                                                        *\n* Syntax:    call UZUnZipToStem zipfile, stem[, include-filespec]        *\n*                                [, exclude-filespec][, mode]            *\n*                                                                        *\n* Params:    zipfile  - Name of zip file to search.                      *\n*            stem     - Name of stem var to store files in.              *\n*            include  - Filespec to search for (may include * and ?).    *\n*            exclude  - Filespec to exclude (may include * and ?).       *\n*            mode     - Specifies 'F'lat or 'T'ree mode.  Umm, this is   *\n*                        hard to explain so I'll give an example, too.   *\n*                       Assuming a file unzip.zip containing:            *\n*                               unzip.c                                  *\n*                               unshrink.c                               *\n*                               extract.c                                *\n*                               os2/makefile.os2                         *\n*                               os2/os2.c                                *\n*                               os2/dll/dll.def                          *\n*                               os2/dll/unzipapi.c                       *\n*                                                                        *\n*                       -- In flat mode, each file is stored in          *\n*                          stem.fullname i.e. stem.\"os2/dll/unzipapi.c\"  *\n*                          A list of files is created in stem.<index>    *\n*                                                                        *\n*                       Flat mode returns:                               *\n*                               stem.0 = 7                               *\n*                               stem.1 = unzip.c                         *\n*                               stem.2 = unshrink.c                      *\n*                               stem.3 = extract.c                       *\n*                               stem.4 = os2/makefile.os2                *\n*                               stem.5 = os2/os2.c                       *\n*                               stem.6 = os2/dll/dll.def                 *\n*                               stem.7 = os2/dll/unzipapi.c              *\n*                                                                        *\n*                       And the following contain the contents of the    *\n*                       various programs:                                *\n*                               stem.unzip.c                             *\n*                               stem.unshrink.c                          *\n*                               stem.extract.c                           *\n*                               stem.os2/makefile.os2                    *\n*                               stem.os2/os2.c                           *\n*                               stem.os2/dll/dll.def                     *\n*                               stem.os2/dll/unzipapi.c                  *\n*                                                                        *\n*                       -- In tree mode, slashes are converted to periods*\n*                          in the pathname thus the above file would have*\n*                          been stored in stem.os2.dll.unzipapi.c        *\n*                          The index would then be stored in stem.OS2.   *\n*                          DLL.<index>.                                  *\n*                                                                        *\n*                       NOTE: All path names are converted to uppercase  *\n*                                                                        *\n*                       Tree mode returns:                               *\n*                               stem.0 = 4                               *\n*                               stem.1 = unzip.c                         *\n*                               stem.2 = unshrink.c                      *\n*                               stem.3 = extract.c                       *\n*                               stem.4 = OS2/                            *\n*                                                                        *\n*                               stem.OS2.0 = 3                           *\n*                               stem.OS2.1 = makefile.os2                *\n*                               stem.OS2.2 = os2.c                       *\n*                               stem.OS2.3 = DLL/                        *\n*                                                                        *\n*                               stem.OS2.DLL.0 = 2                       *\n*                               stem.OS2.DLL.1 = def                     *\n*                               stem.OS2.DLL.2 = unzipapi.c              *\n*                                                                        *\n*                       And the following contain the contents of the    *\n*                       various programs:                                *\n*                               stem.unzip.c                             *\n*                               stem.unshrink.c                          *\n*                               stem.extract.c                           *\n*                               stem.OS2.makefile.os2                    *\n*                               stem.OS2.os2.c                           *\n*                               stem.OS2.DLL.dll.def                     *\n*                               stem.OS2.DLL.unzipapi.c                  *\n*                                                                        *\n*                                                                        *\n* Return:    NO_UTIL_ERROR   - Successful.                               *\n*            ERROR_NOMEM     - Out of memory.                            *\n*************************************************************************/\n\nULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[],\n                          CHAR *queuename, RXSTRING *retstr)\n{\n  char *incname[2];\n  char *excname[2];\n  CONSTRUCTGLOBALS();\n                                       /* validate arguments         */\n  if (numargs < 2 || numargs > 5 ||\n      !RXVALIDSTRING(args[0]) ||\n      !RXVALIDSTRING(args[1]) ||\n      args[0].strlength > 255) {\n    DESTROYGLOBALS();\n    return INVALID_ROUTINE;            /* Invalid call to routine    */\n  }\n                                       /* initialize data area       */\n  G.wildzipfn = args[0].strptr;\n  G.process_all_files = TRUE;\n\n  uO.C_flag = 1;\n  G.extract_flag = TRUE;\n  SetOutputVarStem(__G__ args[1].strptr);\n  G.redirect_data = 3;\n  G.redirect_text = 0;\n\n  if (numargs >= 3 &&                  /* check third option         */\n      !RXNULLSTRING(args[2]) &&\n      args[2].strlength > 0) {            /* a zero length string isn't */\n    if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {\n      G.pfnames = incname;\n      incname[0] = args[2].strptr;\n      incname[1] = NULL;\n      G.filespecs = 1;\n    }\n    G.process_all_files = FALSE;\n  }\n\n  if (numargs >= 4 &&                  /* check third option         */\n      !RXNULLSTRING(args[3]) &&\n      args[3].strlength > 0) {            /* a zero length string isn't */\n    if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {\n      G.pxnames = excname;\n      excname[0] = args[3].strptr;\n      excname[1] = NULL;\n      G.xfilespecs = 1;\n    }\n    G.process_all_files = FALSE;\n  }\n\n  if (numargs == 5 &&                  /* check third option         */\n      !RXNULLSTRING(args[4]) &&\n      (*args[4].strptr & 0x5f) == 'T') {\n    G.redirect_data++;\n    G.os2.request.shvnext = NULL;\n    EZRXSTRING(G.os2.request.shvname, args[4].strptr);\n    G.os2.request.shvnamelen = G.os2.request.shvname.strlength;\n    G.os2.request.shvcode = RXSHV_SYDRO;\n    G.os2.request.shvret = 0;\n    RexxVariablePool(&G.os2.request);\n  }\n\n\n  uO.qflag = 2;\n\n  process_zipfiles(__G);\n  if (G.filespecs > 0 && G.pfnames != incname)\n    KillStringArray(G.pfnames);\n  if (G.xfilespecs > 0 && G.pxnames != excname)\n    KillStringArray(G.pxnames);\n  if (G.redirect_data == 3)\n    SetOutputVarLength(__G);\n  return RexxReturn(__G__ 0,retstr);            /* no error on call           */\n}\n\n\n/*************************************************************************\n* Function:  UZLoadFuncs                                                 *\n*                                                                        *\n* Syntax:    call UZLoadFuncs [option]                                   *\n*                                                                        *\n* Params:    none                                                        *\n*                                                                        *\n* Return:    null string                                                 *\n*************************************************************************/\n\nULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[],\n                           CHAR *queuename, RXSTRING *retstr)\n{\n  INT    entries;                      /* Num of entries             */\n  INT    j;                            /* Counter                    */\n\n  retstr->strlength = 0;               /* set return value           */\n                                       /* check arguments            */\n  if (numargs > 0)\n    return INVALID_ROUTINE;\n\n  entries = sizeof(RxFncTable)/sizeof(PSZ);\n\n  for (j = 0; j < entries; j++) {\n    RexxRegisterFunctionDll(RxFncTable[j],\n          \"UNZIP32\", RxFncTable[j]);\n  }\n  return VALID_ROUTINE;\n}\n\n\n\n/*************************************************************************\n* Function:  UZVer                                                       *\n*                                                                        *\n* Syntax:    call UZVer                                                  *\n*                                                                        *\n* Return:    Version of Unzip                                            *\n*************************************************************************/\n\nULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[],\n                        CHAR *queuename, RXSTRING *retstr)\n{\n  if (numargs > 1)                    /* validate arg count         */\n    return INVALID_ROUTINE;\n\n  if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L')\n    /* strcpy( retstr->strptr, UZ_VERNUM );    \"5.13a BETA\" */\n    sprintf( retstr->strptr, \"%d.%d%d%s\", UZ_MAJORVER, UZ_MINORVER,\n      UZ_PATCHLEVEL, UZ_BETALEVEL );\n  else\n    /* strcpy( retstr->strptr, UZ_VERSION );   UZ_VERNUM\" of 26 Sep 94\" */\n    sprintf( retstr->strptr, \"%d.%d%d%s of %s\", UZ_MAJORVER, UZ_MINORVER,\n      UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE );\n  retstr->strlength = strlen(retstr->strptr);\n  return VALID_ROUTINE;\n}\n\n\n/*************************************************************************\n* Function:  UZUnZip                                                     *\n*                                                                        *\n* Syntax:    call UZUnZip                                                *\n*                                                                        *\n* Return:    Unzip return code                                           *\n*************************************************************************/\n\nULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[],\n                        CHAR *queuename, RXSTRING *retstr)\n{\n  char *argv[30];\n  char *scan;\n  int argc=0;\n  int idx;\n  CONSTRUCTGLOBALS();\n\n  if (numargs < 1 || numargs > 2 ||\n      args[0].strlength > 255) {\n    DESTROYGLOBALS();\n    return INVALID_ROUTINE;            /* Invalid call to routine    */\n  }\n                                       /* initialize data area       */\n  if (numargs == 2)\n    SetOutputVarStem(__G__ args[1].strptr);\n\n  scan = args[0].strptr;\n  argv[argc++] = \"\";         /* D:\\\\SOURCECODE\\\\UNZIP51S\\\\UNZIP.COM\"; */\n  while (*scan == ' ')\n    scan++;\n  argv[argc++] = scan;\n  while ( (scan = strchr(scan,' ')) != NULL) {\n    *scan++ = 0;\n    while (*scan == ' ')\n      scan++;\n    argv[argc++] = scan;\n  }\n  if (*argv[argc-1] == 0)\n    argc--;\n  argv[argc] = 0;\n\n         /* GRR:  should resetMainFlags() be called in here somewhere? */\n\n  sprintf(retstr->strptr, \"%d\", unzip(__G__ argc, argv));   /* a.k.a. MAIN() */\n  if (numargs == 2)\n    SetOutputVarLength(__G);\n  retstr->strlength = strlen(retstr->strptr);\n  return RexxReturn(__G__ 1,retstr);\n}\n\nint varmessage(__GPRO__ ZCONST uch *buf, ulg size)\n{\n  if (size > 0)\n    memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size);\n    G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0);\n  return 0;\n}\n\nint varputchar(__GPRO__ int c)\n{\n  G.os2.buffer[G.os2.putchar_idx++] = c;\n  if (c == '\\n') {\n    G.os2.buffer[G.os2.putchar_idx] = 0;\n    if (G.os2.output_var[0])\n      G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0);\n    else {\n      G.os2.buffer[--G.os2.putchar_idx] = 0;\n      puts(G.os2.buffer);\n      G.os2.putchar_idx = 0;\n    }\n  }\n  return 1;\n}\n\n\n\nint SetOutputVarStem(__GPRO__ const char *name)\n{\n  int len=strlen(name);\n  G.redirect_text=1;\n  G.os2.output_idx = 0;\n  strcpy(G.os2.output_var, name);\n  if (len) {\n    strupr(G.os2.output_var);                 /* uppercase the name         */\n    if (*(G.os2.output_var+len-1) != '.') {\n      *(G.os2.output_var+len) = '.';\n      len++;\n      *(G.os2.output_var+len) = 0;\n    }\n    WriteToVariable(__G__ G.os2.output_var,\"\",0);\n  }\n  G.os2.stem_len = len;\n  return G.os2.stem_len;\n}\n\nint SetOutputVar(__GPRO__ const char *name)\n{\n  int len=strlen(name);\n  G.redirect_text=1;\n  G.os2.output_idx = 0;\n  strcpy(G.os2.output_var, name);\n  strupr(G.os2.output_var);                 /* uppercase the name         */\n  if (*(name+len-1) == '.')\n    G.os2.stem_len = len;\n  else\n    G.os2.stem_len = 0;\n  return G.os2.stem_len;\n}\n\nint SetOutputVarLength(__GPRO)\n{\n  if (G.os2.stem_len > 0) {\n    if (G.os2.putchar_idx)\n      TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1);\n    return PrintToSubVariable(__G__ 0,\"%d\",G.os2.output_idx);\n  }\n  return 0;\n}\n\nint PrintToVariable(__GPRO__ const char *name, const char *format,...)\n{\n  va_list arg_ptr;\n  int ret;\n\n  va_start(arg_ptr, format);\n  ret = _PrintToVariable(__G__ name, format, arg_ptr);\n  va_end(arg_ptr);\n  return ret;\n}\n\nint WriteToVariable(__GPRO__ const char *name, char *buffer, int len)\n{\n  G.os2.request.shvnext = NULL;\n  EZRXSTRING(G.os2.request.shvname, name);\n  G.os2.request.shvnamelen = G.os2.request.shvname.strlength;\n  G.os2.request.shvvalue.strptr = buffer;\n  G.os2.request.shvvalue.strlength = len;\n  G.os2.request.shvvaluelen = len;\n  G.os2.request.shvcode = RXSHV_SET;\n  G.os2.request.shvret = 0;\n  switch (RexxVariablePool(&G.os2.request)) {\n  case RXSHV_BADN:\n    G.os2.rexx_error = INVALID_ROUTINE;\n    break;\n  case RXSHV_MEMFL:\n    G.os2.rexx_mes = ERROR_NOMEM;\n    break;\n  case RXSHV_OK:\n    return 0;\n  }\n  return INVALID_ROUTINE;      /* error on non-zero          */\n}\n\nint _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr)\n{\n  int ret = vsprintf(G.os2.buffer, format, arg_ptr);\n  WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer));\n  return ret;\n}\n\nint PrintToSubVariable(__GPRO__ int idx, const char *format, ...)\n{\n  va_list arg_ptr;\n  int ret;\n\n  if (G.os2.stem_len == 0)\n    return INVALID_ROUTINE;      /* error on non-zero          */\n  sprintf(G.os2.output_var+G.os2.stem_len,\"%d\",idx);\n\n  va_start(arg_ptr, format);\n  ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr);\n  va_end(arg_ptr);\n  return ret;\n}\n\n\nint WriteToNextVariable(__GPRO__ char *buffer, int len)\n{\n  if (G.os2.stem_len > 0) {\n    G.os2.output_idx++;\n    sprintf(G.os2.output_var+G.os2.stem_len,\"%d\",G.os2.output_idx);\n  }\n  return WriteToVariable(__G__ G.os2.output_var, buffer, len);\n}\n\n\nint TextSetNext(__GPRO__ char *buffer, int len, int all)\n{\n  char *scan = buffer, *next, *base=buffer;\n  int remaining=len;\n  int ret;\n\n  while ((next = strchr(scan,'\\n')) != NULL && remaining > 0) {\n    if (next > scan && *(next-1) == 0xd)\n      *(next-1) = 0;\n    else\n      *next = 0;\n    if (WriteToNextVariable(__G__ scan,strlen(scan)))\n      return 0;\n    next++;\n    remaining -= (next-scan);\n    scan = next;\n  }\n  if (remaining > 0)\n    if (all) {\n      *(scan+remaining) = 0;\n      WriteToNextVariable(__G__ scan,remaining);\n    } else {\n      memcpy(buffer,scan,remaining);\n      return remaining;\n    }\n\n  return 0;\n}\n\nint finish_REXX_redirect(__GPRO)\n{\n  char *scan, *ptr;\n  int idx=0, first=1, offset;\n\n  if (!G.redirect_size)\n    return 0;\n  switch(G.redirect_data) {\n  case 1:\n    break;\n  case 2:\n    TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1);\n    SetOutputVarLength(__G);\n    DosFreeMem(G.redirect_buffer);\n    G.redirect_buffer = NULL;\n    G.redirect_size = 0;\n    break;\n  case 3:\n    WriteToNextVariable(__G__ G.filename, strlen(G.filename));\n    strcpy(G.os2.output_var+G.os2.stem_len, G.filename);\n    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);\n    DosFreeMem(G.redirect_buffer);\n    G.redirect_buffer = NULL;\n    G.redirect_size = 0;\n    break;\n  case 4:\n    if ((scan = strrchr(G.filename,'/')) != NULL) {\n      idx = *scan;\n      *scan = 0;\n      strupr(G.filename);\n      *scan = idx;\n    }\n    scan = G.os2.output_var+G.os2.stem_len;\n    strcpy(scan,G.filename);\n    while ((scan = strchr(scan,'/')) != NULL)\n      *scan = '.';\n    WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);\n    DosFreeMem(G.redirect_buffer);\n    G.redirect_buffer = NULL;\n    G.redirect_size = 0;\n    strcpy(G.os2.getvar_buf, G.os2.output_var);\n    do {\n      if ((scan = strrchr(G.filename,'/')) == NULL)\n        offset = 0;\n      else\n        offset = scan-G.filename+1;\n      if (first || !GetVariable(__G__ G.os2.output_var)) {\n        ptr = G.os2.getvar_buf+offset+G.os2.stem_len;\n        *ptr = '0';\n        *(ptr+1) = 0;\n        if (!GetVariable(__G__ G.os2.getvar_buf))\n          idx = 1;\n        else\n          idx = atoi(G.os2.buffer)+1;\n        PrintToVariable(__G__ G.os2.getvar_buf,\"%d\",idx);\n        sprintf(ptr,\"%d\",idx);\n        if (!first) {\n          PrintToVariable(__G__ G.os2.output_var,\"%d\",idx);\n          idx = strlen(G.filename);\n          *(G.filename+idx)   = '/';\n          *(G.filename+idx+1) = 0;\n        }\n        WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset));\n        first=0;\n      }\n      if (offset) {\n        *(G.os2.output_var+G.os2.stem_len+offset-1)   = 0;\n        *scan = 0;\n      }\n    } while (offset);\n    break;\n  }\n  return 0;\n}\n\n#endif /* OS2DLL */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/rexxapi.def",
    "content": "LIBRARY UNZIP32 INITINSTANCE LONGNAMES\nPROTMODE\nDESCRIPTION 'Info-ZIP UnZip API - Copyright Scott Maxwell 1994, Info-ZIP 1995-1997'\nDATA MULTIPLE NONSHARED\nEXPORTS\n     UzpVersion\t\t@1\n     UzpUnzipToMemory\t@2\n     UzpFileTree\t@3\n     UzpMain\t\t@4\n     UzpAltMain\t\t@5\n     UzpVersion2\t@6\n     UZDROPFUNCS\t= UZDropFuncs      @2000\n     UZLOADFUNCS\t= UZLoadFuncs      @2001\n     UZFILETREE\t\t= UZFileTree       @2002\n     UZUNZIPTOVAR\t= UZUnZipToVar     @2003\n     UZUNZIPTOSTEM\t= UZUnZipToStem    @2004\n     UZVER\t\t= UZVer            @2005\n     UZUNZIP\t\t= UZUnZip\t   @2007\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/rexxhelp.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* rexxhelp.c */\n\n#if defined(API_DOC) && defined(OS2DLL)\n\n#define UNZIP_INTERNAL\n#include \"../unzip.h\"\n#include \"../unzvers.h\"\n\nAPIDocStruct REXXDetails[] = {\n  { \"UZDROPFUNCS\"  , \"UZDropFuncs\"  ,\n               \"call UZDropFuncs\",\n               \"Use this function to drop all the loaded UnZip functions.\\n\"\n\"\\t\\tOnce this function is processed by a REXX program, the\\n\"\n\"\\t\\tUnZip functions are not accessible in any OS/2 sessions.\\n\" },\n\n  { \"UZLOADFUNCS\"  , \"UZLoadFuncs\"  ,\n               \"call UZLoadFuncs\",\n               \"Use this function to make all of the UnZip functions\\n\"\n\"\t\tin this package available to all OS/2 sessions.\\n\\n\"\n\"  Example:\tcall RxFuncAdd 'UZLoadFuncs', 'UNZIPAPI', 'UZLoadFuncs'\\n\"\n\"\t\tcall UZLoadFuncs\\n\" },\n\n  { \"UZFILETREE\"   , \"UZFileTree\"   ,\n               \"rc = UZFileTree(zipfile, stem, [include], [exclude], [options])\\n\\n\"\n\"\tzipfile\t- Name of ZIP file to search\\n\"\n\"\tstem\t- Name of the stem variable for results\\n\"\n\"\t\t  Note: stem.0 contains the number of files found.\\n\"\n\"\tinclude - Optional stem variable specifying a list of files (including\\n\"\n\"\t\t  wildcards) to include.  stem.0 must indicate number of items.\\n\"\n\"\texclude - Optional stem variable specifying a list of files (including\\n\"\n\"\t\t  wildcards) to exclude.  stem.0 must indicate number of items.\\n\"\n\"\t    NOTE: If lists are not needed, filespec strings may be passed.\\n\"\n\"\toptions - One of the following:\\n\"\n\"\t\t  'O' - Give file names only.  This is the default.\\n\"\n\"\t\t  'F' - Give file statistics in the form:\\n\"\n\"\t\t\tLength Date Time Name\\n\"\n\"\t\t  'Z' - Also give ZIP statistics in the form:\\n\"\n\"\t\t\tLength Method Size Ratio Date Time CRC-32 Name\",\n               \"Finds all files in the specified ZIP with the specified\\n\"\n\"\t\tfilespec and places their descriptions in a stem variable.\\n\\n\"\n\"\trc:\tReturn codes\\n\"\n\"\t\t0\tSuccessful\\n\"\n\"\t\t2\tError.  Not enough memory.\\n\\n\"\n\"\tExamples:\\n\"\n\"\t\t/* Return a list of all .NDX files in pcboard.qwk */\\n\"\n\"\t\trc = UZFileTree('pcboard.qwk', 'stem.', '*.ndx')\\n\\n\"\n\"\t\t/* Return a list of all files except *.NDX and *.DAT */\\n\"\n\"\t\texc.0 = 2; exc.1 = '*.ndx'; exc.2 = '*.dat'\\n\"\n\"\t\trc = UZFileTree('pcboard.qwk', 'stem.',,'exc.')\\n\" },\n\n  { \"UZUNZIP\"      , \"UZUnZip\"      ,\n               \"rc = UZUnZip('parameters', [stem])\\n\\n\"\n\"\tparameters\t- The entire list of parameters you would use from\\n\"\n\"\t\t\t  the command-line\\n\"\n\"\tstem\t\t- The name of an optional stem variable where any\\n\"\n\"\t\t\t  output should be redirected.\\n\"\n\"\t\t\t  NOTE: If a stem is not specified, all output will\\n\"\n\"\t\t\t\tgo to the console.\",\n               \"Provide a direct entry point to the command line interface.\\n\\n\"\n\"\trc:\tUnZip return code\\n\\n\"\n\"  Examples:\t/* Test the archive 'unzip51s.zip' and return output in stem.*/\\n\"\n\"\t\trc = UZUnZip('-t unzip51s.zip','stem.')\\n\"\n\"\t\t/* Extract the archive, display output on screen */\\n\"\n\"\t\tcall UZUnZip 'doom.zip'\\n\"\n\"\t\t/* Extract all .NDX files from the archive */\\n\"\n\"\t\tcall UZUnZip 'pcboard.qwk *.ndx','stem.'\\n\" },\n\n  { \"UZUNZIPTOVAR\" , \"UZUnZipToVar\" ,\n               \"rc = UZUnZipToVar('zipfile', 'filename', [stem])\\n\\n\"\n\"\tzipfile\t - Name of ZIP file to search\\n\"\n\"\tfilename - Name of file to extract from zipfile\\n\"\n\"\tstem\t - Optional stem variable to extract the file to.\\n\"\n\"\t\t   If you specify a stem variable, the file will be extracted\\n\"\n\"\t\t   to the variable, one line per index, stem.0 containing a\\n\"\n\"\t\t   line count.  In this case, 0 will be returned in rc.\\n\"\n\"\t\t   If NO stem variable is specified, the entire file will be\\n\"\n\"\t\t   extracted to rc.\",\n               \"Unzip one file to a variable.\\n\\n\"\n\"\trc:\tIf no stem variable is specified, rc contains the contents of\\n\"\n\"\t\tthe extracted file if successful or an error-code if not.\\n\"\n\"\t\tIf a stem variable IS specified, rc contains 0 if successful.\\n\"},\n\n  /* GRR:  \"include\" and \"exclude\" used to be identified as stem variables\n   *       (Daniel H bug report)\n   */\n  { \"UZUNZIPTOSTEM\", \"UZUnZipToStem\",\n               \"rc = UZUnZipToStem(zipfile, stem, [include], [exclude], [mode])\\n\"\n\"\tzipfile\t- Name of ZIP file to search\\n\"\n\"\tstem\t- Stem variable used to store the extracted files\\n\"\n\"\tinclude - Optional string variable specifying a list of files (including\\n\"\n\"\t\t  wildcards) to include.  stem.0 must indicate number of items.\\n\"\n\"\texclude - Optional string variable specifying a list of files (including\\n\"\n\"\t\t  wildcards) to exclude.  stem.0 must indicate number of items.\\n\"\n\"\t    NOTE: If lists are not needed, filespec strings may be passed.\\n\"\n\"\tmode\t- Optional mode parameter specifies either 'F'lat (the default)\\n\"\n\"\t\t  or 'T'ree mode.\\n\"\n\"\t\t-- In flat mode, each file is stored in stem.fullname i.e.\\n\"\n\"\t\t   stem.os2/dll/unzipapi.c.  A list of files is created in\\n\"\n\"\t\t   stem.<index>\\n\"\n\"\t\t-- In tree mode, slashes are converted to periods in the\\n\"\n\"\t\t   pathname thus the above file would have been stored in\\n\"\n\"\t\t   stem.OS2.DLL.unzipapi.c and an index stored for each\\n\"\n\"\t\t   directory, i.e. stem.OS2.DLL.<index> = \\\"unzipapi.c\\\",\\n\"\n\"\t\t   stem.OS2.<index> = \\\"DLL/\\\", stem.<index> = \\\"OS2/\\\"\",\n               \"Unzip files to a stem variable.\\n\\n\"\n\"\tExample:\tAssuming a file unzip.zip containing:\\n\"\n\"\t\t\t  unzip.c, unshrink.c, extract.c,\\n\"\n\"\t\t\t  os2/makefile.os2, os2/os2.c\\n\"\n\"\t\t\t  os2/dll/dll.def, os2/dll/unzipapi.c\\n\\n\"\n\"\t\trc = UZUnZipToStem('unzip.zip', 'stem.')\\n\"\n\"\t\tReturns:\tstem.0 = 7\\n\"\n\"\t\t\t\tstem.1 = unzip.c\\n\"\n\"\t\t\t\tstem.2 = unshrink.c\\n\"\n\"\t\t\t\tstem.3 = extract.c\\n\"\n\"\t\t\t\tstem.4 = os2/makefile.os2\\n\"\n\"\t\t\t\tstem.5 = os2/os2.c\\n\"\n\"\t\t\t\tstem.6 = os2/dll/dll.def\\n\"\n\"\t\t\t\tstem.7 = os2/dll/unzipapi.c\\n\"\n\"\t\t\tAnd the following contain the contents of the\\n\"\n\"\t\t\tvarious files:\\n\"\n\"\t\t\t\tstem.unzip.c\\n\"\n\"\t\t\t\tstem.unshrink.c\\n\"\n\"\t\t\t\tstem.extract.c\\n\"\n\"\t\t\t\tstem.os2/makefile.os2\\n\"\n\"\t\t\t\tstem.os2/os2.c\\n\"\n\"\t\t\t\tstem.os2/dll/dll.def\\n\"\n\"\t\t\t\tstem.os2/dll/unzipapi.c\\n\\n\"\n\"\t\trc = UZUnZipToStem('unzip.zip', 'stem.',,,'TREE')\\n\"\n\"\t\tReturns:\tstem.0 = 4\\n\"\n\"\t\t\t\tstem.1 = unzip.c\\n\"\n\"\t\t\t\tstem.2 = unshrink.c\\n\"\n\"\t\t\t\tstem.3 = extract.c\\n\"\n\"\t\t\t\tstem.4 = OS2/\\n\"\n\"\t\t\t\tstem.OS2.0 = 3\\n\"\n\"\t\t\t\tstem.OS2.1 = makefile.os2\\n\"\n\"\t\t\t\tstem.OS2.2 = os2.c\\n\"\n\"\t\t\t\tstem.OS2.3 = DLL/\\n\"\n\"\t\t\t\tstem.OS2.DLL.0 = 2\\n\"\n\"\t\t\t\tstem.OS2.DLL.1 = def\\n\"\n\"\t\t\t\tstem.OS2.DLL.2 = unzipapi.c\\n\"\n\"\\n\"\n\"\t\t\tAnd the following contain the contents of the\\n\"\n\"\t\t\tvarious programs:\\n\"\n\"\t\t\t\tstem.unzip.c\\n\"\n\"\t\t\t\tstem.unshrink.c\\n\"\n\"\t\t\t\tstem.extract.c\\n\"\n\"\t\t\t\tstem.OS2.makefile.os2\\n\"\n\"\t\t\t\tstem.OS2.os2.c\\n\"\n\"\t\t\t\tstem.OS2.DLL.dll.def\\n\"\n\"\t\t\t\tstem.OS2.DLL.unzipapi.c\\n\" },\n\n  { \"UZVER\"        , \"UZVer\"        ,\n               \"rc = UZVer([option])\\n\\n\"\n\"\trc\tString containing UnZip version info in the form 'x.xx'\\n\"\n\"\t\tIf option is 'L' then info is in the form 'x.xx of <date>\",\n               \"Returns the version number of UnZip\\n\" },\n\n  { \"UZAPIVER\"     , \"UZAPIVer\"     ,\n               \"rc = UZAPIVer([option])\\n\\n\"\n\"\trc\tString containing API version info in the form 'x.xx'\\n\"\n\"\t\tIf option is 'L' then info is in the form 'x.xx of <date>\",\n               \"Returns the version number of the API\\n\" },\n  { 0 }\n};\n\nchar *REXXBrief = \"\\\nREXX functions:\\n\\\n  UZDropFuncs     -- Makes all functions in this package unknown to REXX\\n\\\n  UZLoadFuncs     -- Makes all functions in this package known to REXX\\n\\\n  UZFileTree      -- Searches for files matching a given filespec\\n\\\n  UZUnZip\t  -- UnZip command-line entry point\\n\\\n  UZUnZipToVar    -- Unzip one file to a variable\\n\\\n  UZUnZipToStem   -- Unzip files to a variable array\\n\\\n  UZVer           -- Returns the UnZip version number\\n\\\n  UZAPIVer        -- Returns the API version number\\n\";\n\n\n#endif /* API_DOC && OS2DLL */\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/rexxtest.cmd",
    "content": "/* Test REXX UnZip API */\ncall RxFuncAdd 'UZLoadFuncs', 'UNZIP32', 'UZLoadFuncs'\ncall UZLoadFuncs\n\nparse arg all\n\nsay; say 'Demonstrating UZUnZip' UZUnZip(all,'TEST.')\ndo num=1 to test.0\n  say num':'test.num\nend\n\n/*** Demonstrate UZFileTree ***/\nfname = 'g:\\cqc\\channel1\\12-30.qwk'\nsay; say 'Demonstrating UZFileTree by displaying all entries in',\n          fname\nexc.0 = 2\nexc.1 = '*.dat'\nexc.2 = '*.ndx'\ncall UZFileTree fname, 'files','','exc'\ndo num=1 to files.0\n  say num':'files.num\nend\n\nsay; say 'Demonstrating UZUnZipToVar -' UZUnZipToVar(fname,'CONTROL.DAT')\n\n\ntest. = 0\nsay; say 'Demonstrating UZUnZipToVar -' UZUnZipToVar(fname,'CONTROL.DAT','test.')\nSAY \"Test =\" test.0\ndo num=1 to test.0\n  say num':'test.num\nend\n\ntest. = 0\nsay; say 'Demonstrating UZUnZipToStem -' UZUnZipToStem('\\SourceCode\\cqc\\cqcmain.zip','test',\"*.rch\",,'T')\ncall recout \"test\"\n\nsay; say 'Demonstrating UZVer -' UZVer()\n\ncall UZDropFuncs\nexit\n\nrecout: PROCEDURE EXPOSE test.\nparse arg this\nsay this \"Contains\" value(this'.0') \"entries\"\ndo num=1 to value(this'.0')\n  tval = value(this'.'num)\n  say \"Got\" this'.'num':' tval\n  if Right(tval,1) = '/' then\n     call recout this'.'left(tval,length(tval)-1)\n  else\n     say \"Contains:\" value(this'.tval')\nend\nreturn\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/stub.def",
    "content": "DESCRIPTION 'The world-famous Info-ZIP unarchiving utilities'\nSTACKSIZE 0x50000\nIMPORTS\n     UNZIP32.UzpVersion\n     UNZIP32.UzpMain\n     UNZIP32.UzpVersion2\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/unzip.def",
    "content": "NAME WINDOWCOMPAT NEWFILES\nDESCRIPTION 'The world-famous Info-ZIP unarchiving utilities'\n; SEGMENTS\n;   _MSGSEG32 CLASS 'CODE'\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/zgrepapi.cmd",
    "content": "/*---------------------------------------------------------------------------\n\n   zapigrep.cmd  (ye olde REXX procedure for OS/2)\n\n   Script to search members of a zipfile for a string and print the names of\n   any such members (and, optionally, the matching text).\n\n   This is the zipgrep.cmd program completely rewritten to take advantage\n   of the REXX API.  Among the improvements are:\n        egrep no longer needed.  All work done by API and this script.\n\tAdded option switches.\n\n   Be aware, however, that this script does not support regular expressions\n   as zipgrep does.\n\n  ---------------------------------------------------------------------------*/\n\nPARSE ARG args\n\nnocase = 0\nword = 0\ntext = 0\n\nDO WHILE Left(args,1) == '-' | Left(args,1) == '/'\n   PARSE VAR args option args\n   option = Translate(SubStr(option,2))\n   DO WHILE option \\= ''\n      oneopt = Left(option,1)\n      option = SubStr(option,2)\n      SELECT\n       WHEN oneopt == 'W' THEN\n\t  word = 1\n       WHEN oneopt == 'I' THEN\n\t  nocase = 1\n       WHEN oneopt == 'T' THEN\n\t  text = 1\n       OTHERWISE NOP\n      END\n   END\nEND\n\nPARSE VAR args string zipfile members\n\nIF (string == '') THEN DO\n   SAY 'usage:  zipgrep [-i][-t][-w] search_string zipfile [members...]'\n   SAY '   Displays the names of zipfile members containing a given string.'\n   SAY '   By default it displays filenames only of members containing an'\n   SAY '   exact match of the string.  Options are:'\"0a\"x\n   SAY '\t-i  Ignore case'\n   SAY '\t-t  Display matching lines'\n   SAY '\t-w  Match words only'\n   EXIT 1\nEND\nstring = Strip(string,'b','\"')\nIF nocase THEN string = Translate(string)\n\nCALL RxFuncAdd 'UZLoadFuncs', 'UNZIP32', 'UZLoadFuncs'\nCALL UZLoadFuncs\n\nCALL UZUnZipToStem zipfile, 'file.', members\n\nDO i = 1 TO file.0\n   ptr = file.i\n   file = file.ptr\n   IF nocase THEN file = Translate(file)\n   IF word THEN DO\n      wp = WordPos(string,file)\n      IF wp>0 THEN\n\t scan = WordIndex(file,wp)\n      ELSE\n         scan = 0\n   END\n   ELSE\n      scan = Pos(string,file)\n   IF scan \\= 0 THEN DO\n      SAY file.i':'\n      IF text THEN DO\n\t DO WHILE scan > 0\n\t    from = LastPos('0a'x,file,scan)+1\n\t    to = Pos('0a'x,file,scan)\n\t    IF to = 0 THEN to = Length(file.ptr)\n\t    oneline = Strip(SubStr(file.ptr,from,to-from),'T','0a'x)\n\t    SAY Strip(oneline,'T','0d'x)\n\t    IF word THEN DO\n\t       wp = WordPos(string,file,wp+1)\n\t       IF wp>0 THEN\n\t\t  scan = WordIndex(file,wp)\n\t       ELSE\n\t\t  scan = 0\n\t    END\n\t    ELSE\n\t       scan = Pos(string,file,scan+1)\n\t END\n      END\n   END\nEND\n\nEXIT 0\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/zip2exe.cmd",
    "content": "/**** REXX  ********   ZIP2EXE.CMD  **************  01/04/96 *********\\\n|**  This exec will prepend the Info Zip unzipsfx.exe file to an    **|\n|**  existing ZIP file to create a self extracting zip.             **|\n|**                                                                 **|\n|**  The exec requires 1 argument, the name of the zip file to be   **|\n|**  acted upon.                                                    **|\n|**                                                                 **|\n|**  Put this exec into the path that contains your Info Zip        **|\n|**  executables.                                                   **|\n|**                                                                 **|\n\\*********************************************************************/\nrc = 0\n/**  Start Argument processing  ** End Initialization               **/\nPARSE UPPER ARG zip_file\nIF zip_file = \"\"\nTHEN\n  DO\n    SAY \"You must specify the name of the file to be processed\"\n    SAY \"Please try again\"\n    rc = 9\n    SIGNAL FINI\n  END\nIF POS(\".ZIP\",zip_file) = 0\nTHEN\n  DO\n    sfx_file = zip_file||\".EXE\"\n    zip_file = zip_file||\".ZIP\"\n  END\nELSE\n    sfx_file = SUBSTR(zip_file,1,LASTPOS(\".\",zip_file))||\"EXE\"\nzip_file = STREAM(zip_file,\"C\",\"QUERY EXISTS\")\nIF zip_file = \"\"\nTHEN\n  DO\n    SAY \"The file \"||ARG(1)||\" Does not exist\"\n    SAY \"Processing terminated\"\n    rc = 9\n    SIGNAL FINI\n  END\n/**  Start unzipsfx location    ** End Argument processing          **/\nPARSE UPPER SOURCE . . command_file\nunzipsfx = SUBSTR(command_file,1,LASTPOS(\"\\\",command_file))||,\n          \"UNZIPSFX.EXE\"\nIF STREAM(unzipsfx,\"C\",\"QUERY EXISTS\") = \"\"\nTHEN\n  DO\n    SAY \"We are unable to locate the UNZIPSFX.EXE source\"\n    SAY \"Ensure that the ZIP2EXE command is in the directory\",\n        \"which contains UNZIPSFX.EXE\"\n    rc = 9\n    SIGNAL FINI\n  END\n/**  Execute the command        ** End Argument processing          **/\nADDRESS CMD \"@COPY /b \"||unzipsfx||\"+\"||zip_file,\n            sfx_file||\" > NUL\"\nIF rc = 0\nTHEN\n  SAY sfx_file||\" successfully created\"\nELSE\n  SAY sfx_file||\" creation failed\"\nFINI:\n  EXIT  rc\n"
  },
  {
    "path": "deps/infozip/unzip60/os2/zipgrep.cmd",
    "content": "/*---------------------------------------------------------------------------\n\n   zipgrep.cmd  (ye olde REXX procedure for OS/2)\n\n   Script to search members of a zipfile for a string or regular expression\n   and print the names of any such members (and, optionally, the matching\n   text).  The search is case-insensitive by default.\n\n   History:\n     original Bourne shell version by Jean-loup Gailly\n     modified by Greg Roelofs for Ultrix (no egrep -i) and zipinfo -1\n     OS/2 REXX script by Greg Roelofs\n\n   Last modified:  19 Jul 93\n\n  ---------------------------------------------------------------------------*/\n\nPARSE ARG string zipfile members\n\nif (string == '') then do\n    say 'usage:  zipgrep search_string zipfile [members...]'\n    say '   Displays the names of zipfile members containing a given string,'\n    say '   in addition to the matching text.  This procedure requires unzip'\n    say '   and egrep in the current path, and it is quite slow....'\n    exit 1\nend\n\n/* doesn't seem to work...\nnewq = RXQUEUE(\"Create\",zipgrep_pipe)\noldq = RXQUEUE(\"Set\",newq)\n */\n\n/* flush the queue before starting */\ndo QUEUED()\n    PULL junk\nend\n\n/* GRR:  can also add \"2>&1\" before pipe in following external command */\n'@unzip -Z1' zipfile members '| rxqueue'\n\ndo while QUEUED() > 0\n    PARSE PULL file\n    '@unzip -p' zipfile file '| egrep -is' string\n    if rc == 0 then do\n        SAY file':'\n        /* can comment out following line if just want filenames */\n        '@unzip -p' zipfile file '| egrep -i' string\n    end\nend\n\n/*\ncall RXQUEUE \"Delete\",newq\ncall RXQUEUE \"Set\",oldq\n */\n\nexit 0\n"
  },
  {
    "path": "deps/infozip/unzip60/process.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  process.c\n\n  This file contains the top-level routines for processing multiple zipfiles.\n\n  Contains:  process_zipfiles()\n             free_G_buffers()\n             do_seekable()\n             file_size()\n             rec_find()\n             find_ecrec64()\n             find_ecrec()\n             process_zip_cmmnt()\n             process_cdir_file_hdr()\n             get_cdir_ent()\n             process_local_file_hdr()\n             getZip64Data()\n             ef_scan_for_izux()\n             getRISCOSexfield()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#endif\n#if defined(DYNALLOC_CRCTAB) || defined(UNICODE_SUPPORT)\n#  include \"crc32.h\"\n#endif\n\nstatic int    do_seekable        OF((__GPRO__ int lastchance));\n#ifdef DO_SAFECHECK_2GB\n# ifdef USE_STRM_INPUT\nstatic zoff_t file_size          OF((FILE *file));\n# else\nstatic zoff_t file_size          OF((int fh));\n# endif\n#endif /* DO_SAFECHECK_2GB */\nstatic int    rec_find           OF((__GPRO__ zoff_t, char *, int));\nstatic int    find_ecrec64       OF((__GPRO__ zoff_t searchlen));\nstatic int    find_ecrec         OF((__GPRO__ zoff_t searchlen));\nstatic int    process_zip_cmmnt  OF((__GPRO));\nstatic int    get_cdir_ent       OF((__GPRO));\n#ifdef IZ_HAVE_UXUIDGID\nstatic int    read_ux3_value     OF((ZCONST uch *dbuf, unsigned uidgid_sz,\n                                     ulg *p_uidgid));\n#endif /* IZ_HAVE_UXUIDGID */\n\n\nstatic ZCONST char Far CannotAllocateBuffers[] =\n  \"error:  cannot allocate unzip buffers\\n\";\n\n#ifdef SFX\n   static ZCONST char Far CannotFindMyself[] =\n     \"unzipsfx:  cannot find myself! [%s]\\n\";\n# ifdef CHEAP_SFX_AUTORUN\n   static ZCONST char Far AutorunPrompt[] =\n     \"\\nAuto-run command: %s\\nExecute this command? [y/n] \";\n   static ZCONST char Far NotAutoRunning[] =\n     \"Not executing auto-run command.\";\n# endif\n\n#else /* !SFX */\n   /* process_zipfiles() strings */\n# if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))\n     static ZCONST char Far WarnInvalidTZ[] =\n       \"Warning: TZ environment variable not found, cannot use UTC times!!\\n\";\n# endif\n# if !(defined(UNIX) || defined(AMIGA))\n   static ZCONST char Far CannotFindWildcardMatch[] =\n     \"%s:  cannot find any matches for wildcard specification \\\"%s\\\".\\n\";\n# endif /* !(UNIX || AMIGA) */\n   static ZCONST char Far FilesProcessOK[] =\n     \"%d archive%s successfully processed.\\n\";\n   static ZCONST char Far ArchiveWarning[] =\n     \"%d archive%s had warnings but no fatal errors.\\n\";\n   static ZCONST char Far ArchiveFatalError[] =\n     \"%d archive%s had fatal errors.\\n\";\n   static ZCONST char Far FileHadNoZipfileDir[] =\n     \"%d file%s had no zipfile directory.\\n\";\n   static ZCONST char Far ZipfileWasDir[] = \"1 \\\"zipfile\\\" was a directory.\\n\";\n   static ZCONST char Far ManyZipfilesWereDir[] =\n     \"%d \\\"zipfiles\\\" were directories.\\n\";\n   static ZCONST char Far NoZipfileFound[] = \"No zipfiles found.\\n\";\n\n   /* do_seekable() strings */\n# ifdef UNIX\n   static ZCONST char Far CannotFindZipfileDirMsg[] =\n     \"%s:  cannot find zipfile directory in one of %s or\\n\\\n        %s%s.zip, and cannot find %s, period.\\n\";\n   static ZCONST char Far CannotFindEitherZipfile[] =\n     \"%s:  cannot find or open %s, %s.zip or %s.\\n\";\n# else /* !UNIX */\n   static ZCONST char Far CannotFindZipfileDirMsg[] =\n     \"%s:  cannot find zipfile directory in %s,\\n\\\n        %sand cannot find %s, period.\\n\";\n# ifdef VMS\n   static ZCONST char Far CannotFindEitherZipfile[] =\n     \"%s:  cannot find %s (%s).\\n\";\n# else /* !VMS */\n   static ZCONST char Far CannotFindEitherZipfile[] =\n     \"%s:  cannot find either %s or %s.\\n\";\n# endif /* ?VMS */\n# endif /* ?UNIX */\n   extern ZCONST char Far Zipnfo[];       /* in unzip.c */\n#ifndef WINDLL\n   static ZCONST char Far Unzip[] = \"unzip\";\n#else\n   static ZCONST char Far Unzip[] = \"UnZip DLL\";\n#endif\n#ifdef DO_SAFECHECK_2GB\n   static ZCONST char Far ZipfileTooBig[] =\n     \"Trying to read large file (> 2 GiB) without large file support\\n\";\n#endif /* DO_SAFECHECK_2GB */\n   static ZCONST char Far MaybeExe[] =\n     \"note:  %s may be a plain executable, not an archive\\n\";\n   static ZCONST char Far CentDirNotInZipMsg[] = \"\\n\\\n   [%s]:\\n\\\n     Zipfile is disk %lu of a multi-disk archive, and this is not the disk on\\n\\\n     which the central zipfile directory begins (disk %lu).\\n\";\n   static ZCONST char Far EndCentDirBogus[] =\n     \"\\nwarning [%s]:  end-of-central-directory record claims this\\n\\\n  is disk %lu but that the central directory starts on disk %lu; this is a\\n\\\n  contradiction.  Attempting to process anyway.\\n\";\n# ifdef NO_MULTIPART\n   static ZCONST char Far NoMultiDiskArcSupport[] =\n     \"\\nerror [%s]:  zipfile is part of multi-disk archive\\n\\\n  (sorry, not yet supported).\\n\";\n   static ZCONST char Far MaybePakBug[] = \"warning [%s]:\\\n  zipfile claims to be 2nd disk of a 2-part archive;\\n\\\n  attempting to process anyway.  If no further errors occur, this archive\\n\\\n  was probably created by PAK v2.51 or earlier.  This bug was reported to\\n\\\n  NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\\n\\\n  of mid-1992 it still hadn't been.  (If further errors do occur, archive\\n\\\n  was probably created by PKZIP 2.04c or later; UnZip does not yet support\\n\\\n  multi-part archives.)\\n\";\n# else\n   static ZCONST char Far MaybePakBug[] = \"warning [%s]:\\\n  zipfile claims to be last disk of a multi-part archive;\\n\\\n  attempting to process anyway, assuming all parts have been concatenated\\n\\\n  together in order.  Expect \\\"errors\\\" and warnings...true multi-part support\\\n\\n  doesn't exist yet (coming soon).\\n\";\n# endif\n   static ZCONST char Far ExtraBytesAtStart[] =\n     \"warning [%s]:  %s extra byte%s at beginning or within zipfile\\n\\\n  (attempting to process anyway)\\n\";\n#endif /* ?SFX */\n\n#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO))\n   static ZCONST char Far LogInitline[] = \"Archive:  %s\\n\";\n#endif\n\nstatic ZCONST char Far MissingBytes[] =\n  \"error [%s]:  missing %s bytes in zipfile\\n\\\n  (attempting to process anyway)\\n\";\nstatic ZCONST char Far NullCentDirOffset[] =\n  \"error [%s]:  NULL central directory offset\\n\\\n  (attempting to process anyway)\\n\";\nstatic ZCONST char Far ZipfileEmpty[] = \"warning [%s]:  zipfile is empty\\n\";\nstatic ZCONST char Far CentDirStartNotFound[] =\n  \"error [%s]:  start of central directory not found;\\n\\\n  zipfile corrupt.\\n%s\";\nstatic ZCONST char Far Cent64EndSigSearchErr[] =\n  \"fatal error: read failure while seeking for End-of-centdir-64 signature.\\n\\\n  This zipfile is corrupt.\\n\";\nstatic ZCONST char Far Cent64EndSigSearchOff[] =\n  \"error: End-of-centdir-64 signature not where expected (prepended bytes?)\\n\\\n  (attempting to process anyway)\\n\";\n#ifndef SFX\n   static ZCONST char Far CentDirTooLong[] =\n     \"error [%s]:  reported length of central directory is\\n\\\n  %s bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1\\n\\\n  zipfile?).  Compensating...\\n\";\n   static ZCONST char Far CentDirEndSigNotFound[] = \"\\\n  End-of-central-directory signature not found.  Either this file is not\\n\\\n  a zipfile, or it constitutes one disk of a multi-part archive.  In the\\n\\\n  latter case the central directory and zipfile comment will be found on\\n\\\n  the last disk(s) of this archive.\\n\";\n#else /* SFX */\n   static ZCONST char Far CentDirEndSigNotFound[] =\n     \"  End-of-central-directory signature not found.\\n\";\n#endif /* ?SFX */\n#ifdef TIMESTAMP\n   static ZCONST char Far ZipTimeStampFailed[] =\n     \"warning:  cannot set time for %s\\n\";\n   static ZCONST char Far ZipTimeStampSuccess[] =\n     \"Updated time stamp for %s.\\n\";\n#endif\nstatic ZCONST char Far ZipfileCommTrunc1[] =\n  \"\\ncaution:  zipfile comment truncated\\n\";\n#ifndef NO_ZIPINFO\n   static ZCONST char Far NoZipfileComment[] =\n     \"There is no zipfile comment.\\n\";\n   static ZCONST char Far ZipfileCommentDesc[] =\n     \"The zipfile comment is %u bytes long and contains the following text:\\n\";\n   static ZCONST char Far ZipfileCommBegin[] =\n     \"======================== zipfile comment begins\\\n ==========================\\n\";\n   static ZCONST char Far ZipfileCommEnd[] =\n     \"========================= zipfile comment ends\\\n ===========================\\n\";\n   static ZCONST char Far ZipfileCommTrunc2[] =\n     \"\\n  The zipfile comment is truncated.\\n\";\n#endif /* !NO_ZIPINFO */\n#ifdef UNICODE_SUPPORT\n   static ZCONST char Far UnicodeVersionError[] =\n     \"\\nwarning:  Unicode Path version > 1\\n\";\n   static ZCONST char Far UnicodeMismatchError[] =\n     \"\\nwarning:  Unicode Path checksum invalid\\n\";\n#endif\n\n\n\n\n/*******************************/\n/* Function process_zipfiles() */\n/*******************************/\n\nint process_zipfiles(__G)    /* return PK-type error code */\n    __GDEF\n{\n#ifndef SFX\n    char *lastzipfn = (char *)NULL;\n    int NumWinFiles, NumLoseFiles, NumWarnFiles;\n    int NumMissDirs, NumMissFiles;\n#endif\n    int error=0, error_in_archive=0;\n\n\n/*---------------------------------------------------------------------------\n    Start by allocating buffers and (re)constructing the various PK signature\n    strings.\n  ---------------------------------------------------------------------------*/\n\n    G.inbuf = (uch *)malloc(INBUFSIZ + 4);    /* 4 extra for hold[] (below) */\n    G.outbuf = (uch *)malloc(OUTBUFSIZ + 1);  /* 1 extra for string term. */\n\n    if ((G.inbuf == (uch *)NULL) || (G.outbuf == (uch *)NULL)) {\n        Info(slide, 0x401, ((char *)slide,\n          LoadFarString(CannotAllocateBuffers)));\n        return(PK_MEM);\n    }\n    G.hold = G.inbuf + INBUFSIZ;     /* to check for boundary-spanning sigs */\n#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */\n#ifdef SMALL_MEM\n    G.outbuf2 = G.outbuf+RAWBUFSIZ;  /* never changes */\n#endif\n#endif /* !VMS */\n\n#if 0 /* CRC_32_TAB has been NULLified by CONSTRUCTGLOBALS !!!! */\n    /* allocate the CRC table later when we know we can read zipfile data */\n    CRC_32_TAB = NULL;\n#endif /* 0 */\n\n    /* finish up initialization of magic signature strings */\n    local_hdr_sig[0]  /* = extd_local_sig[0] */ =       /* ASCII 'P', */\n      central_hdr_sig[0] = end_central_sig[0] =         /* not EBCDIC */\n      end_centloc64_sig[0] = end_central64_sig[0] = 0x50;\n\n    local_hdr_sig[1]  /* = extd_local_sig[1] */ =       /* ASCII 'K', */\n      central_hdr_sig[1] = end_central_sig[1] =         /* not EBCDIC */\n      end_centloc64_sig[1] = end_central64_sig[1] = 0x4B;\n\n/*---------------------------------------------------------------------------\n    Make sure timezone info is set correctly; localtime() returns GMT on some\n    OSes (e.g., Solaris 2.x) if this isn't done first.  The ifdefs around\n    tzset() were initially copied from dos_to_unix_time() in fileio.c.  They\n    may still be too strict; any listed OS that supplies tzset(), regardless\n    of whether the function does anything, should be removed from the ifdefs.\n  ---------------------------------------------------------------------------*/\n\n#if (defined(WIN32) && defined(USE_EF_UT_TIME))\n    /* For the Win32 environment, we may have to \"prepare\" the environment\n       prior to the tzset() call, to work around tzset() implementation bugs.\n     */\n    iz_w32_prepareTZenv();\n#endif\n\n#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))\n#  ifndef VALID_TIMEZONE\n#     define VALID_TIMEZONE(tmp) \\\n             (((tmp = getenv(\"TZ\")) != NULL) && (*tmp != '\\0'))\n#  endif\n    {\n        char *p;\n        G.tz_is_valid = VALID_TIMEZONE(p);\n#  ifndef SFX\n        if (!G.tz_is_valid) {\n            Info(slide, 0x401, ((char *)slide, LoadFarString(WarnInvalidTZ)));\n            error_in_archive = error = PK_WARN;\n        }\n#  endif /* !SFX */\n    }\n#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */\n\n/* For systems that do not have tzset() but supply this function using another\n   name (_tzset() or something similar), an appropiate \"#define tzset ...\"\n   should be added to the system specifc configuration section.  */\n#if (!defined(T20_VMS) && !defined(MACOS) && !defined(RISCOS) && !defined(QDOS))\n#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))\n    tzset();\n#endif\n#endif\n\n/* Initialize UnZip's built-in pseudo hard-coded \"ISO <--> OEM\" translation,\n   depending on the detected codepage setup.  */\n#ifdef NEED_ISO_OEM_INIT\n    prepare_ISO_OEM_translat(__G);\n#endif\n\n/*---------------------------------------------------------------------------\n    Initialize the internal flag holding the mode of processing \"overwrite\n    existing file\" cases.  We do not use the calling interface flags directly\n    because the overwrite mode may be changed by user interaction while\n    processing archive files.  Such a change should not affect the option\n    settings as passed through the DLL calling interface.\n    In case of conflicting options, the 'safer' flag uO.overwrite_none takes\n    precedence.\n  ---------------------------------------------------------------------------*/\n    G.overwrite_mode = (uO.overwrite_none ? OVERWRT_NEVER :\n                        (uO.overwrite_all ? OVERWRT_ALWAYS : OVERWRT_QUERY));\n\n/*---------------------------------------------------------------------------\n    Match (possible) wildcard zipfile specification with existing files and\n    attempt to process each.  If no hits, try again after appending \".zip\"\n    suffix.  If still no luck, give up.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SFX\n    if ((error = do_seekable(__G__ 0)) == PK_NOZIP) {\n#ifdef EXE_EXTENSION\n        int len=strlen(G.argv0);\n\n        /* append .exe if appropriate; also .sfx? */\n        if ( (G.zipfn = (char *)malloc(len+sizeof(EXE_EXTENSION))) !=\n             (char *)NULL ) {\n            strcpy(G.zipfn, G.argv0);\n            strcpy(G.zipfn+len, EXE_EXTENSION);\n            error = do_seekable(__G__ 0);\n            free(G.zipfn);\n            G.zipfn = G.argv0;  /* for \"cannot find myself\" message only */\n        }\n#endif /* EXE_EXTENSION */\n#ifdef WIN32\n        G.zipfn = G.argv0;  /* for \"cannot find myself\" message only */\n#endif\n    }\n    if (error) {\n        if (error == IZ_DIR)\n            error_in_archive = PK_NOZIP;\n        else\n            error_in_archive = error;\n        if (error == PK_NOZIP)\n            Info(slide, 1, ((char *)slide, LoadFarString(CannotFindMyself),\n              G.zipfn));\n    }\n#ifdef CHEAP_SFX_AUTORUN\n    if (G.autorun_command[0] && !uO.qflag) { /* NO autorun without prompt! */\n        Info(slide, 0x81, ((char *)slide, LoadFarString(AutorunPrompt),\n                      FnFilter1(G.autorun_command)));\n        if (fgets(G.answerbuf, 9, stdin) != (char *)NULL\n            && toupper(*G.answerbuf) == 'Y')\n            system(G.autorun_command);\n        else\n            Info(slide, 1, ((char *)slide, LoadFarString(NotAutoRunning)));\n    }\n#endif /* CHEAP_SFX_AUTORUN */\n\n#else /* !SFX */\n    NumWinFiles = NumLoseFiles = NumWarnFiles = 0;\n    NumMissDirs = NumMissFiles = 0;\n\n    while ((G.zipfn = do_wild(__G__ G.wildzipfn)) != (char *)NULL) {\n        Trace((stderr, \"do_wild( %s ) returns %s\\n\", G.wildzipfn, G.zipfn));\n\n        lastzipfn = G.zipfn;\n\n        /* print a blank line between the output of different zipfiles */\n        if (!uO.qflag  &&  error != PK_NOZIP  &&  error != IZ_DIR\n#ifdef TIMESTAMP\n            && (!uO.T_flag || uO.zipinfo_mode)\n#endif\n            && (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)\n            (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n\n        if ((error = do_seekable(__G__ 0)) == PK_WARN)\n            ++NumWarnFiles;\n        else if (error == IZ_DIR)\n            ++NumMissDirs;\n        else if (error == PK_NOZIP)\n            ++NumMissFiles;\n        else if (error != PK_OK)\n            ++NumLoseFiles;\n        else\n            ++NumWinFiles;\n\n        Trace((stderr, \"do_seekable(0) returns %d\\n\", error));\n        if (error != IZ_DIR && error > error_in_archive)\n            error_in_archive = error;\n#ifdef WINDLL\n        if (error == IZ_CTRLC) {\n            free_G_buffers(__G);\n            return error;\n        }\n#endif\n\n    } /* end while-loop (wildcard zipfiles) */\n\n    if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0  &&\n        (NumMissDirs + NumMissFiles) == 1  &&  lastzipfn != (char *)NULL)\n    {\n#if (!defined(UNIX) && !defined(AMIGA)) /* filenames with wildcard characters */\n        if (iswild(G.wildzipfn)) {\n            if (iswild(lastzipfn)) {\n                NumMissDirs = NumMissFiles = 0;\n                error_in_archive = PK_COOL;\n                if (uO.qflag < 3)\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(CannotFindWildcardMatch),\n                      LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                      G.wildzipfn));\n            }\n        } else\n#endif\n        {\n#ifndef VMS\n            /* 2004-11-24 SMS.\n             * VMS has already tried a default file type of \".zip\" in\n             * do_wild(), so adding ZSUFX here only causes confusion by\n             * corrupting some valid (though nonexistent) file names.\n             * Complaining below about \"fred;4.zip\" is unlikely to be\n             * helpful to the victim.\n             */\n            /* 2005-08-14 Chr. Spieler\n             * Although we already \"know\" the failure result, we call\n             * do_seekable() again with the same zipfile name (and the\n             * lastchance flag set), just to trigger the error report...\n             */\n#if defined(UNIX) || defined(QDOS)\n            char *p =\n#endif\n              strcpy(lastzipfn + strlen(lastzipfn), ZSUFX);\n#endif /* !VMS */\n\n            G.zipfn = lastzipfn;\n\n            NumMissDirs = NumMissFiles = 0;\n            error_in_archive = PK_COOL;\n\n#if defined(UNIX) || defined(QDOS)\n   /* only Unix has case-sensitive filesystems */\n   /* Well FlexOS (sometimes) also has them,  but support is per media */\n   /* and a pig to code for,  so treat as case insensitive for now */\n   /* we do this under QDOS to check for .zip as well as _zip */\n            if ((error = do_seekable(__G__ 0)) == PK_NOZIP || error == IZ_DIR) {\n                if (error == IZ_DIR)\n                    ++NumMissDirs;\n                strcpy(p, ALT_ZSUFX);\n                error = do_seekable(__G__ 1);\n            }\n#else\n            error = do_seekable(__G__ 1);\n#endif\n            Trace((stderr, \"do_seekable(1) returns %d\\n\", error));\n            switch (error) {\n              case PK_WARN:\n                ++NumWarnFiles;\n                break;\n              case IZ_DIR:\n                ++NumMissDirs;\n                error = PK_NOZIP;\n                break;\n              case PK_NOZIP:\n                /* increment again => bug:\n                   \"1 file had no zipfile directory.\" */\n                /* ++NumMissFiles */ ;\n                break;\n              default:\n                if (error)\n                    ++NumLoseFiles;\n                else\n                    ++NumWinFiles;\n                break;\n            }\n\n            if (error > error_in_archive)\n                error_in_archive = error;\n#ifdef WINDLL\n            if (error == IZ_CTRLC) {\n                free_G_buffers(__G);\n                return error;\n            }\n#endif\n        }\n    }\n#endif /* ?SFX */\n\n/*---------------------------------------------------------------------------\n    Print summary of all zipfiles, assuming zipfile spec was a wildcard (no\n    need for a summary if just one zipfile).\n  ---------------------------------------------------------------------------*/\n\n#ifndef SFX\n    if (iswild(G.wildzipfn) && uO.qflag < 3\n#ifdef TIMESTAMP\n        && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag > 1)\n#endif\n                                                    )\n    {\n        if ((NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)\n#ifdef TIMESTAMP\n            && !(uO.T_flag && !uO.zipinfo_mode && uO.qflag)\n#endif\n            && !(uO.tflag && uO.qflag > 1))\n            (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0x401);\n        if ((NumWinFiles > 1) ||\n            (NumWinFiles == 1 &&\n             NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))\n            Info(slide, 0x401, ((char *)slide, LoadFarString(FilesProcessOK),\n              NumWinFiles, (NumWinFiles == 1)? \" was\" : \"s were\"));\n        if (NumWarnFiles > 0)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveWarning),\n              NumWarnFiles, (NumWarnFiles == 1)? \"\" : \"s\"));\n        if (NumLoseFiles > 0)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(ArchiveFatalError),\n              NumLoseFiles, (NumLoseFiles == 1)? \"\" : \"s\"));\n        if (NumMissFiles > 0)\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(FileHadNoZipfileDir), NumMissFiles,\n              (NumMissFiles == 1)? \"\" : \"s\"));\n        if (NumMissDirs == 1)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileWasDir)));\n        else if (NumMissDirs > 0)\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(ManyZipfilesWereDir), NumMissDirs));\n        if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(NoZipfileFound)));\n    }\n#endif /* !SFX */\n\n    /* free allocated memory */\n    free_G_buffers(__G);\n\n    return error_in_archive;\n\n} /* end function process_zipfiles() */\n\n\n\n\n\n/*****************************/\n/* Function free_G_buffers() */\n/*****************************/\n\nvoid free_G_buffers(__G)     /* releases all memory allocated in global vars */\n    __GDEF\n{\n#ifndef SFX\n    unsigned i;\n#endif\n\n#ifdef SYSTEM_SPECIFIC_DTOR\n    SYSTEM_SPECIFIC_DTOR(__G);\n#endif\n\n    inflate_free(__G);\n    checkdir(__G__ (char *)NULL, END);\n\n#ifdef DYNALLOC_CRCTAB\n    if (CRC_32_TAB) {\n        free_crc_table();\n        CRC_32_TAB = NULL;\n    }\n#endif\n\n   if (G.key != (char *)NULL) {\n        free(G.key);\n        G.key = (char *)NULL;\n   }\n\n   if (G.extra_field != (uch *)NULL) {\n        free(G.extra_field);\n        G.extra_field = (uch *)NULL;\n   }\n\n#if (!defined(VMS) && !defined(SMALL_MEM))\n    /* VMS uses its own buffer scheme for textmode flush() */\n    if (G.outbuf2) {\n        free(G.outbuf2);   /* malloc'd ONLY if unshrink and -a */\n        G.outbuf2 = (uch *)NULL;\n    }\n#endif\n\n    if (G.outbuf)\n        free(G.outbuf);\n    if (G.inbuf)\n        free(G.inbuf);\n    G.inbuf = G.outbuf = (uch *)NULL;\n\n#ifdef UNICODE_SUPPORT\n    if (G.filename_full) {\n        free(G.filename_full);\n        G.filename_full = (char *)NULL;\n        G.fnfull_bufsize = 0;\n    }\n#endif /* UNICODE_SUPPORT */\n\n#ifndef SFX\n    for (i = 0; i < DIR_BLKSIZ; i++) {\n        if (G.info[i].cfilname != (char Far *)NULL) {\n            zffree(G.info[i].cfilname);\n            G.info[i].cfilname = (char Far *)NULL;\n        }\n    }\n#endif\n\n#ifdef MALLOC_WORK\n    if (G.area.Slide) {\n        free(G.area.Slide);\n        G.area.Slide = (uch *)NULL;\n    }\n#endif\n\n} /* end function free_G_buffers() */\n\n\n\n\n\n/**************************/\n/* Function do_seekable() */\n/**************************/\n\nstatic int do_seekable(__G__ lastchance)        /* return PK-type error code */\n    __GDEF\n    int lastchance;\n{\n#ifndef SFX\n    /* static int no_ecrec = FALSE;  SKM: moved to globals.h */\n    int maybe_exe=FALSE;\n    int too_weird_to_continue=FALSE;\n#ifdef TIMESTAMP\n    time_t uxstamp;\n    ulg nmember = 0L;\n#endif\n#endif\n    int error=0, error_in_archive;\n\n\n/*---------------------------------------------------------------------------\n    Open the zipfile for reading in BINARY mode to prevent CR/LF translation,\n    which would corrupt the bit streams.\n  ---------------------------------------------------------------------------*/\n\n    if (SSTAT(G.zipfn, &G.statbuf) ||\n#ifdef THEOS\n        (error = S_ISLIB(G.statbuf.st_mode)) != 0 ||\n#endif\n        (error = S_ISDIR(G.statbuf.st_mode)) != 0)\n    {\n#ifndef SFX\n        if (lastchance && (uO.qflag < 3)) {\n#if defined(UNIX) || defined(QDOS)\n            if (G.no_ecrec)\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(CannotFindZipfileDirMsg),\n                  LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                  G.wildzipfn, uO.zipinfo_mode? \"  \" : \"\", G.wildzipfn,\n                  G.zipfn));\n            else\n                Info(slide, 1, ((char *)slide,\n                  LoadFarString(CannotFindEitherZipfile),\n                  LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                  G.wildzipfn, G.wildzipfn, G.zipfn));\n#else /* !(UNIX || QDOS) */\n            if (G.no_ecrec)\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotFindZipfileDirMsg),\n                  LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                  G.wildzipfn, uO.zipinfo_mode? \"  \" : \"\", G.zipfn));\n            else\n#ifdef VMS\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotFindEitherZipfile),\n                  LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                  G.wildzipfn,\n                  (*G.zipfn ? G.zipfn : vms_msg_text())));\n#else /* !VMS */\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotFindEitherZipfile),\n                  LoadFarStringSmall((uO.zipinfo_mode ? Zipnfo : Unzip)),\n                  G.wildzipfn, G.zipfn));\n#endif /* ?VMS */\n#endif /* ?(UNIX || QDOS) */\n        }\n#endif /* !SFX */\n        return error? IZ_DIR : PK_NOZIP;\n    }\n    G.ziplen = G.statbuf.st_size;\n\n#ifndef SFX\n#if defined(UNIX) || defined(DOS_OS2_W32) || defined(THEOS)\n    if (G.statbuf.st_mode & S_IEXEC)   /* no extension on Unix exes:  might */\n        maybe_exe = TRUE;               /*  find unzip, not unzip.zip; etc. */\n#endif\n#endif /* !SFX */\n\n#ifdef VMS\n    if (check_format(__G))              /* check for variable-length format */\n        return PK_ERR;\n#endif\n\n    if (open_input_file(__G))   /* this should never happen, given */\n        return PK_NOZIP;        /*  the stat() test above, but... */\n\n#ifdef DO_SAFECHECK_2GB\n    /* Need more care: Do not trust the size returned by stat() but\n       determine it by reading beyond the end of the file. */\n    G.ziplen = file_size(G.zipfd);\n\n    if (G.ziplen == EOF) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileTooBig)));\n        /*\n        printf(\n\" We need a better error message for: 64-bit file, 32-bit program.\\n\");\n        */\n        CLOSE_INFILE();\n        return IZ_ERRBF;\n    }\n#endif /* DO_SAFECHECK_2GB */\n\n/*---------------------------------------------------------------------------\n    Find and process the end-of-central-directory header.  UnZip need only\n    check last 65557 bytes of zipfile:  comment may be up to 65535, end-of-\n    central-directory record is 18 bytes, and signature itself is 4 bytes;\n    add some to allow for appended garbage.  Since ZipInfo is often used as\n    a debugging tool, search the whole zipfile if zipinfo_mode is true.\n  ---------------------------------------------------------------------------*/\n\n    G.cur_zipfile_bufstart = 0;\n    G.inptr = G.inbuf;\n\n#if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO))\n# if (!defined(WINDLL) && !defined(SFX))\n    if ( (!uO.zipinfo_mode && !uO.qflag\n#  ifdef TIMESTAMP\n          && !uO.T_flag\n#  endif\n         )\n#  ifndef NO_ZIPINFO\n         || (uO.zipinfo_mode && uO.hflag)\n#  endif\n       )\n# else /* not (!WINDLL && !SFX) ==> !NO_ZIPINFO !! */\n    if (uO.zipinfo_mode && uO.hflag)\n# endif /* if..else..: (!WINDLL && !SFX) */\n# ifdef WIN32   /* Win32 console may require codepage conversion for G.zipfn */\n        Info(slide, 0, ((char *)slide, LoadFarString(LogInitline),\n          FnFilter1(G.zipfn)));\n# else\n        Info(slide, 0, ((char *)slide, LoadFarString(LogInitline), G.zipfn));\n# endif\n#endif /* (!WINDLL && !SFX) || !NO_ZIPINFO */\n\n    if ( (error_in_archive = find_ecrec(__G__\n#ifndef NO_ZIPINFO\n                                        uO.zipinfo_mode ? G.ziplen :\n#endif\n                                        MIN(G.ziplen, 66000L)))\n         > PK_WARN )\n    {\n        CLOSE_INFILE();\n\n#ifdef SFX\n        ++lastchance;   /* avoid picky compiler warnings */\n        return error_in_archive;\n#else\n        if (maybe_exe)\n            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeExe),\n            G.zipfn));\n        if (lastchance)\n            return error_in_archive;\n        else {\n            G.no_ecrec = TRUE;    /* assume we found wrong file:  e.g., */\n            return PK_NOZIP;       /*  unzip instead of unzip.zip */\n        }\n#endif /* ?SFX */\n    }\n\n    if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */\n        CLOSE_INFILE();\n        return error_in_archive;\n    }\n\n/*---------------------------------------------------------------------------\n    Test the end-of-central-directory info for incompatibilities (multi-disk\n    archives) or inconsistencies (missing or extra bytes in zipfile).\n  ---------------------------------------------------------------------------*/\n\n#ifdef NO_MULTIPART\n    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk == 1) &&\n            (G.ecrec.num_disk_start_cdir == 1);\n#else\n    error = !uO.zipinfo_mode && (G.ecrec.number_this_disk != 0);\n#endif\n\n#ifndef SFX\n    if (uO.zipinfo_mode &&\n        G.ecrec.number_this_disk != G.ecrec.num_disk_start_cdir)\n    {\n        if (G.ecrec.number_this_disk > G.ecrec.num_disk_start_cdir) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(CentDirNotInZipMsg), G.zipfn,\n              (ulg)G.ecrec.number_this_disk,\n              (ulg)G.ecrec.num_disk_start_cdir));\n            error_in_archive = PK_FIND;\n            too_weird_to_continue = TRUE;\n        } else {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(EndCentDirBogus), G.zipfn,\n              (ulg)G.ecrec.number_this_disk,\n              (ulg)G.ecrec.num_disk_start_cdir));\n            error_in_archive = PK_WARN;\n        }\n#ifdef NO_MULTIPART   /* concatenation of multiple parts works in some cases */\n    } else if (!uO.zipinfo_mode && !error && G.ecrec.number_this_disk != 0) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(NoMultiDiskArcSupport),\n          G.zipfn));\n        error_in_archive = PK_FIND;\n        too_weird_to_continue = TRUE;\n#endif\n    }\n\n    if (!too_weird_to_continue) {  /* (relatively) normal zipfile:  go for it */\n        if (error) {\n            Info(slide, 0x401, ((char *)slide, LoadFarString(MaybePakBug),\n              G.zipfn));\n            error_in_archive = PK_WARN;\n        }\n#endif /* !SFX */\n        if ((G.extra_bytes = G.real_ecrec_offset-G.expect_ecrec_offset) <\n            (zoff_t)0)\n        {\n            Info(slide, 0x401, ((char *)slide, LoadFarString(MissingBytes),\n              G.zipfn, FmZofft((-G.extra_bytes), NULL, NULL)));\n            error_in_archive = PK_ERR;\n        } else if (G.extra_bytes > 0) {\n            if ((G.ecrec.offset_start_central_directory == 0) &&\n                (G.ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */\n            {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(NullCentDirOffset), G.zipfn));\n                G.ecrec.offset_start_central_directory = G.extra_bytes;\n                G.extra_bytes = 0;\n                error_in_archive = PK_ERR;\n            }\n#ifndef SFX\n            else {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(ExtraBytesAtStart), G.zipfn,\n                  FmZofft(G.extra_bytes, NULL, NULL),\n                  (G.extra_bytes == 1)? \"\":\"s\"));\n                error_in_archive = PK_WARN;\n            }\n#endif /* !SFX */\n        }\n\n    /*-----------------------------------------------------------------------\n        Check for empty zipfile and exit now if so.\n      -----------------------------------------------------------------------*/\n\n        if (G.expect_ecrec_offset==0L && G.ecrec.size_central_directory==0) {\n            if (uO.zipinfo_mode)\n                Info(slide, 0, ((char *)slide, \"%sEmpty zipfile.\\n\",\n                  uO.lflag>9? \"\\n  \" : \"\"));\n            else\n                Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty),\n                                    G.zipfn));\n            CLOSE_INFILE();\n            return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;\n        }\n\n    /*-----------------------------------------------------------------------\n        Compensate for missing or extra bytes, and seek to where the start\n        of central directory should be.  If header not found, uncompensate\n        and try again (necessary for at least some Atari archives created\n        with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).\n      -----------------------------------------------------------------------*/\n\n        error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);\n        if (error == PK_BADERR) {\n            CLOSE_INFILE();\n            return PK_BADERR;\n        }\n#ifdef OLD_SEEK_TEST\n        if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) {\n            CLOSE_INFILE();\n            return PK_ERR;  /* file may be locked, or possibly disk error(?) */\n        }\n        if (memcmp(G.sig, central_hdr_sig, 4))\n#else\n        if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||\n            memcmp(G.sig, central_hdr_sig, 4))\n#endif\n        {\n#ifndef SFX\n            zoff_t tmp = G.extra_bytes;\n#endif\n\n            G.extra_bytes = 0;\n            error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);\n            if ((error != PK_OK) || (readbuf(__G__ G.sig, 4) == 0) ||\n                memcmp(G.sig, central_hdr_sig, 4))\n            {\n                if (error != PK_BADERR)\n                  Info(slide, 0x401, ((char *)slide,\n                    LoadFarString(CentDirStartNotFound), G.zipfn,\n                    LoadFarStringSmall(ReportMsg)));\n                CLOSE_INFILE();\n                return (error != PK_OK ? error : PK_BADERR);\n            }\n#ifndef SFX\n            Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong),\n              G.zipfn, FmZofft((-tmp), NULL, NULL)));\n#endif\n            error_in_archive = PK_ERR;\n        }\n\n    /*-----------------------------------------------------------------------\n        Seek to the start of the central directory one last time, since we\n        have just read the first entry's signature bytes; then list, extract\n        or test member files as instructed, and close the zipfile.\n      -----------------------------------------------------------------------*/\n\n        error = seek_zipf(__G__ G.ecrec.offset_start_central_directory);\n        if (error != PK_OK) {\n            CLOSE_INFILE();\n            return error;\n        }\n\n        Trace((stderr, \"about to extract/list files (error = %d)\\n\",\n          error_in_archive));\n\n#ifdef DLL\n        /* G.fValidate is used only to look at an archive to see if\n           it appears to be a valid archive.  There is no interest\n           in what the archive contains, nor in validating that the\n           entries in the archive are in good condition.  This is\n           currently used only in the Windows DLLs for purposes of\n           checking archives within an archive to determine whether\n           or not to display the inner archives.\n         */\n        if (!G.fValidate)\n#endif\n        {\n#ifndef NO_ZIPINFO\n            if (uO.zipinfo_mode)\n                error = zipinfo(__G);                 /* ZIPINFO 'EM */\n            else\n#endif\n#ifndef SFX\n#ifdef TIMESTAMP\n            if (uO.T_flag)\n                error = get_time_stamp(__G__ &uxstamp, &nmember);\n            else\n#endif\n            if (uO.vflag && !uO.tflag && !uO.cflag)\n                error = list_files(__G);              /* LIST 'EM */\n            else\n#endif /* !SFX */\n                error = extract_or_test_files(__G);   /* EXTRACT OR TEST 'EM */\n\n            Trace((stderr, \"done with extract/list files (error = %d)\\n\",\n                   error));\n        }\n\n        if (error > error_in_archive)   /* don't overwrite stronger error */\n            error_in_archive = error;   /*  with (for example) a warning */\n#ifndef SFX\n    } /* end if (!too_weird_to_continue) */\n#endif\n\n    CLOSE_INFILE();\n\n#ifdef TIMESTAMP\n    if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) {\n# ifdef WIN32\n        if (stamp_file(__G__ G.zipfn, uxstamp)) {       /* TIME-STAMP 'EM */\n# else\n        if (stamp_file(G.zipfn, uxstamp)) {             /* TIME-STAMP 'EM */\n# endif\n            if (uO.qflag < 3)\n                Info(slide, 0x201, ((char *)slide,\n                  LoadFarString(ZipTimeStampFailed), G.zipfn));\n            if (error_in_archive < PK_WARN)\n                error_in_archive = PK_WARN;\n        } else {\n            if (!uO.qflag)\n                Info(slide, 0, ((char *)slide,\n                  LoadFarString(ZipTimeStampSuccess), G.zipfn));\n        }\n    }\n#endif\n    return error_in_archive;\n\n} /* end function do_seekable() */\n\n\n\n\n#ifdef DO_SAFECHECK_2GB\n/************************/\n/* Function file_size() */\n/************************/\n/* File size determination which does not mislead for large files in a\n   small-file program.  Probably should be somewhere else.\n   The file has to be opened previously\n*/\n#ifdef USE_STRM_INPUT\nstatic zoff_t file_size(file)\n    FILE *file;\n{\n    int sts;\n    size_t siz;\n#else /* !USE_STRM_INPUT */\nstatic zoff_t file_size(fh)\n    int fh;\n{\n    int siz;\n#endif /* ?USE_STRM_INPUT */\n    zoff_t ofs;\n    char waste[4];\n\n#ifdef USE_STRM_INPUT\n    /* Seek to actual EOF. */\n    sts = zfseeko(file, 0, SEEK_END);\n    if (sts != 0) {\n        /* fseeko() failed.  (Unlikely.) */\n        ofs = EOF;\n    } else {\n        /* Get apparent offset at EOF. */\n        ofs = zftello(file);\n        if (ofs < 0) {\n            /* Offset negative (overflow).  File too big. */\n            ofs = EOF;\n        } else {\n            /* Seek to apparent EOF offset.\n               Won't be at actual EOF if offset was truncated.\n            */\n            sts = zfseeko(file, ofs, SEEK_SET);\n            if (sts != 0) {\n                /* fseeko() failed.  (Unlikely.) */\n                ofs = EOF;\n            } else {\n                /* Read a byte at apparent EOF.  Should set EOF flag. */\n                siz = fread(waste, 1, 1, file);\n                if (feof(file) == 0) {\n                    /* Not at EOF, but should be.  File too big. */\n                    ofs = EOF;\n                }\n            }\n        }\n    }\n#else /* !USE_STRM_INPUT */\n    /* Seek to actual EOF. */\n    ofs = zlseek(fh, 0, SEEK_END);\n    if (ofs == (zoff_t) -1) {\n        /* zlseek() failed.  (Unlikely.) */\n        ofs = EOF;\n    } else if (ofs < 0) {\n        /* Offset negative (overflow).  File too big. */\n        ofs = EOF;\n    } else {\n        /* Seek to apparent EOF offset.\n           Won't be at actual EOF if offset was truncated.\n        */\n        ofs = zlseek(fh, ofs, SEEK_SET);\n        if (ofs == (zoff_t) -1) {\n            /* zlseek() failed.  (Unlikely.) */\n            ofs = EOF;\n        } else {\n            /* Read a byte at apparent EOF.  Should set EOF flag. */\n            siz = read(fh, waste, 1);\n            if (siz != 0) {\n                /* Not at EOF, but should be.  File too big. */\n                ofs = EOF;\n            }\n        }\n    }\n#endif /* ?USE_STRM_INPUT */\n    return ofs;\n} /* end function file_size() */\n#endif /* DO_SAFECHECK_2GB */\n\n\n\n\n/***********************/\n/* Function rec_find() */\n/***********************/\n\nstatic int rec_find(__G__ searchlen, signature, rec_size)\n    /* return 0 when rec found, 1 when not found, 2 in case of read error */\n    __GDEF\n    zoff_t searchlen;\n    char* signature;\n    int rec_size;\n{\n    int i, numblks, found=FALSE;\n    zoff_t tail_len;\n\n/*---------------------------------------------------------------------------\n    Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short\n    block at end of zipfile (if not TOO short).\n  ---------------------------------------------------------------------------*/\n\n    if ((tail_len = G.ziplen % INBUFSIZ) > rec_size) {\n#ifdef USE_STRM_INPUT\n        zfseeko(G.zipfd, G.ziplen-tail_len, SEEK_SET);\n        G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n        G.cur_zipfile_bufstart = zlseek(G.zipfd, G.ziplen-tail_len, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n        if ((G.incnt = read(G.zipfd, (char *)G.inbuf,\n            (unsigned int)tail_len)) != (int)tail_len)\n            return 2;      /* it's expedient... */\n\n        /* 'P' must be at least (rec_size+4) bytes from end of zipfile */\n        for (G.inptr = G.inbuf+(int)tail_len-(rec_size+4);\n             G.inptr >= G.inbuf;\n             --G.inptr) {\n            if ( (*G.inptr == (uch)0x50) &&         /* ASCII 'P' */\n                 !memcmp((char *)G.inptr, signature, 4) ) {\n                G.incnt -= (int)(G.inptr - G.inbuf);\n                found = TRUE;\n                break;\n            }\n        }\n        /* sig may span block boundary: */\n        memcpy((char *)G.hold, (char *)G.inbuf, 3);\n    } else\n        G.cur_zipfile_bufstart = G.ziplen - tail_len;\n\n/*-----------------------------------------------------------------------\n    Loop through blocks of zipfile data, starting at the end and going\n    toward the beginning.  In general, need not check whole zipfile for\n    signature, but may want to do so if testing.\n  -----------------------------------------------------------------------*/\n\n    numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);\n    /*               ==amount=   ==done==   ==rounding==    =blksiz=  */\n\n    for (i = 1;  !found && (i <= numblks);  ++i) {\n        G.cur_zipfile_bufstart -= INBUFSIZ;\n#ifdef USE_STRM_INPUT\n        zfseeko(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);\n#else /* !USE_STRM_INPUT */\n        zlseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n        if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ))\n            != INBUFSIZ)\n            return 2;          /* read error is fatal failure */\n\n        for (G.inptr = G.inbuf+INBUFSIZ-1;  G.inptr >= G.inbuf; --G.inptr)\n            if ( (*G.inptr == (uch)0x50) &&         /* ASCII 'P' */\n                 !memcmp((char *)G.inptr, signature, 4) ) {\n                G.incnt -= (int)(G.inptr - G.inbuf);\n                found = TRUE;\n                break;\n            }\n        /* sig may span block boundary: */\n        memcpy((char *)G.hold, (char *)G.inbuf, 3);\n    }\n    return (found ? 0 : 1);\n} /* end function rec_find() */\n\n\n\n\n#if 0\n/********************************/\n/* Function check_ecrec_zip64() */\n/********************************/\n\nstatic int check_ecrec_zip64(__G)\n    __GDEF\n{\n    return G.ecrec.offset_start_central_directory  == 0xFFFFFFFFL\n        || G.ecrec.size_central_directory          == 0xFFFFFFFFL\n        || G.ecrec.total_entries_central_dir       == 0xFFFF\n        || G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF\n        || G.ecrec.num_disk_start_cdir             == 0xFFFF\n        || G.ecrec.number_this_disk                == 0xFFFF;\n} /* end function check_ecrec_zip64() */\n#endif /* never */\n\n\n\n/***************************/\n/* Function find_ecrec64() */\n/***************************/\n\nstatic int find_ecrec64(__G__ searchlen)         /* return PK-class error */\n    __GDEF\n    zoff_t searchlen;\n{\n    ec_byte_rec64 byterec;          /* buf for ecrec64 */\n    ec_byte_loc64 byterecL;         /* buf for ecrec64 locator */\n    zoff_t ecloc64_start_offset;    /* start offset of ecrec64 locator */\n    zusz_t ecrec64_start_offset;    /* start offset of ecrec64 */\n    zuvl_t ecrec64_start_disk;      /* start disk of ecrec64 */\n    zuvl_t ecloc64_total_disks;     /* total disks */\n    zuvl_t ecrec64_disk_cdstart;    /* disk number of central dir start */\n    zucn_t ecrec64_this_entries;    /* entries on disk with ecrec64 */\n    zucn_t ecrec64_tot_entries;     /* total number of entries */\n    zusz_t ecrec64_cdirsize;        /* length of central dir */\n    zusz_t ecrec64_offs_cdstart;    /* offset of central dir start */\n\n    /* First, find the ecrec64 locator.  By definition, this must be before\n       ecrec with nothing in between.  We back up the size of the ecrec64\n       locator and check.  */\n\n    ecloc64_start_offset = G.real_ecrec_offset - (ECLOC64_SIZE+4);\n    if (ecloc64_start_offset < 0)\n      /* Seeking would go past beginning, so probably empty archive */\n      return PK_COOL;\n\n#ifdef USE_STRM_INPUT\n    zfseeko(G.zipfd, ecloc64_start_offset, SEEK_SET);\n    G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n    G.cur_zipfile_bufstart = zlseek(G.zipfd, ecloc64_start_offset, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n\n    if ((G.incnt = read(G.zipfd, (char *)byterecL, ECLOC64_SIZE+4))\n        != (ECLOC64_SIZE+4)) {\n      if (uO.qflag || uO.zipinfo_mode)\n          Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n      Info(slide, 0x401, ((char *)slide,\n        LoadFarString(Cent64EndSigSearchErr)));\n      return PK_ERR;\n    }\n\n    if (memcmp((char *)byterecL, end_centloc64_sig, 4) ) {\n      /* not found */\n      return PK_COOL;\n    }\n\n    /* Read the locator. */\n    ecrec64_start_disk = (zuvl_t)makelong(&byterecL[NUM_DISK_START_EOCDR64]);\n    ecrec64_start_offset = (zusz_t)makeint64(&byterecL[OFFSET_START_EOCDR64]);\n    ecloc64_total_disks = (zuvl_t)makelong(&byterecL[NUM_THIS_DISK_LOC64]);\n\n    /* Check for consistency */\n#ifdef TEST\n    fprintf(stdout,\"\\nnumber of disks (ECR) %u, (ECLOC64) %lu\\n\",\n            G.ecrec.number_this_disk, ecloc64_total_disks); fflush(stdout);\n#endif\n    if ((G.ecrec.number_this_disk != 0xFFFF) &&\n        (G.ecrec.number_this_disk != ecloc64_total_disks - 1)) {\n      /* Note: For some unknown reason, the developers at PKWARE decided to\n         store the \"zip64 total disks\" value as a counter starting from 1,\n         whereas all other \"split/span volume\" related fields use 0-based\n         volume numbers. Sigh... */\n      /* When the total number of disks as found in the traditional ecrec\n         is not 0xFFFF, the disk numbers in ecrec and ecloc64 must match.\n         When this is not the case, the found ecrec64 locator cannot be valid.\n         -> This is not a Zip64 archive.\n       */\n      Trace((stderr,\n             \"\\ninvalid ECLOC64, differing disk# (ECR %u, ECL64 %lu)\\n\",\n             G.ecrec.number_this_disk, ecloc64_total_disks - 1));\n      return PK_COOL;\n    }\n\n    /* If found locator, look for ecrec64 where the locator says it is. */\n\n    /* For now assume that ecrec64 is on the same disk as ecloc64 and ecrec,\n       which is usually the case and is how Zip writes it.  To do this right,\n       however, we should allow the ecrec64 to be on another disk since\n       the AppNote allows it and the ecrec64 can be large, especially if\n       Version 2 is used (AppNote uses 8 bytes for the size of this record). */\n\n    /* FIX BELOW IF ADD SUPPORT FOR MULTIPLE DISKS */\n\n    if (ecrec64_start_offset > (zusz_t)ecloc64_start_offset) {\n      /* ecrec64 has to be before ecrec64 locator */\n      if (uO.qflag || uO.zipinfo_mode)\n          Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n      Info(slide, 0x401, ((char *)slide,\n        LoadFarString(Cent64EndSigSearchErr)));\n      return PK_ERR;\n    }\n\n#ifdef USE_STRM_INPUT\n    zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET);\n    G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n    G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n\n    if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4))\n        != (ECREC64_SIZE+4)) {\n      if (uO.qflag || uO.zipinfo_mode)\n          Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n      Info(slide, 0x401, ((char *)slide,\n        LoadFarString(Cent64EndSigSearchErr)));\n      return PK_ERR;\n    }\n\n    if (memcmp((char *)byterec, end_central64_sig, 4) ) {\n      /* Zip64 EOCD Record not found */\n      /* Since we already have seen the Zip64 EOCD Locator, it's\n         possible we got here because there are bytes prepended\n         to the archive, like the sfx prefix. */\n\n      /* Make a guess as to where the Zip64 EOCD Record might be */\n      ecrec64_start_offset = ecloc64_start_offset - ECREC64_SIZE - 4;\n\n#ifdef USE_STRM_INPUT\n      zfseeko(G.zipfd, ecrec64_start_offset, SEEK_SET);\n      G.cur_zipfile_bufstart = zftello(G.zipfd);\n#else /* !USE_STRM_INPUT */\n      G.cur_zipfile_bufstart = zlseek(G.zipfd, ecrec64_start_offset, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n\n      if ((G.incnt = read(G.zipfd, (char *)byterec, ECREC64_SIZE+4))\n          != (ECREC64_SIZE+4)) {\n        if (uO.qflag || uO.zipinfo_mode)\n            Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n        Info(slide, 0x401, ((char *)slide,\n          LoadFarString(Cent64EndSigSearchErr)));\n        return PK_ERR;\n      }\n\n      if (memcmp((char *)byterec, end_central64_sig, 4) ) {\n        /* Zip64 EOCD Record not found */\n        /* Probably something not so easy to handle so exit */\n        if (uO.qflag || uO.zipinfo_mode)\n            Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n        Info(slide, 0x401, ((char *)slide,\n          LoadFarString(Cent64EndSigSearchErr)));\n        return PK_ERR;\n      }\n\n      if (uO.qflag || uO.zipinfo_mode)\n          Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n      Info(slide, 0x401, ((char *)slide,\n        LoadFarString(Cent64EndSigSearchOff)));\n    }\n\n    /* Check consistency of found ecrec64 with ecloc64 (and ecrec): */\n    if ( (zuvl_t)makelong(&byterec[NUMBER_THIS_DSK_REC64])\n         != ecrec64_start_disk )\n        /* found ecrec64 does not match ecloc64 info -> no Zip64 archive */\n        return PK_COOL;\n    /* Read all relevant ecrec64 fields and compare them to the corresponding\n       ecrec fields unless those are set to \"all-ones\".\n     */\n    ecrec64_disk_cdstart =\n      (zuvl_t)makelong(&byterec[NUM_DISK_START_CEN_DIR64]);\n    if ( (G.ecrec.num_disk_start_cdir != 0xFFFF) &&\n         (G.ecrec.num_disk_start_cdir != ecrec64_disk_cdstart) )\n        return PK_COOL;\n    ecrec64_this_entries\n      = makeint64(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK64]);\n    if ( (G.ecrec.num_entries_centrl_dir_ths_disk != 0xFFFF) &&\n         (G.ecrec.num_entries_centrl_dir_ths_disk != ecrec64_this_entries) )\n        return PK_COOL;\n    ecrec64_tot_entries\n      = makeint64(&byterec[TOTAL_ENTRIES_CENTRAL_DIR64]);\n    if ( (G.ecrec.total_entries_central_dir != 0xFFFF) &&\n         (G.ecrec.total_entries_central_dir != ecrec64_tot_entries) )\n        return PK_COOL;\n    ecrec64_cdirsize\n      = makeint64(&byterec[SIZE_CENTRAL_DIRECTORY64]);\n    if ( (G.ecrec.size_central_directory != 0xFFFFFFFFL) &&\n         (G.ecrec.size_central_directory != ecrec64_cdirsize) )\n        return PK_COOL;\n    ecrec64_offs_cdstart\n      = makeint64(&byterec[OFFSET_START_CENTRAL_DIRECT64]);\n    if ( (G.ecrec.offset_start_central_directory != 0xFFFFFFFFL) &&\n         (G.ecrec.offset_start_central_directory != ecrec64_offs_cdstart) )\n        return PK_COOL;\n\n    /* Now, we are (almost) sure that we have a Zip64 archive. */\n    G.ecrec.have_ecr64 = 1;\n\n    /* Update the \"end-of-central-dir offset\" for later checks. */\n    G.real_ecrec_offset = ecrec64_start_offset;\n\n    /* Update all ecdir_rec data that are flagged to be invalid\n       in Zip64 mode.  Set the ecrec64-mandatory flag when such a\n       case is found. */\n    if (G.ecrec.number_this_disk == 0xFFFF) {\n      G.ecrec.number_this_disk = ecrec64_start_disk;\n      if (ecrec64_start_disk != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n    if (G.ecrec.num_disk_start_cdir == 0xFFFF) {\n      G.ecrec.num_disk_start_cdir = ecrec64_disk_cdstart;\n      if (ecrec64_disk_cdstart != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n    if (G.ecrec.num_entries_centrl_dir_ths_disk == 0xFFFF) {\n      G.ecrec.num_entries_centrl_dir_ths_disk = ecrec64_this_entries;\n      if (ecrec64_this_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n    if (G.ecrec.total_entries_central_dir == 0xFFFF) {\n      G.ecrec.total_entries_central_dir = ecrec64_tot_entries;\n      if (ecrec64_tot_entries != 0xFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n    if (G.ecrec.size_central_directory == 0xFFFFFFFFL) {\n      G.ecrec.size_central_directory = ecrec64_cdirsize;\n      if (ecrec64_cdirsize != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n    if (G.ecrec.offset_start_central_directory == 0xFFFFFFFFL) {\n      G.ecrec.offset_start_central_directory = ecrec64_offs_cdstart;\n      if (ecrec64_offs_cdstart != 0xFFFFFFFF) G.ecrec.is_zip64_archive = TRUE;\n    }\n\n    return PK_COOL;\n} /* end function find_ecrec64() */\n\n\n\n/*************************/\n/* Function find_ecrec() */\n/*************************/\n\nstatic int find_ecrec(__G__ searchlen)          /* return PK-class error */\n    __GDEF\n    zoff_t searchlen;\n{\n    int found = FALSE;\n    int error_in_archive;\n    int result;\n    ec_byte_rec byterec;\n\n/*---------------------------------------------------------------------------\n    Treat case of short zipfile separately.\n  ---------------------------------------------------------------------------*/\n\n    if (G.ziplen <= INBUFSIZ) {\n#ifdef USE_STRM_INPUT\n        zfseeko(G.zipfd, 0L, SEEK_SET);\n#else /* !USE_STRM_INPUT */\n        zlseek(G.zipfd, 0L, SEEK_SET);\n#endif /* ?USE_STRM_INPUT */\n        if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen))\n            == (int)G.ziplen)\n\n            /* 'P' must be at least (ECREC_SIZE+4) bytes from end of zipfile */\n            for (G.inptr = G.inbuf+(int)G.ziplen-(ECREC_SIZE+4);\n                 G.inptr >= G.inbuf;\n                 --G.inptr) {\n                if ( (*G.inptr == (uch)0x50) &&         /* ASCII 'P' */\n                     !memcmp((char *)G.inptr, end_central_sig, 4)) {\n                    G.incnt -= (int)(G.inptr - G.inbuf);\n                    found = TRUE;\n                    break;\n                }\n            }\n\n/*---------------------------------------------------------------------------\n    Zipfile is longer than INBUFSIZ:\n\n    MB - this next block of code moved to rec_find so that same code can be\n    used to look for zip64 ec record.  No need to include code above since\n    a zip64 ec record will only be looked for if it is a BIG file.\n  ---------------------------------------------------------------------------*/\n\n    } else {\n        found =\n          (rec_find(__G__ searchlen, end_central_sig, ECREC_SIZE) == 0\n           ? TRUE : FALSE);\n    } /* end if (ziplen > INBUFSIZ) */\n\n/*---------------------------------------------------------------------------\n    Searched through whole region where signature should be without finding\n    it.  Print informational message and die a horrible death.\n  ---------------------------------------------------------------------------*/\n\n    if (!found) {\n        if (uO.qflag || uO.zipinfo_mode)\n            Info(slide, 0x401, ((char *)slide, \"[%s]\\n\", G.zipfn));\n        Info(slide, 0x401, ((char *)slide,\n          LoadFarString(CentDirEndSigNotFound)));\n        return PK_ERR;   /* failed */\n    }\n\n/*---------------------------------------------------------------------------\n    Found the signature, so get the end-central data before returning.  Do\n    any necessary machine-type conversions (byte ordering, structure padding\n    compensation) by reading data into character array and copying to struct.\n  ---------------------------------------------------------------------------*/\n\n    G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);\n#ifdef TEST\n    printf(\"\\n  found end-of-central-dir signature at offset %s (%sh)\\n\",\n      FmZofft(G.real_ecrec_offset, NULL, NULL),\n      FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, \"X\"));\n    printf(\"    from beginning of file; offset %d (%.4Xh) within block\\n\",\n      G.inptr-G.inbuf, G.inptr-G.inbuf);\n#endif\n\n    if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0)\n        return PK_EOF;\n\n    G.ecrec.number_this_disk =\n      makeword(&byterec[NUMBER_THIS_DISK]);\n    G.ecrec.num_disk_start_cdir =\n      makeword(&byterec[NUM_DISK_WITH_START_CEN_DIR]);\n    G.ecrec.num_entries_centrl_dir_ths_disk =\n      makeword(&byterec[NUM_ENTRIES_CEN_DIR_THS_DISK]);\n    G.ecrec.total_entries_central_dir =\n      makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);\n    G.ecrec.size_central_directory =\n      makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);\n    G.ecrec.offset_start_central_directory =\n      makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);\n    G.ecrec.zipfile_comment_length =\n      makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);\n\n    /* Now, we have to read the archive comment, BEFORE the file pointer\n       is moved away backwards to seek for a Zip64 ECLOC64 structure.\n     */\n    if ( (error_in_archive = process_zip_cmmnt(__G)) > PK_WARN )\n        return error_in_archive;\n\n    /* Next: Check for existence of Zip64 end-of-cent-dir locator\n       ECLOC64. This structure must reside on the same volume as the\n       classic ECREC, at exactly (ECLOC64_SIZE+4) bytes in front\n       of the ECREC.\n       The ECLOC64 structure directs to the longer ECREC64 structure\n       A ECREC64 will ALWAYS exist for a proper Zip64 archive, as\n       the \"Version Needed To Extract\" field is required to be set\n       to 4.5 or higher whenever any Zip64 features are used anywhere\n       in the archive, so just check for that to see if this is a\n       Zip64 archive.\n     */\n    result = find_ecrec64(__G__ searchlen+76);\n        /* 76 bytes for zip64ec & zip64 locator */\n    if (result != PK_COOL) {\n        if (error_in_archive < result)\n            error_in_archive = result;\n        return error_in_archive;\n    }\n\n    G.expect_ecrec_offset = G.ecrec.offset_start_central_directory +\n                            G.ecrec.size_central_directory;\n\n#ifndef NO_ZIPINFO\n    if (uO.zipinfo_mode) {\n        /* In ZipInfo mode, additional info about the data found in the\n           end-of-central-directory areas is printed out.\n         */\n        zi_end_central(__G);\n    }\n#endif\n\n    return error_in_archive;\n\n} /* end function find_ecrec() */\n\n\n\n\n\n/********************************/\n/* Function process_zip_cmmnt() */\n/********************************/\n\nstatic int process_zip_cmmnt(__G)       /* return PK-type error code */\n    __GDEF\n{\n    int error = PK_COOL;\n\n\n/*---------------------------------------------------------------------------\n    Get the zipfile comment (up to 64KB long), if any, and print it out.\n  ---------------------------------------------------------------------------*/\n\n#ifdef WINDLL\n    /* for comment button: */\n    if ((!G.fValidate) && (G.lpUserFunctions != NULL))\n       G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length;\n#endif /* WINDLL */\n\n#ifndef NO_ZIPINFO\n    /* ZipInfo, verbose format */\n    if (uO.zipinfo_mode && uO.lflag > 9) {\n        /*-------------------------------------------------------------------\n            Get the zipfile comment, if any, and print it out.\n            (Comment may be up to 64KB long.  May the fleas of a thousand\n            camels infest the arm-pits of anyone who actually takes advantage\n            of this fact.)\n          -------------------------------------------------------------------*/\n\n        if (!G.ecrec.zipfile_comment_length)\n            Info(slide, 0, ((char *)slide, LoadFarString(NoZipfileComment)));\n        else {\n            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommentDesc),\n              G.ecrec.zipfile_comment_length));\n            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommBegin)));\n            if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY))\n                error = PK_WARN;\n            Info(slide, 0, ((char *)slide, LoadFarString(ZipfileCommEnd)));\n            if (error)\n                Info(slide, 0, ((char *)slide,\n                  LoadFarString(ZipfileCommTrunc2)));\n        } /* endif (comment exists) */\n\n    /* ZipInfo, non-verbose mode:  print zipfile comment only if requested */\n    } else if (G.ecrec.zipfile_comment_length &&\n               (uO.zflag > 0) && uO.zipinfo_mode) {\n        if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(ZipfileCommTrunc1)));\n            error = PK_WARN;\n        }\n    } else\n#endif /* !NO_ZIPINFO */\n    if ( G.ecrec.zipfile_comment_length &&\n         (uO.zflag > 0\n#ifndef WINDLL\n          || (uO.zflag == 0\n# ifndef NO_ZIPINFO\n              && !uO.zipinfo_mode\n# endif\n# ifdef TIMESTAMP\n              && !uO.T_flag\n# endif\n              && !uO.qflag)\n#endif /* !WINDLL */\n         ) )\n    {\n        if (do_string(__G__ G.ecrec.zipfile_comment_length,\n#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))\n# ifndef NO_ZIPINFO\n                      (oU.zipinfo_mode ? DISPLAY : CHECK_AUTORUN)\n# else\n                      CHECK_AUTORUN\n# endif\n#else\n                      DISPLAY\n#endif\n                     ))\n        {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(ZipfileCommTrunc1)));\n            error = PK_WARN;\n        }\n    }\n#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))\n    else if (G.ecrec.zipfile_comment_length) {\n        if (do_string(__G__ G.ecrec.zipfile_comment_length, CHECK_AUTORUN_Q))\n        {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(ZipfileCommTrunc1)));\n            error = PK_WARN;\n        }\n    }\n#endif\n    return error;\n\n} /* end function process_zip_cmmnt() */\n\n\n\n\n\n/************************************/\n/* Function process_cdir_file_hdr() */\n/************************************/\n\nint process_cdir_file_hdr(__G)    /* return PK-type error code */\n    __GDEF\n{\n    int error;\n\n\n/*---------------------------------------------------------------------------\n    Get central directory info, save host and method numbers, and set flag\n    for lowercase conversion of filename, depending on the OS from which the\n    file is coming.\n  ---------------------------------------------------------------------------*/\n\n    if ((error = get_cdir_ent(__G)) != 0)\n        return error;\n\n    G.pInfo->hostver = G.crec.version_made_by[0];\n    G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);\n/*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */\n\n    G.pInfo->lcflag = 0;\n    if (uO.L_flag == 1)       /* name conversion for monocase systems */\n        switch (G.pInfo->hostnum) {\n            case FS_FAT_:     /* PKZIP and zip -k store in uppercase */\n            case CPM_:        /* like MS-DOS, right? */\n            case VM_CMS_:     /* all caps? */\n            case MVS_:        /* all caps? */\n            case TANDEM_:\n            case TOPS20_:\n            case VMS_:        /* our Zip uses lowercase, but ASi's doesn't */\n        /*  case Z_SYSTEM_:   ? */\n        /*  case QDOS_:       ? */\n                G.pInfo->lcflag = 1;   /* convert filename to lowercase */\n                break;\n\n            default:     /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, ATARI_, */\n                break;   /*  FS_VFAT_, ATHEOS_, BEOS_ (Z_SYSTEM_), THEOS_: */\n                         /*  no conversion */\n        }\n    else if (uO.L_flag > 1)   /* let -LL force lower case for all names */\n        G.pInfo->lcflag = 1;\n\n    /* do Amigas (AMIGA_) also have volume labels? */\n    if (IS_VOLID(G.crec.external_file_attributes) &&\n        (G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||\n         G.pInfo->hostnum == FS_NTFS_ || G.pInfo->hostnum == ATARI_))\n    {\n        G.pInfo->vollabel = TRUE;\n        G.pInfo->lcflag = 0;        /* preserve case of volume labels */\n    } else\n        G.pInfo->vollabel = FALSE;\n\n    /* this flag is needed to detect archives made by \"PKZIP for Unix\" when\n       deciding which kind of codepage conversion has to be applied to\n       strings (see do_string() function in fileio.c) */\n    G.pInfo->HasUxAtt = (G.crec.external_file_attributes & 0xffff0000L) != 0L;\n\n#ifdef UNICODE_SUPPORT\n    /* remember the state of GPB11 (General Purpuse Bit 11) which indicates\n       that the standard path and comment are UTF-8. */\n    G.pInfo->GPFIsUTF8\n        = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11);\n#endif\n\n    return PK_COOL;\n\n} /* end function process_cdir_file_hdr() */\n\n\n\n\n\n/***************************/\n/* Function get_cdir_ent() */\n/***************************/\n\nstatic int get_cdir_ent(__G)    /* return PK-type error code */\n    __GDEF\n{\n    cdir_byte_hdr byterec;\n\n\n/*---------------------------------------------------------------------------\n    Read the next central directory entry and do any necessary machine-type\n    conversions (byte ordering, structure padding compensation--do so by\n    copying the data from the array into which it was read (byterec) to the\n    usable struct (crec)).\n  ---------------------------------------------------------------------------*/\n\n    if (readbuf(__G__ (char *)byterec, CREC_SIZE) == 0)\n        return PK_EOF;\n\n    G.crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];\n    G.crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];\n    G.crec.version_needed_to_extract[0] =\n      byterec[C_VERSION_NEEDED_TO_EXTRACT_0];\n    G.crec.version_needed_to_extract[1] =\n      byterec[C_VERSION_NEEDED_TO_EXTRACT_1];\n\n    G.crec.general_purpose_bit_flag =\n      makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);\n    G.crec.compression_method =\n      makeword(&byterec[C_COMPRESSION_METHOD]);\n    G.crec.last_mod_dos_datetime =\n      makelong(&byterec[C_LAST_MOD_DOS_DATETIME]);\n    G.crec.crc32 =\n      makelong(&byterec[C_CRC32]);\n    G.crec.csize =\n      makelong(&byterec[C_COMPRESSED_SIZE]);\n    G.crec.ucsize =\n      makelong(&byterec[C_UNCOMPRESSED_SIZE]);\n    G.crec.filename_length =\n      makeword(&byterec[C_FILENAME_LENGTH]);\n    G.crec.extra_field_length =\n      makeword(&byterec[C_EXTRA_FIELD_LENGTH]);\n    G.crec.file_comment_length =\n      makeword(&byterec[C_FILE_COMMENT_LENGTH]);\n    G.crec.disk_number_start =\n      makeword(&byterec[C_DISK_NUMBER_START]);\n    G.crec.internal_file_attributes =\n      makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);\n    G.crec.external_file_attributes =\n      makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */\n    G.crec.relative_offset_local_header =\n      makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);\n\n    return PK_COOL;\n\n} /* end function get_cdir_ent() */\n\n\n\n\n\n/*************************************/\n/* Function process_local_file_hdr() */\n/*************************************/\n\nint process_local_file_hdr(__G)    /* return PK-type error code */\n    __GDEF\n{\n    local_byte_hdr byterec;\n\n\n/*---------------------------------------------------------------------------\n    Read the next local file header and do any necessary machine-type con-\n    versions (byte ordering, structure padding compensation--do so by copy-\n    ing the data from the array into which it was read (byterec) to the\n    usable struct (lrec)).\n  ---------------------------------------------------------------------------*/\n\n    if (readbuf(__G__ (char *)byterec, LREC_SIZE) == 0)\n        return PK_EOF;\n\n    G.lrec.version_needed_to_extract[0] =\n      byterec[L_VERSION_NEEDED_TO_EXTRACT_0];\n    G.lrec.version_needed_to_extract[1] =\n      byterec[L_VERSION_NEEDED_TO_EXTRACT_1];\n\n    G.lrec.general_purpose_bit_flag =\n      makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);\n    G.lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);\n    G.lrec.last_mod_dos_datetime = makelong(&byterec[L_LAST_MOD_DOS_DATETIME]);\n    G.lrec.crc32 = makelong(&byterec[L_CRC32]);\n    G.lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);\n    G.lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);\n    G.lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);\n    G.lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);\n\n    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {\n        /* can't trust local header, use central directory: */\n        G.lrec.crc32 = G.pInfo->crc;\n        G.lrec.csize = G.pInfo->compr_size;\n        G.lrec.ucsize = G.pInfo->uncompr_size;\n    }\n\n    G.csize = G.lrec.csize;\n\n    return PK_COOL;\n\n} /* end function process_local_file_hdr() */\n\n\n/*******************************/\n/* Function getZip64Data() */\n/*******************************/\n\nint getZip64Data(__G__ ef_buf, ef_len)\n    __GDEF\n    ZCONST uch *ef_buf; /* buffer containing extra field */\n    unsigned ef_len;    /* total length of extra field */\n{\n    unsigned eb_id;\n    unsigned eb_len;\n\n/*---------------------------------------------------------------------------\n    This function scans the extra field for zip64 information, ie 8-byte\n    versions of compressed file size, uncompressed file size, relative offset\n    and a 4-byte version of disk start number.\n    Sets both local header and central header fields.  Not terribly clever,\n    but it means that this procedure is only called in one place.\n  ---------------------------------------------------------------------------*/\n\n    if (ef_len == 0 || ef_buf == NULL)\n        return PK_COOL;\n\n    Trace((stderr,\"\\ngetZip64Data: scanning extra field of length %u\\n\",\n      ef_len));\n\n    while (ef_len >= EB_HEADSIZE) {\n        eb_id = makeword(EB_ID + ef_buf);\n        eb_len = makeword(EB_LEN + ef_buf);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"getZip64Data: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n        if (eb_id == EF_PKSZ64) {\n\n          int offset = EB_HEADSIZE;\n\n          if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){\n            G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);\n            offset += sizeof(G.crec.ucsize);\n          }\n          if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){\n            G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);\n            offset += sizeof(G.crec.csize);\n          }\n          if (G.crec.relative_offset_local_header == 0xffffffff){\n            G.crec.relative_offset_local_header = makeint64(offset + ef_buf);\n            offset += sizeof(G.crec.relative_offset_local_header);\n          }\n          if (G.crec.disk_number_start == 0xffff){\n            G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);\n            offset += sizeof(G.crec.disk_number_start);\n          }\n        }\n\n        /* Skip this extra field block */\n        ef_buf += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return PK_COOL;\n} /* end function getZip64Data() */\n\n\n#ifdef UNICODE_SUPPORT\n\n/*******************************/\n/* Function getUnicodeData() */\n/*******************************/\n\nint getUnicodeData(__G__ ef_buf, ef_len)\n    __GDEF\n    ZCONST uch *ef_buf; /* buffer containing extra field */\n    unsigned ef_len;    /* total length of extra field */\n{\n    unsigned eb_id;\n    unsigned eb_len;\n\n/*---------------------------------------------------------------------------\n    This function scans the extra field for Unicode information, ie UTF-8\n    path extra fields.\n\n    On return, G.unipath_filename =\n        NULL, if no Unicode path extra field or error\n        \"\", if the standard path is UTF-8 (free when done)\n        null-terminated UTF-8 path (free when done)\n    Return PK_COOL if no error.\n  ---------------------------------------------------------------------------*/\n\n    G.unipath_filename = NULL;\n\n    if (ef_len == 0 || ef_buf == NULL)\n        return PK_COOL;\n\n    Trace((stderr,\"\\ngetUnicodeData: scanning extra field of length %u\\n\",\n      ef_len));\n\n    while (ef_len >= EB_HEADSIZE) {\n        eb_id = makeword(EB_ID + ef_buf);\n        eb_len = makeword(EB_LEN + ef_buf);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"getUnicodeData: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n        if (eb_id == EF_UNIPATH) {\n\n          int offset = EB_HEADSIZE;\n          ush ULen = eb_len - 5;\n          ulg chksum = CRCVAL_INITIAL;\n\n          /* version */\n          G.unipath_version = (uch) *(offset + ef_buf);\n          offset += 1;\n          if (G.unipath_version > 1) {\n            /* can do only version 1 */\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(UnicodeVersionError)));\n            return PK_ERR;\n          }\n\n          /* filename CRC */\n          G.unipath_checksum = makelong(offset + ef_buf);\n          offset += 4;\n\n          /*\n           * Compute 32-bit crc\n           */\n\n          chksum = crc32(chksum, (uch *)(G.filename_full),\n                         strlen(G.filename_full));\n\n          /* If the checksums's don't match then likely filename has been\n           * modified and the Unicode Path is no longer valid.\n           */\n          if (chksum != G.unipath_checksum) {\n            Info(slide, 0x401, ((char *)slide,\n              LoadFarString(UnicodeMismatchError)));\n            if (G.unicode_mismatch == 1) {\n              /* warn and continue */\n            } else if (G.unicode_mismatch == 2) {\n              /* ignore and continue */\n            } else if (G.unicode_mismatch == 0) {\n            }\n            return PK_ERR;\n          }\n\n          /* UTF-8 Path */\n          if ((G.unipath_filename = malloc(ULen + 1)) == NULL) {\n            return PK_ERR;\n          }\n          if (ULen == 0) {\n            /* standard path is UTF-8 so use that */\n            G.unipath_filename[0] = '\\0';\n          } else {\n            /* UTF-8 path */\n            strncpy(G.unipath_filename,\n                    (ZCONST char *)(offset + ef_buf), ULen);\n            G.unipath_filename[ULen] = '\\0';\n          }\n        }\n\n        /* Skip this extra field block */\n        ef_buf += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return PK_COOL;\n} /* end function getUnicodeData() */\n\n\n\n\n#ifdef UNICODE_WCHAR\n  /*---------------------------------------------\n * Unicode conversion functions\n *\n * Based on functions provided by Paul Kienitz\n *\n *---------------------------------------------\n */\n\n/*\n   NOTES APPLICABLE TO ALL STRING FUNCTIONS:\n\n   All of the x_to_y functions take parameters for an output buffer and\n   its available length, and return an int.  The value returned is the\n   length of the string that the input produces, which may be larger than\n   the provided buffer length.  If the returned value is less than the\n   buffer length, then the contents of the buffer will be null-terminated;\n   otherwise, it will not be terminated and may be invalid, possibly\n   stopping in the middle of a multibyte sequence.\n\n   In all cases you may pass NULL as the buffer and/or 0 as the length, if\n   you just want to learn how much space the string is going to require.\n\n   The functions will return -1 if the input is invalid UTF-8 or cannot be\n   encoded as UTF-8.\n*/\n\nstatic int utf8_char_bytes OF((ZCONST char *utf8));\nstatic ulg ucs4_char_from_utf8 OF((ZCONST char **utf8));\nstatic int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *ucs4buf,\n                                   int buflen));\n\n/* utility functions for managing UTF-8 and UCS-4 strings */\n\n\n/* utf8_char_bytes\n *\n * Returns the number of bytes used by the first character in a UTF-8\n * string, or -1 if the UTF-8 is invalid or null.\n */\nstatic int utf8_char_bytes(utf8)\n  ZCONST char *utf8;\n{\n  int      t, r;\n  unsigned lead;\n\n  if (!utf8)\n    return -1;          /* no input */\n  lead = (unsigned char) *utf8;\n  if (lead < 0x80)\n    r = 1;              /* an ascii-7 character */\n  else if (lead < 0xC0)\n    return -1;          /* error: trailing byte without lead byte */\n  else if (lead < 0xE0)\n    r = 2;              /* an 11 bit character */\n  else if (lead < 0xF0)\n    r = 3;              /* a 16 bit character */\n  else if (lead < 0xF8)\n    r = 4;              /* a 21 bit character (the most currently used) */\n  else if (lead < 0xFC)\n    r = 5;              /* a 26 bit character (shouldn't happen) */\n  else if (lead < 0xFE)\n    r = 6;              /* a 31 bit character (shouldn't happen) */\n  else\n    return -1;          /* error: invalid lead byte */\n  for (t = 1; t < r; t++)\n    if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0)\n      return -1;        /* error: not enough valid trailing bytes */\n  return r;\n}\n\n\n/* ucs4_char_from_utf8\n *\n * Given a reference to a pointer into a UTF-8 string, returns the next\n * UCS-4 character and advances the pointer to the next character sequence.\n * Returns ~0 (= -1 in twos-complement notation) and does not advance the\n * pointer when input is ill-formed.\n */\nstatic ulg ucs4_char_from_utf8(utf8)\n  ZCONST char **utf8;\n{\n  ulg  ret;\n  int  t, bytes;\n\n  if (!utf8)\n    return ~0L;                         /* no input */\n  bytes = utf8_char_bytes(*utf8);\n  if (bytes <= 0)\n    return ~0L;                         /* invalid input */\n  if (bytes == 1)\n    ret = **utf8;                       /* ascii-7 */\n  else\n    ret = **utf8 & (0x7F >> bytes);     /* lead byte of a multibyte sequence */\n  (*utf8)++;\n  for (t = 1; t < bytes; t++)           /* consume trailing bytes */\n    ret = (ret << 6) | (*((*utf8)++) & 0x3F);\n  return (zwchar) ret;\n}\n\n\n#if 0 /* currently unused */\n/* utf8_from_ucs4_char - Convert UCS char to UTF-8\n *\n * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6,\n * or -1 if ch is too large to represent.  utf8buf must have room for 6 bytes.\n */\nstatic int utf8_from_ucs4_char(utf8buf, ch)\n  char *utf8buf;\n  ulg ch;\n{\n  int trailing = 0;\n  int leadmask = 0x80;\n  int leadbits = 0x3F;\n  int tch = ch;\n  int ret;\n\n  if (ch > 0x7FFFFFFFL)\n    return -1;                /* UTF-8 can represent 31 bits */\n  if (ch < 0x7F)\n  {\n    *utf8buf++ = (char) ch;   /* ascii-7 */\n    return 1;\n  }\n  do {\n    trailing++;\n    leadmask = (leadmask >> 1) | 0x80;\n    leadbits >>= 1;\n    tch >>= 6;\n  } while (tch & ~leadbits);\n  ret = trailing + 1;\n  /* produce lead byte */\n  *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing)));\n  while (--trailing >= 0)\n    /* produce trailing bytes */\n    *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F));\n  return ret;\n}\n#endif /* unused */\n\n\n/*===================================================================*/\n\n/* utf8_to_ucs4_string - convert UTF-8 string to UCS string\n *\n * Return UCS count.  Now returns int so can return -1.\n */\nstatic int utf8_to_ucs4_string(utf8, ucs4buf, buflen)\n  ZCONST char *utf8;\n  ulg *ucs4buf;\n  int buflen;\n{\n  int count = 0;\n\n  for (;;)\n  {\n    ulg ch = ucs4_char_from_utf8(&utf8);\n    if (ch == ~0L)\n      return -1;\n    else\n    {\n      if (ucs4buf && count < buflen)\n        ucs4buf[count] = ch;\n      if (ch == 0)\n        return count;\n      count++;\n    }\n  }\n}\n\n\n#if 0 /* currently unused */\n/* ucs4_string_to_utf8\n *\n *\n */\nstatic int ucs4_string_to_utf8(ucs4, utf8buf, buflen)\n  ZCONST ulg *ucs4;\n  char *utf8buf;\n  int buflen;\n{\n  char mb[6];\n  int  count = 0;\n\n  if (!ucs4)\n    return -1;\n  for (;;)\n  {\n    int mbl = utf8_from_ucs4_char(mb, *ucs4++);\n    int c;\n    if (mbl <= 0)\n      return -1;\n    /* We could optimize this a bit by passing utf8buf + count */\n    /* directly to utf8_from_ucs4_char when buflen >= count + 6... */\n    c = buflen - count;\n    if (mbl < c)\n      c = mbl;\n    if (utf8buf && count < buflen)\n      strncpy(utf8buf + count, mb, c);\n    if (mbl == 1 && !mb[0])\n      return count;           /* terminating nul */\n    count += mbl;\n  }\n}\n\n\n/* utf8_chars\n *\n * Wrapper: counts the actual unicode characters in a UTF-8 string.\n */\nstatic int utf8_chars(utf8)\n  ZCONST char *utf8;\n{\n  return utf8_to_ucs4_string(utf8, NULL, 0);\n}\n#endif /* unused */\n\n/* --------------------------------------------------- */\n/* Unicode Support\n *\n * These functions common for all Unicode ports.\n *\n * These functions should allocate and return strings that can be\n * freed with free().\n *\n * 8/27/05 EG\n *\n * Use zwchar for wide char which is unsigned long\n * in zip.h and 32 bits.  This avoids problems with\n * different sizes of wchar_t.\n */\n\n#if 0 /* currently unused */\n/* is_ascii_string\n * Checks if a string is all ascii\n */\nint is_ascii_string(mbstring)\n  ZCONST char *mbstring;\n{\n  char *p;\n  uch c;\n\n  for (p = mbstring; c = (uch)*p; p++) {\n    if (c > 0x7F) {\n      return 0;\n    }\n  }\n  return 1;\n}\n\n/* local to UTF-8 */\nchar *local_to_utf8_string(local_string)\n  ZCONST char *local_string;\n{\n  return wide_to_utf8_string(local_to_wide_string(local_string));\n}\n# endif /* unused */\n\n/* wide_to_escape_string\n   provides a string that represents a wide char not in local char set\n\n   An initial try at an algorithm.  Suggestions welcome.\n\n   According to the standard, Unicode character points are restricted to\n   the number range from 0 to 0x10FFFF, respective 21 bits.\n   For a hexadecimal notation, 2 octets are sufficient for the mostly\n   used characters from the \"Basic Multilingual Plane\", all other\n   Unicode characters can be represented by 3 octets (= 6 hex digits).\n   The Unicode standard suggests to write Unicode character points\n   as 4 resp. 6 hex digits, preprended by \"U+\".\n   (e.g.: U+10FFFF for the highest character point, or U+0030 for the ASCII\n   digit \"0\")\n\n   However, for the purpose of escaping non-ASCII chars in an ASCII character\n   stream, the \"U\" is not a very good escape initializer. Therefore, we\n   use the following convention within our Info-ZIP code:\n\n   If not an ASCII char probably need 2 bytes at least.  So if\n   a 2-byte wide encode it as 4 hex digits with a leading #U.  If\n   needs 3 bytes then prefix the string with #L.  So\n   #U1234\n   is a 2-byte wide character with bytes 0x12 and 0x34 while\n   #L123456\n   is a 3-byte wide character with bytes 0x12, 0x34, 0x56.\n   On Windows, wide that need two wide characters need to be converted\n   to a single number.\n  */\n\n /* set this to the max bytes an escape can be */\n#define MAX_ESCAPE_BYTES 8\n\nchar *wide_to_escape_string(wide_char)\n  zwchar wide_char;\n{\n  int i;\n  zwchar w = wide_char;\n  uch b[sizeof(zwchar)];\n  char d[3];\n  char e[11];\n  int len;\n  char *r;\n\n  /* fill byte array with zeros */\n  memzero(b, sizeof(zwchar));\n  /* get bytes in right to left order */\n  for (len = 0; w; len++) {\n    b[len] = (char)(w % 0x100);\n    w /= 0x100;\n  }\n  strcpy(e, \"#\");\n  /* either 2 bytes or 3 bytes */\n  if (len <= 2) {\n    len = 2;\n    strcat(e, \"U\");\n  } else {\n    strcat(e, \"L\");\n  }\n  for (i = len - 1; i >= 0; i--) {\n    sprintf(d, \"%02x\", b[i]);\n    strcat(e, d);\n  }\n  if ((r = malloc(strlen(e) + 1)) == NULL) {\n    return NULL;\n  }\n  strcpy(r, e);\n  return r;\n}\n\n#if 0 /* currently unused */\n/* returns the wide character represented by the escape string */\nzwchar escape_string_to_wide(escape_string)\n  ZCONST char *escape_string;\n{\n  int i;\n  zwchar w;\n  char c;\n  int len;\n  ZCONST char *e = escape_string;\n\n  if (e == NULL) {\n    return 0;\n  }\n  if (e[0] != '#') {\n    /* no leading # */\n    return 0;\n  }\n  len = strlen(e);\n  /* either #U1234 or #L123456 format */\n  if (len != 6 && len != 8) {\n    return 0;\n  }\n  w = 0;\n  if (e[1] == 'L') {\n    if (len != 8) {\n      return 0;\n    }\n    /* 3 bytes */\n    for (i = 2; i < 8; i++) {\n      c = e[i];\n      if (c < '0' || c > '9') {\n        return 0;\n      }\n      w = w * 0x10 + (zwchar)(c - '0');\n    }\n  } else if (e[1] == 'U') {\n    /* 2 bytes */\n    for (i = 2; i < 6; i++) {\n      c = e[i];\n      if (c < '0' || c > '9') {\n        return 0;\n      }\n      w = w * 0x10 + (zwchar)(c - '0');\n    }\n  }\n  return w;\n}\n#endif /* unused */\n\n#ifndef WIN32  /* WIN32 supplies a special variant of this function */\n/* convert wide character string to multi-byte character string */\nchar *wide_to_local_string(wide_string, escape_all)\n  ZCONST zwchar *wide_string;\n  int escape_all;\n{\n  int i;\n  wchar_t wc;\n  int b;\n  int state_dependent;\n  int wsize = 0;\n  int max_bytes = MB_CUR_MAX;\n  char buf[9];\n  char *buffer = NULL;\n  char *local_string = NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if (max_bytes < MAX_ESCAPE_BYTES)\n    max_bytes = MAX_ESCAPE_BYTES;\n\n  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {\n    return NULL;\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  /* set initial state if state-dependent encoding */\n  wc = (wchar_t)'a';\n  b = wctomb(NULL, wc);\n  if (b == 0)\n    state_dependent = 0;\n  else\n    state_dependent = 1;\n  for (i = 0; i < wsize; i++) {\n    if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {\n      /* wchar_t probably 2 bytes */\n      /* could do surrogates if state_dependent and wctomb can do */\n      wc = zwchar_to_wchar_t_default_char;\n    } else {\n      wc = (wchar_t)wide_string[i];\n    }\n    b = wctomb(buf, wc);\n    if (escape_all) {\n      if (b == 1 && (uch)buf[0] <= 0x7f) {\n        /* ASCII */\n        strncat(buffer, buf, b);\n      } else {\n        /* use escape for wide character */\n        char *escape_string = wide_to_escape_string(wide_string[i]);\n        strcat(buffer, escape_string);\n        free(escape_string);\n      }\n    } else if (b > 0) {\n      /* multi-byte char */\n      strncat(buffer, buf, b);\n    } else {\n      /* no MB for this wide */\n        /* use escape for wide character */\n        char *escape_string = wide_to_escape_string(wide_string[i]);\n        strcat(buffer, escape_string);\n        free(escape_string);\n    }\n  }\n  if ((local_string = (char *)malloc(strlen(buffer) + 1)) != NULL) {\n    strcpy(local_string, buffer);\n  }\n  free(buffer);\n\n  return local_string;\n}\n#endif /* !WIN32 */\n\n#if 0 /* currently unused */\n/* convert local string to display character set string */\nchar *local_to_display_string(local_string)\n  ZCONST char *local_string;\n{\n  char *display_string;\n\n  /* For Windows, OEM string should never be bigger than ANSI string, says\n     CharToOem description.\n     For all other ports, just make a copy of local_string.\n  */\n  if ((display_string = (char *)malloc(strlen(local_string) + 1)) == NULL) {\n    return NULL;\n  }\n\n  strcpy(display_string, local_string);\n\n#ifdef EBCDIC\n  {\n    char *ebc;\n\n    if ((ebc = malloc(strlen(display_string) + 1)) ==  NULL) {\n      return NULL;\n    }\n    strtoebc(ebc, display_string);\n    free(display_string);\n    display_string = ebc;\n  }\n#endif\n\n  return display_string;\n}\n#endif /* unused */\n\n/* UTF-8 to local */\nchar *utf8_to_local_string(utf8_string, escape_all)\n  ZCONST char *utf8_string;\n  int escape_all;\n{\n  zwchar *wide = utf8_to_wide_string(utf8_string);\n  char *loc = wide_to_local_string(wide, escape_all);\n  free(wide);\n  return loc;\n}\n\n#if 0 /* currently unused */\n/* convert multi-byte character string to wide character string */\nzwchar *local_to_wide_string(local_string)\n  ZCONST char *local_string;\n{\n  int wsize;\n  wchar_t *wc_string;\n  zwchar *wide_string;\n\n  /* for now try to convert as string - fails if a bad char in string */\n  wsize = mbstowcs(NULL, local_string, strlen(local_string) + 1);\n  if (wsize == (size_t)-1) {\n    /* could not convert */\n    return NULL;\n  }\n\n  /* convert it */\n  if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {\n    return NULL;\n  }\n  wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1);\n  wc_string[wsize] = (wchar_t) 0;\n\n  /* in case wchar_t is not zwchar */\n  if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) {\n    return NULL;\n  }\n  for (wsize = 0; wide_string[wsize] = (zwchar)wc_string[wsize]; wsize++) ;\n  wide_string[wsize] = (zwchar) 0;\n  free(wc_string);\n\n  return wide_string;\n}\n\n\n/* convert wide string to UTF-8 */\nchar *wide_to_utf8_string(wide_string)\n  ZCONST zwchar *wide_string;\n{\n  int mbcount;\n  char *utf8_string;\n\n  /* get size of utf8 string */\n  mbcount = ucs4_string_to_utf8(wide_string, NULL, 0);\n  if (mbcount == -1)\n    return NULL;\n  if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) {\n    return NULL;\n  }\n  mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1);\n  if (mbcount == -1)\n    return NULL;\n\n  return utf8_string;\n}\n#endif /* unused */\n\n/* convert UTF-8 string to wide string */\nzwchar *utf8_to_wide_string(utf8_string)\n  ZCONST char *utf8_string;\n{\n  int wcount;\n  zwchar *wide_string;\n\n  wcount = utf8_to_ucs4_string(utf8_string, NULL, 0);\n  if (wcount == -1)\n    return NULL;\n  if ((wide_string = (zwchar *) malloc((wcount + 1) * sizeof(zwchar)))\n      == NULL) {\n    return NULL;\n  }\n  wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1);\n\n  return wide_string;\n}\n\n#endif /* UNICODE_WCHAR */\n#endif /* UNICODE_SUPPORT */\n\n\n\n\n\n#ifdef USE_EF_UT_TIME\n\n#ifdef IZ_HAVE_UXUIDGID\nstatic int read_ux3_value(dbuf, uidgid_sz, p_uidgid)\n    ZCONST uch *dbuf;   /* buffer a uid or gid value */\n    unsigned uidgid_sz; /* size of uid/gid value */\n    ulg *p_uidgid;      /* return storage: uid or gid value */\n{\n    zusz_t uidgid64;\n\n    switch (uidgid_sz) {\n      case 2:\n        *p_uidgid = (ulg)makeword(dbuf);\n        break;\n      case 4:\n        *p_uidgid = (ulg)makelong(dbuf);\n        break;\n      case 8:\n        uidgid64 = makeint64(dbuf);\n#ifndef LARGE_FILE_SUPPORT\n        if (uidgid64 == (zusz_t)0xffffffffL)\n            return FALSE;\n#endif\n        *p_uidgid = (ulg)uidgid64;\n        if ((zusz_t)(*p_uidgid) != uidgid64)\n            return FALSE;\n        break;\n    }\n    return TRUE;\n}\n#endif /* IZ_HAVE_UXUIDGID */\n\n\n/*******************************/\n/* Function ef_scan_for_izux() */\n/*******************************/\n\nunsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos_mdatetime,\n                          z_utim, z_uidgid)\n    ZCONST uch *ef_buf; /* buffer containing extra field */\n    unsigned ef_len;    /* total length of extra field */\n    int ef_is_c;        /* flag indicating \"is central extra field\" */\n    ulg dos_mdatetime;  /* last_mod_file_date_time in DOS format */\n    iztimes *z_utim;    /* return storage: atime, mtime, ctime */\n    ulg *z_uidgid;      /* return storage: uid and gid */\n{\n    unsigned flags = 0;\n    unsigned eb_id;\n    unsigned eb_len;\n    int have_new_type_eb = 0;\n    long i_time;        /* buffer for Unix style 32-bit integer time value */\n#ifdef TIME_T_TYPE_DOUBLE\n    int ut_in_archive_sgn = 0;\n#else\n    int ut_zip_unzip_compatible = FALSE;\n#endif\n\n/*---------------------------------------------------------------------------\n    This function scans the extra field for EF_TIME, EF_IZUNIX2, EF_IZUNIX, or\n    EF_PKUNIX blocks containing Unix-style time_t (GMT) values for the entry's\n    access, creation, and modification time.\n    If a valid block is found, the time stamps are copied to the iztimes\n    structure (provided the z_utim pointer is not NULL).\n    If a IZUNIX2 block is found or the IZUNIX block contains UID/GID fields,\n    and the z_uidgid array pointer is valid (!= NULL), the owner info is\n    transfered as well.\n    The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring all\n    data from probably present obsolete EF_IZUNIX blocks.\n    If multiple blocks of the same type are found, only the information from\n    the last block is used.\n    The return value is a combination of the EF_TIME Flags field with an\n    additional flag bit indicating the presence of valid UID/GID info,\n    or 0 in case of failure.\n  ---------------------------------------------------------------------------*/\n\n    if (ef_len == 0 || ef_buf == NULL || (z_utim == 0 && z_uidgid == NULL))\n        return 0;\n\n    TTrace((stderr,\"\\nef_scan_for_izux: scanning extra field of length %u\\n\",\n      ef_len));\n\n    while (ef_len >= EB_HEADSIZE) {\n        eb_id = makeword(EB_ID + ef_buf);\n        eb_len = makeword(EB_LEN + ef_buf);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            TTrace((stderr,\n              \"ef_scan_for_izux: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        switch (eb_id) {\n          case EF_TIME:\n            flags &= ~0x0ff;    /* ignore previous IZUNIX or EF_TIME fields */\n            have_new_type_eb = 1;\n            if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {\n                unsigned eb_idx = EB_UT_TIME1;\n                TTrace((stderr,\"ef_scan_for_izux: found TIME extra field\\n\"));\n                flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x0ff);\n                if ((flags & EB_UT_FL_MTIME)) {\n                    if ((eb_idx+4) <= eb_len) {\n                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);\n                        eb_idx += 4;\n                        TTrace((stderr,\"  UT e.f. modification time = %ld\\n\",\n                                i_time));\n\n#ifdef TIME_T_TYPE_DOUBLE\n                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                            if (dos_mdatetime == DOSTIME_MINIMUM) {\n                              ut_in_archive_sgn = -1;\n                              z_utim->mtime =\n                                (time_t)((long)i_time | (~(long)0x7fffffffL));\n                            } else if (dos_mdatetime >= DOSTIME_2038_01_18) {\n                              ut_in_archive_sgn = 1;\n                              z_utim->mtime =\n                                (time_t)((ulg)i_time & (ulg)0xffffffffL);\n                            } else {\n                              ut_in_archive_sgn = 0;\n                              /* cannot determine sign of mtime;\n                                 without modtime: ignore complete UT field */\n                              flags &= ~0x0ff;  /* no time_t times available */\n                              TTrace((stderr,\n                                \"  UT modtime range error; ignore e.f.!\\n\"));\n                              break;            /* stop scanning this field */\n                            }\n                        } else {\n                            /* cannot determine, safe assumption is FALSE */\n                            ut_in_archive_sgn = 0;\n                            z_utim->mtime = (time_t)i_time;\n                        }\n#else /* !TIME_T_TYPE_DOUBLE */\n                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                            ut_zip_unzip_compatible =\n                              ((time_t)0x80000000L < (time_t)0L)\n                              ? (dos_mdatetime == DOSTIME_MINIMUM)\n                              : (dos_mdatetime >= DOSTIME_2038_01_18);\n                            if (!ut_zip_unzip_compatible) {\n                              /* UnZip interprets mtime differently than Zip;\n                                 without modtime: ignore complete UT field */\n                              flags &= ~0x0ff;  /* no time_t times available */\n                              TTrace((stderr,\n                                \"  UT modtime range error; ignore e.f.!\\n\"));\n                              break;            /* stop scanning this field */\n                            }\n                        } else {\n                            /* cannot determine, safe assumption is FALSE */\n                            ut_zip_unzip_compatible = FALSE;\n                        }\n                        z_utim->mtime = (time_t)i_time;\n#endif /* ?TIME_T_TYPE_DOUBLE */\n                    } else {\n                        flags &= ~EB_UT_FL_MTIME;\n                        TTrace((stderr,\"  UT e.f. truncated; no modtime\\n\"));\n                    }\n                }\n                if (ef_is_c) {\n                    break;      /* central version of TIME field ends here */\n                }\n\n                if (flags & EB_UT_FL_ATIME) {\n                    if ((eb_idx+4) <= eb_len) {\n                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);\n                        eb_idx += 4;\n                        TTrace((stderr,\"  UT e.f. access time = %ld\\n\",\n                                i_time));\n#ifdef TIME_T_TYPE_DOUBLE\n                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                            if (ut_in_archive_sgn == -1)\n                              z_utim->atime =\n                                (time_t)((long)i_time | (~(long)0x7fffffffL));\n                            } else if (ut_in_archive_sgn == 1) {\n                              z_utim->atime =\n                                (time_t)((ulg)i_time & (ulg)0xffffffffL);\n                            } else {\n                              /* sign of 32-bit time is unknown -> ignore it */\n                              flags &= ~EB_UT_FL_ATIME;\n                              TTrace((stderr,\n                                \"  UT access time range error: skip time!\\n\"));\n                            }\n                        } else {\n                            z_utim->atime = (time_t)i_time;\n                        }\n#else /* !TIME_T_TYPE_DOUBLE */\n                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&\n                            !ut_zip_unzip_compatible) {\n                            flags &= ~EB_UT_FL_ATIME;\n                            TTrace((stderr,\n                              \"  UT access time range error: skip time!\\n\"));\n                        } else {\n                            z_utim->atime = (time_t)i_time;\n                        }\n#endif /* ?TIME_T_TYPE_DOUBLE */\n                    } else {\n                        flags &= ~EB_UT_FL_ATIME;\n                    }\n                }\n                if (flags & EB_UT_FL_CTIME) {\n                    if ((eb_idx+4) <= eb_len) {\n                        i_time = (long)makelong((EB_HEADSIZE+eb_idx) + ef_buf);\n                        TTrace((stderr,\"  UT e.f. creation time = %ld\\n\",\n                                i_time));\n#ifdef TIME_T_TYPE_DOUBLE\n                        if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                            if (ut_in_archive_sgn == -1)\n                              z_utim->ctime =\n                                (time_t)((long)i_time | (~(long)0x7fffffffL));\n                            } else if (ut_in_archive_sgn == 1) {\n                              z_utim->ctime =\n                                (time_t)((ulg)i_time & (ulg)0xffffffffL);\n                            } else {\n                              /* sign of 32-bit time is unknown -> ignore it */\n                              flags &= ~EB_UT_FL_CTIME;\n                              TTrace((stderr,\n                              \"  UT creation time range error: skip time!\\n\"));\n                            }\n                        } else {\n                            z_utim->ctime = (time_t)i_time;\n                        }\n#else /* !TIME_T_TYPE_DOUBLE */\n                        if (((ulg)(i_time) & (ulg)(0x80000000L)) &&\n                            !ut_zip_unzip_compatible) {\n                            flags &= ~EB_UT_FL_CTIME;\n                            TTrace((stderr,\n                              \"  UT creation time range error: skip time!\\n\"));\n                        } else {\n                            z_utim->ctime = (time_t)i_time;\n                        }\n#endif /* ?TIME_T_TYPE_DOUBLE */\n                    } else {\n                        flags &= ~EB_UT_FL_CTIME;\n                    }\n                }\n            }\n            break;\n\n          case EF_IZUNIX2:\n            if (have_new_type_eb == 0) {\n                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */\n                have_new_type_eb = 1;\n            }\n#ifdef IZ_HAVE_UXUIDGID\n            if (have_new_type_eb > 1)\n                break;          /* IZUNIX3 overrides IZUNIX2 e.f. block ! */\n            if (eb_len == EB_UX2_MINLEN && z_uidgid != NULL) {\n                z_uidgid[0] = (ulg)makeword((EB_HEADSIZE+EB_UX2_UID) + ef_buf);\n                z_uidgid[1] = (ulg)makeword((EB_HEADSIZE+EB_UX2_GID) + ef_buf);\n                flags |= EB_UX2_VALID;   /* signal success */\n            }\n#endif\n            break;\n\n          case EF_IZUNIX3:\n            /* new 3rd generation Unix ef */\n            have_new_type_eb = 2;\n\n        /*\n          Version       1 byte      version of this extra field, currently 1\n          UIDSize       1 byte      Size of UID field\n          UID           Variable    UID for this entry\n          GIDSize       1 byte      Size of GID field\n          GID           Variable    GID for this entry\n        */\n\n#ifdef IZ_HAVE_UXUIDGID\n            if (eb_len >= EB_UX3_MINLEN\n                && z_uidgid != NULL\n                && (*((EB_HEADSIZE + 0) + ef_buf) == 1)\n                    /* only know about version 1 */\n            {\n                uch uid_size;\n                uch gid_size;\n\n                uid_size = *((EB_HEADSIZE + 1) + ef_buf);\n                gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);\n\n                flags &= ~0x0ff;      /* ignore any previous UNIX field */\n\n                if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,\n                                    uid_size, z_uidgid[0])\n                    &&\n                     read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf,\n                                    gid_size, z_uidgid[1]) )\n                {\n                    flags |= EB_UX2_VALID;   /* signal success */\n                }\n            }\n#endif /* IZ_HAVE_UXUIDGID */\n            break;\n\n          case EF_IZUNIX:\n          case EF_PKUNIX:       /* PKUNIX e.f. layout is identical to IZUNIX */\n            if (eb_len >= EB_UX_MINLEN) {\n                TTrace((stderr,\"ef_scan_for_izux: found %s extra field\\n\",\n                        (eb_id == EF_IZUNIX ? \"IZUNIX\" : \"PKUNIX\")));\n                if (have_new_type_eb > 0) {\n                    break;      /* Ignore IZUNIX extra field block ! */\n                }\n                if (z_utim != NULL) {\n                    flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_MTIME)+ef_buf);\n                    TTrace((stderr,\"  Unix EF modtime = %ld\\n\", i_time));\n#ifdef TIME_T_TYPE_DOUBLE\n                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                        if (dos_mdatetime == DOSTIME_MINIMUM) {\n                            ut_in_archive_sgn = -1;\n                            z_utim->mtime =\n                              (time_t)((long)i_time | (~(long)0x7fffffffL));\n                        } else if (dos_mdatetime >= DOSTIME_2038_01_18) {\n                            ut_in_archive_sgn = 1;\n                            z_utim->mtime =\n                              (time_t)((ulg)i_time & (ulg)0xffffffffL);\n                        } else {\n                            ut_in_archive_sgn = 0;\n                            /* cannot determine sign of mtime;\n                               without modtime: ignore complete UT field */\n                            flags &= ~0x0ff;    /* no time_t times available */\n                            TTrace((stderr,\n                                  \"  UX modtime range error: ignore e.f.!\\n\"));\n                        }\n                    } else {\n                        /* cannot determine, safe assumption is FALSE */\n                        ut_in_archive_sgn = 0;\n                        z_utim->mtime = (time_t)i_time;\n                    }\n#else /* !TIME_T_TYPE_DOUBLE */\n                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                        ut_zip_unzip_compatible =\n                          ((time_t)0x80000000L < (time_t)0L)\n                          ? (dos_mdatetime == DOSTIME_MINIMUM)\n                          : (dos_mdatetime >= DOSTIME_2038_01_18);\n                        if (!ut_zip_unzip_compatible) {\n                            /* UnZip interpretes mtime differently than Zip;\n                               without modtime: ignore complete UT field */\n                            flags &= ~0x0ff;    /* no time_t times available */\n                            TTrace((stderr,\n                                  \"  UX modtime range error: ignore e.f.!\\n\"));\n                        }\n                    } else {\n                        /* cannot determine, safe assumption is FALSE */\n                        ut_zip_unzip_compatible = FALSE;\n                    }\n                    z_utim->mtime = (time_t)i_time;\n#endif /* ?TIME_T_TYPE_DOUBLE */\n                    i_time = (long)makelong((EB_HEADSIZE+EB_UX_ATIME)+ef_buf);\n                    TTrace((stderr,\"  Unix EF actime = %ld\\n\", i_time));\n#ifdef TIME_T_TYPE_DOUBLE\n                    if ((ulg)(i_time) & (ulg)(0x80000000L)) {\n                        if (ut_in_archive_sgn == -1)\n                            z_utim->atime =\n                              (time_t)((long)i_time | (~(long)0x7fffffffL));\n                        } else if (ut_in_archive_sgn == 1) {\n                            z_utim->atime =\n                              (time_t)((ulg)i_time & (ulg)0xffffffffL);\n                        } else if (flags & 0x0ff) {\n                            /* sign of 32-bit time is unknown -> ignore it */\n                            flags &= ~EB_UT_FL_ATIME;\n                            TTrace((stderr,\n                                \"  UX access time range error: skip time!\\n\"));\n                        }\n                    } else {\n                        z_utim->atime = (time_t)i_time;\n                    }\n#else /* !TIME_T_TYPE_DOUBLE */\n                    if (((ulg)(i_time) & (ulg)(0x80000000L)) &&\n                        !ut_zip_unzip_compatible && (flags & 0x0ff)) {\n                        /* atime not in range of UnZip's time_t */\n                        flags &= ~EB_UT_FL_ATIME;\n                        TTrace((stderr,\n                                \"  UX access time range error: skip time!\\n\"));\n                    } else {\n                        z_utim->atime = (time_t)i_time;\n                    }\n#endif /* ?TIME_T_TYPE_DOUBLE */\n                }\n#ifdef IZ_HAVE_UXUIDGID\n                if (eb_len >= EB_UX_FULLSIZE && z_uidgid != NULL) {\n                    z_uidgid[0] = makeword((EB_HEADSIZE+EB_UX_UID) + ef_buf);\n                    z_uidgid[1] = makeword((EB_HEADSIZE+EB_UX_GID) + ef_buf);\n                    flags |= EB_UX2_VALID;\n                }\n#endif /* IZ_HAVE_UXUIDGID */\n            }\n            break;\n\n          default:\n            break;\n        }\n\n        /* Skip this extra field block */\n        ef_buf += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return flags;\n}\n\n#endif /* USE_EF_UT_TIME */\n\n\n#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n\n#define SPARKID_2 0x30435241    /* = \"ARC0\" */\n\n/*******************************/\n/* Function getRISCOSexfield() */\n/*******************************/\n\nzvoid *getRISCOSexfield(ef_buf, ef_len)\n    ZCONST uch *ef_buf; /* buffer containing extra field */\n    unsigned ef_len;    /* total length of extra field */\n{\n    unsigned eb_id;\n    unsigned eb_len;\n\n/*---------------------------------------------------------------------------\n    This function scans the extra field for a Acorn SPARK filetype ef-block.\n    If a valid block is found, the function returns a pointer to the start\n    of the SPARK_EF block in the extra field buffer.  Otherwise, a NULL\n    pointer is returned.\n  ---------------------------------------------------------------------------*/\n\n    if (ef_len == 0 || ef_buf == NULL)\n        return NULL;\n\n    Trace((stderr,\"\\ngetRISCOSexfield: scanning extra field of length %u\\n\",\n      ef_len));\n\n    while (ef_len >= EB_HEADSIZE) {\n        eb_id = makeword(EB_ID + ef_buf);\n        eb_len = makeword(EB_LEN + ef_buf);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"getRISCOSexfield: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        if (eb_id == EF_SPARK && (eb_len == 24 || eb_len == 20)) {\n            if (makelong(EB_HEADSIZE + ef_buf) == SPARKID_2) {\n                /* Return a pointer to the valid SPARK filetype ef block */\n                return (zvoid *)ef_buf;\n            }\n        }\n\n        /* Skip this extra field block */\n        ef_buf += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return NULL;\n}\n\n#endif /* (RISCOS || ACORN_FTYPE_NFS) */\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/3rdparty.bug",
    "content": "Known, current PKZIP bugs/limitations:\n-------------------------------------\n\n - PKUNZIP 2.04g is reported to corrupt some files when compressing them with\n   the -ex option; when tested, the files fail the CRC check, and comparison\n   with the original file shows bogus data (6K in one case) embedded in the\n   middle.  PKWARE apparently characterized this as a \"known problem.\"\n\n - PKUNZIP 2.04g considers volume labels valid only if originated on a FAT\n   file system, but other OSes and file systems (e.g., Amiga and OS/2 HPFS)\n   support volume labels, too.\n\n - PKUNZIP 2.04g can restore volume labels created by Zip 2.x but not by\n   PKZIP 2.04g (OS/2 DOS box only??).\n\n - PKUNZIP 2.04g gives an error message for stored directory entries created\n   under other OSes (although it creates the directory anyway), and PKZIP -vt\n   does not report the directory attribute bit as being set, even if it is.\n\n - PKZIP 2.04g mangles unknown extra fields (especially OS/2 extended attri-\n   butes) when adding new files to an existing zipfile [example:  Walnut Creek\n   Hobbes March 1995 CD-ROM, FILE_ID.DIZ additions].\n\n - PKUNZIP 2.04g is unable to detect or deal with prepended junk in a zipfile,\n   reporting CRC errors in valid compressed data.\n\n - PKUNZIP 2.04g (registered version) incorrectly updates/freshens the AV extra\n   field in authenticated archives.  The resultant extra block length and total\n   extra field length are inconsistent.\n\n - [Windows version 2.01] Win95 long filenames (VFAT) are stored OK, but the\n   file system is always listed as ordinary DOS FAT.\n\n - [Windows version 2.50] NT long filenames (NTFS) are stored OK, but the\n   file system is always listed as ordinary DOS FAT.\n\n - PKZIP 2.04 for DOS encrypts using the OEM code page for 8-bit passwords,\n   while PKZIP 2.50 for Windows uses Latin-1 (ISO 8859-1).  This means an\n   archive encrypted with an 8-bit password with one of the two PKZIP versions\n   cannot be decrypted with the other version.\n\n - PKZIP for Windows GUI (v 2.60), PKZIP for Windows command line (v 2.50) and\n   PKZIP for Unix (v 2.51) save the host's native file timestamps, but\n   only in a local extra field. Thus, timestamp-related selections (update\n   or freshen, both in extraction or archiving operations) use the DOS-format\n   localtime records in the Zip archives for comparisons. This may result\n   in wrong decisions of the program when updating archives that were\n   previously created in a different local time zone.\n\n - PKZIP releases newer than PKZIP for DOS 2.04g (PKZIP for Windows, both\n   GUI v 2.60 and console v 2.50; PKZIP for Unix v 2.51; probably others too)\n   use different code pages for storing filenames in central (OEM Codepage)\n   and local (ANSI / ISO 8859-1 Codepage) headers. When a stored filename\n   contains extended-ASCII characters, the local and central filename fields\n   do not match. As a consequence, Info-ZIP's Zip program considers such\n   archives as being corrupt and does not allow to modify them. Beginning\n   with release 5.41, Info-ZIP's UnZip contains a workaround to list AND\n   extract such archives with the correct filenames.\n   Maybe PKWARE has implemented this \"feature\" to allow extraction of their\n   \"made-by-PKZIP for Unix/Windows\" archives using old (v5.2 and earlier)\n   versions of Info-ZIP's UnZip for Unix/WinNT ??? (UnZip versions before\n   v 5.3 assumed that all archive entries were encoded in the codepage of\n   the UnZip program's host system.)\n\n - PKUNZIP 2.04g is reported to have problems with archives created on and/or\n   copied from Iomega ZIP drives (irony, eh?).\n\nKnown, current WinZip bugs/limitations:\n--------------------------------------\n\n - [16-bit version 6.1a] NT short filenames (FAT) are stored OK, but the\n   file system is always listed as NTFS.\n\n - WinZip doesn't allow 8-bit passwords, which means it cannot decrypt an\n   archive created with an 8-bit password (by PKZIP or Info-ZIP's Zip).\n\n - WinZip (at least Versions 6.3 PL1, 7.0 SR1) fails to remove old extra\n   fields when freshening existing archive entries. When updating archives\n   created by Info-ZIP's Zip that contain UT time stamp extra field blocks,\n   UnZip cannot display or restore the updated (DOS) time stamps of the\n   freshened archive members.\n\nKnown, current other third-party Zip utils bugs/limitations:\n------------------------------------------------------------\n\n - Asi's PKZip clones for Macintosh (versions 2.3 and 2.10d) are thoroughly\n   broken. They create invalid Zip archives!\n   a) For the first entry, both compressed size and uncompressed length\n      are recorded as 0, despite the fact that compressed data of non-zero\n      length has been added.\n   b) Their program creates extra fields with an (undocumented) internal\n      structure that violates the requirements of PKWARE's Zip format\n      specification document \"appnote.txt\": Their extra field seems to\n      contain pure data; the 4-byte block header consisting of block ID\n      and data length is missing.\n\nPossibly current PKZIP bugs:\n---------------------------\n\n - PKZIP (2.04g?) can silently ignore read errors on network drives, storing\n   the correct CRC and compressed length but an incorrect and inconsistent\n   uncompressed length.\n\n - PKZIP (2.04g?), when deleting files from within a zipfile on a Novell\n   drive, sometimes only zeros out the data while failing to shrink the\n   zipfile.\n\nOther limitations:\n-----------------\n\n - PKZIP 1.x and 2.x encryption has been cracked (known-plaintext approach;\n   see http://www.cryptography.com/ for details).\n\n[many other bugs in PKZIP 1.0, 1.1, 1.93a, 2.04c and 2.04e]\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/CONTRIBS",
    "content": "This is a partial list of contributors to Info-ZIP's UnZip and the code upon\nwhich it is based.  Others have also contributed, and if you are among them,\nplease let us know (don't be shy!).  Everyone who contributed via the Info-\nZIP digest *should* now be listed here, but oversights are entirely possible.\n\n  Mark Adler             decryption, inflate, explode, funzip code; misc. casts\n  Steve Alpert           VMS rms.h bugfix\n  Jeffrey Altman         inflate.c huft_build() bugfix\n  Glenn Andrews          MS-DOS makefiles; prototyping bugfix; bogus main() fix\n  Andrei Arkhipov        Solaris 2.x package files\n  Joel Aycock            descrip.mms bugfix\n  Vance Baarda           Novell Netware 4.x NLM port\n  Eric Baatz             Borland version() info; Solaris zipgrep packaging fix\n  Bob Babcock            DOS volume-label code (FCBs)\n  Charles Bailey         VMS_SEVERITY fix; VMSWILD () extension\n  Audrey Beck            \"WHERE\" file info for AOL OS/2 forum\n  Myles Bennet           Initial start of Zip64 and Large-File handling\n  Mike Bernardi          Unix makefile entry; CIX uploads\n  James Birdsall         extract.c/makefile/NT stuff, etc.; awesome beta tester\n  Allan Bjorklund        in misc.c\n  Denise Blakeley        Unix makefile entry\n  Wim Bonner             original OS/2 port; Unix makefile entry\n  Paul Borman            BSD/386 (BSDI) fixes; Unix makefile entry\n  Carlton Brewster       mapname bugfix\n  Marcus Brinkmann       Unix configuration fix for GNU/Hurd\n  Rodney Brown           stdin-/dev/null bugfix; VMS error levels; CRC optimiz.\n  Stan Brown             \"zipinfo -M\"/isatty(1) bugfix\n  Jens von Buelow        port to MPE/iX, a Unix variant running on HP 3000\n  John Bush              first full Amiga port; FileDate; Amiga fixes; etc.\n  Christian Carey        Unix makefile bugfix for install target (create dirs)\n  Valter Cavecchia       Unix makefile entry\n  Rudolf Cejka           Unix UID/GID extraction bugfix\n  Peter Chang            optional UNIXBACKUP option (-B)\n  Kevin Cheng            windll MBCS fix (setlocale initialization)\n  Andrey Chernov         BSD 4.4 utime fix\n  Brad Clarke            Win32 XX_flag bugfix; Borland debug code removal\n  Mark Clayton           LynxOS (unix/Makefile update)\n  John Cowan             mods to original match.c; other stuff?\n  Frank da Cruz          xxu.c, on which original mapname.c was based\n  Bill Davidsen          -q(q); mapname stuff; envargs; Xenix stuff; opts; etc.\n  Karl Davis             Acorn RISC OS port\n  Jim Delahanty          NTSD fixes\n  Harald Denker          major Atari update/fixes\n  Matt \"Doc\" D'Errico    AIX stuff, Unix makefile entry\n  Kim DeVaughn           Unix makefile entry\n  Arjan de Vet           various things, but I don't remember exactly what...\n  Frank Donahoe          djgpp v2.x makefile; documentation updates\n  Jean-Michel Dubois     THEOS port\n  James Dugal            ZMEM stuff; unshrink bugfix; file perms stuff; etc.\n  Jim Dumser             -z stuff; umask, opendir/Borland, UID fixes; etc.\n  Peter Eckel            DOS buffer-overrun fix\n  Mark Edwards           mapname.c, misc.c fixes; Unix makefile entry\n  Paul Eggert            man pages update for POSIX compatibility\n  Gershon Elber          Unix makefile entry\n  Patrick Ellis          VMS usage fix (`-' vs. `/' options)\n  Shane Erstad           Borland makefile bugfix\n  Thomas Esken           Acorn typo fix\n  Bruce Evans            Unix makefile entry\n  Derek Fawcus           FlexOS port\n  David Feinleib         Windows NT port\n  David Fenyes           Unix makefile entry\n  Scott Field            Windows NT security-descriptor support; CRC opts\n  Greg Flint             Unix makefile entry\n  Carl Forde             VM/CMS port debugging (with Christian Spieler)\n  Craig Forbes           \"UnZipToMem with no ucsize in local header\" bugfix\n  Joe Foster             Unix makefile bugfix\n  Gordon Fox             Unix makefile bugfix for apollo target\n  Jeffrey Foy            OS/2 stuff(?); [CP/M]\n  Mike Freeman           VMS gcc makefiles; VMS bugfixes; etc.\n  Kevin Fritz            Borland bugfixes; MS-DOS makefile fixes; etc.\n  Aaron Gaalswyk         OS/2 checkdir() fix\n  Jean-loup Gailly       decryption code; ReadByte replacement; much nagging :-)\n  Forrest Gehrke         Unix makefile entry\n  Tim Geibelhaus         Unix makefile entry\n  Henry Gessau           flush/Fwrite/outcnt fixes; new NT port\n  Christian Ghisler      inflate tweaks\n  Filip Gieszczykiewicz  Unix makefile entry\n  Paul Gilmartin         work-around for systems with broken catman/makewhatis\n  Hunter Goatley         VMSCLI interface; VMS help/RUNOFF; list maintainer\n  Ian E. Gorman          VM/CMS & MVS support\n  Bill Gould             MVS file-format fixes\n  Michael Graff          Unix makefile entry\n  Juan Manuel Guerrero   DOS/WIN32 filename mapping fixes, device name handling\n  Giuseppe Guerrini      LynxOS variant of Unix port\n  Richard H. Gumpertz    Unix makefile entry\n  Walter Haidinger       Amiga SAS/C fixes\n  Steve Hanna            Macintosh stuff\n  Mark Hanning-Lee       docs corrections, Unix Makefile fixes, \"check\" target\n  Guy Harris             ZipInfo man-page typo fix\n  Greg Hartwig           finished VM/CMS port\n  Robert Heath           Windows GUI port (WizUnZip)\n  Dave Heiland           new usage screen\n  Ron Henderson          -a bugfix\n  Chris Herborth         new Atari port; Atari fixes\n  Greg Hill              docs update\n  Lon Hohberger          security fix; security advice in man-page\n  John Hollow            \"WHERE\" file path corrections\n  Jason Hood             DOS screen-width support\n  Phil Howard            Unix makefile entry\n  Jonathan Hudson        SMS/QDOS port\n  Joe Isuzu              Unix makefile entry\n  Kimio Itoh             ZipInfo DIR_END bugfix for MSVC 4.0\n  Aubrey Jaffer          pixel, v7 targets\n  \"jelmer\"               directory traversal security fix\n  Graham Jenkins         Sequent Dynix/ptx bugfix\n  Peter Jones            Unix makefile entry\n  Larry Jones            ZMEM stuff; unimplod fix; crc_i386.S improvements; etc.\n  Warren Jones           MKS bugfix\n  Kjetil J{\\o}rgenson    Makefile, OSF/1, NetBSD fixes; djgpp v2 mods; USE_VFAT\n  Bruce Kahn             DOS floppy detection?; Unix makefile entry\n  Bob Kemp               NOTINT16 rewrite; Unix makefile entry\n  J. Kercheval           filmatch.c, on which second match.c was based\n  Paul Kienitz           continuing general Amiga porting; Aztec C support; ASM\n  Raymond L. King        WINDLL VB example maintenance\n  Mike Kincer            AIX \"ps2\" bugfix\n  David Kirschbaum       mapname port; general-purpose meddling; Python jokes\n  Paul Klahr             Regulus port\n  Jim Knoble             Turbo C++ makefile fix\n  Alvin Koh              Borland C++ bugfixes\n  D. Krumbholz           Acorn filetime conversion bug\n  Karel Kubat            Linux strncasecmp bugfix\n  Bo Kullmar             -z code; umask, do_string, BSD time, echo fixes; etc.\n  Peter Kunath           DLL bugfixes, MSVC __asm support\n  Russell Lang           OS/2 DLL calling-convention bugfix\n  Michael Lawler         Borland version() info; process.c string fix; DOS fixes\n  Rudolf Lechleitner     inflate memory leak fix\n  Johnny Lee             Macintosh port; Win3.1 port; far strings; fixes; etc.\n  Alexander Lehmann      makefile.tc bugfix; MS-DOS mapname() bugfix\n  Marty Leisner          Unix perms fix for non-Unix dirs; man pages fonts; etc.\n  Fred Lenk              docs e-mail bugfix\n  Daniel Lewart          AIX stuff; compiler warnings\n  Jim Lill               SCO Unix SYSNDIR bugfix\n  John Limpert           Unix makefile entry\n  Hogan Long             Borland preprocessor bugfix\n  Mike Long              Unix Makefile installation bugfix\n  Warner Losh            in misc.c\n  Dave Lovelace          Data General AOS/VS port\n  Stew Loving-Gibbard    original Windows 16-bit DLL port (non-WizUnZip version)\n  Dale Lutz              \\-to-/ conversion argv/argc bugfix\n  Tony Luu               NT timezone bugfix\n  Igor Mandrichenko      vms.c; many improvements and VMS modifications\n  Javier Manero          fileio.c bugfix; MS-DOS version() bugfix; Watcom fix\n  Paul Manno             makefile.tc fixes\n  Claude Marinier        Unix makefile recursive fix\n  Fulvio Marino          revised UnZip and ZipInfo man pages; Makefile entry\n  Carl Mascott           original Unix port\n  Rafal Maszkowski       Convex unzip.h fixes; Unix makefile entry\n  Jim Mathies            signal handler installing bugfix\n  Eberhard Mattes        handler() bugfix; docs update\n  Adrian Maull           .NET C# example projects for Zip and UnZip dll\n  Peter Mauzey           Unix makefile entry\n  Scott Maxwell          version.h; massive reentrancy fixes; OS/2 DLL port\n  Bob Maynard            16-bit OS/2 pathname bugfix\n  Randy McCaskile        Unix makefile entry\n  John McDonald          OS/2 zip2exe script\n  Gene McManus           -o code\n  Joe Meadows            file.c, on which VMSmunch.c (timestamps) was based\n  Jason Merrill          Sequent patches\n  Tom Metro              corrupted-zipfile handler bugfix\n  Ian Miller             VMS makefile portability bugfix (non-standard \"edit\")\n  Steve Miller           Windows CE GUI port; memory leak bugfix; etc.\n  Ricky Mobley           Unix makefile entry\n  Navin Modi             Unix makefile entry\n  Sergio Monesi          Acorn RISC OS port\n  Paul Motsuk            Borland _rtl_chmod() fix\n  Anthony Naggs          MS-DOS error handling stuff\n  Jim Neeland            unused-variables fix; Unix makefile entry\n  Harry Nyberg           Macintosh INSTALL info\n  Mauricio Ponzo         UNIXBACKUP fix\n  NIIMI Satoshi          Human68k port\n  Mike O'Carroll         early OS/2 stuff\n  Michael D. O'Connor    DOS ifdef/elif mismatch fix; makefile.tc fixes\n  \"Moby\" Dick O'Connor   Unix makefile entry\n  Thomas Opheys          Watcom C stat() bugfix\n  Humberto Ortiz-Zuazaga Linux port; permissions bugfix; missing declarations\n  Keith Owens            MVS support and extensions\n  Fernando Papa          inflate memory leaks\n  Rafael Pappalardo      Convex CRYPT bugfix; Convex Makefile entry, useful info\n  Trevor Paquette        Unix makefile entry\n  Keith Petersen         Pyramid fixes; former Info-ZIP list maintainer\n  George Petrov          initial MVS, VM/CMS ports (!)\n  Alan Phillips          Unix makefile entry\n  Art Pina               C Set/2 crypt.c optimization bug\n  Piet W. Plomp          Unix chmod()/chown() fix; msc_dos fixes; much testing\n  Norbert Pueschel       Amiga timelib\n  Clint Pulley           Unix makefile entry\n  Antonio Querubin, Jr.  descrip.mms (VMS makefile)\n  Alistair Rae           Encore preprocessor bugfix\n  Eric S. Raymond        manpage tweaks for DocBook compatibility\n  Wally Reiher           timezone bugfix\n  Stephen Ritcey         vms/README installation correction\n  Phil Ritzenthaler      ANSIfication bugfix\n  Simon Roberts          Windows CE 2.1x/3.0 cmdline port\n  David Robinson         MSC 6.0 stat() bugfix\n  Jochen Roderburg       floating-point BSD4_4 fix, Borland _timezone fix; etc.\n  Greg Roelofs           maintainer/principal author; ZipInfo; unshrink; etc.\n  Kai Uwe Rommel         \"real\" OS/2 port; many new compilers; bugfixes; etc.\n  Paul Roub              first self-extracting code\n  Shimazaki Ryo          human68k port updates\n  Steve Salisbury        Win32 fixes; dual-mode SFX instruct.; variable INBUFSIZ\n  Darren Salt            Acorn filetype <-> \"Acorn NFS filetype\" translation\n  Georg Sassen           Amiga DICE compiler support\n  Jon Saxton             date formats, OS/2 fixes\n  Tom Schmidt            Unix makefile entry; Xenix and SunOS 3 target bugfixes\n  Hugh Schmidt           VMS stuff\n  Doug Schuessler        Tandem/NSK port fixes\n  Steven M. Schweda      VMS: adapt new 7+ features, I/O performance enhanced\n  Martin Schulz          original Atari port, symlinks bugfix\n  Charles Scripter       various bug reports and bugfixes\n  Chris Seaman           Unix time stuff\n  Richard Seay           MS-DOS Quick C makefile\n  Peter Seebach          fUnZip int main() bugfix\n  Matthew Seitz          keep inherited SGID attrib for created dirs on Unix\n  Gisbert Selke          Unix makefile entry\n  Alex Sergejew          fileio.c, stat(), Makefile fixes; Down Under jokes :-)\n  Jim Seymour            Borland OS/2 fixes\n  Mark Shadley           Unix -X, FGETCH, DESTROYGLOBALS & Unix makefile fixes\n  Miki Shapiro           DLL: zipfilehandle leak (unhandled lseek errors)\n  Timur Shaporev         inflate optimizations\n  Eric Siegerman         bugfix for Unix' port attribute mapper\n  Paul Slootman          partial fix >2G handling on 64bit file offset systems\n  Dave Smith             Tandem/NSK port\n  Fred Smith             Coherent 4.0 fixes\n  Nick Smith             return code for user abort (control-C)\n  Samuel H. Smith        original unzip code (Pascal and C) for MS-DOS\n  Tuomo Soini            file-not-matched bugfix\n  Jim Spath              zipinfo -T century bugfix\n  Christian Spieler      VMS, DOS, WIN32, VM/CMS, portability & performance\n  Cliff Stanford         fileio.c umask bug\n  Jack Stansbury         DEC Alpha NT makefile fix\n  Dan Statkus            OS/2, MS-DOS mapname() ASCII 255 bugfix\n  Jochen Stein           Unix makefile entry\n  Jim Steiner            Unix makefile entry\n  Richard Stephen        Unix makefile entry\n  Wayne Stewart          \"WHERE\" file MS-DOS correction\n  Mike Strock            Win32 MSVC 5.0 \"build file\"; typo fixes\n  E-Yen Tan              djgpp1/GNUmake 3.71 bug work-around; DOS makefile.emx\n  Brian Tillman          \"WHERE\" file VMS fix; make_unz.com portability bugfix\n  Cosmin Truta           Cygwin support; various C & ASM fixes\n  Onno van der Linden    many fixes, esp. Intel Unix and 386 DOS\n  Jim Van Zandt          one of original man pages\n  Geraldo Veiga          Pyramid strrchr/rindex\n  Erik-Jan Vens          Unix makefile entry\n  Antoine Verheijen      new Mac port; Mac bugfixes; MTS/EBCDIC stuff; etc.\n  Santiago Vila          -t stderr/stdout fix\n  Rich Wales             former Info-ZIP moderator and zip guy; MKS stuff\n  Frank Wancho           original TOPS-20 port\n  Douglas Wegscheid      djgpp 2.x USE_LFN compatibility fix\n  Yohanan Weininger      docs update\n  Paul Weiss             unzipsfx bugfix\n  Paul Wells             original Amiga port for SAS/C and Lattice C (?)\n  Mike White             Windows GUI port version 3; 16- and 32-bit Windows DLLs\n  Rainer Wilcke          HP/UX termios bugfix; man-page fixes\n  Charles Wilson         Cygwin support\n  Greg Woods             man-pages bugfixes\n  Mark Wright            original Netware 3.11 NLM port\n  Randy Wright           Unix makefile entry\n  Meiwei Wu              open() return bugfix\n  Steve Youngs           win32 timestamp conversion bugfix\n  Clay Zahrobsky         .zip/wildcard bugfix\n  Eli Zaretskii          improvements to DOS-mode VFAT support; djgpp 2.x fixes\n  Martin P.J. Zinser     VMS .hlp file for unzipsfx; MAKESFX.COM command file\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/Contents",
    "content": "Contents of the \"proginfo\" subdirectory for UnZip 5.42 and later:\n\n  Contents      this file\n  CONTRIBS      list of contributors to UnZip\n  ZipPorts      Info-ZIP rules and guidelines on contributions to the cause\n  3rdparty.bug  known bugs in PK[UN]ZIP, WinZip, etc.\n  defer.in      info about the NEXTBYTE macro and defer/undefer_input functions\n  extrafld.txt  info about all known \"extra field\" types\n  fileinfo.cms  info about the VM/CMS file system, including record formats\n  nt.sd         info about support for Windows NT's Security Descriptors (ACLs)\n  perform.dos   relative performance of Zip and UnZip with various DOS compilers\n  timezone.txt  explanation of the TZ environment variable for timezones\n  ziplimit.txt  limits of the Zip archive format and InfoZip's implementation\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/ZipPorts",
    "content": "__________________________________________________________________________\n\n  This is the Info-ZIP file ZipPorts, last updated on 17 February 1996.\n__________________________________________________________________________\n\n\nThis document defines a set of rules and guidelines for those who wish to\ncontribute patches to Zip and UnZip (or even entire ports to new operating\nsystems).  The list below is something between a style sheet and a \"Miss\nManners\" etiquette guide.  While Info-ZIP encourages contributions and\nfixes from anyone who finds something worth changing, we are also aware\nof the fact that no two programmers have the programming style and that\nunrestrained changes by a few dozen contributors would result in hideously\nugly (and unmaintainable) Frankenstein code.  So consider the following an\nattempt by the maintainers to maintain sanity as well as useful code.\n\n(The first version of this document was called either \"ZipRules\" or the\n\"No Feelthy ...\" file and was compiled by David Kirschbaum in consulta-\ntion with Mark Adler, Cave McNewt and others.  The current incarnation\nexpands upon the original with insights gained from a few more years of\nhappy hacking...)\n\n\nSummary:\n\n  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS\n(0.1) The Golden Rule:    DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE\n(0.2) The Silver Rule:    DO UNTO THE LATEST BETA CODE\n(0.3) The Bronze Rule:    NO FEELTHY PIGGYBACKS\n\n  (1) NO FEELTHY TABS\n  (2) NO FEELTHY CARRIAGE RETURNS\n  (3) NO FEELTHY 8-BIT CHARS\n  (4) NO FEELTHY LEFT-JUSTIFIED DASHES\n  (5) NO FEELTHY FANCY_FILENAMES\n  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS\n  (7) NO FEELTHY E-MAIL BINARIES\n\n\nExplanations:\n\n  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS\n\n      No doubt about it, this is the one which really pisses us off and\n      pretty much guarantees that your port or patch will be ignored and/\n      or laughed at.  Examples range from the *really* severe cases which\n      \"port\" by ripping out all of the existing multi-OS code, to more\n      subtle oopers like relying on a local capability which doesn't exist\n      on other OSes or in older compilers (e.g., the use of ANSI \"#elif\"\n      or \"#pragma\" or \"##\" constructs, C++ comments, GNU extensions, etc.).\n      As to the former, use #ifdefs for your new code (see rule 0.3).  And\n      as to the latter, trust us--there are few things we'd like better\n      than to be able to use some of the elegant \"new\" features out there\n      (many of which have been around for a decade or more).  But our code\n      still compiles on machines dating back even longer, at least in spirit\n      --e.g., the AT&T 3B1 family and Dynix/ptx.  Until we say otherwise,\n      dinosaurs are supported.\n\n\n(0.1) The Golden Rule:  DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE\n\n      In other words, try to fit into the local style of programming--no\n      matter how painful it may be.  This includes cosmetic aspects like\n      indenting the same amount (both in the main C code and in the in-\n      clude files), using braces and comments similarly, NO TABS (see rule\n      #1), etc.; but also more substantive things like (for UnZip) putting\n      character strings into static (far) variables and using the LoadFar-\n      String macros to avoid overflowing limited MS-DOS data segments, and\n      using the ugly Info() macro instead of the more usual *printf()\n      functions so that dynamic-link-library ports are simpler.  NEVER put\n      single-OS code (e.g., OS/2) of more than two or three lines into the\n      main (generic) modules; those are shared by everybody, and nobody else\n      cares about it or wants to see it.\n\n      Note that not only do Zip and UnZip differ in these respects, so do\n      individual parts of each program.  While it would be nice to have\n      global consistency, cosmetic changes are not a high priority; for\n      now we'll settle for local consistency--i.e., don't make things any\n      worse than they already are.\n\n      Exception (BIG exception):  single-letter variable names.  Despite\n      the prevailing practice in much of Zip and parts of UnZip, and de-\n      spite the fact that one-letter variables allow you to pack really\n      cool, compact and complicated expressions onto one line, they also\n      make the code very difficult to maintain and are therefore *strongly*\n      discouraged.  Don't ask us who is responsible in the first place;\n      while this sort of brain damage is not uncommon among former BASIC\n      programmers, it is nevertheless a lifelong embarrassment, and we do\n      try to pity the poor sod (that is, when we're not chasing bugs and\n      cursing him).  :-)\n\n\n(0.2) The Silver Rule:  DO UNTO THE LATEST BETA CODE\n\n      Few things are as annoying as receiving a large patch which obviously\n      represents a lot of time and careful work but which is relative to\n      an old version of Info-ZIP code.  As wonderful as Larry Wall's patch\n      program is at applying context diffs to modified code, we regularly\n      make near-global changes and/or reorganize big chunks of the sources\n      (particularly in UnZip), and \"patch\" can't work miracles--big changes\n      invariably break any patch which is relative to an old version of the\n      code.\n\n      Bottom line:  contact the Info-ZIP core team FIRST (via the zip-bugs\n      e-mail address) and get up to date with the latest code before begin-\n      ning a big new port.  And try to *stay* up to date while working on\n      your port--at least, as much as possible.\n\n\n(0.3) The Bronze Rule:  NO FEELTHY PIGGYBACKS\n\n      UnZip is currently ported to something like 12 operating systems\n      (a few more or less depending on how one counts), and each of these,\n      with the possible exception of VM/CMS, has a unique macro identifying\n      it:  AMIGA, ATARI_ST, __human68k__, MACOS, MSDOS, MVS, OS2, TOPS20,\n      UNIX, VMS, WIN32.  Zip is moving in the same direction.  New ports\n      should NOT piggyback one of the existing ports unless they are sub-\n      stantially similar--for example, Minix and Coherent are basically Unix\n      and therefore are included in the UNIX macro, but DOS djgpp ports and\n      OS/2 emx ports (both of which use the Unix-originated GNU C compiler\n      and often have \"unix\" defined by default) are obviously *not* Unix.\n      [The existing MTS port is a special exception; basically only one per-\n      son knows what MTS really is, and he's not telling.  Presumably it's\n      not very close to Unix, but it's not worth arguing about it now.]\n      Along the same lines, neither OS/2 nor Human68K is the same as (or\n      even close to) MS-DOS.  MVS and VM/CMS, on the other hand, are quite\n      similar to each other and are therefore combined in most places.\n\n      Bottom line:  when adding a new port (e.g., QDOS), create a new macro\n      for it (\"QDOS\"), a new subdirectory (\"qdos\") and a new source file for\n      OS-specific code (\"qdos/qdos.c\").  Use #ifdefs to fit any OS-specific\n      changes into the existing code (e.g., unzpriv.h).  If it's close enough\n      to an existing port that piggybacking is a temptation, define a new\n      \"combination macro\" (e.g., \"CMS_MVS\") and replace the old macros as\n      required.  (This last applies to UnZip, at least; the old preference\n      in Zip was fewer macros and long #ifdef lines, so talk to Onno or Jean-\n      loup about that.)  See also rule 0.1.\n\n      (Note that, for UnZip, new ports need not attempt to deal with all\n      features.  Among other things, the wildcard-zipfile code in do_wild()\n      may be replaced with a supplied dummy version, since opendir/readdir/\n      closedir() or the equivalent can be difficult to implement.)\n\n\n  (1) NO FEELTHY TABS\n\n      Some editors and e-mail systems either have no capability to use\n      and/or display tab characters (ASCII 9) correctly, or they use non-\n      standard or variable-width tab columns, or other horrors.  Some edi-\n      tors auto-convert spaces to tabs, after which the blind use of \"diff\n      -c\" results in a huge and mostly useless patch.  Yes, *we* know about\n      diff's \"-b\" option, but not everyone does.  And yes, we also know this\n      makes the source files bigger, even after compression; so be it.  If\n      we *really* cared that much about the size of the sources, we'd still\n      be writing Unix-only utilities.\n\n      Bottom line:  use spaces, not tabs.\n\n      Exception:  some of the makefiles (the Unix one in particular) require\n      tabs as part of the syntax.\n\n      Related utility programs:\n          Unix, OS/2 and MS-DOS:  expand, unexpand.\n          MS-DOS:  Buerg's TABS; Toad Hall's TOADSOFT.\n          And some editors have the conversion built-in.\n\n\n  (2) NO FEELTHY CARRIAGE RETURNS\n\n      All source, documentation and other text files shall have Unix style\n      line endings (LF only, a.k.a. ctrl-J), not the DOS/OS2/NT CR+LF or Mac\n      CR-only line endings.\n\n      Reason:  \"real programmers\" in any environment can convert back and\n      forth between Unix and DOS/Mac style.  All PC compilers but a few old\n      Borland versions can use either Unix or MS-DOS end-of-lines.  Buerg's\n      LIST (file-display utility) for MS-DOS can use Unix or MS-DOS EOLs.\n      Both Zip and UnZip can convert line-endings as appropriate.  But Unix\n      utilities like diff and patch die a horrible death (or produce horrible\n      output) if the target files have CRs.\n\n      Related utilities:  flip for Unix, OS/2 and MS-DOS; Unix \"tr\".\n\n      Exceptions:  documentation in pre-compiled binary distributions should\n      be in the local (target) format.\n\n\n  (3) NO FEELTHY 8-BIT CHARS\n\n      Do all your editing in a plain-text ASCII editor.  No WordPerfect, MS\n      Word, WordStar document mode, or other word processor files, thenkyew.\n      No desktop publishing.  *Especially* no EBCDIC.  No TIFFs, no GIFs, no\n      embedded pictures or dancing ladies (too bad, Cave Newt).  [Sigh... -CN]\n\n      Reason:  compatibility with different consoles.  My old XT clone is\n      the most limited!\n\n      Exceptions:  some Macintosh makefiles apparently require some 8-bit\n      characters; the Human68k port uses 8-bit characters for Kanji or Kana\n      comments (I think); etc.\n\n      Related utilities:  vi, emacs, EDLIN, Turbo C editor, other programmers'\n      editors, various word processor -> text conversion utilities.\n\n\n  (4) NO FEELTHY LEFT-JUSTIFIED DASHES\n\n      Always precede repeated dashes (------) with one or more leading non-\n      dash characters:  spaces, tabs, pound signs (#), comments (/*), what-\n      ever.\n\n      Reason:  sooner or later your source file will be e-mailed through an\n      undigestifier utility, most of which treat leading dashes as end-of-\n      message separators.  We'd rather not have your code broken up into a\n      dozen separate untitled messages, thank you.\n\n\n  (5) NO FEELTHY FANCY_FILENAMES\n\n      Assume the worst:  that someone on a brain-damaged DOS system has to\n      work with everything your magic fingers produced.  Keep the filenames\n      unimaginative and within MS-DOS limits (i.e., ordinary A..Z, 1..9,\n      \"-$_!\"-type characters, in the 8.3 \"filename.ext\" format).  Mac and\n      Unix users, giggle all you want, but no spaces or multiple dots.\n\n      Reason:  compatibility with different file systems.  MS-DOS FAT is the\n      most limited, with the exception of CompuServe (6.3, argh).\n\n      Exceptions:  slightly longer names are occasionally acceptable within\n      OS-specific subdirectories, but don't do that unless there's a good\n      reason for it.\n\n\n  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS\n\n      Beta testers and developers are in general expected to have both\n      ftp capability and the ability to deal with zipfiles.  Those without\n      should either find a friend who does or else learn about ftp-mailers.\n\n      Reason:  the core development team barely has time to work on the\n      code, much less prepare oddball formats and/or mail betas out (and\n      the situation is getting worse, sigh).\n\n      Exceptions:  anyone seriously proposing to do a new port will be\n      given special treatment, particularly with respect to UnZip; we\n      obviously realize that bootstrapping a completely new port can be\n      quite difficult and have no desire to make it even harder due to\n      lack of access to the latest code (rule 0.2).\n\n      Public releases of UnZip, on the other hand, will be available in\n      two formats:  .tar.Z (16-bit compress'd tar) and .zip (either \"plain\"\n      or self-extracting).  Zip sources and executables will generally only\n      be distributed in .zip format, since Zip is pretty much useless without\n      UnZip.\n\n\n  (7) NO FEELTHY E-MAIL BINARIES\n\n      Binary files (e.g., executables, test zipfiles, etc.) should NEVER\n      be mailed raw.  Where possible, they should be uploaded via ftp in\n      BINARY mode; if that's impossible, Mark's \"ship\" ASCII-encoder should\n      be used; and if that's unavailable, uuencode or xxencode should be\n      used.  Weirdo NeXTmail, mailtool and MIME formats are also Right Out.\n\n      Files larger than 50KB may need to be broken into pieces for mailing\n      (be sure to label them in order!), unless \"ship\" is used (it can\n      auto-split, label and mail files if told to do so).  If Down Under\n      is involved, files must be broken into under-20KB chunks.\n\n      Reasons:  to prevent sounds of gagging mailers from resounding through-\n      out the land.  To be relatively efficient in the binary->ASCII conver-\n      sion.  (Yeah, yeah, I know, there's better conversions out there.  But\n      not as widely known, and they often break on BITNET gateways.)\n\n      Related utilities:  ship, uuencode, uudecode, uuxfer20, quux, others.\n      Just make sure they don't leave embedded or trailing spaces (that is,\n      they should use the \"`\" character in place of ASCII 32).  Otherwise\n      mailers are prone to truncate or whatever.\n\n\nGreg Roelofs (a.k.a. Cave Newt)\nInfo-ZIP UnZip maintainer\n\nDavid Kirschbaum\nformer Info-ZIP Coordinator\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/defer.in",
    "content": "[Regarding an optimization to the bounds-checking code in the core\n NEXTBYTE macro, which code is absolutely vital to the proper processing\n of corrupt zipfiles (lack of checking can result in an infinite loop)\n but which also slows processing.]\n\n\nThe key to the solution is a pair of small functions called\ndefer_leftover_input() and undefer_input().  The idea is, whenever\nyou are going to be processing input using NEXTBYTE, you call\ndefer_leftover_input(), and whenever you are going to process input by\nany other means, such as readbuf(), ZLSEEK, or directly reading stuff\ninto G.inbuf, you call undefer_input().  What defer_leftover_input()\ndoes is adjust G.incnt so that any data beyond the current end of file\nis not visible.  undefer_input() restores it to visibility.  So when\nyou're calling NEXTBYTE (or NEEDBITS or READBITS), an end-of-data\ncondition only occurs at the same time as an end-of-buffer condition,\nand can be handled inside readbyte() instead of needing a check in the\nNEXTBYTE macro.  Note: none of this applies to fUnZip.\n\nIn order for this to work, certain conditions have to be met:\n\n  1) NEXTBYTE input must not be mixed with other forms of input involving\n     G.inptr and G.incnt.  They must be separated by defer/undefer.\n\n  I believe this condition is fully met by simply bracketing the central\n  part of extract_or_test_member with defer/undefer, around the part\n  where the actual decompression is done, and another defer/undefer pair\n  in decrypt() around the reading of the RAND_HEADER_LEN password bytes.\n\n  When USE_ZLIB is defined, I think that calls of fillinbuf() must be\n  bracketed by defer/undefer.\n\n  2) G.csize must not be assumed to contain the number of bytes left to\n     process, when decompressing with NEXTBYTE.  Instead, it contains\n     the number of bytes left after the current buffer is exausted.  To\n     check the number of bytes remaining, use (G.csize + G.incnt).\n\n  I believe the only places this change was needed were in explode.c,\n  mostly in the check at the end of each explode function that tests\n  whether the correct number of bytes has been read.  G.incnt will\n  normally be zero at that time anyway.  The other place is the line\n  that says \"bd = G.csize > 200000L ? 8 : 7;\" but that's just a rough\n  heuristic anyway.\n\n[Paul Kienitz]\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/extrafld.txt",
    "content": "The following are the known types of zipfile extra fields as of this\nwriting.  Extra fields are documented in PKWARE's appnote.txt and are\nintended to allow for backward- and forward-compatible extensions to\nthe zipfile format.  Multiple extra-field types may be chained together,\nprovided that the total length of all extra-field data is less than 64KB.\n(In fact, PKWARE requires that the total length of the entire file header,\nincluding timestamp, file attributes, filename, comment, extra field, etc.,\nbe no more than 64KB.)\n\nEach extra-field type (or subblock) must contain a four-byte header con-\nsisting of a two-byte header ID and a two-byte length (little-endian) for\nthe remaining data in the subblock.  If there are additional subblocks\nwithin the extra field, the header for each one will appear immediately\nfollowing the data for the previous subblock (i.e., with no padding for\nalignment).\n\nAll integer fields in the descriptions below are in little-endian (Intel)\nformat unless otherwise specified.  Note that \"Short\" means two bytes,\n\"Long\" means four bytes, and \"Long-Long\" means eight bytes, regardless\nof their native sizes.  Unless specifically noted, all integer fields should\nbe interpreted as unsigned (non-negative) numbers.\n\nChristian Spieler, Ed Gordon, 20080717\n\n                        -------------------------\n\n          Header ID's of 0 thru 31 are reserved for use by PKWARE.\n          The remaining ID's can be used by third party vendors for\n          proprietary usage.\n\n          The current Header ID mappings defined by PKWARE are:\n\n          0x0001        Zip64 extended information extra field\n          0x0007        AV Info\n          0x0008        Reserved for extended language encoding data (PFS)\n          0x0009        OS/2 extended attributes      (also Info-ZIP)\n          0x000a        NTFS (Win9x/WinNT FileTimes)\n          0x000c        OpenVMS                       (also Info-ZIP)\n          0x000d        UNIX\n          0x000e        Reserved for file stream and fork descriptors\n          0x000f        Patch Descriptor\n          0x0014        PKCS#7 Store for X.509 Certificates\n          0x0015        X.509 Certificate ID and Signature for\n                        individual file\n          0x0016        X.509 Certificate ID for Central Directory\n          0x0017        Strong Encryption Header\n          0x0018        Record Management Controls\n          0x0019        PKCS#7 Encryption Recipient Certificate List\n          0x0065        IBM S/390 (Z390), AS/400 (I400) attributes\n                        - uncompressed\n          0x0066        Reserved for IBM S/390 (Z390), AS/400 (I400)\n                        attributes - compressed\n          0x4690        POSZIP 4690 (reserved)\n\n          The Header ID mappings defined by Info-ZIP and third parties are:\n\n          0x07c8        Info-ZIP Macintosh (old, J. Lee)\n          0x2605        ZipIt Macintosh (first version)\n          0x2705        ZipIt Macintosh v 1.3.5 and newer (w/o full filename)\n          0x2805        ZipIt Macintosh 1.3.5+\n          0x334d        Info-ZIP Macintosh (new, D. Haase's 'Mac3' field)\n          0x4154        Tandem NSK\n          0x4341        Acorn/SparkFS (David Pilling)\n          0x4453        Windows NT security descriptor (binary ACL)\n          0x4704        VM/CMS\n          0x470f        MVS\n          0x4854        Theos, old inofficial port\n          0x4b46        FWKCS MD5 (see below)\n          0x4c41        OS/2 access control list (text ACL)\n          0x4d49        Info-ZIP OpenVMS (obsolete)\n          0x4d63        Macintosh SmartZIP, by Macro Bambini\n          0x4f4c        Xceed original location extra field\n          0x5356        AOS/VS (binary ACL)\n          0x5455        extended timestamp\n          0x554e        Xceed unicode extra field\n          0x5855        Info-ZIP UNIX (original; also OS/2, NT, etc.)\n          0x6375        Info-ZIP UTF-8 comment field\n          0x6542        BeOS (BeBox, PowerMac, etc.)\n          0x6854        Theos\n          0x7075        Info-ZIP UTF-8 name field\n          0x7441        AtheOS (AtheOS/Syllable attributes)\n          0x756e        ASi UNIX\n          0x7855        Info-ZIP UNIX (16-bit UID/GID info)\n          0x7875        Info-ZIP UNIX 3rd generation (generic UID/GID, ...)\n          0xa220        Microsoft Open Packaging Growth Hint\n          0xfb4a        SMS/QDOS\n\nThe following are detailed descriptions of the known extra-field block types:\n\n         -Zip64 Extended Information Extra Field (0x0001):\n          ===============================================\n\n          The following is the layout of the zip64 extended\n          information \"extra\" block. If one of the size or\n          offset fields in the Local or Central directory\n          record is too small to hold the required data,\n          a zip64 extended information record is created.\n          The order of the fields in the zip64 extended\n          information record is fixed, but the fields will\n          only appear if the corresponding Local or Central\n          directory record field is set to 0xFFFF or 0xFFFFFFFF.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value      Size       Description\n          -----      ----       -----------\n  (ZIP64) 0x0001     2 bytes    Tag for this \"extra\" block type\n          Size       2 bytes    Size of this \"extra\" block\n          Original\n          Size       8 bytes    Original uncompressed file size\n          Compressed\n          Size       8 bytes    Size of compressed data\n          Relative Header\n          Offset     8 bytes    Offset of local header record\n          Disk Start\n          Number     4 bytes    Number of the disk on which\n                                this file starts\n\n          This entry in the Local header must include BOTH original\n          and compressed file size fields.  If encrypting the\n          central directory and bit 13 of the general purpose bit\n          flag is set indicating masking, the value stored in the\n          Local Header for the original file size will be zero.\n\n\n         -OS/2 Extended Attributes Extra Field (0x0009):\n          =============================================\n\n          The following is the layout of the OS/2 extended attributes \"extra\"\n          block.  (Last Revision 19960922)\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (OS/2)  0x0009        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed EA data size\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed EA data\n          (var.)        variable    compressed EA data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (OS/2)  0x0009        Short       tag for this extra block type\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local EA data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n\n          The OS/2 extended attribute structure (FEA2LIST) is\n          compressed and then stored in its entirety within this\n          structure.  There will only ever be one \"block\" of data in\n          the variable-length field.\n\n\n         -OS/2 Access Control List Extra Field:\n          ====================================\n\n          The following is the layout of the OS/2 ACL extra block.\n          (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (ACL)   0x4c41        Short       tag for this extra block type (\"AL\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed ACL data size\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed ACL data\n          (var.)        variable    compressed ACL data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (ACL)   0x4c41        Short       tag for this extra block type (\"AL\")\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local ACL data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n\n          The uncompressed ACL data consist of a text header of the form\n          \"ACL1:%hX,%hd\\n\", where the first field is the OS/2 ACCINFO acc_attr\n          member and the second is acc_count, followed by acc_count strings\n          of the form \"%s,%hx\\n\", where the first field is acl_ugname (user\n          group name) and the second acl_access.  This block type will be\n          extended for other operating systems as needed.\n\n\n         -Windows NT Security Descriptor Extra Field (0x4453):\n          ===================================================\n\n          The following is the layout of the NT Security Descriptor (another\n          type of ACL) extra block.  (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (SD)    0x4453        Short       tag for this extra block type (\"SD\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed SD data size\n          Version       Byte        version of uncompressed SD data format\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed SD data\n          (var.)        variable    compressed SD data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (SD)    0x4453        Short       tag for this extra block type (\"SD\")\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local SD data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n          Version specifies how the compressed data are to be interpreted\n          and allows for future expansion of this extra field type.  Currently\n          only version 0 is defined.\n\n          For version 0, the compressed data are to be interpreted as a single\n          valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative\n          format.\n\n\n         -PKWARE Win95/WinNT Extra Field (0x000a):\n          =======================================\n\n          The following description covers PKWARE's \"NTFS\" attributes\n          \"extra\" block, introduced with the release of PKZIP 2.50 for\n          Windows. (Last Revision 20001118)\n\n          (Note: At this time the Mtime, Atime and Ctime values may\n          be used on any WIN32 system.)\n         [Info-ZIP note: In the current implementations, this field has\n          a fixed total data size of 32 bytes and is only stored as local\n          extra field.]\n\n          Value         Size        Description\n          -----         ----        -----------\n  (NTFS)  0x000a        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          Reserved      Long        for future use\n          Tag1          Short       NTFS attribute tag value #1\n          Size1         Short       Size of attribute #1, in bytes\n          (var.)        SubSize1    Attribute #1 data\n          .\n          .\n          .\n          TagN          Short       NTFS attribute tag value #N\n          SizeN         Short       Size of attribute #N, in bytes\n          (var.)        SubSizeN    Attribute #N data\n\n          For NTFS, values for Tag1 through TagN are as follows:\n          (currently only one set of attributes is defined for NTFS)\n\n          Tag        Size       Description\n          -----      ----       -----------\n          0x0001     2 bytes    Tag for attribute #1\n          Size1      2 bytes    Size of attribute #1, in bytes (24)\n          Mtime      8 bytes    64-bit NTFS file last modification time\n          Atime      8 bytes    64-bit NTFS file last access time\n          Ctime      8 bytes    64-bit NTFS file creation time\n\n          The total length for this block is 28 bytes, resulting in a\n          fixed size value of 32 for the TSize field of the NTFS block.\n\n          The NTFS filetimes are 64-bit unsigned integers, stored in Intel\n          (least significant byte first) byte order. They determine the\n          number of 1.0E-07 seconds (1/10th microseconds!) past WinNT \"epoch\",\n          which is \"01-Jan-1601 00:00:00 UTC\".\n\n\n         -PKWARE OpenVMS Extra Field (0x000c):\n          ===================================\n\n          The following is the layout of PKWARE's OpenVMS attributes\n          \"extra\" block.  (Last Revision 12/17/91)\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (VMS)   0x000c        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          CRC           Long        32-bit CRC for remainder of the block\n          Tag1          Short       OpenVMS attribute tag value #1\n          Size1         Short       Size of attribute #1, in bytes\n          (var.)        Size1       Attribute #1 data\n          .\n          .\n          .\n          TagN          Short       OpenVMS attribute tag value #N\n          SizeN         Short       Size of attribute #N, in bytes\n          (var.)        SizeN       Attribute #N data\n\n          Rules:\n\n          1. There will be one or more of attributes present, which\n             will each be preceded by the above TagX & SizeX values.\n             These values are identical to the ATR$C_XXXX and\n             ATR$S_XXXX constants which are defined in ATR.H under\n             OpenVMS C.  Neither of these values will ever be zero.\n\n          2. No word alignment or padding is performed.\n\n          3. A well-behaved PKZIP/OpenVMS program should never produce\n             more than one sub-block with the same TagX value.  Also,\n             there will never be more than one \"extra\" block of type\n             0x000c in a particular directory record.\n\n\n         -Info-ZIP VMS Extra Field:\n          ========================\n\n          The following is the layout of Info-ZIP's VMS attributes extra\n          block for VAX or Alpha AXP.  The local-header and central-header\n          versions are identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (VMS2)  0x4d49        Short       tag for this extra block type (\"JM\")\n          TSize         Short       total data size for this block\n          ID            Long        block ID\n          Flags         Short       info bytes\n          BSize         Short       uncompressed block size\n          Reserved      Long        (reserved)\n          (var.)        variable    compressed VMS file-attributes block\n\n          The block ID is one of the following unterminated strings:\n\n                \"VFAB\"          struct FAB\n                \"VALL\"          struct XABALL\n                \"VFHC\"          struct XABFHC\n                \"VDAT\"          struct XABDAT\n                \"VRDT\"          struct XABRDT\n                \"VPRO\"          struct XABPRO\n                \"VKEY\"          struct XABKEY\n                \"VMSV\"          version (e.g., \"V6.1\"; truncated at hyphen)\n                \"VNAM\"          reserved\n\n          The lower three bits of Flags indicate the compression method.  The\n          currently defined methods are:\n\n                0       stored (not compressed)\n                1       simple \"RLE\"\n                2       deflated\n\n          The \"RLE\" method simply replaces zero-valued bytes with zero-valued\n          bits and non-zero-valued bytes with a \"1\" bit followed by the byte\n          value.\n\n          The variable-length compressed data contains only the data corre-\n          sponding to the indicated structure or string.  Typically multiple\n          VMS2 extra fields are present (each with a unique block type).\n\n\n         -Info-ZIP Macintosh Extra Field:\n          ==============================\n\n          The following is the layout of the (old) Info-ZIP resource-fork extra\n          block for Macintosh.  The local-header and central-header versions\n          are identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac)   0x07c8        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          \"JLEE\"        beLong      extra-field signature\n          FInfo         16 bytes    Macintosh FInfo structure\n          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat\n          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat\n          Flags         beLong      info bits\n          DirID         beLong      HParamBlockRec fileParam.ioDirID\n          VolName       28 bytes    volume name (optional)\n\n          All fields but the first two are in native Macintosh format\n          (big-endian Motorola order, not little-endian Intel).  The least\n          significant bit of Flags is 1 if the file is a data fork, 0 other-\n          wise.  In addition, if this extra field is present, the filename\n          has an extra 'd' or 'r' appended to indicate data fork or resource\n          fork.  The 28-byte VolName field may be omitted.\n\n\n         -ZipIt Macintosh Extra Field (long):\n          ==================================\n\n          The following is the layout of the ZipIt extra block for Macintosh.\n          The local-header and central-header versions are identical.\n          (Last Revision 19970130)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac2)  0x2605        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          \"ZPIT\"        beLong      extra-field signature\n          FnLen         Byte        length of FileName\n          FileName      variable    full Macintosh filename\n          FileType      Byte[4]     four-byte Mac file type string\n          Creator       Byte[4]     four-byte Mac creator string\n\n\n         -ZipIt Macintosh Extra Field (short, for files):\n          ==============================================\n\n          The following is the layout of a shortened variant of the\n          ZipIt extra block for Macintosh (without \"full name\" entry).\n          This variant is used by ZipIt 1.3.5 and newer for entries of\n          files (not directories) that do not have a MacBinary encoded\n          file.  The local-header and central-header versions are identical.\n          (Last Revision 20030602)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac2b) 0x2705        Short       tag for this extra block type\n          TSize         Short       total data size for this block (min. 12)\n          \"ZPIT\"        beLong      extra-field signature\n          FileType      Byte[4]     four-byte Mac file type string\n          Creator       Byte[4]     four-byte Mac creator string\n          fdFlags       beShort     attributes from FInfo.frFlags,\n                                    may be omitted\n          0x0000        beShort     reserved, may be omitted\n\n\n         -ZipIt Macintosh Extra Field (short, for directories):\n          ====================================================\n\n          The following is the layout of a shortened variant of the\n          ZipIt extra block for Macintosh used only for directory\n          entries. This variant is used by ZipIt 1.3.5 and newer to\n          save some optional Mac-specific information about directories.\n          The local-header and central-header versions are identical.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac2c) 0x2805        Short       tag for this extra block type\n          TSize         Short       total data size for this block (12)\n          \"ZPIT\"        beLong      extra-field signature\n          frFlags       beShort     attributes from DInfo.frFlags, may\n                                    be omitted\n          View          beShort     ZipIt view flag, may be omitted\n\n\n          The View field specifies ZipIt-internal settings as follows:\n\n          Bits of the Flags:\n              bit 0           if set, the folder is shown expanded (open)\n                              when the archive contents are viewed in ZipIt.\n              bits 1-15       reserved, zero;\n\n\n         -Info-ZIP Macintosh Extra Field (new):\n          ====================================\n\n          The following is the layout of the (new) Info-ZIP extra\n          block for Macintosh, designed by Dirk Haase.\n          All values are in little-endian.\n          (Last Revision 19981005)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac3)  0x334d        Short       tag for this extra block type (\"M3\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed finder attribute data size\n          Flags         Short       info bits\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n          (CType)       Short       compression type\n          (CRC)         Long        CRC value for uncompressed MacOS data\n          Attribs       variable    finder attribute data (see below)\n\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac3)  0x334d        Short       tag for this extra block type (\"M3\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed finder attribute data size\n          Flags         Short       info bits\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n\n          The third bit of Flags in both headers indicates whether\n          the LOCAL extra field is uncompressed (and therefore whether CType\n          and CRC are omitted):\n\n          Bits of the Flags:\n              bit 0           if set, file is a data fork; otherwise unset\n              bit 1           if set, filename will be not changed\n              bit 2           if set, Attribs is uncompressed (no CType, CRC)\n              bit 3           if set, date and times are in 64 bit\n                              if zero date and times are in 32 bit.\n              bit 4           if set, timezone offsets fields for the native\n                              Mac times are omitted (UTC support deactivated)\n              bits 5-15       reserved;\n\n\n          Attributes:\n\n          Attribs is a Mac-specific block of data in little-endian format with\n          the following structure (if compressed, uncompress it first):\n\n          Value         Size        Description\n          -----         ----        -----------\n          fdFlags       Short       Finder Flags\n          fdLocation.v  Short       Finder Icon Location\n          fdLocation.h  Short       Finder Icon Location\n          fdFldr        Short       Folder containing file\n\n          FXInfo        16 bytes    Macintosh FXInfo structure\n            FXInfo-Structure:\n                fdIconID        Short\n                fdUnused[3]     Short       unused but reserved 6 bytes\n                fdScript        Byte        Script flag and number\n                fdXFlags        Byte        More flag bits\n                fdComment       Short       Comment ID\n                fdPutAway       Long        Home Dir ID\n\n          FVersNum      Byte        file version number\n                                    may be not used by MacOS\n          ACUser        Byte        directory access rights\n\n          FlCrDat       ULong       date and time of creation\n          FlMdDat       ULong       date and time of last modification\n          FlBkDat       ULong       date and time of last backup\n            These time numbers are original Mac FileTime values (local time!).\n            Currently, date-time width is 32-bit, but future version may\n            support be 64-bit times (see flags)\n\n          CrGMTOffs     Long(signed!)   difference \"local Creat. time - UTC\"\n          MdGMTOffs     Long(signed!)   difference \"local Modif. time - UTC\"\n          BkGMTOffs     Long(signed!)   difference \"local Backup time - UTC\"\n            These \"local time - UTC\" differences (stored in seconds) may be\n            used to support timestamp adjustment after inter-timezone transfer.\n            These fields are optional; bit 4 of the flags word controls their\n            presence.\n\n          Charset       Short       TextEncodingBase (Charset)\n                                    valid for the following two fields\n\n          FullPath      variable    Path of the current file.\n                                    Zero terminated string (C-String)\n                                    Currently coded in the native Charset.\n\n          Comment       variable    Finder Comment of the current file.\n                                    Zero terminated string (C-String)\n                                    Currently coded in the native Charset.\n\n\n         -SmartZIP Macintosh Extra Field:\n          ====================================\n\n          The following is the layout of the SmartZIP extra\n          block for Macintosh, designed by Marco Bambini.\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n          0x4d63        Short       tag for this extra block type (\"cM\")\n          TSize         Short       total data size for this block (64)\n          \"dZip\"        beLong      extra-field signature\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n          fdFlags       beShort     Finder Flags\n          fdLocation.v  beShort     Finder Icon Location\n          fdLocation.h  beShort     Finder Icon Location\n          fdFldr        beShort     Folder containing file\n          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat\n          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat\n          frScroll.v    Byte        vertical pos. of folder's scroll bar\n          fdScript      Byte        Script flag and number\n          frScroll.h    Byte        horizontal pos. of folder's scroll bar\n          fdXFlags      Byte        More flag bits\n          FileName      Byte[32]    full Macintosh filename (pascal string)\n\n          All fields but the first two are in native Macintosh format\n          (big-endian Motorola order, not little-endian Intel).\n          The extra field size is fixed to 64 bytes.\n          The local-header and central-header versions are identical.\n\n\n         -Acorn SparkFS Extra Field:\n          =========================\n\n          The following is the layout of David Pilling's SparkFS extra block\n          for Acorn RISC OS.  The local-header and central-header versions are\n          identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Acorn) 0x4341        Short       tag for this extra block type (\"AC\")\n          TSize         Short       total data size for this block (20)\n          \"ARC0\"        Long        extra-field signature\n          LoadAddr      Long        load address or file type\n          ExecAddr      Long        exec address\n          Attr          Long        file permissions\n          Zero          Long        reserved; always zero\n\n          The following bits of Attr are associated with the given file\n          permissions:\n\n                bit 0           user-writable ('W')\n                bit 1           user-readable ('R')\n                bit 2           reserved\n                bit 3           locked ('L')\n                bit 4           publicly writable ('w')\n                bit 5           publicly readable ('r')\n                bit 6           reserved\n                bit 7           reserved\n\n\n         -VM/CMS Extra Field:\n          ==================\n\n          The following is the layout of the file-attributes extra block for\n          VM/CMS.  The local-header and central-header versions are\n          identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n (VM/CMS) 0x4704        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          flData        variable    file attributes data\n\n          flData is an uncompressed fldata_t struct.\n\n\n         -MVS Extra Field:\n          ===============\n\n          The following is the layout of the file-attributes extra block for\n          MVS.  The local-header and central-header versions are identical.\n          (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (MVS)   0x470f        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          flData        variable    file attributes data\n\n          flData is an uncompressed fldata_t struct.\n\n\n         -PKWARE Unix Extra Field (0x000d):\n          ================================\n\n          The following is the layout of PKWARE's Unix \"extra\" block.\n          It was introduced with the release of PKZIP for Unix 2.50.\n          Note: all fields are stored in Intel low-byte/high-byte order.\n          (Last Revision 19980901)\n\n          This field has a minimum data size of 12 bytes and is only stored\n          as local extra field.\n\n          Value         Size        Description\n          -----         ----        -----------\n (Unix0)  0x000d        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          AcTime        Long        time of last access (UTC/GMT)\n          ModTime       Long        time of last modification (UTC/GMT)\n          UID           Short       Unix user ID\n          GID           Short       Unix group ID\n          (var)         variable    Variable length data field\n\n          The variable length data field will contain file type\n          specific data.  Currently the only values allowed are\n          the original \"linked to\" file names for hard or symbolic\n          links, and the major and minor device node numbers for\n          character and block device nodes.  Since device nodes\n          cannot be either symbolic or hard links, only one set of\n          variable length data is stored.  Link files will have the\n          name of the original file stored.  This name is NOT NULL\n          terminated.  Its size can be determined by checking TSize -\n          12.  Device entries will have eight bytes stored as two 4\n          byte entries (in little-endian format).  The first entry\n          will be the major device number, and the second the minor\n          device number.\n\n         [Info-ZIP note: The fixed part of this field has the same layout as\n          Info-ZIP's abandoned \"Unix1 timestamps & owner ID info\" extra field;\n          only the two tag bytes are different.]\n\n\n         -PATCH Descriptor Extra Field (0x000f):\n          =====================================\n\n          The following is the layout of the Patch Descriptor \"extra\"\n          block.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Patch) 0x000f        Short       Tag for this \"extra\" block type\n          TSize         Short       Size of the total \"extra\" block\n          Version       Short       Version of the descriptor\n          Flags         Long        Actions and reactions (see below)\n          OldSize       Long        Size of the file about to be patched\n          OldCRC        Long        32-bit CRC of the file about to be patched\n          NewSize       Long        Size of the resulting file\n          NewCRC        Long        32-bit CRC of the resulting file\n\n\n          Actions and reactions\n\n          Bits          Description\n          ----          ----------------\n          0             Use for auto detection\n          1             Treat as a self-patch\n          2-3           RESERVED\n          4-5           Action (see below)\n          6-7           RESERVED\n          8-9           Reaction (see below) to absent file\n          10-11         Reaction (see below) to newer file\n          12-13         Reaction (see below) to unknown file\n          14-15         RESERVED\n          16-31         RESERVED\n\n          Actions\n\n          Action       Value\n          ------       -----\n          none         0\n          add          1\n          delete       2\n          patch        3\n\n          Reactions\n\n          Reaction     Value\n          --------     -----\n          ask          0\n          skip         1\n          ignore       2\n          fail         3\n\n          Patch support is provided by PKPatchMaker(tm) technology and is\n          covered under U.S. Patents and Patents Pending. The use or\n          implementation in a product of certain technological aspects set\n          forth in the current APPNOTE, including those with regard to\n          strong encryption, patching, or extended tape operations requires\n          a license from PKWARE.  Please contact PKWARE with regard to\n          acquiring a license.\n\n\n         -PKCS#7 Store for X.509 Certificates (0x0014):\n          ============================================\n\n          This field contains information about each of the certificates\n          files may be signed with.  When the Central Directory Encryption\n          feature is enabled for a ZIP file, this record will appear in\n          the Archive Extra Data Record, otherwise it will appear in the\n          first central directory record and will be ignored in any\n          other record.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value     Size     Description\n          -----     ----     -----------\n  (Store) 0x0014    2 bytes  Tag for this \"extra\" block type\n          TSize     2 bytes  Size of the store data\n          SData     TSize    Data about the store\n\n          SData\n          Value     Size        Description\n          -----     ----        -----------\n          Version   2 bytes     Version number, 0x0001 for now\n          StoreD    (variable)  Actual store data\n\n          The StoreD member is suitable for passing as the pbData\n          member of a CRYPT_DATA_BLOB to the CertOpenStore() function\n          in Microsoft's CryptoAPI.  The SSize member above will be\n          cbData + 6, where cbData is the cbData member of the same\n          CRYPT_DATA_BLOB.  The encoding type to pass to\n          CertOpenStore() should be\n          PKCS_7_ANS_ENCODING | X509_ASN_ENCODING.\n\n\n         -X.509 Certificate ID and Signature for individual file (0x0015):\n          ===============================================================\n\n          This field contains the information about which certificate in\n          the PKCS#7 store was used to sign a particular file.  It also\n          contains the signature data.  This field can appear multiple\n          times, but can only appear once per certificate.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (CID)   0x0015        2 bytes     Tag for this \"extra\" block type\n          CSize         2 bytes     Size of Method\n          Method        (variable)\n\n          Method\n          Value         Size        Description\n          -----         ----        -----------\n          Version       2 bytes     Version number, for now 0x0001\n          AlgID         2 bytes     Algorithm ID used for signing\n          IDSize        2 bytes     Size of Certificate ID data\n          CertID        (variable)  Certificate ID data\n          SigSize       2 bytes     Size of Signature data\n          Sig           (variable)  Signature data\n\n          CertID\n          Value         Size        Description\n          -----         ----        -----------\n          Size1         4 bytes     Size of CertID, should be (IDSize - 4)\n          Size1         4 bytes     A bug in version one causes this value\n                                    to appear twice.\n          IssSize       4 bytes     Issuer data size\n          Issuer        (variable)  Issuer data\n          SerSize       4 bytes     Serial Number size\n          Serial        (variable)  Serial Number data\n\n          The Issuer and IssSize members are suitable for creating a\n          CRYPT_DATA_BLOB to be the Issuer member of a CERT_INFO\n          struct. The Serial and SerSize members would be the\n          SerialNumber member of the same CERT_INFO struct.  This\n          struct would be used to find the certificate in the store\n          the file was signed with.  Those structures are from the MS\n          CryptoAPI.\n\n          Sig and SigSize are the actual signature data and size\n          generated by signing the file with the MS CryptoAPI using a\n          hash created with the given AlgID.\n\n\n         -X.509 Certificate ID and Signature for central directory (0x0016):\n          =================================================================\n\n          This field contains the information about which certificate in\n          the PKCS#7 store was used to sign the central directory structure.\n          When the Central Directory Encryption feature is enabled for a\n          ZIP file, this record will appear in the Archive Extra Data Record,\n          otherwise it will appear in the first central directory record,\n          along with the store.  The data structure is the\n          same as the CID, except that SigSize will be 0, and there\n          will be no Sig member.\n\n          This field is also kept after the last central directory\n          record, as the signature data (ID 0x05054b50, it looks like\n          a central directory record of a different type).  This\n          second copy of the data is the Signature Data member of the\n          record, and will have a SigSize that is non-zero, and will\n          have Sig data.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value     Size     Description\n          -----     ----     -----------\n  (CDID)  0x0016    2 bytes  Tag for this \"extra\" block type\n          TSize     2 bytes  Size of data that follows\n          TData     TSize    Data\n\n\n         -Strong Encryption Header (0x0017):\n          =================================\n\n          Value     Size     Description\n          -----     ----     -----------\n          0x0017    2 bytes  Tag for this \"extra\" block type\n          TSize     2 bytes  Size of data that follows\n          Format    2 bytes  Format definition for this record\n          AlgID     2 bytes  Encryption algorithm identifier\n          Bitlen    2 bytes  Bit length of encryption key\n          Flags     2 bytes  Processing flags\n          CertData  TSize-8  Certificate decryption extra field data\n                             (refer to the explanation for CertData\n                              in the section describing the\n                              Certificate Processing Method under\n                              the Strong Encryption Specification)\n\n\n         -Record Management Controls (0x0018):\n          ===================================\n\n          Value     Size     Description\n          -----     ----     -----------\n(Rec-CTL) 0x0018    2 bytes  Tag for this \"extra\" block type\n          CSize     2 bytes  Size of total extra block data\n          Tag1      2 bytes  Record control attribute 1\n          Size1     2 bytes  Size of attribute 1, in bytes\n          Data1     Size1    Attribute 1 data\n            .\n            .\n            .\n          TagN      2 bytes  Record control attribute N\n          SizeN     2 bytes  Size of attribute N, in bytes\n          DataN     SizeN    Attribute N data\n\n\n         -PKCS#7 Encryption Recipient Certificate List (0x0019):\n          =====================================================\n\n          This field contains information about each of the certificates\n          used in encryption processing and it can be used to identify who is\n          allowed to decrypt encrypted files.  This field should only appear\n          in the archive extra data record. This field is not required and\n          serves only to aide archive modifications by preserving public\n          encryption key data. Individual security requirements may dictate\n          that this data be omitted to deter information exposure.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value     Size     Description\n          -----     ----     -----------\n (CStore) 0x0019    2 bytes  Tag for this \"extra\" block type\n          TSize     2 bytes  Size of the store data\n          TData     TSize    Data about the store\n\n          TData:\n\n          Value     Size     Description\n          -----     ----     -----------\n          Version   2 bytes  Format version number - must 0x0001 at this time\n          CStore    (var)    PKCS#7 data blob\n\n\n         -MVS Extra Field (PKWARE, 0x0065):\n          ================================\n\n          The following is the layout of the MVS \"extra\" block.\n          Note: Some fields are stored in Big Endian format.\n          All text is in EBCDIC format unless otherwise specified.\n\n          Value       Size          Description\n          -----       ----          -----------\n  (MVS)   0x0065      2 bytes       Tag for this \"extra\" block type\n          TSize       2 bytes       Size for the following data block\n          ID          4 bytes       EBCDIC \"Z390\" 0xE9F3F9F0 or\n                                    \"T4MV\" for TargetFour\n          (var)       TSize-4       Attribute data\n\n\n         -OS/400 Extra Field (0x0065):\n          ===========================\n\n          The following is the layout of the OS/400 \"extra\" block.\n          Note: Some fields are stored in Big Endian format.\n          All text is in EBCDIC format unless otherwise specified.\n\n          Value       Size          Description\n          -----       ----          -----------\n  (OS400) 0x0065      2 bytes       Tag for this \"extra\" block type\n          TSize       2 bytes       Size for the following data block\n          ID          4 bytes       EBCDIC \"I400\" 0xC9F4F0F0 or\n                                    \"T4MV\" for TargetFour\n          (var)       TSize-4       Attribute data\n\n\n         -Info-ZIP Unicode Path Extra Field:\n          =================================\n\n          Stores the UTF-8 version of the entry path as stored in the\n          local header and central directory header.\n          (Last Revision 20070912)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (UPath) 0x7075        Short       tag for this extra block type (\"up\")\n          TSize         Short       total data size for this block\n          Version       Byte        version of this extra field, currently 1\n          NameCRC32     Long        CRC-32 checksum of standard name field\n          UnicodeName   variable    UTF-8 version of the entry file name\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          The NameCRC32 is the standard zip CRC32 checksum of the File Name\n          field in the header.  This is used to verify that the header\n          File Name field has not changed since the Unicode Path extra field\n          was created.  This can happen if a utility renames the entry but\n          does not update the UTF-8 path extra field.  If the CRC check fails,\n          this UTF-8 Path Extra Field should be ignored and the File Name field\n          in the header should be used instead.\n\n          The UnicodeName is the UTF-8 version of the contents of the File\n          Name field in the header, without any trailing NUL.  The standard\n          name field in the Zip entry header remains filled with the entry\n          name coded in the local machine's extended ASCII system charset.\n          As UnicodeName is defined to be UTF-8, no UTF-8 byte order mark\n          (BOM) is used.  The length of this field is determined by\n          subtracting the size of the previous fields from TSize.\n          If both the File Name and Comment fields are UTF-8, the new General\n          Purpose Bit Flag, bit 11 (Language encoding flag (EFS)), should be\n          used to indicate that both the header File Name and Comment fields\n          are UTF-8 and, in this case, the Unicode Path and Unicode Comment\n          extra fields are not needed and should not be created.  Note that,\n          for backward compatibility, bit 11 should only be used if the native\n          character set of the paths and comments being zipped up are already\n          in UTF-8.  The same method, either general purpose bit 11 or extra\n          fields, should be used in both the Local and Central Directory Header\n          for a file.\n\n          Utilisation rules:\n          1. This field shall never be created for names consisting solely of\n             7-bit ASCII characters.\n          2. On a system that already uses UTF-8 as system charset, this field\n             shall not repeat the string pattern already stored in the Zip\n             entry's standard name field. Instead, a field of exactly 9 bytes\n             (70 75 05 00 01 and 4 bytes CRC) should be created.\n             In this form with 5 data bytes, the field serves as indicator\n             for the UTF-8 encoding of the standard Zip header's name field.\n          3. This field shall not be used whenever the calculated CRC-32 of\n             the entry's standard name field does not match the provided\n             CRC checksum value.  A mismatch of the CRC check indicates that\n             the standard name field was changed by some non-\"up\"-aware\n             utility without synchronizing this UTF-8 name e.f. block.\n\n\n         -Info-ZIP Unicode Comment Extra Field:\n          ====================================\n\n          Stores the UTF-8 version of the entry comment as stored in the\n          central directory header.\n          (Last Revision 20070912)\n\n          Value         Size        Description\n          -----         ----        -----------\n   (UCom) 0x6375        Short       tag for this extra block type (\"uc\")\n          TSize         Short       total data size for this block\n          Version       1 byte      version of this extra field, currently 1\n          ComCRC32      4 bytes     Comment Field CRC32 Checksum\n          UnicodeCom    Variable    UTF-8 version of the entry comment\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          The ComCRC32 is the standard zip CRC32 checksum of the Comment\n          field in the central directory header.  This is used to verify that\n          the comment field has not changed since the Unicode Comment extra\n          field was created.  This can happen if a utility changes the Comment\n          field but does not update the UTF-8 Comment extra field.  If the CRC\n          check fails, this Unicode Comment extra field should be ignored and\n          the Comment field in the header used.\n\n          The UnicodeCom field is the UTF-8 version of the entry comment field\n          in the header.  As UnicodeCom is defined to be UTF-8, no UTF-8 byte\n          order mark (BOM) is used.  The length of this field is determined by\n          subtracting the size of the previous fields from TSize.  If both the\n          File Name and Comment fields are UTF-8, the new General Purpose Bit\n          Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate\n          both the header File Name and Comment fields are UTF-8 and, in this\n          case, the Unicode Path and Unicode Comment extra fields are not\n          needed and should not be created.  Note that, for backward\n          compatibility, bit 11 should only be used if the native character set\n          of the paths and comments being zipped up are already in UTF-8.  The\n          same method, either bit 11 or extra fields, should be used in both\n          the local and central directory headers.\n\n\n         -Extended Timestamp Extra Field:\n          ==============================\n\n          The following is the layout of the extended-timestamp extra block.\n          (Last Revision 19970118)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (time)  0x5455        Short       tag for this extra block type (\"UT\")\n          TSize         Short       total data size for this block\n          Flags         Byte        info bits\n          (ModTime)     Long        time of last modification (UTC/GMT)\n          (AcTime)      Long        time of last access (UTC/GMT)\n          (CrTime)      Long        time of original creation (UTC/GMT)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (time)  0x5455        Short       tag for this extra block type (\"UT\")\n          TSize         Short       total data size for this block\n          Flags         Byte        info bits (refers to local header!)\n          (ModTime)     Long        time of last modification (UTC/GMT)\n\n          The central-header extra field contains the modification time only,\n          or no timestamp at all.  TSize is used to flag its presence or\n          absence.  But note:\n\n              If \"Flags\" indicates that Modtime is present in the local header\n              field, it MUST be present in the central header field, too!\n              This correspondence is required because the modification time\n              value may be used to support trans-timezone freshening and\n              updating operations with zip archives.\n\n          The time values are in standard Unix signed-long format, indicating\n          the number of seconds since 1 January 1970 00:00:00.  The times\n          are relative to Coordinated Universal Time (UTC), also sometimes\n          referred to as Greenwich Mean Time (GMT).  To convert to local time,\n          the software must know the local timezone offset from UTC/GMT.\n\n          The lower three bits of Flags in both headers indicate which time-\n          stamps are present in the LOCAL extra field:\n\n                bit 0           if set, modification time is present\n                bit 1           if set, access time is present\n                bit 2           if set, creation time is present\n                bits 3-7        reserved for additional timestamps; not set\n\n          Those times that are present will appear in the order indicated, but\n          any combination of times may be omitted.  (Creation time may be\n          present without access time, for example.)  TSize should equal\n          (1 + 4*(number of set bits in Flags)), as the block is currently\n          defined.  Other timestamps may be added in the future.\n\n\n         -Info-ZIP Unix Extra Field (type 1):\n          ==================================\n\n          The following is the layout of the old Info-ZIP extra block for\n          Unix.  It has been replaced by the extended-timestamp extra block\n          (0x5455) and the Unix type 2 extra block (0x7855).\n          (Last Revision 19970118)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix1) 0x5855        Short       tag for this extra block type (\"UX\")\n          TSize         Short       total data size for this block\n          AcTime        Long        time of last access (UTC/GMT)\n          ModTime       Long        time of last modification (UTC/GMT)\n          UID           Short       Unix user ID (optional)\n          GID           Short       Unix group ID (optional)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix1) 0x5855        Short       tag for this extra block type (\"UX\")\n          TSize         Short       total data size for this block\n          AcTime        Long        time of last access (GMT/UTC)\n          ModTime       Long        time of last modification (GMT/UTC)\n\n          The file access and modification times are in standard Unix signed-\n          long format, indicating the number of seconds since 1 January 1970\n          00:00:00.  The times are relative to Coordinated Universal Time\n          (UTC), also sometimes referred to as Greenwich Mean Time (GMT).  To\n          convert to local time, the software must know the local timezone\n          offset from UTC/GMT.  The modification time may be used by non-Unix\n          systems to support inter-timezone freshening and updating of zip\n          archives.\n\n          The local-header extra block may optionally contain UID and GID\n          info for the file.  The local-header TSize value is the only\n          indication of this.  Note that Unix UIDs and GIDs are usually\n          specific to a particular machine, and they generally require root\n          access to restore.\n\n          This extra field type is obsolete, but it has been in use since\n          mid-1994.  Therefore future archiving software should continue to\n          support it.  Some guidelines:\n\n              An archive member should either contain the old \"Unix1\"\n              extra field block or the new extra field types \"time\" and/or\n              \"Unix2\".\n\n              If both the old \"Unix1\" block type and one or both of the new\n              block types \"time\" and \"Unix2\" are found, the \"Unix1\" block\n              should be considered invalid and ignored.\n\n              Unarchiving software should recognize both old and new extra\n              field block types, but the info from new types overrides the\n              old \"Unix1\" field.\n\n              Archiving software should recognize \"Unix1\" extra fields for\n              timestamp comparison but never create it for updated, freshened\n              or new archive members.  When copying existing members to a new\n              archive, any \"Unix1\" extra field blocks should be converted to\n              the new \"time\" and/or \"Unix2\" types.\n\n\n         -Info-ZIP UNIX Extra Field (type 2):\n          ==================================\n\n          The following is the layout of the new Info-ZIP extra block for\n          Unix.  (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix2) 0x7855        Short       tag for this extra block type (\"Ux\")\n          TSize         Short       total data size for this block (4)\n          UID           Short       Unix user ID\n          GID           Short       Unix group ID\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix2) 0x7855        Short       tag for this extra block type (\"Ux\")\n          TSize         Short       total data size for this block (0)\n\n          The data size of the central-header version is zero; it is used\n          solely as a flag that UID/GID info is present in the local-header\n          extra field.  If additional fields are ever added to the local\n          version, the central version may be extended to indicate this.\n\n          Note that Unix UIDs and GIDs are usually specific to a particular\n          machine, and they generally require root access to restore.\n\n\n         -Info-ZIP New Unix Extra Field:\n          ====================================\n\n          Currently stores Unix UIDs/GIDs up to 32 bits.\n          (Last Revision 20080509)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (UnixN) 0x7875        Short       tag for this extra block type (\"ux\")\n          TSize         Short       total data size for this block\n          Version       1 byte      version of this extra field, currently 1\n          UIDSize       1 byte      Size of UID field\n          UID           Variable    UID for this entry\n          GIDSize       1 byte      Size of GID field\n          GID           Variable    GID for this entry\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          UIDSize is the size of the UID field in bytes.  This size should\n          match the size of the UID field on the target OS.\n\n          UID is the UID for this entry in standard little endian format.\n\n          GIDSize is the size of the GID field in bytes.  This size should\n          match the size of the GID field on the target OS.\n\n          GID is the GID for this entry in standard little endian format.\n\n          If both the old 16-bit Unix extra field (tag 0x7855, Info-ZIP Unix2)\n          and this extra field are present, the values in this extra field\n          supercede the values in that extra field.\n\n\n         -ASi UNIX Extra Field:\n          ====================\n\n          The following is the layout of the ASi extra block for Unix.  The\n          local-header and central-header versions are identical.\n          (Last Revision 19960916)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix3) 0x756e        Short       tag for this extra block type (\"nu\")\n          TSize         Short       total data size for this block\n          CRC           Long        CRC-32 of the remaining data\n          Mode          Short       file permissions\n          SizDev        Long        symlink'd size OR major/minor dev num\n          UID           Short       user ID\n          GID           Short       group ID\n          (var.)        variable    symbolic link filename\n\n          Mode is the standard Unix st_mode field from struct stat, containing\n          user/group/other permissions, setuid/setgid and symlink info, etc.\n\n          If Mode indicates that this file is a symbolic link, SizDev is the\n          size of the file to which the link points.  Otherwise, if the file\n          is a device, SizDev contains the standard Unix st_rdev field from\n          struct stat (includes the major and minor numbers of the device).\n          SizDev is undefined in other cases.\n\n          If Mode indicates that the file is a symbolic link, the final field\n          will be the name of the file to which the link points.  The file-\n          name length can be inferred from TSize.\n\n          [Note that TSize may incorrectly refer to the data size not counting\n           the CRC; i.e., it may be four bytes too small.]\n\n\n         -BeOS Extra Field:\n          ================\n\n          The following is the layout of the file-attributes extra block for\n          BeOS.  (Last Revision 19970531)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (BeOS)  0x6542        Short       tag for this extra block type (\"Be\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed file attribute data size\n          Flags         Byte        info bits\n          (CType)       Short       compression type\n          (CRC)         Long        CRC value for uncompressed file attribs\n          Attribs       variable    file attribute data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (BeOS)  0x6542        Short       tag for this extra block type (\"Be\")\n          TSize         Short       total data size for this block (5)\n          BSize         Long        size of uncompr. local EF block data\n          Flags         Byte        info bits\n\n          The least significant bit of Flags in both headers indicates whether\n          the LOCAL extra field is uncompressed (and therefore whether CType\n          and CRC are omitted):\n\n                bit 0           if set, Attribs is uncompressed (no CType, CRC)\n                bits 1-7        reserved; if set, assume error or unknown data\n\n          Currently the only supported compression types are deflated (type 8)\n          and stored (type 0); the latter is not used by Info-ZIP's Zip but is\n          supported by UnZip.\n\n          Attribs is a BeOS-specific block of data in big-endian format with\n          the following structure (if compressed, uncompress it first):\n\n              Value     Size        Description\n              -----     ----        -----------\n              Name      variable    attribute name (null-terminated string)\n              Type      Long        attribute type (32-bit unsigned integer)\n              Size      Long Long   data size for this sub-block (64 bits)\n              Data      variable    attribute data\n\n          The attribute structure is repeated for every attribute.  The Data\n          field may contain anything--text, flags, bitmaps, etc.\n\n\n         -AtheOS Extra Field:\n          ==================\n\n          The following is the layout of the file-attributes extra block for\n          AtheOS.  This field is a very close spin-off from the BeOS e.f.\n          The only differences are:\n           - a new extra field signature\n           - numeric field in the attributes data are stored in little-endian\n             format (\"i386\" was initial hardware for AtheOS)\n          (Last Revision 20040908)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n (AtheOS) 0x7441        Short       tag for this extra block type (\"At\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed file attribute data size\n          Flags         Byte        info bits\n          (CType)       Short       compression type\n          (CRC)         Long        CRC value for uncompressed file attribs\n          Attribs       variable    file attribute data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n (AtheOS) 0x7441        Short       tag for this extra block type (\"At\")\n          TSize         Short       total data size for this block (5)\n          BSize         Long        size of uncompr. local EF block data\n          Flags         Byte        info bits\n\n          The least significant bit of Flags in both headers indicates whether\n          the LOCAL extra field is uncompressed (and therefore whether CType\n          and CRC are omitted):\n\n                bit 0           if set, Attribs is uncompressed (no CType, CRC)\n                bits 1-7        reserved; if set, assume error or unknown data\n\n          Currently the only supported compression types are deflated (type 8)\n          and stored (type 0); the latter is not used by Info-ZIP's Zip but is\n          supported by UnZip.\n\n          Attribs is a AtheOS-specific block of data in little-endian format\n          with the following structure (if compressed, uncompress it first):\n\n              Value     Size        Description\n              -----     ----        -----------\n              Name      variable    attribute name (null-terminated string)\n              Type      Long        attribute type (32-bit unsigned integer)\n              Size      Long Long   data size for this sub-block (64 bits)\n              Data      variable    attribute data\n\n          The attribute structure is repeated for every attribute.  The Data\n          field may contain anything--text, flags, bitmaps, etc.\n\n\n         -SMS/QDOS Extra Field:\n          ====================\n\n          The following is the layout of the file-attributes extra block for\n          SMS/QDOS.  The local-header and central-header versions are identical.\n          (Last Revision 19960929)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (QDOS)  0xfb4a        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          LongID        Long        extra-field signature\n          (ExtraID)     Long        additional signature/flag bytes\n          QDirect       64 bytes    qdirect structure\n\n          LongID may be \"QZHD\" or \"QDOS\".  In the latter case, ExtraID will\n          be present.  Its first three bytes are \"02\\0\"; the last byte is\n          currently undefined.\n\n          QDirect contains the file's uncompressed directory info (qdirect\n          struct).  Its elements are in native (big-endian) format:\n\n          d_length      beLong          file length\n          d_access      byte            file access type\n          d_type        byte            file type\n          d_datalen     beLong          data length\n          d_reserved    beLong          unused\n          d_szname      beShort         size of filename\n          d_name        36 bytes        filename\n          d_update      beLong          time of last update\n          d_refdate     beLong          file version number\n          d_backup      beLong          time of last backup (archive date)\n\n\n         -AOS/VS Extra Field:\n          ==================\n\n          The following is the layout of the extra block for Data General\n          AOS/VS.  The local-header and central-header versions are identical.\n          (Last Revision 19961125)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (AOSVS) 0x5356        Short       tag for this extra block type (\"VS\")\n          TSize         Short       total data size for this block\n          \"FCI\\0\"       Long        extra-field signature\n          Version       Byte        version of AOS/VS extra block (10 = 1.0)\n          Fstat         variable    fstat packet\n          AclBuf        variable    raw ACL data ($MXACL bytes)\n\n          Fstat contains the file's uncompressed fstat packet, which is one of\n          the following:\n\n                normal fstat packet             (P_FSTAT struct)\n                DIR/CPD fstat packet            (P_FSTAT_DIR struct)\n                unit (device) fstat packet      (P_FSTAT_UNIT struct)\n                IPC file fstat packet           (P_FSTAT_IPC struct)\n\n          AclBuf contains the raw ACL data; its length is $MXACL.\n\n\n         -Tandem NSK Extra Field:\n          ======================\n\n          The following is the layout of the file-attributes extra block for\n          Tandem NSK.  The local-header and central-header versions are\n          identical.  (Last Revision 19981221)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (TA)    0x4154        Short       tag for this extra block type (\"TA\")\n          TSize         Short       total data size for this block (20)\n          NSKattrs      20 Bytes    NSK attributes\n\n\n         -THEOS Extra Field:\n          =================\n\n          The following is the layout of the file-attributes extra block for\n          Theos.  The local-header and central-header versions are identical.\n          (Last Revision 19990206)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Theos) 0x6854        Short       'Th' signature\n          size          Short       size of extra block\n          flags         Byte        reserved for future use\n          filesize      Long        file size\n          fileorg       Byte        type of file (see below)\n          keylen        Short       key length for indexed and keyed files,\n                                    data segment size for 16 bits programs\n          reclen        Short       record length for indexed,keyed and direct,\n                                    text segment size for 16 bits programs\n          filegrow      Byte        growing factor for indexed,keyed and direct\n          protect       Byte        protections (see below)\n          reserved      Short       reserved for future use\n\n            File types\n            ==========\n\n            0x80  library (keyed access list of files)\n            0x40  directory\n            0x10  stream file\n            0x08  direct file\n            0x04  keyed file\n            0x02  indexed file\n            0x0e  reserved\n            0x01  16 bits real mode program (obsolete)\n            0x21  16 bits protected mode program\n            0x41  32 bits protected mode program\n\n            Protection codes\n            ================\n\n            User protection\n            ---------------\n            0x01  non readable\n            0x02  non writable\n            0x04  non executable\n            0x08  non erasable\n\n            Other protection\n            ----------------\n            0x10  non readable\n            0x20  non writable\n            0x40  non executable Theos before 4.0\n            0x40  modified Theos 4.x\n            0x80  not hidden\n\n\n         -THEOS old inofficial Extra Field:\n          ================================\n\n          The following is the layout of an inoffical former version of a\n          Theos file-attributes extra blocks.  This layout was never published\n          and is no longer created. However, UnZip can optionally support it\n          when compiling with the option flag OLD_THEOS_EXTRA defined.\n          Both the local-header and central-header versions are identical.\n          (Last Revision 19990206)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (THS0)  0x4854        Short       'TH' signature\n          size          Short       size of extra block\n          flags         Short       reserved for future use\n          filesize      Long        file size\n          reclen        Short       record length for indexed,keyed and direct,\n                                    text segment size for 16 bits programs\n          keylen        Short       key length for indexed and keyed files,\n                                    data segment size for 16 bits programs\n          filegrow      Byte        growing factor for indexed,keyed and direct\n          reserved      3 Bytes     reserved for future use\n\n\n         -FWKCS MD5 Extra Field (0x4b46):\n          ==============================\n\n          The FWKCS Contents_Signature System, used in automatically\n          identifying files independent of filename, optionally adds\n          and uses an extra field to support the rapid creation of\n          an enhanced contents_signature.\n          There is no local-header version; the following applies\n          only to the central header.  (Last Revision 19961207)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (MD5)   0x4b46        Short       tag for this extra block type (\"FK\")\n          TSize         Short       total data size for this block (19)\n          \"MD5\"         3 bytes     extra-field signature\n          MD5hash       16 bytes    128-bit MD5 hash of uncompressed data\n                                    (low byte first)\n\n          When FWKCS revises a .ZIP file central directory to add\n          this extra field for a file, it also replaces the\n          central directory entry for that file's uncompressed\n          file length with a measured value.\n\n          FWKCS provides an option to strip this extra field, if\n          present, from a .ZIP file central directory. In adding\n          this extra field, FWKCS preserves .ZIP file Authenticity\n          Verification; if stripping this extra field, FWKCS\n          preserves all versions of AV through PKZIP version 2.04g.\n\n          FWKCS, and FWKCS Contents_Signature System, are\n          trademarks of Frederick W. Kantor.\n\n          (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer\n              Science and RSA Data Security, Inc., April 1992.\n              ll.76-77: \"The MD5 algorithm is being placed in the\n              public domain for review and possible adoption as a\n              standard.\"\n\n\n         -Microsoft Open Packaging Growth Hint (0xa220):\n          =============================================\n\n          Value         Size        Description\n          -----         ----        -----------\n          0xa220        Short       tag for this extra block type\n          TSize         Short       size of Sig + PadVal + Padding\n          Sig           Short       verification signature (A028)\n          PadVal        Short       Initial padding value\n          Padding       variable    filled with NULL characters\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/fileinfo.cms",
    "content": "[Quoting from a C/370 manual, courtesy of Carl Forde.]\n\n  C/370 supports three types of input and output: text streams, binary\n  streams, and record I/O.  Text and binary streams are both ANSI\n  standards; record I/O is a C/370 extension.\n\n[...]\n\n  Record I/O is a C/370 extension to the ANSI standard.  For files\n  opened in record format, C/370 reads and writes one record at a\n  time.  If you try to write more data to a record than the record\n  can hold, the data is truncated.  For record I/O, C/370 only allows\n  the use of fread() and fwrite() to read and write to the files.  Any\n  other functions (such as fprintf(), fscanf(), getc(), and putc())\n  fail.  For record-orientated files, records do not change size when\n  you update them.  If the new data has fewer characters than the\n  original record, the new data fills the first n characters, where\n  n is the number of characters of the new data.  The record will\n  remain the same size, and the old characters (those after) n are\n  left unchanged.  A subsequent update begins at the next boundary.\n  For example, if you have the string \"abcdefgh\":\n\n  abcdefgh\n\n  and you overwrite it with the string \"1234\", the record will look\n  like this:\n\n  1234efgh\n\n  C/370 record I/O is binary.  That is, it does not interpret any of\n  the data in a record file and therefore does not recognize control\n  characters.\n\n\n  The record model consists of:\n\n  * A record, which is the unit of data transmitted to and from a\n    program\n  * A block, which is the unit of data transmitted to and from a\n    device.  Each block may contain one or more records.\n\n  In the record model of I/O, records and blocks have the following\n  attributes:\n\n  RECFM   Specifies the format of the data or how the data is organized\n          on the physical device.\n  LRECL   Specifies the length of logical records (as opposed to\n          physical ones).\n\n  BLKSIZE Specifies the length of physical records (blocks on the\n          physical device).\n\n\n  Opening a File by Filename\n\n  The filename that you specify on the call to fopen() or freopen()\n  must be in the following format:\n\n  >> ----filename---- ----filetype--------------------\n                   |   |             |             |\n                   --.--             -- --filemode--\n                                     |   |\n                                     --.--\n  where\n\n  filename is a 1- to 8-character string of any of the characters,\n  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it\n  from the filetype with one or more spaces, or with a period.\n  [Further note:  filenames are fully case-sensitive, as in Unix.]\n\n  filetype is a 1- to 8-character string of any of the characters,\n  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it\n  from the filemode with one or more spaces, or with a period. The\n  separator between filetype and filemode must be the same as the\n  one between filename and filetype.\n\n  filemode is a 1- to 2-character string.  The first must be any of\n  the characters A-Z, a-z, or *.  If you use the asis parameter on\n  the fopen() or freopen() call, the first character of the filemode\n  must be a capital letter or an asterisk.  Otherwise, the function\n  call fails.  The second character of filemode is optional; if you\n  specify it, it must be any of the digits 0-6.  You cannot specify\n  the second character if you have specified * for the first one.\n\n  If you do not use periods as separators, there is no limit to how\n  much whitespace you can have before and after the filename, the\n  filetype, and filemode.\n\n\n  Opening a File without a File Mode Specified\n\n  If you omit the file mode or specify * for it, C/370 does one\n  of the following when you call fopen() or freopen():\n\n  * If you have specified a read mode, C/370 looks for the named file\n    on all the accessed readable disks, in order.  If it does not find\n    the file, the fopen() or freopen() call fails.\n  * If you have specified any of the write modes, C/370 writes the file\n    on the first writable disk you have accessed.  Specifying a write\n    mode on an fopen() or freopen() call that contains the filename of\n    an existing file destroys that file.  If you do not have any\n    writable disks accessed, the call fails.\n\n\n  fopen() and freopen() parameters\n\n  recfm\n     CMS supports only two RECFMs, V and F.  [note that MVS supports\n     27(!) different RECFMs.]  If you do not specify the RECFM for a\n     file, C/370 determines whether is is in fixed or variable format.\n\n  lrecl and blksize\n     For files in fixed format, CMS allows records to be read and\n     written in blocks.  To have a fixed format CMS file treated as a\n     fixed blocked CMS file, you can open the file with recfm=fb and\n     specify the lrecl and blksize.  If you do not specify a recfm on\n     the open, the blksize can be a multiple of the lrecl, and the\n     file is treated as if it were blocked.\n\n     For files in variable format, the CMS LRECL is different from the\n     LRECL for the record model.  In the record model, the LRECL is\n     equal to the data length plus 4 bytes (for the record descriptor\n     word), and the BLKSIZE  is equal to the LRECL plus 4 bytes (for\n     the block descriptor word).  In CMS, BDWs and RDWs do not exist,\n     but because CMS follows the record model, you must still account\n     for them.  When you specify V, you must still allocate the record\n     descriptor word and block descriptor word.  That is, if you want\n     a maximum of n bytes per record, you must specify a minimum LRECL\n     of n+4 and a minimum BLKSIZE of n+8.\n\n     When you are appending to V files, you can enlarge the record size\n     dynamically, but only if you have not specified LRECL or BLKSIZE\n     on the fopen() or freopen() command that opened the file.\n\n  type\n     If you specify this parameter, the only valid value for CMS disk\n     files is type =record. This opens a file for record I/O.\n\n  asis\n     If you use this parameter, you can open files with mixed-case\n     filenames such as JaMeS dAtA or pErCy.FILE.  If you specify this\n     parameter, the file mode that you specify must be a capital letter\n     (if it is not an asterisk); otherwise; the function call fails and\n     the value returned is NULL.\n\n\n  Reading from Record I/O Files\n     fread() is the only interface allowed for reading record I/O files.\n     Each time you call fread() for a record I/O file, fread() reads\n     one record from the system.  If you call fread() with a request for\n     less than a complete record, the requested bytes are copied to your\n     buffer, and the file position is set to the start fo the next\n     record.  If the request is for more bytes that are in the record,\n     one record is read and the position is set to the start of the next\n     record.  C/370 does not strip any blank characters or interpret any\n     data.\n\n     fread() returns the number of items read successfully, so if you\n     pass a size argument equal to 1 and a count argument equal to the\n     maximum expected length of the record, fread() returns the length,\n     in bytes, of the record read.  If you pass a size argument equal\n     to the maximum expected length of the record, and a count argument\n     equal to 1, fread() returns either 0 or 1, indicating whether a\n     record of length size read.  If a record is read successfully but\n     is less than size bytes long, fread() returns 0.\n\n\n  Writing to Record I/O Files\n     fwrite() is the only interface allowed for writing to a file\n     opened for record I/O.  Only one record is written at a time.  If\n     you attempt to write more new data than a full record can hold or\n     try to update a record with more data than it currently has, C/370\n     truncates your output at the record boundary.  When C/370 performs\n     a truncation, it sets errno and raises SIGIOERR, if SIGIOERR is not\n     set to SIG_IGN.\n\n     When you are writing new records to a fixed-record I/O file, if you\n     try to write a short record, C/370 pads the record with nulls out\n     to LRECL.\n\n     At the completion of an fwrite(), the file position is at the start\n     of the next record.  For new data, the block is flushed out to the\n     system as soon as it is full.\n\n\n  fldata() Behavior\n     When you call the fldata() function for an open CMS minidisk file,\n     it returns a data structure that looks like this:\n\n     struct __filedata {\n          unsigned int   __recfmF      : 1, /* fixed length records */\n                         __recfmV      : 1, /* variable length records */\n                         __recfmU      : 1, /* n/a */\n                         __recfmS      : 1, /* n/a */\n                         __recfmBlk    : 1, /* n/a */\n                         __recfmASA    : 1, /* text mode and ASA */\n                         __recfmM      : 1, /* n/a */\n                         __dsorgPO     : 1, /* n/a */\n                         __dsorgPDSmem : 1, /* n/a */\n                         __dsorgPDSdir : 1, /* n/a */\n                         __dsorgPS     : 1, /* sequential data set */\n                         __dsorgConcat : 1, /* n/a */\n                         __dsorgMem    : 1, /* n/a */\n                         __dsorgHiper  : 1, /* n/a */\n                         __dsorgTemp   : 1, /* created with tmpfile() */\n                         __dsorgVSAM   : 1, /* n/a */\n                         __reserve1    : 1, /* n/a */\n                         __openmode    : 2, /* see below 1 */\n                         __modeflag    : 4, /* see below 2 */\n                         __reserve2    : 9, /* n/a */\n\n          char           __device;  __DISK\n          unsigned long  __blksize,         /* see below 3 */\n                         __maxreclen;       /* see below 4 */\n          unsigned short __vsamtype;        /* n/a */\n          unsigned long  __vsamkeylen;      /* n/a */\n          unsigned long  __vsamRKP;         /* n/a */\n          char *         __dsname;          /* fname ftype fmode */\n          unsigned int   __reserve4;        /* n/a */\n\n          /* note 1: values are: __TEXT, __BINARY, __RECORD\n             note 2: values are: __READ, __WRITE, __APPEND, __UPDATE\n                     these values can be added together to determine\n                     the return value; for example, a file opened with\n                     a+ will have the value __READ + __APPEND.\n             note 3: total block size of the file, including ASA\n                     characters as well as RDW information\n             note 4: maximum record length of the data only (includes\n                     ASA characters but excludes RDW information).\n          */\n       };\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/nt.sd",
    "content": "Info-ZIP portable Zip/UnZip Windows NT security descriptor support\n==================================================================\nScott Field (sfield@microsoft.com), 8 October 1996\n\n\nThis version of Info-ZIP's Win32 code allows for processing of Windows\nNT security descriptors if they were saved in the .zip file using the\nappropriate Win32 Zip running under Windows NT.  This also requires\nthat the file system that Zip/UnZip operates on supports persistent\nAcl storage.  When the operating system is not Windows NT and the\ntarget file system does not support persistent Acl storage, no security\ndescriptor processing takes place.\n\nA Windows NT security descriptor consists of any combination of the\nfollowing components:\n\n       an owner (Sid)\n       a primary group (Sid)\n       a discretionary ACL (Dacl)\n       a system ACL (Sacl)\n       qualifiers for the preceding items\n\nBy default, Zip will save all aspects of the security descriptor except\nfor the Sacl.  The Sacl contains information pertaining to auditing of\nthe file, and requires a security privilege be granted to the calling\nuser in addition to being enabled by the calling application.  In order\nto save the Sacl during Zip, the user must specify the -! switch on the\nZip commandline.  The user must also be granted either the SeBackupPrivilege\n\"Backup files and directories\" or the SeSystemSecurityPrivilege \"Manage\nauditing and security log\".\n\nBy default, UnZip will not restore any aspects of the security descriptor.\nIf the -X option is specified to UnZip, the Dacl is restored to the file.\nThe other items in the security descriptor on the new file will receive\ndefault values.  If the -XX option is specified to UnZip, as many aspects\nof the security descriptor as possible will be restored.  If the calling\nuser is granted the SeRestorePrivilege \"Restore files and directories\",\nall aspects of the security descriptor will be restored.  If the calling\nuser is only granted the SeSystemSecurityPrivilege \"Manage auditing and\nsecurity log\", only the Dacl and Sacl will be restored to the new file.\n\nNote that when operating on files that reside on remote volumes, the\nprivileges specified above must be granted to the calling user on that\nremote machine.  Currently, there is no way to directly test what privileges\nare present on a remote machine, so Zip and UnZip make a remote privilege\ndetermination based on an indirect method.\n\nUnZip considerations\n--------------------\n\nIn order for file security to be processed correctly, any directory entries\nthat have a security descriptor will be processed at the end of the unzip\ncycle.  This allows for unzip to process files within the newly created\ndirectory regardless of the security descriptor associated with the directory\nentry.  This also prevents security inheritance problems that can occur as\na result of creating a new directory and then creating files in that directory\nthat will inherit parent directory permissions; such inherited permissions may\nprevent the security descriptor taken from the zip file from being applied\nto the new file.\n\nIf directories exist which match directory/extract paths in the .zip file,\nfile security is not updated on the target directory.  It is assumed that if\nthe target directory already exists, then appropriate security has already\nbeen applied to that directory.\n\n\"unzip -t\" will test the integrity of stored security descriptors when\npresent and the operating system is Windows NT.\n\nZipInfo (unzip -Z) will display information on stored security descriptor\nwhen \"unzip -Zv\" is specifed.\n\n\nPotential uses\n==============\n\nThe obvious use for this new support is to better support backup and restore\noperations in a Windows NT environment where NTFS file security is utilized.\nThis allows individuals and organizations to archive files in a portable\nfashion and transport these files across the organization.\n\nAnother potential use of this support is setup and installation.  This\nallows for distribution of Windows NT based applications that have preset\nsecurity on files and directories.  For example, prior to creation of the\n.zip file, the user can set file security via File Manager or Explorer on\nthe files to be contained in the .zip file.  In many cases, it is appropriate\nto only grant Everyone Read access to .exe and .dll files, while granting\nAdministrators Full control.  Using this support in conjunction with the\nunzipsfx.exe self-extractor stub can yield a useful and powerful way to\ninstall software with preset security (note that -X or -XX should be\nspecified on the self-extractor commandline).\n\nWhen creating .zip files with security which are intended for transport\nacross systems, it is important to take into account the relevance of\naccess control entries and the associated Sid of each entry.  For example,\nif a .zip file is created on a Windows NT workstation, and file security\nreferences local workstation user accounts (like an account named Fred),\nthis access entry will not be relevant if the .zip file is transported to\nanother machine.  Where possible, take advantage of the built-in well-known\ngroups, like Administrators, Everyone, Network, Guests, etc.  These groups\nhave the same meaning on any Windows NT machine.  Note that the names of\nthese groups may differ depending on the language of the installed Windows\nNT, but this isn't a problem since each name has well-known ID that, upon\nrestore, translates to the correct group name regardless of locale.\n\nWhen access control entries contain Sid entries that reference Domain\naccounts, these entries will only be relevant on systems that recognize\nthe referenced domain.  Generally speaking, the only side effects of\nirrelevant access control entries is wasted space in the stored security\ndescriptor and loss of complete intended access control.  Such irrelevant\naccess control entries will show up as \"Account Unknown\" when viewing file\nsecurity with File Manager or Explorer.\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/perform.dos",
    "content": "Date: Wed, 27 Mar 1996 01:31:50 CET +0100\nFrom: Christian Spieler (IKDA, THD, D-64289 Darmstadt)\nSubject: More detailed comparison of MSDOS Info-ZIP programs' performance\n\nHello all,\n\nIn response to some additional questions and requests concerning\nmy previous message about DOS performance of 16/32-bit Info-ZIP programs,\nI have produced a more detailed comparison:\n\nSystem:\nCx486DX-40, VL-bus, 8MB; IDE hard disk;\nDOS 6.2, HIMEM, EMM386 NOEMS NOVCPI, SMARTDRV 3MB, write back.\n\nI have used the main directory of UnZip 5.20p as source, including the\nobjects and executable of an EMX compile for unzip.exe (to supply some\nbinary test files).\n\nTested programs were (my current updated sources!) Zip 2.0w and UnZip 5.20p\n- 16-bit MSC 5.1, compressed with LZEXE 0.91e\n- 32-bit Watcom C 10.5, as supplied by Kai Uwe Rommel (PMODE 1.22)\n- 32-bit EMX 0.9b\n- 32-bit DJGPP v2\n- 32-bit DJGPP v1.12m4\n\nThe EMX and DJ1 (GO32) executables were bound with the full extender, to\ncreate standalone executables.\n\nA) Tests of Zip\n  Command :  \"<system>\\zip.exe -q<#> tes.zip unz/*\"  (unz/*.* for Watcom!!)\n             where <#> was: 0, 1, 6, 9.\n             The test archive \"tes.zip\" was never deleted, this test\n             measured \"time to update archive\".\n\n  The following table contains average execution seconds (averaged over\n  at least 3 runs, with the first run discarted to fill disk cache);\n  numbers in parenteses specify the standard deviation of the last\n  digits.\n\n  cmpr level|      0     |      1     |      6     |      9\n ===============================================================\n  EMX win95 |   7.77     |   7.97     |  12.82     |  22.31\n ---------------------------------------------------------------\n  EMX       |   7.15(40) |   8.00(6)  |  12.52(25) |  20.93\n  DJ2       |  13.50(32) |  14.20(7)  |  19.05     |  28.48(9)\n  DJ1       |  13.56(30) |  14.48(3)  |  18.70     |  27.43(13)\n  WAT       |   6.94(22) |   8.93     |  15.73(34) |  30.25(6)\n  MSC       |   5.99(82) |   9.40(4)  |  13.59(9)  |  20.77(4)\n ===============================================================\n\n The \"EMX win95\" line was created for comparison, to check the performance\n of emx 0.9 with the RSX extender in a DPMI environment. (This line was\n produced by applying the \"stubbed\" EMX executable in a full screen DOS box.)\n\n\nB) Tests of UnZip\n  Commands :  <system>\\unzip.exe -qt tes.zip         (testing performance)\n              <system>\\unzip.exe -qo tes.zip -dtm    (extracting performance)\n\n  The tes.zip archive created by maximum compression with the Zip test\n  was used as example archive. Contents (archive size was 347783 bytes):\n   1028492 bytes uncompressed, 337235 bytes compressed, 67%, 85 files\n\n  The extraction directory tm was not deleted between the individual runs,\n  thus this measurement checks the \"overwrite all\" time.\n\n           |     testing               |          extracting\n  ===================================================================\n  EMX      |       1.98                |         6.43(8)\n  DJ2      |       2.09                |        11.85(39)\n  DJ1      |       2.09                |         7.46(9)\n  WAT      |       2.42                |         7.10(27)\n  MSC      |       4.94                |         9.57(31)\n\nRemarks:\n\nThe executables compiled by me were generated with all \"performance\"\noptions enabled (ASM_CRC, and ASMV for Zip), and with full crypt support.\nFor DJ1 and DJ2, the GCC options were \"-O2 -m486\", for EMX \"-O -m486\".\n\nThe Watcom UnZip was compiled with ASM_CRC code enabled as well,\nbut the Watcom Zip example was made without any optional assembler code!\n\n\n\nDiscussion of the results:\n\nIn overall performance, the EMX executables clearly win.\nFor UnZip, emx is by far the fastest program, and the Zip performance is\ncomparable to the 16-bit \"reference\".\n\nWhenever \"real\" work including I/O is requested, the DJGPP versions\nlose badly because of poor I/O performance, this is the case especially\nfor the \"newer\" DJGPP v2 !!!\n(I tried to tweak with the transfer buffer size, but without any success.)\nAn interesting result is that DJ v1 UnZip works remarkably better than\nDJ v2 (in contrast to Zip, where both executables' performance is\napproximately equal).\n\nThe Watcom C programs show a clear performance deficit in the \"computational\npart\" (Watcom C compiler produces code that is far from optimal), but\nthe extender (which is mostly responsible for the I/O throughput) seems\nto be quite fast.\n\nThe \"natural\" performance deficit of the 16-bit MSC code, which can be\nclearly seen in the \"testing task\" comparison for UnZip, is (mostly,\nfor Zip more than) compensated by the better I/O throughput (due to the\n\"direct interface\" between \"C RTL\" and \"DOS services\", without any mode\nswitching).\n\nBut performance is only one aspect when choosing which compiler should\nbe used for official distribution:\n\nSizes of the executables:\n    |             Zip                ||           UnZip\n    | standalone           stub      || standalone    |     stub\n======================================================================\nEMX | 143,364  (1) |    94,212       ||  159,748  (1) |   110,596\nDJ2 | 118,272  (2) |       --        ||  124,928  (2) |      --\nDJ1 | 159,744      |    88,064       ||  177,152      |   105,472\nWAT | 140,073      |       --        ||  116,231      |      --\nMSC |  49,212  (3) |       --        ||   45,510  (3) |      --\n\n(1) does not run in \"DPMI only\" environment (Windows DOS box)\n(2) requires externally supplied DPMI server\n(3) compressed with LZexe 0.91\n\nCaveats/Bugs/Problems of the different extenders:\n\nEMX:\n- requires two different extenders to run in all DOS-compatible environments,\n  EMX for \"raw/himem/vcpi\" and RSX for \"dpmi\" (Windows).\n- does not properly support time zones (no daylight savings time)\n\nDJv2:\n- requires an external (freely available) DPMI extender when run on plain\n  DOS; this extender cannot (currently ??) be bound into the executable.\n\nDJv1:\n- uses up large amount of \"low\" dos memory (below 1M) when spawning\n  another program, each instance of a DJv1 program requires its private\n  GO32 extender copy in low dos memory (may be problem for the zip\n  \"-T\" feature)\n\nWatcom/PMODE:\n- extended memory is allocated statically (default: ALL available memory)\n  This means that a spawned program does not get any extended memory.\n  You can work around this problem by setting a hard limit on the amount\n  of extended memory available to the PMODE program, but this limit is\n  \"hard\" and restricts the allocatable memory for the program itself.\n  In detail:\n  The Watcom zip.exe as distributed did not allow the \"zip -T\" feature;\n  there was no extended memory left to spawn unzip.\n  I could work around this  problem by applying PMSETUP to change the\n  amount of allocated extended memory to 2.0 MByte (I had 4MB free extended\n  memory on my test system). But, this limit cannot be enlarged at\n  runtime, when zip needs more memory to store \"header info\" while\n  zipping up a huge drive, and on a system with less free memory, this\n  method is not applicable, either.\n\nSummary:\n\nFor Zip:\nUse the 16-bit executable whenever possible (unless you need the\nlarger memory capabilities when zipping up a huge amount of files)\n\nAs 32-bit executable, we may distribute Watcom C (after we have confirmed\nthat enabling ASMV and ASM_CRC give us some better computational\nperformance.)\nThe alternative for 32-bit remains DJGPP v1, which shows the least problems\n(to my knowledge); v2 and EMX cannot be used because of their lack of\n\"universality\".\n\nFor UnZip:\nHere, the Watcom C 32-bit executable is probably the best compromise,\nbut DJ v1 could be used as well.\nAnd, after all, the 16-bit version does not lose badly when doing\n\"real\" extraction! For the SFX stub, the 16-bit version remains first\nchoice because of its much smaller size!\n\nBest regards\n\nChristian Spieler\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/timezone.txt",
    "content": "Timezone strings:\n-----------------\nThis is a description of valid timezone strings for ENV[ARC]:TZ:\n\"XPG3TZ - time zone information\"\nThe form of the time zone information is based on the XPG3 specification of\nthe TZ environment variable.  Spaces are allowed only in timezone\ndesignations, where they are significant.  The following description\nclosely follows the XPG3 specification, except for the paragraphs starting\n**CLARIFICATION**.\n\n<std><offset>[<dst>[<offset>],<start>[/<time>],<end>[/<time>]]\n\nWhere:\n<std> and <dst>\n      Are each three or more bytes that are the designation for the\n      standard (<std>) and daylight savings time (<dst>) timezones.\n      Only <std> is required - if <dst> is missing, then daylight\n      savings time does not apply in this locale.  Upper- and\n      lower-case letters are allowed.  Any characters except a\n      leading colon (:), digits, a comma (,), a minus (-) or a plus\n      (+) are allowed.\n      **CLARIFICATION**  The two-byte designation `UT' is permitted.\n<offset>\n      Indicates the value one must add to the local time to arrive\n      at Coordinated Universal Time.  The offset has the form:\n      <hh>[:<mm>[:<ss>]]\n      The minutes <mm> and seconds <ss> are optional.  The hour <hh>\n      is required and may be a single digit.  The offset following\n      <std> is required.  If no offset follows <dst>, daylight savings\n      time is assumed to be one hour ahead of standard time.  One or\n      more digits may be used; the value is always interpreted as a\n      decimal number.  The hour must be between 0 and 24, and the\n      minutes (and seconds) if present between 0 and 59.  Out of\n      range values may cause unpredictable behavior.  If preceded by\n      a `-', the timezone is east of the Prime Meridian; otherwise\n      it is west (which may be indicated by an optional preceding\n      `+' sign).\n      **CLARIFICATION**  No more than two digits are allowed in any\n      of <hh>, <mm> or <ss>.  Leading zeros are permitted.\n<start>/<time> and <end>/<time>\n      Indicates when to change to and back from daylight savings\n      time, where <start>/<time> describes when the change from\n      standard time to daylight savings time occurs, and\n      <end>/<time> describes when the change back happens.  Each\n      <time> field describes when, in current local time, the change\n      is made.\n      **CLARIFICATION**  It is recognized that in the Southern\n      hemisphere <start> will specify a date later than <end>.\n      The formats of <start> and <end> are one of the following:\n      J<n>    The Julian day <n> (1 <= <n> <= 365).  Leap days are not\n              counted.  That is, in all years, February 28 is day 59\n              and March 1 is day 60.  It is impossible to refer to\n              the occasional February 29.\n      <n>     The zero-based Julian day (0 <= <n> <= 365).  Leap days\n              are counted, and it is possible to refer to February\n              29.\n      M<m>.<n>.<d>\n              The <d>th day, (0 <= <d> <= 6) of week <n> of month <m>\n              of the year (1 <= <n> <= 5, 1 <= <m> <= 12), where week\n              5 means `the last <d>-day in month <m>' (which may\n              occur in either the fourth or the fifth week).  Week 1\n              is the first week in which the <d>th day occurs.  Day\n              zero is Sunday.\n              **CLARIFICATION**  Neither <n> nor <m> may have a\n              leading zero.  <d> must be a single digit.\n              **CLARIFICATION**  The default <start> and <end> values\n              are from the first Sunday in April until the last Sunday\n              in October.  This allows United States users to leave out\n              the <start> and <end> parts, as most are accustomed to\n              doing.\n      <time> has the same format as <offset> except that no leading\n      sign (`-' or `+') is allowed.  The default, if <time> is not\n      given is 02:00:00.\n      **CLARIFICATION**  The number of hours in <time> may be up\n      to 167, to allow encoding of rules such as `00:00hrs on the\n      Sunday after the second Friday in September'\n\nExample (for Central Europe):\n-----------------------------\nMET-1MEST,M3.5.0,M10.5.0/03\n\nAnother example, for the US East Coast:\n---------------------------------------\nEST5EDT4,M4.1.0/02,M10.5.0/02\nThis string describes the default values when no time zone is set.\n"
  },
  {
    "path": "deps/infozip/unzip60/proginfo/ziplimit.txt",
    "content": "ziplimit.txt\n\nA1) Hard limits of the Zip archive format (without Zip64 extensions):\n\n   Number of entries in Zip archive:            64 Ki (2^16 - 1 entries)\n   Compressed size of archive entry:            4 GiByte (2^32 - 1 Bytes)\n   Uncompressed size of entry:                  4 GiByte (2^32 - 1 Bytes)\n   Size of single-volume Zip archive:           4 GiByte (2^32 - 1 Bytes)\n   Per-volume size of multi-volume archives:    4 GiByte (2^32 - 1 Bytes)\n   Number of parts for multi-volume archives:   64 Ki (2^16 - 1 parts)\n   Total size of multi-volume archive:          256 TiByte (4G * 64k)\n\n   The number of archive entries and of multivolume parts are limited by\n   the structure of the \"end-of-central-directory\" record, where the these\n   numbers are stored in 2-Byte fields.\n   Some Zip and/or UnZip implementations (for example Info-ZIP's) allow\n   handling of archives with more than 64k entries.  (The information\n   from \"number of entries\" field in the \"end-of-central-directory\" record\n   is not really neccessary to retrieve the contents of a Zip archive;\n   it should rather be used for consistency checks.)\n\n   Length of an archive entry name:             64 KiByte (2^16 - 1)\n   Length of archive member comment:            64 KiByte (2^16 - 1)\n   Total length of \"extra field\":               64 KiByte (2^16 - 1)\n   Length of a single e.f. block:               64 KiByte (2^16 - 1)\n   Length of archive comment:                   64 KiByte (2^16 - 1)\n\n   Additional limitation claimed by PKWARE:\n     Size of local-header structure (fixed fields of 30 Bytes + filename\n      local extra field):                     < 64 KiByte\n     Size of central-directory structure (46 Bytes + filename +\n      central extra field + member comment):  < 64 KiByte\n\nA2) Hard limits of the Zip archive format with Zip64 extensions:\n   In 2001, PKWARE has published version 4.5 of the Zip format specification\n   (together with the release of PKZIP for Windows 4.5).  This specification\n   defines new extra field blocks that allow to break the size limits of the\n   standard zipfile structures.  This extended \"Zip64\" format enlarges the\n   theoretical limits to the following values:\n\n   Number of entries in Zip archive:            16 Ei (2^64 - 1 entries)\n   Compressed size of archive entry:            16 EiByte (2^64 - 1 Bytes)\n   Uncompressed size of entry:                  16 EiByte (2^64 - 1 Bytes)\n   Size of single-volume Zip archive:           16 EiByte (2^64 - 1 Bytes)\n   Per-volume size of multi-volume archives:    16 EiByte (2^64 - 1 Bytes)\n   Number of parts for multi-volume archives:   4 Gi (2^32 - 1 parts)\n   Total size of multi-volume archive:          2^96 Byte (16 Ei * 4Gi)\n\n   The Info-ZIP software releases (beginning with Zip 3.0 and UnZip 6.0)\n   support Zip64 archives on selected environments (where the underlying\n   operating system capabilities are sufficient, e.g. Unix, VMS and Win32).\n\nB) Implementation limits of UnZip:\n\n 1. Size limits caused by file I/O and decompression handling:\n   a) Without \"Zip64\" and \"LargeFile\" extensions:\n    Size of Zip archive:                2 GiByte (2^31 - 1 Bytes)\n    Compressed size of archive entry:   2 GiByte (2^31 - 1 Bytes)\n\n   b) With \"Zip64\" enabled and \"LargeFile\" supported:\n    Size of Zip archive:                8 EiByte (2^63 - 1 Bytes)\n    Compressed size of archive entry:   8 EiByte (2^63 - 1 Bytes)\n    Uncompressed size of entry:         8 EiByte (2^63 - 1 Bytes)\n\n   Note: On some systems, even UnZip without \"LargeFile\" extensions enabled\n         may support archive sizes up to 4 GiByte.  To get this support, the\n         target environment has to meet the following requirements:\n         a) The compiler's intrinsic \"long\" data types must be able to hold\n            integer numbers of 2^32. In other words - the standard intrinsic\n            integer types \"long\" and \"unsigned long\" have to be wider than\n            32 bit.\n         b) The system has to supply a C runtime library that is compatible\n            with the more-than-32-bit-wide \"long int\" type of condition a)\n         c) The standard file positioning functions fseek(), ftell() (and/or\n            the Unix style lseek() and tell() functions) have to be capable\n            to move to absolute file offsets of up to 4 GiByte from the file\n            start.\n         On 32-bit CPU hardware, you generally cannot expect that a C compiler\n         provides a \"long int\" type that is wider than 32-bit. So, many of the\n         most popular systems (i386, PowerPC, 680x0, et. al) are out of luck.\n         You may find environment that provide all requirements on systems\n         with 64-bit CPU hardware. Examples might be Cray number crunchers,\n         Compaq (former DEC) Alpha AXP machines, or Intel/AMD x64 computers.\n\n   The number of Zip archive entries is unlimited. The \"number-of-entries\"\n   field of the \"end-of-central-dir\" record is checked against the \"number\n   of entries found in the central directory\" modulus 64k (2^16) (without\n   Zip64 extension) or modulus 2^64 (with Zip64 extensions enabled for\n   Zip64 archives).\n\n   Multi-volume archive extraction is not (yet) supported.\n\n   Memory requirements are mostly independent of the archive size\n   and archive contents.\n   In general, UnZip needs a fixed amount of internal buffer space\n   plus the size to hold the complete information of the currently\n   processed entry's local header. Here, a large extra field\n   (could be up to 64 kByte) may exceed the available memory\n   for MSDOS 16-bit executables (when they were compiled in small\n   or medium memory model, with a fixed 64 KiByte limit on data space).\n\n   The other exception where memory requirements scale with \"larger\"\n   archives is the \"restore directory attributes\" feature. Here, the\n   directory attributes info for each restored directory has to be held\n   in memory until the whole archive has been processed. So, the amount\n   of memory needed to keep this info scales with the number of restored\n   directories and may cause memory problems when a lot of directories\n   are restored in a single run.\n\nC) Implementation limits of the Zip executables:\n\n 1. Size limits caused by file I/O and compression handling:\n   a) Without \"Zip64\" and \"LargeFile\" extensions:\n    Size of Zip archive:                2 GiByte (2^31 - 1 Bytes)\n    Compressed size of archive entry:   2 GiByte (2^31 - 1 Bytes)\n    Uncompressed size of entry:         2 GiByte (2^31 - 1 Bytes),\n                                        (could/should be 4 GiBytes...)\n\n   b) With \"Zip64\" enabled and \"LargeFile\" supported:\n    Size of Zip archive:                8 EiByte (2^63 - 1 Bytes)\n    Compressed size of archive entry:   8 EiByte (2^63 - 1 Bytes)\n    Uncompressed size of entry:         8 EiByte (2^63 - 1 Bytes)\n\n   Multi-volume archive creation now supported in the form of split\n   archives.  Currently up to 99,999 splits are supported.\n\n 2. Limits caused by handling of archive contents lists\n\n 2.1. Number of archive entries (freshen, update, delete)\n     a) 16-bit executable:              64k (2^16 -1) or 32k (2^15 - 1),\n                                        (unsigned vs. signed type of size_t)\n     a1) 16-bit executable:             <16k ((2^16)/4)\n         (The smaller limit a1) results from the array size limit of\n         the \"qsort()\" function.)\n\n         32-bit executable:             <1G ((2^32)/4)\n         (usual system limit of the \"qsort()\" function on 32-bit systems)\n\n         64-bit executable:             <2Ei ((2^64)/8)\n         (theoretical limit of 64-bit flat memory model, the actual limit of\n         currently available OS implementations is several orders of magnitude\n         lower)\n\n     b) stack space needed by qsort to sort list of archive entries\n\n     NOTE: In the current executables, overflows of limits a) and b) are NOT\n           checked!\n\n     c) amount of free memory to hold \"central directory information\" of\n        all archive entries; one entry needs:\n        128 bytes (Zip64), 96 bytes (32-bit) resp. 80 bytes (16-bit)\n        + 3 * length of entry name\n        + length of zip entry comment (when present)\n        + length of extra field(s) (when present, e.g.: UT needs 9 bytes)\n        + some bytes for book-keeping of memory allocation\n\n   Conclusion:\n     For systems with limited memory space (MSDOS, small AMIGAs, other\n     environments without virtual memory), the number of archive entries\n     is most often limited by condition c).\n     For example, with approx. 100 kBytes of free memory after loading and\n     initializing the program, a 16-bit DOS Zip cannot process more than 600\n     to 1000 (+) archive entries.  (For the 16-bit Windows DLL or the 16-bit\n     OS/2 port, limit c) is less important because Windows or OS/2 executables\n     are not restricted to the 1024k area of real mode memory.  These 16-bit\n     ports are limited by conditions a1) and b), say: at maximum approx.\n     16000 entries!)\n\n\n 2.2. Number of \"new\" entries (add operation)\n     In addition to the restrictions above (2.1.), the following limits\n     caused by the handling of the \"new files\" list apply:\n\n     a) 16-bit executable:              <16k ((2^64)/4)\n\n     b) stack size required for \"qsort\" operation on \"new entries\" list.\n\n     NOTE: In the current executables, the overflow checks for these limits\n           are missing!\n\n     c) amount of free memory to hold the directory info list for new entries;\n        one entry needs:\n        32 bytes (Zip64), 24 bytes (32-bit) resp. 22 bytes (16-bit)\n        + 3 * length of filename\n\n     NOTE: For larger systems, the actual usability limits may be more\n     performance issues (how long you want to wait) rather than available\n     memory and other resources.\n\nD) Some technical remarks:\n\n 1. For executables without support for \"Zip64\" archives and \"LargeFile\"\n    I/O extensions, the 2GiByte size limit on archive files is a consequence\n    of the portable C implementation used for the Info-ZIP programs.\n    Zip archive processing requires random access to the archive file for\n    jumping between different parts of the archive's structure.\n    In standard C, this is done via stdio functions fseek()/ftell() resp.\n    unix-io functions lseek()/tell().  In many (most?) C implementations,\n    these functions use \"signed long\" variables to hold offset pointers\n    into sequential files.  In most cases, this is a signed 32-bit number,\n    which is limited to ca. 2E+09.  There may be specific C runtime library\n    implementations that interpret the offset numbers as unsigned, but for\n    us, this is not reliable in the context of portable programming.\n\n 2. Similarly, for executables without \"Zip64\" and \"LargeFile\" support,\n    the 2GiByte limit on the size of a single compressed archive member\n    is again a consequence of the implementation in C.\n    The variables used internally to count the size of the compressed\n    data stream are of type \"long\", which is guaranted to be at least\n    32-bit wide on all supported environments.\n\n    But, why do we use \"signed\" long and not \"unsigned long\"?\n\n    Throughout the I/O handling of the compressed data stream, the sign bit\n    of the \"long\" numbers is (mis-)used as a kind of overflow detection.\n    In the end, this is caused by the fact that standard C lacks any\n    overflow checking on integer arithmetics and does not support access\n    to the underlying hardware's overflow detection (the status bits,\n    especially \"carry\" and \"overflow\" of the CPU's flags-register) in a\n    system-independent manner.\n\n    So, we \"misuse\" the most-significant bit of the compressed data size\n    counters as carry bit for efficient overflow/underflow detection.  We\n    could change the code to a different method of overflow detection, by\n    using a bunch of \"sanity\" comparisons (kind of \"is the calculated result\n    plausible when compared with the operands\"). But, this would \"blow up\"\n    the code of the \"inner loop\", with remarkable loss of processing speed.\n    Or, we could reduce the amount of consistency checks of the compressed\n    data (e.g. detection of premature end of stream) to an absolute minimum,\n    at the cost of the programs' stability when processing corrupted data.\n\n 3. The argumentation above is somewhat out-dated. Beginning with the\n    releases of Zip 3 and UnZip 6, Info-ZIP programs support archive\n    sizes larger than 4GiB on systems where the required underlying\n    support for 64-bit file offsets and file sizes is available from\n    the OS (and the C runtime environment).\n\n    For executables with support for \"Zip64\" archive format and \"LargeFile\"\n    extension, the I/O limits are lifted by applying extended 64-bit off_t\n    file offsets.  All limits discussed above are then based on integer\n    sizes of 64 bits instead of 32, this should allow to handle file and\n    archive sizes up to the limits of manufacturable hardware for the\n    foreseeable future.  The reduction of the theoretical limits from\n    (2^64 - 1) to (2^63 - 1) because of the throughout use of signed\n    numbers can be neglected with the currently imaginable hardware.\n\n    However, this new support partially breaks compatibility with older\n    \"legacy\" systems.  And it should be noted that the portability and\n    readability of the UnZip and Zip code has suffered somehow caused\n    by the extensive use of non-standard language extension needed for\n    64-bit support on the major target systems.\n\nPlease report any problems to:  Zip-Bugs at www.info-zip.org\n\nLast updated:  25 May 2008, Ed Gordon\n               02 January 2009, Christian Spieler\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/Contents",
    "content": "Contents of the \"qdos\" subdirectory for UnZip 5.4 and later:\n\n  Contents      this file\n  IZREADME.SMS  release notes from Jonathan Hudson (author of port)\n  Makefile      makefile for xtc68 cross-compiler on Linux (native QDOS exes)\n  callstub.c    user interface stub for SMS/QDOS specific SFX archives\n  config.S      assembler routine for ...?\n  crc68.s       68000 version of CRC code\n  izqdos.h      SMS/QDOS-specific header file\n  makesfx.c     source for MakeSFX utility (simple concatenation does not work)\n  qdos.c        SMS/QDOS-specific functions\n\nNotes:\n\n  \"Makefile\" is for the xtc68 cross compiler on Linux, but conversion to a\n  native c68 makefile should be trivial.  To build a Linux (or other Unix)\n  UnZip that understands QDOS extra fields, add \"-DQLZIP\" to the LOCAL_UNZIP\n  environment variable and compile with the normal Unix makefile (for example,\n  linux_asm target).  The \"QLZIP\" flag enables the Qdos \"cross-UnZip\" support\n  in unix/unix.c.\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/IZREADME.SMS",
    "content": "IZREADME_SMS (IZREADME.SMS): Info-ZIP for SMS/QDOS,   last revised: 15-Jun-1998\n===============================================================================\n[was \"InfoZIP_SMSQDOS_ReadMe\" in J. Hudson's original ports, ca. 08/1995]\n\nInfo-ZIP Programs\n=================\n\nZip\nUnZip\nUnZipSFX\nfUnZip\n\nIntroduction\n------------\n\nThis archive is a result of frustrations with contemporary (August 95)\nversions of Zip and UnZip. While they use the same compression\nalgorithms as the Info-ZIP programs, there the compatibility ends. If\nyou just use Zip/UnZip only on SMS/QDOS, then perhaps this is not a\nproblem (but I know for some users it still is); if you use Zip/UnZip\nto transport source code and data between diverse systems, then the\ndisregard for Info-ZIP standards is inconvenient, particularly the\nfact that directories are not supported and files are always stored\nunderscored.\n\nThis release of Zip/UnZip offers:\n\n    o   zipfile/directory compatibility with all other supported\n        platforms\n\n    o   SMS/QDOS compatibility and back-compatible with earlier\n        versions.\n\n    o   Improved performance (Zip is typically 50% faster)\n\n    o   Command-line compatibility with Info-ZIP\n\n    o   Self-extracting archives (but not very elegantly)\n\n    o   Archives are marked as 'created by SMS/QDOS'.\n\n    o   Optional recursion into directories\n\n    o   Directory structure restored on unzip of Info-ZIP/PKZIP-\n        compatible archives.\n\n    o   Config'urable for listing and unpack formats (Info-ZIP (.) or\n        SMS/QDOS (_) and 'Press any key' timeouts. Override options\n        from command line.\n\nInfo-ZIP Standards\n------------------\n\nThis (rather long-winded and waffling) section discusses the\nconventions and standards used by Info-ZIP-compatible archivers and how\n\"Info-ZIP for SMS/QDOS\" achieves compatibility.\n\nInfo-ZIP Zip/UnZip on all supported platforms (Unix, DOS, OS/2, NT,\nVAX/VMS, Amiga etc etc), works in a specific way. (Until now SMS/QDOS\nwas neither 'supported' nor Info-ZIP-compliant.)\n\n    a. The zipfile directory is in (/.) (Unix) format.\n\n    b. When zips are listed, it is in 'zipfile' (Unix) format.\n\n    c. When files are added, they are defined in native format.\n\n    d. When files are added, this is shown in 'zipfile' format.\n\n    e. When files are unpacked, this is done to native format, but\n       selection is done in 'zipfile' format.\n\nBasically, the listing and stored format of a file is that of the\ndestination.\n\nSo, given a file structure at some arbitrary 'root' level.\n\n    Makefile\n    src (Dir)\n        afile.c\n        bfile.c\n        docs (Dir)\n             prog.txt\n    hdr (Dir)\n        cfile.h\n        dfile.h\n\nThen these would be in Unix (and Amiga) as\n\n     Makefile\n     src/afile.c\n     src/bfile.c\n     src/docs/prog.txt\n     hdr/cfile.h\n     hdr/dfile.h\n\nThis is also how the zipfile directory appears.\n\nAnd in DOS/OS2/NT\n\n    Makefile\n    src\\afile.c\n    src\\docs\\prog.txt\n    hdr\\cfile.h         .. etc\n\nAnd in VMS      (we SHOUT in VMS and have a silly file system)\n\n    MAKEFILE\n    [SRC]AFILE.C\n    [SRC.DOC]PROG.TXT\n    [HDR]CFILE.H        .. etc\n                        (OK VMS purist, [.SRC] etc. Only an example)\n\nAnd in SMS/QDOS (quiet again, but slightly ludicrous !)\n\n    Makefile\n    src_afile_c\n    src_doc_prog_txt\n    hdr_cfile_h         .. etc\n\nThe main problem regarding SMS/QDOS is not that of extensions - (after\nall, only VMS and DOS _really_ have extensions; Unix, AmigaDOS, NT and\nOS/2 (and Win95) allow multiple '.' in.long.file.names.\n\nThe SMS/QDOS problem is that '_' is both a legal file name character\nand a directory separator. This creates the difficulties, as\ndirectories and files are somewhat different objects.\n\nIt is the intention that these versions of SMS/QDOS Zip/UnZip will\nfollow the Info-ZIP rules, thus providing compatibility with the other\nplatforms. It is possible to zip the file structure described above on\nSMS/QDOS and unpack it on VMS and get the VMS structure as shown in the\nexample (and vice-versa). [We only choose the most obtuse file\nsystems for the examples].\n\nIn order to achieve this, SMS/QDOS names are mapped into Unix-style\nones when the zipfile is created and un-mapped when it is unpacked.\nThere is an option to unpack in 'zipfile' format (i.e. with '.' rather\nthan '_'), but there will be no option to pack to all '_'. That would\ncontravene the standard.  However, a file\n\n        src_split_name_c        (which is src->split_name_c !)\n                                          src/split_name.c)\n\nwhere src is a hard directory, would be stored in the zip directory as\n\n      src/split_name.c\n\nIt does handle '_' with a little intelligence.\n\nThe default UnZip option will be to translate '.' to '_'; this is\nbecause there are still many QDOS/Minerva users that cannot handle '.'\nwithout quotes, which is immensely inconvenient. For many SMS users\n'_' is also the most natural and convenient option. It also means that\nSMS/QDOS <-> SMS/QDOS Zip - UnZip sequences are transparent.\n\nThere will, however, be two ways around this in UnZip.\n\n      1. It is possible to Config the UnZip default to be '.'\n         translations (or not).\n\n      2.  The UnZip -Q1 option will toggle the default (Config'ed)\n          state.\n\nExamples:\n\nGiven that we want/have\n\n     Makefile                   (Makefile)\n     src/afile.c                (src_afile_c)\n     src/bfile.c                (src_bfile_c)\n     src/docs/prog.txt          (src_docs_prog_txt)\n     hdr/cfile.h                (hdr_cfile_h)\n     hdr/dfile.h                (hdr_dfile_h)\n\nThen on SMS/QDOS we might have added the *.c files as\n\n     ex zip;'-r test *_c'\n\n(or VMS, just to do something different)\n\n    zip -r test [.src]*.c\n\nIn both cases the file lists as above (left).\n\nTo unpack on SMS/QDOS (just the _c/.c files)\n\n   ex unzip;'test src/*.c'\n\n   (and VMS, unzip test src/*.c)\n\ni.e. in both cases using the 'zipfile' format. As a concession to\nSMS/QDOS, you could also have:\n\n   ex unzip;'test src_*_c'\n\n        but not unzip test [.src]*.c on VMS !!!!! Sorry, dinosaurs.\n\nBoth SMS/QDOS commands unpack to\n\n     src_afile_c etc, where src_ is a hard sub-directory.\n\n(and the VMS example would unpack to [.src]afile.c, (or to src\\afile.c on\nDOS/NT/OS2 etc).\n\nOptions & SMS/QDOS Features\n---------------------------\n\nThe options supported by Zip/UnZip are basically those documented in\nthe Info-ZIP documents and shown in on-line 'usage'. In particular, -r\nand -j work as intended.\n\nPLEASE NOTE: Previous SMS/QDOS zip/unzips have NOT followed these\nconventions, for example -r was not implemented and -j was reversed.\n\nA number of -Q (SMS/QDOS-specific) options (not yet in the current\ndocuments or usage screens) are implemented.\n\nThe Zip 2.0.1 (and later) default is to add SMS/QDOS headers where\nfile type = 1 (exe) or 2 (rel) or (type > 0 && != 255 and (filesize %\n64) != 0). Directories are included anyway, unless you zip -D.\n\nWhere a header is added for an 'exe' file a '*' is displayed after the\nname in the zip display  (and '#' for 'rel' files).\n\nThe -Q options for Zip are:\n\n    -Q1  Don't add headers for ANY files\n    -Q2  Add headers for all files\n    -Q4  Don't wait for interactive key press\n\n    (additive, so -Q5 => no headers, no wait, -Q6 all headers,\n     no wait etc)\n\n    (the default is exec/rel headers, 5 sec wait)\n\nZip has rationalised the file header storage in zipfiles. The\nprevious Zip used to store a QDOS header for each file. This was very\nwasteful, for example compressing a SMS/QDOS release of PGP in this\nway came to 730Kb, too large for a DD disk. Changing the Zip program\njust to add a header record for the single PGP exe and the zipfile\nsize went down to around 690Kb.\n\nAnd for UnZip\n\n    -Q1 Toggle unpack format status ('.' <-> '_')\n    -Q2 Toggle listing format\n    -Q4 Don't wait for key press\n\nFiles Types\n-----------\n\nThe history of QDOS suffers from incompatible feature\nimplementations. For example, Thor directories have file type 3, CST\nhave type 4 and Level 2 have type 255. Some software writers (both\namateur and otherwise) have used type 3 or 4 for other purposes\n(backward compatibility ?? who cares ??).\n\nIn order to bypass problems cause by incompatible (inconsiderate ?)\nusage of file types, the file type denoting a directory is a\nConfig'urable item. The default is set to -1 (65535 in Config terms),\nwhich means \"determine directory type from the file header of the root\ndirectory\". If this is appears unsuccessful on your system, the value\ncan be Config'ed in the range 3-255.\n\nZip assumes a file is a directory if:\n\n        ((type == CONFIGed_type) && (file_size % 64) == 0)\n\nIf you are unfortunate enough have files of that pass this test but\nare not directories, then Zip will loop endless, as SMS/QDOS opens the\nroot directory again !!! (recursion: see recursion etc).\n\nI suggest you refrain from zipping such files and contact the software\nsupplier and point out the error of their ways.\n\nFile Naming Issues\n------------------\n\nZip will append a '_zip' suffix to the archive filename when the\nsupplied name (i.e. excluding device/directory parts) does not\ncontain a '_' or a '.'. This is broadly compatible with Info-ZIP,\ntaking into account the '_' aberation.\n\nSo\n        ex zip;'ram2_test ...'          >> ram2_test_zip\n\n        ex zip;'ram2_test.zip ...'      >> ram2_test.zip\n\n        ex zip;'ram2_test_rep ... '     >> ram2_test_rep\n\n        ex zip;'ram2_fdbbs.rep ... '    >> ram2_fdbbs.rep\n\n        ex zip;'ram2_test_rep.zip ...'  >> ram2_test_rep.zip\n\nThis implies that if a file ram2_test.zip exists, and you do:\n\n        ex zip;'ram2_test ...'\n\nThen a new file (test_zip) is created, rather than 'test.zip' being\nupdated.\n\nZip supports extensive recursive wild-carding, again the fact that '_'\ncan be a directory separator as well as part of a file name makes this\na bit tricky, but given the example:\n\n     test1_bas\n     test2_bas\n     dir1->demo1_bas            where -> indicates a sub dir\n     dir2->demo2_bas\n\n     ex zip;'ram2_test *_bas'\n     just finds test1_bas, test2_bas\n\n     ex zip;'-r ram2_test *_bas'\n     recurses and finds all the files\n\nYou might think that\n\n    ex zip;'-r ram2_test *_*_bas'\n\nwould just find the files in the subdirectories--well yes, but it will\nalso find very other sub-dir'ed _bas file on the disk too. This is\na feature.\n\nThe pattern matching supports Unix-style 'regex' so you could:\n\n        ex zip;'ram2_test dir?_*_bas'\n        or\n        ex zip;'ram2_test dir[12]_*_bas\n\n\nUnZip has now got a fixed -d option. This is used to specify the\ndirectory to unpack the zipfile into, it must follow immediately\nafter the zip name.\n\n        ex unzip;'ram2_test_zip -d ram3_ *_txt'\n\nwould unpack all *_txt files to ram3_ .\n\nIt is not necessary to set the default directory to pack files, Zip\nwill remove any device names (and store any hard directory names,\nunless you zip -j).\n\n        ex zip;'ram1_test flp1_*'\n\n                ----->\n                        adding: file.dat (deflated 50%)\n                        adding: menu.rext # (deflated xx%)\n                        adding: zip * (deflated yy%)\n                        adding: hard_one (stored 0%)\n                        adding: hard_one/stuff.bas (deflated ...)\n\nDue to the way the file-mapping is implemented, it is not supported\nover the nX_ type network device.\n\nConfig Options\n--------------\n\nA limited number of SMS/QDOS specific functions can be set using the\nQJump Config program.\n\n      For Zip:\n\n      Timeout for interactive 'Press any key' prompt\n\n       65535                  Wait forever      (aka -1)\n       0                      No wait\n       n (1-32767)            Wait for 'n' clocks (1/50 sec)\n\n       Other values are unsupported. Note Config works on 'unsigned'\n       integer values (at least according to my manual).\n\n       Directory file type key.\n\n       Config will accept any value in the range 3-255, known useful\n       values are 3 (Thor), 4 (CST) and 255 (Level 2 devices). A value\n       of 65535 (aka -1) means \"determine from device info\".\n\n       For UnZip:\n\n       Timeout as above\n\n       Unpack mode (SMS/QOS ('_') or Info-ZIP ('.')\n\n       List format (Info-ZIP ('.') or SMS/QDOS ('_')\n\n\nWhen the 'Press a key' text is displayed, if you press ESC, then it\nwaits until you press any other key, infinite timeout. This may be\nuseful if you want (much) more time to study a listing etc.\n\nDefaults for timeout and directory type are 250 and -1 respectively.\n\nMore Goodies\n------------\n\nPart of the Zip compression code is now in assembler; it runs\nnoticably faster than the previous version. Compressing some arbitrary\nfiles with the previous Zip it took 251 seconds, with Zip 2.0.1 it\ntook (a mere) 170 seconds (68008 QL).\n\nMore good news is that SMS/QDOS is just another system option on top\nof standard Info-ZIP, unlike the previous ports that were much more\nSMS/QDOS specific. For example, compiling the standard source with c68\n(i.e. #define QDOS), then you get an SMS/QDOS version.\n\nCompile with Linux/gcc and get the standard Linux version. Now, here's\nthe cool bit; compile with Linux/gcc and \"-DQLZIP\", and get a standard\nLinux Zip/UnZip with SMS/QDOS (header) extensions.\n\nso, on Linux:\n\n            zip -Q stuff.zip qtpi zip unzip\n\nthe -Q tells Zip to look for XTc68/Lux68 cross-compiler data size\nblocks and produce a zipfile with SMS/QDOS headers in it (for exec\ntype programs). This works for exec files produced by the XTc68/Lux68\ncross compilers and ANY SMS/QDOS files copied to a Unix or MS-DOS disk\nfrom an SMS/QDOS floppy using 'qltools v2.2' (or later).\n\nSelf Extracting Archives\n------------------------\n\nInfo-ZIP self-extracting archives (_sfx) are created in a rather\n'brute-force' way. The UnZipSFX program is prepended to a zipfile.\n\ni.e.          file_sfx = unzipsfx + file_zip\n              ex file_sfx\n\nAlthough the UnZipSFX program is a cut-down UnZip, it is still around\n30Kb - 50Kb, depending on platform.\n\nThe success of this approach depends on how the operating system\nloader loads executable files. On most systems where the loader only\nloads the actual program part (Unix, VMS, DOS et al), the this is\nquite efficient; if you make, say, a 4Mb zipfile and prepend a 30Kb\nUnZipSFX image, then the system only loads the 30Kb program and the\nprocess is efficient as the zipped data part is still unpacked from\ndisk. These systems also supply the running UnZipSFX program stub with\nthe path name of the file it was loaded from, so the program knows\nwhat it has to unpack (so on Linux, for example):\n\n     cat /usr/bin/unzipsfx test.zip > test.sfx  # concatenate the files\n     chmod 755 test.sfx                         # make executable\n     test.sfx                                   # to extract, it\n                                                # 'knows' it is \"test.sfx\"\n\nUnfortunately, the more simplistic nature of SMS/QDOS makes this much\nmore difficult and rather less efficient as: (see note 1)\n\n     a. The SMS/QDOS 'loader' loads the whole file into memory.\n\n     b. The SMS/DOS 'loader'/c68 run-time system does not return the\n        name of the file from which it was loaded.\n\n     c. You cannot so easily create a image file by concatenating two\n        files, it is also necessary to ensure the executable file\n        header is set correctly.\n\n     d. The show stopper. The data space required for the\n        self-extracting archive is required, as not easily maintained\n        during electronic transfer.\n\n\nIf anyone is still interested, then the following support for UnZipSFX\nis provided.\n\n o A program 'makesfx' will combine a stub (callstub), UnZipSFX image\n   and a zipfile to produce a sfx (self-extracting zip) file.\n\n o A callable interface is supplied. The user calls the SFX file,\n   which creates the files necessary to do the extraction.\n\nThe makesfx program concatenates the supplied files to standard\noutput.\n\nSo, to create a sfx of all the _c files in the default directory.\n\n # 1st create a zipfile of the required files\n\n ex zip;'ram1_test_zip *_c'\n\n # Now create the sfx file (ram2_test_sfx)\n # our UnZipSFX image is in 'win1_bin'\n # as is the call stub.\n\nex makesfx;'-o test_sfx -x win1_bin_unzipsfx -s win1_bin_callstub -z ram1_test_zip'\n\nThe arguments to makesfx are:\n\n    -s stubfile\n    -x UnZipSFX_program\n    -z Zip_file\n    -o Output_file\n\nYou can now unpack the _sfx file on any SMS/QDOS-compatible\nsystem.\n\n        f$ = \"win2_tmp_test_sfx\"\n        a = alchp(flen(\\f$))\n        lbytes f$,a\n        call a\n        rechp(a)\n\nZipInfo\n-------\n\nGiven the above note concerning SMS/QDOS programs not knowing the name\nby which the program was invoked, then the usual symbolic-link-of-unzip-\nto-zipinfo trick is unavailable (presupposing there is some some SMS/QDOS\ntrick to emulate symbolic links).\n\nZipInfo functionality is only available via 'unzip -Z'. There is no\nseparate ZipInfo program.\n\nCaveat ATP Users\n----------------\n\nATP for SMS/QDOS users should pay particular attention to the\nZip/UnZip options in their atprc and compare with Info-ZIP Zip/UnZip\nusage. Older versions of Zip/UnZip screwed up -j.\n\n\n        zip -jk\n        unzip -jo\n\nDistribution & Copyright\n------------------------\n\nThis software is written by and largely copyrighted by the 'Info-ZIP'\ngroup whose members are noted in the accompanying documentation. This\nparticular SMS/QDOS port plus 'makesfx' was written by, but is not\ncopyrighted by, Jonathan R Hudson. The SMS/QDOS code in this release\nis written from scratch and is not dependent on previous SMS/QDOS\nreleases, but is (largely) compatible.\n\nAs a courtesy to the authors of this package, please ensure that the\ndocumentation is supplied when it is re-distributed.\n\nIn particular, if this archive is split into Zip and UnZip components,\nensure that this document (\"IZREADME_SMS\") is supplied in\neach component.\n\nSMS/QDOS version by:\nJonathan R Hudson (jrhudson@bigfoot.com)\n\nI am grateful to Graham Goodwin for finding some most imaginative\nmeans of breaking the beta code.\n\nI'd also like to thank Thierry Godefroy for providing the 2.1/5.2\nsource code and making the initial contact with the Info-ZIP group.\n\nAnd of course, many, many thanks to the Info-ZIP workers for making\nthis code freely available.\n\nNote 1\n------\n\nThe 'C' language FAQ ('frequently asked questions' [comp.lang.c])\nnotes on the matter of obtaining the load file name of a 'C' program:\n\n16.5:   How can my program discover the complete pathname to the\n        executable file from which it was invoked?\n\nA:      argv[0] may contain all or part of the pathname, or it may\n        contain nothing.  You may be able to duplicate the command\n        language interpreter's search path logic to locate the\n        executable if the name in argv[0] is present but incomplete.\n        However, there is no guaranteed or portable solution.\n                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nNote 2\n------\n\nNUL files for SMS2. There appears to be a conflict between SMS2/LBASIC\ncompiled programs and c68 programs using nul as stdin.\n\n        EW zip,nul;'ram1_test *_bas'    # will not work\n\n                                        # This does work !\n        EW zip,#FOP_IN('nul');'ram2_test *_bas' : CLOSE\n\nNote 3\n------\n\nversion number incremented to 2.0.1a and 5.12a to accomodate Erling\nJacobsen's exit message requirements\n\nversion number incremented to Zip 2.0.1b to fix bug on zipping files\nstarting with leading underscore.\n\nversion number incremented to UnZip 5.12b to fix UnZip problem on\nfiles zipped with leading './', and linked with revised (fixed) c68\n'utime' function (could corrupt level 1 files). (source code _only_ as\nIZQ004.zip).\n\nPorted Zip 2.1 and UnZip 5.2 (July 1996). Released as INZIP005.zip\n\nAll later versions --- see Info-ZIP release notes and documentation.\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/callstub.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include <qdos.h>\n#include <limits.h>\n#include <string.h>\n\nstruct\n{\n    short flag1;\n    short flag2;\n    long offset;            // The offset from &ds to unzipsfx exe\n    long sfxlen;            // size of unzipsfx program\n    long sfxdsiz;           // data size of unzipsfx program\n    long sfxnam;            // Name offset from start of sfxprog\n    long ziplen;            // size of zip file\n} ds = {0x4afb, 0x4afb, 0};\n\n\ntypedef struct {short len; char chrs[1];} __QP_t;\n\n#define __QA(l) struct {short len; char chrs[(l)+1];}\n\n#define T1 \\\n   \"\\nThis is a self-extracting zip archive. In order to process the\\n\" \\\n   \"archive you will be asked to give the name of a temporary directory\\n\" \\\n   \"which must have at least as much free space as this SFX file.\\n\\n\" \\\n   \"You will also be asked for the name of the directory to which the\\n\" \\\n   \"files are extracted. This directory _MUST_ exist. If you do not give\\n\" \\\n   \"an output directory, the current default is used.\\n\\n\\n\" \\\n   \"Device/directory for temporary files: \"\n#define T2 \"Device/directory to extract to      : \"\n\n#define T1LEN (sizeof(T1)-1)\n#define T2LEN (sizeof(T2)-1)\n\nstatic void xgetcwd (__QP_t *s)\n{\n    extern char *_sys_var;\n    static __QP_t **q;\n\n    if (q = (__QP_t ** q) (_sys_var + 0xAC + 4))\n    {\n        memcpy (s->chrs, (*q)->chrs, (*q)->len);\n        s->len = (*q)->len;\n        *(s->chrs+s->len) = 0;\n    }\n}\n\nint checkdir(__QP_t *dir)\n{\n    qdirect_t s;\n    int r,ch;\n\n    if(dir->len > 1)\n    {\n        if(*(dir->chrs + dir->len-2) == '_')\n        {\n            *(dir->chrs + dir->len-1) = 0;\n            dir->len--;\n        }\n        else\n        {\n            *(dir->chrs + dir->len-1) = '_';\n        }\n    }\n    else\n    {\n        xgetcwd(dir);\n    }\n\n    r = ERR_NF;\n\n    if((ch = io_open(dir->chrs, 4)) > 0)\n    {\n        if((r = fs_headr(ch, -1, &s, sizeof(s))) > 0)\n        {\n            r = (s.d_type == 0xff) ? 0 : ERR_NF;\n        }\n        io_close(ch);\n    }\n    return r;\n}\n\nint makesfx(__QP_t *tmp)\n{\n    char *p = (char *)&ds;\n    char *q;\n    char txt[PATH_MAX];\n    int fd,r = 0;\n    qdirect_t qd;\n\n    memcpy(txt, tmp->chrs, tmp->len);\n    memcpy(txt+tmp->len, \"SFX_EXE\", 8);\n\n    q = p + ds.offset;\n    if((fd = io_open(txt, NEW_OVER)) > 0)\n    {\n        memcpy(txt+tmp->len+4, \"DAT\", 4);\n        memcpy(q+ds.sfxnam, txt, tmp->len+8);\n        fs_save(fd, q, ds.sfxlen);\n        qd.d_length = ds.sfxlen;\n        qd.d_datalen = ds.sfxdsiz;\n        qd.d_type = 1;\n        fs_heads(fd, -1, &qd, sizeof(qd));\n        io_close(fd);\n        if((fd = io_open(txt, NEW_OVER)) > 0)\n        {\n            q += ds.sfxlen;\n            fs_save(fd, q, ds.ziplen);\n            io_close(fd);\n        }\n        else r = fd;\n    }\n    else r = fd;\n    return r;\n}\n\n#define T3 \"\\n\\nTo extract the files, run the command \\\"LRUN \"\n#define T4 \"Press any key to exit \"\n#define T3LEN (sizeof(T3)-1)\n#define T4LEN (sizeof(T4)-1)\n\nint unpackit ( __QP_t *tmpdir, __QP_t *outdir, char *basfil, int con)\n{\n    int ch, r = 0;\n    char c;\n\n    memcpy(basfil, tmpdir->chrs,tmpdir->len);\n    memcpy(basfil+tmpdir->len,\"SFX_BAS\", 8);\n\n    if((ch = io_open(basfil, NEW_OVER)) > 0)\n    {\n        char *p,txt[80];\n        int l;\n\n        p = txt;\n        *p++ = 'E';\n        *p++ = 'W';\n        *p++ = ' ';\n        memcpy(p, tmpdir->chrs, tmpdir->len);\n        p += tmpdir->len;\n        memcpy(p, \"SFX_EXE;'-d \", 12);\n        p += 12;\n        memcpy(p, outdir->chrs, outdir->len);\n        p += outdir->len;\n        *p++ = '\\'';\n        *p++ = '\\n';\n        io_sstrg(ch, -1, txt, (int)(p-txt));\n\n        memcpy(txt, \"delete \", 7);\n        p = txt + 7;\n        memcpy(p, tmpdir->chrs, tmpdir->len);\n        p += tmpdir->len;\n        memcpy(p, \"SFX_EXE\\n\", 8);\n        p += 4;\n        l = (int)(p+4-txt);\n        io_sstrg(ch, -1, txt, l);\n        memcpy(p, \"DAT\\n\", 4);\n        io_sstrg(ch, -1, txt, l);\n        memcpy(p, \"BAS\\n\", 4);\n        io_sstrg(ch, -1, txt, l);\n        io_close(ch);\n        makesfx((__QP_t *)tmpdir);\n    }\n    else r = ch;\n\n    if(r == 0)\n    {\n        char t3[80];\n        char *p;\n        p = t3;\n        memcpy(p, T3, T3LEN);\n        p += T3LEN;\n        memcpy (p, basfil, tmpdir->len+7);\n        p += tmpdir->len+7;\n        *p++ = '\"';\n        *p++ = '\\n';\n        io_sstrg(con, -1, t3, (int)(p-t3));\n    }\n    io_sstrg(con, -1, T4, T4LEN);\n    io_fbyte(con, (5*60*50), &c);\n    return r;\n}\n\nint main(void)\n{\n    int con;\n    int r,n;\n    __QA(PATH_MAX) tmpdir;\n    __QA(PATH_MAX) outdir;\n    char basfil[PATH_MAX];\n\n    con = io_open(\"con_480x160a16x38\", 0);\n    sd_bordr(con, -1, 7, 2);\n    sd_clear(con, -1);\n    sd_cure (con, -1);\n\n    io_sstrg(con, -1, T1, T1LEN);\n    if((tmpdir.len = io_fline(con, -1, tmpdir.chrs, PATH_MAX-1)) > 1)\n    {\n        if((r = checkdir((__QP_t *)&tmpdir)) == 0)\n        {\n            io_sstrg(con, -1, T2, T2LEN);\n            if((outdir.len = io_fline(con, -1, outdir.chrs, PATH_MAX-1)) > 0)\n            {\n                if((r = checkdir((__QP_t *)&outdir)) == 0)\n                {\n                    r = unpackit ((__QP_t *)&tmpdir, (__QP_t *)&outdir,\n                                    basfil, con);\n                }\n            }\n        }\n    }\n    sd_bordr(con, -1, 0, 0);\n    sd_clear(con, -1);\n    io_close(con);\n    return r;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/config.S",
    "content": "#\n;===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in unzip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n\n.globl _qlflag\n.globl _qlwait\n#ifdef ZIP\n.globl _dtype\n#endif\n\n.data\n        ds.w    0\n        dc.b    '<<QCFX>>01'\n#ifdef ZIP\n        dc.w    8\n        dc.b    'Info-ZIP'\n*                12345678901234567890\n        ds.w    0\n        dc.w    3\n        dc.b    '?.?'\n        ds.w    0\n#else\n        dc.w    10\n        dc.b    'Info-UNZIP'\n*                12345678901234567890\n        ds.w    0\n        dc.w    3\n        dc.b    '?.?'\n        ds.w    0\n#endif\n        dc.b    10\n        dc.b    0\nl_4:    dc.w    _qlwait-l_4\n        dc.w    0\n        dc.w    0\nl_5:    dc.w    hpt-l_5\nl_6:    dc.w    hxx-l_6\n\n#ifdef ZIP\n        dc.b    10\n        dc.b    0\nd_4:    dc.w    _dtype-d_4\n        dc.w    0\n        dc.w    0\nd_5:    dc.w    dpt-d_5\nd_6:    dc.w    dxx-d_6\n\n#else\n        dc.b    4\n        dc.b    0\nl5:\n        dc.w    list1-l5\n        dc.w    0\nl5a:\n        dc.w    Postit-l5a              ; post proc\nl6:\n        dc.w    apt-l6\nl7:\n        dc.w    axx-l7\n* -------------------------------------\n        dc.b    4\n        dc.b    0\nl8:\n        dc.w    list2-l8\n        dc.w    0\nl8a:\n        dc.w    Postit-l8a              ; post proc\nl9:\n        dc.w    bpt-l9\nla:\n        dc.w    bxx-la\n* -------------------------------------\n#endif\n        dc.w    -1                          ; end\n\n_qlflag:\n        dc.w    0\n_qlwait:\n        dc.w    250\n_dtype:\n        dc.w    255\n\nhpt:    dc.w    10\n        dc.b    'Exit Delay'\n*                12345678901234567890\n        ds.w    0\nhxx:    dc.w    0\n        dc.w    $ffff\n        dc.w    -1\n#ifdef  ZIP\ndpt:    dc.w    14\n        dc.b    'Directory Type'\n*                12345678901234567890\n        ds.w    0\ndxx:    dc.w    3\n        dc.w    $ff\n        dc.w    -1\n#else\n\nlist1:\n        dc.b    0\nlist2:\n        dc.b    0\n\napt:\n        dc.w    11\n        dc.b    'Unpack Mode'\n*                12345678901234567890\n.even\naxx:    dc.b    0\n        dc.b    0\n        dc.w    8\n        dc.b    'SMS/QDOS'\n.even\n        dc.b    1\n        dc.b    0\n        dc.w    7\n        dc.b    'Default'\n.even\n        dc.w    -1\n.even\nbpt:\n        dc.w    12\n        dc.b    'Listing Mode'\n*                12345678901234567890\n.even\nbxx:\n        dc.w    0\n        dc.w    7\n        dc.b    'Default'\n.even\n        dc.b    2\n        dc.b    0\n        dc.w    8\n        dc.b    'SMS/QDOS'\n*                12345678901234567890\n.even\n         dc.w    -1\nPostit:\n        lea.l   _qlflag,a0\n        move.b  list1,d0\n        move.b  d0,(a0)\n        move.b  list2,d0\n        or.b    d0,(a0)\n        moveq   #0,d0\n        rts\n#endif\n        end\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/crc68.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n.text\n\n.globl  _crc32          ; (ulg val, uch *buf, extent bufsize)\n.globl  _get_crc_table  ; ulg *get_crc_table(void)\n\n_crc32:\n        move.l  8(sp),d0\n        bne    valid\n        moveq  #0,d0\n        rts\nvalid:  movem.l d2/d3,-(sp)\n        jsr     _get_crc_table\n        move.l  d0,a0\n        move.l  12(sp),d0\n        move.l  16(sp),a1\n        move.l  20(sp),d1\n        not.l   d0\n\n        move.l  d1,d2\n        lsr.l   #3,d1\n        bra     decr8\nloop8:  moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\ndecr8:  dbra   d1,loop8\n        and.w   #7,d2\n        bra     decr1\nloop1:  moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\ndecr1:  dbra   d2,loop1\ndone:   movem.l (sp)+,d2/d3\n        not.l   d0\n        rts\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/izqdos.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _IZQDOS_H\n#define _IZQDOS_H\n\n#include <qdos.h>\ntypedef struct\n{\n    unsigned short shortid;\n    struct\n    {\n        unsigned char lo;\n        unsigned char hi;\n    } len;\n    char        longid[8];\n    struct      qdirect     header;\n} qdosextra;\n\ntypedef struct\n{\n    unsigned short shortid;\n    struct\n    {\n        unsigned char lo;\n        unsigned char hi;\n    } len;\n    char        longid[4];\n    struct      qdirect     header;\n} jbextra;\n\n#define SHORTID     0x4afb\n#define JBSHORTID   0x4afb\n#define LONGID      \"QDOS02\"\n#define JBLONGID    \"QZHD\"\n#define EXTRALEN    (sizeof(qdosextra) - 2 * sizeof(char) - sizeof(short))\n#define JBEXTRALEN  (sizeof(jbextra)   - 2 * sizeof(char) - sizeof(short))\n\nextern short qlflag;\nextern short qlwait;\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/makesfx.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * makesfx - Makes a QDOS sfx zip file\n * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n * created by Jonathan Hudson, 04/09/95\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <fcntl.h>\n\n#define SFXFLAG \"??Special Flag for unzipsfx hack  ??\"\n\n#ifdef QDOS\n# include <qdos.h>\n# define ZMODE (X_OK|R_OK)\n# define rev_long(x) (x)\n# define XFLAG 0x4afb\n#else\n# define ZMODE (R_OK)\n# define getchid(p1) p1\n# include <sys/stat.h>\n  long rev_long(long l);\n# define XFLAG 0xfb4a\n\ntypedef struct\n{\n    long id;\n    long dlen;\n} NTC;\n\nstruct qdirect  {\n    long            d_length __attribute__ ((packed));  /* file length */\n    unsigned char   d_access __attribute__ ((packed));  /* file access type */\n    unsigned char   d_type __attribute__ ((packed));    /* file type */\n    long            d_datalen __attribute__ ((packed)); /* data length */\n    long            d_reserved __attribute__ ((packed));/* Unused */\n    short           d_szname __attribute__ ((packed));  /* size of name */\n    char            d_name[36] __attribute__ ((packed));/* name area */\n    long            d_update __attribute__ ((packed));  /* last update */\n    long            d_refdate __attribute__ ((packed));\n    long            d_backup __attribute__ ((packed));   /* EOD */\n} ;\n\nint fs_headr (int fd, long t, struct qdirect *qs, short size)\n{\n    NTC ntc;\n    int r = -1;\n    struct stat s;\n\n    fstat(fd, &s);\n    qs->d_length = s.st_size;\n    lseek(fd, -8, SEEK_END);\n    read(fd, &ntc, 8);\n    if(ntc.id == *(long *)\"XTcc\")\n    {\n        qs->d_datalen = ntc.dlen;    /* This is big endian */\n        qs->d_type = 1;\n        r = 0;\n    }\n    lseek(fd, 0, 0);\n    return 42;                       /* why not ??? */\n}\n\ntypedef unsigned char uch;\n\nlong rev_long (long l)\n{\n    uch cc[4];\n    cc[0] = (uch)(l >> 24);\n    cc[1] = (uch)((l >> 16) & 0xff);\n    cc[2] = (uch)((l >> 8) & 0xff);\n    cc[3] = (uch)(l & 0xff);\n    return *(long *)cc;\n}\n\n#endif\n\n#define RBUFSIZ 4096\n\nvoid usage(void)\n{\n    fputs(\"makesfx -o outfile -z zipfile -xunzipsfx -sstubfile\\n\", stderr);\n    exit(0);\n}\n\nint main (int ac, char **av)\n{\n    int fd, fo;\n    static char local_sig[4] = \"PK\\003\\004\";\n    char *p, tmp[4];\n    short ok = 0;\n    char *of = NULL;\n    char *xf = NULL;\n    char *zf = NULL;\n    char *sf = NULL;\n    int c;\n\n    while((c = getopt(ac, av, \"o:z:x:s:h\")) != EOF)\n    {\n        switch(c)\n        {\n            case 'o':\n                of = optarg;\n                break;\n            case 'z':\n                zf = optarg;\n                break;\n            case 'x':\n                xf = optarg;\n                break;\n            case 's':\n                sf = optarg;\n                break;\n            case 'h':\n                usage();\n                break;\n        }\n    }\n\n\n    if(zf && xf && of && sf)\n    {\n        if((fd = open(zf, O_RDONLY)) > 0)\n        {\n            if((read(fd, tmp, 4) == 4))\n            {\n                if(*(long *)tmp == *(long *)local_sig)\n                {\n                    ok = 1;\n                }\n            }\n            close(fd);\n        }\n        if(!ok)\n        {\n            fprintf(stderr,\n                    \"Huum, %s doesn't look like a ZIP file to me\\n\", zf);\n            exit(0);\n        }\n\n        if(strstr(xf, \"unzipsfx\"))\n        {\n            if(access(xf, ZMODE))\n            {\n                fprintf(stderr, \"Sorry, don't like the look of %s\\n\", xf);\n                exit(0);\n            }\n        }\n\n        if((fo = open(of, O_CREAT|O_TRUNC|O_RDWR, 0666)) != -1)\n        {\n            struct qdirect sd,xd;\n            int n;\n            int dsoff = 0;\n            int nfoff = 0;\n            int zlen = 0;\n\n            if((fd = open(sf, O_RDONLY)) != -1)\n            {\n                if(fs_headr(getchid(fd), -1, &sd, sizeof(sd)) > 0)\n                {\n                    unsigned short *q;\n                    p = malloc(sd.d_length);\n                    n = read(fd, p, sd.d_length);\n                    for(q = (unsigned short *)p;\n                        q != (unsigned short *)(p+sd.d_length); q++)\n                    {\n                        if(*q == XFLAG && *(q+1) == XFLAG)\n                        {\n                            dsoff = (int)q-(int)p;\n                            break;\n                        }\n                    }\n                    write(fo, p, n);\n                    close(fd);\n                }\n            }\n\n            if(dsoff == 0)\n            {\n                puts(\"Fails\");\n\n                exit(0);\n            }\n\n            if((fd = open(xf, O_RDONLY)) != -1)\n            {\n                char *q;\n                if(fs_headr(getchid(fd), -1, &xd, sizeof(xd)) > 0)\n                {\n                    p = realloc(p, xd.d_length);\n                    n = read(fd, p, xd.d_length);\n                    {\n                        for(q = p; q < p+xd.d_length ; q++)\n                        {\n                            if(*q == '?')\n                            {\n                                if(memcmp(q, SFXFLAG, sizeof(SFXFLAG)-1) == 0)\n                                {\n                                    nfoff = (int)(q-p);\n                                    break;\n                                }\n                            }\n                        }\n                    }\n                    write(fo, p, n);\n                    close(fd);\n\n                    if((fd = open(zf, O_RDONLY)) > 0)\n                    {\n                        p = realloc(p, RBUFSIZ);\n                        while((n = read(fd, p, RBUFSIZ)) > 0)\n                        {\n                            write(fo, p, n);\n                            zlen += n;\n                        }\n                        close(fd);\n                    }\n                    lseek(fo, dsoff+4, SEEK_SET);\n                    n = rev_long((sd.d_length-dsoff));\n                    write(fo, &n, sizeof(long));\n                    n = rev_long(xd.d_length);\n                    write(fo, &n, sizeof(long));\n                    write(fo, &xd.d_datalen, sizeof(long));\n                    n = rev_long(nfoff);\n                    write(fo, &n, sizeof(long));\n                    n = rev_long(zlen);\n                    write(fo, &n, sizeof(long));\n                    close(fo);\n                }\n                else\n                {\n                    close(fd);\n                    fputs(\"Can't read unzipsfx header\", stderr);\n                    exit(0);\n                }\n            }\n            free(p);\n        }\n    }\n    else\n        usage();\n\n    return 0;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/qdos/qdos.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  qdos.c\n\n  QDOS-specific routines for use with Info-ZIP's UnZip 5.3 and later.\n\n  Contains:  Qstrfix()\n             QFilename()\n             QMatch()\n             chowner()\n             Qgetch()\n             QReturn()\n             LastDir()\n             screensize()\n             do_wild()           <-- generic enough to put in file_io.c?\n             mapattr()\n             mapname()\n             checkdir()\n             qfix()\n             close_outfile()\n             stamp_file()\n             getp()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n#define UNZIP_INTERNAL\n\n#include \"unzip.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n#include <dirent.h>\n#include \"izqdos.h\"\n#include \"unzvers.h\"\n\n#ifndef SFX\nchar _prog_name[] = \"UnZip\";\n#else\nchar _prog_name[] = \"??Special Flag for unzipsfx hack  ??\";\n#endif\n/* sorrid hack at request of GRR follows; hope the compiler stays kind to us */\nchar _version[] = {UZ_MAJORVER+'0','.',UZ_MINORVER+'0',UZ_PATCHLEVEL+'0'};\nchar _extra[] = \" \" UZ_BETALEVEL;\nchar _copyright[] = \"(c) Info-ZIP Group\";\nchar *  _endmsg = NULL;\nlong _stack = 16*1024;         /* huge stack (for qdos) */\n\nextern void consetup_title(chanid_t,struct WINDOWDEF *);\nvoid (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;\n\nstruct WINDOWDEF _condetails =\n{\n    2,\n    1,\n    0,\n    7,\n    500,\n    220,\n    2,\n    30\n};\n\n\nstatic jobid_t chowner(chanid_t chan)\n{\n    extern char *_sys_var;\n    char *scht;\n    long *cdb;\n    long jid;\n\n    scht = *((char **)(_sys_var + 0x78));\n    cdb = *(long **)((long *)scht  + (chan & 0xffff));\n    jid = *(cdb + 2);\n    return jid;\n}\n\nint QReturn(int err)\n{\n    jobid_t me,you;\n\n    me = getpid();\n    you = chowner(getchid(0));\n\n    if((me == you) && ((qlflag & 4) == 0))\n    {\n        if(isatty(0) && isatty(2) && qlwait)\n        {\n            char c = 0;\n            fputs(\"Press a key to exit\", stderr);\n            if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)\n            {\n                io_fbyte(getchid(0), -1, &c);\n            }\n        }\n    }\n    if(err > 0) err = -err;     /* We like -ve err nos (exclusively, alas) */\n    exit(err);\n}\n\n#ifndef FUNZIP\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\nchar *Qstrfix (char *p)\n{\n    char *q;\n    for (q = p; (q = strstr(q, \".zip\"));)\n    {\n        *q = '_';\n        q += 4;\n    }\n    return p;\n}\n\nvoid QFilename(char *f)\n{\n    char *o,*p,*q = strdup(f);\n    p = q;\n\n    if(*q == '.' && *(q+1) == '/') q += 2;\n    o = q;\n\n    for(;*q;q++)\n    {\n        if(*q == '/') *q = '_';\n        if((qlflag & 1) == 0)\n        {\n            if(*q == '.') *q = '_';\n        }\n    }\n    strcpy(f,o);\n    free(p);\n}\n\nint QMatch(uch c1, uch c2)\n{\n    int m =0;\n\n    if(c1 != c2)\n    {\n        if(c1 == '_' && (c2 == '.' || c2 == '/'))\n        {\n            m = 1;\n        }\n    }\n    else\n    {\n        m = 1;\n    }\n    return m;\n}\n\n\nint Qgetch(void)\n{\n    char ch;\n\n    if(io_fbyte(getchid(0), -1, &ch) < 0)\n    {\n        return EOF;\n    }\n    else\n    {\n        return (int) ch;\n    }\n}\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    QLRECT_t rect;\n\n    if(0 == sd_chenq(getchid(1), -1, &rect))\n    {\n        if(tt_cols)\n            *tt_cols = rect.q_width;\n        if(tt_rows)\n            *tt_rows = rect.q_height;\n    }\n    else\n    {\n        if(tt_cols)\n            *tt_cols = 80;\n        if(tt_rows)\n            *tt_rows = 24;\n    }\n    return 0;\n}\n\n\n\n#ifndef SFX\nchar *LastDir(char *ws)\n{\n    char *p;\n    char *q = ws;\n    struct stat s;\n\n    for(p = ws; *p; p++)\n    {\n        if(*p == '_')\n        {\n            char c;\n\n            p++;\n            c = *p;\n            *p = 0;\n            if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))\n            {\n                q = p;\n            }\n            *p = c;\n        }\n    }\n    return q;\n}\n\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n    char basedir[40];\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        char *ws = NULL, *us = NULL;\n\n        notfirstcall = TRUE;\n\n        /* break the wildspec into a directory part and a wildcard filename */\n\n        ws = (char *) iswild(wildspec);\n\n        if(ws == NULL)\n        {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            return matchname;\n        }\n\n        us = LastDir(wildspec);\n\n        if(us == wildspec)\n        {\n            dirname = basedir;\n            getcwd(basedir, sizeof(basedir)-1);\n            dirnamelen = strlen(basedir);\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            wildname = us;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                if (match(file->d_name, wildname, 0 WISEP)) { /* 0=case sens.*/\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 == case sens. */\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case QDOS_:\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case TANDEM_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                return 0;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                   VMS (and probably others ??) leave 0 in the upper 16-bit\n                   part of the external_file_attributes field. Instead, they\n                   store file permission attributes in some extra field.\n                   As a work-around, we search for the presence of one of\n                   these extra fields and fall back to the MSDOS compatible\n                   part of external_file_attributes if one of the known\n                   e.f. types has been detected.\n                   Later, we might implement extraction of the permission\n                   bits from the VMS extra field. But for now, the work-around\n                   should be sufficient to provide \"readable\" extracted files.\n                   (For ASI Unix e.f., an experimental remap of the e.f.\n                   mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                return 0;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in SMS/QDOS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case '.':\n                if (pp == pathcomp) {   /* nothing appended yet... */\n                    if (*cp == '/') {   /* don't bother appending \"./\" to */\n                        ++cp;           /*  the path: skip behind the '/' */\n                        break;\n                    } else if (!uO.ddotflag && *cp == '.' && cp[1] == '/') {\n                        /* \"../\" dir traversal detected */\n                        cp += 2;        /*  skip over behind the '/' */\n                        killed_ddot = TRUE; /*  set \"show message\" flag */\n                        break;\n                    }\n                }\n                *pp++ = (((qlflag & 1) == 0) ? '_' : '.');\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        G.filename[strlen(G.filename) - 1] = '_';\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-2)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '_';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n        short dlen;\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if (isdirdev(buildpath))\n            {\n                dlen = 5;\n            }\n            else\n            {\n                dlen = 0;\n            }\n\n            if ((end-buildpath-dlen) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if ((stat(tmproot, &G.statbuf) ||\n                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            if (tmproot[rootlen-1] == '/' || tmproot[rootlen-1] == '_') {\n                tmproot[--rootlen] = '\\0';\n            }\n            tmproot[rootlen++] = '_';\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n        }\n        Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\nstatic void qfix(__G__ ef_ptr, ef_len)\n    __GDEF\n    uch *ef_ptr;\n    unsigned ef_len;\n{\n    qdosextra qextra;\n\n    while (ef_len >= EB_HEADSIZE)\n    {\n        qdosextra   *extra = &qextra;\n        jbextra     *jbp   = (jbextra *)&qextra;\n        unsigned    eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"qfix: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        /* Must ensure that we don't use ODD addresses here */\n\n        memcpy(&qextra, ef_ptr, sizeof(qdosextra));\n        switch (extra->shortid) {\n          case SHORTID:\n            if (!strncmp(extra->longid, LONGID, strlen(LONGID)))\n            {\n                if (eb_len != EXTRALEN)\n                    fputs(\"warning: invalid length in Qdos field\", stderr);\n                if (extra->header.d_type)\n                {\n                    fs_heads(fgetchid(G.outfile), (timeout_t)-1,\n                             &extra->header, 14);\n                    G.pInfo->file_attr |= S_IXUSR;\n                }\n            }\n\n            if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID)))\n            {\n                if (eb_len != JBEXTRALEN)\n                    fputs(\"warning: invalid length in QZ field\", stderr);\n                if (jbp->header.d_type)\n                {\n                    fs_heads(fgetchid(G.outfile), (timeout_t)-1,\n                             &jbp->header, 14);\n                    G.pInfo->file_attr |= S_IXUSR;\n                }\n            }\n            break;\n\n          default:\n            Trace((stderr,\"qfix: unknown extra field block, ID=%d\\n\",\n               extra->shortid));\n            break;\n        }\n\n        /* Skip this extra field block */\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n}\n\n\n#ifdef QDOS\n#  include <utime.h>\n   long timezone = 0;\n#endif\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        struct utimbuf t2;      /* modtime, actime */\n    } zt;\n#ifdef USE_EF_UT_TIME\n    unsigned eb_izux_flg;\n#endif\n\n    if (G.extra_field) {\n        qfix(__G__ G.extra_field, G.lrec.extra_field_length);\n    }\n\n    fclose(G.outfile);\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.\n  ---------------------------------------------------------------------------*/\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n#ifdef USE_EF_UT_TIME\n        eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                       G.lrec.extra_field_length, 0,\n                       G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                       (G.tz_is_valid ? &(zt.t3) : NULL),\n#else\n                       &(zt.t3),\n#endif\n                       NULL) : 0);\n        if (eb_izux_flg & EB_UT_FL_MTIME) {\n            TTrace((stderr,\n              \"\\nclose_outfile:  Unix e.f. modif. time = %ld\\n\",\n              zt.t3.mtime));\n        } else {\n            zt.t3.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n        }\n        if (eb_izux_flg & EB_UT_FL_ATIME) {\n            TTrace((stderr,\n              \"close_outfile:  Unix e.f. access time = %ld\\n\",\n              zt.t3.atime));\n        } else {\n            zt.t3.atime = zt.t3.mtime;\n            TTrace((stderr,\n              \"\\nclose_outfile:  modification/access times = %ld\\n\",\n              zt.t3.mtime));\n        }\n#else\n        zt.t3.atime = zt.t3.mtime\n          = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n#endif\n\n        /* set the file's access and modification times */\n        if (utime(G.filename, &(zt.t2))) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  cannot set the time for %s\\n\",\n              FnFilter1(G.filename)));\n        }\n    }\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    struct utimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n           \"c68\", \" v4.2x\", \"SMS/QDOS\",\n            \" on \", __DATE__, \"\",\"\");\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n#endif /* !FUNZIP */\n\n#if CRYPT\n\nchar *getp(__G__ m, p, n)\n    __GDEF\n    const char *m;              /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    int c;                      /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n\n    /* get password */\n    w = \"\";\n    sd_cure(getchid(0), -1);    /* enable cursor */\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* display prompt and flush */\n        fflush(stderr);\n        i = 0;\n        do {\n            c = getch();\n            if (c == 0xc2) {\n                if (i > 0) {\n                    i--; /* the `del' keys works */\n                    fputs(\"\\b \\b\", stderr);\n                }\n            }\n            else if (i < n) {\n                p[i++] = c;     /* truncate past n */\n                if(c != '\\n') putc('*', stderr);\n            }\n        } while (c != '\\n');\n\n        putc('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n\n    p[i-1] = 0;                 /* terminate at newline */\n    sd_curs(getchid(0), -1);    /* suppress cursor */\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* CRYPT */\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/Contents",
    "content": "Contents of the \"tandem\" subdirectory for UnZip 5.42 and later:\n\n  Contents      this file\n  README\n  HISTORY\n  commacs       generic support macros for compiling\n  doit          macro to extract and rename required Tandem files from archive\n  macros        Info-ZIP-specific macros for compiling\n  make          Tandem NSK script to compile UnZip intelligently\n  makesfx       Tandem NSK script to compile UnZipSFX\n  tandem.c      Tandem NSK-specific Zip & UnZip support routines\n  tandem.h      Tandem NSK-specific data declarations\n  tanunz.c      Tandem NSK-specific UnZip support routines\n  tannsk.h      Tandem NSK-specific declarations that need delayed including\n\nTo compile, run the rename.unix script on a Unix system (renames *.c files\nto *c and *.h files to *h, and leaves all files necessary for Tandem port\nin the Tandem subdirectory).  Then transfer the renamed files to the Tandem\nsystem (if by ftp, use ASCII mode so the line-endings are converted to CR/LF\nformat properly).  Edit the `make' script and change all references to\n$DATA9.DAVESZIP with whatever subvol you use, and change all references to\nSUPER.DAVES with whatever user id you use.  Then run it.  Individual object\nfiles will be named *o (that is, unzip.c -> unzipc -> unzipo), and an\nintermediate UnZip library (unziplib) and final UnZip binary (unzipl or\nunzipw, depending on large or wide model) will be created.\n\nThe filecode for unzipl should be 100 [OBJECT]...presumably this is automatic.\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/HISTORY",
    "content": "Tandem Port History\n===================\n\nHi, I'm Dave Smith and I work at BP Oil UK, looking after their European card\nprocessing system since 1992.  We need to send lots of files via FTP to other\nBP machines (Novell, NT, Sun...). Sending large files was frowned upon, so the\nsearch for a zip product was on.\n\nWe tried the GZIP product from Twinsoft Netherlands but it was complicated to\nuse and it was not widely known by other arts of BP.\n\nWhat we really wanted was a PKZIP compatible product, as this is a widely known\nproduct.  By chance when surfing the web I discovered the Info-ZIP web site.\nThis claimed PKZIP 2.04g compatibility and had a number of ports, was free, and\neven had source code, but unfortunately no Tandem version :-(\n\nThus in the autumn 1996 I bit the bullet and took on the job of porting the\ncode to Tandem NSK (Guardian).  This meant dusting off my circa 1985 'C'\nprogramming skills and firing up the Tandem 'C' compiler - not known for its\nease of use, especially debugging 8-;  This was all on D30 by the way.\n\nTo start this off I had to choose an existing port to base te Tandem one on.\nNearest (?) was the VM-CMS/MVS port by George Petrov.  The main similarity\nbeing that these machines are record based, and have a similarish filing system\nto Guardian.\n\nFirst to be tackled was ZIP.  By the end of 1996 I had a version which compiled\nand ran (giving the program banner) - which seemed like a major acheivement at\nthe time.\n\nIn December 1996 I forwarded a version of ZIP to Info-ZIP which wor\nked only on Edit files, and had no concept of directories.  Became ZIP 2.1\n\nBy March 1997 I had improved ZIP so that it could cope with Unstructured files\nas well (Became ZIP 2.2).  I also had ported a version of UNZIP which could\ncreate Unstructured files (not Edit) - UNZIP 5.20\n\nAt the start of September 1997 I sent UNZIP with Edit file support to Info-ZIP\n(incorporated into 5.32)\n\nIn March 1998 I submitted file I/O improvements (SBB) for ZIP (2.3a)\n\nIn August 1998 I added Tandem DEFINE processing for ZIP (2.3e).  This was a\nfeature required by BP to allow them to store files with a different internal\nname than the physical file being zipped (without renaming it).\nAlso added storing of proper UTC timestamps which allow for DST & timezone.\n\nAlso in August I added the same file I/O improvements for UNZIP (5.33f)\n\nI then added the ability to update the unzipped files last modified and last\nopen timestamps - this required help from TNSC to allow me access to the\npriviliged procedure call.  Also can give the files back to the original user\nby use of the '-X' flag.\n\nAt the end of 1998 I was given the go ahead to add the zipping of Enscribe\nfiles.  This first version stores all Enscribe file attributes EXCEPT SQL, alt\nkey and partition information.\n\nZIP now uses its own Guardian I/O (rather than the 'C'library) for the reading\nof files to be zipped.\n\nUnstructured files use Large Transfer mode and READ (56K or 30K reads)\nEdit files use IOEdit routines\nEnscribe files use READ and SBB and add LF to the end of each record.\n\nUNZIP has the ability to update the filecode of files restored to ther original\nvalue (Unstructured only)\n\n\nTo Do ZIP\n===========\n1. Change I/O to use NSK/Large Transfer mode in fwrite of ZIP file itself- this\n   will dramaticaly speed up updating an existing zipfile. When updating an\n   existing zipfile it copies it to a temporary file currently using only SBB.\n2. Add raw binary mode to allow storing of raw data in zip file - e.g. only to\n   be unzipped on Tandem !  This is simplest/fastest way to provide full\n   Enscribe support for Tandem platform - with no cross-platform support.\n3. Add SQL support !!\n\nTo Do UNZIP\n===========\n1. Re-write the I/O routines to use NSK to recreate the original Enscribe file\n   structure.\n2. Use NSK Large Transfer mode I/O for reading/writing of ZIP file\n3. Add raw binary mode to allow restoration of Tandem file from previous raw\n   data ZIP (see above)\n4. Add SQL support !!\n\n\n\nCurrent Versions on Website\n===========================\n\nZIP 2.3\nUNZIP 5.5\n\nAs of February 17th 2002\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/README",
    "content": "Tandem Port of Info ZIP (unzip)\n=======================\n\nRecent changes:\n1. Support UNZIPing of EDIT (text) files by use of the \"-a\" parameter\n2. Changes for version 2.2 affected files:\n- TANDEMC     (changes to stat() to pass file creation time)\n- ZIPINFOC    (exclude TANDEM from tzset() test)\n3. Fix to default time/date field to UK format (dd/mm/yyyy)\n03/08/98  5.33f   Updates for TANDEMC/H to keep instep with ZIP (file buffering)\n                 New DOIT macro for extracting files from archive\n                 Fix in2ex to expand full vol/subvol depending on '-j' flag\n17/08/98  5.33f   Set USE_EF_UT_TIME to allow for timezone changes\n18/08/98  5.33f   Use define LICENSED to build object able to update timestamps\n19/08/98  5.33f   Add -X flag support (restore file owner id) via unzip.c/h\n                 new chown function in tandem.c.\n                 Modified close_outfile to make the chown the last step.\n30/11/98  5.41a  Updated mapname/chmod/in2ex, include licensing in MAKE\n21/12/98  5.41a  Add decoding of new Tandem extra field EF_TANDEM\n                 Make '-a' default option.  Add '-b' option to force creation\n                 of 'C' filecode 180 type text files.\n                 If available populate Tandem file code (e.g. Object files)\n                 Rationalised TANDEMH and TANDEMC wth ZIP 2.3i\n                 Fixed MORE (-M flag) processing by creating zgetch()\n12/01/99  5.41a  Correct bug stopping setting of last open timestamp\n24/03/99  5.41b  Split TANDEMC into TANDEMC/TANZIPC/TANUNZC\n24/03/99  5.41b  Added TANNSKH to allow for declarations which require\n                 structures defined in ZIPH after call to TANDEMH\n07/05/99  5.41c  Assume not DST if can't resolve time (no DST table available)\n01/06/99  5.41c  Add steps to make Self Extracting files (SFX)\n12/01/01  5.42g  Fix problems with MAKE for WIDE objects, updated TANDEMC/H\n                 in line with ZIP, updated DOIT to remove TIMEZONE.C\n\n                 If we ever want to use TIMEZONE.C then we need to set the\n                 define IZTZ_DEFINESTDGLOBALS, it then compiles OK.  The object\n                 would need to be added to the building of UNZIPLIB in make.\n\n09/02/01  5.50a  Added code to tandem.c to create files with appropriate\n                 extent sizes, or actual values if file was originally NSK\n15/02/01         Update tandem.c to force first character to 'A' for Tandem\n                 filenames\n12/04/01  5.50c  Fix problem with duff EF lengths in ef_scan_for_tandem\n12/04/01         Change definition of nsk_attrs to allow for Wide mode and\n                 subsequent respecifications of procedures that use it\n12/04/01         Fix bug in tanunz.c so that call to FILE_ALTERLIST_ has upper\n                 case filename\n12/04/01         Update tandem.c to only allow '$' in in2ex as appropriate\n16/07/01  5.50g  Fixed bug in tandem.c for incorrect use of slist_items rather\n                 than vlist_items\n18/07/01         Allow edit files to be created with original extents\n25/07/02  5.51b  Add \"-r\" remove file extensions command line option\n07/08/02  5.51b  Non-Tandem non-text files now set to code 0 (not 100)\n21/10/02  5.51b  Tandem Enscribe files containing text set to code 101\n03/01/03  5.51b  Fix bug in extract of Text files - caused by Deflate64 changes\n                 which made various buffers 64k and mismatches with unsigned.\n                 Added NO_DEFLATE64 to MAKE and made this the default for\n                 non-WIDE mode. If DEFLATE64 is used and non-WIDE then it drops\n                 down to MED_MEM model for OUTBUFSIZ logic.\n\nA few notes about the files on this subvol\n\nCOMMACS   -  required by MAKE, *** held on ZIP subvol ***\nDOIT      -  macro to extract required Tandem files from archive and rename\nMACROS    -  required by MAKE, *** held on ZIP subvol ***\nMAKE      -  recompile UNZIP code, attempts to only recompile changed code\nMAKESFX   -  make SFX header file\nREADME    -  this file\nUNZIPLIB  -  library of ZIP compiled routines, used by ZIP/ZIPNOTE etc\nUNZIPL    -  ZIP object (bound using LARGE memory model)\n\n*C        -  Source file\n*H        -  Header files\n*O        -  Individual object files (when compiled by MAKE)\n\nInstall Notes:\n==============\nStage 1 - get UNZIP object onto Tandem\n- download Tandem Unzip executables archive from Web\n- using PC unzip program (e.g. pkunzip/WinZip) extract UNZIP\n- copy UNZIP from PC to Tandem in Binary mode s(FTP/IXF)\n- alter file code to 100\n- optionally place in $SYSTEM.SYSTEM to allow easy access from command line\n\nStage 2 - (optional) retrieve source code (requires UNZIP on Tandem)\n- download UNZIP source archive from web - contains all supported platforms\n- copy archive onto Tandem as Binary\n- extract Tandem DOIT macro ( UNZIP -j <archive> tandem/DOIT )\n- update DOIT macro to point at archive file\n- restore relevant files by running DOIT\n- replace references to $T with a collector on your system\n- replace references to SUPER.DAVES with whatever user id you use\n- to compile run MAKE (compiles, accelerates, licences)\n- NOTE:  Always run the accelerated object on TNS/R systems, otherwise\n         it runs extremely slow.\n\n\nAdditional Notes - LICENSE the object:\n======================================\nIf you wish to be able to update the last modified time of files you unzip\nyou need to add the line \"#define LICENSED\" to the TANDEMH file.  If you set\nthis option you MUST FUP LICENSE the file as SUPER.SUPER.\nThis is a Tandem restriction since we have to call a PRIV procedure to update\nthe file label.  For UNZIP the define is setup (default) in tandem.h\n\n\nAdditional Notes - Self Extracting\n==================================\n\nTo create a Self Extracting (SFX) file you need to do the following\n- run the MAKESFX file to create the SFX object files\n- create a normal Zip file\n- create an empty Unstructured file\n- FUP COPY SFX into new file\n- FUP COPY your Zip file to the end of this new file\n- run ZIP -A <zipfile> to fix the internal pointers\n- alter the filecode of <zipfile> to 100 (I'll do this in Zip -A soon)\n\nFor performance you should Axcel the finished file.\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/commacs",
    "content": "?section CC ROUTINE\n#FRAME\n[#PUSH file stem src obj htime file prev time stime otime\n       comp out options sup buf col locn group\n]\n\n[#IF [#ARGUMENT /VALUE file/ WORD /SPACE/ END]]\n[#IF [#EMPTYV file] |THEN|\n  #OUTPUT Syntax: CC <file> <collector> <comp-options>\n  #RESET FRAMES\n  #RETURN\n]\n\n[#IF NOT [#FILEINFO /EXISTENCE/ [file]]\n|THEN|\n  #OUTPUT [file] does not exist !\n  #RESET FRAMES\n  #RETURN\n]\n\n#PUSH #DEFAULTS vol subvol\n#SETMANY vol subvol src, [#FILEINFO /VOLUME, SUBVOL, FILE/ [file]]\nVOLUME [vol].[subvol]\n\n#SETV stem file\n#CHARDEL stem [#CHARCOUNT stem]\n#SET obj [stem]O\n#SETV stem src\n#CHARDEL stem [#CHARCOUNT stem]\n\n[#IF [#ARGUMENT /VALUE out/ DEVICE END]]\n[#IF [#EMPTYV out] |THEN| #SET out $T.#C]\n\n#SETMANY col group, [#FILEINFO /VOLUME, SUBVOL/ [out]]\n#SET locn [group].[stem]\n#SET sup [#LOOKUPPROCESS /ANCESTOR/ [col]]\n\n#SET options [#REST]\n\n== Find newest Header file\n#SET htime 0\n#SET file [#FILENAMES /MAXIMUM 1/ *H]\n[#LOOP |WHILE| NOT [#EMPTYV file]\n|DO|\n  #SET time [#FILEINFO /MODIFICATION/ [file]]\n  [#IF time > htime |THEN| #SETV htime time]\n\n  #SETV prev file\n  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ *H]\n]\n\n#SET stime [#FILEINFO /MODIFICATION/ [src]]\n#SET otime [#FILEINFO /MODIFICATION/ [obj]]\n\n#SET comp 0\n\n[#IF otime < htime\n|THEN|\n  #OUTPUT Header file(s) changed since object [obj] compiled\n  #SET comp -1\n]\n\n[#IF otime < stime\n|THEN|\n  #OUTPUT Source file [src] changed since object [obj] compiled\n  #SET comp -1\n]\n\n[#IF comp\n|THEN|\n  SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !\n  #SET buf\n  #OUTPUT Compiling [src]... [options]\n  C /IN [src], OUT [out].[stem]/[obj];SYMBOLS,HIGHPIN [options]\n  [#CASE [tacl^completioncode]\n  | 0 |\n    #OUTPUT Compiled OK: [src]\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !\n    #SET _completion:completioncode 0\n  | 1 |\n    #OUTPUT [src]: Compile Warnings\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS\n    #OUTPUTV buf\n  |OTHERWISE|\n    #OUTPUT [src]: Compile FAILED !\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS\n    #OUTPUTV buf\n  ]\n|ELSE|\n  #OUTPUT Object file [obj] is up to date\n  #SET _completion:completioncode 0\n]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/doit",
    "content": "?tacl macro\n#frame\n#push zipfile\n#SET zipfile [#FILEINFO /SUBVOL/ A]\n\nunzip -a [zipfile] *.c  -x */*\n== Following not required\nRENAME apic     apicz\nRENAME apihelpc apihelpz\nRENAME timezonc timezonz\n\nunzip -a [zipfile] *.h -x */*\n\nunzip -aj [zipfile] tandem/*.h\n\nunzip -aj [zipfile] tandem/*.c\n\nunzip -aj [zipfile] tandem/* -x tandem/*.*\n\n#unframe\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/macros",
    "content": "?section ADD^LIST routine\n[#IF [#ARGUMENT /VALUE item/ WORD/SPACE/]]\n#APPEND bin ADD * FROM [item]\n#SET itime [#FILEINFO /MODIFICATION/ [item]]\n[#IF itime > ntime |THEN| #SETV ntime itime]\n\n?section BBZIPLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list CRYPTO\nadd^list DEFLATEO\nadd^list FILEIOO\nadd^list GLOBALSO\nadd^list TANDEMO\nadd^list TANZIPO\nadd^list TREESO\nadd^list TTYIOO\nadd^list UTILO\nadd^list ZIPFILEO\nadd^list ZIPUPO\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBZIP MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM ZIPO\n#APPEND bin select search ($system.system.c%2%, [lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ ZIPO] |THEN|\n  #OUTPUT %1% is older than ZIPO\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section BBANY MACRO\n#FRAME\n#push bin memory anytime build\n#SET build 0\n#SETMANY memory, %2% LARGE\n#OUTPUT Building %1% with [memory] memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM %1%O\n#APPEND bin select search ($system.system.c[memory],[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET anytime [#FILEINFO /MODIFICATION/ %1%]\n[#IF anytime < [#FILEINFO /MODIFICATION/ %1%O] |THEN|\n  #OUTPUT %1% is older than %1%O\n  #SET build -1\n]\n[#IF anytime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n\n?section BBUNZIPLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list CRYPTO\nadd^list ENVARGSO\nadd^list EXPLODEO\nadd^list EXTRACTO\nadd^list FILEIOO\nadd^list GLOBALSO\nadd^list INFLATEO\nadd^list LISTO\nadd^list MATCHO\nadd^list PROCESSO\nadd^list TANDEMO\nadd^list TANUNZO\nadd^list TTYIOO\nadd^list UNSHRINO\nadd^list ZIPINFOO\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBUNZIP MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM UNZIPO\n#APPEND bin select search ($system.system.c%2%,[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPO] |THEN|\n  #OUTPUT %1% is older than UNZIPO\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section BBSFXLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list EXTRACTX\nadd^list FILEIOX\nadd^list GLOBALSX\nadd^list INFLATEX\nadd^list MATCHX\nadd^list PROCESSX\nadd^list TANDEMX\nadd^list TANUNZX\nadd^list TTYIOX\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBSFX MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM UNZIPX\n#APPEND bin select search ($system.system.c%2%,[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPX] |THEN|\n  #OUTPUT %1% is older than UNZIPX\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section accel^file MACRO\n#FRAME\n#PUSH buf\n[#IF [#FILEINFO /MODIFICATION/ %1%]\n   > [#FILEINFO /MODIFICATION/ %2%]\n|THEN|\n  #OUTPUT %2% is older than %1%\n  #OUTPUT Accelerating %1% to %2%\n  AXCEL /OUTV buf/ %1%,%2%\n  #OUTPUTV buf\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Accelerated %2% OK\n  | 1         | #OUTPUT %2%: AXCEL Failed with Warnings\n  | OTHERWISE | #OUTPUT %2%: AXCEL Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %2% is up to date\n]\n\n#UNFRAME\n\n?section fup^license ROUTINE\n#FRAME\n#PUSH #DEFAULTS filename old^user current^user\n\n[#IF [#ARGUMENT /VALUE filename/ FILENAME]]\n\n#SET old^user [#USERNAME [#PROCESSINFO /PAID/]]\n#SETV current^user old^user\n[#LOOP |WHILE| current^user '<>' \"SUPER.SUPER\"\n               AND NOT [#INPUTEOF]\n|DO|\n  #OUTPUT Please log on as SUPER.SUPER (CTRL-Y aborts)\n  logon SUPER.SUPER\n  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]\n  #OUTPUT\n]\n\n[#IF current^user '=' \"SUPER.SUPER\" |THEN|\n  #OUTPUT Licensing [filename]\n  $SYSTEM.SYSTEM.FUP LICENSE [filename]\n]\n\n[#LOOP |WHILE| current^user '<>' old^user\n               AND NOT [#INPUTEOF]\n|DO|\n  #OUTPUT Please log on as [old^user] (CTRL-Y aborts)\n  logon [old^user]\n  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]\n  #OUTPUT\n]\n\n#UNFRAME\n\n\n?section CODE routine\n#FRAME\n#PUSH delta arg\n\n#SET /TYPE delta/ DELTA\n\n[#LOOP |WHILE| [#COMPUTE [#ARGUMENT /VALUE arg/ NUMBER END] = 1 ]\n|DO|\n  #APPEND DELTA [arg]I\n]\n\n#RESULT [#DELTA /COMMANDS DELTA/]\n\n#UNFRAME\n\n\n?section TACL^COMPLETIONCODE routine\n#RESULT [_completion:completioncode]\n\n?SECTION INCREMENT routine\n#FRAME\n#PUSH increment_variable increment_value\n\n[#IF [#ARGUMENT /VALUE increment_variable/ VARIABLE]]\n[#IF [#EMPTYV [increment_variable]]|THEN|#SET [increment_variable] 0]\n[#IF [#MORE]\n  |THEN|\n    [#IF [#ARGUMENT /VALUE increment_value/ NUMBER]]\n  |ELSE|\n    #SET increment_value 1\n]\n[#IF [#ARGUMENT END]]\n\n#SET [increment_variable] [#COMPUTE [increment_variable] + [increment_value]]\n\n#UNFRAME\n\n?section ERROR^IN^FUP^OUTPUT routine\n#FRAME\n#PUSH err output last line type\n\n#SETMANY err output, 0 0\n\n[#LOOP |WHILE| NOT [#EMPTYV fup^out]\n|DO|\n   #EXTRACTV fup^out line\n   [#SETMANY type, [#CHARGET line 1 TO 7] .]\n   [#CASE [type]\n     | ERROR     | #SETMANY output err, -1 -1\n     | WARNING   | #SET output -1\n     | OTHERWISE |\n   ]\n   [#IF output |THEN|\n     #OUTPUTV last\n     #OUTPUTV line\n     #SET output 0\n     #EXTRACTV fup^out line\n   ]\n   #SETV last line\n]\n\n#RESULT [err]\n\n#UNFRAME\n\n?section SECURE^FILE routine\n#FRAME\n\n[#DEF fup^out TEXT |BODY|]\n[#DEF fup^buf TEXT |BODY|]\n\n[#DEF fup^cmd MACRO |BODY|\n  FUP /OUTV fup^out/ %*%\n  #SETV fup^buf fup^out\n  [#IF [error^in^fup^output]\n  |THEN|\n    #OUTPUT Error detected in FUP output, ABORTING !!\n    #OUTPUT ..............................................................\n    #OUTPUTV fup^buf\n    #OUTPUT ..............................................................\n    #RAISE _BREAK\n  ]\n]\n\n[#DEF display^action MACRO |BODY|\n  [#IF NOT action |THEN|\n    #OUTPUT /HOLD/ Updating [file] ...\n    #SET action -1\n    #SET count 0\n  ]\n  #OUTPUT /COLUMN 3/ ... %*%\n]\n\n[#DEF display^noaction MACRO |BODY|\n  [#IF count\n  |THEN|\n    increment count\n  |ELSE|\n    #OUTPUT\n    #SET count 1\n  ]\n  [#IF count |THEN|\n    #OUTPUT /COLUMN [count]/ [code 27]A.\n    [#IF count > 75\n    |THEN|\n      #SET count 0\n    ]\n  ]\n]\n\n[#DEF process^file TEXT |BODY|\n  #SET action 0\n  #SETMANY cur^owner cur^security cur^license cur^progid, &\n    [#FILEINFO /OWNER, SECURITY, LICENSED, PROGID/ [file]]\n\n  #SET cur^owner [#USERNAME [cur^owner]]\n\n  [#IF NOT [#EMPTYV owner]\n  |THEN|\n    [#IF owner '<>' cur^owner\n    |THEN|\n      display^action giving to [owner]  (was [cur^owner])\n      fup^cmd GIVE [file], [owner]\n      [#IF cur^progid\n      |THEN|\n        #OUTPUT /COLUMN 3/... WARNING!  Loss of PROGID flag\n        #SET cur^progid 0\n      ]\n    ]\n  ]\n  [#IF NOT [#EMPTYV security]\n  |THEN|\n    [#IF security '<>' cur^security\n    |THEN|\n      display^action securing to [security] (was [cur^security])\n      fup^cmd SECURE [file], [security]\n    ]\n  ]\n  [#IF license |THEN|\n    [#IF NOT cur^license\n    |THEN|\n      display^action licensed\n      fup^cmd LICENSE [file]\n    ]\n  ]\n  [#IF progid |THEN|\n    [#IF NOT cur^progid\n    |THEN|\n      display^action PROGID flag set\n      fup^cmd SECURE [file],, PROGID\n    ]\n  ]\n  [#IF action\n  |THEN|\n    fup^cmd INFO [file]\n  |ELSE|\n    [#IF tflag\n    |THEN|\n      display^noaction\n    |ELSE|\n      #OUTPUT  /HOLD/ Unchanged : [file]\n      [#IF cur^progid  |THEN| #OUTPUT /COLUMN 39,HOLD/ P]\n      [#IF cur^license |THEN| #OUTPUT /COLUMN 40,HOLD/ L]\n      #OUTPUTV /COLUMN 43,HOLD/ cur^security\n      #OUTPUTV /COLUMN 50,HOLD/ cur^owner\n      #OUTPUT\n    ]\n ]\n]\n\n#PUSH arg template file security owner progid license prev action count tflag\n#PUSH cur^security cur^owner cur^license cur^progid\n\n#SETMANY license progid, 0 0\n#SET count 0\n#SET tflag 0\n\n[#LOOP |WHILE| [#MORE]\n|DO|\n  [#CASE [#ARGUMENT /VALUE arg/ FILENAME\n                                USER /USERNAME/\n                                USER\n                                SECURITY\n                                KEYWORD /WORDLIST LICENSE/\n                                KEYWORD /WORDLIST PROGID/\n                                TEMPLATE\n         ]\n  | 1 | #SETV file     arg\n  | 2 | #SETV owner    arg\n  | 3 | #SET  owner [#USERNAME [arg]]\n  | 4 | #SETV security arg\n  | 5 | #SET  license  -1\n  | 6 | #SET  progid   -1\n  | 7 | #SETV template arg\n  ]\n]\n[#IF [#ARGUMENT END]]\n\n\n[#IF [#EMPTYV template]\n|THEN|\n  #SETV template file\n|ELSE|\n  #SET tflag -1\n  #OUTPUT /HOLD/ Template : [template]\n  [#IF progid  |THEN| #OUTPUT /COLUMN 39,HOLD/ P]\n  [#IF license |THEN| #OUTPUT /COLUMN 40,HOLD/ L]\n  [#IF NOT [#EMPTYV security] |THEN| #OUTPUTV /HOLD/ \"  \"[security]\"\"]\n  [#IF NOT [#EMPTYV owner]    |THEN| #OUTPUTV /HOLD/ \"  [owner]\"]\n  #OUTPUT\n]\n\n[#IF [#EMPTYV template]\n|THEN|\n  #OUTPUT ERROR!  No filename specified\n  #RESET FRAMES\n  #RETURN\n|ELSE|\n  #SET file [#FILENAMES /MAXIMUM 1/ [template]]\n  [#LOOP |WHILE| NOT [#EMPTYV file]\n  |DO|\n    process^file\n    #SETV prev file\n    #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ [template]]\n  ]\n]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/make",
    "content": "?tacl routine\n#FRAME\nSINK [#LOAD /keep 1/ commacs]\nSINK [#LOAD /keep 1/ macros]\n\n[#PUSH file prev memory clib OK model unzip lib accel unlicensed licensed\n       options fileset nocrypt crypt arg^value object^owner object^security\n       deflate64\n]\n#PUSH #DEFAULTS\n\n#SET OK -1\n\n== Customise the following values for your environment\n#SET object^owner    SUPER.DAVES\n#SET object^security \"UUUU\"\n\n[#LOOP |WHILE| [#MORE] |DO|\n  [#CASE [#ARGUMENT /VALUE arg^value/\n           KEYWORD /WORDLIST LARGE SMALL/\n           KEYWORD /WORDLIST NOWIDE WIDE/\n           KEYWORD /WORDLIST UNLICENSED/\n           KEYWORD /WORDLIST NOCRYPT/\n           KEYWORD /WORDLIST DEFLATE64 NODEFLATE64/\n           TEMPLATE FILENAME ]\n    |1| #SET memory [arg^value]\n    |2| #SET model [arg^value]\n    |3| #SET unlicensed [arg^value]\n    |4| #SET nocrypt [arg^value]\n    |5| #SET deflate64 [arg^value]\n    |6| #SET fileset [arg^value]\n    |OTHERWISE|\n  ]\n]\n\n[#IF [#EMPTYV memory] |THEN| #SET memory LARGE]\n[#IF [#EMPTYV model] |THEN| #SET model NOWIDE]\n[#IF [#EMPTYV deflate64] |THEN| #SET deflate64 DEFLATE64]\n\n[#IF model '=' \"WIDE\"\n  |THEN| #SETV clib model\n  |ELSE| #SETV clib memory\n]\n\n[#IF model '=' \"WIDE\"\n|THEN|\n  #SET unzip UNZIPW\n|ELSE|\n  #SET unzip UNZIPL\n]\n#SET lib [unzip]B\n#SET accel UNZIP\n#SET options [options], [model]\n\n[#IF unlicensed '=' \"UNLICENSED\"\n|THEN|\n  #SET unzip [unzip]U\n  #SET accel [accel]U\n  #SET lib   [lib]U\n|ELSE|\n  #SET licensed LICENSED\n  #SET options [options], define [licensed]\n]\n\n[#IF nocrypt '=' \"NOCRYPT\"\n|THEN|\n|ELSE|\n  #SET crypt USE_CRYPT\n  #SET options [options], define [crypt]\n]\n\n[#IF deflate64 '=' \"NODEFLATE64\"\n|THEN|\n  #SET options [options], define NO_DEFLATE64\n]\n\n[#IF [#EMPTYV fileset] |THEN| #SET fileset *C]\n\n#OUTPUT Files to compile: [fileset]\n#OUTPUT Pointer Model   : [model]\n#OUTPUT Memory Model    : [memory]\n#OUTPUT C Library       : [clib]\n#OUTPUT Axcel Object    : [accel]\n#OUTPUT Run Object      : [unzip]\n#OUTPUT Library Object  : [lib]\n#OUTPUT Compile Options : [options]\n#OUTPUT\n\n#SET file [#FILENAMES /MAXIMUM 1/ [fileset]]\n[#LOOP |while| NOT [#EMPTYV file]\n|DO|\n  #SETV prev file\n  CC [file] $T.#UNZIP [options]\n  [#IF [tacl^completioncode] > 1 |THEN| #set OK 0 ]\n  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ [fileset]]\n]\n\n[#IF OK |THEN|\n  BBUNZIPLIB\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n#PUSH #PROCESSFILESECURITY\nVOLUME ,\"NUNU\"\n\n[#IF OK |THEN|\n  BBUNZIP [unzip] [clib]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n[#IF OK |THEN|\n  secure^file [accel] [object^security] [object^owner]\n  accel^file [unzip] [accel]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n[#IF OK\n  |THEN| #OUTPUT Successfully produced Accelerated Object [accel]\n         secure^file [accel] [object^security] [object^owner]\n         [#IF [#INTERACTIVE] |THEN|\n           [#IF licensed '=' \"LICENSED\" |THEN|\n             #OUTPUT [accel] will not run without being LICENSED\n             [#IF [#FILEINFO /LICENSED/ [accel]]\n             |THEN|\n               #OUTPUT [accel] already LICENSED\n             |ELSE|\n               [#IF [#MATCH Y* [#INPUT [accel] License [accel] ?]] |THEN|\n                 fup^license [accel]\n               ]\n             ]\n           ]\n         ]\n  |ELSE| #OUTPUT Failed to produce Accelerated Object [accel]\n]\n\n#OUTPUT Finished\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/makesfx",
    "content": "?tacl routine\n#FRAME\nload /keep 1/ commacs\n\n#PUSH file prev memory OK model sfx lib accel unlicensed licensed options\n#PUSH #DEFAULTS\n\nload /keep 1/ macros\n\n#SET OK -1\n\n[#IF [#ARGUMENT /VALUE memory/ KEYWORD /WORDLIST LARGE WIDE/ OTHERWISE ]]\n[#IF [#ARGUMENT /VALUE unlicensed/ KEYWORD /WORDLIST UNLICENSED/ OTHERWISE ]]\n\n[#IF memory '=' \"WIDE\"\n|THEN|\n  #SET model WIDE\n  #SET sfx   SFX\n|ELSE|\n  #SET memory LARGE\n  #SET model NOWIDE\n  #SET sfx   SFX\n]\n#OUTPUT Creating SFX Module\n#SET lib [sfx]B\n#SET accel SFX\n\n#SET options [options], [model], define SFX\n\n[#IF unlicensed '=' \"UNLICENSED\"\n|THEN|\n  #SET sfx   [sfx]U\n  #SET accel [accel]U\n  #SET lib   [lib]U\n|ELSE|\n  #SET licensed LICENSED\n  #SET options [options], define [licensed]\n]\n\n#OUTPUT Memory Model    : [memory]\n#OUTPUT Axcel Module    : [accel]\n#OUTPUT Run Module      : [sfx]\n\n[#IF [#FILEINFO /MODIFICATION/ EXTRACTC] > [#FILEINFO /MODIFICATION/ EXTRACTX]\n|THEN|\n  #OUTPUT Compiling EXTRACTC for SFX\n  C /IN EXTRACTC, OUT $T.#SFX.EXTRACT/EXTRACTX;SYMBOLS,HIGHPIN [options]\n|ELSE|\n  #OUTPUT EXTRACT(SFX) is up to date\n]\n\n[#IF [#FILEINFO /MODIFICATION/ PROCESSC] > [#FILEINFO /MODIFICATION/ PROCESSX]\n|THEN|\n  #OUTPUT Compiling PROCESSC for SFX\n  C /IN PROCESSC, OUT $T.#SFX.PROCESS/PROCESSX;SYMBOLS,HIGHPIN [options]\n|ELSE|\n  #OUTPUT PROCESS(SFX) is up to date\n]\n\n[#IF [#FILEINFO /MODIFICATION/ TANUNZC] > [#FILEINFO /MODIFICATION/ TANUNZX]\n|THEN|\n  #OUTPUT Compiling TANUNZC for SFX\n  C /IN TANUNZC , OUT $T.#SFX.TANUNZ /TANUNZX ;SYMBOLS,HIGHPIN [options]\n|ELSE|\n  #OUTPUT TANUNZ(SFX) is up to date\n]\n\n[#IF [#FILEINFO /MODIFICATION/ UNZIPC] > [#FILEINFO /MODIFICATION/ UNZIPX]\n|THEN|\n  #OUTPUT Compiling UNZIPC for SFX\n  C /IN UNZIPC  , OUT $T.#SFX.UNZIP  /UNZIPX  ;SYMBOLS,HIGHPIN [options]\n|ELSE|\n  #OUTPUT UNZIP(SFX) is up to date\n]\n\nBBSFXLIB\nBBSFX [sfx] [memory]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/tandem.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * routines common to TANDEM (ZIP and UNZIP)\n */\n\n#include \"zip.h\"   /* This sets up ZIP / UNZIP define */\n\n#include <tal.h>\n#include \"$system.zsysdefs.zsysc\" nolist\n#include <cextdecs> nolist\n#include \"tannsk.h\"\n\nstatic time_t gmt_to_time_t (long long *);\n\nint isatty (fnum)\nint fnum;\n{\n  return 1;\n}\n\n/********************/\n/* Function in2ex() */\n/********************/\n\n#ifdef UNZIP\nchar *in2ex(__G__ n)\n  __GDEF\n#else\nchar *in2ex(n)\n#endif\n  char *n;              /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name buffer */\n  char *y;              /* pointer to external buffer */\n  char *max;            /* pointer to max end of next file part */\n  char *t;              /* pointer to internal - start of substring */\n  char *p;              /* pointer to internal - TANDEM delimiter */\n  char *e;              /* pointer to internal - DOS extension delimiter */\n  char *z;              /* pointer to internal - end of substring */\n  int len;              /* length of substring to copy to external name */\n  int allow_dollar;     /* $ symbol allowed as next character */\n\n  if ((x = malloc(strlen(n) + 4)) == NULL)  /* + 4 for safety */\n    return NULL;\n\n  *x = '\\0';\n\n  /* Junk pathname as requested */\n#ifdef UNZIP\n  if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)\n    ++t;\n  else\n    t = n;\n#endif /* UNZIP */\n#ifdef ZIP\n  if (!pathput)\n    t = last(n, INTERNAL_DELIMITER);\n  else\n    t = n;\n#endif /* ZIP */\n\n  allow_dollar = TRUE;\n\n  while (*t != '\\0') {  /* File part could be sys, vol, subvol or file */\n    if (*t == INTERNAL_DELIMITER) {    /* System, Volume or Subvol Name */\n      t++;\n      if (*t == INTERNAL_DELIMITER) {  /* System */\n        strcat(x, TANDEM_NODE_STR);\n        t++;\n      }\n      else {\n        strcat(x, TANDEM_DELIMITER_STR);\n        allow_dollar = FALSE;\n      }\n    }\n    /* Work out where end of current external string is */\n    y = x + strlen(x);\n\n    /* Work out substring to copy and externalise */\n    p = strchr(t, INTERNAL_DELIMITER);\n    e = strchr(t, DOS_EXTENSION);\n    if (p != NULL) {\n      if (e > p)\n        e = NULL;\n    }\n\n    z = e;\n    if (z == NULL)\n      z = p;\n    if (z == NULL)\n      z = t + strlen(t);\n\n    /* can't have Tandem name longer than 8 characters */\n    max = y + MAXFILEPARTLEN;\n\n    /* Allow $ symbol as first character in some cases */\n    if (*t == '$') {\n      if (allow_dollar)\n        *y++ = *t++;\n      else;\n        *t++;\n    }\n\n    /* Make sure first real character is alpha */\n    if (! isalpha(*t) )\n      *y++ = 'A';\n\n    /* Characters left to process */\n    len = z - t;\n\n    while ( len > 0 ) {\n      if ( isalnum(*t) ) {\n        *y++ = toupper(*t++);\n        if (y >= max)\n          break;\n      }\n      else\n        t++;\n      len--;\n    }\n    *y = '\\0';\n    t = p;\n\n    if (p == NULL) {\n      /* Last part of filename, store pseudo extension if available */\n      if (e != NULL) {\n        strcat(x, TANDEM_EXTENSION_STR);\n        y = x + strlen(x);\n\n        /* no restriction on extension length as its virtual */\n        z = e + 1;\n        while ( *z != '\\0' ) {\n          *y++ = toupper(*z++);\n        }\n        *y = '\\0';\n      }\n      break;\n    }\n  }\n\n  return x;\n}\n\nvoid zexit(status)\n  int status;\n{\n  /* Exit(>0) creates saveabend files */\n  terminate_program (0,0,(short)status,,,);\n}\n\n/************************/\n/*  Function zputc()    */\n/************************/\n\n#ifdef putc\n#  undef putc\n#endif\n\nint zputc(ch, fptr)\n  int ch;\n  FILE *fptr;\n{\n  int err;\n  err = putc(ch,fptr);\n  fflush(fptr);\n  return err;\n}\n#define putc zputc\n\n#ifdef LICENSED\n_tal _priv short FILE_CHANGELABEL_ (\n short,          /* IN */\n short,          /* IN */\n const short _far *    /* IN */\n );\n\n_c _callable int changelabel OF((short, const short *, const short *));\n\n_c _callable int changelabel(fnum, modtime, actime)\n  short fnum;\n  const short *modtime;\n  const short *actime;\n{\n  int err;\n\n  err = FILE_CHANGELABEL_(fnum, 16, modtime);\n  if (!err)\n    err = FILE_CHANGELABEL_(fnum, 17, actime);\n  return err;\n}\n\nint islicensed(void)\n{\n  #define plist_items 1\n  #define plist_size 10\n\n  short myphandle[ZSYS_VAL_PHANDLE_WLEN];\n  short licensetag[plist_items] = {37};\n  short licensed[plist_size];\n  short maxlen = plist_size;\n  short items = plist_items;\n  short resultlen[1], err;\n\n  err = PROCESSHANDLE_NULLIT_(myphandle);\n\n  if (!err)\n    err = PROCESS_GETINFO_(myphandle);\n\n  if (!err)\n    err = PROCESS_GETINFOLIST_(/*cpu*/,\n                               /*pin*/,\n                               /*nodename*/,\n                               /*nodenamelen*/,\n                               myphandle,\n                               licensetag,\n                               items,\n                               licensed,\n                               maxlen,\n                               resultlen\n                              );\n\n  if (err != 0)\n    return 0;\n  else\n    return licensed[0];\n}\n#endif /* LICENSED */\n\nint utime(file, time)\n  const char *file;\n  const ztimbuf *time;\n{\n#ifdef LICENSED\n  int result, err;\n  union timestamp_ov {\n    long long fulltime;\n    short wordtime[4];\n  };\n  union timestamp_ov lasttime, opentime;\n  struct tm *modt, *opent;\n  short datetime[8], errormask[1];\n  short len, fnum, access, exclus, options;\n  char fname[FILENAME_MAX + 1];\n  short extension;\n  char ext[EXTENSION_MAX + 1];\n\n  if (islicensed() ) {\n    /* Attempt to update file label */\n    modt = gmtime( &time->modtime );\n\n    datetime[0] = modt->tm_year + 1900;\n    datetime[1] = modt->tm_mon + 1;\n    datetime[2] = modt->tm_mday;\n    datetime[3] = modt->tm_hour;\n    datetime[4] = modt->tm_min;\n    datetime[5] = modt->tm_sec;\n    datetime[6] = datetime[7] = 0;\n    errormask[0] = 0;\n    lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);\n\n    opent = gmtime( &time->actime );\n\n    datetime[0] = opent->tm_year + 1900;\n    datetime[1] = opent->tm_mon + 1;\n    datetime[2] = opent->tm_mday;\n    datetime[3] = opent->tm_hour;\n    datetime[4] = opent->tm_min;\n    datetime[5] = opent->tm_sec;\n    datetime[6] = datetime[7] = 0;\n    errormask[0] = 0;\n    opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);\n\n    /* Remove any (pseudo) file extension */\n    extension = parsename (file,fname,ext);\n    len = strlen(fname);\n\n    access = NSK_WRONLY;\n    exclus = NSK_SHARED;\n    options = NSK_NOUPDATEOPENTIME;\n\n    extension = parsename (file,fname,ext);\n    len = strlen(fname);\n\n    err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n    result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);\n    err = FILE_CLOSE_(fnum);\n    return result;\n  }\n  return -1;\n#else  /* !LICENSED */\n  return 0;             /* \"no error\", to suppress annoying failure messages */\n#endif  /* ?LICENSED */\n}\n\n/* TANDEM version of chmod() function */\n\nint chmod(file, unix_sec)\n  const char *file;\n  mode_t unix_sec;\n{\n  FILE *stream;\n  struct nsk_sec_type {\n    unsigned progid : 1;\n    unsigned clear  : 1;\n    unsigned null   : 2;\n    unsigned read   : 3;\n    unsigned write  : 3;\n    unsigned execute: 3;\n    unsigned purge  : 3;\n  };\n  union nsk_sec_ov {\n    struct nsk_sec_type bit_ov;\n    short int_ov;\n  };\n  union nsk_sec_ov nsk_sec;\n  short fnum, err, nsk_sec_int;\n  short len, access, exclus, extension, options;\n  char fname[FILENAME_MAX + 1];\n  char ext[EXTENSION_MAX + 1];\n\n  nsk_sec.bit_ov.progid = 0;\n  nsk_sec.bit_ov.clear  = 0;\n  nsk_sec.bit_ov.null   = 0;\n\n  /*  4=\"N\", 5=\"C\", 6=\"U\", 7=\"-\"   */\n\n  if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;\n  else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;\n  else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;\n  else nsk_sec.bit_ov.read = 7;\n\n  if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;\n  else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;\n  else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;\n  else nsk_sec.bit_ov.write = 7;\n\n  if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;\n  else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;\n  else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;\n  else nsk_sec.bit_ov.execute = 7;\n\n  nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;\n\n  nsk_sec_int = nsk_sec.int_ov;\n\n  access = NSK_RDONLY;\n  exclus = NSK_SHARED;\n  options = NSK_NOUPDATEOPENTIME;\n\n  extension = parsename (file,fname,ext);\n  len = strlen(fname);\n\n  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n  err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE);\n  err = FILE_CLOSE_(fnum);\n\n  return (err != 0 ? -1 : 0);\n}\n\n/* TANDEM version of chown() function */\n\nint chown(file, uid, gid)\n  const char *file;\n  uid_t uid;\n  gid_t gid;\n{\n  FILE *stream;\n  struct nsk_own_type {\n    unsigned group  : 8;\n    unsigned user   : 8;\n  };\n  union nsk_own_ov {\n    struct nsk_own_type bit_ov;\n    short int_ov;\n  };\n  union nsk_own_ov nsk_own;\n  short fnum, err, nsk_own_int;\n  short len, access, exclus, extension, options;\n  char fname[FILENAME_MAX + 1];\n  char ext[EXTENSION_MAX + 1];\n\n  nsk_own.bit_ov.group = gid;\n  nsk_own.bit_ov.user  = uid;\n\n  nsk_own_int = nsk_own.int_ov;\n\n  access = NSK_RDONLY;\n  exclus = NSK_SHARED;\n  options = NSK_NOUPDATEOPENTIME;\n\n  extension = parsename (file,fname,ext);\n  len = strlen(fname);\n\n  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n  err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE);\n  err = FILE_CLOSE_(fnum);\n  return (err != 0 ? -1 : 0);\n}\n\n/* TANDEM version of getch() - non-echo character reading */\nint zgetch(void)\n{\n  char ch;\n  short f, err, count, fnum, rlen;\n\n  rlen = 1;\n  f = (short)fileno(stdin);\n  fnum = fdtogfn (f);\n  #define ECHO_MODE 20\n  err = (SETMODE(fnum, ECHO_MODE, 0) != CCE);\n  err = (READX(fnum, &ch, rlen, (short *) &count) != CCE);\n  err = (SETMODE(fnum, ECHO_MODE, 1) != CCE);\n\n  if (err)\n    if (err != 1)\n      return EOF;\n    else\n      ch = 'q';\n  else\n    if (count == 0)\n      ch = '\\r';\n\n  return (int)ch;\n}\n\nshort parsename(srce, fname, ext)\n  const char *srce;\n  char *fname;\n  char *ext;\n{\n  /* As a way of supporting DOS extensions from Tandem we look for a space\n     separated extension string after the Guardian filename\n     e.g. ZIP ZIPFILE \"$DATA4.TESTING.INVOICE TXT\"\n  */\n\n  char *fstart;\n  char *fptr;\n  short extension = 0;\n\n  *fname = *ext = '\\0';  /* set to null string */\n\n  fstart = (char *) srce;\n\n  if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {\n    extension = 1;\n\n    fptr++;\n    strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));\n\n    fptr = strchr(fstart, TANDEM_EXTENSION);  /* End of filename */\n    strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));\n  }\n  else {\n    /* just copy string */\n    strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));\n  }\n\n  return extension;\n}\n\nstatic time_t gmt_to_time_t (gmt)\n  long long *gmt;\n{\n  #define GMT_TO_LCT 0\n  #define GMT_TO_LST 1\n\n  struct tm temp_tm;\n  short  date_time[8];\n  long   julian_dayno;\n  long long lct, lst, itime;\n  short  err[1], type;\n\n  type = GMT_TO_LCT;\n  lct = CONVERTTIMESTAMP(*gmt, type,, err);\n\n  if (!err[0]) {\n    type = GMT_TO_LST;\n    lst = CONVERTTIMESTAMP(*gmt, type,, err);\n  }\n\n  itime = (err[0] ? *gmt : lct);\n  /* If we have no DST in force then make sure we give it a value,\n     else mktime screws up if we set the isdst flag to -1 */\n  temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1));\n\n  julian_dayno = INTERPRETTIMESTAMP(itime, date_time);\n\n  temp_tm.tm_sec   = date_time[5];\n  temp_tm.tm_min   = date_time[4];\n  temp_tm.tm_hour  = date_time[3];\n  temp_tm.tm_mday  = date_time[2];\n  temp_tm.tm_mon   = date_time[1] - 1;     /* C's so sad */\n  temp_tm.tm_year  = date_time[0] - 1900;  /* it's almost funny */\n\n  return (mktime(&temp_tm));\n}\n\n/* TANDEM version of stat() function */\nint stat(n, s)\n  const char *n;\n  struct stat *s;\n{\n  #define ilist_items 26\n  #define klist_items 4\n  #define slist_items 3\n  #define ulist_items 1\n  #define flist_size 100\n\n  short err, i, extension;\n  char fname[FILENAME_MAX + 1];\n  short fnamelen;\n  char ext[EXTENSION_MAX + 1];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44,\n                            50, 51, 52, 61, 63, 66, 67, 70, 72, 73,\n                            74, 75, 76, 77, 78, 79                 };\n  short ilen[ilist_items] ={ 4,  4,  4,  2,  1,  2,  1,  1,  1,  1,\n                             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\n                             1,  1,  1,  1,  1,  1                 };\n  short ioff[ilist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short klist[klist_items]={45, 46, 68, 69                         };\n  short klen[klist_items] ={ 1,  1,  1,  1                         };\n  short koff[klist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short slist[slist_items]={43, 80, 90                             };\n  short slen[slist_items] ={ 1,  1,  1                             };\n  short soff[slist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short ulist[ulist_items]={65                                     };\n  short ulen[ulist_items] ={ 1                                     };\n  short uoff[ulist_items];\n\n  short flist[flist_size];\n  short extra[2];\n  short *rlen=&extra[0];\n  short *err_item=&extra[1];\n  unsigned short *fowner;\n  unsigned short *fprogid;\n  char *fsec;\n\n  nsk_stat_ov *nsk_ov;\n  nsk_file_attrs *nsk_attr;\n\n  short end, count, kind, level, options, searchid;\n  short info[5];\n\n  /* Initialise stat structure */\n  s->st_dev = _S_GUARDIANOBJECT;\n  s->st_ino = 0;\n  s->st_nlink = 0;\n  s->st_rdev = 0;\n  s->st_uid = s->st_gid = 0;\n  s->st_size = 0;\n  s->st_atime = s->st_ctime = s->st_mtime = 0;\n  s->st_reserved[0] = 0;\n  s->st_reserved[1] = 0;\n  s->st_reserved[2] = 0;\n  nsk_ov = (nsk_stat_ov *)&s->st_reserved[0];\n  nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region;\n\n  /* Check to see if name contains a (pseudo) file extension */\n  extension = parsename (n,fname,ext);\n\n  fnamelen = strlen(fname);\n\n  options = 3; /* Allow Subvols and Templates */\n  err = FILENAME_SCAN_( fname,\n                        fnamelen,\n                        &count,\n                        &kind,\n                        &level,\n                        options\n                      );\n\n  /* allow kind == 2 (DEFINE names) */\n  if (err != 0) return -1;\n\n  if (kind == 1 || (kind == 0 && level < 2)) {\n    /* Pattern, Subvol Name or One part Filename - lets see if it exists */\n    err = FILENAME_FINDSTART_ ( &searchid,\n                                fname,\n                                fnamelen,\n                                ,\n                                DISK_DEVICE\n                              );\n\n    if (err != 0) {\n      end = FILENAME_FINDFINISH_ ( searchid );\n      return -1;\n    }\n\n    err = FILENAME_FINDNEXT_ ( searchid,\n                               fname,\n                               FILENAME_MAX,\n                               &fnamelen,\n                               info\n                              );\n    end = FILENAME_FINDFINISH_ ( searchid );\n\n    if (err != 0)\n      return -1;  /* Non existing template, subvol or file */\n\n    if (kind == 1 || info[2] == -1) {\n      s->st_mode = S_IFDIR;    /* Its an existing template or directory */\n      return 0;\n    }\n\n    /* Must be a real file so drop to code below to get info on it */\n  }\n\n  err = FILE_GETINFOLISTBYNAME_( fname,\n                                 fnamelen,\n                                 ilist,\n                                 ilist_items,\n                                 flist,\n                                 flist_size,\n                                 rlen,\n                                 err_item\n                               );\n  if (err != 0) return -1;\n\n  ioff[0] = 0;\n\n  /*  Build up table of offets into result list */\n  for (i=1; i < ilist_items; i++)\n    ioff[i] = ioff[i-1] + ilen[i-1];\n\n  /* Set up main stat fields */\n\n  /* Setup timestamps */\n  s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]);\n  s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]);\n  nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]);\n\n  s->st_size = *(off_t *)&flist[ioff[3]];\n\n  fowner = (unsigned short *)&flist[ioff[4]];\n  s->st_uid = *fowner & 0x00ff;\n  s->st_gid = *fowner >> 8;\n\n  /* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */\n  fsec = (char *)&flist[ioff[5]];\n  fprogid = (unsigned short *)&flist[ioff[6]];\n\n  s->st_mode = S_IFREG |  /* Regular File */\n  /*  Parse Read Flag */\n               ((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |\n               ((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |\n               ((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |\n  /*  Parse Write Flag */\n               ((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |\n               ((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |\n               ((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |\n  /*  Parse Execute Flag */\n               ((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |\n               ((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |\n               ((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |\n  /*  Parse Progid */\n               (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;\n\n  /* Set up NSK additional stat fields */\n  nsk_attr->progid   = (unsigned) flist[ioff[6]];\n  nsk_attr->filetype = (unsigned) flist[ioff[7]];\n  nsk_attr->filecode = (unsigned) flist[ioff[8]];\n  nsk_attr->block    = (unsigned short) flist[ioff[9]];\n  nsk_attr->priext   = (unsigned short) flist[ioff[10]];\n  nsk_attr->secext   = (unsigned short) flist[ioff[11]];\n  nsk_attr->maxext   = (unsigned short) flist[ioff[12]];\n  nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]];\n  nsk_attr->licensed     = (unsigned) flist[ioff[14]];\n  nsk_attr->flags.audited      = (unsigned) flist[ioff[15]];\n  nsk_attr->flags.acompress    = (unsigned) flist[ioff[16]];\n  nsk_attr->flags.refresheof   = (unsigned) flist[ioff[17]];\n  nsk_attr->flags.buffered     = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0);\n  nsk_attr->flags.verified     = (unsigned) flist[ioff[19]];\n  nsk_attr->flags.serial       = (unsigned) flist[ioff[20]];\n  nsk_attr->flags.crashopen    = (unsigned) flist[ioff[22]];\n  nsk_attr->flags.rollforward  = (unsigned) flist[ioff[23]];\n  nsk_attr->flags.broken       = (unsigned) flist[ioff[24]];\n  nsk_attr->flags.corrupt      = (unsigned) flist[ioff[25]];\n  nsk_attr->fileopen     = (unsigned) flist[ioff[21]];\n\n\n  if (nsk_attr->filetype == NSK_UNSTRUCTURED) {\n    /* extra info for Unstructured files */\n    err = FILE_GETINFOLISTBYNAME_( fname,\n                                   fnamelen,\n                                   ulist,\n                                   ulist_items,\n                                   flist,\n                                   flist_size,\n                                   rlen,\n                                   err_item\n                                 );\n    if (err != 0) return -1;\n\n    uoff[0] = 0;\n\n    /*  Build up table of offets into result list */\n    for (i=1; i < ulist_items; i++)\n      uoff[i] = uoff[i-1] + ulen[i-1];\n  }\n  else {\n    /* extra info for Structured files */\n    err = FILE_GETINFOLISTBYNAME_( fname,\n                                   fnamelen,\n                                   slist,\n                                   slist_items,\n                                   flist,\n                                   flist_size,\n                                   rlen,\n                                   err_item\n                                 );\n    if (err != 0) return -1;\n\n    soff[0] = 0;\n\n    /*  Build up table of offets into result list */\n    for (i=1; i < slist_items; i++)\n      soff[i] = soff[i-1] + slen[i-1];\n\n    nsk_attr->reclen   = (unsigned) flist[soff[0]];\n    nsk_attr->flags.secpart   = (unsigned) flist[soff[1]];\n    nsk_attr->flags.primpart  = (unsigned)\n     ( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 );\n\n    if (nsk_attr->filetype == NSK_KEYSEQUENCED) {\n      /* extra info for Key Sequenced files */\n      err = FILE_GETINFOLISTBYNAME_( fname,\n                                     fnamelen,\n                                     klist,\n                                     klist_items,\n                                     flist,\n                                     flist_size,\n                                     rlen,\n                                     err_item\n                                   );\n      if (err != 0) return -1;\n\n      koff[0] = 0;\n\n      /*  Build up table of offets into result list */\n      for (i=1; i < klist_items; i++)\n        koff[i] = koff[i-1] + klen[i-1];\n\n      nsk_attr->keyoff   = (unsigned) flist[koff[0]];\n      nsk_attr->keylen   = (unsigned) flist[koff[1]];\n      nsk_attr->flags.dcompress = (unsigned) flist[koff[2]];\n      nsk_attr->flags.icompress = (unsigned) flist[koff[3]];\n    }\n  }\n\n  return 0;\n}\n\n#ifndef SFX\n/* TANDEM Directory processing */\n\nDIR *opendir(const char *dirname)\n{\n   short i, resolve;\n   char sname[FILENAME_MAX + 1];\n   short snamelen;\n   char fname[FILENAME_MAX + 1];\n   short fnamelen;\n   char *p;\n   short searchid, err, end;\n   struct dirent *entry;\n   DIR *dirp;\n   char ext[EXTENSION_MAX + 1];\n   short extension;\n\n   extension = parsename(dirname, sname, ext);\n   snamelen = strlen(sname);\n\n   /*  First we work out how detailed the template is...\n    *  e.g. If the template is DAVES*.* we want the search result\n    *       in the same format\n    */\n\n   p = sname;\n   i = 0;\n   while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){\n     i++;\n     p++;\n   };\n   resolve = 2 - i;\n\n   /*  Attempt to start a filename template */\n   err = FILENAME_FINDSTART_ ( &searchid,\n                               sname,\n                               snamelen,\n                               resolve,\n                               DISK_DEVICE\n                             );\n   if (err != 0) {\n     end = FILENAME_FINDFINISH_(searchid);\n     return NULL;\n   }\n\n   /* Create DIR structure */\n   if ((dirp = malloc(sizeof(DIR))) == NULL ) {\n     end = FILENAME_FINDFINISH_(searchid);\n     return NULL;\n   }\n   dirp->D_list = dirp->D_curpos = NULL;\n   strcpy(dirp->D_path, dirname);\n\n   while ((err = FILENAME_FINDNEXT_(searchid,\n                                    fname,\n                                    FILENAME_MAX,\n                                    &fnamelen\n                                   )\n           ) == 0 ){\n     /*  Create space for entry */\n     if ((entry = malloc (sizeof(struct dirent))) == NULL) {\n       end = FILENAME_FINDFINISH_(searchid);\n       return NULL;\n     }\n\n     /*  Link to last entry */\n     if (dirp->D_curpos == NULL)\n       dirp->D_list = dirp->D_curpos = entry;  /* First name */\n     else {\n       dirp->D_curpos->d_next = entry;         /* Link */\n       dirp->D_curpos = entry;\n     };\n     /* Add directory entry */\n     *dirp->D_curpos->d_name = '\\0';\n     strncat(dirp->D_curpos->d_name,fname,fnamelen);\n     if (extension) {\n       strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);\n       strcat(dirp->D_curpos->d_name,ext);\n     };\n     dirp->D_curpos->d_next = NULL;\n   };\n\n   end = FILENAME_FINDFINISH_(searchid);\n\n   if (err == 1) {  /*  Should return EOF at end of search */\n     dirp->D_curpos = dirp->D_list;        /* Set current pos to start */\n     return dirp;\n   }\n   else\n     return NULL;\n}\n\nstruct dirent *readdir(DIR *dirp)\n{\n   struct dirent *cur;\n\n   cur = dirp->D_curpos;\n   dirp->D_curpos = dirp->D_curpos->d_next;\n   return cur;\n}\n\nvoid rewinddir(DIR *dirp)\n{\n   dirp->D_curpos = dirp->D_list;\n}\n\nint closedir(DIR *dirp)\n{\n   struct dirent *node;\n\n   while (dirp->D_list != NULL) {\n      node = dirp->D_list;\n      dirp->D_list = dirp->D_list->d_next;\n      free( node );\n   }\n   free( dirp );\n   return 0;\n}\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/tandem.h",
    "content": "/*\n  Copyright (c) 1990-2006 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __tandem_h   /* prevent multiple inclusions */\n#define __tandem_h\n\n#ifndef TANDEM\n#  define TANDEM     /* better than __TANDEM */\n#endif\n\n/* LICENSED define now supplied by compile time option (MAKE) */\n\n#define NO_UNISTD_H\n#define NO_RMDIR\n#define NO_MKTEMP\n\n/* TANDEM supplies proper UTC vs. local time conversion, so enable Info-ZIP's\n   UT e.f. support unless explicitly suppressed by a compilation option. */\n#if (!defined(USE_EF_UT_TIME) && !defined(NO_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n#if (defined(NO_EF_UT_TIME) && defined(USE_EF_UT_TIME))\n#  undef USE_EF_UT_TIME\n#endif\n\n/* Include file for TANDEM */\n\n#ifndef NULL\n#  define NULL 0\n#endif\n\n#include <time.h>               /* the usual non-BSD time functions */\n#include <stdio.h>\n#include <sysstat.h>\n#include <unistd.h>\n#include <errno.h>\n#include <ctype.h>\n\n#define PASSWD_FROM_STDIN\n                  /* Kludge until we know how to open a non-echo tty channel */\n\n#define NSK_UNSTRUCTURED   0\n#define NSK_RELATIVE       1\n#define NSK_ENTRYSEQUENCED 2\n#define NSK_KEYSEQUENCED   3\n#define NSK_OBJECTFILECODE 100\n#define NSK_EDITFILECODE   101\n#define NSK_ZIPFILECODE    1001\n#define TANDEM_BLOCKSIZE   4096\n#define MAX_NORMAL_READ    4096\n#define MAX_EDIT_READ      255\n#define MAX_LARGE_READ        57344\n#define MAX_LARGE_READ_EXPAND 30720\n\n#define MAXFILEPARTLEN     8\n#define MAXPATHLEN         128\n#define EXTENSION_MAX      3\n/* FILENAME_MAX is defined in stdio.h */\n\n#define EXIT zexit      /*  To stop creation of Abend files */\n#define RETURN zexit    /*  To stop creation of Abend files */\n#define putc zputc      /*  To allow us to auto flush  */\n\n\n#define FOPR \"rb\"\n#define FOPM \"r+\"\n#define FOPW \"wb\"\n#define FOPWT \"w\"\n\n#define NAMELEN FILENAME_MAX+1+EXTENSION_MAX   /* allow for space extension */\n\nstruct dirent {\n   struct dirent *d_next;\n   char   d_name[NAMELEN+1];\n};\n\ntypedef struct _DIR {\n   struct  dirent *D_list;\n   struct  dirent *D_curpos;\n   char            D_path[NAMELEN+1];\n} DIR;\n\nDIR *          opendir(const char *dirname);\nstruct dirent *readdir(DIR *dirp);\nvoid           rewinddir(DIR *dirp);\nint            closedir(DIR *dirp);\nchar *         readd(DIR *dirp);\n\n#define DISK_DEVICE         3\n\n/* SETMODE Literals */\n#define SET_FILE_SECURITY   1\n#define SET_FILE_OWNER      2\n#define SET_FILE_BUFFERED   90\n#define SET_FILE_MAXEXTENTS 92\n#define SET_FILE_BUFFERSIZE 93\n#define SET_LARGE_TRANSFERS 141\n\n/* FILE_OPEN_ Literals */\n#define NSK_RDWR             0\n#define NSK_RDONLY           1\n#define NSK_WRONLY           2\n#define NSK_APPEND           3\n#define NSK_SHARED           0\n#define NSK_EXCLUSIVE        1\n#define NSK_PROCESSEXCLUSIVE 2\n#define NSK_PROTECTED        3\n#define NSK_UNSTRUCTUREDACCESS 0x8000\n#define NSK_NOUPDATEOPENTIME   0x2000\n\n#define NSK_NO_DELIMITER        0x0001\n#define NSK_USE_FF_DELIMITER    0x0002\n#define NSK_SPACE_FILL          0x0004\n#define NSK_TRIM_TRAILING_SPACE 0x0008\n#define NSK_LARGE_READ_EXPAND   0x0100     /* use smaller value for Expand */\n\n#define DOS_EXTENSION      '.'\n#define TANDEM_EXTENSION   ' '\n#define TANDEM_DELIMITER   '.'\n#define TANDEM_NODE        '\\\\'\n#define INTERNAL_DELIMITER '/'\n#define INTERNAL_NODE      '//'\n#define TANDEM_WILD_1      '*'\n#define TANDEM_WILD_2      '?'\n\n#define DOS_EXTENSION_STR      \".\"\n#define TANDEM_EXTENSION_STR   \" \"\n#define TANDEM_DELIMITER_STR   \".\"\n#define TANDEM_NODE_STR        \"\\\\\"\n#define INTERNAL_DELIMITER_STR \"/\"\n#define INTERNAL_NODE_STR      \"//\"\n\n/* Use 'spare' area at end of stat structure to hold additional Tandem/NSK\n   file details. Initially used to hold Creation time, now also holds most\n   Enscribe details */\n\nstruct nsk_stat_reserved\n{\n  int64_t spare[3];\n};\n\n#pragma FIELDALIGN SHARED8 nsk_owner\nstruct nsk_owner\n{\n  unsigned group   : 8;\n  unsigned user    : 8;\n};\n\n#pragma FIELDALIGN SHARED8 nsk_file_flags\nstruct nsk_file_flags\n{\n  unsigned buffered    : 1;\n  unsigned audited     : 1;\n  unsigned acompress   : 1;\n  unsigned icompress   : 1;\n  unsigned dcompress   : 1;\n  unsigned oddunstr    : 1;\n  unsigned verified    : 1;\n  unsigned serial      : 1;\n  unsigned refresheof  : 1;\n  unsigned broken      : 1;\n  unsigned corrupt     : 1;\n  unsigned primpart    : 1;\n  unsigned secpart     : 1;\n  unsigned crashopen   : 1;\n  unsigned rollforward : 1;\n  unsigned clearonpurge: 1;\n};\n\n#pragma FIELDALIGN SHARED8 nsk_file_attrs_def\nstruct nsk_file_attrs_def\n{\n  unsigned short filecode;  /* 16 */\n  unsigned short block;     /* 16 */  /* Allow of block > 4096 one day ! */\n  struct nsk_file_flags flags;     /* 16 */\n  struct nsk_owner owner;   /* 16 */\n  unsigned short priext;    /* 16 */\n  unsigned short secext;    /* 16 */\n  unsigned maxext    : 10;\n  unsigned read      : 3;\n  unsigned write     : 3;\n  unsigned execute   : 3;\n  unsigned delete    : 3;\n  unsigned licensed  : 1;\n  unsigned progid    : 1;\n  unsigned keylen    : 8;\n  unsigned           : 5;\n  unsigned keyoff    : 11;\n  unsigned           : 1;\n  unsigned filetype  : 2;\n  unsigned fileopen  : 1;\n  unsigned reclen    : 12;\n};\ntypedef struct nsk_file_attrs_def nsk_file_attrs;\n\n#pragma FIELDALIGN SHARED8 nsk_stat_overlay\nstruct nsk_stat_overlay\n{\n  time_t creation_time;       /* 32 bits */\n  nsk_file_attrs nsk_ef_region;\n /*  char   nsk_ef_region[20]; *//* EF region */\n};\n\ntypedef union\n{\n  struct nsk_stat_reserved reserved;\n  struct nsk_stat_overlay  ov;\n} nsk_stat_ov;\n\n/* Prototype function declarations */\n\nvoid zexit (int);\n\nint zputc(\n  int,\n  FILE *\n);\n\nint zgetch (void);\n\nshort parsename(\n  const char *,\n  char *,\n  char *\n);\n\nint islicensed (void);\n\n/* End of prototype function declarations */\n\n#endif /* !__tandem_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/tannsk.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  Header declaration(s) which are forced to go after earlier includes\n */\n\n#ifndef __tannsk_h   /* prevent multiple inclusions */\n#define __tannsk_h\n\n/* ztimbuf is declared in zip\\tailor.h after include of tandem.h */\nint utime (const char *, const ztimbuf *);\n\n#endif /* !__tannsk_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/tandem/tanunz.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  tanunz.c\n\n  Tandem/NSK routines for use with Info-ZIP's UnZip 5.3 and later.\n\n  Contains:  do_wild()           <-- generic enough to put in fileio.c?\n             ef_scan_for_tandem()\n             open_outfile()\n             mapattr()\n             mapname()\n             checkdir()\n             mkdir()\n             close_outfile()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#include <tal.h>\n#include \"$system.zsysdefs.zsysc\" nolist\n#include <cextdecs> nolist\n#include \"tannsk.h\"\n\n\nchar *in2ex OF((__GPRO__ char *));\n\nstatic nsk_file_attrs *ef_scan_for_tandem (\n    uch *ef_buf,\n    unsigned ef_len\n  );\n\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\n\n/****************************/\n/* Strings used in tanunz.c */\n/****************************/\n\nstatic ZCONST char Far CannotDeleteOldFile[] =\n  \"error:  cannot delete old %s\\n\";\nstatic ZCONST char Far CannotCreateFile[] = \"error:  cannot create %s\\n\";\n\n\n#ifndef SFX\n/**********************/\n/* Function do_wild() */  /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n    static char *intname;\n    int isdir = 0;\n    int pdosflag = 0;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(matchname, wildspec, FILNAMSIZ);\n            matchname[FILNAMSIZ-1] = '\\0';\n            have_dirname = FALSE;\n            wild_dir = NULL;\n            return matchname;\n        }\n\n        dirnamelen = strlen(wildspec);\n\n        if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  cannot allocate wildcard buffers\\n\"));\n             strncpy(matchname, wildspec, FILNAMSIZ);\n             matchname[FILNAMSIZ-1] = '\\0';\n             return matchname;   /* but maybe filespec was not a wildcard */\n        }\n        strcpy(dirname, wildspec);\n        wildname = wildspec;\n        have_dirname = FALSE;\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild: readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && wildname[0] != '.')\n                    continue;  /* Unix: '*' and '?' do not match leading dot */\n                if (match(file->d_name, wildname, 0 WISEP) && /* 0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild: match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 0 WISEP)) {   /* 0 == case sens. */\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n/*********************************/\n/* Function ef_scan_for_tandem() */\n/*********************************/\n\nstatic nsk_file_attrs *ef_scan_for_tandem(ef_buf, ef_len)\n    uch *ef_buf;                /* buffer containing extra field */\n    unsigned ef_len;            /* total length of extra field */\n{\n    unsigned eb_id;\n    unsigned eb_len;\n\n  /*---------------------------------------------------------------------------\n    This function scans the extra field for EF_TANDEM\n    -------------------------------------------------------------------------*/\n\n    if (ef_buf == NULL)\n      return NULL;\n\n    while (ef_len >= EB_HEADSIZE) {\n      eb_id = makeword(EB_ID + ef_buf);\n      eb_len = makeword(EB_LEN + ef_buf);\n\n      if (eb_len > (ef_len - EB_HEADSIZE)) {\n          /* discovered some extra field inconsistency! */\n          TTrace((stderr,\n            \"ef_scan_for_tandem: block length %u > rest ef_size %u\\n\", eb_len,\n            ef_len - EB_HEADSIZE));\n          break;\n      }\n\n      switch (eb_id) {\n        case EF_TANDEM:\n          return (nsk_file_attrs *)(char *)(ef_buf + EB_HEADSIZE);\n          break;\n\n        default:\n          break;\n      }\n\n      /* Skip this extra field block */\n      ef_buf += (eb_len + EB_HEADSIZE);\n      ef_len -= (eb_len + EB_HEADSIZE);\n  }\n\n  return NULL;\n}\n\n\n/***************************/\n/* Function open_outfile() */\n/***************************/\n\nint open_outfile(__G)           /* return 1 if fail */\n    __GDEF\n{\n    int fdesc;\n    short fnum, err, len;\n    int priext, secext;\n    short maxext, filecode, blocksize;\n\n    #define alist_items 1\n    #define vlist_bytes 2\n    short alist[alist_items]={42};\n    unsigned short vlist[alist_items];\n    short extra, *err_item=&extra;\n    nsk_file_attrs *znsk_attr;\n    ulg eof, pages;\n    char nsk_work[FILENAME_MAX + 1], *nsk_fname=&nsk_work[0];\n\n#ifdef DLL\n    if (G.redirect_data)\n        return (redirect_outfile(__G) == FALSE);\n#endif\n    if (SSTAT(G.filename, &G.statbuf) == 0) {\n        Trace((stderr, \"open_outfile:  stat(%s) returns 0:  file exists\\n\",\n          FnFilter1(G.filename)));\n        if (unlink(G.filename) != 0) {\n            Trace((stderr, \"open_outfile:  existing file %s is read-only\\n\",\n              FnFilter1(G.filename)));\n            chmod(G.filename, S_IRUSR | S_IWUSR);\n            Trace((stderr, \"open_outfile:  %s now writable\\n\",\n              FnFilter1(G.filename)));\n            if (unlink(G.filename) != 0) {\n                Info(slide, 0x401, ((char *)slide,\n                  LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));\n                return 1;\n            }\n        }\n        Trace((stderr, \"open_outfile:  %s now deleted\\n\",\n          FnFilter1(G.filename)));\n    }\n\n    /* Set up Tandem specific file information if present */\n    znsk_attr = ef_scan_for_tandem(G.extra_field, G.lrec.extra_field_length);\n    if (znsk_attr != NULL) {\n        /* Set extent sizes */\n        priext = znsk_attr->priext;\n        secext  = znsk_attr->secext;\n        maxext  = (int) znsk_attr->maxext;\n        /* If original file was Enscribe and text then recreate as Edit */\n        filecode = (znsk_attr->filetype != NSK_UNSTRUCTURED ?\n                    (G.pInfo->textmode ? NSK_EDITFILECODE : NSK_UNSTRUCTURED) :\n                    znsk_attr->filecode);\n        blocksize = znsk_attr->block;\n    } else {\n        /* Try to work out some decent sizes based on how big the file is */\n        eof = G.lrec.ucsize;\n        pages = (eof/2048) + 2;\n        if (pages <= 500) {\n            priext = pages; /* fits into one extent */\n            maxext = 16;\n        } else {\n            priext = 500; /* Try and fit into 500 page chunks */\n            maxext = pages/(priext - 50); /* Allow for Enscribe overhead */\n            if (maxext > 978) {\n                priext = eof >> 10;         /* 512 equal extents */\n                maxext = 978;                /* 2048 * 512 == 2^10 */\n            }\n        }\n        secext = priext;\n        filecode = (G.pInfo->textmode ? NSK_EDITFILECODE : NSK_UNSTRUCTURED);\n        blocksize = TANDEM_BLOCKSIZE;\n    }\n\n    if ((fdesc = creat(G.filename,,priext,secext)) != -1){\n        fnum = fdtogfn ((short)fdesc);\n        err = (SETMODE (fnum, SET_FILE_BUFFERSIZE, blocksize) != CCE);\n        err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 0) != CCE);\n        err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 1) != CCE);\n        err = (SETMODE (fnum, SET_FILE_MAXEXTENTS, maxext) != CCE);\n        err = close(fdesc);\n\n        vlist[0] = filecode;\n\n        /* Note that FILE_ALTERLIST_ expects uppercase names */\n        /* Need to call strlen and upshift                   */\n        len = strlen(G.filename);\n        err = STRING_UPSHIFT_(G.filename,\n                              len,\n                              nsk_fname,\n                              len);\n\n        err = FILE_ALTERLIST_(nsk_fname,\n                              len,\n                              alist,\n                              alist_items,\n                              vlist,\n                              vlist_bytes,\n                              ,\n                              err_item);\n    };\n\n    G.outfile = fopen(G.filename, (G.pInfo->textmode ? FOPWT : FOPW));\n\n    if (G.outfile == (FILE *)NULL) {\n        Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),\n          FnFilter1(G.filename)));\n        return 1;\n    }\n\n#ifdef USE_FWRITE\n#ifdef _IOFBF  /* make output fully buffered (works just about like write()) */\n    setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);\n#else\n    setbuf(G.outfile, (char *)slide);\n#endif\n#endif /* USE_FWRITE */\n    return 0;\n\n} /* end function open_outfile() */\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case TANDEM_:\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                return 0;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                   VMS (and probably others ??) leave 0 in the upper 16-bit\n                   part of the external_file_attributes field. Instead, they\n                   store file permission attributes in some extra field.\n                   As a work-around, we search for the presence of one of\n                   these extra fields and fall back to the MSDOS compatible\n                   part of external_file_attributes if one of the known\n                   e.f. types has been detected.\n                   Later, we might implement extraction of the permission\n                   bits from the VMS extra field. But for now, the work-around\n                   should be sufficient to provide \"readable\" extracted files.\n                   (For ASI Unix e.f., an experimental remap of the e.f.\n                   mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                return 0;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems without concept of \"group,\" \"other,\" \"system\" */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp;                 /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels on Tandem */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    /* TANDEM - call in2ex */\n    pp = in2ex(__G__ G.filename);\n    if (pp == (char *)NULL)\n        return MPN_NOMEM;\n    strcpy(G.filename, pp);\n    free(pp);\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    /* directories have already been junked in in2ex() */\n    cp = G.filename;            /* point to internal zipfile-member pathname */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) { /* includes space char, let checkdir handle it */\n            case TANDEM_DELIMITER: /* can assume -j flag not given */\n                *pp = '\\0';\n                if (((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || (128 <= workch && workch <= 254))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == TANDEM_DELIMITER) {\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n/* By using in2ex() to pre-process the filename we do not need to worry\n   about the lengths of filename parts.  We just need to cope with mapping the\n   pseudo file extensions properly of the actual filename (last part of name).\n   e.g.  \"tandem c\" -> tandemc\n         \"revsion.h\" -> revisioh\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n    char fname[FILENAME_MAX + 1];\n    short fnamelen, extlen, trunclen, i;\n    char ext[EXTENSION_MAX + 1];\n    char *ptr;\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (mkdir(buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename)));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        *end++ = TANDEM_DELIMITER;\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n\n        if (!uO.rflag  /* Do not add extension if asked */\n            && parsename(pathcomp, fname, ext))\n        {\n            fnamelen = strlen(fname);\n            extlen = strlen(ext);\n            if (fnamelen+extlen > MAXFILEPARTLEN) {\n                /* Doesn't fit.  Best approx is to use up to three characters\n                   from extension and place these on the end of as much of the\n                   start of the filename part as possible.\n                 */\n                if (extlen > EXTENSION_MAX)\n                    extlen = EXTENSION_MAX;\n                trunclen = MAXFILEPARTLEN - extlen;\n                ptr = fname;\n                for (i=0; i < trunclen; i++)\n                    *end++ = *ptr++;\n                ptr = ext;\n                for (i=0; i < extlen; i++)\n                    *end++ = *ptr++;\n                *end = '\\0';     /* mark end of string */\n            }\n            else {\n                /* Just join parts end to end */\n                ptr = fname;\n                while ((*end = *ptr++) != '\\0')\n                    ++end;\n                ptr = ext;\n                while ((*end = *ptr++) != '\\0')\n                  ++end;\n            }\n        }\n        else\n            while ((*end = *pathcomp++) != '\\0')\n              ++end;\n\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[rootlen-1] == TANDEM_DELIMITER) {\n                tmproot[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (stat(tmproot, &G.statbuf) ||\n                                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[rootlen++] = TANDEM_DELIMITER;\n            tmproot[rootlen] = '\\0';\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n/********************/\n/* Function mkdir() */\n/********************/\n\nint mkdir(path, mode)\nconst char *path;  /* both    */\nmode_t mode;       /* ignored */\n/*\n * returns:   0 - successful\n *           -1 - failed (errno not set, however)\n */\n{\n    return 0;\n}\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } zt;\n    ulg z_uidgid[2];\n    unsigned eb_izux_flg;\n    nsk_file_attrs *znsk_attr;\n    short err;\n    unsigned short len;\n\n    #define alist_items 1\n    #define vlist_bytes 2\n    short alist[alist_items]={42     };\n    unsigned short vlist[alist_items];\n    short extra, *err_item=&extra;\n\n    char nsk_work[FILENAME_MAX + 1], *nsk_fname=&nsk_work[0];\n\n    fclose(G.outfile);\n\n    /* Set up Tandem specific file information if present */\n    znsk_attr = ef_scan_for_tandem(G.extra_field, G.lrec.extra_field_length);\n\n    /* Currently we do not create 'proper' Tandem files in unzip - we only  */\n    /* create unstructured (180) or edit (101) files.  This code allows     */\n    /* some limited support for restoration of Tandem file attributes       */\n\n    if (znsk_attr != NULL) {\n      /* Reset File Code */\n      if (!uO.bflag && !G.pInfo->textmode\n          && znsk_attr->filetype == NSK_UNSTRUCTURED) {\n        /* leave type 101 files alone */\n        vlist[0] = znsk_attr->filecode;\n\n        /* Note that FILE_ALTERLIST_ expect uppercase names and that        */\n        /* G.lrec.filename_length is the length of original zipped filename */\n        /* not any 'rename' name.  Need to re call strlen and upshift       */\n        len = strlen(G.filename);\n        err = STRING_UPSHIFT_(G.filename,\n                              len,\n                              nsk_fname,\n                              len);\n\n        err = FILE_ALTERLIST_(nsk_fname,\n                              len,\n                              alist,\n                              alist_items,\n                              vlist,\n                              vlist_bytes,\n                              ,\n                              err_item);\n      }\n    }\n\n\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.  On the other hand, we\n    then have to check for restoration of UID/GID.\n  ---------------------------------------------------------------------------*/\n\n    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                   (G.tz_is_valid ? &(zt.t3) : NULL),\n#else\n                   &(zt.t3),\n#endif\n                   z_uidgid) : 0);\n    if (eb_izux_flg & EB_UT_FL_MTIME) {\n        TTrace((stderr, \"\\nclose_outfile:  Unix e.f. modif. time = %ld\\n\",\n          zt.t3.mtime));\n    } else {\n        zt.t3.mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n    if (eb_izux_flg & EB_UT_FL_ATIME) {\n        TTrace((stderr, \"close_outfile:  Unix e.f. access time = %ld\\n\",\n          zt.t3.atime));\n    } else {\n        zt.t3.atime = zt.t3.mtime;\n        TTrace((stderr, \"\\nclose_outfile:  modification/access times = %ld\\n\",\n          zt.t3.mtime));\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file's last modified time to that stored in the zipfile.\n    Not sure how (yet) or whether it's a good idea to set the last open time\n  ---------------------------------------------------------------------------*/\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        /* set the file's access and modification times */\n        if (utime(G.filename, &(zt.t2)))\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot set times for %s\\n\",\n                  FnFilter1(G.filename)));\n            else\n                Info(slide, 0x201, ((char *)slide,\n                  \" (warning) cannot set times\"));\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n#endif\n\n/*---------------------------------------------------------------------------\n       if -X option was specified and we have UID/GID info, restore it\n       this must come after the file security and modtimes changes - since once\n       we have secured the file to somebody else we cannot access it again.\n  ---------------------------------------------------------------------------*/\n\n    if (uO.X_flag && eb_izux_flg & EB_UX2_VALID) {\n        TTrace((stderr, \"close_outfile:  restoring Unix UID/GID info\\n\"));\n        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))\n        {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot set UID %lu and/or GID %lu for %s\\n\",\n                  z_uidgid[0], z_uidgid[1], FnFilter1(G.filename)));\n            else\n                Info(slide, 0x201, ((char *)slide,\n                  \" (warning) cannot set UID %lu and/or GID %lu\",\n                  z_uidgid[0], z_uidgid[1]));\n        }\n    }\n\n} /* end function close_outfile() */\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n\n    /* Pyramid, NeXT have problems with huge macro expansion, too: no Info() */\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n    \"C \",\n    \"T9255D44 - (16OCT98)\",\n    \"NonStop \",\n    \"(Tandem/NSK)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/Contents",
    "content": "Contents of the \"theos\" subdirectory for UnZip 5.41 and later:\n\n  Contents      this file\n  makefile      makefile for UnZip for THEOS architectures\n  theos.c       Theos-specific support routines\n  thscfg.h\n  charconv.h\n  oldstat.h\n  stat.h\n  _fprintf.c\n  _isatty.c\n  _opendir.c\n  _setargv.c\n  _sprintf.c\n  _stat.c\n\nType \"make\" or \"make help\" to get general compile instructions (beyond\nthose in the INSTALL file), or \"make list\" for a list of makefile targets.\nNote that there are some MS-DOS and cross-compilation targets thrown in\njust to make things more exciting.\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/_fprintf.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include <stdio.h>\n#include <stdarg.h>\n\n/* for Info and similar macroes. fprintf is already a macro and fprintf x\n * fools the preprocessor\n */\n\nint _fprintf(FILE* fp, const char* fmt, ...)\n{\n    va_list ap;\n    long n;\n\n    va_start(ap, fmt);\n    n = vfprintf(fp, fmt, (long*) ap);\n    va_end(ap);\n    return n;\n}\n\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/_isatty.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* replace standard library function who needs a FILE* */\n\n#pragma library\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <sc.h>\n#include <lub.h>\n\nshort _isatty(int fd)\n{\n    register short lub;\n\n    lub = (int) _fcntl(&stdin[fd], 5, (size_t) 0);\n    return (lub >= CONIN && lub <= CONOUT)\n        || (lub >= COM1 && lub <= COM4)\n        || (lub >= COM5 && lub <= COM16);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/_setargv.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * _setargv.c - derived from an command argument expander\n *\n * Author  : Jean-Michel Dubois\n * Date    : 13-Dec-98\n *\n * Function: Looks for member names (fn.ft.mb) and add the libraries names\n *           (fn.ft) to the list of files to zip to force inclusion of\n *           libraries if necessary.\n *           Strings beginning by a dash are considered as options and left\n *           unchanged.\n *\n * Syntax  : void _setargv(int *argc, char ***argv);\n *\n * Returns : new argc. Caller's argc and argv are updated.\n *       If a insufficient memory condition occurs, return 0 and errno\n *       is set to ENOMEM.\n *\n * Example :\n *      main(int argc, char **argv)\n *      {\n *          if (_setargv(&argc, &argv)) {\n *              ...\n */\n#pragma library\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n#include <errno.h>\n#include <scr.h>\n#include <peek.h>\n\n/* Allocate argv array in 16 entries chunks */\n\nstatic int allocarg(int n, int asize, char ***nargv, char *s)\n{\n    if ((n+1) > asize) {    /* If array full */\n        asize += 16;        /* increase size and reallocate */\n        if (!(*nargv = (char **) realloc(*nargv, asize * sizeof (void *)))) {\n            errno = _errnum = ENOMEM;    /* Not enough memory */\n            return 0;\n        }\n    }\n    (*nargv)[n] = strdup(s);    /* Save argument */\n    return asize;               /* Return new maxsize */\n}\n\n/* check if file is a member of a library */\n\nstatic int ismember(char* path)\n{\n    char* p;\n\n    if ((p = strrchr(path, '/')) == NULL)\n        p = path;\n    return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));\n}\n\n/* extract library name from a file name */\n\nstatic char* libname(char* path)\n{\n    char* p;\n    static char lib[256];\n    char disk[3];\n\n    strcpy(lib, path);\n    if (p = strrchr(lib, ':')) {\n        strncpy(disk, p, 2);\n        disk[2] = '\\0';\n        *p = '\\0' ;\n    } else\n        disk[0] = '\\0';\n\n    if ((p = strrchr(lib, '/')) == NULL)\n        p = lib;\n\n    p = strchr(p, '.');\n    p = strchr(p + 1, '.');\n    *p = 0;\n    strcat(lib, disk);\n    return lib;\n}\n\n/* Main body of the function */\n\nint _setargv(int *argc, char ***argv)\n{\n    register int nargc;     /* New arguments counter */\n    char **nargv;           /* New arguments pointers */\n    register int i, j;\n    int asize;              /* argv array size */\n    char *arg;\n    char lib[256];\n\n    _errnum = 0;\n    nargc = 0;          /* Initialise counter, size counter */\n    asize = *argc;      /* and new argument vector to the */\n                        /* current argv array size */\n\n    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {\n        /* For each initial argument */\n        for (i = 0; i < *argc; i++) {\n            arg = (*argv)[i];\n#ifdef DEBUG\n            fprintf(stderr, \"checking arg: %s\", arg);\n#endif\n            if (i == 0 || *arg == '-' || ! ismember(arg)) {\n                /* if it begins with a dash or doesn't include\n                 * a library name simply add it to the new array */\n                if (! (asize = allocarg(nargc, asize, &nargv, arg)))\n                    return 0;   /* Not enough memory */\n                nargc++;\n            } else {\n                short insert;\n                strcpy(lib, libname(arg));\n                /* add library name if necessary */\n                for (j = 2, insert = 1; i < nargc; i++) {\n                    if (ismember(nargv[i])\n                     && ! strcmp(lib, libname(nargv[i]))) {\n                        insert = 0;\n                        break;\n                    }\n                }\n                if (insert) {\n#ifdef DEBUG\n                    fprintf(stderr, \"inserting lib %s \", lib);\n#endif\n                    if (! (asize = allocarg(nargc, asize, &nargv, lib)))\n                        return 0;   /* Not enough memory */\n                    nargc++;\n                }\n                /* add file name */\n#ifdef DEBUG\n                fprintf(stderr, \"inserting file %s\", arg);\n#endif\n                if (! (asize = allocarg(nargc, asize, &nargv, arg)))\n                    return 0;   /* Not enough memory */\n                nargc++;\n            }\n#ifdef DEBUG\n            fprintf(stderr, \"\\n\");\n#endif\n        }\n        /* Update caller's parameters */\n        *argc = nargc;\n        *argv = nargv;\n        /* and sign on success */\n        return nargc;\n    }\n\n    /* If it is not possible to allocate initial array, sign on error */\n    _errnum = ENOMEM;\n    return 0;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/_sprintf.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include <stdio.h>\n#include <stdarg.h>\n\n/* for Info and similar macroes. fprintf is already a macro and fprintf x\n * fools the preprocessor\n */\n\nint _sprintf(char *s, const char *fmt, ...)\n{\n    va_list ap;\n    long n;\n\n    va_start(ap, fmt);\n    n = vsprintf(s, fmt, (long*) ap);\n    va_end(ap);\n    return n;\n}\n\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/_stat.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#pragma library\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sc.h>\n#include <peek.h>\n#include <lub.h>\n#include <fdb.h>\n#include <fsa.h>\n#include \"theos/stat.h\"\n\n/* replacement for standard library functions stat and fstat */\n\nint _stat_(struct stat* st, struct fdb* fdb);\nint _dstat_(struct stat* st);\n\n#define peekucb() peeknuc()\n\n/* map THEOS protection code to Unix modes */\n\nunsigned short _tm2um_(char protect)\n{\n    unsigned short umask = 0;\n\n    if (!(protect & _FDB_READ_PROTECT))\n        umask = S_IRUSR|S_IRGRP;\n\n    if (!(protect & _FDB_WRITE_PROTECT))\n        umask |= S_IWUSR|S_IWGRP;\n\n    if (!(protect & _FDB_EXECUTE_PROTECT))\n        umask |= S_IXUSR|S_IXGRP;\n\n    if (!(protect & _FDB_ERASE_PROTECT))\n        umask |= S_IEUSR|S_IEGRP;\n\n    if (!(protect & _FDB_SHARED_READ_PROTECT)) {\n        if (_osmajor > 3)\n            umask |= S_IROTH|S_IXOTH;\n        else\n            umask |= S_IROTH;\n    }\n\n    if (!(protect & _FDB_SHARED_WRITE_PROTECT))\n        umask |= S_IWOTH;\n\n    if (!(protect & _FDB_MODIFIED)) {\n        if (_osmajor > 3)\n            umask |= S_IMODF;\n        else\n            umask |= S_IXOTH;\n    }\n\n    if (protect & _FDB_NOT_HIDDEN)\n        umask |= S_INHID;\n\n    return umask;\n}\n\n/* map Unix modes to THEOS protections */\n\nchar _um2tm_(unsigned short mask)\n{\n    char protect = 0;\n\n    if (!(mask & (S_IRUSR|S_IRGRP)))\n        protect |= _FDB_READ_PROTECT;\n\n    if (!(mask & (S_IWUSR|S_IWGRP)))\n        protect |= _FDB_WRITE_PROTECT;\n\n    if (!(mask & (S_IXUSR|S_IXGRP)))\n        protect |= _FDB_EXECUTE_PROTECT;\n\n    if (!(mask & (S_IEUSR|S_IEGRP)))\n        protect |= _FDB_ERASE_PROTECT;\n\n    if (_osmajor < 4) {\n        if (!(mask & S_IROTH))\n            protect |= _FDB_SHARED_READ_PROTECT;\n    } else {\n        if (!(mask & (S_IROTH|S_IXOTH)))\n            protect |= _FDB_SHARED_READ_PROTECT;\n    }\n\n    if (!(mask & S_IWOTH))\n        protect |= _FDB_SHARED_WRITE_PROTECT;\n\n    if (mask & S_IMODF && _osmajor > 3)\n        protect |= _FDB_MODIFIED;\n\n    if (mask & S_INHID && _osmajor > 3)\n        protect |= _FDB_NOT_HIDDEN;\n\n    return protect;\n}\n\n/* root directory stat */\n\nstatic int rdirstat(char* fn, struct stat *st)\n{\n    register char* p = strchr(fn, ':');\n    char drive;\n\n    drive = p ? p[1] : 'S';\n\n    if (drive >= 'a' && drive <= 'Z')\n        drive -= 0x40;\n\n    memset(st, 0, sizeof(struct stat));\n\n    if (getlub(drive - 'A') != 255) {\n        st->st_org = _FDB_STAT_DIRECTORY;\n        st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;\n        st->st_nlink = 1;\n        st->st_dev = st->st_rdev = drive - 'A';\n        st->st_uid = st->st_gid = getuid();\n        st->st_protect = _FDB_ERASE_PROTECT;\n        return 0;\n    }\n    errno = _errnum = ENOENT;\n    _errarg = fn;\n    return -1;\n}\n\n/* file stat */\n\nint _stat(const char *fn, struct stat *st)\n{\n    char buf[256], buf2[256];\n    char *ifn;\n    register struct fdb *fdb;\n    register char *p;\n\n    if ((ifn = (char *)malloc(strlen(fn)+1)) == NULL) {\n        errno = _errnum = ENOMEM;\n        return -1;\n    }\n\n    if (p = strrchr(ifn, ':'))\n        *p = 0;\n\n    /* on current drive ./:d and .:m point to current dir\n     * on another drive to root directory */\n\n    if (! strcmp(ifn, \"/\") || ! strcmp(ifn, \".\") || ! strcmp(ifn, \"./\")) {\n        if (p == NULL) {\n            free(ifn);\n            /* current dir on current drive */\n            ifn = getcwd(buf2, 256);\n            /* getcwd returns NULL on root dir on drive S */\n            if (ifn == NULL)\n                strcpy(ifn = buf2, \"/:S\");\n            /* getcwd returns /:d on root dir on any other drive */\n            if (ifn[1] == ':')\n                return rdirstat(ifn, st);\n        } else {\n            int rstat;\n            *p = ':';\n            rstat = rdirstat(ifn, st);\n            free(ifn);\n            return rstat;\n        }\n    }\n\n    if (p)\n        *p = ':';\n\n    strcpy(buf2, ifn);\n    /* remove trailing slash before optional disk name */\n    if (p = strrchr(buf2, '/')) {\n        if (p[1] == ':') {\n            *p = p[1];\n            p[1] = p[2];\n            p[2] = p[3];\n        } else if (p[1] == '\\0')\n            *p = '\\0';\n    }\n    /* if ifn is a file get file directory block structure and device */\n    if (fdb = _locate(buf2, buf, &st->st_dev)) {\n        /* is it a file from another user... */\n        if (strchr(buf2, '\\\\')\n        /* a public system file */\n          || fdb->fileowner == 0\n        /* or a file from the current user account ? */\n          || fdb->fileowner == getuid()) {\n            /* yes, return stat */\n            return _stat_(st, fdb);\n        } else {\n            /* no, say file doesn't exist */\n            errno = _errnum = ENOENT;\n            _errarg = fn;\n            return -1;\n        }\n    }\n    /* else should be a device */\n    st->st_rdev = st->st_dev = _lub_name(*ifn == ':' ? ifn+1 : ifn);\n\n    free(ifn);\n    if (st->st_dev != -1 && getlub(st->st_dev) != 255)\n        return _dstat_(st);\n\n    errno = _errnum = ENOENT;\n    _errarg = fn;\n    return -1;\n}\n\nint _fstat(int fd, struct stat *st)\n{\n    unsigned short fsanum;\n    struct fsa fsa;\n    register FILE *fp;\n    int status;\n    register int i;\n    register char *p;\n\n    if (fd < FOPEN_MAX) {\n        fp = &stdin[fd];\n        if (_fcntl(fp,1,0) & 0x80) {\n            fsanum = (unsigned short) _fcntl(fp,83,0);\n            st->st_dev = (unsigned short) _fcntl(fp,5,0);\n\n            if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {\n                for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;\n                     i < (sizeof(fsa));\n                     i++, fsanum++, p++)\n                    *p = _peekfsa((char *) fsanum);\n                status = _stat_(st, (struct fdb*) &fsa);\n                if ((st->st_blksize = _fcntl(fp,817,0)) == 0)\n                    st->st_blksize = BUFSIZ;\n                return status;\n            }\n            return _dstat_(st);\n        }\n    }\n    errno = _errnum = EBADF;\n    return -1;\n}\n\nstatic int _isprt(int dev)\n{\n    return IS_PRT_LUB(dev);\n}\n\n/* device stat */\n\nint _dstat_(st)\nregister struct stat* st;\n{\n    register struct ucb* ucb;\n\n    ucb = getucb(st->st_dev);\n    st->st_ino = 0;\n    if (st->st_dev <= Z_DISK\n     || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {\n        st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;\n        if (peekucb(&ucb->devowner) == 255)\n            st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;\n    } else {\n        st->st_mode = S_IFCHR | S_IWUSR;\n        if (_isprt(st->st_dev))\n            st->st_mode |= S_IRUSR;\n        if (peekucb(&ucb->devowner) == 255) {\n            st->st_mode |= S_IWGRP | S_IWOTH;\n            if (_isprt(st->st_dev))\n                st->st_mode |= S_IRGRP | S_IROTH;\n        }\n    }\n    st->st_nlink = 1;\n    st->st_uid = st->st_gid = getuid();\n    st->st_size = 0;\n    st->st_atime = st->st_mtime = st->st_ctime = 0;\n    st->st_rlen = 0;\n    st->st_klen = 0;\n    st->st_grow = 0;\n    st->st_blksize = 0;\n    return 0;\n}\n\n/* regular file stat */\n\nint _stat_(st, fdb)\nregister struct stat* st;\nregister struct fdb* fdb;\n{\n    st->st_rdev = st->st_dev;\n    st->st_ino = 0;\n    st->st_org = fdb->filestat;\n\n    switch (fdb->filestat) {\n    case _FDB_STAT_LIBRARY:         st->st_mode = S_IFLIB;  break;\n    case _FDB_STAT_DIRECTORY:       st->st_mode = S_IFDIR;  break;\n    case _FDB_STAT_STREAM:          st->st_mode = S_IFREG;  break;\n    case _FDB_STAT_RELATIVE:        st->st_mode = S_IFREL;  break;\n    case _FDB_STAT_KEYED:           st->st_mode = S_IFKEY;  break;\n    case _FDB_STAT_INDEXED:         st->st_mode = S_IFIND;  break;\n    case _FDB_STAT_RANDOM:          st->st_mode = S_IFRND;  break;\n    case _FDB_STAT_PROGRAM:         st->st_mode = S_IFR16;  break;\n    case _FDB_STAT_16_BIT_PROGRAM:  st->st_mode = S_IFP16;  break;\n    case _FDB_STAT_32_BIT_PROGRAM:  st->st_mode = S_IFP32;  break;\n    }\n\n    st->st_mode |= _tm2um_(st->st_protect = fdb->protect);\n    st->st_nlink = 1;\n    st->st_uid = st->st_gid = fdb->fileowner;\n    st->st_size = fdb->filesize;\n    st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);\n    st->st_rlen = fdb->reclen;\n    st->st_klen = fdb->keylen;\n    st->st_grow = fdb->filegrow;\n    st->st_blksize = 0;\n    return 0;\n}\n\n#include <direct.h>\n\nstruct dirent* _opendir(const char* dirpath)\n{\n    int l;\n    char *p;\n    struct dirent* dir;\n    char *mypath = NULL;\n\n    if (dirpath != NULL &&\n        (mypath = (char *)malloc(strlen(dirpath)+1)) == NULL) {\n        errno = _errnum = ENOMEM;\n        return NULL;\n    }\n\n    if (mypath) {\n        l = strlen(mypath);\n        if (l) {\n            p = dirpath + l - 1;\n            if (*p == '/') {\n                *p = '\\0';\n                dir = opendir(dirpath);\n                *p = '/';\n                return dir;\n            }\n        }\n\n    }\n    return opendir(mypath);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/charconv.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#ifdef IZ_THS2ISO_ARRAY\nZCONST uch Far ths2iso[] = {\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 80 - 87 */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 88 - 8F */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 90 - 97 */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 98 - 9F */\n    0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,  /* A0 - A7 */\n    0x2B, 0x2D, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B, 0x23,  /* A8 - AF */\n    0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,  /* B0 - B7 */\n    0x3D, 0x23, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,  /* B8 - BF */\n    0xC4, 0xE4, 0xE2, 0xE0, 0xE1, 0xC9, 0xEB, 0xEA,  /* C0 - C7 */\n    0xE8, 0xE9, 0xEF, 0xEE, 0xEC, 0xED, 0xD6, 0xF6,  /* C8 - CF */\n    0xF4, 0xF2, 0xF3, 0xDC, 0xFC, 0xFB, 0xF9, 0xFA,  /* D0 - D7 */\n    0xC7, 0xE7, 0xD1, 0xF1, 0xC6, 0xE6, 0xC5, 0xE5,  /* D8 - DF */\n    0xDF, 0xBF, 0xA1, 0xA2, 0xA3, 0xA5, 0xB5, 0xA4,  /* E0 - E7 */\n    0xBC, 0xBD, 0xFF, 0xA7, 0xB0, 0xB2, 0x20, 0x20,  /* E8 - EF */\n    0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* F0 - F7 */\n    0x20, 0x20, 0xB7, 0x20, 0x20, 0x20, 0x20, 0x20   /* F8 - FF */\n};\n#endif /* IZ_THS2ISO_ARRAY */\n\n#ifdef IZ_THS2OEM_ARRAY\nZCONST uch Far ths2oem[] = {\n    254,254,254,254, 254,254,134,135,   /* 80 - 87 */\n    136,137,138,139, 140,141,142,143,   /* 88 - 8F */\n    144,145,146,147, 148,149,150,151,   /* 90 - 97 */\n    152,153,154,155, 156,157,158,159,   /* 98 - 9F */\n    218,191,217,192, 197,195,180,194,   /* A0 - A7 */\n    193,196,179,218, 191,217,192,201,   /* A8 - AF */\n    183,188,200,206, 199,182,203,202,   /* B0 - B7 */\n    205,186,186,187, 188,189,190,191,   /* B8 - BF */\n    142,132,131,133, 160,144,137,136,   /* C0 - C7 */\n    138,130,139,140, 141,161,153,148,   /* C8 - CF */\n    147,149,162,154, 129,150,151,163,   /* D0 - D7 */\n    128,135,165,164, 146,145,143,134,   /* D8 - DF */\n    225,168,173,155, 156,157,158, 31,   /* E0 - E7 */\n    172,171,152, 21, 248,253,238,239,   /* E8 - EF */\n    240,241,242,243, 244,245,246,247,   /* F0 - F7 */\n    248,249,250,251, 252,253,254,255    /* F8 - FF */\n};\n#endif /* IZ_THS2OEM_ARRAY */\n\n#ifdef IZ_ISO2THS_ARRAY\nZCONST uch Far iso2ths[] = {\n    0x3F, 0x3F, 0x27, 0x3F, 0x22, 0x2E, 0xA4, 0xB3,  /* 80 - 87 */\n    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */\n    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */\n    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */\n    0x20, 0xE2, 0xE3, 0xE4, 0xE7, 0xE5, 0x7C, 0xEB,  /* A0 - A7 */\n    0x20, 0x20, 0x20, 0x22, 0x20, 0x2D, 0x20, 0x2D,  /* A8 - AF */\n    0xEC, 0xF1, 0xED, 0x20, 0x20, 0xE6, 0x20, 0xFA,  /* B0 - B7 */\n    0x20, 0x20, 0x20, 0x22, 0xE8, 0xE9, 0x20, 0xE1,  /* B8 - BF */\n    0xC3, 0xC4, 0xC2, 0x41, 0xC0, 0xDE, 0xDC, 0xD8,  /* C0 - C7 */\n    0xC8, 0xC5, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* C8 - CF */\n    0x44, 0xDA, 0xD1, 0xD2, 0xD0, 0x4F, 0xCE, 0x78,  /* D0 - D7 */\n    0x4F, 0xD6, 0xD7, 0xD5, 0xD3, 0x59, 0x20, 0xE0,  /* D8 - DF */\n    0xC3, 0xC4, 0xC2, 0x61, 0xC1, 0xDF, 0xDD, 0xD9,  /* E0 - E7 */\n    0xC8, 0xC9, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* E8 - EF */\n    0x64, 0xDB, 0xD1, 0xD2, 0xD0, 0x4F, 0xCF, 0xF1,  /* F0 - F7 */\n    0x6F, 0xD6, 0xD7, 0xD5, 0xD4, 0x79, 0x20, 0xEA   /* F8 - FF */\n};\n#endif /* IZ_ISO2THS_ARRAY */\n\n#ifdef IZ_OEM2THS_ARRAY\nZCONST uch Far oem2ths[] = {\n    216,212,201,194, 193,195,223,217,   /* 80 - 87 */\n    199,198,200,202, 203,204,192,222,   /* 88 - 8F */\n    197,221,220,208, 207,209,213,214,   /* 90 - 97 */\n    234,206,211,227, 228,229,230,159,   /* 98 - 9F */\n    196,205,210,215, 219,218,254,254,   /* A0 - A7 */\n    225,254,254,233, 232,226, 34, 34,   /* A8 - AF */\n    254,254,254,170, 166,166,181,176,   /* B0 - B7 */\n    161,181,185,176, 177,177,162,161,   /* B8 - BF */\n    163,168,167,165, 169,164,165,180,   /* C0 - C7 */\n    178,175,183,182, 180,184,179,168,   /* C8 - CF */\n    183,167,182,178, 163,160,175,179,   /* D0 - D7 */\n    164,162,160,254, 254,254,254,254,   /* D8 - DF */\n    254,224,254,254, 254,254,254, 31,   /* E0 - E7 */\n    254,254,254, 21, 254,254,238,239,   /* E8 - EF */\n    240,241,242,243, 244,245,246,247,   /* F0 - F7 */\n    236,249,250,251, 252,237,254,255    /* F8 - FF */\n};\n#endif /* IZ_OEM2THS_ARRAY */\n\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/oldstat.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#define _THS_IFMT       0xff00  /* type of file */\n#define _THS_IFLIB      0x8000  /* library */\n#define _THS_IFDIR      0x4000  /* directory */\n#define _THS_IFCHR      0x2000  /* character device */\n#define _THS_IFREG      0x1000  /* regular file */\n#define _THS_IODRC      0x0800  /* direct */\n#define _THS_IOKEY      0x0400  /* keyed */\n#define _THS_IOIND      0x0200  /* indexed */\n#define _THS_IOPRG      0x0100  /* program */\n#define _THS_IO286      0x2100  /* program */\n#define _THS_IO386      0x4100  /* program */\n#define _THS_IREAD      0x0001  /* read permission */\n#define _THS_IWRITE     0x0002  /* write permission */\n#define _THS_IEXEC      0x0004  /* execute permission */\n#define _THS_IERASE     0x0008  /* erase permission */\n#define _THS_IRWXU      0x000f  /* read, write, execute, erase: owner */\n#define _THS_IRUSR      0x0001  /* read permission: owner */\n#define _THS_IWUSR      0x0002  /* write permission: owner */\n#define _THS_IXUSR      0x0004  /* execute permission: owner */\n#define _THS_IEUSR      0x0008  /* erase permission: owner */\n#define _THS_IROTH      0x0010  /* read permission: other */\n#define _THS_IWOTH      0x0020  /* write permission: other */\n#define _THS_IXOTH      0x0040  /* execute permission: other */\n#define _THS_HIDDN      0x0080  /* hidden, 0 = true */\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/stat.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#ifndef __theos_stat_h\n#define __theos_stat_h\n\n/* extended stat structure for stat, fstat, chmod */\n/* Written by Jean-Michel Dubois */\n\n#pragma field word\nstruct stat {\n    unsigned short  st_mode;        /* file attributes */\n        #define S_IFMT      0xf000      /* file type mask */\n        #define S_IFIFO     0x1000      /* pipe */\n        #define S_IFCHR     0x2000      /* char device */\n        #define S_IFSOCK    0x3000      /* socket */\n        #define S_IFDIR     0x4000      /* directory */\n        #define S_IFLIB     0x5000      /* library */\n        #define S_IFBLK     0x6000      /* block device */\n        #define S_IFREG     0x8000      /* regular file */\n        #define S_IFREL     0x9000      /* relative (direct) */\n        #define S_IFKEY     0xA000      /* keyed */\n        #define S_IFIND     0xB000      /* indexed */\n        #define S_IFRND     0xC000      /* ???? */\n        #define S_IFR16     0xD000      /* 16 bit real mode program */\n        #define S_IFP16     0xE000      /* 16 bit protected mode prog */\n        #define S_IFP32     0xF000      /* 32 bit protected mode prog */\n\n        #define S_ISUID     0x0800      /* meaningless */\n        #define S_ISGID     0x0400      /* meaningless */\n        #define S_ISVTX     0x0200      /* meaningless */\n\n        #define S_IMODF     0x0800      /* modified */\n        #define S_INHID     0x0400      /* not hidden */\n\n        #define S_IRWXU     0x03c0      /* read,write,execute: owner */\n        #define S_IEUSR     0x0200      /* erase permission: owner */\n        #define S_IRUSR     0x0100      /* read permission: owner */\n        #define S_IWUSR     0x0080      /* write permission: owner */\n        #define S_IXUSR     0x0040      /* execute permission: owner */\n    /* group permissions */\n        #define S_IRWXG     0x0238\n        #define S_IEGRP     0x0200\n        #define S_IRGRP     0x0020\n        #define S_IWGRP     0x0010\n        #define S_IXGRP     0x0008\n    /* other never has erase permission */\n        #define S_IRWXO     0x0207      /* read,write,execute: other */\n        #define S_IROTH     0x0004      /* read permission: other */\n        #define S_IWOTH     0x0002      /* write permission: other */\n        #define S_IXOTH     0x0001      /* execute permission: other */\n\n        #define S_IREAD     0x0100      /* read permission, owner */\n        #define S_IEXEC     0x0040      /* execute permission, owner */\n        #define S_IWRITE    0x0080      /* write permission, owner */\n    short           st_ino;         /* not used */\n    short           st_dev;         /* not used */\n    short           st_rdev;        /* not used */\n    short           st_nlink;       /* not used */\n    short           st_uid;         /* owner id */\n    short           st_gid;         /* not used */\n    unsigned long   st_size;        /* size of file */\n    unsigned long   st_atime;       /* not used */\n    unsigned long   st_mtime;       /* date & time last modified */\n    unsigned long   st_ctime;       /* not used */\n    unsigned long   st_blksize;     /* buffer size */\n    unsigned short  st_org;         /* organization */\n    unsigned short  st_rlen;        /* record size */\n    unsigned short  st_klen;        /* key size */\n    char            st_grow;        /* growing factor */\n    char            st_protect;     /* native protections */\n};\n#pragma field\n\n#define S_ISREG(m)      (((m) & S_IFMT) >= S_IFREG)\n#define S_ISLIB(m)      (((m) & S_IFMT) == S_IFLIB)\n#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)\n#define S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)\n#define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)\n\n#define S_ISSEQ(m)      (((m) & S_IFMT) == S_IFREG)\n#define S_ISREL(m)      (((m) & S_IFMT) == S_IFREL)\n#define S_ISKEY(m)      (((m) & S_IFMT) == S_IFKEY)\n#define S_ISIND(m)      (((m) & S_IFMT) == S_IFIND)\n#define S_ISPRG(m)      (((m) & S_IFMT) >= S_IFP16)\n#define S_ISLNK(m)      0\n\n/* avoid conflict with original THEOS functions */\n\n#define stat(a,b)       _stat(a,b)\n#define fstat(a,b)      _fstat(a,b)\n#define chmod(a,b)      _chmod(a,b)\n\nextern int _stat(const char *file, struct stat *statptr);\nextern int _fstat(int fd, struct stat *statptr);\nextern int _chmod(const char *file, short mask);\n\n#define _chstat(a,b)    ((int) _sc_168(a,'p',(size_t)(b)))\nextern unsigned short   _sc_168(const char _far *fn, int cmd, size_t value);\n\n#endif /* !__theos_stat_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/theos.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  theos.c\n\n  Theos-specific routines for use with Info-ZIP's UnZip 5.41 and later.\n\n  Contains:  do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             stamp_file()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include <direct.h>\n#include <sc.h>\n#include <fdb.h>\n#include <nuc.h>\n#include <peek.h>\n\n/* standard function doesn't work with a trailing / */\n#define opendir(a) _opendir(a)\nextern DIR* _opendir(const char* dirpath);\n\n#ifdef SET_DIR_ATTRIB\ntypedef struct uxdirattr {      /* struct for holding unix style directory */\n    struct uxdirattr *next;     /*  info until can be sorted and set at end */\n    char *fn;                   /* filename of directory */\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } u;\n    unsigned perms;             /* same as min_info.file_attr */\n    char fnbuf[1];              /* buffer stub for directory name */\n} uxdirattr;\n#define UxAtt(d)  ((uxdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\nstatic int created_dir;        /* used in mapname(), checkdir() */\nstatic int renamed_fullpath;   /* ditto */\n\n#define _FDB_SHARED_EXECUTE_PROTECT _FDB_MODIFIED\n\nuch _um2tm_(ush mask);\n\nint chmodv2_3(const char *fname, short mask)\n{\n    return _filechange(fname,'p',(size_t) _um2tm_(mask)|0x80);\n}\n\nint chlen(char *fname, unsigned short reclen, unsigned short keylen)\n{\n    size_t a = reclen + ((size_t) keylen << 16);\n    return _filechange(fname,'ma',(size_t) &a);\n}\n\n#define chgrow(a,b) ((int) _filechange(a,'g',(size_t)(b)))\n#define chorg(a,b)  ((int) _filechange(a,'m',(size_t)(b)))\n\n#ifndef SFX\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\nint dateformat()\n{\n/*---------------------------------------------------------------------------\n    For those operating systems that support it, this function returns a\n    value that tells how national convention says that numeric dates are\n    displayed.  Return values are DF_YMD, DF_DMY and DF_MDY (the meanings\n    should be fairly obvious).\n  ---------------------------------------------------------------------------*/\n\n    switch (peeknuc(&NUC->dateopt) & (aform|eform|iform)) {\n    case aform: return DF_MDY;\n    case eform: return DF_DMY;\n    }\n    return DF_YMD;\n}\n\n\n/* usual THEOS match function for filenames */\n\n/* match from Phase One Systems */\n\n/* Returns non-zero if string matches the literal mask */\nint match(string, pattern, ignore_case __WDL)\n    ZCONST char *string;\n    ZCONST char *pattern;\n    int ignore_case;            /* unused in this variant of match()! */\n    __WDLDEF\n{\n    int matched, k;\n\n    if (!(*pattern))\n        return 1;\n    for(;;) {\n        if ( (!(*string)) && (!(*pattern)) )\n            return(1);\n        else if ( !(*pattern) )\n            return(0);\n        else if (*pattern == '*') {\n            if (!*(pattern+1))\n                return(1);\n            k=0;\n            do {\n                matched = match(string+k, pattern+1, ignore_case __WDL);\n                k++;\n            } while ( (!matched) && *(string+k));\n            return(matched);\n        } else if (*pattern == '@') {\n            if (!((*string >= 'a' && *string <= 'z')\n                ||(*string >= 'A' && *string <= 'Z')))\n                return(0);\n        } else if (*pattern == '#') {\n            if (*string < '0' || *string > '9')\n                return(0);\n        } else if (*pattern != '?') {\n            if (toupper(*string) != toupper(*pattern))\n                return(0);\n\n        }\n        string++; pattern++;\n    }\n} /* end function match() */\n\n\n\n/**********************/\n/* Function do_wild() */   /* for porting:  dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!notfirstcall) {    /* first call:  must initialize everything */\n        notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strcpy(matchname, wildspec);\n            have_dirname = FALSE;\n            wild_dir = NULL;\n            return matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((wildname = (ZCONST char *)strrchr(wildspec, '/')) ==\n            (ZCONST char *)NULL)\n        {\n            dirname = \".\";\n            dirnamelen = 1;\n            have_dirname = FALSE;\n            wildname = wildspec;\n        } else {\n            ++wildname;     /* point at character after '/' */\n            dirnamelen = wildname - wildspec;\n            if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(matchname, wildspec, FILNAMSIZ);\n                matchname[FILNAMSIZ-1] = '\\0';\n                return matchname;   /* but maybe filespec was not a wildcard */\n            }\n            strncpy(dirname, wildspec, dirnamelen);\n            dirname[dirnamelen] = '\\0';   /* terminate for strcpy below */\n            have_dirname = TRUE;\n        }\n\n        if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {\n            while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (match(file->d_name, wildname, 1 WISEP)) { /*1=ignore case*/\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (have_dirname) {\n                        strcpy(matchname, dirname);\n                        strcpy(matchname+dirnamelen, file->d_name);\n                    } else\n                        strcpy(matchname, file->d_name);\n                    return matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir(wild_dir);\n            wild_dir = (DIR *)NULL;\n        }\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(matchname, wildspec, FILNAMSIZ);\n        matchname[FILNAMSIZ-1] = '\\0';\n        return matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (wild_dir == (DIR *)NULL) {\n        notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */\n        if (have_dirname)\n            free(dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, wildname, 1 WISEP)) {   /* 1 == ignore case */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (have_dirname) {\n                /* strcpy(matchname, dirname); */\n                strcpy(matchname+dirnamelen, file->d_name);\n            } else\n                strcpy(matchname, file->d_name);\n            return matchname;\n        }\n    }\n\n    closedir(wild_dir);     /* have read at least one entry; nothing left */\n    wild_dir = (DIR *)NULL;\n    notfirstcall = FALSE;   /* reset for new wildspec */\n    if (have_dirname)\n        free(dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n        case THEOS_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr != 0 || !G.extra_field) {\n                return 0;\n            } else {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap from the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n                int r = FALSE;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n                if (!r)\n                    return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6))\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n                return 0;\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n/* portabilibity functions to ensure access to port 2.0 and new ports */\n\nint isv2_3()\n{\n    return G.extra_field[0] == 'T' && G.extra_field[1] == 'h';\n}\n\nint isv2_3lib()\n{\n    return isv2_3() && S_ISLIB((G.pInfo->file_attr >> 8) & 0xFF);\n}\n\nint isv2_3dir()\n{\n    return isv2_3() && S_ISDIR((G.pInfo->file_attr >> 8) & 0xFF);\n}\n\n#ifdef OLD_THEOS_EXTRA\n#define S_IFMT_     0xf800      /* type of file */\n#define S_IFLIB_    0x8000      /* library */\n#define S_IFDIR_    0x4000      /* directory */\n\n#define S_ISLIB_(a) (((a) & 0xff) == _FDB_STAT_LIBRARY)\n#define S_ISDIR_(a) (((a) & 0xff) == _FDB_STAT_DIRECTORY)\n\nstruct extra_block\n{\n    ush     signature;\n    ush     size;\n    ush     flags;\n    ulg     filesize;\n    ush     reclen;\n    ush     keylen;\n    uch     filegrow;\n    uch     reserved[3];\n};\n\nstruct extra_block *v2_0extra()\n{\n    return (struct extra_block *) G.extra_field;\n}\n\nint isv2_0()\n{\n    return ((struct extra_block *) G.extra_field)->signature == 0x4854;\n}\n\nint isv2_0lib()\n{\n  return isv2_0() && S_ISLIB_(G.pInfo->file_attr);\n}\n\nint isv2_0dir()\n{\n  return isv2_0() && S_ISDIR_(G.pInfo->file_attr);\n}\n\n#define islib() (isv2_0lib() || isv2_3lib())\n#define isdir() (isv2_0dir() || isv2_3dir())\n#define chmodv2_0(a,b)  ((int) _sc_168(a,'p',(size_t)(b)|0x80))\n#undef chmod\n#define chmod(a,b) (isv2_0() && chmodv2_0(a,b))||(isv2_3() && chmodv2_3(a,b))\n#else\n#define islib() isv2_3lib()\n#define isdir() isv2_3dir()\n#undef chmod\n#define chmod(a,b) chmodv2_0(a,b)\n#endif\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in Unix */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    created_dir = FALSE;        /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            default:\n                if (isfnsym(workch) || workch == '.')\n                    *pp++ = (char)workch;\n                else\n                    *pp++ = '_';\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (islib() && G.filename[strlen(G.filename) - 1] == '/')\n            G.filename[strlen(G.filename) - 1] = '\\0';\n\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n#if 0  /*========== NOTES ==========*/\n\n  extract-to dir:      a:path/\n  buildpath:           path1/path2/ ...   (NULL-terminated)\n  pathcomp:                filename\n\n  mapname():\n    loop over chars in zipfile member name\n      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?\n        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)\n        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)\n        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)\n    finally add filename itself and check for existence? (could use with rename)\n        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)\n    checkdir(name, GETPATH)     -->  copy path to name and free space\n\n#endif /* 0 */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n    static int rootlen = 0;   /* length of rootpath */\n    static char *rootpath;    /* user's \"extract-to\" directory */\n    static char rootdisk[3];  /* user's \"extract-to\" disk */\n    static char *buildpath;   /* full path (so far) to extracted file */\n    static char *end;         /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0')\n            ++end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        if ((end-buildpath) > FILNAMSIZ-3)  /* need '/', one-char name, '\\0' */\n            too_long = TRUE;                /* check if extracting directory? */\n        Trace((stderr, \"appending disk segment [%s]\\n\", FnFilter1(rootdisk)));\n        strcat(buildpath, rootdisk);\n        if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(buildpath)));\n                free(buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (islib()) {\n                ulg size;\n#ifdef OLD_THEOS_EXTRA\n                if (isv2_0lib())\n                    size = v2_0extra()->filesize;\n                else\n#endif\n                {\n                    size = (ulg) G.extra_field[5] |\n                           ((ulg) G.extra_field[6] << 8) |\n                           ((ulg) G.extra_field[7] << 16) |\n                           ((ulg) G.extra_field[8] << 24);\n                }\n                if (makelib(buildpath, size / 64)) {\n                    Info(slide, 1, ((char*)slide,\n                      \"checkdir error:  can't create library %s\\n\\\n                     unable to process %s.\\n\",\n                      FnFilter2(buildpath), FnFilter1(G.filename));\n                    free(buildpath);\n                    /* path didn't exist, tried to create, failed */\n                    return MPN_ERR_SKIP;\n                }\n            } else if (mkdir(buildpath) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(buildpath), FnFilter1(G.filename));\n                free(buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode) && isdir()) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename));\n            free(buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        } else if (!S_ISLIB(G.statbuf.st_mode) && islib()) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not library\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(buildpath), FnFilter1(G.filename));\n            free(buildpath);\n            /* path existed but wasn't lib */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(buildpath)));\n            free(buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *end++ = '/';\n        *end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(buildpath);\n        buildpath = end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*end = *pathcomp++) != '\\0') {\n            ++end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((end-old_end) > FILENAME_MAX)      /* GRR:  proper constant? */\n                *(end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((end-buildpath) >= FILNAMSIZ) {\n                *--end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        strcat(buildpath, rootdisk);\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+\n                                        (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((rootlen > 0) && !renamed_fullpath) {\n            strcpy(buildpath, rootpath);\n            end = buildpath + rootlen;\n        } else {\n            *buildpath = '\\0';\n            end = buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        if (pathcomp == (char *)NULL) {\n            rootlen = 0;\n            return MPN_OK;\n        }\n        if (rootlen > 0)        /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((rootlen = strlen(pathcomp)) > 0) {\n            int prepend_slash = 0;\n            char *tmproot, *p;\n\n            if (*pathcomp == ':') {\n                preprend_slash = 1;\n                rootlen++;\n            }\n            if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            if (prepend_slash)\n                strcpy(tmproot, \"/\");\n            else\n                *tmproot = '\\0';\n            strcat(tmproot, pathcomp);\n            Trace((stderr, \"initializing root path to [%s]\\n\",\n              FnFilter1(tmproot)));\n            if (tmproot[rootlen-1] == '/') {\n                tmproot[--rootlen] = '\\0';\n            }\n            if (rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\",\n                      FnFilter1(tmproot)));\n                    free(tmproot);\n                    rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            /* split rootpath in path and disk */\n            if ((p = strchr(tmproot, ':')) != NULL) {\n                strncpy(rootdisk, p, 2);\n                rootdisk[2] = '\\0';\n                *p = '\\0';\n                rootlen = p - tmproot;\n            } else\n                rootdisk[0] = '\\0';\n            if (rootpath[rootlen - 1] != '/') {\n                rootpath[rootlen++] = '/';\n                rootpath[rootlen] = '\\0';\n            }\n            if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {\n                free(tmproot);\n                rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s], rootdisk now = [%s]\\n\",\n                FnFilter1(rootpath), FnFilter2(rootdisk)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (rootlen > 0) {\n            free(rootpath);\n            rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n#ifdef MORE\n\n/**************************/\n/* Function screenlines() */\n/**************************/\n\nint screenlines()\n{\n    return getpl(27) + 1;\n}\n\n#endif /* MORE */\n\n\n\n\n\n#if (!defined(MTS) || defined(SET_DIR_ATTRIB))\nstatic void get_extattribs OF((__GPRO__ iztimes *pzt));\n\nstatic int get_extattribs(__G__ pzt)\n    __GDEF\n    iztimes *pzt;\n{\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.\n  ---------------------------------------------------------------------------*/\n#ifdef USE_EF_UT_TIME\n    unsigned eb_izux_flg;\n\n    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                   (G.tz_is_valid ? pzt : NULL),\n#else\n                   pzt,\n#endif\n                   z_uidgid) : 0);\n    if (eb_izux_flg & EB_UT_FL_MTIME) {\n        TTrace((stderr, \"\\nget_extattribs:  Unix e.f. modif. time = %ld\\n\",\n          pzt->mtime));\n    } else {\n        pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n    if (eb_izux_flg & EB_UT_FL_ATIME) {\n        TTrace((stderr, \"get_extattribs:  Unix e.f. access time = %ld\\n\",\n          pzt->atime));\n    } else {\n        pzt->atime = pzt->mtime;\n        TTrace((stderr, \"\\nget_extattribs:  modification/access times = %ld\\n\",\n          pzt->mtime));\n    }\n#else\n    pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    pzt->atime = pzt->mtime;\n#endif\n}\n#endif /* !MTS || SET_DIR_ATTRIB */\n\n\n\n#ifndef MTS\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } zt;\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate a storage area, put the uncom-\n    pressed \"data\" in it, and create the link.  Since we know it's a symbolic\n    link to start with, we shouldn't have to worry about overflowing unsigned\n    ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n    fclose(G.outfile);\n\n    get_extattribs(__G__ &(zt.t3));\n\n    /* set the file's access and modification times */\n    if (utime(G.filename, &(zt.t2))) {\n        if (uO.qflag)\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  cannot set times for %s\\n\", FnFilter1(G.filename)));\n        else\n            Info(slide, 0x201, ((char *)slide,\n              \" (warning) cannot set times\"));\n    }\n\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n    if (chmod(G.filename, 0xffff & G.pInfo->file_attr))\n        perror(\"chmod (file attributes) error\");\n\n/*---------------------------------------------------------------------------\n    Change the file structure and set native .\n  ---------------------------------------------------------------------------*/\n\n    if (isv2_3()) {\n        chorg(G.filename, G.extra_field[9]);\n        chlen(G.filename,\n            (ush) G.extra_field[10] | ((ush) G.extra_field[11] << 8),\n            (ush) G.extra_field[12] | ((ush) G.extra_field[13] << 8));\n        chgrow(G.filename, G.extra_field[14]);\n    }\n#if OLD_THEOS_EXTRA\n     else if (isv2_0()) {\n        chorg(G.filename, G.pInfo->file_attr & 0xFF);\n        chlen(G.filename, v2_0extra()->reclen, v2_0extra()->keylen);\n        chgrow(G.filename, v2_0extra()->filegrow);\n    }\n#endif\n} /* end function close_outfile() */\n\n#endif /* !MTS */\n\n\n\n\n#ifdef SET_DIR_ATTRIB\n/* messages of code for setting directory attributes */\nstatic ZCONST char Far DirlistUidGidFailed[] =\n  \"warning:  cannot set UID %d and/or GID %d for %s\\n\";\nstatic ZCONST char Far DirlistUtimeFailed[] =\n  \"warning:  cannot set modification, access times for %s\\n\";\n#  ifndef NO_CHMOD\n  static ZCONST char Far DirlistChmodFailed[] =\n    \"warning:  cannot set permissions for %s\\n\";\n#  endif\n\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    uxdirattr *d_entry;\n\n    d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename));\n    *pd = (direntry *)d_entry;\n    if (d_entry == (uxdirattr *)NULL) {\n        return PK_MEM;\n    }\n    d_entry->fn = d_entry->fnbuf;\n    strcpy(d_entry->fn, G.filename);\n\n    d_entry->perms = G.pInfo->file_attr;\n\n    get_extattribs(__G__ &(d_entry->u.t3));\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    int errval = PK_OK;\n\n    if (utime(d->fn, &UxAtt(d)->u.t2)) {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(DirlistUtimeFailed), FnFilter1(d->fn)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n    if (chmod(d->fn, 0xffff & UxAtt(d)->perms)) {\n        Info(slide, 0x201, ((char *)slide,\n          LoadFarString(DirlistChmodFailed), FnFilter1(d->fn)));\n        /* perror(\"chmod (file attributes) error\"); */\n        if (!errval)\n            errval = PK_WARN;\n    }\n    return errval;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    ztimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    char buf1[40];\n    extern char Far  CompiledWith[];\n\n    sprintf(slide, CompiledWith,\n        \"THEOS C \",\"5.28\", \"THEOS \", \"4.x\", \" on \", __DATE__);\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/theos/thscfg.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __theos_thscfg_h\n#define __theos_thscfg_h\n\n#include <unistd.h>        /* dup proto & unix system calls live here */\n#define _HANDLE_DEFINED\n#include <fcntl.h>         /* O_BINARY for open() w/o CR/LF translation */\n#include <conio.h>\n#include <time.h>\n#include <sys/types.h>     /* off_t, time_t, dev_t, ... */\n#include \"theos/stat.h\"\n#include <sys/utime.h>\n#define GOT_UTIMBUF\n#define DATE_FORMAT   dateformat()\n#define SCREENLINES   screenlines()\n#define USE_EF_UT_TIME\n#define DIR_END '/'\n#define INT_SPRINTF\n#define lenEOL        1\n#define PutNativeEOL  *q++ = native(CR);\n#define PIPE_ERROR (errno = 9999)\n#define isatty(a) _isatty(a)\n#undef match\nint open(const char *name, int mode, ...);\nsize_t read(int fd, char *buf, size_t len);\nsize_t write(int fd, char *buf, size_t len);\nunsigned long lseek(int fd, long offset, int base);\nint close(int);\nint _fprintf(FILE *fp, const char *fmt, ...);\nint _isatty(int);\ntypedef unsigned char uid_t;\ntypedef unsigned char gid_t;\n\nextern int _sprintf(char *s, const char *fmt, ...);\n\n#ifndef NO_BOGUS_SPC\n# include <stdio.h>\n# undef fprintf\n# undef sprintf\n# define fprintf _fprintf\n# define sprintf _sprintf\n#else /* NO_BOGUS_SPC */\n#ifndef Info   /* may already have been defined for redirection */\n#  ifdef FUNZIP\n#    define Info(buf,flag,sprf_arg) \\\n     fprintf((flag)&1? stderr : stdout, (char *)(_sprintf sprf_arg, (buf)))\n#  else\n#    define Info(buf,flag,sprf_arg) \\\n     UzpMessagePrnt((zvoid *)&G, (uch *)(buf), (ulg)_sprintf sprf_arg, (flag))\n#  endif\n#endif /* !Info */\n#endif /* ?NO_BOGUS_SPC */\n\n#endif /* !__theos_thscfg_h */\n\n"
  },
  {
    "path": "deps/infozip/unzip60/timezone.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Replacement time library functions, based on platform independent public\n * domain timezone code from ftp://elsie.nci.nih.gov/pub, with mktime and\n * mkgmtime from our own mktime.c in Zip.\n *\n * Contains:  tzset()\n *            __tzset()\n *            gmtime()\n *            localtime()\n *            mktime()\n *            mkgmtime()\n *            GetPlatformLocalTimezone()  [different versions]\n */\n\n/* HISTORY/CHANGES\n * 17 Jun 00, Paul Kienitz, added the PD-based tzset(), localtime(), and so on\n *            to amiga/filedate.c, replacing GNU-based functions which had\n *            replaced time_lib.c, both having been rejected for licensing\n *            reasons.  Support for timezone files and leap seconds was removed.\n *\n * 23 Aug 00, Paul Kienitz, split into separate timezone.c file, made platform\n *            independent, copied in mktime() and mkgmtime() from Zip, renamed\n *            locale_TZ as GetPlatformLocalTimezone(), for use as a generic\n *            hook by other platforms.\n */\n\n#ifndef __timezone_c\n#define __timezone_c\n\n\n#include \"zip.h\"\n#include \"timezone.h\"\n#include <ctype.h>\n#include <errno.h>\n\n#ifdef IZTZ_DEFINESTDGLOBALS\nlong timezone = 0;\nint daylight = 0;\nchar *tzname[2];\n#endif\n\n#ifndef IZTZ_GETLOCALETZINFO\n#  define IZTZ_GETLOCALETZINFO(ptzstruct, pgenrulefunct) (FALSE)\n#endif\n\nint real_timezone_is_set = FALSE;       /* set by tzset() */\n\n\n#define TZDEFRULESTRING \",M4.1.0,M10.5.0\"\n#define TZDEFAULT       \"EST5EDT\"\n\n#define SECSPERMIN      60\n#define MINSPERHOUR     60\n#define HOURSPERDAY     24\n#define DAYSPERWEEK     7\n#define DAYSPERNYEAR    365\n#define DAYSPERLYEAR    366\n#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)\n#define SECSPERDAY      ((long) SECSPERHOUR * HOURSPERDAY)\n#define MONSPERYEAR 12\n\n#define EPOCH_WDAY      4     /* Jan 1, 1970 was thursday */\n#define EPOCH_YEAR      1970\n#define TM_YEAR_BASE    1900\n#define FIRST_GOOD_YEAR ((time_t) -1 < (time_t) 1 ? EPOCH_YEAR-68 : EPOCH_YEAR)\n#define LAST_GOOD_YEAR  (EPOCH_YEAR + ((time_t) -1 < (time_t) 1 ? 67 : 135))\n\n#define YDAYS(month, year) yr_days[leap(year)][month]\n\n/* Nonzero if `y' is a leap year, else zero. */\n#define leap(y)  (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n\n/* Number of leap years from EPOCH_YEAR  to `y' (not including `y' itself). */\n#define _P4      ((EPOCH_YEAR / 4) * 4 + 1)\n#define _P100    ((EPOCH_YEAR / 100) * 100 + 1)\n#define _P400    ((EPOCH_YEAR / 400) * 400 + 1)\n#define nleap(y) (((y) - _P4) / 4 - ((y) - _P100) / 100 + ((y) - _P400) / 400)\n\n/* Length of month `m' (0 .. 11) */\n#define monthlen(m, y) (yr_days[0][(m)+1] - yr_days[0][m] + \\\n                        ((m) == 1 && leap(y)))\n\n/* internal module-level constants */\n#ifndef IZ_MKTIME_ONLY\nstatic ZCONST char  gmt[] = \"GMT\";\nstatic ZCONST int    mon_lengths[2][MONSPERYEAR] = {\n    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\n    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }\n};\n#endif /* !IZ_MKTIME_ONLY */\nstatic ZCONST int    yr_days[2][MONSPERYEAR+1] = {\n    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },\n    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }\n};\n#ifndef IZ_MKTIME_ONLY\nstatic ZCONST int   year_lengths[2] = {\n    DAYSPERNYEAR, DAYSPERLYEAR\n};\n\n/* internal variables */\nstatic struct state statism;\n\n\n/* prototypes of static functions */\nstatic time_t transtime OF((ZCONST time_t janfirst, ZCONST int year,\n                            ZCONST struct rule * ZCONST rulep,\n                            ZCONST long offset));\nstatic void generate_transitions OF((register struct state * ZCONST sp,\n                                     ZCONST struct rule * ZCONST start,\n                                     ZCONST struct rule * ZCONST end));\nstatic ZCONST char *getzname OF((ZCONST char *strp));\nstatic ZCONST char *getnum OF((ZCONST char *strp, int * ZCONST nump,\n                               ZCONST int min, ZCONST int max));\nstatic ZCONST char *getsecs OF((ZCONST char *strp, long * ZCONST secsp));\nstatic ZCONST char *getoffset OF((ZCONST char *strp, long * ZCONST offsetp));\nstatic ZCONST char *getrule OF((ZCONST char *strp, struct rule * ZCONST rulep));\nstatic int Parse_TZ OF((ZCONST char *name, register struct state * ZCONST sp));\n\n\nstatic time_t transtime(janfirst, year, rulep, offset)\n     ZCONST time_t janfirst;\n     ZCONST int year;\n     ZCONST struct rule * ZCONST rulep;\n     ZCONST long offset;\n{\n    register int    leapyear;\n    register time_t value;\n    register int    i;\n    int             d, m1, yy0, yy1, yy2, dow;\n\n    value = 0;\n    leapyear = leap(year);\n    switch (rulep->r_type) {\n\n    case JULIAN_DAY:\n        /*\n        ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap\n        ** years.\n        ** In non-leap years, or if the day number is 59 or less, just\n        ** add SECSPERDAY times the day number-1 to the time of\n        ** January 1, midnight, to get the day.\n        */\n        value = janfirst + (rulep->r_day - 1) * SECSPERDAY;\n        if (leapyear && rulep->r_day >= 60)\n            value += SECSPERDAY;\n        break;\n\n    case DAY_OF_YEAR:\n        /*\n        ** n - day of year.\n        ** Just add SECSPERDAY times the day number to the time of\n        ** January 1, midnight, to get the day.\n        */\n        value = janfirst + rulep->r_day * SECSPERDAY;\n        break;\n\n    case MONTH_NTH_DAY_OF_WEEK:\n        /*\n        ** Mm.n.d - nth \"dth day\" of month m.\n        */\n        value = janfirst;\n/*\n        for (i = 0; i < rulep->r_mon - 1; ++i)\n            value += mon_lengths[leapyear][i] * SECSPERDAY;\n*/\n        value += yr_days[leapyear][rulep->r_mon - 1] * SECSPERDAY;\n\n        /*\n        ** Use Zeller's Congruence to get day-of-week of first day of\n        ** month.\n        */\n        m1 = (rulep->r_mon + 9) % 12 + 1;\n        yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;\n        yy1 = yy0 / 100;\n        yy2 = yy0 % 100;\n        dow = ((26 * m1 - 2) / 10 +\n            1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;\n        if (dow < 0)\n            dow += DAYSPERWEEK;\n\n        /*\n        ** \"dow\" is the day-of-week of the first day of the month.  Get\n        ** the day-of-month (zero-origin) of the first \"dow\" day of the\n        ** month.\n        */\n        d = rulep->r_day - dow;\n        if (d < 0)\n            d += DAYSPERWEEK;\n        for (i = 1; i < rulep->r_week; ++i) {\n            if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1])\n                break;\n            d += DAYSPERWEEK;\n        }\n\n        /*\n        ** \"d\" is the day-of-month (zero-origin) of the day we want.\n        */\n        value += d * SECSPERDAY;\n        break;\n    }\n\n    /*\n    ** \"value\" is the Epoch-relative time of 00:00:00 UTC on the day in\n    ** question.  To get the Epoch-relative time of the specified local\n    ** time on that day, add the transition time and the current offset\n    ** from UTC.\n    */\n    return value + rulep->r_time + offset;\n}\n\nstatic void generate_transitions(sp, start, end)\n     register struct state * ZCONST sp;\n     ZCONST struct rule * ZCONST start;\n     ZCONST struct rule * ZCONST end;\n{\n    register int             year;\n    register time_t          janfirst;\n    time_t                   starttime;\n    time_t                   endtime;\n    long                     stdoffset = -sp->ttis[0].tt_gmtoff;\n    long                     dstoffset = -sp->ttis[1].tt_gmtoff;\n    register time_t *        atp;\n    register unsigned char * typep;\n\n    /*\n    ** Two transitions per year, from EPOCH_YEAR to LAST_GOOD_YEAR.\n    */\n    sp->timecnt = 2 * (LAST_GOOD_YEAR - EPOCH_YEAR + 1);\n    atp = sp->ats;\n    typep = sp->types;\n    janfirst = 0;\n    for (year = EPOCH_YEAR; year <= LAST_GOOD_YEAR; ++year) {\n        starttime = transtime(janfirst, year, start, stdoffset);\n        endtime = transtime(janfirst, year, end, dstoffset);\n        if (starttime > endtime) {\n            *atp++ = endtime;\n            *typep++ = 0;   /* DST ends */\n            *atp++ = starttime;\n            *typep++ = 1;   /* DST begins */\n        } else {\n            *atp++ = starttime;\n            *typep++ = 1;   /* DST begins */\n            *atp++ = endtime;\n            *typep++ = 0;   /* DST ends */\n        }\n        janfirst += year_lengths[leap(year)] * SECSPERDAY;\n    }\n}\n\nstatic ZCONST char *getzname(strp)\n     ZCONST char *strp;\n{\n    register char   c;\n\n    while ((c = *strp) != '\\0' && !isdigit(c) && c != ',' && c != '-' &&\n        c != '+')\n            ++strp;\n    return strp;\n}\n\nstatic ZCONST char *getnum(strp, nump, min, max)\n     ZCONST char *strp;\n     int * ZCONST nump;\n     ZCONST int min;\n     ZCONST int max;\n{\n    register char   c;\n    register int    num;\n\n    if (strp == NULL || !isdigit(c = *strp))\n        return NULL;\n    num = 0;\n    do {\n        num = num * 10 + (c - '0');\n        if (num > max)\n            return NULL;    /* illegal value */\n        c = *++strp;\n    } while (isdigit(c));\n    if (num < min)\n        return NULL;        /* illegal value */\n    *nump = num;\n    return strp;\n}\n\nstatic ZCONST char *getsecs(strp, secsp)\n     ZCONST char *strp;\n     long * ZCONST secsp;\n{\n    int num;\n\n    /*\n    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like\n    ** \"M10.4.6/26\", which does not conform to Posix,\n    ** but which specifies the equivalent of\n    ** ``02:00 on the first Sunday on or after 23 Oct''.\n    */\n    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);\n    if (strp == NULL)\n        return NULL;\n    *secsp = num * (long) SECSPERHOUR;\n    if (*strp == ':') {\n        ++strp;\n        strp = getnum(strp, &num, 0, MINSPERHOUR - 1);\n        if (strp == NULL)\n            return NULL;\n        *secsp += num * SECSPERMIN;\n        if (*strp == ':') {\n            ++strp;\n            /* `SECSPERMIN' allows for leap seconds.  */\n            strp = getnum(strp, &num, 0, SECSPERMIN);\n            if (strp == NULL)\n                return NULL;\n            *secsp += num;\n        }\n    }\n    return strp;\n}\n\nstatic ZCONST char *getoffset(strp, offsetp)\n     ZCONST char *strp;\n     long * ZCONST offsetp;\n{\n    register int    neg = 0;\n\n    if (*strp == '-') {\n        neg = 1;\n        ++strp;\n    } else if (*strp == '+')\n        ++strp;\n    strp = getsecs(strp, offsetp);\n    if (strp == NULL)\n        return NULL;        /* illegal time */\n    if (neg)\n        *offsetp = -*offsetp;\n    return strp;\n}\n\nstatic ZCONST char *getrule(strp, rulep)\n     ZCONST char *strp;\n     struct rule * ZCONST rulep;\n{\n    if (*strp == 'J') {\n        /*\n        ** Julian day.\n        */\n        rulep->r_type = JULIAN_DAY;\n        ++strp;\n        strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);\n    } else if (*strp == 'M') {\n        /*\n        ** Month, week, day.\n        */\n        rulep->r_type = MONTH_NTH_DAY_OF_WEEK;\n        ++strp;\n        strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);\n        if (strp == NULL)\n            return NULL;\n        if (*strp++ != '.')\n            return NULL;\n        strp = getnum(strp, &rulep->r_week, 1, 5);\n        if (strp == NULL)\n            return NULL;\n        if (*strp++ != '.')\n            return NULL;\n        strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);\n    } else if (isdigit(*strp)) {\n        /*\n        ** Day of year.\n        */\n        rulep->r_type = DAY_OF_YEAR;\n        strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);\n    } else  return NULL;        /* invalid format */\n    if (strp == NULL)\n        return NULL;\n    if (*strp == '/') {\n        /*\n        ** Time specified.\n        */\n        ++strp;\n        strp = getsecs(strp, &rulep->r_time);\n    } else\n        rulep->r_time = 2 * SECSPERHOUR;    /* default = 2:00:00 */\n    return strp;\n}\n\nstatic int Parse_TZ(name, sp)\n     ZCONST char *name;\n     register struct state * ZCONST sp;\n{\n    ZCONST char *            stdname;\n    ZCONST char *            dstname;\n    size_t                   stdlen;\n    size_t                   dstlen;\n    long                     stdoffset;\n    long                     dstoffset;\n    register char *          cp;\n\n    dstname = NULL;\n    stdname = name;\n    name = getzname(name);\n    stdlen = name - stdname;\n    if (stdlen < 3)\n        return -1;\n    if (*name == '\\0')\n        return -1;\n    name = getoffset(name, &stdoffset);\n    if (name == NULL)\n        return -1;\n    if (*name != '\\0') {\n        dstname = name;\n        name = getzname(name);\n        dstlen = name - dstname;    /* length of DST zone name */\n        if (dstlen < 3)\n            return -1;\n        if (*name != '\\0' && *name != ',' && *name != ';') {\n            name = getoffset(name, &dstoffset);\n            if (name == NULL)\n                return -1;\n        } else\n            dstoffset = stdoffset - SECSPERHOUR;\n        if (*name == '\\0')\n            name = TZDEFRULESTRING;\n        if (*name == ',' || *name == ';') {\n            struct rule     start;\n            struct rule     end;\n\n            ++name;\n            if ((name = getrule(name, &start)) == NULL)\n                return -1;\n            if (*name++ != ',')\n                return -1;\n            if ((name = getrule(name, &end)) == NULL)\n                return -1;\n            if (*name != '\\0')\n                return -1;\n            sp->typecnt = 2;    /* standard time and DST */\n            sp->ttis[0].tt_gmtoff = -stdoffset;\n            sp->ttis[0].tt_isdst = 0;\n            sp->ttis[0].tt_abbrind = 0;\n            sp->ttis[1].tt_gmtoff = -dstoffset;\n            sp->ttis[1].tt_isdst = 1;\n            sp->ttis[1].tt_abbrind = stdlen + 1;\n            generate_transitions(sp, &start, &end);\n        }\n    } else {\n        dstlen = 0;\n        sp->typecnt = 1;        /* only standard time */\n        sp->timecnt = 0;\n        sp->ttis[0].tt_gmtoff = -stdoffset;\n        sp->ttis[0].tt_isdst = 0;\n        sp->ttis[0].tt_abbrind = 0;\n    }\n    sp->charcnt = stdlen + 1;\n    if (dstlen != 0)\n        sp->charcnt += dstlen + 1;\n    if ((size_t) sp->charcnt > sizeof(sp->chars))\n        return -1;\n    cp = sp->chars;\n    (void) strncpy(cp, stdname, stdlen);\n    cp += stdlen;\n    *cp++ = '\\0';\n    if (dstlen != 0) {\n        (void) strncpy(cp, dstname, dstlen);\n        *(cp + dstlen) = '\\0';\n    }\n    return 0;\n}\n\nvoid tzset()\n{\n    char *TZstring;\n    int dstfirst;\n    static char *old_TZstring = NULL;\n\n    TZstring = getenv(\"TZ\");    /* read TZ envvar */\n    if (old_TZstring && TZstring && !strcmp(old_TZstring, TZstring))\n        /* do not repeatedly parse an unchanged TZ specification */\n        return;\n    if ((TZstring && TZstring[0] && Parse_TZ(TZstring, &statism) == 0)\n                || IZTZ_GETLOCALETZINFO(&statism, generate_transitions)\n                || Parse_TZ(gmt, &statism) == 0) {\n        daylight  = statism.typecnt > 1;\n        dstfirst  = daylight && statism.ttis[0].tt_isdst && !statism.ttis[1].tt_isdst;\n        timezone  = -statism.ttis[dstfirst].tt_gmtoff;\n        tzname[0] = statism.chars + statism.ttis[dstfirst].tt_abbrind;\n        tzname[1] = statism.chars + statism.ttis[!dstfirst].tt_abbrind;\n        real_timezone_is_set = TRUE;\n        if (TZstring) {\n            if (old_TZstring)\n                old_TZstring = realloc(old_TZstring, strlen(TZstring) + 1);\n            else\n                old_TZstring = malloc(strlen(TZstring) + 1);\n            if (old_TZstring)\n                strcpy(old_TZstring, TZstring);\n        }\n    } else {\n        timezone = 0;   /* default is GMT0 which means no offsets */\n        daylight = 0;   /* from local system time                 */\n        real_timezone_is_set = FALSE;\n        if (old_TZstring) {\n            free(old_TZstring);\n            old_TZstring = NULL;\n        }\n    }\n#ifdef IZTZ_SETLOCALTZINFO\n    /* Some SAS/C library functions, e.g. stat(), call library       */\n    /* __tzset() themselves. So envvar TZ *must* exist in order to   */\n    /* to get the right offset from GMT.  XXX  TRY HARD to fix this! */\n    set_TZ(timezone, daylight);\n#endif /* IZTZ_SETLOCALTZINFO */\n}\n\n/* XXX  Does this also help SAS/C library work? */\nvoid __tzset()\n{\n    if (!real_timezone_is_set) tzset();\n}\n\nstatic struct tm _tmbuf;\n\nstruct tm *gmtime(when)\n     ZCONST time_t *when;\n{\n    long days = *when / SECSPERDAY;\n    long secs = *when % SECSPERDAY;\n    int isleap;\n\n    memset(&_tmbuf, 0, sizeof(_tmbuf));   /* get any nonstandard fields */\n    _tmbuf.tm_wday = (days + EPOCH_WDAY) % 7;\n    _tmbuf.tm_year = EPOCH_YEAR - TM_YEAR_BASE;\n    isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE);\n    while (days >= year_lengths[isleap]) {\n        days -= year_lengths[isleap];\n        _tmbuf.tm_year++;\n        isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE);\n    }\n    _tmbuf.tm_mon = 0;\n    _tmbuf.tm_yday = days;\n    while (days >= mon_lengths[isleap][_tmbuf.tm_mon])\n        days -= mon_lengths[isleap][_tmbuf.tm_mon++];\n    _tmbuf.tm_mday = days + 1;\n    _tmbuf.tm_isdst = 0;\n    _tmbuf.tm_sec = secs % SECSPERMIN;\n    _tmbuf.tm_min = (secs / SECSPERMIN) % SECSPERMIN;\n    _tmbuf.tm_hour = secs / SECSPERHOUR;\n    return &_tmbuf;\n}\n\nstruct tm *localtime(when)\n     ZCONST time_t *when;\n{\n    time_t     localwhen = *when;\n    int        timetype;\n    struct tm *ret;\n\n    __tzset();\n    if (statism.timecnt == 0 || localwhen < statism.ats[0])\n        timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 &&\n                   !statism.ttis[1].tt_isdst;\n    else {\n        for (timetype = 1; timetype < statism.timecnt; ++timetype)\n            if (localwhen < statism.ats[timetype])\n                break;\n        timetype = statism.types[timetype - 1];\n    }\n    localwhen += statism.ttis[timetype].tt_gmtoff;\n    ret = gmtime(&localwhen);\n    ret->tm_isdst = statism.ttis[timetype].tt_isdst;\n    return ret;\n}\n\n#ifdef NEED__ISINDST\nint _isindst(tb)\n    struct tm *tb;\n{\n    time_t     localt;          /* time_t equivalent of given tm struct */\n    time_t     univt;           /* assumed UTC value of given time */\n    long       tzoffset_adj;    /* timezone-adjustment `remainder' */\n    int        bailout_cnt;     /* counter of tries for tz correction */\n    int        timetype;\n\n    __tzset();\n\n    /* when DST is unsupported in current timezone, DST is always off */\n    if (statism.typecnt <= 1) return FALSE;\n\n    localt = mkgmtime(tb);\n    if (localt == (time_t)-1)\n        /* specified time is out-of-range, default to FALSE */\n        return FALSE;\n\n    univt = localt - statism.ttis[0].tt_gmtoff;\n    bailout_cnt = 3;\n    do {\n        if (statism.timecnt == 0 || univt < statism.ats[0])\n            timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 &&\n                       !statism.ttis[1].tt_isdst;\n        else {\n            for (timetype = 1; timetype < statism.timecnt; ++timetype)\n                if (univt < statism.ats[timetype])\n                    break;\n            timetype = statism.types[timetype - 1];\n        }\n        if ((tzoffset_adj = localt - univt - statism.ttis[timetype].tt_gmtoff)\n            == 0L)\n            break;\n        univt += tzoffset_adj;\n    } while (--bailout_cnt > 0);\n\n    /* return TRUE when DST is active at given time */\n    return (statism.ttis[timetype].tt_isdst);\n}\n#endif /* NEED__ISINDST */\n#endif /* !IZ_MKTIME_ONLY */\n\n/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT\n   of the local time and date in the exploded time structure `tm',\n   adjust out of range fields in `tm' and set `tm->tm_yday', `tm->tm_wday'.\n   If `tm->tm_isdst < 0' was passed to mktime(), the correct setting of\n   tm_isdst is determined and returned. Otherwise, mktime() assumes this\n   field as valid; its information is used when converting local time\n   to UTC.\n   Return -1 if time in `tm' cannot be represented as time_t value. */\n\ntime_t mktime(tm)\n     struct tm *tm;\n{\n  struct tm *ltm;               /* Local time. */\n  time_t loctime;               /* The time_t value of local time. */\n  time_t then;                  /* The time to return. */\n  long tzoffset_adj;            /* timezone-adjustment `remainder' */\n  int bailout_cnt;              /* counter of tries for tz correction */\n  int save_isdst;               /* Copy of the tm->isdst input value */\n\n  save_isdst = tm->tm_isdst;\n  loctime = mkgmtime(tm);\n  if (loctime == -1) {\n    tm->tm_isdst = save_isdst;\n    return (time_t)-1;\n  }\n\n  /* Correct for the timezone and any daylight savings time.\n     The correction is verified and repeated when not correct, to\n     take into account the rare case that a change to or from daylight\n     savings time occurs between when it is the time in `tm' locally\n     and when it is that time in Greenwich. After the second correction,\n     the \"timezone & daylight\" offset should be correct in all cases. To\n     be sure, we allow a third try, but then the loop is stopped. */\n  bailout_cnt = 3;\n  then = loctime;\n  do {\n    ltm = localtime(&then);\n    if (ltm == (struct tm *)NULL ||\n        (tzoffset_adj = loctime - mkgmtime(ltm)) == 0L)\n      break;\n    then += tzoffset_adj;\n  } while (--bailout_cnt > 0);\n\n  if (ltm == (struct tm *)NULL || tzoffset_adj != 0L) {\n    /* Signal failure if timezone adjustment did not converge. */\n    tm->tm_isdst = save_isdst;\n    return (time_t)-1;\n  }\n\n  if (save_isdst >= 0) {\n    if (ltm->tm_isdst  && !save_isdst)\n    {\n      if (then + 3600 < then)\n        then = (time_t)-1;\n      else\n        then += 3600;\n    }\n    else if (!ltm->tm_isdst && save_isdst)\n    {\n      if (then - 3600 > then)\n        then = (time_t)-1;\n      else\n        then -= 3600;\n    }\n    ltm->tm_isdst = save_isdst;\n  }\n\n  if (tm != ltm)  /* `tm' may already point to localtime's internal storage */\n    *tm = *ltm;\n\n  return then;\n}\n\n\n#ifndef NO_TIME_T_MAX\n   /* Provide default values for the upper limit of the time_t range.\n      These are the result of the decomposition into a `struct tm' for\n      the time value 0xFFFFFFFEL ( = (time_t)-2 ).\n      Note: `(time_t)-1' is reserved for \"invalid time\"!  */\n#  ifndef TM_YEAR_MAX\n#    define TM_YEAR_MAX         2106\n#  endif\n#  ifndef TM_MON_MAX\n#    define TM_MON_MAX          1       /* February */\n#  endif\n#  ifndef TM_MDAY_MAX\n#    define TM_MDAY_MAX         7\n#  endif\n#  ifndef TM_HOUR_MAX\n#    define TM_HOUR_MAX         6\n#  endif\n#  ifndef TM_MIN_MAX\n#    define TM_MIN_MAX          28\n#  endif\n#  ifndef TM_SEC_MAX\n#    define TM_SEC_MAX          14\n#  endif\n#endif /* NO_TIME_T_MAX */\n\n/* Adjusts out-of-range values for `tm' field `tm_member'. */\n#define ADJUST_TM(tm_member, tm_carry, modulus) \\\n  if ((tm_member) < 0) { \\\n    tm_carry -= (1 - ((tm_member)+1) / (modulus)); \\\n    tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \\\n  } else if ((tm_member) >= (modulus)) { \\\n    tm_carry += (tm_member) / (modulus); \\\n    tm_member = (tm_member) % (modulus); \\\n  }\n\n/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT\n   of the Greenwich Mean time and date in the exploded time structure `tm'.\n   This function does always put back normalized values into the `tm' struct,\n   parameter, including the calculated numbers for `tm->tm_yday',\n   `tm->tm_wday', and `tm->tm_isdst'.\n   Returns -1 if the time in the `tm' parameter cannot be represented\n   as valid `time_t' number. */\n\ntime_t mkgmtime(tm)\n     struct tm *tm;\n{\n  int years, months, days, hours, minutes, seconds;\n\n  years = tm->tm_year + TM_YEAR_BASE;   /* year - 1900 -> year */\n  months = tm->tm_mon;                  /* 0..11 */\n  days = tm->tm_mday - 1;               /* 1..31 -> 0..30 */\n  hours = tm->tm_hour;                  /* 0..23 */\n  minutes = tm->tm_min;                 /* 0..59 */\n  seconds = tm->tm_sec;                 /* 0..61 in ANSI C. */\n\n  ADJUST_TM(seconds, minutes, 60)\n  ADJUST_TM(minutes, hours, 60)\n  ADJUST_TM(hours, days, 24)\n  ADJUST_TM(months, years, 12)\n  if (days < 0)\n    do {\n      if (--months < 0) {\n        --years;\n        months = 11;\n      }\n      days += monthlen(months, years);\n    } while (days < 0);\n  else\n    while (days >= monthlen(months, years)) {\n      days -= monthlen(months, years);\n      if (++months >= 12) {\n        ++years;\n        months = 0;\n      }\n    }\n\n  /* Restore adjusted values in tm structure */\n  tm->tm_year = years - TM_YEAR_BASE;\n  tm->tm_mon = months;\n  tm->tm_mday = days + 1;\n  tm->tm_hour = hours;\n  tm->tm_min = minutes;\n  tm->tm_sec = seconds;\n\n  /* Set `days' to the number of days into the year. */\n  days += YDAYS(months, years);\n  tm->tm_yday = days;\n\n  /* Now calculate `days' to the number of days since Jan 1, 1970. */\n  days = (unsigned)days + 365 * (unsigned)(years - EPOCH_YEAR) +\n         (unsigned)(nleap (years));\n  tm->tm_wday = ((unsigned)days + EPOCH_WDAY) % 7;\n  tm->tm_isdst = 0;\n\n  if (years < EPOCH_YEAR)\n    return (time_t)-1;\n\n#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))\n#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))\n  if (years > TM_YEAR_MAX ||\n      (years == TM_YEAR_MAX &&\n       (tm->tm_yday > (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) ||\n        (tm->tm_yday == (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) &&\n         (hours > TM_HOUR_MAX ||\n          (hours == TM_HOUR_MAX &&\n           (minutes > TM_MIN_MAX ||\n            (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))\n    return (time_t)-1;\n#endif\n#endif\n\n  return (time_t)(SECSPERDAY * (unsigned long)(unsigned)days +\n                  SECSPERHOUR * (unsigned long)hours +\n                  (unsigned long)(SECSPERMIN * minutes + seconds));\n}\n\n#endif /* __timezone_c */\n"
  },
  {
    "path": "deps/infozip/unzip60/timezone.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __timezone_h\n#define __timezone_h\n\n#ifndef IZ_MKTIME_ONLY\n\n/* limits for our timezone info data:\n * we support only basic standard and daylight time, with max 2 transitions\n * per year, but for the maximum range of years a 32-bit second counter\n * can cover (these are 136 years plus a bit more than one month)\n */\n#define TZ_MAX_TIMES    272 /* (=2*(LastGoodYr + 1 - FirstGoodYr) */\n#define TZ_MAX_TYPES    2   /* We only support basic standard and daylight */\n#ifdef WIN32    /* Win32 tzinfo supplies at max (2 * 32) chars of tz names */\n#define TZ_MAX_CHARS    64  /* Maximum number of abbreviation characters */\n#else\n#define TZ_MAX_CHARS    50  /* Maximum number of abbreviation characters */\n#endif\n\n/* supported types of transition rules */\n#define JULIAN_DAY              0   /* Jn - Julian day */\n#define DAY_OF_YEAR             1   /* n - day of year */\n#define MONTH_NTH_DAY_OF_WEEK   2   /* Mm.n.d - month, week, day of week */\n\n\nstruct ttinfo {\n    long            tt_gmtoff;  /* UTC offset in seconds */\n    int             tt_isdst;   /* used to set tm_isdst */\n    int             tt_abbrind; /* abbreviation list index */\n};\n\nstruct state {\n    int             timecnt;\n    int             typecnt;\n    int             charcnt;\n    time_t          ats[TZ_MAX_TIMES];\n    unsigned char   types[TZ_MAX_TIMES];\n    struct ttinfo   ttis[TZ_MAX_TYPES];\n    char            chars[TZ_MAX_CHARS];\n};\n\nstruct rule {\n    int             r_type;     /* type of rule--JULIAN_DAY etc */\n    int             r_day;      /* day number of rule */\n    int             r_week;     /* week number of rule */\n    int             r_mon;      /* month number of rule */\n    long            r_time;     /* transition time of rule */\n};\n\nextern int real_timezone_is_set;        /* set by tzset() */\n\n\n/* prototypes of functions not in time.h */\n\nvoid __tzset OF((void));\n\n#ifdef NEED__ISINDST\nint _isindst OF((struct tm *tb));\n#endif\n\n/* callback function to be supplied by the program that uses this library */\nint GetPlatformLocalTimezone OF((register struct state * ZCONST sp,\n        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                        ZCONST struct rule * ZCONST start,\n                                        ZCONST struct rule * ZCONST end)));\n#ifdef IZTZ_SETLOCALTZINFO\nvoid set_TZ OF((long time_zone, int day_light));\n#endif\n\n#endif /* !IZ_MKTIME_ONLY */\n\ntime_t mkgmtime OF((struct tm *tm));\n\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/tops20/Contents",
    "content": "Contents of the \"tops20\" sub-archive for UnZip 5.3 and later:\n\n  Contents       this file\n  make.mic       command file to make UnZip and ZipInfo with KCC\n  rename.mic     command file to rename Info-ZIP filenames to KCC format\n  tops20.c       TOPS20-specific routines for UnZip\n\nThis port has not been updated since version 5.0.\n"
  },
  {
    "path": "deps/infozip/unzip60/tops20/make.mic",
    "content": "@te no pau e\n@cc -c -q unzip\n@cc -c -q crc32\n@cc -c -q crypt\n@cc -c -q envarg\n@cc -c -q explod\n@cc -c -q extrac\n@cc -c -q fileio\n@cc -c -q global\n@cc -c -q inflat\n@cc -c -q list\n@cc -c -q match\n@cc -c -q proces\n@cc -c -q ttyio\n@cc -c -q unredu\n@cc -c -q unshri\n@cc -c -q zipinf\n@cc -c -q tops20\n@cc -o unzip unzip.rel crc32.rel crypt.rel envarg.rel explod.rel extrac.rel fileio.rel global.rel inflat.rel match.rel proces.rel ttyio.rel unredu.rel unshri.rel zipinf.rel tops20.rel -ltmx\n@kmic\n"
  },
  {
    "path": "deps/infozip/unzip60/tops20/rename.mic",
    "content": "@rename envargs.c envarg.c\n@rename explode.c explod.c\n@rename extract.c extrac.c\n@rename globals.c global.c\n@rename inflate.c inflat.c\n@rename unreduce.c unredu.c\n@rename unshrink.c unshri.c\n@rename zipinfo.c zipinf.c\n@kmic\n"
  },
  {
    "path": "deps/infozip/unzip60/tops20/tops20.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  tops20.c\n\n  TOPS20-specific routines for use with Info-ZIP's UnZip 5.1 and later.\n\n  Contains:  mapattr()\n             close_outfile()\n             version()\n             upper()\n             enquote()\n             dequote()\n             fnlegal()\n\n  (not yet ported:  do_wild(), mapname(), checkdir(), ...)\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)        /* just like Unix except no umask() */\n    __GDEF\n{\n    ulg  tmp = G.crec.external_file_attributes;\n\n    switch (G.pInfo->hostnum) {\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            break;\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>1 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case FS_FAT_:   /* MSDOS half of attributes should always be correct */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            tmp = !(tmp & 1) << 1;   /* read-only bit --> write perms bits */\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n#if 0\n        case ATARI_:\n        case TOPS20_:\n        default:\n            G.pInfo->file_attr = 0666;\n            break;\n#endif\n    } /* end switch (host-OS-created-by) */\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n#   define JSYS_CLASS           0070000000000\n#   define FLD(val,mask)        (((unsigned)(val)*((mask)&(-(mask))))&(mask))\n#   define _DEFJS(name,class)   (FLD(class,JSYS_CLASS) | (monsym(name)&0777777))\n#   define IDTIM                _DEFJS(\"IDTIM%\", 1)\n#   define SFTAD                _DEFJS(\"SFTAD%\", 0)\n#   define YRBASE               1900\n    int ablock[5], tblock[2];\n    int yr, mo, dy, hh, mm, ss;\n    char temp[100];\n    unsigned tad;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    struct tm *t;\n\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n\n        if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n            G.tz_is_valid &&\n#endif\n            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                              G.lrec.last_mod_dos_date, &z_utime, NULL)\n             & EB_UT_FL_MTIME))\n            t = localtime(&(z_utime.mtime));\n        else\n            t = (struct tm *)NULL;\n\n        if (t != (struct tm *)NULL)\n        {\n            yr = t->tm_year + 1900;\n            mo = t->tm_mon;\n            dy = t->tm_mday;\n            hh = t->tm_hour;\n            mm = t->tm_min;\n            ss = t->tm_sec;\n        }\n        else\n        {\n            /* dissect the date */\n            yr = ((G.lrec.last_mod_dos_date >> 9) & 0x7f) + 1980;\n            mo = ((G.lrec.last_mod_dos_date >> 5) & 0x0f) - 1;\n            dy = (G.lrec.last_mod_dos_date & 0x1f);\n\n            /* dissect the time */\n            hh = (G.lrec.last_mod_dos_time >> 11) & 0x1f;\n            mm = (G.lrec.last_mod_dos_time >> 5) & 0x3f;\n            ss = (G.lrec.last_mod_dos_time & 0x1f) * 2;\n        }\n#else /* !USE_EF_UT_TIME */\n\n        /* dissect the date */\n        yr = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + (1980 - YRBASE);\n        mo = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f;\n        dy = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;\n\n        /* dissect the time */\n        hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;\n        mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;\n        ss = (G.lrec.last_mod_dos_datetime << 1) & 0x1f;\n#endif /* ?USE_EF_UT_TIME */\n\n        sprintf(temp, \"%02d/%02d/%02d %02d:%02d:%02d\", mo, dy, yr, hh, mm, ss);\n\n        ablock[1] = (int)(temp - 1);\n        ablock[2] = 0;\n        if (!jsys(IDTIM, ablock)) {\n            Info(slide, 1, ((char *)slide, \"error:  IDTIM failure for %s\\n\",\n              G.filename));\n            fclose(G.outfile);\n            return;\n        }\n\n        tad = ablock[2];\n        tblock[0] = tad;\n        tblock[1] = tad;\n        tblock[2] = -1;\n\n        ablock[1] = fcntl(fileno(G.outfile), F_GETSYSFD, 0);\n                                                    /* _uffd[outfd]->uf_ch */\n        ablock[2] = (int) tblock;\n        ablock[3] = 3;\n        if (!jsys(SFTAD, ablock))\n            Info(slide, 1,((char *)slide,\n              \"error:  cannot set the time for %s\\n\", G.filename));\n\n    } /* if (uO.D_flag <= 1) */\n\n    fclose(G.outfile);\n\n} /* end function close_outfile() */\n\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n#if 0\n    char buf[40];\n#endif\n\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n#  ifdef __COMPILER_KCC__\n      \"KCC\", \"\",\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#  endif\n#endif\n\n      \"TOPS-20\",\n\n#if defined(foobar) || defined(FOOBAR)\n      \" (Foo BAR)\",   /* OS version or hardware */\n#else\n      \"\",\n#endif /* Foo BAR */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n\n\n/**********************/\n/*  Function upper()  */\n/**********************/\n\nint upper(s)        /* returns s in uppercase */\n    char *s;        /* string to be uppercased */\n{\n    for (;  *s;  ++s)\n        *s = toupper(*s);\n}\n\n\n\n\n\n/************************/\n/*  Function enquote()  */\n/************************/\n\nint enquote(s)      /* calls dequote(s) to normalize string, then */\n    char *s;        /*  inserts ^Vs before otherwise illegal characters */\n{                   /*  in s, assuming that s is a TOPS-20 filename */\n    char d[100];\n    char *p, *q;\n    char c;\n\n    if (s && *s) {\n        dequote(s);\n        p = s - 1;\n        q = d - 1;\n        while (c = *++p) {\n            if (!fnlegal(c))\n                *++q = '\\026';\n            *++q = c;\n        }\n        *++q = '\\0';\n        strcpy(s, d);\n    }\n    return 0;\n}\n\n\n\n\n\n/************************/\n/*  Function dequote()  */\n/************************/\n\nint dequote(s)        /* returns s without ^Vs */\n    char *s;          /* string to be dequoted */\n{\n    char d[100];\n    char *p, *q;\n    int c;\n\n    if (s && *s) {\n        p = s - 1;\n        q = d - 1;\n        while (c = *++p)\n            if (c != '\\026')\n                *++q = c;\n        *++q = '\\0';\n        strcpy(s, d);\n    }\n    return 0;\n}\n\n\n\n\n\n/************************/\n/*  Function fnlegal()  */\n/************************/\n\nint fnlegal(c)         /* returns TRUE if c is a member of the */\n    char c;            /*  legal character set for filenames */\n{\n    char *q;\n    static char *legals = {\"$%**-<>>AZ[[]]__az\"};\n\n    q = legals;\n    while (*q)\n        if (c < *q++)\n            break;\n        else if (c <= *q++)\n            return TRUE;\n\n    return FALSE;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/ttyio.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ttyio.c\n\n  This file contains routines for doing console input/output, including code\n  for non-echoing input.  It is used by the encryption/decryption code but\n  does not contain any restricted code itself.  This file is shared between\n  Info-ZIP's Zip and UnZip.\n\n  Contains:  echo()         (VMS only)\n             Echon()        (Unix only)\n             Echoff()       (Unix only)\n             screensize()   (Unix only)\n             zgetch()       (Unix, VMS, and non-Unix/VMS versions)\n             getp()         (\"PC,\" Unix/Atari/Be, VMS/VMCMS/MVS)\n\n  ---------------------------------------------------------------------------*/\n\n#define __TTYIO_C       /* identifies this source module */\n\n#include \"zip.h\"\n#include \"crypt.h\"\n\n#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))\n/* Non-echo console/keyboard input is needed for (en/de)cryption's password\n * entry, and for UnZip(SFX)'s MORE and Pause features.\n * (The corresponding #endif is found at the end of this module.)\n */\n\n#include \"ttyio.h\"\n\n#ifndef PUTC\n#  define PUTC putc\n#endif\n\n#ifdef ZIP\n#  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */\n#    undef GLOBAL\n#  endif\n#  define GLOBAL(g) g\n#else\n#  define GLOBAL(g) G.g\n#endif\n\n#if (defined(__ATHEOS__) || defined(__BEOS__))  /* why yes, we do */\n#  define HAVE_TERMIOS_H\n#endif\n\n#ifdef _POSIX_VERSION\n#  ifndef USE_POSIX_TERMIOS\n#    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */\n#  endif\n#  ifndef HAVE_TERMIOS_H\n#    define HAVE_TERMIOS_H     /* POSIX termios.h */\n#  endif\n#endif /* _POSIX_VERSION */\n\n#ifdef UNZIP            /* Zip handles this with the unix/configure script */\n#  ifndef _POSIX_VERSION\n#    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)\n#      ifndef USE_SYSV_TERMIO\n#        define USE_SYSV_TERMIO\n#      endif\n#      ifdef COHERENT\n#        ifndef HAVE_TERMIO_H\n#          define HAVE_TERMIO_H\n#        endif\n#        ifdef HAVE_SYS_TERMIO_H\n#          undef HAVE_SYS_TERMIO_H\n#        endif\n#      else /* !COHERENT */\n#        ifdef HAVE_TERMIO_H\n#          undef HAVE_TERMIO_H\n#        endif\n#        ifndef HAVE_SYS_TERMIO_H\n#           define HAVE_SYS_TERMIO_H\n#        endif\n#      endif /* ?COHERENT */\n#    endif /* (SYSV || CRAY) && !__MINT__ */\n#  endif /* !_POSIX_VERSION */\n#  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))\n#    ifndef NO_FCNTL_H\n#      define NO_FCNTL_H\n#    endif\n#  endif /* !(BSD4_4 || SYSV || __convexc__) */\n#endif /* UNZIP */\n\n#ifdef HAVE_TERMIOS_H\n#  ifndef USE_POSIX_TERMIOS\n#    define USE_POSIX_TERMIOS\n#  endif\n#endif\n\n#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))\n#  ifndef USE_SYSV_TERMIO\n#    define USE_SYSV_TERMIO\n#  endif\n#endif\n\n#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))\n#  include <sys/ioctl.h>\n#  define GOT_IOCTL_H\n   /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */\n#endif\n\n#ifndef HAVE_WORKING_GETCH\n   /* include system support for switching of console echo */\n#  ifdef VMS\n#    include <descrip.h>\n#    include <iodef.h>\n#    include <ttdef.h>\n     /* Workaround for broken header files of older DECC distributions\n      * that are incompatible with the /NAMES=AS_IS qualifier. */\n#    define sys$assign SYS$ASSIGN\n#    define sys$dassgn SYS$DASSGN\n#    define sys$qiow SYS$QIOW\n#    include <starlet.h>\n#    include <ssdef.h>\n#  else /* !VMS */\n#    ifdef HAVE_TERMIOS_H\n#      include <termios.h>\n#      define sgttyb termios\n#      define sg_flags c_lflag\n#      define GTTY(f, s) tcgetattr(f, (zvoid *) s)\n#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)\n#    else /* !HAVE_TERMIOS_H */\n#      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */\n#        ifdef HAVE_TERMIO_H\n#          include <termio.h>\n#        endif\n#        ifdef HAVE_SYS_TERMIO_H\n#          include <sys/termio.h>\n#        endif\n#        ifdef NEED_PTEM\n#          include <sys/stream.h>\n#          include <sys/ptem.h>\n#        endif\n#        define sgttyb termio\n#        define sg_flags c_lflag\n#        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)\n#        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)\n#      else /* !USE_SYSV_TERMIO */\n#        ifndef CMS_MVS\n#          if (!defined(MINIX) && !defined(GOT_IOCTL_H))\n#            include <sys/ioctl.h>\n#          endif\n#          include <sgtty.h>\n#          define GTTY gtty\n#          define STTY stty\n#          ifdef UNZIP\n             /*\n              * XXX : Are these declarations needed at all ????\n              */\n             /*\n              * GRR: let's find out...   Hmmm, appears not...\n             int gtty OF((int, struct sgttyb *));\n             int stty OF((int, struct sgttyb *));\n              */\n#          endif\n#        endif /* !CMS_MVS */\n#      endif /* ?USE_SYSV_TERMIO */\n#    endif /* ?HAVE_TERMIOS_H */\n#    ifndef NO_FCNTL_H\n#      ifndef UNZIP\n#        include <fcntl.h>\n#      endif\n#    else\n       char *ttyname OF((int));\n#    endif\n#  endif /* ?VMS */\n#endif /* !HAVE_WORKING_GETCH */\n\n\n\n#ifndef HAVE_WORKING_GETCH\n#ifdef VMS\n\nstatic struct dsc$descriptor_s DevDesc =\n        {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, \"SYS$COMMAND\"};\n     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */\n\n/*\n * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c\n * and hence on Joe Meadows' file.c code.\n */\nint echo(opt)\n    int opt;\n{\n    /*\n     * For VMS v5.x:\n     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,\n     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6\n     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,\n     *     System Services Reference Manual, pp. sys-23, sys-379\n     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,\n     *     Intro to System Routines, sec. 2.9.2\n     * Greg Roelofs, 15 Aug 91\n     */\n\n    short           DevChan, iosb[4];\n    long            status;\n    unsigned long   ttmode[2];  /* space for 8 bytes */\n\n\n    /* assign a channel to standard input */\n    status = sys$assign(&DevDesc, &DevChan, 0, 0);\n    if (!(status & 1))\n        return status;\n\n    /* use sys$qio and the IO$_SENSEMODE function to determine the current\n     * tty status (for password reading, could use IO$_READVBLK function\n     * instead, but echo on/off will be more general)\n     */\n    status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,\n                     ttmode, 8, 0, 0, 0, 0);\n    if (!(status & 1))\n        return status;\n    status = iosb[0];\n    if (!(status & 1))\n        return status;\n\n    /* modify mode buffer to be either NOECHO or ECHO\n     * (depending on function argument opt)\n     */\n    if (opt == 0)   /* off */\n        ttmode[1] |= TT$M_NOECHO;                       /* set NOECHO bit */\n    else\n        ttmode[1] &= ~((unsigned long) TT$M_NOECHO);    /* clear NOECHO bit */\n\n    /* use the IO$_SETMODE function to change the tty status */\n    status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,\n                     ttmode, 8, 0, 0, 0, 0);\n    if (!(status & 1))\n        return status;\n    status = iosb[0];\n    if (!(status & 1))\n        return status;\n\n    /* deassign the sys$input channel by way of clean-up */\n    status = sys$dassgn(DevChan);\n    if (!(status & 1))\n        return status;\n\n    return SS$_NORMAL;   /* we be happy */\n\n} /* end function echo() */\n\n\n/*\n * Read a single character from keyboard in non-echoing mode (VMS).\n * (returns EOF in case of errors)\n */\nint tt_getch()\n{\n    short           DevChan, iosb[4];\n    long            status;\n    char            kbbuf[16];  /* input buffer with - some - excess length */\n\n    /* assign a channel to standard input */\n    status = sys$assign(&DevDesc, &DevChan, 0, 0);\n    if (!(status & 1))\n        return EOF;\n\n    /* read a single character from SYS$COMMAND (no-echo) and\n     * wait for completion\n     */\n    status = sys$qiow(0,DevChan,\n                      IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,\n                      &iosb, 0, 0,\n                      &kbbuf, 1, 0, 0, 0, 0);\n    if ((status&1) == 1)\n        status = iosb[0];\n\n    /* deassign the sys$input channel by way of clean-up\n     * (for this step, we do not need to check the completion status)\n     */\n    sys$dassgn(DevChan);\n\n    /* return the first char read, or EOF in case the read request failed */\n    return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF);\n\n} /* end function tt_getch() */\n\n\n#else /* !VMS:  basically Unix */\n\n\n/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */\n#ifndef CMS_MVS\n\n#ifdef ZIP                      /* moved to globals.h for UnZip */\n   static int echofd=(-1);      /* file descriptor whose echo is off */\n#endif\n\n/*\n * Turn echo off for file descriptor f.  Assumes that f is a tty device.\n */\nvoid Echoff(__G__ f)\n    __GDEF\n    int f;                    /* file descriptor for which to turn echo off */\n{\n    struct sgttyb sg;         /* tty device structure */\n\n    GLOBAL(echofd) = f;\n    GTTY(f, &sg);             /* get settings */\n    sg.sg_flags &= ~ECHO;     /* turn echo off */\n    STTY(f, &sg);\n}\n\n/*\n * Turn echo back on for file descriptor echofd.\n */\nvoid Echon(__G)\n    __GDEF\n{\n    struct sgttyb sg;         /* tty device structure */\n\n    if (GLOBAL(echofd) != -1) {\n        GTTY(GLOBAL(echofd), &sg);    /* get settings */\n        sg.sg_flags |= ECHO;  /* turn echo on */\n        STTY(GLOBAL(echofd), &sg);\n        GLOBAL(echofd) = -1;\n    }\n}\n\n#endif /* !CMS_MVS */\n#endif /* ?VMS */\n\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n\n#ifdef ATH_BEO_UNX\n#ifdef MORE\n\n/*\n * Get the number of lines on the output terminal.  SCO Unix apparently\n * defines TIOCGWINSZ but doesn't support it (!M_UNIX).\n *\n * GRR:  will need to know width of terminal someday, too, to account for\n *       line-wrapping.\n */\n\n#if (defined(TIOCGWINSZ) && !defined(M_UNIX))\n\nint screensize(tt_rows, tt_cols)\n    int *tt_rows;\n    int *tt_cols;\n{\n    struct winsize wsz;\n#ifdef DEBUG_WINSZ\n    static int firsttime = TRUE;\n#endif\n\n    /* see termio(4) under, e.g., SunOS */\n    if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {\n#ifdef DEBUG_WINSZ\n        if (firsttime) {\n            firsttime = FALSE;\n            fprintf(stderr, \"ttyio.c screensize():  ws_row = %d\\n\",\n              wsz.ws_row);\n            fprintf(stderr, \"ttyio.c screensize():  ws_col = %d\\n\",\n              wsz.ws_col);\n        }\n#endif\n        /* number of rows */\n        if (tt_rows != NULL)\n            *tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24);\n        /* number of columns */\n        if (tt_cols != NULL)\n            *tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80);\n        return 0;    /* signal success */\n    } else {         /* this happens when piping to more(1), for example */\n#ifdef DEBUG_WINSZ\n        if (firsttime) {\n            firsttime = FALSE;\n            fprintf(stderr,\n              \"ttyio.c screensize():  ioctl(TIOCGWINSZ) failed\\n\"));\n        }\n#endif\n        /* VT-100 assumed to be minimal hardware */\n        if (tt_rows != NULL)\n            *tt_rows = 24;\n        if (tt_cols != NULL)\n            *tt_cols = 80;\n        return 1;       /* signal failure */\n    }\n}\n\n#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */\n\nint screensize(tt_rows, tt_cols)\n    int *tt_rows;\n    int *tt_cols;\n{\n    char *envptr, *getenv();\n    int n;\n    int errstat = 0;\n\n    /* GRR:  this is overly simplistic, but don't have access to stty/gtty\n     * system anymore\n     */\n    if (tt_rows != NULL) {\n        envptr = getenv(\"LINES\");\n        if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {\n            /* VT-100 assumed to be minimal hardware */\n            *tt_rows = 24;\n            errstat = 1;    /* signal failure */\n        } else {\n            *tt_rows = n;\n        }\n    }\n    if (tt_cols != NULL) {\n        envptr = getenv(\"COLUMNS\");\n        if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {\n            *tt_cols = 80;\n            errstat = 1;    /* signal failure */\n        } else {\n            *tt_cols = n;\n        }\n    }\n    return errstat;\n}\n\n#endif /* ?(TIOCGWINSZ && !M_UNIX) */\n#endif /* MORE */\n\n\n/*\n * Get a character from the given file descriptor without echo or newline.\n */\nint zgetch(__G__ f)\n    __GDEF\n    int f;                      /* file descriptor from which to read */\n{\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    char oldmin, oldtim;\n#endif\n    char c;\n    struct sgttyb sg;           /* tty device structure */\n\n    GTTY(f, &sg);               /* get settings */\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    oldmin = sg.c_cc[VMIN];     /* save old values */\n    oldtim = sg.c_cc[VTIME];\n    sg.c_cc[VMIN] = 1;          /* need only one char to return read() */\n    sg.c_cc[VTIME] = 0;         /* no timeout */\n    sg.sg_flags &= ~ICANON;     /* canonical mode off */\n#else\n    sg.sg_flags |= CBREAK;      /* cbreak mode on */\n#endif\n    sg.sg_flags &= ~ECHO;       /* turn echo off, too */\n    STTY(f, &sg);               /* set cbreak mode */\n    GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */\n\n    read(f, &c, 1);             /* read our character */\n\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    sg.c_cc[VMIN] = oldmin;     /* restore old values */\n    sg.c_cc[VTIME] = oldtim;\n    sg.sg_flags |= ICANON;      /* canonical mode on */\n#else\n    sg.sg_flags &= ~CBREAK;     /* cbreak mode off */\n#endif\n    sg.sg_flags |= ECHO;        /* turn echo on */\n    STTY(f, &sg);               /* restore canonical mode */\n    GLOBAL(echofd) = -1;\n\n    return (int)(uch)c;\n}\n\n\n#else /* !ATH_BEO_UNX */\n#ifndef VMS     /* VMS supplies its own variant of getch() */\n\n\nint zgetch(__G__ f)\n    __GDEF\n    int f;    /* file descriptor from which to read (must be open already) */\n{\n    char c, c2;\n\n/*---------------------------------------------------------------------------\n    Get a character from the given file descriptor without echo; can't fake\n    CBREAK mode (i.e., newline required), but can get rid of all chars up to\n    and including newline.\n  ---------------------------------------------------------------------------*/\n\n    echoff(f);\n    read(f, &c, 1);\n    if (c != '\\n')\n        do {\n            read(f, &c2, 1);   /* throw away all other chars up thru newline */\n        } while (c2 != '\\n');\n    echon();\n    return (int)c;\n}\n\n#endif /* !VMS */\n#endif /* ?ATH_BEO_UNX */\n\n#endif /* UNZIP && !FUNZIP */\n#endif /* !HAVE_WORKING_GETCH */\n\n\n#if CRYPT                       /* getp() is only used with full encryption */\n\n/*\n * Simple compile-time check for source compatibility between\n * zcrypt and ttyio:\n */\n#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))\n   error:  This Info-ZIP tool requires zcrypt 2.7 or later.\n#endif\n\n/*\n * Get a password of length n-1 or less into *p using the prompt *m.\n * The entered password is not echoed.\n */\n\n#ifdef HAVE_WORKING_GETCH\n/*\n * For the AMIGA, getch() is defined as Agetch(), which is in\n * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()\n * uses the infrastructure that is already in place in filedate.c, it is\n * smaller.  With this function, echoff() and echon() are not needed.\n *\n * For the MAC, a non-echo macgetch() function is defined in the MacOS\n * specific sources which uses the event handling mechanism of the\n * desktop window manager to get a character from the keyboard.\n *\n * For the other systems in this section, a non-echo getch() function\n * is either contained the C runtime library (conio package), or getch()\n * is defined as an alias for a similar system specific RTL function.\n */\n\n#ifndef WINDLL   /* WINDLL does not support a console interface */\n#ifndef QDOS     /* QDOS supplies a variant of this function */\n\n/* This is the getp() function for all systems (with TTY type user interface)\n * that supply a working `non-echo' getch() function for \"raw\" console input.\n */\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n\n    /* get password */\n    w = \"\";\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* display prompt and flush */\n        fflush(stderr);\n        i = 0;\n        do {                    /* read line, keeping first n characters */\n            if ((c = (char)getch()) == '\\r')\n                c = '\\n';       /* until user hits CR */\n            if (c == 8 || c == 127) {\n                if (i > 0) i--; /* the `backspace' and `del' keys works */\n            }\n            else if (i < n)\n                p[i++] = c;     /* truncate past n */\n        } while (c != '\\n');\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* !QDOS */\n#endif /* !WINDLL */\n\n\n#else /* !HAVE_WORKING_GETCH */\n\n\n#if (defined(ATH_BEO_UNX) || defined(__MINT__))\n\n#ifndef _PATH_TTY\n#  ifdef __MINT__\n#    define _PATH_TTY ttyname(2)\n#  else\n#    define _PATH_TTY \"/dev/tty\"\n#  endif\n#endif\n\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n    int f;                      /* file descriptor for tty device */\n\n#ifdef PASSWD_FROM_STDIN\n    /* Read from stdin. This is unsafe if the password is stored on disk. */\n    f = 0;\n#else\n    /* turn off echo on tty */\n\n    if ((f = open(_PATH_TTY, 0)) == -1)\n        return NULL;\n#endif\n    /* get password */\n    w = \"\";\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* prompt */\n        fflush(stderr);\n        i = 0;\n        echoff(f);\n        do {                    /* read line, keeping n */\n            read(f, &c, 1);\n            if (i < n)\n                p[i++] = c;\n        } while (c != '\\n');\n        echon();\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n\n#ifndef PASSWD_FROM_STDIN\n    close(f);\n#endif\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* ATH_BEO_UNX || __MINT__ */\n\n\n\n#if (defined(VMS) || defined(CMS_MVS))\n\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n    FILE *f;                    /* file structure for SYS$COMMAND device */\n\n#ifdef PASSWD_FROM_STDIN\n    f = stdin;\n#else\n    if ((f = fopen(ctermid(NULL), \"r\")) == NULL)\n        return NULL;\n#endif\n\n    /* get password */\n    fflush(stdout);\n    w = \"\";\n    do {\n        if (*w)                 /* bug: VMS apparently adds \\n to NULL fputs */\n            fputs(w, stderr);   /* warning if back again */\n        fputs(m, stderr);       /* prompt */\n        fflush(stderr);\n        i = 0;\n        echoff(f);\n        do {                    /* read line, keeping n */\n            if ((c = (char)getc(f)) == '\\r')\n                c = '\\n';\n            if (i < n)\n                p[i++] = c;\n        } while (c != '\\n');\n        echon();\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n#ifndef PASSWD_FROM_STDIN\n    fclose(f);\n#endif\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* VMS || CMS_MVS */\n#endif /* ?HAVE_WORKING_GETCH */\n#endif /* CRYPT */\n#endif /* CRYPT || (UNZIP && !FUNZIP) */\n"
  },
  {
    "path": "deps/infozip/unzip60/ttyio.h",
    "content": "/*\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n   ttyio.h\n */\n\n#ifndef __ttyio_h   /* don't include more than once */\n#define __ttyio_h\n\n#ifndef __crypt_h\n#  include \"crypt.h\"  /* ensure that encryption header file has been seen */\n#endif\n\n#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))\n/*\n * Non-echo keyboard/console input support is needed and enabled.\n */\n\n#ifndef __G         /* UnZip only, for now (DLL stuff) */\n#  define __G\n#  define __G__\n#  define __GDEF\n#  define __GPRO    void\n#  define __GPRO__\n#endif\n\n#ifndef ZCONST      /* UnZip only (until have configure script like Zip) */\n#  define ZCONST const\n#endif\n\n#if (defined(MSDOS) || defined(OS2) || defined(WIN32))\n#  ifndef DOS_OS2_W32\n#    define DOS_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(__human68k__))\n#  ifndef DOS_H68_OS2_W32\n#    define DOS_H68_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(FLEXOS))\n#  ifndef DOS_FLX_OS2_W32\n#    define DOS_FLX_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))\n#  ifndef DOS_FLX_H68_OS2_W32\n#    define DOS_FLX_H68_OS2_W32\n#  endif\n#endif\n\n#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX))\n#  ifndef ATH_BEO_UNX\n#    define ATH_BEO_UNX\n#  endif\n#endif\n\n#if (defined(VM_CMS) || defined(MVS))\n#  ifndef CMS_MVS\n#    define CMS_MVS\n#  endif\n#endif\n\n\n/* Function prototypes */\n\n/* The following systems supply a `non-echo' character input function \"getch()\"\n * (or an alias) and do not need the echoff() / echon() function pair.\n */\n#ifdef AMIGA\n#  define echoff(f)\n#  define echon()\n#  define getch() Agetch()\n#  define HAVE_WORKING_GETCH\n#endif /* AMIGA */\n\n#ifdef ATARI\n#  define echoff(f)\n#  define echon()\n#  include <osbind.h>\n#  define getch() (Cnecin() & 0x000000ff)\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef MACOS\n#  define echoff(f)\n#  define echon()\n#  define getch() macgetch()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef NLM\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef QDOS\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef RISCOS\n#  define echoff(f)\n#  define echon()\n#  define getch() SWI_OS_ReadC()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef DOS_H68_OS2_W32\n#  define echoff(f)\n#  define echon()\n#  ifdef WIN32\n#    ifndef getch\n#      define getch() getch_win32()\n#    endif\n#  else /* !WIN32 */\n#    ifdef __EMX__\n#      ifndef getch\n#        define getch() _read_kbd(0, 1, 0)\n#      endif\n#    else /* !__EMX__ */\n#      ifdef __GO32__\n#        include <pc.h>\n#        define getch() getkey()\n#      else /* !__GO32__ */\n#        include <conio.h>\n#      endif /* ?__GO32__ */\n#    endif /* ?__EMX__ */\n#  endif /* ?WIN32 */\n#  define HAVE_WORKING_GETCH\n#endif /* DOS_H68_OS2_W32 */\n\n#ifdef FLEXOS\n#  define echoff(f)\n#  define echon()\n#  define getch() getchar() /* not correct, but may not be on a console */\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal\n * input echo on and off. The following \"fake\" definitions allow inclusion\n * of crypt support and UnZip's \"pause prompting\" features, but without\n * any echo suppression.\n */\n#ifdef CMS_MVS\n#  define echoff(f)\n#  define echon()\n#endif\n\n#ifdef TANDEM\n#  define echoff(f)\n#  define echon()\n#  define getch() zgetch() /* defined in TANDEMC */\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* The THEOS C runtime library supplies the function conmask() to toggle\n * terminal input echo on (conmask(\"e\")) and off (conmask(\"n\")).  But,\n * since THEOS C RTL also contains a working non-echo getch() function,\n * the echo toggles are not needed.\n */\n#ifdef THEOS\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* VMS has a single echo() function in ttyio.c to toggle terminal\n * input echo on and off.\n */\n#ifdef VMS\n#  define echoff(f)  echo(0)\n#  define echon()    echo(1)\n#  define getch()    tt_getch()\n#  define FGETCH(f)  tt_getch()\n   int echo OF((int));\n   int tt_getch OF((void));\n#endif\n\n/* For all other systems, ttyio.c supplies the two functions Echoff() and\n * Echon() for suppressing and (re)enabling console input echo.\n */\n#ifndef echoff\n#  define echoff(f)  Echoff(__G__ f)\n#  define echon()    Echon(__G)\n   void Echoff OF((__GPRO__ int f));\n   void Echon OF((__GPRO));\n#endif\n\n/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */\n#if (defined(UNZIP) && !defined(FUNZIP))\n#  ifdef HAVE_WORKING_GETCH\n#    define FGETCH(f)  getch()\n#  endif\n#  ifndef FGETCH\n     /* default for all systems where no getch()-like function is available */\n     int zgetch OF((__GPRO__ int f));\n#    define FGETCH(f)  zgetch(__G__ f)\n#  endif\n#endif /* UNZIP && !FUNZIP */\n\n#if (CRYPT && !defined(WINDLL))\n   char *getp OF((__GPRO__ ZCONST char *m, char *p, int n));\n#endif\n\n#else /* !(CRYPT || (UNZIP && !FUNZIP)) */\n\n/*\n * No need for non-echo keyboard/console input; provide dummy definitions.\n */\n#define echoff(f)\n#define echon()\n\n#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */\n\n#endif /* !__ttyio_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/ubz2err.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ubz2err.c\n\n  This file contains the \"fatal error\" callback routine required by the\n  \"minimal\" (silent, non-stdio) setup of the bzip2 compression library.\n\n  The fatal bzip2 error bail-out routine is provided in a separate code\n  module, so that it can be easily overridden when the UnZip package is\n  used as a static link library. One example is the WinDLL static library\n  usage for building a monolythic binary of the Windows application \"WiZ\"\n  that supports bzip2 both in compression and decompression operations.\n\n  Contains:  bz_internal_error()      (USE_BZIP2 only)\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __UBZ2ERR_C     /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifdef WINDLL\n#  ifdef POCKET_UNZIP\n#    include \"wince/intrface.h\"\n#  else\n#    include \"windll/windll.h\"\n#  endif\n#endif\n\n#ifdef USE_BZIP2\n\n/**********************************/\n/*  Function bz_internal_error()  */\n/**********************************/\n\n/* Call-back function for the bzip2 decompression code (compiled with\n * BZ_NO_STDIO), required to handle fatal internal bug-type errors of\n * the bzip2 library.\n */\nvoid bz_internal_error(bzerrcode)\n    int bzerrcode;\n{\n    GETGLOBALS();\n\n    Info(slide, 0x421, ((char *)slide,\n      \"error: internal fatal libbzip2 error number %d\\n\", bzerrcode));\n#ifdef WINDLL\n    longjmp(dll_error_return, 1);\n#else\n    DESTROYGLOBALS();\n    EXIT(PK_BADERR);\n#endif\n} /* end function bz_internal_error() */\n\n#endif /* USE_BZIP2 */\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Contents",
    "content": "Contents of the \"unix\" subdirectory for UnZip 6.0 and later:\n\n  Contents      this file\n  Makefile      makefile for UnZip for various architectures and OS's\n  configure     automatic build configuration script\n  unix.c        Unix-specific support routines\n  unxcfg.h      Unix-specific configuration settings\n  zipgrep       script to scan zip archive entries for lines matching a pattern\n  Packaging/    subdirectory containing SysV.4 (e.g., Solaris 2.x) package info\n\nType \"make\" or \"make help\" to get general compile instructions (beyond\nthose in the INSTALL file), or \"make list\" for a list of makefile targets.\nNote that there are some MS-DOS and cross-compilation targets thrown in\njust to make things more exciting.\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Packaging/README",
    "content": "Solaris packaging\n-----------------\n\nTo generate a Solaris package for Info-ZIP UnZip utilities,\nfirst see the top level INSTALL and README files.  Do a\n\"make solaris\", which will automatically build two Solaris\ninstallable package files for the package, IZunzip.\n\n   IZunzip     -- Solaris installable package in directory format.\n   IZunzip_$(arch).pkg -- Solaris installable package in \"stream\" format.\n\n   Where:  $(arch) := system architecture, currently i386, sparc, or ppc.\n                      (use \"uname -p\" to determine)\n\nThe \".pkg\" file is a single file datastream that can be compressed\nand/or ftp'd.  This is the recommended form, because all required\nfiles are resident in the archive, and it is easily distributed.\n\nTo install, simply:\n\n    1)  copy the package to the target system's /tmp directory.\n    2)  login or su to root\n    3)  pkgadd -d /tmp/IZunzip_$(arch).pkg\n    4)  add /opt/Info-ZIP/IZunzip/bin to PATH\n    5)  add /opt/Info-ZIP/IZunzip/man to MANPATH\n\nThis works for both SPARC and x86.\n\nOngoing maintenance:\n\n  Keep the files, \"prototype\" and \"pkginfo.in\" up to date.\n  Observe variable substitutions made by \"Makefile\".\n  See manpages for pkginfo(1), pkginfo(4), pkgmk(1), pkgproto(1)\n\nVariations:\n\n  If you wish the base directory to be set to something other than\n  /opt/Info-ZIP, change the setting BASEDIR in pkginfo.in and\n  re-run the make.\n\n\n-John Bush (John.Bush@East.Sun.COM)\n July 20, 1996\n\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Packaging/pkginfo.in",
    "content": "PKG=IZunzip\nNAME=Info-ZIP UnZip Utilities\nCATEGORY=application\nVENDOR=Info-ZIP\nEMAIL=Zip-Bugs@lists.wku.edu\nHOTLINE=Zip-Bugs@lists.wku.edu\nDESC=Copyrighted FREEWARE.  See README, WHERE, and LICENSE docs in pkg's doc dir.\nCLASSES=none\nBASEDIR=/opt/Info-ZIP\n#BASEDIR=/usr/local\nVERSION=\".VERSION.\"\nPSTAMP=\".PSTAMP.\"\nARCH=\".ARCH.\"\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Packaging/postinstall",
    "content": "#!/bin/sh\n#\n# Post installation script (simply inform installer about PATH etc)\n#\necho \" \"\necho \" \"\necho \"Installation is complete.  Now, you should add the following\"\necho \"(or equivalnet) commands to the appropriate initial user shell\"\necho \"scripts (such as .profile, .login, etc) -- \"\necho \" \"\necho \" For korn or bourne shell:\"\necho \"   PATH=\\${PATH}:${BASEDIR}/${PKG}/bin\"\necho \"   MANPATH=\\${MANPATH}:${BASEDIR}/${PKG}/man\"\necho \"   export PATH MANPATH\"\necho \" \"\necho \" For C shell:\"\necho \"   set path=(\\$path ${BASEDIR}/${PKG}/bin)\"\necho \"   setenv MANPATH \\$MANPATH:${BASEDIR}/${PKG}/man\"\necho \" \"\necho \" See the files under ${BASEDIR}/${PKG}/doc for more information.\"\necho \" \"\nexit 0\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Packaging/preinstall.in",
    "content": "#!/bin/sh\necho \" \"\necho \"REPORT ALL BUGS, PROBLEMS, AND ACCOLADES TO:\"\necho \" \"\necho \"         Zip-Bugs@lists.wku.edu\"\necho \" \"\necho \"Checking architecture platform for .ARCH. ...\"\narch=`uname -p`\nif [ \"arch_${arch}\" != \"arch_.ARCH.\" ]; then\n   echo \" \"\n   echo \"This product MUST be installed on a Solaris .ARCH. platform.\"\n   echo \"Your machine looks like it is a ${arch} platform.\"\n   echo \"Please install the version for the .ARCH. architecture.\"\n   echo \"Aborting the installation because of this. \"\n   echo \" \"\n   returncode=1\n else\n   echo \" \"\n   echo \"This product works on .ARCH., which you happen to have!\"\n   echo \" \"\n   returncode=0\nfi\necho \" \"\n/usr/bin/sleep 4\nexit ${returncode:-1}\n#\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/Packaging/prototype",
    "content": "d none $BASEDIR 0755 root bin\nd none $BASEDIR/$PKG 0755 root bin\nd none $PKG/bin 0755 root bin\nf none $PKG/bin/unzip=unzip 0755 root bin\nf none $PKG/bin/funzip=funzip 0755 root bin\nf none $PKG/bin/unzipsfx=unzipsfx 0755 root bin\nf none $PKG/bin/zipgrep=unix/zipgrep 0755 root bin\ns none $PKG/bin/zipinfo=unzip\nd none $PKG/doc 0755 root bin\nf none $PKG/doc/ZipPorts=proginfo/ZipPorts 0644 root bin\nf none $PKG/doc/CONTRIBS=proginfo/CONTRIBS 0644 root bin\nf none $PKG/doc/COPYING.OLD=COPYING.OLD 0644 root bin\nf none $PKG/doc/LICENSE=LICENSE 0644 root bin\nf none $PKG/doc/README=README 0644 root bin\nf none $PKG/doc/WHERE=WHERE 0644 root bin\nf none $PKG/doc/INSTALL=INSTALL 0644 root bin\nf none $PKG/doc/funzip.txt=funzip.txt 0644 root bin\nf none $PKG/doc/unzip.txt=unzip.txt 0644 root bin\nf none $PKG/doc/unzipsfx.txt=unzipsfx.txt 0644 root bin\nf none $PKG/doc/zipgrep.txt=zipgrep.txt 0644 root bin\nf none $PKG/doc/zipinfo.txt=zipinfo.txt 0644 root bin\nd none $PKG/man 0755 root bin\nd none $PKG/man/man1 0755 root bin\nf none $PKG/man/man1/funzip.1=man/funzip.1 0644 root bin\nf none $PKG/man/man1/unzip.1=man/unzip.1 0644 root bin\nf none $PKG/man/man1/unzipsfx.1=man/unzipsfx.1 0644 root bin\nf none $PKG/man/man1/zipgrep.1=man/zipgrep.1 0644 root bin\nf none $PKG/man/man1/zipinfo.1=man/zipinfo.1 0644 root bin\ni pkginfo\ni prototype\ni README\ni preinstall\ni postinstall\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/configure",
    "content": ":\n#!/bin/sh -x\n# The above : is necessary on some buggy systems.\n\n# configure: Guess values for system-dependent variables\n# Output the flag definitions to the file \"flags\".\n# Parameters: $1 = $(CC), $2 = $(CFLAGS), $3 = $(IZ_BZIP2)\n# To construct unzip automatically using this file, type\n# \"make -f unix/Makefile generic\".\n# If this fails, then type \"make list\" to get a list of special targets.\n\ntrap \"rm -f conftest* core a.out; exit 1\" 1 2 3 15\n\nCC=${1-cc}\nCFLAGS=${2}\nCFLAGSR=${CFLAGS}\nIZ_BZIP2=${3}\nCFLAGS=\"${CFLAGS} -I. -DUNIX\"\nLFLAGS1=\"\"\nLFLAGS2=\"-s\"\nLN=\"ln -s\"\n\nCFLAGS_OPT=''\nCFLAGS_BZ=''\nBZLF=''\n\necho \"Check C compiler operation\"\ncat > conftest.c << _EOF_\nint main()\n{\n   return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c\nstatus=$?\nif test $status -ne 0; then\n  echo ''\n  echo \"C compiler \\\"${CC}\\\" does not work as expected.\"\n  echo \"Failing command was: $CC $CFLAGS -c conftest.c\"\n  exit $status\nelse\n  echo '  Ok'\nfi\n\necho 'Check C compiler type (optimization options)'\n# Sun C?\ncat > conftest.c << _EOF_\nint main()\n{\n#ifndef __SUNPRO_C\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\nif test $? -eq 0; then\n  CFLAGS_OPT='-xO3'\n  echo \"  Sun C ($CFLAGS_OPT)\"\nelse\n  # Tru64 DEC/Compaq/HP C?\n  cat > conftest.c << _EOF_\nint main()\n{\n#ifndef __DECC\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n  $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n  if test $? -eq 0; then\n    CFLAGS_OPT='-O3'\n    echo \"  DEC C ($CFLAGS_OPT)\"\n  else\n    # HP-UX HP C?\n    cat > conftest.c << _EOF_\nint main()\n{\n#ifdef __GNUC__\n   bad code\n#endif\n#ifndef __hpux\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n    $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n    if test $? -eq 0; then\n      # HP-UX, not GCC.  Lame bundled or real ANSI compiler?\n      CFLAGS_OPT_TRY=\"+O3 +Onolimit\"\n      $CC $CFLAGS $CFLAGS_OPT_TRY -c conftest.c 2>&1 | \\\n       grep '(Bundled)' > /dev/null\n      if test $? -ne 0; then\n        CFLAGS_OPT=\"$CFLAGS_OPT_TRY\"\n        echo \"  HP-UX ANSI C ($CFLAGS_OPT)\"\n      else\n        echo '  HP-UX Bundled C (no opt)'\n      fi\n    else\n      # GNU C?\n      cat > conftest.c << _EOF_\nint main()\n{\n#ifndef __GNUC__\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n      $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n      if test $? -eq 0; then\n        CFLAGS_OPT='-O3'\n        echo \"  GNU C ($CFLAGS_OPT)\"\n\t# Special Mac OS X shared library \"ld\" option?\n        if test ` uname -s 2> /dev/null ` = 'Darwin'; then\n          lf='-Wl,-search_paths_first'\n          $CC $CFLAGS $lf conftest.c > /dev/null 2>/dev/null\n          if test $? -eq 0; then\n            BZLF=${lf}\n          fi\n          rm -f conftest\n        fi\n      else\n        CFLAGS_OPT='-O'\n        echo \"  Other-unknown C ($CFLAGS_OPT)\"\n      fi\n    fi\n  fi\nfi\n\n# optimization flags\nif test -n \"${CFLAGS_OPT}\"; then\n  CFLAGSR=\"${CFLAGSR} ${CFLAGS_OPT}\"\n  CFLAGS_BZ=\"${CFLAGS_BZ} ${CFLAGS_OPT}\"\nfi\n\necho Check for the C preprocessor\n# on SVR4, cc -E does not produce correct assembler files. Need /lib/cpp.\nCPP=\"${CC} -E\"\n# solaris as(1) needs -P, maybe others as well ?\n[ -f /usr/ccs/lib/cpp ] && CPP=\"/usr/ccs/lib/cpp -P\"\n[ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp\n[ -f /lib/cpp ] && CPP=/lib/cpp\n[ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp\n[ -f /xenix ] && CPP=\"${CC} -E\"\n[ -f /lynx.os ] && CPP=\"${CC} -E\"\n\necho \"#include <stdio.h>\" > conftest.c\n$CPP conftest.c >/dev/null 2>/dev/null || CPP=\"${CC} -E\"\n\necho Check if we can use asm code\nCRC32OA=\"\"\nif eval \"$CPP crc_i386.S > _crc_i386.s 2>/dev/null\"; then\n  if test ! -s _crc_i386.s || grep error < _crc_i386.s > /dev/null; then\n    :\n  elif eval \"$CC -c _crc_i386.s >/dev/null 2>/dev/null\" && [ -f _crc_i386.o ]; then\n    CFLAGSR=\"${CFLAGSR} -DASM_CRC\"\n    CRC32OA=\"crc_gcc.o\"\n    echo \"int foo() { return 0;}\" > conftest.c\n    $CC -c conftest.c >/dev/null 2>/dev/null\n    echo Check if compiler generates underlines\n    nm conftest.o | grep \"(^|[^_])foo\" >/dev/null 2>/dev/null\n    [ $? -eq 0 ] && CPP=\"${CPP} -DNO_UNDERLINE\"\n  fi\nfi\nrm -f _crc_i386.s _crc_i386.o\n\n# ANSI options for compilers that don't have __STDC__ defined by default\n# Currently HPUX, pyramid, Dynix, AIX, OSF/1 and ultrix\n\necho Check for ANSI options\ncat > conftest.c << _EOF_\nint main()\n{\n#ifndef __STDC__\n   forget it\n#endif\n   return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  for OPT in \"-Aa -D_HPUX_SOURCE\" -Xa -qlanglvl=ansi -std1 -std\n  do\n    $CC $CFLAGS $OPT -c conftest.c > /dev/null 2>/dev/null\n    [ $? -eq 0 ] && CFLAGSR=\"${CFLAGSR} ${OPT}\" && break\n  done\nfi\n\necho Check for prototypes\necho \"int main(int argc, char *argv[]) { return 0; }\" > conftest.c\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_PROTO\"\n\n# const check currently handles mips cc and non ANSI compilers.\n# does it need more ?\necho Check the handling of const\ncat > conftest.c << _EOF_\ntypedef int charset[2];\nint main()\n{\n  const charset x;\n  const char *foo;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_CONST\"\n\necho Check for time_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\n#include <time.h>\nint main()\n{\n  time_t t;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_TIME_T\"\n\necho Check for size_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\nint main()\n{\n  size_t s;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_SIZE_T\"\n\necho Check for off_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\nint main()\n{\n  off_t s;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_OFF_T\"\n\n# Added 11/4/2003 EG\n# Revised 8/12/04 EG\n# Now we set the 64-bit file environment and check the size of off_t\necho Check for Large File Support\ncat > conftest.c << _EOF_\n# define _LARGEFILE_SOURCE       /* some OSes need this for fseeko */\n# define _LARGEFILE64_SOURCE\n# define _FILE_OFFSET_BITS 64       /* select default interface as 64 bit */\n# define _LARGE_FILES        /* some OSes need this for 64-bit off_t */\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n#include <stdio.h>\nint main()\n{\n  off_t offset;\n  struct stat s;\n  /* see if have 64-bit off_t */\n  if (sizeof(offset) < 8)\n    return 1;\n  printf(\"  off_t is %d bytes\\n\", sizeof(off_t));\n  /* see if have 64-bit stat */\n  if (sizeof(s.st_size) < 8) {\n    printf(\"  s.st_size is %d bytes\\n\", sizeof(s.st_size));\n    return 2;\n  }\n  return 3;\n}\n_EOF_\n# compile it\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  echo -- no Large File Support\nelse\n# run it\n  ./conftest\n  r=$?\n  if [ $r -eq 1 ]; then\n    echo -- no Large File Support - no 64-bit off_t\n  elif [ $r -eq 2 ]; then\n    echo -- no Large File Support - no 64-bit stat\n  elif [ $r -eq 3 ]; then\n    echo -- yes we have Large File Support!\n    CFLAGSR=\"${CFLAGSR} -DLARGE_FILE_SUPPORT\"\n  else\n    echo -- no Large File Support - conftest returned $r\n  fi\nfi\n\n# Added 11/24/2005 EG\n# Check for wide char for Unicode support\necho Check for wide char support\ncat > conftest.c << _EOF_\n#include <stdlib.h>\n#include <stdio.h>\n#include <wchar.h>\nint main()\n{\n  size_t wsize;\n  wchar_t *wide_string;\n\n  if ((wide_string = (wchar_t *)malloc(4 * sizeof(wchar_t))) == NULL) {\n    return 0;\n  }\n  /* get wide string */\n  wsize = mbstowcs(wide_string, \"foo\", 3);\n  wide_string[wsize] = (wchar_t) NULL;\n#ifndef __STDC_ISO_10646__\n  return 1;\n#else\n  printf(\"  __STDC_ISO_10646__ = %d\\n\", __STDC_ISO_10646__);\n  return 2;\n#endif\n}\n_EOF_\n# compile it\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  echo \"-- no Unicode (wchar_t) support\"\nelse\n# have wide char support\n# run it\n  ./conftest\n  r=$?\n  if [ $r -eq 0 ]; then\n    echo -- no Unicode wchar_t support - wchar_t allocation error\n  elif [ $r -eq 1 ]; then\n    echo -- no Unicode support - wchar_t encoding unspecified\n  elif [ $r -eq 2 ]; then\n    echo -- have wchar_t with known UCS encoding - enabling Unicode support!\n    CFLAGSR=\"${CFLAGSR} -DUNICODE_SUPPORT -DUNICODE_WCHAR\"\n  else\n    echo \"-- no Unicode (wchar_t) support - conftest returned $r\"\n  fi\nfi\n\necho \"Check for setlocale support (needed for UNICODE Native check)\"\ncat > conftest.c << _EOF_\n#include <locale.h>\nint main()\n{\n  char *loc = setlocale(LC_CTYPE, \"\");\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\nif [ $? -eq 0 ]; then\n  echo \"-- have setlocale, can check for charset type\"\n  echo \"--  - enabling UTF8-native support!\"\n  CFLAGSR=\"${CFLAGSR} -DUNICODE_SUPPORT -DUTF8_MAYBE_NATIVE\"\nelse\n  echo \"-- no Unicode (UTF-8 native) support!\"\n  CFLAGSR=\"${CFLAGSR} -DNO_SETLOCALE\"\nfi\n\n# from configure 2.4i (Onno) 12/5/04\necho Check for gcc no-builtin flag\n# -fno-builtin since version 2\ncat > conftest.c << _EOF_\nint main()\n{\n#if __GNUC__ >= 2\n   return 0;\n#else\n   forget it\n#endif\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -eq 0 ] && BFLAG=\"-fno-builtin\"\n\n# Check for missing functions\n# add NO_'function_name' to flags if missing\nfor func in fchmod fchown lchown nl_langinfo\ndo\n  echo Check for $func\n  echo \"int main(){ $func(); return 0; }\" > conftest.c\n  $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null\n  [ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`\"\ndone\n\n# Check (seriously) for a working lchmod.\necho 'Check for lchmod'\ntemp_file=\"/tmp/unzip_test_$$\"\ntemp_link=\"link_$$\"\n( echo '#include <unistd.h>' ; \\\n  echo \"int main() { lchmod(\\\"${temp_file}\\\", 0666); }\" \\\n) > conftest.c\nln -s \"${temp_link}\" \"${temp_file}\" && \\\n $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null && \\\n ./conftest\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_LCHMOD\"\nrm -f \"${temp_file}\"\n\necho Check for memset\necho \"int main(){ char k; memset(&k,0,0); return 0; }\" > conftest.c\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DZMEM\"\n\necho Check for errno declaration\ncat > conftest.c << _EOF_\n#include <errno.h>\nmain()\n{\n  errno = 0;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_ERRNO\"\n\necho Check for directory libraries\ncat > conftest.c << _EOF_\nint main() { return closedir(opendir(\".\")); }\n_EOF_\n\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  OPT=\"\"\n  for lib in ndir dir ucb bsd BSD PW x dirent\n  do\n    $CC -o conftest conftest.c -l$lib >/dev/null 2>/dev/null\n    [ $? -eq 0 ] && OPT=-l$lib && break\n  done\n  if [ ${OPT} ]; then\n    LFLAGS2=\"${LFLAGS2} ${OPT}\"\n  else\n    CFLAGSR=\"${CFLAGSR} -DNO_DIR\"\n  fi\nfi\n\n# Dynix/ptx 1.3 needed this\necho Check for readlink\necho \"int main(){ return readlink(); }\" > conftest.c\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  $CC -o conftest conftest.c -lseq >/dev/null 2>/dev/null\n  [ $? -eq 0 ] && LFLAGS2=\"${LFLAGS2} -lseq\"\nfi\n\necho Check for directory include file\nOPT=\"\"\nfor inc in dirent.h sys/ndir.h ndir.h sys/dir.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c > /dev/null 2>/dev/null\n   [ $? -eq 0 ] && OPT=\"-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`\" && break\ndone\nCFLAGSR=\"${CFLAGSR} ${OPT}\"\n\necho Check for non existent include files\nfor inc in stdlib.h stddef.h unistd.h fcntl.h string.h langinfo.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c >/dev/null 2>/dev/null\n   [ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_`echo $inc | tr '[a-z]./' '[A-Z]__'`\"\ndone\n\necho Check for term I/O include file\nOPT=\"\"\nfor inc in termios.h termio.h sgtty.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c > /dev/null 2>/dev/null\n   [ $? -eq 0 ] && OPT=\"-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`\" && break\ndone\nCFLAGSR=\"${CFLAGSR} ${OPT}\"\n\necho Check for MBCS include files\nOPT=\"\"\nfor inc in mbstring.h mbctype.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c > /dev/null 2>/dev/null\n   [ $? -eq 0 ] && OPT=\"-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`\" && break\ndone\nCFLAGSR=\"${CFLAGSR} ${OPT}\"\n\n# Check for MBCS support\necho Check for MBCS support\ncat > conftest.c << _EOF_\n#include <stdlib.h>\n#include <stdio.h>\n#include <wchar.h>\n#ifdef HAVE_MBSTRING_H\n#  include <mbstring.h>\n#endif\nint main()\n{\n  char *tst;\n  tst = \"Hallo\";\n  return mblen(tst, MB_CUR_MAX);\n}\n_EOF_\n# compile it\n$CC ${CFLAGS} ${CFLAGSR} -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  echo \"-- no MBCS support\"\n  CFLAGSR=\"${CFLAGSR} -DNO_MBCS\"\nelse\n#\n  echo \"-- have MBCS support\"\n  CFLAGSR=\"${CFLAGSR} -D_MBCS\"\n# check for library-supplied functions\n# add FUNCTION_NAME='function_name' to flags if found\n  for func in mbschr mbsrchr\n  do\n    echo Check for MBCS $func\n    echo \"int main() { $func(); return 0; }\" > conftest.c\n    $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null\n    [ $? -eq 0 ] && CFLAGSR=\"${CFLAGSR} -D`echo $func | tr '[a-z]' '[A-Z]'`=$func\"\n  done\nfi\n\n# needed for AIX (and others ?) when mmap is used\necho Check for valloc\ncat > conftest.c << _EOF_\nmain()\n{\n#ifdef MMAP\n    valloc();\n#endif\n}\n_EOF_\n$CC ${CFLAGS} -c conftest.c > /dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGSR=\"${CFLAGSR} -DNO_VALLOC\"\n\necho Check for /usr/local/bin and /usr/local/man\nBINDIR=$HOME/bin\n[ -d /usr/local/bin ] && BINDIR=/usr/local/bin\n\nMANDIR=manl\n[ -d /usr/man/manl ]       && MANDIR=/usr/man/manl\n[ -d /usr/local/man/manl ] && MANDIR=/usr/local/man/manl\n[ -d /usr/local/man/man1 ] && MANDIR=/usr/local/man/man1\n\necho Checking for OS specialties\nif [ -f /usr/bin/hostinfo ]; then\n  if /usr/bin/hostinfo | grep NeXT > /dev/null; then\n    CFLAGSR=\"${CFLAGSR} -posix\"\n    LFLAGS1=\"${LFLAGS1} -posix -object\"\n  fi\n# XXX ATT6300, Cray\nelif [ -f /xenix ]; then\n  if uname -p | grep 286 > /dev/null; then\n    CFLAGSR=\"${CFLAGSR} -LARGE -Mel2 -DMEDIUM_MEM -DWSIZE=16384 -DNO_VOID\"\n    LFLAGS1=\"${LFLAGS1} -LARGE -Mel2\"\n  fi\nelif uname -X >/dev/null 2>/dev/null; then\n# SCO shared library check\n  echo \"int main() { return 0;}\" > conftest.c\n  $CC -o conftest conftest.c -lc_s -nointl >/dev/null 2> /dev/null\n  [ $? -eq 0 ] && LFLAGS2=\"-lc_s -nointl\"\nelse\n  SYSTEM=`uname -s 2>/dev/null` || SYSTEM=\"unknown\"\n  echo \"int main() { return 0;}\" > conftest.c\n  case $SYSTEM in\n     OSF1|ULTRIX)\n        echo Check for -Olimit option\n        $CC ${CFLAGS} -Olimit 1000 -o conftest conftest.c >/dev/null 2>/dev/null\n        [ $? -eq 0 ] && CFLAGSR=\"${CFLAGSR} -Olimit 1000\"\n        ;;\n###     HP-UX)\n###        echo Check for +Onolimit option\n###        $CC ${CFLAGS} +Onolimit -o conftest conftest.c >/dev/null 2>/dev/null\n###        [ $? -eq 0 ] && CFLAGSR=\"${CFLAGSR} +Onolimit\"\n###        ;;\n###     SunOS)\n###        CFLAGSR=\"${CFLAGSR} -D_FILE_OFFSET_BITS=64\"\n###        ;;\n  esac\nfi\n\necho Check for symbolic links\nln -s /dev/null null > /dev/null 2>/dev/null || LN=ln\n\nrm -f a.out conftest.c conftest.o conftest null\n\n\n# bzip2\n\necho \"Check bzip2 support\"\nD_USE_BZ2=\"\"\nLIBBZ2=\"\"\nL_BZ2=\"\"\nCC_BZ=\"${CC}\"\n\nif test -n \"${IZ_BZIP2}\" -a \"${IZ_BZIP2}\" != \"bzip2\" ; then\n  echo \"  Check for bzip2 compiled library in IZ_BZIP2 (${IZ_BZIP2})\"\n  if test -f \"${IZ_BZIP2}/libbz2.a\"; then\n#\n#   A bzip2 library built with BZ_NO_STDIO should have an\n#   unresolved external, \"bz_internal_error\".  The default,\n#   full-function library will not mention it.\n#\n    nm ${IZ_BZIP2}/libbz2.a | grep bz_internal_error > /dev/null\n    if test $? -eq 0; then\n      echo \"    Found bzip2 BZ_NO_STDIO library, ${IZ_BZIP2}/libbz2.a\"\n      if test -f \"${IZ_BZIP2}/bzlib.h\"; then\n        LIBBZ2=\"${IZ_BZIP2}/libbz2.a\"\n        D_USE_BZ2=\"-DUSE_BZIP2\"\n        L_BZ2=\"${BZLF} -lbz2\"\n        echo \"-- Found bzip2 library - linking in bzip2\"\n      else\n        echo \"    ${IZ_BZIP2}/bzlib.h not found\"\n        echo \"-- Since IZ_BZIP2 defined (!= \\\"bzip2\\\"),\"\n        echo \"-- => skipping OS and bzip2 dir checks.\"\n        echo \"-- NO bzip2 support !\"\n      fi\n    else\n      echo \"    Found bzip2 library, ${IZ_BZIP2}/libbz2.a,\"\n      echo \"      but library not compiled with BZ_NO_STDIO.\"\n      echo \"    ERROR: This (default) variant of bzip2 library is NOT\"\n      echo \"      supported with UnZip because of its incompatible\"\n      echo \"      error handling!\"\n      echo \"      Please see the UnZip installation instructions in\"\n      echo \"      the INSTALL text file.\"\n      echo \"    Skipping bzip2 support...\"\n    fi\n  else\n    echo \"    ${IZ_BZIP2}/libbz2.a not found\"\n    echo \"-- Since IZ_BZIP2 defined (!= \\\"bzip2\\\"),\"\n    echo \"-- => skipping OS and bzip2 dir checks.\"\n    echo \"-- NO bzip2 support !\"\n  fi\nelse\n  echo \"  Check for bzip2 sources in unzip's bzip2 subdirectory\"\n  if test -f \"${IZ_BZIP2}/bzlib.c\" -a -f \"${IZ_BZIP2}/bzlib.h\"; then\n    echo \"-- Found bzip2 source in ${IZ_BZIP2}/ directory\"\n    echo \"-- Will try to build bzip2 library from source and link in\"\n    LIBBZ2=\"${IZ_BZIP2}/libbz2.a\"\n    D_USE_BZ2=\"-DUSE_BZIP2\"\n    L_BZ2=\"${BZLF} -lbz2\"\n  else\n    echo \"-- bzip2 sources not found - no bzip2 support\"\n  fi\nfi\n\n\necho CC=\\\"${CC}\\\" CF=\\\"${CFLAGSR} ${D_USE_BZ2}\\\" CRCA_O=\\\"${CRC32OA}\\\" \\\n       AS=\\\"${CC} -c\\\" LFLAGS1=\\\"${LFLAGS1}\\\" LF2=\\\"${LFLAGS2}\\\" \\\n       CC_BZ=\\\"${CC_BZ}\\\" CFLAGS_BZ=\\\"${CFLAGS_BZ}\\\" \\\n       IZ_BZIP2=\\\"${IZ_BZIP2}\\\" D_USE_BZ2=\\\"${D_USE_BZ2}\\\" \\\n       L_BZ2=\\\"${L_BZ2}\\\" LIBBZ2=\\\"${LIBBZ2}\\\"  > flags\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/unix.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unix.c\n\n  Unix-specific routines for use with Info-ZIP's UnZip 5.41 and later.\n\n  Contains:  readdir()\n             do_wild()           <-- generic enough to put in fileio.c?\n             mapattr()\n             mapname()\n             checkdir()\n             mkdir()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             stamp_file()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#ifdef SCO_XENIX\n#  define SYSNDIR\n#else  /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */\n#  if defined(__convexc__) || defined(SYSV) || defined(CRAY) || defined(BSD4_4)\n#    define DIRENT\n#  endif\n#endif\n#if defined(_AIX) || defined(__mpexl)\n#  define DIRENT\n#endif\n#ifdef COHERENT\n#  if defined(_I386) || (defined(__COHERENT__) && (__COHERENT__ >= 0x420))\n#    define DIRENT\n#  endif\n#endif\n\n#ifdef _POSIX_VERSION\n#  ifndef DIRENT\n#    define DIRENT\n#  endif\n#endif\n\n#ifdef DIRENT\n#  include <dirent.h>\n#else\n#  ifdef SYSV\n#    ifdef SYSNDIR\n#      include <sys/ndir.h>\n#    else\n#      include <ndir.h>\n#    endif\n#  else /* !SYSV */\n#    ifndef NO_SYSDIR\n#      include <sys/dir.h>\n#    endif\n#  endif /* ?SYSV */\n#  ifndef dirent\n#    define dirent direct\n#  endif\n#endif /* ?DIRENT */\n\n#ifdef SET_DIR_ATTRIB\ntypedef struct uxdirattr {      /* struct for holding unix style directory */\n    struct uxdirattr *next;     /*  info until can be sorted and set at end */\n    char *fn;                   /* filename of directory */\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } u;\n    unsigned perms;             /* same as min_info.file_attr */\n    int have_uidgid;            /* flag */\n    ulg uidgid[2];\n    char fnbuf[1];              /* buffer stub for directory name */\n} uxdirattr;\n#define UxAtt(d)  ((uxdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\n/* static int created_dir;      */      /* used in mapname(), checkdir() */\n/* static int renamed_fullpath; */      /* ditto */\n\nstatic unsigned filtattr OF((__GPRO__ unsigned perms));\n\n\n/*****************************/\n/* Strings used multiple     */\n/* times in unix.c           */\n/*****************************/\n\n#ifndef MTS\n/* messages of code for setting file/directory attributes */\nstatic ZCONST char CannotSetItemUidGid[] =\n  \"warning:  cannot set UID %lu and/or GID %lu for %s\\n          %s\\n\";\nstatic ZCONST char CannotSetUidGid[] =\n  \" (warning) cannot set UID %lu and/or GID %lu\\n          %s\";\nstatic ZCONST char CannotSetItemTimestamps[] =\n  \"warning:  cannot set modif./access times for %s\\n          %s\\n\";\nstatic ZCONST char CannotSetTimestamps[] =\n  \" (warning) cannot set modif./access times\\n          %s\";\n#endif /* !MTS */\n\n\n#ifndef SFX\n#ifdef NO_DIR                  /* for AT&T 3B1 */\n\n#define opendir(path) fopen(path,\"r\")\n#define closedir(dir) fclose(dir)\ntypedef FILE DIR;\ntypedef struct zdir {\n    FILE *dirhandle;\n    struct dirent *entry;\n} DIR\nDIR *opendir OF((ZCONST char *dirspec));\nvoid closedir OF((DIR *dirp));\nstruct dirent *readdir OF((DIR *dirp));\n\nDIR *opendir(dirspec)\n    ZCONST char *dirspec;\n{\n    DIR *dirp;\n\n    if ((dirp = malloc(sizeof(DIR)) != NULL) {\n        if ((dirp->dirhandle = fopen(dirspec, \"r\")) == NULL) {\n            free(dirp);\n            dirp = NULL;\n        }\n    }\n    return dirp;\n}\n\nvoid closedir(dirp)\n    DIR *dirp;\n{\n    fclose(dirp->dirhandle);\n    free(dirp);\n}\n\n/*\n *  Apparently originally by Rich Salz.\n *  Cleaned up and modified by James W. Birdsall.\n */\nstruct dirent *readdir(dirp)\n    DIR *dirp;\n{\n\n    if (dirp == NULL)\n        return NULL;\n\n    for (;;)\n        if (fread(&(dirp->entry), sizeof (struct dirent), 1,\n                  dirp->dirhandle) == 0)\n            return (struct dirent *)NULL;\n        else if ((dirp->entry).d_ino)\n            return &(dirp->entry);\n\n} /* end function readdir() */\n\n#endif /* NO_DIR */\n\n\n/**********************/\n/* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */\n/**********************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in unxcfg.h:\n    static DIR *wild_dir = (DIR *)NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n*/\n    struct dirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.notfirstcall) {  /* first call:  must initialize everything */\n        G.notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(G.matchname, wildspec, FILNAMSIZ);\n            G.matchname[FILNAMSIZ-1] = '\\0';\n            G.have_dirname = FALSE;\n            G.wild_dir = NULL;\n            return G.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) {\n            G.dirname = \".\";\n            G.dirnamelen = 1;\n            G.have_dirname = FALSE;\n            G.wildname = wildspec;\n        } else {\n            ++G.wildname;     /* point at character after '/' */\n            G.dirnamelen = G.wildname - wildspec;\n            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == (char *)NULL) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(G.matchname, wildspec, FILNAMSIZ);\n                G.matchname[FILNAMSIZ-1] = '\\0';\n                return G.matchname; /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.dirname, wildspec, G.dirnamelen);\n            G.dirname[G.dirnamelen] = '\\0';   /* terminate for strcpy below */\n            G.have_dirname = TRUE;\n        }\n\n        if ((G.wild_dir = (zvoid *)opendir(G.dirname)) != (zvoid *)NULL) {\n            while ((file = readdir((DIR *)G.wild_dir)) !=\n                   (struct dirent *)NULL) {\n                Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                if (file->d_name[0] == '.' && G.wildname[0] != '.')\n                    continue; /* Unix:  '*' and '?' do not match leading dot */\n                if (match(file->d_name, G.wildname, 0 WISEP) &&/*0=case sens.*/\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(file->d_name, \".\") && strcmp(file->d_name, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    if (G.have_dirname) {\n                        strcpy(G.matchname, G.dirname);\n                        strcpy(G.matchname+G.dirnamelen, file->d_name);\n                    } else\n                        strcpy(G.matchname, file->d_name);\n                    return G.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            closedir((DIR *)G.wild_dir);\n            G.wild_dir = (zvoid *)NULL;\n        }\n        Trace((stderr, \"do_wild:  opendir(%s) returns NULL\\n\",\n          FnFilter1(G.dirname)));\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.matchname, wildspec, FILNAMSIZ);\n        G.matchname[FILNAMSIZ-1] = '\\0';\n        return G.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if ((DIR *)G.wild_dir == (DIR *)NULL) {\n        G.notfirstcall = FALSE; /* nothing left--reset for new wildspec */\n        if (G.have_dirname)\n            free(G.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    while ((file = readdir((DIR *)G.wild_dir)) != (struct dirent *)NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        if (file->d_name[0] == '.' && G.wildname[0] != '.')\n            continue;   /* Unix:  '*' and '?' do not match leading dot */\n        if (match(file->d_name, G.wildname, 0 WISEP)) { /* 0 == case sens. */\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            if (G.have_dirname) {\n                /* strcpy(G.matchname, G.dirname); */\n                strcpy(G.matchname+G.dirnamelen, file->d_name);\n            } else\n                strcpy(G.matchname, file->d_name);\n            return G.matchname;\n        }\n    }\n\n    closedir((DIR *)G.wild_dir);  /* at least one entry read; nothing left */\n    G.wild_dir = (zvoid *)NULL;\n    G.notfirstcall = FALSE;       /* reset for new wildspec */\n    if (G.have_dirname)\n        free(G.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n\n#ifndef S_ISUID\n# define S_ISUID        0004000 /* set user id on execution */\n#endif\n#ifndef S_ISGID\n# define S_ISGID        0002000 /* set group id on execution */\n#endif\n#ifndef S_ISVTX\n# define S_ISVTX        0001000 /* save swapped text even after use */\n#endif\n\n/************************/\n/*  Function filtattr() */\n/************************/\n/* This is used to clear or keep the SUID and SGID bits on file permissions.\n * It's possible that a file in an archive could have one of these bits set\n * and, unknown to the person unzipping, could allow others to execute the\n * file as the user or group.  The new option -K bypasses this check.\n */\n\nstatic unsigned filtattr(__G__ perms)\n    __GDEF\n    unsigned perms;\n{\n    /* keep setuid/setgid/tacky perms? */\n    if (!uO.K_flag)\n        perms &= ~(S_ISUID | S_ISGID | S_ISVTX);\n\n    return (0xffff & perms);\n} /* end function filtattr() */\n\n\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\nint mapattr(__G)\n    __GDEF\n{\n    int r;\n    ulg tmp = G.crec.external_file_attributes;\n\n    G.pInfo->file_attr = 0;\n    /* initialized to 0 for check in \"default\" branch below... */\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>17 & 7);   /* Amiga RWE bits */\n            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);\n            break;\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n        case UNIX_:\n        case VMS_:\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            r = FALSE;\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            if (G.pInfo->file_attr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some extra field.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap of the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            G.pInfo->file_attr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n            }\n            if (!r) {\n#ifdef SYMLINKS\n                /* Check if the file is a (POSIX-compatible) symbolic link.\n                 * We restrict symlink support to those \"made-by\" hosts that\n                 * are known to support symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   SYMLINK_HOST(G.pInfo->hostnum);\n#endif\n                return 0;\n            }\n            /* fall through! */\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n            /* PKWARE's PKZip for Unix marks entries as FS_FAT_, but stores the\n             * Unix attributes in the upper 16 bits of the external attributes\n             * field, just like Info-ZIP's Zip for Unix.  We try to use that\n             * value, after a check for consistency with the MSDOS attribute\n             * bits (see below).\n             */\n            G.pInfo->file_attr = (unsigned)(tmp >> 16);\n            /* fall through! */\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            /* Ensure that DOS subdir bit is set when the entry's name ends\n             * in a '/'.  Some third-party Zip programs fail to set the subdir\n             * bit for directory entries.\n             */\n            if ((tmp & 0x10) == 0) {\n                extent fnlen = strlen(G.filename);\n                if (fnlen > 0 && G.filename[fnlen-1] == '/')\n                    tmp |= 0x10;\n            }\n            /* read-only bit --> write perms; subdir bit --> dir exec bit */\n            tmp = !(tmp & 1) << 1  |  (tmp & 0x10) >> 4;\n            if ((G.pInfo->file_attr & 0700) == (unsigned)(0400 | tmp<<6)) {\n                /* keep previous G.pInfo->file_attr setting, when its \"owner\"\n                 * part appears to be consistent with DOS attribute flags!\n                 */\n#ifdef SYMLINKS\n                /* Entries \"made by FS_FAT_\" could have been zipped on a\n                 * system that supports POSIX-style symbolic links.\n                 */\n                G.pInfo->symlink = S_ISLNK(G.pInfo->file_attr) &&\n                                   (G.pInfo->hostnum == FS_FAT_);\n#endif\n                return 0;\n            }\n            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    /* for originating systems with no concept of \"group,\" \"other,\" \"system\": */\n    umask( (int)(tmp=umask(0)) );    /* apply mask to expanded r/w(/x) perms */\n    G.pInfo->file_attr &= ~tmp;\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];      /* path-component buffer */\n    char *pp, *cp=(char *)NULL;    /* character pointers */\n    char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;       /* is set when skipping \"../\" pathcomp */\n    int error = MPN_OK;\n    register unsigned workch;      /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels in Unix */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.created_dir = FALSE;      /* not yet */\n\n    /* user gave full pathname:  don't prepend rootpath */\n    G.renamed_fullpath = (renamed && (*G.filename == '/'));\n\n    if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)\n        return MPN_NOMEM;       /* initialize path buffer, unless no memory */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (uO.jflag)               /* junking directories */\n        cp = (char *)strrchr(G.filename, '/');\n    if (cp == (char *)NULL)     /* no '/' or not junking dirs */\n        cp = G.filename;        /* point to internal zipfile-member pathname */\n    else\n        ++cp;                   /* point to start of last component of path */\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    while ((workch = (uch)*cp++) != 0) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n#ifdef __CYGWIN__   /* Cygwin runs on Win32, apply FAT/NTFS filename rules */\n            case ':':         /* drive spec not stored, so no colon allowed */\n            case '\\\\':        /* '\\\\' may come as normal filename char (not */\n            case '<':         /*  dir sep char!) from unix-like file system */\n            case '>':         /* no redirection symbols allowed either */\n            case '|':         /* no pipe signs allowed */\n            case '\"':         /* no double quotes allowed */\n            case '?':         /* no wildcards allowed */\n            case '*':\n                *pp++ = '_';  /* these rules apply equally to FAT and NTFS */\n                break;\n#endif\n\n            case ';':             /* VMS version (or DEC-20 attrib?) */\n                lastsemi = pp;\n                *pp++ = ';';      /* keep for now; remove VMS \";##\" */\n                break;            /*  later, if requested */\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n#ifdef MTS\n            case ' ':             /* change spaces to underscore under */\n                *pp++ = '_';      /*  MTS; leave as spaces under Unix */\n                break;\n#endif\n\n            default:\n                /* disable control character filter when requested,\n                 * else allow 8-bit characters (e.g. UTF-8) in filenames:\n                 */\n                if (uO.cflxflag ||\n                    (isprint(workch) || (128 <= workch && workch <= 254)))\n                    *pp++ = (char)workch;\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (G.filename[strlen(G.filename) - 1] == '/') {\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n#ifndef NO_CHMOD\n            /* Filter out security-relevant attributes bits. */\n            G.pInfo->file_attr = filtattr(__G__ G.pInfo->file_attr);\n            /* When extracting non-UNIX directories or when extracting\n             * without UID/GID restoration or SGID preservation, any\n             * SGID flag inherited from the parent directory should be\n             * maintained to allow files extracted into this new folder\n             * to inherit the GID setting from the parent directory.\n             */\n            if (G.pInfo->hostnum != UNIX_ || !(uO.X_flag || uO.K_flag)) {\n                /* preserve SGID bit when inherited from parent dir */\n                if (!SSTAT(G.filename, &G.statbuf)) {\n                    G.pInfo->file_attr |= G.statbuf.st_mode & S_ISGID;\n                } else {\n                    perror(\"Could not read directory attributes\");\n                }\n            }\n\n            /* set approx. dir perms (make sure can still read/write in dir) */\n            if (chmod(G.filename, G.pInfo->file_attr | 0700))\n                perror(\"chmod (directory attributes) error\");\n#endif\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \";###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n    /* On UNIX (and compatible systems), \".\" and \"..\" are reserved for\n     * directory navigation and cannot be used as regular file names.\n     * These reserved one-dot and two-dot names are mapped to \"_\" and \"__\".\n     */\n    if (strcmp(pathcomp, \".\") == 0)\n        *pathcomp = '_';\n    else if (strcmp(pathcomp, \"..\") == 0)\n        strcpy(pathcomp, \"__\");\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n#if 0  /*========== NOTES ==========*/\n\n  extract-to dir:      a:path/\n  buildpath:           path1/path2/ ...   (NULL-terminated)\n  pathcomp:                filename\n\n  mapname():\n    loop over chars in zipfile member name\n      checkdir(path component, COMPONENT | CREATEDIR) --> map as required?\n        (d:/tmp/unzip/)                    (disk:[tmp.unzip.)\n        (d:/tmp/unzip/jj/)                 (disk:[tmp.unzip.jj.)\n        (d:/tmp/unzip/jj/temp/)            (disk:[tmp.unzip.jj.temp.)\n    finally add filename itself and check for existence? (could use with rename)\n        (d:/tmp/unzip/jj/temp/msg.outdir)  (disk:[tmp.unzip.jj.temp]msg.outdir)\n    checkdir(name, GETPATH)     -->  copy path to name and free space\n\n#endif /* 0 */\n\n\n\n\n/***********************/\n/* Function checkdir() */\n/***********************/\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n /* static int rootlen = 0; */  /* length of rootpath */\n /* static char *rootpath;  */  /* user's \"extract-to\" directory */\n /* static char *buildpath; */  /* full path (so far) to extracted file */\n /* static char *end;       */  /* pointer to end of buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        int too_long = FALSE;\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0')\n            ++G.end;\n#ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */\n        if ((G.end-old_end) > FILENAME_MAX)  /* GRR:  proper constant? */\n            *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check end-buildpath after each append, set warning variable if\n         * within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check: need to append '/', at least one-char name, '\\0' */\n        if ((G.end-G.buildpath) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n        if (SSTAT(G.buildpath, &G.statbuf)) {   /* path doesn't exist */\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpath);\n                return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */\n            }\n            if (too_long) {\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpath)));\n                free(G.buildpath);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (mkdir(G.buildpath, 0777) == -1) {   /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpath),\n                  strerror(errno),\n                  FnFilter1(G.filename)));\n                free(G.buildpath);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(G.buildpath), FnFilter1(G.filename)));\n            free(G.buildpath);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\", FnFilter1(G.buildpath)));\n            free(G.buildpath);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.end++ = '/';\n        *G.end = '\\0';\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full path to the string pointed at by pathcomp, and free\n    G.buildpath.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        strcpy(pathcomp, G.buildpath);\n        Trace((stderr, \"getting and freeing path [%s]\\n\",\n          FnFilter1(pathcomp)));\n        free(G.buildpath);\n        G.buildpath = G.end = (char *)NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n#ifdef SHORT_NAMES\n        char *old_end = end;\n#endif\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.end = *pathcomp++) != '\\0') {\n            ++G.end;\n#ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */\n            if ((G.end-old_end) > FILENAME_MAX)    /* GRR:  proper constant? */\n                *(G.end = old_end + FILENAME_MAX) = '\\0';\n#endif\n            if ((G.end-G.buildpath) >= FILNAMSIZ) {\n                *--G.end = '\\0';\n                Info(slide, 0x201, ((char *)slide,\n                  \"checkdir warning:  path too long; truncating\\n\\\n                   %s\\n                -> %s\\n\",\n                  FnFilter1(G.filename), FnFilter2(G.buildpath)));\n                return MPN_INF_TRUNC;   /* filename truncated */\n            }\n        }\n        Trace((stderr, \"buildpath now = [%s]\\n\", FnFilter1(G.buildpath)));\n        /* could check for existence here, prompt for new name... */\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n/* GRR:  for VMS and TOPS-20, add up to 13 to strlen */\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpath to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+\n                                          (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.buildpath = (char *)malloc(strlen(G.filename)+G.rootlen+1))\n#endif\n            == (char *)NULL)\n            return MPN_NOMEM;\n        if ((G.rootlen > 0) && !G.renamed_fullpath) {\n            strcpy(G.buildpath, G.rootpath);\n            G.end = G.buildpath + G.rootlen;\n        } else {\n            *G.buildpath = '\\0';\n            G.end = G.buildpath;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpath)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if\n    necessary; else assume it's a zipfile member and return.  This path\n    segment gets used in extracting all members from every zipfile specified\n    on the command line.\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == (char *)NULL) {\n            G.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.rootlen = strlen(pathcomp)) > 0) {\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(G.rootlen+2)) == (char *)NULL) {\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (tmproot[G.rootlen-1] == '/') {\n                tmproot[--G.rootlen] = '\\0';\n            }\n            if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||\n                                  !S_ISDIR(G.statbuf.st_mode)))\n            {   /* path does not exist */\n                if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* skip (or treat as stored file) */\n                    return MPN_INF_SKIP;\n                }\n                /* create the directory (could add loop here scanning tmproot\n                 * to create more than one level, but why really necessary?) */\n                if (mkdir(tmproot, 0777) == -1) {\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir:  cannot create extraction directory: %s\\n\\\n           %s\\n\",\n                      FnFilter1(tmproot), strerror(errno)));\n                    free(tmproot);\n                    G.rootlen = 0;\n                    /* path didn't exist, tried to create, and failed: */\n                    /* file exists, or 2+ subdir levels required */\n                    return MPN_ERR_SKIP;\n                }\n            }\n            tmproot[G.rootlen++] = '/';\n            tmproot[G.rootlen] = '\\0';\n            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n                free(tmproot);\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            free(G.rootpath);\n            G.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n#ifdef NO_MKDIR\n\n/********************/\n/* Function mkdir() */\n/********************/\n\nint mkdir(path, mode)\n    ZCONST char *path;\n    int mode;   /* ignored */\n/*\n * returns:   0 - successful\n *           -1 - failed (errno not set, however)\n */\n{\n    char command[FILNAMSIZ+40]; /* buffer for system() call */\n\n    /* GRR 930416:  added single quotes around path to avoid bug with\n     * creating directories with ampersands in name; not yet tested */\n    sprintf(command, \"IFS=\\\" \\t\\n\\\" /bin/mkdir '%s' 2>/dev/null\", path);\n    if (system(command))\n        return -1;\n    return 0;\n}\n\n#endif /* NO_MKDIR */\n\n\n\n\n#if (!defined(MTS) || defined(SET_DIR_ATTRIB))\nstatic int get_extattribs OF((__GPRO__ iztimes *pzt, ulg z_uidgid[2]));\n\nstatic int get_extattribs(__G__ pzt, z_uidgid)\n    __GDEF\n    iztimes *pzt;\n    ulg z_uidgid[2];\n{\n/*---------------------------------------------------------------------------\n    Convert from MSDOS-format local time and date to Unix-format 32-bit GMT\n    time:  adjust base year from 1980 to 1970, do usual conversions from\n    yy/mm/dd hh:mm:ss to elapsed seconds, and account for timezone and day-\n    light savings time differences.  If we have a Unix extra field, however,\n    we're laughing:  both mtime and atime are ours.  On the other hand, we\n    then have to check for restoration of UID/GID.\n  ---------------------------------------------------------------------------*/\n    int have_uidgid_flg;\n    unsigned eb_izux_flg;\n\n    eb_izux_flg = (G.extra_field ? ef_scan_for_izux(G.extra_field,\n                   G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n#ifdef IZ_CHECK_TZ\n                   (G.tz_is_valid ? pzt : NULL),\n#else\n                   pzt,\n#endif\n                   z_uidgid) : 0);\n    if (eb_izux_flg & EB_UT_FL_MTIME) {\n        TTrace((stderr, \"\\nget_extattribs:  Unix e.f. modif. time = %ld\\n\",\n          pzt->mtime));\n    } else {\n        pzt->mtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n    }\n    if (eb_izux_flg & EB_UT_FL_ATIME) {\n        TTrace((stderr, \"get_extattribs:  Unix e.f. access time = %ld\\n\",\n          pzt->atime));\n    } else {\n        pzt->atime = pzt->mtime;\n        TTrace((stderr, \"\\nget_extattribs:  modification/access times = %ld\\n\",\n          pzt->mtime));\n    }\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    have_uidgid_flg =\n#ifdef RESTORE_UIDGID\n            (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));\n#else\n            0;\n#endif\n    return have_uidgid_flg;\n}\n#endif /* !MTS || SET_DIR_ATTRIB */\n\n\n\n#ifndef MTS\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)    /* GRR: change to return PK-style warning level */\n    __GDEF\n{\n    union {\n        iztimes t3;             /* mtime, atime, ctime */\n        ztimbuf t2;             /* modtime, actime */\n    } zt;\n    ulg z_uidgid[2];\n    int have_uidgid_flg;\n\n    have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);\n\n/*---------------------------------------------------------------------------\n    If symbolic links are supported, allocate storage for a symlink control\n    structure, put the uncompressed \"data\" and other required info in it, and\n    add the structure to the \"deferred symlinks\" chain.  Since we know it's a\n    symbolic link to start with, we shouldn't have to worry about overflowing\n    unsigned ints with unsigned longs.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SYMLINKS\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n# ifdef SET_SYMLINK_ATTRIBS\n        extent attribsize = sizeof(unsigned) +\n                            (have_uidgid_flg ? sizeof(z_uidgid) : 0);\n# else\n        extent attribsize = 0;\n# endif\n        /* size of the symlink entry is the sum of\n         *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n         *  system specific attribute data size (might be 0),\n         *  and the lengths of name and link target.\n         */\n        extent slnk_entrysize = (sizeof(slinkentry) + 1) + attribsize +\n                                ucsize + strlen(G.filename);\n        slinkentry *slnk_entry;\n\n        if (slnk_entrysize < ucsize) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n\n        if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed: no mem\\n\",\n              FnFilter1(G.filename)));\n            fclose(G.outfile);\n            return;\n        }\n        slnk_entry->next = NULL;\n        slnk_entry->targetlen = ucsize;\n        slnk_entry->attriblen = attribsize;\n# ifdef SET_SYMLINK_ATTRIBS\n        memcpy(slnk_entry->buf, &(G.pInfo->file_attr),\n               sizeof(unsigned));\n        if (have_uidgid_flg)\n            memcpy(slnk_entry->buf + 4, z_uidgid, sizeof(z_uidgid));\n# endif\n        slnk_entry->target = slnk_entry->buf + slnk_entry->attriblen;\n        slnk_entry->fname = slnk_entry->target + ucsize + 1;\n        strcpy(slnk_entry->fname, G.filename);\n\n        /* move back to the start of the file to re-read the \"link data\" */\n        rewind(G.outfile);\n\n        if (fread(slnk_entry->target, 1, ucsize, G.outfile) != ucsize)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  symbolic link (%s) failed\\n\",\n              FnFilter1(G.filename)));\n            free(slnk_entry);\n            fclose(G.outfile);\n            return;\n        }\n        fclose(G.outfile);                  /* close \"link\" file for good... */\n        slnk_entry->target[ucsize] = '\\0';\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"-> %s \",\n              FnFilter1(slnk_entry->target)));\n        /* add this symlink record to the list of deferred symlinks */\n        if (G.slink_last != NULL)\n            G.slink_last->next = slnk_entry;\n        else\n            G.slink_head = slnk_entry;\n        G.slink_last = slnk_entry;\n        return;\n    }\n#endif /* SYMLINKS */\n\n#ifdef QLZIP\n    if (G.extra_field) {\n        static void qlfix OF((__GPRO__ uch *ef_ptr, unsigned ef_len));\n\n        qlfix(__G__ G.extra_field, G.lrec.extra_field_length);\n    }\n#endif\n\n#if (defined(NO_FCHOWN))\n    fclose(G.outfile);\n#endif\n\n    /* if -X option was specified and we have UID/GID info, restore it */\n    if (have_uidgid_flg\n        /* check that both uid and gid values fit into their data sizes */\n        && ((ulg)(uid_t)(z_uidgid[0]) == z_uidgid[0])\n        && ((ulg)(gid_t)(z_uidgid[1]) == z_uidgid[1])) {\n        TTrace((stderr, \"close_outfile:  restoring Unix UID/GID info\\n\"));\n#if (defined(NO_FCHOWN))\n        if (chown(G.filename, (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))\n#else\n        if (fchown(fileno(G.outfile), (uid_t)z_uidgid[0], (gid_t)z_uidgid[1]))\n#endif\n        {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,\n                  z_uidgid[0], z_uidgid[1], FnFilter1(G.filename),\n                  strerror(errno)));\n            else\n                Info(slide, 0x201, ((char *)slide, CannotSetUidGid,\n                  z_uidgid[0], z_uidgid[1], strerror(errno)));\n        }\n    }\n\n#if (!defined(NO_FCHOWN) && defined(NO_FCHMOD))\n    fclose(G.outfile);\n#endif\n\n#if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD))\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n    if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr)))\n        perror(\"fchmod (file attributes) error\");\n\n    fclose(G.outfile);\n#endif /* !NO_FCHOWN && !NO_FCHMOD */\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        /* set the file's access and modification times */\n        if (utime(G.filename, &(zt.t2))) {\n            if (uO.qflag)\n                Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,\n                  FnFilter1(G.filename), strerror(errno)));\n            else\n                Info(slide, 0x201, ((char *)slide, CannotSetTimestamps,\n                  strerror(errno)));\n        }\n    }\n\n#if (defined(NO_FCHOWN) || defined(NO_FCHMOD))\n/*---------------------------------------------------------------------------\n    Change the file permissions from default ones to those stored in the\n    zipfile.\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_CHMOD\n    if (chmod(G.filename, filtattr(__G__ G.pInfo->file_attr)))\n        perror(\"chmod (file attributes) error\");\n#endif\n#endif /* NO_FCHOWN || NO_FCHMOD */\n\n} /* end function close_outfile() */\n\n#endif /* !MTS */\n\n\n#if (defined(SYMLINKS) && defined(SET_SYMLINK_ATTRIBS))\nint set_symlnk_attribs(__G__ slnk_entry)\n    __GDEF\n    slinkentry *slnk_entry;\n{\n    if (slnk_entry->attriblen > 0) {\n# if (!defined(NO_LCHOWN))\n      if (slnk_entry->attriblen > sizeof(unsigned)) {\n        ulg *z_uidgid_p = (zvoid *)(slnk_entry->buf + sizeof(unsigned));\n        /* check that both uid and gid values fit into their data sizes */\n        if (((ulg)(uid_t)(z_uidgid_p[0]) == z_uidgid_p[0]) &&\n            ((ulg)(gid_t)(z_uidgid_p[1]) == z_uidgid_p[1])) {\n          TTrace((stderr,\n            \"set_symlnk_attribs:  restoring Unix UID/GID info for\\n\\\n        %s\\n\",\n            FnFilter1(slnk_entry->fname)));\n          if (lchown(slnk_entry->fname,\n                     (uid_t)z_uidgid_p[0], (gid_t)z_uidgid_p[1]))\n          {\n            Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,\n              z_uidgid_p[0], z_uidgid_p[1], FnFilter1(slnk_entry->fname),\n              strerror(errno)));\n          }\n        }\n      }\n# endif /* !NO_LCHOWN */\n# if (!defined(NO_LCHMOD))\n      TTrace((stderr,\n        \"set_symlnk_attribs:  restoring Unix attributes for\\n        %s\\n\",\n        FnFilter1(slnk_entry->fname)));\n      if (lchmod(slnk_entry->fname,\n                 filtattr(__G__ *(unsigned *)(zvoid *)slnk_entry->buf)))\n          perror(\"lchmod (file attributes) error\");\n# endif /* !NO_LCHMOD */\n    }\n    /* currently, no error propagation... */\n    return PK_OK;\n} /* end function set_symlnk_attribs() */\n#endif /* SYMLINKS && SET_SYMLINK_ATTRIBS */\n\n\n#ifdef SET_DIR_ATTRIB\n/* messages of code for setting directory attributes */\n#  ifndef NO_CHMOD\n  static ZCONST char DirlistChmodFailed[] =\n    \"warning:  cannot set permissions for %s\\n          %s\\n\";\n#  endif\n\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    uxdirattr *d_entry;\n\n    d_entry = (uxdirattr *)malloc(sizeof(uxdirattr) + strlen(G.filename));\n    *pd = (direntry *)d_entry;\n    if (d_entry == (uxdirattr *)NULL) {\n        return PK_MEM;\n    }\n    d_entry->fn = d_entry->fnbuf;\n    strcpy(d_entry->fn, G.filename);\n\n    d_entry->perms = G.pInfo->file_attr;\n\n    d_entry->have_uidgid = get_extattribs(__G__ &(d_entry->u.t3),\n                                          d_entry->uidgid);\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    int errval = PK_OK;\n\n    if (UxAtt(d)->have_uidgid &&\n        /* check that both uid and gid values fit into their data sizes */\n        ((ulg)(uid_t)(UxAtt(d)->uidgid[0]) == UxAtt(d)->uidgid[0]) &&\n        ((ulg)(gid_t)(UxAtt(d)->uidgid[1]) == UxAtt(d)->uidgid[1]) &&\n        chown(UxAtt(d)->fn, (uid_t)UxAtt(d)->uidgid[0],\n              (gid_t)UxAtt(d)->uidgid[1]))\n    {\n        Info(slide, 0x201, ((char *)slide, CannotSetItemUidGid,\n          UxAtt(d)->uidgid[0], UxAtt(d)->uidgid[1], FnFilter1(d->fn),\n          strerror(errno)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n    /* Skip restoring directory time stamps on user' request. */\n    if (uO.D_flag <= 0) {\n        /* restore directory timestamps */\n        if (utime(d->fn, &UxAtt(d)->u.t2)) {\n            Info(slide, 0x201, ((char *)slide, CannotSetItemTimestamps,\n              FnFilter1(d->fn), strerror(errno)));\n            if (!errval)\n                errval = PK_WARN;\n        }\n    }\n#ifndef NO_CHMOD\n    if (chmod(d->fn, UxAtt(d)->perms)) {\n        Info(slide, 0x201, ((char *)slide, DirlistChmodFailed,\n          FnFilter1(d->fn), strerror(errno)));\n        if (!errval)\n            errval = PK_WARN;\n    }\n#endif /* !NO_CHMOD */\n    return errval;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n\n#ifdef TIMESTAMP\n\n/***************************/\n/*  Function stamp_file()  */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    ztimbuf tp;\n\n    tp.modtime = tp.actime = modtime;\n    return (utime(fname, &tp));\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n#if (defined(__GNUC__) && defined(NX_CURRENT_COMPILER_RELEASE))\n    char cc_namebuf[40];\n    char cc_versbuf[40];\n#else\n#if (defined(__SUNPRO_C))\n    char cc_versbuf[17];\n#else\n#if (defined(__HP_cc) || defined(__IBMC__))\n    char cc_versbuf[25];\n#else\n#if (defined(__DECC_VER))\n    char cc_versbuf[17];\n    int cc_verstyp;\n#else\n#if (defined(CRAY) && defined(_RELEASE))\n    char cc_versbuf[40];\n#endif /* (CRAY && _RELEASE) */\n#endif /* __DECC_VER */\n#endif /* __HP_cc || __IBMC__ */\n#endif /* __SUNPRO_C */\n#endif /* (__GNUC__ && NX_CURRENT_COMPILER_RELEASE) */\n\n#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))\n    char os_namebuf[40];\n#else\n#if defined(__NetBSD__)\n    char os_namebuf[40];\n#endif\n#endif\n\n    /* Pyramid, NeXT have problems with huge macro expansion, too:  no Info() */\n    sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n#  ifdef NX_CURRENT_COMPILER_RELEASE\n      (sprintf(cc_namebuf, \"NeXT DevKit %d.%02d \",\n        NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100),\n       cc_namebuf),\n      (strlen(__VERSION__) > 8)? \"(gcc)\" :\n        (sprintf(cc_versbuf, \"(gcc %s)\", __VERSION__), cc_versbuf),\n#  else\n      \"gcc \", __VERSION__,\n#  endif\n#else\n#if defined(__SUNPRO_C)\n      \"Sun C \", (sprintf(cc_versbuf, \"version %x\", __SUNPRO_C), cc_versbuf),\n#else\n#if (defined(__HP_cc))\n      \"HP C \",\n      (((__HP_cc% 100) == 0) ?\n      (sprintf(cc_versbuf, \"version A.%02d.%02d\",\n      (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100))) :\n      (sprintf(cc_versbuf, \"version A.%02d.%02d.%02d\",\n      (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100))),\n      cc_versbuf),\n#else\n#if (defined(__DECC_VER))\n      \"DEC C \",\n      (sprintf(cc_versbuf, \"%c%d.%d-%03d\",\n               ((cc_verstyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' :\n                (cc_verstyp == 8 ? 'S' : 'V')),\n               __DECC_VER / 10000000,\n               (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000),\n               cc_versbuf),\n#else\n#if defined(CRAY) && defined(_RELEASE)\n      \"cc \", (sprintf(cc_versbuf, \"version %d\", _RELEASE), cc_versbuf),\n#else\n#ifdef __IBMC__\n      \"IBM C \",\n      (sprintf(cc_versbuf, \"version %d.%d.%d\",\n               (__IBMC__ / 100), ((__IBMC__ / 10) % 10), (__IBMC__ % 10)),\n               cc_versbuf),\n#else\n#ifdef __VERSION__\n#   ifndef IZ_CC_NAME\n#    define IZ_CC_NAME \"cc \"\n#   endif\n      IZ_CC_NAME, __VERSION__\n#else\n#   ifndef IZ_CC_NAME\n#    define IZ_CC_NAME \"cc\"\n#   endif\n      IZ_CC_NAME, \"\",\n#endif /* ?__VERSION__ */\n#endif /* ?__IBMC__ */\n#endif /* ?(CRAY && _RELEASE) */\n#endif /* ?__DECC_VER */\n#endif /* ?__HP_cc */\n#endif /* ?__SUNPRO_C */\n#endif /* ?__GNUC__ */\n\n#ifndef IZ_OS_NAME\n#  define IZ_OS_NAME \"Unix\"\n#endif\n      IZ_OS_NAME,\n\n#if defined(sgi) || defined(__sgi)\n      \" (Silicon Graphics IRIX)\",\n#else\n#ifdef sun\n#  ifdef sparc\n#    ifdef __SVR4\n      \" (Sun SPARC/Solaris)\",\n#    else /* may or may not be SunOS */\n      \" (Sun SPARC)\",\n#    endif\n#  else\n#  if defined(sun386) || defined(i386)\n      \" (Sun 386i)\",\n#  else\n#  if defined(mc68020) || defined(__mc68020__)\n      \" (Sun 3)\",\n#  else /* mc68010 or mc68000:  Sun 2 or earlier */\n      \" (Sun 2)\",\n#  endif\n#  endif\n#  endif\n#else\n#ifdef __hpux\n      \" (HP-UX)\",\n#else\n#ifdef __osf__\n      \" (DEC OSF/1)\",\n#else\n#ifdef _AIX\n      \" (IBM AIX)\",\n#else\n#ifdef aiws\n      \" (IBM RT/AIX)\",\n#else\n#if defined(CRAY) || defined(cray)\n#  ifdef _UNICOS\n      (sprintf(os_namebuf, \" (Cray UNICOS release %d)\", _UNICOS), os_namebuf),\n#  else\n      \" (Cray UNICOS)\",\n#  endif\n#else\n#if defined(uts) || defined(UTS)\n      \" (Amdahl UTS)\",\n#else\n#ifdef NeXT\n#  ifdef mc68000\n      \" (NeXTStep/black)\",\n#  else\n      \" (NeXTStep for Intel)\",\n#  endif\n#else              /* the next dozen or so are somewhat order-dependent */\n#ifdef LINUX\n#  ifdef __ELF__\n      \" (Linux ELF)\",\n#  else\n      \" (Linux a.out)\",\n#  endif\n#else\n#ifdef MINIX\n      \" (Minix)\",\n#else\n#ifdef M_UNIX\n      \" (SCO Unix)\",\n#else\n#ifdef M_XENIX\n      \" (SCO Xenix)\",\n#else\n#ifdef __NetBSD__\n#  ifdef NetBSD0_8\n      (sprintf(os_namebuf, \" (NetBSD 0.8%c)\", (char)(NetBSD0_8 - 1 + 'A')),\n       os_namebuf),\n#  else\n#  ifdef NetBSD0_9\n      (sprintf(os_namebuf, \" (NetBSD 0.9%c)\", (char)(NetBSD0_9 - 1 + 'A')),\n       os_namebuf),\n#  else\n#  ifdef NetBSD1_0\n      (sprintf(os_namebuf, \" (NetBSD 1.0%c)\", (char)(NetBSD1_0 - 1 + 'A')),\n       os_namebuf),\n#  else\n      (BSD4_4 == 0.5)? \" (NetBSD before 0.9)\" : \" (NetBSD 1.1 or later)\",\n#  endif\n#  endif\n#  endif\n#else\n#ifdef __FreeBSD__\n      (BSD4_4 == 0.5)? \" (FreeBSD 1.x)\" : \" (FreeBSD 2.0 or later)\",\n#else\n#ifdef __bsdi__\n      (BSD4_4 == 0.5)? \" (BSD/386 1.0)\" : \" (BSD/386 1.1 or later)\",\n#else\n#ifdef __386BSD__\n      (BSD4_4 == 1)? \" (386BSD, post-4.4 release)\" : \" (386BSD)\",\n#else\n#ifdef __CYGWIN__\n      \" (Cygwin)\",\n#else\n#if defined(i686) || defined(__i686) || defined(__i686__)\n      \" (Intel 686)\",\n#else\n#if defined(i586) || defined(__i586) || defined(__i586__)\n      \" (Intel 586)\",\n#else\n#if defined(i486) || defined(__i486) || defined(__i486__)\n      \" (Intel 486)\",\n#else\n#if defined(i386) || defined(__i386) || defined(__i386__)\n      \" (Intel 386)\",\n#else\n#ifdef pyr\n      \" (Pyramid)\",\n#else\n#ifdef ultrix\n#  ifdef mips\n      \" (DEC/MIPS)\",\n#  else\n#  ifdef vax\n      \" (DEC/VAX)\",\n#  else /* __alpha? */\n      \" (DEC/Alpha)\",\n#  endif\n#  endif\n#else\n#ifdef gould\n      \" (Gould)\",\n#else\n#ifdef MTS\n      \" (MTS)\",\n#else\n#ifdef __convexc__\n      \" (Convex)\",\n#else\n#ifdef __QNX__\n      \" (QNX 4)\",\n#else\n#ifdef __QNXNTO__\n      \" (QNX Neutrino)\",\n#else\n#ifdef Lynx\n      \" (LynxOS)\",\n#else\n#ifdef __APPLE__\n#  ifdef __i386__\n      \" Mac OS X Intel i32\",\n#  else\n#  ifdef __ppc__\n      \" Mac OS X PowerPC\",\n#  else\n#  ifdef __ppc64__\n      \" Mac OS X PowerPC64\",\n#  else\n      \" Mac OS X\",\n#  endif /* __ppc64__ */\n#  endif /* __ppc__ */\n#  endif /* __i386__ */\n#else\n      \"\",\n#endif /* Apple */\n#endif /* Lynx */\n#endif /* QNX Neutrino */\n#endif /* QNX 4 */\n#endif /* Convex */\n#endif /* MTS */\n#endif /* Gould */\n#endif /* DEC */\n#endif /* Pyramid */\n#endif /* 386 */\n#endif /* 486 */\n#endif /* 586 */\n#endif /* 686 */\n#endif /* Cygwin */\n#endif /* 386BSD */\n#endif /* BSDI BSD/386 */\n#endif /* NetBSD */\n#endif /* FreeBSD */\n#endif /* SCO Xenix */\n#endif /* SCO Unix */\n#endif /* Minix */\n#endif /* Linux */\n#endif /* NeXT */\n#endif /* Amdahl */\n#endif /* Cray */\n#endif /* RT/AIX */\n#endif /* AIX */\n#endif /* OSF/1 */\n#endif /* HP-UX */\n#endif /* Sun */\n#endif /* SGI */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n\n#ifdef QLZIP\n\nstruct qdirect  {\n    long            d_length __attribute__ ((packed));  /* file length */\n    unsigned char   d_access __attribute__ ((packed));  /* file access type */\n    unsigned char   d_type __attribute__ ((packed));    /* file type */\n    long            d_datalen __attribute__ ((packed)); /* data length */\n    long            d_reserved __attribute__ ((packed));/* Unused */\n    short           d_szname __attribute__ ((packed));  /* size of name */\n    char            d_name[36] __attribute__ ((packed));/* name area */\n    long            d_update __attribute__ ((packed));  /* last update */\n    long            d_refdate __attribute__ ((packed));\n    long            d_backup __attribute__ ((packed));   /* EOD */\n};\n\n#define LONGID  \"QDOS02\"\n#define EXTRALEN (sizeof(struct qdirect) + 8)\n#define JBLONGID    \"QZHD\"\n#define JBEXTRALEN  (sizeof(jbextra)  - 4 * sizeof(char))\n\ntypedef struct {\n    char        eb_header[4] __attribute__ ((packed));  /* place_holder */\n    char        longid[8] __attribute__ ((packed));\n    struct      qdirect     header __attribute__ ((packed));\n} qdosextra;\n\ntypedef struct {\n    char        eb_header[4];                           /* place_holder */\n    char        longid[4];\n    struct      qdirect     header;\n} jbextra;\n\n\n\n/*  The following two functions SH() and LG() convert big-endian short\n *  and long numbers into native byte order.  They are some kind of\n *  counterpart to the generic UnZip's makeword() and makelong() functions.\n */\nstatic ush SH(ush val)\n{\n    uch swapbuf[2];\n\n    swapbuf[1] = (uch)(val & 0xff);\n    swapbuf[0] = (uch)(val >> 8);\n    return (*(ush *)swapbuf);\n}\n\n\n\nstatic ulg LG(ulg val)\n{\n    /*  convert the big-endian unsigned long number `val' to the machine\n     *  dependent representation\n     */\n    ush swapbuf[2];\n\n    swapbuf[1] = SH((ush)(val & 0xffff));\n    swapbuf[0] = SH((ush)(val >> 16));\n    return (*(ulg *)swapbuf);\n}\n\n\n\nstatic void qlfix(__G__ ef_ptr, ef_len)\n    __GDEF\n    uch *ef_ptr;\n    unsigned ef_len;\n{\n    while (ef_len >= EB_HEADSIZE)\n    {\n        unsigned    eb_id  = makeword(EB_ID + ef_ptr);\n        unsigned    eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"qlfix: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        switch (eb_id) {\n          case EF_QDOS:\n          {\n            struct _ntc_\n            {\n                long id;\n                long dlen;\n            } ntc;\n            long dlen = 0;\n\n            qdosextra   *extra = (qdosextra *)ef_ptr;\n            jbextra     *jbp   = (jbextra   *)ef_ptr;\n\n            if (!strncmp(extra->longid, LONGID, strlen(LONGID)))\n            {\n                if (eb_len != EXTRALEN)\n                    if (uO.qflag)\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  invalid length in Qdos field for %s\\n\",\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  invalid length in Qdos field\"));\n\n                if (extra->header.d_type)\n                {\n                    dlen = extra->header.d_datalen;\n                }\n            }\n\n            if (!strncmp(jbp->longid, JBLONGID, strlen(JBLONGID)))\n            {\n                if (eb_len != JBEXTRALEN)\n                    if (uO.qflag)\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  invalid length in QZ field for %s\\n\",\n                          FnFilter1(G.filename)));\n                    else\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  invalid length in QZ field\"));\n                if (jbp->header.d_type)\n                {\n                    dlen = jbp->header.d_datalen;\n                }\n            }\n\n            if ((long)LG(dlen) > 0)\n            {\n                zfseeko(G.outfile, -8, SEEK_END);\n                fread(&ntc, 8, 1, G.outfile);\n                if (ntc.id != *(long *)\"XTcc\")\n                {\n                    ntc.id = *(long *)\"XTcc\";\n                    ntc.dlen = dlen;\n                    fwrite (&ntc, 8, 1, G.outfile);\n                }\n                Info(slide, 0x201, ((char *)slide, \"QData = %d\", LG(dlen)));\n            }\n            return;     /* finished, cancel further extra field scanning */\n          }\n\n          default:\n            Trace((stderr,\"qlfix: unknown extra field block, ID=%d\\n\",\n               eb_id));\n        }\n\n        /* Skip this extra field block */\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n}\n#endif /* QLZIP */\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/unxcfg.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    Unix specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __unxcfg_h\n#define __unxcfg_h\n\n\n/* LARGE FILE SUPPORT - 10/6/04 EG */\n/* This needs to be set before the includes so they set the right sizes */\n\n#if (defined(NO_LARGE_FILE_SUPPORT) && defined(LARGE_FILE_SUPPORT))\n#  undef LARGE_FILE_SUPPORT\n#endif\n\n/* Automatically set ZIP64_SUPPORT if LFS */\n#ifdef LARGE_FILE_SUPPORT\n# if (!defined(NO_ZIP64_SUPPORT) && !defined(ZIP64_SUPPORT))\n#   define ZIP64_SUPPORT\n# endif\n#endif\n\n/* NO_ZIP64_SUPPORT takes preceedence over ZIP64_SUPPORT */\n#if defined(NO_ZIP64_SUPPORT) && defined(ZIP64_SUPPORT)\n#  undef ZIP64_SUPPORT\n#endif\n\n#ifdef LARGE_FILE_SUPPORT\n  /* 64-bit Large File Support */\n\n  /* The following Large File Summit (LFS) defines turn on large file support\n     on Linux (probably 2.4 or later kernel) and many other unixen */\n\n  /* These have to be before any include that sets types so the large file\n     versions of the types are set in the includes */\n\n# define _LARGEFILE_SOURCE      /* some OSes need this for fseeko */\n# define _LARGEFILE64_SOURCE\n# define _FILE_OFFSET_BITS 64   /* select default interface as 64 bit */\n# define _LARGE_FILES           /* some OSes need this for 64-bit off_t */\n# define __USE_LARGEFILE64\n#endif /* LARGE_FILE_SUPPORT */\n\n\n#include <sys/types.h>          /* off_t, time_t, dev_t, ... */\n#include <sys/stat.h>\n\n#ifdef NO_OFF_T\n  typedef long zoff_t;\n#else\n  typedef off_t zoff_t;\n#endif\n#define ZOFF_T_DEFINED\ntypedef struct stat z_stat;\n#define Z_STAT_DEFINED\n\n#ifndef COHERENT\n#  include <fcntl.h>            /* O_BINARY for open() w/o CR/LF translation */\n#else /* COHERENT */\n#  ifdef _I386\n#    include <fcntl.h>          /* Coherent 4.0.x, Mark Williams C */\n#  else\n#    include <sys/fcntl.h>      /* Coherent 3.10, Mark Williams C */\n#  endif\n#  define SHORT_SYMS\n#  ifndef __COHERENT__          /* Coherent 4.2 has tzset() */\n#    define tzset  settz\n#  endif\n#endif /* ?COHERENT */\n\n#ifndef NO_PARAM_H\n#  ifdef NGROUPS_MAX\n#    undef NGROUPS_MAX      /* SCO bug:  defined again in <sys/param.h> */\n#  endif\n#  ifdef BSD\n#    define TEMP_BSD        /* may be defined again in <sys/param.h> */\n#    undef BSD\n#  endif\n#  include <sys/param.h>    /* conflict with <sys/types.h>, some systems? */\n#  ifdef TEMP_BSD\n#    undef TEMP_BSD\n#    ifndef BSD\n#      define BSD\n#    endif\n#  endif\n#endif /* !NO_PARAM_H */\n\n#ifdef __osf__\n#  define DIRENT\n#  ifdef BSD\n#    undef BSD\n#  endif\n#endif /* __osf__ */\n\n#ifdef __CYGWIN__\n#  include <unistd.h>\n#  define DIRENT\n#  define HAVE_TERMIOS_H\n#  ifndef timezone\n#    define timezone _timezone\n#  endif\n#endif\n\n#ifdef BSD\n#  include <sys/time.h>\n#  include <sys/timeb.h>\n#  if (defined(_AIX) || defined(__GLIBC__) || defined(__GNU__))\n#    include <time.h>\n#  endif\n#else\n#  include <time.h>\n   struct tm *gmtime(), *localtime();\n#endif\n\n#if (defined(BSD4_4) || (defined(SYSV) && defined(MODERN)))\n#  include <unistd.h>           /* this includes utime.h on SGIs */\n#  if (defined(BSD4_4) || defined(linux) || defined(__GLIBC__))\n#    include <utime.h>\n#    define GOT_UTIMBUF\n#  endif\n#  if (!defined(GOT_UTIMBUF) && (defined(__hpux) || defined(__SUNPRO_C)))\n#    include <utime.h>\n#    define GOT_UTIMBUF\n#  endif\n#  if (!defined(GOT_UTIMBUF) && defined(__GNU__))\n#    include <utime.h>\n#    define GOT_UTIMBUF\n#  endif\n#endif\n#if (defined(__DGUX__) && !defined(GOT_UTIMBUF))\n   /* DG/UX requires this because of a non-standard struct utimebuf */\n#  include <utime.h>\n#  define GOT_UTIMBUF\n#endif\n\n#if (defined(V7) || defined(pyr_bsd))\n#  define strchr   index\n#  define strrchr  rindex\n#endif\n#ifdef V7\n#  define O_RDONLY 0\n#  define O_WRONLY 1\n#  define O_RDWR   2\n#endif\n\n#if defined(NO_UNICODE_SUPPORT) && defined(UNICODE_SUPPORT)\n   /* disable Unicode (UTF-8) support when requested */\n#  undef UNICODE_SUPPORT\n#endif\n\n#if (defined(_MBCS) && defined(NO_MBCS))\n   /* disable MBCS support when requested */\n#  undef _MBCS\n#endif\n\n#if (!defined(NO_SETLOCALE) && !defined(_MBCS))\n# if (!defined(UNICODE_SUPPORT) || !defined(UTF8_MAYBE_NATIVE))\n   /* enable setlocale here, unless this happens later for UTF-8 and/or\n    * MBCS support */\n#  include <locale.h>\n#  ifndef SETLOCALE\n#    define SETLOCALE(category, locale) setlocale(category, locale)\n#  endif\n# endif\n#endif\n#ifndef NO_SETLOCALE\n# if (!defined(NO_WORKING_ISPRINT) && !defined(HAVE_WORKING_ISPRINT))\n   /* enable \"enhanced\" unprintable chars detection in fnfilter() */\n#  define HAVE_WORKING_ISPRINT\n# endif\n#endif\n\n#ifdef MINIX\n#  include <stdio.h>\n#endif\n#if (!defined(HAVE_STRNICMP) & !defined(NO_STRNICMP))\n#  define NO_STRNICMP\n#endif\n#ifndef DATE_FORMAT\n#  define DATE_FORMAT DF_MDY    /* GRR:  customize with locale.h somehow? */\n#endif\n#define lenEOL          1\n#ifdef EBCDIC\n#  define PutNativeEOL  *q++ = '\\n';\n#else\n#  define PutNativeEOL  *q++ = native(LF);\n#endif\n#define SCREENSIZE(ttrows, ttcols)  screensize(ttrows, ttcols)\n#define SCREENWIDTH     80\n#define SCREENLWRAP     1\n#define USE_EF_UT_TIME\n#if (!defined(NO_LCHOWN) || !defined(NO_LCHMOD))\n#  define SET_SYMLINK_ATTRIBS\n#endif\n#ifdef MTS\n#  ifdef SET_DIR_ATTRIB\n#    undef SET_DIR_ATTRIB\n#  endif\n#else /* !MTS */\n#  define SET_DIR_ATTRIB\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))   /* GRR 970513 */\n#    define TIMESTAMP\n#  endif\n#  define RESTORE_UIDGID\n#endif /* ?MTS */\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    int created_dir, renamed_fullpath;\\\n    char *rootpath, *buildpath, *end;\\\n    ZCONST char *wildname;\\\n    char *dirname, matchname[FILNAMSIZ];\\\n    int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n    zvoid *wild_dir;\n\n/* created_dir, and renamed_fullpath are used by both mapname() and    */\n/*    checkdir().                                                      */\n/* rootlen, rootpath, buildpath and end are used by checkdir().        */\n/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */\n/*    and notfirstcall are used by do_wild().                          */\n\n#endif /* !__unxcfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/unix/zipgrep",
    "content": "#!/bin/sh\n#\n#    zipgrep: Use unzip and egrep to search the specified members of a\n# Zip archive for a string or pattern.  Search all members if no members\n# are specified explicitly.  The script attempts to handle egrep's \"-h\"\n# and \"-l\" options internally.\n#\n# This script assumes that the desired \"unzip\" and \"egrep\" (and \"sed\")\n# programs are on the user's PATH.\n#\n\npat=\"\"\nopt=\"\"\nwhile test $# -ne 0; do\n  case \"$1\" in\n  -e | -f) opt=\"$opt $1\"; shift; pat=\"$1\";;\n  -*)      opt=\"$opt $1\";;\n   *)      if test -z \"$pat\"; then\n             pat=\"$1\"\n           else\n             break;\n           fi;;\n  esac\n  shift\ndone\n\nif test $# = 0; then\n  echo usage: `basename \"$0\"` \"[egrep_options] pattern zipfile [members...]\"\n  echo Uses unzip and egrep to search the zip members for a string or pattern.\n  exit 1\nfi\nzipfile=\"$1\"; shift\n\nlist=0\nsilent=0\nopt=`echo \"$opt\" | sed -e 's/ //g' -e 's/-//g'`\ncase \"$opt\" in\n  *l*) list=1; opt=`echo $opt | sed s/l//`\nesac\ncase \"$opt\" in\n  *h*) silent=1\nesac\nif test -n \"$opt\"; then\n  opt=\"-$opt\"\nfi\n\nstatus_grep_global=1\nIFS='\n'\n\n# Escape shell-special characters in \"pat\".\npat=` echo \"$pat\" | \\\n sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g' -e 's/|/\\\\\\|/g' -e 's/&/\\\\\\&/g' `\n\n# Use \"unzip -Z1\" to get a listing of the specified members from the\n# specified archive.  Escape any backslashes in a file name.\nfor i in `unzip -Z1 \"$zipfile\" ${1+\"$@\"} | sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g' `; do\n  if test $list -eq 1; then\n    # \"-l\": Show only the archive member name, not the matching line(s).\n    unzip -p-L \"$zipfile\" \"$i\" | \\\n     egrep $opt \"$pat\" > /dev/null && echo \"$i\"\n    status_grep=$?\n  elif test $silent -eq 1; then\n    # \"-h\": Show only the matching line(s), not the archive member name.\n    # (\"-s\" in \"opt\" will silence \"egrep\", stopping all output.)\n    unzip -p-L \"$zipfile\" \"$i\" | \\\n     egrep $opt \"$pat\"\n    status_grep=$?\n  else\n    # Escape (or re-escape) shell-special characters in the archive\n    # member name, \"i\".\n    i=` echo \"$i\" | \\\n     sed -e 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g' -e 's/|/\\\\\\|/g' -e 's/&/\\\\\\&/g' `\n\n    # Globally, send fd 4 to stdout.  In the pipeline, send normal\n    # stdout to fd 4, and send grep status to fd 3.  Collect fd 3\n    # with ``.\n    exec 4>&1\n    status_grep=` ( \\\n     ( unzip -p-L \"$zipfile\" \"$i\" | \\\n     egrep $opt \"$pat\" 1>&4 ; echo $? >&3 ) 4>&1 | \\\n     sed \"s|^|${i}:|\" 1>&4 \\\n     ) 3>&1 `\n  fi\n\n  # Save the primary command status.  (May be the grep status.)\n  sts=$?\n  # If this grep status was zero, set the global grep status to zero.\n  test \"$status_grep\" -eq 0 && status_grep_global=0\n  # If this grep status was not zero or one, exit now.\n  test \"$status_grep\" -gt 1 && exit \"$status_grep\"\n\ndone\n\n# If \"sts\" is good (0), then exit with the global grep status.\n# Else, when \"sts\" is bad, exit with the worst status we can find.\nif test $sts -eq 0 ; then\n  exit $status_grep_global\nelse\n  if test \"$status_grep\" -gt 1 ; then\n    exit \"$status_grep\"\n  else\n    exit $sts\n  fi\nfi\n"
  },
  {
    "path": "deps/infozip/unzip60/unreduce.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unreduce.c\n\n  Copyright-clean dummy module, without any real code.\n\n  If you really need unreduce support, replace this module by the full\n  source code, available as add-on package from our distribution site.\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __UNREDUCE_C    /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"      /* defines COPYRIGHT_CLEAN by default */\n\n\n#ifndef COPYRIGHT_CLEAN\n\n /* This line is indented to hide the #error directive from pure traditional\n  * K&R C preprocessors. These do not recognize the #error directive, but\n  * they also recognize only lines that start with a '#' in column 1 as\n  * preprocessor directives.\n  */\n #error This dummy-module does not support the unreduce method!\n\n#endif /* !COPYRIGHT_CLEAN */\n"
  },
  {
    "path": "deps/infozip/unzip60/unshrink.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unshrink.c                     version 1.22                     19 Mar 2008\n\n\n       NOTE:  This code may or may not infringe on the so-called \"Welch\n       patent\" owned by Unisys.  (From reading the patent, it appears\n       that a pure LZW decompressor is *not* covered, but this claim has\n       not been tested in court, and Unisys is reported to believe other-\n       wise.)  It is therefore the responsibility of the user to acquire\n       whatever license(s) may be required for legal use of this code.\n\n       THE INFO-ZIP GROUP DISCLAIMS ALL LIABILITY FOR USE OF THIS CODE\n       IN VIOLATION OF APPLICABLE PATENT LAW.\n\n\n  Shrinking is basically a dynamic LZW algorithm with allowed code sizes of\n  up to 13 bits; in addition, there is provision for partial clearing of\n  leaf nodes.  PKWARE uses the special code 256 (decimal) to indicate a\n  change in code size or a partial clear of the code tree:  256,1 for the\n  former and 256,2 for the latter.  [Note that partial clearing can \"orphan\"\n  nodes:  the parent-to-be can be cleared before its new child is added,\n  but the child is added anyway (as an orphan, as though the parent still\n  existed).  When the tree fills up to the point where the parent node is\n  reused, the orphan is effectively \"adopted.\"  Versions prior to 1.05 were\n  affected more due to greater use of pointers (to children and siblings\n  as well as parents).]\n\n  This replacement version of unshrink.c was written from scratch.  It is\n  based only on the algorithms described in Mark Nelson's _The Data Compres-\n  sion Book_ and in Terry Welch's original paper in the June 1984 issue of\n  IEEE _Computer_; no existing source code, including any in Nelson's book,\n  was used.\n\n  Memory requirements have been reduced in this version and are now no more\n  than the original Sam Smith code.  This is still larger than any of the\n  other algorithms:  at a minimum, 8K+8K+16K (stack+values+parents) assuming\n  16-bit short ints, and this does not even include the output buffer (the\n  other algorithms leave the uncompressed data in the work area, typically\n  called slide[]).  For machines with a 64KB data space this is a problem,\n  particularly when text conversion is required and line endings have more\n  than one character.  UnZip's solution is to use two roughly equal halves\n  of outbuf for the ASCII conversion in such a case; the \"unshrink\" argument\n  to flush() signals that this is the case.\n\n  For large-memory machines, a second outbuf is allocated for translations,\n  but only if unshrinking and only if translations are required.\n\n              | binary mode  |        text mode\n    ---------------------------------------------------\n    big mem   |  big outbuf  | big outbuf + big outbuf2  <- malloc'd here\n    small mem | small outbuf | half + half small outbuf\n\n  Copyright 1994, 1995 Greg Roelofs.  See the accompanying file \"COPYING\"\n  in UnZip 5.20 (or later) source or binary distributions.\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __UNSHRINK_C    /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n\n#ifndef LZW_CLEAN\n\nstatic void  partial_clear  OF((__GPRO__ int lastcodeused));\n\n#ifdef DEBUG\n#  define OUTDBG(c) \\\n   if ((c)<32 || (c)>=127) fprintf(stderr,\"\\\\x%02x\",(c)); else putc((c),stderr);\n#else\n#  define OUTDBG(c)\n#endif\n\n/* HSIZE is defined as 2^13 (8192) in unzip.h (resp. unzpriv.h */\n#define BOGUSCODE  256\n#define FLAG_BITS  parent        /* upper bits of parent[] used as flag bits */\n#define CODE_MASK  (HSIZE - 1)   /* 0x1fff (lower bits are parent's index) */\n#define FREE_CODE  HSIZE         /* 0x2000 (code is unused or was cleared) */\n#define HAS_CHILD  (HSIZE << 1)  /* 0x4000 (code has a child--do not clear) */\n\n#define parent G.area.shrink.Parent\n#define Value  G.area.shrink.value /* \"value\" conflicts with Pyramid ioctl.h */\n#define stack  G.area.shrink.Stack\n\n\n/***********************/\n/* Function unshrink() */\n/***********************/\n\nint unshrink(__G)\n     __GDEF\n{\n    uch *stacktop = stack + (HSIZE - 1);\n    register uch *newstr;\n    uch finalval;\n    int codesize=9, len, error;\n    shrint code, oldcode, curcode;\n    shrint lastfreecode;\n    unsigned int outbufsiz;\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    /* Normally realbuf and outbuf will be the same.  However, if the data\n     * are redirected to a large memory buffer, realbuf will point to the\n     * new location while outbuf will remain pointing to the malloc'd\n     * memory buffer. */\n    uch *realbuf = G.outbuf;\n#else\n#   define realbuf G.outbuf\n#endif\n\n\n/*---------------------------------------------------------------------------\n    Initialize various variables.\n  ---------------------------------------------------------------------------*/\n\n    lastfreecode = BOGUSCODE;\n\n#ifndef VMS     /* VMS uses its own buffer scheme for textmode flush(). */\n#ifndef SMALL_MEM\n    /* non-memory-limited machines:  allocate second (large) buffer for\n     * textmode conversion in flush(), but only if needed */\n    if (G.pInfo->textmode && !G.outbuf2 &&\n        (G.outbuf2 = (uch *)malloc(TRANSBUFSIZ)) == (uch *)NULL)\n        return PK_MEM3;\n#endif\n#endif /* !VMS */\n\n    for (code = 0;  code < BOGUSCODE;  ++code) {\n        Value[code] = (uch)code;\n        parent[code] = BOGUSCODE;\n    }\n    for (code = BOGUSCODE+1;  code < HSIZE;  ++code)\n        parent[code] = FREE_CODE;\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n    if (G.redirect_slide) { /* use normal outbuf unless we're a DLL routine */\n        realbuf = G.redirect_buffer;\n        outbufsiz = (unsigned)G.redirect_size;\n    } else\n#endif\n#ifdef DLL\n    if (G.pInfo->textmode && !G.redirect_data)\n#else\n    if (G.pInfo->textmode)\n#endif\n        outbufsiz = RAWBUFSIZ;\n    else\n        outbufsiz = OUTBUFSIZ;\n    G.outptr = realbuf;\n    G.outcnt = 0L;\n\n/*---------------------------------------------------------------------------\n    Get and output first code, then loop over remaining ones.\n  ---------------------------------------------------------------------------*/\n\n    READBITS(codesize, oldcode)\n    if (G.zipeof)\n        return PK_OK;\n\n    finalval = (uch)oldcode;\n    OUTDBG(finalval)\n    *G.outptr++ = finalval;\n    ++G.outcnt;\n\n    while (TRUE) {\n        READBITS(codesize, code)\n        if (G.zipeof)\n            break;\n        if (code == BOGUSCODE) {   /* possible to have consecutive escapes? */\n            READBITS(codesize, code)\n            if (G.zipeof)\n                break;\n            if (code == 1) {\n                ++codesize;\n                Trace((stderr, \" (codesize now %d bits)\\n\", codesize));\n                if (codesize > MAX_BITS) return PK_ERR;\n            } else if (code == 2) {\n                Trace((stderr, \" (partial clear code)\\n\"));\n                /* clear leafs (nodes with no children) */\n                partial_clear(__G__ lastfreecode);\n                Trace((stderr, \" (done with partial clear)\\n\"));\n                lastfreecode = BOGUSCODE; /* reset start of free-node search */\n            }\n            continue;\n        }\n\n    /*-----------------------------------------------------------------------\n        Translate code:  traverse tree from leaf back to root.\n      -----------------------------------------------------------------------*/\n\n        newstr = stacktop;\n        curcode = code;\n\n        if (parent[code] == FREE_CODE) {\n            /* or (FLAG_BITS[code] & FREE_CODE)? */\n            Trace((stderr, \" (found a KwKwK code %d; oldcode = %d)\\n\", code,\n              oldcode));\n            *newstr-- = finalval;\n            code = oldcode;\n        }\n\n        while (code != BOGUSCODE) {\n            if (newstr < stack) {\n                /* Bogus compression stream caused buffer underflow! */\n                Trace((stderr, \"unshrink stack overflow!\\n\"));\n                return PK_ERR;\n            }\n            if (parent[code] == FREE_CODE) {\n                /* or (FLAG_BITS[code] & FREE_CODE)? */\n                Trace((stderr, \" (found a KwKwK code %d; oldcode = %d)\\n\",\n                  code, oldcode));\n                *newstr-- = finalval;\n                code = oldcode;\n            } else {\n                *newstr-- = Value[code];\n                code = (shrint)(parent[code] & CODE_MASK);\n            }\n        }\n\n        len = (int)(stacktop - newstr++);\n        finalval = *newstr;\n\n    /*-----------------------------------------------------------------------\n        Write expanded string in reverse order to output buffer.\n      -----------------------------------------------------------------------*/\n\n        Trace((stderr,\n          \"code %4d; oldcode %4d; char %3d (%c); len %d; string [\", curcode,\n          oldcode, (int)(*newstr), (*newstr<32 || *newstr>=127)? ' ':*newstr,\n          len));\n\n        {\n            register uch *p;\n\n            for (p = newstr;  p < newstr+len;  ++p) {\n                *G.outptr++ = *p;\n                OUTDBG(*p)\n                if (++G.outcnt == outbufsiz) {\n                    Trace((stderr, \"doing flush(), outcnt = %lu\\n\", G.outcnt));\n                    if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) {\n                        Trace((stderr, \"unshrink:  flush() error (%d)\\n\",\n                          error));\n                        return error;\n                    }\n                    G.outptr = realbuf;\n                    G.outcnt = 0L;\n                    Trace((stderr, \"done with flush()\\n\"));\n                }\n            }\n        }\n\n    /*-----------------------------------------------------------------------\n        Add new leaf (first character of newstr) to tree as child of oldcode.\n      -----------------------------------------------------------------------*/\n\n        /* search for freecode */\n        code = (shrint)(lastfreecode + 1);\n        /* add if-test before loop for speed? */\n        while ((code < HSIZE) && (parent[code] != FREE_CODE))\n            ++code;\n        lastfreecode = code;\n        Trace((stderr, \"]; newcode %d\\n\", code));\n        if (code >= HSIZE)\n            /* invalid compressed data caused max-code overflow! */\n            return PK_ERR;\n\n        Value[code] = finalval;\n        parent[code] = oldcode;\n        oldcode = curcode;\n\n    }\n\n/*---------------------------------------------------------------------------\n    Flush any remaining data and return to sender...\n  ---------------------------------------------------------------------------*/\n\n    if (G.outcnt > 0L) {\n        Trace((stderr, \"doing final flush(), outcnt = %lu\\n\", G.outcnt));\n        if ((error = flush(__G__ realbuf, G.outcnt, TRUE)) != 0) {\n            Trace((stderr, \"unshrink:  flush() error (%d)\\n\", error));\n            return error;\n        }\n        Trace((stderr, \"done with flush()\\n\"));\n    }\n\n    return PK_OK;\n\n} /* end function unshrink() */\n\n\n\n\n\n/****************************/\n/* Function partial_clear() */      /* no longer recursive... */\n/****************************/\n\nstatic void partial_clear(__G__ lastcodeused)\n    __GDEF\n    int lastcodeused;\n{\n    register shrint code;\n\n    /* clear all nodes which have no children (i.e., leaf nodes only) */\n\n    /* first loop:  mark each parent as such */\n    for (code = BOGUSCODE+1;  code <= lastcodeused;  ++code) {\n        register shrint cparent = (shrint)(parent[code] & CODE_MASK);\n\n        if (cparent > BOGUSCODE)\n            FLAG_BITS[cparent] |= HAS_CHILD;   /* set parent's child-bit */\n    }\n\n    /* second loop:  clear all nodes *not* marked as parents; reset flag bits */\n    for (code = BOGUSCODE+1;  code <= lastcodeused;  ++code) {\n        if (FLAG_BITS[code] & HAS_CHILD)    /* just clear child-bit */\n            FLAG_BITS[code] &= ~HAS_CHILD;\n        else {                              /* leaf:  lose it */\n            Trace((stderr, \"%d\\n\", code));\n            parent[code] = FREE_CODE;\n        }\n    }\n\n    return;\n}\n\n#endif /* !LZW_CLEAN */\n"
  },
  {
    "path": "deps/infozip/unzip60/unzip.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unzip.c\n\n  UnZip - a zipfile extraction utility.  See below for make instructions, or\n  read the comments in Makefile and the various Contents files for more de-\n  tailed explanations.  To report a bug, submit a *complete* description via\n  //www.info-zip.org/zip-bug.html; include machine type, operating system and\n  version, compiler and version, and reasonably detailed error messages or\n  problem report.  To join Info-ZIP, see the instructions in README.\n\n  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,\n  which in turn was almost a complete rewrite of version 3.x.  For a detailed\n  revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of\n  the many (near infinite) contributors, see \"CONTRIBS\" in the UnZip source\n  distribution.\n\n  UnZip 6.0 adds support for archives larger than 4 GiB using the Zip64\n  extensions as well as support for Unicode information embedded per the\n  latest zip standard additions.\n\n  ---------------------------------------------------------------------------\n\n  [from original zipinfo.c]\n\n  This program reads great gobs of totally nifty information, including the\n  central directory stuff, from ZIP archives (\"zipfiles\" for short).  It\n  started as just a testbed for fooling with zipfiles, but at this point it\n  is actually a useful utility.  It also became the basis for the rewrite of\n  UnZip (3.16 -> 4.0), using the central directory for processing rather than\n  the individual (local) file headers.\n\n  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.\n  If the executable is named \"unzip\" (or \"unzip.exe\", depending), it behaves\n  like UnZip by default; if it is named \"zipinfo\" or \"ii\", it behaves like\n  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z\n  option; for example, \"unzip -Z [zipinfo_options] archive.zip\".\n\n  Another dandy product from your buddies at Newtware!\n\n  Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/\n           23 August 1990 -> April 1997\n\n  ---------------------------------------------------------------------------\n\n  Version:  unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,\n              Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,\n              AtheOS, BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos\n              and TOPS-20.\n\n  Copyrights:  see accompanying file \"LICENSE\" in UnZip source distribution.\n               (This software is free but NOT IN THE PUBLIC DOMAIN.)\n\n  ---------------------------------------------------------------------------*/\n\n\n\n#define __UNZIP_C       /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"      /* includes, typedefs, macros, prototypes, etc. */\n#include \"crypt.h\"\n#include \"unzvers.h\"\n\n#ifndef WINDLL          /* The WINDLL port uses windll/windll.c instead... */\n\n/***************************/\n/* Local type declarations */\n/***************************/\n\n#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\ntypedef struct _sign_info\n    {\n        struct _sign_info *previous;\n        void (*sighandler)(int);\n        int sigtype;\n    } savsigs_info;\n#endif\n\n/*******************/\n/* Local Functions */\n/*******************/\n\n#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\nstatic int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain,\n                                int signal_type, void (*newhandler)(int)));\n#endif\n#ifndef SFX\nstatic void  help_extended      OF((__GPRO));\nstatic void  show_version_info  OF((__GPRO));\n#endif\n\n\n/*************/\n/* Constants */\n/*************/\n\n#include \"consts.h\"  /* all constant global variables are in here */\n                     /* (non-constant globals were moved to globals.c) */\n\n/* constant local variables: */\n\n#ifndef SFX\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n   static ZCONST char Far EnvUnZip[] = ENV_UNZIP;\n   static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;\n   static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;\n   static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;\n#ifdef RISCOS\n   static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;\n#endif /* RISCOS */\n  static ZCONST char Far NoMemEnvArguments[] =\n    \"envargs:  cannot get memory for arguments\";\n#endif /* !_WIN32_WCE */\n  static ZCONST char Far CmdLineParamTooLong[] =\n    \"error:  command line parameter #%d exceeds internal size limit\\n\";\n#endif /* !SFX */\n\n#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\n  static ZCONST char Far CantSaveSigHandler[] =\n    \"error:  cannot save signal handler settings\\n\";\n#endif\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n   static ZCONST char Far NotExtracting[] =\n     \"caution:  not extracting; -d ignored\\n\";\n   static ZCONST char Far MustGiveExdir[] =\n     \"error:  must specify directory to which to extract with -d option\\n\";\n   static ZCONST char Far OnlyOneExdir[] =\n     \"error:  -d option used more than once (only one exdir allowed)\\n\";\n#endif\n#if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR))\n  static ZCONST char Far UTF8EscapeUnSupp[] =\n    \"warning:  -U \\\"escape all non-ASCII UTF-8 chars\\\" is not supported\\n\";\n#endif\n\n#if CRYPT\n   static ZCONST char Far MustGivePasswd[] =\n     \"error:  must give decryption password with -P option\\n\";\n#endif\n\n#ifndef SFX\n   static ZCONST char Far Zfirst[] =\n   \"error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\\n\";\n#endif\nstatic ZCONST char Far InvalidOptionsMsg[] = \"error:\\\n  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\\n\";\nstatic ZCONST char Far IgnoreOOptionMsg[] =\n  \"caution:  both -n and -o specified; ignoring -o\\n\";\n\n/* usage() strings */\n#ifndef SFX\n#ifdef VMS\n   static ZCONST char Far Example3[] = \"vms.c\";\n   static ZCONST char Far Example2[] = \"  unzip \\\"-V\\\" foo \\\"Bar\\\"\\\n (Quote names to preserve case, unless SET PROC/PARS=EXT)\\n\";\n#else /* !VMS */\n   static ZCONST char Far Example3[] = \"ReadMe\";\n#ifdef RISCOS\n   static ZCONST char Far Example2[] =\n\"  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\\n\";\n#else /* !RISCOS */\n#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))\n   static ZCONST char Far Example2[] =\n     \"\";                /* no room:  too many local3[] items */\n#else /* !OS2 */\n#ifdef MACOS\n   static ZCONST char Far Example2[] = \"\"; /* not needed */\n#else /* !MACOS */\n   static ZCONST char Far Example2[] = \" \\\n unzip -p foo | more  => send contents of foo.zip via pipe into program more\\n\";\n#endif /* ?MACOS */\n#endif /* ?OS2 */\n#endif /* ?RISCOS */\n#endif /* ?VMS */\n\n/* local1[]:  command options */\n#if defined(TIMESTAMP)\n   static ZCONST char Far local1[] =\n     \"  -T  timestamp archive to latest\";\n#else /* !TIMESTAMP */\n   static ZCONST char Far local1[] = \"\";\n#endif /* ?TIMESTAMP */\n\n/* local2[] and local3[]:  modifier options */\n#ifdef DOS_FLX_H68_OS2_W32\n#ifdef FLEXOS\n   static ZCONST char Far local2[] = \"\";\n#else\n   static ZCONST char Far local2[] =\n     \" -$  label removables (-$$ => fixed disks)\";\n#endif\n#ifdef OS2\n#ifdef MORE\n   static ZCONST char Far local3[] = \"\\\n  -X  restore ACLs if supported              -s  spaces in filenames => '_'\\n\\\n                                             -M  pipe through \\\"more\\\" pager\\n\";\n#else\n   static ZCONST char Far local3[] = \" \\\n -X  restore ACLs if supported              -s  spaces in filenames => '_'\\n\\n\";\n#endif /* ?MORE */\n#else /* !OS2 */\n#ifdef WIN32\n#ifdef NTSD_EAS\n#ifdef MORE\n   static ZCONST char Far local3[] = \"\\\n  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\\n\\\n                                             -M  pipe through \\\"more\\\" pager\\n\";\n#else\n   static ZCONST char Far local3[] = \" \\\n -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\\n\\n\";\n#endif /* ?MORE */\n#else /* !NTSD_EAS */\n#ifdef MORE\n   static ZCONST char Far local3[] = \"\\\n  -M  pipe through \\\"more\\\" pager            \\\n  -s  spaces in filenames => '_'\\n\\n\";\n#else\n   static ZCONST char Far local3[] = \" \\\n                                            -s  spaces in filenames => '_'\\n\\n\";\n#endif /* ?MORE */\n#endif /* ?NTSD_EAS */\n#else /* !WIN32 */\n#ifdef MORE\n   static ZCONST char Far local3[] = \"  -\\\nM  pipe through \\\"more\\\" pager              -s  spaces in filenames => '_'\\n\\n\";\n#else\n   static ZCONST char Far local3[] = \"\\\n                                             -s  spaces in filenames => '_'\\n\";\n#endif\n#endif /* ?WIN32 */\n#endif /* ?OS2 || ?WIN32 */\n#else /* !DOS_FLX_OS2_W32 */\n#ifdef VMS\n   static ZCONST char Far local2[] = \" -X  restore owner/ACL protection info\";\n#ifdef MORE\n   static ZCONST char Far local3[] = \"\\\n  -Y  treat \\\".nnn\\\" as \\\";nnn\\\" version         -2  force ODS2 names\\n\\\n  --D restore dir (-D: no) timestamps        -M  pipe through \\\"more\\\" pager\\n\\\n  (Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND.)\\\n\\n\\n\";\n#else\n   static ZCONST char Far local3[] = \"\\n\\\n  -Y  treat \\\".nnn\\\" as \\\";nnn\\\" version         -2  force ODS2 names\\n\\\n  --D restore dir (-D: no) timestamps\\n\\\n  (Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND.)\\\n\\n\\n\";\n#endif\n#else /* !VMS */\n#ifdef ATH_BEO_UNX\n   static ZCONST char Far local2[] = \" -X  restore UID/GID info\";\n#ifdef MORE\n   static ZCONST char Far local3[] = \"\\\n  -K  keep setuid/setgid/tacky permissions   -M  pipe through \\\"more\\\" pager\\n\";\n#else\n   static ZCONST char Far local3[] = \"\\\n  -K  keep setuid/setgid/tacky permissions\\n\";\n#endif\n#else /* !ATH_BEO_UNX */\n#ifdef TANDEM\n   static ZCONST char Far local2[] = \"\\\n -X  restore Tandem User ID                 -r  remove file extensions\\n\\\n  -b  create 'C' (180) text files          \";\n#ifdef MORE\n   static ZCONST char Far local3[] = \" \\\n                                            -M  pipe through \\\"more\\\" pager\\n\";\n#else\n   static ZCONST char Far local3[] = \"\\n\";\n#endif\n#else /* !TANDEM */\n#ifdef AMIGA\n   static ZCONST char Far local2[] = \" -N  restore comments as filenotes\";\n#ifdef MORE\n   static ZCONST char Far local3[] = \" \\\n                                            -M  pipe through \\\"more\\\" pager\\n\";\n#else\n   static ZCONST char Far local3[] = \"\\n\";\n#endif\n#else /* !AMIGA */\n#ifdef MACOS\n   static ZCONST char Far local2[] = \" -E  show Mac info during extraction\";\n   static ZCONST char Far local3[] = \" \\\n -i  ignore filenames in mac extra info     -J  junk (ignore) Mac extra info\\n\\\n\\n\";\n#else /* !MACOS */\n#ifdef MORE\n   static ZCONST char Far local2[] = \" -M  pipe through \\\"more\\\" pager\";\n   static ZCONST char Far local3[] = \"\\n\";\n#else\n   static ZCONST char Far local2[] = \"\";   /* Atari, Mac, CMS/MVS etc. */\n   static ZCONST char Far local3[] = \"\";\n#endif\n#endif /* ?MACOS */\n#endif /* ?AMIGA */\n#endif /* ?TANDEM */\n#endif /* ?ATH_BEO_UNX */\n#endif /* ?VMS */\n#endif /* ?DOS_FLX_OS2_W32 */\n#endif /* !SFX */\n\n#ifndef NO_ZIPINFO\n#ifdef VMS\n   static ZCONST char Far ZipInfoExample[] = \"* or % (e.g., \\\"*font-%.zip\\\")\";\n#else\n   static ZCONST char Far ZipInfoExample[] = \"*, ?, [] (e.g., \\\"[a-j]*.zip\\\")\";\n#endif\n\nstatic ZCONST char Far ZipInfoUsageLine1[] = \"\\\nZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\\n\\\n\\n\\\nList name, date/time, attribute, size, compression method, etc., about files\\n\\\nin list (excluding those in xlist) contained in the specified .zip archive(s).\\\n\\n\\\"file[.zip]\\\" may be a wildcard name containing %s.\\n\\n\\\n   usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\\n\\\n      or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\\n\";\n\nstatic ZCONST char Far ZipInfoUsageLine2[] = \"\\nmain\\\n listing-format options:             -s  short Unix \\\"ls -l\\\" format (def.)\\n\\\n  -1  filenames ONLY, one per line       -m  medium Unix \\\"ls -l\\\" format\\n\\\n  -2  just filenames but allow -h/-t/-z  -l  long Unix \\\"ls -l\\\" format\\n\\\n                                         -v  verbose, multi-page format\\n\";\n\nstatic ZCONST char Far ZipInfoUsageLine3[] = \"miscellaneous options:\\n\\\n  -h  print header line       -t  print totals for listed files or for all\\n\\\n  -z  print zipfile comment   -T  print file times in sortable decimal format\\\n\\n  -C  be case-insensitive   %s\\\n  -x  exclude filenames that follow from listing\\n\";\n#ifdef MORE\n   static ZCONST char Far ZipInfoUsageLine4[] =\n     \"  -M  page output through built-in \\\"more\\\"\\n\";\n#else /* !MORE */\n   static ZCONST char Far ZipInfoUsageLine4[] = \"\";\n#endif /* ?MORE */\n#endif /* !NO_ZIPINFO */\n\n#ifdef BETA\n#  ifdef VMSCLI\n   /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */\n     ZCONST char Far BetaVersion[] = \"%s\\\n        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\\n\\n\";\n#  else\n     static ZCONST char Far BetaVersion[] = \"%s\\\n        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\\n\\n\";\n#  endif\n#endif\n\n#ifdef SFX\n#  ifdef VMSCLI\n   /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */\n     ZCONST char Far UnzipSFXBanner[] =\n#  else\n     static ZCONST char Far UnzipSFXBanner[] =\n#  endif\n     \"UnZipSFX %d.%d%d%s of %s, by Info-ZIP (http://www.info-zip.org).\\n\";\n#  ifdef SFX_EXDIR\n     static ZCONST char Far UnzipSFXOpts[] =\n    \"Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\\n\";\n#  else\n     static ZCONST char Far UnzipSFXOpts[] =\n       \"Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\\n\";\n#  endif\n#else /* !SFX */\n   static ZCONST char Far CompileOptions[] =\n     \"UnZip special compilation options:\\n\";\n   static ZCONST char Far CompileOptFormat[] = \"        %s\\n\";\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n   static ZCONST char Far EnvOptions[] =\n     \"\\nUnZip and ZipInfo environment options:\\n\";\n   static ZCONST char Far EnvOptFormat[] = \"%16s:  %.1024s\\n\";\n#endif\n   static ZCONST char Far None[] = \"[none]\";\n#  ifdef ACORN_FTYPE_NFS\n     static ZCONST char Far AcornFtypeNFS[] = \"ACORN_FTYPE_NFS\";\n#  endif\n#  ifdef ASM_CRC\n     static ZCONST char Far AsmCRC[] = \"ASM_CRC\";\n#  endif\n#  ifdef ASM_INFLATECODES\n     static ZCONST char Far AsmInflateCodes[] = \"ASM_INFLATECODES\";\n#  endif\n#  ifdef CHECK_VERSIONS\n     static ZCONST char Far Check_Versions[] = \"CHECK_VERSIONS\";\n#  endif\n#  ifdef COPYRIGHT_CLEAN\n     static ZCONST char Far Copyright_Clean[] =\n     \"COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)\";\n#  endif\n#  ifdef DEBUG\n     static ZCONST char Far UDebug[] = \"DEBUG\";\n#  endif\n#  ifdef DEBUG_TIME\n     static ZCONST char Far DebugTime[] = \"DEBUG_TIME\";\n#  endif\n#  ifdef DLL\n     static ZCONST char Far Dll[] = \"DLL\";\n#  endif\n#  ifdef DOSWILD\n     static ZCONST char Far DosWild[] = \"DOSWILD\";\n#  endif\n#  ifdef LZW_CLEAN\n     static ZCONST char Far LZW_Clean[] =\n     \"LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)\";\n#  endif\n#  ifndef MORE\n     static ZCONST char Far No_More[] = \"NO_MORE\";\n#  endif\n#  ifdef NO_ZIPINFO\n     static ZCONST char Far No_ZipInfo[] = \"NO_ZIPINFO\";\n#  endif\n#  ifdef NTSD_EAS\n     static ZCONST char Far NTSDExtAttrib[] = \"NTSD_EAS\";\n#  endif\n#  if defined(WIN32) && defined(NO_W32TIMES_IZFIX)\n     static ZCONST char Far W32NoIZTimeFix[] = \"NO_W32TIMES_IZFIX\";\n#  endif\n#  ifdef OLD_THEOS_EXTRA\n     static ZCONST char Far OldTheosExtra[] =\n     \"OLD_THEOS_EXTRA (handle also old Theos port extra field)\";\n#  endif\n#  ifdef OS2_EAS\n     static ZCONST char Far OS2ExtAttrib[] = \"OS2_EAS\";\n#  endif\n#  ifdef QLZIP\n     static ZCONST char Far SMSExFldOnUnix[] = \"QLZIP\";\n#  endif\n#  ifdef REENTRANT\n     static ZCONST char Far Reentrant[] = \"REENTRANT\";\n#  endif\n#  ifdef REGARGS\n     static ZCONST char Far RegArgs[] = \"REGARGS\";\n#  endif\n#  ifdef RETURN_CODES\n     static ZCONST char Far Return_Codes[] = \"RETURN_CODES\";\n#  endif\n#  ifdef SET_DIR_ATTRIB\n     static ZCONST char Far SetDirAttrib[] = \"SET_DIR_ATTRIB\";\n#  endif\n#  ifdef SYMLINKS\n     static ZCONST char Far SymLinkSupport[] =\n     \"SYMLINKS (symbolic links supported, if RTL and file system permit)\";\n#  endif\n#  ifdef TIMESTAMP\n     static ZCONST char Far TimeStamp[] = \"TIMESTAMP\";\n#  endif\n#  ifdef UNIXBACKUP\n     static ZCONST char Far UnixBackup[] = \"UNIXBACKUP\";\n#  endif\n#  ifdef USE_EF_UT_TIME\n     static ZCONST char Far Use_EF_UT_time[] = \"USE_EF_UT_TIME\";\n#  endif\n#  ifndef LZW_CLEAN\n     static ZCONST char Far Use_Unshrink[] =\n     \"USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)\";\n#  endif\n#  ifndef COPYRIGHT_CLEAN\n     static ZCONST char Far Use_Smith_Code[] =\n     \"USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)\";\n#  endif\n#  ifdef USE_DEFLATE64\n     static ZCONST char Far Use_Deflate64[] =\n     \"USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)\";\n#  endif\n#  ifdef UNICODE_SUPPORT\n#   ifdef UTF8_MAYBE_NATIVE\n#    ifdef UNICODE_WCHAR\n       /* direct native UTF-8 check AND charset transform via wchar_t */\n       static ZCONST char Far Use_Unicode[] =\n       \"UNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)\";\n#    else\n       /* direct native UTF-8 check, only */\n       static ZCONST char Far Use_Unicode[] =\n       \"UNICODE_SUPPORT [char coding: %s] (handle UTF-8 paths)\";\n#    endif\n       static ZCONST char Far SysChUTF8[] = \"UTF-8\";\n       static ZCONST char Far SysChOther[] = \"other\";\n#   else /* !UTF8_MAYBE_NATIVE */\n       /* charset transform via wchar_t, no native UTF-8 support */\n       static ZCONST char Far Use_Unicode[] =\n       \"UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths)\";\n#   endif /* ?UTF8_MAYBE_NATIVE */\n#  endif /* UNICODE_SUPPORT */\n#  ifdef _MBCS\n     static ZCONST char Far Have_MBCS_Support[] =\n     \"MBCS-support (multibyte character support, MB_CUR_MAX = %u)\";\n#  endif\n#  ifdef MULT_VOLUME\n     static ZCONST char Far Use_MultiVol[] =\n     \"MULT_VOLUME (multi-volume archives supported)\";\n#  endif\n#  ifdef LARGE_FILE_SUPPORT\n     static ZCONST char Far Use_LFS[] =\n     \"LARGE_FILE_SUPPORT (large files over 2 GiB supported)\";\n#  endif\n#  ifdef ZIP64_SUPPORT\n     static ZCONST char Far Use_Zip64[] =\n     \"ZIP64_SUPPORT (archives using Zip64 for large files supported)\";\n#  endif\n#  if (defined(__DJGPP__) && (__DJGPP__ >= 2))\n#    ifdef USE_DJGPP_ENV\n       static ZCONST char Far Use_DJGPP_Env[] = \"USE_DJGPP_ENV\";\n#    endif\n#    ifdef USE_DJGPP_GLOB\n       static ZCONST char Far Use_DJGPP_Glob[] = \"USE_DJGPP_GLOB\";\n#    endif\n#  endif /* __DJGPP__ && (__DJGPP__ >= 2) */\n#  ifdef USE_VFAT\n     static ZCONST char Far Use_VFAT_support[] = \"USE_VFAT\";\n#  endif\n#  ifdef USE_ZLIB\n     static ZCONST char Far UseZlib[] =\n     \"USE_ZLIB (compiled with version %s; using version %s)\";\n#  endif\n#  ifdef USE_BZIP2\n     static ZCONST char Far UseBZip2[] =\n     \"USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version %s)\";\n#  endif\n#  ifdef VMS_TEXT_CONV\n     static ZCONST char Far VmsTextConv[] = \"VMS_TEXT_CONV\";\n#  endif\n#  ifdef VMSCLI\n     static ZCONST char Far VmsCLI[] = \"VMSCLI\";\n#  endif\n#  ifdef VMSWILD\n     static ZCONST char Far VmsWild[] = \"VMSWILD\";\n#  endif\n#  ifdef WILD_STOP_AT_DIR\n     static ZCONST char Far WildStopAtDir[] = \"WILD_STOP_AT_DIR\";\n#  endif\n#  if CRYPT\n#    ifdef PASSWD_FROM_STDIN\n       static ZCONST char Far PasswdStdin[] = \"PASSWD_FROM_STDIN\";\n#    endif\n     static ZCONST char Far Decryption[] =\n       \"        [decryption, version %d.%d%s of %s]\\n\";\n     static ZCONST char Far CryptDate[] = CR_VERSION_DATE;\n#  endif\n#  ifndef __RSXNT__\n#    ifdef __EMX__\n       static ZCONST char Far EnvEMX[] = \"EMX\";\n       static ZCONST char Far EnvEMXOPT[] = \"EMXOPT\";\n#    endif\n#    if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))\n       static ZCONST char Far EnvGO32[] = \"GO32\";\n       static ZCONST char Far EnvGO32TMP[] = \"GO32TMP\";\n#    endif\n#  endif /* !__RSXNT__ */\n\n#ifdef VMS\n/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */\n   ZCONST char Far UnzipUsageLine1[] = \"\\\nUnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\\n\\n\";\n# ifdef COPYRIGHT_CLEAN\n   static ZCONST char Far UnzipUsageLine1v[] = \"\\\nUnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\\n\\\nbug reports using http://www.info-zip.org/zip-bug.html; see README for details.\\\n\\n\\n\";\n# else\n   static ZCONST char Far UnzipUsageLine1v[] = \"\\\nUnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\\n\\\nSend bug reports using //www.info-zip.org/zip-bug.html; see README for details.\\\n\\n\\n\";\n# endif /* ?COPYRIGHT_CLEAN */\n#else /* !VMS */\n# ifdef COPYRIGHT_CLEAN\n   static ZCONST char Far UnzipUsageLine1[] = \"\\\nUnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\\n\\\nbug reports using http://www.info-zip.org/zip-bug.html; see README for details.\\\n\\n\\n\";\n# else\n   static ZCONST char Far UnzipUsageLine1[] = \"\\\nUnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\\n\\\nSend bug reports using //www.info-zip.org/zip-bug.html; see README for details.\\\n\\n\\n\";\n# endif /* ?COPYRIGHT_CLEAN */\n# define UnzipUsageLine1v       UnzipUsageLine1\n#endif /* ?VMS */\n\nstatic ZCONST char Far UnzipUsageLine2v[] = \"\\\nLatest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\\\n\\nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\\\n\\n\\n\";\n\n#ifdef MACOS\nstatic ZCONST char Far UnzipUsageLine2[] = \"\\\nUsage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\\n \\\n Default action is to extract files in list, to exdir;\\n\\\n  file[.zip] may be a wildcard.  %s\\n\";\n#else /* !MACOS */\n#ifdef VM_CMS\nstatic ZCONST char Far UnzipUsageLine2[] = \"\\\nUsage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\\n \\\n Default action is to extract files in list, except those in xlist, to disk fm;\\\n\\n  file[.zip] may be a wildcard.  %s\\n\";\n#else /* !VM_CMS */\nstatic ZCONST char Far UnzipUsageLine2[] = \"\\\nUsage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\\n \\\n Default action is to extract files in list, except those in xlist, to exdir;\\n\\\n  file[.zip] may be a wildcard.  %s\\n\";\n#endif /* ?VM_CMS */\n#endif /* ?MACOS */\n\n#ifdef NO_ZIPINFO\n#  define ZIPINFO_MODE_OPTION  \"\"\n   static ZCONST char Far ZipInfoMode[] =\n     \"(ZipInfo mode is disabled in this version.)\";\n#else\n#  define ZIPINFO_MODE_OPTION  \"[-Z] \"\n   static ZCONST char Far ZipInfoMode[] =\n     \"-Z => ZipInfo mode (\\\"unzip -Z\\\" for usage).\";\n#endif /* ?NO_ZIPINFO */\n\n#ifdef VMS\n   static ZCONST char Far VMSusageLine2b[] = \"\\\n=> define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\\\n\\n\";\n#endif\n\n#ifdef MACOS\nstatic ZCONST char Far UnzipUsageLine3[] = \"\\n\\\n  -d  extract files into exdir               -l  list files (short format)\\n\\\n  -f  freshen existing files, create none    -t  test compressed archive data\\n\\\n  -u  update files, create if necessary      -z  display archive comment only\\n\\\n  -v  list verbosely/show version info     %s\\n\";\n#else /* !MACOS */\n#ifdef VM_CMS\nstatic ZCONST char Far UnzipUsageLine3[] = \"\\n\\\n  -p  extract files to pipe, no messages     -l  list files (short format)\\n\\\n  -f  freshen existing files, create none    -t  test compressed archive data\\n\\\n  -u  update files, create if necessary      -z  display archive comment only\\n\\\n  -v  list verbosely/show version info     %s\\n\\\n  -x  exclude files that follow (in xlist)   -d  extract files onto disk fm\\n\";\n#else /* !VM_CMS */\nstatic ZCONST char Far UnzipUsageLine3[] = \"\\n\\\n  -p  extract files to pipe, no messages     -l  list files (short format)\\n\\\n  -f  freshen existing files, create none    -t  test compressed archive data\\n\\\n  -u  update files, create if necessary      -z  display archive comment only\\n\\\n  -v  list verbosely/show version info     %s\\n\\\n  -x  exclude files that follow (in xlist)   -d  extract files into exdir\\n\";\n#endif /* ?VM_CMS */\n#endif /* ?MACOS */\n\n/* There is not enough space on a standard 80x25 Windows console screen for\n * the additional line advertising the UTF-8 debugging options. This may\n * eventually also be the case for other ports. Probably, the -U option need\n * not be shown on the introductory screen at all. [Chr. Spieler, 2008-02-09]\n *\n * Likely, other advanced options should be moved to an extended help page and\n * the option to list that page put here.  [E. Gordon, 2008-3-16]\n */\n#if (defined(UNICODE_SUPPORT) && !defined(WIN32))\n#ifdef VMS\nstatic ZCONST char Far UnzipUsageLine4[] = \"\\\nmodifiers:\\n\\\n  -n  never overwrite or make a new version of an existing file\\n\\\n  -o  always make a new version (-oo: overwrite original) of an existing file\\n\\\n  -q  quiet mode (-qq => quieter)            -a  auto-convert any text files\\n\\\n  -j  junk paths (do not make directories)   -aa treat ALL files as text\\n\\\n  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\\n\\\n  -C  match filenames case-insensitively     -L  make (some) names \\\nlowercase\\n %-42s  -V  retain VMS version numbers\\n%s\";\n#else /* !VMS */\nstatic ZCONST char Far UnzipUsageLine4[] = \"\\\nmodifiers:\\n\\\n  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)\\n\\\n  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files\\n\\\n  -j  junk paths (do not make directories)   -aa treat ALL files as text\\n\\\n  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\\n\\\n  -C  match filenames case-insensitively     -L  make (some) names \\\nlowercase\\n %-42s  -V  retain VMS version numbers\\n%s\";\n#endif /* ?VMS */\n#else /* !UNICODE_SUPPORT */\n#ifdef VMS\nstatic ZCONST char Far UnzipUsageLine4[] = \"\\\nmodifiers:\\n\\\n  -n  never overwrite or make a new version of an existing file\\n\\\n  -o  always make a new version (-oo: overwrite original) of an existing file\\n\\\n  -q  quiet mode (-qq => quieter)            -a  auto-convert any text files\\n\\\n  -j  junk paths (do not make directories)   -aa treat ALL files as text\\n\\\n  -C  match filenames case-insensitively     -L  make (some) names \\\nlowercase\\n %-42s  -V  retain VMS version numbers\\n%s\";\n#else /* !VMS */\nstatic ZCONST char Far UnzipUsageLine4[] = \"\\\nmodifiers:\\n\\\n  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)\\n\\\n  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files\\n\\\n  -j  junk paths (do not make directories)   -aa treat ALL files as text\\n\\\n  -C  match filenames case-insensitively     -L  make (some) names \\\nlowercase\\n %-42s  -V  retain VMS version numbers\\n%s\";\n#endif /* ?VMS */\n#endif /* ?UNICODE_SUPPORT */\n\nstatic ZCONST char Far UnzipUsageLine5[] = \"\\\nSee \\\"unzip -hh\\\" or unzip.txt for more help.  Examples:\\n\\\n  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\\n\\\n%s\\\n  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\\n\";\n#endif /* ?SFX */\n\n\n\n\n\n/*****************************/\n/*  main() / UzpMain() stub  */\n/*****************************/\n\nint MAIN(argc, argv)   /* return PK-type error code (except under VMS) */\n    int argc;\n    char *argv[];\n{\n    int r;\n\n    CONSTRUCTGLOBALS();\n    r = unzip(__G__ argc, argv);\n    DESTROYGLOBALS();\n    RETURN(r);\n}\n\n\n\n\n/*******************************/\n/*  Primary UnZip entry point  */\n/*******************************/\n\nint unzip(__G__ argc, argv)\n    __GDEF\n    int argc;\n    char *argv[];\n{\n#ifndef NO_ZIPINFO\n    char *p;\n#endif\n#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))\n    int i;\n#endif\n    int retcode, error=FALSE;\n#ifndef NO_EXCEPT_SIGNALS\n#ifdef REENTRANT\n    savsigs_info *oldsighandlers = NULL;\n#   define SET_SIGHANDLER(sigtype, newsighandler) \\\n      if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \\\n                                      (newsighandler))) > PK_WARN) \\\n          goto cleanup_and_exit\n#else\n#   define SET_SIGHANDLER(sigtype, newsighandler) \\\n      signal((sigtype), (newsighandler))\n#endif\n#endif /* NO_EXCEPT_SIGNALS */\n\n    /* initialize international char support to the current environment */\n    SETLOCALE(LC_CTYPE, \"\");\n\n#ifdef UNICODE_SUPPORT\n    /* see if can use UTF-8 Unicode locale */\n# ifdef UTF8_MAYBE_NATIVE\n    {\n        char *codeset;\n#  if !(defined(NO_NL_LANGINFO) || defined(NO_LANGINFO_H))\n        /* get the codeset (character set encoding) currently used */\n#       include <langinfo.h>\n\n        codeset = nl_langinfo(CODESET);\n#  else /* NO_NL_LANGINFO || NO_LANGINFO_H */\n        /* query the current locale setting for character classification */\n        codeset = setlocale(LC_CTYPE, NULL);\n        if (codeset != NULL) {\n            /* extract the codeset portion of the locale name */\n            codeset = strchr(codeset, '.');\n            if (codeset != NULL) ++codeset;\n        }\n#  endif /* ?(NO_NL_LANGINFO || NO_LANGINFO_H) */\n        /* is the current codeset UTF-8 ? */\n        if ((codeset != NULL) && (strcmp(codeset, \"UTF-8\") == 0)) {\n            /* successfully found UTF-8 char coding */\n            G.native_is_utf8 = TRUE;\n        } else {\n            /* Current codeset is not UTF-8 or cannot be determined. */\n            G.native_is_utf8 = FALSE;\n        }\n        /* Note: At least for UnZip, trying to change the process codeset to\n         *       UTF-8 does not work.  For the example Linux setup of the\n         *       UnZip maintainer, a successful switch to \"en-US.UTF-8\"\n         *       resulted in garbage display of all non-basic ASCII characters.\n         */\n    }\n# endif /* UTF8_MAYBE_NATIVE */\n\n    /* initialize Unicode */\n    G.unicode_escape_all = 0;\n    G.unicode_mismatch = 0;\n\n    G.unipath_version = 0;\n    G.unipath_checksum = 0;\n    G.unipath_filename = NULL;\n#endif /* UNICODE_SUPPORT */\n\n\n#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))\n    extern void DebugMalloc(void);\n\n    atexit(DebugMalloc);\n#endif\n\n#ifdef MALLOC_WORK\n    /* The following (rather complex) expression determines the allocation\n       size of the decompression work area.  It simulates what the\n       combined \"union\" and \"struct\" declaration of the \"static\" work\n       area reservation achieves automatically at compile time.\n       Any decent compiler should evaluate this expression completely at\n       compile time and provide constants to the zcalloc() call.\n       (For better readability, some subexpressions are encapsulated\n       in temporarly defined macros.)\n     */\n#   define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))\n#   define UZ_NUMOF_CHUNKS \\\n      (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \\\n                 (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE)\n    G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);\n#   undef UZ_SLIDE_CHUNK\n#   undef UZ_NUMOF_CHUNKS\n    G.area.shrink.Parent = (shrint *)G.area.Slide;\n    G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE));\n    G.area.shrink.Stack = G.area.Slide +\n                           (sizeof(shrint) + sizeof(uch))*(HSIZE);\n#endif\n\n/*---------------------------------------------------------------------------\n    Set signal handler for restoring echo, warn of zipfile corruption, etc.\n  ---------------------------------------------------------------------------*/\n#ifndef NO_EXCEPT_SIGNALS\n#ifdef SIGINT\n    SET_SIGHANDLER(SIGINT, handler);\n#endif\n#ifdef SIGTERM                 /* some systems really have no SIGTERM */\n    SET_SIGHANDLER(SIGTERM, handler);\n#endif\n#if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC))\n    SET_SIGHANDLER(SIGABRT, handler);\n#endif\n#ifdef SIGBREAK\n    SET_SIGHANDLER(SIGBREAK, handler);\n#endif\n#ifdef SIGBUS\n    SET_SIGHANDLER(SIGBUS, handler);\n#endif\n#ifdef SIGILL\n    SET_SIGHANDLER(SIGILL, handler);\n#endif\n#ifdef SIGSEGV\n    SET_SIGHANDLER(SIGSEGV, handler);\n#endif\n#endif /* NO_EXCEPT_SIGNALS */\n\n#if (defined(WIN32) && defined(__RSXNT__))\n    for (i = 0 ; i < argc; i++) {\n        _ISO_INTERN(argv[i]);\n    }\n#endif\n\n/*---------------------------------------------------------------------------\n    Macintosh initialization code.\n  ---------------------------------------------------------------------------*/\n\n#ifdef MACOS\n    {\n        int a;\n\n        for (a = 0;  a < 4;  ++a)\n            G.rghCursor[a] = GetCursor(a+128);\n        G.giCursor = 0;\n    }\n#endif\n\n/*---------------------------------------------------------------------------\n    NetWare initialization code.\n  ---------------------------------------------------------------------------*/\n\n#ifdef NLM\n    InitUnZipConsole();\n#endif\n\n/*---------------------------------------------------------------------------\n    Acorn RISC OS initialization code.\n  ---------------------------------------------------------------------------*/\n\n#ifdef RISCOS\n    set_prefix();\n#endif\n\n/*---------------------------------------------------------------------------\n    Theos initialization code.\n  ---------------------------------------------------------------------------*/\n\n#ifdef THEOS\n    /* The easiest way found to force creation of libraries when selected\n     * members are to be unzipped. Explicitly add libraries names to the\n     * arguments list before the first member of the library.\n     */\n    if (! _setargv(&argc, &argv)) {\n        Info(slide, 0x401, ((char *)slide, \"cannot process argv\\n\"));\n        retcode = PK_MEM;\n        goto cleanup_and_exit;\n    }\n#endif\n\n/*---------------------------------------------------------------------------\n    Sanity checks.  Commentary by Otis B. Driftwood and Fiorello:\n\n    D:  It's all right.  That's in every contract.  That's what they\n        call a sanity clause.\n\n    F:  Ha-ha-ha-ha-ha.  You can't fool me.  There ain't no Sanity\n        Claus.\n  ---------------------------------------------------------------------------*/\n\n#ifdef DEBUG\n# ifdef LARGE_FILE_SUPPORT\n  /* test if we can support large files - 10/6/04 EG */\n    if (sizeof(zoff_t) < 8) {\n        Info(slide, 0x401, ((char *)slide, \"LARGE_FILE_SUPPORT set but not supported\\n\"));\n        retcode = PK_BADERR;\n        goto cleanup_and_exit;\n    }\n    /* test if we can show 64-bit values */\n    {\n        zoff_t z = ~(zoff_t)0;  /* z should be all 1s now */\n        char *sz;\n\n        sz = FmZofft(z, FZOFFT_HEX_DOT_WID, \"X\");\n        if ((sz[0] != 'F') || (strlen(sz) != 16))\n        {\n            z = 0;\n        }\n\n        /* shift z so only MSB is set */\n        z <<= 63;\n        sz = FmZofft(z, FZOFFT_HEX_DOT_WID, \"X\");\n        if ((sz[0] != '8') || (strlen(sz) != 16))\n        {\n            Info(slide, 0x401, ((char *)slide,\n              \"Can't show 64-bit values correctly\\n\"));\n            retcode = PK_BADERR;\n            goto cleanup_and_exit;\n        }\n    }\n# endif /* LARGE_FILE_SUPPORT */\n\n    /* 2004-11-30 SMS.\n       Test the NEXTBYTE macro for proper operation.\n    */\n    {\n        int test_char;\n        static uch test_buf[2] = { 'a', 'b' };\n\n        G.inptr = test_buf;\n        G.incnt = 1;\n\n        test_char = NEXTBYTE;           /* Should get 'a'. */\n        if (test_char == 'a')\n        {\n            test_char = NEXTBYTE;       /* Should get EOF, not 'b'. */\n        }\n        if (test_char != EOF)\n        {\n            Info(slide, 0x401, ((char *)slide,\n \"NEXTBYTE macro failed.  Try compiling with ALT_NEXTBYTE defined?\"));\n\n            retcode = PK_BADERR;\n            goto cleanup_and_exit;\n        }\n    }\n#endif /* DEBUG */\n\n/*---------------------------------------------------------------------------\n    First figure out if we're running in UnZip mode or ZipInfo mode, and put\n    the appropriate environment-variable options into the queue.  Then rip\n    through any command-line options lurking about...\n  ---------------------------------------------------------------------------*/\n\n#ifdef SFX\n    G.argv0 = argv[0];\n#if (defined(OS2) || defined(WIN32))\n    G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */\n#else\n    G.zipfn = G.argv0;\n#endif\n\n#ifdef VMSCLI\n    {\n        ulg status = vms_unzip_cmdline(&argc, &argv);\n        if (!(status & 1)) {\n            retcode = (int)status;\n            goto cleanup_and_exit;\n        }\n    }\n#endif /* VMSCLI */\n\n    uO.zipinfo_mode = FALSE;\n    error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */\n\n#else /* !SFX */\n\n#ifdef RISCOS\n    /* get the extensions to swap from environment */\n    getRISCOSexts(ENV_UNZIPEXTS);\n#endif\n\n#ifdef MSDOS\n    /* extract MKS extended argument list from environment (before envargs!) */\n    mksargs(&argc, &argv);\n#endif\n\n#ifdef VMSCLI\n    {\n        ulg status = vms_unzip_cmdline(&argc, &argv);\n        if (!(status & 1)) {\n            retcode = (int)status;\n            goto cleanup_and_exit;\n        }\n    }\n#endif /* VMSCLI */\n\n    G.noargs = (argc == 1);   /* no options, no zipfile, no anything */\n\n#ifndef NO_ZIPINFO\n    for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {\n        if (*p == DIR_END\n#ifdef DIR_END2\n            || *p == DIR_END2\n#endif\n           )\n            break;\n    }\n    ++p;\n\n#ifdef THEOS\n    if (strncmp(p, \"ZIPINFO.\",8) == 0 || strstr(p, \".ZIPINFO:\") != NULL ||\n        strncmp(p, \"II.\",3) == 0 || strstr(p, \".II:\") != NULL ||\n#else\n    if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||\n        STRNICMP(p, \"ii\", 2) == 0 ||\n#endif\n        (argc > 1 && strncmp(argv[1], \"-Z\", 2) == 0))\n    {\n        uO.zipinfo_mode = TRUE;\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),\n                             LoadFarStringSmall2(EnvZipInfo2))) != PK_OK)\n            perror(LoadFarString(NoMemEnvArguments));\n#endif\n    } else\n#endif /* !NO_ZIPINFO */\n    {\n        uO.zipinfo_mode = FALSE;\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),\n                             LoadFarStringSmall2(EnvUnZip2))) != PK_OK)\n            perror(LoadFarString(NoMemEnvArguments));\n#endif\n    }\n\n    if (!error) {\n        /* Check the length of all passed command line parameters.\n         * Command arguments might get sent through the Info() message\n         * system, which uses the sliding window area as string buffer.\n         * As arguments may additionally get fed through one of the FnFilter\n         * macros, we require all command line arguments to be shorter than\n         * WSIZE/4 (and ca. 2 standard line widths for fixed message text).\n         */\n        for (i = 1 ; i < argc; i++) {\n           if (strlen(argv[i]) > ((WSIZE>>2) - 160)) {\n               Info(slide, 0x401, ((char *)slide,\n                 LoadFarString(CmdLineParamTooLong), i));\n               retcode = PK_PARAM;\n               goto cleanup_and_exit;\n           }\n        }\n#ifndef NO_ZIPINFO\n        if (uO.zipinfo_mode)\n            error = zi_opts(__G__ &argc, &argv);\n        else\n#endif /* !NO_ZIPINFO */\n            error = uz_opts(__G__ &argc, &argv);\n    }\n\n#endif /* ?SFX */\n\n    if ((argc < 0) || error) {\n        retcode = error;\n        goto cleanup_and_exit;\n    }\n\n/*---------------------------------------------------------------------------\n    Now get the zipfile name from the command line and then process any re-\n    maining options and file specifications.\n  ---------------------------------------------------------------------------*/\n\n#ifdef DOS_FLX_H68_NLM_OS2_W32\n    /* convert MSDOS-style 'backward slash' directory separators to Unix-style\n     * 'forward slashes' for user's convenience (include zipfile name itself)\n     */\n#ifdef SFX\n    for (G.pfnames = argv, i = argc;  i > 0;  --i) {\n#else\n    /* argc does not include the zipfile specification */\n    for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {\n#endif\n#ifdef __human68k__\n        extern char *_toslash(char *);\n        _toslash(*G.pfnames);\n#else /* !__human68k__ */\n        char *q = *G.pfnames;\n\n        while (*q != '\\0') {\n            if (*q == '\\\\')\n                *q = '/';\n            INCSTR(q);\n        }\n#endif /* ?__human68k__ */\n        ++G.pfnames;\n    }\n#endif /* DOS_FLX_H68_NLM_OS2_W32 */\n\n#ifndef SFX\n    G.wildzipfn = *argv++;\n#endif\n\n#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */\n\n    G.filespecs = argc;\n    G.xfilespecs = 0;\n\n    if (argc > 0) {\n        char **pp = argv-1;\n\n        G.pfnames = argv;\n        while (*++pp)\n            if (strcmp(*pp, \"-x\") == 0) {\n                if (pp > argv) {\n                    *pp = 0;              /* terminate G.pfnames */\n                    G.filespecs = pp - G.pfnames;\n                } else {\n                    G.pfnames = (char **)fnames;  /* defaults */\n                    G.filespecs = 0;\n                }\n                G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */\n                G.xfilespecs = argc - G.filespecs - 1;\n                break;                    /* skip rest of args */\n            }\n        G.process_all_files = FALSE;\n    } else\n        G.process_all_files = TRUE;      /* for speed */\n\n#else /* !SFX || SFX_EXDIR */             /* check for -x or -d */\n\n    G.filespecs = argc;\n    G.xfilespecs = 0;\n\n    if (argc > 0) {\n        int in_files=FALSE, in_xfiles=FALSE;\n        char **pp = argv-1;\n\n        G.process_all_files = FALSE;\n        G.pfnames = argv;\n        while (*++pp) {\n            Trace((stderr, \"pp - argv = %d\\n\", pp-argv));\n#ifdef CMS_MVS\n            if (!uO.exdir && STRNICMP(*pp, \"-d\", 2) == 0) {\n#else\n            if (!uO.exdir && strncmp(*pp, \"-d\", 2) == 0) {\n#endif\n                int firstarg = (pp == argv);\n\n                uO.exdir = (*pp) + 2;\n                if (in_files) {      /* ... zipfile ... -d exdir ... */\n                    *pp = (char *)NULL;         /* terminate G.pfnames */\n                    G.filespecs = pp - G.pfnames;\n                    in_files = FALSE;\n                } else if (in_xfiles) {\n                    *pp = (char *)NULL;         /* terminate G.pxnames */\n                    G.xfilespecs = pp - G.pxnames;\n                    /* \"... -x xlist -d exdir\":  nothing left */\n                }\n                /* first check for \"-dexdir\", then for \"-d exdir\" */\n                if (*uO.exdir == '\\0') {\n                    if (*++pp)\n                        uO.exdir = *pp;\n                    else {\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(MustGiveExdir)));\n                        /* don't extract here by accident */\n                        retcode = PK_PARAM;\n                        goto cleanup_and_exit;\n                    }\n                }\n                if (firstarg) { /* ... zipfile -d exdir ... */\n                    if (pp[1]) {\n                        G.pfnames = pp + 1;  /* argv+2 */\n                        G.filespecs = argc - (G.pfnames-argv);  /* for now... */\n                    } else {\n                        G.process_all_files = TRUE;\n                        G.pfnames = (char **)fnames;  /* GRR: necessary? */\n                        G.filespecs = 0;     /* GRR: necessary? */\n                        break;\n                    }\n                }\n            } else if (!in_xfiles) {\n                if (strcmp(*pp, \"-x\") == 0) {\n                    in_xfiles = TRUE;\n                    if (pp == G.pfnames) {\n                        G.pfnames = (char **)fnames;  /* defaults */\n                        G.filespecs = 0;\n                    } else if (in_files) {\n                        *pp = 0;                   /* terminate G.pfnames */\n                        G.filespecs = pp - G.pfnames;  /* adjust count */\n                        in_files = FALSE;\n                    }\n                    G.pxnames = pp + 1; /* excluded-names ptr starts after -x */\n                    G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */\n                } else\n                    in_files = TRUE;\n            }\n        }\n    } else\n        G.process_all_files = TRUE;      /* for speed */\n\n    if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */\n        Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));\n#endif /* ?(SFX && !SFX_EXDIR) */\n\n#ifdef UNICODE_SUPPORT\n    /* set Unicode-escape-all if option -U used */\n    if (uO.U_flag == 1)\n# ifdef UNICODE_WCHAR\n        G.unicode_escape_all = TRUE;\n# else\n        Info(slide, 0x401, ((char *)slide, LoadFarString(UTF8EscapeUnSupp)));\n# endif\n#endif\n\n\n/*---------------------------------------------------------------------------\n    Okey dokey, we have everything we need to get started.  Let's roll.\n  ---------------------------------------------------------------------------*/\n\n    retcode = process_zipfiles(__G);\n\ncleanup_and_exit:\n#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\n    /* restore all signal handlers back to their state at function entry */\n    while (oldsighandlers != NULL) {\n        savsigs_info *thissigsav = oldsighandlers;\n\n        signal(thissigsav->sigtype, thissigsav->sighandler);\n        oldsighandlers = thissigsav->previous;\n        free(thissigsav);\n    }\n#endif\n#if (defined(MALLOC_WORK) && !defined(REENTRANT))\n    if (G.area.Slide != (uch *)NULL) {\n        free(G.area.Slide);\n        G.area.Slide = (uch *)NULL;\n    }\n#endif\n#if (defined(MSDOS) && !defined(SFX) && !defined(WINDLL))\n    if (retcode != PK_OK)\n        check_for_windows(\"UnZip\");\n#endif\n    return(retcode);\n\n} /* end main()/unzip() */\n\n\n\n\n\n#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))\n/*******************************/\n/* Function setsignalhandler() */\n/*******************************/\n\nstatic int setsignalhandler(__G__ p_savedhandler_chain, signal_type,\n                            newhandler)\n    __GDEF\n    savsigs_info **p_savedhandler_chain;\n    int signal_type;\n    void (*newhandler)(int);\n{\n    savsigs_info *savsig;\n\n    savsig = malloc(sizeof(savsigs_info));\n    if (savsig == NULL) {\n        /* error message and break */\n        Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler)));\n        return PK_MEM;\n    }\n    savsig->sigtype = signal_type;\n    savsig->sighandler = signal(SIGINT, newhandler);\n    if (savsig->sighandler == SIG_ERR) {\n        free(savsig);\n    } else {\n        savsig->previous = *p_savedhandler_chain;\n        *p_savedhandler_chain = savsig;\n    }\n    return PK_OK;\n\n} /* end function setsignalhandler() */\n\n#endif /* REENTRANT && !NO_EXCEPT_SIGNALS */\n\n\n\n\n\n/**********************/\n/* Function uz_opts() */\n/**********************/\n\nint uz_opts(__G__ pargc, pargv)\n    __GDEF\n    int *pargc;\n    char ***pargv;\n{\n    char **argv, *s;\n    int argc, c, error=FALSE, negative=0, showhelp=0;\n\n\n    argc = *pargc;\n    argv = *pargv;\n\n    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {\n        s = *argv + 1;\n        while ((c = *s++) != 0) {    /* \"!= 0\":  prevent Turbo C warning */\n#ifdef CMS_MVS\n            switch (tolower(c))\n#else\n            switch (c)\n#endif\n            {\n                case ('-'):\n                    ++negative;\n                    break;\n#ifdef RISCOS\n                case ('/'):\n                    if (negative) {   /* negative not allowed with -/ swap */\n                        Info(slide, 0x401, ((char *)slide,\n                          \"error:  must give extensions list\"));\n                        return(PK_PARAM);  /* don't extract here by accident */\n                    }\n                    exts2swap = s; /* override Unzip$Exts */\n                    s += strlen(s);\n                    break;\n#endif\n                case ('a'):\n                    if (negative) {\n                        uO.aflag = MAX(uO.aflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.aflag;\n                    break;\n#if (defined(DLL) && defined(API_DOC))\n                case ('A'):    /* extended help for API */\n                    APIhelp(__G__ argc, argv);\n                    *pargc = -1;  /* signal to exit successfully */\n                    return 0;\n#endif\n                case ('b'):\n                    if (negative) {\n#if (defined(TANDEM) || defined(VMS))\n                        uO.bflag = MAX(uO.bflag-negative,0);\n#endif\n                        negative = 0;   /* do nothing:  \"-b\" is default */\n                    } else {\n#ifdef VMS\n                        if (uO.aflag == 0)\n                           ++uO.bflag;\n#endif\n#ifdef TANDEM\n                        ++uO.bflag;\n#endif\n                        uO.aflag = 0;\n                    }\n                    break;\n#ifdef UNIXBACKUP\n                case ('B'): /* -B: back up existing files */\n                    if (negative)\n                        uO.B_flag = FALSE, negative = 0;\n                    else\n                        uO.B_flag = TRUE;\n                    break;\n#endif\n                case ('c'):\n                    if (negative) {\n                        uO.cflag = FALSE, negative = 0;\n#ifdef NATIVE\n                        uO.aflag = 0;\n#endif\n                    } else {\n                        uO.cflag = TRUE;\n#ifdef NATIVE\n                        uO.aflag = 2;   /* so you can read it on the screen */\n#endif\n#ifdef DLL\n                        if (G.redirect_text)\n                            G.redirect_data = 2;\n#endif\n                    }\n                    break;\n#ifndef CMS_MVS\n                case ('C'):    /* -C:  match filenames case-insensitively */\n                    if (negative)\n                        uO.C_flag = FALSE, negative = 0;\n                    else\n                        uO.C_flag = TRUE;\n                    break;\n#endif /* !CMS_MVS */\n#if (!defined(SFX) || defined(SFX_EXDIR))\n                case ('d'):\n                    if (negative) {   /* negative not allowed with -d exdir */\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(MustGiveExdir)));\n                        return(PK_PARAM);  /* don't extract here by accident */\n                    }\n                    if (uO.exdir != (char *)NULL) {\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(OnlyOneExdir)));\n                        return(PK_PARAM);    /* GRR:  stupid restriction? */\n                    } else {\n                        /* first check for \"-dexdir\", then for \"-d exdir\" */\n                        uO.exdir = s;\n                        if (*uO.exdir == '\\0') {\n                            if (argc > 1) {\n                                --argc;\n                                uO.exdir = *++argv;\n                                if (*uO.exdir == '-') {\n                                    Info(slide, 0x401, ((char *)slide,\n                                      LoadFarString(MustGiveExdir)));\n                                    return(PK_PARAM);\n                                }\n                                /* else uO.exdir points at extraction dir */\n                            } else {\n                                Info(slide, 0x401, ((char *)slide,\n                                  LoadFarString(MustGiveExdir)));\n                                return(PK_PARAM);\n                            }\n                        }\n                        /* uO.exdir now points at extraction dir (-dexdir or\n                         *  -d exdir); point s at end of exdir to avoid mis-\n                         *  interpretation of exdir characters as more options\n                         */\n                        if (*s != 0)\n                            while (*++s != 0)\n                                ;\n                    }\n                    break;\n#endif /* !SFX || SFX_EXDIR */\n#if (!defined(NO_TIMESTAMPS))\n                case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */\n                    if (negative) {\n                        uO.D_flag = MAX(uO.D_flag-negative,0);\n                        negative = 0;\n                    } else\n                        uO.D_flag++;\n                    break;\n#endif /* (!NO_TIMESTAMPS) */\n                case ('e'):    /* just ignore -e, -x options (extract) */\n                    break;\n#ifdef MACOS\n                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */\n                    if( negative ) {\n                        uO.E_flag = FALSE, negative = 0;\n                    } else {\n                        uO.E_flag = TRUE;\n                    }\n                    break;\n#endif /* MACOS */\n                case ('f'):    /* \"freshen\" (extract only newer files) */\n                    if (negative)\n                        uO.fflag = uO.uflag = FALSE, negative = 0;\n                    else\n                        uO.fflag = uO.uflag = TRUE;\n                    break;\n#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n                case ('F'):    /* Acorn filetype & NFS extension handling */\n                    if (negative)\n                        uO.acorn_nfs_ext = FALSE, negative = 0;\n                    else\n                        uO.acorn_nfs_ext = TRUE;\n                    break;\n#endif /* RISCOS || ACORN_FTYPE_NFS */\n                case ('h'):    /* just print help message and quit */\n                    if (showhelp == 0) {\n#ifndef SFX\n                        if (*s == 'h')\n                            showhelp = 2;\n                        else\n#endif /* !SFX */\n                        {\n                            showhelp = 1;\n                        }\n                    }\n                    break;\n#ifdef MACOS\n                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */\n                    if( negative ) {\n                        uO.i_flag = FALSE, negative = 0;\n                    } else {\n                        uO.i_flag = TRUE;\n                    }\n                    break;\n#endif  /* MACOS */\n                case ('j'):    /* junk pathnames/directory structure */\n                    if (negative)\n                        uO.jflag = FALSE, negative = 0;\n                    else\n                        uO.jflag = TRUE;\n                    break;\n#if (defined(ATH_BEO) || defined(MACOS))\n                case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */\n                    if( negative ) {\n                        uO.J_flag = FALSE, negative = 0;\n                    } else {\n                        uO.J_flag = TRUE;\n                    }\n                    break;\n#endif /* ATH_BEO || MACOS */\n#ifdef ATH_BEO_UNX\n                case ('K'):\n                    if (negative) {\n                        uO.K_flag = FALSE, negative = 0;\n                    } else {\n                        uO.K_flag = TRUE;\n                    }\n                    break;\n#endif /* ATH_BEO_UNX */\n#ifndef SFX\n                case ('l'):\n                    if (negative) {\n                        uO.vflag = MAX(uO.vflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.vflag;\n                    break;\n#endif /* !SFX */\n#ifndef CMS_MVS\n                case ('L'):    /* convert (some) filenames to lowercase */\n                    if (negative) {\n                        uO.L_flag = MAX(uO.L_flag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.L_flag;\n                    break;\n#endif /* !CMS_MVS */\n#ifdef MORE\n#ifdef CMS_MVS\n                case ('m'):\n#endif\n                case ('M'):    /* send all screen output through \"more\" fn. */\n/* GRR:  eventually check for numerical argument => height */\n                    if (negative)\n                        G.M_flag = FALSE, negative = 0;\n                    else\n                        G.M_flag = TRUE;\n                    break;\n#endif /* MORE */\n                case ('n'):    /* don't overwrite any files */\n                    if (negative)\n                        uO.overwrite_none = FALSE, negative = 0;\n                    else\n                        uO.overwrite_none = TRUE;\n                    break;\n#ifdef AMIGA\n                case ('N'):    /* restore comments as filenotes */\n                    if (negative)\n                        uO.N_flag = FALSE, negative = 0;\n                    else\n                        uO.N_flag = TRUE;\n                    break;\n#endif /* AMIGA */\n                case ('o'):    /* OK to overwrite files without prompting */\n                    if (negative) {\n                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.overwrite_all;\n                    break;\n                case ('p'):    /* pipes:  extract to stdout, no messages */\n                    if (negative) {\n                        uO.cflag = FALSE;\n                        uO.qflag = MAX(uO.qflag-999,0);\n                        negative = 0;\n                    } else {\n                        uO.cflag = TRUE;\n                        uO.qflag += 999;\n                    }\n                    break;\n#if CRYPT\n                /* GRR:  yes, this is highly insecure, but dozens of people\n                 * have pestered us for this, so here we go... */\n                case ('P'):\n                    if (negative) {   /* negative not allowed with -P passwd */\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(MustGivePasswd)));\n                        return(PK_PARAM);  /* don't extract here by accident */\n                    }\n                    if (uO.pwdarg != (char *)NULL) {\n/*\n                        GRR:  eventually support multiple passwords?\n                        Info(slide, 0x401, ((char *)slide,\n                          LoadFarString(OnlyOnePasswd)));\n                        return(PK_PARAM);\n */\n                    } else {\n                        /* first check for \"-Ppasswd\", then for \"-P passwd\" */\n                        uO.pwdarg = s;\n                        if (*uO.pwdarg == '\\0') {\n                            if (argc > 1) {\n                                --argc;\n                                uO.pwdarg = *++argv;\n                                if (*uO.pwdarg == '-') {\n                                    Info(slide, 0x401, ((char *)slide,\n                                      LoadFarString(MustGivePasswd)));\n                                    return(PK_PARAM);\n                                }\n                                /* else pwdarg points at decryption password */\n                            } else {\n                                Info(slide, 0x401, ((char *)slide,\n                                  LoadFarString(MustGivePasswd)));\n                                return(PK_PARAM);\n                            }\n                        }\n                        /* pwdarg now points at decryption password (-Ppasswd or\n                         *  -P passwd); point s at end of passwd to avoid mis-\n                         *  interpretation of passwd characters as more options\n                         */\n                        if (*s != 0)\n                            while (*++s != 0)\n                                ;\n                    }\n                    break;\n#endif /* CRYPT */\n                case ('q'):    /* quiet:  fewer comments/messages */\n                    if (negative) {\n                        uO.qflag = MAX(uO.qflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.qflag;\n                    break;\n#ifdef QDOS\n                case ('Q'):   /* QDOS flags */\n                    qlflag ^= strtol(s, &s, 10);\n                    break;    /* we XOR this as we can config qlflags */\n#endif\n#ifdef TANDEM\n                case ('r'):    /* remove file extensions */\n                    if (negative)\n                        uO.rflag = FALSE, negative = 0;\n                    else\n                        uO.rflag = TRUE;\n                    break;\n#endif /* TANDEM */\n#ifdef DOS_FLX_NLM_OS2_W32\n                case ('s'):    /* spaces in filenames:  allow by default */\n                    if (negative)\n                        uO.sflag = FALSE, negative = 0;\n                    else\n                        uO.sflag = TRUE;\n                    break;\n#endif /* DOS_FLX_NLM_OS2_W32 */\n#ifdef VMS\n                /* VMS:  extract \"text\" files in Stream_LF format (-a[a]) */\n                case ('S'):\n                    if (negative)\n                        uO.S_flag = FALSE, negative = 0;\n                    else\n                        uO.S_flag = TRUE;\n                    break;\n#endif /* VMS */\n                case ('t'):\n                    if (negative)\n                        uO.tflag = FALSE, negative = 0;\n                    else\n                        uO.tflag = TRUE;\n                    break;\n#ifdef TIMESTAMP\n                case ('T'):\n                    if (negative)\n                        uO.T_flag = FALSE, negative = 0;\n                    else\n                        uO.T_flag = TRUE;\n                    break;\n#endif\n                case ('u'):    /* update (extract only new and newer files) */\n                    if (negative)\n                        uO.uflag = FALSE, negative = 0;\n                    else\n                        uO.uflag = TRUE;\n                    break;\n#ifdef UNICODE_SUPPORT\n                case ('U'):    /* escape UTF-8, or disable UTF-8 support */\n                    if (negative) {\n                        uO.U_flag = MAX(uO.U_flag-negative,0);\n                        negative = 0;\n                    } else\n                        uO.U_flag++;\n                    break;\n#else /* !UNICODE_SUPPORT */\n#ifndef CMS_MVS\n                case ('U'):    /* obsolete; to be removed in version 6.0 */\n                    if (negative)\n                        uO.L_flag = TRUE, negative = 0;\n                    else\n                        uO.L_flag = FALSE;\n                    break;\n#endif /* !CMS_MVS */\n#endif /* ?UNICODE_SUPPORT */\n#ifndef SFX\n                case ('v'):    /* verbose */\n                    if (negative) {\n                        uO.vflag = MAX(uO.vflag-negative,0);\n                        negative = 0;\n                    } else if (uO.vflag)\n                        ++uO.vflag;\n                    else\n                        uO.vflag = 2;\n                    break;\n#endif /* !SFX */\n#ifndef CMS_MVS\n                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */\n                    if (negative)\n                        uO.V_flag = FALSE, negative = 0;\n                    else\n                        uO.V_flag = TRUE;\n                    break;\n#endif /* !CMS_MVS */\n#ifdef WILD_STOP_AT_DIR\n                case ('W'):    /* Wildcard interpretation (stop at '/'?) */\n                    if (negative)\n                        uO.W_flag = FALSE, negative = 0;\n                    else\n                        uO.W_flag = TRUE;\n                    break;\n#endif /* WILD_STOP_AT_DIR */\n                case ('x'):    /* extract:  default */\n#ifdef SFX\n                    /* when 'x' is the only option in this argument, and the\n                     * next arg is not an option, assume this initiates an\n                     * exclusion list (-x xlist):  terminate option-scanning\n                     * and leave uz_opts with argv still pointing to \"-x\";\n                     * the xlist is processed later\n                     */\n                    if (s - argv[0] == 2 && *s == '\\0' &&\n                        argc > 1 && argv[1][0] != '-') {\n                        /* break out of nested loops without \"++argv;--argc\" */\n                        goto opts_done;\n                    }\n#endif /* SFX */\n                    break;\n#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))\n                case ('X'):   /* restore owner/protection info (need privs?) */\n                    if (negative) {\n                        uO.X_flag = MAX(uO.X_flag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.X_flag;\n                    break;\n#endif /* RESTORE_UIDGID || RESTORE_ACL */\n#ifdef VMS\n                case ('Y'):    /* Treat \".nnn\" as \";nnn\" version. */\n                    if (negative)\n                        uO.Y_flag = FALSE, negative = 0;\n                    else\n                        uO.Y_flag = TRUE;\n                    break;\n#endif /* VMS */\n                case ('z'):    /* display only the archive comment */\n                    if (negative) {\n                        uO.zflag = MAX(uO.zflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.zflag;\n                    break;\n#ifndef SFX\n                case ('Z'):    /* should have been first option (ZipInfo) */\n                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));\n                    error = TRUE;\n                    break;\n#endif /* !SFX */\n#ifdef VMS\n                case ('2'):    /* Force ODS2-compliant names. */\n                    if (negative)\n                        uO.ods2_flag = FALSE, negative = 0;\n                    else\n                        uO.ods2_flag = TRUE;\n                    break;\n#endif /* VMS */\n#ifdef DOS_H68_OS2_W32\n                case ('$'):\n                    if (negative) {\n                        uO.volflag = MAX(uO.volflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.volflag;\n                    break;\n#endif /* DOS_H68_OS2_W32 */\n#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))\n                case (':'):    /* allow \"parent dir\" path components */\n                    if (negative) {\n                        uO.ddotflag = MAX(uO.ddotflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.ddotflag;\n                    break;\n#endif /* !RISCOS && !CMS_MVS && !TANDEM */\n#ifdef UNIX\n                case ('^'):    /* allow control chars in filenames */\n                    if (negative) {\n                        uO.cflxflag = MAX(uO.cflxflag-negative,0);\n                        negative = 0;\n                    } else\n                        ++uO.cflxflag;\n                    break;\n#endif /* UNIX */\n                default:\n                    error = TRUE;\n                    break;\n\n            } /* end switch */\n        } /* end while (not end of argument string) */\n    } /* end while (not done with switches) */\n\n/*---------------------------------------------------------------------------\n    Check for nonsensical combinations of options.\n  ---------------------------------------------------------------------------*/\n\n#ifdef SFX\nopts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */\n#endif\n\n    if (showhelp > 0) {         /* just print help message and quit */\n        *pargc = -1;\n#ifndef SFX\n        if (showhelp == 2) {\n            help_extended(__G);\n            return PK_OK;\n        } else\n#endif /* !SFX */\n        {\n            return USAGE(PK_OK);\n        }\n    }\n\n    if ((uO.cflag && (uO.tflag || uO.uflag)) ||\n        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))\n    {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));\n        error = TRUE;\n    }\n    if (uO.aflag > 2)\n        uO.aflag = 2;\n#ifdef VMS\n    if (uO.bflag > 2)\n        uO.bflag = 2;\n    /* Clear -s flag when converting text files. */\n    if (uO.aflag <= 0)\n        uO.S_flag = 0;\n#endif /* VMS */\n    if (uO.overwrite_all && uO.overwrite_none) {\n        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));\n        uO.overwrite_all = FALSE;\n    }\n#ifdef MORE\n    if (G.M_flag && !isatty(1))  /* stdout redirected: \"more\" func. useless */\n        G.M_flag = 0;\n#endif\n\n#ifdef SFX\n    if (error)\n#else\n    if ((argc-- == 0) || error)\n#endif\n    {\n        *pargc = argc;\n        *pargv = argv;\n#ifndef SFX\n        if (uO.vflag >= 2 && argc == -1) {              /* \"unzip -v\" */\n            show_version_info(__G);\n            return PK_OK;\n        }\n        if (!G.noargs && !error)\n            error = TRUE;       /* had options (not -h or -v) but no zipfile */\n#endif /* !SFX */\n        return USAGE(error);\n    }\n\n#ifdef SFX\n    /* print our banner unless we're being fairly quiet */\n    if (uO.qflag < 2)\n        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),\n          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          LoadFarStringSmall(VersionDate)));\n#ifdef BETA\n    /* always print the beta warning:  no unauthorized distribution!! */\n    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), \"\\n\",\n      \"SFX\"));\n#endif\n#endif /* SFX */\n\n    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag\n#ifdef TIMESTAMP\n                                                     || uO.T_flag\n#endif\n                                                                 )\n        G.extract_flag = FALSE;\n    else\n        G.extract_flag = TRUE;\n\n    *pargc = argc;\n    *pargv = argv;\n    return PK_OK;\n\n} /* end function uz_opts() */\n\n\n\n\n/********************/\n/* Function usage() */\n/********************/\n\n#ifdef SFX\n#  ifdef VMS\n#    define LOCAL \"X.\\n\\\n(Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND.)\"\n#  endif\n#  ifdef UNIX\n#    define LOCAL \"X\"\n#  endif\n#  ifdef DOS_OS2_W32\n#    define LOCAL \"s$\"\n#  endif\n#  if (defined(FLEXOS) || defined(NLM))\n#    define LOCAL \"s\"\n#  endif\n#  ifdef AMIGA\n#    define LOCAL \"N\"\n#  endif\n   /* Default for all other systems: */\n#  ifndef LOCAL\n#    define LOCAL \"\"\n#  endif\n\n#  ifndef NO_TIMESTAMP\n#    ifdef MORE\n#      define SFXOPT1 \"DM\"\n#    else\n#      define SFXOPT1 \"D\"\n#    endif\n#  else\n#    ifdef MORE\n#      define SFXOPT1 \"M\"\n#    else\n#      define SFXOPT1 \"\"\n#    endif\n#  endif\n\nint usage(__G__ error)   /* return PK-type error code */\n    __GDEF\n    int error;\n{\n    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),\n      UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n      LoadFarStringSmall(VersionDate)));\n    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),\n      SFXOPT1, LOCAL));\n#ifdef BETA\n    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), \"\\n\",\n      \"SFX\"));\n#endif\n\n    if (error)\n        return PK_PARAM;\n    else\n        return PK_COOL;     /* just wanted usage screen: no error */\n\n} /* end function usage() */\n\n\n\n\n\n#else /* !SFX */\n#  ifdef VMS\n#    define QUOT '\\\"'\n#    define QUOTS \"\\\"\"\n#  else\n#    define QUOT ' '\n#    define QUOTS \"\"\n#  endif\n\nint usage(__G__ error)   /* return PK-type error code */\n    __GDEF\n    int error;\n{\n    int flag = (error? 1 : 0);\n\n\n/*---------------------------------------------------------------------------\n    Print either ZipInfo usage or UnZip usage, depending on incantation.\n    (Strings must be no longer than 512 bytes for Turbo C, apparently.)\n  ---------------------------------------------------------------------------*/\n\n    if (uO.zipinfo_mode) {\n\n#ifndef NO_ZIPINFO\n\n        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),\n          ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          LoadFarStringSmall(VersionDate),\n          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));\n        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));\n        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),\n          LoadFarStringSmall(ZipInfoUsageLine4)));\n#ifdef VMS\n        Info(slide, flag, ((char *)slide, \"\\n\\\nYou must quote non-lowercase options and filespecs, unless SET PROC/PARSE=EXT.\\\n\\n\"));\n#endif\n\n#endif /* !NO_ZIPINFO */\n\n    } else {   /* UnZip mode */\n\n        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),\n          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          LoadFarStringSmall(VersionDate)));\n#ifdef BETA\n        Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), \"\", \"\"));\n#endif\n\n        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),\n          ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));\n#ifdef VMS\n        if (!error)  /* maybe no command-line tail found; show extra help */\n            Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));\n#endif\n\n        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),\n          LoadFarStringSmall(local1)));\n\n        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),\n          LoadFarStringSmall(local2), LoadFarStringSmall2(local3)));\n\n        /* This is extra work for SMALL_MEM, but it will work since\n         * LoadFarStringSmall2 uses the same buffer.  Remember, this\n         * is a hack. */\n        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),\n          LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),\n          LoadFarStringSmall2(Example3)));\n\n    } /* end if (uO.zipinfo_mode) */\n\n    if (error)\n        return PK_PARAM;\n    else\n        return PK_COOL;     /* just wanted usage screen: no error */\n\n} /* end function usage() */\n\n#endif /* ?SFX */\n\n\n\n\n#ifndef SFX\n\n/* Print extended help to stdout. */\nstatic void help_extended(__G)\n    __GDEF\n{\n    extent i;             /* counter for help array */\n\n    /* help array */\n    static ZCONST char *text[] = {\n  \"\",\n  \"Extended Help for UnZip\",\n  \"\",\n  \"See the UnZip Manual for more detailed help\",\n  \"\",\n  \"\",\n  \"UnZip lists and extracts files in zip archives.  The default action is to\",\n  \"extract zipfile entries to the current directory, creating directories as\",\n  \"needed.  With appropriate options, UnZip lists the contents of archives\",\n  \"instead.\",\n  \"\",\n  \"Basic unzip command line:\",\n  \"  unzip [-Z] options archive[.zip] [file ...] [-x xfile ...] [-d exdir]\",\n  \"\",\n  \"Some examples:\",\n  \"  unzip -l foo.zip        - list files in short format in archive foo.zip\",\n  \"\",\n  \"  unzip -t foo            - test the files in archive foo\",\n  \"\",\n  \"  unzip -Z foo            - list files using more detailed zipinfo format\",\n  \"\",\n  \"  unzip foo               - unzip the contents of foo in current dir\",\n  \"\",\n  \"  unzip -a foo            - unzip foo and convert text files to local OS\",\n  \"\",\n  \"If unzip is run in zipinfo mode, a more detailed list of archive contents\",\n  \"is provided.  The -Z option sets zipinfo mode and changes the available\",\n  \"options.\",\n  \"\",\n  \"Basic zipinfo command line:\",\n  \"  zipinfo options archive[.zip] [file ...] [-x xfile ...]\",\n  \"  unzip -Z options archive[.zip] [file ...] [-x xfile ...]\",\n  \"\",\n  \"Below, Mac OS refers to Mac OS before Mac OS X.  Mac OS X is a Unix based\",\n  \"port and is referred to as Unix Apple.\",\n  \"\",\n  \"\",\n  \"unzip options:\",\n  \"  -Z   Switch to zipinfo mode.  Must be first option.\",\n  \"  -hh  Display extended help.\",\n  \"  -A   [OS/2, Unix DLL] Print extended help for DLL.\",\n  \"  -c   Extract files to stdout/screen.  As -p but include names.  Also,\",\n  \"         -a allowed and EBCDIC conversions done if needed.\",\n  \"  -f   Freshen by extracting only if older file on disk.\",\n  \"  -l   List files using short form.\",\n  \"  -p   Extract files to pipe (stdout).  Only file data is output and all\",\n  \"         files extracted in binary mode (as stored).\",\n  \"  -t   Test archive files.\",\n  \"  -T   Set timestamp on archive(s) to that of newest file.  Similar to\",\n  \"       zip -o but faster.\",\n  \"  -u   Update existing older files on disk as -f and extract new files.\",\n  \"  -v   Use verbose list format.  If given alone as unzip -v show version\",\n  \"         information.  Also can be added to other list commands for more\",\n  \"         verbose output.\",\n  \"  -z   Display only archive comment.\",\n  \"\",\n  \"unzip modifiers:\",\n  \"  -a   Convert text files to local OS format.  Convert line ends, EOF\",\n  \"         marker, and from or to EBCDIC character set as needed.\",\n  \"  -b   Treat all files as binary.  [Tandem] Force filecode 180 ('C').\",\n  \"         [VMS] Autoconvert binary files.  -bb forces convert of all files.\",\n  \"  -B   [UNIXBACKUP compile option enabled] Save a backup copy of each\",\n  \"         overwritten file in foo~ or foo~99999 format.\",\n  \"  -C   Use case-insensitive matching.\",\n  \"  -D   Skip restoration of timestamps for extracted directories.  On VMS this\",\n  \"         is on by default and -D essentially becames -DD.\",\n  \"  -DD  Skip restoration of timestamps for all entries.\",\n  \"  -E   [MacOS (not Unix Apple)]  Display contents of MacOS extra field during\",\n  \"         restore.\",\n  \"  -F   [Acorn] Suppress removal of NFS filetype extension.  [Non-Acorn if\",\n  \"         ACORN_FTYPE_NFS] Translate filetype and append to name.\",\n  \"  -i   [MacOS] Ignore filenames in MacOS extra field.  Instead, use name in\",\n  \"         standard header.\",\n  \"  -j   Junk paths and deposit all files in extraction directory.\",\n  \"  -J   [BeOS] Junk file attributes.  [MacOS] Ignore MacOS specific info.\",\n  \"  -K   [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.\",\n  \"  -L   Convert to lowercase any names from uppercase only file system.\",\n  \"  -LL  Convert all files to lowercase.\",\n  \"  -M   Pipe all output through internal pager similar to Unix more(1).\",\n  \"  -n   Never overwrite existing files.  Skip extracting that file, no prompt.\",\n  \"  -N   [Amiga] Extract file comments as Amiga filenotes.\",\n  \"  -o   Overwrite existing files without prompting.  Useful with -f.  Use with\",\n  \"         care.\",\n  \"  -P p Use password p to decrypt files.  THIS IS INSECURE!  Some OS show\",\n  \"         command line to other users.\",\n  \"  -q   Perform operations quietly.  The more q (as in -qq) the quieter.\",\n  \"  -s   [OS/2, NT, MS-DOS] Convert spaces in filenames to underscores.\",\n  \"  -S   [VMS] Convert text files (-a, -aa) into Stream_LF format.\",\n  \"  -U   [UNICODE enabled] Show non-local characters as #Uxxxx or #Lxxxxxx ASCII\",\n  \"         text escapes where x is hex digit.  [Old] -U used to leave names\",\n  \"         uppercase if created on MS-DOS, VMS, etc.  See -L.\",\n  \"  -UU  [UNICODE enabled] Disable use of stored UTF-8 paths.  Note that UTF-8\",\n  \"         paths stored as native local paths are still processed as Unicode.\",\n  \"  -V   Retain VMS file version numbers.\",\n  \"  -W   [Only if WILD_STOP_AT_DIR] Modify pattern matching so ? and * do not\",\n  \"         match directory separator /, but ** does.  Allows matching at specific\",\n  \"         directory levels.\",\n  \"  -X   [VMS, Unix, OS/2, NT, Tandem] Restore UICs and ACL entries under VMS,\",\n  \"         or UIDs/GIDs under Unix, or ACLs under certain network-enabled\",\n  \"         versions of OS/2, or security ACLs under Windows NT.  Can require\",\n  \"         user privileges.\",\n  \"  -XX  [NT] Extract NT security ACLs after trying to enable additional\",\n  \"         system privileges.\",\n  \"  -Y   [VMS] Treat archived name endings of .nnn as VMS version numbers.\",\n  \"  -$   [MS-DOS, OS/2, NT] Restore volume label if extraction medium is\",\n  \"         removable.  -$$ allows fixed media (hard drives) to be labeled.\",\n  \"  -/ e [Acorn] Use e as extension list.\",\n  \"  -:   [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into\",\n  \"         locations outside of current extraction root folder.  This allows\",\n  \"         paths such as ../foo to be extracted above the current extraction\",\n  \"         directory, which can be a security problem.\",\n  \"  -^   [Unix] Allow control characters in names of extracted entries.  Usually\",\n  \"         this is not a good thing and should be avoided.\",\n  \"  -2   [VMS] Force unconditional conversion of names to ODS-compatible names.\",\n  \"         Default is to exploit destination file system, preserving cases and\",\n  \"         extended name characters on ODS5 and applying ODS2 filtering on ODS2.\",\n  \"\",\n  \"\",\n  \"Wildcards:\",\n  \"  Internally unzip supports the following wildcards:\",\n  \"    ?       (or %% or #, depending on OS) matches any single character\",\n  \"    *       matches any number of characters, including zero\",\n  \"    [list]  matches char in list (regex), can do range [ac-f], all but [!bf]\",\n  \"  If port supports [], must escape [ as [[]\",\n  \"  For shells that expand wildcards, escape (\\\\* or \\\"*\\\") so unzip can recurse.\",\n  \"\",\n  \"Include and Exclude:\",\n  \"  -i pattern pattern ...   include files that match a pattern\",\n  \"  -x pattern pattern ...   exclude files that match a pattern\",\n  \"  Patterns are paths with optional wildcards and match paths as stored in\",\n  \"  archive.  Exclude and include lists end at next option or end of line.\",\n  \"    unzip archive -x pattern pattern ...\",\n  \"\",\n  \"Multi-part (split) archives (archives created as a set of split files):\",\n  \"  Currently split archives are not readable by unzip.  A workaround is\",\n  \"  to use zip to convert the split archive to a single-file archive and\",\n  \"  use unzip on that.  See the manual page for Zip 3.0 or later.\",\n  \"\",\n  \"Streaming (piping into unzip):\",\n  \"  Currently unzip does not support streaming.  The funzip utility can be\",\n  \"  used to process the first entry in a stream.\",\n  \"    cat archive | funzip\",\n  \"\",\n  \"Testing archives:\",\n  \"  -t        test contents of archive\",\n  \"  This can be modified using -q for quieter operation, and -qq for even\",\n  \"  quieter operation.\",\n  \"\",\n  \"Unicode:\",\n  \"  If compiled with Unicode support, unzip automatically handles archives\",\n  \"  with Unicode entries.  Currently Unicode on Win32 systems is limited.\",\n  \"  Characters not in the current character set are shown as ASCII escapes\",\n  \"  in the form #Uxxxx where the Unicode character number fits in 16 bits,\",\n  \"  or #Lxxxxxx where it doesn't, where x is the ASCII character for a hex\",\n  \"  digit.\",\n  \"\",\n  \"\",\n  \"zipinfo options (these are used in zipinfo mode (unzip -Z ...)):\",\n  \"  -1  List names only, one per line.  No headers/trailers.  Good for scripts.\",\n  \"  -2  List names only as -1, but include headers, trailers, and comments.\",\n  \"  -s  List archive entries in short Unix ls -l format.  Default list format.\",\n  \"  -m  List in long Unix ls -l format.  As -s, but includes compression %.\",\n  \"  -l  List in long Unix ls -l format.  As -m, but compression in bytes.\",\n  \"  -v  List zipfile information in verbose, multi-page format.\",\n  \"  -h  List header line.  Includes archive name, actual size, total files.\",\n  \"  -M  Pipe all output through internal pager similar to Unix more(1) command.\",\n  \"  -t  List totals for files listed or for all files.  Includes uncompressed\",\n  \"        and compressed sizes, and compression factors.\",\n  \"  -T  Print file dates and times in a sortable decimal format (yymmdd.hhmmss)\",\n  \"        Default date and time format is a more human-readable version.\",\n  \"  -U  [UNICODE] If entry has a UTF-8 Unicode path, display any characters\",\n  \"        not in current character set as text #Uxxxx and #Lxxxxxx escapes\",\n  \"        representing the Unicode character number of the character in hex.\",\n  \"  -UU [UNICODE]  Disable use of any UTF-8 path information.\",\n  \"  -z  Include archive comment if any in listing.\",\n  \"\",\n  \"\",\n  \"funzip stream extractor:\",\n  \"  funzip extracts the first member in an archive to stdout.  Typically\",\n  \"  used to unzip the first member of a stream or pipe.  If a file argument\",\n  \"  is given, read from that file instead of stdin.\",\n  \"\",\n  \"funzip command line:\",\n  \"  funzip [-password] [input[.zip|.gz]]\",\n  \"\",\n  \"\",\n  \"unzipsfx self extractor:\",\n  \"  Self-extracting archives made with unzipsfx are no more (or less)\",\n  \"  portable across different operating systems than unzip executables.\",\n  \"  In general, a self-extracting archive made on a particular Unix system,\",\n  \"  for example, will only self-extract under the same flavor of Unix.\",\n  \"  Regular unzip may still be used to extract embedded archive however.\",\n  \"\",\n  \"unzipsfx command line:\",\n  \"  <unzipsfx+archive_filename>  [-options] [file(s) ... [-x xfile(s) ...]]\",\n  \"\",\n  \"unzipsfx options:\",\n  \"  -c, -p - Output to pipe.  (See above for unzip.)\",\n  \"  -f, -u - Freshen and Update, as for unzip.\",\n  \"  -t     - Test embedded archive.  (Can be used to list contents.)\",\n  \"  -z     - Print archive comment.  (See unzip above.)\",\n  \"\",\n  \"unzipsfx modifiers:\",\n  \"  Most unzip modifiers are supported.  These include\",\n  \"  -a     - Convert text files.\",\n  \"  -n     - Never overwrite.\",\n  \"  -o     - Overwrite without prompting.\",\n  \"  -q     - Quiet operation.\",\n  \"  -C     - Match names case-insensitively.\",\n  \"  -j     - Junk paths.\",\n  \"  -V     - Keep version numbers.\",\n  \"  -s     - Convert spaces to underscores.\",\n  \"  -$     - Restore volume label.\",\n  \"\",\n  \"If unzipsfx compiled with SFX_EXDIR defined, -d option also available:\",\n  \"  -d exd - Extract to directory exd.\",\n  \"By default, all files extracted to current directory.  This option\",\n  \"forces extraction to specified directory.\",\n  \"\",\n  \"See unzipsfx manual page for more information.\",\n  \"\"\n    };\n\n    for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n    {\n        Info(slide, 0, ((char *)slide, \"%s\\n\", text[i]));\n    }\n} /* end function help_extended() */\n\n\n\n\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n#if (!defined(MODERN) || defined(NO_STDLIB_H))\n/* Declare getenv() to be sure (might be missing in some environments) */\nextern char *getenv();\n#endif\n#endif\n\n/********************************/\n/* Function show_version_info() */\n/********************************/\n\nstatic void show_version_info(__G)\n    __GDEF\n{\n    if (uO.qflag > 3)                           /* \"unzip -vqqqq\" */\n        Info(slide, 0, ((char *)slide, \"%d\\n\",\n          (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL)));\n    else {\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n        char *envptr;\n#endif\n        int numopts = 0;\n\n        Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),\n          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          LoadFarStringSmall(VersionDate)));\n        Info(slide, 0, ((char *)slide,\n          LoadFarString(UnzipUsageLine2v)));\n        version(__G);\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));\n#ifdef ACORN_FTYPE_NFS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(AcornFtypeNFS)));\n        ++numopts;\n#endif\n#ifdef ASM_CRC\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(AsmCRC)));\n        ++numopts;\n#endif\n#ifdef ASM_INFLATECODES\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(AsmInflateCodes)));\n        ++numopts;\n#endif\n#ifdef CHECK_VERSIONS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Check_Versions)));\n        ++numopts;\n#endif\n#ifdef COPYRIGHT_CLEAN\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Copyright_Clean)));\n        ++numopts;\n#endif\n#ifdef DEBUG\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(UDebug)));\n        ++numopts;\n#endif\n#ifdef DEBUG_TIME\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(DebugTime)));\n        ++numopts;\n#endif\n#ifdef DLL\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Dll)));\n        ++numopts;\n#endif\n#ifdef DOSWILD\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(DosWild)));\n        ++numopts;\n#endif\n#ifdef LZW_CLEAN\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(LZW_Clean)));\n        ++numopts;\n#endif\n#ifndef MORE\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(No_More)));\n        ++numopts;\n#endif\n#ifdef NO_ZIPINFO\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(No_ZipInfo)));\n        ++numopts;\n#endif\n#ifdef NTSD_EAS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(NTSDExtAttrib)));\n        ++numopts;\n#endif\n#if defined(WIN32) && defined(NO_W32TIMES_IZFIX)\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(W32NoIZTimeFix)));\n        ++numopts;\n#endif\n#ifdef OLD_THEOS_EXTRA\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(OldTheosExtra)));\n        ++numopts;\n#endif\n#ifdef OS2_EAS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(OS2ExtAttrib)));\n        ++numopts;\n#endif\n#ifdef QLZIP\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(SMSExFldOnUnix)));\n        ++numopts;\n#endif\n#ifdef REENTRANT\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Reentrant)));\n        ++numopts;\n#endif\n#ifdef REGARGS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(RegArgs)));\n        ++numopts;\n#endif\n#ifdef RETURN_CODES\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Return_Codes)));\n        ++numopts;\n#endif\n#ifdef SET_DIR_ATTRIB\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(SetDirAttrib)));\n        ++numopts;\n#endif\n#ifdef SYMLINKS\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(SymLinkSupport)));\n        ++numopts;\n#endif\n#ifdef TIMESTAMP\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(TimeStamp)));\n        ++numopts;\n#endif\n#ifdef UNIXBACKUP\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(UnixBackup)));\n        ++numopts;\n#endif\n#ifdef USE_EF_UT_TIME\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_EF_UT_time)));\n        ++numopts;\n#endif\n#ifndef COPYRIGHT_CLEAN\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_Smith_Code)));\n        ++numopts;\n#endif\n#ifndef LZW_CLEAN\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_Unshrink)));\n        ++numopts;\n#endif\n#ifdef USE_DEFLATE64\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_Deflate64)));\n        ++numopts;\n#endif\n#ifdef UNICODE_SUPPORT\n# ifdef UTF8_MAYBE_NATIVE\n        sprintf((char *)(slide+256), LoadFarStringSmall(Use_Unicode),\n          LoadFarStringSmall2(G.native_is_utf8 ? SysChUTF8 : SysChOther));\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          (char *)(slide+256)));\n# else\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_Unicode)));\n# endif\n        ++numopts;\n#endif\n#ifdef _MBCS\n        sprintf((char *)(slide+256), LoadFarStringSmall(Have_MBCS_Support),\n          (unsigned int)MB_CUR_MAX);\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          (char *)(slide+256)));\n        ++numopts;\n#endif\n#ifdef MULT_VOLUME\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_MultiVol)));\n        ++numopts;\n#endif\n#ifdef LARGE_FILE_SUPPORT\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_LFS)));\n        ++numopts;\n#endif\n#ifdef ZIP64_SUPPORT\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_Zip64)));\n        ++numopts;\n#endif\n#if (defined(__DJGPP__) && (__DJGPP__ >= 2))\n#  ifdef USE_DJGPP_ENV\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_DJGPP_Env)));\n        ++numopts;\n#  endif\n#  ifdef USE_DJGPP_GLOB\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_DJGPP_Glob)));\n        ++numopts;\n#  endif\n#endif /* __DJGPP__ && (__DJGPP__ >= 2) */\n#ifdef USE_VFAT\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(Use_VFAT_support)));\n        ++numopts;\n#endif\n#ifdef USE_ZLIB\n        sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),\n          ZLIB_VERSION, zlibVersion());\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          (char *)(slide+256)));\n        ++numopts;\n#endif\n#ifdef USE_BZIP2\n        sprintf((char *)(slide+256), LoadFarStringSmall(UseBZip2),\n          BZ2_bzlibVersion());\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          (char *)(slide+256)));\n        ++numopts;\n#endif\n#ifdef VMS_TEXT_CONV\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(VmsTextConv)));\n        ++numopts;\n#endif\n#ifdef VMSCLI\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(VmsCLI)));\n        ++numopts;\n#endif\n#ifdef VMSWILD\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(VmsWild)));\n        ++numopts;\n#endif\n#ifdef WILD_STOP_AT_DIR\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(WildStopAtDir)));\n        ++numopts;\n#endif\n#if CRYPT\n# ifdef PASSWD_FROM_STDIN\n        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),\n          LoadFarStringSmall(PasswdStdin)));\n# endif\n        Info(slide, 0, ((char *)slide, LoadFarString(Decryption),\n          CR_MAJORVER, CR_MINORVER, CR_BETA_VER,\n          LoadFarStringSmall(CryptDate)));\n        ++numopts;\n#endif /* CRYPT */\n        if (numopts == 0)\n            Info(slide, 0, ((char *)slide,\n              LoadFarString(CompileOptFormat),\n              LoadFarStringSmall(None)));\n\n#ifndef _WIN32_WCE /* Win CE does not support environment variables */\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));\n        envptr = getenv(LoadFarStringSmall(EnvUnZip));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvUnZip),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n        envptr = getenv(LoadFarStringSmall(EnvUnZip2));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvUnZip2),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n        envptr = getenv(LoadFarStringSmall(EnvZipInfo));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvZipInfo),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n        envptr = getenv(LoadFarStringSmall(EnvZipInfo2));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvZipInfo2),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n#ifndef __RSXNT__\n#ifdef __EMX__\n        envptr = getenv(LoadFarStringSmall(EnvEMX));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvEMX),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n        envptr = getenv(LoadFarStringSmall(EnvEMXOPT));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvEMXOPT),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n#endif /* __EMX__ */\n#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))\n        envptr = getenv(LoadFarStringSmall(EnvGO32));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvGO32),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n        envptr = getenv(LoadFarStringSmall(EnvGO32TMP));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvGO32TMP),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n#endif /* __GO32__ && !(__DJGPP__ >= 2) */\n#endif /* !__RSXNT__ */\n#ifdef RISCOS\n        envptr = getenv(LoadFarStringSmall(EnvUnZipExts));\n        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),\n          LoadFarStringSmall(EnvUnZipExts),\n          (envptr == (char *)NULL || *envptr == 0)?\n          LoadFarStringSmall2(None) : envptr));\n#endif /* RISCOS */\n#endif /* !_WIN32_WCE */\n    }\n} /* end function show_version() */\n\n#endif /* !SFX */\n#endif /* !WINDLL */\n"
  },
  {
    "path": "deps/infozip/unzip60/unzip.h",
    "content": "/*---------------------------------------------------------------------------\n\n  unzip.h (new)\n\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  This header file contains the public macros and typedefs required by\n  both the UnZip sources and by any application using the UnZip API.  If\n  UNZIP_INTERNAL is defined, it includes unzpriv.h (containing includes,\n  prototypes and extern variables used by the actual UnZip sources).\n\n  ---------------------------------------------------------------------------*/\n/*---------------------------------------------------------------------------\nThis is version 2009-Jan-02 of the Info-ZIP license.\nThe definitive version of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and\na copy at http://www.info-zip.org/pub/infozip/license.html.\n\n\nCopyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n\n   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n   Rich Wales, Mike White.\n\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held liable\nfor any direct, indirect, incidental, special or consequential damages\narising out of the use of or inability to use this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  Additional documentation is not needed\n       for executables where a command line license option provides these and\n       a note regarding this option is in the executable's startup banner.  The\n       sole exception to this condition is redistribution of a standard\n       UnZipSFX binary (including SFXWiz) as part of a self-extracting archive;\n       that is permitted without inclusion of this license, as long as the\n       normal SFX banner has not been removed from the binary or disabled.\n\n    3. Altered versions--including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP--must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases--including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n\n    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"\n       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its\n       own source and binary releases.\n  ---------------------------------------------------------------------------*/\n\n#ifndef __unzip_h   /* prevent multiple inclusions */\n#define __unzip_h\n\n/*---------------------------------------------------------------------------\n    Predefined, machine-specific macros.\n  ---------------------------------------------------------------------------*/\n\n#ifdef __GO32__                 /* MS-DOS extender:  NOT Unix */\n#  ifdef unix\n#    undef unix\n#  endif\n#  ifdef _unix\n#    undef _unix\n#  endif\n#  ifdef __unix\n#    undef __unix\n#  endif\n#  ifdef __unix__\n#    undef __unix__\n#  endif\n#endif\n\n#if ((defined(__convex__) || defined(__convexc__)) && !defined(CONVEX))\n#  define CONVEX\n#endif\n\n#if (defined(unix) || defined(_unix) || defined(__unix) || defined(__unix__))\n#  ifndef UNIX\n#    define UNIX\n#  endif\n#endif /* unix || _unix || __unix || __unix__ */\n#if (defined(M_XENIX) || defined(COHERENT) || defined(__hpux))\n#  ifndef UNIX\n#    define UNIX\n#  endif\n#endif /* M_XENIX || COHERENT || __hpux */\n#if (defined(__NetBSD__) || defined(__FreeBSD__))\n#  ifndef UNIX\n#    define UNIX\n#  endif\n#endif /* __NetBSD__ || __FreeBSD__ */\n#if (defined(CONVEX) || defined(MINIX) || defined(_AIX) || defined(__QNX__))\n#  ifndef UNIX\n#    define UNIX\n#  endif\n#endif /* CONVEX || MINIX || _AIX || __QNX__ */\n\n#if (defined(VM_CMS) || defined(MVS))\n#  define CMS_MVS\n#endif\n\n#if (defined(__OS2__) && !defined(OS2))\n#  define OS2\n#endif\n\n#if (defined(__TANDEM) && !defined(TANDEM))\n#  define TANDEM\n#endif\n\n#if (defined(__VMS) && !defined(VMS))\n#  define VMS\n#endif\n\n#if ((defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32))\n#  define WIN32\n#endif\n#if ((defined(__WINNT__) || defined(__WINNT)) && !defined(WIN32))\n#  define WIN32\n#endif\n\n#if defined(_WIN32_WCE)\n#  ifndef WIN32         /* WinCE is treated as a variant of the Win32 API */\n#    define WIN32\n#  endif\n#  ifndef UNICODE       /* WinCE requires UNICODE wide character support */\n#    define UNICODE\n#  endif\n#endif\n\n#ifdef __COMPILER_KCC__\n#  include <c-env.h>\n#  ifdef SYS_T20\n#    define TOPS20\n#  endif\n#endif /* __COMPILER_KCC__ */\n\n/* Borland C does not define __TURBOC__ if compiling for a 32-bit platform */\n#ifdef __BORLANDC__\n#  ifndef __TURBOC__\n#    define __TURBOC__\n#  endif\n#  if (!defined(__MSDOS__) && !defined(OS2) && !defined(WIN32))\n#    define __MSDOS__\n#  endif\n#endif\n\n/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */\n#ifdef __POWERC\n#  define __TURBOC__\n#  define MSDOS\n#endif /* __POWERC */\n\n#if (defined(__MSDOS__) && !defined(MSDOS))   /* just to make sure */\n#  define MSDOS\n#endif\n\n/* RSXNTDJ (at least up to v1.3) compiles for WIN32 (RSXNT) using a derivate\n   of the EMX environment, but defines MSDOS and __GO32__. ARG !!! */\n#if (defined(MSDOS) && defined(WIN32))\n#  undef MSDOS                  /* WIN32 is >>>not<<< MSDOS */\n#endif\n#if (defined(__GO32__) && defined(__EMX__) && defined(__RSXNT__))\n#  undef __GO32__\n#endif\n\n#if (defined(linux) && !defined(LINUX))\n#  define LINUX\n#endif\n\n#ifdef __riscos\n#  define RISCOS\n#endif\n\n#if (defined(THINK_C) || defined(MPW))\n#  define MACOS\n#endif\n#if (defined(__MWERKS__) && defined(macintosh))\n#  define MACOS\n#endif\n\n/* use prototypes and ANSI libraries if __STDC__, or MS-DOS, or OS/2, or Win32,\n * or IBM C Set/2, or Borland C, or Watcom C, or GNU gcc (emx or Cygwin),\n * or Macintosh, or Sequent, or Atari, or IBM RS/6000, or Silicon Graphics,\n * or Convex?, or AtheOS, or BeOS.\n */\n#if (defined(__STDC__) || defined(MSDOS) || defined(OS2) || defined(WIN32))\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n#if (defined(__IBMC__) || defined(__BORLANDC__) || defined(__WATCOMC__))\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n#if (defined(__EMX__) || defined(__CYGWIN__))\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n#if (defined(MACOS) || defined(ATARI_ST) || defined(RISCOS) || defined(THEOS))\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n/* Sequent running Dynix/ptx:  non-modern compiler */\n#if (defined(_AIX) || defined(sgi) || (defined(_SEQUENT_) && !defined(PTX)))\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n#if (defined(CMS_MVS) || defined(__ATHEOS__) || defined(__BEOS__))\n/* || defined(CONVEX) ? */\n#  ifndef PROTO\n#    define PROTO\n#  endif\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n/* Bundled C compiler on HP-UX needs this.  Others shouldn't care. */\n#if (defined(__hpux))\n#  ifndef MODERN\n#    define MODERN\n#  endif\n#endif\n\n/* turn off prototypes if requested */\n#if (defined(NOPROTO) && defined(PROTO))\n#  undef PROTO\n#endif\n\n/* used to remove arguments in function prototypes for non-ANSI C */\n#ifdef PROTO\n#  define OF(a) a\n#else\n#  define OF(a) ()\n#endif\n\n/* enable the \"const\" keyword only if MODERN and if not otherwise instructed */\n#ifdef MODERN\n#  if (!defined(ZCONST) && (defined(USE_CONST) || !defined(NO_CONST)))\n#    define ZCONST const\n#  endif\n#endif\n\n#ifndef ZCONST\n#  define ZCONST\n#endif\n\n/* Tell Microsoft Visual C++ 2005 (and newer) to leave us alone\n * and let us use standard C functions the way we're supposed to.\n * (These preprocessor symbols must appear before the first system\n *  header include. They are located here, because for WINDLL the\n *  first system header includes follow just below.)\n */\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#  ifndef _CRT_SECURE_NO_WARNINGS\n#    define _CRT_SECURE_NO_WARNINGS\n#  endif\n#  ifndef _CRT_NONSTDC_NO_WARNINGS\n#    define _CRT_NONSTDC_NO_WARNINGS\n#  endif\n#  if defined(POCKET_UNZIP) && !defined(_CRT_NON_CONFORMING_SWPRINTFS)\n#    define _CRT_NON_CONFORMING_SWPRINTFS\n#  endif\n#endif\n\n/* NO_UNIXBACKUP overrides UNIXBACKUP */\n#if defined(NO_UNIXBACKUP) && defined(UNIXBACKUP)\n#  undef UNIXBACKUP\n#endif\n\n/*---------------------------------------------------------------------------\n    Grab system-specific public include headers.\n  ---------------------------------------------------------------------------*/\n\n#ifdef POCKET_UNZIP             /* WinCE port */\n#  include \"wince/punzip.h\"     /* must appear before windows.h */\n#endif\n\n#ifdef WINDLL\n   /* for UnZip, the \"basic\" part of the win32 api is sufficient */\n#  ifndef WIN32_LEAN_AND_MEAN\n#    define WIN32_LEAN_AND_MEAN\n#    define IZ_HASDEFINED_WIN32LEAN\n#  endif\n#  include <windows.h>\n#  include \"windll/structs.h\"\n#  ifdef IZ_HASDEFINED_WIN32LEAN\n#    undef WIN32_LEAN_AND_MEAN\n#    undef IZ_HASDEFINED_WIN32LEAN\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    Grab system-dependent definition of EXPENTRY for prototypes below.\n  ---------------------------------------------------------------------------*/\n\n#if 0\n#if (defined(OS2) && !defined(FUNZIP))\n#  ifdef UNZIP_INTERNAL\n#    define INCL_NOPM\n#    define INCL_DOSNLS\n#    define INCL_DOSPROCESS\n#    define INCL_DOSDEVICES\n#    define INCL_DOSDEVIOCTL\n#    define INCL_DOSERRORS\n#    define INCL_DOSMISC\n#    ifdef OS2DLL\n#      define INCL_REXXSAA\n#      include <rexxsaa.h>\n#    endif\n#  endif /* UNZIP_INTERNAL */\n#  include <os2.h>\n#  define UZ_EXP EXPENTRY\n#endif /* OS2 && !FUNZIP */\n#endif /* 0 */\n\n#if (defined(OS2) && !defined(FUNZIP))\n#  if (defined(__IBMC__) || defined(__WATCOMC__))\n#    define UZ_EXP  _System    /* compiler keyword */\n#  else\n#    define UZ_EXP\n#  endif\n#endif /* OS2 && !FUNZIP */\n\n#if (defined(WINDLL) || defined(USE_UNZIP_LIB))\n#  ifndef EXPENTRY\n#    define UZ_EXP WINAPI\n#  else\n#    define UZ_EXP EXPENTRY\n#  endif\n#endif\n\n#ifndef UZ_EXP\n#  define UZ_EXP\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*---------------------------------------------------------------------------\n    Public typedefs.\n  ---------------------------------------------------------------------------*/\n\n#ifndef _IZ_TYPES_DEFINED\n#ifdef MODERN\n   typedef void zvoid;\n#else /* !MODERN */\n#  ifndef AOS_VS         /* mostly modern? */\n#    ifndef VAXC         /* not fully modern, but has knows 'void' */\n#      define void int\n#    endif /* !VAXC */\n#  endif /* !AOS_VS */\n   typedef char zvoid;\n#endif /* ?MODERN */\ntypedef unsigned char   uch;    /* code assumes unsigned bytes; these type-  */\ntypedef unsigned short  ush;    /*  defs replace byte/UWORD/ULONG (which are */\ntypedef unsigned long   ulg;    /*  predefined on some systems) & match zip  */\n#define _IZ_TYPES_DEFINED\n#endif /* !_IZ_TYPES_DEFINED */\n\n/* InputFn is not yet used and is likely to change: */\n#ifdef PROTO\n   typedef int   (UZ_EXP MsgFn)     (zvoid *pG, uch *buf, ulg size, int flag);\n   typedef int   (UZ_EXP InputFn)   (zvoid *pG, uch *buf, int *size, int flag);\n   typedef void  (UZ_EXP PauseFn)   (zvoid *pG, ZCONST char *prompt, int flag);\n   typedef int   (UZ_EXP PasswdFn)  (zvoid *pG, int *rcnt, char *pwbuf,\n                                     int size, ZCONST char *zfn,\n                                     ZCONST char *efn);\n   typedef int   (UZ_EXP StatCBFn)  (zvoid *pG, int fnflag, ZCONST char *zfn,\n                                     ZCONST char *efn, ZCONST zvoid *details);\n   typedef void  (UZ_EXP UsrIniFn)  (void);\n#else /* !PROTO */\n   typedef int   (UZ_EXP MsgFn)     ();\n   typedef int   (UZ_EXP InputFn)   ();\n   typedef void  (UZ_EXP PauseFn)   ();\n   typedef int   (UZ_EXP PasswdFn)  ();\n   typedef int   (UZ_EXP StatCBFn)  ();\n   typedef void  (UZ_EXP UsrIniFn)  ();\n#endif /* ?PROTO */\n\ntypedef struct _UzpBuffer {    /* rxstr */\n    ulg   strlength;           /* length of string */\n    char  *strptr;             /* pointer to string */\n} UzpBuffer;\n\ntypedef struct _UzpInit {\n    ulg structlen;             /* length of the struct being passed */\n\n    /* GRR: can we assume that each of these is a 32-bit pointer?  if not,\n     * does it matter? add \"far\" keyword to make sure? */\n    MsgFn *msgfn;\n    InputFn *inputfn;\n    PauseFn *pausefn;\n    UsrIniFn *userfn;          /* user init function to be called after */\n                               /*  globals constructed and initialized */\n\n    /* pointer to program's environment area or something? */\n    /* hooks for performance testing? */\n    /* hooks for extra unzip -v output? (detect CPU or other hardware?) */\n    /* anything else?  let me (Greg) know... */\n} UzpInit;\n\ntypedef struct _UzpCB {\n    ulg structlen;             /* length of the struct being passed */\n    /* GRR: can we assume that each of these is a 32-bit pointer?  if not,\n     * does it matter? add \"far\" keyword to make sure? */\n    MsgFn *msgfn;\n    InputFn *inputfn;\n    PauseFn *pausefn;\n    PasswdFn *passwdfn;\n    StatCBFn *statrepfn;\n} UzpCB;\n\n/* the collection of general UnZip option flags and option arguments */\ntypedef struct _UzpOpts {\n#ifndef FUNZIP\n    char *exdir;        /* pointer to extraction root directory (-d option) */\n    char *pwdarg;       /* pointer to command-line password (-P option) */\n    int zipinfo_mode;   /* behave like ZipInfo or like normal UnZip? */\n    int aflag;          /* -a: do ASCII-EBCDIC and/or end-of-line translation */\n#ifdef VMS\n    int bflag;          /* -b: force fixed record format for binary files */\n#endif\n#ifdef TANDEM\n    int bflag;          /* -b: create text files in 'C' format (180)*/\n#endif\n#if defined(UNIX) || defined(OS2) || defined(WIN32)\n    int B_flag;         /* -B: back up existing files by renaming to *~##### */\n#else\n#ifdef UNIXBACKUP\n    int B_flag;         /* -B: back up existing files by renaming to *~##### */\n#endif\n#endif\n    int cflag;          /* -c: output to stdout */\n    int C_flag;         /* -C: match filenames case-insensitively */\n    int D_flag;         /* -D: don't restore directory (-DD: any) timestamps */\n#ifdef MACOS\n    int E_flag;         /* -E: [MacOS] show Mac extra field during restoring */\n#endif\n    int fflag;          /* -f: \"freshen\" (extract only newer files) */\n#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n    int acorn_nfs_ext;  /* -F: RISC OS types & NFS filetype extensions */\n#endif\n    int hflag;          /* -h: header line (zipinfo) */\n#ifdef MACOS\n    int i_flag;         /* -i: [MacOS] ignore filenames stored in Mac e.f. */\n#endif\n#ifdef RISCOS\n    int scanimage;      /* -I: scan image files */\n#endif\n    int jflag;          /* -j: junk pathnames (unzip) */\n#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(MACOS))\n    int J_flag;         /* -J: ignore AtheOS/BeOS/MacOS e. f. info (unzip) */\n#endif\n#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX))\n    int K_flag;         /* -K: keep setuid/setgid/tacky permissions */\n#endif\n    int lflag;          /* -12slmv: listing format (zipinfo) */\n    int L_flag;         /* -L: convert filenames from some OSes to lowercase */\n    int overwrite_none; /* -n: never overwrite files (no prompting) */\n#ifdef AMIGA\n    int N_flag;         /* -N: restore comments as AmigaDOS filenotes */\n#endif\n    int overwrite_all;  /* -o: OK to overwrite files without prompting */\n#endif /* !FUNZIP */\n    int qflag;          /* -q: produce a lot less output */\n#ifdef TANDEM\n    int rflag;          /* -r: remove file extensions */\n#endif\n#ifndef FUNZIP\n#if (defined(MSDOS) || defined(FLEXOS) || defined(OS2) || defined(WIN32))\n    int sflag;          /* -s: convert spaces in filenames to underscores */\n#endif\n#if (defined(NLM))\n    int sflag;          /* -s: convert spaces in filenames to underscores */\n#endif\n#ifdef VMS\n    int S_flag;         /* -S: use Stream_LF for text files (-a[a]) */\n#endif\n#if (defined(MSDOS) || defined(__human68k__) || defined(OS2) || defined(WIN32))\n    int volflag;        /* -$: extract volume labels */\n#endif\n    int tflag;          /* -t: test (unzip) or totals line (zipinfo) */\n    int T_flag;         /* -T: timestamps (unzip) or dec. time fmt (zipinfo) */\n    int uflag;          /* -u: \"update\" (extract only newer/brand-new files) */\n#if defined(UNIX) || defined(VMS) || defined(WIN32)\n    int U_flag;         /* -U: escape non-ASCII, -UU No Unicode paths */\n#endif\n    int vflag;          /* -v: (verbosely) list directory */\n    int V_flag;         /* -V: don't strip VMS version numbers */\n    int W_flag;         /* -W: wildcard '*' won't match '/' dir separator */\n#if (defined (__ATHEOS__) || defined(__BEOS__) || defined(UNIX))\n    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */\n#else\n#if (defined(TANDEM) || defined(THEOS))\n    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */\n#else\n#if (defined(OS2) || defined(VMS) || defined(WIN32))\n    int X_flag;         /* -X: restore owner/protection or UID/GID or ACLs */\n#endif\n#endif\n#endif\n#ifdef VMS\n    int Y_flag;         /* -Y: treat \".nnn\" as \";nnn\" version */\n#endif\n    int zflag;          /* -z: display the zipfile comment (only, for unzip) */\n#ifdef VMS\n    int ods2_flag;      /* -2: force names to conform to ODS2 */\n#endif\n#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))\n    int ddotflag;       /* -:: don't skip over \"../\" path elements */\n#endif\n#ifdef UNIX\n    int cflxflag;       /* -^: allow control chars in extracted filenames */\n#endif\n#endif /* !FUNZIP */\n} UzpOpts;\n\n/* intended to be a private struct: */\ntypedef struct _ver {\n    uch major;              /* e.g., integer 5 */\n    uch minor;              /* e.g., 2 */\n    uch patchlevel;         /* e.g., 0 */\n    uch not_used;\n} _version_type;\n\ntypedef struct _UzpVer {\n    ulg structlen;            /* length of the struct being passed */\n    ulg flag;                 /* bit 0: is_beta   bit 1: uses_zlib */\n    ZCONST char *betalevel;   /* e.g. \"g BETA\" or \"\" */\n    ZCONST char *date;        /* e.g. \"9 Oct 08\" (beta) or \"9 October 2008\" */\n    ZCONST char *zlib_version;/* e.g. \"1.2.3\" or NULL */\n    _version_type unzip;      /* current UnZip version */\n    _version_type zipinfo;    /* current ZipInfo version */\n    _version_type os2dll;     /* OS2DLL version (retained for compatibility */\n    _version_type windll;     /* WinDLL version (retained for compatibility */\n    _version_type dllapimin;  /* last incompatible change of library API */\n} UzpVer;\n\n/* for Visual BASIC access to Windows DLLs: */\ntypedef struct _UzpVer2 {\n    ulg structlen;            /* length of the struct being passed */\n    ulg flag;                 /* bit 0: is_beta   bit 1: uses_zlib */\n    char betalevel[10];       /* e.g. \"g BETA\" or \"\" */\n    char date[20];            /* e.g. \"9 Oct 08\" (beta) or \"9 October 2008\" */\n    char zlib_version[10];    /* e.g. \"1.2.3\" or NULL */\n    _version_type unzip;      /* current UnZip version */\n    _version_type zipinfo;    /* current ZipInfo version */\n    _version_type os2dll;     /* OS2DLL version (retained for compatibility */\n    _version_type windll;     /* WinDLL version (retained for compatibility */\n    _version_type dllapimin;  /* last incompatible change of library API */\n} UzpVer2;\n\n\ntypedef struct _Uzp_Siz64 {\n    unsigned long lo32;\n    unsigned long hi32;\n} Uzp_Siz64;\n\ntypedef struct _Uzp_cdir_Rec {\n    uch version_made_by[2];\n    uch version_needed_to_extract[2];\n    ush general_purpose_bit_flag;\n    ush compression_method;\n    ulg last_mod_dos_datetime;\n    ulg crc32;\n    Uzp_Siz64 csize;\n    Uzp_Siz64 ucsize;\n    ush filename_length;\n    ush extra_field_length;\n    ush file_comment_length;\n    ush disk_number_start;\n    ush internal_file_attributes;\n    ulg external_file_attributes;\n    Uzp_Siz64 relative_offset_local_header;\n} Uzp_cdir_Rec;\n\n\n#define UZPINIT_LEN   sizeof(UzpInit)\n#define UZPVER_LEN    sizeof(UzpVer)\n#define cbList(func)  int (* UZ_EXP func)(char *filename, Uzp_cdir_Rec *crec)\n\n\n/*---------------------------------------------------------------------------\n    Return (and exit) values of the public UnZip API functions.\n  ---------------------------------------------------------------------------*/\n\n/* external return codes */\n#define PK_OK              0   /* no error */\n#define PK_COOL            0   /* no error */\n#define PK_WARN            1   /* warning error */\n#define PK_ERR             2   /* error in zipfile */\n#define PK_BADERR          3   /* severe error in zipfile */\n#define PK_MEM             4   /* insufficient memory (during initialization) */\n#define PK_MEM2            5   /* insufficient memory (password failure) */\n#define PK_MEM3            6   /* insufficient memory (file decompression) */\n#define PK_MEM4            7   /* insufficient memory (memory decompression) */\n#define PK_MEM5            8   /* insufficient memory (not yet used) */\n#define PK_NOZIP           9   /* zipfile not found */\n#define PK_PARAM          10   /* bad or illegal parameters specified */\n#define PK_FIND           11   /* no files found */\n#define PK_DISK           50   /* disk full */\n#define PK_EOF            51   /* unexpected EOF */\n\n#define IZ_CTRLC          80   /* user hit ^C to terminate */\n#define IZ_UNSUP          81   /* no files found: all unsup. compr/encrypt. */\n#define IZ_BADPWD         82   /* no files found: all had bad password */\n#define IZ_ERRBF          83   /* big-file archive, small-file program */\n\n/* return codes of password fetches (negative = user abort; positive = error) */\n#define IZ_PW_ENTERED      0   /* got some password string; use/try it */\n#define IZ_PW_CANCEL      -1   /* no password available (for this entry) */\n#define IZ_PW_CANCELALL   -2   /* no password, skip any further pwd. request */\n#define IZ_PW_ERROR        5   /* = PK_MEM2 : failure (no mem, no tty, ...) */\n\n/* flag values for status callback function */\n#define UZ_ST_START_EXTRACT     1       /* no details */\n#define UZ_ST_IN_PROGRESS       2       /* no details */\n#define UZ_ST_FINISH_MEMBER     3       /* 'details': extracted size */\n\n/* return values of status callback function */\n#define UZ_ST_CONTINUE          0\n#define UZ_ST_BREAK             1\n\n\n/*---------------------------------------------------------------------------\n    Prototypes for public UnZip API (DLL) functions.\n  ---------------------------------------------------------------------------*/\n\n#define  UzpMatch match\n\nint      UZ_EXP UzpMain            OF((int argc, char **argv));\nint      UZ_EXP UzpAltMain         OF((int argc, char **argv, UzpInit *init));\nZCONST UzpVer * UZ_EXP UzpVersion  OF((void));\nvoid     UZ_EXP UzpFreeMemBuffer   OF((UzpBuffer *retstr));\n#ifndef WINDLL\nint      UZ_EXP UzpUnzipToMemory   OF((char *zip, char *file, UzpOpts *optflgs,\n                                       UzpCB *UsrFunc, UzpBuffer *retstr));\nint      UZ_EXP UzpGrep            OF((char *archive, char *file,\n                                       char *pattern, int cmd, int SkipBin,\n                                       UzpCB *UsrFunc));\n#endif\n#ifdef OS2\nint      UZ_EXP UzpFileTree        OF((char *name, cbList(callBack),\n                                       char *cpInclude[], char *cpExclude[]));\n#endif\n\nunsigned UZ_EXP UzpVersion2        OF((UzpVer2 *version));\nint      UZ_EXP UzpValidate        OF((char *archive, int AllCodes));\n\n\n/* default I/O functions (can be swapped out via UzpAltMain() entry point): */\n\nint      UZ_EXP UzpMessagePrnt   OF((zvoid *pG, uch *buf, ulg size, int flag));\nint      UZ_EXP UzpMessageNull   OF((zvoid *pG, uch *buf, ulg size, int flag));\nint      UZ_EXP UzpInput         OF((zvoid *pG, uch *buf, int *size, int flag));\nvoid     UZ_EXP UzpMorePause     OF((zvoid *pG, ZCONST char *prompt, int flag));\nint      UZ_EXP UzpPassword      OF((zvoid *pG, int *rcnt, char *pwbuf,\n                                     int size, ZCONST char *zfn,\n                                     ZCONST char *efn));\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*---------------------------------------------------------------------------\n    Remaining private stuff for UnZip compilation.\n  ---------------------------------------------------------------------------*/\n\n#ifdef UNZIP_INTERNAL\n#  include \"unzpriv.h\"\n#endif\n\n\n#endif /* !__unzip_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/unzip.txt",
    "content": "UNZIP(1L)                                                            UNZIP(1L)\n\nNAME\n       unzip - list, test and extract compressed files in a ZIP archive\n\nSYNOPSIS\n       unzip  [-Z] [-cflptTuvz[abjnoqsCDKLMUVWX$/:^]] file[.zip] [file(s) ...]\n       [-x xfile(s) ...] [-d exdir]\n\nDESCRIPTION\n       unzip will list, test, or extract files from a  ZIP  archive,  commonly\n       found  on MS-DOS systems.  The default behavior (with no options) is to\n       extract into the current directory (and subdirectories  below  it)  all\n       files  from  the  specified ZIP archive.  A companion program, zip(1L),\n       creates ZIP archives; both programs are compatible with  archives  cre-\n       ated  by  PKWARE's  PKZIP and PKUNZIP for MS-DOS, but in many cases the\n       program options or default behaviors differ.\n\nARGUMENTS\n       file[.zip]\n              Path of the ZIP archive(s).  If  the  file  specification  is  a\n              wildcard, each matching file is processed in an order determined\n              by the operating system (or file system).  Only the filename can\n              be a wildcard; the path itself cannot.  Wildcard expressions are\n              similar to those supported in commonly  used  Unix  shells  (sh,\n              ksh, csh) and may contain:\n\n              *      matches a sequence of 0 or more characters\n\n              ?      matches exactly 1 character\n\n              [...]  matches  any  single character found inside the brackets;\n                     ranges are specified by a beginning character, a  hyphen,\n                     and  an  ending  character.  If an exclamation point or a\n                     caret (`!' or `^') follows the  left  bracket,  then  the\n                     range  of  characters within the brackets is complemented\n                     (that is,  anything  except  the  characters  inside  the\n                     brackets  is  considered a match).  To specify a verbatim\n                     left bracket, the three-character sequence ``[[]'' has to\n                     be used.\n\n              (Be  sure  to quote any character that might otherwise be inter-\n              preted or modified by the operating system,  particularly  under\n              Unix  and  VMS.)   If no matches are found, the specification is\n              assumed to be a literal filename; and if that  also  fails,  the\n              suffix  .zip  is  appended.  Note that self-extracting ZIP files\n              are supported, as with any other ZIP archive; just  specify  the\n              .exe suffix (if any) explicitly.\n\n       [file(s)]\n              An  optional  list of archive members to be processed, separated\n              by spaces.  (VMS versions  compiled  with  VMSCLI  defined  must\n              delimit  files  with  commas instead.  See -v in OPTIONS below.)\n              Regular expressions (wildcards) may be used  to  match  multiple\n              members;  see  above.   Again, be sure to quote expressions that\n              would otherwise be expanded or modified by the operating system.\n\n       [-x xfile(s)]\n              An optional list of archive members to be excluded from process-\n              ing.  Since wildcard characters normally match  (`/')  directory\n              separators  (for  exceptions see the option -W), this option may\n              be used to exclude any files that are  in  subdirectories.   For\n              example,  ``unzip foo *.[ch] -x */*'' would extract all C source\n              files in the main directory, but  none  in  any  subdirectories.\n              Without  the  -x  option,  all C source files in all directories\n              within the zipfile would be extracted.\n\n       [-d exdir]\n              An optional directory to which to extract  files.   By  default,\n              all files and subdirectories are recreated in the current direc-\n              tory; the -d option allows extraction in an arbitrary  directory\n              (always  assuming one has permission to write to the directory).\n              This option need not appear at the end of the command  line;  it\n              is also accepted before the zipfile specification (with the nor-\n              mal options), immediately after the  zipfile  specification,  or\n              between the file(s) and the -x option.  The option and directory\n              may be concatenated without any white space  between  them,  but\n              note that this may cause normal shell behavior to be suppressed.\n              In particular, ``-d ~'' (tilde) is expanded  by  Unix  C  shells\n              into  the  name  of  the  user's  home directory, but ``-d~'' is\n              treated as a literal subdirectory ``~'' of  the  current  direc-\n              tory.\n\nOPTIONS\n       Note  that,  in  order  to  support obsolescent hardware, unzip's usage\n       screen is limited to 22 or 23 lines and should therefore be  considered\n       only  a  reminder  of  the basic unzip syntax rather than an exhaustive\n       list of all possible flags.  The exhaustive list follows:\n\n       -Z     zipinfo(1L) mode.  If the first option on the  command  line  is\n              -Z,  the  remaining options are taken to be zipinfo(1L) options.\n              See the appropriate manual  page  for  a  description  of  these\n              options.\n\n       -A     [OS/2,  Unix  DLL] print extended help for the DLL's programming\n              interface (API).\n\n       -c     extract files to stdout/screen (``CRT'').  This option is  simi-\n              lar  to  the  -p  option  except  that  the name of each file is\n              printed as it is extracted, the -a option is allowed, and ASCII-\n              EBCDIC  conversion  is  automatically  performed if appropriate.\n              This option is not listed in the unzip usage screen.\n\n       -f     freshen existing files, i.e.,  extract  only  those  files  that\n              already  exist  on disk and that are newer than the disk copies.\n              By default unzip queries before overwriting, but the  -o  option\n              may be used to suppress the queries.  Note that under many oper-\n              ating systems, the TZ (timezone) environment  variable  must  be\n              set  correctly  in  order  for -f and -u to work properly (under\n              Unix the variable is usually set  automatically).   The  reasons\n              for this are somewhat subtle but have to do with the differences\n              between DOS-format file times (always local time) and  Unix-for-\n              mat  times  (always in GMT/UTC) and the necessity to compare the\n              two.  A typical TZ value is ``PST8PDT'' (US  Pacific  time  with\n              automatic  adjustment  for  Daylight  Savings  Time  or ``summer\n              time'').\n\n       -l     list archive files (short format).  The names, uncompressed file\n              sizes  and  modification  dates and times of the specified files\n              are printed, along with totals  for  all  files  specified.   If\n              UnZip  was  compiled  with  OS2_EAS  defined, the -l option also\n              lists columns for the sizes of stored OS/2  extended  attributes\n              (EAs)  and  OS/2  access control lists (ACLs).  In addition, the\n              zipfile comment and individual file comments (if any)  are  dis-\n              played.   If  a file was archived from a single-case file system\n              (for example, the old MS-DOS FAT file system) and the -L  option\n              was  given,  the  filename is converted to lowercase and is pre-\n              fixed with a caret (^).\n\n       -p     extract files to pipe (stdout).  Nothing but the  file  data  is\n              sent  to  stdout,  and  the files are always extracted in binary\n              format, just as they are stored (no conversions).\n\n       -t     test archive files.  This option extracts each specified file in\n              memory  and  compares  the  CRC  (cyclic  redundancy  check,  an\n              enhanced checksum) of the expanded file with the original file's\n              stored CRC value.\n\n       -T     [most  OSes]  set the timestamp on the archive(s) to that of the\n              newest file in each one.  This corresponds to zip's  -go  option\n              except  that  it can be used on wildcard zipfiles (e.g., ``unzip\n              -T \\*.zip'') and is much faster.\n\n       -u     update existing files and  create  new  ones  if  needed.   This\n              option  performs  the same function as the -f option, extracting\n              (with query) files that are newer than those with the same  name\n              on  disk,  and  in  addition it extracts those files that do not\n              already exist on disk.  See -f above for information on  setting\n              the timezone properly.\n\n       -v     list  archive  files (verbose format) or show diagnostic version\n              info.  This option has evolved and now behaves as both an option\n              and  a modifier.  As an option it has two purposes:  when a zip-\n              file is specified with no other options, -v lists archive  files\n              verbosely,  adding  to the basic -l info the compression method,\n              compressed size, compression ratio and 32-bit CRC.  In  contrast\n              to  most  of the competing utilities, unzip removes the 12 addi-\n              tional header bytes of encrypted  entries  from  the  compressed\n              size  numbers.  Therefore, compressed size and compression ratio\n              figures are independent of the  entry's  encryption  status  and\n              show the correct compression performance.  (The complete size of\n              the encrypted compressed data  stream  for  zipfile  entries  is\n              reported  by the more verbose zipinfo(1L) reports, see the sepa-\n              rate manual.)  When no zipfile is specified (that is,  the  com-\n              plete  command  is  simply ``unzip -v''), a diagnostic screen is\n              printed.  In addition to the normal header with release date and\n              version,  unzip  lists  the  home Info-ZIP ftp site and where to\n              find a list of other ftp and non-ftp sites; the target operating\n              system  for  which  it  was  compiled, as well as (possibly) the\n              hardware on which it was  compiled,  the  compiler  and  version\n              used,  and the compilation date; any special compilation options\n              that might affect the program's operation (see  also  DECRYPTION\n              below);  and  any  options  stored in environment variables that\n              might do the same (see ENVIRONMENT OPTIONS below).  As  a  modi-\n              fier  it  works  in conjunction with other options (e.g., -t) to\n              produce more verbose or debugging output; this is not yet  fully\n              implemented but will be in future releases.\n\n       -z     display only the archive comment.\n\nMODIFIERS\n       -a     convert  text files.  Ordinarily all files are extracted exactly\n              as they are stored (as ``binary'' files).  The -a option  causes\n              files  identified by zip as text files (those with the `t' label\n              in zipinfo  listings,  rather  than  `b')  to  be  automatically\n              extracted  as such, converting line endings, end-of-file charac-\n              ters and the character set itself as necessary.   (For  example,\n              Unix  files  use line feeds (LFs) for end-of-line (EOL) and have\n              no end-of-file (EOF) marker; Macintoshes  use  carriage  returns\n              (CRs) for EOLs; and most PC operating systems use CR+LF for EOLs\n              and control-Z for EOF.  In  addition,  IBM  mainframes  and  the\n              Michigan  Terminal System use EBCDIC rather than the more common\n              ASCII character set, and NT supports Unicode.)  Note that  zip's\n              identification  of  text  files  is  by  no  means perfect; some\n              ``text'' files may actually be binary  and  vice  versa.   unzip\n              therefore  prints  ``[text]''  or ``[binary]'' as a visual check\n              for each file it extracts when using the  -a  option.   The  -aa\n              option  forces  all files to be extracted as text, regardless of\n              the supposed file type.  On VMS, see also -S.\n\n       -b     [general] treat all files as binary (no text conversions).  This\n              is a shortcut for ---a.\n\n       -b     [Tandem]  force  the creation files with filecode type 180 ('C')\n              when extracting Zip entries marked as \"text\". (On Tandem, -a  is\n              enabled by default, see above).\n\n       -b     [VMS]  auto-convert binary files (see -a above) to fixed-length,\n              512-byte record format.  Doubling the option  (-bb)  forces  all\n              files  to  be extracted in this format. When extracting to stan-\n              dard output (-c or -p option in effect), the default  conversion\n              of  text record delimiters is disabled for binary (-b) resp. all\n              (-bb) files.\n\n       -B     [when compiled with UNIXBACKUP defined] save a  backup  copy  of\n              each  overwritten  file. The backup file is gets the name of the\n              target file with a tilde and optionally a unique sequence number\n              (up to 5 digits) appended.  The sequence number is applied when-\n              ever another file with the  original  name  plus  tilde  already\n              exists.   When used together with the \"overwrite all\" option -o,\n              numbered backup files are  never  created.  In  this  case,  all\n              backup  files  are  named  as the original file with an appended\n              tilde, existing backup files are deleted without  notice.   This\n              feature  works  similarly to the default behavior of emacs(1) in\n              many locations.\n\n              Example: the old copy of ``foo'' is renamed to ``foo~''.\n\n              Warning: Users should be aware that the -B option does not  pre-\n              vent  loss  of existing data under all circumstances.  For exam-\n              ple, when unzip  is  run  in  overwrite-all  mode,  an  existing\n              ``foo~'' file is deleted before unzip attempts to rename ``foo''\n              to ``foo~''.  When this rename attempt fails (because of a  file\n              locks,  insufficient  privileges,  or  ...),  the  extraction of\n              ``foo~'' gets cancelled, but the  old  backup  file  is  already\n              lost.   A  similar scenario takes place when the sequence number\n              range for numbered backup files gets exhausted (99999, or  65535\n              for  16-bit  systems).   In  this case, the backup file with the\n              maximum sequence number is  deleted  and  replaced  by  the  new\n              backup version without notice.\n\n       -C     use  case-insensitive  matching  for  the  selection  of archive\n              entries from the command-line list  of  extract  selection  pat-\n              terns.  unzip's philosophy is ``you get what you ask for'' (this\n              is also responsible for  the  -L/-U  change;  see  the  relevant\n              options below).  Because some file systems are fully case-sensi-\n              tive (notably those under the Unix operating system) and because\n              both  ZIP  archives  and  unzip itself are portable across plat-\n              forms, unzip's default behavior is to match  both  wildcard  and\n              literal filenames case-sensitively.  That is, specifying ``make-\n              file'' on the command line will only match ``makefile''  in  the\n              archive,  not  ``Makefile''  or  ``MAKEFILE'' (and similarly for\n              wildcard specifications).  Since this does not correspond to the\n              behavior of many other operating/file systems (for example, OS/2\n              HPFS, which preserves mixed case but is not  sensitive  to  it),\n              the  -C  option  may be used to force all filename matches to be\n              case-insensitive.  In the example above, all three  files  would\n              then  match  ``makefile''  (or  ``make*'',  or similar).  The -C\n              option affects file specs in both the normal file list  and  the\n              excluded-file list (xlist).\n\n              Please  note  that  the -C option does neither affect the search\n              for the zipfile(s) nor the matching of archive entries to exist-\n              ing files on the extraction path.  On a case-sensitive file sys-\n              tem, unzip will never try  to  overwrite  a  file  ``FOO''  when\n              extracting an entry ``foo''!\n\n       -D     skip  restoration  of timestamps for extracted items.  Normally,\n              unzip tries to restore all meta-information for extracted  items\n              that  are supplied in the Zip archive (and do not require privi-\n              leges or impose a security risk).  By specifying  -D,  unzip  is\n              told  to  suppress  restoration  of  timestamps  for directories\n              explicitly created from Zip archive entries.  This  option  only\n              applies to ports that support setting timestamps for directories\n              (currently ATheOS, BeOS, MacOS,  OS/2,  Unix,  VMS,  Win32,  for\n              other unzip ports, -D has no effect).  The duplicated option -DD\n              forces suppression of timestamp restoration  for  all  extracted\n              entries (files and directories).  This option results in setting\n              the timestamps for all extracted entries to the current time.\n\n              On VMS, the default setting for this option is  -D  for  consis-\n              tency   with  the  behaviour  of  BACKUP:  file  timestamps  are\n              restored, timestamps of extracted directories are  left  at  the\n              current  time.   To  enable restoration of directory timestamps,\n              the negated option --D should be specified.  On VMS, the  option\n              -D  disables timestamp restoration for all extracted Zip archive\n              items.  (Here, a single -D on the command line combines with the\n              default -D to do what an explicit -DD does on other systems.)\n\n       -E     [MacOS  only]  display  contents  of  MacOS  extra  field during\n              restore operation.\n\n       -F     [Acorn only] suppress removal of  NFS  filetype  extension  from\n              stored filenames.\n\n       -F     [non-Acorn  systems supporting long filenames with embedded com-\n              mas, and only if compiled with ACORN_FTYPE_NFS  defined]  trans-\n              late  filetype information from ACORN RISC OS extra field blocks\n              into a NFS filetype extension and append it to the names of  the\n              extracted  files.   (When the stored filename appears to already\n              have an appended NFS filetype extension, it is replaced  by  the\n              info from the extra field.)\n\n       -i     [MacOS  only]  ignore  filenames  stored  in MacOS extra fields.\n              Instead, the most compatible filename stored in the generic part\n              of the entry's header is used.\n\n       -j     junk paths.  The archive's directory structure is not recreated;\n              all files are deposited in the extraction directory (by default,\n              the current one).\n\n       -J     [BeOS   only]  junk  file  attributes.   The  file's  BeOS  file\n              attributes are not restored, just the file's data.\n\n       -J     [MacOS only] ignore MacOS extra fields.  All Macintosh  specific\n              info  is  skipped.  Data-fork  and resource-fork are restored as\n              separate files.\n\n       -K     [AtheOS,  BeOS,   Unix   only]   retain   SUID/SGID/Tacky   file\n              attributes.  Without this flag, these attribute bits are cleared\n              for security reasons.\n\n       -L     convert to lowercase any filename originating on  an  uppercase-\n              only operating system or file system.  (This was unzip's default\n              behavior in releases prior to 5.11; the new default behavior  is\n              identical  to  the old behavior with the -U option, which is now\n              obsolete and will be removed in a future release.)  Depending on\n              the  archiver,  files  archived  under  single-case file systems\n              (VMS, old MS-DOS FAT,  etc.)  may  be  stored  as  all-uppercase\n              names;  this  can  be  ugly or inconvenient when extracting to a\n              case-preserving file system such as OS/2 HPFS or  a  case-sensi-\n              tive  one  such  as  under  Unix.   By  default  unzip lists and\n              extracts such filenames exactly  as  they're  stored  (excepting\n              truncation,  conversion  of  unsupported characters, etc.); this\n              option causes the names of all files from certain systems to  be\n              converted  to  lowercase.   The  -LL option forces conversion of\n              every filename to lowercase, regardless of the originating  file\n              system.\n\n       -M     pipe  all  output  through an internal pager similar to the Unix\n              more(1) command.  At the end of a  screenful  of  output,  unzip\n              pauses  with  a  ``--More--''  prompt; the next screenful may be\n              viewed by pressing the Enter (Return)  key  or  the  space  bar.\n              unzip  can  be terminated by pressing the ``q'' key and, on some\n              systems, the Enter/Return key.  Unlike Unix more(1), there is no\n              forward-searching  or  editing  capability.  Also, unzip doesn't\n              notice if long lines wrap at the edge of the screen, effectively\n              resulting  in  the printing of two or more lines and the likeli-\n              hood that some text will scroll off the top of the screen before\n              being  viewed.  On some systems the number of available lines on\n              the screen is not detected, in  which  case  unzip  assumes  the\n              height is 24 lines.\n\n       -n     never  overwrite existing files.  If a file already exists, skip\n              the extraction of that file without prompting.  By default unzip\n              queries before extracting any file that already exists; the user\n              may choose to overwrite only the  current  file,  overwrite  all\n              files,  skip  extraction of the current file, skip extraction of\n              all existing files, or rename the current file.\n\n       -N     [Amiga] extract file comments as Amiga filenotes.  File comments\n              are created with the -c option of zip(1L), or with the -N option\n              of the Amiga port of zip(1L), which  stores  filenotes  as  com-\n              ments.\n\n       -o     overwrite existing files without prompting.  This is a dangerous\n              option, so use it with care.  (It is often used  with  -f,  how-\n              ever,  and  is  the  only  way  to overwrite directory EAs under\n              OS/2.)\n\n       -P password\n              use password to decrypt  encrypted  zipfile  entries  (if  any).\n              THIS  IS  INSECURE!   Many  multi-user operating systems provide\n              ways for any user to see the current command line of  any  other\n              user;  even on stand-alone systems there is always the threat of\n              over-the-shoulder peeking.  Storing the  plaintext  password  as\n              part  of  a  command  line in an automated script is even worse.\n              Whenever possible, use the non-echoing,  interactive  prompt  to\n              enter  passwords.   (And  where security is truly important, use\n              strong encryption such as Pretty Good  Privacy  instead  of  the\n              relatively  weak  encryption provided by standard zipfile utili-\n              ties.)\n\n       -q     perform operations quietly (-qq  =  even  quieter).   Ordinarily\n              unzip  prints the names of the files it's extracting or testing,\n              the extraction methods, any file or zipfile comments that may be\n              stored in the archive, and possibly a summary when finished with\n              each archive.  The -q[q] options suppress the printing  of  some\n              or all of these messages.\n\n       -s     [OS/2,  NT,  MS-DOS] convert spaces in filenames to underscores.\n              Since all PC operating systems allow spaces in filenames,  unzip\n              by   default   extracts  filenames  with  spaces  intact  (e.g.,\n              ``EA DATA. SF'').  This can be awkward, however, since MS-DOS in\n              particular  does  not  gracefully  support  spaces in filenames.\n              Conversion of spaces to underscores can eliminate  the  awkward-\n              ness in some cases.\n\n       -S     [VMS] convert text files (-a, -aa) into Stream_LF record format,\n              instead of the text-file default, variable-length record format.\n              (Stream_LF  is  the  default  record  format of VMS unzip. It is\n              applied unless conversion (-a, -aa and/or -b, -bb) is  requested\n              or a VMS-specific entry is processed.)\n\n       -U     [UNICODE_SUPPORT  only]  modify or disable UTF-8 handling.  When\n              UNICODE_SUPPORT is available, the  option  -U  forces  unzip  to\n              escape  all  non-ASCII  characters from UTF-8 coded filenames as\n              ``#Uxxxx'' (for UCS-2 characters, or  ``#Lxxxxxx''  for  unicode\n              codepoints  needing  3  octets).  This option is mainly provided\n              for debugging purpose when the fairly new UTF-8 support is  sus-\n              pected to mangle up extracted filenames.\n\n              The  option  -UU  allows  to entirely disable the recognition of\n              UTF-8 encoded  filenames.   The  handling  of  filename  codings\n              within unzip falls back to the behaviour of previous versions.\n\n              [old, obsolete usage] leave filenames uppercase if created under\n              MS-DOS, VMS, etc.  See -L above.\n\n       -V     retain (VMS) file version numbers.  VMS files can be stored with\n              a  version  number,  in  the format file.ext;##.  By default the\n              ``;##'' version numbers are stripped,  but  this  option  allows\n              them  to  be retained.  (On file systems that limit filenames to\n              particularly short lengths, the version numbers may be truncated\n              or stripped regardless of this option.)\n\n       -W     [only  when  WILD_STOP_AT_DIR compile-time option enabled] modi-\n              fies the pattern matching routine so that both `?'  (single-char\n              wildcard)  and `*' (multi-char wildcard) do not match the direc-\n              tory  separator  character  `/'.   (The  two-character  sequence\n              ``**'' acts as a multi-char wildcard that includes the directory\n              separator in its matched characters.)  Examples:\n\n               \"*.c\" matches \"foo.c\" but not \"mydir/foo.c\"\n               \"**.c\" matches both \"foo.c\" and \"mydir/foo.c\"\n               \"*/*.c\" matches \"bar/foo.c\" but not \"baz/bar/foo.c\"\n               \"??*/*\" matches \"ab/foo\" and \"abc/foo\"\n                       but not \"a/foo\" or \"a/b/foo\"\n\n              This modified behaviour is equivalent to  the  pattern  matching\n              style used by the shells of some of UnZip's supported target OSs\n              (one example is Acorn RISC OS).  This option may not  be  avail-\n              able on systems where the Zip archive's internal directory sepa-\n              rator character `/' is allowed as regular  character  in  native\n              operating  system  filenames.   (Currently,  UnZip uses the same\n              pattern matching rules for both wildcard zipfile  specifications\n              and  zip  entry  selection  patterns in most ports.  For systems\n              allowing `/' as regular filename character, the -W option  would\n              not work as expected on a wildcard zipfile specification.)\n\n       -X     [VMS,  Unix,  OS/2,  NT,  Tandem]  restore owner/protection info\n              (UICs and ACL  entries)  under  VMS,  or  user  and  group  info\n              (UID/GID)  under Unix, or access control lists (ACLs) under cer-\n              tain network-enabled versions of OS/2 (Warp Server with IBM  LAN\n              Server/Requester 3.0 to 5.0; Warp Connect with IBM Peer 1.0), or\n              security ACLs under Windows NT.  In most cases this will require\n              special  system  privileges, and doubling the option (-XX) under\n              NT instructs unzip to use privileges for extraction;  but  under\n              Unix,  for  example,  a  user  who belongs to several groups can\n              restore files owned by any of those groups, as long as the  user\n              IDs  match  his  or her own.  Note that ordinary file attributes\n              are always restored--this option applies only to optional, extra\n              ownership  info  available  on  some  operating  systems.  [NT's\n              access control lists do not appear to be  especially  compatible\n              with OS/2's, so no attempt is made at cross-platform portability\n              of access privileges.  It is not  clear  under  what  conditions\n              this would ever be useful anyway.]\n\n       -Y     [VMS]  treat  archived  file  name  endings  of  ``.nnn'' (where\n              ``nnn'' is a decimal  number) as if they were VMS  version  num-\n              bers  (``;nnn'').  (The default is to treat them as file types.)\n              Example:\n                       \"a.b.3\" -> \"a.b;3\".\n\n       -$     [MS-DOS, OS/2, NT] restore the volume label  if  the  extraction\n              medium  is  removable  (e.g.,  a diskette).  Doubling the option\n              (-$$) allows fixed media (hard disks) to be  labelled  as  well.\n              By default, volume labels are ignored.\n\n       -/ extensions\n              [Acorn  only] overrides the extension list supplied by Unzip$Ext\n              environment variable.  During  extraction,  filename  extensions\n              that  match  one of the items in this extension list are swapped\n              in front of the base name of the extracted file.\n\n       -:     [all but Acorn, VM/CMS, MVS, Tandem] allows to  extract  archive\n              members into locations outside of the current `` extraction root\n              folder''. For security reasons, unzip normally removes  ``parent\n              dir''  path  components  (``../'')  from  the names of extracted\n              file.  This safety feature (new for version 5.50) prevents unzip\n              from  accidentally  writing files to ``sensitive'' areas outside\n              the active extraction folder tree  head.   The  -:  option  lets\n              unzip  switch  back  to its previous, more liberal behaviour, to\n              allow exact extraction of (older)  archives  that  used  ``../''\n              components  to  create  multiple directory trees at the level of\n              the current extraction folder.   This  option  does  not  enable\n              writing  explicitly  to  the root directory (``/'').  To achieve\n              this, it is necessary to set the  extraction  target  folder  to\n              root (e.g. -d / ).  However, when the -: option is specified, it\n              is still possible to implicitly write to the root  directory  by\n              specifying   enough  ``../''  path  components  within  the  zip\n              archive.  Use this option with extreme caution.\n\n       -^     [Unix only] allow control characters in names of  extracted  ZIP\n              archive  entries.   On Unix, a file name may contain any (8-bit)\n              character code with the two exception '/' (directory  delimiter)\n              and  NUL  (0x00, the C string termination indicator), unless the\n              specific file system has more restrictive  conventions.   Gener-\n              ally,  this  allows  to  embed ASCII control characters (or even\n              sophisticated control sequences) in  file  names,  at  least  on\n              'native'  Unix  file  systems.  However, it may be highly suspi-\n              cious to make use of  this  Unix  \"feature\".   Embedded  control\n              characters in file names might have nasty side effects when dis-\n              played on screen by some listing code without sufficient filter-\n              ing.   And,  for  ordinary  users, it may be difficult to handle\n              such file names (e.g. when trying to specify it for open,  copy,\n              move,  or delete operations).  Therefore, unzip applies a filter\n              by default that removes potentially dangerous control characters\n              from  the extracted file names. The -^ option allows to override\n              this filter in the rare  case  that  embedded  filename  control\n              characters are to be intentionally restored.\n\n       -2     [VMS]   force   unconditionally  conversion  of  file  names  to\n              ODS2-compatible names.  The default is to exploit  the  destina-\n              tion file system, preserving case and extended file name charac-\n              ters on an  ODS5  destination  file  system;  and  applying  the\n              ODS2-compatibility  file  name  filtering on an ODS2 destination\n              file system.\n\nENVIRONMENT OPTIONS\n       unzip's default behavior may be modified via options placed in an envi-\n       ronment variable.  This can be done with any option, but it is probably\n       most useful with the -a, -L, -C, -q, -o, or -n modifiers:   make  unzip\n       auto-convert  text  files  by  default,  make it convert filenames from\n       uppercase systems to lowercase, make it match names case-insensitively,\n       make  it  quieter, or make it always overwrite or never overwrite files\n       as it extracts them.  For example, to make unzip act as quietly as pos-\n       sible,  only  reporting errors, one would use one of the following com-\n       mands:\n\n         Unix Bourne shell:\n              UNZIP=-qq; export UNZIP\n\n         Unix C shell:\n              setenv UNZIP -qq\n\n         OS/2 or MS-DOS:\n              set UNZIP=-qq\n\n         VMS (quotes for lowercase):\n              define UNZIP_OPTS \"-qq\"\n\n       Environment options are, in effect, considered  to  be  just  like  any\n       other  command-line options, except that they are effectively the first\n       options on the command line.  To override an  environment  option,  one\n       may use the ``minus operator'' to remove it.  For instance, to override\n       one of the quiet-flags in the example above, use the command\n\n           unzip --q[other options] zipfile\n\n       The first hyphen is the normal switch character, and the  second  is  a\n       minus  sign, acting on the q option.  Thus the effect here is to cancel\n       one quantum of quietness.  To cancel both quiet flags,  two  (or  more)\n       minuses may be used:\n\n           unzip -t--q zipfile\n           unzip ---qt zipfile\n\n       (the  two  are equivalent).  This may seem awkward or confusing, but it\n       is reasonably intuitive:  just ignore the  first  hyphen  and  go  from\n       there.  It is also consistent with the behavior of Unix nice(1).\n\n       As  suggested  by  the  examples  above, the default variable names are\n       UNZIP_OPTS for VMS (where the symbol used to install unzip as a foreign\n       command would otherwise be confused with the environment variable), and\n       UNZIP for all other operating systems.  For compatibility with zip(1L),\n       UNZIPOPT  is also accepted (don't ask).  If both UNZIP and UNZIPOPT are\n       defined, however, UNZIP takes precedence.   unzip's  diagnostic  option\n       (-v  with  no zipfile name) can be used to check the values of all four\n       possible unzip and zipinfo environment variables.\n\n       The timezone variable (TZ) should be set according to the  local  time-\n       zone in order for the -f and -u to operate correctly.  See the descrip-\n       tion of -f above for details.  This variable may also be  necessary  to\n       get  timestamps  of  extracted  files  to  be set correctly.  The WIN32\n       (Win9x/ME/NT4/2K/XP/2K3) port of unzip gets the timezone  configuration\n       from  the  registry, assuming it is correctly set in the Control Panel.\n       The TZ variable is ignored for this port.\n\nDECRYPTION\n       Encrypted archives are fully supported by Info-ZIP software, but due to\n       United States export restrictions, de-/encryption support might be dis-\n       abled in your compiled binary.  However, since spring 2000,  US  export\n       restrictions  have  been  liberated,  and  our  source  archives do now\n       include full crypt code.  In case you need  binary  distributions  with\n       crypt support enabled, see the file ``WHERE'' in any Info-ZIP source or\n       binary distribution for locations both inside and outside the US.\n\n       Some compiled versions of unzip may not support decryption.  To check a\n       version  for  crypt  support,  either  attempt  to  test  or extract an\n       encrypted archive, or else check unzip's diagnostic screen (see the  -v\n       option  above)  for  ``[decryption]'' as one of the special compilation\n       options.\n\n       As noted above, the -P option may be used to supply a password  on  the\n       command  line,  but  at  a  cost in security.  The preferred decryption\n       method is simply to extract normally; if a zipfile member is encrypted,\n       unzip  will  prompt  for  the  password  without echoing what is typed.\n       unzip continues to use the same password as long as it  appears  to  be\n       valid,  by testing a 12-byte header on each file.  The correct password\n       will always check out against the  header,  but  there  is  a  1-in-256\n       chance  that  an  incorrect password will as well.  (This is a security\n       feature of the PKWARE zipfile  format;  it  helps  prevent  brute-force\n       attacks  that  might  otherwise gain a large speed advantage by testing\n       only the header.)  In the case that an incorrect password is given  but\n       it  passes the header test anyway, either an incorrect CRC will be gen-\n       erated for the extracted data  or  else  unzip  will  fail  during  the\n       extraction  because  the  ``decrypted'' bytes do not constitute a valid\n       compressed data stream.\n\n       If the first password fails the header check on some file,  unzip  will\n       prompt  for  another password, and so on until all files are extracted.\n       If a password is not known, entering a null password (that is,  just  a\n       carriage  return or ``Enter'') is taken as a signal to skip all further\n       prompting.  Only unencrypted files in the archive(s) will thereafter be\n       extracted.   (In fact, that's not quite true; older versions of zip(1L)\n       and zipcloak(1L) allowed null passwords, so unzip checks each encrypted\n       file  to  see  if  the null password works.  This may result in ``false\n       positives'' and extraction errors, as noted above.)\n\n       Archives encrypted with 8-bit passwords (for  example,  passwords  with\n       accented European characters) may not be portable across systems and/or\n       other archivers.  This problem stems from the use of multiple  encoding\n       methods  for  such  characters,  including Latin-1 (ISO 8859-1) and OEM\n       code page 850.  DOS PKZIP 2.04g uses the OEM code page;  Windows  PKZIP\n       2.50 uses Latin-1 (and is therefore incompatible with DOS PKZIP); Info-\n       ZIP uses the OEM code page on DOS, OS/2 and Win3.x ports but ISO coding\n       (Latin-1  etc.)  everywhere  else;  and  Nico Mak's WinZip 6.x does not\n       allow 8-bit passwords at all.  UnZip 5.3 (or newer) attempts to use the\n       default  character set first (e.g., Latin-1), followed by the alternate\n       one (e.g., OEM code page) to test passwords.   On  EBCDIC  systems,  if\n       both  of  these  fail, EBCDIC encoding will be tested as a last resort.\n       (EBCDIC is not tested on non-EBCDIC systems, because there are no known\n       archivers that encrypt using EBCDIC encoding.)  ISO character encodings\n       other than Latin-1 are not supported.  The new addition of  (partially)\n       Unicode (resp.  UTF-8) support in UnZip 6.0 has not yet been adapted to\n       the encryption password handling in unzip.  On systems that  use  UTF-8\n       as  native  character  encoding, unzip simply tries decryption with the\n       native UTF-8 encoded password; the built-in attempts to check the pass-\n       word in translated encoding have not yet been adapted for UTF-8 support\n       and will consequently fail.\n\nEXAMPLES\n       To use unzip to extract all members of the archive letters.zip into the\n       current directory and subdirectories below it, creating any subdirecto-\n       ries as necessary:\n\n           unzip letters\n\n       To extract all members of letters.zip into the current directory only:\n\n           unzip -j letters\n\n       To test letters.zip, printing only a summary message indicating whether\n       the archive is OK or not:\n\n           unzip -tq letters\n\n       To  test  all zipfiles in the current directory, printing only the sum-\n       maries:\n\n           unzip -tq \\*.zip\n\n       (The backslash before the  asterisk  is  only  required  if  the  shell\n       expands  wildcards,  as  in  Unix;  double  quotes could have been used\n       instead, as in the source examples below.)  To extract to standard out-\n       put all members of letters.zip whose names end in .tex, auto-converting\n       to the local end-of-line convention and piping the output into more(1):\n\n           unzip -ca letters \\*.tex | more\n\n       To extract the binary file paper1.dvi to standard output and pipe it to\n       a printing program:\n\n           unzip -p articles paper1.dvi | dvips\n\n       To extract all FORTRAN and C source files--*.f,  *.c,  *.h,  and  Make-\n       file--into the /tmp directory:\n\n           unzip source.zip \"*.[fch]\" Makefile -d /tmp\n\n       (the  double  quotes are necessary only in Unix and only if globbing is\n       turned on).  To extract all FORTRAN and C source files,  regardless  of\n       case  (e.g.,  both *.c and *.C, and any makefile, Makefile, MAKEFILE or\n       similar):\n\n           unzip -C source.zip \"*.[fch]\" makefile -d /tmp\n\n       To extract any such files but convert any uppercase MS-DOS or VMS names\n       to  lowercase  and  convert the line-endings of all of the files to the\n       local standard (without respect to  any  files  that  might  be  marked\n       ``binary''):\n\n           unzip -aaCL source.zip \"*.[fch]\" makefile -d /tmp\n\n       To  extract  only  newer  versions  of the files already in the current\n       directory, without querying (NOTE:  be  careful  of  unzipping  in  one\n       timezone  a  zipfile  created in another--ZIP archives other than those\n       created by Zip 2.1 or later contain  no  timezone  information,  and  a\n       ``newer'' file from an eastern timezone may, in fact, be older):\n\n           unzip -fo sources\n\n       To extract newer versions of the files already in the current directory\n       and to create any files not already  there  (same  caveat  as  previous\n       example):\n\n           unzip -uo sources\n\n       To  display a diagnostic screen showing which unzip and zipinfo options\n       are stored in environment variables,  whether  decryption  support  was\n       compiled in, the compiler with which unzip was compiled, etc.:\n\n           unzip -v\n\n       In  the  last  five examples, assume that UNZIP or UNZIP_OPTS is set to\n       -q.  To do a singly quiet listing:\n\n           unzip -l file.zip\n\n       To do a doubly quiet listing:\n\n           unzip -ql file.zip\n\n       (Note that the ``.zip'' is generally not necessary.)  To do a  standard\n       listing:\n\n           unzip --ql file.zip\n       or\n           unzip -l-q file.zip\n       or\n           unzip -l--q file.zip\n       (Extra minuses in options don't hurt.)\n\nTIPS\n       The  current  maintainer,  being  a  lazy sort, finds it very useful to\n       define a pair of aliases:  tt for ``unzip -tq'' and ii for ``unzip -Z''\n       (or  ``zipinfo'').   One may then simply type ``tt zipfile'' to test an\n       archive, something that is worth making a habit of  doing.   With  luck\n       unzip  will  report  ``No  errors  detected  in compressed data of zip-\n       file.zip,'' after which one may breathe a sigh of relief.\n\n       The maintainer also finds it useful to set the UNZIP environment  vari-\n       able  to  ``-aL''  and  is  tempted to add ``-C'' as well.  His ZIPINFO\n       variable is set to ``-z''.\n\nDIAGNOSTICS\n       The exit status (or error level) approximates the exit codes defined by\n       PKWARE and takes on the following values, except under VMS:\n\n              0      normal; no errors or warnings detected.\n\n              1      one or more warning errors were encountered, but process-\n                     ing completed successfully anyway.   This  includes  zip-\n                     files  where  one or more files was skipped due to unsup-\n                     ported compression method or encryption with  an  unknown\n                     password.\n\n              2      a generic error in the zipfile format was detected.  Pro-\n                     cessing may have completed successfully anyway; some bro-\n                     ken zipfiles created by other archivers have simple work-\n                     arounds.\n\n              3      a severe error in the zipfile format was detected.   Pro-\n                     cessing probably failed immediately.\n\n              4      unzip  was  unable  to  allocate  memory  for one or more\n                     buffers during program initialization.\n\n              5      unzip was unable to allocate memory or unable to obtain a\n                     tty to read the decryption password(s).\n\n              6      unzip  was unable to allocate memory during decompression\n                     to disk.\n\n              7      unzip was unable  to  allocate  memory  during  in-memory\n                     decompression.\n\n              8      [currently not used]\n\n              9      the specified zipfiles were not found.\n\n              10     invalid options were specified on the command line.\n\n              11     no matching files were found.\n\n              50     the disk is (or was) full during extraction.\n\n              51     the end of the ZIP archive was encountered prematurely.\n\n              80     the  user  aborted  unzip  prematurely with control-C (or\n                     similar)\n\n              81     testing or extraction of one or more files failed due  to\n                     unsupported  compression  methods  or unsupported decryp-\n                     tion.\n\n              82     no files were found due to  bad  decryption  password(s).\n                     (If even one file is successfully processed, however, the\n                     exit status is 1.)\n\n       VMS interprets standard Unix (or PC) return values as  other,  scarier-\n       looking things, so unzip instead maps them into VMS-style status codes.\n       The current mapping is as  follows:    1  (success)  for  normal  exit,\n       0x7fff0001    for   warning   errors,   and   (0x7fff000?   +   16*nor-\n       mal_unzip_exit_status) for all other errors, where the `?' is 2 (error)\n       for unzip values 2, 9-11 and 80-82, and 4 (fatal error) for the remain-\n       ing ones (3-8, 50, 51).  In addition, there is a compilation option  to\n       expand  upon  this behavior:  defining RETURN_CODES results in a human-\n       readable explanation of what the error status means.\n\nBUGS\n       Multi-part archives are not yet supported, except in  conjunction  with\n       zip.  (All parts must be concatenated together in order, and then ``zip\n       -F'' (for zip 2.x) or ``zip -FF'' (for zip 3.x) must  be  performed  on\n       the  concatenated  archive  in  order to ``fix'' it.  Also, zip 3.0 and\n       later can combine multi-part (split) archives into a  combined  single-\n       file  archive using ``zip -s- inarchive -O outarchive''.  See the zip 3\n       manual page for more information.)  This will definitely  be  corrected\n       in the next major release.\n\n       Archives  read  from  standard input are not yet supported, except with\n       funzip  (and  then  only  the  first  member  of  the  archive  can  be\n       extracted).\n\n       Archives  encrypted with 8-bit passwords (e.g., passwords with accented\n       European characters) may not be portable across  systems  and/or  other\n       archivers.  See the discussion in DECRYPTION above.\n\n       unzip's -M (``more'') option tries to take into account automatic wrap-\n       ping of long lines. However, the code may fail to  detect  the  correct\n       wrapping   locations.   First,  TAB  characters  (and  similar  control\n       sequences) are not taken into account, they  are  handled  as  ordinary\n       printable  characters.   Second,  depending  on  the actual system / OS\n       port, unzip may not detect the true screen geometry but rather rely  on\n       \"commonly used\" default dimensions.  The correct handling of tabs would\n       require the implementation of a query for the actual tabulator setup on\n       the output console.\n\n       Dates,  times  and  permissions  of stored directories are not restored\n       except under Unix. (On Windows NT and successors,  timestamps  are  now\n       restored.)\n\n       [MS-DOS]  When  extracting or testing files from an archive on a defec-\n       tive floppy diskette, if the  ``Fail''  option  is  chosen  from  DOS's\n       ``Abort,  Retry,  Fail?'' message, older versions of unzip may hang the\n       system, requiring a reboot.  This problem appears to be fixed, but con-\n       trol-C (or control-Break) can still be used to terminate unzip.\n\n       Under DEC Ultrix, unzip would sometimes fail on long zipfiles (bad CRC,\n       not always reproducible).  This was apparently due either to a hardware\n       bug  (cache  memory)  or  an operating system bug (improper handling of\n       page faults?).  Since Ultrix has been abandoned  in  favor  of  Digital\n       Unix (OSF/1), this may not be an issue anymore.\n\n       [Unix]  Unix  special  files  such as FIFO buffers (named pipes), block\n       devices and character devices are not restored even if they are somehow\n       represented  in the zipfile, nor are hard-linked files relinked.  Basi-\n       cally the only file types restored by unzip are regular files, directo-\n       ries and symbolic (soft) links.\n\n       [OS/2] Extended attributes for existing directories are only updated if\n       the -o (``overwrite all'') option is given.  This is  a  limitation  of\n       the  operating  system;  because  directories only have a creation time\n       associated with them, unzip has no way to determine whether the  stored\n       attributes are newer or older than those on disk.  In practice this may\n       mean a two-pass approach is required:  first unpack  the  archive  nor-\n       mally  (with  or  without  freshening/updating  existing  files),  then\n       overwrite just the directory entries (e.g., ``unzip -o foo */'').\n\n       [VMS] When extracting to another directory, only the [.foo]  syntax  is\n       accepted  for  the  -d  option;  the simple Unix foo syntax is silently\n       ignored (as is the less common VMS foo.dir syntax).\n\n       [VMS] When the file being extracted already exists, unzip's query  only\n       allows  skipping, overwriting or renaming; there should additionally be\n       a choice for creating a new version of the file.  In fact, the  ``over-\n       write''  choice does create a new version; the old version is not over-\n       written or deleted.\n\nSEE ALSO\n       funzip(1L),  zip(1L),  zipcloak(1L),  zipgrep(1L),  zipinfo(1L),   zip-\n       note(1L), zipsplit(1L)\n\nURL\n       The Info-ZIP home page is currently at\n           http://www.info-zip.org/pub/infozip/\n       or\n           ftp://ftp.info-zip.org/pub/infozip/ .\n\nAUTHORS\n       The  primary  Info-ZIP authors (current semi-active members of the Zip-\n       Bugs workgroup) are:  Ed Gordon (Zip, general maintenance, shared code,\n       Zip64,  Win32,  Unix,  Unicode);  Christian  Spieler (UnZip maintenance\n       coordination, VMS, MS-DOS, Win32, shared code, general  Zip  and  UnZip\n       integration  and  optimization);  Onno van der Linden (Zip); Mike White\n       (Win32, Windows GUI, Windows  DLLs);  Kai  Uwe  Rommel  (OS/2,  Win32);\n       Steven  M.  Schweda  (VMS, Unix, support of new features); Paul Kienitz\n       (Amiga, Win32, Unicode); Chris Herborth (BeOS,  QNX,  Atari);  Jonathan\n       Hudson (SMS/QDOS); Sergio Monesi (Acorn RISC OS); Harald Denker (Atari,\n       MVS); John Bush (Solaris, Amiga); Hunter Goatley  (VMS,  Info-ZIP  Site\n       maintenance);  Steve  Salisbury (Win32); Steve Miller (Windows CE GUI),\n       Johnny Lee (MS-DOS, Win32, Zip64); and Dave Smith (Tandem NSK).\n\n       The following people were former members of  the  Info-ZIP  development\n       group  and  provided  major  contributions  to key parts of the current\n       code: Greg ``Cave Newt'' Roelofs (UnZip, unshrink decompression); Jean-\n       loup  Gailly  (deflate compression); Mark Adler (inflate decompression,\n       fUnZip).\n\n       The author of the original unzip code upon which Info-ZIP's  was  based\n       is  Samuel H. Smith; Carl Mascott did the first Unix port; and David P.\n       Kirschbaum organized and led Info-ZIP in  its  early  days  with  Keith\n       Petersen  hosting the original mailing list at WSMR-SimTel20.  The full\n       list of contributors to UnZip has grown quite large;  please  refer  to\n       the  CONTRIBS  file  in  the UnZip source distribution for a relatively\n       complete version.\n\nVERSIONS\n       v1.2   15 Mar 89   Samuel H. Smith\n       v2.0    9 Sep 89   Samuel H. Smith\n       v2.x   fall 1989   many Usenet contributors\n       v3.0    1 May 90   Info-ZIP (DPK, consolidator)\n       v3.1   15 Aug 90   Info-ZIP (DPK, consolidator)\n       v4.0    1 Dec 90   Info-ZIP (GRR, maintainer)\n       v4.1   12 May 91   Info-ZIP\n       v4.2   20 Mar 92   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.0   21 Aug 92   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.01  15 Jan 93   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.1    7 Feb 94   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.11   2 Aug 94   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.12  28 Aug 94   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.2   30 Apr 96   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.3   22 Apr 97   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.31  31 May 97   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.32   3 Nov 97   Info-ZIP (Zip-Bugs subgroup, GRR)\n       v5.4   28 Nov 98   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v5.41  16 Apr 00   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v5.42  14 Jan 01   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v5.5   17 Feb 02   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v5.51  22 May 04   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v5.52  28 Feb 05   Info-ZIP (Zip-Bugs subgroup, SPC)\n       v6.0   20 Apr 09   Info-ZIP (Zip-Bugs subgroup, SPC)\n\nInfo-ZIP                     20 April 2009 (v6.0)                    UNZIP(1L)\n"
  },
  {
    "path": "deps/infozip/unzip60/unzipsfx.txt",
    "content": "UNZIPSFX(1L)                                                      UNZIPSFX(1L)\n\nNAME\n       unzipsfx - self-extracting stub for prepending to ZIP archives\n\nSYNOPSIS\n       <name  of  unzipsfx+archive  combo>  [-cfptuz[ajnoqsCLV$]] [file(s) ...\n       [-x xfile(s) ...]]\n\nDESCRIPTION\n       unzipsfx is a modified version of unzip(1L) designed to be prepended to\n       existing  ZIP  archives  in  order  to  form  self-extracting archives.\n       Instead of taking its first non-flag argument to be the  zipfile(s)  to\n       be  extracted,  unzipsfx  seeks  itself  under the name by which it was\n       invoked and tests or extracts the contents  of  the  appended  archive.\n       Because the executable stub adds bulk to the archive (the whole purpose\n       of which is to be as small as possible), a  number  of  the  less-vital\n       capabilities  in  regular unzip have been removed.  Among these are the\n       usage (or help) screen, the listing and diagnostic  functions  (-l  and\n       -v),   the   ability  to  decompress  older  compression  formats  (the\n       ``reduce,''  ``shrink''  and  ``implode''  methods).   The  ability  to\n       extract  to a directory other than the current one can be selected as a\n       compile-time option, which is now enabled  by  default  since  UnZipSFX\n       version  5.5.   Similarly,  decryption  is  supported as a compile-time\n       option but should be  avoided  unless  the  attached  archive  contains\n       encrypted files. Starting with release 5.5, another compile-time option\n       adds a simple ``run command after extraction'' feature.   This  feature\n       is  currently  incompatible with the ``extract to different directory''\n       feature and remains disabled by default.\n\n       Note that self-extracting archives made with unzipsfx are no  more  (or\n       less)  portable  across  different  operating systems than is the unzip\n       executable itself.  In general a self-extracting archive made on a par-\n       ticular Unix system, for example, will only self-extract under the same\n       flavor of Unix.  Regular unzip may still be used to extract the  embed-\n       ded  archive  as  with  any normal zipfile, although it will generate a\n       harmless warning about extra bytes at the  beginning  of  the  zipfile.\n       Despite this, however, the self-extracting archive is technically not a\n       valid ZIP archive, and PKUNZIP may be unable to  test  or  extract  it.\n       This limitation is due to the simplistic manner in which the archive is\n       created; the internal directory structure is not updated to reflect the\n       extra bytes prepended to the original zipfile.\n\nARGUMENTS\n       [file(s)]\n              An  optional  list  of archive members to be processed.  Regular\n              expressions (wildcards) similar to those in Unix egrep(1) may be\n              used to match multiple members.  These wildcards may contain:\n\n              *      matches a sequence of 0 or more characters\n\n              ?      matches exactly 1 character\n\n              [...]  matches  any  single character found inside the brackets;\n                     ranges are specified by a beginning character, a  hyphen,\n                     and  an  ending  character.  If an exclamation point or a\n                     caret (`!' or `^') follows the  left  bracket,  then  the\n                     range  of  characters within the brackets is complemented\n                     (that is,  anything  except  the  characters  inside  the\n                     brackets is considered a match).\n\n              (Be  sure  to quote any character that might otherwise be inter-\n              preted or modified by the operating system,  particularly  under\n              Unix and VMS.)\n\n       [-x xfile(s)]\n              An optional list of archive members to be excluded from process-\n              ing.   Since  wildcard  characters  match  directory  separators\n              (`/'),  this option may be used to exclude any files that are in\n              subdirectories.  For example, ``foosfx  *.[ch]  -x  */*''  would\n              extract  all  C  source files in the main directory, but none in\n              any subdirectories.  Without the -x option, all C  source  files\n              in all directories within the zipfile would be extracted.\n\n       If unzipsfx is compiled with SFX_EXDIR defined, the following option is\n       also enabled:\n\n       [-d exdir]\n              An optional directory to which to extract  files.   By  default,\n              all files and subdirectories are recreated in the current direc-\n              tory; the -d option allows extraction in an arbitrary  directory\n              (always  assuming one has permission to write to the directory).\n              The option and directory may be concatenated without  any  white\n              space  between  them,  but note that this may cause normal shell\n              behavior to be suppressed.  In particular, ``-d ~''  (tilde)  is\n              expanded  by  Unix  C  shells  into  the name of the user's home\n              directory, but ``-d~'' is  treated  as  a  literal  subdirectory\n              ``~'' of the current directory.\n\nOPTIONS\n       unzipsfx  supports the following unzip(1L) options:  -c and -p (extract\n       to standard output/screen), -f and  -u  (freshen  and  update  existing\n       files  upon  extraction),  -t (test archive) and -z (print archive com-\n       ment).  All normal listing options (-l, -v and -Z) have  been  removed,\n       but  the  testing  option (-t) may be used as a ``poor man's'' listing.\n       Alternatively, those creating  self-extracting  archives  may  wish  to\n       include a short listing in the zipfile comment.\n\n       See unzip(1L) for a more complete description of these options.\n\nMODIFIERS\n       unzipsfx  currently supports all unzip(1L) modifiers:  -a (convert text\n       files), -n (never overwrite),  -o  (overwrite  without  prompting),  -q\n       (operate  quietly),  -C  (match  names case-insensitively), -L (convert\n       uppercase-OS names to lowercase), -j (junk paths) and -V  (retain  ver-\n       sion  numbers);  plus  the following operating-system specific options:\n       -X (restore VMS owner/protection info), -s (convert spaces in filenames\n       to  underscores  [DOS,  OS/2,  NT])  and -$ (restore volume label [DOS,\n       OS/2, NT, Amiga]).\n\n       (Support for regular ASCII text-conversion may  be  removed  in  future\n       versions, since it is simple enough for the archive's creator to ensure\n       that text files have the appropriate format for the local  OS.   EBCDIC\n       conversion  will  of  course continue to be supported since the zipfile\n       format implies ASCII storage of text files.)\n\n       See unzip(1L) for a more complete description of these modifiers.\n\nENVIRONMENT OPTIONS\n       unzipsfx  uses  the  same  environment  variables  as  unzip(1L)  does,\n       although this is likely to be an issue only for the person creating and\n       testing the self-extracting archive.  See unzip(1L) for details.\n\nDECRYPTION\n       Decryption is supported exactly as in unzip(1L); that is, interactively\n       with  a  non-echoing  prompt  for  the  password(s).  See unzip(1L) for\n       details.  Once again, note that if the archive has no  encrypted  files\n       there  is  no  reason to use a version of unzipsfx with decryption sup-\n       port; that only adds to the size of the archive.\n\nAUTORUN COMMAND\n       When unzipsfx was compiled with  CHEAP_SFX_AUTORUN  defined,  a  simple\n       ``command  autorun'' feature is supported. You may enter a command into\n       the Zip archive comment, using the following format:\n\n           $AUTORUN$>[command line string]\n\n       When unzipsfx recognizes the ``$AUTORUN$>'' token at the  beginning  of\n       the Zip archive comment, the remainder of the first line of the comment\n       (until the first newline character) is passed as a shell command to the\n       operating  system using the C rtl ``system'' function. Before executing\n       the command, unzipsfx displays the command on the console  and  prompts\n       the user for confirmation.  When the user has switched off prompting by\n       specifying the -q option, autorun commands are never executed.\n\n       In case the archive comment contains  additional  lines  of  text,  the\n       remainder  of the archive comment following the first line is displayed\n       normally, unless quiet  operation  was  requested  by  supplying  a  -q\n       option.\n\nEXAMPLES\n       To create a self-extracting archive letters from a regular zipfile let-\n       ters.zip and change the new  archive's  permissions  to  be  world-exe-\n       cutable under Unix:\n\n           cat unzipsfx letters.zip > letters\n           chmod 755 letters\n           zip -A letters\n\n       To  create  the  same archive under MS-DOS, OS/2 or NT (note the use of\n       the /b [binary] option to the copy command):\n\n           copy /b unzipsfx.exe+letters.zip letters.exe\n           zip -A letters.exe\n\n       Under VMS:\n\n           copy unzipsfx.exe,letters.zip letters.exe\n           letters == \"$currentdisk:[currentdir]letters.exe\"\n           zip -A letters.exe\n\n       (The VMS append command may also be used.  The second command  installs\n       the  new  program as a ``foreign command'' capable of taking arguments.\n       The third line assumes that Zip is already installed as a foreign  com-\n       mand.)  Under AmigaDOS:\n\n           MakeSFX letters letters.zip UnZipSFX\n\n       (MakeSFX  is included with the UnZip source distribution and with Amiga\n       binary distributions.  ``zip -A'' doesn't work on Amiga self-extracting\n       archives.)   To  test  (or  list)  the  newly  created  self-extracting\n       archive:\n\n           letters -t\n\n       To test letters quietly, printing only  a  summary  message  indicating\n       whether the archive is OK or not:\n\n           letters -tqq\n\n       To extract the complete contents into the current directory, recreating\n       all files and subdirectories as necessary:\n\n           letters\n\n       To extract all *.txt files (in Unix quote the `*'):\n\n           letters *.txt\n\n       To extract everything except the *.txt files:\n\n           letters -x *.txt\n\n       To extract only the README file to standard output (the screen):\n\n           letters -c README\n\n       To print only the zipfile comment:\n\n           letters -z\n\nLIMITATIONS\n       The principle and fundamental limitation of unzipsfx is that it is  not\n       portable  across architectures or operating systems, and therefore nei-\n       ther are the resulting archives.  For some architectures there is  lim-\n       ited  portability,  however  (e.g., between some flavors of Intel-based\n       Unix).\n\n       Another problem with the current implementation  is  that  any  archive\n       with  ``junk''  prepended  to  the beginning technically is no longer a\n       zipfile (unless zip(1) is used to adjust the zipfile offsets  appropri-\n       ately, as noted above).  unzip(1) takes note of the prepended bytes and\n       ignores them since some file-transfer protocols, notably MacBinary, are\n       also  known  to  prepend  junk.  But PKWARE's archiver suite may not be\n       able to deal with the modified archive unless  its  offsets  have  been\n       adjusted.\n\n       unzipsfx  has no knowledge of the user's PATH, so in general an archive\n       must either be in the current directory when it is invoked, or  else  a\n       full or relative path must be given.  If a user attempts to extract the\n       archive from a directory in  the  PATH  other  than  the  current  one,\n       unzipsfx  will  print  a  warning to the effect, ``can't find myself.''\n       This is always true under Unix and may be true in some cases under  MS-\n       DOS,  depending  on  the compiler used (Microsoft C fully qualifies the\n       program name, but other compilers may not).  Under OS/2  and  NT  there\n       are  operating-system  calls available that provide the full path name,\n       so the archive may be invoked from anywhere in the  user's  path.   The\n       situation is not known for AmigaDOS, Atari TOS, MacOS, etc.\n\n       As  noted  above,  a number of the normal unzip(1L) functions have been\n       removed in order to make unzipsfx smaller:  usage and diagnostic  info,\n       listing  functions  and  extraction  to  other directories.  Also, only\n       stored and deflated files are  supported.   The  latter  limitation  is\n       mainly relevant to those who create SFX archives, however.\n\n       VMS  users  must know how to set up self-extracting archives as foreign\n       commands in order to use any of unzipsfx's options.  This is not neces-\n       sary  for  simple  extraction,  but  the command to do so then becomes,\n       e.g., ``run letters'' (to continue the examples given above).\n\n       unzipsfx on the Amiga requires the use of a special  program,  MakeSFX,\n       in  order to create working self-extracting archives; simple concatena-\n       tion does not work.  (For  technically  oriented  users,  the  attached\n       archive  is  defined  as a ``debug hunk.'')  There may be compatibility\n       problems between the ROM levels of older Amigas and newer ones.\n\n       All current bugs in unzip(1L) exist in unzipsfx as well.\n\nDIAGNOSTICS\n       unzipsfx's exit status (error level) is identical to that of unzip(1L);\n       see the corresponding man page.\n\nSEE ALSO\n       funzip(1L), unzip(1L), zip(1L), zipcloak(1L), zipgrep(1L), zipinfo(1L),\n       zipnote(1L), zipsplit(1L)\n\nURL\n       The Info-ZIP home page is currently at\n           http://www.info-zip.org/pub/infozip/\n       or\n           ftp://ftp.info-zip.org/pub/infozip/ .\n\nAUTHORS\n       Greg Roelofs was responsible for the basic modifications to UnZip  nec-\n       essary  to create UnZipSFX.  See unzip(1L) for the current list of Zip-\n       Bugs authors, or the file CONTRIBS in the UnZip source distribution for\n       the full list of Info-ZIP contributors.\n\nInfo-ZIP                     20 April 2009 (v6.0)                 UNZIPSFX(1L)\n"
  },
  {
    "path": "deps/infozip/unzip60/unzipstb.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unzipstb.c\n\n  Simple stub function for UnZip DLL (or shared library, whatever); does\n  exactly the same thing as normal UnZip, except for additional printf()s\n  of various version numbers, solely as a demonstration of what can/should\n  be checked when using the DLL.  (If major version numbers ever differ,\n  assume program is incompatible with DLL--especially if DLL version is\n  older.  This is not likely to be a problem with *this* simple program,\n  but most user programs will be much more complex.)\n\n  ---------------------------------------------------------------------------*/\n\n#include <stdio.h>\n#include \"unzip.h\"\n#if defined(MODERN) && !defined(NO_STDDEF_H)\n# include <stddef.h>\n#endif\n#include \"unzvers.h\"\n\nint main(int argc, char *argv[])\n{\n    static ZCONST UzpVer *pVersion;     /* no pervert jokes, please... */\n\n    pVersion = UzpVersion();\n\n    printf(\"UnZip stub:  checking version numbers (DLL is dated %s)\\n\",\n      pVersion->date);\n    printf(\"   UnZip versions:    expecting %u.%u%u, using %u.%u%u%s\\n\",\n      UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, pVersion->unzip.major,\n      pVersion->unzip.minor, pVersion->unzip.patchlevel, pVersion->betalevel);\n    printf(\"   ZipInfo versions:  expecting %u.%u%u, using %u.%u%u\\n\",\n      ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, pVersion->zipinfo.major,\n      pVersion->zipinfo.minor, pVersion->zipinfo.patchlevel);\n\n/*\n    D2_M*VER and os2dll.* are obsolete, though retained for compatibility:\n\n    printf(\"   OS2 DLL versions:  expecting %u.%u%u, using %u.%u%u\\n\",\n      D2_MAJORVER, D2_MINORVER, D2_PATCHLEVEL, pVersion->os2dll.major,\n      pVersion->os2dll.minor, pVersion->os2dll.patchlevel);\n */\n\n    if (pVersion->flag & 2)\n        printf(\"   using zlib version %s\\n\", pVersion->zlib_version);\n\n    /* This example code only uses the dll calls UzpVersion() and\n     * UzpMain().  The APIs for these two calls have maintained backward\n     * compatibility since at least the UnZip release 5.3 !\n     */\n#   define UZDLL_MINVERS_MAJOR          5\n#   define UZDLL_MINVERS_MINOR          3\n#   define UZDLL_MINVERS_PATCHLEVEL     0\n    /* This UnZip DLL stub requires a DLL version of at least: */\n    if ( (pVersion->unzip.major < UZDLL_MINVERS_MAJOR) ||\n         ((pVersion->unzip.major == UZDLL_MINVERS_MAJOR) &&\n          ((pVersion->unzip.minor < UZDLL_MINVERS_MINOR) ||\n           ((pVersion->unzip.minor == UZDLL_MINVERS_MINOR) &&\n            (pVersion->unzip.patchlevel < UZDLL_MINVERS_PATCHLEVEL)\n           )\n          )\n         ) )\n    {\n        printf(\"  aborting because of too old UnZip DLL version!\\n\");\n        return -1;\n    }\n\n    /* In case the offsetof() macro is not supported by some C compiler\n       environment, it might be replaced by something like:\n         ((extent)(void *)&(((UzpVer *)0)->dllapimin))\n     */\n    if (pVersion->structlen >=\n#if defined(MODERN) && !defined(NO_STDDEF_H)\n        ( offsetof(UzpVer, dllapimin)\n#else\n          ((unsigned)&(((UzpVer *)0)->dllapimin))\n#endif\n         + sizeof(_version_type) ))\n    {\n#ifdef OS2DLL\n#       define UZ_API_COMP_MAJOR        UZ_OS2API_COMP_MAJOR\n#       define UZ_API_COMP_MINOR        UZ_OS2API_COMP_MINOR\n#       define UZ_API_COMP_REVIS        UZ_OS2API_COMP_REVIS\n#else /* !OS2DLL */\n#ifdef WINDLL\n#       define UZ_API_COMP_MAJOR        UZ_WINAPI_COMP_MAJOR\n#       define UZ_API_COMP_MINOR        UZ_WINAPI_COMP_MINOR\n#       define UZ_API_COMP_REVIS        UZ_WINAPI_COMP_REVIS\n#else /* !WINDLL */\n#       define UZ_API_COMP_MAJOR        UZ_GENAPI_COMP_MAJOR\n#       define UZ_API_COMP_MINOR        UZ_GENAPI_COMP_MINOR\n#       define UZ_API_COMP_REVIS        UZ_GENAPI_COMP_REVIS\n#endif /* ?WINDLL */\n#endif /* ?OS2DLL */\n        printf(\n          \"   UnZip API version: can handle <= %u.%u%u, DLL supplies %u.%u%u\\n\",\n          UZ_API_COMP_MAJOR, UZ_API_COMP_MINOR, UZ_API_COMP_REVIS,\n          pVersion->dllapimin.major, pVersion->dllapimin.minor,\n          pVersion->dllapimin.patchlevel);\n        if ( (pVersion->dllapimin.major > UZ_API_COMP_MAJOR) ||\n             ((pVersion->dllapimin.major == UZ_API_COMP_MAJOR) &&\n              ((pVersion->dllapimin.minor > UZ_API_COMP_MINOR) ||\n               ((pVersion->dllapimin.minor == UZ_API_COMP_MINOR) &&\n                (pVersion->dllapimin.patchlevel > UZ_API_COMP_REVIS)\n               )\n              )\n             ) )\n        {\n            printf(\"  aborting because of unsupported dll api version!\\n\");\n            return -1;\n        }\n    }\n    printf(\"\\n\");\n\n    /* call the actual UnZip routine (string-arguments version) */\n    return UzpMain(argc, argv);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/unzpriv.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unzpriv.h\n\n  This header file contains private (internal) macros, typedefs, prototypes\n  and global-variable declarations used by all of the UnZip source files.\n  In a prior life it was part of the main unzip.h header, but now it is only\n  included by that header if UNZIP_INTERNAL is defined.\n\n  ---------------------------------------------------------------------------*/\n\n\n\n#ifndef __unzpriv_h   /* prevent multiple inclusions */\n#define __unzpriv_h\n\n/* First thing: Signal all following code that we compile UnZip utilities! */\n#ifndef UNZIP\n#  define UNZIP\n#endif\n\n/* GRR 960204:  MORE defined here in preparation for removal altogether */\n#ifndef MORE\n# ifndef RISCOS\n#  define MORE\n# endif\n#endif\n\n/* fUnZip should never need to be reentrant */\n#ifdef FUNZIP\n#  ifdef REENTRANT\n#    undef REENTRANT\n#  endif\n#  ifdef DLL\n#    undef DLL\n#  endif\n#  ifdef SFX            /* fUnZip is NOT the sfx stub! */\n#    undef SFX\n#  endif\n#  ifdef USE_BZIP2      /* fUnZip does not support bzip2 decompression */\n#    undef USE_BZIP2\n#  endif\n#endif\n\n#if (defined(USE_ZLIB) && !defined(HAVE_ZL_INFLAT64) && !defined(NO_DEFLATE64))\n   /* zlib does not (yet?) provide Deflate64(tm) support */\n#  define NO_DEFLATE64\n#endif\n\n#ifdef NO_DEFLATE64\n   /* disable support for Deflate64(tm) */\n#  ifdef USE_DEFLATE64\n#    undef USE_DEFLATE64\n#  endif\n#else\n   /* enable Deflate64(tm) support unless compiling for SFX stub */\n#  if (!defined(USE_DEFLATE64) && !defined(SFX))\n#    define USE_DEFLATE64\n#  endif\n#endif\n\n/* disable bzip2 support for SFX stub, unless explicitly requested */\n#if (defined(SFX) && !defined(BZIP2_SFX) && defined(USE_BZIP2))\n#  undef USE_BZIP2\n#endif\n\n#if (defined(NO_VMS_TEXT_CONV) || defined(VMS))\n#  ifdef VMS_TEXT_CONV\n#    undef VMS_TEXT_CONV\n#  endif\n#else\n#  if (!defined(VMS_TEXT_CONV) && !defined(SFX))\n#    define VMS_TEXT_CONV\n#  endif\n#endif\n\n/* Enable -B option per default on specific systems, to allow backing up\n * files that would be overwritten.\n * (This list of systems must be kept in sync with the list of systems\n * that add the B_flag to the UzpOpts structure, see unzip.h.)\n */\n#if (!defined(NO_UNIXBACKUP) && !defined(UNIXBACKUP))\n#  if defined(UNIX) || defined(OS2) || defined(WIN32)\n#    define UNIXBACKUP\n#  endif\n#endif\n\n#if (defined(DLL) && !defined(REENTRANT))\n#  define REENTRANT\n#endif\n\n#if (!defined(DYNAMIC_CRC_TABLE) && !defined(FUNZIP))\n#  define DYNAMIC_CRC_TABLE\n#endif\n\n#if (defined(DYNAMIC_CRC_TABLE) && !defined(REENTRANT))\n#  ifndef DYNALLOC_CRCTAB\n#    define DYNALLOC_CRCTAB\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    OS-dependent configuration for UnZip internals\n  ---------------------------------------------------------------------------*/\n\n/* Some compiler distributions for Win32/i386 systems try to emulate\n * a Unix (POSIX-compatible) environment.\n */\n#if (defined(WIN32) && defined(UNIX))\n   /* UnZip does not support merging both ports in a single executable. */\n#  if (defined(FORCE_WIN32_OVER_UNIX) && defined(FORCE_UNIX_OVER_WIN32))\n     /* conflicting choice requests -> we prefer the Win32 environment */\n#    undef FORCE_UNIX_OVER_WIN32\n#  endif\n#  ifdef FORCE_WIN32_OVER_UNIX\n     /* native Win32 support was explicitly requested... */\n#    undef UNIX\n#  else\n     /* use the POSIX (Unix) emulation features by default... */\n#    undef WIN32\n#  endif\n#endif\n\n/* bad or (occasionally?) missing stddef.h: */\n#if (defined(M_XENIX) || defined(DNIX))\n#  define NO_STDDEF_H\n#endif\n\n#if (defined(M_XENIX) && !defined(M_UNIX))   /* SCO Xenix only, not SCO Unix */\n#  define SCO_XENIX\n#  define NO_LIMITS_H        /* no limits.h, but MODERN defined */\n#  define NO_UID_GID         /* no uid_t/gid_t */\n#  define size_t int\n#endif\n\n#ifdef realix   /* Modcomp Real/IX, real-time SysV.3 variant */\n#  define SYSV\n#  define NO_UID_GID         /* no uid_t/gid_t */\n#endif\n\n#if (defined(_AIX) && !defined(_ALL_SOURCE))\n#  define _ALL_SOURCE\n#endif\n\n#if defined(apollo)          /* defines __STDC__ */\n#    define NO_STDLIB_H\n#endif\n\n#ifdef DNIX\n#  define SYSV\n#  define SHORT_NAMES         /* 14-char limitation on path components */\n/* #  define FILENAME_MAX  14 */\n#  define FILENAME_MAX  NAME_MAX    /* GRR:  experiment */\n#endif\n\n#if (defined(SYSTEM_FIVE) || defined(__SYSTEM_FIVE))\n#  ifndef SYSV\n#    define SYSV\n#  endif\n#endif /* SYSTEM_FIVE || __SYSTEM_FIVE */\n#if (defined(M_SYSV) || defined(M_SYS5))\n#  ifndef SYSV\n#    define SYSV\n#  endif\n#endif /* M_SYSV || M_SYS5 */\n/* __SVR4 and __svr4__ catch Solaris on at least some combos of compiler+OS */\n#if (defined(__SVR4) || defined(__svr4__) || defined(sgi) || defined(__hpux))\n#  ifndef SYSV\n#    define SYSV\n#  endif\n#endif /* __SVR4 || __svr4__ || sgi || __hpux */\n#if (defined(LINUX) || defined(__QNX__))\n#  ifndef SYSV\n#    define SYSV\n#  endif\n#endif /* LINUX || __QNX__ */\n\n#if (defined(ultrix) || defined(__ultrix) || defined(bsd4_2))\n#  if (!defined(BSD) && !defined(SYSV))\n#    define BSD\n#  endif\n#endif /* ultrix || __ultrix || bsd4_2 */\n#if (defined(sun) || defined(pyr) || defined(CONVEX))\n#  if (!defined(BSD) && !defined(SYSV))\n#    define BSD\n#  endif\n#endif /* sun || pyr || CONVEX */\n\n#ifdef pyr  /* Pyramid:  has BSD and AT&T \"universes\" */\n#  ifdef BSD\n#    define pyr_bsd\n#    define USE_STRINGS_H  /* instead of more common string.h */\n#    define ZMEM           /* ZMEM now uses bcopy/bzero: not in AT&T universe */\n#  endif                   /* (AT&T memcpy claimed to be very slow, though) */\n#  define DECLARE_ERRNO\n#endif /* pyr */\n\n/* stat() bug for Borland, VAX C RTL, and Atari ST MiNT on TOS\n * filesystems:  returns 0 for wildcards!  (returns 0xffffffff on Minix\n * filesystem or `U:' drive under Atari MiNT.)  Watcom C was previously\n * included on this list; it would be good to know what version the problem\n * was fixed at, if it did exist.  */\n#if (defined(__TURBOC__) && !defined(WIN32))\n/*#  define WILD_STAT_BUG*/\n#endif\n#if (defined(VMS) || defined(__MINT__))\n#  define WILD_STAT_BUG\n#endif\n\n/*---------------------------------------------------------------------------\n    OS-dependent includes\n  ---------------------------------------------------------------------------*/\n\n\n/*---------------------------------------------------------------------------\n    API (DLL) section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef DLL\n#  define MAIN   UZ_EXP UzpMain   /* was UzpUnzip */\n#  ifdef OS2DLL\n#    undef Info\n#    define REDIRECTC(c)             varputchar(__G__ c)\n#    define REDIRECTPRINT(buf,size)  varmessage(__G__ buf, size)\n#    define FINISH_REDIRECT()        finish_REXX_redirect(__G)\n#  else\n#    define REDIRECTC(c)\n#    define REDIRECTPRINT(buf,size)  0\n#    define FINISH_REDIRECT()        close_redirect(__G)\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    Acorn RISCOS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef RISCOS\n#  include \"acorn/riscos.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    Amiga section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef AMIGA\n#  include \"amiga/amiga.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    AOS/VS section (somewhat similar to Unix, apparently):\n  ---------------------------------------------------------------------------*/\n\n#ifdef AOS_VS\n#  ifdef __FILEIO_C\n#    include \"aosvs/aosvs.h\"\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    Atari ST section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef ATARI\n#  include <time.h>\n#  include <stat.h>\n#  include <fcntl.h>\n#  include <limits.h>\n#  define SYMLINKS\n#  define EXE_EXTENSION  \".tos\"\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT  DF_DMY\n#  endif\n#  define DIR_END        '/'\n#  define INT_SPRINTF\n#  define timezone      _timezone\n#  define lenEOL        2\n#  define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}\n#  undef SHORT_NAMES\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#    define TIMESTAMP\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    AtheOS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef __ATHEOS__\n#  include \"atheos/athcfg.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    BeOS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef __BEOS__\n#  include \"beos/beocfg.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    Human68k/X680x0 section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef __human68k__\n   /* DO NOT DEFINE DOS_OS2 HERE!  If Human68k is so much */\n   /*  like MS-DOS and/or OS/2, create DOS_H68_OS2 macro. */\n#  if (!defined(_MBCS) && !defined(NO_MBCS))\n     /* enable MBCS support by default for this system */\n#    define _MBCS\n#  endif\n#  if (defined(_MBCS) && defined(NO_MBCS))\n     /* disable MBCS support when explicitely requested */\n#    undef _MBCS\n#  endif\n#  include <time.h>\n#  include <fcntl.h>\n#  include <io.h>\n#  include <conio.h>\n#  include <sys/stat.h>\n#  ifdef HAVE_MBSTRING_H\n#    include <mbstring.h>\n#  endif\n#  ifdef HAVE_MBCTYPE_H\n#    include <mbctype.h>\n#  else\n#    ifndef _ismbblead\n#      define _ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c)))\n#    endif\n#  endif\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_YMD   /* Japanese standard */\n#  endif\n#  define lenEOL        1\n#  define PutNativeEOL  *q++ = native(LF);\n#  define INT_SPRINTF\n#  define SYMLINKS\n#  ifdef SFX\n#    define MAIN main_sfx\n#  endif\n#endif\n\n/*---------------------------------------------------------------------------\n    Mac section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef MACOS\n#  include \"maccfg.h\"\n#endif /* MACOS */\n\n/*---------------------------------------------------------------------------\n    MS-DOS, OS/2, FLEXOS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef WINDLL\n#  ifdef MORE\n#    undef MORE\n#  endif\n#  ifdef OS2_EAS\n#    undef OS2_EAS\n#  endif\n#endif\n\n#if (defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__)))\n#  ifndef MSC\n#    define MSC               /* This should work for older MSC, too!  */\n#  endif\n#endif\n\n#if (defined(MSDOS) || defined(OS2) || defined(FLEXOS))\n#  include <sys/types.h>      /* off_t, time_t, dev_t, ... */\n#  include <sys/stat.h>\n#  include <io.h>             /* lseek(), open(), setftime(), dup(), creat() */\n#  include <time.h>           /* localtime() */\n#  include <fcntl.h>          /* O_BINARY for open() w/o CR/LF translation */\n\n#  ifdef OS2                  /* defined for all OS/2 compilers */\n#    include \"os2/os2cfg.h\"\n#  else\n#    ifdef FLEXOS\n#      include \"flexos/flxcfg.h\"\n#    else\n#      include \"msdos/doscfg.h\"\n#    endif\n#  endif\n\n#  if (defined(_MSC_VER) && (_MSC_VER == 700) && !defined(GRR))\n    /*\n     * ARGH.  MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not\n     *  1970 Jan 1 00:00.  So we have to diddle time_t's appropriately:  add or\n     *  subtract 70 years' worth of seconds; i.e., number of days times 86400;\n     *  i.e., (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==\n     *  (25550 + 17 + 1) * 86400 == 2209075200 seconds.  We know time_t is an\n     *  unsigned long (ulg) on the only system with this bug.\n     */\n#    define TIMET_TO_NATIVE(x)  (x) += (ulg)2209075200L;\n#    define NATIVE_TO_TIMET(x)  (x) -= (ulg)2209075200L;\n#  endif\n#  if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0450))\n#    define timezone      _timezone\n#  endif\n#  if (defined(__GO32__) || defined(FLEXOS))\n#    define DIR_END       '/'\n#  else\n#    define DIR_END       '\\\\'  /* OS uses '\\\\' as directory separator */\n#    define DIR_END2      '/'   /* also check for '/' (RTL may convert) */\n#  endif\n#  ifdef DATE_FORMAT\n#    undef DATE_FORMAT\n#  endif\n#  define DATE_FORMAT     dateformat()\n#  define lenEOL          2\n#  define PutNativeEOL    {*q++ = native(CR); *q++ = native(LF);}\n#  if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#    define USE_EF_UT_TIME\n#  endif\n#endif /* MSDOS || OS2 || FLEXOS */\n\n/*---------------------------------------------------------------------------\n    MTS section (piggybacks UNIX, I think):\n  ---------------------------------------------------------------------------*/\n\n#ifdef MTS\n#  include <sys/types.h>      /* off_t, time_t, dev_t, ... */\n#  include <sys/stat.h>\n#  include <sys/file.h>       /* MTS uses this instead of fcntl.h */\n#  include <timeb.h>\n#  include <time.h>\n#  include <unix.h>           /* some important non-ANSI routines */\n#  define mkdir(s,n) (-1)     /* no \"make directory\" capability */\n#  define EBCDIC              /* set EBCDIC conversion on */\n#  define NO_STRNICMP         /* unzip's is as good the one in MTS */\n#  define USE_FWRITE\n#  define close_outfile()  fclose(G.outfile)   /* can't set time on files */\n#  define umask(n)            /* don't have umask() on MTS */\n#  define FOPWT         \"w\"   /* open file for writing in TEXT mode */\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_MDY\n#  endif\n#  define lenEOL        1\n#  define PutNativeEOL  *q++ = native(LF);\n#endif /* MTS */\n\n /*---------------------------------------------------------------------------\n    Novell Netware NLM section\n  ---------------------------------------------------------------------------*/\n\n#ifdef NLM\n#  include \"netware/nlmcfg.h\"\n#endif\n\n /*---------------------------------------------------------------------------\n    QDOS section\n  ---------------------------------------------------------------------------*/\n\n#ifdef QDOS\n#  define DIRENT\n#  include <fcntl.h>\n#  include <unistd.h>\n#  include <sys/stat.h>\n#  include <time.h>\n#  include \"qdos/izqdos.h\"\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_MDY\n#  endif\n#  define lenEOL        1\n#  define PutNativeEOL  *q++ = native(LF);\n#  define DIR_END       '_'\n#  define RETURN        QReturn\n#  undef PATH_MAX\n#  define PATH_MAX      36\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#    define TIMESTAMP\n#  endif\n#  define SCREENSIZE(ttrows, ttcols)  screensize(ttrows, ttcols)\n#  define SCREENWIDTH 80\n#endif\n\n/*---------------------------------------------------------------------------\n    Tandem NSK section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef TANDEM\n#  include \"tandem.h\"\n#  include <fcntl.h>\n#  ifndef __INT32\n     /* We are compiling with non-WIDE memory model, int = 16 bits */\n#    ifndef INT_16BIT\n#      define INT_16BIT   /* report \"int\" size is 16-bit to inflate setup */\n#    endif\n#    ifdef USE_DEFLATE64\n       /* Following required for 64k WSIZE of Deflate64 support */\n#      define MED_MEM     /* else OUTBUFSIZ is 64K and fails in do_string */\n#      define INBUFSIZ  8192  /* but larger buffer for real OSes */\n#    endif\n#  endif\n   /* use a single LF delimiter so that writes to 101 text files work */\n#  define PutNativeEOL  *q++ = native(LF);\n#  define lenEOL        1\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT  DF_DMY\n#  endif\n#  define SCREENLINES   25\n   /* USE_EF_UT_TIME is set in tandem.h */\n#  define RESTORE_UIDGID\n#  define NO_STRNICMP\n#endif\n\n/*---------------------------------------------------------------------------\n    THEOS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef THEOS\n#  include \"theos/thscfg.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    TOPS-20 section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef TOPS20\n#  include <sys/types.h>        /* off_t, time_t, dev_t, ... */\n#  include <sys/stat.h>\n#  include <sys/param.h>\n#  include <sys/time.h>\n#  include <sys/timeb.h>\n#  include <sys/file.h>\n#  include <timex.h>\n#  include <monsym.h>           /* get amazing monsym() macro */\n   extern int open(), close(), read();\n   extern int stat(), unlink(), jsys(), fcntl();\n   extern long lseek(), dup(), creat();\n#  define strchr    index       /* GRR: necessary? */\n#  define strrchr   rindex\n#  define REALLY_SHORT_SYMS\n#  define NO_MKDIR\n#  ifndef HAVE_STRNICMP\n#    define NO_STRNICMP           /* probably not provided by TOPS20 C RTL  */\n#  endif\n#  define DIR_BEG       '<'\n#  define DIR_END       '>'\n#  define DIR_EXT       \".directory\"\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_MDY\n#  endif\n#  define EXE_EXTENSION \".exe\"  /* just a guess... */\n#endif /* TOPS20 */\n\n/*---------------------------------------------------------------------------\n    Unix section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef UNIX\n#  include \"unix/unxcfg.h\"\n#endif /* UNIX */\n\n/*---------------------------------------------------------------------------\n    VM/CMS and MVS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef CMS_MVS\n#  include \"vmmvs.h\"\n#  define CLOSE_INFILE()  close_infile(__G)\n#endif\n\n/*---------------------------------------------------------------------------\n    VMS section:\n  ---------------------------------------------------------------------------*/\n\n#ifdef VMS\n#  include \"vms/vmscfg.h\"\n#endif /* VMS */\n\n/*---------------------------------------------------------------------------\n    Win32 (Windows 95/NT) section:\n  ---------------------------------------------------------------------------*/\n\n#if (defined(WIN32) && !defined(POCKET_UNZIP) && !defined(_WIN32_WCE))\n#  include \"win32/w32cfg.h\"\n#endif\n\n/*---------------------------------------------------------------------------\n    Win32 Windows CE section (also POCKET_UNZIP)\n  ---------------------------------------------------------------------------*/\n\n#if (defined(_WIN32_WCE) || defined(POCKET_UNZIP))\n#  include \"wince/wcecfg.h\"\n#endif\n\n\n\n/* ----------------------------------------------------------------------------\n   MUST BE AFTER LARGE FILE INCLUDES\n   ---------------------------------------------------------------------------- */\n/* This stuff calls in types and messes up large file includes.  It needs to\n   go after large file defines in local includes.\n   I am guessing that moving them here probably broke some ports, but hey.\n   10/31/2004 EG */\n/* ----------------------------------------------------------------------------\n   Common includes\n   ---------------------------------------------------------------------------- */\n\n/* Some ports apply specific adjustments which must be in effect before\n   reading the \"standard\" include headers.\n */\n\n#ifdef EFT\n#  define Z_OFF_T off_t  /* Amdahl UTS nonsense (\"extended file types\") */\n#else\n#if (defined(UNIX) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64))\n#  define Z_OFF_T off_t /* 64bit offsets to support 2GB < zipfile size < 4GB */\n#else\n#  define Z_OFF_T long\n#endif\n#endif\n\n#ifndef ZOFF_T_DEFINED\n   typedef Z_OFF_T zoff_t;\n#  define ZOFF_T_DEFINED\n#endif\n#ifndef Z_STAT_DEFINED\n   typedef struct stat z_stat;\n#  define Z_STAT_DEFINED\n#endif\n\n#ifndef MINIX            /* Minix needs it after all the other includes (?) */\n#  include <stdio.h>\n#endif\n\n#include <ctype.h>       /* skip for VMS, to use tolower() function? */\n#include <errno.h>       /* used in mapname() */\n#ifdef USE_STRINGS_H\n#  include <strings.h>   /* strcpy, strcmp, memcpy, index/rindex, etc. */\n#else\n#  include <string.h>    /* strcpy, strcmp, memcpy, strchr/strrchr, etc. */\n#endif\n#if (defined(MODERN) && !defined(NO_LIMITS_H))\n#  include <limits.h>    /* MAX/MIN constant symbols for system types... */\n#endif\n\n/* this include must be down here for SysV.4, for some reason... */\n#include <signal.h>      /* used in unzip.c, fileio.c */\n\n\n#ifdef MODERN\n#  ifndef NO_STDDEF_H\n#    include <stddef.h>\n#  endif\n#  ifndef NO_STDLIB_H\n#    include <stdlib.h>  /* standard library prototypes, malloc(), etc. */\n#  endif\n   typedef size_t extent;\n#else /* !MODERN */\n#  ifndef AOS_VS         /* mostly modern? */\n     Z_OFF_T lseek();\n#    ifdef VAXC          /* not fully modern, but has stdlib.h and void */\n#      include <stdlib.h>\n#    else\n       char *malloc();\n#    endif /* ?VAXC */\n#  endif /* !AOS_VS */\n   typedef unsigned int extent;\n#endif /* ?MODERN */\n\n\n\n\n/*************/\n/*  Defines  */\n/*************/\n\n#define UNZIP_BZ2VERS   46\n#ifdef ZIP64_SUPPORT\n# ifdef USE_BZIP2\n#  define UNZIP_VERSION   UNZIP_BZ2VERS\n# else\n#  define UNZIP_VERSION   45\n# endif\n#else\n#ifdef USE_DEFLATE64\n#  define UNZIP_VERSION   21   /* compatible with PKUNZIP 4.0 */\n#else\n#  define UNZIP_VERSION   20   /* compatible with PKUNZIP 2.0 */\n#endif\n#endif\n#define VMS_UNZIP_VERSION 42   /* if OS-needed-to-extract is VMS:  can do */\n\n#if (defined(MSDOS) || defined(OS2))\n#  define DOS_OS2\n#endif\n\n#if (defined(OS2) || defined(WIN32))\n#  define OS2_W32\n#endif\n\n#if (defined(DOS_OS2) || defined(WIN32))\n#  define DOS_OS2_W32\n#  define DOS_W32_OS2          /* historical:  don't use */\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(__human68k__))\n#  define DOS_H68_OS2_W32\n#endif\n\n#if (defined(DOS_OS2) || defined(FLEXOS))\n#  define DOS_FLX_OS2\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(FLEXOS))\n#  define DOS_FLX_OS2_W32\n#endif\n\n#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))\n#  define DOS_FLX_H68_OS2_W32\n#endif\n\n#if (defined(DOS_FLX_OS2) || defined(NLM))\n#  define DOS_FLX_NLM_OS2\n#endif\n\n#if (defined(DOS_FLX_OS2_W32) || defined(NLM))\n#  define DOS_FLX_NLM_OS2_W32\n#endif\n\n#if (defined(DOS_FLX_H68_OS2_W32) || defined(NLM))\n#  define DOS_FLX_H68_NLM_OS2_W32\n#endif\n\n#if (defined(TOPS20) || defined(VMS))\n#  define T20_VMS\n#endif\n\n#if (defined(MSDOS) || defined(T20_VMS))\n#  define DOS_T20_VMS\n#endif\n\n#if (defined(__ATHEOS__) || defined(__BEOS__))\n#  define ATH_BEO\n#endif\n\n#if (defined(ATH_BEO) || defined(UNIX))\n#  define ATH_BEO_UNX\n#endif\n\n#if (defined(ATH_BEO_UNX) || defined(THEOS))\n#  define ATH_BEO_THS_UNX\n#endif\n\n/* clean up with a few defaults */\n#ifndef DIR_END\n#  define DIR_END       '/'     /* last char before program name or filename */\n#endif\n#ifndef DATE_FORMAT\n# ifdef DATEFMT_ISO_DEFAULT\n#  define DATE_FORMAT   DF_YMD  /* defaults to invariant ISO-style */\n# else\n#  define DATE_FORMAT   DF_MDY  /* defaults to US convention */\n# endif\n#endif\n#ifndef DATE_SEPCHAR\n#  define DATE_SEPCHAR  '-'\n#endif\n#ifndef CLOSE_INFILE\n#  define CLOSE_INFILE()  close(G.zipfd)\n#endif\n#ifndef RETURN\n#  define RETURN        return  /* only used in main() */\n#endif\n#ifndef EXIT\n#  define EXIT          exit\n#endif\n#ifndef USAGE\n#  define USAGE(ret)    usage(__G__ (ret))    /* used in unzip.c, zipinfo.c */\n#endif\n#ifndef TIMET_TO_NATIVE         /* everybody but MSC 7.0 and Macintosh */\n#  define TIMET_TO_NATIVE(x)\n#  define NATIVE_TO_TIMET(x)\n#endif\n#ifndef STRNICMP\n#  ifdef NO_STRNICMP\n#    define STRNICMP zstrnicmp\n#  else\n#    define STRNICMP strnicmp\n#  endif\n#endif\n\n\n#if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_UNX) || defined(RISCOS))\n#  ifndef HAVE_UNLINK\n#    define HAVE_UNLINK\n#  endif\n#endif\n#if (defined(AOS_VS) || defined(ATARI)) /* GRR: others? */\n#  ifndef HAVE_UNLINK\n#    define HAVE_UNLINK\n#  endif\n#endif\n\n/* OS-specific exceptions to the \"ANSI <--> INT_SPRINTF\" rule */\n\n#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))\n#  if (defined(SYSV) || defined(CONVEX) || defined(NeXT) || defined(BSD4_4))\n#    define INT_SPRINTF      /* sprintf() returns int:  SysVish/Posix */\n#  endif\n#  if (defined(DOS_FLX_NLM_OS2_W32) || defined(VMS) || defined(AMIGA))\n#    define INT_SPRINTF      /* sprintf() returns int:  ANSI */\n#  endif\n#  if (defined(ultrix) || defined(__ultrix)) /* Ultrix 4.3 and newer */\n#    if (defined(POSIX) || defined(__POSIX))\n#      define INT_SPRINTF    /* sprintf() returns int:  ANSI/Posix */\n#    endif\n#    ifdef __GNUC__\n#      define PCHAR_SPRINTF  /* undetermined actual return value */\n#    endif\n#  endif\n#  if (defined(__osf__) || defined(_AIX) || defined(CMS_MVS) || defined(THEOS))\n#    define INT_SPRINTF      /* sprintf() returns int:  ANSI/Posix */\n#  endif\n#  if defined(sun)\n#    define PCHAR_SPRINTF    /* sprintf() returns char *:  SunOS cc *and* gcc */\n#  endif\n#endif\n\n/* defaults that we hope will take care of most machines in the future */\n\n#if (!defined(PCHAR_SPRINTF) && !defined(INT_SPRINTF))\n#  ifdef __STDC__\n#    define INT_SPRINTF      /* sprintf() returns int:  ANSI */\n#  endif\n#  ifndef INT_SPRINTF\n#    define PCHAR_SPRINTF    /* sprintf() returns char *:  BSDish */\n#  endif\n#endif\n\n#define MSG_STDERR(f)  (f & 1)        /* bit 0:  0 = stdout, 1 = stderr */\n#define MSG_INFO(f)    ((f & 6) == 0) /* bits 1 and 2:  0 = info */\n#define MSG_WARN(f)    ((f & 6) == 2) /* bits 1 and 2:  1 = warning */\n#define MSG_ERROR(f)   ((f & 6) == 4) /* bits 1 and 2:  2 = error */\n#define MSG_FATAL(f)   ((f & 6) == 6) /* bits 1 and 2:  (3 = fatal error) */\n#define MSG_ZFN(f)     (f & 0x0008)   /* bit 3:  1 = print zipfile name */\n#define MSG_FN(f)      (f & 0x0010)   /* bit 4:  1 = print filename */\n#define MSG_LNEWLN(f)  (f & 0x0020)   /* bit 5:  1 = leading newline if !SOL */\n#define MSG_TNEWLN(f)  (f & 0x0040)   /* bit 6:  1 = trailing newline if !SOL */\n#define MSG_MNEWLN(f)  (f & 0x0080)   /* bit 7:  1 = trailing NL for prompts */\n/* the following are subject to change */\n#define MSG_NO_WGUI(f) (f & 0x0100)   /* bit 8:  1 = skip if Windows GUI */\n#define MSG_NO_AGUI(f) (f & 0x0200)   /* bit 9:  1 = skip if Acorn GUI */\n#define MSG_NO_DLL2(f) (f & 0x0400)   /* bit 10:  1 = skip if OS/2 DLL */\n#define MSG_NO_NDLL(f) (f & 0x0800)   /* bit 11:  1 = skip if WIN32 DLL */\n#define MSG_NO_WDLL(f) (f & 0x1000)   /* bit 12:  1 = skip if Windows DLL */\n\n#if (defined(MORE) && !defined(SCREENLINES))\n#  ifdef DOS_FLX_NLM_OS2_W32\n#    define SCREENLINES 25  /* can be (should be) a function instead */\n#  else\n#    define SCREENLINES 24  /* VT-100s are assumed to be minimal hardware */\n#  endif\n#endif\n#if (defined(MORE) && !defined(SCREENSIZE))\n#  ifndef SCREENWIDTH\n#    define SCREENSIZE(scrrows, scrcols) { \\\n          if ((scrrows) != NULL) *(scrrows) = SCREENLINES; }\n#  else\n#    define SCREENSIZE(scrrows, scrcols) { \\\n          if ((scrrows) != NULL) *(scrrows) = SCREENLINES; \\\n          if ((scrcols) != NULL) *(scrcols) = SCREENWIDTH; }\n#  endif\n#endif\n\n#if (defined(__16BIT__) || defined(MED_MEM) || defined(SMALL_MEM))\n# define DIR_BLKSIZ  64     /* number of directory entries per block\n                             *  (should fit in 4096 bytes, usually) */\n#else\n# define DIR_BLKSIZ 16384   /* use more memory, to reduce long-range seeks */\n#endif\n\n#ifndef WSIZE\n#  ifdef USE_DEFLATE64\n#    define WSIZE   65536L  /* window size--must be a power of two, and */\n#  else                     /*  at least 64K for PKZip's deflate64 method */\n#    define WSIZE   0x8000  /* window size--must be a power of two, and */\n#  endif                    /*  at least 32K for zip's deflate method */\n#endif\n\n#ifdef __16BIT__\n#  ifndef INT_16BIT\n#    define INT_16BIT       /* on 16-bit systems int size is 16 bits */\n#  endif\n#else\n#  define nearmalloc  malloc\n#  define nearfree    free\n#  if (!defined(__IBMC__) || !defined(OS2))\n#    ifndef near\n#      define near\n#    endif\n#    ifndef far\n#      define far\n#    endif\n#  endif\n#endif\n\n#if (defined(DYNALLOC_CRCTAB) && !defined(DYNAMIC_CRC_TABLE))\n#  undef DYNALLOC_CRCTAB\n#endif\n\n#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))\n#  undef DYNALLOC_CRCTAB   /* not safe with reentrant code */\n#endif\n\n#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))\n#  ifdef DYNALLOC_CRCTAB\n#    undef DYNALLOC_CRCTAB\n#  endif\n#endif\n\n#if (defined(USE_ZLIB) && defined(ASM_CRC))\n#  undef ASM_CRC\n#endif\n\n#ifdef USE_ZLIB\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    undef IZ_CRC_BE_OPTIMIZ\n#  endif\n#  ifdef IZ_CRC_LE_OPTIMIZ\n#    undef IZ_CRC_LE_OPTIMIZ\n#  endif\n#endif\n#if (!defined(IZ_CRC_BE_OPTIMIZ) && !defined(IZ_CRC_LE_OPTIMIZ))\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n#    undef IZ_CRCOPTIM_UNFOLDTBL\n#  endif\n#endif\n\n#ifndef INBUFSIZ\n#  if (defined(MED_MEM) || defined(SMALL_MEM))\n#    define INBUFSIZ  2048  /* works for MS-DOS small model */\n#  else\n#    define INBUFSIZ  8192  /* larger buffers for real OSes */\n#  endif\n#endif\n\n#if (defined(INT_16BIT) && (defined(USE_DEFLATE64) || lenEOL > 1))\n   /* For environments using 16-bit integers OUTBUFSIZ must be limited to\n    * less than 64k (do_string() uses \"unsigned\" in calculations involving\n    * OUTBUFSIZ).  This is achieved by defining MED_MEM when WSIZE = 64k (aka\n    * Deflate64 support enabled) or EOL markers contain multiple characters.\n    * (The rule gets applied AFTER the default rule for INBUFSIZ because it\n    * is not neccessary to reduce INBUFSIZE in this case.)\n    */\n#  if (!defined(SMALL_MEM) && !defined(MED_MEM))\n#    define MED_MEM\n#  endif\n#endif\n\n/* Logic for case of small memory, length of EOL > 1:  if OUTBUFSIZ == 2048,\n * OUTBUFSIZ>>1 == 1024 and OUTBUFSIZ>>7 == 16; therefore rawbuf is 1008 bytes\n * and transbuf 1040 bytes.  Have room for 32 extra EOL chars; 1008/32 == 31.5\n * chars/line, smaller than estimated 35-70 characters per line for C source\n * and normal text.  Hence difference is sufficient for most \"average\" files.\n * (Argument scales for larger OUTBUFSIZ.)\n */\n#ifdef SMALL_MEM          /* i.e., 16-bit OSes:  MS-DOS, OS/2 1.x, etc. */\n#  define LoadFarString(x)       fLoadFarString(__G__ (x))\n#  define LoadFarStringSmall(x)  fLoadFarStringSmall(__G__ (x))\n#  define LoadFarStringSmall2(x) fLoadFarStringSmall2(__G__ (x))\n#  if (defined(_MSC_VER) && (_MSC_VER >= 600))\n#    define zfstrcpy(dest, src)  _fstrcpy((dest), (src))\n#    define zfstrcmp(s1, s2)     _fstrcmp((s1), (s2))\n#  endif\n#  if !(defined(SFX) || defined(FUNZIP))\n#    if (defined(_MSC_VER))\n#      define zfmalloc(sz)       _fmalloc((sz))\n#      define zffree(x)          _ffree(x)\n#    endif\n#    if (defined(__TURBOC__))\n#      include <alloc.h>\n#      define zfmalloc(sz)       farmalloc((unsigned long)(sz))\n#      define zffree(x)          farfree(x)\n#    endif\n#  endif /* !(SFX || FUNZIP) */\n#  ifndef Far\n#    define Far far  /* __far only works for MSC 6.00, not 6.0a or Borland */\n#  endif\n#  define OUTBUFSIZ INBUFSIZ\n#  if (lenEOL == 1)\n#    define RAWBUFSIZ (OUTBUFSIZ>>1)\n#  else\n#    define RAWBUFSIZ ((OUTBUFSIZ>>1) - (OUTBUFSIZ>>7))\n#  endif\n#  define TRANSBUFSIZ (OUTBUFSIZ-RAWBUFSIZ)\n   typedef short  shrint;            /* short/int or \"shrink int\" (unshrink) */\n#else\n#  define zfstrcpy(dest, src)       strcpy((dest), (src))\n#  define zfstrcmp(s1, s2)          strcmp((s1), (s2))\n#  define zfmalloc                  malloc\n#  define zffree(x)                 free(x)\n#  ifdef QDOS\n#    define LoadFarString(x)        Qstrfix(x)   /* fix up _ for '.' */\n#    define LoadFarStringSmall(x)   Qstrfix(x)\n#    define LoadFarStringSmall2(x)  Qstrfix(x)\n#  else\n#    define LoadFarString(x)        (char *)(x)\n#    define LoadFarStringSmall(x)   (char *)(x)\n#    define LoadFarStringSmall2(x)  (char *)(x)\n#  endif\n#  ifdef MED_MEM\n#    define OUTBUFSIZ 0xFF80         /* can't malloc arrays of 0xFFE8 or more */\n#    define TRANSBUFSIZ 0xFF80\n     typedef short  shrint;\n#  else\n#    define OUTBUFSIZ (lenEOL*WSIZE) /* more efficient text conversion */\n#    define TRANSBUFSIZ (lenEOL*OUTBUFSIZ)\n#    ifdef AMIGA\n       typedef short shrint;\n#    else\n       typedef int  shrint;          /* for efficiency/speed, we hope... */\n#    endif\n#  endif /* ?MED_MEM */\n#  define RAWBUFSIZ OUTBUFSIZ\n#endif /* ?SMALL_MEM */\n\n#ifndef Far\n#  define Far\n#endif\n\n#ifndef Cdecl\n#  define Cdecl\n#endif\n\n#ifndef MAIN\n#  define MAIN  main\n#endif\n\n#ifdef SFX      /* disable some unused features for SFX executables */\n#  ifndef NO_ZIPINFO\n#    define NO_ZIPINFO\n#  endif\n#  ifdef TIMESTAMP\n#    undef TIMESTAMP\n#  endif\n#endif\n\n#ifdef SFX\n#  ifdef CHEAP_SFX_AUTORUN\n#    ifndef NO_SFX_EXDIR\n#      define NO_SFX_EXDIR\n#    endif\n#  endif\n#  ifndef NO_SFX_EXDIR\n#    ifndef SFX_EXDIR\n#      define SFX_EXDIR\n#    endif\n#  else\n#    ifdef SFX_EXDIR\n#      undef SFX_EXDIR\n#    endif\n#  endif\n#endif\n\n/* user may have defined both by accident...  NOTIMESTAMP takes precedence */\n#if (defined(TIMESTAMP) && defined(NOTIMESTAMP))\n#  undef TIMESTAMP\n#endif\n\n#if (!defined(COPYRIGHT_CLEAN) && !defined(USE_SMITH_CODE))\n#  define COPYRIGHT_CLEAN\n#endif\n\n/* The LZW patent is expired worldwide since 2004-Jul-07, so USE_UNSHRINK\n * is now enabled by default.  See unshrink.c.\n */\n#if (!defined(LZW_CLEAN) && !defined(USE_UNSHRINK))\n#  define USE_UNSHRINK\n#endif\n\n#ifndef O_BINARY\n#  define O_BINARY  0\n#endif\n\n#ifndef PIPE_ERROR\n#  ifndef EPIPE\n#    define EPIPE -1\n#  endif\n#  define PIPE_ERROR (errno == EPIPE)\n#endif\n\n/* File operations--use \"b\" for binary if allowed or fixed length 512 on VMS */\n#ifdef VMS\n#  define FOPR  \"r\",\"ctx=stm\"\n#  define FOPM  \"r+\",\"ctx=stm\",\"rfm=fix\",\"mrs=512\"\n#  define FOPW  \"w\",\"ctx=stm\",\"rfm=fix\",\"mrs=512\"\n#  define FOPWR \"w+\",\"ctx=stm\",\"rfm=fix\",\"mrs=512\"\n#endif /* VMS */\n\n#ifdef CMS_MVS\n/* Binary files must be RECFM=F,LRECL=1 for ftell() to get correct pos */\n/* ...unless byteseek is used.  Let's try that for a while.            */\n#  define FOPR \"rb,byteseek\"\n#  define FOPM \"r+b,byteseek\"\n#  ifdef MVS\n#    define FOPW \"wb,recfm=u,lrecl=32760,byteseek\" /* New binary files */\n#    define FOPWE \"wb\"                             /* Existing binary files */\n#    define FOPWT \"w,lrecl=133\"                    /* New text files */\n#    define FOPWTE \"w\"                             /* Existing text files */\n#  else\n#    define FOPW \"wb,recfm=v,lrecl=32760\"\n#    define FOPWT \"w\"\n#  endif\n#endif /* CMS_MVS */\n\n#ifdef TOPS20          /* TOPS-20 MODERN?  You kidding? */\n#  define FOPW \"w8\"\n#endif /* TOPS20 */\n\n/* Defaults when nothing special has been defined previously. */\n#ifdef MODERN\n#  ifndef FOPR\n#    define FOPR \"rb\"\n#  endif\n#  ifndef FOPM\n#    define FOPM \"r+b\"\n#  endif\n#  ifndef FOPW\n#    define FOPW \"wb\"\n#  endif\n#  ifndef FOPWT\n#    define FOPWT \"wt\"\n#  endif\n#  ifndef FOPWR\n#    define FOPWR \"w+b\"\n#  endif\n#else /* !MODERN */\n#  ifndef FOPR\n#    define FOPR \"r\"\n#  endif\n#  ifndef FOPM\n#    define FOPM \"r+\"\n#  endif\n#  ifndef FOPW\n#    define FOPW \"w\"\n#  endif\n#  ifndef FOPWT\n#    define FOPWT \"w\"\n#  endif\n#  ifndef FOPWR\n#    define FOPWR \"w+\"\n#  endif\n#endif /* ?MODERN */\n\n/*\n * If <limits.h> exists on most systems, should include that, since it may\n * define some or all of the following:  NAME_MAX, PATH_MAX, _POSIX_NAME_MAX,\n * _POSIX_PATH_MAX.\n */\n#ifdef DOS_FLX_NLM_OS2_W32\n#  include <limits.h>\n#endif\n\n/* 2008-07-22 SMS.\n * Unfortunately, on VMS, <limits.h> exists, and is included by <stdlib.h>\n * (so it's pretty much unavoidable), and it defines PATH_MAX to a fixed\n * short value (256, correct only for older systems without ODS-5 support),\n * rather than one based on the real RMS NAM[L] situation.  So, we\n * artificially undefine it here, to allow our better-defined _MAX_PATH\n * (see vms/vmscfg.h) to be used.\n */\n#ifdef VMS\n#  undef PATH_MAX\n#endif\n\n#ifndef PATH_MAX\n#  ifdef MAXPATHLEN\n#    define PATH_MAX      MAXPATHLEN    /* in <sys/param.h> on some systems */\n#  else\n#    ifdef _MAX_PATH\n#      define PATH_MAX    _MAX_PATH\n#    else\n#      if FILENAME_MAX > 255\n#        define PATH_MAX  FILENAME_MAX  /* used like PATH_MAX on some systems */\n#      else\n#        define PATH_MAX  1024\n#      endif\n#    endif /* ?_MAX_PATH */\n#  endif /* ?MAXPATHLEN */\n#endif /* !PATH_MAX */\n\n/*\n * buffer size required to hold the longest legal local filepath\n * (including the trailing '\\0')\n */\n#define FILNAMSIZ  PATH_MAX\n\n#ifdef UNICODE_SUPPORT\n# if !(defined(UTF8_MAYBE_NATIVE) || defined(UNICODE_WCHAR))\n#  undef UNICODE_SUPPORT\n# endif\n#endif\n/* 2007-09-18 SMS.\n * Include <locale.h> here if it will be needed later for Unicode.\n * Otherwise, SETLOCALE may be defined here, and then defined again\n * (differently) when <locale.h> is read later.\n */\n#ifdef UNICODE_SUPPORT\n# ifdef UNICODE_WCHAR\n#  if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))\n#   include <wchar.h>\n#  endif\n# endif\n# ifndef _MBCS  /* no need to include <locale.h> twice, see below */\n#   include <locale.h>\n#   ifndef SETLOCALE\n#     define SETLOCALE(category, locale) setlocale(category, locale)\n#   endif\n# endif\n#endif /* UNICODE_SUPPORT */\n\n/* DBCS support for Info-ZIP  (mainly for japanese (-: )\n * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)\n */\n#ifdef _MBCS\n#  include <locale.h>\n   /* Multi Byte Character Set */\n#  define ___MBS_TMP_DEF  char *___tmp_ptr;\n#  define ___TMP_PTR      ___tmp_ptr\n#  ifndef CLEN\n#    define NEED_UZMBCLEN\n#    define CLEN(ptr) (int)uzmbclen((ZCONST unsigned char *)(ptr))\n#  endif\n#  ifndef PREINCSTR\n#    define PREINCSTR(ptr) (ptr += CLEN(ptr))\n#  endif\n#  define POSTINCSTR(ptr) (___TMP_PTR=(char *)(ptr), PREINCSTR(ptr),___TMP_PTR)\n   char *plastchar OF((ZCONST char *ptr, extent len));\n#  define lastchar(ptr, len) ((int)(unsigned)*plastchar(ptr, len))\n#  ifndef MBSCHR\n#    define NEED_UZMBSCHR\n#    define MBSCHR(str,c) (char *)uzmbschr((ZCONST unsigned char *)(str), c)\n#  endif\n#  ifndef MBSRCHR\n#    define NEED_UZMBSRCHR\n#    define MBSRCHR(str,c) (char *)uzmbsrchr((ZCONST unsigned char *)(str), c)\n#  endif\n#  ifndef SETLOCALE\n#    define SETLOCALE(category, locale) setlocale(category, locale)\n#  endif\n#else /* !_MBCS */\n#  define ___MBS_TMP_DEF\n#  define ___TMP_PTR\n#  define CLEN(ptr) 1\n#  define PREINCSTR(ptr) (++(ptr))\n#  define POSTINCSTR(ptr) ((ptr)++)\n#  define plastchar(ptr, len) (&ptr[(len)-1])\n#  define lastchar(ptr, len) (ptr[(len)-1])\n#  define MBSCHR(str, c) strchr(str, c)\n#  define MBSRCHR(str, c) strrchr(str, c)\n#  ifndef SETLOCALE\n#    define SETLOCALE(category, locale)\n#  endif\n#endif /* ?_MBCS */\n#define INCSTR(ptr) PREINCSTR(ptr)\n\n\n#if (defined(MALLOC_WORK) && !defined(MY_ZCALLOC))\n   /* Any system without a special calloc function */\n# ifndef zcalloc\n#  define zcalloc(items, size) \\\n          (zvoid far *)calloc((unsigned)(items), (unsigned)(size))\n# endif\n# ifndef zcfree\n#  define zcfree    free\n# endif\n#endif /* MALLOC_WORK && !MY_ZCALLOC */\n\n#if (defined(CRAY) && defined(ZMEM))\n#  undef ZMEM\n#endif\n\n#ifdef ZMEM\n#  undef ZMEM\n#  define memcmp(b1,b2,len)      bcmp(b2,b1,len)\n#  define memcpy(dest,src,len)   bcopy(src,dest,len)\n#  define memzero                bzero\n#else\n#  define memzero(dest,len)      memset(dest,0,len)\n#endif\n\n#ifndef TRUE\n#  define TRUE      1   /* sort of obvious */\n#endif\n#ifndef FALSE\n#  define FALSE     0\n#endif\n\n#ifndef SEEK_SET\n#  define SEEK_SET  0\n#  define SEEK_CUR  1\n#  define SEEK_END  2\n#endif\n\n#if (!defined(S_IEXEC) && defined(S_IXUSR))\n#  define S_IEXEC   S_IXUSR\n#endif\n\n#if (defined(UNIX) && defined(S_IFLNK) && !defined(MTS))\n#  define SYMLINKS\n#  ifndef S_ISLNK\n#    define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)\n#  endif\n#endif /* UNIX && S_IFLNK && !MTS */\n\n#ifndef S_ISDIR\n#  ifdef CMS_MVS\n#    define S_ISDIR(m)  (FALSE)\n#  else\n#    define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)\n# endif\n#endif\n\n#ifndef IS_VOLID\n#  define IS_VOLID(m)  ((m) & 0x08)\n#endif\n\n/***********************************/\n/*  LARGE_FILE_SUPPORT             */\n/***********************************/\n/* This whole section lifted from Zip 3b tailor.h\n\n * Types are in OS dependent headers (eg, w32cfg.h)\n *\n * LARGE_FILE_SUPPORT and ZIP64_SUPPORT are automatically\n * set in OS dependent headers (for some ports) based on the port and compiler.\n *\n * Function prototypes are below as OF is defined earlier in this file\n * but after OS dependent header is included.\n *\n * E. Gordon 9/21/2003\n * Updated 1/28/2004\n * Lifted and placed here 6/7/2004 - Myles Bennett\n */\n#ifdef LARGE_FILE_SUPPORT\n  /* 64-bit Large File Support */\n\n/* ---------------------------- */\n\n# if defined(UNIX) || defined(VMS)\n\n    /* 64-bit stat functions */\n#   define zstat stat\n#   define zfstat fstat\n\n    /* 64-bit fseeko */\n#   define zlseek lseek\n#   define zfseeko fseeko\n\n    /* 64-bit ftello */\n#   define zftello ftello\n\n    /* 64-bit fopen */\n#   define zfopen fopen\n#   define zfdopen fdopen\n\n# endif /* UNIX || VMS */\n\n/* ---------------------------- */\n\n# ifdef WIN32\n\n#   if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__)\n    /* MS C (VC), MinGW GCC port and LCC-32 use the MS C Runtime lib */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n#     define zfstat _fstati64\n\n      /* 64-bit lseek */\n#     define zlseek _lseeki64\n\n#     if defined(_MSC_VER) && (_MSC_VER >= 1400)\n        /* Beginning with VS 8.0 (Visual Studio 2005, MSC 14), the Microsoft\n           C rtl publishes its (previously internal) implmentations of\n           \"fseeko\" and \"ftello\" for 64-bit file offsets. */\n        /* 64-bit fseeko */\n#       define zfseeko _fseeki64\n        /* 64-bit ftello */\n#       define zftello _ftelli64\n\n#     else /* not (defined(_MSC_VER) && (_MSC_VER >= 1400)) */\n\n#     if defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__ >= 0x800)\n        /* Up-to-date versions of MinGW define the macro __MSVCRT_VERSION__\n           to denote the version of the MS C rtl dll used for linking.  When\n           configured to link against the runtime of MS Visual Studio 8 (or\n           newer), the built-in 64-bit fseek/ftell functions are available. */\n        /* 64-bit fseeko */\n#       define zfseeko _fseeki64\n        /* 64-bit ftello */\n#       define zftello _ftelli64\n\n#     else /* !(defined(__MSVCRT_VERSION__) && (__MSVCRT_VERSION__>=0x800)) */\n        /* The version of the C runtime is lower than MSC 14 or unknown. */\n\n        /* The newest MinGW port contains built-in extensions to the MSC rtl\n           that provide fseeko and ftello, but our implementations will do\n           for now. */\n       /* 64-bit fseeko */\n       int zfseeko OF((FILE *, zoff_t, int));\n\n       /* 64-bit ftello */\n       zoff_t zftello OF((FILE *));\n\n#     endif /* ? (__MSVCRT_VERSION__ >= 0x800) */\n#     endif /* ? (_MSC_VER >= 1400) */\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif /* _MSC_VER || __MINGW__ || __LCC__ */\n\n#   ifdef __CYGWIN__\n    /* CYGWIN GCC Posix emulator on Windows\n       (configuration not yet finished/tested)  */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n#     define zfstat _fstati64\n\n      /* 64-bit lseek */\n#     define zlseek _lseeki64\n\n      /* 64-bit fseeko */\n#     define zfseeko fseeko\n\n      /* 64-bit ftello */\n#     define zftello ftello\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n#   if defined(__WATCOMC__) || defined(__BORLANDC__)\n    /* WATCOM C and Borland C provide their own C runtime libraries,\n       but they are sufficiently compatible with MS CRTL. */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n#     define zfstat _fstati64\n\n#   ifdef __WATCOMC__\n      /* 64-bit lseek */\n#     define zlseek _lseeki64\n#   endif\n\n      /* 64-bit fseeko */\n      int zfseeko OF((FILE *, zoff_t, int));\n\n      /* 64-bit ftello */\n      zoff_t zftello OF((FILE *));\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n#   ifdef __IBMC__\n      /* IBM C */\n\n      /* 64-bit stat functions */\n\n      /* 64-bit fseeko */\n\n      /* 64-bit ftello */\n\n      /* 64-bit fopen */\n\n#   endif\n\n# endif /* WIN32 */\n\n#else\n  /* No Large File Support */\n\n# ifndef REGULUS  /* returns the inode number on success(!)...argh argh argh */\n#   define zstat stat\n# endif\n# define zfstat fstat\n# define zlseek lseek\n# define zfseeko fseek\n# define zftello ftell\n# define zfopen fopen\n# define zfdopen fdopen\n\n# if defined(UNIX) || defined(VMS) || defined(WIN32)\n    /* For these systems, implement \"64bit file vs. 32bit prog\" check  */\n#   ifndef DO_SAFECHECK_2GB\n#     define DO_SAFECHECK_2GB\n#   endif\n# endif\n\n#endif\n\n/* No \"64bit file vs. 32bit prog\" check for SFX stub, to save space */\n#if (defined(DO_SAFECHECK_2GB) && defined(SFX))\n#  undef DO_SAFECHECK_2GB\n#endif\n\n#ifndef SSTAT\n#  ifdef WILD_STAT_BUG\n#    define SSTAT(path,pbuf) (iswild(path) || zstat(path,pbuf))\n#  else\n#    define SSTAT    zstat\n#  endif\n#endif\n\n\n/* Default fzofft() format selection. */\n\n#ifndef FZOFFT_FMT\n\n#  ifdef LARGE_FILE_SUPPORT\n#    define FZOFFT_FMT \"ll\"\n#    define FZOFFT_HEX_WID_VALUE \"16\"\n#  else /* def LARGE_FILE_SUPPORT */\n#    define FZOFFT_FMT \"l\"\n#    define FZOFFT_HEX_WID_VALUE \"8\"\n#  endif /* def LARGE_FILE_SUPPORT */\n\n#endif /* ndef FZOFFT_FMT */\n\n#define FZOFFT_HEX_WID ((char *) -1)\n#define FZOFFT_HEX_DOT_WID ((char *) -2)\n\n#define FZOFFT_NUM 4            /* Number of chambers. */\n#define FZOFFT_LEN 24           /* Number of characters/chamber. */\n\n\n#ifdef SHORT_SYMS                   /* Mark Williams C, ...? */\n#  define extract_or_test_files     xtr_or_tst_files\n#  define extract_or_test_member    xtr_or_tst_member\n#endif\n\n#ifdef REALLY_SHORT_SYMS            /* TOPS-20 linker:  first 6 chars */\n#  define process_cdir_file_hdr     XXpcdfh\n#  define process_local_file_hdr    XXplfh\n#  define extract_or_test_files     XXxotf  /* necessary? */\n#  define extract_or_test_member    XXxotm  /* necessary? */\n#  define check_for_newer           XXcfn\n#  define overwrite_all             XXoa\n#  define process_all_files         XXpaf\n#  define extra_field               XXef\n#  define explode_lit8              XXel8\n#  define explode_lit4              XXel4\n#  define explode_nolit8            XXnl8\n#  define explode_nolit4            XXnl4\n#  define cpdist8                   XXcpdist8\n#  define inflate_codes             XXic\n#  define inflate_stored            XXis\n#  define inflate_fixed             XXif\n#  define inflate_dynamic           XXid\n#  define inflate_block             XXib\n#  define maxcodemax                XXmax\n#endif\n\n#ifndef S_TIME_T_MAX            /* max value of signed (>= 32-bit) time_t */\n#  define S_TIME_T_MAX  ((time_t)(ulg)0x7fffffffL)\n#endif\n#ifndef U_TIME_T_MAX            /* max value of unsigned (>= 32-bit) time_t */\n#  define U_TIME_T_MAX  ((time_t)(ulg)0xffffffffL)\n#endif\n#ifdef DOSTIME_MINIMUM          /* min DOSTIME value (1980-01-01) */\n#  undef DOSTIME_MINIMUM\n#endif\n#define DOSTIME_MINIMUM ((ulg)0x00210000L)\n#ifdef DOSTIME_2038_01_18       /* approximate DOSTIME equivalent of */\n#  undef DOSTIME_2038_01_18     /*  the signed-32-bit time_t limit */\n#endif\n#define DOSTIME_2038_01_18 ((ulg)0x74320000L)\n\n#ifdef QDOS\n#  define ZSUFX         \"_zip\"\n#  define ALT_ZSUFX     \".zip\"\n#else\n#  ifdef RISCOS\n#    define ZSUFX       \"/zip\"\n#  else\n#    define ZSUFX       \".zip\"\n#  endif\n#  define ALT_ZSUFX     \".ZIP\"   /* Unix-only so far (only case-sensitive fs) */\n#endif\n\n#define CENTRAL_HDR_SIG   \"\\001\\002\"   /* the infamous \"PK\" signature bytes, */\n#define LOCAL_HDR_SIG     \"\\003\\004\"   /*  w/o \"PK\" (so unzip executable not */\n#define END_CENTRAL_SIG   \"\\005\\006\"   /*  mistaken for zipfile itself) */\n#define EXTD_LOCAL_SIG    \"\\007\\010\"   /* [ASCII \"\\113\" == EBCDIC \"\\080\" ??] */\n\n/** internal-only return codes **/\n#define IZ_DIR            76   /* potential zipfile is a directory */\n/* special return codes for mapname() */\n#define MPN_OK            0      /* mapname successful */\n#define MPN_INF_TRUNC    (1<<8)  /* caution - filename truncated */\n#define MPN_INF_SKIP     (2<<8)  /* info  - skipped because nothing to do */\n#define MPN_ERR_SKIP     (3<<8)  /* error - entry skipped */\n#define MPN_ERR_TOOLONG  (4<<8)  /* error - path too long */\n#define MPN_NOMEM        (10<<8) /* error - out of memory, file skipped */\n#define MPN_CREATED_DIR  (16<<8) /* directory created: set time & permission */\n#define MPN_VOL_LABEL    (17<<8) /* volume label, but can't set on hard disk */\n#define MPN_INVALID      (99<<8) /* internal logic error, should never reach */\n/* mask for internal mapname&checkdir return codes */\n#define MPN_MASK          0x7F00\n/* error code for extracting/testing extra field blocks */\n#define IZ_EF_TRUNC       79   /* local extra field truncated (PKZIP'd) */\n\n/* choice of activities for do_string() */\n#define SKIP              0             /* skip header block */\n#define DISPLAY           1             /* display archive comment (ASCII) */\n#define DISPL_8           5             /* display file comment (ext. ASCII) */\n#define DS_FN             2             /* read filename (ext. ASCII, chead) */\n#define DS_FN_C           2             /* read filename from central header */\n#define DS_FN_L           6             /* read filename from local header */\n#define EXTRA_FIELD       3             /* copy extra field into buffer */\n#define DS_EF             3\n#ifdef AMIGA\n#  define FILENOTE        4             /* convert file comment to filenote */\n#endif\n#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))\n#  define CHECK_AUTORUN   7             /* copy command, display remainder */\n#  define CHECK_AUTORUN_Q 8             /* copy command, skip remainder */\n#endif\n\n#define DOES_NOT_EXIST    -1   /* return values for check_for_newer() */\n#define EXISTS_AND_OLDER  0\n#define EXISTS_AND_NEWER  1\n\n#define OVERWRT_QUERY     0    /* status values for G.overwrite_mode */\n#define OVERWRT_ALWAYS    1\n#define OVERWRT_NEVER     2\n\n#define IS_OVERWRT_ALL    (G.overwrite_mode == OVERWRT_ALWAYS)\n#define IS_OVERWRT_NONE   (G.overwrite_mode == OVERWRT_NEVER)\n\n#ifdef VMS\n  /* return codes for VMS-specific open_outfile() function */\n# define OPENOUT_OK       0   /* file openend normally */\n# define OPENOUT_FAILED   1   /* file open failed */\n# define OPENOUT_SKIPOK   2   /* file not opened, skip at error level OK */\n# define OPENOUT_SKIPWARN 3   /* file not opened, skip at error level WARN */\n#endif /* VMS */\n\n#define ROOT              0    /* checkdir() extract-to path:  called once */\n#define INIT              1    /* allocate buildpath:  called once per member */\n#define APPEND_DIR        2    /* append a dir comp.:  many times per member */\n#define APPEND_NAME       3    /* append actual filename:  once per member */\n#define GETPATH           4    /* retrieve the complete path and free it */\n#define END               5    /* free root path prior to exiting program */\n\n/* version_made_by codes (central dir):  make sure these */\n/*  are not defined on their respective systems!! */\n#define FS_FAT_           0    /* filesystem used by MS-DOS, OS/2, Win32 */\n#define AMIGA_            1\n#define VMS_              2\n#define UNIX_             3\n#define VM_CMS_           4\n#define ATARI_            5    /* what if it's a minix filesystem? [cjh] */\n#define FS_HPFS_          6    /* filesystem used by OS/2 (and NT 3.x) */\n#define MAC_              7    /* HFS filesystem used by MacOS */\n#define Z_SYSTEM_         8\n#define CPM_              9\n#define TOPS20_           10\n#define FS_NTFS_          11   /* filesystem used by Windows NT */\n#define QDOS_             12\n#define ACORN_            13   /* Archimedes Acorn RISC OS */\n#define FS_VFAT_          14   /* filesystem used by Windows 95, NT */\n#define MVS_              15\n#define BEOS_             16   /* hybrid POSIX/database filesystem */\n#define TANDEM_           17   /* Tandem NSK */\n#define THEOS_            18   /* THEOS */\n#define MAC_OSX_          19   /* Mac OS/X (Darwin) */\n#define ATHEOS_           30   /* AtheOS */\n#define NUM_HOSTS         31   /* index of last system + 1 */\n/* don't forget to update zipinfo.c appropiately if NUM_HOSTS changes! */\n\n#define STORED            0    /* compression methods */\n#define SHRUNK            1\n#define REDUCED1          2\n#define REDUCED2          3\n#define REDUCED3          4\n#define REDUCED4          5\n#define IMPLODED          6\n#define TOKENIZED         7\n#define DEFLATED          8\n#define ENHDEFLATED       9\n#define DCLIMPLODED      10\n#define BZIPPED          12\n#define LZMAED           14\n#define IBMTERSED        18\n#define IBMLZ77ED        19\n#define WAVPACKED        97\n#define PPMDED           98\n#define NUM_METHODS      17     /* number of known method IDs */\n/* don't forget to update list.c (list_files()), extract.c and zipinfo.c\n * appropriately if NUM_METHODS changes */\n\n/* (the PK-class error codes are public and have been moved into unzip.h) */\n\n#define DF_MDY            0    /* date format 10/26/91 (USA only) */\n#define DF_DMY            1    /* date format 26/10/91 (most of the world) */\n#define DF_YMD            2    /* date format 91/10/26 (a few countries) */\n\n/*---------------------------------------------------------------------------\n    Extra-field block ID values and offset info.\n  ---------------------------------------------------------------------------*/\n/* extra-field ID values, all little-endian: */\n#define EF_PKSZ64    0x0001    /* PKWARE's 64-bit filesize extensions */\n#define EF_AV        0x0007    /* PKWARE's authenticity verification */\n#define EF_EFS       0x0008    /* PKWARE's extended language encoding */\n#define EF_OS2       0x0009    /* OS/2 extended attributes */\n#define EF_PKW32     0x000a    /* PKWARE's Win95/98/WinNT filetimes */\n#define EF_PKVMS     0x000c    /* PKWARE's VMS */\n#define EF_PKUNIX    0x000d    /* PKWARE's Unix */\n#define EF_PKFORK    0x000e    /* PKWARE's future stream/fork descriptors */\n#define EF_PKPATCH   0x000f    /* PKWARE's patch descriptor */\n#define EF_PKPKCS7   0x0014    /* PKWARE's PKCS#7 store for X.509 Certs */\n#define EF_PKFX509   0x0015    /* PKWARE's file X.509 Cert&Signature ID */\n#define EF_PKCX509   0x0016    /* PKWARE's central dir X.509 Cert ID */\n#define EF_PKENCRHD  0x0017    /* PKWARE's Strong Encryption header */\n#define EF_PKRMCTL   0x0018    /* PKWARE's Record Management Controls*/\n#define EF_PKLSTCS7  0x0019    /* PKWARE's PKCS#7 Encr. Recipient Cert List */\n#define EF_PKIBM     0x0065    /* PKWARE's IBM S/390 & AS/400 attributes */\n#define EF_PKIBM2    0x0066    /* PKWARE's IBM S/390 & AS/400 compr. attribs */\n#define EF_IZVMS     0x4d49    /* Info-ZIP's VMS (\"IM\") */\n#define EF_IZUNIX    0x5855    /* Info-ZIP's first Unix[1] (\"UX\") */\n#define EF_IZUNIX2   0x7855    /* Info-ZIP's second Unix[2] (\"Ux\") */\n#define EF_IZUNIX3   0x7875    /* Info-ZIP's newest Unix[3] (\"ux\") */\n#define EF_TIME      0x5455    /* universal timestamp (\"UT\") */\n#define EF_UNIPATH   0x7075    /* Info-ZIP Unicode Path (\"up\") */\n#define EF_UNICOMNT  0x6375    /* Info-ZIP Unicode Comment (\"uc\") */\n#define EF_MAC3      0x334d    /* Info-ZIP's new Macintosh (= \"M3\") */\n#define EF_JLMAC     0x07c8    /* Johnny Lee's old Macintosh (= 1992) */\n#define EF_ZIPIT     0x2605    /* Thomas Brown's Macintosh (ZipIt) */\n#define EF_ZIPIT2    0x2705    /* T. Brown's Mac (ZipIt) v 1.3.8 and newer ? */\n#define EF_SMARTZIP  0x4d63    /* Mac SmartZip by Marco Bambini */\n#define EF_VMCMS     0x4704    /* Info-ZIP's VM/CMS (\"\\004G\") */\n#define EF_MVS       0x470f    /* Info-ZIP's MVS (\"\\017G\") */\n#define EF_ACL       0x4c41    /* (OS/2) access control list (\"AL\") */\n#define EF_NTSD      0x4453    /* NT security descriptor (\"SD\") */\n#define EF_ATHEOS    0x7441    /* AtheOS (\"At\") */\n#define EF_BEOS      0x6542    /* BeOS (\"Be\") */\n#define EF_QDOS      0xfb4a    /* SMS/QDOS (\"J\\373\") */\n#define EF_AOSVS     0x5356    /* AOS/VS (\"VS\") */\n#define EF_SPARK     0x4341    /* David Pilling's Acorn/SparkFS (\"AC\") */\n#define EF_TANDEM    0x4154    /* Tandem NSK (\"TA\") */\n#define EF_THEOS     0x6854    /* Jean-Michel Dubois' Theos \"Th\" */\n#define EF_THEOSO    0x4854    /* old Theos port */\n#define EF_MD5       0x4b46    /* Fred Kantor's MD5 (\"FK\") */\n#define EF_ASIUNIX   0x756e    /* ASi's Unix (\"nu\") */\n\n#define EB_HEADSIZE       4    /* length of extra field block header */\n#define EB_ID             0    /* offset of block ID in header */\n#define EB_LEN            2    /* offset of data length field in header */\n#define EB_UCSIZE_P       0    /* offset of ucsize field in compr. data */\n#define EB_CMPRHEADLEN    6    /* lenght of compression header */\n\n#define EB_UX_MINLEN      8    /* minimal \"UX\" field contains atime, mtime */\n#define EB_UX_FULLSIZE    12   /* full \"UX\" field (atime, mtime, uid, gid) */\n#define EB_UX_ATIME       0    /* offset of atime in \"UX\" extra field data */\n#define EB_UX_MTIME       4    /* offset of mtime in \"UX\" extra field data */\n#define EB_UX_UID         8    /* byte offset of UID in \"UX\" field data */\n#define EB_UX_GID         10   /* byte offset of GID in \"UX\" field data */\n\n#define EB_UX2_MINLEN     4    /* minimal \"Ux\" field contains UID/GID */\n#define EB_UX2_UID        0    /* byte offset of UID in \"Ux\" field data */\n#define EB_UX2_GID        2    /* byte offset of GID in \"Ux\" field data */\n#define EB_UX2_VALID      (1 << 8)      /* UID/GID present */\n\n#define EB_UX3_MINLEN     7    /* minimal \"ux\" field size (2-byte UID/GID) */\n\n#define EB_UT_MINLEN      1    /* minimal UT field contains Flags byte */\n#define EB_UT_FLAGS       0    /* byte offset of Flags field */\n#define EB_UT_TIME1       1    /* byte offset of 1st time value */\n#define EB_UT_FL_MTIME    (1 << 0)      /* mtime present */\n#define EB_UT_FL_ATIME    (1 << 1)      /* atime present */\n#define EB_UT_FL_CTIME    (1 << 2)      /* ctime present */\n\n#define EB_FLGS_OFFS      4    /* offset of flags area in generic compressed\n                                  extra field blocks (BEOS, MAC, and others) */\n#define EB_OS2_HLEN       4    /* size of OS2/ACL compressed data header */\n#define EB_BEOS_HLEN      5    /* length of BeOS&AtheOS e.f attribute header */\n#define EB_BE_FL_UNCMPR   0x01 /* \"BeOS&AtheOS attribs uncompr.\" bit flag */\n#define EB_MAC3_HLEN      14   /* length of Mac3 attribute block header */\n#define EB_SMARTZIP_HLEN  64   /* fixed length of the SmartZip extra field */\n#define EB_M3_FL_DATFRK   0x01 /* \"this entry is data fork\" flag */\n#define EB_M3_FL_UNCMPR   0x04 /* \"Mac3 attributes uncompressed\" bit flag */\n#define EB_M3_FL_TIME64   0x08 /* \"Mac3 time fields are 64 bit wide\" flag */\n#define EB_M3_FL_NOUTC    0x10 /* \"Mac3 timezone offset fields missing\" flag */\n\n#define EB_NTSD_C_LEN     4    /* length of central NT security data */\n#define EB_NTSD_L_LEN     5    /* length of minimal local NT security data */\n#define EB_NTSD_VERSION   4    /* offset of NTSD version byte */\n#define EB_NTSD_MAX_VER   (0)  /* maximum version # we know how to handle */\n\n#define EB_ASI_CRC32      0    /* offset of ASI Unix field's crc32 checksum */\n#define EB_ASI_MODE       4    /* offset of ASI Unix permission mode field */\n\n#define EB_IZVMS_HLEN     12   /* length of IZVMS attribute block header */\n#define EB_IZVMS_FLGS     4    /* offset of compression type flag */\n#define EB_IZVMS_UCSIZ    6    /* offset of ucsize field in IZVMS header */\n#define EB_IZVMS_BCMASK   07   /* 3 bits for compression type */\n#define EB_IZVMS_BCSTOR   0    /*  Stored */\n#define EB_IZVMS_BC00     1    /*  0byte -> 0bit compression */\n#define EB_IZVMS_BCDEFL   2    /*  Deflated */\n\n\n/*---------------------------------------------------------------------------\n    True sizes of the various headers (excluding their 4-byte signatures),\n    as defined by PKWARE--so it is not likely that these will ever change.\n    But if they do, make sure both these defines AND the typedefs below get\n    updated accordingly.\n\n    12/27/2006\n    The Zip64 End Of Central Directory record is variable size and now\n    comes in two flavors, version 1 and the new version 2 that supports\n    central directory encryption.  We only use the old fields at the\n    top of the Zip64 EOCDR, and this block is a fixed size still, but\n    need to be aware of the stuff following.\n  ---------------------------------------------------------------------------*/\n#define LREC_SIZE    26   /* lengths of local file headers, central */\n#define CREC_SIZE    42   /*  directory headers, end-of-central-dir */\n#define ECREC_SIZE   18   /*  record, zip64 end-of-cent-dir locator */\n#define ECLOC64_SIZE 16   /*  and zip64 end-of-central-dir record,  */\n#define ECREC64_SIZE 52   /*  respectively                          */\n\n#define MAX_BITS    13                 /* used in unshrink() */\n#define HSIZE       (1 << MAX_BITS)    /* size of global work area */\n\n#define LF     10        /* '\\n' on ASCII machines; must be 10 due to EBCDIC */\n#define CR     13        /* '\\r' on ASCII machines; must be 13 due to EBCDIC */\n#define CTRLZ  26        /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */\n\n#ifdef EBCDIC\n#  define foreign(c)    ascii[(uch)(c)]\n#  define native(c)     ebcdic[(uch)(c)]\n#  define NATIVE        \"EBCDIC\"\n#  define NOANSIFILT\n#endif\n\n#ifdef VMS\n#  define ENV_UNZIP       \"UNZIP_OPTS\"     /* names of environment variables */\n#  define ENV_ZIPINFO     \"ZIPINFO_OPTS\"\n#endif /* VMS */\n#ifdef RISCOS\n#  define ENV_UNZIP       \"Unzip$Options\"\n#  define ENV_ZIPINFO     \"Zipinfo$Options\"\n#  define ENV_UNZIPEXTS   \"Unzip$Exts\"\n#endif /* RISCOS */\n#ifndef ENV_UNZIP\n#  define ENV_UNZIP       \"UNZIP\"          /* the standard names */\n#  define ENV_ZIPINFO     \"ZIPINFO\"\n#endif\n#define ENV_UNZIP2        \"UNZIPOPT\"     /* alternate names, for zip compat. */\n#define ENV_ZIPINFO2      \"ZIPINFOOPT\"\n\n#if (!defined(QQ) && !defined(NOQQ))\n#  define QQ\n#endif\n\n#ifdef QQ                         /* Newtware version:  no file */\n#  define QCOND     (!uO.qflag)   /*  comments with -vq or -vqq */\n#else                             /* Bill Davidsen version:  no way to */\n#  define QCOND     (longhdr)     /*  kill file comments when listing */\n#endif\n\n#ifdef OLD_QQ\n#  define QCOND2    (uO.qflag < 2)\n#else\n#  define QCOND2    (!uO.qflag)\n#endif\n\n#ifdef WILD_STOP_AT_DIR\n#  define __WDLPRO  , int sepc\n#  define __WDL     , sepc\n#  define __WDLDEF  int sepc;\n#  define WISEP     , (uO.W_flag ? '/' : '\\0')\n#else\n#  define __WDLPRO\n#  define __WDL\n#  define __WDLDEF\n#  define WISEP\n#endif\n\n\n\n\n/**************/\n/*  Typedefs  */\n/**************/\n\n#ifdef ZIP64_SUPPORT\n# ifndef Z_UINT8_DEFINED\n#   if (defined(__GNUC__) || defined(__hpux) || defined(__SUNPRO_C))\n  typedef unsigned long long    z_uint8;\n#   else\n  typedef unsigned __int64      z_uint8;\n#   endif\n#   define Z_UINT8_DEFINED\n# endif\n#endif\n#ifndef Z_UINT4_DEFINED\n# if (defined(MODERN) && !defined(NO_LIMITS_H))\n#  if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL))\n     typedef unsigned int       z_uint4;\n#    define Z_UINT4_DEFINED\n#  else\n#  if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL))\n     typedef unsigned long      z_uint4;\n#    define Z_UINT4_DEFINED\n#  else\n#  if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL))\n     typedef unsigned short     z_uint4;\n#    define Z_UINT4_DEFINED\n#  endif\n#  endif\n#  endif\n# endif /* MODERN && !NO_LIMITS_H */\n#endif /* !Z_UINT4_DEFINED */\n#ifndef Z_UINT4_DEFINED\n  typedef ulg                   z_uint4;\n# define Z_UINT4_DEFINED\n#endif\n\n/* The following three user-defined unsigned integer types are used for\n   holding zipfile entities (required widths without / with Zip64 support):\n   a) sizes and offset of zipfile entries\n      (4 bytes / 8 bytes)\n   b) enumeration and counts of zipfile entries\n      (2 bytes / 8 bytes)\n      Remark: internally, we use 4 bytes for archive member counting in the\n              No-Zip64 case, because UnZip supports more than 64k entries for\n              classic Zip archives without Zip64 extensions.\n   c) enumeration and counts of zipfile volumes of multivolume archives\n      (2 bytes / 4 bytes)\n */\n#ifdef ZIP64_SUPPORT\n  typedef  z_uint8              zusz_t;     /* zipentry sizes & offsets */\n  typedef  z_uint8              zucn_t;     /* archive entry counts */\n  typedef  z_uint4              zuvl_t;     /* multivolume numbers */\n# define MASK_ZUCN64            (~(zucn_t)0)\n/* In case we ever get to support an environment where z_uint8 may be WIDER\n   than 64 bit wide, we will have to apply a construct similar to\n     #define MASK_ZUCN64        (~(zucn_t)0 & (zucn_t)0xffffffffffffffffULL)\n   for the 64-bit mask.\n */\n#else\n  typedef  ulg                  zusz_t;     /* zipentry sizes & offsets */\n  typedef  unsigned int         zucn_t;     /* archive entry counts */\n  typedef  unsigned short       zuvl_t;     /* multivolume numbers */\n# define MASK_ZUCN64            (~(zucn_t)0)\n#endif\n#define MASK_ZUCN16             ((zucn_t)0xFFFF)\n\n#ifdef NO_UID_GID\n#  ifdef UID_USHORT\n     typedef unsigned short  uid_t;    /* TI SysV.3 */\n     typedef unsigned short  gid_t;\n#  else\n     typedef unsigned int    uid_t;    /* SCO Xenix */\n     typedef unsigned int    gid_t;\n#  endif\n#endif\n\n#if (defined(GOT_UTIMBUF) || defined(sgi) || defined(ATARI))\n   typedef struct utimbuf ztimbuf;\n#else\n   typedef struct ztimbuf {\n       time_t actime;        /* new access time */\n       time_t modtime;       /* new modification time */\n   } ztimbuf;\n#endif\n\ntypedef struct iztimes {\n   time_t atime;             /* new access time */\n   time_t mtime;             /* new modification time */\n   time_t ctime;             /* used for creation time; NOT same as st_ctime */\n} iztimes;\n\n#ifdef SET_DIR_ATTRIB\n   typedef struct direntry {    /* head of system-specific struct holding */\n       struct direntry *next;   /*  defered directory attributes info */\n       char *fn;                /* filename of directory */\n       char buf[1];             /* start of system-specific internal data */\n   } direntry;\n#endif /* SET_DIR_ATTRIB */\n\n#ifdef SYMLINKS\n   typedef struct slinkentry {  /* info for deferred symlink creation */\n       struct slinkentry *next; /* pointer to next entry in chain */\n       extent targetlen;        /* length of target filespec */\n       extent attriblen;        /* length of system-specific attrib data */\n       char *target;            /* pointer to target filespec */\n       char *fname;             /* pointer to name of link */\n       char buf[1];             /* data/name/link buffer */\n   } slinkentry;\n#endif /* SYMLINKS */\n\ntypedef struct min_info {\n    zoff_t offset;\n    zusz_t compr_size;       /* compressed size (needed if extended header) */\n    zusz_t uncompr_size;     /* uncompressed size (needed if extended header) */\n    ulg crc;                 /* crc (needed if extended header) */\n    zuvl_t diskstart;        /* no of volume where this entry starts */\n    uch hostver;\n    uch hostnum;\n    unsigned file_attr;      /* local flavor, as used by creat(), chmod()... */\n    unsigned encrypted : 1;  /* file encrypted: decrypt before uncompressing */\n    unsigned ExtLocHdr : 1;  /* use time instead of CRC for decrypt check */\n    unsigned textfile : 1;   /* file is text (according to zip) */\n    unsigned textmode : 1;   /* file is to be extracted as text */\n    unsigned lcflag : 1;     /* convert filename to lowercase */\n    unsigned vollabel : 1;   /* \"file\" is an MS-DOS volume (disk) label */\n#ifdef SYMLINKS\n    unsigned symlink : 1;    /* file is a symbolic link */\n#endif\n    unsigned HasUxAtt : 1;   /* crec ext_file_attr has Unix style mode bits */\n#ifdef UNICODE_SUPPORT\n    unsigned GPFIsUTF8: 1;   /* crec gen_purpose_flag UTF-8 bit 11 is set */\n#endif\n#ifndef SFX\n    char Far *cfilname;      /* central header version of filename */\n#endif\n} min_info;\n\ntypedef struct VMStimbuf {\n    char *revdate;    /* (both roughly correspond to Unix modtime/st_mtime) */\n    char *credate;\n} VMStimbuf;\n\n/*---------------------------------------------------------------------------\n    Zipfile work area declarations.\n  ---------------------------------------------------------------------------*/\n\n#ifdef MALLOC_WORK\n   union work {\n     struct {                 /* unshrink(): */\n       shrint *Parent;          /* pointer to (8192 * sizeof(shrint)) */\n       uch *value;              /* pointer to 8KB char buffer */\n       uch *Stack;              /* pointer to another 8KB char buffer */\n     } shrink;\n     uch *Slide;              /* explode(), inflate(), unreduce() */\n   };\n#else /* !MALLOC_WORK */\n   union work {\n     struct {                 /* unshrink(): */\n       shrint Parent[HSIZE];    /* (8192 * sizeof(shrint)) == 16KB minimum */\n       uch value[HSIZE];        /* 8KB */\n       uch Stack[HSIZE];        /* 8KB */\n     } shrink;                  /* total = 32KB minimum; 80KB on Cray/Alpha */\n     uch Slide[WSIZE];        /* explode(), inflate(), unreduce() */\n   };\n#endif /* ?MALLOC_WORK */\n\n#define slide  G.area.Slide\n\n#if (defined(DLL) && !defined(NO_SLIDE_REDIR))\n#  define redirSlide G.redirect_sldptr\n#else\n#  define redirSlide G.area.Slide\n#endif\n\n/*---------------------------------------------------------------------------\n    Zipfile layout declarations.  If these headers ever change, make sure the\n    xxREC_SIZE defines (above) change with them!\n  ---------------------------------------------------------------------------*/\n\n   typedef uch   local_byte_hdr[ LREC_SIZE ];\n#      define L_VERSION_NEEDED_TO_EXTRACT_0     0\n#      define L_VERSION_NEEDED_TO_EXTRACT_1     1\n#      define L_GENERAL_PURPOSE_BIT_FLAG        2\n#      define L_COMPRESSION_METHOD              4\n#      define L_LAST_MOD_DOS_DATETIME           6\n#      define L_CRC32                           10\n#      define L_COMPRESSED_SIZE                 14\n#      define L_UNCOMPRESSED_SIZE               18\n#      define L_FILENAME_LENGTH                 22\n#      define L_EXTRA_FIELD_LENGTH              24\n\n   typedef uch   cdir_byte_hdr[ CREC_SIZE ];\n#      define C_VERSION_MADE_BY_0               0\n#      define C_VERSION_MADE_BY_1               1\n#      define C_VERSION_NEEDED_TO_EXTRACT_0     2\n#      define C_VERSION_NEEDED_TO_EXTRACT_1     3\n#      define C_GENERAL_PURPOSE_BIT_FLAG        4\n#      define C_COMPRESSION_METHOD              6\n#      define C_LAST_MOD_DOS_DATETIME           8\n#      define C_CRC32                           12\n#      define C_COMPRESSED_SIZE                 16\n#      define C_UNCOMPRESSED_SIZE               20\n#      define C_FILENAME_LENGTH                 24\n#      define C_EXTRA_FIELD_LENGTH              26\n#      define C_FILE_COMMENT_LENGTH             28\n#      define C_DISK_NUMBER_START               30\n#      define C_INTERNAL_FILE_ATTRIBUTES        32\n#      define C_EXTERNAL_FILE_ATTRIBUTES        34\n#      define C_RELATIVE_OFFSET_LOCAL_HEADER    38\n\n   typedef uch   ec_byte_rec[ ECREC_SIZE+4 ];\n/*     define SIGNATURE                         0   space-holder only */\n#      define NUMBER_THIS_DISK                  4\n#      define NUM_DISK_WITH_START_CEN_DIR       6\n#      define NUM_ENTRIES_CEN_DIR_THS_DISK      8\n#      define TOTAL_ENTRIES_CENTRAL_DIR         10\n#      define SIZE_CENTRAL_DIRECTORY            12\n#      define OFFSET_START_CENTRAL_DIRECTORY    16\n#      define ZIPFILE_COMMENT_LENGTH            20\n\n   typedef uch   ec_byte_loc64[ ECLOC64_SIZE+4 ];\n#      define NUM_DISK_START_EOCDR64            4\n#      define OFFSET_START_EOCDR64              8\n#      define NUM_THIS_DISK_LOC64               16\n\n   typedef uch   ec_byte_rec64[ ECREC64_SIZE+4 ];\n#      define ECREC64_LENGTH                    4\n#      define EC_VERSION_MADE_BY_0              12\n#      define EC_VERSION_NEEDED_0               14\n#      define NUMBER_THIS_DSK_REC64             16\n#      define NUM_DISK_START_CEN_DIR64          20\n#      define NUM_ENTRIES_CEN_DIR_THS_DISK64    24\n#      define TOTAL_ENTRIES_CENTRAL_DIR64       32\n#      define SIZE_CENTRAL_DIRECTORY64          40\n#      define OFFSET_START_CENTRAL_DIRECT64     48\n\n\n/* The following structs are used to hold all header data of a zip entry.\n   Traditionally, the structs' layouts followed the data layout of the\n   corresponding zipfile header structures.  However, the zipfile header\n   layouts were designed in the old ages of 16-bit CPUs, they are subject\n   to structure padding and/or alignment issues on newer systems with a\n   \"natural word width\" of more than 2 bytes.\n   Please note that the structure members are now reordered by size\n   (top-down), to prevent internal padding and optimize memory usage!\n */\n   typedef struct local_file_header {                 /* LOCAL */\n       zusz_t csize;\n       zusz_t ucsize;\n       ulg last_mod_dos_datetime;\n       ulg crc32;\n       uch version_needed_to_extract[2];\n       ush general_purpose_bit_flag;\n       ush compression_method;\n       ush filename_length;\n       ush extra_field_length;\n   } local_file_hdr;\n\n   typedef struct central_directory_file_header {     /* CENTRAL */\n       zusz_t csize;\n       zusz_t ucsize;\n       zusz_t relative_offset_local_header;\n       ulg last_mod_dos_datetime;\n       ulg crc32;\n       ulg external_file_attributes;\n       zuvl_t disk_number_start;\n       ush internal_file_attributes;\n       uch version_made_by[2];\n       uch version_needed_to_extract[2];\n       ush general_purpose_bit_flag;\n       ush compression_method;\n       ush filename_length;\n       ush extra_field_length;\n       ush file_comment_length;\n   } cdir_file_hdr;\n\n   typedef struct end_central_dir_record {            /* END CENTRAL */\n       zusz_t size_central_directory;\n       zusz_t offset_start_central_directory;\n       zucn_t num_entries_centrl_dir_ths_disk;\n       zucn_t total_entries_central_dir;\n       zuvl_t number_this_disk;\n       zuvl_t num_disk_start_cdir;\n       int have_ecr64;                  /* valid Zip64 ecdir-record exists */\n       int is_zip64_archive;            /* Zip64 ecdir-record is mandatory */\n       ush zipfile_comment_length;\n   } ecdir_rec;\n\n\n/* Huffman code lookup table entry--this entry is four bytes for machines\n   that have 16-bit pointers (e.g. PC's in the small or medium model).\n   Valid extra bits are 0..16.  e == 31 is EOB (end of block), e == 32\n   means that v is a literal, 32 < e < 64 means that v is a pointer to\n   the next table, which codes (e & 31)  bits, and lastly e == 99 indicates\n   an unused code.  If a code with e == 99 is looked up, this implies an\n   error in the data. */\n\nstruct huft {\n    uch e;                /* number of extra bits or operation */\n    uch b;                /* number of bits in this code or subcode */\n    union {\n        ush n;            /* literal, length base, or distance base */\n        struct huft *t;   /* pointer to next level of table */\n    } v;\n};\n\n\ntypedef struct _APIDocStruct {\n    char *compare;\n    char *function;\n    char *syntax;\n    char *purpose;\n} APIDocStruct;\n\n\n\n\n/*************/\n/*  Globals  */\n/*************/\n\n#if (defined(OS2) && !defined(FUNZIP))\n#  include \"os2/os2data.h\"\n#endif\n\n#include \"globals.h\"\n\n\n\n/*************************/\n/*  Function Prototypes  */\n/*************************/\n\n/*---------------------------------------------------------------------------\n    Functions in unzip.c (initialization routines):\n  ---------------------------------------------------------------------------*/\n\n#ifndef WINDLL\n   int    MAIN                   OF((int argc, char **argv));\n   int    unzip                  OF((__GPRO__ int argc, char **argv));\n   int    uz_opts                OF((__GPRO__ int *pargc, char ***pargv));\n   int    usage                  OF((__GPRO__ int error));\n#endif /* !WINDLL */\n\n/*---------------------------------------------------------------------------\n    Functions in process.c (main driver routines):\n  ---------------------------------------------------------------------------*/\n\nint      process_zipfiles        OF((__GPRO));\nvoid     free_G_buffers          OF((__GPRO));\n/* static int    do_seekable     OF((__GPRO__ int lastchance)); */\n/* static int    find_ecrec      OF((__GPRO__ long searchlen)); */\n/* static int    process_central_comment OF((__GPRO)); */\nint      process_cdir_file_hdr   OF((__GPRO));\nint      process_local_file_hdr  OF((__GPRO));\nint      getZip64Data            OF((__GPRO__ ZCONST uch *ef_buf,\n                                     unsigned ef_len));\n#ifdef UNICODE_SUPPORT\n  int    getUnicodeData          OF((__GPRO__ ZCONST uch *ef_buf,\n                                     unsigned ef_len));\n#endif\nunsigned ef_scan_for_izux        OF((ZCONST uch *ef_buf, unsigned ef_len,\n                                     int ef_is_c, ulg dos_mdatetime,\n                                     iztimes *z_utim, ulg *z_uidgid));\n#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))\n   zvoid *getRISCOSexfield       OF((ZCONST uch *ef_buf, unsigned ef_len));\n#endif\n\n#ifndef SFX\n\n/*---------------------------------------------------------------------------\n    Functions in zipinfo.c (`zipinfo-style' listing routines):\n  ---------------------------------------------------------------------------*/\n\n#ifndef NO_ZIPINFO\n#ifndef WINDLL\n   int   zi_opts                 OF((__GPRO__ int *pargc, char ***pargv));\n#endif\nvoid     zi_end_central          OF((__GPRO));\nint      zipinfo                 OF((__GPRO));\n/* static int      zi_long       OF((__GPRO__ zusz_t *pEndprev)); */\n/* static int      zi_short      OF((__GPRO)); */\n/* static char    *zi_time       OF((__GPRO__ ZCONST ulg *datetimez,\n                                     ZCONST time_t *modtimez, char *d_t_str));*/\n#endif /* !NO_ZIPINFO */\n\n/*---------------------------------------------------------------------------\n    Functions in list.c (generic zipfile-listing routines):\n  ---------------------------------------------------------------------------*/\n\nint      list_files              OF((__GPRO));\n#ifdef TIMESTAMP\n   int   get_time_stamp          OF((__GPRO__  time_t *last_modtime,\n                                     ulg *nmember));\n#endif\nint      ratio                   OF((zusz_t uc, zusz_t c));\nvoid     fnprint                 OF((__GPRO));\n\n#endif /* !SFX */\n\n/*---------------------------------------------------------------------------\n    Functions in fileio.c:\n  ---------------------------------------------------------------------------*/\n\nint      open_input_file      OF((__GPRO));\nint      open_outfile         OF((__GPRO));                    /* also vms.c */\nvoid     undefer_input        OF((__GPRO));\nvoid     defer_leftover_input OF((__GPRO));\nunsigned readbuf              OF((__GPRO__ char *buf, register unsigned len));\nint      readbyte             OF((__GPRO));\nint      fillinbuf            OF((__GPRO));\nint      seek_zipf            OF((__GPRO__ zoff_t abs_offset));\n#ifdef FUNZIP\n   int   flush                OF((__GPRO__ ulg size));  /* actually funzip.c */\n#else\n   int   flush                OF((__GPRO__ uch *buf, ulg size, int unshrink));\n#endif\n/* static int  disk_error     OF((__GPRO)); */\nvoid     handler              OF((int signal));\ntime_t   dos_to_unix_time     OF((ulg dos_datetime));\nint      check_for_newer      OF((__GPRO__ char *filename)); /* os2,vmcms,vms */\nint      do_string            OF((__GPRO__ unsigned int length, int option));\nush      makeword             OF((ZCONST uch *b));\nulg      makelong             OF((ZCONST uch *sig));\nzusz_t   makeint64            OF((ZCONST uch *sig));\nchar    *fzofft               OF((__GPRO__ zoff_t val,\n                                  ZCONST char *pre, ZCONST char *post));\n#if (!defined(STR_TO_ISO) || defined(NEED_STR2ISO))\n   char *str2iso              OF((char *dst, ZCONST char *src));\n#endif\n#if (!defined(STR_TO_OEM) || defined(NEED_STR2OEM))\n   char *str2oem              OF((char *dst, ZCONST char *src));\n#endif\n#ifdef NO_STRNICMP\n   int   zstrnicmp            OF((register ZCONST char *s1,\n                                  register ZCONST char *s2,\n                                  register unsigned n));\n#endif\n#ifdef REGULUS\n   int   zstat                OF((ZCONST char *p, struct stat *s));\n#endif\n#ifdef ZMEM   /* MUST be ifdef'd because of conflicts with the standard def. */\n   zvoid *memset OF((register zvoid *, register int, register unsigned int));\n   int    memcmp OF((register ZCONST zvoid*, register ZCONST zvoid *,\n                     register unsigned int));\n   zvoid *memcpy OF((register zvoid *, register ZCONST zvoid *,\n                     register unsigned int));\n#endif\n#ifdef NEED_UZMBCLEN\n   extent uzmbclen          OF((ZCONST unsigned char *ptr));\n#endif\n#ifdef NEED_UZMBSCHR\n   unsigned char *uzmbschr  OF((ZCONST unsigned char *str, unsigned int c));\n#endif\n#ifdef NEED_UZMBSRCHR\n   unsigned char *uzmbsrchr OF((ZCONST unsigned char *str, unsigned int c));\n#endif\n#ifdef SMALL_MEM\n   char *fLoadFarString       OF((__GPRO__ const char Far *sz));\n   char *fLoadFarStringSmall  OF((__GPRO__ const char Far *sz));\n   char *fLoadFarStringSmall2 OF((__GPRO__ const char Far *sz));\n   #ifndef zfstrcpy\n     char Far * Far zfstrcpy  OF((char Far *s1, const char Far *s2));\n   #endif\n   #if (!defined(SFX) && !defined(zfstrcmp))\n     int Far zfstrcmp         OF((const char Far *s1, const char Far *s2));\n   #endif\n#endif\n\n\n/*---------------------------------------------------------------------------\n    Functions in extract.c:\n  ---------------------------------------------------------------------------*/\n\nint    extract_or_test_files     OF((__GPRO));\n/* static int   store_info          OF((void)); */\n/* static int   extract_or_test_member   OF((__GPRO)); */\n/* static int   TestExtraField   OF((__GPRO__ uch *ef, unsigned ef_len)); */\n/* static int   test_OS2         OF((__GPRO__ uch *eb, unsigned eb_size)); */\n/* static int   test_NT          OF((__GPRO__ uch *eb, unsigned eb_size)); */\n#ifndef SFX\n  unsigned find_compr_idx        OF((unsigned compr_methodnum));\n#endif\nint    memextract                OF((__GPRO__ uch *tgt, ulg tgtsize,\n                                     ZCONST uch *src, ulg srcsize));\nint    memflush                  OF((__GPRO__ ZCONST uch *rawbuf, ulg size));\n#if (defined(VMS) || defined(VMS_TEXT_CONV))\n   uch   *extract_izvms_block    OF((__GPRO__ ZCONST uch *ebdata,\n                                     unsigned size, unsigned *retlen,\n                                     ZCONST uch *init, unsigned needlen));\n#endif\nchar  *fnfilter                  OF((ZCONST char *raw, uch *space,\n                                     extent size));\n\n/*---------------------------------------------------------------------------\n    Decompression functions:\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) && !defined(FUNZIP))\nint    explode                   OF((__GPRO));                  /* explode.c */\n#endif\nint    huft_free                 OF((struct huft *t));          /* inflate.c */\nint    huft_build                OF((__GPRO__ ZCONST unsigned *b, unsigned n,\n                                     unsigned s, ZCONST ush *d, ZCONST uch *e,\n                                     struct huft **t, unsigned *m));\n#ifdef USE_ZLIB\n   int    UZinflate              OF((__GPRO__ int is_defl64));  /* inflate.c */\n#  define inflate_free(x)        inflateEnd(&((Uz_Globs *)(&G))->dstrm)\n#else\n   int    inflate                OF((__GPRO__ int is_defl64));  /* inflate.c */\n   int    inflate_free           OF((__GPRO));                  /* inflate.c */\n#endif /* ?USE_ZLIB */\n#if (!defined(SFX) && !defined(FUNZIP))\n#ifndef COPYRIGHT_CLEAN\n   int    unreduce               OF((__GPRO));                 /* unreduce.c */\n/* static void  LoadFollowers    OF((__GPRO__ f_array *follower, uch *Slen));\n                                                                * unreduce.c */\n#endif /* !COPYRIGHT_CLEAN */\n#ifndef LZW_CLEAN\n   int    unshrink               OF((__GPRO));                 /* unshrink.c */\n/* static void  partial_clear    OF((__GPRO));                  * unshrink.c */\n#endif /* !LZW_CLEAN */\n#endif /* !SFX && !FUNZIP */\n#ifdef USE_BZIP2\n   int    UZbunzip2              OF((__GPRO));                  /* extract.c */\n   void   bz_internal_error      OF((int bzerrcode));           /* ubz2err.c */\n#endif\n\n/*---------------------------------------------------------------------------\n    Internal API functions (only included in DLL versions):\n  ---------------------------------------------------------------------------*/\n\n#ifdef DLL\n   void     setFileNotFound       OF((__GPRO));                     /* api.c */\n   int      unzipToMemory         OF((__GPRO__ char *zip, char *file,\n                                      UzpBuffer *retstr));          /* api.c */\n   int      redirect_outfile      OF((__GPRO));                     /* api.c */\n   int      writeToMemory         OF((__GPRO__ ZCONST uch *rawbuf,\n                                      extent size));                /* api.c */\n   int      close_redirect        OF((__GPRO));                     /* api.c */\n   /* this obsolescent entry point kept for compatibility: */\n   int      UzpUnzip              OF((int argc, char **argv));/* use UzpMain */\n#ifdef OS2DLL\n   int      varmessage            OF((__GPRO__ ZCONST uch *buf, ulg size));\n   int      varputchar            OF((__GPRO__ int c));         /* rexxapi.c */\n   int      finish_REXX_redirect  OF((__GPRO));                 /* rexxapi.c */\n#endif\n#ifdef API_DOC\n   void     APIhelp               OF((__GPRO__ int argc, char **argv));\n#endif                                                          /* apihelp.c */\n#endif /* DLL */\n\n/*---------------------------------------------------------------------------\n    MSDOS-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef MSDOS\n#if (!defined(FUNZIP) && !defined(SFX) && !defined(WINDLL))\n   void     check_for_windows     OF((ZCONST char *app));         /* msdos.c */\n#endif\n#if (defined(__GO32__) || defined(__EMX__))\n   unsigned _dos_getcountryinfo(void *);                          /* msdos.c */\n#if (!defined(__DJGPP__) || (__DJGPP__ < 2))\n   unsigned _dos_setftime(int, unsigned, unsigned);               /* msdos.c */\n   unsigned _dos_setfileattr(const char *, unsigned);             /* msdos.c */\n   unsigned _dos_creat(const char *, unsigned, int *);            /* msdos.c */\n   void _dos_getdrive(unsigned *);                                /* msdos.c */\n   unsigned _dos_close(int);                                      /* msdos.c */\n#endif /* !__DJGPP__ || (__DJGPP__ < 2) */\n#endif /* __GO32__ || __EMX__ */\n#endif\n\n/*---------------------------------------------------------------------------\n    OS/2-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef OS2   /* GetFileTime conflicts with something in Win32 header files */\n#if (defined(REENTRANT) && defined(USETHREADID))\n   ulg   GetThreadId          OF((void));\n#endif\n   int   GetCountryInfo       OF((void));                           /* os2.c */\n   long  GetFileTime          OF((ZCONST char *name));              /* os2.c */\n/* static void  SetPathAttrTimes OF((__GPRO__ int flags, int dir));    os2.c */\n/* static int   SetEAs        OF((__GPRO__ const char *path,\n                                  void *eablock));                     os2.c */\n/* static int   SetACL        OF((__GPRO__ const char *path,\n                                  void *eablock));                     os2.c */\n/* static int   IsFileNameValid OF((const char *name));                os2.c */\n/* static void  map2fat       OF((char *pathcomp, char **pEndFAT));    os2.c */\n/* static int   SetLongNameEA OF((char *name, char *longname));        os2.c */\n/* static void  InitNLS       OF((void));                              os2.c */\n   int   IsUpperNLS           OF((int nChr));                       /* os2.c */\n   int   ToLowerNLS           OF((int nChr));                       /* os2.c */\n   void  DebugMalloc          OF((void));                           /* os2.c */\n#endif\n\n/*---------------------------------------------------------------------------\n    QDOS-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef QDOS\n   int    QMatch              (uch, uch);\n   void   QFilename           (__GPRO__ char *);\n   char  *Qstrfix             (char *);\n   int    QReturn             (int zip_error);\n#endif\n\n/*---------------------------------------------------------------------------\n    TOPS20-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef TOPS20\n   int    upper               OF((char *s));                     /* tops20.c */\n   int    enquote             OF((char *s));                     /* tops20.c */\n   int    dequote             OF((char *s));                     /* tops20.c */\n   int    fnlegal             OF(()); /* error if prototyped? */ /* tops20.c */\n#endif\n\n/*---------------------------------------------------------------------------\n    VM/CMS- and MVS-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef CMS_MVS\n   extent getVMMVSexfield     OF((char *type, uch *ef_block, unsigned datalen));\n   FILE  *vmmvs_open_infile   OF((__GPRO));                       /* vmmvs.c */\n   void   close_infile        OF((__GPRO));                       /* vmmvs.c */\n#endif\n\n/*---------------------------------------------------------------------------\n    VMS-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef VMS\n   int    check_format        OF((__GPRO));                         /* vms.c */\n/* int    open_outfile        OF((__GPRO));           * (see fileio.c) vms.c */\n/* int    flush               OF((__GPRO__ uch *rawbuf, unsigned size,\n                                  int final_flag));   * (see fileio.c) vms.c */\n   char  *vms_msg_text        OF((void));                           /* vms.c */\n#ifdef RETURN_CODES\n   void   return_VMS          OF((__GPRO__ int zip_error));         /* vms.c */\n#else\n   void   return_VMS          OF((int zip_error));                  /* vms.c */\n#endif\n#ifdef VMSCLI\n   ulg    vms_unzip_cmdline   OF((int *, char ***));            /* cmdline.c */\n   int    VMSCLI_usage        OF((__GPRO__ int error));         /* cmdline.c */\n#endif\n#endif\n\n/*---------------------------------------------------------------------------\n    WIN32-only functions:\n  ---------------------------------------------------------------------------*/\n\n#ifdef WIN32\n   int   IsWinNT        OF((void));                               /* win32.c */\n#ifdef NTSD_EAS\n   void  process_defer_NT     OF((__GPRO));                       /* win32.c */\n   int   test_NTSD      OF((__GPRO__ uch *eb, unsigned eb_size,\n                            uch *eb_ucptr, ulg eb_ucsize));       /* win32.c */\n#  define TEST_NTSD     test_NTSD\n#endif\n#ifdef W32_STAT_BANDAID\n   int   zstat_win32    OF((__W32STAT_GLOBALS__\n                            const char *path, z_stat *buf));      /* win32.c */\n#endif\n#endif\n\n/*---------------------------------------------------------------------------\n    Miscellaneous/shared functions:\n  ---------------------------------------------------------------------------*/\n\nUz_Globs *globalsCtor    OF((void));                            /* globals.c */\n\nint      envargs         OF((int *Pargc, char ***Pargv,\n                             ZCONST char *envstr, ZCONST char *envstr2));\n                                                                /* envargs.c */\nvoid     mksargs         OF((int *argcp, char ***argvp));       /* envargs.c */\n\nint      match           OF((ZCONST char *s, ZCONST char *p,\n                             int ic __WDLPRO));                   /* match.c */\nint      iswild          OF((ZCONST char *p));                    /* match.c */\n\n/* declarations of public CRC-32 functions have been moved into crc32.h\n   (free_crc_table(), get_crc_table(), crc32())                      crc32.c */\n\nint      dateformat      OF((void));                                /* local */\nchar     dateseparator   OF((void));                                /* local */\n#ifndef WINDLL\n   void  version         OF((__GPRO));                              /* local */\n#endif\nint      mapattr         OF((__GPRO));                              /* local */\nint      mapname         OF((__GPRO__ int renamed));                /* local */\nint      checkdir        OF((__GPRO__ char *pathcomp, int flag));   /* local */\nchar    *do_wild         OF((__GPRO__ ZCONST char *wildzipfn));     /* local */\nchar    *GetLoadPath     OF((__GPRO));                              /* local */\n#if (defined(MORE) && (defined(ATH_BEO_UNX) || defined(QDOS) || defined(VMS)))\n   int screensize        OF((int *tt_rows, int *tt_cols));          /* local */\n# if defined(VMS)\n   int screenlinewrap    OF((void));                                /* local */\n# endif\n#endif /* MORE && (ATH_BEO_UNX || QDOS || VMS) */\n#ifdef OS2_W32\n   int   SetFileSize     OF((FILE *file, zusz_t filesize));         /* local */\n#endif\n#ifndef MTS /* macro in MTS */\n   void  close_outfile   OF((__GPRO));                              /* local */\n#endif\n#ifdef SET_SYMLINK_ATTRIBS\n   int  set_symlnk_attribs  OF((__GPRO__ slinkentry *slnk_entry));  /* local */\n#endif\n#ifdef SET_DIR_ATTRIB\n   int   defer_dir_attribs  OF((__GPRO__ direntry **pd));           /* local */\n   int   set_direc_attribs  OF((__GPRO__ direntry *d));             /* local */\n#endif\n#ifdef TIMESTAMP\n# ifdef WIN32\n   int   stamp_file      OF((__GPRO__\n                             ZCONST char *fname, time_t modtime));  /* local */\n# else\n   int   stamp_file      OF((ZCONST char *fname, time_t modtime));  /* local */\n# endif\n#endif\n#ifdef NEED_ISO_OEM_INIT\n   void  prepare_ISO_OEM_translat   OF((__GPRO));                   /* local */\n#endif\n#if (defined(MALLOC_WORK) && defined(MY_ZCALLOC))\n   zvoid far *zcalloc    OF((unsigned int, unsigned int));\n   zvoid zcfree          OF((zvoid far *));\n#endif /* MALLOC_WORK && MY_ZCALLOC */\n#ifdef SYSTEM_SPECIFIC_CTOR\n   void  SYSTEM_SPECIFIC_CTOR   OF((__GPRO));                       /* local */\n#endif\n#ifdef SYSTEM_SPECIFIC_DTOR\n   void  SYSTEM_SPECIFIC_DTOR   OF((__GPRO));                       /* local */\n#endif\n\n\n\n\n\n/************/\n/*  Macros  */\n/************/\n\n#ifndef MAX\n#  define MAX(a,b)   ((a) > (b) ? (a) : (b))\n#endif\n#ifndef MIN\n#  define MIN(a,b)   ((a) < (b) ? (a) : (b))\n#endif\n\n#ifdef DEBUG\n#  if (defined(THEOS) && defined(NO_BOGUS_SPC))\n#    define NO_DEBUG_IN_MACROS\n#    define Trace(x)   _fprintf x\n#  else\n#    define Trace(x)   fprintf x\n#  endif\n#else\n#  define Trace(x)\n#endif\n\n#ifdef DEBUG_TIME\n#  define TTrace(x)  fprintf x\n#else\n#  define TTrace(x)\n#endif\n\n#ifdef NO_DEBUG_IN_MACROS\n#  define MTrace(x)\n#else\n#  define MTrace(x)  Trace(x)\n#endif\n\n#if (defined(UNIX) || defined(T20_VMS)) /* generally old systems */\n#  define ToLower(x)   ((char)(isupper((int)x)? tolower((int)x) : x))\n#else\n#  define ToLower      tolower          /* assumed \"smart\"; used in match() */\n#endif\n\n#ifdef USE_STRM_INPUT\n   /* ``Replace'' the unbuffered UNIX style I/O function with similar\n    * standard C functions from <stdio.h>.\n    */\n#  define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd))\n#  ifdef zlseek\n#    undef zlseek\n#  endif\n#  define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w))\n#  define close(fd) fclose((FILE *)(fd))\n#endif /* USE_STRM_INPUT */\n\n/* The return value of the Info() \"macro function\" is never checked in\n * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the\n * Info() definition for \"FUNZIP\" would have to be corrected:\n * #define Info(buf,flag,sprf_arg) \\\n *      (fputs((char *)(sprintf sprf_arg, (buf)), \\\n *             (flag)&1? stderr : stdout) < 0)\n */\n#ifndef Info   /* may already have been defined for redirection */\n#  ifdef FUNZIP\n#    define Info(buf,flag,sprf_arg) \\\n     fputs((char *)(sprintf sprf_arg, (buf)), (flag)&1? stderr : stdout)\n#  else\n#    ifdef INT_SPRINTF  /* optimized version for \"int sprintf()\" flavour */\n#      define Info(buf,flag,sprf_arg) \\\n       (*G.message)((zvoid *)&G, (uch *)(buf), (ulg)sprintf sprf_arg, (flag))\n#    else          /* generic version, does not use sprintf() return value */\n#      define Info(buf,flag,sprf_arg) \\\n       (*G.message)((zvoid *)&G, (uch *)(buf), \\\n                     (ulg)(sprintf sprf_arg, strlen((char *)(buf))), (flag))\n#    endif\n#  endif\n#endif /* !Info */\n\n/*  This wrapper macro around fzofft() is just defined to \"hide\" the\n *  argument needed to reference the global storage buffers.\n */\n#define FmZofft(val, pre, post) fzofft(__G__ val, pre, post)\n\n/*  The following macro wrappers around the fnfilter function are used many\n *  times to prepare archive entry names or name components for displaying\n *  listings and (warning/error) messages. They use sections in the upper half\n *  of 'slide' as buffer, since their output is normally fed through the\n *  Info() macro with 'slide' (the start of this area) as message buffer.\n */\n#define FnFilter1(fname) \\\n        fnfilter((fname), slide + (extent)(WSIZE>>1), (extent)(WSIZE>>2))\n#define FnFilter2(fname) \\\n        fnfilter((fname), slide + (extent)((WSIZE>>1) + (WSIZE>>2)),\\\n                 (extent)(WSIZE>>2))\n\n#ifndef FUNZIP   /* used only in inflate.c */\n#  define MESSAGE(str,len,flag)  (*G.message)((zvoid *)&G,(str),(len),(flag))\n#endif\n\n#if 0            /* Optimization: use the (const) result of crc32(0L,NULL,0) */\n#  define CRCVAL_INITIAL  crc32(0L, NULL, 0)\n#else\n#  define CRCVAL_INITIAL  0L\n#endif\n\n#ifdef SYMLINKS\n   /* This macro defines the Zip \"made by\" hosts that are considered\n      to support storing symbolic link entries. */\n#  define SYMLINK_HOST(hn) ((hn) == UNIX_ || (hn) == ATARI_ || \\\n      (hn) == ATHEOS_ || (hn) == BEOS_ || (hn) == VMS_)\n#endif\n\n#ifndef TEST_NTSD               /* \"NTSD valid?\" checking function */\n#  define TEST_NTSD     NULL    /*   ... is not available */\n#endif\n\n#define SKIP_(length) if(length&&((error=do_string(__G__ length,SKIP))!=0))\\\n  {error_in_archive=error; if(error>1) return error;}\n\n/*\n *  Skip a variable-length field, and report any errors.  Used in zipinfo.c\n *  and unzip.c in several functions.\n *\n *  macro SKIP_(length)\n *      ush length;\n *  {\n *      if (length && ((error = do_string(length, SKIP)) != 0)) {\n *          error_in_archive = error;   /-* might be warning *-/\n *          if (error > 1)              /-* fatal *-/\n *              return (error);\n *      }\n *  }\n *\n */\n\n\n#ifdef FUNZIP\n#  define FLUSH(w)  flush(__G__ (ulg)(w))\n#  define NEXTBYTE  getc(G.in)   /* redefined in crypt.h if full version */\n#else\n#  define FLUSH(w)  ((G.mem_mode) ? memflush(__G__ redirSlide,(ulg)(w)) \\\n                                  : flush(__G__ redirSlide,(ulg)(w),0))\n#  define NEXTBYTE  (G.incnt-- > 0 ? (int)(*G.inptr++) : readbyte(__G))\n#endif\n\n\n#define READBITS(nbits,zdest) {if(nbits>G.bits_left) {int temp; G.zipeof=1;\\\n  while (G.bits_left<=8*(int)(sizeof(G.bitbuf)-1) && (temp=NEXTBYTE)!=EOF) {\\\n  G.bitbuf|=(ulg)temp<<G.bits_left; G.bits_left+=8; G.zipeof=0;}}\\\n  zdest=(shrint)((unsigned)G.bitbuf&mask_bits[nbits]);G.bitbuf>>=nbits;\\\n  G.bits_left-=nbits;}\n\n/*\n * macro READBITS(nbits,zdest)    * only used by unreduce and unshrink *\n *  {\n *      if (nbits > G.bits_left) {  * fill G.bitbuf, 8*sizeof(ulg) bits *\n *          int temp;\n *\n *          G.zipeof = 1;\n *          while (G.bits_left <= 8*(int)(sizeof(G.bitbuf)-1) &&\n *                 (temp = NEXTBYTE) != EOF) {\n *              G.bitbuf |= (ulg)temp << G.bits_left;\n *              G.bits_left += 8;\n *              G.zipeof = 0;\n *          }\n *      }\n *      zdest = (shrint)((unsigned)G.bitbuf & mask_bits[nbits]);\n *      G.bitbuf >>= nbits;\n *      G.bits_left -= nbits;\n *  }\n *\n */\n\n\n/* GRR:  should use StringLower for STRLOWER macro if possible */\n\n/*\n *  Copy the zero-terminated string in str1 into str2, converting any\n *  uppercase letters to lowercase as we go.  str2 gets zero-terminated\n *  as well, of course.  str1 and str2 may be the same character array.\n */\n#ifdef _MBCS\n#  define STRLOWER(str1, str2) \\\n   { \\\n       char  *p, *q, c; unsigned i; \\\n       p = (char *)(str1); \\\n       q = (char *)(str2); \\\n       while ((c = *p) != '\\0') { \\\n           if ((i = CLEN(p)) > 1) { \\\n               while (i--) *q++ = *p++; \\\n           } else { \\\n               *q++ = (char)(isupper((int)(c))? tolower((int)(c)) : c); \\\n               p++; \\\n           } \\\n       } \\\n       *q = '\\0'; \\\n   }\n#else\n#  define STRLOWER(str1, str2) \\\n   { \\\n       char  *p, *q; \\\n       p = (char *)(str1) - 1; \\\n       q = (char *)(str2); \\\n       while (*++p) \\\n           *q++ = (char)(isupper((int)(*p))? tolower((int)(*p)) : *p); \\\n       *q = '\\0'; \\\n   }\n#endif\n/*\n *  NOTES:  This macro makes no assumptions about the characteristics of\n *    the tolower() function or macro (beyond its existence), nor does it\n *    make assumptions about the structure of the character set (i.e., it\n *    should work on EBCDIC machines, too).  The fact that either or both\n *    of isupper() and tolower() may be macros has been taken into account;\n *    watch out for \"side effects\" (in the C sense) when modifying this\n *    macro.\n */\n\n#ifndef foreign\n#  define foreign(c)  (c)\n#endif\n\n#ifndef native\n#  define native(c)   (c)\n#  define A_TO_N(str1)\n#else\n#  ifndef NATIVE\n#    define NATIVE     \"native chars\"\n#  endif\n#  define A_TO_N(str1) {register uch *p;\\\n     for (p=(uch *)(str1); *p; p++) *p=native(*p);}\n#endif\n/*\n *  Translate the zero-terminated string in str1 from ASCII to the native\n *  character set. The translation is performed in-place and uses the\n *  \"native\" macro to translate each character.\n *\n *  NOTE:  Using the \"native\" macro means that is it the only part of unzip\n *    which knows which translation table (if any) is actually in use to\n *    produce the native character set.  This makes adding new character set\n *    translation tables easy, insofar as all that is needed is an appropriate\n *    \"native\" macro definition and the translation table itself.  Currently,\n *    the only non-ASCII native character set implemented is EBCDIC, but this\n *    may not always be so.\n */\n\n\n/* default setup for internal codepage: assume ISO 8859-1 compatibility!! */\n#if (!defined(NATIVE) && !defined(CRTL_CP_IS_ISO) && !defined(CRTL_CP_IS_OEM))\n#  define CRTL_CP_IS_ISO\n#endif\n\n\n/*  Translate \"extended ASCII\" chars (OEM coding for DOS and OS/2; else\n *  ISO-8859-1 [ISO Latin 1, Win Ansi,...]) into the internal \"native\"\n *  code page.  As with A_TO_N(), conversion is done in place.\n */\n#ifndef _ISO_INTERN\n#  ifdef CRTL_CP_IS_OEM\n#    ifndef IZ_ISO2OEM_ARRAY\n#      define IZ_ISO2OEM_ARRAY\n#    endif\n#    define _ISO_INTERN(str1) if (iso2oem) {register uch *p;\\\n       for (p=(uch *)(str1); *p; p++)\\\n         *p = native((*p & 0x80) ? iso2oem[*p & 0x7f] : *p);}\n#  else\n#    define _ISO_INTERN(str1)   A_TO_N(str1)\n#  endif\n#endif\n\n#ifndef _OEM_INTERN\n#  ifdef CRTL_CP_IS_OEM\n#    define _OEM_INTERN(str1)   A_TO_N(str1)\n#  else\n#    ifndef IZ_OEM2ISO_ARRAY\n#      define IZ_OEM2ISO_ARRAY\n#    endif\n#    define _OEM_INTERN(str1) if (oem2iso) {register uch *p;\\\n       for (p=(uch *)(str1); *p; p++)\\\n         *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);}\n#  endif\n#endif\n\n#ifndef STR_TO_ISO\n#  ifdef CRTL_CP_IS_ISO\n#    define STR_TO_ISO          strcpy\n#  else\n#    define STR_TO_ISO          str2iso\n#    define NEED_STR2ISO\n#  endif\n#endif\n\n#ifndef STR_TO_OEM\n#  ifdef CRTL_CP_IS_OEM\n#    define STR_TO_OEM          strcpy\n#  else\n#    define STR_TO_OEM          str2oem\n#    define NEED_STR2OEM\n#  endif\n#endif\n\n#if (!defined(INTERN_TO_ISO) && !defined(ASCII2ISO))\n#  ifdef CRTL_CP_IS_OEM\n     /* know: \"ASCII\" is \"OEM\" */\n#    define ASCII2ISO(c) \\\n       ((((c) & 0x80) && oem2iso) ? oem2iso[(c) & 0x7f] : (c))\n#    if (defined(NEED_STR2ISO) && !defined(CRYP_USES_OEM2ISO))\n#      define CRYP_USES_OEM2ISO\n#    endif\n#  else\n     /* assume: \"ASCII\" is \"ISO-ANSI\" */\n#    define ASCII2ISO(c) (c)\n#  endif\n#endif\n\n#if (!defined(INTERN_TO_OEM) && !defined(ASCII2OEM))\n#  ifdef CRTL_CP_IS_OEM\n     /* know: \"ASCII\" is \"OEM\" */\n#    define ASCII2OEM(c) (c)\n#  else\n     /* assume: \"ASCII\" is \"ISO-ANSI\" */\n#    define ASCII2OEM(c) \\\n       ((((c) & 0x80) && iso2oem) ? iso2oem[(c) & 0x7f] : (c))\n#    if (defined(NEED_STR2OEM) && !defined(CRYP_USES_ISO2OEM))\n#      define CRYP_USES_ISO2OEM\n#    endif\n#  endif\n#endif\n\n/* codepage conversion setup for testp() in crypt.c */\n#ifdef CRTL_CP_IS_ISO\n#  ifndef STR_TO_CP2\n#    define STR_TO_CP2  STR_TO_OEM\n#  endif\n#else\n#  ifdef CRTL_CP_IS_OEM\n#    ifndef STR_TO_CP2\n#      define STR_TO_CP2  STR_TO_ISO\n#    endif\n#  else /* native internal CP is neither ISO nor OEM */\n#    ifndef STR_TO_CP1\n#      define STR_TO_CP1  STR_TO_ISO\n#    endif\n#    ifndef STR_TO_CP2\n#      define STR_TO_CP2  STR_TO_OEM\n#    endif\n#  endif\n#endif\n\n\n/* Convert filename (and file comment string) into \"internal\" charset.\n * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)\n * codepage when made on\n *  -> DOS (this includes 16-bit Windows 3.1)  (FS_FAT_)\n *  -> OS/2                                    (FS_HPFS_)\n *  -> Win95/WinNT with Nico Mak's WinZip      (FS_NTFS_ && hostver == \"5.0\")\n * EXCEPTIONS:\n *  PKZIP for Windows 2.5, 2.6, and 4.0 flag their entries as \"FS_FAT_\", but\n *  the filename stored in the local header is coded in Windows ANSI (CP 1252\n *  resp. ISO 8859-1 on US and western Europe locale settings).\n *  Likewise, PKZIP for UNIX 2.51 flags its entries as \"FS_FAT_\", but the\n *  filenames stored in BOTH the local and the central header are coded\n *  in the local system's codepage (usually ANSI codings like ISO 8859-1).\n *\n * All other ports are assumed to code zip entry filenames in ISO 8859-1.\n */\n#ifndef Ext_ASCII_TO_Native\n#  define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \\\n    if (((hostnum) == FS_FAT_ && \\\n         !(((islochdr) || (isuxatt)) && \\\n           ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \\\n        (hostnum) == FS_HPFS_ || \\\n        ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \\\n        _OEM_INTERN((string)); \\\n    } else { \\\n        _ISO_INTERN((string)); \\\n    }\n#endif\n\n\n\n/**********************/\n/*  Global constants  */\n/**********************/\n\n   extern ZCONST unsigned near mask_bits[17];\n   extern ZCONST char *fnames[2];\n\n#ifdef EBCDIC\n   extern ZCONST uch ebcdic[];\n#endif\n#ifdef IZ_ISO2OEM_ARRAY\n   extern ZCONST uch Far *iso2oem;\n   extern ZCONST uch Far iso2oem_850[];\n#endif\n#ifdef IZ_OEM2ISO_ARRAY\n   extern ZCONST uch Far *oem2iso;\n   extern ZCONST uch Far oem2iso_850[];\n#endif\n\n   extern ZCONST char Far  VersionDate[];\n   extern ZCONST char Far  CentSigMsg[];\n#ifndef SFX\n   extern ZCONST char Far  EndSigMsg[];\n#endif\n   extern ZCONST char Far  SeekMsg[];\n   extern ZCONST char Far  FilenameNotMatched[];\n   extern ZCONST char Far  ExclFilenameNotMatched[];\n   extern ZCONST char Far  ReportMsg[];\n\n#ifndef SFX\n   extern ZCONST char Far  Zipnfo[];\n   extern ZCONST char Far  CompiledWith[];\n#endif /* !SFX */\n\n\n\n/***********************************/\n/*  Global (shared?) RTL variables */\n/***********************************/\n\n#ifdef DECLARE_ERRNO\n   extern int             errno;\n#endif\n\n/*---------------------------------------------------------------------\n    Unicode Support\n    28 August 2005\n  ---------------------------------------------------------------------*/\n#if (defined(UNICODE_SUPPORT) && defined(UNICODE_WCHAR))\n\n  /* Default character when a zwchar too big for wchar_t */\n# define zwchar_to_wchar_t_default_char '_'\n\n  /* Default character string when wchar_t does not convert to mb */\n# define wide_to_mb_default_string \"_\"\n\n  /* wide character type */\n  typedef unsigned long zwchar;\n\n  /* UTF-8 related conversion functions, currently found in process.c */\n\n# if 0 /* currently unused */\n  /* check if string is all ASCII */\n  int is_ascii_string OF((ZCONST char *mbstring));\n# endif /* unused */\n\n  /* convert UTF-8 string to multi-byte string */\n  char *utf8_to_local_string OF((ZCONST char *utf8_string, int escape_all));\n\n  /* convert UTF-8 string to wide string */\n  zwchar *utf8_to_wide_string OF((ZCONST char *utf8_string));\n\n  /* convert wide string to multi-byte string */\n  char *wide_to_local_string OF((ZCONST zwchar *wide_string, int escape_all));\n\n# if 0 /* currently unused */\n  /* convert local string to multi-byte display string */\n  char *local_to_display_string OF((ZCONST char *local_string));\n# endif /* unused */\n\n  /* convert wide character to escape string */\n  char *wide_to_escape_string OF((unsigned long));\n\n# define utf8_to_escaped_string(utf8_string) \\\n         utf8_to_local_string(utf8_string, TRUE)\n\n# if 0 /* currently unused */\n  /* convert escape string to wide character */\n  unsigned long escape_string_to_wide OF((ZCONST char *escape_string));\n\n  /* convert local to UTF-8 */\n  char *local_to_utf8_string OF ((ZCONST char *local_string));\n\n  /* convert local to wide string */\n  zwchar *local_to_wide_string OF ((ZCONST char *local_string));\n\n  /* convert wide string to UTF-8 */\n  char *wide_to_utf8_string OF((ZCONST zwchar *wide_string));\n# endif /* unused */\n\n#endif /* UNICODE_SUPPORT && UNICODE_WCHAR */\n\n\n#endif /* !__unzpriv_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/unzvers.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n   unzvers.h (for UnZip) by Info-ZIP.\n */\n\n#ifndef __unzvers_h     /* don't include more than once */\n#define __unzvers_h\n\n#ifdef BETA\n#  undef BETA           /* undefine BETA for public releases */\n#endif\n\n#ifdef BETA\n#  define UZ_BETALEVEL      \"h03 BETA\"\n#  define UZ_VERSION_DATE   \"17 Apr 09\"         /* internal beta version */\n#else\n#  define UZ_BETALEVEL      \"\"\n#  define UZ_VERSION_DATE   \"20 April 2009\"     /* official release version */\n#  define RELEASE\n#endif\n\n#define UZ_MAJORVER    6   /* UnZip */\n#define UZ_MINORVER    0\n\n#define ZI_MAJORVER    3   /* ZipInfo */\n#define ZI_MINORVER    0\n\n#define UZ_PATCHLEVEL  0\n\n#define UZ_VER_STRING  \"6.0\"          /* keep in sync with Version numbers! */\n\n#ifndef IZ_COMPANY_NAME               /* might be already defined... */\n#  define IZ_COMPANY_NAME \"Info-ZIP\"\n#endif\n\n/* these are obsolete but remain for backward compatibility: */\n#if (defined(OS2) || defined(__OS2__))\n#  define D2_MAJORVER    UZ_MAJORVER    /* DLL for OS/2 */\n#  define D2_MINORVER    UZ_MINORVER\n#  define D2_PATCHLEVEL  UZ_PATCHLEVEL\n#endif\n\n#define DW_MAJORVER    UZ_MAJORVER    /* DLL for MS Windows */\n#define DW_MINORVER    UZ_MINORVER\n#define DW_PATCHLEVEL  UZ_PATCHLEVEL\n\n#define WIN_VERSION_DATE  UZ_VERSION_DATE\n\n#define UNZ_DLL_VERSION   UZ_VER_STRING\n\n/* The following version constants specify the UnZip version that introduced\n * the most recent incompatible change (means: change that breaks backward\n * compatibility) of a DLL/Library binary API definition.\n *\n * Currently, UnZip supports three distinct DLL/Library APIs, which each\n * carry their own \"compatibility level\":\n * a) The \"generic\" (console-mode oriented) API has been used on UNIX,\n *    for example. This API provides a \"callable\" interface similar to the\n *    interactive command line of the normal program executables.\n * b) The OS/2-only API provides (additional) functions specially tailored\n *    for interfacing with the REXX shell.\n * c) The Win32 DLL API with a pure binary interface which can be used to\n *    build GUI mode as well as Console mode applications.\n *\n * Whenever a change that breaks backward compatibility gets applied to\n * any of the DLL/Library APIs, the corresponding compatibility level should\n * be synchronized with the current UnZip version numbers.\n */\n/* generic DLL API minimum compatible version*/\n#define UZ_GENAPI_COMP_MAJOR  6\n#define UZ_GENAPI_COMP_MINOR  0\n#define UZ_GENAPI_COMP_REVIS  0\n/* os2dll API minimum compatible version*/\n#define UZ_OS2API_COMP_MAJOR  6\n#define UZ_OS2API_COMP_MINOR  0\n#define UZ_OS2API_COMP_REVIS  0\n/* windll API minimum compatible version*/\n#define UZ_WINAPI_COMP_MAJOR  6\n#define UZ_WINAPI_COMP_MINOR  0\n#define UZ_WINAPI_COMP_REVIS  0\n\n#endif /* !__unzvers_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/Contents",
    "content": "Contents of the \"vms\" sub-archive for UnZip 6.00 and later:\n\n  Contents            this file\n  INSTALL.VMS         VMS-specific build and install instructions\n  NOTES.TXT           description of new features in VMS Zip 3.0 and UnZip 6.0\n  README              general VMS info about using UnZip and zipfiles\n  UNZIP_MSG.MSG       messages source for VMS built-in error message facility\n  unzip_def.rnh       UnZip default help page, RUNOFF format\n  unzip_cli.help      UnZip VMSCLI help page, TPU format\n  unzipsfx.hlp        UnZipSFX pre-formatted help page\n  cvthelp.tpu         TPU macro file to convert .help file to RUNOFF format\n  cmdline.c           VMS-style command-line-interface code (if VMSCLI defined)\n  unz_cli.cld         more VMS-command-line stuff (if VMSCLI defined)\n  vms.c               VMS file manipulation code\n  vms.h               VMS header file for UnZip\n  vmscfg.h            VMS-specific configuration settings\n  vmsdefs.h           VMS system declarations (missing C compiler support)\n  build_unzip.com     command file to build or (re-)link UnZip\n  descrip.mms         MMK/MMS makefile for UnZip/ZipInfo and UnZipSFX\n  descrip_deps.mms    MMK/MMS include file providing source dependencies\n  descrip_mkdeps.mms  MMK/MMS makefile for regenerating descrip_deps.mms\n  descrip_src.mms     MMK/MMS include file, provides environment setup\n  collect_deps.com    command file used in source dependencies creation\n  mod_deps.com        command file used in source dependencies creation\n  unzip.opt           options file used for linking unzip\n  unzipsfx.opt        options file used for linking unzipsfx\n  makesfx.com         command file to create self-extracting archives\n  unixio_gcc.h        unixio.h system header replacement for gcc\n  unixlib_gcc.h       unixlib.h system header replacement for gcc\n  bzlib.h             VMS wrapper header file for the bzip2 library definitions\n  find_bzip2_lib.com  command procedure to set up environment for bzip2 support\n  infback9.h          VMS wrapper header file for zlib inflate64 definitions\n  zlib.h              VMS wrapper header file for zlib library definitions\n\nMAKE/VMS is no longer supported since MMK (MMS clone by Matt Madison/MadGoat\nEnterprises, compatible with descrip.mms) is both free and becoming quite\npopular.  MMK is available by anonymous ftp from ftp.spc.edu/ftp.wku.edu and\nby mailserver at lists.wku.edu.  Check VMS newsgroups for announcements and\nexact location.\n\nDetailed compilation and installation instructions can be found in the\nINSTALL.VMS file in this directory.\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/INSTALL.VMS",
    "content": "\n  VMS (OpenVMS):\n\n     On VMS, two build methods are provided: a command procedure, and\n     description files for MMS or MMK.  Both methods must be run from\n     the main directory, not the [.VMS] subdirectory.\n\n     A simple build using the command procedure looks like this:\n          @ [.VMS]BUILD_UNZIP.COM\n\n     A simple build using MMS or MMK looks like this:\n          MMS /DESCRIP = [.VMS]DESCRIP.MMS      ! Or, with MMK, ...\n          MMK /DESCRIP = [.VMS]DESCRIP.MMS\n\n     Various options for each build method are explained in comments in\n     the main builder file, either BUILD_UNZIP.COM or DESCRIP.MMS.\n\n     Here are some more complex build examples:\n\n     o Build with the large-file option enabled (non-VAX only):\n\n          @ [.VMS]BUILD_UNZIP LARGE\n       or:\n          MMS /DESC = [.VMS] /MACRO = LARGE=1\n\n     o Re-link the executables (small-file and large-file):\n\n          @ [.VMS]BUILD_UNZIP LINK\n          @ [.VMS]BUILD_UNZIP LARGE LINK\n       or\n          MMK /DESC = [.VMS] CLEAN_EXE  ! Deletes existing executables.\n          MMK /DESC = [.VMS]            ! Builds new executables.\n          MMK /DESC = [.VMS] /MACRO = LARGE=1 CLEAN_EXE\n          MMK /DESC = [.VMS] /MACRO = LARGE=1\n\n     o Build a large-file product from scratch, for debug, getting\n       compiler listings and link maps:\n\n          MMS /DESC = [.VMS] CLEAN\n          MMS /DESC = [.VMS] /MACRO = (DBG=1, LARGE=1. LIST=1)\n\n     On VAX, the builders attempt to cope with the various available C\n     compilers, DEC/Compaq/HP C, VAX C, or GNU C.  If DEC/Compaq/HP C is\n     not available or not desired, comments in the relevant builder file\n     explain the command-line options used to select a different\n     compiler.\n\n     By default, Zip uses (and UnZip supports) the \"deflate\" compression\n     method.  To add support for the optional \"bzip2\" compression method,\n     first obtain and build the bzip2 software (http://www.bzip.org/ or,\n     for a more VMS-friendly kit, http://antinode.info/dec/sw/bzip2.html).\n     Then, define the macro IZ_BZIP2 on the BUILD_UNZIP.COM or MMS/MMK\n     command line to specify the directory where the bzip2 files may be\n     found.  For example:\n\n          @ [.VMS]BUILD_UNZIP LARGE -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_4B_VMS]\n     or:\n          MMS /DESC = [.VMS] /MACRO = (LARGE=1, -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_4B_VMS])\n\n     Note that historically, UnZip has been built with the default\n     compiler option, /NAMES = UPPERCASE, while bzip2 is normally built\n     with /NAMES = AS_IS, to avoid name collisions.  With modern\n     compilers, the \"#pragma names\" directives in [.VMS]BZLIB.H will\n     handle these differences without user intervention.  An old\n     compiler (for example, DEC C V4.0-000) will emit complaints\n     %CC-I-UNKNOWNPRAGMA, and will mishandle the bzip2 library function\n     names, which will cause the link to fail.  To solve this problem,\n     either build the bzip2 BZ_NO_STDIO object library with /NAMES =\n     UPPERCASE, or else build UnZip with /NAMES = AS_IS.  For example:\n\n          @ [.VMS]BUILD_UNZIP LARGE \"CCOPTS=/NAMES=AS_IS\" -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_4B_VMS]\n     or:\n          MMS /DESC = [.VMS] /MACRO = (LARGE=1, \"CCOPTS=/NAMES=AS_IS\", -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_4B_VMS])\n\n     System-architecture-specific files (like objects and executables)\n     are placed in separate directories, such as [.ALPHA], [.IA64], or\n     [.VAX].  Large-file products get their own directories, [.ALPHAL]\n     or [.IA64L].  On VAX, VAX C products are placed in [.VAXV], GNU C\n     products in [.VAXG].  Each product builder announces what the\n     destination directory will be when it is run.\n\n     Common files, such as the help libraries (UNZIP.HLP for the default\n     UNIX-like command-line interface, UNZIP_CLI.HLP for the VMS-like\n     command-line interface), are placed in the main directory.  With a\n     mixed-architecture VMS cluster, the same main directory on a shared\n     disk may may be used by all system types.  (Using the NOHELP option\n     with BUILD_UNZIP.COM can keep it from making the same help files\n     repeatedly.)  Building the help files is detailed below.\n\n  Completing installation:\n\n     To complete the installation, the executables may be left in place,\n     or moved (or copied) to a convenient place.  While other methods\n     (like DCL$PATH) exist, most users define symbols to make the UnZip\n     executables available as foreign commands.  These symbol definitions\n     may be placed in a user's SYS$LOGIN:LOGIN.COM, or in a more central\n     location, like SYS$MANAGER:SYLOGIN.COM.  Typical symbol definitions\n     might look like these:\n\n          UNZIP :== $ dev:[dir]UNZIP.EXE        ! UNIX-like command line.\n     or:\n          UNZIP :== $ dev:[dir]UNZIP_CLI.EXE    ! VMS-like command line.\n\n     On a non-VAX system, different symbols could be defined for the\n     small-file and large-file programs.  For example:\n\n          UNZIPS  :== $ dev:[dir.ALPHA]UNZIP.EXE  ! UNZIPS = small-file UnZip.\n          UNZIP*L :== $ dev:[dir.ALPHAL]UNZIP.EXE !UNZIP[L] = large-file UnZip.\n\n     The builders create help text files, UNZIP.HLP and UNZIP_CLI.HLP.\n     These may be incorporated into an existing help library, or a separate\n     UnZip help library may be created using commands like these, using\n     either UNZIP.HLP (as shown) or UNZIP_CLI.HLP:\n\n          LIBRARY /HELP dev:[dir]existing_library.HLB UNZIP.HLP\n\n          LIBRARY /CREATE /HELP UNZIP.HLB UNZIP.HLP\n\n     UnZip help may then be accessed from a separate UnZip help library\n     using a command like:\n\n          HELP /LIBRARY = device:[directory]UNZIP.HLB\n\n     For greater ease, the user (or system manager) may define a\n     HLP$LIBRARY logical name to allow the HELP utility to find the UnZip\n     help library automatically.  See HELP HELP /USERLIBRARY for more\n     details.   The command procedure HLP_LIB_NEXT.COM may be used to\n     determine the next available HLP$LIBRARY logical name, and could be\n     adapted to define a HLP$LIBRARY logical name for a UnZip help library.\n\n     The builders also create VMS message files, UNZIP_MSG.EXE, in the\n     destination directory with the program executables.  A user may\n     gain DCL access to the UnZip error messages using a command like:\n\n          SET MESSAGE device:[directory]UNZIP_MSG.EXE\n\n     For system-wide access, the system manager may move or copy this\n     file to SYS$MESSAGE, although this could cause some confusion if\n     multiple versions of UnZip are used on the system, and their error\n     message source files differ.\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/NOTES.TXT",
    "content": "      VMS Notes for Info-ZIP Zip 3.0 and UnZip 6.0\n      ============================================\n\n   This document describes some VMS-specific behavior and implementation\ndetails of the Info-ZIP Zip and UnZip programs.\n\n   Last modified: 2009-03-02.\n\n\n   Command-line Case\n   -----------------\n\n   Zip and UnZip now include code which can preserve the case of\ncommand-line parameters and options, which obviates quoting upper-case\noptions like \"-V\" or \"-Z\".  This works on non-VAX systems with a\nsufficiently recent C RTL, and SET PROCESS /PARSE_STYLE = EXTENDED.\n(Sufficiently recent here means __CRTL_VER >= 70301000, which includes\nVMS V7.3-1 with a C Run Time Library ECO, or V7.3-2 or newer.)   This\ncode uses the decc$feature_set_value() function to enable the\nDECC$ARGV_PARSE_STYLE feature.  There is a small range of C RTL versions\nwhere this function is unavailable, but where manually setting the\nlogical name DECC$ARGV_PARSE_STYLE to \"ENABLE\" will work.   HELP CRTL\nleads to some additional information on these features.\n\n\n   File Name Case (ODS5)\n   ---------------------\n\n   In general, Zip 3.0 and UnZip 6.0 should handle file name case (and\nextended file names) in reasonable ways on ODS5 disks.\n\n   Zip offers a variety of \"-C\" (/PRESERVE_CASE) options to control how\ncase is handled when adding files to an archive.  The default settings\n(\"-C2-\", /PRESERVE_CASE = NOODS2, down-case ODS2 file names; \"-C5\",\n/PRESERVE_CASE = ODS5, preserve case of ODS5 file names) should be\nconsistent with previous Zip versions for files on ODS2 disks, and\nreasonable for files on ODS5 disks.\n\n   UnZip should preserve case when it extracts to an ODS5 destination\ndisk (unless \"-2\" (/ODS2) is specified).  (Note that previous UnZip\nversions, including version 5.52, did not properly preserve case for\ndirectories, which were always up-cased.)\n\n   The Zip and UnZip builders should work properly on ODS2 and ODS5\ndisks, with old (pre-ODS5) and new (case-conscious) versions of MMS (or\nMMK).  All testing was done with SET PROCESS /CASE_LOOKUP = BLIND.\nVarious problems may be expected with /CASE_LOOKUP = SENSITIVE.\n\n   For consistency, the builders should always create product files\n(.OBJ, .EXE, .HLB, and so on) with upper-case names, whether the build\nis done on an ODS2 or ODS5 disk.  Note, however, that in a world with\nboth ODS2 and ODS5 disks, and old and new Zip and UnZip versions, it's\npossible to encounter lower-case product file names.  For example, a VMS\nbinary kit could be created on an ODS2 disk, and a Zip archive created\nfrom that (using Zip 2.x, or Zip 3.x with default settings).  Such a Zip\narchive would contain down-cased names for those product files, and\nthose lower-case names would then normally be preserved when UnZip was\nused to extract that archive onto an ODS5 destination.  Normally, things\nwill work regardless of such case changes, but there may be some\nuntested combinations of unexpected name cases and quirky MMS (or MMK)\nbehavior, where something goes wrong.  Complaints are always welcome,\nbut it may not be possible to get everything to work as expected with\nevery version of VMS, MMS (or MMK), Zip, and UnZip, on every file\nsystem.\n\n   It might help matters if _all_ VMS binary kits were produced on ODS5\ndisks, and packaged using (case-preserving) Zip version 3.x, but this\nwould certainly be different from the way things have been done before,\nand maintaining control over this process is essentially impossible.\n\n\n   Symbolic Links (ODS5)\n   ---------------------\n\n   VMS V8.3 offers support for symbolic links (symlinks) on ODS5 disks.\nIn previous Zip and UnZip versions, the generic code for symlinks was\ndisabled, and there was no VMS-specific code for symlinks.  Now, by\ndefault, Zip and UnZip attempt to support symlinks wherever the C\nheaders and C run-time library include the functions needed for symlink\nsupport.  This means non-VAX systems with __CRTL_VER >= 70301000, so\nthis includes VMS V7.3-1 and up, and thus symlink-capable Zip and UnZip\nprograms may be built on systems which do not themselves offer symlink\nsupport.  (Various run-time failures may be expected if symlinks are\nencountered on pre-V8.3 systems, either in a file system or in a Zip\narchive.)\n\n   Symlink support can be disabled at build-time, if desired, by\ndefining the C macro NO_SYMLINKS.  (See comments in the builder\nregarding LOCAL_UNZIP or LOCAL_ZIP, as appropriate.)  For example, using\nMMS to build UnZip:\n\n      MMS /DESCRIP = [.VMS] /MACRO = (\"LOCAL_UNZIP=NO_SYMLINKS=1\")\n\nor, using the command procedure to build Zip:\n\n      LOCAL_ZIP == \"NO_SYMLINKS=1\"\n      @ [.VMS]BUILD_ZIP.COM\n      DELETE /SYMBOL /GLOBAL LOCAL_ZIP\n\n   The Zip or UnZip \"-v\" (/VERBOSE) report should include\nSYMLINK_SUPPORT (Zip) or SYMLINKS (UnZip) in its list of \"special\ncompilation options\" if the program was built with symlink support.\n\n\n   File I/O Performance\n   --------------------\n\n   When compiled using DEC/Compaq/HP C (not GNU C or VAX C), the Zip and\nUnZip file I/O code now includes access callback functions which are\nused to try to set some RMS parameters to non-default values, with the\nintention of improving file I/O speed.  This affects reading an archive\nfile in UnZip and writing one in Zip.  (Reading and writing the\nindividual data files are handled in more exotic ways, making these\nparameters less important for them.)\n\n   Currently, the built-in default parameters enable read-ahead and\nwrite-behind, using a multi-buffer count of 2, and a multi-block count\nof 127 (the maximum).  For writing the archive, the default extend\nquantity is 16384 blocks (8MB), with truncation enabled.  This\ncombination is believed to be, at worst, fairly harmless for most\nsituations, and, in most cases, to provide a substantial speed\nimprovement, especially with large archives.\n\n   This code allows SET RMS_DEFAULT parameters to override the built-in\ndefault values.  On some old VMS versions, sys$getjpi() can not provide\nthe SET RMS_DEFAULT values, and in this situation, the callback function\nwill not try to use its improved parameter values.  Users on such old\nVMS versions who seek improved I/O speed may wish to bypass this check,\nwhich requires changing the code in the get_rms_defaults() function in\n[.VMS]VMS.C.  The \"-vv\" (/VERBOSE = MORE) option on both programs\nenables diagnostic messages which show the operation of the callback\nfunction.  A message showing a failure status from sys$getjpi()\nindicates this problem.\n\n   Sample results (UnZip shown, Zip similar):\n\n   VMS VAX V5.4, VAX C.  Callback code disabled, no messages:\n      WIMP $ unzip -tvv TESTMAKE.ZIP\n      Archive:  SYS$SYSDEVICE:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMS VAX V5.5-2, DEC C.  SYS$GETJPI() fails (%SYSTEM-F-BADPARAM):\n      WEAK $ unzip -tvv TESTMAKE.ZIP\n      Get RMS defaults.  getjpi sts = %x00000014.\n      Archive:  DUA1:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMS VAX V7.3, DEC/Compaq C.  Callback code works:\n      WUSS $ unzip -tvv TESTMAKE.ZIP\n      Get RMS defaults.  getjpi sts = %x00000001.\n                     Default: deq =      0, mbc =   0, mbf =   0.\n      Open callback.  ID = 1, deq =  16384, mbc = 127, mbf =   2.\n      Archive:  ALP$DKA0:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMSV5.5-2 is too old.  V7.3 is new enough.  Anyone with more precise\ninformation is invited to contribute it.\n\n   Users who find other parameter sets more beneficial, or who find\nparticular problems with this set are welcome to comment.\n\n   In this version, as in previous versions, when UnZip expands a -V\narchive, it allocates the entire extent of a data file before writing\nany of its data.  In some previous versions, this could cause the\ndestination disk to be locked for a considerable time (minutes), if\nhighwater marking was enabled on that disk.  Now, the FAB SQO\n(\"sequential access only\") flag (or equivalent) is set, which prevents\nthis troublesome disk locking.\n\n   In some previous versions, when UnZip expanded a non-V archive, it\ndid no pre-allocation, and used the default extension quantity.  This\ncould slow file creation significantly for large files.  Now, space for\nextracted files is pre-allocated, and the same SQO (\"sequential access\nonly\") flag is set, as with a -V archive.\n\n\n   Changes to the \"-V\" (/VMS) Option\n   ---------------------------------\n\n   The intent of the \"-V\" (/VMS) option was to store VMS file attributes\nin a Zip archive, allowing UnZip to extract an exact copy of a file on a\nVMS system, including all its VMS attributes.\n\n   In Zip before version 2.31, using the \"-V\" (/VMS) option created an\narchive which usually contained data from beyond the EOF (End-of-File)\nmarker in a data file, but generally not all the disk blocks allocated\nfor the file.  When extracted on a VMS system, the result was usually\nacceptable (because the data from beyond the EOF marker were usually\nignored).  However, when extracted on a non-VMS system, the resulting\nfile was usually corrupted by being NUL-padded to the next larger 16KB\nmultiple in size.\n\n   Now (Zip 2.31 and later), with \"-V\" (/VMS), Zip truncates a data file\nat EOF, and portable-format files (Stream_LF, fixed-512) should be\nextracted properly on a non-VMS system.  On a VMS system, well-formed\nfiles (that is, those with no valid data beyond EOF) should also be\nrestored correctly.\n\n   With the new \"-VV\" (/VMS = ALL) option, the archive includes all\nallocated blocks for the file (including those beyond EOF).  When\nextracted on a VMS system, the original file should be reproduced with\nas much fidelity as possible, but on a non-VMS system, most files will\nbe seen as corrupt because of the data from beyond EOF.\n\n\n   Changes to Program Exit Status Values\n   -------------------------------------\n\n   Zip and UnZip exit with 32-bit VMS status values which are formed\nfrom their internal OS-independent status values.  In previous program\nversions, this was done by converting the internal success code (0) into\n%x00000001 (SS$_NORMAL), and converting the other internal warning and\nerror codes using an artificial control/facility code, 0x7FFF (which\nincludes some reserved bits), and a severity value which was determined\naccording to rules specified in the VMS-specific exit function.\nCuriously, the internal status codes were left-shifted by 4 bits instead\nof 3, so all the resulting VMS message codes (bits 13:3) were even.\n\n   Zip and UnZip now have facility names and codes assigned by HP\n(UnZip: IZ_UNZIP, 1954; Zip: IZ_ZIP, 1955).  Now, by default, the\nprograms exit with standard 32-bit VMS status values which differ from\nthe old ones in several ways: The official facility code is used, and\nthe facility-specific bit is set.  (For compatibility with older\nversions, the internal status codes are still left-shifted by 4 bits.\nThis also makes it easier to extract the internal status code from a\nhexadecimal representation of the VMS status code.)  The builders also\ncreate non-executable message files (UNZIP_MSG.EXE and ZIP_MSG.EXE) so\nthat, after a suitable SET MESSAGE command, the program messages will be\navailable from DCL.  For example:\n\n      $ SET MESSAGE dev:[dir]ZIP_MSG.EXE\n      $ ZIP FRED.ZIP no_such_file\n        zip warning: name not matched: no_such_file\n\n      zip error: Nothing to do!\n      (dev:[dir]FRED.ZIP;)\n\n      ALP $ WRITE SYS$OUTPUT F$MESSAGE( $STATUS)\n      %IZ_ZIP-W-NONE, Nothing to do\n\nThe message files may be copied into SYS$MESSAGE to make them generally\navailable, although this could cause some confusion if multiple versions\nof the programs are used on the system, and their error message source\nfiles differ.  Each different destination directory will get its own\nUNZIP_MSG.EXE or ZIP_MSG.EXE ([.ALPHA], [.ALPHAL], [.VAX], and so on),\nbut all of the same-architecture files are equivalent to each other.\nThat is, on an Alpha system, any of the [.ALPHA*]ZIP_MSG.EXE files could\nbe used; on an IA64 system, any of the [.IA64*]ZIP_MSG.EXE files could\nbe used; and on a VAX system, any of the [.VAX*]ZIP_MSG.EXE files could\nbe used.  (Similar for UNZIP_MSG.EXE, of course.)\n\n   If desired, the programs may be built to use the old exit status values\nby defining a C macro with the old facility value:\n\"CTL_FAC_IZ_UNZIP=0x7FFF\" (UnZip) or \"CTL_FAC_IZ_ZIP=0x7FFF\" (Zip).\n(See comments in the builder regarding LOCAL_UNZIP or LOCAL_ZIP, as\nappropriate.)  This will maintain compatibility with older program\nversions, but will make the programs incompatible with the new error\nmessage files.\n\n\n   VMS File Attribute Schemes\n   --------------------------\n\n   Zip's \"-V\" (/VMS) option causes VMS file attributes to be stored in\nan archive.  Since Zip version 2.2 (released in 1996), Zip has, by\ndefault, stored VMS file attributes using a scheme (\"PK\") which is\ncompatible with the one used by PKWARE in their PKZIP product.  Before\nthat, a different scheme (\"IM\") was used.  UnZip versions before 5.2\nsupport only the older IM scheme, but since UnZip version 5.2, both\nschemes have been supported by UnZip.\n\n   The IM scheme has not been well tested recently, but it is still\navailable.  Some problems were seen when the IM scheme was used with\nsymbolic links on VMS V8.3.  Details on how build Zip to use the IM\nscheme instead of the PK scheme are included in comments in the main\nbuilder files.  Look for VMS_IM_EXTRA in [.VMS]BUILD_ZIP.COM or IM in\n[.VMS]DESCRIP.MMS.\n\n   The \"special compilation options\" section of a \"zip -v\" (\"zip\n/verbose\") report should show either VMS_PK_EXTRA or VMS_IM_EXTRA,\naccording to how Zip was built.\n\n\n   UTC Date-Times\n   --------------\n\n   Zip archives traditionally include local (MS-DOS compatible)\ndate-time information for files.  Since Zip version 2.1, it has also\nbeen possible to store UTC date-time information in the archive, and\nsince UnZip version 5.2, UnZip has been able to use this UTC date-time\ninformation when extracting files.\n\n   On VMS, support in the C run-time environment for UTC became\navailable with VMS V7.0.  UTC support in Zip and UnZip is automatically\nenabled at compile time, if it is available on the system where the code\nis compiled (__CRTL_VER >= 70000000).  It may be disabled at compile\ntime by defining the C macro NO_EF_UT_TIME.  Details on how build Zip\nand UnZip with additional C macros defined are included in comments in\nthe main builder files.  Look for LOCAL_[UN]ZIP in\n[.VMS]BUILD_[UN]ZIP.COM or in [.VMS]DESCRIP.MMS.  For example, using MMS\nto build UnZip:\n\n      MMS /DESCRIP = [.VMS] /MACRO = (\"LOCAL_UNZIP=NO_EF_UT_TIME=1\")\n\nor, using the command procedure to build Zip:\n\n      LOCAL_ZIP == \"NO_EF_UT_TIME=1\"\n      @ [.VMS]BUILD_ZIP.COM\n      DELETE /SYMBOL /GLOBAL LOCAL_ZIP\n\n   The \"special compilation options\" section of a \"zip -v\" (\"zip\n/verbose\") or \"unzip -v\" (\"unzip /verbose\") report should show\nUSE_EF_UT_TIME if the program was built with UTC support.\n\n\n   Building with the LIST option using MMK or MMS\n   ----------------------------------------------\n\n   Currently, building with MMK or MMS using the LIST option (as in\n\"/MACRO = LIST=1\") may cause a failure for some old versions of the DEC\nC compiler.  The LIST option currently adds \"/show = (all, nomessages)\"\nto the CC command line, and some old DEC C compilers do not support the\n\"nomessages\" keyword.  When VAX C is used, this keyword is omitted, but\nthe builder does not distinguish between the various DEC/Compaq/HP C\nversions.  The work-arounds are to use BUILD_[UN]ZIP.COM, or edit\n[.VMS]DESCRIP_SRC.MMS to remove the troublesome keyword.\n\n\n   GNU C\n   -----\n\n   Zip and UnZip have been built using GNU C (VAX) version 2.3, mostly\nfor fun, but serious users are encouraged to report any interest in\ncontinuing this activity.  The GNU C 2.3 header files were missing some\nthings, including definitions of SEEK_CUR, SEEK_END, and SEEK_SET.  The\nVMS-specific code now expects to find unixio.h and unixlib.h, which were\nabsent from the GNU C 2.3 distribution.\n\n   To work around these difficulties, the Zip and UnZip kits include\nsome emergency replacement unixio.h and unixlib.h files which appear to\nwork for these programs, at least.  To install them, use commands like\nthe following:\n\n      COPY [.VMS]UNIXIO_GCC.H GNU_CC_INCLUDE:[000000]UNIXIO.H\n      COPY [.VMS]UNIXLIB_GCC.H GNU_CC_INCLUDE:[000000]UNIXLIB.H\n      SET PROTECTION W:RE GNU_CC_INCLUDE:[000000]UNIXIO.H, UNIXLIB.H\n\n   There may be an error in the GNU C header file ATRDEF.H which can\ncause Zip to fail, when making a \"-V\" archive, with a spurious \"could\nnot open for reading\" error message, followed by more bad behavior.  It\nprobably also causes trouble of some kind in UnZip.  To check the\nquestionable macro definition, use a command like the following:\n\n      SEARCH GNU_CC_INCLUDE:[000000]ATRDEF.H ATR$S_JOURNAL\n\nThis should show something equivalent to this:\n\n      #define ATR$S_JOURNAL           0x001\n\nIf you see \"0x002\" (or equivalent) instead of \"0x001\" (or equivalent),\nthen this value must be corrected in the file before building Zip or\nUnZip.\n\n   You may also see several warnings from the compiler caused by other\ndefects in the GNU C header files, such as:\n\n<various>: warning: passing arg 4 of `qsort' from incompatible pointer type\n\n[...]rab.h:134: warning: unnamed struct/union that defines no instances\n[...]rab.h:143: warning: unnamed struct/union that defines no instances\n\nThese warnings appear to be harmless.\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/README",
    "content": "VMS README for UnZip 5.3 and later, 25 February 1997\n----------------------------------------------------\n\nNotes about using UnZip and zipfiles under VMS (see INSTALL for instructions\non compiling):\n\n - Install UnZip as foreign symbol by adding this to login.com:\n      $ unzip == \"$disk:[dir]unzip.exe\"\n      $ zipinfo == \"$disk:[dir]unzip.exe \"\"-Z\"\"\"\n   where \"disk\" and \"dir\" are location of UnZip executable; the \"$\" before\n   the disk name is important.  Some people, including the author, prefer\n   a short alias such as \"ii\" instead of \"zipinfo\"; edit to taste.  (All of\n   the quotes around the -Z are necessary, but don't ask us to explain it...)\n\n - Optionally install UnZipSFX for use with the MAKESFX.COM command file:\n      $ unzipsfx :== disk:[dir]unzipsfx.exe\n   Thereafter an archive \"foo.zip\" may be converted to \"foo.exe\" simply by\n   typing \"@makesfx foo\" (assuming MAKESFX.COM is in the current directory).\n   Note that there is *no* leading \"$\" in this case.\n\n - After proper installation, the default version of UnZip is invoked just\n   as in Unix or MS-DOS:  \"unzip -opts archive files\".  The hyphen ('-') is\n   the switch character, not the slash ('/') as in native VMS commands.  An\n   alternative is available if VMSCLI is defined during compilation; this\n   version does provide a native VMS-style command interface (e.g., /ZIPINFO\n   instead of -Z).  Both versions accept the command \"unzip -v\", which can\n   be used to check whether VMSCLI was defined or not; but an even simpler\n   method is to type \"unzip\" and look at the help screen.  Note that options\n   placed in an environment variable (UNZIP_OPTS) must be of the short, hy-\n   phenated form regardless of how UnZip was compiled.\n\n - The VMS C runtime library translates all command-line text to lowercase\n   unless it is quoted, making some options and/or filenames not work as\n   intended.  For example:\n        unzip -V zipfile vms/README;*\n   is translated to\n        unzip -v zipfile vms/readme;*\n   which may not match the contents of the zipfile and definitely won't\n   extract the file with its version number as intended.  This can be\n   avoided by use of the -C option (/CASE_INSENSITIVE) or by enclosing\n   the uppercase stuff in quotes:\n        unzip \"-V\" zipfile \"vms/README;*\"\n   Note that quoting the whole line probably won't work, since it would\n   be interpreted as a single argument by the C library.\n\n - Wildcards that refer to files internal to the archive behave like Unix\n   wildcards, not VMS ones (assuming UnZip was not compiled with VMSWILD\n   defined).  This is both a matter of consistency (see above) and power--\n   full Unix regular expressions are supported, so that one can specify\n   \"all .c and .h files that start with a, b, c or d and do not have a 2\n   before the dot\" as \"[a-d]*[^2].[ch]\".  Of course, \"*.[ch]\" is a much more\n   common wildcard specification, but the power is there if you need it.\n   Note that \"*\" matches zipfile directory separators ('/'), too.  If UnZip\n   *was* compiled with VMSWILD defined (do \"unzip -v\" to check), the single-\n   character wildcard is \"%\" rather than \"?\", and character sets (ranges)\n   are delimited with () instead of [] (for example, \"*.(ch)\").\n\n - Wildcards that refer to zipfiles (i.e., external VMS files) behave like\n   normal VMS wildcards regardless of whether VMSWILD was defined or not.\n   Ranges are not supported.  Thus \"unzip *font-%.zip\" is about as much as\n   one can do for specifying wildcard zipfiles.\n\n - Created files get whatever permissions were stored in the archive (mapped\n   to VMS and/or masked with your default permissions, depending on the\n   originating operating system), but created directories additionally in-\n   herit the (possibly more restrictive) permissions of the parent directory.\n   And obviously things won't work if you don't have permission to write to\n   the extraction directory.\n\n - When transferring files, particularly via Kermit, pay attention to the\n   settings!  In particular, zipfiles must be transferred in some binary\n   mode, which is NOT Kermit's default mode, and this mode must usually be\n   set on BOTH sides of the transfer (e.g., both VAX and PC).  See the notes\n   below for details.\n\n\n\n\nFrom Info-ZIP Digest (Wed, 6 Nov 1991), Volume 91, Issue 290:\n\n   Date: Tue, 5 Nov 91 15:31 CDT\n   From: Hugh Schmidt <HUGH@macc.wisc.edu>\n\n            ****************************************************\n            *** VMS ZIP and PKZIP compatibility using KERMIT ***\n            ****************************************************\n\n   Many use Procomm's kermit to transfer zipped files between PC and VMS\n   VAX.  The following VMS kermit settings make VMS Zip/UnZip compatible\n   with PC Zip/UnZip or PKZIP/PKUNZIP:\n                                         VMS kermit          Procomm kermit\n                                    -------------------   --------------------\n   Uploading PC zipfile to VMS:     set file type fixed   set file type binary\n   Downloading VMS zipfile to PC:   set file type block   set file type binary\n\n   \"Block I/O lets you bypass the VMS RMS record-processing capabilities\n   entirely\", (Guide to VMS file applications, Section 8.5).  The kermit\n   guys must have known this!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/UNZIP_MSG.MSG",
    "content": "!    VMS Error Message Source File for UnZip\n!\n! Because the facility code was formally assigned by HP, the .FACILITY\n! directive below specifies /SYSTEM.  Because the messages are, in\n! general, specific to UnZip, this file is not compiled with /SHARED.\n! For example:\n!\n!    MESSAGE /OBJECT = [.dest]UNZIP_MSG.OBJ /NOSYMBOLS [.VMS]UNZIP_MSG.MSG\n!\n!    LINK /SHAREABLE = [.dest]UNZIP_MSG.EXE [.dest]UNZIP_MSG.OBJ\n!\n!-----------------------------------------------------------------------\n\n.TITLE  Info-ZIP UnZip Error Messages\n.FACILITY IZ_UNZIP, 1954 /SYSTEM\n.IDENT 'V6.0-000'\n\n! PK_\n.BASE 0\nOK      /SUCCESS      <Normal successful completion>\n.BASE 2\nWARN    /WARNING      <Generic warning - bad CRC, unknown compress method, ...>\n.BASE 4\nERR     /ERROR        <Error in zipfile>\n.BASE 6\nBADERR  /SEVERE       <Error in zipfile>\n.BASE 8\nMEM     /SEVERE       <insufficient memory (init)>\n.BASE 10\nMEM2    /SEVERE       <insufficient memory (password)>\n.BASE 12\nMEM3    /SEVERE       <insufficient memory (file expand)>\n.BASE 14\nMEM4    /SEVERE       <insufficient memory (memory expand)>\n.BASE 16\nMEM5    /SEVERE       <insufficient memory (???)>\n.BASE 18\nNOZIP   /ERROR        <zipfile not found>\n.BASE 20\nPARAM   /ERROR        <Invalid parameters specified on command line>\n.BASE 22\nFIND    /ERROR        <No files found to extract or view>\n\n.BASE 100\nDISK    /SEVERE       <I/O error - disk full, ...>\n.BASE 102\nEOF     /SEVERE       <Unexpected end-of-file in zipfile>\n\n! IZ_\n.BASE 160\nCTRLC   /ERROR        <User interrupt (CRTL/C)>\n.BASE 162\nUNSUP   /ERROR        <Unsupported compression or encryption for all files>\n.BASE 164\nBADPWD  /ERROR        <Bad decryption password for all files>\n.BASE 166\nERRBF   /ERROR        <Large-file archive, small-file program>\n\n.END\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/build_unzip.com",
    "content": "$! BUILD_UNZIP.COM\n$!\n$!     Build procedure for VMS versions of UnZip/ZipInfo and UnZipSFX.\n$!\n$!     Last revised:  2009-03-01  SMS.\n$!\n$!     Command arguments:\n$!     - suppress help file processing: \"NOHELP\"\n$!     - suppress message file processing: \"NOMSG\"\n$!     - select link-only: \"LINK\"\n$!     - select compiler environment: \"VAXC\", \"DECC\", \"GNUC\"\n$!     - select BZIP2 support: \"USEBZ2\"\n$!       This option is a shortcut for \"IZ_BZIP2=SYS$DISK:[.bzip2]\", and\n$!       runs the DCL build procedure there,\n$!     - select BZIP2 support: \"IZ_BZIP2=dev:[dir]\", where \"dev:[dir]\"\n$!       (or a suitable logical name) tells where to find \"bzlib.h\".\n$!       The BZIP2 object library (LIBBZ2_NS.OLB) is expected to be in\n$!       a \"[.dest]\" directory under that one (\"dev:[dir.ALPHAL]\", for\n$!       example), or in that directory itself.\n$!       By default, the SFX programs are built without BZIP2 support.\n$!       Add \"BZIP2_SFX=1\" to the LOCAL_UNZIP C macros to enable it.\n$!       (See LOCAL_UNZIP, below.)\n$!     - use ZLIB compression library: \"IZ_ZLIB=dev:[dir]\", where\n$!       \"dev:[dir]\" (or a suitable logical name) tells where to find\n$!       \"zlib.h\".  The ZLIB object library (LIBZ.OLB) is expected to be\n$!       in a \"[.dest]\" directory under that one (\"dev:[dir.ALPHAL]\",\n$!       for example), or in that directory itself.\n$!     - select large-file support: \"LARGE\"\n$!     - select compiler listings: \"LIST\"  Note that the whole argument\n$!       is added to the compiler command, so more elaborate options\n$!       like \"LIST/SHOW=ALL\" (quoted or space-free) may be specified.\n$!     - supply additional compiler options: \"CCOPTS=xxx\"  Allows the\n$!       user to add compiler command options like /ARCHITECTURE or\n$!       /[NO]OPTIMIZE.  For example, CCOPTS=/ARCH=HOST/OPTI=TUNE=HOST\n$!       or CCOPTS=/DEBUG/NOOPTI.  These options must be quoted or\n$!       space-free.\n$!     - supply additional linker options: \"LINKOPTS=xxx\"  Allows the\n$!       user to add linker command options like /DEBUG or /MAP.  For\n$!       example: LINKOPTS=/DEBUG or LINKOPTS=/MAP/CROSS.  These options\n$!       must be quoted or space-free.  Default is\n$!       LINKOPTS=/NOTRACEBACK, but if the user specifies a LINKOPTS\n$!       string, /NOTRACEBACK will not be included unless specified by\n$!       the user.\n$!     - select installation of CLI interface version of UnZip:\n$!       \"VMSCLI\" or \"CLI\"\n$!     - force installation of UNIX interface version of UnZip\n$!       (override LOCAL_UNZIP environment): \"NOVMSCLI\" or \"NOCLI\"\n$!\n$!     To specify additional options, define the symbol LOCAL_UNZIP\n$!     as a comma-separated list of the C macros to be defined, and\n$!     then run BUILD_UNZIP.COM.  For example:\n$!\n$!             $ LOCAL_UNZIP = \"RETURN_CODES\"\n$!             $ @ [.VMS]BUILD_UNZIP.COM\n$!\n$!     VMS-specific options include VMSWILD and RETURN_CODES.  See the\n$!     INSTALL file for other options (for example, CHECK_VERSIONS).\n$!\n$!     If you edit this procedure to set LOCAL_UNZIP here, be sure to\n$!     use only one \"=\", to avoid affecting other procedures.\n$!\n$!     Note: This command procedure always generates both the \"default\"\n$!     UnZip having the UNIX style command interface and the \"VMSCLI\"\n$!     UnZip having the CLI compatible command interface.  There is no\n$!     need to add \"VMSCLI\" to the LOCAL_UNZIP symbol.  (The only effect\n$!     of \"VMSCLI\" now is the selection of the CLI style UnZip\n$!     executable in the foreign command definition.)\n$!\n$!\n$ on error then goto error\n$ on control_y then goto error\n$ OLD_VERIFY = f$verify( 0)\n$!\n$ edit := edit                  ! override customized edit commands\n$ say := write sys$output\n$!\n$!##################### Read settings from environment ########################\n$!\n$ if (f$type( LOCAL_UNZIP) .eqs. \"\")\n$ then\n$     LOCAL_UNZIP = \"\"\n$ else  ! Trim blanks and append comma if missing\n$     LOCAL_UNZIP = f$edit( LOCAL_UNZIP, \"TRIM\")\n$     if (f$extract( (f$length( LOCAL_UNZIP)- 1), 1, LOCAL_UNZIP) .nes. \",\")\n$     then\n$         LOCAL_UNZIP = LOCAL_UNZIP + \", \"\n$     endif\n$ endif\n$!\n$! Check for the presence of \"VMSCLI\" in LOCAL_UNZIP.  If yes, we will\n$! define the foreign command for \"unzip\" to use the executable\n$! containing the CLI interface.\n$!\n$ pos_cli = f$locate( \"VMSCLI\", LOCAL_UNZIP)\n$ len_local_unzip = f$length( LOCAL_UNZIP)\n$ if (pos_cli .ne. len_local_unzip)\n$ then\n$     CLI_IS_DEFAULT = 1\n$     ! Remove \"VMSCLI\" macro from LOCAL_UNZIP. The UnZip executable\n$     ! including the CLI interface is now created unconditionally.\n$     LOCAL_UNZIP = f$extract( 0, pos_cli, LOCAL_UNZIP)+ -\n       f$extract( pos_cli+7, len_local_unzip- (pos_cli+ 7), LOCAL_UNZIP)\n$ else\n$     CLI_IS_DEFAULT = 0\n$ endif\n$ delete /symbol /local pos_cli\n$ delete /symbol /local len_local_unzip\n$!\n$!##################### Customizing section #############################\n$!\n$ unzx_unx = \"UNZIP\"\n$ unzx_cli = \"UNZIP_CLI\"\n$ unzsfx_unx = \"UNZIPSFX\"\n$ unzsfx_cli = \"UNZIPSFX_CLI\"\n$!\n$ CCOPTS = \"\"\n$ IZ_BZIP2 = \"\"\n$ BUILD_BZIP2 = 0\n$ IZ_ZLIB = \"\"\n$ LINKOPTS = \"/notraceback\"\n$ LINK_ONLY = 0\n$ LISTING = \" /nolist\"\n$ LARGE_FILE = 0\n$ MAKE_HELP = 1\n$ MAKE_MSG = 1\n$ MAY_USE_DECC = 1\n$ MAY_USE_GNUC = 0\n$!\n$! Process command line parameters requesting optional features.\n$!\n$ arg_cnt = 1\n$ argloop:\n$     current_arg_name = \"P''arg_cnt'\"\n$     curr_arg = f$edit( 'current_arg_name', \"UPCASE\")\n$     if (curr_arg .eqs. \"\") then goto argloop_out\n$!\n$     if (f$extract( 0, 5, curr_arg) .eqs. \"CCOPT\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         CCOPTS = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 7, curr_arg) .eqs. \"IZ_BZIP\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         IZ_BZIP2 = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 6, curr_arg) .eqs. \"USEBZ2\")\n$     then\n$         if (IZ_BZIP2 .eqs. \"\")\n$         then\n$             IZ_BZIP2 = \"SYS$DISK:[.BZIP2]\"\n$             BUILD_BZIP2 = 1\n$         endif\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 7, curr_arg) .eqs. \"IZ_ZLIB\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         IZ_ZLIB = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 5, curr_arg) .eqs. \"LARGE\")\n$     then\n$         LARGE_FILE = 1\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 7, curr_arg) .eqs. \"LINKOPT\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         LINKOPTS = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$! Note: LINK test must follow LINKOPTS test.\n$!\n$     if (f$extract( 0, 4, curr_arg) .eqs. \"LINK\")\n$     then\n$         LINK_ONLY = 1\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 4, curr_arg) .eqs. \"LIST\")\n$     then\n$         LISTING = \"/''curr_arg'\"      ! But see below for mods.\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"NOHELP\")\n$     then\n$         MAKE_HELP = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"NOMSG\")\n$     then\n$         MAKE_MSG = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"VAXC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"DECC\")\n$     then\n$         MAY_USE_DECC = 1\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"GNUC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 1\n$         goto argloop_end\n$     endif\n$!\n$     if ((curr_arg .eqs. \"VMSCLI\") .or. (curr_arg .eqs. \"CLI\"))\n$     then\n$         CLI_IS_DEFAULT = 1\n$         goto argloop_end\n$     endif\n$!\n$     if ((curr_arg .eqs. \"NOVMSCLI\") .or. (curr_arg .eqs. \"NOCLI\"))\n$     then\n$         CLI_IS_DEFAULT = 0\n$         goto argloop_end\n$     endif\n$!\n$     say \"Unrecognized command-line option: ''curr_arg'\"\n$     goto error\n$!\n$     argloop_end:\n$     arg_cnt = arg_cnt + 1\n$ goto argloop\n$ argloop_out:\n$!\n$ if (CLI_IS_DEFAULT)\n$ then\n$     UNZEXEC = unzx_cli\n$ else\n$     UNZEXEC = unzx_unx\n$ endif\n$!\n$!#######################################################################\n$!\n$! Find out current disk, directory, compiler and options\n$!\n$ workdir = f$environment( \"default\")\n$ here = f$parse( workdir, , , \"device\")+ f$parse( workdir, , , \"directory\")\n$!\n$! Sense the host architecture (Alpha, Itanium, or VAX).\n$!\n$ if (f$getsyi( \"HW_MODEL\") .lt. 1024)\n$ then\n$     arch = \"VAX\"\n$ else\n$     if (f$getsyi( \"ARCH_TYPE\") .eq. 2)\n$     then\n$         arch = \"ALPHA\"\n$     else\n$         if (f$getsyi( \"ARCH_TYPE\") .eq. 3)\n$         then\n$             arch = \"IA64\"\n$         else\n$             arch = \"unknown_arch\"\n$         endif\n$     endif\n$ endif\n$!\n$ dest = arch\n$ cmpl = \"DEC/Compaq/HP C\"\n$ opts = \"\"\n$ if (arch .nes. \"VAX\")\n$ then\n$     HAVE_DECC_VAX = 0\n$     USE_DECC_VAX = 0\n$!\n$     if (MAY_USE_GNUC)\n$     then\n$         say \"GNU C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build UnZip.\"\n$         goto error\n$     endif\n$!\n$     if (.not. MAY_USE_DECC)\n$     then\n$         say \"VAX C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build UnZip.\"\n$         goto error\n$     endif\n$!\n$     cc = \"cc /standard = relax /prefix = all /ansi\"\n$     defs = \"''LOCAL_UNZIP'MODERN\"\n$     if (LARGE_FILE .ne. 0)\n$     then\n$         defs = \"LARGE_FILE_SUPPORT, ''defs'\"\n$     endif\n$ else\n$     if (LARGE_FILE .ne. 0)\n$     then\n$        say \"LARGE_FILE_SUPPORT is not available on VAX.\"\n$        LARGE_FILE = 0\n$     endif\n$     HAVE_DECC_VAX = (f$search( \"SYS$SYSTEM:DECC$COMPILER.EXE\") .nes. \"\")\n$     HAVE_VAXC_VAX = (f$search( \"SYS$SYSTEM:VAXC.EXE\") .nes. \"\")\n$     MAY_HAVE_GNUC = (f$trnlnm( \"GNU_CC\") .nes. \"\")\n$     if (HAVE_DECC_VAX .and. MAY_USE_DECC)\n$     then\n$         ! We use DECC:\n$         USE_DECC_VAX = 1\n$         cc = \"cc /decc /prefix = all\"\n$         defs = \"''LOCAL_UNZIP'MODERN\"\n$     else\n$         ! We use VAXC (or GNU C):\n$         USE_DECC_VAX = 0\n$         defs = \"''LOCAL_UNZIP'VMS\"\n$         if ((.not. HAVE_VAXC_VAX .and. MAY_HAVE_GNUC) .or. MAY_USE_GNUC)\n$         then\n$             cc = \"gcc\"\n$             dest = \"''dest'G\"\n$             cmpl = \"GNU C\"\n$             opts = \"GNU_CC:[000000]GCCLIB.OLB /LIBRARY,\"\n$         else\n$             if (HAVE_DECC_VAX)\n$             then\n$                 cc = \"cc /vaxc\"\n$             else\n$                 cc = \"cc\"\n$             endif\n$             dest = \"''dest'V\"\n$             cmpl = \"VAX C\"\n$         endif\n$         opts = \"''opts' SYS$DISK:[.''dest']VAXCSHR.OPT /OPTIONS,\"\n$     endif\n$ endif\n$!\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     defs = \"USE_BZIP2, ''defs'\"\n$ endif\n$!\n$! Reveal the plan.  If compiling, set some compiler options.\n$!\n$ if (LINK_ONLY)\n$ then\n$     say \"Linking on ''arch' for ''cmpl'.\"\n$ else\n$     say \"Compiling on ''arch' using ''cmpl'.\"\n$!\n$     DEF_UNX = \"/define = (''defs')\"\n$     DEF_CLI = \"/define = (''defs', VMSCLI)\"\n$     DEF_SXUNX = \"/define = (''defs', SFX)\"\n$     DEF_SXCLI = \"/define = (''defs', VMSCLI, SFX)\"\n$ endif\n$!\n$! Search directory for BZIP2.\n$!\n$ if (BUILD_BZIP2)\n$ then\n$!    Our own BZIP2 directory.\n$     seek_bz = dest\n$ else\n$!    User-specified BZIP2 directory.\n$     seek_bz = arch\n$ endif\n$!\n$! Search directory for ZLIB.\n$!\n$ seek_zl = arch\n$!\n$! Change the destination directory, if the large-file option is enabled.\n$!\n$ if (LARGE_FILE .ne. 0)\n$ then\n$     dest = \"''dest'L\"\n$ endif\n$!\n$! If BZIP2 support was selected, find the header file and object\n$! library.  Complain if things fail.\n$!\n$ cc_incl = \"[]\"\n$ lib_bzip2_opts = \"\"\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     bz2_olb = \"LIBBZ2_NS.OLB\"\n$     if (.not. LINK_ONLY)\n$     then\n$         define incl_bzip2 'IZ_BZIP2'\n$         if (BUILD_BZIP2 .and. (IZ_BZIP2 .eqs. \"SYS$DISK:[.BZIP2]\"))\n$         then\n$             set def [.BZIP2]\n$             @buildbz2.com\n$             set def [-]\n$         endif\n$     endif\n$!\n$     @ [.VMS]FIND_BZIP2_LIB.COM 'IZ_BZIP2' 'seek_bz' 'bz2_olb' lib_bzip2\n$     if (f$trnlnm( \"lib_bzip2\") .eqs. \"\")\n$     then\n$         say \"Can't find BZIP2 object library.  Can't link.\"\n$         goto error\n$     else\n$         lib_bzip2_opts = \"lib_bzip2:''bz2_olb' /library,\"\n$         cc_incl = cc_incl+ \", [.VMS]\"\n$     endif\n$ endif\n$!\n$! If ZLIB use was selected, find the object library.\n$! Complain if things fail.\n$!\n$ lib_zlib_opts = \"\"\n$ if (IZ_ZLIB .nes. \"\")\n$ then\n$     zlib_olb = \"LIBZ.OLB\"\n$     define incl_zlib 'IZ_ZLIB'\n$     defs = \"''defs', USE_ZLIB\"\n$     @ [.VMS]FIND_BZIP2_LIB.COM 'IZ_ZLIB' 'seek_zl' 'zlib_olb' lib_zlib\n$     if (f$trnlnm( \"lib_zlib\") .eqs. \"\")\n$     then\n$         say \"Can't find ZLIB object library.  Can't link.\"\n$         goto error\n$     else\n$         lib_zlib_opts = \"lib_zlib:''zlib_olb' /library, \"\n$         if (f$locate( \"[.VMS]\", cc_incl) .ge. f$length( cc_incl))\n$         then\n$             cc_incl = cc_incl+ \", [.VMS]\"\n$         endif\n$         @ [.VMS]FIND_BZIP2_LIB.COM 'IZ_ZLIB' -\n           contrib.infback9 infback9.h'zlib_olb' incl_zlib_contrib_infback9\n$     endif\n$ endif\n$!\n$! If [.'dest'] does not exist, either complain (link-only) or make it.\n$!\n$ if (f$search( \"''dest'.dir;1\") .eqs. \"\")\n$ then\n$     if (LINK_ONLY)\n$     then\n$         say \"Can't find directory \"\"[.''dest']\"\".  Can't link.\"\n$         goto error\n$     else\n$         create /directory [.'dest']\n$     endif\n$ endif\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Arrange to get arch-specific list file placement, if listing, and if\n$! the user didn't specify a particular \"/LIST =\" destination.\n$!\n$     L = f$edit( LISTING, \"COLLAPSE\")\n$     if ((f$extract( 0, 5, L) .eqs. \"/LIST\") .and. -\n       (f$extract( 4, 1, L) .nes. \"=\"))\n$     then\n$         LISTING = \" /LIST = [.''dest']\"+ f$extract( 5, 1000, LISTING)\n$     endif\n$!\n$! Define compiler command.\n$!\n$     cc = cc+ \" /include = (''cc_incl')\"+ LISTING+ CCOPTS\n$!\n$ endif\n$!\n$! Define linker command.\n$!\n$ link = \"link ''LINKOPTS'\"\n$!\n$! Make a VAXCRTL options file for GNU C or VAC C, if needed.\n$!\n$ if ((opts .nes. \"\") .and. -\n   (f$locate( \"VAXCSHR\", f$edit( opts, \"UPCASE\")) .lt. f$length( opts)) .and. -\n   (f$search( \"[.''dest']VAXCSHR.OPT\") .eqs. \"\"))\n$ then\n$     open /write opt_file_ln [.'dest']VAXCSHR.OPT\n$     write opt_file_ln \"SYS$SHARE:VAXCRTL.EXE /SHARE\"\n$     close opt_file_ln\n$ endif\n$!\n$! Show interesting facts.\n$!\n$ say \"   architecture = ''arch' (destination = [.''dest'])\"\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     if (.not. LINK_ONLY)\n$     then\n$         say \"   BZIP2 include dir: ''f$trnlnm( \"incl_bzip2\")'\"\n$     endif\n$     say \"   BZIP2 library dir: ''f$trnlnm( \"lib_bzip2\")'\"\n$ endif\n$ if (IZ_ZLIB .nes. \"\")\n$ then\n$     if (.not. LINK_ONLY)\n$     then\n$         say \"   ZLIB include dir:  ''f$trnlnm( \"incl_zlib\")'\"\n$     endif\n$     say \"   ZLIB library dir:  ''f$trnlnm( \"lib_zlib\")'\"\n$ endif\n$ if (.not. LINK_ONLY)\n$ then\n$     say \"   cc = ''cc'\"\n$ endif\n$ say \"   link = ''link'\"\n$ if (.not. MAKE_HELP)\n$ then\n$     say \"   Not making new help files.\"\n$ endif\n$ if (.not. MAKE_MSG)\n$ then\n$     say \"   Not making new message files.\"\n$ endif\n$ say \"\"\n$!\n$ tmp = f$verify( 1)    ! Turn echo on to see what's happening.\n$!\n$!------------------------------- UnZip section ------------------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Process the help file, if desired.\n$!\n$     if (MAKE_HELP)\n$     then\n$         runoff /out = UNZIP.HLP [.VMS]UNZIP_DEF.RNH\n$     endif\n$!\n$! Process the message file, if desired.\n$!\n$     if (MAKE_MSG)\n$     then\n$         message /object = [.'dest']UNZIP_MSG.OBJ /nosymbols -\n           [.VMS]UNZIP_MSG.MSG\n$         link /shareable = [.'dest']UNZIP_MSG.EXE [.'dest']UNZIP_MSG.OBJ\n$     endif\n$!\n$! Compile the sources.\n$!\n$     cc 'DEF_UNX' /object = [.'dest']UNZIP.OBJ UNZIP.C\n$     cc 'DEF_UNX' /object = [.'dest']CRC32.OBJ CRC32.C\n$     cc 'DEF_UNX' /object = [.'dest']CRYPT.OBJ CRYPT.C\n$     cc 'DEF_UNX' /object = [.'dest']ENVARGS.OBJ ENVARGS.C\n$     cc 'DEF_UNX' /object = [.'dest']EXPLODE.OBJ EXPLODE.C\n$     cc 'DEF_UNX' /object = [.'dest']EXTRACT.OBJ EXTRACT.C\n$     cc 'DEF_UNX' /object = [.'dest']FILEIO.OBJ FILEIO.C\n$     cc 'DEF_UNX' /object = [.'dest']GLOBALS.OBJ GLOBALS.C\n$     cc 'DEF_UNX' /object = [.'dest']INFLATE.OBJ INFLATE.C\n$     cc 'DEF_UNX' /object = [.'dest']LIST.OBJ LIST.C\n$     cc 'DEF_UNX' /object = [.'dest']MATCH.OBJ MATCH.C\n$     cc 'DEF_UNX' /object = [.'dest']PROCESS.OBJ PROCESS.C\n$     cc 'DEF_UNX' /object = [.'dest']TTYIO.OBJ TTYIO.C\n$     cc 'DEF_UNX' /object = [.'dest']UBZ2ERR.OBJ UBZ2ERR.C\n$     cc 'DEF_UNX' /object = [.'dest']UNREDUCE.OBJ UNREDUCE.C\n$     cc 'DEF_UNX' /object = [.'dest']UNSHRINK.OBJ UNSHRINK.C\n$     cc 'DEF_UNX' /object = [.'dest']ZIPINFO.OBJ ZIPINFO.C\n$     cc 'DEF_UNX' /object = [.'dest']VMS.OBJ [.VMS]VMS.C\n$!\n$! Create the object library.\n$!\n$     if (f$search( \"[.''dest']UNZIP.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']UNZIP.OLB\n$!\n$     libr /object /replace [.'dest']UNZIP.OLB -\n       [.'dest']CRC32.OBJ, -\n       [.'dest']CRYPT.OBJ, -\n       [.'dest']ENVARGS.OBJ, -\n       [.'dest']EXPLODE.OBJ, -\n       [.'dest']EXTRACT.OBJ, -\n       [.'dest']FILEIO.OBJ, -\n       [.'dest']GLOBALS.OBJ, -\n       [.'dest']INFLATE.OBJ, -\n       [.'dest']LIST.OBJ, -\n       [.'dest']MATCH.OBJ, -\n       [.'dest']PROCESS.OBJ, -\n       [.'dest']TTYIO.OBJ, -\n       [.'dest']UBZ2ERR.OBJ, -\n       [.'dest']UNREDUCE.OBJ, -\n       [.'dest']UNSHRINK.OBJ, -\n       [.'dest']ZIPINFO.OBJ, -\n       [.'dest']VMS.OBJ\n$!\n$ endif\n$!\n$! Link the executable.\n$!\n$ link /executable = [.'dest']'unzx_unx'.EXE -\n   SYS$DISK:[.'dest']UNZIP.OBJ, -\n   SYS$DISK:[.'dest']UNZIP.OLB /library, -\n   'lib_bzip2_opts' -\n   SYS$DISK:[.'dest']UNZIP.OLB /library, -\n   'lib_zlib_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]UNZIP.OPT /options\n$!\n$!----------------------- UnZip (CLI interface) section ----------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Process the CLI help file, if desired.\n$!\n$     if (MAKE_HELP)\n$     then\n$         set default [.VMS]\n$         edit /tpu /nosection /nodisplay /command = CVTHELP.TPU -\n           UNZIP_CLI.HELP\n$         set default [-]\n$         runoff /output = UNZIP_CLI.HLP [.VMS]UNZIP_CLI.RNH\n$     endif\n$!\n$! Compile the CLI sources.\n$!\n$     cc 'DEF_CLI' /object = [.'dest']UNZIPCLI.OBJ UNZIP.C\n$     cc 'DEF_CLI' /object = [.'dest']CMDLINE.OBJ -\n       [.VMS]CMDLINE.C\n$!\n$! Create the command definition object file.\n$!\n$     set command /object = [.'dest']UNZ_CLI.OBJ [.VMS]UNZ_CLI.CLD\n$!\n$! Create the CLI object library.\n$!\n$     if (f$search( \"[.''dest']UNZIPCLI.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']UNZIPCLI.OLB\n$!\n$     libr /object /replace [.'dest']UNZIPCLI.OLB -\n       [.'dest']CMDLINE.OBJ, -\n       [.'dest']UNZ_CLI.OBJ\n$!\n$ endif\n$!\n$! Link the CLI executable.\n$!\n$ link /executable = [.'dest']'unzx_cli'.EXE -\n   SYS$DISK:[.'dest']UNZIPCLI.OBJ, -\n   SYS$DISK:[.'dest']UNZIPCLI.OLB /library, -\n   SYS$DISK:[.'dest']UNZIP.OLB /library, -\n   'lib_bzip2_opts' -\n   SYS$DISK:[.'dest']UNZIP.OLB /library, -\n   'lib_zlib_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]UNZIP.OPT /options\n$!\n$!-------------------------- UnZipSFX section --------------------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Compile the variant SFX sources.\n$!\n$     cc 'DEF_SXUNX' /object = [.'dest']UNZIPSFX.OBJ UNZIP.C\n$     cc 'DEF_SXUNX' /object = [.'dest']CRC32_.OBJ CRC32.C\n$     cc 'DEF_SXUNX' /object = [.'dest']CRYPT_.OBJ CRYPT.C\n$     cc 'DEF_SXUNX' /object = [.'dest']EXTRACT_.OBJ EXTRACT.C\n$     cc 'DEF_SXUNX' /object = [.'dest']FILEIO_.OBJ FILEIO.C\n$     cc 'DEF_SXUNX' /object = [.'dest']GLOBALS_.OBJ GLOBALS.C\n$     cc 'DEF_SXUNX' /object = [.'dest']INFLATE_.OBJ INFLATE.C\n$     cc 'DEF_SXUNX' /object = [.'dest']MATCH_.OBJ MATCH.C\n$     cc 'DEF_SXUNX' /object = [.'dest']PROCESS_.OBJ PROCESS.C\n$     cc 'DEF_SXUNX' /object = [.'dest']TTYIO_.OBJ TTYIO.C\n$     cc 'DEF_SXUNX' /object = [.'dest']UBZ2ERR_.OBJ UBZ2ERR.C\n$     cc 'DEF_SXUNX' /object = [.'dest']VMS_.OBJ [.VMS]VMS.C\n$!\n$! Create the SFX object library.\n$!\n$     if (f$search( \"[.''dest']UNZIPSFX.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']UNZIPSFX.OLB\n$!\n$     libr /object /replace [.'dest']UNZIPSFX.OLB -\n       [.'dest']CRC32_.OBJ, -\n       [.'dest']CRYPT_.OBJ, -\n       [.'dest']EXTRACT_.OBJ, -\n       [.'dest']FILEIO_.OBJ, -\n       [.'dest']GLOBALS_.OBJ, -\n       [.'dest']INFLATE_.OBJ, -\n       [.'dest']MATCH_.OBJ, -\n       [.'dest']PROCESS_.OBJ, -\n       [.'dest']TTYIO_.OBJ, -\n       [.'dest']UBZ2ERR_.OBJ, -\n       [.'dest']VMS_.OBJ\n$!\n$ endif\n$!\n$! Link the SFX executable.\n$!\n$ link /executable = [.'dest']'unzsfx_unx'.EXE -\n   SYS$DISK:[.'dest']UNZIPSFX.OBJ, -\n   SYS$DISK:[.'dest']UNZIPSFX.OLB /library, -\n   'lib_bzip2_opts' -\n   SYS$DISK:[.'dest']UNZIPSFX.OLB /library, -\n   'lib_zlib_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]UNZIPSFX.OPT /options\n$!\n$!--------------------- UnZipSFX (CLI interface) section ---------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Compile the SFX CLI sources.\n$!\n$     cc 'DEF_SXCLI' /object = [.'dest']UNZSXCLI.OBJ UNZIP.C\n$     cc 'DEF_SXCLI' /object = [.'dest']CMDLINE_.OBJ -\n       [.VMS]CMDLINE.C\n$!\n$! Create the SFX CLI object library.\n$!\n$     if (f$search( \"[.''dest']UNZSXCLI.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']UNZSXCLI.OLB\n$!\n$     libr /object /replace [.'dest']UNZSXCLI.OLB -\n       [.'dest']CMDLINE_.OBJ, -\n       [.'dest']UNZ_CLI.OBJ\n$!\n$ endif\n$!\n$! Link the SFX CLI executable.\n$!\n$ link /executable = [.'dest']'unzsfx_cli'.EXE -\n   SYS$DISK:[.'dest']UNZSXCLI.OBJ, -\n   SYS$DISK:[.'dest']UNZSXCLI.OLB /library, -\n   SYS$DISK:[.'dest']UNZIPSFX.OLB /library, -\n   'lib_bzip2_opts' -\n   SYS$DISK:[.'dest']UNZIPSFX.OLB /library, -\n   'lib_zlib_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]UNZIPSFX.OPT /options\n$!\n$!----------------------------- Symbols section ------------------------------\n$!\n$ there = here- \"]\"+ \".''dest']\"\n$!\n$! Define the foreign command symbols.  Similar commands may be useful\n$! in SYS$MANAGER:SYLOGIN.COM and/or users' LOGIN.COM.\n$!\n$ unzip   == \"$''there'''unzexec'.EXE\"\n$ zipinfo == \"$''there'''unzexec'.EXE \"\"-Z\"\"\"\n$!\n$! Deassign the temporary process logical names, restore the original\n$! default directory, and restore the DCL verify status.\n$!\n$ error:\n$!\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     if (f$trnlnm( \"incl_bzip2\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign incl_bzip2\n$     endif\n$     if (f$trnlnm( \"lib_bzip2\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign lib_bzip2\n$     endif\n$ endif\n$!\n$ if (IZ_ZLIB .nes. \"\")\n$ then\n$     if (f$trnlnm( \"incl_zlib\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign incl_zlib\n$     endif\n$     if (f$trnlnm( \"incl_zlib_contrib_infback9\", -\n       \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign incl_zlib_contrib_infback9\n$     endif\n$     if (f$trnlnm( \"lib_zlib\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign lib_zlib\n$     endif\n$ endif\n$!\n$ if (f$type( here) .nes. \"\")\n$ then\n$     if (here .nes. \"\")\n$     then\n$         set default 'here'\n$     endif\n$ endif\n$!\n$ if (f$type( OLD_VERIFY) .nes. \"\")\n$ then\n$     tmp = f$verify( OLD_VERIFY)\n$ endif\n$!\n$ exit\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/bzlib.h",
    "content": "/* 2007-01-02 SMS.\n * VMS-specific BZLIB.H jacket header file to ensure compatibility with\n * BZIP2 code compiled using /NAMES = AS_IS.\n *\n * The logical name INCL_BZIP2 must point to the BZIP2 source directory.\n *\n * A \"names as_is\" prototype for bz_internal_error() is included for the\n * same reason.  See bzip2 \"bzlib_private.h\".  Note that this \"names\n * as_is\" prototype must be the first to be read by the compiler, but\n * one or more other prototypes (perhaps with the default \"names\"\n * attributes) should cause no trouble.\n */\n\n#pragma names save\n#pragma names as_is\n\n#include \"INCL_BZIP2:BZLIB.H\"\n\nextern void bz_internal_error ( int bzerrcode );\n\n#pragma names restore\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/cmdline.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n#define module_name VMS_UNZIP_CMDLINE\n#define module_ident \"02-013\"\n#endif /* 0 */\n\n/*\n**\n**  Facility:   UNZIP\n**\n**  Module:     VMS_UNZIP_CMDLINE\n**\n**  Author:     Hunter Goatley <goathunter@MadGoat.com>\n**\n**  Date:       25 Apr 97 (orig. Zip version, 30 Jul 93)\n**\n**  Abstract:   Routines to handle a VMS CLI interface for UnZip.  The CLI\n**              command line is parsed and a new argc/argv are built and\n**              returned to UnZip.\n**\n**  Modified by:\n**\n**      02-013          S. Schweda, C. Spieler  29-Dec-2007 03:34\n**              Extended /RESTORE qualifier to support timestamp restoration\n**              options.\n**      02-012          Steven Schweda          07-Jul-2006 19:04\n**              Added /TEXT=STMLF qualifier option.\n**      02-011          Christian Spieler       21-Apr-2005 01:23\n**              Added /FULL=DIAGNOSTICS option modifier.\n**      02-010          Steven Schweda          14-FEB-2005 20:04\n**              Added /DOT_VERSION (-Y) and /ODS2 (-2) qualifiers.\n**      02-009          Steven Schweda          28-JAN-2005 16:16\n**              Added /TIMESTAMP (-T) qualifier.\n**      02-008          Christian Spieler       08-DEC-2001 23:44\n**              Added support for /TRAVERSE_DIRS argument\n**      02-007          Christian Spieler       24-SEP-2001 21:12\n**              Escape verbatim '%' chars in format strings; version unchanged.\n**      02-007          Onno van der Linden     02-Jul-1998 19:07\n**              Modified to support GNU CC 2.8 on Alpha; version unchanged.\n**      02-007          Johnny Lee              25-Jun-1998 07:38\n**              Fixed typo (superfluous ';'); no version num change.\n**      02-007          Hunter Goatley          11-NOV-1997 10:38\n**              Fixed \"zip\" vs. \"unzip\" typo; no version num change.\n**      02-007          Christian Spieler       14-SEP-1997 22:43\n**              Cosmetic mods to stay in sync with Zip; no version num change.\n**      02-007          Christian Spieler       12-JUL-1997 02:05\n**              Revised argv vector construction for better handling of quoted\n**              arguments (e.g.: embedded white space); no version num change.\n**      02-007          Christian Spieler       04-MAR-1997 22:25\n**              Made /CASE_INSENSITIVE common to UnZip and ZipInfo mode;\n**              added support for /PASSWORD=\"decryption_key\" argument.\n**      02-006          Christian Spieler       11-MAY-1996 22:40\n**              Added SFX version of VMSCLI_usage().\n**      02-005          Patrick Ellis           09-MAY-1996 22:25\n**              Show UNIX style usage screen when UNIX style options are used.\n**      02-004          Christian Spieler       06-FEB-1996 02:20\n**              Added /HELP qualifier.\n**      02-003          Christian Spieler       23-DEC-1995 17:20\n**              Adapted to UnZip 5.2.\n**      02-002          Hunter Goatley          16-JUL-1994 10:20\n**              Fixed some typos.\n**      02-001          Cave Newt               14-JUL-1994 15:18\n**              Removed obsolete /EXTRACT option; fixed /*TEXT options;\n**              wrote VMSCLI usage() function\n**      02-000          Hunter Goatley          12-JUL-1994 00:00\n**              Original UnZip version (v5.11).\n**      01-000          Hunter Goatley          30-JUL-1993 07:54\n**              Original version (for Zip v1.9p1).\n**\n*/\n\n/*    Stand-alone test procedure:\n *\n * cc /define = TEST=1 [.vms]cmdline.c /include = [] /object = [.vms]\n * set command /object = [.vms]unz_cli.obj [.vms]unz_cli.cld\n * link /executable = [] [.vms]cmdline.obj, [.vms]unz_cli.obj\n * EXEC*UTE == \"$SYS$DISK:[]'\"\n * exec cmdline [ /qualifiers ...] [parameters ...]\n */\n\n\f\n\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n#if defined(__DECC) || defined(__GNUC__)\n#pragma module module_name module_ident\n#else\n#module module_name module_ident\n#endif\n#endif /* 0 */\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#ifndef TEST\n#  include \"unzvers.h\"  /* for VMSCLI_usage() */\n#endif /* !TEST */\n\n/* Workaround for broken header files of older DECC distributions\n * that are incompatible with the /NAMES=AS_IS qualifier. */\n/* - lib$routines.h definitions: */\n#define lib$establish LIB$ESTABLISH\n#define lib$get_foreign LIB$GET_FOREIGN\n#define lib$get_input LIB$GET_INPUT\n#define lib$sig_to_ret LIB$SIG_TO_RET\n/* - str$routines.h definitions: */\n#define str$concat STR$CONCAT\n#define str$find_first_substring STR$FIND_FIRST_SUBSTRING\n\n#include <ssdef.h>\n#include <descrip.h>\n#include <climsgdef.h>\n#include <clidef.h>\n#include <lib$routines.h>\n#include <str$routines.h>\n\n#ifndef CLI$_COMMA\nglobalvalue CLI$_COMMA;\n#endif\n\n/*\n**  \"Macro\" to initialize a dynamic string descriptor.\n*/\n#define init_dyndesc(dsc) {\\\n        dsc.dsc$w_length = 0;\\\n        dsc.dsc$b_dtype = DSC$K_DTYPE_T;\\\n        dsc.dsc$b_class = DSC$K_CLASS_D;\\\n        dsc.dsc$a_pointer = NULL;}\n\n/*\n**  Memory allocation step for argv string buffer.\n*/\n#define ARGBSIZE_UNIT 256\n\n/*\n**  Memory reallocation macro for argv string buffer.\n*/\n#define CHECK_BUFFER_ALLOCATION(buf, reserved, requested) { \\\n    if ((requested) > (reserved)) { \\\n        char *save_buf = (buf); \\\n        (reserved) += ARGBSIZE_UNIT; \\\n        if (((buf) = (char *) realloc((buf), (reserved))) == NULL) { \\\n            if (save_buf != NULL) free(save_buf); \\\n            return (SS$_INSFMEM); \\\n        } \\\n    } \\\n}\n\n/*\n**  Define descriptors for all of the CLI parameters and qualifiers.\n*/\n#if 0\n$DESCRIPTOR(cli_extract,        \"EXTRACT\");             /* obsolete */\n#endif\n$DESCRIPTOR(cli_text,           \"TEXT\");                /* -a[a] */\n$DESCRIPTOR(cli_text_auto,      \"TEXT.AUTO\");           /* -a */\n$DESCRIPTOR(cli_text_all,       \"TEXT.ALL\");            /* -aa */\n$DESCRIPTOR(cli_text_none,      \"TEXT.NONE\");           /* ---a */\n$DESCRIPTOR(cli_text_stmlf,     \"TEXT.STMLF\");          /* -S */\n$DESCRIPTOR(cli_binary,         \"BINARY\");              /* -b[b] */\n$DESCRIPTOR(cli_binary_auto,    \"BINARY.AUTO\");         /* -b */\n$DESCRIPTOR(cli_binary_all,     \"BINARY.ALL\");          /* -bb */\n$DESCRIPTOR(cli_binary_none,    \"BINARY.NONE\");         /* ---b */\n$DESCRIPTOR(cli_case_insensitive,\"CASE_INSENSITIVE\");   /* -C */\n$DESCRIPTOR(cli_screen,         \"SCREEN\");              /* -c */\n$DESCRIPTOR(cli_directory,      \"DIRECTORY\");           /* -d */\n$DESCRIPTOR(cli_freshen,        \"FRESHEN\");             /* -f */\n$DESCRIPTOR(cli_help,           \"HELP\");                /* -h */\n$DESCRIPTOR(cli_junk,           \"JUNK\");                /* -j */\n$DESCRIPTOR(cli_lowercase,      \"LOWERCASE\");           /* -L */\n$DESCRIPTOR(cli_list,           \"LIST\");                /* -l */\n$DESCRIPTOR(cli_brief,          \"BRIEF\");               /* -l */\n$DESCRIPTOR(cli_full,           \"FULL\");                /* -v */\n$DESCRIPTOR(cli_full_diags,     \"FULL.DIAGNOSTICS\");    /* -vv */\n$DESCRIPTOR(cli_existing,       \"EXISTING\");            /* -o, -oo, -n */\n$DESCRIPTOR(cli_exist_newver,   \"EXISTING.NEW_VERSION\"); /* -o */\n$DESCRIPTOR(cli_exist_over,     \"EXISTING.OVERWRITE\");  /* -oo */\n$DESCRIPTOR(cli_exist_noext,    \"EXISTING.NOEXTRACT\");  /* -n */\n$DESCRIPTOR(cli_overwrite,      \"OVERWRITE\");           /* -o, -n */\n$DESCRIPTOR(cli_quiet,          \"QUIET\");               /* -q */\n$DESCRIPTOR(cli_super_quiet,    \"QUIET.SUPER\");         /* -qq */\n$DESCRIPTOR(cli_test,           \"TEST\");                /* -t */\n$DESCRIPTOR(cli_pipe,           \"PIPE\");                /* -p */\n$DESCRIPTOR(cli_password,       \"PASSWORD\");            /* -P */\n$DESCRIPTOR(cli_timestamp,      \"TIMESTAMP\");           /* -T */\n$DESCRIPTOR(cli_uppercase,      \"UPPERCASE\");           /* -U */\n$DESCRIPTOR(cli_update,         \"UPDATE\");              /* -u */\n$DESCRIPTOR(cli_version,        \"VERSION\");             /* -V */\n$DESCRIPTOR(cli_restore,        \"RESTORE\");             /* -X */\n$DESCRIPTOR(cli_restore_own,    \"RESTORE.OWNER_PROT\");  /* -X */\n$DESCRIPTOR(cli_restore_date,   \"RESTORE.DATE\");        /* -DD */\n$DESCRIPTOR(cli_restore_date_all, \"RESTORE.DATE.ALL\");  /* --D */\n$DESCRIPTOR(cli_restore_date_files, \"RESTORE.DATE.FILES\"); /* -D */\n$DESCRIPTOR(cli_dot_version,    \"DOT_VERSION\");         /* -Y */\n$DESCRIPTOR(cli_comment,        \"COMMENT\");             /* -z */\n$DESCRIPTOR(cli_exclude,        \"EXCLUDE\");             /* -x */\n$DESCRIPTOR(cli_ods2,           \"ODS2\");                /* -2 */\n$DESCRIPTOR(cli_traverse,       \"TRAVERSE_DIRS\");       /* -: */\n\n$DESCRIPTOR(cli_information,    \"ZIPINFO\");             /* -Z */\n$DESCRIPTOR(cli_short,          \"SHORT\");               /* -Zs */\n$DESCRIPTOR(cli_medium,         \"MEDIUM\");              /* -Zm */\n$DESCRIPTOR(cli_long,           \"LONG\");                /* -Zl */\n$DESCRIPTOR(cli_verbose,        \"VERBOSE\");             /* -Zv */\n$DESCRIPTOR(cli_header,         \"HEADER\");              /* -Zh */\n$DESCRIPTOR(cli_totals,         \"TOTALS\");              /* -Zt */\n$DESCRIPTOR(cli_times,          \"TIMES\");               /* -ZT */\n$DESCRIPTOR(cli_one_line,       \"ONE_LINE\");            /* -Z2 */\n\n$DESCRIPTOR(cli_page,           \"PAGE\");                /* -M , -ZM */\n\n$DESCRIPTOR(cli_yyz,            \"YYZ_UNZIP\");\n\n$DESCRIPTOR(cli_zipfile,        \"ZIPFILE\");\n$DESCRIPTOR(cli_infile,         \"INFILE\");\n$DESCRIPTOR(unzip_command,      \"unzip \");\n\nstatic int show_VMSCLI_usage;\n\n#ifndef vms_unzip_cld\n#  define vms_unzip_cld VMS_UNZIP_CLD\n#endif\n#if defined(__DECC) || defined(__GNUC__)\nextern void *vms_unzip_cld;\n#else\nglobalref void *vms_unzip_cld;\n#endif\n\n/* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */\n\n#ifndef cli$dcl_parse\n#  define cli$dcl_parse CLI$DCL_PARSE\n#endif\n#ifndef cli$present\n#  define cli$present CLI$PRESENT\n#endif\n#ifndef cli$get_value\n#  define cli$get_value CLI$GET_VALUE\n#endif\nextern unsigned long cli$dcl_parse ();\nextern unsigned long cli$present ();\nextern unsigned long cli$get_value ();\n\nunsigned long vms_unzip_cmdline (int *, char ***);\nstatic unsigned long get_list (struct dsc$descriptor_s *,\n                               struct dsc$descriptor_d *, int,\n                               char **, unsigned long *, unsigned long *);\nstatic unsigned long check_cli (struct dsc$descriptor_s *);\n\n\f\n#ifdef TEST\nint\nmain(int argc, char **argv)\n{\n    return (vms_unzip_cmdline(&argc, &argv));\n}\n#endif /* TEST */\n\n\f\nunsigned long\nvms_unzip_cmdline (int *argc_p, char ***argv_p)\n{\n/*\n**  Routine:    vms_unzip_cmdline\n**\n**  Function:\n**\n**      Parse the DCL command line and create a fake argv array to be\n**      handed off to Zip.\n**\n**      NOTE: the argv[] is built as we go, so all the parameters are\n**      checked in the appropriate order!!\n**\n**  Formal parameters:\n**\n**      argc_p          - Address of int to receive the new argc\n**      argv_p          - Address of char ** to receive the argv address\n**\n**  Calling sequence:\n**\n**      status = vms_unzip_cmdline (&argc, &argv);\n**\n**  Returns:\n**\n**      SS$_NORMAL      - Success.\n**      SS$_INSFMEM     - A malloc() or realloc() failed\n**      SS$_ABORT       - Bad time value\n**\n*/\n    register unsigned long status;\n    char options[256];\n    char *the_cmd_line;                 /* buffer for argv strings */\n    unsigned long cmdl_size;            /* allocated size of buffer */\n    unsigned long cmdl_len;             /* used size of buffer */\n    char *ptr;\n    int  x, len, zipinfo, exclude_list;\n    int restore_date;\n\n    int new_argc;\n    char **new_argv;\n\n    struct dsc$descriptor_d work_str;\n    struct dsc$descriptor_d foreign_cmdline;\n    struct dsc$descriptor_d output_directory;\n    struct dsc$descriptor_d password_arg;\n\n    init_dyndesc(work_str);\n    init_dyndesc(foreign_cmdline);\n    init_dyndesc(output_directory);\n    init_dyndesc(password_arg);\n\n    /*\n    **  See if the program was invoked by the CLI (SET COMMAND) or by\n    **  a foreign command definition.  Check for /YYZ_UNZIP, which is a\n    **  valid default qualifier solely for this test.\n    */\n    show_VMSCLI_usage = TRUE;\n    status = check_cli(&cli_yyz);\n    if (!(status & 1)) {\n        lib$get_foreign(&foreign_cmdline);\n        /*\n        **  If nothing was returned or the first character is a \"-\", then\n        **  assume it's a UNIX-style command and return.\n        */\n        if (foreign_cmdline.dsc$w_length == 0)\n            return (SS$_NORMAL);\n        if ((*(foreign_cmdline.dsc$a_pointer) == '-') ||\n            ((foreign_cmdline.dsc$w_length > 1) &&\n             (*(foreign_cmdline.dsc$a_pointer) == '\"') &&\n             (*(foreign_cmdline.dsc$a_pointer + 1) == '-'))) {\n            show_VMSCLI_usage = FALSE;\n            return (SS$_NORMAL);\n        }\n\n        str$concat(&work_str, &unzip_command, &foreign_cmdline);\n        status = cli$dcl_parse(&work_str, &vms_unzip_cld, lib$get_input,\n                        lib$get_input, 0);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  There's always going to be a new_argv[] because of the image name.\n    */\n    if ((the_cmd_line = (char *) malloc(cmdl_size = ARGBSIZE_UNIT)) == NULL)\n        return (SS$_INSFMEM);\n\n    strcpy(the_cmd_line, \"unzip\");\n    cmdl_len = sizeof(\"unzip\");\n\n    /*\n    **  First, check to see if any of the regular options were specified.\n    */\n\n    options[0] = '-';\n    ptr = &options[1];          /* Point to temporary buffer */\n\n    /*\n    **  Is it ZipInfo??\n    */\n    zipinfo = 0;\n    status = cli$present(&cli_information);\n    if (status & 1) {\n\n        zipinfo = 1;\n\n        *ptr++ = 'Z';\n\n        if (cli$present(&cli_one_line) & 1)\n            *ptr++ = '2';\n        if (cli$present(&cli_short) & 1)\n            *ptr++ = 's';\n        if (cli$present(&cli_medium) & 1)\n            *ptr++ = 'm';\n        if (cli$present(&cli_long) & 1)\n            *ptr++ = 'l';\n        if (cli$present(&cli_verbose) & 1)\n            *ptr++ = 'v';\n        if (cli$present(&cli_header) & 1)\n            *ptr++ = 'h';\n        if (cli$present(&cli_comment) & 1)\n            *ptr++ = 'c';\n        if (cli$present(&cli_totals) & 1)\n            *ptr++ = 't';\n        if (cli$present(&cli_times) & 1)\n            *ptr++ = 'T';\n\n    }\n    else {\n\n#if 0\n        /*\n        **  Extract files?\n        */\n        status = cli$present(&cli_extract);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'x';\n#endif\n\n        /*\n        **  Write binary files in VMS binary (fixed-length, 512-byte records,\n        **  record attributes: none) format\n        **  (auto-convert, or force to convert all files)\n        */\n        status = cli$present(&cli_binary);\n        if (status != CLI$_ABSENT) {\n            *ptr++ = '-';\n            *ptr++ = '-';\n            *ptr++ = 'b';\n            if ((status & 1) &&\n                !((status = cli$present(&cli_binary_none)) & 1)) {\n                *ptr++ = 'b';\n                if ((status = cli$present(&cli_binary_all)) & 1)\n                    *ptr++ = 'b';\n            }\n        }\n\n        /*\n        **  Convert files as text (CR LF -> LF, etc.)\n        **  (auto-convert, or force to convert all files)\n        */\n        status = cli$present(&cli_text);\n        if (status != CLI$_ABSENT) {\n            *ptr++ = '-';\n            *ptr++ = '-';\n            *ptr++ = 'a';\n            if ((status & 1) &&\n                !((status = cli$present(&cli_text_none)) & 1)) {\n                *ptr++ = 'a';\n                if ((status = cli$present(&cli_text_all)) & 1)\n                    *ptr++ = 'a';\n                if ((status = cli$present(&cli_text_stmlf)) & 1)\n                    *ptr++ = 'S';\n            }\n        }\n\n        /*\n        **  Extract files to screen?\n        */\n        status = cli$present(&cli_screen);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'c';\n\n        /*\n        **  Re-create directory structure?  (default)\n        */\n        status = cli$present(&cli_directory);\n        if (status == CLI$_PRESENT) {\n            status = cli$get_value(&cli_directory, &output_directory);\n        }\n\n        /*\n        **  Restore directory date-times.\n        */\n        restore_date = 0;\n        status = cli$present(&cli_restore_date);\n        if (status != CLI$_ABSENT) {\n            /* Emit \"----D\" to reset the timestamp restore state \"D_flag\"\n            ** consistently to 0 (independent of optional environment\n            ** option settings).\n            */\n            *ptr++ = '-';\n            *ptr++ = '-';\n            *ptr++ = '-';\n            *ptr++ = 'D';\n            if (status == CLI$_NEGATED) {\n                /* /RESTORE=NODATE */\n                restore_date = 2;\n            } else {\n                status = cli$present(&cli_restore_date_all);\n                if (status == CLI$_PRESENT) {\n                    /* /RESTORE=(DATE=ALL) */\n                    restore_date = 0;\n                } else {\n                    /* /RESTORE=(DATE=FILES) (default) */\n                    restore_date = 1;\n                }\n            }\n            /* Emit the required number of (positive) \"D\" characters. */\n            while (restore_date > 0) {\n                *ptr++ = 'D';\n                restore_date--;\n            }\n        }\n\n        /*\n        **  Freshen existing files, create none\n        */\n        status = cli$present(&cli_freshen);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'f';\n\n        /*\n        **  Show the help.\n        */\n        status = cli$present(&cli_help);\n        if (status & 1)\n            *ptr++ = 'h';\n\n        /*\n        **  Junk stored directory names on unzip\n        */\n        status = cli$present(&cli_junk);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'j';\n\n        /*\n        **  List contents (/BRIEF (default) or /FULL)\n        */\n        status = cli$present(&cli_list);\n        if (status & 1) {\n            if (cli$present(&cli_full) & 1) {\n               *ptr++ = 'v';\n               if (cli$present(&cli_full_diags) & 1)\n                   *ptr++ = 'v';\n            } else\n               *ptr++ = 'l';\n        }\n\n        /*\n        **  Existing files: new version, overwrite, no extract?\n        */\n        status = cli$present(&cli_exist_newver);\n        if (status == CLI$_PRESENT) {\n            *ptr++ = 'o';\n        }\n        status = cli$present(&cli_exist_over);\n        if (status == CLI$_PRESENT) {\n            *ptr++ = 'o';\n            *ptr++ = 'o';\n        }\n        status = cli$present(&cli_exist_noext);\n        if (status == CLI$_PRESENT) {\n            *ptr++ = 'n';\n        }\n\n        /*\n        **  Overwrite files (deprecated) ?\n        */\n        status = cli$present(&cli_overwrite);\n        if (status == CLI$_NEGATED)\n            *ptr++ = 'n';\n        else if (status != CLI$_ABSENT)\n            *ptr++ = 'o';\n\n        /*\n        **  Decryption password from command line?\n        */\n        status = cli$present(&cli_password);\n        if (status == CLI$_PRESENT) {\n            status = cli$get_value(&cli_password, &password_arg);\n        }\n\n        /*\n        **  Pipe files to SYS$OUTPUT with no informationals?\n        */\n        status = cli$present(&cli_pipe);\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'p';\n\n        /*\n        **  Quiet\n        */\n        status = cli$present(&cli_quiet);\n        if (status & 1) {\n            *ptr++ = 'q';\n            if ((status = cli$present(&cli_super_quiet)) & 1)\n                *ptr++ = 'q';\n        }\n\n        /*\n        **  Test archive integrity\n        */\n        status = cli$present(&cli_test);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 't';\n\n        /*\n        **  Set archive timestamp according to its newest file.\n        */\n        status = cli$present(&cli_timestamp);\n        if (status & 1)\n            *ptr++ = 'T';\n\n        /*\n        **  Extract \"foo.ext.###\" as \"foo.ext;###\" (treat .### as version number)\n        */\n        status = cli$present(&cli_dot_version);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'Y';\n\n        /*\n        **  Force conversion of extracted file names to old ODS2 conventions\n        */\n        status = cli$present(&cli_ods2);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = '2';\n\n        /*\n        **  Traverse directories (don't skip \"../\" path components)\n        */\n        status = cli$present(&cli_traverse);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = ':';\n\n        /*\n        **  Make (some) names lowercase\n        */\n        status = cli$present(&cli_lowercase);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'L';\n\n        /*\n        **  Uppercase (don't convert to lower)\n        */\n        status = cli$present(&cli_uppercase);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'U';\n\n        /*\n        **  Update (extract only new and newer files)\n        */\n        status = cli$present(&cli_update);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'u';\n\n        /*\n        **  Version (retain VMS/DEC-20 file versions)\n        */\n        status = cli$present(&cli_version);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'V';\n\n        /*\n        **  Restore owner/protection info\n        */\n        status = cli$present(&cli_restore_own);\n        if (status != CLI$_ABSENT) {\n            if (status == CLI$_NEGATED) {\n                *ptr++ = '-';\n            } else if ((status = cli$present(&cli_restore))\n                       == CLI$_NEGATED) {\n                *ptr++ = '-';\n            }\n            *ptr++ = 'X';\n        }\n\n        /*\n        **  Display only the archive comment\n        */\n        status = cli$present(&cli_comment);\n        if (status == CLI$_NEGATED)\n            *ptr++ = '-';\n        if (status != CLI$_ABSENT)\n            *ptr++ = 'z';\n\n    }   /* ZipInfo check way up there.... */\n\n    /* The following options are common to both UnZip and ZipInfo mode. */\n\n    /*\n    **  Match filenames case-insensitively (-C)\n    */\n    status = cli$present(&cli_case_insensitive);\n    if (status == CLI$_NEGATED)\n        *ptr++ = '-';\n    if (status != CLI$_ABSENT)\n        *ptr++ = 'C';\n\n    /*\n    **  Use builtin pager for all screen output\n    */\n    status = cli$present(&cli_page);\n    if (status == CLI$_NEGATED)\n        *ptr++ = '-';\n    if (status != CLI$_ABSENT)\n        *ptr++ = 'M';\n\n    /*\n    **  Check existence of a list of files to exclude, fetch is done later.\n    */\n    status = cli$present(&cli_exclude);\n    exclude_list = ((status & 1) != 0);\n\n    /*\n    **  If the user didn't give any DCL qualifier, assume he wants the\n    **  Un*x interface.\n    if ( (ptr == &options[1]) &&\n         (output_directory.dsc$w_length == 0) &&\n         (password_arg.dsc$w_length == 0) &&\n         (!exclude_list)  ) {\n        free(the_cmd_line);\n        return (SS$_NORMAL);\n    }\n    */\n\n    /*\n    **  Now copy the final options string to the_cmd_line.\n    */\n    len = ptr - &options[0];\n    if (len > 1) {\n        options[len] = '\\0';\n        x = cmdl_len;\n        cmdl_len += len + 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], options);\n    }\n\n    /*\n    **  If specified, add the decryption password argument.\n    **/\n    if (password_arg.dsc$w_length != 0) {\n        x = cmdl_len;\n        cmdl_len += password_arg.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-P\");\n        strncpy(&the_cmd_line[x+3], password_arg.dsc$a_pointer,\n                password_arg.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    /*\n    **  Now get the specified zip file name.\n    */\n    status = cli$present(&cli_zipfile);\n    if (status & 1) {\n        status = cli$get_value(&cli_zipfile, &work_str);\n\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n\n    }\n\n    /*\n    **  Get the output directory, for UnZip.\n    **/\n    if (output_directory.dsc$w_length != 0) {\n        x = cmdl_len;\n        cmdl_len += output_directory.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-d\");\n        strncpy(&the_cmd_line[x+3], output_directory.dsc$a_pointer,\n                output_directory.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    /*\n    **  Run through the list of files to unzip.\n    */\n    status = cli$present(&cli_infile);\n    if (status & 1) {\n        status = get_list(&cli_infile, &foreign_cmdline, '\\0',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  Get the list of files to exclude, if there are any.\n    */\n    if (exclude_list) {\n        x = cmdl_len;\n        cmdl_len += 3;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-x\");\n\n        status = get_list(&cli_exclude, &foreign_cmdline, '\\0',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  We have finished collecting the strings for the argv vector,\n    **  release unused space.\n    */\n    if ((the_cmd_line = (char *) realloc(the_cmd_line, cmdl_len)) == NULL)\n        return (SS$_INSFMEM);\n\n    /*\n    **  Now that we've built our new UNIX-like command line, count the\n    **  number of args and build an argv array.\n    */\n    for (new_argc = 0, x = 0; x < cmdl_len; x++)\n        if (the_cmd_line[x] == '\\0')\n            new_argc++;\n\n    /*\n    **  Allocate memory for the new argv[].  The last element of argv[]\n    **  is supposed to be NULL, so allocate enough for new_argc+1.\n    */\n    if ((new_argv = (char **) calloc(new_argc+1, sizeof(char *))) == NULL)\n        return (SS$_INSFMEM);\n\n    /*\n    **  For each option, store the address in new_argv[] and convert the\n    **  separating blanks to nulls so each argv[] string is terminated.\n    */\n    for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {\n        new_argv[x] = ptr;\n        ptr += strlen(ptr) + 1;\n    }\n    new_argv[new_argc] = NULL;\n\n#if defined(TEST) || defined(DEBUG)\n    printf(\"new_argc    = %d\\n\", new_argc);\n    for (x = 0; x < new_argc; x++)\n        printf(\"new_argv[%d] = %s\\n\", x, new_argv[x]);\n#endif /* TEST || DEBUG */\n\n    /*\n    **  All finished.  Return the new argc and argv[] addresses to Zip.\n    */\n    *argc_p = new_argc;\n    *argv_p = new_argv;\n\n    return (SS$_NORMAL);\n}\n\n\n\f\nstatic unsigned long\nget_list (struct dsc$descriptor_s *qual, struct dsc$descriptor_d *rawtail,\n          int delim, char **p_str, unsigned long *p_size, unsigned long *p_end)\n{\n/*\n**  Routine:    get_list\n**\n**  Function:   This routine runs through a comma-separated CLI list\n**              and copies the strings to the argv buffer.  The\n**              specified separation character is used to separate\n**              the strings in the argv buffer.\n**\n**              All unquoted strings are converted to lower-case.\n**\n**  Formal parameters:\n**\n**      qual    - Address of descriptor for the qualifier name\n**      rawtail - Address of descriptor for the full command line tail\n**      delim   - Character to use to separate the list items\n**      p_str   - Address of pointer pointing to output buffer (argv strings)\n**      p_size  - Address of number containing allocated size for output string\n**      p_end   - Address of number containing used length in output buf\n**\n*/\n\n    register unsigned long status;\n    struct dsc$descriptor_d work_str;\n\n    init_dyndesc(work_str);\n\n    status = cli$present(qual);\n    if (status & 1) {\n\n        unsigned long len, old_len;\n        long ind, sind;\n        int keep_case;\n        char *src, *dst; int x;\n\n        /*\n        **  Just in case the string doesn't exist yet, though it does.\n        */\n        if (*p_str == NULL) {\n            *p_size = ARGBSIZE_UNIT;\n            if ((*p_str = (char *) malloc(*p_size)) == NULL)\n                return (SS$_INSFMEM);\n            len = 0;\n        } else {\n            len = *p_end;\n        }\n\n        while ((status = cli$get_value(qual, &work_str)) & 1) {\n            old_len = len;\n            len += work_str.dsc$w_length + 1;\n            CHECK_BUFFER_ALLOCATION(*p_str, *p_size, len)\n\n            /*\n            **  Look for the filename in the original foreign command\n            **  line to see if it was originally quoted.  If so, then\n            **  don't convert it to lowercase.\n            */\n            keep_case = FALSE;\n            str$find_first_substring(rawtail, &ind, &sind, &work_str);\n            if ((ind > 1 && *(rawtail->dsc$a_pointer + ind - 2) == '\"') ||\n                (ind == 0))\n                keep_case = TRUE;\n\n            /*\n            **  Copy the string to the buffer, converting to lowercase.\n            */\n            src = work_str.dsc$a_pointer;\n            dst = *p_str+old_len;\n            for (x = 0; x < work_str.dsc$w_length; x++) {\n                if (!keep_case && ((*src >= 'A') && (*src <= 'Z')))\n                    *dst++ = *src++ + 32;\n                else\n                    *dst++ = *src++;\n            }\n            if (status == CLI$_COMMA)\n                (*p_str)[len-1] = (char)delim;\n            else\n                (*p_str)[len-1] = '\\0';\n        }\n        *p_end = len;\n    }\n\n    return (SS$_NORMAL);\n\n}\n\n\f\nstatic unsigned long\ncheck_cli (struct dsc$descriptor_s *qual)\n{\n/*\n**  Routine:    check_cli\n**\n**  Function:   Check to see if a CLD was used to invoke the program.\n**\n**  Formal parameters:\n**\n**      qual    - Address of descriptor for qualifier name to check.\n**\n*/\n    lib$establish(lib$sig_to_ret);      /* Establish condition handler */\n    return (cli$present(qual));         /* Just see if something was given */\n}\n\n\f\n#ifndef TEST\n#ifdef SFX\n\n#ifdef SFX_EXDIR\n#  define SFXOPT_EXDIR \"\\n                   and /DIRECTORY=exdir-spec\"\n#else\n#  define SFXOPT_EXDIR \"\"\n#endif\n\n#ifdef MORE\n#  define SFXOPT1 \"/PAGE, \"\n#else\n#  define SFXOPT1 \"\"\n#endif\n\nint VMSCLI_usage(__GPRO__ int error)    /* returns PK-type error code */\n{\n    extern ZCONST char UnzipSFXBanner[];\n#ifdef BETA\n    extern ZCONST char BetaVersion[];\n#endif\n    int flag;\n\n    if (!show_VMSCLI_usage)\n       return usage(__G__ error);\n\n    flag = (error? 1 : 0);\n\n    Info(slide, flag, ((char *)slide, UnzipSFXBanner,\n      UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL, UZ_VERSION_DATE));\n    Info(slide, flag, ((char *)slide, \"\\\nValid main options are /TEST, /FRESHEN, /UPDATE, /PIPE, /SCREEN, /COMMENT%s.\\n\",\n      SFXOPT_EXDIR));\n    Info(slide, flag, ((char *)slide, \"\\\nModifying options are /TEXT, /BINARY, /JUNK, /EXISTING, /QUIET,\\n\\\n                      /CASE_INSENSITIVE, /LOWERCASE, %s/VERSION, /RESTORE.\\n\",\n      SFXOPT1));\n#ifdef BETA\n    Info(slide, flag, ((char *)slide, BetaVersion, \"\\n\", \"SFX\"));\n#endif\n\n    if (error)\n        return PK_PARAM;\n    else\n        return PK_COOL;     /* just wanted usage screen: no error */\n\n} /* end function VMSCLI_usage() */\n\n\n#else /* !SFX */\n\nint VMSCLI_usage(__GPRO__ int error)    /* returns PK-type error code */\n{\n    extern ZCONST char UnzipUsageLine1[];\n#ifdef BETA\n    extern ZCONST char BetaVersion[];\n#endif\n    int flag;\n\n    if (!show_VMSCLI_usage)\n       return usage(__G__ error);\n\n/*---------------------------------------------------------------------------\n    If user requested usage, send it to stdout; else send to stderr.\n  ---------------------------------------------------------------------------*/\n\n    flag = (error? 1 : 0);\n\n\n/*---------------------------------------------------------------------------\n    Print either ZipInfo usage or UnZip usage, depending on incantation.\n  ---------------------------------------------------------------------------*/\n\n    if (uO.zipinfo_mode) {\n\n#ifndef NO_ZIPINFO\n\n        Info(slide, flag, ((char *)slide, \"\\\nZipInfo %d.%d%d%s %s, by Newtware and the fine folks at Info-ZIP.\\n\\n\\\nList name, date/time, attribute, size, compression method, etc., about files\\n\\\nin list (excluding those in xlist) contained in the specified .zip archive(s).\\\n\\n\\\"file[.zip]\\\" may be a wildcard name containing * or %% (e.g., \\\"*font-%%\\\n.zip\\\").\\n\", ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          UZ_VERSION_DATE));\n\n        Info(slide, flag, ((char *)slide, \"\\\n   usage:  zipinfo file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\\n\\\n   or:  unzip /ZIPINFO file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options\\\n\\n\\nmain\\\n listing-format options:              /SHORT   short \\\"ls -l\\\" format (def.)\\n\\\n  /ONE_LINE  just filenames, one/line     /MEDIUM  medium Unix \\\"ls -l\\\" format\\n\\\n  /VERBOSE   verbose, multi-page format   /LONG    long Unix \\\"ls -l\\\" format\\n\\\n\"));\n\n        Info(slide, flag, ((char *)slide, \"\\\nmiscellaneous options:\\n  \\\n/HEADER   print header line       /TOTALS  totals for listed files or for all\\n\\\n  /COMMENT  print zipfile comment   /TIMES   times in sortable decimal format\\n\\\n  /[NO]CASE_INSENSITIVE  match filenames case-insensitively\\n\\\n  /[NO]PAGE page output through built-in \\\"more\\\"\\n\\\n  /EXCLUDE=(file-spec1,etc.)  exclude file-specs from listing\\n\"));\n\n        Info(slide, flag, ((char *)slide, \"\\n\\\nType unzip \\\"-Z\\\" for Unix style flags\\n\\\nRemember that non-lowercase filespecs must be\\\n quoted in VMS (e.g., \\\"Makefile\\\").\\n\"));\n\n#endif /* !NO_ZIPINFO */\n\n    } else {   /* UnZip mode */\n\n        Info(slide, flag, ((char *)slide, UnzipUsageLine1,\n          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,\n          UZ_VERSION_DATE));\n\n#ifdef BETA\n        Info(slide, flag, ((char *)slide, BetaVersion, \"\", \"\"));\n#endif\n\n        Info(slide, flag, ((char *)slide, \"\\\nUsage: unzip file[.zip] [list] [/EXCL=(xlist)] [/DIR=exdir] /options /modifiers\\\n\\n  Default action is to extract files in list, except those in xlist, to exdir\\\n;\\n  file[.zip] may be a wildcard.  %s\\n\\n\",\n#ifdef NO_ZIPINFO\n          \"(ZipInfo mode is disabled in this version.)\"\n#else\n          \"Type \\\"unzip /ZIPINFO\\\" for ZipInfo-mode usage.\"\n#endif\n          ));\n\n        Info(slide, flag, ((char *)slide, \"\\\nMajor options include (type unzip -h for Unix style flags):\\n\\\n   /[NO]TEST, /LIST, /[NO]SCREEN, /PIPE, /[NO]FRESHEN, /[NO]UPDATE,\\n\\\n   /[NO]COMMENT, /DIRECTORY=directory-spec, /EXCLUDE=(file-spec1,etc.)\\n\\n\\\nModifiers include:\\n\\\n   /BRIEF, /FULL, /[NO]TEXT[=NONE|AUTO|ALL], /[NO]BINARY[=NONE|AUTO|ALL],\\n\\\n   /EXISTING={NEW_VERSION|OVERWRITE|NOEXTRACT}, /[NO]JUNK, /QUIET,\\n\\\n   /QUIET[=SUPER], /[NO]PAGE, /[NO]CASE_INSENSITIVE, /[NO]LOWERCASE,\\n\\\n   /[NO]VERSION, /RESTORE[=([NO]OWNER_PROT[,NODATE|DATE={ALL|FILES}])]\\n\\n\"));\n\n        Info(slide, flag, ((char *)slide, \"\\\nExamples (see unzip.txt or \\\"HELP UNZIP\\\" for more info):\\n\\\n   unzip edit1 /EXCL=joe.jou /CASE_INSENSITIVE    => Extract all files except\\\n\\n\\\n      joe.jou (or JOE.JOU, or any combination of case) from zipfile edit1.zip.\\\n\\n  \\\n unzip zip201 \\\"Makefile.VMS\\\" vms/*.[ch]         => extract VMS Makefile and\\\n\\n\\\n      *.c and *.h files; must quote uppercase names if /CASE_INSENS not used.\\\n\\n\\\n   unzip foo /DIR=tmp:[.test] /JUNK /TEXT /EXIS=NEW  => extract all files to\\\n\\n\\\n      tmp. dir., flatten hierarchy, auto-conv. text files, create new versions.\\\n\\n\"));\n\n    } /* end if (zipinfo_mode) */\n\n    if (error)\n        return PK_PARAM;\n    else\n        return PK_COOL;     /* just wanted usage screen: no error */\n\n} /* end function VMSCLI_usage() */\n\n#endif /* ?SFX */\n#endif /* !TEST */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/collect_deps.com",
    "content": "$!                                              1 December 2006.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$!    For the product named by P1,\n$!    collect all source file dependencies specified by P3,\n$!    and add P4 prefix.\n$!    Convert absolute dependencies to relative from one level above P5.\n$!    P2 = output file specification.\n$!\n$! MMS /EXTENDED_SYNTAX can't easily pass a macro invocation for P4, so\n$! we remove any internal spaces which might have been added to prevent\n$! immediate evaluation of a macro invocation.\n$!\n$ prefix = f$edit( p4, \"COLLAPSE\")\n$!\n$ dev_lose = f$edit( f$parse( p5, , , \"DEVICE\", \"SYNTAX_ONLY\"), \"UPCASE\")\n$ dir_lose = f$edit( f$parse( p5, , , \"DIRECTORY\", \"SYNTAX_ONLY\"), \"UPCASE\")\n$ suffix = \".VMS]\"\n$ suffix_loc = f$locate( suffix, dir_lose)\n$ if (suffix_loc .lt f$length( dir_lose))\n$ then\n$    dev_dir_lose = dev_lose+ dir_lose- suffix\n$ else\n$    dev_dir_lose = dev_lose+ dir_lose- \"]\"\n$ endif\n$!\n$! For portability, make the output file record format Stream_LF.\n$!\n$ create /fdl = sys$input 'p2'\nRECORD\n        Carriage_Control carriage_return\n        Format stream_lf\n$!\n$ open /read /write /error = end_main deps_out 'p2'\n$ on error then goto loop_main_end\n$!\n$! Include proper-inclusion-check preface.\n$!\n$ incl_macro = \"INCL_\"+ f$parse( p2, , , \"NAME\", \"SYNTAX_ONLY\")\n$ write deps_out \"#\"\n$ write deps_out \"# ''p1' for VMS - MMS (or MMK) Source Dependency File.\"\n$ write deps_out \"#\"\n$ write deps_out \"\"\n$ write deps_out -\n   \"# This description file is included by other description files.  It is\"\n$ write deps_out -\n   \"# not intended to be used alone.  Verify proper inclusion.\"\n$ write deps_out \"\"\n$ write deps_out \".IFDEF ''incl_macro'\"\n$ write deps_out \".ELSE\"\n$ write deps_out -\n   \"$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\"\n$ write deps_out \".ENDIF\"\n$ write deps_out \"\"\n$!\n$! Actual dependencies from individual dependency files.\n$!\n$ loop_main_top:\n$    file = f$search( p3)\n$    if (file .eqs. \"\") then goto loop_main_end\n$!\n$    open /read /error = end_subs deps_in 'file'\n$    loop_subs_top:\n$       read /error = loop_subs_end deps_in line\n$       line_reduced = f$edit( line, \"COMPRESS, TRIM, UPCASE\")\n$       colon = f$locate( \" : \", line_reduced)\n$       d_d_l_loc = f$locate( dev_dir_lose, -\n         f$extract( (colon+ 3), 1000, line_reduced))\n$       if (d_d_l_loc .eq. 0)\n$       then\n$          front = f$extract( 0, (colon+ 3), line_reduced)\n$          back = f$extract( (colon+ 3+ f$length( dev_dir_lose)), -\n            1000, line_reduced)\n$          line = front+ \"[\"+ back\n$       endif\n$       write deps_out \"''prefix'\"+ \"''line'\"\n$    goto loop_subs_top\n$!\n$    loop_subs_end:\n$    close deps_in\n$!\n$ goto loop_main_top\n$!\n$ loop_main_end:\n$ close deps_out\n$!\n$ end_main:\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/cvthelp.tpu",
    "content": "!       TITLE   CVTHELP.TPU\n!       IDENT   01-001\n!\n!++\n! Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n!\n! See the accompanying file LICENSE, version 2000-Apr-09 or later\n! (the contents of which are also included in zip.h) for terms of use.\n! If, for some reason, all these files are missing, the Info-ZIP license\n! also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n!\n!++\n!\n!  Program:     CVTHELP.TPU\n!\n!  Author:      Hunter Goatley\n!\n!  Date:        January 12, 1992\n!\n!  Purpose:     Convert .HELP files to RUNOFF .RNH files.  Substitutes\n!               RUNOFF commands for tags imbedded in the .HELP file.\n!\n!  Calling sequence:\n!\n!       $ EDIT/TPU/NOJOURNAL/NODISPLAY/COMMAND=CVTHELP file.HELP\n!\n!  Modified by:\n!\n!       01-001          Hunter Goatley            7-FEB-2001 15:40\n!               Added <NEXT> for qualifier separators.\n!\n!       01-000          Hunter Goatley           12-JAN-1992 15:15\n!               Original version.\n!\n!--\nProcedure eve_convert_help\nLocal   temp\n        ,x\n        ;\n\n   qualifier_level := 0;\n   hg$substitute_topic(current_buffer, \"<MAIN>\", \".indent-3\", \"1\");\n   hg$substitute_topic(current_buffer, \"<QUALIFIER>\", \".sk;.indent-3\", \"\");\n   hg$substitute_topic(current_buffer, \"<TOPIC>\", \".indent-3\", \"2\");\n   hg$substitute_topic(current_buffer, \"<SUBTOPIC>\", \".indent-3\", \"3\");\n   hg$substitute_topic(current_buffer, \"<SUBSUBTOPIC>\", \".indent-3\", \"4\");\n   hg$substitute_comment(current_buffer,\"<QUALIFIERS>\",\".indent-3;2 Qualifiers\");\n   hg$substitute_comment(current_buffer,\"<PARAMETER>\",\".indent-2\");\n   hg$substitute_comment(current_buffer,\"<PTEXT>\",\".lm+3\");\n   hg$substitute_comment(current_buffer,\"<TXETP>\",\".lm-3\");\n   hg$substitute_comment(current_buffer,\"<ETEXT>\",\".lm+4\");\n   hg$substitute_comment(current_buffer,\"<TXETE>\",\".lm-4\");\n   hg$substitute_comment(current_buffer,\"<INIT>\",\".noflags;.lm3;.rm70\");\n   hg$substitute_comment(current_buffer,\"<LITERAL>\",\".lm+4;.literal\");\n   hg$substitute_comment(current_buffer,\"<LARETIL>\",\".end literal;.lm-4\");\n   hg$substitute_comment(current_buffer,\"<DOT1LIST>\",'.list 1,\"o\"');\n   hg$substitute_comment(current_buffer,\"<DOT0LIST>\",'.list 0,\"o\"');\n   hg$substitute_comment(current_buffer,\"<ENTRY>\",\".le\");\n   hg$substitute_comment(current_buffer,\"<TSIL>\",\".end list\");\n   hg$substitute_comment(current_buffer,\"<CENTER>\",\".center\");\n   hg$substitute_comment(current_buffer,\"<FORMAT>\",\".sk;.indent2\");\n   hg$substitute_comment(current_buffer,\"<NOTE>\",\".note\");\n   hg$substitute_comment(current_buffer,\"<ETON>\",\".end note\");\n   hg$substitute_comment(current_buffer, LINE_BEGIN & LINE_END,\".sk\");\n   hg$substitute_comment(current_buffer, LINE_BEGIN & \"|\", \"\");\n   hg$substitute_comment(current_buffer,\"<NEXT>\",\".br\");\n\nEndProcedure;           ! eve_convert_help\n\nProcedure hg$substitute_comment (the_buffer, target, new)\nLocal   temp\n        ,save_pos\n        ,x\n        ;\n  on_error;\n  endon_error;\n\n  save_pos := mark(none);\n  position(beginning_of(the_buffer));\n  loop\n        x := search(target, forward);\n        exitif x = 0;\n        position (x);\n        erase_character(length(x));\n        copy_text(new);\n  endloop;\n\n  position(save_pos);\n\nEndProcedure;           ! hg$substitute_comment\n\nProcedure hg$substitute_topic (the_buffer, target, new, level)\nLocal   temp\n        ,save_pos\n        ,x\n        ;\n  on_error;\n  endon_error;\n\n  save_pos := mark(none);\n  position(beginning_of(the_buffer));\n  loop\n        x := search(target, forward);\n        exitif x = 0;\n        position (x);\n        erase_character(length(x));\n        move_vertical(-1);\n        if (length(current_line) = 0)\n        then copy_text(\"|\");\n        endif;\n        move_vertical(1);\n        copy_text(\".!------------------------------------------------------\");\n        split_line;\n        copy_text(new);\n        move_horizontal(-current_offset);\n        move_vertical(1);\n        if level <> \"\" then\n                copy_text(level + \" \");\n!       else\n!           if qualifier_level = 0\n!           then\n!               copy_text(\"2 Qualifiers\");\n!               split_line; split_line;\n!               copy_text(new); split_line;\n!               qualifier_level := 1;\n!           endif;\n        endif;\n        move_horizontal(-current_offset);\n        move_vertical(1);\n        if length(current_line) = 0\n        then\n            if (target = \"<MAIN>\") OR (target = \"<TOPIC>\")\n                OR (target = \"<SUBTOPIC>\") or (target = \"<SUBSUBTOPIC>\")\n            then copy_text(\".br\");\n            else copy_text(\".sk\");\n            endif;\n        endif;\n  endloop;\n\n  position(save_pos);\n\nEndProcedure;           ! hg$substitute_topic\n\n!===============================================================================\nProcedure tpu$init_procedure\nLocal   temp\n        ,orig_filespec\n        ,f\n        ;\n\n   on_error\n   endon_error;\n\n !Prompt user for information\n\n  orig_filespec := get_info(command_line, \"file_name\");\n  if orig_filespec = \"\"\n  then\n        message(\"No .HELP file given\");\n        quit;\n  endif;\n  f := file_parse(orig_filespec, \".HELP\");              !Add .LIS ending\n\n    ! Create a buffer and window for editing\n\n  main_buf := create_buffer (\"MAIN\",f);\n  set (eob_text, main_buf, \"[End of buffer]\");\n\n  position (beginning_of(main_buf));\n\n  eve_convert_help;\n\n  f := file_parse(orig_filespec,\"\",\"\",NAME);\n\n  write_file (main_buf, f+\".RNH\");\n\n quit;\nEndProcedure;           !TPU$INIT_PROCEDURE\n\ntpu$init_procedure;\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/descrip.mms",
    "content": "#                                               1 March 2009.  SMS.\n#\n#    UnZip 6.0 for VMS - MMS (or MMK) Description File.\n#\n# Usage:\n#\n#    MMS /DESCRIP = [.VMS]DESCRIP.MMS [/MACRO = (<see_below>)] [target]\n#\n# Note that this description file must be used from the main\n# distribution directory, not from the [.VMS] subdirectory.\n#\n# Optional macros:\n#\n#    USEBZ2=1       Build with optional BZIP2 support.  This macro\n#                   is a shortcut for IZ_BZIP2=SYS$DISK:[.BZIP2].\n#                   Additionally, it forces invokation of the UnZip-supplied\n#                   bzip2 make script provided in [.bzip2]descrbz2.mms.\n#                   This results in a \"single-command\" build of UnZip with\n#                   bzip2 support directly from the sources.\n#\n#    IZ_BZIP2=dev:[dir]  Build with optional BZIP2 support.  The value\n#                        of the MMS macro, (\"dev:[dir]\", or a suitable\n#                   logical name) tells where to find \"bzlib.h\".  The\n#                   BZIP2 object library (LIBBZ2_NS.OLB) is expected to\n#                   be in a \"[.dest]\" directory under that one\n#                   (\"dev:[dir.ALPHAL]\", for example), or in that\n#                   directory itself.\n#                   By default, the SFX programs are built without BZIP2\n#                   support.  Add \"BZIP2_SFX=1\" to the LOCAL_UNZIP C\n#                   macros to enable it.  (See LOCAL_UNZIP, below.)\n#\n#    IZ_ZLIB=dev:[dir]  Use ZLIB compression library instead of internal\n#                       compression routines.  The value of the MMS\n#                   macro (\"dev:[dir]\", or a suitable logical name)\n#                   tells where to find \"zlib.h\".  The ZLIB object\n#                   library (LIBZ.OLB) is expected to be in a\n#                   \"[.dest]\" directory under that one\n#                   (\"dev:[dir.ALPHAL]\", for example), or in that\n#                   directory itself.\n#\n#    CCOPTS=xxx     Compile with CC options xxx.  For example:\n#                   CCOPTS=/ARCH=HOST\n#\n#    DBG=1          Compile with /DEBUG /NOOPTIMIZE.\n#                   Link with /DEBUG /TRACEBACK.\n#                   (Default is /NOTRACEBACK.)\n#\n#    LARGE=1        Enable large-file (>2GB) support.  Non-VAX only.\n#\n#    LINKOPTS=xxx   Link with LINK options xxx.  For example:\n#                   LINKOPTS=/NOINFO\n#\n#    LIST=1         Compile with /LIST /SHOW = (ALL, NOMESSAGES).\n#                   Link with /MAP /CROSS_REFERENCE /FULL.\n#\n#    NOSHARE=1      Link /NOSYSSHR (not using shareable images).\n#    NOSHARE=OLDVAX Link /NOSYSSHR on VAX for:\n#                      DEC C with VMS before V7.3.\n#                      VAX C without DEC C RTL (DEC C not installed).\n#\n#    \"LOCAL_UNZIP= c_macro_1=value1 [, c_macro_2=value2 [...]]\"\n#                   Compile with these additional C macros defined.\n#\n# VAX-specific optional macros:\n#\n#    VAXC=1         Use the VAX C compiler, assuming \"CC\" runs it.\n#                   (That is, DEC C is not installed, or else DEC C is\n#                   installed, but VAX C is the default.)\n#\n#    FORCE_VAXC=1   Use the VAX C compiler, assuming \"CC /VAXC\" runs it.\n#                   (That is, DEC C is installed, and it is the\n#                   default, but you want VAX C anyway, you fool.)\n#\n#    GNUC=1         Use the GNU C compiler.  (Seriously under-tested.)\n#\n#\n# The default target, ALL, builds the selected product executables and\n# help files.\n#\n# Other targets:\n#\n#    CLEAN      deletes architecture-specific files, but leaves any\n#               individual source dependency files and the help files.\n#\n#    CLEAN_ALL  deletes all generated files, except the main (collected)\n#               source dependency file.\n#\n#    CLEAN_EXE  deletes only the architecture-specific executables.\n#               Handy if all you wish to do is re-link the executables.\n#\n# Example commands:\n#\n# To build the conventional small-file product using the DEC/Compaq/HP C\n# compiler (Note: DESCRIP.MMS is the default description file name.):\n#\n#    MMS /DESCRIP = [.VMS]\n#\n# To get the large-file executables (on a non-VAX system):\n#\n#    MMS /DESCRIP = [.VMS] /MACRO = (LARGE=1)\n#\n# To delete the architecture-specific generated files for this system\n# type:\n#\n#    MMS /DESCRIP = [.VMS] /MACRO = (LARGE=1) CLEAN     ! Large-file.\n# or\n#    MMS /DESCRIP = [.VMS] CLEAN                        ! Small-file.\n#\n# To build a complete small-file product for debug with compiler\n# listings and link maps:\n#\n#    MMS /DESCRIP = [.VMS] CLEAN\n#    MMS /DESCRIP = [.VMS] /MACRO = (DBG=1, LIST=1)\n#\n########################################################################\n\n# Include primary product description file.\n\nINCL_DESCRIP_SRC = 1\n.INCLUDE [.VMS]DESCRIP_SRC.MMS\n\n# Object library names.\n\nLIB_UNZIP = SYS$DISK:[.$(DEST)]UNZIP.OLB\nLIB_UNZIP_CLI = SYS$DISK:[.$(DEST)]UNZIPCLI.OLB\nLIB_UNZIPSFX = SYS$DISK:[.$(DEST)]UNZIPSFX.OLB\nLIB_UNZIPSFX_CLI = SYS$DISK:[.$(DEST)]UNZSFXCLI.OLB\n\n# Help file names.\n\nUNZIP_HELP = UNZIP.HLP UNZIP_CLI.HLP\n\n# Message file names.\n\nUNZIP_MSG_MSG = [.VMS]UNZIP_MSG.MSG\nUNZIP_MSG_EXE = [.$(DEST)]UNZIP_MSG.EXE\nUNZIP_MSG_OBJ = [.$(DEST)]UNZIP_MSG.OBJ\n\n\n# TARGETS.\n\n# Default target, ALL.  Build All executables,\n# and help files.\n\nALL : $(UNZIP) $(UNZIP_CLI) $(UNZIPSFX) $(UNZIPSFX_CLI) $(UNZIP_HELP) \\\n      $(UNZIP_MSG_EXE)\n\t@ write sys$output \"Done.\"\n\n# CLEAN target.  Delete the [.$(DEST)] directory and everything in it.\n\nCLEAN :\n\tif (f$search( \"[.$(DEST)]*.*\") .nes. \"\") then -\n\t delete [.$(DEST)]*.*;*\n\tif (f$search( \"$(DEST).dir\") .nes. \"\") then -\n\t set protection = w:d $(DEST).dir;*\n\tif (f$search( \"$(DEST).dir\") .nes. \"\") then -\n\t delete $(DEST).dir;*\n\n# CLEAN_ALL target.  Delete:\n#    The [.$(DEST)] directories and everything in them.\n#    All help-related derived files,\n#    All individual C dependency files.\n# Also mention:\n#    Comprehensive dependency file.\n#\nCLEAN_ALL :\n\tif (f$search( \"[.ALPHA*]*.*\") .nes. \"\") then -\n\t delete [.ALPHA*]*.*;*\n\tif (f$search( \"ALPHA*.dir\", 1) .nes. \"\") then -\n\t set protection = w:d ALPHA*.dir;*\n\tif (f$search( \"ALPHA*.dir\", 2) .nes. \"\") then -\n\t delete ALPHA*.dir;*\n\tif (f$search( \"[.IA64*]*.*\") .nes. \"\") then -\n\t delete [.IA64*]*.*;*\n\tif (f$search( \"IA64*.dir\", 1) .nes. \"\") then -\n\t set protection = w:d IA64*.dir;*\n\tif (f$search( \"IA64*.dir\", 2) .nes. \"\") then -\n\t delete IA64*.dir;*\n\tif (f$search( \"[.VAX*]*.*\") .nes. \"\") then -\n\t delete [.VAX*]*.*;*\n\tif (f$search( \"VAX*.dir\", 1) .nes. \"\") then -\n\t set protection = w:d VAX*.dir;*\n\tif (f$search( \"VAX*.dir\", 2) .nes. \"\") then -\n\t delete VAX*.dir;*\n\tif (f$search( \"[.VMS]UNZIP_CLI.RNH\") .nes. \"\") then -\n\t delete [.VMS]UNZIP_CLI.RNH;*\n\tif (f$search( \"UNZIP_CLI.HLP\") .nes. \"\") then -\n\t delete UNZIP_CLI.HLP;*\n\tif (f$search( \"UNZIP.HLP\") .nes. \"\") then -\n\t delete UNZIP.HLP;*\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete *.MMSD;*\n\tif (f$search( \"[.VMS]*.MMSD\") .nes. \"\") then -\n\t delete [.VMS]*.MMSD;*\n\t@ write sys$output \"\"\n\t@ write sys$output \"Note:  This procedure will not\"\n\t@ write sys$output \"   DELETE [.VMS]DESCRIP_DEPS.MMS;*\"\n\t@ write sys$output -\n \"You may choose to, but a recent version of MMS (V3.5 or newer?) is\"\n\t@ write sys$output -\n \"needed to regenerate it.  (It may also be recovered from the original\"\n\t@ write sys$output -\n \"distribution kit.)  See [.VMS]DESCRIP_MKDEPS.MMS for instructions on\"\n\t@ write sys$output -\n \"generating [.VMS]DESCRIP_DEPS.MMS.\"\n        @ write sys$output \"\"\n\n# CLEAN_EXE target.  Delete the executables in [.$(DEST)].\n\nCLEAN_EXE :\n        if (f$search( \"[.$(DEST)]*.EXE\") .nes. \"\") then -\n         delete [.$(DEST)]*.EXE;*\n\n\n# Object library module dependencies.\n\n$(LIB_UNZIP) : $(LIB_UNZIP)($(MODS_OBJS_LIB_UNZIP))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(LIB_UNZIP_CLI) : $(LIB_UNZIP_CLI)($(MODS_OBJS_LIB_UNZIP_CLI))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(LIB_UNZIPSFX) : $(LIB_UNZIPSFX)($(MODS_OBJS_LIB_UNZIPSFX))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(LIB_UNZIPSFX_CLI) : $(LIB_UNZIPSFX_CLI)($(MODS_OBJS_LIB_UNZIPSFX_CLI))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n\n# Module ID options files.\n\nOPT_ID = SYS$DISK:[.VMS]UNZIP.OPT\nOPT_ID_SFX = SYS$DISK:[.VMS]UNZIPSFX.OPT\n\n# Default C compile rule.\n\n.C.OBJ :\n        $(CC) $(CFLAGS) $(CDEFS_UNX) $(MMS$SOURCE)\n\n\n# Normal sources in [.VMS].\n\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.C\n\n# Command-line interface files.\n\n[.$(DEST)]CMDLINE.OBJ : [.VMS]CMDLINE.C\n\t$(CC) $(CFLAGS) $(CDEFS_CLI) $(MMS$SOURCE)\n\n[.$(DEST)]UNZIPCLI.OBJ : UNZIP.C\n\t$(CC) $(CFLAGS) $(CDEFS_CLI) $(MMS$SOURCE)\n\n[.$(DEST)]UNZ_CLI.OBJ : [.VMS]UNZ_CLI.CLD\n\n# SFX variant sources.\n\n[.$(DEST)]CRC32_.OBJ : CRC32.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]CRYPT_.OBJ : CRYPT.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]EXTRACT_.OBJ : EXTRACT.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]FILEIO_.OBJ : FILEIO.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]GLOBALS_.OBJ : GLOBALS.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]INFLATE_.OBJ : INFLATE.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]MATCH_.OBJ : MATCH.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]PROCESS_.OBJ : PROCESS.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]TTYIO_.OBJ : TTYIO.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]UBZ2ERR_.OBJ : UBZ2ERR.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n[.$(DEST)]UNZIPSFX.OBJ : UNZIP.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX) $(MMS$SOURCE)\n\n# SFX CLI variant sources.\n\n[.$(DEST)]CMDLINE_.OBJ : [.VMS]CMDLINE.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX_CLI) $(MMS$SOURCE)\n\n[.$(DEST)]UNZSFXCLI.OBJ : UNZIP.C\n\t$(CC) $(CFLAGS) $(CDEFS_SFX_CLI) $(MMS$SOURCE)\n\n# VAX C LINK options file.\n\n.IFDEF OPT_FILE\n$(OPT_FILE) :\n\topen /write opt_file_ln  $(OPT_FILE)\n\twrite opt_file_ln \"SYS$SHARE:VAXCRTL.EXE /SHARE\"\n\tclose opt_file_ln\n.ENDIF\n\n# Local BZIP2 object library.\n\n$(LIB_BZ2_LOCAL) :\n\t$(MMS) $(MMSQUALIFIERS) /DESCR=$(IZ_BZIP2)descrbz2.mms'macro' -\n\t   /MACRO = (SRCDIR=$(IZ_BZIP2), DSTDIR=$(BZ2DIR_BIN), -\n\t   DEST=$(IZ_BZIP2)$(DESTM)) $(MMSTARGETS)\n\n# Normal UnZip executable.\n\n$(UNZIP) : [.$(DEST)]UNZIP.OBJ \\\n           $(LIB_UNZIP) $(LIB_BZ2_DEP) $(OPT_FILE) $(OPT_ID)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_UNZIP) /library, -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LIB_UNZIP) /library, -\n\t $(LIB_ZLIB_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options -\n\t $(NOSHARE_OPTS)\n\n# CLI UnZip executable.\n\n$(UNZIP_CLI) : [.$(DEST)]UNZIPCLI.OBJ \\\n               $(LIB_UNZIP_CLI) $(LIB_BZ2_DEP) $(OPT_FILE) $(OPT_ID)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_UNZIP_CLI) /library, -\n\t $(LIB_UNZIP) /library, -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LIB_UNZIP) /library, -\n\t $(LIB_ZLIB_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options -\n\t $(NOSHARE_OPTS)\n\n# SFX UnZip executable.\n\n$(UNZIPSFX) : [.$(DEST)]UNZIPSFX.OBJ \\\n              $(LIB_UNZIPSFX) $(LIB_BZ2_DEP) $(OPT_FILE) $(OPT_ID_SFX)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_UNZIPSFX) /library, -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LIB_UNZIPSFX) /library, -\n\t $(LIB_ZLIB_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID_SFX) /options -\n\t $(NOSHARE_OPTS)\n\n# SFX CLI UnZip executable.\n\n$(UNZIPSFX_CLI) : [.$(DEST)]UNZSFXCLI.OBJ \\\n                  $(LIB_UNZIPSFX_CLI) $(LIB_UNZIPSFX) $(LIB_BZ2_DEP) \\\n                  $(OPT_FILE) $(OPT_ID_SFX)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_UNZIPSFX_CLI) /library, -\n\t $(LIB_UNZIPSFX) /library, -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LIB_UNZIPSFX) /library, -\n\t $(LIB_ZLIB_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID_SFX) /options -\n\t $(NOSHARE_OPTS)\n\n\n# Help files.\n\nUNZIP.HLP : [.VMS]UNZIP_DEF.RNH\n\trunoff /output = $(MMS$TARGET) $(MMS$SOURCE)\n\nUNZIP_CLI.HLP : [.VMS]UNZIP_CLI.HELP [.VMS]CVTHELP.TPU\n\tedit /tpu /nosection /nodisplay /command = [.VMS]CVTHELP.TPU -\n\t $(MMS$SOURCE)\n\trename UNZIP_CLI.RNH [.VMS]\n        purge /nolog /keep = 1 [.VMS]UNZIP_CLI.RNH\n\trunoff /output = $(MMS$TARGET) [.VMS]UNZIP_CLI.RNH\n\n# Message file.\n\n$(UNZIP_MSG_EXE) : $(UNZIP_MSG_OBJ)\n        link /shareable = $(MMS$TARGET) $(UNZIP_MSG_OBJ)\n\n$(UNZIP_MSG_OBJ) : $(UNZIP_MSG_MSG)\n        message /object = $(MMS$TARGET) /nosymbols $(UNZIP_MSG_MSG)\n\n# Include generated source dependencies.\n\nINCL_DESCRIP_DEPS = 1\n.INCLUDE [.VMS]DESCRIP_DEPS.MMS\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/descrip_deps.mms",
    "content": "#\n# UnZip for VMS - MMS (or MMK) Source Dependency File.\n#\n\n# This description file is included by other description files.  It is\n# not intended to be used alone.  Verify proper inclusion.\n\n.IFDEF INCL_DESCRIP_DEPS\n.ELSE\n$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\n.ENDIF\n\n[.$(DEST)]CRC32.OBJ : []CRC32.C\n[.$(DEST)]CRC32.OBJ : []ZIP.H\n[.$(DEST)]CRC32.OBJ : []UNZIP.H\n[.$(DEST)]CRC32.OBJ : []UNZPRIV.H\n[.$(DEST)]CRC32.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]CRC32.OBJ : []GLOBALS.H\n[.$(DEST)]CRC32.OBJ : []CRC32.H\n[.$(DEST)]CRC32_.OBJ : []CRC32.C\n[.$(DEST)]CRC32_.OBJ : []ZIP.H\n[.$(DEST)]CRC32_.OBJ : []UNZIP.H\n[.$(DEST)]CRC32_.OBJ : []UNZPRIV.H\n[.$(DEST)]CRC32_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]CRC32_.OBJ : []GLOBALS.H\n[.$(DEST)]CRC32_.OBJ : []CRC32.H\n[.$(DEST)]CRYPT.OBJ : []CRYPT.C\n[.$(DEST)]CRYPT.OBJ : []ZIP.H\n[.$(DEST)]CRYPT.OBJ : []UNZIP.H\n[.$(DEST)]CRYPT.OBJ : []UNZPRIV.H\n[.$(DEST)]CRYPT.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]CRYPT.OBJ : []GLOBALS.H\n[.$(DEST)]CRYPT.OBJ : []CRYPT.H\n[.$(DEST)]CRYPT.OBJ : []TTYIO.H\n[.$(DEST)]CRYPT.OBJ : []CRC32.H\n[.$(DEST)]CRYPT_.OBJ : []CRYPT.C\n[.$(DEST)]CRYPT_.OBJ : []ZIP.H\n[.$(DEST)]CRYPT_.OBJ : []UNZIP.H\n[.$(DEST)]CRYPT_.OBJ : []UNZPRIV.H\n[.$(DEST)]CRYPT_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]CRYPT_.OBJ : []GLOBALS.H\n[.$(DEST)]CRYPT_.OBJ : []CRYPT.H\n[.$(DEST)]CRYPT_.OBJ : []TTYIO.H\n[.$(DEST)]CRYPT_.OBJ : []CRC32.H\n[.$(DEST)]ENVARGS.OBJ : []ENVARGS.C\n[.$(DEST)]ENVARGS.OBJ : []UNZIP.H\n[.$(DEST)]ENVARGS.OBJ : []UNZPRIV.H\n[.$(DEST)]ENVARGS.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]ENVARGS.OBJ : []GLOBALS.H\n[.$(DEST)]EXPLODE.OBJ : []EXPLODE.C\n[.$(DEST)]EXPLODE.OBJ : []UNZIP.H\n[.$(DEST)]EXPLODE.OBJ : []UNZPRIV.H\n[.$(DEST)]EXPLODE.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]EXPLODE.OBJ : []GLOBALS.H\n[.$(DEST)]EXTRACT.OBJ : []EXTRACT.C\n[.$(DEST)]EXTRACT.OBJ : []UNZIP.H\n[.$(DEST)]EXTRACT.OBJ : []UNZPRIV.H\n[.$(DEST)]EXTRACT.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]EXTRACT.OBJ : []GLOBALS.H\n[.$(DEST)]EXTRACT.OBJ : []CRC32.H\n[.$(DEST)]EXTRACT.OBJ : []ZIP.H\n[.$(DEST)]EXTRACT.OBJ : []CRYPT.H\n[.$(DEST)]EXTRACT_.OBJ : []EXTRACT.C\n[.$(DEST)]EXTRACT_.OBJ : []UNZIP.H\n[.$(DEST)]EXTRACT_.OBJ : []UNZPRIV.H\n[.$(DEST)]EXTRACT_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]EXTRACT_.OBJ : []GLOBALS.H\n[.$(DEST)]EXTRACT_.OBJ : []CRC32.H\n[.$(DEST)]EXTRACT_.OBJ : []ZIP.H\n[.$(DEST)]EXTRACT_.OBJ : []CRYPT.H\n[.$(DEST)]FILEIO.OBJ : []FILEIO.C\n[.$(DEST)]FILEIO.OBJ : []UNZIP.H\n[.$(DEST)]FILEIO.OBJ : []UNZPRIV.H\n[.$(DEST)]FILEIO.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]FILEIO.OBJ : []GLOBALS.H\n[.$(DEST)]FILEIO.OBJ : []CRC32.H\n[.$(DEST)]FILEIO.OBJ : []ZIP.H\n[.$(DEST)]FILEIO.OBJ : []CRYPT.H\n[.$(DEST)]FILEIO.OBJ : []TTYIO.H\n[.$(DEST)]FILEIO.OBJ : []EBCDIC.H\n[.$(DEST)]FILEIO_.OBJ : []FILEIO.C\n[.$(DEST)]FILEIO_.OBJ : []UNZIP.H\n[.$(DEST)]FILEIO_.OBJ : []UNZPRIV.H\n[.$(DEST)]FILEIO_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]FILEIO_.OBJ : []GLOBALS.H\n[.$(DEST)]FILEIO_.OBJ : []CRC32.H\n[.$(DEST)]FILEIO_.OBJ : []ZIP.H\n[.$(DEST)]FILEIO_.OBJ : []CRYPT.H\n[.$(DEST)]FILEIO_.OBJ : []TTYIO.H\n[.$(DEST)]FILEIO_.OBJ : []EBCDIC.H\n[.$(DEST)]GLOBALS.OBJ : []GLOBALS.C\n[.$(DEST)]GLOBALS.OBJ : []UNZIP.H\n[.$(DEST)]GLOBALS.OBJ : []UNZPRIV.H\n[.$(DEST)]GLOBALS.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]GLOBALS.OBJ : []GLOBALS.H\n[.$(DEST)]GLOBALS_.OBJ : []GLOBALS.C\n[.$(DEST)]GLOBALS_.OBJ : []UNZIP.H\n[.$(DEST)]GLOBALS_.OBJ : []UNZPRIV.H\n[.$(DEST)]GLOBALS_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]GLOBALS_.OBJ : []GLOBALS.H\n[.$(DEST)]INFLATE.OBJ : []INFLATE.C\n[.$(DEST)]INFLATE.OBJ : []INFLATE.H\n[.$(DEST)]INFLATE.OBJ : []UNZIP.H\n[.$(DEST)]INFLATE.OBJ : []UNZPRIV.H\n[.$(DEST)]INFLATE.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]INFLATE.OBJ : []GLOBALS.H\n[.$(DEST)]INFLATE_.OBJ : []INFLATE.C\n[.$(DEST)]INFLATE_.OBJ : []INFLATE.H\n[.$(DEST)]INFLATE_.OBJ : []UNZIP.H\n[.$(DEST)]INFLATE_.OBJ : []UNZPRIV.H\n[.$(DEST)]INFLATE_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]INFLATE_.OBJ : []GLOBALS.H\n[.$(DEST)]LIST.OBJ : []LIST.C\n[.$(DEST)]LIST.OBJ : []UNZIP.H\n[.$(DEST)]LIST.OBJ : []UNZPRIV.H\n[.$(DEST)]LIST.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]LIST.OBJ : []GLOBALS.H\n[.$(DEST)]MATCH.OBJ : []MATCH.C\n[.$(DEST)]MATCH.OBJ : []UNZIP.H\n[.$(DEST)]MATCH.OBJ : []UNZPRIV.H\n[.$(DEST)]MATCH.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]MATCH.OBJ : []GLOBALS.H\n[.$(DEST)]MATCH_.OBJ : []MATCH.C\n[.$(DEST)]MATCH_.OBJ : []UNZIP.H\n[.$(DEST)]MATCH_.OBJ : []UNZPRIV.H\n[.$(DEST)]MATCH_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]MATCH_.OBJ : []GLOBALS.H\n[.$(DEST)]PROCESS.OBJ : []PROCESS.C\n[.$(DEST)]PROCESS.OBJ : []UNZIP.H\n[.$(DEST)]PROCESS.OBJ : []UNZPRIV.H\n[.$(DEST)]PROCESS.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]PROCESS.OBJ : []GLOBALS.H\n[.$(DEST)]PROCESS.OBJ : []CRC32.H\n[.$(DEST)]PROCESS.OBJ : []ZIP.H\n[.$(DEST)]PROCESS_.OBJ : []PROCESS.C\n[.$(DEST)]PROCESS_.OBJ : []UNZIP.H\n[.$(DEST)]PROCESS_.OBJ : []UNZPRIV.H\n[.$(DEST)]PROCESS_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]PROCESS_.OBJ : []GLOBALS.H\n[.$(DEST)]PROCESS_.OBJ : []CRC32.H\n[.$(DEST)]PROCESS_.OBJ : []ZIP.H\n[.$(DEST)]TTYIO.OBJ : []TTYIO.C\n[.$(DEST)]TTYIO.OBJ : []ZIP.H\n[.$(DEST)]TTYIO.OBJ : []UNZIP.H\n[.$(DEST)]TTYIO.OBJ : []UNZPRIV.H\n[.$(DEST)]TTYIO.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]TTYIO.OBJ : []GLOBALS.H\n[.$(DEST)]TTYIO.OBJ : []CRYPT.H\n[.$(DEST)]TTYIO.OBJ : []TTYIO.H\n[.$(DEST)]TTYIO_.OBJ : []TTYIO.C\n[.$(DEST)]TTYIO_.OBJ : []ZIP.H\n[.$(DEST)]TTYIO_.OBJ : []UNZIP.H\n[.$(DEST)]TTYIO_.OBJ : []UNZPRIV.H\n[.$(DEST)]TTYIO_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]TTYIO_.OBJ : []GLOBALS.H\n[.$(DEST)]TTYIO_.OBJ : []CRYPT.H\n[.$(DEST)]TTYIO_.OBJ : []TTYIO.H\n[.$(DEST)]UBZ2ERR.OBJ : []UBZ2ERR.C\n[.$(DEST)]UBZ2ERR.OBJ : []UNZIP.H\n[.$(DEST)]UBZ2ERR.OBJ : []UNZPRIV.H\n[.$(DEST)]UBZ2ERR.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UBZ2ERR.OBJ : []GLOBALS.H\n[.$(DEST)]UBZ2ERR_.OBJ : []UBZ2ERR.C\n[.$(DEST)]UBZ2ERR_.OBJ : []UNZIP.H\n[.$(DEST)]UBZ2ERR_.OBJ : []UNZPRIV.H\n[.$(DEST)]UBZ2ERR_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UBZ2ERR_.OBJ : []GLOBALS.H\n[.$(DEST)]UNREDUCE.OBJ : []UNREDUCE.C\n[.$(DEST)]UNREDUCE.OBJ : []UNZIP.H\n[.$(DEST)]UNREDUCE.OBJ : []UNZPRIV.H\n[.$(DEST)]UNREDUCE.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNREDUCE.OBJ : []GLOBALS.H\n[.$(DEST)]UNSHRINK.OBJ : []UNSHRINK.C\n[.$(DEST)]UNSHRINK.OBJ : []UNZIP.H\n[.$(DEST)]UNSHRINK.OBJ : []UNZPRIV.H\n[.$(DEST)]UNSHRINK.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNSHRINK.OBJ : []GLOBALS.H\n[.$(DEST)]UNZIP.OBJ : []UNZIP.C\n[.$(DEST)]UNZIP.OBJ : []UNZIP.H\n[.$(DEST)]UNZIP.OBJ : []UNZPRIV.H\n[.$(DEST)]UNZIP.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNZIP.OBJ : []GLOBALS.H\n[.$(DEST)]UNZIP.OBJ : []CRYPT.H\n[.$(DEST)]UNZIP.OBJ : []UNZVERS.H\n[.$(DEST)]UNZIP.OBJ : []CONSTS.H\n[.$(DEST)]UNZIPSFX.OBJ : []UNZIP.C\n[.$(DEST)]UNZIPSFX.OBJ : []UNZIP.H\n[.$(DEST)]UNZIPSFX.OBJ : []UNZPRIV.H\n[.$(DEST)]UNZIPSFX.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNZIPSFX.OBJ : []GLOBALS.H\n[.$(DEST)]UNZIPSFX.OBJ : []CRYPT.H\n[.$(DEST)]UNZIPSFX.OBJ : []UNZVERS.H\n[.$(DEST)]UNZIPSFX.OBJ : []CONSTS.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []UNZIP.C\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []UNZIP.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []UNZPRIV.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []GLOBALS.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []CRYPT.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []UNZVERS.H\n[.$(DEST)]UNZIPSFX_CLI.OBJ : []CONSTS.H\n[.$(DEST)]UNZIP_CLI.OBJ : []UNZIP.C\n[.$(DEST)]UNZIP_CLI.OBJ : []UNZIP.H\n[.$(DEST)]UNZIP_CLI.OBJ : []UNZPRIV.H\n[.$(DEST)]UNZIP_CLI.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]UNZIP_CLI.OBJ : []GLOBALS.H\n[.$(DEST)]UNZIP_CLI.OBJ : []CRYPT.H\n[.$(DEST)]UNZIP_CLI.OBJ : []UNZVERS.H\n[.$(DEST)]UNZIP_CLI.OBJ : []CONSTS.H\n[.$(DEST)]ZIPINFO.OBJ : []ZIPINFO.C\n[.$(DEST)]ZIPINFO.OBJ : []UNZIP.H\n[.$(DEST)]ZIPINFO.OBJ : []UNZPRIV.H\n[.$(DEST)]ZIPINFO.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]ZIPINFO.OBJ : []GLOBALS.H\n[.$(DEST)]CMDLINE.OBJ : [.VMS]CMDLINE.C\n[.$(DEST)]CMDLINE.OBJ : []UNZIP.H\n[.$(DEST)]CMDLINE.OBJ : []UNZPRIV.H\n[.$(DEST)]CMDLINE.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]CMDLINE.OBJ : []GLOBALS.H\n[.$(DEST)]CMDLINE.OBJ : []UNZVERS.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.C\n[.$(DEST)]VMS.OBJ : []UNZIP.H\n[.$(DEST)]VMS.OBJ : []UNZPRIV.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]VMS.OBJ : []GLOBALS.H\n[.$(DEST)]VMS.OBJ : []CRC32.H\n[.$(DEST)]VMS.OBJ : []ZIP.H\n[.$(DEST)]VMS.OBJ : []UNZIP.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.C\n[.$(DEST)]VMS_.OBJ : []UNZIP.H\n[.$(DEST)]VMS_.OBJ : []UNZPRIV.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMSCFG.H\n[.$(DEST)]VMS_.OBJ : []GLOBALS.H\n[.$(DEST)]VMS_.OBJ : []CRC32.H\n[.$(DEST)]VMS_.OBJ : []ZIP.H\n[.$(DEST)]VMS_.OBJ : []UNZIP.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMSDEFS.H\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/descrip_mkdeps.mms",
    "content": "#                                               1 February 2008.  SMS.\n#\n#    UnZip 6.0 for VMS - MMS Dependency Description File.\n#\n#    MMS /EXTENDED_SYNTAX description file to generate a C source\n#    dependencies file.  Unsightly errors result when /EXTENDED_SYNTAX\n#    is not specified.  Typical usage:\n#\n#    $ MMS /EXTEND /DESCRIP = [.VMS]DESCRIP_MKDEPS.MMS /SKIP\n#\n# Note that this description file must be used from the main\n# distribution directory, not from the [.VMS] subdirectory.\n#\n# This description file uses these command procedures:\n#\n#    [.VMS]MOD_DEP.COM\n#    [.VMS]COLLECT_DEPS.COM\n#\n# MMK users without MMS will be unable to generate the dependencies file\n# using this description file, however there should be one supplied in\n# the kit.  If this file has been deleted, users in this predicament\n# will need to recover it from the original distribution kit.\n#\n# Note:  This dependency generation scheme assumes that the dependencies\n# do not depend on host architecture type or other such variables.\n# Therefore, no \"#include\" directive in the C source itself should be\n# conditional on such variables.\n#\n# The default target is the comprehensive source dependency file,\n# DEPS_FILE = [.VMS]DESCRIP_DEPS.MMS.\n#\n# Other targets:\n#\n#    CLEAN      deletes the individual source dependency files,\n#               *.MMSD;*, but leaves the comprehensive source dependency\n#               file.\n#\n#    CLEAN_ALL  deletes all source dependency files, including the\n#               individual *.MMSD;* files and the comprehensive file,\n#               DESCRIP_DEPS.MMS.*.\n#\n\n# Required command procedures.\n\nCOMS = [.VMS]MOD_DEP.COM [.VMS]COLLECT_DEPS.COM\n\n# Include the source file lists (among other data).\n\nINCL_DESCRIP_SRC = 1\n.INCLUDE [.VMS]DESCRIP_SRC.MMS\n\n# The ultimate product, a comprehensive dependency list.\n\nDEPS_FILE = [.VMS]DESCRIP_DEPS.MMS\n\n# Detect valid qualifier and/or macro options.\n\n.IF $(FINDSTRING Skip, $(MMSQUALIFIERS)) .eq Skip\nDELETE_MMSD = 1\n.ELSIF NOSKIP\nPURGE_MMSD = 1\n.ELSE\nUNK_MMSD = 1\n.ENDIF\n\n# Dependency suffixes and rules.\n#\n# .FIRST is assumed to be used already, so the MMS qualifier/macro check\n# is included in each rule (one way or another).\n\n.SUFFIXES_BEFORE .C .MMSD\n\n.C.MMSD :\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n\t$(CC) $(CFLAGS_INCL) $(MMS$SOURCE) /NOLIST /NOOBJECT -\n\t /MMS_DEPENDENCIES = (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\n# List of MMS dependency files.\n\n# In case it's not obvious...\n# To extract module name lists from object library module=object lists:\n# 1.  Transform \"module=[.dest]name.OBJ\" into \"module=[.dest] name\".\n# 2.  For [.VMS], add [.VMS] to name.\n# 3.  Delete \"*]\" words.\n#\n# A similar scheme works for executable lists.\n\nMODS_LIB_UNZIP_N = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] *, $(MODS_OBJS_LIB_UNZIP_N)))\n\nMODS_LIB_UNZIP_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_UNZIP_V)))\n\nMODS_LIB_UNZIPCLI_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_UNZIPCLI_C_V)))\n\nMODS_LIB_UNZIPSFX_N = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] *, $(MODS_OBJS_LIB_UNZIPSFX_N)))\n\nMODS_LIB_UNZIPSFX_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_UNZIPSFX_V)))\n\nMODS_UNZIP = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(UNZIP)))\n\nMODS_UNZIP_CLI = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(UNZIP_CLI)))\n\nMODS_UNZIPSFX = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(UNZIPSFX)))\n\nMODS_UNZIPSFX_CLI = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(UNZIPSFX_CLI)))\n\n# Complete list of C object dependency file names.\n# Note that the CLI UnZip main program object file is a special case.\n\nDEPS = $(FOREACH NAME, \\\n $(MODS_LIB_UNZIP_N) $(MODS_LIB_UNZIP_V) \\\n $(MODS_LIB_UNZIPCLI_V) \\\n $(MODS_LIB_UNZIPSFX_N) $(MODS_LIB_UNZIPSFX_V) \\\n $(MODS_UNZIP) $(MODS_UNZIP_CLI) \\\n $(MODS_UNZIPSFX) $(MODS_UNZIPSFX_CLI), \\\n $(NAME).mmsd)\n\n# Default target is the comprehensive dependency list.\n\n$(DEPS_FILE) : $(DEPS) $(COMS)\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete individual .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the individual .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n#\n#       Note that the space in P4, which prevents immediate macro\n#       expansion, is removed by COLLECT_DEPS.COM.\n#\n        @[.VMS]COLLECT_DEPS.COM \"UnZip\" -\n         \"$(MMS$TARGET)\" \"[...]*.mmsd\" \"[.$ (DEST)]\" $(MMSDESCRIPTION_FILE)\n        @ write sys$output -\n         \"Created a new dependency file: $(MMS$TARGET)\"\n.IF DELETE_MMSD\n\t@ write sys$output -\n         \"Deleting intermediate .MMSD files...\"\n\tdelete /log *.MMSD;*, [.VMS]*.MMSD;*\n.ELSE\n\t@ write sys$output -\n         \"Purging intermediate .MMSD files...\"\n\tpurge /log *.MMSD, [.VMS]*.MMSD\n.ENDIF\n\n# CLEAN target.  Delete the individual C dependency files.\n\nCLEAN :\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete /log *.MMSD;*\n\tif (f$search( \"[.VMS]*.MMSD\") .nes. \"\") then -\n\t delete /log [.VMS]*.MMSD;*\n\n# CLEAN_ALL target.  Delete:\n#    The individual C dependency files.\n#    The collected source dependency file.\n\nCLEAN_ALL :\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete /log *.MMSD;*\n\tif (f$search( \"[.VMS]*.MMSD\") .nes. \"\") then -\n\t delete /log [.VMS]*.MMSD;*\n\tif (f$search( \"[.VMS]DESCRIP_DEPS.MMS\") .nes. \"\") then -\n\t delete /log [.VMS]DESCRIP_DEPS.MMS;*\n\n# Explicit dependencies and rules for utility variant modules.\n#\n# The extra dependency on the normal dependency file obviates including\n# the /SKIP warning code in each rule here.\n\nCRC32_.MMSD : CRC32.C CRC32.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nCRYPT_.MMSD : CRYPT.C CRYPT.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nEXTRACT_.MMSD : EXTRACT.C EXTRACT.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nFILEIO_.MMSD : FILEIO.C FILEIO.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nGLOBALS_.MMSD : GLOBALS.C GLOBALS.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nINFLATE_.MMSD : INFLATE.C INFLATE.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nMATCH_.MMSD : MATCH.C MATCH.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nPROCESS_.MMSD : PROCESS.C PROCESS.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nTTYIO_.MMSD : TTYIO.C TTYIO.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nUBZ2ERR_.MMSD : UBZ2ERR.C UBZ2ERR.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n[.VMS]VMS_.MMSD : [.VMS]VMS.C [.VMS]VMS.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nUNZIP_CLI.MMSD : UNZIP.C UNZIP.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nUNZIPSFX.MMSD : UNZIP.C UNZIP.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_SFX) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nUNZIPSFX_CLI.MMSD : UNZIP.C UNZIP.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(CFLAGS_SFX) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n# Special case.  No normal (non-CLI) version.\n\n[.VMS]CMDLINE.MMSD : [.VMS]CMDLINE.C\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/descrip_src.mms",
    "content": "#                                               1 March 2009.  SMS.\n#\n#    UnZip 6.0 for VMS - MMS (or MMK) Source Description File.\n#\n\n# This description file is included by other description files.  It is\n# not intended to be used alone.  Verify proper inclusion.\n\n.IFDEF INCL_DESCRIP_SRC\n.ELSE\n$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\n.ENDIF\n\n\n# Define MMK architecture macros when using MMS.\n\n.IFDEF __MMK__                  # __MMK__\n.ELSE                           # __MMK__\nALPHA_X_ALPHA = 1\nIA64_X_IA64 = 1\nVAX_X_VAX = 1\n.IFDEF $(MMS$ARCH_NAME)_X_ALPHA     # $(MMS$ARCH_NAME)_X_ALPHA\n__ALPHA__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_ALPHA\n.IFDEF $(MMS$ARCH_NAME)_X_IA64      # $(MMS$ARCH_NAME)_X_IA64\n__IA64__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_IA64\n.IFDEF $(MMS$ARCH_NAME)_X_VAX       # $(MMS$ARCH_NAME)_X_VAX\n__VAX__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_VAX\n.ENDIF                          # __MMK__\n\n# Combine command-line VAX C compiler macros.\n\n.IFDEF VAXC                     # VAXC\nVAXC_OR_FORCE_VAXC = 1\n.ELSE                           # VAXC\n.IFDEF FORCE_VAXC                   # FORCE_VAXC\nVAXC_OR_FORCE_VAXC = 1\n.ENDIF                              # FORCE_VAXC\n.ENDIF                          # VAXC\n\n# Analyze architecture-related and option macros.\n\n.IFDEF __ALPHA__                # __ALPHA__\nDECC = 1\nDESTM = ALPHA\n.ELSE                           # __ALPHA__\n.IFDEF __IA64__                     # __IA64__\nDECC = 1\nDESTM = IA64\n.ELSE                               # __IA64__\n.IFDEF __VAX__                          # __VAX__\n.IFDEF VAXC_OR_FORCE_VAXC                   # VAXC_OR_FORCE_VAXC\nDESTM = VAXV\n.ELSE                                       # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                                     # GNUC\nCC = GCC\nDESTM = VAXG\n.ELSE                                           # GNUC\nDECC = 1\nDESTM = VAX\n.ENDIF                                          # GNUC\n.ENDIF                                      # VAXC_OR_FORCE_VAXC\n.ELSE                                   # __VAX__\nDESTM = UNK\nUNK_DEST = 1\n.ENDIF                                  # __VAX__\n.ENDIF                              # __IA64__\n.ENDIF                          # __ALPHA__\n\n.IFDEF LARGE                    # LARGE\n.IFDEF __VAX__                      # __VAX__\n.ELSE                               # __VAX__\nDESTL = L\n.ENDIF                              # __VAX__\n.ENDIF                          # LARGE\n\nDEST = $(DESTM)$(DESTL)\nSEEK_BZ = $(DESTM)\n\n# Library module name suffix for XXX_.OBJ with GNU C.\n\n.IFDEF GNUC                     # GNUC\nGCC_ = _\n.ELSE                           # GNUC\nGCC_ =\n.ENDIF                          # GNUC\n\n# Check for option problems.\n\n.IFDEF __VAX__                  # __VAX__\n.IFDEF LARGE                        # LARGE\nLARGE_VAX = 1\n.ENDIF                              # LARGE\n.IFDEF VAXC_OR_FORCE_VAXC           # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                             # GNUC\nVAX_MULTI_CMPL = 1\n.ENDIF                                  # GNUC\n.ENDIF                              # VAXC_OR_FORCE_VAXC\n.ELSE                           # __VAX__\n.IFDEF VAXC_OR_FORCE_VAXC           # VAXC_OR_FORCE_VAXC\nNON_VAX_CMPL = 1\n.ELSE                               # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                             # GNUC\nNON_VAX_CMPL = 1\n.ENDIF                                  # GNUC\n.ENDIF                              # VAXC_OR_FORCE_VAXC\n.ENDIF                          # __VAX__\n\n# Shortcut to include BZIP2 support from the optional bzip2 source subdir\n# in the UnZip source location.\n\nBZ2DIR_BIN = SYS$DISK:[.BZIP2.$(DESTM)]\nBZ2_OLB = LIBBZ2_NS.OLB\nLIB_BZ2_LOCAL = $(BZ2DIR_BIN)$(BZ2_OLB)\n\n.IFDEF USEBZ2                   # USEBZ2\n.IFDEF IZ_BZIP2                     # IZ_BZIP2\n.ELSE                               # IZ_BZIP2\nIZ_BZIP2 = SYS$DISK:[.BZIP2]\nLIB_BZ2_DEP = $(LIB_BZ2_LOCAL)\nBUILD_BZIP2 = 1\n.ENDIF                              # IZ_BZIP2\n.ENDIF                          # USEBZ2\n\n# Complain about any problems (and die) if warranted.  Otherwise, show\n# optional package directories being used, and the destination\n# directory.  Make the destination directory, if necessary.\n\n.FIRST\n.IFDEF __MMK__                  # __MMK__\n\t@ write sys$output \"\"\n.ENDIF                          # __MMK__\n.IFDEF UNK_DEST                 # UNK_DEST\n\t@ write sys$output -\n \"   Unknown system architecture.\"\n.IFDEF __MMK__                      # __MMK__\n\t@ write sys$output -\n \"   MMK on IA64?  Try adding \"\"/MACRO = __IA64__\"\".\"\n.ELSE                               # __MMK__\n\t@ write sys$output -\n \"   MMS too old?  Try adding \"\"/MACRO = MMS$ARCH_NAME=ALPHA\"\",\"\n\t@ write sys$output -\n \"   or \"\"/MACRO = MMS$ARCH_NAME=IA64\"\", or \"\"/MACRO = MMS$ARCH_NAME=VAX\"\",\"\n\t@ write sys$output -\n \"   as appropriate.  (Or try a newer version of MMS.)\"\n.ENDIF                              # __MMK__\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                           # UNK_DEST\n.IFDEF VAX_MULTI_CMPL               # VAX_MULTI_CMPL\n\t@ write sys$output -\n \"   Macro \"\"GNUC\"\" is incompatible with \"\"VAXC\"\" or \"\"FORCE_VAXC\"\".\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                               # VAX_MULTI_CMPL\n.IFDEF NON_VAX_CMPL                     # NON_VAX_CMPL\n\t@ write sys$output -\n \"   Macros \"\"GNUC\"\", \"\"VAXC\"\", and \"\"FORCE_VAXC\"\" are valid only on VAX.\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                                   # NON_VAX_CMPL\n.IFDEF LARGE_VAX                            # LARGE_VAX\n\t@ write sys$output -\n \"   Macro \"\"LARGE\"\" is invalid on VAX.\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                                       # LARGE_VAX\n.IFDEF IZ_BZIP2                                 # IZ_BZIP2\n.IFDEF BUILD_BZIP2                                  # BUILD_BZIP2\n\t@ if (f$search( \"$(IZ_BZIP2)bzlib.h\") .eqs. \"\") then -\n\t   write sys$output \"   Can not find header file $(IZ_BZIP2)bzlib.h\"\n\t@ if (f$search( \"$(IZ_BZIP2)bzlib.h\") .eqs. \"\") then -\n\t   write sys$output \"\"\n\t@ if (f$search( \"$(IZ_BZIP2)bzlib.h\") .eqs. \"\") then -\n\t   I_WILL_DIE_NOW.  /$$$$INVALID$$$$\n\t@ write sys$output \"   BZIP2 dir: $(BZ2DIR_BIN)\"\n\t@ define lib_bzip2 $(BZ2DIR_BIN)\n\t@ if (f$search( \"$(IZ_BZIP2)$(DESTM).dir\") .eqs. \"\") then -\n\t   create /directory $(BZ2DIR_BIN)\n.ELSE                                               # BUILD_BZIP2\n\t@ @[.VMS]FIND_BZIP2_LIB.COM $(IZ_BZIP2) $(SEEK_BZ) $(BZ2_OLB) lib_bzip2\n\t@ if (f$trnlnm( \"lib_bzip2\") .eqs. \"\") then -\n\t   write sys$output \"   Can not find BZIP2 object library.\"\n\t@ if (f$trnlnm( \"lib_bzip2\") .eqs. \"\") then -\n\t   write sys$output \"\"\n\t@ if (f$trnlnm( \"lib_bzip2\") .eqs. \"\") then -\n\t   I_WILL_DIE_NOW.  /$$$$INVALID$$$$\n\t@ write sys$output \"   BZIP2 dir: ''f$trnlnm( \"lib_bzip2\")'\"\n.ENDIF                                              # BUILD_BZIP2\n\t@ write sys$output \"\"\n\t@ define incl_bzip2 $(IZ_BZIP2)\n.ENDIF                                          # IZ_BZIP2\n.IFDEF IZ_ZLIB                                  # IZ_ZLIB\n\t@ @[.VMS]FIND_BZIP2_LIB.COM $(IZ_ZLIB) $(SEEK_BZ) LIBZ.OLB lib_zlib\n\t@ if (f$trnlnm( \"lib_zlib\") .eqs. \"\") then -\n\t   write sys$output \"   Can not find ZLIB object library.\"\n\t@ if (f$trnlnm( \"lib_zlib\") .eqs. \"\") then -\n\t   write sys$output \"\"\n\t@ if (f$trnlnm( \"lib_zlib\") .eqs. \"\") then -\n\t   I_WILL_DIE_NOW.  /$$$$INVALID$$$$\n\t@ write sys$output \"   ZLIB dir:  ''f$trnlnm( \"lib_zlib\")'\"\n\t@ write sys$output \"\"\n\t@ define incl_zlib $(IZ_ZLIB)\n\t@ @[.VMS]FIND_BZIP2_LIB.COM $(IZ_ZLIB) -\n\t   contrib.infback9 infback9.h incl_zlib_contrib_infback9\n.ENDIF                                          # IZ_ZLIB\n\t@ write sys$output \"   Destination: [.$(DEST)]\"\n\t@ write sys$output \"\"\n\tif (f$search( \"$(DEST).DIR;1\") .eqs. \"\") then -\n\t create /directory [.$(DEST)]\n.ENDIF                                      # LARGE_VAX\n.ENDIF                                  # NON_VAX_CMPL\n.ENDIF                              # VAX_MULTI_CMPL\n.ENDIF                          # UNK_DEST\n\n# BZIP2 options.\n\n.IFDEF IZ_BZIP2                 # IZ_BZIP2\nCDEFS_BZ = , USE_BZIP2\nCFLAGS_INCL = /include = ([], [.VMS])\nLIB_BZIP2_OPTS = lib_bzip2:$(BZ2_OLB) /library,\n.ENDIF                          # IZ_BZIP2\n\n# ZLIB options.\n\n.IFDEF IZ_ZLIB                  # IZ_ZLIB\nCDEFS_ZL = , USE_ZLIB\n.IFDEF CFLAGS_INCL                  # CFLAGS_INCL\n.ELSE                               # CFLAGS_INCL\nCFLAGS_INCL = /include = ([], [.VMS])\n.ENDIF                              # CFLAGS_INCL\nLIB_ZLIB_OPTS = LIB_ZLIB:LIBZ.OLB /library,\n.ELSE                           # IZ_ZLIB\n.IFDEF CFLAGS_INCL                  # CFLAGS_INCL\n.ELSE                               # CFLAGS_INCL\nCFLAGS_INCL = /include = []\n.ENDIF                              # CFLAGS_INCL\n.ENDIF                          # IZ_ZLIB\n\n# DBG options.\n\n.IFDEF DBG                      # DBG\nCFLAGS_DBG = /debug /nooptimize\nLINKFLAGS_DBG = /debug /traceback\n.ELSE                           # DBG\nCFLAGS_DBG =\nLINKFLAGS_DBG = /notraceback\n.ENDIF                          # DBG\n\n# Large-file options.\n\n.IFDEF LARGE                    # LARGE\nCDEFS_LARGE = , LARGE_FILE_SUPPORT\n.ENDIF                          # LARGE\n\n# C compiler defines.\n\n.IFDEF LOCAL_UNZIP\nC_LOCAL_UNZIP = , $(LOCAL_UNZIP)\n.ENDIF\n\nCDEFS = VMS $(CDEFS_BZ) $(CDEFS_LARGE) $(CDEFS_ZL) $(C_LOCAL_UNZIP)\n\nCDEFS_UNX = /define = ($(CDEFS))\n\nCDEFS_CLI = /define = ($(CDEFS), VMSCLI)\n\nCDEFS_SFX = /define = ($(CDEFS), SFX)\n\nCDEFS_SFX_CLI = /define = ($(CDEFS), SFX, VMSCLI)\n\n# Other C compiler options.\n\n.IFDEF DECC                             # DECC\nCFLAGS_ARCH = /decc /prefix = (all)\n.ELSE                                   # DECC\n.IFDEF FORCE_VAXC                           # FORCE_VAXC\nCFLAGS_ARCH = /vaxc\n.IFDEF VAXC                                     # VAXC\n.ELSE                                           # VAXC\nVAXC = 1\n.ENDIF                                          # VAXC\n.ELSE                                       # FORCE_VAXC\nCFLAGS_ARCH =\n.ENDIF                                      # FORCE_VAXC\n.ENDIF                                  # DECC\n\n# LINK (share) library options.\n# Omit shareable image options file for NOSHARE.\n\n.IFDEF VAXC_OR_FORCE_VAXC               # VAXC_OR_FORCE_VAXC\n.IFDEF NOSHARE                              # NOSHARE\nOPT_FILE =\nLFLAGS_ARCH =\n.ELSE                                       # NOSHARE\nOPT_FILE = [.$(DEST)]VAXCSHR.OPT\nLFLAGS_ARCH = $(OPT_FILE) /options,\n.ENDIF                                      # NOSHARE\n.ELSE                                   # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                                 # GNUC\nLFLAGS_GNU = GNU_CC:[000000]GCCLIB.OLB /LIBRARY\n.IFDEF NOSHARE                                  # NOSHARE\nOPT_FILE =\nLFLAGS_ARCH = $(LFLAGS_GNU),\n.ELSE                                           # NOSHARE\nOPT_FILE = [.$(DEST)]VAXCSHR.OPT\nLFLAGS_ARCH = $(LFLAGS_GNU), SYS$DISK:$(OPT_FILE) /options,\n.ENDIF                                          # NOSHARE\n.ELSE                                       # GNUC\nOPT_FILE =\nLFLAGS_ARCH =\n.ENDIF                                      # GNUC\n.ENDIF                                  # VAXC_OR_FORCE_VAXC\n\n# LINK NOSHARE options.\n\n.IFDEF NOSHARE                  # NOSHARE\n.IFDEF __ALPHA__                    # __ALPHA__\nNOSHARE_OPTS = , SYS$LIBRARY:STARLET.OLB /LIBRARY\\\n /INCLUDE = CMA$TIS /NOSYSSHR\n.ELSE                               # __ALPHA__\n.IFDEF __IA64__                         # __IA64__\nNOSHARE_OPTS = , SYS$LIBRARY:STARLET.OLB /LIBRARY\\\n /INCLUDE = CMA$TIS /NOSYSSHR\n.ELSE                                   # __IA64__\nOLDVAX_OLDVAX = 1\n.IFDEF DECC                                 # DECC\n.IFDEF OLDVAX_$(NOSHARE)                        # OLDVAX_$(NOSHARE)\nNOSHARE_OPTS = , SYS$LIBRARY:DECCRTL.OLB /LIBRARY\\\n /INCLUDE = CMA$TIS /NOSYSSHR\n.ELSE                                           # OLDVAX_$(NOSHARE)\nNOSHARE_OPTS = , SYS$LIBRARY:DECCRTL.OLB /LIBRARY\\\n /INCLUDE = (CMA$TIS, CMA$TIS_VEC) /NOSYSSHR\n.ENDIF                                          # OLDVAX_$(NOSHARE)\n.ELSE                                       # DECC\n.IFDEF OLDVAX_$(NOSHARE)                        # OLDVAX_$(NOSHARE)\nNOSHARE_OPTS = , SYS$LIBRARY:VAXCRTL.OLB /LIBRARY,\\\n SYS$LIBRARY:IMAGELIB.OLB /LIBRARY /NOSYSSHR\n.ELSE                                           # OLDVAX_$(NOSHARE)\nNOSHARE_OPTS = , SYS$LIBRARY:VAXCRTL.OLB /LIBRARY,\\\n SYS$LIBRARY:DECCRTL.OLB /LIBRARY /INCLUDE = CMA$TIS,\\\n SYS$LIBRARY:IMAGELIB.OLB /LIBRARY /NOSYSSHR\n.ENDIF                                          # OLDVAX_$(NOSHARE)\n.ENDIF                                      # DECC\n.ENDIF                                  # __IA64__\n.ENDIF                              # __ALPHA__\n.ELSE                           # NOSHARE\nNOSHARE_OPTS =\n.ENDIF                          # NOSHARE\n\n# LIST options.\n\n.IFDEF LIST                     # LIST\n.IFDEF DECC                         # DECC\nCFLAGS_LIST = /list = $*.LIS /show = (all, nomessages)\n.ELSE                               # DECC\nCFLAGS_LIST = /list = $*.LIS /show = (all)\n.ENDIF                              # DECC\nLINKFLAGS_LIST = /map = $*.MAP /cross_reference /full\n.ELSE                           # LIST\nCFLAGS_LIST =\nLINKFLAGS_LIST =\n.ENDIF                          # LIST\n\n# Common CFLAGS and LINKFLAGS.\n\nCFLAGS = \\\n $(CFLAGS_ARCH) $(CFLAGS_DBG) $(CFLAGS_INCL) $(CFLAGS_LIST) $(CCOPTS) \\\n /object = $(MMS$TARGET)\n\nLINKFLAGS = \\\n $(LINKFLAGS_DBG) $(LINKFLAGS_LIST) $(LINKOPTS) \\\n /executable = $(MMS$TARGET)\n\n# Object library module=object lists.\n\n#    Primary object library, [].\n\nMODS_OBJS_LIB_UNZIP_N = \\\n CRC32=[.$(DEST)]CRC32.OBJ \\\n CRYPT=[.$(DEST)]CRYPT.OBJ \\\n ENVARGS=[.$(DEST)]ENVARGS.OBJ \\\n EXPLODE=[.$(DEST)]EXPLODE.OBJ \\\n EXTRACT=[.$(DEST)]EXTRACT.OBJ \\\n FILEIO=[.$(DEST)]FILEIO.OBJ \\\n GLOBALS=[.$(DEST)]GLOBALS.OBJ \\\n INFLATE=[.$(DEST)]INFLATE.OBJ \\\n LIST=[.$(DEST)]LIST.OBJ \\\n MATCH=[.$(DEST)]MATCH.OBJ \\\n PROCESS=[.$(DEST)]PROCESS.OBJ \\\n TTYIO=[.$(DEST)]TTYIO.OBJ \\\n UBZ2ERR=[.$(DEST)]UBZ2ERR.OBJ \\\n UNREDUCE=[.$(DEST)]UNREDUCE.OBJ \\\n UNSHRINK=[.$(DEST)]UNSHRINK.OBJ \\\n ZIPINFO=[.$(DEST)]ZIPINFO.OBJ\n\n#    Primary object library, [.VMS].\n\nMODS_OBJS_LIB_UNZIP_V = \\\n VMS=[.$(DEST)]VMS.OBJ\n\nMODS_OBJS_LIB_UNZIP = $(MODS_OBJS_LIB_UNZIP_N) $(MODS_OBJS_LIB_UNZIP_V)\n\n#    CLI object library, [.VMS].\n\nMODS_OBJS_LIB_UNZIPCLI_C_V = \\\n CMDLINE=[.$(DEST)]CMDLINE.OBJ\n\nMODS_OBJS_LIB_UNZIPCLI_CLD_V = \\\n VMS_UNZIP_CLD=[.$(DEST)]UNZ_CLI.OBJ\n\nMODS_OBJS_LIB_UNZIP_CLI = \\\n $(MODS_OBJS_LIB_UNZIPCLI_C_V) \\\n $(MODS_OBJS_LIB_UNZIPCLI_CLD_V)\n\n# SFX object library, [].\n\nMODS_OBJS_LIB_UNZIPSFX_N = \\\n CRC32$(GCC_)=[.$(DEST)]CRC32_.OBJ \\\n CRYPT$(GCC_)=[.$(DEST)]CRYPT_.OBJ \\\n EXTRACT$(GCC_)=[.$(DEST)]EXTRACT_.OBJ \\\n FILEIO$(GCC_)=[.$(DEST)]FILEIO_.OBJ \\\n GLOBALS$(GCC_)=[.$(DEST)]GLOBALS_.OBJ \\\n INFLATE$(GCC_)=[.$(DEST)]INFLATE_.OBJ \\\n MATCH$(GCC_)=[.$(DEST)]MATCH_.OBJ \\\n PROCESS$(GCC_)=[.$(DEST)]PROCESS_.OBJ \\\n TTYIO$(GCC_)=[.$(DEST)]TTYIO_.OBJ \\\n UBZ2ERR$(GCC_)=[.$(DEST)]UBZ2ERR_.OBJ\n\n# SFX object library, [.VMS].\n\nMODS_OBJS_LIB_UNZIPSFX_V = \\\n VMS$(GCC_)=[.$(DEST)]VMS_.OBJ\n\nMODS_OBJS_LIB_UNZIPSFX = \\\n $(MODS_OBJS_LIB_UNZIPSFX_N) \\\n $(MODS_OBJS_LIB_UNZIPSFX_V)\n\n# SFX object library, [.VMS] (no []).\n\nMODS_OBJS_LIB_UNZIPSFX_CLI_C_V = \\\n CMDLINE$(GCC_)=[.$(DEST)]CMDLINE_.OBJ\n\nMODS_OBJS_LIB_UNZIPSFX_CLI_CLD_V = \\\n VMS_UNZIP_CLD=[.$(DEST)]UNZ_CLI.OBJ\n\nMODS_OBJS_LIB_UNZIPSFX_CLI = \\\n $(MODS_OBJS_LIB_UNZIPSFX_CLI_C_V) \\\n $(MODS_OBJS_LIB_UNZIPSFX_CLI_CLD_V)\n\n# Executables.\n\nUNZIP = [.$(DEST)]UNZIP.EXE\n\nUNZIP_CLI = [.$(DEST)]UNZIP_CLI.EXE\n\nUNZIPSFX = [.$(DEST)]UNZIPSFX.EXE\n\nUNZIPSFX_CLI = [.$(DEST)]UNZIPSFX_CLI.EXE\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/find_bzip2_lib.com",
    "content": "$!                                              28 December 2006.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$! Find the BZIP2 object library under P1, starting in the [.'P2']\n$! destination directory.  (We assume, initially, that the BZIP2\n$! directory has a destination directory structure like ours.)\n$!\n$! Set the P4 logical name to the directory where it was found.\n$! P5 and P6 may be used for qualifiers on the DEFINE command.\n$!\n$ bz_orig = p1\n$ dest = p2\n$ libbz2 = p3\n$!\n$! Remove any trailing colon, to allow logical name translation.\n$!\n$ bz_dev_dir = \"\"\n$ bz_base = bz_orig\n$ if (f$extract( (f$length( bz_base)- 1), 1, bz_base) .eqs. \":\")\n$ then\n$     bz_base = bz_base- \":\"\n$ endif\n$!\n$ bz_base_eqv = f$trnlnm( bz_base)\n$ if (bz_base_eqv .nes. \"\")\n$ then\n$     bz_orig = bz_base_eqv\n$     bz_base = bz_base_eqv\n$ endif\n$ bz_base = bz_base- \"]\"\n$!\n$! Candidate 1 = the actual analogue destination directory.\n$!\n$ bz_dev_dir_cand = bz_base+ \".\"+ dest+ \"]\"\n$ lib_cand = bz_dev_dir_cand+ libbz2\n$ if (f$search( lib_cand) .nes. \"\")\n$ then\n$     bz_dev_dir = bz_dev_dir_cand\n$ else\n$!\n$!     Candidate 2 = the actual analogue destination directory + \"L\".\n$!\n$     bz_dev_dir_cand = bz_base+ \".\"+ dest+ \"L]\"\n$     lib_cand = bz_dev_dir_cand+ libbz2\n$     if (f$search( lib_cand) .nes. \"\")\n$     then\n$         bz_dev_dir = bz_dev_dir_cand\n$     else\n$!\n$!         Candidate 3 = the actual user-specified directory.\n$!\n$         bz_dev_dir_cand = bz_orig\n$         lib_cand = bz_dev_dir_cand+ libbz2\n$         if (f$search( lib_cand) .nes. \"\")\n$         then\n$             bz_dev_dir = bz_dev_dir_cand\n$         endif\n$     endif\n$ endif\n$!\n$ if (bz_dev_dir .nes. \"\")\n$ then\n$     if (p4 .eqs. \"\")\n$     then\n$         write sys$output bz_dev_dir\n$     else\n$         define 'p5' 'p4' 'bz_dev_dir' 'p6'\n$     endif\n$ endif\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/hlp_lib_next.com",
    "content": "$!                                              21 November 2004.  SMS.\n$!\n$!    HLP_LIB_NEXT.COM\n$!\n$!    Find the next available HLP$LIBRARY[_*] logical name.\n$!\n$ base = \"HLP$LIBRARY\"\n$ candidate = base$ i = 0\n$!\n$ loop_top:\n$    if (i .gt. 0) then candidate = base+ \"_\"+ f$string( i)\n$    i = i+ 1\n$    if (f$trnlnm( candidate) .nes. \"\") then goto loop_top\n$!\n$ write sys$output candidate\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/infback9.h",
    "content": "/* 2008-07-29 SMS.\n * VMS-specific INFBACK9.H jacket header file to help find the\n * relatively obscure actual header file.\n *\n * The logical name INCL_ZLIB_CONTRIB_INFBACK9 must point to the ZLIB\n * source subdirectory where infback9.h is situated.\n */\n\n#include \"INCL_ZLIB_CONTRIB_INFBACK9:INFBACK9.H\"\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/makesfx.com",
    "content": "$!\n$!  MAKESFX.COM:  command-procedure to create self-extracting ZIP archives\n$!                usage:  @MAKESFX foo    (foo.zip -> foo.exe)\n$!\n$!  Change history:\n$!\n$!  Date      Who   What\n$!  --------  ----  -----------------------------------------------------------\n$!  19940804  MPJZ  Created\n$!  19940810  GRR   Removed superflous creation of name symbol\n$!  20000113  MPJZ  Better symbol check, fixed bug in zip \"-A\" check\n$!\n$!  MPJZ: Martin P.J. Zinser\n$!\n$!  For this to work a symbol unzipsfx has to be defined which contains the\n$!  location of the unzip stub (e.g., unzipsfx:== device:[dir]unzipsfx.exe)\n$!\n$!  The zipfile given in p1 will be concatenated with unzipsfx and given a\n$!  filename extension of .exe.  The default file extension for p1 is .zip\n$!\n$!  Use at your own risk, there is no guarantee here.  If it doesn't work,\n$!  blame me (zinser@decus.de), not the people from Info-ZIP.\n$!\n$!-----------------------------------------------------------------------------\n$!\n$! First check stub related stuff\n$!\n$ if (f$type(unzipsfx).nes.\"STRING\")\n$ then\n$   type sys$input\nYou need to define the symbol \"unzipsfx\" to point to the location of the\nunzipsfx stub before invoking this procedure.\nExiting now...\n$   exit 2\n$ endif\n$ usfx = f$parse(unzipsfx) - \";\"\n$ if (f$search(usfx).eqs.\"\")\n$ then\n$   write sys$output \"The unzipsfx stub can not be found on the location\"\n$   write sys$output \"pointed to by the unzipsfx symbol -- ''usfx'\"\n$   write sys$output \"Exiting now\"\n$   exit 2\n$ endif\n$!\n$! Now check the input file\n$!\n$ if (p1.eqs.\"\")\n$ then\n$   type sys$input\nRequired parameter input-file missing\nExiting now...\n$   exit 2\n$ endif\n$ inf = p1\n$ file = f$parse(inf,,,\"DEVICE\") + f$parse(inf,,,\"DIRECTORY\") + -\n         f$parse(inf,,,\"NAME\")\n$ finf = file + f$parse(inf,\".ZIP\",,\"TYPE\") + f$parse(inf,,,\"VERSION\")\n$ if (f$search(finf).eqs.\"\")\n$ then\n$   write sys$output \"Input file ''finf' does not exist\"\n$   exit 2\n$ endif\n$!\n$! Finally create the self-extracting archive\n$!\n$ copy 'usfx','finf' 'file'.exe\n$!\n$! Zip \"-A\" will make the resulting archive compatible with other\n$! unzip programs, but is not essential for running the exe.\n$!\n$ if (f$type(zip).eqs.\"STRING\") then zip \"-A\" 'file'.exe\n$ exit\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/mod_dep.com",
    "content": "$!                                              3 March 2005.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$!    Modify a dependencies file (P1), changing the object file name to\n$!    P2.\n$!    P3 = output file specification.\n$!\n$!\n$ prefix = f$edit( p3, \"COLLAPSE\")\n$!\n$! Strip any device:[directory] from P2.\n$!\n$ obj_name = f$parse( P2, , , \"NAME\", \"SYNTAX_ONLY\")+ -\n   f$parse( P2, , , \"TYPE\", \"SYNTAX_ONLY\")\n$!\n$ open /read /error = end_main deps_in 'p1'\n$ open /write /error = end_main deps_out 'p3'\n$ on error then goto loop_main_end\n$ loop_main_top:\n$     read /error = loop_main_end deps_in line\n$     line_reduced = f$edit( line, \"COMPRESS, TRIM\")\n$     colon = f$locate( \" : \", line_reduced)\n$     line = obj_name+ f$extract( colon, 2000, line)\n$     write deps_out \"''line'\"\n$ goto loop_main_top\n$!\n$ loop_main_end:\n$ close deps_in\n$ close deps_out\n$!\n$ end_main:\n$!\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unixio_gcc.h",
    "content": "/* 2004-12-12 SMS.\n *\n * Emergency replacement UNIXIO.H for GNU C, for use as needed.\n * Install as GNU_CC_INCLUDE:[000000]UNIXIO.H\n */\n\n#ifndef __UNIXIO_LOADED\n#define __UNIXIO_LOADED 1\n\n#include <sys/types.h>\n\n#include <stdlib.h>\n\n#ifndef SEEK_SET\n# define SEEK_SET 0\n#endif /* ndef SEEK_SET */\n\n#ifndef SEEK_CUR\n# define SEEK_CUR 1\n#endif /* ndef SEEK_CUR */\n\n#ifndef SEEK_END\n# define SEEK_END 2\n#endif /* ndef SEEK_END */\n\n#endif  /* ndef __UNIXIO_LOADED */\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unixlib_gcc.h",
    "content": "/* 2004-12-12 SMS.\n *\n * Emergency replacement UNIXLIB.H for GNU C, for use as needed.\n * Install as GNU_CC_INCLUDE:[000000]UNIXLIB.H\n */\n\n#ifndef __UNIXLIB_LOADED\n#define __UNIXLIB_LOADED 1\n\n#include <sys/types.h>\n#include <stdlib.h>\n\ntypedef struct stat stat_t;\n\n#endif  /* ndef __UNIXLIB_LOADED */\n\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unz_cli.cld",
    "content": "\tModule\t\tVMS_UNZIP_CLD\n\tIdent\t\t\"03-003\"\n\nDefine\tVerb\t\tUNZIP\n\tParameter\tP1, Label=ZIPFILE, Prompt=\"Zip file\"\n\tParameter\tP2, Label=INFILE, VALUE(LIST), Prompt=\"Files to UnZip\"\n\tQualifier\tBINARY, VALUE(TYPE=CONVBIN_KEYWORDS), Negatable\n\tQualifier\tTEXT, VALUE(TYPE=CONVTXT_KEYWORDS, LIST), Negatable\n\tQualifier\tSCREEN, Negatable\n\tQualifier\tDIRECTORY, VALUE(REQUIRED,TYPE=$FILE), Nonnegatable\n\tQualifier\tFRESHEN, Negatable\n\tQualifier\tHELP, Nonnegatable\n\tQualifier\tJUNK, Negatable\n\tQualifier\tLIST, Nonnegatable\n\tQualifier\tBRIEF, Nonnegatable, Default\n\tQualifier\tFULL, VALUE(TYPE=FULL_MODIFIER), Nonnegatable\n\tQualifier\tEXISTING, VALUE(REQUIRED, TYPE=EXISTING_KEYWORDS),\n\t\t\tNonnegatable\n\tQualifier\tOVERWRITE, Negatable\n\tQualifier\tQUIET, VALUE(TYPE=QUIET_MODIFIER), Nonnegatable\n\tQualifier\tTEST, Negatable\n\tQualifier\tPIPE, Nonnegatable\n\tQualifier\tPASSWORD, VALUE(REQUIRED), Nonnegatable\n\tQualifier\tTIMESTAMP, Nonnegatable\n\tQualifier\tTRAVERSE_DIRS, Negatable\n\tQualifier\tUPPERCASE, Negatable\n\tQualifier\tUPDATE, Negatable\n\tQualifier\tVERSION, Negatable\n\tQualifier\tRESTORE, VALUE(TYPE=RESTORE_KEYWORDS, LIST), Negatable\n\tQualifier\tCOMMENT, Negatable\n\tQualifier\tEXCLUDE, VALUE(LIST), Nonnegatable\n\tQualifier\tCASE_INSENSITIVE, Negatable\n\tQualifier\tLOWERCASE, Negatable\n\tQualifier\tPAGE, Negatable\n\tQualifier\tDOT_VERSION, Negatable\n\tQualifier\tODS2, Negatable\n\tQualifier\tYYZ_UNZIP, NonNegatable, Default\n\tQualifier\tZIPINFO, Syntax=INFORMATION, NonNegatable\n\tDisAllow\tBRIEF and FULL\n\tDisAllow\tDIRECTORY and SCREEN\n\tDisAllow\tBINARY and TEXT.ALL\n\tDisAllow\tBINARY.ALL and TEXT\n\tDisAllow\t(OVERWRITE or (neg OVERWRITE)) and EXISTING\n\tDisAllow\t(neg RESTORE) and RESTORE.DATE\n\tDisAllow\t(neg RESTORE) and (neg RESTORE.DATE)\n\tDisAllow\t(neg RESTORE) and RESTORE.OWNER_PROT\n\tDisAllow\t(neg RESTORE) and (neg RESTORE.OWNER_PROT)\n\tDisAllow\t(neg RESTORE.DATE) and RESTORE.DATE.ALL\n\tDisAllow\t(neg RESTORE.DATE) and RESTORE.DATE.FILES\n\tDisAllow\tTEXT.ALL and TEXT.AUTO\n\tDisAllow\tTEXT.AUTO and TEXT.NONE\n\tDisAllow\tTEXT.NONE and TEXT.ALL\n\tDisAllow\tTEXT.NONE and TEXT.STMLF\n\tDisAllow\t(neg TEXT) and TEXT.STMLF\n\tDisAllow\tZIPINFO and HELP\n\nDefine\tType\t\tCONVBIN_KEYWORDS\n\tKeyword\t\tAUTO, DEFAULT\n\tKeyword\t\tALL\n\tKeyword\t\tNONE\n\nDefine\tType\t\tCONVTXT_KEYWORDS\n\tKeyword\t\tAUTO, DEFAULT\n\tKeyword\t\tALL\n\tKeyword\t\tNONE\n\tKeyword\t\tSTMLF\n\nDefine\tType\t\tEXISTING_KEYWORDS\n\tKeyword\t\tNEW_VERSION\n\tKeyword\t\tOVERWRITE\n\tKeyword\t\tNOEXTRACT\n\nDefine\tType\t\tRESTORE_KEYWORDS\n\tKeyword\t\tDATE, VALUE(TYPE=RESTOREDATE_KEYS, Required),\n\t\t\tNegatable\n\tKeyword\t\tOWNER_PROT, Default, Negatable\n\nDefine\tType\t\tRESTOREDATE_KEYS\n        Keyword\t\tFILES, DEFAULT\n\tKeyword\t\tALL\n\nDefine\tType\t\tQUIET_MODIFIER\n\tKeyword\t\tSUPER\n\nDefine\tType\t\tFULL_MODIFIER\n\tKeyword\t\tDIAGNOSTICS\n\nDefine Syntax INFORMATION\n\tParameter\tP1, Label=ZIPFILE, Prompt=\"Zip file\"\n\tParameter\tP2, Label=INFILE, VALUE(LIST), Prompt=\"Files to display\"\n\tQualifier\tZIPINFO, NonNegatable, Default\n\tQualifier\tONE_LINE, Nonnegatable\n\tQualifier\tSHORT, Nonnegatable\n\tQualifier\tMEDIUM, Nonnegatable\n\tQualifier\tLONG, Nonnegatable\n\tQualifier\tVERBOSE, Nonnegatable\n\tQualifier\tHEADER, Nonnegatable\n\tQualifier\tCOMMENT, Nonnegatable\n\tQualifier\tTOTALS, Nonnegatable\n\tQualifier\tTIMES, Nonnegatable\n\tQualifier\tEXCLUDE, VALUE(LIST), Nonnegatable\n\tQualifier\tCASE_INSENSITIVE, Negatable\n\tQualifier\tPAGE, Negatable\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unzip.opt",
    "content": "Ident = \"UnZip 6.0\"\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unzip_cli.help",
    "content": ".!\n.!  File:       UNZIP_CLI.HELP\n.!\n.!  Author:     Hunter Goatley\n.!\n.!  Date:       12 Jul 94 (orig. UNZIP.RNH, 23 Oct 91)\n.!\n.!  Description:\n.!\n.!      TPU-processable source file to produce VMS on-line help for\n.!      portable UnZip.  Adapted from UNZIP.RNH, originally based on\n.!      UNZIP.MAN (now UNZIP.TXT).\n.!\n.!      To build:\n.!          $ EDIT /TPU/NOSECTION/NODISPLAY/COMMAND=CVTHELP.TPU UNZIP_CLI.HELP\n.!          $ RUNOFF /OUT=UNZIP.HLP UNZIP_CLI.RNH\n.!          $ LIBR /HELP/INSERT libr UNZIP\n.!\n.!  Modification history:\n.!\n.!      02-001          Hunter Goatley          12-JUL-1994 16:59\n.!              Genesis.\n.!      02-002          Cave Newt               14-JUL-1994 11:36\n.!              Fixed /*TEXT options and added/removed various options.\n.!      02-003          Cave Newt               28-JUL-1994 08:54\n.!              Removed semicolons from comments and moved /ZIPINFO.\n.!      02-004          Christian Spieler       06-OCT-1995 02:02\n.!              Changed to conform to revised .CLD definition.\n.!      02-005          Christian Spieler       06-FEB-1996 02:20\n.!              Added description of /HELP qualifier.\n.!      02-006          Christian Spieler       12-MAY-1996 00:50\n.!              Some clarifications/cleanups.\n.!      02-007          Christian Spieler       04-MAR-1997 22:25\n.!              Added /[NO]CASE_INSENSITIVE to ZipInfo mode;\n.!              documented the new /PASSWORD=\"decryption_key\" option.\n.!      02-007          Christian Spieler       22-JUL-1997 22:37\n.!              Formatting changes (prevent line wraps);\n.!              added \"Exit_Codes\" subtopic (no version number change).\n.!      02-007          Christian Spieler       28-APR-2000 03:22\n.!              Changed references to plaintext UnZip documentation file\n.!              into UNZIP.TXT (no version number change).\n.!      02-007          Hunter Goatley          07-Feb-2001 15:43\n.!              Reformatted qualifier item headers to show negated form of\n.!              option qualifier on separate line (no version number change).\n.!      02-008          Christian Spieler       18-Apr-2001 22:29\n.!              Added description for extended functionality of -b option.\n.!      02-009          Christian Spieler       10-Dec-2001 13:37\n.!              Added description for new /TRAVERSE_DIRS option.\n.!      02-010          Steven Schweda          28-Jan-2005 16:16:36\n.!              Added /TIMESTAMP (-T) qualifier.\n.!      02-010          Christian Spieler       29-Jan-2005 01:50\n.!              Completed description of -T qualifier (also for UNIX style).\n.!      02-011          Steven Schweda          14-FEB-2005 20:04\n.!              Added /DOT_VERSION (-Y) and /ODS2 (-2) qualifiers.\n.!      02-012          Steven Schweda          07-JUL-2006 01:30\n.!              Added /TEXT = STMLF (-s) qualifier.\n.!      02-012          Christian Spieler       04-Mar-2007 14:39\n.!              Changed -s qualifier into -S;\n.!              updated documentation of UnZip's exit codes.\n.!      03-002          S. Schweda, C. Spieler  09-Jan-2008 03:35\n.!              Added documentation of extended /RESTORE=(...) qualifier.\n.!      03-003          S. Schweda, C. Spieler  13-Sep-2008 20:00\n.!              Added /EXISTING qualifier.\n.!\n<INIT>\n<MAIN>\nUNZIP\n\nUnZip is used to extract files compressed and packaged by Zip (see HELP ZIP\nfor information on ZIP).\n\nFor a brief help on Zip and Unzip, run each without specifying any\nparameters on the command line (or apply the /HELP qualifier).\nTo get a brief help sceen about the alternate UNIX style command interface,\nrun each with the -h option applied.\n\nUNZIP will list, test, or extract from a ZIP archive.  ZIP archives are commonly\nfound on MS-DOS systems; a VMS version of ZIP can also be found here.\n\nArchive member extraction is implied by the absence of the /SCREEN (-c),\n/PIPE (-p), /TEST (-t), /TIMESTAMP (-T), /LIST (-l, -v) or /COMMENT (-z)\nqualifiers (options).\nAll archive members are processed unless a filespec is provided to\nspecify a subset of the archive members.\n<FORMAT>\nUNZIP zipfile [file[,...]] [/qualifiers]\n\n.!\f\n<TOPIC>\nParameters\n\n<PARAMETER>\nzipfile\n\n<PTEXT>\nFile specification for the ZIP archive(s) with optional wildcards. UnZip will\nperform actions specified for every zipfile matching the specification.\nThe default file specification is SYS$DISK:[].ZIP.\n\nNote that self-extracting ZIP files are supported; just specify the .EXE\nsuffix yourself.\n<TXETP>\n\n<PARAMETER>\nfile\n\n<PTEXT>\nAn optional comma-separated list of archive members to be processed;\nif no list is given, all archive members are processed.  Expressions\nmay be used to match multiple members.  Expressions should be enclosed\nin double-quotes to prevent interpretation by DCL.  Multiple filenames\nshould be separated by blanks.  Each file specification is similar to\na Unix egrep expression and may contain:\n\n<LITERAL>\n|*       matches a sequence of 0 or more characters\n|?       matches exactly 1 character\n|[...]   matches any single character found inside the brackets;\n|        ranges are specified by a beginning character, a hyphen,\n|        and an ending character.  If a '!' or '^' immediately\n|        follows the left bracket, then any character not in the\n|        given range is matched.\n|        Hint: To specify a verbatim left bracket '[', the\n|              three-character sequence \"[[]\" has to be used.\n<LARETIL>\n<TXETP>\n\n<QUALIFIERS>\n<QUALIFIER>\n/ZIPINFO\n\n/ZIPINFO\n\nDisplays information about the Zip archive and the files contained therein.\nThis function used to be provided by a separate ZipInfo program.\n\nThe following qualifiers may be specified with /ZIPINFO:\n\n<LITERAL>\n|  /SHORT                 Short UNIX \"ls -l\" format (default)\n|  /MEDIUM                Medium UNIX \"ls -l\" format\n|  /LONG                  Long UNIX \"ls -l\" format\n|  /VERBOSE               Verbose, multi-page format\n|  /ONE_LINE              Filenames only, one per line\n|  /HEADER                Print header lines\n|  /TOTALS                Print totals for files\n|  /TIMES                 Print file times in sortable decimal format\n|  /[NO]CASE_INSENSITIVE  Match filenames case-insensitively\n|  /[NO]PAGE              Page screen output through built-in \"more\"\n<LARETIL>\n<QUALIFIER>\n/BINARY\n\n/BINARY[=KEYWORD]\n<NEXT>\n/NOBINARY (default)\n\nSelects conversion to VMS \"standard\" binary file format for\nextracted files, which is \"fixed length 512 byte records,\nno record attributes\". When extracting to SYS$OUTPUT (/SCREEN\nor /PIPE qualifier), this qualifier deactivates the default\n\"text data\" conversion, instead.\nThe optional keywords recognized are:\n<LITERAL>\n|  AUTO     Automatically extracts files marked as \"binary\" (rather\n|           than \"text\") in standard VMS binary file format. (default)\n|  ALL      Extracts all files in standard VMS binary file format.\n|  NONE     Same as /NOBINARY.\n<LARETIL>\n\nNote that a combination of /BINARY[=AUTO] and /TEXT[=AUTO] is allowed.\n(see /TEXT qualifier)\n<QUALIFIER>\n/BRIEF\n\n/BRIEF (default)\n\nWhen used with /LIST, specifies that a brief listing of the archive's\ncontents is to be displayed.  A brief listing shows the length, date,\ntime, and file name for the files in the archive.\n<QUALIFIER>\n/CASE_INSENSITIVE\n\n/CASE_INSENSITIVE\n<NEXT>\n/NOCASE_INSENSITIVE (default)\n\nMatch filenames case-insensitively.  (Good default option under VMS.)\n<QUALIFIER>\n/COMMENT\n\n/COMMENT\n<NEXT>\n/NOCOMMENT\n\nDisplay the archive comment.\n<QUALIFIER>\n/DIRECTORY\n\n/DIRECTORY=directory-spec\n\nSpecifies the output directory where all the extracted files are to be\nplaced.\n<QUALIFIER>\n/DOT_VERSION\n\n/DOT_VERSION\n<NEXT>\n/NODOT_VERSION (default)\n\nCauses UnZip to treat archived file name endings of \".nnn\" (where \"nnn\"\nis a decimal number) as if they were VMS version numbers (\";nnn\").  (The\ndefault is to treat them as file types.)  Example: \"a.b.3\" -> \"a.b;3\".\n<QUALIFIER>\n/EXCLUDE\n\n/EXCLUDE=(file[,...])\n\nA comma-separated list of files to exclude when extracting files.\nIf multiple files are specified, the list should be included in\nparentheses.\n<QUALIFIER>\n/EXISTING\n\n/EXISTING = keyword\n\nValid keywords (exactly one must be specified) are:\n<LITERAL>\n|  NEW_VERSION   Create a new version of an existing file.\n|  OVERWRITE     Overwrite the same version of an existing file.\n|                (But only if the archive member name includes a\n|                version number.)\n|  NOEXTRACT     Do not extract.  An existing file is not affected.\n<LARETIL>\n\nWhen UnZip would extract an archive member, but the destination file\nalready exists, UnZip will, by default, ask the user what to do.\n/EXISTING lets the user specify on the command line what to do in this\nsituation, eliminating the interactive question(s).\n\nNOEXTRACT will always stop UnZip from extracting an archive member if\nthe destination file already exists.\n\nIf an archive member name does not include a VMS version number, or if\nUnZip is run with /NOVERSION (the default, causing it to ignore version\nnumbers), then either NEW_VERSION or OVERWRITE will cause UnZip to\ncreate a new version of the existing file.\n\nIf an archive member name does include a VMS version number, and if\nUnZip is run with /VERSION, then NEW_VERSION will cause UnZip to create\na new version of the existing file, and OVERWRITE will cause UnZip to\noverwrite the existing file which has the version specified by the\narchive member name.\n<QUALIFIER>\n/FRESHEN\n\n/FRESHEN\n<NEXT>\n/NOFRESHEN\n\nFreshen existing files; replace if newer.  Does not cause any new files to\nbe created.\n<QUALIFIER>\n/FULL\n\n/FULL\n\nWhen used with /LIST, specifies that a full listing of the archive's\ncontents is to be displayed.  A full listing shows the length,\ncompression method, compressed size, compression ratio, date,\ntime, CRC value, and file name for the files in the archive.\n<QUALIFIER>\n/HELP\n\n/HELP\n\nDisplays a one-page brief help screen and exits quietly.\n<QUALIFIER>\n/JUNK\n\n/JUNK\n<NEXT>\n/NOJUNK (default)\n\nJunk the stored paths (don't recreated the archive's directory\nstructure.\n<QUALIFIER>\n/LIST\n\n/LIST\n\nList the contents of the archive.  /BRIEF and /FULL can be used to\nspecify the amount of information displayed.  The default is /BRIEF.\n<QUALIFIER>\n/LOWERCASE\n\n/LOWERCASE\n<NEXT>\n/NOLOWERCASE (default)\n\nConvert filenames from all-uppercase operating systems to lowercase.  This\noption has no effect under VMS.\n<QUALIFIER>\n/ODS2\n\n/ODS2\n<NEXT>\n/NOODS2 (default)\n\nCauses UnZip to convert archived file names to ODS2-compatible file\nnames (substituting \"_\" for any invalid characters), regardless of the\ntype of the destination file system.\n\nThe default is to use ODS5-compatible file names when the destination\nfile system is ODS5, and to convert the names to ODS2-compatible names\nwhen the destination file system is ODS2.\n\nBeginning in UnZip 6.0, ODS2-compatible names are explicitly set to\nupper case.\n<QUALIFIER>\n/OVERWRITE\n\n/OVERWRITE\n<NEXT>\n/NOOVERWRITE\n\nSee /EXISTING.\n\n/OVERWRITE is equivalent to /EXISTING = NEW_VERSION.\n<NEXT>\n/NOOVERWRITE is equivalent to /EXISTING = NOEXTRACT.\n<QUALIFIER>\n/PAGE\n\n/PAGE\n<NEXT>\n/NOPAGE\n\nFeed all screen output through the built-in \"more\" pager.\n<QUALIFIER>\n/PASSWORD\n\n/PASSWORD=decryption-password\n\nSpecifies a decryption password and prevents UnZip from prompting for\na password in case the specified decryption key was wrong. The supplied\nstring must be enclosed in double-quotes whenever it contains lowercase\nor special characters.\n<QUALIFIER>\n/PIPE\n\n/PIPE\n\nExtract files to SYS$OUTPUT with no informational messages.\n<QUALIFIER>\n/QUIET\n\n/QUIET[=SUPER]\n\nPerform operations quietly.  The keyword SUPER can be specified to make\noperations even more quiet.\n<QUALIFIER>\n/RESTORE\n\n/RESTORE[=(KEYWORD, ...)]\n\nSelects restoration options for some meta-data.\nThe optional keywords recognized are:\n<LITERAL>\n|  OWNER_PROT    Restore file owner and ACL protection settings.\n|  NOOWNER_PROT  Do not restore file owner and ACL protection settings.\n|  NODATE        Do not restore any timestamps.\n|  DATE=ALL      Restore timestamps for all extracted entries, files\n|                and directories.\n|  DATE=FILES    Restore timestamps for extracted files.  (default)\n<LARETIL>\n\nBy default, VMS UnZip restores the original date-time attributes for files,\nbut not for directories.  This agrees with the behavior of VMS BACKUP\n(and UnZip versions before 5.52 where the capability to restore directory\ntimestamps was added).\n\nFor compatibility with UnZip versions before 6.0 (5.53), the following\nobsolete short forms are still accepted:\n<LITERAL>\n| Obsolete form:        Modern form:\n| /RESTORE              /RESTORE = OWNER_PROT\n| /NORESTORE            /RESTORE = NOOWNER_PROT\n<LARETIL>\n<QUALIFIER>\n/SCREEN\n\n/SCREEN\n<NEXT>\n/NOSCREEN\n\nExtracts matching files to SYS$OUTPUT (the terminal).\n<QUALIFIER>\n/TEST\n\n/TEST\n<NEXT>\n/NOTEST\n\nTest archive files.\n<QUALIFIER>\n/TEXT\n\n/TEXT[=(KEYWORD, ...)]\n<NEXT>\n/NOTEXT (default)\n\nSelects conversion to VMS standard text file format.\nThe optional keywords recognized are:\n<LITERAL>\n|  AUTO     Automatically extracts files marked as \"text\" (rather\n|           than \"binary\") in standard VMS text file format. (default)\n|  ALL      Extracts all files in standard VMS text file format.\n|  NONE     Same as /NOTEXT.\n|  STMLF    Use Stream_LF record format for text files (instead of the\n|           default variable-length record format).\n<LARETIL>\n\nA similar functionality is available for binary files, see qualifier /BINARY.\n<QUALIFIER>\n/TIMESTAMP\n\n/TIMESTAMP\n\nSets the timestamp of an archive to that of its newest file.  This qualifier\ncorresponds to zip's /APPEND/LATEST (-go) option, but can be applied to\nwildcard zipfile specifications (e.g. \"*.zip\") and is much faster.\n<QUALIFIER>\n/TRAVERSE_DIRS\n\n/TRAVERSE_DIRS\n<NEXT>\n/NOTRAVERSE_DIRS (default)\n\nAllows to extract archive members into locations outside of the currently\nactive \"extraction root dir\".  For security reasons, UnZip normally\nremoves \"parent dir\" path components (\"../\") from the names of extracted\nfiles.  This feature (new for UnZip 5.50) prevents UnZip from accidentally\nwriting files to \"sensitive\" areas outside the directory tree below the\nspecified \"extraction root\".  By specifying the /TRAVERSE_DIRS option,\nthis security feature can be switched off. This allows users to extract\n(older) archives that made use of \"../\" to create multiple directory\ntrees at the level of the current extraction folder.\n<QUALIFIER>\n/UPDATE\n\n/UPDATE\n<NEXT>\n/NOUPDATE\n\nUpdate existing files; create new ones if needed.\n<QUALIFIER>\n/VERSION\n\n/VERSION\n<NEXT>\n/NOVERSION (default)\n\nRetain VMS file version numbers.\n\n<TOPIC>\nAuthors\n\nInfo-ZIP; currently maintained by Christian Spieler.  VMS support maintained\nby Igor Mandrichenko, Steven M. Schweda, Christian Spieler and Hunter Goatley.\nOriginally based on a program by Samuel H. Smith.\n\nVMS on-line help ported from UNZIP.TXT by Hunter Goatley.\n\n<TOPIC>\nExit_Status\n\nOn VMS, UnZip's UNIX-style exit values are mapped into VMS-style status\ncodes with facility code 1954 = %x7A2, and with the inhibit-message\n(%x10000000) and facility-specific (%x00008000) bits set:\n<LITERAL>\n|   %x17A28001                        normal exit\n|   %x17A28000 + 16*UnZip_error_code  warnings\n|   %x17A28002 + 16*UnZip_error_code  normal errors\n|   %x17A28004 + 16*UnZip_error_code  fatal errors\n<LARETIL>\n\nNote that multiplying the UNIX-style UnZip error code by 16 places it\nconveniently in the hexadecimal representation of the VMS exit code,\n\"__\" in %x17A28__s, where \"s\" is the severity code.  For example, a\nmissing archive might cause UnZip error code 9, which would be\ntransformed into the VMS exit status %X17A28092.\n\nThe UnZip VMS exit codes include severity values which approximate those\ndefined by PKWARE, as shown in the following table:\n<LITERAL>\n|    VMS     UnZip err\n|  severity    code     Error description\n| ----------+---------+----------------------------------------------\n|  Success       0      Normal.  No errors or warnings detected.\n|  Warning       1      One or more warnings  were  encountered, but\n|                       processing  completed  successfully  anyway.\n|                       This  includes  archives  where  one or more\n|                       (but not all)  files were skipped because of\n|                       unsupported compress or encrypt methods,  or\n|                       bad passwords.\n|  Error         2      Error in the archive format.  Processing may\n|                       have completed  successfully  anyway.   Some\n|                       defects in archives (made by other programs)\n|                       can be repaired transparently.\n|  Fatal         3      Severe error in the archive format. Process-\n|                       ing probably failed immediately.\n|  Fatal         4      Memory allocation failed in program initial-\n|                       ization.\n|  Fatal         5      Memory  allocation  failed  in password pro-\n|                       cessing.\n|  Fatal         6      Memory allocation failed while decompressing\n|                       to disk.\n|  Fatal         7      Memory allocation failed while decompressing\n|                       in memory.\n|  Fatal         8      Memory  allocation  failed    (reserved  for\n|                       future use).\n|  Error         9      Specified archive files were not found.\n|  Error        10      Invalid command-line options or parameters.\n|  Error        11      No files matched selection criteria.\n|  Fatal        50      Disk full.\n|  Fatal        51      Unexpected  end-of-file  while  reading  the\n|                       archive.\n|  Error        80      User interrupt (Ctrl/C).\n|  Error        81      No files were processed,  because  of unsup-\n|                       ported compress or encrypt methods.\n|  Error        82      No  files  were  processed,  because  of bad\n|                       password(s).\n|  Fatal        83      Large-file archive could not be processed by\n|                       this small-file program.\n<LARETIL>\n\n<TOPIC>\nUNIX_Options\n\nThe default action of UnZip is to extract all zipfile entries.  The following\noptions and modifiers can be provided:\n\n<LITERAL>\n|  -Z   ZipInfo mode\n|  -c   extract files to SYS$OUTPUT (terminal)\n|  -f   freshen existing files (replace if newer); create none\n|  -h   show brief help screen and exit quietly\n|  -l   list archive files (short format)\n|  -p   extract files to SYS$OUTPUT; no informational messages\n|  -t   test archive files\n|  -T   set zipfile timestamps to that of each archive's newest entry\n|  -u   update existing files; create new ones if needed\n|  -v   list archive files (verbose format)\n|  -z   display only the archive comment\n|\n|MODIFIERS\n|  -a   extract text files in standard VMS text file format\n|  -aa  extract all files as text\n|  -b   auto-extract only binary files in fixed 512-byte record format\n|  -bb  extract all files as binary in fixed 512-byte record format\n|  -j   junk paths (don't recreate archive's directory structure)\n|  -n   never overwrite or make a new version of an existing file\n|  -o   always make a new version (-oo: overwrite orig) existing file\n|  -q   perform operations quietly (-qq => even quieter)\n|  -C   match filenames case-insensitively\n|  -D   do not restore any timestamps (--D restore them even for dirs)\n|  -L   convert filenames to lowercase if created under DOS, VMS, etc.\n|  -M   feed screen output through built-in \"more\" pager\n|  -P<password> supply decryption password on the cmd line (insecure!)\n|  -S   use Stream_LF record format to extract text files (with -a[a])\n|  -V   retain (VMS) file version numbers\n|  -X   restore owner/ACL protection info (may require privileges)\n|  -Y   treat \".nnn\" suffix as version number (\"a.b.3\" -> \"a.b;3\")\n|  -:   allow \"../\" path components to traverse across top extract dir\n|  -2   force creation of ODS2-compatible file names\n<LARETIL>\n\nNote that uppercase options such as -C, -D, -L, -M, -P, -S, -T, -V, -X, -Y,\nand -Z must be specified in quotes (unless SET PROC/PARSE=EXTEND is set).\nFor example:\n\n<LITERAL>\n|  $ unzip \"-VX\" -a zipfile\n<LARETIL>\n\n<TOPIC>\nUNZIP_OPTS_Default\n\nUnZip allows to modify its default behaviour by specifying (UNIX style)\noption defaults via the UNZIP_OPTS logical name.\nFor example, the following will cause UnZip to match filenames without regard\nto case, restore owner/protection information and perform all operations at\nquiet-level 1 by default:\n\n<LITERAL>\n|  $ define UNZIP_OPTS \"-qCX\"\n<LARETIL>\n\nNote that the quotation marks here are required to preserve lowercase options\n(opposite of the command-line behavior). To negate a default option on the\ncommand line, add one or more minus  signs before the option letter, in\naddition to the leading switch character `-':\n\n<LITERAL>\n|  $ unzip --ql zipfile\n<LARETIL>\n\nor\n\n<LITERAL>\n|  $ unzip -l-q zipfile\n<LARETIL>\n\nAt present it is not possible to decrement an option below zero--that is,\nmore than a few minuses have no effect.\n\nUNZIP_OPTS may be defined as a symbol rather than a logical, but if both\nare defined, the logical is used.\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unzip_def.rnh",
    "content": ".!\n.!  File:       UNZIP_DEF.RNH\n.!\n.!  Author:     Hunter Goatley\n.!\n.!  Date:       October 23, 1991\n.!\n.!  Description:\n.!\n.!      RUNOFF source file for VMS on-line help for portable UnZip.\n.!      Adapted from UNZIP.MAN (now UNZIP.TXT).\n.!\n.!      To build:       $ REN UNZIP_DEF.RNH UNZIP.RNH\n.!                      $ RUNOFF UNZIP.RNH\n.!                      $ LIBR/HELP/INSERT libr UNZIP\n.!\n.!  Modification history:\n.!\n.!      01-001          Hunter Goatley          23-OCT-1991 09:21\n.!              Genesis.\n.!      01-002          Cave Newt               16-MAR-1992 22:37\n.!              Updated for UnZip 4.2.\n.!      01-003          Igor Mandrichenko       23-MAY-1992 22:14\n.!              Added -X option to command syntax.\n.!      01-004          Cave Newt               24-MAY-1992 13:30\n.!              Added UNZIP_OPTS environment variable help.\n.!      01-005          Igor Mandrichenko       14-DEC-1993 18:55\n.!              Modified for UnZip V5.1\n.!      01-006          Cave Newt               21-DEC-1993 12:38\n.!              Added -x option and cleaned up.\n.!      01-007          Cave Newt               14-JUL-1994 09:45\n.!              Added -Z, -C and -L options, removed -U, minor clean-up.\n.!      01-008          Cave Newt               28-JUL-1994 08:57\n.!              Removed semi-colons from comments.\n.!      02-001          Christian Spieler       09-DEC-1995 02:25\n.!              Modified for UnZip 5.2.\n.!      02-002          Christian Spieler       06-FEB-1996 02:25\n.!              Added -h \"help\" option.\n.!      02-003          Christian Spieler       04-MAR-1997 20:25\n.!              Added -P \"command line password\" option.\n.!      02-004          Christian Spieler       26-JUL-1997 00:05\n.!              Added Exit_Codes subtopic, explaining UnZip's VMS return codes.\n.!      02-005          Christian Spieler       28-APR-2000 03:22\n.!              Changed references to plaintext UnZip documentation file\n.!              into \"UNZIP.TXT\".\n.!      02-006          Christian Spieler       15-APR-2001 22:29\n.!              Added description for extended functionality of -b option.\n.!      02-007          Christian Spieler       10-DEC-2001 13:58\n.!              Added description for new -: traverse dirs option.\n.!      02-008          Christian Spieler       29-JAN-2005 01:50\n.!              Added description for the -T \"set archive timestamp\" option.\n.!      02-009          Christian Spieler       04-MAR-2007 14:37\n.!              Added description for the -S \"Stream-LF text files\" option;\n.!              updated the documentation of the VMS exit codes.\n.!      02-010          S. Schweda, C. Spieler  28-Dec-2007 21:28\n.!              Added description for the -D \"timestamp restoration\" option.\n.!\n.noflags\n.lm4 .rm72\n.indent -4\n1 UNZIP\n.br\nUnZip is used to extract files compressed and packaged by Zip (see HELP ZIP\nfor information on ZIP).\n.sk\nFor a brief help on Zip and Unzip, run each without specifying any\nparameters on the command line, or specify the -h flag (but not in UnZip's\nZipinfo mode).\n.sk\nUNZIP will list, test, or extract from a ZIP archive.  ZIP archives are commonly\nfound on MS-DOS systems; a VMS version of ZIP can also be found here.\n.sk\nArchive member extraction is implied by the absence of the -c, -p, -t, -l, -v or\n-z options.  All archive members are processed unless a filespec is provided to\nspecify a subset of the archive members.\nFormat:\n.sk;.lm+1;.literal\nUNZIP [-cfhlptTuvxz[ajnoqCDLMSVXY:2]] file[.zip] [list] [-x xlist] [-d out_dir]\n.end literal;.lm-1\n.!------------------------------------------------------------------------------\n.indent -4\n2 Parameters\n.sk;.indent -4\nfile[.zip]\n.sk\nFile specification for the ZIP archive(s) with optional wildcards. UnZip will\nperform actions specified for every zipfile matching the specification.\nDefault file specification is SYS$DISK:[].ZIP.\nNote that self-extracting ZIP files are supported; just specify the .EXE\nsuffix yourself.\n.sk;.indent -4\n[list]\n.sk\nAn optional list of archive members to be processed; if no list is given, all\narchive members are processed.  Expressions may be\nused to match multiple members.  Expressions should be enclosed in double-quotes\nto prevent interpretation by DCL.  Multiple filenames should be separated by\nblanks.  Each file specification is similar to a Unix egrep expression and may\ncontain:\n.sk\n.literal\n     *       matches a sequence of 0 or more characters\n     ?       matches exactly 1 character\n     [...]   matches any single character found inside the brackets;\n             ranges are specified by a beginning character, a hyphen,\n             and an ending character.  If a '!' or '^' immediately\n             follows the left bracket, then any character not in the\n             given range is matched.\n             Hint: To specify a verbatim left bracket '[', the\n                   three-character sequence \"[[]\" has to be used.\n.end literal\n.sk\n.sk;.indent -4\n[-x xlist]\n.sk\nAn optional list of archive members to be excluded from processing.  The xlist\noverrides any files included in the normal list.\n.sk;.indent -4\n[-d out_dir]\n.sk\nOptional directory specification to be used as target root directory\nfor files to be extracted.  Directory should be specified in \"[.foo]\"\nformat rather than \"foo.dir\" or \"foo/\" format.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Options\n.br\nThe default action of UnZip is to extract all zipfile entries.  The following\noptions and modifiers can be provided:\n.sk;.literal\n   -Z   ZipInfo mode\n   -c   extract files to SYS$OUTPUT (terminal)\n   -f   freshen existing files (replace if newer); create none\n   -h   show brief help screen and exit quietly\n   -l   list archive files (short format)\n   -p   extract files to SYS$OUTPUT; no informational messages\n   -t   test archive files\n   -T   set zipfile timestamps to that of each archive's newest entry\n   -u   update existing files; create new ones if needed\n   -v   list archive files (verbose format)\n   -z   display only the archive comment\n.end literal;.sk;.literal\n MODIFIERS\n   -a   extract text files in standard VMS text file format\n   -aa  extract all files as text\n   -b   auto-extract only binary files in fixed 512-byte record format\n   -bb  extract all files as binary in fixed 512-byte record format\n   -j   junk paths (don't recreate archive's directory structure)\n   -n   never overwrite or make a new version of an existing file\n   -o   always make a new version (-oo: overwrite orig) existing file\n   -q   perform operations quietly (-qq => even quieter)\n   -C   match filenames case-insensitively\n   -D   do not restore any timestamps (--D restore them even for dirs)\n   -L   convert filenames to lowercase if created under DOS, VMS, etc.\n   -M   feed screen output through built-in \"more\" pager\n   -P<password> supply decryption password on the cmd line (insecure!)\n   -S   use Stream_LF record format to extract text files (with -a[a])\n   -V   retain (VMS) file version numbers\n   -X   restore owner/ACL protection info (may require privileges)\n   -Y   treat \".nnn\" suffix as version number (\"a.b.3\" -> \"a.b;3\")\n   -:   allow \"../\" path components to traverse across top extract dir\n   -2   force creation of ODS2-compatible file names\n.end literal;.sk\nNote that uppercase options (-C, -D, -L, -M, -P, -S, -T, -V, -X, -Y, and\n-Z) must be specified in quotes (unless SET PROC/PARSE=EXTEND is set).\nFor example:\n.sk;.literal\n    unzip \"-VX\" -a zipfile\n.end literal;.sk\nWhen extracting to SYS$OUTPUT (-c or -p options) redirected to a file,\nyou may want to override the default text file conversion by specifying\nthe -b option. A single \"-b\" option switches to \"binary piping\" mode\nfor Zip entries marked as non-text, only. To force \"binary piping\" mode\neven for Zip file entries marked as text, the \"-bb\" option should be used.\n(Please note that a later \"-a\" cancels any -b option, see below.)\n.sk\nThe output conversion options -b and -a may be combined to perform\nbinary conversions on binary files and text conversion on text files.\nBut note: For compatibility with implementation on other systems, -b cancels\nany -a option; to get the intended result, -a must be specified AFTER -b.\nAnd, in combination, \"text\" recognition takes precedence; this means\nthat -bba (-bb -a) has the same effect as -ba (-b -a), and -aa overrides\nbinary conversion for ALL files.\n.sk\nThe conversion option -S is only effective when used together with\n-a or -aa. When specified, \"text\" files are written in Stream-LF record\nformat instead of the VMS default of Variable-Length record format.\n(When no conversion options are specified, all non-VMS entries are always\nwritten as Stream-LF files.)\n.sk\nPlease note that using the \"-P<password>\" option is higly insecure, the\nplaintext password may be seen by others. For this reason (and because of\nlack of space), the \"-P<password>\" option is not advertised on UnZip's\nonline help screen.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Exit_Status\n.br\nOn VMS, UnZip's UNIX-style exit values are mapped into VMS-style status\ncodes with facility code 1954 = %x7A2, and with the inhibit-message\n(%x10000000) and facility-specific (%x00008000) bits set:\n.sk\n.literal\n   %x17A28001                        normal exit\n   %x17A28000 + 16*UnZip_error_code  warnings\n   %x17A28002 + 16*UnZip_error_code  normal errors\n   %x17A28004 + 16*UnZip_error_code  fatal errors\n.end literal\n.sk\nNote that multiplying the UNIX-style UnZip error code by 16 places it\nconveniently in the hexadecimal representation of the VMS exit code,\n\"__\" in %x17A28__s, where \"s\" is the severity code.  For example, a\nmissing archive might cause UnZip error code 9, which would be\ntransformed into the VMS exit status %X17A28092.\n.sk\nThe UnZip VMS exit codes include severity values which approximate those\ndefined by PKWARE, as shown in the following table:\n.literal\n\n    VMS     UnZip err\n  severity    code     Error description\n ----------+---------+----------------------------------------------\n  Success       0      Normal.  No errors or warnings detected.\n  Warning       1      One or more warnings  were  encountered, but\n                       processing  completed  successfully  anyway.\n                       This  includes  archives  where  one or more\n                       (but not all)  files were skipped because of\n                       unsupported compress or encrypt methods,  or\n                       bad passwords.\n  Error         2      Error in the archive format.  Processing may\n                       have completed  successfully  anyway.   Some\n                       defects in archives (made by other programs)\n                       can be repaired transparently.\n  Fatal         3      Severe error in the archive format. Process-\n                       ing probably failed immediately.\n  Fatal         4      Memory allocation failed in program initial-\n                       ization.\n  Fatal         5      Memory  allocation  failed  in password pro-\n                       cessing.\n  Fatal         6      Memory allocation failed while decompressing\n                       to disk.\n  Fatal         7      Memory allocation failed while decompressing\n                       in memory.\n  Fatal         8      Memory  allocation  failed    (reserved  for\n                       future use).\n  Error         9      Specified archive files were not found.\n  Error        10      Invalid command-line options or parameters.\n  Error        11      No files matched selection criteria.\n  Fatal        50      Disk full.\n  Fatal        51      Unexpected  end-of-file  while  reading  the\n                       archive.\n  Error        80      User interrupt (Ctrl/C).\n  Error        81      No files were processed,  because  of unsup-\n                       ported compress or encrypt methods.\n  Error        82      No  files  were  processed,  because  of bad\n                       password(s).\n  Fatal        83      Large-file archive could not be processed by\n                       this small-file program.\n.end literal\n.!------------------------------------------------------------------------------\n.indent -4\n2 Logical_Names\n.br\nUnZip allows to modify its default behaviour by specifying option defaults\nvia the UNZIP_OPTS logical name.\nFor example, the following will cause UnZip to restore owner/protection\ninformation and perform all operations at quiet-level 1 by default:\n.sk;.literal\n    define UNZIP_OPTS \"-qX\"\n.end literal;.sk\nNote that the quotation marks here are required to preserve lowercase options\n(opposite of the command-line behavior).\nTo negate a default option on the command line, add one or more minus\nsigns before the option letter, in addition to the leading switch character\n`-':\n.sk;.literal\n    unzip --ql zipfile\n.end literal\nor\n.literal\n    unzip -l-q zipfile\n.end literal;.sk\nAt present it is not possible to decrement an option below zero--that is,\nmore than a few minuses have no effect.\n.sk\nUNZIP_OPTS may be defined as a symbol rather than a logical name, but if\nboth are defined, the logical name takes precedence.\n.!-----------------------------------------------------------------------------\n.indent -4\n2 Authors\n.br\nInfo-ZIP; currently maintained by Christian Spieler.  VMS support maintained\nby Christian Spieler and Hunter Goatley.  Originally based on a program\nby Samuel H. Smith.\n.sk\nVMS on-line help ported from UNZIP.TXT by Hunter Goatley.\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unzipsfx.hlp",
    "content": "1 UNZIPSFX\n\n     unzipsfx  -  self-extracting  stub  for  prepending  to  ZIP\n     archives\n\n     <name  of  unzipsfx+archive   combo>   [-cfptuz[ajnoqsCLV$]]\n     [file(s) ...] [-x xfile(s) ...]\n\n     unzipsfx is a modified version of unzip designed  to  be\n     prepended  to  existing  ZIP archives in order to form self-\n     extracting archives.  Instead of taking its  first  non-flag\n     argument  to  be  the  zipfile(s)  to be extracted, unzipsfx\n     seeks itself under the name by  which  it  was  invoked  and\n     tests  or  extracts  the  contents  of the appended archive.\n     Because the executable stub adds bulk to  the  archive  (the\n     whole  purpose  of  which  is to be as small as possible), a\n     number of the regular version's less-vital capabilities have\n     been  removed.   Among these are the usage (or help) screen,\n     the listing and diagnostic functions (-l and -v), the  abil-\n     ity to decompress older compression formats (the ``reduce,''\n     ``shrink'' and ``implode''  methods),  and  the  ability  to\n     extract  to a directory other than the current one.  Decryp-\n     tion is supported as a compile-time  option  but  should  be\n     avoided  unless  the  attached  archive  contains  encrypted\n     files.\n\n     Note that self-extracting archives made with unzipsfx are no\n     more  (or  less) portable across different operating systems\n     than is the unzip executable itself.   In  general  a  self-\n     extracting  archive  made  on  a particular Unix system, for\n     example, will only self-extract under  the  same  flavor  of\n     Unix.  Regular unzip may still be used to extract the embed-\n     ded archive as with any normal  zipfile,  although  it  will\n     generate  a harmless warning about extra bytes at the begin-\n     ning of the zipfile.\n\n\n\n[file(s)]\n\n          An optional list of archive members  to  be  processed.\n          Regular  expressions  (wildcards)  similar  to those in\n          Unix egrep(1) may be used to  match  multiple  members.\n          These wildcards may contain:\n\n          *    matches a sequence of 0 or more characters\n\n          ?    matches exactly 1 character\n\n          [...]\n               matches any  single  character  found  inside  the\n               brackets;  ranges  are  specified  by  a beginning\n               character, a hyphen, and an ending character.   If\n               an  exclamation point or a caret (`!' or `^') fol-\n               lows the left bracket, then the range  of  charac-\n               ters within the brackets is complemented (that is,\n               anything except the characters inside the brackets\n               is considered a match).\n\n          (Be sure to quote any character which  might  otherwise\n          be  interpreted  or  modified  by the operating system,\n          particularly under Unix and VMS.)\n\n[-x xfile(s)]\n\n          An optional list of archive members to be excluded from\n          processing.   Since wildcard characters match directory\n          separators (`/'), this option may be  used  to  exclude\n          any  files  which  are in subdirectories.  For example,\n          ``unzip foo *.[ch] -x */*'' would extract all C  source\n          files  in the main directory, but none in any subdirec-\n          tories.  Without the -x option, all C source  files  in\n          all directories within the zipfile would be extracted.\n\n2 Options\n\n     unzipsfx supports the following unzip options:   -c  and\n     -p  (extract  to standard output/screen), -f and -u (freshen\n     and  update  existing  files  upon  extraction),  -t   (test\n     archive) and -z (print archive comment).  All normal listing\n     options (-l, -v and -Z) have been removed, but  the  testing\n     option (-t) may be used as a ``poor man's'' listing.  Alter-\n     natively, those creating self-extracting archives  may  wish\n     to include a short listing in the zipfile comment.\n\n     See unzip for  a  more  complete  description  of  these\n     options.\n\n     MODIFIERS\n\n     unzipsfx currently supports  all  unzip  modifiers:   -a\n     (convert  text  files),  -n (never overwrite), -o (overwrite\n     without prompting), -q (operate quietly),  -C  (match  names\n     case-insenstively), -L (convert uppercase-OS names to lower-\n     case), -j (junk paths) and -V (retain version numbers); plus\n     the   following   operating-system   specific  options:   -X\n     (restore VMS owner/protection info), -s (convert  spaces  in\n     filenames  to  underscores  [DOS, OS/2, NT]) and -$ (restore\n     volume label [DOS, OS/2, NT, Amiga]).\n\n     (Support for regular ASCII text-conversion may be removed in\n     future versions, since it is simple enough for the archive's\n     creator to ensure that text files have the appropriate  for-\n     mat for the local OS.  EBCDIC conversion will of course con-\n     tinue to be supported since the zipfile format implies ASCII\n     storage of text files.)\n\n     See unzip for  a  more  complete  description  of  these\n     modifiers.\n\n2 Environment_options\n\n     unzipsfx uses the same environment  variables  as  unzip\n     does,  although  this  is likely to be an issue only for the\n     person creating and  testing  the  self-extracting  archive.\n     See unzip for details.\n\n2 Decryption\n\n     Decryption is supported exactly as in  unzip;  that  is,\n     interactively with a non-echoing prompt for the password(s).\n     See unzip for details.  Once again,  note  that  if  the\n     archive  has  no encrypted files there is no reason to use a\n     version of unzipsfx with decryption support; that only  adds\n     to the size of the archive.\n\n2 Examples\n\n     To create a self-extracting archive letters from  a  regular\n     zipfile letters.zip and change the new archive's permissions\n     to be world-executable under Unix:\n\n         cat unzipsfx letters.zip > letters\n         chmod 755 letters\n\n     To create the same archive under MS-DOS, OS/2  or  NT  (note\n     the use of the /b [binary] option to the copy command):\n\n         copy /b unzipsfx.exe+letters.zip letters.exe\n\n     Under VMS:\n\n         copy unzipsfx.exe,letters.zip letters.exe\n         letters == \"$currentdisk:[currentdir]letters.exe\"\n\n     (The VMS append command may also be used.  The  second  com-\n     mand installs the new program as a ``foreign command'' capa-\n     ble of taking  arguments.)  To  test  (or  list)  the  newly\n     created self-extracting archive:\n\n         letters -t\n\n     To test letters quietly, printing  only  a  summary  message\n     indicating whether the archive is OK or not:\n\n         letters -tq\n\n     To extract the complete contents into the current directory,\n     recreating all files and subdirectories as necessary:\n\n         letters\n\n     To extract only the README  file  to  standard  output  (the\n     screen):\n\n         letters -c README\n\n     To print only the zipfile comment:\n\n         letters -z\n\n2 Limitations\n\n     The principle and fundamental limitation of unzipsfx is that\n     it  is  not  portable across architectures or operating sys-\n     tems, and therefore neither are the resulting archives.  For\n     some  architectures  there  is  limited portability, however\n     (e.g., between some flavors of Intel-based Unix).\n\n     unzipsfx has no knowledge of the user's PATH, so in  general\n     an  archive  must either be in the current directory when it\n     is invoked, or else a full or relative path must  be  given.\n     If  a  user attempts to extract the archive from a directory\n     in the PATH other than the current one, unzipsfx will  print\n     a  warning  to  the  effect, ``can't find myself.''  This is\n     always true under Unix and may be true in some  cases  under\n     MS-DOS,  depending  on  the compiler used (Microsoft C fully\n     qualifies the program name, but other  compilers  may  not).\n     Under OS/2 and NT there are operating-system calls available\n     which provide the full path name,  so  the  archive  may  be\n     invoked  from anywhere in the user's path.  The situation is\n     not known for Atari TOS, MacOS, etc.\n\n     As noted above, a number of the normal  unzip  functions\n     have  been removed in order to make unzipsfx smaller:  usage\n     and diagnostic info, listing  functions  and  extraction  to\n     other directories.  Also, only stored and deflated files are\n     supported.  The latter  limitation  is  mainly  relevant  to\n     those who create SFX archives, however.\n\n     VMS users must know how to set up  self-extracting  archives\n     as  foreign  commands  in  order  to  use  any of unzipsfx's\n     options.  This is not necessary for simple  extraction,  but\n     the command to do so then becomes, e.g., ``run letters'' (to\n     continue the examples given above).\n\n     unzipsfx is not supported on the Amiga because  of  the  way\n     the  loader  works;  the  entire  archive  contents would be\n     loaded into memory by default.  It may be possible  to  work\n     around this by defining the attached archive to be a ``debug\n     hunk,'' but compatibility problems between the ROM levels of\n     older  Amigas  and  newer  ones are likely to cause problems\n     regardless.\n\n     All current bugs in unzip exist in unzipsfx as well.\n\n2 Diagnostics\n\n     unzipsfx's exit status (error level) is identical to that of\n     unzip; see the corresponding help entry.\n\n2 See_also\n\n     funzip, unzip, zip,  zipcloak,  zipgrep,\n     zipinfo, zipnote, zipsplit\n\n2 Authors\n\n     Greg Roelofs was responsible for the basic modifications  to\n     UnZip  necessary  to create UnZipSFX.  See unzip for the\n     current list of zip-bugs authors, or the  file  CONTRIBS  in\n     the  UnZip source distribution for the full list of Info-ZIP\n     contributors.\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/unzipsfx.opt",
    "content": "Ident = \"UnZipSFX 6.0\"\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/vms.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vms.c                                        Igor Mandrichenko and others\n\n  This file contains routines to extract VMS file attributes from a zipfile\n  extra field and create a file with these attributes.  The code was almost\n  entirely written by Igor, with a couple of routines by GRR and lots of\n  modifications and fixes by Christian Spieler.\n\n  Contains:  check_format()\n             open_outfile()\n             find_vms_attrs()\n             flush()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             dos_to_unix_time()         (TIMESTAMP only)\n             stamp_file()               (TIMESTAMP only)\n             vms_msg_text()\n             do_wild()\n             mapattr()\n             mapname()\n             checkdir()\n             check_for_newer()\n             return_VMS\n             screensize()\n             screenlinewrap()\n             version()\n\n  ---------------------------------------------------------------------------*/\n\n#ifdef VMS                      /* VMS only! */\n\n#define UNZIP_INTERNAL\n\n#include \"unzip.h\"\n#include \"crc32.h\"\n#include \"vms.h\"\n#include \"vmsdefs.h\"\n\n#ifdef MORE\n#  include <ttdef.h>\n#endif\n#include <unixlib.h>\n\n#include <dvidef.h>\n#include <ssdef.h>\n#include <stsdef.h>\n\n/* Workaround for broken header files of older DECC distributions\n * that are incompatible with the /NAMES=AS_IS qualifier. */\n#define lib$getdvi LIB$GETDVI\n#define lib$getsyi LIB$GETSYI\n#define lib$sys_getmsg LIB$SYS_GETMSG\n#include <lib$routines.h>\n\n#ifndef EEXIST\n#  include <errno.h>    /* For mkdir() status codes */\n#endif\n\n/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.\n   Otherwise, lame system headers on VAX cause compiler warnings.\n   (GNU C may define vax but not __VAX.)\n*/\n#ifdef vax\n#  define __VAX 1\n#endif\n\n#ifdef __VAX\n#  define GVTC (unsigned int)\n#else\n#  define GVTC\n#endif\n\n/* With GNU C, some FAB bits may be declared only as masks, not as\n * structure bits.\n */\n#ifdef __GNUC__\n#  define OLD_FABDEF 1\n#endif\n\n#define ASYNCH_QIO              /* Use asynchronous PK-style QIO writes */\n\n/* buffer size for a single block write (using RMS or QIO WRITEVBLK),\n   must be less than 64k and a multiple of 512 ! */\n#define BUFS512 (((OUTBUFSIZ>0xFFFF) ? 0xFFFF : OUTBUFSIZ) & (~511))\n/* buffer size for record output (RMS limit for max. record size) */\n#define BUFSMAXREC 32767\n/* allocation size for RMS and QIO output buffers */\n#define BUFSALLOC (BUFS512 * 2 > BUFSMAXREC ? BUFS512 * 2 : BUFSMAXREC)\n        /* locbuf size */\n\n/* VMS success or warning status */\n#define OK(s)   (((s) & STS$M_SUCCESS) != 0)\n#define STRICMP(s1, s2) STRNICMP(s1, s2, 2147483647)\n\n/* Interactive inquiry response codes for replace(). */\n\n#define REPL_NO_EXTRACT   0\n#define REPL_NEW_VERSION  1\n#define REPL_OVERWRITE    2\n#define REPL_ERRLV_WARN   256\n#define REPL_TASKMASK     255\n\n/* 2008-09-13 CS.\n * Note: In extract.c, there are similar strings \"InvalidResponse\" and\n * \"AssumeNone\" defined.  However, as the UI functionality of the VMS\n * \"version-aware\" query is slightly different from the generic variant,\n * these strings are kept separate for now to allow independent\n * \"fine tuning\" without affecting the other variant of the\n * \"overwrite or ...\" user query.\n */\nZCONST char Far InvalidResponse[] =\n  \"error:  invalid response [%.1s]\\n\";\nZCONST char Far AssumeNo[] =\n  \"\\n(EOF or read error, treating as \\\"[N]o extract (all)\\\" ...)\\n\";\n\n\n#ifdef SET_DIR_ATTRIB\n/* Structure for holding directory attribute data for final processing\n * after all files are in place.\n */\ntypedef struct vmsdirattr {\n    struct vmsdirattr *next;            /* link to next in (linked) list */\n    char *fn;                           /* file (directory) name */\n\n    /* Non-VMS attributes data */\n    ulg mod_dos_datetime;               /* G.lrec.last_mod_dos_datetime */\n    unsigned perms;                     /* same as min_info.file_attr */\n\n    unsigned xlen;                      /* G.lrec.extra_field_length */\n    char buf[1];                        /* data buffer (extra_field, fn) */\n} vmsdirattr;\n#define VmsAtt(d)  ((vmsdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n/*\n *   Local static storage\n */\nstatic struct FAB        fileblk;       /* File Access Block */\nstatic struct XABDAT     dattim;        /* date-time XAB */\nstatic struct XABRDT     rdt;           /* revision date-time XAB */\nstatic struct RAB        rab;           /* Record Access Block */\nstatic struct NAM_STRUCT nam;           /* name block */\n\nstatic struct FAB *outfab = NULL;\nstatic struct RAB *outrab = NULL;\nstatic struct XABFHC *xabfhc = NULL;    /* file header characteristics */\nstatic struct XABDAT *xabdat = NULL;    /* date-time */\nstatic struct XABRDT *xabrdt = NULL;    /* revision date-time */\nstatic struct XABPRO *xabpro = NULL;    /* protection */\nstatic struct XABKEY *xabkey = NULL;    /* key (indexed) */\nstatic struct XABALL *xaball = NULL;    /* allocation */\nstatic struct XAB *first_xab = NULL, *last_xab = NULL;\n\nstatic int replace_code_all = -1;       /* All-file response for replace(). */\n\nstatic uch rfm;\n\nstatic uch locbuf[BUFSALLOC];           /* Space for 2 buffers of BUFS512 */\nstatic unsigned loccnt = 0;\nstatic uch *locptr;\nstatic char got_eol = 0;\n\nstruct bufdsc\n{\n    struct bufdsc *next;\n    uch *buf;\n    unsigned bufcnt;\n};\n\nstatic struct bufdsc b1, b2, *curbuf;   /* buffer ring for asynchronous I/O */\n\nstatic int  _flush_blocks(__GPRO__ uch *rawbuf, unsigned size, int final_flag);\nstatic int  _flush_stream(__GPRO__ uch *rawbuf, unsigned size, int final_flag);\nstatic int  _flush_varlen(__GPRO__ uch *rawbuf, unsigned size, int final_flag);\nstatic int  _flush_qio(__GPRO__ uch *rawbuf, unsigned size, int final_flag);\nstatic int  _close_rms(__GPRO);\nstatic int  _close_qio(__GPRO);\n#ifdef ASYNCH_QIO\nstatic int  WriteQIO(__GPRO__ uch *buf, unsigned len);\n#endif\nstatic int  WriteBuffer(__GPRO__ uch *buf, unsigned len);\nstatic int  WriteRecord(__GPRO__ uch *rec, unsigned len);\n\nstatic int  (*_flush_routine)(__GPRO__ uch *rawbuf, unsigned size,\n                              int final_flag);\nstatic int  (*_close_routine)(__GPRO);\n\n#ifdef SYMLINKS\nstatic int  _read_link_rms(__GPRO__ int byte_count, char *link_text_buf);\n#endif /* SYMLINKS */\n\nstatic void init_buf_ring(void);\nstatic void set_default_datetime_XABs(__GPRO);\nstatic int  create_default_output(__GPRO);\nstatic int  create_rms_output(__GPRO);\nstatic int  create_qio_output(__GPRO);\nstatic int  replace(__GPRO);\nstatic int  replace_rms_newversion(__GPRO);\nstatic int  replace_rms_overwrite(__GPRO);\nstatic int  find_vms_attrs(__GPRO__ int set_date_time);\nstatic void free_up(void);\n#ifdef CHECK_VERSIONS\nstatic int  get_vms_version(char *verbuf, int len);\n#endif /* CHECK_VERSIONS */\nstatic unsigned find_eol(ZCONST uch *p, unsigned n, unsigned *l);\n#ifdef SET_DIR_ATTRIB\nstatic char *vms_path_fixdown(ZCONST char *dir_spec, char *dir_file);\n#endif\n#ifdef TIMESTAMP\nstatic time_t mkgmtime(struct tm *tm);\nstatic void uxtime2vmstime(time_t utimeval, long int binval[2]);\n#endif /* TIMESTAMP */\nstatic int vms_msg_fetch(int status);\nstatic void vms_msg(__GPRO__ ZCONST char *string, int status);\n\n\n/*\n   2005-02-14 SMS.\n   Added some ODS5 support:\n      Use longer name structures in NAML, where available.\n      Locate special characters mindful of \"^\" escapes.\n*/\n\n/* Hex digit table. */\n\nchar hex_digit[16] = {\n '0', '1', '2', '3', '4', '5', '6', '7',\n '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'\n};\n\n\n/* Character property table for converting Zip file names to\n   (simpler) ODS2 or (escaped) ODS5 extended file names.\n\n   ODS2 valid characters: 0-9 A-Z a-z $ - _\n\n   ODS5 Invalid characters:\n      C0 control codes (0x00 to 0x1F inclusive)\n      Asterisk (*)\n      Question mark (?)\n\n   ODS5 Invalid characters only in VMS V7.2 (which no one runs, right?):\n      Double quotation marks (\")\n      Backslash (\\)\n      Colon (:)\n      Left angle bracket (<)\n      Right angle bracket (>)\n      Slash (/)\n      Vertical bar (|)\n\n   Characters escaped by \"^\":\n      SP  !  \"  #  %  &  '  (  )  +  ,  .  :  ;  =\n       @  [  \\  ]  ^  `  {  |  }  ~\n\n   Either \"^_\" or \"^ \" is accepted as a space.  Period (.) is a special\n   case.  Note that un-escaped < and > can also confuse a directory\n   spec.\n\n   Characters put out as ^xx:\n      7F (DEL)\n      80-9F (C1 control characters)\n      A0 (nonbreaking space)\n      FF (Latin small letter y diaeresis)\n\n   Other cases:\n      Unicode: \"^Uxxxx\", where \"xxxx\" is four hex digits.\n\n   Property table values:\n      Normal ODS2           1\n      Lower-case ODS2       2\n      Period                4\n      Space                 8\n      ODS5 simple          16\n      ODS5 1-char escape   32\n      ODS5 hex-hex escape  64\n*/\n\nunsigned char char_prop[256] = {\n\n/* NUL SOH STX ETX EOT ENQ ACK BEL   BS  HT  LF  VT  FF  CR  SO  SI */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB  CAN  EM SUB ESC  FS  GS  RS  US */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/*  SP  !   \"   #   $   %   &   '    (   )   *   +   ,   -   .   /  */\n    8, 32, 32, 32, 17, 32, 32, 32,  32, 32,  0, 32, 32, 17,  4,  0,\n\n/*  0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?  */\n   17, 17, 17, 17, 17, 17, 17, 17,  17, 17, 32, 32, 32, 32, 32, 32,\n\n/*  @   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O  */\n   32, 17, 17, 17, 17, 17, 17, 17,  17, 17, 17, 17, 17, 17, 17, 17,\n\n/*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \\   ]   ^   _  */\n   17, 17, 17, 17, 17, 17, 17, 17,  17, 17, 17, 32, 32, 32, 32, 17,\n\n/*  `   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o  */\n   32, 18, 18, 18, 18, 18, 18, 18,  18, 18, 18, 18, 18, 18, 18, 18,\n\n/*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~  DEL */\n   18, 18, 18, 18, 18, 18, 18, 18,  18, 18, 18, 32, 32, 32, 32, 64,\n\n   64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,\n   64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,\n   64, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 16,\n   16, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 16,\n   16, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 16,\n   16, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 16,\n   16, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 16,\n   16, 16, 16, 16, 16, 16, 16, 16,  16, 16, 16, 16, 16, 16, 16, 64\n};\n\n\n/* 2004-11-23 SMS.\n *\n *       get_rms_defaults().\n *\n *    Get user-specified values from (DCL) SET RMS_DEFAULT.  FAB/RAB\n *    items of particular interest are:\n *\n *       fab$w_deq         default extension quantity (blocks) (write).\n *       rab$b_mbc         multi-block count.\n *       rab$b_mbf         multi-buffer count (used with rah and wbh).\n */\n\n#define DIAG_FLAG (uO.vflag >= 3)\n\n/* Default RMS parameter values.\n * The default extend quantity (deq) should not matter much here, as the\n * initial allocation should always be set according to the known file\n * size, and no extension should be needed.\n */\n\n#define RMS_DEQ_DEFAULT 16384   /* About 1/4 the max (65535 blocks). */\n#define RMS_MBC_DEFAULT 127     /* The max, */\n#define RMS_MBF_DEFAULT 2       /* Enough to enable rah and wbh. */\n\n/* GETJPI item descriptor structure. */\ntypedef struct\n{\n    short buf_len;\n    short itm_cod;\n    void *buf;\n    int *ret_len;\n} jpi_item_t;\n\n/* Durable storage */\nstatic int rms_defaults_known = 0;\n\n/* JPI item buffers. */\nstatic unsigned short rms_ext;\nstatic char rms_mbc;\nstatic unsigned char rms_mbf;\n\n/* Active RMS item values. */\nunsigned short rms_ext_active;\nchar rms_mbc_active;\nunsigned char rms_mbf_active;\n\n/* GETJPI item lengths. */\nstatic int rms_ext_len;         /* Should come back 2. */\nstatic int rms_mbc_len;         /* Should come back 1. */\nstatic int rms_mbf_len;         /* Should come back 1. */\n\n/* Desperation attempts to define unknown macros.  Probably doomed.\n * If these get used, expect sys$getjpiw() to return %x00000014 =\n * %SYSTEM-F-BADPARAM, bad parameter value.\n * They keep compilers with old header files quiet, though.\n */\n#ifndef JPI$_RMS_EXTEND_SIZE\n#  define JPI$_RMS_EXTEND_SIZE 542\n#endif /* ndef JPI$_RMS_EXTEND_SIZE */\n\n#ifndef JPI$_RMS_DFMBC\n#  define JPI$_RMS_DFMBC 535\n#endif /* ndef JPI$_RMS_DFMBC */\n\n#ifndef JPI$_RMS_DFMBFSDK\n#  define JPI$_RMS_DFMBFSDK 536\n#endif /* ndef JPI$_RMS_DFMBFSDK */\n\n/* GETJPI item descriptor set. */\n\nstruct\n{\n    jpi_item_t rms_ext_itm;\n    jpi_item_t rms_mbc_itm;\n    jpi_item_t rms_mbf_itm;\n    int term;\n} jpi_itm_lst =\n     { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len },\n       { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len },\n       { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len },\n       0\n     };\n\nstatic int get_rms_defaults()\n{\n    int sts;\n\n    /* Get process RMS_DEFAULT values. */\n\n    sts = sys$getjpiw(0, 0, 0, &jpi_itm_lst, 0, 0, 0);\n    if ((sts & STS$M_SEVERITY) != STS$K_SUCCESS)\n    {\n        /* Failed.  Don't try again. */\n        rms_defaults_known = -1;\n    }\n    else\n    {\n        /* Fine, but don't come back. */\n        rms_defaults_known = 1;\n    }\n\n    /* Limit the active values according to the RMS_DEFAULT values. */\n\n    if (rms_defaults_known > 0)\n    {\n        /* Set the default values. */\n        rms_ext_active = RMS_DEQ_DEFAULT;\n        rms_mbc_active = RMS_MBC_DEFAULT;\n        rms_mbf_active = RMS_MBF_DEFAULT;\n\n        /* Default extend quantity.  Use the user value, if set. */\n        if (rms_ext > 0)\n        {\n            rms_ext_active = rms_ext;\n        }\n\n        /* Default multi-block count.  Use the user value, if set. */\n        if (rms_mbc > 0)\n        {\n            rms_mbc_active = rms_mbc;\n        }\n\n        /* Default multi-buffer count.  Use the user value, if set. */\n        if (rms_mbf > 0)\n        {\n            rms_mbf_active = rms_mbf;\n        }\n    }\n\n    if (DIAG_FLAG)\n    {\n        fprintf(stderr, \"Get RMS defaults.  getjpi sts = %%x%08x.\\n\", sts);\n\n        if (rms_defaults_known > 0)\n        {\n            fprintf(stderr,\n              \"               Default: deq = %6d, mbc = %3d, mbf = %3d.\\n\",\n              rms_ext, rms_mbc, rms_mbf);\n        }\n    }\n    return sts;\n}\n\n\nint check_format(__G)\n    __GDEF\n{\n    int rtype;\n    int sts;\n    struct FAB fab;\n#ifdef NAML$C_MAXRSS\n    struct NAML nam;\n#endif\n\n    fab = cc$rms_fab;                   /* Initialize FAB. */\n\n#ifdef NAML$C_MAXRSS\n\n    nam = cc$rms_naml;                  /* Initialize NAML. */\n    fab.fab$l_naml = &nam;              /* Point FAB to NAML. */\n\n    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = G.zipfn;\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(G.zipfn);\n\n    if (ERR(sts = sys$open(&fab)))\n    {\n        Info(slide, 1, ((char *)slide, \"\\n\\\n     error:  cannot open zipfile [ %s ].\\n\",\n          FnFilter1(G.zipfn)));\n        vms_msg(__G__ \"     sys$open() error: \", sts);\n        return PK_ERR;\n    }\n    rtype = fab.fab$b_rfm;\n    sys$close(&fab);\n\n    if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)\n    {\n        Info(slide, 1, ((char *)slide, \"\\n\\\n     Error:  zipfile is in variable-length record format.  Please\\n\\\n     run \\\"bilf l %s\\\" to convert the zipfile to stream-LF\\n\\\n     record format.  (BILF is available at various VMS archives.)\\n\\n\",\n          FnFilter1(G.zipfn)));\n        return PK_ERR;\n    }\n\n    return PK_COOL;\n}\n\n\n\n#define PRINTABLE_FORMAT(x)      ( (x) == FAB$C_VAR     \\\n                                || (x) == FAB$C_STMLF   \\\n                                || (x) == FAB$C_STMCR   \\\n                                || (x) == FAB$C_STM     )\n\n/* VMS extra field types */\n#define VAT_NONE    0\n#define VAT_IZ      1   /* old Info-ZIP format */\n#define VAT_PK      2   /* PKWARE format */\n\n/*\n *  open_outfile() assignments:\n *\n *  VMS attributes ?        create_xxx      _flush_xxx\n *  ----------------        ----------      ----------\n *  not found               'default'       text mode ?\n *                                          yes -> 'stream'\n *                                          no  -> 'block'\n *\n *  yes, in IZ format       'rms'           uO.cflag ?\n *                                          yes -> switch (fab.rfm)\n *                                              VAR  -> 'varlen'\n *                                              STM* -> 'stream'\n *                                              default -> 'block'\n *                                          no -> 'block'\n *\n *  yes, in PK format       'qio'           uO.cflag ?\n *                                          yes -> switch (pka_rattr)\n *                                              VAR  -> 'varlen'\n *                                              STM* -> 'stream'\n *                                              default -> 'block'\n *                                          no -> 'qio'\n *\n *  \"text mode\" == G.pInfo->textmode || (uO.cflag && !uO.bflag)\n *  (simplified, for complete expression see create_default_output() code)\n */\n\n/* The VMS version of open_outfile() supports special return codes:\n *      OPENOUT_OK            a file has been opened normally\n *      OPENOUT_FAILED        the file open process failed\n *      OPENOUT_SKIPOK        file open skipped at user request, err level OK\n *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN\n */\nint open_outfile(__G)\n    __GDEF\n{\n    /* Get process RMS_DEFAULT values, if not already done. */\n    if (rms_defaults_known == 0)\n    {\n        get_rms_defaults();\n    }\n\n    switch (find_vms_attrs(__G__ (uO.D_flag <= 1)))\n    {\n        case VAT_NONE:\n        default:\n            return  create_default_output(__G);\n        case VAT_IZ:\n            return  create_rms_output(__G);\n        case VAT_PK:\n            return  create_qio_output(__G);\n    }\n}\n\nstatic void init_buf_ring()\n{\n    locptr = &locbuf[0];\n    loccnt = 0;\n\n    b1.buf = &locbuf[0];\n    b1.bufcnt = 0;\n    b1.next = &b2;\n    b2.buf = &locbuf[BUFS512];\n    b2.bufcnt = 0;\n    b2.next = &b1;\n    curbuf = &b1;\n}\n\n\n/* Static data storage for time conversion: */\n\n/*   string constants for month names */\nstatic ZCONST char *month[] =\n            {\"JAN\", \"FEB\", \"MAR\", \"APR\", \"MAY\", \"JUN\",\n             \"JUL\", \"AUG\", \"SEP\", \"OCT\", \"NOV\", \"DEC\"};\n\n/*   buffer for time string */\nstatic char timbuf[24];         /* length = first entry in \"date_str\" + 1 */\n\n/*   fixed-length string descriptor for timbuf: */\nstatic ZCONST struct dsc$descriptor date_str =\n            {sizeof(timbuf)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};\n\n\nstatic void set_default_datetime_XABs(__GPRO)\n{\n    unsigned yr, mo, dy, hh, mm, ss;\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    struct tm *t;\n\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n         & EB_UT_FL_MTIME))\n        t = localtime(&(z_utime.mtime));\n    else\n        t = (struct tm *)NULL;\n    if (t != (struct tm *)NULL)\n    {\n        yr = t->tm_year + 1900;\n        mo = t->tm_mon;\n        dy = t->tm_mday;\n        hh = t->tm_hour;\n        mm = t->tm_min;\n        ss = t->tm_sec;\n    }\n    else\n    {\n        yr = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + 1980;\n        mo = ((G.lrec.last_mod_dos_datetime >> 21) & 0x0f) - 1;\n        dy = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;\n        hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;\n        mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;\n        ss = (G.lrec.last_mod_dos_datetime << 1) & 0x3e;\n    }\n#else /* !USE_EF_UT_TIME */\n\n    yr = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + 1980;\n    mo = ((G.lrec.last_mod_dos_datetime >> 21) & 0x0f) - 1;\n    dy = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;\n    hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;\n    mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;\n    ss = (G.lrec.last_mod_dos_datetime << 1) & 0x1f;\n#endif /* ?USE_EF_UT_TIME */\n\n    dattim = cc$rms_xabdat;     /* fill XABs with default values */\n    rdt = cc$rms_xabrdt;\n    sprintf(timbuf, \"%02u-%3s-%04u %02u:%02u:%02u.00\",\n            dy, month[mo], yr, hh, mm, ss);\n    sys$bintim(&date_str, &dattim.xab$q_cdt);\n    memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));\n}\n\n\n/* The following return codes are supported:\n *      OPENOUT_OK            a file has been opened normally\n *      OPENOUT_FAILED        the file open process failed\n *      OPENOUT_SKIPOK        file open skipped at user request, err level OK\n *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN\n */\nstatic int create_default_output(__GPRO)\n{\n    int ierr;\n    int text_output, bin_fixed;\n\n    /* Extract the file in text format (Variable_length by default,\n     * Stream_LF with \"-S\" (/TEXT = STMLF), when\n     *  a) explicitly requested by the user (through the -a option),\n     *     and it is not a symbolic link,\n     * or\n     *  b) piping to SYS$OUTPUT, unless \"binary\" piping was requested\n     *     by the user (through the -b option).\n     */\n    text_output = (G.pInfo->textmode\n#ifdef SYMLINKS\n                   && !G.symlnk\n#endif\n                  ) ||\n                  (uO.cflag &&\n                   (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile)));\n    /* Use fixed length 512 byte record format for disk file when\n     *  a) explicitly requested by the user (-b option),\n     * and\n     *  b) it is not a symbolic link,\n     * and\n     *  c) it is not extracted in text mode.\n     */\n    bin_fixed = !text_output &&\n#ifdef SYMLINKS\n                !G.symlnk &&\n#endif\n                (uO.bflag != 0) && ((uO.bflag != 1) || !G.pInfo->textfile);\n\n    rfm = FAB$C_STMLF;  /* Default, stream-LF format from VMS or UNIX */\n\n    if (!uO.cflag)              /* Redirect output */\n    {\n        rab = cc$rms_rab;               /* Initialize RAB. */\n        fileblk = cc$rms_fab;           /* Initialize FAB. */\n\n        fileblk.fab$l_xab = NULL;       /* No XABs. */\n        rab.rab$l_fab = &fileblk;       /* Point RAB to FAB. */\n\n        outfab = &fileblk;              /* Set pointers used elsewhere. */\n        outrab = &rab;\n\n        if (text_output && (!uO.S_flag))\n        {   /* Default format for output `real' text file */\n            fileblk.fab$b_rfm = FAB$C_VAR;      /* variable length records */\n            fileblk.fab$b_rat = FAB$M_CR;       /* implied (CR) carriage ctrl */\n        }\n        else if (bin_fixed)\n        {   /* Default format for output `real' binary file */\n            fileblk.fab$b_rfm = FAB$C_FIX;      /* fixed length records */\n            fileblk.fab$w_mrs = 512;            /* record size 512 bytes */\n            fileblk.fab$b_rat = 0;              /* no carriage ctrl */\n        }\n        else\n        {   /* Default format for output misc (bin or text) file */\n            fileblk.fab$b_rfm = FAB$C_STMLF;    /* stream-LF record format */\n            fileblk.fab$b_rat = FAB$M_CR;       /* implied (CR) carriage ctrl */\n        }\n\n#ifdef NAML$C_MAXRSS\n\n        nam = CC_RMS_NAM;               /* Initialize NAML. */\n        fileblk.FAB_NAM = &nam;         /* Point FAB to NAML. */\n\n        fileblk.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n        fileblk.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNA = G.filename;\n        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNS = strlen(G.filename);\n\n        /* Prepare date-time XABs, unless user requests not to. */\n        if (uO.D_flag <= 1) {\n            set_default_datetime_XABs(__G);\n            dattim.xab$l_nxt = fileblk.fab$l_xab;\n            fileblk.fab$l_xab = (void *) &dattim;\n        }\n\n/* 2005-02-14 SMS.  What does this mean?  ----vvvvvvvvvvvvvvvvvvvvvvvvvvv */\n        fileblk.fab$w_ifi = 0;  /* Clear IFI. It may be nonzero after ZIP */\n        fileblk.fab$b_fac = FAB$M_BRO | FAB$M_PUT;  /* {block|record} output */\n#ifdef SYMLINKS\n        if (G.symlnk)\n            /* Symlink file is read back to retrieve the link text. */\n            fileblk.fab$b_fac |= FAB$M_GET;\n#endif\n\n        /* 2004-11-23 SMS.\n         * If RMS_DEFAULT values have been determined, and have not been\n         * set by the user, then set some FAB/RAB parameters for faster\n         * output.  User-specified RMS_DEFAULT values override the\n         * built-in default values, so if the RMS_DEFAULT values could\n         * not be determined, then these (possibly unwise) values could\n         * not be overridden, and hence will not be set.  Honestly,\n         * this seems to be excessively cautious, but only old VMS\n         * versions will be affected.\n         */\n\n        /* If RMS_DEFAULT (and adjusted active) values are available,\n         * then set the FAB/RAB parameters.  If RMS_DEFAULT values are\n         * not available, then suffer with the default behavior.\n         */\n        if (rms_defaults_known > 0)\n        {\n            /* Set the FAB/RAB parameters accordingly. */\n            fileblk.fab$w_deq = rms_ext_active;\n            rab.rab$b_mbc = rms_mbc_active;\n            rab.rab$b_mbf = rms_mbf_active;\n\n#ifdef OLD_FABDEF\n\n            /* Truncate at EOF on close, as we may over-extend. */\n            fileblk.fab$l_fop |= FAB$M_TEF ;\n\n            /* If using multiple buffers, enable write-behind. */\n            if (rms_mbf_active > 1)\n            {\n                rab.rab$l_rop |= RAB$M_WBH;\n            }\n        }\n\n        /* Set the initial file allocation according to the file\n         * size.  Also set the \"sequential access only\" flag, as\n         * otherwise, on a file system with highwater marking\n         * enabled, allocating space for a large file may lock the\n         * disk for a long time (minutes).\n         */\n        fileblk.fab$l_alq = (unsigned) (G.lrec.ucsize+ 511)/ 512;\n        fileblk.fab$l_fop |= FAB$M_SQO;\n\n#else /* !OLD_FABDEF */\n\n            /* Truncate at EOF on close, as we may over-extend. */\n            fileblk.fab$v_tef = 1;\n\n            /* If using multiple buffers, enable write-behind. */\n            if (rms_mbf_active > 1)\n            {\n                rab.rab$v_wbh = 1;\n            }\n        }\n\n        /* Set the initial file allocation according to the file\n         * size.  Also set the \"sequential access only\" flag, as\n         * otherwise, on a file system with highwater marking\n         * enabled, allocating space for a large file may lock the\n         * disk for a long time (minutes).\n         */\n        fileblk.fab$l_alq = (unsigned) (G.lrec.ucsize+ 511)/ 512;\n        fileblk.fab$v_sqo = 1;\n\n#endif /* ?OLD_FABDEF */\n\n        ierr = sys$create(outfab);\n        if (ierr == RMS$_FEX)\n        {\n            /* File exists.\n             * Consider command-line options, or ask the user what to do.\n             */\n            ierr = replace(__G);\n            switch (ierr & REPL_TASKMASK)\n            {\n                case REPL_NO_EXTRACT:   /* No extract. */\n                    free_up();\n                    return ((ierr & REPL_ERRLV_WARN)\n                            ? OPENOUT_SKIPWARN : OPENOUT_SKIPOK);\n                case REPL_NEW_VERSION:  /* Create a new version. */\n                    ierr = replace_rms_newversion(__G);\n                    break;\n                case REPL_OVERWRITE:    /* Overwrite the existing file. */\n                    ierr = replace_rms_overwrite(__G);\n                    break;\n            }\n        }\n\n        if (ERR(ierr))\n        {\n            char buf[NAM_MAXRSS + 128]; /* Name length + message length. */\n\n            sprintf(buf, \"[ Cannot create ($create) output file %s ]\\n\",\n              G.filename);\n            vms_msg(__G__ buf, ierr);\n            if (fileblk.fab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", fileblk.fab$l_stv);\n            }\n            free_up();\n            return OPENOUT_FAILED;\n        }\n\n        if (!text_output)\n        {\n            rab.rab$l_rop |= (RAB$M_BIO | RAB$M_ASY);\n        }\n        rab.rab$b_rac = RAB$C_SEQ;\n\n        if ((ierr = sys$connect(&rab)) != RMS$_NORMAL)\n        {\n#ifdef DEBUG\n            vms_msg(__G__ \"create_default_output: sys$connect failed.\\n\", ierr);\n            if (fileblk.fab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", fileblk.fab$l_stv);\n            }\n#endif\n            Info(slide, 1, ((char *)slide,\n                 \"Cannot create ($connect) output file:  %s\\n\",\n                 FnFilter1(G.filename)));\n            free_up();\n            return OPENOUT_FAILED;\n        }\n    }                   /* end if (!uO.cflag) */\n\n    init_buf_ring();\n\n    _flush_routine = text_output ? got_eol=0,_flush_stream : _flush_blocks;\n    _close_routine = _close_rms;\n    return OPENOUT_OK;\n}\n\n\n\n/* The following return codes are supported:\n *      OPENOUT_OK            a file has been opened normally\n *      OPENOUT_FAILED        the file open process failed\n *      OPENOUT_SKIPOK        file open skipped at user request, err level OK\n *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN\n */\nstatic int create_rms_output(__GPRO)\n{\n    int ierr;\n    int text_output;\n\n    /* extract the file in text (variable-length) format, when\n     * piping to SYS$OUTPUT, unless \"binary\" piping was requested\n     * by the user (through the -b option); the \"-a\" option is\n     * ignored when extracting zip entries with VMS attributes saved\n     */\n    text_output = uO.cflag &&\n                  (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile));\n\n    rfm = outfab->fab$b_rfm;    /* Use record format from VMS extra field */\n\n    if (uO.cflag)               /* SYS$OUTPUT */\n    {\n        if (text_output && !PRINTABLE_FORMAT(rfm))\n        {\n            Info(slide, 1, ((char *)slide,\n               \"[ File %s has illegal record format to put to screen ]\\n\",\n               FnFilter1(G.filename)));\n            free_up();\n            return OPENOUT_FAILED;\n        }\n    }\n    else                        /* File output */\n    {\n        rab = cc$rms_rab;               /* Initialize RAB. */\n\n        /* The output FAB has already been initialized with the values\n         * found in the Zip file's \"VMS attributes\" extra field.\n         */\n\n#ifdef NAML$C_MAXRSS\n\n        nam = CC_RMS_NAM;               /* Initialize NAML. */\n        outfab->FAB_NAM = &nam;         /* Point FAB to NAML. */\n\n        outfab->fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n        outfab->fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n        FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNA = G.filename;\n        FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNS = strlen(G.filename);\n\n        /* Prepare date-time XABs, unless user requests not to. */\n        if (uO.D_flag <= 1) {\n            /* If no XAB date/time, use attributes from non-VMS fields. */\n            if (!(xabdat && xabrdt))\n            {\n                set_default_datetime_XABs(__G);\n\n                if (xabdat == NULL)\n                {\n                    dattim.xab$l_nxt = outfab->fab$l_xab;\n                    outfab->fab$l_xab = (void *) &dattim;\n                }\n            }\n        }\n/* 2005-02-14 SMS.  What does this mean?  ----vvvvvvvvvvvvvvvvvvvvvvvvvvv */\n        outfab->fab$w_ifi = 0;  /* Clear IFI. It may be nonzero after ZIP */\n        outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT;      /* block-mode output */\n#ifdef SYMLINKS\n        /* 2007-02-28 SMS.\n         * VMS/RMS symlink properties will be restored naturally when\n         * the link file is recreated this way, so there's no need to do\n         * the deferred symlink post-processing step for this file.\n         * Therefore, clear the pInfo->symlink flag here, and the symlink\n         * \"close file\" processor will only display the link text.\n         */\n        if (G.symlnk) {\n            G.pInfo->symlink = 0;\n            if (QCOND2) {\n                /* Symlink file is read back to display the link text. */\n                outfab->fab$b_fac |= FAB$M_GET;\n            }\n        }\n#endif /* SYMLINKS */\n\n        /* 2004-11-23 SMS.\n         * Set the \"sequential access only\" flag, as otherwise, on a\n         * file system with highwater marking enabled, allocating space\n         * for a large file may lock the disk for a long time (minutes).\n         */\n#ifdef OLD_FABDEF\n        outfab-> fab$l_fop |= FAB$M_SQO;\n#else /* !OLD_FABDEF */\n        outfab-> fab$v_sqo = 1;\n#endif /* ?OLD_FABDEF */\n\n        ierr = sys$create(outfab);\n        if (ierr == RMS$_FEX)\n        {\n            /* File exists.\n             * Consider command-line options, or ask the user what to do.\n             */\n            ierr = replace(__G);\n            switch (ierr & REPL_TASKMASK)\n            {\n                case REPL_NO_EXTRACT:   /* No extract. */\n                    free_up();\n                    return ((ierr & REPL_ERRLV_WARN)\n                            ? OPENOUT_SKIPWARN : OPENOUT_SKIPOK);\n                case REPL_NEW_VERSION:  /* Create a new version. */\n                    ierr = replace_rms_newversion(__G);\n                    break;\n                case REPL_OVERWRITE:    /* Overwrite the existing file. */\n                    ierr = replace_rms_overwrite(__G);\n                    break;\n            }\n        }\n\n        if (ERR(ierr))\n        {\n            char buf[NAM_MAXRSS + 128]; /* Name length + message length. */\n\n            sprintf(buf, \"[ Cannot create ($create) output file %s ]\\n\",\n              G.filename);\n            vms_msg(__G__ buf, ierr);\n            if (outfab->fab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outfab->fab$l_stv);\n            }\n            free_up();\n            return OPENOUT_FAILED;\n        }\n\n        if (outfab->fab$b_org & (FAB$C_REL | FAB$C_IDX)) {\n            /* relative and indexed files require explicit allocation */\n            ierr = sys$extend(outfab);\n            if (ERR(ierr))\n            {\n                char buf[NAM_MAXRSS + 128];    /* Name length + msg length. */\n\n                sprintf(buf, \"[ Cannot allocate space for %s ]\\n\", G.filename);\n                vms_msg(__G__ buf, ierr);\n                if (outfab->fab$l_stv != 0)\n                {\n                    vms_msg(__G__ \"\", outfab->fab$l_stv);\n                }\n                free_up();\n                return OPENOUT_FAILED;\n            }\n        }\n\n        outrab = &rab;\n        rab.rab$l_fab = outfab;\n        {\n            rab.rab$l_rop |= (RAB$M_BIO | RAB$M_ASY);\n        }\n        rab.rab$b_rac = RAB$C_SEQ;\n\n        if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)\n        {\n#ifdef DEBUG\n            vms_msg(__G__ \"create_rms_output: sys$connect failed.\\n\", ierr);\n            if (outfab->fab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outfab->fab$l_stv);\n            }\n#endif\n            Info(slide, 1, ((char *)slide,\n                 \"Cannot create ($connect) output file:  %s\\n\",\n                 FnFilter1(G.filename)));\n            free_up();\n            return OPENOUT_FAILED;\n        }\n    }                   /* end if (!uO.cflag) */\n\n    init_buf_ring();\n\n    if ( text_output )\n        switch (rfm)\n        {\n            case FAB$C_VAR:\n                _flush_routine = _flush_varlen;\n                break;\n            case FAB$C_STM:\n            case FAB$C_STMCR:\n            case FAB$C_STMLF:\n                _flush_routine = _flush_stream;\n                got_eol = 0;\n                break;\n            default:\n                _flush_routine = _flush_blocks;\n                break;\n        }\n    else\n        _flush_routine = _flush_blocks;\n    _close_routine = _close_rms;\n    return OPENOUT_OK;\n}\n\n\n\nstatic  int pka_devchn;\nstatic  int pka_io_pending;\nstatic  unsigned pka_vbn;\n\n/* IOSB for QIO[W] read and write operations. */\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\nstatic struct\n{\n    unsigned short  status;\n    unsigned int    count;      /* Unaligned ! */\n    unsigned short  dummy;\n} pka_io_iosb;\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n/* IOSB for QIO[W] miscellaneous ACP operations. */\nstatic struct\n{\n    unsigned short  status;\n    unsigned short  dummy;\n    unsigned int    count;\n} pka_acp_iosb;\n\nstatic struct fibdef    pka_fib;\nstatic struct atrdef    pka_atr[VMS_MAX_ATRCNT];\nstatic int              pka_idx;\nstatic ulg              pka_uchar;\nstatic struct fatdef    pka_rattr;\n\n/* Directory attribute storage, descriptor (list). */\nstatic struct atrdef pka_recattr[2] =\n { { sizeof(pka_rattr), ATR$C_RECATTR, GVTC &pka_rattr},        /* RECATTR. */\n   { 0, 0, 0 }                                          /* List terminator. */\n };\n\nstatic struct dsc$descriptor    pka_fibdsc =\n{   sizeof(pka_fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (void *) &pka_fib  };\n\nstatic struct dsc$descriptor_s  pka_devdsc =\n{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &nam.NAM_DVI[1]  };\n\nstatic struct dsc$descriptor_s  pka_fnam =\n{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL  };\n\n/* Expanded and resultant name storage. */\nstatic char exp_nam[NAM_MAXRSS];\nstatic char res_nam[NAM_MAXRSS];\n\n/* Special ODS5-QIO-compatible name storage. */\n#ifdef NAML$C_MAXRSS\nstatic char sys_nam[NAML$C_MAXRSS];     /* Probably need less here. */\n#endif /* NAML$C_MAXRSS */\n\n#define PK_PRINTABLE_RECTYP(x)   ( (x) == FAT$C_VARIABLE \\\n                                || (x) == FAT$C_STREAMLF \\\n                                || (x) == FAT$C_STREAMCR \\\n                                || (x) == FAT$C_STREAM   )\n\n\n/* The following return codes are supported:\n *      OPENOUT_OK            a file has been opened normally\n *      OPENOUT_FAILED        the file open process failed\n *      OPENOUT_SKIPOK        file open skipped at user request, err level OK\n *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN\n */\nstatic int create_qio_output(__GPRO)\n{\n    int status;\n    int i;\n    int text_output;\n\n    /* extract the file in text (variable-length) format, when\n     * piping to SYS$OUTPUT, unless \"binary\" piping was requested\n     * by the user (through the -b option); the \"-a\" option is\n     * ignored when extracting zip entries with VMS attributes saved\n     */\n    text_output = uO.cflag &&\n                  (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile));\n\n    if ( uO.cflag )\n    {\n        int rtype;\n\n        if (text_output)\n        {\n            rtype = pka_rattr.fat$v_rtype;\n            if (!PK_PRINTABLE_RECTYP(rtype))\n            {\n                Info(slide, 1, ((char *)slide,\n                   \"[ File %s has illegal record format to put to screen ]\\n\",\n                   FnFilter1(G.filename)));\n                return OPENOUT_FAILED;\n            }\n        }\n        else\n            /* force \"block I/O\" for binary piping mode */\n            rtype = FAT$C_UNDEFINED;\n\n        init_buf_ring();\n\n        switch (rtype)\n        {\n            case FAT$C_VARIABLE:\n                _flush_routine = _flush_varlen;\n                break;\n            case FAT$C_STREAM:\n            case FAT$C_STREAMCR:\n            case FAT$C_STREAMLF:\n                _flush_routine = _flush_stream;\n                got_eol = 0;\n                break;\n            default:\n                _flush_routine = _flush_blocks;\n                break;\n        }\n        _close_routine = _close_rms;\n    }\n    else                        /* !(uO.cflag) : redirect output */\n    {\n        fileblk = cc$rms_fab;           /* Initialize FAB. */\n        nam = CC_RMS_NAM;               /* Initialize NAM[L]. */\n        fileblk.FAB_NAM = &nam;         /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n        fileblk.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n        fileblk.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n        /* Special ODS5-QIO-compatible name storage. */\n        nam.naml$l_filesys_name = sys_nam;\n        nam.naml$l_filesys_name_alloc = sizeof(sys_nam);\n\n#endif /* NAML$C_MAXRSS */\n\n        /* VMS-format file name, derived from archive. */\n        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNA = G.filename;\n        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNS = strlen(G.filename);\n\n        /* Expanded and resultant name storage. */\n        nam.NAM_ESA = exp_nam;\n        nam.NAM_ESS = sizeof(exp_nam);\n        nam.NAM_RSA = res_nam;\n        nam.NAM_RSS = sizeof(res_nam);\n\n        if ( ERR(status = sys$parse(&fileblk)) )\n        {\n            vms_msg(__G__ \"create_qio_output: sys$parse failed.\\n\", status);\n            return OPENOUT_FAILED;\n        }\n\n        pka_devdsc.dsc$w_length = (unsigned short)nam.NAM_DVI[0];\n\n        if ( ERR(status = sys$assign(&pka_devdsc, &pka_devchn, 0, 0)) )\n        {\n            vms_msg(__G__ \"create_qio_output: sys$assign failed.\\n\", status);\n            return OPENOUT_FAILED;\n        }\n\n#ifdef NAML$C_MAXRSS\n\n        /* Enable fancy name characters.  Note that \"fancy\" here does\n           not include Unicode, for which there's no support elsewhere.\n        */\n        pka_fib.fib$v_names_8bit = 1;\n        pka_fib.fib$b_name_format_in = FIB$C_ISL1;\n\n        /* ODS5 Extended names used as input to QIO have peculiar\n           encoding (perhaps to minimize storage?), so the special\n           filesys_name result (typically containing fewer carets) must\n           be used here.\n        */\n        pka_fnam.dsc$a_pointer = nam.naml$l_filesys_name;\n        pka_fnam.dsc$w_length = nam.naml$l_filesys_name_size;\n\n#else /* !NAML$C_MAXRSS */\n\n        /* Extract only the name.type;version.\n           2005-02-14 SMS.\n           Note: In old code, the version in the name here was retained\n           only if -V (uO.V_flag, so that there might be an explicit\n           version number in the archive (or perhaps not)), but the\n           version should already have been stripped before this in\n           adj_file_name_odsX(), and sys$parse() here should always\n           return a good version number which may be used as-is.  If\n           not, here's where to fix the (new) problem.  Note that the\n           ODS5-compatible code uses the whole thing in filesys_name,\n           too, and that's critical for proper interpretation of funny\n           names.  (Omitting the \";\" can cause trouble, so it should\n           certainly be kept, even if the version digits are removed\n           here.)\n        */\n\n        pka_fnam.dsc$a_pointer = nam.NAM_L_NAME;\n        pka_fnam.dsc$w_length =\n          nam.NAM_B_NAME + nam.NAM_B_TYPE + nam.NAM_B_VER;\n\n#if 0\n        pka_fnam.dsc$w_length = nam.NAM_B_NAME + nam.NAM_B_TYPE;\n        if ( uO.V_flag /* keep versions */ )\n            pka_fnam.dsc$w_length += nam.NAM_B_VER;\n#endif /* 0 */\n\n#endif /* ?NAML$C_MAXRSS */\n\n        /* Move the directory ID from the NAM[L] to the FIB.\n           Clear the FID in the FIB, as we're using the name.\n        */\n        for (i = 0; i < 3; i++)\n        {\n            pka_fib.FIB$W_DID[i] = nam.NAM_DID[i];\n            pka_fib.FIB$W_FID[i] = 0;\n        }\n\n        /* 2004-11-23 SMS.\n         * Set the \"sequential access only\" flag, as otherwise, on a\n         * file system with highwater marking enabled, allocating space\n         * for a large file may lock the disk for a long time (minutes).\n         * (The \"no other readers\" flag is also required, if you want\n         * the \"sequential access only\" flag to have any effect.)\n         */\n        pka_fib.FIB$L_ACCTL = FIB$M_WRITE | FIB$M_SEQONLY | FIB$M_NOREAD;\n\n        /* Allocate space for the file */\n        pka_fib.FIB$W_EXCTL = FIB$M_EXTEND;\n        if ( pka_uchar & FCH$M_CONTIG )\n            pka_fib.FIB$W_EXCTL |= FIB$M_ALCON | FIB$M_FILCON;\n        if ( pka_uchar & FCH$M_CONTIGB )\n            pka_fib.FIB$W_EXCTL |= FIB$M_ALCONB;\n\n#define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )\n\n        pka_fib.fib$l_exsz = SWAPW(pka_rattr.fat$l_hiblk);\n\n        status = sys$qiow(0,                /* event flag */\n                          pka_devchn,       /* channel */\n                          IO$_CREATE|IO$M_CREATE|IO$M_ACCESS, /* funct */\n                          &pka_acp_iosb,    /* IOSB */\n                          0,                /* AST address */\n                          0,                /* AST parameter */\n                          &pka_fibdsc,      /* P1 = File Info Block */\n                          &pka_fnam,        /* P2 = File name (descr) */\n                          0,                /* P3 (= Resulting name len) */\n                          0,                /* P4 (= Resulting name descr) */\n                          pka_atr,          /* P5 = Attribute descr */\n                          0);               /* P6 (not used) */\n\n        if ( !ERR(status) )\n            status = pka_acp_iosb.status;\n\n        if ( status == SS$_DUPFILENAME )\n        {\n            /* File exists.  Prepare to ask user what to do. */\n\n            /* Arrange to store the resultant file spec (with new\n             * version?) where the message code will find it.\n             */\n            short res_nam_len;\n            struct dsc$descriptor_s  res_nam_dscr =\n              { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };\n\n            res_nam_dscr.dsc$a_pointer = G.filename;\n            res_nam_dscr.dsc$w_length = sizeof(G.filename);\n\n            /* File exists.\n             * Consider command-line options, or ask the user what to do.\n             */\n            status = replace(__G);\n            switch (status & REPL_TASKMASK)\n            {\n                case REPL_NO_EXTRACT:   /* No extract. */\n                    free_up();\n                    return ((status & REPL_ERRLV_WARN)\n                            ? OPENOUT_SKIPWARN : OPENOUT_SKIPOK);\n                case REPL_NEW_VERSION:  /* Create a new version. */\n                    pka_fib.FIB$W_NMCTL |= FIB$M_NEWVER;\n                    break;\n                case REPL_OVERWRITE:    /* Overwrite the existing file. */\n                    pka_fib.FIB$W_NMCTL |= FIB$M_SUPERSEDE;\n                    break;\n            }\n\n            /* Retry file creation with new (user-specified) policy. */\n            status = sys$qiow(0,                /* event flag */\n                              pka_devchn,       /* channel */\n                              IO$_CREATE|IO$M_CREATE|IO$M_ACCESS, /* funct */\n                              &pka_acp_iosb,    /* IOSB */\n                              0,                /* AST address */\n                              0,                /* AST parameter */\n                              &pka_fibdsc,      /* P1 = File Info Block */\n                              &pka_fnam,        /* P2 = File name (descr) */\n                              &res_nam_len,     /* P3 = Resulting name len */\n                              &res_nam_dscr,    /* P4 = Resulting name descr */\n                              pka_atr,          /* P5 = Attribute descr */\n                              0);               /* P6 (not used) */\n\n            if ( !ERR(status) )\n                status = pka_acp_iosb.status;\n\n            if (res_nam_len > 0)\n            {\n                /* NUL-terminate the resulting file spec. */\n                G.filename[res_nam_len] = '\\0';\n            }\n\n            /* Clear any user-specified version policy flags\n             * (for the next file to be processed).\n             */\n            pka_fib.FIB$W_NMCTL &= (~(FIB$M_NEWVER| FIB$M_SUPERSEDE));\n        }\n\n        if ( ERR(status) )\n        {\n            char buf[NAM_MAXRSS + 128]; /* Name length + message length. */\n\n            sprintf(buf, \"[ Cannot create (QIO) output file %s ]\\n\",\n              G.filename);\n            vms_msg(__G__ buf, status);\n            sys$dassgn(pka_devchn);\n            return OPENOUT_FAILED;\n        }\n\n#ifdef ASYNCH_QIO\n        init_buf_ring();\n        pka_io_pending = FALSE;\n#else\n        locptr = locbuf;\n        loccnt = 0;\n#endif\n        pka_vbn = 1;\n        _flush_routine = _flush_qio;\n        _close_routine = _close_qio;\n    }                   /* end if (!uO.cflag) */\n    return OPENOUT_OK;\n}\n\n\n/* 2008-07-23 SMS.\n * Segregated user query function from file re-open functions/code.\n *\n * There was no code in create_qio_output() to deal with an\n * SS$_DUPFILENAME condition, leading to ugly run-time failures, and its\n * requirements differ from those of the RMS (non-QIO) functions,\n * create_default_output() and create_rms_output().\n *\n * Whether it makes sense to have a second layer of VMS-specific\n * querying after the generic UnZip query in extract.c:\n * extract_or_test_entrylist() is another question, but changing that\n * looks more scary than just getting the VMS-specific stuff to work\n * right (better?).\n */\n\n/* \"File exists\" handler(s).  Ask user about further action. */\n\n/* RMS create new version. */\nstatic int replace_rms_newversion(__GPRO)\n{\n    int ierr;\n    struct NAM_STRUCT nam;\n\n    nam = CC_RMS_NAM;           /* Initialize local NAM[L] block. */\n    outfab->FAB_NAM = &nam;     /* Point FAB to local NAM[L]. */\n\n    /* Arrange to store the resultant file spec (with new version), so\n     * that we can extract the actual file version from it, for later\n     * use in the \"extracting:/inflating:/...\"  message (G.filename).\n     */\n    nam.NAM_RSA = res_nam;\n    nam.NAM_RSS = sizeof(res_nam);\n\n#ifdef NAML$C_MAXRSS\n\n    outfab->fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    outfab->fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNA = G.filename;\n    FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNS = strlen(G.filename);\n\n    /* Maximize version number. */\n    outfab->fab$l_fop |= FAB$M_MXV;\n\n    /* Create the new-version file. */\n    ierr = sys$create(outfab);\n\n    if (nam.NAM_RSL > 0)\n    {\n        /* File spec version pointers.\n         * Versions must exist, so a simple right-to-left search for \";\"\n         * should work, even on ODS5 extended file specs.\n         */\n        char *semi_col_orig;\n        char *semi_col_res;\n\n        /* NUL-terminate the (complete) resultant file spec. */\n        res_nam[nam.NAM_RSL] = '\\0';\n\n        /* Find the versions (\";\") in the original and resultant file specs. */\n        semi_col_orig = strrchr(G.filename, ';');\n        semi_col_res = strrchr(res_nam, ';');\n\n        if ((semi_col_orig != NULL) && (semi_col_res != NULL))\n        {\n            /* Transfer the resultant version to the original file spec. */\n            strcpy((semi_col_orig + 1), (semi_col_res + 1));\n        }\n    }\n    return ierr;\n}\n\n\n/* RMS overwrite original version. */\nstatic int replace_rms_overwrite(__GPRO)\n{\n    /* Supersede existing file. */\n    outfab->fab$l_fop |= FAB$M_SUP;\n    /* Create (overwrite) the original-version file. */\n    return sys$create(outfab);\n}\n\n\n/* Main query function to ask user how to handle an existing file\n * (unless command-line options already specify what to do).\n */\nstatic int replace(__GPRO)\n{\n    char answ[10];\n    int replace_code;\n\n    if (replace_code_all >= 0)\n    {\n        /* Use the previous all-file response. */\n        replace_code = replace_code_all;\n    }\n    else if (uO.overwrite_none)\n    {\n        /* \"-n\".  Do not extract this (or any) file. */\n        replace_code = replace_code_all = REPL_NO_EXTRACT;\n    }\n    else if (uO.overwrite_all == 1)\n    {\n        /* \"-o\".  Create a new version of this (or any) file. */\n        replace_code = replace_code_all = REPL_NEW_VERSION;\n    }\n    else if (uO.overwrite_all > 1)\n    {\n        /* \"-oo\".  Overwrite (supersede) this (or any) existing file. */\n        replace_code = replace_code_all = REPL_OVERWRITE;\n    }\n    else\n    {\n        replace_code = -1;\n        do\n        {\n            /* Request, accept, and decode a response. */\n            Info(slide, 0x81, ((char *)slide,\n              \"%s exists:  new [v]ersion, [o]verwrite, or [n]o extract?\\n\\\n  (Uppercase response [V,O,N] => Do same for all files): \",\n              FnFilter1(G.filename)));\n            fflush(stderr);\n\n            if (fgets(answ, sizeof(answ), stdin) == (char *)NULL)\n            {\n                Info(slide, 1, ((char *)slide, AssumeNo));\n                /* Handle the NULL answer as \"N\",\n                 * do not extract any existing files.  */\n                replace_code_all = REPL_NO_EXTRACT;\n                /* Set a warning indicator. */\n                replace_code = REPL_NO_EXTRACT | REPL_ERRLV_WARN;\n                /* We are finished, break out of the query loop. */\n                break;\n            }\n\n            /* Strip off a trailing newline, to avoid corrupt\n             * complaints when displaying the answer.\n             */\n            if (answ[strlen(answ) - 1] == '\\n')\n                answ[strlen(answ) - 1] = '\\0';\n\n            /* Extra newline to avoid having the extracting:/inflating:/...:\n             * message overwritten by the next query.\n             */\n            Info(slide, 1, ((char *)slide, \"\\n\"));\n\n            /* Interpret response.  Store upper-case answer for future use. */\n            switch (answ[0])\n            {\n                case 'N':\n                    replace_code_all = REPL_NO_EXTRACT;\n                case 'n':\n                    /* Do not extract this file. */\n                    replace_code = REPL_NO_EXTRACT;\n                    break;\n                case 'O':\n                    replace_code_all = REPL_OVERWRITE;\n                case 'o':\n                    /* Overwrite (supersede) this existing file. */\n                    replace_code = REPL_OVERWRITE;\n                    break;\n                case 'V':\n                    replace_code_all = REPL_NEW_VERSION;\n                case 'v':\n                    /* Create a new version of this file. */\n                    replace_code = REPL_NEW_VERSION;\n                    break;\n                default:\n                    /* Invalid response.  Try again. */\n                    Info(slide, 1, ((char *)slide, InvalidResponse, answ));\n            }\n        } while (replace_code < 0);\n    }\n    return replace_code;\n}\n\n\n\n#define W(p)    (*(unsigned short*)(p))\n#define L(p)    (*(unsigned long*)(p))\n#define EQL_L(a, b)     ( L(a) == L(b) )\n#define EQL_W(a, b)     ( W(a) == W(b) )\n\n/*\n * Function find_vms_attrs() scans the ZIP entry extra field, if any,\n * and looks for VMS attribute records.  Various date-time attributes\n * are ignored if set_date_time is FALSE (typically for a directory).\n *\n * For a set of IZ records, a FAB and various XABs are created and\n * chained together.\n *\n * For a PK record, the pka_atr[] attribute descriptor array is\n * populated.\n *\n * The return value is a VAT_* value, according to the type of extra\n * field attribute data found.\n */\nstatic int find_vms_attrs(__GPRO__ int set_date_time)\n{\n    uch *scan = G.extra_field;\n    struct  EB_header *hdr;\n    int len;\n    int type=VAT_NONE;\n\n    outfab = NULL;\n    xabfhc = NULL;\n    xabdat = NULL;\n    xabrdt = NULL;\n    xabpro = NULL;\n    first_xab = last_xab = NULL;\n\n    if (scan == NULL)\n        return VAT_NONE;\n    len = G.lrec.extra_field_length;\n\n#define LINK(p) {/* Link xaballs and xabkeys into chain */      \\\n                if ( first_xab == NULL )                \\\n                        first_xab = (void *) p;         \\\n                if ( last_xab != NULL )                 \\\n                        last_xab->xab$l_nxt = (void *) p;       \\\n                last_xab = (void *) p;                  \\\n                p->xab$l_nxt = NULL;                    \\\n        }\n    /* End of macro LINK */\n\n    while (len > 0)\n    {\n        hdr = (struct EB_header *)scan;\n        if (EQL_W(&hdr->tag, IZ_SIGNATURE))\n        {\n            /*\n             *  Info-ZIP-style extra block decoding.\n             */\n            uch *blk;\n            unsigned siz;\n            uch *block_id;\n\n            type = VAT_IZ;\n\n            siz = hdr->size;\n            blk = (uch *)(&hdr->data[0]);\n            block_id = (uch *)(&((struct IZ_block *)hdr)->bid);\n\n            if (EQL_L(block_id, FABSIG)) {\n                outfab = (struct FAB *)extract_izvms_block(__G__ blk,\n                  siz, NULL, (uch *)&cc$rms_fab, FABL);\n            } else if (EQL_L(block_id, XALLSIG)) {\n                xaball = (struct XABALL *)extract_izvms_block(__G__ blk,\n                  siz, NULL, (uch *)&cc$rms_xaball, XALLL);\n                LINK(xaball);\n            } else if (EQL_L(block_id, XKEYSIG)) {\n                xabkey = (struct XABKEY *)extract_izvms_block(__G__ blk,\n                  siz, NULL, (uch *)&cc$rms_xabkey, XKEYL);\n                LINK(xabkey);\n            } else if (EQL_L(block_id, XFHCSIG)) {\n                xabfhc = (struct XABFHC *) extract_izvms_block(__G__ blk,\n                  siz, NULL, (uch *)&cc$rms_xabfhc, XFHCL);\n            } else if (EQL_L(block_id, XDATSIG)) {\n                if (set_date_time) {\n                    xabdat = (struct XABDAT *) extract_izvms_block(__G__ blk,\n                      siz, NULL, (uch *)&cc$rms_xabdat, XDATL);\n                }\n            } else if (EQL_L(block_id, XRDTSIG)) {\n                if (set_date_time) {\n                    xabrdt = (struct XABRDT *) extract_izvms_block(__G__ blk,\n                      siz, NULL, (uch *)&cc$rms_xabrdt, XRDTL);\n                }\n            } else if (EQL_L(block_id, XPROSIG)) {\n                xabpro = (struct XABPRO *) extract_izvms_block(__G__ blk,\n                  siz, NULL, (uch *)&cc$rms_xabpro, XPROL);\n            } else if (EQL_L(block_id, VERSIG)) {\n#ifdef CHECK_VERSIONS\n                char verbuf[80];\n                unsigned verlen = 0;\n                uch *vers;\n                char *m;\n\n                get_vms_version(verbuf, sizeof(verbuf));\n                vers = extract_izvms_block(__G__ blk, siz,\n                                           &verlen, NULL, 0);\n                if ((m = strrchr((char *) vers, '-')) != NULL)\n                    *m = '\\0';  /* Cut out release number */\n                if (strcmp(verbuf, (char *) vers) && uO.qflag < 2)\n                {\n                    Info(slide, 0, ((char *)slide,\n                         \"[ Warning: VMS version mismatch.\"));\n\n                    Info(slide, 0, ((char *)slide,\n                         \"   This version %s --\", verbuf));\n                    strncpy(verbuf, (char *) vers, verlen);\n                    verbuf[verlen] = '\\0';\n                    Info(slide, 0, ((char *)slide,\n                         \" version made by %s ]\\n\", verbuf));\n                }\n                free(vers);\n#endif /* CHECK_VERSIONS */\n            } else {\n                Info(slide, 1, ((char *)slide,\n                     \"[ Warning: Unknown block signature %s ]\\n\",\n                     block_id));\n            }\n        }\n        else if (hdr->tag == PK_SIGNATURE)\n        {\n            /*\n             *  PKWARE-style extra block decoding.\n             */\n            struct  PK_header   *blk;\n            register byte   *scn;\n            register int    len;\n\n            type = VAT_PK;\n\n            blk = (struct PK_header *)hdr;\n            len = blk->size - (PK_HEADER_SIZE - EB_HEADSIZE);\n            scn = (byte *)(&blk->data);\n            pka_idx = 0;\n\n            if (blk->crc32 != crc32(CRCVAL_INITIAL, scn, (extent)len))\n            {\n                Info(slide, 1, ((char *)slide,\n                  \"[ Warning: CRC error, discarding PKWARE extra field ]\\n\"));\n                len = 0;\n                type = VAT_NONE;\n            }\n\n            while (len > PK_FLDHDR_SIZE)\n            {\n                register struct  PK_field  *fld;\n                int skip=0;\n\n                fld = (struct PK_field *)scn;\n                switch(fld->tag)\n                {\n                    case ATR$C_UCHAR:\n                        pka_uchar = L(&fld->value);\n                        break;\n                    case ATR$C_RECATTR:\n                        pka_rattr = *(struct fatdef *)(&fld->value);\n                        break;\n                    case ATR$C_UIC:\n                    case ATR$C_ADDACLENT:\n                        skip = !uO.X_flag;\n                        break;\n                    case ATR$C_CREDATE:\n                    case ATR$C_REVDATE:\n                    case ATR$C_EXPDATE:\n                    case ATR$C_BAKDATE:\n                    case ATR$C_ASCDATES:\n                        skip = (set_date_time == FALSE);\n                        break;\n                }\n\n                if ( !skip )\n                {\n                    pka_atr[pka_idx].atr$w_size = fld->size;\n                    pka_atr[pka_idx].atr$w_type = fld->tag;\n                    pka_atr[pka_idx].atr$l_addr = GVTC &fld->value;\n                    ++pka_idx;\n                }\n                len -= fld->size + PK_FLDHDR_SIZE;\n                scn += fld->size + PK_FLDHDR_SIZE;\n            }\n            pka_atr[pka_idx].atr$w_size = 0;    /* End of list */\n            pka_atr[pka_idx].atr$w_type = 0;\n            pka_atr[pka_idx].atr$l_addr = 0; /* NULL when DECC VAX gets fixed */\n        }\n        len -= hdr->size + EB_HEADSIZE;\n        scan += hdr->size + EB_HEADSIZE;\n    }\n\n    if ( type == VAT_IZ )\n    {\n        if (outfab != NULL)\n        {\n            /* Do not link XABPRO or XABRDT now.\n             * Leave them for sys$close() resp. set_direc_attribs().\n             */\n            outfab->fab$l_xab = NULL;\n            if (xabfhc != NULL)\n            {\n                xabfhc->xab$l_nxt = outfab->fab$l_xab;\n                outfab->fab$l_xab = (void *) xabfhc;\n            }\n            if (xabdat != NULL)\n            {\n                xabdat->xab$l_nxt = outfab->fab$l_xab;\n                outfab->fab$l_xab = (void *) xabdat;\n            }\n            if (first_xab != NULL)      /* Link xaball,xabkey subchain */\n            {\n                last_xab->xab$l_nxt = outfab->fab$l_xab;\n                outfab->fab$l_xab = (void *) first_xab;\n            }\n        }\n        else\n            type = VAT_NONE;\n    }\n    return type;\n}\n\n\n\nstatic void free_up()\n{\n    /*\n     * Free up all allocated XABs.\n     */\n    if (xabdat != NULL) free(xabdat);\n    if (xabpro != NULL) free(xabpro);\n    if (xabrdt != NULL) free(xabrdt);\n    if (xabfhc != NULL) free(xabfhc);\n    while (first_xab != NULL)\n    {\n        struct XAB *x;\n\n        x = (struct XAB *) first_xab->xab$l_nxt;\n        free(first_xab);\n        first_xab = x;\n    }\n    /* Free FAB storage, if not the static one. */\n    if (outfab != NULL && outfab != &fileblk)\n        free(outfab);\n}\n\n\n\n#ifdef CHECK_VERSIONS\n\nstatic int get_vms_version(verbuf, len)\n    char *verbuf;\n    int len;\n{\n    int i = SYI$_VERSION;\n    int verlen = 0;\n    struct dsc$descriptor version;\n    char *m;\n\n    version.dsc$a_pointer = verbuf;\n    version.dsc$w_length  = len - 1;\n    version.dsc$b_dtype   = DSC$K_DTYPE_B;\n    version.dsc$b_class   = DSC$K_CLASS_S;\n\n    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)\n        return 0;\n\n    /* Cut out trailing spaces \"V5.4-3   \" -> \"V5.4-3\" */\n    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)\n        --m;\n    *m = '\\0';\n\n    /* Cut out release number \"V5.4-3\" -> \"V5.4\" */\n    if ((m = strrchr(verbuf, '-')) != NULL)\n        *m = '\\0';\n    return strlen(verbuf) + 1;  /* Transmit ending '\\0' too */\n}\n\n#endif /* CHECK_VERSIONS */\n\n\n\n/* flush contents of output buffer */\nint flush(__G__ rawbuf, size, unshrink)    /* return PK-type error code */\n    __GDEF\n    uch *rawbuf;\n    ulg size;\n    int unshrink;\n{\n    G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);\n    if (uO.tflag)\n        return PK_COOL; /* Do not output. Update CRC only */\n    else\n        return (*_flush_routine)(__G__ rawbuf, size, 0);\n}\n\n\n\nstatic int _flush_blocks(__G__ rawbuf, size, final_flag)\n                                                /* Asynchronous version */\n    __GDEF\n    uch *rawbuf;\n    unsigned size;\n    int final_flag;   /* 1 if this is the final flushout */\n{\n    int status;\n    unsigned off = 0;\n\n    while (size > 0)\n    {\n        if (curbuf->bufcnt < BUFS512)\n        {\n            unsigned ncpy;\n\n            ncpy = size > (BUFS512 - curbuf->bufcnt) ?\n                   (BUFS512 - curbuf->bufcnt) : size;\n            memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);\n            size -= ncpy;\n            curbuf->bufcnt += ncpy;\n            off += ncpy;\n        }\n        if (curbuf->bufcnt == BUFS512)\n        {\n            status = WriteBuffer(__G__ curbuf->buf, curbuf->bufcnt);\n            if (status)\n                return status;\n            curbuf = curbuf->next;\n            curbuf->bufcnt = 0;\n        }\n    }\n\n    return (final_flag && (curbuf->bufcnt > 0)) ?\n        WriteBuffer(__G__ curbuf->buf, curbuf->bufcnt) :\n        PK_COOL;\n}\n\n\n\n#ifdef ASYNCH_QIO\nstatic int WriteQIO(__G__ buf, len)\n    __GDEF\n    uch *buf;\n    unsigned len;\n{\n    int status;\n\n    if (pka_io_pending) {\n        status = sys$synch(0, &pka_io_iosb);\n        if (!ERR(status))\n            status = pka_io_iosb.status;\n        if (ERR(status))\n        {\n            vms_msg(__G__ \"[ WriteQIO: sys$synch found I/O failure ]\\n\",\n                    status);\n            return PK_DISK;\n        }\n        pka_io_pending = FALSE;\n    }\n    /*\n     *   Put content of buffer as a single VB\n     */\n    status = sys$qio(0, pka_devchn, IO$_WRITEVBLK,\n                     &pka_io_iosb, 0, 0,\n                     buf, len, pka_vbn,\n                     0, 0, 0);\n    if (ERR(status))\n    {\n        vms_msg(__G__ \"[ WriteQIO: sys$qio failed ]\\n\", status);\n        return PK_DISK;\n    }\n    pka_io_pending = TRUE;\n    pka_vbn += (len>>9);\n\n    return PK_COOL;\n}\n\n/*\n   2004-10-01 SMS.  Changed to clear the extra byte written out by qio()\n   and sys$write() when an odd byte count is incremented to the next\n   even value, either explicitly (qio), or implicitly (sys$write), on\n   the theory that a reliable NUL beats left-over garbage.  Alpha and\n   VAX object files seem frequently to have even more than one byte of\n   extra junk past EOF, so this may not help them.\n*/\n\nstatic int _flush_qio(__G__ rawbuf, size, final_flag)\n                                                /* Asynchronous version */\n    __GDEF\n    uch *rawbuf;\n    unsigned size;\n    int final_flag;   /* 1 if this is the final flushout */\n{\n    int status;\n    unsigned off = 0;\n\n    while (size > 0)\n    {\n        if (curbuf->bufcnt < BUFS512)\n        {\n            unsigned ncpy;\n\n            ncpy = size > (BUFS512 - curbuf->bufcnt) ?\n                   (BUFS512 - curbuf->bufcnt) : size;\n            memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);\n            size -= ncpy;\n            curbuf->bufcnt += ncpy;\n            off += ncpy;\n        }\n        if (curbuf->bufcnt == BUFS512)\n        {\n            status = WriteQIO(__G__ curbuf->buf, curbuf->bufcnt);\n            if (status)\n                return status;\n            curbuf = curbuf->next;\n            curbuf->bufcnt = 0;\n        }\n    }\n\n    if (final_flag && (curbuf->bufcnt > 0))\n    {\n        unsigned bufcnt_even;\n\n        /* Round up to an even byte count. */\n        bufcnt_even = (curbuf->bufcnt+1) & (~1);\n        /* If there is one, clear the extra byte. */\n        if (bufcnt_even > curbuf->bufcnt)\n            curbuf->buf[curbuf->bufcnt] = '\\0';\n\n        return WriteQIO(curbuf->buf, bufcnt_even);\n    }\n    else\n    {\n        return PK_COOL;\n    }\n}\n\n#else /* !ASYNCH_QIO */\n\nstatic int _flush_qio(__G__ rawbuf, size, final_flag)\n    __GDEF\n    uch *rawbuf;\n    unsigned size;\n    int final_flag;   /* 1 if this is the final flushout */\n{\n    int status;\n    uch *out_ptr=rawbuf;\n\n    if ( final_flag )\n    {\n        if ( loccnt > 0 )\n        {\n            unsigned loccnt_even;\n\n            /* Round up to an even byte count. */\n            loccnt_even = (loccnt+1) & (~1);\n            /* If there is one, clear the extra byte. */\n            if (loccnt_even > loccnt)\n                locbuf[loccnt] = '\\0';\n\n            status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,\n                              &pka_io_iosb, 0, 0,\n                              locbuf,\n                              loccnt_even,\n                              pka_vbn,\n                              0, 0, 0);\n            if (!ERR(status))\n                status = pka_io_iosb.status;\n            if (ERR(status))\n            {\n                vms_msg(__G__ \"[ Write QIO failed ]\\n\", status);\n                return PK_DISK;\n            }\n        }\n        return PK_COOL;\n    }\n\n    if ( loccnt > 0 )\n    {\n        /*\n         *   Fill local buffer upto 512 bytes then put it out\n         */\n        unsigned ncpy;\n\n        ncpy = 512-loccnt;\n        if ( ncpy > size )\n            ncpy = size;\n\n        memcpy(locptr, out_ptr, ncpy);\n        locptr += ncpy;\n        loccnt += ncpy;\n        size -= ncpy;\n        out_ptr += ncpy;\n        if ( loccnt == 512 )\n        {\n            status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,\n                              &pka_io_iosb, 0, 0,\n                              locbuf, loccnt, pka_vbn,\n                              0, 0, 0);\n            if (!ERR(status))\n                status = pka_io_iosb.status;\n            if (ERR(status))\n            {\n                vms_msg(__G__ \"[ Write QIO failed ]\\n\", status);\n                return PK_DISK;\n            }\n\n            pka_vbn++;\n            loccnt = 0;\n            locptr = locbuf;\n        }\n    }\n\n    if ( size >= 512 )\n    {\n        unsigned nblk, put_cnt;\n\n        /*\n         *   Put rest of buffer as a single VB\n         */\n        put_cnt = (nblk = size>>9)<<9;\n        status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,\n                          &pka_io_iosb, 0, 0,\n                          out_ptr, put_cnt, pka_vbn,\n                          0, 0, 0);\n        if (!ERR(status))\n            status = pka_io_iosb.status;\n        if (ERR(status))\n        {\n            vms_msg(__G__ \"[ Write QIO failed ]\\n\", status);\n            return PK_DISK;\n        }\n\n        pka_vbn += nblk;\n        out_ptr += put_cnt;\n        size -= put_cnt;\n    }\n\n    if ( size > 0 )\n    {\n        memcpy(locptr, out_ptr, size);\n        loccnt += size;\n        locptr += size;\n    }\n\n    return PK_COOL;\n}\n#endif /* ?ASYNCH_QIO */\n\n\n\n/*\n * The routine _flush_varlen() requires: \"(size & 1) == 0\"\n * (The variable-length record algorithm assumes an even byte-count!)\n */\nstatic int _flush_varlen(__G__ rawbuf, size, final_flag)\n    __GDEF\n    uch *rawbuf;\n    unsigned size;\n    int final_flag;\n{\n    unsigned nneed;\n    unsigned reclen;\n    uch *inptr=rawbuf;\n\n    /*\n     * Flush local buffer\n     */\n\n    if ( loccnt > 0 )           /* incomplete record left from previous call */\n    {\n        reclen = *(ush*)locbuf;\n        nneed = reclen + 2 - loccnt;\n        if ( nneed > size )\n        {\n            if ( size+loccnt > BUFSMAXREC )\n            {\n                char buf[80];\n                Info(buf, 1, (buf,\n                     \"[ Record too long (%u bytes) ]\\n\", reclen));\n                return PK_DISK;\n            }\n            memcpy(locbuf+loccnt, inptr, size);\n            loccnt += size;\n            size = 0;\n        }\n        else\n        {\n            memcpy(locbuf+loccnt, inptr, nneed);\n            loccnt += nneed;\n            size -= nneed;\n            inptr += nneed;\n            if ( reclen & 1 )\n            {\n                size--;\n                inptr++;\n            }\n            if ( WriteRecord(__G__ locbuf+2, reclen) )\n                return PK_DISK;\n            loccnt = 0;\n        }\n    }\n    /*\n     * Flush incoming records\n     */\n    while (size > 0)\n    {\n        reclen = *(ush*)inptr;\n        if ( reclen+2 <= size )\n        {\n            if (WriteRecord(__G__ inptr+2, reclen))\n                return PK_DISK;\n            size -= 2+reclen;\n            inptr += 2+reclen;\n            if ( reclen & 1 )\n            {\n                --size;\n                ++inptr;\n            }\n        }\n        else\n        {\n            memcpy(locbuf, inptr, size);\n            loccnt = size;\n            size = 0;\n        }\n\n    }\n    /*\n     * Final flush rest of local buffer\n     */\n    if ( final_flag && loccnt > 0 )\n    {\n        char buf[80];\n\n        Info(buf, 1, (buf,\n             \"[ Warning, incomplete record of length %u ]\\n\",\n             (unsigned)*(ush*)locbuf));\n        if ( WriteRecord(__G__ locbuf+2, loccnt-2) )\n            return PK_DISK;\n    }\n    return PK_COOL;\n}\n\n\n\n/*\n *   Routine _flush_stream breaks decompressed stream into records\n *   depending on format of the stream (fab->rfm, G.pInfo->textmode, etc.)\n *   and puts out these records. It also handles CR LF sequences.\n *   Should be used when extracting *text* files.\n */\n\n#define VT      0x0B\n#define FF      0x0C\n\n/* The file is from MSDOS/OS2/NT -> handle CRLF as record end, throw out ^Z */\n\n/* GRR NOTES:  cannot depend on hostnum!  May have \"flip'd\" file or re-zipped\n * a Unix file, etc. */\n\n#ifdef USE_ORIG_DOS\n# define ORG_DOS \\\n          (G.pInfo->hostnum==FS_FAT_    \\\n        || G.pInfo->hostnum==FS_HPFS_   \\\n        || G.pInfo->hostnum==FS_NTFS_)\n#else\n# define ORG_DOS    1\n#endif\n\n/* Record delimiters */\n#ifdef undef\n#define RECORD_END(c, f)                                                \\\n(    ( ORG_DOS || G.pInfo->textmode ) && c==CTRLZ                       \\\n  || ( f == FAB$C_STMLF && c==LF )                                      \\\n  || ( f == FAB$C_STMCR || ORG_DOS || G.pInfo->textmode ) && c==CR      \\\n  || ( f == FAB$C_STM && (c==CR || c==LF || c==FF || c==VT) )           \\\n)\n#else\n#   define  RECORD_END(c, f)   ((c) == LF || (c) == (CR))\n#endif\n\nstatic unsigned find_eol(p, n, l)\n/*\n *  Find first CR, LF, CR/LF or LF/CR in string 'p' of length 'n'.\n *  Return offset of the sequence found or 'n' if not found.\n *  If found, return in '*l' length of the sequence (1 or 2) or\n *  zero if sequence end not seen, i.e. CR or LF is last char\n *  in the buffer.\n */\n    ZCONST uch *p;\n    unsigned n;\n    unsigned *l;\n{\n    unsigned off = n;\n    ZCONST uch *q;\n\n    *l = 0;\n\n    for (q=p ; n > 0 ; --n, ++q)\n        if ( RECORD_END(*q, rfm) )\n        {\n            off = q-p;\n            break;\n        }\n\n    if ( n > 1 )\n    {\n        *l = 1;\n        if ( ( q[0] == CR && q[1] == LF ) || ( q[0] == LF && q[1] == CR ) )\n            *l = 2;\n    }\n\n    return off;\n}\n\n/* Record delimiters that must be put out */\n#define PRINT_SPEC(c)   ( (c)==FF || (c)==VT )\n\n\n\nstatic int _flush_stream(__G__ rawbuf, size, final_flag)\n    __GDEF\n    uch *rawbuf;\n    unsigned size;\n    int final_flag; /* 1 if this is the final flushout */\n{\n    int rest;\n    unsigned end = 0, start = 0;\n\n    if (size == 0 && loccnt == 0)\n        return PK_COOL;         /* Nothing to do ... */\n\n    if ( final_flag )\n    {\n        unsigned recsize;\n\n        /*\n         * This is flush only call. size must be zero now.\n         * Just eject everything we have in locbuf.\n         */\n        recsize = loccnt - (got_eol ? 1 : 0);\n        /*\n         *  If the last char of file was ^Z ( end-of-file in MSDOS ),\n         *  we will see it now.\n         */\n        if ( recsize==1 && locbuf[0] == CTRLZ )\n            return PK_COOL;\n\n        return WriteRecord(__G__ locbuf, recsize);\n    }\n\n\n    if ( loccnt > 0 )\n    {\n        /* Find end of record partially saved in locbuf */\n\n        unsigned recsize;\n        int complete=0;\n\n        if ( got_eol )\n        {\n            recsize = loccnt - 1;\n            complete = 1;\n\n            if ( (got_eol == CR && rawbuf[0] == LF) ||\n                 (got_eol == LF && rawbuf[0] == CR) )\n                end = 1;\n\n            got_eol = 0;\n        }\n        else\n        {\n            unsigned eol_len;\n            unsigned eol_off;\n\n            eol_off = find_eol(rawbuf, size, &eol_len);\n\n            if ( loccnt+eol_off > BUFSMAXREC )\n            {\n                /*\n                 *  No room in locbuf. Dump it and clear\n                 */\n                char buf[80];           /* CANNOT use slide for Info() */\n\n                recsize = loccnt;\n                start = 0;\n                Info(buf, 1, (buf,\n                     \"[ Warning: Record too long (%u) ]\\n\", loccnt+eol_off));\n                complete = 1;\n                end = 0;\n            }\n            else\n            {\n                if ( eol_off >= size )\n                {\n                    end = size;\n                    complete = 0;\n                }\n                else if ( eol_len == 0 )\n                {\n                    got_eol = rawbuf[eol_off];\n                    end = size;\n                    complete = 0;\n                }\n                else\n                {\n                    memcpy(locptr, rawbuf, eol_off);\n                    recsize = loccnt + eol_off;\n                    locptr += eol_off;\n                    loccnt += eol_off;\n                    end = eol_off + eol_len;\n                    complete = 1;\n                }\n            }\n        }\n\n        if ( complete )\n        {\n            if (WriteRecord(__G__ locbuf, recsize))\n                return PK_DISK;\n            loccnt = 0;\n            locptr = locbuf;\n        }\n    }                           /* end if ( loccnt ) */\n\n    for (start = end; start < size && end < size; )\n    {\n        unsigned eol_off, eol_len;\n\n        got_eol = 0;\n\n#ifdef undef\n        if (uO.cflag)\n            /* skip CR's at the beginning of record */\n            while (start < size && rawbuf[start] == CR)\n                ++start;\n#endif\n\n        if ( start >= size )\n            continue;\n\n        /* Find record end */\n        end = start+(eol_off = find_eol(rawbuf+start, size-start, &eol_len));\n\n        if ( end >= size )\n            continue;\n\n        if ( eol_len > 0 )\n        {\n            if ( WriteRecord(__G__ rawbuf+start, end-start) )\n                return PK_DISK;\n            start = end + eol_len;\n        }\n        else\n        {\n            got_eol = rawbuf[end];\n            end = size;\n            continue;\n        }\n    }\n\n    rest = size - start;\n\n    if (rest > 0)\n    {\n        if ( rest > BUFSMAXREC )\n        {\n            unsigned recsize;\n            char buf[80];               /* CANNOT use slide for Info() */\n\n            recsize = rest - (got_eol ? 1 : 0 );\n            Info(buf, 1, (buf,\n                 \"[ Warning: Record too long (%u) ]\\n\", recsize));\n            got_eol = 0;\n            return WriteRecord(__G__ rawbuf+start, recsize);\n        }\n        else\n        {\n            memcpy(locptr, rawbuf + start, rest);\n            locptr += rest;\n            loccnt += rest;\n        }\n    }\n    return PK_COOL;\n}\n\n\n\nstatic int WriteBuffer(__G__ buf, len)\n    __GDEF\n    uch *buf;\n    unsigned len;\n{\n    int status;\n\n    if (uO.cflag)\n    {\n        (void)(*G.message)((zvoid *)&G, buf, len, 0);\n    }\n    else\n    {\n        status = sys$wait(outrab);\n        if (ERR(status))\n        {\n            vms_msg(__G__ \"[ WriteBuffer: sys$wait failed ]\\n\", status);\n            if (outrab->rab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outrab->rab$l_stv);\n            }\n        }\n\n        /* If odd byte count, then this must be the final record.\n           Clear the extra byte past EOF to help keep the file clean.\n        */\n        if (len & 1)\n            buf[len] = '\\0';\n\n        outrab->rab$w_rsz = len;\n        outrab->rab$l_rbf = (char *) buf;\n\n        if (ERR(status = sys$write(outrab)))\n        {\n            vms_msg(__G__ \"[ WriteBuffer: sys$write failed ]\\n\", status);\n            if (outrab->rab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outrab->rab$l_stv);\n            }\n            return PK_DISK;\n        }\n    }\n    return PK_COOL;\n}\n\n\n\nstatic int WriteRecord(__G__ rec, len)\n    __GDEF\n    uch *rec;\n    unsigned len;\n{\n    int status;\n\n    if (uO.cflag)\n    {\n        (void)(*G.message)((zvoid *)&G, rec, len, 0);\n        (void)(*G.message)((zvoid *)&G, (uch *) (\"\\n\"), 1, 0);\n    }\n    else\n    {\n        if (ERR(status = sys$wait(outrab)))\n        {\n            vms_msg(__G__ \"[ WriteRecord: sys$wait failed ]\\n\", status);\n            if (outrab->rab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outrab->rab$l_stv);\n            }\n        }\n        outrab->rab$w_rsz = len;\n        outrab->rab$l_rbf = (char *) rec;\n\n        if (ERR(status = sys$put(outrab)))\n        {\n            vms_msg(__G__ \"[ WriteRecord: sys$put failed ]\\n\", status);\n            if (outrab->rab$l_stv != 0)\n            {\n                vms_msg(__G__ \"\", outrab->rab$l_stv);\n            }\n            return PK_DISK;\n        }\n    }\n    return PK_COOL;\n}\n\n\n\n#ifdef SYMLINKS\n/* Read symlink text from a still-open rms file. */\n\nstatic int _read_link_rms(int byte_count, char *link_text_buf)\n{\n    /* Use RMS to read the link text into the user's buffer.\n     * Rewind, then read byte count = byte_count.\n     * NUL-terminate the link text.\n     *\n     * $WAIT may be pointless if not async, but $WAIT elsewhere seems\n     * to be used unconditionally, so what do I know?\n     */\n    int sts;\n    int bytes_read;\n\n    /* Clear the bytes-read count. */\n    bytes_read = 0;\n\n    /* Wait for anything pending. */\n    sts = sys$wait(outrab);\n    {\n        /* Rewind. */\n        sts = sys$rewind(outrab);\n        if (!ERR(sts))\n        {\n            /* Wait for $REWIND. */\n            sts = sys$wait(outrab);\n            if (!ERR(sts))\n            {\n                /* Read the link text. */\n                outrab->rab$w_usz = byte_count;\n                outrab->rab$l_ubf = link_text_buf;\n                sts = sys$read(outrab);\n                if (!ERR(sts))\n                {\n                    /* Wait for $READ. */\n                    sts = sys$wait(outrab);\n\n                    if (!ERR(sts))\n                        /* Set the resultant byte count. */\n                        bytes_read = outrab->rab$w_rsz;\n                }\n            }\n        }\n    }\n\n    /* NUL-terminate the link text. */\n    link_text_buf[bytes_read] = '\\0';\n\n    return sts;\n}\n\n#endif /* SYMLINKS */\n\n\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    int status;\n\n    status = (*_flush_routine)(__G__ NULL, 0, 1);\n    if (status)\n        return /* PK_DISK */;\n    if (uO.cflag)\n        return /* PK_COOL */;   /* Don't close stdout */\n    /* return */ (*_close_routine)(__G);\n}\n\n\n\nstatic int _close_rms(__GPRO)\n{\n    int status;\n    struct XABPRO pro;\n    int retcode = PK_OK;\n\n#ifdef SYMLINKS\n\n/*----------------------------------------------------------------------\n    UNIX description:\n    If symbolic links are supported, allocate storage for a symlink\n    control structure, put the uncompressed \"data\" and other required\n    info in it, and add the structure to the \"deferred symlinks\" chain.\n    Since we know it's a symbolic link to start with, we shouldn't have\n    to worry about overflowing unsigned ints with unsigned longs.\n----------------------------------------------------------------------*/\n\n    if (G.symlnk) {\n        extent ucsize = (extent)G.lrec.ucsize;\n\n        /* 2007-03-03 SMS.\n         * If the symlink is already a symlink (restored with VMS/RMS\n         * symlink attributes), then read the link text from the file,\n         * and close the file (using the appropriate methods), and then\n         * return.\n         */\n        if (G.pInfo->symlink == 0)\n        {\n            if (QCOND2)\n            {\n                /* Link text storage. */\n                char* link_target = malloc(ucsize + 1);\n\n                if (link_target == NULL)\n                {\n                    Info(slide, 0x201, ((char *)slide,\n                      \"warning:  cannot show symlink (%s) target, no mem\\n\",\n                      FnFilter1(G.filename)));\n                      retcode = PK_MEM;\n                }\n                else\n                {\n                    /* Read the link text. */\n                    status = _read_link_rms(ucsize, link_target);\n\n                    if (ERR(status))\n                    {\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  error reading symlink text: %s\\n\",\n                          strerror(EVMSERR, status)));\n                        retcode = PK_DISK;\n                    }\n                    else\n                    {\n                        Info(slide, 0, ((char *)slide, \"-> %s \",\n                          FnFilter1(link_target)));\n                    }\n\n                    free(link_target);\n                }\n            }\n        }\n        else\n        {\n            extent slnk_entrysize;\n            slinkentry *slnk_entry;\n\n            /* It's a symlink in need of post-processing. */\n            /* Size of the symlink entry is the sum of\n             *  (struct size (includes 1st '\\0') + 1 additional trailing '\\0'),\n             *  system specific attribute data size (might be 0),\n             *  and the lengths of name and link target.\n             */\n            slnk_entrysize = (sizeof(slinkentry) + 1) +\n                             ucsize + strlen(G.filename);\n\n            if (slnk_entrysize < ucsize) {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  symbolic link (%s) failed: mem alloc overflow\\n\",\n                  FnFilter1(G.filename)));\n                retcode = PK_ERR;\n            }\n            else\n            {\n                if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize))\n                    == NULL) {\n                    Info(slide, 0x201, ((char *)slide,\n                      \"warning:  symbolic link (%s) failed, no mem\\n\",\n                      FnFilter1(G.filename)));\n                    retcode = PK_MEM;\n                }\n                else\n                {\n                    slnk_entry->next = NULL;\n                    slnk_entry->targetlen = ucsize;\n                    /* don't set attributes for symlinks */\n                    slnk_entry->attriblen = 0;\n                    slnk_entry->target = slnk_entry->buf;\n                    slnk_entry->fname = slnk_entry->target + ucsize + 1;\n                    strcpy(slnk_entry->fname, G.filename);\n\n                    /* Read the link text using the appropriate method. */\n                    status = _read_link_rms(ucsize, slnk_entry->target);\n\n                    if (ERR(status))\n                    {\n                        Info(slide, 0x201, ((char *)slide,\n                          \"warning:  error reading symlink text (rms): %s\\n\",\n                          strerror(EVMSERR, status)));\n                        free(slnk_entry);\n                        retcode = PK_DISK;\n                    }\n                    else\n                    {\n                        if (QCOND2)\n                            Info(slide, 0, ((char *)slide, \"-> %s \",\n                              FnFilter1(slnk_entry->target)));\n\n                        /* Add this symlink record to the list of\n                           deferred symlinks. */\n                        if (G.slink_last != NULL)\n                            G.slink_last->next = slnk_entry;\n                        else\n                            G.slink_head = slnk_entry;\n                        G.slink_last = slnk_entry;\n                    }\n                }\n            }\n        }\n    }\n#endif /* SYMLINKS */\n\n    /* Link XABRDT, XABDAT, and (optionally) XABPRO. */\n    if (xabrdt != NULL)\n    {\n        xabrdt->xab$l_nxt = NULL;\n        outfab->fab$l_xab = (void *) xabrdt;\n    }\n    else\n    {\n        rdt.xab$l_nxt = NULL;\n        outfab->fab$l_xab = (void *) &rdt;\n    }\n    if (xabdat != NULL)\n    {\n        xabdat->xab$l_nxt = outfab->fab$l_xab;\n        outfab->fab$l_xab = (void *)xabdat;\n    }\n\n    if (xabpro != NULL)\n    {\n        if ( !uO.X_flag )\n            xabpro->xab$l_uic = 0;    /* Use default (user's) uic */\n        xabpro->xab$l_nxt = outfab->fab$l_xab;\n        outfab->fab$l_xab = (void *) xabpro;\n    }\n    else\n    {\n        pro = cc$rms_xabpro;\n        pro.xab$w_pro = G.pInfo->file_attr;\n        pro.xab$l_nxt = outfab->fab$l_xab;\n        outfab->fab$l_xab = (void *) &pro;\n    }\n\n    status = sys$wait(outrab);\n    if (ERR(status))\n    {\n        vms_msg(__G__ \"[ _close_rms: sys$wait failed ]\\n\", status);\n        if (outrab->rab$l_stv != 0)\n        {\n            vms_msg(__G__ \"\", outrab->rab$l_stv);\n        }\n    }\n\n    status = sys$close(outfab);\n#ifdef DEBUG\n    if (ERR(status))\n    {\n        vms_msg(__G__\n          \"\\r[ Warning: cannot set owner/protection/time attributes ]\\n\",\n          status);\n        if (outfab->fab$l_stv != 0)\n        {\n            vms_msg(__G__ \"\", outfab->fab$l_stv);\n        }\n        retcode = PK_WARN;\n    }\n#endif\n    free_up();\n    return retcode;\n}\n\n\n\nstatic int _close_qio(__GPRO)\n{\n    int status;\n\n    pka_fib.FIB$L_ACCTL =\n        FIB$M_WRITE | FIB$M_NOTRUNC ;\n    pka_fib.FIB$W_EXCTL = 0;\n\n    pka_fib.FIB$W_FID[0] =\n    pka_fib.FIB$W_FID[1] =\n    pka_fib.FIB$W_FID[2] =\n    pka_fib.FIB$W_DID[0] =\n    pka_fib.FIB$W_DID[1] =\n    pka_fib.FIB$W_DID[2] = 0;\n\n#ifdef ASYNCH_QIO\n    if (pka_io_pending) {\n        status = sys$synch(0, &pka_io_iosb);\n        if (!ERR(status))\n            status = pka_io_iosb.status;\n        if (ERR(status))\n        {\n            vms_msg(__G__ \"[ _close_qio: sys$synch found I/O failure ]\\n\",\n                    status);\n        }\n        pka_io_pending = FALSE;\n    }\n#endif /* ASYNCH_QIO */\n\n#ifdef SYMLINKS\n    if (G.symlnk && QCOND2)\n    {\n        /* Read back the symlink target specification for display purpose. */\n        extent ucsize = (extent)G.lrec.ucsize;\n        char *link_target;   /* Link text storage. */\n\n        if ((link_target = malloc(ucsize + 1)) == NULL)\n        {\n            Info(slide, 0x201, ((char *)slide,\n              \"warning:  cannot show symlink (%s) target, no mem\\n\",\n              FnFilter1(G.filename)));\n        }\n        else\n        {\n            unsigned bytes_read = 0;\n\n            status = sys$qiow(0,                /* event flag */\n                              pka_devchn,       /* channel */\n                              IO$_READVBLK,     /* function */\n                              &pka_io_iosb,     /* IOSB */\n                              0,                /* AST address */\n                              0,                /* AST parameter */\n                              link_target,      /* P1 = buffer address */\n                              ucsize,           /* P2 = requested byte count */\n                              1,                /* P3 = VBN (1 = first) */\n                              0,                /* P4 (not used) */\n                              0,                /* P5 (not used) */\n                              0);               /* P6 (not used) */\n\n            if (!ERR(status))\n                /* Final status. */\n                status = pka_io_iosb.status;\n\n            /* Set the resultant byte count. */\n            if (!ERR(status))\n                bytes_read = pka_io_iosb.count;\n\n            /* NUL-terminate the link text. */\n            link_target[bytes_read] = '\\0';\n\n            if (ERR(status))\n            {\n                Info(slide, 0x201, ((char *)slide,\n                  \"warning:  error reading symlink text (qio): %s\\n\",\n                  strerror(EVMSERR, status)));\n            }\n            else\n            {\n                Info(slide, 0, ((char *)slide, \"-> %s \",\n                  FnFilter1(link_target)));\n            }\n\n            free(link_target);\n\n        }\n    }\n#endif /* SYMLINKS */\n\n    status = sys$qiow(0, pka_devchn, IO$_DEACCESS, &pka_acp_iosb,\n                      0, 0,\n                      &pka_fibdsc, 0, 0, 0,\n                      pka_atr, 0);\n\n    sys$dassgn(pka_devchn);\n    if ( !ERR(status) )\n        status = pka_acp_iosb.status;\n    if ( ERR(status) )\n    {\n        vms_msg(__G__ \"[ Deaccess QIO failed ]\\n\", status);\n        return PK_DISK;\n    }\n    return PK_COOL;\n}\n\n\n\n#ifdef SET_DIR_ATTRIB\n\n/*\n * 2006-10-04 SMS.\n * vms_path_fixdown().\n *\n * Convert VMS directory spec to VMS directory file name.  That is,\n * change \"dev:[a.b.c.e]\" to \"dev:[a.b.c]e.DIR;1\".  The result (always\n * larger than the source) is returned in the user's buffer.\n */\n\n#define DIR_TYPE_VER \".DIR;1\"\n\nstatic char *vms_path_fixdown(ZCONST char *dir_spec, char *dir_file)\n{\n    char dir_close;\n    char dir_open;\n    unsigned i;\n    unsigned dir_spec_len;\n\n    dir_spec_len = strlen(dir_spec);\n    if (dir_spec_len == 0) return NULL;\n    i = dir_spec_len - 1;\n    dir_close = dir_spec[i];\n\n    /* Identify the directory delimiters (which must exist). */\n    if (dir_close == ']')\n    {\n        dir_open = '[';\n    }\n    else if (dir_close == '>')\n    {\n        dir_open = '<';\n    }\n    else\n    {\n        return NULL;\n    }\n\n    /* Find the beginning of the last directory name segment. */\n    while ((i > 0) && ((dir_spec[i - 1] == '^') ||\n           ((dir_spec[i] != '.') && (dir_spec[i] != dir_open))))\n    {\n        i--;\n    }\n\n    /* Form the directory file name from the pieces. */\n    if (dir_spec[i] == dir_open)\n    {\n        /* Top-level directory. */\n        sprintf(dir_file, \"%.*s000000%c%.*s%s\",\n          /*  \"dev:[\" \"000000\" \"]\" */\n          (i + 1), dir_spec, dir_close,\n          /*  \"a\" \".DIR;1\" */\n          (dir_spec_len - i - 2), (dir_spec + i + 1), DIR_TYPE_VER);\n    }\n    else\n    {\n        /* Non-top-level directory. */\n        sprintf(dir_file, \"%.*s%c%.*s%s\",\n          /*  \"dev:[a.b.c\" \"]\" */\n          i, dir_spec, dir_close,\n          /*  \"e\" \".DIR;1\" */\n          (dir_spec_len - i - 2), (dir_spec + i + 1), DIR_TYPE_VER);\n    }\n    return dir_file;\n} /* end function vms_path_fixdown(). */\n\n\n\n/* Save directory attributes (as the archive's extra field). */\n\n/* 2006-12-13 SMS.\n * This could probably be made more efficient by analyzing the data\n * here, extracting the important data, and saving only what's needed.\n * Given the existing code, it seemed simpler to save them all here, and\n * deal with what's important in set_direc_attribs().\n */\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    vmsdirattr *d_entry;\n    unsigned fnlen;\n    unsigned xlen;\n\n    /* Allocate space to save the file (directory) name, the extra\n     * block, and all the other data needed by the extra-block data\n     * scanner functions.  If that works, save the data.\n     */\n    fnlen = strlen(G.filename);\n    xlen = G.lrec.extra_field_length;\n    d_entry = (vmsdirattr *) malloc(sizeof(vmsdirattr) + fnlen + xlen);\n    *pd = (direntry *) d_entry;\n    if (d_entry == (vmsdirattr *) NULL)\n    {\n        return PK_MEM;\n    }\n\n    /* Save extra block length and data. */\n    d_entry->xlen = xlen;\n    memcpy(d_entry->buf, G.extra_field, xlen);\n\n    /* Set pointer to file (directory) name. */\n    d_entry->fn = d_entry->buf + xlen;\n\n    /* Save file (directory) name. */\n    strcpy(d_entry->fn, G.filename);\n    /* Strip the closing ']' char, to allow proper sorting. */\n    d_entry->fn[fnlen - 1] = '\\0';\n\n    /* Save generic permission data from mapattr(). */\n    d_entry->perms = G.pInfo->file_attr;\n\n    /* Save G.lrec.last_mod_dos_datetime. */\n    d_entry->mod_dos_datetime = G.lrec.last_mod_dos_datetime;\n\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    uch *sav_ef_ptr;\n    int i;\n    int status;\n    int type;\n    ush attr;\n    struct XABPRO pro;\n    char dir_name[NAM_MAXRSS + 1];\n    char warnmsg[NAM_MAXRSS + 128]; /* Name length + message length. */\n    int retcode = PK_OK;\n\n    /* Re-append the closing ']' character which has been stripped in\n     * defer_dir_attribs() for compatibility with generic sorting code.\n     */\n    strcat(VmsAtt(d)->fn, \"]\");\n\n    /* Convert \"[a.b.c]\" form into \"[a.b]c.DIR;1\" */\n    vms_path_fixdown(VmsAtt(d)->fn, dir_name);\n\n    /* Dummy up critical global (G) data from the preserved directory\n     * attribute data.\n     */\n    sav_ef_ptr = G.extra_field;\n    G.extra_field = (uch *)((VmsAtt(d)->xlen > 0) ? VmsAtt(d)->buf : NULL);\n    G.lrec.extra_field_length = VmsAtt(d)->xlen;\n\n    /* Extract the VMS file attributes from the preserved attribute\n     * data, if they exist, and restore the date-time stamps.\n     */\n    type = find_vms_attrs(__G__ (uO.D_flag <= 0));\n\n    if (outfab == NULL)\n    {\n        /* Default and PK schemes need a FAB.  (IZ supplies one.)\n         * In a degenerate case, this could be the first use of fileblk,\n         * so we assume that we need to initialize it.\n         */\n        fileblk = cc$rms_fab;           /* Initialize FAB. */\n        outfab = &fileblk;              /* Set pointer used elsewhere. */\n    }\n\n    /* Arrange FAB-NAM[L] for file (directory) access. */\n    if (type != VAT_NONE)\n    {\n        if (type == VAT_IZ)\n        {\n            /* Make an attribute descriptor list for the VMS creation and\n             * revision dates (which were stored in the IZ XABs by\n             * find_vms_attrs()).\n             */\n            pka_idx = 0;\n\n            if (xabrdt != NULL)\n            {\n                /* Revision date-time from XABRDT. */\n                pka_atr[pka_idx].atr$w_size = 8;\n                pka_atr[pka_idx].atr$w_type = ATR$C_REVDATE;\n                pka_atr[pka_idx].atr$l_addr = GVTC &xabrdt->xab$q_rdt;\n                ++pka_idx;\n            }\n            if (xabdat != NULL)\n            {\n                /* Trust the XABRDT value for revision date. */\n                if (xabrdt == NULL)\n                {\n                    /* Revision date-time from XABDAT. */\n                    pka_atr[pka_idx].atr$w_size = 8;\n                    pka_atr[pka_idx].atr$w_type = ATR$C_REVDATE;\n                    pka_atr[pka_idx].atr$l_addr = GVTC &xabdat->xab$q_rdt;\n                    ++pka_idx;\n                }\n                /* Creation date-time from XABDAT. */\n                pka_atr[pka_idx].atr$w_size = 8;\n                pka_atr[pka_idx].atr$w_type = ATR$C_CREDATE;\n                pka_atr[pka_idx].atr$l_addr = GVTC &xabdat->xab$q_cdt;\n                ++pka_idx;\n            }\n            if (xabpro != NULL)\n            {\n                if ( uO.X_flag ) {\n                    pka_atr[pka_idx].atr$w_size = 4;\n                    pka_atr[pka_idx].atr$w_type = ATR$C_UIC;\n                    pka_atr[pka_idx].atr$l_addr = GVTC &xabpro->xab$l_uic;\n                    ++pka_idx;\n                }\n                attr = xabpro->xab$w_pro;\n            }\n            else\n            {\n                /* Revoke directory Delete permission for all. */\n                attr = VmsAtt(d)->perms\n                      | (((1<< XAB$V_NODEL)<< XAB$V_SYS)|\n                         ((1<< XAB$V_NODEL)<< XAB$V_OWN)|\n                         ((1<< XAB$V_NODEL)<< XAB$V_GRP)|\n                         ((1<< XAB$V_NODEL)<< XAB$V_WLD));\n            }\n            pka_atr[pka_idx].atr$w_size = 2;\n            pka_atr[pka_idx].atr$w_type = ATR$C_FPRO;\n            pka_atr[pka_idx].atr$l_addr = GVTC &attr;\n            ++pka_idx;\n        }\n    }\n    else\n    {\n        /* No VMS attribute data were found.  Prepare to assemble\n         * non-VMS attribute data.\n         */\n        pka_idx = 0;\n\n        /* Get the (already converted) non-VMS permissions. */\n        attr = VmsAtt(d)->perms;        /* Use right-sized prot storage. */\n\n        /* Revoke directory Delete permission for all. */\n        attr |= (((1<< XAB$V_NODEL)<< XAB$V_SYS)|\n                 ((1<< XAB$V_NODEL)<< XAB$V_OWN)|\n                 ((1<< XAB$V_NODEL)<< XAB$V_GRP)|\n                 ((1<< XAB$V_NODEL)<< XAB$V_WLD));\n\n        pka_atr[pka_idx].atr$w_size = 2;\n        pka_atr[pka_idx].atr$w_type = ATR$C_FPRO;\n        pka_atr[pka_idx].atr$l_addr = GVTC &attr;\n        ++pka_idx;\n\n        /* Restore directory date-time if user requests it (-D). */\n        if (uO.D_flag <= 0)\n        {\n            /* Set the directory date-time from the non-VMS data.\n             * Dummy up the DOS-style modification date into global (G)\n             * data from the preserved directory attribute data.\n             */\n            G.lrec.last_mod_dos_datetime = VmsAtt(d)->mod_dos_datetime;\n\n            /* Extract date-time data from the normal attribute data. */\n            set_default_datetime_XABs(__G);\n\n            /* Make an attribute descriptor list for the VMS creation\n             * and revision dates (which were stored in the XABs by\n             * set_default_datetime_XABs()).\n             */\n            pka_atr[pka_idx].atr$w_size = 8;\n            pka_atr[pka_idx].atr$w_type = ATR$C_CREDATE;\n            pka_atr[pka_idx].atr$l_addr = GVTC &dattim.xab$q_cdt;\n            ++pka_idx;\n            pka_atr[pka_idx].atr$w_size = 8;\n            pka_atr[pka_idx].atr$w_type = ATR$C_REVDATE;\n            pka_atr[pka_idx].atr$l_addr = GVTC &rdt.xab$q_rdt;\n            ++pka_idx;\n        }\n\n        /* Set the directory protection from the non-VMS data. */\n\n        /* Terminate the attribute descriptor list. */\n        pka_atr[pka_idx].atr$w_size = 0;    /* End of list */\n        pka_atr[pka_idx].atr$w_type = 0;\n        pka_atr[pka_idx].atr$l_addr = 0; /* NULL when DECC VAX gets fixed. */\n    }\n\n    nam = CC_RMS_NAM;               /* Initialize NAM[L]. */\n    outfab->FAB_NAM = &nam;         /* Point FAB to NAM[L]. */\n\n    /* Point the FAB-NAM[L] to the VMS-format directory file name. */\n\n#ifdef NAML$C_MAXRSS\n\n    outfab->fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    outfab->fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n    /* Special ODS5-QIO-compatible name storage. */\n    nam.naml$l_filesys_name = sys_nam;\n    nam.naml$l_filesys_name_alloc = sizeof(sys_nam);\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNA = dir_name;\n    FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNS = strlen(dir_name);\n\n    /* Expanded and resultant name storage. */\n    nam.NAM_ESA = exp_nam;\n    nam.NAM_ESS = sizeof(exp_nam);\n    nam.NAM_RSA = res_nam;\n    nam.NAM_RSS = sizeof(res_nam);\n\n    status = sys$parse(outfab);\n    if ( ERR(status) )\n    {\n        sprintf(warnmsg,\n          \"warning:  set-dir-attributes failed ($parse) for %s.\\n\",\n          dir_name);\n        vms_msg(__G__ warnmsg, status);\n        retcode = PK_WARN;\n        goto cleanup_exit;\n    }\n\n    /* Set the length in the device name descriptor. */\n    pka_devdsc.dsc$w_length = (unsigned short) nam.NAM_DVI[0];\n\n    /* Open a channel to the disk device. */\n    status = sys$assign(&pka_devdsc, &pka_devchn, 0, 0);\n    if ( ERR(status) )\n    {\n        sprintf(warnmsg,\n          \"warning:  set-dir-attributes failed ($assign) for %s.\\n\",\n          dir_name);\n        vms_msg(__G__ warnmsg, status);\n        retcode = PK_WARN;\n        goto cleanup_exit;\n    }\n\n    /* Move the directory ID from the NAM[L] to the FIB.\n       Clear the FID in the FIB, as we're using the name.\n    */\n    for (i = 0; i < 3; i++)\n    {\n        pka_fib.FIB$W_DID[i] = nam.NAM_DID[i];\n        pka_fib.FIB$W_FID[i] = 0;\n    }\n\n#ifdef NAML$C_MAXRSS\n\n    /* Enable fancy name characters.  Note that \"fancy\" here does\n       not include Unicode, for which there's no support elsewhere.\n    */\n    pka_fib.fib$v_names_8bit = 1;\n    pka_fib.fib$b_name_format_in = FIB$C_ISL1;\n\n    /* ODS5 Extended names used as input to QIO have peculiar\n       encoding (perhaps to minimize storage?), so the special\n       filesys_name result (typically containing fewer carets) must\n       be used here.\n    */\n    pka_fnam.dsc$a_pointer = nam.naml$l_filesys_name;\n    pka_fnam.dsc$w_length = nam.naml$l_filesys_name_size;\n\n#else /* !NAML$C_MAXRSS */\n\n    /* ODS2-only: Use the whole name. */\n    pka_fnam.dsc$a_pointer = nam.NAM_L_NAME;\n    pka_fnam.dsc$w_length = nam.NAM_B_NAME + nam.NAM_B_TYPE + nam.NAM_B_VER;\n\n#endif /* ?NAML$C_MAXRSS */\n\n    /* 2007-07-13 SMS.\n     * Our freshly created directory can easily contain fewer files than\n     * the original archived directory (for example, if not all the\n     * files in the original directory were included in the archive), so\n     * its size may differ from that of the archived directory.  Thus,\n     * simply restoring the original RECATTR attributes structure, which\n     * includes EFBLK (and so on) can cause \"SYSTEM-W-BADIRECTORY, bad\n     * directory file format\" complaints.  Instead, we overwrite\n     * selected archived attributes with current attributes, to avoid\n     * setting obsolete/inappropriate attributes on the newly created\n     * directory file.\n     *\n     * First, see if there is a RECATTR structure about which we need to\n     * worry.\n     */\n    for (i = 0; pka_atr[i].atr$w_type != 0; i++)\n    {\n        if (pka_atr[i].atr$w_type == ATR$C_RECATTR)\n        {\n            /* We found a RECATTR structure which (we must assume) needs\n             * adjustment.  Retrieve the RECATTR data for the existing\n             * (newly created) directory file.\n             */\n            status = sys$qiow(0,                    /* event flag */\n                              pka_devchn,           /* channel */\n                              IO$_ACCESS,           /* function code */\n                              &pka_acp_iosb,        /* IOSB */\n                              0,                    /* AST address */\n                              0,                    /* AST parameter */\n                              &pka_fibdsc,          /* P1 = File Info Block */\n                              &pka_fnam,            /* P2 = File name */\n                              0,                    /* P3 = Rslt nm len */\n                              0,                    /* P4 = Rslt nm str */\n                              pka_recattr,          /* P5 = Attributes */\n                              0);                   /* P6 (not used) */\n\n            /* If initial success, then get the final status from the IOSB. */\n            if ( !ERR(status) )\n                status = pka_acp_iosb.status;\n\n            if ( ERR(status) )\n            {\n                sprintf(warnmsg,\n                  \"warning:  set-dir-attributes failed ($qiow acc) for %s.\\n\",\n                  dir_name);\n                vms_msg(__G__ warnmsg, status);\n                retcode = PK_WARN;\n            }\n            else\n            {\n                /* We should have valid RECATTR data.  Overwrite the\n                 * critical bits of the archive RECATTR structure with\n                 * the current bits.  The book says that an attempt to\n                 * modify HIBLK will be ignored, and FFBYTE should\n                 * always be zero, but safety is cheap.\n                 */\n                struct fatdef *ptr_recattr;\n\n                ptr_recattr = (struct fatdef *) pka_atr[i].atr$l_addr;\n                ptr_recattr->fat$l_hiblk =  pka_rattr.fat$l_hiblk;\n                ptr_recattr->fat$l_efblk =  pka_rattr.fat$l_efblk;\n                ptr_recattr->fat$w_ffbyte = pka_rattr.fat$w_ffbyte;\n            }\n        /* There should be only one RECATTR structure in the list, so\n         * escape from the loop after the first/only one has been\n         * processed.\n         */\n        break;\n        }\n    }\n\n    /* Modify the file (directory) attributes. */\n    status = sys$qiow(0,                            /* event flag */\n                      pka_devchn,                   /* channel */\n                      IO$_MODIFY,                   /* function code */\n                      &pka_acp_iosb,                /* IOSB */\n                      0,                            /* AST address */\n                      0,                            /* AST parameter */\n                      &pka_fibdsc,                  /* P1 = File Info Block */\n                      &pka_fnam,                    /* P2 = File name */\n                      0,                            /* P3 = Rslt nm len */\n                      0,                            /* P4 = Rslt nm str */\n                      pka_atr,                      /* P5 = Attributes */\n                      0);                           /* P6 (not used) */\n\n    /* If initial success, then get the final status from the IOSB. */\n    if ( !ERR(status) )\n        status = pka_acp_iosb.status;\n\n    if ( ERR(status) )\n    {\n        sprintf(warnmsg,\n          \"warning:  set-dir-attributes failed ($qiow mod) for %s.\\n\",\n          dir_name);\n        vms_msg(__G__ warnmsg, status);\n        retcode = PK_WARN;\n    }\n    sys$dassgn(pka_devchn);\ncleanup_exit:\n    free_up();                          /* Free FAB, XAB storage. */\n    free(d);                            /* Free directory attribute storage. */\n    G.extra_field = sav_ef_ptr;         /* Restore original pointer. */\n    return retcode;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n#ifdef TIMESTAMP\n\n/* Nonzero if `y' is a leap year, else zero. */\n#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n\n/* Number of leap years from 1970 to `y' (not including `y' itself). */\n#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)\n\n/* Accumulated number of days from 01-Jan up to start of current month. */\nstatic ZCONST short ydays[] = {\n    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365\n};\n\n/***********************/\n/* Function mkgmtime() */\n/***********************/\n\nstatic time_t mkgmtime(tm)\n    struct tm *tm;\n{\n    time_t m_time;\n    int yr, mo, dy, hh, mm, ss;\n    unsigned days;\n\n    yr = tm->tm_year - 70;\n    mo = tm->tm_mon;\n    dy = tm->tm_mday - 1;\n    hh = tm->tm_hour;\n    mm = tm->tm_min;\n    ss = tm->tm_sec;\n\n    /* calculate days from BASE to this year and add expired days this year */\n    dy = (unsigned)dy + ((unsigned)yr * 365) + (unsigned)nleap(yr+1970) +\n         (unsigned)ydays[mo] + ((mo > 1) && leap(yr+1970));\n\n    /* convert date & time to seconds relative to 00:00:00, 01/01/1970 */\n    return (time_t)((unsigned long)(unsigned)dy * 86400L +\n                    (unsigned long)hh * 3600L +\n                    (unsigned long)(mm * 60 + ss));\n\n} /* end function mkgmtime() */\n\n\n\n/*******************************/\n/* Function dos_to_unix_time() */  /* only used for timestamping of archives */\n/*******************************/\n\ntime_t dos_to_unix_time(dosdatetime)\n    ulg dosdatetime;\n{\n    struct tm *ltm;             /* Local time. */\n    time_t loctime;             /* The time_t value of local time. */\n    time_t then;                /* The time to return. */\n    long tzoffset_adj;          /* timezone-adjustment `remainder' */\n    int bailout_cnt;            /* counter of tries for tz correction */\n\n    then = time(NULL);\n    ltm = localtime(&then);\n\n    /* dissect date */\n    ltm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + 80;\n    ltm->tm_mon  = ((int)(dosdatetime >> 21) & 0x0f) - 1;\n    ltm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);\n\n    /* dissect time */\n    ltm->tm_hour = (int)(dosdatetime >> 11) & 0x1f;\n    ltm->tm_min  = (int)(dosdatetime >> 5) & 0x3f;\n    ltm->tm_sec  = (int)(dosdatetime << 1) & 0x3e;\n\n    loctime = mkgmtime(ltm);\n\n    /* Correct for the timezone and any daylight savings time.\n       The correction is verified and repeated when not correct, to\n       take into account the rare case that a change to or from daylight\n       savings time occurs between when it is the time in `tm' locally\n       and when it is that time in Greenwich. After the second correction,\n       the \"timezone & daylight\" offset should be correct in all cases. To\n       be sure, we allow a third try, but then the loop is stopped. */\n    bailout_cnt = 3;\n    then = loctime;\n    do {\n      ltm = localtime(&then);\n      tzoffset_adj = (ltm != NULL) ? (loctime - mkgmtime(ltm)) : 0L;\n      if (tzoffset_adj == 0L)\n        break;\n      then += tzoffset_adj;\n    } while (--bailout_cnt > 0);\n\n    if ( (dosdatetime >= DOSTIME_2038_01_18) &&\n         (then < (time_t)0x70000000L) )\n        then = U_TIME_T_MAX;    /* saturate in case of (unsigned) overflow */\n    if (then < (time_t)0L)      /* a converted DOS time cannot be negative */\n        then = S_TIME_T_MAX;    /*  -> saturate at max signed time_t value */\n    return then;\n\n} /* end function dos_to_unix_time() */\n\n\n\n/*******************************/\n/*  Function uxtime2vmstime()  */\n/*******************************/\n\nstatic void uxtime2vmstime(  /* convert time_t value into 64 bit VMS bintime */\n    time_t utimeval,\n    long int binval[2] )\n{\n    time_t m_time = utimeval;\n    struct tm *t = localtime(&m_time);\n\n    if (t == (struct tm *)NULL) {\n        /* time conversion error; use current time instead, hoping\n           that localtime() does not reject it as well! */\n        m_time = time(NULL);\n        t = localtime(&m_time);\n    }\n    sprintf(timbuf, \"%02d-%3s-%04d %02d:%02d:%02d.00\",\n            t->tm_mday, month[t->tm_mon], t->tm_year + 1900,\n            t->tm_hour, t->tm_min, t->tm_sec);\n    sys$bintim(&date_str, binval);\n} /* end function uxtime2vmstime() */\n\n\n\n/***************************/\n/*  Function stamp_file()  */  /* adapted from VMSmunch...it just won't die! */\n/***************************/\n\nint stamp_file(fname, modtime)\n    ZCONST char *fname;\n    time_t modtime;\n{\n    int status;\n    int i;\n    static long int Cdate[2], Rdate[2], Edate[2], Bdate[2];\n    static short int revisions;\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n    static union {\n      unsigned short int value;\n      struct {\n        unsigned system : 4;\n        unsigned owner : 4;\n        unsigned group : 4;\n        unsigned world : 4;\n      } bits;\n    } prot;\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n    static unsigned long uic;\n    static struct fjndef jnl;\n\n    static struct atrdef Atr[] = {\n        {sizeof(pka_rattr), ATR$C_RECATTR, GVTC &pka_rattr},\n        {sizeof(pka_uchar), ATR$C_UCHAR, GVTC &pka_uchar},\n        {sizeof(Cdate), ATR$C_CREDATE, GVTC &Cdate[0]},\n        {sizeof(Rdate), ATR$C_REVDATE, GVTC &Rdate[0]},\n        {sizeof(Edate), ATR$C_EXPDATE, GVTC &Edate[0]},\n        {sizeof(Bdate), ATR$C_BAKDATE, GVTC &Bdate[0]},\n        {sizeof(revisions), ATR$C_ASCDATES, GVTC &revisions},\n        {sizeof(prot), ATR$C_FPRO, GVTC &prot},\n        {sizeof(uic), ATR$C_UIC, GVTC &uic},\n        {sizeof(jnl), ATR$C_JOURNAL, GVTC &jnl},\n        {0, 0, 0}\n    };\n\n    fileblk = cc$rms_fab;               /* Initialize FAB. */\n    nam = CC_RMS_NAM;                   /* Initialize NAM[L]. */\n    fileblk.FAB_NAM = &nam;             /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n    fileblk.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fileblk.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n    /* Special ODS5-QIO-compatible name storage. */\n    nam.naml$l_filesys_name = sys_nam;\n    nam.naml$l_filesys_name_alloc = sizeof(sys_nam);\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNA = (char *)fname;\n    FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNS = strlen(fname);\n\n    nam.NAM_ESA = exp_nam;\n    nam.NAM_ESS = sizeof(exp_nam);\n    nam.NAM_RSA = res_nam;\n    nam.NAM_RSS = sizeof(res_nam);\n\n    if ( ERR(status = sys$parse(&fileblk)) )\n    {\n        vms_msg(__G__ \"stamp_file: sys$parse failed.\\n\", status);\n        return -1;\n    }\n\n    pka_devdsc.dsc$w_length = (unsigned short)nam.NAM_DVI[0];\n\n    if ( ERR(status = sys$assign(&pka_devdsc, &pka_devchn, 0, 0)) )\n    {\n        vms_msg(__G__ \"stamp_file: sys$assign failed.\\n\", status);\n        return -1;\n    }\n\n    /* Load the descriptor with the appropriate name data: */\n#ifdef NAML$C_MAXRSS\n\n    /* Enable fancy name characters.  Note that \"fancy\" here does\n       not include Unicode, for which there's no support elsewhere.\n    */\n    pka_fib.fib$v_names_8bit = 1;\n    pka_fib.fib$b_name_format_in = FIB$C_ISL1;\n\n    /* ODS5 Extended names used as input to QIO have peculiar\n       encoding (perhaps to minimize storage?), so the special\n       filesys_name result (typically containing fewer carets) must\n       be used here.\n    */\n    pka_fnam.dsc$a_pointer = nam.naml$l_filesys_name;\n    pka_fnam.dsc$w_length = nam.naml$l_filesys_name_size;\n\n#else /* !NAML$C_MAXRSS */\n\n    /* Extract only the name.type;version. */\n    pka_fnam.dsc$a_pointer = nam.NAM_L_NAME;\n    pka_fnam.dsc$w_length = nam.NAM_B_NAME + nam.NAM_B_TYPE + nam.NAM_B_VER;\n\n#endif /* ?NAML$C_MAXRSS */\n\n    /* Move the directory ID from the NAM[L] to the FIB.\n       Clear the FID in the FIB, as we're using the name.\n    */\n    for (i = 0; i < 3; i++)\n    {\n        pka_fib.FIB$W_DID[i] = nam.NAM_DID[i];\n        pka_fib.FIB$W_FID[i] = 0;\n    }\n\n    /* Use the IO$_ACCESS function to return info about the file.\n       This way, the file is not opened, and the expiration and\n       revision dates are not modified.\n    */\n    status = sys$qiow(0, pka_devchn, IO$_ACCESS,\n                      &pka_acp_iosb, 0, 0,\n                      &pka_fibdsc, &pka_fnam, 0, 0, Atr, 0);\n\n    if ( !ERR(status) )\n        status = pka_acp_iosb.status;\n\n    if ( ERR(status) )\n    {\n        vms_msg(__G__ \"[ Access file QIO failed. ]\\n\", status);\n        sys$dassgn(pka_devchn);\n        return -1;\n    }\n\n    uxtime2vmstime(modtime, Cdate);\n    memcpy(Rdate, Cdate, sizeof(Cdate));\n\n    /* Note: Part of the FIB was cleared by earlier QIOW, so reset it. */\n    pka_fib.FIB$L_ACCTL = FIB$M_NORECORD;\n\n    /* Move the directory ID from the NAM[L] to the FIB.\n       Clear the FID in the FIB, as we're using the name.\n    */\n    for (i = 0; i < 3; i++)\n    {\n        pka_fib.FIB$W_DID[i] = nam.NAM_DID[i];\n        pka_fib.FIB$W_FID[i] = 0;\n    }\n\n    /* Use the IO$_MODIFY function to change info about the file */\n    /* Note, used this way, the file is not opened, however this would */\n    /* normally cause the expiration and revision dates to be modified. */\n    /* Using FIB$M_NORECORD prohibits this from happening. */\n    status = sys$qiow(0, pka_devchn, IO$_MODIFY,\n                      &pka_acp_iosb, 0, 0,\n                      &pka_fibdsc, &pka_fnam, 0, 0, Atr, 0);\n\n    if ( !ERR(status) )\n        status = pka_acp_iosb.status;\n\n    if ( ERR(status) )\n    {\n        vms_msg(__G__ \"[ Modify file QIO failed. ]\\n\", status);\n        sys$dassgn(pka_devchn);\n        return -1;\n    }\n\n    if ( ERR(status = sys$dassgn(pka_devchn)) )\n    {\n        vms_msg(__G__ \"stamp_file: sys$dassgn failed.\\n\", status);\n        return -1;\n    }\n\n    return 0;\n\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n#ifdef DEBUG\n#if 0   /* currently not used anywhere ! */\nvoid dump_rms_block(p)\n    unsigned char *p;\n{\n    unsigned char bid, len;\n    int err;\n    char *type;\n    char buf[132];\n    int i;\n\n    err = 0;\n    bid = p[0];\n    len = p[1];\n    switch (bid)\n    {\n        case FAB$C_BID:\n            type = \"FAB\";\n            break;\n        case XAB$C_ALL:\n            type = \"xabALL\";\n            break;\n        case XAB$C_KEY:\n            type = \"xabKEY\";\n            break;\n        case XAB$C_DAT:\n            type = \"xabDAT\";\n            break;\n        case XAB$C_RDT:\n            type = \"xabRDT\";\n            break;\n        case XAB$C_FHC:\n            type = \"xabFHC\";\n            break;\n        case XAB$C_PRO:\n            type = \"xabPRO\";\n            break;\n        default:\n            type = \"Unknown\";\n            err = 1;\n            break;\n    }\n    printf(\"Block @%08X of type %s (%d).\", p, type, bid);\n    if (err)\n    {\n        printf(\"\\n\");\n        return;\n    }\n    printf(\" Size = %d\\n\", len);\n    printf(\" Offset - Hex - Dec\\n\");\n    for (i = 0; i < len; i += 8)\n    {\n        int j;\n\n        printf(\"%3d - \", i);\n        for (j = 0; j < 8; j++)\n            if (i + j < len)\n                printf(\"%02X \", p[i + j]);\n            else\n                printf(\"   \");\n        printf(\" - \");\n        for (j = 0; j < 8; j++)\n            if (i + j < len)\n                printf(\"%03d \", p[i + j]);\n            else\n                printf(\"    \");\n        printf(\"\\n\");\n    }\n}\n\n#endif                          /* never */\n#endif                          /* DEBUG */\n\n\n\nstatic char vms_msgbuf[256];            /* VMS-specific error message. */\nstatic $DESCRIPTOR(vms_msgbuf_dscr, vms_msgbuf);\n\n\nchar *vms_msg_text(void)\n{\n    return vms_msgbuf;\n}\n\n\nstatic int vms_msg_fetch(int status)\n{\n    int msglen = 0;\n    int sts;\n\n    sts = lib$sys_getmsg(&status, &msglen, &vms_msgbuf_dscr, 0, 0);\n\n    vms_msgbuf[msglen] = '\\0';\n    return sts;\n}\n\n\nstatic void vms_msg(__GPRO__ ZCONST char *string, int status)\n{\n    if (ERR(vms_msg_fetch(status)))\n        Info(slide, 1, ((char *)slide,\n             \"%s[ VMS status = %d ]\\n\", string, status));\n    else\n        Info(slide, 1, ((char *)slide,\n             \"%s[ %s ]\\n\", string, vms_msgbuf));\n}\n\n\n\n#ifndef SFX\n\n/* 2004-11-23 SMS.\n * Changed to return the resulting file name even when sys$search()\n * fails.  Before, if the user specified \"fred.zip;4\" and there was\n * none, the error message would complain:\n *    cannot find either fred.zip;4 or fred.zip;4.zip.\n * when it wasn't really looking for \"fred.zip;4.zip\".\n */\n/* 2005-08-11 SPC.\n * The calling interface for the VMS version of do_wild() differs from all\n * other implementations in the way it returns status info.\n * There are three return states:\n * a) pointer to buffer with non-zero-length string\n *    - canonical full filespec of existing file (search succeeded).\n * b) pointer to buffer with zero-length string\n *    - initial file search has failed, extended VMS error info is available\n *      through call to vms_msg_text().\n * c) NULL pointer\n *    - repeated file search has failed, because\n *      i)   the list of matches for the pattern has been exhausted after at\n *           least one successful attempt.\n *      ii)  a second attempt for a failed initial pattern (where do_wild()\n *           has returned a zero-length string) was tried and failed again.\n */\nchar *do_wild( __G__ wld )\n    __GDEF\n    ZCONST char *wld;\n{\n    int status;\n\n    static char filenam[NAM_MAXRSS + 1];\n    static char efn[NAM_MAXRSS];\n    static char last_wild[NAM_MAXRSS + 1];\n    static struct FAB fab;\n    static struct NAM_STRUCT nam;\n    static int first_call = 1;\n    static ZCONST char deflt[] = \"[]*.ZIP\";\n\n    if ( first_call || strcmp(wld, last_wild) )\n    {   /* (Re)Initialize everything */\n\n        strcpy( last_wild, wld );\n\n        fab = cc$rms_fab;               /* Initialize FAB. */\n        nam = CC_RMS_NAM;               /* Initialize NAM[L]. */\n        fab.FAB_NAM = &nam;             /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n        fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n        fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = (char *) deflt;\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = sizeof(deflt) - 1;\n\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = last_wild;\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(last_wild);\n\n        nam.NAM_ESA = efn;\n        nam.NAM_ESS = sizeof(efn)-1;\n        nam.NAM_RSA = filenam;\n        nam.NAM_RSS = sizeof(filenam)-1;\n\n        first_call = 0;\n\n        /* 2005-08-08 SMS.\n         * Parse the file spec.  If sys$parse() fails, save the VMS\n         * error message for later use, and return an empty string.\n         */\n        nam.NAM_NOP = NAM_M_SYNCHK;     /* Syntax-only analysis. */\n        if ( !OK(status = sys$parse(&fab)) )\n        {\n            vms_msg_fetch(status);\n            filenam[0] = '\\0';          /* Initialization failed */\n            return filenam;\n        }\n\n        /* 2005-11-16 SMS.\n         * If syntax-only parse worked, re-parse normally so that\n         * sys$search() will work properly.  Regardless of parse error,\n         * leave filenam[] as-was.\n         */\n        nam.NAM_NOP = 0;                /* Normal analysis. */\n        if ( OK(status = sys$parse(&fab)) )\n        {\n            status = sys$search(&fab);\n        }\n\n        if ( !OK(status) )\n        {\n            /* Save the VMS error message for later use. */\n            vms_msg_fetch(status);\n        }\n    }\n    else\n    {\n        if ( !OK(sys$search(&fab)) )\n        {\n            first_call = 1;             /* Reinitialize next time */\n            return (char *)NULL;\n        }\n    }\n    filenam[nam.NAM_RSL] = '\\0';        /* Add the NUL terminator. */\n    return filenam;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\nstatic ulg unix_to_vms[8]={ /* Map from UNIX rwx to VMS rwed */\n                            /* Note that unix w bit is mapped to VMS wd bits */\n                                                              /* no access */\n    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* --- */\n    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL,                  /* --x */\n    XAB$M_NOREAD |                               XAB$M_NOEXE,    /* -w- */\n    XAB$M_NOREAD,                                                /* -wx */\n                   XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* r-- */\n                   XAB$M_NOWRITE | XAB$M_NODEL,                  /* r-x */\n                                                 XAB$M_NOEXE,    /* rw- */\n    0                                                            /* rwx */\n                                                              /* full access */\n};\n\n#define SETDFPROT   /* We are using undocumented VMS System Service     */\n                    /* SYS$SETDFPROT here. If your version of VMS does  */\n                    /* not have that service, undef SETDFPROT.          */\n                    /* IM: Maybe it's better to put this to Makefile    */\n                    /* and DESCRIP.MMS */\n#ifdef SETDFPROT\nextern int sys$setdfprot();\n#endif\n\nint mapattr(__G)\n    __GDEF\n{\n    ulg tmp = G.crec.external_file_attributes;\n    ulg theprot;\n    static ulg  defprot = (ulg)-1L,\n                sysdef, owndef, grpdef, wlddef; /* Default protection fields */\n\n    /* IM: The only field of XABPRO we need to set here is */\n    /*     file protection, so we need not to change type */\n    /*     of G.pInfo->file_attr. WORD is quite enough. */\n\n    if ( defprot == (ulg)-1L )\n    {\n        /*\n         * First time here -- Get user default settings\n         */\n\n#ifdef SETDFPROT    /* Undef this if linker cat't resolve SYS$SETDFPROT */\n        defprot = (ulg)0L;\n        if ( !ERR(sys$setdfprot(0, &defprot)) )\n        {\n            sysdef = defprot & ( (1L<<XAB$S_SYS)-1 ) << XAB$V_SYS;\n            owndef = defprot & ( (1L<<XAB$S_OWN)-1 ) << XAB$V_OWN;\n            grpdef = defprot & ( (1L<<XAB$S_GRP)-1 ) << XAB$V_GRP;\n            wlddef = defprot & ( (1L<<XAB$S_WLD)-1 ) << XAB$V_WLD;\n        }\n        else\n#endif /* SETDFPROT */\n        {\n            umask(defprot = umask(0));\n            defprot = ~defprot;\n            wlddef = unix_to_vms[defprot & 07] << XAB$V_WLD;\n            grpdef = unix_to_vms[(defprot>>3) & 07] << XAB$V_GRP;\n            owndef = unix_to_vms[(defprot>>6) & 07] << XAB$V_OWN;\n            sysdef = owndef >> (XAB$V_OWN - XAB$V_SYS);\n            defprot = sysdef | owndef | grpdef | wlddef;\n        }\n    }\n\n    switch (G.pInfo->hostnum) {\n        case AMIGA_:\n            tmp = (unsigned)(tmp>>16 & 0x0f);   /* Amiga RWED bits */\n            G.pInfo->file_attr =  (tmp << XAB$V_OWN) |\n                                   grpdef | sysdef | wlddef;\n            break;\n\n        case THEOS_:\n            tmp &= 0xF1FFFFFFL;\n            if ((tmp & 0xF0000000L) != 0x40000000L)\n                tmp &= 0x01FFFFFFL;     /* not a dir, mask all ftype bits */\n            else\n                tmp &= 0x41FFFFFFL;     /* leave directory bit as set */\n            /* fall through! */\n\n        case UNIX_:\n        case VMS_:  /*IM: ??? Does VMS Zip store protection in UNIX format ?*/\n                    /* GRR:  Yup.  Bad decision on my part... */\n        case ACORN_:\n        case ATARI_:\n        case ATHEOS_:\n        case BEOS_:\n        case QDOS_:\n        case TANDEM_:\n            {\n              int r = FALSE;\n              unsigned uxattr = (unsigned)(tmp >> 16);  /* drwxrwxrwx */\n\n              if (uxattr == 0 && G.extra_field) {\n                /* Some (non-Info-ZIP) implementations of Zip for Unix and\n                 * VMS (and probably others ??) leave 0 in the upper 16-bit\n                 * part of the external_file_attributes field. Instead, they\n                 * store file permission attributes in some e.f. block.\n                 * As a work-around, we search for the presence of one of\n                 * these extra fields and fall back to the MSDOS compatible\n                 * part of external_file_attributes if one of the known\n                 * e.f. types has been detected.\n                 * Later, we might implement extraction of the permission\n                 * bits from the VMS extra field. But for now, the work-around\n                 * should be sufficient to provide \"readable\" extracted files.\n                 * (For ASI Unix e.f., an experimental remap of the e.f.\n                 * mode value IS already provided!)\n                 */\n                ush ebID;\n                unsigned ebLen;\n                uch *ef = G.extra_field;\n                unsigned ef_len = G.crec.extra_field_length;\n\n                while (!r && ef_len >= EB_HEADSIZE) {\n                    ebID = makeword(ef);\n                    ebLen = (unsigned)makeword(ef+EB_LEN);\n                    if (ebLen > (ef_len - EB_HEADSIZE))\n                        /* discoverd some e.f. inconsistency! */\n                        break;\n                    switch (ebID) {\n                      case EF_ASIUNIX:\n                        if (ebLen >= (EB_ASI_MODE+2)) {\n                            uxattr =\n                              (unsigned)makeword(ef+(EB_HEADSIZE+EB_ASI_MODE));\n                            /* force stop of loop: */\n                            ef_len = (ebLen + EB_HEADSIZE);\n                            break;\n                        }\n                        /* else: fall through! */\n                      case EF_PKVMS:\n                        /* \"found nondecypherable e.f. with perm. attr\" */\n                        r = TRUE;\n                      default:\n                        break;\n                    }\n                    ef_len -= (ebLen + EB_HEADSIZE);\n                    ef += (ebLen + EB_HEADSIZE);\n                }\n              }\n              if (!r) {\n#ifdef SYMLINKS\n                  /* Check if the file is a (POSIX-compatible) symbolic link.\n                   * We restrict symlink support to those \"made-by\" hosts that\n                   * are known to support symbolic links.\n                   */\n                  G.pInfo->symlink = S_ISLNK(uxattr) &&\n                                     SYMLINK_HOST(G.pInfo->hostnum);\n#endif\n                  theprot  = (unix_to_vms[uxattr & 07] << XAB$V_WLD)\n                           | (unix_to_vms[(uxattr>>3) & 07] << XAB$V_GRP)\n                           | (unix_to_vms[(uxattr>>6) & 07] << XAB$V_OWN);\n                  if ( uxattr & 0x4000 )\n                      /* Directory -- set D bits */\n                      theprot |= (XAB$M_NODEL << XAB$V_SYS)\n                              | (XAB$M_NODEL << XAB$V_OWN)\n                              | (XAB$M_NODEL << XAB$V_GRP)\n                              | (XAB$M_NODEL << XAB$V_WLD);\n                  G.pInfo->file_attr = theprot;\n                  break;\n              }\n            }\n            /* fall through! */\n\n        /* all remaining cases:  expand MSDOS read-only bit into write perms */\n        case FS_FAT_:\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case MAC_:\n        case TOPS20_:\n        default:\n            theprot = defprot;\n            if ( tmp & 1 )   /* Test read-only bit */\n            {   /* Bit is set -- set bits in all fields */\n                tmp = XAB$M_NOWRITE | XAB$M_NODEL;\n                theprot |= (tmp << XAB$V_SYS) | (tmp << XAB$V_OWN) |\n                           (tmp << XAB$V_GRP) | (tmp << XAB$V_WLD);\n            }\n            G.pInfo->file_attr = theprot;\n            break;\n    } /* end switch (host-OS-created-by) */\n\n    return 0;\n\n} /* end function mapattr() */\n\n\n#define PATH_DEFAULT \"SYS$DISK:[]\"\n\n/* dest_struct_level()\n\n      Returns file system structure level for argument, negative on\n      error.\n*/\n\nint dest_struct_level(char *path)\n{\n    int acp_code;\n\n#ifdef DVI$C_ACP_F11V5\n\n    /* Should know about ODS5 file system.  Do actual check.\n       (This should be non-VAX with __CRTL_VER >= 70200000.)\n    */\n\n    int sts;\n\n    struct FAB fab;\n    struct NAM_STRUCT nam;\n    char e_name[NAM_MAXRSS + 1];\n\n    struct dsc$descriptor_s dev_descr =\n     { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };\n\n    fab = cc$rms_fab;                   /* Initialize FAB. */\n    nam = CC_RMS_NAM;                   /* Initialize NAM[L]. */\n    fab.FAB_NAM = &nam;                 /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna = (char *) -1;        /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;        /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = PATH_DEFAULT;\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = strlen(PATH_DEFAULT);\n\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = path;\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(path);\n\n    nam.NAM_ESA = e_name;\n    nam.NAM_ESS = sizeof(e_name) - 1;\n\n    nam.NAM_NOP = NAM_M_SYNCHK;         /* Syntax-only analysis. */\n    sts = sys$parse(&fab);\n\n    if ((sts & STS$M_SUCCESS) == STS$K_SUCCESS)\n    {\n        /* Load resultant device name into device descriptor. */\n        dev_descr.dsc$a_pointer = nam.NAM_L_DEV;\n        dev_descr.dsc$w_length = nam.NAM_B_DEV;\n\n        /* Get filesystem type code.\n           (Text results for this item code have been unreliable.)\n        */\n        sts = lib$getdvi(&((int) DVI$_ACPTYPE),\n                         0,\n                         &dev_descr,\n                         &acp_code,\n                         0,\n                         0);\n\n        if ((sts & STS$M_SUCCESS) != STS$K_SUCCESS)\n        {\n            acp_code = -2;\n        }\n    }\n    else\n    {\n        acp_code = -1;\n    }\n\n#else /* !DVI$C_ACP_F11V5 */\n\n/* Too old for ODS5 file system.  Return level 2. */\n\n    acp_code = DVI$C_ACP_F11V2;\n\n#endif /* ?DVI$C_ACP_F11V5 */\n\n    return acp_code;\n}\n\n/* 2005-02-12 SMS.\n   Note that these name conversion functions do no length checking.\n   Buffer overflows are possible.\n*/\n\nstatic void adj_dir_name_ods2(char *dest, char *src, int src_len)\n{\n    /* The source string (src) typically extends beyond the directory\n       segment of interest, hence the confining src_len argument.\n    */\n    unsigned char uchr;\n    unsigned char prop;\n    char * src_last;\n\n    for (src_last = src + src_len; src < src_last; src++)\n    {\n        prop = char_prop[uchr = *src];  /* Get source char, properties. */\n        if ((prop & 2) != 0)            /* Up-case lower case. */\n        {\n            uchr -= ('a' - 'A');        /* (Simple-fast is adequate.) */\n        }\n        else if ((prop & 1) == 0)       /* Replace invalid char */\n        {\n            uchr = '_';                 /* with \"_\". */\n        }\n        *dest++ = uchr;                 /* Store good char. */\n    }\n    *dest = '\\0';                       /* Terminate destination. */\n}\n\n\nstatic void adj_dir_name_ods5(char *dest, char *src, int src_len)\n{\n    /* The source string (src) typically extends beyond the directory\n       segment of interest, hence the confining src_len argument.\n    */\n    unsigned char uchr;\n    unsigned char prop;\n    char * src_last;\n\n    for (src_last = src + src_len; src < src_last; src++)\n    {\n        prop = char_prop[uchr = *src];          /* Get source char, props. */\n        prop = char_prop[uchr];                 /* Get source char props. */\n        if ((prop & (32+8+4)) != 0)             /* Escape 1-char, including */\n        {                                       /* SP and dot. */\n            *dest++ = '^';                      /* Insert caret. */\n            if ((prop & 8) != 0)                /* Replace SP with \"_\". */\n            {\n                uchr = '_';\n            }\n            else if (uchr == '?')\n            {\n                uchr = '/';                     /* Replace \"?\" with \"/\". */\n            }\n        }\n        else if ((prop & 64) != 0)              /* Escape hex-hex. */\n        {\n            *dest++ = '^';                      /* Insert caret. */\n            *dest++ = hex_digit[uchr >> 4];     /* First hex digit. */\n            uchr = hex_digit[uchr & 15];        /* Second hex digit. */\n        }\n        else if ((prop & 16) == 0)              /* Replace invalid with \"_\". */\n        {\n            uchr = '_';\n        }\n        *dest++ = uchr;                         /* Put good (or last) char. */\n    }\n    *dest = '\\0';                               /* Terminate destination. */\n}\n\n\nstatic void adj_file_name_ods2(char *dest, char *src)\n{\n    unsigned char uchr;\n    unsigned char prop;\n    char *endp;\n    char *versionp;\n    char *last_dot;\n\n    endp = src + strlen(src);   /* Pointer to the NUL-terminator of src. */\n    /* Starting at the end, find the last non-decimal-digit. */\n    versionp = endp;\n    while ((--versionp >= src) && isdigit(*versionp));\n\n    /* Left-most non-digit of a valid version is \";\" (or perhaps \".\"). */\n    if ((*versionp != ';') && ((uO.Y_flag == 0) || (*versionp != '.')))\n    {\n        /* No valid version.  The last dot is the last dot. */\n        versionp = endp;\n    }\n    else\n    {   /* Some kind of valid version. */\n        if (!uO.V_flag)                 /* Not -V, so cut off version. */\n        {\n            *versionp = '\\0';\n        }\n        else if (*versionp == '.')\n        {\n            *versionp = ';';            /* Replace version dot with \";\". */\n        }\n    }\n\n    /* 2008-11-04 SMS.\n     * Simplified the scheme here to escape all non-last dots.  This\n     * should work when Zip works correctly (Zip 3.1).\n     * Note that if no last dot is found, the non-last-dot test below\n     * will always fail, but that's not a problem.\n     */\n\n    /* Find the last dot (if any). */\n    last_dot = versionp;\n    while ((--last_dot >= src) && (*last_dot != '.'));\n\n    /* Critical features having been located, transform the name. */\n    while ((uchr = *src++) != '\\0')     /* Get source character. */\n    {\n        /* Note that \"src\" has been incremented, affecting \"src <=\". */\n        prop = char_prop[uchr];         /* Get source char properties. */\n        if ((prop & 2) != 0)            /* Up-case lower case. */\n        {\n            uchr -= ('a' - 'A');        /* (Simple-fast is adequate.) */\n        }\n        else if ((prop & 4) != 0)       /* Dot. */\n        {\n            if (src <= last_dot)        /* Replace non-last dot */\n            {\n                uchr = '_';             /* with \"_\". */\n            }\n        }\n        else if ((prop & 1) == 0)       /* Replace SP or invalid char, */\n        {\n            if (src <= versionp)        /* if not in version, */\n            {\n                uchr = '_';             /* with \"_\". */\n            }\n        }\n        *dest++ = uchr;                 /* Store good char. */\n    }\n    *dest = '\\0';                       /* Terminate destination. */\n}\n\n\nstatic void adj_file_name_ods5(char *dest, char *src)\n{\n    unsigned char uchr;\n    unsigned char prop;\n    char *endp;\n    char *versionp;\n    char *last_dot;\n\n    endp = src + strlen(src);   /* Pointer to the NUL-terminator of src. */\n    /* Starting at the end, find the last non-decimal-digit. */\n    versionp = endp;\n    while ((--versionp >= src) && isdigit(*versionp));\n\n    /* Left-most non-digit of a valid version is \";\" (or perhaps \".\"). */\n    if ((*versionp != ';') && ((uO.Y_flag == 0) || (*versionp != '.')))\n    {\n        /* No valid version.  The last dot is the last dot. */\n        versionp = endp;\n    }\n    else\n    {   /* Some kind of valid version. */\n        if (!uO.V_flag)                 /* Not -V, so cut off version. */\n        {\n            *versionp = '\\0';\n        }\n        else if (*versionp == '.')\n        {\n            *versionp = ';';            /* Replace version dot with \";\". */\n        }\n    }\n\n    /* 2008-11-04 SMS.\n     * Simplified the scheme here to escape all non-last dots.  This\n     * should work when Zip works correctly (Zip 3.1).\n     * Note that if no last dot is found, the non-last-dot test below\n     * will always fail, but that's not a problem.\n     */\n\n    /* Find the last dot (if any). */\n    last_dot = versionp;\n    while ((--last_dot >= src) && (*last_dot != '.'));\n\n    /* Critical features having been located, transform the name. */\n    while ((uchr = *src++) != '\\0')             /* Get source character. */\n    {\n        /* Note that \"src\" has been incremented, affecting \"src <=\". */\n        prop = char_prop[uchr];                 /* Get source char props. */\n        if ((prop & (32+8)) != 0)               /* Escape 1-char, including */\n        {                                       /* SP (but not dot). */\n            if (src <= versionp)                /* No escapes for version. */\n            {\n                *dest++ = '^';                  /* Insert caret. */\n                if ((prop & 8) != 0)            /* Replace SP with \"_\". */\n                {\n                    uchr = '_';\n                }\n                else if (uchr == '?')\n                {\n                    uchr = '/';                 /* Replace \"?\" with \"/\". */\n                }\n            }\n        }\n        else if ((prop & 4) != 0)               /* Dot. */\n        {\n            if (src <= last_dot)                /* Escape non-last dot */\n            {\n                *dest++ = '^';                  /* Insert caret. */\n            }\n        }\n        else if ((prop & 64) != 0)              /* Escape hex-hex. */\n        {\n            *dest++ = '^';                      /* Insert caret. */\n            *dest++ = hex_digit[uchr >> 4];     /* First hex digit. */\n            uchr = hex_digit[uchr & 15];        /* Second hex digit. */\n        }\n        else if ((prop & 16) == 0)              /* Replace invalid with \"_\". */\n        {\n            uchr = '_';\n        }\n        *dest++ = uchr;                         /* Put good (or last) char. */\n    }\n    *dest = '\\0';                               /* Terminate destination. */\n}\n\n\n\n#   define FN_MASK   7\n#   define USE_DEFAULT  (FN_MASK+1)\n\n/*\n * Checkdir function codes:\n *      ROOT        -   set root path from unzip qq d:[dir]\n *      INIT        -   get ready for \"filename\"\n *      APPEND_DIR  -   append pathcomp\n *      APPEND_NAME -   append filename\n *      APPEND_NAME | USE_DEFAULT   -    expand filename using collected path\n *      GETPATH     -   return resulting filespec\n *      END         -   free dynamically allocated space prior to program exit\n */\n\nstatic int created_dir;\nstatic int dest_file_sys_level;\nstatic int ods2_names = -1;\n\nint mapname(__G__ renamed)\n        /* returns: */\n        /* MPN_OK if no error, */\n        /* MPN_INF_TRUNC if caution (filename trunc), */\n        /* MPN_INF_SKIP if warning (skip file, dir doesn't exist), */\n        /* MPN_ERR_SKIP if error (skip file), */\n        /* MPN_CREATED_DIR if has created directory, */\n        /* MPN_VOL_LABEL if path was volume label (skip it) */\n        /* MPN_NOMEM if no memory (skip file) */\n    __GDEF\n    int renamed;\n{\n    char pathcomp[FILNAMSIZ];       /* Path-component buffer. */\n    char *last_slash;               /* Last slash in path. */\n    char *next_slash;               /* Next slash in path. */\n    int  dir_len;                   /* Length of a directory segment. */\n\n    char *cp = (char *)NULL;        /* character pointer */\n    int killed_ddot = FALSE;        /* Set when skipping \"../\" pathcomp. */\n    int error = MPN_OK;\n\n    if ( renamed )\n    {\n        if ( !(error = checkdir(__G__ pathcomp, APPEND_NAME | USE_DEFAULT)) )\n            strcpy(G.filename, pathcomp);\n        return error;\n    }\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    if (G.pInfo->vollabel)\n        return MPN_VOL_LABEL;   /* can't set disk volume labels on VMS */\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = !uO.fflag;\n\n    created_dir = FALSE;        /* not yet */\n\n    /* If not yet known, determine the destination file system type\n       (ODS2 or ODS5).  (If the user specified a destination, we should\n       already have this, so use the default destination.)\n    */\n    if (ods2_names < 0)\n    {\n        /* If user doesn't force ODS2, set flag according to destination. */\n        if (uO.ods2_flag == 0)\n        {\n            ods2_names =\n             (dest_struct_level(PATH_DEFAULT) <= DVI$C_ACP_F11V2);\n        }\n        else\n        {\n            ods2_names = 1;     /* User demands ODS2 names. */\n        }\n    }\n\n/* GRR:  for VMS, convert to internal format now or later? or never? */\n    if (checkdir(__G__ pathcomp, INIT) == 10)\n        return MPN_NOMEM;       /* Initialize path buffer, unless no memory. */\n\n    /* Locate and treat directory segments one at a time.\n       When pointer exceeds last_slash, then directory segments are\n       done, and only the name (with version?) remains.\n    */\n\n    *pathcomp = '\\0';           /* Initialize translation buffer. */\n    last_slash = strrchr(G.filename, '/');      /* Find last slash. */\n\n    if (uO.jflag)               /* If junking directories, */\n        cp = last_slash;        /* start at (will be after) the last slash. */\n\n    if (cp == NULL)             /* If no '/', or keeping directories, */\n        cp = G.filename;        /* start at the front of the pathname. */\n    else                        /* Else, with directories to junk, */\n        ++cp;                   /* start after the last slash. */\n\n    /* Loop through the directory segments. */\n    while (cp < last_slash)\n    {\n        next_slash = strchr(cp, '/');  /* Find the next slash. */\n        dir_len = next_slash- cp;\n\n        /* Filter out unacceptable directories. */\n        if ((dir_len == 2) && (strncmp(cp, \"..\", 2) == 0))\n        {   /* Double dot. */\n            if (!uO.ddotflag)           /* Not allowed.  Skip it. */\n            {\n                dir_len = 0;\n                killed_ddot = TRUE;     /* Record skipping double-dot. */\n            }\n        }\n        else if ((dir_len == 1) && (strncmp(cp, \".\", 1) == 0))\n        {   /* Single dot.  No-op.  Skip it. */\n            dir_len = 0;\n        }\n\n        /* If non-null, acceptable directory, then process it. */\n        if (dir_len > 0)\n        {\n            if (ods2_names)     /* Make directory name ODS2-compliant. */\n            {\n                adj_dir_name_ods2(pathcomp, cp, dir_len);\n            }\n            else                /* Make directory name ODS5-compliant. */\n            {\n                adj_dir_name_ods5(pathcomp, cp, dir_len);\n            }\n            if (((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                 & MPN_MASK) > MPN_INF_TRUNC)\n                return error;\n        }\n        cp = next_slash+ 1;     /* Continue at the next name segment. */\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n    /* If there is one, adjust the name.type;version segment. */\n    if (strlen(cp) == 0)\n    {\n        /* Directory only, no file name.  Create the directory, as needed.\n           Report directory creation to user.\n        */\n        checkdir(__G__ \"\", APPEND_NAME);   /* create directory, if not found */\n        checkdir(__G__ G.filename, GETPATH);\n        if (created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %s\\n\",\n                  FnFilter1(G.filename)));\n            }\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    /* Process the file name. */\n    if (ods2_names)     /* Make file name ODS2-compliant. */\n    {\n        adj_file_name_ods2(pathcomp, cp);\n    }\n    else                /* Make file name ODS5-compliant. */\n    {\n        adj_file_name_ods5(pathcomp, cp);\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    return error;\n\n} /* end function mapname() */\n\n\n\nint checkdir(__G__ pathcomp, fcn)\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n    __GDEF\n    char *pathcomp;\n    int fcn;\n{\n    int function=fcn & FN_MASK;\n    static char pathbuf[FILNAMSIZ];\n\n    /* previously created directory (initialized to impossible dir. spec.) */\n    static char lastdir[FILNAMSIZ] = \"\\t\";\n\n    static char *pathptr = pathbuf;     /* For debugger */\n    static char *devptr, *dirptr;\n    static int  devlen, dirlen;\n    static int  root_dirlen;\n    static char *end;\n    static int  first_comp, root_has_dir;\n    static int  rootlen=0;\n    static char *rootend;\n    static int  mkdir_failed=0;\n    int status;\n    struct FAB fab;\n    struct NAM_STRUCT nam;\n\n\n/************\n *** ROOT ***\n ************/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (function == ROOT)\n    {   /*  Assume VMS root spec */\n        /* 2006-01-20 SMS.\n           Changed to use sys$parse() instead of sys$filescan() for analysis\n           of the user-specified destination directory.  Previously, various\n           values behaved badly, without complaint, e.g. \"-d sys$scratch\".\n        */\n        char *root_dest;\n\n        /* If the root path has already been set, return immediately. */\n        if (rootlen > 0)\n            return MPN_OK;\n\n        /* Initialization. */\n        root_dest = PATH_DEFAULT;   /* Default destination for ODSx sensing. */\n        root_has_dir = 0;           /* Root includes a directory. */\n        fab = cc$rms_fab;           /* Initialize FAB. */\n        nam = CC_RMS_NAM;           /* Initialize NAM[L]. */\n        fab.FAB_NAM = &nam;         /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n        fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n        fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n        /* Specified file spec. */\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = pathcomp;\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(pathcomp);\n\n        /* Default file spec. */\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = PATH_DEFAULT;\n        FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = strlen(PATH_DEFAULT);\n\n        /* Expanded file spec. */\n        nam.NAM_ESA = pathbuf;\n        nam.NAM_ESS = NAM_MAXRSS;\n\n        status = sys$parse(&fab);\n\n        /* OK so far, if OK or if directory not found. */\n        if (((status & STS$M_SEVERITY) != STS$K_SUCCESS) &&\n            (status != RMS$_DNF))\n        {\n            /* Invalid destination directory specified. */\n            Info(slide, 1, ((char *)slide,\n              \"Invalid destination directory (parse error): %s\\n\",\n              FnFilter1(pathcomp)));\n            return MPN_ERR_SKIP;\n        }\n\n        /* Should be only a device:[directory], so name+type+version\n           should have length 2 (\".;\").\n        */\n        if (nam.NAM_B_NAME + nam.NAM_B_TYPE + nam.NAM_B_VER > 2)\n        {\n            Info(slide, 1, ((char *)slide,\n              \"Invalid destination directory (includes file name): %s\\n\",\n              FnFilter1(nam.NAM_ESA)));\n            return MPN_ERR_SKIP;\n        }\n\n        /* Truncate at name, leaving only \"dev:[dir]\". */\n        *nam.NAM_L_NAME = '\\0';\n        rootlen = nam.NAM_L_NAME - nam.NAM_ESA;\n\n        /* Remove any trailing dots in directory. */\n        if ((nam.NAM_ESA[rootlen-1] == ']') &&\n            (nam.NAM_ESA[rootlen-2] != '^'))\n        {\n            root_has_dir = 1;\n            rootlen -= 2;\n            while ((nam.NAM_ESA[rootlen] == '.') &&\n                   (nam.NAM_ESA[rootlen-1] != '^'))\n            {\n                rootlen--;\n            }\n            nam.NAM_ESA[++rootlen] = ']';\n            nam.NAM_ESA[++rootlen] = '\\0';\n        }\n\n        devlen = nam.NAM_L_DIR - nam.NAM_ESA;\n\n        /* If directory not found, then create it. */\n        if (status == RMS$_DNF)\n        {\n            if (status = mkdir(nam.NAM_ESA, 0))\n            {\n                Info(slide, 1, ((char *)slide,\n                  \"Can not create destination directory: %s\\n\",\n                  FnFilter1(nam.NAM_ESA)));\n\n                /* path didn't exist, tried to create, and failed. */\n                return MPN_ERR_SKIP;\n            }\n        }\n\n        /* Save the (valid) device:[directory] spec. */\n        strcpy(pathbuf, nam.NAM_ESA);\n        root_dest = pathbuf;\n\n        /* At this point, the true destination is known.  If the user\n           supplied an invalid destination directory, the default\n           directory will be used.  (This may be pointless, but should\n           be safe.)\n        */\n\n        /* If not yet known, determine the destination (root_dest) file\n           system type (ODS2 or ODS5).\n        */\n        if (ods2_names < 0)\n        {\n            /* If user doesn't force ODS2, set flag according to dest. */\n            if (uO.ods2_flag == 0)\n            {\n                ods2_names = (dest_struct_level(root_dest) <= DVI$C_ACP_F11V2);\n            }\n            else\n            {\n                ods2_names = 1;     /* User demands ODS2 names. */\n            }\n        }\n\n        /* Replace trailing \"]\" with \".\", for later appending. */\n        if ((pathbuf[rootlen-1] == ']') || (pathbuf[rootlen-1] == '>'))\n        {\n            pathbuf[rootlen-1] = '.';\n        }\n\n        /* Set various pointers and lengths. */\n        devptr = pathbuf;\n        dirptr = pathbuf + (nam.NAM_L_DIR - nam.NAM_ESA);\n        rootend = pathbuf + rootlen;\n        *(end = rootend) = '\\0';\n        root_dirlen = dirlen = rootlen - devlen;\n        first_comp = !root_has_dir;\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n\n/************\n *** INIT ***\n ************/\n\n    if ( function == INIT )\n    {\n        if ( strlen(G.filename) + rootlen + 13 > NAM_MAXRSS )\n            return MPN_ERR_TOOLONG;\n\n        if ( rootlen == 0 )     /* No root given, reset everything. */\n        {\n            devptr = dirptr = rootend = pathbuf;\n            devlen = dirlen = 0;\n        }\n        end = rootend;\n        first_comp = !root_has_dir;\n        if ( dirlen = root_dirlen )\n            end[-1] = '.';\n        *end = '\\0';\n        return MPN_OK;\n    }\n\n\n/******************\n *** APPEND_DIR ***\n ******************/\n    if ( function == APPEND_DIR )\n    {\n        int cmplen;\n\n        cmplen = strlen(pathcomp);\n\n        if ( first_comp )\n        {\n            *end++ = '[';\n            if ( cmplen )\n                *end++ = '.';   /*       \"dir/...\" --> \"[.dir...]\"    */\n            /*                     else  \"/dir...\" --> \"[dir...]\"     */\n            first_comp = 0;\n        }\n\n        if ( cmplen == 1 && *pathcomp == '.' )\n            ; /* \"..././...\" -- ignore */\n\n        else if ( cmplen == 2 && pathcomp[0] == '.' && pathcomp[1] == '.' )\n        {   /* \".../../...\" -- convert to \"...-...\" */\n            *end++ = '-';\n            *end++ = '.';\n        }\n\n        else if ( cmplen + (end-pathptr) > NAM_MAXRSS )\n            return MPN_ERR_TOOLONG;\n\n        else\n        {\n            strcpy(end, pathcomp);\n            *(end+=cmplen) = '.';\n            ++end;\n        }\n        dirlen = end - dirptr;\n        *end = '\\0';\n        return MPN_OK;\n    }\n\n\n/*******************\n *** APPEND_NAME ***\n *******************/\n    if ( function == APPEND_NAME )\n    {\n        if ( fcn & USE_DEFAULT )\n        {   /* Expand renamed filename using collected path, return\n             *  at pathcomp */\n            fab = cc$rms_fab;           /* Initialize FAB. */\n            nam = CC_RMS_NAM;           /* Initialize NAM[L]. */\n            fab.FAB_NAM = &nam;         /* Point FAB to NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n            fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n            fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n            FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = pathptr;\n            FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = end - pathptr;\n            FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = G.filename;\n            FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(G.filename);\n\n            nam.NAM_ESA = pathcomp;     /* (Great design. ---v.  SMS.) */\n            nam.NAM_ESS = NAM_MAXRSS;   /* Assume large enough. */\n\n            if (!OK(status = sys$parse(&fab)) && status == RMS$_DNF )\n                                         /* Directory not found: */\n            {                            /* ... try to create it */\n                char    save;\n                char    *dirend;\n                int     mkdir_failed;\n\n                dirend = (char*)nam.NAM_L_DIR + nam.NAM_B_DIR;\n                save = *dirend;\n                *dirend = '\\0';\n                if ( (mkdir_failed = mkdir(nam.NAM_L_DEV, 0)) &&\n                     errno == EEXIST )\n                    mkdir_failed = 0;\n                *dirend = save;\n                if ( mkdir_failed )\n                    return 3;\n                created_dir = TRUE;\n            }                                /* if (sys$parse... */\n            pathcomp[nam.NAM_ESL] = '\\0';\n            return MPN_OK;\n        }                                /* if (USE_DEFAULT) */\n        else\n        {\n            *end = '\\0';\n            if ( dirlen )\n            {\n                dirptr[dirlen-1] = ']'; /* Close directory */\n\n                /*\n                 *  Try to create the target directory.\n                 *  Don't waste time creating directory that was created\n                 *  last time.\n                 */\n                if ( STRICMP(lastdir, pathbuf) )\n                {\n                    mkdir_failed = 0;\n                    if ( mkdir(pathbuf, 0) )\n                    {\n                        if ( errno != EEXIST )\n                            mkdir_failed = 1;   /* Mine for GETPATH */\n                    }\n                    else\n                        created_dir = TRUE;\n                    strcpy(lastdir, pathbuf);\n                }\n            }\n            else\n            {   /*\n                 * Target directory unspecified.\n                 * Try to create \"SYS$DISK:[]\"\n                 */\n                if ( strcmp(lastdir, PATH_DEFAULT) )\n                {\n                    strcpy(lastdir, PATH_DEFAULT);\n                    mkdir_failed = 0;\n                    if ( mkdir(lastdir, 0) && errno != EEXIST )\n                        mkdir_failed = 1;   /* Mine for GETPATH */\n                }\n            }\n            if ( strlen(pathcomp) + (end-pathbuf) > 255 )\n                return MPN_INF_TRUNC;\n            strcpy(end, pathcomp);\n            end += strlen(pathcomp);\n            return MPN_OK;\n        }\n    }\n\n\n/***************\n *** GETPATH ***\n ***************/\n    if ( function == GETPATH )\n    {\n        if ( mkdir_failed )\n            return MPN_ERR_SKIP;\n        *end = '\\0';                    /* To be safe */\n        strcpy( pathcomp, pathbuf );\n        return MPN_OK;\n    }\n\n\n/***********\n *** END ***\n ***********/\n    if ( function == END )\n    {\n        Trace((stderr, \"checkdir(): nothing to free...\\n\"));\n        rootlen = 0;\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n}\n\n\n\nint check_for_newer(__G__ filenam)   /* return 1 if existing file newer or */\n    __GDEF                           /*  equal; 0 if older; -1 if doesn't */\n    char *filenam;                   /*  exist yet */\n{\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n    struct tm *t;\n#endif\n    char *filenam_stat;\n    unsigned short timbuf[7];\n    unsigned dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;\n    struct FAB fab;\n    struct XABDAT xdat;\n#ifdef NAML$C_MAXRSS\n    struct NAM_STRUCT nam;\n#endif\n\n    /* 2008-07-12 SMS.\n     * Special case for \".\" as a file name, not as the current directory.\n     * Substitute \".;\" to keep stat() from seeing a plain \".\".\n    */\n    if (strcmp(filenam, \".\") == 0)\n        filenam_stat = \".;\";\n    else\n        filenam_stat = filenam;\n\n    if (stat(filenam_stat, &G.statbuf))\n        return DOES_NOT_EXIST;\n\n    fab  = cc$rms_fab;                  /* Initialize FAB. */\n    xdat = cc$rms_xabdat;               /* Initialize XAB. */\n\n#ifdef NAML$C_MAXRSS\n\n    nam  = CC_RMS_NAM;                  /* Initialize NAM[L]. */\n    fab.FAB_NAM = &nam;                 /* Point FAB to NAM[L]. */\n\n    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* NAML$C_MAXRSS */\n\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = filenam;\n    FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen(filenam);\n\n    fab.fab$l_xab = (char *) &xdat;\n    fab.fab$l_fop = FAB$M_GET | FAB$M_UFO;\n\n    if (ERR(sys$open(&fab)))             /* open failure:  report exists and */\n        return EXISTS_AND_OLDER;         /*  older so new copy will be made  */\n    sys$numtim(&timbuf, &xdat.xab$q_cdt);\n    fab.fab$l_xab = NULL;\n\n    sys$dassgn(fab.fab$l_stv);\n    sys$close(&fab);   /* be sure file is closed and RMS knows about it */\n\n#ifdef USE_EF_UT_TIME\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n         & EB_UT_FL_MTIME))\n        t = localtime(&(z_utime.mtime));\n    else\n        t = (struct tm *)NULL;\n\n    if (t != (struct tm *)NULL)\n    {\n        yr2 = (unsigned)(t->tm_year) + 1900;\n        mo2 = (unsigned)(t->tm_mon) + 1;\n        dy2 = (unsigned)(t->tm_mday);\n        hh2 = (unsigned)(t->tm_hour);\n        mm2 = (unsigned)(t->tm_min);\n        ss2 = (unsigned)(t->tm_sec);\n\n        /* round to nearest sec--may become 60,\n           but doesn't matter for compare */\n        ss = (unsigned)((float)timbuf[5] + (float)timbuf[6]*.01 + 0.5);\n        TTrace((stderr, \"check_for_newer:  using Unix extra field mtime\\n\"));\n    }\n    else\n#endif /* USE_EF_UT_TIME */\n    {\n        yr2 = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + 1980;\n        mo2 = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f;\n        dy2 = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;\n        hh2 = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;\n        mm2 = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;\n        ss2 = (G.lrec.last_mod_dos_datetime << 1) & 0x1f;\n\n        /* round to nearest 2 secs--may become 60,\n           but doesn't matter for compare */\n        ss = (unsigned)((float)timbuf[5] + (float)timbuf[6]*.01 + 1.) & (~1);\n    }\n    yr = timbuf[0];\n    mo = timbuf[1];\n    dy = timbuf[2];\n    hh = timbuf[3];\n    mm = timbuf[4];\n\n    if (yr > yr2)\n        return EXISTS_AND_NEWER;\n    else if (yr < yr2)\n        return EXISTS_AND_OLDER;\n\n    if (mo > mo2)\n        return EXISTS_AND_NEWER;\n    else if (mo < mo2)\n        return EXISTS_AND_OLDER;\n\n    if (dy > dy2)\n        return EXISTS_AND_NEWER;\n    else if (dy < dy2)\n        return EXISTS_AND_OLDER;\n\n    if (hh > hh2)\n        return EXISTS_AND_NEWER;\n    else if (hh < hh2)\n        return EXISTS_AND_OLDER;\n\n    if (mm > mm2)\n        return EXISTS_AND_NEWER;\n    else if (mm < mm2)\n        return EXISTS_AND_OLDER;\n\n    if (ss >= ss2)\n        return EXISTS_AND_NEWER;\n\n    return EXISTS_AND_OLDER;\n}\n\n\n\n#ifdef RETURN_CODES\nvoid return_VMS(__G__ err)\n    __GDEF\n#else\nvoid return_VMS(err)\n#endif\n    int err;\n{\n    int severity;\n\n#ifdef RETURN_CODES\n/*---------------------------------------------------------------------------\n    Do our own, explicit processing of error codes and print message, since\n    VMS misinterprets return codes as rather obnoxious system errors (\"access\n    violation,\" for example).\n  ---------------------------------------------------------------------------*/\n\n    switch (err) {\n        case PK_COOL:\n            break;   /* life is fine... */\n        case PK_WARN:\n            Info(slide, 1, ((char *)slide, \"\\n\\\n[return-code %d:  warning error \\\n(e.g., failed CRC or unknown compression method)]\\n\", err));\n            break;\n        case PK_ERR:\n        case PK_BADERR:\n            Info(slide, 1, ((char *)slide, \"\\n\\\n[return-code %d:  error in zipfile \\\n(e.g., cannot find local file header sig)]\\n\", err));\n            break;\n        case PK_MEM:\n        case PK_MEM2:\n        case PK_MEM3:\n        case PK_MEM4:\n        case PK_MEM5:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  insufficient memory]\\n\", err));\n            break;\n        case PK_NOZIP:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  zipfile not found]\\n\", err));\n            break;\n        case PK_PARAM:   /* exit(PK_PARAM); gives \"access violation\" */\n            Info(slide, 1, ((char *)slide, \"\\n\\\n[return-code %d:  bad or illegal parameters specified on command line]\\n\",\n              err));\n            break;\n        case PK_FIND:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  no files found to extract/view/etc.]\\n\",\n              err));\n            break;\n        case PK_DISK:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  disk full or other I/O error]\\n\", err));\n            break;\n        case PK_EOF:\n            Info(slide, 1, ((char *)slide, \"\\n\\\n[return-code %d:  unexpected EOF in zipfile (i.e., truncated)]\\n\", err));\n            break;\n        case IZ_CTRLC:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  you hit ctrl-C to terminate]\\n\", err));\n            break;\n        case IZ_UNSUP:\n            Info(slide, 1, ((char *)slide, \"\\n\\\n[return-code %d:  unsupported compression or encryption for all files]\\n\",\n              err));\n            break;\n        case IZ_BADPWD:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  bad decryption password for all files]\\n\",\n              err));\n            break;\n#ifdef DO_SAFECHECK_2GB\n        case IZ_ERRBF:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  big-file archive, small-file program]\\n\",\n              err));\n            break;\n#endif /* DO_SAFECHECK_2GB */\n        default:\n            Info(slide, 1, ((char *)slide,\n              \"\\n[return-code %d:  unknown return-code (screw-up)]\\n\", err));\n            break;\n    }\n#endif /* RETURN_CODES */\n\n/*---------------------------------------------------------------------------\n *  Return an intelligent status/severity level:\n *\n *  2007-01-29 SMS.\n *\n *  VMS Status Code Summary  (See STSDEF.H for details.)\n *\n *      Bits:   31:28    27:16     15:3     2 1 0\n *      Field:  Control  Facility  Message  Severity\n *                                          -----\n *                                          0 0 0  0    Warning\n *                                          0 0 1  1    Success\n *                                          0 1 0  2    Error\n *                                          0 1 1  3    Information\n *                                          1 0 0  4    Severe (fatal) error\n *\n *  In the Control field, bits 31:29 are reserved.  Bit 28 inhibits\n *  printing the message.  In the Facility field, bit 27 means\n *  customer-defined (not HP-assigned, like us).  In the Message field,\n *  bit 15 means facility-specific (which our messages are).\n *\n *  Note that the C library translates exit(0) to a $STATUS value of 1\n *  (i.e., exit is both silent and has a $SEVERITY of \"success\").\n *\n *  Previous versions of Info-ZIP programs used a generic (\"chosen (by\n *  experimentation)\") Control+Facility code of 0x7FFF, which included\n *  some reserved control bits, the inhibit-printing bit, and the\n *  customer-defined bit.\n *\n *  HP has now assigned official Facility names and corresponding\n *  Facility codes for the Info-ZIP products:\n *\n *      Facility Name    Facility Code\n *      IZ_UNZIP         1954 = 0x7A2\n *      IZ_ZIP           1955 = 0x7A3\n *\n *  Now, unless the CTL_FAC_IZ_UZP macro is defined at build-time, we\n *  will use the official Facility code.\n *\n  ---------------------------------------------------------------------------*/\n\n/* Official HP-assigned Info-ZIP UnZip Facility code. */\n#define FAC_IZ_UZP 1954   /* 0x7A2 */\n\n#ifndef CTL_FAC_IZ_UZP\n   /*\n    * Default is inhibit-printing with the official Facility code.\n    */\n#  define CTL_FAC_IZ_UZP ((0x1 << 12) | FAC_IZ_UZP)\n#  define MSG_FAC_SPEC 0x8000   /* Facility-specific code. */\n#else /* CTL_FAC_IZ_UZP */\n   /* Use the user-supplied Control+Facility code for err or warn. */\n#  ifndef MSG_FAC_SPEC          /* Old default is not Facility-specific. */\n#    define MSG_FAC_SPEC 0x0    /* Facility-specific code.  Or 0x8000. */\n#  endif /* !MSG_FAC_SPEC */\n#endif /* ?CTL_FAC_IZ_ZIP */\n#define VMS_UZ_FAC_BITS       ((CTL_FAC_IZ_UZP << 16) | MSG_FAC_SPEC)\n\n    severity = (err == PK_WARN) ? 0 :                           /* warn  */\n               (err == PK_ERR ||                                /* error */\n                (err >= PK_NOZIP && err <= PK_FIND) ||          /*  ...  */\n                (err >= IZ_CTRLC && err <= IZ_BADPWD)) ? 2 :    /*  ...  */\n               4;                                               /* fatal */\n\n    exit(                                           /* $SEVERITY:            */\n         (err == PK_COOL) ? SS$_NORMAL :            /* success               */\n         (VMS_UZ_FAC_BITS | (err << 4) | severity)  /* warning, error, fatal */\n        );\n\n} /* end function return_VMS() */\n\n\n#ifdef MORE\nstatic int scrnlines = -1;\nstatic int scrncolumns = -1;\nstatic int scrnwrap = -1;\n\n\nstatic int getscreeninfo(int *tt_rows, int *tt_cols, int *tt_wrap)\n{\n    /*\n     * For VMS v5.x:\n     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,\n     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6\n     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,\n     *     System Services Reference Manual, pp. sys-23, sys-379\n     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,\n     *     Intro to System Routines, sec. 2.9.2\n     * GRR, 15 Aug 91 / SPC, 07 Aug 1995, 14 Nov 1999\n     */\n\n#ifndef OUTDEVICE_NAME\n#define OUTDEVICE_NAME  \"SYS$OUTPUT\"\n#endif\n\n    static ZCONST struct dsc$descriptor_s OutDevDesc =\n        {(sizeof(OUTDEVICE_NAME) - 1), DSC$K_DTYPE_T, DSC$K_CLASS_S,\n         OUTDEVICE_NAME};\n     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */\n\n    short  OutDevChan, iosb[4];\n    long   status;\n    struct tt_characts\n    {\n        uch class, type;\n        ush pagewidth;\n        union {\n            struct {\n                uch ttcharsbits[3];\n                uch pagelength;\n            } ttdef_bits;\n            unsigned ttcharflags;\n        } ttdef_area;\n    }      ttmode;              /* total length = 8 bytes */\n\n\n    /* assign a channel to standard output */\n    status = sys$assign(&OutDevDesc, &OutDevChan, 0, 0);\n    if (OK(status))\n    {\n        /* use sys$qiow and the IO$_SENSEMODE function to determine\n         * the current tty status.\n         */\n        status = sys$qiow(0, OutDevChan, IO$_SENSEMODE, &iosb, 0, 0,\n                          &ttmode, sizeof(ttmode), 0, 0, 0, 0);\n        /* deassign the output channel by way of clean-up */\n        (void) sys$dassgn(OutDevChan);\n    }\n\n    if ( OK(status) && OK(status = iosb[0]) ) {\n        if (tt_rows != NULL)\n            *tt_rows = ( (ttmode.ttdef_area.ttdef_bits.pagelength >= 5)\n                        ? (int) (ttmode.ttdef_area.ttdef_bits.pagelength)\n                                                        /* TT device value */\n                        : (24) );                       /* VT 100 default  */\n        if (tt_cols != NULL)\n            *tt_cols = ( (ttmode.pagewidth >= 10)\n                        ? (int) (ttmode.pagewidth)      /* TT device value */\n                        : (80) );                       /* VT 100 default  */\n        if (tt_wrap != NULL)\n            *tt_wrap = ((ttmode.ttdef_area.ttcharflags & TT$M_WRAP) != 0);\n    } else {\n        /* VT 100 defaults */\n        if (tt_rows != NULL)\n            *tt_rows = 24;\n        if (tt_cols != NULL)\n            *tt_cols = 80;\n        if (tt_wrap != NULL)\n            *tt_wrap = FALSE;\n    }\n\n    return (OK(status));\n}\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    if (scrnlines < 0 || scrncolumns < 0)\n        getscreeninfo(&scrnlines, &scrncolumns, &scrnwrap);\n    if (tt_rows != NULL) *tt_rows = scrnlines;\n    if (tt_cols != NULL) *tt_cols = scrncolumns;\n    return !(scrnlines > 0 && scrncolumns > 0);\n}\n\nint screenlinewrap()\n{\n    if (scrnwrap == -1)\n        getscreeninfo(&scrnlines, &scrncolumns, &scrnwrap);\n    return (scrnwrap);\n}\n#endif /* MORE */\n\n\n#ifndef SFX\n\n/************************/\n/*  Function version()  */\n/************************/\n\n/* 2004-11-23 SMS.\n * Changed to include the \"-x\" part of the VMS version.\n * Added the IA64 system type name.\n * Prepared for VMS versions after 9.  (We should live so long.)\n */\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#ifdef VMS_VERSION\n    char *chrp1;\n    char *chrp2;\n    char buf[40];\n    char vms_vers[16];\n    int ver_maj;\n#endif\n#ifdef __DECC_VER\n    char buf2[40];\n    int  vtyp;\n#endif\n\n#ifdef VMS_VERSION\n    /* Truncate the version string at the first (trailing) space. */\n    strncpy(vms_vers, VMS_VERSION, sizeof(vms_vers));\n    vms_vers[sizeof(vms_vers)-1] = '\\0';\n    chrp1 = strchr(vms_vers, ' ');\n    if (chrp1 != NULL)\n        *chrp1 = '\\0';\n\n    /* Determine the major version number. */\n    ver_maj = 0;\n    chrp1 = strchr(&vms_vers[1], '.');\n    for (chrp2 = &vms_vers[1];\n         chrp2 < chrp1;\n         ver_maj = ver_maj * 10 + *(chrp2++) - '0');\n#endif /* VMS_VERSION */\n\n/*  DEC C in ANSI mode does not like \"#ifdef MACRO\" inside another\n    macro when MACRO is equated to a value (by \"#define MACRO 1\").   */\n\n    len = sprintf((char *)slide, LoadFarString(CompiledWith),\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if defined(DECC) || defined(__DECC) || defined (__DECC__)\n      \"DEC C\",\n#    ifdef __DECC_VER\n      (sprintf(buf2, \" %c%d.%d-%03d\",\n               ((vtyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' :\n                (vtyp == 8 ? 'S' : 'V')),\n               __DECC_VER / 10000000,\n               (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000), buf2),\n#    else\n      \"\",\n#    endif\n#  else\n#    ifdef VAXC\n      \"VAX C\", \"\",\n#    else\n      \"unknown compiler\", \"\",\n#    endif\n#  endif\n#endif\n\n#ifdef VMS_VERSION\n#  if defined(__alpha)\n      \"OpenVMS\",\n      (sprintf(buf, \" (%s Alpha)\", vms_vers), buf),\n#  elif defined(__ia64)\n      \"OpenVMS\",\n      (sprintf(buf, \" (%s IA64)\", vms_vers), buf),\n#  else /* VAX */\n      (ver_maj >= 6) ? \"OpenVMS\" : \"VMS\",\n      (sprintf(buf, \" (%s VAX)\", vms_vers), buf),\n#  endif\n#else\n      \"VMS\",\n      \"\",\n#endif /* ?VMS_VERSION */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n\n} /* end function version() */\n\n#endif /* !SFX */\n\n\n\n#ifdef __DECC\n\n/* 2004-11-20 SMS.\n *\n *       acc_cb(), access callback function for DEC C open().\n *\n *    Set some RMS FAB/RAB items, with consideration of user-specified\n * values from (DCL) SET RMS_DEFAULT.  Items of particular interest are:\n *\n *       fab$w_deq         default extension quantity (blocks) (write).\n *       rab$b_mbc         multi-block count.\n *       rab$b_mbf         multi-buffer count (used with rah and wbh).\n *\n *    See also the OPEN* macros in VMSCFG.H.  Currently, no notice is\n * taken of the caller-ID value, but options could be set differently\n * for read versus write access.  (I assume that specifying fab$w_deq,\n * for example, for a read-only file has no ill effects.)\n */\n\n/* Global storage. */\n\nint openr_id = OPENR_ID;        /* Callback id storage, read. */\n\n/* acc_cb() */\n\nint acc_cb(int *id_arg, struct FAB *fab, struct RAB *rab)\n{\n    int sts;\n\n    /* Get process RMS_DEFAULT values, if not already done. */\n    if (rms_defaults_known == 0)\n    {\n        get_rms_defaults();\n    }\n\n    /* If RMS_DEFAULT (and adjusted active) values are available, then set\n     * the FAB/RAB parameters.  If RMS_DEFAULT values are not available,\n     * suffer with the default parameters.\n     */\n    if (rms_defaults_known > 0)\n    {\n        /* Set the FAB/RAB parameters accordingly. */\n        fab-> fab$w_deq = rms_ext_active;\n        rab-> rab$b_mbc = rms_mbc_active;\n        rab-> rab$b_mbf = rms_mbf_active;\n\n        /* Truncate at EOF on close, as we'll probably over-extend. */\n        fab-> fab$v_tef = 1;\n\n        /* If using multiple buffers, enable read-ahead and write-behind. */\n        if (rms_mbf_active > 1)\n        {\n            rab-> rab$v_rah = 1;\n            rab-> rab$v_wbh = 1;\n        }\n\n        if (DIAG_FLAG)\n        {\n            fprintf(stderr,\n              \"Open callback.  ID = %d, deq = %6d, mbc = %3d, mbf = %3d.\\n\",\n              *id_arg, fab-> fab$w_deq, rab-> rab$b_mbc, rab-> rab$b_mbf);\n        }\n    }\n\n    /* Declare success. */\n    return 0;\n}\n\n\n\n/*\n * 2004-09-19 SMS.\n *\n *----------------------------------------------------------------------\n *\n *       decc_init()\n *\n *    On non-VAX systems, uses LIB$INITIALIZE to set a collection of C\n *    RTL features without using the DECC$* logical name method.\n *\n *----------------------------------------------------------------------\n */\n\n#ifdef __CRTL_VER\n#if !defined(__VAX) && (__CRTL_VER >= 70301000)\n\n#include <unixlib.h>\n\n/*--------------------------------------------------------------------*/\n\n/* Global storage. */\n\n/*    Flag to sense if decc_init() was called. */\n\nstatic int decc_init_done = -1;\n\n/*--------------------------------------------------------------------*/\n\n/* decc_init()\n\n      Uses LIB$INITIALIZE to set a collection of C RTL features without\n      requiring the user to define the corresponding logical names.\n*/\n\n/* Structure to hold a DECC$* feature name and its desired value. */\n\ntypedef struct\n{\n   char *name;\n   int value;\n} decc_feat_t;\n\n/* Array of DECC$* feature names and their desired values. */\n\ndecc_feat_t decc_feat_array[] = {\n\n   /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */\n { \"DECC$ARGV_PARSE_STYLE\", 1 },\n\n   /* Preserve case for file names on ODS5 disks. */\n { \"DECC$EFS_CASE_PRESERVE\", 1 },\n\n   /* Enable multiple dots (and most characters) in ODS5 file names,\n      while preserving VMS-ness of \";version\". */\n { \"DECC$EFS_CHARSET\", 1 },\n\n   /* List terminator. */\n { (char *)NULL, 0 } };\n\n\n/* LIB$INITIALIZE initialization function. */\n\nstatic void decc_init(void)\n{\n    int feat_index;\n    int feat_value;\n    int feat_value_max;\n    int feat_value_min;\n    int i;\n    int sts;\n\n    /* Set the global flag to indicate that LIB$INITIALIZE worked. */\n\n    decc_init_done = 1;\n\n    /* Loop through all items in the decc_feat_array[]. */\n\n    for (i = 0; decc_feat_array[i].name != NULL; i++)\n    {\n        /* Get the feature index. */\n        feat_index = decc$feature_get_index(decc_feat_array[i].name);\n        if (feat_index >= 0)\n        {\n            /* Valid item.  Collect its properties. */\n            feat_value = decc$feature_get_value(feat_index, 1);\n            feat_value_min = decc$feature_get_value(feat_index, 2);\n            feat_value_max = decc$feature_get_value(feat_index, 3);\n\n            if ((decc_feat_array[i].value >= feat_value_min) &&\n                (decc_feat_array[i].value <= feat_value_max))\n            {\n                /* Valid value.  Set it if necessary. */\n                if (feat_value != decc_feat_array[i].value)\n                {\n                    sts = decc$feature_set_value(\n                              feat_index,\n                              1,\n                              decc_feat_array[i].value);\n                }\n            }\n            else\n            {\n                /* Invalid DECC feature value. */\n                printf(\" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\\n\",\n                  feat_value,\n                  feat_value_min, decc_feat_array[i].name, feat_value_max);\n            }\n        }\n        else\n        {\n            /* Invalid DECC feature name. */\n            printf(\" UNKNOWN DECC FEATURE: %s.\\n\", decc_feat_array[i].name);\n        }\n    }\n}\n\n/* Get \"decc_init()\" into a valid, loaded LIB$INITIALIZE PSECT. */\n\n#pragma nostandard\n\n/* Establish the LIB$INITIALIZE PSECT, with proper alignment and\n   attributes.\n*/\nglobaldef {\"LIB$INITIALIZ\"} readonly _align (LONGWORD)\n   int spare[8] = { 0 };\nglobaldef {\"LIB$INITIALIZE\"} readonly _align (LONGWORD)\n   void (*x_decc_init)() = decc_init;\n\n/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */\n\n#pragma extern_model save\n/* The declaration for LIB$INITIALIZE() is missing in the VMS system header\n   files.  Addionally, the lowercase name \"lib$initialize\" is defined as a\n   macro, so that this system routine can be reference in code using the\n   traditional C-style lowercase convention of function names for readability.\n   (VMS system functions declared in the VMS system headers are defined in a\n   similar way to allow using lowercase names within the C code, whereas the\n   \"externally\" visible names in the created object files are uppercase.)\n */\n#ifndef lib$initialize\n#  define lib$initialize LIB$INITIALIZE\n#endif\nint lib$initialize(void);\n#pragma extern_model strict_refdef\nint dmy_lib$initialize = (int)lib$initialize;\n#pragma extern_model restore\n\n#pragma standard\n\n#endif /* !defined(__VAX) && (__CRTL_VER >= 70301000) */\n#endif /* __CRTL_VER */\n#endif /* __DECC */\n\n#endif /* VMS */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/vms.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vms.h\n\n  Generic VMS header file for Info-ZIP's Zip and UnZip.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vms_h\n#define __vms_h 1\n\n#ifndef __DESCRIP_LOADED\n#include <descrip.h>\n#endif\n#ifndef __STARLET_LOADED\n/* Workaround for broken header files of older DECC distributions\n * that are incompatible with the /NAMES=AS_IS qualifier. */\n#define sys$assign SYS$ASSIGN\n#define sys$bintim SYS$BINTIM\n#define sys$close SYS$CLOSE\n#define sys$connect SYS$CONNECT\n#define sys$create SYS$CREATE\n#define sys$dassgn SYS$DASSGN\n#define sys$extend SYS$EXTEND\n#define sys$getjpiw SYS$GETJPIW\n#define sys$numtim SYS$NUMTIM\n#define sys$open SYS$OPEN\n#define sys$parse SYS$PARSE\n#define sys$put SYS$PUT\n#define sys$qio SYS$QIO\n#define sys$qiow SYS$QIOW\n#define sys$read SYS$READ\n#define sys$rewind SYS$REWIND\n#define sys$search SYS$SEARCH\n#define sys$setdfprot SYS$SETDFPROT\n#define sys$synch SYS$SYNCH\n#define sys$wait SYS$WAIT\n#define sys$write SYS$WRITE\n#include <starlet.h>\n#endif /* ndef __STARLET_LOADED */\n#ifndef __SYIDEF_LOADED\n#include <syidef.h>\n#endif\n#ifndef __ATRDEF_LOADED\n#include <atrdef.h>\n#endif\n#ifndef __FIBDEF_LOADED\n#include <fibdef.h>\n#endif\n#ifndef __IODEF_LOADED\n#include <iodef.h>\n#endif\n#if !defined(_RMS_H) && !defined(__RMS_LOADED)\n#include <rms.h>\n#endif\n\n#define ERR(s) !((s) & 1)       /* VMS system error */\n\n#ifndef SYI$_VERSION\n#define SYI$_VERSION 4096       /* VMS 5.4 definition */\n#endif\n\n/*\n *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions\n *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third\n *  party compilers which do not support `variant_union' define preprocessor\n *  symbols to `hide' the \"intermediate union/struct\" names from the\n *  programmer's API.\n *  We check the presence of these defines and for DEC's FIBDEF.H defining\n *  __union as variant_union to make sure we access the structure correctly.\n */\n#define variant_union 1\n#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))\n#  define FIB$W_DID     fib$w_did\n#  define FIB$W_FID     fib$w_fid\n#  define FIB$L_ACCTL   fib$l_acctl\n#  define FIB$W_EXCTL   fib$w_exctl\n#  define FIB$W_NMCTL   fib$w_nmctl\n#else\n#  define FIB$W_DID     fib$r_did_overlay.fib$w_did\n#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid\n#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl\n#  define FIB$W_EXCTL   fib$r_exctl_overlay.fib$w_exctl\n#  define FIB$W_NMCTL   fib$r_nmctl_overlay.fib$w_nmctl\n#endif\n#undef variant_union\n\n\n/* 2005-02-10 SMS.  Copied NAM[L] macros here from Zip. */\n\n/* Define macros for use with either NAM or NAML. */\n\n#ifdef NAML$C_MAXRSS            /* NAML is available (ODS5 support...) */\n\n#  ifndef NAM_MAXRSS            /* May have been defined before. */\n#    define NAM_MAXRSS NAML$C_MAXRSS\n#  endif\n\n#  define NAM_STRUCT NAML\n\n#  define FAB_OR_NAML(fab, nam) (nam)\n#  define FAB_OR_NAML_DNA naml$l_long_defname\n#  define FAB_OR_NAML_DNS naml$l_long_defname_size\n#  define FAB_OR_NAML_FNA naml$l_long_filename\n#  define FAB_OR_NAML_FNS naml$l_long_filename_size\n\n#  define CC_RMS_NAM cc$rms_naml\n#  define FAB_NAM fab$l_naml\n\n#  define NAM_ESA naml$l_long_expand\n#  define NAM_ESL naml$l_long_expand_size\n#  define NAM_ESS naml$l_long_expand_alloc\n#  define NAM_RSA naml$l_long_result\n#  define NAM_RSL naml$l_long_result_size\n#  define NAM_RSS naml$l_long_result_alloc\n#  define NAM_DID naml$w_did\n#  define NAM_DVI naml$t_dvi\n#  define NAM_FID naml$w_fid\n#  define NAM_FNB naml$l_fnb\n#  define NAM_NOP naml$b_nop\n#  define NAM_M_SYNCHK NAML$M_SYNCHK\n#  define NAM_B_DEV naml$l_long_dev_size\n#  define NAM_L_DEV naml$l_long_dev\n#  define NAM_B_DIR naml$l_long_dir_size\n#  define NAM_L_DIR naml$l_long_dir\n#  define NAM_B_NAME naml$l_long_name_size\n#  define NAM_L_NAME naml$l_long_name\n#  define NAM_B_TYPE naml$l_long_type_size\n#  define NAM_L_TYPE naml$l_long_type\n#  define NAM_B_VER naml$l_long_ver_size\n#  define NAM_L_VER naml$l_long_ver\n\n#else /* !NAML$C_MAXRSS */      /* NAML is not available.  Use NAM. */\n\n#  ifndef NAM_MAXRSS            /* May have been defined before. */\n#    define NAM_MAXRSS NAM$C_MAXRSS\n#  endif\n\n#  define NAM_STRUCT NAM\n\n#  define FAB_OR_NAML(fab, nam) (fab)\n#  define FAB_OR_NAML_DNA fab$l_dna\n#  define FAB_OR_NAML_DNS fab$b_dns\n#  define FAB_OR_NAML_FNA fab$l_fna\n#  define FAB_OR_NAML_FNS fab$b_fns\n\n#  define CC_RMS_NAM cc$rms_nam\n#  define FAB_NAM fab$l_nam\n#  define NAM_ESA nam$l_esa\n#  define NAM_ESL nam$b_esl\n#  define NAM_ESS nam$b_ess\n#  define NAM_RSA nam$l_rsa\n#  define NAM_RSL nam$b_rsl\n#  define NAM_RSS nam$b_rss\n#  define NAM_DID nam$w_did\n#  define NAM_DVI nam$t_dvi\n#  define NAM_FID nam$w_fid\n#  define NAM_FNB nam$l_fnb\n#  define NAM_NOP nam$b_nop\n#  define NAM_M_SYNCHK NAM$M_SYNCHK\n#  define NAM_B_DEV nam$b_dev\n#  define NAM_L_DEV nam$l_dev\n#  define NAM_B_DIR nam$b_dir\n#  define NAM_L_DIR nam$l_dir\n#  define NAM_B_NAME nam$b_name\n#  define NAM_L_NAME nam$l_name\n#  define NAM_B_TYPE nam$b_type\n#  define NAM_L_TYPE nam$l_type\n#  define NAM_B_VER nam$b_ver\n#  define NAM_L_VER nam$l_ver\n\n#endif /* ?NAML$C_MAXRSS */\n\n\nstruct EB_header    /* Common header of extra block */\n{   ush tag;\n    ush size;\n    uch data[1];\n};\n\n#ifndef EB_HEADSIZE\n#  define EB_HEADSIZE 4\n#endif\n\n/*------ Old style Info-ZIP extra field definitions -----*/\n\n#if (!defined(VAXC) && !defined(_RMS_H) && !defined(__RMS_LOADED))\n\nstruct XAB {                    /* This definition may be skipped */\n    unsigned char xab$b_cod;\n    unsigned char xab$b_bln;\n    short int xabdef$$_fill_1;\n    char *xab$l_nxt;\n};\n\n#endif /* !VAXC && !_RMS_H && !__RMS_LOADED */\n\n#ifndef EB_IZVMS_BCMASK\n#  define EB_IZVMS_BCMASK   07  /* 3 bits for compression type */\n#endif\n#ifndef EB_IZVMS_BCSTOR\n#  define EB_IZVMS_BCSTOR   0   /*  Stored */\n#endif\n#ifndef EB_IZVMS_BC00\n#  define EB_IZVMS_BC00     1   /*  0byte -> 0bit compression */\n#endif\n#ifndef EB_IZVMS_BCDEFL\n#  define EB_IZVMS_BCDEFL   2   /*  Deflated */\n#endif\n\n/*\n *  Extra record format\n *  ===================\n *  signature       (2 bytes)   = 'I','M'\n *  size            (2 bytes)\n *  block signature (4 bytes)\n *  flags           (2 bytes)\n *  uncomprssed size(2 bytes)\n *  reserved        (4 bytes)\n *  data            ((size-12) bytes)\n *  ....\n */\n\nstruct IZ_block                 /* Extra field block header structure */\n{\n    ush sig;\n    ush size;\n    ulg bid;\n    ush flags;\n    ush length;\n    ulg reserved;\n    uch body[1];                /* The actual size is unknown */\n};\n\n/*\n *   Extra field signature and block signatures\n */\n\n#define IZ_SIGNATURE \"IM\"\n#define FABSIG  \"VFAB\"\n#define XALLSIG \"VALL\"\n#define XFHCSIG \"VFHC\"\n#define XDATSIG \"VDAT\"\n#define XRDTSIG \"VRDT\"\n#define XPROSIG \"VPRO\"\n#define XKEYSIG \"VKEY\"\n#define XNAMSIG \"VNAM\"\n#define VERSIG  \"VMSV\"\n\n/*\n *   Block sizes\n */\n\n#define FABL    (cc$rms_fab.fab$b_bln)\n#define RABL    (cc$rms_rab.rab$b_bln)\n#define XALLL   (cc$rms_xaball.xab$b_bln)\n#define XDATL   (cc$rms_xabdat.xab$b_bln)\n#define XFHCL   (cc$rms_xabfhc.xab$b_bln)\n#define XKEYL   (cc$rms_xabkey.xab$b_bln)\n#define XPROL   (cc$rms_xabpro.xab$b_bln)\n#define XRDTL   (cc$rms_xabrdt.xab$b_bln)\n#define XSUML   (cc$rms_xabsum.xab$b_bln)\n#define EXTBSL  4               /* Block signature length */\n#define RESL    8               /* Reserved 8 bytes */\n#define EXTHL   (EB_HEADSIZE+EXTBSL+RESL)\n\ntypedef unsigned char byte;\n\nstruct iosb\n{\n    ush status;\n    ush count;\n    ulg spec;\n};\n\n/*------------ PKWARE extra block definitions ----------*/\n\n/* Structure of PKWARE extra header */\n\n#ifdef VMS_ZIP\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __nostandard\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n\n#ifdef VMS_ORIGINAL_PK_LAYOUT\n/*  The original order of ATR fields in the PKZIP VMS-extra field leads\n *  to unaligned fields in the PK_info structure representing the\n *  extra field layout.  When compiled for Alpha AXP, this results in\n *  some performance (and code size) penalty.  It is not allowed to\n *  apply structure padding, since this is explicitly forbidden in\n *  the specification (APPNOTE.TXT) for the PK VMS extra field.\n */\ntypedef struct PK_info\n{\n    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];\n    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];\n    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];\n    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];\n    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];\n    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];\n    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];\n    ush tag_rn; ush len_rn;     ush  rn;\n    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];\n    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];\n    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];\n} PK_info_t;\n#else /* !VMS_ORIGINAL_PK_LAYOUT */\n/*  The Info-ZIP support for the PK VMS extra field uses a reordered\n *  field layout to achieve ``natural alignment'' of the PK_info structure\n *  members whenever possible.  This rearrangement does not violate the\n *  PK's VMS extra field specification and should not break any ``well\n *  behaving'' (PK)Unzip utility. (`Well behaving' means that (PK)Unzip\n *  should use the field tag to identify the ATR$ field rather than\n *  assuming a fixed order of ATR$ fields in the PK VMS extra field.)\n */\ntypedef struct PK_info\n{\n    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];\n    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];\n    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];\n    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];\n    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];\n    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];\n    ush tag_rn; ush len_rn;     ush  rn;\n    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];\n    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];\n    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];\n    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];\n} PK_info_t;\n#endif /* ?VMS_ORIGINAL_PK_LAYOUT */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __standard\n#endif /* __DECC || __DECCXX */\n\n#endif /* VMS_ZIP */\n\n/* PKWARE \"VMS\" tag */\n#define PK_SIGNATURE        0x000C\n\n/* Total number of attributes to be saved */\n#define VMS_ATTR_COUNT  11\n#define VMS_MAX_ATRCNT  20\n\nstruct PK_field\n{\n    ush         tag;\n    ush         size;\n    byte        value[1];\n};\n\n#define PK_FLDHDR_SIZE  4\n\nstruct PK_header\n{\n    ush tag;\n    ush size;\n    ulg crc32;\n    byte data[1];\n};\n\n#define PK_HEADER_SIZE  8\n\n#endif /* !__vms_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/vmscfg.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    OpenVMS specific configuration section (included by unzpriv.h):\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vmscfg_h   /* Prevent (unlikely) multiple inclusions. */\n#define __vmscfg_h\n\n/* Workaround for broken header files of older DECC distributions\n * that are incompatible with the /NAMES=AS_IS qualifier. */\n#define cma$tis_errno_get_addr CMA$TIS_ERRNO_GET_ADDR\n\n/* LARGE FILE SUPPORT - 10/6/04 EG */\n/* This needs to be set before the includes so they set the right sizes */\n\n#ifdef NO_LARGE_FILE_SUPPORT\n# ifdef LARGE_FILE_SUPPORT\n#  undef LARGE_FILE_SUPPORT\n# endif\n#endif\n\n#ifdef LARGE_FILE_SUPPORT\n\n# define _LARGEFILE             /* Define the pertinent macro. */\n\n/* LARGE_FILE_SUPPORT implies ZIP64_SUPPORT,\n   unless explicitly disabled by NO_ZIP64_SUPPORT.\n*/\n#  ifdef NO_ZIP64_SUPPORT\n#    ifdef ZIP64_SUPPORT\n#      undef ZIP64_SUPPORT\n#    endif\n#  else\n#    ifndef ZIP64_SUPPORT\n#      define ZIP64_SUPPORT\n#    endif\n#  endif\n\n#endif /* def LARGE_FILE_SUPPORT */\n\n/* 2007-02-22 SMS.\n * Enable symbolic links according to the available C RTL support,\n * unless prohibited by the user defining NO_SYMLINKS.\n */\n#if !defined(__VAX) && defined(__CRTL_VER) && __CRTL_VER >= 70301000\n#  ifndef NO_SYMLINKS\n#     define SYMLINKS\n#  endif\n#endif\n\n#ifdef SYMLINKS\n#  include <unistd.h>\n#endif\n\n#  include <types.h>                    /* GRR:  experimenting... */\n#  include <stat.h>\n#  include <time.h>                     /* the usual non-BSD time functions */\n#  include <file.h>                     /* same things as fcntl.h has */\n#  include <unixio.h>\n#  include <rms.h>\n\n/* Define maximum path length according to NAM[L] member size. */\n#  ifndef NAM_MAXRSS\n#    ifdef NAML$C_MAXRSS\n#      define NAM_MAXRSS NAML$C_MAXRSS\n#    else\n#      define NAM_MAXRSS NAM$C_MAXRSS\n#    endif\n#  endif\n\n#  define _MAX_PATH (NAM_MAXRSS+1)      /* to define FILNAMSIZ below */\n\n#  ifdef RETURN_CODES  /* VMS interprets standard PK return codes incorrectly */\n#    define RETURN(ret) return_VMS(__G__ (ret))   /* verbose version */\n#    define EXIT(ret)   return_VMS(__G__ (ret))\n#  else\n#    define RETURN      return_VMS                /* quiet version */\n#    define EXIT        return_VMS\n#  endif\n#  ifdef VMSCLI\n#    define USAGE(ret)  VMSCLI_usage(__G__ (ret))\n#  endif\n#  define DIR_BEG       '['\n#  define DIR_END       ']'\n#  define DIR_EXT       \".dir\"\n#  ifndef UZ_FNFILTER_REPLACECHAR\n     /* We use '?' instead of the single char wildcard '%' as \"unprintable\n      * charcode\" placeholder, because '%' is valid for ODS-5 names but '?'\n      * is invalid. This choice may allow easier detection of \"unprintables\"\n      * when reading the fnfilter() output.\n      */\n#    define UZ_FNFILTER_REPLACECHAR  '?'\n#  endif\n#  ifndef DATE_FORMAT\n#    define DATE_FORMAT DF_MDY\n#  endif\n#  define lenEOL        1\n#  define PutNativeEOL  *q++ = native(LF);\n#  define SCREENSIZE(ttrows, ttcols)  screensize(ttrows, ttcols)\n#  define SCREENWIDTH   80\n#  define SCREENLWRAP   screenlinewrap()\n#  if (defined(__VMS_VERSION) && !defined(VMS_VERSION))\n#    define VMS_VERSION __VMS_VERSION\n#  endif\n#  if (defined(__VMS_VER) && !defined(__CRTL_VER))\n#    define __CRTL_VER __VMS_VER\n#  endif\n#  if ((!defined(__CRTL_VER)) || (__CRTL_VER < 70000000))\n#    define NO_GMTIME           /* gmtime() of earlier VMS C RTLs is broken */\n#  else\n#    if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#      define USE_EF_UT_TIME\n#    endif\n#    if (!defined(HAVE_STRNICMP) && !defined(NO_STRNICMP))\n#      define HAVE_STRNICMP\n#      ifdef STRNICMP\n#        undef STRNICMP\n#      endif\n#      define STRNICMP  strncasecmp\n#    endif\n#  endif\n#  ifndef HAVE_STRNICMP                 /* use our private zstrnicmp() */\n#    define NO_STRNICMP                 /*  unless explicitly overridden */\n#  endif\n#  if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#    define TIMESTAMP\n#  endif\n#  define SET_DIR_ATTRIB\n#  define RESTORE_UIDGID\n   /* VMS is run on little-endian processors with 4-byte ints:\n    * enable the optimized CRC-32 code */\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    undef IZ_CRC_BE_OPTIMIZ\n#  endif\n#  if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ)\n#    define IZ_CRC_LE_OPTIMIZ\n#  endif\n#  if !defined(IZ_CRCOPTIM_UNFOLDTBL) && !defined(NO_CRC_OPTIMIZ)\n#    define IZ_CRCOPTIM_UNFOLDTBL\n#  endif\n   /* Enable \"better\" unprintable charcodes filtering in fnfilter().\n    * (On VMS, the isprint() implementation seems to detect 8-bit printable\n    * characters even for the default \"C\" locale. A previous localization\n    * setup by calling setlocale() is not neccessary.) */\n#  if (!defined(NO_WORKING_ISPRINT) && !defined(HAVE_WORKING_ISPRINT))\n#    define HAVE_WORKING_ISPRINT\n#  endif\n\n#ifdef NO_OFF_T\n  typedef long zoff_t;\n#else\n  typedef off_t zoff_t;\n#endif\n#define ZOFF_T_DEFINED\n\ntypedef struct stat z_stat;\n#define Z_STAT_DEFINED\n\n\n#ifdef __DECC\n\n    /* File open callback ID values. */\n#   define OPENR_ID 1\n\n    /* File open callback ID storage. */\n    extern int openr_id;\n\n    /* File open callback function. */\n    extern int acc_cb();\n\n    /* Option macros for open().\n     * General: Stream access\n     *\n     * Callback function (DEC C only) sets deq, mbc, mbf, rah, wbh, ...\n     */\n#   define OPNZIP_RMS_ARGS \"ctx=stm\", \"acc\", acc_cb, &openr_id\n\n#else /* !__DECC */ /* (So, GNU C, VAX C, ...)*/\n\n#   define OPNZIP_RMS_ARGS \"ctx=stm\"\n\n#endif /* ?__DECC */\n\n#endif /* !__vmscfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/vmsdefs.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vmsdefs.h\n\n  Contents of three header files from Joe\n  Meadows' FILE program.  Used by vmsmunch\n\n        06-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com\n                        Moved \"contents of three header files\" from\n                        VMSmunch.h to VMSdefs.h .\n\n        16-Sep-1995     Christian Spieler\n                        Added #pragma (no)member_alignment directives\n                        to achieve compatibility with DEC C and Alpha AXP\n\n        05-Oct-1995     Christian Spieler\n                        Revised fatdef, fchdef, fjndef to achieve closer\n                        compatibility with DEC's system include header files\n                        supplied with C version 4.0 and newer.\n\n        10-Oct-1995     Christian Spieler\n                        Use lowercase filenames for vms specific sources\n                        (VMSmunch.? -> vmsmunch.?, VMSdefs.h -> vmsdefs.h)\n\n        15-Dec-1995     Christian Spieler\n                        Removed the last \"tabs\" from the source.\n\n        24-Jun-1997     Onno van der Linden / Chr. Spieler\n                        Modifications to support the VMS port of GNU C 2.x.\n\n        27-Jul-1999     Chr. Spieler\n                        Added Info-ZIP copyright note for identification.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vmsdefs_h\n#define __vmsdefs_h 1\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __nostandard\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define __struct struct\n#define __union union\n#else\n#define __struct variant_struct\n#define __union variant_union\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#ifdef __cplusplus\n    extern \"C\" {\n#endif\n\n/*---------------------------------------------------------------------------\n    fatdef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FAT$K_LENGTH 32\n#define FAT$C_LENGTH 32\n#define FAT$S_FATDEF 32\n\nstruct fatdef {\n  __union  {\n    unsigned char fat$b_rtype;          /* record type                      */\n    __struct  {\n      unsigned fat$v_rtype : 4;         /* record type subfield             */\n      unsigned fat$v_fileorg : 4;       /* file organization                */\n    } fat$r_rtype_bits;\n  } fat$r_rtype_overlay;\n# define FAT$S_RTYPE 4\n# define FAT$V_RTYPE 0\n#   define FAT$C_UNDEFINED 0\n#   define FAT$C_FIXED 1\n#   define FAT$C_VARIABLE 2\n#   define FAT$C_VFC 3\n#   define FAT$C_STREAM 4\n#   define FAT$C_STREAMLF 5\n#   define FAT$C_STREAMCR 6\n# define FAT$S_FILEORG 4\n# define FAT$V_FILEORG 4\n#   define FAT$C_SEQUENTIAL 0\n#   define FAT$C_RELATIVE 1\n#   define FAT$C_INDEXED 2\n#   define FAT$C_DIRECT 3\n  __union  {\n    unsigned char fat$b_rattrib;        /* record attributes                */\n    __struct  {\n      unsigned fat$v_fortrancc : 1;\n      unsigned fat$v_impliedcc : 1;\n      unsigned fat$v_printcc : 1;\n      unsigned fat$v_nospan : 1;\n      unsigned fat$v_msbrcw : 1;\n    } fat$r_rattrib_bits;\n  } fat$r_rattrib_overlay;\n#   define FAT$V_FORTRANCC 0\n#   define FAT$M_FORTRANCC 1\n#   define FAT$V_IMPLIEDCC 1\n#   define FAT$M_IMPLIEDCC 2\n#   define FAT$V_PRINTCC 2\n#   define FAT$M_PRINTCC 4\n#   define FAT$V_NOSPAN 3\n#   define FAT$M_NOSPAN 8\n#   define FAT$V_MSBRCW 4\n#   define FAT$M_MSBRCW 16\n  unsigned short int fat$w_rsize;       /* record size in bytes             */\n  __union\n  {\n    unsigned long int fat$l_hiblk;      /* highest allocated VBN            */\n    __struct\n    {\n      unsigned short int fat$w_hiblkh;  /* high order word                  */\n      unsigned short int fat$w_hiblkl;  /* low order word                   */\n    } fat$r_hiblk_fields;\n  } fat$r_hiblk_overlay;\n  __union\n  {\n    unsigned long int fat$l_efblk;      /* end of file VBN                  */\n    __struct\n    {\n      unsigned short int fat$w_efblkh;  /* high order word                  */\n      unsigned short int fat$w_efblkl;  /* low order word                   */\n    } fat$r_efblk_fields;\n  } fat$r_efblk_overlay;\n  unsigned short int fat$w_ffbyte;      /* first free byte in EFBLK         */\n  unsigned char fat$b_bktsize;          /* bucket size in blocks            */\n  unsigned char fat$b_vfcsize;          /* # of control bytes in VFC record */\n  unsigned short int fat$w_maxrec;      /* maximum record size in bytes     */\n  unsigned short int fat$w_defext;      /* default extend quantity          */\n  unsigned short int fat$w_gbc;         /* global buffer count              */\n  char fat$fill[8];\n  unsigned short int fat$w_versions;\n};\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define fat$b_rtype fat$r_rtype_overlay.fat$b_rtype\n#define fat$v_rtype fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_rtype\n#define fat$v_fileorg fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_fileorg\n#define fat$b_rattrib fat$r_rattrib_overlay.fat$b_rattrib\n#define fat$v_fortrancc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_fortrancc\n#define fat$v_impliedcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_impliedcc\n#define fat$v_printcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_printcc\n#define fat$v_nospan fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_nospan\n#define fat$v_msbrcw fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_msbrcw\n#define fat$l_hiblk fat$r_hiblk_overlay.fat$l_hiblk\n#define fat$w_hiblkh fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkh\n#define fat$w_hiblkl fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkl\n#define fat$l_efblk fat$r_efblk_overlay.fat$l_efblk\n#define fat$w_efblkh fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkh\n#define fat$w_efblkl fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkl\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#define __FATDEF_LOADED 1       /* prevent inclusion of DECC's fatdef.h */\n\n/*---------------------------------------------------------------------------\n    fchdef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FCH$V_BADACL 0x00B\n#define FCH$M_BADACL (1 << FCH$V_BADACL)\n#define FCH$V_BADBLOCK 0x00E\n#define FCH$M_BADBLOCK (1 << FCH$V_BADBLOCK)\n#define FCH$V_CONTIG 0x007\n#define FCH$M_CONTIG (1 << FCH$V_CONTIG)\n#define FCH$V_CONTIGB 0x005\n#define FCH$M_CONTIGB (1 << FCH$V_CONTIGB)\n#define FCH$V_DIRECTORY 0x00D\n#define FCH$M_DIRECTORY (1 << FCH$V_DIRECTORY)\n#define FCH$V_ERASE 0x011\n#define FCH$M_ERASE (1 << FCH$V_ERASE)\n#define FCH$V_LOCKED 0x006\n#define FCH$M_LOCKED (1 << FCH$V_LOCKED)\n#define FCH$V_MARKDEL 0x00F\n#define FCH$M_MARKDEL (1 << FCH$V_MARKDEL)\n#define FCH$V_NOBACKUP 0x001\n#define FCH$M_NOBACKUP (1 << FCH$V_NOBACKUP)\n#define FCH$V_NOCHARGE 0x010\n#define FCH$M_NOCHARGE (1 << FCH$V_NOCHARGE)\n#define FCH$V_READCHECK 0x003\n#define FCH$M_READCHECK (1 << FCH$V_READCHECK)\n#define FCH$V_SPOOL 0x00C\n#define FCH$M_SPOOL (1 << FCH$V_SPOOL)\n#define FCH$V_WRITCHECK 0x004\n#define FCH$M_WRITCHECK (1 << FCH$V_WRITCHECK)\n#define FCH$V_WRITEBACK 0x002\n#define FCH$M_WRITEBACK (1 << FCH$V_WRITEBACK)\n\nstruct fchdef  {\n  __union  {\n    int fch$$_fill_1;\n    __struct  {\n      unsigned fch$$_fill_31 : 8;\n      unsigned fch$v_vcc_state : 3;    /* VCC state bits              */\n      unsigned fch$$_fill_32 : 7;\n      unsigned fch$$_alm_state : 2;\n      unsigned fch$v_associated : 1;   /* ISO 9660 Associated file    */\n      unsigned fch$v_existence : 1;    /* ISO 9660 Existence file     */\n      unsigned fch$v_fill_6 : 2;\n    } fch$r_fill_1_chunks;\n    __struct  {\n      unsigned fch$v_wascontig : 1;\n      unsigned fch$v_nobackup : 1 ;\n      unsigned fch$v_writeback : 1;\n      unsigned fch$v_readcheck : 1;\n      unsigned fch$v_writcheck : 1;\n      unsigned fch$v_contigb : 1;\n      unsigned fch$v_locked : 1;\n      unsigned fch$v_contig : 1;\n      unsigned fch$$_fill_3 : 3;\n      unsigned fch$v_badacl : 1;\n      unsigned fch$v_spool : 1;\n      unsigned fch$v_directory : 1;\n      unsigned fch$v_badblock : 1;\n      unsigned fch$v_markdel : 1;\n      unsigned fch$v_nocharge : 1;\n      unsigned fch$v_erase : 1;\n      unsigned fch$$_fill_4 : 1;\n      unsigned fch$v_shelved : 1;\n      unsigned fch$v_scratch : 1;\n      unsigned fch$v_nomove : 1;\n      unsigned fch$v_noshelvable : 1;\n    } fch$r_fill_1_bits;\n  } fch$r_fch_union;\n};\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define fch$v_vcc_state fch$r_fch_union.fch$r_fill_1_chunks.fch$v_vcc_state\n#define fch$v_associated fch$r_fch_union.fch$r_fill_1_chunks.fch$v_associated\n#define fch$v_existence fch$r_fch_union.fch$r_fill_1_chunks.fch$v_existence\n#define fch$v_wascontig fch$r_fch_union.fch$r_fill_1_bits.fch$v_wascontig\n#define fch$v_nobackup fch$r_fch_union.fch$r_fill_1_bits.fch$v_nobackup\n#define fch$v_writeback fch$r_fch_union.fch$r_fill_1_bits.fch$v_writeback\n#define fch$v_readcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_readcheck\n#define fch$v_writcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_writcheck\n#define fch$v_contigb fch$r_fch_union.fch$r_fill_1_bits.fch$v_contigb\n#define fch$v_locked fch$r_fch_union.fch$r_fill_1_bits.fch$v_locked\n#define fch$v_contig fch$r_fch_union.fch$r_fill_1_bits.fch$v_contig\n#define fch$v_badacl fch$r_fch_union.fch$r_fill_1_bits.fch$v_badacl\n#define fch$v_spool fch$r_fch_union.fch$r_fill_1_bits.fch$v_spool\n#define fch$v_directory fch$r_fch_union.fch$r_fill_1_bits.fch$v_directory\n#define fch$v_badblock fch$r_fch_union.fch$r_fill_1_bits.fch$v_badblock\n#define fch$v_markdel fch$r_fch_union.fch$r_fill_1_bits.fch$v_markdel\n#define fch$v_nocharge fch$r_fch_union.fch$r_fill_1_bits.fch$v_nocharge\n#define fch$v_erase fch$r_fch_union.fch$r_fill_1_bits.fch$v_erase\n#define fch$v_shelved fch$r_fch_union.fch$r_fill_1_bits.fch$v_shelved\n#define fch$v_scratch fch$r_fch_union.fch$r_fill_1_bits.fch$v_scratch\n#define fch$v_nomove fch$r_fch_union.fch$r_fill_1_bits.fch$v_nomove\n#define fch$v_noshelvable fch$r_fch_union.fch$r_fill_1_bits.fch$v_noshelvable\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#define __FCHDEF_LOADED 1       /* prevent inclusion of DECC's fchdef.h */\n\n/*---------------------------------------------------------------------------\n    fjndef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FJN$M_ONLY_RU 1\n#define FJN$M_RUJNL 2\n#define FJN$M_BIJNL 4\n#define FJN$M_AIJNL 8\n#define FJN$M_ATJNL 16\n#define FJN$M_NEVER_RU 32\n#define FJN$M_JOURNAL_FILE 64\n#define FJN$S_FJNDEF 1\nstruct fjndef  {\n  unsigned fjn$v_only_ru : 1;\n  unsigned fjn$v_rujnl : 1;\n  unsigned fjn$v_bijnl : 1;\n  unsigned fjn$v_aijnl : 1;\n  unsigned fjn$v_atjnl : 1;\n  unsigned fjn$v_never_ru : 1;\n  unsigned fjn$v_journal_file : 1;\n  unsigned fjn$v_fill_7 : 1;\n} ;\n\n#define __FJNDEF_LOADED 1       /* prevent inclusion of DECC's fjndef.h */\n\n/*---------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\n    }\n#endif\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __standard\n#endif /* __DECC || __DECCXX */\n\n#endif /* !__vmsdefs_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/vms/zlib.h",
    "content": "/* 2008-07-26 SMS.\n * VMS-specific ZLIB.H jacket header file.\n *\n * The logical name INCL_ZLIB must point to the ZLIB source directory.\n */\n\n#include \"INCL_ZLIB:ZLIB.H\"\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Contents",
    "content": "Contents of the \"win32\" sub-archive for UnZip 6.0 and later:\n\n  Contents      this file\n  Makefile      makefile for UnZip using MS Visual C++\n  Makefile.bc   makefile for UnZip using Borland C++\n  Makefile.dj   makefile for UnZip using djgpp v2.x with rsxntdj 1.31\n  Makefile.emx  makefile for UnZip using emx+gcc 0.9c with RSXNT 1.4 (+)\n  Makefile.gcc  makefile for UnZip using native Win32 gcc ports (Cygwin, MinGW)\n  Makefile.lcc  makefile for UnZip using free LCC-Win32 compiler\n  Makefile.wat  makefile for UnZip using Watcom C/C++\n  crc_i386.asm  32-bit Intel-assembler version of CRC routine\n  crc_i386.c    ditto, for MS[V]C with no MASM only\n  crc_lcc.asm   ditto, adapted for LCC-Win32 assembler syntax\n  nt.c          WinNT-specific support routines (ACLs/security descriptors)\n  nt.h          WinNT-specific support header\n  rsxntwin.h    supplement header for RSXNT, fills holes in their <windows.h>\n  w32cfg.h      Win32-specific configuration, included by unzpriv.h\n  win32.c       Win32-specific support routines\n  win32i64.c\n  winapp.rc     resource file for regular console-mode UnZip application\n  vc6/          directory containing Visual C++ 6.0 project files\n    funzip.dsp    MSVC++ 6.0 project file for fUnZip command-line tool\n    unzip.dsp     MSVC++ 6.0 project file for UnZip command-line main program\n    unzipsfx.dsp  MSVC++ 6.0 project file for UnZipSFX console mode stub\n    unzipbz2.dsp  MSVC++ 6.0 project file for UnZip with bzip2 support\n    bz2lib.dsp    MSVC++ 6.0 project file for bz2lib (de)compression library\n    unzip.dsw     MSVC++ 6.0 workspace file for all UnZip command line tools\n  vc8/          directory containing Visual C++ 2005 (8.0) project files\n    funzip.vcproj   MSVC++ 8.0 project file for fUnZip command-line tool\n    unzip.vcproj    MSVC++ 8.0 project file for UnZip command-line main program\n    unzipsfx.vcproj MSVC++ 8.0 project file for UnZipSFX console mode stub\n    unzipbz2.vcproj MSVC++ 8.0 project file for UnZip with bzip2 support\n    bz2lib.vcproj   MSVC++ 8.0 project file for bz2lib (de)compression library\n    unzip.sln       MSVC++ 8.0 workspace file for all UnZip command line tools\n\ncrc_i386.c has been tested with MSVC and can be selected through the MSVC\nmakefile.  It is provided for those who may have MSVC but no assembler.\nNote that some C compilers on Pentium-class machines have been reported\nto emit faster code from the plain C sources (crc32.c) than the assembler\nroutines provide.  This has not been tested lately, however.\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.bc",
    "content": "# Makefile for UnZip(SFX) and fUnZip for Borland C++ for Windows 9x/NT\n# Version: 6.0 and later\n# Alvin Koh, Jim Knoble, Christian Spieler, E-Yen Tan, Cosmin Truta, etc.\n#\n# Tested with Borland C++ 5.5 (may work with older C++Builder 3.0, too)\n#\n# Last revised: 07 Sep 2008 (Christian Spieler)\n#\n#\n\n#    Optional nonstandard preprocessor flags (as -DCHECK_EOF or -DDOS_WILD)\n#    should be added to the environment via \"set LOCAL_UNZIP=-DFOO\" or added\n#    to the declaration of LOC here:\nLOC = $(LOCAL_UNZIP)\n\n# Type for CPU required: 3: 80386, 4: 80486, 5: Pentium,\n#                        6: Pentium Pro, Pentium II, etc.\n!ifndef CPU_TYP\nCPU_TYP = 6\n!endif\n\n# (De)Select inclusion of optimized assembler CRC32 routine:\n!ifdef NOASM\nUSE_ASMCRC=0\n!else\n!ifdef USEASM\nUSE_ASMCRC=1\n!endif\n!endif\n\n# Specify USEMASM=1 or USETASM=1 in case you have one of these x86 assemblers\n# to use the assembler instead of the inline ASM C code.\n#USEMASM=1\n#USETASM=1\n# For the Turbo Assembler, you may choose between the (old) 16-bit version\n# and the 32-bit program which is faster provides more resources.\n#USETASM16=1\n\n!ifndef USE_ASMCRC\n# default to ASM CRC C code for now (BCC needs TASM32 to support inline asm)...\nUSE_ASMCRC = 0\n!endif\n\n!ifndef USE_IZTIMEZONE\n#default: do not use the IZ timezone replacement\nUSE_IZTIMEZONE=0\n!endif\n\n!if $(USE_IZTIMEZONE) != 0\nLOC = -DW32_USE_IZ_TIMEZONE $(LOC)\n!endif\n\n# If you have bcc32i, you should define:\n# CC = bcc32i\n# This compiler generates a faster code.\nCC = bcc32\n!ifdef USETASM16\nAS = tasm\n!else\nAS = tasm32\n!endif\nAR = tlib\nLD = ilink32\n\n!if $(USE_ASMCRC) != 0\nASMFLG = -DASM_CRC\nCRC32 = crc_i386\nCRC32X = $(CRC32)\nCRC32F = $(CRC32)\nCRC32L = $(CRC32)\nCRC32G = $(CRC32)\nCRC32B = $(CRC32)\n!else\nASMFLG =\nCRC32 = crc32\nCRC32X = crc32x\nCRC32F = crc32f\nCRC32L = crc32l\nCRC32G = crc32g\nCRC32B = $(OB)crc32b\n!endif\n\n!if $(USE_IZTIMEZONE) != 0\nTIMEZONE_OBJU = timezone.obj\nTIMEZONE_OBJX = timezonx.obj\nTIMEZONE_OBJD = timezonl.obj\nTIMEZONE_OBLX = timezolx.obj\nTIMEZONE_OBJB = $(OB)timezonb.obj\n!else\nTIMEZONE_OBJU =\nTIMEZONE_OBJX =\nTIMEZONE_OBJD =\nTIMEZONE_OBLX =\nTIMEZONE_OBJB =\n!endif\n\n!if $(UNCLEAN)\nDIRT = -DUSE_SMITH_CODE -DUSE_UNSHRINK\n!else\nDIRT =\n!endif\n\n!if $(DEBUG)\nCC_SIZE_OPT = -Od\nCC_SPEED_OPT = -Od\n!else\n# Smallest code\nCC_SIZE_OPT = -O1 -OS\n# Fastest code\nCC_SPEED_OPT = -O2 -OS -Oc\n!endif\n!if $(WARNINGS)\nCC_WARN = -w -w-aus -w-par -w-sig -w-use\n!else\nCC_WARN = -w-\n!endif\n\n# compiler flags\n\nASCPUFLAG = __$(CPU_TYP)86\n!if $(CPU_TYP) != 0\nCC_CPUFLG = -$(CPU_TYP)\n!endif\nASFLAGS = -ml -m2 -w0 -D$(ASCPUFLAG) $(LOC)\nCFLAGS = $(CC_WARN) $(CC_CPUFLG) -d -ff- -k- -P-.C -I. $(ASMFLG) $(LOC) $(DIRT)\nLDFLAGS = # -lxncd -l-P\t\t# for bcc\nLDFLAGS_DLL = $(LDFLAGS) -tWD\nLDFLAGS_GUI = $(LDFLAGS) -tW\nUNFLAGS = $(CFLAGS) $(CC_SPEED_OPT)\nFUFLAGS = $(CFLAGS) $(CC_SPEED_OPT) -K -DFUNZIP\nSXFLAGS = $(CFLAGS) $(CC_SIZE_OPT) -DSFX\nDLFLAGS = $(CFLAGS) $(CC_SPEED_OPT) -tWD -DWINDLL -DDLL\nSLFLAGS = $(CFLAGS) $(CC_SIZE_OPT) -DWINDLL -DDLL -DUNZIPLIB -DSFX\nGXFLAGS = $(CFLAGS) $(CC_SIZE_OPT) -tW -DSFX\nLBFLAGS = $(CFLAGS) $(CC_SPEED_OPT) -DWINDLL -DDLL -DUNZIPLIB\n\n# list macros\n\n# special subdirectory for the static library binaries, to separate them\n# from other binaries (including dll import library file)\nOBDIR = ow32lib\nOB = $(OBDIR)/\n\n# object files\nOBJU1 = unzip.obj $(CRC32).obj crypt.obj envargs.obj explode.obj\nOBJU2 = extract.obj fileio.obj globals.obj inflate.obj list.obj match.obj\nOBJU3 = process.obj ttyio.obj ubz2err.obj unreduce.obj unshrink.obj zipinfo.obj\nOBJUS = win32.obj win32i64.obj nt.obj $(TIMEZONE_OBJU)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJUS)\nOBJF  = funzip.obj $(CRC32F).obj cryptf.obj globalsf.obj inflatef.obj \\\n\tttyiof.obj win32f.obj win32i64f.obj\nOBJX1 = unzipsfx.obj $(CRC32X).obj cryptx.obj\nOBJX2 = extractx.obj fileiox.obj globalsx.obj inflatex.obj matchx.obj\nOBJX3 = processx.obj ttyiox.obj ubz2errx.obj\nOBJXS = win32x.obj win32i64x.obj ntx.obj $(TIMEZONE_OBJX)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS)\nOBJD1 = api.obj $(CRC32L).obj cryptl.obj explodel.obj\nOBJD2 = extractl.obj fileiol.obj globalsl.obj inflatel.obj listl.obj matchl.obj\nOBJD3 = processl.obj ubz2errl.obj unreducl.obj unshrnkl.obj zipinfol.obj\nOBJDS = win32l.obj win32i64l.obj ntl.obj windll.obj $(ASMOBJS) $(TIMEZONE_OBJD)\nOBJD  = $(OBJD1) $(OBJD2) $(OBJD3) $(OBJDS)\nOBLX1 = apig.obj $(CRC32G).obj cryptg.obj\nOBLX2 = extractg.obj fileiog.obj globalsg.obj inflateg.obj\nOBLX3 = matchg.obj processg.obj ubz2errg.obj\nOBLXS = win32g.obj win32i64g.obj ntg.obj windllg.obj $(TIMEZONE_OBLX)\nOBLX  = $(OBLX1) $(OBLX2) $(OBLX3) $(OBLXS)\nOBGX  = sfxwiz.obj\nOBJLIB = $(OB)windllb.obj $(OB)apib.obj\nOBJB1 = $(CRC32B).obj $(OB)cryptb.obj\nOBJB2 = $(OB)explodeb.obj $(OB)extractb.obj $(OB)fileiob.obj $(OB)globalsb.obj\nOBJB3 = $(OB)inflateb.obj $(OB)listb.obj $(OB)matchb.obj $(OB)processb.obj\nOBJB4 = $(OB)ubz2errb.obj $(OB)unreducb.obj $(OB)unshrnkb.obj $(OB)zipinfob.obj\nOBJBS = $(OB)win32b.obj $(OB)win32i64b.obj $(OB)ntb.obj $(TIMEZONE_OBJB)\nOBJB  = $(OBJLIB) $(OBJB1) $(OBJB2) $(OBJB3) $(OBJB4) $(OBJBS)\n\nUNZIP_H = unzip.h unzpriv.h globals.h win32/w32cfg.h\nWINDLL_H = windll/windll.h windll/structs.h windll/decs.h\nWINDLL_DEF = windll/windll32.def\nWINDLL_IMP_H = windll/decs.h windll/structs.h\n\n# implicit rules\n\n.asm.obj:\n\t$(AS) $(ASFLAGS) $<\n\n.c.obj:\n\t$(CC) -c $(UNFLAGS) {$< }\n\n# explicit rules\n\n# Default target is all the command line executables\nunzips: unzip.exe funzip.exe unzipsfx.exe\ndll:    unzip32.dll\ndllsample: uzexampl.exe\nguisfx: SFXWiz32.exe\nlib:    $(OBDIR) $(OB)unzip32.lib\nall:    unzips dll dllsample guisfx lib\n\nunzip.exe:      $(OBJU) winapp.res\n\t$(CC) $(LDFLAGS) -e$@ @&&|\n$(OBJU)\n|\n\nfunzip.exe:     $(OBJF)\n\t$(CC) $(LDFLAGS) -e$@ @&&|\n$(OBJF)\n|\n\nunzipsfx.exe:   $(OBJX)\n\t$(CC) $(LDFLAGS) -e$@ @&&|\n$(OBJX)\n|\n\nunzip32.dll:    $(OBJD) windll.res $(WINDLL_DEF)\n\t$(LD) -Gn -x -c -aa -Tpd @&&|\nc0d32.obj $(OBJD),$@,,import32.lib cw32.lib,$(WINDLL_DEF:/=\\),windll.res\n|\n#\t$(CC) $(LDFLAGS_DLL) -e$@ @&&|\n#$(OBJD)\n##, windll.res\n#|\n#\tbrc32 windll.res $@\n\nunzsfx32.lib:   $(OBLX)\n\t$(AR) /C $(@:/=\\) @&&|\n/u $(OBLX:/=\\)\n|\n\nSFXWiz32.exe:   $(OBGX) sfxwiz.res unzsfx32.lib\n\t$(LD) -Gn -x -c -aa -Tpe @&&|\nc0w32.obj $(OBGX),$@,,unzsfx32.lib import32.lib cw32.lib,,sfxwiz.res\n|\n#\t$(CC) $(LDFLAGS_GUI) -e$@ $(OBGX) unzsfx32.lib $(LDLIBS)\n#\tbrc32 sfxwiz.res $@\n\nuzexampl.exe:   uzexampl.obj\n\t$(CC) $(LDFLAGS) -e$@ uzexampl.obj #version.lib\n\n$(OB)unzip32.lib: $(OBJB)\n\t$(AR) /C $(@:/=\\) @&&|\n/u $(OBJB:/=\\)\n|\n\nclean:\n\trem Ignore any errors in the following...\n\t-del *.obj\n\t-del winapp.res\n\t-del unzip.exe\n\t-del funzip.exe\n\t-del unzipsfx.exe\n\t-del windll.res\n\t-del unzip32.dll\n\t-del uzexampl.exe\n\t-del sfxwiz.res\n\t-del unzsfx32.lib\n\t-del SFXWiz32.exe\n\t-del $(OB:/=\\)*.obj\n\t-del $(OB:/=\\)unzip32.lib\n\t-del *.tds\n\t-del $(OB:/=\\)*.tds\n\n# individual file dependencies\n\ncrc32.obj:      crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt.obj:      crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs.obj:    envargs.c $(UNZIP_H)\nexplode.obj:    explode.c $(UNZIP_H)\nextract.obj:    extract.c $(UNZIP_H) crc32.h crypt.h\nfileio.obj:     fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals.obj:    globals.c $(UNZIP_H)\ninflate.obj:    inflate.c inflate.h $(UNZIP_H)\nlist.obj:       list.c $(UNZIP_H)\nmatch.obj:      match.c $(UNZIP_H)\nprocess.obj:    process.c $(UNZIP_H) crc32.h\ntimezone.obj:   timezone.c $(UNZIP_H) zip.h timezone.h\nttyio.obj:      ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err.obj:    ubz2err.c $(UNZIP_H)\nunreduce.obj:   unreduce.c $(UNZIP_H)\nunshrink.obj:   unshrink.c $(UNZIP_H)\nunzip.obj:      unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo.obj:    zipinfo.c $(UNZIP_H)\n\n!ifdef USEMASM\ncrc_i386.obj:   win32/crc_i386.asm\n\tmasm -ml win32/crc_i386.asm,$@;\n!else\n!ifdef USETASM\ncrc_i386.obj:   win32/crc_i386.asm\n\t$(AS) $(ASFLAGS) win32\\crc_i386.asm, $@ ;\n!else\ncrc_i386.obj:\twin32/crc_i386.c\n\t$(CC) -c $(UNFLAGS) -o$@ win32/crc_i386.c\n!endif\n!endif\n\nwin32.obj:      win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(UNFLAGS) win32/win32.c\n\nwin32i64.obj:   win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(UNFLAGS) win32/win32i64.c\n\nnt.obj:         win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(UNFLAGS) win32/nt.c\n\nfunzip.obj:     funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(FUFLAGS) -o$@ funzip.c\n\ncrc32f.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(FUFLAGS) -o$@ crc32.c\n\ncryptf.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(FUFLAGS) -o$@ crypt.c\n\nglobalsf.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(FUFLAGS) -o$@ globals.c\n\ninflatef.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(FUFLAGS) -o$@ inflate.c\n\nttyiof.obj:     ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(FUFLAGS) -o$@ ttyio.c\n\nwin32f.obj:     win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(FUFLAGS) -o$@ win32/win32.c\n\nwin32i64f.obj:  win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(FUFLAGS) -o$@ win32/win32i64.c\n\nunzipsfx.obj:   unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(SXFLAGS) -o$@ unzip.c\n\ncrc32x.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(SXFLAGS) -o$@ crc32.c\n\ncryptx.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(SXFLAGS) -o$@ crypt.c\n\nextractx.obj:   extract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(SXFLAGS) -o$@ extract.c\n\nfileiox.obj:    fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(SXFLAGS) -o$@ fileio.c\n\nglobalsx.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -o$@ globals.c\n\ninflatex.obj:   inflate.c inflate.h $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -o$@ inflate.c\n\nmatchx.obj:     match.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -o$@ match.c\n\nprocessx.obj:   process.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(SXFLAGS) -o$@ process.c\n\ntimezonx.obj:   timezone.c $(UNZIP_H) zip.h timezone.h\n\t$(CC) -c $(SXFLAGS) -o$@ timezone.c\n\nttyiox.obj:     ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(SXFLAGS) -o$@ ttyio.c\n\nubz2errx.obj:   ubz2err.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -o$@ ubz2err.c\n\nwin32x.obj:     win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(SXFLAGS) -o$@ win32/win32.c\n\nwin32i64x.obj:  win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(SXFLAGS) -o$@ win32/win32i64.c\n\nntx.obj:        win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(SXFLAGS) -o$@ win32/nt.c\n\nuzexampl.obj:   windll/uzexampl.c windll/uzexampl.h\n\t$(CC) -c $(UNFLAGS) -I./windll -o$@ windll/uzexampl.c\n\nwinapp.res:\twin32/winapp.rc unzvers.h\n\t$(RC) /l 0x409 /fo$@ /i win32 /d WIN32 win32/winapp.rc\n\n# DLL compilation section\napi.obj:        api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) -c $(DLFLAGS) -o$@ api.c\n\ncrc32l.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(DLFLAGS) -o$@ crc32.c\n\ncryptl.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(DLFLAGS) -o$@ crypt.c\n\nexplodel.obj:    explode.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ explode.c\n\nextractl.obj:   extract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) -c $(DLFLAGS) -o$@ extract.c\n\nfileiol.obj:    fileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(DLFLAGS) -o$@ fileio.c\n\nglobalsl.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ globals.c\n\ninflatel.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(DLFLAGS) -o$@ inflate.c\n\nlistl.obj:      list.c $(UNZIP_H) $(WINDLL_H)\n\t$(CC) -c $(DLFLAGS) -o$@ list.c\n\nmatchl.obj:     match.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ match.c\n\nprocessl.obj:   process.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) -c $(DLFLAGS) -o$@ process.c\n\ntimezonl.obj:   timezone.c $(UNZIP_H) zip.h timezone.h\n\t$(CC) -c $(DLFLAGS) -o$@ timezone.c\n\nubz2errl.obj:   ubz2err.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ ubz2err.c\n\nunreducl.obj:   unreduce.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ unreduce.c\n\nunshrnkl.obj:   unshrink.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ unshrink.c\n\nzipinfol.obj:   zipinfo.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ zipinfo.c\n\nwin32l.obj:     win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(DLFLAGS) -o$@ win32/win32.c\n\nwin32i64l.obj:  win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(DLFLAGS) -o$@ win32/win32i64.c\n\nntl.obj:        win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(DLFLAGS) -o$@ win32/nt.c\n\nwindll.obj: windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(DLFLAGS) -o$@ windll/windll.c\n\nwindll.res:\twindll/windll.rc unzvers.h\n\t$(RC) /l 0x409 /fo$@ /i windll /d WIN32 windll/windll.rc\n\n# SFX Lib compilation section\napig.obj:       api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) -c $(SLFLAGS) -o$@ api.c\n\ncrc32g.obj:     crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(SLFLAGS) -o$@ crc32.c\n\ncryptg.obj:     crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(SLFLAGS) -o$@ crypt.c\n\nexplodeg.obj:    explode.c $(UNZIP_H)\n\t$(CC) -c $(SLFLAGS) -o$@ explode.c\n\nextractg.obj:   extract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) -c $(SLFLAGS) -o$@ extract.c\n\nfileiog.obj:    fileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(SLFLAGS) -o$@ fileio.c\n\nglobalsg.obj:   globals.c $(UNZIP_H)\n\t$(CC) -c $(SLFLAGS) -o$@ globals.c\n\ninflateg.obj:   inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(SLFLAGS) -o$@ inflate.c\n\nmatchg.obj:     match.c $(UNZIP_H)\n\t$(CC) -c $(SLFLAGS) -o$@ match.c\n\nprocessg.obj:   process.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) -c $(SLFLAGS) -o$@ process.c\n\ntimezong.obj:   timezone.c $(UNZIP_H) zip.h timezone.h\n\t$(CC) -c $(SLFLAGS) -o$@ timezone.c\n\nubz2errg.obj:   ubz2err.c $(UNZIP_H)\n\t$(CC) -c $(SLFLAGS) -o$@ ubz2err.c\n\nwin32g.obj:     win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(SLFLAGS) -o$@ win32/win32.c\n\nwin32i64g.obj:  win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(SLFLAGS) -o$@ win32/win32i64.c\n\nntg.obj:        win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(SLFLAGS) -o$@ win32/nt.c\n\nwindllg.obj: windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(SLFLAGS) -o$@ windll/windll.c\n\nsfxwiz.obj:     windll/guisfx/sfxwiz.c windll/guisfx/dialog.h $(WINDLL_IMP_H)\n\t$(CC) -c $(GXFLAGS) -o$@ windll/guisfx/sfxwiz.c\n\nsfxwiz.res:     windll/guisfx/sfxwiz.rc\n\t$(RC) /l 0x409 /fo$@ /i windll/guisfx /d WIN32 windll/guisfx/sfxwiz.rc\n\n# Static LIB compilation section\n$(OB)apib.obj:      api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) -c $(LBFLAGS) -o$@ api.c\n\n$(OB)crc32b.obj:    crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(LBFLAGS) -o$@ crc32.c\n\n$(OB)cryptb.obj:    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(LBFLAGS) -o$@ crypt.c\n\n$(OB)explodeb.obj:  explode.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ explode.c\n\n$(OB)extractb.obj:  extract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) -c $(LBFLAGS) -o$@ extract.c\n\n$(OB)fileiob.obj:   fileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(LBFLAGS) -o$@ fileio.c\n\n$(OB)globalsb.obj:  globals.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ globals.c\n\n$(OB)inflateb.obj:  inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(LBFLAGS) -o$@ inflate.c\n\n$(OB)listb.obj:     list.c $(UNZIP_H) $(WINDLL_H)\n\t$(CC) -c $(LBFLAGS) -o$@ list.c\n\n$(OB)matchb.obj:    match.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ match.c\n\n$(OB)processb.obj:  process.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) -c $(LBFLAGS) -o$@ process.c\n\n$(OB)timezonb.obj:  timezone.c $(UNZIP_H) zip.h timezone.h\n\t$(CC) -c $(LBFLAGS) -o$@ timezone.c\n\n$(OB)ubz2errb.obj:  ubz2err.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ ubz2err.c\n\n$(OB)unreducb.obj:  unreduce.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ unreduce.c\n\n$(OB)unshrnkb.obj:  unshrink.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ unshrink.c\n\n$(OB)zipinfob.obj:  zipinfo.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ zipinfo.c\n\n$(OB)win32b.obj:    win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(LBFLAGS) -o$@ win32/win32.c\n\n$(OB)win32i64b.obj: win32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(LBFLAGS) -o$@ win32/win32i64.c\n\n$(OB)ntb.obj:       win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(LBFLAGS) -o$@ win32/nt.c\n\n$(OB)windllb.obj: windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(LBFLAGS) -o$@ windll/windll.c\n\n$(OBDIR):\n\t-mkdir $@\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.dj",
    "content": "# Makefile for UnZip, fUnZip and UnZipSFX\n# for rsxntdj 1.6beta2 (with djgpp v2.3) under Windows 9x and Windows NT.\n# By E-Yen Tan. Last updated 25th December 2006.\n\nCC = gcc -Zwin32\nCFLAGS = -O2 -Wall -I. -DWIN32 -DASM_CRC $(LOCAL_UNZIP)\nAS = gcc\nASFLAGS = -Di386\nLDFLAGS = -o ./\nLDFLAGS2 = -lalias -L. $(L_ADVAPI32)\nIMPLIBS = $(ADVAPI32LIB)\n\nADVAPI32 = advapi32\nADVAPI32LIB = lib$(ADVAPI32).a\nL_ADVAPI32 = -l$(ADVAPI32)\n\nOBJU1 = unzip.o crc_gcc.o crc32.o crypt.o envargs.o explode.o extract.o\nOBJU2 = fileio.o globals.o inflate.o list.o match.o process.o ttyio.o\nOBJU3 = ubz2err.o unreduce.o unshrink.o zipinfo.o win32.o nt.o\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3)\nOBJX1 = unzipsf_.o crc_gcc.o crc32_.o crypt_.o extract_.o fileio_.o globals_.o\nOBJX2 = inflate_.o match_.o process_.o ttyio_.o ubz2err_.o win32_.o nt_.o\nOBJX  = $(OBJX1) $(OBJX2)\nOBJF  = funzip.o crc_gcc.o crc32f.o cryptf.o inflatef.o globalsf.o ttyiof.o \\\n\twin32f.o\n\nUNZIP_H = unzip.h unzpriv.h globals.h win32/w32cfg.h\n\n# rules\n\n.SUFFIXES: .c .o\n\n.c.o:\n\t$(CC) -c $(CFLAGS) -o$@ $<\n\n.asm.o:\n\t$(AS) $(ASFLAGS) $<\n\nall:\tunzip.exe funzip.exe unzipsfx.exe\n\nunzip.exe: $(OBJU) $(IMPLIBS)\n\t$(CC) $(LDFLAGS)$@ $(OBJU) $(LDFLAGS2)\n\nfunzip.exe: $(OBJF) $(IMPLIBS)\n\t$(CC) $(LDFLAGS)$@ $(OBJF) $(LDFLAGS2)\n\nunzipsfx.exe: $(OBJX) $(IMPLIBS)\n\t$(CC) $(LDFLAGS)$@ $(OBJX) $(LDFLAGS2)\n\nuzexampl.exe:\tuzexampl$(OBJ)\n\t$(CC) $(LDFLAGS)$@ uzexampl$(OBJ) -lversion $(LDFLAGS2)\n\n$(ADVAPI32LIB):\n\tmakelib \"$(windir)/system/advapi32.dll\" -o ./$@\n\ncrc32.o:\tcrc32.c $(UNZIP_H) crc32.h\nenvargs.o:\tenvargs.c $(UNZIP_H)\nexplode.o:\texplode.c $(UNZIP_H)\nextract.o:\textract.c $(UNZIP_H) crypt.h\nfileio.o:\tfileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h\nglobals.o:\tglobals.c $(UNZIP_H)\ninflate.o:\tinflate.c $(UNZIP_H)\nlist.o:\t\tlist.c $(UNZIP_H)\nmatch.o:\tmatch.c $(UNZIP_H)\nprocess.o:\tprocess.c $(UNZIP_H)\nttyio.o:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err.o:\tubz2err.c $(UNZIP_H)\nunreduce.o:\tunreduce.c $(UNZIP_H)\nunshrink.o:\tunshrink.c $(UNZIP_H)\nunzip.o:\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo.o:\tzipinfo.c $(UNZIP_H)\n\nfunzip.o:\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -o$@ funzip.c\n\nuzexampl$(OBJ):\twindll/uzexampl.c windll/uzexampl.h\n\t$(CC) -c $(CFLAGS) -o$@ windll/uzexampl.c\n\nwin32.o:\twin32/win32.c $(UNZIP_H) win32/nt.h unzvers.h\n\t$(CC) -c $(CFLAGS) -o$@ win32/win32.c\n\nwin32f.o:\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ win32/win32.c\n\nwin32_.o:\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ win32/win32.c\n\nnt.o:\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) -o$@ win32/nt.c\n\nnt_.o:\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ win32/nt.c\n\ncrc_gcc.o:\tcrc_i386.S\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\ncrypt.o:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) -o$@ crypt.c\n\ncryptf.o:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ crypt.c\n\ncrc32f.o:\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ crc32.c\n\nglobalsf.o:\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ globals.c\n\ninflatef.o:\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ inflate.c\n\nttyiof.o:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DFUNZIP -o$@ ttyio.c\n\ncrc32_.o:\tcrc32.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ crc32.c\n\ncrypt_.o:\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ crypt.c\n\nextract_.o:\textract.c $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ extract.c\n\nfileio_.o:\tfileio.c $(UNZIP_H) crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ fileio.c\n\nglobals_.o:\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ globals.c\n\ninflate_.o:\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ inflate.c\n\nmatch_.o:\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ match.c\n\nprocess_.o:\tprocess.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ process.c\n\nttyio_.o:\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ ttyio.c\n\nubz2err_.o:\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ ubz2err.c\n\nunzipsf_.o:\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS) -DSFX -o$@ unzip.c\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.emx",
    "content": "# Makefile for UnZip, fUnZip and UnZipSFX\n# for emx 0.9d + rsxnt 1.42 / gcc under WIN32. Derived from makefile.os2\n# By E-Yen Tan and Christian Spieler. Last updated 25 December 2006.\n#\n# This makefile should work fine with GNU make and hopefully some others.\n# Tested with Spieler's special GNU make 3.74 gnuish 16-bit version.\n#\n# If make does not support long command-line passing to gcc, the link step\n# will fail. In this case, you have to edit the link commands to use the\n# commented-out alternative that creates a link response file \"by hand\".\n\n#ifdef NOASM\n#AS_FLAGS =\n#else\nAS_FLAGS = -DASM_CRC\n#endif\n\nCP=copy\nRM=del\n\nCC=gcc -Zwin32 -I.\nCC_OSIZ=-O1\nCC_OTIM=-O2 -mpentium\nCC_OPTS=-Wall -DWIN32 $(AS_FLAGS) $(LOCAL_UNZIP)\nCFLAGS=$(CC_OTIM) $(CC_OPTS)\nCFLAGSX=$(CC_OSIZ) $(CC_OPTS) -DSFX\nCFLAGSF=$(CC_OTIM) $(CC_OPTS) -DFUNZIP\nDLLFLAG=\nAS=gcc\nASFLAGS=-Di386\nLDFLAGS=-Zsys -o ./\nLDFLAGS2=-ladvapi32 -Zsmall-conv -s\nOUT=-o\nOBJ=.o\n\n#ifdef NOASM\n#CRCA_O=\n#else\nCRCA_O=crc_gcc\n#endif\nOBJUS=win32$(OBJ) nt$(OBJ)\nOBJXS=win32_$(OBJ) nt_$(OBJ)\nOBJFS=win32f$(OBJ)\nOSDEP_H=win32/w32cfg.h\n\n\n# default settings for target dependent macros:\nDIRSEP = /\nAS_DIRSEP = /\n\nOBJU1 = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ)\nOBJU2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ)\nOBJU3 = inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ)\nOBJU4 = ubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJUS)\nOBJX1 = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_O) crypt_$(OBJ)\nOBJX2 = extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ)\nOBJX3 = match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS)\nOBJF  = funzip$(OBJ) crc32f$(OBJ) $(CRCA_O) cryptf$(OBJ) inflatef$(OBJ) \\\n\tglobalsf$(OBJ) ttyiof$(OBJ) $(OBJFS)\n\nUNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES:\t.c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ $<\n\n# targets\n\nall:\tunzip.exe funzip.exe unzipsfx.exe\n\n# This next bit is nasty, but is needed to overcome the MS-DOS command\n# line limit as response files for emx's gcc seem to only work if each\n# file is on a different line. DJGPP doesn't do this (if you are at all\n# interested).\n\nunzip.exe: $(OBJU)\n#\t@ echo off\n#\t-@ $(RM) unzip.rsp\n#\t@ for %f in ($(OBJU1)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU2)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU3)) do echo %f >> unzip.rsp\n#\t@ for %f in ($(OBJU4) $(OBJUS)) do echo %f >> unzip.rsp\n#\t$(CC) $(LDFLAGS)$@ $(DEF) @unzip.rsp $(LDFLAGS2)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJU) $(LDFLAGS2)\n#\t@ $(RM) unzip.rsp\n\nfunzip.exe: $(OBJF)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJF) $(LDFLAGS2)\n\nunzipsfx.exe:\t$(OBJX)\n#\t@ echo off\n#\t-@ $(RM) unzipsfx.rsp\n#\t@ for %f in ($(OBJX1)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJX2)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJX3)) do echo %f >> unzipsfx.rsp\n#\t@ for %f in ($(OBJXS)) do echo %f >> unzipsfx.rsp\n#\t$(CC) $(LDFLAGS)$@ $(DEF) @unzipsfx.rsp $(LDFLAGS2)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJX) $(LDFLAGS2)\n#\t@ $(RM) unzipsfx.rsp\n\nuzexampl.exe:\tuzexampl$(OBJ)\n\t$(CC) $(LDFLAGS)$@ $(DEF) uzexampl$(OBJ) -lversion $(LDFLAGS2)\n\n# dependencies\n\napihelp$(OBJ):\tapihelp.c $(UNZIP_H) unzvers.h\ncrc32$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\nenvargs$(OBJ):\tenvargs.c $(UNZIP_H)\nexplode$(OBJ):\texplode.c $(UNZIP_H)\nextract$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\nfileio$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(OBJ):\tglobals.c $(UNZIP_H)\ninflate$(OBJ):\tinflate.c $(UNZIP_H)\nlist$(OBJ):\tlist.c $(UNZIP_H)\nmatch$(OBJ):\tmatch.c $(UNZIP_H)\nprocess$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\nttyio$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OBJ):\tubz2err.c $(UNZIP_H)\nunreduce$(OBJ):\tunreduce.c $(UNZIP_H)\nunshrink$(OBJ):\tunshrink.c $(UNZIP_H)\nunzip$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\napi$(OBJ):\tapi.c $(UNZIP_H) unzvers.h\nzipinfo$(OBJ):\tzipinfo.c $(UNZIP_H)\n\nfunzip$(OBJ):\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\t# funzip only\n\t$(CC) -c $(CFLAGS) $(OUT)$@ funzip.c\n\nunzipstb$(OBJ):\tunzipstb.c\t\t\t\t\t# DLL version\n\t$(CC) -c $(CFLAGS) $(OUT)$@ unzipstb.c\n\nuzexampl$(OBJ):\twindll/uzexampl.c windll/uzexampl.h\t\t# WINDLL example\n\t$(CC) -c $(CFLAGS) $(OUT)$@ windll/uzexampl.c\n\nwin32$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h unzvers.h\t# win32 only\n\t$(CC) -c $(CFLAGS) $(OUT)$@ win32$(DIRSEP)win32.c\n\nwin32f$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\t\t# win32 funzip\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ win32$(DIRSEP)win32.c\n\nwin32_$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\t\t# win32 unzipsfx\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ win32$(DIRSEP)win32.c\n\nnt$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\t\t# win32 only\n\t$(CC) -c $(CFLAGS) $(OUT)$@ win32$(DIRSEP)nt.c\n\nnt_$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\t\t# win32 only\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ win32$(DIRSEP)nt.c\n\nos2$(OBJ):\tos2/os2.c $(UNZIP_H) unzvers.h\t\t\t# OS/2 only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ os2$(DIRSEP)os2.c\n\nos2_$(OBJ):\tos2/os2.c $(UNZIP_H)\t\t\t\t# OS/2 unzipsfx\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ os2$(DIRSEP)os2.c\n\nos2acl$(OBJ):\tos2/os2acl.c $(UNZIP_H) unzvers.h\t\t# OS/2 only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ os2$(DIRSEP)os2acl.c\n\nrexxhelp$(OBJ):\tos2/rexxhelp.c\t\t\t\t\t# OS/2 DLL only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ os2$(DIRSEP)rexxhelp.c\n\nrexxapi$(OBJ):\tos2/rexxapi.c\t\t\t\t\t# OS/2 DLL only\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ os2$(DIRSEP)rexxapi.c\n\ncrc_i86$(OBJ):\tmsdos/crc_i86.asm\t\t\t\t# 16bit only\n\t$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)\n\ncrc_i386$(OBJ):\twin32/crc_i386.asm\t\t\t\t# 32bit, MASM\n\t$(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)\n\ncrc_gcc$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\ncrypt$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(DLLFLAG) $(OUT)$@ crypt.c\n\n# funzip compilation section\ncryptf$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ crypt.c\n\ncrc32f$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ crc32.c\n\nglobalsf$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ globals.c\n\ninflatef$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ inflate.c\n\nttyiof$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGSF) $(OUT)$@ ttyio.c\n\n# unzipsfx compilation section\ncrc32_$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ crypt.c\n\nextract_$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ extract.c\n\nfileio_$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ fileio.c\n\nglobals_$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ globals.c\n\ninflate_$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ inflate.c\n\nmatch_$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ match.c\n\nprocess_$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ process.c\n\nttyio_$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ ttyio.c\n\nubz2err_$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ ubz2err.c\n\nunzipsf_$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGSX) $(OUT)$@ unzip.c\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.gcc",
    "content": "# Makefile for UnZip, fUnZip and UnZipSFX for native Win32-Intel ports of gcc.\n# Currently supported implementations: Cygnus/Win32 and MinGW32.\n#\n# First version: Cosmin Truta, Dec 1997.\n# Last revision: Christian Spieler, 09-Aug-2008.\n#\n# To use, do \"make -f win32/makefile.gcc\".\n\n# configuration switches supported:\n#   NOASM=1     disable assembler crc32 code, the generic C source code\n#               is used instead.\n#   NOCRC_OPT=1 disable \"unfolding CRC tables\" optimization.\n#   OPT_P6=1    add \"modern gcc\" tuning option for PentiumPro family CPU.\n#   USEBZ2=1    activate integrated compilation of bzip2 compression support,\n#               this requires the bzip2 sources present in the bzip2 subfolder.\n#   USEZLIB=1   replace internal deflate code by externally provided zlib.\n#   USE_POSIX=1 build posix-style binaries targeted for the CygWin unix\n#               emulation environment.\n\n\n### Optional section\n\n# The following options allow to override the default assembler code usage\nifdef NOASM\nAPPLY_ASMCRC=0\nendif\nifdef USEASM\nAPPLY_ASMCRC=1\nendif\n\n# The external zlib library supplies its own crc32 implementation...\nifdef USEZLIB\nAPPLY_ASMCRC=0\nendif\n\n# default is ASM CRC code (from .S source) for now...\nifndef APPLY_ASMCRC\nAPPLY_ASMCRC=1\nendif\n\n# optional inclusion of bzip2 decompression\nIZ_BZIP2 = bzip2\nifdef USEBZ2\nINC_BZ2LIB = -I$(IZ_BZIP2)\nLOCFLAGS = $(INC_BZ2LIB) -DUSE_BZIP2\nLD_BZ2LIB = -L$(IZ_BZIP2) -lbz2\nLIBBZIP2 = $(IZ_BZIP2)/libbz2.a\nelse\nINC_BZ2LIB =\nLOCFLAGS =\nLD_BZ2LIB =\nLIBBZIP2 =\nendif\nLIBBZIP2X = $(LIBBZIP2)\n\nifndef USEZLIB\n\n# Apply the \"CRC unfolding tables\" optimization unless explicitly disabled.\n# (This optimization might have negative effects on old CPU designs with a\n# small first-level data cache.)\nifndef NOCRC_OPT\nLOCFLAGS += -DIZ_CRCOPTIM_UNFOLDTBL\nendif\n\n# Optional nonstandard preprocessor flags (as -DUSE_ZLIB or -DUSE_SMITH_CODE)\n# should be added to the environment via \"set LOCAL_UNZIP=-DFOO\" or added\n# to the declaration of LOCFLAGS here:\nifneq ($(APPLY_ASMCRC),0)\nLOCFLAGS += -DASM_CRC\nendif\n\nelse    # ifndef USEZLIB\n\nLOCFLAGS += -DUSE_ZLIB\n\nendif   # ifndef USEZLIB ... else ...\n\n# Finally, append additional externally supplied options.\nLOCFLAGS += $(LOCAL_UNZIP)\n\n# Some gcc distributions for Win32 (e.g. CygWin) try to emulate a POSIX-\n# compatible (Unix-style) environment.  This Makefile defaults to a\n# \"native Win32\" build.  To build POSIX-mode binaries, it is recommended\n# to use the Makefile of the Unix port.  However, by defining the variable\n# \"USE_POSIX\", building binaries for the POSIX environment can be enabled\n# here as well.\nifdef USE_POSIX\nCC_ENVIR_OPT = -DUNIX -DFORCE_UNIX_OVER_WIN32\nelse\nCC_ENVIR_OPT = -DWIN32 -DFORCE_WIN32_OVER_UNIX\nendif\n\n\n### Compiler-specific section\n\n# ------------ GNU C ------------\nCC = gcc\n\n#AS = as\nAS = $(CC)\n\n#LD = ld\nLD = $(CC)\n\nAR = ar\n\nRC = windres\n\n# Quiet\nCC_QUIET_OPT =\nAS_QUIET_OPT = $(CC_QUIET_OPT)\nLD_QUIET_OPT = $(CC_QUIET_OPT)\n\n# Warnings\nCC_WARN_OPT = -Wall\nAS_WARN_OPT = $(CC_WARN_OPT)\nLD_WARN_OPT =\n\n# Debug version\nCC_DEBUG_OPT = -g\nAS_DEBUG_OPT = $(CC_DEBUG_OPT)\nLD_DEBUG_OPT = $(CC_DEBUG_OPT)\n\n# Release version\nCC_RELEASE_OPT =\nAS_RELEASE_OPT =\nLD_RELEASE_OPT = -s\n\n# Prefered target CPU (instruction scheduling optimized for...)\nifndef CC_CPU_OPT\nCC_CPU_OPT = -mcpu=pentiumpro\nendif\n\n# Smallest code  (-Os is new since EGC 1.1, use -O1 for 2.8.1 and earlier)\nCC_SIZE_OPT = -Os $(CC_CPU_OPT)\n\n# Fastest code\nCC_SPEED_OPT = -O2 $(CC_CPU_OPT)\n\n# Output object file name\nCC_OUT_OPT = -o\n\n# Other specific options\nCC_SPECIFIC_OPT = -c $(CC_ENVIR_OPT)\nAS_SPECIFIC_OPT = -c\nLD_SPECIFIC_OPT = -o $@\n\n# Libraries for the debug & release version\n# (GCC 2.95 and newer does not require the system library specifications)\nifdef USEZLIB\nLD_RELEASE_LIBS = -L. -lz -luser32 -ladvapi32\nelse\nLD_RELEASE_LIBS = -luser32 -ladvapi32\nendif\nLD_DEBUG_LIBS = $(LD_RELEASE_LIBS)\n\n\n### System-specific section\n\n# Suffixes\nOBJ = .o\nEXE = .exe\n\n.SUFFIXES: .c .S $(OBJ) $(EXE)\n.PHONY: FORCE\n\n# Commands\nRM = rm -f\n\n\n### General section\n\nCFLAGS  = $(CC_SPECIFIC_OPT) $(CC_QUIET_OPT) $(CC_WARN_OPT) $(LOCFLAGS) \\\n $(CC_OUT_OPT) $@\nASFLAGS = $(AS_SPECIFIC_OPT) $(AS_QUIET_OPT) $(AS_WARN_OPT) $(LOCFLAGS)\nLDFLAGS = $(LD_SPECIFIC_OPT) $(LD_QUIET_OPT) $(LD_WARN_OPT)\n\n# To build with debug info, use 'make DEBUG=1'.\nifdef DEBUG\nCVER     = $(CC_DEBUG_OPT)\nASVER    = $(AS_DEBUG_OPT)\nLDVER    = $(LD_DEBUG_OPT)\nGENFLAGS =\nFFLAGS   = -DFUNZIP\nSFXFLAGS = -DSFX\nGENDLLFL = -DDLL -DWINDLL\nGENGUILB = -DSFX -DDLL -DWINDLL -DUNZIPLIB\nGENGUISX = -DSFX\nGENLIBFL = -DDLL -DWINDLL -DUNZIPLIB\nLDLIBS   = $(LD_DEBUG_LIBS)\nelse\nCVER     = $(CC_RELEASE_OPT)\nASVER    = $(AS_RELEASE_OPT)\nLDVER    = $(LD_RELEASE_OPT)\nGENFLAGS = $(CC_SPEED_OPT)\nFFLAGS   = $(CC_SPEED_OPT) -DFUNZIP\nSFXFLAGS = $(CC_SIZE_OPT) -DSFX\nGENDLLFL = $(CC_SPEED_OPT) -DDLL -DWINDLL\nGENGUILB = $(CC_SIZE_OPT) -DSFX -DDLL -DWINDLL -DUNZIPLIB\nGENGUISX = $(CC_SIZE_OPT) -DSFX\nGENLIBFL = $(CC_SPEED_OPT) -DDLL -DWINDLL -DUNZIPLIB\nLDLIBS   = $(LD_RELEASE_LIBS)\nendif\nGUILDFLAG=-mwindows\n\n# Object files\nifneq ($(APPLY_ASMCRC),0)\nOBJA  = crc_i386$(OBJ)\nelse\nOBJA  =\nendif\nOBJU1 = unzip$(OBJ) crc32$(OBJ) crypt$(OBJ) envargs$(OBJ)\nOBJU2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ) inflate$(OBJ)\nOBJU3 = list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ) ubz2err$(OBJ)\nOBJU4 = unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)\nOBJUS = win32$(OBJ) win32i64$(OBJ) nt$(OBJ) winapprc$(OBJ)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJA) $(OBJUS)\nOBJX1 = unzipsfx$(OBJ) crc32x$(OBJ) cryptx$(OBJ) extractx$(OBJ)\nOBJX2 = fileiox$(OBJ) globalsx$(OBJ) inflatex$(OBJ) matchx$(OBJ) processx$(OBJ)\nOBJX3 = ttyiox$(OBJ) ubz2errx$(OBJ)\nOBJXS = win32x$(OBJ) win32i64x$(OBJ) ntx$(OBJ)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJA) $(OBJXS)\nOBJF1 = funzip$(OBJ) crc32$(OBJ) cryptf$(OBJ) globalsf$(OBJ) inflatef$(OBJ)\nOBJF2 = ttyiof$(OBJ)\nOBJFS = win32f$(OBJ) win32i64f$(OBJ)\nOBJF  = $(OBJF1) $(OBJF2) $(OBJA) $(OBJFS)\nOBJDLL = windll$(OBJ) windllrc$(OBJ) api$(OBJ)\nOBJD1 = crc32l$(OBJ) cryptl$(OBJ)\nOBJD2 = explodel$(OBJ) extractl$(OBJ) fileiol$(OBJ) globalsl$(OBJ)\nOBJD3 = inflatel$(OBJ) listl$(OBJ) matchl$(OBJ) processl$(OBJ) ubz2errl$(OBJ)\nOBJD4 = unreducl$(OBJ) unshrnkl$(OBJ) zipinfol$(OBJ)\nOBJDS = win32l$(OBJ) win32i64l$(OBJ) ntl$(OBJ)\nOBJD  = $(OBJDLL) $(OBJD1) $(OBJD2) $(OBJD3) $(OBJD4) $(OBJA) $(OBJDS)\nOBLX1 = apig$(OBJ) crc32g$(OBJ) cryptg$(OBJ)\nOBLX2 = extractg$(OBJ) fileiog$(OBJ) globalsg$(OBJ) inflateg$(OBJ)\nOBLX3 = matchg$(OBJ) processg$(OBJ) ubz2errg$(OBJ)\nOBLXS = win32g$(OBJ) win32i64g$(OBJ) ntg$(OBJ) windllg$(OBJ)\nOBLX  = $(OBLX1) $(OBLX2) $(OBLX3) $(OBJA) $(OBLXS)\nOBGX  = sfxwiz$(OBJ) sfxwizrc$(OBJ)\nOBJLIB = windllb$(OBJ) apib$(OBJ)\nOBJB1 = crc32b$(OBJ) cryptb$(OBJ)\nOBJB2 = explodeb$(OBJ) extractb$(OBJ) fileiob$(OBJ) globalsb$(OBJ)\nOBJB3 = inflateb$(OBJ) listb$(OBJ) matchb$(OBJ) processb$(OBJ) ubz2errb$(OBJ)\nOBJB4 = unreducb$(OBJ) unshrnkb$(OBJ) zipinfob$(OBJ)\nOBJBS = win32b$(OBJ) win32i64b$(OBJ) ntb$(OBJ)\nOBJB  = $(OBJLIB) $(OBJB1) $(OBJB2) $(OBJB3) $(OBJB4) $(OBJA) $(OBJBS)\n\nUNZIP_H = unzip.h unzpriv.h globals.h win32/w32cfg.h\nWINDLL_H = windll/windll.h windll/structs.h windll/decs.h\nDLLDEF = windll/windllgcc.def\nWINDLL_IMP_H = windll/decs.h windll/structs.h\n\n\n# Default target is all the executables\nunzips: unzip$(EXE) funzip$(EXE) unzipsfx$(EXE)\ndll:    unzip32.dll\ndllsample: uzexampl$(EXE)\nguisfx: SFXWiz32$(EXE)\nlib:    libunzip32.a\nall:    unzips dll dllsample guisfx lib\n\nunzip$(EXE): $(OBJU) $(LIBBZIP2)\n\t$(LD) $(LDFLAGS) $(LDVER) $(OBJU) $(LD_BZ2LIB) $(LDLIBS)\n\nunzipsfx$(EXE): $(OBJX) $(LIBBZIP2X)\n\t$(LD) $(LDFLAGS) $(LDVER) $(OBJX) $(LDLIBS)\n\nfunzip$(EXE): $(OBJF)\n\t$(LD) $(LDFLAGS) $(LDVER) $(OBJF) $(LDLIBS)\n\nunzip32.dll: $(DLLDEF) $(OBJD) $(LIBBZIP2)\n\tdllwrap --driver-name $(CC) --def $(DLLDEF) $(LDFLAGS) $(LDVER) $(OBJD) $(LD_BZ2LIB) $(LDLIBS)\n\nlibunzsfx32.a: $(OBLX)\n\t$(AR) -rus $@ $(OBLX)\n\nSFXWiz32$(EXE): $(OBGX) libunzsfx32.a $(LIBBZIP2X)\n\t$(LD) $(GUILDFLAG) $(LDFLAGS) $(LDVER) $(OBGX) -L. -lunzsfx32 $(LDLIBS)\n\nuzexampl$(EXE): uzexampl$(OBJ)\n\t$(CC) $(LDFLAGS) $(LDVER) uzexampl$(OBJ) -lversion $(LDLIBS)\n\nlibunzip32.a: $(OBJB)\n\t$(AR) -rus $@ $(OBJB)\n\n\n# create/update the library for the optional bzip2 support:\n$(IZ_BZIP2)/libbz2.a: FORCE\n\t$(subst /,\\,$(MAKE)) -C $(IZ_BZIP2) -f Makebz2.iz CC=\"$(CC)\" RM=\"$(RM)\"\nFORCE:\n\n# How to compile sources\n.c$(OBJ):\n\t$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) $<\n.S$(OBJ):\n\t$(AS) $(ASFLAGS) $(ASVER) $(GENFLAGS) $<\n\n# Dependencies\ncrc32$(OBJ):    crc32.c $(UNZIP_H) zip.h crc32.h\ncrypt$(OBJ):    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\nenvargs$(OBJ):  envargs.c $(UNZIP_H)\nexplode$(OBJ):  explode.c $(UNZIP_H)\nextract$(OBJ):  extract.c $(UNZIP_H) crc32.h crypt.h\nfileio$(OBJ):   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nfunzip$(OBJ):   funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\nglobals$(OBJ):  globals.c $(UNZIP_H)\ninflate$(OBJ):  inflate.c inflate.h $(UNZIP_H)\nlist$(OBJ):     list.c $(UNZIP_H)\nmatch$(OBJ):    match.c $(UNZIP_H)\nprocess$(OBJ):  process.c $(UNZIP_H) crc32.h\nttyio$(OBJ):    ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OBJ): ubz2err.c $(UNZIP_H)\nunreduce$(OBJ): unreduce.c $(UNZIP_H)\nunshrink$(OBJ): unshrink.c $(UNZIP_H)\nunzip$(OBJ):    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo$(OBJ):  zipinfo.c $(UNZIP_H)\ncrc_i386$(OBJ): crc_i386.S\n\nwin32$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) -I. $<\n\nwin32i64$(OBJ): win32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) -I. $<\n\nnt$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) -I. $<\n\nwinapprc$(OBJ):\twin32/winapp.rc unzvers.h\n\t- $(RC) -o $@ $<\n\n# UnZipSFX compilation section\ncrc32x$(OBJ): crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\ncryptx$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nextractx$(OBJ): extract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nfileiox$(OBJ):   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nglobalsx$(OBJ): globals.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\ninflatex$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nmatchx$(OBJ): match.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nprocessx$(OBJ): process.c $(UNZIP_H) crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nttyiox$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nubz2errx$(OBJ): ubz2err.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nunzipsfx$(OBJ): unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) $<\n\nwin32x$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) -I. $<\n\nwin32i64x$(OBJ): win32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) -I. $<\n\nntx$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(SFXFLAGS) -I. $<\n\n# fUnZip compilation section\ncryptf$(OBJ): crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) $<\n\nglobalsf$(OBJ): globals.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) $<\n\ninflatef$(OBJ): inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) $<\n\nttyiof$(OBJ): ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) $<\n\nwin32f$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) -I. $<\n\nwin32i64f$(OBJ): win32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(FFLAGS) -I. $<\n\n# WINDLL sample\nuzexampl$(OBJ):\twindll/uzexampl.c windll/uzexampl.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENFLAGS) -I. $<\n\n# DLL compilation section\napi$(OBJ): api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\ncrc32l$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\ncryptl$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nexplodel$(OBJ):\texplode.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nextractl$(OBJ):\textract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nfileiol$(OBJ):\tfileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nglobalsl$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\ninflatel$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nlistl$(OBJ):\tlist.c $(UNZIP_H) $(WINDLL_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nmatchl$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nprocessl$(OBJ):\tprocess.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nubz2errl$(OBJ): ubz2err.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nunreducl$(OBJ):\tunreduce.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nunshrnkl$(OBJ):\tunshrink.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nzipinfol$(OBJ):\tzipinfo.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) $<\n\nwin32l$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) -I. $<\n\nwin32i64l$(OBJ): win32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) -I. $<\n\nntl$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) -I. $<\n\nwindll$(OBJ): windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENDLLFL) -I. $<\n\nwindllrc$(OBJ):\twindll/windll.rc unzvers.h\n\t- $(RC) -o $@ $<\n\n# SFX Lib compilation section\napig$(OBJ):\tapi.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\ncrc32g$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\ncryptg$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nextractg$(OBJ):\textract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nfileiog$(OBJ):\tfileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nglobalsg$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\ninflateg$(OBJ):\tinflate.c inflate.h $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nmatchg$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nprocessg$(OBJ):\tprocess.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nubz2errg$(OBJ): ubz2err.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) $<\n\nwin32g$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) -I. $<\n\nwin32i64g$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) -I. $<\n\nntg$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) -I. $<\n\nwindllg$(OBJ):  windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUILB) -I. $<\n\nsfxwiz$(OBJ):\twindll/guisfx/sfxwiz.c windll/guisfx/dialog.h $(WINDLL_IMP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENGUISX) -I. $<\n\nsfxwizrc$(OBJ):\twindll/guisfx/sfxwiz.rc\n\t- $(RC)  --include-dir windll/guisfx --define WIN32 -o$@ $<\n\n# Static LIB compilation section\napib$(OBJ): api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\ncrc32b$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\ncryptb$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nexplodeb$(OBJ):\texplode.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nextractb$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nfileiob$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nglobalsb$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\ninflateb$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nlistb$(OBJ):\tlist.c $(UNZIP_H) $(WINDLL_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nmatchb$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nprocessb$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nubz2errb$(OBJ): ubz2err.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nunreducb$(OBJ):\tunreduce.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nunshrnkb$(OBJ):\tunshrink.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nzipinfob$(OBJ):\tzipinfo.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) $<\n\nwin32b$(OBJ): win32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) -I. $<\n\nwin32i64b$(OBJ): win32/win32i64.c $(UNZIP_H)\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) -I. $<\n\nntb$(OBJ): win32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) -I. $<\n\nwindllb$(OBJ): windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) $(CFLAGS) $(CVER) $(GENLIBFL) -I. $<\n\nclean:\n\t-$(subst /,\\,$(MAKE)) -C $(IZ_BZIP2) -f Makebz2.iz RM=\"$(RM)\" clean\n\t-$(RM) *$(OBJ)\n\t-$(RM) unzip$(EXE) funzip$(EXE) unzipsfx$(EXE)\n\t-$(RM) unzip32.dll uzexampl$(EXE) SFXWiz32$(EXE)\n\t-$(RM) libunzip32.a libunzsfx32.a\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.lcc",
    "content": "# Makefile for UnZip, fUnZip and UnZipSFX using LCC-Win32.\n# By E-Yen Tan (3 June 1998).\n# Last updated 20 Jul 2008 (Christian Spieler).\n#\n# This version includes rules to build the 32-bit windll DLL.\n\n# This compiler evaluates #include locations relative to current working dir,\n# not relative to the location of the file containing the #include directive.\n# As a consequence, a \"-Iwin32\" option is required to allow compilation of\n# the WIN32 specific sources.\n\nCC=lcc\nCCFLAGS=-Zp8 -O -DWIN32 $(AS_FLAGS)\n#DLLFLAG=\nDLLFLAG=-DWINDLL -DDLL -I./windll\nAS=lcc\nASFLAGS=\nLD = lcclnk\n#DLLLDFLAG=\nDLLLDFLAG=-dll -entry DllMain\nLDFLAGS=-s -o ./\nLDFLAGS2=\nOUT=-Fo\nOBJ=.obj\n\nCP=copy\nRM=del\n\n# Optional macros should be declared below.\n# (LCC's Make is unable to read the LOCAL_UNZIP environment variable.)\nLOC = $(ASMFLG)\n\n# Options to select optimized assembler code for CRC32 calculation.\n#ifdef NOASM\n#ASMFLG=\n#CRCA_O=\n#CRCA_OF=\n#CRCA_OL=\n#CRCA_OG=\n#CRCA_OX=\n#else\nASMFLG=-DASM_CRC\nCRCA_O=crc_lcc$(OBJ)\nCRCA_OF=$(CRCA_O)\nCRCA_OL=$(CRCA_O)\nCRCA_OG=$(CRCA_O)\nCRCA_OX=$(CRCA_O)\n#endif\n\nCFLAGS = $(CCFLAGS) $(LOC)\n\nCFLAGS_UN = $(CFLAGS)\nCFLAGS_SX = $(CFLAGS) -DSFX\nCFLAGS_FU = $(CFLAGS) -DFUNZIP\nCFLAGS_DL = $(CFLAGS) $(DLLFLAG)\nCFLAGS_SL = $(CFLAGS) $(DLLFLAG) -DUNZIPLIB -DSFX\nCFLAGS_GX = $(CFLAGS) -I./windll -I./windll/guisfx -DSFX\n\n\n# The system specific files are defined here:\nOBJUS=win32$(OBJ) win32i64$(OBJ) nt$(OBJ)\nOBJXS=win32_$(OBJ) win32i64_$(OBJ) nt_$(OBJ)\nOBJFS=win32f$(OBJ) win32i64f$(OBJ)\nOBJDS=win32l$(OBJ) win32i64l$(OBJ) ntl$(OBJ)\nOBLXS=win32g$(OBJ) win32i64g$(OBJ) ntg$(OBJ) windllg$(OBJ)\nOSDEP_H=win32/w32cfg.h\nWINDLL_H=windll/windll.h windll/structs.h windll/decs.h\nDLLDEF=.\\windll\\windll_lc.def\t# lcclink requires backslashes as dir-sep!!\nWINDLL_IMP_H = windll/decs.h windll/structs.h\n\n\nOBJU1 = unzip$(OBJ) crc32$(OBJ) $(CRCA_O) crypt$(OBJ) envargs$(OBJ)\nOBJU2 = explode$(OBJ) extract$(OBJ) fileio$(OBJ) globals$(OBJ)\nOBJU3 = inflate$(OBJ) list$(OBJ) match$(OBJ) process$(OBJ) ttyio$(OBJ)\nOBJU4 = ubz2err$(OBJ) unreduce$(OBJ) unshrink$(OBJ) zipinfo$(OBJ)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJUS)\nOBJX1 = unzipsf_$(OBJ) crc32_$(OBJ) $(CRCA_OX) crypt_$(OBJ)\nOBJX2 = extract_$(OBJ) fileio_$(OBJ) globals_$(OBJ) inflate_$(OBJ)\nOBJX3 = match_$(OBJ) process_$(OBJ) ttyio_$(OBJ) ubz2err_$(OBJ)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS)\nOBJF  = funzip$(OBJ) crc32f$(OBJ) $(CRCA_OF) cryptf$(OBJ) inflatef$(OBJ) \\\n\tglobalsf$(OBJ) ttyiof$(OBJ) $(OBJFS)\nOBJDLL = windll$(OBJ) windll32.res api$(OBJ)\nOBJD1 = crc32l$(OBJ) $(CRCA_OL) cryptl$(OBJ)\nOBJD2 = explodel$(OBJ) extractl$(OBJ) fileiol$(OBJ) globalsl$(OBJ)\nOBJD3 = inflatel$(OBJ) listl$(OBJ) matchl$(OBJ) processl$(OBJ)\nOBJD4 = ubz2errl$(OBJ) unreducl$(OBJ) unshrnkl$(OBJ) zipinfol$(OBJ)\nOBJD  = $(OBJDLL) $(OBJD1) $(OBJD2) $(OBJD3) $(OBJD4) $(OBJDS)\nOBLX1 = apig$(OBJ) crc32g$(OBJ) $(CRCA_OG) cryptg$(OBJ)\nOBLX2 = extractg$(OBJ) fileiog$(OBJ) globalsg$(OBJ) inflateg$(OBJ)\nOBLX3 = matchg$(OBJ) processg$(OBJ) ubz2errg$(OBJ)\nOBLX  = $(OBLX1) $(OBLX2) $(OBLX3) $(OBLXS)\nOBGX  = sfxwiz$(OBJ)\n\nUNZIP_H = unzip.h unzpriv.h globals.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES: .c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c $(CFLAGS_UN) $(OUT)$@ $<\n\n.asm$(OBJ):\n\t$(AS) $(ASFLAGS) $(OUT)$@ $<\n\n# targets\n\nunzips:\tunzip.exe funzip.exe unzipsfx.exe\ndll:\tunzip32.dll\ndllsample: uzexampl.exe\nguisfx:\tSFXWiz32.exe\nall:\tunzips dll dllsample guisfx\n\nunzip.exe: $(OBJU) winapp.res\n\t$(LD) $(LDFLAGS)$@ $(DEF) $(OBJU) winapp.res $(LDFLAGS2)\n\nfunzip.exe: $(OBJF)\n\t$(LD) $(LDFLAGS)$@ $(DEF) $(OBJF) $(LDFLAGS2)\n\nunzipsfx.exe:\t$(OBJX)\n\t$(LD) $(LDFLAGS)$@ $(DEF) $(OBJX) $(LDFLAGS2)\n\nunzip32.dll: $(DLLDEF) $(OBJD)\n\t$(LD) $(DLLLDFLAG) $(LDFLAGS)$@ $(DLLDEF) $(OBJD) $(LDFLAGS2)\n\nunzsfx32.lib:\t$(OBLX)\n\tlcclib $@ $(OBLX)\n\nSFXWiz32.exe:\t$(OBGX) sfxwiz.res unzsfx32.lib\n\t$(LD) -subsystem windows $(LDFLAGS)$@  \\\n\t\t$(OBGX) sfxwiz.res unzsfx32.lib\n\nuzexampl.exe: uzexampl$(OBJ)\n\t$(LD) $(LDFLAGS)$@ $(DEF) uzexampl$(OBJ) version.lib $(LDFLAGS2)\n\n# dependencies\n\napi$(OBJ):\tapi.c $(UNZIP_H) unzvers.h\napihelp$(OBJ):\tapihelp.c $(UNZIP_H) unzvers.h\ncrc32$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\nenvargs$(OBJ):\tenvargs.c $(UNZIP_H)\nexplode$(OBJ):\texplode.c $(UNZIP_H)\nextract$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\nfileio$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\nglobals$(OBJ):\tglobals.c $(UNZIP_H)\ninflate$(OBJ):\tinflate.c $(UNZIP_H)\nlist$(OBJ):\tlist.c $(UNZIP_H)\nmatch$(OBJ):\tmatch.c $(UNZIP_H)\nprocess$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\nttyio$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\nubz2err$(OBJ):\tubz2err.c $(UNZIP_H)\nunreduce$(OBJ):\tunreduce.c $(UNZIP_H)\nunshrink$(OBJ):\tunshrink.c $(UNZIP_H)\nunzip$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\nzipinfo$(OBJ):\tzipinfo.c $(UNZIP_H)\n\nfunzip$(OBJ):\tfunzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $(OUT)$@ funzip.c\n\nuzexampl$(OBJ):\twindll/uzexampl.c windll/uzexampl.h\n\t$(CC) -c $(CFLAGS_UN) -I./windll $(OUT)$@ windll/uzexampl.c\n\nwin32$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h unzvers.h\n\t$(CC) -c $(CFLAGS_UN) -Iwin32 $(OUT)$@ win32/win32.c\n\nwin32i64$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_UN) -Iwin32 $(OUT)$@ win32/win32i64.c\n\nnt$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_UN) -Iwin32 $(OUT)$@ win32/nt.c\n\ncrc_lcc$(OBJ):\twin32/crc_lcc.asm\n\t$(AS) $(ASFLAGS) $(OUT)$@ win32/crc_lcc.asm\n\ncrypt$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS_UN) $(OUT)$@ crypt.c\n\nwinapp.res:\twin32/winapp.rc unzvers.h\n\t- lrc -v -r -I./win32 -DWIN32 -o$@ win32/winapp.rc\n\ncrc32f$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_FU) $(OUT)$@ crc32.c\n\ncryptf$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS_FU) $(OUT)$@ crypt.c\n\nglobalsf$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_FU) $(OUT)$@ globals.c\n\ninflatef$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS_FU) $(OUT)$@ inflate.c\n\nttyiof$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS_FU) $(OUT)$@ ttyio.c\n\nwin32f$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_FU) -Iwin32 $(OUT)$@ win32/win32.c\n\nwin32i64f$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_FU) -Iwin32 $(OUT)$@ win32/win32i64.c\n\ncrc32_$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ crypt.c\n\nextract_$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ extract.c\n\nfileio_$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ fileio.c\n\nglobals_$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ globals.c\n\ninflate_$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ inflate.c\n\nmatch_$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ match.c\n\nprocess_$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ process.c\n\nttyio_$(OBJ):\tttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ ttyio.c\n\nubz2err_$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ ubz2err.c\n\nunzipsf_$(OBJ):\tunzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS_SX) $(OUT)$@ unzip.c\n\nwin32_$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_SX) -Iwin32 $(OUT)$@ win32/win32.c\n\nwin32i64_$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SX) -Iwin32 $(OUT)$@ win32/win32i64.c\n\nnt_$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_SX) -Iwin32 $(OUT)$@ win32/nt.c\n\n# DLL compilation section\napi$(OBJ):\tapi.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ api.c\n\ncrc32l$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ crc32.c\n\ncryptl$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ crypt.c\n\nexplodel$(OBJ):\texplode.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ explode.c\n\nextractl$(OBJ):\textract.c $(UNZIP_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ extract.c\n\nfileiol$(OBJ):\tfileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ fileio.c\n\nglobalsl$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ globals.c\n\ninflatel$(OBJ):\tinflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ inflate.c\n\nlistl$(OBJ):\tlist.c $(UNZIP_H) $(WINDLL_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ list.c\n\nmatchl$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ match.c\n\nprocessl$(OBJ):\tprocess.c $(UNZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ process.c\n\nubz2errl$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ ubz2err.c\n\nunreducl$(OBJ):\tunreduce.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ unreduce.c\n\nunshrnkl$(OBJ):\tunshrink.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ unshrink.c\n\nzipinfol$(OBJ):\tzipinfo.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ zipinfo.c\n\nwin32l$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_DL) -Iwin32 $(OUT)$@ win32/win32.c\n\nwin32i64l$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_DL) -Iwin32 $(OUT)$@ win32/win32i64.c\n\nntl$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_DL) -Iwin32 $(OUT)$@ win32/nt.c\n\nwindll$(OBJ): windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS_DL) $(OUT)$@ windll/windll.c\n\nwindll32.res:\twindll/windll.rc unzvers.h\n\t- lrc -v -r $(DLLFLAG) -DWIN32 -o$@ windll/windll.rc\n\n# SFX Lib compilation section\napig$(OBJ):\tapi.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ api.c\n\ncrc32g$(OBJ):\tcrc32.c $(UNZIP_H) zip.h crc32.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ crc32.c\n\ncryptg$(OBJ):\tcrypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ crypt.c\n\nextractg$(OBJ):\textract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ extract.c\n\nfileiog$(OBJ):\tfileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ fileio.c\n\nglobalsg$(OBJ):\tglobals.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ globals.c\n\ninflateg$(OBJ):\tinflate.c inflate.h $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ inflate.c\n\nmatchg$(OBJ):\tmatch.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ match.c\n\nprocessg$(OBJ):\tprocess.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ process.c\n\nubz2errg$(OBJ):\tubz2err.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ ubz2err.c\n\nwin32g$(OBJ):\twin32/win32.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_SL) -Iwin32 $(OUT)$@ win32/win32.c\n\nwin32i64g$(OBJ):\twin32/win32i64.c $(UNZIP_H)\n\t$(CC) -c $(CFLAGS_SL) -Iwin32 $(OUT)$@ win32/win32i64.c\n\nntg$(OBJ):\twin32/nt.c $(UNZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS_SL) -Iwin32 $(OUT)$@ win32/nt.c\n\nwindllg$(OBJ):  windll/windll.c $(UNZIP_H) $(WINDLL_H) crypt.h unzvers.h consts.h\n\t$(CC) -c $(CFLAGS_SL) $(OUT)$@ windll/windll.c\n\nsfxwiz$(OBJ):\twindll/guisfx/sfxwiz.c windll/guisfx/dialog.h $(WINDLL_IMP_H)\n\t$(CC) -c $(CFLAGS_GX) $(OUT)$@ windll/guisfx/sfxwiz.c\n\nsfxwiz.res:\twindll/guisfx/sfxwiz.rc\n\t- lrc -v -r -Iwindll/guisfx -DWIN32 -o$@ windll/guisfx/sfxwiz.rc\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/Makefile.wat",
    "content": "# WMAKE makefile for Windows 9x and Windows NT (Intel only)\n# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 18 Jan 2009.\n# Makes UnZip.exe, fUnZip.exe, and UnZipSFX.exe.\n#\n# Invoke from UnZip source dir with \"WMAKE -F WIN32\\MAKEFILE.WAT [targets]\"\n# To build with debug info use \"WMAKE DEBUG=1 ...\"\n# To build with no assembly modules use \"WMAKE NOASM=1 ...\"\n# To omit unshrinking support use \"WMAKE NO_LZW=1 ...\"\n# To support unreducing, get the real unreduce.c and go \"WMAKE OFFEND_RMS=1 ...\"\n# To use Info-Zip's generic timezone functions use \"WMAKE USE_IZTIMEZONE=1 ...\"\n# To include support for bzip2 decompression, get the bzip2 source distribution\n#  into the bzip2/ subfolder and start compilation with \"WMAKE USEBZ2=1 ...\"\n#\n# Other options to be fed to the compiler can be specified in an environment\n# variable called LOCAL_UNZIP.\n\nvariation = $(%LOCAL_UNZIP)\n\n# Stifle annoying \"Delete this file?\" questions when errors occur:\n.ERASE\n\n.EXTENSIONS:\n.EXTENSIONS: .exe .obj .obx .c .h .asm\n\n# We maintain multiple sets of object files in different directories so that\n# we can compile msdos, dos/4gw or pmode/w, and win32 versions of UnZip without\n# their object files interacting.  The following var must be a directory name\n# ending with a backslash.  All object file names must include this macro\n# at the beginning, for example \"$(O)foo.obj\".\n\n!ifdef DEBUG\nOBDIR = od32w\n!else\nOBDIR = ob32w\n!endif\nO = $(OBDIR)\\   # comment here so backslash won't continue the line\n\n!ifdef NO_LZW\ncvars = $+$(cvars)$- -DLZW_CLEAN\navars = $+$(avars)$- -DLZW_CLEAN\n# \"$+$(foo)$-\" means expand foo as it has been defined up to now; normally,\n# this Make defers inner expansion until the outer macro is expanded.\n!endif\n!ifdef OFFEND_RMS\ncvars = $+$(cvars)$- -DUSE_SMITH_CODE\navars = $+$(avars)$- -DUSE_SMITH_CODE\n!endif\n\nIZ_BZIP2 = bzip2\n!ifdef USEBZ2\ncvars = $+$(cvars)$- -DUSE_BZIP2 -I$(IZ_BZIP2)\nBZIPLIB = $(IZ_BZIP2)/$(OBDIR)/bz2.lib\nBZ2LNKLIB = lib {$(BZIPLIB)}\n!else\nBZIPLIB =\nBZ2LNKLIB =\n!endif\n\n!ifndef USE_IZTIMEZONE\n#default: do not use the IZ timezone replacement\nUSE_IZTIMEZONE=0\n!endif\n\n# The assembly hot-spot code in crc_i386.asm is optional.  This section\n# controls its usage.\n\n!ifdef NOASM\ncrcaob =\n!else   # !NOASM\ncvars = $+$(cvars)$- -DASM_CRC\ncrcaob = $(O)crc_i386.obj\n!endif\n\n!if $(USE_IZTIMEZONE) != 0\ncvars = $+$(cvars)$- -DW32_USE_IZ_TIMEZONE\nTIMEZONE_OBJU = $(O)timezone.obj\nTIMEZONE_OBJX = $(O)timezone.obx\nTIMEZONE_OBJD = $(O)timezonl.obj\nTIMEZONE_OBLX = $(O)timezolx.obj\nTIMEZONE_OBJB = $(O)timezonb.obj\n!else\nTIMEZONE_OBJU =\nTIMEZONE_OBJX =\nTIMEZONE_OBJD =\nTIMEZONE_OBLX =\nTIMEZONE_OBJB =\n!endif\n\n# Our object files.  OBJU is for UnZip, OBJX for UnZipSFX, OBJF for fUnZip:\n\nOBJU1 = $(O)unzip.obj $(O)crc32.obj $(crcaob) $(O)crypt.obj $(O)envargs.obj\nOBJU2 = $(O)explode.obj $(O)extract.obj $(O)fileio.obj $(O)globals.obj\nOBJU3 = $(O)inflate.obj $(O)list.obj $(O)match.obj $(O)process.obj\nOBJU4 = $(O)ubz2err.obj $(O)ttyio.obj $(O)unreduce.obj $(O)unshrink.obj\nOBJU5 = $(O)zipinfo.obj\nOBJUS = $(O)win32.obj $(O)win32i64.obj $(O)nt.obj $(TIMEZONE_OBJU)\nOBJU  = $(OBJU1) $(OBJU2) $(OBJU3) $(OBJU4) $(OBJU5) $(OBJUS)\n\nOBJX1 = $(O)unzip.obx $(O)crc32.obx $(crcaob) $(O)crypt.obx $(O)extract.obx\nOBJX2 = $(O)fileio.obx $(O)globals.obx $(O)inflate.obx $(O)match.obx\nOBJX3 = $(O)process.obx $(O)ttyio.obx $(O)ubz2err.obx\nOBJXS = $(O)win32.obx $(O)win32i64.obx $(O)nt.obx $(TIMEZONE_OBJX)\nOBJX  = $(OBJX1) $(OBJX2) $(OBJX3) $(OBJXS)\n\nOBJF1 = $(O)funzip.obj $(O)crc32f.obj $(crcaob) $(O)cryptf.obj\nOBJF2 = $(O)globalsf.obj $(O)inflatef.obj $(O)ttyiof.obj\nOBJFS = $(O)win32f.obj $(O)win32i64f.obj\nOBJF  = $(OBJF1) $(OBJF2) $(OBJFS)\n\nOBJD1 = $(O)api.obj $(O)crc32l.obj $(crcaob) $(O)cryptl.obj $(O)explodel.obj\nOBJD2 = $(O)extractl.obj $(O)fileiol.obj $(O)globalsl.obj $(O)inflatel.obj\nOBJD3 = $(O)listl.obj $(O)matchl.obj $(O)processl.obj $(O)ubz2errl.obj\nOBJD4 = $(O)unreducl.obj $(O)unshrnkl.obj $(O)zipinfol.obj\nOBJDS = $(O)win32l.obj $(O)win32i64l.obj $(O)ntl.obj $(O)windll.obj $(TIMEZONE_OBJD)\nOBJD  = $(OBJD1) $(OBJD2) $(OBJD3) $(OBJD4) $(OBJDS)\n\nUNZIP_H = unzip.h unzpriv.h globals.h win32/w32cfg.h\nWINDLL_H = windll/windll.h windll/decs.h windll/structs.h\nWINDLL_DEF = windll/windll32.def\nWINDLL_IMP_H = windll/decs.h windll/structs.h\n\n# Now we have to pick out the proper compiler and options for it.\n\ncc     = wcc386\nlink   = wlink\nasm    = wasm\nrc     = wrc\n# Use Pentium Pro timings, register args, static strings in code, high strictness:\ncflags = -bt=NT -6r -zt -zq -wx\naflags = -bt=NT -mf -3 -zq\nrflags = -bt=NT\nlflags = sys NT\nlflags_dll = sys NT_DLL\ncvars  = $+$(cvars)$- -DWIN32 $(variation)\navars  = $+$(avars)$- $(variation)\n\n# Specify optimizations, or a nonoptimized debugging version:\n\n!ifdef DEBUG\ncdebug = -od -d2\ncdebux = -od -d2\nldebug = d w all op symf\n!else\ncdebug = -s -obhikl+rt -oe=100 -zp8\ncdebux = -s -obhiklrs\n# -oa helps slightly but might be dangerous.\nldebug = op el\n!endif\n\nCFLAGS_FU = $(cdebug) $(cflags) $(cvars) -DFUNZIP\nCFLAGS_DL = $(cdebug) $(cflags) $(cvars) -bd -bm -DWINDLL -DDLL\n\n# How to compile sources:\n.c.obx:\n\t$(cc) $(cdebux) $(cflags) $(cvars) -DSFX $[@ -fo=$@\n\n.c.obj:\n\t$(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@\n\n# Here we go!  By default, make all targets:\nall: UnZip.exe fUnZip.exe UnZipSFX.exe\n\n# Convenient shorthand options for single targets:\nu:   UnZip.exe     .SYMBOLIC\nf:   fUnZip.exe    .SYMBOLIC\nx:   UnZipSFX.exe  .SYMBOLIC\nd:   UnZip32.dll   .SYMBOLIC\n\nUnZip.exe:\t$(OBDIR) $(OBJU) $(BZIPLIB) $(O)winapp.res\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJU)} $(BZ2LNKLIB)\n\nUnZipSFX.exe:\t$(OBDIR) $(OBJX) $(BZIPLIB)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJX)} $(BZ2LNKLIB)\n\nfUnZip.exe:\t$(OBDIR) $(OBJF)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJF)}\n\nUnZip32.dll:\t$(OBDIR) $(OBJD) $(BZIPLIB) $(O)windll.res\n\t$(link) $(lflags_dll) $(ldebug) name $@ file {$(OBJD)} $(BZ2LNKLIB)\n\t$(rc) $(rflags) $(O)windll.res $@\n\nuzexampl.exe:\t$(OBDIR) $(O)uzexampl.obj\n\t$(link) $(lflags) $(ldebug) name $@ file {$(O)uzexampl.obj} lib version.lib\n\n# Source dependencies:\n\n#       generic (UnZip, fUnZip):\n\n$(O)crc32.obj:    crc32.c $(UNZIP_H) zip.h crc32.h\n$(O)crypt.obj:    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n$(O)envargs.obj:  envargs.c $(UNZIP_H)\n$(O)explode.obj:  explode.c $(UNZIP_H)\n$(O)extract.obj:  extract.c $(UNZIP_H) crc32.h crypt.h\n$(O)fileio.obj:   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n$(O)funzip.obj:   funzip.c $(UNZIP_H) crc32.h crypt.h ttyio.h\n$(O)globals.obj:  globals.c $(UNZIP_H)\n$(O)inflate.obj:  inflate.c inflate.h $(UNZIP_H)\n$(O)list.obj:     list.c $(UNZIP_H)\n$(O)match.obj:    match.c $(UNZIP_H)\n$(O)process.obj:  process.c $(UNZIP_H) crc32.h\n$(O)timezone.obj: timezone.c $(UNZIP_H) zip.h timezone.h\n$(O)ttyio.obj:    ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n$(O)ubz2err.obj:  ubz2err.c $(UNZIP_H)\n$(O)unreduce.obj: unreduce.c $(UNZIP_H)\n$(O)unshrink.obj: unshrink.c $(UNZIP_H)\n$(O)unzip.obj:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n$(O)zipinfo.obj:  zipinfo.c $(UNZIP_H)\n\n#       UnZipSFX variants:\n\n$(O)crc32.obx:    crc32.c $(UNZIP_H) zip.h crc32.h\n$(O)crypt.obx:    crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n$(O)extract.obx:  extract.c $(UNZIP_H) crc32.h crypt.h\n$(O)fileio.obx:   fileio.c $(UNZIP_H) crc32.h crypt.h ttyio.h ebcdic.h\n$(O)globals.obx:  globals.c $(UNZIP_H)\n$(O)inflate.obx:  inflate.c inflate.h $(UNZIP_H)\n$(O)match.obx:    match.c $(UNZIP_H)\n$(O)process.obx:  process.c $(UNZIP_H) crc32.h\n$(O)timezone.obx: timezone.c $(UNZIP_H) zip.h timezone.h\n$(O)ttyio.obx:    ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n$(O)ubz2err.obx:  ubz2err.c $(UNZIP_H)\n$(O)unzip.obx:    unzip.c $(UNZIP_H) crypt.h unzvers.h consts.h\n\n# Special case object files:\n\n$(O)win32.obj:    win32\\win32.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32.c -fo=$@\n\n$(O)win32.obx:    win32\\win32.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(cdebux) $(cflags) $(cvars) -DSFX win32\\win32.c -fo=$@\n\n$(O)win32i64.obj: win32\\win32i64.c $(UNZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32i64.c -fo=$@\n\n$(O)win32i64.obx: win32\\win32i64.c $(UNZIP_H)\n\t$(cc) $(cdebux) $(cflags) $(cvars) -DSFX win32\\win32i64.c -fo=$@\n\n$(O)nt.obj:    win32\\nt.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\nt.c -fo=$@\n\n$(O)nt.obx:    win32\\nt.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(cdebux) $(cflags) $(cvars) -DSFX win32\\nt.c -fo=$@\n\n$(O)crc_i386.obj: win32\\crc_i386.asm\n\t$(asm) $(aflags) $(avars) win32\\crc_i386.asm -fo=$@\n\n$(O)winapp.res:\twin32\\winapp.rc unzvers.h\n\t$(rc) $(rflags) /r /fo=$@ /dWIN32 win32\\winapp.rc\n\n# Variant object files for fUnZip:\n\n$(O)crc32f.obj:   crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(cc) $(CFLAGS_FU) crc32.c -fo=$@\n\n$(O)cryptf.obj:   crypt.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(cc) $(CFLAGS_FU) crypt.c -fo=$@\n\n$(O)globalsf.obj: globals.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_FU) globals.c -fo=$@\n\n$(O)inflatef.obj: inflate.c inflate.h $(UNZIP_H) crypt.h\n\t$(cc) $(CFLAGS_FU) inflate.c -fo=$@\n\n$(O)ttyiof.obj:   ttyio.c $(UNZIP_H) zip.h crypt.h ttyio.h\n\t$(cc) $(CFLAGS_FU) ttyio.c -fo=$@\n\n$(O)win32f.obj:   win32\\win32.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_FU) win32\\win32.c -fo=$@\n\n$(O)win32i64f.obj: win32\\win32i64.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_FU) win32\\win32i64.c -fo=$@\n\n# DLL compilation section\n$(O)api.obj:      api.c $(UNZIP_H) $(WINDLL_H) unzvers.h\n\t$(cc) $(CFLAGS_DL) api.c -fo=$@\n$(O)crc32l.obj:   crc32.c $(UNZIP_H) zip.h crc32.h\n\t$(cc) $(CFLAGS_DL) crc32.c -fo=$@\n$(O)cryptl.obj:   crypt.c $(UNZIP_H) zip.h crypt.h crc32.h ttyio.h\n\t$(cc) $(CFLAGS_DL) crypt.c -fo=$@\n$(O)explodel.obj: explode.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) explode.c -fo=$@\n$(O)extractl.obj: extract.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h\n\t$(cc) $(CFLAGS_DL) extract.c -fo=$@\n$(O)fileiol.obj:  fileio.c $(UNZIP_H) $(WINDLL_H) crc32.h crypt.h ttyio.h ebcdic.h\n\t$(cc) $(CFLAGS_DL) fileio.c -fo=$@\n$(O)globalsl.obj: globals.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) globals.c -fo=$@\n$(O)inflatel.obj: inflate.c inflate.h $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) inflate.c -fo=$@\n$(O)listl.obj:\t  list.c $(UNZIP_H) $(WINDLL_H)\n\t$(cc) $(CFLAGS_DL) list.c -fo=$@\n$(O)matchl.obj:\t  match.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) match.c -fo=$@\n$(O)processl.obj: process.c $(UNZIP_H) $(WINDLL_H) crc32.h\n\t$(cc) $(CFLAGS_DL) process.c -fo=$@\n$(O)timezonl.obj: timezone.c $(UNZIP_H) zip.h timezone.h\n\t$(cc) $(CFLAGS_DL) timezone.c -fo=$@\n$(O)ubz2errl.obj: ubz2err.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) ubz2err.c -fo=$@\n$(O)unreducl.obj: unreduce.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) unreduce.c -fo=$@\n$(O)unshrnkl.obj: unshrink.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) unshrink.c -fo=$@\n$(O)zipinfol.obj: zipinfo.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) zipinfo.c -fo=$@\n\n$(O)win32l.obj:\t  win32\\win32.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(CFLAGS_DL) -I. win32\\win32.c -fo=$@\n\n$(O)win32i64l.obj: win32\\win32i64.c $(UNZIP_H)\n\t$(cc) $(CFLAGS_DL) -I. win32\\win32i64.c -fo=$@\n\n$(O)ntl.obj:      win32\\nt.c $(UNZIP_H) win32\\nt.h\n\t$(cc) $(CFLAGS_DL) -I. win32\\nt.c -fo=$@\n\n$(O)windll.obj:   windll\\windll.c $(UNZIP_H) $(WINDLL_H)\n$(O)windll.obj:   crypt.h unzvers.h consts.h\n\t$(cc) $(CFLAGS_DL) -I. windll\\windll.c -fo=$@\n\n$(O)windll.res:\twindll\\windll.rc unzvers.h\n\t$(rc) $(rflags) /r /fo=$@ /i=windll /dWIN32 windll\\windll.rc\n\n# Windll command line example:\n$(O)uzexampl.obj: windll/uzexampl.c windll/uzexampl.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) windll\\uzexampl.c -fo=$@\n\n# The bzip2 (de)compression library for BZIP2 support:\n$(IZ_BZIP2)/$(OBDIR)/bz2.lib : .ALWAYS .RECHECK\n\t$(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat CC=$(cc) AR=lib386 &\n\tCFLSYS=\"$(cdebug) $(cflags)\" &\n\tBZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)/$(OBDIR)\n\n# Creation of subdirectory for intermediate files\n$(OBDIR):\n\t-mkdir $@\n\n# Unwanted file removal:\n\nclean_bz2_lib: .SYMBOLIC\n\t-$(MAKE) -h -f $(IZ_BZIP2)/makbz2iz.wat &\n\tBZROOTDIR=$(IZ_BZIP2) BZOBDIR=$(IZ_BZIP2)\\$(OBDIR) clean\n\nclean:     clean_bz2_lib  .SYMBOLIC\n\tdel $(O)*.ob?\n\tdel $(O)*.res\n\ncleaner:   clean  .SYMBOLIC\n\tdel UnZip.exe\n\tdel fUnZip.exe\n\tdel UnZipSFX.exe\n\tdel UnZip32.dll\n\tdel uzexampl.exe\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/crc_i386.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_i386.asm, optimized CRC calculation function for Zip and UnZip,\n; created by Paul Kienitz and Christian Spieler.  Last revised 07 Jan 2007.\n;\n; Revised 06-Oct-96, Scott Field (sfield@microsoft.com)\n;   fixed to assemble with masm by not using .model directive which makes\n;   assumptions about segment alignment.  Also,\n;   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather\n;   than lodsb, and other misc. changes resulting in the following performance\n;   increases:\n;\n;      unrolled loops                NO_UNROLLED_LOOPS\n;      *8    >8      <8              *8      >8      <8\n;\n;      +54%  +42%    +35%            +82%    +52%    +25%\n;\n;   first item in each table is input buffer length, even multiple of 8\n;   second item in each table is input buffer length, > 8\n;   third item in each table is input buffer length, < 8\n;\n; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n;   Incorporated Rodney Brown's 32-bit-reads optimization as found in the\n;   UNIX AS source crc_i386.S. This new code can be disabled by defining\n;   the macro symbol NO_32_BIT_LOADS.\n;\n; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n;   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs\n;   (like the Pentium Pro, Pentium II, and probably some Pentium clones).\n;   This optimization is controlled by the macro symbol __686 and is disabled\n;   by default. (This default is based on the assumption that most users\n;   do not yet work on a Pentium Pro or Pentium II machine ...)\n;\n; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro)\n;   Working without .model directive caused tasm32 version 5.0 to produce\n;   bad object code. The optimized alignments can be optionally disabled\n;   by defining NO_ALIGN, thus allowing to use .model flat. There is no need\n;   to define this macro if using other versions of tasm.\n;\n; Revised 16-Jan-2005, Cosmin Truta (cosmint@cs.ubbcluj.ro)\n;   Enabled the 686 build by default, because there are hardly any pre-686 CPUs\n;   in serious use nowadays. (See the 12-Oct-97 note above.)\n;\n; Revised 03-Jan-2006, Chr. Spieler\n;   Enlarged unrolling loops to \"do 16 bytes per turn\"; optimized access to\n;   data buffer in loop body (adjust pointer only once in loop body and use\n;   offsets to access each item); added additional support for the \"unfolded\n;   tables\" optimization variant (enabled by IZ_CRCOPTIM_UNFOLDTBL).\n;\n; Revised 07-Jan-2007, Chr. Spieler\n;   Recognize additional conditional flag CRC_TABLE_ONLY that prevents\n;   compilation of the crc32() function.\n;\n; FLAT memory model assumed.\n;\n; Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n; This results in shorter code at the expense of reduced performance.\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used,\n; or only the precomputed CRC_32_Table is needed.\n;\n    IFNDEF USE_ZLIB\n    IFNDEF CRC_TABLE_ONLY\n;\n        .386p\n        name    crc_i386\n\n    IFDEF NO_ALIGN\n        .model flat\n    ENDIF\n\n    IFNDEF PRE_686\n    IFNDEF __686\n__686   EQU     1 ; optimize for Pentium Pro, Pentium II and compatible CPUs\n    ENDIF\n    ENDIF\n\nextrn   _get_crc_table:near    ; ZCONST ulg near *get_crc_table(void);\n\n;\n    IFNDEF NO_STD_STACKFRAME\n        ; Use a `standard' stack frame setup on routine entry and exit.\n        ; Actually, this option is set as default, because it results\n        ; in smaller code !!\nSTD_ENTRY       MACRO\n                push    ebp\n                mov     ebp,esp\n        ENDM\n\n        Arg1    EQU     08H[ebp]\n        Arg2    EQU     0CH[ebp]\n        Arg3    EQU     10H[ebp]\n\nSTD_LEAVE       MACRO\n                pop     ebp\n        ENDM\n\n    ELSE  ; NO_STD_STACKFRAME\n\nSTD_ENTRY       MACRO\n        ENDM\n\n        Arg1    EQU     18H[esp]\n        Arg2    EQU     1CH[esp]\n        Arg3    EQU     20H[esp]\n\nSTD_LEAVE       MACRO\n        ENDM\n\n    ENDIF ; ?NO_STD_STACKFRAME\n\n; These two (three) macros make up the loop body of the CRC32 cruncher.\n; registers modified:\n;   eax  : crc value \"c\"\n;   esi  : pointer to next data byte (or dword) \"buf++\"\n; registers read:\n;   edi  : pointer to base of crc_table array\n; scratch registers:\n;   ebx  : index into crc_table array\n;          (requires upper three bytes = 0 when __686 is undefined)\n    IFNDEF  __686 ; optimize for 386, 486, Pentium\nDo_CRC  MACRO\n                mov     bl,al                ; tmp = c & 0xFF\n                shr     eax,8                ; c = (c >> 8)\n                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]\n        ENDM\n    ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs\nDo_CRC  MACRO\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                shr     eax,8                  ; c = (c >> 8)\n                xor     eax,[edi+ebx*4]        ;  ^ table[tmp]\n        ENDM\n    ENDIF ; ?__686\nDo_CRC_byte     MACRO\n                xor     al, byte ptr [esi]     ; c ^= *buf\n                inc     esi                    ; buf++\n                Do_CRC                         ; c = (c >> 8) ^ table[c & 0xFF]\n        ENDM\nDo_CRC_byteof   MACRO   ofs\n                xor     al, byte ptr [esi+ofs] ; c ^= *(buf+ofs)\n                Do_CRC                         ; c = (c >> 8) ^ table[c & 0xFF]\n        ENDM\n    IFNDEF  NO_32_BIT_LOADS\n      IFDEF IZ_CRCOPTIM_UNFOLDTBL\n        ; the edx register is needed in crc calculation\n        SavLen  EQU     Arg3\n\nUpdCRC_dword    MACRO\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                mov     edx,[edi+ebx*4+3072]   ;  table[256*3+tmp]\n                movzx   ebx,ah                 ; tmp = (c>>8) & 0xFF\n                shr     eax,16                 ;\n                xor     edx,[edi+ebx*4+2048]   ;  ^ table[256*2+tmp]\n                movzx   ebx,al                 ; tmp = (c>>16) & 0xFF\n                shr     eax,8                  ; tmp = (c>>24)\n                xor     edx,[edi+ebx*4+1024]   ;  ^ table[256*1+tmp]\n                mov     eax,[edi+eax*4]        ;  ^ table[256*0+tmp]\n                xor     eax,edx                ; ..\n        ENDM\nUpdCRC_dword_sh MACRO   dwPtrIncr\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                mov     edx,[edi+ebx*4+3072]   ;  table[256*3+tmp]\n                movzx   ebx,ah                 ; tmp = (c>>8) & 0xFF\n                xor     edx,[edi+ebx*4+2048]   ;  ^ table[256*2+tmp]\n                shr     eax,16                 ;\n                movzx   ebx,al                 ; tmp = (c>>16) & 0xFF\n                add     esi, 4*dwPtrIncr       ; ((ulg *)buf) += dwPtrIncr\n                shr     eax,8                  ; tmp = (c>>24)\n                xor     edx,[edi+ebx*4+1024]   ;  ^ table[256*1+tmp]\n                mov     eax,[edi+eax*4]        ;  ^ table[256*0+tmp]\n                xor     eax,edx                ; ..\n        ENDM\n      ELSE ; IZ_CRCOPTIM_UNFOLDTBL\n        ; the edx register is not needed anywhere else\n        SavLen  EQU     edx\n\nUpdCRC_dword    MACRO\n                Do_CRC\n                Do_CRC\n                Do_CRC\n                Do_CRC\n        ENDM\nUpdCRC_dword_sh MACRO   dwPtrIncr\n                Do_CRC\n                Do_CRC\n                add     esi, 4*dwPtrIncr       ; ((ulg *)buf) += dwPtrIncr\n                Do_CRC\n                Do_CRC\n        ENDM\n      ENDIF ; ?IZ_CRCOPTIM_UNFOLDTBL\nDo_CRC_dword    MACRO\n                xor     eax, dword ptr [esi]   ; c ^= *(ulg *)buf\n                UpdCRC_dword_sh 1              ; ... ((ulg *)buf)++\n        ENDM\nDo_CRC_4dword   MACRO\n                xor     eax, dword ptr [esi]    ; c ^= *(ulg *)buf\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+4]  ; c ^= *((ulg *)buf+1)\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+8]  ; c ^= *((ulg *)buf+2)\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+12] ; c ^= *((ulg *)buf]+3\n                UpdCRC_dword_sh\t4               ; ... ((ulg *)buf)+=4\n        ENDM\n    ENDIF ; !NO_32_BIT_LOADS\n\n    IFNDEF NO_ALIGN\n_TEXT   segment use32 para public 'CODE'\n    ELSE\n_TEXT   segment use32\n    ENDIF\n        assume  CS: _TEXT\n\n        public  _crc32\n_crc32          proc    near  ; ulg crc32(ulg crc, ZCONST uch *buf, extent len)\n                STD_ENTRY\n                push    edi\n                push    esi\n                push    ebx\n                push    edx\n                push    ecx\n\n                mov     esi,Arg2            ; 2nd arg: uch *buf\n                sub     eax,eax             ;> if (!buf)\n                test    esi,esi             ;>   return 0;\n                jz      fine                ;> else {\n\n                call    _get_crc_table\n                mov     edi,eax\n                mov     eax,Arg1            ; 1st arg: ulg crc\n    IFNDEF __686\n                sub     ebx,ebx             ; ebx=0; make bl usable as a dword\n    ENDIF\n                mov     ecx,Arg3            ; 3rd arg: extent len\n                not     eax                 ;>   c = ~crc;\n\n                test    ecx,ecx\n    IFNDEF  NO_UNROLLED_LOOPS\n                jz      bail\n    IFNDEF  NO_32_BIT_LOADS\nalign_loop:\n                test    esi,3               ; align buf pointer on next\n                jz      SHORT aligned_now   ;  dword boundary\n                Do_CRC_byte\n                dec     ecx\n                jnz     align_loop\naligned_now:\n    ENDIF ; !NO_32_BIT_LOADS\n                mov     SavLen,ecx          ; save current len for later\n                shr     ecx,4               ; ecx = len / 16\n                jz      No_Sixteens\n    IFNDEF NO_ALIGN\n; align loop head at start of 486 internal cache line !!\n                align   16\n    ENDIF\nNext_Sixteen:\n    IFNDEF  NO_32_BIT_LOADS\n                Do_CRC_4dword\n    ELSE ; NO_32_BIT_LOADS\n                Do_CRC_byteof   0\n                Do_CRC_byteof   1\n                Do_CRC_byteof   2\n                Do_CRC_byteof   3\n                Do_CRC_byteof   4\n                Do_CRC_byteof   5\n                Do_CRC_byteof   6\n                Do_CRC_byteof   7\n                Do_CRC_byteof   8\n                Do_CRC_byteof   9\n                Do_CRC_byteof   10\n                Do_CRC_byteof   11\n                Do_CRC_byteof   12\n                Do_CRC_byteof   13\n                Do_CRC_byteof   14\n                Do_CRC_byteof   15\n                add     esi, 16                 ; buf += 16\n    ENDIF ; ?NO_32_BIT_LOADS\n                dec     ecx\n                jnz     Next_Sixteen\nNo_Sixteens:\n                mov     ecx,SavLen\n                and     ecx,00000000FH      ; ecx = len % 16\n    IFNDEF  NO_32_BIT_LOADS\n                shr     ecx,2               ; ecx = len / 4\n                jz      SHORT No_Fours\nNext_Four:\n                Do_CRC_dword\n                dec     ecx\n                jnz     Next_Four\nNo_Fours:\n                mov     ecx,SavLen\n                and     ecx,000000003H      ; ecx = len % 4\n    ENDIF ; !NO_32_BIT_LOADS\n    ENDIF ; !NO_UNROLLED_LOOPS\n                jz      SHORT bail          ;>   if (len)\n    IFNDEF NO_ALIGN\n; align loop head at start of 486 internal cache line !!\n                align   16\n    ENDIF\nloupe:                                      ;>     do {\n                Do_CRC_byte                 ;        c = CRC32(c,*buf++,crctab);\n                dec     ecx                 ;>     } while (--len);\n                jnz     loupe\n\nbail:                                       ;> }\n                not     eax                 ;> return ~c;\nfine:\n                pop     ecx\n                pop     edx\n                pop     ebx\n                pop     esi\n                pop     edi\n                STD_LEAVE\n                ret\n_crc32          endp\n\n_TEXT   ends\n;\n    ENDIF ; !CRC_TABLE_ONLY\n    ENDIF ; !USE_ZLIB\n;\nend\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/crc_i386.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm\n * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.\n * Last revised: 07-Jan-2007\n *\n * Original coded (in crc_i386.asm) and put into the public domain\n * by Paul Kienitz and Christian Spieler.\n *\n * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)\n *   fixed to assemble with masm by not using .model directive which makes\n *   assumptions about segment alignment.  Also,\n *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather\n *   than lodsb, and other misc. changes resulting in the following performance\n *   increases:\n *\n *      unrolled loops                NO_UNROLLED_LOOPS\n *      *8    >8      <8              *8      >8      <8\n *\n *      +54%  +42%    +35%            +82%    +52%    +25%\n *\n *   first item in each table is input buffer length, even multiple of 8\n *   second item in each table is input buffer length, > 8\n *   third item in each table is input buffer length, < 8\n *\n * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the\n *   UNIX AS source crc_i386.S. This new code can be disabled by defining\n *   the macro symbol NO_32_BIT_LOADS.\n *\n * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs\n *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).\n *   This optimization is controlled by the macro symbol __686 and is disabled\n *   by default. (This default is based on the assumption that most users\n *   do not yet work on a Pentium Pro or Pentium II machine ...)\n *\n * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++\n *   32-bit, removed unneeded kludge for potentially unknown movzx mnemonic,\n *   confirmed correct working with MS VC++ (32-bit).\n *\n * Revised 22-May-98, Peter Kunath, Chr. Spieler: The 16-Nov-97 revision broke\n *   MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its\n *   own __asm {...} construct.  For MSVC, a \"#pragma warning\" was added to\n *   shut up the \"no return value\" warning message.\n *\n * Revised 13-Dec-98, Chr. Spieler: Modified path to \"zip.h\" header file.\n *\n * Revised 16-Jan-2005, Cosmin Truta: Added the ASM_CRC guard, for easier\n *   switching between ASM vs. non-ASM builds, when handling makefiles.\n *   Also enabled the 686 build by default, because there are hardly any\n *   pre-686 CPUs in serious use nowadays. (See the 12-Oct-97 note above.)\n *\n * Revised 03-Jan-2006, Chr. Spieler\n *   Enlarged unrolling loops to \"do 16 bytes per turn\"; optimized access to\n *   data buffer in loop body (adjust pointer only once in loop body and use\n *   offsets to access each item); added additional support for the \"unfolded\n *   tables\" optimization variant (enabled by IZ_CRCOPTIM_UNFOLDTBL).\n *\n * Revised 07-Jan-2007, Chr. Spieler\n *   Recognize additional conditional flag CRC_TABLE_ONLY that prevents\n *   compilation of the crc32() function.\n *\n * FLAT memory model assumed.\n *\n * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n * This results in shorter code at the expense of reduced performance.\n *\n */\n\n#include \"../zip.h\"\n#include \"../crc32.h\"\n\n#if defined(ASM_CRC) && !defined(USE_ZLIB) && !defined(CRC_TABLE_ONLY)\n\n#if !defined(PRE_686) && !defined(__686)\n#  define __686\n#endif\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n/* Select wether the following inline-assember code is supported. */\n#if (defined(_MSC_VER) && _MSC_VER >= 700)\n#if (defined(_M_IX86) && _M_IX86 >= 300)\n#  define MSC_INLINE_ASM_32BIT_SUPPORT\n   /* Disable warning for no return value, typical of asm functions */\n#  pragma warning( disable : 4035 )\n#endif\n#endif\n\n#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)\n#  define MSC_INLINE_ASM_32BIT_SUPPORT\n#endif\n\n#ifdef MSC_INLINE_ASM_32BIT_SUPPORT\n/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */\n\n/*\n * These two (three) macros make up the loop body of the CRC32 cruncher.\n * registers modified:\n *   eax  : crc value \"c\"\n *   esi  : pointer to next data byte (or dword) \"buf++\"\n * registers read:\n *   edi  : pointer to base of crc_table array\n * scratch registers:\n *   ebx  : index into crc_table array\n *          (requires upper three bytes = 0 when __686 is undefined)\n */\n#ifndef __686\n#define Do_CRC { \\\n  __asm { mov   bl, al }; \\\n  __asm { shr   eax, 8 }; \\\n  __asm { xor   eax, [edi+ebx*4] }; }\n#else /* __686 */\n#define Do_CRC { \\\n  __asm { movzx ebx, al }; \\\n  __asm { shr   eax, 8  }; \\\n  __asm { xor   eax, [edi+ebx*4] }; }\n#endif /* ?__686 */\n\n#define Do_CRC_byte { \\\n  __asm { xor   al, byte ptr [esi] }; \\\n  __asm { inc   esi }; \\\n  Do_CRC; }\n\n#define Do_CRC_byteof(ofs) { \\\n  __asm { xor   al, byte ptr [esi+(ofs)] }; \\\n  Do_CRC; }\n\n#ifndef NO_32_BIT_LOADS\n#ifdef IZ_CRCOPTIM_UNFOLDTBL\n# define SavLen  len            /* the edx register is needed elsewhere */\n# define UpdCRC_dword { \\\n   __asm { movzx   ebx,al }; \\\n   __asm { mov     edx,[edi+ebx*4+3072] }; \\\n   __asm { movzx   ebx,ah }; \\\n   __asm { shr     eax,16 }; \\\n   __asm { xor     edx,[edi+ebx*4+2048] }; \\\n   __asm { movzx   ebx,al }; \\\n   __asm { shr     eax,8 }; \\\n   __asm { xor     edx,[edi+ebx*4+1024] }; \\\n   __asm { mov     eax,[edi+eax*4] }; \\\n   __asm { xor     eax,edx }; }\n# define UpdCRC_dword_sh(dwPtrIncr) { \\\n   __asm { movzx   ebx,al }; \\\n   __asm { mov     edx,[edi+ebx*4+3072] }; \\\n   __asm { movzx   ebx,ah }; \\\n   __asm { xor     edx,[edi+ebx*4+2048] }; \\\n   __asm { shr     eax,16 }; \\\n   __asm { movzx   ebx,al }; \\\n   __asm { add     esi, 4*dwPtrIncr }; \\\n   __asm { shr     eax,8 }; \\\n   __asm { xor     edx,[edi+ebx*4+1024] }; \\\n   __asm { mov     eax,[edi+eax*4] }; \\\n   __asm { xor     eax,edx }; }\n#else /* !IZ_CRCOPTIM_UNFOLDTBL */\n# define SavLen  edx            /* the edx register is free for use here */\n# define UpdCRC_dword { \\\n    Do_CRC; \\\n    Do_CRC; \\\n    Do_CRC; \\\n    Do_CRC; }\n# define UpdCRC_dword_sh(dwPtrIncr) { \\\n    Do_CRC; \\\n    Do_CRC; \\\n    __asm { add   esi, 4*(dwPtrIncr) }; \\\n    Do_CRC; \\\n    Do_CRC; }\n#endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n\n#define Do_CRC_dword { \\\n  __asm { xor   eax, dword ptr [esi] }; \\\n  UpdCRC_dword_sh(1); }\n\n#define Do_CRC_4dword { \\\n  __asm { xor   eax, dword ptr [esi] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+4] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+8] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+12] }; \\\n  UpdCRC_dword_sh(4); }\n#endif /* !NO_32_BIT_LOADS */\n\n/* ========================================================================= */\nulg crc32(crc, buf, len)\n    ulg crc;                    /* crc shift register */\n    ZCONST uch *buf;            /* pointer to bytes to pump through */\n    extent len;                 /* number of bytes in buf[] */\n/* Run a set of bytes through the crc shift register.  If buf is a NULL\n   pointer, then initialize the crc shift register contents instead.\n   Return the current crc in either case. */\n{\n    __asm {\n                push    edx\n                push    ecx\n\n                mov     esi,buf         ;/* 2nd arg: uch *buf              */\n                sub     eax,eax         ;/*> if (!buf)                     */\n                test    esi,esi         ;/*>   return 0;                   */\n                jz      fine            ;/*> else {                        */\n\n                call    get_crc_table\n                mov     edi,eax\n                mov     eax,crc         ;/* 1st arg: ulg crc               */\n#ifndef __686\n                sub     ebx,ebx         ;/* ebx=0; => bl usable as a dword */\n#endif\n                mov     ecx,len         ;/* 3rd arg: extent len            */\n                not     eax             ;/*>   c = ~crc;                   */\n\n                test    ecx,ecx\n#ifndef NO_UNROLLED_LOOPS\n                jz      bail\n#  ifndef NO_32_BIT_LOADS\nalign_loop:\n                test    esi,3           ;/* align buf pointer on next      */\n                jz      aligned_now     ;/*  dword boundary                */\n    }\n                Do_CRC_byte             ;\n    __asm {\n                dec     ecx\n                jnz     align_loop\naligned_now:\n#  endif /* !NO_32_BIT_LOADS */\n                mov     SavLen,ecx      ;/* save current len for later  */\n                shr     ecx,4           ;/* ecx = len / 16    */\n                jz      No_Sixteens\n; align loop head at start of 486 internal cache line !!\n                align   16\nNext_Sixteen:\n    }\n#  ifndef NO_32_BIT_LOADS\n                Do_CRC_4dword ;\n#  else /* NO_32_BIT_LOADS */\n                Do_CRC_byteof(0) ;\n                Do_CRC_byteof(1) ;\n                Do_CRC_byteof(2) ;\n                Do_CRC_byteof(3) ;\n                Do_CRC_byteof(4) ;\n                Do_CRC_byteof(5) ;\n                Do_CRC_byteof(6) ;\n                Do_CRC_byteof(7) ;\n                Do_CRC_byteof(8) ;\n                Do_CRC_byteof(9) ;\n                Do_CRC_byteof(10) ;\n                Do_CRC_byteof(11) ;\n                Do_CRC_byteof(12) ;\n                Do_CRC_byteof(13) ;\n                Do_CRC_byteof(14) ;\n                Do_CRC_byteof(15) ;\n    __asm {     add     esi,16 };\n#  endif /* ?NO_32_BIT_LOADS */\n    __asm {\n                dec     ecx\n                jnz     Next_Sixteen\nNo_Sixteens:\n                mov     ecx,SavLen\n                and     ecx,00000000FH  ;/* ecx = len % 16    */\n#  ifndef NO_32_BIT_LOADS\n                shr     ecx,2\n                jz      No_Fours\nNext_Four:\n    }\n                Do_CRC_dword ;\n    __asm {\n                dec     ecx\n                jnz     Next_Four\nNo_Fours:\n                mov     ecx,SavLen\n                and     ecx,000000003H  ;/* ecx = len % 4    */\n#  endif /* !NO_32_BIT_LOADS */\n#endif /* !NO_UNROLLED_LOOPS */\n                jz      bail            ;/*>  if (len)                       */\n; align loop head at start of 486 internal cache line !!\n                align   16\nloupe:                                  ;/*>    do {                         */\n    }\n                Do_CRC_byte             ;/*       c = CRC32(c,*buf++,crctab);*/\n    __asm {\n                dec     ecx             ;/*>    } while (--len);             */\n                jnz     loupe\n\nbail:                                   ;/*> }                               */\n                not     eax             ;/*> return ~c;                      */\nfine:\n                pop     ecx\n                pop     edx\n    }\n#ifdef NEED_RETURN\n    return _EAX;\n#endif\n}\n#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */\n#if (defined(_MSC_VER) && _MSC_VER >= 700)\n#if (defined(_M_IX86) && _M_IX86 >= 300)\n   /* Reenable missing return value warning */\n#  pragma warning( default : 4035 )\n#endif\n#endif\n#endif /* ASM_CRC && !USE_ZLIB && !CRC_TABLE_ONLY */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/crc_lcc.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2006 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip,\n; created by Paul Kienitz and Christian Spieler.  Last revised 02 Jan 2006.\n;\n; The code in this file has been copied verbatim from crc_i386.{asm|S};\n; only the assembler syntax and metacommands have been adapted to\n; the habits of the free LCC-Win32 C compiler package.\n; This version of the code uses the \"optimized for i686\" variant of\n; crc_i386.{asm|S}.\n; IMPORTANT NOTE to the Info-ZIP editors:\n; The TAB characters in this source file are required by the parser of\n; the LCC-Win32 assembler program and MUST NOT be removed!!\n;\n; For more information (and a revision log), look into the original\n; source files.\n;\n\t.text\n\t.file \"crc32.c\"\n\t.text\n\t.type\t_crc32,function\n_crc32:\n\tpushl\t%ebp\n\tmovl\t%esp,%ebp\n\tpushl\t%ecx\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\t.line\t34\n\t.line\t37\n\tmovl\t12(%ebp),%esi\n\tsubl\t%eax,%eax\n\ttestl\t%esi,%esi\n\tjz\t_$3\n\t.line\t39\n\tcall\t_get_crc_table\n\tmovl\t%eax,%edi\n\t.line\t41\n\tmovl\t8(%ebp),%eax\n\tmovl\t16(%ebp),%ecx\n\tnotl\t%eax\n\ttestl\t%ecx,%ecx\n\tjz\t_$4\n_$5:\n\ttestl\t$3,%esi\n\tjz\t_$6\n\txorb    (%esi),%al\n\tincl\t%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$5\n_$6:\n\tmovl\t%ecx,%edx\n\tshrl\t$4,%ecx\n\tjz\t_$8\n_$7:\n\txorl\t(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t4(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t8(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t12(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\taddl\t$16,%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$7\n_$8:\n\tmovl\t%edx,%ecx\n\tandl\t$0x0f,%ecx\n        shrl\t$2,%ecx\n\tjz\t_$10\n_$9:\n\txorl\t(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\taddl\t$4,%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$9\n_$10:\n\tmovl\t%edx,%ecx\n\tandl\t$0x03,%ecx\n\tjz\t_$4\n_$11:\n\txorb    (%esi),%al\n\tincl    %esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$11\n_$4:\n\txorl\t$0xffffffff,%eax\n_$3:\n\t.line\t52\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tleave\n\tret\n_$34:\n\t.size\t_crc32,_$34-_crc32\n\t.globl\t_crc32\n\t.extern\t_get_crc_table\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/nt.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n\n  Copyright (c) 1996  Scott Field (dedicated to Info-Zip group)\n\n  Module Name:\n\n    nt.c\n\n  Abstract:\n\n    This module implements WinNT security descriptor operations for the\n    Win32 Info-ZIP project.  Operation such as setting file security,\n    using/querying local and remote privileges, and queuing of operations\n    is performed here.  The contents of this module are only relevant\n    when the code is running on Windows NT, and the target volume supports\n    persistent Acl storage.\n\n    User privileges that allow accessing certain privileged aspects of the\n    security descriptor (such as the Sacl) are only used if the user specified\n    to do so.\n\n  Author:\n\n    Scott Field (sfield@microsoft.com)\n\n  Last revised:  18 Jan 97\n\n */\n\n#define WIN32_LEAN_AND_MEAN\n#define UNZIP_INTERNAL\n#include \"../unzip.h\"\n\n#ifdef CR\n#undef CR\n#endif\n\n#include <windows.h>\n#ifdef __RSXNT__\n#  include \"../win32/rsxntwin.h\"\n#endif\n#include \"../win32/nt.h\"\n\n\n#ifdef NTSD_EAS         /* This file is only needed for NTSD handling */\n\n/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */\n#ifndef FILE_SHARE_DELETE\n#  define FILE_SHARE_DELETE 0x00000004\n#endif\n\n/* This macro definition is missing in old versions of MS' winbase.h. */\n#ifndef InterlockedExchangePointer\n#  define InterlockedExchangePointer(Target, Value) \\\n      (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))\n#endif\n\n\n/* private prototypes */\n\nstatic BOOL Initialize(VOID);\nstatic VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);\nstatic VOID InitLocalPrivileges(VOID);\n\n\nvolatile BOOL bInitialized = FALSE; /* module level stuff initialized? */\nHANDLE hInitMutex = NULL;           /* prevent multiple initialization */\n\nBOOL g_bRestorePrivilege = FALSE;   /* for local set file security override */\nBOOL g_bSaclPrivilege = FALSE;      /* for local set sacl operations, only when\n                                       restore privilege not present */\n\n/* our single cached volume capabilities structure that describes the last\n   volume root we encountered.  A single entry like this works well in the\n   zip/unzip scenario for a number of reasons:\n   1. typically one extraction path during unzip.\n   2. typically process one volume at a time during zip, and then move\n      on to the next.\n   3. no cleanup code required and no memory leaks.\n   4. simple code.\n\n   This approach should be reworked to a linked list approach if we expect to\n   be called by many threads which are processing a variety of input/output\n   volumes, since lock contention and stale data may become a bottleneck. */\n\nVOLUMECAPS g_VolumeCaps;\nCRITICAL_SECTION VolumeCapsLock;\n\n\nstatic BOOL Initialize(VOID)\n{\n    HANDLE hMutex;\n    HANDLE hOldMutex;\n\n    if (bInitialized) return TRUE;\n\n    hMutex = CreateMutex(NULL, TRUE, NULL);\n    if(hMutex == NULL) return FALSE;\n\n    hOldMutex = (HANDLE)InterlockedExchangePointer((void *)&hInitMutex,\n                                                   hMutex);\n\n    if (hOldMutex != NULL) {\n        /* somebody setup the mutex already */\n        InterlockedExchangePointer((void *)&hInitMutex,\n                                   hOldMutex);\n\n        CloseHandle(hMutex); /* close new, un-needed mutex */\n\n        /* wait for initialization to complete and return status */\n        WaitForSingleObject(hOldMutex, INFINITE);\n        ReleaseMutex(hOldMutex);\n\n        return bInitialized;\n    }\n\n    if (!bInitialized) {\n        /* initialize module level resources */\n\n        InitializeCriticalSection( &VolumeCapsLock );\n        memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));\n\n        InitLocalPrivileges();\n\n        bInitialized = TRUE;\n    }\n\n    InterlockedExchangePointer((void *)&hInitMutex,\n                               NULL);\n\n    ReleaseMutex(hMutex); /* release correct mutex */\n\n    CloseHandle(hMutex);  /* free the no longer needed handle resource */\n\n    return TRUE;\n}\n\n\nBOOL ValidateSecurity(uch *securitydata)\n{\n    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;\n    PACL pAcl;\n    PSID pSid;\n    BOOL bAclPresent;\n    BOOL bDefaulted;\n\n    if(!IsWinNT()) return TRUE; /* don't do anything if not on WinNT */\n\n    if(!IsValidSecurityDescriptor(sd)) return FALSE;\n\n    /* verify Dacl integrity */\n\n    if(!GetSecurityDescriptorDacl(sd, &bAclPresent, &pAcl, &bDefaulted))\n        return FALSE;\n\n    if(bAclPresent && pAcl!=NULL) {\n        if(!IsValidAcl(pAcl)) return FALSE;\n    }\n\n    /* verify Sacl integrity */\n\n    if(!GetSecurityDescriptorSacl(sd, &bAclPresent, &pAcl, &bDefaulted))\n        return FALSE;\n\n    if(bAclPresent && pAcl!=NULL) {\n        if(!IsValidAcl(pAcl)) return FALSE;\n    }\n\n    /* verify owner integrity */\n\n    if(!GetSecurityDescriptorOwner(sd, &pSid, &bDefaulted))\n        return FALSE;\n\n    if(pSid != NULL) {\n        if(!IsValidSid(pSid)) return FALSE;\n    }\n\n    /* verify group integrity */\n\n    if(!GetSecurityDescriptorGroup(sd, &pSid, &bDefaulted))\n        return FALSE;\n\n    if(pSid != NULL) {\n        if(!IsValidSid(pSid)) return FALSE;\n    }\n\n    return TRUE;\n}\n\nstatic VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)\n{\n    HANDLE hFile;\n\n    *dwRemotePrivileges = 0;\n\n    /* see if we have the SeRestorePrivilege */\n\n    hFile = CreateFileA(\n        FileName,\n        ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,\n        FILE_SHARE_READ | FILE_SHARE_DELETE, /* no sd updating allowed here */\n        NULL,\n        OPEN_EXISTING,\n        FILE_FLAG_BACKUP_SEMANTICS,\n        NULL\n        );\n\n    if(hFile != INVALID_HANDLE_VALUE) {\n        /* no remote way to determine SeRestorePrivilege -- just try a\n           read/write to simulate it */\n        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION |\n          SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION |\n          GROUP_SECURITY_INFORMATION;\n        PSECURITY_DESCRIPTOR sd;\n        DWORD cbBuf = 0;\n\n        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);\n\n        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {\n            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {\n                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {\n                    if(SetKernelObjectSecurity(hFile, si, sd))\n                        *dwRemotePrivileges |= OVERRIDE_RESTORE;\n                }\n                HeapFree(GetProcessHeap(), 0, sd);\n            }\n        }\n\n        CloseHandle(hFile);\n    } else {\n\n        /* see if we have the SeSecurityPrivilege */\n        /* note we don't need this if we have SeRestorePrivilege */\n\n        hFile = CreateFileA(\n            FileName,\n            ACCESS_SYSTEM_SECURITY,\n            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* max */\n            NULL,\n            OPEN_EXISTING,\n            0,\n            NULL\n            );\n\n        if(hFile != INVALID_HANDLE_VALUE) {\n            CloseHandle(hFile);\n            *dwRemotePrivileges |= OVERRIDE_SACL;\n        }\n    }\n}\n\n\nBOOL GetVolumeCaps(\n    char *rootpath,         /* filepath, or NULL */\n    char *name,             /* filename associated with rootpath */\n    PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */\n    )\n{\n    char TempRootPath[MAX_PATH + 1];\n    DWORD cchTempRootPath = 0;\n    BOOL bSuccess = TRUE;   /* assume success until told otherwise */\n\n    if(!bInitialized) if(!Initialize()) return FALSE;\n\n    /* process the input path to produce a consistent path suitable for\n       compare operations and also suitable for certain picky Win32 API\n       that don't like forward slashes */\n\n    if(rootpath != NULL && rootpath[0] != '\\0') {\n        DWORD i;\n\n        cchTempRootPath = lstrlenA(rootpath);\n        if(cchTempRootPath > MAX_PATH) return FALSE;\n\n        /* copy input, converting forward slashes to back slashes as we go */\n\n        for(i = 0 ; i <= cchTempRootPath ; i++) {\n            if(rootpath[i] == '/') TempRootPath[i] = '\\\\';\n            else TempRootPath[i] = rootpath[i];\n        }\n\n        /* check for UNC and Null terminate or append trailing \\ as\n           appropriate */\n\n        /* possible valid UNCs we are passed follow:\n           \\\\machine\\foo\\bar (path is \\\\machine\\foo\\)\n           \\\\machine\\foo     (path is \\\\machine\\foo\\)\n           \\\\machine\\foo\\\n           \\\\.\\c$\\     (FIXFIX: Win32API doesn't like this - GetComputerName())\n           LATERLATER: handling mounted DFS drives in the future will require\n                       slightly different logic which isn't available today.\n                       This is required because directories can point at\n                       different servers which have differing capabilities.\n         */\n\n        if(TempRootPath[0] == '\\\\' && TempRootPath[1] == '\\\\') {\n            DWORD slash = 0;\n\n            for(i = 2 ; i < cchTempRootPath ; i++) {\n                if(TempRootPath[i] == '\\\\') {\n                    slash++;\n\n                    if(slash == 2) {\n                        i++;\n                        TempRootPath[i] = '\\0';\n                        cchTempRootPath = i;\n                        break;\n                    }\n                }\n            }\n\n            /* if there was only one slash found, just tack another onto the\n               end */\n\n            if(slash == 1 && TempRootPath[cchTempRootPath] != '\\\\') {\n                TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\\\\' */\n                TempRootPath[cchTempRootPath+1] = '\\0';\n                cchTempRootPath++;\n            }\n\n        } else {\n\n            if(TempRootPath[1] == ':') {\n\n                /* drive letter specified, truncate to root */\n                TempRootPath[2] = '\\\\';\n                TempRootPath[3] = '\\0';\n                cchTempRootPath = 3;\n            } else {\n\n                /* must be file on current drive */\n                TempRootPath[0] = '\\0';\n                cchTempRootPath = 0;\n            }\n\n        }\n\n    } /* if path != NULL */\n\n    /* grab lock protecting cached entry */\n    EnterCriticalSection( &VolumeCapsLock );\n\n    if(!g_VolumeCaps.bValid ||\n       lstrcmpiA(g_VolumeCaps.RootPath, TempRootPath) != 0)\n    {\n\n        /* no match found, build up new entry */\n\n        DWORD dwFileSystemFlags;\n        DWORD dwRemotePrivileges = 0;\n        BOOL bRemote = FALSE;\n\n        /* release lock during expensive operations */\n        LeaveCriticalSection( &VolumeCapsLock );\n\n        bSuccess = GetVolumeInformationA(\n            (TempRootPath[0] == '\\0') ? NULL : TempRootPath,\n            NULL, 0,\n            NULL, NULL,\n            &dwFileSystemFlags,\n            NULL, 0);\n\n\n        /* only if target volume supports Acls, and we were told to use\n           privileges do we need to go out and test for the remote case */\n\n        if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) &&\n           VolumeCaps->bUsePrivileges)\n        {\n            if(GetDriveTypeA( (TempRootPath[0] == '\\0') ? NULL : TempRootPath )\n               == DRIVE_REMOTE)\n            {\n                bRemote = TRUE;\n\n                /* make a determination about our remote capabilities */\n\n                GetRemotePrivilegesSet(name, &dwRemotePrivileges);\n            }\n        }\n\n        /* always take the lock again, since we release it below */\n        EnterCriticalSection( &VolumeCapsLock );\n\n        /* replace the existing data if successful */\n        if(bSuccess) {\n\n            lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);\n            g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;\n            g_VolumeCaps.bRemote = bRemote;\n            g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;\n            g_VolumeCaps.bValid = TRUE;\n        }\n    }\n\n    if(bSuccess) {\n        /* copy input elements */\n        g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;\n        g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;\n\n        /* give caller results */\n        memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));\n    } else {\n        g_VolumeCaps.bValid = FALSE;\n    }\n\n    LeaveCriticalSection( &VolumeCapsLock ); /* release lock */\n\n    return bSuccess;\n}\n\n\nBOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)\n{\n    HANDLE hFile;\n    DWORD dwDesiredAccess = 0;\n    DWORD dwFlags = 0;\n    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)securitydata;\n    SECURITY_DESCRIPTOR_CONTROL sdc;\n    SECURITY_INFORMATION RequestedInfo = 0;\n    DWORD dwRev;\n    BOOL bRestorePrivilege = FALSE;\n    BOOL bSaclPrivilege = FALSE;\n    BOOL bSuccess;\n\n    if(!bInitialized) if(!Initialize()) return FALSE;\n\n    /* defer directory processing */\n\n    if(VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n        /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */\n        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;\n    }\n\n    /* evaluate the input security descriptor and act accordingly */\n\n    if(!IsValidSecurityDescriptor(sd))\n        return FALSE;\n\n    if(!GetSecurityDescriptorControl(sd, &sdc, &dwRev))\n        return FALSE;\n\n    /* setup privilege usage based on if told we can use privileges, and if so,\n       what privileges we have */\n\n    if(VolumeCaps->bUsePrivileges) {\n        if(VolumeCaps->bRemote) {\n            /* use remotely determined privileges */\n            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_RESTORE)\n                bRestorePrivilege = TRUE;\n\n            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)\n                bSaclPrivilege = TRUE;\n\n        } else {\n            /* use local privileges */\n            bRestorePrivilege = g_bRestorePrivilege;\n            bSaclPrivilege = g_bSaclPrivilege;\n        }\n    }\n\n\n    /* if a Dacl is present write Dacl out */\n    /* if we have SeRestorePrivilege, write owner and group info out */\n\n    if(sdc & SE_DACL_PRESENT) {\n        dwDesiredAccess |= WRITE_DAC;\n        RequestedInfo |= DACL_SECURITY_INFORMATION;\n\n        if(bRestorePrivilege) {\n            dwDesiredAccess |= WRITE_OWNER;\n            RequestedInfo |= (OWNER_SECURITY_INFORMATION |\n              GROUP_SECURITY_INFORMATION);\n        }\n    }\n\n    /* if a Sacl is present and we have either SeRestorePrivilege or\n       SeSystemSecurityPrivilege try to write Sacl out */\n\n    if((sdc & SE_SACL_PRESENT) && (bRestorePrivilege || bSaclPrivilege)) {\n        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;\n        RequestedInfo |= SACL_SECURITY_INFORMATION;\n    }\n\n    if(RequestedInfo == 0)  /* nothing to do */\n        return FALSE;\n\n    if(bRestorePrivilege)\n        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;\n\n    hFile = CreateFileA(\n        resource,\n        dwDesiredAccess,\n        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,/* max sharing */\n        NULL,\n        OPEN_EXISTING,\n        dwFlags,\n        NULL\n        );\n\n    if(hFile == INVALID_HANDLE_VALUE)\n        return FALSE;\n\n    bSuccess = SetKernelObjectSecurity(hFile, RequestedInfo, sd);\n\n    CloseHandle(hFile);\n\n    return bSuccess;\n}\n\nstatic VOID InitLocalPrivileges(VOID)\n{\n    HANDLE hToken;\n    TOKEN_PRIVILEGES tp;\n\n    /* try to enable some interesting privileges that give us the ability\n       to get some security information that we normally cannot.\n\n       note that enabling privileges is only relevant on the local machine;\n       when accessing files that are on a remote machine, any privileges\n       that are present on the remote machine get enabled by default. */\n\n    if(!OpenProcessToken(GetCurrentProcess(),\n        TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))\n        return;\n\n    tp.PrivilegeCount = 1;\n    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\n\n    if(LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tp.Privileges[0].Luid)) {\n\n        /* try to enable SeRestorePrivilege; if this succeeds, we can write\n           all aspects of the security descriptor */\n\n        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&\n           GetLastError() == ERROR_SUCCESS) g_bRestorePrivilege = TRUE;\n\n    }\n\n    /* try to enable SeSystemSecurityPrivilege, if SeRestorePrivilege not\n       present; if this succeeds, we can write the Sacl */\n\n    if(!g_bRestorePrivilege &&\n        LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {\n\n        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&\n           GetLastError() == ERROR_SUCCESS) g_bSaclPrivilege = TRUE;\n    }\n\n    CloseHandle(hToken);\n}\n#endif /* NTSD_EAS */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/nt.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* nt.h:  central header for EF_NTSD \"SD\" extra field */\n\n#ifndef _NT_H\n#define _NT_H\n\n#define NTSD_BUFFERSIZE (1024)  /* threshold to cause malloc() */\n#define OVERRIDE_BACKUP     1   /* we have SeBackupPrivilege on remote */\n#define OVERRIDE_RESTORE    2   /* we have SeRestorePrivilege on remote */\n#define OVERRIDE_SACL       4   /* we have SeSystemSecurityPrivilege on remote */\n\ntypedef struct {\n    BOOL bValid;                /* are our contents valid? */\n    BOOL bUsePrivileges;        /* use privilege overrides? */\n    DWORD dwFileSystemFlags;    /* describes target file system */\n    BOOL bRemote;               /* is volume remote? */\n    DWORD dwRemotePrivileges;   /* relevant only on remote volumes */\n    DWORD dwFileAttributes;\n    char RootPath[MAX_PATH+1];  /* path to network / filesystem */\n} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;\n\nBOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);\nBOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);\nBOOL ValidateSecurity(uch *securitydata);\n\n#endif /* _NT_H */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/rsxntwin.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* rsxntwin.h\n *\n * fills some gaps in the rsxnt 1.3 win32 header files (<windows.h>) that are\n * required for compiling Info-ZIP sources for Win NT / Win 95\n */\n\n#ifdef __RSXNT__\n#if !defined (_RSXNTWIN_H)\n#define _RSXNTWIN_H\n\n#ifdef TFUNCT   /* TFUNCT is undefined when MSSDK headers are used */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define PASCAL __stdcall\n\n#define ANYSIZE_ARRAY 1\n\n#ifndef TIME_ZONE_ID_UNKNOWN\n#  define TIME_ZONE_ID_UNKNOWN  0\n#endif\n#ifndef TIME_ZONE_ID_INVALID\n#  define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL\n#endif\n\n#define FILE_ATTRIBUTE_HIDDEN   0x00000002\n#define FILE_ATTRIBUTE_SYSTEM   0x00000004\n\n#define FILE_SHARE_DELETE       0x00000004\n\n#define FILE_PERSISTENT_ACLS    0x00000008\n\n#define HFILE_ERROR        ((HFILE)-1)\n\n#define FS_PERSISTENT_ACLS      FILE_PERSISTENT_ACLS\n\n\nBOOL WINAPI DosDateTimeToFileTime(WORD, WORD, LPFILETIME);\n\n\n#ifndef SetVolumeLabel\n#define SetVolumeLabel TFUNCT(SetVolumeLabel)\n#endif\nBOOL WINAPI SetVolumeLabel(LPCTSTR, LPCTSTR);\n\n\n#ifndef GetDriveType\n#define GetDriveType TFUNCT(GetDriveType)\n#endif\nDWORD GetDriveType(LPCTSTR);\n\n#define DRIVE_UNKNOWN     0\n#define DRIVE_REMOVABLE   2\n#define DRIVE_FIXED       3\n#define DRIVE_REMOTE      4\n#define DRIVE_CDROM       5\n#define DRIVE_RAMDISK     6\n\n#ifndef SearchPath\n#define SearchPath TFUNCT(SearchPath)\n#endif\nBOOL WINAPI SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, UINT, LPTSTR, LPTSTR *);\n\n#define ERROR_SUCCESS                   0\n#define ERROR_INSUFFICIENT_BUFFER       122\n\nLONG WINAPI InterlockedExchange(LPLONG, LONG);\n\n#define ACCESS_SYSTEM_SECURITY          0x01000000L\n\ntypedef PVOID PSECURITY_DESCRIPTOR;\ntypedef PVOID PSID;\ntypedef struct _ACL {\n    BYTE  AclRevision;\n    BYTE  Sbz1;\n    WORD   AclSize;\n    WORD   AceCount;\n    WORD   Sbz2;\n} ACL;\ntypedef ACL *PACL;\n\ntypedef struct _LUID {\n    DWORD LowPart;\n    LONG HighPart;\n} LUID, *PLUID;\n\ntypedef struct _LUID_AND_ATTRIBUTES {\n    LUID Luid;\n    DWORD Attributes;\n    } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;\n\ntypedef struct _TOKEN_PRIVILEGES {\n    DWORD PrivilegeCount;\n    LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];\n} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;\n\n#define TOKEN_QUERY             0x0008\n#define TOKEN_ADJUST_PRIVILEGES 0x0020\n\nBOOL WINAPI OpenProcessToken(HANDLE, DWORD, PHANDLE);\nBOOL WINAPI AdjustTokenPrivileges(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD,\n                PTOKEN_PRIVILEGES, PDWORD);\n\n#ifndef LookupPrivilegeValue\n#define LookupPrivilegeValue TFUNCT(LookupPrivilegeValue)\n#endif\nBOOL WINAPI LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);\n\ntypedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION;\n#define OWNER_SECURITY_INFORMATION      0x00000001L\n#define GROUP_SECURITY_INFORMATION      0x00000002L\n#define DACL_SECURITY_INFORMATION       0x00000004L\n#define SACL_SECURITY_INFORMATION       0x00000008L\n\ntypedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;\n#define SE_DACL_PRESENT         0x0004\n#define SE_SACL_PRESENT         0x0010\n\n#define SE_PRIVILEGE_ENABLED    0x00000002L\n\n#define SE_SECURITY_NAME                  TEXT(\"SeSecurityPrivilege\")\n#define SE_BACKUP_NAME                    TEXT(\"SeBackupPrivilege\")\n#define SE_RESTORE_NAME                   TEXT(\"SeRestorePrivilege\")\n\nBOOL WINAPI GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,\n                PSECURITY_DESCRIPTOR, DWORD, LPDWORD);\nBOOL WINAPI SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,\n                PSECURITY_DESCRIPTOR);\nBOOL WINAPI IsValidSid(PSID);\nBOOL WINAPI IsValidAcl(PACL);\nBOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR);\nBOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);\nDWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR);\nBOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,\n                PSECURITY_DESCRIPTOR_CONTROL, LPDWORD);\nBOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,\n                SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL);\nBOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,\n                                      LPBOOL, PACL *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);\nBOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,\n                                      LPBOOL, PACL *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);\nBOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, BOOL);\nBOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, BOOL);\nVOID WINAPI InitializeCriticalSection();\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* TFUNCT */\n#endif /* !defined (_RSXNTWIN_H) */\n#endif /* __RSXNT__ */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/bz2lib.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"bz2lib\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** NICHT BEARBEITEN **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=bz2lib - Win32 Debug\n!MESSAGE Dies ist kein gltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE\n!MESSAGE verwenden Sie den Befehl \"Makefile exportieren\" und fhren Sie den Befehl\n!MESSAGE \n!MESSAGE NMAKE /f \"bz2lib.mak\".\n!MESSAGE \n!MESSAGE Sie knnen beim Ausfhren von NMAKE eine Konfiguration angeben\n!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:\n!MESSAGE \n!MESSAGE NMAKE /f \"bz2lib.mak\" CFG=\"bz2lib - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Fr die Konfiguration stehen zur Auswahl:\n!MESSAGE \n!MESSAGE \"bz2lib - Win32 Release\" (basierend auf  \"Win32 (x86) Static Library\")\n!MESSAGE \"bz2lib - Win32 Debug\" (basierend auf  \"Win32 (x86) Static Library\")\n!MESSAGE \"bz2lib - Win32 ASM Release\" (basierend auf  \"Win32 (x86) Static Library\")\n!MESSAGE \"bz2lib - Win32 ASM Debug\" (basierend auf  \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"bz2lib - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"bz2lib__Win32_Release\"\n# PROP BASE Intermediate_Dir \"bz2lib__Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"bz2lib__Win32_Release\"\n# PROP Intermediate_Dir \"bz2lib__Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /Oy- /D \"NDEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /c\n# SUBTRACT CPP /YX /Yc /Yu\n# ADD BASE RSC /l 0x407 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"bz2lib__Win32_Release\\bz2.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"bz2lib - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"bz2lib__Win32_Debug\"\n# PROP BASE Intermediate_Dir \"bz2lib__Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"bz2lib__Win32_Debug\"\n# PROP Intermediate_Dir \"bz2lib__Win32_Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_MBCS\" /D \"_LIB\" /YX /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /GZ /c\n# SUBTRACT CPP /YX /Yc /Yu\n# ADD BASE RSC /l 0x407 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"bz2lib__Win32_Debug\\bz2.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"bz2lib - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"bz2lib___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"bz2lib___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"bz2lib__Win32_Release\"\n# PROP Intermediate_Dir \"bz2lib__Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /Oy- /D \"NDEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /c\n# SUBTRACT BASE CPP /YX /Yc /Yu\n# ADD CPP /nologo /W3 /GX /O2 /Oy- /D \"NDEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /c\n# SUBTRACT CPP /YX /Yc /Yu\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo /out:\"bz2lib__Win32_Release\\bz2.lib\"\n# ADD LIB32 /nologo /out:\"bz2lib__Win32_Release\\bz2.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"bz2lib - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"bz2lib___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"bz2lib___Win32_ASM_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"bz2lib__Win32_Debug\"\n# PROP Intermediate_Dir \"bz2lib__Win32_Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /GZ /c\n# SUBTRACT BASE CPP /YX /Yc /Yu\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_MBCS\" /D \"_LIB\" /D \"BZ_NO_STDIO\" /FD /GZ /c\n# SUBTRACT CPP /YX /Yc /Yu\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo /out:\"bz2lib__Win32_Debug\\bz2.lib\"\n# ADD LIB32 /nologo /out:\"bz2lib__Win32_Debug\\bz2.lib\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"bz2lib - Win32 Release\"\n# Name \"bz2lib - Win32 Debug\"\n# Name \"bz2lib - Win32 ASM Release\"\n# Name \"bz2lib - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\blocksort.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\bzlib.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\compress.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\crctable.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\decompress.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\huffman.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\randtable.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\bzlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\bzlib_private.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/funzip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"funzip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=funzip - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"funzip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"funzip.mak\" CFG=\"funzip - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"funzip - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"funzip - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"funzip - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"funzip - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"funzip - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"funzip___Win32_Release\"\n# PROP BASE Intermediate_Dir \"funzip___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"funzip___Win32_Release\"\n# PROP Intermediate_Dir \"funzip___Win32_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"funzip - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"funzip___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"funzip___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"funzip___Win32_Debug\"\n# PROP Intermediate_Dir \"funzip___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"funzip - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"funzip___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"funzip___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"funzip___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"funzip___Win32_ASM_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"FUNZIP\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"funzip - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"funzip___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"funzip___Win32_ASM_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"funzip___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"funzip___Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"FUNZIP\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"funzip - Win32 Release\"\n# Name \"funzip - Win32 Debug\"\n# Name \"funzip - Win32 ASM Release\"\n# Name \"funzip - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\funzip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\w32cfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/unzip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unzip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=unzip - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzip.mak\" CFG=\"unzip - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzip - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzip - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzip - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzip - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unzip - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzip__Win32_Release\"\n# PROP BASE Intermediate_Dir \"unzip__Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzip__Win32_Release\"\n# PROP Intermediate_Dir \"unzip__Win32_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"unzip - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzip__Win32_Debug\"\n# PROP BASE Intermediate_Dir \"unzip__Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzip__Win32_Debug\"\n# PROP Intermediate_Dir \"unzip__Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unzip - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzip__Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"unzip__Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzip__Win32_ASM_Release\"\n# PROP Intermediate_Dir \"unzip__Win32_ASM_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"unzip - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzip__Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"unzip__Win32_ASM_Debug\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzip__Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"unzip__Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzip - Win32 Release\"\n# Name \"unzip - Win32 Debug\"\n# Name \"unzip - Win32 ASM Release\"\n# Name \"unzip - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\envargs.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipinfo.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\w32cfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/unzip.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"bz2lib\"=\".\\bz2lib.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"funzip\"=\".\\funzip.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unzip\"=\".\\unzip.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unzipbz2\"=\".\\unzipbz2.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name bz2lib\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"unzipsfx\"=\".\\unzipsfx.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/unzipbz2.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unzipbz2\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=unzipbz2 - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipbz2.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipbz2.mak\" CFG=\"unzipbz2 - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzipbz2 - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipbz2 - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipbz2 - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipbz2 - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unzipbz2 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzipbz2__Win32_Release\"\n# PROP BASE Intermediate_Dir \"unzipbz2__Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzipbz2__Win32_Release\"\n# PROP Intermediate_Dir \"unzipbz2__Win32_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386 /out:\"unzipbz2__Win32_Release/unzip.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"unzipbz2 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzipbz2__Win32_Debug\"\n# PROP BASE Intermediate_Dir \"unzipbz2__Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzipbz2__Win32_Debug\"\n# PROP Intermediate_Dir \"unzipbz2__Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /out:\"unzipbz2__Win32_Debug/unzip.exe\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unzipbz2 - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzipbz2__Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"unzipbz2__Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzipbz2__Win32_ASM_Release\"\n# PROP Intermediate_Dir \"unzipbz2__Win32_ASM_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386 /out:\"unzipbz2__Win32_ASM_Release/unzip.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"unzipbz2 - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzipbz2__Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"unzipbz2__Win32_ASM_Debug\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzipbz2__Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"unzipbz2__Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /out:\"unzipbz2__Win32_ASM_Debug/unzip.exe\" /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzipbz2 - Win32 Release\"\n# Name \"unzipbz2 - Win32 Debug\"\n# Name \"unzipbz2 - Win32 ASM Release\"\n# Name \"unzipbz2 - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\envargs.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipinfo.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\w32cfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc6/unzipsfx.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unzipsfx\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=unzipsfx - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipsfx.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipsfx.mak\" CFG=\"unzipsfx - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzipsfx - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipsfx - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipsfx - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"unzipsfx - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unzipsfx - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzipsfx___Win32_Release\"\n# PROP BASE Intermediate_Dir \"unzipsfx___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzipsfx___Win32_Release\"\n# PROP Intermediate_Dir \"unzipsfx___Win32_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O1 /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"unzipsfx - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzipsfx___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"unzipsfx___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzipsfx___Win32_Debug\"\n# PROP Intermediate_Dir \"unzipsfx___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unzipsfx - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"unzipsfx___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"unzipsfx___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"unzipsfx___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"unzipsfx___Win32_ASM_Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"SFX\" /FD /c\n# ADD CPP /nologo /W3 /GX /O1 /D \"NDEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"unzipsfx - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"unzipsfx___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"unzipsfx___Win32_ASM_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"unzipsfx___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"unzipsfx___Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"SFX\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzipsfx - Win32 Release\"\n# Name \"unzipsfx - Win32 Debug\"\n# Name \"unzipsfx - Win32 ASM Release\"\n# Name \"unzipsfx - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\w32cfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/bz2lib.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"bz2lib\"\n\tProjectGUID=\"{80CD1B7E-762B-4C1F-99E9-DCED59936BEE}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\bz2lib__Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\bz2lib__Win32_Debug\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;_LIB;BZ_NO_STDIO\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\bz2lib__Win32_Debug/bz2lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"bz2lib__Win32_Debug\\bz2.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tOutputFile=\".\\bz2lib__Win32_Debug/bz2lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\bz2lib__Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\bz2lib__Win32_Release\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;_LIB;BZ_NO_STDIO\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\bz2lib__Win32_Release/bz2lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tObjectFile=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"bz2lib__Win32_Release\\bz2.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tOutputFile=\".\\bz2lib__Win32_Release/bz2lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\bz2lib__Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\bz2lib__Win32_Debug\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;_LIB;BZ_NO_STDIO\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\bz2lib__Win32_Debug/bz2lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\bz2lib__Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"bz2lib__Win32_Debug\\bz2.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tOutputFile=\".\\bz2lib__Win32_Debug/bz2lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\bz2lib__Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\bz2lib__Win32_Release\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;_LIB;BZ_NO_STDIO\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\bz2lib__Win32_Release/bz2lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tObjectFile=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\bz2lib__Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"bz2lib__Win32_Release\\bz2.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tOutputFile=\".\\bz2lib__Win32_Release/bz2lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\blocksort.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\bzlib.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\compress.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\crctable.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\decompress.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\huffman.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\randtable.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\bzlib.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\bzip2\\bzlib_private.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/bz2lib.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{80CD1B7E-762B-4C1F-99E9-DCED59936BEE}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>StaticLibrary</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\bz2lib__Win32_Debug\\</OutDir>\n    <IntDir>.\\bz2lib__Win32_Debug\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\bz2lib__Win32_Release\\</OutDir>\n    <IntDir>.\\bz2lib__Win32_Release\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\bz2lib__Win32_Debug\\</OutDir>\n    <IntDir>.\\bz2lib__Win32_Debug\\</IntDir>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\bz2lib__Win32_Release\\</OutDir>\n    <IntDir>.\\bz2lib__Win32_Release\\</IntDir>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;_LIB;BZ_NO_STDIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\bz2lib__Win32_Debug/bz2lib.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\bz2lib__Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\bz2lib__Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\bz2lib__Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Lib>\n      <OutputFile>bz2lib__Win32_Debug\\bz2.lib</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Lib>\n    <Bscmake>\n      <OutputFile>.\\bz2lib__Win32_Debug/bz2lib.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;_LIB;BZ_NO_STDIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\bz2lib__Win32_Release/bz2lib.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\bz2lib__Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\bz2lib__Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\bz2lib__Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Lib>\n      <OutputFile>bz2lib__Win32_Release\\bz2.lib</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Lib>\n    <Bscmake>\n      <OutputFile>.\\bz2lib__Win32_Release/bz2lib.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;_LIB;BZ_NO_STDIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\bz2lib__Win32_Debug/bz2lib.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\bz2lib__Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\bz2lib__Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\bz2lib__Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Lib>\n      <OutputFile>bz2lib__Win32_Debug\\bz2.lib</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Lib>\n    <Bscmake>\n      <OutputFile>.\\bz2lib__Win32_Debug/bz2lib.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;_LIB;BZ_NO_STDIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\bz2lib__Win32_Release/bz2lib.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\bz2lib__Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\bz2lib__Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\bz2lib__Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Lib>\n      <OutputFile>bz2lib__Win32_Release\\bz2.lib</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </Lib>\n    <Bscmake>\n      <OutputFile>.\\bz2lib__Win32_Release/bz2lib.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\bzip2\\blocksort.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\bzlib.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\compress.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\crctable.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\decompress.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\huffman.c\" />\n    <ClCompile Include=\"..\\..\\bzip2\\randtable.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\bzip2\\bzlib.h\" />\n    <ClInclude Include=\"..\\..\\bzip2\\bzlib_private.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/funzip.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"funzip\"\n\tProjectGUID=\"{F9251B3E-AC94-467B-877B-9FD9CE1F6D17}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\funzip___Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\funzip___Win32_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\funzip___Win32_Debug/funzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;FUNZIP;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\funzip___Win32_Debug/funzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\funzip___Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\funzip___Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\funzip___Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_Debug/funzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\funzip___Win32_Debug/funzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_Debug/funzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\funzip___Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\funzip___Win32_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\funzip___Win32_Release/funzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"WIN32;FUNZIP;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\funzip___Win32_Release/funzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\funzip___Win32_Release/\"\n\t\t\t\tObjectFile=\".\\funzip___Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\funzip___Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_Release/funzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\funzip___Win32_Release/funzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_Release/funzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\funzip___Win32_ASM_Debug\"\n\t\t\tIntermediateDirectory=\".\\funzip___Win32_ASM_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\funzip___Win32_ASM_Debug/funzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;FUNZIP;ASM_CRC;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\funzip___Win32_ASM_Debug/funzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\funzip___Win32_ASM_Debug/\"\n\t\t\t\tObjectFile=\".\\funzip___Win32_ASM_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\funzip___Win32_ASM_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_ASM_Debug/funzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\funzip___Win32_ASM_Debug/funzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_ASM_Debug/funzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\funzip___Win32_ASM_Release\"\n\t\t\tIntermediateDirectory=\".\\funzip___Win32_ASM_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\funzip___Win32_ASM_Release/funzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;FUNZIP;ASM_CRC;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\funzip___Win32_ASM_Release/funzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\funzip___Win32_ASM_Release/\"\n\t\t\t\tObjectFile=\".\\funzip___Win32_ASM_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\funzip___Win32_ASM_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_ASM_Release/funzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\funzip___Win32_ASM_Release/funzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\funzip___Win32_ASM_Release/funzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\crc_i386.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\funzip.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzpriv.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\w32cfg.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/funzip.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{F9251B3E-AC94-467B-877B-9FD9CE1F6D17}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\funzip___Win32_Debug\\</OutDir>\n    <IntDir>.\\funzip___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\funzip___Win32_Release\\</OutDir>\n    <IntDir>.\\funzip___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\funzip___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\funzip___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\funzip___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\funzip___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\funzip___Win32_Debug/funzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;FUNZIP;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\funzip___Win32_Debug/funzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\funzip___Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\funzip___Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\funzip___Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\funzip___Win32_Debug/funzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\funzip___Win32_Debug/funzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\funzip___Win32_Debug/funzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\funzip___Win32_Release/funzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>WIN32;FUNZIP;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\funzip___Win32_Release/funzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\funzip___Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\funzip___Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\funzip___Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\funzip___Win32_Release/funzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\funzip___Win32_Release/funzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\funzip___Win32_Release/funzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\funzip___Win32_ASM_Debug/funzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;FUNZIP;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\funzip___Win32_ASM_Debug/funzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\funzip___Win32_ASM_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\funzip___Win32_ASM_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\funzip___Win32_ASM_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\funzip___Win32_ASM_Debug/funzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\funzip___Win32_ASM_Debug/funzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\funzip___Win32_ASM_Debug/funzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\funzip___Win32_ASM_Release/funzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;FUNZIP;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\funzip___Win32_ASM_Release/funzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\funzip___Win32_ASM_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\funzip___Win32_ASM_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\funzip___Win32_ASM_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\funzip___Win32_ASM_Release/funzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\funzip___Win32_ASM_Release/funzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\funzip___Win32_ASM_Release/funzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\crc_i386.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\funzip.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\inflate.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\globals.h\" />\n    <ClInclude Include=\"..\\..\\inflate.h\" />\n    <ClInclude Include=\"..\\nt.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\..\\unzip.h\" />\n    <ClInclude Include=\"..\\..\\unzpriv.h\" />\n    <ClInclude Include=\"..\\w32cfg.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzip.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 2013\nVisualStudioVersion = 12.0.30110.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unzip\", \"unzip.vcxproj\", \"{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tASM Debug|Win32 = ASM Debug|Win32\n\t\tASM Release|Win32 = ASM Release|Win32\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}.Release|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzip.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unzip\"\n\tProjectGUID=\"{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzip__Win32_ASM_Release\"\n\t\t\tIntermediateDirectory=\".\\unzip__Win32_ASM_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzip__Win32_ASM_Release/unzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;ASM_CRC;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzip__Win32_ASM_Release/unzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzip__Win32_ASM_Release/\"\n\t\t\t\tObjectFile=\".\\unzip__Win32_ASM_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzip__Win32_ASM_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_ASM_Release/unzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzip__Win32_ASM_Release/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_ASM_Release/unzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzip__Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\unzip__Win32_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzip__Win32_Release/unzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzip__Win32_Release/unzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzip__Win32_Release/\"\n\t\t\t\tObjectFile=\".\\unzip__Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzip__Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_Release/unzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzip__Win32_Release/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_Release/unzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzip__Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzip__Win32_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzip__Win32_Debug/unzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzip__Win32_Debug/unzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzip__Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\unzip__Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzip__Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_Debug/unzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzip__Win32_Debug/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_Debug/unzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzip__Win32_ASM_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzip__Win32_ASM_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzip__Win32_ASM_Debug/unzip.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;ASM_CRC;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzip__Win32_ASM_Debug/unzip.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzip__Win32_ASM_Debug/\"\n\t\t\t\tObjectFile=\".\\unzip__Win32_ASM_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzip__Win32_ASM_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_ASM_Debug/unzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzip__Win32_ASM_Debug/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzip__Win32_ASM_Debug/unzip.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\crc_i386.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\envargs.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\explode.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\extract.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\fileio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\list.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\match.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\process.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ubz2err.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unreduce.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unshrink.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32i64.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zipinfo.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\consts.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ebcdic.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzpriv.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzvers.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\w32cfg.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzip.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{BCBD96B1-A86D-415C-9BF7-AC8EEEC669A2}</ProjectGuid>\n    <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\unzip__Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\unzip__Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\unzip__Win32_Release\\</OutDir>\n    <IntDir>.\\unzip__Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\unzip__Win32_Debug\\</OutDir>\n    <IntDir>.\\unzip__Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\unzip__Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\unzip__Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzip__Win32_ASM_Release/unzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzip__Win32_ASM_Release/unzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzip__Win32_ASM_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzip__Win32_ASM_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzip__Win32_ASM_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzip__Win32_ASM_Release/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzip__Win32_ASM_Release/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzip__Win32_ASM_Release/unzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzip__Win32_Release/unzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzip__Win32_Release/unzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzip__Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzip__Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzip__Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzip__Win32_Release/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzip__Win32_Release/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzip__Win32_Release/unzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzip__Win32_Debug/unzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzip__Win32_Debug/unzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzip__Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzip__Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzip__Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzip__Win32_Debug/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzip__Win32_Debug/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzip__Win32_Debug/unzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzip__Win32_ASM_Debug/unzip.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzip__Win32_ASM_Debug/unzip.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzip__Win32_ASM_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzip__Win32_ASM_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzip__Win32_ASM_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzip__Win32_ASM_Debug/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzip__Win32_ASM_Debug/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzip__Win32_ASM_Debug/unzip.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\crc_i386.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\envargs.c\" />\n    <ClCompile Include=\"..\\..\\explode.c\" />\n    <ClCompile Include=\"..\\..\\extract.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\inflate.c\" />\n    <ClCompile Include=\"..\\..\\list.c\" />\n    <ClCompile Include=\"..\\..\\match.c\" />\n    <ClCompile Include=\"..\\nt.c\" />\n    <ClCompile Include=\"..\\..\\process.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\..\\ubz2err.c\" />\n    <ClCompile Include=\"..\\..\\unreduce.c\" />\n    <ClCompile Include=\"..\\..\\unshrink.c\" />\n    <ClCompile Include=\"..\\..\\unzip.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\..\\zipinfo.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\consts.h\" />\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\..\\globals.h\" />\n    <ClInclude Include=\"..\\..\\inflate.h\" />\n    <ClInclude Include=\"..\\nt.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\..\\unzip.h\" />\n    <ClInclude Include=\"..\\..\\unzpriv.h\" />\n    <ClInclude Include=\"..\\..\\unzvers.h\" />\n    <ClInclude Include=\"..\\w32cfg.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzipbz2.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unzipbz2\"\n\tProjectGUID=\"{226D352D-7B6E-44CB-A12C-BB04AE14BE88}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzipbz2__Win32_ASM_Release\"\n\t\t\tIntermediateDirectory=\".\\unzipbz2__Win32_ASM_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipbz2__Win32_ASM_Release/unzipbz2.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../bzip2\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;ASM_CRC;USE_BZIP2;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipbz2__Win32_ASM_Release/unzipbz2.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipbz2__Win32_ASM_Release/\"\n\t\t\t\tObjectFile=\".\\unzipbz2__Win32_ASM_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipbz2__Win32_ASM_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\"unzipbz2__Win32_ASM_Release/unzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipbz2__Win32_ASM_Release/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipbz2__Win32_ASM_Release/unzipbz2.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzipbz2__Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\unzipbz2__Win32_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipbz2__Win32_Release/unzipbz2.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../bzip2\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;USE_BZIP2;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipbz2__Win32_Release/unzipbz2.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipbz2__Win32_Release/\"\n\t\t\t\tObjectFile=\".\\unzipbz2__Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipbz2__Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\"unzipbz2__Win32_Release/unzip.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipbz2__Win32_Release/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipbz2__Win32_Release/unzipbz2.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzipbz2__Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzipbz2__Win32_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipbz2__Win32_Debug/unzipbz2.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../bzip2\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;USE_BZIP2;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipbz2__Win32_Debug/unzipbz2.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipbz2__Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\unzipbz2__Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipbz2__Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\"unzipbz2__Win32_Debug/unzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipbz2__Win32_Debug/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipbz2__Win32_Debug/unzipbz2.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzipbz2__Win32_ASM_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzipbz2__Win32_ASM_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipbz2__Win32_ASM_Debug/unzipbz2.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../bzip2\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;ASM_CRC;USE_BZIP2;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipbz2__Win32_ASM_Debug/unzipbz2.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipbz2__Win32_ASM_Debug/\"\n\t\t\t\tObjectFile=\".\\unzipbz2__Win32_ASM_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipbz2__Win32_ASM_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\"unzipbz2__Win32_ASM_Debug/unzip.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipbz2__Win32_ASM_Debug/unzip.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipbz2__Win32_ASM_Debug/unzipbz2.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\crc_i386.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\envargs.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\explode.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\extract.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\fileio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\list.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\match.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\process.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ubz2err.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unreduce.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unshrink.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32i64.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zipinfo.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\consts.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ebcdic.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzpriv.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzvers.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\w32cfg.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzipbz2.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{226D352D-7B6E-44CB-A12C-BB04AE14BE88}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\unzipbz2__Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\unzipbz2__Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\unzipbz2__Win32_Release\\</OutDir>\n    <IntDir>.\\unzipbz2__Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\unzipbz2__Win32_Debug\\</OutDir>\n    <IntDir>.\\unzipbz2__Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\unzipbz2__Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\unzipbz2__Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipbz2__Win32_ASM_Release/unzipbz2.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <AdditionalIncludeDirectories>../../bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>NDEBUG;WIN32;ASM_CRC;USE_BZIP2;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzipbz2__Win32_ASM_Release/unzipbz2.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipbz2__Win32_ASM_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipbz2__Win32_ASM_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipbz2__Win32_ASM_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>unzipbz2__Win32_ASM_Release/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzipbz2__Win32_ASM_Release/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipbz2__Win32_ASM_Release/unzipbz2.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipbz2__Win32_Release/unzipbz2.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MaxSpeed</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <AdditionalIncludeDirectories>../../bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>NDEBUG;WIN32;USE_BZIP2;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzipbz2__Win32_Release/unzipbz2.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipbz2__Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipbz2__Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipbz2__Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>unzipbz2__Win32_Release/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzipbz2__Win32_Release/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipbz2__Win32_Release/unzipbz2.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipbz2__Win32_Debug/unzipbz2.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>../../bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>_DEBUG;WIN32;USE_BZIP2;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzipbz2__Win32_Debug/unzipbz2.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipbz2__Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipbz2__Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipbz2__Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>unzipbz2__Win32_Debug/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzipbz2__Win32_Debug/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipbz2__Win32_Debug/unzipbz2.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipbz2__Win32_ASM_Debug/unzipbz2.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <AdditionalIncludeDirectories>../../bzip2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <PreprocessorDefinitions>_DEBUG;WIN32;ASM_CRC;USE_BZIP2;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzipbz2__Win32_ASM_Debug/unzipbz2.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipbz2__Win32_ASM_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipbz2__Win32_ASM_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipbz2__Win32_ASM_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>unzipbz2__Win32_ASM_Debug/unzip.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzipbz2__Win32_ASM_Debug/unzip.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipbz2__Win32_ASM_Debug/unzipbz2.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\crc_i386.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\envargs.c\" />\n    <ClCompile Include=\"..\\..\\explode.c\" />\n    <ClCompile Include=\"..\\..\\extract.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\inflate.c\" />\n    <ClCompile Include=\"..\\..\\list.c\" />\n    <ClCompile Include=\"..\\..\\match.c\" />\n    <ClCompile Include=\"..\\nt.c\" />\n    <ClCompile Include=\"..\\..\\process.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\..\\ubz2err.c\" />\n    <ClCompile Include=\"..\\..\\unreduce.c\" />\n    <ClCompile Include=\"..\\..\\unshrink.c\" />\n    <ClCompile Include=\"..\\..\\unzip.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\..\\zipinfo.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\consts.h\" />\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\..\\globals.h\" />\n    <ClInclude Include=\"..\\..\\inflate.h\" />\n    <ClInclude Include=\"..\\nt.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\..\\unzip.h\" />\n    <ClInclude Include=\"..\\..\\unzpriv.h\" />\n    <ClInclude Include=\"..\\..\\unzvers.h\" />\n    <ClInclude Include=\"..\\w32cfg.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"bz2lib.vcxproj\">\n      <Project>{80cd1b7e-762b-4c1f-99e9-dced59936bee}</Project>\n      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n    </ProjectReference>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzipsfx.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unzipsfx\"\n\tProjectGUID=\"{F9746F4E-5ED8-4E23-ABBA-E8F2EFEB638E}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzipsfx___Win32_ASM_Release\"\n\t\t\tIntermediateDirectory=\".\\unzipsfx___Win32_ASM_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipsfx___Win32_ASM_Release/unzipsfx.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;SFX;ASM_CRC;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipsfx___Win32_ASM_Release/unzipsfx.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipsfx___Win32_ASM_Release/\"\n\t\t\t\tObjectFile=\".\\unzipsfx___Win32_ASM_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipsfx___Win32_ASM_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_ASM_Release/unzipsfx.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipsfx___Win32_ASM_Release/unzipsfx.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_ASM_Release/unzipsfx.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzipsfx___Win32_ASM_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzipsfx___Win32_ASM_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipsfx___Win32_ASM_Debug/unzipsfx.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;SFX;ASM_CRC;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipsfx___Win32_ASM_Debug/unzipsfx.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipsfx___Win32_ASM_Debug/\"\n\t\t\t\tObjectFile=\".\\unzipsfx___Win32_ASM_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipsfx___Win32_ASM_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_ASM_Debug/unzipsfx.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipsfx___Win32_ASM_Debug/unzipsfx.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_ASM_Debug/unzipsfx.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\unzipsfx___Win32_Debug\"\n\t\t\tIntermediateDirectory=\".\\unzipsfx___Win32_Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipsfx___Win32_Debug/unzipsfx.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;SFX;_CONSOLE\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipsfx___Win32_Debug/unzipsfx.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipsfx___Win32_Debug/\"\n\t\t\t\tObjectFile=\".\\unzipsfx___Win32_Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipsfx___Win32_Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"4\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_Debug/unzipsfx.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipsfx___Win32_Debug/unzipsfx.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_Debug/unzipsfx.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\unzipsfx___Win32_Release\"\n\t\t\tIntermediateDirectory=\".\\unzipsfx___Win32_Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\unzipsfx___Win32_Release/unzipsfx.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"WIN32;SFX;_CONSOLE\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\unzipsfx___Win32_Release/unzipsfx.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\unzipsfx___Win32_Release/\"\n\t\t\t\tObjectFile=\".\\unzipsfx___Win32_Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\unzipsfx___Win32_Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_Release/unzipsfx.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\unzipsfx___Win32_Release/unzipsfx.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\unzipsfx___Win32_Release/unzipsfx.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\crc_i386.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\extract.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\fileio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\match.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\process.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ubz2err.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\win32.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\consts.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crc32.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\crypt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ebcdic.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\globals.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\inflate.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\nt.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\ttyio.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzpriv.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\unzvers.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\w32cfg.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\zip.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/vc8/unzipsfx.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{F9746F4E-5ED8-4E23-ABBA-E8F2EFEB638E}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup>\n    <_ProjectFileVersion>12.0.21005.1</_ProjectFileVersion>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\unzipsfx___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\unzipsfx___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\unzipsfx___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\unzipsfx___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\unzipsfx___Win32_Debug\\</OutDir>\n    <IntDir>.\\unzipsfx___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\unzipsfx___Win32_Release\\</OutDir>\n    <IntDir>.\\unzipsfx___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipsfx___Win32_ASM_Release/unzipsfx.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MinSpace</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>NDEBUG;WIN32;SFX;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzipsfx___Win32_ASM_Release/unzipsfx.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipsfx___Win32_ASM_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipsfx___Win32_ASM_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipsfx___Win32_ASM_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzipsfx___Win32_ASM_Release/unzipsfx.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzipsfx___Win32_ASM_Release/unzipsfx.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipsfx___Win32_ASM_Release/unzipsfx.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipsfx___Win32_ASM_Debug/unzipsfx.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;SFX;ASM_CRC;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzipsfx___Win32_ASM_Debug/unzipsfx.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipsfx___Win32_ASM_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipsfx___Win32_ASM_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipsfx___Win32_ASM_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzipsfx___Win32_ASM_Debug/unzipsfx.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzipsfx___Win32_ASM_Debug/unzipsfx.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipsfx___Win32_ASM_Debug/unzipsfx.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipsfx___Win32_Debug/unzipsfx.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_DEBUG;WIN32;SFX;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <MinimalRebuild>true</MinimalRebuild>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <PrecompiledHeaderOutputFile>.\\unzipsfx___Win32_Debug/unzipsfx.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipsfx___Win32_Debug/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipsfx___Win32_Debug/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipsfx___Win32_Debug/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzipsfx___Win32_Debug/unzipsfx.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <ProgramDatabaseFile>.\\unzipsfx___Win32_Debug/unzipsfx.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipsfx___Win32_Debug/unzipsfx.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Midl>\n      <TypeLibraryName>.\\unzipsfx___Win32_Release/unzipsfx.tlb</TypeLibraryName>\n      <HeaderFileName />\n    </Midl>\n    <ClCompile>\n      <Optimization>MinSpace</Optimization>\n      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\n      <PreprocessorDefinitions>WIN32;SFX;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <StringPooling>true</StringPooling>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <PrecompiledHeaderOutputFile>.\\unzipsfx___Win32_Release/unzipsfx.pch</PrecompiledHeaderOutputFile>\n      <AssemblerListingLocation>.\\unzipsfx___Win32_Release/</AssemblerListingLocation>\n      <ObjectFileName>.\\unzipsfx___Win32_Release/</ObjectFileName>\n      <ProgramDataBaseFileName>.\\unzipsfx___Win32_Release/</ProgramDataBaseFileName>\n      <WarningLevel>Level3</WarningLevel>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n    </ClCompile>\n    <ResourceCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <Culture>0x0409</Culture>\n    </ResourceCompile>\n    <Link>\n      <OutputFile>.\\unzipsfx___Win32_Release/unzipsfx.exe</OutputFile>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <ProgramDatabaseFile>.\\unzipsfx___Win32_Release/unzipsfx.pdb</ProgramDatabaseFile>\n      <SubSystem>Console</SubSystem>\n      <TargetMachine>MachineX86</TargetMachine>\n    </Link>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\unzipsfx___Win32_Release/unzipsfx.bsc</OutputFile>\n    </Bscmake>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\crc_i386.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\extract.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\inflate.c\" />\n    <ClCompile Include=\"..\\..\\match.c\" />\n    <ClCompile Include=\"..\\nt.c\" />\n    <ClCompile Include=\"..\\..\\process.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\..\\ubz2err.c\" />\n    <ClCompile Include=\"..\\..\\unzip.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\consts.h\" />\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\..\\globals.h\" />\n    <ClInclude Include=\"..\\..\\inflate.h\" />\n    <ClInclude Include=\"..\\nt.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\..\\unzip.h\" />\n    <ClInclude Include=\"..\\..\\unzpriv.h\" />\n    <ClInclude Include=\"..\\..\\unzvers.h\" />\n    <ClInclude Include=\"..\\w32cfg.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/unzip60/win32/w32cfg.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    Win32 specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __w32cfg_h\n#define __w32cfg_h\n\n#ifdef __CYGWIN__\n/* We treat the file system underneath the Cygwin Unix emulator environment\n * as \"native VFAT/NTFS\" and use the WIN32 API for its special attributes...\n */\n#  ifdef UNIX\n#    undef UNIX\n#  endif\n#endif\n\n#if (defined(_MSC_VER) && !defined(MSC))\n#  define MSC\n#endif\n\n/* enable multibyte character set support by default */\n#if (!defined(_MBCS) && !defined(NO_MBCS))\n#  define _MBCS\n#endif\n#if (defined(_MBCS) && defined(NO_MBCS))\n#  undef _MBCS\n#endif\n#if (defined(__CYGWIN__) && defined(_MBCS))\n#  undef _MBCS                  /* Cygwin RTL lacks support for __mb_cur_max */\n#endif\n#if (defined(__DJGPP__) && !defined(__EMX__) && defined(_MBCS))\n#  undef _MBCS                  /* __mb_cur_max missing for RSXNTdj 1.6 beta */\n#endif\n\n#include <sys/types.h>          /* off_t, time_t, dev_t, ... */\n#include <sys/stat.h>\n#include <io.h>                 /* read(), open(), etc. */\n#include <time.h>\n#if ((defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset))\n#  define tzset _tzset\n#endif\n#if (defined(__LCC__) && !defined(tzset))\n#  define tzset _tzset\n#endif\n#ifdef __MINGW32__\n   extern void _tzset(void);    /* this is missing in <time.h> */\n#  ifndef tzset\n#    define tzset _tzset\n#  endif\n#endif\n#ifdef W32_USE_IZ_TIMEZONE\n#  ifdef __BORLANDC__\n#    define tzname tzname\n#    define IZTZ_DEFINESTDGLOBALS\n#  endif\n#  ifdef __WATCOMC__\n#    define IZTZ_DEFINESTDGLOBALS\n#  endif\n#  ifndef tzset\n#    define tzset _tzset\n#  endif\n#  ifndef timezone\n#    define timezone _timezone\n#  endif\n#  ifndef daylight\n#    define daylight _daylight\n#  endif\n#  ifndef tzname\n#    define tzname _tzname\n#  endif\n#  if (!defined(NEED__ISINDST) && !defined(__BORLANDC__))\n#    define NEED__ISINDST\n#  endif\n#  ifdef IZTZ_GETLOCALETZINFO\n#    undef IZTZ_GETLOCALETZINFO\n#  endif\n#  define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone\n#endif /* W32_USE_IZ_TIMEZONE */\n#include <memory.h>\n#if (!defined(__RSXNT__) && !defined(__CYGWIN__))\n#  include <direct.h>           /* mkdir() */\n#endif\n#include <fcntl.h>\n#ifdef __CYGWIN__\n#  include <unistd.h>\n   extern int setmode(int, int);        /* this is missing in <fcntl.h> */\n#endif\n#if (defined(MSC) || defined(__WATCOMC__) || defined(__MINGW32__))\n#  include <sys/utime.h>\n#else\n#  include <utime.h>\n#endif\n#define GOT_UTIMBUF\n\n#ifdef _MBCS\n#  if (!defined(__EMX__) && !defined(__DJGPP__) && !defined(__CYGWIN__))\n#  if (!defined(__MINGW32__) || defined(__MSVCRT__))\n#    include <stdlib.h>\n#    include <mbstring.h>\n     /* for MSC (and compatible compilers), use routines supplied by RTL */\n#    define CLEN(ptr) _mbclen((const uch *)(ptr))\n#    define PREINCSTR(ptr) (ptr = (char *)_mbsinc((const uch *)(ptr)))\n#    define MBSCHR(str, c) (char *)_mbschr((const uch *)(str), (c))\n#    define MBSRCHR(str, c) (char *)_mbsrchr((const uch *)(str), (c))\n#  endif\n#  endif\n#  if (defined(__MINGW32__) && !defined(MB_CUR_MAX))\n#    ifdef __MSVCRT__\n       extern int *__p___mb_cur_max(void);\n#      define MB_CUR_MAX (*__p___mb_cur_max())\n#    else\n       extern int *_imp____mb_cur_max_dll;\n#      define MB_CUR_MAX (*_imp____mb_cur_max_dll)\n#    endif\n#  endif\n#  if (defined(__LCC__) && !defined(MB_CUR_MAX))\n     extern int *_imp____mb_cur_max;\n#    define MB_CUR_MAX (*_imp____mb_cur_max)\n#  endif\n#  if (defined(__DJGPP__) && !defined(__EMX__) && !defined(MB_CUR_MAX))\n     extern int *_imp____mb_cur_max;\n#    define MB_CUR_MAX (*_imp____mb_cur_max)\n#  endif\n#endif\n\n/* for UnZip, the \"basic\" part of the win32 api is sufficient */\n#ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#if defined(__FILEIO_C)\n#  ifndef __CYGWIN__\n#    include <conio.h>\n#  endif\n#  include <windows.h>\n#  ifdef __RSXNT__\n#    include \"../win32/rsxntwin.h\"\n#  endif\n#  ifndef TIME_ZONE_ID_INVALID\n#    define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL\n#  endif\n#endif\n#if (defined(__ENVARGS_C) || defined(__EXTRACT_C) || defined(__UNZIP_C) || \\\n     defined(ZCRYPT_INTERNAL))\n#  include <windows.h>\n#  ifdef __RSXNT__\n#    include \"../win32/rsxntwin.h\"\n#  endif\n#  ifndef TIME_ZONE_ID_INVALID\n#    define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL\n#  endif\n#endif\n\n#ifndef Cdecl\n#  define Cdecl __cdecl\n#endif\n\n/* the following definitions are considered as \"obsolete\" by Microsoft and\n * might be missing in some versions of <windows.h>\n */\n#ifndef AnsiToOem\n#  define AnsiToOem CharToOemA\n#endif\n#ifndef OemToAnsi\n#  define OemToAnsi OemToCharA\n#endif\n\n#define DIR_END       '\\\\'      /* OS uses '\\\\' as directory separator */\n#define DIR_END2      '/'       /* also check for '/' (RTL may convert) */\n#ifdef DATE_FORMAT\n#  undef DATE_FORMAT\n#endif\n#define DATE_FORMAT   dateformat()\n#ifdef DATE_SEPCHAR\n#  undef DATE_SEPCHAR\n#endif\n#define DATE_SEPCHAR  dateseparator()\n#define lenEOL        2\n#define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}\n\n#if (defined(__RSXNT__) && !defined(HAVE_MKTIME))\n#  define HAVE_MKTIME           /* use mktime() in time conversion routines */\n#endif\n#if (defined(MSC) && !defined(HAVE_MKTIME))\n#  define HAVE_MKTIME           /* use mktime() in time conversion routines */\n#endif\n#if (defined(__CYGWIN__) && defined(HAVE_MKTIME))\n#  undef HAVE_MKTIME            /* Cygnus' mktime() implementation is buggy */\n#endif\n#if (defined(W32_USE_IZ_TIMEZONE) && !defined(HAVE_MKTIME))\n#  define HAVE_MKTIME           /* use mktime() in time conversion routines */\n#endif\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n#if (!defined(NO_DIR_ATTRIB) && !defined(SET_DIR_ATTRIB))\n#  define SET_DIR_ATTRIB\n#endif\n#if (!defined(NOTIMESTAMP) && !defined(TIMESTAMP))\n#  define TIMESTAMP\n#endif\n#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS))\n#  define NTSD_EAS      /* enable NTSD support unless explicitly suppressed */\n#endif\n#if (defined(NTSD_EAS) && !defined(RESTORE_ACL))\n#  define RESTORE_ACL   /* \"restore ACLs\" only needed when NTSD_EAS active */\n#endif\n#if (!defined(NO_UNICODE_SUPPORT) && !defined(UNICODE_SUPPORT))\n#  define UNICODE_SUPPORT       /* enable UTF-8 filename support by default */\n#endif\n#if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR))\n#  define UNICODE_WCHAR         /* wchar_t is UTF-16 encoded on WIN32 */\n#endif\n#ifdef UTF8_MAYBE_NATIVE\n#  undef UTF8_MAYBE_NATIVE      /* UTF-8 cannot be system charset on WIN32 */\n#endif\n\n/* The following compiler systems provide or use a runtime library with a\n * locale-aware isprint() implementation.  For these systems, the \"enhanced\"\n * unprintable charcode detection in fnfilter() gets enabled.\n */\n#if (!defined(HAVE_WORKING_ISPRINT) && !defined(NO_WORKING_ISPRINT))\n#  if defined(MSC) || defined(__BORLANDC__)\n#    define HAVE_WORKING_ISPRINT\n#  endif\n#  if defined(__MINGW32__) && defined(__MSVCRT__)\n#    define HAVE_WORKING_ISPRINT\n#  endif\n#endif\n\n/* WIN32 runs solely on little-endian processors; enable support\n * for the 32-bit optimized CRC-32 C code by default.\n */\n#ifdef IZ_CRC_BE_OPTIMIZ\n#  undef IZ_CRC_BE_OPTIMIZ\n#endif\n#if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ)\n#  define IZ_CRC_LE_OPTIMIZ\n#endif\n\n/* handlers for OEM <--> ANSI string conversions */\n#ifdef __RSXNT__\n   /* RSXNT uses OEM coded strings in functions supplied by C RTL */\n#  ifdef CRTL_CP_IS_ISO\n#    undef CRTL_CP_IS_ISO\n#  endif\n#  ifndef CRTL_CP_IS_OEM\n#    define CRTL_CP_IS_OEM\n#  endif\n#else\n   /* \"real\" native WIN32 compilers use ANSI coded strings in C RTL calls */\n#  ifndef CRTL_CP_IS_ISO\n#    define CRTL_CP_IS_ISO\n#  endif\n#  ifdef CRTL_CP_IS_OEM\n#    undef CRTL_CP_IS_OEM\n#  endif\n#endif\n\n#ifdef CRTL_CP_IS_ISO\n   /* C RTL's file system support assumes ANSI coded strings */\n#  define ISO_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define OEM_TO_INTERN(src, dst)  OemToAnsi(src, dst)\n#  define INTERN_TO_ISO(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define INTERN_TO_OEM(src, dst)  AnsiToOem(src, dst)\n#endif /* CRTL_CP_IS_ISO */\n#ifdef CRTL_CP_IS_OEM\n   /* C RTL's file system support assumes OEM coded strings */\n#  define ISO_TO_INTERN(src, dst)  AnsiToOem(src, dst)\n#  define OEM_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define INTERN_TO_ISO(src, dst)  OemToAnsi(src, dst)\n#  define INTERN_TO_OEM(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#endif /* CRTL_CP_IS_OEM */\n#define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1)\n#define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1)\n#ifndef WINDLL\n   /* Despite best intentions, for the command-line version UzpPassword()\n    * could return either character set, depending on whether running under\n    * Win95 (DOS-session) or WinNT (native WinNT command interpreter)! */\n#  define STR_TO_CP2(dst, src)  (AnsiToOem(src, dst), dst)\n#  define STR_TO_CP3(dst, src)  (OemToAnsi(src, dst), dst)\n#else\n   /* The WINDLL front end is known to supply ISO/ANSI-coded passwords! */\n#  define STR_TO_CP2(dst, src)  (AnsiToOem(src, dst), dst)\n#endif\n/* dummy defines to disable these functions, they are not needed */\n#define STR_TO_OEM\n#define STR_TO_ISO\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    int created_dir, renamed_fullpath, fnlen;\\\n    unsigned nLabelDrive;\\\n    char lastRootPath[4];\\\n    int lastVolOldFAT, lastVolLocTim;\\\n    char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\\\n    ZCONST char *wildname;\\\n    char *dirname, matchname[FILNAMSIZ];\\\n    int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n    zvoid *wild_dir;\n\n/* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by   */\n/*    both mapname() and checkdir().                                   */\n/* lastRootPath, lastVolOldFAT and lastVolLocTim are used by           */\n/*    IsVolumeOldFAT() and NTQueryVolInfo().                           */\n/* rootlen, rootpath, buildpathHPFS, buildpathFAT, endHPFS, and endFAT */\n/*    are used by checkdir().                                          */\n/* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */\n/*    and notfirstcall are used by do_wild().                          */\n\n/* This replacement for C-RTL-supplied getch() (or similar) functionality\n * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95,\n * and supports the <ALT>+[0]<digit><digit><digit> feature.\n */\nint getch_win32  OF((void));\n\n/* Up to now, all versions of Microsoft C runtime libraries lack the support\n * for customized (non-US) switching rules between daylight saving time and\n * standard time in the TZ environment variable string.\n * But non-US timezone rules are correctly supported when timezone information\n * is read from the OS system settings in the Win32 registry.\n * The following work-around deletes any TZ environment setting from\n * the process environment.  This results in a fallback of the RTL time\n * handling code to the (correctly interpretable) OS system settings, read\n * from the registry.\n */\n#ifdef USE_EF_UT_TIME\n# if (defined(__WATCOMC__) || defined(__CYGWIN__) || \\\n      defined(W32_USE_IZ_TIMEZONE))\n#   define iz_w32_prepareTZenv()\n# else\n#   define iz_w32_prepareTZenv()        putenv(\"TZ=\")\n# endif\n#endif\n\n/* This patch of stat() is useful for at least two compilers.  It is   */\n/* difficult to take a stat() of a root directory under Windows95, so  */\n/* zstat_win32() detects that case and fills in suitable values.       */\n#ifndef __RSXNT__\n#  ifndef W32_STATROOT_FIX\n#    define W32_STATROOT_FIX\n#  endif\n#endif /* !__RSXNT__ */\n\n#define W32_STAT_BANDAID\n#if defined(REENTRANT)\n#  define __W32STAT_GLOBALS__       Uz_Globs *pG,\n#  define __W32STAT_G__             pG,\n#else\n#  define __W32STAT_GLOBALS__\n#  define __W32STAT_G__\n#endif\n#ifdef SSTAT\n#  undef SSTAT\n#endif\n#ifdef WILD_STAT_BUG\n#  define SSTAT(path, pbuf) (iswild(path) || zstat_win32(__W32STAT_G__ path, pbuf))\n#else\n#  define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf)\n#endif\n\n#ifdef __WATCOMC__\n#  ifdef __386__\n#    ifndef WATCOMC_386\n#      define WATCOMC_386\n#    endif\n#    define __32BIT__\n#    undef far\n#    define far\n#    undef near\n#    define near\n#    undef Cdecl\n#    define Cdecl\n\n/* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't.  */\n#    define _get_osfhandle _os_handle\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  endif /* __386__ */\n#endif /* __WATCOMC__ */\n\n#define SCREENWIDTH 80\n#define SCREENSIZE(scrrows, scrcols)  screensize(scrrows, scrcols)\nint screensize(int *tt_rows, int *tt_cols);\n\n/* on the DOS or NT console screen, line-wraps are always enabled */\n#define SCREENLWRAP 1\n#define TABSIZE 8\n\n\n/* 64-bit-Integers & Large File Support\n * (pasted here from Zip 3b, osdep.h - Myles Bennett 7-jun-2004)\n * (updated from Zip 3.0d - Ed Gordon 6-oct-2004)\n *\n *  If this is set it is assumed that the port\n *  supports 64-bit file calls.  The types are\n *  defined here.  Any local implementations are\n *  in w32i64.c and the prototypes for the calls are\n *  in unzip.h.  Note that a port must support\n *  these calls fully or should not set\n *  LARGE_FILE_SUPPORT.\n */\n\n/* Automatically set ZIP64_SUPPORT if supported */\n\n#ifndef NO_ZIP64_SUPPORT\n# ifndef ZIP64_SUPPORT\n#   if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)\n#     define ZIP64_SUPPORT\n#   elif defined(__LCC__)\n      /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */\n#   elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n#     define ZIP64_SUPPORT\n#   elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520))\n      /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */\n#   endif\n# endif\n#endif\n\n#ifdef ZIP64_SUPPORT\n  /* base type for file offsets and file sizes */\n# if (defined(__GNUC__) || defined(ULONG_LONG_MAX))\n    typedef long long    zoff_t;\n# else\n    /* all other compilers use this as intrinsic 64-bit type */\n    typedef __int64      zoff_t;\n# endif\n# define ZOFF_T_DEFINED\n\n  /* user-defined types and format strings for 64-bit numbers and\n   * file pointer functions  (these depend on the rtl library and library\n   * headers used; they are NOT compiler-specific)\n   */\n# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__LCC__)\n    /* MS C and VC, MinGW32, lcc32 */\n    /* these systems use the Microsoft C RTL */\n\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n#   define Z_STAT_DEFINED\n\n#   ifdef __LCC__\n      /* The LCC headers lack these declarations of MSC rtl functions in\n         sys/stat.h. */\n      struct _stati64 {\n        unsigned int st_dev;\n        unsigned short st_ino;\n        unsigned short st_mode;\n        short st_nlink;\n        short st_uid;\n        short st_gid;\n        unsigned int st_rdev;\n        __int64 st_size;\n        time_t st_atime;\n        time_t st_mtime;\n        time_t st_ctime;\n      };\n      int _stati64(const char *, struct _stati64 *);\n      int _fstati64(int, struct _stati64 *);\n       __int64 _lseeki64(int, __int64, int);\n#   endif /* __LCC__ */\n\n    /* printf format size prefix for zoff_t values */\n#   define FZOFFT_FMT \"I64\"\n#   define FZOFFT_HEX_WID_VALUE \"16\"\n\n#   define SHORTHDRSTATS \"%9I64u  %02u%c%02u%c%02u %02u:%02u  %c\"\n#   define SHORTFILETRAILER \" --------                   -------\\n%9I64u                   %9lu file%s\\n\"\n\n# elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520))\n    /* Borland C 5.2 or newer */\n\n    /* 64-bit stat struct */\n    typedef struct stati64 z_stat;\n#   define Z_STAT_DEFINED\n\n    /* Borland C does not provide a 64-bit-capable _lseeki64(), so we\n       need to use the stdio.h stream functions instead. */\n#   ifndef USE_STRM_INPUT\n#     define USE_STRM_INPUT\n#   endif\n\n    /* printf format size prefix for zoff_t values */\n#   define FZOFFT_FMT \"L\"\n#   define FZOFFT_HEX_WID_VALUE \"16\"\n\n#   define SHORTHDRSTATS \"%9Lu  %02u%c%02u%c%02u %02u:%02u  %c\"\n#   define SHORTFILETRAILER \" --------                   -------\\n%9Lu                   %9lu file%s\\n\"\n\n# elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n    /* WATCOM C */\n\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n#   define Z_STAT_DEFINED\n\n    /* printf format size prefix for zoff_t values */\n#   define FZOFFT_FMT \"ll\"\n#   define FZOFFT_HEX_WID_VALUE \"16\"\n\n#   define SHORTHDRSTATS \"%9llu  %02u%c%02u%c%02u %02u:%02u  %c\"\n#   define SHORTFILETRAILER \" --------                   -------\\n%9llu                   %9lu file%s\\n\"\n\n# elif (defined(__IBMC__) && (__IBMC__ >= 350))\n    /* IBM C */\n\n    /* 64-bit stat struct */\n\n    /* printf format size prefix for zoff_t values */\n#   define FZOFFT_FMT \"I64\"\n#   define FZOFFT_HEX_WID_VALUE \"16\"\n\n#   define SHORTHDRSTATS \"%9I64u  %02u%c%02u%c%02u %02u:%02u  %c\"\n#   define SHORTFILETRAILER \" --------                   -------\\n%9I64u                   %9lu file%s\\n\"\n\n# endif\n\n#endif\n\n/* If port has LARGE_FILE_SUPPORT then define here\n   to make automatic unless overridden */\n\n#ifndef LARGE_FILE_SUPPORT\n# ifndef NO_LARGE_FILE_SUPPORT\n#   if defined(_MSC_VER) || defined(__MINGW32__)\n#     define LARGE_FILE_SUPPORT\n#   elif defined(__LCC__)\n      /* LCC links against crtdll.dll -> no support of 64-bit offsets :( */\n#   elif defined(__CYGWIN__)\n#     define LARGE_FILE_SUPPORT\n#   elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n#     define LARGE_FILE_SUPPORT\n#   elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0520))\n      /* Borland C RTL lacks any support to get/set 64-bit file pointer :( */\n#   endif\n# endif\n#endif\n\n\n#ifndef LARGE_FILE_SUPPORT\n  /* No Large File Support */\n\n  /* base type for file offsets and file sizes */\n  typedef long zoff_t;\n# define ZOFF_T_DEFINED\n\n  /* stat struct */\n  typedef struct stat z_stat;\n# define Z_STAT_DEFINED\n\n#  define FZOFFT_FMT \"l\"\n#  define FZOFFT_HEX_WID_VALUE \"8\"\n\n\n#  define SHORTHDRSTATS \"%9lu  %02u%c%02u%c%02u %02u:%02u  %c\"\n#  define SHORTFILETRAILER \" --------                   -------\\n%9lu                   %9lu file%s\\n\"\n\n#endif /* LARGE_FILE_SUPPORT */\n\n#endif /* !__w32cfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/win32.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  win32.c\n\n  32-bit Windows-specific (NT/9x) routines for use with Info-ZIP's UnZip 5.3\n  and later.\n\n  Contains:  GetLoadPath()\n             Opendir()\n             Readdir()\n             Closedir()\n             SetSD()              set security descriptor on file\n             FindSDExtraField()   extract SD e.f. block from extra field\n             IsWinNT()            indicate type of WIN32 platform\n             test_NTSD()          test integrity of NT security data\n             utime2NtfsFileTime()\n             utime2VFatFileTime()\n             FStampIsLocTime()\n             NtfsFileTime2utime()\n             VFatFileTime2utime()\n             getNTfiletime()\n             SetFileSize()\n             close_outfile()\n             defer_dir_attribs()\n             set_direc_attribs()\n             stamp_file()\n             isfloppy()\n             NTQueryVolInfo()\n             IsVolumeOldFAT()\n             do_wild()\n             mapattr()\n             mapname()\n             maskDOSdevice()\n             map2fat()\n             checkdir()\n             dateformat()\n             dateseparator()\n             version()\n             screensize()\n             zstat_win32()\n             conv_to_rule()\n             GetPlatformLocalTimezone()\n             getch_win32()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"../unzip.h\"\n\n#ifdef CR\n#undef CR\n#endif\n\n#include <windows.h>    /* must be AFTER unzip.h to avoid struct G problems */\n#ifdef __RSXNT__\n#  include \"../win32/rsxntwin.h\"\n#endif\n#include \"../win32/nt.h\"\n\n#ifndef FUNZIP          /* most of this file is not used with fUnZip */\n\n/* some non-MS runtime headers (e.g. lcc) may miss this definition */\n#ifndef FILE_WRITE_ATTRIBUTES\n#  define FILE_WRITE_ATTRIBUTES 0x0100\n#endif\n\n#if (defined(__EMX__) || defined(__CYGWIN__))\n#  define MKDIR(path,mode)   mkdir(path,mode)\n#else\n#  define MKDIR(path,mode)   mkdir(path)\n#endif\n\n#ifdef HAVE_WORKING_DIRENT_H\n#  undef HAVE_WORKING_DIRENT_H\n#endif\n/* The emxrtl dirent support of (__GO32__ || __EMX__) converts to lowercase! */\n#if defined(__CYGWIN__)\n#  define HAVE_WORKING_DIRENT_H\n#endif\n\n#ifndef SFX\n#  ifdef HAVE_WORKING_DIRENT_H\n#    include <dirent.h>         /* use readdir() */\n#    define zdirent  dirent\n#    define zDIR     DIR\n#    define Opendir  opendir\n#    define Readdir  readdir\n#    define Closedir closedir\n#  else /* !HAVE_WORKING_DIRENT_H */\n     typedef struct zdirent {\n         char    reserved [21];\n         char    ff_attrib;\n         short   ff_ftime;\n         short   ff_fdate;\n         long    size;\n         char    d_name[MAX_PATH];\n         int     d_first;\n         HANDLE  d_hFindFile;\n     } zDIR;\n\n     static zDIR           *Opendir  (const char *n);\n     static struct zdirent *Readdir  (zDIR *d);\n     static void            Closedir (zDIR *d);\n#  endif /* ?HAVE_WORKING_DIRENT_H */\n#endif /* !SFX */\n\n#ifdef SET_DIR_ATTRIB\ntypedef struct NTdirattr {      /* struct for holding unix style directory */\n    struct NTdirattr *next;     /*  info until can be sorted and set at end */\n    char *fn;                   /* filename of directory */\n    FILETIME Modft;    /* File time type defined in NT, `last modified' time */\n    FILETIME Accft;    /* NT file time type, `last access' time */\n    FILETIME Creft;    /* NT file time type, `file creation' time */\n    int gotTime;\n    unsigned perms;             /* same as min_info.file_attr */\n#ifdef NTSD_EAS\n    unsigned SDlen;             /* length of SD data in buf */\n#endif\n    char buf[1];                /* buffer stub for directory SD and name */\n} NTdirattr;\n#define NtAtt(d)  ((NTdirattr *)d)    /* typecast shortcut */\n#endif /* SET_DIR_ATTRIB */\n\n\n/* Function prototypes */\n#ifdef NTSD_EAS\n   static int  SetSD(__GPRO__ char *path, unsigned fperms,\n                     uch *eb_ptr, unsigned eb_len);\n   static int  FindSDExtraField(__GPRO__\n                                uch *ef_ptr, unsigned ef_len,\n                                uch **p_ebSD_ptr, unsigned *p_ebSD_len);\n#endif\n\n#ifndef NO_W32TIMES_IZFIX\n   static void utime2NtfsFileTime(time_t ut, FILETIME *pft);\n#endif\nstatic void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin);\n#if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX))\n   static int NtfsFileTime2utime(const FILETIME *pft, time_t *ut);\n#endif\n#ifdef W32_STAT_BANDAID\n   static int VFatFileTime2utime(const FILETIME *pft, time_t *ut);\n#endif\nstatic int FStampIsLocTime(__GPRO__ const char *path);\n\n\nstatic int  getNTfiletime   (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,\n                             FILETIME *pCreFT);\nstatic int  isfloppy        (int nDrive);\nstatic int  NTQueryVolInfo  (__GPRO__ const char *name);\nstatic int  IsVolumeOldFAT  (__GPRO__ const char *name);\nstatic void maskDOSdevice   (__GPRO__ char *pathcomp);\nstatic void map2fat         (char *pathcomp, char **pEndFAT);\n\n\n#if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING))\n   int _CRT_glob = 0;   /* suppress command line globbing by C RTL */\n#endif\n\n#ifdef ACORN_FTYPE_NFS\n/* Acorn bits for NFS filetyping */\ntypedef struct {\n  uch ID[2];\n  uch size[2];\n  uch ID_2[4];\n  uch loadaddr[4];\n  uch execaddr[4];\n  uch attr[4];\n} RO_extra_block;\n\n#endif /* ACORN_FTYPE_NFS */\n\n/* static int created_dir;      */     /* used by mapname(), checkdir() */\n/* static int renamed_fullpath; */     /* ditto */\n/* static int fnlen;            */     /* ditto */\n/* static unsigned nLabelDrive; */     /* ditto */\n\nextern char Far TruncNTSD[];    /* in extract.c */\n\n\n\n#ifdef SFX\n\n/**************************/\n/* Function GetLoadPath() */\n/**************************/\n\nchar *GetLoadPath(__GPRO)\n{\n#ifdef MSC\n    extern char *_pgmptr;\n    return _pgmptr;\n\n#else    /* use generic API call */\n\n    GetModuleFileName(NULL, G.filename, FILNAMSIZ);\n    _ISO_INTERN(G.filename);    /* translate to codepage of C rtl's stdio */\n    return G.filename;\n#endif\n\n} /* end function GetLoadPath() */\n\n\n\n\n\n#else /* !SFX */\n\n#ifndef HAVE_WORKING_DIRENT_H\n\n/**********************/        /* Borrowed from ZIP 2.0 sources            */\n/* Function Opendir() */        /* Difference: no special handling for      */\n/**********************/        /*             hidden or system files.      */\n\nstatic zDIR *Opendir(n)\n    const char *n;          /* directory to open */\n{\n    zDIR *d;                /* malloc'd return value */\n    char *p;                /* malloc'd temporary string */\n    WIN32_FIND_DATAA fd;\n    extent len = strlen(n);\n\n    /* Start searching for files in directory n */\n\n    if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||\n        (p = malloc(strlen(n) + 5)) == NULL)\n    {\n        if (d != (zDIR *)NULL)\n            free((void *)d);\n        return (zDIR *)NULL;\n    }\n    INTERN_TO_ISO(n, p);\n    if (len > 0) {\n        if (p[len-1] == ':')\n            p[len++] = '.';     /* x: => x:. */\n        else if (p[len-1] == '/' || p[len-1] == '\\\\')\n            --len;              /* foo/ => foo */\n    }\n    strcpy(p+len, \"/*\");\n\n    if (INVALID_HANDLE_VALUE == (d->d_hFindFile = FindFirstFileA(p, &fd))) {\n        free((zvoid *)d);\n        free((zvoid *)p);\n        return NULL;\n    }\n    strcpy(d->d_name, fd.cFileName);\n\n    free((zvoid *)p);\n    d->d_first = 1;\n    return d;\n\n} /* end of function Opendir() */\n\n\n\n\n/**********************/        /* Borrowed from ZIP 2.0 sources            */\n/* Function Readdir() */        /* Difference: no special handling for      */\n/**********************/        /*             hidden or system files.      */\n\nstatic struct zdirent *Readdir(d)\n    zDIR *d;                    /* directory stream from which to read */\n{\n    /* Return pointer to first or next directory entry, or NULL if end. */\n\n    if ( d->d_first )\n        d->d_first = 0;\n    else\n    {\n        WIN32_FIND_DATAA fd;\n\n        if ( !FindNextFileA(d->d_hFindFile, &fd) )\n            return NULL;\n\n        ISO_TO_INTERN(fd.cFileName, d->d_name);\n    }\n    return (struct zdirent *)d;\n\n} /* end of function Readdir() */\n\n\n\n\n/***********************/\n/* Function Closedir() */       /* Borrowed from ZIP 2.0 sources */\n/***********************/\n\nstatic void Closedir(d)\n    zDIR *d;                    /* directory stream to close */\n{\n    FindClose(d->d_hFindFile);\n    free(d);\n}\n\n#endif /* !HAVE_WORKING_DIRENT_H */\n#endif /* ?SFX */\n\n\n\n\n#ifdef NTSD_EAS\n\n/**********************/\n/*  Function SetSD()  */   /* return almost-PK errors */\n/**********************/\n\nstatic int SetSD(__G__ path, fperms, eb_ptr, eb_len)\n    __GDEF\n    char *path;\n    unsigned fperms;\n    uch *eb_ptr;\n    unsigned eb_len;\n{\n    ulg ntsd_ucSize;\n    VOLUMECAPS VolumeCaps;\n    uch *security_data;\n    int error;\n\n    ntsd_ucSize = makelong(eb_ptr + (EB_HEADSIZE+EB_UCSIZE_P));\n    if (ntsd_ucSize > 0L && eb_len <= (EB_NTSD_L_LEN + EB_CMPRHEADLEN))\n        return IZ_EF_TRUNC;               /* no compressed data! */\n\n    /* provide useful input */\n    VolumeCaps.dwFileAttributes = fperms;\n    VolumeCaps.bUsePrivileges = (uO.X_flag > 1);\n\n    /* check target volume capabilities - just fall through\n     * and try if fail */\n    if (GetVolumeCaps(G.rootpath, path, &VolumeCaps) &&\n        !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS))\n        return PK_OK;\n\n    /* allocate storage for uncompressed data */\n    security_data = (uch *)malloc((extent)ntsd_ucSize);\n    if (security_data == (uch *)NULL)\n        return PK_MEM4;\n\n    error = memextract(__G__ security_data, ntsd_ucSize,\n      (eb_ptr + (EB_HEADSIZE+EB_NTSD_L_LEN)), (ulg)(eb_len - EB_NTSD_L_LEN));\n\n    if (error == PK_OK) {\n        if (SecuritySet(path, &VolumeCaps, security_data)) {\n            error = PK_COOL;\n            if (!uO.tflag && QCOND2)\n                Info(slide, 0, ((char *)slide, \" (%ld bytes security)\",\n                  ntsd_ucSize));\n        }\n    }\n\n    free(security_data);\n    return error;\n}\n\n\n\n\n/********************************/   /* scan extra fields for something */\n/*  Function FindSDExtraField() */   /*  we happen to know */\n/********************************/\n/* Returns TRUE when a valid NTFS SD block is found.\n * Address and size of the NTSD e.f. block are passed up to the caller.\n * In case of more than one valid NTSD block in the e.f., the last block\n * found is passed up.\n * Returns FALSE and leaves the content of the ebSD_ptr and ebSD_len\n * parameters untouched when no valid NTFS SD block is found. */\nstatic int FindSDExtraField(__GPRO__\n                            uch *ef_ptr, unsigned ef_len,\n                            uch **p_ebSD_ptr, unsigned *p_ebSD_len)\n{\n    int rc = FALSE;\n\n    if (!uO.X_flag)\n        return FALSE;  /* user said don't process ACLs; for now, no other\n                          extra block types are handled here */\n\n    while (ef_len >= EB_HEADSIZE)\n    {\n        unsigned eb_id = makeword(EB_ID + ef_ptr);\n        unsigned eb_len = makeword(EB_LEN + ef_ptr);\n\n        if (eb_len > (ef_len - EB_HEADSIZE)) {\n            /* discovered some extra field inconsistency! */\n            Trace((stderr,\n              \"FindSDExtraField: block length %u > rest ef_size %u\\n\", eb_len,\n              ef_len - EB_HEADSIZE));\n            break;\n        }\n\n        switch (eb_id)\n        {\n            /* process security descriptor extra data if:\n                 Caller is WinNT AND\n                 Target local/remote drive supports acls AND\n                 Target file is not a directory (else we defer processing\n                   until later)\n             */\n            case EF_NTSD:\n                if (!IsWinNT())\n                    break; /* OS not capable of handling NTFS attributes */\n\n                if (eb_len < EB_NTSD_L_LEN)\n                    break; /* not a valid NTSD extra field */\n\n                /* check if we know how to handle this version */\n                if (*(ef_ptr + (EB_HEADSIZE+EB_NTSD_VERSION))\n                    > (uch)EB_NTSD_MAX_VER)\n                    break;\n\n                *p_ebSD_ptr = ef_ptr;\n                *p_ebSD_len = eb_len;\n                rc = TRUE;\n                break;\n\n#ifdef DEBUG\n            case EF_OS2:\n            case EF_AV:\n            case EF_PKVMS:\n            case EF_PKW32:\n            case EF_PKUNIX:\n            case EF_IZVMS:\n            case EF_IZUNIX:\n            case EF_IZUNIX2:\n            case EF_TIME:\n            case EF_MAC3:\n            case EF_JLMAC:\n            case EF_ZIPIT:\n            case EF_VMCMS:\n            case EF_MVS:\n            case EF_ACL:\n            case EF_ATHEOS:\n            case EF_BEOS:\n            case EF_QDOS:\n            case EF_AOSVS:\n            case EF_SPARK:\n            case EF_MD5:\n            case EF_ASIUNIX:\n                break;          /* shut up for other known e.f. blocks  */\n#endif /* DEBUG */\n\n            default:\n                Trace((stderr,\n                  \"FindSDExtraField: unknown extra field block, ID=%u\\n\",\n                  eb_id));\n                break;\n        }\n\n        ef_ptr += (eb_len + EB_HEADSIZE);\n        ef_len -= (eb_len + EB_HEADSIZE);\n    }\n\n    return rc;\n}\n\n\n\n\n#ifndef SFX\n\n/**************************/\n/*  Function test_NTSD()  */   /*  returns PK_WARN when NTSD data is invalid */\n/**************************/\n\n#ifdef __BORLANDC__\n/* Turn off warning about not using all parameters for this function only */\n#pragma argsused\n#endif\nint test_NTSD(__G__ eb, eb_size, eb_ucptr, eb_ucsize)\n    __GDEF\n    uch *eb;\n    unsigned eb_size;\n    uch *eb_ucptr;\n    ulg eb_ucsize;\n{\n    return (ValidateSecurity(eb_ucptr) ? PK_OK : PK_WARN);\n} /* end function test_NTSD() */\n\n#endif /* !SFX */\n#endif /* NTSD_EAS */\n\n\n\n\n/**********************/\n/* Function IsWinNT() */\n/**********************/\n\nint IsWinNT(void)       /* returns TRUE if real NT, FALSE if Win9x or Win32s */\n{\n    static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */\n\n    if (g_PlatformId == 0xFFFFFFFF) {\n        /* note: GetVersionEx() doesn't exist on WinNT 3.1 */\n        if (GetVersion() < 0x80000000)\n            g_PlatformId = TRUE;\n        else\n            g_PlatformId = FALSE;\n    }\n    return (int)g_PlatformId;\n}\n\n\n/* DEBUG_TIME insertion: */\n#ifdef DEBUG_TIME\nstatic int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft);\n\nstatic int show_NTFileTime(FILE *hdo, char *TTmsg, int isloc, FILETIME *pft)\n{\n    SYSTEMTIME w32tm;\n    int rval;\n\n    rval = FileTimeToSystemTime(pft, &w32tm);\n    if (!rval) {\n        fprintf(hdo, \"%s\\n %08lX,%08lX (%s) -> Conversion failed !!!\\n\",\n                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),\n                (isloc ? \"local\" : \"UTC\"));\n    } else {\n        fprintf(hdo, \"%s\\n %08lx,%08lx -> %04u-%02u-%02u, %02u:%02u:%02u %s\\n\",\n                TTmsg, (ulg)(pft->dwHighDateTime), (ulg)(pft->dwLowDateTime),\n                w32tm.wYear, w32tm.wMonth, w32tm.wDay, w32tm.wHour,\n                w32tm.wMinute, w32tm.wSecond, (isloc ? \"local\" : \"UTC\"));\n    }\n    return rval;\n}\n#define FTTrace(x)   show_NTFileTime x\n#else\n#define FTTrace(x)\n#endif /* DEBUG_TIME */\n/* end of DEBUG_TIME insertion */\n\n#ifndef IZ_USE_INT64\n#  if (defined(__GNUC__) || defined(ULONG_LONG_MAX))\n     typedef long long            LLONG64;\n     typedef unsigned long long   ULLNG64;\n#    define IZ_USE_INT64\n#  elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n     typedef __int64              LLONG64;\n     typedef unsigned __int64     ULLNG64;\n#    define IZ_USE_INT64\n#  elif (defined(_MSC_VER) && (_MSC_VER >= 1100))\n     typedef __int64              LLONG64;\n     typedef unsigned __int64     ULLNG64;\n#    define IZ_USE_INT64\n#  elif (defined(__IBMC__) && (__IBMC__ >= 350))\n     typedef __int64              LLONG64;\n     typedef unsigned __int64     ULLNG64;\n#    define IZ_USE_INT64\n#  elif defined(HAVE_INT64)\n     typedef __int64              LLONG64;\n     typedef unsigned __int64     ULLNG64;\n#    define IZ_USE_INT64\n#  endif\n#endif\n\n/* scale factor and offset for conversion time_t -> FILETIME */\n#define NT_QUANTA_PER_UNIX 10000000L\n#define UNIX_TIME_ZERO_HI  0x019DB1DEUL\n#define UNIX_TIME_ZERO_LO  0xD53E8000UL\n/* special FILETIME values for bound-checks */\n#define UNIX_TIME_UMAX_HI  0x0236485EUL\n#define UNIX_TIME_UMAX_LO  0xD4A5E980UL\n#define UNIX_TIME_SMIN_HI  0x0151669EUL\n#define UNIX_TIME_SMIN_LO  0xD53E8000UL\n#define UNIX_TIME_SMAX_HI  0x01E9FD1EUL\n#define UNIX_TIME_SMAX_LO  0xD4A5E980UL\n#define DOSTIME_MIN_FT_HI  0x01A8E79FUL\n#define DOSTIME_MIN_FT_LO  0xE1D58000UL\n/* time_t equivalent of DOSTIME_MINIMUM */\n#define UTIME_1980_JAN_01_00_00   315532800L\n\n\n#ifndef NO_W32TIMES_IZFIX\n/*********************************/\n/* Function utime2NtfsFileTime() */ /* convert Unix time_t format into the */\n/*********************************/ /* form used by SetFileTime() in NT/9x */\n\nstatic void utime2NtfsFileTime(time_t ut, FILETIME *pft)\n{\n#ifdef IZ_USE_INT64\n    ULLNG64 NTtime;\n\n    /* NT_QUANTA_PER_UNIX is small enough so that \"ut * NT_QUANTA_PER_UNIX\"\n     * cannot overflow in 64-bit signed calculation, regardless whether \"ut\"\n     * is signed or unsigned.  */\n    NTtime = ((LLONG64)ut * NT_QUANTA_PER_UNIX) +\n             ((ULLNG64)UNIX_TIME_ZERO_LO + ((ULLNG64)UNIX_TIME_ZERO_HI << 32));\n    pft->dwLowDateTime = (DWORD)NTtime;\n    pft->dwHighDateTime = (DWORD)(NTtime >> 32);\n\n#else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */\n    unsigned int b1, b2, carry = 0;\n    unsigned long r0, r1, r2, r3;\n    long r4;            /* signed, to catch environments with signed time_t */\n\n    b1 = ut & 0xFFFF;\n    b2 = (ut >> 16) & 0xFFFF;       /* if ut is over 32 bits, too bad */\n    r1 = b1 * (NT_QUANTA_PER_UNIX & 0xFFFF);\n    r2 = b1 * (NT_QUANTA_PER_UNIX >> 16);\n    r3 = b2 * (NT_QUANTA_PER_UNIX & 0xFFFF);\n    r4 = b2 * (NT_QUANTA_PER_UNIX >> 16);\n    r0 = (r1 + (r2 << 16)) & 0xFFFFFFFFL;\n    if (r0 < r1)\n        carry++;\n    r1 = r0;\n    r0 = (r0 + (r3 << 16)) & 0xFFFFFFFFL;\n    if (r0 < r1)\n        carry++;\n    pft->dwLowDateTime = r0 + UNIX_TIME_ZERO_LO;\n    if (pft->dwLowDateTime < r0)\n        carry++;\n    pft->dwHighDateTime = r4 + (r2 >> 16) + (r3 >> 16)\n                            + UNIX_TIME_ZERO_HI + carry;\n#endif /* ?IZ_USE_INT64 */\n\n} /* end function utime2NtfsFileTime() */\n#endif /* !NO_W32TIMES_IZFIX */\n\n\n\n/*********************************/\n/* Function utime2VFatFileTime() */ /* convert Unix time_t format into the */\n/*********************************/ /* form used by SetFileTime() in NT/9x */\n\nstatic void utime2VFatFileTime(time_t ut, FILETIME *pft, int clipDosMin)\n{\n    time_t utc = ut;\n    struct tm *ltm;\n    SYSTEMTIME w32tm;\n    FILETIME lft;\n\n    /* The milliseconds field gets always initialized to 0. */\n    w32tm.wMilliseconds = 0;\n\n#ifdef __BORLANDC__   /* Borland C++ 5.x crashes when trying to reference tm */\n    if (utc < UTIME_1980_JAN_01_00_00)\n        utc = UTIME_1980_JAN_01_00_00;\n#endif\n    ltm = localtime(&utc);\n    if (ltm == (struct tm *)NULL)\n        /* localtime() did not accept given utc time value; try to use\n           the UTC value */\n        ltm = gmtime(&utc);\n    if (ltm == (struct tm *)NULL) {\n        if (ut <= (UTIME_1980_JAN_01_00_00 + 86400)) {\n            /* use DOSTIME_MINIMUM date instead of \"early\" failure dates */\n            w32tm.wYear = 1980;\n            w32tm.wMonth = 1;\n            w32tm.wDay = 1;\n            w32tm.wHour = 0;\n            w32tm.wMinute = 0;\n            w32tm.wSecond = 0;\n        } else {\n            /* as a last resort, use the current system time */\n            GetLocalTime(&w32tm);\n        }\n    } else if (clipDosMin && (ltm->tm_year < 80)) {\n        w32tm.wYear = 1980;\n        w32tm.wMonth = 1;\n        w32tm.wDay = 1;\n        w32tm.wHour = 0;\n        w32tm.wMinute = 0;\n        w32tm.wSecond = 0;\n    } else {\n        w32tm.wYear = ltm->tm_year + 1900; /* year + 1900 -> year */\n        w32tm.wMonth = ltm->tm_mon + 1;    /* 0..11 -> 1..12 */\n        w32tm.wDay = ltm->tm_mday;         /* 1..31 */\n        w32tm.wHour = ltm->tm_hour;        /* 0..23 */\n        w32tm.wMinute = ltm->tm_min;       /* 0..59 */\n        w32tm.wSecond = ltm->tm_sec;       /* 0..61 in ANSI C */\n    }\n\n    SystemTimeToFileTime(&w32tm, &lft);\n    LocalFileTimeToFileTime(&lft, pft);\n\n} /* end function utime2VFatFileTime() */\n\n\n\n /* nonzero if `y' is a leap year, else zero */\n#define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)\n /* number of leap years from 1970 to `y' (not including `y' itself) */\n#define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)\n\nextern ZCONST ush ydays[];              /* defined in fileio.c */\n\n#if (defined(W32_STAT_BANDAID) && !defined(NO_W32TIMES_IZFIX))\n/*********************************/\n/* Function NtfsFileTime2utime() */\n/*********************************/\n\nstatic int NtfsFileTime2utime(const FILETIME *pft, time_t *ut)\n{\n#ifdef IZ_USE_INT64\n    ULLNG64 NTtime;\n\n    NTtime = ((ULLNG64)pft->dwLowDateTime +\n              ((ULLNG64)pft->dwHighDateTime << 32));\n\n#ifndef TIME_T_TYPE_DOUBLE\n    /* underflow and overflow handling */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +\n                      ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        }\n        if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +\n                      ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +\n                      ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +\n                      ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n#endif /* !TIME_T_TYPE_DOUBLE */\n\n    NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +\n               ((ULLNG64)UNIX_TIME_ZERO_HI << 32));\n    *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);\n    return TRUE;\n#else /* !IZ_USE_INT64 (64-bit integer arithmetics may not be supported) */\n    time_t days;\n    SYSTEMTIME w32tm;\n\n#ifndef TIME_T_TYPE_DOUBLE\n    /* underflow and overflow handling */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n#endif /* !TIME_T_TYPE_DOUBLE */\n\n    FileTimeToSystemTime(pft, &w32tm);\n\n    /* set `days' to the number of days into the year */\n    days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +\n           (w32tm.wMonth > 2 && leap (w32tm.wYear));\n\n    /* now set `days' to the number of days since 1 Jan 1970 */\n    days += 365 * (time_t)(w32tm.wYear - 1970) +\n            (time_t)(nleap(w32tm.wYear));\n\n    *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +\n                   (time_t)(60 * w32tm.wMinute + w32tm.wSecond));\n    return TRUE;\n#endif /* ?IZ_USE_INT64 */\n} /* end function NtfsFileTime2utime() */\n#endif /* W32_STAT_BANDAID && !NO_W32TIMES_IZFIX */\n\n\n\n#ifdef W32_STAT_BANDAID\n/*********************************/\n/* Function VFatFileTime2utime() */\n/*********************************/\n\nstatic int VFatFileTime2utime(const FILETIME *pft, time_t *ut)\n{\n    FILETIME lft;\n#ifndef HAVE_MKTIME\n    WORD wDOSDate, wDOSTime;\n#else\n    SYSTEMTIME w32tm;\n    struct tm ltm;\n#endif\n\n    if (!FileTimeToLocalFileTime(pft, &lft)) {\n        /* if pft cannot be converted to local time, set ut to current time */\n        time(ut);\n        return FALSE;\n    }\n    FTTrace((stdout, \"VFatFT2utime, feed for mktime()\", 1, &lft));\n#ifndef HAVE_MKTIME\n    /* This version of the FILETIME-to-UNIXTIME conversion function\n     * uses DOS-DATE-TIME format as intermediate stage. For modification\n     * and access times, this is no problem. But, the extra fine resolution\n     * of the VFAT-stored creation time gets lost.\n     */\n    if (!FileTimeToDosDateTime(&lft, &wDOSDate, &wDOSTime)) {\n        static const FILETIME dosmin_ft =\n                {DOSTIME_MIN_FT_LO, DOSTIME_MIN_FT_HI};\n        if (CompareFileTime(&lft, &dosmin_ft) <= 0) {\n            /* underflow -> set to minimum DOS time */\n            wDOSDate = (WORD)((DWORD)DOSTIME_MINIMUM >> 16);\n            wDOSTime = (WORD)DOSTIME_MINIMUM;\n        } else {\n            /* overflow -> set to maximum DOS time */\n            wDOSDate = (WORD)0xFF9F;    /* 2107-12-31 */\n            wDOSTime = (WORD)0xBF7D;    /* 23:59:58 */\n        }\n    }\n    TTrace((stdout,\"DosDateTime is %04u-%02u-%02u %02u:%02u:%02u\\n\",\n      (unsigned)((wDOSDate>>9)&0x7f)+1980,(unsigned)((wDOSDate>>5)&0x0f),\n      (unsigned)(wDOSDate&0x1f),(unsigned)((wDOSTime>>11)&0x1f),\n      (unsigned)((wDOSTime>>5)&0x3f),(unsigned)((wDOSTime<<1)&0x3e)));\n    *ut = dos_to_unix_time(((ulg)wDOSDate << 16) | (ulg)wDOSTime);\n\n    /* a cheap error check: dos_to_unix_time() only returns an odd time\n     * when clipping at maximum time_t value. DOS_DATE_TIME values have\n     * a resolution of 2 seconds and are therefore even numbers.\n     */\n    return (((*ut)&1) == (time_t)0);\n#else /* HAVE_MKTIME */\n    FileTimeToSystemTime(&lft, &w32tm);\n#ifndef TIME_T_TYPE_DOUBLE\n    /* underflow and overflow handling */\n    /* TODO: The range checks are not accurate, the actual limits may\n     *       be off by one daylight-saving-time shift (typically 1 hour),\n     *       depending on the current state of \"is_dst\".\n     */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n#endif /* !TIME_T_TYPE_DOUBLE */\n    ltm.tm_year = w32tm.wYear - 1900;\n    ltm.tm_mon = w32tm.wMonth - 1;\n    ltm.tm_mday = w32tm.wDay;\n    ltm.tm_hour = w32tm.wHour;\n    ltm.tm_min = w32tm.wMinute;\n    ltm.tm_sec = w32tm.wSecond;\n    ltm.tm_isdst = -1;  /* let mktime determine if DST is in effect */\n    *ut = mktime(&ltm);\n\n    /* a cheap error check: mktime returns \"(time_t)-1L\" on conversion errors.\n     * Normally, we would have to apply a consistency check because \"-1\"\n     * could also be a valid time. But, it is quite unlikely to read back odd\n     * time numbers from file systems that store time stamps in DOS format.\n     * (The only known exception is creation time on VFAT partitions.)\n     */\n    return (*ut != (time_t)-1L);\n#endif /* ?HAVE_MKTIME */\n\n} /* end function VFatFileTime2utime() */\n#endif /* W32_STAT_BANDAID */\n\n\n\n/******************************/\n/* Function FStampIsLocTime() */\n/******************************/\n\nstatic int FStampIsLocTime(__GPRO__ const char *path)\n{\n    return (NTQueryVolInfo(__G__ path) ? G.lastVolLocTim : FALSE);\n}\n\n\n\n#ifndef NO_W32TIMES_IZFIX\n# define UTIME_2_IZFILETIME(ut, pft) \\\n   if (fs_uses_loctime) {utime2VFatFileTime(ut, pft, TRUE);} \\\n   else {utime2NtfsFileTime(ut, pft);}\n#else\n# define UTIME_2_IZFILETIME(ut, pft) \\\n   utime2VFatFileTime(ut, pft, fs_uses_loctime);\n#endif\n\n\n\n/****************************/      /* Get the file time in a format that */\n/* Function getNTfiletime() */      /*  can be used by SetFileTime() in NT */\n/****************************/\n\nstatic int getNTfiletime(__G__ pModFT, pAccFT, pCreFT)\n    __GDEF\n    FILETIME *pModFT;\n    FILETIME *pAccFT;\n    FILETIME *pCreFT;\n{\n#ifdef USE_EF_UT_TIME\n    unsigned eb_izux_flg;\n    iztimes z_utime;   /* struct for Unix-style actime & modtime, + creatime */\n#endif\n    int fs_uses_loctime = FStampIsLocTime(__G__ G.filename);\n\n    /* Copy and/or convert time and date variables, if necessary;\n     * return a flag indicating which time stamps are available. */\n#ifdef USE_EF_UT_TIME\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        ((eb_izux_flg = ef_scan_for_izux(G.extra_field,\n          G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n          &z_utime, NULL)) & EB_UT_FL_MTIME))\n    {\n        TTrace((stderr, \"getNTfiletime:  Unix e.f. modif. time = %lu\\n\",\n          z_utime.mtime));\n        UTIME_2_IZFILETIME(z_utime.mtime, pModFT)\n        if (eb_izux_flg & EB_UT_FL_ATIME) {\n            UTIME_2_IZFILETIME(z_utime.atime, pAccFT)\n        }\n        if (eb_izux_flg & EB_UT_FL_CTIME) {\n            UTIME_2_IZFILETIME(z_utime.ctime, pCreFT)\n        }\n        return (int)eb_izux_flg;\n    }\n#endif /* USE_EF_UT_TIME */\n#ifndef NO_W32TIMES_IZFIX\n    if (!fs_uses_loctime) {\n        time_t ux_modtime;\n\n        ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n        utime2NtfsFileTime(ux_modtime, pModFT);\n    } else\n#endif /* NO_W32TIMES_IZFIX */\n    {\n        FILETIME lft;\n\n        DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16),\n                              (WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL),\n                              &lft);\n        LocalFileTimeToFileTime(&lft, pModFT);\n    }\n    *pAccFT = *pModFT;\n    return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n\n} /* end function getNTfiletime() */\n\n\n\n\n/**************************/\n/* Function SetFileSize() */\n/**************************/\n\nint SetFileSize(FILE *file, zusz_t filesize)\n{\n#ifdef __RSXNT__\n    /* RSXNT environment lacks a translation function from C file pointer\n       to Win32-API file handle. So, simply do nothing. */\n    return 0;\n#else /* !__RSXNT__ */\n    /* not yet verified, if that really creates an unfragmented file\n      rommel@ars.de\n     */\n    HANDLE os_fh;\n#ifdef Z_UINT8_DEFINED\n    LARGE_INTEGER fsbuf;\n#endif\n\n    /* Win9x supports FAT file system, only; presetting file size does\n       not help to prevent fragmentation. */\n    if (!IsWinNT()) return 0;\n\n    /* Win32-API calls require access to the Win32 file handle.\n       The interface function used to retrieve the Win32 handle for\n       a file opened by the C rtl is non-standard and may not be\n       available for every Win32 compiler environment.\n       (see also win32/win32.c of the Zip distribution)\n     */\n    os_fh = (HANDLE)_get_osfhandle(fileno(file));\n    /* move file pointer behind the last byte of the expected file size */\n#ifdef Z_UINT8_DEFINED\n    fsbuf.QuadPart = filesize;\n    if ((SetFilePointer(os_fh, fsbuf.LowPart, &fsbuf.HighPart, FILE_BEGIN)\n         == 0xFFFFFFFF) && GetLastError() != NO_ERROR)\n#else\n    if (SetFilePointer(os_fh, (ulg)filesize, 0, FILE_BEGIN) == 0xFFFFFFFF)\n#endif\n        return -1;\n    /* extend/truncate file to the current position */\n    if (SetEndOfFile(os_fh) == 0)\n        return -1;\n    /* move file position pointer back to the start of the file! */\n    return (SetFilePointer(os_fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) ? -1 : 0;\n#endif /* ?__RSXNT__ */\n} /* end function SetFileSize() */\n\n\n\n\n/****************************/\n/* Function close_outfile() */\n/****************************/\n\nvoid close_outfile(__G)\n    __GDEF\n{\n    FILETIME Modft;    /* File time type defined in NT, `last modified' time */\n    FILETIME Accft;    /* NT file time type, `last access' time */\n    FILETIME Creft;    /* NT file time type, `file creation' time */\n    HANDLE hFile = INVALID_HANDLE_VALUE;        /* File handle defined in NT */\n    int gotTime;\n#ifdef NTSD_EAS\n    uch *ebSDptr;\n    unsigned ebSDlen;\n#endif\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n    char *ansi_name = (char *)alloca(strlen(G.filename) + 1);\n\n    INTERN_TO_ISO(G.filename, ansi_name);\n#   define Ansi_Fname  ansi_name\n#else\n#   define Ansi_Fname  G.filename\n#endif\n\n#ifndef __RSXNT__\n    if (IsWinNT()) {\n        /* Truncate the file to the current position.\n         * This is needed to remove excess allocation in case the\n         * extraction has failed or stopped prematurely. */\n        SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));\n    }\n#endif\n\n    /* Close the file and then re-open it using the Win32\n     * CreateFile call, so that the file can be created\n     * with GENERIC_WRITE access, otherwise the SetFileTime\n     * call will fail. */\n    fclose(G.outfile);\n\n    /* don't set the time stamp and attributes on standard output */\n    if (uO.cflag)\n        return;\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);\n\n        /* open a handle to the file before processing extra fields;\n           we do this in case new security on file prevents us from updating\n           time stamps */\n        hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n    } else {\n        gotTime = 0;\n    }\n\n    /* sfield@microsoft.com: set attributes before time in case we decide to\n       support other filetime members later.  This also allows us to apply\n       attributes before the security is changed, which may prevent this\n       from succeeding otherwise.  Also, since most files don't have\n       any interesting attributes, only change them if something other than\n       FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well\n       as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the\n       file anyway, when it's created new. */\n    if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {\n        if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))\n            Info(slide, 1, ((char *)slide,\n              \"\\nwarning (%d): could not set file attributes\\n\",\n              (int)GetLastError()));\n    }\n\n#ifdef NTSD_EAS\n    /* set NTFS SD extra fields */\n    if (G.extra_field &&    /* zipfile extra field may have extended attribs */\n        FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n                         &ebSDptr, &ebSDlen))\n    {\n        int err = SetSD(__G__ Ansi_Fname, G.pInfo->file_attr,\n                        ebSDptr, ebSDlen);\n\n        if (err == IZ_EF_TRUNC) {\n            if (uO.qflag)\n                Info(slide, 1, ((char *)slide, \"%-22s \",\n                  FnFilter1(G.filename)));\n            Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),\n              ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? \"\\n\":\"\"));\n        }\n    }\n#endif /* NTSD_EAS */\n\n    /* skip restoring time stamps on user's request */\n    if (uO.D_flag <= 1) {\n        if ( hFile == INVALID_HANDLE_VALUE )\n            Info(slide, 1, ((char *)slide,\n              \"\\nCreateFile() error %d when trying set file time\\n\",\n              (int)GetLastError()));\n        else {\n            if (gotTime) {\n                FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;\n                FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;\n                FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;\n\n                if (!SetFileTime(hFile, pCreft, pAccft, pModft))\n                    Info(slide, 0, ((char *)slide,\n                      \"\\nSetFileTime failed: %d\\n\", (int)GetLastError()));\n            }\n            CloseHandle(hFile);\n        }\n    }\n\n    return;\n\n#undef Ansi_Fname\n\n} /* end function close_outfile() */\n\n\n\n\n#ifdef SET_DIR_ATTRIB\n\nint defer_dir_attribs(__G__ pd)\n    __GDEF\n    direntry **pd;\n{\n    NTdirattr *d_entry;\n#ifdef NTSD_EAS\n    uch *ebSDptr;\n    unsigned ebSDlen;\n#endif\n\n    /* Win9x does not support setting directory time stamps. */\n    if (!IsWinNT()) {\n        *pd = (direntry *)NULL;\n        return PK_OK;\n    }\n\n#ifdef NTSD_EAS\n    /* set extended attributes from extra fields */\n    if (G.extra_field &&  /* zipfile e.f. may have extended attribs */\n        FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n                         &ebSDptr, &ebSDlen)) {\n        /* ebSDlen contains the payload size of the e.f. block, but\n           we store it including the e.b. header. */\n        ebSDlen += EB_HEADSIZE;\n    } else {\n        /* no NTSD e.f. block -> no space needed to allocate */\n        ebSDlen = 0;\n    }\n#endif /* NTSD_EAS */\n\n    d_entry = (NTdirattr *)malloc(sizeof(NTdirattr)\n#ifdef NTSD_EAS\n                                  + ebSDlen\n#endif\n                                  + strlen(G.filename));\n    *pd = (direntry *)d_entry;\n    if (d_entry == (NTdirattr *)NULL) {\n        return PK_MEM;\n    }\n#ifdef NTSD_EAS\n    if (ebSDlen > 0)\n        memcpy(d_entry->buf, ebSDptr, ebSDlen);\n    d_entry->SDlen = ebSDlen;\n    d_entry->fn = d_entry->buf + ebSDlen;\n#else\n    d_entry->fn = d_entry->buf;\n#endif\n\n    strcpy(d_entry->fn, G.filename);\n\n    d_entry->perms = G.pInfo->file_attr;\n\n    d_entry->gotTime = (uO.D_flag <= 0\n                        ? getNTfiletime(__G__ &(d_entry->Modft),\n                                        &(d_entry->Accft), &(d_entry->Creft))\n                        : 0);\n    return PK_OK;\n} /* end function defer_dir_attribs() */\n\n\nint set_direc_attribs(__G__ d)\n    __GDEF\n    direntry *d;\n{\n    int errval;\n    HANDLE hFile = INVALID_HANDLE_VALUE;        /* File handle defined in NT */\n#ifdef __RSXNT__\n    char *ansi_name;\n#endif\n\n    /* Win9x does not support setting directory time stamps. */\n    if (!IsWinNT())\n        return PK_OK;\n\n    errval = PK_OK;\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n    ansi_name = (char *)alloca(strlen(d->fn) + 1);\n    INTERN_TO_ISO(d->fn, ansi_name);\n#   define Ansi_Dirname  ansi_name\n#else\n#   define Ansi_Dirname  d->fn\n#endif\n\n    /* Skip restoring directory time stamps on user' request. */\n    if (uO.D_flag <= 0) {\n        /* Open a handle to the directory before processing extra fields;\n           we do this in case new security on file prevents us from updating\n           time stamps.\n           Although the WIN32 documentation recommends to use GENERIC_WRITE\n           access flag to create the handle for SetFileTime(), this is too\n           demanding for directories with the \"read-only\" attribute bit set.\n           So we use the more specific flag FILE_WRITE_ATTRIBUTES here to\n           request the minimum required access rights. (This problem is a\n           Windows bug that has been silently fixed in Windows XP SP2.) */\n        hFile = CreateFileA(Ansi_Dirname, FILE_WRITE_ATTRIBUTES,\n                            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,\n                            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\n    }\n\n#ifdef NTSD_EAS\n    if (NtAtt(d)->SDlen > 0) {\n        int err;\n\n        if (QCOND2) {\n            Info(slide, 1, ((char *)slide, \" set attrib: %-22s  \",\n              FnFilter1(d->fn)));\n        }\n\n        /* set NTFS SD extra fields */\n        err = SetSD(__G__ Ansi_Dirname, NtAtt(d)->perms,\n                        NtAtt(d)->buf, NtAtt(d)->SDlen - EB_HEADSIZE);\n        if (err == IZ_EF_TRUNC) {\n            if (!QCOND2)\n                Info(slide, 1, ((char *)slide, \"%-22s  \",\n                  FnFilter1(d->fn)));\n            Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),\n              NtAtt(d)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), \"\\n\"));\n        } else if (QCOND2) {\n            Info(slide, 0, ((char *)slide, \"\\n\"));\n        }\n        if (errval < err)\n            errval = err;\n    }\n#endif /* NTSD_EAS */\n\n    /* Skip restoring directory time stamps on user' request. */\n    if (uO.D_flag <= 0) {\n        if (hFile == INVALID_HANDLE_VALUE) {\n            Info(slide, 1, ((char *)slide,\n              \"warning: CreateFile() error %d (set file times for %s)\\n\",\n              (int)GetLastError(), FnFilter1(d->fn)));\n            if (!errval)\n                errval = PK_WARN;\n        } else {\n            if (NtAtt(d)->gotTime) {\n                FILETIME *pModft = (NtAtt(d)->gotTime & EB_UT_FL_MTIME)\n                                  ? &(NtAtt(d)->Modft) : NULL;\n                FILETIME *pAccft = (NtAtt(d)->gotTime & EB_UT_FL_ATIME)\n                                  ? &(NtAtt(d)->Accft) : NULL;\n                FILETIME *pCreft = (NtAtt(d)->gotTime & EB_UT_FL_CTIME)\n                                  ? &(NtAtt(d)->Creft) : NULL;\n\n                if (!SetFileTime(hFile, pCreft, pAccft, pModft)) {\n                    Info(slide, 0, ((char *)slide,\n                      \"warning:  SetFileTime() for %s error %d\\n\",\n                      FnFilter1(d->fn), (int)GetLastError()));\n                    if (!errval)\n                        errval = PK_WARN;\n                }\n            }\n            CloseHandle(hFile);\n        }\n    }\n\n    return errval;\n} /* end function set_direc_attribs() */\n\n#endif /* SET_DIR_ATTRIB */\n\n\n\n\n#ifdef TIMESTAMP\n\n/*************************/\n/* Function stamp_file() */\n/*************************/\n\nint stamp_file(__GPRO__ ZCONST char *fname, time_t modtime)\n{\n    FILETIME Modft;    /* File time type defined in NT, `last modified' time */\n    HANDLE hFile;      /* File handle defined in NT    */\n    int errstat = 0;   /* return status: 0 == \"OK\", -1 == \"Failure\" */\n    int fs_uses_loctime = FStampIsLocTime(__G__ fname);\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n    char *ansi_name = (char *)alloca(strlen(fname) + 1);\n\n    INTERN_TO_ISO(fname, ansi_name);\n#   define Ansi_Fname  ansi_name\n#else\n#   define Ansi_Fname  fname\n#endif\n\n    /* open a handle to the file to prepare setting the mod-time stamp */\n    hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n    if ( hFile == INVALID_HANDLE_VALUE ) {\n        errstat = -1;\n    } else {\n        /* convert time_t modtime into WIN32 native 64bit format */\n        UTIME_2_IZFILETIME(modtime, &Modft)\n        /* set Access and Modification times of the file to modtime */\n        if (!SetFileTime(hFile, NULL, &Modft, &Modft)) {\n            errstat = -1;\n        }\n        CloseHandle(hFile);\n    }\n\n    return errstat;\n\n#undef Ansi_Fname\n} /* end function stamp_file() */\n\n#endif /* TIMESTAMP */\n\n\n\n\n/***********************/\n/* Function isfloppy() */   /* more precisely, is it removable? */\n/***********************/\n\nstatic int isfloppy(int nDrive)   /* 1 == A:, 2 == B:, etc. */\n{\n    char rootPathName[4];\n\n    rootPathName[0] = (char)('A' + nDrive - 1);   /* build the root path */\n    rootPathName[1] = ':';                        /*  name, e.g. \"A:/\" */\n    rootPathName[2] = '/';\n    rootPathName[3] = '\\0';\n\n    return (GetDriveTypeA(rootPathName) == DRIVE_REMOVABLE);\n\n} /* end function isfloppy() */\n\n\n\n\n/*****************************/\n/* Function NTQueryVolInfo() */\n/*****************************/\n\n/*\n * Note:  8.3 limits on filenames apply only to old-style FAT filesystems.\n *        More recent versions of Windows (Windows NT 3.5 / Windows 4.0)\n *        can support long filenames (LFN) on FAT filesystems.  Check the\n *        filesystem maximum component length field to detect LFN support.\n */\n\nstatic int NTQueryVolInfo(__GPRO__ const char *name)\n{\n /* static char lastRootPath[4] = \"\"; */\n /* static int lastVolOldFAT; */\n /* static int lastVolLocTim; */\n    char *tmp0;\n    char tmp1[MAX_PATH], tmp2[MAX_PATH];\n    DWORD volSerNo, maxCompLen, fileSysFlags;\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n    char *ansi_name = (char *)alloca(strlen(name) + 1);\n\n    INTERN_TO_ISO(name, ansi_name);\n    name = ansi_name;\n#endif\n\n    if ((!strncmp(name, \"//\", 2) || !strncmp(name, \"\\\\\\\\\", 2)) &&\n        (name[2] != '\\0' && name[2] != '/' && name[2] != '\\\\')) {\n        /* GetFullPathname() and GetVolumeInformation() do not work\n         * on UNC names. For now, we return \"error\".\n         * **FIXME**: check if UNC name is mapped to a drive letter\n         *            and use mapped drive for volume info query.\n         */\n        return FALSE;\n    }\n    if (isalpha((uch)name[0]) && (name[1] == ':'))\n        tmp0 = (char *)name;\n    else\n    {\n        if (!GetFullPathNameA(name, MAX_PATH, tmp1, &tmp0))\n            return FALSE;\n        tmp0 = &tmp1[0];\n    }\n    if (strncmp(G.lastRootPath, tmp0, 2) != 0) {\n        /* For speed, we skip repeated queries for the same device */\n        strncpy(G.lastRootPath, tmp0, 2);   /* Build the root path name, */\n        G.lastRootPath[2] = '/';            /* e.g. \"A:/\"                */\n        G.lastRootPath[3] = '\\0';\n\n        if (!GetVolumeInformationA((LPCSTR)G.lastRootPath,\n              (LPSTR)tmp1, (DWORD)MAX_PATH,\n              &volSerNo, &maxCompLen, &fileSysFlags,\n              (LPSTR)tmp2, (DWORD)MAX_PATH)) {\n            G.lastRootPath[0] = '\\0';\n            return FALSE;\n        }\n\n        /*  LFNs are available if the component length is > 12 */\n        G.lastVolOldFAT = (maxCompLen <= 12);\n/*      G.lastVolOldFAT = !strncmp(strupr(tmp2), \"FAT\", 3);   old version */\n\n        /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in\n         * local time!\n         */\n        G.lastVolLocTim = !strncmp(strupr(tmp2), \"VFAT\", 4) ||\n                          !strncmp(tmp2, \"HPFS\", 4) ||\n                          !strncmp(tmp2, \"FAT\", 3);\n    }\n\n    return TRUE;\n\n} /* end function NTQueryVolInfo() */\n\n\n\n\n/*****************************/\n/* Function IsVolumeOldFAT() */\n/*****************************/\n\nstatic int IsVolumeOldFAT(__GPRO__ const char *name)\n{\n    return (NTQueryVolInfo(__G__ name) ? G.lastVolOldFAT : FALSE);\n}\n\n\n\n\n#ifndef SFX\n\n/************************/\n/*  Function do_wild()  */   /* identical to OS/2 version */\n/************************/\n\nchar *do_wild(__G__ wildspec)\n    __GDEF\n    ZCONST char *wildspec;  /* only used first time on a given dir */\n{\n/* these statics are now declared in SYSTEM_SPECIFIC_GLOBALS in w32cfg.h:\n    static zDIR *wild_dir = NULL;\n    static ZCONST char *wildname;\n    static char *dirname, matchname[FILNAMSIZ];\n    static int notfirstcall=FALSE, have_dirname, dirnamelen;\n*/\n    char *fnamestart;\n    struct zdirent *file;\n\n    /* Even when we're just returning wildspec, we *always* do so in\n     * matchname[]--calling routine is allowed to append four characters\n     * to the returned string, and wildspec may be a pointer to argv[].\n     */\n    if (!G.notfirstcall) {  /* first call:  must initialize everything */\n        G.notfirstcall = TRUE;\n\n        if (!iswild(wildspec)) {\n            strncpy(G.matchname, wildspec, FILNAMSIZ);\n            G.matchname[FILNAMSIZ-1] = '\\0';\n            G.have_dirname = FALSE;\n            G.wild_dir = NULL;\n            return G.matchname;\n        }\n\n        /* break the wildspec into a directory part and a wildcard filename */\n        if ((G.wildname = MBSRCHR(wildspec, '/')) == (ZCONST char *)NULL &&\n            (G.wildname = MBSRCHR(wildspec, ':')) == (ZCONST char *)NULL) {\n            G.dirname = \".\";\n            G.dirnamelen = 1;\n            G.have_dirname = FALSE;\n            G.wildname = wildspec;\n        } else {\n            ++G.wildname;     /* point at character after '/' or ':' */\n            G.dirnamelen = G.wildname - wildspec;\n            if ((G.dirname = (char *)malloc(G.dirnamelen+1)) == NULL) {\n                Info(slide, 1, ((char *)slide,\n                  \"warning:  cannot allocate wildcard buffers\\n\"));\n                strncpy(G.matchname, wildspec, FILNAMSIZ);\n                G.matchname[FILNAMSIZ-1] = '\\0';\n                return G.matchname; /* but maybe filespec was not a wildcard */\n            }\n            strncpy(G.dirname, wildspec, G.dirnamelen);\n            G.dirname[G.dirnamelen] = '\\0';   /* terminate for strcpy below */\n            G.have_dirname = TRUE;\n        }\n        Trace((stderr, \"do_wild:  dirname = [%s]\\n\", FnFilter1(G.dirname)));\n\n        if ((G.wild_dir = (zvoid *)Opendir(G.dirname)) != NULL) {\n            if (G.have_dirname) {\n                strcpy(G.matchname, G.dirname);\n                fnamestart = G.matchname + G.dirnamelen;\n            } else\n                fnamestart = G.matchname;\n            while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {\n                Trace((stderr, \"do_wild:  Readdir returns %s\\n\",\n                  FnFilter1(file->d_name)));\n                strcpy(fnamestart, file->d_name);\n                if (MBSRCHR(fnamestart, '.') == (char *)NULL)\n                    strcat(fnamestart, \".\");\n                if (match(fnamestart, G.wildname, TRUE WISEP) &&\n                    /* skip \".\" and \"..\" directory entries */\n                    strcmp(fnamestart, \".\") && strcmp(fnamestart, \"..\")) {\n                    Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n                    /* remove trailing dot */\n                    fnamestart = plastchar(fnamestart, strlen(fnamestart));\n                    if (*fnamestart == '.')\n                        *fnamestart = '\\0';\n                    return G.matchname;\n                }\n            }\n            /* if we get to here directory is exhausted, so close it */\n            Closedir((zDIR *)G.wild_dir);\n            G.wild_dir = NULL;\n        }\n        Trace((stderr, \"do_wild:  Opendir(%s) returns NULL\\n\",\n          FnFilter1(G.dirname)));\n\n        /* return the raw wildspec in case that works (e.g., directory not\n         * searchable, but filespec was not wild and file is readable) */\n        strncpy(G.matchname, wildspec, FILNAMSIZ);\n        G.matchname[FILNAMSIZ-1] = '\\0';\n        return G.matchname;\n    }\n\n    /* last time through, might have failed opendir but returned raw wildspec */\n    if (G.wild_dir == NULL) {\n        G.notfirstcall = FALSE;    /* reset for new wildspec */\n        if (G.have_dirname)\n            free(G.dirname);\n        return (char *)NULL;\n    }\n\n    /* If we've gotten this far, we've read and matched at least one entry\n     * successfully (in a previous call), so dirname has been copied into\n     * matchname already.\n     */\n    if (G.have_dirname) {\n        /* strcpy(G.matchname, G.dirname); */\n        fnamestart = G.matchname + G.dirnamelen;\n    } else\n        fnamestart = G.matchname;\n    while ((file = Readdir((zDIR *)G.wild_dir)) != NULL) {\n        Trace((stderr, \"do_wild:  readdir returns %s\\n\",\n          FnFilter1(file->d_name)));\n        strcpy(fnamestart, file->d_name);\n        if (MBSRCHR(fnamestart, '.') == (char *)NULL)\n            strcat(fnamestart, \".\");\n        if (match(fnamestart, G.wildname, TRUE WISEP)) {\n            Trace((stderr, \"do_wild:  match() succeeds\\n\"));\n            /* remove trailing dot */\n            fnamestart = plastchar(fnamestart, strlen(fnamestart));\n            if (*fnamestart == '.')\n                *fnamestart = '\\0';\n            return G.matchname;\n        }\n    }\n\n    Closedir((zDIR *)G.wild_dir);  /* at least one entry read; nothing left */\n    G.wild_dir = NULL;\n    G.notfirstcall = FALSE;        /* reset for new wildspec */\n    if (G.have_dirname)\n        free(G.dirname);\n    return (char *)NULL;\n\n} /* end function do_wild() */\n\n#endif /* !SFX */\n\n\n\n/**********************/\n/* Function mapattr() */\n/**********************/\n\n/* Identical to MS-DOS, OS/2 versions.  However, NT has a lot of extra\n * permission stuff, so this function should probably be extended in the\n * future. */\n\nint mapattr(__G)\n    __GDEF\n{\n    /* set archive bit for file entries (file is not backed up): */\n    G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |\n      (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ?\n       0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff;\n    return 0;\n\n} /* end function mapattr() */\n\n\n\n\n/************************/\n/*  Function mapname()  */\n/************************/\n\nint mapname(__G__ renamed)\n    __GDEF\n    int renamed;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - caution (truncated filename)\n *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n *  MPN_ERR_SKIP    - error -> skip entry\n *  MPN_ERR_TOOLONG - error -> path is too long\n *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n */\n{\n    char pathcomp[FILNAMSIZ];   /* path-component buffer */\n    char *pp, *cp=NULL;         /* character pointers */\n    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */\n#ifdef ACORN_FTYPE_NFS\n    char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */\n    RO_extra_block *ef_spark;      /* pointer Acorn FTYPE ef block */\n#endif\n    int killed_ddot = FALSE;    /* is set when skipping \"../\" pathcomp */\n    int error;\n    register unsigned workch;   /* hold the character being tested */\n\n\n/*---------------------------------------------------------------------------\n    Initialize various pointers and counters and stuff.\n  ---------------------------------------------------------------------------*/\n\n    /* can create path as long as not just freshening, or if user told us */\n    G.create_dirs = (!uO.fflag || renamed);\n\n    G.created_dir = FALSE;      /* not yet */\n    G.renamed_fullpath = FALSE;\n    G.fnlen = strlen(G.filename);\n\n    if (renamed) {\n        cp = G.filename;    /* point to beginning of renamed name... */\n        if (*cp) do {\n            if (*cp == '\\\\')    /* convert backslashes to forward */\n                *cp = '/';\n        } while (*PREINCSTR(cp));\n        cp = G.filename;\n        /* use temporary rootpath if user gave full pathname */\n        if (G.filename[0] == '/') {\n            G.renamed_fullpath = TRUE;\n            pathcomp[0] = '/';  /* copy the '/' and terminate */\n            pathcomp[1] = '\\0';\n            ++cp;\n        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {\n            G.renamed_fullpath = TRUE;\n            pp = pathcomp;\n            *pp++ = *cp++;      /* copy the \"d:\" (+ '/', possibly) */\n            *pp++ = *cp++;\n            if (*cp == '/')\n                *pp++ = *cp++;  /* otherwise add \"./\"? */\n            *pp = '\\0';\n        }\n    }\n\n    /* pathcomp is ignored unless renamed_fullpath is TRUE: */\n    if ((error = checkdir(__G__ pathcomp, INIT)) != 0)    /* init path buffer */\n        return error;           /* ...unless no mem or vol label on hard disk */\n\n    *pathcomp = '\\0';           /* initialize translation buffer */\n    pp = pathcomp;              /* point to translation buffer */\n    if (!renamed) {             /* cp already set if renamed */\n        if (uO.jflag)           /* junking directories */\n            cp = (char *)MBSRCHR(G.filename, '/');\n        if (cp == NULL)         /* no '/' or not junking dirs */\n            cp = G.filename;    /* point to internal zipfile-member pathname */\n        else\n            ++cp;               /* point to start of last component of path */\n    }\n\n/*---------------------------------------------------------------------------\n    Begin main loop through characters in filename.\n  ---------------------------------------------------------------------------*/\n\n    for (; (workch = (uch)*cp) != 0; INCSTR(cp)) {\n\n        switch (workch) {\n            case '/':             /* can assume -j flag not given */\n                *pp = '\\0';\n                maskDOSdevice(__G__ pathcomp);\n                if (strcmp(pathcomp, \".\") == 0) {\n                    /* don't bother appending \"./\" to the path */\n                    *pathcomp = '\\0';\n                } else if (!uO.ddotflag && strcmp(pathcomp, \"..\") == 0) {\n                    /* \"../\" dir traversal detected, skip over it */\n                    *pathcomp = '\\0';\n                    killed_ddot = TRUE;     /* set \"show message\" flag */\n                }\n                /* when path component is not empty, append it now */\n                if (*pathcomp != '\\0' &&\n                    ((error = checkdir(__G__ pathcomp, APPEND_DIR))\n                     & MPN_MASK) > MPN_INF_TRUNC)\n                    return error;\n                pp = pathcomp;    /* reset conversion buffer for next piece */\n                lastsemi = (char *)NULL; /* leave direct. semi-colons alone */\n                break;\n\n            case ':':             /* drive spec not stored, so no colon allowed */\n            case '\\\\':            /* '\\\\' may come as normal filename char (not */\n            case '<':             /*  dir sep char!) from unix-like file system */\n            case '>':             /* no redirection symbols allowed either */\n            case '|':             /* no pipe signs allowed */\n            case '\"':             /* no double quotes allowed */\n            case '?':             /* no wildcards allowed */\n            case '*':\n                *pp++ = '_';      /* these rules apply equally to FAT and NTFS */\n                break;\n            case ';':             /* start of VMS version? */\n                lastsemi = pp;    /* remove VMS version later... */\n                *pp++ = ';';      /*  but keep semicolon for now */\n                break;\n\n#ifdef ACORN_FTYPE_NFS\n            case ',':             /* NFS filetype extension */\n                lastcomma = pp;\n                *pp++ = ',';      /* keep for now; may need to remove */\n                break;            /*  later, if requested */\n#endif\n\n            case ' ':             /* keep spaces unless specifically */\n                /* NT cannot create filenames with spaces on FAT volumes */\n                if (uO.sflag || IsVolumeOldFAT(__G__ G.filename))\n                    *pp++ = '_';\n                else\n                    *pp++ = ' ';\n                break;\n\n            default:\n                /* allow European characters in filenames: */\n                if (isprint(workch) || workch >= 127)\n#ifdef _MBCS\n                {\n                    memcpy(pp, cp, CLEN(cp));\n                    INCSTR(pp);\n                }\n#else\n                    *pp++ = (char)workch;\n#endif\n        } /* end switch */\n\n    } /* end while loop */\n\n    /* Show warning when stripping insecure \"parent dir\" path components */\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n/*---------------------------------------------------------------------------\n    Report if directory was created (and no file to create:  filename ended\n    in '/'), check name to be sure it exists, and combine path and name be-\n    fore exiting.\n  ---------------------------------------------------------------------------*/\n\n    if (lastchar(G.filename, G.fnlen) == '/') {\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_name = (char *)alloca(strlen(G.filename) + 1);\n\n        INTERN_TO_ISO(G.filename, ansi_name);\n#       define Ansi_Fname  ansi_name\n#else\n#       define Ansi_Fname  G.filename\n#endif\n        checkdir(__G__ G.filename, GETPATH);\n        if (G.created_dir) {\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %-22s\\n\",\n                  FnFilter1(G.filename)));\n            }\n\n            /* set file attributes:\n               The default for newly created directories is \"DIR attribute\n               flags set\", so there is no need to change attributes unless\n               one of the DOS style attribute flags is set. The readonly\n               attribute need not be masked, since it does not prevent\n               modifications in the new directory. */\n            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {\n                if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))\n                    Info(slide, 1, ((char *)slide,\n                      \"\\nwarning (%d): could not set file attributes for %s\\n\",\n                      (int)GetLastError(), FnFilter1(G.filename)));\n            }\n\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        } else if (IS_OVERWRT_ALL) {\n            /* overwrite attributes of existing directory on user's request */\n\n            /* set file attributes: */\n            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {\n                if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))\n                    Info(slide, 1, ((char *)slide,\n                      \"\\nwarning (%d): could not set file attributes for %s\\n\",\n                      (int)GetLastError(), FnFilter1(G.filename)));\n            }\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    *pp = '\\0';                   /* done with pathcomp:  terminate it */\n\n    /* if not saving them, remove VMS version numbers (appended \"###\") */\n    if (!uO.V_flag && lastsemi) {\n        pp = lastsemi + 1;        /* semi-colon was kept:  expect #'s after */\n        while (isdigit((uch)(*pp)))\n            ++pp;\n        if (*pp == '\\0')          /* only digits between ';' and end:  nuke */\n            *lastsemi = '\\0';\n    }\n\n#ifdef ACORN_FTYPE_NFS\n    /* translate Acorn filetype information if asked to do so */\n    if (uO.acorn_nfs_ext &&\n        (ef_spark = (RO_extra_block *)\n                    getRISCOSexfield(G.extra_field, G.lrec.extra_field_length))\n        != (RO_extra_block *)NULL)\n    {\n        /* file *must* have a RISC OS extra field */\n        long ft = (long)makelong(ef_spark->loadaddr);\n        /*32-bit*/\n        if (lastcomma) {\n            pp = lastcomma + 1;\n            while (isxdigit((uch)(*pp))) ++pp;\n            if (pp == lastcomma+4 && *pp == '\\0') *lastcomma='\\0'; /* nuke */\n        }\n        if ((ft & 1<<31)==0) ft=0x000FFD00;\n        sprintf(pathcomp+strlen(pathcomp), \",%03x\", (int)(ft>>8) & 0xFFF);\n    }\n#endif /* ACORN_FTYPE_NFS */\n\n    maskDOSdevice(__G__ pathcomp);\n\n    if (*pathcomp == '\\0') {\n        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n          FnFilter1(G.filename)));\n        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n    }\n\n    checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */\n    checkdir(__G__ G.filename, GETPATH);\n\n    if (G.pInfo->vollabel) {    /* set the volume label now */\n        char drive[4];\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_name = (char *)alloca(strlen(G.filename) + 1);\n        INTERN_TO_ISO(G.filename, ansi_name);\n#       define Ansi_Fname  ansi_name\n#else\n#       define Ansi_Fname  G.filename\n#endif\n\n        /* Build a drive string, e.g. \"b:\" */\n        drive[0] = (char)('a' + G.nLabelDrive - 1);\n        strcpy(drive + 1, \":\\\\\");\n        if (QCOND2)\n            Info(slide, 0, ((char *)slide, \"labelling %s %-22s\\n\", drive,\n              FnFilter1(G.filename)));\n        if (!SetVolumeLabelA(drive, Ansi_Fname)) {\n            Info(slide, 1, ((char *)slide,\n              \"mapname:  error setting volume label\\n\"));\n            return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n        }\n        /* success:  skip the \"extraction\" quietly */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n#undef Ansi_Fname\n    }\n\n    Trace((stderr, \"mapname returns with filename = [%s] (error = %d)\\n\\n\",\n      FnFilter1(G.filename), error));\n    return error;\n\n} /* end function mapname() */\n\n\n\n\n/****************************/\n/* Function maskDOSdevice() */\n/****************************/\n\nstatic void maskDOSdevice(__G__ pathcomp)\n    __GDEF\n    char *pathcomp;\n{\n/*---------------------------------------------------------------------------\n    Put an underscore in front of the file name if the file name is a\n    DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to\n    extract such a file would fail at best and wedge us at worst.\n  ---------------------------------------------------------------------------*/\n#if !defined(S_IFCHR) && defined(_S_IFCHR)\n#  define S_IFCHR _S_IFCHR\n#endif\n#if !defined(S_ISCHR)\n# if defined(_S_ISCHR)\n#  define S_ISCHR(m) _S_ISCHR(m)\n# elif defined(S_IFCHR)\n#  define S_ISCHR(m) ((m) & S_IFCHR)\n# endif\n#endif\n\n#ifdef DEBUG\n    if (zstat(pathcomp, &G.statbuf) == 0) {\n        Trace((stderr,\n               \"maskDOSdevice() stat(\\\"%s\\\", buf) st_mode result: %X, %o\\n\",\n               FnFilter1(pathcomp), G.statbuf.st_mode, G.statbuf.st_mode));\n    } else {\n        Trace((stderr, \"maskDOSdevice() stat(\\\"%s\\\", buf) failed\\n\",\n               FnFilter1(pathcomp)));\n    }\n#endif\n    if (zstat(pathcomp, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) {\n        extent i;\n\n        /* pathcomp contains a name of a DOS character device (builtin or\n         * installed device driver).\n         * Prepend a '_' to allow creation of the item in the file system.\n         */\n        for (i = strlen(pathcomp) + 1; i > 0; --i)\n            pathcomp[i] = pathcomp[i - 1];\n        pathcomp[0] = '_';\n    }\n} /* end function maskDOSdevice() */\n\n\n\n\n\n/**********************/\n/* Function map2fat() */        /* Not quite identical to OS/2 version */\n/**********************/\n\nstatic void map2fat(pathcomp, pEndFAT)\n    char *pathcomp, **pEndFAT;\n{\n    char *ppc = pathcomp;       /* variable pointer to pathcomp */\n    char *pEnd = *pEndFAT;      /* variable pointer to buildpathFAT */\n    char *pBegin = *pEndFAT;    /* constant pointer to start of this comp. */\n    char *last_dot = NULL;      /* last dot not converted to underscore */\n    register unsigned workch;   /* hold the character being tested */\n\n\n    /* Only need check those characters which are legal in NTFS but not\n     * in FAT:  to get here, must already have passed through mapname.\n     * Also must truncate path component to ensure 8.3 compliance.\n     */\n    while ((workch = (uch)*ppc++) != 0) {\n        switch (workch) {\n            case '[':\n            case ']':\n            case '+':\n            case ',':\n            case ';':\n            case '=':\n                *pEnd++ = '_';      /* convert brackets to underscores */\n                break;\n\n            case '.':\n                if (pEnd == *pEndFAT) {   /* nothing appended yet... */\n                    if (*ppc == '\\0')     /* don't bother appending a */\n                        break;            /*  \"./\" component to the path */\n                    else if (*ppc == '.' && ppc[1] == '\\0') {   /* \"../\" */\n                        *pEnd++ = '.';    /*  add first dot, */\n                        *pEnd++ = '.';    /*  add second dot, and */\n                        ++ppc;            /*  skip over to pathcomp's end */\n                    } else {              /* FAT doesn't allow null filename */\n                        *pEnd++ = '_';    /*  bodies, so map .exrc -> _exrc */\n                    }                     /*  (_.exr would keep max 3 chars) */\n                } else {                  /* found dot within path component */\n                    last_dot = pEnd;      /*  point at last dot so far... */\n                    *pEnd++ = '_';        /*  convert to underscore for now */\n                }\n                break;\n\n            default:\n                *pEnd++ = (char)workch;\n\n        } /* end switch */\n    } /* end while loop */\n\n    *pEnd = '\\0';                 /* terminate buildpathFAT */\n\n    /* NOTE:  keep in mind that pEnd points to the end of the path\n     * component, and *pEndFAT still points to the *beginning* of it...\n     * Also note that the algorithm does not try to get too fancy:\n     * if there are no dots already, the name either gets truncated\n     * at 8 characters or the last underscore is converted to a dot\n     * (only if more characters are saved that way).  In no case is\n     * a dot inserted between existing characters.\n     */\n    if (last_dot == NULL) {       /* no dots:  check for underscores... */\n        char *plu = MBSRCHR(pBegin, '_');   /* pointer to last underscore */\n\n        if ((plu != NULL) &&      /* found underscore: convert to dot? */\n            (MIN(plu - pBegin, 8) + MIN(pEnd - plu - 1, 3) > 8)) {\n            last_dot = plu;       /* be lazy:  drop through to next if-blk */\n        } else if ((pEnd - *pEndFAT) > 8) {\n            /* no underscore; or converting underscore to dot would save less\n               chars than leaving everything in the basename */\n            *pEndFAT += 8;        /* truncate at 8 chars */\n            **pEndFAT = '\\0';\n        } else\n            *pEndFAT = pEnd;      /* whole thing fits into 8 chars or less */\n    }\n\n    if (last_dot != NULL) {       /* one dot is OK: */\n        *last_dot = '.';          /* put it back in */\n\n        if ((last_dot - pBegin) > 8) {\n            char *p, *q;\n            int i;\n\n            p = last_dot;\n            q = last_dot = pBegin + 8;\n            for (i = 0;  (i < 4) && *p;  ++i)  /* too many chars in basename: */\n                *q++ = *p++;                   /*  shift .ext left and trun- */\n            *q = '\\0';                         /*  cate/terminate it */\n            *pEndFAT = q;\n        } else if ((pEnd - last_dot) > 4) {    /* too many chars in extension */\n            *pEndFAT = last_dot + 4;\n            **pEndFAT = '\\0';\n        } else\n            *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */\n\n        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')\n            last_dot[-1] = '_';                /* NO blank in front of '.'! */\n    }\n} /* end function map2fat() */\n\n\n\n\n/***********************/       /* Borrowed from os2.c for UnZip 5.1.        */\n/* Function checkdir() */       /* Difference: no EA stuff                   */\n/***********************/       /*             HPFS stuff works on NTFS too  */\n\nint checkdir(__G__ pathcomp, flag)\n    __GDEF\n    char *pathcomp;\n    int flag;\n/*\n * returns:\n *  MPN_OK          - no problem detected\n *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n *                    exists and is not a directory, but is supposed to be\n *  MPN_ERR_TOOLONG - path is too long\n *  MPN_NOMEM       - can't allocate memory for filename buffers\n */\n{\n /* static int rootlen = 0;     */   /* length of rootpath */\n /* static char *rootpath;      */   /* user's \"extract-to\" directory */\n /* static char *buildpathHPFS; */   /* full path (so far) to extracted file, */\n /* static char *buildpathFAT;  */   /*  both HPFS/EA (main) and FAT versions */\n /* static char *endHPFS;       */   /* corresponding pointers to end of */\n /* static char *endFAT;        */   /*  buildpath ('\\0') */\n\n#   define FN_MASK   7\n#   define FUNCTION  (flag & FN_MASK)\n\n\n\n/*---------------------------------------------------------------------------\n    APPEND_DIR:  append the path component to the path being built and check\n    for its existence.  If doesn't exist and we are creating directories, do\n    so for this one; else signal success or error as appropriate.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_DIR) {\n        char *p = pathcomp;\n        int too_long = FALSE;\n\n        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n        while ((*G.endHPFS = *p++) != '\\0')     /* copy to HPFS filename */\n            ++G.endHPFS;\n        if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n            p = pathcomp;\n            while ((*G.endFAT = *p++) != '\\0')  /* copy to FAT filename, too */\n                ++G.endFAT;\n        } else\n            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */\n\n        /* GRR:  could do better check, see if overrunning buffer as we go:\n         * check endHPFS-buildpathHPFS after each append, set warning variable\n         * if within 20 of FILNAMSIZ; then if var set, do careful check when\n         * appending.  Clear variable when begin new path. */\n\n        /* next check:  need to append '/', at least one-char name, '\\0' */\n        if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)\n            too_long = TRUE;                    /* check if extracting dir? */\n#ifdef FIX_STAT_BUG\n        /* Borland C++ 5.0 does not handle a call to stat() well if the\n         * directory does not exist (it tends to crash in strange places.)\n         * This is apparently a problem only when compiling for GUI rather\n         * than console. The code below attempts to work around this problem.\n         */\n        if (access(G.buildpathFAT, 0) != 0) {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* path doesn't exist:  nothing to do */\n                return MPN_INF_SKIP;\n            }\n            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpathHPFS)));\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpathFAT),\n                  strerror(errno),\n                  FnFilter1(G.filename)));\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        }\n#endif /* FIX_STAT_BUG */\n        if (SSTAT(G.buildpathFAT, &G.statbuf))   /* path doesn't exist */\n        {\n            if (!G.create_dirs) { /* told not to create (freshening) */\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* path doesn't exist:  nothing to do */\n                return MPN_INF_SKIP;\n            }\n            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  path too long: %s\\n\",\n                  FnFilter1(G.buildpathHPFS)));\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* no room for filenames:  fatal */\n                return MPN_ERR_TOOLONG;\n            }\n            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n                Info(slide, 1, ((char *)slide,\n                  \"checkdir error:  cannot create %s\\n\\\n                 %s\\n\\\n                 unable to process %s.\\n\",\n                  FnFilter2(G.buildpathFAT),\n                  strerror(errno),\n                  FnFilter1(G.filename)));\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                /* path didn't exist, tried to create, failed */\n                return MPN_ERR_SKIP;\n            }\n            G.created_dir = TRUE;\n        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  %s exists but is not directory\\n\\\n                 unable to process %s.\\n\",\n              FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n            free(G.buildpathHPFS);\n            free(G.buildpathFAT);\n            /* path existed but wasn't dir */\n            return MPN_ERR_SKIP;\n        }\n        if (too_long) {\n            Info(slide, 1, ((char *)slide,\n              \"checkdir error:  path too long: %s\\n\",\n              FnFilter1(G.buildpathHPFS)));\n            free(G.buildpathHPFS);\n            free(G.buildpathFAT);\n            /* no room for filenames:  fatal */\n            return MPN_ERR_TOOLONG;\n        }\n        *G.endHPFS++ = '/';\n        *G.endFAT++ = '/';\n        *G.endHPFS = *G.endFAT = '\\0';\n        Trace((stderr, \"buildpathHPFS now = [%s]\\nbuildpathFAT now =  [%s]\\n\",\n          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n        return MPN_OK;\n\n    } /* end if (FUNCTION == APPEND_DIR) */\n\n/*---------------------------------------------------------------------------\n    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want\n    filename to reflect name used on disk, not EAs; if full path is HPFS,\n    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == GETPATH) {\n        Trace((stderr, \"getting and freeing FAT path [%s]\\n\",\n          FnFilter1(G.buildpathFAT)));\n        Trace((stderr, \"freeing HPFS path [%s]\\n\",\n          FnFilter1(G.buildpathHPFS)));\n        strcpy(pathcomp, G.buildpathFAT);\n        free(G.buildpathFAT);\n        free(G.buildpathHPFS);\n        G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    APPEND_NAME:  assume the path component is the filename; append it and\n    return without checking for existence.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == APPEND_NAME) {\n        char *p = pathcomp;\n        int error = MPN_OK;\n\n        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n        /* The buildpathHPFS buffer has been allocated large enough to\n         * hold the complete combined name, so there is no need to check\n         * for OS filename size limit overflow within the copy loop.\n         */\n        while ((*G.endHPFS = *p++) != '\\0') {   /* copy to HPFS filename */\n            ++G.endHPFS;\n        }\n        /* Now, check for OS filename size overflow.  When detected, the\n         * mapped HPFS name is truncated and a warning message is shown.\n         */\n        if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {\n            G.buildpathHPFS[FILNAMSIZ-1] = '\\0';\n            Info(slide, 1, ((char *)slide,\n              \"checkdir warning:  path too long; truncating\\n \\\n              %s\\n                -> %s\\n\",\n              FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));\n            error = MPN_INF_TRUNC;  /* filename truncated */\n        }\n\n        /* The buildpathFAT buffer has the same allocated size as the\n         * buildpathHPFS buffer, so there is no need for an overflow check\n         * within the following copy loop, either.\n         */\n        if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n            /* copy to FAT filename, too */\n            p = pathcomp;\n            while ((*G.endFAT = *p++) != '\\0')\n                ++G.endFAT;\n        } else\n            /* map into FAT fn, update endFAT */\n            map2fat(pathcomp, &G.endFAT);\n\n        /* Check that the FAT path does not exceed the FILNAMSIZ limit, and\n         * truncate when neccessary.\n         * Note that truncation can only happen when the HPFS path (which is\n         * never shorter than the FAT path) has been already truncated.\n         * So, emission of the warning message and setting the error code\n         * has already happened.\n         */\n        if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)\n            G.buildpathFAT[FILNAMSIZ-1] = '\\0';\n        Trace((stderr, \"buildpathHPFS: %s\\nbuildpathFAT:  %s\\n\",\n          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n\n        return error;  /* could check for existence, prompt for new name... */\n\n    } /* end if (FUNCTION == APPEND_NAME) */\n\n/*---------------------------------------------------------------------------\n    INIT:  allocate and initialize buffer space for the file currently being\n    extracted.  If file was renamed with an absolute path, don't prepend the\n    extract-to path.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == INIT) {\n        Trace((stderr, \"initializing buildpathHPFS and buildpathFAT to \"));\n#ifdef ACORN_FTYPE_NFS\n        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+\n                                              (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))\n#endif\n            == NULL)\n            return MPN_NOMEM;\n#ifdef ACORN_FTYPE_NFS\n        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+\n                                             (uO.acorn_nfs_ext ? 5 : 1)))\n#else\n        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))\n#endif\n            == NULL) {\n            free(G.buildpathHPFS);\n            return MPN_NOMEM;\n        }\n        if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */\n/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */\n            if (G.renamed_fullpath && pathcomp[1] == ':')\n                *G.buildpathHPFS = (char)ToLower(*pathcomp);\n            else if (!G.renamed_fullpath && G.rootlen > 1 &&\n                     G.rootpath[1] == ':')\n                *G.buildpathHPFS = (char)ToLower(*G.rootpath);\n            else {\n                char tmpN[MAX_PATH], *tmpP;\n                if (GetFullPathNameA(\".\", MAX_PATH, tmpN, &tmpP) > MAX_PATH)\n                { /* by definition of MAX_PATH we should never get here */\n                    Info(slide, 1, ((char *)slide,\n                      \"checkdir warning: current dir path too long\\n\"));\n                    return MPN_INF_TRUNC;   /* can't get drive letter */\n                }\n                G.nLabelDrive = *tmpN - 'a' + 1;\n                *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');\n            }\n            G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */\n            if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */\n                || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */\n                free(G.buildpathHPFS);\n                free(G.buildpathFAT);\n                return MPN_VOL_LABEL;  /* skipping with message */\n            }\n            *G.buildpathHPFS = '\\0';\n        } else if (G.renamed_fullpath) /* pathcomp = valid data */\n            strcpy(G.buildpathHPFS, pathcomp);\n        else if (G.rootlen > 0)\n            strcpy(G.buildpathHPFS, G.rootpath);\n        else\n            *G.buildpathHPFS = '\\0';\n        G.endHPFS = G.buildpathHPFS;\n        G.endFAT = G.buildpathFAT;\n        while ((*G.endFAT = *G.endHPFS) != '\\0') {\n            ++G.endFAT;\n            ++G.endHPFS;\n        }\n        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpathHPFS)));\n        return MPN_OK;\n    }\n\n/*---------------------------------------------------------------------------\n    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n    sary; else assume it's a zipfile member and return.  This path segment\n    gets used in extracting all members from every zipfile specified on the\n    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to\n    directory specification includes a drive letter (leading \"x:\"), it is\n    treated just as if it had a trailing '/'--that is, one directory level\n    will be created if the path doesn't exist, unless this is otherwise pro-\n    hibited (e.g., freshening).\n  ---------------------------------------------------------------------------*/\n\n#if (!defined(SFX) || defined(SFX_EXDIR))\n    if (FUNCTION == ROOT) {\n        Trace((stderr, \"initializing root path to [%s]\\n\",\n          FnFilter1(pathcomp)));\n        if (pathcomp == NULL) {\n            G.rootlen = 0;\n            return MPN_OK;\n        }\n        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n            return MPN_OK;\n        if ((G.rootlen = strlen(pathcomp)) > 0) {\n            int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n            char *tmproot;\n\n            if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            strcpy(tmproot, pathcomp);\n            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n                has_drive = TRUE;   /* drive designator */\n            if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\\\') {\n                tmproot[--G.rootlen] = '\\0';\n                had_trailing_pathsep = TRUE;\n            }\n            if (has_drive && (G.rootlen == 2)) {\n                if (!had_trailing_pathsep)   /* i.e., original wasn't \"x:/\" */\n                    add_dot = TRUE;    /* relative path: add '.' before '/' */\n            } else if (G.rootlen > 0) {   /* need not check \"x:.\" and \"x:/\" */\n                if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n                {\n                    /* path does not exist */\n                    if (!G.create_dirs /* || iswild(tmproot) */ ) {\n                        free(tmproot);\n                        G.rootlen = 0;\n                        /* treat as stored file */\n                        return MPN_INF_SKIP;\n                    }\n                    /* create directory (could add loop here scanning tmproot\n                     * to create more than one level, but really necessary?) */\n                    if (MKDIR(tmproot, 0777) == -1) {\n                        Info(slide, 1, ((char *)slide,\n                          \"checkdir:  cannot create extraction directory: %s\\n\",\n                          FnFilter1(tmproot)));\n                        free(tmproot);\n                        G.rootlen = 0;\n                        /* path didn't exist, tried to create, failed: */\n                        /* file exists, or need 2+ subdir levels */\n                        return MPN_ERR_SKIP;\n                    }\n                }\n            }\n            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n                tmproot[G.rootlen++] = '.';\n            tmproot[G.rootlen++] = '/';\n            tmproot[G.rootlen] = '\\0';\n            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n                free(tmproot);\n                G.rootlen = 0;\n                return MPN_NOMEM;\n            }\n            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n        }\n        return MPN_OK;\n    }\n#endif /* !SFX || SFX_EXDIR */\n\n/*---------------------------------------------------------------------------\n    END:  free rootpath, immediately prior to program exit.\n  ---------------------------------------------------------------------------*/\n\n    if (FUNCTION == END) {\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            free(G.rootpath);\n            G.rootlen = 0;\n        }\n        return MPN_OK;\n    }\n\n    return MPN_INVALID; /* should never reach */\n\n} /* end function checkdir() */\n\n\n\n\n\n#ifndef SFX\n\n/*************************/\n/* Function dateformat() */\n/*************************/\n\nint dateformat()\n{\n  char df[2];   /* LOCALE_IDATE has a maximum value of 2 */\n\n  if (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDATE, df, 2) != 0) {\n    switch (df[0])\n    {\n      case '0':\n        return DF_MDY;\n      case '1':\n        return DF_DMY;\n      case '2':\n        return DF_YMD;\n    }\n  }\n  return DF_MDY;\n}\n\n\n/****************************/\n/* Function dateseparator() */\n/****************************/\n\nchar dateseparator()\n{\n  char df[2];   /* use only if it is one character */\n\n  if ((GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, df, 2) != 0) &&\n      (df[0] != '\\0'))\n    return df[0];\n  else\n    return '-';\n}\n\n\n#ifndef WINDLL\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__G)\n    __GDEF\n{\n    int len;\n#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))\n    char buf[80];\n#if (defined(_MSC_VER) && (_MSC_VER > 900))\n    char buf2[80];\n#endif\n#endif\n\n    len = sprintf((char *)slide, CompiledWith,\n\n#if defined(_MSC_VER)  /* MSC == VC++, but what about SDK compiler? */\n      (sprintf(buf, \"Microsoft C %d.%02d \", _MSC_VER/100, _MSC_VER%100), buf),\n#  if (_MSC_VER == 800)\n      \"(Visual C++ v1.1)\",\n#  elif (_MSC_VER == 850)\n      \"(Windows NT v3.5 SDK)\",\n#  elif (_MSC_VER == 900)\n      \"(Visual C++ v2.x)\",\n#  elif (_MSC_VER > 900)\n      (sprintf(buf2, \"(Visual C++ %d.%d)\", _MSC_VER/100 - 6, _MSC_VER%100/10),\n        buf2),\n#  else\n      \"(bad version)\",\n#  endif\n#elif defined(__WATCOMC__)\n#  if (__WATCOMC__ % 10 > 0)\n      (sprintf(buf, \"Watcom C/C++ %d.%02d\", __WATCOMC__ / 100,\n       __WATCOMC__ % 100), buf), \"\",\n#  else\n      (sprintf(buf, \"Watcom C/C++ %d.%d\", __WATCOMC__ / 100,\n       (__WATCOMC__ % 100) / 10), buf), \"\",\n#  endif\n#elif defined(__BORLANDC__)\n      \"Borland C++\",\n#  if (__BORLANDC__ < 0x0200)\n      \" 1.0\",\n#  elif (__BORLANDC__ == 0x0200)\n      \" 2.0\",\n#  elif (__BORLANDC__ == 0x0400)\n      \" 3.0\",\n#  elif (__BORLANDC__ == 0x0410)   /* __TURBOC__ = 0x0310 */\n      \" 3.1\",\n#  elif (__BORLANDC__ == 0x0452)   /* __TURBOC__ = 0x0320 */\n      \" 4.0 or 4.02\",\n#  elif (__BORLANDC__ == 0x0460)   /* __TURBOC__ = 0x0340 */\n      \" 4.5\",\n#  elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0340 */\n      \" 5.0\",\n#  elif (__BORLANDC__ == 0x0520)   /* __TURBOC__ = 0x0520 */\n      \" 5.2 (C++ Builder 1.0)\",\n#  elif (__BORLANDC__ == 0x0530)   /* __TURBOC__ = 0x0530 */\n      \" 5.3 (C++ Builder 3.0)\",\n#  elif (__BORLANDC__ == 0x0540)   /* __TURBOC__ = 0x0540 */\n      \" 5.4 (C++ Builder 4.0)\",\n#  elif (__BORLANDC__ == 0x0550)   /* __TURBOC__ = 0x0550 */\n      \" 5.5 (C++ Builder 5.0)\",\n#  elif (__BORLANDC__ == 0x0551)   /* __TURBOC__ = 0x0551 */\n      \" 5.5.1 (C++ Builder 5.0.1)\",\n#  elif (__BORLANDC__ == 0x0560)   /* __TURBOC__ = 0x0560 */\n      \" 6.0 (C++ Builder 6.0)\",\n#  else\n      \" later than 6.0\",\n#  endif\n#elif defined(__LCC__)\n      \"LCC-Win32\", \"\",\n#elif defined(__GNUC__)\n#  if defined(__RSXNT__)\n#    if (defined(__DJGPP__) && !defined(__EMX__))\n      (sprintf(buf, \"rsxnt(djgpp v%d.%02d) / gcc \",\n        __DJGPP__, __DJGPP_MINOR__), buf),\n#    elif defined(__DJGPP__)\n      (sprintf(buf, \"rsxnt(emx+djgpp v%d.%02d) / gcc \",\n        __DJGPP__, __DJGPP_MINOR__), buf),\n#    elif (defined(__GO32__) && !defined(__EMX__))\n      \"rsxnt(djgpp v1.x) / gcc \",\n#    elif defined(__GO32__)\n      \"rsxnt(emx + djgpp v1.x) / gcc \",\n#    elif defined(__EMX__)\n      \"rsxnt(emx)+gcc \",\n#    else\n      \"rsxnt(unknown) / gcc \",\n#    endif\n#  elif defined(__CYGWIN__)\n      \"cygnus win32 / gcc \",\n#  elif defined(__MINGW32__)\n      \"mingw32 / gcc \",\n#  else\n      \"gcc \",\n#  endif\n      __VERSION__,\n#else /* !_MSC_VER, !__WATCOMC__, !__BORLANDC__, !__LCC__, !__GNUC__ */\n      \"unknown compiler (SDK?)\", \"\",\n#endif /* ?compilers */\n\n      \"\\nWindows 9x / Windows NT/2K/XP/2K3\", \" (32-bit)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    (*G.message)((zvoid *)&G, slide, (ulg)len, 0);\n\n    return;\n\n} /* end function version() */\n\n#endif /* !WINDLL */\n#endif /* !SFX */\n\n\n\n#ifdef MORE\n\nint screensize(int *tt_rows, int *tt_cols)\n{\n    HANDLE hstdout;\n    CONSOLE_SCREEN_BUFFER_INFO scr;\n\n    hstdout = GetStdHandle(STD_OUTPUT_HANDLE);\n    GetConsoleScreenBufferInfo(hstdout, &scr);\n    if (tt_rows != NULL) *tt_rows = scr.srWindow.Bottom - scr.srWindow.Top + 1;\n    if (tt_cols != NULL) *tt_cols = scr.srWindow.Right - scr.srWindow.Left + 1;\n    return 0;           /* signal success */\n}\n\n#endif /* MORE */\n\n\n\n#ifdef W32_STAT_BANDAID\n\n/* All currently known variants of WIN32 operating systems (Windows 95/98,\n * WinNT 3.x, 4.0, 5.x) have a nasty bug in the OS kernel concerning\n * conversions between UTC and local time: In the time conversion functions\n * of the Win32 API, the timezone offset (including seasonal daylight saving\n * shift) between UTC and local time evaluation is erratically based on the\n * current system time. The correct evaluation must determine the offset\n * value as it {was/is/will be} for the actual time to be converted.\n *\n * Newer versions of MS C runtime lib's stat() returns utc time-stamps so\n * that localtime(timestamp) corresponds to the (potentially false) local\n * time shown by the OS' system programs (Explorer, command shell dir, etc.)\n * The RSXNT port follows the same strategy, but fails to recognize the\n * access-time attribute.\n *\n * For the NTFS file system (and other filesystems that store time-stamps\n * as UTC values), this results in st_mtime (, st_{c|a}time) fields which\n * are not stable but vary according to the seasonal change of \"daylight\n * saving time in effect / not in effect\".\n *\n * Other C runtime libs (CygWin), or the crtdll.dll supplied with Win9x/NT\n * return the unix-time equivalent of the UTC FILETIME values as got back\n * from the Win32 API call. This time, return values from NTFS are correct\n * whereas utimes from files on (V)FAT volumes vary according to the DST\n * switches.\n *\n * To achieve timestamp consistency of UTC (UT extra field) values in\n * Zip archives, the Info-ZIP programs require work-around code for\n * proper time handling in stat() (and other time handling routines).\n *\n * However, nowadays most other programs on Windows systems use the\n * time conversion strategy of Microsofts C runtime lib \"msvcrt.dll\".\n * To improve interoperability in environments where a \"consistent\" (but\n * false) \"UTC<-->LocalTime\" conversion is preferred over \"stable\" time\n * stamps, the Info-ZIP specific time conversion handling can be\n * deactivated by defining the preprocessor flag NO_W32TIMES_IZFIX.\n */\n/* stat() functions under Windows95 tend to fail for root directories.   *\n * Watcom and Borland, at least, are affected by this bug.  Watcom made  *\n * a partial fix for 11.0 but still missed some cases.  This substitute  *\n * detects the case and fills in reasonable values.  Otherwise we get    *\n * effects like failure to extract to a root dir because it's not found. */\n\nint zstat_win32(__W32STAT_GLOBALS__ const char *path, z_stat *buf)\n{\n    if (!zstat(path, buf))\n    {\n        /* stat was successful, now redo the time-stamp fetches */\n#ifndef NO_W32TIMES_IZFIX\n        int fs_uses_loctime = FStampIsLocTime(__G__ path);\n#endif\n        HANDLE h;\n        FILETIME Modft, Accft, Creft;\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(path) + 1);\n\n        INTERN_TO_ISO(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  path\n#endif\n\n        TTrace((stdout, \"stat(%s) finds modtime %08lx\\n\", path, buf->st_mtime));\n        h = CreateFileA(Ansi_Path, GENERIC_READ,\n                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n        if (h != INVALID_HANDLE_VALUE) {\n            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);\n            CloseHandle(h);\n\n            if (ftOK) {\n                FTTrace((stdout, \"GetFileTime returned Modft\", 0, &Modft));\n                FTTrace((stdout, \"GetFileTime returned Creft\", 0, &Creft));\n#ifndef NO_W32TIMES_IZFIX\n                if (!fs_uses_loctime) {\n                    /*  On a filesystem that stores UTC timestamps, we refill\n                     *  the time fields of the struct stat buffer by directly\n                     *  using the UTC values as returned by the Win32\n                     *  GetFileTime() API call.\n                     */\n                    NtfsFileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        NtfsFileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        NtfsFileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    TTrace((stdout,\"NTFS, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                } else\n#endif /* NO_W32TIMES_IZFIX */\n                {\n                    /*  On VFAT and FAT-like filesystems, the FILETIME values\n                     *  are converted back to the stable local time before\n                     *  converting them to UTC unix time-stamps.\n                     */\n                    VFatFileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    TTrace((stdout, \"VFAT, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                }\n            }\n        }\n#       undef Ansi_Path\n        return 0;\n    }\n#ifdef W32_STATROOT_FIX\n    else\n    {\n        DWORD flags;\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(path) + 1);\n\n        INTERN_TO_ISO(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  path\n#endif\n\n        flags = GetFileAttributesA(Ansi_Path);\n        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {\n            Trace((stderr, \"\\nstat(\\\"%s\\\",...) failed on existing directory\\n\",\n                   FnFilter1(path)));\n            memset(buf, 0, sizeof(z_stat));\n            buf->st_atime = buf->st_ctime = buf->st_mtime =\n              dos_to_unix_time(DOSTIME_MINIMUM);        /* 1-1-80 */\n            buf->st_mode = S_IFDIR | S_IREAD |\n                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);\n            return 0;\n        } /* assumes: stat() won't fail on non-dirs without good reason */\n#       undef Ansi_Path\n    }\n#endif /* W32_STATROOT_FIX */\n    return -1;\n}\n\n#endif /* W32_STAT_BANDAID */\n\n\n\n#ifdef W32_USE_IZ_TIMEZONE\n#include \"timezone.h\"\n#define SECSPERMIN      60\n#define MINSPERHOUR     60\n#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);\n\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)\n{\n    if (lpw32tm->wYear != 0) {\n        ptrule->r_type = JULIAN_DAY;\n        ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;\n    } else {\n        ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;\n        ptrule->r_mon = lpw32tm->wMonth;\n        ptrule->r_day = lpw32tm->wDayOfWeek;\n        ptrule->r_week = lpw32tm->wDay;\n    }\n    ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +\n                     (long)(lpw32tm->wMinute * SECSPERMIN) +\n                     (long)lpw32tm->wSecond;\n}\n\nint GetPlatformLocalTimezone(register struct state * ZCONST sp,\n        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                        ZCONST struct rule * ZCONST start,\n                                        ZCONST struct rule * ZCONST end))\n{\n    TIME_ZONE_INFORMATION tzinfo;\n    DWORD res;\n\n    /* read current timezone settings from registry if TZ envvar missing */\n    res = GetTimeZoneInformation(&tzinfo);\n    if (res != TIME_ZONE_ID_INVALID)\n    {\n        struct rule startrule, stoprule;\n\n        conv_to_rule(&(tzinfo.StandardDate), &stoprule);\n        conv_to_rule(&(tzinfo.DaylightDate), &startrule);\n        sp->timecnt = 0;\n        sp->ttis[0].tt_abbrind = 0;\n        if ((sp->charcnt =\n             WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1,\n                                 sp->chars, sizeof(sp->chars), NULL, NULL))\n            == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[1].tt_abbrind = sp->charcnt;\n        sp->charcnt +=\n            WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1,\n                                sp->chars + sp->charcnt,\n                                sizeof(sp->chars) - sp->charcnt, NULL, NULL);\n        if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias)\n                                * MINSPERHOUR;\n        sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias)\n                                * MINSPERHOUR;\n        sp->ttis[0].tt_isdst = 0;\n        sp->ttis[1].tt_isdst = 1;\n        sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2;\n\n        if (sp->typecnt > 1)\n            (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);\n        return TRUE;\n    }\n    return FALSE;\n}\n#endif /* W32_USE_IZ_TIMEZONE */\n\n#endif /* !FUNZIP */\n\n\n\n#ifndef WINDLL\n/* This replacement getch() function was originally created for Watcom C\n * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32\n * ports apply this replacement rather that their supplied getch() (or\n * alike) function.  There are problems with unabsorbed LF characters left\n * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.\n * (Under Win95, ENTER returns two(!!) characters: CR-LF.)  This problem\n * does not appear when run on a WinNT console prompt!\n */\n\n/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */\n/* Note that if PASSWD_FROM_STDIN is defined, the file containing   */\n/* the password must have a carriage return after the word, not a   */\n/* Unix-style newline (linefeed only).  This discards linefeeds.    */\n\nint getch_win32(void)\n{\n  HANDLE stin;\n  DWORD rc;\n  unsigned char buf[2];\n  int ret = -1;\n  DWORD odemode = ~(DWORD)0;\n\n#  ifdef PASSWD_FROM_STDIN\n  stin = GetStdHandle(STD_INPUT_HANDLE);\n#  else\n  stin = CreateFileA(\"CONIN$\", GENERIC_READ | GENERIC_WRITE,\n                     FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\n  if (stin == INVALID_HANDLE_VALUE)\n    return -1;\n#  endif\n  if (GetConsoleMode(stin, &odemode))\n    SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */\n  if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)\n    ret = buf[0];\n  /* when the user hits return we get CR LF.  We discard the LF, not the CR,\n   * because when we call this for the first time after a previous input\n   * such as the one for \"replace foo? [y]es, ...\" the LF may still be in\n   * the input stream before whatever the user types at our prompt. */\n  if (ret == '\\n')\n    if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)\n      ret = buf[0];\n  if (odemode != ~(DWORD)0)\n    SetConsoleMode(stin, odemode);\n#  ifndef PASSWD_FROM_STDIN\n  CloseHandle(stin);\n#  endif\n  return ret;\n}\n#endif /* !WINDLL */\n\n\n\n#if (defined(UNICODE_SUPPORT) && !defined(FUNZIP))\n/* convert wide character string to multi-byte character string */\nchar *wide_to_local_string(wide_string, escape_all)\n  ZCONST zwchar *wide_string;\n  int escape_all;\n{\n  int i;\n  wchar_t wc;\n  int bytes_char;\n  int default_used;\n  int wsize = 0;\n  int max_bytes = 9;\n  char buf[9];\n  char *buffer = NULL;\n  char *local_string = NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if (max_bytes < MB_CUR_MAX)\n    max_bytes = MB_CUR_MAX;\n\n  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {\n    return NULL;\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  for (i = 0; i < wsize; i++) {\n    if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {\n      /* wchar_t probably 2 bytes */\n      /* could do surrogates if state_dependent and wctomb can do */\n      wc = zwchar_to_wchar_t_default_char;\n    } else {\n      wc = (wchar_t)wide_string[i];\n    }\n    /* Unter some vendor's C-RTL, the Wide-to-MultiByte conversion functions\n     * (like wctomb() et. al.) do not use the same codepage as the other\n     * string arguments I/O functions (fopen, mkdir, rmdir etc.).\n     * Therefore, we have to fall back to the underlying Win32-API call to\n     * achieve a consistent behaviour for all supported compiler environments.\n     * Failing RTLs are for example:\n     *   Borland (locale uses OEM-CP as default, but I/O functions expect ANSI\n     *            names)\n     *   Watcom  (only \"C\" locale, wctomb() always uses OEM CP)\n     * (in other words: all supported environments except the Microsoft RTLs)\n     */\n    bytes_char = WideCharToMultiByte(\n                          CP_ACP, WC_COMPOSITECHECK,\n                          &wc, 1,\n                          (LPSTR)buf, sizeof(buf),\n                          NULL, &default_used);\n    if (default_used)\n      bytes_char = -1;\n    if (escape_all) {\n      if (bytes_char == 1 && (uch)buf[0] <= 0x7f) {\n        /* ASCII */\n        strncat(buffer, buf, 1);\n      } else {\n        /* use escape for wide character */\n        char *escape_string = wide_to_escape_string(wide_string[i]);\n        strcat(buffer, escape_string);\n        free(escape_string);\n      }\n    } else if (bytes_char > 0) {\n      /* multi-byte char */\n      strncat(buffer, buf, bytes_char);\n    } else {\n      /* no MB for this wide */\n      /* use escape for wide character */\n      char *escape_string = wide_to_escape_string(wide_string[i]);\n      strcat(buffer, escape_string);\n      free(escape_string);\n    }\n  }\n  if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) {\n    free(buffer);\n    return NULL;\n  }\n\n  return local_string;\n}\n\n\n#if 0\nwchar_t *utf8_to_wchar_string(utf8_string)\n  char *utf8_string;       /* path to get utf-8 name for */\n{\n  wchar_t  *qw;\n  int       ulen;\n  int       ulenw;\n\n  if (utf8_string == NULL)\n    return NULL;\n\n    /* get length */\n    ulenw = MultiByteToWideChar(\n                CP_UTF8,           /* UTF-8 code page */\n                0,                 /* flags for character-type options */\n                utf8_string,       /* string to convert */\n                -1,                /* string length (-1 = NULL terminated) */\n                NULL,              /* buffer */\n                0 );               /* buffer length (0 = return length) */\n    if (ulenw == 0) {\n      /* failed */\n      return NULL;\n    }\n    ulenw++;\n    /* get length in bytes */\n    ulen = sizeof(wchar_t) * (ulenw + 1);\n    if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {\n      return NULL;\n    }\n    /* convert multibyte to wide */\n    ulen = MultiByteToWideChar(\n               CP_UTF8,           /* UTF-8 code page */\n               0,                 /* flags for character-type options */\n               utf8_string,       /* string to convert */\n               -1,                /* string length (-1 = NULL terminated) */\n               qw,                /* buffer */\n               ulenw);            /* buffer length (0 = return length) */\n    if (ulen == 0) {\n      /* failed */\n      free(qw);\n      return NULL;\n    }\n\n  return qw;\n}\n\nwchar_t *local_to_wchar_string(local_string)\n  char *local_string;       /* path of local name */\n{\n  wchar_t  *qw;\n  int       ulen;\n  int       ulenw;\n\n  if (local_string == NULL)\n    return NULL;\n\n    /* get length */\n    ulenw = MultiByteToWideChar(\n                CP_ACP,            /* ANSI code page */\n                0,                 /* flags for character-type options */\n                local_string,      /* string to convert */\n                -1,                /* string length (-1 = NULL terminated) */\n                NULL,              /* buffer */\n                0 );               /* buffer length (0 = return length) */\n    if (ulenw == 0) {\n      /* failed */\n      return NULL;\n    }\n    ulenw++;\n    /* get length in bytes */\n    ulen = sizeof(wchar_t) * (ulenw + 1);\n    if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {\n      return NULL;\n    }\n    /* convert multibyte to wide */\n    ulen = MultiByteToWideChar(\n               CP_ACP,            /* ANSI code page */\n               0,                 /* flags for character-type options */\n               local_string,      /* string to convert */\n               -1,                /* string length (-1 = NULL terminated) */\n               qw,                /* buffer */\n               ulenw);            /* buffer length (0 = return length) */\n    if (ulen == 0) {\n      /* failed */\n      free(qw);\n      return NULL;\n    }\n\n  return qw;\n}\n#endif /* 0 */\n#endif /* UNICODE_SUPPORT && !FUNZIP */\n\n\n\n/* --------------------------------------------------- */\n/* Large File Support\n *\n * Initial functions by E. Gordon and R. Nausedat\n * 9/10/2003\n * Lifted from Zip 3b, win32.c and place here by Myles Bennett\n * 7/6/2004\n *\n * These implement 64-bit file support for Windows.  The\n * defines and headers are in win32/w32cfg.h.\n *\n * Moved to win32i64.c by Mike White to avoid conflicts in\n * same name functions in WiZ using UnZip and Zip libraries.\n * 9/25/2003\n */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/win32i64.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  win32/win32i64.c - UnZip 6\n\n  64-bit filesize support for WIN32 Zip and UnZip.\n  ---------------------------------------------------------------------------*/\n\n#include \"../zip.h\"\n\n/* --------------------------------------------------- */\n/* Large File Support\n *\n * Initial functions by E. Gordon and R. Nausedat\n * 9/10/2003\n *\n * These implement 64-bit file support for Windows.  The\n * defines and headers are in win32/osdep.h.\n *\n * These moved from win32.c by Mike White to avoid conflicts\n * in WiZ of same name functions in UnZip and Zip libraries.\n * 9/25/04 EG\n */\n\n#if defined(LARGE_FILE_SUPPORT) && !defined(__CYGWIN__)\n# ifdef USE_STRM_INPUT\n\n#  ifndef zftello\n/* 64-bit buffered ftello\n *\n * Win32 does not provide a 64-bit buffered\n * ftell (in the published api anyway) so below provides\n * hopefully close version.\n * We have not gotten _telli64 to work with buffered\n * streams.  Below cheats by using fgetpos improperly and\n * may not work on other ports.\n */\n\nzoff_t zftello(stream)\n  FILE *stream;\n{\n  fpos_t fpos = 0;\n\n  if (fgetpos(stream, &fpos) != 0) {\n    return -1L;\n  } else {\n    return fpos;\n  }\n}\n#  endif /* ndef zftello */\n\n\n#  ifndef zfseeko\n/* 64-bit buffered fseeko\n *\n * Win32 does not provide a 64-bit buffered\n * fseeko, so use _lseeki64 and fflush.  Note\n * that SEEK_CUR can lose track of location\n * if fflush is done between the last buffered\n * io and this call.\n */\n\nint zfseeko(stream, offset, origin)\n  FILE *stream;\n  zoff_t offset;\n  int origin;\n{\n\n  /* fseek() or its replacements are supposed to clear the eof status\n     of the stream. fflush() and _lseeki64() do not touch the stream's\n     eof flag, so we have to do it manually. */\n#if ((defined(_MSC_VER) && (_MSC_VER >= 1200)) || \\\n     (defined(__MINGW32__) && defined(__MSVCRT_VERSION__)))\n  /* For the MSC environment (VS 6 or higher), and for recent releases of\n     the MinGW environment, we \"know\" the internals of the FILE structure.\n     So, we can clear just the EOF bit of the status flag. */\n  stream->_flag &= ~_IOEOF;\n#else\n  /* Unfortunately, there is no standard \"cleareof()\" function, so we have\n     to use clearerr().  This has the unwanted side effect of clearing the\n     ferror() state as well. */\n  clearerr(stream);\n#endif\n\n  if (origin == SEEK_CUR) {\n    /* instead of synching up lseek easier just to figure and\n       use an absolute offset */\n    offset += zftello(stream);\n    origin = SEEK_SET;\n  }\n  fflush(stream);\n  if (_lseeki64(fileno(stream), offset, origin) == (zoff_t)-1L) {\n    return -1;\n  } else {\n    return 0;\n  }\n}\n#  endif  /* ndef fseeko */\n# endif /* USE_STRM_INPUT */\n#endif  /* Win32 LARGE_FILE_SUPPORT */\n\n#if 0\nFILE* zfopen(filename, mode)\nconst char *filename;\nconst char *mode;\n{\n  FILE* fTemp;\n\n  fTemp = fopen(filename, mode);\n  if( fTemp == NULL )\n    return NULL;\n\n  /* sorry, could not make VC60 and its rtl work properly without setting the\n   * file buffer to NULL. the problem seems to be _telli64 which seems to\n   * return the max stream position, comments are welcome\n   */\n  setbuf(fTemp, NULL);\n\n  return fTemp;\n}\n#endif\n/* --------------------------------------------------- */\n"
  },
  {
    "path": "deps/infozip/unzip60/win32/winapp.rc",
    "content": "#include <windows.h>\n#if (defined(WIN32) && !defined(__EMX__) && !defined(__MINGW32__))\n#include <winver.h>\n#endif\n#include \"../unzvers.h\"\n\nVS_VERSION_INFO VERSIONINFO\nFILEVERSION UZ_MAJORVER,UZ_MINORVER,UZ_PATCHLEVEL,0\nPRODUCTVERSION UZ_MAJORVER,UZ_MINORVER,UZ_PATCHLEVEL,0\nFILEFLAGSMASK 0x3L\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\nFILEOS VOS__WINDOWS32\nFILETYPE VFT_APP\nFILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        BLOCK \"040904B0\"\n#else\n        BLOCK \"040904E4\"\n#endif\n        BEGIN\n            VALUE \"Comments\", \"\\0\"\n            VALUE \"CompanyName\", IZ_COMPANY_NAME \"\\0\"\n            VALUE \"FileDescription\", \"Info-ZIP's UnZip for Win32 console\\0\"\n            VALUE \"FileVersion\", UZ_VER_STRING \"\\0\"\n            VALUE \"InternalName\", \"UnZip\\0\"\n            VALUE \"LegalCopyright\", \"Info-ZIP 1996-2009\\0\"\n            VALUE \"LegalTrademarks\", \"\\0\"\n            VALUE \"OriginalFilename\", \"UNZIP.EXE\\0\"\n            VALUE \"PrivateBuild\", \"\\0\"\n            VALUE \"ProductName\", \"Info-ZIP's UnZip for Windows\\0\"\n            VALUE \"ProductVersion\", UZ_VER_STRING \"\\0\"\n            VALUE \"SpecialBuild\", \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        VALUE \"Translation\", 0x409, 1200\n#else\n        VALUE \"Translation\", 0x409, 1252\n#endif\n    END\nEND\n"
  },
  {
    "path": "deps/infozip/unzip60/win32-experimental/unz60d10_w32wide-Unicode_patch.txt",
    "content": "diff -ru2 unz60d10/extract.c unz60d10_w32w/extract.c\n--- unz60d10/extract.c\tThu Dec 27 21:41:40 2007\n+++ unz60d10_w32w/extract.c\tMon Feb 11 02:22:00 2008\n@@ -87,4 +87,11 @@\n static int store_info OF((__GPRO));\n #ifdef SET_DIR_ATTRIB\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int extract_or_test_entrylistw OF((__GPRO__ unsigned numchunk,\n+                ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,\n+                unsigned *pnum_dirs,\n+                direntryw **pdirlistw,\n+                int error_in_archive));\n+# endif\n static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk,\n                 ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes,\n@@ -112,4 +119,7 @@\n #endif\n #ifdef SET_DIR_ATTRIB\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   static int Cdecl dircompw OF((ZCONST zvoid *a, ZCONST zvoid *b));\n+# endif\n    static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));\n #endif\n@@ -336,4 +346,7 @@\n #ifdef SET_DIR_ATTRIB\n     unsigned num_dirs=0;\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    direntryw *dirlistw=(direntryw *)NULL, **sorted_dirlistw=(direntryw **)NULL;\n+#endif\n     direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL;\n #endif\n@@ -356,8 +369,25 @@\n     if (uO.exdir != (char *)NULL && G.extract_flag) {\n         G.create_dirs = !uO.fflag;\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        if (G.has_win32_wide) {\n+          wchar_t *exdirw = local_to_wchar_string(uO.exdir);\n+          if ((error = checkdirw(exdirw, ROOT)) > MPN_INF_SKIP) {\n+              /* out of memory, or file in way */\n+              free(exdirw);\n+              return (error == MPN_NOMEM ? PK_MEM : PK_ERR);\n+          }\n+          free(exdirw);\n+        } else {\n+          if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {\n+              /* out of memory, or file in way */\n+              return (error == MPN_NOMEM ? PK_MEM : PK_ERR);\n+          }\n+        }\n+# else /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n         if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) {\n             /* out of memory, or file in way */\n             return (error == MPN_NOMEM ? PK_MEM : PK_ERR);\n         }\n+# endif /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n     }\n #endif /* !SFX || SFX_EXDIR */\n@@ -570,5 +600,18 @@\n       -----------------------------------------------------------------------*/\n \n-        error = extract_or_test_entrylist(__G__ j,\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        if (G.has_win32_wide)\n+        {\n+          error = extract_or_test_entrylistw(__G__ j,\n+                        &filnum, &num_bad_pwd, &old_extra_bytes,\n+# ifdef SET_DIR_ATTRIB\n+                        &num_dirs, &dirlistw,\n+# endif\n+                        error_in_archive);\n+        }\n+        else\n+#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+        {\n+          error = extract_or_test_entrylist(__G__ j,\n                         &filnum, &num_bad_pwd, &old_extra_bytes,\n #ifdef SET_DIR_ATTRIB\n@@ -576,4 +619,5 @@\n #endif\n                         error_in_archive);\n+        }\n         if (error != PK_COOL) {\n             if (error > error_in_archive)\n@@ -643,4 +687,55 @@\n #ifdef SET_DIR_ATTRIB\n     if (num_dirs > 0) {\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+      if (G.has_win32_wide) {\n+        sorted_dirlistw = (direntryw **)malloc(num_dirs*sizeof(direntryw *));\n+        if (sorted_dirlistw == (direntryw **)NULL) {\n+            Info(slide, 0x401, ((char *)slide,\n+              LoadFarString(DirlistSortNoMem)));\n+            while (dirlistw != (direntryw *)NULL) {\n+                direntryw *dw = dirlistw;\n+\n+                dirlistw = dirlistw->next;\n+                free(dw);\n+            }\n+        } else {\n+            ulg ndirs_fail = 0;\n+\n+            if (num_dirs == 1)\n+                sorted_dirlistw[0] = dirlistw;\n+            else {\n+                for (i = 0;  i < num_dirs;  ++i) {\n+                    sorted_dirlistw[i] = dirlistw;\n+                    dirlistw = dirlistw->next;\n+                }\n+                qsort((char *)sorted_dirlistw, num_dirs, sizeof(direntryw *),\n+                  dircompw);\n+            }\n+\n+            Trace((stderr, \"setting directory times/perms/attributes\\n\"));\n+            for (i = 0;  i < num_dirs;  ++i) {\n+                direntryw *dw = sorted_dirlistw[i];\n+\n+                Trace((stderr, \"dir = %s\\n\", dw->fn));\n+                if ((error = set_direc_attribsw(__G__ dw)) != PK_OK) {\n+                    ndirs_fail++;\n+                    Info(slide, 0x201, ((char *)slide,\n+                      LoadFarString(DirlistSetAttrFailed), dw->fnw));\n+                    if (!error_in_archive)\n+                        error_in_archive = error;\n+                }\n+                free(dw);\n+            }\n+            free(sorted_dirlistw);\n+            if (!uO.tflag && QCOND2) {\n+                if (ndirs_fail > 0)\n+                    Info(slide, 0, ((char *)slide,\n+                      LoadFarString(DirlistFailAttrSum), ndirs_fail));\n+            }\n+        }\n+      }\n+      else\n+# endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+      {\n         sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *));\n         if (sorted_dirlist == (direntry **)NULL) {\n@@ -688,4 +783,5 @@\n             }\n         }\n+      }\n     }\n #endif /* SET_DIR_ATTRIB */\n@@ -821,190 +917,731 @@\n #endif\n \n-#ifdef USE_WAVP\n-#  define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)\n-#else\n-#  define UNKN_WAVP TRUE      /* WavPack unknown */\n+#ifdef USE_WAVP\n+#  define UNKN_WAVP (G.crec.compression_method!=WAVPACKED)\n+#else\n+#  define UNKN_WAVP TRUE      /* WavPack unknown */\n+#endif\n+\n+#ifdef USE_PPMD\n+#  define UNKN_PPMD (G.crec.compression_method!=PPMDED)\n+#else\n+#  define UNKN_PPMD TRUE      /* PPMd unknown */\n+#endif\n+\n+#ifdef SFX\n+#  ifdef USE_DEFLATE64\n+#    define UNKN_COMPR \\\n+     (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \\\n+      && G.crec.compression_method>ENHDEFLATED \\\n+      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n+#  else\n+#    define UNKN_COMPR \\\n+     (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\\\n+      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n+#  endif\n+#else\n+#  ifdef COPYRIGHT_CLEAN  /* no reduced files */\n+#    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \\\n+                      G.crec.compression_method <= REDUCED4)\n+#  else\n+#    define UNKN_RED  FALSE  /* reducing not unknown */\n+#  endif\n+#  ifdef LZW_CLEAN  /* no shrunk files */\n+#    define UNKN_SHR (G.crec.compression_method == SHRUNK)\n+#  else\n+#    define UNKN_SHR  FALSE  /* unshrinking not unknown */\n+#  endif\n+#  ifdef USE_DEFLATE64\n+#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n+     G.crec.compression_method==TOKENIZED || \\\n+     (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n+      && UNKN_WAVP && UNKN_PPMD))\n+#  else\n+#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n+     G.crec.compression_method==TOKENIZED || \\\n+     (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n+      && UNKN_WAVP && UNKN_PPMD))\n+#  endif\n+#endif\n+\n+#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))\n+    int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);\n+#   define UNZVERS_SUPPORT  unzvers_support\n+#else\n+#   define UNZVERS_SUPPORT  UNZIP_VERSION\n+#endif\n+\n+/*---------------------------------------------------------------------------\n+    Check central directory info for version/compatibility requirements.\n+  ---------------------------------------------------------------------------*/\n+\n+    G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */\n+    G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */\n+    G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */\n+    G.pInfo->crc = G.crec.crc32;\n+    G.pInfo->compr_size = G.crec.csize;\n+    G.pInfo->uncompr_size = G.crec.ucsize;\n+\n+    switch (uO.aflag) {\n+        case 0:\n+            G.pInfo->textmode = FALSE;   /* bit field */\n+            break;\n+        case 1:\n+            G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */\n+            break;\n+        default:  /* case 2: */\n+            G.pInfo->textmode = TRUE;\n+            break;\n+    }\n+\n+    if (G.crec.version_needed_to_extract[1] == VMS_) {\n+        if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {\n+            if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n+                  FnFilter1(G.filename), \"VMS\",\n+                  G.crec.version_needed_to_extract[0] / 10,\n+                  G.crec.version_needed_to_extract[0] % 10,\n+                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));\n+            return 0;\n+        }\n+#ifndef VMS   /* won't be able to use extra field, but still have data */\n+        else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */\n+            Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),\n+              FnFilter1(G.filename)));\n+            fgets(G.answerbuf, 9, stdin);\n+            if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))\n+                return 0;\n+        }\n+#endif /* !VMS */\n+    /* usual file type:  don't need VMS to extract */\n+    } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {\n+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n+            Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n+              FnFilter1(G.filename), \"PK\",\n+              G.crec.version_needed_to_extract[0] / 10,\n+              G.crec.version_needed_to_extract[0] % 10,\n+              UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));\n+        return 0;\n+    }\n+\n+    if (UNKN_COMPR) {\n+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {\n+#ifndef SFX\n+            unsigned cmpridx;\n+\n+            if ((cmpridx = find_compr_idx(G.crec.compression_method))\n+                < NUM_METHODS)\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),\n+                  FnFilter1(G.filename),\n+                  LoadFarStringSmall(ComprNames[cmpridx])));\n+            else\n+#endif\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),\n+                  FnFilter1(G.filename),\n+                  G.crec.compression_method));\n+        }\n+        return 0;\n+    }\n+#if (!CRYPT)\n+    if (G.pInfo->encrypted) {\n+        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n+            Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),\n+              FnFilter1(G.filename)));\n+        return 0;\n+    }\n+#endif /* !CRYPT */\n+\n+#ifndef SFX\n+    /* store a copy of the central header filename for later comparison */\n+    if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {\n+        Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),\n+          FnFilter1(G.filename)));\n+    } else\n+        zfstrcpy(G.pInfo->cfilname, G.filename);\n+#endif /* !SFX */\n+\n+    /* map whatever file attributes we have into the local format */\n+    mapattr(__G);   /* GRR:  worry about return value later */\n+\n+    G.pInfo->diskstart = G.crec.disk_number_start;\n+    G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;\n+    return 1;\n+\n+} /* end function store_info() */\n+\n+\n+\n+\n+\n+#ifndef SFX\n+/*******************************/\n+/*  Function find_compr_idx()  */\n+/*******************************/\n+\n+unsigned find_compr_idx(compr_methodnum)\n+    unsigned compr_methodnum;\n+{\n+   unsigned i;\n+\n+   for (i = 0; i < NUM_METHODS; i++) {\n+      if (ComprIDs[i] == compr_methodnum) break;\n+   }\n+   return i;\n+}\n+#endif /* !SFX */\n+\n+\n+\n+\n+\n+/******************************************/\n+/*  Function extract_or_test_entrylist()  */\n+/******************************************/\n+\n+static int extract_or_test_entrylist(__G__ numchunk,\n+                pfilnum, pnum_bad_pwd, pold_extra_bytes,\n+#ifdef SET_DIR_ATTRIB\n+                pnum_dirs, pdirlist,\n+#endif\n+                error_in_archive)    /* return PK-type error code */\n+    __GDEF\n+    unsigned numchunk;\n+    ulg *pfilnum;\n+    ulg *pnum_bad_pwd;\n+    zoff_t *pold_extra_bytes;\n+#ifdef SET_DIR_ATTRIB\n+    unsigned *pnum_dirs;\n+    direntry **pdirlist;\n+#endif\n+    int error_in_archive;\n+{\n+    unsigned i;\n+    int renamed, query;\n+    int skip_entry;\n+    zoff_t bufstart, inbuf_offset, request;\n+    int error, errcode;\n+\n+/* possible values for local skip_entry flag: */\n+#define SKIP_NO         0       /* do not skip this entry */\n+#define SKIP_Y_EXISTING 1       /* skip this entry, do not overwrite file */\n+#define SKIP_Y_NONEXIST 2       /* skip this entry, do not create new file */\n+\n+    /*-----------------------------------------------------------------------\n+        Second loop:  process files in current block, extracting or testing\n+        each one.\n+      -----------------------------------------------------------------------*/\n+\n+    for (i = 0; i < numchunk; ++i) {\n+        (*pfilnum)++;   /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */\n+        G.pInfo = &G.info[i];\n+#ifdef NOVELL_BUG_FAILSAFE\n+        G.dne = FALSE;  /* assume file exists until stat() says otherwise */\n+#endif\n+\n+        /* if the target position is not within the current input buffer\n+         * (either haven't yet read far enough, or (maybe) skipping back-\n+         * ward), skip to the target position and reset readbuf(). */\n+\n+        /* seek_zipf(__G__ pInfo->offset);  */\n+        request = G.pInfo->offset + G.extra_bytes;\n+        inbuf_offset = request % INBUFSIZ;\n+        bufstart = request - inbuf_offset;\n+\n+        Trace((stderr, \"\\ndebug: request = %ld, inbuf_offset = %ld\\n\",\n+          (long)request, (long)inbuf_offset));\n+        Trace((stderr,\n+          \"debug: bufstart = %ld, cur_zipfile_bufstart = %ld\\n\",\n+          (long)bufstart, (long)G.cur_zipfile_bufstart));\n+        if (request < 0) {\n+            Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),\n+              G.zipfn, LoadFarString(ReportMsg)));\n+            error_in_archive = PK_ERR;\n+            if (*pfilnum == 1 && G.extra_bytes != 0L) {\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarString(AttemptRecompensate)));\n+                *pold_extra_bytes = G.extra_bytes;\n+                G.extra_bytes = 0L;\n+                request = G.pInfo->offset;  /* could also check if != 0 */\n+                inbuf_offset = request % INBUFSIZ;\n+                bufstart = request - inbuf_offset;\n+                Trace((stderr, \"debug: request = %ld, inbuf_offset = %ld\\n\",\n+                  (long)request, (long)inbuf_offset));\n+                Trace((stderr,\n+                  \"debug: bufstart = %ld, cur_zipfile_bufstart = %ld\\n\",\n+                  (long)bufstart, (long)G.cur_zipfile_bufstart));\n+                /* try again */\n+                if (request < 0) {\n+                    Trace((stderr,\n+                      \"debug: recompensated request still < 0\\n\"));\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarStringSmall(SeekMsg),\n+                      G.zipfn, LoadFarString(ReportMsg)));\n+                    error_in_archive = PK_BADERR;\n+                    continue;\n+                }\n+            } else {\n+                error_in_archive = PK_BADERR;\n+                continue;  /* this one hosed; try next */\n+            }\n+        }\n+\n+        if (bufstart != G.cur_zipfile_bufstart) {\n+            Trace((stderr, \"debug: bufstart != cur_zipfile_bufstart\\n\"));\n+#ifdef USE_STRM_INPUT\n+            zfseeko(G.zipfd, bufstart, SEEK_SET);\n+            G.cur_zipfile_bufstart = zftello(G.zipfd);\n+#else /* !USE_STRM_INPUT */\n+            G.cur_zipfile_bufstart =\n+              zlseek(G.zipfd, bufstart, SEEK_SET);\n+#endif /* ?USE_STRM_INPUT */\n+            if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)\n+            {\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n+                  *pfilnum, \"lseek\", (long)bufstart));\n+                error_in_archive = PK_BADERR;\n+                continue;   /* can still do next file */\n+            }\n+            G.inptr = G.inbuf + (int)inbuf_offset;\n+            G.incnt -= (int)inbuf_offset;\n+        } else {\n+            G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;\n+            G.inptr = G.inbuf + (int)inbuf_offset;\n+        }\n+\n+        /* should be in proper position now, so check for sig */\n+        if (readbuf(__G__ G.sig, 4) == 0) {  /* bad offset */\n+            Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n+              *pfilnum, \"EOF\", (long)request));\n+            error_in_archive = PK_BADERR;\n+            continue;   /* but can still try next one */\n+        }\n+        if (strncmp(G.sig, local_hdr_sig, 4)) {\n+            Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),\n+              *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request));\n+            /*\n+                GRRDUMP(G.sig, 4)\n+                GRRDUMP(local_hdr_sig, 4)\n+             */\n+            error_in_archive = PK_ERR;\n+            if ((*pfilnum == 1 && G.extra_bytes != 0L) ||\n+                (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) {\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarString(AttemptRecompensate)));\n+                if (G.extra_bytes) {\n+                    *pold_extra_bytes = G.extra_bytes;\n+                    G.extra_bytes = 0L;\n+                } else\n+                    G.extra_bytes = *pold_extra_bytes; /* third attempt */\n+                if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) ||\n+                    (readbuf(__G__ G.sig, 4) == 0)) {  /* bad offset */\n+                    if (error != PK_BADERR)\n+                      Info(slide, 0x401, ((char *)slide,\n+                        LoadFarString(OffsetMsg), *pfilnum, \"EOF\",\n+                        (long)request));\n+                    error_in_archive = PK_BADERR;\n+                    continue;   /* but can still try next one */\n+                }\n+                if (strncmp(G.sig, local_hdr_sig, 4)) {\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(OffsetMsg), *pfilnum,\n+                      LoadFarStringSmall(LocalHdrSig), (long)request));\n+                    error_in_archive = PK_BADERR;\n+                    continue;\n+                }\n+            } else\n+                continue;  /* this one hosed; try next */\n+        }\n+        if ((error = process_local_file_hdr(__G)) != PK_COOL) {\n+            Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),\n+              *pfilnum));\n+            error_in_archive = error;   /* only PK_EOF defined */\n+            continue;   /* can still try next one */\n+        }\n+        if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) !=\n+             PK_COOL)\n+        {\n+            if (error > error_in_archive)\n+                error_in_archive = error;\n+            if (error > PK_WARN) {\n+                Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),\n+                  FnFilter1(G.filename), \"local\"));\n+                continue;   /* go on to next one */\n+            }\n+        }\n+        if (G.extra_field != (uch *)NULL) {\n+            free(G.extra_field);\n+            G.extra_field = (uch *)NULL;\n+        }\n+        if ((error =\n+             do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)\n+        {\n+            if (error > error_in_archive)\n+                error_in_archive = error;\n+            if (error > PK_WARN) {\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarString(ExtFieldMsg),\n+                  FnFilter1(G.filename), \"local\"));\n+                continue;   /* go on */\n+            }\n+        }\n+#ifndef SFX\n+        /* Filename consistency checks must come after reading in the local\n+         * extra field, so that a UTF-8 entry name e.f. block has already\n+         * been processed.\n+         */\n+        if (G.pInfo->cfilname != (char Far *)NULL) {\n+            if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {\n+#  ifdef SMALL_MEM\n+                char *temp_cfilnam = slide + (7 * (WSIZE>>3));\n+\n+                zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname);\n+#    define  cFile_PrintBuf  temp_cfilnam\n+#  else\n+#    define  cFile_PrintBuf  G.pInfo->cfilname\n+#  endif\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarStringSmall2(LvsCFNamMsg),\n+                  FnFilter2(cFile_PrintBuf), FnFilter1(G.filename)));\n+#  undef    cFile_PrintBuf\n+                zfstrcpy(G.filename, G.pInfo->cfilname);\n+                if (error_in_archive < PK_WARN)\n+                    error_in_archive = PK_WARN;\n+            }\n+            zffree(G.pInfo->cfilname);\n+            G.pInfo->cfilname = (char Far *)NULL;\n+        }\n+#endif /* !SFX */\n+        /* Size consistency checks must come after reading in the local extra\n+         * field, so that any Zip64 extension local e.f. block has already\n+         * been processed.\n+         */\n+        if (G.lrec.compression_method == STORED) {\n+            zusz_t csiz_decrypted = G.lrec.csize;\n+\n+            if (G.pInfo->encrypted)\n+                csiz_decrypted -= 12;\n+            if (G.lrec.ucsize != csiz_decrypted) {\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarStringSmall2(WrnStorUCSizCSizDiff),\n+                  FnFilter1(G.filename),\n+                  FmZofft(G.lrec.ucsize, NULL, \"u\"),\n+                  FmZofft(csiz_decrypted, NULL, \"u\")));\n+                G.lrec.ucsize = csiz_decrypted;\n+                if (error_in_archive < PK_WARN)\n+                    error_in_archive = PK_WARN;\n+            }\n+        }\n+\n+#if CRYPT\n+        if (G.pInfo->encrypted &&\n+            (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {\n+            if (error == PK_WARN) {\n+                if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(SkipIncorrectPasswd),\n+                      FnFilter1(G.filename)));\n+                ++(*pnum_bad_pwd);\n+            } else {  /* (error > PK_WARN) */\n+                if (error > error_in_archive)\n+                    error_in_archive = error;\n+                Info(slide, 0x401, ((char *)slide,\n+                  LoadFarString(SkipCannotGetPasswd),\n+                  FnFilter1(G.filename)));\n+            }\n+            continue;   /* go on to next file */\n+        }\n+#endif /* CRYPT */\n+\n+        /*\n+         * just about to extract file:  if extracting to disk, check if\n+         * already exists, and if so, take appropriate action according to\n+         * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper\n+         * loop because we don't store the possibly renamed filename[] in\n+         * info[])\n+         */\n+#ifdef DLL\n+        if (!uO.tflag && !uO.cflag && !G.redirect_data)\n+#else\n+        if (!uO.tflag && !uO.cflag)\n+#endif\n+        {\n+            renamed = FALSE;   /* user hasn't renamed output file yet */\n+\n+startover:\n+            query = FALSE;\n+            skip_entry = SKIP_NO;\n+            /* for files from DOS FAT, check for use of backslash instead\n+             *  of slash as directory separator (bug in some zipper(s); so\n+             *  far, not a problem in HPFS, NTFS or VFAT systems)\n+             */\n+#ifndef SFX\n+            if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) {\n+                char *p=G.filename;\n+\n+                if (*p) do {\n+                    if (*p == '\\\\') {\n+                        if (!G.reported_backslash) {\n+                            Info(slide, 0x21, ((char *)slide,\n+                              LoadFarString(BackslashPathSep), G.zipfn));\n+                            G.reported_backslash = TRUE;\n+                            if (!error_in_archive)\n+                                error_in_archive = PK_WARN;\n+                        }\n+                        *p = '/';\n+                    }\n+                } while (*PREINCSTR(p));\n+            }\n+#endif /* !SFX */\n+\n+            if (!renamed) {\n+               /* remove absolute path specs */\n+               if (G.filename[0] == '/') {\n+                   Info(slide, 0x401, ((char *)slide,\n+                        LoadFarString(AbsolutePathWarning),\n+                        FnFilter1(G.filename)));\n+                   if (!error_in_archive)\n+                       error_in_archive = PK_WARN;\n+                   do {\n+                       char *p = G.filename + 1;\n+                       do {\n+                           *(p-1) = *p;\n+                       } while (*p++ != '\\0');\n+                   } while (G.filename[0] == '/');\n+               }\n+            }\n+\n+            /* mapname can create dirs if not freshening or if renamed */\n+            error = mapname(__G__ renamed);\n+            if ((errcode = error & ~MPN_MASK) != PK_OK &&\n+                error_in_archive < errcode)\n+                error_in_archive = errcode;\n+            if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) {\n+                if (errcode == MPN_CREATED_DIR) {\n+#ifdef SET_DIR_ATTRIB\n+                    direntry *d_entry;\n+\n+                    error = defer_dir_attribs(__G__ &d_entry);\n+                    if (d_entry == (direntry *)NULL) {\n+                        /* There may be no dir_attribs info available, or\n+                         * we have encountered a mem allocation error.\n+                         * In case of an error, report it and set program\n+                         * error state to warning level.\n+                         */\n+                        if (error) {\n+                            Info(slide, 0x401, ((char *)slide,\n+                                 LoadFarString(DirlistEntryNoMem)));\n+                            if (!error_in_archive)\n+                                error_in_archive = PK_WARN;\n+                        }\n+                    } else {\n+                        d_entry->next = (*pdirlist);\n+                        (*pdirlist) = d_entry;\n+                        ++(*pnum_dirs);\n+                    }\n+#endif /* SET_DIR_ATTRIB */\n+                } else if (errcode == MPN_VOL_LABEL) {\n+#ifdef DOS_OS2_W32\n+                    Info(slide, 0x401, ((char *)slide,\n+                      LoadFarString(SkipVolumeLabel),\n+                      FnFilter1(G.filename),\n+                      uO.volflag? \"hard disk \" : \"\"));\n+#else\n+                    Info(slide, 1, ((char *)slide,\n+                      LoadFarString(SkipVolumeLabel),\n+                      FnFilter1(G.filename), \"\"));\n+#endif\n+                } else if (errcode > MPN_INF_SKIP &&\n+                           error_in_archive < PK_ERR)\n+                    error_in_archive = PK_ERR;\n+                Trace((stderr, \"mapname(%s) returns error code = %d\\n\",\n+                  FnFilter1(G.filename), error));\n+                continue;   /* go on to next file */\n+            }\n+\n+#ifdef QDOS\n+            QFilename(__G__ G.filename);\n+#endif\n+            switch (check_for_newer(__G__ G.filename)) {\n+                case DOES_NOT_EXIST:\n+#ifdef NOVELL_BUG_FAILSAFE\n+                    G.dne = TRUE;   /* stat() says file DOES NOT EXIST */\n+#endif\n+                    /* freshen (no new files): skip unless just renamed */\n+                    if (uO.fflag && !renamed)\n+                        skip_entry = SKIP_Y_NONEXIST;\n+                    break;\n+                case EXISTS_AND_OLDER:\n+#ifdef UNIXBACKUP\n+                    if (!uO.B_flag)\n+#endif\n+                    {\n+                        if (IS_OVERWRT_NONE)\n+                            /* never overwrite:  skip file */\n+                            skip_entry = SKIP_Y_EXISTING;\n+                        else if (!IS_OVERWRT_ALL)\n+                            query = TRUE;\n+                    }\n+                    break;\n+                case EXISTS_AND_NEWER:             /* (or equal) */\n+#ifdef UNIXBACKUP\n+                    if ((!uO.B_flag && IS_OVERWRT_NONE) ||\n+#else\n+                    if (IS_OVERWRT_NONE ||\n+#endif\n+                        (uO.uflag && !renamed)) {\n+                        /* skip if update/freshen & orig name */\n+                        skip_entry = SKIP_Y_EXISTING;\n+                    } else {\n+#ifdef UNIXBACKUP\n+                        if (!IS_OVERWRT_ALL && !uO.B_flag)\n+#else\n+                        if (!IS_OVERWRT_ALL)\n+#endif\n+                            query = TRUE;\n+                    }\n+                    break;\n+                }\n+            if (query) {\n+#ifdef WINDLL\n+                switch (G.lpUserFunctions->replace != NULL ?\n+                        (*G.lpUserFunctions->replace)(G.filename) :\n+                        IDM_REPLACE_NONE) {\n+                    case IDM_REPLACE_RENAME:\n+                        _ISO_INTERN(G.filename);\n+                        renamed = TRUE;\n+                        goto startover;\n+                    case IDM_REPLACE_ALL:\n+                        G.overwrite_mode = OVERWRT_ALWAYS;\n+                        /* FALL THROUGH, extract */\n+                    case IDM_REPLACE_YES:\n+                        break;\n+                    case IDM_REPLACE_NONE:\n+                        G.overwrite_mode = OVERWRT_NEVER;\n+                        /* FALL THROUGH, skip */\n+                    case IDM_REPLACE_NO:\n+                        skip_entry = SKIP_Y_EXISTING;\n+                        break;\n+                }\n+#else /* !WINDLL */\n+                extent fnlen;\n+reprompt:\n+                Info(slide, 0x81, ((char *)slide,\n+                  LoadFarString(ReplaceQuery),\n+                  FnFilter1(G.filename)));\n+                if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {\n+                    Info(slide, 1, ((char *)slide,\n+                      LoadFarString(AssumeNone)));\n+                    *G.answerbuf = 'N';\n+                    if (!error_in_archive)\n+                        error_in_archive = 1;  /* not extracted:  warning */\n+                }\n+                switch (*G.answerbuf) {\n+                    case 'r':\n+                    case 'R':\n+                        do {\n+                            Info(slide, 0x81, ((char *)slide,\n+                              LoadFarString(NewNameQuery)));\n+                            fgets(G.filename, FILNAMSIZ, stdin);\n+                            /* usually get \\n here:  better check for it */\n+                            fnlen = strlen(G.filename);\n+                            if (lastchar(G.filename, fnlen) == '\\n')\n+                                G.filename[--fnlen] = '\\0';\n+                        } while (fnlen == 0);\n+#ifdef WIN32  /* WIN32 fgets( ... , stdin) returns OEM coded strings */\n+                        _OEM_INTERN(G.filename);\n+#endif\n+                        renamed = TRUE;\n+                        goto startover;   /* sorry for a goto */\n+                    case 'A':   /* dangerous option:  force caps */\n+                        G.overwrite_mode = OVERWRT_ALWAYS;\n+                        /* FALL THROUGH, extract */\n+                    case 'y':\n+                    case 'Y':\n+                        break;\n+                    case 'N':\n+                        G.overwrite_mode = OVERWRT_NEVER;\n+                        /* FALL THROUGH, skip */\n+                    case 'n':\n+                        /* skip file */\n+                        skip_entry = SKIP_Y_EXISTING;\n+                        break;\n+                    case '\\n':\n+                    case '\\r':\n+                        /* Improve echo of '\\n' and/or '\\r'\n+                           (sizeof(G.answerbuf) == 10 (see globals.h), so\n+                           there is enough space for the provided text...) */\n+                        strcpy(G.answerbuf, \"{ENTER}\");\n+                        /* fall through ... */\n+                    default:\n+                        Info(slide, 1, ((char *)slide,\n+                          LoadFarString(InvalidResponse), *G.answerbuf));\n+                        goto reprompt;   /* yet another goto? */\n+                } /* end switch (*answerbuf) */\n+#endif /* ?WINDLL */\n+            } /* end if (query) */\n+            if (skip_entry != SKIP_NO) {\n+#ifdef WINDLL\n+                if (skip_entry == SKIP_Y_EXISTING) {\n+                    /* report skipping of an existing entry */\n+                    Info(slide, 0, ((char *)slide,\n+                      ((IS_OVERWRT_NONE || !uO.uflag || renamed) ?\n+                       \"Target file exists.\\nSkipping %s\\n\" :\n+                       \"Target file newer.\\nSkipping %s\\n\"),\n+                      FnFilter1(G.filename)));\n+                }\n+#endif /* WINDLL */\n+                continue;\n+            }\n+        } /* end if (extracting to disk) */\n+\n+#ifdef DLL\n+        if ((G.statreportcb != NULL) &&\n+            (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,\n+                              G.filename, NULL)) {\n+            return IZ_CTRLC;        /* cancel operation by user request */\n+        }\n #endif\n-\n-#ifdef USE_PPMD\n-#  define UNKN_PPMD (G.crec.compression_method!=PPMDED)\n-#else\n-#  define UNKN_PPMD TRUE      /* PPMd unknown */\n+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */\n+        UserStop();\n #endif\n-\n-#ifdef SFX\n-#  ifdef USE_DEFLATE64\n-#    define UNKN_COMPR \\\n-     (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \\\n-      && G.crec.compression_method>ENHDEFLATED \\\n-      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n-#  else\n-#    define UNKN_COMPR \\\n-     (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\\\n-      && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD)\n-#  endif\n-#else\n-#  ifdef COPYRIGHT_CLEAN  /* no reduced files */\n-#    define UNKN_RED (G.crec.compression_method >= REDUCED1 && \\\n-                      G.crec.compression_method <= REDUCED4)\n-#  else\n-#    define UNKN_RED  FALSE  /* reducing not unknown */\n-#  endif\n-#  ifdef LZW_CLEAN  /* no shrunk files */\n-#    define UNKN_SHR (G.crec.compression_method == SHRUNK)\n-#  else\n-#    define UNKN_SHR  FALSE  /* unshrinking not unknown */\n-#  endif\n-#  ifdef USE_DEFLATE64\n-#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n-     G.crec.compression_method==TOKENIZED || \\\n-     (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n-      && UNKN_WAVP && UNKN_PPMD))\n-#  else\n-#    define UNKN_COMPR (UNKN_RED || UNKN_SHR || \\\n-     G.crec.compression_method==TOKENIZED || \\\n-     (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \\\n-      && UNKN_WAVP && UNKN_PPMD))\n-#  endif\n+#ifdef AMIGA\n+        G.filenote_slot = i;\n #endif\n-\n-#if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS))\n-    int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS);\n-#   define UNZVERS_SUPPORT  unzvers_support\n+        G.disk_full = 0;\n+        if ((error = extract_or_test_member(__G)) != PK_COOL) {\n+            if (error > error_in_archive)\n+                error_in_archive = error;       /* ...and keep going */\n+#ifdef DLL\n+            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {\n #else\n-#   define UNZVERS_SUPPORT  UNZIP_VERSION\n+            if (G.disk_full > 1) {\n #endif\n-\n-/*---------------------------------------------------------------------------\n-    Check central directory info for version/compatibility requirements.\n-  ---------------------------------------------------------------------------*/\n-\n-    G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1;   /* bit field */\n-    G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8;  /* bit */\n-    G.pInfo->textfile = G.crec.internal_file_attributes & 1;    /* bit field */\n-    G.pInfo->crc = G.crec.crc32;\n-    G.pInfo->compr_size = G.crec.csize;\n-    G.pInfo->uncompr_size = G.crec.ucsize;\n-\n-    switch (uO.aflag) {\n-        case 0:\n-            G.pInfo->textmode = FALSE;   /* bit field */\n-            break;\n-        case 1:\n-            G.pInfo->textmode = G.pInfo->textfile;   /* auto-convert mode */\n-            break;\n-        default:  /* case 2: */\n-            G.pInfo->textmode = TRUE;\n-            break;\n-    }\n-\n-    if (G.crec.version_needed_to_extract[1] == VMS_) {\n-        if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {\n-            if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n-                Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n-                  FnFilter1(G.filename), \"VMS\",\n-                  G.crec.version_needed_to_extract[0] / 10,\n-                  G.crec.version_needed_to_extract[0] % 10,\n-                  VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));\n-            return 0;\n+                return error_in_archive;        /* (unless disk full) */\n+            }\n         }\n-#ifndef VMS   /* won't be able to use extra field, but still have data */\n-        else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */\n-            Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),\n-              FnFilter1(G.filename)));\n-            fgets(G.answerbuf, 9, stdin);\n-            if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))\n-                return 0;\n+#ifdef DLL\n+        if ((G.statreportcb != NULL) &&\n+            (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,\n+                              G.filename, (zvoid *)&G.lrec.ucsize)) {\n+            return IZ_CTRLC;        /* cancel operation by user request */\n         }\n-#endif /* !VMS */\n-    /* usual file type:  don't need VMS to extract */\n-    } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) {\n-        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n-            Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),\n-              FnFilter1(G.filename), \"PK\",\n-              G.crec.version_needed_to_extract[0] / 10,\n-              G.crec.version_needed_to_extract[0] % 10,\n-              UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10));\n-        return 0;\n-    }\n-\n-    if (UNKN_COMPR) {\n-        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {\n-#ifndef SFX\n-            unsigned cmpridx;\n-\n-            if ((cmpridx = find_compr_idx(G.crec.compression_method))\n-                < NUM_METHODS)\n-                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),\n-                  FnFilter1(G.filename),\n-                  LoadFarStringSmall(ComprNames[cmpridx])));\n-            else\n #endif\n-                Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),\n-                  FnFilter1(G.filename),\n-                  G.crec.compression_method));\n-        }\n-        return 0;\n-    }\n-#if (!CRYPT)\n-    if (G.pInfo->encrypted) {\n-        if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))\n-            Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),\n-              FnFilter1(G.filename)));\n-        return 0;\n-    }\n-#endif /* !CRYPT */\n-\n-#ifndef SFX\n-    /* store a copy of the central header filename for later comparison */\n-    if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) {\n-        Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName),\n-          FnFilter1(G.filename)));\n-    } else\n-        zfstrcpy(G.pInfo->cfilname, G.filename);\n-#endif /* !SFX */\n-\n-    /* map whatever file attributes we have into the local format */\n-    mapattr(__G);   /* GRR:  worry about return value later */\n-\n-    G.pInfo->diskstart = G.crec.disk_number_start;\n-    G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header;\n-    return 1;\n-\n-} /* end function store_info() */\n-\n-\n-\n-\n-\n-#ifndef SFX\n-/*******************************/\n-/*  Function find_compr_idx()  */\n-/*******************************/\n-\n-unsigned find_compr_idx(compr_methodnum)\n-    unsigned compr_methodnum;\n-{\n-   unsigned i;\n-\n-   for (i = 0; i < NUM_METHODS; i++) {\n-      if (ComprIDs[i] == compr_methodnum) break;\n-   }\n-   return i;\n-}\n-#endif /* !SFX */\n+#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */\n+        UserStop();\n+#endif\n+    } /* end for-loop (i:  files in current block) */\n \n+    return error_in_archive;\n \n+} /* end function extract_or_test_entrylist() */\n \n \n \n-/******************************************/\n-/*  Function extract_or_test_entrylist()  */\n-/******************************************/\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n \n-static int extract_or_test_entrylist(__G__ numchunk,\n+static int extract_or_test_entrylistw(__G__ numchunk,\n                 pfilnum, pnum_bad_pwd, pold_extra_bytes,\n #ifdef SET_DIR_ATTRIB\n-                pnum_dirs, pdirlist,\n+                pnum_dirs, pdirlistw,\n #endif\n                 error_in_archive)    /* return PK-type error code */\n@@ -1016,5 +1653,5 @@\n #ifdef SET_DIR_ATTRIB\n     unsigned *pnum_dirs;\n-    direntry **pdirlist;\n+    direntryw **pdirlistw;\n #endif\n     int error_in_archive;\n@@ -1190,8 +1827,4 @@\n         }\n #ifndef SFX\n-        /* Filename consistency checks must come after reading in the local\n-         * extra field, so that a UTF-8 entry name e.f. block has already\n-         * been processed.\n-         */\n         if (G.pInfo->cfilname != (char Far *)NULL) {\n             if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) {\n@@ -1316,5 +1949,8 @@\n \n             /* mapname can create dirs if not freshening or if renamed */\n-            error = mapname(__G__ renamed);\n+            if (G.has_win32_wide)\n+              error = mapnamew(__G__ renamed);\n+            else\n+              error = mapname(__G__ renamed);\n             if ((errcode = error & ~MPN_MASK) != PK_OK &&\n                 error_in_archive < errcode)\n@@ -1323,24 +1959,24 @@\n                 if (errcode == MPN_CREATED_DIR) {\n #ifdef SET_DIR_ATTRIB\n-                    direntry *d_entry;\n+                  direntryw *d_entryw;\n \n-                    error = defer_dir_attribs(__G__ &d_entry);\n-                    if (d_entry == (direntry *)NULL) {\n-                        /* There may be no dir_attribs info available, or\n-                         * we have encountered a mem allocation error.\n-                         * In case of an error, report it and set program\n-                         * error state to warning level.\n-                         */\n-                        if (error) {\n-                            Info(slide, 0x401, ((char *)slide,\n-                                 LoadFarString(DirlistEntryNoMem)));\n-                            if (!error_in_archive)\n-                                error_in_archive = PK_WARN;\n-                        }\n-                    } else {\n-                        d_entry->next = (*pdirlist);\n-                        (*pdirlist) = d_entry;\n-                        ++(*pnum_dirs);\n-                    }\n+                  error = defer_dir_attribsw(__G__ &d_entryw);\n+                  if (d_entryw == (direntryw *)NULL) {\n+                      /* There may be no dir_attribs info available, or\n+                       * we have encountered a mem allocation error.\n+                       * In case of an error, report it and set program\n+                       * error state to warning level.\n+                       */\n+                      if (error) {\n+                          Info(slide, 0x401, ((char *)slide,\n+                               LoadFarString(DirlistEntryNoMem)));\n+                          if (!error_in_archive)\n+                              error_in_archive = PK_WARN;\n+                      }\n+                  } else {\n+                      d_entryw->next = (*pdirlistw);\n+                      (*pdirlistw) = d_entryw;\n+                      ++(*pnum_dirs);\n+                  }\n #endif /* SET_DIR_ATTRIB */\n                 } else if (errcode == MPN_VOL_LABEL) {\n@@ -1366,5 +2002,5 @@\n             QFilename(__G__ G.filename);\n #endif\n-            switch (check_for_newer(__G__ G.filename)) {\n+            switch (check_for_newerw(__G__ G.unipath_widefilename)) {\n                 case DOES_NOT_EXIST:\n #ifdef NOVELL_BUG_FAILSAFE\n@@ -1538,5 +2174,7 @@\n     return error_in_archive;\n \n-} /* end function extract_or_test_entrylist() */\n+} /* end function extract_or_test_entrylistw() */\n+\n+#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n \n \n@@ -2565,4 +3203,14 @@\n  /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */\n }\n+\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int Cdecl dircompw(a, b)  /* used by qsort(); swiped from Zip */\n+    ZCONST zvoid *a, *b;\n+{\n+    /* order is significant:  this sorts in reverse order (deepest first) */\n+    return wcscmp((*(direntryw **)b)->fnw, (*(direntryw **)a)->fnw);\n+ /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */\n+}\n+# endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n \n #endif /* SET_DIR_ATTRIB */\ndiff -ru2 unz60d10/fileio.c unz60d10_w32w/fileio.c\n--- unz60d10/fileio.c\tSun Jan 27 16:39:14 2008\n+++ unz60d10_w32w/fileio.c\tMon Feb 11 01:09:22 2008\n@@ -294,5 +294,12 @@\n         zlstat(G.filename, &G.statbuf) == 0)\n #else\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    if ((G.has_win32_wide\n+         ? SSTATW(G.unipath_widefilename, &G.statbuf)\n+         : SSTAT(G.filename, &G.statbuf)\n+        ) == 0)\n+#else\n     if (SSTAT(G.filename, &G.statbuf) == 0)\n+#endif\n #endif /* ?SYMLINKS */\n     {\n@@ -378,5 +385,13 @@\n             chmod(G.filename, 0);\n #endif /* NLM */\n-            if (unlink(G.filename) != 0) {\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+            if ((G.has_win32_wide\n+                 ? _wunlink(G.unipath_widefilename)\n+                 : unlink(G.filename)\n+                ) != 0)\n+#else\n+            if (unlink(G.filename) != 0)\n+#endif\n+            {\n                 Info(slide, 0x401, ((char *)slide,\n                   LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));\n@@ -456,5 +471,12 @@\n         G.outfile = zfopen(G.filename, FOPWR);\n #else\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        G.outfile = (G.has_win32_wide\n+                    ? zfopenw(G.unipath_widefilename, L\"wb\")\n+                    : zfopen(G.filename, FOPW)\n+                    );\n+#else /* (UNICODE_SUPPORT && WIN32_WIDE) */\n         G.outfile = zfopen(G.filename, FOPW);\n+#endif /* ?(UNICODE_SUPPORT && WIN32_WIDE) */\n #endif\n #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)\n@@ -1984,4 +2006,115 @@\n } /* end function check_for_newer() */\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int check_for_newerw(__G__ filenamew)  /* return 1 if existing file is newer */\n+    __GDEF                           /*  or equal; 0 if older; -1 if doesn't */\n+    wchar_t *filenamew;                  /*  exist yet */\n+{\n+    time_t existing, archive;\n+#ifdef USE_EF_UT_TIME\n+    iztimes z_utime;\n+#endif\n+#ifdef AOS_VS\n+    long    dyy, dmm, ddd, dhh, dmin, dss;\n+\n+\n+    dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;\n+    dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;\n+    ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;\n+    dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;\n+    dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;\n+    dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;\n+\n+    /* under AOS/VS, file times can only be set at creation time,\n+     * with the info in a special DG format.  Make sure we can create\n+     * it here - we delete it later & re-create it, whether or not\n+     * it exists now.\n+     */\n+    if (!zvs_create(filenamew, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |\n+        (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))\n+        return DOES_NOT_EXIST;\n+#endif /* AOS_VS */\n+\n+    Trace((stderr, \"check_for_newer:  doing stat(%s)\\n\", FnFilter1(filename)));\n+    if (SSTATW(filenamew, &G.statbuf)) {\n+        Trace((stderr,\n+          \"check_for_newer:  stat(%s) returns %d:  file does not exist\\n\",\n+          FnFilter1(filename), SSTAT(filename, &G.statbuf)));\n+#ifdef SYMLINKS\n+        Trace((stderr, \"check_for_newer:  doing lstat(%s)\\n\",\n+          FnFilter1(filename)));\n+        /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */\n+        if (zlstat(filename, &G.statbuf) == 0) {\n+            Trace((stderr,\n+              \"check_for_newer:  lstat(%s) returns 0:  symlink does exist\\n\",\n+              FnFilter1(filename)));\n+            if (QCOND2 && !IS_OVERWRT_ALL)\n+                Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),\n+                  FnFilter1(filename), \" with no real file\"));\n+            return EXISTS_AND_OLDER;   /* symlink dates are meaningless */\n+        }\n+#endif /* SYMLINKS */\n+        return DOES_NOT_EXIST;\n+    }\n+    Trace((stderr, \"check_for_newer:  stat(%s) returns 0:  file exists\\n\",\n+      FnFilter1(filename)));\n+\n+#ifdef SYMLINKS\n+    /* GRR OPTION:  could instead do this test ONLY if G.symlnk is true */\n+    if (zlstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {\n+        Trace((stderr, \"check_for_newer:  %s is a symbolic link\\n\",\n+          FnFilter1(filename)));\n+        if (QCOND2 && !IS_OVERWRT_ALL)\n+            Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),\n+              FnFilter1(filename), \"\"));\n+        return EXISTS_AND_OLDER;   /* symlink dates are meaningless */\n+    }\n+#endif /* SYMLINKS */\n+\n+    NATIVE_TO_TIMET(G.statbuf.st_mtime)   /* NOP unless MSC 7.0 or Macintosh */\n+\n+#ifdef USE_EF_UT_TIME\n+    /* The `Unix extra field mtime' should be used for comparison with the\n+     * time stamp of the existing file >>>ONLY<<< when the EF info is also\n+     * used to set the modification time of the extracted file.\n+     */\n+    if (G.extra_field &&\n+#ifdef IZ_CHECK_TZ\n+        G.tz_is_valid &&\n+#endif\n+        (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,\n+                          G.lrec.last_mod_dos_datetime, &z_utime, NULL)\n+         & EB_UT_FL_MTIME))\n+    {\n+        TTrace((stderr, \"check_for_newer:  using Unix extra field mtime\\n\"));\n+        existing = G.statbuf.st_mtime;\n+        archive  = z_utime.mtime;\n+    } else {\n+        /* round up existing filetime to nearest 2 seconds for comparison,\n+         * but saturate in case of arithmetic overflow\n+         */\n+        existing = ((G.statbuf.st_mtime & 1) &&\n+                    (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?\n+                   G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;\n+        archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n+    }\n+#else /* !USE_EF_UT_TIME */\n+    /* round up existing filetime to nearest 2 seconds for comparison,\n+     * but saturate in case of arithmetic overflow\n+     */\n+    existing = ((G.statbuf.st_mtime & 1) &&\n+                (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?\n+               G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;\n+    archive  = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n+#endif /* ?USE_EF_UT_TIME */\n+\n+    TTrace((stderr, \"check_for_newer:  existing %lu, archive %lu, e-a %ld\\n\",\n+      (ulg)existing, (ulg)archive, (long)(existing-archive)));\n+\n+    return (existing >= archive);\n+\n+} /* end function check_for_newerw() */\n+#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+\n #endif /* !VMS && !OS2 && !CMS_MVS */\n \n@@ -2319,4 +2452,23 @@\n                 free(fn);\n               }\n+# ifdef WIN32_WIDE\n+              G.unipath_widefilename = NULL;\n+              if (G.has_win32_wide) {\n+                if (G.unipath_filename)\n+                  /* Get wide path from UTF-8 */\n+                  G.unipath_widefilename = utf8_to_wchar_string(G.unipath_filename);\n+                else\n+                  G.unipath_widefilename = utf8_to_wchar_string(G.filename);\n+\n+                if (G.pInfo->lcflag)      /* replace with lowercase filename */\n+                    wcslwr(G.unipath_widefilename);\n+\n+                if (G.pInfo->vollabel && length > 8 && G.unipath_widefilename[8] == '.') {\n+                    wchar_t *p = G.unipath_widefilename+8;\n+                    while (*p++)\n+                        p[-1] = *p;  /* disk label, and 8th char is dot:  remove dot */\n+                }\n+              }\n+# endif /* WIN32_WIDE */\n             }\n #endif /* UNICODE_SUPPORT */\ndiff -ru2 unz60d10/globals.h unz60d10_w32w/globals.h\n--- unz60d10/globals.h\tSun Jan 27 16:31:56 2008\n+++ unz60d10_w32w/globals.h\tMon Feb 11 01:09:22 2008\n@@ -302,4 +302,8 @@\n     ulg      unipath_checksum;     /* Unicode field checksum */\n     char     *unipath_filename;    /* UTF-8 path */\n+# ifdef WIN32_WIDE\n+    wchar_t  *unipath_widefilename;     /* wide character filename */\n+    int      has_win32_wide;       /* true if Win32 W calls work */\n+# endif\n     char     *unipath_escapedfilename;\n #endif /* UNICODE_SUPPORT */\ndiff -ru2 unz60d10/match.c unz60d10_w32w/match.c\n--- unz60d10/match.c\tSun Aug 14 20:00:36 2005\n+++ unz60d10_w32w/match.c\tSun Jan  6 18:19:46 2008\n@@ -1,4 +1,4 @@\n /*\n-  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n+  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n \n   See the accompanying file LICENSE, version 2000-Apr-09 or later\n@@ -407,5 +407,18 @@\n } /* end function iswild() */\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int iswildw(pw)          /* originally only used for stat()-bug workaround in */\n+    ZCONST wchar_t *pw;  /*  VAX C, Turbo/Borland C, Watcom C, Atari MiNT libs; */\n+{                    /*  now used in process_zipfiles() as well */\n+    for (; *pw; pw++)\n+        if (*pw == '\\\\' && *(pw+1))\n+            ++pw;\n+        else if (*pw == '?' || *pw == '*' || *pw == '[')\n+            return TRUE;\n+\n+    return FALSE;\n \n+} /* end function iswildw() */\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n \n \ndiff -ru2 unz60d10/process.c unz60d10_w32w/process.c\n--- unz60d10/process.c\tSun Feb  3 00:03:34 2008\n+++ unz60d10_w32w/process.c\tMon Feb 11 01:09:22 2008\n@@ -43,4 +43,7 @@\n #  include \"crc32.h\"\n #endif\n+#ifdef UNICODE_SUPPORT\n+#  include <wchar.h>\n+#endif /* def UNICODE_SUPPORT */\n \n static int    do_seekable        OF((__GPRO__ int lastchance));\n@@ -552,5 +555,12 @@\n \n     inflate_free(__G);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    if (G.has_win32_wide)\n+      checkdirw(__G__ (wchar_t *)NULL, END);\n+    else\n+      checkdir(__G__ (char *)NULL, END);\n+#else\n     checkdir(__G__ (char *)NULL, END);\n+#endif\n \n #ifdef DYNALLOC_CRCTAB\n@@ -1507,26 +1517,4 @@\n      */\n \n-    /* This is an internal comment.  Remove before the next public beta.\n-\n-       Below check does not catch when an entry requires Zip64, as\n-       when the uncompressed size is larger than 4 GB, but the\n-       standard fields in ecrec (called EOCDR in the Zip source)\n-       are sufficient, as when the file compresses under the Zip64\n-       limit.  In such cases ecrec64 (called Zip64 EOCDR in Zip)\n-       will exist to flag the archive as Zip64, even though none\n-       of the ecrec values are set to the FFFF or FFFFFFFF flag\n-       values.\n-\n-      if(check_ecrec_zip64(__G)){\n-        need_zip64 = TRUE;\n-      }\n-\n-       In fact, this check is not needed, as ecrec64 will ALWAYS\n-       exist for a proper Zip64 archive, as the Version Needed To Extract\n-       field is required to be set to 4.5 or higher.\n-\n-       End of internal comment.\n-     */\n-\n     /* The ecrec64 will ALWAYS exist for a proper Zip64 archive, as\n        the Version Needed To Extract field is required to be set to\n@@ -1954,7 +1942,4 @@\n             G.unipath_filename[ULen] = '\\0';\n           }\n-# if 0\n-          G.unipath_escapedfilename = utf8_to_escaped_string(G.unipath_filename);\n-# endif\n         }\n \n@@ -2324,4 +2309,37 @@\n   return w;\n }\n+\n+char *wchar_to_local_string(wchar_string, escape_all)\n+  wchar_t *wchar_string;\n+  int escape_all;\n+{\n+  zwchar *wide_string = wchar_to_wide_string(wchar_string);\n+  char *local_string = wide_to_local_string(wide_string, escape_all);\n+\n+  free(wide_string);\n+\n+  return local_string;\n+}\n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+zwchar *wchar_to_wide_string(wchar_string)\n+  wchar_t *wchar_string;\n+{\n+  int i;\n+  int wchar_len;\n+  zwchar *wide_string;\n+\n+  wchar_len = wcslen(wchar_string);\n+\n+  if ((wide_string = malloc((wchar_len + 1) * sizeof(zwchar))) == NULL) {\n+    return NULL;\n+  }\n+  for (i = 0; i <= wchar_len; i++) {\n+    wide_string[i] = wchar_string[i];\n+  }\n+\n+  return wide_string;\n+}\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n \n char *utf8_to_escaped_string(utf8_string, escape_all)\ndiff -ru2 unz60d10/unzpriv.h unz60d10_w32w/unzpriv.h\n--- unz60d10/unzpriv.h\tSun Feb  3 15:50:52 2008\n+++ unz60d10_w32w/unzpriv.h\tMon Feb 11 02:05:46 2008\n@@ -1318,4 +1318,7 @@\n #     define zstat _stati64\n #     define zfstat _fstati64\n+#  if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+#     define zstatw _wstati64\n+#  endif\n \n     /* 64-bit lseek */\n@@ -1332,4 +1335,7 @@\n     /* 64-bit fopen */\n #     define zfopen fopen\n+#   if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+#     define zfopenw _wfopen\n+#   endif\n #     define zfdopen fdopen\n \n@@ -1904,4 +1910,11 @@\n        char buf[1];             /* start of system-specific internal data */\n    } direntry;\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   typedef struct direntryw {   /* head of system-specific struct holding */\n+       struct direntryw *next;  /*  defered directory attributes info */\n+       wchar_t *fnw;            /* filename of directory */\n+       wchar_t buf[1];          /* start of system-specific internal data */\n+   } direntryw;\n+# endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n #endif /* SET_DIR_ATTRIB */\n \n@@ -2225,4 +2238,7 @@\n time_t   dos_to_unix_time     OF((ulg dos_datetime));\n int      check_for_newer      OF((__GPRO__ char *filename)); /* os2,vmcms,vms */\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int      check_for_newerw     OF((__GPRO__ wchar_t *filenamew)); /* os2,vmcms,vms */\n+#endif\n int      do_string            OF((__GPRO__ unsigned int length, int option));\n ush      makeword             OF((ZCONST uch *b));\n@@ -2468,4 +2484,8 @@\n    int   zstat_win32    OF((__W32STAT_GLOBALS__\n                             const char *path, z_stat *buf));      /* win32.c */\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   int   zstat_win32w   OF((__W32STAT_GLOBALS__\n+                            const wchar_t *pathw, z_stat *buf));      /* win32.c */\n+# endif\n #endif\n #endif\n@@ -2485,4 +2505,7 @@\n                              int ic __WDLPRO));                   /* match.c */\n int      iswild          OF((ZCONST char *p));                    /* match.c */\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int      iswildw         OF((ZCONST wchar_t *pw));                /* match.c */\n+#endif\n \n /* declarations of public CRC-32 functions have been moved into crc32.h\n@@ -2497,4 +2520,8 @@\n int      mapname         OF((__GPRO__ int renamed));                /* local */\n int      checkdir        OF((__GPRO__ char *pathcomp, int flag));   /* local */\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+  int    mapnamew        OF((__GPRO__ int renamed));                /* local */\n+  int    checkdirw       OF((__GPRO__ wchar_t *pathcomp, int flag));   /* local */\n+#endif\n char    *do_wild         OF((__GPRO__ ZCONST char *wildzipfn));     /* local */\n char    *GetLoadPath     OF((__GPRO));                              /* local */\n@@ -2517,4 +2544,8 @@\n    int   defer_dir_attribs  OF((__GPRO__ direntry **pd));           /* local */\n    int   set_direc_attribs  OF((__GPRO__ direntry *d));             /* local */\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   int   defer_dir_attribsw  OF((__GPRO__ direntryw **pd));           /* local */\n+   int   set_direc_attribsw  OF((__GPRO__ direntryw *d));             /* local */\n+# endif\n #endif\n #ifdef TIMESTAMP\n@@ -2980,4 +3011,8 @@\n   /* convert UTF-8 string to wide string */\n   zwchar *utf8_to_wide_string OF((char *));\n+\n+  char *wchar_to_local_string OF((wchar_t *, int));\n+\n+  zwchar *wchar_to_wide_string OF((wchar_t *));\n \n   /* convert wide string to multi-byte string */\ndiff -ru2 unz60d10/win32/nt.c unz60d10_w32w/win32/nt.c\n--- unz60d10/win32/nt.c\tTue Dec 25 12:34:50 2007\n+++ unz60d10_w32w/win32/nt.c\tMon Feb 11 02:09:20 2008\n@@ -1,6 +1,6 @@\n /*\n-  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n+  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n \n-  See the accompanying file LICENSE, version 2000-Apr-09 or later\n+  See the accompanying file LICENSE, version 2007-Mar-04 or later\n   (the contents of which are also included in unzip.h) for terms of use.\n   If, for some reason, all these files are missing, the Info-ZIP license\n@@ -63,5 +63,10 @@\n \n static BOOL Initialize(VOID);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static VOID GetRemotePrivilegesSet(wchar_t *FileName,\n+                                   PDWORD dwRemotePrivileges);\n+#else\n static VOID GetRemotePrivilegesSet(CHAR *FileName, PDWORD dwRemotePrivileges);\n+#endif\n static VOID InitLocalPrivileges(VOID);\n \n@@ -191,5 +196,10 @@\n }\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static VOID GetRemotePrivilegesSet(wchar_t *FileName,\n+                                   PDWORD dwRemotePrivileges)\n+#else\n static VOID GetRemotePrivilegesSet(char *FileName, PDWORD dwRemotePrivileges)\n+#endif\n {\n     HANDLE hFile;\n@@ -199,5 +209,9 @@\n     /* see if we have the SeRestorePrivilege */\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    hFile = CreateFileW(\n+#else\n     hFile = CreateFileA(\n+#endif\n         FileName,\n         ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER | READ_CONTROL,\n@@ -236,5 +250,9 @@\n         /* note we don't need this if we have SeRestorePrivilege */\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        hFile = CreateFileW(\n+#else\n         hFile = CreateFileA(\n+#endif\n             FileName,\n             ACCESS_SYSTEM_SECURITY,\n@@ -255,10 +273,19 @@\n \n BOOL GetVolumeCaps(\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    wchar_t *rootpath,      /* filepath, or NULL */\n+    wchar_t *name,          /* filename associated with rootpath */\n+#else\n     char *rootpath,         /* filepath, or NULL */\n     char *name,             /* filename associated with rootpath */\n+#endif\n     PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */\n     )\n {\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    wchar_t TempRootPath[MAX_PATH + 1];\n+#else\n     char TempRootPath[MAX_PATH + 1];\n+#endif\n     DWORD cchTempRootPath = 0;\n     BOOL bSuccess = TRUE;   /* assume success until told otherwise */\n@@ -273,5 +300,9 @@\n         DWORD i;\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        cchTempRootPath = lstrlenW(rootpath);\n+#else\n         cchTempRootPath = lstrlenA(rootpath);\n+#endif\n         if(cchTempRootPath > MAX_PATH) return FALSE;\n \n@@ -345,5 +376,9 @@\n \n     if(!g_VolumeCaps.bValid ||\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+       lstrcmpiW(g_VolumeCaps.RootPath, TempRootPath) != 0)\n+#else\n        lstrcmpiA(g_VolumeCaps.RootPath, TempRootPath) != 0)\n+#endif\n     {\n \n@@ -357,5 +392,9 @@\n         LeaveCriticalSection( &VolumeCapsLock );\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        bSuccess = GetVolumeInformationW(\n+#else\n         bSuccess = GetVolumeInformationA(\n+#endif\n             (TempRootPath[0] == '\\0') ? NULL : TempRootPath,\n             NULL, 0,\n@@ -371,5 +410,9 @@\n            VolumeCaps->bUsePrivileges)\n         {\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+            if(GetDriveTypeW( (TempRootPath[0] == '\\0') ? NULL : TempRootPath )\n+#else\n             if(GetDriveTypeA( (TempRootPath[0] == '\\0') ? NULL : TempRootPath )\n+#endif\n                == DRIVE_REMOTE)\n             {\n@@ -388,5 +431,9 @@\n         if(bSuccess) {\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+            lstrcpynW(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);\n+#else\n             lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);\n+#endif\n             g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;\n             g_VolumeCaps.bRemote = bRemote;\n@@ -413,5 +460,9 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+BOOL SecuritySet(wchar_t *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)\n+#else\n BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata)\n+#endif\n {\n     HANDLE hFile;\n@@ -491,5 +542,9 @@\n         dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    hFile = CreateFileW(\n+#else\n     hFile = CreateFileA(\n+#endif\n         resource,\n         dwDesiredAccess,\ndiff -ru2 unz60d10/win32/nt.h unz60d10_w32w/win32/nt.h\n--- unz60d10/win32/nt.h\tMon Jan 24 02:46:38 2005\n+++ unz60d10_w32w/win32/nt.h\tMon Feb 11 02:07:20 2008\n@@ -1,4 +1,4 @@\n /*\n-  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n+  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n \n   See the accompanying file LICENSE, version 2000-Apr-09 or later\n@@ -24,9 +24,18 @@\n     DWORD dwRemotePrivileges;   /* relevant only on remote volumes */\n     DWORD dwFileAttributes;\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    wchar_t RootPath[MAX_PATH+1];  /* path to network / filesystem */\n+#else\n     char RootPath[MAX_PATH+1];  /* path to network / filesystem */\n+#endif\n } VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+BOOL SecuritySet(wchar_t *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);\n+BOOL GetVolumeCaps(wchar_t *rootpath, wchar_t *name, PVOLUMECAPS VolumeCaps);\n+#else\n BOOL SecuritySet(char *resource, PVOLUMECAPS VolumeCaps, uch *securitydata);\n BOOL GetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);\n+#endif\n BOOL ValidateSecurity(uch *securitydata);\n \ndiff -ru2 unz60d10/win32/vc6/funzip.dsp unz60d10_w32w/win32/vc6/funzip.dsp\n--- unz60d10/win32/vc6/funzip.dsp\tMon Feb 11 02:55:18 2008\n+++ unz60d10_w32w/win32/vc6/funzip.dsp\tMon Feb 11 02:55:38 2008\n@@ -45,5 +45,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -69,5 +69,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\n@@ -93,5 +93,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"FUNZIP\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -117,5 +117,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"FUNZIP\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"FUNZIP\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\ndiff -ru2 unz60d10/win32/vc6/unzip.dsp unz60d10_w32w/win32/vc6/unzip.dsp\n--- unz60d10/win32/vc6/unzip.dsp\tSat Mar 24 19:51:24 2007\n+++ unz60d10_w32w/win32/vc6/unzip.dsp\tMon Feb 11 02:52:48 2008\n@@ -45,5 +45,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -69,5 +69,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /FR /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\n@@ -93,5 +93,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -118,5 +118,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\ndiff -ru2 unz60d10/win32/vc6/unzipbz2.dsp unz60d10_w32w/win32/vc6/unzipbz2.dsp\n--- unz60d10/win32/vc6/unzipbz2.dsp\tSun Jan  6 19:14:44 2008\n+++ unz60d10_w32w/win32/vc6/unzipbz2.dsp\tMon Feb 11 02:52:48 2008\n@@ -45,5 +45,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -69,5 +69,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\n@@ -93,5 +93,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NDEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -118,5 +118,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"_DEBUG\" /D \"WIN32\" /D \"ASM_CRC\" /D \"USE_BZIP2\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\ndiff -ru2 unz60d10/win32/vc6/unzipsfx.dsp unz60d10_w32w/win32/vc6/unzipsfx.dsp\n--- unz60d10/win32/vc6/unzipsfx.dsp\tSun Jan  6 19:13:46 2008\n+++ unz60d10_w32w/win32/vc6/unzipsfx.dsp\tMon Feb 11 02:52:48 2008\n@@ -45,5 +45,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O1 /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O1 /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -69,5 +69,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\n@@ -93,5 +93,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"SFX\" /FD /c\n-# ADD CPP /nologo /W3 /GX /O1 /D \"NDEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\n+# ADD CPP /nologo /W3 /GX /O1 /D \"NDEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /c\n # ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n # ADD RSC /l 0x409 /d \"NDEBUG\"\n@@ -117,5 +117,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"SFX\" /FD /GZ /c\n-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\n+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"SFX\" /D \"ASM_CRC\" /D \"_CONSOLE\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /D \"_MBCS\" /FD /GZ /c\n # ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n # ADD RSC /l 0x409 /d \"_DEBUG\"\ndiff -ru2 unz60d10/win32/w32cfg.h unz60d10_w32w/win32/w32cfg.h\n--- unz60d10/win32/w32cfg.h\tThu Oct  4 02:05:42 2007\n+++ unz60d10_w32w/win32/w32cfg.h\tTue Jan  1 18:34:48 2008\n@@ -271,15 +271,38 @@\n #define STR_TO_ISO\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   wchar_t *utf8_to_wchar_string OF((char *));\n+   wchar_t *local_to_wchar_string OF((char *));\n+   int has_win32_wide();\n+#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+\n /* Static variables that we have to add to Uz_Globs: */\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n #define SYSTEM_SPECIFIC_GLOBALS \\\n     int created_dir, renamed_fullpath, fnlen;\\\n     unsigned nLabelDrive;\\\n     char lastRootPath[4];\\\n+    wchar_t lastRootPathw[4];\\\n     int lastVolOldFAT, lastVolLocTim;\\\n     char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\\\n+    wchar_t *rootpathw, *buildpathHPFSw, *buildpathFATw, *endHPFSw, *endFATw;\\\n     ZCONST char *wildname;\\\n+    ZCONST wchar_t *wildnamew;\\\n     char *dirname, matchname[FILNAMSIZ];\\\n+    wchar_t *dirnamew, matchnamew[FILNAMSIZ];\\\n     int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n     zvoid *wild_dir;\n+#else /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+#define SYSTEM_SPECIFIC_GLOBALS \\\n+    int created_dir, renamed_fullpath, fnlen;\\\n+    unsigned nLabelDrive;\\\n+    char lastRootPath[4];\\\n+    int lastVolOldFAT, lastVolLocTim;\\\n+    char *rootpath, *buildpathHPFS, *buildpathFAT, *endHPFS, *endFAT;\\\n+    ZCONST char *wildname;\\\n+    char *dirname, matchname[FILNAMSIZ];\\\n+    int rootlen, have_dirname, dirnamelen, notfirstcall;\\\n+    zvoid *wild_dir;\n+#endif /* ?(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n \n /* created_dir, renamed_fullpath, fnlen, and nLabelDrive are used by   */\n@@ -342,4 +365,13 @@\n #  define SSTAT(path, pbuf) zstat_win32(__W32STAT_G__ path, pbuf)\n #endif\n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+# ifdef WILD_STAT_BUG\n+#  define SSTATW(pathw, pbuf) (iswildw(pathw) || zstat_win32w(__W32STAT_G__ pathw, pbuf))\n+# else\n+#  define SSTATW(pathw, pbuf) zstat_win32w(__W32STAT_G__ pathw, pbuf)\n+# endif\n+#endif /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+\n \n #ifdef __WATCOMC__\ndiff -ru2 unz60d10/win32/win32.c unz60d10_w32w/win32/win32.c\n--- unz60d10/win32/win32.c\tTue Jan  1 21:26:22 2008\n+++ unz60d10_w32w/win32/win32.c\tTue Jan  1 21:26:24 2008\n@@ -75,4 +75,12 @@\n #endif\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+# if (defined(__EMX__) || defined(__CYGWIN__))\n+#  define MKDIRW(pathw,mode)   _wmkdir(pathw,mode)\n+# else\n+#  define MKDIRW(pathw,mode)   _wmkdir(pathw)\n+# endif\n+#endif\n+\n #ifdef HAVE_WORKING_DIRENT_H\n #  undef HAVE_WORKING_DIRENT_H\n@@ -124,4 +132,22 @@\n } NTdirattr;\n #define NtAtt(d)  ((NTdirattr *)d)    /* typecast shortcut */\n+\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+ typedef struct NTdirattrw {     /* struct for holding unix style directory */\n+    struct NTdirattrw *next;     /*  info until can be sorted and set at end */\n+    wchar_t *fnw;                /* filename of directory */\n+    FILETIME Modft;    /* File time type defined in NT, `last modified' time */\n+    FILETIME Accft;    /* NT file time type, `last access' time */\n+    FILETIME Creft;    /* NT file time type, `file creation' time */\n+    int gotTime;\n+    unsigned perms;             /* same as min_info.file_attr */\n+# ifdef NTSD_EAS\n+    unsigned SDlen;             /* length of SD data in buf */\n+# endif\n+    wchar_t buf[1];                /* buffer stub for directory SD and name */\n+ } NTdirattrw;\n+# define NtAttw(dw)  ((NTdirattrw *)dw)    /* typecast shortcut */\n+# endif\n+\n #endif /* SET_DIR_ATTRIB */\n \n@@ -129,10 +155,15 @@\n /* Function prototypes */\n #ifdef NTSD_EAS\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   static int  SetSD(__GPRO__ wchar_t *path, unsigned fperms,\n+                     uch *eb_ptr, unsigned eb_len);\n+# else\n    static int  SetSD(__GPRO__ char *path, unsigned fperms,\n                      uch *eb_ptr, unsigned eb_len);\n+# endif\n    static int  FindSDExtraField(__GPRO__\n                                 uch *ef_ptr, unsigned ef_len,\n                                 uch **p_ebSD_ptr, unsigned *p_ebSD_len);\n-#endif\n+#endif /* NTSD_EAS */\n \n #ifndef NO_W32TIMES_IZFIX\n@@ -147,13 +178,27 @@\n #endif\n static int FStampIsLocTime(__GPRO__ const char *path);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   static int FStampIsLocTimeW(__GPRO__ const wchar_t *pathw);\n+#endif\n \n \n static int  getNTfiletime   (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,\n                              FILETIME *pCreFT);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int  getNTfiletimeW  (__GPRO__ FILETIME *pModFT, FILETIME *pAccFT,\n+                             FILETIME *pCreFT);\n+#endif\n static int  isfloppy        (int nDrive);\n static int  NTQueryVolInfo  (__GPRO__ const char *name);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+   static int  NTQueryVolInfoW  (__GPRO__ const wchar_t *namew);\n+#endif\n static int  IsVolumeOldFAT  (__GPRO__ const char *name);\n static void maskDOSdevice   (__GPRO__ char *pathcomp);\n static void map2fat         (char *pathcomp, char **pEndFAT);\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+  static void maskDOSdevicew (__GPRO__ wchar_t *pathcompw);\n+  static void map2fatw      (wchar_t *pathcompw, wchar_t **pEndFATw);\n+#endif\n \n \n@@ -309,7 +354,13 @@\n /**********************/\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int SetSD(__G__ path, fperms, eb_ptr, eb_len)\n+    __GDEF\n+    wchar_t *path;\n+#else\n static int SetSD(__G__ path, fperms, eb_ptr, eb_len)\n     __GDEF\n     char *path;\n+#endif\n     unsigned fperms;\n     uch *eb_ptr;\n@@ -918,4 +969,12 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int FStampIsLocTimeW(__GPRO__ const wchar_t *pathw)\n+{\n+    return (NTQueryVolInfoW(__G__ pathw) ? G.lastVolLocTim : FALSE);\n+}\n+#endif\n+\n+\n \n #ifndef NO_W32TIMES_IZFIX\n@@ -991,4 +1050,63 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+  static int getNTfiletimeW(__G__ pModFT, pAccFT, pCreFT)\n+      __GDEF\n+      FILETIME *pModFT;\n+      FILETIME *pAccFT;\n+      FILETIME *pCreFT;\n+  {\n+# ifdef USE_EF_UT_TIME\n+      unsigned eb_izux_flg;\n+      iztimes z_utime;   /* struct for Unix-style actime & modtime, + creatime */\n+# endif\n+      int fs_uses_loctime = FStampIsLocTimeW(__G__ G.unipath_widefilename);\n+\n+      /* Copy and/or convert time and date variables, if necessary;\n+       * return a flag indicating which time stamps are available. */\n+# ifdef USE_EF_UT_TIME\n+      if (G.extra_field &&\n+#  ifdef IZ_CHECK_TZ\n+          G.tz_is_valid &&\n+#  endif\n+          ((eb_izux_flg = ef_scan_for_izux(G.extra_field,\n+            G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime,\n+            &z_utime, NULL)) & EB_UT_FL_MTIME))\n+      {\n+          TTrace((stderr, \"getNTfiletime:  Unix e.f. modif. time = %lu\\n\",\n+            z_utime.mtime));\n+          UTIME_2_IZFILETIME(z_utime.mtime, pModFT)\n+          if (eb_izux_flg & EB_UT_FL_ATIME) {\n+              UTIME_2_IZFILETIME(z_utime.atime, pAccFT)\n+          }\n+          if (eb_izux_flg & EB_UT_FL_CTIME) {\n+              UTIME_2_IZFILETIME(z_utime.ctime, pCreFT)\n+          }\n+          return (int)eb_izux_flg;\n+      }\n+# endif /* USE_EF_UT_TIME */\n+# ifndef NO_W32TIMES_IZFIX\n+      if (!fs_uses_loctime) {\n+          time_t ux_modtime;\n+\n+          ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n+          utime2NtfsFileTime(ux_modtime, pModFT);\n+      } else\n+#endif /* NO_W32TIMES_IZFIX */\n+      {\n+          FILETIME lft;\n+\n+          DosDateTimeToFileTime((WORD)(G.lrec.last_mod_dos_datetime >> 16),\n+                                (WORD)(G.lrec.last_mod_dos_datetime & 0xFFFFL),\n+                                &lft);\n+          LocalFileTimeToFileTime(&lft, pModFT);\n+      }\n+      *pAccFT = *pModFT;\n+      return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n+\n+  } /* end function getNTfiletime() */\n+#endif /* (UNICODE_SUPPORT && WIN32_WIDE) */\n+\n+\n \n \n@@ -1059,66 +1177,72 @@\n     unsigned ebSDlen;\n #endif\n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    if (!G.has_win32_wide) {\n+#endif\n #ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n-    char *ansi_name = (char *)alloca(strlen(G.filename) + 1);\n+      char *ansi_name = (char *)alloca(strlen(G.filename) + 1);\n \n-    INTERN_TO_ISO(G.filename, ansi_name);\n-#   define Ansi_Fname  ansi_name\n+      INTERN_TO_ISO(G.filename, ansi_name);\n+#     define Ansi_Fname  ansi_name\n #else\n-#   define Ansi_Fname  G.filename\n+#     define Ansi_Fname  G.filename\n #endif\n \n #ifndef __RSXNT__\n-    if (IsWinNT()) {\n+# if !(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE))\n+      if (IsWinNT()) {\n         /* Truncate the file to the current position.\n          * This is needed to remove excess allocation in case the\n          * extraction has failed or stopped prematurely. */\n         SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));\n-    }\n+      }\n+# endif /* !(defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n #endif\n \n-    /* Close the file and then re-open it using the Win32\n-     * CreateFile call, so that the file can be created\n-     * with GENERIC_WRITE access, otherwise the SetFileTime\n-     * call will fail. */\n-    fclose(G.outfile);\n-\n-    /* don't set the time stamp and attributes on standard output */\n-    if (uO.cflag)\n-        return;\n-\n-    /* skip restoring time stamps on user's request */\n-    if (uO.D_flag <= 1) {\n-        gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);\n-\n-        /* open a handle to the file before processing extra fields;\n-           we do this in case new security on file prevents us from updating\n-           time stamps */\n-        hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n-             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n-    } else {\n-        gotTime = 0;\n-    }\n-\n-    /* sfield@microsoft.com: set attributes before time in case we decide to\n-       support other filetime members later.  This also allows us to apply\n-       attributes before the security is changed, which may prevent this\n-       from succeeding otherwise.  Also, since most files don't have\n-       any interesting attributes, only change them if something other than\n-       FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well\n-       as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the\n-       file anyway, when it's created new. */\n-    if ((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {\n-        if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))\n-            Info(slide, 1, ((char *)slide,\n-              \"\\nwarning (%d): could not set file attributes\\n\",\n-              (int)GetLastError()));\n-    }\n+      /* Close the file and then re-open it using the Win32\n+       * CreateFile call, so that the file can be created\n+       * with GENERIC_WRITE access, otherwise the SetFileTime\n+       * call will fail. */\n+      fclose(G.outfile);\n+\n+      /* don't set the time stamp and attributes on standard output */\n+      if (uO.cflag)\n+          return;\n+\n+      gotTime = getNTfiletime(__G__ &Modft, &Accft, &Creft);\n+\n+      /* open a handle to the file before processing extra fields;\n+         we do this in case new security on file prevents us from updating\n+         time stamps */\n+      hFile = CreateFileA(Ansi_Fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n+           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n+\n+      /* sfield@microsoft.com: set attributes before time in case we decide to\n+         support other filetime members later.  This also allows us to apply\n+         attributes before the security is changed, which may prevent this\n+         from succeeding otherwise.  Also, since most files don't have\n+         any interesting attributes, only change them if something other than\n+         FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well\n+         as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the\n+         file anyway, when it's created new. */\n+      if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {\n+          if (!SetFileAttributesA(Ansi_Fname, G.pInfo->file_attr & 0x7F))\n+              Info(slide, 1, ((char *)slide,\n+                \"\\nwarning (%d): could not set file attributes\\n\",\n+                (int)GetLastError()));\n+      }\n \n #ifdef NTSD_EAS\n-    /* set NTFS SD extra fields */\n-    if (G.extra_field &&    /* zipfile extra field may have extended attribs */\n-        FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n-                         &ebSDptr, &ebSDlen))\n-    {\n+      /* set NTFS SD extra fields */\n+      if (G.extra_field &&    /* zipfile extra field may have extended attribs */\n+          FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n+                           &ebSDptr, &ebSDlen))\n+      {\n+# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+        /* no win32_wide implies \"no NT SD support\", so FindSDExtraField\n+         * will never return \"success\".\n+         */\n+# else /* (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n         int err = SetSD(__G__ Ansi_Fname, G.pInfo->file_attr,\n                         ebSDptr, ebSDlen);\n@@ -1131,9 +1255,10 @@\n               ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? \"\\n\":\"\"));\n         }\n-    }\n+# endif /* ? (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n+      }\n #endif /* NTSD_EAS */\n \n-    /* skip restoring time stamps on user's request */\n-    if (uO.D_flag <= 1) {\n+      /* skip restoring time stamps on user's request */\n+      if (uO.D_flag <= 1) {\n         if ( hFile == INVALID_HANDLE_VALUE )\n             Info(slide, 1, ((char *)slide,\n@@ -1152,10 +1277,101 @@\n             CloseHandle(hFile);\n         }\n-    }\n+      }\n \n-    return;\n+      return;\n \n #undef Ansi_Fname\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    } else {\n+      /* wide version */\n+\n+#ifndef __RSXNT__\n+      if (IsWinNT()) {\n+          /* Truncate the file to the current position.\n+           * This is needed to remove excess allocation in case the\n+           * extraction has failed or stopped prematurely. */\n+          SetEndOfFile((HANDLE)_get_osfhandle(fileno(G.outfile)));\n+      }\n+#endif\n+\n+      /* Close the file and then re-open it using the Win32\n+       * CreateFile call, so that the file can be created\n+       * with GENERIC_WRITE access, otherwise the SetFileTime\n+       * call will fail. */\n+      fclose(G.outfile);\n+\n+      /* don't set the time stamp and attributes on standard output */\n+      if (uO.cflag)\n+          return;\n+\n+      gotTime = getNTfiletimeW(__G__ &Modft, &Accft, &Creft);\n+\n+      /* open a handle to the file before processing extra fields;\n+         we do this in case new security on file prevents us from updating\n+         time stamps */\n+      hFile = CreateFileW(G.unipath_widefilename,\n+           GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n+           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n+\n+      /* sfield@microsoft.com: set attributes before time in case we decide to\n+         support other filetime members later.  This also allows us to apply\n+         attributes before the security is changed, which may prevent this\n+         from succeeding otherwise.  Also, since most files don't have\n+         any interesting attributes, only change them if something other than\n+         FILE_ATTRIBUTE_ARCHIVE appears in the attributes.  This works well\n+         as an optimization because FILE_ATTRIBUTE_ARCHIVE gets applied to the\n+         file anyway, when it's created new. */\n+      if((G.pInfo->file_attr & 0x7F) & ~FILE_ATTRIBUTE_ARCHIVE) {\n+          if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))\n+              Info(slide, 1, ((char *)slide,\n+                \"\\nwarning (%d): could not set file attributes\\n\",\n+                (int)GetLastError()));\n+      }\n+\n+#ifdef NTSD_EAS\n+      /* set NTFS SD extra fields */\n+      if (G.extra_field &&    /* zipfile extra field may have extended attribs */\n+          FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n+                           &ebSDptr, &ebSDlen))\n+      {\n+          int err = SetSD(__G__ G.unipath_widefilename, G.pInfo->file_attr,\n+                          ebSDptr, ebSDlen);\n+\n+          if (err == IZ_EF_TRUNC) {\n+              if (uO.qflag)\n+                  Info(slide, 1, ((char *)slide, \"%-22s \",\n+                    FnFilter1(G.filename)));\n+              Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),\n+                ebSDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), uO.qflag? \"\\n\":\"\"));\n+          }\n+      }\n+#endif /* NTSD_EAS */\n+\n+      /* skip restoring time stamps on user's request */\n+      if (uO.D_flag <= 1) {\n+        if ( hFile == INVALID_HANDLE_VALUE )\n+            Info(slide, 1, ((char *)slide,\n+              \"\\nCreateFile() error %d when trying set file time\\n\",\n+              (int)GetLastError()));\n+        else {\n+            if (gotTime) {\n+                FILETIME *pModft = (gotTime & EB_UT_FL_MTIME) ? &Modft : NULL;\n+                FILETIME *pAccft = (gotTime & EB_UT_FL_ATIME) ? &Accft : NULL;\n+                FILETIME *pCreft = (gotTime & EB_UT_FL_CTIME) ? &Creft : NULL;\n+\n+                if (!SetFileTime(hFile, pCreft, pAccft, pModft))\n+                    Info(slide, 0, ((char *)slide,\n+                      \"\\nSetFileTime failed: %d\\n\", (int)GetLastError()));\n+            }\n+            CloseHandle(hFile);\n+        }\n+      }\n+\n+      return;\n+\n+    }\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n } /* end function close_outfile() */\n \n@@ -1225,8 +1441,76 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int defer_dir_attribsw(__G__ pdw)\n+    __GDEF\n+    direntryw **pdw;\n+{\n+    NTdirattrw *d_entryw;\n+#ifdef NTSD_EAS\n+    uch *ebSDptr;\n+    unsigned ebSDlen;\n+#endif\n+\n+    /* Win9x does not support setting directory time stamps. */\n+    if (!IsWinNT()) {\n+        *pdw = (direntryw *)NULL;\n+        return PK_OK;\n+    }\n+\n+#ifdef NTSD_EAS\n+    /* set extended attributes from extra fields */\n+    if (G.extra_field &&  /* zipfile e.f. may have extended attribs */\n+        FindSDExtraField(__G__ G.extra_field, G.lrec.extra_field_length,\n+                         &ebSDptr, &ebSDlen)) {\n+        /* ebSDlen contains the payload size of the e.f. block, but\n+           we store it including the e.b. header. */\n+        ebSDlen += EB_HEADSIZE;\n+    } else {\n+        /* no NTSD e.f. block -> no space needed to allocate */\n+        ebSDlen = 0;\n+    }\n+#endif /* NTSD_EAS */\n+\n+    d_entryw = (NTdirattrw *)malloc(sizeof(NTdirattrw)\n+#ifdef NTSD_EAS\n+                                  + ebSDlen\n+#endif\n+                                  + (wcslen(G.unipath_widefilename)\n+                                     * sizeof(wchar_t)));\n+    *pdw = (direntryw *)d_entryw;\n+    if (d_entryw == (NTdirattrw *)NULL) {\n+        return PK_MEM;\n+    }\n+#ifdef NTSD_EAS\n+    if (ebSDlen > 0)\n+        memcpy(d_entryw->buf, ebSDptr, ebSDlen);\n+    d_entryw->SDlen = ebSDlen;\n+    d_entryw->fnw = d_entryw->buf + ebSDlen;\n+#else\n+    d_entryw->fnw = d_entryw->buf;\n+#endif\n+\n+    wcscpy(d_entryw->fnw, G.unipath_widefilename);\n+\n+    d_entryw->perms = G.pInfo->file_attr;\n+\n+    d_entryw->gotTime = (uO.D_flag <= 0\n+                         ? getNTfiletimeW(__G__ &(d_entryw->Modft),\n+                                          &(d_entryw->Accft),\n+                                          &(d_entryw->Creft))\n+                         : 0);\n+    return PK_OK;\n+} /* end function defer_dir_attribsw() */\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n+\n int set_direc_attribs(__G__ d)\n     __GDEF\n     direntry *d;\n {\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+    /* Win9x does not support setting directory time stamps. */\n+    return PK_OK;\n+#else /* ! (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n     int errval;\n     HANDLE hFile = INVALID_HANDLE_VALUE;        /* File handle defined in NT */\n@@ -1320,6 +1604,107 @@\n \n     return errval;\n+#endif /* ? (defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)) */\n } /* end function set_direc_attribs() */\n \n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+int set_direc_attribsw(__G__ dw)\n+    __GDEF\n+    direntryw *dw;\n+{\n+    int errval;\n+    HANDLE hFile = INVALID_HANDLE_VALUE;        /* File handle defined in NT */\n+\n+    /* Win9x does not support setting directory time stamps. */\n+    if (!IsWinNT())\n+        return PK_OK;\n+\n+    errval = PK_OK;\n+\n+    /* Skip restoring directory time stamps on user' request. */\n+    if (uO.D_flag <= 0) {\n+        /* Open a handle to the directory before processing extra fields;\n+           we do this in case new security on file prevents us from updating\n+           time stamps.\n+           Although the WIN32 documentation recommends to use GENERIC_WRITE\n+           access flag to create the handle for SetFileTime(), this is too\n+           demanding for directories with the \"read-only\" attribute bit set.\n+           So we use the more specific flag FILE_WRITE_ATTRIBUTES here to\n+           request the minimum required access rights. (This problem is a\n+           Windows bug that has been silently fixed in Windows XP SP2.) */\n+        hFile = CreateFileW(dw->fnw, FILE_WRITE_ATTRIBUTES,\n+                            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,\n+                            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\n+    }\n+\n+#ifdef NTSD_EAS\n+    if (NtAtt(dw)->SDlen > 0) {\n+        int err;\n+\n+        if (QCOND2) {\n+            char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);\n+            Info(slide, 1, ((char *)slide, \" set attrib: %-22s  \",\n+              FnFilter1(fn)));\n+            free(fn);\n+        }\n+\n+        /* set NTFS SD extra fields */\n+        err = SetSD(__G__ dw->fnw, NtAtt(dw)->perms,\n+                        NtAtt(dw)->buf, NtAtt(dw)->SDlen - EB_HEADSIZE);\n+        if (err == IZ_EF_TRUNC) {\n+            if (!QCOND2) {\n+                char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);\n+                Info(slide, 1, ((char *)slide, \"%-22s  \",\n+                  FnFilter1(fn)));\n+                free(fn);\n+            }\n+            Info(slide, 1, ((char *)slide, LoadFarString(TruncNTSD),\n+              NtAtt(dw)->SDlen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), \"\\n\"));\n+        } else if (QCOND2) {\n+            Info(slide, 0, ((char *)slide, \"\\n\"));\n+        }\n+        if (errval < err)\n+            errval = err;\n+    }\n+#endif /* NTSD_EAS */\n+\n+    /* Skip restoring directory time stamps on user' request. */\n+    if (uO.D_flag <= 0) {\n+        if (hFile == INVALID_HANDLE_VALUE) {\n+            char *fn = wchar_to_local_string(dw->fnw, G.unicode_escape_all);\n+            Info(slide, 1, ((char *)slide,\n+              \"warning: CreateFile() error %d (set file times for %s)\\n\",\n+              (int)GetLastError(), FnFilter1(fn)));\n+            free(fn);\n+            if (!errval)\n+                errval = PK_WARN;\n+        } else {\n+            if (NtAtt(dw)->gotTime) {\n+                FILETIME *pModft = (NtAtt(dw)->gotTime & EB_UT_FL_MTIME)\n+                                  ? &(NtAtt(dw)->Modft) : NULL;\n+                FILETIME *pAccft = (NtAtt(dw)->gotTime & EB_UT_FL_ATIME)\n+                                  ? &(NtAtt(dw)->Accft) : NULL;\n+                FILETIME *pCreft = (NtAtt(dw)->gotTime & EB_UT_FL_CTIME)\n+                                  ? &(NtAtt(dw)->Creft) : NULL;\n+\n+                if (!SetFileTime(hFile, pCreft, pAccft, pModft)) {\n+                    char *fn = wchar_to_local_string(dw->fnw,\n+                                                     G.unicode_escape_all);\n+                    Info(slide, 0, ((char *)slide,\n+                      \"warning:  SetFileTime() for %s error %d\\n\",\n+                      FnFilter1(fn), (int)GetLastError()));\n+                    free(fn);\n+                    if (!errval)\n+                        errval = PK_WARN;\n+                }\n+            }\n+            CloseHandle(hFile);\n+        }\n+    }\n+\n+    return errval;\n+} /* end function set_direc_attribsw() */\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n #endif /* SET_DIR_ATTRIB */\n \n@@ -1419,5 +1804,5 @@\n #endif\n \n-    if ((!strncmp(name, \"//\", 2) || !strncmp(name, \"\\\\\\\\\", 2)) &&\n+    if ((!strncmp(name, \"//\", 2) || !strncmp(name,\"\\\\\\\\\", 2)) &&\n         (name[2] != '\\0' && name[2] != '/' && name[2] != '\\\\')) {\n         /* GetFullPathname() and GetVolumeInformation() do not work\n@@ -1467,4 +1852,63 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int NTQueryVolInfoW(__GPRO__ const wchar_t *namew)\n+{\n+ /* static char lastRootPath[4] = \"\"; */\n+ /* static int lastVolOldFAT; */\n+ /* static int lastVolLocTim; */\n+    wchar_t *tmp0w;\n+    wchar_t tmp1w[MAX_PATH], tmp2w[MAX_PATH];\n+    DWORD volSerNo, maxCompLen, fileSysFlags;\n+\n+    if ((!wcsncmp(namew, L\"//\", 2) || !wcsncmp(namew, L\"\\\\\\\\\", 2)) &&\n+        (namew[2] != '\\0' && namew[2] != '/' && namew[2] != '\\\\')) {\n+        /* GetFullPathname() and GetVolumeInformation() do not work\n+         * on UNC names. For now, we return \"error\".\n+         * **FIXME**: check if UNC name is mapped to a drive letter\n+         *            and use mapped drive for volume info query.\n+         */\n+        return FALSE;\n+    }\n+    if (iswalpha(namew[0]) && (namew[1] == ':'))\n+        tmp0w = (wchar_t *)namew;\n+    else\n+    {\n+        if (!GetFullPathNameW(namew, MAX_PATH, tmp1w, &tmp0w))\n+            return FALSE;\n+        tmp0w = &tmp1w[0];\n+    }\n+    if (wcsncmp(G.lastRootPathw, tmp0w, 2) != 0) {\n+        /* For speed, we skip repeated queries for the same device */\n+        wcsncpy(G.lastRootPathw, tmp0w, 2); /* Build the root path name, */\n+        G.lastRootPathw[2] = '/';           /* e.g. \"A:/\"                */\n+        G.lastRootPathw[3] = '\\0';\n+\n+        if (!GetVolumeInformationW(G.lastRootPathw,\n+              tmp1w, (DWORD)MAX_PATH,\n+              &volSerNo, &maxCompLen, &fileSysFlags,\n+              tmp2w, (DWORD)MAX_PATH)) {\n+            G.lastRootPathw[0] = '\\0';\n+            return FALSE;\n+        }\n+\n+        /*  LFNs are available if the component length is > 12 */\n+        G.lastVolOldFAT = (maxCompLen <= 12);\n+/*      G.lastVolOldFAT = !strncmp(strupr(tmp2), \"FAT\", 3);   old version */\n+\n+        /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in\n+         * local time!\n+         */\n+        G.lastVolLocTim = !wcsncmp(_wcsupr(tmp2w), L\"VFAT\", 4) ||\n+                          !wcsncmp(tmp2w, L\"HPFS\", 4) ||\n+                          !wcsncmp(tmp2w, L\"FAT\", 3);\n+    }\n+\n+    return TRUE;\n+\n+} /* end function NTQueryVolInfoW() */\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n+\n \n \n@@ -1478,4 +1922,11 @@\n }\n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+static int IsVolumeOldFATw(__GPRO__ const wchar_t *namew)\n+{\n+    return (NTQueryVolInfoW(__G__ namew) ? G.lastVolOldFAT : FALSE);\n+}\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n \n \n@@ -1931,13 +2382,253 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n \n+/* Win32 wide version */\n \n-/****************************/\n-/* Function maskDOSdevice() */\n-/****************************/\n-\n-static void maskDOSdevice(__G__ pathcomp)\n+int mapnamew(__G__ renamed)\n     __GDEF\n-    char *pathcomp;\n+    int renamed;\n+/*\n+ * returns:\n+ *  MPN_OK          - no problem detected\n+ *  MPN_INF_TRUNC   - caution (truncated filename)\n+ *  MPN_INF_SKIP    - info \"skip entry\" (dir doesn't exist)\n+ *  MPN_ERR_SKIP    - error -> skip entry\n+ *  MPN_ERR_TOOLONG - error -> path is too long\n+ *  MPN_NOMEM       - error (memory allocation failed) -> skip entry\n+ *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]\n+ */\n+{\n+    wchar_t pathcompw[FILNAMSIZ];   /* path-component buffer */\n+    wchar_t *ppw, *cpw=NULL;         /* character pointers */\n+    wchar_t *lastsemiw = NULL;      /* pointer to last semi-colon in pathcomp */\n+    int killed_ddot = FALSE;    /* is set when skipping \"../\" pathcomp */\n+    int error;\n+    register wchar_t workchw;   /* hold the character being tested */\n+\n+\n+/*---------------------------------------------------------------------------\n+    Initialize various pointers and counters and stuff.\n+  ---------------------------------------------------------------------------*/\n+\n+    /* can create path as long as not just freshening, or if user told us */\n+    G.create_dirs = (!uO.fflag || renamed);\n+\n+    G.created_dir = FALSE;      /* not yet */\n+    G.renamed_fullpath = FALSE;\n+    G.fnlen = wcslen(G.unipath_widefilename);\n+\n+    if (renamed) {\n+        cpw = G.unipath_widefilename;    /* point to beginning of renamed name... */\n+        if (*cpw) do {\n+            if (*cpw == '\\\\')    /* convert backslashes to forward */\n+                *cpw = '/';\n+        } while (*(++cpw));\n+        cpw = G.unipath_widefilename;\n+        /* use temporary rootpath if user gave full pathname */\n+        if (G.unipath_widefilename[0] == '/') {\n+            G.renamed_fullpath = TRUE;\n+            pathcompw[0] = '/';  /* copy the '/' and terminate */\n+            pathcompw[1] = '\\0';\n+            ++cpw;\n+        } else if (iswalpha(G.unipath_widefilename[0]) && G.unipath_widefilename[1] == ':') {\n+            G.renamed_fullpath = TRUE;\n+            ppw = pathcompw;\n+            *ppw++ = *cpw++;      /* copy the \"d:\" (+ '/', possibly) */\n+            *ppw++ = *cpw++;\n+            if (*cpw == '/')\n+                *ppw++ = *cpw++;  /* otherwise add \"./\"? */\n+            *ppw = '\\0';\n+        }\n+    }\n+\n+    /* pathcomp is ignored unless renamed_fullpath is TRUE: */\n+    if ((error = checkdirw(__G__ pathcompw, INIT)) != 0)    /* init path buffer */\n+        return error;           /* ...unless no mem or vol label on hard disk */\n+\n+    *pathcompw = '\\0';           /* initialize translation buffer */\n+    ppw = pathcompw;              /* point to translation buffer */\n+    if (!renamed) {             /* cp already set if renamed */\n+        if (uO.jflag)           /* junking directories */\n+            cpw = wcschr(G.unipath_widefilename, '/');\n+        if (cpw == NULL)         /* no '/' or not junking dirs */\n+            cpw = G.unipath_widefilename;    /* point to internal zipfile-member pathname */\n+        else\n+            ++cpw;               /* point to start of last component of path */\n+    }\n+\n+/*---------------------------------------------------------------------------\n+    Begin main loop through characters in filename.\n+  ---------------------------------------------------------------------------*/\n+\n+    for (; (workchw = *cpw) != 0; cpw++) {\n+\n+        switch (workchw) {\n+            case '/':             /* can assume -j flag not given */\n+                *ppw = '\\0';\n+                maskDOSdevicew(__G__ pathcompw);\n+                if (wcscmp(pathcompw, L\".\") == 0) {\n+                    /* don't botherw appending \"./\" to the path */\n+                    *pathcompw = '\\0';\n+                } else if (!uO.ddotflag && wcscmp(pathcompw, L\"..\") == 0) {\n+                    /* \"../\" dir traversal detected, skip over it */\n+                    *pathcompw = '\\0';\n+                    killed_ddot = TRUE;     /* set \"show message\" flag */\n+                }\n+                /* when path component is not empty, append it now */\n+                if (*pathcompw != '\\0' &&\n+                    ((error = checkdirw(__G__ pathcompw, APPEND_DIR))\n+                     & MPN_MASK) > MPN_INF_TRUNC)\n+                    return error;\n+                ppw = pathcompw;    /* reset conversion buffer for next piece */\n+                lastsemiw = (wchar_t *)NULL; /* leave direct. semi-colons alone */\n+                break;\n+\n+            case ':':             /* drive spec not stored, so no colon allowed */\n+            case '\\\\':            /* '\\\\' may come as normal filename char (not */\n+            case '<':             /*  dir sep char!) from unix-like file system */\n+            case '>':             /* no redirection symbols allowed either */\n+            case '|':             /* no pipe signs allowed */\n+            case '\"':             /* no double quotes allowed */\n+            case '?':             /* no wildcards allowed */\n+            case '*':\n+                *ppw++ = '_';      /* these rules apply equally to FAT and NTFS */\n+                break;\n+            case ';':             /* start of VMS version? */\n+                lastsemiw = ppw;    /* remove VMS version later... */\n+                *ppw++ = ';';      /*  but keep semicolon for now */\n+                break;\n+\n+\n+            case ' ':             /* keep spaces unless specifically */\n+                /* NT cannot create filenames with spaces on FAT volumes */\n+                if (uO.sflag || IsVolumeOldFATw(__G__ G.unipath_widefilename))\n+                    *ppw++ = '_';\n+                else\n+                    *ppw++ = ' ';\n+                break;\n+\n+            default:\n+                /* allow European characters in filenames: */\n+                if (iswprint(workchw) || workchw >= 127)\n+                    *ppw++ = workchw;\n+        } /* end switch */\n+\n+    } /* end while loop */\n+\n+    /* Show warning when stripping insecure \"parent dir\" path components */\n+    /* For now use standard path for output messages */\n+    if (killed_ddot && QCOND2) {\n+        Info(slide, 0, ((char *)slide,\n+          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n+          FnFilter1(G.filename)));\n+        if (!(error & ~MPN_MASK))\n+            error = (error & MPN_MASK) | PK_WARN;\n+    }\n+\n+/*---------------------------------------------------------------------------\n+    Report if directory was created (and no file to create:  filename ended\n+    in '/'), check name to be sure it exists, and combine path and name be-\n+    fore exiting.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (G.unipath_widefilename[wcslen(G.unipath_widefilename) - 1] == '/') {\n+        checkdirw(__G__ G.unipath_widefilename, GETPATH);\n+        if (G.created_dir) {\n+            if (QCOND2) {\n+                Info(slide, 0, ((char *)slide, \"   creating: %-22s\\n\",\n+                  FnFilter1(G.filename)));\n+            }\n+\n+            /* set file attributes:\n+               The default for newly created directories is \"DIR attribute\n+               flags set\", so there is no need to change attributes unless\n+               one of the DOS style attribute flags is set. The readonly\n+               attribute need not be masked, since it does not prevent\n+               modifications in the new directory. */\n+            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {\n+                if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))\n+                    Info(slide, 1, ((char *)slide,\n+                      \"\\nwarning (%d): could not set file attributes for %s\\n\",\n+                      (int)GetLastError(), FnFilter1(G.filename)));\n+            }\n+\n+            /* set dir time (note trailing '/') */\n+            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n+        } else if (IS_OVERWRT_ALL) {\n+            /* overwrite attributes of existing directory on user's request */\n+\n+            /* set file attributes: */\n+            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {\n+                if (!SetFileAttributesW(G.unipath_widefilename, G.pInfo->file_attr & 0x7F))\n+                    Info(slide, 1, ((char *)slide,\n+                      \"\\nwarning (%d): could not set file attributes for %s\\n\",\n+                      (int)GetLastError(), FnFilter1(G.filename)));\n+            }\n+        }\n+        /* dir existed already; don't look for data to extract */\n+        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n+    }\n+\n+    *ppw = '\\0';                   /* done with pathcomp:  terminate it */\n+\n+    /* if not saving them, remove VMS version numbers (appended \"###\") */\n+    if (!uO.V_flag && lastsemiw) {\n+        ppw = lastsemiw + 1;        /* semi-colon was kept:  expect #'s after */\n+        while (iswdigit(*ppw))\n+            ++ppw;\n+        if (*ppw == '\\0')          /* only digits between ';' and end:  nuke */\n+            *lastsemiw = '\\0';\n+    }\n+\n+    maskDOSdevicew(__G__ pathcompw);\n+\n+    if (*pathcompw == '\\0') {\n+        Info(slide, 1, ((char *)slide, \"mapname:  conversion of %s failed\\n\",\n+          FnFilter1(G.filename)));\n+        return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n+    }\n+\n+    checkdirw(__G__ pathcompw, APPEND_NAME);  /* returns 1 if truncated: care? */\n+    checkdirw(__G__ G.unipath_widefilename, GETPATH);\n+\n+    if (G.pInfo->vollabel) {    /* set the volume label now */\n+        char drive[4];\n+        wchar_t drivew[4];\n+\n+        /* Build a drive string, e.g. \"b:\" */\n+        drive[0] = (char)('a' + G.nLabelDrive - 1);\n+        drivew[0] = (wchar_t)('a' + G.nLabelDrive - 1);\n+        wcscpy(drivew + 1, L\":\\\\\");\n+        if (QCOND2)\n+            Info(slide, 0, ((char *)slide, \"labelling %s %-22s\\n\", drive,\n+              FnFilter1(G.filename)));\n+        if (!SetVolumeLabelW(drivew, G.unipath_widefilename)) {\n+            Info(slide, 1, ((char *)slide,\n+              \"mapname:  error setting volume label\\n\"));\n+            return (error & ~MPN_MASK) | MPN_ERR_SKIP;\n+        }\n+        /* success:  skip the \"extraction\" quietly */\n+        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n+    }\n+\n+    Trace((stderr, \"mapname returns with filename = [%s] (error = %d)\\n\\n\",\n+      FnFilter1(G.filename), error));\n+    return error;\n+\n+} /* end function mapnamew() */\n+\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n+\n+\n+\n+/****************************/\n+/* Function maskDOSdevice() */\n+/****************************/\n+\n+static void maskDOSdevice(__G__ pathcomp)\n+    __GDEF\n+    char *pathcomp;\n {\n /*---------------------------------------------------------------------------\n@@ -1981,4 +2672,40 @@\n \n \n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+\n+static void maskDOSdevicew(__G__ pathcompw)\n+    __GDEF\n+    wchar_t *pathcompw;\n+{\n+/*---------------------------------------------------------------------------\n+    Put an underscore in front of the file name if the file name is a\n+    DOS/WINDOWS device name like CON.*, AUX.*, PRN.*, etc. Trying to\n+    extract such a file would fail at best and wedge us at worst.\n+  ---------------------------------------------------------------------------*/\n+#if !defined(S_IFCHR) && defined(_S_IFCHR)\n+#  define S_IFCHR _S_IFCHR\n+#endif\n+#if !defined(S_ISCHR)\n+# if defined(_S_ISCHR)\n+#  define S_ISCHR(m) _S_ISCHR(m)\n+# elif defined(S_IFCHR)\n+#  define S_ISCHR(m) ((m) & S_IFCHR)\n+# endif\n+#endif\n+\n+    if (zstatw(pathcompw, &G.statbuf) == 0 && S_ISCHR(G.statbuf.st_mode)) {\n+        extent i;\n+\n+        /* pathcomp contains a name of a DOS character device (builtin or\n+         * installed device driver).\n+         * Prepend a '_' to allow creation of the item in the file system.\n+         */\n+        for (i = wcslen(pathcompw) + 1; i > 0; --i)\n+            pathcompw[i] = pathcompw[i - 1];\n+        pathcompw[0] = '_';\n+    }\n+} /* end function maskDOSdevicew() */\n+\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n \n \n@@ -2080,19 +2807,511 @@\n             *pEndFAT = pEnd;   /* filename is fine; point at terminating zero */\n \n-        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')\n-            last_dot[-1] = '_';                /* NO blank in front of '.'! */\n+        if ((last_dot - pBegin) > 0 && last_dot[-1] == ' ')\n+            last_dot[-1] = '_';                /* NO blank in front of '.'! */\n+    }\n+} /* end function map2fat() */\n+\n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+\n+static void map2fatw(pathcompw, pEndFATw)\n+    wchar_t *pathcompw, **pEndFATw;\n+{\n+    wchar_t *ppcw = pathcompw;       /* variable pointer to pathcomp */\n+    wchar_t *pEndw = *pEndFATw;      /* variable pointer to buildpathFAT */\n+    wchar_t *pBeginw = *pEndFATw;    /* constant pointer to start of this comp. */\n+    wchar_t *last_dotw = NULL;      /* last dot not converted to underscore */\n+    register wchar_t workchw;   /* hold the character being tested */\n+\n+\n+    /* Only need check those characters which are legal in NTFS but not\n+     * in FAT:  to get here, must already have passed through mapname.\n+     * Also must truncate path component to ensure 8.3 compliance.\n+     */\n+    while ((workchw = *ppcw++) != 0) {\n+        switch (workchw) {\n+            case '[':\n+            case ']':\n+            case '+':\n+            case ',':\n+            case ';':\n+            case '=':\n+                *pEndw++ = '_';      /* convert brackets to underscores */\n+                break;\n+\n+            case '.':\n+                if (pEndw == *pEndFATw) {   /* nothing appended yet... */\n+                    if (*ppcw == '\\0')     /* don't bother appending a */\n+                        break;            /*  \"./\" component to the path */\n+                    else if (*ppcw == '.' && ppcw[1] == '\\0') {   /* \"../\" */\n+                        *pEndw++ = '.';    /*  add first dot, */\n+                        *pEndw++ = '.';    /*  add second dot, and */\n+                        ++ppcw;            /*  skip over to pathcomp's end */\n+                    } else {              /* FAT doesn't allow null filename */\n+                        *pEndw++ = '_';    /*  bodies, so map .exrc -> _exrc */\n+                    }                     /*  (_.exr would keep max 3 chars) */\n+                } else {                  /* found dot within path component */\n+                    last_dotw = pEndw;      /*  point at last dot so far... */\n+                    *pEndw++ = '_';        /*  convert to underscore for now */\n+                }\n+                break;\n+\n+            default:\n+                *pEndw++ = workchw;\n+\n+        } /* end switch */\n+    } /* end while loop */\n+\n+    *pEndw = '\\0';                 /* terminate buildpathFAT */\n+\n+    /* NOTE:  keep in mind that pEnd points to the end of the path\n+     * component, and *pEndFAT still points to the *beginning* of it...\n+     * Also note that the algorithm does not try to get too fancy:\n+     * if there are no dots already, the name either gets truncated\n+     * at 8 characters or the last underscore is converted to a dot\n+     * (only if more characters are saved that way).  In no case is\n+     * a dot inserted between existing characters.\n+     */\n+    if (last_dotw == NULL) {       /* no dots:  check for underscores... */\n+        wchar_t *pluw = wcschr(pBeginw, '_');   /* pointer to last underscore */\n+\n+        if ((pluw != NULL) &&      /* found underscore: convert to dot? */\n+            (MIN(pluw - pBeginw, 8) + MIN(pEndw - pluw - 1, 3) > 8)) {\n+            last_dotw = pluw;       /* be lazy:  drop through to next if-blk */\n+        } else if ((pEndw - *pEndFATw) > 8) {\n+            /* no underscore; or converting underscore to dot would save less\n+               chars than leaving everything in the basename */\n+            *pEndFATw += 8;        /* truncate at 8 chars */\n+            **pEndFATw = '\\0';\n+        } else\n+            *pEndFATw = pEndw;      /* whole thing fits into 8 chars or less */\n+    }\n+\n+    if (last_dotw != NULL) {       /* one dot is OK: */\n+        *last_dotw = '.';          /* put it back in */\n+\n+        if ((last_dotw - pBeginw) > 8) {\n+            wchar_t *pw, *qw;\n+            int i;\n+\n+            pw = last_dotw;\n+            qw = last_dotw = pBeginw + 8;\n+            for (i = 0;  (i < 4) && *pw;  ++i)  /* too many chars in basename: */\n+                *qw++ = *pw++;                   /*  shift .ext left and trun- */\n+            *qw = '\\0';                         /*  cate/terminate it */\n+            *pEndFATw = qw;\n+        } else if ((pEndw - last_dotw) > 4) {    /* too many chars in extension */\n+            *pEndFATw = last_dotw + 4;\n+            **pEndFATw = '\\0';\n+        } else\n+            *pEndFATw = pEndw;   /* filename is fine; point at terminating zero */\n+\n+        if ((last_dotw - pBeginw) > 0 && last_dotw[-1] == ' ')\n+            last_dotw[-1] = '_';                /* NO blank in front of '.'! */\n+    }\n+} /* end function map2fatw() */\n+\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n+\n+\n+/***********************/       /* Borrowed from os2.c for UnZip 5.1.        */\n+/* Function checkdir() */       /* Difference: no EA stuff                   */\n+/***********************/       /*             HPFS stuff works on NTFS too  */\n+\n+int checkdir(__G__ pathcomp, flag)\n+    __GDEF\n+    char *pathcomp;\n+    int flag;\n+/*\n+ * returns:\n+ *  MPN_OK          - no problem detected\n+ *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n+ *  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n+ *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n+ *                    exists and is not a directory, but is supposed to be\n+ *  MPN_ERR_TOOLONG - path is too long\n+ *  MPN_NOMEM       - can't allocate memory for filename buffers\n+ */\n+{\n+ /* static int rootlen = 0;     */   /* length of rootpath */\n+ /* static char *rootpath;      */   /* user's \"extract-to\" directory */\n+ /* static char *buildpathHPFS; */   /* full path (so far) to extracted file, */\n+ /* static char *buildpathFAT;  */   /*  both HPFS/EA (main) and FAT versions */\n+ /* static char *endHPFS;       */   /* corresponding pointers to end of */\n+ /* static char *endFAT;        */   /*  buildpath ('\\0') */\n+\n+#   define FN_MASK   7\n+#   define FUNCTION  (flag & FN_MASK)\n+\n+\n+\n+/*---------------------------------------------------------------------------\n+    APPEND_DIR:  append the path component to the path being built and check\n+    for its existence.  If doesn't exist and we are creating directories, do\n+    so for this one; else signal success or error as appropriate.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (FUNCTION == APPEND_DIR) {\n+        char *p = pathcomp;\n+        int too_long = FALSE;\n+\n+        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n+        while ((*G.endHPFS = *p++) != '\\0')     /* copy to HPFS filename */\n+            ++G.endHPFS;\n+        if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n+            p = pathcomp;\n+            while ((*G.endFAT = *p++) != '\\0')  /* copy to FAT filename, too */\n+                ++G.endFAT;\n+        } else\n+            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */\n+\n+        /* GRR:  could do better check, see if overrunning buffer as we go:\n+         * check endHPFS-buildpathHPFS after each append, set warning variable\n+         * if within 20 of FILNAMSIZ; then if var set, do careful check when\n+         * appending.  Clear variable when begin new path. */\n+\n+        /* next check:  need to append '/', at least one-char name, '\\0' */\n+        if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)\n+            too_long = TRUE;                    /* check if extracting dir? */\n+#ifdef FIX_STAT_BUG\n+        /* Borland C++ 5.0 does not handle a call to stat() well if the\n+         * directory does not exist (it tends to crash in strange places.)\n+         * This is apparently a problem only when compiling for GUI rather\n+         * than console. The code below attempts to work around this problem.\n+         */\n+        if (access(G.buildpathFAT, 0) != 0) {\n+            if (!G.create_dirs) { /* told not to create (freshening) */\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* path doesn't exist:  nothing to do */\n+                return MPN_INF_SKIP;\n+            }\n+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */\n+                Info(slide, 1, ((char *)slide,\n+                  \"checkdir error:  path too long: %s\\n\",\n+                  FnFilter1(G.buildpathHPFS)));\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* no room for filenames:  fatal */\n+                return MPN_ERR_TOOLONG;\n+            }\n+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n+                Info(slide, 1, ((char *)slide,\n+                  \"checkdir error:  cannot create %s\\n\\\n+                 unable to process %s.\\n\",\n+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* path didn't exist, tried to create, failed */\n+                return MPN_ERR_SKIP;\n+            }\n+            G.created_dir = TRUE;\n+        }\n+#endif /* FIX_STAT_BUG */\n+        if (SSTAT(G.buildpathFAT, &G.statbuf))   /* path doesn't exist */\n+        {\n+            if (!G.create_dirs) { /* told not to create (freshening) */\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* path doesn't exist:  nothing to do */\n+                return MPN_INF_SKIP;\n+            }\n+            if (too_long) {   /* GRR:  should allow FAT extraction w/o EAs */\n+                Info(slide, 1, ((char *)slide,\n+                  \"checkdir error:  path too long: %s\\n\",\n+                  FnFilter1(G.buildpathHPFS)));\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* no room for filenames:  fatal */\n+                return MPN_ERR_TOOLONG;\n+            }\n+            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n+                Info(slide, 1, ((char *)slide,\n+                  \"checkdir error:  cannot create %s\\n\\\n+                 unable to process %s.\\n\",\n+                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                /* path didn't exist, tried to create, failed */\n+                return MPN_ERR_SKIP;\n+            }\n+            G.created_dir = TRUE;\n+        } else if (!S_ISDIR(G.statbuf.st_mode)) {\n+            Info(slide, 1, ((char *)slide,\n+              \"checkdir error:  %s exists but is not directory\\n   \\\n+              unable to process %s.\\n\",\n+              FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n+            free(G.buildpathHPFS);\n+            free(G.buildpathFAT);\n+            /* path existed but wasn't dir */\n+            return MPN_ERR_SKIP;\n+        }\n+        if (too_long) {\n+            Info(slide, 1, ((char *)slide,\n+              \"checkdir error:  path too long: %s\\n\",\n+               FnFilter1(G.buildpathHPFS)));\n+            free(G.buildpathHPFS);\n+            free(G.buildpathFAT);\n+            /* no room for filenames:  fatal */\n+            return MPN_ERR_TOOLONG;\n+        }\n+        *G.endHPFS++ = '/';\n+        *G.endFAT++ = '/';\n+        *G.endHPFS = *G.endFAT = '\\0';\n+        Trace((stderr, \"buildpathHPFS now = [%s]\\nbuildpathFAT now =  [%s]\\n\",\n+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n+        return MPN_OK;\n+\n+    } /* end if (FUNCTION == APPEND_DIR) */\n+\n+/*---------------------------------------------------------------------------\n+    GETPATH:  copy full FAT path to the string pointed at by pathcomp (want\n+    filename to reflect name used on disk, not EAs; if full path is HPFS,\n+    buildpathFAT and buildpathHPFS will be identical).  Also free both paths.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (FUNCTION == GETPATH) {\n+        Trace((stderr, \"getting and freeing FAT path [%s]\\n\",\n+          FnFilter1(G.buildpathFAT)));\n+        Trace((stderr, \"freeing HPFS path [%s]\\n\",\n+          FnFilter1(G.buildpathHPFS)));\n+        strcpy(pathcomp, G.buildpathFAT);\n+        free(G.buildpathFAT);\n+        free(G.buildpathHPFS);\n+        G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;\n+        return MPN_OK;\n+    }\n+\n+/*---------------------------------------------------------------------------\n+    APPEND_NAME:  assume the path component is the filename; append it and\n+    return without checking for existence.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (FUNCTION == APPEND_NAME) {\n+        char *p = pathcomp;\n+        int error = MPN_OK;\n+\n+        Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n+        /* The buildpathHPFS buffer has been allocated large enough to\n+         * hold the complete combined name, so there is no need to check\n+         * for OS filename size limit overflow within the copy loop.\n+         */\n+        while ((*G.endHPFS = *p++) != '\\0') {   /* copy to HPFS filename */\n+            ++G.endHPFS;\n+        }\n+        /* Now, check for OS filename size overflow.  When detected, the\n+         * mapped HPFS name is truncated and a warning message is shown.\n+         */\n+        if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {\n+            G.buildpathHPFS[FILNAMSIZ-1] = '\\0';\n+            Info(slide, 1, ((char *)slide,\n+              \"checkdir warning:  path too long; truncating\\n \\\n+              %s\\n                -> %s\\n\",\n+              FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));\n+            error = MPN_INF_TRUNC;  /* filename truncated */\n+        }\n+\n+        /* The buildpathFAT buffer has the same allocated size as the\n+         * buildpathHPFS buffer, so there is no need for an overflow check\n+         * within the following copy loop, either.\n+         */\n+        if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n+            /* copy to FAT filename, too */\n+            p = pathcomp;\n+            while ((*G.endFAT = *p++) != '\\0')\n+                ++G.endFAT;\n+        } else\n+            /* map into FAT fn, update endFAT */\n+            map2fat(pathcomp, &G.endFAT);\n+\n+        /* Check that the FAT path does not exceed the FILNAMSIZ limit, and\n+         * truncate when neccessary.\n+         * Note that truncation can only happen when the HPFS path (which is\n+         * never shorter than the FAT path) has been already truncated.\n+         * So, emission of the warning message and setting the error code\n+         * has already happened.\n+         */\n+        if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)\n+            G.buildpathFAT[FILNAMSIZ-1] = '\\0';\n+        Trace((stderr, \"buildpathHPFS: %s\\nbuildpathFAT:  %s\\n\",\n+          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n+\n+        return error;  /* could check for existence, prompt for new name... */\n+\n+    } /* end if (FUNCTION == APPEND_NAME) */\n+\n+/*---------------------------------------------------------------------------\n+    INIT:  allocate and initialize buffer space for the file currently being\n+    extracted.  If file was renamed with an absolute path, don't prepend the\n+    extract-to path.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (FUNCTION == INIT) {\n+        Trace((stderr, \"initializing buildpathHPFS and buildpathFAT to \"));\n+#ifdef ACORN_FTYPE_NFS\n+        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+\n+                                              (uO.acorn_nfs_ext ? 5 : 1)))\n+#else\n+        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))\n+#endif\n+            == NULL)\n+            return MPN_NOMEM;\n+#ifdef ACORN_FTYPE_NFS\n+        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+\n+                                             (uO.acorn_nfs_ext ? 5 : 1)))\n+#else\n+        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))\n+#endif\n+            == NULL) {\n+            free(G.buildpathHPFS);\n+            return MPN_NOMEM;\n+        }\n+        if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */\n+/* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */\n+            if (G.renamed_fullpath && pathcomp[1] == ':')\n+                *G.buildpathHPFS = (char)ToLower(*pathcomp);\n+            else if (!G.renamed_fullpath && G.rootlen > 1 &&\n+                     G.rootpath[1] == ':')\n+                *G.buildpathHPFS = (char)ToLower(*G.rootpath);\n+            else {\n+                char tmpN[MAX_PATH], *tmpP;\n+                if (GetFullPathNameA(\".\", MAX_PATH, tmpN, &tmpP) > MAX_PATH)\n+                { /* by definition of MAX_PATH we should never get here */\n+                    Info(slide, 1, ((char *)slide,\n+                      \"checkdir warning: current dir path too long\\n\"));\n+                    return MPN_INF_TRUNC;   /* can't get drive letter */\n+                }\n+                G.nLabelDrive = *tmpN - 'a' + 1;\n+                *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');\n+            }\n+            G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */\n+            if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */\n+                || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */\n+                free(G.buildpathHPFS);\n+                free(G.buildpathFAT);\n+                return MPN_VOL_LABEL;  /* skipping with message */\n+            }\n+            *G.buildpathHPFS = '\\0';\n+        } else if (G.renamed_fullpath) /* pathcomp = valid data */\n+            strcpy(G.buildpathHPFS, pathcomp);\n+        else if (G.rootlen > 0)\n+            strcpy(G.buildpathHPFS, G.rootpath);\n+        else\n+            *G.buildpathHPFS = '\\0';\n+        G.endHPFS = G.buildpathHPFS;\n+        G.endFAT = G.buildpathFAT;\n+        while ((*G.endFAT = *G.endHPFS) != '\\0') {\n+            ++G.endFAT;\n+            ++G.endHPFS;\n+        }\n+        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpathHPFS)));\n+        return MPN_OK;\n+    }\n+\n+/*---------------------------------------------------------------------------\n+    ROOT:  if appropriate, store the path in rootpath and create it if neces-\n+    sary; else assume it's a zipfile member and return.  This path segment\n+    gets used in extracting all members from every zipfile specified on the\n+    command line.  Note that under OS/2 and MS-DOS, if a candidate extract-to\n+    directory specification includes a drive letter (leading \"x:\"), it is\n+    treated just as if it had a trailing '/'--that is, one directory level\n+    will be created if the path doesn't exist, unless this is otherwise pro-\n+    hibited (e.g., freshening).\n+  ---------------------------------------------------------------------------*/\n+\n+#if (!defined(SFX) || defined(SFX_EXDIR))\n+    if (FUNCTION == ROOT) {\n+        Trace((stderr, \"initializing root path to [%s]\\n\",\n+          FnFilter1(pathcomp)));\n+        if (pathcomp == NULL) {\n+            G.rootlen = 0;\n+            return MPN_OK;\n+        }\n+        if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n+            return MPN_OK;\n+        if ((G.rootlen = strlen(pathcomp)) > 0) {\n+            int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n+            char *tmproot;\n+\n+            if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {\n+                G.rootlen = 0;\n+                return MPN_NOMEM;\n+            }\n+            strcpy(tmproot, pathcomp);\n+            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n+                has_drive = TRUE;   /* drive designator */\n+            if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\\\') {\n+                tmproot[--G.rootlen] = '\\0';\n+                had_trailing_pathsep = TRUE;\n+            }\n+            if (has_drive && (G.rootlen == 2)) {\n+                if (!had_trailing_pathsep)   /* i.e., original wasn't \"x:/\" */\n+                    add_dot = TRUE;    /* relative path: add '.' before '/' */\n+            } else if (G.rootlen > 0) {   /* need not check \"x:.\" and \"x:/\" */\n+                if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n+                {\n+                    /* path does not exist */\n+                    if (!G.create_dirs /* || iswild(tmproot) */ ) {\n+                        free(tmproot);\n+                        G.rootlen = 0;\n+                        /* treat as stored file */\n+                        return MPN_INF_SKIP;\n+                    }\n+                    /* create directory (could add loop here scanning tmproot\n+                     * to create more than one level, but really necessary?) */\n+                    if (MKDIR(tmproot, 0777) == -1) {\n+                        Info(slide, 1, ((char *)slide,\n+                          \"checkdir:  cannot create extraction directory: %s\\n\",\n+                          FnFilter1(tmproot)));\n+                        free(tmproot);\n+                        G.rootlen = 0;\n+                        /* path didn't exist, tried to create, failed: */\n+                        /* file exists, or need 2+ subdir levels */\n+                        return MPN_ERR_SKIP;\n+                    }\n+                }\n+            }\n+            if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n+                tmproot[G.rootlen++] = '.';\n+            tmproot[G.rootlen++] = '/';\n+            tmproot[G.rootlen] = '\\0';\n+            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n+                free(tmproot);\n+                G.rootlen = 0;\n+                return MPN_NOMEM;\n+            }\n+            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n+        }\n+        return MPN_OK;\n+    }\n+#endif /* !SFX || SFX_EXDIR */\n+\n+/*---------------------------------------------------------------------------\n+    END:  free rootpath, immediately prior to program exit.\n+  ---------------------------------------------------------------------------*/\n+\n+    if (FUNCTION == END) {\n+        Trace((stderr, \"freeing rootpath\\n\"));\n+        if (G.rootlen > 0) {\n+            free(G.rootpath);\n+            G.rootlen = 0;\n+        }\n+        return MPN_OK;\n     }\n-} /* end function map2fat() */\n \n+    return MPN_INVALID; /* should never reach */\n+\n+} /* end function checkdir() */\n \n \n \n-/***********************/       /* Borrowed from os2.c for UnZip 5.1.        */\n-/* Function checkdir() */       /* Difference: no EA stuff                   */\n-/***********************/       /*             HPFS stuff works on NTFS too  */\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n \n-int checkdir(__G__ pathcomp, flag)\n+/* WIN32 wide version */\n+\n+int checkdirw(__G__ pathcompw, flag)\n     __GDEF\n-    char *pathcomp;\n+    wchar_t *pathcompw;\n     int flag;\n /*\n@@ -2126,16 +3345,20 @@\n \n     if (FUNCTION == APPEND_DIR) {\n-        char *p = pathcomp;\n+        wchar_t *pw = pathcompw;\n         int too_long = FALSE;\n-\n-        Trace((stderr, \"appending dir segment [%s]\\n\", FnFilter1(pathcomp)));\n-        while ((*G.endHPFS = *p++) != '\\0')     /* copy to HPFS filename */\n-            ++G.endHPFS;\n-        if (!IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n-            p = pathcomp;\n-            while ((*G.endFAT = *p++) != '\\0')  /* copy to FAT filename, too */\n-                ++G.endFAT;\n+        char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);\n+        char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);\n+        /* Could use G.filename from the standard path, but may\n+           not work well on this port */\n+        char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);\n+\n+        while ((*G.endHPFSw = *pw++) != '\\0')     /* copy to HPFS filename */\n+            ++G.endHPFSw;\n+        if (!IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {\n+            pw = pathcompw;\n+            while ((*G.endFATw = *pw++) != '\\0')  /* copy to FAT filename, too */\n+                ++G.endFATw;\n         } else\n-            map2fat(pathcomp, &G.endFAT);   /* map into FAT fn, update endFAT */\n+            map2fatw(pathcompw, &G.endFATw);   /* map into FAT fn, update endFAT */\n \n         /* GRR:  could do better check, see if overrunning buffer as we go:\n@@ -2145,5 +3368,5 @@\n \n         /* next check:  need to append '/', at least one-char name, '\\0' */\n-        if ((G.endHPFS-G.buildpathHPFS) > FILNAMSIZ-3)\n+        if ((G.endHPFSw-G.buildpathHPFSw) > FILNAMSIZ-3)\n             too_long = TRUE;                    /* check if extracting dir? */\n #ifdef FIX_STAT_BUG\n@@ -2153,8 +3376,11 @@\n          * than console. The code below attempts to work around this problem.\n          */\n-        if (access(G.buildpathFAT, 0) != 0) {\n+        if (_waccess(G.buildpathFATw, 0) != 0) {\n             if (!G.create_dirs) { /* told not to create (freshening) */\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n+                free(buildpathHPFS);\n+                free(buildpathFAT);\n+                free(fn);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n                 /* path doesn't exist:  nothing to do */\n                 return MPN_INF_SKIP;\n@@ -2163,28 +3389,40 @@\n                 Info(slide, 1, ((char *)slide,\n                   \"checkdir error:  path too long: %s\\n\",\n-                  FnFilter1(G.buildpathHPFS)));\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n+                  FnFilter1(fn)));\n+                free(buildpathHPFS);\n+                free(buildpathFAT);\n+                free(fn);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n                 /* no room for filenames:  fatal */\n                 return MPN_ERR_TOOLONG;\n             }\n-            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n-                Info(slide, 1, ((char *)slide,\n-                  \"checkdir error:  cannot create %s\\n\\\n-                 unable to process %s.\\n\",\n-                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n-                /* path didn't exist, tried to create, failed */\n-                return MPN_ERR_SKIP;\n-            }\n-            G.created_dir = TRUE;\n+\t\t\t{\n+\t\t\t\tint i = MKDIRW(G.buildpathFATw, 0777);\n+\t\t\t\tif (i == -1) { /* create the directory */\n+\t\t\t\t\tInfo(slide, 1, ((char *)slide,\n+\t\t\t\t\t  \"checkdir error:  cannot create %s\\n\\\n+\t\t\t\t\t unable to process %s.\\n\",\n+\t\t\t\t\t  FnFilter2(buildpathFAT), FnFilter1(fn)));\n+\t\t\t\t\tfree(buildpathHPFS);\n+\t\t\t\t\tfree(buildpathFAT);\n+\t\t\t\t\tfree(fn);\n+\t\t\t\t\tfree(G.buildpathHPFSw);\n+\t\t\t\t\tfree(G.buildpathFATw);\n+\t\t\t\t\t/* path didn't exist, tried to create, failed */\n+\t\t\t\t\treturn MPN_ERR_SKIP;\n+\t\t\t\t}\n+\t\t\t\tG.created_dir = TRUE;\n+\t\t\t}\n         }\n #endif /* FIX_STAT_BUG */\n-        if (SSTAT(G.buildpathFAT, &G.statbuf))   /* path doesn't exist */\n+        if (SSTATW(G.buildpathFATw, &G.statbuf))   /* path doesn't exist */\n         {\n             if (!G.create_dirs) { /* told not to create (freshening) */\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n+                free(buildpathHPFS);\n+                free(buildpathFAT);\n+                free(fn);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n                 /* path doesn't exist:  nothing to do */\n                 return MPN_INF_SKIP;\n@@ -2193,28 +3431,41 @@\n                 Info(slide, 1, ((char *)slide,\n                   \"checkdir error:  path too long: %s\\n\",\n-                  FnFilter1(G.buildpathHPFS)));\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n+                  FnFilter1(buildpathHPFS)));\n+                free(buildpathHPFS);\n+                free(buildpathFAT);\n+                free(fn);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n                 /* no room for filenames:  fatal */\n                 return MPN_ERR_TOOLONG;\n             }\n-            if (MKDIR(G.buildpathFAT, 0777) == -1) { /* create the directory */\n-                Info(slide, 1, ((char *)slide,\n-                  \"checkdir error:  cannot create %s\\n\\\n-                 unable to process %s.\\n\",\n-                  FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n-                /* path didn't exist, tried to create, failed */\n-                return MPN_ERR_SKIP;\n-            }\n-            G.created_dir = TRUE;\n+            {\n+\t\t\t\tchar *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);\n+\t\t\t\tint i = MKDIRW(G.buildpathFATw, 0777);\n+\t\t\t\tif (i == -1) { /* create the directory */\n+\t\t\t\t\tInfo(slide, 1, ((char *)slide,\n+\t\t\t\t\t  \"checkdir error:  cannot create %s\\n\\\n+\t\t\t\t\t unable to process %s.\\n\",\n+\t\t\t\t\t  FnFilter2(buildpathFAT), FnFilter1(fn)));\n+\t\t\t\t\tfree(buildpathHPFS);\n+\t\t\t\t\tfree(buildpathFAT);\n+\t\t\t\t\tfree(fn);\n+\t\t\t\t\tfree(G.buildpathHPFSw);\n+\t\t\t\t\tfree(G.buildpathFATw);\n+\t\t\t\t\t/* path didn't exist, tried to create, failed */\n+\t\t\t\t\treturn MPN_ERR_SKIP;\n+\t\t\t\t}\n+\t\t\t\tG.created_dir = TRUE;\n+\t\t\t}\n         } else if (!S_ISDIR(G.statbuf.st_mode)) {\n             Info(slide, 1, ((char *)slide,\n               \"checkdir error:  %s exists but is not directory\\n   \\\n               unable to process %s.\\n\",\n-              FnFilter2(G.buildpathFAT), FnFilter1(G.filename)));\n-            free(G.buildpathHPFS);\n-            free(G.buildpathFAT);\n+              FnFilter2(buildpathFAT), FnFilter1(fn)));\n+              free(buildpathHPFS);\n+              free(buildpathFAT);\n+              free(fn);\n+              free(G.buildpathHPFSw);\n+              free(G.buildpathFATw);\n             /* path existed but wasn't dir */\n             return MPN_ERR_SKIP;\n@@ -2223,15 +3474,23 @@\n             Info(slide, 1, ((char *)slide,\n               \"checkdir error:  path too long: %s\\n\",\n-               FnFilter1(G.buildpathHPFS)));\n-            free(G.buildpathHPFS);\n-            free(G.buildpathFAT);\n+               FnFilter1(buildpathHPFS)));\n+                free(buildpathHPFS);\n+                free(buildpathFAT);\n+                free(fn);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n             /* no room for filenames:  fatal */\n             return MPN_ERR_TOOLONG;\n         }\n-        *G.endHPFS++ = '/';\n-        *G.endFAT++ = '/';\n-        *G.endHPFS = *G.endFAT = '\\0';\n+        *G.endHPFSw++ = '/';\n+        *G.endFATw++ = '/';\n+        *G.endHPFSw = *G.endFATw = '\\0';\n         Trace((stderr, \"buildpathHPFS now = [%s]\\nbuildpathFAT now =  [%s]\\n\",\n-          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n+          FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));\n+        free(buildpathHPFS);\n+        free(buildpathFAT);\n+        free(fn);\n+        //free(G.buildpathHPFSw);\n+        //free(G.buildpathFATw);\n         return MPN_OK;\n \n@@ -2245,12 +3504,16 @@\n \n     if (FUNCTION == GETPATH) {\n+        char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all);\n+        char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);\n         Trace((stderr, \"getting and freeing FAT path [%s]\\n\",\n-          FnFilter1(G.buildpathFAT)));\n+          FnFilter1(buildpathFAT)));\n         Trace((stderr, \"freeing HPFS path [%s]\\n\",\n-          FnFilter1(G.buildpathHPFS)));\n-        strcpy(pathcomp, G.buildpathFAT);\n-        free(G.buildpathFAT);\n-        free(G.buildpathHPFS);\n-        G.buildpathHPFS = G.buildpathFAT = G.endHPFS = G.endFAT = NULL;\n+          FnFilter1(buildpathHPFS)));\n+        wcscpy(pathcompw, G.buildpathFATw);\n+        free(buildpathFAT);\n+        free(buildpathHPFS);\n+        free(G.buildpathFATw);\n+        free(G.buildpathHPFSw);\n+        G.buildpathHPFSw = G.buildpathFATw = G.endHPFSw = G.endFATw = NULL;\n         return MPN_OK;\n     }\n@@ -2262,6 +3525,8 @@\n \n     if (FUNCTION == APPEND_NAME) {\n-        char *p = pathcomp;\n+        wchar_t *pw = pathcompw;\n         int error = MPN_OK;\n+        char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);\n+        char *fn = wchar_to_local_string(G.unipath_widefilename, G.unicode_escape_all);\n \n         Trace((stderr, \"appending filename [%s]\\n\", FnFilter1(pathcomp)));\n@@ -2270,16 +3535,19 @@\n          * for OS filename size limit overflow within the copy loop.\n          */\n-        while ((*G.endHPFS = *p++) != '\\0') {   /* copy to HPFS filename */\n-            ++G.endHPFS;\n+        while ((*G.endHPFSw = *pw++) != '\\0') {   /* copy to HPFS filename */\n+            ++G.endHPFSw;\n         }\n         /* Now, check for OS filename size overflow.  When detected, the\n          * mapped HPFS name is truncated and a warning message is shown.\n          */\n-        if ((G.endHPFS-G.buildpathHPFS) >= FILNAMSIZ) {\n-            G.buildpathHPFS[FILNAMSIZ-1] = '\\0';\n+        if ((G.endHPFSw-G.buildpathHPFSw) >= FILNAMSIZ) {\n+            char *buildpathHPFS;\n+            G.buildpathHPFSw[FILNAMSIZ-1] = '\\0';\n+            buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);\n             Info(slide, 1, ((char *)slide,\n               \"checkdir warning:  path too long; truncating\\n \\\n               %s\\n                -> %s\\n\",\n-              FnFilter1(G.filename), FnFilter2(G.buildpathHPFS)));\n+              FnFilter1(fn), FnFilter2(buildpathHPFS)));\n+            free(buildpathHPFS);\n             error = MPN_INF_TRUNC;  /* filename truncated */\n         }\n@@ -2289,12 +3557,12 @@\n          * within the following copy loop, either.\n          */\n-        if (G.pInfo->vollabel || !IsVolumeOldFAT(__G__ G.buildpathHPFS)) {\n+        if (G.pInfo->vollabel || !IsVolumeOldFATw(__G__ G.buildpathHPFSw)) {\n             /* copy to FAT filename, too */\n-            p = pathcomp;\n-            while ((*G.endFAT = *p++) != '\\0')\n-                ++G.endFAT;\n+            pw = pathcompw;\n+            while ((*G.endFATw = *pw++) != '\\0')\n+                ++G.endFATw;\n         } else\n             /* map into FAT fn, update endFAT */\n-            map2fat(pathcomp, &G.endFAT);\n+            map2fatw(pathcompw, &G.endFATw);\n \n         /* Check that the FAT path does not exceed the FILNAMSIZ limit, and\n@@ -2305,8 +3573,16 @@\n          * has already happened.\n          */\n-        if ((G.endFAT-G.buildpathFAT) >= FILNAMSIZ)\n-            G.buildpathFAT[FILNAMSIZ-1] = '\\0';\n-        Trace((stderr, \"buildpathHPFS: %s\\nbuildpathFAT:  %s\\n\",\n-          FnFilter1(G.buildpathHPFS), FnFilter2(G.buildpathFAT)));\n+        if ((G.endFATw-G.buildpathFATw) >= FILNAMSIZ)\n+            G.buildpathFATw[FILNAMSIZ-1] = '\\0';\n+        {\n+          char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);\n+          char *buildpathFAT = wchar_to_local_string(G.buildpathFATw,G.unicode_escape_all);\n+          Trace((stderr, \"buildpathHPFS: %s\\nbuildpathFAT:  %s\\n\",\n+            FnFilter1(buildpathHPFS), FnFilter2(buildpathFAT)));\n+          free(buildpathHPFS);\n+          free(buildpathFAT);\n+        }\n+        free(fn);\n+        free(pathcomp);\n \n         return error;  /* could check for existence, prompt for new name... */\n@@ -2321,33 +3597,23 @@\n \n     if (FUNCTION == INIT) {\n-        Trace((stderr, \"initializing buildpathHPFS and buildpathFAT to \"));\n-#ifdef ACORN_FTYPE_NFS\n-        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+\n-                                              (uO.acorn_nfs_ext ? 5 : 1)))\n-#else\n-        if ((G.buildpathHPFS = (char *)malloc(G.fnlen+G.rootlen+1))\n-#endif\n+        Trace((stderr, \"initializing buildpathHPFSw and buildpathFATw to \"));\n+        if ((G.buildpathHPFSw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))\n             == NULL)\n             return MPN_NOMEM;\n-#ifdef ACORN_FTYPE_NFS\n-        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+\n-                                             (uO.acorn_nfs_ext ? 5 : 1)))\n-#else\n-        if ((G.buildpathFAT = (char *)malloc(G.fnlen+G.rootlen+1))\n-#endif\n+        if ((G.buildpathFATw = (wchar_t *)malloc((G.fnlen+G.rootlen+1) * sizeof(wchar_t)))\n             == NULL) {\n-            free(G.buildpathHPFS);\n+            free(G.buildpathHPFSw);\n             return MPN_NOMEM;\n         }\n         if (G.pInfo->vollabel) { /* use root or renamed path, but don't store */\n /* GRR:  for network drives, do strchr() and return IZ_VOL_LABEL if not [1] */\n-            if (G.renamed_fullpath && pathcomp[1] == ':')\n-                *G.buildpathHPFS = (char)ToLower(*pathcomp);\n+            if (G.renamed_fullpath && pathcompw[1] == ':')\n+                *G.buildpathHPFSw = (wchar_t)towlower(*pathcompw);\n             else if (!G.renamed_fullpath && G.rootlen > 1 &&\n-                     G.rootpath[1] == ':')\n-                *G.buildpathHPFS = (char)ToLower(*G.rootpath);\n+                     G.rootpathw[1] == ':')\n+                *G.buildpathHPFSw = (wchar_t)towlower(*G.rootpathw);\n             else {\n-                char tmpN[MAX_PATH], *tmpP;\n-                if (GetFullPathNameA(\".\", MAX_PATH, tmpN, &tmpP) > MAX_PATH)\n+                wchar_t tmpNw[MAX_PATH], *tmpPw;\n+                if (GetFullPathNameW(L\".\", MAX_PATH, tmpNw, &tmpPw) > MAX_PATH)\n                 { /* by definition of MAX_PATH we should never get here */\n                     Info(slide, 1, ((char *)slide,\n@@ -2355,28 +3621,33 @@\n                     return MPN_INF_TRUNC;   /* can't get drive letter */\n                 }\n-                G.nLabelDrive = *tmpN - 'a' + 1;\n-                *G.buildpathHPFS = (char)(G.nLabelDrive - 1 + 'a');\n+                G.nLabelDrive = (char)(*tmpNw - 'a' + 1);\n+                *G.buildpathHPFSw = (wchar_t)(G.nLabelDrive - 1 + 'a');\n             }\n-            G.nLabelDrive = *G.buildpathHPFS - 'a' + 1; /* save for mapname() */\n-            if (uO.volflag == 0 || *G.buildpathHPFS < 'a' /* no labels/bogus? */\n+            G.nLabelDrive = (char)(*G.buildpathHPFSw - 'a' + 1); /* save for mapname() */\n+            if (uO.volflag == 0 || *G.buildpathHPFSw < 'a' /* no labels/bogus? */\n                 || (uO.volflag == 1 && !isfloppy(G.nLabelDrive))) { /* !fixed */\n-                free(G.buildpathHPFS);\n-                free(G.buildpathFAT);\n+                free(G.buildpathHPFSw);\n+                free(G.buildpathFATw);\n                 return MPN_VOL_LABEL;  /* skipping with message */\n             }\n-            *G.buildpathHPFS = '\\0';\n+            *G.buildpathHPFSw = '\\0';\n         } else if (G.renamed_fullpath) /* pathcomp = valid data */\n-            strcpy(G.buildpathHPFS, pathcomp);\n+            wcscpy(G.buildpathHPFSw, pathcompw);\n         else if (G.rootlen > 0)\n-            strcpy(G.buildpathHPFS, G.rootpath);\n+            wcscpy(G.buildpathHPFSw, G.rootpathw);\n         else\n-            *G.buildpathHPFS = '\\0';\n-        G.endHPFS = G.buildpathHPFS;\n-        G.endFAT = G.buildpathFAT;\n-        while ((*G.endFAT = *G.endHPFS) != '\\0') {\n-            ++G.endFAT;\n-            ++G.endHPFS;\n+            *G.buildpathHPFSw = '\\0';\n+        G.endHPFSw = G.buildpathHPFSw;\n+        G.endFATw = G.buildpathFATw;\n+        while ((*G.endFATw = *G.endHPFSw) != '\\0') {\n+            ++G.endFATw;\n+            ++G.endHPFSw;\n         }\n-        Trace((stderr, \"[%s]\\n\", FnFilter1(G.buildpathHPFS)));\n+        {\n+          char *buildpathHPFS = wchar_to_local_string(G.buildpathHPFSw, G.unicode_escape_all);\n+          Trace((stderr, \"[%s]\\n\", FnFilter1(buildpathHPFS)));\n+          free(buildpathHPFS);\n+        }\n+\n         return MPN_OK;\n     }\n@@ -2395,7 +3666,9 @@\n #if (!defined(SFX) || defined(SFX_EXDIR))\n     if (FUNCTION == ROOT) {\n+        char *pathcomp = wchar_to_local_string(pathcompw, G.unicode_escape_all);\n         Trace((stderr, \"initializing root path to [%s]\\n\",\n           FnFilter1(pathcomp)));\n-        if (pathcomp == NULL) {\n+        free(pathcomp);\n+        if (pathcompw == NULL) {\n             G.rootlen = 0;\n             return MPN_OK;\n@@ -2403,17 +3676,17 @@\n         if (G.rootlen > 0)      /* rootpath was already set, nothing to do */\n             return MPN_OK;\n-        if ((G.rootlen = strlen(pathcomp)) > 0) {\n+        if ((G.rootlen = wcslen(pathcompw)) > 0) {\n             int had_trailing_pathsep=FALSE, has_drive=FALSE, add_dot=FALSE;\n-            char *tmproot;\n+            wchar_t *tmprootw;\n \n-            if ((tmproot = (char *)malloc(G.rootlen+3)) == (char *)NULL) {\n+            if ((tmprootw = (wchar_t *)malloc((G.rootlen+3) * sizeof(wchar_t))) == (wchar_t *)NULL) {\n                 G.rootlen = 0;\n                 return MPN_NOMEM;\n             }\n-            strcpy(tmproot, pathcomp);\n-            if (isalpha((uch)tmproot[0]) && tmproot[1] == ':')\n+            wcscpy(tmprootw, pathcompw);\n+            if (iswalpha(tmprootw[0]) && tmprootw[1] == ':')\n                 has_drive = TRUE;   /* drive designator */\n-            if (tmproot[G.rootlen-1] == '/' || tmproot[G.rootlen-1] == '\\\\') {\n-                tmproot[--G.rootlen] = '\\0';\n+            if (tmprootw[G.rootlen-1] == '/' || tmprootw[G.rootlen-1] == '\\\\') {\n+                tmprootw[--G.rootlen] = '\\0';\n                 had_trailing_pathsep = TRUE;\n             }\n@@ -2422,9 +3695,9 @@\n                     add_dot = TRUE;    /* relative path: add '.' before '/' */\n             } else if (G.rootlen > 0) {   /* need not check \"x:.\" and \"x:/\" */\n-                if (SSTAT(tmproot, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n+                if (SSTATW(tmprootw, &G.statbuf) || !S_ISDIR(G.statbuf.st_mode))\n                 {\n                     /* path does not exist */\n                     if (!G.create_dirs /* || iswild(tmproot) */ ) {\n-                        free(tmproot);\n+                        free(tmprootw);\n                         G.rootlen = 0;\n                         /* treat as stored file */\n@@ -2433,12 +3706,15 @@\n                     /* create directory (could add loop here scanning tmproot\n                      * to create more than one level, but really necessary?) */\n-                    if (MKDIR(tmproot, 0777) == -1) {\n+                    if (MKDIRW(tmprootw, 0777) == -1) {\n+                        char *tmproot = wchar_to_local_string(tmprootw, G.unicode_escape_all);\n                         Info(slide, 1, ((char *)slide,\n                           \"checkdir:  cannot create extraction directory: %s\\n\",\n                           FnFilter1(tmproot)));\n                         free(tmproot);\n+                        free(tmprootw);\n                         G.rootlen = 0;\n                         /* path didn't exist, tried to create, failed: */\n                         /* file exists, or need 2+ subdir levels */\n+                        free(pathcomp);\n                         return MPN_ERR_SKIP;\n                     }\n@@ -2446,13 +3722,17 @@\n             }\n             if (add_dot)                    /* had just \"x:\", make \"x:.\" */\n-                tmproot[G.rootlen++] = '.';\n-            tmproot[G.rootlen++] = '/';\n-            tmproot[G.rootlen] = '\\0';\n-            if ((G.rootpath = (char *)realloc(tmproot, G.rootlen+1)) == NULL) {\n-                free(tmproot);\n+                tmprootw[G.rootlen++] = '.';\n+            tmprootw[G.rootlen++] = '/';\n+            tmprootw[G.rootlen] = '\\0';\n+            if ((G.rootpathw = (wchar_t *)realloc(tmprootw, (G.rootlen+1) * sizeof(wchar_t))) == NULL) {\n+                free(tmprootw);\n                 G.rootlen = 0;\n                 return MPN_NOMEM;\n             }\n-            Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(G.rootpath)));\n+            {\n+              char *rootpath = wchar_to_local_string(G.rootpathw, G.unicode_escape_all);\n+              Trace((stderr, \"rootpath now = [%s]\\n\", FnFilter1(rootpath)));\n+              free(rootpath);\n+            }\n         }\n         return MPN_OK;\n@@ -2467,5 +3747,5 @@\n         Trace((stderr, \"freeing rootpath\\n\"));\n         if (G.rootlen > 0) {\n-            free(G.rootpath);\n+            free(G.rootpathw);\n             G.rootlen = 0;\n         }\n@@ -2475,6 +3755,7 @@\n     return MPN_INVALID; /* should never reach */\n \n-} /* end function checkdir() */\n+} /* end function checkdirw() */\n \n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n \n \n@@ -2809,4 +4090,99 @@\n }\n \n+\n+\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n+\n+int zstat_win32w(__W32STAT_GLOBALS__ const wchar_t *pathw, z_stat *buf)\n+{\n+    if (!zstatw(pathw, buf))\n+    {\n+        char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);\n+        /* stat was successful, now redo the time-stamp fetches */\n+#ifndef NO_W32TIMES_IZFIX\n+        int fs_uses_loctime = FStampIsLocTimeW(__G__ pathw);\n+#endif\n+        HANDLE h;\n+        FILETIME Modft, Accft, Creft;\n+\n+        TTrace((stdout, \"stat(%s) finds modtime %08lx\\n\", path, buf->st_mtime));\n+        h = CreateFileW(pathw, GENERIC_READ,\n+                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\n+                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n+        if (h != INVALID_HANDLE_VALUE) {\n+            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);\n+            CloseHandle(h);\n+\n+            if (ftOK) {\n+                FTTrace((stdout, \"GetFileTime returned Modft\", 0, &Modft));\n+                FTTrace((stdout, \"GetFileTime returned Creft\", 0, &Creft));\n+#ifndef NO_W32TIMES_IZFIX\n+                if (!fs_uses_loctime) {\n+                    /*  On a filesystem that stores UTC timestamps, we refill\n+                     *  the time fields of the struct stat buffer by directly\n+                     *  using the UTC values as returned by the Win32\n+                     *  GetFileTime() API call.\n+                     */\n+                    NtfsFileTime2utime(&Modft, &(buf->st_mtime));\n+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n+                        NtfsFileTime2utime(&Accft, &(buf->st_atime));\n+                    else\n+                        buf->st_atime = buf->st_mtime;\n+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n+                        NtfsFileTime2utime(&Creft, &(buf->st_ctime));\n+                    else\n+                        buf->st_ctime = buf->st_mtime;\n+                    TTrace((stdout,\"NTFS, recalculated modtime %08lx\\n\",\n+                            buf->st_mtime));\n+                } else\n+#endif /* NO_W32TIMES_IZFIX */\n+                {\n+                    /*  On VFAT and FAT-like filesystems, the FILETIME values\n+                     *  are converted back to the stable local time before\n+                     *  converting them to UTC unix time-stamps.\n+                     */\n+                    VFatFileTime2utime(&Modft, &(buf->st_mtime));\n+                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n+                        VFatFileTime2utime(&Accft, &(buf->st_atime));\n+                    else\n+                        buf->st_atime = buf->st_mtime;\n+                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n+                        VFatFileTime2utime(&Creft, &(buf->st_ctime));\n+                    else\n+                        buf->st_ctime = buf->st_mtime;\n+                    TTrace((stdout, \"VFAT, recalculated modtime %08lx\\n\",\n+                            buf->st_mtime));\n+                }\n+            }\n+        }\n+        free(path);\n+\n+        return 0;\n+    }\n+#ifdef W32_STATROOT_FIX\n+    else\n+    {\n+        DWORD flags;\n+\n+        flags = GetFileAttributesW(pathw);\n+        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {\n+            char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all);\n+            Trace((stderr, \"\\nstat(\\\"%s\\\",...) failed on existing directory\\n\",\n+                   FnFilter1(path)));\n+            free(path);\n+            memset(buf, 0, sizeof(z_stat));\n+            buf->st_atime = buf->st_ctime = buf->st_mtime =\n+              dos_to_unix_time(DOSTIME_MINIMUM);        /* 1-1-80 */\n+            buf->st_mode = S_IFDIR | S_IREAD |\n+                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);\n+            return 0;\n+        } /* assumes: stat() won't fail on non-dirs without good reason */\n+    }\n+#endif /* W32_STATROOT_FIX */\n+    return -1;\n+}\n+\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\n+\n #endif /* W32_STAT_BANDAID */\n \n@@ -2939,6 +4315,5 @@\n \n \n-#if 0\n-#ifdef UNICODE_SUPPORT\n+#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE)\n wchar_t *utf8_to_wchar_string(utf8_string)\n   char *utf8_string;       /* path to get utf-8 name for */\n@@ -3030,22 +4405,40 @@\n   return qw;\n }\n-#endif /* UNICODE_SUPPORT */\n-#endif /* 0 */\n \n+int has_win32_wide()\n+{\n+  int is_win32_wide;\n \n+  /* test if we have wide function support */\n \n-/* --------------------------------------------------- */\n-/* Large File Support\n- *\n- * Initial functions by E. Gordon and R. Nausedat\n- * 9/10/2003\n- * Lifted from Zip 3b, win32.c and place here by Myles Bennett\n- * 7/6/2004\n- *\n- * These implement 64-bit file support for Windows.  The\n- * defines and headers are in win32/w32cfg.h.\n- *\n- * Moved to win32i64.c by Mike White to avoid conflicts in\n- * same name functions in WiZ using UnZip and Zip libraries.\n- * 9/25/2003\n- */\n+  /* first guess: On \"real\" WinNT, the WIN32 wide API >>is<< supported. */\n+  is_win32_wide = IsWinNT();\n+\n+  if (!is_win32_wide)\n+  {\n+    /* On a non-WinNT environment (Win9x or Win32s), wide functions\n+     * might although supported when program is linked against the\n+     * Win9x Unicode support library.\n+     * => run a check whether a needed API function is supported.\n+     */\n+    DWORD r;\n+    /* get attributes for this directory */\n+    r = GetFileAttributesA(\".\");\n+\n+    /* r should be 16 = FILE_ATTRIBUTE_DIRECTORY */\n+    if (r == FILE_ATTRIBUTE_DIRECTORY) {\n+      /* now see if it works for the wide version */\n+      r = GetFileAttributesW(L\".\");\n+      /* if this fails then we probably don't have wide functions */\n+      if (r == 0xFFFFFFFF) {\n+        /* error is probably \"This function is only valid in Win32 mode.\" */\n+      } else if (r == FILE_ATTRIBUTE_DIRECTORY) {\n+        /* worked, so assume we have wide support */\n+        is_win32_wide = TRUE;\n+      }\n+    }\n+  }\n+  return is_win32_wide;\n+}\n+\n+#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */\ndiff -ru2 unz60d10/windll/vc6/dll/unz32dll.dsp unz60d10_w32w/windll/vc6/dll/unz32dll.dsp\n--- unz60d10/windll/vc6/dll/unz32dll.dsp\tWed Dec 27 23:25:00 2006\n+++ unz60d10_w32w/windll/vc6/dll/unz32dll.dsp\tMon Feb 11 02:38:32 2008\n@@ -46,5 +46,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n-# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n+# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /YX /FD /c\n # ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n # ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n@@ -72,5 +72,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /YX /FD /c\n # ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n # ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n@@ -98,5 +98,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n-# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n+# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"ASM_CRC\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /YX /FD /c\n # ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n # ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n@@ -124,5 +124,5 @@\n # PROP Target_Dir \"\"\n # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"ASM_CRC\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"UNICODE_SUPPORT\" /D \"WIN32_WIDE\" /FR /YX /FD /c\n # ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n # ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/Contents",
    "content": "Contents of the \"WinCE\" subdirectory for UnZip 5.52 and later:\n\n   Contents     This file.\n   README       Information about the Windows CE port and its author.\n   punzip.h     Main header file for the entire Pocket UnZip project.\n   wcecfg.h     Common system-specific configurations for Windows CE port code.\n   wcemain.c    Main entry code for Win CE command line tool.\n   winmain.cpp  Contains the entire user interface and all Windows code.\n   winmain.h    Header for winmain.cpp.\n   intrface.cpp The interface between the Windows code and Info-ZIP code.\n   intrface.h   Header for intrface.cpp.\n   wince.cpp    All the Win32 APIs and C runtimes called by Info-ZIP.\n   wince.h      Header for wince.cpp.\n   punzip.rc    Resource file for all dialogs, bitmaps, menus, icons, etc.\n   resource.h   Resource header file for punzip.rc and other source modules.\n   punzip.htp   Windows CE help file (rename to punzip.html for WinNT).\n   punzip.rcv   Version resource and version defines.\n   punzip.ic2   Windows CE app icons (16x16 and 32x32, both 2 bits/pixel).\n   punzip.ico   Windows NT application icons (16x16 and 32x32, 16 bits/pixel).\n   zipfile.ic2  Windows CE zip icons (16x16 and 32x32, both 2 bits/pixel).\n   zipfile.ico  Windows NT zip file icons (16x16 and 32x32, 16 bits/pixel).\n   imglist.2bp  Windows CE image list bitmap (2 bits/pixel).\n   imglist.bmp  Windows NT image list bitmap (16 bits/pixel including mask).\n   ilmask.bmp   Windows CE image list mask bitmap (1 bit/pixel).\n   toolbar.2bp  Windows CE toolbar bitmap (2 bits/pixel).\n   toolbar.bmp  Windows NT toolbar bitmap (16 bits/pixel).\n   inc\\         Contains dummy headers that are called by Info-ZIP code.\n   vc5\\\n     punzip.dsp   Visual C++ 5.0 project for WinCE (SH3 and MIPS) and WinNT.\n   vc6\\\n     punzip.dsp   Visual C++ 6.0 project for WinCE (SH3 and MIPS) and WinNT.\n   vcEMbed3\\\n     punzip.vcp   Visual C++ Embedded Tools 3.0 project for pUnZip (WinCE).\n     unzipcmd.vcp Visual C++ Embedded Tools 3.0 project for WinCE cmdline tool.\n     unzipwce.vcw Visual C++ Embedded Tools 3.0 workspace for all WinCE tools.\n\nPlease note that Info-ZIP's source distribution for UnZip contains all text\nfiles in UNIX format (LF line terminators). But the Microsoft tools require\nsome of the sources and project files to be supplied in MSDOS format (CR-LF\nline terminators). You have to apply UnZip's \"-a\" option (or use some third-\nparty line termination converter) to get the UnZip sources unpacked in the\ncorrect file format.\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/README",
    "content": "_______________________________________________________________________________\n\n   This is the Windows CE Info-ZIP port README, last updated 17 September 2003.\n_______________________________________________________________________________\n\n   Copyright and Disclaimer\n_______________________________________________________________________________\n\nCopyright\n\n     All the source files for Pocket UnZip are copyrighted by Info-ZIP.\n     For details on terms and conditions look into the LICENSE file\n     that should be part of the source distribution.\n     The original author Steve P. Miller has gracefully allowed to\n     put his own source contributions for \"Pocket UnZip\" under the\n     Info-ZIP license.\n\nDisclaimer\n\n     All project files are provided \"as is\" with no guarantee of\n     their correctness.  The authors are not liable for any outcome\n     that is the result of using this source.  The source for Pocket\n     UnZip has been placed in the public domain to help provide an\n     understanding of its implementation.  You are hereby granted\n     full permission to use this source in any way you wish, except\n     to alter Pocket UnZip itself.  For comments, suggestions, and\n     bug reports, please write to stevemil@pobox.com or to the\n     generic Info-ZIP e-mail address Zip-Bugs@lists.wku.edu.\n\n_______________________________________________________________________________\n\n   About the Windows CE Port (known as \"Pocket UnZip\")\n_______________________________________________________________________________\n\nThe Windows CE port, known as Pocket UnZip, is designed to run on Microsoft's\nWindows CE operating system.  The port is completely contained in the files\nlisted above.  There were very few minor modifications made to the Info-ZIP\ncode in order for this port to work.  This was possible because the Info-ZIP\ncode is fairly generic and also because several hooks have already been placed\nin the code from past Windows ports.  The Windows CE port leverages off of\nthese efforts for two reasons.  Mainly, I wanted to avoid modifying the\nInfo-ZIP core code since people don't like it when your changes break other\nports.  Second, this makes the Windows CE port easy to upgrade when fixes and\nfeatures are released by the Info-ZIP group.\n\nThe port is made up of the project file (punzip.dsp), one global header\n(punzip.h), three main source modules (winmain.cpp/h, intrface.cpp/h,\nand wince.cpp/h), the resource script files (punzip.rc, punzip.rcv, and\nresource.h), several resources (punzip.ic2, zipfile.ic2, imglist.2bp,\nilmask.bmp, toolbar.2bp, punzip.ico, zipfile.ico, imglist.bmp, and\ntoolbar.bmp), and the help file (punzip.htp).\n\nThe application's entry point is WinMain(), which is located in winmain.cpp\n(what a surprise).  winmain.cpp basically contains all the Windows code and\nthe user interface.  It knows nothing about the Info-ZIP code or things like\nthe Globals struct.  That stuff is the job of the intrface module.\nintrface.cpp implements an easy (or at least easier) to understand interface\nto the Info-ZIP routines.  It also handles all the callbacks from Info-ZIP\nand relays the appropriate information back to the code in winmain.cpp.\nThe final module is wince.cpp.  This module implements all the Win32 APIs\nand C runtime functions that are called by the rest of the code, but are\nnot natively implemented on Windows CE.  Most all of this module is excluded\nfor NT native builds.\n\nTwo preprocessor defines are used in conjunction with several defines from\nthe Info-ZIP code and from other ports.  The two that are specific to the\nWindows CE port are:\n\n     POCKET_UNZIP   Always set for the Windows CE port (CE and NT).\n     _WIN32_WCE     Set for Windows CE native; not set for Windows NT native.\n\nThese three defines are the minimum defines that must be addressed by the\nproject file in order to build this port.  This port's main header, punzip.h,\ngets included by all the Info-ZIP source files when POCKET_UNZIP is defined.\npunzip.h in turn ensures that all the other relevant Info-ZIP defines are set\nto correctly build the port.  If you wish to alter the Info-ZIP defines used\nto build this port, you can do so by altering punzip.h.\n\nThere are quite a few _WIN32_WCE checks throughout the source files for this\nport.  These checks allow the application to build natively for Windows NT for\ndebugging purposes, and just because it can with little effort due to the\nsimilarities between the Windows CE API and the Windows NT API. Any non-Windows\nCE code is assumed to be for Windows NT only.  This project currently will not\nwork on Windows 95 because Windows CE is mostly UNICODE, and this port assumes\nthat all Win32 calls to the operating system take UNICODE parameters.  I could\nscatter a few dozen \"#ifdef UNICODE\" checks around and make it work on Windows\n95, but I see no reason to complicate this port's code for that reason since\nthere is already a Windows 95 port of the Info-ZIP code.\n\n_______________________________________________________________________________\n\n   Building the Windows CE Port (known as \"Pocket UnZip\")\n_______________________________________________________________________________\n\nAt the time this README was written, Microsoft just released Visual C++ for\nWindows CE version 1.0.  This development kit uses the the standard Microsoft\nVisual C++ version 5.0 or 6.0 development environment and project files\n(DSP files). To build Windows CE binaries of Pocket UnZip, you will need\nversion 1.0 or later of Visual C++ for Windows CE.\n\nThis port's project file, punzip.dsp, contains the information for building all\nthe various binaries.  These include Windows NT native, Windows CE native for\nHitachi SH-3 processors, and Windows CE native for MIPS processors.  All\nprojects have Debug and Retail flavors as well.  The following table lists the\nWindows CE devices and which binary they run:\n\n     Manufacturer             CPU             Binary\n     ---------------------    ------------    ------\n     Philips Electronics      MIPS R3910      MIPS\n     NEC Corp.                NEC VR4101      MIPS\n     Casio Computer Co.       Hitachi SH-3    SH-3\n     Compaq Computer Corp.    Hitachi SH-3    SH-3\n     Hewlett-Packard Co.      Hitachi SH-3    SH-3\n     Hitachi Ltd.             Hitachi SH-3    SH-3\n     LG Electronics Inc.      Hitachi SH-3    SH-3\n\nThe revision of this port made for UnZip 5.51 does now also provide a project\nfile for use with Microsoft's free \"Visual C++ embedded 3.0\" development system\nfor Windows CE.\n\nPocket UnZip should build out of the box.  If you have just unzipped the\nInfo-ZIP's UnZip sources, you should have a root directory with the core\nInfo-ZIP files in it and several subdirectories under it for the various\nports, one of which is the WinCE directory.  The project files punzip.dsp\nare located in the subdirectory vc5 resp. vc6 below the wince directory.\nOpen the punzip.dsp file from the subdirectory matching your Visual C++\nbase version.  The project file uses all the files in the WinCE\nsubdirectory as well as the following files in the Info-ZIP root:\n\n     api.c        crypt.h      globals.c    process.c    unzip.h\n     consts.h     ebcdic.h     globals.h    ttyio.c      unzpriv.h\n     crc32.c      explode.c    inflate.c    ttyio.h      unzvers.h\n     crc32.h      extract.c    inflate.h    unreduce.c   zip.h\n     crypt.c      fileio.c     list.c       unshrink.c\n\n_______________________________________________________________________________\n\n   Contacting the Authors\n_______________________________________________________________________________\n\nThe Info-ZIP group is made up of dozens of people, past and present, who\nhave devoted countless hours to providing the public with free and portable\ncompression software.  The author of the Windows CE port, Pocket UnZip, is\nSteve P. Miller.\n\nIf you have questions, comments, suggestions, or bug reports concerning Pocket\nUnZip itself, you can write Steve Miller at:\n\n     stevemil@pobox.com\n\nIf you find a bug that appears to be more Info-ZIP related (i.e. the actual\ndecompression part of Pocket UnZip), you can send mail to:\n\n     Zip-Bugs@lists.wku.edu\n\nFor all other general discussion type questions or comments, you can send mail\nto (as well as join) the following mailing list:\n\n     Info-Zip@lists.wku.edu\n\nSee the main UnZip README file for info on how to join the latter list.\n\n_______________________________________________________________________________\n\nBeginning with UnZip 5.51, the source distribution contains a second port for\nWinCE, providing a \"command line UnZip tool\" for batch processing on Windows CE\nsystems.\nThis port was contributed in September 2002 by:\n    Simon Roberts\n    IBM Global Services, EMEA\n    Phone: (INT 44- 2392 )(UK  02392 ) 563937: Tie-line(UK): 25-3937\n    Notes: Simon Roberts/UK/IBM@IBMGB\n    Internet: Simon_Roberts@uk.ibm.com\n\nThe tight integration of this contribution into the main UnZip distribution\ncode required some reorganization and was carried out by the UnZip maintenance\ncoordinator Christian Spieler.\n\nThe build of the Win CE command line program requires compiling\nand linking together the following source modules:\n\n    wince/wcemain.c             main entry point\n    unzip.c                     unzip command line interface\n    crc32.c                     CRC-32 calculation\n    crypt.c                     decryption support\n    extract.c                   general archive extraction handling\n    fileio.c                    internal I/O helper routines\n    globals.c                   global communication resources setup\n    list.c                      archive listing\n    match.c                     wildcard pattern matching\n    process.c                   general archives processing code\n    ttyio.c                     interactive console I/O\n    explode.c                   decompression for \"Imploded\" data (LZ77)\n    inflate.c                   decompression for \"Deflate\" methods\n    unreduce.c                  decompression for \"Reduced\" data\n    unshrink.c                  decompression for \"Shrunk\" data (LZW)\n    wince/intrface.cpp          WinCE specific UnZip code\n    wince/wince.cpp             WinCE specific C RTL lib replacements\n\nThese source modules depend on the following header files:\n\n    zip.h                       wrapper for unzip.h used by some modules\n    unzip.h                     main UnZip project header\n    unzpriv.h                   extended defines for project internals\n    globals.h                   global resource structures\n    wince/wcecfg.h              Windows CE specific configuration\n    wince/wince.h               WinCE C(++) library roundups\n\n    consts.h                    global constant data\n    crc32.h                     CRC-32 calculation interface\n    crypt.h                     decryption interface\n    ebcdic.h                    ASCII <--> EBCDIC translation\n    ttyio.h                     console I/O interface\n    unzvers.h                   version/release information\n    wince/intrface.h            public entities in wince/intrface.cpp\n\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/inc/conio.h",
    "content": ""
  },
  {
    "path": "deps/infozip/unzip60/wince/inc/errno.h",
    "content": ""
  },
  {
    "path": "deps/infozip/unzip60/wince/inc/locale.h",
    "content": ""
  },
  {
    "path": "deps/infozip/unzip60/wince/inc/signal.h",
    "content": ""
  },
  {
    "path": "deps/infozip/unzip60/wince/inc/stdio.h",
    "content": ""
  },
  {
    "path": "deps/infozip/unzip60/wince/intrface.cpp",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        INTRFACE.CPP\n//\n// Description: This module acts as the interface between the Info-ZIP code and\n//              our Windows code in WINMAIN.CPP.  We expose the needed\n//              functions to query a file list, test file(s), extract file(s),\n//              and display a zip file comment.  The windows code is never\n//              bothered with understanding the Globals structure \"Uz_Globs\".\n//\n//              This module also catches all the callbacks from the Info-ZIP\n//              code, cleans up the data provided in the callback, and then\n//              forwards the information to the appropriate function in the\n//              windows code.  These callbacks include status messages, file\n//              lists, comments, password prompt, and file overwrite prompts.\n//\n//              Finally, this module implements the few functions that the\n//              Info-ZIP code expects the port to implement. These functions are\n//              OS dependent and are mostly related to validating file names and\n//              directories, and setting file attributes and dates of saved files.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  As of June 1999, Steve P. Miller has agreed to apply\n//              the Info-ZIP License (see citation on top of this module)\n//              to his work.  See the contents of this License for terms\n//              and conditon of using the product \"Pocket UnZip\".\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com or the Info-ZIP\n//              mailing list Zip-Bugs@lists.wku.edu.\n//\n// Functions:   DoListFiles\n//              DoExtractOrTestFiles\n//              DoGetComment\n//              SetExtractToDirectory\n//              InitGlobals\n//              FreeGlobals\n//              ExtractOrTestFilesThread\n//              IsFileOrDirectory\n//              SmartCreateDirectory\n//              CheckForAbort2\n//              SetCurrentFile\n//              UzpMessagePrnt2\n//              UzpInput2\n//              UzpMorePause\n//              UzpPassword\n//              UzpReplace\n//              UzpSound\n//              SendAppMsg\n//              win_fprintf\n//              test_NT\n//              utimeToFileTime\n//              GetFileTimes\n//              IsOldFileSystem\n//              SetFileSize\n//              close_outfile\n//              do_wild\n//              mapattr\n//              mapname\n//              checkdir\n//              match\n//              iswild\n//              conv_to_rule\n//              GetPlatformLocalTimezone\n//              wide_to_local_string\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n// 08/01/99  Johnny Lee, Christian Spieler, Steve Miller, and others\n//                         Adapted to UnZip 5.41 (Version 1.1)\n// 12/01/02  Chr. Spieler  Updated interface for UnZip 5.50\n// 02/23/05  Chr. Spieler  Modified and optimized utimeToFileTime() to support\n//                         the NO_W32TIMES_IZFIX compilation option\n// 11/01/09  Chr. Spieler  Added wide_to_local_string() conversion function\n//                         from win32.c, which is currently needed for the\n//                         new UTF-8 names support (until we manage to port\n//                         the complete UnZip code to native wide-char support).\n//\n//*****************************************************************************\n\n\n//*****************************************************************************\n// The following information and structure are here just for reference\n//*****************************************************************************\n//\n// The Windows CE version of Unzip builds with the following defines set:\n//\n//\n//    WIN32\n//    _WINDOWS\n//    UNICODE\n//    _UNICODE\n//    WIN32_LEAN_AND_MEAN\n//    STRICT\n//\n//    POCKET_UNZIP         (Main define - Always set)\n//\n//    UNZIP_INTERNAL\n//    WINDLL\n//    DLL\n//    REENTRANT\n//    USE_EF_UT_TIME\n//    NO_ZIPINFO\n//    NO_STDDEF_H\n//    NO_NTSD_EAS\n//\n//    USE_SMITH_CODE       (optional - See INSTALL document)\n//    LZW_CLEAN            (optional - See INSTALL document)\n//    NO_W32TIMES_IZFIX    (optional - See INSTALL document)\n//\n//    DEBUG                (When building for Debug)\n//    _DEBUG               (When building for Debug)\n//    NDEBUG               (When building for Retail)\n//    _NDEBUG              (When building for Retail)\n//\n//    _WIN32_WCE=100       (When building for Windows CE native)\n//\n//****************************************************************************/\n\nextern \"C\" {\n#define __INTRFACE_CPP__\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n#include \"crypt.h\"     // Needed to pick up CRYPT define\n#include <commctrl.h>\n#include \"intrface.h\"\n#include \"winmain.h\"\n\n#ifndef _WIN32_WCE\n#include <process.h>   // _beginthreadex() and _endthreadex()\n#endif\n\n}\n#include <tchar.h> // Must be outside of extern \"C\" block\n\n#ifdef POCKET_UNZIP\n\n//******************************************************************************\n//***** \"Local\" Global Variables\n//******************************************************************************\n\nstatic USERFUNCTIONS  g_uf;\nstatic EXTRACT_INFO  *g_pExtractInfo = NULL;\nstatic FILE_NODE     *g_pFileLast    = NULL;\nstatic CHAR           g_szExtractToDirectory[_MAX_PATH];\nstatic BOOL           g_fOutOfMemory;\n\n//******************************************************************************\n//***** Local Function Prototypes\n//******************************************************************************\n\n// Internal functions of the GUI interface.\nstatic Uz_Globs* InitGlobals(LPCSTR szZipFile);\nstatic void FreeGlobals(Uz_Globs *pG);\n\n#ifdef _WIN32_WCE\nstatic DWORD WINAPI ExtractOrTestFilesThread(LPVOID lpv);\n#else\nstatic unsigned __stdcall ExtractOrTestFilesThread(void *lpv);\n#endif\n\nstatic void SetCurrentFile(__GPRO);\n\n#endif // POCKET_UNZIP\n\n// Internal helper functions for the UnZip core.\nstatic int IsFileOrDirectory(LPCTSTR szPath);\nstatic BOOL SmartCreateDirectory(__GPRO__ LPCSTR szDirectory, BOOL *pNewDir);\nstatic void utimeToFileTime(time_t ut, FILETIME *pft, BOOL fOldFileSystem);\nstatic int GetFileTimes(Uz_Globs *pG, FILETIME *pftCreated,\n                        FILETIME *pftAccessed, FILETIME *pftModified);\n\n// Check for FAT, VFAT, HPFS, etc.\nstatic BOOL IsOldFileSystem(char *szPath);\n\n#ifdef POCKET_UNZIP\n\nextern \"C\" {\n\n// Local variants of callbacks from Info-ZIP code.\n// (These functions are not referenced by name outside this source module.)\nint UZ_EXP UzpMessagePrnt2(zvoid *pG, uch *buffer, ulg size, int flag);\nint UZ_EXP UzpInput2(zvoid *pG, uch *buffer, int *size, int flag);\nint UZ_EXP CheckForAbort2(zvoid *pG, int fnflag, ZCONST char *zfn,\n                          ZCONST char *efn, ZCONST zvoid *details);\nint WINAPI UzpReplace(LPSTR szFile, unsigned nbufsiz);\nvoid WINAPI UzpSound(void);\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI SendAppMsg(z_uint8 uzSize, z_uint8 uzCompressedSize,\n#else\nvoid WINAPI SendAppMsg(ulg uzSize, ulg uzCompressedSize,\n#endif\n                       unsigned ratio,\n                       unsigned month, unsigned day, unsigned year,\n                       unsigned hour, unsigned minute, char uppercase,\n                       LPCSTR szPath, LPCSTR szMethod, ulg dwCRC,\n                       char chCrypt);\n\n} // extern \"C\"\n\n\n//******************************************************************************\n//***** Our exposed interface functions to the Info-ZIP core\n//******************************************************************************\n\nint DoListFiles(LPCSTR szZipFile) {\n\n   int result;\n\n   // Create our Globals struct and fill it in whith some default values.\n   Uz_Globs *pG = InitGlobals(szZipFile);\n   if (!pG) {\n      return PK_MEM;\n   }\n\n   pG->UzO.vflag = 1; // verbosely: list directory (for WIN32 it is 0 or 1)\n   pG->process_all_files = TRUE; // improves speed\n\n   g_pFileLast = NULL;\n   g_fOutOfMemory = FALSE;\n\n   // We wrap some exception handling around the entire Info-ZIP engine to be\n   // safe.  Since we are running on a device with tight memory configurations,\n   // all sorts of problems can arise when we run out of memory.\n   __try {\n\n      // Call the unzip routine.  We will catch the file information in a\n      // callback to SendAppMsg().\n      result = process_zipfiles(pG);\n\n      // Make sure we didn't run out of memory in the process.\n      if (g_fOutOfMemory) {\n         result = PK_MEM;\n      }\n\n   } __except(EXCEPTION_EXECUTE_HANDLER) {\n\n      // Catch any exception here.\n      DebugOut(TEXT(\"Exception 0x%08X occurred in DoListFiles()\"),\n               GetExceptionCode());\n      result = PK_EXCEPTION;\n   }\n\n   g_pFileLast = NULL;\n\n   // It is possible that the ZIP engine change the file name a bit (like adding\n   // a \".zip\" if needed).  If so, we will pick up the new name.\n   if ((result != PK_EXCEPTION) && pG->zipfn && *pG->zipfn) {\n      strcpy(g_szZipFile, pG->zipfn);\n   }\n\n   // Free our globals.\n   FreeGlobals(pG);\n\n   return result;\n}\n\n//******************************************************************************\nBOOL DoExtractOrTestFiles(LPCSTR szZipFile, EXTRACT_INFO *pei) {\n\n   // WARNING!!!  This functions hands the EXTRACT_INFO structure of to a thread\n   // to perform the actual extraction/test.  When the thread is done, it will\n   // send a message to the progress dialog.  The calling function must not\n   // delete the EXTRACT_INFO structure until it receives the message.  Currently,\n   // this is not a problem for us since the structure lives on the stack of the\n   // calling thread.  The calling thread then displays a dialog that blocks the\n   // calling thread from clearing the stack until the dialog is dismissed, which\n   // occurs when the dialog receives the message.\n\n   // Create our globals so we can store the file name.\n   Uz_Globs *pG = InitGlobals(szZipFile);\n   if (!pG) {\n      pei->result = PK_MEM;\n      SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE, (LPARAM)pei);\n      return FALSE;\n   }\n\n   // Store a global pointer to the Extract structure so it can be reached from\n   // our thread and callback functions.\n   g_pExtractInfo = pei;\n\n   // Spawn our thread\n   DWORD dwThreadId;\n   HANDLE hThread;\n\n#ifdef _WIN32_WCE\n\n   // On CE, we use good old CreateThread() since the WinCE CRT does not\n   // allocate per-thread storage.\n   hThread = CreateThread(NULL, 0, ExtractOrTestFilesThread, pG, 0,\n                          &dwThreadId);\n\n#else\n\n   // On NT, we need use the CRT's thread function so that we don't leak any\n   // CRT allocated memory when the thread exits.\n   hThread = (HANDLE)_beginthreadex(NULL, 0, ExtractOrTestFilesThread, pG, 0,\n                                    (unsigned*)&dwThreadId);\n\n#endif\n\n   // Bail out if our thread failed to create.\n   if (!hThread) {\n\n      DebugOut(TEXT(\"CreateThread() failed [%u]\"), GetLastError());\n\n      // Set our error as a memory error.\n      g_pExtractInfo->result = PK_MEM;\n\n      // Free our globals.\n      FreeGlobals(pG);\n\n      // Tell the progress dialog that we are done.\n      SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE, (LPARAM)pei);\n\n      g_pExtractInfo = NULL;\n      return FALSE;\n   }\n\n   // Close our thread handle since we have no use for it.\n   CloseHandle(hThread);\n   return TRUE;\n}\n\n//******************************************************************************\nint DoGetComment(LPCSTR szZipFile) {\n\n   int result;\n\n   // Create our Globals struct and fill it in with some default values.\n   Uz_Globs *pG = InitGlobals(szZipFile);\n   if (!pG) {\n      return PK_MEM;\n   }\n\n   pG->UzO.zflag = TRUE; // display the zipfile comment\n\n   // We wrap some exception handling around the entire Info-ZIP engine to be\n   // safe.  Since we are running on a device with tight memory configurations,\n   // all sorts of problems can arise when we run out of memory.\n   __try {\n\n      // Call the unzip routine.  We will catch the comment string in a callback\n      // to win_fprintf().\n      result = process_zipfiles(pG);\n\n   } __except(EXCEPTION_EXECUTE_HANDLER) {\n\n      // Catch any exception here.\n      DebugOut(TEXT(\"Exception 0x%08X occurred in DoGetComment()\"),\n               GetExceptionCode());\n      result = PK_EXCEPTION;\n   }\n\n   // Free our globals.\n   FreeGlobals(pG);\n\n   return result;\n}\n\n//******************************************************************************\nBOOL SetExtractToDirectory(LPTSTR szDirectory) {\n\n   BOOL fNeedToAddWack = FALSE;\n\n   // Remove any trailing wack from the path.\n   int length = _tcslen(szDirectory);\n   if ((length > 0) && (szDirectory[length - 1] == TEXT('\\\\'))) {\n      szDirectory[--length] = TEXT('\\0');\n      fNeedToAddWack = TRUE;\n   }\n\n#ifndef _WIN32_WCE\n\n   // Check to see if a root directory was specified.\n   if ((length == 2) && isalpha(szDirectory[0]) && (szDirectory[1] == ':')) {\n\n      // If just a root is specified, we need to only verify the drive letter.\n      if (!(GetLogicalDrives() & (1 << (tolower(szDirectory[0]) - (int)'a')))) {\n\n         // This drive does not exist.  Bail out with a failure.\n         return FALSE;\n      }\n\n   } else\n\n#endif\n\n   // We only verify path if length is >0 since we know \"\\\" is valid.\n   if (length > 0) {\n\n      // Verify the the path exists and that it is a directory.\n      if (IsFileOrDirectory(szDirectory) != 2) {\n         return FALSE;\n      }\n   }\n\n   // Store the directory for when we do an extract.\n   TSTRTOMBS(g_szExtractToDirectory, szDirectory, countof(g_szExtractToDirectory));\n\n   // We always want a wack at the end of our path.\n   strcat(g_szExtractToDirectory, \"\\\\\");\n\n   // Add the wack back to the end of the path.\n   if (fNeedToAddWack) {\n      _tcscat(szDirectory, TEXT(\"\\\\\"));\n   }\n\n   return TRUE;\n}\n\n//******************************************************************************\n//***** Internal functions\n//******************************************************************************\n\nstatic Uz_Globs* InitGlobals(LPCSTR szZipFile)\n{\n   // Create our global structure - pG\n   CONSTRUCTGLOBALS();\n\n   // Bail out if we failed to allocate our Globals structure.\n   if (!pG) {\n      return NULL;\n   }\n\n   // Clear our USERFUNCTIONS structure\n   ZeroMemory(&g_uf, sizeof(g_uf));\n\n   // Initialize a global pointer to our USERFUNCTIONS structure that is\n   // used by WINMAIN.CPP to access it (without using the pG construction).\n   lpUserFunctions = &g_uf;\n\n   // Store a global pointer to our USERFUNCTIONS structure in pG so that\n   // the generic Info-ZIP code LIST.C and PROCESS.C can access it.\n   pG->lpUserFunctions = &g_uf;\n\n   // Fill in all our callback functions.\n   pG->message      = UzpMessagePrnt2;\n   pG->input        = UzpInput2;\n   pG->mpause       = UzpMorePause;\n   pG->statreportcb = CheckForAbort2;\n   pG->lpUserFunctions->replace                = UzpReplace;\n   pG->lpUserFunctions->sound                  = UzpSound;\n   pG->lpUserFunctions->SendApplicationMessage = SendAppMsg;\n   pG->lpUserFunctions->SendApplicationMessage_i32 = NULL;\n\n#if CRYPT\n   pG->decr_passwd = UzpPassword;\n#endif\n\n   // Match filenames case-sensitively.  We can do this since we can guarantee\n   // exact case because the user can only select files via our UI.\n   pG->UzO.C_flag = FALSE;\n\n   // Allocate and store the ZIP file name in pG->zipfn\n   if (!(pG->zipfnPtr = new char[FILNAMSIZ])) {\n      FreeGlobals(pG);\n      return NULL;\n   }\n   pG->zipfn = pG->zipfnPtr;\n   strcpy(pG->zipfn, szZipFile);\n\n   // Allocate and store the ZIP file name in pG->zipfn.  This needs to done\n   // so that do_wild() does not wind up clearing out the zip file name when\n   // it returns in process.c\n   if (!(pG->wildzipfnPtr = new char[FILNAMSIZ])) {\n      FreeGlobals(pG);\n      return NULL;\n   }\n   pG->wildzipfn = pG->wildzipfnPtr;\n   strcpy(pG->wildzipfn, szZipFile);\n\n   return pG;\n}\n\n//******************************************************************************\nstatic void FreeGlobals(Uz_Globs *pG)\n{\n   // Free our ZIP file name\n   if (pG->zipfnPtr) {\n      delete[] pG->zipfnPtr;\n      pG->zipfnPtr = pG->zipfn = NULL;\n   }\n\n   // Free our wild name buffer\n   if (pG->wildzipfnPtr) {\n      delete[] pG->wildzipfnPtr;\n      pG->wildzipfnPtr = pG->wildzipfn = NULL;\n   }\n\n   // Free everything else.\n   DESTROYGLOBALS();\n}\n\n//******************************************************************************\n#ifdef _WIN32_WCE\n\n// On WinCE, we declare our thread function the way CreateThread() likes it.\nstatic DWORD WINAPI ExtractOrTestFilesThread(LPVOID lpv)\n\n#else\n\n// On WinNT, we declare our thread function the way _beginthreadex likes it.\nstatic unsigned __stdcall ExtractOrTestFilesThread(void *lpv)\n\n#endif\n{\n   Uz_Globs *pG = (Uz_Globs*)lpv;\n\n   if (g_pExtractInfo->fExtract) {\n\n      pG->extract_flag = TRUE;\n\n      switch (g_pExtractInfo->overwriteMode) {\n\n         case OM_NEWER:         // Update (extract only newer/brand-new files)\n            pG->UzO.uflag = TRUE;\n            break;\n\n         case OM_ALWAYS:        // OK to overwrite files without prompting\n            pG->UzO.overwrite_all = TRUE;\n            break;\n\n         case OM_NEVER:         // Never overwrite files (no prompting)\n            pG->UzO.overwrite_none = TRUE;\n            break;\n\n         default:               // Force a prompt\n            pG->UzO.overwrite_all = FALSE;\n            pG->UzO.overwrite_none = FALSE;\n            pG->UzO.uflag = FALSE;\n            break;\n      }\n\n      // Throw away paths if requested.\n      pG->UzO.jflag = !g_pExtractInfo->fRestorePaths;\n\n   } else {\n      pG->UzO.tflag = TRUE;\n   }\n\n   if (g_pExtractInfo->szFileList) {\n      pG->filespecs = g_pExtractInfo->dwFileCount;\n      pG->pfnames = g_pExtractInfo->szFileList;\n   } else {\n      // Improves performance if all files are being extracted.\n      pG->process_all_files = TRUE;\n   }\n\n   // Invalidate our file offset to show that we are starting a new operation.\n   g_pExtractInfo->uzFileOffset = ~(zusz_t)0;\n\n   // We wrap some exception handling around the entire Info-ZIP engine to be\n   // safe.  Since we are running on a device with tight memory configurations,\n   // all sorts of problems can arise when we run out of memory.\n   __try {\n\n      // Put a jump marker on our stack so the user can abort.\n      int error = setjmp(dll_error_return);\n\n      // If setjmp() returns 0, then we just set our jump marker and we can\n      // continue with the operation.  If setjmp() returned something else,\n      // then we reached this point because the operation was aborted and\n      // set our instruction pointer back here.\n\n      if (error > 0) {\n         // We already called process_zipfiles() and were thrown back here.\n         g_pExtractInfo->result = (error == 1) ? PK_BADERR : error;\n\n      } else {\n         // Entering Info-ZIP... close your eyes.\n         g_pExtractInfo->result = process_zipfiles(pG);\n      }\n\n   } __except(EXCEPTION_EXECUTE_HANDLER) {\n\n      // Catch any exception here.\n      DebugOut(TEXT(\"Exception 0x%08X occurred in ExtractOrTestFilesThread()\"),\n               GetExceptionCode());\n      g_pExtractInfo->result = PK_EXCEPTION;\n   }\n\n   // Free our globals.\n   FreeGlobals(pG);\n\n   // Tell the progress dialog that we are done.\n   SendMessage(g_hDlgProgress, WM_PRIVATE, MSG_OPERATION_COMPLETE,\n               (LPARAM)g_pExtractInfo);\n\n   // Clear our global pointer as we are done with it.\n   g_pExtractInfo = NULL;\n\n#ifndef _WIN32_WCE\n   // On NT, we need to free any CRT allocated memory.\n   _endthreadex(0);\n#endif\n\n   return 0;\n}\n\n//******************************************************************************\nstatic void SetCurrentFile(__GPRO)\n{\n   // Reset all our counters as we about to process a new file.\n   g_pExtractInfo->uzFileOffset = (zusz_t)G.pInfo->offset;\n   g_pExtractInfo->dwFile++;\n   g_pExtractInfo->uzBytesWrittenThisFile = 0;\n   g_pExtractInfo->uzBytesWrittenPreviousFiles += g_pExtractInfo->uzBytesTotalThisFile;\n   g_pExtractInfo->uzBytesTotalThisFile = G.lrec.ucsize;\n   g_pExtractInfo->szFile = G.filename;\n   g_pExtractInfo->fNewLineOfText = TRUE;\n\n   // Pass control to our GUI thread to do a full update our progress dialog.\n   SendMessage(g_hWndMain, WM_PRIVATE, MSG_UPDATE_PROGRESS_COMPLETE,\n               (LPARAM)g_pExtractInfo);\n\n   // Check our abort flag.\n}\n#endif // POCKET_UNZIP\n\n//******************************************************************************\nstatic int IsFileOrDirectory(LPCTSTR szPath)\n{\n   // Geth the attributes of the item.\n   DWORD dwAttribs = GetFileAttributes(szPath);\n\n   // Bail out now if we could not find the path at all.\n   if (dwAttribs == 0xFFFFFFFF) {\n      return 0;\n   }\n\n   // Return 1 for file and 2 for directory.\n   return ((dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 1);\n}\n\n//******************************************************************************\nstatic BOOL SmartCreateDirectory(__GPRO__ LPCSTR szDirectory, BOOL *pNewDir)\n{\n   // Copy path to a UNICODE buffer.\n   TCHAR szBuffer[_MAX_PATH];\n   MBSTOTSTR(szBuffer, szDirectory, countof(szBuffer));\n\n   switch (IsFileOrDirectory(szBuffer)) {\n      case 0:\n         // Create the directory if it does not exist.\n         if (!CreateDirectory(szBuffer, NULL)) {\n            Info(slide, 1, ((char *)slide, \"error creating directory: %s\\n\",\n              FnFilter1( szDirectory)));\n            return FALSE;\n         }\n         if (pNewDir != NULL) *pNewDir = TRUE;\n         break;\n\n      case 1:\n         // If there is a file with the same name, then display an error.\n         Info(slide, 1, ((char *)slide,\n              \"cannot create %s as a file with same name already exists.\\n\",\n              FnFilter1(szDirectory)));\n         return FALSE;\n   }\n\n   // If the directory already exists or was created, then return success.\n   return TRUE;\n}\n\n\n#ifdef POCKET_UNZIP\n//******************************************************************************\n//***** Callbacks from Info-ZIP code.\n//******************************************************************************\n\nint UZ_EXP UzpMessagePrnt2(zvoid *pG, uch *buffer, ulg size, int flag)\n{\n\n   // Some ZIP files cause us to get called during DoListFiles(). We only handle\n   // messages while processing DoExtractFiles().\n   if (!g_pExtractInfo) {\n      if (g_hWndEdit) {\n         SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,\n                     (LPARAM)buffer);\n      } else {\n#ifdef UNICODE\n         DebugOut(TEXT(\"Unhandled call to UzpMessagePrnt2(\\\"%S\\\")\"), buffer);\n#else\n         DebugOut(TEXT(\"Unhandled call to UzpMessagePrnt2(\\\"%s\\\")\"), buffer);\n#endif\n      }\n      return 0;\n   }\n\n   // When extracting, mapname() will get called for every file which in turn\n   // will call SetCurrentFile().  For testing though, mapname() never gets\n   // called so we need to be on the lookout for a new file.\n   if (g_pExtractInfo->uzFileOffset != (zusz_t)((Uz_Globs*)pG)->pInfo->offset) {\n      SetCurrentFile((Uz_Globs*)pG);\n   }\n\n   // Make sure this message was intended for us to display.\n   if (!MSG_NO_WGUI(flag) && !MSG_NO_WDLL(flag)) {\n\n      // Insert a leading newline if requested to do so.\n      if (MSG_LNEWLN(flag) && !g_pExtractInfo->fNewLineOfText) {\n         SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)\"\\n\");\n         g_pExtractInfo->fNewLineOfText = TRUE;\n      }\n\n      // Since we use a proportional font, we need to do a little cleanup of the\n      // text we are passed since it assumes a fixed font and adds padding to try\n      // to line things up.  We remove leading whitespace on any new line of text.\n      if (g_pExtractInfo->fNewLineOfText) {\n         while (*buffer == ' ') {\n            buffer++;\n         }\n      }\n\n      // We always remove trailing whitespace.\n      LPSTR psz = (LPSTR)buffer;\n      LPSTR pszn;\n      while ((pszn = MBSCHR(psz, ' ')) != NULL) {\n         for (psz = pszn+1; *psz == ' '; psz++);\n         if (*psz == '\\0') {\n            *pszn = '\\0';\n            break;\n         }\n      }\n\n\n      // Determine if the next line of text will be a new line of text.\n      g_pExtractInfo->fNewLineOfText = ((*psz == '\\r') || (*psz == '\\n'));\n\n      // Change all forward slashes to back slashes in the buffer\n      ForwardSlashesToBackSlashesA((LPSTR)buffer);\n\n      // Add the cleaned-up text to our extraction log edit control.\n      SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)buffer);\n\n      // Append a trailing newline if requested to do so.\n      if (MSG_TNEWLN(flag) || MSG_MNEWLN(flag) && !g_pExtractInfo->fNewLineOfText) {\n         SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)\"\\n\");\n         g_pExtractInfo->fNewLineOfText = TRUE;\n      }\n   }\n\n   return 0;\n}\n\n//******************************************************************************\nint UZ_EXP UzpInput2(zvoid *pG, uch *buffer, int *size, int flag)\n{\n   DebugOut(TEXT(\"WARNING: UzpInput2(...) called\"));\n   return 0;\n}\n\n//******************************************************************************\nvoid UZ_EXP UzpMorePause(zvoid *pG, const char *szPrompt, int flag)\n{\n   DebugOut(TEXT(\"WARNING: UzpMorePause(...) called\"));\n}\n\n//******************************************************************************\nint UZ_EXP UzpPassword(zvoid *pG, int *pcRetry, char *szPassword, int nSize,\n                       const char *szZipFile, const char *szFile)\n{\n   // Return Values:\n   //    IZ_PW_ENTERED    got some PWD string, use/try it\n   //    IZ_PW_CANCEL     no password available (for this entry)\n   //    IZ_PW_CANCELALL  no password, skip any further PWD request\n   //    IZ_PW_ERROR      failure (no mem, no tty, ...)\n\n#if CRYPT\n\n   // Build the data structure for our dialog.\n   DECRYPT_INFO di;\n   di.retry      = *pcRetry;\n   di.szPassword = szPassword;\n   di.nSize      = nSize;\n   di.szFile     = szFile;\n\n   // Clear the password to be safe.\n   *di.szPassword = '\\0';\n\n   // On our first call for a file, *pcRetry == 0.  If we would like to allow\n   // for retries, then we set the value of *pcRetry to the number of retries we\n   // are willing to allow.  We will be recalled as neccessary, each time with\n   // *pcRetry being decremented once.  1 is the last retry we will get.\n   *pcRetry = (*pcRetry == 0) ? MAX_PASSWORD_RETRIES : (*pcRetry - 1);\n\n   // Pass control to our GUI thread which will prompt the user for a password.\n   return SendMessage(g_hWndMain, WM_PRIVATE, MSG_PROMPT_FOR_PASSWORD, (LPARAM)&di);\n\n#else\n   return IZ_PW_CANCELALL;\n#endif\n}\n\n//******************************************************************************\nint UZ_EXP CheckForAbort2(zvoid *pG, int fnflag, ZCONST char *zfn,\n                    ZCONST char *efn, ZCONST zvoid *details)\n{\n   int rval = UZ_ST_CONTINUE;\n\n   if (g_pExtractInfo->fAbort) {\n\n      // Add a newline to our log if we are in the middle of a line of text.\n      if (!g_pExtractInfo->fNewLineOfText) {\n         SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)\"\\n\");\n      }\n\n      // Make sure whatever file we are currently processing gets closed.\n      if (((int)((Uz_Globs *)pG)->outfile != 0) &&\n          ((int)((Uz_Globs *)pG)->outfile != -1)) {\n         if (g_pExtractInfo->fExtract && *efn) {\n\n            // Make sure the user is aware that this file is screwed.\n            SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,\n                        (LPARAM)\"warning: \");\n            SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,\n                        (LPARAM)efn);\n            SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,\n                        (LPARAM)\" is probably truncated.\\n\");\n         }\n      }\n\n      // Display an aborted message in the log\n      SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT,\n                  (LPARAM)\"Operation aborted by user.\\n\");\n\n      // Signal \"Immediate Cancel\" back to the UnZip engine.\n      rval = UZ_ST_BREAK;\n   }\n\n   return rval;\n}\n\n//******************************************************************************\nint WINAPI UzpReplace(LPSTR szFile, unsigned nbufsiz) {\n   // Pass control to our GUI thread which will prompt the user to overwrite.\n   // The nbufsiz parameter is not needed here, because this program does not\n   // (yet?) contain support for renaming the extraction target.\n   return SendMessage(g_hWndMain, WM_PRIVATE, MSG_PROMPT_TO_REPLACE,\n                      (LPARAM)szFile);\n}\n\n//******************************************************************************\nvoid WINAPI UzpSound(void) {\n   // Do nothing.\n}\n\n//******************************************************************************\n// Called from LIST.C\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI SendAppMsg(z_uint8 uzSize, z_uint8 uzCompressedSize,\n#else\nvoid WINAPI SendAppMsg(ulg uzSize, ulg uzCompressedSize,\n#endif\n                       unsigned ratio,\n                       unsigned month, unsigned day, unsigned year,\n                       unsigned hour, unsigned minute, char uppercase,\n                       LPCSTR szPath, LPCSTR szMethod, ulg dwCRC,\n                       char chCrypt)\n{\n   // If we are out of memory, then just bail since we will only make things worse.\n   if (g_fOutOfMemory) {\n      return;\n   }\n\n   // We get our Globals structure.\n   GETGLOBALS();\n\n   // Allocate a FILE_NODE large enough to hold this file.\n   int length = strlen(szPath) + strlen(szMethod);\n   g_pFileLast = (FILE_NODE*)new BYTE[sizeof(FILE_NODE) +\n                                      (sizeof(CHAR) * length)];\n\n   // Bail out if we failed to allocate the node.\n   if (!g_pFileLast) {\n#ifdef UNICODE\n      DebugOut(TEXT(\"Failed to create a FILE_NODE for \\\"%S\\\".\"), szPath);\n#else\n      DebugOut(TEXT(\"Failed to create a FILE_NODE for \\\"%s\\\".\"), szPath);\n#endif\n      g_fOutOfMemory = TRUE;\n      return;\n   }\n\n   // Fill in our node.\n   g_pFileLast->uzSize           = (zusz_t)uzSize;\n   g_pFileLast->uzCompressedSize = (zusz_t)uzCompressedSize;\n   g_pFileLast->dwCRC            = dwCRC;\n   g_pFileLast->szComment        = NULL;\n   g_pFileLast->szType           = NULL;\n\n   // Fix the year value to contain the real year.\n   year += 1900;\n\n   // Year:   0 - 4095 (12) 1111 1111 1111 0000 0000 0000 0000 0000 (0xFFF00000)\n   // Month:  1 -   12 ( 4) 0000 0000 0000 1111 0000 0000 0000 0000 (0x000F0000)\n   // Day:    1 -   31 ( 5) 0000 0000 0000 0000 1111 1000 0000 0000 (0x0000F800)\n   // Hour:   0 -   23 ( 5) 0000 0000 0000 0000 0000 0111 1100 0000 (0x000007C0)\n   // Minute: 0 -   59 ( 6) 0000 0000 0000 0000 0000 0000 0011 1111 (0x0000003F)\n\n   // Do some bit shifting to make the date and time fit in a DWORD.\n   g_pFileLast->dwModified = (((DWORD)(year   & 0x0FFF) << 20) |\n                              ((DWORD)(month  & 0x000F) << 16) |\n                              ((DWORD)(day    & 0x001F) << 11) |\n                              ((DWORD)(hour   & 0x001F) <<  6) |\n                              ((DWORD)(minute & 0x003F)));\n\n   // We need to get our globals structure to determine our attributes and\n   // encryption information.\n   g_pFileLast->dwAttributes = (pG->crec.external_file_attributes & 0xFF);\n   if (chCrypt == 'E') {\n      g_pFileLast->dwAttributes |= ZFILE_ATTRIBUTE_ENCRYPTED;\n   }\n\n   // Store the path and method in our string buffer.\n   strcpy(g_pFileLast->szPathAndMethod, szPath);\n   strcpy(g_pFileLast->szPathAndMethod + strlen(szPath) + 1, szMethod);\n\n   // Pass the file object to our windows code to have it added to our list.\n   AddFileToListView(g_pFileLast);\n}\n\n//******************************************************************************\nint win_fprintf(zvoid *pG, FILE *file, unsigned int dwCount, char far *buffer)\n{\n\n   // win_fprintf() is used within Info-ZIP to write to a file as well as log\n   // information.  If the \"file\" is a real file handle (not stdout or stderr),\n   // then we write the data to the file and return.\n\n   if ((file != stdout) && (file != stderr)) {\n\n      DWORD dwBytesWritten = 0;\n#if (defined(_WIN32_WCE) && (_WIN32_WCE < 211))\n      // On WinCE all FILEs are really HANDLEs.  See WINCE.CPP for more info.\n      WriteFile((HANDLE)file, buffer, dwCount, &dwBytesWritten, NULL);\n#else\n      dwBytesWritten = fwrite(buffer, 1, dwCount, file);\n#endif\n\n      // Update our bytes written count.\n      g_pExtractInfo->uzBytesWrittenThisFile += dwBytesWritten;\n\n      // Pass control to our GUI thread to do a partial update our progress dialog.\n      SendMessage(g_hWndMain, WM_PRIVATE, MSG_UPDATE_PROGRESS_PARTIAL,\n                  (LPARAM)g_pExtractInfo);\n\n      return dwBytesWritten;\n   }\n\n   // Check to see if we are expecting a extraction progress string\n   if (g_pExtractInfo) {\n\n      // Most of our progress strings come to our UzpMessagePrnt2() callback,\n      // but we occasionally get one here.  We will just forward it to\n      // UzpMessagePrnt2() as if it never came here.\n      UzpMessagePrnt2(pG, (uch*)buffer, dwCount, 0);\n      return dwCount;\n   }\n\n   // Check to see if we are expecting a zip file comment string.\n   if (g_hWndEdit) {\n\n      // Change all forward slashes to back slashes in the buffer\n      ForwardSlashesToBackSlashesA((LPSTR)buffer);\n\n      SendMessage(g_hWndMain, WM_PRIVATE, MSG_ADD_TEXT_TO_EDIT, (LPARAM)buffer);\n      return dwCount;\n   }\n\n   // Check to see if we are expecting a compressed file comment string.\n   if (g_pFileLast) {\n      char *p1, *p2;\n\n      // Calcalute the size of the buffer we will need to store this comment.\n      // We are going to convert all ASC values 0 - 31 (except tab, new line,\n      // and CR) to ^char.\n      int size = 1;\n      for (p1 = buffer; *p1; INCSTR(p1)) {\n         size += ((*p1 >= 32) || (*p1 == '\\t') ||\n                  (*p1 == '\\r') || (*p1 == '\\n')) ? CLEN(p1) : 2;\n      }\n\n      // Allocate a comment buffer and assign it to the last file node we saw.\n      if (g_pFileLast->szComment = new CHAR[size]) {\n\n         // Copy while formatting.\n         for (p1 = buffer, p2 = (char*)g_pFileLast->szComment; *p1; INCSTR(p1)) {\n            if ((*p1 >= 32) || (*p1 == '\\t') ||\n                (*p1 == '\\r') || (*p1 == '\\n')) {\n               memcpy(p2, p1, CLEN(p1));\n               p2 += CLEN(p1);\n            } else {\n               *(p2++) = '^';\n               *(p2++) = 64 + *p1;\n            }\n         }\n         *p2 = '\\0';\n      }\n\n      // Update the attributes of the file node to include the comment attribute.\n      g_pFileLast->dwAttributes |= ZFILE_ATTRIBUTE_COMMENT;\n\n      // Clear the file node so we don't try to add another bogus comment to it.\n      g_pFileLast = NULL;\n\n      return dwCount;\n   }\n\n   if (dwCount >= _MAX_PATH) {\n      buffer[_MAX_PATH] = '\\0';\n   }\n#ifdef UNICODE\n   DebugOut(TEXT(\"Unhandled call to win_fprintf(\\\"%S\\\")\"), buffer);\n#else\n   DebugOut(TEXT(\"Unhandled call to win_fprintf(\\\"%S\\\")\"), buffer);\n#endif\n   return dwCount;\n}\n\n//******************************************************************************\nvoid WINAPI Wiz_NoPrinting(int f) {\n   // Do nothing.\n}\n\n#endif // POCKET_UNZIP\n\n//******************************************************************************\n//***** Functions that Info-ZIP expects the port to write and export.\n//***** Some of this code was stolen from the WIN32 port and highly modified.\n//******************************************************************************\n\n#ifdef NTSD_EAS\n#ifndef SFX\n//******************************************************************************\n// Called from EXTRACT.C\nint test_NTSD(__GPRO__ uch *eb, unsigned eb_size) {\n   // This function is called when an NT security descriptor is found in the\n   // extra field.  We have nothing to do, so we just return success.\n   return PK_OK;\n}\n#endif /* !SFX */\n#endif /* NTSD_EAS */\n\nstatic void utimeToFileTime(time_t ut, FILETIME *pft, BOOL fOldFileSystem)\n{\n\n   // time_t    is a 32-bit value for the seconds since January 1, 1970\n   // FILETIME  is a 64-bit value for the number of 100-nanosecond intervals\n   //           since January 1, 1601\n   // DWORDLONG is a 64-bit unsigned int that we can use to perform large math\n   //           operations.\n\n\n   // time_t has minimum of 1/1/1970.  Many file systems, such as FAT, have a\n   // minimum date of 1/1/1980.  If extracting to one of those file systems and\n   // out time_t is less than 1980, then we make it 1/1/1980.\n   // (365 days/yr * 10 yrs + 3 leap yr days) * (60 secs * 60 mins * 24 hrs).\n   if (fOldFileSystem && (ut < 0x12CFF780)) {\n      ut = 0x12CFF780;\n   }\n\n#ifndef NO_W32TIMES_IZFIX\n   // Now for the next fix for old file systems.  If we are in Daylight Savings\n   // Time (DST) and the file is not in DST, then we need subtract off the DST\n   // bias from the filetime.  This is due to a bug in Windows (NT, CE, and 95)\n   // that causes the DST bias to be added to all file times when the system\n   // is in DST, even if the file is not in DST.  This only effects old file\n   // systems since they store local times instead of UTC times.  Newer file\n   // systems like NTFS and CEFS store UTC times.\n   if (fOldFileSystem)\n#endif\n   {\n      // We use the CRT's localtime() and Win32's LocalTimeToFileTime()\n      // functions to compute a FILETIME value that always shows the correct\n      // local time in Windows' file listings.  This works because localtime()\n      // correctly adds the DST bias only if the file time is in DST.\n      // FileTimeToLocalTime() always adds the DST bias to the time.\n      // Therefore, if the functions return different results, we know we\n      // are dealing with a non-DST file during a system DST.\n\n      FILETIME lftCRT;\n\n      // Get the CRT result - result is a \"tm\" struct.\n      struct tm *ptmCRT = localtime(&ut);\n\n      // Check if localtime() returned something useful; continue with the\n      // \"NewFileSystem\" code in case of an error. This failsafe method\n      // should give an \"almost\" correct filetime result.\n      if (ptmCRT != (struct tm *)NULL) {\n         // Convert the \"tm\" struct to a FILETIME.\n         SYSTEMTIME stCRT;\n         ZeroMemory(&stCRT, sizeof(stCRT));\n         if (fOldFileSystem && (ptmCRT->tm_year < 80)) {\n            stCRT.wYear   = 1980;\n            stCRT.wMonth  = 1;\n            stCRT.wDay    = 1;\n            stCRT.wHour   = 0;\n            stCRT.wMinute = 0;\n            stCRT.wSecond = 0;\n         } else {\n            stCRT.wYear   = ptmCRT->tm_year + 1900;\n            stCRT.wMonth  = ptmCRT->tm_mon + 1;\n            stCRT.wDay    = ptmCRT->tm_mday;\n            stCRT.wHour   = ptmCRT->tm_hour;\n            stCRT.wMinute = ptmCRT->tm_min;\n            stCRT.wSecond = ptmCRT->tm_sec;\n         }\n         SystemTimeToFileTime(&stCRT, &lftCRT);\n         LocalFileTimeToFileTime(&lftCRT, pft);\n         // we are finished!\n         return;\n      }\n   }\n   // For \"Modern\" file system that stores timestamps in UTC (or as second\n   // chance in case of localtime() errors) the conversion of time_t into\n   // 64-bit FILETIME is a simple arithmetic rescaling calculation.\n   // Compute the FILETIME for the given time_t.\n   DWORDLONG dwl = ((DWORDLONG)116444736000000000 +\n                   ((DWORDLONG)ut * (DWORDLONG)10000000));\n\n   // Store the return value.\n   *pft = *(FILETIME*)&dwl;\n\n}\n\n//******************************************************************************\nstatic int GetFileTimes(__GPRO__ FILETIME *pftCreated,\n                        FILETIME *pftAccessed, FILETIME *pftModified)\n{\n   // We need to check to see if this file system is limited.  This includes\n   // FAT, VFAT, and HPFS.  It does not include NTFS and CEFS.  The limited\n   // file systems can not support dates < 1980 and they store file local times\n   // for files as opposed to UTC times.\n   BOOL fOldFileSystem = IsOldFileSystem(G.filename);\n\n#ifdef USE_EF_UT_TIME  // Always true for WinCE build\n\n#ifdef IZ_CHECK_TZ\n   if (G.extra_field && G.tz_is_valid) {\n#else\n   if (G.extra_field) {\n#endif\n\n      // Structure for Unix style actime, modtime, creatime\n      iztimes z_utime;\n\n      // Get any date/time we can.  This can return 0 to 3 unix time fields.\n      unsigned eb_izux_flg = ef_scan_for_izux(G.extra_field,\n                                              G.lrec.extra_field_length, 0,\n                                              G.lrec.last_mod_dos_datetime,\n                                              &z_utime, NULL);\n\n      // We require at least a modified time.\n      if (eb_izux_flg & EB_UT_FL_MTIME) {\n\n         // We know we have a modified time, so get it first.\n         utimeToFileTime(z_utime.mtime, pftModified, fOldFileSystem);\n\n         // Get the accessed time if we have one.\n         if (eb_izux_flg & EB_UT_FL_ATIME) {\n            utimeToFileTime(z_utime.atime, pftAccessed, fOldFileSystem);\n         }\n\n         // Get the created time if we have one.\n         if (eb_izux_flg & EB_UT_FL_CTIME) {\n            utimeToFileTime(z_utime.ctime, pftCreated, fOldFileSystem);\n         }\n\n         // Return our flags.\n         return (int)eb_izux_flg;\n      }\n   }\n\n#endif // USE_EF_UT_TIME\n\n   // If all else fails, we can resort to using the DOS date and time data.\n   time_t ux_modtime = dos_to_unix_time(G.lrec.last_mod_dos_datetime);\n   utimeToFileTime(ux_modtime, pftModified, fOldFileSystem);\n\n   *pftAccessed = *pftModified;\n\n   return (EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n}\n\n//******************************************************************************\n//***** Functions to correct time stamp bugs on old file systems.\n//******************************************************************************\n\n//******************************************************************************\n// Borrowed/Modified from win32.c\nstatic BOOL IsOldFileSystem(char *szPath) {\n\n#ifdef _WIN32_WCE\n\n   char szRoot[10];\n\n   // Get the first nine characters of the path.\n   strncpy(szRoot, szPath, 9);\n   szRoot[9] = '\\0';\n\n   // Convert to uppercase to help with compare.\n   _strupr(szRoot);\n\n   // PC Cards are mounted off the root in a directory called \"\\PC Cards\".\n   // PC Cards are FAT, no CEOS.  We need to check if the file is being\n   // extracted to the PC card.\n   return !strcmp(szRoot, \"\\\\PC CARD\\\\\");\n\n#else\n\n   char szRoot[_MAX_PATH] = \"\\0\\0\\0\", szFS[64];\n\n   // Check to see if our path contains a drive letter.\n   if (isalpha(szPath[0]) && (szPath[1] == ':') && (szPath[2] == '\\\\')) {\n\n      // If so, then just copy the drive letter, colon, and wack to our root path.\n      strncpy(szRoot, szPath, 3);\n\n   } else {\n\n      // Expand the path so we can get a drive letter.\n      GetFullPathNameA(szPath, sizeof(szRoot), szRoot, NULL);\n\n      // Make sure we actually got a drive letter back in our root path buffer..\n      if (!isalpha(szRoot[0]) || (szRoot[1] != ':') || (szRoot[2] != '\\\\')) {\n\n         // When in doubt, return TRUE.\n         return TRUE;\n      }\n   }\n\n   // NULL terminate after the wack to ensure we have just the root path.\n   szRoot[3] = '\\0';\n\n   // Get the file system type string.\n   GetVolumeInformationA(szRoot, NULL, 0, NULL, NULL, NULL, szFS, sizeof(szFS));\n\n   // Ensure that the file system type string is uppercase.\n   _strupr(szFS);\n\n   // Return true for (V)FAT and (OS/2) HPFS format.\n   return !strncmp(szFS, \"FAT\",  3) ||\n          !strncmp(szFS, \"VFAT\", 4) ||\n          !strncmp(szFS, \"HPFS\", 4);\n\n#endif // _WIN32_WCE\n}\n\n//******************************************************************************\nint SetFileSize(FILE *file, zusz_t filesize)\n{\n#if (defined(_WIN32_WCE) || defined(__RSXNT__))\n    // For native Windows CE, it is not known whether the API supports\n    // presetting a file's size.\n    // RSXNT environment lacks a translation function from C file pointer\n    // to Win32-API file handle.\n    // So, simply do nothing.\n    return 0;\n#else /* !(_WIN32_WCE || __RSXNT__) */\n    /* not yet verified, if that really creates an unfragmented file\n      rommel@ars.de\n     */\n    HANDLE os_fh;\n#ifdef Z_UINT8_DEFINED\n    LARGE_INTEGER fsbuf;\n#endif\n\n    /* Win9x supports FAT file system, only; presetting file size does\n       not help to prevent fragmentation. */\n    if ((long)GetVersion() < 0) return 0;\n\n    /* Win32-API calls require access to the Win32 file handle.\n       The interface function used to retrieve the Win32 handle for\n       a file opened by the C rtl is non-standard and may not be\n       available for every Win32 compiler environment.\n       (see also win32/win32.c of the Zip distribution)\n     */\n    os_fh = (HANDLE)_get_osfhandle(fileno(file));\n    /* move file pointer behind the last byte of the expected file size */\n#ifdef Z_UINT8_DEFINED\n    fsbuf.QuadPart = filesize;\n    if ((SetFilePointer(os_fh, fsbuf.LowPart, &fsbuf.HighPart, FILE_BEGIN)\n         == 0xFFFFFFFF) && GetLastError() != NO_ERROR)\n#else\n    if (SetFilePointer(os_fh, filesize, 0, FILE_BEGIN) == 0xFFFFFFFF)\n#endif\n        return -1;\n    /* extend/truncate file to the current position */\n    if (SetEndOfFile(os_fh) == 0)\n        return -1;\n    /* move file position pointer back to the start of the file! */\n    return (SetFilePointer(os_fh, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) ? -1 : 0;\n#endif /* ?(_WIN32_WCE || __RSXNT__) */\n} /* end function SetFileSize() */\n\n//******************************************************************************\nvoid close_outfile(__GPRO)\n{\n   HANDLE hFile;\n\n   TCHAR szFile[_MAX_PATH];\n   MBSTOTSTR(szFile, G.filename, countof(szFile));\n\n   /* skip restoring time stamps on user's request */\n   if (uO.D_flag <= 1) {\n      // Get the 3 time stamps for the file.\n      FILETIME ftCreated, ftAccessed, ftModified;\n      int timeFlags = GetFileTimes(__G__ &ftCreated, &ftAccessed, &ftModified);\n\n#if (defined(_WIN32_WCE) && (_WIN32_WCE < 211))\n\n      // Cast the outfile to a HANDLE (since that is really what it is), and\n      // flush the file.  We need to flush, because any unsaved data that is\n      // written to the file during CloseHandle() will step on the work done\n      // by SetFileTime().\n      hFile = (HANDLE)G.outfile;\n      FlushFileBuffers(hFile);\n\n#else\n\n      // Close the file and then re-open it using the Win32 CreateFile() call.\n      // SetFileTime() requires a Win32 file HANDLE created with GENERIC_WRITE\n      // access.\n      fclose(G.outfile);\n      hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,\n                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n\n#endif\n\n      // Set the file's date and time.\n      if (hFile != INVALID_HANDLE_VALUE) {\n\n         // Make sure we retrieved some valid time stamp(s)\n         if (timeFlags) {\n\n            // Set the various date and time fields.\n            if (!SetFileTime(hFile,\n                    (timeFlags & EB_UT_FL_CTIME) ? &ftCreated  : NULL,\n                    (timeFlags & EB_UT_FL_ATIME) ? &ftAccessed : NULL,\n                    (timeFlags & EB_UT_FL_MTIME) ? &ftModified : NULL))\n            {\n               DebugOut(TEXT(\"SetFileTime() failed [%u]\"), GetLastError());\n            }\n\n         } else {\n            DebugOut(TEXT(\"GetFileTimes() failed\"));\n         }\n\n         // Close out file.\n         CloseHandle(hFile);\n\n      } else {\n         DebugOut(TEXT(\"CreateFile() failed [%u]\"), GetLastError());\n      }\n   }\n\n   // If the file was successfully written, then set the attributes.\n#ifdef POCKET_UNZIP\n   if (!G.disk_full && !g_pExtractInfo->fAbort) {\n#else\n   if (!G.disk_full) {\n#endif\n      if (!SetFileAttributes(szFile, G.pInfo->file_attr & 0x7F)) {\n         DebugOut(TEXT(\"SetFileAttributes() failed [%u]\"), GetLastError());\n      }\n   }\n\n   // Clear outfile so we know it is closed.\n   G.outfile = 0;\n\n   return;\n}\n\n//******************************************************************************\n// Called by PROCESS.C\nchar* do_wild(__GPRO__ ZCONST char *wildspec)\n{\n   // This is a very slimmed down version of do_wild() taken from WIN32.C.\n   // Since we don't support wildcards, we basically just return the wildspec\n   // passed in as the filename.\n\n#ifndef POCKET_UNZIP\n   // Delete allocated storage for the match name\n   if (G.matchname != NULL)\n   {\n      delete G.matchname;\n      G.matchname = NULL;\n   }\n#endif\n\n   // First call - must initialize everything.\n   if (!G.notfirstcall) {\n      G.notfirstcall = TRUE;\n#ifdef POCKET_UNZIP\n      return strcpy(G.matchname, wildspec);\n#else\n      // allocate some storage for the match name\n      G.matchname = new char[strlen(wildspec) + 1];\n      if (G.matchname != NULL)\n         return strcpy(G.matchname, wildspec);\n#endif\n   }\n\n   // Last time through - reset for new wildspec.\n   G.notfirstcall = FALSE;\n\n   return (char *)NULL;\n}\n\n//******************************************************************************\n// Called from EXTRACT.C\nint mapattr(__GPRO)\n{\n#ifdef POCKET_UNZIP\n   // Check to see if we are extracting this file for viewing.  Currently, we do\n   // this by checking the szMappedPath member of our extract info stucture\n   // since we know OnActionView() is the only one who sets this member.\n\n   if (g_pExtractInfo && g_pExtractInfo->szMappedPath) {\n\n      // If we are extracting for view only, then we ignore the file's real\n      // attributes and force the file to create as read-only.  We make the file\n      // read-only to help prevent the user from making changes to the temporary\n      // file and then trying to save the changes back to a file that we will\n      // eventually delete.\n      G.pInfo->file_attr = FILE_ATTRIBUTE_READONLY;\n\n   } else\n#endif\n   {\n      /* set archive bit for file entries (file is not backed up): */\n      G.pInfo->file_attr = ((unsigned)G.crec.external_file_attributes |\n        (G.crec.external_file_attributes & FILE_ATTRIBUTE_DIRECTORY ?\n         0 : FILE_ATTRIBUTE_ARCHIVE)) & 0xff;\n   }\n   return 0;\n} /* end function mapattr() */\n\n//******************************************************************************\n// Called from EXTRACT.C\n//\n// returns:\n//  MPN_OK          - no problem detected\n//  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename\n//  MPN_INF_SKIP    - path doesn't exist, not allowed to create\n//  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path\n//                    exists and is not a directory, but is supposed to be\n//  MPN_ERR_TOOLONG - path is too long\n//  MPN_NOMEM       - can't allocate memory for filename buffers\n//\n//  MPN_VOL_LABEL   - Path was a volume label, skip it.\n//  MPN_CREATED_DIR - Created a directory.\n//\nint mapname(__GPRO__ int renamed)\n{\n    int error = MPN_OK;\n    CHAR szBuffer[countof(G.filename)] = \"\";\n    CHAR *pIn = NULL, *pOut, *pLastSemi = NULL;\n    CHAR *pPathComp, workch;\n    BOOL killed_ddot = FALSE, renamed_fullpath = FALSE, created_dir = FALSE;\n\n#ifdef POCKET_UNZIP\n    // mapname() is a great place to reset all our status counters for the next\n    // file to be processed since it is called for every zip file member before\n    // any work is done with that member.\n    SetCurrentFile(__G);\n#endif\n\n    // If Volume Label, skip the \"extraction\" quietly\n    if (G.pInfo->vollabel) {\n       return MPN_VOL_LABEL;\n    }\n\n#ifndef POCKET_UNZIP // The GUI interface does not support renaming...\n    if (renamed) {\n        pIn = G.filename;   // point to beginning of renamed name...\n        if (*pIn) do {\n            if (*pIn == '\\\\')   // convert backslashes to forward\n                *pIn = '/';\n        } while (*PREINCSTR(pIn));\n        pIn = G.filename;\n        // use temporary rootpath if user gave full pathname\n        if (G.filename[0] == '/') {\n            renamed_fullpath = TRUE;\n            szBuffer[0] = '\\\\'; // copy the '/' and terminate\n            szBuffer[1] = '\\0';\n            ++pIn;\n        } else if (isalpha((uch)G.filename[0]) && G.filename[1] == ':') {\n            renamed_fullpath = TRUE;\n            pOut = szBuffer;\n            *pOut++ = *pIn++;   // copy the \"d:\" (+ '/', possibly)\n            *pOut++ = *pIn++;\n            if (*pIn == '/') {\n                *pOut++ = '\\\\';\n                pIn++;          // otherwise add \"./\"?\n            }\n            *pOut = '\\0';\n        }\n    }\n#endif\n\n    // Initialize file path buffer with our \"extract to\" path.\n    if (!renamed_fullpath) {\n#ifdef POCKET_UNZIP\n        strcpy(szBuffer, g_szExtractToDirectory);\n#else\n        strcpy(szBuffer, G.rootpath);\n#endif\n        pOut = szBuffer + strlen(szBuffer);\n    }\n    pPathComp = pOut;\n\n    if (!renamed) {\n        // Point pIn to beginning of our internal pathname.\n        // If we are junking paths, then locate the file portion of the path.\n        if (uO.jflag)\n            pIn = (CHAR*)MBSRCHR(G.filename, '/');\n        if (pIn == NULL)\n            pIn = G.filename;\n        else\n            ++pIn;\n    }\n\n    // Begin main loop through characters in filename.\n    for ( ; (workch = *pIn) != '\\0'; INCSTR(pIn)) {\n\n        // Make sure we don't overflow our output buffer.\n        if (pOut >= (szBuffer + countof(szBuffer) - 2)) {\n            Info(slide, 1, ((char*)slide, \"path too long: %s\\n\",\n              FnFilter1(G.filename)));\n            return MPN_ERR_TOOLONG;\n        }\n\n        // Examine the next character in our input buffer.\n        switch (workch) {\n\n          // Check for a directory wack.\n          case '/':\n            *pOut = '\\0';\n            // Skip dir traversals unless they are explicitly allowed.\n            if (strcmp(pPathComp, \".\") == 0) {\n                // don't bother appending \"./\" to the path\n                *pPathComp = '\\0';\n            } else if (!uO.ddotflag && strcmp(pPathComp, \"..\") == 0) {\n                // \"../\" dir traversal detected, skip over it\n                *pPathComp = '\\0';\n                killed_ddot = TRUE;     // set \"show message\" flag\n            }\n            // When path component is not empty, append it now.\n            if (*pPathComp == '\\0') {\n                // Reset insert pos to start of path component.\n                pOut = pPathComp;\n            } else {\n                if (!SmartCreateDirectory(__G__ szBuffer, &created_dir)) {\n                   Info(slide, 1, ((char*)slide, \"failure extracting: %s\\n\",\n                        FnFilter1(G.filename)));\n                   return MPN_ERR_SKIP;\n                }\n                *(pOut++) = '\\\\';\n                pPathComp = pOut;  // Remember start pos of new path component\n            }\n            pLastSemi = NULL;  // Leave any directory semi-colons alone\n            break;\n\n          // Check for illegal characters and replace with underscore.\n          case ':':\n          case '\\\\':\n          case '*':\n          case '?':\n          case '\"':\n          case '<':\n          case '>':\n          case '|':\n            *(pOut++) = '_';\n            break;\n\n          // Check for start of VMS version.\n          case ';':\n            pLastSemi = pOut;  // Make note as to where we are.\n            *(pOut++) = ';';   // Leave the semi-colon alone for now.\n            break;\n\n          default:\n            // Allow European characters and spaces in filenames.\n#ifdef _MBCS\n            if ((UCHAR)workch >= 0x20) {\n                memcpy(pOut, pIn, CLEN(pIn));\n                INCSTR(pOut);\n            } else {\n                *(pOut++) = '_';\n            }\n#else\n            *(pOut++) = (((UCHAR)workch >= 0x20) ? workch : '_');\n#endif\n       }\n    }\n\n    // Show warning when stripping insecure \"parent dir\" path components\n    if (killed_ddot && QCOND2) {\n        Info(slide, 0, ((char *)slide,\n          \"warning:  skipped \\\"../\\\" path component(s) in %s\\n\",\n          FnFilter1(G.filename)));\n        if (!(error & ~MPN_MASK))\n            error = (error & MPN_MASK) | PK_WARN;\n    }\n\n    // Done with output buffer, terminate it.\n    *pOut = '\\0';\n\n    // Remove any VMS version numbers if found (appended \";###\").\n    if (pLastSemi) {\n\n        // Walk over all digits following the semi-colon.\n        for (pOut = pLastSemi + 1; (*pOut >= '0') && (*pOut <= '9'); pOut++);\n\n        // If we reached the end, then nuke the semi-colon and digits.\n        if (!*pOut)\n           *pLastSemi = '\\0';\n    }\n\n    // Copy the mapped name back to the internal path buffer\n    strcpy(G.filename, szBuffer);\n\n#ifdef POCKET_UNZIP\n    // Fill in the mapped name buffer if the original caller requested us to.\n    if (g_pExtractInfo->szMappedPath) {\n        strcpy(g_pExtractInfo->szMappedPath, szBuffer);\n    }\n#endif\n\n    // If it is a directory, then display the \"creating\" status text.\n    if ((pOut > szBuffer) && (lastchar(szBuffer, pOut-szBuffer) == '\\\\')) {\n        if (created_dir) {\n#ifdef UNICODE\n            TCHAR szFile[_MAX_PATH];\n\n            MBSTOTSTR(szFile, G.filename, countof(szFile));\n#           define T_Fname  szFile\n#else\n#           define T_Fname  G.filename\n#endif\n            if (QCOND2) {\n                Info(slide, 0, ((char *)slide, \"   creating: %-22s\\n\",\n                  FnFilter1(G.filename)));\n            }\n\n            // set file attributes:\n            // The default for newly created directories is \"DIR attribute\n            // flags set\", so there is no need to change attributes unless\n            // one of the DOS style attribute flags is set. There is no need\n            // to mask the readonly attribute, because it does not prevent\n            // modifications in the new directory.\n            if(G.pInfo->file_attr & (0x7F & ~FILE_ATTRIBUTE_DIRECTORY)) {\n                if (!SetFileAttributes(T_Fname, G.pInfo->file_attr & 0x7F))\n                    Info(slide, 1, ((char *)slide,\n                      \"\\nwarning (%d): could not set file attributes for %s\\n\",\n                      (int)GetLastError(), FnFilter1(G.filename)));\n            }\n\n            /* set dir time (note trailing '/') */\n            return (error & ~MPN_MASK) | MPN_CREATED_DIR;\n        }\n        /* dir existed already; don't look for data to extract */\n        return (error & ~MPN_MASK) | MPN_INF_SKIP;\n    }\n\n    return error;\n}\n\n//******************************************************************************\n// Called from PROCESS.C\nint checkdir(__GPRO__ char *pathcomp, int flag) {\n#ifdef POCKET_UNZIP\n\n    // This function is only called by free_G_buffers() from PROCESS.C with the\n    // flag set to END.  We have nothing to do, so we just return success.\n    return MPN_OK;\n\n#else // !POCKET_UNZIP\n\n#   define FN_MASK 7\n#   define FUNCTION (flag & FN_MASK)\n    int rc = MPN_OK;\n\n    switch (FUNCTION) {\n    case ROOT:\n      {\n        // User specified a root path. save the root without separator\n        char* pathcompStart;\n\n        if (pathcomp == NULL) {\n            G.rootlen = 0;      // trivial NULL clause...\n            break;\n        }\n        if (G.rootlen > 0)\n            break;              // nothing to do, rootpath was already set\n\n        G.rootlen = strlen(pathcomp);\n        pathcompStart = pathcomp;\n        // Strip the drive if given. CE does not support Drive\n        if (pathcomp[1] == ':') {\n            G.rootlen -= 2;\n            pathcompStart += 2;\n        }\n        // Check for trailing separator, Strip if given\n        // accomodate it if required.\n        if (pathcomp[G.rootlen - 1] == '/' || pathcomp[G.rootlen - 1] == '\\\\')\n            G.rootlen--;\n        // Save the root\n        memcpy(G.rootpath, pathcompStart, G.rootlen);\n        G.rootpath[G.rootlen] = '\\0';\n\n        // Check if directory exists and try to create when neccessary.\n        if (!SmartCreateDirectory(__G__ G.rootpath, NULL)) {\n            rc = MPN_ERR_SKIP; // Create directory failed\n        }\n\n        // Add trailing path separator\n        G.rootpath[G.rootlen++] = '\\\\';\n        G.rootpath[G.rootlen] = '\\0';\n        break;\n     }\n\n    case END:\n        Trace((stderr, \"freeing rootpath\\n\"));\n        if (G.rootlen > 0) {\n            G.rootlen = 0;\n            G.rootpath[0] = '\\0';\n        }\n        break;\n\n    default:\n        rc = MPN_INVALID;       /* should never reach */\n        break;\n    }\n    return rc;\n\n#endif // !POCKET_UNZIP\n} /* end function checkdir() */\n\n#ifdef POCKET_UNZIP\n//******************************************************************************\n// Called from EXTRACT.C and LIST.C\nint match(ZCONST char *string, ZCONST char *pattern, int ignore_case __WDLPRO)\n{\n   // match() for the other ports compares a file in the Zip file with some\n   // command line file pattern.  In our case, we always pass in exact matches,\n   // so we can simply do a string compare to see if we have a match.\n   return (strcmp(string, pattern) == 0);\n}\n\n//******************************************************************************\n// Called from PROCESS.C\nint iswild(ZCONST char *pattern) {\n   // Our file patterns never contain wild characters.  They are always exact\n   // matches of file names in our Zip file.\n   return FALSE;\n}\n\n#else // !POCKET_UNZIP\n\n/************************/\n/*  Function version()  */\n/************************/\n\nvoid version(__GPRO)\n{\n    // Dummy function, does nothing.\n}\n\n#ifndef WINDLL\n/* Console input not supported on CE so just return -1 */\nint getch_win32(void)\n{\n  return -1;\n}\n#endif /* !WINDLL */\n#endif // !POCKET_UNZIP\n\n#if (defined(UNICODE_SUPPORT))\n/* convert wide character string to multi-byte character string */\nchar *wide_to_local_string(ZCONST zwchar *wide_string,\n                           int escape_all)\n{\n  int i;\n  wchar_t wc;\n  int bytes_char;\n  int default_used;\n  int wsize = 0;\n  int max_bytes = 9;\n  char buf[9];\n  char *buffer = NULL;\n  char *local_string = NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if (max_bytes < MB_CUR_MAX)\n    max_bytes = MB_CUR_MAX;\n\n  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {\n    return NULL;\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  for (i = 0; i < wsize; i++) {\n    if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {\n      /* wchar_t probably 2 bytes */\n      /* could do surrogates if state_dependent and wctomb can do */\n      wc = zwchar_to_wchar_t_default_char;\n    } else {\n      wc = (wchar_t)wide_string[i];\n    }\n    /* The C-RTL under WinCE does not support the generic C-style\n     * Wide-to-MultiByte conversion functions (like wctomb() et. al.).\n     * Therefore, we have to fall back to the underlying WinCE-API call to\n     * get WCHAR-to-ANSI translation done.\n     */\n    bytes_char = WideCharToMultiByte(\n                          CP_ACP, WC_COMPOSITECHECK,\n                          &wc, 1,\n                          (LPSTR)buf, sizeof(buf),\n                          NULL, &default_used);\n    if (default_used)\n      bytes_char = -1;\n    if (escape_all) {\n      if (bytes_char == 1 && (uch)buf[0] <= 0x7f) {\n        /* ASCII */\n        strncat(buffer, buf, 1);\n      } else {\n        /* use escape for wide character */\n        char *escape_string = wide_to_escape_string(wide_string[i]);\n        strcat(buffer, escape_string);\n        free(escape_string);\n      }\n    } else if (bytes_char > 0) {\n      /* multi-byte char */\n      strncat(buffer, buf, bytes_char);\n    } else {\n      /* no MB for this wide */\n      /* use escape for wide character */\n      char *escape_string = wide_to_escape_string(wide_string[i]);\n      strcat(buffer, escape_string);\n      free(escape_string);\n    }\n  }\n  if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) {\n    free(buffer);\n    return NULL;\n  }\n\n  return local_string;\n}\n#endif /* UNICODE_SUPPORT */\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/intrface.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        INTRFACE.H\n//\n// Description: This module acts as the interface between the Info-ZIP code and\n//              our Windows code in WINMAIN.CPP.  See INTRFACE.CPP for a more\n//              detailed description and the actual implementation.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n#ifndef __INTRFACE_H__\n#define __INTRFACE_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef POCKET_UNZIP\n//******************************************************************************\n//***** Types and Structures\n//******************************************************************************\n\ntypedef enum _OVERWRITE_MODE {\n   OM_PROMPT = 0,\n   OM_NEWER,\n   OM_ALWAYS,\n   OM_NEVER\n} OVERWRITE_MODE, *LPOVERWRITE_MODE;\n\ntypedef struct _EXTRACT_INFO {\n   zusz_t          uzByteCount;   // Total bytes to extract/test\n   DWORD           dwFileCount;   // Number of files to extract/test.\n   LPSTR          *szFileList;    // ARGV list of files, NULL for all files.\n   LPSTR           szMappedPath;  // Used to store mapped name. May be NULL.\n   OVERWRITE_MODE  overwriteMode; // How to handle file overwrites.\n   BOOL            fExtract;      // TRUE for extract, FALSE for test\n   BOOL            fRestorePaths; // TRUE to restore paths, FALSE to junk them.\n   BOOL            fAbort;        // Set during operation by UI to abort.\n   int             result;        // Result code from extraction/test.\n\n   // Window handles for the various controls in our progress dialogs.\n   HWND            hWndEditFile;\n   HWND            hWndProgFile;\n   HWND            hWndProgTotal;\n   HWND            hWndPercentage;\n   HWND            hWndFilesProcessed;\n   HWND            hWndBytesProcessed;\n\n   // Values used to keep track of our progress.\n   zusz_t          uzBytesTotalThisFile;\n   zusz_t          uzBytesWrittenThisFile;\n   zusz_t          uzBytesWrittenPreviousFiles;\n   zusz_t          uzFileOffset;\n   DWORD           dwFile;\n   LPCSTR          szFile;\n   BOOL            fNewLineOfText;\n\n} EXTRACT_INFO, *LPEXTRACT_INFO;\n\ntypedef struct _DECRYPT_INFO {\n   int    retry;\n   LPSTR  szPassword;\n   DWORD  nSize;\n   LPCSTR szFile;\n} DECRYPT_INFO, *LPDECRYPT_INFO;\n\n//******************************************************************************\n//***** Function Prototypes\n//******************************************************************************\n\n// Our exposed interface functions to the Info-ZIP core.\nint  DoListFiles(LPCSTR szZipFile);\nBOOL DoExtractOrTestFiles(LPCSTR szZipFile, EXTRACT_INFO *pei);\nint  DoGetComment(LPCSTR szZipFile);\nBOOL SetExtractToDirectory(LPTSTR szDirectory);\n\n// \"Internal\" callbacks from Info-ZIP code.\n// (The \"official\" callback functions are declared in the UnZip DLL headers,\n// see \"unzip.h\".)\nvoid WINAPI Wiz_NoPrinting(int f);\nint  win_fprintf(zvoid *pG, FILE *file, unsigned int dwCount, char far *buffer);\n\n\n//******************************************************************************\n//***** Global Variables\n//******************************************************************************\n\n#ifdef GLOBAL_DECLARE\n#undef GLOBAL_DECLARE\n#undef GLOBAL_INIT\n#endif\n\n#ifdef __INTRFACE_CPP__\n   #define GLOBAL_DECLARE\n   #define GLOBAL_INIT(value) =value\n#else\n   #define GLOBAL_DECLARE extern\n   #define GLOBAL_INIT(value)\n#endif\n\nGLOBAL_DECLARE jmp_buf         dll_error_return;\nGLOBAL_DECLARE LPDCL           lpDCL           GLOBAL_INIT(NULL);\nGLOBAL_DECLARE LPUSERFUNCTIONS lpUserFunctions GLOBAL_INIT(NULL);\n\n#endif // POCKET_UNZIP\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // __INTRFACE_H__\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/punzip.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        PUNZIP.H\n//\n// Description: This is our global header for the entire Pocket UnZip project.\n//              This header contains all global project build flags, defines,\n//              constants, and macros.  It also includes all other headers that\n//              are needed by the project.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n#ifndef __PUNZIP_H__\n#define __PUNZIP_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n//******************************************************************************\n//***** Standard Win32 project flags\n//******************************************************************************\n\n#ifndef WIN32\n#define WIN32\n#endif\n\n#ifndef _WINDOWS\n#define _WINDOWS\n#endif\n\n#ifdef _WIN32_WCE   /* for native Windows CE, force UNICODE mode */\n#ifndef UNICODE\n#define UNICODE\n#endif\n#endif /* _WIN32_WCE */\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#ifndef STRICT\n#define STRICT\n#endif\n\n#if defined(_UNICODE) && !defined(UNICODE)\n#define UNICODE\n#endif\n\n#if defined(UNICODE) && !defined(_UNICODE)\n#define _UNICODE\n#endif\n\n#if defined(_DEBUG) && !defined(DEBUG)\n#define DEBUG\n#endif\n\n#if defined(DEBUG) && !defined(_DEBUG)\n#define _DEBUG\n#endif\n\n#if defined(_NDEBUG) && !defined(NDEBUG)\n#define NDEBUG\n#endif\n\n#if defined(NDEBUG) && !defined(_NDEBUG)\n#define _NDEBUG\n#endif\n\n\n//******************************************************************************\n//***** Pocket Unzip and Info-ZIP flags\n//******************************************************************************\n\n#ifndef POCKET_UNZIP\n#define POCKET_UNZIP\n#endif\n\n#ifndef WINDLL\n#define WINDLL\n#endif\n\n#ifndef DLL\n#define DLL\n#endif\n\n#ifndef REENTRANT\n#define REENTRANT\n#endif\n\n#ifndef NO_ZIPINFO\n#define NO_ZIPINFO\n#endif\n\n#ifndef NO_STDDEF_H\n#define NO_STDDEF_H\n#endif\n\n// Read COPYING document before enabling this define.\n#if 0\n#ifndef USE_SMITH_CODE\n#define USE_SMITH_CODE\n#endif\n#endif\n\n// Read COPYING document before enabling this define.\n#if 0\n#ifndef USE_UNSHRINK\n#define USE_UNSHRINK\n#endif\n#endif\n\n\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // __PUNZIP_H__\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/punzip.htp",
    "content": "<html>\n<head>\n<title>Pocket UnZip</title>\n</head>\n<body>\n\n<h2>Pocket UnZip</h2>\n\n<hr>\n<h3>Table of Contents</h3>\n\n<ul>\n    <li>Why use Pocket UnZip for Windows CE?</li>\n    <li>Key Features of Pocket UnZip</li>\n    <li>Installing Pocket UnZip</li>\n    <li>Opening a Zip File</li>\n    <li>Zip File Listing</li>\n    <li>Properties Dialog</li>\n    <li>File Comments</li>\n    <li>Extracting Files</li>\n    <li>Testing Files</li>\n    <li>Viewing Files</li>\n    <li>Encrypted Files</li>\n    <li>About Pocket UnZip</li>\n</ul>\n\n<hr>\n<h3>Why use Pocket UnZip for Windows CE?</h3>\n\n<ul>\n    <li>Your H/PC can now read the number one file format used\n        for Internet downloads.</li>\n    <li>Software venders can now distribute their Windows CE\n        applications in a single compressed Zip file. </li>\n    <li>Maximize your PCMCIA flash card ram storage by zipping up\n        files to take with you on the road.</li>\n</ul>\n\n<hr>\n<h3>Key Features of Pocket UnZip</h3>\n\n<ul>\n    <li>Handles all files created with a Zip compatible\n        compression utility. This includes utilities from PKWARE,\n        Info-ZIP, and many others. </li>\n    <li>Easy to use graphical interface that closely resembles\n        the Windows CE Explorer. </li>\n    <li>Displays a detailed list of Zip file contents, including\n        name, date, size, attributes, and compression statistics\n        of each file. </li>\n    <li>Displays comments for the each file within the Zip file,\n        as well as the main comment for the Zip file itself. </li>\n    <li>Supports the ability to test files, extract files, and\n        view files directly from the Zip file. </li>\n    <li>Supports decryption of password encrypted Zip files. </li>\n    <li>It's free!</li>\n</ul>\n\n<hr>\n<h3>Installing Pocket UnZip</h3>\n\n<p>Place <strong>PUNZIP.EXE</strong> and <strong>PUNZIP.HTP </strong>(optional\nhelp file) into your <strong>\\Windows</strong> directory on your\nH/PC.</p>\n\n<p>From your H/PC's <strong>Start Menu</strong>, choose <strong>Run...</strong>,\nenter &quot;<strong>punzip</strong>&quot;, and tap <strong>OK</strong>.</p>\n\n<p>The first time you run Pocket UnZip, it will register itself\nas the application for handling Zip files. From then on, you can\njust double-tap on Zip files in Explorer or from your Desktop to\nopen them in Pocket UnZip.</p>\n\n<hr>\n<h3>Opening a Zip File</h3>\n\n<p>There are several ways to open a Zip file.</p>\n\n<ul>\n    <li>Double-tap on a Zip file in Windows CE Explorer or from\n        your Windows CE desktop. </li>\n    <li>From within Pocket UnZip, choose the <strong>Open...</strong>\n        command from the <strong>File</strong> menu. You may also\n        tap the <strong>Open</strong> toolbar button or press <strong>Ctrl+O</strong>.\n    </li>\n    <li>Pocket UnZip keeps track of the four most recently opened\n        Zip files. You may quickly open one of these recent files\n        by selecting the Zip file directly from Pocket UnZip's <strong>File</strong>\n        menu.</li>\n</ul>\n\n<hr>\n<h3>Zip File Listing</h3>\n\n<p>Pocket UnZip's main view displays a list of files,\ndirectories, and volume labels that are stored within the\ncurrently loaded Zip file. This list can be displayed in two\nmodes, normal and expanded. The normal mode is sufficient for\nmost users. It contains the following information for every item\nin the Zip file:</p>\n\n<ul>\n    <li><strong>Name</strong>: Name and path of the compressed\n        file, directory, or volume label.</li>\n    <li><strong>Size</strong>: Size, in bytes, that the item\n        requires when uncompressed.</li>\n    <li><strong>Type</strong>: Type of item.</li>\n    <li><strong>Modified</strong>: Date and time that the item\n        was last modified.</li>\n</ul>\n\n<p>Expanded mode contains all the above information, plus the\nfollowing additional information:</p>\n\n<ul>\n    <li><strong>Attributes</strong>: Attributes of the item.\n        <ul>\n            <li><font face=\"Courier New\"><strong>V</strong></font>:\n                Volume label</li>\n            <li><font face=\"Courier New\"><strong>D</strong></font>:\n                Directory</li>\n            <li><font face=\"Courier New\"><strong>R</strong></font>:\n                Read-only file</li>\n            <li><font face=\"Courier New\"><strong>A</strong></font>:\n                Archive file</li>\n            <li><font face=\"Courier New\"><strong>H</strong></font>:\n                Hidden file</li>\n            <li><font face=\"Courier New\"><strong>S</strong></font>:\n                System file</li>\n            <li><font face=\"Courier New\"><strong>E</strong></font>:\n                Encrypted (this file will require a password)</li>\n            <li><font face=\"Courier New\"><strong>C</strong></font>:\n                Comment (this item has a comment)</li>\n        </ul>\n    </li>\n    <li><strong>Compressed</strong>: Compressed size, in bytes,\n        of the item.</li>\n    <li><strong>Ratio</strong>: Compression ratio of the item.</li>\n    <li><strong>Method</strong>: Compression method used to\n        compress the item.</li>\n    <li><strong>CRC</strong>: 32 bit Cyclic Redundancy Check\n        signature of the item.</li>\n    <li><strong>Comment</strong>: Optional comment string that\n        was associated with the item when compressed.</li>\n</ul>\n\n<p>You may toggle between the normal view and the expanded view\nby selecting the <strong>Extended View</strong> option from the <strong>View</strong>\nmenu, or by tapping the associated toolbar button.</p>\n\n<hr>\n<h3>Properties Dialog</h3>\n\n<p>The properties dialog is useful for viewing detailed\ninformation for one or more files. It is invoked by selecting one\nor more files in the file list and then choosing <strong>Properties</strong>\nfrom the <strong>File</strong> menu. For convenience, you can\nalso tap the toolbar button or press <strong>Alt+Enter</strong>.</p>\n\n<p>If one file is selected, the properties dialog will show you\ndetailed information about that one file and its comment.</p>\n\n<p>If multiple files are selected, the dialog will show you\ncombined results for all the files selected. Cumulative results\nwill be given for the file count, byte counts, and compression\nratio. Merged results will be given for the compression method,\ndate, CRC, attributes, and comment. For the date, all values that\nare common between the selected files (such as year), will be\nshown with their common value. All values that differ between the\nselected files will be shown as question marks. For attributes, a\nblack check means that all selected files have that particular\nattribute, a gray check mark means that some of the selected\nfiles have that attribute, and no check mark means that none of\nthe selected files have that attribute.</p>\n\n<p>By using the properties dialog with multiple files, you can\ndetermine things like... What is the total number of files or\nbytes in the Zip file? What is the total compression ratio for\nall selected files. Are all the selected files from the same\nyear? Same month? How many files have comments?</p>\n\n<hr>\n<h3>File Comments</h3>\n\n<p>Zip files provide two levels of commenting. At compression\ntime, users can add per-file comments, as well as one main\ncomment for the entire Zip file. The per-file comments are\nusually used to give a short description of each file. The main\ncomment is usually used for credits, copyright information,\ninstallation instructions, version numbers, etc. Pocket UnZip\ncan display both types of comments. </p>\n\n<p>Per-file comments can be viewed in Comments column of the main\nfile list while in expanded mode (see the <strong>Zip File Listing</strong>\nsection) and also in the properties dialog (see the <strong>Properties\nDialog</strong> section).</p>\n\n<p>The main Zip file comment can be viewed by selecting <strong>Zip\nFile Comment</strong> from the <strong>View</strong> menu or by\npressing the associated toolbar button. This option will be\ndisabled if the Zip file does not contain a main comment.</p>\n\n<hr>\n<h3>Extracting Files</h3>\n\n<p>Once you have opened a Zip file into Pocket UnZip, you should\nsee a list of the Zip file's contents. Select one or more files\nfrom the file list and then choose <strong>Extract Selected Files</strong>\n(<strong>Ctrl+E</strong>) or <strong>Extract All Files</strong> (<strong>Ctrl+A</strong>,\n<strong>Ctrl+E</strong>) from the <strong>Action</strong> menu. You may\nalso use the noted shortcut keys or the associated toolbar\nbuttons.</p>\n\n<p>An extract options dialog will appear showing you some\nstatistics about the files you are about to extract and prompting\nyou for some information. There are three options available to\nyou.</p>\n\n<p>The <strong>Restore file paths</strong> option allows you to\ncontrol whether the directory structure of the files you have\nselected to extract will be preserved. When this option is\nchecked, any directory paths associated with the compressed files\nwill be created, and the file will be extracted to the newly\ncreated directory. If this option is not checked, all files will\nbe extracted to a single directory, regardless of any path\ninformation associated with the compressed files.</p>\n\n<p>The <strong>Overwrite Options</strong> allow you to tell\nPocket UnZip what to do if a file already exists on your file\nsystem with the same name of a file that is about to be\nextracted. The choices are:</p>\n\n<ul>\n    <li><strong>Prompt to overwrite</strong>: Causes a dialog to\n        appear for every situation that involves possibly\n        overwriting a file. This allows you to decide what files\n        get overwritten on a file-by-file basis. </li>\n    <li><strong>Overwrite if newer</strong>: Causes Pocket UnZip\n        to automatically overwrite any files that have a date and\n        time that is earlier then the date and time of the file\n        being extracted. This option can be useful for updating\n        files. </li>\n    <li><strong>Always overwrite</strong>: Causes Pocket UnZip to\n        always automatically overwrite any files without\n        prompting or warning. Use with caution. </li>\n    <li><strong>Never overwrite</strong>: Causes Pocket UnZip to\n        automatically skip all files that already exist on the\n        file system.</li>\n</ul>\n\n<p>The <strong>Extract To</strong> field specifies the root\ndirectory that should be used to extract files to. If you checked\nthe <strong>Restore file paths</strong> option, then any\ndirectories associated with the files being extracted will be\ncreated under the directory specified in this field. The\ndirectory you enter must already exist. To create directories and\nbrowse for directories, use the <strong>Browse...</strong>\nbutton.</p>\n\n<p>Once you have chosen the options you wish to use, press the <strong>Extract</strong>\nbutton. A progress dialog will appear and the extraction will\nbegin. At any time during the extraction, you may tap the <strong>Abort</strong>\nbutton to abort the extraction operation.</p>\n\n<p><strong>Note: Aborting the\nextraction operation while processing a file will likely cause a\npartial file to get extracted and saved.</strong></p>\n\n<p>During the extraction, you may get interrupted for one of\nthree reasons. First, if an error occurs, you will be notified\nwith a message box. Second, if you have chosen the <strong>Prompt\nto overwrite</strong> option and you are trying to extract a file\nthat already exists, you will be prompted on how to handle the\nsituation. Third, if a file being extracted is encrypted, then\nyou will be prompted for that file's password (see the <strong>Encrypted\nFiles</strong> section).</p>\n\n<p>Once the extraction is complete, the <strong>Abort</strong>\nbutton will change to a <strong>Close</strong> button and any\nerrors or warnings will be displayed. Tap the <strong>Close</strong>\nbutton to return to Pocket UnZip's main screen.</p>\n\n<hr>\n<h3>Testing Files</h3>\n\n<p>Testing files is essentially the same as extracting files,\nexcept for that the actual extracted data is never written to\nyour file system. Testing files is useful when you wish to verify\nthe integrity of a Zip file without actually extracting the files\nwithin it.</p>\n\n<p>Once you have opened a Zip file into Pocket UnZip, you should\nsee a list of the Zip file's contents. Select one or more files\nfrom the file list and then choose <strong>Test Selected Files</strong>\n(<strong>Ctrl+T</strong>) or <strong>Test All Files</strong> (<strong>Ctrl+A</strong>,\n<strong>Ctrl+T</strong>) from the <strong>Action</strong> menu. You may\nalso use the noted shortcut keys or the associated toolbar\nbuttons.</p>\n\n<p>A progress dialog will appear and the testing will begin. At\nany time during the testing, you may tap the <strong>Abort</strong>\nbutton to abort the testing operation.</p>\n\n<p>During the testing, you may get interrupted for one of two\nreasons. First, if an error occurs, you will be notified with a\nmessage box. Second, if a file being tested is encrypted, then\nyou will be prompted for that file's password (see the <strong>Encrypted\nFiles</strong> section).</p>\n\n<p>Once the testing is complete, the <strong>Abort</strong>\nbutton will change to a <strong>Close</strong> button and any\nerrors or warnings will be displayed. Tap the <strong>Close</strong>\nbutton to return to Pocket UnZip's main screen.</p>\n\n<hr>\n<h3>Viewing Files</h3>\n\n<p>Pocket UnZip provides the ability to view, or even execute,\nfiles directly from a Zip file. This feature is a major\nconvenience over having to extract and then manually open each\nfile you wish to view. Internally, this is what Pocket UnZip is\ndoing for you, but it takes care of all the work of extracting\nthe file to a temporary directory, launching the associated\nviewer for that file type, and cleaning up when done.</p>\n\n<p>To view a file, simply select a single file from Pocket\nUnZip's main file list and press <strong>Enter</strong>. You may also\nchoose <strong>View Selected File</strong> from the <strong>Action</strong>\nmenu, press the associated toolbar button, or just double-tap on\nthe file you wish to view.</p>\n\n<p>The file will be extracted to a directory called<strong>\nTemporary Pocket UnZip Files</strong> in the root of your file\nsystem. If the file you wish to view is encrypted, you will be\nprompted for a password. If the file has an associated viewer\napplication installed (such as Pocket Word for .PWD files), then\nthat viewer will automatically be launched with the newly\nextracted file as its command line. If there is no associated\nviewer application, then you will be prompted for the application\nyou wish to use to view the file.</p>\n\n<p>Pocket UnZip also provides minimal support for allowing you to\nuse the view file action to run executable programs directly from\nthe Zip file. If the file you choose to view is an executable\n(file extension is EXE), then the file will be executed after it\nis extracted. Pocket UnZip will only extract the file you select\nand none of its dependent files (like DLLs). If the executable\nyou extract depends on other files in the Zip file, it will most\nlikely fail to execute.</p>\n\n<p>When Pocket UnZip exits, it will delete the <strong>Temporary\nPocket UnZip Files</strong> directory and all the files in it. If\nyou are running more than one instance of Pocket UnZip, then only\nthe last instance of Pocket UnZip that you exit will perform this\ndelete. Most applications, such as Pocket Word, lock files when\nviewing them. Any files being viewed by such an application when\nyou exit Pocket UnZip will not be deleted.</p>\n\n<hr>\n<h3>Encrypted Files</h3>\n\n<p>If an encrypted file is encountered during an extract, test,\nor view operation, you will be prompted for a password. You can\nchoose to skip the file, skip all encrypted files, or enter a\npassword. You will be given three attempts at entering the\ncorrect password before the file will be skipped automatically.\nOnce you have entered the correct password for a given file, that\npassword will be remembered and automatically used for all other\nencrypted files that are encountered during that single extract,\ntest, or view operation. If another encrypted file is found that\nuses a different password than the remembered password, then you\nwill be prompted again for a new password.</p>\n\n<p>This technique provides support for multi-password Zip files,\nwhile still providing users with single password Zip files the\nconvenience of only having to enter their password once during\nthe operation for all encrypted files. For security reasons,\npasswords are not remembered after the operation completes.</p>\n\n<hr>\n<h3>About Pocket UnZip</h3>\n\n<p>Thank you for using Version 2.0 of Pocket UnZip for Windows\nCE.</p>\n\n<p>Pocket UnZip was developed by Steve P. Miller. Although I'd\nlike to take full credit, I could not have done it without the\npublic decompression source code provided by the Info-ZIP group.\nPocket UnZip uses version 6.0 of Info-ZIP's core decompression\ncode. Many thanks go to Greg Roelofs and all the fine folks at\nInfo-ZIP.</p>\n\n<p>Please send all comments, suggestions, and bug reports\nto <strong>stevemil@pobox.com</strong>.</p>\n\n<p>Pocket UnZip is freeware - no shareware fees, no purchase\nfees. You can still send me an email or a box of cookies if you\nlike it. If you would like to distribute Pocket UnZip, please\nlook at the terms and conditions listed in the accompaning\nInfo-ZIP LICENSE file.</p>\n\n<p>For the latest news, binaries, source code, and more\ninformation about the Info-ZIP group, visit\n<strong>ftp://ftp.info-zip.org/pub/infozip/</strong>.</p>\n\n<p>For more information about me, or to check out some of my\nother applications (mostly Windows 95 / NT / CE), stop by my\npersonal web page at <strong>http://pobox.com/~stevemil/</strong>.</p>\n\n<p>Copyright  1997-2009 Info-Zip. All Rights Reserved.</p>\n</body>\n</html>\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/punzip.rc",
    "content": "//Microsoft Developer Studio generated resource script.\n//\n#include \"resource.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"afxres.h\"\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// Englisch (USA) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\n#ifdef _WIN32\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n#pragma code_page(1252)\n#endif //_WIN32\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE DISCARDABLE\nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE DISCARDABLE\nBEGIN\n    \"#include \"\"afxres.h\"\"\\0\"\nEND\n\n3 TEXTINCLUDE DISCARDABLE\nBEGIN\n    \"#include \"\"punzip.rcv\"\"\\r\\n\"\n    \"#ifdef _WIN32_WCE\\r\\n\"\n    \"IDI_UNZIP ICON DISCARDABLE \"\"punzip.ic2\"\"\\r\\n\"\n    \"IDI_ZIPFILE ICON DISCARDABLE \"\"zipfile.ic2\"\"\\r\\n\"\n    \"IDB_TOOLBAR BITMAP DISCARDABLE \"\"toolbar.2bp\"\"\\r\\n\"\n    \"IDB_IMAGELIST BITMAP DISCARDABLE \"\"imglist.2bp\"\"\\r\\n\"\n    \"IDB_IMAGELIST_MASK BITMAP DISCARDABLE \"\"ilmask.bmp\"\"\\r\\n\"\n    \"#else\\r\\n\"\n    \"IDI_UNZIP ICON DISCARDABLE \"\"punzip.ico\"\"\\r\\n\"\n    \"IDI_ZIPFILE ICON DISCARDABLE \"\"zipfile.ico\"\"\\r\\n\"\n    \"IDB_TOOLBAR BITMAP DISCARDABLE \"\"toolbar.bmp\"\"\\r\\n\"\n    \"IDB_IMAGELIST BITMAP DISCARDABLE \"\"imglist.bmp\"\"\\r\\n\"\n    \"#endif\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Menu\n//\n\nIDR_UNZIP MENU DISCARDABLE\nBEGIN\n    POPUP \"&File\"\n    BEGIN\n        MENUITEM \"&Open...\\tCtrl+O\",            IDM_FILE_OPEN, GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM \"&Properties\\tAlt+Enter\",      IDM_FILE_PROPERTIES, GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM SEPARATOR\n        MENUITEM \"&Close\",                      IDM_FILE_CLOSE, GRAYED\n    END\n    POPUP \"&Actions\"\n    BEGIN\n        MENUITEM \"&Extract Selected Files\\tCtrl+E\", IDM_ACTION_EXTRACT\n        , GRAYED\n        MENUITEM \"E&xtract All Files\",          IDM_ACTION_EXTRACT_ALL\n        , GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM \"&Test Selected Files\\tCtrl+T\", IDM_ACTION_TEST, GRAYED\n        MENUITEM \"Te&st All Files\",             IDM_ACTION_TEST_ALL, GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM \"&View Selected File\\tEnter\",  IDM_ACTION_VIEW, GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM \"Select &All\\tCtrl+A\",         IDM_ACTION_SELECT_ALL\n        , GRAYED\n    END\n    POPUP \"&View\"\n    BEGIN\n        MENUITEM \"&Expanded View\",              IDM_VIEW_EXPANDED_VIEW\n        , GRAYED\n        MENUITEM SEPARATOR\n        MENUITEM \"Zip File &Comment\",           IDM_VIEW_COMMENT, GRAYED\n    END\n    POPUP \"&Help\"\n    BEGIN\n        MENUITEM \"&About Pocket UnZip\",         IDM_HELP_ABOUT, GRAYED\n    END\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_REPLACE DIALOG DISCARDABLE  1, 1, 250, 60\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION\nCAPTION \"Confirm File Replace\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    LTEXT           \"\",IDC_FILE,6,6,237,18,NOT WS_GROUP\n    LTEXT           \"Would you like to replace the existing file?\",\n                    IDC_STATIC,6,26,237,10,NOT WS_GROUP\n    PUSHBUTTON      \"&Yes\",IDM_REPLACE_YES,6,40,54,14\n    PUSHBUTTON      \"Yes to &All\",IDM_REPLACE_ALL,67,40,54,14\n    PUSHBUTTON      \"&No\",IDM_REPLACE_NO,128,40,54,14\n    PUSHBUTTON      \"N&o to All\",IDM_REPLACE_NONE,189,40,54,14\nEND\n\nIDD_COMMENT DIALOG DISCARDABLE  1, 1, 361, 196\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Zip File Comment\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    EDITTEXT        IDC_COMMENT,6,6,349,184,ES_MULTILINE | WS_VSCROLL |\n                    WS_HSCROLL | NOT WS_TABSTOP\nEND\n\nIDD_PROPERTIES DIALOG DISCARDABLE  0, 0, 251, 114\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Properties\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    EDITTEXT        IDC_COMMENT,6,18,238,90,ES_MULTILINE | NOT WS_VISIBLE |\n                    WS_VSCROLL | WS_HSCROLL\n    LTEXT           \"\",IDC_FILE,11,22,229,8\n    LTEXT           \"Size:\",IDC_STATIC,11,34,70,8\n    LTEXT           \"\",IDC_FILE_SIZE,84,34,100,8\n    LTEXT           \"Compressed Size:\",IDC_STATIC,11,46,70,8\n    LTEXT           \"\",IDC_COMPRESSED_SIZE,84,46,100,8\n    LTEXT           \"Compression Factor:\",IDC_STATIC,11,58,70,8\n    LTEXT           \"\",IDC_COMPRESSON_FACTOR,84,58,100,8\n    LTEXT           \"Compression Method:\",IDC_STATIC,11,70,70,8\n    LTEXT           \"\",IDC_COMPRESSION_METHOD,84,70,100,8\n    LTEXT           \"Modified:\",IDC_STATIC,11,82,70,8\n    LTEXT           \"\",IDC_MODIFIED,84,82,100,8\n    LTEXT           \"CRC:\",IDC_STATIC,11,94,70,8\n    LTEXT           \"\",IDC_CRC,84,94,100,8\n    LTEXT           \"Attributes:\",IDC_STATIC,190,34,50,8\n    CONTROL         \"Directory\",IDC_DIRECTORY,\"Button\",BS_3STATE,190,44,50,\n                    10\n    CONTROL         \"Read-only\",IDC_READONLY,\"Button\",BS_3STATE,190,54,50,10\n    CONTROL         \"Archive\",IDC_ARCHIVE,\"Button\",BS_3STATE,190,64,50,10\n    CONTROL         \"Hidden\",IDC_HIDDEN,\"Button\",BS_3STATE,190,74,50,10\n    CONTROL         \"System\",IDC_SYSTEM,\"Button\",BS_3STATE,190,84,50,10\n    CONTROL         \"Encrypted\",IDC_ENCRYPTED,\"Button\",BS_3STATE,190,94,50,\n                    10\n    CONTROL         \"Tab2\",IDC_TAB,\"SysTabControl32\",WS_TABSTOP,4,4,242,106\nEND\n\nIDD_EXTRACT DIALOG DISCARDABLE  0, 0, 297, 105\nSTYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nCAPTION \"Extract Files\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    DEFPUSHBUTTON   \"&Extract\",IDOK,246,6,45,14\n    PUSHBUTTON      \"&Cancel\",IDCANCEL,246,24,45,14\n    LTEXT           \"Files to extract:\",IDC_STATIC,12,18,54,8\n    RTEXT           \"\",IDC_FILE_COUNT,67,18,46,8\n    LTEXT           \"Bytes to extract:\",IDC_STATIC,12,30,54,8\n    RTEXT           \"\",IDC_BYTE_COUNT,67,30,46,8\n    GROUPBOX        \"Statistics\",IDC_STATIC,6,6,118,37\n    CONTROL         \"&Restore file paths\",IDC_RESTORE_PATHS,\"Button\",\n                    BS_AUTOCHECKBOX | WS_TABSTOP,8,47,118,10\n    LTEXT           \"Extract &To:\",IDC_STATIC,6,64,59,8\n    EDITTEXT        IDC_EXTRACT_TO,6,74,230,14,ES_AUTOHSCROLL\n    PUSHBUTTON      \"&Browse...\",IDC_BROWSE,246,74,45,14\n    LTEXT           \"If encrypted files are encountered during extraction, you will be prompted for a password.\",\n                    IDC_STATIC,6,91,285,8\n    CONTROL         \"&Prompt to overwrite\",IDC_OVERWRITE_PROMPT,\"Button\",\n                    BS_AUTORADIOBUTTON,138,18,80,10\n    CONTROL         \"&Overwrite if newer\",IDC_OVERWRITE_NEWER,\"Button\",\n                    BS_AUTORADIOBUTTON,138,30,80,10\n    CONTROL         \"&Always overwrite\",IDC_OVERWRITE_ALWAYS,\"Button\",\n                    BS_AUTORADIOBUTTON,138,42,80,10\n    CONTROL         \"&Never overwrite\",IDC_OVERWRITE_NEVER,\"Button\",\n                    BS_AUTORADIOBUTTON,138,54,80,10\n    GROUPBOX        \"Overwrite Options\",IDC_STATIC,132,6,104,61\nEND\n\nIDD_PASSWORD DIALOG DISCARDABLE  1, 1, 250, 79\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Password Required for Encrypted File\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    LTEXT           \"\",IDC_FILE,6,6,237,18,NOT WS_GROUP\n    LTEXT           \"\",IDC_PROMPT,6,26,237,10,NOT WS_GROUP\n    EDITTEXT        IDC_PASSWORD,6,40,237,14,ES_PASSWORD | ES_AUTOHSCROLL\n    PUSHBUTTON      \"Skip &All\",IDC_SKIP_ALL,170,59,73,14\n    DEFPUSHBUTTON   \"&Ok\",IDOK,6,59,73,14\n    PUSHBUTTON      \"&Skip\",IDCANCEL,88,59,73,14\nEND\n\nIDD_EXTRACT_PROGRESS DIALOG DISCARDABLE  0, 0, 400, 129\nSTYLE DS_MODALFRAME | WS_POPUP\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    PUSHBUTTON      \"&Abort\",IDCANCEL,6,110,112,14\n    LTEXT           \"File Progress\",IDC_FILE,6,5,389,8\n    CONTROL         \"Progress1\",IDC_FILE_PROGRESS,\"msctls_progress32\",\n                    WS_BORDER,6,15,112,10\n    LTEXT           \"Total Progress\",IDC_STATIC,6,28,61,8\n    RTEXT           \"0%\",IDC_PERCENTAGE,84,28,33,8\n    CONTROL         \"Progress1\",IDC_TOTAL_PROGRESS,\"msctls_progress32\",\n                    WS_BORDER,6,38,112,10\n    LTEXT           \"Files processed:\",IDC_STATIC,10,55,58,8\n    RTEXT           \"0\",IDC_FILES_PROCESSED,68,55,44,8\n    LTEXT           \"Files total:\",IDC_STATIC,10,66,58,8\n    RTEXT           \"\",IDC_FILES_TOTAL,68,66,44,8\n    LTEXT           \"Bytes processed:\",IDC_STATIC,10,83,58,8\n    RTEXT           \"0\",IDC_BYTES_PROCESSED,68,83,44,8\n    LTEXT           \"Bytes total:\",IDC_STATIC,10,94,58,8\n    RTEXT           \"\",IDC_BYTES_TOTAL,68,94,44,8\n    EDITTEXT        IDC_LOG,123,15,272,109,ES_MULTILINE | WS_VSCROLL |\n                    WS_HSCROLL\n    GROUPBOX        \"\",IDC_STATIC,6,49,112,29\n    GROUPBOX        \"\",IDC_STATIC,6,77,112,29\nEND\n\nIDD_ABOUT DIALOG DISCARDABLE  34, 22, 270, 126\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"About Pocket UnZip\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    ICON            100,IDC_STATIC,9,8,20,20\n    LTEXT           \"\",IDC_PRODUCT,36,15,228,8\n    LTEXT           \"\",IDC_VERSION,36,29,228,8\n    LTEXT           \"\",IDC_DEVELOPER,36,39,228,8\n    LTEXT           \"Visit my web site at http://pobox.com/~stevemil/\",\n                    IDC_STATIC,36,49,228,8\n    LTEXT           \"\",IDC_COPYRIGHT,36,59,228,8\n    CTEXT           \"Many thanks go to Greg Roelofs and all the fine folks at Info-ZIP.\",\n                    IDC_STATIC,5,79,259,8\n    CTEXT           \"\",IDC_COMMENT,20,89,229,16\n    CTEXT           \"Visit ftp://ftp.info-zip.org/pub/infozip/ for the latest news and binaries.\",\n                    IDC_STATIC,5,109,259,8\n    GROUPBOX        \"\",IDC_STATIC,3,0,263,71,BS_LEFT\n    GROUPBOX        \"\",IDC_STATIC,3,71,263,49,BS_LEFT\nEND\n\nIDD_VIEW_PROGRESS DIALOG DISCARDABLE  0, 0, 189, 57\nSTYLE DS_MODALFRAME | WS_POPUP\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    PUSHBUTTON      \"&Abort\",IDCANCEL,60,36,70,14\n    CTEXT           \"Extracting temporary file for your viewing pleasure.\",\n                    IDC_FILE,6,6,177,8\n    CONTROL         \"Progress1\",IDC_FILE_PROGRESS,\"msctls_progress32\",\n                    WS_BORDER,6,20,177,10\nEND\n\nIDD_VIEW_ASSOCIATION DIALOG DISCARDABLE  0, 0, 297, 63\nSTYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU\nCAPTION \"Open With\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    LTEXT           \"There does not appear to be any application associated with this file\",\n                    IDC_STATIC,6,6,230,10\n    LTEXT           \"type.  In order to view this file, you must specify a viewer application.\",\n                    IDC_STATIC,6,15,230,10\n    LTEXT           \"&Path to viewer application.\",IDC_STATIC,6,32,230,8\n    EDITTEXT        IDC_PATH,6,42,230,14,ES_AUTOHSCROLL\n    PUSHBUTTON      \"&Browse...\",IDC_BROWSE,246,42,45,14\n    DEFPUSHBUTTON   \"&OK\",IDOK,246,6,45,14\n    PUSHBUTTON      \"&Cancel\",IDCANCEL,246,24,45,14\nEND\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// DESIGNINFO\n//\n\n#ifdef APSTUDIO_INVOKED\nGUIDELINES DESIGNINFO DISCARDABLE\nBEGIN\n    IDD_REPLACE, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 243\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 54\n    END\n\n    IDD_COMMENT, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 355\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 190\n    END\n\n    IDD_PROPERTIES, DIALOG\n    BEGIN\n        LEFTMARGIN, 4\n        RIGHTMARGIN, 246\n        TOPMARGIN, 4\n        BOTTOMMARGIN, 110\n    END\n\n    IDD_EXTRACT, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 291\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 99\n    END\n\n    IDD_PASSWORD, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 243\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 73\n    END\n\n    IDD_EXTRACT_PROGRESS, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 394\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 123\n    END\n\n    IDD_ABOUT, DIALOG\n    BEGIN\n        RIGHTMARGIN, 265\n        TOPMARGIN, 1\n        BOTTOMMARGIN, 120\n    END\n\n    IDD_VIEW_PROGRESS, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 183\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 51\n    END\n\n    IDD_VIEW_ASSOCIATION, DIALOG\n    BEGIN\n        LEFTMARGIN, 6\n        RIGHTMARGIN, 291\n        TOPMARGIN, 6\n        BOTTOMMARGIN, 57\n    END\nEND\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Accelerator\n//\n\nIDR_UNZIP ACCELERATORS DISCARDABLE\nBEGIN\n    \"A\",            IDM_ACTION_SELECT_ALL,  VIRTKEY, CONTROL, NOINVERT\n    \"E\",            IDM_ACTION_EXTRACT,     VIRTKEY, CONTROL, NOINVERT\n    \"O\",            IDM_FILE_OPEN,          VIRTKEY, CONTROL, NOINVERT\n    \"T\",            IDM_ACTION_TEST,        VIRTKEY, CONTROL, NOINVERT\n    VK_RETURN,      IDM_ACTION_VIEW,        VIRTKEY, NOINVERT\n    VK_RETURN,      IDM_FILE_PROPERTIES,    VIRTKEY, ALT, NOINVERT\nEND\n\n#endif    // Englisch (USA) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n#include \"punzip.rcv\"\n#ifdef _WIN32_WCE\nIDI_UNZIP ICON DISCARDABLE \"punzip.ic2\"\nIDI_ZIPFILE ICON DISCARDABLE \"zipfile.ic2\"\nIDB_TOOLBAR BITMAP DISCARDABLE \"toolbar.2bp\"\nIDB_IMAGELIST BITMAP DISCARDABLE \"imglist.2bp\"\nIDB_IMAGELIST_MASK BITMAP DISCARDABLE \"ilmask.bmp\"\n#else\nIDI_UNZIP ICON DISCARDABLE \"punzip.ico\"\nIDI_ZIPFILE ICON DISCARDABLE \"zipfile.ico\"\nIDB_TOOLBAR BITMAP DISCARDABLE \"toolbar.bmp\"\nIDB_IMAGELIST BITMAP DISCARDABLE \"imglist.bmp\"\n#endif\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/punzip.rcv",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        PUNZIP.RCV\n//\n// Description: Resources that Microsoft Visual C++ does not edit directly.\n//              This file sets all the version defines and declares the Version\n//              Info resource.  This file is included by both the C compiler and\n//              the resource compiler.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n#ifndef __PUNZIP_RCV__\n#define __PUNZIP_RCV__\n\n#ifdef APSTUDIO_INVOKED\n   #error this file is not editable by Microsoft Visual C++\n#endif // APSTUDIO_INVOKED\n\n#ifdef _WIN32_WCE\n#define VS_FFI_FILEFLAGSMASK    0x0000003FL\n#define VS_FF_PRERELEASE        0x00000002L\n#define VOS__WINDOWS32          0x00000004L\n#define VFT_APP                 0x00000001L\n#define VFT2_UNKNOWN            0x00000000L\n#define VS_FF_DEBUG             0x00000001L\n#else\n#include <winver.h>\n#endif\n#include \"../unzvers.h\"\n\n//******************************************************************************\n//***** User Modifiable Version Defines\n//******************************************************************************\n\n#define VERSION_MAJOR        2\n#define VERSION_MINOR        0\n#define VERSION_PRIVATE      0\n#define VERSION_PATCH        UZ_PATCHLEVEL\n\n#define VERSION_STRING       \"2.0\"\n\n// Set VER_FF_PRERELEASE to VS_FF_PRERELEASE for beta and 0 for release.\n#ifdef BETA\n#define VER_FF_PRERELEASE VS_FF_PRERELEASE\n#else\n#define VER_FF_PRERELEASE 0\n#endif\n\n//******************************************************************************\n//***** Fixed Version Defines\n//******************************************************************************\n\n#define VER_INTERNALNAME_STR \"PUNZIP\"\n#define VER_PRODUCT_STR      \"Pocket UnZip\\256\"\n#define VER_DEVELOPER_STR    \"Steve P. Miller (stevemil@pobox.com)\"\n#define VER_COMMENT_STR      \"Pocket UnZip is built on top of Info-ZIP's UnZip \" UZ_VER_STRING UZ_BETALEVEL \" source code from \" UZ_VERSION_DATE \".\"\n\n#define VER_FILENAME_STR     VER_INTERNALNAME_STR \".EXE\"\n#define VER_VERSION          VERSION_MAJOR,VERSION_MINOR,VERSION_PRIVATE,VERSION_PATCH\n\n#define VER_COMPANY_STR      VER_DEVELOPER_STR\n#define VER_COPYRIGHT_STR    \"Copyright \\251 1997-2009 Info-ZIP.  All Rights Reserved.\"\n\n\n#ifdef UNICODE\n   #define VER_CODEPAGE \" Unicode)\"\n#else\n   #define VER_CODEPAGE \" Ansi)\"\n#endif\n\n#if defined(_X86_) || defined(_M_IX86)\n   #define VER_ARCH \" (i386,\" VER_CODEPAGE\n#elif defined(_MIPS_) || defined(_M_MRX000)\n   #define VER_ARCH \" (MIPS)\"\n#elif defined(_SH3_)\n   #define VER_ARCH \" (Hitachi SH-3)\"\n#elif defined(_PPC_) || defined(_M_PPC)\n   #define VER_ARCH \" (IBM PowerPC)\"\n#elif defined(_ALPHA_) || defined(_M_ALPHA)\n   #define VER_ARCH \" (DEC Alpha)\"\n#elif defined(_M_MPPC)\n   #define VER_ARCH \" (Macintosh PowerPC)\"\n#elif defined(_M_M68K)\n   #define VER_ARCH \" (Macintosh 68K)\"\n#else\n   #define VER_ARCH \"\"\n#endif\n\n\n#ifdef _DEBUG\n   #define VER_FF_DEBUG          VS_FF_DEBUG\n#else\n   #define VER_FF_DEBUG          0\n#endif\n\n#if (VERSION_PATCH > 0)\n   #define VER_FF_PATCHED        VS_FF_PATCHED\n#else\n   #define VER_FF_PATCHED        0\n#endif\n\n#if (VERSION_PRIVATE > 0)\n   #define VER_FF_PRIVATEBUILD   VS_FF_PRIVATEBUILD\n#else\n   #define VER_FF_PRIVATEBUILD   0\n#endif\n\n#ifdef _DEBUG\n   #if (VER_FF_PRERELEASE == VS_FF_PRERELEASE)\n      #define VER_VERSION_STR    VERSION_STRING \" Beta (Debug)\"\n   #else\n      #define VER_VERSION_STR    VERSION_STRING \" (Debug)\"\n   #endif\n#else\n   #if (VER_FF_PRERELEASE == VS_FF_PRERELEASE)\n      #define VER_VERSION_STR    VERSION_STRING \" Beta\"\n   #else\n      #define VER_VERSION_STR    VERSION_STRING\n   #endif\n#endif\n\n#ifdef _WIN32_WCE\n#define VER_FULLPRODUCT_STR      VER_PRODUCT_STR \" for Windows\\256 CE\" VER_ARCH\n#define VER_FULLVERSION_STR      VER_VERSION_STR \" for Windows\\256 CE\" VER_ARCH\n#else\n#define VER_FULLPRODUCT_STR      VER_PRODUCT_STR \" for Windows\\256 NT\" VER_ARCH\n#define VER_FULLVERSION_STR      VER_VERSION_STR \" for Windows\\256 NT\" VER_ARCH\n#endif\n\n//******************************************************************************\n//***** VERSIONINFO Resource\n//******************************************************************************\n\n#ifdef RC_INVOKED\n\nVS_VERSION_INFO VERSIONINFO\n\n   FILEVERSION    VER_VERSION\n   PRODUCTVERSION VER_VERSION\n   FILEFLAGSMASK  VS_FFI_FILEFLAGSMASK\n   FILEFLAGS      VER_FF_PRERELEASE | VER_FF_DEBUG | VER_FF_PATCHED | VER_FF_PRIVATEBUILD\n   FILEOS         VOS__WINDOWS32\n   FILETYPE       VFT_APP\n   FILESUBTYPE    VFT2_UNKNOWN\n\n   BEGIN\n      BLOCK \"StringFileInfo\"\n      BEGIN\n#ifdef UNICODE\n         BLOCK \"040904B0\"     // 0x0409 = U.S. English, 0x04B0 = Unicode\n#else\n         BLOCK \"040904E4\"     // 0x0409 = U.S. English, 0x04E4 = Ansi 1252\n#endif\n         BEGIN\n             VALUE \"CompanyName\",     VER_COMPANY_STR \"\\0\"\n             VALUE \"FileDescription\", VER_FULLPRODUCT_STR \"\\0\"\n             VALUE \"FileVersion\",     VER_FULLVERSION_STR \"\\0\"\n             VALUE \"InternalName\",    VER_INTERNALNAME_STR \"\\0\"\n             VALUE \"LegalCopyright\",  VER_COPYRIGHT_STR \"\\0\"\n             VALUE \"OriginalFilename\",VER_FILENAME_STR \"\\0\"\n             VALUE \"ProductName\",     VER_PRODUCT_STR \"\\0\"\n             VALUE \"ProductVersion\",  VER_VERSION_STR \"\\0\"\n             VALUE \"Comments\",        VER_COMMENT_STR \"\\0\"\n         END\n      END\n\n      BLOCK \"VarFileInfo\"\n      BEGIN\n#ifdef UNICODE\n         // English language (0x0409) and the Unicode codepage (1200)\n         VALUE \"Translation\", 0x0409, 1200\n#else\n         // English language (0x0409) and the Western Europe codepage (1252)\n         VALUE \"Translation\", 0x0409, 1252\n#endif\n      END\n   END\n\n#endif // RC_INVOKED\n\n#endif // __PUNZIP_RCV__\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by punzip.rc\n//\n\n#define IDR_UNZIP                       100\n\n#define IDI_UNZIP                       100\n#define IDI_ZIPFILE                     101\n\n#define IDB_TOOLBAR                     100\n#define IDB_IMAGELIST                   101\n#define IDB_IMAGELIST_MASK              102\n\n#define IDD_PROPERTIES                  100\n#define IDD_EXTRACT                     101\n#define IDD_REPLACE                     102\n#define IDD_EXTRACT_PROGRESS            103\n#define IDD_VIEW_PROGRESS               104\n#define IDD_PASSWORD                    105\n#define IDD_VIEW_ASSOCIATION            106\n#define IDD_COMMENT                     107\n#define IDD_ABOUT                       108\n\n#define IDC_TAB                         1000\n#define IDC_COMMENT                     1001\n#define IDC_FILES_TOTAL                 1002\n#define IDC_BYTES_TOTAL                 1003\n#define IDC_RESTORE_PATHS               1004\n#define IDC_OVERWRITE_PROMPT            1005\n#define IDC_OVERWRITE_NEWER             1006\n#define IDC_OVERWRITE_ALWAYS            1007\n#define IDC_OVERWRITE_NEVER             1008\n#define IDC_EXTRACT_TO                  1009\n#define IDC_BROWSE                      1010\n#define IDC_FILE                        1011\n#define IDC_PROMPT                      1012\n#define IDC_PASSWORD                    1013\n#define IDC_SKIP_ALL                    1014\n#define IDC_FILE_PROGRESS               1015\n#define IDC_PERCENTAGE                  1016\n#define IDC_TOTAL_PROGRESS              1017\n#define IDC_FILES_PROCESSED             1018\n#define IDC_FILE_COUNT                  1019\n#define IDC_BYTES_PROCESSED             1020\n#define IDC_BYTE_COUNT                  1021\n#define IDC_LOG                         1022\n#define IDC_FILE_SIZE                   1023\n#define IDC_MODIFIED                    1024\n#define IDC_COMPRESSED_SIZE             1025\n#define IDC_COMPRESSON_FACTOR           1026\n#define IDC_COMPRESSION_METHOD          1027\n#define IDC_CRC                         1028\n#define IDC_DIRECTORY                   1029\n#define IDC_READONLY                    1030\n#define IDC_ARCHIVE                     1031\n#define IDC_HIDDEN                      1032\n#define IDC_SYSTEM                      1033\n#define IDC_ENCRYPTED                   1034\n#define IDC_PRODUCT                     1035\n#define IDC_VERSION                     1036\n#define IDC_DEVELOPER                   1037\n#define IDC_COPYRIGHT                   1038\n#define IDC_PATH                        1039\n\n#define IDM_REPLACE_NO                  100\n#define IDM_REPLACE_TEXT                101\n#define IDM_REPLACE_YES                 102\n#define IDM_REPLACE_ALL                 103\n#define IDM_REPLACE_NONE                104\n#define IDM_REPLACE_RENAME              105\n#define IDM_REPLACE_HELP                106\n\n#define IDM_FILE_OPEN                   40001\n#define IDM_FILE_PROPERTIES             40002\n#define IDM_FILE_CLOSE                  40003\n#define IDM_ACTION_EXTRACT              40004\n#define IDM_ACTION_EXTRACT_ALL          40005\n#define IDM_ACTION_TEST                 40006\n#define IDM_ACTION_TEST_ALL             40007\n#define IDM_ACTION_VIEW                 40008\n#define IDM_ACTION_SELECT_ALL           40009\n#define IDM_VIEW_EXPANDED_VIEW          40010\n#define IDM_VIEW_COMMENT                40011\n#define IDM_HELP_ABOUT                  40012\n#define IDC_STATIC                      -1\n\n// Next default values for new objects\n//\n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        103\n#define _APS_NEXT_COMMAND_VALUE         40013\n#define _APS_NEXT_CONTROL_VALUE         1040\n#define _APS_NEXT_SYMED_VALUE           109\n#endif\n#endif\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/vc5/punzip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"punzip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\n# TARGTYPE \"Win32 (WCE MIPS) Application\" 0x0a01\n# TARGTYPE \"Win32 (WCE SH) Application\" 0x0901\n\nCFG=punzip - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.mak\" CFG=\"punzip - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"punzip - Win32 Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 ANSI Release\" (based on\\\n \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 ANSI Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Release\" (based on\\\n \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Debug\" (based on\\\n \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH) Release\" (based on\\\n \"Win32 (WCE SH) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH) Debug\" (based on\\\n \"Win32 (WCE SH) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"punzip__\"\n# PROP BASE Intermediate_Dir \"punzip__\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"AnsiRelease\"\n# PROP Intermediate_Dir \"AnsiRelease\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /YX /FD /c\n# SUBTRACT BASE CPP /X /Fr\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"punzip_0\"\n# PROP BASE Intermediate_Dir \"punzip_0\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"AnsiDebug\"\n# PROP Intermediate_Dir \"AnsiDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT BASE CPP /X /Fr\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WMIPSRel\"\n# PROP BASE Intermediate_Dir \"WMIPSRel\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WMIPSRel\"\n# PROP Intermediate_Dir \"WMIPSRel\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /O2 /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D \"_WIN32_WCE\" /D \"UNICODE\" /YX /QMRWCE /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D _WIN32_WCE=100 /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /QMRWCE /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d \"_WIN32_WCE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d \"_WIN32_WCE\" /d \"NDEBUG\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /machine:MIPS /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WMIPSDbg\"\n# PROP BASE Intermediate_Dir \"WMIPSDbg\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WMIPSDbg\"\n# PROP Intermediate_Dir \"WMIPSDbg\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D \"_WIN32_WCE\" /D \"UNICODE\" /YX /QMRWCE /c\n# ADD CPP /nologo /W3 /GX /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D _WIN32_WCE=100 /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /QMRWCE /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d \"_WIN32_WCE\" /d \"DEBUG\"\n# ADD RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d \"_WIN32_WCE\" /d \"DEBUG\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /machine:MIPS /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WCESHRel\"\n# PROP BASE Intermediate_Dir \"WCESHRel\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WCESHRel\"\n# PROP Intermediate_Dir \"WCESHRel\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /O2 /D \"NDEBUG\" /D \"SH3\" /D \"_SH3_\" /D \"_WIN32_WCE\" /D \"UNICODE\" /YX /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"SH3\" /D \"_SH3_\" /D _WIN32_WCE=100 /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"SH3\" /d \"_SH3_\" /d \"_WIN32_WCE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /r /d \"SH3\" /d \"_SH3_\" /d \"_WIN32_WCE\" /d \"NDEBUG\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /machine:SH3 /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WCESHDbg\"\n# PROP BASE Intermediate_Dir \"WCESHDbg\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WCESHDbg\"\n# PROP Intermediate_Dir \"WCESHDbg\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SH3\" /D \"_SH3_\" /D \"_WIN32_WCE\" /D \"UNICODE\" /YX /c\n# ADD CPP /nologo /W3 /GX /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"SH3\" /D \"_SH3_\" /D _WIN32_WCE=100 /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /c\n# SUBTRACT CPP /X /u /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"SH3\" /d \"_SH3_\" /d \"_WIN32_WCE\" /d \"DEBUG\"\n# ADD RSC /l 0x409 /r /d \"SH3\" /d \"_SH3_\" /d \"_WIN32_WCE\" /d \"DEBUG\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /machine:SH3 /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /map /nodefaultlib\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\n\n!ENDIF \n\n# Begin Target\n\n# Name \"punzip - Win32 Release\"\n# Name \"punzip - Win32 Debug\"\n# Name \"punzip - Win32 ANSI Release\"\n# Name \"punzip - Win32 ANSI Debug\"\n# Name \"punzip - Win32 (WCE MIPS) Release\"\n# Name \"punzip - Win32 (WCE MIPS) Debug\"\n# Name \"punzip - Win32 (WCE SH) Release\"\n# Name \"punzip - Win32 (WCE SH) Debug\"\n# Begin Group \"Info-ZIP Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\..\\api.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# Begin Group \"Pocket UnZip Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\intrface.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\intrface.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rc\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rcv\n# End Source File\n# Begin Source File\n\nSOURCE=..\\resource.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wcecfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.h\n# End Source File\n# End Group\n# Begin Group \"Resources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\ilmask.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ico\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ico\n# End Source File\n# End Group\n# Begin Group \"Documentation\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\Contents\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.htp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\README\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/vc6/punzip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"punzip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (WCE x86em) Application\" 0x7f01\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\n# TARGTYPE \"Win32 (WCE SH3) Application\" 0x8101\n# TARGTYPE \"Win32 (WCE MIPS) Application\" 0x8201\n\nCFG=punzip - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.mak\" CFG=\"punzip - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"punzip - Win32 Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 ANSI Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 ANSI Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"punzip - Win32 (WCE x86em) Release\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"punzip - Win32 (WCE x86em) Debug\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Release\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Debug\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH3) Release\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH3) Debug\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n# PROP WCE_FormatVersion \"6.0\"\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\" /d \"UNICODE\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"punzip__\"\n# PROP BASE Intermediate_Dir \"punzip__\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"AnsiRelease\"\n# PROP Intermediate_Dir \"AnsiRelease\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /YX /FD /c\n# SUBTRACT BASE CPP /X /Fr\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../..\" /D \"NDEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"_X86_\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"punzip_0\"\n# PROP BASE Intermediate_Dir \"punzip_0\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"AnsiDebug\"\n# PROP Intermediate_Dir \"AnsiDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /YX /FD /c\n# SUBTRACT BASE CPP /X /Fr\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../..\" /D \"_DEBUG\" /D \"_X86_\" /D \"_WINDOWS\" /D \"POCKET_UNZIP\" /D \"_MBCS\" /YX /FD /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"_X86_\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 user32.lib gdi32.lib comctl32.lib advapi32.lib shell32.lib comdlg32.lib /nologo /version:1.0 /subsystem:windows /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"x86emRel\"\n# PROP BASE Intermediate_Dir \"x86emRel\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"x86emRel\"\n# PROP Intermediate_Dir \"x86emRel\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /ML /W3 /O2 /D \"WIN32\" /D \"STRICT\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"NDEBUG\" /D \"x86\" /D \"i486\" /D \"_x86_\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\n# ADD CPP /nologo /MT /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"WIN32\" /D \"STRICT\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"NDEBUG\" /D \"x86\" /D \"i486\" /D \"_x86_\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"NDEBUG\"\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /machine:I386 /nodefaultlib:\"$(CENoDefaultLib)\" /windowsce:emulation\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /machine:I386 /nodefaultlib:\"$(CENoDefaultLib)\" /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"x86emDbg\"\n# PROP BASE Intermediate_Dir \"x86emDbg\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"x86emDbg\"\n# PROP Intermediate_Dir \"x86emDbg\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /MLd /W3 /Gm /Zi /Od /D \"WIN32\" /D \"STRICT\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"_DEBUG\" /D \"x86\" /D \"i486\" /D \"_x86_\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\n# SUBTRACT BASE CPP /X /u /Fr\n# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"WIN32\" /D \"STRICT\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"_DEBUG\" /D \"x86\" /D \"i486\" /D \"_x86_\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\n# SUBTRACT CPP /X /u /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"_DEBUG\" /d \"x86\" /d \"i486\" /d \"_x86_\"\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"_DEBUG\" /d \"x86\" /d \"i486\" /d \"_x86_\"\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /debug /machine:I386 /nodefaultlib:\"$(CENoDefaultLib)\" /windowsce:emulation\n# SUBTRACT BASE LINK32 /pdb:none /incremental:no /map /nodefaultlib\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /debug /machine:I386 /nodefaultlib:\"$(CENoDefaultLib)\" /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none /incremental:no /map /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WMIPSRel\"\n# PROP BASE Intermediate_Dir \"WMIPSRel\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WMIPSRel\"\n# PROP Intermediate_Dir \"WMIPSRel\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nCPP=clmips.exe\n# ADD BASE CPP /nologo /M$(CECrt) /W3 /O2 /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"UNICODE\" /YX /QMRWCE /c\n# ADD CPP /nologo /M$(CECrtMT) /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /QMRWCE /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"NDEBUG\"\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /machine:MIPS /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WMIPSDbg\"\n# PROP BASE Intermediate_Dir \"WMIPSDbg\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WMIPSDbg\"\n# PROP Intermediate_Dir \"WMIPSDbg\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nCPP=clmips.exe\n# ADD BASE CPP /nologo /M$(CECrtDebug) /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"UNICODE\" /YX /QMRWCE /c\n# ADD CPP /nologo /M$(CECrtMTDebug) /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /QMRWCE /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"DEBUG\"\n# ADD RSC /l 0x409 /r /d \"MIPS\" /d \"_MIPS_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"DEBUG\"\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /machine:MIPS /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WSH3Rel\"\n# PROP BASE Intermediate_Dir \"WSH3Rel\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WSH3Rel\"\n# PROP Intermediate_Dir \"WSH3Rel\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nCPP=shcl.exe\n# ADD BASE CPP /nologo /M$(CECrt) /W3 /O2 /D \"NDEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"UNICODE\" /YX /c\n# ADD CPP /nologo /M$(CECrtMT) /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\n# SUBTRACT CPP /X /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /r /d \"SH3\" /d \"SHx\" /d \"_SH3_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"NDEBUG\"\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /machine:SH3 /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WSH3Dbg\"\n# PROP BASE Intermediate_Dir \"WSH3Dbg\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WSH3Dbg\"\n# PROP Intermediate_Dir \"WSH3Dbg\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nCPP=shcl.exe\n# ADD BASE CPP /nologo /M$(CECrtDebug) /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"UNICODE\" /YX /c\n# ADD CPP /nologo /M$(CECrtMTDebug) /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CEConfigName)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /c\n# SUBTRACT CPP /X /u /Fr\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /r /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"DEBUG\"\n# ADD RSC /l 0x409 /r /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"$(CEConfigName)\" /d \"UNICODE\" /d \"DEBUG\"\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /machine:SH3 /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /map /nodefaultlib\n\n!ENDIF \n\n# Begin Target\n\n# Name \"punzip - Win32 Release\"\n# Name \"punzip - Win32 Debug\"\n# Name \"punzip - Win32 ANSI Release\"\n# Name \"punzip - Win32 ANSI Debug\"\n# Name \"punzip - Win32 (WCE x86em) Release\"\n# Name \"punzip - Win32 (WCE x86em) Debug\"\n# Name \"punzip - Win32 (WCE MIPS) Release\"\n# Name \"punzip - Win32 (WCE MIPS) Debug\"\n# Name \"punzip - Win32 (WCE SH3) Release\"\n# Name \"punzip - Win32 (WCE SH3) Debug\"\n# Begin Group \"Info-ZIP Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\..\\api.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\acorn\\swiven.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\amiga\\memwatch.h\"\\\n\t\"..\\..\\amiga\\z-stat.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\stat.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# Begin Group \"Pocket UnZip Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\intrface.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\intrface.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rc\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rcv\n# End Source File\n# Begin Source File\n\nSOURCE=..\\resource.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wcecfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 ANSI Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\win32\\rsxntwin.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\macdir.h\"\\\n\t\"..\\..\\macstat.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.h\n# End Source File\n# End Group\n# Begin Group \"Resources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\ilmask.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ico\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ico\n# End Source File\n# End Group\n# Begin Group \"Documentation\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\Contents\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.htp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\README\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/vcEMbed3/punzip.vcp",
    "content": "# Microsoft eMbedded Visual Tools Project File - Name=\"punzip\" - Package Owner=<4>\n# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (WCE x86em) Application\" 0x7f01\n# TARGTYPE \"Win32 (WCE SH3) Application\" 0x8101\n# TARGTYPE \"Win32 (WCE MIPS) Application\" 0x8201\n\nCFG=punzip - Win32 (WCE SH3) Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.vcn\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"punzip.vcn\" CFG=\"punzip - Win32 (WCE SH3) Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"punzip - Win32 (WCE x86em) Release\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"punzip - Win32 (WCE x86em) Debug\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Release\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE MIPS) Debug\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH3) Release\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"punzip - Win32 (WCE SH3) Debug\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n# PROP ATL_Project 0\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"x86emRel\"\n# PROP BASE Intermediate_Dir \"x86emRel\\GuiBuild\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"x86emRel\"\n# PROP Intermediate_Dir \"x86emRel\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"UNICODE\" /d \"WIN32\" /d \"STRICT\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"NDEBUG\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /O2 /D \"NDEBUG\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"x86\" /D \"i486\" /D \"_X86_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /YX /Gz /c\n# ADD CPP /nologo /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"x86\" /D \"i486\" /D \"_X86_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /Gz /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"x86emDbg\"\n# PROP BASE Intermediate_Dir \"x86emDbg\\GuiBuild\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"x86emDbg\"\n# PROP Intermediate_Dir \"x86emDbg\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"UNICODE\" /d \"_UNICODE\" /d \"WIN32\" /d \"STRICT\" /d \"x86\" /d \"i486\" /d \"_X86_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"UNICODE\" /d \"_UNICODE\" /d \"WIN32\" /d \"STRICT\" /d \"x86\" /d \"i486\" /d \"_X86_\" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"_WIN32_WCE_EMULATION\" /d \"INTERNATIONAL\" /d \"USA\" /d \"INTLMSG_CODEPAGE\" /d \"_DEBUG\"\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"_DEBUG\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"x86\" /D \"i486\" /D \"_X86_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /YX /Gz /c\n# SUBTRACT BASE CPP /X /u /Fr\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"_DEBUG\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"x86\" /D \"i486\" /D \"_X86_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /Gz /c\n# SUBTRACT CPP /X /u /Fr\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /debug /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT BASE LINK32 /pdb:none /incremental:no /map /nodefaultlib\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /stack:0x10000,0x1000 /subsystem:windows /debug /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none /incremental:no /map /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WMIPSRel\"\n# PROP BASE Intermediate_Dir \"WMIPSRel\\GuiBuild\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WMIPSRel\"\n# PROP Intermediate_Dir \"WMIPSRel\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"MIPS\" /d \"_MIPS_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"NDEBUG\" /r\n# ADD RSC /l 0x409 /d \"MIPS\" /d \"_MIPS_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"NDEBUG\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /O2 /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D _WIN32_WCE=$(CEVersion) /D UNDER_CE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /YX /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /M$(CECrtMT) /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /nodefaultlib:\"$(CENoDefaultLib)\" /machine:MIPS /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WMIPSDbg\"\n# PROP BASE Intermediate_Dir \"WMIPSDbg\\GuiBuild\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WMIPSDbg\"\n# PROP Intermediate_Dir \"WMIPSDbg\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"MIPS\" /d \"_MIPS_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"DEBUG\" /r\n# ADD RSC /l 0x409 /d \"MIPS\" /d \"_MIPS_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"DEBUG\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D _WIN32_WCE=$(CEVersion) /D UNDER_CE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /M$(CECrtMTDebug) /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:MIPS /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /nodefaultlib:\"$(CENoDefaultLib)\" /machine:MIPS /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WSH3Rel\"\n# PROP BASE Intermediate_Dir \"WSH3Rel\\GuiBuild\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WSH3Rel\"\n# PROP Intermediate_Dir \"WSH3Rel\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"NDEBUG\" /r\n# ADD RSC /l 0x409 /d \"SH3\" /d \"SHx\" /d \"_SH3_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"NDEBUG\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /O2 /D \"NDEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D _WIN32_WCE=$(CEVersion) /D UNDER_CE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /YX /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /O2 /I \"../..\" /I \"../../wince/inc\" /D \"NDEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /M$(CECrtMT) /c\n# SUBTRACT CPP /X /Fr\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libc.lib /nologo /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /nodefaultlib:\"$(CENoDefaultLib)\" /machine:SH3 /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /nodefaultlib\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WSH3Dbg\"\n# PROP BASE Intermediate_Dir \"WSH3Dbg\\GuiBuild\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WSH3Dbg\"\n# PROP Intermediate_Dir \"WSH3Dbg\\GuiBuild\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nPFILE=pfile.exe\n# ADD BASE PFILE COPY\n# ADD PFILE COPY\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"DEBUG\" /r\n# ADD RSC /l 0x409 /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"DEBUG\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D _WIN32_WCE=$(CEVersion) /D UNDER_CE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"POCKET_UNZIP\" /D \"UNICODE\" /D \"_MBCS\" /YX /M$(CECrtMTDebug) /c\n# SUBTRACT CPP /X /u /Fr\nMTL=midl.exe\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib libcd.lib /nologo /debug /machine:SH3 /subsystem:windowsce\n# SUBTRACT BASE LINK32 /pdb:none /nodefaultlib\n# ADD LINK32 coredll.lib commctrl.lib /nologo /debug /nodefaultlib:\"$(CENoDefaultLib)\" /machine:SH3 /subsystem:windowsce\n# SUBTRACT LINK32 /pdb:none /map /nodefaultlib\n\n!ENDIF \n\n# Begin Target\n\n# Name \"punzip - Win32 (WCE x86em) Release\"\n# Name \"punzip - Win32 (WCE x86em) Debug\"\n# Name \"punzip - Win32 (WCE MIPS) Release\"\n# Name \"punzip - Win32 (WCE MIPS) Debug\"\n# Name \"punzip - Win32 (WCE SH3) Release\"\n# Name \"punzip - Win32 (WCE SH3) Debug\"\n# Begin Group \"Info-ZIP Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\..\\api.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_API_C=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_API_C=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# Begin Group \"Pocket UnZip Sources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\intrface.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\intrface.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rc\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.rcv\n# End Source File\n# Begin Source File\n\nSOURCE=..\\resource.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wcecfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.cpp\n\n!IF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"punzip - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINMA=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_WINMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\winmain.h\n# End Source File\n# End Group\n# Begin Group \"Resources\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\ilmask.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\imglist.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.ico\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.2bp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\toolbar.bmp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ic2\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipfile.ico\n# End Source File\n# End Group\n# Begin Group \"Documentation\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\Contents\n# End Source File\n# Begin Source File\n\nSOURCE=..\\punzip.htp\n# End Source File\n# Begin Source File\n\nSOURCE=..\\README\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/vcEMbed3/unzipcmd.vcp",
    "content": "# Microsoft eMbedded Visual Tools Project File - Name=\"unzipcmd\" - Package Owner=<4>\n# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (WCE ARM) Application\" 0x8501\n# TARGTYPE \"Win32 (WCE x86em) Application\" 0x7f01\n# TARGTYPE \"Win32 (WCE SH3) Application\" 0x8101\n# TARGTYPE \"Win32 (WCE SH4) Application\" 0x8601\n# TARGTYPE \"Win32 (WCE MIPS) Application\" 0x8201\n\nCFG=unzipcmd - Win32 (WCE MIPS) Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipcmd.vcn\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzipcmd.vcn\" CFG=\"unzipcmd - Win32 (WCE MIPS) Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzipcmd - Win32 (WCE x86em) Release\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE x86em) Debug\" (based on \"Win32 (WCE x86em) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE MIPS) Release\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE MIPS) Debug\" (based on \"Win32 (WCE MIPS) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE SH4) Release\" (based on \"Win32 (WCE SH4) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE SH4) Debug\" (based on \"Win32 (WCE SH4) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE SH3) Release\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE SH3) Debug\" (based on \"Win32 (WCE SH3) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE ARM) Release\" (based on \"Win32 (WCE ARM) Application\")\n!MESSAGE \"unzipcmd - Win32 (WCE ARM) Debug\" (based on \"Win32 (WCE ARM) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\n# PROP ATL_Project 2\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"x86emRel\"\n# PROP BASE Intermediate_Dir \"x86emRel\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"x86emRel\"\n# PROP Intermediate_Dir \"x86emRel\\ConBuild\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"i486\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"i486\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Ox /Os /D _WIN32_WCE=$(CEVersion) /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"$(CePlatform)\" /D \"i486\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NDEBUG\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /Ox /Os /I \"../..\" /I \"../../wince/inc\" /D \"_X86_\" /D \"x86\" /D \"i486\" /D \"NDEBUG\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /subsystem:windows /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:\"\" /stack:0x10000,0x1000 /subsystem:windows /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"x86emDbg\"\n# PROP BASE Intermediate_Dir \"x86emDbg\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"x86emDbg\"\n# PROP Intermediate_Dir \"x86emDbg\\ConBuild\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"i486\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"_X86_\" /d \"x86\" /d \"i486\" /r\nCPP=cl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"i486\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_X86_\" /D \"x86\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"_X86_\" /D \"x86\" /D \"i486\" /D \"WIN32\" /D \"STRICT\" /D \"_WIN32_WCE_EMULATION\" /D \"INTERNATIONAL\" /D \"USA\" /D \"INTLMSG_CODEPAGE\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /subsystem:windows /debug /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT BASE LINK32 /incremental:no\n# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:\"\" /stack:0x10000,0x1000 /subsystem:windows /debug /nodefaultlib:$(CENoDefaultLib) /machine:I386 /windowsce:emulation\n# SUBTRACT LINK32 /pdb:none\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WMIPSRel\"\n# PROP BASE Intermediate_Dir \"WMIPSRel\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519010-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WMIPSRel\"\n# PROP Intermediate_Dir \"WMIPSRel\\ConBuild\"\n# PROP CPU_ID \"{D6519010-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /Oxs /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /Ox /Os /I \"../..\" /I \"../../wince/inc\" /D \"MIPS\" /D \"_MIPS_\" /D \"NDEBUG\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPS\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPS\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WMIPSDbg\"\n# PROP BASE Intermediate_Dir \"WMIPSDbg\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519010-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WMIPSDbg\"\n# PROP Intermediate_Dir \"WMIPSDbg\\ConBuild\"\n# PROP CPU_ID \"{D6519010-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"MIPS\" /d \"_MIPS_\" /r\nCPP=clmips.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"MIPS\" /D \"_MIPS_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPS\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:MIPS\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WSH4Rel\"\n# PROP BASE Intermediate_Dir \"WSH4Rel\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519021-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WSH4Rel\"\n# PROP Intermediate_Dir \"WSH4Rel\\ConBuild\"\n# PROP CPU_ID \"{D6519021-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH4\" /d \"_SH4_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"NDEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH4\" /d \"_SH4_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH4\" /D \"_SH4_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /Qsh4 /Oxs /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /Ox /Os /I \"../..\" /I \"../../wince/inc\" /D \"SHx\" /D \"SH4\" /D \"_SH4_\" /D \"NDEBUG\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /Qsh4 /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH4\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH4\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WSH4Dbg\"\n# PROP BASE Intermediate_Dir \"WSH4Dbg\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519021-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WSH4Dbg\"\n# PROP Intermediate_Dir \"WSH4Dbg\\ConBuild\"\n# PROP CPU_ID \"{D6519021-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH4\" /d \"_SH4_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"DEBUG\" /d \"UNICODE\" /d \"_UNICODE\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH4\" /d \"_SH4_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH4\" /D \"_SH4_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /Qsh4 /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"SHx\" /D \"SH4\" /D \"_SH4_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /Qsh4 /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH4\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH4\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"WSH3Rel\"\n# PROP BASE Intermediate_Dir \"WSH3Rel\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"WSH3Rel\"\n# PROP Intermediate_Dir \"WSH3Rel\\ConBuild\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /Oxs /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /Ox /Os /I \"../..\" /I \"../../wince/inc\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D \"NDEBUG\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"WSH3Dbg\"\n# PROP BASE Intermediate_Dir \"WSH3Dbg\\ConBuild\"\n# PROP BASE CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"WSH3Dbg\"\n# PROP Intermediate_Dir \"WSH3Dbg\\ConBuild\"\n# PROP CPU_ID \"{D6519020-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"SHx\" /d \"SH3\" /d \"_SH3_\" /r\nCPP=shcl.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"SHx\" /D \"SH3\" /D \"_SH3_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /MACHINE:SH3\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"ARMRel\"\n# PROP BASE Intermediate_Dir \"ARMRel\\ConBuild\"\n# PROP BASE CPU_ID \"{D6518FFC-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"ARMRel\"\n# PROP Intermediate_Dir \"ARMRel\\ConBuild\"\n# PROP CPU_ID \"{D6518FFC-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"NDEBUG\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"ARM\" /D \"_ARM_\" /D UNDER_CE=$(CEVersion) /D \"UNICODE\" /D \"_UNICODE\" /D \"NDEBUG\" /YX /Oxs /M$(CECrtMT) /c\n# ADD CPP /nologo /W3 /Ox /Os /I \"../..\" /I \"../../wince/inc\" /D \"ARM\" /D \"_ARM_\" /D \"NDEBUG\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMT) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"ARMDbg\"\n# PROP BASE Intermediate_Dir \"ARMDbg\\ConBuild\"\n# PROP BASE CPU_ID \"{D6518FFC-710F-11D3-99F2-00105A0DF099}\"\n# PROP BASE Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"ARMDbg\"\n# PROP Intermediate_Dir \"ARMDbg\\ConBuild\"\n# PROP CPU_ID \"{D6518FFC-710F-11D3-99F2-00105A0DF099}\"\n# PROP Platform_ID \"{8A9A2F80-6887-11D3-842E-005004848CBA}\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\nRSC=rc.exe\n# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /r\n# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d \"UNICODE\" /d \"_UNICODE\" /d \"DEBUG\" /d \"$(CePlatform)\" /d \"ARM\" /d \"_ARM_\" /r\nCPP=clarm.exe\n# ADD BASE CPP /nologo /W3 /Zi /Od /D \"DEBUG\" /D \"ARM\" /D \"_ARM_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /YX /M$(CECrtMTDebug) /c\n# ADD CPP /nologo /W3 /Zi /Od /I \"../..\" /I \"../../wince/inc\" /D \"DEBUG\" /D \"ARM\" /D \"_ARM_\" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D \"$(CePlatform)\" /D \"UNICODE\" /D \"_UNICODE\" /D \"_MBCS\" /D \"NO_ZIPINFO\" /YX /M$(CECrtMTDebug) /c\nMTL=midl.exe\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n# ADD LINK32 commctrl.lib coredll.lib /nologo /base:\"0x00010000\" /stack:0x10000,0x1000 /entry:\"WinMainCRTStartup\" /debug /nodefaultlib:\"$(CENoDefaultLib)\" /subsystem:$(CESubsystem) /align:\"4096\" /MACHINE:ARM\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzipcmd - Win32 (WCE x86em) Release\"\n# Name \"unzipcmd - Win32 (WCE x86em) Debug\"\n# Name \"unzipcmd - Win32 (WCE MIPS) Release\"\n# Name \"unzipcmd - Win32 (WCE MIPS) Debug\"\n# Name \"unzipcmd - Win32 (WCE SH4) Release\"\n# Name \"unzipcmd - Win32 (WCE SH4) Debug\"\n# Name \"unzipcmd - Win32 (WCE SH3) Release\"\n# Name \"unzipcmd - Win32 (WCE SH3) Debug\"\n# Name \"unzipcmd - Win32 (WCE ARM) Release\"\n# Name \"unzipcmd - Win32 (WCE ARM) Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_CRC32=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRC32=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_CRYPT=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_CRYPT=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\explode.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_EXPLO=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXPLO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\extract.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_EXTRA=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_EXTRA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_FILEI=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\ebcdic.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_FILEI=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\charconv.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_GLOBA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_GLOBA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_INFLA=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\inflate.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_INFLA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\intrface.cpp\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_INTRF=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\"..\\winmain.h\"\\\n\t\nNODEP_CPP_INTRF=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\list.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_LIST_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_LIST_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\match.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_MATCH=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_MATCH=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\process.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_PROCE=\\\n\t\"..\\..\\crc32.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_PROCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_TTYIO=\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\ttyio.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\zip.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_TTYIO=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ubz2err.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\decs.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\..\\windll\\windll.h\"\\\n\t\"..\\intrface.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UBZ2ERR_=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unreduce.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_UNRED=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNRED=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unshrink.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_UNSHR=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNSHR=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_UNZIP=\\\n\t\"..\\..\\consts.h\"\\\n\t\"..\\..\\crypt.h\"\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_UNZIP=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wcemain.c\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_WCEMA=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WCEMA=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.cpp\n\n!IF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE x86em) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE MIPS) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH4) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE SH3) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Release\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ELSEIF  \"$(CFG)\" == \"unzipcmd - Win32 (WCE ARM) Debug\"\n\nDEP_CPP_WINCE=\\\n\t\"..\\..\\globals.h\"\\\n\t\"..\\..\\timezone.h\"\\\n\t\"..\\..\\unzip.h\"\\\n\t\"..\\..\\unzpriv.h\"\\\n\t\"..\\..\\unzvers.h\"\\\n\t\"..\\..\\windll\\structs.h\"\\\n\t\"..\\punzip.h\"\\\n\t\"..\\punzip.rcv\"\\\n\t\"..\\wcecfg.h\"\\\n\t\"..\\wince.h\"\\\n\t\nNODEP_CPP_WINCE=\\\n\t\"..\\..\\acorn\\riscos.h\"\\\n\t\"..\\..\\amiga\\amiga.h\"\\\n\t\"..\\..\\aosvs\\aosvs.h\"\\\n\t\"..\\..\\flexos\\flxcfg.h\"\\\n\t\"..\\..\\maccfg.h\"\\\n\t\"..\\..\\msdos\\doscfg.h\"\\\n\t\"..\\..\\netware\\nlmcfg.h\"\\\n\t\"..\\..\\os2\\os2cfg.h\"\\\n\t\"..\\..\\os2\\os2data.h\"\\\n\t\"..\\..\\qdos\\izqdos.h\"\\\n\t\"..\\..\\tandem.h\"\\\n\t\"..\\..\\theos\\thscfg.h\"\\\n\t\"..\\..\\unix\\unxcfg.h\"\\\n\t\"..\\..\\vmmvs.h\"\\\n\t\"..\\..\\win32\\w32cfg.h\"\\\n\t\"..\\..\\zlib.h\"\\\n\t\n\n!ENDIF \n\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\consts.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\inflate.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\intrface.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzpriv.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\unzvers.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wcecfg.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\wince.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/vcEMbed3/unzipwce.vcw",
    "content": "Microsoft eMbedded Visual Tools Workspace File, Format Version 3.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"punzip\"=\".\\punzip.vcp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unzipcmd\"=\".\\unzipcmd.vcp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/wcecfg.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n    WinCE \"command line tool\" specific configuration section:\n  ---------------------------------------------------------------------------*/\n\n#ifndef __wcecfg_h\n#define __wcecfg_h\n\n/*---------------------------------------------------------------------------\n    Standard Win32 project flags\n  ---------------------------------------------------------------------------*/\n\n#ifdef _WIN32_WCE   /* for native Windows CE, force UNICODE mode */\n#ifndef UNICODE\n#define UNICODE\n#endif\n#endif /* _WIN32_WCE */\n\n// for UnZip, the \"basic\" part of the win32 api is sufficient\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#if defined(_UNICODE) && !defined(UNICODE)\n#define UNICODE\n#endif\n\n#if defined(UNICODE) && !defined(_UNICODE)\n#define _UNICODE\n#endif\n\n#if defined(_DEBUG) && !defined(DEBUG)\n#define DEBUG\n#endif\n\n#if defined(DEBUG) && !defined(_DEBUG)\n#define _DEBUG\n#endif\n\n#if defined(_NDEBUG) && !defined(NDEBUG)\n#define NDEBUG\n#endif\n\n#if defined(NDEBUG) && !defined(_NDEBUG)\n#define _NDEBUG\n#endif\n\n//******************************************************************************\n//***** Common Info-ZIP UnZip feature/configuration flags\n//******************************************************************************\n\n// Windows CE environment allows support for UTC time stamps\n#ifndef USE_EF_UT_TIME\n#define USE_EF_UT_TIME\n#endif\n\n// NTFS extended attributes support is not available on Windows CE\n#ifndef NO_NTSD_EAS\n#define NO_NTSD_EAS\n#endif\n\n#ifdef NTSD_EAS\n#undef NTSD_EAS\n#endif\n\n#ifdef _WIN32_WCE\n// Windows CE does not provide the rename() function needed for UNIXBACKUP\n# ifndef NO_UNIXBACKUP\n#  define NO_UNIXBACKUP\n# endif\n# ifdef UNIXBACKUP\n#  undef UNIXBACKUP\n# endif\n#endif\n\n#if (!defined(NO_UNICODE_SUPPORT) && !defined(UNICODE_SUPPORT))\n#define UNICODE_SUPPORT\n#endif\n#if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR))\n#define UNICODE_WCHAR           /* wchar_t is UTF-16 encoded on WinCE */\n#endif\n#ifdef UTF8_MAYBE_NATIVE\n#undef UTF8_MAYBE_NATIVE        /* UTF-8 cannot be system charset on WinCE */\n#endif\n\n#ifdef POCKET_UNZIP\n// The PUnZip GUI interface does not make use of ZipInfo style archive\n// listings.\n// For the command-line tool, it may be considered to disable ZipInfo, too,\n// to save memory and resources.\n# ifndef NO_ZIPINFO\n# define NO_ZIPINFO\n# endif\n#endif\n\n#ifndef POCKET_UNZIP\n// CE does not support exception handling model\n# define NO_EXCEPT_SIGNALS\n# define MAIN main_stub\n#endif\n\n//******************************************************************************\n//***** Global defines, constants, and macros\n//******************************************************************************\n\n#if (defined(_MSC_VER) && !defined(MSC))\n#define MSC\n#endif\n\n#ifndef PATH_MAX\n#define PATH_MAX _MAX_PATH\n#endif\n\n// WinCE uses ISO 8859-1 as codepage for 8-bit chars\n#define CRTL_CP_IS_ISO\n// The functionality of ISO <--> OEM conversion IS needed on WinCE, too!!\n// (Otherwise, extended ASCII filenames and passwords in archives coming\n// from other platforms may not be handled properly.)\n// Since WinCE does not supply ISO <--> OEM conversion, we try to fall\n// back to the hardcoded tables in the generic UnZip code.\n\n#define ASCII2OEM(c) (((c) & 0x80) ? iso2oem[(c) & 0x7f] : (c))\n#if !defined(IZ_ISO2OEM_ARRAY)\n#  define IZ_ISO2OEM_ARRAY\n#endif\n#if !defined(CRYP_USES_ISO2OEM)\n#  define CRYP_USES_ISO2OEM\n#endif\n\n#define OEM_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#define INTERN_TO_ISO(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#define INTERN_TO_OEM(src, dst)  {register uch c;\\\n    register uch *dstp = (uch *)(dst), *srcp = (uch *)(src);\\\n    do {\\\n        c = (uch)foreign(*srcp++);\\\n        *dstp++ = (uch)ASCII2OEM(c);\\\n    } while (c != '\\0');}\n\n#if defined(UNICODE)\n#  define MBSTOTSTR mbstowcs\n#  define TSTRTOMBS wcstombs\n#else\n#  define MBSTOTSTR strncpy\n#  define TSTRTOMBS strncpy\n#endif\n\n\n#if (defined(_MBCS) && !defined(_WIN32_WCE))\n   /* MSC-specific version, _mbsinc() may not be available for other systems */\n#  define CLEN(ptr) _mbclen((const UCHAR *)(ptr))\n#  define PREINCSTR(ptr) (ptr = (char *)_mbsinc((const UCHAR *)(ptr)))\n#  define MBSCHR(str, c) (char *)_mbschr((const UCHAR *)(str), (c))\n#  define MBSRCHR(str, c) (char *)_mbsrchr((const UCHAR *)(str), (c))\n#endif\n\n/* Up to now, all versions of Microsoft C runtime libraries lack the support\n * for customized (non-US) switching rules between daylight saving time and\n * standard time in the TZ environment variable string.\n * But non-US timezone rules are correctly supported when timezone information\n * is read from the OS system settings in the Win32 registry.\n * The following work-around deletes any TZ environment setting from\n * the process environment.  This results in a fallback of the RTL time\n * handling code to the (correctly interpretable) OS system settings, read\n * from the registry.\n */\n#ifdef USE_EF_UT_TIME\n# if (defined(_WIN32_WCE) || defined(W32_USE_IZ_TIMEZONE))\n#   define iz_w32_prepareTZenv()\n# else\n#   define iz_w32_prepareTZenv()        putenv(\"TZ=\")\n# endif\n#endif\n\n#ifdef DIR_END\n#undef DIR_END\n#define DIR_END   '\\\\' // ZipInfo with VC++ 4.0 requires this\n#endif\n\n// We are defining a few new error types for our code.\n#define PK_EXCEPTION  500\n#define PK_ABORTED    501\n\n#ifndef DATE_FORMAT\n#define DATE_FORMAT   DF_MDY\n#endif\n#if ((_WIN32_WCE >= 211) && !defined(POCKET_UNZIP))\n# ifndef USE_FWRITE\n# define USE_FWRITE\n# endif\n#endif\n#define lenEOL        2\n#define PutNativeEOL  {*q++ = native(CR); *q++ = native(LF);}\n\n#define countof(a) (sizeof(a)/sizeof(*(a)))\n\n// The max number of retries (not including the first attempt) for entering\n// a password for and encrypted file before giving up on that file.\n#define MAX_PASSWORD_RETRIES 2\n\n#ifdef POCKET_UNZIP\n\n// Variables that we want to add to our Globals struct.\n#define SYSTEM_SPECIFIC_GLOBALS  \\\n   char  matchname[FILNAMSIZ];   \\\n   int   notfirstcall;           \\\n   char *zipfnPtr;               \\\n   char *wildzipfnPtr;\n\n#else /* !POCKET_UNZIP */\n\n/* Static variables that we have to add to Uz_Globs: */\n#define SYSTEM_SPECIFIC_GLOBALS \\\n    char rootpath[_MAX_PATH];\\\n    char *wildname, *matchname;\\\n    int rootlen, notfirstcall;\n\n/* This replacement for C-RTL-supplied getch() (or similar) functionality\n * avoids leaving unabsorbed LFs in the keyboard buffer under Windows95,\n * and supports the <ALT>+[0]<digit><digit><digit> feature.\n */\nint getch_win32  OF((void));\n\n#endif /* ?POCKET_UNZIP */\n\n\n//******************************************************************************\n//***** Global headers\n//******************************************************************************\n\n#include <windows.h>\n#ifndef TIME_ZONE_ID_INVALID\n#  define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL\n#endif\n#include <setjmp.h>\n#include <stdlib.h>\n#if defined(_MBCS) && !defined(_WIN32_WCE)\n#include <mbstring.h>\n#endif\n#include <excpt.h>\n#ifndef Cdecl\n#define Cdecl __cdecl\n#endif\n#include \"wince/wince.h\"     // Our WinCE specific code and our debug function.\n#ifdef POCKET_UNZIP\n#include \"wince/resource.h\"  // Our resource constants\n#include \"wince/punzip.rcv\"  // Our version information.\n#endif\n\n\n#ifndef _WIN32_WCE /* native Windows CE does not support 64-bit filesizes */\n\n/* 64-bit-Integers & Large File Support\n *\n *  If this is set it is assumed that the port\n *  supports 64-bit file calls.  The types are\n *  defined here.  Any local implementations are\n *  in w32i64.c and the protypes for the calls are\n *  in unzip.h.  Note that a port must support\n *  these calls fully or should not set\n *  LARGE_FILE_SUPPORT.\n */\n\n/* Automatically set ZIP64_SUPPORT if supported */\n\n#ifndef NO_ZIP64_SUPPORT\n# ifndef ZIP64_SUPPORT\n#   if defined(_MSC_VER)\n#     define ZIP64_SUPPORT\n#   endif\n# endif\n#endif\n\n#ifdef ZIP64_SUPPORT\n  /* base type for file offsets and file sizes */\n# if (defined(__GNUC__) || defined(ULONG_LONG_MAX))\n    typedef long long    zoff_t;\n# else\n    /* all other compilers use this as intrinsic 64-bit type */\n    typedef __int64      zoff_t;\n# endif\n# define ZOFF_T_DEFINED\n\n  /* user-defined types and format strings for 64-bit numbers and\n   * file pointer functions  (these depend on the rtl library and library\n   * headers used; they are NOT compiler-specific)\n   */\n# if defined(_MSC_VER)\n    /* MS C and VC */\n    /* these systems use the Microsoft C RTL */\n\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n#   define Z_STAT_DEFINED\n\n    /* printf format size prefix for zoff_t values */\n#   define FZOFFT_FMT \"I64\"\n#   define FZOFFT_HEX_WID_VALUE \"16\"\n\n# endif\n\n#endif\n\n/* If port has LARGE_FILE_SUPPORT then define here\n   to make automatic unless overridden */\n\n#ifndef LARGE_FILE_SUPPORT\n# ifndef NO_LARGE_FILE_SUPPORT\n#   if defined(_MSC_VER)\n#     define LARGE_FILE_SUPPORT\n#   endif\n# endif\n#endif\n\n#endif /* !_WIN32_WCE */\n\n#endif /* !__w32cfg_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/wcemain.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  wcemain.c\n\n  ---------------------------------------------------------------------------*/\n\n#define __WCEMAIN_C     /* identifies this source module */\n#define UNZIP_INTERNAL\n#include \"unzip.h\"      /* includes, typedefs, macros, prototypes, etc. */\n\n\nint WINAPI WinMain( HINSTANCE hInstance,\n                    HINSTANCE hPrevInstance,\n                    LPTSTR    lpCmdLine,\n                    int       nCmdShow)\n{\n    int r;\n    int i;\n    LPTSTR argArray[10];\n    int argBuffSize = lstrlen(lpCmdLine) + 1;\n    void* argBuff = malloc(argBuffSize);\n    char* argv[10];\n\n\n    /* Parse the command line into an argument array */\n    int argc = 0;\n    LPTSTR argPtr = lpCmdLine;\n    LPTSTR nextParam = NULL;\n    LPTSTR closingQuote = NULL;\n    unsigned short* endOfCmdLine = lpCmdLine + lstrlen(lpCmdLine);\n    TCHAR Blank = _T(' ');\n\n    /* Init the arrays */\n    for (i = 0; i < 10;i++)\n        argArray[i];\n    for (i = 0;i < 10;i++)\n        argv[i] = NULL;\n\n\n    /* Create the argument array, we have to convert this from wchar\n     * (unicode) to mbcs (single byte ascii)\n     */\n    while(argPtr != NULL)\n    {\n        /* Look for the first non-blank character */\n        while((memcmp(argPtr, &Blank, sizeof(TCHAR)) == 0) &&\n              (argPtr < endOfCmdLine))\n        {\n            argPtr++;\n        }\n\n        /* Check for quote enclosed strings for extended file names. */\n        if (argPtr[0] == _T('\"') &&\n            /* Look for closing quote */\n            (closingQuote = _tcschr(argPtr + 1, _T('\"'))) != NULL)\n        {\n            /* Clear the enclosing quotes */\n            *argPtr++ = _T('\\0');\n            *closingQuote = _T('\\0');\n            nextParam = closingQuote + 1;\n        }\n        else\n        {\n            nextParam = argPtr;\n        }\n\n        /* Set the parameter */\n        argArray[argc] = argPtr;\n        argc++;\n\n        /* Look for the next blank */\n        argPtr = _tcschr(nextParam, _T(' '));\n        if (argPtr != NULL)\n        {\n            /* Terminate the parameter and\n               point after the blank to the keyword */\n            *argPtr++ = _T('\\0');\n        }\n    }\n    /* Add one to the arg count for null terminator. */\n    argc++;\n\n#ifndef UNICODE\n    /* No need to convert the parameters */\n    argv = (char*)argArray;\n#else\n    /* Unicode so we need to convert the parameters to ascii. */\n    /* Get the storage we need to hold the converted data */\n    if (argBuff != NULL)\n    {\n\n        int i;\n        char* ptrArgBuff;\n\n        /* Clear the asci argument buffer */\n        memset(argBuff,'\\0',argBuffSize);\n        /* Command line parameters give ? */\n        if (argBuffSize == 0)\n        {\n            /* No so just set the first argumen in the array to\n             * the buffer */\n            argv[0] = argBuff;\n        }\n        else\n        {\n            argv[0] = (char*)_T(\"UnzipCE.exe\");\n            /* We have some storage build an asci version of\n             * the command parameters */\n            ptrArgBuff = (char*)argBuff;\n            for(i = 0; i < (argc - 1); i++)\n            {\n                /* convert the data */\n                int paramLength = lstrlen(argArray[i]);\n                int bytesWritten =\n                    WideCharToMultiByte(CP_ACP, 0,\n                                        argArray[i], paramLength,\n                                        ptrArgBuff, paramLength,\n                                        NULL, NULL);\n                if (bytesWritten == 0)\n                {\n                    /* Conversion failed ser return value and exit loop */\n                    r = (int)GetLastError();\n                    break;\n                }\n                else\n                {\n                    argv[i + 1] = ptrArgBuff;\n                    /* Point to the next area of the buffer */\n                    ptrArgBuff = ptrArgBuff + bytesWritten + 1;\n                }\n            }\n        }\n    }\n#endif /* UNICODE */\n    return MAIN(argc, argv);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/wince.cpp",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        WINCE.CPP\n//\n// Description: This file implements all the Win32 APIs and C runtime functions\n//              that the Info-ZIP code calls, but are not implemented natively\n//              on Windows CE.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n// Functions:   DebugOut\n//              chmod\n//              close\n//              isatty\n//              lseek\n//              open\n//              read\n//              setmode\n//              unlink\n//              fflush\n//              fgets\n//              fileno\n//              fopen\n//              fprintf\n//              fclose\n//              putc\n//              sprintf\n//              _stricmp\n//              _strupr\n//              strrchr                 (non-_MBCS only)\n//              isupper\n//              stat\n//              localtime\n//\n// Internal helper functions:\n//              SafeGetTimeZoneInformation\n//              GetTransitionTimeT\n//              IsDST\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n\nextern \"C\" {\n#define __WINCE_CPP\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n}\n#include <tchar.h> // Must be outside of extern \"C\" block\n\n\n//******************************************************************************\n//***** For all platforms - Our debug output function\n//******************************************************************************\n\n#ifdef DEBUG // RETAIL version is __inline and does not generate any code.\n\nvoid DebugOut(LPCTSTR szFormat, ...) {\n   TCHAR szBuffer[512] = TEXT(\"PUNZIP: \");\n\n   va_list pArgs;\n   va_start(pArgs, szFormat);\n   _vsntprintf(szBuffer + 8, countof(szBuffer) - 10, szFormat, pArgs);\n   va_end(pArgs);\n\n   TCHAR *psz = szBuffer;\n   while (psz = _tcschr(psz, TEXT('\\n'))) {\n      *psz = TEXT('|');\n   }\n   psz = szBuffer;\n   while (psz = _tcschr(psz, TEXT('\\r'))) {\n      *psz = TEXT('|');\n   }\n\n   _tcscat(szBuffer, TEXT(\"\\r\\n\"));\n\n   OutputDebugString(szBuffer);\n}\n\n#endif // DEBUG\n\n\n//******************************************************************************\n//***** Windows CE Native\n//******************************************************************************\n\n#if defined(_WIN32_WCE)\n\n//******************************************************************************\n//***** Local Function Prototyopes\n//******************************************************************************\n\nstatic void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi);\nstatic time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi,\n                                 int year, BOOL fStartDST);\nstatic BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime);\n\n//******************************************************************************\n//***** IO.H functions\n//******************************************************************************\n\n//-- Called from fileio.c\nint __cdecl chmod(const char *filename, int pmode) {\n   // Called before unlink() to delete read-only files.\n\n   DWORD dwAttribs = (pmode & _S_IWRITE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY;\n\n   TCHAR szPath[_MAX_PATH];\n   MBSTOTSTR(szPath, filename, countof(szPath));\n   return (SetFileAttributes(szPath, dwAttribs) ? 0 : -1);\n}\n\n//******************************************************************************\n//-- Called from process.c\nint __cdecl close(int handle) {\n   return (CloseHandle((HANDLE)handle) ? 0 : -1);\n}\n\n//******************************************************************************\n//-- Called from fileio.c\nint __cdecl isatty(int handle) {\n   // returns TRUE if handle is a terminal, console, printer, or serial port\n   // called with 1 (stdout) and 2 (stderr)\n   return 0;\n}\n\n//******************************************************************************\n//-- Called from extract.c, fileio.c, process.c\nlong __cdecl lseek(int handle, long offset, int origin) {\n   // SEEK_SET, SEEK_CUR, SEEK_END are equal to FILE_BEGIN, FILE_CURRENT, FILE_END\n   return SetFilePointer((HANDLE)handle, offset, NULL, origin);\n}\n\n//******************************************************************************\n//-- Called from fileio.c\nint __cdecl open(const char *filename, int oflags, ...) {\n\n   // The Info-Zip code currently only opens existing ZIP files for read\n   // using open().\n\n   DWORD dwAccess = 0;\n   DWORD dwCreate = 0;\n\n   switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {\n      case _O_RDONLY:\n         dwAccess = GENERIC_READ;\n         break;\n      case _O_WRONLY:\n         dwAccess = GENERIC_WRITE;\n         break;\n      case _O_RDWR:\n         dwAccess = GENERIC_READ | GENERIC_WRITE;\n         break;\n   }\n   switch (oflags & (O_CREAT | O_TRUNC)) {\n      case _O_CREAT:\n         dwCreate = OPEN_ALWAYS;\n         break;\n      case _O_CREAT | _O_TRUNC:\n         dwCreate = CREATE_ALWAYS;\n         break;\n      default:\n         dwCreate = OPEN_EXISTING;\n         break;\n   }\n\n   TCHAR szPath[_MAX_PATH];\n   MBSTOTSTR(szPath, filename, countof(szPath));\n   HANDLE hFile = CreateFile(szPath, dwAccess,\n                             FILE_SHARE_READ | FILE_SHARE_WRITE,\n                             NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);\n   if ((hFile != INVALID_HANDLE_VALUE) && ((oflags & O_APPEND) == O_APPEND)) {\n      SetFilePointer(hFile, 0, NULL, FILE_END);\n   }\n   return ((hFile == INVALID_HANDLE_VALUE) ? -1 : (int)hFile);\n}\n\n//******************************************************************************\n//-- Called from extract.c, fileio.c, process.c\nint __cdecl read(int handle, void *buffer, unsigned int count) {\n   DWORD dwRead = 0;\n   return (ReadFile((HANDLE)handle, buffer, count, &dwRead, NULL) ? dwRead : -1);\n}\n\n#if _WIN32_WCE < 211\n//******************************************************************************\n//-- Called from extract.c\nint __cdecl setmode(int handle, int mode) {\n   //TEXT/BINARY translation - currently always called with O_BINARY.\n   return O_BINARY;\n}\n#endif\n\n//******************************************************************************\n//-- Called from fileio.c\nint __cdecl unlink(const char *filename) {\n\n   // Called to delete files before an extract overwrite.\n\n   TCHAR szPath[_MAX_PATH];\n   MBSTOTSTR(szPath, filename, countof(szPath));\n   return (DeleteFile(szPath) ? 0: -1);\n}\n\n//******************************************************************************\n//***** STDIO.H functions\n//******************************************************************************\n#if _WIN32_WCE < 211\n// Old versions of Win CE prior to 2.11 do not support stdio library functions.\n// We provide simplyfied replacements that are more or less copies of the\n// UNIX style low level I/O API functions. Only unbuffered I/O in binary mode\n// is supported.\n//-- Called from fileio.c\nint __cdecl fflush(FILE *stream) {\n   return (FlushFileBuffers((HANDLE)stream) ? 0 : EOF);\n}\n\n//******************************************************************************\n//-- Called from extract.c\nchar * __cdecl fgets(char *string, int n, FILE *stream) {\n   // stream always equals \"stdin\" and fgets() should never be called.\n   DebugOut(TEXT(\"WARNING: fgets(0x%08X, %d, %08X) called.\"), string, n, stream);\n   return NULL;\n}\n\n//******************************************************************************\n//-- Called from extract.c\nint __cdecl fileno(FILE *stream) {\n   return (int)stream;\n}\n\n//******************************************************************************\n//-- Called from fileio.c\nFILE * __cdecl fopen(const char *filename, const char *mode) {\n\n   // fopen() is used to create all extracted files.\n\n   DWORD dwAccess = 0;\n   DWORD dwCreate = 0;\n   BOOL  fAppend  = FALSE;\n\n   if (strstr(mode, \"r+\")) {\n      dwAccess = GENERIC_READ | GENERIC_WRITE;\n      dwCreate = OPEN_EXISTING;\n   } else if (strstr(mode, \"w+\")) {\n      dwAccess = GENERIC_READ | GENERIC_WRITE;\n      dwCreate = CREATE_ALWAYS;\n   } else if (strstr(mode, \"a+\")) {\n      dwAccess = GENERIC_READ | GENERIC_WRITE;\n      dwCreate = OPEN_ALWAYS;\n      fAppend = TRUE;\n   } else if (strstr(mode, \"r\")) {\n      dwAccess = GENERIC_READ;\n      dwCreate = OPEN_EXISTING;\n   } else if (strstr(mode, \"w\")) {\n      dwAccess = GENERIC_WRITE;\n      dwCreate = CREATE_ALWAYS;\n   } else if (strstr(mode, \"a\")) {\n      dwAccess = GENERIC_WRITE;\n      dwCreate = OPEN_ALWAYS;\n      fAppend  = TRUE;\n   }\n\n   TCHAR szPath[_MAX_PATH];\n   MBSTOTSTR(szPath, filename, countof(szPath));\n   HANDLE hFile = CreateFile(szPath, dwAccess,\n                             FILE_SHARE_READ | FILE_SHARE_WRITE,\n                             NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL);\n\n   if (hFile == INVALID_HANDLE_VALUE) {\n      return NULL;\n   }\n\n   if (fAppend) {\n      SetFilePointer(hFile, 0, NULL, FILE_END);\n   }\n\n   return (FILE*)hFile;\n}\n\n//******************************************************************************\n//-- Called from many sources when compiled for DEBUG\nint __cdecl fprintf(FILE *stream, const char *format, ...) {\n\n   // All standard output/error in Info-ZIP is handled through fprintf()\n   if ((stream == stdout) || (stream == stderr)) {\n      return 1;\n   }\n\n   // \"stream\" always equals \"stderr\" or \"stdout\" - log error if we see otherwise.\n#ifdef UNICODE\n   DebugOut(TEXT(\"WARNING: fprintf(0x%08X, \\\"%S\\\", ...) called.\"), stream, format);\n#else\n   DebugOut(TEXT(\"WARNING: fprintf(0x%08X, \\\"%s\\\", ...) called.\"), stream, format);\n#endif\n   return 0;\n}\n\n//******************************************************************************\n//-- Called from fileio.c\nint __cdecl fclose(FILE *stream) {\n   return (CloseHandle((HANDLE)stream) ? 0 : EOF);\n}\n\n//******************************************************************************\n//-- Called from fileio.c\nint __cdecl putc(int c, FILE *stream) {\n   DebugOut(TEXT(\"WARNING: putc(%d, 0x%08X) called.\"), c, stream);\n   return 0;\n}\n\n//******************************************************************************\n//-- Called from intrface.cpp, extract.c, fileio.c, list.c, process.c\nint __cdecl sprintf(char *buffer, const char *format, ...) {\n\n   WCHAR wszBuffer[512], wszFormat[512];\n\n   MBSTOTSTR(wszFormat, format, countof(wszFormat));\n   BOOL fPercent = FALSE;\n   for (WCHAR *pwsz = wszFormat; *pwsz; pwsz++) {\n      if (*pwsz == L'%') {\n         fPercent = !fPercent;\n      } else if (fPercent && (((*pwsz >= L'a') && (*pwsz <= L'z')) ||\n                              ((*pwsz >= L'A') && (*pwsz <= L'Z'))))\n      {\n         if (*pwsz == L's') {\n            *pwsz = L'S';\n         } else if (*pwsz == L'S') {\n            *pwsz = L's';\n         }\n         fPercent = FALSE;\n      }\n   }\n\n   va_list pArgs;\n   va_start(pArgs, format);\n   _vsntprintf(wszBuffer, countof(wszBuffer), wszFormat, pArgs);\n   va_end(pArgs);\n\n   TSTRTOMBS(buffer, wszBuffer, countof(wszBuffer));\n\n   return 0;\n}\n#endif /* _WIN32_WCE < 211 */\n\n#ifndef POCKET_UNZIP\n//******************************************************************************\n//-- Called from unzip.c\nvoid __cdecl perror(const char* errorText)\n{\n    OutputDebugString((LPCTSTR)errorText);\n}\n#endif // !POCKET_UNZIP\n\n#ifdef USE_FWRITE\n//******************************************************************************\n//-- Called from fileio.c\nvoid __cdecl setbuf(FILE *, char *)\n{\n    // We are using fwrite and the call to setbuf was to set the stream\n    // unbuffered which is the default behaviour, we have nothing to do.\n}\n#endif // USE_FWRITE\n\n//******************************************************************************\n//***** STDLIB.H functions\n//******************************************************************************\n\n#ifdef _MBCS\nint __cdecl mblen(const char *mbc, size_t mbszmax)\n{\n    // very simple cooked-down version of mblen() without any error handling\n    // (Windows CE does not support multibyte charsets with a maximum char\n    // length > 2 bytes)\n    return (IsDBCSLeadByte((BYTE)*mbc) ? 2 : 1);\n}\n#endif /* _MBCS */\n\n//******************************************************************************\n//***** STRING.H functions\n//******************************************************************************\n\n//-- Called from winmain.cpp\nint __cdecl _stricmp(const char *string1, const char *string2) {\n   while (*string1 && ((*string1 | 0x20) == (*string2 | 0x20))) {\n      string1++;\n      string2++;\n   }\n   return (*string1 - *string2);\n}\n\n//******************************************************************************\n//-- Called from intrface.cpp and winmain.cpp\nchar* __cdecl _strupr(char *string) {\n   while (*string) {\n      if ((*string >= 'a') && (*string <= 'z')) {\n         *string -= 'a' - 'A';\n      }\n      string++;\n   }\n   return string;\n}\n\n//******************************************************************************\n//-- Called from fileio.c (\"open_input_file()\")\nchar* __cdecl strerror(int errnum) {\n   return \"[errmsg not available]\";\n}\n\n#ifndef _MBCS\n//******************************************************************************\n//-- Called from winmain.cpp\nchar* __cdecl strrchr(const char *string, int c) {\n\n   // Walk to end of string.\n   for (char *p = (char*)string; *p; p++) {\n   }\n\n   // Walk backwards looking for character.\n   for (p--; p >= string; p--) {\n      if ((int)*p == c) {\n         return p;\n      }\n   }\n\n   return NULL;\n}\n#endif /* !_MBCS */\n\n//******************************************************************************\n//***** CTYPE.H functions\n//******************************************************************************\n\n#if _WIN32_WCE < 300\nint __cdecl isupper(int c) {\n   return ((c >= 'A') && (c <= 'Z'));\n}\n#endif\n\n//******************************************************************************\n//***** STAT.H functions\n//******************************************************************************\n\n//-- Called fileio.c, process.c, intrface.cpp\nint __cdecl stat(const char *path, struct stat *buffer) {\n\n   // stat() is called on both the ZIP files and extracted files.\n\n   // Clear our stat buffer to be safe.\n   ZeroMemory(buffer, sizeof(struct stat));\n\n   // Find the file/direcotry and fill in a WIN32_FIND_DATA structure.\n   WIN32_FIND_DATA w32fd;\n   ZeroMemory(&w32fd, sizeof(w32fd));\n\n   TCHAR szPath[_MAX_PATH];\n   MBSTOTSTR(szPath, path, countof(szPath));\n   HANDLE hFind = FindFirstFile(szPath, &w32fd);\n\n   // Bail out now if we could not find the file/directory.\n   if (hFind == INVALID_HANDLE_VALUE) {\n      return -1;\n   }\n\n   // Close the find.\n   FindClose(hFind);\n\n   // Mode flags that are currently used: S_IWRITE, S_IFMT, S_IFDIR, S_IEXEC\n   if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n      buffer->st_mode = _S_IFDIR | _S_IREAD | _S_IEXEC;\n   } else {\n      buffer->st_mode = _S_IFREG | _S_IREAD;\n   }\n   if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {\n      buffer->st_mode |= _S_IWRITE;\n   }\n\n   // Store the file size.\n   buffer->st_size  = (_off_t)w32fd.nFileSizeLow;\n\n   // Convert the modified FILETIME to a time_t and store it.\n   DWORDLONG dwl = *(DWORDLONG*)&w32fd.ftLastWriteTime;\n   buffer->st_mtime = (time_t)((dwl - (DWORDLONG)116444736000000000) / (DWORDLONG)10000000);\n\n   return 0;\n}\n\n//******************************************************************************\n//***** TIME.H functions\n//******************************************************************************\n\n// Evaluates to TRUE if 'y' is a leap year, otherwise FALSE\n// #define IS_LEAP_YEAR(y) ((((y) % 4 == 0) && ((y) % 100 != 0)) || ((y) % 400 == 0))\n\n// The macro below is a reduced version of the above macro.  It is valid for\n// years between 1901 and 2099 which easily includes all years representable\n// by the current implementation of time_t.\n#define IS_LEAP_YEAR(y) (((y) & 3) == 0)\n\n#define BASE_DOW          4                  // 1/1/1970 was a Thursday.\n#define SECONDS_IN_A_DAY  (24L * 60L * 60L)  // Number of seconds in one day.\n\n// Month to Year Day conversion array.\nint M2YD[] = {\n   0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365\n};\n\n// Month to Leap Year Day conversion array.\nint M2LYD[] = {\n   0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366\n};\n\n//******************************************************************************\n//-- Called from list.c\nstruct tm * __cdecl localtime(const time_t *timer) {\n\n   // Return value for localtime().  Source currently never references\n   // more than one \"tm\" at a time, so the single return structure is ok.\n   static struct tm g_tm;\n   ZeroMemory(&g_tm, sizeof(g_tm));\n\n   // Get our time zone information.\n   TIME_ZONE_INFORMATION tzi;\n   SafeGetTimeZoneInformation(&tzi);\n\n   // Create a time_t that has been corrected for our time zone.\n   time_t localTime = *timer - (tzi.Bias * 60L);\n\n   // Decide if value is in Daylight Savings Time.\n   if (g_tm.tm_isdst = (int)IsDST(&tzi, localTime)) {\n      localTime -= tzi.DaylightBias * 60L; // usually 60 minutes\n   } else {\n      localTime -= tzi.StandardBias * 60L; // usually  0 minutes\n   }\n\n   // time_t   is a 32-bit value for the seconds since January 1, 1970\n   // FILETIME is a 64-bit value for the number of 100-nanosecond intervals\n   //          since January 1, 1601\n\n   // Compute the FILETIME for the given local time.\n   DWORDLONG dwl = ((DWORDLONG)116444736000000000 +\n                   ((DWORDLONG)localTime * (DWORDLONG)10000000));\n   FILETIME ft = *(FILETIME*)&dwl;\n\n   // Convert the FILETIME to a SYSTEMTIME.\n   SYSTEMTIME st;\n   ZeroMemory(&st, sizeof(st));\n   FileTimeToSystemTime(&ft, &st);\n\n   // Finish filling in our \"tm\" structure.\n   g_tm.tm_sec  = (int)st.wSecond;\n   g_tm.tm_min  = (int)st.wMinute;\n   g_tm.tm_hour = (int)st.wHour;\n   g_tm.tm_mday = (int)st.wDay;\n   g_tm.tm_mon  = (int)st.wMonth - 1;\n   g_tm.tm_year = (int)st.wYear - 1900;\n\n   return &g_tm;\n}\n\n//******************************************************************************\nstatic void SafeGetTimeZoneInformation(TIME_ZONE_INFORMATION *ptzi)\n{\n\n   ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));\n\n   // Ask the OS for the standard/daylight rules for the current time zone.\n   if ((GetTimeZoneInformation(ptzi) == 0xFFFFFFFF) ||\n       (ptzi->StandardDate.wMonth > 12) || (ptzi->DaylightDate.wMonth > 12))\n   {\n      // If the OS fails us, we default to the United States' rules.\n      ZeroMemory(ptzi, sizeof(TIME_ZONE_INFORMATION));\n      ptzi->StandardDate.wMonth =  10;  // October\n      ptzi->StandardDate.wDay   =   5;  // Last Sunday (DOW == 0)\n      ptzi->StandardDate.wHour  =   2;  // At 2:00 AM\n      ptzi->DaylightBias        = -60;  // One hour difference\n      ptzi->DaylightDate.wMonth =   4;  // April\n      ptzi->DaylightDate.wDay   =   1;  // First Sunday (DOW == 0)\n      ptzi->DaylightDate.wHour  =   2;  // At 2:00 AM\n   }\n}\n\n//******************************************************************************\nstatic time_t GetTransitionTimeT(TIME_ZONE_INFORMATION *ptzi,\n                                 int year, BOOL fStartDST)\n{\n   // We only handle years within the range that time_t supports.  We need to\n   // handle the very end of 1969 since the local time could be up to 13 hours\n   // into the previous year.  In this case, our code will actually return a\n   // negative value, but it will be compared to another negative value and is\n   // handled correctly.  The same goes for the 13 hours past a the max time_t\n   // value of 0x7FFFFFFF (in the year 2038).  Again, these values are handled\n   // correctly as well.\n\n   if ((year < 1969) || (year > 2038)) {\n      return (time_t)0;\n   }\n\n   SYSTEMTIME *pst = fStartDST ? &ptzi->DaylightDate : &ptzi->StandardDate;\n\n   // WORD wYear          Year (0000 == 0)\n   // WORD wMonth         Month (January == 1)\n   // WORD wDayOfWeek     Day of week (Sunday == 0)\n   // WORD wDay           Month day (1 - 31)\n   // WORD wHour          Hour (0 - 23)\n   // WORD wMinute        Minute (0 - 59)\n   // WORD wSecond        Second (0 - 59)\n   // WORD wMilliseconds  Milliseconds (0 - 999)\n\n   // Compute the number of days since 1/1/1970 to the beginning of this year.\n   long daysToYear = ((year - 1970) * 365) // Tally up previous years.\n                   + ((year - 1969) >> 2); // Add few extra for the leap years.\n\n   // Compute the number of days since the beginning of this year to the\n   // beginning of the month.  We will add to this value to get the actual\n   // year day.\n   long yearDay = IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth - 1] :\n                                       M2YD [pst->wMonth - 1];\n\n   // Check for day-in-month format.\n   if (pst->wYear == 0) {\n\n      // Compute the week day for the first day of the month (Sunday == 0).\n      long monthDOW = (daysToYear + yearDay + BASE_DOW) % 7;\n\n      // Add the day offset of the transition day to the year day.\n      if (monthDOW < pst->wDayOfWeek) {\n         yearDay += (pst->wDayOfWeek - monthDOW) + (pst->wDay - 1) * 7;\n      } else {\n         yearDay += (pst->wDayOfWeek - monthDOW) + pst->wDay * 7;\n      }\n\n      // It is possible that we overshot the month, especially if pst->wDay\n      // is 5 (which means the last instance of the day in the month). Check\n      // if the year-day has exceeded the month and adjust accordingly.\n      if ((pst->wDay == 5) &&\n          (yearDay >= (IS_LEAP_YEAR(year) ? M2LYD[pst->wMonth] :\n                                            M2YD [pst->wMonth])))\n      {\n         yearDay -= 7;\n      }\n\n   // If not day-in-month format, then we assume an absolute date.\n   } else {\n\n      // Simply add the month day to the current year day.\n      yearDay += pst->wDay - 1;\n   }\n\n   // Tally up all our days, hours, minutes, and seconds since 1970.\n   long seconds = ((SECONDS_IN_A_DAY * (daysToYear + yearDay)) +\n                   (3600L * (long)pst->wHour) +\n                   (60L * (long)pst->wMinute) +\n                   (long)pst->wSecond);\n\n   // If we are checking for the end of DST, then we need to add the DST bias\n   // since we are in DST when we chack this time stamp.\n   if (!fStartDST) {\n      seconds += ptzi->DaylightBias * 60L;\n   }\n\n   return (time_t)seconds;\n}\n\n//******************************************************************************\nstatic BOOL IsDST(TIME_ZONE_INFORMATION *ptzi, time_t localTime) {\n\n   // If either of the months is 0, then this usually means that the time zone\n   // does not use DST.  Unfortunately, Windows CE since it has a bug where it\n   // never really fills in these fields with the correct values, so it appears\n   // like we are never in DST.  This is supposed to be fixed in future releases,\n   // so hopefully this code will get some use then.\n   if ((ptzi->StandardDate.wMonth == 0) || (ptzi->DaylightDate.wMonth == 0)) {\n      return FALSE;\n   }\n\n   // time_t   is a 32-bit value for the seconds since January 1, 1970\n   // FILETIME is a 64-bit value for the number of 100-nanosecond intervals\n   //          since January 1, 1601\n\n   // Compute the FILETIME for the given local time.\n   DWORDLONG dwl = ((DWORDLONG)116444736000000000 +\n                   ((DWORDLONG)localTime * (DWORDLONG)10000000));\n   FILETIME ft = *(FILETIME*)&dwl;\n\n   // Convert the FILETIME to a SYSTEMTIME.\n   SYSTEMTIME st;\n   ZeroMemory(&st, sizeof(st));\n   FileTimeToSystemTime(&ft, &st);\n\n   // Get our start and end daylight savings times.\n   time_t timeStart = GetTransitionTimeT(ptzi, (int)st.wYear, TRUE);\n   time_t timeEnd   = GetTransitionTimeT(ptzi, (int)st.wYear, FALSE);\n\n   // Check what hemisphere we are in.\n   if (timeStart < timeEnd) {\n\n      // Northern hemisphere ordering.\n      return ((localTime >= timeStart) && (localTime < timeEnd));\n\n   } else if (timeStart > timeEnd) {\n\n      // Southern hemisphere ordering.\n      return ((localTime < timeEnd) || (localTime >= timeStart));\n   }\n\n   // If timeStart equals timeEnd then this time zone does not support DST.\n   return FALSE;\n}\n\n#endif // _WIN32_WCE\n\n//******************************************************************************\n//***** Functions to supply timezone information from the Windows registry to\n//***** Info-ZIP's private RTL \"localtime() et al.\" replacements in timezone.c.\n//******************************************************************************\n\n//******************************************************************************\n// Copied from win32.c\n#ifdef W32_USE_IZ_TIMEZONE\n#include \"timezone.h\"\n#define SECSPERMIN      60\n#define MINSPERHOUR     60\n#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);\n\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)\n{\n    if (lpw32tm->wYear != 0) {\n        ptrule->r_type = JULIAN_DAY;\n        ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;\n    } else {\n        ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;\n        ptrule->r_mon = lpw32tm->wMonth;\n        ptrule->r_day = lpw32tm->wDayOfWeek;\n        ptrule->r_week = lpw32tm->wDay;\n    }\n    ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +\n                     (long)(lpw32tm->wMinute * SECSPERMIN) +\n                     (long)lpw32tm->wSecond;\n}\n\nint GetPlatformLocalTimezone(register struct state * ZCONST sp,\n        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                        ZCONST struct rule * ZCONST start,\n                                        ZCONST struct rule * ZCONST end))\n{\n    TIME_ZONE_INFORMATION tzinfo;\n    DWORD res;\n\n    /* read current timezone settings from registry if TZ envvar missing */\n    res = GetTimeZoneInformation(&tzinfo);\n    if (res != TIME_ZONE_ID_INVALID)\n    {\n        struct rule startrule, stoprule;\n\n        conv_to_rule(&(tzinfo.StandardDate), &stoprule);\n        conv_to_rule(&(tzinfo.DaylightDate), &startrule);\n        sp->timecnt = 0;\n        sp->ttis[0].tt_abbrind = 0;\n        if ((sp->charcnt =\n             WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1,\n                                 sp->chars, sizeof(sp->chars), NULL, NULL))\n            == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[1].tt_abbrind = sp->charcnt;\n        sp->charcnt +=\n            WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1,\n                                sp->chars + sp->charcnt,\n                                sizeof(sp->chars) - sp->charcnt, NULL, NULL);\n        if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias)\n                                * MINSPERHOUR;\n        sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias)\n                                * MINSPERHOUR;\n        sp->ttis[0].tt_isdst = 0;\n        sp->ttis[1].tt_isdst = 1;\n        sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2;\n\n        if (sp->typecnt > 1)\n            (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);\n        return TRUE;\n    }\n    return FALSE;\n}\n#endif /* W32_USE_IZ_TIMEZONE */\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/wince.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        WINCE.H\n//\n// Description: This file declares all the Win32 APIs and C runtime functions\n//              that the Info-ZIP code calls, but are not implemented natively\n//              on Windows CE.  See WINCE.CPP for the implementation.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n#ifndef __WINCE_H__\n#define __WINCE_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n//******************************************************************************\n//***** For all platforms - Our debug output function\n//******************************************************************************\n\n// If we are building for debug, we implement the DebugOut() function. If we are\n// building for release, then we turn all calls to DebugOut() into no-ops.  The\n// Microsoft compiler (and hopefully others) will not generate any code at all\n// for the retail version of DebugOut() defined here.  This works much better\n// than trying to create a variable argument macro - something C/C++ does not\n// support cleanly.\n\n#ifdef DEBUG\nvoid DebugOut(LPCTSTR szFormat, ...);\n#else\n__inline void DebugOut(LPCTSTR szFormat, ...) {}\n#endif\n\n\n//******************************************************************************\n//***** Windows NT Native\n//******************************************************************************\n\n#if !defined(_WIN32_WCE)\n#ifndef UNICODE\n#include <stdio.h>\n#endif\n#include <io.h>\n#include <time.h>\n#include <fcntl.h>\n#include <sys\\stat.h>\n#endif\n\n//******************************************************************************\n//***** Windows CE Native\n//******************************************************************************\n\n#if defined(_WIN32_WCE)\n\n#if defined(__WINCE_CPP)\n   // internal, suppress \"import linkage\" specifier\n#  define ZCRTIMP\n#else\n   // do not use import linkage specifier either; symbols are provided locally\n#  define ZCRTIMP\n#endif\n\n#ifndef ZeroMemory\n#define ZeroMemory(Destination,Length) memset(Destination, 0, Length)\n#endif\n\n#ifdef _MBCS\n   // WinCE C RTL does not provide the setlocale function\n#  define setlocale(category, locale)\n#endif\n\n// A few forgotten defines in Windows CE's TCHAR.H\n#ifndef _stprintf\n#define _stprintf wsprintf\n#endif\n\n#if _WIN32_WCE < 211 //sr551b functions in stdlib CE300\n#ifndef _vsntprintf\n#define _vsntprintf(d,c,f,a) wvsprintf(d,f,a)\n#endif\n#ifndef _vsnwprintf\n#define _vsnwprintf(d,c,f,a) wvsprintf(d,f,a)\n#endif\n#endif //end sr551b\n\n//******************************************************************************\n//***** SYS\\TYPES.H functions\n//******************************************************************************\n\n#ifndef _OFF_T_DEFINED\ntypedef long _off_t;\n#define _OFF_T_DEFINED\n#endif\n#ifndef _TIME_T_DEFINED\ntypedef long time_t;\n#define _TIME_T_DEFINED\n#endif\n\n//******************************************************************************\n//***** CTYPE.H functions\n//******************************************************************************\n#if _WIN32_WCE < 300\nZCRTIMP int __cdecl isupper(int);\n#endif\n_CRTIMP int __cdecl tolower(int);\n// This is a coarse approximation to ASCII isalpha(), it returns TRUE not only\n// on all ASCII letters but also on punctuation chars in the range of 0x40-0x7F\n#ifndef isalpha\n#define isalpha(c) (((c) & 0xC0) == 0xC0)\n#endif\n\n//******************************************************************************\n//***** FCNTL.H functions\n//******************************************************************************\n\n#ifndef _O_RDONLY       // do not redefine existing FCNTL.H constants\n\n#define _O_RDONLY 0x0000   // open for reading only\n#define _O_WRONLY 0x0001   // open for writing only\n#define _O_RDWR   0x0002   // open for reading and writing\n#define _O_APPEND 0x0008   // writes done at eof\n\n#define _O_CREAT  0x0100   // create and open file\n#define _O_TRUNC  0x0200   // open and truncate\n#define _O_EXCL   0x0400   // open only if file doesn't already exist\n\n\n//# define _O_TEXT    0x4000   // file mode is text (translated)\n#define _O_BINARY 0x8000   // file mode is binary (untranslated)\n\n#endif // _O_RDONLY (and alikes...) undefined\n\n#ifndef O_RDONLY        // do not redefine existing FCNTL.H constants\n\n#define O_RDONLY  _O_RDONLY\n#define O_WRONLY  _O_WRONLY\n#define O_RDWR    _O_RDWR\n#define O_APPEND  _O_APPEND\n#define O_CREAT   _O_CREAT\n#define O_TRUNC   _O_TRUNC\n#define O_EXCL    _O_EXCL\n#define O_TEXT    _O_TEXT\n#define O_BINARY  _O_BINARY\n//#define O_RAW      _O_BINARY\n//#define O_TEMPORARY   _O_TEMPORARY\n//#define O_NOINHERIT   _O_NOINHERIT\n//#define O_SEQUENTIAL  _O_SEQUENTIAL\n//#define O_RANDOM   _O_RANDOM\n\n#endif // O_RDONLY (and other old-fashioned constants) undefined\n\n//******************************************************************************\n//***** IO.H functions\n//******************************************************************************\n\nZCRTIMP int __cdecl chmod(const char *, int);\nZCRTIMP int __cdecl close(int);\nZCRTIMP int __cdecl isatty(int);\nZCRTIMP long __cdecl lseek(int, long, int);\nZCRTIMP int __cdecl open(const char *, int, ...);\nZCRTIMP int __cdecl read(int, void *, unsigned int);\n#if _WIN32_WCE < 211\nZCRTIMP int __cdecl setmode(int, int);\n#else\n# define setmode _setmode\n#endif\nZCRTIMP int __cdecl unlink(const char *);\n\n\n//******************************************************************************\n//***** STDIO.H functions\n//******************************************************************************\n\n#if _WIN32_WCE < 211 //sr551b functions in stdlib CE300\n//typedef struct _iobuf FILE;\ntypedef int FILE;\n\n#define stdin  ((int*)-2)\n#define stdout ((int*)-3)\n#define stderr ((int*)-4)\n\n#define EOF    (-1)\n\nZCRTIMP int __cdecl fflush(FILE *);\nZCRTIMP char * __cdecl fgets(char *, int, FILE *);\nZCRTIMP int __cdecl fileno(FILE *);\nZCRTIMP FILE * __cdecl fopen(const char *, const char *);\nZCRTIMP int __cdecl fprintf(FILE *, const char *, ...);\nZCRTIMP int __cdecl fclose(FILE *);\nZCRTIMP int __cdecl putc(int, FILE *);\nZCRTIMP int __cdecl sprintf(char *, const char *, ...);\n#endif // _WIN32_WCE < 211\n#if _WIN32_WCE >= 211\n// CE falsely uses (FILE *) pointer args for UNIX style I/O functions that\n// normally expect numeric file handles (e.g. setmode())\n# undef fileno\n# define fileno(strm)  (strm)\n#endif // _WIN32_WCE < 211\n#ifndef POCKET_UNZIP\nZCRTIMP void __cdecl perror(const char* errorText);\n#endif\n#ifdef USE_FWRITE\nZCRTIMP void __cdecl setbuf(FILE *, char *);\n#endif\n\n\n//******************************************************************************\n//***** STDLIB.H functions\n//******************************************************************************\n\n#ifdef _MBCS\n#ifndef MB_CUR_MAX\n# define MB_CUR_MAX 2\n#endif\nZCRTIMP int __cdecl mblen(const char *mbc, size_t mbszmax);\n#endif /* _MBCS */\n#if _WIN32_WCE >= 211\n# define errno ((int)GetLastError())\n#endif\n#ifdef _WIN32_WCE_EMULATION\n  // The emulation runtime library lacks a required element for setjmp/longjmp,\n  // disable the recovery functionality for now.\n# undef setjmp\n# define setjmp(buf) 0\n# undef longjmp\n# define longjmp(buf, rv)\n#endif\n\n//******************************************************************************\n//***** STRING.H functions\n//******************************************************************************\n\nZCRTIMP int     __cdecl _stricmp(const char *, const char *);\nZCRTIMP char *  __cdecl _strupr(char *);\nZCRTIMP char *  __cdecl strerror(int errnum);\nZCRTIMP char *  __cdecl strrchr(const char *, int);\n\n\n//******************************************************************************\n//***** TIME.H functions\n//******************************************************************************\n\n#ifndef _TM_DEFINED\nstruct tm {\n   int tm_sec;     // seconds after the minute - [0,59]\n   int tm_min;     // minutes after the hour - [0,59]\n   int tm_hour;    // hours since midnight - [0,23]\n   int tm_mday;    // day of the month - [1,31]\n   int tm_mon;     // months since January - [0,11]\n   int tm_year;    // years since 1900\n// int tm_wday;    // days since Sunday - [0,6]\n// int tm_yday;    // days since January 1 - [0,365]\n   int tm_isdst;   // daylight savings time flag\n};\n#define _TM_DEFINED\n#endif\n\nZCRTIMP struct tm * __cdecl localtime(const time_t *);\n// tzset is not supported on native WCE, define it as a NOP macro\n#ifndef tzset\n# define tzset()\n#endif\n\n//******************************************************************************\n//***** SYS\\STAT.H functions\n//******************************************************************************\n\nstruct stat {\n// _dev_t st_dev;\n// _ino_t st_ino;\n   unsigned short st_mode;\n// short st_nlink;\n// short st_uid;\n// short st_gid;\n// _dev_t st_rdev;\n   _off_t st_size;\n// time_t st_atime;\n   time_t st_mtime;\n// time_t st_ctime;\n};\n\n#define _S_IFMT   0170000  // file type mask\n#define _S_IFDIR  0040000  // directory\n//#define _S_IFCHR   0020000  // character special\n//#define _S_IFIFO   0010000  // pipe\n#define _S_IFREG  0100000  // regular\n#define _S_IREAD  0000400  // read permission, owner\n#define _S_IWRITE 0000200  // write permission, owner\n#define _S_IEXEC  0000100  // execute/search permission, owner\n\n#define S_IFMT  _S_IFMT\n#define S_IFDIR  _S_IFDIR\n//#define S_IFCHR  _S_IFCHR\n//#define S_IFREG  _S_IFREG\n#define S_IREAD  _S_IREAD\n#define S_IWRITE _S_IWRITE\n#define S_IEXEC  _S_IEXEC\n\nZCRTIMP int __cdecl stat(const char *, struct stat *);\n\n\n//******************************************************************************\n\n#endif // _WIN32_WCE\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // __WINCE_H__\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/winmain.cpp",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        WINMAIN.CPP\n//\n// Description: This module contains all the Windows specific code for Pocket\n//              UnZip.  It contains the entire user interface.  This code knows\n//              almost nothing about the Info-ZIP code.  All Info-ZIP related\n//              functions are wrapped by helper functions in INTRFACE.CPP.  The\n//              code in this module only calls those wrapper functions and\n//              INTRFACE.CPP handles all the details and callbacks of the\n//              Info-ZIP code.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n// Functions:   WinMain\n//              InitializeApplication\n//              ShutdownApplication\n//              RegisterUnzip\n//              BuildImageList\n//              WndProc\n//              OnCreate\n//              OnFileOpen\n//              OnActionView\n//              OnActionSelectAll\n//              OnViewExpandedView\n//              OnHelp\n//              OnGetDispInfo\n//              OnDeleteItem\n//              OnItemChanged\n//              Sort\n//              CompareFunc\n//              SetCaptionText\n//              DrawBanner\n//              AddDeleteColumns\n//              ResizeColumns\n//              GetZipErrorString\n//              AddFileToListView\n//              EnableAllMenuItems\n//              CheckAllMenuItems\n//              CenterWindow\n//              AddTextToEdit\n//              FormatValue\n//              BuildAttributesString\n//              BuildTypeString\n//              GetFileFromPath\n//              ForwardSlashesToBackSlashesA\n//              ForwardSlashesToBackSlashesW\n//              DeleteDirectory(LPTSTR szPath);\n//              RegWriteKey\n//              RegReadKey\n//              WriteOptionString\n//              WriteOptionInt\n//              GetOptionString\n//              GetOptionInt\n//              DisableEditing\n//              EditSubclassProc\n//              GetMenuString\n//              InitializeMRU\n//              AddFileToMRU\n//              RemoveFileFromMRU\n//              ActivateMRU\n//              ReadZipFileList\n//              DlgProcProperties\n//              MergeValues\n//              CheckThreeStateBox\n//              ExtractOrTestFiles\n//              DlgProcExtractOrTest\n//              FolderBrowser\n//              DlgProcBrowser\n//              SubclassSaveAsDlg\n//              DlgProcExtractProgress\n//              DlgProcViewProgress\n//              UpdateProgress\n//              PromptToReplace\n//              DlgProcReplace\n//              DlgProcPassword\n//              DlgProcViewAssociation\n//              DlgProcComment\n//              DlgProcAbout\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\nextern \"C\" {\n#define __WINMAIN_CPP__\n#define UNZIP_INTERNAL\n\n#include \"unzip.h\"\n\n#include \"crypt.h\"     // Needed to pick up CRYPT define setting and return values.\n\n#include \"unzvers.h\"   // Only needed by consts.h (VERSION_DATE & VersionDate)\n#include \"consts.h\"    // Only include once - defines constant string messages.\n\n#include <commctrl.h>  // Common controls - mainly ListView and ImageList\n#include <commdlg.h>   // Common dialogs - OpenFile dialog\n\n#ifndef _WIN32_WCE\n#include <shlobj.h>    // On NT, we use the SHBrowseForFolder() stuff.\n#include <shellapi.h>  // CommandLineToArgvW() and ExtractIconEx()\n#endif\n\n#include \"intrface.h\"  // Interface between Info-ZIP and us\n#include \"winmain.h\"   // Us\n}\n#include <tchar.h>     // Must be outside of extern \"C\" block\n\n\n//******************************************************************************\n//***** \"Local\" Global Variables\n//******************************************************************************\n\nstatic LPCTSTR         g_szAppName     = TEXT(\"Pocket UnZip\");\nstatic LPCTSTR         g_szClass       = TEXT(\"PocketUnZip\");\nstatic LPCTSTR         g_szRegKey      = TEXT(\"Software\\\\Pocket UnZip\");\nstatic LPCTSTR         g_szTempDir     = NULL;\nstatic HWND            g_hWndList      = NULL;\nstatic HWND            g_hWndCmdBar    = NULL;\nstatic int             g_cyCmdBar      = 0;\nstatic HFONT           g_hFontBanner   = NULL;\nstatic HICON           g_hIconMain     = NULL;\nstatic WNDPROC         g_wpSaveAsDlg   = NULL;\nstatic WNDPROC         g_wpEdit        = NULL;\nstatic int             g_sortColumn    = -1;\nstatic BOOL            g_fExpandedView = FALSE;\nstatic BOOL            g_fLoading      = FALSE;\nstatic BOOL            g_fSkipped      = FALSE;\nstatic BOOL            g_fViewing      = FALSE;\nstatic HWND            g_hWndWaitFor   = NULL;\nstatic FILE_TYPE_NODE *g_pftHead       = NULL;\n\n#ifdef _WIN32_WCE\nstatic LPCTSTR         g_szHelpFile    = TEXT(\"\\\\windows\\\\punzip.htp\");\n#else\nstatic TCHAR           g_szTempDirPath[_MAX_PATH];\nstatic LPCTSTR         g_szHelpFile    = TEXT(\"punzip.html\");\n#endif\n\nstatic COLUMN g_columns[] = {\n   { TEXT(\"Name\"),       LVCFMT_LEFT  },\n   { TEXT(\"Size\"),       LVCFMT_RIGHT },\n   { TEXT(\"Type\"),       LVCFMT_LEFT  },\n   { TEXT(\"Modified\"),   LVCFMT_LEFT  },\n   { TEXT(\"Attributes\"), LVCFMT_LEFT  },\n   { TEXT(\"Compressed\"), LVCFMT_RIGHT },\n   { TEXT(\"Ratio\"),      LVCFMT_RIGHT },\n   { TEXT(\"Method\"),     LVCFMT_LEFT  },\n   { TEXT(\"CRC\"),        LVCFMT_LEFT  },\n   { TEXT(\"Comment\"),    LVCFMT_LEFT  }\n};\n\n\n//******************************************************************************\n//***** Local Function Prototypes\n//******************************************************************************\n\n// Startup and Shutdown Functions\nvoid InitializeApplication(LPCTSTR szZipFile);\nvoid ShutdownApplication();\nvoid RegisterUnzip();\nvoid BuildImageList();\n\n// Our Main Window's Message Handler\nLRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// Event Handlers for our Main Window\nint OnCreate();\nvoid OnFileOpen();\nvoid OnActionView();\nvoid OnActionSelectAll();\nvoid OnViewExpandedView();\nvoid OnHelp();\n\n// Event Handlers for our List View\nvoid OnGetDispInfo(LV_DISPINFO *plvdi);\nvoid OnDeleteItem(NM_LISTVIEW *pnmlv);\nvoid OnItemChanged(NM_LISTVIEW *pnmlv);\n\n// List View Sort Functions\nvoid Sort(int sortColumn, BOOL fForce);\nint CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM sortColumn);\n\n// Helper/Utility Functions\nvoid SetCaptionText(LPCTSTR szPrefix);\nvoid DrawBanner(HDC hdc);\nvoid AddDeleteColumns();\nvoid ResizeColumns();\nLPCTSTR GetZipErrorString(int error);\nvoid AddFileToListView(FILE_NODE *pFile);\nvoid EnableAllMenuItems(UINT uMenuItem, BOOL fEnabled);\nvoid CheckAllMenuItems(UINT uMenuItem, BOOL fChecked);\nvoid CenterWindow(HWND hWnd);\nvoid AddTextToEdit(LPCSTR szText);\nLPTSTR FormatValue(LPTSTR szValue, zusz_t uzValue);\nLPTSTR BuildAttributesString(LPTSTR szBuffer, DWORD dwAttributes);\nLPCSTR BuildTypeString(FILE_NODE *pFile, LPSTR szType);\nLPCSTR GetFileFromPath(LPCSTR szPath);\nvoid ForwardSlashesToBackSlashesA(LPSTR szBuffer);\n#ifdef UNICODE\n   void ForwardSlashesToBackSlashesW(LPWSTR szBuffer);\n#  define ForwardSlashesToBackSlashes ForwardSlashesToBackSlashesW\n#else\n#  define ForwardSlashesToBackSlashes ForwardSlashesToBackSlashesA\n#endif\nvoid DeleteDirectory(LPTSTR szPath);\n\n// Registry Functions\nvoid RegWriteKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPCTSTR szValue);\nBOOL RegReadKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPTSTR szValue, DWORD cBytes);\nvoid WriteOptionString(LPCTSTR szOption, LPCTSTR szValue);\nvoid WriteOptionInt(LPCTSTR szOption, DWORD dwValue);\nLPTSTR GetOptionString(LPCTSTR szOption, LPCTSTR szDefault, LPTSTR szValue, DWORD nSize);\nDWORD GetOptionInt(LPCTSTR szOption, DWORD dwDefault);\n\n// EDIT Control Subclass Functions\nvoid DisableEditing(HWND hWndEdit);\nLRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// MRU Functions\nvoid InitializeMRU();\nvoid AddFileToMRU(LPCSTR szFile);\nvoid RemoveFileFromMRU(LPCTSTR szFile);\nvoid ActivateMRU(UINT uIDItem);\n\n// Open Zip File Functions\nvoid ReadZipFileList(LPCTSTR wszPath);\n\n// Zip File Properties Dialog Functions\nBOOL CALLBACK DlgProcProperties(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\nvoid MergeValues(int *p1, int p2);\nvoid CheckThreeStateBox(HWND hDlg, int nIDButton, int state);\n\n// Extract/Test Dialog Functions\nvoid ExtractOrTestFiles(BOOL fExtract);\nBOOL CALLBACK DlgProcExtractOrTest(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// Folder Browsing Dialog Functions\nBOOL FolderBrowser(LPTSTR szPath, DWORD dwLength);\nBOOL CALLBACK DlgProcBrowser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\nvoid SubclassSaveAsDlg();\n\n// Extraction/Test/View Progress Dialog Functions\nBOOL CALLBACK DlgProcExtractProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\nBOOL CALLBACK DlgProcViewProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\nvoid UpdateProgress(EXTRACT_INFO *pei, BOOL fFull);\n\n// Replace File Dialog Functions\nint PromptToReplace(LPCSTR szPath);\nBOOL CALLBACK DlgProcReplace(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// Password Dialog Functions\nBOOL CALLBACK DlgProcPassword(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// View Association Dialog Functions\nBOOL CALLBACK DlgProcViewAssociation(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// Comment Dialog Functions\nBOOL CALLBACK DlgProcComment(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n// About Dialog Functions\nBOOL CALLBACK DlgProcAbout(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);\n\n\n//******************************************************************************\n//***** WinMain - Our one and only entry point\n//******************************************************************************\n\n// Entrypoint is a tiny bit different on Windows CE - UNICODE command line.\n#ifdef _WIN32_WCE\nextern \"C\" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                              LPTSTR lpCmdLine, int nCmdShow)\n#else\nextern \"C\" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                              LPSTR lpCmdLine, int nCmdShow)\n#endif\n{\n   // Wrap the whole ball of wax in a big exception handler.\n   __try {\n\n      // Store global instance handle.\n      g_hInst = hInstance;\n\n      // Create our banner font.  We need to do this before creating our window.\n      // This font handle will be deleted in ShutdownApplication().\n      LOGFONT lf;\n      ZeroMemory(&lf, sizeof(lf));\n      lf.lfHeight = 16;\n      lf.lfWeight = FW_BOLD;\n      lf.lfCharSet = ANSI_CHARSET;\n      lf.lfOutPrecision = OUT_DEFAULT_PRECIS;\n      lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;\n      lf.lfQuality = DEFAULT_QUALITY;\n      lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;\n      _tcscpy(lf.lfFaceName, TEXT(\"MS Sans Serif\"));\n      g_hFontBanner = CreateFontIndirect(&lf);\n\n      // Define the window class for our application's main window.\n      WNDCLASS wc;\n      ZeroMemory(&wc, sizeof(wc));\n      wc.lpszClassName = g_szClass;\n      wc.hInstance     = hInstance;\n      wc.lpfnWndProc   = WndProc;\n      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);\n\n      TCHAR *szZipPath = NULL;\n\n#ifdef _WIN32_WCE\n\n      // Get our main window's small icon.  On Windows CE, we need to send ourself\n      // a WM_SETICON in order for our task bar to update itself.\n      g_hIconMain = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_UNZIP),\n                                     IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);\n      wc.hIcon = g_hIconMain;\n\n      // On Windows CE, we only need the WS_VISIBLE flag.\n      DWORD dwStyle = WS_VISIBLE;\n\n      // Get and store command line file (if any).\n      if (lpCmdLine && *lpCmdLine) {\n         szZipPath = lpCmdLine;\n      }\n\n#else\n\n      // On NT we add a cursor, icon, and menu to our application's window class.\n      wc.hCursor      = LoadCursor(NULL, IDC_ARROW);\n      wc.hIcon        = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UNZIP));\n      wc.lpszMenuName = MAKEINTRESOURCE(IDR_UNZIP);\n\n      // On Windows NT, we use the standard overlapped window style.\n      DWORD dwStyle = WS_OVERLAPPEDWINDOW;\n\n      TCHAR szBuffer[_MAX_PATH];\n\n      // Get and store command line file (if any).\n      if (lpCmdLine && *lpCmdLine) {\n         MBSTOTSTR(szBuffer, lpCmdLine, countof(szBuffer));\n         szZipPath = szBuffer;\n      }\n\n#endif\n\n      // Register our window class with the OS.\n      if (!RegisterClass(&wc)) {\n         DebugOut(TEXT(\"RegisterClass() failed [%u]\"), GetLastError());\n      }\n\n      // Create our main window using our registered window class.\n      g_hWndMain = CreateWindow(wc.lpszClassName, g_szAppName, dwStyle,\n                                CW_USEDEFAULT, CW_USEDEFAULT,\n                                CW_USEDEFAULT, CW_USEDEFAULT,\n                                NULL, NULL, hInstance, NULL);\n\n      // Quit now if we failed to create our main window.\n      if (!g_hWndMain) {\n         DebugOut(TEXT(\"CreateWindow() failed [%u]\"), GetLastError());\n         ShutdownApplication();\n         return 0;\n      }\n\n      // Make sure our window is visible.  Really only needed for NT.\n      ShowWindow(g_hWndMain, nCmdShow);\n\n      // Load our keyboard accelerator shortcuts.\n      MSG    msg;\n      HACCEL hAccel = LoadAccelerators(g_hInst, MAKEINTRESOURCE(IDR_UNZIP));\n      DWORD  dwPaintFlags = 0;\n\n      // The message pump.  Loop until we get a WM_QUIT message.\n      while (GetMessage(&msg, NULL, 0, 0)) {\n\n         // Check to see if this is an accelerator and handle it if neccessary.\n         if (!TranslateAccelerator(g_hWndMain, hAccel, &msg)) {\n\n            // If a normal message, then dispatch it to the correct window.\n            TranslateMessage(&msg);\n            DispatchMessage(&msg);\n\n            // Wait until our application is up and visible before trying to\n            // initialize some of our structures and load any command line file.\n            if ((msg.message == WM_PAINT) && (dwPaintFlags != 0x11)) {\n               if (msg.hwnd == g_hWndWaitFor) {\n                  dwPaintFlags |= 0x01;\n               } else if (msg.hwnd == g_hWndList) {\n                  dwPaintFlags |= 0x10;\n               }\n               if (dwPaintFlags == 0x11) {\n                  InitializeApplication((szZipPath && *szZipPath) ?\n                                        szZipPath : NULL);\n               }\n            }\n         }\n      }\n\n      // Clean up code.\n      ShutdownApplication();\n\n      // Nice clean finish - were out of here.\n      return msg.wParam;\n\n\n   } __except(EXCEPTION_EXECUTE_HANDLER) {\n\n      // Something very bad happened.  Try our best to appear somewhat graceful.\n      MessageBox(NULL,\n         TEXT(\"An internal error occurred.  Possible causes are that you are \")\n         TEXT(\"out of memory, a ZIP file (if one is loaded) contains an \")\n         TEXT(\"unexpected error, or there is a bug in our program (that's why \")\n         TEXT(\"it's free).  Pocket UnZip cannot continue.  It will exit now, \")\n         TEXT(\"but you may restart it and try again.\\n\\n\")\n         TEXT(\"If the problem persists, please write to stevemil@pobox.com with \")\n         TEXT(\"any information that might help track down the problem.\"),\n         g_szAppName, MB_ICONERROR | MB_OK);\n   }\n\n   return 1;\n}\n\n\n//******************************************************************************\n//***** Startup and Shutdown Functions\n//******************************************************************************\n\nvoid InitializeApplication(LPCTSTR szZipFile) {\n\n   // This function is called after our class is registered and all our windows\n   // are created and visible to the user.\n\n   // Show hour glass cursor.\n   HCURSOR hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));\n\n   // Register UnZip in the registry to handle \".ZIP\" files.\n   RegisterUnzip();\n\n   // Enumerate the system file assoications and build an image list.\n   BuildImageList();\n\n   // Load our initial MRU into our menu.\n   InitializeMRU();\n\n   // Restore/remove our cursor.\n   SetCursor(hCur);\n\n   // Clear our initialization window handle.\n   g_hWndWaitFor = NULL;\n\n   // Load our command line file if one was specified. Otherwise, just update\n   // our banner to show that no file is loaded.\n   if (szZipFile) {\n      ReadZipFileList(szZipFile);\n   } else {\n      DrawBanner(NULL);\n   }\n\n   // Enable some controls.\n   EnableAllMenuItems(IDM_FILE_OPEN,          TRUE);\n   EnableAllMenuItems(IDM_FILE_CLOSE,         TRUE);\n   EnableAllMenuItems(IDM_VIEW_EXPANDED_VIEW, TRUE);\n   EnableAllMenuItems(IDM_HELP_ABOUT,         TRUE);\n\n   // Set our temporary directory.\n#ifdef _WIN32_WCE\n   g_szTempDir = TEXT(\"\\\\Temporary Pocket UnZip Files\");\n#else\n   g_szTempDir = TEXT(\"C:\\\\Temporary Pocket UnZip Files\");\n\n   // Set the drive to be the same drive as the OS installation is on.\n   if (GetWindowsDirectory(g_szTempDirPath, countof(g_szTempDirPath))) {\n      lstrcpy(g_szTempDirPath + 3, TEXT(\"Temporary Pocket UnZip Files\"));\n      g_szTempDir  = g_szTempDirPath;\n   }\n#endif\n}\n\n//******************************************************************************\nvoid ShutdownApplication() {\n\n   // Free our banner font.\n   if (g_hFontBanner) {\n      DeleteObject(g_hFontBanner);\n      g_hFontBanner = NULL;\n   }\n\n   // Delete our FILE_TYPE_NODE linked list.\n   for (FILE_TYPE_NODE *pft = g_pftHead; pft; ) {\n      FILE_TYPE_NODE *pftNext = pft->pNext;\n      delete[] (BYTE*)pft;\n      pft = pftNext;\n   }\n   g_pftHead = NULL;\n\n   // If there are no other instances of our application open, then delete our\n   // temporary directory and all the files in it.  Any files opened for viewing\n   // should be locked and will fail to delete.  This is to be expected.\n   if (g_szTempDir && (FindWindow(g_szClass, NULL) == NULL)) {\n      TCHAR szPath[_MAX_PATH];\n      _tcscpy(szPath, g_szTempDir);\n      DeleteDirectory(szPath);\n   }\n}\n\n//******************************************************************************\nvoid RegisterUnzip() {\n\n#ifdef _WIN32_WCE\n\n   // WARNING!  Since Windows CE does not support any way to get your binary's\n   // name at runtime, we have to hard-code in \"punzip.exe\".  If our binary is\n   // not named this or is in a non-path directory, then we will fail to\n   // register ourself with the system as the default application to handle\n   // \".zip\" files.\n   TCHAR szPath[32] = TEXT(\"punzip.exe\");\n   TCHAR szTstPath[32];\n\n#else\n\n   // Get our module's path and file name.  We use the short path name for the\n   // registry because it is guaranteed to contain no spaces.\n   TCHAR szLongPath[_MAX_PATH];\n   TCHAR szPath[_MAX_PATH];\n   TCHAR szTstPath[_MAX_PATH];\n   GetModuleFileName(NULL, szLongPath, countof(szLongPath));\n   GetShortPathName(szLongPath, szPath, countof(szPath));\n\n#endif\n\n   // Store a pointer to the end of our path for easy appending.\n   LPTSTR szEnd = szPath + _tcslen(szPath);\n\n   BOOL fDoRegisterPUnZip = TRUE;\n\n   // Associate \"ZIP\" file extensions to our application\n   if (RegReadKey(HKEY_CLASSES_ROOT, TEXT(\".zip\"), szTstPath, sizeof(szTstPath)))\n   {\n      if (_tcscmp(szTstPath, TEXT(\"zipfile\")) != 0)\n         fDoRegisterPUnZip = FALSE;\n      else if (RegReadKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\\\\shell\\\\Open\\\\command\"),\n                          szTstPath, sizeof(szTstPath)) &&\n               (_tcsncmp(szTstPath, szPath, _tcslen(szPath)) != 0))\n         fDoRegisterPUnZip = FALSE;\n\n      if (!fDoRegisterPUnZip)\n      {\n         fDoRegisterPUnZip =\n            (IDOK == MessageBox(g_hWndMain,\n                                TEXT(\"Currently, Pocket UnZip is not registered as default \")\n                                TEXT(\"handler for Zip archives.\\n\\n\")\n                                TEXT(\"Please, confirm that Pocket UnZip should now register itself \")\n                                TEXT(\"as default application for handling Zip archives (.zip files)\"),\n                                g_szAppName,\n                                MB_ICONQUESTION | MB_OKCANCEL));\n      }\n   }\n   if (fDoRegisterPUnZip) {\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\".zip\"), TEXT(\"zipfile\"));\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\"), TEXT(\"ZIP File\"));\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\\\\shell\"), NULL);\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\\\\shell\\\\Open\"), NULL);\n      _tcscpy(szEnd, TEXT(\" %1\"));\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\\\\shell\\\\Open\\\\command\"), szPath);\n\n      // Register our program icon for all ZIP files.\n      _stprintf(szEnd, TEXT(\",-%u\"), IDI_ZIPFILE);\n      RegWriteKey(HKEY_CLASSES_ROOT, TEXT(\"zipfile\\\\DefaultIcon\"), szPath);\n   }\n\n   // Create our application option location.\n   RegWriteKey(HKEY_CURRENT_USER, TEXT(\"Software\"), NULL);\n   RegWriteKey(HKEY_CURRENT_USER, g_szRegKey, NULL);\n}\n\n//******************************************************************************\nvoid BuildImageList() {\n\n   // Create our global image list.\n#ifdef _WIN32_WCE\n\n   // On Windows CE, we can't spare a color for the mask, so we have to create\n   // the mask in a separate monochrome bitmap.\n\n   HIMAGELIST hil = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 8, 8);\n\n   // Load our default bitmaps into the image list.\n   HBITMAP hBmpImageList = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST));\n   HBITMAP hBmpMask = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST_MASK));\n   ImageList_Add(hil, hBmpImageList, hBmpMask);\n   DeleteObject(hBmpImageList);\n   DeleteObject(hBmpMask);\n\n#else\n\n   // On Windows NT, we use magenta as a transparency mask color.\n   HIMAGELIST hil = ImageList_LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_IMAGELIST),\n                                         16, 8, RGB(255, 0, 255));\n#endif\n\n   // Set up for our registry file type enumeration.\n   FILE_TYPE_NODE *pftLast = NULL;\n   TCHAR szExtension[128], szKey[128], szDescription[_MAX_PATH], szIconFile[_MAX_PATH + 16];\n   DWORD dwIndex = 0, dwCount = countof(szExtension);\n\n   // Enumerate all the keys immediately under HKEY_CLASSES_ROOT.\n   while (ERROR_SUCCESS == RegEnumKeyEx(HKEY_CLASSES_ROOT, dwIndex++, szExtension,\n                                        &dwCount, NULL, NULL, NULL, NULL))\n   {\n      dwCount = countof(szExtension);\n\n      // Check to see if we read an extension key (starts with a period)\n      if (*szExtension != TEXT('.')) {\n         continue;\n      }\n\n      // Read the actual key name for this extension.\n      if (!RegReadKey(HKEY_CLASSES_ROOT, szExtension, szKey, sizeof(szKey))) {\n         continue;\n      }\n\n      // Read the Description for this extension.\n      RegReadKey(HKEY_CLASSES_ROOT, szKey, szDescription, sizeof(szDescription));\n\n      HICON hIcon = NULL;\n      LPTSTR szEnd = szKey + _tcslen(szKey);\n\n      // Attempt to get an icon for this extension from the \"DefaultIcon\" key.\n      _tcscpy(szEnd, TEXT(\"\\\\DefaultIcon\"));\n      if (RegReadKey(HKEY_CLASSES_ROOT, szKey, szIconFile, sizeof(szIconFile))) {\n\n         // Look for the comma between the file name and the image.\n         LPTSTR szImageId = _tcschr(szIconFile, TEXT(','));\n         if (szImageId) {\n\n            // NULL terminate the file name portion of szIconFile.\n            *(szImageId++) = TEXT('\\0');\n\n            // Get the image ID value from szIconFile.\n            int imageId = _ttoi(szImageId);\n\n            // Extract the icon from the module specified in szIconFile.\n            ExtractIconEx(szIconFile, imageId, NULL, &hIcon, 1);\n            if (hIcon == NULL) {\n               ExtractIconEx(szIconFile, imageId, &hIcon, NULL, 1);\n            }\n         }\n      }\n\n      // If we failed to get the icon using the \"DefaultIcon\" key, then try\n      // using the \"shell\\Open\\command\" key.\n      if (hIcon == NULL) {\n\n         _tcscpy(szEnd, TEXT(\"\\\\shell\\\\Open\\\\command\"));\n         if (RegReadKey(HKEY_CLASSES_ROOT, szKey, szIconFile, sizeof(szIconFile))) {\n\n            // Get a pointer to just the binary - strip quotes and spaces.\n            LPTSTR szPath;\n            if (*szIconFile == TEXT('\\\"')) {\n               szPath = szIconFile + 1;\n               if (szEnd = _tcschr(szPath, TEXT('\\\"'))) {\n                  *szEnd = TEXT('\\0');\n               }\n            } else {\n               szPath = szIconFile;\n               if (szEnd = _tcschr(szPath, TEXT(' '))) {\n                  *szEnd = TEXT('\\0');\n               }\n            }\n\n            // Extract the icon from the module specified in szIconFile.\n            ExtractIconEx(szPath, 0, NULL, &hIcon, 1);\n            if (hIcon == NULL) {\n               ExtractIconEx(szPath, 0, &hIcon, NULL, 1);\n            }\n         }\n      }\n\n      // If we found an icon, add it to our image list.\n      int image = -1;\n      if (hIcon) {\n         image = ImageList_AddIcon(hil, hIcon);\n      }\n\n      // If no icon could be found, then check to see if this is an executable.\n      if ((image == -1) && (\n#ifndef _WIN32_WCE // Windows CE only recognizes EXE's as executable.\n         !_tcsicmp(szExtension + 1, TEXT(\"bat\")) ||\n         !_tcsicmp(szExtension + 1, TEXT(\"cmd\")) ||\n         !_tcsicmp(szExtension + 1, TEXT(\"com\")) ||\n#endif\n         !_tcsicmp(szExtension + 1, TEXT(\"exe\"))))\n      {\n         image = IMAGE_APPLICATION;\n      }\n\n      // If we don't have a description or a icon, then bail on this extension.\n      if (!*szDescription && (image < 0)) {\n         continue;\n      }\n\n      // Create our FILE_TYPE_NODE.\n      size_t length = _tcslen(szExtension) - 1 + _tcslen(szDescription);\n      FILE_TYPE_NODE *pft = (FILE_TYPE_NODE*) new BYTE[\n         sizeof(FILE_TYPE_NODE) + (sizeof(TCHAR) * length)];\n\n      // Bail out if we could not create our node.\n      if (!pft) {\n         DebugOut(TEXT(\"Not enough memory to create a FILE_TYPE_NODE.\"));\n         continue;\n      }\n\n      // Fill in the node.\n      pft->pNext = NULL;\n      pft->image = (image >= 0) ? image : IMAGE_GENERIC;\n      TSTRTOMBS(pft->szExtAndDesc, szExtension + 1, length + 2);\n      size_t sizext = (strlen(pft->szExtAndDesc) + 1);\n      TSTRTOMBS(pft->szExtAndDesc + sizext,\n                szDescription, length - sizext + 2);\n\n      // Add the node to our list.\n      if (pftLast) {\n         pftLast->pNext = pft;\n      } else {\n         g_pftHead = pft;\n      }\n      pftLast = pft;\n   }\n\n   // Assign this image list to our tree control.\n   ListView_SetImageList(g_hWndList, hil, LVSIL_SMALL);\n}\n\n\n//******************************************************************************\n//***** Our Main Window's Message Handler\n//******************************************************************************\n\nLRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   switch(uMsg) {\n      case WM_CREATE:\n         g_hWndMain = hWnd;\n         return OnCreate();\n\n      case WM_ERASEBKGND:\n         DrawBanner((HDC)wParam);\n         return 0;\n\n      case WM_SIZE:\n         // Resize our list view control to match our client area.\n         MoveWindow(g_hWndList, 0, g_cyCmdBar + 22, LOWORD(lParam),\n                    HIWORD(lParam) - (g_cyCmdBar + 22), TRUE);\n\n#ifndef _WIN32_WCE\n         // On NT we have to resize our toolbar as well.\n         MoveWindow(g_hWndCmdBar, 0, 0, LOWORD(lParam), g_cyCmdBar, TRUE);\n#endif\n         return 0;\n\n      case WM_SETFOCUS:\n         // Always direct focus to our list control.\n         SetFocus(g_hWndList);\n         return 0;\n\n      case WM_DESTROY:\n         PostQuitMessage(0);\n         return 0;\n\n      case WM_HELP:\n         OnHelp();\n         return 0;\n\n      case WM_PRIVATE:\n         switch (wParam) {\n\n#ifdef _WIN32_WCE\n            case MSG_SUBCLASS_DIALOG:\n               SubclassSaveAsDlg();\n               return 0;\n#endif\n            case MSG_ADD_TEXT_TO_EDIT:\n               AddTextToEdit((LPCSTR)lParam);\n               return 0;\n\n            case MSG_PROMPT_TO_REPLACE:\n               return PromptToReplace((LPCSTR)lParam);\n\n#if CRYPT\n            case MSG_PROMPT_FOR_PASSWORD:\n               return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_PASSWORD),\n                                     g_hDlgProgress, (DLGPROC)DlgProcPassword,\n                                     lParam);\n#endif\n\n            case MSG_UPDATE_PROGRESS_PARTIAL:\n               UpdateProgress((EXTRACT_INFO*)lParam, FALSE);\n               return 0;\n\n            case MSG_UPDATE_PROGRESS_COMPLETE:\n               UpdateProgress((EXTRACT_INFO*)lParam, TRUE);\n               return 0;\n         }\n         return 0;\n\n      case WM_NOTIFY:\n         switch (((LPNMHDR)lParam)->code) {\n\n            case LVN_GETDISPINFO:\n               OnGetDispInfo((LV_DISPINFO*)lParam);\n               return 0;\n\n            case LVN_DELETEITEM:\n               OnDeleteItem((NM_LISTVIEW*)lParam);\n               return 0;\n\n            case LVN_COLUMNCLICK:\n               Sort(((NM_LISTVIEW*)lParam)->iSubItem, FALSE);\n               return 0;\n\n            case LVN_ITEMCHANGED:\n               OnItemChanged((NM_LISTVIEW*)lParam);\n               return 0;\n\n            case NM_DBLCLK:\n            case NM_RETURN:\n               OnActionView();\n               return 0;\n         }\n\n         return 0;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n\n            case IDM_FILE_OPEN:\n               OnFileOpen();\n               return 0;\n\n            case IDM_FILE_PROPERTIES:\n               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_PROPERTIES), hWnd, (DLGPROC)DlgProcProperties);\n               return 0;\n\n            case IDM_FILE_CLOSE:\n               SendMessage(hWnd, WM_CLOSE, 0, 0);\n               return 0;\n\n            case IDM_ACTION_EXTRACT_ALL:\n               OnActionSelectAll();\n               // Fall through to IDM_ACTION_EXTRACT\n\n            case IDM_ACTION_EXTRACT:\n               ExtractOrTestFiles(TRUE);\n               return 0;\n\n            case IDM_ACTION_TEST_ALL:\n               OnActionSelectAll();\n               // Fall through to IDM_ACTION_TEST\n\n            case IDM_ACTION_TEST:\n               ExtractOrTestFiles(FALSE);\n               return 0;\n\n            case IDM_ACTION_VIEW:\n               OnActionView();\n               return 0;\n\n            case IDM_ACTION_SELECT_ALL:\n               OnActionSelectAll();\n               return 0;\n\n            case IDM_VIEW_EXPANDED_VIEW:\n               OnViewExpandedView();\n               return 0;\n\n            case IDM_VIEW_COMMENT:\n               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_COMMENT), hWnd, (DLGPROC)DlgProcComment);\n               return 0;\n\n            case IDM_HELP_ABOUT:\n               DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)DlgProcAbout);\n               return 0;\n\n            case IDHELP:\n               return SendMessage(hWnd, WM_HELP, 0, 0);\n\n            default:\n               // Check to see if a MRU file was selected.\n               if ((LOWORD(wParam) >= MRU_START_ID) &&\n                   (LOWORD(wParam) < (MRU_START_ID + MRU_MAX_FILE)))\n               {\n                  ActivateMRU(LOWORD(wParam));\n               }\n         }\n    }\n    return DefWindowProc(hWnd, uMsg, wParam, lParam);\n}\n\n//******************************************************************************\n//***** Event Handlers for our Main Window\n//******************************************************************************\n\nint OnCreate() {\n\n   // Our toolbar buttons.\n   static TBBUTTON tbButton[] = {\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 0, IDM_FILE_OPEN,          0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 1, IDM_FILE_PROPERTIES,    0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 2, IDM_ACTION_EXTRACT,     0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 3, IDM_ACTION_EXTRACT_ALL, 0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 4, IDM_ACTION_TEST,        0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 5, IDM_ACTION_TEST_ALL,    0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 6, IDM_ACTION_VIEW,        0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 0, 0,                      0, TBSTYLE_SEP,    0, 0, 0, -1 },\n      { 7, IDM_VIEW_EXPANDED_VIEW, 0, TBSTYLE_BUTTON, 0, 0, 0, -1 },\n      { 8, IDM_VIEW_COMMENT,       0, TBSTYLE_BUTTON, 0, 0, 0, -1 }\n   };\n\n   // Our toolbar buttons' tool tip text.\n   static LPTSTR szToolTips[] = {\n       TEXT(\"\"),  // Menu\n       TEXT(\"Open (Ctrl+O)\"),\n       TEXT(\"Properties (Alt+Enter)\"),\n       TEXT(\"Extract Selected Files\"),\n       TEXT(\"Extract All Files\"),\n       TEXT(\"Test Selected Files\"),\n       TEXT(\"Test All Files\"),\n       TEXT(\"View Selected File\"),\n       TEXT(\"Expanded View\"),\n       TEXT(\"View Zip File Comment\")\n   };\n\n   // Initialize the common controls.\n   InitCommonControls();\n\n   // Check to see if we have a help file.\n   BOOL fHelp = (GetFileAttributes(g_szHelpFile) != 0xFFFFFFFF);\n\n   // Set our window's icon so it can update the task bar.\n   if (g_hIconMain) {\n      SendMessage(g_hWndMain, WM_SETICON, FALSE, (LPARAM)g_hIconMain);\n   }\n\n   // Create the tree control.  Our main window will resize it to fit.\n   g_hWndList = CreateWindow(WC_LISTVIEW, TEXT(\"\"),\n                             WS_VSCROLL | WS_CHILD | WS_VISIBLE |\n                             LVS_REPORT | LVS_SHOWSELALWAYS,\n                             0, 0, 0, 0, g_hWndMain, NULL, g_hInst, NULL);\n\n#ifdef _WIN32_WCE\n\n   // Create a command bar and add the toolbar bitmaps to it.\n   g_hWndCmdBar = CommandBar_Create(g_hInst, g_hWndMain, 1);\n   CommandBar_AddBitmap(g_hWndCmdBar, g_hInst, IDB_TOOLBAR, 9, 16, 16);\n   CommandBar_InsertMenubar(g_hWndCmdBar, g_hInst, IDR_UNZIP, 0);\n   CommandBar_AddButtons(g_hWndCmdBar, countof(tbButton), tbButton);\n   CommandBar_AddAdornments(g_hWndCmdBar, fHelp ? CMDBAR_HELP : 0, 0);\n\n   // Add tool tips to the tool bar.\n   CommandBar_AddToolTips(g_hWndCmdBar, countof(szToolTips), szToolTips);\n\n   // Store the height of the command bar for later calculations.\n   g_cyCmdBar = CommandBar_Height(g_hWndCmdBar);\n\n   // We set our wait window handle to our menu window within our command bar.\n   // This is the last window that will be painted during startup of our app.\n   g_hWndWaitFor = GetWindow(g_hWndCmdBar, GW_CHILD);\n\n   // Add the help item to our help menu if we have a help file.\n   if (fHelp) {\n      HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 3);\n      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);\n      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED, IDHELP, TEXT(\"&Help\"));\n   }\n\n#else\n\n   // Create a tool bar and add the toolbar bitmaps to it.\n   g_hWndCmdBar = CreateToolbarEx(g_hWndMain, WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS,\n                                  1, 9, g_hInst, IDB_TOOLBAR, tbButton,\n                                  countof(tbButton), 16, 16, 16, 16,\n                                  sizeof(TBBUTTON));\n\n   // Get our tool tip control.\n   HWND hWndTT = (HWND)SendMessage(g_hWndCmdBar, TB_GETTOOLTIPS, 0, 0);\n\n   // Set our tool tip strings.\n   TOOLINFO ti;\n   ti.cbSize = sizeof(ti);\n   int tip = 0, button;\n   while (SendMessage(hWndTT, TTM_ENUMTOOLS, tip++, (LPARAM)&ti)) {\n      for (button = 0; button < countof(tbButton); button++) {\n         if (tbButton[button].idCommand == (int)ti.uId) {\n            ti.lpszText = szToolTips[tbButton[button].iBitmap + 1];\n            SendMessage(hWndTT, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);\n            break;\n         }\n      }\n   }\n\n   // Store the height of the tool bar for later calculations.\n   RECT rc;\n   GetWindowRect(g_hWndCmdBar, &rc);\n   g_cyCmdBar = rc.bottom - rc.top;\n\n   // We set our wait window handle to our toolbar.\n   // This is the last window that will be painted during the startup of our app.\n   g_hWndWaitFor = g_hWndCmdBar;\n\n   // Add the help item to our help menu if we have a help file.\n   if (fHelp) {\n      HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 3);\n      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);\n      InsertMenu(hMenu, 0, MF_BYPOSITION | MF_ENABLED, IDHELP, TEXT(\"&Help\\tF1\"));\n   }\n\n#endif // _WIN32_WCE\n\n   // Enable Full Row Select - This feature is supported on Windows CE and was\n   // introduced to Win95/NT with IE 3.0.  If the user does not have a\n   // COMCTL32.DLL that supports this feature, then they will just see the\n   // old standard First Column Select.\n   SendMessage(g_hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT |\n               SendMessage(g_hWndList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0));\n\n   // Get our expanded view option from the registry.\n   g_fExpandedView = GetOptionInt(TEXT(\"ExpandedView\"), FALSE);\n\n   // Show or remove menu check for expanded view option.\n   CheckAllMenuItems(IDM_VIEW_EXPANDED_VIEW, g_fExpandedView);\n\n   // Create our columns.\n   AddDeleteColumns();\n\n   // Set our current sort column to our name column\n   Sort(0, TRUE);\n\n   return 0;\n}\n\n//******************************************************************************\nvoid OnFileOpen() {\n\n   TCHAR szPath[_MAX_PATH] = TEXT(\"\");\n\n   OPENFILENAME ofn;\n   ZeroMemory(&ofn, sizeof(ofn));\n\n   ofn.lStructSize  = sizeof(ofn);\n   ofn.hwndOwner    = g_hWndMain;\n   ofn.hInstance    = g_hInst;\n   ofn.lpstrFilter  = TEXT(\"ZIP files (*.zip)\\0*.zip\\0SFX files (*.exe)\\0*.exe\\0All Files (*.*)\\0*.*\\0\");\n   ofn.nFilterIndex = 1;\n   ofn.lpstrFile    = szPath;\n   ofn.nMaxFile     = countof(szPath);\n   ofn.Flags        = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;\n   ofn.lpstrDefExt  = TEXT(\"zip\");\n\n   if (GetOpenFileName(&ofn)) {\n      ReadZipFileList(szPath);\n   }\n}\n\n//******************************************************************************\nvoid OnActionView() {\n\n   // We only allow a view if one item is selected.\n   int count = ListView_GetSelectedCount(g_hWndList);\n   if (count != 1) {\n      return;\n   }\n\n   // Query the selected item for its FILE_NODE.\n   LV_ITEM lvi;\n   ZeroMemory(&lvi, sizeof(lvi));\n   lvi.mask = LVIF_IMAGE | LVIF_PARAM;\n   lvi.iItem = ListView_GetNextItem(g_hWndList, -1, LVNI_SELECTED);\n   ListView_GetItem(g_hWndList, &lvi);\n   FILE_NODE *pfn = (FILE_NODE*)lvi.lParam;\n\n   // Bail out if the selected item is a folder or volume label.\n   if (pfn->dwAttributes & (FILE_ATTRIBUTE_DIRECTORY | ZFILE_ATTRIBUTE_VOLUME)) {\n      MessageBox(g_hWndMain, TEXT(\"You cannot view folders or volume labels.\"),\n                 g_szAppName, MB_ICONINFORMATION | MB_OK);\n      return;\n   }\n\n   // Make sure our temporary directory exists.\n   CreateDirectory(g_szTempDir, NULL);\n\n   TCHAR szPath[_MAX_PATH + 256];\n\n   // Set our extraction directory to our temporary directory.\n   if (!SetExtractToDirectory((LPTSTR)g_szTempDir)) {\n\n      // Create error message.  Use szPath buffer because it is handy.\n      _stprintf(szPath,\n         TEXT(\"Could not create \\\"%s\\\"\\n\\n\")\n         TEXT(\"Most likely cause is that your drive is full.\"),\n         g_szTempDir);\n\n      // Display error message.\n      MessageBox(g_hWndMain, szPath, g_szAppName, MB_ICONERROR | MB_OK);\n\n      return;\n   }\n\n   // Create our single item file array.\n   CHAR *argv[2] = { pfn->szPathAndMethod, NULL };\n\n   // Create a buffer to store the mapped name of the file.  If the has to be\n   // renamed to be compatible with our file system, then we need to know that\n   // new name in order to open it correctly.\n   CHAR szMappedPath[_MAX_PATH];\n   *szMappedPath = '\\0';\n\n   // Configure our extract structure.\n   EXTRACT_INFO ei;\n   ZeroMemory(&ei, sizeof(ei));\n   ei.fExtract      = TRUE;\n   ei.dwFileCount   = 1;\n   ei.uzByteCount   = pfn->uzSize;\n   ei.szFileList    = argv;\n   ei.fRestorePaths = FALSE;\n   ei.overwriteMode = OM_PROMPT;\n   ei.szMappedPath  = szMappedPath;\n\n   // Clear our skipped flag and set our viewing flag.\n   g_fSkipped = FALSE;\n   g_fViewing = TRUE;\n\n   // Display our progress dialog and do the extraction.\n   DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_VIEW_PROGRESS), g_hWndMain,\n                  (DLGPROC)DlgProcViewProgress, (LPARAM)&ei);\n\n   // Clear our viewing flag.\n   g_fViewing = FALSE;\n\n   // Check to see if the user skipped the file by aborting the decryption or\n   // overwrite prompts.  The only other case that causes us to skip a file\n   // is when the user enters the incorrect password too many times.  In this\n   // case, IZ_BADPWD will be returned.\n   if (g_fSkipped) {\n      return;\n   }\n   if (ei.result == IZ_BADPWD) {\n      MessageBox(g_hWndMain, TEXT(\"Password was incorrect.  The file has been skipped.\"),\n                 g_szAppName, MB_ICONWARNING | MB_OK);\n      return;\n   }\n\n   // Check to see if the extraction failed.\n   if (ei.result != PK_OK) {\n\n      if (ei.result == PK_ABORTED) {\n         _tcscpy(szPath, GetZipErrorString(ei.result));\n\n      } else {\n         // Create error message.  Use szPath buffer because it is handy.\n         _stprintf(szPath,\n#ifdef UNICODE\n            TEXT(\"Could not extract \\\"%S\\\".\\n\\n%s\\n\\nTry using the Test or \")\n#else\n            TEXT(\"Could not extract \\\"%s\\\".\\n\\n%s\\n\\nTry using the Test or \")\n#endif\n            TEXT(\"Extract action on the file for more details.\"),\n            *szMappedPath ? szMappedPath : pfn->szPathAndMethod,\n            GetZipErrorString(ei.result));\n      }\n\n      // Display error message.\n      MessageBox(g_hWndMain, szPath, g_szAppName, MB_ICONERROR | MB_OK);\n\n      // If we managed to create a bad file, then delete it.\n      if (*szMappedPath) {\n         MBSTOTSTR(szPath, szMappedPath, countof(szPath));\n         SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);\n         if (!DeleteFile(szPath)) {\n            SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);\n         }\n      }\n\n      return;\n   }\n\n   // Convert the file name to UNICODE.\n   MBSTOTSTR(szPath, szMappedPath, countof(szPath));\n\n   // Prepare to launch the file.\n   SHELLEXECUTEINFO sei;\n   ZeroMemory(&sei, sizeof(sei));\n   sei.cbSize      = sizeof(sei);\n   sei.hwnd        = g_hWndMain;\n   sei.lpDirectory = g_szTempDir;\n   sei.nShow       = SW_SHOWNORMAL;\n\n#ifdef _WIN32_WCE\n\n   TCHAR szApp[_MAX_PATH];\n\n   // On Windows CE, there is no default file association dialog that appears\n   // when ShellExecuteEx() is given an unknown file type.  We check to see if\n   // file is unknown, and display our own file association prompt.\n\n   // Check our file image to see if this file has no associated viewer.\n   if (lvi.iImage == IMAGE_GENERIC) {\n\n      // Display our file association prompt dialog.\n      if (IDOK != DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_VIEW_ASSOCIATION),\n                                 g_hWndMain, (DLGPROC)DlgProcViewAssociation,\n                                 (LPARAM)szApp))\n      {\n         // If the user aborted the association prompt, then delete file and exit.\n         SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);\n         if (!DeleteFile(szPath)) {\n            SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);\n         }\n         return;\n      }\n      // Set the file to be the viewer app and the parameters to be the file.\n      // Note: Some applications require that arguments with spaces be quoted,\n      // while other applications choked when quotes we part of the filename.\n      // In the end, it seems safer to leave the quotes off.\n      sei.lpFile = szApp;\n      sei.lpParameters = szPath;\n   } else {\n      sei.lpFile = szPath;\n   }\n\n#else\n\n   // On NT, ShellExecuteEx() will prompt user for association if needed.\n   sei.lpFile = szPath;\n\n#endif\n\n   // Launch the file.  All errors will be displayed by ShellExecuteEx().\n   ShellExecuteEx(&sei);\n}\n\n//******************************************************************************\nvoid OnActionSelectAll() {\n   for (int i = ListView_GetItemCount(g_hWndList) - 1; i >= 0; i--) {\n      ListView_SetItemState(g_hWndList, i, LVIS_SELECTED, LVIS_SELECTED);\n   }\n}\n\n//******************************************************************************\nvoid OnViewExpandedView() {\n\n   // Toggle our expanded view option.\n   g_fExpandedView = !g_fExpandedView;\n\n   // Show or remove menu check and toolbar button press.\n   CheckAllMenuItems(IDM_VIEW_EXPANDED_VIEW, g_fExpandedView);\n\n   // Display the new columns.\n   AddDeleteColumns();\n\n   // Re-sort if we just did away with out sort column.\n   if (!g_fExpandedView && (g_sortColumn > 3)) {\n      Sort(0, TRUE);\n   }\n\n   // Write our expanded view option to the registry.\n   WriteOptionInt(TEXT(\"ExpandedView\"), g_fExpandedView);\n}\n\n//******************************************************************************\nvoid OnHelp() {\n\n   // Prepare to launch the help file.\n   SHELLEXECUTEINFO sei;\n   ZeroMemory(&sei, sizeof(sei));\n   sei.cbSize      = sizeof(sei);\n   sei.hwnd        = g_hWndMain;\n   sei.lpFile      = g_szHelpFile;\n\n   // Launch the file.\n   ShellExecuteEx(&sei);\n}\n\n\n//******************************************************************************\n//***** Event Handlers for our List View\n//******************************************************************************\n\nvoid OnGetDispInfo(LV_DISPINFO *plvdi) {\n\n   // Make sure we have the minimum amount of data to process this event.\n   if ((plvdi->item.iItem < 0) || !plvdi->item.lParam || !plvdi->item.pszText) {\n      return;\n   }\n\n   // Get a pointer to the file node for this item.\n   FILE_NODE *pFile = (FILE_NODE*)plvdi->item.lParam;\n\n   CHAR szBuffer[_MAX_PATH * 2];\n\n   switch (plvdi->item.iSubItem) {\n\n      case 0: // Name\n\n         // Copy the string to a temporary buffer.\n         strcpy(szBuffer, pFile->szPathAndMethod);\n\n         // Change all forward slashes to back slashes in the buffer\n         ForwardSlashesToBackSlashesA(szBuffer);\n\n         // Convert the string to UNICODE and store it in our list control.\n         MBSTOTSTR(plvdi->item.pszText, szBuffer, plvdi->item.cchTextMax);\n\n         return;\n\n      case 1: // Size\n         FormatValue(plvdi->item.pszText, pFile->uzSize);\n         return;\n\n      case 2: // Type\n         MBSTOTSTR(plvdi->item.pszText, BuildTypeString(pFile, szBuffer),\n                  plvdi->item.cchTextMax);\n         return;\n\n      case 3: // Modified\n         int hour; hour = (pFile->dwModified >> 6) & 0x001F;\n         _stprintf(plvdi->item.pszText, TEXT(\"%u/%u/%u %u:%02u %cM\"),\n                   (pFile->dwModified  >> 16) & 0x000F,\n                   (pFile->dwModified  >> 11) & 0x001F,\n                   ((pFile->dwModified >> 20) & 0x0FFF) % 100,\n                   (hour % 12) ? (hour % 12) : 12,\n                   pFile->dwModified & 0x003F,\n                   hour >= 12 ? 'P' : 'A');\n         return;\n\n      case 4: // Attributes\n         BuildAttributesString(plvdi->item.pszText, pFile->dwAttributes);\n         return;\n\n      case 5: // Compressed\n         FormatValue(plvdi->item.pszText, pFile->uzCompressedSize);\n         return;\n\n      case 6: // Ratio\n         int factor; factor = ratio(pFile->uzSize, pFile->uzCompressedSize);\n         _stprintf(plvdi->item.pszText, TEXT(\"%d.%d%%\"), factor / 10,\n                   ((factor < 0) ? -factor : factor) % 10);\n         return;\n\n      case 7: // Method\n         MBSTOTSTR(plvdi->item.pszText, pFile->szPathAndMethod + strlen(pFile->szPathAndMethod) + 1,\n                  plvdi->item.cchTextMax);\n         return;\n\n      case 8: // CRC\n         _stprintf(plvdi->item.pszText, TEXT(\"%08X\"), pFile->dwCRC);\n         return;\n\n      case 9: // Comment\n         MBSTOTSTR(plvdi->item.pszText, pFile->szComment ? pFile->szComment : \"\",\n                   plvdi->item.cchTextMax);\n         return;\n   }\n}\n\n//******************************************************************************\nvoid OnDeleteItem(NM_LISTVIEW *pnmlv) {\n   if (pnmlv->lParam) {\n\n      // Free any comment string associated with this item.\n      if (((FILE_NODE*)pnmlv->lParam)->szComment) {\n         delete[] (CHAR*)((FILE_NODE*)pnmlv->lParam)->szComment;\n      }\n\n      // Free the item itself.\n      delete[] (LPBYTE)pnmlv->lParam;\n   }\n}\n\n//******************************************************************************\nvoid OnItemChanged(NM_LISTVIEW *pnmlv) {\n   int count = ListView_GetSelectedCount(pnmlv->hdr.hwndFrom);\n   EnableAllMenuItems(IDM_FILE_PROPERTIES, count > 0);\n   EnableAllMenuItems(IDM_ACTION_EXTRACT,  count > 0);\n   EnableAllMenuItems(IDM_ACTION_TEST,     count > 0);\n   EnableAllMenuItems(IDM_ACTION_VIEW,     count == 1);\n}\n\n//******************************************************************************\n//***** List View Sort Functions\n//******************************************************************************\n\nvoid Sort(int sortColumn, BOOL fForce) {\n\n   // Do not change the column header text if it is already correct.\n   if (sortColumn != g_sortColumn) {\n\n      TCHAR szColumn[32];\n      LV_COLUMN lvc;\n      lvc.mask = LVCF_TEXT;\n      lvc.pszText = szColumn;\n\n      // Remove the '^' from the current sort column.\n      if (g_sortColumn != -1) {\n         _stprintf(szColumn, (g_columns[g_sortColumn].format == LVCFMT_LEFT) ?\n                   TEXT(\"%s   \") : TEXT(\"   %s\"), g_columns[g_sortColumn].szName);\n         ListView_SetColumn(g_hWndList, g_sortColumn, &lvc);\n      }\n\n      // Set the new sort column.\n      g_sortColumn = sortColumn;\n\n      // Add the '^' to the new sort column.\n      _stprintf(szColumn, (g_columns[g_sortColumn].format == LVCFMT_LEFT) ?\n                TEXT(\"%s ^\") : TEXT(\"^ %s\"), g_columns[g_sortColumn].szName);\n      ListView_SetColumn(g_hWndList, g_sortColumn, &lvc);\n\n      // Sort the list by the new column.\n      ListView_SortItems(g_hWndList, CompareFunc, g_sortColumn);\n\n   } else if (fForce) {\n      // Force the list to sort by the same column.\n      ListView_SortItems(g_hWndList, CompareFunc, g_sortColumn);\n   }\n}\n\n//******************************************************************************\nint CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM sortColumn) {\n   FILE_NODE *pFile1 = (FILE_NODE*)lParam1, *pFile2 = (FILE_NODE*)lParam2;\n   TCHAR szBuffer1[8], szBuffer2[8];\n\n   // Return Negative value if the first item should precede the second.\n   // Return Positive value if the first item should follow the second.\n   // Return Zero if the two items are equivalent.\n\n   int result = 0;\n\n   // Compute the relationship based on the current sort column\n   switch (sortColumn) {\n\n      case 1: // Size - Smallest to Largest\n         if (pFile1->uzSize != pFile2->uzSize) {\n            result = ((pFile1->uzSize < pFile2->uzSize) ? -1 : 1);\n         }\n         break;\n\n      case 2: { // Type - Volume Label's first, then directories, then files\n         int f1 = (pFile1->dwAttributes & ZFILE_ATTRIBUTE_VOLUME)   ? 1 :\n                  (pFile1->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 3;\n         int f2 = (pFile2->dwAttributes & ZFILE_ATTRIBUTE_VOLUME)   ? 1 :\n                  (pFile2->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 2 : 3;\n         if ((f1 == 3) && (f2 == 3)) {\n            CHAR szType1[128];\n            CHAR szType2[128];\n            result = _stricmp(BuildTypeString(pFile1, szType1),\n                              BuildTypeString(pFile2, szType2));\n         } else {\n            result = f1 - f2;\n         }\n         break;\n      }\n\n      case 3: // Modified - Newest to Oldest\n         if (pFile1->dwModified != pFile2->dwModified) {\n            result = ((pFile1->dwModified > pFile2->dwModified) ? -1 : 1);\n         }\n         break;\n\n      case 4: // Attributes - String Sort\n         result = _tcscmp(BuildAttributesString(szBuffer1, pFile1->dwAttributes),\n                          BuildAttributesString(szBuffer2, pFile2->dwAttributes));\n         break;\n\n      case 5: // Compressed Size - Smallest to Largest\n         if (pFile1->uzCompressedSize != pFile2->uzCompressedSize) {\n            result = ((pFile1->uzCompressedSize < pFile2->uzCompressedSize) ? -1 : 1);\n         }\n         break;\n\n      case 6: // Ratio - Smallest to Largest\n         int factor1, factor2;\n         factor1 = ratio(pFile1->uzSize, pFile1->uzCompressedSize);\n         factor2 = ratio(pFile2->uzSize, pFile2->uzCompressedSize);\n         result = factor1 - factor2;\n         break;\n\n      case 7: // Method - String Sort\n         result = _stricmp(pFile1->szPathAndMethod + strlen(pFile1->szPathAndMethod) + 1,\n                           pFile2->szPathAndMethod + strlen(pFile2->szPathAndMethod) + 1);\n         break;\n\n      case 8: // CRC - Smallest to Largest\n         if (pFile1->dwCRC != pFile2->dwCRC) {\n            result = ((pFile1->dwCRC < pFile2->dwCRC) ? -1 : 1);\n         }\n         break;\n\n      case 9: // Comment - String Sort\n         result = _stricmp(pFile1->szComment ? pFile1->szComment : \"\",\n                           pFile2->szComment ? pFile2->szComment : \"\");\n         break;\n   }\n\n   // If the sort resulted in a tie, we use the name to break the tie.\n   if (result == 0) {\n      result = _stricmp(pFile1->szPathAndMethod, pFile2->szPathAndMethod);\n   }\n\n   return result;\n}\n\n\n//******************************************************************************\n//***** Helper/Utility Functions\n//******************************************************************************\n\nvoid SetCaptionText(LPCTSTR szPrefix) {\n   TCHAR szCaption[_MAX_PATH + 32];\n   if (szPrefix) {\n      _stprintf(szCaption, TEXT(\"%s - \"), szPrefix);\n   } else {\n      *szCaption = 0;\n   }\n   if (*g_szZipFile) {\n      size_t lenPrefix = _tcslen(szCaption);\n      MBSTOTSTR(szCaption + lenPrefix, GetFileFromPath(g_szZipFile),\n                countof(szCaption) - lenPrefix);\n   } else {\n      _tcscat(szCaption, TEXT(\"Pocket UnZip\"));\n   }\n   SetWindowText(g_hWndMain, szCaption);\n}\n\n//******************************************************************************\nvoid DrawBanner(HDC hdc) {\n\n   // If we were not passed in a DC, then get one now.\n   BOOL fReleaseDC = FALSE;\n   if (!hdc) {\n      hdc = GetDC(g_hWndMain);\n      fReleaseDC = TRUE;\n   }\n\n   // Compute the banner rectangle.\n   RECT rc;\n   GetClientRect(g_hWndMain, &rc);\n   rc.top += g_cyCmdBar;\n   rc.bottom = rc.top + 22;\n\n   // Fill in the background with a light grey brush.\n   FillRect(hdc, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));\n\n   // Draw a highlight line across the top of our banner.\n   POINT pt[2] = { { rc.left, rc.top + 1 }, { rc.right, rc.top + 1 } };\n\n   SelectObject(hdc, GetStockObject(WHITE_PEN));\n   Polyline(hdc, pt, 2);\n\n   // Get the ZIP file image.  We do this only once and cache the result.\n   // Note that you do not need to free icons as they are a resource.\n   static HICON hIcon = NULL;\n   if (!hIcon) {\n      hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ZIPFILE),\n                               IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);\n   }\n\n   // Draw the ZIP file image.\n   DrawIconEx(hdc, rc.left + 6, rc.top + 3, hIcon, 16, 16, 0, NULL, DI_NORMAL);\n\n   // Set our font and colors.\n   HFONT hFontStock = (HFONT)SelectObject(hdc, g_hFontBanner);\n   SetTextColor(hdc, RGB(0, 0, 0));\n   SetBkMode(hdc, TRANSPARENT);\n\n   rc.left   += 26;\n   rc.right  -= 48;\n   rc.bottom -=  2;\n\n   // Decide what text to display.\n   TCHAR szPath[_MAX_PATH + 16];\n   if (g_hWndWaitFor) {\n      _tcscpy(szPath, TEXT(\"Initializing...\"));\n   } else if (*g_szZipFile) {\n      if (g_fLoading) {\n#ifdef UNICODE\n         _stprintf(szPath, TEXT(\"Loading %S\"), g_szZipFile);\n#else\n         _stprintf(szPath, TEXT(\"Loading %s\"), g_szZipFile);\n#endif\n      } else {\n         MBSTOTSTR(szPath, g_szZipFile, countof(szPath));\n      }\n   } else {\n      _tcscpy(szPath, TEXT(\"No File Loaded\"));\n   }\n\n   // Draw the banner text.\n   DrawText(hdc, szPath, _tcslen(szPath), &rc,\n            DT_NOPREFIX | DT_SINGLELINE | DT_LEFT | DT_VCENTER);\n\n   // Remove all non stock objects from the DC\n   SelectObject(hdc, hFontStock);\n\n   // Free our DC if we created it.\n   if (fReleaseDC) {\n      ReleaseDC(g_hWndMain, hdc);\n   }\n}\n\n//******************************************************************************\nvoid AddDeleteColumns() {\n\n   static int curColumns = 0;\n   int column, newColumns = (g_fExpandedView ? countof(g_columns) : 4);\n\n   // Are we adding columns?\n   if (newColumns > curColumns) {\n\n      // Set up column structure.\n      TCHAR szColumn[32];\n      LV_COLUMN lvc;\n      lvc.mask = LVCF_TEXT | LVCF_FMT;\n      lvc.pszText = szColumn;\n\n      // Loop through each column we need to add.\n      for (column = curColumns; column < newColumns; column++) {\n\n         // Build the real column string.\n         _stprintf(szColumn, (g_columns[column].format == LVCFMT_LEFT) ?\n                   TEXT(\"%s   \") : TEXT(\"   %s\"), g_columns[column].szName);\n\n         // Insert the column with the correct format.\n         lvc.fmt = g_columns[column].format;\n         ListView_InsertColumn(g_hWndList, column, &lvc);\n      }\n\n   // Otherwise, we are removing columns.\n   } else {\n\n      // Loop through each column we need to delete and delete them.\n      for (column = curColumns - 1; column >= newColumns; column--) {\n         ListView_DeleteColumn(g_hWndList, column);\n      }\n   }\n\n   // Store our new column count statically to help us with the next call to\n   // AddDeleteColumns().\n   curColumns = newColumns;\n\n   // Re-calcualte our column widths.\n   ResizeColumns();\n}\n\n//******************************************************************************\nvoid ResizeColumns() {\n\n   // Hide the window since we are going to be doing some column shifting.\n   ShowWindow(g_hWndList, SW_HIDE);\n\n   // Resize all the columns to best fit both the column data and the header.\n   for (int column = 0; column < countof(g_columns); column++) {\n      ListView_SetColumnWidth(g_hWndList, column, LVSCW_AUTOSIZE_USEHEADER);\n   }\n\n   // Show the window again.\n   ShowWindow(g_hWndList, SW_SHOW);\n}\n\n//******************************************************************************\nLPCTSTR GetZipErrorString(int error) {\n\n   switch (error) {\n\n      case PK_OK: // no error\n         return TEXT(\"Operation completed successfully.\");\n\n      case PK_WARN: // warning error\n         return TEXT(\"There were warnings during the operation.\");\n\n      case PK_ERR:    // error in zipfile\n      case PK_BADERR: // severe error in zipfile\n         return TEXT(\"The operation could not be successfully completed.  \")\n                TEXT(\"Possible causes are that the ZIP file contains errors, \")\n                TEXT(\"or that an error occurred while trying to create a \")\n                TEXT(\"directory or file.\");\n\n      case PK_MEM:  // insufficient memory\n      case PK_MEM2: // insufficient memory\n      case PK_MEM3: // insufficient memory\n      case PK_MEM4: // insufficient memory\n      case PK_MEM5: // insufficient memory\n         return TEXT(\"There is not enough memory to perform the operation.  \")\n                TEXT(\"Try closing other running applications or adjust your \")\n                TEXT(\"memory configuration.\");\n\n      case PK_NOZIP: // zipfile not found or corrupt.\n         return TEXT(\"The ZIP file either contains errors or could not be found.\");\n\n      case PK_PARAM: // bad or illegal parameters specified\n         break; // Not used in the Windows CE port.\n\n      case PK_FIND: // no files found in ZIP file\n         return TEXT(\"The ZIP file contains errors that prevented the \")\n                TEXT(\"operation from completing successfully.  A possible \")\n                TEXT(\"cause is that one or more of the files listed as being \")\n                TEXT(\"in the ZIP file could not actually be found within the \")\n                TEXT(\"ZIP file itself.\");\n\n      case PK_DISK: // disk full or file locked\n         return TEXT(\"An error occurred while attempting to save a file.  \")\n                TEXT(\"Possible causes are that your file storage is full or \")\n                TEXT(\"read only, or that a file with the same name already \")\n                TEXT(\"exists and is locked by another application.\");\n\n      case PK_EOF: // unexpected end of file\n         return TEXT(\"The ZIP file contains errors that prevented the \")\n                TEXT(\"operation from completing successfully.  A possible \")\n                TEXT(\"cause is that your ZIP file is incomplete and might be \")\n                TEXT(\"truncated.\");\n\n      case IZ_UNSUP:  // no files found: all unsup. compr/encrypt.\n         return TEXT(\"None of the files could be processed because they were \")\n                TEXT(\"all compressed using an unsupported compression or \")\n                TEXT(\"encryption algorithm.\");\n\n      case IZ_BADPWD: // no files found: all had bad password.\n         return TEXT(\"None of the files could be processed because all the \")\n                TEXT(\"password(s) specified were incorrect.\");\n\n      case PK_EXCEPTION: // exception occurred\n         return TEXT(\"An internal error occurred.  Possible causes are that \")\n                TEXT(\"you are out of memory, you are out of file storage \")\n                TEXT(\"space, the ZIP file contains unexpected errors, or there \")\n                TEXT(\"is a bug in our program (that's why it's free).\");\n\n      case IZ_CTRLC:  // canceled by user's interaction\n      case PK_ABORTED: // user aborted\n         return TEXT(\"The operation was aborted.\");\n   }\n\n   return TEXT(\"An unknown error occurred while processing the ZIP file.\");\n}\n\n//******************************************************************************\nvoid AddFileToListView(FILE_NODE *pFile) {\n\n   // Set up our List View Item structure.\n   LV_ITEM lvi;\n   ZeroMemory(&lvi, sizeof(lvi));\n   lvi.mask    = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;\n   lvi.pszText = LPSTR_TEXTCALLBACK;\n   lvi.lParam  = (LPARAM)pFile;\n   lvi.iImage  = IMAGE_GENERIC;\n\n   // Special case Volume Labels.\n   if (pFile->dwAttributes & ZFILE_ATTRIBUTE_VOLUME) {\n      pFile->szType = \"Volume Label\";\n      lvi.iImage = IMAGE_VOLUME;\n\n   // Special case folders.\n   } else if (pFile->dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n      pFile->szType = \"Folder\";\n      lvi.iImage = IMAGE_FOLDER;\n\n   // Do a lookup on the file extension.\n   } else {\n\n      // Locate the file portion of our path.\n      LPCSTR pszFile = GetFileFromPath(pFile->szPathAndMethod);\n\n      // Find the extension portion of our file.\n      LPCSTR pszExt = MBSRCHR(pszFile, '.');\n\n      // Search our known extension list for this extension.\n      if (pszExt && *(pszExt + 1)) {\n\n         // Loop through our linked list\n         for (FILE_TYPE_NODE *pft = g_pftHead; pft; pft = pft->pNext) {\n\n            // Check for a match.\n            if (!_stricmp(pszExt + 1, pft->szExtAndDesc)) {\n\n               // We found a match, store the image and type string and exit loop.\n               lvi.iImage = pft->image;\n               pFile->szType = pft->szExtAndDesc + strlen(pft->szExtAndDesc) + 1;\n               if (!*pFile->szType) {\n                  pFile->szType = NULL;\n               }\n               break;\n            }\n         }\n      }\n   }\n\n   // Add the item to our list.\n   ListView_InsertItem(g_hWndList, &lvi);\n}\n\n//******************************************************************************\nvoid EnableAllMenuItems(UINT uMenuItem, BOOL fEnabled) {\n#ifdef _WIN32_WCE\n   HMENU hMenu = CommandBar_GetMenu(g_hWndCmdBar, 0);\n#else\n   HMENU hMenu = GetMenu(g_hWndMain);\n#endif\n   EnableMenuItem(hMenu, uMenuItem, fEnabled ? MF_ENABLED : MF_GRAYED);\n   SendMessage(g_hWndCmdBar, TB_ENABLEBUTTON, uMenuItem, MAKELONG(fEnabled, 0));\n}\n\n//******************************************************************************\nvoid CheckAllMenuItems(UINT uMenuItem, BOOL fChecked) {\n#ifdef _WIN32_WCE\n   HMENU hMenu = CommandBar_GetMenu(g_hWndCmdBar, 0);\n#else\n   HMENU hMenu = GetMenu(g_hWndMain);\n#endif\n   CheckMenuItem(hMenu, uMenuItem, fChecked ? MF_CHECKED : MF_UNCHECKED);\n   SendMessage(g_hWndCmdBar, TB_PRESSBUTTON, uMenuItem, MAKELONG(fChecked, 0));\n}\n\n//******************************************************************************\nvoid CenterWindow(HWND hWnd) {\n\n   RECT rc, rcParent;\n\n   // Get our window rectangle.\n   GetWindowRect(hWnd, &rc);\n\n   // Get our parent's window rectangle.\n   GetWindowRect(GetParent(hWnd), &rcParent);\n\n   // Center our window over our parent's window.\n   SetWindowPos(hWnd, NULL,\n      rcParent.left + ((rcParent.right  - rcParent.left) - (rc.right  - rc.left)) / 2,\n      rcParent.top  + ((rcParent.bottom - rcParent.top ) - (rc.bottom - rc.top )) / 2,\n      0, 0, SWP_NOZORDER | SWP_NOSIZE);\n}\n\n//******************************************************************************\nvoid AddTextToEdit(LPCSTR szText) {\n\n   if (!g_hWndEdit) {\n      return;\n   }\n\n   // Add the characters one by one to our edit box while performing the\n   // the following newline conversions:\n   //    Single CR -> CR/LF\n   //    Single LF -> CR/LF\n   //    CR and LF -> CR/LF\n   //    LF and CR -> CR/LF\n   //    0 - 31    -> ^char\n\n   TCHAR szOut[256], *pszOut = szOut;\n   CHAR *pszIn = (LPSTR)szText, cPrev = '\\0';\n\n   while (*pszIn) {\n\n      if (*pszIn == '\\n') {\n         if (cPrev == '\\r') {\n            cPrev = '\\0';\n         } else {\n            *(pszOut++) = TEXT('\\r');\n            *(pszOut++) = TEXT('\\n');\n            cPrev = '\\n';\n         }\n\n      } else if (*pszIn == '\\r') {\n         if (cPrev == '\\n') {\n            cPrev = '\\0';\n         } else {\n            *(pszOut++) = TEXT('\\r');\n            *(pszOut++) = TEXT('\\n');\n            cPrev = '\\r';\n         }\n\n      } else if ((*pszIn < 32) && (*pszIn != '\\t')) {\n         *(pszOut++) = (TCHAR)'^';\n         *(pszOut++) = (TCHAR)(64 + *pszIn);\n         cPrev = *pszIn;\n\n      } else {\n         *(pszOut++) = (TCHAR)*pszIn;\n         cPrev = *pszIn;\n      }\n      pszIn++;\n\n      // If our out buffer is full, then dump it to the edit box.\n      if ((pszOut - szOut) > 253) {\n         *pszOut = TEXT('\\0');\n         SendMessage(g_hWndEdit, EM_SETSEL, -1, -1);\n         SendMessage(g_hWndEdit, EM_REPLACESEL, FALSE, (LPARAM)szOut);\n         pszOut = szOut;\n      }\n   }\n\n   // One final flush of any partially full out buffer.\n   if (pszOut > szOut) {\n      *pszOut = TEXT('\\0');\n      SendMessage(g_hWndEdit, EM_SETSEL, -1, -1);\n      SendMessage(g_hWndEdit, EM_REPLACESEL, FALSE, (LPARAM)szOut);\n   }\n}\n\n//******************************************************************************\nLPTSTR FormatValue(LPTSTR szValue, zusz_t uzValue) {\n#ifdef ZIP64_SUPPORT\n    DWORD dw = 0, dwGroup[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };\n#else\n    DWORD dw = 0, dwGroup[4] = { 0, 0, 0, 0 };\n#endif\n   while (uzValue) {\n      dwGroup[dw++] = (DWORD)(uzValue % 1000);\n      uzValue /= 1000;\n   }\n   switch (dw) {\n      case 2:  _stprintf(szValue, TEXT(\"%u,%03u\"), dwGroup[1], dwGroup[0]); break;\n      case 3:  _stprintf(szValue, TEXT(\"%u,%03u,%03u\"), dwGroup[2], dwGroup[1], dwGroup[0]); break;\n      case 4:  _stprintf(szValue, TEXT(\"%u,%03u,%03u,%03u\"), dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]); break;\n#ifdef ZIP64_SUPPORT\n      case 5:\n          _stprintf(szValue, TEXT(\"%u,%03u,%03u,%03u,%03u\"),\n                    dwGroup[4], dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]);\n          break;\n      case 6:\n          _stprintf(szValue, TEXT(\"%u,%03u,%03u,%03u,%03u,%03u\"), dwGroup[5],\n                    dwGroup[4], dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]);\n          break;\n      case 7:\n          _stprintf(szValue, TEXT(\"%u,%03u,%03u,%03u,%03u,%03u,%03u\"), dwGroup[6], dwGroup[5],\n                    dwGroup[4], dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]);\n          break;\n      case 8:\n          _stprintf(szValue, TEXT(\"%u,%03u,%03u,%03u,%03u,%03u,%03u,%03u\"), dwGroup[7], dwGroup[6], dwGroup[5],\n                    dwGroup[4], dwGroup[3], dwGroup[2], dwGroup[1], dwGroup[0]);\n#endif\n      default: _stprintf(szValue, TEXT(\"%u\"), dwGroup[0]);\n   }\n   return szValue;\n}\n\n//******************************************************************************\nLPTSTR BuildAttributesString(LPTSTR szBuffer, DWORD dwAttributes) {\n   // Build the attribute string according to the flags specified for this file.\n   _stprintf(szBuffer, TEXT(\"%s%s%s%s%s%s%s%s\"),\n             (dwAttributes & ZFILE_ATTRIBUTE_VOLUME)    ? TEXT(\"V\") : TEXT(\"\"),\n             (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)  ? TEXT(\"D\") : TEXT(\"\"),\n             (dwAttributes & FILE_ATTRIBUTE_READONLY)   ? TEXT(\"R\") : TEXT(\"\"),\n             (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)    ? TEXT(\"A\") : TEXT(\"\"),\n             (dwAttributes & FILE_ATTRIBUTE_HIDDEN)     ? TEXT(\"H\") : TEXT(\"\"),\n             (dwAttributes & FILE_ATTRIBUTE_SYSTEM)     ? TEXT(\"S\") : TEXT(\"\"),\n             (dwAttributes & ZFILE_ATTRIBUTE_ENCRYPTED) ? TEXT(\"E\") : TEXT(\"\"),\n             (dwAttributes & ZFILE_ATTRIBUTE_COMMENT)   ? TEXT(\"C\") : TEXT(\"\"));\n   return szBuffer;\n}\n\n//******************************************************************************\nLPCSTR BuildTypeString(FILE_NODE *pFile, LPSTR szType) {\n\n   // First check to see if we have a known description.\n   if (pFile->szType) {\n      return pFile->szType;\n   }\n\n   // Locate the file portion of our path.\n   LPCSTR pszFile = GetFileFromPath(pFile->szPathAndMethod);\n\n   // Get the extension portion of the file.\n   LPCSTR pszExt = MBSRCHR(pszFile, '.');\n\n   // If we have an extension create a type name for this file.\n   if (pszExt && *(pszExt + 1)) {\n      strcpy(szType, pszExt + 1);\n      _strupr(szType);\n      strcat(szType, \" File\");\n      return szType;\n   }\n\n   // If no extension, then use the default \"File\".\n   return \"File\";\n}\n\n//******************************************************************************\nLPCSTR GetFileFromPath(LPCSTR szPath) {\n   LPCSTR p1 = MBSRCHR(szPath, '/'), p2 = MBSRCHR(szPath, '\\\\');\n   if (p1 && (p1 > p2)) {\n      return p1 + 1;\n   } else if (p2) {\n      return p2 + 1;\n   }\n   return szPath;\n}\n\n//******************************************************************************\nvoid ForwardSlashesToBackSlashesA(LPSTR szBuffer) {\n   while (*szBuffer) {\n      if (*szBuffer == '/') {\n         *szBuffer = '\\\\';\n      }\n      INCSTR(szBuffer);\n   }\n}\n\n//******************************************************************************\nvoid ForwardSlashesToBackSlashesW(LPWSTR szBuffer) {\n   while (*szBuffer) {\n      if (*szBuffer == L'/') {\n         *szBuffer = L'\\\\';\n      }\n      szBuffer++;\n   }\n}\n\n//******************************************************************************\nvoid DeleteDirectory(LPTSTR szPath) {\n\n   // Make note to where the end of our path is.\n   LPTSTR szEnd = szPath + _tcslen(szPath);\n\n   // Add our search spec to the path.\n   _tcscpy(szEnd, TEXT(\"\\\\*.*\"));\n\n   // Start a directory search.\n   WIN32_FIND_DATA w32fd;\n   HANDLE hFind = FindFirstFile(szPath, &w32fd);\n\n   // Loop through all entries in this directory.\n   if (hFind != INVALID_HANDLE_VALUE) {\n\n      do {\n         // Append the file/directory name to the path.\n         _tcscpy(szEnd + 1, w32fd.cFileName);\n\n         // Check to see if this entry is a subdirectory.\n         if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n\n            // Ignore current directory (.) and previous directory (..)\n            if (_tcscmp(w32fd.cFileName, TEXT(\".\"))   &&\n                _tcscmp(w32fd.cFileName, TEXT(\"..\")))\n            {\n               // Recurse into DeleteDirectory() to delete subdirectory.\n               DeleteDirectory(szPath);\n            }\n\n         // Otherwise, it must be a file.\n         } else {\n\n            // If the file is marked as read-only, then change to read/write.\n            if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\n               SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);\n            }\n\n            // Attempt to delete the file.  If we fail and the file used to be\n            // read-only, then set the read-only bit back on it.\n            if (!DeleteFile(szPath) &&\n                (w32fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY))\n            {\n               SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);\n            }\n         }\n\n      // Get the next directory entry.\n      } while (FindNextFile(hFind, &w32fd));\n\n      // Close the directory search.\n      FindClose(hFind);\n   }\n\n   // Remove the directory.\n   *szEnd = TEXT('\\0');\n   RemoveDirectory(szPath);\n}\n\n\n//******************************************************************************\n//***** Registry Functions\n//******************************************************************************\n\nvoid RegWriteKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPCTSTR szValue) {\n   HKEY  hKey = NULL;\n   DWORD dwDisposition;\n\n   if (RegCreateKeyEx(hKeyRoot, szSubKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) {\n      if (szValue) {\n         RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szValue,\n                       sizeof(TCHAR) * (_tcslen(szValue) + 1));\n      }\n      RegCloseKey(hKey);\n   }\n}\n\n//******************************************************************************\nBOOL RegReadKey(HKEY hKeyRoot, LPCTSTR szSubKey, LPTSTR szValue, DWORD cBytes) {\n   *szValue = TEXT('\\0');\n   HKEY hKey = NULL;\n   LRESULT lResult = -1;\n\n   if (RegOpenKeyEx(hKeyRoot, szSubKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\n      lResult = RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)szValue, &cBytes);\n      RegCloseKey(hKey);\n   }\n   return ((lResult == ERROR_SUCCESS) && *szValue);\n}\n\n//******************************************************************************\nvoid WriteOptionString(LPCTSTR szOption, LPCTSTR szValue) {\n   HKEY hKey = NULL;\n\n   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {\n      RegSetValueEx(hKey, szOption, 0, REG_SZ, (LPBYTE)szValue,\n                    sizeof(TCHAR) * (_tcslen(szValue) + 1));\n      RegCloseKey(hKey);\n   }\n}\n\n//******************************************************************************\nvoid WriteOptionInt(LPCTSTR szOption, DWORD dwValue) {\n   HKEY hKey = NULL;\n\n   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {\n      RegSetValueEx(hKey, szOption, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\n      RegCloseKey(hKey);\n   }\n}\n\n//******************************************************************************\nLPTSTR GetOptionString(LPCTSTR szOption, LPCTSTR szDefault, LPTSTR szValue, DWORD nSize) {\n   HKEY hKey = NULL;\n   LONG lResult = -1;\n\n   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\n      lResult = RegQueryValueEx(hKey, szOption, NULL, NULL, (LPBYTE)szValue, &nSize);\n      RegCloseKey(hKey);\n   }\n   if (lResult != ERROR_SUCCESS) {\n      _tcscpy(szValue, szDefault);\n   }\n   return szValue;\n}\n\n//******************************************************************************\nDWORD GetOptionInt(LPCTSTR szOption, DWORD dwDefault) {\n   HKEY  hKey = NULL;\n   LONG  lResult = -1;\n   DWORD dwValue;\n   DWORD nSize = sizeof(dwValue);\n\n   if (RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {\n      lResult = RegQueryValueEx(hKey, szOption, NULL, NULL, (LPBYTE)&dwValue, &nSize);\n      RegCloseKey(hKey);\n   }\n   return (lResult == ERROR_SUCCESS) ? dwValue : dwDefault;\n}\n\n//******************************************************************************\n//***** EDIT Control Subclass Functions\n//******************************************************************************\n\nvoid DisableEditing(HWND hWndEdit) {\n\n   // Make sure the control does not have ES_READONLY or ES_WANTRETURN styles.\n   DWORD dwStyle = (DWORD)GetWindowLong(hWndEdit, GWL_STYLE);\n   if (dwStyle & (ES_READONLY | ES_WANTRETURN)) {\n      SetWindowLong(hWndEdit, GWL_STYLE, dwStyle & ~(ES_READONLY | ES_WANTRETURN));\n   }\n\n   // Subclass the control so we can intercept certain keys.\n   g_wpEdit = (WNDPROC)GetWindowLong(hWndEdit, GWL_WNDPROC);\n   SetWindowLong(hWndEdit, GWL_WNDPROC, (LONG)EditSubclassProc);\n}\n\n//******************************************************************************\nLRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   BOOL fCtrl, fShift;\n\n   switch (uMsg) {\n      // For cut, paste, delete, and undo, the control post itself a message.\n      // we throw away that message.  This works as a fail-safe in case we miss\n      // some keystroke that causes one of these operations.  This also disables\n      // the context menu on NT from causing one of these actions to occur.\n      case WM_CUT:\n      case WM_PASTE:\n      case WM_CLEAR:\n      case WM_UNDO:\n         MessageBeep(0);\n         return 0;\n\n      // WM_CHAR is used for normal characters. A-Z, numbers, symbols, enter,\n      // backspace, esc, and tab. In does not include del or movement keys.\n      case WM_CHAR:\n         fCtrl  = (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE;\n\n         // We only allow CTRL-C (copy), plain ESC, plain TAB, plain ENTER.\n         if (( fCtrl && (wParam == 3))         ||\n             (!fCtrl && (wParam == VK_ESCAPE)) ||\n             (!fCtrl && (wParam == VK_RETURN)) ||\n             (!fCtrl && (wParam == VK_TAB)))\n         {\n            break;\n         }\n         MessageBeep(0);\n         return 0;\n\n      // WM_KEYDOWN handles del, insert, arrows, pg up/down, home/end.\n      case WM_KEYDOWN:\n         fCtrl  = (GetKeyState(VK_CONTROL) & 0x8000) ? TRUE : FALSE;\n         fShift = (GetKeyState(VK_SHIFT)   & 0x8000) ? TRUE : FALSE;\n\n         // Skip all forms of DELETE, SHIFT-INSERT (paste),\n         // CTRL-RETURN (hard-return), and CTRL-TAB (hard-tab).\n         if ((          (wParam == VK_DELETE)) ||\n             (fShift && (wParam == VK_INSERT)) ||\n             (fCtrl  && (wParam == VK_RETURN)) ||\n             (fCtrl  && (wParam == VK_TAB)))\n         {\n            MessageBeep(0);\n            return 0;\n         }\n         break;\n   }\n   return CallWindowProc(g_wpEdit, hWnd, uMsg, wParam, lParam);\n}\n\n\n//******************************************************************************\n//***** MRU Functions\n//******************************************************************************\n\n#ifdef _WIN32_WCE\nint GetMenuString(HMENU hMenu, UINT uIDItem, LPTSTR lpString, int nMaxCount,\n                  UINT uFlag) {\n   MENUITEMINFO mii;\n   ZeroMemory(&mii, sizeof(mii));\n   mii.cbSize = sizeof(mii);\n   mii.fMask = MIIM_TYPE;\n   mii.dwTypeData = lpString;\n   mii.cch = nMaxCount;\n   return (GetMenuItemInfo(hMenu, uIDItem, uFlag == MF_BYPOSITION, &mii) ?\n           mii.cch : 0);\n}\n#endif\n\n//******************************************************************************\nvoid InitializeMRU() {\n\n   TCHAR szMRU[MRU_MAX_FILE][_MAX_PATH + 4], szOption[8];\n   int   i, j;\n\n   // Get our menu handle.\n#ifdef _WIN32_WCE\n   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);\n#else\n   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);\n#endif\n\n   // Read all our current MRUs from the registry.\n   for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {\n\n      // Build option name for current MRU and read from registry.\n      _stprintf(szOption, TEXT(\"MRU%d\"), i+1);\n      GetOptionString(szOption, TEXT(\"\"), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);\n\n      // If this MRU exists, then add it.\n      if (szMRU[i][3]) {\n\n         // Build the accelerator prefix for this menu item.\n         szMRU[i][0] = TEXT('&');\n         szMRU[i][1] = TEXT('1') + j;\n         szMRU[i][2] = TEXT(' ');\n\n         // Add the item to our menu.\n         InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,\n                    szMRU[i]);\n\n         // Increment our actual MRU count.\n         j++;\n      }\n   }\n}\n\n//******************************************************************************\nvoid AddFileToMRU(LPCSTR szFile) {\n\n   TCHAR szMRU[MRU_MAX_FILE + 1][_MAX_PATH + 4], szOption[8];\n   int   i, j;\n\n   // Store the new file in our first MRU index.\n   MBSTOTSTR(&szMRU[0][3], szFile, _MAX_PATH);\n\n   //---------------------------------------------------------------------------\n   // We first read the current MRU list from the registry, merge in our new\n   // file at the top, and then write back to the registry.  The registry merge\n   // is done to allow multiple instances of Pocket UnZip to maintain a global\n   // MRU list independent to this current instance's MRU list.\n   //---------------------------------------------------------------------------\n\n   // Read all our current MRUs from the registry.\n   for (i = 1; i <= MRU_MAX_FILE; i++) {\n\n      // Build option name for current MRU and read from registry.\n      _stprintf(szOption, TEXT(\"MRU%d\"), i);\n      GetOptionString(szOption, TEXT(\"\"), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);\n   }\n\n   // Write our new merged MRU list back to the registry.\n   for (i = 0, j = 0; (i <= MRU_MAX_FILE) && (j < MRU_MAX_FILE); i++) {\n\n      // If this MRU exists and is different then our new file, then add it.\n      if ((i == 0) || (szMRU[i][3] && _tcsicmp(&szMRU[0][3], &szMRU[i][3]))) {\n\n         // Build option name for current MRU and write to registry.\n         _stprintf(szOption, TEXT(\"MRU%d\"), ++j);\n         WriteOptionString(szOption, &szMRU[i][3]);\n      }\n   }\n\n   //---------------------------------------------------------------------------\n   // The next thing we need to do is read our local MRU from our File menu,\n   // merge in our new file, and store the new list back to our File menu.\n   //---------------------------------------------------------------------------\n\n   // Get our menu handle.\n#ifdef _WIN32_WCE\n   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);\n#else\n   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);\n#endif\n\n   // Read all our current MRUs from our File Menu.\n   for (i = 1; i <= MRU_MAX_FILE; i++) {\n\n      // Query our file Menu for a MRU file.\n      if (GetMenuString(hMenu, MRU_START_ID + i - 1, szMRU[i],\n                        countof(szMRU[0]), MF_BYCOMMAND))\n      {\n         // Delete this item from the menu for now.\n         DeleteMenu(hMenu, MRU_START_ID + i - 1, MF_BYCOMMAND);\n      } else {\n         szMRU[i][3] = TEXT('\\0');\n      }\n   }\n\n   // Write our new merged MRU list back to the File menu.\n   for (i = 0, j = 0; (i <= MRU_MAX_FILE) && (j < MRU_MAX_FILE); i++) {\n\n      // If this MRU exists and is different then our new file, then add it.\n      if ((i == 0) || (szMRU[i][3] && _tcsicmp(&szMRU[0][3], &szMRU[i][3]))) {\n\n         // Build the accelerator prefix for this menu item.\n         szMRU[i][0] = TEXT('&');\n         szMRU[i][1] = TEXT('1') + j;\n         szMRU[i][2] = TEXT(' ');\n\n         // Add the item to our menu.\n         InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,\n                    szMRU[i]);\n\n         // Increment our actual MRU count.\n         j++;\n      }\n   }\n}\n\n//******************************************************************************\nvoid RemoveFileFromMRU(LPCTSTR szFile) {\n\n   TCHAR szMRU[MRU_MAX_FILE][_MAX_PATH + 4], szOption[8];\n   int   i, j;\n   BOOL  fFound;\n\n   //---------------------------------------------------------------------------\n   // We first look for this file in our global MRU stored in the registry.  We\n   // read the current MRU list from the registry, and then write it back while\n   // removing all occurrances of the file specified.\n   //---------------------------------------------------------------------------\n\n   // Read all our current MRUs from the registry.\n   for (i = 0, fFound = FALSE; i < MRU_MAX_FILE; i++) {\n\n      // Build option name for current MRU and read from registry.\n      _stprintf(szOption, TEXT(\"MRU%d\"), i+1);\n      GetOptionString(szOption, TEXT(\"\"), &szMRU[i][3], sizeof(TCHAR) * _MAX_PATH);\n\n      // Check for a match.\n      if (!_tcsicmp(szFile, &szMRU[i][3])) {\n         szMRU[i][3] = TEXT('\\0');\n         fFound = TRUE;\n      }\n   }\n\n   // Only write the MRU back to the registry if we found a file to remove.\n   if (fFound) {\n\n      // Write the updated MRU list back to the registry.\n      for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {\n\n         // If this MRU still exists, then add it.\n         if (szMRU[i][3]) {\n\n            // Build option name for current MRU and write to registry.\n            _stprintf(szOption, TEXT(\"MRU%d\"), ++j);\n            WriteOptionString(szOption, &szMRU[i][3]);\n         }\n      }\n\n      // If our list got smaller, clear the unused items in the registry.\n      while (j++ < MRU_MAX_FILE) {\n         _stprintf(szOption, TEXT(\"MRU%d\"), j);\n         WriteOptionString(szOption, TEXT(\"\"));\n      }\n   }\n\n   //---------------------------------------------------------------------------\n   // We next thing we do is look for this file in our local MRU stored in our\n   // File menu.  We read the current MRU list from the menu, and then write it\n   // back while removing all occurrances of the file specified.\n   //---------------------------------------------------------------------------\n\n   // Get our menu handle.\n#ifdef _WIN32_WCE\n   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);\n#else\n   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);\n#endif\n\n   // Read all our current MRUs from our File Menu.\n   for (i = 0, fFound = FALSE; i < MRU_MAX_FILE; i++) {\n\n      // Query our file Menu for a MRU file.\n      if (!GetMenuString(hMenu, MRU_START_ID + i, szMRU[i], countof(szMRU[0]),\n          MF_BYCOMMAND))\n      {\n         szMRU[i][3] = TEXT('\\0');\n      }\n\n      // Check for a match.\n      if (!_tcsicmp(szFile, &szMRU[i][3])) {\n         szMRU[i][3] = TEXT('\\0');\n         fFound = TRUE;\n      }\n   }\n\n   // Only update menu if we found a file to remove.\n   if (fFound) {\n\n      // Clear out our menu's MRU list.\n      for (i = MRU_START_ID; i < (MRU_START_ID + MRU_MAX_FILE); i++) {\n         DeleteMenu(hMenu, i, MF_BYCOMMAND);\n      }\n\n      // Write the rest of our MRU list back to the menu.\n      for (i = 0, j = 0; i < MRU_MAX_FILE; i++) {\n\n         // If this MRU still exists, then add it.\n         if (szMRU[i][3]) {\n\n            // Build the accelerator prefix for this menu item.\n            szMRU[i][0] = TEXT('&');\n            szMRU[i][1] = TEXT('1') + j;\n            szMRU[i][2] = TEXT(' ');\n\n            // Add the item to our menu.\n            InsertMenu(hMenu, 4 + j, MF_BYPOSITION | MF_STRING, MRU_START_ID + j,\n                       szMRU[i]);\n\n            // Increment our actual MRU count.\n            j++;\n         }\n      }\n   }\n}\n\n//******************************************************************************\nvoid ActivateMRU(UINT uIDItem) {\n   TCHAR szFile[_MAX_PATH + 4];\n\n   // Get our menu handle.\n#ifdef _WIN32_WCE\n   HMENU hMenu = GetSubMenu(CommandBar_GetMenu(g_hWndCmdBar, 0), 0);\n#else\n   HMENU hMenu = GetSubMenu(GetMenu(g_hWndMain), 0);\n#endif\n\n   // Query our menu for the selected MRU.\n   if (GetMenuString(hMenu, uIDItem, szFile, countof(szFile), MF_BYCOMMAND)) {\n\n      // Move past 3 character accelerator prefix and open the file.\n      ReadZipFileList(&szFile[3]);\n   }\n}\n\n\n//******************************************************************************\n//***** Open Zip File Functions\n//******************************************************************************\n\nvoid ReadZipFileList(LPCTSTR wszPath) {\n\n   // Show wait cursor.\n   HCURSOR hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));\n\n   TSTRTOMBS(g_szZipFile, wszPath, countof(g_szZipFile));\n\n   // Update our banner to show that we are loading.\n   g_fLoading = TRUE;\n   DrawBanner(NULL);\n\n   // Update our caption to show that we are loading.\n   SetCaptionText(TEXT(\"Loading\"));\n\n   // Clear our list view.\n   ListView_DeleteAllItems(g_hWndList);\n\n   // Ghost all our Unzip related menu items.\n   EnableAllMenuItems(IDM_FILE_PROPERTIES,    FALSE);\n   EnableAllMenuItems(IDM_ACTION_EXTRACT,     FALSE);\n   EnableAllMenuItems(IDM_ACTION_EXTRACT_ALL, FALSE);\n   EnableAllMenuItems(IDM_ACTION_TEST,        FALSE);\n   EnableAllMenuItems(IDM_ACTION_TEST_ALL,    FALSE);\n   EnableAllMenuItems(IDM_ACTION_VIEW,        FALSE);\n   EnableAllMenuItems(IDM_ACTION_SELECT_ALL,  FALSE);\n   EnableAllMenuItems(IDM_VIEW_COMMENT,       FALSE);\n\n   // Let Info-ZIP and our callbacks do the work.\n   SendMessage(g_hWndList, WM_SETREDRAW, FALSE, 0);\n   int result = DoListFiles(g_szZipFile);\n   SendMessage(g_hWndList, WM_SETREDRAW, TRUE, 0);\n\n   // Restore/remove cursor.\n   SetCursor(hCur);\n\n   // Update our column widths\n   ResizeColumns();\n\n   if ((result == PK_OK) || (result == PK_WARN)) {\n\n      // Sort the items by name.\n      Sort(0, TRUE);\n\n      // Update this file to our MRU list and menu.\n      AddFileToMRU(g_szZipFile);\n\n      // Enabled the comment button if the zip file has a comment.\n      if (lpUserFunctions->cchComment) {\n         EnableAllMenuItems(IDM_VIEW_COMMENT, TRUE);\n      }\n\n      // Update other items that are related to having a Zip file loaded.\n      EnableAllMenuItems(IDM_ACTION_EXTRACT_ALL, TRUE);\n      EnableAllMenuItems(IDM_ACTION_TEST_ALL,    TRUE);\n      EnableAllMenuItems(IDM_ACTION_SELECT_ALL,  TRUE);\n\n   } else {\n\n      // Make sure we didn't partially load and added a few files.\n      ListView_DeleteAllItems(g_hWndList);\n\n      // If the file itself is bad or missing, then remove it from our MRU.\n      if ((result == PK_ERR) || (result == PK_BADERR) || (result == PK_NOZIP) ||\n          (result == PK_FIND) || (result == PK_EOF))\n      {\n         RemoveFileFromMRU(wszPath);\n      }\n\n      // Display an error.\n      TCHAR szError[_MAX_PATH + 128];\n      _stprintf(szError, TEXT(\"Failure loading \\\"%s\\\".\\n\\n\"), wszPath);\n      _tcscat(szError, GetZipErrorString(result));\n      MessageBox(g_hWndMain, szError, g_szAppName, MB_OK | MB_ICONERROR);\n\n      // Clear our file status.\n      *g_szZipFile = '\\0';\n   }\n\n   // Update our caption to show that we are done loading.\n   SetCaptionText(NULL);\n\n   // Update our banner to show that we are done loading.\n   g_fLoading = FALSE;\n   DrawBanner(NULL);\n}\n\n\n//******************************************************************************\n//***** Zip File Properties Dialog Functions\n//******************************************************************************\n\nBOOL CALLBACK DlgProcProperties(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG: {\n\n         // Add \"General\" and \"Comments\" tabs to tab control.  We are using a\n         // poor man's version of a property sheet.  We display our 2 pages\n         // by showing and hiding controls as necessary.  For our purposes,\n         // this is much easier than dealing with separate property pages.\n\n         TC_ITEM tci;\n         tci.mask = TCIF_TEXT;\n         tci.pszText = TEXT(\"General\");\n         TabCtrl_InsertItem(GetDlgItem(hDlg, IDC_TAB), 0, &tci);\n         tci.pszText = TEXT(\"Comment\");\n         TabCtrl_InsertItem(GetDlgItem(hDlg, IDC_TAB), 1, &tci);\n\n#ifdef _WIN32_WCE\n         // Add \"Ok\" button to caption bar.\n         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN |\n                       GetWindowLong(hDlg, GWL_EXSTYLE));\n#endif\n         // Center us over our parent.\n         CenterWindow(hDlg);\n\n         int    directory = -1, readOnly = -1, archive = -1, hidden = -1;\n         int    system = -1, encrypted = -1;\n         int    year = -1, month = -1, day = -1, hour = -1, minute = -1, pm = -1;\n         zusz_t uzSize = 0, uzCompressedSize = 0;\n         LPCSTR szPath = NULL, szMethod = NULL, szComment = NULL;\n         DWORD  dwCRC = 0, dwCount = 0, dwCommentCount = 0;\n         TCHAR  szBuffer[MAX_PATH];\n\n         // Loop through all selected items.\n         LV_ITEM lvi;\n         ZeroMemory(&lvi, sizeof(lvi));\n         lvi.mask = LVIF_PARAM;\n         lvi.iItem = -1;\n         while ((lvi.iItem = ListView_GetNextItem(g_hWndList, lvi.iItem, LVNI_SELECTED)) != -1) {\n\n            // Get the FILE_NODE for the selected item.\n            ListView_GetItem(g_hWndList, &lvi);\n            FILE_NODE *pFile = (FILE_NODE*)lvi.lParam;\n\n            // Merge this file's attributes into our accumulative attributes.\n            MergeValues(&directory, (pFile->dwAttributes & FILE_ATTRIBUTE_DIRECTORY)  != 0);\n            MergeValues(&readOnly,  (pFile->dwAttributes & FILE_ATTRIBUTE_READONLY)   != 0);\n            MergeValues(&archive,   (pFile->dwAttributes & FILE_ATTRIBUTE_ARCHIVE)    != 0);\n            MergeValues(&hidden,    (pFile->dwAttributes & FILE_ATTRIBUTE_HIDDEN)     != 0);\n            MergeValues(&system,    (pFile->dwAttributes & FILE_ATTRIBUTE_SYSTEM)     != 0);\n            MergeValues(&encrypted, (pFile->dwAttributes & ZFILE_ATTRIBUTE_ENCRYPTED) != 0);\n\n            // Merge this file's date/time into our accumulative date/time.\n            int curHour = (pFile->dwModified >> 6) & 0x001F;\n            MergeValues(&year,   (pFile->dwModified >> 20) & 0x0FFF);\n            MergeValues(&month,  (pFile->dwModified >> 16) & 0x000F);\n            MergeValues(&day,    (pFile->dwModified >> 11) & 0x001F);\n            MergeValues(&hour,   (curHour % 12) ? (curHour % 12) : 12);\n            MergeValues(&minute, pFile->dwModified & 0x003F);\n            MergeValues(&pm,     curHour >= 12);\n\n            // Store this file's name.\n            szPath = pFile->szPathAndMethod;\n\n            // Store this file's CRC.\n            dwCRC = pFile->dwCRC;\n\n            // Add the size and compressed size to our accumulative sizes.\n            uzSize += pFile->uzSize;\n            uzCompressedSize += pFile->uzCompressedSize;\n\n            // Merge in our compression method.\n            LPCSTR szCurMethod = pFile->szPathAndMethod + strlen(pFile->szPathAndMethod) + 1;\n            if ((szMethod == NULL) || !strcmp(szMethod, szCurMethod)) {\n               szMethod = szCurMethod;\n            } else {\n               szMethod = \"Multiple Methods\";\n            }\n\n            // Increment our file count.\n            dwCount++;\n\n            // Increment our comment count if this file has a comment.\n            if (pFile->szComment) {\n               szComment = pFile->szComment;\n               dwCommentCount++;\n            }\n         };\n\n         if (dwCount > 1) {\n\n            // If multiple items selected, then display a selected count string\n            // in place of the file name.\n            _stprintf(szBuffer, TEXT(\"%u items selected.\"), dwCount);\n            SetDlgItemText(hDlg, IDC_FILE, szBuffer);\n\n            // Display \"Multiple\" for CRC if multiple items selected.\n            SetDlgItemText(hDlg, IDC_CRC, TEXT(\"Multiple CRCs\"));\n\n         } else {\n\n            // Set the file name text for the single item selected.\n            MBSTOTSTR(szBuffer, szPath, countof(szBuffer));\n            ForwardSlashesToBackSlashes(szBuffer);\n            SetDlgItemText(hDlg, IDC_FILE, szBuffer);\n\n            // Set the CRC text for the single item selected.\n            _stprintf(szBuffer, TEXT(\"0x%08X\"), dwCRC);\n            SetDlgItemText(hDlg, IDC_CRC, szBuffer);\n         }\n\n         // Set the Size tally text.\n         FormatValue(szBuffer, uzSize);\n         _tcscat(szBuffer, (dwCount > 1) ? TEXT(\" bytes total\") : TEXT(\" bytes\"));\n         SetDlgItemText(hDlg, IDC_FILE_SIZE, szBuffer);\n\n         // Set the Compressed Size tally text.\n         FormatValue(szBuffer, uzCompressedSize);\n         _tcscat(szBuffer, (dwCount > 1) ? TEXT(\" bytes total\") : TEXT(\" bytes\"));\n         SetDlgItemText(hDlg, IDC_COMPRESSED_SIZE, szBuffer);\n\n         // Set the Compression Factor text.\n         int factor = ratio(uzSize, uzCompressedSize);\n         _stprintf(szBuffer, TEXT(\"%d.%d%%\"), factor / 10,\n                   ((factor < 0) ? -factor : factor) % 10);\n         SetDlgItemText(hDlg, IDC_COMPRESSON_FACTOR, szBuffer);\n\n         // Set the Compression Method text.\n         MBSTOTSTR(szBuffer, szMethod, countof(szBuffer));\n         SetDlgItemText(hDlg, IDC_COMPRESSION_METHOD, szBuffer);\n\n         // Set the Attribute check boxes.\n         CheckThreeStateBox(hDlg, IDC_DIRECTORY, directory);\n         CheckThreeStateBox(hDlg, IDC_READONLY,  readOnly);\n         CheckThreeStateBox(hDlg, IDC_ARCHIVE,   archive);\n         CheckThreeStateBox(hDlg, IDC_HIDDEN,    hidden);\n         CheckThreeStateBox(hDlg, IDC_SYSTEM,    system);\n         CheckThreeStateBox(hDlg, IDC_ENCRYPTED, encrypted);\n\n         // Build and set the Modified Date text.  The MS compiler does not\n         // consider \"??/\" to be a valid string.  \"??/\" is a trigraph that is\n         // turned into \"\\\" by the preprocessor and causes grief for the compiler.\n         LPTSTR psz = szBuffer;\n         psz += ((month  < 0) ? _stprintf(psz, TEXT(\"?\\?/\")) :\n                                _stprintf(psz, TEXT(\"%u/\"), month));\n         psz += ((day    < 0) ? _stprintf(psz, TEXT(\"?\\?/\")) :\n                                _stprintf(psz, TEXT(\"%u/\"), day));\n         psz += ((year   < 0) ? _stprintf(psz, TEXT(\"?\\? \")) :\n                                _stprintf(psz, TEXT(\"%u \"), year % 100));\n         psz += ((hour   < 0) ? _stprintf(psz, TEXT(\"?\\?:\")) :\n                                _stprintf(psz, TEXT(\"%u:\"), hour));\n         psz += ((minute < 0) ? _stprintf(psz, TEXT(\"?\\? \")) :\n                                _stprintf(psz, TEXT(\"%02u \"), minute));\n         psz += ((pm     < 0) ? _stprintf(psz, TEXT(\"?M\")) :\n                                _stprintf(psz, TEXT(\"%cM\"), pm ? TEXT('P') : TEXT('A')));\n         SetDlgItemText(hDlg, IDC_MODIFIED, szBuffer);\n\n         // Store a global handle to our edit control.\n         g_hWndEdit = GetDlgItem(hDlg, IDC_COMMENT);\n\n         // Disable our edit box from being edited.\n         DisableEditing(g_hWndEdit);\n\n         // Stuff the appropriate message into the Comment edit control.\n         if (dwCommentCount == 0) {\n            if (dwCount == 1) {\n               AddTextToEdit(\"This file does not have a comment.\");\n            } else {\n               AddTextToEdit(\"None of the selected files have a comment.\");\n            }\n         } else if (dwCount == 1) {\n            AddTextToEdit(szComment);\n         } else {\n            CHAR szTemp[64];\n            _stprintf(szBuffer, TEXT(\"%u of the selected files %s a comment.\"),\n                      dwCommentCount, (dwCommentCount == 1)? TEXT(\"has\") : TEXT(\"have\"));\n            TSTRTOMBS(szTemp, szBuffer, countof(szTemp));\n            AddTextToEdit(szTemp);\n         }\n         g_hWndEdit = NULL;\n\n\n         // Whooh, done with WM_INITDIALOG\n         return TRUE;\n      }\n\n      case WM_NOTIFY:\n         // Check to see if tab control was changed to new tab.\n         if (((NMHDR*)lParam)->code == TCN_SELCHANGE) {\n            HWND hWndTab     = ((NMHDR*)lParam)->hwndFrom;\n            HWND hWndComment = GetDlgItem(hDlg, IDC_COMMENT);\n            HWND hWnd        = GetWindow(hDlg, GW_CHILD);\n\n            // If General tab selected, hide comment edit box and show all other controls.\n            if (TabCtrl_GetCurSel(hWndTab) == 0) {\n               while (hWnd) {\n                  ShowWindow(hWnd, ((hWnd == hWndTab) || (hWnd != hWndComment)) ?\n                             SW_SHOW : SW_HIDE);\n                  hWnd = GetWindow(hWnd, GW_HWNDNEXT);\n               }\n\n            // If Comment tab selected, hide all controls except comment edit box.\n            } else {\n               while (hWnd) {\n                  ShowWindow(hWnd, ((hWnd == hWndTab) || (hWnd == hWndComment)) ?\n                             SW_SHOW : SW_HIDE);\n                  hWnd = GetWindow(hWnd, GW_HWNDNEXT);\n               }\n            }\n         }\n         return FALSE;\n\n      case WM_COMMAND:\n         // Exit the dialog on OK (Enter) or CANCEL (Esc).\n         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {\n            EndDialog(hDlg, LOWORD(wParam));\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n//******************************************************************************\nvoid MergeValues(int *p1, int p2) {\n   if ((*p1 == -1) || (*p1 == p2)) {\n      *p1 = p2;\n   } else {\n      *p1 = -2;\n   }\n}\n\n//******************************************************************************\nvoid CheckThreeStateBox(HWND hDlg, int nIDButton, int state) {\n   CheckDlgButton(hDlg, nIDButton, (state == 0) ? BST_UNCHECKED :\n                                   (state == 1) ? BST_CHECKED :\n                                                  BST_INDETERMINATE);\n}\n\n\n//******************************************************************************\n//***** Extract/Test Dialog Functions\n//******************************************************************************\n\nvoid ExtractOrTestFiles(BOOL fExtract) {\n\n   EXTRACT_INFO ei;\n   ZeroMemory(&ei, sizeof(ei));\n\n   // Set our Extract or Test flag.\n   ei.fExtract = fExtract;\n\n   // Get the number of selected items and make sure we have at least one item.\n   if ((ei.dwFileCount = ListView_GetSelectedCount(g_hWndList)) <= 0) {\n      return;\n   }\n\n   // If we are not extracting/testing all, then create and buffer large enough to\n   // hold the file list for all the selected files.\n   if ((int)ei.dwFileCount != ListView_GetItemCount(g_hWndList)) {\n      ei.szFileList = new LPSTR[ei.dwFileCount + 1];\n      if (!ei.szFileList) {\n         MessageBox(g_hWndMain, GetZipErrorString(PK_MEM), g_szAppName,\n                    MB_ICONERROR | MB_OK);\n         return;\n      }\n   }\n\n   ei.dwFileCount = 0;\n   ei.uzByteCount = 0;\n\n   LV_ITEM lvi;\n   ZeroMemory(&lvi, sizeof(lvi));\n   lvi.mask = LVIF_PARAM;\n   lvi.iItem = -1;\n\n   // Walk through all the selected files to build our counts and set our file\n   // list pointers into our FILE_NODE paths for each selected item.\n   while ((lvi.iItem = ListView_GetNextItem(g_hWndList, lvi.iItem, LVNI_SELECTED)) >= 0) {\n      ListView_GetItem(g_hWndList, &lvi);\n      if (ei.szFileList) {\n         ei.szFileList[ei.dwFileCount] = ((FILE_NODE*)lvi.lParam)->szPathAndMethod;\n      }\n      ei.dwFileCount++;\n      ei.uzByteCount += ((FILE_NODE*)lvi.lParam)->uzSize;\n   }\n   if (ei.szFileList) {\n      ei.szFileList[ei.dwFileCount] = NULL;\n   }\n\n   // If we are extracting, display the extract dialog to query for parameters.\n   if (!fExtract || (DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXTRACT), g_hWndMain,\n                                    (DLGPROC)DlgProcExtractOrTest, (LPARAM)&ei) == IDOK))\n   {\n      // Display our progress dialog and do the extraction/test.\n      DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_EXTRACT_PROGRESS), g_hWndMain,\n                     (DLGPROC)DlgProcExtractProgress, (LPARAM)&ei);\n   }\n\n   // Free our file list buffer if we created one.\n   if (ei.szFileList) {\n      delete[] ei.szFileList;\n   }\n}\n\n//******************************************************************************\nBOOL CALLBACK DlgProcExtractOrTest(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   static EXTRACT_INFO *pei;\n   TCHAR  szPath[_MAX_PATH];\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n         // Store our extract information structure.\n         pei = (EXTRACT_INFO*)lParam;\n\n         // Load our settings.\n         pei->fRestorePaths = GetOptionInt(TEXT(\"RestorePaths\"), TRUE);\n         pei->overwriteMode = (OVERWRITE_MODE)GetOptionInt(TEXT(\"OverwriteMode\"), OM_PROMPT);\n\n         // Load and set our path string.\n         GetOptionString(TEXT(\"ExtractToDirectory\"), TEXT(\"\\\\\"), szPath, sizeof(szPath));\n         SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);\n\n         // Set the state of all the controls.\n         SetDlgItemText(hDlg, IDC_FILE_COUNT, FormatValue(szPath, pei->dwFileCount));\n         SetDlgItemText(hDlg, IDC_BYTE_COUNT, FormatValue(szPath, pei->uzByteCount));\n         CheckDlgButton(hDlg, IDC_RESTORE_PATHS, pei->fRestorePaths);\n         CheckDlgButton(hDlg, IDC_OVERWRITE_PROMPT, pei->overwriteMode == OM_PROMPT);\n         CheckDlgButton(hDlg, IDC_OVERWRITE_NEWER,  pei->overwriteMode == OM_NEWER);\n         CheckDlgButton(hDlg, IDC_OVERWRITE_ALWAYS, pei->overwriteMode == OM_ALWAYS);\n         CheckDlgButton(hDlg, IDC_OVERWRITE_NEVER,  pei->overwriteMode == OM_NEVER);\n\n         // Limit our edit control to max path.\n         SendDlgItemMessage(hDlg, IDC_EXTRACT_TO, EM_LIMITTEXT, sizeof(szPath) - 1, 0);\n\n         // Center our dialog.\n         CenterWindow(hDlg);\n         return TRUE;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n\n            case IDOK:\n\n               // Force us to read and validate the extract to directory.\n               SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_EXTRACT_TO, EN_KILLFOCUS), 0);\n\n               // Get our current path string.\n               GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));\n\n               // Verify our \"extract to\" path is valid.\n               if (!SetExtractToDirectory(szPath)) {\n                  MessageBox(hDlg, TEXT(\"The directory you entered is invalid or does not exist.\"),\n                             g_szAppName, MB_ICONERROR | MB_OK);\n                  SetFocus(GetDlgItem(hDlg, IDC_EXTRACT_TO));\n                  return FALSE;\n               }\n\n               // Query other control values.\n               pei->fRestorePaths = IsDlgButtonChecked(hDlg, IDC_RESTORE_PATHS);\n               pei->overwriteMode =\n                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_NEWER)  ? OM_NEWER  :\n                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_ALWAYS) ? OM_ALWAYS :\n                  IsDlgButtonChecked(hDlg, IDC_OVERWRITE_NEVER)  ? OM_NEVER  : OM_PROMPT;\n\n               // Write our settings.\n               WriteOptionInt(TEXT(\"RestorePaths\"), pei->fRestorePaths);\n               WriteOptionInt(TEXT(\"OverwriteMode\"), pei->overwriteMode);\n               WriteOptionString(TEXT(\"ExtractToDirectory\"), szPath);\n\n               // Fall through to IDCANCEL\n\n            case IDCANCEL:\n               EndDialog(hDlg, LOWORD(wParam));\n               return FALSE;\n\n            case IDC_EXTRACT_TO:\n\n               // Make sure the path ends in a wack (\\).\n               if (HIWORD(wParam) == EN_KILLFOCUS) {\n                  GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));\n                  size_t length = _tcslen(szPath);\n                  if ((length == 0) || szPath[length - 1] != TEXT('\\\\')) {\n                     szPath[length    ] = TEXT('\\\\');\n                     szPath[length + 1] = TEXT('\\0');\n                     SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);\n                  }\n               }\n               return FALSE;\n\n            case IDC_BROWSE:\n               GetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath, countof(szPath));\n               if (FolderBrowser(szPath, countof(szPath))) {\n                  SetDlgItemText(hDlg, IDC_EXTRACT_TO, szPath);\n               }\n               return FALSE;\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n\n//******************************************************************************\n//***** Folder Browsing Dialog Functions\n//******************************************************************************\n\nBOOL FolderBrowser(LPTSTR szPath, DWORD dwLength) {\n\n#ifdef _WIN32_WCE\n\n   // On Windows CE, we use a common save-as dialog to query the diretory.  We\n   // display the dialog in this function, and then we sublass it.  Our subclass\n   // functions tweaks the dialog a bit and and returns the path.\n\n   ForwardSlashesToBackSlashes(szPath);\n\n   TCHAR szInitialDir[_MAX_PATH];\n   _tcscpy(szInitialDir, szPath);\n\n   // Remove trailing wacks from path - The common dialog doesn't like them.\n   size_t length = _tcslen(szInitialDir);\n   while ((length > 0) && (szInitialDir[length - 1] == TEXT('\\\\'))) {\n      szInitialDir[--length] = TEXT('\\0');\n   }\n\n   // Set up the parameters for our save-as dialog.\n   OPENFILENAME ofn;\n   ZeroMemory(&ofn, sizeof(ofn));\n   ofn.lStructSize     = sizeof(ofn);\n   ofn.hwndOwner       = g_hWndMain;\n   ofn.hInstance       = g_hInst;\n   ofn.lpstrFilter     = TEXT(\" \\0!\\0\");\n   ofn.nFilterIndex    = 1;\n   ofn.lpstrFile       = szPath;\n   ofn.nMaxFile        = dwLength;\n   ofn.lpstrInitialDir = *szInitialDir ? szInitialDir : NULL;\n   ofn.lpstrTitle      = TEXT(\"Extract To\");\n   ofn.Flags           = OFN_HIDEREADONLY | OFN_NOVALIDATE | OFN_NOTESTFILECREATE;\n\n   // Post a message to our main window telling it that we are about to create\n   // a save as dialog.  Our main window will receive this message after the\n   // save as dialog is created.  This gives us a change to subclass the save as\n   // dialog.\n   PostMessage(g_hWndMain, WM_PRIVATE, MSG_SUBCLASS_DIALOG, 0);\n\n   // Create and display the common save-as dialog.\n   if (GetSaveFileName(&ofn)) {\n\n      // If success, then remove are special \"!\" filename from the end.\n      szPath[_tcslen(szPath) - 1] = TEXT('\\0');\n      return TRUE;\n   }\n   return FALSE;\n\n#else // !_WIN32_WCE\n\n   // On Windows NT, the shell provides us with a nice folder browser dialog.\n   // We don't need to jump through any hoops to make it work like on Windows CE.\n   // The only problem is that on VC 4.0, the libraries don't export the UNICODE\n   // shell APIs because only Win95 had a shell library at the time.  The\n   // following code requires headers and libs from VC 4.2 or later.\n\n   // Set up our BROWSEINFO structure.\n   BROWSEINFO bi;\n   ZeroMemory(&bi, sizeof(bi));\n   bi.hwndOwner = g_hWndMain;\n   bi.pszDisplayName = szPath;\n   bi.lpszTitle = TEXT(\"Extract To\");\n   bi.ulFlags = BIF_RETURNONLYFSDIRS;\n\n   // Prompt user for path.\n   LPITEMIDLIST piidl = SHBrowseForFolder(&bi);\n   if (!piidl) {\n      return FALSE;\n   }\n\n   // Build path string.\n   SHGetPathFromIDList(piidl, szPath);\n\n   // Free the PIDL returned by SHBrowseForFolder.\n   LPMALLOC pMalloc = NULL;\n   SHGetMalloc(&pMalloc);\n   pMalloc->Free(piidl);\n\n   // Add trailing wack if one is not present.\n   size_t length = _tcslen(szPath);\n   if ((length > 0) && (szPath[length - 1] != TEXT('\\\\'))) {\n      szPath[length++] = TEXT('\\\\');\n      szPath[length]   = TEXT('\\0');\n   }\n\n   return TRUE;\n\n#endif // _WIN32_WCE\n}\n\n//******************************************************************************\n#ifdef _WIN32_WCE\nBOOL CALLBACK DlgProcBrowser(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   // This is our subclass of Windows CE's common save-as dialog.  We intercept\n   // the messages we care about and forward everything else to the original\n   // window procedure for the dialog.\n\n   if (uMsg == WM_PRIVATE) { // wParam always equals MSG_INIT_DIALOG\n\n      RECT rc1, rc2;\n\n      // Get the window rectangle for the name edit control.\n      HWND hWnd = GetDlgItem(hDlg, IDC_SAVE_NAME_EDIT);\n      GetWindowRect(hWnd, &rc1);\n      POINT pt1 = { rc1.left, rc1.top };\n      ScreenToClient(hDlg, &pt1);\n\n      // Hide all the windows we don't want.\n      ShowWindow(hWnd, SW_HIDE);\n      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_NAME_PROMPT), SW_HIDE);\n      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_TYPE_PROMPT), SW_HIDE);\n      ShowWindow(GetDlgItem(hDlg, IDC_SAVE_TYPE_LIST), SW_HIDE);\n\n      // Get the window rectangle for the file list.\n      hWnd = GetDlgItem(hDlg, IDC_SAVE_FILE_LIST);\n      GetWindowRect(hWnd, &rc2);\n      POINT pt2 = { rc2.left, rc2.top };\n      ScreenToClient(hDlg, &pt2);\n\n      // Resize the file list to fill the dialog.\n      MoveWindow(hWnd, pt2.x, pt2.y, rc2.right - rc2.left, rc1.bottom - rc2.top, TRUE);\n\n   } else if ((uMsg == WM_COMMAND) && (LOWORD(wParam) == IDOK)) {\n\n      // Get our file list window.\n      HWND hWnd = GetDlgItem(hDlg, IDC_SAVE_FILE_LIST);\n\n      // Check to see if a directory is selected.\n      if (ListView_GetNextItem(hWnd, -1, LVNI_SELECTED) >= 0) {\n\n         // If a directory is highlighted, then we post ourself a \"Ok\".  The \"Ok\"\n         // we are processing now will cause us to change into the highlighted\n         // directory, and our posted \"Ok\" will close the dialog in that directory.\n         PostMessage(hDlg, uMsg, wParam, lParam);\n\n      } else {\n         // If no directory is selected, then enter the imaginary filename \"!\"\n         // into the name edit control and let the \"Ok\" end this dialog. The\n         // result will be the correct path with a \"\\!\" at the end.\n         SetDlgItemText(hDlg, IDC_SAVE_NAME_EDIT, TEXT(\"!\"));\n      }\n   }\n\n   // Pass all messages to the base control's window proc.\n   return CallWindowProc(g_wpSaveAsDlg, hDlg, uMsg, wParam, lParam);\n}\n#endif // _WIN32_WCE\n\n//******************************************************************************\n#ifdef _WIN32_WCE\nvoid SubclassSaveAsDlg() {\n\n   // Get our current thread ID so we can compare it to other thread IDs.\n   DWORD dwThreadId = GetCurrentThreadId();\n\n   // Get the the top window in the z-order that is a child of the desktop.\n   // Dialogs are always children of the desktop on CE.  This first window\n   // should be the dialog we are looking for, but we will walk the window list\n   // just in case.\n   HWND hWnd = GetWindow(g_hWndMain, GW_HWNDFIRST);\n\n   // Walk the window list.\n   while (hWnd) {\n\n      // Check to see if this window was created by us and has controls from a\n      // common \"save as\" dialog.\n      if ((GetWindowThreadProcessId(hWnd, NULL) == dwThreadId) &&\n           GetDlgItem(hWnd, IDC_SAVE_FILE_LIST) &&\n           GetDlgItem(hWnd, IDC_SAVE_NAME_EDIT))\n      {\n         // We found our dialog.  Subclass it.\n         g_wpSaveAsDlg = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);\n         SetWindowLong(hWnd, GWL_WNDPROC, (LONG)DlgProcBrowser);\n\n         // Send our new dialog a message so it can do its initialization.\n         SendMessage(hWnd, WM_PRIVATE, MSG_INIT_DIALOG, 0);\n      }\n\n      // Get the next window in our window list.\n      hWnd = GetWindow(hWnd, GW_HWNDNEXT);\n   }\n}\n#endif // _WIN32_WCE\n\n\n//******************************************************************************\n//***** Extraction/Test/View Progress Dialog Functions\n//******************************************************************************\n\nBOOL CALLBACK DlgProcExtractProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   static EXTRACT_INFO *pei;\n   static BOOL fComplete;\n   static HWND hWndButton;\n   TCHAR szBuffer[32];\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n         // Globally store our handle so our worker thread can post to us.\n         g_hDlgProgress = hDlg;\n\n         // Get a pointer to our extract information structure.\n         pei = (EXTRACT_INFO*)lParam;\n\n         // Clear our complete flag.  It will be set to TRUE when done.\n         fComplete = FALSE;\n\n         // Get and store our edit control.\n         g_hWndEdit = GetDlgItem(hDlg, IDC_LOG);\n\n         // Disable our edit box from being edited.\n         DisableEditing(g_hWndEdit);\n\n         // Store a static handle for our Abort/Close button.\n         hWndButton = GetDlgItem(hDlg, IDCANCEL);\n\n#ifdef _WIN32_WCE\n\n         // Set our No-Drag style\n         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_NODRAG |GetWindowLong(hDlg, GWL_EXSTYLE));\n\n         RECT rc1, rc2, rcEdit;\n\n         // Get our current client size.\n         GetClientRect(hDlg, &rc1);\n\n         // Get the window rectangle for the edit control in client coordinates.\n         GetWindowRect(g_hWndEdit, &rcEdit);\n         ScreenToClient(hDlg, ((POINT*)&rcEdit));\n         ScreenToClient(hDlg, ((POINT*)&rcEdit) + 1);\n\n         // Resize our dialog to be full screen (same size as parent).\n         GetWindowRect(g_hWndMain, &rc2);\n         MoveWindow(hDlg, rc2.left, rc2.top, rc2.right - rc2.left,\n                    rc2.bottom - rc2.top + 1, FALSE);\n\n         // Get our new client size.\n         GetClientRect(hDlg, &rc2);\n\n         // Resize our edit box to fill the client.\n         MoveWindow(g_hWndEdit, rcEdit.left, rcEdit.top,\n                    (rcEdit.right  - rcEdit.left) + (rc2.right  - rc1.right),\n                    (rcEdit.bottom - rcEdit.top)  + (rc2.bottom - rc1.bottom),\n                    FALSE);\n\n#else\n         // On NT, we just center our dialog over our parent.\n         CenterWindow(hDlg);\n#endif\n\n         // Store some globals until the extract/test finishes.\n         pei->hWndEditFile       = GetDlgItem(hDlg, IDC_FILE);\n         pei->hWndProgFile       = GetDlgItem(hDlg, IDC_FILE_PROGRESS);\n         pei->hWndProgTotal      = GetDlgItem(hDlg, IDC_TOTAL_PROGRESS);\n         pei->hWndPercentage     = GetDlgItem(hDlg, IDC_PERCENTAGE);\n         pei->hWndFilesProcessed = GetDlgItem(hDlg, IDC_FILES_PROCESSED);\n         pei->hWndBytesProcessed = GetDlgItem(hDlg, IDC_BYTES_PROCESSED);\n\n         if (pei->fExtract) {\n            // Set our main window's caption.\n            SetCaptionText(TEXT(\"Extracting\"));\n\n         } else {\n            // Set our main window's caption.\n            SetCaptionText(TEXT(\"Testing\"));\n\n            // Hide the current file progress for test since it never moves.\n            ShowWindow(pei->hWndProgFile, SW_HIDE);\n         }\n\n         // Set the ranges on our progress bars.\n         SendMessage(pei->hWndProgFile,  PBM_SETRANGE, 0,\n                     MAKELPARAM(0, PROGRESS_MAX));\n         SendMessage(pei->hWndProgTotal, PBM_SETRANGE, 0,\n                     MAKELPARAM(0, PROGRESS_MAX));\n\n         // Set our file and byte totals.\n         SetDlgItemText(hDlg, IDC_FILES_TOTAL,\n                        FormatValue(szBuffer, pei->dwFileCount));\n         SetDlgItemText(hDlg, IDC_BYTES_TOTAL,\n                        FormatValue(szBuffer, pei->uzByteCount));\n\n         // Launch our Extract/Test thread and wait for WM_PRIVATE\n         DoExtractOrTestFiles(g_szZipFile, pei);\n\n         return TRUE;\n\n\n      case WM_PRIVATE: // Sent with wParam equal to MSG_OPERATION_COMPLETE when\n                       // test/extract is complete.\n\n         // Check to see if the operation was a success\n         if ((pei->result == PK_OK) || (pei->result == PK_WARN)) {\n\n            // Set all our fields to their \"100%\" settings.\n            SendMessage(pei->hWndProgFile,  PBM_SETPOS, PROGRESS_MAX, 0);\n            SendMessage(pei->hWndProgTotal, PBM_SETPOS, PROGRESS_MAX, 0);\n            SetWindowText(pei->hWndPercentage, TEXT(\"100%\"));\n            SetDlgItemText(hDlg, IDC_FILES_PROCESSED,\n                           FormatValue(szBuffer, pei->dwFileCount));\n            SetDlgItemText(hDlg, IDC_BYTES_PROCESSED,\n                           FormatValue(szBuffer, pei->uzByteCount));\n         }\n\n         // Update our status text.\n         SetWindowText(pei->hWndEditFile,\n            (pei->result == PK_OK)      ? TEXT(\"Completed.  There were no warnings or errors.\") :\n            (pei->result == PK_WARN)    ? TEXT(\"Completed.  There was one or more warnings.\") :\n            (pei->result == PK_ABORTED) ? TEXT(\"Aborted.  There may be warnings or errors.\") :\n                                          TEXT(\"Completed.  There was one or more errors.\"));\n\n         // Clear our global edit handle.\n         g_hWndEdit = NULL;\n\n         // Update our caption to show that we are done extracting/testing.\n         SetCaptionText(NULL);\n\n         // Change our abort button to now read \"Close\".\n         SetWindowText(hWndButton, TEXT(\"&Close\"));\n         EnableWindow(hWndButton, TRUE);\n\n         // Display an error dialog if an error occurred.\n         if ((pei->result != PK_OK) && (pei->result != PK_WARN)) {\n            MessageBox(hDlg, GetZipErrorString(pei->result),\n                       g_szAppName, MB_ICONERROR | MB_OK);\n         }\n\n         // We are done.  Allow the user to close the dialog.\n         fComplete = TRUE;\n         return FALSE;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n            case IDCANCEL:\n               // If abort is pressed, then set a flag that our worker thread\n               // periodically checks to decide if it needs to bail out.\n               if (!fComplete && !pei->fAbort) {\n                  pei->fAbort = TRUE;\n                  SetWindowText(hWndButton, TEXT(\"Aborting...\"));\n                  EnableWindow(hWndButton, FALSE);\n                  return FALSE;\n               }\n               // fall through to IDOK\n\n            case IDOK:\n               // Don't allow dialog to close until extract/test is complete.\n               if (fComplete) {\n                  g_hDlgProgress = NULL;\n                  EndDialog(hDlg, LOWORD(wParam));\n               }\n               return FALSE;\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n//******************************************************************************\nBOOL CALLBACK DlgProcViewProgress(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   static EXTRACT_INFO *pei;\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n         // Globally store our handle so our worker thread can post to us.\n         g_hDlgProgress = hDlg;\n\n         // Get a pointer to our extract information structure.\n         pei = (EXTRACT_INFO*)lParam;\n\n         // Center our dialog over our parent.\n         CenterWindow(hDlg);\n\n         // Store some globals until the extract finishes.\n         pei->hWndProgFile = GetDlgItem(hDlg, IDC_FILE_PROGRESS);\n\n         // Set the ranges on our progress bar.\n         SendDlgItemMessage(hDlg, IDC_FILE_PROGRESS, PBM_SETRANGE, 0,\n                            MAKELPARAM(0, PROGRESS_MAX));\n\n         // Launch our Extract thread and wait for WM_PRIVATE message.\n         DoExtractOrTestFiles(g_szZipFile, pei);\n\n         return TRUE;\n\n      case WM_PRIVATE: // Sent with wParam equal to MSG_OPERATION_COMPLETE when\n                       // test/extract is complete.\n\n         // We are done.  Close our dialog.  Any errors will be reported by\n         // OnActionView().\n         g_hDlgProgress = NULL;\n         EndDialog(hDlg, LOWORD(wParam));\n         return FALSE;\n\n      case WM_COMMAND:\n         // If abort is pressed, then set a flag that our worker thread\n         // periodically checks to decide if it needs to bail out.\n         if ((LOWORD(wParam) == IDCANCEL) && !pei->fAbort) {\n            pei->fAbort = TRUE;\n            SetWindowText(GetDlgItem(hDlg, IDCANCEL), TEXT(\"Aborting...\"));\n            EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);\n            return FALSE;\n         }\n   }\n\n   return FALSE;\n}\n\n//******************************************************************************\nvoid UpdateProgress(EXTRACT_INFO *pei, BOOL fFull) {\n\n   DWORD dwFile, dwTotal, dwPercentage;\n   TCHAR szBuffer[_MAX_PATH + 32];\n\n   // Compute our file progress bar position.\n   if (pei->uzBytesTotalThisFile) {\n      dwFile = (DWORD)(((DWORDLONG)PROGRESS_MAX *\n                        (DWORDLONG)pei->uzBytesWrittenThisFile) /\n                        (DWORDLONG)pei->uzBytesTotalThisFile);\n   } else {\n      dwFile = PROGRESS_MAX;\n   }\n\n   // Set our file progress indicators.\n   SendMessage(pei->hWndProgFile,  PBM_SETPOS, dwFile,  0);\n\n   // If we are only updating our View Progress dialog, then we are done.\n   if (!pei->hWndProgTotal) {\n      return;\n   }\n\n   // Compute our total progress bar position.\n   dwTotal = (DWORD)(((DWORDLONG)PROGRESS_MAX *\n                      (DWORDLONG)(pei->uzBytesWrittenPreviousFiles +\n                                  pei->uzBytesWrittenThisFile +\n                                  pei->dwFile)) /\n                      (DWORDLONG)(pei->uzByteCount +\n                                  pei->dwFileCount));\n   dwPercentage = dwTotal / (PROGRESS_MAX / 100);\n\n   // Set our total progress indicators.\n   SendMessage(pei->hWndProgTotal, PBM_SETPOS, dwTotal, 0);\n\n   // Set our total percentage text.\n   _stprintf(szBuffer, TEXT(\"%u%%\"), dwPercentage);\n   SetWindowText(pei->hWndPercentage, szBuffer);\n\n   // Set our current file and byte process counts.\n   FormatValue(szBuffer, pei->dwFile - 1);\n   SetWindowText(pei->hWndFilesProcessed, szBuffer);\n   FormatValue(szBuffer, pei->uzBytesWrittenPreviousFiles +\n               pei->uzBytesWrittenThisFile);\n   SetWindowText(pei->hWndBytesProcessed, szBuffer);\n\n\n   if (fFull) {\n\n      // Build our message string.\n      _tcscpy(szBuffer, pei->fExtract ? TEXT(\"Extract\") : TEXT(\"Test\"));\n      size_t preflen = _tcslen(szBuffer);\n      MBSTOTSTR(szBuffer+preflen, pei->szFile,countof(szBuffer)-preflen);\n\n      // Change all forward slashes to back slashes in the buffer.\n      ForwardSlashesToBackSlashes(szBuffer);\n\n      // Update the file name in our dialog.\n      SetWindowText(pei->hWndEditFile, szBuffer);\n   }\n}\n\n\n//******************************************************************************\n//***** Replace File Dialog Functions\n//******************************************************************************\n\nint PromptToReplace(LPCSTR szPath) {\n\n   // Check to see if we are extracting for view only.\n   if (g_fViewing) {\n\n      // Build prompt.\n      TCHAR szMessage[_MAX_PATH + 128];\n      _stprintf(szMessage,\n#ifdef UNICODE\n         TEXT(\"A file named \\\"%S\\\" has already been extracted for viewing.  \")\n#else\n         TEXT(\"A file named \\\"%s\\\" has already been extracted for viewing.  \")\n#endif\n         TEXT(\"That file might be opened and locked for viewing by another application.\\n\\n\")\n         TEXT(\"Would you like to attempt to overwrite it with the new file?\"),\n         GetFileFromPath(szPath));\n\n      // Display prompt.\n      if (IDYES == MessageBox(g_hDlgProgress, szMessage, g_szAppName,\n                              MB_ICONWARNING | MB_YESNO))\n      {\n         // Tell Info-ZIP to continue with extraction.\n         return IDM_REPLACE_YES;\n      }\n\n      // Remember that the file was skipped and tell Info-ZIP to abort extraction.\n      g_fSkipped = TRUE;\n      return IDM_REPLACE_NO;\n   }\n\n   // Otherwise, do the normal replace prompt dialog.\n   return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_REPLACE), g_hWndMain,\n                         (DLGPROC)DlgProcReplace, (LPARAM)szPath);\n}\n\n//******************************************************************************\nBOOL CALLBACK DlgProcReplace(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n   TCHAR szMessage[_MAX_PATH + 32];\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n         // Play the question tone to alert the user.\n         MessageBeep(MB_ICONQUESTION);\n\n         // Display a message with the file name.\n#ifdef UNICODE\n         _stprintf(szMessage, TEXT(\"\\\"%S\\\" already exists.\"), (LPCSTR)lParam);\n#else\n         _stprintf(szMessage, TEXT(\"\\\"%s\\\" already exists.\"), (LPCSTR)lParam);\n#endif\n\n         // Change all forward slashes to back slashes in the buffer.\n         ForwardSlashesToBackSlashes(szMessage);\n\n         // Display the file string.\n         SetDlgItemText(hDlg, IDC_FILE, szMessage);\n\n         // Center our dialog over our parent.\n         CenterWindow(hDlg);\n         return TRUE;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n\n            case IDCANCEL:\n            case IDOK:\n               EndDialog(hDlg, IDM_REPLACE_NO);\n               break;\n\n            case IDM_REPLACE_ALL:\n            case IDM_REPLACE_NONE:\n            case IDM_REPLACE_YES:\n            case IDM_REPLACE_NO:\n               EndDialog(hDlg, wParam);\n               break;\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n\n//******************************************************************************\n//***** Password Dialog Functions\n//******************************************************************************\n\n#if CRYPT\n\nBOOL CALLBACK DlgProcPassword(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   // Return Values:\n   //    IZ_PW_ENTERED    got some PWD string, use/try it\n   //    IZ_PW_CANCEL     no password available (for this entry)\n   //    IZ_PW_CANCELALL  no password, skip any further PWD request\n   //    IZ_PW_ERROR      failure (no mem, no tty, ...)\n\n   static DECRYPT_INFO *pdi;\n   TCHAR szMessage[_MAX_PATH + 32];\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n         // Play the question tone to alert the user.\n         MessageBeep(MB_ICONQUESTION);\n\n#ifdef _WIN32_WCE\n         // Add \"Ok\" button to caption bar.\n         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN |\n                       GetWindowLong(hDlg, GWL_EXSTYLE));\n#endif\n\n         // Store our decrypt information structure.\n         pdi = (DECRYPT_INFO*)lParam;\n\n         // Display a message with the file name.\n#ifdef UNICODE\n         _stprintf(szMessage, TEXT(\"\\\"%S\\\" is encrypted.\"), pdi->szFile);\n#else\n         _stprintf(szMessage, TEXT(\"\\\"%s\\\" is encrypted.\"), pdi->szFile);\n#endif\n\n         // Change all forward slashes to back slashes in the buffer.\n         ForwardSlashesToBackSlashes(szMessage);\n\n         // Display the message with the file name.\n         SetDlgItemText(hDlg, IDC_FILE, szMessage);\n\n         // Display the appropriate prompt.\n         if (pdi->retry) {\n            _stprintf(szMessage, TEXT(\"Password was incorrect. Please re-enter (%d/%d).\"),\n                     MAX_PASSWORD_RETRIES - pdi->retry + 2, MAX_PASSWORD_RETRIES + 1);\n            SetDlgItemText(hDlg, IDC_PROMPT, szMessage);\n         } else {\n            SetDlgItemText(hDlg, IDC_PROMPT, TEXT(\"Please enter the password.\"));\n         }\n\n         // Limit the password to the size of the password buffer we have been given.\n         SendDlgItemMessage(hDlg, IDC_PASSWORD, EM_LIMITTEXT, pdi->nSize - 1, 0);\n\n         // Center our dialog over our parent.\n         CenterWindow(hDlg);\n         return TRUE;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n\n            case IDOK:\n\n               // Store the password in our return password buffer.\n               GetDlgItemText(hDlg, IDC_PASSWORD, szMessage, countof(szMessage));\n               TSTRTOMBS(pdi->szPassword, szMessage, pdi->nSize);\n               EndDialog(hDlg, IZ_PW_ENTERED);\n               return FALSE;\n\n            case IDCANCEL:\n               g_fSkipped = TRUE;\n               EndDialog(hDlg, IZ_PW_CANCEL);\n               return FALSE;\n\n            case IDC_SKIP_ALL:\n               g_fSkipped = TRUE;\n               EndDialog(hDlg, IZ_PW_CANCELALL);\n               return FALSE;\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n#endif // CRYPT\n\n//******************************************************************************\n//***** View Association Dialog Functions\n//******************************************************************************\n\nBOOL CALLBACK DlgProcViewAssociation(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   static LPTSTR szApp;\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n         // Store the path buffer for our application.\n         szApp = (LPTSTR)lParam;\n\n         // Read our default viewer from the registry.\n#ifdef _WIN32_WCE\n         GetOptionString(TEXT(\"FileViewer\"), TEXT(\"\\\\Windows\\\\PWord.exe\"),\n                         szApp, sizeof(TCHAR) * _MAX_PATH);\n#else\n         GetOptionString(TEXT(\"FileViewer\"), TEXT(\"notepad.exe\"),\n                         szApp, sizeof(TCHAR) * _MAX_PATH);\n#endif\n\n         // Limit our edit control to our buffer size.\n         SendDlgItemMessage(hDlg, IDC_PATH, EM_LIMITTEXT, _MAX_PATH - 1, 0);\n\n         // Set our path string in our dialog.\n         SetDlgItemText(hDlg, IDC_PATH, szApp);\n\n         // Center our dialog over our parent.\n         CenterWindow(hDlg);\n         return TRUE;\n\n      case WM_COMMAND:\n         switch (LOWORD(wParam)) {\n\n            case IDOK:\n               // Get the text currently in the path edit box and store it.\n               GetDlgItemText(hDlg, IDC_PATH, szApp, _MAX_PATH);\n               WriteOptionString(TEXT(\"FileViewer\"), szApp);\n               // Fall through\n\n            case IDCANCEL:\n               EndDialog(hDlg, LOWORD(wParam));\n               break;\n\n            case IDC_BROWSE:\n               // Get the text currently in the path edit box.\n               GetDlgItemText(hDlg, IDC_PATH, szApp, _MAX_PATH);\n\n               // Get the direcory from the path text.\n               ForwardSlashesToBackSlashes(szApp);\n               TCHAR szInitialDir[_MAX_PATH], *szFile;\n               _tcscpy(szInitialDir, szApp);\n               if (szFile = _tcsrchr(szInitialDir, TEXT('\\\\'))) {\n                  *szFile = TEXT('\\0');\n               }\n\n               // Prepare to display browse dialog.\n               OPENFILENAME ofn;\n               ZeroMemory(&ofn, sizeof(ofn));\n               ofn.lStructSize     = sizeof(ofn);\n               ofn.hwndOwner       = hDlg;\n               ofn.hInstance       = g_hInst;\n               ofn.lpstrFilter     = TEXT(\"Programs (*.exe)\\0*.exe\\0All Files (*.*)\\0*.*\\0\");\n               ofn.nFilterIndex    = 1;\n               ofn.lpstrFile       = szApp;\n               ofn.nMaxFile        = _MAX_PATH;\n               ofn.lpstrInitialDir = szInitialDir;\n               ofn.lpstrTitle      = TEXT(\"Open With...\");\n               ofn.Flags           = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;\n               ofn.lpstrDefExt     = TEXT(\"exe\");\n\n               // Display the browse dialog and update our path edit box if neccessary.\n               if (GetOpenFileName(&ofn)) {\n                  SetDlgItemText(hDlg, IDC_PATH, szApp);\n               }\n               break;\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n\n//******************************************************************************\n//***** Comment Dialog Functions\n//******************************************************************************\n\nBOOL CALLBACK DlgProcComment(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n   RECT    rc;\n   HCURSOR hCur;\n   int     result;\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n         // Get the handle to our edit box and store it globally.\n         g_hWndEdit = GetDlgItem(hDlg, IDC_COMMENT);\n\n         // Disable our edit box from being edited.\n         DisableEditing(g_hWndEdit);\n\n#ifdef _WIN32_WCE\n         // Add \"Ok\" button to caption bar and make window No-Drag.\n         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN | WS_EX_NODRAG |\n                       GetWindowLong(hDlg, GWL_EXSTYLE));\n\n         // On CE, we resize our dialog to be full screen (same size as parent).\n         GetWindowRect(g_hWndMain, &rc);\n         MoveWindow(hDlg, rc.left, rc.top, rc.right - rc.left,\n                    rc.bottom - rc.top + 1, FALSE);\n#else\n         // On NT we just center the dialog.\n         CenterWindow(hDlg);\n#endif\n\n         // Set our edit control to be the full size of our dialog.\n         GetClientRect(hDlg, &rc);\n         MoveWindow(g_hWndEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE);\n\n         // Show hour glass cursor while processing comment.\n         hCur = SetCursor(LoadCursor(NULL, IDC_WAIT));\n\n         // Let Info-ZIP and our callbacks do the work.\n         result = DoGetComment(g_szZipFile);\n\n         // Restore/remove our cursor.\n         SetCursor(hCur);\n\n         // Display an error dialog if an error occurred.\n         if ((result != PK_OK) && (result != PK_WARN)) {\n            MessageBox(g_hWndMain, GetZipErrorString(result), g_szAppName,\n                       MB_ICONERROR | MB_OK);\n         }\n\n         // Clear our global edit box handle as we are done with it.\n         g_hWndEdit = NULL;\n\n         // Return FALSE to prevent edit box from gaining focus and showing highlight.\n         return FALSE;\n\n      case WM_COMMAND:\n         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {\n            EndDialog(hDlg, LOWORD(wParam));\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n\n\n//******************************************************************************\n//***** About Dialog Functions\n//******************************************************************************\n\nBOOL CALLBACK DlgProcAbout(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {\n\n   switch (uMsg) {\n\n      case WM_INITDIALOG:\n\n#ifdef _WIN32_WCE\n         // Add \"Ok\" button to caption bar.\n         SetWindowLong(hDlg, GWL_EXSTYLE, WS_EX_CAPTIONOKBTN |\n                       GetWindowLong(hDlg, GWL_EXSTYLE));\n#endif\n\n         // Fill in a few static members.\n         // (For VER_FULLVERSION_STR and VER_COMMENT_STR, the TEXT() macro is\n         //  not applicable, because they are defined as a set of concatenated\n         //  string constants. These strings need to be converted to UNICODE\n         //  at runtime, sigh.)\n         TCHAR szBuffer[128];\n         SetDlgItemText(hDlg, IDC_PRODUCT, TEXT(VER_PRODUCT_STR));\n#ifdef UNICODE\n         _stprintf(szBuffer, TEXT(\"Freeware Version %S\"), VER_FULLVERSION_STR);\n#else\n         _stprintf(szBuffer, TEXT(\"Freeware Version %s\"), VER_FULLVERSION_STR);\n#endif\n         SetDlgItemText(hDlg, IDC_VERSION, szBuffer);\n         _stprintf(szBuffer, TEXT(\"Developed by %s\"), TEXT(VER_DEVELOPER_STR));\n         SetDlgItemText(hDlg, IDC_DEVELOPER, szBuffer);\n         SetDlgItemText(hDlg, IDC_COPYRIGHT, TEXT(VER_COPYRIGHT_STR));\n#ifdef UNICODE\n         _stprintf(szBuffer, TEXT(\"%S\"), VER_COMMENT_STR);\n         SetDlgItemText(hDlg, IDC_COMMENT, szBuffer);\n#else\n         SetDlgItemText(hDlg, IDC_COMMENT, VER_COMMENT_STR);\n#endif\n\n         // Center the dialog over our parent.\n         CenterWindow(hDlg);\n         return TRUE;\n\n      case WM_COMMAND:\n         if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) {\n            EndDialog(hDlg, 0);\n         }\n         return FALSE;\n   }\n   return FALSE;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/wince/winmain.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n//******************************************************************************\n//\n// File:        WINMAIN.H\n//\n// Description: This module contains all the Windows specific declarations for\n//              Pocket UnZip.  See WINMAIN.CPP for a more detailed description\n//              and the actual implementation.\n//\n// Copyright:   All the source files for Pocket UnZip, except for components\n//              written by the Info-ZIP group, are copyrighted 1997 by Steve P.\n//              Miller.  The product \"Pocket UnZip\" itself is property of the\n//              author and cannot be altered in any way without written consent\n//              from Steve P. Miller.\n//\n// Disclaimer:  All project files are provided \"as is\" with no guarantee of\n//              their correctness.  The authors are not liable for any outcome\n//              that is the result of using this source.  The source for Pocket\n//              UnZip has been placed in the public domain to help provide an\n//              understanding of its implementation.  You are hereby granted\n//              full permission to use this source in any way you wish, except\n//              to alter Pocket UnZip itself.  For comments, suggestions, and\n//              bug reports, please write to stevemil@pobox.com.\n//\n//\n// Date      Name          History\n// --------  ------------  -----------------------------------------------------\n// 02/01/97  Steve Miller  Created (Version 1.0 using Info-ZIP UnZip 5.30)\n//\n//******************************************************************************\n\n#ifndef __WINMAIN_H__\n#define __WINMAIN_H__\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n//******************************************************************************\n//***** Constants / Macros\n//******************************************************************************\n\n#define MRU_MAX_FILE                       4  // Should not exceed 9\n#define MRU_START_ID                     501\n\n#define WM_PRIVATE                    0x9999\n#define MSG_SUBCLASS_DIALOG                1\n#define MSG_INIT_DIALOG                    2\n#define MSG_ADD_TEXT_TO_EDIT               3\n#define MSG_PROMPT_TO_REPLACE              4\n#define MSG_PROMPT_FOR_PASSWORD            5\n#define MSG_UPDATE_PROGRESS_PARTIAL        6\n#define MSG_UPDATE_PROGRESS_COMPLETE       7\n#define MSG_OPERATION_COMPLETE             8\n\n#define IDC_SAVE_FILE_LIST                12\n#define IDC_SAVE_NAME_PROMPT            1023\n#define IDC_SAVE_NAME_EDIT              1021\n#define IDC_SAVE_TYPE_PROMPT            1022\n#define IDC_SAVE_TYPE_LIST              1020\n\n#define PROGRESS_MAX                   32768\n\n#define ZFILE_ATTRIBUTE_VOLUME    0x00000008\n#define ZFILE_ATTRIBUTE_ENCRYPTED 0x10000000\n#define ZFILE_ATTRIBUTE_COMMENT   0x20000000\n\n#define IMAGE_VOLUME                       0\n#define IMAGE_FOLDER                       1\n#define IMAGE_APPLICATION                  2\n#define IMAGE_GENERIC                      3\n\n\n#ifndef OFN_NOVALIDATE\n#define OFN_NOVALIDATE               0x00000100\n#endif\n\n#ifndef LVS_EX_FULLROWSELECT\n#define LVS_EX_FULLROWSELECT      0x00000020\n#endif\n\n// LVM_SETEXTENDEDLISTVIEWSTYLE came after VC 4.0\n#ifndef LVM_SETEXTENDEDLISTVIEWSTYLE\n#define LVM_SETEXTENDEDLISTVIEWSTYLE (LVM_FIRST + 54)\n#endif\n\n// LVM_GETEXTENDEDLISTVIEWSTYLE came after VC 4.0\n#ifndef LVM_GETEXTENDEDLISTVIEWSTYLE\n#define LVM_GETEXTENDEDLISTVIEWSTYLE (LVM_FIRST + 55)\n#endif\n\n#ifdef _WIN32_WCE\n#define CheckDlgButton(hDlg, ctrl, fChecked) \\\n           SendDlgItemMessage(hDlg, ctrl, BM_SETCHECK, fChecked, 0)\n#define IsDlgButtonChecked(hDlg, ctrl) \\\n           SendDlgItemMessage(hDlg, ctrl, BM_GETCHECK, 0, 0)\n#endif\n\n//******************************************************************************\n//***** Types and Structures\n//******************************************************************************\n\ntypedef struct _FILE_TYPE_NODE {\n   struct _FILE_TYPE_NODE *pNext;\n   int                     image;\n   CHAR                    szExtAndDesc[2];\n} FILE_TYPE_NODE, *LPFILE_TYPE_NODE;\n\ntypedef struct _FILE_NODE {\n   zusz_t          uzSize;\n   zusz_t          uzCompressedSize;\n   DWORD           dwModified;\n   DWORD           dwAttributes;\n   DWORD           dwCRC;\n   LPCSTR          szComment;\n   LPCSTR          szType;\n   CHAR            szPathAndMethod[2];\n} FILE_NODE, *LPFILE_NODE;\n\ntypedef struct _COLUMN {\n   LPTSTR szName;\n   int    format;\n} COLUMN, *LPCOLUMN;\n\n\n//******************************************************************************\n//***** Exported Function Prototypes\n//******************************************************************************\n\nvoid AddFileToListView(FILE_NODE *pFile);\nLPCSTR GetFileFromPath(LPCSTR szPath);\nvoid ForwardSlashesToBackSlashesA(LPSTR szBuffer);\n\n\n//******************************************************************************\n//***** Global Variables\n//******************************************************************************\n\n#ifdef GLOBAL_DECLARE\n#undef GLOBAL_DECLARE\n#undef GLOBAL_INIT\n#endif\n\n#ifdef __WINMAIN_CPP__\n   #define GLOBAL_DECLARE\n   #define GLOBAL_INIT(value) =value\n#else\n   #define GLOBAL_DECLARE extern\n   #define GLOBAL_INIT(value)\n#endif\n\nGLOBAL_DECLARE HINSTANCE g_hInst                GLOBAL_INIT(NULL);\nGLOBAL_DECLARE HWND      g_hWndMain             GLOBAL_INIT(NULL);\nGLOBAL_DECLARE HWND      g_hWndEdit             GLOBAL_INIT(NULL);\nGLOBAL_DECLARE HWND      g_hDlgProgress         GLOBAL_INIT(NULL);\nGLOBAL_DECLARE CHAR      g_szZipFile[_MAX_PATH] GLOBAL_INIT(\"\");\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // __WINMAIN_H__\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/Contents",
    "content": "Contents of the \"windll\" subdirectory for UnZip 6.0 and later:\n\n  Contents       this file\n  decs.h         Exported function declarations.\n  structs.h      header file, used by both the DLL and by calling applications,\n                 defines the structures used in the DLL interface\n  unziplib.def   definition file for 32-bit UnZip library\n  windll16.def   definition file for 16-bit UnZip DLL\n  windll32.def   definition file for 32-bit UnZip DLL\n  windllgcc.def  definition file for 32-bit UnZip DLL, variant for GCC tools\n  windll_lc.def  definition file for 32-bit UnZip DLL, variant for LCC tools\n  windll.c       contains the entry point for the DLL, \"fake\" printing,\n                 sound, rename, replace and password functions\n  windll.h       header file for both 16- and 32-bit DLLs\n  windll.rc      resource file for both 16- and 32-bit DLLs\n  windll.txt     simplistic explanation of how to use DLL\n  uzexampl.c     a very simplistic example of how to load the DLL and make\n                 a call into it\n  uzexampl.h     header file for uzexampl.c\n\n  guisfx\\        directory with GUI frontend for SFX stub\n    dialog.h       interface declarations to dialog definition\n    sfxw.ico       icon graphic (binary file!)\n    sfxwiz.c       main source module for SFX stub\n    sfxwiz.dlg     dialog window definitions\n    sfxwiz.rc      resourses for GUISFX stub\n    sfxwiz16.mak   makefile for 16-bit GUISFX stub (Borland C++ 4.52)\n    unzsfx16.def   linker definition file for 16-bit unzipsfx static library\n\n  csharp\\        example files for using the Visual C++ DLL with C# under the\n                 .NET framework 1.1\n  vb\\            example files for using the Visual C++ DLL with Visual Basic\n\n  vc5\\dll\\       directory with DLL project for Visual C++ 5.0\n  vc5\\exampl\\    directory with dll usage example project for Visual C++ 5.0\n  vc5\\lib\\       directory with LIB project for Visual C++ 5.0\n  vc5\\sfx\\       directory with SFX project files for Visual C++ 5.0\n    SFXWiz32.dsp   MS Visual C++ 5.0 project file for 32-bit GUISFX stub\n    SFXWiz32.dsw   MS Visual C++ 5.0 workspace file for 32-bit GUISFX stub\n    unzsfx32.dsp   MS Visual C++ 5.0 project for 32-bit sfxunzip static lib\n  vc5\\\n    unzip32.dsw    MS Visual C++ 5.0 workspace file for all windll projects\n\n  vc6\\dll\\       directory with DLL project for Visual C++ 6.0\n  vc6\\exampl\\    directory with dll usage example project for Visual C++ 6.0\n  vc6\\lib\\       directory with LIB project for Visual C++ 6.0\n  vc6\\sfx\\       directory with SFX project files for Visual C++ 6.0\n    SFXWiz32.dsp   MS Visual C++ 6.0 project file for 32-bit GUISFX stub\n    SFXWiz32.dsw   MS Visual C++ 6.0 workspace file for 32-bit GUISFX stub\n    unzsfx32.dsp   MS Visual C++ 6.0 project for 32-bit sfxunzip static lib\n  vc6\\\n    unzip32.dsw    MS Visual C++ 6.0 workspace file for all windll projects\n\n  vc8\\dll\\       directory with DLL project for Visual C++ 2005 (VC++ 8.0)\n  vc8\\exampl\\    directory with dll usage example project for Visual C++ 2005\n  vc8\\lib\\       directory with LIB project for Visual C++ 2005 (VC++ 8.0)\n  vc8\\sfx\\       directory with SFX project files for Visual Studio 8\n    SFXWiz32.sln     MS Visual C++ 2005 solution file for 32-bit GUISFX stub\n    SFXWiz32.vcproj  MS Visual C++ 2005 project file for 32-bit GUISFX stub\n    unzsfx32.vcproj  MS Visual C++ 2005 project for 32-bit sfxunzip static lib\n  vc8\\\n    unzip32.sln    MS Visual C++ 2005 solution file for all windll projects\n\n\nThe source file uzexampl.c contains a short example showing how to call the\nWin32 UnZip DLL from C. This code should work with all C compiler environments\nthat allow to build a >>working<< unzip32.dll binary.  This has been verified\nwith Microsoft Visual C++ (Version 6.0 [1998] and 8.0 [2005]) as well as the\nfree MinGW GCC compiler implementation.  The example code is a simple\nconsole application that calls the UnZip dll to extract files from a Zip\narchive.  The code assumes that the unzip32.dll binary is available somewhere\non the execution path.\n\nIf you want to build the UnZip DLL, the WinDLL usage example, or the WinGUI SFX\nstub from the command line, you may use the MSC Makefile supplied in the\nsubdirectory of the Win32 command line port.\n\nIn the default setup, the UnZip DLL is linked against the shared C runtime\ndll.  This configuration is most feasible for multi-module C/C++ based\nprograms.  For usage with non-C projects (e.g. Visual Basic 5/6 or MS .NET\nmanaged code), a statically linked UnZip DLL might be more appropiate.\nBoth the Visual Studio projects and the MSC Makefile in the win32/ subdir\nsupport statically linked builds through specific configurations (VC projects)\nor a configuration switch (for details look into ../win32/Makefile).\n\nNote that Borland C++ 5.0 is full of bugs; version 4.5 or 5.01 is recommended\ninstead.  If you must use Borland C++ 5.0, using the Intel optimizing compiler\nis required to avoid crashes (possibly due to a bug in the stat() function in\nthe normal Borland compiler).  This does have the advantage of giving you a\nsmaller code size than the 4.52 compiler.  Borland C++ 5.01 has resolved many\nof the problems seen with 5.0 and can be used reliably.\nThe UnZip DLL and SFXWiz have been successfully built with Borland C++ 5.5.1\nfrom the command line. However, we do not currently have the resources to\nsupply project files for the Borland IDE environment (C Builder 5.x - 6.x).\nFor compilation with Borland C++, please use the appropiate targets supplied\nwith the Borland Makefile in the Win32 subdirectory.\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/AssemblyInfo.cs",
    "content": "using System.Reflection;\nusing System.Runtime.CompilerServices;\n\n//\n// General Information about an assembly is controlled through the following\n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n//\n[assembly: AssemblyTitle(\"\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"\")]\n[assembly: AssemblyCopyright(\"\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n//\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version\n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Revision and Build Numbers\n// by using the '*' as shown below:\n\n[assembly: AssemblyVersion(\"1.0.*\")]\n\n//\n// In order to sign your assembly you must specify a key to use. Refer to the\n// Microsoft .NET Framework documentation for more information on assembly signing.\n//\n// Use the attributes below to control which key is used for signing.\n//\n// Notes:\n//   (*) If no key is specified, the assembly is not signed.\n//   (*) KeyName refers to a key that has been installed in the Crypto Service\n//       Provider (CSP) on your machine. KeyFile refers to a file which contains\n//       a key.\n//   (*) If the KeyFile and the KeyName values are both specified, the\n//       following processing occurs:\n//       (1) If the KeyName can be found in the CSP, that key is used.\n//       (2) If the KeyName does not exist and the KeyFile does exist, the key\n//           in the KeyFile is installed into the CSP and used.\n//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\n//       When specifying the KeyFile, the location of the KeyFile should be\n//       relative to the project output directory which is\n//       %Project Directory%\\obj\\<configuration>. For example, if your KeyFile is\n//       located in the project directory, you would specify the AssemblyKeyFile\n//       attribute as [assembly: AssemblyKeyFile(\"..\\\\..\\\\mykey.snk\")]\n//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\n//       documentation for more information on this.\n//\n[assembly: AssemblyDelaySign(false)]\n[assembly: AssemblyKeyFile(\"\")]\n[assembly: AssemblyKeyName(\"\")]\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/CSharpInfoZip_UnZipSample.csproj",
    "content": "<VisualStudioProject>\n    <CSHARP\n        ProjectType = \"Local\"\n        ProductVersion = \"7.10.3077\"\n        SchemaVersion = \"2.0\"\n        ProjectGuid = \"{D08B77ED-BEAD-4AF0-81B4-6F1CB998273C}\"\n    >\n        <Build>\n            <Settings\n                ApplicationIcon = \"App.ico\"\n                AssemblyKeyContainerName = \"\"\n                AssemblyName = \"CSharpInfoZip_UnZipSample\"\n                AssemblyOriginatorKeyFile = \"\"\n                DefaultClientScript = \"JScript\"\n                DefaultHTMLPageLayout = \"Grid\"\n                DefaultTargetSchema = \"IE50\"\n                DelaySign = \"false\"\n                OutputType = \"WinExe\"\n                PreBuildEvent = \"\"\n                PostBuildEvent = \"\"\n                RootNamespace = \"CSharpInfoZip_UnZipSample\"\n                RunPostBuildEvent = \"OnBuildSuccess\"\n                StartupObject = \"\"\n            >\n                <Config\n                    Name = \"Debug\"\n                    AllowUnsafeBlocks = \"false\"\n                    BaseAddress = \"285212672\"\n                    CheckForOverflowUnderflow = \"false\"\n                    ConfigurationOverrideFile = \"\"\n                    DefineConstants = \"DEBUG;TRACE\"\n                    DocumentationFile = \"\"\n                    DebugSymbols = \"true\"\n                    FileAlignment = \"4096\"\n                    IncrementalBuild = \"false\"\n                    NoStdLib = \"false\"\n                    NoWarn = \"\"\n                    Optimize = \"false\"\n                    OutputPath = \"bin\\Debug\\\"\n                    RegisterForComInterop = \"false\"\n                    RemoveIntegerChecks = \"false\"\n                    TreatWarningsAsErrors = \"false\"\n                    WarningLevel = \"4\"\n                />\n                <Config\n                    Name = \"Release\"\n                    AllowUnsafeBlocks = \"false\"\n                    BaseAddress = \"285212672\"\n                    CheckForOverflowUnderflow = \"false\"\n                    ConfigurationOverrideFile = \"\"\n                    DefineConstants = \"TRACE\"\n                    DocumentationFile = \"\"\n                    DebugSymbols = \"false\"\n                    FileAlignment = \"4096\"\n                    IncrementalBuild = \"false\"\n                    NoStdLib = \"false\"\n                    NoWarn = \"\"\n                    Optimize = \"true\"\n                    OutputPath = \"bin\\Release\\\"\n                    RegisterForComInterop = \"false\"\n                    RemoveIntegerChecks = \"false\"\n                    TreatWarningsAsErrors = \"false\"\n                    WarningLevel = \"4\"\n                />\n            </Settings>\n            <References>\n                <Reference\n                    Name = \"System\"\n                    AssemblyName = \"System\"\n                    HintPath = \"..\\..\\..\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\System.dll\"\n                />\n                <Reference\n                    Name = \"System.Data\"\n                    AssemblyName = \"System.Data\"\n                    HintPath = \"..\\..\\..\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\System.Data.dll\"\n                />\n                <Reference\n                    Name = \"System.Drawing\"\n                    AssemblyName = \"System.Drawing\"\n                    HintPath = \"..\\..\\..\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\System.Drawing.dll\"\n                />\n                <Reference\n                    Name = \"System.Windows.Forms\"\n                    AssemblyName = \"System.Windows.Forms\"\n                    HintPath = \"..\\..\\..\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\System.Windows.Forms.dll\"\n                />\n                <Reference\n                    Name = \"System.XML\"\n                    AssemblyName = \"System.XML\"\n                    HintPath = \"..\\..\\..\\WINDOWS\\Microsoft.NET\\Framework\\v1.1.4322\\System.XML.dll\"\n                />\n            </References>\n        </Build>\n        <Files>\n            <Include>\n                <File\n                    RelPath = \"App.ico\"\n                    BuildAction = \"Content\"\n                />\n                <File\n                    RelPath = \"AssemblyInfo.cs\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"Form1.cs\"\n                    SubType = \"Form\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"Form1.resx\"\n                    DependentUpon = \"Form1.cs\"\n                    BuildAction = \"EmbeddedResource\"\n                />\n                <File\n                    RelPath = \"frmShowContents.cs\"\n                    SubType = \"Form\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"frmShowContents.resx\"\n                    DependentUpon = \"frmShowContents.cs\"\n                    BuildAction = \"EmbeddedResource\"\n                />\n                <File\n                    RelPath = \"Unzip.cs\"\n                    SubType = \"Code\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"UnZipDLLPrintMessageEventArgs.cs\"\n                    SubType = \"Code\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"UnZipDLLServiceMessageEventArgs.cs\"\n                    SubType = \"Code\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"ZipFileEntries.cs\"\n                    SubType = \"Code\"\n                    BuildAction = \"Compile\"\n                />\n                <File\n                    RelPath = \"ZipFileEntry.cs\"\n                    SubType = \"Code\"\n                    BuildAction = \"Compile\"\n                />\n            </Include>\n        </Files>\n    </CSHARP>\n</VisualStudioProject>\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/Form1.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\nusing System.Drawing;\nusing System.Collections;\nusing System.ComponentModel;\nusing System.Windows.Forms;\nusing System.Data;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for Form1.\n\t/// </summary>\n\tpublic class Form1 : System.Windows.Forms.Form\n\t{\n\t\tprivate System.Windows.Forms.Button btnUnzipArchive;\n\t\tprivate System.Windows.Forms.OpenFileDialog openFileDialog1;\n\t\tprivate System.Windows.Forms.Label label1;\n\t\tprivate System.Windows.Forms.TextBox textBox1;\n\t\tprivate System.Windows.Forms.Label lblProgress;\n\t\tprivate System.Windows.Forms.ProgressBar prgBar;\n\n\t\t//Define the Unzip object\n\t\tUnzip m_Unzip = new Unzip();\n\t\tprivate ulong m_CurrentSize;\n\t\tprivate System.Windows.Forms.Button btnListZipFiles;\n\t\tprivate CheckBox chkOverwriteAll;\n\n\n\t\t/// <summary>\n\t\t/// Required designer variable.\n\t\t/// </summary>\n\t\tprivate System.ComponentModel.Container components = null;\n\n\t\tpublic Form1()\n\t\t{\n\t\t\t//\n\t\t\t// Required for Windows Form Designer support\n\t\t\t//\n\t\t\tInitializeComponent();\n\n\t\t\t//\n\t\t\t// TODO: Add any constructor code after InitializeComponent call\n\t\t\t//\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Clean up any resources being used.\n\t\t/// </summary>\n\t\tprotected override void Dispose( bool disposing )\n\t\t{\n\t\t\tif( disposing )\n\t\t\t{\n\t\t\t\tif (components != null)\n\t\t\t\t{\n\t\t\t\t\tcomponents.Dispose();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.Dispose( disposing );\n\t\t}\n\n\t\t#region Windows Form Designer generated code\n\t\t/// <summary>\n\t\t/// Required method for Designer support - do not modify\n\t\t/// the contents of this method with the code editor.\n\t\t/// </summary>\n\t\tprivate void InitializeComponent()\n\t\t{\n\t\t\tthis.btnUnzipArchive = new System.Windows.Forms.Button();\n\t\t\tthis.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();\n\t\t\tthis.label1 = new System.Windows.Forms.Label();\n\t\t\tthis.textBox1 = new System.Windows.Forms.TextBox();\n\t\t\tthis.lblProgress = new System.Windows.Forms.Label();\n\t\t\tthis.prgBar = new System.Windows.Forms.ProgressBar();\n\t\t\tthis.btnListZipFiles = new System.Windows.Forms.Button();\n\t\t\tthis.chkOverwriteAll = new System.Windows.Forms.CheckBox();\n\t\t\tthis.SuspendLayout();\n\t\t\t//\n\t\t\t// btnUnzipArchive\n\t\t\t//\n\t\t\tthis.btnUnzipArchive.Location = new System.Drawing.Point(8, 24);\n\t\t\tthis.btnUnzipArchive.Name = \"btnUnzipArchive\";\n\t\t\tthis.btnUnzipArchive.Size = new System.Drawing.Size(96, 24);\n\t\t\tthis.btnUnzipArchive.TabIndex = 0;\n\t\t\tthis.btnUnzipArchive.Text = \"Unzip archive...\";\n\t\t\tthis.btnUnzipArchive.Click += new System.EventHandler(this.btnUnzipArchive_Click);\n\t\t\t//\n\t\t\t// label1\n\t\t\t//\n\t\t\tthis.label1.Location = new System.Drawing.Point(8, 64);\n\t\t\tthis.label1.Name = \"label1\";\n\t\t\tthis.label1.Size = new System.Drawing.Size(184, 16);\n\t\t\tthis.label1.TabIndex = 1;\n\t\t\tthis.label1.Text = \"Unzip DLL Print callback message:\";\n\t\t\t//\n\t\t\t// textBox1\n\t\t\t//\n\t\t\tthis.textBox1.Location = new System.Drawing.Point(8, 80);\n\t\t\tthis.textBox1.Multiline = true;\n\t\t\tthis.textBox1.Name = \"textBox1\";\n\t\t\tthis.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;\n\t\t\tthis.textBox1.Size = new System.Drawing.Size(464, 120);\n\t\t\tthis.textBox1.TabIndex = 2;\n\t\t\t//\n\t\t\t// lblProgress\n\t\t\t//\n\t\t\tthis.lblProgress.Location = new System.Drawing.Point(8, 208);\n\t\t\tthis.lblProgress.Name = \"lblProgress\";\n\t\t\tthis.lblProgress.Size = new System.Drawing.Size(216, 16);\n\t\t\tthis.lblProgress.TabIndex = 3;\n\t\t\t//\n\t\t\t// prgBar\n\t\t\t//\n\t\t\tthis.prgBar.Location = new System.Drawing.Point(8, 224);\n\t\t\tthis.prgBar.Name = \"prgBar\";\n\t\t\tthis.prgBar.Size = new System.Drawing.Size(216, 16);\n\t\t\tthis.prgBar.TabIndex = 4;\n\t\t\t//\n\t\t\t// btnListZipFiles\n\t\t\t//\n\t\t\tthis.btnListZipFiles.Location = new System.Drawing.Point(120, 24);\n\t\t\tthis.btnListZipFiles.Name = \"btnListZipFiles\";\n\t\t\tthis.btnListZipFiles.Size = new System.Drawing.Size(96, 24);\n\t\t\tthis.btnListZipFiles.TabIndex = 5;\n\t\t\tthis.btnListZipFiles.Text = \"List zip files...\";\n\t\t\tthis.btnListZipFiles.Click += new System.EventHandler(this.btnListZipFiles_Click);\n\t\t\t//\n\t\t\t// chkOverwriteAll\n\t\t\t//\n\t\t\tthis.chkOverwriteAll.AutoSize = true;\n\t\t\tthis.chkOverwriteAll.Location = new System.Drawing.Point(255, 29);\n\t\t\tthis.chkOverwriteAll.Name = \"chkOverwriteAll\";\n\t\t\tthis.chkOverwriteAll.Size = new System.Drawing.Size(177, 17);\n\t\t\tthis.chkOverwriteAll.TabIndex = 6;\n\t\t\tthis.chkOverwriteAll.Text = \"Overwrite all files without prompt\";\n\t\t\tthis.chkOverwriteAll.UseVisualStyleBackColor = true;\n\t\t\t//\n\t\t\t// Form1\n\t\t\t//\n\t\t\tthis.AutoScaleBaseSize = new System.Drawing.Size(5, 13);\n\t\t\tthis.ClientSize = new System.Drawing.Size(480, 254);\n\t\t\tthis.Controls.Add(this.chkOverwriteAll);\n\t\t\tthis.Controls.Add(this.btnListZipFiles);\n\t\t\tthis.Controls.Add(this.prgBar);\n\t\t\tthis.Controls.Add(this.lblProgress);\n\t\t\tthis.Controls.Add(this.textBox1);\n\t\t\tthis.Controls.Add(this.label1);\n\t\t\tthis.Controls.Add(this.btnUnzipArchive);\n\t\t\tthis.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;\n\t\t\tthis.MaximizeBox = false;\n\t\t\tthis.MinimizeBox = false;\n\t\t\tthis.Name = \"Form1\";\n\t\t\tthis.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;\n\t\t\tthis.Text = \"Form1\";\n\t\t\tthis.ResumeLayout(false);\n\t\t\tthis.PerformLayout();\n\n\t\t}\n\t\t#endregion\n\n\t\t/// <summary>\n\t\t/// The main entry point for the application.\n\t\t/// </summary>\n\t\t[STAThread]\n\t\tstatic void Main()\n\t\t{\n\t\t\tApplication.Run(new Form1());\n\t\t}\n\n\t\t#region Event Handlers\n\n\t\tprivate void btnUnzipArchive_Click(object sender, System.EventArgs e)\n\t\t{\n\t\t\topenFileDialog1.ShowDialog();\n\t\t\tstring file = openFileDialog1.FileName;\n\n\t\t\tif (file == null | file == string.Empty) return;\n\n\t\t\t//Clear the DLL messages output area\n\t\t\tm_CurrentSize = 0;\n\t\t\tprgBar.Value = prgBar.Minimum;\n\t\t\tlblProgress.Text = \"\";\n\t\t\ttextBox1.Text = \"\";\n\n\t\t\t//Instantiate the Unzip object\n\t\t\tm_Unzip = new Unzip();\n\n\t\t\t//NOTE:\n\t\t\t//There are many unzip options.  This sample just demonstrates basic unzip options.\n\t\t\t//Consult the InfoZip documentation for more option information.\n\n\t\t\t//Set the Unzip object properties\n\t\t\tm_Unzip.ZipFileName = file;\n\t\t\tm_Unzip.HonorDirectories = HonorDirectoriesEnum.True;\n\t\t\tm_Unzip.ExtractOrList = ExtractOrListEnum.Extract;\n\n\t\t\t//This option sets the DLL to display only the archive comment and\n\t\t\t//then exit immediately.\n\t\t\t//m_Unzip.DisplayComment = DisplayCommentEnum.True;\n\n\t\t\t//This option switches the DLL into \"verbose ZipInfo\" mode. The\n\t\t\t//DLL extracts nothing, but instead prints out a verbose technical list\n\t\t\t//of the content of the Zip archive central directory.\n\t\t\t//This option works now, but gets terribly slow when applied to archives\n\t\t\t//with a large number of entries.\n\t\t\t//m_Unzip.VerboseZI = VerboseZIEnum.True;\n\n\t\t\tif (chkOverwriteAll.Checked)\n\t\t\t{\n\t\t\t\tm_Unzip.OverWriteFiles = OverWriteFilesEnum.True;\n\t\t\t\tm_Unzip.PromptToOverWrite = PromptToOverWriteEnum.NotRequired;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_Unzip.OverWriteFiles = OverWriteFilesEnum.False;\n\t\t\t\tm_Unzip.PromptToOverWrite = PromptToOverWriteEnum.Required;\n\t\t\t}\n\n\t\t\t//NOTE:\n\t\t\t//Directory where the unzipped files are stored.  Change this as appropriate\n\t\t\tm_Unzip.ExtractDirectory = @\"c:\\temp\\unzip\";\n\n\t\t\t//Wire the event handlers to receive the events from the Unzip class\n\t\t\tm_Unzip.ReceivePrintMessage +=new UnZipDLLPrintMessageEventHandler(unZip_ReceivePrintMessage);\n\t\t\tm_Unzip.ReceiveServiceMessage +=new UnZipDLLServiceMessageEventHandler(unZip_ReceiveServiceMessage);\n\n\t\t\t//Unzip the files\n\t\t\tint ret = m_Unzip.UnZipFiles();\n\n\t\t\t//Examine the return code\n\t\t\tMessageBox.Show(\"Done.  Return Code: \" + ret.ToString());\n\t\t}\n\n\t\tprivate void btnListZipFiles_Click(object sender, System.EventArgs e)\n\t\t{\n\n\t\t\topenFileDialog1.ShowDialog();\n\t\t\tstring file = openFileDialog1.FileName;\n\n\t\t\tif (file == null | file == string.Empty) return;\n\n\t\t\t//Clear the DLL messages output area\n\t\t\tprgBar.Value = prgBar.Minimum;\n\t\t\tlblProgress.Text = \"\";\n\t\t\ttextBox1.Text = \"\";\n\n\t\t\t//Instantiate the Unzip object\n\t\t\tm_Unzip = new Unzip();\n\n\t\t\t//NOTE:\n\t\t\t//There are many unzip options.  This sample just demonstrates basic unzip options.\n\t\t\t//Consult the InfoZip documentation for more option information.\n\n\t\t\t//Set the Unzip object properties\n\t\t\tm_Unzip.ZipFileName = file;\n\t\t\tm_Unzip.HonorDirectories = HonorDirectoriesEnum.True;\n\t\t\tm_Unzip.ExtractOrList = ExtractOrListEnum.ListContents;\n\n\t\t\t//Wire the event handlers to receive the events from the Unzip class\n\t\t\tm_Unzip.ReceivePrintMessage +=new UnZipDLLPrintMessageEventHandler(unZip_ReceivePrintMessage);\n\t\t\tm_Unzip.ReceiveServiceMessage +=new UnZipDLLServiceMessageEventHandler(unZip_ReceiveServiceMessage);\n\n\t\t\t//Unzip the files\n\t\t\tZipFileEntries zfes = m_Unzip.GetZipFileContents();\n\n\t\t\t//Show the file contents\n\t\t\tfrmShowContents frm = new frmShowContents();\n\t\t\tfrm.UnzippedFileCollection = zfes;\n\n\t\t\t//WORK AROUND:\n\t\t\tfrm.Comment = m_Unzip.GetZipFileComment();\n\n\t\t\tfrm.ShowDialog(this);\n\n\t\t\t//Examine the return code\n\t\t\tMessageBox.Show(\"Done.\");\n\n\t\t}\n\n\t\tprivate void unZip_ReceivePrintMessage(object sender, UnZipDLLPrintMessageEventArgs e)\n\t\t{\n\t\t\ttextBox1.Text += e.PrintMessage.Replace(\"\\n\", Environment.NewLine);\n\t\t\tApplication.DoEvents();\n\t\t}\n\n\t\tprivate int unZip_ReceiveServiceMessage(object sender, UnZipDLLServiceMessageEventArgs e)\n\t\t{\n\t\t\tm_CurrentSize += e.SizeOfFileEntry;\n\t\t\tprgBar.Value = Convert.ToInt32(100 * Convert.ToDouble(m_CurrentSize)\n                                     / Convert.ToDouble(e.ZipFileSize));\n\t\t\tlblProgress.Text = \"Unzipping \" + m_CurrentSize.ToString(\"N0\") + \" of \" +\n                         e.ZipFileSize.ToString(\"N0\") + \" bytes.\";\n\t\t\tApplication.DoEvents();\n\n\t\t\treturn 0;\n\t\t}\n\n\t\t#endregion\n\n\n\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/Form1.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 1.3\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">1.3</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\">this is my long string</data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        [base64 mime encoded serialized .NET Framework object]\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        [base64 mime encoded string representing a byte array form of the .NET Framework object]\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used forserialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"btnUnzipArchive.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"btnUnzipArchive.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"btnUnzipArchive.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"openFileDialog1.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"openFileDialog1.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"openFileDialog1.Location\" type=\"System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>17, 17</value>\n  </data>\n  <data name=\"label1.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"label1.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"label1.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"textBox1.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"textBox1.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"textBox1.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"lblProgress.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"lblProgress.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"lblProgress.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"prgBar.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"prgBar.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"prgBar.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"btnListZipFiles.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"btnListZipFiles.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"btnListZipFiles.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"chkOverwriteAll.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"chkOverwriteAll.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"chkOverwriteAll.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"$this.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.Language\" type=\"System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>(Default)</value>\n  </data>\n  <data name=\"$this.TrayLargeIcon\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.Localizable\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.GridSize\" type=\"System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>8, 8</value>\n  </data>\n  <data name=\"$this.DrawGrid\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </data>\n  <data name=\"$this.TrayHeight\" type=\"System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>80</value>\n  </data>\n  <data name=\"$this.SnapToGrid\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </data>\n  <data name=\"$this.Name\">\n    <value>Form1</value>\n  </data>\n  <data name=\"$this.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n</root>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/ReadMeCS.txt",
    "content": "On Windows open this file in WordPad.\n\nContents of the \"windll/csharp\" sub-archive\n\nThis directory contains Visual C Sharp (C#) sample project for\nusing the unzip32.dll library.  This project was generously donated\nby Adrian Maull.  The Zip source archive contains a corresponding\nproject for using the zip32.dll library.\n\nThese sample projects are distributed as part of the Info-ZIP distribution\nunder the Info-ZIP license.\n\nNote that the files may be saved in \"UNIX LF\" format with carriage returns\nstripped.  These may need to be restored before the project can be successfully\nused.\n\nThe project is based on .NET Framework 1.1.  It was contributed\nto the Info-Zip project April 2005.  If you have questions or comments,\ncontact us at www.Info-ZIP.org or for specific questions about these\nprojects contact Adrian Maull directly at adrian.maull@sprintpcs.com.\n\nSee UnZip.cs for more detailed information about the project.  Currently\nthe sample project has some bugs as noted in the above file.\n\nThe original code has been adapted to the modified WinDLL interface of\nUnZip 6, using Visual C# 2005 (.Net Framework 2.0) and a unzip32.dll compiled\nby Visual C++ 6.0.  The provided project file is still in the format for\nVisual Studio 7.1 (VS .Net 2003, .Net 1.1).  But the code of the project\ncan be used with newer Visual Studio versions (2005 = 8.0 or 2008 = 9.0);\nonly the project file gets (irreversibly) converted to the newer Visual\nStudio format when first opened.\n\nHowever, this project is not tested throughoutly by us at this time.\n\nNote on using Visual Studio C# 2005, 2008 (or newer?):\nThe UnZip maintainer was unsuccessful to run the C# sample code using\nVisual Studio 2005 or 2008 together with an unzip32.dll compiled with\nthe same Visual Studio version in default configuration (unzip32.dll linked\nagainst the DLL version of the C runtime library).  The C# program failed\nto load the unzip32.dll because of an \"OS loader lock\" conflict. This conflict\nshould only show up when loading \"mixed mode\" dll that contain both managed\nand unmanaged code.  So, it cannot be caused by the \"pure native code\"\nunzip32.dll directly, which contains nothing dangerous in its DLLMain()\nfunction.  It seems to be caused by the new \"side-by-side\" C runtime dlls\n(msvcr80.dll or msvcr90.dll being loaded multiple times by a .NET application\nthat uses msvcr??-linked native dlls).\nTo fix this issue, one of the following work-arounds could be used:\na) use an unzip32.dll that was linked against the system msvcrt.dll (the\n   \"old\" MSVC 6.0 runtime) that is a core system component of all Windows\n   versions from Windows 98/Windows ME and Windows 2000 and newer (at least\n   up to Windows Vista/Windows Server 2008),\nor\nb) use a statically linked variant of unzip32.dll (see the option DLLSTANDALONE\n   in the MSC Makefile for Win32 executables, \"win32/Makefile\").\n\nEd Gordon, Christian Spieler\n2009/01/17\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/UnZipDLLPrintMessageEventArgs.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for UnZipDLLPrintMessageEventArgs.\n\t/// </summary>\n\tpublic class UnZipDLLPrintMessageEventArgs : EventArgs\n\t{\n\t\tprivate string m_PrintMessage = string.Empty;\n\n\t\tpublic UnZipDLLPrintMessageEventArgs(string msg)\n\t\t{\n\t\t\tm_PrintMessage = msg;\n\t\t}\n\n\t\tpublic string PrintMessage\n\t\t{\n\t\t\tget {return m_PrintMessage;}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/UnZipDLLServiceMessageEventArgs.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for UnZipDLLServiceMessageEventArgs.\n\t/// </summary>\n\tpublic class UnZipDLLServiceMessageEventArgs\n\t{\n\t\tprivate ulong m_ZipFileSize = 0;\n\t\tprivate ulong m_SizeOfFileEntry = 0;\n\t\tprivate string m_FileEntryName = string.Empty;\n\n\t\t//zipFileSize = Total size of the zip file\n\t\t//fileEntryBytes - size of an individual file in the zip\n\t\t//fileEntryName - name of an individual file in the zip\n\t\tpublic UnZipDLLServiceMessageEventArgs(ulong zipFileSize, string fileEntryName, ulong fileEntryBytes)\n\t\t{\n\t\t\tm_ZipFileSize = zipFileSize;\n\t\t\tm_SizeOfFileEntry = fileEntryBytes;\n\t\t\tm_FileEntryName = fileEntryName;\n\t\t}\n\n\t\tpublic ulong ZipFileSize\n\t\t{\n\t\t\tget {return m_ZipFileSize;}\n\t\t}\n\n\t\tpublic ulong SizeOfFileEntry\n\t\t{\n\t\t\tget {return m_SizeOfFileEntry;}\n\t\t}\n\n\t\tpublic string FileEntryName\n\t\t{\n\t\t\tget {return m_FileEntryName;}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/Unzip.cs",
    "content": "#region README\n\n  //_____________________________________________________________________________\n  //\n  //Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n  //Adrian Maull, April 2005.\n  //\n  //If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n  //I will try to respond to coments/questions, I do not guarantee such response.\n  //\n  //THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n  //KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n  //IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n  //PARTICULAR PURPOSE.\n  //\n  //_____________________________________________________________________________\n\n\n#endregion\n\n#region KNOWN ISSUES\n\n  //_____________________________________________________________________________\n  //\n  //KNOWN ISSUES:\n  //From my testing I have encountered some issues\n  //\n  //1.  I receive an error code from the Unzip32.dll when I try to retrieve the comment from the\n  //    zip file.  To display a comment you set the nzflag of the DCLIST structure = 1.  In this\n  //    implementation, just set the m_Unzip.ExtractList = ExtractListEnum.ListContents and\n  //    m_Unzip.DisplayComment = DisplayCommentEnum.True\n  //    I provided a work around to this in the GetZipFileComment() method.\n  //\n  //    [CS, 2009-01-10:]\n  //    The DisplayComment option works now. However, the work-around code to\n  //    retrieve the zipfile comment using direct I/O has not yet been replaced\n  //    by code using the UnZip DLL.\n  //\n  //2.  I have not tested any password/encryption logic in this sample\n  //_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\nusing System.Security.Permissions;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Windows.Forms;\nusing System.IO;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n  /// <summary>\n  /// Summary description for Unzip.\n  /// </summary>\n\n  #region Public Enums\n\n  public enum ExtractOnlyNewerEnum {False, True};\n  public enum SpaceToUnderScoreEnum {False, True};\n  public enum PromptToOverWriteEnum {NotRequired, Required};\n  public enum QuietEnum {AllMessages, LessMessages, NoMessages};\n  public enum WriteStdOutEnum {False, True};\n  public enum TestZipEnum {False, True};\n  public enum ExtractOrListEnum {Extract, ListContents};\n  public enum FreshenExistingEnum {False, True};\n  public enum DisplayCommentEnum {False, True};\n  public enum HonorDirectoriesEnum {False, True};\n  public enum OverWriteFilesEnum {False, True};\n  public enum ConvertCR_CRLFEnum {False, True};\n  public enum VerboseZIEnum {False, True};\n  public enum UnixFileBackupEnum { False, True }\n  public enum CaseSensitivityEnum { True, False };\n  public enum RestoreTimeStampsEnum { All, FilesOnly, None };\n  public enum UTF8NameTranslationEnum { Automatic, EscapeNonASCII, Disabled };\n  public enum PrivilegeEnum {Default, ACL, Privilege};\n  public enum ReplaceFileOptionsEnum {ReplaceNo=100, ReplaceYes=102, ReplaceAll=103,\n                                      ReplaceNone=104, ReplaceRename=105};\n\n\n  #endregion\n\n  #region Event Delegates\n\n  public delegate void UnZipDLLPrintMessageEventHandler(object sender, UnZipDLLPrintMessageEventArgs  e);\n  public delegate int UnZipDLLServiceMessageEventHandler(object sender, UnZipDLLServiceMessageEventArgs  e);\n\n  #endregion\n\n  public class Unzip\n  {\n    public Unzip()\n    {\n    }\n\n    #region Constants\n    // Current version of the DCLIST interface structure, must be matched\n    // with the UZ_DCL_STRUCTVER constant as defined in the struct.h header\n    // from the UnZip WinDLL code.\n    private const uint uz_dcl_StructVer = 0x600;\n    #endregion\n\n    #region Private Vars\n\n    private ulong m_ZipFileSize;\n    private ulong m_ZipFileCount;\n    private int m_Stop;\n    private string m_ZipFileName;\n    private string m_ExtractionDirectory;\n    private string m_Password;\n    private string m_Comment;\n    private string [] m_FilesToUnzip = new string[0]; //Default\n    private string [] m_FilesToExclude = new string[0]; //Default\n    private ZipFileEntries m_ZipFileEntries = new ZipFileEntries();\n    private Encoding m_EncodingANSI = Encoding.Default;\n\n    private ExtractOnlyNewerEnum m_ExtractOnlyNewer;\n    private SpaceToUnderScoreEnum m_SpaceToUnderScore;\n    private PromptToOverWriteEnum m_PromptToOverWrite;\n    private QuietEnum m_Quiet;\n    private WriteStdOutEnum m_WriteStdOut;\n    private TestZipEnum m_TestZip;\n    private ExtractOrListEnum m_ExtractOrList;\n    private FreshenExistingEnum m_FreshenExisting;\n    private DisplayCommentEnum m_DisplayComment;\n    private HonorDirectoriesEnum m_HonorDirectories;\n    private OverWriteFilesEnum m_OverWriteFiles;\n    private ConvertCR_CRLFEnum m_ConvertCR_CRLF;\n    private VerboseZIEnum m_VerboseZI;\n    private UnixFileBackupEnum m_UnixFileBackup;\n    private CaseSensitivityEnum m_CaseSensitivity;\n    private RestoreTimeStampsEnum m_RestoreTimeStamps;\n    private UTF8NameTranslationEnum m_UTF8NameTranslation;\n    private PrivilegeEnum m_Privilege;\n\n\n    #endregion\n\n    #region Structures\n\n    // Callback Large String\n    protected struct UNZIPCBChar\n    {\n      [MarshalAs( UnmanagedType.ByValArray, SizeConst= 32000, ArraySubType = UnmanagedType.U1)]\n      public byte [] ch;\n    }\n\n    // Callback Small String (size of a filename buffer)\n    protected struct UNZIPCBCh\n    {\n      [MarshalAs( UnmanagedType.ByValArray, SizeConst= 260, ArraySubType = UnmanagedType.U1)]\n      public byte [] ch;\n    }\n\n    //UNZIP32.DLL DCLIST Structure\n    [ StructLayout( LayoutKind.Sequential )]\n    protected struct DCLIST\n    {\n      public uint StructVersID;       // struct version id (= UZ_DCL_STRUCTVER)\n      public int ExtractOnlyNewer;    //1 = Extract Only Newer/New, Else 0\n      public int SpaceToUnderscore;   //1 = Convert Space To Underscore, Else 0\n      public int PromptToOverwrite;   //1 = Prompt To Overwrite Required, Else 0\n      public int fQuiet;              //2 = No Messages, 1 = Less, 0 = All\n      public int ncflag;              //1 = Write To Stdout, Else 0\n      public int ntflag;              //1 = Test Zip File, Else 0\n      public int nvflag;              //0 = Extract, 1 = List Zip Contents\n      public int nfflag;              //1 = Extract Only Newer Over Existing, Else 0\n      public int nzflag;              //1 = Display Zip File Comment, Else 0\n      public int ndflag;              //1 = Honor Directories, Else 0\n      public int noflag;              //1 = Overwrite Files, Else 0\n      public int naflag;              //1 = Convert CR To CRLF, Else 0\n      public int nZIflag;             //1 = Zip Info Verbose, Else 0\n      public int B_flag;              //1 = backup existing files\n      public int C_flag;              //1 = Case Insensitivity, 0 = Case Sensitivity\n      public int D_flag;              //controls restoration of timestamps\n                                      //0 = restore all timestamps (default)\n                                      //1 = skip restoration of timestamps for folders\n                                      //    created on behalf of directory entries in the\n                                      //    Zip archive\n                                      //2 = no restoration of timestamps; extracted files\n                                      //    and dirs get stamped with current time */\n      public int U_flag;              // controls UTF-8 filename coding support\n                                      //0 = automatic UTF-8 translation enabled (default)\n                                      //1 = recognize UTF-8 coded names, but all non-ASCII\n                                      //    characters are \"escaped\" into \"#Uxxxx\"\n                                      //2 = UTF-8 support is disabled, filename handling\n                                      //    works exactly as in previous UnZip versions */\n      public int fPrivilege;          //1 = ACL, 2 = Privileges\n      public string Zip;              //The Zip Filename To Extract Files\n      public string ExtractDir;       //The Extraction Directory, NULL If Extracting To Current Dir\n    }\n\n    //UNZIP32.DLL Userfunctions Structure\n    [ StructLayout( LayoutKind.Sequential )]\n    protected struct USERFUNCTION\n    {\n      public UZDLLPrintCallback UZDLLPrnt;              //Print function callback\n      public int UZDLLSND;                              //Not supported\n      public UZDLLReplaceCallback UZDLLREPLACE;         //Replace function callback\n      public UZDLLPasswordCallback UZDLLPASSWORD;       //Password function callback\n      // 64-bit versions\n      public UZReceiveDLLMessageCallback UZDLLMESSAGE;  //Receive message callback\n      public UZDLLServiceCallback UZDLLSERVICE;         //Service callback\n      // 32-bit versions (not used/needed here)\n      public UZReceiveDLLMsgCBck_32 UZDLLMESSAGE_I32;   //Receive message callback\n      public UZDLLServiceCBck_32 UZDLLSERVICE_I32;      //Service callback\n      public ulong TotalSizeComp;                       //Total Size Of Zip Archive\n      public ulong TotalSize;                           //Total Size Of All Files In Archive\n      public ulong NumMembers;                          //Total Number Of All Files In The Archive\n      public uint CompFactor;                           //Compression Factor\n      public short cchComment;                          //Flag If Archive Has A Comment!\n    }\n\n    #endregion\n\n    #region DLL Function Declares\n\n    //NOTE:\n    //This Assumes UNZIP32.DLL Is In Your \\Windows\\System Directory!\n    [DllImport(\"unzip32.dll\", SetLastError=true)]\n    private static extern int Wiz_SingleEntryUnzip (int ifnc, string [] ifnv, int xfnc, string [] xfnv,\n      ref DCLIST dcl, ref USERFUNCTION Userf);\n\n\n    #endregion\n\n    #region Properties\n\n    public string Password\n    {\n      get {return m_Password;}\n      set {m_Password = value;}\n    }\n\n    public string Comment\n    {\n      get {return m_Comment;}\n      set {m_Comment = value;}\n    }\n\n    public ExtractOnlyNewerEnum ExtractOnlyNewer\n    {\n      get {return m_ExtractOnlyNewer;}\n      set {m_ExtractOnlyNewer = value;}\n    }\n\n    public SpaceToUnderScoreEnum SpaceToUnderScore\n    {\n      get {return m_SpaceToUnderScore;}\n      set {m_SpaceToUnderScore = value;}\n    }\n\n    public PromptToOverWriteEnum PromptToOverWrite\n    {\n      get {return m_PromptToOverWrite;}\n      set {m_PromptToOverWrite = value;}\n    }\n\n    public QuietEnum Quiet\n    {\n      get {return m_Quiet;}\n      set {m_Quiet = value;}\n    }\n\n    public WriteStdOutEnum WriteStdOut\n    {\n      get {return m_WriteStdOut;}\n      set {m_WriteStdOut = value;}\n    }\n\n    public TestZipEnum TestZip\n    {\n      get {return m_TestZip;}\n      set {m_TestZip = value;}\n    }\n\n    public ExtractOrListEnum ExtractOrList\n    {\n      get {return m_ExtractOrList;}\n      set {m_ExtractOrList = value;}\n    }\n\n    public FreshenExistingEnum FreshenExisting\n    {\n      get {return m_FreshenExisting;}\n      set {m_FreshenExisting = value;}\n    }\n\n    public DisplayCommentEnum DisplayComment\n    {\n      get {return m_DisplayComment;}\n      set {m_DisplayComment = value;}\n    }\n\n    public HonorDirectoriesEnum HonorDirectories\n    {\n      get {return m_HonorDirectories;}\n      set {m_HonorDirectories = value;}\n    }\n\n    public OverWriteFilesEnum OverWriteFiles\n    {\n      get {return m_OverWriteFiles;}\n      set {m_OverWriteFiles = value;}\n    }\n\n    public ConvertCR_CRLFEnum ConvertCR_CRLF\n    {\n      get {return m_ConvertCR_CRLF;}\n      set {m_ConvertCR_CRLF = value;}\n    }\n\n    public VerboseZIEnum VerboseZI\n    {\n      get {return m_VerboseZI;}\n      set {m_VerboseZI = value;}\n    }\n\n    public UnixFileBackupEnum UnixFileBackup\n    {\n      get { return m_UnixFileBackup; }\n      set { m_UnixFileBackup = value; }\n    }\n\n    public CaseSensitivityEnum CaseSensitivity\n    {\n      get {return m_CaseSensitivity;}\n      set {m_CaseSensitivity = value;}\n    }\n\n    public RestoreTimeStampsEnum RestoreTimeStamps\n    {\n      get { return m_RestoreTimeStamps; }\n      set { m_RestoreTimeStamps = value; }\n    }\n\n    public UTF8NameTranslationEnum UTF8NameTranslation\n    {\n      get { return m_UTF8NameTranslation; }\n      set { m_UTF8NameTranslation = value; }\n    }\n\n    public PrivilegeEnum Privilege\n    {\n      get {return m_Privilege;}\n      set {m_Privilege = value;}\n    }\n\n    public string ZipFileName\n    {\n      get {return m_ZipFileName;}\n      set {m_ZipFileName = value;}\n    }\n\n    public string ExtractDirectory\n    {\n      get {return m_ExtractionDirectory;}\n      set {m_ExtractionDirectory = value;}\n    }\n\n    public string [] FilesToUnzip\n    {\n      get {return m_FilesToUnzip;}\n      set {m_FilesToUnzip = value;}\n    }\n\n    public string [] FilesToExclude\n    {\n      get {return m_FilesToExclude;}\n      set {m_FilesToExclude = value;}\n    }\n\n    #endregion\n\n    #region UnZip DLL Delegates\n\n    //Callback For UNZIP32.DLL - Receive Message Function\n    protected delegate void UZReceiveDLLMessageCallback (ulong ucsize, ulong csiz,\n                                ushort cfactor, ushort mo,\n                                ushort dy, ushort yr, ushort hh, ushort mm, byte c,\n                                [MarshalAs(UnmanagedType.LPStr)]String fname,\n                                [MarshalAs(UnmanagedType.LPStr)]String meth,\n                                uint crc, sbyte fCrypt);\n\n    //Callback For UNZIP32.DLL - Receive Message Function (no-Int64 variant, not used here)\n    protected delegate void UZReceiveDLLMsgCBck_32(uint ucsize_lo, uint ucsize_hi, uint csiz_lo, uint csiz_hi,\n                                ushort cfactor, ushort mo,\n                                ushort dy, ushort yr, ushort hh, ushort mm, byte c,\n                                [MarshalAs(UnmanagedType.LPStr)]String fname,\n                                [MarshalAs(UnmanagedType.LPStr)]String meth,\n                                uint crc, sbyte fCrypt);\n\n    //Callback For UNZIP32.DLL - Print Message Function\n    protected delegate int UZDLLPrintCallback ([MarshalAs(UnmanagedType.LPStr)]String fname, uint x);\n\n    //Callback For UNZIP32.DLL - DLL Service Function\n    protected delegate int UZDLLServiceCallback([MarshalAs(UnmanagedType.LPStr)]String fname,\n                                                ulong ucsize);\n\n    //Callback For UNZIP32.DLL - DLL Service Function (no-Int64 variant, not used here)\n    protected delegate int UZDLLServiceCBck_32([MarshalAs(UnmanagedType.LPStr)]String fname,\n                                               uint ucsize_lo, uint ucsize_hi);\n\n    //Callback For UNZIP32.DLL - Password Function\n    protected delegate int UZDLLPasswordCallback(ref UNZIPCBCh pwd, int bufsize,\n                                                 [MarshalAs(UnmanagedType.LPStr)]String msg,\n                                                 [MarshalAs(UnmanagedType.LPStr)]String entryname);\n\n    //Callback For UNZIP32.DLL - Replace Function To Overwrite Files\n    protected delegate int UZDLLReplaceCallback(ref UNZIPCBCh fname, uint fnbufsiz);\n\n    #endregion\n\n    #region Events\n\n    public event UnZipDLLPrintMessageEventHandler ReceivePrintMessage;\n    public event UnZipDLLServiceMessageEventHandler ReceiveServiceMessage;\n\n    #endregion\n\n    #region Protected Functions\n\n    protected virtual void OnReceivePrintMessage (UnZipDLLPrintMessageEventArgs e)\n    {\n      if (ReceivePrintMessage != null)\n      {\n        ReceivePrintMessage(this, e);\n      }\n    }\n\n    protected virtual void OnReceiveServiceMessage (UnZipDLLServiceMessageEventArgs e)\n    {\n      if (ReceiveServiceMessage != null)\n      {\n        ReceiveServiceMessage(this, e);\n      }\n    }\n\n    #endregion\n\n    #region CallBack Functions\n\n    //This function is called when the DCLIST structure's nvflag is ExtractListEnum.ListContents.\n    //It is used to list the zip file contents\n    protected void UZReceiveDLLMessage (ulong ucsize, ulong csiz, ushort cfactor, ushort mo,\n                              ushort dy, ushort yr, ushort hh, ushort mm, byte c,\n                              [MarshalAs(UnmanagedType.LPStr)]String fname,\n                              [MarshalAs(UnmanagedType.LPStr)]String meth,\n                              uint crc, sbyte fCrypt)\n    {\n      //Add up the size of each file in the zip file\n      m_ZipFileSize += ucsize;\n      m_ZipFileCount ++;\n\n      //NOTE:\n      //Build out the ZipFileEntry collection\n      //You can do additional formatting for the month, day, and year properties\n      ZipFileEntry zfe = new ZipFileEntry();\n      zfe.FileName = Path.GetFileName(fname);\n      zfe.FilePath = Path.GetDirectoryName(fname);\n      zfe.IsFolder = (zfe.FileName.Length == 0 ? true : false);\n      zfe.FileSize = unchecked(ucsize);\n      zfe.FileMonth = mo;\n      zfe.FileDay = dy;\n      zfe.FileYear = yr;\n      zfe.FileHour = hh;\n      zfe.FileMinute = mm;\n      zfe.CompressedSize = unchecked(csiz);\n      zfe.CompressionFactor = cfactor;\n      zfe.CompressionMethShort = meth;\n\n      m_ZipFileEntries.Add(zfe);\n\n    }\n\n    protected int UZDLLPrint([MarshalAs(UnmanagedType.LPStr)]String msg, uint x)\n    {\n      UnZipDLLPrintMessageEventArgs e =\n          new UnZipDLLPrintMessageEventArgs(msg.Substring(0, Math.Min(unchecked((int)x),\n                                                                      msg.Length)));\n      OnReceivePrintMessage(e);\n\n      return 0;\n    }\n\n    /*\n    DLLSERVICE *ServCallBk  = Callback function designed to be used for\n                allowing the application to process Windows messages,\n                or canceling the operation, as well as giving the\n                option of a progress indicator. If this function\n                returns a non-zero value, then it will terminate\n                what it is doing. It provides the application with\n                the name of the name of the archive member it has\n                just processed, as well as it's original size.\n\n    fname.ch = the name of the file being zipped\n    ucsize = the size of the file being zipped\n\n     * */\n    protected int UZDLLService([MarshalAs(UnmanagedType.LPStr)]String fname,\n                               ulong ucsize)\n    {\n      //Raise this event\n      UnZipDLLServiceMessageEventArgs e =\n          new UnZipDLLServiceMessageEventArgs(m_ZipFileSize, fname, unchecked(ucsize));\n      OnReceiveServiceMessage (e);\n\n      return m_Stop;\n    }\n\n    protected int UZDLLPassword(ref UNZIPCBCh pwd, int bufsize,\n                        [MarshalAs(UnmanagedType.LPStr)]String msg,\n                        [MarshalAs(UnmanagedType.LPStr)]String entryname)\n    {\n      if (m_Password == null | m_Password == string.Empty) return -1;\n\n      if (m_Password.Length >= bufsize)\n      {\n        MessageBox.Show(\"Length of supplied password exceeds available pw buffer size \"\n                    + bufsize.ToString() + \"!\", \"Password Error\",\n                    MessageBoxButtons.OK, MessageBoxIcon.Error);\n        return 5;  // IZ_PW_ERROR\n      }\n\n      //clear the byte array\n      for (int i = 0; i < bufsize; i ++)\n        pwd.ch[i] = 0;\n\n      m_EncodingANSI.GetBytes(m_Password, 0, m_Password.Length, pwd.ch, 0);\n\n      return 0;\n    }\n\n    protected int UZDLLReplace(ref UNZIPCBCh fname, uint fnbufsiz)\n    {\n      ReplaceFileOptionsEnum ReplaceFileOption = ReplaceFileOptionsEnum.ReplaceNo; //Default\n      string s = string.Empty;\n      int i = 0;\n\n      if (fnbufsiz > fname.ch.Length) fnbufsiz = (uint)fname.ch.Length;\n      for (i = 0; i < fnbufsiz; i++)\n        if (fname.ch[i] == 0) break;\n      s = m_EncodingANSI.GetString(fname.ch, 0, i);\n\n      DialogResult rslt = MessageBox.Show(\"Overwrite [\" + s + \"]?  Click Cancel to skip all.\",\n                                  \"Overwrite Confirmation\", MessageBoxButtons.YesNoCancel,\n                                  MessageBoxIcon.Question);\n      switch (rslt)\n      {\n        case DialogResult.No:\n          ReplaceFileOption = ReplaceFileOptionsEnum.ReplaceNo;\n          break;\n        case DialogResult.Yes:\n          ReplaceFileOption = ReplaceFileOptionsEnum.ReplaceYes;\n          break;\n        case DialogResult.Cancel:\n          ReplaceFileOption = ReplaceFileOptionsEnum.ReplaceNone;\n          break;\n      }\n      return ConvertEnumToInt(ReplaceFileOption);\n    }\n\n    #endregion\n\n    #region Public Functions\n\n    public int UnZipFiles ()\n    {\n      int ret = -1;\n\n      //check to see if there is enough information to proceed.\n      //Exceptions can be thrown if required data is not passed in\n      if (m_ZipFileName == string.Empty) return -1;\n      if (m_ExtractionDirectory == string.Empty) return -1;\n\n      //The zip file size, in bytes, is stored in the m_ZipFileSize variable.\n      //m_ZipFileCount is the number of files in the zip.  This information\n      //is useful for some sort of progress information during unzipping.\n      if (!GetZipFileSizeAndCount()) return ret;\n\n      DCLIST dclist = new DCLIST();\n      dclist.StructVersID = uz_dcl_StructVer;   // Current version of this structure\n      dclist.ExtractOnlyNewer = ConvertEnumToInt(m_ExtractOnlyNewer);\n      dclist.SpaceToUnderscore = ConvertEnumToInt(m_SpaceToUnderScore);\n      dclist.PromptToOverwrite = ConvertEnumToInt(m_PromptToOverWrite);\n      dclist.fQuiet = ConvertEnumToInt(m_Quiet);\n      dclist.ncflag = ConvertEnumToInt(m_WriteStdOut);\n      dclist.ntflag = ConvertEnumToInt (m_TestZip);\n      dclist.nvflag = ConvertEnumToInt(m_ExtractOrList);\n      dclist.nfflag = ConvertEnumToInt(m_FreshenExisting);\n      dclist.nzflag = ConvertEnumToInt(m_DisplayComment);\n      dclist.ndflag = ConvertEnumToInt(m_HonorDirectories);\n      dclist.noflag = ConvertEnumToInt(m_OverWriteFiles);\n      dclist.naflag = ConvertEnumToInt(m_ConvertCR_CRLF);\n      dclist.nZIflag = ConvertEnumToInt(m_VerboseZI);\n      dclist.B_flag = ConvertEnumToInt(m_UnixFileBackup);\n      dclist.C_flag = ConvertEnumToInt(m_CaseSensitivity);\n      dclist.D_flag = ConvertEnumToInt(m_RestoreTimeStamps);\n      dclist.U_flag = ConvertEnumToInt(m_UTF8NameTranslation);\n      dclist.fPrivilege = ConvertEnumToInt(m_Privilege);\n      dclist.Zip = m_ZipFileName;\n      dclist.ExtractDir = m_ExtractionDirectory;\n\n      USERFUNCTION uf = PrepareUserFunctionCallbackStructure();\n\n      try\n      {\n        ret = Wiz_SingleEntryUnzip(m_FilesToUnzip.Length, m_FilesToUnzip, m_FilesToExclude.Length,\n          m_FilesToExclude, ref dclist, ref uf);\n      }\n      catch (Exception e)\n      {\n        MessageBox.Show (e.ToString() + Environment.NewLine +\n                         \"Last Win32ErrorCode: \" + Marshal.GetLastWin32Error());\n        //You can check the meaning of return codes here:\n        //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__0-499_.asp\n      }\n\n      return ret;\n    }\n\n    public bool GetZipFileSizeAndCount(ref ulong size, ref ulong fileCount)\n    {\n      if (!GetZipFileSizeAndCount()) return false;\n      size = m_ZipFileSize;\n      fileCount = m_ZipFileCount;\n      return true;\n    }\n\n    public ZipFileEntries GetZipFileContents ()\n    {\n      int ret = 0;\n\n      DCLIST dclist = new DCLIST();\n      dclist.StructVersID = uz_dcl_StructVer;\n      dclist.nvflag = ConvertEnumToInt(ExtractOrListEnum.ListContents);\n      dclist.Zip = m_ZipFileName;\n\n      USERFUNCTION uf = PrepareUserFunctionCallbackStructure();\n\n      m_ZipFileSize = 0;\n      m_ZipFileCount = 0;\n      m_ZipFileEntries.Clear();\n\n      //This call will fill the m_ZipFileEntries collection because when the nvflag = ExtractListEnum.ListContents\n      //the UZReceiveDLLMessage callback function is called\n      try\n      {\n        ret = Wiz_SingleEntryUnzip(m_FilesToUnzip.Length, m_FilesToUnzip, m_FilesToExclude.Length,\n          m_FilesToExclude, ref dclist, ref uf);\n      }\n      catch(Exception e)\n      {\n        MessageBox.Show (e.ToString() + Environment.NewLine +\n                         \"Last Win32ErrorCode: \" + Marshal.GetLastWin32Error());\n        //You can check the meaning of return codes here:\n        //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__0-499_.asp\n      }\n\n      return m_ZipFileEntries;\n    }\n\n    public string GetZipFileComment()\n    {\n      //WORK AROUND:\n      //This method provides a work around to setting the nzflag of the DCLIST structure = 1, which instructs\n      //the dll to extract the zip file comment.  See the KNOWN ISSUES region at the beginning of this code\n      //sample.\n\n      //NOTE:\n      //Explanation of Big Endian and Little Endian Architecture\n      //http://support.microsoft.com/default.aspx?scid=kb;en-us;102025\n      //Bytes in the stream are in Big Endian format.  We have to read the bytes and\n      //convert to Little Endian format.  That's what the GetLittleEndianByteOrder function\n      //does.\n\n      const int CENTRALRECORDENDSIGNATURE = 0x06054b50;\n      const int CENTRALRECORDENDSIZE = 22;\n\n      string comment = string.Empty;\n      Encoding ae = Encoding.Default;\n\n      if (m_ZipFileName == null | m_ZipFileName == string.Empty) return string.Empty;\n\n      try\n      {\n        FileStream fs = File.OpenRead(m_ZipFileName);\n        long pos = fs.Length - CENTRALRECORDENDSIZE;\n\n        while (GetLittleEndianByteOrder(fs,4) != CENTRALRECORDENDSIGNATURE)\n          fs.Seek(pos--, SeekOrigin.Begin);\n\n\n        int diskNumber = GetLittleEndianByteOrder(fs,2);              /* number of this disk */\n        int startingDiskNum = GetLittleEndianByteOrder(fs,2);         /* number of the starting disk */\n        int entriesOnrThisDisk = GetLittleEndianByteOrder(fs,2);      /* entries on this disk */\n        int totalEntries = GetLittleEndianByteOrder(fs,2);            /* total number of entries */\n        int centralDirectoryTotalSize = GetLittleEndianByteOrder(fs,4); /* size of entire central directory */\n        int offsetOfCentralDirectory = GetLittleEndianByteOrder(fs,4);  /* offset of central on starting disk */\n        //This is what we really want here\n        int commentSize = GetLittleEndianByteOrder(fs,2);             /* length of zip file comment */\n\n\n        byte[] zipFileComment = new byte[commentSize];\n        fs.Read(zipFileComment, 0, zipFileComment.Length);\n\n        comment =  ae.GetString(zipFileComment, 0, zipFileComment.Length);\n        fs.Close();\n      }\n      catch (Exception e)\n      {\n        throw new Exception(e.Message);\n      }\n      return comment;\n    }\n\n    public void Stop ()\n    {\n      //m_Stop gets returned from the UZDLLService callback.\n      //A value of 1 means abort processing.\n      m_Stop = 1;\n    }\n\n    #endregion\n\n    #region Private Functions\n\n    private int ConvertEnumToInt (System.Enum obj)\n    {\n      return Convert.ToInt32(obj);\n    }\n\n    private bool GetZipFileSizeAndCount()\n    {\n      int ret = 0;\n\n      DCLIST dclist = new DCLIST();\n      dclist.StructVersID = uz_dcl_StructVer;   // Current version of this structure\n      dclist.nvflag = ConvertEnumToInt(ExtractOrListEnum.ListContents);\n      dclist.Zip = m_ZipFileName;\n      dclist.ExtractDir = m_ExtractionDirectory;\n\n      USERFUNCTION uf = PrepareUserFunctionCallbackStructure();\n\n      //Reset these variables\n      m_ZipFileSize = 0;\n      m_ZipFileCount = 0;\n\n      ret = Wiz_SingleEntryUnzip(m_FilesToUnzip.Length, m_FilesToUnzip, m_FilesToExclude.Length,\n                                 m_FilesToExclude, ref dclist, ref uf);\n\n      return (ret == 0);\n    }\n\n\n    private USERFUNCTION PrepareUserFunctionCallbackStructure()\n    {\n      USERFUNCTION uf = new USERFUNCTION();\n      uf.UZDLLPrnt = new UZDLLPrintCallback(UZDLLPrint);\n      uf.UZDLLSND = 0; //Not supported\n      uf.UZDLLREPLACE = new UZDLLReplaceCallback(UZDLLReplace);\n      uf.UZDLLPASSWORD = new UZDLLPasswordCallback(UZDLLPassword);\n      uf.UZDLLMESSAGE = new UZReceiveDLLMessageCallback(UZReceiveDLLMessage);\n      uf.UZDLLSERVICE = new UZDLLServiceCallback(UZDLLService);\n      uf.UZDLLMESSAGE_I32 = null; // not used\n      uf.UZDLLSERVICE_I32 = null; // not used\n\n      return uf;\n    }\n\n    private int GetLittleEndianByteOrder(FileStream fs, int len)\n    {\n      int result = 0;\n      int n = 0;\n      int [] byteArr = new int[len];\n\n      //Pull the bytes from the stream\n      for(n=0;n<len;n++)\n        byteArr[n] = fs.ReadByte();\n\n      //Left shift the bytes to get a resulting number in little endian format\n      for(n=0;n<byteArr.Length;n++)\n        result += (byteArr[n] << (n*8));\n\n      return result;\n    }\n\n    #endregion\n  }\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/ZipFileEntries.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\nusing System.Collections;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for ZipFileEntries\n\t/// </summary>\n\t[Serializable]\n\tpublic class ZipFileEntries: CollectionBase, IDisposable\n\t{\n\n\t\tpublic ZipFileEntries()\n\t\t{\n\t\t}\n\n\t\t//the normal collections methods...\n\t\tpublic void Add(ZipFileEntry obj)\n\t\t{\n\t\t\tList.Add(obj);\n\t\t}\n\n\t\tpublic void Remove(int index)\n\t\t{\n\t\t\tif (index > Count - 1 || index < 0)\n\t\t\t{\n\t\t\t\t//throw an error here...\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tList.RemoveAt(index);\n\t\t\t}\n\t\t}\n\n\t\tpublic ZipFileEntry Item(int Index)\n\t\t{\n\t\t\treturn (ZipFileEntry) List[Index];\n\t\t}\n\n\n\t\t#region IDisposable Members\n\n\t\tpublic void Dispose()\n\t\t{\n\t\t\t//Any custom dispose logic goes here...\n\t\t}\n\n\t\t#endregion\n\n\n\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/ZipFileEntry.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for ZipFileEntry.\n\t/// </summary>\n\tpublic class ZipFileEntry\n\t{\n\n\t\t#region Private Vars\n\n\t\tprivate string m_FileName;\n\t\tprivate string m_FilePath;\n\t\tprivate bool m_IsFolder;\n\t\tprivate ulong m_FileSize;\n\t\tprivate int m_FileMonth;\n\t\tprivate int m_FileDay;\n\t\tprivate int m_FileYear;\n\t\tprivate int m_FileHour;\n\t\tprivate int m_FileMinute;\n\t\tprivate int m_CompressionFactor;\n\t\tprivate ulong m_CompressedSize;\n\t\tprivate string m_CompressMeth;\n\n\t\t#endregion\n\n\t\tpublic ZipFileEntry()\n\t\t{\n\t\t}\n\n\t\t#region Properties\n\n\t\tpublic string FileName\n\t\t{\n\t\t\tget {return m_FileName;}\n\t\t\tset {m_FileName = value;}\n\t\t}\n\n\t\tpublic string FilePath\n\t\t{\n\t\t\tget {return m_FilePath;}\n\t\t\tset {m_FilePath = value;}\n\t\t}\n\n\t\tpublic bool IsFolder\n\t\t{\n\t\t\tget {return m_IsFolder;}\n\t\t\tset {m_IsFolder = value;}\n\t\t}\n\n\t\tpublic ulong FileSize\n\t\t{\n\t\t\tget {return m_FileSize;}\n\t\t\tset {m_FileSize = value;}\n\t\t}\n\n\t\tpublic int FileMonth\n\t\t{\n\t\t\tget {return m_FileMonth;}\n\t\t\tset {m_FileMonth = value;}\n\t\t}\n\n\t\tpublic int FileDay\n\t\t{\n\t\t\tget {return m_FileDay;}\n\t\t\tset {m_FileDay = value;}\n\t\t}\n\n\t\tpublic int FileYear\n\t\t{\n\t\t\tget {return m_FileYear;}\n\t\t\tset {m_FileYear = value;}\n\t\t}\n\n\t\tpublic int FileHour\n\t\t{\n\t\t\tget {return m_FileHour;}\n\t\t\tset {m_FileHour = value;}\n\t\t}\n\n\t\tpublic int FileMinute\n\t\t{\n\t\t\tget {return m_FileMinute;}\n\t\t\tset {m_FileMinute = value;}\n\t\t}\n\n\t\tpublic int CompressionFactor\n\t\t{\n\t\t\tget {return m_CompressionFactor;}\n\t\t\tset {m_CompressionFactor = value;}\n\t\t}\n\n\t\tpublic ulong CompressedSize\n\t\t{\n\t\t\tget {return m_CompressedSize;}\n\t\t\tset {m_CompressedSize = value;}\n\t\t}\n\n\t\tpublic string CompressionMethShort\n\t\t{\n\t\t\tget {return m_CompressMeth;}\n\t\t\tset {m_CompressMeth = value;}\n\t\t}\n\n\t\t#endregion\n\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/frmShowContents.cs",
    "content": "#region README\n\n\t//_____________________________________________________________________________\n\t//\n\t//Sample C# code, .NET Framework 1.1, contributed to the Info-Zip project by\n\t//Adrian Maull, April 2005.\n\t//\n\t//If you have questions or comments, contact me at adrian.maull@sprintpcs.com.  Though\n\t//I will try to respond to coments/questions, I do not guarantee such response.\n\t//\n\t//THIS CODE AND INFORMATION ARE PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n\t//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n\t//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\n\t//PARTICULAR PURPOSE.\n\t//\n\t//_____________________________________________________________________________\n\n\n#endregion\n\nusing System;\nusing System.Drawing;\nusing System.Collections;\nusing System.ComponentModel;\nusing System.Windows.Forms;\n\nnamespace CSharpInfoZip_UnZipSample\n{\n\t/// <summary>\n\t/// Summary description for frmShowContents.\n\t/// </summary>\n\tpublic class frmShowContents : System.Windows.Forms.Form\n\t{\n\t\tprivate System.Windows.Forms.DataGrid dataGrid1;\n\t\tprivate System.Windows.Forms.Label label1;\n\t\tprivate System.Windows.Forms.Label label2;\n\t\tprivate System.Windows.Forms.TextBox txtComment;\n\n\t\tprivate ZipFileEntries m_ZipFileEntries;\n\t\tprivate string m_Comment;\n\n\t\t/// <summary>\n\t\t/// Required designer variable.\n\t\t/// </summary>\n\t\tprivate System.ComponentModel.Container components = null;\n\n\n\t\tpublic ZipFileEntries UnzippedFileCollection\n\t\t{\n\t\t\tset\n\t\t\t{\n\t\t\t\tm_ZipFileEntries = value;\n\t\t\t\tdataGrid1.DataSource = m_ZipFileEntries;\n\t\t\t\tlabel1.Text = m_ZipFileEntries.Count + \" files in this zip.\";\n\t\t\t}\n\t\t}\n\n\t\tpublic string Comment\n\t\t{\n\t\t\tset\n\t\t\t{\n\t\t\t\tm_Comment = value;\n\t\t\t\ttxtComment.Text = m_Comment;\n\t\t\t}\n\t\t}\n\n\t\tpublic frmShowContents()\n\t\t{\n\t\t\t//\n\t\t\t// Required for Windows Form Designer support\n\t\t\t//\n\t\t\tInitializeComponent();\n\n\t\t\t//\n\t\t\t// TODO: Add any constructor code after InitializeComponent call\n\t\t\t//\n\t\t}\n\n\t\t/// <summary>\n\t\t/// Clean up any resources being used.\n\t\t/// </summary>\n\t\tprotected override void Dispose( bool disposing )\n\t\t{\n\t\t\tif( disposing )\n\t\t\t{\n\t\t\t\tif(components != null)\n\t\t\t\t{\n\t\t\t\t\tcomponents.Dispose();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.Dispose( disposing );\n\t\t}\n\n\t\t#region Windows Form Designer generated code\n\t\t/// <summary>\n\t\t/// Required method for Designer support - do not modify\n\t\t/// the contents of this method with the code editor.\n\t\t/// </summary>\n\t\tprivate void InitializeComponent()\n\t\t{\n\t\t\tthis.dataGrid1 = new System.Windows.Forms.DataGrid();\n\t\t\tthis.label1 = new System.Windows.Forms.Label();\n\t\t\tthis.label2 = new System.Windows.Forms.Label();\n\t\t\tthis.txtComment = new System.Windows.Forms.TextBox();\n\t\t\t((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();\n\t\t\tthis.SuspendLayout();\n\t\t\t//\n\t\t\t// dataGrid1\n\t\t\t//\n\t\t\tthis.dataGrid1.DataMember = \"\";\n\t\t\tthis.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;\n\t\t\tthis.dataGrid1.Location = new System.Drawing.Point(8, 16);\n\t\t\tthis.dataGrid1.Name = \"dataGrid1\";\n\t\t\tthis.dataGrid1.Size = new System.Drawing.Size(592, 192);\n\t\t\tthis.dataGrid1.TabIndex = 0;\n\t\t\t//\n\t\t\t// label1\n\t\t\t//\n\t\t\tthis.label1.Location = new System.Drawing.Point(8, 216);\n\t\t\tthis.label1.Name = \"label1\";\n\t\t\tthis.label1.Size = new System.Drawing.Size(320, 16);\n\t\t\tthis.label1.TabIndex = 1;\n\t\t\tthis.label1.Text = \"label1\";\n\t\t\t//\n\t\t\t// label2\n\t\t\t//\n\t\t\tthis.label2.Location = new System.Drawing.Point(8, 256);\n\t\t\tthis.label2.Name = \"label2\";\n\t\t\tthis.label2.Size = new System.Drawing.Size(160, 16);\n\t\t\tthis.label2.TabIndex = 2;\n\t\t\tthis.label2.Text = \"Zip file comment:\";\n\t\t\t//\n\t\t\t// txtComment\n\t\t\t//\n\t\t\tthis.txtComment.Location = new System.Drawing.Point(8, 272);\n\t\t\tthis.txtComment.Multiline = true;\n\t\t\tthis.txtComment.Name = \"txtComment\";\n\t\t\tthis.txtComment.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;\n\t\t\tthis.txtComment.Size = new System.Drawing.Size(592, 72);\n\t\t\tthis.txtComment.TabIndex = 3;\n\t\t\tthis.txtComment.Text = \"\";\n\t\t\t//\n\t\t\t// frmShowContents\n\t\t\t//\n\t\t\tthis.AutoScaleBaseSize = new System.Drawing.Size(5, 13);\n\t\t\tthis.ClientSize = new System.Drawing.Size(616, 400);\n\t\t\tthis.Controls.Add(this.txtComment);\n\t\t\tthis.Controls.Add(this.label2);\n\t\t\tthis.Controls.Add(this.label1);\n\t\t\tthis.Controls.Add(this.dataGrid1);\n\t\t\tthis.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;\n\t\t\tthis.MaximizeBox = false;\n\t\t\tthis.MinimizeBox = false;\n\t\t\tthis.Name = \"frmShowContents\";\n\t\t\tthis.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;\n\t\t\tthis.Text = \"frmShowContents\";\n\t\t\tthis.Load += new System.EventHandler(this.frmShowContents_Load);\n\t\t\t((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();\n\t\t\tthis.ResumeLayout(false);\n\n\t\t}\n\t\t#endregion\n\n\t\tprivate void frmShowContents_Load(object sender, System.EventArgs e)\n\t\t{\n\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/csharp/frmShowContents.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 1.3\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">1.3</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\">this is my long string</data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        [base64 mime encoded serialized .NET Framework object]\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        [base64 mime encoded string representing a byte array form of the .NET Framework object]\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used forserialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"dataGrid1.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"dataGrid1.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"dataGrid1.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"label1.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"label1.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"label1.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"label2.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"label2.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"label2.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"txtComment.Modifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"txtComment.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n  <data name=\"txtComment.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.Locked\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.Language\" type=\"System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>(Default)</value>\n  </data>\n  <data name=\"$this.TrayLargeIcon\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.Localizable\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>False</value>\n  </data>\n  <data name=\"$this.GridSize\" type=\"System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\">\n    <value>8, 8</value>\n  </data>\n  <data name=\"$this.Name\">\n    <value>frmShowContents</value>\n  </data>\n  <data name=\"$this.DrawGrid\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </data>\n  <data name=\"$this.TrayHeight\" type=\"System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>80</value>\n  </data>\n  <data name=\"$this.SnapToGrid\" type=\"System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>True</value>\n  </data>\n  <data name=\"$this.DefaultModifiers\" type=\"System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\">\n    <value>Private</value>\n  </data>\n</root>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/decs.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-04 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __decs_h   /* prevent multiple inclusions */\n#define __decs_h\n\n/* for UnZip, the \"basic\" part of the win32 api is sufficient */\n#ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#  define IZ_HASDEFINED_WIN32LEAN\n#endif\n#include <windows.h>\n#ifndef __unzip_h\n#  include \"../unzip.h\"\n#endif\n#ifndef __structs_h\n#  include \"../windll/structs.h\"\n#endif\n#ifdef IZ_HASDEFINED_WIN32LEAN\n#  undef WIN32_LEAN_AND_MEAN\n#  undef IZ_HASDEFINED_WIN32LEAN\n#endif\n\n#define Wiz_Match match\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid    WINAPI Wiz_NoPrinting(int f);\nint     WINAPI Wiz_Validate(LPSTR archive, int AllCodes);\nBOOL    WINAPI Wiz_Init(zvoid *, LPUSERFUNCTIONS);\nBOOL    WINAPI Wiz_SetOpts(zvoid *, LPDCL);\nint     WINAPI Wiz_Unzip(zvoid *, int, char **, int, char **);\nint     WINAPI Wiz_SingleEntryUnzip(int, char **, int, char **,\n                                    LPDCL, LPUSERFUNCTIONS);\nint     WINAPI Wiz_SingleEntryUnzpList(unsigned, LPCSTR, unsigned, LPCSTR,\n                                       LPDCL, LPUSERFUNCTIONS);\n\nint     WINAPI Wiz_UnzipToMemory(LPSTR zip, LPSTR file,\n                                 LPUSERFUNCTIONS lpUserFunctions,\n                                 UzpBuffer *retstr);\nint     WINAPI Wiz_Grep(LPSTR archive, LPSTR file, LPSTR pattern,\n                        int cmd, int SkipBin,\n                        LPUSERFUNCTIONS lpUserFunctions);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __decs_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/dialog.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* dialog.h for sfxwiz */\n#define ICN_INSTALL         10\n#define IDM_REPLACE_NO     100\n#define IDM_REPLACE_TEXT   101\n#define IDM_REPLACE_YES    102\n#define IDM_REPLACE_ALL    103\n#define IDM_REPLACE_NONE   104\n#define ID_TARGET          201\n#define ID_TEXT1           202\n#define ID_TEXT2           203\n#define ID_TEXT3           204\n#define ID_BROWSE          205\n#define ID_INSTALL         206\n#define ID_INFOZIP         207\n#define ID_AUTHOR          208\n#define ID_EMAIL           209\n#define ID_STATUS          210\n#define INITDIALOG         300\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/sfxwiz.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* Tell Microsoft Visual C++ 2005 (and newer) to leave us alone\n * and let us use standard C functions the way we're supposed to.\n * (These preprocessor symbols must appear before the first system\n *  header include.)\n */\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#  ifndef _CRT_SECURE_NO_WARNINGS\n#    define _CRT_SECURE_NO_WARNINGS\n#  endif\n#endif\n\n#include <windows.h>\n#include <stdio.h>\n#ifdef WIN32\n#  if defined(__LCC__)\n#    include <string.h>\n#    include <commdlg.h>\n#    include <dlgs.h>\n#  endif\n   #include <shlobj.h>\n#else\n   #include <mem.h>\n   #include <stdlib.h>\n   #include <dir.h>\n   #include <dlgs.h>\n   #include <ctype.h>\n   #include <commdlg.h>\n   #include <string.h>\n#endif\n#include \"dialog.h\"\n#ifndef UzpMatch\n#define UzpMatch match\n#endif\n#include \"../structs.h\"\n#include \"../decs.h\"\n\nLPUSERFUNCTIONS lpUserFunctions;\nHANDLE hUF       = (HANDLE)NULL;\nLPDCL lpDCL      = NULL;\nHANDLE hZUF      = (HANDLE)NULL;\nHANDLE hDCL      = (HANDLE)NULL;\n\nBOOL fDoAll = FALSE;\n\nchar ** argv;\n\nHINSTANCE hInst;\nHWND hWnd;\n\n#ifndef TCHAR\n#define TCHAR char\n#endif\n\n#ifndef _MAX_PATH\n#define _MAX_PATH 260\n#endif\n\nint WINAPI password(LPSTR p, int n, LPCSTR m, LPCSTR name);\nint WINAPI DisplayBuf(TCHAR far *buf, unsigned long size);\nint WINAPI GetReplaceDlgRetVal(LPSTR filename, unsigned fnbufsiz);\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI ReceiveDllMessage(z_uint8 ucsize, z_uint8 csiz,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n    unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n    TCHAR fCrypt);\n#else\nvoid WINAPI ReceiveDllMessage(unsigned long ucsize, unsigned long csiz,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n    unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n    TCHAR fCrypt);\n#endif\nvoid WINAPI ReceiveDllMessage_NO_INT64(unsigned long ucsize_low,\n    unsigned long ucsize_high, unsigned long csiz_low, unsigned long csiz_high,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n    unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n    TCHAR fCrypt);\n\nchar szAppName[_MAX_PATH];\nchar szTarget[_MAX_PATH];\nchar szThisApp[_MAX_PATH];\nint iReturn;\n\nDLGPROC fpProc;\n\n#ifndef MAX_PATH\n   #define MAX_PATH    _MAX_PATH            // maximum path =length\n#endif\n#define TRUE        1                       // true value\n#define FALSE       0                       // false value\n\nTCHAR   zfn[MAX_PATH],                      // zip filename and path\n        szHomeDir[MAX_PATH];                // Original directory\n\n/****************************************************************************\n\n    FUNCTION: Replace(HWND, WORD, WPARAM, LPARAM)\n\n    PURPOSE:  Processes messages for \"Replace\" dialog box\n\n    MESSAGES:\n\n    WM_INITDIALOG - initialize dialog box\n    WM_COMMAND    - Input received\n\n****************************************************************************/\n\nBOOL WINAPI ReplaceProc(HWND hReplaceDlg, WORD wMessage,\n                        WPARAM wParam, LPARAM lParam)\n{\n    static char __far *lpsz;\n    TCHAR szTemp[MAX_PATH];\n\n    switch (wMessage)\n    {\n    case WM_INITDIALOG:\n        lpsz = (char __far *)lParam;\n        wsprintf(szTemp, \"Replace %s ?\", (LPSTR)lpsz);\n        SetDlgItemText(hReplaceDlg, IDM_REPLACE_TEXT, szTemp);\n        return TRUE;\n\n    case WM_COMMAND:\n        switch (LOWORD(wParam))\n        {\n        case IDCANCEL:              /* ESC key      */\n        case IDOK:                  /* Enter key    */\n            EndDialog(hReplaceDlg, IDM_REPLACE_NO);\n            break;\n        case IDM_REPLACE_ALL:\n            fDoAll = TRUE;\n        case IDM_REPLACE_NONE:\n        case IDM_REPLACE_YES:\n        case IDM_REPLACE_NO:\n            EndDialog(hReplaceDlg, wParam);\n            break;\n        }\n        return TRUE;\n    }\n    return FALSE;\n}\n\n/****************************************************************************\n\n    FUNCTION: GetDirProc(HWND, unsigned, WPARAM, LPARAM)\n\n    PURPOSE:  Processes messages for \"Set Reference Dir Procedure for\n              Update Archive\" dialog box\n\n    MESSAGES:\n\n    WM_INITDIALOG - initialize dialog box\n    WM_COMMAND    - Input received\n\n****************************************************************************/\n#ifdef WIN32\nBOOL WINAPI\nGetDirProc(HWND hDlg, WORD wMessage, WPARAM wParam, LPARAM lParam)\n{\n   switch (wMessage) {\n   case WM_INITDIALOG:\n/*\nCommon control identifiers for GetOpenFileName and GetSaveFileName\nControl identifier   Control Description\ncmb2                 Drop-down combo box that displays the current drive\n                     or folder, and that allows the user to select a\n                     drive or folder to open\nstc4                 Label for the cmb2 combo box\nlst1                 List box that displays the contents of the current drive or folder\nstc1                 Label for the lst1 list box\nedt1                 Edit control that displays the name of the current file, or in which the user can type the name of the file to open\nstc3                 Label for the edt1 edit control\ncmb1                 Drop-down combo box that displays the list of file type filters\nstc2                 Label for the cmb1 combo box\nchx1                 The read-only check box\nIDOK                 The OK command button (push button)\nIDCANCEL             The Cancel command button (push button)\npshHelp              The Help command button (push button)\n\n*/\n      CommDlg_OpenSave_HideControl(GetParent(hDlg), cmb1);\n      CommDlg_OpenSave_HideControl(GetParent(hDlg), stc2);\n      CommDlg_OpenSave_HideControl(GetParent(hDlg), edt1);\n      CommDlg_OpenSave_HideControl(GetParent(hDlg), stc3);\n      CommDlg_OpenSave_SetControlText(GetParent(hDlg),\n            IDOK, \"Set\");\n      break;\n   default:\n         break;\n   }\nreturn DefWindowProc(hDlg, wMessage, wParam, lParam);\n}\n#else\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\n\nBOOL WINAPI\nGetDirProc(HWND hwndDlg, WORD wMessage, WPARAM wParam, LPARAM lParam)\n{\nHWND hTemp;\n\n   switch (wMessage) {\n   case WM_INITDIALOG:\n      hTemp = GetDlgItem(hwndDlg, lst1);\n      EnableWindow(hTemp, FALSE);\n      ShowWindow(hTemp, SW_HIDE);\n      hTemp = GetDlgItem(hwndDlg, edt1);\n      EnableWindow(hTemp, FALSE);\n      ShowWindow(hTemp, SW_HIDE);\n      hTemp = GetDlgItem(hwndDlg, stc2);\n      EnableWindow(hTemp, FALSE);\n      ShowWindow(hTemp, SW_HIDE);\n      hTemp = GetDlgItem(hwndDlg, stc3);\n      EnableWindow(hTemp, FALSE);\n      ShowWindow(hTemp, SW_HIDE);\n      hTemp = GetDlgItem(hwndDlg, cmb1);\n      EnableWindow(hTemp, FALSE);\n      ShowWindow(hTemp, SW_HIDE);\n\n      break;\n   case WM_COMMAND:\n      switch (LOWORD(wParam)) {\n         case IDCANCEL:\n            EndDialog(hwndDlg, FALSE);\n            break;\n         case IDOK:\n            getcwd(szTarget, MAX_PATH);\n            EndDialog(hwndDlg, TRUE);\n            break;\n         }\n      default:\n         break;\n   }\n   return FALSE;\n}\n#endif /* !WIN32 */\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\n\nBOOL FAR PASCAL InitDialogProc (HWND hDlg, WORD wMsg, WORD wParam, LONG lParam) {\n   BOOL fProcessed = TRUE;\n   TCHAR szMessage[256];\n\n   RECT rc;\n\n   switch (wMsg) {\n      case WM_INITDIALOG:\n\n         hWnd = hDlg;\n         SetWindowText(hDlg,(LPSTR) szAppName);\n         SetDlgItemText(hDlg,ID_TARGET,(LPSTR)szTarget);\n\n#ifdef WIN32\n         GetCurrentDirectory(MAX_PATH, szHomeDir);\n         SetCurrentDirectory(szTarget);\n#else\n         getcwd(szHomeDir, MAX_PATH);\n         chdir(szTarget);\n         setdisk(toupper(szTarget[0]) - 'A');\n#endif\n         GetWindowRect(hDlg, &rc);\n         SetWindowPos(hDlg, NULL,\n            (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2,\n            (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 3,\n            0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\n         break;\n\n      case WM_COMMAND:\n         switch (wParam) {\n\n            case ID_BROWSE :\n                {\n#ifndef WIN32\n                FARPROC lpGetDirProc;\n#endif\n                char szTemp[MAX_PATH]=\"mike_~@~*\";\n                OPENFILENAME ofn;\n\n                memset(&ofn, '\\0', sizeof(OPENFILENAME)); /* init struct */\n                ofn.lStructSize = sizeof(OPENFILENAME);\n                ofn.hwndOwner = hWnd;\n                ofn.hInstance = hInst;\n                ofn.lpstrFilter = NULL;\n                ofn.nFilterIndex = 1;\n\n                ofn.lpstrFile = szTemp;\n                ofn.nMaxFile = MAX_PATH;\n                ofn.lpstrFileTitle = NULL;\n                ofn.nMaxFileTitle = MAX_PATH; /* ignored ! */\n                ofn.lpstrTitle = (LPSTR)\"Set Extraction Directory\";\n                ofn.lpstrInitialDir = NULL;\n                ofn.Flags = OFN_ENABLEHOOK |\n#ifdef WIN32\n                            OFN_EXPLORER|\n#endif\n                            OFN_HIDEREADONLY|OFN_NOVALIDATE;\n#ifndef WIN32\n                lpGetDirProc = MakeProcInstance((FARPROC)GetDirProc, hInst);\n   #ifndef MSC\n                (UINT CALLBACK *)ofn.lpfnHook = (UINT CALLBACK *)lpGetDirProc;\n   #else\n                ofn.lpfnHook = lpGetDirProc;\n   #endif\n#else\n                ofn.lpfnHook = (LPOFNHOOKPROC)GetDirProc;\n#endif\n                ofn.lpTemplateName = \"GETDIR\";   /* see getfiles.dlg   */\n                if (!GetOpenFileName(&ofn))\n                   {\n                   break;\n                   }\n\n                ofn.lpstrFile[ofn.nFileOffset-1] = '\\0';\n#ifdef WIN32\n                SetCurrentDirectory(ofn.lpstrFile);\n#else\n                getcwd(szTemp, MAX_PATH);\n                chdir(ofn.lpstrFile);\n                setdisk(toupper(ofn.lpstrFile[0]) - 'A');\n#endif\n                lstrcpy(szTarget,ofn.lpstrFile);\n                SetDlgItemText(hDlg,ID_TARGET,(LPSTR)szTarget);\n                }\n               break;\n\n            case IDOK:\n#ifdef WIN32\n               GetCurrentDirectory(_MAX_PATH,szTarget);\n#else\n               getcwd(szTarget, _MAX_PATH);\n#endif\n\n               lpDCL->ncflag = 0;\n               lpDCL->fQuiet = 0; // If not zero, no status messages will come through\n               lpDCL->ntflag = 0;\n               lpDCL->nvflag = 0;\n               lpDCL->nzflag = 0;\n               lpDCL->ndflag = 1;\n               lpDCL->naflag = 0;\n               lpDCL->nfflag = 0;\n               lpDCL->noflag = 0;\n               lpDCL->PromptToOverwrite = 1;\n               lpDCL->ExtractOnlyNewer = 0;\n               lpDCL->lpszZipFN = zfn;\n               lpDCL->lpszExtractDir = NULL;\n               iReturn = Wiz_SingleEntryUnzip(0, NULL, 0, NULL, lpDCL, lpUserFunctions);\n\n/* external return codes for unzip library */\n//#define PK_OK              0   /* no error */\n//#define PK_COOL            0   /* no error */\n//#define PK_WARN            1   /* warning error */\n//#define PK_ERR             2   /* error in zipfile */\n//#define PK_BADERR          3   /* severe error in zipfile */\n//#define PK_MEM             4   /* insufficient memory (during initialization) */\n//#define PK_MEM2            5   /* insufficient memory (password failure) */\n//#define PK_MEM3            6   /* insufficient memory (file decompression) */\n//#define PK_MEM4            7   /* insufficient memory (memory decompression) */\n//#define PK_MEM5            8   /* insufficient memory (not yet used) */\n//#define PK_NOZIP           9   /* zipfile not found */\n//#define PK_PARAM          10   /* bad or illegal parameters specified */\n//#define PK_FIND           11   /* no files found */\n//#define PK_DISK           50   /* disk full */\n//#define PK_EOF            51   /* unexpected EOF */\n\n//#define IZ_CTRLC          80   /* user hit ^C to terminate */\n//#define IZ_UNSUP          81   /* no files found: all unsup. compr/encrypt. */\n//#define IZ_BADPWD         82   /* no files found: all had bad password */\n\n/* return codes of password fetches (negative = user abort; positive = error) */\n//#define IZ_PW_ENTERED      0   /* got some password string; use/try it */\n//#define IZ_PW_CANCEL      -1   /* no password available (for this entry) */\n//#define IZ_PW_CANCELALL   -2   /* no password, skip any further pwd. request */\n//#define IZ_PW_ERROR        5   /* = PK_MEM2 : failure (no mem, no tty, ...) */\n               switch (iReturn) {\n                case PK_OK:\n                     wsprintf(szMessage, \"%s\", \"All files extracted OK\");\n                     break;\n                case PK_ERR:\n                     wsprintf(szMessage, \"%s\", \"Warning occurred on one or more files\");\n                     break;\n                case PK_BADERR:\n                     wsprintf(szMessage, \"%s\", \"Error in archive\");\n                     break;\n                case PK_MEM:\n                case PK_MEM2:\n                case PK_MEM3:\n                case PK_MEM4:\n                case PK_MEM5:\n                     wsprintf(szMessage, \"%s\", \"Insufficient memory\");\n                     break;\n                case PK_NOZIP:\n                     wsprintf(szMessage, \"%s\", \"Archive not found\");\n                     break;\n                case PK_FIND:\n                     wsprintf(szMessage, \"%s\", \"No files found\");\n                     break;\n                case PK_DISK:\n                     wsprintf(szMessage, \"%s\", \"Disk full\");\n                     break;\n                case PK_EOF:\n                     wsprintf(szMessage, \"%s\", \"Unexpected end of file\");\n                     break;\n                case IZ_UNSUP:\n                     wsprintf(szMessage, \"%s\", \"No files found: All unsupported\");\n                     break;\n                case IZ_BADPWD:\n                     wsprintf(szMessage, \"%s\", \"No files found: Bad password\");\n                     break;\n                default:\n                     wsprintf(szMessage, \"%s\", \"Unknown error\");\n                     break;\n                }\n               MessageBox(hDlg, szMessage, szAppName, MB_OK);\n/* Uncomment line below to have SFXWix terminate automatically\n   when done.\n */\n//              EndDialog(hDlg, wParam);\n\n               break;\n               case IDCANCEL:\n                    EndDialog(hDlg, wParam);\n                    PostQuitMessage(0);\n                    exit(0); // ..and then quit\n                    break;\n         }\n         break;\n\n      default:\n         fProcessed = FALSE;\n         break;\n   }\n   return(fProcessed);\n}\n\n\n#define WasCancelled(hDlg) (!IsWindowEnabled(GetDlgItem(hDlg,IDCANCEL)))\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint WINAPI password(LPSTR p, int n, LPCSTR m, LPCSTR name)\n{\nTCHAR sz[MAX_PATH];\nsprintf(sz, \"%s is encrypted\", name);\nMessageBox(hWnd, sz, \"Encryption not supported\", MB_OK);\nreturn IZ_PW_CANCELALL;\n}\n\nint WINAPI DisplayBuf(TCHAR far *buf, unsigned long size)\n{\nif ((buf[0] != '\\n') && (buf[0] != '\\r'))\n   SetDlgItemText(hWnd, ID_STATUS, buf);\nreturn (unsigned int) size;\n}\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint WINAPI GetReplaceDlgRetVal(LPSTR filename, unsigned fnbufsiz)\n{\n#ifndef WIN32\nFARPROC lpfnprocReplace;\n#endif\nint ReplaceDlgRetVal;   /* replace dialog return value */\n\n#ifdef WIN32\nReplaceDlgRetVal = DialogBoxParam(hInst, \"Replace\",\n   hWnd, (DLGPROC)ReplaceProc, (DWORD)filename);\n#else\nlpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);\nReplaceDlgRetVal = DialogBoxParam(hInst, \"Replace\",\n   hWnd, lpfnprocReplace, (DWORD)filename);\nFreeProcInstance(lpfnprocReplace);\n#endif\nreturn ReplaceDlgRetVal;\n}\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI ReceiveDllMessage(z_uint8 ucsize, z_uint8 csiz,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n    unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n    TCHAR fCrypt)\n{\n}\n#else\nvoid WINAPI ReceiveDllMessage(unsigned long ucsize, unsigned long csiz,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n    unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n    TCHAR fCrypt)\n{\n}\n#endif\nvoid WINAPI ReceiveDllMessage_NO_INT64(unsigned long ucsize_low,\n   unsigned long ucsize_high, unsigned long csiz_low, unsigned long csiz_high,\n   unsigned cfactor, unsigned mo, unsigned dy, unsigned yr, unsigned hh,\n   unsigned mm, TCHAR c, LPCSTR filename, LPCSTR methbuf, unsigned long crc,\n   TCHAR fCrypt)\n{\n}\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\n\nint PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,\n                    LPSTR lpszCmdLine, int nCmdShow)\n{\nTCHAR *ptr = NULL;\nhInst = hInstance;\n\nhDCL = GlobalAlloc( GPTR, (DWORD)sizeof(DCL));\nif (!hDCL)\n   {\n   return 0;\n   }\nlpDCL = (LPDCL)GlobalLock(hDCL);\nif (!lpDCL)\n   {\n   return 0;\n   }\n\nhUF = GlobalAlloc( GPTR, (DWORD)sizeof(USERFUNCTIONS));\nif (!hUF)\n   {\n   return 0;\n   }\nlpUserFunctions = (LPUSERFUNCTIONS)GlobalLock(hUF);\n\nif (!lpUserFunctions)\n   {\n   return 0;\n   }\n\nlpUserFunctions->password = password;\nlpUserFunctions->print = DisplayBuf;\nlpUserFunctions->sound = NULL;\nlpUserFunctions->replace = GetReplaceDlgRetVal;\nlpUserFunctions->SendApplicationMessage = ReceiveDllMessage;\nlpUserFunctions->SendApplicationMessage_i32 = ReceiveDllMessage_NO_INT64;\nlpUserFunctions->ServCallBk = NULL;\n\n\n\nGetModuleFileName(hInstance,(LPSTR)szThisApp,sizeof(szThisApp));\nlstrcpy(zfn, szThisApp);\n\nptr = strrchr(szThisApp, '\\\\');\nif (ptr != NULL)\n   {\n   lstrcpy(szAppName, ptr);\n   ptr[0] = '\\0';\n   lstrcpy(szTarget, szThisApp);\n\n   iReturn = DialogBox(hInstance, MAKEINTRESOURCE(INITDIALOG),\n         (HWND)NULL, (DLGPROC)InitDialogProc);\n   DestroyWindow((HWND) INITDIALOG);\n\n#ifdef WIN32\n   SetCurrentDirectory(szHomeDir);\n#else\n   getcwd(szTarget, MAX_PATH);\n   chdir(szHomeDir);\n   setdisk(toupper(szHomeDir[0]) - 'A');\n#endif\n   }\nPostQuitMessage(0);\nreturn (0);\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/sfxwiz.dlg",
    "content": "GETDIR DIALOG 1, 1, 176, 134\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Unzip To\"\nFONT 8, \"Helv\"\n{\n CONTROL \"File &Name:\", 1090, \"STATIC\", SS_LEFT | WS_CHILD | NOT WS_VISIBLE, 2, 4, 2, 8\n CONTROL \"\", 1152, \"EDIT\", ES_LEFT | ES_AUTOHSCROLL | ES_OEMCONVERT | WS_CHILD | NOT WS_VISIBLE | WS_BORDER, 2, 16, 2, 12\n CONTROL \"\", 1120, \"LISTBOX\", LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_CHILD | NOT WS_VISIBLE, 2, 34, 2, 60\n CONTROL \"&Directories:\", -1, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 8, 6, 92, 9\n CONTROL \"\", 1088, \"STATIC\", SS_LEFT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 8, 18, 92, 9\n CONTROL \"\", 1121, \"LISTBOX\", LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 8, 32, 92, 68\n CONTROL \"List Files of &Type:\", 1089, \"STATIC\", SS_LEFT | WS_CHILD | NOT WS_VISIBLE, 2, 104, 2, 9\n CONTROL \"\", 1136, \"COMBOBOX\", CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_CHILD | NOT WS_VISIBLE | WS_BORDER | WS_VSCROLL, 2, 114, 2, 34\n CONTROL \"Dri&ves:\", 1091, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 8, 104, 92, 9\n CONTROL \"\", 1137, \"COMBOBOX\", CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 8, 114, 92, 68\n CONTROL \"OK\", IDOK, \"BUTTON\", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 106, 6, 50, 14\n CONTROL \"Cancel\", IDCANCEL, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 106, 24, 50, 14\n}\n\nINITDIALOG DIALOG PRELOAD MOVEABLE DISCARDABLE 16, 2, 286, 146\nSTYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU\nCAPTION \"Caption\"\nFONT 8, \"Helv\"\n{\n CONTROL \"Extract\", IDOK, \"BUTTON\", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 212, 4, 68, 16\n CONTROL \"Done\", IDCANCEL, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 212, 28, 68, 16\n CONTROL \"Directory\", ID_TARGET, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 76, 272, 20\n CONTROL \"Target Directory:\", ID_TEXT3, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 60, 60, 10\n CONTROL \"Browse\", ID_BROWSE, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 212, 52, 68, 16\n CONTROL \"Contents will be extracted to the directory shown below:\", ID_TEXT1, \"STATIC\", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE | WS_GROUP, 4, 20, 185, 12\n CONTROL \"Browse to change the target directory:\", ID_TEXT2, \"STATIC\", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE | WS_GROUP, 4, 36, 147, 13\n CONTROL \"Info-ZIP's Windows SFX\", ID_INFOZIP, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 4, 100, 10\n CONTROL \"By Mike White\", ID_AUTHOR, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 100, 64, 10\n CONTROL \"gretamcw@coastside.net\", ID_EMAIL, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 112, 88, 10\n CONTROL \"\", ID_STATUS, \"STATIC\", SS_LEFT | WS_CHILD | WS_VISIBLE, 4, 132, 276, 10\n}\n\nREPLACE DIALOG 1, 1, 156, 56\nSTYLE WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SYSMENU | WS_POPUP\nCAPTION \"Target File Exists\"\n{\n CONTROL \"\", IDM_REPLACE_TEXT, \"STATIC\", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 4, 4, 148, 10\n CONTROL \"&Skip\", IDM_REPLACE_NO, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 4, 36, 44, 12\n CONTROL \"Re&place\", IDM_REPLACE_YES, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 4, 20, 44, 12\n CONTROL \"Replace &All\", IDM_REPLACE_ALL, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 20, 44, 12\n CONTROL \"Skip A&ll\", IDM_REPLACE_NONE, \"BUTTON\", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 56, 36, 44, 12\n}\n\n\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/sfxwiz.rc",
    "content": "#include <windows.h>\n\n\n#include \"dialog.h\"\n\n#include \"sfxwiz.dlg\"\n\nICN_INSTALL ICON  \"sfxw.ico\"\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/sfxwiz16.mak",
    "content": "#\n# Borland C++ IDE generated makefile\n#\n.AUTODEPEND\n\n\n#\n# Borland C++ tools\n#\nIMPLIB  = Implib\nBCC     = Bcc +BccW16.cfg\nTLINK   = TLink\nTLIB    = TLib\nBRC     = Brc\nTASM    = Tasm\n#\n# IDE macros\n#\n\n\n#\n# Options\n#\nIDE_LFLAGS =  -LE:\\BC45\\LIB\nIDE_RFLAGS =\nLLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe =  -Twe -c -C -LE:\\BC45\\LIB;E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN -n\nRLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe =  -31\nBLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe =\nCNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = -IE:\\BC45\\INCLUDE;E:\\WIZ\\UNZIP;E:\\WIZ\\UNZIP\\WINDLL;E:\\WIZ\\UNZIP\\WINDLL\\GUISFX -DDLL;API;USE_UNZIP_LIB;\nLNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = -x\nLEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = $(LLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe)\nREAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = $(RLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe)\nBEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = $(BLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe)\nCLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib =  -ml -WS\nLLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib =  -Twe -c -C\nRLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib =  -31\nBLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib =\nCEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(CLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib)\nCNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = -IE:\\BC45\\INCLUDE;E:\\WIZ\\UNZIP;E:\\WIZ\\UNZIP\\WINDLL;E:\\WIZ\\UNZIP\\WINDLL\\GUISFX -DSFX;DLL;USE_EF_UT_TIME;UNZIPLIB;WINDLL\nLNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = -x\nLEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = $(LEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(LLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib)\nREAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = $(REAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(RLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib)\nBEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = $(BEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(BLATW16_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib)\n\n#\n# Dependency List\n#\nDep_sfxwiz = \\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN\\sfxwiz.exe\n\nsfxwiz : BccW16.cfg $(Dep_sfxwiz)\n  echo MakeNode\n\nDep_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe = \\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN\\unzsfx16.lib\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.res\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.obj\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN\\sfxwiz.exe : $(Dep_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe)\n  $(TLINK)   @&&|\n /v $(IDE_LFLAGS) $(LEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(LNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) +\nE:\\BC45\\LIB\\c0wl.obj+\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.obj\n$<,$*\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN\\unzsfx16.lib+\nE:\\BC45\\LIB\\import.lib+\nE:\\BC45\\LIB\\mathwl.lib+\nE:\\BC45\\LIB\\cwl.lib\n\n|\n   $(BRC) E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.res $<\n\nDep_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib = \\\n   unzsfx16.def\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crypt.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\explode.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\extract.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\fileio.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\globals.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\inflate.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\match.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\process.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crc32.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\api.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\msdos.obj\\\n   E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\windll.obj\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\BIN\\unzsfx16.lib : $(Dep_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib)\n  $(TLIB) $< $(IDE_BFLAGS) $(BEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) @&&|\n -+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crypt.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\explode.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\extract.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\fileio.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\globals.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\inflate.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\match.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\process.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crc32.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\api.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\msdos.obj &\n-+E:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\windll.obj\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crypt.obj :  ..\\..\\crypt.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\crypt.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\explode.obj :  ..\\..\\explode.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\explode.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\extract.obj :  ..\\..\\extract.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\extract.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\fileio.obj :  ..\\..\\fileio.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\fileio.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\globals.obj :  ..\\..\\globals.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\globals.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\inflate.obj :  ..\\..\\inflate.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\inflate.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\match.obj :  ..\\..\\match.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\match.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\process.obj :  ..\\..\\process.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\process.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\crc32.obj :  ..\\..\\crc32.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\crc32.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\api.obj :  ..\\..\\api.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\api.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\msdos.obj :  ..\\..\\msdos\\msdos.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\..\\msdos\\msdos.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\windll.obj :  ..\\windll.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbunzsfx16dlib) -o$@ ..\\windll.c\n|\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.res :  sfxwiz.rc\n  $(BRC) $(IDE_RFLAGS) $(REAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) -R -FO$@ sfxwiz.rc\n\nE:\\WIZ\\UNZIP\\WINDLL\\GUISFX\\OBJ\\sfxwiz.obj :  sfxwiz.c\n  $(BCC)   -P- -c @&&|\n $(CEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) $(CNIEAT_EcbWIZbUNZIPbWINDLLbGUISFXbBINbsfxwizdexe) -o$@ sfxwiz.c\n|\n\n# Compiler configuration file\nBccW16.cfg :\n   Copy &&|\n-R\n-v\n-vi\n-H\n-H=sfxwiz.csm\n-H-\n-ml\n-WS\n-f-\n-ff-\n-d\n-v-\n-R-\n-Z\n-O\n-Oe\n-Ol\n-Ob\n-OW\n-3\n-Og\n| $@\n\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/guisfx/unzsfx16.def",
    "content": ";module-definition file for Windows UnZip static Library -- used by link.exe\nLIBRARY UNZSFX16  ; Library module name\n\nDESCRIPTION 'Windows Info-ZIP UnZip SFX Library (16 bit), by Mike White'\n\nCODE  PRELOAD FIXED\n\nDATA  PRELOAD MOVEABLE\n\nEXPORTS\n     Wiz_SingleEntryUnzip\n     UzpVersion\n     Wiz_Grep\n     Wiz_Init\n     Wiz_SetOpts\n     Wiz_Unzip\n     Wiz_Validate\n     Wiz_NoPrinting\n     UzpVersion2\n     Wiz_UnzipToMemory\n     Wiz_Match\n     UzpFreeMemBuffer\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/structs.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __unzip_structs_h\n#define __unzip_structs_h\n\n#ifndef Far\n#  define Far far\n#endif\n\n/* Porting definitions between Win 3.1x and Win32 */\n#ifdef WIN32\n#  define far\n#  define _far\n#  define __far\n#  define near\n#  define _near\n#  define __near\n#  ifndef FAR\n#    define FAR\n#  endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef Z_UINT8_DEFINED\n# if defined(__GNUC__)\n   typedef unsigned long long    z_uint8;\n#  define Z_UINT8_DEFINED\n# elif (defined(_MSC_VER) && (_MSC_VER >= 1100))\n   typedef unsigned __int64      z_uint8;\n#  define Z_UINT8_DEFINED\n# elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n   typedef unsigned __int64      z_uint8;\n#  define Z_UINT8_DEFINED\n# elif (defined(__IBMC__) && (__IBMC__ >= 350))\n   typedef unsigned __int64      z_uint8;\n#  define Z_UINT8_DEFINED\n# elif (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0500))\n   typedef unsigned __int64      z_uint8;\n#  define Z_UINT8_DEFINED\n# elif (defined(__LCC__))\n   typedef unsigned __int64      z_uint8;\n#  define Z_UINT8_DEFINED\n# endif\n#endif\n\n/* The following \"function\" types are jointly defined in both Zip and UnZip\n * DLLs.  They are guarded by the DEFINED_ONCE symbol to prevent multiple\n * declarations in applications that reference both the Zip and the UnZip DLL.\n */\n#ifndef DEFINED_ONCE\n#define DEFINED_ONCE\n\ntypedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);\ntypedef int (WINAPI DLLPASSWORD) (LPSTR pwbuf, int bufsiz,\n    LPCSTR promptmsg, LPCSTR entryname);\n# ifdef Z_UINT8_DEFINED\ntypedef int (WINAPI DLLSERVICE) (LPCSTR entryname, z_uint8 uncomprsiz);\n# else\ntypedef int (WINAPI DLLSERVICE) (LPCSTR entryname, unsigned long uncomprsiz);\n# endif\ntypedef int (WINAPI DLLSERVICE_I32) (LPCSTR entryname,\n    unsigned long ucsz_lo, unsigned long ucsz_hi);\n#endif /* DEFINED_ONCE */\n\ntypedef void (WINAPI DLLSND) (void);\ntypedef int (WINAPI DLLREPLACE) (LPSTR efnam, unsigned efbufsiz);\n#ifdef Z_UINT8_DEFINED\ntypedef void (WINAPI DLLMESSAGE) (z_uint8 ucsize, z_uint8 csize,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n#else\ntypedef void (WINAPI DLLMESSAGE) (unsigned long ucsize, unsigned long csize,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n#endif\ntypedef void (WINAPI DLLMESSAGE_I32) (unsigned long ucsiz_l,\n    unsigned long ucsiz_h, unsigned long csiz_l, unsigned long csiz_h,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n\ntypedef struct {\n  DLLPRNT *print;\n  DLLSND *sound;\n  DLLREPLACE *replace;\n  DLLPASSWORD *password;\n  DLLMESSAGE *SendApplicationMessage;\n  DLLSERVICE *ServCallBk;\n  DLLMESSAGE_I32 *SendApplicationMessage_i32;\n  DLLSERVICE_I32 *ServCallBk_i32;\n#ifdef Z_UINT8_DEFINED\n  z_uint8 TotalSizeComp;\n  z_uint8 TotalSize;\n  z_uint8 NumMembers;\n#else\n  struct _TotalSizeComp {\n    unsigned long u4Lo;\n    unsigned long u4Hi;\n  } TotalSizeComp;\n  struct _TotalSize {\n    unsigned long u4Lo;\n    unsigned long u4Hi;\n  } TotalSize;\n  struct _NumMembers {\n    unsigned long u4Lo;\n    unsigned long u4Hi;\n  } NumMembers;\n#endif\n  unsigned CompFactor;\n  WORD cchComment;\n} USERFUNCTIONS, far * LPUSERFUNCTIONS;\n\n/* The following symbol UZ_DCL_STRUCTVER must be incremented whenever an\n * incompatible change is applied to the WinDLL API structure \"DCL\" !\n */\n#define UZ_DCL_STRUCTVER        0x600\n/* The structure \"DCL\" is collects most the UnZip WinDLL program options\n * that control the operation of the main UnZip WinDLL function.\n */\ntypedef struct {\n  unsigned StructVersID;  /* struct version id (= UZ_DCL_STRUCTVER) */\n  int ExtractOnlyNewer;   /* TRUE for \"update\" without interaction\n                             (extract only newer/new files, without queries) */\n  int SpaceToUnderscore;  /* TRUE if convert space to underscore */\n  int PromptToOverwrite;  /* TRUE if prompt to overwrite is wanted */\n  int fQuiet;             /* quiet flag:\n                             { 0 = all | 1 = few | 2 = no } messages */\n  int ncflag;             /* write to stdout if TRUE */\n  int ntflag;             /* test zip file */\n  int nvflag;             /* verbose listing */\n  int nfflag;             /* \"freshen\" (replace existing files by newer versions) */\n  int nzflag;             /* display zip file comment */\n  int ndflag;             /* controls (sub)dir recreation during extraction\n                             0 = junk paths from filenames\n                             1 = \"safe\" usage of paths in filenames (skip ../)\n                             2 = allow unsafe path components (dir traversal)\n                           */\n  int noflag;             /* always overwriting existing files if TRUE */\n  int naflag;             /* do end-of-line translation */\n  int nZIflag;            /* get ZipInfo output if TRUE */\n  int B_flag;             /* backup existing files if TRUE */\n  int C_flag;             /* be case insensitive if TRUE */\n  int D_flag;             /* controls restoration of timestamps\n                             0 = restore all timestamps (default)\n                             1 = skip restoration of timestamps for folders\n                                 created on behalf of directory entries in the\n                                 Zip archive\n                             2 = no restoration of timestamps; extracted files\n                                 and dirs get stamped with current time */\n  int U_flag;             /* controls UTF-8 filename coding support\n                             0 = automatic UTF-8 translation enabled (default)\n                             1 = recognize UTF-8 coded names, but all non-ASCII\n                                 characters are \"escaped\" into \"#Uxxxx\"\n                             2 = UTF-8 support is disabled, filename handling\n                                 works exactly as in previous UnZip versions */\n  int fPrivilege;         /* 1 => restore ACLs in user mode,\n                             2 => try to use privileges for restoring ACLs */\n  LPSTR lpszZipFN;        /* zip file name */\n  LPSTR lpszExtractDir;   /* directory to extract to. This should be NULL if\n                             you are extracting to the current directory. */\n} DCL, far * LPDCL;\n\n#ifdef __cplusplus\n}\n#endif\n\n/* return codes of the (DLLPASSWORD)() callback function */\n#define IDM_REPLACE_NO     100\n#define IDM_REPLACE_TEXT   101\n#define IDM_REPLACE_YES    102\n#define IDM_REPLACE_ALL    103\n#define IDM_REPLACE_NONE   104\n#define IDM_REPLACE_RENAME 105\n#define IDM_REPLACE_HELP   106\n\n#endif /* __unzip_structs_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/unziplib.def",
    "content": ";module-definition file for Windows UnZip static Library -- used by link.exe\nLIBRARY UNZIP32  ; Library module name\n\n;DESCRIPTION 'Windows Info-ZIP UnZip Library (32 bit), by Mike White'\n\nCODE  PRELOAD FIXED\n\nDATA  PRELOAD MOVEABLE\n\nEXPORTS\n     Wiz_SingleEntryUnzip\n     UzpVersion\n     Wiz_Init\n     Wiz_SetOpts\n     Wiz_Unzip\n     Wiz_Validate\n     Wiz_NoPrinting\n     UzpVersion2\n     Wiz_UnzipToMemory\n     Wiz_Match\n     Wiz_Grep\n     UzpFreeMemBuffer\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/uzexampl.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n   This is a very simplistic example of how to load and make a call into the\n   dll. This has been compiled and tested for a 32-bit console version, but\n   not under 16-bit windows. However, the #ifdef's have been left in for the\n   16-bit code, simply as an example.\n\n */\n\n#ifndef WIN32   /* this code is currently only tested for 32-bit console */\n#  define WIN32\n#endif\n\n#if defined(__WIN32__) && !defined(WIN32)\n#  define WIN32\n#endif\n\n/* Tell Microsoft Visual C++ 2005 to leave us alone and\n * let us use standard C functions the way we're supposed to.\n */\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#  ifndef _CRT_SECURE_NO_WARNINGS\n#    define _CRT_SECURE_NO_WARNINGS\n#  endif\n#  ifndef _CRT_NONSTDC_NO_WARNINGS\n#    define _CRT_NONSTDC_NO_WARNINGS\n#  endif\n#endif\n\n#include <stddef.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <time.h>\n#include <string.h>\n#include \"uzexampl.h\"\n#include \"../unzvers.h\"\n#ifdef WIN32\n#  include <winver.h>\n#else\n#  include <ver.h>\n#endif\n\n#ifndef _MAX_PATH\n#  define _MAX_PATH 260           /* max total file or directory name path */\n#endif\n\n#ifdef WIN32\n#define UNZ_DLL_NAME \"UNZIP32.DLL\\0\"\n#else\n#define UNZ_DLL_NAME \"UNZIP16.DLL\\0\"\n#endif\n\n#define DLL_WARNING \"Cannot find %s.\"\\\n            \" The Dll must be in the application directory, the path, \"\\\n            \"the Windows directory or the Windows System directory.\"\n#define DLL_VERSION_WARNING \"%s has the wrong version number.\"\\\n            \" Insure that you have the correct dll's installed, and that \"\\\n            \"an older dll is not in your path or Windows System directory.\"\n\nint hFile;              /* file handle */\n\nLPUSERFUNCTIONS lpUserFunctions;\nHANDLE hUF = (HANDLE)NULL;\nLPDCL lpDCL = NULL;\nHANDLE hDCL = (HANDLE)NULL;\nHINSTANCE hUnzipDll;\nHANDLE hZCL = (HANDLE)NULL;\n#ifdef WIN32\nDWORD dwPlatformId = 0xFFFFFFFF;\n#endif\nstatic ZCONST UzpVer *lpUzVersInfo = NULL;\n\n\n/* Forward References */\nint WINAPI DisplayBuf(LPSTR, unsigned long);\nint WINAPI GetReplaceDlgRetVal(LPSTR, unsigned);\nint WINAPI password(LPSTR, int, LPCSTR, LPCSTR);\n\nZCONST UzpVer * UZ_EXP UzpVersion  OF((void));\n_DLL_UZVER pUzpVersion;\n_DLL_UNZIP pWiz_SingleEntryUnzip;\n\nstatic void FreeUpMemory(void);\n\nint main(int argc, char **argv)\n{\nint exfc, infc;\nchar **exfv, **infv;\nchar *x_opt;\nDWORD dwVerInfoSize;\nDWORD dwVerHnd;\nchar szFullPath[_MAX_PATH];\nint retcode;\n#ifdef WIN32\nchar *ptr;\n#else\nHFILE hfile;\nOFSTRUCT ofs;\n#endif\nHANDLE  hMem;         /* handle to mem alloc'ed */\n\nif (argc < 2)   /* We must have an archive to unzip */\n   {\n   char *progname = strrchr(argv[0], '\\\\');\n\n   if (progname != NULL)\n      progname++;\n   else\n      {\n      progname = argv[0];\n      if (progname == NULL || *progname == '\\0') progname = \"example\";\n      }\n   printf(\"usage: %s <zipfile> [entry1 [entry2 [...]]] [-x xentry1 [...]]\",\n          progname);\n   return 0;\n   }\n\nhDCL = GlobalAlloc( GPTR, (DWORD)sizeof(DCL));\nif (!hDCL)\n   {\n   return -1;\n   }\nlpDCL = (LPDCL)GlobalLock(hDCL);\nif (!lpDCL)\n   {\n   GlobalFree(hDCL);\n   return -1;\n   }\n\nhUF = GlobalAlloc( GPTR, (DWORD)sizeof(USERFUNCTIONS));\nif (!hUF)\n   {\n   GlobalUnlock(hDCL);\n   GlobalFree(hDCL);\n   return -1;\n   }\nlpUserFunctions = (LPUSERFUNCTIONS)GlobalLock(hUF);\n\nif (!lpUserFunctions)\n   {\n   GlobalFree(hUF);\n   GlobalUnlock(hDCL);\n   GlobalFree(hDCL);\n   return -1;\n   }\n\nlpUserFunctions->password = password;\nlpUserFunctions->print = DisplayBuf;\nlpUserFunctions->sound = NULL;\nlpUserFunctions->replace = GetReplaceDlgRetVal;\nlpUserFunctions->SendApplicationMessage = ReceiveDllMessage;\n\n/* First we go look for the unzip dll */\n#ifdef WIN32\nif (SearchPath(\n    NULL,               /* address of search path               */\n    UNZ_DLL_NAME,       /* address of filename                  */\n    NULL,               /* address of extension                 */\n    _MAX_PATH,           /* size, in characters, of buffer       */\n    szFullPath,         /* address of buffer for found filename */\n    &ptr                /* address of pointer to file component */\n   ) == 0)\n#else\nhfile = OpenFile(UNZ_DLL_NAME,  &ofs, OF_SEARCH);\nif (hfile == HFILE_ERROR)\n#endif\n   {\n   char str[256];\n   wsprintf (str, DLL_WARNING, UNZ_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return -1;\n   }\n#ifndef WIN32\nelse\n   lstrcpy(szFullPath, ofs.szPathName);\n_lclose(hfile);\n#endif\n\n/* Now we'll check the unzip dll version information. Note that this is\n   not the same information as is returned from a call to UzpVersion()\n */\ndwVerInfoSize =\n    GetFileVersionInfoSize(szFullPath, &dwVerHnd);\n\nif (dwVerInfoSize)\n   {\n   BOOL  fRet, fRetName;\n   char str[256];\n   LPSTR   lpstrVffInfo; /* Pointer to block to hold info */\n   LPSTR lszVer = NULL;\n   LPSTR lszVerName = NULL;\n   UINT  cchVer = 0;\n\n   /* Get a block big enough to hold the version information */\n   hMem          = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);\n   lpstrVffInfo  = GlobalLock(hMem);\n\n   /* Get the version information */\n   if (GetFileVersionInfo(szFullPath, 0L, dwVerInfoSize, lpstrVffInfo))\n      {\n      fRet = VerQueryValue(lpstrVffInfo,\n               TEXT(\"\\\\StringFileInfo\\\\040904E4\\\\FileVersion\"),\n              (LPVOID)&lszVer,\n              &cchVer);\n      fRetName = VerQueryValue(lpstrVffInfo,\n               TEXT(\"\\\\StringFileInfo\\\\040904E4\\\\CompanyName\"),\n               (LPVOID)&lszVerName,\n               &cchVer);\n      if (!fRet || !fRetName ||\n         (lstrcmpi(lszVer, UNZ_DLL_VERSION) != 0) ||\n         (lstrcmpi(lszVerName, IZ_COMPANY_NAME) != 0))\n         {\n         wsprintf (str, DLL_VERSION_WARNING, UNZ_DLL_NAME);\n         printf(\"%s\\n\", str);\n         GlobalUnlock(hMem);\n         GlobalFree(hMem);\n         FreeUpMemory();\n         return -1;\n         }\n      }\n      /* free memory */\n   GlobalUnlock(hMem);\n   GlobalFree(hMem);\n   }\nelse\n   {\n   char str[256];\n   wsprintf (str, DLL_VERSION_WARNING, UNZ_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return -1;\n   }\n/* Okay, now we know that the dll exists, and has the proper version\n * information in it. We can go ahead and load it.\n */\nhUnzipDll = LoadLibrary(UNZ_DLL_NAME);\n#ifndef WIN32\nif (hUnzipDll > HINSTANCE_ERROR)\n#else\nif (hUnzipDll != NULL)\n#endif\n   {\n   pUzpVersion =\n     (_DLL_UZVER)GetProcAddress(hUnzipDll, \"UzpVersion\");\n   pWiz_SingleEntryUnzip =\n     (_DLL_UNZIP)GetProcAddress(hUnzipDll, \"Wiz_SingleEntryUnzip\");\n   }\nelse\n   {\n   char str[256];\n   wsprintf (str, \"Could not load %s\", UNZ_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return -1;\n   }\n\n/*\n   Before we actually start with the extraction process, we should first\n   check whether the API of the loaded dll is compatible with the API\n   definition used to compile this frontend program.\n */\nlpUzVersInfo = (*pUzpVersion)();\n\n/* The UnZip WinDLL code may change quite frequently.  To be safe, we\n * require the DLL to be at least at the release level of this example\n * frontend code.\n */\n#   define UZDLL_MINVERS_MAJOR          UZ_MAJORVER\n#   define UZDLL_MINVERS_MINOR          UZ_MINORVER\n#   define UZDLL_MINVERS_PATCHLEVEL     UZ_PATCHLEVEL\n/* This UnZip DLL stub requires a DLL version of at least: */\nif ( (lpUzVersInfo->unzip.major < UZDLL_MINVERS_MAJOR) ||\n     ((lpUzVersInfo->unzip.major == UZDLL_MINVERS_MAJOR) &&\n      ((lpUzVersInfo->unzip.minor < UZDLL_MINVERS_MINOR) ||\n       ((lpUzVersInfo->unzip.minor == UZDLL_MINVERS_MINOR) &&\n        (lpUzVersInfo->unzip.patchlevel < UZDLL_MINVERS_PATCHLEVEL)\n       )\n      )\n     ) )\n{\n  char str[256];\n  wsprintf(str, \"The version %u.%u%u of the loaded UnZip DLL is too old!\",\n           lpUzVersInfo->unzip.major, lpUzVersInfo->unzip.minor,\n           lpUzVersInfo->unzip.patchlevel);\n  printf(\"%s\\n\", str);\n  FreeLibrary(hUnzipDll);\n  FreeUpMemory();\n  return -1;\n}\n\nif (lpUzVersInfo->structlen >=\n    (offsetof(UzpVer, dllapimin) + sizeof(_version_type)))\n{\n  if ( (lpUzVersInfo->dllapimin.major > UZ_WINAPI_COMP_MAJOR) ||\n       ((lpUzVersInfo->dllapimin.major == UZ_WINAPI_COMP_MAJOR) &&\n        ((lpUzVersInfo->dllapimin.minor > UZ_WINAPI_COMP_MINOR) ||\n         ((lpUzVersInfo->dllapimin.minor == UZ_WINAPI_COMP_MINOR) &&\n          (lpUzVersInfo->dllapimin.patchlevel > UZ_WINAPI_COMP_REVIS)\n         )\n        )\n       ) )\n  {\n    char str[256];\n    wsprintf(str, \"Found incompatible WinDLL API version %u.%u%u, aborting!\",\n             lpUzVersInfo->dllapimin.major, lpUzVersInfo->dllapimin.minor,\n             lpUzVersInfo->dllapimin.patchlevel);\n    printf(\"%s\\n\", str);\n    FreeLibrary(hUnzipDll);\n    FreeUpMemory();\n    return -1;\n  }\n}\n\n/*\n   Here is where the actual extraction process begins. First we set up the\n   flags to be passed into the dll.\n */\nlpDCL->StructVersID = UZ_DCL_STRUCTVER; /* version of this structure */\nlpDCL->ncflag = 0;              /* write to stdout if true */\nlpDCL->fQuiet = 0;              /* we want all messages\n                                   1 = fewer messages,\n                                   2 = no messages */\nlpDCL->ntflag = 0;              /* test zip file if true */\nlpDCL->nvflag = 0;              /* give a verbose listing if true */\nlpDCL->nzflag = 0;              /* display zip file comment if true */\nlpDCL->ndflag = 1;              /* recreate directories != 0,\n                                   skip \"../\" if < 2 */\nlpDCL->naflag = 0;              /* do not convert CR to CRLF */\nlpDCL->nfflag = 0;              /* do not freshen existing files only */\nlpDCL->noflag = 1;              /* over-write all files if true */\nlpDCL->nZIflag = 0;             /* no ZipInfo output mode */\nlpDCL->B_flag = 0;              /* do not backup existing files */\nlpDCL->C_flag = 0;              /* do not match case-insensitive */\nlpDCL->D_flag = 0;              /* restore all timestamps */\nlpDCL->U_flag = 0;              /* do not disable UTF-8 support */\nlpDCL->ExtractOnlyNewer = 0;    /* do not extract only newer */\nlpDCL->SpaceToUnderscore = 0;   /* do not convert space to '_' in filenames */\nlpDCL->PromptToOverwrite = 0;   /* \"overwrite all\" selected -> no query mode */\nlpDCL->lpszZipFN = argv[1];     /* the archive name */\nlpDCL->lpszExtractDir = NULL;   /* the directory to extract to.\n                                   This is set to NULL if you are extracting\n                                   to the current directory.\n                                 */\n/*\n   As this is a quite short example, intended primarily to show how to\n   load and call in to the dll, the command-line parameters are only\n   parsed in a very simplistic way:\n   We assume that the command-line parameters after the zip archive\n   make up a list of file patterns:\n   \" [file_i1] [file_i2] ... [file_iN] [-x file_x1 [file_x2] ...]\".\n   We scan for an argument \"-x\"; all arguments in front are\n   \"include file patterns\", all arguments after are \"exclude file patterns\".\n   If no more arguments are given, we extract ALL files.\n\n   In summary, the example program should be run like:\n   example <archive.name> [files to include] [-x files to exclude]\n   (\"<...> denotes mandatory arguments, \"[...]\" optional arguments)\n */\nx_opt = NULL;\nif (argc > 2) {\n  infv = &argv[2];\n  for (infc = 0; infc < argc-2; infc++)\n    if (!strcmp(\"-x\", infv[infc])) {\n        x_opt = infv[infc];\n        infv[infc] = NULL;\n        break;\n    }\n  exfc = argc - infc - 3;\n  if (exfc > 0)\n    exfv = &argv[infc+3];\n  else {\n    exfc = 0;\n    exfv = NULL;\n  }\n} else {\n  infc = exfc = 0;\n  infv = exfv = NULL;\n}\nretcode = (*pWiz_SingleEntryUnzip)(infc, infv, exfc, exfv, lpDCL,\n                                   lpUserFunctions);\nif (x_opt) {\n  infv[infc] = x_opt;\n  x_opt = NULL;\n}\n\nif (retcode != 0)\n   printf(\"Error unzipping (error/warning code %d)...\\n\", retcode);\n\nFreeLibrary(hUnzipDll);\nFreeUpMemory();\nreturn retcode;\n}\n\nint WINAPI GetReplaceDlgRetVal(LPSTR filename, unsigned fnbufsiz)\n{\n/* This is where you will decide if you want to replace, rename etc existing\n   files.\n */\nreturn 1;\n}\n\nstatic void FreeUpMemory(void)\n{\nif (hUF)\n   {\n   GlobalUnlock(hUF);\n   GlobalFree(hUF);\n   }\nif (hDCL)\n   {\n   GlobalUnlock(hDCL);\n   GlobalFree(hDCL);\n   }\n}\n\n/* This is a very stripped down version of what is done in Wiz. Essentially\n   what this function is for is to do a listing of an archive contents. It\n   is actually never called in this example, but a dummy procedure had to\n   be put in, so this was used.\n */\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI ReceiveDllMessage(z_uint8 ucsize, z_uint8 csiz,\n    unsigned cfactor, unsigned mo, unsigned dy, unsigned yr,\n    unsigned hh, unsigned mm, char c, LPCSTR filename,\n    LPCSTR methbuf, unsigned long crc, char fCrypt)\n#else\nvoid WINAPI ReceiveDllMessage(unsigned long ucsize, unsigned long csiz,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt)\n#endif\n{\nchar psLBEntry[_MAX_PATH];\nchar LongHdrStats[] =\n          \"%7lu  %7lu %4s  %02u-%02u-%02u  %02u:%02u  %c%s\";\nchar CompFactorStr[] = \"%c%d%%\";\nchar CompFactor100[] = \"100%%\";\nchar szCompFactor[10];\nchar sgn;\n\nif (csiz > ucsize)\n   sgn = '-';\nelse\n   sgn = ' ';\nif (cfactor == 100)\n   lstrcpy(szCompFactor, CompFactor100);\nelse\n   sprintf(szCompFactor, CompFactorStr, sgn, cfactor);\n   wsprintf(psLBEntry, LongHdrStats,\n      ucsize, csiz, szCompFactor, mo, dy, yr, hh, mm, c, filename);\n\nprintf(\"%s\\n\", psLBEntry);\n}\n\n/* Password entry routine - see password.c in the wiz directory for how\n   this is actually implemented in WiZ. If you have an encrypted file,\n   this will probably give you great pain.\n */\nint WINAPI password(LPSTR p, int n, LPCSTR m, LPCSTR name)\n{\nreturn 1;\n}\n\n/* Dummy \"print\" routine that simply outputs what is sent from the dll */\nint WINAPI DisplayBuf(LPSTR buf, unsigned long size)\n{\nprintf(\"%s\", (char *)buf);\nreturn (int)(unsigned int) size;\n}\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/uzexampl.h",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n Example header file\n\n Do not use this header file in the WiZ application, use WIZ.H\n instead.\n\n*/\n#ifndef _UZEXAMPL_H\n#define _UZEXAMPL_H\n\n#include <windows.h>\n#ifdef __RSXNT__\n#  include \"../win32/rsxntwin.h\"\n#endif\n#include <assert.h>    /* required for all Windows applications */\n#include <stdlib.h>\n#include <stdio.h>\n#include <commdlg.h>\n#ifndef __RSXNT__\n#  include <dlgs.h>\n#endif\n#include <windowsx.h>\n\n#include \"../unzip.h\"\n#include \"../windll/structs.h\"\n#include \"../windll/decs.h\"\n\n/* Defines */\n\ntypedef const UzpVer * (WINAPI * _DLL_UZVER)(void);\ntypedef int (WINAPI * _DLL_UNZIP)(int, char **, int, char **,\n                                  LPDCL, LPUSERFUNCTIONS);\n\n/* Global variables */\n\nextern LPUSERFUNCTIONS lpUserFunctions;\nextern LPDCL lpDCL;\n\nextern HINSTANCE hUnzipDll;\n\nextern int hFile;                 /* file handle             */\n\n/* Global functions */\n\nint WINAPI DisplayBuf(LPSTR, unsigned long);\n\n/* Procedure Calls */\n#ifdef Z_UINT8_DEFINED\nvoid WINAPI ReceiveDllMessage(z_uint8 ucsize, z_uint8 csize,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n#else\nvoid WINAPI ReceiveDllMessage(unsigned long ucsize, unsigned long csize,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n#endif\nvoid WINAPI ReceiveDllMessage_NO_INT64(unsigned long ucsiz_l,\n    unsigned long ucsiz_h, unsigned long csiz_l, unsigned long csiz_h,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n#endif /* _UZEXAMPL_H */\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vb/VBReadMe.txt",
    "content": "On Windows, please read this file using WordPad to format lines properly.\n\nThis directory contains a short example on how to use the Win32 UnZip DLL\nwith Visual Basic.  The example code consists of a simple dialog form and\na standard module containing the interface code to call unzip32.dll.\nThe code assumes that the unzip32.dll binary is available somewhere on the\nexecution path. The easiest way to satisfy this rule is to keep a copy of\nunzip32.dll in the directory where the VB executable is stored, but if\nit's in the command path it should be found.\nNOTE: Whenever a VB program is run from the VB6 IDE, the \"path of the VB\nexecutable\" is the path where the IDE program file \"VB6.EXE\" is stored,\nNOT the storage directory of the VB project file (= result of the App.Path\nproperty accessed from within the VB program).\n\nThe example code has been edited last with Visual Basic 6, but should be\ncompatible with VB 5. To maintain compatibility with VB5 after having modified\nthe example project in VB6, the project file has to be edited using a standard\ntext editor (e.g.: Notepad), to remove the line specifying the \"Retained\"\nproperty.  This property line is not recognized by VB 5 and would prevent\ncorrect loading of the project in VB 5.\n\nThis VB example makes use of the \"Windows Common Dialogs\" ActiveX control\ncomdlg32.ocx, supplied with Visual Basic. Unfortunately, there are different\nrevisions of this control available which are not binary compatible. In order\nto maintain compatibility of the source code with all available versions of\ncomdlg32.ocx, the source files may have to be edited manually after the\nprogram has been saved from the VB environment on a system containing the\nlatest release of comdlg32.ocx:\n\nBoth vbunzip.frm and vbunzip.vbp should contain a reference line for the\ncommon dialog ocx reading like:\nObject = \"{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.1#0\"; \"COMDLG32.OCX\"\n                                                 ^^^\nThe important section of this line is the revision number \"1.1\" (marked by\nthe \"^^^\" signs). On a system with a more recent version of comdlg32.ocx\ninstalled, this version number is updated to \"1.2\" (or higher) by VB\nautomatically. This number has to be changed back to \"1.1\" manually,\notherwise the example code can no longer be used on systems with old versions\nof comdlg32.ocx.\n\nWhen fetching the VB example code from the UnZip source distribution, one\nhas to make sure that the files are stored in the correct \"DOS/Windows-native\"\ntext format with \"CR-LF\" line endings. Visual Basic does not accept Unix style\ntext format (LF line terminators) for Form class modules (*.frm) and the\nproject file (*.vbp).  You may use unzip's -a option to convert the project\non extraction. If this is a full source distribution, see the Where file for\nwhere to download the compiled unzip DLL for a specific platform which includes\nthis example project in native format for that platform.\n\nFor more information, see the comments within the VB source.\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vb/vbunzip.bas",
    "content": "Attribute VB_Name = \"VBUnzBas\"\nOption Explicit\n\n'-- Please Do Not Remove These Comment Lines!\n'----------------------------------------------------------------\n'-- Sample VB 5 / VB 6 code to drive unzip32.dll\n'-- Contributed to the Info-ZIP project by Mike Le Voi\n'--\n'-- Contact me at: mlevoi@modemss.brisnet.org.au\n'--\n'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'----------------------------------------------------------------\n'--\n'-- This Source Code Is Freely Available From The Info-ZIP Project\n'-- Web Server At:\n'-- ftp://ftp.info-zip.org/pub/infozip/infozip.html\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White\n'-- And The Fine People Of The Info-ZIP Group\n'-- For Letting Me Use And Modify Their Original\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'-- For Your Hard Work In Helping Me Get This To Work!!!\n'---------------------------------------------------------------\n'--\n'-- Contributed To The Info-ZIP Project By Raymond L. King.\n'-- Modified June 21, 1998\n'-- By Raymond L. King\n'-- Custom Software Designers\n'--\n'-- Contact Me At: king@ntplx.net\n'-- ICQ 434355\n'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\n'--\n'---------------------------------------------------------------\n'--\n'-- Modified August 17, 1998\n'--  by Christian Spieler\n'--  (implemented sort of a \"real\" user interface)\n'-- Modified May 11, 2003\n'--  by Christian Spieler\n'--  (use late binding for referencing the common dialog)\n'-- Modified February 01, 2008\n'--  by Christian Spieler\n'--  (adapted DLL interface changes, fixed UZDLLPass callback)\n'-- Modified December 08, 2008 to December 30, 2008\n'--  by Ed Gordon\n'--  Updated sample project for UnZip 6.0 unzip32.dll\n'--  (support UnZip 6.0 flags and structures)\n'-- Modified January 03, 2009\n'--  by Christian Spieler\n'--  (better solution for overwrite_all handling, use Double\n'--  instead of Currency to stay safe against number overflow,\n'--  corrected UZDLLServ_I32() calling interface,\n'--  removed code that is unsupported under VB5)\n'--\n'---------------------------------------------------------------\n\n'-- Expected Version data for the DLL compatibility check\n'\n'   For consistency of the version checking algorithm, the version number\n'   constants \"UzDLL_MinVer\" and \"UzDLL_MaxAPI\" have to fullfil the\n'   condition \"UzDLL_MinVer <= \"UzDLL_MaxAPI\".\n'   Version data supplied by a specific UnZip DLL always obey the\n'   relation  \"UzDLL Version\" >= \"UzDLL API\".\n\n'Oldest UnZip DLL version that is supported by this program\nPrivate Const cUzDLL_MinVer_Major As Byte = 6\nPrivate Const cUzDLL_MinVer_Minor As Byte = 0\nPrivate Const cUzDLL_MinVer_Revis As Byte = 0\n\n'Last (newest) UnZip DLL API version that is known (and supported)\n'by this program\nPrivate Const cUzDLL_MaxAPI_Major As Byte = 6\nPrivate Const cUzDLL_MaxAPI_Minor As Byte = 0\nPrivate Const cUzDLL_MaxAPI_Revis As Byte = 0\n\n'Current structure version ID of the DCLIST structure layout\nPrivate Const cUz_DCLStructVer As Long = &H600\n\n'-- C Style argv\nPrivate Type UNZIPnames\n  uzFiles(0 To 99) As String\nEnd Type\n\n'-- Callback Large \"String\"\nPrivate Type UNZIPCBChar\n  ch(32800) As Byte\nEnd Type\n\n'-- Callback Small \"String\"\nPrivate Type UNZIPCBCh\n  ch(256) As Byte\nEnd Type\n\n'-- UNZIP32.DLL DCL Structure\nPrivate Type DCLIST\n  StructVersID      As Long    ' Currently version &H600 of this structure\n  ExtractOnlyNewer  As Long    ' 1 = Extract Only Newer/New, Else 0\n  SpaceToUnderscore As Long    ' 1 = Convert Space To Underscore, Else 0\n  PromptToOverwrite As Long    ' 1 = Prompt To Overwrite Required, Else 0\n  fQuiet            As Long    ' 2 = No Messages, 1 = Less, 0 = All\n  ncflag            As Long    ' 1 = Write To Stdout, Else 0\n  ntflag            As Long    ' 1 = Test Zip File, Else 0\n  nvflag            As Long    ' 0 = Extract, 1 = List Zip Contents\n  nfflag            As Long    ' 1 = Extract Only Newer Over Existing, Else 0\n  nzflag            As Long    ' 1 = Display Zip File Comment, Else 0\n  ndflag            As Long    ' 0 = Junk paths, 1 = safe path components only, 2 = all\n  noflag            As Long    ' 1 = Overwrite Files, Else 0\n  naflag            As Long    ' 1 = Convert CR To CRLF, Else 0\n  nZIflag           As Long    ' 1 = Zip Info Verbose, Else 0\n  B_flag            As Long    ' 1 = Backup existing files, Else 0\n  C_flag            As Long    ' 1 = Case Insensitivity, 0 = Case Sensitivity\n  D_flag            As Long    ' Timestamp restoration, 0 = All, 1 = Files, 2 = None\n  U_flag            As Long    ' 0 = Unicode enabled, 1 = Escape chars, 2 = No Unicode\n  fPrivilege        As Long    ' 1 = ACL, 2 = Privileges\n  Zip               As String  ' The Zip Filename To Extract Files\n  ExtractDir        As String  ' The Extraction Directory, NULL If Extracting To Current Dir\nEnd Type\n\n'-- UNZIP32.DLL Userfunctions Structure\nPrivate Type USERFUNCTION\n  UZDLLPrnt         As Long     ' Pointer To Apps Print Function\n  UZDLLSND          As Long     ' Pointer To Apps Sound Function\n  UZDLLREPLACE      As Long     ' Pointer To Apps Replace Function\n  UZDLLPASSWORD     As Long     ' Pointer To Apps Password Function\n  ' 64-bit versions (VB6 does not support passing 64-bit values!)\n  UZDLLMESSAGE      As Long     ' Pointer To Apps Message Function (Not Used!)\n  UZDLLSERVICE      As Long     ' Pointer To Apps Service Function (Not Used!)\n  ' 32-bit versions\n  UZDLLMESSAGE_I32  As Long     ' Pointer To Apps Message Function\n  UZDLLSERVICE_I32  As Long     ' Pointer To Apps Service Function\n  ' All 64-bit values passed as low and high parts!\n  TotalSizeComp_Lo  As Long     ' Total Size Of Zip Archive (low 32 bits)\n  TotalSizeComp_Hi  As Long     ' Total Size Of Zip Archive (high 32 bits)\n  TotalSize_Lo      As Long     ' Total Size Of All Files In Archive (low 32)\n  TotalSize_Hi      As Long     ' Total Size Of All Files In Archive (high 32)\n  NumMembers_Lo     As Long     ' Total Number Of All Files In The Archive (low 32)\n  NumMembers_Hi     As Long     ' Total Number Of All Files In The Archive (high 32)\n  CompFactor        As Long     ' Compression Factor\n  cchComment        As Integer  ' Flag If Archive Has A Comment!\nEnd Type\n\n'-- UNZIP32.DLL Version Structure\nPrivate Type UZPVER2\n  structlen       As Long         ' Length Of The Structure Being Passed\n  flag            As Long         ' Bit 0: is_beta  bit 1: uses_zlib\n  beta            As String * 10  ' e.g., \"g BETA\" or \"\"\n  date            As String * 20  ' e.g., \"4 Sep 95\" (beta) or \"4 September 1995\"\n  zlib            As String * 10  ' e.g., \"1.0.5\" or NULL\n  unzip(1 To 4)   As Byte         ' Version Type Unzip\n  zipinfo(1 To 4) As Byte         ' Version Type Zip Info\n  os2dll          As Long         ' Version Type OS2 DLL\n  windll(1 To 4)  As Byte         ' Version Type Windows DLL\n  dllapimin(1 To 4) As Byte       ' Version Type DLL API minimum compatibility\nEnd Type\n\n'-- This assumes UNZIP32.DLL is somewhere on your execution path!\n'-- The term \"execution path\" means a search in the following locations,\n'-- in the listed sequence (for more details look up the documentation\n'-- of the LoadLibrary() Win32 API call):\n'--  1) the directory from which the VB6 application was loaded,\n'--  2) your current working directory in effect when the VB6 program\n'--     tries to access a first API call of UNZIP32.DLL,\n'--  3) the Windows \"SYSTEM32\" (only NT/2K/XP...) and \"SYSTEM\" directories,\n'--     and the Windows directory,\n'--  4) the folder list of your command path (e.g. check the environment\n'--     variable PATH as set in a console window started from scratch).\n'-- Normally, the Windows system directory is on your command path,\n'-- so installing the UNZIP32.DLL in the Windows System Directory\n'-- should always work.\n'--\n'-- WARNING:\n'-- When a VB6 program is run in the VB6 IDE, the \"directory from which the\n'-- application was loaded\" is the\n'--  ===>>> directory where VB6.EXE is stored (!!!),\n'-- not the storage directory of the VB project file\n'-- (the folder returned by \"App.Path\").\n'-- When a compiled VB6 program is run, the \"application load directory\"\n'-- is identical with the folder reported by \"App.Path\".\n'--\nPrivate Declare Function Wiz_SingleEntryUnzip Lib \"unzip32.dll\" _\n  (ByVal ifnc As Long, ByRef ifnv As UNZIPnames, _\n   ByVal xfnc As Long, ByRef xfnv As UNZIPnames, _\n   dcll As DCLIST, Userf As USERFUNCTION) As Long\n\nPrivate Declare Function UzpVersion2 Lib \"unzip32.dll\" _\n  (uzpv As UZPVER2) As Long\n\n'-- Private variable holding the API version id as reported by the\n'-- loaded UnZip DLL\nPrivate m_UzDllApiVers As Long\n\n'-- Private Variables For Structure Access\nPrivate UZDCL  As DCLIST\nPrivate UZUSER As USERFUNCTION\nPrivate UZVER2 As UZPVER2\n\n'-- Public Variables For Setting The\n'-- UNZIP32.DLL DCLIST Structure\n'-- These Must Be Set Before The Actual Call To VBUnZip32\nPublic uExtractOnlyNewer As Long     ' 1 = Extract Only Newer/New, Else 0\nPublic uSpaceUnderScore  As Long     ' 1 = Convert Space To Underscore, Else 0\nPublic uPromptOverWrite  As Long     ' 1 = Prompt To Overwrite Required, Else 0\nPublic uQuiet            As Long     ' 2 = No Messages, 1 = Less, 0 = All\nPublic uWriteStdOut      As Long     ' 1 = Write To Stdout, Else 0\nPublic uTestZip          As Long     ' 1 = Test Zip File, Else 0\nPublic uExtractList      As Long     ' 0 = Extract, 1 = List Contents\nPublic uFreshenExisting  As Long     ' 1 = Update Existing by Newer, Else 0\nPublic uDisplayComment   As Long     ' 1 = Display Zip File Comment, Else 0\nPublic uHonorDirectories As Long     ' 1 = Honor Directories, Else 0\nPublic uOverWriteFiles   As Long     ' 1 = Overwrite Files, Else 0\nPublic uConvertCR_CRLF   As Long     ' 1 = Convert CR To CRLF, Else 0\nPublic uVerbose          As Long     ' 1 = Zip Info Verbose\nPublic uCaseSensitivity  As Long     ' 1 = Case Insensitivity, 0 = Case Sensitivity\nPublic uPrivilege        As Long     ' 1 = ACL, 2 = Privileges, Else 0\nPublic uZipFileName      As String   ' The Zip File Name\nPublic uExtractDir       As String   ' Extraction Directory, Null If Current Directory\n\n'-- Public Program Variables\nPublic uZipNumber    As Long         ' Zip File Number\nPublic uNumberFiles  As Long         ' Number Of Files\nPublic uNumberXFiles As Long         ' Number Of Extracted Files\nPublic uZipMessage   As String       ' For Zip Message\nPublic uZipInfo      As String       ' For Zip Information\nPublic uZipNames     As UNZIPnames   ' Names Of Files To Unzip\nPublic uExcludeNames As UNZIPnames   ' Names Of Zip Files To Exclude\nPublic uVbSkip       As Boolean      ' For DLL Password Function\n\n'-- Puts A Function Pointer In A Structure\n'-- For Callbacks.\nPublic Function FnPtr(ByVal lp As Long) As Long\n\n  FnPtr = lp\n\nEnd Function\n\n'-- Callback For UNZIP32.DLL - Receive Message Function\nPublic Sub UZReceiveDLLMessage_I32( _\n    ByVal ucsize_lo As Long, _\n    ByVal ucsize_hi As Long, _\n    ByVal csiz_lo As Long, _\n    ByVal csiz_hi As Long, _\n    ByVal cfactor As Integer, _\n    ByVal mo As Integer, _\n    ByVal dy As Integer, _\n    ByVal yr As Integer, _\n    ByVal hh As Integer, _\n    ByVal mm As Integer, _\n    ByVal c As Byte, _\n    ByRef fname As UNZIPCBCh, _\n    ByRef meth As UNZIPCBCh, _\n    ByVal crc As Long, _\n    ByVal fCrypt As Byte)\n\n  Dim s0     As String\n  Dim xx     As Long\n  Dim cCh    As Byte\n  Dim strout As String * 80\n  Dim ucsize As Double\n  Dim csiz   As Double\n\n  '-- Always implement a runtime error handler in Callback Routines!\n  On Error Resume Next\n\n  '------------------------------------------------\n  '-- This Is Where The Received Messages Are\n  '-- Printed Out And Displayed.\n  '-- You Can Modify Below!\n  '------------------------------------------------\n\n  strout = Space$(80)\n\n  '-- For Zip Message Printing\n  If uZipNumber = 0 Then\n    Mid$(strout, 1, 50) = \"Filename:\"\n    Mid$(strout, 53, 4) = \"Size\"\n    Mid$(strout, 62, 4) = \"Date\"\n    Mid$(strout, 71, 4) = \"Time\"\n    uZipMessage = strout & vbNewLine\n    strout = Space$(80)\n  End If\n\n  s0 = \"\"\n\n  '-- Do Not Change This For Next!!!\n  For xx = 0 To UBound(fname.ch)\n    If fname.ch(xx) = 0 Then Exit For\n    s0 = s0 & Chr$(fname.ch(xx))\n  Next\n\n  ucsize = CnvI64Struct2Dbl(ucsize_lo, ucsize_hi)\n  csiz = CnvI64Struct2Dbl(csiz_lo, csiz_hi)\n\n  '-- Assign Zip Information For Printing\n  Mid$(strout, 1, 50) = Mid$(s0, 1, 50)\n  Mid$(strout, 51, 9) = Right$(\"        \" & CStr(ucsize), 9)\n  Mid$(strout, 62, 3) = Right$(\"0\" & Trim$(CStr(mo)), 2) & \"/\"\n  Mid$(strout, 65, 3) = Right$(\"0\" & Trim$(CStr(dy)), 2) & \"/\"\n  Mid$(strout, 68, 2) = Right$(\"0\" & Trim$(CStr(yr)), 2)\n  Mid$(strout, 72, 3) = Right$(Str$(hh), 2) & \":\"\n  Mid$(strout, 75, 2) = Right$(\"0\" & Trim$(CStr(mm)), 2)\n\n  ' Mid$(strout, 77, 2) = Right$(\" \" & CStr(cfactor), 2)\n  ' Mid$(strout, 80, 8) = Right$(\"        \" & CStr(csiz), 8)\n  ' s0 = \"\"\n  ' For xx = 0 To 255\n  '     If meth.ch(xx) = 0 Then Exit For\n  '     s0 = s0 & Chr$(meth.ch(xx))\n  ' Next xx\n\n  '-- Do Not Modify Below!!!\n  uZipMessage = uZipMessage & strout & vbNewLine\n  uZipNumber = uZipNumber + 1\n\nEnd Sub\n\n'-- Callback For UNZIP32.DLL - Print Message Function\nPublic Function UZDLLPrnt(ByRef fname As UNZIPCBChar, ByVal x As Long) As Long\n\n  Dim s0 As String\n  Dim xx As Long\n  Dim cCh As Byte\n\n  '-- Always implement a runtime error handler in Callback Routines!\n  On Error Resume Next\n\n  s0 = \"\"\n\n  '-- Gets The UNZIP32.DLL Message For Displaying.\n  For xx = 0 To x - 1\n    cCh = fname.ch(xx)\n    Select Case cCh\n    Case 0\n      Exit For\n    Case 10\n      s0 = s0 & vbNewLine     ' Damn UNIX :-)\n    Case 92 ' = Asc(\"\\\")\n      s0 = s0 & \"/\"\n    Case Else\n      s0 = s0 & Chr$(cCh)\n    End Select\n  Next\n\n  '-- Assign Zip Information\n  uZipInfo = uZipInfo & s0\n\n  UZDLLPrnt = 0\n\nEnd Function\n\n'-- Callback For UNZIP32.DLL - DLL Service Function\nPublic Function UZDLLServ_I32(ByRef mname As UNZIPCBChar, _\n         ByVal lUcSiz_Lo As Long, ByVal lUcSiz_Hi As Long) As Long\n\n  Dim UcSiz As Double\n  Dim s0 As String\n  Dim xx As Long\n\n  '-- Always implement a runtime error handler in Callback Routines!\n  On Error Resume Next\n\n  ' Parameters lUcSiz_Lo and lUcSiz_Hi contain the uncompressed size\n  ' of the extracted archive entry.\n  ' This information may be used for some kind of progress display...\n  UcSiz = CnvI64Struct2Dbl(lUcSiz_Lo, lUcSiz_Hi)\n\n  s0 = \"\"\n  '-- Get Zip32.DLL Message For processing\n  For xx = 0 To UBound(mname.ch)\n    If mname.ch(xx) = 0 Then Exit For\n    s0 = s0 & Chr$(mname.ch(xx))\n  Next\n  ' At this point, s0 contains the message passed from the DLL\n  ' (like the current file being extracted)\n  ' It is up to the developer to code something useful here :)\n\n  UZDLLServ_I32 = 0 ' Setting this to 1 will abort the zip!\n\nEnd Function\n\n'-- Callback For UNZIP32.DLL - Password Function\nPublic Function UZDLLPass(ByRef pwbuf As UNZIPCBCh, _\n  ByVal bufsiz As Long, ByRef promptmsg As UNZIPCBCh, _\n  ByRef entryname As UNZIPCBCh) As Long\n\n  Dim prompt     As String\n  Dim xx         As Long\n  Dim szpassword As String\n\n  '-- Always implement a runtime error handler in Callback Routines!\n  On Error Resume Next\n\n  UZDLLPass = -1  'IZ_PW_CANCEL\n\n  If uVbSkip Then Exit Function\n\n  '-- Get the Password prompt\n  For xx = 0 To UBound(promptmsg.ch)\n    If promptmsg.ch(xx) = 0 Then Exit For\n    prompt = prompt & Chr$(promptmsg.ch(xx))\n  Next\n  If Len(prompt) = 0 Then\n    prompt = \"Please Enter The Password!\"\n  Else\n    prompt = prompt & \" \"\n    For xx = 0 To UBound(entryname.ch)\n      If entryname.ch(xx) = 0 Then Exit For\n      prompt = prompt & Chr$(entryname.ch(xx))\n    Next\n  End If\n\n  '-- Get The Zip File Password\n  Do\n    szpassword = InputBox(prompt)\n    If Len(szpassword) < bufsiz Then Exit Do\n    ' -- Entered password exceeds UnZip's password buffer size\n    If MsgBox(\"The supplied password exceeds the maximum password length \" _\n            & CStr(bufsiz - 1) & \" supported by the UnZip DLL.\" _\n            , vbExclamation + vbRetryCancel, \"UnZip password too long\") _\n         = vbCancel Then\n      szpassword = \"\"\n      Exit Do\n    End If\n  Loop\n\n  '-- No Password So Exit The Function\n  If Len(szpassword) = 0 Then\n    uVbSkip = True\n    Exit Function\n  End If\n\n  '-- Zip File Password So Process It\n  For xx = 0 To bufsiz - 1\n    pwbuf.ch(xx) = 0\n  Next\n  '-- Password length has already been checked, so\n  '-- it will fit into the communication buffer.\n  For xx = 0 To Len(szpassword) - 1\n    pwbuf.ch(xx) = Asc(Mid$(szpassword, xx + 1, 1))\n  Next\n\n  pwbuf.ch(xx) = 0 ' Put Null Terminator For C\n\n  UZDLLPass = 0   ' IZ_PW_ENTERED\n\nEnd Function\n\n'-- Callback For UNZIP32.DLL - Report Function To Overwrite Files.\n'-- This Function Will Display A MsgBox Asking The User\n'-- If They Would Like To Overwrite The Files.\nPublic Function UZDLLReplacePrmt(ByRef fname As UNZIPCBChar, _\n                                 ByVal fnbufsiz As Long) As Long\n\n  Dim s0 As String\n  Dim xx As Long\n  Dim cCh As Byte\n  Dim bufmax As Long\n\n  '-- Always implement a runtime error handler in Callback Routines!\n  On Error Resume Next\n\n  UZDLLReplacePrmt = 100   ' 100 = Do Not Overwrite - Keep Asking User\n  s0 = \"\"\n  bufmax = UBound(fname.ch)\n  If bufmax >= fnbufsiz Then bufmax = fnbufsiz - 1\n\n  For xx = 0 To bufmax\n    cCh = fname.ch(xx)\n    Select Case cCh\n    Case 0\n      Exit For\n    Case 92 ' = Asc(\"\\\")\n      s0 = s0 & \"/\"\n    Case Else\n      s0 = s0 & Chr$(cCh)\n    End Select\n  Next\n\n  '-- This Is The MsgBox Code\n  xx = MsgBox(\"Overwrite \"\"\" & s0 & \"\"\" ?\", vbExclamation Or vbYesNoCancel, _\n              \"VBUnZip32 - File Already Exists!\")\n  Select Case xx\n  Case vbYes\n    UZDLLReplacePrmt = 102    ' 102 = Overwrite, 103 = Overwrite All\n  Case vbCancel\n    UZDLLReplacePrmt = 104    ' 104 = Overwrite None\n  Case Else\n    'keep the default as set at function entry.\n  End Select\n\nEnd Function\n\n'-- ASCIIZ To String Function\nPublic Function szTrim(szString As String) As String\n\n  Dim pos As Long\n\n  pos = InStr(szString, vbNullChar)\n\n  Select Case pos\n    Case Is > 1\n      szTrim = Trim$(Left$(szString, pos - 1))\n    Case 1\n      szTrim = \"\"\n    Case Else\n      szTrim = Trim$(szString)\n  End Select\n\nEnd Function\n\n'-- convert a 64-bit int divided in two Int32 variables into\n'-- a single 64-bit floating-point value\nPrivate Function CnvI64Struct2Dbl(ByVal lInt64Lo As Long, lInt64Hi As Long) As Double\n  If lInt64Lo < 0 Then\n    CnvI64Struct2Dbl = 2# ^ 32 + CDbl(lInt64Lo)\n  Else\n    CnvI64Struct2Dbl = CDbl(lInt64Lo)\n  End If\n  CnvI64Struct2Dbl = CnvI64Struct2Dbl + (2# ^ 32) * CDbl(lInt64Hi)\nEnd Function\n\n'-- Concatenate a \"structured\" version number into a single integer value,\n'-- to facilitate version number comparisons\n'-- (In case the practically used NumMajor numbers will ever exceed 128, it\n'-- should be considered to use the number type \"Double\" to store the\n'-- concatenated number. \"Double\" can store signed integer numbers up to a\n'-- width of 52 bits without loss of precision.)\nPrivate Function ConcatVersNums(ByVal NumMajor As Byte, ByVal NumMinor As Byte _\n                              , ByVal NumRevis As Byte, ByVal NumBuild As Byte) As Long\n  If (NumMajor And &H80) <> 0 Then\n    ConcatVersNums = (NumMajor And &H7F) * (2 ^ 24) Or &H80000000\n  Else\n    ConcatVersNums = NumMajor * (2 ^ 24)\n  End If\n  ConcatVersNums = ConcatVersNums _\n                 + NumMinor * (2 ^ 16) _\n                 + NumRevis * (2 ^ 8) _\n                 + NumBuild\nEnd Function\n\n'-- Helper function to provide a printable version number string, using the\n'-- current formatting rule for version number display as implemented in UnZip.\nPrivate Function VersNumsToTxt(ByVal NumMajor As Byte, ByVal NumMinor As Byte _\n                             , ByVal NumRevis As Byte) As String\n  VersNumsToTxt = CStr(NumMajor) & \".\" & Hex$(NumMinor)\n  If NumRevis <> 0 Then VersNumsToTxt = VersNumsToTxt & Hex$(NumRevis)\nEnd Function\n\n'-- Helper function to convert a \"concatenated\" version id into a printable\n'-- version number string, using the current formatting rule for version number\n'-- display as implemented in UnZip.\nPrivate Function VersIDToTxt(ByVal VersionID As Long) As String\n  Dim lNumTemp As Long\n\n  lNumTemp = VersionID \\ (2 ^ 24)\n  If lNumTemp < 0 Then lNumTemp = 256 + lNumTemp\n  VersIDToTxt = CStr(lNumTemp) & \".\" _\n             & Hex$((VersionID And &HFF0000) \\ &H10000)\n  lNumTemp = (VersionID And &HFF00&) \\ &H100\n  If lNumTemp <> 0 Then VersIDToTxt = VersIDToTxt & Hex$(lNumTemp)\nEnd Function\n\n'-- Main UNZIP32.DLL UnZip32 Subroutine\n'-- (WARNING!) Do Not Change!\nPublic Sub VBUnZip32()\n\n  Dim retcode As Long\n  Dim MsgStr As String\n  Dim TotalSizeComp As Double\n  Dim TotalSize As Double\n  Dim NumMembers As Double\n\n  '-- Set The UNZIP32.DLL Options\n  '-- (WARNING!) Do Not Change\n  UZDCL.StructVersID = cUz_DCLStructVer      ' Current version of this structure\n  UZDCL.ExtractOnlyNewer = uExtractOnlyNewer ' 1 = Extract Only Newer/New\n  UZDCL.SpaceToUnderscore = uSpaceUnderScore ' 1 = Convert Space To Underscore\n  UZDCL.PromptToOverwrite = uPromptOverWrite ' 1 = Prompt To Overwrite Required\n  UZDCL.fQuiet = uQuiet                      ' 2 = No Messages 1 = Less 0 = All\n  UZDCL.ncflag = uWriteStdOut                ' 1 = Write To Stdout\n  UZDCL.ntflag = uTestZip                    ' 1 = Test Zip File\n  UZDCL.nvflag = uExtractList                ' 0 = Extract 1 = List Contents\n  UZDCL.nfflag = uFreshenExisting            ' 1 = Update Existing by Newer\n  UZDCL.nzflag = uDisplayComment             ' 1 = Display Zip File Comment\n  UZDCL.ndflag = uHonorDirectories           ' 1 = Honour Directories\n  UZDCL.noflag = uOverWriteFiles             ' 1 = Overwrite Files\n  UZDCL.naflag = uConvertCR_CRLF             ' 1 = Convert CR To CRLF\n  UZDCL.nZIflag = uVerbose                   ' 1 = Zip Info Verbose\n  UZDCL.C_flag = uCaseSensitivity            ' 1 = Case insensitivity, 0 = Case Sensitivity\n  UZDCL.fPrivilege = uPrivilege              ' 1 = ACL 2 = Priv\n  UZDCL.Zip = uZipFileName                   ' ZIP Filename\n  UZDCL.ExtractDir = uExtractDir             ' Extraction Directory, NULL If Extracting\n                                             ' To Current Directory\n\n  '-- Set Callback Addresses\n  '-- (WARNING!!!) Do Not Change\n  UZUSER.UZDLLPrnt = FnPtr(AddressOf UZDLLPrnt)\n  UZUSER.UZDLLSND = 0&    '-- Not Supported\n  UZUSER.UZDLLREPLACE = FnPtr(AddressOf UZDLLReplacePrmt)\n  UZUSER.UZDLLPASSWORD = FnPtr(AddressOf UZDLLPass)\n  UZUSER.UZDLLMESSAGE_I32 = FnPtr(AddressOf UZReceiveDLLMessage_I32)\n  UZUSER.UZDLLSERVICE_I32 = FnPtr(AddressOf UZDLLServ_I32)\n\n  '-- Set UNZIP32.DLL Version Space\n  '-- (WARNING!!!) Do Not Change\n  With UZVER2\n    .structlen = Len(UZVER2)\n    .beta = String$(10, vbNullChar)\n    .date = String$(20, vbNullChar)\n    .zlib = String$(10, vbNullChar)\n  End With\n\n  '-- Get Version\n  retcode = UzpVersion2(UZVER2)\n  If retcode <> 0 Then\n    MsgBox \"Incompatible DLL version discovered!\" & vbNewLine _\n         & \"The UnZip DLL requires a version structure of length \" _\n         & CStr(retcode) & \", but the VB frontend expects the DLL to need \" _\n         & Len(UZVER2) & \"bytes.\" & vbNewLine _\n         & vbNewLine & \"The program cannot continue.\" _\n         , vbCritical + vbOKOnly, App.Title\n    Exit Sub\n  End If\n\n  ' Check that the DLL version is sufficiently recent\n  If (ConcatVersNums(UZVER2.unzip(1), UZVER2.unzip(2) _\n                  , UZVER2.unzip(3), UZVER2.unzip(4)) < _\n      ConcatVersNums(cUzDLL_MinVer_Major, cUzDLL_MinVer_Minor _\n                  , cUzDLL_MinVer_Revis, 0)) Then\n    ' The found UnZip DLL is too old!\n    MsgBox \"Incompatible old DLL version discovered!\" & vbNewLine _\n         & \"This program requires an UnZip DLL version of at least \" _\n         & VersNumsToTxt(cUzDLL_MinVer_Major, cUzDLL_MinVer_Minor, cUzDLL_MinVer_Revis) _\n         & \", but the version reported by the found DLL is only \" _\n         & VersNumsToTxt(UZVER2.unzip(1), UZVER2.unzip(2), UZVER2.unzip(3)) _\n         & \".\" & vbNewLine _\n         & vbNewLine & \"The program cannot continue.\" _\n         , vbCritical + vbOKOnly, App.Title\n    Exit Sub\n  End If\n\n  ' Concatenate the DLL API version info into a single version id variable.\n  ' This variable may be used later on to switch between different\n  ' known variants of specific API calls or API structures.\n  m_UzDllApiVers = ConcatVersNums(UZVER2.dllapimin(1), UZVER2.dllapimin(2) _\n                                , UZVER2.dllapimin(3), UZVER2.dllapimin(4))\n  ' check that the DLL API version is not too new\n  If (m_UzDllApiVers > _\n      ConcatVersNums(cUzDLL_MaxAPI_Major, cUzDLL_MaxAPI_Minor _\n                  , cUzDLL_MaxAPI_Revis, 0)) Then\n    ' The found UnZip DLL is too new!\n    MsgBox \"DLL version with incompatible API discovered!\" & vbNewLine _\n         & \"This program can only handle UnZip DLL API versions up to \" _\n         & VersNumsToTxt(cUzDLL_MaxAPI_Major, cUzDLL_MaxAPI_Minor, cUzDLL_MaxAPI_Revis) _\n         & \", but the found DLL reports a newer API version of \" _\n         & VersIDToTxt(m_UzDllApiVers) & \".\" & vbNewLine _\n         & vbNewLine & \"The program cannot continue.\" _\n         , vbCritical + vbOKOnly, App.Title\n    Exit Sub\n  End If\n\n  '--------------------------------------\n  '-- You Can Change This For Displaying\n  '-- The Version Information!\n  '--------------------------------------\n  MsgStr$ = \"DLL Date: \" & szTrim(UZVER2.date)\n  MsgStr$ = MsgStr$ & vbNewLine$ & \"Zip Info: \" _\n       & VersNumsToTxt(UZVER2.zipinfo(1), UZVER2.zipinfo(2), UZVER2.zipinfo(3))\n  MsgStr$ = MsgStr$ & vbNewLine$ & \"DLL Version: \" _\n       & VersNumsToTxt(UZVER2.windll(1), UZVER2.windll(2), UZVER2.windll(3))\n  MsgStr$ = MsgStr$ & vbNewLine$ & \"DLL API Compatibility: \" _\n       & VersIDToTxt(m_UzDllApiVers)\n  MsgStr$ = MsgStr$ & vbNewLine$ & \"--------------\"\n  '-- End Of Version Information.\n\n  '-- Go UnZip The Files! (Do Not Change Below!!!)\n  '-- This Is The Actual UnZip Routine\n  retcode = Wiz_SingleEntryUnzip(uNumberFiles, uZipNames, uNumberXFiles, _\n                                 uExcludeNames, UZDCL, UZUSER)\n  '---------------------------------------------------------------\n\n  '-- If There Is An Error Display A MsgBox!\n  If retcode <> 0 Then _\n    MsgBox \"UnZip DLL call returned error code #\" & CStr(retcode) _\n          , vbExclamation, App.Title\n\n  '-- Add up 64-bit values\n  TotalSizeComp = CnvI64Struct2Dbl(UZUSER.TotalSizeComp_Lo, _\n                                   UZUSER.TotalSizeComp_Hi)\n  TotalSize = CnvI64Struct2Dbl(UZUSER.TotalSize_Lo, _\n                               UZUSER.TotalSize_Hi)\n  NumMembers = CnvI64Struct2Dbl(UZUSER.NumMembers_Lo, _\n                                UZUSER.NumMembers_Hi)\n\n  '-- You Can Change This As Needed!\n  '-- For Compression Information\n  MsgStr$ = MsgStr$ & vbNewLine & _\n       \"Only Shows If uExtractList = 1 List Contents\"\n  MsgStr$ = MsgStr$ & vbNewLine & \"--------------\"\n  MsgStr$ = MsgStr$ & vbNewLine & \"Comment         : \" & UZUSER.cchComment\n  MsgStr$ = MsgStr$ & vbNewLine & \"Total Size Comp : \" _\n                    & Format$(TotalSizeComp, \"#,0\")\n  MsgStr$ = MsgStr$ & vbNewLine & \"Total Size      : \" _\n                    & Format$(TotalSize, \"#,0\")\n  MsgStr$ = MsgStr$ & vbNewLine & \"Compress Factor : %\" & UZUSER.CompFactor\n  MsgStr$ = MsgStr$ & vbNewLine & \"Num Of Members  : \" & NumMembers\n  MsgStr$ = MsgStr$ & vbNewLine & \"--------------\"\n\n  VBUnzFrm.txtMsgOut.Text = VBUnzFrm.txtMsgOut.Text & MsgStr$ & vbNewLine\nEnd Sub\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vb/vbunzip.frm",
    "content": "VERSION 5.00\nObject = \"{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.1#0\"; \"COMDLG32.OCX\"\nBegin VB.Form VBUnzFrm \n   AutoRedraw      =   -1  'True\n   Caption         =   \"VBUnzFrm\"\n   ClientHeight    =   4785\n   ClientLeft      =   780\n   ClientTop       =   525\n   ClientWidth     =   9375\n   BeginProperty Font \n      Name            =   \"Fixedsys\"\n      Size            =   9\n      Charset         =   0\n      Weight          =   400\n      Underline       =   0   'False\n      Italic          =   0   'False\n      Strikethrough   =   0   'False\n   EndProperty\n   LinkTopic       =   \"VBUnzFrm\"\n   ScaleHeight     =   4785\n   ScaleWidth      =   9375\n   StartUpPosition =   1  'Fenstermitte\n   Begin VB.CheckBox checkOverwriteAll \n      Alignment       =   1  'Rechts ausgerichtet\n      Caption         =   \"Overwrite all?\"\n      BeginProperty Font \n         Name            =   \"MS Sans Serif\"\n         Size            =   9.75\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   255\n      Left            =   240\n      TabIndex        =   5\n      Top             =   1320\n      Width           =   4425\n   End\n   Begin VB.TextBox txtZipFName \n      BeginProperty Font \n         Name            =   \"Courier New\"\n         Size            =   9.75\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   375\n      Left            =   4440\n      TabIndex        =   1\n      Top             =   120\n      Width           =   4335\n   End\n   Begin VB.TextBox txtExtractRoot \n      BeginProperty Font \n         Name            =   \"Courier New\"\n         Size            =   9.75\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   375\n      Left            =   4440\n      TabIndex        =   4\n      Top             =   720\n      Width           =   4335\n   End\n   Begin VB.CommandButton cmdStartUnz \n      Caption         =   \"Start\"\n      Height          =   495\n      Left            =   240\n      TabIndex        =   6\n      Top             =   1800\n      Width           =   3255\n   End\n   Begin VB.TextBox txtMsgOut \n      BeginProperty Font \n         Name            =   \"Courier New\"\n         Size            =   9\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   2175\n      Left            =   240\n      Locked          =   -1  'True\n      MultiLine       =   -1  'True\n      ScrollBars      =   3  'Beides\n      TabIndex        =   8\n      TabStop         =   0   'False\n      Top             =   2520\n      Width           =   8895\n   End\n   Begin VB.CommandButton cmdQuitVBUnz \n      Cancel          =   -1  'True\n      Caption         =   \"Quit\"\n      Height          =   495\n      Left            =   6240\n      TabIndex        =   7\n      Top             =   1800\n      Width           =   2895\n   End\n   Begin VB.CommandButton cmdSearchZfile \n      Caption         =   \"...\"\n      BeginProperty Font \n         Name            =   \"MS Sans Serif\"\n         Size            =   8.25\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   375\n      Left            =   8760\n      TabIndex        =   2\n      Top             =   120\n      Width           =   375\n   End\n   Begin MSComDlg.CommonDialog CommonDialog1 \n      Left            =   4800\n      Top             =   1800\n      _ExtentX        =   847\n      _ExtentY        =   847\n      _Version        =   393216\n   End\n   Begin VB.Label Label1 \n      Caption         =   \"Complete path-name of Zip-archive:\"\n      BeginProperty Font \n         Name            =   \"MS Sans Serif\"\n         Size            =   9.75\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   255\n      Left            =   240\n      TabIndex        =   0\n      Top             =   120\n      Width           =   3855\n   End\n   Begin VB.Label Label2 \n      Caption         =   \"Extract archive into directory:\"\n      BeginProperty Font \n         Name            =   \"MS Sans Serif\"\n         Size            =   9.75\n         Charset         =   0\n         Weight          =   400\n         Underline       =   0   'False\n         Italic          =   0   'False\n         Strikethrough   =   0   'False\n      EndProperty\n      Height          =   255\n      Left            =   240\n      TabIndex        =   3\n      Top             =   720\n      Width           =   3855\n   End\nEnd\nAttribute VB_Name = \"VBUnzFrm\"\nAttribute VB_GlobalNameSpace = False\nAttribute VB_Creatable = False\nAttribute VB_PredeclaredId = True\nAttribute VB_Exposed = False\nOption Explicit\n\n'---------------------------------------------------\n'-- Please Do Not Remove These Comment Lines!\n'----------------------------------------------------------------\n'-- Sample VB 5 / VB 6 code to drive unzip32.dll\n'-- Contributed to the Info-ZIP project by Mike Le Voi\n'--\n'-- Contact me at: mlevoi@modemss.brisnet.org.au\n'--\n'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'----------------------------------------------------------------\n'--\n'-- This Source Code Is Freely Available From The Info-ZIP Project\n'-- Web Server At:\n'-- ftp://ftp.info-zip.org/pub/infozip/infozip.html\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White\n'-- And The Fine People Of The Info-ZIP Group\n'-- For Letting Me Use And Modify Their Orginal\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'-- For Your Hard Work In Helping Me Get This To Work!!!\n'---------------------------------------------------------------\n'--\n'-- Contributed To The Info-ZIP Project By Raymond L. King.\n'-- Modified June 21, 1998\n'-- By Raymond L. King\n'-- Custom Software Designers\n'--\n'-- Contact Me At: king@ntplx.net\n'-- ICQ 434355\n'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\n'--\n'---------------------------------------------------------------\n'--\n'-- Modified August 17, 1998\n'-- by Christian Spieler\n'-- (added sort of a \"windows oriented\" user interface)\n'-- Modified May 11, 2003\n'-- by Christian Spieler\n'-- (use late binding for referencing the common dialog)\n'-- Modified December 30, 2008\n'-- by Ed Gordon\n'-- (add Overwrite_All checkbox and resizing of txtMsgOut\n'-- output box)\n'-- Modified January 03, 2009\n'-- by Christian Spieler\n'-- (fixed tab navigation sequence, changed passing of\n'-- \"overwrite-all\" setting to use existing option flags,\n'-- cleared all msg buffer at start of every DLL call,\n'-- removed code that is not supported by VB5)\n'--\n'---------------------------------------------------------------\n\nPrivate mCommDlgCtrl As Object\n\nPrivate Sub cmdStartUnz_Click()\n\n    Dim MsgTmp As String\n    \n    Cls\n    txtMsgOut.Text = \"\"\n    \n    '-- Init Global Message Variables\n    uZipInfo = \"\"\n    uZipMessage = \"\"\n    uZipNumber = 0   ' Holds The Number Of Zip Files\n    \n    '-- Select UNZIP32.DLL Options - Change As Required!\n    ' 1 = Always Overwrite Files\n    uOverWriteFiles = Me.checkOverwriteAll.Value\n    ' 1 = Prompt To Overwrite\n    uPromptOverWrite = IIf(uOverWriteFiles = 0, 1, 0)\n    uDisplayComment = 0   ' 1 = Display comment ONLY!!!\n    uHonorDirectories = 1  ' 1 = Honour Zip Directories\n    \n    '-- Select Filenames If Required\n    '-- Or Just Select All Files\n    uZipNames.uzFiles(0) = vbNullString\n    uNumberFiles = 0\n    \n    '-- Select Filenames To Exclude From Processing\n    ' Note UNIX convention!\n    '   vbxnames.s(0) = \"VBSYX/VBSYX.MID\"\n    '   vbxnames.s(1) = \"VBSYX/VBSYX.SYX\"\n    '   numx = 2\n    \n    '-- Or Just Select All Files\n    uExcludeNames.uzFiles(0) = vbNullString\n    uNumberXFiles = 0\n    \n    '-- Change The Next 2 Lines As Required!\n    '-- These Should Point To Your Directory\n    uZipFileName = txtZipFName.Text\n    uExtractDir = txtExtractRoot.Text\n    If Len(uExtractDir) <> 0 Then\n      uExtractList = 0  ' 0 = Extract if dir specified\n    Else\n      uExtractList = 1  ' 1 = List Contents Of Zip\n    End If\n    \n    '-- Let's Go And Unzip Them!\n    Call VBUnZip32\n    \n    '-- Tell The User What Happened\n    If Len(uZipMessage) > 0 Then\n        MsgTmp = uZipMessage\n        uZipMessage = \"\"\n    End If\n    \n    '-- Display Zip File Information.\n    If Len(uZipInfo) > 0 Then\n        MsgTmp = MsgTmp & vbNewLine & \"uZipInfo is:\" & vbNewLine & uZipInfo\n        uZipInfo = \"\"\n    End If\n    \n    '-- Display The Number Of Extracted Files!\n    If uZipNumber > 0 Then\n        MsgTmp = MsgTmp & vbNewLine & \"Number Of Files: \" & Str(uZipNumber)\n    End If\n    \n    txtMsgOut.Text = txtMsgOut.Text & MsgTmp & vbNewLine\n    \n    \nEnd Sub\n\n\nPrivate Sub Form_Load()\n    \n    '-- To work around compatibility issues between different versions of\n    '-- Visual Basic, we use a late bound untyped object variable to reference\n    '-- the common dialog ActiveX-control object at runtime.\n    On Error Resume Next\n    Set mCommDlgCtrl = CommonDialog1\n    On Error GoTo 0\n    '-- Disable the \"call openfile dialog\" button, when the common dialog\n    '-- object is not available\n    cmdSearchZfile.Visible = Not (mCommDlgCtrl Is Nothing)\n    \n    txtZipFName.Text = vbNullString\n    txtExtractRoot.Text = vbNullString\n    Me.Show\n    \nEnd Sub\n\nPrivate Sub Form_Resize()\n    Dim Wid As Single\n    Dim Hei As Single\n    \n    Wid = Me.Width - 600 ' 9495 - 8895\n    If Wid < 2000 Then Wid = 2000\n    txtMsgOut.Width = Wid\n    \n    Hei = Me.Height - 3120 ' 5295 - 2175\n    If Hei < 1000 Then Hei = 1000\n    txtMsgOut.Height = Hei\n\nEnd Sub\n\nPrivate Sub Form_Unload(Cancel As Integer)\n    '-- remove runtime reference to common dialog control object\n    Set mCommDlgCtrl = Nothing\nEnd Sub\n\n\nPrivate Sub cmdQuitVBUnz_Click()\n    Unload Me\nEnd Sub\n\n\nPrivate Sub cmdSearchZfile_Click()\n    If mCommDlgCtrl Is Nothing Then Exit Sub\n    mCommDlgCtrl.CancelError = False\n    mCommDlgCtrl.DialogTitle = \"Open Zip-archive\"\n    '-- The following property is not supported in the first version(s)\n    '-- of the common dialog controls. But this feature is of minor\n    '-- relevance in our context, so we simply skip over the statement\n    '-- in case of errors.\n    On Error Resume Next\n    mCommDlgCtrl.DefaultExt = \".zip\"\n    On Error GoTo err_deactivateControl\n    '-- Initialize the file name with the current setting of the filename\n    '-- text box.\n    mCommDlgCtrl.FileName = txtZipFName.Text\n    '-- Provide reasonable filter settings for selecting Zip archives.\n    mCommDlgCtrl.Filter = \"Zip archives (*.zip)|*.zip|All files (*.*)|*.*\"\n    mCommDlgCtrl.ShowOpen\n    '-- In case the user closed the dialog via cancel, the FilenName\n    '-- property contains its initial setting and no change occurs.\n    txtZipFName.Text = mCommDlgCtrl.FileName\n    Exit Sub\n\nerr_deactivateControl:\n    '-- Emit a warning message.\n    MsgBox \"Unexpected error #\" & CStr(Err.Number) & \" in call to ComDLG32\" _\n         & \" FileOpen dialog:\" & vbNewLine & Err.Description & vbNewLine _\n         & vbNewLine & \"The version of the COMDLG32.OCX control installed\" _\n         & \" on your system seems to be too old. Please consider upgrading\" _\n         & \" to a recent release of the Common Dialog ActiveX control.\" _\n         & vbNewLine & \"The \"\"Choose File from List\"\" dialog functionality\" _\n         & \" has been disabled for this session.\", _\n         vbCritical + vbOKOnly, \"FileOpen Dialog incompatible\"\n    '-- Deactivate the control and prevent further usage in this session.\n    Set mCommDlgCtrl = Nothing\n    cmdSearchZfile.Enabled = False\nEnd Sub\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vb/vbunzip.vbp",
    "content": "Type=Exe\nForm=vbunzip.frm\nModule=VBUnzBas; vbunzip.bas\nObject={F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.1#0; COMDLG32.OCX\nIconForm=\"VBUnzFrm\"\nStartup=\"VBUnzFrm\"\nHelpFile=\"\"\nTitle=\"VBUnZip\"\nExeName32=\"VBunzip.exe\"\nCommand32=\"\"\nName=\"VBUnzipProject\"\nHelpContextID=\"0\"\nCompatibleMode=\"0\"\nMajorVer=1\nMinorVer=0\nRevisionVer=0\nAutoIncrementVer=0\nServerSupportFiles=0\nVersionCompanyName=\"Info-ZIP\"\nVersionLegalCopyright=\"(c) Info-ZIP 1998-2009\"\nCompilationType=0\nOptimizationType=0\nFavorPentiumPro(tm)=0\nCodeViewDebugInfo=0\nNoAliasing=0\nBoundsCheck=0\nOverflowCheck=0\nFlPointCheck=0\nFDIVCheck=0\nUnroundedFP=0\nStartMode=0\nUnattended=0\nThreadPerObject=0\nMaxNumberOfThreads=1\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/dll/unz32dll.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unz32dll\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\n\nCFG=unz32dll - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32dll.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32dll.mak\" CFG=\"unz32dll - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unz32dll - Win32 Release\" (based on\\\n \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Release\" (based on\\\n \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Static Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Static Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Static Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Static Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unz32dll - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/app\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../Release/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/app\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../Debug/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM/app\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../Release.ASM/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM/app\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../Debug.ASM/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease/app\"\n# PROP Intermediate_Dir \"StatRelease\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../StatRelease/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug/app\"\n# PROP Intermediate_Dir \"StatDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../StatDebug/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease.ASM/app\"\n# PROP Intermediate_Dir \"StatRelease.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../StatRelease.ASM/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug.ASM/app\"\n# PROP Intermediate_Dir \"StatDebug.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../StatDebug.ASM/app/unzip32.dll\" /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unz32dll - Win32 Release\"\n# Name \"unz32dll - Win32 Debug\"\n# Name \"unz32dll - Win32 ASM Release\"\n# Name \"unz32dll - Win32 ASM Debug\"\n# Name \"unz32dll - Win32 Static Release\"\n# Name \"unz32dll - Win32 Static Debug\"\n# Name \"unz32dll - Win32 ASM Static Release\"\n# Name \"unz32dll - Win32 ASM Static Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll32.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipinfo.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/exampl/c_dll_ex.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"c_dll_ex\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=c_dll_ex - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"c_dll_ex.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"c_dll_ex.mak\" CFG=\"c_dll_ex - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"c_dll_ex - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Static Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Static Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"c_dll_ex - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/app\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386 /out:\"../Release/app/uzexampl.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/app\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /out:\"../Debug/app/uzexampl.exe\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease/app\"\n# PROP Intermediate_Dir \"StatRelease\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386 /out:\"../StatRelease/app/uzexampl.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug/app\"\n# PROP Intermediate_Dir \"StatDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /out:\"../StatDebug/app/uzexampl.exe\" /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"c_dll_ex - Win32 Release\"\n# Name \"c_dll_ex - Win32 Debug\"\n# Name \"c_dll_ex - Win32 Static Release\"\n# Name \"c_dll_ex - Win32 Static Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\uzexampl.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\uzexampl.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/lib/unz32lib.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unz32lib\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=unz32lib - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32lib.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32lib.mak\" CFG=\"unz32lib - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unz32lib - Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 ASM Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 ASM Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\n\n!IF  \"$(CFG)\" == \"unz32lib - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/libs\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /FD /c\n# SUBTRACT CPP /YX\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Release/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/libs\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /Z7 /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /FD /c\n# SUBTRACT CPP /YX\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Debug/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM/libs\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /FD /c\n# SUBTRACT CPP /YX\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Release.ASM/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM/libs\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /Z7 /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /FD /c\n# SUBTRACT CPP /YX\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Debug.ASM/libs/unzip32.lib\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unz32lib - Win32 Release\"\n# Name \"unz32lib - Win32 Debug\"\n# Name \"unz32lib - Win32 ASM Release\"\n# Name \"unz32lib - Win32 ASM Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\unziplib.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipinfo.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/sfx/SFXWiz32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"SFXWiz\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\n\nCFG=SFXWiz - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"SFXWiz32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"SFXWiz32.mak\" CFG=\"SFXWiz - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"SFXWiz - Win32 Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 ASM Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 ASM Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"SFXWiz - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /machine:I386 /libpath:\"..\\Release\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:\"..\\Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /machine:I386 /libpath:\"..\\Release.ASM\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:\"..\\Debug.ASM\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"SFXWiz - Win32 Release\"\n# Name \"SFXWiz - Win32 Debug\"\n# Name \"SFXWiz - Win32 ASM Release\"\n# Name \"SFXWiz - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxwiz.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxwiz.rc\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\dialog.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxw.ico\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/sfx/SFXWiz32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 5.00\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\n\n###############################################################################\n\nProject: \"SFXWiz\"=.\\SFXWiz32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unzsfx32\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"unzsfx32\"=.\\unzsfx32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/sfx/unzsfx32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unzsfx32\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 5.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=unzsfx32 - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzsfx32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzsfx32.mak\" CFG=\"unzsfx32 - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzsfx32 - Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 ASM Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 ASM Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\n\n!IF  \"$(CFG)\" == \"unzsfx32 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /YX /FD /c\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /YX /FD /c\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzsfx32 - Win32 Release\"\n# Name \"unzsfx32 - Win32 Debug\"\n# Name \"unzsfx32 - Win32 ASM Release\"\n# Name \"unzsfx32 - Win32 ASM Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc5/unzip32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 5.00\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\n\n###############################################################################\n\nProject: \"SFXWiz\"=.\\sfx\\SFXWiz32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unzsfx32\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"c_dll_ex\"=.\\exampl\\c_dll_ex.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unz32dll\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"unz32dll\"=.\\dll\\unz32dll.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unz32lib\"=.\\lib\\unz32lib.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unzsfx32\"=.\\sfx\\unzsfx32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/dll/unz32dll.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unz32dll\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\n\nCFG=unz32dll - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32dll.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32dll.mak\" CFG=\"unz32dll - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unz32dll - Win32 Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Static Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 Static Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Static Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"unz32dll - Win32 ASM Static Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unz32dll - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/app\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../Release/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/app\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../Debug/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM/app\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../Release.ASM/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM/app\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../Debug.ASM/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease/app\"\n# PROP Intermediate_Dir \"StatRelease\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../StatRelease/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug/app\"\n# PROP Intermediate_Dir \"StatDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../StatDebug/app/unzip32.dll\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease.ASM/app\"\n# PROP Intermediate_Dir \"StatRelease.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386 /out:\"../StatRelease.ASM/app/unzip32.dll\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32dll - Win32 ASM Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug.ASM/app\"\n# PROP Intermediate_Dir \"StatDebug.ASM\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"../StatDebug.ASM/app/unzip32.dll\" /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unz32dll - Win32 Release\"\n# Name \"unz32dll - Win32 Debug\"\n# Name \"unz32dll - Win32 ASM Release\"\n# Name \"unz32dll - Win32 ASM Debug\"\n# Name \"unz32dll - Win32 Static Release\"\n# Name \"unz32dll - Win32 Static Debug\"\n# Name \"unz32dll - Win32 ASM Static Release\"\n# Name \"unz32dll - Win32 ASM Static Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll32.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipinfo.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/exampl/c_dll_ex.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"c_dll_ex\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=c_dll_ex - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"c_dll_ex.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"c_dll_ex.mak\" CFG=\"c_dll_ex - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"c_dll_ex - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Static Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"c_dll_ex - Win32 Static Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"c_dll_ex - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/app\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /MD /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386 /out:\"../Release/app/uzexampl.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/app\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /out:\"../Debug/app/uzexampl.exe\" /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Static Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"StatRelease\"\n# PROP BASE Intermediate_Dir \"StatRelease\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../StatRelease/app\"\n# PROP Intermediate_Dir \"StatRelease\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /c\n# ADD CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /machine:I386 /out:\"../StatRelease/app/uzexampl.exe\"\n\n!ELSEIF  \"$(CFG)\" == \"c_dll_ex - Win32 Static Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"StatDebug\"\n# PROP BASE Intermediate_Dir \"StatDebug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../StatDebug/app\"\n# PROP Intermediate_Dir \"StatDebug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib version.lib /nologo /subsystem:console /debug /machine:I386 /out:\"../StatDebug/app/uzexampl.exe\" /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"c_dll_ex - Win32 Release\"\n# Name \"c_dll_ex - Win32 Debug\"\n# Name \"c_dll_ex - Win32 Static Release\"\n# Name \"c_dll_ex - Win32 Static Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\uzexampl.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\uzexampl.h\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/lib/unz32lib.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unz32lib\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=unz32lib - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32lib.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unz32lib.mak\" CFG=\"unz32lib - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unz32lib - Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 ASM Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unz32lib - Win32 ASM Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unz32lib - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release/libs\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Release/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug/libs\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /Z7 /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Debug/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM/libs\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Release.ASM/libs/unzip32.lib\"\n\n!ELSEIF  \"$(CFG)\" == \"unz32lib - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM/libs\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /Z7 /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo /out:\"../Debug.ASM/libs/unzip32.lib\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unz32lib - Win32 Release\"\n# Name \"unz32lib - Win32 Debug\"\n# Name \"unz32lib - Win32 ASM Release\"\n# Name \"unz32lib - Win32 ASM Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\explode.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\list.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unreduce.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\unshrink.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\unziplib.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipinfo.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/sfx/SFXWiz32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"SFXWiz\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\n\nCFG=SFXWiz - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"SFXWiz32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"SFXWiz32.mak\" CFG=\"SFXWiz - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"SFXWiz - Win32 Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 ASM Release\" (based on \"Win32 (x86) Application\")\n!MESSAGE \"SFXWiz - Win32 ASM Debug\" (based on \"Win32 (x86) Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"SFXWiz - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /machine:I386 /libpath:\"..\\Release\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:\"..\\Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /machine:I386 /libpath:\"..\\Release.ASM\"\n\n!ELSEIF  \"$(CFG)\" == \"SFXWiz - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /D \"WIN32\" /D \"API\" /D \"DLL\" /D \"USE_UNZIP_LIB\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comctl32.lib unzsfx32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:\"..\\Debug.ASM\"\n\n!ENDIF \n\n# Begin Target\n\n# Name \"SFXWiz - Win32 Release\"\n# Name \"SFXWiz - Win32 Debug\"\n# Name \"SFXWiz - Win32 ASM Release\"\n# Name \"SFXWiz - Win32 ASM Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxwiz.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxwiz.rc\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\dialog.h\n# End Source File\n# End Group\n# Begin Group \"Resource Files\"\n\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\guisfx\\sfxw.ico\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/sfx/SFXWiz32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\n\n###############################################################################\n\nProject: \"SFXWiz\"=.\\SFXWiz32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unzsfx32\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"unzsfx32\"=.\\unzsfx32.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/sfx/unzsfx32.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"unzsfx32\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=unzsfx32 - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"unzsfx32.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"unzsfx32.mak\" CFG=\"unzsfx32 - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"unzsfx32 - Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 ASM Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"unzsfx32 - Win32 ASM Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"unzsfx32 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /YX /FD /c\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"../Release.ASM\"\n# PROP Intermediate_Dir \"Release.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /GX /O2 /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /GX /O1 /I \"../../..\" /D \"NDEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"unzsfx32 - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"../Debug.ASM\"\n# PROP Intermediate_Dir \"Debug.ASM\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Gz /W3 /Gm /GX /Zi /Od /I \"../../..\" /D \"_DEBUG\" /D \"_MBCS\" /D \"WIN32\" /D \"WINDLL\" /D \"DLL\" /D \"UNZIPLIB\" /D \"SFX\" /D \"USE_EF_UT_TIME\" /D \"ASM_CRC\" /YX /FD /c\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ENDIF \n\n# Begin Target\n\n# Name \"unzsfx32 - Win32 Release\"\n# Name \"unzsfx32 - Win32 Debug\"\n# Name \"unzsfx32 - Win32 ASM Release\"\n# Name \"unzsfx32 - Win32 ASM Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\crc_i386.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\extract.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\inflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\match.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\process.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ubz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc6/unzip32.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELSCHT WERDEN!\n\n###############################################################################\n\nProject: \"SFXWiz\"=\".\\sfx\\SFXWiz32.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unzsfx32\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"c_dll_ex\"=\".\\exampl\\c_dll_ex.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n    Begin Project Dependency\n    Project_Dep_Name unz32dll\n    End Project Dependency\n}}}\n\n###############################################################################\n\nProject: \"unz32dll\"=\".\\dll\\unz32dll.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unz32lib\"=\".\\lib\\unz32lib.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"unzsfx32\"=\".\\sfx\\unzsfx32.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/dll/unz32dll.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unz32dll\"\n\tProjectGUID=\"{26E880E4-A1B1-4FB1-8833-13FC0FA48857}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\Debug.ASM\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Debug.ASM/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"3\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug.ASM/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug.ASM/\"\n\t\t\t\tObjectFile=\".\\Debug.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../Debug.ASM/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Debug.ASM/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../Debug.ASM/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug/app\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Debug/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"3\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../Debug/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Debug/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../Debug/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\Release.ASM\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Release.ASM/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"2\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release.ASM/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release.ASM/\"\n\t\t\t\tObjectFile=\".\\Release.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../Release.ASM/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release.ASM/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../Release.ASM/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release.ASM/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release/app\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Release/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"2\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../Release/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../Release/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../StatDebug.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\StatDebug.ASM\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../StatDebug.ASM/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatDebug.ASM/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatDebug.ASM/\"\n\t\t\t\tObjectFile=\".\\StatDebug.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatDebug.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../StatDebug.ASM/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatDebug.ASM/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../StatDebug.ASM/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatDebug.ASM/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Static Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../StatDebug/app\"\n\t\t\tIntermediateDirectory=\".\\StatDebug\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../StatDebug/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatDebug/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatDebug/\"\n\t\t\t\tObjectFile=\".\\StatDebug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatDebug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../StatDebug/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatDebug/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../StatDebug/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatDebug/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\tOutputDirectory=\".\\../StatRelease.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\StatRelease.ASM\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../StatRelease.ASM/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatRelease.ASM/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatRelease.ASM/\"\n\t\t\t\tObjectFile=\".\\StatRelease.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatRelease.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../StatRelease.ASM/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatRelease.ASM/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../StatRelease.ASM/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatRelease.ASM/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Static Release|Win32\"\n\t\t\tOutputDirectory=\".\\../StatRelease/app\"\n\t\t\tIntermediateDirectory=\".\\StatRelease\"\n\t\t\tConfigurationType=\"2\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../StatRelease/app/unz32dll.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;USE_EF_UT_TIME\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatRelease/unz32dll.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatRelease/\"\n\t\t\t\tObjectFile=\".\\StatRelease/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatRelease/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG,WIN32\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib\"\n\t\t\t\tOutputFile=\"../StatRelease/app/unzip32.dll\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tModuleDefinitionFile=\"..\\..\\windll32.def\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatRelease/app/unzip32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tImportLibrary=\".\\../StatRelease/app/unzip32.lib\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatRelease/app/unz32dll.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\api.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crc32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\crc_i386.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crypt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\explode.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\extract.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\fileio.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\globals.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\inflate.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\list.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\match.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\nt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\process.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\ubz2err.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\unreduce.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\unshrink.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32i64.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\windll.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\windll.rc\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"..\\..\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\windll32.def\"\n\t\t\t>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\zipinfo.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/exampl/c_dll_ex.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"c_dll_ex\"\n\tProjectGUID=\"{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}\"\n\tRootNamespace=\"c_dll_ex\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release/app\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../Release/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_CONSOLE;WIN32\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"2\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug/app\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../Debug/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_CONSOLE;WIN32\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"3\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Debug/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../Release/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_CONSOLE;WIN32\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"2\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../Debug/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_CONSOLE;WIN32\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"3\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Static Release|Win32\"\n\t\t\tOutputDirectory=\".\\../StatRelease/app\"\n\t\t\tIntermediateDirectory=\".\\StatRelease\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../StatRelease/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_CONSOLE;WIN32\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatRelease/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatRelease/\"\n\t\t\t\tObjectFile=\".\\StatRelease/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatRelease/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatRelease/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatRelease/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Static Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../StatDebug/app\"\n\t\t\tIntermediateDirectory=\".\\StatDebug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../StatDebug/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_CONSOLE;WIN32\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatDebug/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatDebug/\"\n\t\t\t\tObjectFile=\".\\StatDebug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatDebug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatDebug/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatDebug/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\tOutputDirectory=\".\\../StatRelease.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\StatRelease\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../StatRelease/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_CONSOLE;WIN32\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatRelease/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatRelease/\"\n\t\t\t\tObjectFile=\".\\StatRelease/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatRelease/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatRelease/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatRelease/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../StatDebug.ASM/app\"\n\t\t\tIntermediateDirectory=\".\\StatDebug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tTypeLibraryName=\".\\../StatDebug/app/c_dll_ex.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_CONSOLE;WIN32\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tBasicRuntimeChecks=\"3\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\StatDebug/c_dll_ex.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\StatDebug/\"\n\t\t\t\tObjectFile=\".\\StatDebug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\StatDebug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib version.lib\"\n\t\t\t\tOutputFile=\"$(OutDir)/uzexampl.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../StatDebug/app/uzexampl.pdb\"\n\t\t\t\tSubSystem=\"1\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../StatDebug/app/c_dll_ex.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\uzexampl.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Static Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Static Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Static Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Static Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\uzexampl.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/lib/unz32lib.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unz32lib\"\n\tProjectGUID=\"{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release.ASM/libs\"\n\t\t\tIntermediateDirectory=\".\\Release.ASM\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;UNZIPLIB;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release.ASM/unz32lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release.ASM/\"\n\t\t\t\tObjectFile=\".\\Release.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"../Release.ASM/libs/unzip32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release.ASM/libs/unz32lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug.ASM/libs\"\n\t\t\tIntermediateDirectory=\".\\Debug.ASM\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;UNZIPLIB;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug.ASM/unz32lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug.ASM/\"\n\t\t\t\tObjectFile=\".\\Debug.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"../Debug.ASM/libs/unzip32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM/libs/unz32lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug/libs\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;WINDLL;DLL;UNZIPLIB;USE_EF_UT_TIME\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/unz32lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"../Debug/libs/unzip32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/libs/unz32lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release/libs\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"2\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;WINDLL;DLL;UNZIPLIB;USE_EF_UT_TIME\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/unz32lib.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\"../Release/libs/unzip32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/libs/unz32lib.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\api.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crc32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\crc_i386.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crypt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\explode.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\extract.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\fileio.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\globals.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\inflate.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\list.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\match.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\nt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\process.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\ubz2err.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\unreduce.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\unshrink.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\unziplib.def\"\n\t\t\t>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32i64.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\windll.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\zipinfo.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/sfx/SFXWiz32.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 9.00\n# Visual C++ Express 2005\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"SFXWiz\", \"SFXWiz32.vcproj\", \"{6BC29537-2E45-4429-A634-5C45B649436C}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398} = {7545BD38-9F08-4F69-A944-E9981A5AB398}\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unzsfx32\", \"unzsfx32.vcproj\", \"{7545BD38-9F08-4F69-A944-E9981A5AB398}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tASM Debug|Win32 = ASM Debug|Win32\n\t\tASM Release|Win32 = ASM Release|Win32\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Release|Win32.Build.0 = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/sfx/SFXWiz32.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"SFXWiz\"\n\tProjectGUID=\"{6BC29537-2E45-4429-A634-5C45B649436C}\"\n\tRootNamespace=\"SFXWiz\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Debug/SFXWiz32.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;API;DLL;USE_UNZIP_LIB\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/SFXWiz32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/SFXWiz32.pdb\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib comctl32.lib comdlg32.lib unzsfx32.lib\"\n\t\t\t\tOutputFile=\".\\../Debug/SFXWiz32.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tAdditionalLibraryDirectories=\"..\\Debug\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Debug/SFXWiz32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/SFXWiz32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug.ASM\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Debug.ASM/SFXWiz32.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;_WINDOWS;WIN32;API;DLL;USE_UNZIP_LIB\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/SFXWiz32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib comctl32.lib comdlg32.lib unzsfx32.lib\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM/SFXWiz32.exe\"\n\t\t\t\tLinkIncremental=\"2\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tAdditionalLibraryDirectories=\"..\\Debug.ASM\"\n\t\t\t\tGenerateDebugInformation=\"true\"\n\t\t\t\tProgramDatabaseFile=\".\\../Debug.ASM/SFXWiz32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM/SFXWiz32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Release/SFXWiz32.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;API;DLL;USE_UNZIP_LIB\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/SFXWiz32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/SFXWiz32.pdb\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib comctl32.lib comdlg32.lib unzsfx32.lib\"\n\t\t\t\tOutputFile=\".\\../Release/SFXWiz32.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tAdditionalLibraryDirectories=\"..\\Release\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release/SFXWiz32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/SFXWiz32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release.ASM\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"1\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tMkTypLibCompatible=\"true\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tTargetEnvironment=\"1\"\n\t\t\t\tTypeLibraryName=\".\\../Release.ASM/SFXWiz32.tlb\"\n\t\t\t\tHeaderFileName=\"\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;_WINDOWS;WIN32;API;DLL;USE_UNZIP_LIB\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/SFXWiz32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/SFXWiz32.pdb\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLinkerTool\"\n\t\t\t\tAdditionalDependencies=\"advapi32.lib user32.lib comctl32.lib comdlg32.lib unzsfx32.lib\"\n\t\t\t\tOutputFile=\".\\../Release.ASM/SFXWiz32.exe\"\n\t\t\t\tLinkIncremental=\"1\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tAdditionalLibraryDirectories=\"..\\Release.ASM\"\n\t\t\t\tProgramDatabaseFile=\".\\../Release.ASM/SFXWiz32.pdb\"\n\t\t\t\tSubSystem=\"2\"\n\t\t\t\tTargetMachine=\"1\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManifestTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release.ASM/SFXWiz32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCAppVerifierTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebDeploymentTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<Filter\n\t\t\tName=\"Source Files\"\n\t\t\tFilter=\"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\guisfx\\sfxwiz.c\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\guisfx\\sfxwiz.rc\"\n\t\t\t\t>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\\VSProjects\\Info-ZIP\\unz6\\unz60d10\\windll\\guisfx\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\\VSProjects\\Info-ZIP\\unz6\\unz60d10\\windll\\guisfx\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\\VSProjects\\Info-ZIP\\unz6\\unz60d10\\windll\\guisfx\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t\t<FileConfiguration\n\t\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t\t>\n\t\t\t\t\t<Tool\n\t\t\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t\t\tAdditionalIncludeDirectories=\"\\VSProjects\\Info-ZIP\\unz6\\unz60d10\\windll\\guisfx\"\n\t\t\t\t\t/>\n\t\t\t\t</FileConfiguration>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Resource Files\"\n\t\t\tFilter=\"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\guisfx\\sfxw.ico\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t\t<Filter\n\t\t\tName=\"Header Files\"\n\t\t\tFilter=\"h;hpp;hxx;hm;inl\"\n\t\t\t>\n\t\t\t<File\n\t\t\t\tRelativePath=\"..\\..\\guisfx\\dialog.h\"\n\t\t\t\t>\n\t\t\t</File>\n\t\t</Filter>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/sfx/unzsfx32.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<VisualStudioProject\n\tProjectType=\"Visual C++\"\n\tVersion=\"8,00\"\n\tName=\"unzsfx32\"\n\tProjectGUID=\"{7545BD38-9F08-4F69-A944-E9981A5AB398}\"\n\t>\n\t<Platforms>\n\t\t<Platform\n\t\t\tName=\"Win32\"\n\t\t/>\n\t</Platforms>\n\t<ToolFiles>\n\t</ToolFiles>\n\t<Configurations>\n\t\t<Configuration\n\t\t\tName=\"Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release\"\n\t\t\tIntermediateDirectory=\".\\Release\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;WINDLL;DLL;UNZIPLIB;SFX;USE_EF_UT_TIME\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release/unzsfx32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release/\"\n\t\t\t\tObjectFile=\".\\Release/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\".\\../Release\\unzsfx32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release/unzsfx32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Release|Win32\"\n\t\t\tOutputDirectory=\".\\../Release.ASM\"\n\t\t\tIntermediateDirectory=\".\\Release.ASM\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"1\"\n\t\t\t\tInlineFunctionExpansion=\"1\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"NDEBUG;WIN32;WINDLL;DLL;UNZIPLIB;SFX;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tStringPooling=\"true\"\n\t\t\t\tRuntimeLibrary=\"0\"\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Release.ASM/unzsfx32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Release.ASM/\"\n\t\t\t\tObjectFile=\".\\Release.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Release.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\".\\../Release.ASM\\unzsfx32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Release.ASM/unzsfx32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug\"\n\t\t\tIntermediateDirectory=\".\\Debug\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;WINDLL;DLL;UNZIPLIB;SFX;USE_EF_UT_TIME\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug/unzsfx32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug/\"\n\t\t\t\tObjectFile=\".\\Debug/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\".\\../Debug\\unzsfx32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug/unzsfx32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t\t<Configuration\n\t\t\tName=\"ASM Debug|Win32\"\n\t\t\tOutputDirectory=\".\\../Debug.ASM\"\n\t\t\tIntermediateDirectory=\".\\Debug.ASM\"\n\t\t\tConfigurationType=\"4\"\n\t\t\tUseOfMFC=\"0\"\n\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n\t\t\tCharacterSet=\"2\"\n\t\t\t>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreBuildEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCustomBuildTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\tOptimization=\"0\"\n\t\t\t\tAdditionalIncludeDirectories=\"../../..\"\n\t\t\t\tPreprocessorDefinitions=\"_DEBUG;WIN32;WINDLL;DLL;UNZIPLIB;SFX;USE_EF_UT_TIME;ASM_CRC\"\n\t\t\t\tMinimalRebuild=\"true\"\n\t\t\t\tRuntimeLibrary=\"1\"\n\t\t\t\tPrecompiledHeaderFile=\".\\Debug.ASM/unzsfx32.pch\"\n\t\t\t\tAssemblerListingLocation=\".\\Debug.ASM/\"\n\t\t\t\tObjectFile=\".\\Debug.ASM/\"\n\t\t\t\tProgramDataBaseFileName=\".\\Debug.ASM/\"\n\t\t\t\tWarningLevel=\"3\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tDebugInformationFormat=\"3\"\n\t\t\t\tCallingConvention=\"2\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCResourceCompilerTool\"\n\t\t\t\tCulture=\"1033\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPreLinkEventTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCLibrarianTool\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM\\unzsfx32.lib\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCALinkTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCXDCMakeTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCBscMakeTool\"\n\t\t\t\tSuppressStartupBanner=\"true\"\n\t\t\t\tOutputFile=\".\\../Debug.ASM/unzsfx32.bsc\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCFxCopTool\"\n\t\t\t/>\n\t\t\t<Tool\n\t\t\t\tName=\"VCPostBuildEventTool\"\n\t\t\t/>\n\t\t</Configuration>\n\t</Configurations>\n\t<References>\n\t</References>\n\t<Files>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\api.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crc32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\crc_i386.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\crypt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\extract.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\fileio.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\globals.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\inflate.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\match.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\nt.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\process.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\ubz2err.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\..\\win32\\win32i64.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t\t<File\n\t\t\tRelativePath=\"..\\..\\windll.c\"\n\t\t\t>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Release|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t\t<FileConfiguration\n\t\t\t\tName=\"ASM Debug|Win32\"\n\t\t\t\t>\n\t\t\t\t<Tool\n\t\t\t\t\tName=\"VCCLCompilerTool\"\n\t\t\t\t\tAdditionalIncludeDirectories=\"\"\n\t\t\t\t\tPreprocessorDefinitions=\"\"\n\t\t\t\t/>\n\t\t\t</FileConfiguration>\n\t\t</File>\n\t</Files>\n\t<Globals>\n\t</Globals>\n</VisualStudioProject>\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/vc8/unzip32.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 9.00\n# Visual C++ Express 2005\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"SFXWiz\", \"sfx\\SFXWiz32.vcproj\", \"{6BC29537-2E45-4429-A634-5C45B649436C}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398} = {7545BD38-9F08-4F69-A944-E9981A5AB398}\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unz32dll\", \"dll\\unz32dll.vcproj\", \"{26E880E4-A1B1-4FB1-8833-13FC0FA48857}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unz32lib\", \"lib\\unz32lib.vcproj\", \"{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"unzsfx32\", \"sfx\\unzsfx32.vcproj\", \"{7545BD38-9F08-4F69-A944-E9981A5AB398}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"c_dll_ex\", \"exampl\\c_dll_ex.vcproj\", \"{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857} = {26E880E4-A1B1-4FB1-8833-13FC0FA48857}\n\tEndProjectSection\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tASM Debug|Win32 = ASM Debug|Win32\n\t\tASM Release|Win32 = ASM Release|Win32\n\t\tASM Static Debug|Win32 = ASM Static Debug|Win32\n\t\tASM Static Release|Win32 = ASM Static Release|Win32\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\t\tStatic Debug|Win32 = Static Debug|Win32\n\t\tStatic Release|Win32 = Static Release|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.ASM Static Release|Win32.Build.0 = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Release|Win32.Build.0 = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{6BC29537-2E45-4429-A634-5C45B649436C}.Static Release|Win32.Build.0 = Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Static Debug|Win32.ActiveCfg = Static Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Static Debug|Win32.Build.0 = Static Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Static Release|Win32.ActiveCfg = Static Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.ASM Static Release|Win32.Build.0 = Static Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Release|Win32.Build.0 = Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Static Debug|Win32.ActiveCfg = Static Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Static Debug|Win32.Build.0 = Static Debug|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Static Release|Win32.ActiveCfg = Static Release|Win32\n\t\t{26E880E4-A1B1-4FB1-8833-13FC0FA48857}.Static Release|Win32.Build.0 = Static Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Static Debug|Win32.ActiveCfg = ASM Static Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Static Debug|Win32.Build.0 = ASM Static Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Static Release|Win32.ActiveCfg = ASM Static Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.ASM Static Release|Win32.Build.0 = ASM Static Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Release|Win32.Build.0 = Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Static Debug|Win32.ActiveCfg = Static Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Static Debug|Win32.Build.0 = Static Debug|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Static Release|Win32.ActiveCfg = Static Release|Win32\n\t\t{AC199DDF-4CC8-4BEE-988E-1D20C7336F22}.Static Release|Win32.Build.0 = Static Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.ASM Static Release|Win32.Build.0 = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.Build.0 = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Release|Win32.Build.0 = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{7545BD38-9F08-4F69-A944-E9981A5AB398}.Static Release|Win32.Build.0 = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.ASM Static Release|Win32.Build.0 = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Release|Win32.Build.0 = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Static Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Static Debug|Win32.Build.0 = Debug|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Static Release|Win32.ActiveCfg = Release|Win32\n\t\t{80E5EF65-3BD4-4EFF-BA4C-CA893C95EE8B}.Static Release|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Windows Info-ZIP Unzip DLL module\n *\n * Author: Mike White\n *\n * Original: 1996\n *\n * This module has the entry points for \"unzipping\" a zip file.\n */\n\n/*---------------------------------------------------------------------------\n\n  This file is the WINDLL replacement for the generic ``main program source\n  file'' unzip.c.\n\n  See the general comments in the header part of unzip.c.\n\n  Copyrights:  see accompanying file \"COPYING\" in UnZip source distribution.\n               (This software is free but NOT IN THE PUBLIC DOMAIN.  There\n               are some restrictions on commercial use.)\n\n  ---------------------------------------------------------------------------*/\n\n#define __WINDLL_C      /* identifies this source module */\n\n#define WIN32_LEAN_AND_MEAN\n#define UNZIP_INTERNAL\n#include \"../unzip.h\"\n#include \"../crypt.h\"\n#include \"../unzvers.h\"\n#include \"../windll/windll.h\"\n#include \"../windll/structs.h\"\n#include \"../consts.h\"\n#include <malloc.h>\n\n/* Added type casts to prevent potential \"type mismatch\" error messages. */\n#ifdef REENTRANT\n#  undef __G\n#  undef __G__\n#  define __G                 (Uz_Globs *)pG\n#  define __G__               (Uz_Globs *)pG,\n#endif\n\nHANDLE hwildZipFN;\nHANDLE hInst;               /* current instance */\nHANDLE hDCL;\nint fNoPrinting = 0;\nextern jmp_buf dll_error_return;\n\n/* Helper function to release memory allocated by Wiz_SetOpts() */\nstatic void FreeDllMem(__GPRO);\n\n/* For displaying status messages and error messages */\nstatic int UZ_EXP DllMessagePrint(zvoid *pG, uch *buf, ulg size, int flag);\n\n#if 0 /* currently unused */\n/* For displaying files extracted to the display window */\nint DllDisplayPrint(zvoid *pG, uch *buf, ulg size, int flag);\n#endif /* never */\n\n/* Callback function for status report and/or user interception */\nstatic int UZ_EXP Wiz_StatReportCB(zvoid *pG, int fnflag, ZCONST char *zfn,\n                                   ZCONST char *efn, ZCONST zvoid *details);\n\n/* Dummy sound function for those applications that don't use sound */\nstatic void WINAPI DummySound(void);\n\nstatic int UnzipAllocMemory(unsigned, char *, char *, char ***, unsigned *);\nstatic int UnzipParseString(LPCSTR, unsigned *, char ***);\nstatic void UnzipFreeArguments(unsigned, char ***);\n\n#ifndef UNZIPLIB\n/*  DLL Entry Point */\n\n#ifdef __BORLANDC__\n#pragma argsused\n/* Borland seems to want DllEntryPoint instead of DllMain like MSVC */\n#define DllMain DllEntryPoint\n#endif\n#ifdef WIN32\nBOOL WINAPI DllMain( HINSTANCE hInstance,\n                     DWORD dwReason,\n                     LPVOID plvReserved)\n#else\nint FAR PASCAL LibMain( HINSTANCE hInstance,\n                        WORD wDataSegment,\n                        WORD wHeapSize,\n                        LPSTR lpszCmdLine )\n#endif\n{\n#ifndef WIN32\n   /* The startup code for the DLL initializes the local heap(if there is one)\n    * with a call to LocalInit which locks the data segment.\n    */\n\n   if ( wHeapSize != 0 )\n      {\n      UnlockData( 0 );\n      }\n   hInst = hInstance;\n   return 1;   /* Indicate that the DLL was initialized successfully. */\n#else\n   BOOL rc = TRUE;\n   switch( dwReason )\n      {\n      case DLL_PROCESS_ATTACH:\n         // DLL is loaded. Do your initialization here.\n         // If cannot init, set rc to FALSE.\n         hInst = hInstance;\n         break;\n\n      case DLL_PROCESS_DETACH:\n         // DLL is unloaded. Do your cleanup here.\n         break;\n      default:\n         break;\n      }\n   return rc;\n#endif\n}\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint FAR PASCAL WEP ( int bSystemExit )\n{\n   return 1;\n}\n#endif /* !UNZIPLIB */\n\nstatic int UnzipAllocMemory(unsigned int i, char *cmd, char *str,\n                            char ***pargVee, unsigned int *pargCee)\n{\n    if (((*pargVee)[i] = (char *)malloc(sizeof(char) * strlen(cmd)+1 ))\n        == NULL)\n    {\n        if (pargCee != NULL)\n            (*pargCee)++;\n        UnzipFreeArguments(*pargCee, pargVee);\n        fprintf(stdout, \"Unable to allocate memory in unzip library at %s\\n\",\n                str);\n        return PK_MEM;\n    }\n    strcpy((*pargVee)[i], cmd);\n    (*pargCee)++;\n    return PK_OK;\n}\n\nstatic void UnzipFreeArguments(unsigned int argCee, char ***pargVee)\n{\n    unsigned i;\n\n    /* Free the arguments in the arrays */\n    for (i = 0; i < argCee; i++)\n    {\n        free ((*pargVee)[i]);\n        (*pargVee)[i] = NULL;\n    }\n\n    /* Then free the arrays themselves */\n    free(*pargVee);\n}\n\n\nstatic int UnzipParseString(LPCSTR s, unsigned int *pargCee, char ***pargVee)\n{\n    unsigned int i = 0;\n    char *str1, *str2, *str3;\n    size_t size;\n\n    str1 = (char *) malloc(lstrlen(s)+4);\n    lstrcpy(str1, s);\n    lstrcat(str1, \" @\");\n\n    str2 = strchr(str1, '\\\"'); // get first occurance of double quote\n\n    while ((str3 = strchr(str1, '\\t')) != NULL)\n    {\n        str3[0] = ' '; // Change tabs into a single space\n    }\n\n    /* Note that if a quoted string contains multiple adjacent spaces, they\n       will not be removed, because they could well point to a valid\n       folder/file name.\n     */\n    while ((str2 = strchr(str1, '\\\"')) != NULL)\n    {\n        // Found an opening double quote; get the corresponding closing quote\n        str3 = strchr(str2+1, '\\\"');\n        if (str3 == NULL)\n        {\n            free(str1);\n            return PK_PARAM; /* Something is screwy with the\n                                string, bail out */\n        }\n        str3[0] = '\\0';  // terminate str2 with a NULL\n\n        size = _msize(*pargVee);\n        if ((*pargVee = (char **)realloc(*pargVee, size + sizeof(char *)))\n            == NULL)\n        {\n            fprintf(stdout, \"Unable to allocate memory in unzip dll\\n\");\n            return PK_MEM;\n        }\n        // argCee is incremented in UnzipAllocMemory\n        if (UnzipAllocMemory(i, str2+1, \"Creating file list from string\",\n                             pargVee, pargCee) != PK_OK)\n        {\n            free(str1);\n            return PK_MEM;\n        }\n        i++;\n        str3+=2;  // Point past the whitespace character\n        str2[0] = '\\0'; // Terminate str1\n        lstrcat(str1, str3);\n    }    // end while\n\n    /* points to first occurance of a space */\n    str2 = strchr(str1, ' ');\n\n    /*  Go through the string character by character, looking for instances\n        of two spaces together. Terminate when you find the trailing @\n    */\n    while ((str2[0] != '\\0') && (str2[0] != '@'))\n    {\n        while ((str2[0] == ' ') && (str2[1] == ' '))\n        {\n            str3 = &str2[1];\n            str2[0] = '\\0';\n            lstrcat(str1, str3);\n        }\n        str2++;\n    }\n\n    /* Do we still have a leading space? */\n    if (str1[0] == ' ')\n    {\n        str3 = &str1[1];\n        lstrcpy(str1, str3); // Dump the leading space\n    }\n\n\n    /* Okay, now we have gotten rid of any tabs and replaced them with\n       spaces, and have replaced multiple spaces with a single space. We\n       couldn't do this before because the folder names could have actually\n       contained these characters.\n    */\n\n    str2 = str3 = str1;\n\n    while ((str2[0] != '\\0') && (str3[0] != '@'))\n    {\n        str3 = strchr(str2+1, ' ');\n        str3[0] = '\\0';\n        size = _msize(pargVee);\n        if ((*pargVee = (char **)realloc(*pargVee, size + sizeof(char *)))\n            == NULL)\n        {\n            fprintf(stdout, \"Unable to allocate memory in unzip dll\\n\");\n            return PK_MEM;\n        }\n        if (UnzipAllocMemory(i, str2, \"Creating file list from string\",\n                             pargVee, pargCee) != PK_OK)\n        {\n            free(str1);\n            return PK_MEM;\n        }\n        i++;\n        str3++;\n        str2 = str3;\n    }\n    free(str1);\n    return PK_OK;\n}\n\n/* DLL calls */\n\nBOOL WINAPI Wiz_Init(pG, lpUserFunc)\nzvoid *pG;\nLPUSERFUNCTIONS lpUserFunc;\n{\n    G.message = DllMessagePrint;\n    G.statreportcb = Wiz_StatReportCB;\n    if (lpUserFunc->sound == NULL)\n       lpUserFunc->sound = DummySound;\n    G.lpUserFunctions = lpUserFunc;\n\n    SETLOCALE(LC_CTYPE, \"\");\n\n    if (!G.lpUserFunctions->print ||\n        !G.lpUserFunctions->sound ||\n        !G.lpUserFunctions->replace)\n        return FALSE;\n\n    return TRUE;\n}\n\n/*\n    StructVersID      = version of this structure (= UZ_DCL_STRUCTVER)\n    ExtractOnlyNewer  = TRUE for \"update\" without interaction\n                        (extract only newer/new files, without queries)\n    SpaceToUnderscore = TRUE if convert space to underscore\n    PromptToOverwrite = TRUE if prompt to overwrite is wanted\n    fQuiet            = quiet flag:\n                         0 = all messages, 1 = few messages, 2 = no messages\n    ncflag            = write to stdout if TRUE\n    ntflag            = test zip file\n    nvflag            = verbose listing\n    nfflag            = \"freshen\" (replace existing files by newer versions)\n    nzflag            = display zip file comment\n    ndflag            = controls (sub)directory recreation during extraction\n                        0 = junk paths from filenames\n                        1 = \"safe\" usage of paths in filenames (skip \"../\")\n                        2 = allow also unsafe path components (dir traversal)\n    noflag            = always overwriting existing files if TRUE\n    naflag            = do end-of-line translation\n    nZIflag           = get ZipInfo if TRUE\n    B_flag            = backup existing files if TRUE\n    C_flag            = be case insensitive if TRUE\n    D_flag            = controls restoration of timestamps\n                        0 = restore all timestamps (default)\n                        1 = skip restoration of timestamps for folders\n                            created on behalf of directory entries in the\n                            Zip archive\n                        2 = do not restore any timestamps; extracted files\n                            and directories get stamped with the current time\n    U_flag            = controls UTF-8 filename coding support\n                        0 = automatic UTF-8 translation enabled (default)\n                        1 = recognize UTF-8 coded names, but all non-ASCII\n                            characters are \"escaped\" into \"#Uxxxx\"\n                        2 = UTF-8 support is disabled, filename handling\n                            works exactly as in previous UnZip versions\n    fPrivilege        = 1 => restore ACLs in user mode,\n                        2 => try to use privileges for restoring ACLs\n    lpszZipFN         = zip file name\n    lpszExtractDir    = directory to extract to. This should be NULL if you\n                        are extracting to the current directory.\n */\n\nBOOL WINAPI Wiz_SetOpts(pG, lpDCL)\nzvoid *pG;\nLPDCL lpDCL;\n{\n    if (lpDCL->StructVersID != UZ_DCL_STRUCTVER)\n        return FALSE;\n\n    uO.qflag = lpDCL->fQuiet;  /* Quiet flag */\n    G.pfnames = (char **)&fnames[0];    /* assign default file name vector */\n    G.pxnames = (char **)&fnames[1];\n\n    uO.jflag = (lpDCL->ndflag == 0);\n    uO.ddotflag = (lpDCL->ndflag >= 2);\n    uO.cflag = lpDCL->ncflag;\n    uO.tflag = lpDCL->ntflag;\n    uO.vflag = lpDCL->nvflag;\n    uO.zflag = lpDCL->nzflag;\n    uO.aflag = lpDCL->naflag;\n#ifdef UNIXBACKUP\n    uO.B_flag = lpDCL->B_flag;\n#endif\n    uO.C_flag = lpDCL->C_flag;\n    uO.D_flag = lpDCL->D_flag;\n    uO.U_flag = lpDCL->U_flag;\n    uO.overwrite_all = lpDCL->noflag;\n    uO.overwrite_none = !(lpDCL->noflag || lpDCL->PromptToOverwrite);\n    uO.uflag = lpDCL->ExtractOnlyNewer || lpDCL->nfflag;\n    uO.fflag = lpDCL->nfflag;\n#ifdef WIN32\n    uO.X_flag = lpDCL->fPrivilege;\n#endif\n    uO.sflag = lpDCL->SpaceToUnderscore; /* Translate spaces to underscores? */\n    if (lpDCL->nZIflag)\n      {\n      uO.zipinfo_mode = TRUE;\n      uO.hflag = TRUE;\n      uO.lflag = 10;\n      uO.qflag = 2;\n      }\n    else\n      {\n      uO.zipinfo_mode = FALSE;\n      }\n\n    G.extract_flag = (!uO.zipinfo_mode &&\n                      !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag\n#ifdef TIMESTAMP\n                      && !uO.T_flag\n#endif\n                     );\n\n    if (lpDCL->lpszExtractDir != NULL && G.extract_flag)\n       {\n#ifndef CRTL_CP_IS_ISO\n       char *pExDirRoot = (char *)malloc(strlen(lpDCL->lpszExtractDir)+1);\n\n       if (pExDirRoot == NULL)\n           return FALSE;\n       ISO_TO_INTERN(lpDCL->lpszExtractDir, pExDirRoot);\n#else\n#  define pExDirRoot lpDCL->lpszExtractDir\n#endif\n       if (strlen(pExDirRoot) >= FILNAMSIZ)\n           {\n           /* The supplied extract root path exceed the filename size limit. */\n#ifndef CRTL_CP_IS_ISO\n           free(pExDirRoot);\n#endif\n           return FALSE;\n           }\n       uO.exdir = pExDirRoot;\n       }\n    else\n       {\n       uO.exdir = (char *)NULL;\n       }\n\n/* G.wildzipfn needs to be initialized so that do_wild does not wind\n   up clearing out the zip file name when it returns in process.c\n*/\n    if (strlen(lpDCL->lpszZipFN) >= FILNAMSIZ)\n       /* length of supplied archive name exceed the system's filename limit */\n       return FALSE;\n\n    hwildZipFN = GlobalAlloc(GPTR, FILNAMSIZ);\n    if (hwildZipFN == (HGLOBAL) NULL)\n       return FALSE;\n\n    G.wildzipfn = GlobalLock(hwildZipFN);\n    lstrcpy(G.wildzipfn, lpDCL->lpszZipFN);\n    _ISO_INTERN(G.wildzipfn);\n\n    return TRUE;    /* set up was OK */\n}\n\nstatic void FreeDllMem(__GPRO)\n{\n    if (G.wildzipfn) {\n        GlobalUnlock(hwildZipFN);\n        G.wildzipfn = NULL;\n    }\n    if (hwildZipFN)\n        hwildZipFN = GlobalFree(hwildZipFN);\n\n#ifndef CRTL_CP_IS_ISO\n    if (uO.exdir != NULL) {\n        free(uO.exdir);\n        uO.exdir = NULL;\n    }\n#endif\n\n    uO.zipinfo_mode = FALSE;\n}\n\nint WINAPI Wiz_Unzip(pG, ifnc, ifnv, xfnc, xfnv)\nzvoid *pG;\nint ifnc;\nchar **ifnv;\nint xfnc;\nchar **xfnv;\n{\n    int retcode, f_cnt;\n#ifndef CRTL_CP_IS_ISO\n    unsigned bufsize;\n    char **intern_ifv = NULL, **intern_xfv = NULL;\n#endif\n\n    if (ifnv == (char **)NULL && ifnc != 0)\n        ifnc = 0;\n    else\n        for (f_cnt = 0; f_cnt < ifnc; f_cnt++)\n            if (ifnv[f_cnt] == (char *)NULL) {\n                ifnc = f_cnt;\n                break;\n            }\n    if (xfnv == (char **)NULL && xfnc != 0)\n        xfnc = 0;\n    else\n        for (f_cnt = 0; f_cnt < xfnc; f_cnt++)\n            if (xfnv[f_cnt] == (char *)NULL) {\n                xfnc = f_cnt;\n                break;\n            }\n\n    G.process_all_files = (ifnc == 0 && xfnc == 0);         /* for speed */\n    G.filespecs = ifnc;\n    G.xfilespecs = xfnc;\n\n    if (ifnc > 0) {\n        for (f_cnt = ifnc; --f_cnt >= 0;)\n            if (strlen(ifnv[f_cnt]) > ((WSIZE>>2) - 160)) {\n                /* include filename pattern is too long for internal buffers */\n                FreeDllMem(__G);\n                return PK_PARAM;\n            }\n\n#ifdef CRTL_CP_IS_ISO\n        G.pfnames = ifnv;\n#else /* !CRTL_CP_IS_ISO */\n        intern_ifv = (char **)malloc((ifnc+1)*sizeof(char **));\n        if (intern_ifv == (char **)NULL)\n        {\n            FreeDllMem(__G);\n            return PK_BADERR;\n        }\n\n        bufsize = 0;\n        for (f_cnt = ifnc; --f_cnt >= 0;)\n            bufsize += strlen(ifnv[f_cnt]) + 1;\n        intern_ifv[0] = (char *)malloc(bufsize);\n        if (intern_ifv[0] == (char *)NULL)\n        {\n            free(intern_ifv);\n            FreeDllMem(__G);\n            return PK_BADERR;\n        }\n\n        for (f_cnt = 0; ; f_cnt++)\n        {\n            ISO_TO_INTERN(ifnv[f_cnt], intern_ifv[f_cnt]);\n            if ((f_cnt+1) >= ifnc)\n                break;\n            intern_ifv[f_cnt+1] = intern_ifv[f_cnt] +\n                                  (strlen(intern_ifv[f_cnt]) + 1);\n        }\n        intern_ifv[ifnc] = (char *)NULL;\n        G.pfnames = intern_ifv;\n#endif /* ?CRTL_CP_IS_ISO */\n    }\n\n    if (xfnc > 0) {\n        for (f_cnt = xfnc; --f_cnt >= 0;)\n            if (strlen(xfnv[f_cnt]) > ((WSIZE>>2) - 160))\n            {\n                /* exclude filename pattern is too long for internal buffers */\n#ifndef CRTL_CP_IS_ISO\n                if (ifnc > 0)\n                {\n                    free(intern_ifv[0]);\n                    free(intern_ifv);\n                }\n#endif\n                FreeDllMem(__G);\n                return PK_PARAM;\n            }\n\n#ifdef CRTL_CP_IS_ISO\n        G.pxnames = xfnv;\n#else /* !CRTL_CP_IS_ISO */\n        intern_xfv = (char **)malloc((xfnc+1)*sizeof(char **));\n        if (intern_xfv == (char **)NULL)\n        {\n            if (ifnc > 0)\n            {\n                free(intern_ifv[0]);\n                free(intern_ifv);\n            }\n            FreeDllMem(__G);\n            return PK_BADERR;\n        }\n\n        bufsize = 0;\n        for (f_cnt = xfnc; --f_cnt >= 0;)\n            bufsize += strlen(xfnv[f_cnt]) + 1;\n        intern_xfv[0] = (char *)malloc(bufsize);\n        if (intern_xfv[0] == (char *)NULL)\n        {\n            free(intern_xfv);\n            if (ifnc > 0)\n            {\n                free(intern_ifv[0]);\n                free(intern_ifv);\n            }\n            FreeDllMem(__G);\n            return PK_BADERR;\n        }\n\n        for (f_cnt = 0; ; f_cnt++)\n        {\n            ISO_TO_INTERN(xfnv[f_cnt], intern_xfv[f_cnt]);\n            if ((f_cnt+1) >= xfnc)\n                break;\n            intern_xfv[f_cnt+1] = intern_xfv[f_cnt] +\n                                  (strlen(intern_xfv[f_cnt]) + 1);\n        }\n        intern_xfv[xfnc] = (char *)NULL;\n        G.pxnames = intern_xfv;\n#endif /* ?CRTL_CP_IS_ISO */\n    }\n\n/*---------------------------------------------------------------------------\n    Okey dokey, we have everything we need to get started.  Let's roll.\n  ---------------------------------------------------------------------------*/\n\n    retcode = setjmp(dll_error_return);\n    if (retcode)\n    {\n#ifndef CRTL_CP_IS_ISO\n        if (xfnc > 0)\n        {\n            free(intern_xfv[0]);\n            free(intern_xfv);\n        }\n        if (ifnc > 0)\n        {\n            free(intern_ifv[0]);\n            free(intern_ifv);\n        }\n#endif\n        FreeDllMem(__G);\n        return PK_BADERR;\n    }\n\n    retcode = process_zipfiles(__G);\n#ifndef CRTL_CP_IS_ISO\n    if (xfnc > 0)\n    {\n        free(intern_xfv[0]);\n        free(intern_xfv);\n    }\n    if (ifnc > 0)\n    {\n        free(intern_ifv[0]);\n        free(intern_ifv);\n    }\n#endif\n    FreeDllMem(__G);\n    return retcode;\n}\n\n\n/*\nifnc       = number of file names being passed. If all files are to be\n             extracted, then this can be zero.\nifnv       = file names to be unarchived. Wildcard patterns are recognized\n             and expanded. If all files are to be extracted, then this can\n             be NULL.\nxfnc       = number of \"file names to be excluded from processing\" being\n             passed. If all files are to be extracted, set this to zero.\nxfnv       = file names to be excluded from the unarchiving process. Wildcard\n             characters are allowed and expanded. If all files are to be\n             extracted, set this argument to NULL.\nlpDCL      = pointer to a structure with the flags for setting the\n             various options, as well as the zip file name.\nlpUserFunc = pointer to a structure that contains pointers to functions\n             in the calling application, as well as sizes passed back to\n             the calling application etc.\n*/\n\nint WINAPI Wiz_SingleEntryUnzip(int ifnc, char **ifnv, int xfnc, char **xfnv,\n   LPDCL lpDCL, LPUSERFUNCTIONS lpUserFunc)\n{\n   int retcode;\n   CONSTRUCTGLOBALS();\n\n   if (!Wiz_Init((zvoid *)&G, lpUserFunc))\n   {\n      DESTROYGLOBALS();\n      return PK_BADERR;\n   }\n\n   if (lpDCL->lpszZipFN == NULL)\n   {\n      /* Something has screwed up, we don't have a filename */\n      DESTROYGLOBALS();\n      return PK_NOZIP;\n   }\n\n   if (!Wiz_SetOpts((zvoid *)&G, lpDCL))\n   {\n      DESTROYGLOBALS();\n      return PK_MEM;\n   }\n\n#ifdef SFX\n   G.zipfn = lpDCL->lpszZipFN;\n   G.argv0 = lpDCL->lpszZipFN;\n#endif\n\n   /* Here is the actual call to \"unzip\" the files (or whatever else you\n    * are doing.)\n    */\n   retcode = Wiz_Unzip((zvoid *)&G, ifnc, ifnv, xfnc, xfnv);\n\n   DESTROYGLOBALS();\n   return retcode;\n}\n\n\n/*\nThis calling wrapper provided a method to pass file lists as plain strings\ninstead of the usual string arrays. For VB Users only...\nifnc       = number of file names being passed. If all files are to be\n             extracted, then this can be zero.\nExtList    = Pointer to a list of file names to be extracted, separated by\n             white space. If all files are to be extracted, then this should\n             be NULL. Parameter ifnc should have an accurate count of the\n             number of filenames being passed in.\nxfnc       = number of \"file names to be excluded from processing\" being\n             passed. If all files are to be extracted, set this to zero.\nExcList    = Pointer to a list of file names to be excluded from processing.\n             Parameter xfnc should have an accurate count of the number of\n             the number of filenames being passed in.\nlpDCL      = pointer to a structure with the flags for setting the\n             various options, as well as the zip file name.\nlpUserFunc = pointer to a structure that contains pointers to functions\n             in the calling application, as well as sizes passed back to\n             the calling application etc.\n*/\n\nint WINAPI Wiz_SingleEntryUnzpList(unsigned int ifnc, LPCSTR ExtList,\n   unsigned int xfnc, LPCSTR ExcList,\n   LPDCL lpDCL, LPUSERFUNCTIONS lpUserFunc)\n{\n    int retcode;\n    char **argVExt, **argVExc;\n    unsigned int argCExt, argCExc;\n\n    argCExt = argCExc = 0;\n\n    if (ExtList != NULL)\n    {\n        if ((argVExt = (char **)malloc((ifnc)*sizeof(char *))) == NULL)\n        {\n            fprintf(stdout, \"Unable to allocate memory in unzip dll\\n\");\n            return PK_MEM;\n        }\n        if ((retcode = UnzipParseString(ExtList, &argCExt, &argVExt)) != PK_OK)\n            return retcode;\n    }\n\n    if (ExcList != NULL)\n    {\n        if ((argVExc = (char **)malloc((ifnc)*sizeof(char *))) == NULL)\n        {\n            fprintf(stdout, \"Unable to allocate memory in unzip dll\\n\");\n            UnzipFreeArguments(argCExt, &argVExt);\n            return PK_MEM;\n        }\n        if ((retcode = UnzipParseString(ExcList, &argCExc, &argVExc)) != PK_OK)\n        {\n            UnzipFreeArguments(argCExt, &argVExt);\n            return retcode;\n        }\n    }\n\n    retcode = Wiz_SingleEntryUnzip(argCExt, argVExt, argCExc, argVExc,\n                                   lpDCL, lpUserFunc);\n    UnzipFreeArguments(argCExc, &argVExc);\n    UnzipFreeArguments(argCExt, &argVExt);\n    return retcode;\n}\n\n\nint win_fprintf(zvoid *pG, FILE *file, unsigned int size, char far *buffer)\n{\n   if ((file != stderr) && (file != stdout))\n   {\n      return write(fileno(file),(char far *)(buffer),size);\n   }\n   if (!fNoPrinting)\n      return G.lpUserFunctions->print((LPSTR)buffer, size);\n   return (int)size;\n}\n\n/**********************************\n * Function DllMessagePrint()     *\n *                                *\n * Send messages to status window *\n **********************************/\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nstatic int UZ_EXP DllMessagePrint(pG, buf, size, flag)\n    zvoid *pG;      /* globals struct:  always passed */\n    uch *buf;       /* preformatted string to be printed */\n    ulg size;       /* length of string (may include nulls) */\n    int flag;       /* flag bits */\n{\n    if (!fNoPrinting)\n        return G.lpUserFunctions->print((LPSTR)buf, size);\n    else\n        return (int)size;\n}\n\n#if 0 /* currently unused */\n/********************************\n * Function DllDisplayPrint()   *\n *                              *\n * Send files to display window *\n ********************************/\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint DllDisplayPrint(pG, buf, size, flag)\n    zvoid *pG;      /* globals struct:  always passed */\n    uch *buf;       /* preformatted string to be printed */\n    ulg size;       /* length of string (may include nulls) */\n    int flag;       /* flag bits */\n{\n    return (!fNoPrinting\n            ? G.lpUserFunctions->print((LPSTR)buf, size)\n            : (int)size);\n}\n#endif /* never */\n\n\n/**********************************\n * Function UzpPassword()         *\n *                                *\n * Prompt for decryption password *\n **********************************/\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint UZ_EXP UzpPassword(pG, rcnt, pwbuf, size, zfn, efn)\n    zvoid *pG;          /* globals struct: always passed */\n    int *rcnt;          /* retry counter */\n    char *pwbuf;        /* buffer for password */\n    int size;           /* size of password buffer */\n    ZCONST char *zfn;   /* name of zip archiv */\n    ZCONST char *efn;   /* name of archiv entry being processed */\n{\n#if CRYPT\n    LPCSTR m;\n\n    if (*rcnt == 0) {\n        *rcnt = 2;\n        m = \"Enter password for: \";\n    } else {\n        (*rcnt)--;\n        m = \"Password incorrect--reenter: \";\n    }\n\n    return (*G.lpUserFunctions->password)((LPSTR)pwbuf, size, m, (LPCSTR)efn);\n#else /* !CRYPT */\n    return IZ_PW_ERROR; /* internal error, function should never get called */\n#endif /* ?CRYPT */\n} /* end function UzpPassword() */\n\n/* Turn off all messages to the calling application */\nvoid WINAPI Wiz_NoPrinting(int f)\n{\n    fNoPrinting = f;\n}\n\n/* Dummy sound function for those applications that don't use sound */\nstatic void WINAPI DummySound(void)\n{\n}\n\n/* Interface between WINDLL specific service callback functions and the\n   generic DLL's \"status report & user interception\" callback */\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nstatic int WINAPI Wiz_StatReportCB(zvoid *pG, int fnflag, ZCONST char *zfn,\n                    ZCONST char *efn, ZCONST zvoid *details)\n{\n    int rval = UZ_ST_CONTINUE;\n\n    switch (fnflag) {\n      case UZ_ST_START_EXTRACT:\n        if (G.lpUserFunctions->sound != NULL)\n            (*G.lpUserFunctions->sound)();\n        break;\n      case UZ_ST_FINISH_MEMBER:\n        if ((G.lpUserFunctions->ServCallBk != NULL) &&\n            (*G.lpUserFunctions->ServCallBk)(efn,\n                                             (details == NULL ? 0L :\n#ifdef Z_UINT8_DEFINED\n                                              (z_uint8)(*((zusz_t *)details))\n#else\n                                              *((zusz_t *)details)\n#endif\n                                             )))\n            rval = UZ_ST_BREAK;\n        else if (G.lpUserFunctions->ServCallBk_i32 != NULL) {\n             unsigned long siz_u4L = 0L;\n             unsigned long siz_u4H = 0L;\n             if (details != NULL) {\n                 siz_u4L = (unsigned long)(*(zusz_t *)details);\n#ifdef ZIP64_SUPPORT\n                 siz_u4H = (unsigned long)((*(zusz_t *)details) >> 32);\n#endif\n             }\n             if ((*G.lpUserFunctions->ServCallBk_i32)(efn, siz_u4L, siz_u4H))\n                 rval = UZ_ST_BREAK;\n        }\n        break;\n      case UZ_ST_IN_PROGRESS:\n        break;\n      default:\n        break;\n    }\n    return rval;\n}\n\n\n#ifndef SFX\n#ifndef __16BIT__\n\nint WINAPI Wiz_UnzipToMemory(LPSTR zip, LPSTR file,\n    LPUSERFUNCTIONS lpUserFunctions, UzpBuffer *retstr)\n{\n    int r;\n#ifndef CRTL_CP_IS_ISO\n    char *intern_zip, *intern_file;\n#endif\n\n    CONSTRUCTGLOBALS();\n#ifndef CRTL_CP_IS_ISO\n    intern_zip = (char *)malloc(strlen(zip)+1);\n    if (intern_zip == NULL) {\n       DESTROYGLOBALS();\n       return PK_MEM;\n    }\n    intern_file = (char *)malloc(strlen(file)+1);\n    if (intern_file == NULL) {\n       DESTROYGLOBALS();\n       free(intern_zip);\n       return PK_MEM;\n    }\n    ISO_TO_INTERN(zip, intern_zip);\n    ISO_TO_INTERN(file, intern_file);\n#   define zip intern_zip\n#   define file intern_file\n#endif\n    if (!Wiz_Init((zvoid *)&G, lpUserFunctions)) {\n       DESTROYGLOBALS();\n       return PK_BADERR;\n    }\n    G.redirect_data = 1;\n\n    r = (unzipToMemory(__G__ zip, file, retstr) == PK_COOL);\n\n    DESTROYGLOBALS();\n#ifndef CRTL_CP_IS_ISO\n#  undef file\n#  undef zip\n    free(intern_file);\n    free(intern_zip);\n#endif\n    if (!r && retstr->strlength) {\n       free(retstr->strptr);\n       retstr->strptr = NULL;\n    }\n    return r;\n}\n\n\n\n\n/* Purpose: Determine if file in archive contains the string szSearch\n\n   Parameters: archive  = archive name\n               file     = file contained in the archive. This cannot be\n                          a wildcard to be meaningful\n               pattern  = string to search for\n               cmd      = 0 - case-insensitive search\n                          1 - case-sensitve search\n                          2 - case-insensitive, whole words only\n                          3 - case-sensitive, whole words only\n               SkipBin  = if true, skip any files that have control\n                          characters other than CR, LF, or tab in the first\n                          100 characters.\n\n   Returns:    TRUE if a match is found\n               FALSE if no match is found\n               -1 on error\n\n   Comments: This does not pretend to be as useful as the standard\n             Unix grep, which returns the strings associated with a\n             particular pattern, nor does it search past the first\n             matching occurrence of the pattern.\n */\n\nint WINAPI Wiz_Grep(LPSTR archive, LPSTR file, LPSTR pattern, int cmd,\n                   int SkipBin, LPUSERFUNCTIONS lpUserFunctions)\n{\n    int retcode = FALSE, compare;\n    ulg i, j, patternLen, buflen;\n    char * sz, *p;\n    UzpBuffer retstr;\n\n    /* Turn off any windows printing functions, as they may not have been\n     * identified yet. There is no requirement that we initialize the\n     * dll with printing stuff for this. */\n    Wiz_NoPrinting(TRUE);\n\n    if (!Wiz_UnzipToMemory(archive, file, lpUserFunctions, &retstr)) {\n       Wiz_NoPrinting(FALSE);\n       return -1;   /* not enough memory, file not found, or other error */\n    }\n\n    if (SkipBin) {\n        if (retstr.strlength < 100)\n            buflen = retstr.strlength;\n        else\n            buflen = 100;\n        for (i = 0; i < buflen; i++) {\n            if (iscntrl(retstr.strptr[i])) {\n                if ((retstr.strptr[i] != 0x0A) &&\n                    (retstr.strptr[i] != 0x0D) &&\n                    (retstr.strptr[i] != 0x09))\n                {\n                    /* OK, we now think we have a binary file of some sort */\n                    free(retstr.strptr);\n                    Wiz_NoPrinting(FALSE);\n                    return FALSE;\n                }\n            }\n        }\n    }\n\n    patternLen = strlen(pattern);\n\n    if (retstr.strlength < patternLen) {\n        free(retstr.strptr);\n        Wiz_NoPrinting(FALSE);\n        return FALSE;\n    }\n\n    sz = malloc(patternLen + 3); /* add two in case doing whole words only */\n    if (cmd > 1) {\n        strcpy(sz, \" \");\n        strcat(sz, pattern);\n        strcat(sz, \" \");\n    } else\n        strcpy(sz, pattern);\n\n    if ((cmd == 0) || (cmd == 2)) {\n        for (i = 0; i < strlen(sz); i++)\n            sz[i] = toupper(sz[i]);\n        for (i = 0; i < retstr.strlength; i++)\n            retstr.strptr[i] = toupper(retstr.strptr[i]);\n    }\n\n    for (i = 0; i < (retstr.strlength - patternLen); i++) {\n        p = &retstr.strptr[i];\n        compare = TRUE;\n        for (j = 0; j < patternLen; j++) {\n            /* We cannot do strncmp here, as we may be dealing with a\n             * \"binary\" file, such as a word processing file, or perhaps\n             * even a true executable of some sort. */\n            if (p[j] != sz[j]) {\n                compare = FALSE;\n                break;\n            }\n        }\n        if (compare == TRUE) {\n            retcode = TRUE;\n            break;\n        }\n    }\n\n    free(sz);\n    free(retstr.strptr);\n    Wiz_NoPrinting(FALSE); /* Turn printing back on */\n    return retcode;\n}\n#endif /* !__16BIT__ */\n\nint WINAPI Wiz_Validate(LPSTR archive, int AllCodes)\n{\n    return UzpValidate((char *)archive, AllCodes);\n}\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll.h",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __windll_h   /* prevent multiple inclusions */\n#define __windll_h\n\n#include <windows.h>\n#include <assert.h>    /* required for all Windows applications */\n#include <setjmp.h>\n\n#include \"../unzip.h\"\n#include \"../windll/structs.h\"\n#include \"../windll/decs.h\"\n\n/* Allow compilation under Borland C++ also */\n#ifndef __based\n#  define __based(A)\n#endif\n\n#ifdef UNZIP_INTERNAL\n\nextern jmp_buf dll_error_return;\n\nextern HANDLE hInst;        /* current instance */\n\nint win_fprintf(zvoid *pG, FILE *file, unsigned int, char far *);\n#endif\n\n#endif /* __windll_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll.rc",
    "content": "#include <windows.h>\n#if (defined(WIN32) && !defined(__EMX__) && !defined(__MINGW32__))\n#include <winver.h>\n#endif\n#include \"../unzvers.h\"\n\nVS_VERSION_INFO VERSIONINFO\nFILEVERSION UZ_MAJORVER,UZ_MINORVER,UZ_PATCHLEVEL,0\nPRODUCTVERSION UZ_MAJORVER,UZ_MINORVER,UZ_PATCHLEVEL,0\nFILEFLAGSMASK 0x3L\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\nFILEOS VOS__WINDOWS32\nFILETYPE VFT_DLL\nFILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        BLOCK \"040904B0\"\n#else\n        BLOCK \"040904E4\"\n#endif\n        BEGIN\n            VALUE \"Comments\", \"\\0\"\n            VALUE \"CompanyName\", IZ_COMPANY_NAME \"\\0\"\n            VALUE \"FileDescription\", \"Info-ZIP's UnZip DLL for Win32\\0\"\n            VALUE \"FileVersion\", UZ_VER_STRING \"\\0\"\n            VALUE \"InternalName\", \"UnZip32\\0\"\n            VALUE \"LegalCopyright\", \"Info-ZIP 1996-2009\\0\"\n            VALUE \"LegalTrademarks\", \"\\0\"\n            VALUE \"OriginalFilename\", \"UNZIP32.DLL\\0\"\n            VALUE \"PrivateBuild\", \"\\0\"\n            VALUE \"ProductName\", \"Info-ZIP's UnZip Windows DLL\\0\"\n            VALUE \"ProductVersion\", UZ_VER_STRING \"\\0\"\n            VALUE \"SpecialBuild\", \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        VALUE \"Translation\", 0x409, 1200\n#else\n        VALUE \"Translation\", 0x409, 1252\n#endif\n    END\nEND\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll.txt",
    "content": "There are now several entry points to the dll.\n\nThere is a single \"unzipping\" entry point of:\n\nint WINAPI Wiz_SingleEntryUnzip(int ifnc, char **ifnv, int xfnc, char **xfnv,\n                                LPDCL lpDCL, LPUSERFUNCTIONS lpUserFunc)\n\nwhere the arguments are:\n\nifnc       = number of file names being passed. If all files are to be\n             extracted, then this can be zero.\nifnv       = file names to be unarchived. Wildcard patterns are recognized\n             and expanded. If all files are to be extracted, then this can\n             be NULL.\nxfnc       = number of \"file names to be excluded from processing\" being\n             passed. If all files are to be extracted, set this to zero.\nxfnv       = file names to be excluded from the unarchiving process. Wildcard\n             characters are allowed and expanded. If all files are to be\n             extracted, set this argument to NULL.\nlpDCL      = pointer to a structure with the flags for setting the\n             various options, as well as the zip file name.\nlpUserFunc = pointer to a structure that contains pointers to functions\n             in the calling application, as well as sizes passed back to\n             the calling application etc. See below for a detailed description\n             of all the parameters.\n\nThis calling wrapper for Wiz_SingleEntryUnzip() provides a method to pass\nfile lists as plain strings instead of the usual string arrays.\nFor VB Users only...:\n\nint WINAPI Wiz_SingleEntryUnzpList(unsigned int ifnc, LPCSTR ExtList,\n                                   unsigned int xfnc, LPCSTR ExcList,\n                                   LPDCL lpDCL, LPUSERFUNCTIONS lpUserFunc)\n\nifnc       = number of file names being passed. If all files are to be\n             extracted, then this can be zero.\nExtList    = Pointer to a list of file names to be extracted, separated by\n             white space. If all files are to be extracted, then this should\n             be NULL. Parameter ifnc should have an accurate count of the\n             number of filenames being passed in.\nxfnc       = number of \"file names to be excluded from processing\" being\n             passed. If all files are to be extracted, set this to zero.\nExcList    = Pointer to a list of file names to be excluded from processing.\n             Parameter xfnc should have an accurate count of the number of\n             the number of filenames being passed in.\nlpDCL      = pointer to a structure with the flags for setting the\n             various options, as well as the zip file name.\nlpUserFunc = pointer to a structure that contains pointers to functions\n             in the calling application, as well as sizes passed back to\n             the calling application etc.\n\n\nThe DCL structure collects the set of option flags supported by the WinDLL\ninterface to control the operation of the main function calls.\nThe first member of this structure is now a version identifier that should\nbe used to check structural compatibility of a passed option struct with\nthe expected structure layout. The C header file containing the reference\ndefinition of the DCL structure also provides a symbol denoting the currently\nvalid StructVersID:\n\n#define UZ_DCL_STRUCTVER        0x600\n\nThe layout of the DCL structure is shown below:\n\ntypedef struct {\n unsigned StructVersID  = struct version id (= UZ_DCL_STRUCTVER)\n int ExtractOnlyNewer   = TRUE for \"update\" without interaction\n                          (extract only newer/new files, without queries)\n int SpaceToUnderscore  = TRUE if convert space to underscore\n int PromptToOverwrite  = TRUE if prompt to overwrite is wanted\n int fQuiet             = quiet flag:\n                           0 = all messages, 1 = few messages, 2 = no messages\n int ncflag             = write to stdout if TRUE\n int ntflag             = test zip file\n int nvflag             = verbose listing\n int nfflag             = \"freshen\" (replace existing files by newer versions)\n int nzflag             = display zip file comment\n int ndflag             = controls (sub)directory recreation during extraction\n                          0 = junk paths from filenames\n                          1 = \"safe\" usage of paths in filenames (skip \"../\")\n                          2 = allow also unsafe path components (dir traversal)\n int noflag             = always overwriting existing files if TRUE\n int naflag             = do end-of-line translation\n int nZIflag            = get ZipInfo if TRUE\n int B_flag             = backup existing files if TRUE\n int C_flag             = be case insensitive if TRUE\n int D_flag             = controls restoration of timestamps\n                          0 = restore all timestamps (default)\n                          1 = skip restoration of timestamps for folders\n                              created on behalf of directory entries in the\n                              Zip archive\n                          2 = do not restore any timestamps; extracted files\n                              and directories get stamped with the current time\n int U_flag             = controls UTF-8 filename coding support\n                          0 = automatic UTF-8 translation enabled (default)\n                          1 = recognize UTF-8 coded names, but all non-ASCII\n                              characters are \"escaped\" into \"#Uxxxx\"\n                          2 = UTF-8 support is disabled, filename handling\n                              works exactly as in previous UnZip versions\n int fPrivilege         = 1 => restore ACLs in user mode,\n                          2 => try to use privileges for restoring ACLs\n LPSTR lpszZipFN        = zip file name\n LPSTR lpszExtractDir   = directory to extract to. This should be NULL if you\n                          are extracting to the current directory.\n} DCL, far * LPDCL;\n\nREMARKS:\nThe four extract-mode flags ExtractOnlyNewer, nfflag, PromptToOverwrite, and\nnoflag control which of the selected archive entries are actually processed.\nThey are mapped to UnZip's command line qualifiers \"-u\", \"-f\", \"-o\", \"-n\"\naccording to the following decision matrix:\n _____________________________________________________________________\n | UnZip 1)|| Extract-  | nfflag | noflag | PrompTo-  | lpUserFunc   |\n | options || OnlyNewer |        |        | Overwrite | ->replape()  |\n =====================================================================\n | none 2) ||   false   |  false |  false |   true    |queryfunc() 5)|\n | -o      ||   false   |  false |  true  |   false   |     N/A      |\n | -n      ||   false   |  false |  false |   false   |     N/A      |\n |---------||-----------|--------|--------|-----------|--------------|\n | -u      ||   true    |  false |  false |   true    |queryfunc() 5)|\n | -uo     ||   true    |  false |  true  |   false   |     N/A      |\n | -un  3) ||   true    |  false |  false |   false   |     N/A      |\n |---------||-----------|--------|--------|-----------|--------------|\n | -f      ||    N/A    |  true  |  false |   true    |queryfunc() 5)|\n | -fo     ||    N/A    |  true  |  true  |   false   |     N/A      |\n | -fn  4) ||    N/A    |  true  |  false |   false   |     N/A      |\n ---------------------------------------------------------------------\n Legend: true:  integer number <> 0\n         false: integer number 0\n         N/A:   not applicable, could be set to any value\n NOTES:\n 1) The UnZip options are explained in the generic UnZip manual, see\n    \"unzip.txt\" or \"man/unzip.1\".\n 2) no options from the set \"ufno\" are specified.\n 3) -un is functionally equivalent to -n\n 4) -fn is functionally equivalent to \"do nothing\", so this combination\n    does not make sense.\n 5) queryfunc() is a callback function provided by the caller of the\n    unzip dll that may return one of the following result keys:\n     IDM_REPLACE_NO, IDM_REPLACE_YES,\n     IDM_REPLACE_ALL, IDM_REPLACE_NONE,\n     IDM_REPLACE_RENAME\n     (IDM_REPLACE_TEXT, IDM_REPLACE_HELP are defined but not used)\n    UnZip's internal code treats a \"NULL\" lpUserFunc->replace() function\n    pointer as \"{return IDM_REPLACE_NONE}\". However, currently, the windll\n    interface checks for this function pointer to be not NULL and signals\n    a fatal error if this condition is not fulfilled.\n\n\nThe typedef's for the function pointers in the structure USERFUNCTIONS\nare shown immediately below.\n\ntypedef unsigned short ush;\ntypedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);\ntypedef int (WINAPI DLLPASSWORD) (LPSTR pwbuf, int bufsiz,\n    LPCSTR promptmsg, LPCSTR entryname);\ntypedef int (WINAPI DLLSERVICE) (LPCSTR entryname, z_uint8 uncomprsiz);\ntypedef int (WINAPI DLLSERVICE_I32) (LPCSTR entryname,\n    unsigned long ucsz_lo, unsigned long ucsz_hi);\ntypedef void (WINAPI DLLSND) (void);\ntypedef int (WINAPI DLLREPLACE) (LPSTR efnam, unsigned efbufsiz);\ntypedef void (WINAPI DLLMESSAGE) (z_uint8 ucsize, z_uint8 csize,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\ntypedef void (WINAPI DLLMESSAGE_I32) (unsigned long ucsiz_l,\n    unsigned long ucsiz_h, unsigned long csiz_l, unsigned long csiz_h,\n    unsigned cfactor,\n    unsigned mo, unsigned dy, unsigned yr, unsigned hh, unsigned mm,\n    char c, LPCSTR filename, LPCSTR methbuf, unsigned long crc, char fCrypt);\n\nStructure USERFUNCTIONS\n\ntypedef struct {\n DLLPRNT *print;        = a pointer to the application's print routine.\n DLLSND *sound;         = a pointer to the application's sound routine. This\n                          can be NULL if your application doesn't use\n                          sound.\n DLLREPLACE *replace    = a pointer to the application's replace routine. The\n                          replace routine may modify the content of the efnam\n                          string buffer, but must not write beyond its fixed\n                          size of efbufsiz bytes! (This is a potential security\n                          leak of the windll interface.) When modifying the\n                          efnam buffer, the replace routine should return\n                          the status IDM_REPLACE_RENAME.\n DLLPASSWORD *password  = a pointer to the application's password routine.\n                          This function should return one of the status values\n                          IZ_PW_ENTERED (0), IZ_PW_CANCEL (-1),\n                          IZ_PW_CANCEL_ALL (-2), IZ_PW_ERROR (5).\n DLLMESSAGE *SendApplicationMessage = a pointer to the application's routine\n                          for displaying information about specific files\n                          in the archive. Used for listing the contents of\n                          an archive.\n DLLSERVICE *ServCallBk  = Callback function designed to be used for\n                          allowing the application to process Windows messages,\n                          or canceling the operation, as well as giving the\n                          option of a progress indicator. If this function\n                          returns a non-zero value, then it will terminate\n                          what it is doing. It provides the application with\n                          the name of the archive member it has just processed,\n                          as well as it's original size.\n DLLMESSAGE_I32 *SendApplicationMessage_i32 = variant of SendApplicationMessage\n                          callback, for environments that do not support the\n                          64-bit integer types required to transfer \"large\"\n                          ZIP64-compatible sizes.\n DLLSERVICE_I32 *ServCallBk_i32  = variant of the ServCallBk callback function,\n                          for environments that do not support 64-bit integers.\n [NOTE: The _i32 variants of the SendApplicationMessage and ServCallBk callback\n        functions are only called when the corresponding \"regular\" callback\n        function pointers are set to NULL.  For the i386 architecture, the\n        \"..._i32\" calling interfaces are binary identical with the\n        corresponding regular __int64-aware interfaces.]\n [NOTE: The values below are filled in only when listing the contents of an\n        archive.]\n z_uint8 TotalSizeComp  = value to be filled in by the dll for the\n                          compressed total size of the archive. Note this\n                          value does not include the size of the archive\n                          header and central directory list.\n z_uint8 TotalSize      = value to be filled in by the dll for the total\n                          size of all files in the archive.\n z_uint8 NumMembers     = total number of files in the archive.\n unsigned CompFactor    = value to be filled in by the dll for the overall\n                          compression factor. This could actually be computed\n                          from the other values, but it is available.\n WORD cchComment        = flag to be set if archive has a comment\n} USERFUNCTIONS, far * LPUSERFUNCTIONS;\n\nWiz_SingleEntryUnzip() returns a PKWARE compatible error code (0 if no\nerror or warning). For an explanation of the supported error codes see\nthe UnZip user documentation (the UnZip man page).\n\nFor examples of how the actual calls to the dll are set up in WiZ, look in\nthe files action.c and wizmain.c in the WiZ source directory. For a trival\nexample of how to load and call the dll, look in uzexampl.c and uzexampl.h.\n\nFor examples of how the actual loading and unloading of the dll's themselves\nwas done, look in wizmain.c in the WiZ source directory. Note that WiZ looks\nspecifically for a particular version number of the dll, and also expects to\nfind the company name to be Info-ZIP. This is to protect from getting\ndifferent versions of the dll loaded, with resulting unknown behavior.\n\nAdditional entry points:\n\n    const UzpVer * WINAPI UzpVersion(void);\n\nwhere UzpVer is defined as:\n\ntypedef struct _UzpVer {\n    ulg structlen;            /* length of the struct being passed */\n    ulg flag;                 /* bit 0: is_beta   bit 1: uses_zlib */\n    LPCSTR betalevel;         /* e.g. \"g BETA\" or \"\" */\n    LPCSTR date;              /* e.g. \"9 Oct 08\" (beta) or \"9 October 2008\" */\n    LPCSTR zlib_version;      /* e.g. \"1.2.3\" or NULL */\n    _version_type unzip;      /* current UnZip version */\n    _version_type zipinfo;    /* current ZipInfo version */\n    _version_type os2dll;     /* OS2DLL version (retained for compatibility) */\n    _version_type windll;     /* WinDLL version (retained for compatibility) */\n    _version_type dllapimin;  /* last incompatible change of library API */\n} UzpVer;\n\nand _version_type is defined as:\n\ntypedef struct _ver {\n    uch major;              /* e.g., integer 5 */\n    uch minor;              /* e.g., 2 */\n    uch patchlevel;         /* e.g., 0 */\n    uch not_used;\n} _version_type;\n\n    See api.c for exactly what UzpVersion does, but the short description is\n    \"UzpVersion() returns a pointer to a dll-internal static structure\n    containing the unzip32.dll version information\".\n\nFor usage with languages that do not support function which return pointers\nto structures, the variant UzpVersion2() allows to retrieve the version info\ninto a memory area supplied by the caller:\n\n    unsigned WINAPI UzpVersion2(UzpVer2 far *);\n\nwhere UzpVer2 is defined as:\n\ntypedef struct _UzpVer2 {\n    ulg structlen;            /* length of the struct being passed */\n    ulg flag;                 /* bit 0: is_beta   bit 1: uses_zlib */\n    char betalevel[10];       /* e.g. \"g BETA\" or \"\" */\n    char date[20];            /* e.g. \"9 Oct 08\" (beta) or \"9 October 2008\" */\n    char zlib_version[10];    /* e.g. \"1.2.3\" or NULL */\n    _version_type unzip;      /* current UnZip version */\n    _version_type zipinfo;    /* current ZipInfo version */\n    _version_type os2dll;     /* OS2DLL version (retained for compatibility) */\n    _version_type windll;     /* WinDLL version (retained for compatibility) */\n    _version_type dllapimin;  /* last incompatible change of library API */\n} UzpVer2;\n\n   See api.c for the exact function of UzpVersion2, but the short description\n   is \"fill in the version information in the UzpVer2 structure\".\n\nvoid WINAPI Wiz_NoPrinting(int flag)\n\n   This entry point simply turns off all messages to the calling application if\n   flag is true, and turns them on if flag is false.\n\nint WINAPI Wiz_Validate(LPSTR archive, int AllCodes)\n\n   If AllCodes is FALSE, then Unz_Validate returns TRUE if archive points to a\n   valid archive, and FALSE otherwise. If AllCodes is TRUE, then Unz_Validate\n   returns whatever error code process_zipfiles returns, without evaluating it.\n\nint WINAPI Wiz_UnzipToMemory(LPSTR zip, LPSTR file, LPUSERFUNCTIONS lpUserFunc,\n                             UzpBuffer *retstr)\n\n   Where UzpBuffer is defined as:\n\n   typedef struct _UzpBuffer {\n      ulg strlength; /* length of string */\n      char * strptr; /* pointer to string */\n   } UzpBuffer\n\n   Pass the name of the zip file in zip and the name of the file you wish to\n   extract in file. UzpUnzipToMemory will create a buffer and return it in\n   *retstr. 0 on return indicates failure.\n\nvoid WINAPI UzpFreeMemBuffer(UzpBuffer *retstr)\n   Use this routine to release the return data space allocated by the function\n   Wiz_UnzipToMemory().\n\nint WINAPI Wiz_Grep(LPSTR archive, LPSTR file, LPSTR pattern, int cmd,\n                    int SkipBin, LPUSERFUNCTIONS lpUserFunc)\n\n   Pass the name of the zip file in \"zip\", the name of the zip entry you wish\n   to perform the \"grep\" on in \"file\", and the string you wish to look for in\n   \"pattern\". There are four possible options for cmd:\n\n   0 => case insensitive search\n   1 => case sensitive search\n   2 => case insensitive search, whole words only\n   3 => case sensitive search, whole words only\n\n   If SkipBin is TRUE, then any binary (loosely interpreted) files will be\n   ignored.\n\n   lpUserFunc is a pointer to a USERFUNCTION structure as shown above.\n\n   UzpGrep returns:\n\n   -1 => error such as unable to allocate memory, unable to find file, etc.\n    0 => match not found, based on the search criteria\n    1 => match found, based on the search criteria\n\nThere is an additional function call that does not specifically deal with\n\"unzipping\", but is a quite useful function that is currently used in Wiz\nitself in several places. This call is currently only available in the\nstatic library, not in the DLL.\n\nMatch the pattern (wildcard) against the string (fixed):\n\n  match(const char *string, const char *pattern, int ignore_case);\n\nor, when UnZips WILD_SEP_AT_DIR compile-time option was set:\n\n  match(const char *string, const char *pattern, int ignore_case, int sepc);\n\n  returns TRUE if string matches pattern, FALSE otherwise.  In the pattern:\n\n     `*' matches any sequence of characters (zero or more)\n     `?' matches any single character\n     [SET] matches any character in the specified set,\n     [!SET] or [^SET] matches any character not in the specified set.\n\n  In case the code was compiled with WILD_STOP_AT_DIR enabled, the pattern\n  wildcard functionality is modified as follows:\n     `*' matches any sequence of characters (zero or more) until the first\n         occurence of the separating character denoted by `sepc'\n     `**' matches any sequence of characters (zero or more)\n\n  A set is composed of characters or ranges; a range looks like ``character\n  hyphen character'' (as in 0-9 or A-Z).  [0-9a-zA-Z_] is the minimal set of\n  characters allowed in the [..] pattern construct.  Other characters are\n  allowed (i.e., 8-bit characters) if your system will support them.\n\n  To suppress the special syntactic significance of any of ``[]*?!^-\\'', in-\n  side or outside a [..] construct, and match the character exactly, precede\n  it with a ``\\'' (backslash).\n\nThe remaining functions are linked together. Their use would be as\nfollows (explanations for each function are shown further below):\n\n    #include \"windll.h\"\n    #include \"structs.h\"\n    MyApiCallingRoutine()\n    {\n        CREATEGLOBALS();\n        .\n        .\n        .\n        Wiz_Init(pG, lpUserFunctions); /* Set up user functions */\n        /* zvoid *pG, LPUSERFUNCTIONS lpUserFunctions */\n        .\n        .\n        do {\n          .\n          .\n          Wiz_SetOpts(pG, lpDCL); /* Set up unzipping options */\n          /* zvoid *pG, LPDCL lpDCL */\n          .\n          .\n          Wiz_Unzip(pG, ifnc, ifnv, xfnc, xfnv); /* Unzip files */\n          .\n          .\n        } while (!finished_condition)\n        .\n        .\n        DESTROYGLOBALS();\n    }\n\nEach entry point is as defined below:\n\n    BOOL WINAPI Wiz_Init(zvoid *, LPUSERFUNCTIONS);\n\n    BOOL WINAPI Wiz_SetOpts(zvoid *, LPDCL);\n\n    int WINAPI Wiz_Unzip(zvoid *, int, char **, int, char **);\n\nNote that you should use either Wiz_SingleEntryUnzip OR the series of calls\ndescribed above. Using both, depending on how you do it, could cause\nproblems. The series of \"lower level\" gives you more freedom to add additional\nfunctionalities, whereas the single-entry api is easier to use. When using\nthe \"series\" of calls, make sure that Wiz_SetOpts and Wiz_Unzip are always\nused together! When successfully called, Wiz_SetOpts has allocated some\ninternal structures which are in turn free'd by Wiz_Unzip.\n\nLast revised January 18, 2009.\n\nMike White, Christian Spieler\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll16.def",
    "content": ";module-definition file for Windows UnZip16 DLL -- used by link.exe\nLIBRARY UNZIP16 ; Library module name\n\nDESCRIPTION 'Windows Info-ZIP UnZip16 DLL by Mike White'\n\nCODE  PRELOAD FIXED\n\nDATA  PRELOAD MOVEABLE\n\nEXPORTS\n     Wiz_SingleEntryUnzip\n     UzpVersion\n     Wiz_Init\n     Wiz_SetOpts\n     Wiz_Unzip\n     Wiz_Validate\n     Wiz_NoPrinting\n     UzpVersion2\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll32.def",
    "content": ";module-definition file for Windows UnZip32 DLL -- used by link.exe\nLIBRARY UNZIP32  ; Library module name\n\n;DESCRIPTION 'Windows Info-ZIP UnZip32 DLL by Mike White'\n\n;CODE  PRELOAD FIXED\n\n;DATA  PRELOAD MOVEABLE\n\nEXPORTS\n     Wiz_SingleEntryUnzip\n     Wiz_SingleEntryUnzpList\n     UzpVersion\n     Wiz_Init\n     Wiz_SetOpts\n     Wiz_Unzip\n     Wiz_Validate\n     Wiz_NoPrinting\n     UzpVersion2\n     Wiz_UnzipToMemory\n     Wiz_Grep\n     UzpFreeMemBuffer\n\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windll_lc.def",
    "content": "LIBRARY UNZIP32\n\n\nEXPORTS\n     Wiz_SingleEntryUnzip=Wiz_SingleEntryUnzip\n     Wiz_SingleEntryUnzpList=Wiz_SingleEntryUnzpList\n     UzpVersion=UzpVersion\n     Wiz_Init=Wiz_Init\n     Wiz_SetOpts=Wiz_SetOpts\n     Wiz_Unzip=Wiz_Unzip\n     Wiz_Validate=Wiz_Validate\n     Wiz_NoPrinting=Wiz_NoPrinting\n     UzpVersion2=UzpVersion2\n     Wiz_UnzipToMemory=Wiz_UnzipToMemory\n     Wiz_Grep=Wiz_Grep\n     UzpFreeMemBuffer=UzpFreeMemBuffer\n"
  },
  {
    "path": "deps/infozip/unzip60/windll/windllgcc.def",
    "content": "LIBRARY UNZIP32\n\n;DESCRIPTION 'Windows Info-ZIP UnZip32 DLL by Mike White'\n\n\nEXPORTS\n     Wiz_SingleEntryUnzip=Wiz_SingleEntryUnzip@24\n     Wiz_SingleEntryUnzpList=Wiz_SingleEntryUnzpList@24\n     UzpVersion=UzpVersion@0\n     Wiz_Init=Wiz_Init@8\n     Wiz_SetOpts=Wiz_SetOpts@8\n     Wiz_Unzip=Wiz_Unzip@20\n     Wiz_Validate=Wiz_Validate@8\n     Wiz_NoPrinting=Wiz_NoPrinting@4\n     UzpVersion2=UzpVersion2@4\n     Wiz_UnzipToMemory=Wiz_UnzipToMemory@16\n     Wiz_Grep=Wiz_Grep@24\n     UzpFreeMemBuffer=UzpFreeMemBuffer@4\n"
  },
  {
    "path": "deps/infozip/unzip60/zip.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* This is a dummy zip.h to allow the source files shared with Zip\n   (crypt.c, crc32.c, ttyio.c, win32/win32i64.c) to compile for UnZip.\n   (In case you are looking for the Info-ZIP license, please follow\n   the pointers above.)  */\n\n#ifndef __zip_h   /* don't include more than once */\n#define __zip_h\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n#define local static\n\n#define ZE_MEM         PK_MEM\n#define ziperr(c, h)   return\n\n#endif /* !__zip_h */\n"
  },
  {
    "path": "deps/infozip/unzip60/zipgrep.txt",
    "content": "ZIPGREP(1L)                                                        ZIPGREP(1L)\n\nNAME\n       zipgrep - search files in a ZIP archive for lines matching a pattern\n\nSYNOPSIS\n       zipgrep     [egrep_options]     pattern     file[.zip]    [file(s) ...]\n       [-x xfile(s) ...]\n\nDESCRIPTION\n       zipgrep will search files within a ZIP archive for lines  matching  the\n       given  string  or  pattern.   zipgrep  is  a  shell script and requires\n       egrep(1) and unzip(1L) to function.  Its output is identical to that of\n       egrep(1).\n\nARGUMENTS\n       pattern\n              The  pattern  to  be  located  within a ZIP archive.  Any\n              string or regular expression accepted by egrep(1) may  be\n              used.   file[.zip]  Path  of  the ZIP archive.  (Wildcard\n              expressions for the ZIP archive name are not  supported.)\n              If  the literal filename is not found, the suffix .zip is\n              appended.  Note that self-extracting ZIP files  are  sup-\n              ported,  as  with any other ZIP archive; just specify the\n              .exe suffix (if any) explicitly.\n\n       [file(s)]\n              An optional list of archive members to be processed, sep-\n              arated  by spaces.  If no member files are specified, all\n              members of the ZIP archive are searched.  Regular expres-\n              sions (wildcards) may be used to match multiple members:\n\n              *      matches a sequence of 0 or more characters\n\n              ?      matches exactly 1 character\n\n              [...]  matches  any  single  character  found  inside the\n                     brackets; ranges  are  specified  by  a  beginning\n                     character,  a hyphen, and an ending character.  If\n                     an exclamation point or a caret (`!' or `^')  fol-\n                     lows  the  left bracket, then the range of charac-\n                     ters within the brackets is complemented (that is,\n                     anything except the characters inside the brackets\n                     is considered a match).\n\n              (Be sure to quote any character that might  otherwise  be\n              interpreted or modified by the operating system.)\n\n       [-x xfile(s)]\n              An  optional  list of archive members to be excluded from\n              processing.  Since wildcard  characters  match  directory\n              separators  (`/'), this option may be used to exclude any\n              files that are in subdirectories.  For example, ``zipgrep\n              grumpy  foo  *.[ch]  -x */*'' would search for the string\n              ``grumpy'' in all C source files in the main directory of\n              the  ``foo''  archive,  but  none  in any subdirectories.\n              Without the -x option, all C source files in all directo-\n              ries within the zipfile would be searched.\n\nOPTIONS\n       All  options  prior  to  the  ZIP archive filename are passed to\n       egrep(1).\n\nSEE ALSO\n       egrep(1), unzip(1L),  zip(1L),  funzip(1L),  zipcloak(1L),  zip-\n       info(1L), zipnote(1L), zipsplit(1L)\n\nURL\n       The   Info-ZIP   home  page  is  currently  at  http://www.info-\n       zip.org/pub/infozip/ or ftp://ftp.info-zip.org/pub/infozip/ .\n\nAUTHORS\n       zipgrep was written by Jean-loup Gailly.\n\nInfo-ZIP                         20 April 2009                     ZIPGREP(1L)\n"
  },
  {
    "path": "deps/infozip/unzip60/zipinfo.c",
    "content": "/*\n  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2009-Jan-02 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  zipinfo.c                                              Greg Roelofs et al.\n\n  This file contains all of the ZipInfo-specific listing routines for UnZip.\n\n  Contains:  zi_opts()\n             zi_end_central()\n             zipinfo()\n             zi_long()\n             zi_short()\n             zi_time()\n\n  ---------------------------------------------------------------------------*/\n\n\n#define UNZIP_INTERNAL\n#include \"unzip.h\"\n\n\n#ifndef NO_ZIPINFO  /* strings use up too much space in small-memory systems */\n\n/* Define OS-specific attributes for use on ALL platforms--the S_xxxx\n * versions of these are defined differently (or not defined) by different\n * compilers and operating systems. */\n\n#define UNX_IFMT       0170000     /* Unix file type mask */\n#define UNX_IFREG      0100000     /* Unix regular file */\n#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */\n#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */\n#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */\n#define UNX_IFDIR      0040000     /* Unix directory */\n#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */\n#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */\n#define UNX_ISUID      04000       /* Unix set user id on execution */\n#define UNX_ISGID      02000       /* Unix set group id on execution */\n#define UNX_ISVTX      01000       /* Unix directory permissions control */\n#define UNX_ENFMT      UNX_ISGID   /* Unix record locking enforcement flag */\n#define UNX_IRWXU      00700       /* Unix read, write, execute: owner */\n#define UNX_IRUSR      00400       /* Unix read permission: owner */\n#define UNX_IWUSR      00200       /* Unix write permission: owner */\n#define UNX_IXUSR      00100       /* Unix execute permission: owner */\n#define UNX_IRWXG      00070       /* Unix read, write, execute: group */\n#define UNX_IRGRP      00040       /* Unix read permission: group */\n#define UNX_IWGRP      00020       /* Unix write permission: group */\n#define UNX_IXGRP      00010       /* Unix execute permission: group */\n#define UNX_IRWXO      00007       /* Unix read, write, execute: other */\n#define UNX_IROTH      00004       /* Unix read permission: other */\n#define UNX_IWOTH      00002       /* Unix write permission: other */\n#define UNX_IXOTH      00001       /* Unix execute permission: other */\n\n#define VMS_IRUSR      UNX_IRUSR   /* VMS read/owner */\n#define VMS_IWUSR      UNX_IWUSR   /* VMS write/owner */\n#define VMS_IXUSR      UNX_IXUSR   /* VMS execute/owner */\n#define VMS_IRGRP      UNX_IRGRP   /* VMS read/group */\n#define VMS_IWGRP      UNX_IWGRP   /* VMS write/group */\n#define VMS_IXGRP      UNX_IXGRP   /* VMS execute/group */\n#define VMS_IROTH      UNX_IROTH   /* VMS read/other */\n#define VMS_IWOTH      UNX_IWOTH   /* VMS write/other */\n#define VMS_IXOTH      UNX_IXOTH   /* VMS execute/other */\n\n#define AMI_IFMT       06000       /* Amiga file type mask */\n#define AMI_IFDIR      04000       /* Amiga directory */\n#define AMI_IFREG      02000       /* Amiga regular file */\n#define AMI_IHIDDEN    00200       /* to be supported in AmigaDOS 3.x */\n#define AMI_ISCRIPT    00100       /* executable script (text command file) */\n#define AMI_IPURE      00040       /* allow loading into resident memory */\n#define AMI_IARCHIVE   00020       /* not modified since bit was last set */\n#define AMI_IREAD      00010       /* can be opened for reading */\n#define AMI_IWRITE     00004       /* can be opened for writing */\n#define AMI_IEXECUTE   00002       /* executable image, a loadable runfile */\n#define AMI_IDELETE    00001       /* can be deleted */\n\n#define THS_IFMT    0xF000         /* Theos file type mask */\n#define THS_IFIFO   0x1000         /* pipe */\n#define THS_IFCHR   0x2000         /* char device */\n#define THS_IFSOCK  0x3000         /* socket */\n#define THS_IFDIR   0x4000         /* directory */\n#define THS_IFLIB   0x5000         /* library */\n#define THS_IFBLK   0x6000         /* block device */\n#define THS_IFREG   0x8000         /* regular file */\n#define THS_IFREL   0x9000         /* relative (direct) */\n#define THS_IFKEY   0xA000         /* keyed */\n#define THS_IFIND   0xB000         /* indexed */\n#define THS_IFRND   0xC000         /* ???? */\n#define THS_IFR16   0xD000         /* 16 bit real mode program */\n#define THS_IFP16   0xE000         /* 16 bit protected mode prog */\n#define THS_IFP32   0xF000         /* 32 bit protected mode prog */\n#define THS_IMODF   0x0800         /* modified */\n#define THS_INHID   0x0400         /* not hidden */\n#define THS_IEUSR   0x0200         /* erase permission: owner */\n#define THS_IRUSR   0x0100         /* read permission: owner */\n#define THS_IWUSR   0x0080         /* write permission: owner */\n#define THS_IXUSR   0x0040         /* execute permission: owner */\n#define THS_IROTH   0x0004         /* read permission: other */\n#define THS_IWOTH   0x0002         /* write permission: other */\n#define THS_IXOTH   0x0001         /* execute permission: other */\n\n#ifdef OLD_THEOS_EXTRA\n#  include \"theos/oldstat.h\"\n#endif\n\n#ifndef NSK_UNSTRUCTURED\n# define NSK_UNSTRUCTURED   0\n#endif\n#ifndef NSK_OBJECTFILECODE\n# define NSK_OBJECTFILECODE 100\n#endif\n#ifndef NSK_EDITFILECODE\n# define NSK_EDITFILECODE   101\n#endif\n\n#define LFLAG  3   /* short \"ls -l\" type listing */\n\nstatic int   zi_long   OF((__GPRO__ zusz_t *pEndprev, int error_in_archive));\nstatic int   zi_short  OF((__GPRO));\nstatic void  zi_showMacTypeCreator\n                       OF((__GPRO__ uch *ebfield));\nstatic char *zi_time   OF((__GPRO__ ZCONST ulg *datetimez,\n                           ZCONST time_t *modtimez, char *d_t_str));\n\n\n/**********************************************/\n/*  Strings used in zipinfo.c (ZipInfo half)  */\n/**********************************************/\n\nstatic ZCONST char nullStr[] = \"\";\nstatic ZCONST char PlurSufx[] = \"s\";\n\nstatic ZCONST char Far ZipInfHeader2[] =\n  \"Zip file size: %s bytes, number of entries: %s\\n\";\nstatic ZCONST char Far EndCentDirRec[] = \"\\nEnd-of-central-directory record:\\n\";\nstatic ZCONST char Far LineSeparators[] = \"-------------------------------\\n\\n\";\nstatic ZCONST char Far ZipFSizeVerbose[] = \"\\\n  Zip archive file size:               %s (%sh)\\n\";\nstatic ZCONST char Far ActOffsetCentDir[] = \"\\\n  Actual end-cent-dir record offset:   %s (%sh)\\n\\\n  Expected end-cent-dir record offset: %s (%sh)\\n\\\n  (based on the length of the central directory and its expected offset)\\n\\n\";\nstatic ZCONST char Far SinglePartArchive1[] = \"\\\n  This zipfile constitutes the sole disk of a single-part archive; its\\n\\\n  central directory contains %s %s.\\n\\\n  The central directory is %s (%sh) bytes long,\\n\";\nstatic ZCONST char Far SinglePartArchive2[] = \"\\\n  and its (expected) offset in bytes from the beginning of the zipfile\\n\\\n  is %s (%sh).\\n\\n\";\nstatic ZCONST char Far MultiPartArchive1[] = \"\\\n  This zipfile constitutes disk %lu of a multi-part archive.  The central\\n\\\n  directory starts on disk %lu at an offset within that archive part\\n\";\nstatic ZCONST char Far MultiPartArchive2[] = \"\\\n  of %s (%sh) bytes.  The entire\\n\\\n  central directory is %s (%sh) bytes long.\\n\";\nstatic ZCONST char Far MultiPartArchive3[] = \"\\\n  %s of the archive entries %s contained within this zipfile volume,\\n\\\n  out of a total of %s %s.\\n\\n\";\n\nstatic ZCONST char Far CentralDirEntry[] =\n  \"\\nCentral directory entry #%lu:\\n---------------------------\\n\\n\";\nstatic ZCONST char Far ZipfileStats[] =\n  \"%lu file%s, %s bytes uncompressed, %s bytes compressed:  %s%d.%d%%\\n\";\n\n/* zi_long() strings */\nstatic ZCONST char Far OS_FAT[] = \"MS-DOS, OS/2 or NT FAT\";\nstatic ZCONST char Far OS_Amiga[] = \"Amiga\";\nstatic ZCONST char Far OS_VMS[] = \"VMS\";\nstatic ZCONST char Far OS_Unix[] = \"Unix\";\nstatic ZCONST char Far OS_VMCMS[] = \"VM/CMS\";\nstatic ZCONST char Far OS_AtariST[] = \"Atari ST\";\nstatic ZCONST char Far OS_HPFS[] = \"OS/2 or NT HPFS\";\nstatic ZCONST char Far OS_Macintosh[] = \"Macintosh HFS\";\nstatic ZCONST char Far OS_ZSystem[] = \"Z-System\";\nstatic ZCONST char Far OS_CPM[] = \"CP/M\";\nstatic ZCONST char Far OS_TOPS20[] = \"TOPS-20\";\nstatic ZCONST char Far OS_NTFS[] = \"NTFS\";\nstatic ZCONST char Far OS_QDOS[] = \"SMS/QDOS\";\nstatic ZCONST char Far OS_Acorn[] = \"Acorn RISC OS\";\nstatic ZCONST char Far OS_MVS[] = \"MVS\";\nstatic ZCONST char Far OS_VFAT[] = \"Win32 VFAT\";\nstatic ZCONST char Far OS_AtheOS[] = \"AtheOS\";\nstatic ZCONST char Far OS_BeOS[] = \"BeOS\";\nstatic ZCONST char Far OS_Tandem[] = \"Tandem NSK\";\nstatic ZCONST char Far OS_Theos[] = \"Theos\";\nstatic ZCONST char Far OS_MacDarwin[] = \"Mac OS/X (Darwin)\";\n#ifdef OLD_THEOS_EXTRA\n  static ZCONST char Far OS_TheosOld[] = \"Theos (Old)\";\n#endif /* OLD_THEOS_EXTRA */\n\nstatic ZCONST char Far MthdNone[] = \"none (stored)\";\nstatic ZCONST char Far MthdShrunk[] = \"shrunk\";\nstatic ZCONST char Far MthdRedF1[] = \"reduced (factor 1)\";\nstatic ZCONST char Far MthdRedF2[] = \"reduced (factor 2)\";\nstatic ZCONST char Far MthdRedF3[] = \"reduced (factor 3)\";\nstatic ZCONST char Far MthdRedF4[] = \"reduced (factor 4)\";\nstatic ZCONST char Far MthdImplode[] = \"imploded\";\nstatic ZCONST char Far MthdToken[] = \"tokenized\";\nstatic ZCONST char Far MthdDeflate[] = \"deflated\";\nstatic ZCONST char Far MthdDeflat64[] = \"deflated (enhanced-64k)\";\nstatic ZCONST char Far MthdDCLImplode[] = \"imploded (PK DCL)\";\nstatic ZCONST char Far MthdBZip2[] = \"bzipped\";\nstatic ZCONST char Far MthdLZMA[] = \"LZMA-ed\";\nstatic ZCONST char Far MthdTerse[] = \"tersed (IBM)\";\nstatic ZCONST char Far MthdLZ77[] = \"LZ77-compressed (IBM)\";\nstatic ZCONST char Far MthdWavPack[] = \"WavPacked\";\nstatic ZCONST char Far MthdPPMd[] = \"PPMd-ed\";\n\nstatic ZCONST char Far DeflNorm[] = \"normal\";\nstatic ZCONST char Far DeflMax[] = \"maximum\";\nstatic ZCONST char Far DeflFast[] = \"fast\";\nstatic ZCONST char Far DeflSFast[] = \"superfast\";\n\nstatic ZCONST char Far ExtraBytesPreceding[] =\n  \"  There are an extra %s bytes preceding this file.\\n\\n\";\n\nstatic ZCONST char Far UnknownNo[] = \"unknown (%d)\";\n\n#ifdef ZIP64_SUPPORT\n  static ZCONST char Far LocalHeaderOffset[] =\n    \"\\n  offset of local header from start of archive:   %s\\n\\\n                                                  (%sh) bytes\\n\";\n#else\n  static ZCONST char Far LocalHeaderOffset[] =\n    \"\\n  offset of local header from start of archive:   %s (%sh) bytes\\n\";\n#endif\nstatic ZCONST char Far HostOS[] =\n  \"  file system or operating system of origin:      %s\\n\";\nstatic ZCONST char Far EncodeSWVer[] =\n  \"  version of encoding software:                   %u.%u\\n\";\nstatic ZCONST char Far MinOSCompReq[] =\n  \"  minimum file system compatibility required:     %s\\n\";\nstatic ZCONST char Far MinSWVerReq[] =\n  \"  minimum software version required to extract:   %u.%u\\n\";\nstatic ZCONST char Far CompressMethod[] =\n  \"  compression method:                             %s\\n\";\nstatic ZCONST char Far SlideWindowSizeImplode[] =\n  \"  size of sliding dictionary (implosion):         %cK\\n\";\nstatic ZCONST char Far ShannonFanoTrees[] =\n  \"  number of Shannon-Fano trees (implosion):       %c\\n\";\nstatic ZCONST char Far CompressSubtype[] =\n  \"  compression sub-type (deflation):               %s\\n\";\nstatic ZCONST char Far FileSecurity[] =\n  \"  file security status:                           %sencrypted\\n\";\nstatic ZCONST char Far ExtendedLocalHdr[] =\n  \"  extended local header:                          %s\\n\";\nstatic ZCONST char Far FileModDate[] =\n  \"  file last modified on (DOS date/time):          %s\\n\";\n#ifdef USE_EF_UT_TIME\n  static ZCONST char Far UT_FileModDate[] =\n    \"  file last modified on (UT extra field modtime): %s %s\\n\";\n  static ZCONST char Far LocalTime[] = \"local\";\n#ifndef NO_GMTIME\n  static ZCONST char Far GMTime[] = \"UTC\";\n#endif\n#endif /* USE_EF_UT_TIME */\nstatic ZCONST char Far CRC32Value[] =\n  \"  32-bit CRC value (hex):                         %.8lx\\n\";\nstatic ZCONST char Far CompressedFileSize[] =\n  \"  compressed size:                                %s bytes\\n\";\nstatic ZCONST char Far UncompressedFileSize[] =\n  \"  uncompressed size:                              %s bytes\\n\";\nstatic ZCONST char Far FilenameLength[] =\n  \"  length of filename:                             %u characters\\n\";\nstatic ZCONST char Far ExtraFieldLength[] =\n  \"  length of extra field:                          %u bytes\\n\";\nstatic ZCONST char Far FileCommentLength[] =\n  \"  length of file comment:                         %u characters\\n\";\nstatic ZCONST char Far FileDiskNum[] =\n  \"  disk number on which file begins:               disk %lu\\n\";\nstatic ZCONST char Far ApparentFileType[] =\n  \"  apparent file type:                             %s\\n\";\nstatic ZCONST char Far VMSFileAttributes[] =\n  \"  VMS file attributes (%06o octal):             %s\\n\";\nstatic ZCONST char Far AmigaFileAttributes[] =\n  \"  Amiga file attributes (%06o octal):           %s\\n\";\nstatic ZCONST char Far UnixFileAttributes[] =\n  \"  Unix file attributes (%06o octal):            %s\\n\";\nstatic ZCONST char Far NonMSDOSFileAttributes[] =\n  \"  non-MSDOS external file attributes:             %06lX hex\\n\";\nstatic ZCONST char Far MSDOSFileAttributes[] =\n  \"  MS-DOS file attributes (%02X hex):                none\\n\";\nstatic ZCONST char Far MSDOSFileAttributesRO[] =\n  \"  MS-DOS file attributes (%02X hex):                read-only\\n\";\nstatic ZCONST char Far MSDOSFileAttributesAlpha[] =\n  \"  MS-DOS file attributes (%02X hex):                %s%s%s%s%s%s%s%s\\n\";\nstatic ZCONST char Far TheosFileAttributes[] =\n  \"  Theos file attributes (%04X hex):               %s\\n\";\n\nstatic ZCONST char Far TheosFTypLib[] = \"Library     \";\nstatic ZCONST char Far TheosFTypDir[] = \"Directory   \";\nstatic ZCONST char Far TheosFTypReg[] = \"Sequential  \";\nstatic ZCONST char Far TheosFTypRel[] = \"Direct      \";\nstatic ZCONST char Far TheosFTypKey[] = \"Keyed       \";\nstatic ZCONST char Far TheosFTypInd[] = \"Indexed     \";\nstatic ZCONST char Far TheosFTypR16[] = \" 86 program \";\nstatic ZCONST char Far TheosFTypP16[] = \"286 program \";\nstatic ZCONST char Far TheosFTypP32[] = \"386 program \";\nstatic ZCONST char Far TheosFTypUkn[] = \"???         \";\n\nstatic ZCONST char Far ExtraFieldTrunc[] = \"\\n\\\n  error: EF data block (type 0x%04x) size %u exceeds remaining extra field\\n\\\n         space %u; block length has been truncated.\\n\";\nstatic ZCONST char Far ExtraFields[] = \"\\n\\\n  The central-directory extra field contains:\";\nstatic ZCONST char Far ExtraFieldType[] = \"\\n\\\n  - A subfield with ID 0x%04x (%s) and %u data bytes\";\nstatic ZCONST char Far efPKSZ64[] = \"PKWARE 64-bit sizes\";\nstatic ZCONST char Far efAV[] = \"PKWARE AV\";\nstatic ZCONST char Far efOS2[] = \"OS/2\";\nstatic ZCONST char Far efPKVMS[] = \"PKWARE VMS\";\nstatic ZCONST char Far efPKWin32[] = \"PKWARE Win32\";\nstatic ZCONST char Far efPKUnix[] = \"PKWARE Unix\";\nstatic ZCONST char Far efIZVMS[] = \"Info-ZIP VMS\";\nstatic ZCONST char Far efIZUnix[] = \"old Info-ZIP Unix/OS2/NT\";\nstatic ZCONST char Far efIZUnix2[] = \"Unix UID/GID (16-bit)\";\nstatic ZCONST char Far efIZUnix3[] = \"Unix UID/GID (any size)\";\nstatic ZCONST char Far efTime[] = \"universal time\";\nstatic ZCONST char Far efU8Path[] = \"UTF8 path name\";\nstatic ZCONST char Far efU8Commnt[] = \"UTF8 entry comment\";\nstatic ZCONST char Far efJLMac[] = \"old Info-ZIP Macintosh\";\nstatic ZCONST char Far efMac3[] = \"new Info-ZIP Macintosh\";\nstatic ZCONST char Far efZipIt[] = \"ZipIt Macintosh\";\nstatic ZCONST char Far efSmartZip[] = \"SmartZip Macintosh\";\nstatic ZCONST char Far efZipIt2[] = \"ZipIt Macintosh (short)\";\nstatic ZCONST char Far efVMCMS[] = \"VM/CMS\";\nstatic ZCONST char Far efMVS[] = \"MVS\";\nstatic ZCONST char Far efACL[] = \"OS/2 ACL\";\nstatic ZCONST char Far efNTSD[] = \"Security Descriptor\";\nstatic ZCONST char Far efAtheOS[] = \"AtheOS\";\nstatic ZCONST char Far efBeOS[] = \"BeOS\";\nstatic ZCONST char Far efQDOS[] = \"SMS/QDOS\";\nstatic ZCONST char Far efAOSVS[] = \"AOS/VS\";\nstatic ZCONST char Far efSpark[] = \"Acorn SparkFS\";\nstatic ZCONST char Far efMD5[] = \"Fred Kantor MD5\";\nstatic ZCONST char Far efASiUnix[] = \"ASi Unix\";\nstatic ZCONST char Far efTandem[] = \"Tandem NSK\";\nstatic ZCONST char Far efTheos[] = \"Theos\";\nstatic ZCONST char Far efUnknown[] = \"unknown\";\n\nstatic ZCONST char Far OS2EAs[] = \".\\n\\\n    The local extra field has %lu bytes of OS/2 extended attributes.\\n\\\n    (May not match OS/2 \\\"dir\\\" amount due to storage method)\";\nstatic ZCONST char Far izVMSdata[] = \".  The extra\\n\\\n    field is %s and has %u bytes of VMS %s information%s\";\nstatic ZCONST char Far izVMSstored[] = \"stored\";\nstatic ZCONST char Far izVMSrleenc[] = \"run-length encoded\";\nstatic ZCONST char Far izVMSdeflat[] = \"deflated\";\nstatic ZCONST char Far izVMScunknw[] = \"compressed(?)\";\nstatic ZCONST char Far *izVMScomp[4] =\n  {izVMSstored, izVMSrleenc, izVMSdeflat, izVMScunknw};\nstatic ZCONST char Far ACLdata[] = \".\\n\\\n    The local extra field has %lu bytes of access control list information\";\nstatic ZCONST char Far NTSDData[] = \".\\n\\\n    The local extra field has %lu bytes of NT security descriptor data\";\nstatic ZCONST char Far UTdata[] = \".\\n\\\n    The local extra field has UTC/GMT %s time%s\";\nstatic ZCONST char Far UTmodification[] = \"modification\";\nstatic ZCONST char Far UTaccess[] = \"access\";\nstatic ZCONST char Far UTcreation[] = \"creation\";\nstatic ZCONST char Far U8PthCmnComplete[] = \".\\n\\\n    The UTF8 data of the extra field (V%u, ASCII name CRC `%.8lx') are:\\n   \";\nstatic ZCONST char Far U8PthCmnF24[] = \". The first\\n\\\n    24 UTF8 bytes in the extra field (V%u, ASCII name CRC `%.8lx') are:\\n   \";\nstatic ZCONST char Far ZipItFname[] = \".\\n\\\n    The Mac long filename is %s\";\nstatic ZCONST char Far Mac3data[] = \".\\n\\\n    The local extra field has %lu bytes of %scompressed Macintosh\\n\\\n    finder attributes\";\n /* MacOSdata[] is used by EF_MAC3, EF_ZIPIT, EF_ZIPIT2 and EF_JLEE e. f. */\nstatic ZCONST char Far MacOSdata[] = \".\\n\\\n    The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'\";\nstatic ZCONST char Far MacOSdata1[] = \".\\n\\\n    The associated file has type code `0x%lx' and creator code `0x%lx'\";\nstatic ZCONST char Far MacOSJLEEflags[] = \".\\n    File is marked as %s\";\nstatic ZCONST char Far MacOS_RF[] = \"Resource-fork\";\nstatic ZCONST char Far MacOS_DF[] = \"Data-fork\";\nstatic ZCONST char Far MacOSMAC3flags[] = \".\\n\\\n    File is marked as %s, File Dates are in %d Bit\";\nstatic ZCONST char Far AtheOSdata[] = \".\\n\\\n    The local extra field has %lu bytes of %scompressed AtheOS file attributes\";\nstatic ZCONST char Far BeOSdata[] = \".\\n\\\n    The local extra field has %lu bytes of %scompressed BeOS file attributes\";\n /* The associated file has type code `%c%c%c%c' and creator code `%c%c%c%c'\" */\nstatic ZCONST char Far QDOSdata[] = \".\\n\\\n    The QDOS extra field subtype is `%c%c%c%c'\";\nstatic ZCONST char Far AOSVSdata[] = \".\\n\\\n    The AOS/VS extra field revision is %d.%d\";\nstatic ZCONST char Far TandemUnstr[] = \"Unstructured\";\nstatic ZCONST char Far TandemRel[]   = \"Relative\";\nstatic ZCONST char Far TandemEntry[] = \"Entry Sequenced\";\nstatic ZCONST char Far TandemKey[]   = \"Key Sequenced\";\nstatic ZCONST char Far TandemEdit[]  = \"Edit\";\nstatic ZCONST char Far TandemObj[]  = \"Object\";\nstatic ZCONST char Far *TandemFileformat[6] =\n  {TandemUnstr, TandemRel, TandemEntry, TandemKey, TandemEdit, TandemObj};\nstatic ZCONST char Far Tandemdata[] = \".\\n\\\n    The file was originally a Tandem %s file, with file code %u\";\nstatic ZCONST char Far MD5data[] = \".\\n\\\n    The 128-bit MD5 signature is %s\";\n#ifdef CMS_MVS\n   static ZCONST char Far VmMvsExtraField[] = \".\\n\\\n    The stored file open mode (FLDATA TYPE) is \\\"%s\\\"\";\n   static ZCONST char Far VmMvsInvalid[] = \"[invalid]\";\n#endif /* CMS_MVS */\n\nstatic ZCONST char Far First20[] = \".  The first\\n    20 are:  \";\nstatic ZCONST char Far ColonIndent[] = \":\\n   \";\nstatic ZCONST char Far efFormat[] = \" %02x\";\n\nstatic ZCONST char Far lExtraFieldType[] = \"\\n\\\n  There %s a local extra field with ID 0x%04x (%s) and\\n\\\n  %u data bytes (%s).\\n\";\nstatic ZCONST char Far efIZuid[] =\n  \"GMT modification/access times and Unix UID/GID\";\nstatic ZCONST char Far efIZnouid[] = \"GMT modification/access times only\";\n\n\nstatic ZCONST char Far NoFileComment[] = \"\\n  There is no file comment.\\n\";\nstatic ZCONST char Far FileCommBegin[] = \"\\n\\\n------------------------- file comment begins ----------------------------\\n\";\nstatic ZCONST char Far FileCommEnd[] = \"\\\n-------------------------- file comment ends -----------------------------\\n\";\n\n/* zi_time() strings */\nstatic ZCONST char Far BogusFmt[] = \"%03d\";\nstatic ZCONST char Far shtYMDHMTime[] = \"%02u-%s-%02u %02u:%02u\";\nstatic ZCONST char Far lngYMDHMSTime[] = \"%u %s %u %02u:%02u:%02u\";\nstatic ZCONST char Far DecimalTime[] = \"%04u%02u%02u.%02u%02u%02u\";\n#ifdef USE_EF_UT_TIME\n  static ZCONST char Far lngYMDHMSTimeError[] = \"???? ??? ?? ??:??:??\";\n#endif\n\n\n\n\n\n#ifndef WINDLL\n\n/************************/\n/*  Function zi_opts()  */\n/************************/\n\nint zi_opts(__G__ pargc, pargv)\n    int *pargc;\n    char ***pargv;\n    __GDEF\n{\n    char   **argv, *s;\n    int    argc, c, error=FALSE, negative=0;\n    int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */\n    int    tflag_slm=TRUE, tflag_2v=FALSE;\n    int    explicit_h=FALSE, explicit_t=FALSE;\n\n\n#ifdef MACOS\n    uO.lflag = LFLAG;         /* reset default on each call */\n#endif\n    G.extract_flag = FALSE;   /* zipinfo does not extract to disk */\n    argc = *pargc;\n    argv = *pargv;\n\n    while (--argc > 0 && (*++argv)[0] == '-') {\n        s = argv[0] + 1;\n        while ((c = *s++) != 0) {    /* \"!= 0\":  prevent Turbo C warning */\n            switch (c) {\n                case '-':\n                    ++negative;\n                    break;\n                case '1':      /* shortest listing:  JUST filenames */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 1;\n                    break;\n                case '2':      /* just filenames, plus headers if specified */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 2;\n                    break;\n#ifndef CMS_MVS\n                case ('C'):    /* -C:  match filenames case-insensitively */\n                    if (negative)\n                        uO.C_flag = FALSE, negative = 0;\n                    else\n                        uO.C_flag = TRUE;\n                    break;\n#endif /* !CMS_MVS */\n                case 'h':      /* header line */\n                    if (negative)\n                        hflag_2 = hflag_slmv = FALSE, negative = 0;\n                    else {\n                        hflag_2 = hflag_slmv = explicit_h = TRUE;\n                        if (uO.lflag == -1)\n                            uO.lflag = 0;\n                    }\n                    break;\n                case 'l':      /* longer form of \"ls -l\" type listing */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 5;\n                    break;\n                case 'm':      /* medium form of \"ls -l\" type listing */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 4;\n                    break;\n#ifdef MORE\n                case 'M':      /* send output through built-in \"more\" */\n                    if (negative)\n                        G.M_flag = FALSE, negative = 0;\n                    else\n                        G.M_flag = TRUE;\n                    break;\n#endif\n                case 's':      /* default:  shorter \"ls -l\" type listing */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 3;\n                    break;\n                case 't':      /* totals line */\n                    if (negative)\n                        tflag_2v = tflag_slm = FALSE, negative = 0;\n                    else {\n                        tflag_2v = tflag_slm = explicit_t = TRUE;\n                        if (uO.lflag == -1)\n                            uO.lflag = 0;\n                    }\n                    break;\n                case ('T'):    /* use (sortable) decimal time format */\n                    if (negative)\n                        uO.T_flag = FALSE, negative = 0;\n                    else\n                        uO.T_flag = TRUE;\n                    break;\n#ifdef UNICODE_SUPPORT\n                case ('U'):    /* escape UTF-8, or disable UTF-8 support */\n                    if (negative) {\n                        uO.U_flag = MAX(uO.U_flag-negative,0);\n                        negative = 0;\n                    } else\n                        uO.U_flag++;\n                    break;\n#endif /* UNICODE_SUPPORT */\n                case 'v':      /* turbo-verbose listing */\n                    if (negative)\n                        uO.lflag = -2, negative = 0;\n                    else\n                        uO.lflag = 10;\n                    break;\n#ifdef WILD_STOP_AT_DIR\n                case ('W'):    /* Wildcard interpretation (stop at '/'?) */\n                    if (negative)\n                        uO.W_flag = FALSE, negative = 0;\n                    else\n                        uO.W_flag = TRUE;\n                    break;\n#endif /* WILD_STOP_AT_DIR */\n                case 'z':      /* print zipfile comment */\n                    if (negative)\n                        uO.zflag = negative = 0;\n                    else\n                        uO.zflag = 1;\n                    break;\n                case 'Z':      /* ZipInfo mode:  ignore */\n                    break;\n                default:\n                    error = TRUE;\n                    break;\n            }\n        }\n    }\n    if ((argc-- == 0) || error) {\n        *pargc = argc;\n        *pargv = argv;\n        return USAGE(error);\n    }\n\n#ifdef MORE\n    if (G.M_flag && !isatty(1))  /* stdout redirected: \"more\" func useless */\n        G.M_flag = 0;\n#endif\n\n    /* if no listing options given (or all negated), or if only -h/-t given\n     * with individual files specified, use default listing format */\n    if ((uO.lflag < 0) || ((argc > 0) && (uO.lflag == 0)))\n        uO.lflag = LFLAG;\n\n    /* set header and totals flags to default or specified values */\n    switch (uO.lflag) {\n        case 0:   /* 0:  can only occur if either -t or -h explicitly given; */\n        case 2:   /*  therefore set both flags equal to normally false value */\n            uO.hflag = hflag_2;\n            uO.tflag = tflag_2v;\n            break;\n        case 1:   /* only filenames, *always* */\n            uO.hflag = FALSE;\n            uO.tflag = FALSE;\n            uO.zflag = FALSE;\n            break;\n        case 3:\n        case 4:\n        case 5:\n            uO.hflag = ((argc > 0) && !explicit_h)? FALSE : hflag_slmv;\n            uO.tflag = ((argc > 0) && !explicit_t)? FALSE : tflag_slm;\n            break;\n        case 10:\n            uO.hflag = hflag_slmv;\n            uO.tflag = tflag_2v;\n            break;\n    }\n\n    *pargc = argc;\n    *pargv = argv;\n    return 0;\n\n} /* end function zi_opts() */\n\n#endif /* !WINDLL */\n\n\n\n\n\n/*******************************/\n/*  Function zi_end_central()  */\n/*******************************/\n\nvoid zi_end_central(__G)\n    __GDEF\n{\n/*---------------------------------------------------------------------------\n    Print out various interesting things about the zipfile.\n  ---------------------------------------------------------------------------*/\n\n    if (uO.lflag > 9) {\n        /* verbose format */\n        Info(slide, 0, ((char *)slide, LoadFarString(EndCentDirRec)));\n        Info(slide, 0, ((char *)slide, LoadFarString(LineSeparators)));\n\n        Info(slide, 0, ((char *)slide, LoadFarString(ZipFSizeVerbose),\n          FmZofft(G.ziplen, \"11\", NULL),\n          FmZofft(G.ziplen, FZOFFT_HEX_DOT_WID, \"X\")));\n        Info(slide, 0, ((char *)slide, LoadFarString(ActOffsetCentDir),\n          FmZofft(G.real_ecrec_offset, \"11\", \"u\"),\n          FmZofft(G.real_ecrec_offset, FZOFFT_HEX_DOT_WID, \"X\"),\n          FmZofft(G.expect_ecrec_offset, \"11\", \"u\"),\n          FmZofft(G.expect_ecrec_offset, FZOFFT_HEX_DOT_WID, \"X\")));\n\n        if (G.ecrec.number_this_disk == 0) {\n            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive1),\n              FmZofft(G.ecrec.total_entries_central_dir, NULL, \"u\"),\n              (G.ecrec.total_entries_central_dir == 1)? \"entry\" : \"entries\",\n              FmZofft(G.ecrec.size_central_directory, NULL, \"u\"),\n              FmZofft(G.ecrec.size_central_directory,\n                      FZOFFT_HEX_DOT_WID, \"X\")));\n            Info(slide, 0, ((char *)slide, LoadFarString(SinglePartArchive2),\n              FmZofft(G.ecrec.offset_start_central_directory, NULL, \"u\"),\n              FmZofft(G.ecrec.offset_start_central_directory,\n                      FZOFFT_HEX_DOT_WID, \"X\")));\n        } else {\n            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive1),\n              (ulg)(G.ecrec.number_this_disk + 1),\n              (ulg)(G.ecrec.num_disk_start_cdir + 1)));\n            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive2),\n              FmZofft(G.ecrec.offset_start_central_directory, NULL, \"u\"),\n              FmZofft(G.ecrec.offset_start_central_directory,\n                      FZOFFT_HEX_DOT_WID, \"X\"),\n              FmZofft(G.ecrec.size_central_directory, NULL, \"u\"),\n              FmZofft(G.ecrec.size_central_directory,\n                      FZOFFT_HEX_DOT_WID, \"X\")));\n            Info(slide, 0, ((char *)slide, LoadFarString(MultiPartArchive3),\n              FmZofft(G.ecrec.num_entries_centrl_dir_ths_disk, NULL, \"u\"),\n              (G.ecrec.num_entries_centrl_dir_ths_disk == 1)? \"is\" : \"are\",\n              FmZofft(G.ecrec.total_entries_central_dir, NULL, \"u\"),\n              (G.ecrec.total_entries_central_dir == 1) ? \"entry\" : \"entries\"));\n        }\n    }\n    else if (uO.hflag) {\n        /* print zip file size and number of contained entries: */\n        Info(slide, 0, ((char *)slide, LoadFarString(ZipInfHeader2),\n          FmZofft(G.ziplen, NULL, NULL),\n          FmZofft(G.ecrec.total_entries_central_dir, NULL, \"u\")));\n    }\n\n} /* end function zi_end_central() */\n\n\n\n\n\n/************************/\n/*  Function zipinfo()  */\n/************************/\n\nint zipinfo(__G)   /* return PK-type error code */\n    __GDEF\n{\n    int do_this_file=FALSE, error, error_in_archive=PK_COOL;\n    int *fn_matched=NULL, *xn_matched=NULL;\n    ulg j, members=0L;\n    zusz_t tot_csize=0L, tot_ucsize=0L;\n    zusz_t endprev;   /* buffers end of previous entry for zi_long()'s check\n                       *  of extra bytes */\n\n\n/*---------------------------------------------------------------------------\n    Malloc space for check on unmatched filespecs (no big deal if one or both\n    are NULL).\n  ---------------------------------------------------------------------------*/\n\n    if (G.filespecs > 0  &&\n        (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != NULL)\n        for (j = 0;  j < G.filespecs;  ++j)\n            fn_matched[j] = FALSE;\n\n    if (G.xfilespecs > 0  &&\n        (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != NULL)\n        for (j = 0;  j < G.xfilespecs;  ++j)\n            xn_matched[j] = FALSE;\n\n/*---------------------------------------------------------------------------\n    Set file pointer to start of central directory, then loop through cen-\n    tral directory entries.  Check that directory-entry signature bytes are\n    actually there (just a precaution), then process the entry.  We know\n    the entire central directory is on this disk:  we wouldn't have any of\n    this information unless the end-of-central-directory record was on this\n    disk, and we wouldn't have gotten to this routine unless this is also\n    the disk on which the central directory starts.  In practice, this had\n    better be the *only* disk in the archive, but maybe someday we'll add\n    multi-disk support.\n  ---------------------------------------------------------------------------*/\n\n    uO.L_flag = FALSE;      /* zipinfo mode: never convert name to lowercase */\n    G.pInfo = G.info;       /* (re-)initialize, (just to make sure) */\n    G.pInfo->textmode = 0;  /* so one can read on screen (is this ever used?) */\n\n    /* reset endprev for new zipfile; account for multi-part archives (?) */\n    endprev = (G.crec.relative_offset_local_header == 4L)? 4L : 0L;\n\n\n    for (j = 1L;; j++) {\n        if (readbuf(__G__ G.sig, 4) == 0) {\n            error_in_archive = PK_EOF;\n            break;\n        }\n        if (memcmp(G.sig, central_hdr_sig, 4)) {  /* is it a CentDir entry? */\n            /* no new central directory entry\n             * -> is the number of processed entries compatible with the\n             *    number of entries as stored in the end_central record?\n             */\n            if (((j - 1) &\n                 (ulg)(G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16))\n                == (ulg)G.ecrec.total_entries_central_dir)\n            {\n                /* \"j modulus 4T/64k\" matches the reported 64/16-bit-unsigned\n                 * number of directory entries -> probably, the regular\n                 * end of the central directory has been reached\n                 */\n                break;\n            } else {\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(CentSigMsg), j));\n                Info(slide, 0x401,\n                     ((char *)slide, LoadFarString(ReportMsg)));\n                error_in_archive = PK_BADERR;   /* sig not found */\n                break;\n            }\n        }\n        /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag, ...: */\n        if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {\n            error_in_archive = error;   /* only PK_EOF defined */\n            break;\n        }\n\n        if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=\n             PK_COOL)\n        {\n          if (error > error_in_archive)\n              error_in_archive = error;\n          if (error > PK_WARN)        /* fatal */\n              break;\n        }\n\n        if (!G.process_all_files) {   /* check if specified on command line */\n            unsigned i;\n\n            if (G.filespecs == 0)\n                do_this_file = TRUE;\n            else {  /* check if this entry matches an `include' argument */\n                do_this_file = FALSE;\n                for (i = 0; i < G.filespecs; i++)\n                    if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) {\n                        do_this_file = TRUE;\n                        if (fn_matched)\n                            fn_matched[i] = TRUE;\n                        break;       /* found match, so stop looping */\n                    }\n            }\n            if (do_this_file) {  /* check if this is an excluded file */\n                for (i = 0; i < G.xfilespecs; i++)\n                    if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) {\n                        do_this_file = FALSE;  /* ^-- ignore case in match */\n                        if (xn_matched)\n                            xn_matched[i] = TRUE;\n                        break;\n                    }\n            }\n        }\n\n    /*-----------------------------------------------------------------------\n        If current file was specified on command line, or if no names were\n        specified, do the listing for this file.  Otherwise, get rid of the\n        file comment and go back for the next file.\n      -----------------------------------------------------------------------*/\n\n        if (G.process_all_files || do_this_file) {\n\n            /* Read the extra field, if any.  The extra field info is required\n             * for resolving the Zip64 sizes/offsets and may be used in more\n             * analysis of the entry below.\n             */\n            if ((error = do_string(__G__ G.crec.extra_field_length,\n                                   EXTRA_FIELD)) != 0)\n            {\n                if (G.extra_field != NULL) {\n                    free(G.extra_field);\n                    G.extra_field = NULL;\n                }\n                error_in_archive = error;\n                /* The premature return in case of a \"fatal\" error (PK_EOF) is\n                 * delayed until we analyze the extra field contents.\n                 * This allows us to display all the other info that has been\n                 * successfully read in.\n                 */\n            }\n\n            switch (uO.lflag) {\n                case 1:\n                case 2:\n                    fnprint(__G);\n                    SKIP_(G.crec.file_comment_length)\n                    break;\n\n                case 3:\n                case 4:\n                case 5:\n                    if ((error = zi_short(__G)) != PK_COOL) {\n                        error_in_archive = error;   /* might be warning */\n                    }\n                    break;\n\n                case 10:\n                    Info(slide, 0, ((char *)slide,\n                      LoadFarString(CentralDirEntry), j));\n                    if ((error = zi_long(__G__ &endprev,\n                                         error_in_archive)) != PK_COOL) {\n                        error_in_archive = error;   /* might be warning */\n                    }\n                    break;\n\n                default:\n                    SKIP_(G.crec.file_comment_length)\n                    break;\n\n            } /* end switch (lflag) */\n            if (error > PK_WARN)        /* fatal */\n                break;\n\n            tot_csize += G.crec.csize;\n            tot_ucsize += G.crec.ucsize;\n            if (G.crec.general_purpose_bit_flag & 1)\n                tot_csize -= 12;   /* don't count encryption header */\n            ++members;\n\n#ifdef DLL\n            if ((G.statreportcb != NULL) &&\n                (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,\n                                  G.filename, (zvoid *)&G.crec.ucsize)) {\n                /* cancel operation by user request */\n                error_in_archive = IZ_CTRLC;\n                break;\n            }\n#endif\n#ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */\n            UserStop();\n#endif\n\n        } else {        /* not listing this file */\n            SKIP_(G.crec.extra_field_length)\n            SKIP_(G.crec.file_comment_length)\n            if (endprev != 0) endprev = 0;\n\n        } /* end if (list member?) */\n\n    } /* end for-loop (j: member files) */\n\n/*---------------------------------------------------------------------------\n    Check that we actually found requested files; if so, print totals.\n  ---------------------------------------------------------------------------*/\n\n    if ((error_in_archive <= PK_WARN) && uO.tflag) {\n        char *sgn = \"\";\n        int cfactor = ratio(tot_ucsize, tot_csize);\n\n        if (cfactor < 0) {\n            sgn = \"-\";\n            cfactor = -cfactor;\n        }\n        Info(slide, 0, ((char *)slide, LoadFarString(ZipfileStats),\n          members, (members==1L)? nullStr:PlurSufx,\n          FmZofft(tot_ucsize, NULL, \"u\"),\n          FmZofft(tot_csize, NULL, \"u\"),\n          sgn, cfactor/10, cfactor%10));\n    }\n\n/*---------------------------------------------------------------------------\n    Check for unmatched filespecs on command line and print warning if any\n    found.\n  ---------------------------------------------------------------------------*/\n\n    if (fn_matched) {\n        if (error_in_archive <= PK_WARN)\n            for (j = 0;  j < G.filespecs;  ++j)\n                if (!fn_matched[j])\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(FilenameNotMatched), G.pfnames[j]));\n        free((zvoid *)fn_matched);\n    }\n    if (xn_matched) {\n        if (error_in_archive <= PK_WARN)\n            for (j = 0;  j < G.xfilespecs;  ++j)\n                if (!xn_matched[j])\n                    Info(slide, 0x401, ((char *)slide,\n                      LoadFarString(ExclFilenameNotMatched), G.pxnames[j]));\n        free((zvoid *)xn_matched);\n    }\n\n\n    /* Skip the following checks in case of a premature listing break. */\n    if (error_in_archive <= PK_WARN) {\n\n/*---------------------------------------------------------------------------\n    Double check that we're back at the end-of-central-directory record.\n  ---------------------------------------------------------------------------*/\n\n        if ( (memcmp(G.sig,\n                     (G.ecrec.have_ecr64 ?\n                      end_central64_sig : end_central_sig),\n                     4) != 0)\n            && (!G.ecrec.is_zip64_archive)\n            && (memcmp(G.sig, end_central_sig, 4) != 0)\n           ) {          /* just to make sure again */\n            Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));\n            error_in_archive = PK_WARN;   /* didn't find sig */\n        }\n\n        /* Set specific return code when no files have been found. */\n        if (members == 0L && error_in_archive <= PK_WARN)\n            error_in_archive = PK_FIND;\n\n        if (uO.lflag >= 10)\n            (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n    }\n\n    return error_in_archive;\n\n} /* end function zipinfo() */\n\n\n\n\n\n/************************/\n/*  Function zi_long()  */\n/************************/\n\nstatic int zi_long(__G__ pEndprev, error_in_archive)\n    /* return PK-type error code */\n    __GDEF\n    zusz_t *pEndprev;                /* for zi_long() check of extra bytes */\n    int error_in_archive;            /* may signal premature return */\n{\n#ifdef USE_EF_UT_TIME\n    iztimes z_utime;\n#endif\n    int  error;\n    unsigned  hostnum, hostver, extnum, extver, methid, methnum, xattr;\n    char workspace[12], attribs[22];\n    ZCONST char *varmsg_str;\n    char unkn[16];\n    static ZCONST char Far *os[NUM_HOSTS] = {\n        OS_FAT, OS_Amiga, OS_VMS, OS_Unix, OS_VMCMS, OS_AtariST, OS_HPFS,\n        OS_Macintosh, OS_ZSystem, OS_CPM, OS_TOPS20, OS_NTFS, OS_QDOS,\n        OS_Acorn, OS_VFAT, OS_MVS, OS_BeOS, OS_Tandem, OS_Theos, OS_MacDarwin,\n        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\n        OS_AtheOS\n    };\n    static ZCONST char Far *method[NUM_METHODS] = {\n        MthdNone, MthdShrunk, MthdRedF1, MthdRedF2, MthdRedF3, MthdRedF4,\n        MthdImplode, MthdToken, MthdDeflate, MthdDeflat64, MthdDCLImplode,\n        MthdBZip2, MthdLZMA, MthdTerse, MthdLZ77, MthdWavPack, MthdPPMd\n    };\n    static ZCONST char Far *dtypelng[4] = {\n        DeflNorm, DeflMax, DeflFast, DeflSFast\n    };\n\n\n/*---------------------------------------------------------------------------\n    Check whether there's any extra space inside the zipfile.  If *pEndprev is\n    zero, it's probably a signal that OS/2 extra fields are involved (with\n    unknown compressed size).  We won't worry about prepended junk here...\n  ---------------------------------------------------------------------------*/\n\n    if (G.crec.relative_offset_local_header != *pEndprev && *pEndprev > 0L) {\n        /*  GRR DEBUG\n        Info(slide, 0, ((char *)slide,\n          \"  [crec.relative_offset_local_header = %lu, endprev = %lu]\\n\",\n          G.crec.relative_offset_local_header, *pEndprev));\n         */\n        Info(slide, 0, ((char *)slide, LoadFarString(ExtraBytesPreceding),\n          FmZofft((G.crec.relative_offset_local_header - (*pEndprev)),\n          NULL, NULL)));\n    }\n\n    /* calculate endprev for next time around (problem:  extra fields may\n     * differ in length between local and central-directory records) */\n    *pEndprev = G.crec.relative_offset_local_header + (4L + LREC_SIZE) +\n      G.crec.filename_length + G.crec.extra_field_length + G.crec.csize;\n\n/*---------------------------------------------------------------------------\n    Print out various interesting things about the compressed file.\n  ---------------------------------------------------------------------------*/\n\n    hostnum = (unsigned)(G.pInfo->hostnum);\n    hostver = (unsigned)(G.pInfo->hostver);\n    extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);\n    extver = (unsigned)G.crec.version_needed_to_extract[0];\n    methid = (unsigned)G.crec.compression_method;\n    methnum = find_compr_idx(G.crec.compression_method);\n\n    (*G.message)((zvoid *)&G, (uch *)\"  \", 2L, 0);  fnprint(__G);\n\n    Info(slide, 0, ((char *)slide, LoadFarString(LocalHeaderOffset),\n      FmZofft(G.crec.relative_offset_local_header, NULL, \"u\"),\n      FmZofft(G.crec.relative_offset_local_header, FZOFFT_HEX_DOT_WID, \"X\")));\n\n    if (hostnum >= NUM_HOSTS) {\n        sprintf(unkn, LoadFarString(UnknownNo),\n                (int)G.crec.version_made_by[1]);\n        varmsg_str = unkn;\n    } else {\n        varmsg_str = LoadFarStringSmall(os[hostnum]);\n#ifdef OLD_THEOS_EXTRA\n        if (hostnum == FS_VFAT_ && hostver == 20) {\n            /* entry made by old non-official THEOS port zip archive */\n            varmsg_str = LoadFarStringSmall(OS_TheosOld);\n        }\n#endif /* OLD_THEOS_EXTRA */\n    }\n    Info(slide, 0, ((char *)slide, LoadFarString(HostOS), varmsg_str));\n    Info(slide, 0, ((char *)slide, LoadFarString(EncodeSWVer), hostver/10,\n      hostver%10));\n\n    if ((extnum >= NUM_HOSTS) || (os[extnum] == NULL)) {\n        sprintf(unkn, LoadFarString(UnknownNo),\n                (int)G.crec.version_needed_to_extract[1]);\n        varmsg_str = unkn;\n    } else {\n        varmsg_str = LoadFarStringSmall(os[extnum]);\n    }\n    Info(slide, 0, ((char *)slide, LoadFarString(MinOSCompReq), varmsg_str));\n    Info(slide, 0, ((char *)slide, LoadFarString(MinSWVerReq), extver/10,\n      extver%10));\n\n    if (methnum >= NUM_METHODS) {\n        sprintf(unkn, LoadFarString(UnknownNo), G.crec.compression_method);\n        varmsg_str = unkn;\n    } else {\n        varmsg_str = LoadFarStringSmall(method[methnum]);\n    }\n    Info(slide, 0, ((char *)slide, LoadFarString(CompressMethod), varmsg_str));\n    if (methid == IMPLODED) {\n        Info(slide, 0, ((char *)slide, LoadFarString(SlideWindowSizeImplode),\n          (G.crec.general_purpose_bit_flag & 2)? '8' : '4'));\n        Info(slide, 0, ((char *)slide, LoadFarString(ShannonFanoTrees),\n          (G.crec.general_purpose_bit_flag & 4)? '3' : '2'));\n    } else if (methid == DEFLATED || methid == ENHDEFLATED) {\n        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);\n\n        Info(slide, 0, ((char *)slide, LoadFarString(CompressSubtype),\n          LoadFarStringSmall(dtypelng[dnum])));\n    }\n\n    Info(slide, 0, ((char *)slide, LoadFarString(FileSecurity),\n      (G.crec.general_purpose_bit_flag & 1) ? nullStr : \"not \"));\n    Info(slide, 0, ((char *)slide, LoadFarString(ExtendedLocalHdr),\n      (G.crec.general_purpose_bit_flag & 8) ? \"yes\" : \"no\"));\n    /* print upper 3 bits for amusement? */\n\n    /* For printing of date & time, a \"char d_t_buf[21]\" is required.\n     * To save stack space, we reuse the \"char attribs[22]\" buffer which\n     * is not used yet.\n     */\n#   define d_t_buf attribs\n\n    zi_time(__G__ &G.crec.last_mod_dos_datetime, NULL, d_t_buf);\n    Info(slide, 0, ((char *)slide, LoadFarString(FileModDate), d_t_buf));\n#ifdef USE_EF_UT_TIME\n    if (G.extra_field &&\n#ifdef IZ_CHECK_TZ\n        G.tz_is_valid &&\n#endif\n        (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,\n                          G.crec.last_mod_dos_datetime, &z_utime, NULL)\n         & EB_UT_FL_MTIME))\n    {\n        TIMET_TO_NATIVE(z_utime.mtime)   /* NOP unless MSC 7.0 or Macintosh */\n        d_t_buf[0] = (char)0;               /* signal \"show local time\" */\n        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);\n        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),\n          d_t_buf, LoadFarStringSmall(LocalTime)));\n#ifndef NO_GMTIME\n        d_t_buf[0] = (char)1;           /* signal \"show UTC (GMT) time\" */\n        zi_time(__G__ &G.crec.last_mod_dos_datetime, &(z_utime.mtime), d_t_buf);\n        Info(slide, 0, ((char *)slide, LoadFarString(UT_FileModDate),\n          d_t_buf, LoadFarStringSmall(GMTime)));\n#endif /* !NO_GMTIME */\n    }\n#endif /* USE_EF_UT_TIME */\n\n    Info(slide, 0, ((char *)slide, LoadFarString(CRC32Value), G.crec.crc32));\n    Info(slide, 0, ((char *)slide, LoadFarString(CompressedFileSize),\n      FmZofft(G.crec.csize, NULL, \"u\")));\n    Info(slide, 0, ((char *)slide, LoadFarString(UncompressedFileSize),\n      FmZofft(G.crec.ucsize, NULL, \"u\")));\n    Info(slide, 0, ((char *)slide, LoadFarString(FilenameLength),\n      G.crec.filename_length));\n    Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldLength),\n      G.crec.extra_field_length));\n    Info(slide, 0, ((char *)slide, LoadFarString(FileCommentLength),\n      G.crec.file_comment_length));\n    Info(slide, 0, ((char *)slide, LoadFarString(FileDiskNum),\n      (ulg)(G.crec.disk_number_start + 1)));\n    Info(slide, 0, ((char *)slide, LoadFarString(ApparentFileType),\n      (G.crec.internal_file_attributes & 1)? \"text\"\n         : (G.crec.internal_file_attributes & 2)? \"ebcdic\"\n              : \"binary\"));             /* changed to accept EBCDIC */\n#ifdef ATARI\n    printf(\"  external file attributes (hex):                   %.8lx\\n\",\n      G.crec.external_file_attributes);\n#endif\n    xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF);\n    if (hostnum == VMS_) {\n        char   *p=attribs, *q=attribs+1;\n        int    i, j, k;\n\n        for (k = 0;  k < 12;  ++k)\n            workspace[k] = 0;\n        if (xattr & VMS_IRUSR)\n            workspace[0] = 'R';\n        if (xattr & VMS_IWUSR) {\n            workspace[1] = 'W';\n            workspace[3] = 'D';\n        }\n        if (xattr & VMS_IXUSR)\n            workspace[2] = 'E';\n        if (xattr & VMS_IRGRP)\n            workspace[4] = 'R';\n        if (xattr & VMS_IWGRP) {\n            workspace[5] = 'W';\n            workspace[7] = 'D';\n        }\n        if (xattr & VMS_IXGRP)\n            workspace[6] = 'E';\n        if (xattr & VMS_IROTH)\n            workspace[8] = 'R';\n        if (xattr & VMS_IWOTH) {\n            workspace[9] = 'W';\n            workspace[11] = 'D';\n        }\n        if (xattr & VMS_IXOTH)\n            workspace[10] = 'E';\n\n        *p++ = '(';\n        for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */\n            for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */\n                if (workspace[k])\n                    *p++ = workspace[k];\n            *p++ = ',';                       /* group separator */\n            if (j == 0)\n                while ((*p++ = *q++) != ',')\n                    ;                         /* system, owner perms are same */\n        }\n        *p-- = '\\0';\n        *p = ')';   /* overwrite last comma */\n        Info(slide, 0, ((char *)slide, LoadFarString(VMSFileAttributes), xattr,\n          attribs));\n\n    } else if (hostnum == AMIGA_) {\n        switch (xattr & AMI_IFMT) {\n            case AMI_IFDIR:  attribs[0] = 'd';  break;\n            case AMI_IFREG:  attribs[0] = '-';  break;\n            default:         attribs[0] = '?';  break;\n        }\n        attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';\n        attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';\n        attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';\n        attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';\n        attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';\n        attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';\n        attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';\n        attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';\n        attribs[9] = 0;   /* better dlm the string */\n        Info(slide, 0, ((char *)slide, LoadFarString(AmigaFileAttributes),\n          xattr, attribs));\n\n    } else if (hostnum == THEOS_) {\n        ZCONST char Far *fpFtyp;\n\n        switch (xattr & THS_IFMT) {\n            case THS_IFLIB:  fpFtyp = TheosFTypLib;  break;\n            case THS_IFDIR:  fpFtyp = TheosFTypDir;  break;\n            case THS_IFREG:  fpFtyp = TheosFTypReg;  break;\n            case THS_IFREL:  fpFtyp = TheosFTypRel;  break;\n            case THS_IFKEY:  fpFtyp = TheosFTypKey;  break;\n            case THS_IFIND:  fpFtyp = TheosFTypInd;  break;\n            case THS_IFR16:  fpFtyp = TheosFTypR16;  break;\n            case THS_IFP16:  fpFtyp = TheosFTypP16;  break;\n            case THS_IFP32:  fpFtyp = TheosFTypP32;  break;\n            default:         fpFtyp = TheosFTypUkn;  break;\n        }\n        strcpy(attribs, LoadFarStringSmall(fpFtyp));\n        attribs[12] = (xattr & THS_INHID) ? '.' : 'H';\n        attribs[13] = (xattr & THS_IMODF) ? '.' : 'M';\n        attribs[14] = (xattr & THS_IWOTH) ? '.' : 'W';\n        attribs[15] = (xattr & THS_IROTH) ? '.' : 'R';\n        attribs[16] = (xattr & THS_IEUSR) ? '.' : 'E';\n        attribs[17] = (xattr & THS_IXUSR) ? '.' : 'X';\n        attribs[18] = (xattr & THS_IWUSR) ? '.' : 'W';\n        attribs[19] = (xattr & THS_IRUSR) ? '.' : 'R';\n        attribs[20] = 0;\n        Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes),\n          xattr, attribs));\n\n#ifdef OLD_THEOS_EXTRA\n    } else if (hostnum == FS_VFAT_ && hostver == 20) {\n        /* process old non-official THEOS port zip archive */\n        ZCONST char Far *fpFtyp;\n\n        switch (xattr & _THS_IFMT) {\n            case _THS_IFLIB:  fpFtyp = TheosFTypLib;  break;\n            case _THS_IFDIR:  fpFtyp = TheosFTypDir;  break;\n            case _THS_IFREG:  fpFtyp = TheosFTypReg;  break;\n            case _THS_IODRC:  fpFtyp = TheosFTypRel;  break;\n            case _THS_IOKEY:  fpFtyp = TheosFTypKey;  break;\n            case _THS_IOIND:  fpFtyp = TheosFTypInd;  break;\n            case _THS_IOPRG:  fpFtyp = TheosFTypR16;  break;\n            case _THS_IO286:  fpFtyp = TheosFTypP16;  break;\n            case _THS_IO386:  fpFtyp = TheosFTypP32;  break;\n            default:         fpFtyp = TheosFTypUkn;  break;\n        }\n        strcpy(attribs, LoadFarStringSmall(fpFtyp));\n        attribs[12] = (xattr & _THS_HIDDN) ? 'H' : '.';\n        attribs[13] = (xattr & _THS_IXOTH) ? '.' : 'X';\n        attribs[14] = (xattr & _THS_IWOTH) ? '.' : 'W';\n        attribs[15] = (xattr & _THS_IROTH) ? '.' : 'R';\n        attribs[16] = (xattr & _THS_IEUSR) ? '.' : 'E';\n        attribs[17] = (xattr & _THS_IXUSR) ? '.' : 'X';\n        attribs[18] = (xattr & _THS_IWUSR) ? '.' : 'W';\n        attribs[19] = (xattr & _THS_IRUSR) ? '.' : 'R';\n        attribs[20] = 0;\n        Info(slide, 0, ((char *)slide, LoadFarString(TheosFileAttributes),\n          xattr, attribs));\n#endif /* OLD_THEOS_EXTRA */\n\n    } else if ((hostnum != FS_FAT_) && (hostnum != FS_HPFS_) &&\n               (hostnum != FS_NTFS_) && (hostnum != FS_VFAT_) &&\n               (hostnum != ACORN_) &&\n               (hostnum != VM_CMS_) && (hostnum != MVS_))\n    {                                 /* assume Unix-like */\n        switch ((unsigned)(xattr & UNX_IFMT)) {\n            case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;\n            case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;\n            case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;\n            case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;\n            case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;\n            case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;\n            case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;\n            default:          attribs[0] = '?';  break;\n        }\n        attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';\n        attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';\n        attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';\n\n        attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';\n        attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';\n        attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';\n\n        if (xattr & UNX_IXUSR)\n            attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';\n        else\n            attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';   /* S = undefined */\n        if (xattr & UNX_IXGRP)\n            attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';   /* == UNX_ENFMT */\n        else\n            attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';\n        if (xattr & UNX_IXOTH)\n            attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';   /* \"sticky bit\" */\n        else\n            attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';   /* T = undefined */\n        attribs[10] = 0;\n\n        Info(slide, 0, ((char *)slide, LoadFarString(UnixFileAttributes), xattr,\n          attribs));\n\n    } else {\n        Info(slide, 0, ((char *)slide, LoadFarString(NonMSDOSFileAttributes),\n            G.crec.external_file_attributes >> 8));\n\n    } /* endif (hostnum: external attributes format) */\n\n    if ((xattr=(unsigned)(G.crec.external_file_attributes & 0xFF)) == 0)\n        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributes),\n          xattr));\n    else if (xattr == 1)\n        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesRO),\n          xattr));\n    else\n        Info(slide, 0, ((char *)slide, LoadFarString(MSDOSFileAttributesAlpha),\n          xattr, (xattr&1)? \"rdo \" : nullStr,\n          (xattr&2)? \"hid \" : nullStr,\n          (xattr&4)? \"sys \" : nullStr,\n          (xattr&8)? \"lab \" : nullStr,\n          (xattr&16)? \"dir \" : nullStr,\n          (xattr&32)? \"arc \" : nullStr,\n          (xattr&64)? \"lnk \" : nullStr,\n          (xattr&128)? \"exe\" : nullStr));\n\n/*---------------------------------------------------------------------------\n    Analyze the extra field, if any, and print the file comment, if any (the\n    filename has already been printed, above).  That finishes up this file\n    entry...\n  ---------------------------------------------------------------------------*/\n\n    if (G.crec.extra_field_length > 0) {\n        uch *ef_ptr = G.extra_field;\n        ush ef_len = G.crec.extra_field_length;\n        ush eb_id, eb_datalen;\n        ZCONST char Far *ef_fieldname;\n\n        if (error_in_archive > PK_WARN)   /* fatal:  can't continue */\n            /* delayed \"fatal error\" return from extra field reading */\n            return error_in_archive;\n        if (G.extra_field == (uch *)NULL)\n            return PK_ERR;   /* not consistent with crec length */\n\n        Info(slide, 0, ((char *)slide, LoadFarString(ExtraFields)));\n\n        while (ef_len >= EB_HEADSIZE) {\n            eb_id = makeword(&ef_ptr[EB_ID]);\n            eb_datalen = makeword(&ef_ptr[EB_LEN]);\n            ef_ptr += EB_HEADSIZE;\n            ef_len -= EB_HEADSIZE;\n\n            if (eb_datalen > (ush)ef_len) {\n                Info(slide, 0x421, ((char *)slide,\n                  LoadFarString(ExtraFieldTrunc), eb_id, eb_datalen, ef_len));\n                eb_datalen = ef_len;\n            }\n\n            switch (eb_id) {\n                case EF_PKSZ64:\n                    ef_fieldname = efPKSZ64;\n                    if ((G.crec.relative_offset_local_header\n                         & (~(zusz_t)0xFFFFFFFFL)) != 0) {\n                        /* Subtract the size of the 64bit local offset from\n                           the local e.f. size, local Z64 e.f. block has no\n                           offset; when only local offset present, the entire\n                           local PKSZ64 block is missing. */\n                        *pEndprev -= (eb_datalen == 8 ? 12 : 8);\n                    }\n                    break;\n                case EF_AV:\n                    ef_fieldname = efAV;\n                    break;\n                case EF_OS2:\n                    ef_fieldname = efOS2;\n                    break;\n                case EF_ACL:\n                    ef_fieldname = efACL;\n                    break;\n                case EF_NTSD:\n                    ef_fieldname = efNTSD;\n                    break;\n                case EF_PKVMS:\n                    ef_fieldname = efPKVMS;\n                    break;\n                case EF_IZVMS:\n                    ef_fieldname = efIZVMS;\n                    break;\n                case EF_PKW32:\n                    ef_fieldname = efPKWin32;\n                    break;\n                case EF_PKUNIX:\n                    ef_fieldname = efPKUnix;\n                    break;\n                case EF_IZUNIX:\n                    ef_fieldname = efIZUnix;\n                    if (hostnum == UNIX_ && *pEndprev > 0L)\n                        *pEndprev += 4L;  /* also have UID/GID in local copy */\n                    break;\n                case EF_IZUNIX2:\n                    ef_fieldname = efIZUnix2;\n                    if (*pEndprev > 0L)\n                        *pEndprev += 4L;  /* 4 byte UID/GID in local copy */\n                    break;\n                case EF_IZUNIX3:\n                    ef_fieldname = efIZUnix3;\n#if 0\n                    if (*pEndprev > 0L)\n                        *pEndprev += 4L;  /* 4 byte UID/GID in local copy */\n#endif\n                    break;\n                case EF_TIME:\n                    ef_fieldname = efTime;\n                    break;\n                case EF_UNIPATH:\n                    ef_fieldname = efU8Path;\n                    break;\n                case EF_UNICOMNT:\n                    ef_fieldname = efU8Commnt;\n                    break;\n                case EF_MAC3:\n                    ef_fieldname = efMac3;\n                    break;\n                case EF_JLMAC:\n                    ef_fieldname = efJLMac;\n                    break;\n                case EF_ZIPIT:\n                    ef_fieldname = efZipIt;\n                    break;\n                case EF_ZIPIT2:\n                    ef_fieldname = efZipIt2;\n                    break;\n                case EF_VMCMS:\n                    ef_fieldname = efVMCMS;\n                    break;\n                case EF_MVS:\n                    ef_fieldname = efMVS;\n                    break;\n                case EF_ATHEOS:\n                    ef_fieldname = efAtheOS;\n                    break;\n                case EF_BEOS:\n                    ef_fieldname = efBeOS;\n                    break;\n                case EF_QDOS:\n                    ef_fieldname = efQDOS;\n                    break;\n                case EF_AOSVS:\n                    ef_fieldname = efAOSVS;\n                    break;\n                case EF_SPARK:   /* from RISC OS */\n                    ef_fieldname = efSpark;\n                    break;\n                case EF_MD5:\n                    ef_fieldname = efMD5;\n                    break;\n                case EF_ASIUNIX:\n                    ef_fieldname = efASiUnix;\n                    break;\n                case EF_TANDEM:\n                    ef_fieldname = efTandem;\n                    break;\n                case EF_SMARTZIP:\n                    ef_fieldname = efSmartZip;\n                    break;\n                case EF_THEOS:\n#ifdef OLD_THEOS_EXTRA\n                case EF_THEOSO:\n#endif\n                    ef_fieldname = efTheos;\n                    break;\n                default:\n                    ef_fieldname = efUnknown;\n                    break;\n            }\n            Info(slide, 0, ((char *)slide, LoadFarString(ExtraFieldType),\n                 eb_id, LoadFarStringSmall(ef_fieldname), eb_datalen));\n\n            /* additional, field-specific information: */\n            switch (eb_id) {\n                case EF_OS2:\n                case EF_ACL:\n                    if (eb_datalen >= EB_OS2_HLEN) {\n                        if (eb_id == EF_OS2)\n                            ef_fieldname = OS2EAs;\n                        else\n                            ef_fieldname = ACLdata;\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(ef_fieldname), makelong(ef_ptr)));\n                        *pEndprev = 0L;   /* no clue about csize of local */\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_NTSD:\n                    if (eb_datalen >= EB_NTSD_C_LEN) {\n                        Info(slide, 0, ((char *)slide, LoadFarString(NTSDData),\n                          makelong(ef_ptr)));\n                        *pEndprev = 0L;   /* no clue about csize of local */\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_IZVMS:\n                    if (eb_datalen >= 8) {\n                        char *p, q[8];\n                        unsigned compr = makeword(ef_ptr+EB_IZVMS_FLGS)\n                                        & EB_IZVMS_BCMASK;\n\n                        *q = '\\0';\n                        if (compr > 3)\n                            compr = 3;\n                        switch (makelong(ef_ptr)) {\n                            case 0x42414656: /* \"VFAB\" */\n                                p = \"FAB\"; break;\n                            case 0x4C4C4156: /* \"VALL\" */\n                                p = \"XABALL\"; break;\n                            case 0x43484656: /* \"VFHC\" */\n                                p = \"XABFHC\"; break;\n                            case 0x54414456: /* \"VDAT\" */\n                                p = \"XABDAT\"; break;\n                            case 0x54445256: /* \"VRDT\" */\n                                p = \"XABRDT\"; break;\n                            case 0x4F525056: /* \"VPRO\" */\n                                p = \"XABPRO\"; break;\n                            case 0x59454B56: /* \"VKEY\" */\n                                p = \"XABKEY\"; break;\n                            case 0x56534D56: /* \"VMSV\" */\n                                p = \"version\";\n                                if (eb_datalen >= 16) {\n                                    /* put termitation first, for A_TO_N() */\n                                    q[7] = '\\0';\n                                    q[0] = ' ';\n                                    q[1] = '(';\n                                    strncpy(q+2,\n                                            (char *)ef_ptr+EB_IZVMS_HLEN, 4);\n                                    A_TO_N(q+2);\n                                    q[6] = ')';\n                                }\n                                break;\n                            default:\n                                p = \"unknown\";\n                        }\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(izVMSdata),\n                          LoadFarStringSmall(izVMScomp[compr]),\n                          makeword(ef_ptr+EB_IZVMS_UCSIZ), p, q));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_TIME:\n                    if (eb_datalen > 0) {\n                        char types[80];\n                        int num = 0, len;\n\n                        *types = '\\0';\n                        if (*ef_ptr & 1) {\n                            strcpy(types, LoadFarString(UTmodification));\n                            ++num;\n                        }\n                        if (*ef_ptr & 2) {\n                            len = strlen(types);\n                            if (num)\n                                types[len++] = '/';\n                            strcpy(types+len, LoadFarString(UTaccess));\n                            ++num;\n                            if (*pEndprev > 0L)\n                                *pEndprev += 4L;\n                        }\n                        if (*ef_ptr & 4) {\n                            len = strlen(types);\n                            if (num)\n                                types[len++] = '/';\n                            strcpy(types+len, LoadFarString(UTcreation));\n                            ++num;\n                            if (*pEndprev > 0L)\n                                *pEndprev += 4L;\n                        }\n                        if (num > 0)\n                            Info(slide, 0, ((char *)slide,\n                              LoadFarString(UTdata), types,\n                              num == 1? nullStr : PlurSufx));\n                    }\n                    break;\n                case EF_UNIPATH:\n                case EF_UNICOMNT:\n                    if (eb_datalen >= 5) {\n                        unsigned i, n;\n                        ulg name_crc = makelong(ef_ptr+1);\n\n                        if (eb_datalen <= 29) {\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(U8PthCmnComplete),\n                                 (unsigned)ef_ptr[0], name_crc));\n                            n = eb_datalen;\n                        } else {\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(U8PthCmnF24),\n                                 (unsigned)ef_ptr[0], name_crc));\n                            n = 29;\n                        }\n                        for (i = 5;  i < n;  ++i)\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(efFormat), ef_ptr[i]));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_MAC3:\n                    if (eb_datalen >= EB_MAC3_HLEN) {\n                        ulg eb_uc = makelong(ef_ptr);\n                        unsigned mac3_flgs = makeword(ef_ptr+EB_FLGS_OFFS);\n                        unsigned eb_is_uc = mac3_flgs & EB_M3_FL_UNCMPR;\n\n                        Info(slide, 0, ((char *)slide, LoadFarString(Mac3data),\n                          eb_uc, eb_is_uc ? \"un\" : nullStr));\n                        if (eb_is_uc) {\n                            if (*pEndprev > 0L)\n                                *pEndprev += makelong(ef_ptr);\n                        } else {\n                            *pEndprev = 0L; /* no clue about csize of local */\n                        }\n\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(MacOSMAC3flags),\n                          LoadFarStringSmall(mac3_flgs & EB_M3_FL_DATFRK ?\n                                             MacOS_DF : MacOS_RF),\n                          (mac3_flgs & EB_M3_FL_TIME64 ? 64 : 32)));\n                        zi_showMacTypeCreator(__G__ &ef_ptr[6]);\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_ZIPIT2:\n                    if (eb_datalen >= 5 &&\n                        makelong(ef_ptr) == 0x5449505A /* \"ZPIT\" */) {\n\n                        if (eb_datalen >= 12) {\n                            zi_showMacTypeCreator(__G__ &ef_ptr[4]);\n                        }\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_ZIPIT:\n                    if (eb_datalen >= 5 &&\n                        makelong(ef_ptr) == 0x5449505A /* \"ZPIT\" */) {\n                        unsigned fnlen = ef_ptr[4];\n\n                        if ((unsigned)eb_datalen >= fnlen + (5 + 8)) {\n                            uch nullchar = ef_ptr[fnlen+5];\n\n                            ef_ptr[fnlen+5] = '\\0'; /* terminate filename */\n                            A_TO_N(ef_ptr+5);\n                            Info(slide, 0, ((char *)slide,\n                              LoadFarString(ZipItFname), (char *)ef_ptr+5));\n                            ef_ptr[fnlen+5] = nullchar;\n                            zi_showMacTypeCreator(__G__ &ef_ptr[fnlen+5]);\n                        }\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_JLMAC:\n                    if (eb_datalen >= 40 &&\n                        makelong(ef_ptr) == 0x45454C4A /* \"JLEE\" */)\n                    {\n                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);\n\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(MacOSJLEEflags),\n                          LoadFarStringSmall(ef_ptr[31] & 1 ?\n                                             MacOS_DF : MacOS_RF)));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_SMARTZIP:\n                    if ((eb_datalen == EB_SMARTZIP_HLEN) &&\n                        makelong(ef_ptr) == 0x70695A64 /* \"dZip\" */) {\n                        char filenameBuf[32];\n                        zi_showMacTypeCreator(__G__ &ef_ptr[4]);\n                        memcpy(filenameBuf, &ef_ptr[33], 31);\n                        filenameBuf[ef_ptr[32]] = '\\0';\n                        A_TO_N(filenameBuf);\n                        Info(slide, 0, ((char *)slide,\n                             LoadFarString(ZipItFname), filenameBuf));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n#ifdef CMS_MVS\n                case EF_VMCMS:\n                case EF_MVS:\n                    {\n                        char type[100];\n\n                        Info(slide, 0, ((char *)slide,\n                             LoadFarString(VmMvsExtraField),\n                             (getVMMVSexfield(type, ef_ptr-EB_HEADSIZE,\n                             (unsigned)eb_datalen) > 0)?\n                             type : LoadFarStringSmall(VmMvsInvalid)));\n                    }\n                    break;\n#endif /* CMS_MVS */\n                case EF_ATHEOS:\n                case EF_BEOS:\n                    if (eb_datalen >= EB_BEOS_HLEN) {\n                        ulg eb_uc = makelong(ef_ptr);\n                        unsigned eb_is_uc =\n                          *(ef_ptr+EB_FLGS_OFFS) & EB_BE_FL_UNCMPR;\n\n                        if (eb_id == EF_ATHEOS)\n                            ef_fieldname = AtheOSdata;\n                        else\n                            ef_fieldname = BeOSdata;\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(ef_fieldname),\n                          eb_uc, eb_is_uc ? \"un\" : nullStr));\n                        if (eb_is_uc) {\n                            if (*pEndprev > 0L)\n                                *pEndprev += makelong(ef_ptr);\n                        } else {\n                            *pEndprev = 0L; /* no clue about csize of local */\n                        }\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_QDOS:\n                    if (eb_datalen >= 4) {\n                        Info(slide, 0, ((char *)slide, LoadFarString(QDOSdata),\n                          ef_ptr[0], ef_ptr[1], ef_ptr[2], ef_ptr[3]));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_AOSVS:\n                    if (eb_datalen >= 5) {\n                        Info(slide, 0, ((char *)slide, LoadFarString(AOSVSdata),\n                          ((int)(uch)ef_ptr[4])/10, ((int)(uch)ef_ptr[4])%10));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_TANDEM:\n                    if (eb_datalen == 20) {\n                        unsigned type, code;\n\n                        type = (ef_ptr[18] & 0x60) >> 5;\n                        code = makeword(ef_ptr);\n                        /* Arrg..., Tandem e.f. uses BigEndian byte-order */\n                        code = ((code << 8) & 0xff00) | ((code >> 8) & 0x00ff);\n                        if (type == NSK_UNSTRUCTURED) {\n                            if (code == NSK_EDITFILECODE)\n                                type = 4;\n                            else if (code == NSK_OBJECTFILECODE)\n                                type = 5;\n                        }\n                        Info(slide, 0, ((char *)slide,\n                          LoadFarString(Tandemdata),\n                          LoadFarStringSmall(TandemFileformat[type]),\n                          code));\n                    } else {\n                        goto ef_default_display;\n                    }\n                    break;\n                case EF_MD5:\n                    if (eb_datalen >= 19) {\n                        char md5[33];\n                        int i;\n\n                        for (i = 0;  i < 16;  ++i)\n                            sprintf(&md5[i<<1], \"%02x\", ef_ptr[15-i]);\n                        md5[32] = '\\0';\n                        Info(slide, 0, ((char *)slide, LoadFarString(MD5data),\n                          md5));\n                        break;\n                    }   /* else: fall through !! */\n                default:\nef_default_display:\n                    if (eb_datalen > 0) {\n                        unsigned i, n;\n\n                        if (eb_datalen <= 24) {\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(ColonIndent)));\n                            n = eb_datalen;\n                        } else {\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(First20)));\n                            n = 20;\n                        }\n                        for (i = 0;  i < n;  ++i)\n                            Info(slide, 0, ((char *)slide,\n                                 LoadFarString(efFormat), ef_ptr[i]));\n                    }\n                    break;\n            }\n            (*G.message)((zvoid *)&G, (uch *)\".\", 1L, 0);\n\n            ef_ptr += eb_datalen;\n            ef_len -= eb_datalen;\n        }\n        (*G.message)((zvoid *)&G, (uch *)\"\\n\", 1L, 0);\n    }\n\n    /* high bit == Unix/OS2/NT GMT times (mtime, atime); next bit == UID/GID */\n    if ((xattr = (unsigned)((G.crec.external_file_attributes & 0xC000) >> 12))\n        & 8)\n    {\n        if (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)\n        {\n            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),\n              \"is\", EF_IZUNIX, LoadFarStringSmall(efIZUnix),\n              (unsigned)(xattr&12), (xattr&4)? efIZuid : efIZnouid));\n            if (*pEndprev > 0L)\n                *pEndprev += (ulg)(xattr&12);\n        }\n        else if (hostnum == FS_FAT_ && !(xattr&4))\n            Info(slide, 0, ((char *)slide, LoadFarString(lExtraFieldType),\n              \"may be\", EF_IZUNIX, LoadFarStringSmall(efIZUnix), 8,\n              efIZnouid));\n    }\n\n    if (!G.crec.file_comment_length)\n        Info(slide, 0, ((char *)slide, LoadFarString(NoFileComment)));\n    else {\n        Info(slide, 0, ((char *)slide, LoadFarString(FileCommBegin)));\n        if ((error = do_string(__G__ G.crec.file_comment_length, DISPL_8)) !=\n            PK_COOL)\n        {\n            error_in_archive = error;   /* might be warning */\n            if (error > PK_WARN)   /* fatal */\n                return error;\n        }\n        Info(slide, 0, ((char *)slide, LoadFarString(FileCommEnd)));\n    }\n\n    return error_in_archive;\n\n} /* end function zi_long() */\n\n\n\n\n\n/*************************/\n/*  Function zi_short()  */\n/*************************/\n\nstatic int zi_short(__G)   /* return PK-type error code */\n    __GDEF\n{\n#ifdef USE_EF_UT_TIME\n    iztimes     z_utime;\n    time_t      *z_modtim;\n#endif\n    int         k, error, error_in_archive=PK_COOL;\n    unsigned    hostnum, hostver, methid, methnum, xattr;\n    char        *p, workspace[12], attribs[16];\n    char        methbuf[5];\n    static ZCONST char dtype[5]=\"NXFS\"; /* normal, maximum, fast, superfast */\n    static ZCONST char Far os[NUM_HOSTS+1][4] = {\n        \"fat\", \"ami\", \"vms\", \"unx\", \"cms\", \"atr\", \"hpf\", \"mac\", \"zzz\",\n        \"cpm\", \"t20\", \"ntf\", \"qds\", \"aco\", \"vft\", \"mvs\", \"be \", \"nsk\",\n        \"ths\", \"osx\", \"???\", \"???\", \"???\", \"???\", \"???\", \"???\", \"???\",\n        \"???\", \"???\", \"???\", \"ath\", \"???\"\n    };\n#ifdef OLD_THEOS_EXTRA\n    static ZCONST char Far os_TheosOld[] = \"tho\";\n#endif\n    static ZCONST char Far method[NUM_METHODS+1][5] = {\n        \"stor\", \"shrk\", \"re:1\", \"re:2\", \"re:3\", \"re:4\", \"i#:#\", \"tokn\",\n        \"def#\", \"d64#\", \"dcli\", \"bzp2\", \"lzma\", \"ters\", \"lz77\", \"wavp\",\n        \"ppmd\", \"u###\"\n    };\n\n\n/*---------------------------------------------------------------------------\n    Print out various interesting things about the compressed file.\n  ---------------------------------------------------------------------------*/\n\n    methid = (unsigned)(G.crec.compression_method);\n    methnum = find_compr_idx(G.crec.compression_method);\n    hostnum = (unsigned)(G.pInfo->hostnum);\n    hostver = (unsigned)(G.pInfo->hostver);\n/*\n    extnum = (unsigned)MIN(G.crec.version_needed_to_extract[1], NUM_HOSTS);\n    extver = (unsigned)G.crec.version_needed_to_extract[0];\n */\n\n    zfstrcpy(methbuf, method[methnum]);\n    if (methid == IMPLODED) {\n        methbuf[1] = (char)((G.crec.general_purpose_bit_flag & 2)? '8' : '4');\n        methbuf[3] = (char)((G.crec.general_purpose_bit_flag & 4)? '3' : '2');\n    } else if (methid == DEFLATED || methid == ENHDEFLATED) {\n        ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);\n        methbuf[3] = dtype[dnum];\n    } else if (methnum >= NUM_METHODS) {   /* unknown */\n        sprintf(&methbuf[1], \"%03u\", G.crec.compression_method);\n    }\n\n    for (k = 0;  k < 15;  ++k)\n        attribs[k] = ' ';\n    attribs[15] = 0;\n\n    xattr = (unsigned)((G.crec.external_file_attributes >> 16) & 0xFFFF);\n    switch (hostnum) {\n        case VMS_:\n            {   int    i, j;\n\n                for (k = 0;  k < 12;  ++k)\n                    workspace[k] = 0;\n                if (xattr & VMS_IRUSR)\n                    workspace[0] = 'R';\n                if (xattr & VMS_IWUSR) {\n                    workspace[1] = 'W';\n                    workspace[3] = 'D';\n                }\n                if (xattr & VMS_IXUSR)\n                    workspace[2] = 'E';\n                if (xattr & VMS_IRGRP)\n                    workspace[4] = 'R';\n                if (xattr & VMS_IWGRP) {\n                    workspace[5] = 'W';\n                    workspace[7] = 'D';\n                }\n                if (xattr & VMS_IXGRP)\n                  workspace[6] = 'E';\n                if (xattr & VMS_IROTH)\n                    workspace[8] = 'R';\n                if (xattr & VMS_IWOTH) {\n                    workspace[9] = 'W';\n                    workspace[11] = 'D';\n                }\n                if (xattr & VMS_IXOTH)\n                    workspace[10] = 'E';\n\n                p = attribs;\n                for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */\n                    for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */\n                        if (workspace[k])\n                            *p++ = workspace[k];\n                    *p++ = ',';                     /* group separator */\n                }\n                *--p = ' ';   /* overwrite last comma */\n                if ((p - attribs) < 12)\n                    sprintf(&attribs[12], \"%u.%u\", hostver/10, hostver%10);\n            }\n            break;\n\n        case AMIGA_:\n            switch (xattr & AMI_IFMT) {\n                case AMI_IFDIR:  attribs[0] = 'd';  break;\n                case AMI_IFREG:  attribs[0] = '-';  break;\n                default:         attribs[0] = '?';  break;\n            }\n            attribs[1] = (xattr & AMI_IHIDDEN)?   'h' : '-';\n            attribs[2] = (xattr & AMI_ISCRIPT)?   's' : '-';\n            attribs[3] = (xattr & AMI_IPURE)?     'p' : '-';\n            attribs[4] = (xattr & AMI_IARCHIVE)?  'a' : '-';\n            attribs[5] = (xattr & AMI_IREAD)?     'r' : '-';\n            attribs[6] = (xattr & AMI_IWRITE)?    'w' : '-';\n            attribs[7] = (xattr & AMI_IEXECUTE)?  'e' : '-';\n            attribs[8] = (xattr & AMI_IDELETE)?   'd' : '-';\n            sprintf(&attribs[12], \"%u.%u\", hostver/10, hostver%10);\n            break;\n\n        case THEOS_:\n            switch (xattr & THS_IFMT) {\n                case THS_IFLIB: *attribs = 'L'; break;\n                case THS_IFDIR: *attribs = 'D'; break;\n                case THS_IFCHR: *attribs = 'C'; break;\n                case THS_IFREG: *attribs = 'S'; break;\n                case THS_IFREL: *attribs = 'R'; break;\n                case THS_IFKEY: *attribs = 'K'; break;\n                case THS_IFIND: *attribs = 'I'; break;\n                case THS_IFR16: *attribs = 'P'; break;\n                case THS_IFP16: *attribs = '2'; break;\n                case THS_IFP32: *attribs = '3'; break;\n                default:        *attribs = '?'; break;\n            }\n            attribs[1] = (xattr & THS_INHID) ? '.' : 'H';\n            attribs[2] = (xattr & THS_IMODF) ? '.' : 'M';\n            attribs[3] = (xattr & THS_IWOTH) ? '.' : 'W';\n            attribs[4] = (xattr & THS_IROTH) ? '.' : 'R';\n            attribs[5] = (xattr & THS_IEUSR) ? '.' : 'E';\n            attribs[6] = (xattr & THS_IXUSR) ? '.' : 'X';\n            attribs[7] = (xattr & THS_IWUSR) ? '.' : 'W';\n            attribs[8] = (xattr & THS_IRUSR) ? '.' : 'R';\n            sprintf(&attribs[12], \"%u.%u\", hostver/10, hostver%10);\n            break;\n\n        case FS_VFAT_:\n#ifdef OLD_THEOS_EXTRA\n            if (hostver == 20) {\n                switch (xattr & _THS_IFMT) {\n                    case _THS_IFLIB: *attribs = 'L'; break;\n                    case _THS_IFDIR: *attribs = 'd'; break;\n                    case _THS_IFCHR: *attribs = 'c'; break;\n                    case _THS_IFREG: *attribs = 'S'; break;\n                    case _THS_IODRC: *attribs = 'D'; break;\n                    case _THS_IOKEY: *attribs = 'K'; break;\n                    case _THS_IOIND: *attribs = 'I'; break;\n                    case _THS_IOPRG: *attribs = 'P'; break;\n                    case _THS_IO286: *attribs = '2'; break;\n                    case _THS_IO386: *attribs = '3'; break;\n                    default:         *attribs = '?'; break;\n                }\n                attribs[1] = (xattr & _THS_HIDDN) ? 'H' : '.';\n                attribs[2] = (xattr & _THS_IXOTH) ? '.' : 'X';\n                attribs[3] = (xattr & _THS_IWOTH) ? '.' : 'W';\n                attribs[4] = (xattr & _THS_IROTH) ? '.' : 'R';\n                attribs[5] = (xattr & _THS_IEUSR) ? '.' : 'E';\n                attribs[6] = (xattr & _THS_IXUSR) ? '.' : 'X';\n                attribs[7] = (xattr & _THS_IWUSR) ? '.' : 'W';\n                attribs[8] = (xattr & _THS_IRUSR) ? '.' : 'R';\n                sprintf(&attribs[12], \"%u.%u\", hostver/10, hostver%10);\n                break;\n            } /* else: fall through! */\n#endif /* OLD_THEOS_EXTRA */\n\n        case FS_FAT_:\n        case FS_HPFS_:\n        case FS_NTFS_:\n        case VM_CMS_:\n        case MVS_:\n        case ACORN_:\n            if (hostnum != FS_FAT_ ||\n                (unsigned)(xattr & 0700) !=\n                 ((unsigned)0400 |\n                  ((unsigned)!(G.crec.external_file_attributes & 1) << 7) |\n                  ((unsigned)(G.crec.external_file_attributes & 0x10) << 2))\n               )\n            {\n                xattr = (unsigned)(G.crec.external_file_attributes & 0xFF);\n                sprintf(attribs, \".r.-...     %u.%u\", hostver/10, hostver%10);\n                attribs[2] = (xattr & 0x01)? '-' : 'w';\n                attribs[5] = (xattr & 0x02)? 'h' : '-';\n                attribs[6] = (xattr & 0x04)? 's' : '-';\n                attribs[4] = (xattr & 0x20)? 'a' : '-';\n                if (xattr & 0x10) {\n                    attribs[0] = 'd';\n                    attribs[3] = 'x';\n                } else\n                    attribs[0] = '-';\n                if (IS_VOLID(xattr))\n                    attribs[0] = 'V';\n                else if ((p = MBSRCHR(G.filename, '.')) != (char *)NULL) {\n                    ++p;\n                    if (STRNICMP(p, \"com\", 3) == 0 ||\n                        STRNICMP(p, \"exe\", 3) == 0 ||\n                        STRNICMP(p, \"btm\", 3) == 0 ||\n                        STRNICMP(p, \"cmd\", 3) == 0 ||\n                        STRNICMP(p, \"bat\", 3) == 0)\n                        attribs[3] = 'x';\n                }\n                break;\n            } /* else: fall through! */\n\n        default:   /* assume Unix-like */\n            switch ((unsigned)(xattr & UNX_IFMT)) {\n                case (unsigned)UNX_IFDIR:   attribs[0] = 'd';  break;\n                case (unsigned)UNX_IFREG:   attribs[0] = '-';  break;\n                case (unsigned)UNX_IFLNK:   attribs[0] = 'l';  break;\n                case (unsigned)UNX_IFBLK:   attribs[0] = 'b';  break;\n                case (unsigned)UNX_IFCHR:   attribs[0] = 'c';  break;\n                case (unsigned)UNX_IFIFO:   attribs[0] = 'p';  break;\n                case (unsigned)UNX_IFSOCK:  attribs[0] = 's';  break;\n                default:          attribs[0] = '?';  break;\n            }\n            attribs[1] = (xattr & UNX_IRUSR)? 'r' : '-';\n            attribs[4] = (xattr & UNX_IRGRP)? 'r' : '-';\n            attribs[7] = (xattr & UNX_IROTH)? 'r' : '-';\n            attribs[2] = (xattr & UNX_IWUSR)? 'w' : '-';\n            attribs[5] = (xattr & UNX_IWGRP)? 'w' : '-';\n            attribs[8] = (xattr & UNX_IWOTH)? 'w' : '-';\n\n            if (xattr & UNX_IXUSR)\n                attribs[3] = (xattr & UNX_ISUID)? 's' : 'x';\n            else\n                attribs[3] = (xattr & UNX_ISUID)? 'S' : '-';  /* S==undefined */\n            if (xattr & UNX_IXGRP)\n                attribs[6] = (xattr & UNX_ISGID)? 's' : 'x';  /* == UNX_ENFMT */\n            else\n                /* attribs[6] = (xattr & UNX_ISGID)? 'l' : '-';  real 4.3BSD */\n                attribs[6] = (xattr & UNX_ISGID)? 'S' : '-';  /* SunOS 4.1.x */\n            if (xattr & UNX_IXOTH)\n                attribs[9] = (xattr & UNX_ISVTX)? 't' : 'x';  /* \"sticky bit\" */\n            else\n                attribs[9] = (xattr & UNX_ISVTX)? 'T' : '-';  /* T==undefined */\n\n            sprintf(&attribs[12], \"%u.%u\", hostver/10, hostver%10);\n            break;\n\n    } /* end switch (hostnum: external attributes format) */\n\n#ifdef OLD_THEOS_EXTRA\n    Info(slide, 0, ((char *)slide, \"%s %s %s \", attribs,\n      LoadFarStringSmall(((hostnum == FS_VFAT_ && hostver == 20) ?\n                          os_TheosOld :\n                          os[hostnum])),\n      FmZofft(G.crec.ucsize, \"8\", \"u\")));\n#else\n    Info(slide, 0, ((char *)slide, \"%s %s %s \", attribs,\n      LoadFarStringSmall(os[hostnum]),\n      FmZofft(G.crec.ucsize, \"8\", \"u\")));\n#endif\n    Info(slide, 0, ((char *)slide, \"%c\",\n      (G.crec.general_purpose_bit_flag & 1)?\n      ((G.crec.internal_file_attributes & 1)? 'T' : 'B') :  /* encrypted */\n      ((G.crec.internal_file_attributes & 1)? 't' : 'b'))); /* plaintext */\n    k = (G.crec.extra_field_length ||\n         /* a local-only \"UX\" (old Unix/OS2/NT GMT times \"IZUNIX\") e.f.? */\n         ((G.crec.external_file_attributes & 0x8000) &&\n          (hostnum == UNIX_ || hostnum == FS_HPFS_ || hostnum == FS_NTFS_)));\n    Info(slide, 0, ((char *)slide, \"%c\", k?\n      ((G.crec.general_purpose_bit_flag & 8)? 'X' : 'x') :  /* extra field */\n      ((G.crec.general_purpose_bit_flag & 8)? 'l' : '-'))); /* no extra field */\n      /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ extended local header or not */\n\n    if (uO.lflag == 4) {\n        zusz_t csiz = G.crec.csize;\n\n        if (G.crec.general_purpose_bit_flag & 1)\n            csiz -= 12;    /* if encrypted, don't count encryption header */\n        Info(slide, 0, ((char *)slide, \"%3d%%\",\n          (ratio(G.crec.ucsize,csiz)+5)/10));\n    } else if (uO.lflag == 5)\n        Info(slide, 0, ((char *)slide, \" %s\",\n          FmZofft(G.crec.csize, \"8\", \"u\")));\n\n    /* For printing of date & time, a \"char d_t_buf[16]\" is required.\n     * To save stack space, we reuse the \"char attribs[16]\" buffer whose\n     * content is no longer needed.\n     */\n#   define d_t_buf attribs\n#ifdef USE_EF_UT_TIME\n    z_modtim = G.extra_field &&\n#ifdef IZ_CHECK_TZ\n               G.tz_is_valid &&\n#endif\n               (ef_scan_for_izux(G.extra_field, G.crec.extra_field_length, 1,\n                                 G.crec.last_mod_dos_datetime, &z_utime, NULL)\n                & EB_UT_FL_MTIME)\n              ? &z_utime.mtime : NULL;\n    TIMET_TO_NATIVE(z_utime.mtime)     /* NOP unless MSC 7.0 or Macintosh */\n    d_t_buf[0] = (char)0;              /* signal \"show local time\" */\n#else\n#   define z_modtim NULL\n#endif\n    Info(slide, 0, ((char *)slide, \" %s %s \", methbuf,\n      zi_time(__G__ &G.crec.last_mod_dos_datetime, z_modtim, d_t_buf)));\n    fnprint(__G);\n\n/*---------------------------------------------------------------------------\n    Skip the file comment, if any (the filename has already been printed,\n    above).  That finishes up this file entry...\n  ---------------------------------------------------------------------------*/\n\n    SKIP_(G.crec.file_comment_length)\n\n    return error_in_archive;\n\n} /* end function zi_short() */\n\n\n\n\n\n/**************************************/\n/*  Function zi_showMacTypeCreator()  */\n/**************************************/\n\nstatic void zi_showMacTypeCreator(__G__ ebfield)\n    __GDEF\n    uch *ebfield;\n{\n    /* not every Type / Creator character is printable */\n    if (isprint(native(ebfield[0])) && isprint(native(ebfield[1])) &&\n        isprint(native(ebfield[2])) && isprint(native(ebfield[3])) &&\n        isprint(native(ebfield[4])) && isprint(native(ebfield[5])) &&\n        isprint(native(ebfield[6])) && isprint(native(ebfield[7]))) {\n       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata),\n            native(ebfield[0]), native(ebfield[1]),\n            native(ebfield[2]), native(ebfield[3]),\n            native(ebfield[4]), native(ebfield[5]),\n            native(ebfield[6]), native(ebfield[7])));\n    } else {\n       Info(slide, 0, ((char *)slide, LoadFarString(MacOSdata1),\n            (((ulg)ebfield[0]) << 24) +\n            (((ulg)ebfield[1]) << 16) +\n            (((ulg)ebfield[2]) << 8)  +\n            ((ulg)ebfield[3]),\n            (((ulg)ebfield[4]) << 24) +\n            (((ulg)ebfield[5]) << 16) +\n            (((ulg)ebfield[6]) << 8)  +\n            ((ulg)ebfield[7])));\n    }\n} /* end function zi_showMacTypeCreator() */\n\n\n\n\n\n/************************/\n/*  Function zi_time()  */\n/************************/\n\nstatic char *zi_time(__G__ datetimez, modtimez, d_t_str)\n    __GDEF\n    ZCONST ulg *datetimez;\n    ZCONST time_t *modtimez;\n    char *d_t_str;\n{\n    unsigned yr, mo, dy, hh, mm, ss;\n    char monthbuf[4];\n    ZCONST char *monthstr;\n    static ZCONST char Far month[12][4] = {\n        \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n        \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"\n    };\n#ifdef USE_EF_UT_TIME\n    struct tm *t;\n#endif\n\n\n\n/*---------------------------------------------------------------------------\n    Convert the file-modification date and time info to a string of the form\n    \"1991 Feb 23 17:15:00\", \"23-Feb-91 17:15\" or \"19910223.171500\", depending\n    on values of lflag and T_flag.  If using Unix-time extra fields, convert\n    to local time or not, depending on value of first character in d_t_str[].\n  ---------------------------------------------------------------------------*/\n\n#ifdef USE_EF_UT_TIME\n    if (modtimez != NULL) {\n#ifndef NO_GMTIME\n        /* check for our secret message from above... */\n        t = (d_t_str[0] == (char)1)? gmtime(modtimez) : localtime(modtimez);\n#else\n        t = localtime(modtimez);\n#endif\n        if (uO.lflag > 9 && t == (struct tm *)NULL)\n            /* time conversion error in verbose listing format,\n             * return string with '?' instead of data\n             */\n            return (strcpy(d_t_str, LoadFarString(lngYMDHMSTimeError)));\n    } else\n        t = (struct tm *)NULL;\n    if (t != (struct tm *)NULL) {\n        mo = (unsigned)(t->tm_mon + 1);\n        dy = (unsigned)(t->tm_mday);\n        yr = (unsigned)(t->tm_year);\n\n        hh = (unsigned)(t->tm_hour);\n        mm = (unsigned)(t->tm_min);\n        ss = (unsigned)(t->tm_sec);\n    } else\n#endif /* USE_EF_UT_TIME */\n    {\n        yr = ((unsigned)(*datetimez >> 25) & 0x7f) + 80;\n        mo = ((unsigned)(*datetimez >> 21) & 0x0f);\n        dy = ((unsigned)(*datetimez >> 16) & 0x1f);\n\n        hh = (((unsigned)*datetimez >> 11) & 0x1f);\n        mm = (((unsigned)*datetimez >> 5) & 0x3f);\n        ss = (((unsigned)*datetimez << 1) & 0x3e);\n    }\n\n    if (mo == 0 || mo > 12) {\n        sprintf(monthbuf, LoadFarString(BogusFmt), mo);\n        monthstr = monthbuf;\n    } else\n        monthstr = LoadFarStringSmall(month[mo-1]);\n\n    if (uO.lflag > 9)   /* verbose listing format */\n        sprintf(d_t_str, LoadFarString(lngYMDHMSTime), yr+1900, monthstr, dy,\n          hh, mm, ss);\n    else if (uO.T_flag)\n        sprintf(d_t_str, LoadFarString(DecimalTime), yr+1900, mo, dy,\n          hh, mm, ss);\n    else   /* was:  if ((uO.lflag >= 3) && (uO.lflag <= 5)) */\n        sprintf(d_t_str, LoadFarString(shtYMDHMTime), yr%100, monthstr, dy,\n          hh, mm);\n\n    return d_t_str;\n\n} /* end function zi_time() */\n\n#endif /* !NO_ZIPINFO */\n"
  },
  {
    "path": "deps/infozip/unzip60/zipinfo.txt",
    "content": "ZIPINFO(1L)                                                        ZIPINFO(1L)\n\nNAME\n       zipinfo - list detailed information about a ZIP archive\n\nSYNOPSIS\n       zipinfo [-12smlvhMtTz] file[.zip] [file(s) ...] [-x xfile(s) ...]\n\n       unzip -Z [-12smlvhMtTz] file[.zip] [file(s) ...] [-x xfile(s) ...]\n\nDESCRIPTION\n       zipinfo  lists technical information about files in a ZIP archive, most\n       commonly found on  MS-DOS  systems.   Such  information  includes  file\n       access permissions, encryption status, type of compression, version and\n       operating system or file system of compressing program, and  the  like.\n       The  default  behavior (with no options) is to list single-line entries\n       for each file in the archive, with header and trailer  lines  providing\n       summary  information  for  the  entire  archive.  The format is a cross\n       between Unix ``ls -l'' and ``unzip -v'' output.  See DETAILED  DESCRIP-\n       TION  below.   Note  that  zipinfo  is the same program as unzip (under\n       Unix, a link to it); on some systems, however, zipinfo support may have\n       been omitted when unzip was compiled.\n\nARGUMENTS\n       file[.zip]\n              Path  of  the  ZIP  archive(s).   If the file specification is a\n              wildcard, each matching file is processed in an order determined\n              by the operating system (or file system).  Only the filename can\n              be a wildcard; the path itself cannot.  Wildcard expressions are\n              similar to Unix egrep(1) (regular) expressions and may contain:\n\n              *      matches a sequence of 0 or more characters\n\n              ?      matches exactly 1 character\n\n              [...]  matches  any  single character found inside the brackets;\n                     ranges are specified by a beginning character, a  hyphen,\n                     and  an  ending  character.  If an exclamation point or a\n                     caret (`!' or `^') follows the  left  bracket,  then  the\n                     range  of  characters within the brackets is complemented\n                     (that is,  anything  except  the  characters  inside  the\n                     brackets  is  considered a match).  To specify a verbatim\n                     left bracket, the three-character sequence ``[[]'' has to\n                     be used.\n\n              (Be  sure  to quote any character that might otherwise be inter-\n              preted or modified by the operating system,  particularly  under\n              Unix  and  VMS.)   If no matches are found, the specification is\n              assumed to be a literal filename; and if that  also  fails,  the\n              suffix  .zip  is  appended.  Note that self-extracting ZIP files\n              are supported, as with any other ZIP archive; just  specify  the\n              .exe suffix (if any) explicitly.\n\n       [file(s)]\n              An  optional  list of archive members to be processed, separated\n              by spaces.  (VMS versions  compiled  with  VMSCLI  defined  must\n              delimit  files with commas instead.)  Regular expressions (wild-\n              cards) may be used to match multiple members; see above.  Again,\n              be sure to quote expressions that would otherwise be expanded or\n              modified by the operating system.\n\n       [-x xfile(s)]\n              An optional list of archive members to be excluded from process-\n              ing.\n\nOPTIONS\n       -1     list  filenames  only,  one  per line.  This option excludes all\n              others;  headers,  trailers  and  zipfile  comments  are   never\n              printed.  It is intended for use in Unix shell scripts.\n\n       -2     list  filenames  only,  one  per  line,  but allow headers (-h),\n              trailers (-t) and zipfile comments (-z), as well.   This  option\n              may  be  useful in cases where the stored filenames are particu-\n              larly long.\n\n       -s     list zipfile info in short Unix ``ls -l'' format.  This  is  the\n              default behavior; see below.\n\n       -m     list zipfile info in medium Unix ``ls -l'' format.  Identical to\n              the -s output, except that the compression factor, expressed  as\n              a percentage, is also listed.\n\n       -l     list  zipfile  info  in  long Unix ``ls -l'' format.  As with -m\n              except that the compressed size (in bytes) is printed instead of\n              the compression ratio.\n\n       -v     list zipfile information in verbose, multi-page format.\n\n       -h     list  header line.  The archive name, actual size (in bytes) and\n              total number of files is printed.\n\n       -M     pipe all output through an internal pager similar  to  the  Unix\n              more(1)  command.   At the end of a screenful of output, zipinfo\n              pauses with a ``--More--'' prompt; the  next  screenful  may  be\n              viewed  by  pressing  the  Enter  (Return) key or the space bar.\n              zipinfo can be terminated by pressing the ``q'' key and, on some\n              systems, the Enter/Return key.  Unlike Unix more(1), there is no\n              forward-searching or editing capability.  Also, zipinfo  doesn't\n              notice if long lines wrap at the edge of the screen, effectively\n              resulting in the printing of two or more lines and  the  likeli-\n              hood that some text will scroll off the top of the screen before\n              being viewed.  On some systems the number of available lines  on\n              the  screen  is  not detected, in which case zipinfo assumes the\n              height is 24 lines.\n\n       -t     list totals for files listed or for all files.   The  number  of\n              files  listed,  their  uncompressed and compressed total sizes ,\n              and their overall compression factor is printed; or, if only the\n              totals  line is being printed, the values for the entire archive\n              are given.  The compressed total size does not  include  the  12\n              additional  header  bytes of each encrypted entry. Note that the\n              total compressed (data) size will never match the actual zipfile\n              size,  since  the  latter  includes  all of the internal zipfile\n              headers in addition to the compressed data.\n\n       -T     print the file dates and times  in  a  sortable  decimal  format\n              (yymmdd.hhmmss).   The  default  date format is a more standard,\n              human-readable version with abbreviated month names  (see  exam-\n              ples below).\n\n       -U     [UNICODE_SUPPORT  only]  modify or disable UTF-8 handling.  When\n              UNICODE_SUPPORT is available, the  option  -U  forces  unzip  to\n              escape  all  non-ASCII  characters from UTF-8 coded filenames as\n              ``#Uxxxx''.  This option is mainly provided for  debugging  pur-\n              pose when the fairly new UTF-8 support is suspected to mangle up\n              extracted filenames.\n\n              The option -UU allows to entirely  disable  the  recognition  of\n              UTF-8  encoded  filenames.   The  handling  of  filename codings\n              within unzip falls back to the behaviour of previous versions.\n\n       -z     include the archive comment (if any) in the listing.\n\nDETAILED DESCRIPTION\n       zipinfo has a number of modes, and its behavior can be rather difficult\n       to  fathom  if  one isn't familiar with Unix ls(1) (or even if one is).\n       The default behavior is to list files in the following format:\n\n  -rw-rws---  1.9 unx    2802 t- defX 11-Aug-91 13:48 perms.2660\n\n       The last three fields are the modification date and time of  the  file,\n       and  its  name.  The case of the filename is respected; thus files that\n       come from MS-DOS PKZIP are always capitalized.  If the file was  zipped\n       with  a  stored  directory  name, that is also displayed as part of the\n       filename.\n\n       The second and third fields indicate that the  file  was  zipped  under\n       Unix  with version 1.9 of zip.  Since it comes from Unix, the file per-\n       missions at the beginning of the line are printed in Unix format.   The\n       uncompressed file-size (2802 in this example) is the fourth field.\n\n       The fifth field consists of two characters, either of which may take on\n       several values.  The first character may be either `t' or `b', indicat-\n       ing  that zip believes the file to be text or binary, respectively; but\n       if the file is encrypted, zipinfo notes this fact by  capitalizing  the\n       character  (`T'  or  `B').   The second character may also take on four\n       values, depending on whether there is an extended local  header  and/or\n       an  ``extra  field''  associated  with  the  file  (fully  explained in\n       PKWare's APPNOTE.TXT,  but  basically  analogous  to  pragmas  in  ANSI\n       C--i.e.,  they  provide a standard way to include non-standard informa-\n       tion in the archive).  If neither  exists,  the  character  will  be  a\n       hyphen  (`-'); if there is an extended local header but no extra field,\n       `l'; if the reverse, `x'; and if both exist, `X'.   Thus  the  file  in\n       this  example is (probably) a text file, is not encrypted, and has nei-\n       ther an extra field nor an extended local header  associated  with  it.\n       The  example below, on the other hand, is an encrypted binary file with\n       an extra field:\n\n  RWD,R,R     0.9 vms     168 Bx shrk  9-Aug-91 19:15 perms.0644\n\n       Extra fields are used for various purposes (see discussion  of  the  -v\n       option  below)  including  the storage of VMS file attributes, which is\n       presumably the case here.  Note that the file attributes are listed  in\n       VMS  format.   Some  other  possibilities for the host operating system\n       (which is actually  a  misnomer--host  file  system  is  more  correct)\n       include  OS/2  or  NT with High Performance File System (HPFS), MS-DOS,\n       OS/2 or NT with File Allocation Table (FAT) file system, and Macintosh.\n       These are denoted as follows:\n\n  -rw-a--     1.0 hpf    5358 Tl i4:3  4-Dec-91 11:33 longfilename.hpfs\n  -r--ahs     1.1 fat    4096 b- i4:2 14-Jul-91 12:58 EA DATA. SF\n  --w-------  1.0 mac   17357 bx i8:2  4-May-92 04:02 unzip.macr\n\n       File  attributes  in  the  first two cases are indicated in a Unix-like\n       format, where the seven subfields indicate whether the file:  (1) is  a\n       directory,  (2) is readable (always true), (3) is writable, (4) is exe-\n       cutable (guessed on the basis of the extension--.exe, .com, .bat,  .cmd\n       and  .btm files are assumed to be so), (5) has its archive bit set, (6)\n       is hidden, and (7) is a system file.  Interpretation of Macintosh  file\n       attributes  is  unreliable because some Macintosh archivers don't store\n       any attributes in the archive.\n\n       Finally, the sixth field indicates the compression method and  possible\n       sub-method  used.  There are six methods known at present:  storing (no\n       compression), reducing, shrinking, imploding,  tokenizing  (never  pub-\n       licly  released), and deflating.  In addition, there are four levels of\n       reducing (1 through 4); four types of imploding (4K or 8K sliding  dic-\n       tionary,  and  2 or 3 Shannon-Fano trees); and four levels of deflating\n       (superfast, fast, normal,  maximum  compression).   zipinfo  represents\n       these  methods  and  their  sub-methods  as follows:  stor; re:1, re:2,\n       etc.; shrk; i4:2, i8:3, etc.; tokn; and defS, defF, defN, and defX.\n\n       The medium and long listings are almost identical to the  short  format\n       except that they add information on the file's compression.  The medium\n       format lists the file's compression factor as a  percentage  indicating\n       the amount of space that has been ``removed'':\n\n  -rw-rws---  1.5 unx    2802 t- 81% defX 11-Aug-91 13:48 perms.2660\n\n       In  this example, the file has been compressed by more than a factor of\n       five; the compressed data are only 19% of the original size.  The  long\n       format gives the compressed file's size in bytes, instead:\n\n  -rw-rws---  1.5 unx    2802 t-     538 defX 11-Aug-91 13:48 perms.2660\n\n       In  contrast to the unzip listings, the compressed size figures in this\n       listing format denote the complete size of compressed  data,  including\n       the 12 extra header bytes in case of encrypted entries.\n\n       Adding the -T option changes the file date and time to decimal format:\n\n  -rw-rws---  1.5 unx    2802 t-     538 defX 910811.134804 perms.2660\n\n       Note  that  because  of  limitations in the MS-DOS format used to store\n       file times, the seconds field is always rounded  to  the  nearest  even\n       second.   For  Unix  files this is expected to change in the next major\n       releases of zip(1L) and unzip.\n\n       In addition to individual file information, a default  zipfile  listing\n       also includes header and trailer lines:\n\n  Archive:  OS2.zip   5453 bytes   5 files\n  ,,rw,       1.0 hpf     730 b- i4:3 26-Jun-92 23:40 Contents\n  ,,rw,       1.0 hpf    3710 b- i4:3 26-Jun-92 23:33 makefile.os2\n  ,,rw,       1.0 hpf    8753 b- i8:3 26-Jun-92 15:29 os2unzip.c\n  ,,rw,       1.0 hpf      98 b- stor 21-Aug-91 15:34 unzip.def\n  ,,rw,       1.0 hpf      95 b- stor 21-Aug-91 17:51 zipinfo.def\n  5 files, 13386 bytes uncompressed, 4951 bytes compressed:  63.0%\n\n       The  header line gives the name of the archive, its total size, and the\n       total number of files; the trailer gives the number  of  files  listed,\n       their  total  uncompressed  size,  and their total compressed size (not\n       including any of zip's internal overhead).  If, however,  one  or  more\n       file(s)  are  provided,  the  header  and trailer lines are not listed.\n       This behavior is also similar to that of Unix's ``ls -l'';  it  may  be\n       overridden  by  specifying the -h and -t options explicitly.  In such a\n       case the listing format must also be specified explicitly, since -h  or\n       -t  (or  both)  in  the  absence of other options implies that ONLY the\n       header or trailer line (or both) is listed.  See the  EXAMPLES  section\n       below for a semi-intelligible translation of this nonsense.\n\n       The  verbose  listing  is  mostly self-explanatory.  It also lists file\n       comments and the zipfile comment, if any, and the type  and  number  of\n       bytes  in  any  stored  extra  fields.   Currently known types of extra\n       fields include PKWARE's authentication  (``AV'')  info;  OS/2  extended\n       attributes;  VMS  filesystem  info,  both PKWARE and Info-ZIP versions;\n       Macintosh resource forks; Acorn/Archimedes SparkFS  info;  and  so  on.\n       (Note  that  in  the case of OS/2 extended attributes--perhaps the most\n       common use of zipfile extra fields--the  size  of  the  stored  EAs  as\n       reported  by  zipinfo may not match the number given by OS/2's dir com-\n       mand: OS/2 always reports the number of bytes required in  16-bit  for-\n       mat, whereas zipinfo always reports the 32-bit storage.)\n\n       Again,  the  compressed  size figures of the individual entries include\n       the 12 extra header bytes for  encrypted  entries.   In  contrast,  the\n       archive  total  compressed size and the average compression ratio shown\n       in the summary bottom line are calculated without the extra  12  header\n       bytes of encrypted entries.\n\nENVIRONMENT OPTIONS\n       Modifying  zipinfo's default behavior via options placed in an environ-\n       ment variable can be a bit complicated to  explain,  due  to  zipinfo's\n       attempts  to  handle  various  defaults in an intuitive, yet Unix-like,\n       manner.  (Try not to laugh.)  Nevertheless, there  is  some  underlying\n       logic.   In brief, there are three ``priority levels'' of options:  the\n       default options; environment options, which can override or add to  the\n       defaults; and explicit options given by the user, which can override or\n       add to either of the above.\n\n       The default listing format, as noted above, corresponds roughly to  the\n       \"zipinfo  -hst\"  command  (except  when  individual zipfile members are\n       specified).  A user who prefers the long-listing format (-l)  can  make\n       use of the zipinfo's environment variable to change this default:\n\n       Unix Bourne shell:\n              ZIPINFO=-l; export ZIPINFO\n\n       Unix C shell:\n              setenv ZIPINFO -l\n\n       OS/2 or MS-DOS:\n              set ZIPINFO=-l\n\n       VMS (quotes for lowercase):\n              define ZIPINFO_OPTS \"-l\"\n\n       If,  in addition, the user dislikes the trailer line, zipinfo's concept\n       of ``negative options'' may be used to override the  default  inclusion\n       of  the  line.   This is accomplished by preceding the undesired option\n       with one or more minuses:  e.g., ``-l-t'' or ``--tl'', in this example.\n       The  first  hyphen  is the regular switch character, but the one before\n       the `t' is a minus sign.  The dual use of hyphens  may  seem  a  little\n       awkward,  but it's reasonably intuitive nonetheless:  simply ignore the\n       first hyphen and go from there.  It is also consistent with the  behav-\n       ior of the Unix command nice(1).\n\n       As suggested above, the default variable names are ZIPINFO_OPTS for VMS\n       (where the symbol used to install zipinfo as a  foreign  command  would\n       otherwise  be  confused with the environment variable), and ZIPINFO for\n       all other operating systems.  For compatibility  with  zip(1L),  ZIPIN-\n       FOOPT is also accepted (don't ask).  If both ZIPINFO and ZIPINFOOPT are\n       defined, however, ZIPINFO takes precedence.  unzip's diagnostic  option\n       (-v  with  no zipfile name) can be used to check the values of all four\n       possible unzip and zipinfo environment variables.\n\nEXAMPLES\n       To get a basic, short-format listing of the complete contents of a  ZIP\n       archive  storage.zip,  with  both header and totals lines, use only the\n       archive name as an argument to zipinfo:\n\n           zipinfo storage\n\n       To produce a basic, long-format listing (not verbose), including header\n       and totals lines, use -l:\n\n           zipinfo -l storage\n\n       To  list the complete contents of the archive without header and totals\n       lines, either negate the -h and -t options or else specify the contents\n       explicitly:\n\n           zipinfo --h-t storage\n           zipinfo storage \\*\n\n       (where  the  backslash  is  required  only if the shell would otherwise\n       expand the `*' wildcard, as in Unix when globbing is turned  on--double\n       quotes around the asterisk would have worked as well).  To turn off the\n       totals line by default,  use  the  environment  variable  (C  shell  is\n       assumed here):\n\n           setenv ZIPINFO --t\n           zipinfo storage\n\n       To get the full, short-format listing of the first example again, given\n       that the environment variable is set as in the previous example, it  is\n       necessary  to  specify the -s option explicitly, since the -t option by\n       itself implies that ONLY the footer line is to be printed:\n\n           setenv ZIPINFO --t\n           zipinfo -t storage            [only totals line]\n           zipinfo -st storage           [full listing]\n\n       The -s option, like -m and -l, includes headers and footers by default,\n       unless  otherwise  specified.  Since the environment variable specified\n       no footers and that has a higher precedence than the  default  behavior\n       of -s, an explicit -t option was necessary to produce the full listing.\n       Nothing was indicated about the header, however, so the -s  option  was\n       sufficient.   Note  that both the -h and -t options, when used by them-\n       selves or with each other,  override  any  default  listing  of  member\n       files;  only  the  header  and/or footer are printed.  This behavior is\n       useful when zipinfo is used with a wildcard zipfile specification;  the\n       contents of all zipfiles are then summarized with a single command.\n\n       To list information on a single file within the archive, in medium for-\n       mat, specify the filename explicitly:\n\n           zipinfo -m storage unshrink.c\n\n       The specification of any member file, as in this example, will override\n       the  default  header and totals lines; only the single line of informa-\n       tion about the requested file will be  printed.   This  is  intuitively\n       what  one would expect when requesting information about a single file.\n       For multiple files, it is often useful to know the total compressed and\n       uncompressed size; in such cases -t may be specified explicitly:\n\n           zipinfo -mt storage \"*.[ch]\" Mak\\*\n\n       To  get  maximal  information  about  the  ZIP archive, use the verbose\n       option.  It is usually wise to pipe the output into a  filter  such  as\n       Unix more(1) if the operating system allows it:\n\n           zipinfo -v storage | more\n\n       Finally,  to  see  the most recently modified files in the archive, use\n       the -T option in conjunction with an external sorting utility  such  as\n       Unix sort(1) (and sed(1) as well, in this example):\n\n           zipinfo -T storage | sort -nr -k 7 | sed 15q\n\n       The -nr option to sort(1) tells it to sort numerically in reverse order\n       rather than in textual order, and the -k 7 option tells it to  sort  on\n       the  seventh  field.  This assumes the default short-listing format; if\n       -m or -l is used, the proper sort(1) option would be -k 8.  Older  ver-\n       sions  of  sort(1)  do  not  support the -k option, but you can use the\n       traditional + option instead, e.g., +6 instead  of  -k 7.   The  sed(1)\n       command  filters out all but the first 15 lines of the listing.  Future\n       releases of zipinfo may incorporate date/time and filename  sorting  as\n       built-in options.\n\nTIPS\n       The  author  finds  it  convenient to define an alias ii for zipinfo on\n       systems that allow aliases (or, on other systems, copy/rename the  exe-\n       cutable, create a link or create a command file with the name ii).  The\n       ii usage parallels the common ll alias for long listings in  Unix,  and\n       the similarity between the outputs of the two commands was intentional.\n\nBUGS\n       As with unzip, zipinfo's -M (``more'') option is overly  simplistic  in\n       its  handling  of screen output; as noted above, it fails to detect the\n       wrapping of long lines and may thereby cause lines at the  top  of  the\n       screen to be scrolled off before being read.  zipinfo should detect and\n       treat each occurrence of line-wrap  as  one  additional  line  printed.\n       This  requires  knowledge  of the screen's width as well as its height.\n       In addition, zipinfo should detect the true screen geometry on all sys-\n       tems.\n\n       zipinfo's  listing-format  behavior is unnecessarily complex and should\n       be simplified.  (This is not to say that it will be.)\n\nSEE ALSO\n       ls(1), funzip(1L), unzip(1L), unzipsfx(1L), zip(1L), zipcloak(1L), zip-\n       note(1L), zipsplit(1L)\n\nURL\n       The Info-ZIP home page is currently at\n           http://www.info-zip.org/pub/infozip/\n       or\n           ftp://ftp.info-zip.org/pub/infozip/ .\n\nAUTHOR\n       Greg  ``Cave Newt'' Roelofs.  ZipInfo contains pattern-matching code by\n       Mark Adler and fixes/improvements by many others.  Please refer to  the\n       CONTRIBS  file  in  the  UnZip  source distribution for a more complete\n       list.\n\nInfo-ZIP                     20 April 2009 (v3.0)                  ZIPINFO(1L)\n"
  },
  {
    "path": "deps/infozip/zip30/BUGS",
    "content": "- zip sometimes crashes on some versions of NetBSD (0.8, 0.9 and early\n  0.9-current), FreeBSD (<= 1.1) and BSDI (< 1.1) . This is due to a\n  bug in stdio.\n  Upgrading the stdio package in /usr/src/lib/libc/stdio should\n  fix the problem. See *BSD mirrors in src/lib/libc/stdio\n  You must at least replace setvbuf.o in all the libc's with a newer version.\n"
  },
  {
    "path": "deps/infozip/zip30/Betas_Readme.txt",
    "content": "Betas are works in progress.  When a beta has a seemingly stable set\nof features, we may post a public beta so outside developers can see\nwhere the code is going and make contributions or comment.\n\nA Release Candidate is a beta that we believe has the full feature\nset that will be released.  It's still being tested, and things can\nstill change, but we thought it close when we posted it.\n\nWe take suggestions, bug fixes, and patches at any time, so send them in.\n\nWe make no guarantees as to the state of betas so use at your own risk.\nAll code, including releases, are released under the Info-ZIP license.\n\nEnjoy!\n\nEd Gordon\n20 April 2008\n"
  },
  {
    "path": "deps/infozip/zip30/CHANGES",
    "content": "------------------------- August 7th 1996 version 2.2a ------------------\n 1. QDOS port (Jonathan Hudson)\n 2. win32 volumelabel handling (Paul)\n 3. VM/CMS clean up (Greg Hartwig)\n 4. leading \"../\" in internal filenames are allowed (Paul)\n 5. System V packages support (John Bush)\n 6. Fix handling of atx in zipup() (Onno, Greg)\n 7. Fixed typo that caused zip -R to dump core (Onno)\n 8. msdos/makefile.dj2: fix for command line too long when linking zip.exe\n 9. win95 long filename support with djgpp v2 (Onno, Kimio Itoh)\n------------------------- August 9th 1996 version 2.2b ------------------\n 1. windll: use wiz instead of wizip (Mike)\n 2. use z->name NOT z->zname to open files (Onno, Mike)\n------------------------ September 1st 1996 version 2.2c ------------------\n 1. windll: use fprintf instead of putc to send data to std{out,err} (Mike)\n 2. os2: make borlandc version detection equal to unzip 5.30d (Kai Uwe)\n 3. use #elif constructions for msdos,os2 and win32 compiler detection (Onno)\n 4. fix for incorrect free in zip.c (Onno, Mike, Steve)\n 5. BeBox port from Chris\n 6. unix/{configure,Makefile} fixes for SCO Xenix 286 (Tom Schmidt)\n 7. remove zilog entry from unix/Makefile (Onno)\n 8. man page fixes (Tom Schmidt)\n 9. SCO ODT {3,5} fixes (Bill Davidsen)\n------------------------ October 8th 1996 version 2.2d ------------------\n 1. Fix bug in QDOS patch that broke zipsplit.c (Onno, Paul)\n 2. Fix a couple of warnings from BorlandC (Mike)\n 3. msdos/makefile.wat: Delete some more files when cleaning up (Paul)\n 4. store msdos volumelabels without a dot in them (Paul)\n 5. clean up of unix/{Makefile,configure,packaging} (Tom Schmidt)\n 6. make QDOS port case independent (Jonathan Hudson)\n 7. new amiga SASC makefile (Walter Haidinger)\n 8. don't truncate filenames in win32's in2ex() (Paul)\n 9. os2/makefile.os2 update for emx 0.9c (Kai Uwe)\n10. password() function for QDOS (Jonathan)\n11. fix the last(?) free() related bug (Mike)\n12. win32: security descriptors operations (Scott Field)\n13. win32: FILE_SHARE_DELETE is not defined in some win32 compilers (Onno)\n14. win32: fix makefile.wat to include nt.c (Onno)\n------------------------ January 17th 1997 version 2.2e ------------------\n 1. define USE_CASE_MAP in osdep.h for those ports that need it (Onno)\n 2. define PROCNAME in osdep.h for those ports that need it (Onno)\n 3. wild() prototype decl only if PROCNAME defined => delete MSVMS define (Onno)\n 4. add DOS EMX makefile (E-Yen Tan)\n 5. include <qdos.h> a little earlier in qdos/qdos.c (Jonathan)\n 6. add ttyio.o to OBJZ in qdos/Makefile.qdos (Jonathan)\n 7. remove unused fprintebc define from zip.c (Onno)\n 8. use the right password routine in ttyio.c for unzip (Mike)\n 9. BeOS update from Chris\n10. Fix for 'zip -r foo x:' (Paul)\n11. Fix library bug on beos (Chris)\n12. Fix calculating version number (kitoh_@mix.or.jp, Walter Haidinger)\n13. IsWinNT always returned TRUE (Mike)\n14. Windll update from Mike\n15. Improved crc routines for x86 from Scott Field\n16. Detect in unix/configure if we can use crc_i386.S (Onno)\n17. Fix spurious internal logic error (Paul)\n18. Fix to include directory names on the Acorn when needed (Sergio)\n19. include zip.h in mvs.h (Onno, George Carr)\n20. add workaround for AZTEC C compiler bug to revision.h (Paul, Walter)\n21. MVS doesn't have rmdir (George Carr)\n22. define and use USE_ZIPMAIN for WINDLL en VM_CMS (Onno)\n23. Fixes from Greg Hartwig to make CMS standalone versions possible.\n24. Move OS specific encryption stuff to the os specific directories (Christian)\n25. Change password fetching interface in ttyio and crypt (Christian)\n26. Update emx support for 0.9c (Christian)\n27. Define WINDLL instead of MSWIN (Christian)\n28. Extended time stamp extra field format support (Christian)\n29. Support for rsxnt-emx 0.9c win32 compiler (Christian)\n30. Use izshr017b (Christian)\n------------------------ March 11th 1997 version 2.2f ------------------\n 1. Move makefile.emx, rsxwinnt.h and zip.def to win32 subdir (Kai Uwe)\n 2. Add win32 target to makefile.os2 to allow cross compilation (Kai Uwe)\n 3. Fix NTSD_EAS link time failures with win32 (Paul)\n 4. Fix buffer freed too early in password verification code (Mike)\n 5. Remove unix/zipgrep and man/zipgrep.1 (sanvila@ctv.es)\n 6. Only use crc_i386.o when we're using an x86 (Onno, Mark)\n 7. Remove carriage returns from amiga/crc_68.a (Paul)\n 8. New windll from Mike\n 9. Fix typo in os2/os2zip.c (Kai Uwe)\n10. Don't use ctime (last file status change) for unix and qdos cross compile\n    (Greg)\n11. added gccwin32 crosscompilation target (RSXNT) to os2/makefile.os2 (Kai Uwe)\n12. fixed the OS/2 file attribute and time stamp generation for zipping\n    stdin (\"-\") (Kai Uwe)\n13. fixed the atime and ctime stat fields for the OS/2 Watcom C library\n    (Kai Uwe)\n14. added atime and ctime support for the UT extra field when generated under\n    OS/2, the atime and ctime values are only stored when zipping (Kai Uwe)\n15. qdos patches from Jonathan Hudson mainly for extended time flag handling\n16. amiga aztec compiler bug workaround (Paul)\n17. fix -v output of zipcloak, zipnote and zipsplit (Paul)\n18. new amiga/makefile.azt with targets for debug versions (Paul)\n------------------------ March 31st 1997 version 2.2g ------------------\n 1. remove -I/usr/local/include from unix/Makefile (Chris)\n 2. Update versinfolines in revision.h (Greg)\n 3. change 1U to 0x1 to accomodate non ANSI compilers (Onno, Rodney Brown)\n 4. win32zip.c: cast buffer parameter in memcompress() to char * (Mike)\n 5. remove beos/zipgrep (Chris)\n 6. correct the -e password verification check in zip.c (Christian)\n 7. use ZCONST instead of const in the generic code. (Christian)\n 8. fix mktime timezone correction when time is near to daylight/nodaylight\n    switch points. (Christian)\n 9. correct dependencies in makefile.os2 (Christian)\n10. use a more sensible default for iztime.ctime than \"0\" when system does not\n    not support creation time stamps. (Christian)\n11. fix VMS_PK_EXTRA function interface declarations. (Christian)\n12. implement atime/ctime support in win32. (Christian)\n13. win32/win32.c: replacement getch() for Watcom. (Paul)\n14. win32/makefile.wat: debug object files kept separate. (Paul)\n15. msdos/makefile.wat: debug object files kept separate. (Paul)\n16. Fix extended time defines for the acorn. (Sergio)\n17. Define PROCNAME() in acorn/osdep.h (Sergio)\n18. Ignore exit status of ${INSTALL_D} in unix/Makefile (Chris)\n19. Add Metroworks and BEOS info to version() in several files (Chris)\n20. Move defines for the password fetch to zip.h (Christian)\n21. Support the obsolete version rsxnt 1.1 / emx 0.9b (Christian)\n22. Remove obsolete \"#define PROCNAME ...\" from cmsmvs/cmsmvs.h (Christian)\n23. Fix extended time defines for qdos (Jonathan Hudson)\n24. Use watcom getch() from unz530q in win32/win32.c (Onno)\n25. Don't install zipgrep via the unix package tools (John Bush)\n26. use izshr021 (Onno)\n27. Fix zipnote: use iname not zname in zipnote.c (Onno)\n28. Create proginfo directory (Christian)\n------------------------ May 5th 1997 version 2.2h --------------------\n 1. Fix vms/zipup.h: iztime --> iztimes  (Onno, Mike Freeman)\n 2. Remove windll/wizdll.def (Mike)\n 3. Add a couple of external variable declaration to windll.h (Mike)\n 4. Remove zipgrep from install in unix/Makefile (Onno)\n 5. Make updating .zip files with extended time fields possible (Kai Uwe)\n 6. Delete beos/Makefile.gcc, beos/Makefiles handles both compilers (Chris)\n 7. Fixes for unused variables (Chris)\n 8. Added very simplistic example how to load and call the windll (Mike)\n 9. Updated windll documentation to note this example (Mike)\n10. Removed an unused memeber of a structure in windll (Mike)\n11. Add BUGS instead of infozip.who and algorith.doc with the packaging\n    tools (John Bush)\n12. tailor.h: increment NUM_HOSTS to keep in sync with UnZip (Christian)\n13. win32/osdep.h: remove NO_SECURE_TESTS define (Christian)\n14. zip.h: add declaration for free_crc_table() (Christian)\n15. windll: move everything that's not windows specific into api.* (Mike)\n16. use iname when checking for directory names in zipfile.c (Sergio)\n17. improved mktime.c with better error checking (Christian)\n18. improved crc routines (Christian, Rodney Brown)\n19. get the -z option working again (Onno, Brad Clarke)\n20. define BROKEN_FSEEK and seekable() for those systems where fseek()\n    always returns 0 (== OK) (Onno, Jeffrey Altman)\n------------------------ May 10th 1997 version 2.2i --------------------\n 1. win32's seekable should only check for FILE_TYPE_DISK (Onno, Jeffrey Altman)\n 2. add (ulg) cast to zipbeg = ~0 in zipfile.c (Steve)\n 3. seekable() *really* belongs in flush_block, keep it there (Onno)\n 4. seekable() calls fseekable(FILE *) (Onno)\n 5. define HAVE_FSEEKABLE if a port has their own fseekable (Onno)\n 6. WatCom doesn't have _get_osfhandle, use _os_handle instead (Paul)\n 7. upgrade to Mike's latest windll sources (Mike)\n 8. add -P option so you can specify a password on the commandline (Onno)\n 9. Get -@ working again (Onno)\n10. emx+RSXNT doesn't know about _get_osfhandle() (Kai Uwe)\n11. fix a couple of typos in the OS/2 makefiles (Kai Uwe)\n12. fix initialization bug in windll code (Mike)\n13. tweak deletedir for RISC OS (Sergio)\n14. RISCOS doesn't know about fstat() (Sergio)\n15. Remove acorn/acorn (Sergio)\n16. Delete debugging statements from version_local() in msdos.c (Greg)\n17. Fix huge bug in readzipfile() (Onno)\n------------------------ May 18th 1997 version 2.2j --------------------\n 1. Add missing ';' after return ZE_PARMS in zip.c (Mike)\n 2. Remove obsolete 'struct stat st' in zipfile.c (Onno)\n 3. Get Amiga SFX handling working again (Paul)\n 4. Get zip -A working again (Onno)\n 5. Change an && to & in zipfile.c (Johnny)\n 6. Fix handling of empty sfx archives (Onno, Mike)\n 7. Remove experimental entries from the makefiles (Jean-loup)\n 8. Add exit codes to the manual page (Onno)\n 9. Remove lines from the help screen that contain lesser used options (Onno)\n------------------------ June 8th 1997 version 2.2k --------------------\n 1. use zip -t ddmmyyyy for year 2000 stuff (Greg)\n 2. zip -@ only handles ONE filename per line (Jean-loup)\n 3. beos support for DR9 filesystem and symlinks (Chris)\n 4. VB support for windll (Mike)\n------------------------ June 10th 1997 version 2.2l -------------------\n 1. beos filetype support (Chris)\n 2. fill the buffer in getnam() to get it working again (Onno)\n 3. implement -x@filename and -i@filename (Onno)\n------------------------ June 22nd 1997 version 2.2m -------------------\n 1. Add a ; after de nextarg label in main() (Onno, Erik Baatz)\n 2. Initialize p to NULL in get_filters() (Onno, Frank Donahoe)\n 3. Fix typo in first if statement in filetypes() (Johnny Lee)\n 4. zip -A works again (Onno, Greg)\n 5. don't free zipbuf for VMS and CMS_MVS in main() (Onno, Mike Freeman)\n 6. fix make_zip.com, link_zip.com and vmsdefs.h for gcc 2.6.3 on VMS (Onno)\n 7. clarify -g option in the man page (Jean-loup)\n------------------------ July 6th 1997 version 2.2n -------------------\n 1. use local in readzipfile2() declaration (Onno, Mike Freeman)\n 2. return values with windll in get_filters() (Mike)\n 3. a couple of minor patches for BEOS (Chris)\n 4. zip -g works again (Onno, Chris)\n 5. Some more Visual Basic dll support (Mike)\n 6. Fix stack overflow in readzipfile() for DOS (Onno, Michael Mauch)\n------------------------ August 19th 1997 version 2.2o -------------------\n 1. beos README and Makefile tweaks from Chris.\n 2. Syntax corrections for README and man/zip.1  (Frank Donahoe)\n 3. Use name not iname when deleting directories in trash() (Christian)\n 4. change several wkuvx1 to lists in e-mail addresses (Christian)\n 5. default to PK style extra fields for VMS (Christian)\n 6. use izshr023 (Christian)\n 7. replace buggy time library functions (Walter Haidinger, Paul, Christian)\n 8. in2ex() and stat() are needed also when UTIL isn't defined (Greg Hartwig)\n 9. don't use type=record in fopen() for MVS and CMS (Greg Hartwig)\n10. Change P and K literals to hex for EBCDIC systems (Greg Hartwig)\n11. Add output path support for CMS and MVS (Greg Hartwig)\n12. Add memtoasc and memtoebc for EBCDIC systems (Greg Hartwig)\n13. Handle comments correctly to fix zipnote for CMS and MVS (Greg Hartwig)\n14. Add -tt option (do not operate on files after date mmddyy) (Christian)\n15. move alloc routines for DOS into the !UTIL block (Christian)\n16. move UTIL blocks and version_local() functions to a more logical place\n    (Christian)\n17. Handle -P, -R, -x@, -i@ and -tt for the VMS CLI (Christian)\n18. Update VMS help file with the new options (Christian)\n19. Use iname in MATCH, not zname (Jonathan Hudson)\n20. windll: more Visual Basic support (Mike)\n21. windll: more project makefiles (Mike)\n22. windll: insert Zip in front of global variable names (Mike)\n------------------------ August 25th 1997 version 2.2p -------------------\n 1. Remove unused flags from LFLAGS2 in unix/Makefile (Onno)\n 2. SunOS make bug: change unix_.o rule in unix/Makefile (Onno, Mike Freeman)\n 3. ZipIsWinNT() instead of IsWinNT() in zip.h (Mike)\n 4. Fix -t and -tt behaviour for windll (Mike)\n 5. Remove windll makefiles that are now elsewhere (Mike)\n 6. BEOS: preserve file attributes associated with symbolic links (Chris)\n 7. No need to use in2ex() for ziputils (Christian)\n 8. Fix comment handling for EBCDIC systems (Christian)\n 9. EBCDIC conversion for entry names read from zipfile in UTIL mode (Christian)\n10. Fix \"fatal\" error messages on EBCDIC systems (Christian)\n11. zipnote.c: Fix handling of entry name changes for EBCDIC systems (Christian)\n12. removed a large part of \"dead\" code from ziputils version (Christian)\n13. use z->iname in comparison functions for sorting (Christian)\n14. new installation utils for the acorn (Sergio)\n15. use LSSTAT in set_extra_field for unix and beos (Onno)\n16. perror(z->zname) instead of perror(\"zip warning\") (Onno, Geoff Pennington)\n17. Amiga SFX should work again (Paul)\n18. refer to zip22 in install.doc (Frank Donahoe)\n------------------------ September 10th 1997 version 2.2q -------------------\n 1. Change .doc to .txt, these aren't MS-Word documents (John D. Mitchell)\n 2. Change msdos$_(OBJ) to msdos_$(OBJ) (Kai Uwe)\n 3. Fix a couple of amiga related glitches (Paul)\n 4. Support for DOS packed .exe files in makefile.dj2 (Frank Donahoe)\n 5. Change warning message for zip -A (Greg)\n------------------------ September 29th 1997 version 2.2r -------------------\n 1. Fix make svr4package (Eric Baatz)\n 2. Fix VMS warning (Mike Freeman, Christian)\n 3. Clean up beos gcc port and beos README (Chris)\n-------------------------- October 6th 1997 version 2.2s --------------------\n 1. Change lpPrint to lpZipPrint for windll (Mike)\n 2. Change lpPassword to lpZipPassword for windll (Mike)\n 3. Amiga timezone fixes (Paul)\n 4. WatCom C 11.0 makefile fixes (Paul)\n 5. Tandem port from Dave Smith\n 6. Corrections and updates for install.txt (Christian)\n 7. Minor VMS README update (Christian)\n-------------------------- October 12th 1997 version 2.2t --------------------\n 1. qdos compiler bug workaround (Jonathan)\n 2. prevent storing qdos specific filenames that exceed filesystem limits\n    (Jonathan)\n 3. fix undelimited comment in fileio.c (Frank Donahoe)\n 4. disable storing of symlinks in BEOS until OS support is available (Chris)\n 5. Init hash_head to 0 in amiga/deflate.a (Paul)\n 6. Upgrade to izshr025 (Christian)\n 7. don't add \".zip\" to ZIP name for TANDEM (Dave Smith)\n 8. use zipup.h not tandem.h in zipup.c (Dave Smith)\n 9. rename history to CHANGES (Onno)\n10. rename install.txt to INSTALL (Onno)\n11. rename zip.txt to ZIPMAN (Onno)\n12. create WHATSNEW (Onno)\n-------------------------- October 15th 1997 version 2.2u --------------------\n 1. Use Info-ZIP instead of Info-Zip (Christian)\n 2. Note recent filename changes in several files (Christian)\n 3. Remove a couple of items from the TODO list (Christian, Onno)\n 4. Add windll port, zip -t yyyymmdd and zip -R to WHATSNEW (Christian)\n 5. VMS documentation cleanups and clarifications (Christian)\n 6. dist entry in unix/Makefile (Onno)\n 7. remove duplicate amiga/timezone.txt (Christian)\n 8. rename ZIPMAN to MANUAL and update a couple of files regarding this (Onno)\n-------------------------- October 24th 1997 version 2.2v --------------------\n 1. izshr026: in WHERE wiz40 instead of wiz30 (Christian)\n 2. izshr026: another couple of Info-ZIP spelling fixes (Christian)\n 3. Remove zipgrep from the makefiles that still had it (Christian)\n 4. Update makefiles to handle the MANUAL renaming change (Christian)\n 5. Fix the last daylight savings bug on the Amiga (Paul)\n 6. Fix the SCO Unix specialty detection in unix/configure (Onno,\n    bug reported by Bo Kullmar for Solaris 2.6 and with uname -X output\n    for SCO Unix from ken@apisys.com and dgsmith@vnet.ibm.com)\n 7. Update WHERE and amiga/time_lib.c from unzip 5.32g (Greg)\n-------------------------- October 26th 1997 version 2.2w --------------------\n 1. Additional +Onolimit check in unix/configure (Onno, Peter Jones)\n 2. Use ZIPERR macro instead of ziperr (Christian)\n 3. initialize z->lflg for zip entries without extra field (Christian)\n 4. \"local (+ locextend)\" vs. \"central\" header consistency check (Christian)\n 5. Override local header values with central header values with -A\n    and differences between these headers (Christain)\n 6. made \"deltaoff\" signed long; offset adjustment may be negative (Christian)\n 7. fix a number of \"wild\" deallocation bugs (Christian)\n 8. When zipping from a FAT drive (only 8.3 DOS names) under OS/2 or\n    WIN32, set z->vem to \"OS_DOS | <real zip version number>\".\n    Mark as \"made by DOS PKZIP 2.0\" only when dosify was requested. (Christian)\n 9. DOS port should not store fake unix style external attributes. (Christian)\n10. amiga/time_lib.c from izshr028 (Christian)\n-------------------------- October 31st 1997 version 2.2y --------------------\n 1. amiga/time_lib.c from izshr029 (Christian)\n 2. Turbo C++ version code clarification (E-Yen Tan)\n 3. Fix spelling in cmsvms/zipname.conven (Rodney Brown)\n 4. Fix memset check in unix/configure for Unixware 2.1.1 (Rodney Brown)\n 5. Forward declaration fixes for HP-UX bundled compiler (Rodney Brown)\n-------------------------- November 3rd 1997 version 2.2 --------------------\n 1. Update WHERE (Greg).\n-------------------------- January 4th 1998 version 2.21a -------------------\n 1. BSD friendly version of version_local() in unix/unix.c (Onno)\n 2. No NT versions in DOS version_local() (Steve Salisbury)\n 3. -t mmddyyyy instead of -t ddmmyyyy in WHATSNEW (Walter Haidinger)\n 4. use generic fseekable() for rsxnt (Christian)\n 5. Fix MSC 8.x warnings (Christian, Steve Salisbury)\n 6. win32 Borland C++ makefile (E-Yen Tan)\n 7. Tandem doesn't know about extensions like .zip,.arj, ... (Dave Smith)\n 8. Use dosmatch for EMX and DJGPP too (Christian)\n 9. dummy djgpp startup functions to remove command line globbing and\n    recognition of environment variables from djgpp.env (Christian)\n10. include DJGPP_MINOR in DOS version_local() (Christian)\n11. TC 2.0 doesn't have mktime() (Christian, mmp@earthling.net)\n12. VMS: rename opendir() to zopendir() so avoiding name clash with\n    VMS 7.x POSIX libraries (Christian, Martin Zinser)\n13. Add support for VMS DEC C V 5.6 features (Christian)\n14. Use iname for comparison in check_dup (Christian Spieler, Christian Michel)\n15. Fix access to uninitialized ioctx records in vms_get_attributes()\n    Christian, Robert Nielsen)\n16. Parenthesis around MAX_MATCH>>1 in match.S (Greg)\n17. Use strchr() not strrchr() for -i and -x to get -i@ and -x@ really\n    working (Onno, Kai Uwe)\n18. add chmod statements to unix/Makefile (Quentin Barnes)\n19. Windll: handle both -r and -R (Mike)\n20. Windll: general error handler in main() via setjmp/longjmp (Mike)\n21. Don't allow zip -i@x.lst foo.zip (Onno)\n22. vms/link_zip.com: use .eqs. not .nes. when checking with f$search\n    for the zip AXP object library (David Dachtera)\n23. rsxnt 1.3.1 fixes (E-Yen Tan)\n-------------------------- January 20th 1998 version 2.21b -------------------\n 1. Bigger PATH_MAX for win32's windll (Mike)\n 2. Update windll.txt w.r.t. PATH_MAX (Mike)\n 3. Amiga SAS/C fixes (Walter, Paul)\n 4. zip -i@ and -x@ should *really* work now ...... (Onno)\n-------------------------- February 20th 1998 version 2.21c -------------------\n 1. make -f unix/Makefile qnx needs LN=ln in its options (Chris)\n 2. Support Metroworks Codewarrior/x86 on BEOS (Chris)\n 3. Add Norbert Pueschel to proginfo/infozip.who (Walter)\n 4. Use big endian for Be types (Chris)\n 5. zip -i and -x were broken by the -i@ fix last time around (Christian)\n 6. win32 stat bandaid (Paul)\n 7. acorn filetype and timestamp fixes (Sergio, D. Krumbholz)\n 8. update to izshr30 (Christian)\n 9. Support for NTSD in the RSXNT environment (Christian)\n10. restructure readzipfile() (Christian)\n11. Where needed define MATCH in osdep.h (Christian)\n12. version_local() fixes for RSXNT (Christian)\n13. New vmsmunch.c (Christian)\n-------------------------- March 15th 1998 version 2.3a -------------------\n 1. Fixes for the windll API (Mike)\n 2. Use CPUTYPE in BorlandC Makefile for DOS (E-Yen Tan)\n 3. BEOS: -rostr not available for the x86 compiler (Chris)\n 4. preserve file attributes of a symlink on BEOS (Chris)\n 5. New VM/CMS README.CMS and version_local() (Ian Gorman)\n 6. INSTALL fixes from Takahiro Watanabe\n 7. OS/390 port from Paul von Behren\n 8. new api.h from Mike\n-------------------------- April 19th 1998 version 2.3b -------------------\n 1. Improve Tandem file I/O performance (Dave Smith)\n 2. New VM/CMS README.CMS and version_local() (Ian Gorman)\n 3. cygwin32 port from Cosmin Truta\n 4. Workaround for tasm32 5.0 bug in win32/crc_i386.asm (Cosmin Truta)\n 5. win32/match32.asm fixes for tasm 5.0 (Cosmin Truta)\n 6. simplify OS/390 port (Christian)\n 7. win32 timezone handling fixes (Christian)\n 8. fix 40-bit time conversion on the acorn (Sergio and Christian)\n 9. strip network part from UNC type filenames (Christian)\n10. Makefile for OpenMVS (Ian Gorman)\n11. Use the Watcom getch() for cygwin32 (Christian)\n12. Borland C++ 5.x added to win32's version_local() (Cosmin Truta)\n13. Borland C++ needs tzset() in win32 (Christian, Cosmin Truta)\n-------------------------- May 21st 1998 version 2.3c -------------------\n 1. Better error messages for -i and -x (Christian)\n 2. Win32 stat() wrapper needs dos2unixtime (Christian,Paul,Mike)\n 3. DJGPP: use _chmod to handle LFN attributes correctly (Michael Mauch)\n 4. Fix Borlandc warnings (Mike)\n 5. win32/makefile.bor fixes from Michael Mauch\n 6. win32/makefile.{dj,emx} fixes from E-Yen Tan\n 7. Use izshr031 (Christian)\n 8. CMS: use RECFM=V LRECL=32760 by adding \"byteseek\" (Greg Hartwig)\n 9. Check external name for trailing \"/\" (Greg Hartwig)\n10. More specific info in CMS version_local() (Greg Hartwig)\n11. Changed usage info to refer to \"fm\" rather than \"path\" on CMS (Greg Hartwig)\n12. No more \"extra data\" messages when using the same OS (Greg Hartwig)\n13. Rewritten README.CMS, one version for ZIP and UNZIP (Greg Hartwig)\n14. DOS/OS2/WIN32/UNIX: ex2in() strips off \"//host/share/\" from UNC names (SPC)\n-------------------------- June 23rd 1998 version 2.3d -------------------\n 1. Fixed Win32's stat() bandaid handling of time stamps (SPC)\n 2. General fix of file selections for DELETE and FRESHEN action (SPC)\n 3. CMS_MVS: Use ASCII coding for TIME extra field ID (SPC)\n 4. EBCDIC: Repaired bogus CMS_MVS fix in zipup.c; check the internal\n    name for trailing (ASCII) '/' to detect directory entries (SPC)\n 5. Use explicit ASCII coding when comparing or setting chars in iname (SPC)\n 6. Fixed win32/makefile.bor, win32/makefile.dj (support NTSD),\n    win32/makefile.emx (SPC)\n 7. Replaced win32/makefile.cyg by win32/makefile.gcc, containing new\n    support for mingw32 GCC environment (SPC)\n 8. Use izshr032 (SPC)\n 9. Modified zipup.c to hold (un)compressed lengths in \"ulg\" variables, in\n    an attempt to support handling of huge (>2GByte) files. (SPC)\n10. Removed some duplicate #defines from api.h, they are now in crypt.h (SPC)\n11. Reenabled \"extra data size\" info messages in noisy mode for all systems\n    except RISCOS and CMS_MVS (SPC)\n12. For EMX 0.9c, the runtime lib contains a working mktime(), use it (SPC)\n13. Miscellanous cosmetic changes (SPC)\n14. Move win32/makefile.emx to msdos (E-Yen Tan)\n15. make api.h work with zcrypt2.8 (Mike)\n16. define ydays differently in api.h to avoid linking problems (Mike)\n17. New windll.txt (Mike)\n18. win32 lcc patches  (E-Yen Tan)\n19. win32 lcc makefile (E-Yen Tan)\n20. Multiple inclusion bug: no malloc.h when using lcc-win32 (E-Yen Tan)\n21. New VB support files for windll (Mike Le Voi, Raymond King)\n22. MacOS port by Dirk Haase\n-------------------------- August 1st 1998 version 2.3e -------------------\n 1. Generalized check for validy of TZ timezone setup info, similar to\n    UnZip; use it on AMIGA and MSDOS, as before. (SPC)\n 2. Apply TZ validy check on OS/2 and enable creation of UT e.f. (SPC)\n 3. BEOS: New Makefile, updates for README and Contents (Chris Herborth)\n 4. beos/beos.c: declare some private functions as \"local\" (SPC)\n 5. Include memcompress() code only for ports that make use of it, controlled\n    by preprocessor symbol ZP_NEED_MEMCOMPR (SPC)\n 6. cmsmvs/README.CMS fix: Zip archive entries to be extracted into var-length\n    records CMS files should >>NOT<< contain binary data ... (SPC)\n 7. crc32.c, crctab.c: the crc polynom table is ZCONST (SPC)\n 8. trees.c: fixed a bug in the deflate algorithm that limited the compressed\n    size of an archive member to 512 MByte (SPC)\n 9. deflate.c: Integrated the changes found in zlib that are neccessary to make\n    the deflate algorithm deterministic; modified msdos/match.asm to take\n    care of the \"nice_match\" global no longer being constant.  (SPC)\n10. deflate.c, trees.c, zipup.c: Reorganized and simplified deflate's\n    compressed output buffer handling. I/O and compression code are now\n    separated more cleanly. (SPC)\n11. Killed bits.c by moving its contents into trees.c resp. zipup.c;\n    synchronized all Makefiles and Make procedures with this change. (SPC)\n12. Integrated support for optionally replacement of deflate and crc32 by\n    public domain zlib code. (SPC)\n13. Synchronize the different variants (UNIX/GNU C, OS/2, WIN32) of i386\n    assembler replacement for deflate's longest_match() (SPC)\n14. Moved the EMX+rsxnt Makefile.emx from msdos/ back into win32/ (SPC)\n15. Restored a separate Makefile.emx for DOS; on DOS, some make programs may\n    have difficulties with recursive invokation (SPC)\n16. Fixed the \"include header mess\" of the new MACOS port and removed the\n    \"work-around hacks\" caused by these bad MACOS .h-file includes (SPC)\n17. Integrated Dirk Haase's beta4 (27-Jun-98) release of MacZIP (Dirk Haase)\n18. Added support for MS Quick C in the MSDOS version_local() report (SPC)\n19. Added WIN32 rsxnt targets linking against the emx crtl DLL to Makefile.emx\n    in os2/ and win32/ (SPC)\n20. Fixed typo in os2/os2.c wild() function. (Kai Uwe Rommel)\n21. Removed ChangeNameForFAT() from os2/os2.c in2ex() to fix problem with\n    long filename support. (Kai Uwe Rommel)\n22. os2/os2zip.[ch]: correct type of DOS-style timestamp data is \"ulg\" (SPC)\n23. vms/cmdline.c: Removed wrong ';' behind if condition (Johnny Lee)\n24. VMS: Preliminary preparations in C code for supporting GNU C on OpenVMS\n    Alpha (Onno van der Linden, Christian Spieler)\n25. VMS: Fixed check against adding zipfile to itself in fileio.c (SPC)\n26. WIN32: Added lcc-Win32 variants of i386 assembler code for crc32() and\n    longest_match(). (SPC)\n27. WIN32: Removed bogus type-cast in assignment to statb st_mode member (SPC)\n28. zip.c: Fixed MACOS-related typo that broke \"-@\" command option (SPC)\n29. zipup.c: Fixed messed-up expression for assignment to z->ver (SPC)\n30. MACOS extra fields: check realloc return values (Onno, Johnny Lee)\n31. Fix the PUTBYTE macro in trees.c: >= instead of < (Onno)\n-------------------------- September 6th 1998 version 2.3f -------------------\n 1. Add zp_tz_is_valid to globals.c (Onno, Frank Donahoe)\n 2. Updated tandem files from Dave Smith\n 3. Windll: allow comments to zip archive with VB (Mike)\n 4. Windll: add support for -b and update the documentation (Mike)\n 5. win32: use wbS for FOPW to handle large zip files better (Steve Miller)\n 6. MVS fix: use fseek();clearerr() instead of rewind() (Onno, Lee Burton)\n 7. Updated VB examples for windll (Mike)\n 8. Tandem: use UTC timestamps and GID/UID in extra field (Dave Smith)\n 9. Tandem: handle -o option (Dave Smith)\n10. default for ZCONST is const in tailor.h, override in osdep.h (Onno)\n11. additional Macintosh options in zip.c (Dirk Haase)\n12. additional Macintosh options in zip.1 and MANUAL (Onno, Dirk Haase)\n13. Integrate Beta 5 of the Macintosh Port (Dirk Haase)\n-------------------------- October 27th 1998 version 2.3g -------------------\n 1. zip_tz_is_valid should be zp_tz_is_valid (Kai Uwe)\n 2. MVS native (not OE) beta fixes (Keith Owens)\n 3. LynxOS support from Giuseppe Guerrini\n 4. MVS already has stat() and fstat() so use 'em (Keith Owens)\n 5. MVS fix in readzipfile() for new, unopened dataset without EOF marker\n    (Keith Owens)\n 6. Remove 16-bit stuff from windll/windll.rc (Mike)\n 7. Windll: Use hCurrentInst not hInst (Mike)\n 8. In util.c compare strchr() return value with NULL (Onno, Frank Donahoe)\n 9. unix/unix.c: initialize variable t in ex2in() (Onno, Frank Danahoe)\n10. Remove windll/borland subdirectory (Mike)\n11. Really fix extra field realloc() for BeOS and MacOS (Christian)\n12. Fix the dj2 LFN related access violation bug (Christian, Joe Forster)\n13. proginfo/3rdparty.bug: Added more info about other Zip clone's bugs.\n14. The global copyright definitions in revision.h now depend on DEFCPYRT\n    (Christian).\n15. tandem/macros: removed obsolete object file references (Christian)\n16. fix memory leak with the \"filter\" patterns (Christian, Leah Kramer)\n17. zip.c: completed the support for MacOS specific -N (Christian)\n18. reorganized the Mac specific help screen code (Christian)\n19. zipup.c: corrected the USE_ZLIB code to emit \"stored\" entries under\n    the same conditions as the \"native deflate\" code (Christian)\n20. A couple of vars that will never be negative should be unsigned (Christian)\n-------------------------- November 18th 1998 version 2.3h -------------------\n 1. DJGPP: When compressing from stdin don't set binary mode if stdin is\n    a terminal (E-Yen Tan)\n 2. Fix signed/unsigned comparisons in fileio.c, util.c and zipcloak.c\n    (Frank Donahoe)\n 3. Move macgetch() prototype from macos/source/macos.c to macos/osdep.h\n    (Christian)\n 4. _doserrno should have type int, not unsigned int (Christian)\n 5. In zipfile.c init a file pointer with NULL to fix gcc warning (Christian)\n 6. Upgrade to MacOS beta 7 (Dirk Haase)\n 7. Move the #pragma statements from generic sources to cmsmvs.h (Christian)\n 8. Support for QNX/Neutrino 2.0 (Chris)\n 9. Default to -r in help screen add -R at the bottom (Chris)\n10. Clean up Makefile for BeOS R4 on x86 (Chris)\n11. Beos: If not storing symlinks store attributes of symlink target (Chris)\n12. Use izshr037 (Christian)\n13. Remove ZIPERR() macro from in {msdos,win32}/osdep.h (Christian)\n14. win32/win32.c: Fix 1-day offset in non-64bit FileTime2utime() (Christian)\n15. win32: enable 64-bit FileTime2utime() for MS VC++ >= 5.0 (Christian)\n16. cygwin32 only has _P_WAIT (Thomas Klausner)\n17. msname() should *really* ignore illegal characters (Thomas Klausner)\n18. Fix a missing ')' in Opendir() from win32zip.c (Thomas Klausner)\n-------------------------- December 5th 1998 version 2.3i -------------------\n 1. Remove the #pragma statements that were forgotten the first time (Ian)\n 2. Remove obsolete macos/source/CharMap.h (Steve Salisbury)\n 3. isatty(fileno(zstdin)) in zipup.c should be isatty(zstdin)\n    (Onno, E-Yen Tan)\n 4. several \"shut up warnings from compiler\" fixes (Christian)\n 5. several cosmetic source changes (Christian)\n 6. win32: make NTSD handling to be robust against alignment and structure\n    padding problems (Christian)\n 7. Apply don't set binary mode when stdin is a terminal in zipup.c for\n    MSDOS and human68k (Christian)\n 8. Upgrade to MacOS beta 8 (Dirk Haase)\n 9. Add callback for WINDLL to handle user termination (Mike)\n10. Fix typo in acornzip.c (Darren Salt)\n11. acorn/sendbits.s: pass correct parameters to flush_outbuf() (Darren Salt)\n12. Fixes for IBM C/C++ 3.6 where time_t is a double (Kai Uwe)\n13. Fixes for IBM Visual Age C++ for win32 (Douglas Hendrix)\n14. man/zip.1: some version numbers in the text were still \"2.2\" (Christian)\n15. win32/makefile.emx: added a compilation variant that generates\n    standalone executables (Christian)\n16. change __CYGWIN32__ into __CYGWIN__ and add compatiblity definition for\n    B19 and older (Cosmin Truta)\n17. create uniform win32 getch() replacement (Christian)\n18. put back in define of USE_EF_UT_TIME in tandem.h (Dave Smith)\n19. put back in define of USE_CASE_MAP in tandem.h (Dave Smith)\n20. updates to make/macros to allow the object to be licensed (Dave Smith)\n21. updates to macros/doit to remove mktime.c (Dave Smith)\n22. updates to tandem.c for in2ex/mapname/chmod amendments to match Unzip\n    (Dave Smith)\n23. Use izshr039.zip (Christian)\n24. Init filenotes to 0 for the amiga too (Onno)\n25. get_filters(): remove one flag=0 statement to make -R work again (Onno)\n-------------------------- December 17th 1998 version 2.3j ------------------\n 1. FOPWT defines opening a temp file for writing (Ian)\n 2. Remove handling of bits.c from a couple of tandem files (Christian)\n 3. A couple of \"shut up warnings from compiler\" fixes (Christian)\n 4. win32/osdep.h: removed duplicate \"IZ_PACKED\" definition (Christian)\n 5. win32/zipup.h: remove invalid \"elseif\" preprocessor token (Christian)\n 6. sync MacOS help screen with other ports (Christian)\n 7. get_filters(): set flag to 0 when -R isn't used (Christian)\n 8. \"local extra != central extra\" now has \"info\" status (Christian)\n 9. use windll directory as \"home\" directory for builds (Mike)\n10. CMS/MVS: define FOPWT (Ian)\n11. Upgrade to MacOS beta 9 (Dirk Haase)\n-------------------------- January 17th 1999 version 2.3k ------------------\n 1. Change FOPW into FOPW_TMP (Christian)\n 2. win32: #include uses paths relative to the parent directory (Christian)\n 3. Use forward slashes as path separator in #include statements (Christian)\n 4. windll: fix descriptions of f{In,Ex}cludeDate (Christian)\n 5. win32/makefile.lcc: add some -I<path> options to find files in the\n    right places (Christian)\n 6. Supply default empty IZ_PACKED define (Christian)\n 7. windll: Fix some typos, descriptions (Christian)\n 8. windll project files: use relative paths, no specific root directory\n    (Christian)\n 9. windll project files: remove link references to import libraries that\n    are not used by the zip library (Christian)\n10. windll: fix potential infinite loop in a VB sample (Mike)\n11. windll/windll.txt: remove \"may not work with VB\" statement (Mike)\n12. Multibyte character set support from Yoshioka Tsuneo\n13. Theos port from Jean-Michel Dubois\n14. Tandem: added simple handling of Enscribe files by converting them into\n    text type files (Dave Smith)\n15. Tandem Extra Field (\"TA\") containing Tandem File Attributes (Dave Smith)\n16. Tandem history file showing background info to (UN)ZIP ports (Dave Smith)\n17. create ZIP file on tandem with special file code (1001) (Dave Smith)\n18. made tandem.c & tandem.h code completely the same as UNZIP (Dave Smith)\n19. unix/configure: move +Onolimit and -Olimit into the machine specific\n    section (Onno, John Wiersba)\n-------------------------- February 21st 1999 version 2.3l ------------------\n 1. Fix qdos Makefile (Jonathan Hudson)\n 2. fgets instead of gets in zipnote to fix linker warnings (Jonathan Hudson)\n 3. Theos: remove _setargv.c and a reference in zip.c (Jean-Michel Dubois)\n 4. Theos README (Jean-Michel Dubois)\n 5. interchanged the fRecurse flag values for \"-R\" and \"-r\" (Christian)\n 6. add \"z\" pr prefix to MBCS functions to avoid name clashes (Christian)\n 7. Whenever the position of the increment operator does not matter, the\n    INCSTR variant is used, which has been mapped to the {PRE|POS}INCSTR\n    variant that is more efficient. (Christian)\n 8. fixed the \"-R\" handling in fileio.c, filter() function (Christian)\n 9. simplified some THEOS specific code additions (Christian)\n10. changed the line break of the compiler version message in version_local()\n    for MSDOS and Win32 to take into account some verbose compilers (Christian)\n11. removed the THEOS changes from ttyio.c. Instead, a THEOS specific\n    setup was added to ttyio.h (Christian)\n12. sync vms/link_zip.com with the corresponding make_zip.com (Christian)\n13. added compatibility settings for support of MBCS on Win32 with all tested\n    compilers to win32/osdep.h\n14. added type-casts to isalpha() macro calls (Christian)\n15. fixed win32's wild_match which was clobbered by the MBCS addition\n    (Christian)\n16. finished up the \"potential infinite loop\" problems in the VB sample\n    that Mike started to repair (Christian)\n17. in ziperr.h, AZTEK C might require the false comma that was removed\n    to satisfy THEOS C (Christian)\n18. removed the bogus THEOS specific isdir check in zipup.c (Christian)\n19. modified the code for line ending translation to be independent\n    of the local system's convention for '\\n' and '\\r'; this allowed\n    the removal of the THEOS specialities (Christian)\n20. Tandem: -B option to zip Enscribe files with no record delimiters\n    (Dave Smith)\n21. Tandem: attempt to catch Large Transfer mode failure (Dave Smith)\n22. Theos: Fixed keyboard entry functions. (Jean-Michel Dubois)\n23. Theos: workaround for the argument wild card expansion that is bugged\n    in the standard library. Managed by MAINWA_BUG flag. (Jean-Michel Dubois)\n24. Theos: support for filenames and notes with accented characters.\n    (Jean-Michel Dubois)\n25. Upgrade to MacOS final (Dirk Haase)\n-------------------------- March 31st 1999 version 2.3m -------------------\n 1. Theos: for relative paths to root directory cause open, fopen and stat\n    failure, workaround this. (Jean-Michel Dubois)\n 2. Theos: when no path is indicated in a file or directory name and the\n    file or directory doesn't exist in the current directory it looks for\n    the file or directory in the root directory, workaround this.\n    (Jean-Michel Dubois)\n 3. Corrected some typos and spelling error in macos/HISTORY.TXT; skipped\n    off invisible trailing whitespace (Christian)\n 4. proginfo/extra.fld: added documentation for Tandem and Theos extra\n    field layout (Christian with Dave D Smith resp. Jean-Michel Dubois)\n 5. qdos/Makefile.qdos: The build of ZipCloak requires inclusion of\n    the crctab object module; qfileio_.o compilation requires the -DUTIL\n    flag (Christian)\n 6. win32: fix incorrect MB_CUR_MAX macro for mingw32 and lcc (Christian)\n 7. theos/_fprintf.c, theos/_rename.c, theos/osdep.h: Some function\n    parameters require the \"const\" attribute to achieve compatibility\n    with ANSI C requirements (Christian)\n 8. theos/theos.c: map Theos' (No)Hidden file attribute to MSDOS Hidden\n    bit in the MSDOS part of zipentry header's external attribute field;\n 9. theos/stat.h: prevent multiple inclusions\n10. Theos: Fixed wild card management for options other than adding\n    (Jean-Michel Dubois)\n11. Theos: Removed modifications of const strings (Jean-Michel Dubois)\n12. Split tandem.c up into separate zip/unzip parts (Dave Smith, Christian)\n13. Move inclusion of OS specific zipup.h files to tailor.h (Onno)\n-------------------------- August 14th 1999 version 2.3n -------------------\n 1. Move inclusion of OS specific zipup.h files back to zipup.c (Onno)\n 2. Remove getline() from zipnote.c and use gets() again (Onno)\n 3. BeOS PowerPC R4.1 support (Chris)\n 4. New DOIT and MACROS files for the tandem port (Dave Smith)\n 5. Don't switch the console to binary mode (Michel de Ruiter)\n 6. In some circumstances undosm could be freed twice (Mike)\n 7. Also define const in tailor.h for ultrix (Onno, Foppa Uberti Massimo)\n 8. Tandem: Change zopen in TANZIPC to allow opening of files with missing\n    alt keys (err 4) (Dave Smith)\n 9. Tandem: Assume not DST if can't resolve time (no DST table available)\n    (Dave Smith)\n10. WIN32: skip trailing dots and spaces in getnam (Onno, Dan Kegel)\n11. Use ZE_NONE when nothing to freshen or update (Onno, Yuri Sidorenko)\n12. Remove tabs from files that don't need them (Onno)\n13. Remove tabs and spaces from the end of a text line (Onno)\n14. Upgrade macos to 1.04b2 (Dirk)\n15. Add -Q documentation to manual page (Jonathan Hudson)\n16. Copy hiperspace files instead of renaming them (Keith Owens)\n17. Disallow some more characters to appear in DOS filenames when using -k\n    (Onno, Thomas Klausner)\n18. Document missing options and environment variables in the manual (Onno)\n19. New acorn/GMakefile to compile with gcc on RISCOS (Darren Salt)\n20. ISO 8601 date format support for -t and -tt (Rodney Brown)\n-------------------------- September 21st 1999 version 2.3o -------------------\n 1. Sync zip.h license with LICENSE (Onno)\n 2. Add copyright notice to README, os2zip.c and os2.zip.h (Onno, Greg)\n 3. Fix the ASM variable in acorn/GMakefile (Darren Salt)\n 4. Add another requirement to acorn/ReadMe.GMakefile (Darren Salt)\n 5. Fix unbalanced parenthesis in vms_get_attributes declaration in zip.h\n    and move it to vms/zipup.h (Onno, Mike Freeman)\n 6. Make a couple of os2 files public domain (Kai Uwe)\n 7. Change and rename disclaimer array in revision.h (Onno)\n 8. Change copyright array in revision.h (Onno)\n 9. macstuff.c copyright is the same as macstuff.h (Christian)\n10. WHATSNEW: add ISO 8601 dates supported (Christian)\n11. fileio.c - msname(): strip off leading dots, these are illegal for\n    MSDOS compatible names (Christian)\n13. fileio.c - replace(): deactivate \"dead\" code for CMS_MVS (Christian)\n14. man/zip.1: \"-$\" option is also used for WIN32 ports\n15. msdos/msdos.c - version_local(): break the version line for\n    GNU compilers too (Christian)\n16. tailor.h: added typecasts to MBCS macros, to suppress \"type mismatch\"\n    warnings (Christian)\n17. util.c, zip.h, zipfile.c: ZCONSTify several pointers (Christian)\n18. util.c - recmatch(), zip.c - version_info(): add compile time option\n    WILD_STOP_AT_DIR (Christian, Darren Salt)\n19. util.c - envargs(): MBCS related fixes (Christian)\n20. win32/lm32_lcc.asm: add TAB characters that are required by the lcc\n    assembler source parser (Christian)\n21. zip.c: fix the \"is a console\" check (Christian)\n22. zipnote.c: use getline() (Christian)\n23. zipup.c: use zclose() in case of I/O errors (Christian)\n24. zipup.c: use ZE_WRITE when a write error occurs (Christian)\n25. win32/win32.c: HAVE_INT64 is used by mingw32 (Cosmin Truta)\n26. update shared sources to match izshr041 (Christian)\n-------------------------- November 29th 1999 version 2.3 ------------------\n 1. Missing parenthesis in win32/win32.c (Steve Salisbury)\n 2. Add Cosmin Truta to proginfo/infozip.who (Onno)\n 3. Remove one parenthesis pair too many from vms_get_attributes() declaration\n    in vms/zipup.h (Mike Freeman)\n 4. qdos .s are expected to start with a #, work around it (Jonathan Hudson)\n 5. tandem: -B0 should be deflating not storing (Dave Smith)\n 6. human68k updates from Shimazaki Ryo\n 7. beos Makefile cleanup (Chris)\n 8. workaround for fseek to negativate offset behaviour of the RISC OS\n    SharedCLibrary (Darren Salt)\n 9. set file type for RISC OS in zipcloak.c (Darren Salt)\n10. change tandem zgetch() to allow crypt version to work (Dave Smith)\n11. fix a comment typo in acorn/riscos.c (Christian)\n12. fileio.c: two type-cast to shut up noisy compilers (Christian)\n13. human68k: fix missing case_flag argmument (Christian)\n14. win32/win32.c: remove HAVE_INT64 completely (Christian)\n15. zip.c: raise \"cannot zip to console\" error when stdout IS a tty (Christian)\n16. zip.h: don't use dummy argument names in declarations (Christian)\n17. Add missing semicolon in fileio.c (Shimazaki Ryo)\n18. win32.c: IBMC compiler >= 3.50 have int64 (Kai Uwe)\n19. Handle initialization error return value from MVS stat() in procname()\n    (Keith Owens)\n20. Use RISC OS instead of RiscOS in the manual (Darren Salt)\n21. Use # instead of ? as single character wildcard on RISC OS (Darren Salt)\n22. New windll example.c (Mike)\n23. Correct storage of 8-bit char filenames with RSXNT (Burkhard Hirzinger)\n24. fix install in unix/Makefile (Santiago Vila, Onno)\n25. Fix zip -L output (Santiago Vila, Onno)\n26. Ignore unix special files (Jonathan O'Brien)\n27. Upgrade to izshr042 (Onno)\n28. Make copyright notice the same as in izshr042 (Onno)\n29. Make copyright notice in zip.h the same as LICENSE (Christian)\n30. Set tempzf to NULL _after_ it has been closed (Chris Kacher)\n31. Change email address for Jonathan Hudson (Jonathan Hudson)\n32. Remove win32/winzip.c.orig (Steve Salisbury)\n33. Use 'Steve Salisbury' throughout the documentation (Steve Salisbury)\n34. Change email address for Steve Salisbury (Steve Salisbury)\n35. Change email address for Chris Herborth (Chris Herborth)\n36. Use zip23 in INSTALL (Roger Cornelius)\n37. Use zcrypt28 in INSTALL (Onno)\n38. New acorn/srcrename (Darren Salt)\n39. amiga/makefile.azt: make clean should remove some more items (Paul)\n40. Change email address for Cosmin Truta (Cosmin Truta)\n-------------------------- February 11th 2001 version 2.4a ------------------\n 1. Identify newer Borland compilers (Brad Clarke)\n 2. Detect Turbo C 2.01 which doesn't have mktime (Brian Lindholm)\n 3. Fix the use of -@ together with -i -x (Christian)\n 4. Update msdos/README.DOS to match reality (Christian)\n 5. win32: use assembler crc32 code (Christian)\n 6. windll: _CRTIMP is needed in several function declarations (Christian)\n 7. back to zip 2.2 memcompress() behaviour  (Kelly Anderson)\n 8. new amiga time code based on nih public domain code  (Paul Kienitz)\n 9. Detect some more Borland C++ builder versions (Brad Clarke)\n10. Fix OS/2's extended file attributes compression code (Christian, Kai Uwe)\n11. Correct translation of EBCDIC passwords to ASCII (Christian)\n12. Attempt at integrating novell patches from Roger Foss (Onno)\n13. Use izshr043 (Christian)\n-------------------------- July 3rd 2001 version 2.4b ------------------\n 1. Fix OS/2's ACL compression code (Christian, Kai Uwe)\n 2. Rename netware subdir to novell (Christian)\n 3. Remove -dNETWARE -dDOS from novell Makefile (Christian)\n 4. Remove defined(NETWARE) from the sources (Christian)\n 5. printf is a macro in glibc 2.2, fix version_local function\n    (Christian, Matthew Wilcox)\n-------------------------- January 13th 2002 version 2.4c ------------------\n 1. Use klist_items when initilizating koff[] in tandem.c (Dave Smith)\n 2. Only call NLMsignals() in zip.c when NLM is defined (Mike, Onno)\n 3. include riscos.h instead of acorn/riscos.h in acorn/osdep.h (Andy Wingate)\n 4. Use izshr044 (Christian)\n-------------------------- January 13th 2002 version 2.4d ------------------\n 1. Don't use mmap for stored entries (Christian)\n 2. BIG_MEM and MMAP cannot be defined at the same time (Christian)\n 3. Allow redirection of version screen to file (Christian)\n 4. Fix for OS/2 output redirection bug (Christian, Kai Uwe)\n 5. Acorn script for creating self extracting zips (Darren Salt)\n 6. Update amiga makefiles to support revised timezone routines (Christian)\n 7. Correct memcompress calculation for allocation size (Christian)\n 8. Fix FORCE_METHOD debug option for level 1 and 2 (Christian)\n 9. Whitespace cleanup in man/zip.1 (Christian)\n10. Define IZ_IMP to specify compiler declaration prefixes (Christian)\n11. make win32 and msdos version_local() \"stdio-macro-safe\" (Christian)\n12. move tandem's zip specific zipopen to tanzip.c (Christian)\n13. first parm is void * in external scope of vms_get_attributes() (Christian)\n14. use right novell subdirectory in zipup.c (Christian)\n15. update copyright for files modified in 2002 (Onno)\n-------------------------- January 19th 2002 version 2.4e ------------------\n 1. Add MacOS X to version_local() (Mark)\n 2. unix/configure: Init LFLAGS1 to \"\", MacOS X doesn't like -s (Onno, Mark)\n 3. rename errors array to ziperrors to avoid MacOS X library clash (Mark)\n 4. Support for the upx executable packer in DOS makefiles (Christian)\n 5. remove obsolete -m486 switch from dos djgpp makefile (Christian)\n 6. When using DOS, force the use of msdos style external attributes when\n    updating zip entries created under another OS (Christian)\n 7. os2/makefile.os2: fixed ASFLAGS for watcom16dos (Christian)\n 8. Update copyright and ftp address in several files (Christian)\n 9. The RISCOS port uses '.' as directory separator, not '/' (Christian)\n10. win32/makefile.bor: more options to compile the asm CRC code (Christian)\n11. win32: use registry to handle timezones with MS C rtl (Christian)\n12. acorn: use recommended practice for calling the linker (Andy Wingate)\n13. unix/configure: check if CPP works else use ${CC} -E (Onno, Mark)\n14. update versioninfolines in revision.h to match reality (Onno)\n-------------------------- February 10th 2002 version 2.4f ------------------\n 1. vms: Zip -V is now able to handle file sizes up to 4Gb (Christian)\n 2. vms: Include target environment detection for MMS/MMK (Christian)\n 3. Change dummy message from zipcloak (Christian)\n 4. acorn: add riscos specific -/ option (Darren)\n 5. Update acorn's WILD_STOP_AT_DIR feature (Christian)\n 6. acorn: Fix buffer allocation for -/ option (Christian, Darren)\n 7. acorn: fix make clean (Andy Wingate)\n 8. acorn: use tabs for GMakefile to make GNU make happy (Andy Wingate)\n 9. tandem: use nskopen not zipopen (Dave Smith)\n10. tandem: allow passing of CRYPT define (Dave Smith)\n11. use izshr045 (Christian)\n-------------------------- April 1st 2002 version 2.4g ------------------\n 1. acorn: fix assembler and compiler options in makefile (Darren)\n 2. use izshr046 (Christian)\n 3. MVS: define isatty to 1 to fix screen output (Christian)\n 4. tandem: encryption really works now (Dave Smith)\n 5. win32: detect Borland C++ builder 6 (Brad Clarke)\n-------------------------- April 30th 2003 version 2.4h ------------------\n 1. tandem: fix temporary file contention (Dave Smith)\n 2. cmsmvs: generate better filenames with -j (Owen Leibman)\n 3. tandem: fix temporary file leftovers (Dave Smith)\n 4. solaris: enable large file I/O to break 2G barrier (Rick Moakley, Onno)\n\nNote:  Zip 2.4 was never released.  That code was the start of the Zip 3.0\neffort below.  Some changes and fixes also made it to the Zip 2.3x releases.\n\n---------------------- January 21st 2004 version 3.0a ----------------------\nInitial work on Zip 3.0 by Ed Gordon and Rainer Nausedat\n 1. Changed some comments to update copyrights (Ed)\n 2. Changed text in command line messages from zip 2.4 to zip 3.0 (Ed)\n 3. Changes to many files for Zip64 wrapped in ifdef ZIP64_SUPPORT (Rainer)\n 4. Attempt to fix buggy Win32 buffered 64-bit calls (Ed)\n 5. Add functions to zipfile.c for Little-Endian memory writes (Rainer)\n 6. Add functions to zipfile.c for writing Zip64 extra fields (Rainer)\n 7. Major changes to putlocal, putcentral, and putend (Rainer)\n 8. Fixing -F and -FF for Zip64 postponed (Ed and Rainer)\n 9. Command line code replaced.  Global table sets options, long options now\n    supported.  Permutes so order of arguments can vary (Ed)\n10. Fix bug where not allowed to use -@ with stdout but was with stdin.\n    Now can read filenames from stdin using -@ and output to stdout and\n    no longer am allowed to use -@ if reading from stdin (Ed)\n11. Replace stat() with zstat(), fstat() with zfstat() and struct\n    stat with z_stat in Zip64 blocks.  Put 64-bit file calls in ifdef\n    LARGE_FILE_SUPPORT blocks.  Can implement Zip64 without > 4 GB\n    file support but for now need large files for Zip64 support (Ed)\n12. Move port-specific code to osdep.h and win32.c (port specific) and\n    tailor.h (generic) and remove temporary os_io.c.  As OF() is\n    not defined until after osdep.h includes in tailor.h function\n    prototypes for zfseeko, zftello, and zstat after that in tailor.h (Ed)\n13. Settings of ZIP64_SUPPORT and LARGE_FILE_SUPPORT automatic based on\n    port and version of compiler.  Defining NO_ZIP64_SUPPORT or\n    NO_LARGE_FILE_SUPPORT overrides this (Ed)\n14. Bugs compiling scanzipf_fix(...) in zipfile.c and the fix functions could\n    use rewrite (Rainer and Ed)\n15. Add prototype for zfopen for mapping to 64-bit fopen on ports using\n    inodes but not implemented (Ed)\n16. More work on extended local headers and encypted archives (Rainer)\n17. Fix DLL files so now compiles (Ed)\n18. File size in dll limited to 32-bit in structure.  A new DLL api is needed\n    to return 64-bit file sizes.  Current api fixed to return max 32-bit if\n    more than that (Ed)\n19. Add local header Zip64 support and local extra field.  Fixed cast\n    to ulg missed previously that forced zstat to return value mod 4 GB in\n    zipup.c which kept local header code from seeing actual file size (Ed)\n20. Add new option --force-zip64 to force use of zip64 fields.  Could\n    be temporary (Ed)\n21. Fix for VB added to api.c that just store the passed strings internally.\n    Should update api to optionally return file sizes as 64-bit in call back\n    and to accept RootDir and other strings in same call that zips (Ed)\n22. Readme updated to describe new features and mention updated mail group\n    web links (Ed)\n23. Minor bugs in output format found and fixed.  Now can add\n    files > 4 GB to archive and unzip using major unzippers (Ed)\n24. If zip used as filter (zip - -) and sizes exceed limits of extended\n    local header (data descriptor) then set max 32-bit values there.  Major\n    unzippers ignore and use central directory values which are correct.  Can\n    create Zip64 data descriptor using --force-zip64 option but seems no need\n    for it (Ed)\n25. A few bugs in how headers are handled prevented zipping large numbers\n    of files.  Fixed (Rainer)\n26. A bit of an attempt to fix -F and -FF.  Seems to work but not that\n    robust.  More work needed (Ed)\n27. After some cast and other fixes zip compiles on Linux Red Hat 9 using Unix\n    generic.  Added automatic detection of fseeko64 and if detected\n    sets LARGE_FILE_SUPPORT and setting that sets ZIP64_SUPPORT.  Works but\n    could not test large files on the small system (Ed)\n28. Tried to fix bug that prevents zipnotes from compiling when ZIP64_SUPPORT\n    is set.  Still broke.  This crashes the Unix Makefile but after\n    zip is compiled (Ed)\n---------------------- May 8th 2004 version 3.0b ----------------------\n 1. Update license headers on more files (Ed)\n 2. Change many ZIP64_SUPPORT ifdefs to LARGE_FILE_SUPPORT where appropriate.\n    Now can test ports using three stages, compile with NO_LARGE_FILE_SUPPORT\n    (which disables ZIP64_SUPPORT) to test base code, compile with\n    NO_ZIP64_SUPPORT to test the 64-bit file calls (assuming port sets\n    LARGE_FILE_SUPPORT) but otherwise use the base code, and without either\n    to test Zip64 if enabled on port (Ed)\n 3. Fix zipnotes bug by moving a ZIP64_SUPPORT block in zipfile.c (Ed)\n 4. Add Large File Summit (LFS) code to Unix port to enable 64-bit calls.\n    Update configure to include test for all needed 64-bit file calls before\n    enabling LARGE_FILE_SUPPORT for unix port (Ed)\n 5. Merge encryption code from zcrypt29 (files from unzip) into zip and\n    enable by default (Ed)\n 6. New man pages for zipnote, zipsplit, and zipcloak (Greg, Ed)\n 7. Add encryption notice to crypt.c comments and to version information\n    in zip.c (Greg, Ed)\n 8. Add Russian OEM EBCDIC support when OEM_RUSS defined in ebcdic.h but\n    Dmitri reports that 0x2F not '/' so make recommended change in cutpath\n    call in zipfile.c used by -D option (Dmitri - Nov 10 2003 email)\n 9. ToDo30 file added to list what's left to do in this release (Ed)\n10. Change fopen to zfopen for large file code and map to fopen64 for\n    Unix (Ed)\n11. ftello64 seems broken in zipup.c on Linux (kernel 2.4), returning\n    negatives past the 2 GB barrier, though ftello64 works in a test program.\n    Likely error in defines.  For now skip ftello64 check for Unix with\n    LARGE_FILE_SUPPORT.\n12. A few updates in Readme.  Needs overhaul likely.  Also verified mxserver\n    is gone and replaced with list addresses (Ed)\n13. First iterations at updating WinDLL for Zip64 (Mike)\n14. Decide to drop backward dll compatibility in favor of a cleaner\n    dll interface.  Decide to add string interfaces for VB (Ed, Mike)\n15. Add string interfaces to dll interface to bypass array limitations\n    imposed by VB and add -x and -i to interface (Mike)\n16. Create new VB example using new Zip64 dll interface (Ed)\n17. Add O_LARGEFILE define for zopen in unix/zipup.h to enable reading\n    large files in unix (Ed)\n18. Combine ZpSetOptions and ZpArchive dll calls to allow removing all VB kluges\n    in api.c to work around VB garbage collecting passed strings (Mike)\n19. Change new VBz64 example to use updated interface.  All works without\n    kluges (Ed)\n---------------------- August 15th 2004 version 3.0c ----------------------\n 1. Add date formats in -t and -tt date errors (Ed)\n 2. Add -so to display all available options (Ed)\n 3. Many fixes from Dan Nelson to fix some large file support problems and\n    add large file support to a few ports.  Main change is rather than use\n    explicit 64-bit calls like fopen64 now set 64-bit environment and use\n    standard calls.  Also add a define for 64-bit printf format used to\n    print 64-bit stats (Dan, Ed)\n 4. Changes to Unix config based on suggestions from Dan Nelson.  Check\n    if off_t is at least 64 bit (Dan, Ed)\n 5. Add -- to get_option.  Any arguments after -- on command line now\n    read as paths and not options (Ed)\n 6. Add extended help (Ed)\n 7. Change add_filter flag parameter from char to int as some compilers have\n    problems with char arguments (Ed)\n 8. Changed filter() to do R and i separately so i has precedence over R (Ed)\n 9. Split variable t in zip.c into t (off_t) and tf (ulg) (Ed)\n10. Add quotes to zipname in check_zipfile for MSDOS to allow spaces in\n    archive path given to unzip to test ( , Ed)\n11. Move zip.h include before ctype.h include in trees.c and zipup.c as\n    when ctype.h is first and using 64-bit environment at least on unix port\n    found it defines off_t as 4 bytes in those files as off_t is defined as\n    8 bytes in other files and this changes the size of the zlist structure\n    which is not good (Ed)\n12. Add default 64-bit file environment to tailor.h if LARGE_FILE_SUPPORT\n    is set but no port 64-bit file defines are set up earlier in the file.\n    Should allow other ports to set LARGE_FILE_SUPPORT on the compiler\n    command line to test if the standard defines work (Ed)\n13. Adjust binary detection in trees.c by changing 20% binary (4 out of 5\n    ascii) that used >> 2 to 2% (64 out of 65) using >> 6 instead.\n    trees.c  (Ed)\n---------------------- November 12th 2004 version 3.0d ----------------------\n 1. Add global variable for EncryptionPassword in VBz64 example and\n    some other password callback cleanup (Ed)\n 2. Add -W option to turn on WILD_STOP_AT_DIR where wildcards will not\n    include directory boundaries in matches (Ed)\n 3. Add -nw option \"no wild\" to completely disable wildcards in MATCH\n    function.  Allows a list of files to be read in without worrying about\n    wildcards or escapes (Ed)\n 4. Add -s option split-size but not implemented (Ed)\n 5. Add -sp option split-pause but not implemented (Ed)\n 6. Add changes for WiZ including moving Win32 64-bit wrappers into\n    win32i64.c to avoid naming conflict between libraries in WiZ (Mike, Ed)\n 7. Some large file fixes in crypt.c (Ed)\n 8. Add new error code ZE_UNSUP for unsupported compiler options.  Add\n    check of size of zoff_t in zip.c when LARGE_FILE_SUPPORT enabled (Ed)\n 9. Changed ZE_UNSUP to ZE_COMPERR to avoid conflict with unzip (Ed)\n10. On VMS (sufficiently recent, non-VAX), DECC$ARGV_PARSE_STYLE is set\n    automatically to preserve case of the command line if the user has\n    SET PROCESS /PARSE = EXTEND.  This obviates quoting upper-case\n    options, like -V, when enabled.  VMS.C (Steven Schweda (SMS))\n11. On VMS, building with macro VMS_PRESERVE_CASE defined preserves case\n    of names in archive, instead of forcing lower-case (the former and\n    current default behavior).  VMSZIP.C (SMS)\n12. On VMS, in some of the simplest cases, ODS5 extended file name\n    escape characters (\"^\") are removed from names in archive.\n    VMSZIP.C (SMS)\n13. On VMS, fixed a problem in some cases with mixed-case directory\n    names, where too much of the directory hierarchy was included in the\n    path names in the archive.  VMSZIP.C (SMS)\n14. On VMS, minor changes for large file support (long -> zoff_t).\n    VMSZIP.C (SMS)\n15. On VMS, changed some structure declarations to typedefs, and\n    rearranged to simplify #if's and reduce potential name conflicts.\n    VMS.H, VMS_IM.C, VMS_PK.C (SMS)\n16. On VMS, reformed -V (/VMS) processing.  Added -VV (/VMS=ALL).\n    Removed some sign bits to accomodate files bigger than 2GB.\n    CMDLINE.C, VMS_IM.C, VMS_PK.C, ZIP.C, ZIP_CLI.CLD, ZIP_CLI.HELP,\n    ZIPUP.H (SMS)\n17. Update command line options to support -VV as distinct option (Ed)\n18. More VMS changes (SMS)\n19. Add zoff_t format function (SMS)\n20. On VMS, when -b was not used, temporary archive files were always\n    created in the current default directory, rather than in the archive\n    file destination directory.  VMS now uses its own tempname()\n    function.  FILEIO.C, VMS.C (SMS)\n21. Remove using FNMAX for path size in a few places including filetime.c\n    to avoid exceeding limit (based on fixes from Greg and others) (Ed)\n22. Add port atheos (Ruslan Nickolaev, Ed)\n23. Bug fix adds different extra fields for local and central in VMS (SMS)\n24. Now short options also take optional values as next argument (Ed)\n25. Change -dd to control -v dots (SMS, Ed)\n26. On VMS, a new open callback function senses (where supported) the\n    process RMS_DEFAULT values for file extend quantity (deq),\n    multi-block count (mbc), and multi-buffer count (mbf), and sets the\n    FAB/RAB parameters accordingly.  The default deq is now much larger\n    than before (16384, was none), and the default mbc is now 127\n    (up from 64), speeding creation of a large archive file.  Explicitly\n    set RMS_DEFAULT values override built-in defaults.  OSDEP.H, VMS.C\n    (SMS)\n27. VMS CLI definitions and CLI help have been updated, and may be\n    approximately correct.  CMDLINE.C, ZIP_CLI.CLD, ZIP_CLI.HELP (SMS)\n28. The man file zip.1 updated and Makefile updated to generate manual\n    pages for zipcloak.1, zipnote.1, and zipsplit.1 (Ed)\n---------------------- July 23rd 2005 version 3.0e ----------------------\n 1. Debian patch 004 - apply 2.4i configure changes from Onno to remove\n    need for -fno-builtin in unix/configure (Onno, Ed)\n 2. Debian patch 005 for bug 279867 - fix bug that could crash on large paths\n    and create security problem.  Apply patch changes from Greg (Greg, Ed)\n 3. SourceForge patch 1074363 - add win32i64.c to win32/makefile.w32 (Ed)\n 4. Add check when not ZIP64_SUPPORT in scanzipf_reg() in zipfile.c if\n    Zip64 archive being read (Ed)\n 5. Renamed fzofft() used to format zoff_t values to zip_fzofft() to remove\n    conflict when combined with UnZip in WiZ (Mike)\n 6. Add check in scanzipf_reg() in zipfile.c if Zip64 archive being read (Ed)\n 7. Fixes for amiga/makefile.azt to define directory for object files (Paul)\n 8. Define prototypes for local functions optionerr, get_shortopt and\n    get_longopt in fileio.c.  Define err argument of optionerr as ZCONST (Paul)\n 9. Add help_extended and DisplayRunningStats prototypes, fix other prototypes\n    in zip.c (Paul)\n10. Split int kk off of k for argument types (Paul)\n11. Aztec #endif quirk fix in zip.c for Amiga (Paul)\n12. Add detection of binary in first buffer read from file in zipup.c to avoid\n    a -l or -ll translation on binary file.  Not perfect but at least should\n    catch some binary files (Ed)\n13. Remove check for >= 128 from binary check in zipup.c as <= 6 enough for\n    signed char (SMS, Ed)\n14. SF Bug 1074368 - check for empty zip file in readzipfile() in zipfile.c\n    (Christian d'Heureuse, Ed)\n15. Add error exit to prevent archive corruption when updating a large-file\n    archive with a small-file program.  Add ZE_ZIP64 error.\n    ziperr.h, zipfile.c (SMS)\n16. Change percent() in zipup.c to do rounding better, handle cases near limits\n    while rounding, and allow negative percent returns (SMS, Ed)\n17. Add function ffile_size() in zipfile.c but in #if 0 block until determine\n    if works on all ports under all conditions.  Currently only used for size\n    check for Zip64 archive detection if compiled without ZIP64_SUPPORT and\n    this check may already be handled in scanzipf_reg() and should be added to\n    scanzipf_fix() when that is updated (SMS, Ed)\n18. Change >>1 to /2 in zipsplit.c to allow for negative percent returns (SMS)\n19. Add type uzoff_t for unsigned zoff_t things.  Should clean up some casting\n    (Ed)\n20. Based on discussions with other development groups, when data descriptors\n    (extended local headers) are used, force to Zip64.  This is compatible\n    with other unzips and does not require a change of the AppNote, but the\n    resulting archive requires Zip64 to read.  Using standard data descriptors\n    would mean that the zip operation would fail if a Zip64 entry was\n    encountered.  See zipfile.c (Ed)\n21. Add define SPLIT_SUPPORT to enable splits.  The command line options are\n    done and the globals are set up but nothing more.  globals.c, zip.h, and\n    zip.c mainly (Ed)\n22. Create spanning signature at beginning of archive when splitting enabled.\n    If reading a split archive skip the spanning signature unless creating a\n    split archive.  zip.c, globals.c (Ed)\n23. Start implementing split archives.  Define two methods. split_method = 1\n    updates local headers and is the most compatible but requires updating\n    previous splits.  split_method = 2 uses data descriptors and should work\n    for streams and removable media but may not be as compatible with other\n    zip applications.  (In part based on previous discussions with Rainer.)\n    Updated global variables to include bytes written to just the current\n    entry in the current split.  zipfile.c (Ed)\n24. Add note about output redirection to zip.1 (?, Ed)\n25. Remove num < 0 check as num now unsigned.  util.c (SMS, Ed)\n26. Change lastchar to lastchr in fileio.c in places to avoid function by same\n    name (SMS, Ed)\n27. Moved #endif /* !WINDLL */ in zip.c (Mike)\n28. Account for vms directory version being ;1.  vmszip.c (SMS)\n29. Fix Zip64 check in scanzipf_reg to use the buffer.  zipfile.c (Ed)\n30. Default define size_t (for use by Steve's ffile_size() function).  tailor.h (Ed)\n31. Enable Steve's ffile_size() function and enable large file check.  It\n    currently does not allow file sizes over 2 GB but the code is not supporting\n    it anyway without large file support.  Should remove that part of the check\n    when the casts are fixed.  zipfile.c (Ed)\n32. Fixes for djgpp.  Now compiles with djgpp 2 (Ed)\n33. Add new VC6 projects for win32 and windll (Cosmin)\n34. Convert some variables in zipsplit.c from ulg to zoff_t so compiles (Ed)\n35. Add wildcards to extended help.  zip.c (Ed)\n36. For optional option value now '-' is same as missing value.  fileio.c (Ed)\n37. Remove extra free() from -dd option switch.  zip.c (Ed)\n38. Change write_unsigned_to_mem() to write_ulong_to_mem() and write_short_to_mem()\n    to write_ushort_to_mem().  zipfile.c (Ed)\n39. Create new append to mem functions.  zipfile.c (Ed)\n40. Change zlist nam and ext from extent to ushort as that is what gets written.\n    zipfile.c (Ed)\n41. Change GetSD to use ush instead of size_t.  win32/win32zip.c (Ed)\n42. Change PutLocal(), PutExtended(), PutCentral(), and PutEnd() to write to\n    memory and then write the block at once to the file.  zipfile.c (Ed)\n43. Change zcomlen from extent to ush, other extent conversions.  zipfile.c,\n    globals.c, zip.h (Ed)\n44. Add is_seekable() and global output_is_seekable.  Do seekable check\n    when output file is opened.  zipup.c, globals.c, zip.h, zip.c (Ed)\n45. Do not increment files_so_far and bytes_so_far if file could not be read.\n    zip.c (Ed)\n46. If force_zip64 set, only force compressed size in central directory to Zip64\n    instead of all entries (csize, usize, off, disk) in Zip64 extra field.  This\n    fixes inconsistent handling of disk numbers.  zipfile.c (Ed)\n47. Add end status if displaying running stats and not all files were read.\n    zip.c (Ed)\n48. Change force_zip64 to zip64_archive in putend().  zipfile.c (Ed)\n49. Enable the i686-optimized code by default.  crc_i386.S,\n    win32/crc_i386.asm, win32/crc_i386.c (Cosmin)\n50. Document and implement a new text detection scheme provided by Cosmin in\n    set_file_type().  Should be able to handle UTF-8 and some other character sets.\n    proginfo/txtvsbin.txt, trees.c (Cosmin, Johnny, Christian)\n51. Update binary detection for -l and -ll to use Cosmin black list.  zipup.c (Ed)\n52. Change ZE_BIG to include read and write.  ziperr.h (Ed)\n53. If archive not seekable then use data descriptors.  If ZIP64_SUPPORT always\n    create Zip64 data descriptors and add a Zip64 extra field to flag it is\n    a Zip64 data descriptor.  This is klugy but should be compatible with other\n    unzips.  See the note in zipfile.c for details.  (Ed)\n54. Use ush for comment length in putend().  Instead of extent use ush for\n    zcount and fcount same as in zip file.  zip.h (Ed)\n55. Update VB readme.  windll/VB/readmeVB.txt (Ed)\n56. Change (INSTALL) to (INSTALL_PROGRAM).  unix/Makefile (, Ed)\n57. During update the file and byte status counts were off.  Fixed by not coun-\n    ting files copied from old to new as those are not in totals.  zip.c (Ed)\n58. Change from -b to -bx for nroff of manuals to text files.  unix/Makefile (Ed)\n59. Add cygwin to makefile.  unix/Makefile (, Ed)\n60. Fix bug where files to delete not added to list.  zip.c (Ed)\n61. Fix delete stats.  zip.c (Ed)\n62. Increment version of crypt to 2.10.  Update default behavior notes.\n    crypt.c, crypt.h (Paul, Christian)\n63. Format changes, add parentheses to zfseeko(), fix output bytes, add ifdef\n    blocks for ZIP10, fzofft formatting, casts.  crypt.c (Christian)\n64. Cast block_start to unsigned.  deflate.c (Christian)\n65. Let -R patterns match in subdirectories.  Update filter() to use switch,\n    use global icount and Rcount, handle subdirectories, update icount and\n    RCount in filterlist_to_patterns().  fileio.c, zip.c, zip.h, globals.c\n    (Christian)\n66. Enclose option -! and use_privileges under NTSD_EAS guard.  globals.c,\n    zip.c, zip.h (Cosmin)\n67. Updates to version, copyright, license.  [I did not split the copyright\n    to 2 lines as it already takes up space on the help screen.  Ed]\n    revision.h (Christian)\n68. Add ZCONST to some read-only string pointer arguments in function\n    declarations.  zipcloak.c, zipnote.c, zipsplit.c, zip.c, zip.h (Christian)\n69. Fix byte counts on exit in zipcloak() and zipbare() to fix zipcloak bug\n    (Christian)\n70. Modified zipnote.c to use WRBUFSIZ to handle line widths of at least 2047\n    characters in write mode (Christian)\n71. Change simple() and greedy() from zoff_t to uzoff_t.  zipsplit.c (Christian)\n72. Remove duplicate copyright notices.  zipsplit.c (Christian)\n73. Remove export notice from help page.  Move notice to bottom of license\n    page.  zipcloak.c (Ed)\n74. File USexport.msg export history added. (Greg)\n75. Added support for VMS ODS5 extended file names.  (Eight-bit only, no\n    Unicode.)  VMS name character \"/\" is mapped to Zip name character\n    \"?\".  New command-line options -C[2|5][-] (/PRESERVE_CASE[=opts])\n    control name case preservation and/or down-casing.  globals.c,\n    zip.c, zip.h, vms/cmdline.c, vms/vms_im.c, vms/vms_pk.c, vms/vms.c,\n    vms/vmszip.c, vms/vms.h  (SMS)\n76. New VMS option -ww (/DOT_VERSION) stores version numbers as \".nnn\"\n    instead of \";nnn\" [changed from -Y to -ww (Ed)].  zip.c (SMS)\n77. Changes to vms_open().  vms/vms_im.c, vms/vms_pk.c\n78. Changes to vms_read().  vms/vms_pk.c (SMS)\n79. Documentation updates.  vms/vms_zip.rnh (SMS)\n80. Minor updates.  vms/zip_cli.help, vms/cmdline.c, vms/vms_zip.rnh (Ed)\n81. Changes to vmsmunch().  vms/vmsmunch.c (SMS)\n82. Do some updating of VMS options.  vms/zip_cli.cld (SMS)\n83. Moved the VMS-specific ziptyp() function from zipfile.c to vms/vms.c\n    to segregate better the RMS stuff. (SMS)\n84. Put 64-bit calls in ZIP64_SUPPORT ifdef blocks, change some long parameters\n    for append to memory block functions to ulg, remove redundant includes,\n    add OFT protos to some functions with parameter types that get promoted\n    like ush to avoid warnings in VMS.  zipfile.c (SMS)\n85. Use zip_fzofft() to format number.  zipsplit.c (SMS)\n86. Add file_id.diz from Zip 2.31 (?, Ed)\n87. Update install from Zip 2.31 (?, Ed)\n88. Update license from Zip 2.31.  License (?, Ed)\n89. Update Readme.cr from Zip 2.31 (?, Ed)\n90. Add 64-bit assembler for Win32 from Zip 2.31.  win32/makefile.a64,\n    win32/readme.a64, win32/gvmat64.asm (?, Ed)\n91. Update Readme (Ed)\n92. Update headers.  crctab.c, crc32.c, deflate.c, ebcdic.h, fileio.h (Ed)\n93. Option for extra verbose VMS, change DIAG_FLAG from verbose to\n    (verbose >= 2).  vms/vms.c (SMS)\n94. Update copyright header.  qdos/qdos.c (Christian, Ed)\n95. Change exit(0) to exit(ZE_OK).  qdos/qdos.c (Christian)\n96. Change ulg to unsigned long.  tailor.h (, Christian)\n97. Default uzoff_t to unsigned long long if LARGE_FILE_SUPPORT manually\n    enabled for an otherwise unsupported port.  tailor.h (Ed)\n98. Update copyright header.  tailor.h (Ed)\n99. Change EXIT(0) to EXIT(ZE_LOGIC) for ziperr recursion.  zip.c (Christian)\n100. Change EXIT(0) to EXIT(ZE_OK) for successful returns.  zip.c,\n     zipcloak.c (Christian)\n101. Update license.  zip.h (Christian)\n102. Initialized mesg in zipcloak.c, zipnote.c, zipsplit.c to fix access\n     violation crashes.  (Christian)\n103. Added -q (Quiet mode) option to zipcloak, zipnote, zipsplit.  (Christian)\n104. Add proto of mb_clen().  fileio.c (Cosmin)\n105. Synchronize ttyio.c and ttyio.h with the unzip-5.52 source. (Cosmin)\n106. Control the POSIX emulation provided by some Unix-on-Windows compiler\n     distributions, such as Cygwin, via the FORCE_WIN32_OVER_UNIX macro.\n     tailor.h, win32/Makefile.gcc (Cosmin)\n107. Remove getenv() declaration.  util.c (Cosmin)\n108. Fix definitions of zopen and zstdin.  unix/zipup.h (Cosmin)\n109. Enable binary file operations for DJGPP and Cygwin.  unix/osdep.h (Cosmin)\n110. Remove -DMSDOS from CFLAGS; use correct dependency in target crc_i386.obj.\n     win32/makefile.w32, win32/makenoas.w32 (Cosmin)\n111. Update win32/makefile.bor and win32/makefile.gcc (Cosmin)\n112. Put mktemp() declaration inside the NO_PROTO guard.  tailor.h (Cosmin)\n113. Use the right type (DWORD) for volSerNo, maxCompLen and fileSysFlags\n     in FSusesLocalTime().  win32/win32.c (Cosmin)\n114. Set the \"zip Debug\" configuration as default.  win32/vc6/zip.dsp (Cosmin)\n115. Define ASM_CRC by default.  win32/osdep.h (Cosmin)\n116. Avoid using file names that are distinguished solely by letter case;\n     e.g. crc_i386.S and crc_i386.s.  unix/Makefile (Cosmin)\n117. Stylistic fix inside ex2in().  unix/unix.c (Cosmin)\n118. Change zlist dsk from ush to ulg to support Zip64 and added casts in\n     zipfile.c to write ush.  zip.h, zipfile.c (Christian, Ed)\n119. Conditionally apply S_IFLNK to support DJGPP.  unix/unix.c (Cosmin)\n120. Change -dd [siz] (display dots, set optional dot size) to the options\n     -dd (turn dots on, use 10 MB default) and -ds siz (set dot size).\n     Found that using -dd with an optional value got confusing as detection\n     of an optional argument, when the next argument was not either an option\n     or the end of the line, was easy to overlook.  Easier to avoid optional\n     values.  zip.c (Ed)\n121. Change text output of manual pages to zip.txt, zip.txt, zipcloak.txt,\n     zipnote.txt, zipsplit.txt.  unix/Makefile (Christian, Ed)\n122. Change comments using // to /* */ format.  api.c, zip.c   (Christian)\n123. Add support for signals SIGABRT, SIGBREAK, SIGBUS, SIGILL, and SIGSEGV\n     to utilities.  zipcloak.c, zipnote.c, zipsplit.c (Christian)\n124. Update ToDo30.txt file (Ed)\n125. Delete old Manual file (Ed)\n126. Update WHERE from Zip 2.32 (Ed)\n127. Change description of dot-size.  zip.c (Ed)\n128. Change VMS to use -ds to set dotsize.  vms/cmdline.c (Ed)\n129. Update manuals.  man/zip.1, man/zipsplit.1, man/zipnote.1,\n     man/zipcloak.1 (Ed)\n130. Detect i586, i686 and Cygwin in version_local().  unix/unix.c (Cosmin)\n131. Add clean target.  win32/makefile.w32, win32/makenoas.w32 (Cosmin)\n132. Changed most 64-bit size/offset variable declarations (like zoff_t)\n     into \"unsigned\" type (like uzoff_t), for better backward compatibility\n     with non-ZIP64_SUPPORT setups where \"ulg\" was used for these variables.\n     deflate.c, fileio.c, globals.c, trees.c, vms/vms_pk.c, win32zip.c,\n     zip.c, zip.h, zipfile.c, zipup.c (Christian)\n133. Add (ulg) cast to strstart in flush_block.  deflate.c (Christian)\n134. Updated Win32 LARGE_FILE_SUPPORT setup for Watcom and MinGW.\n     tailor.h, win32/osdep.h (Christian)\n135. Add attempt count to tempname().  fileio.c (Christian)\n136. Fixed size counter handling in debug code for Zip64. trees.c (Christian)\n137. Moved cryptnote display text definition into revision.h, like was done\n     in Zip 2.31.  zip.c, revision.h (Christian)\n138. Add ZCONST.  fileio.c (Christian)\n139. Removed earlier change in trash() where ASCII-containing iname was\n     searched for native-coded '/' characters.  [Added note but left as\n     changed 5/20/05 EG]  zipfile.c (Christian)\n140. Change zipup size error message to use zip_fzofft().  zipup.c (Christian)\n141. Updated win32/makefile.wat to enable Zip64 support and use directory\n     for intermediate files.  (Christian)\n142. Change fcount and zcount from ulg to extent as extent is used internally,\n     but Zip64 standard supports up to ulg.  Add note to zip.h.  globals.c,\n     zip.h (Christian)\n143. Define NO_W32TIMES_IZFIX in compile options when appropriate. Add\n     version information for USE_ZLIB compiler option.  zip.c (Christian)\n144. Add support for SIGABRT, SIGBREAK, SIGBUS, SIGILL, and SIGSEGV signals.\n     zip.c (Christian)\n145. Add display-usize option to show uncompressed size.  zip.c (Ed)\n146. Add many descriptions to options table.  zip.c (Ed)\n147. Remove -R from help screen as on extended help screen.  zip.c (Ed)\n148. Add basics to extended help.  zip.c (Ed)\n149. Fix checks in scanzipf_reg() for empty file since cenbeg now unsigned.\n     Change buffer from t to b in small big check.  Back up after small\n     zip big archive check.  zipfile.c (Ed)\n150. Change Zip64 not supported warning in scanzipf_reg().  zipfile.c (Ed)\n151. Fix bug where local and central headers were not matching when compiled\n     with NO_LARGE_FILE_SUPPORT.  Restored order of zlist structure elements\n     to match order of local header as scanzipf_reg() compares it as an\n     array of bytes to the local header.  Gag.  It needs fixing but at least\n     it works as intended now.  zip.h, zipfile.c (Ed)\n152. Minor fix from 10000 to 10 K for WriteNumString().  util.c (Ed)\n153. Add overflow check to file_read().  zipup.c (SMS)\n154. Add parameter p1 product specification.  vms/collect_deps.com (SMS)\n155. VMS changes.  vms/descrip_mkdeps.mms (SMS)\n156. Change zoff_t to uzoff_t and unsigned int to size_t.  vms/vms_im.c,\n     vms/vms_pk.c (SMS)\n157. Fix ; that was : at end of line.  Fix DisplayNumString() prototype.\n     zip.h (Ed)\n158. Get rid of leading blanks in DisplayNumString().  util.c (Ed)\n159. Reset dot_count each file.  zipup.c (Ed)\n160. Minor changes to extended help.  zip.c (Ed)\n161. Move defines into DEFINED_ONCE block.  api.h (Mike)\n162. Add Still Remaining And Planned For Zip 3.0 section.  WhatsNew (Ed)\n163. Delete quotes around CHANGES.  Readme (Ed)\n164. Add -lf, open file at path and use for logging, -la, append to\n     existing logfile, and -li, include informational messages, options.\n     globals.c, zip.h, zip.c (Ed)\n165. Update extended help to include logging.  zip.c (Ed)\n166. Add support for required short option value in form -o=value as optional\n     does.  fileio.c (Ed)\n167. If bytes_total is smaller than bytes_so_far for some reason then display\n     negative of bytes_to_go.  This can happen if files grow in size after all\n     the sizes are initially added up.  zip.c (Ed)\n168. Use usize from filetime for adding to bytes_total when updating instead\n     of size in old entry.  zip.c (Ed)\n169. Change status counts files_so_far and bytes_so_far to include bad files\n     so the status counts end at the end but add bad_files_so_far and\n     bad_bytes_so_far to track bad files.  After minor fixes it looks like\n     the counts remaining at the end are correct, even when some files are\n     not readable.  Update bad file warnings.  zip.c, zip.h, globals.c,\n     zipup.c (Ed)\n170. Add uq for unsigned q in zipup().  Initialize z->len in case an error\n     later so have a valid size.  zipup.c (Ed)\n171. Check noisy in DisplayRunningStats() so logging is independent of it.\n     zip.c (Ed)\n172. Add check in DOS for windows and if running DOS version on Windows warn\n     user.  zip.c, msdos/msdos.c, msdos/osdep.h (Johnny)\n173. Add errno.h for strerror(errno) call.  zip.c, zipup.c (SMS)\n174. Fix log problem if using -q option.  zipup.c (Ed)\n175. Change \"Far char\" to \"char Far\" as Far is a qualifier not for the char\n     type but the storage allocation of the array.  fileio.c (Christian)\n176. Update note on extent.  globals.c (Christian, Ed)\n177. Remove extra USE_ZLIB.  zip.c (Christian)\n178. Add note for the OEM_RUSS '/' bug.  Need to look at later as it seems\n     the Russian bug remains unfixed.  zipfile.c (Christian, Ed)\n180. So byte counts always come out even, create good_bytes_so_far to\n     count bytes read in and convert bytes_so_far to use the counts\n     from the initial scan.  If files change during the zip operation\n     good_bytes_so_far will change and not match bytes_so_far.\n     zip.h, globals.c, zip.c (Ed)\n181. Changes to extended help.  zip.c (Ed)\n182. Update WhatsNew (Ed)\n183. Update DLL resource copyright.  windll.rc, windll.aps (Ed)\n184. Add directory search improvements to Win32 (within recursion, reuse\n     attribs from directory lookup to avoid calling stat()).  Add\n     getd_attribs(), procname_win32().  win32/win32zip.c (Johnny)\n185. Cache result of IsFileSystemOldFAT() to avoid repetitive system calls\n     for identical information.  win32/win32.c  (Johnny)\n186. Add optimization to dosmatch(): apply alternate shortcut code when the\n     pattern to match consists of one multichar wildcard ('*') followed\n     by a fixed string.  util.c (Johnny)\n187. Move DOS check_for_windows() checks to Help and Version and errors\n     only.  Shorten message to one line.  zip.c, msdos/msdos.c (Ed)\n188. Define WIN32_OEM to enable oem ansi conversions for more than RSXNT.\n     Not yet fully implemented.  win32/win32.c, win32zip.c, zip.c,\n     zipfile.c (Ed)\n189. Directory search improvements for MSDOS.  msdos/msdos.c (Johnny)\n190. Add caching of directory information.  If pattern is just *string no\n     need to recurse.  win32/win32.c (Johnny)\n191. If wild_stop_at_dir then do recurse to handle cases like a/b/*.txt.\n     win32/win32.c (Ed)\n192. Additional improvements to directory search speedups, including\n     a) MSDOS port fixes for Turbo C++ compiler\n     b) In both Win32 and MSDOS, change getDirEntryAttr() into macro,\n        saving one function call overhead\n     e) Add explaining comment to optimized procname_{local} code\n     f) In util.c, move \"*literal\" pattern-matching optimization from\n        dosmatch() to recmatch(). Advantages:\n        - optimization used for all systems\n        - optimization applied to all occurences where a \"*\" is last wildcard\n          in pattern\n        - \"dosmatch()\" only preconditoning wrapper for matching workhorse\n          \"recmatch()\", it should not implement matching algorithms itself\n        - optimization not applied for WILD_STOP_AT_DIR option\n     g) >>>disabled<<< \"*literal\" optimization for all MBCS-aware environments,\n        because suspect that supplied optimization code is not MBCS-clean\n        (for details see the comment within the patch), so IS NOT USED for\n        win32 port!  Can force activation of match optimization by specifying\n        conditional compilation symbol TEST_FOR_MBCS_CLEAN.\n     (Christian)\n193. Add and move comments, implement changes for directory search improvements\n     in Zip 3.0 util.c (Ed)\n194. In win32/win32.c, IsFileSystemOldFAT(), add declarations of static caching\n     variables where missing to fix win32 port compilation bug (Christian)\n195. Correct changed arguments in RSXNT-only character set conversion\n     call.  win32/win32zip.c (Christian)\n196. Implement Directory Search improvements from Zip 2.32.  win32/win32zip.c\n     (Johnny, Ed)\n197. Debian Bug #312090 fix.  Reworded man page to give multiple examples of\n     recursion, not just zip -r foo foo.  man/zip.1 (Ed)\n198. Change \"-Aa -D_HPUX_SOURCE +e\" to -Ae for HP.  \"HP-UX with the HP compiler\n     and on AIX 4.2.0. AIX 5.1 with gcc-3.4.3 (32-bit) and Darwin built fine\n     - though AIX 5.1 needed CC=gcc make -e ... to find gcc.  According to the\n     HP-UX man page -Ae is equivalent to -Aa -D_HPUX_SOURCE +e it seems the\n     +e is needed and -Ae is more terse anyway.\"  Expression generated before\n     was too long.  unix/configure (Rodney Brown)\n199. Add support for osf4.0f that does not have fseeko or ftello but has 64-bit\n     fseek and ftell though.  tailor.h (Rodney)\n200. Fix unsigned char to char in recmatch(), add casts for compares.  util.c\n     (Ed)\n201. Fix for alpha off_t long long.  unix/osdep.h (Rodney)\n202. Change shmatch() from uch to char and change parameters to recmatch().\n     Change dosmatch().  util.c (SMS, Rodney, Ed)\n203. Add local for DisplayRunningStats().  zip.c (Rodney, Ed)\n204. Disable unused append_ubyte_to_mem().  Fix error messages in other append.\n     zipfile.c (Rodney, Ed)\n205. Delete unused getDirEntryAttribs().  msdos/msdos.c (Christian)\n206. Change warning when running msdos version on Windows.  msdos/msdos.c (Ed)\n207. Change recmatch() to support MBCS matching.  util.c (Christian)\n208. Update WhatsNew (Ed)\n209. Update Readme (Ed)\n210. Format Readme to fit in 80 character lines (SMS, Ed)\n211. Rename install.vms to install_vms.txt.  vms/install_vms.txt (SMS)\n212. Add reference to vms/install_vms.txt in INSTALL (SMS)\n213. Update INSTALL (Ed)\n214. Remove ALT_NEXTBYTE and Building UnZip sections as no longer needed.\n     vms/notes.txt (SMS, Ed)\n215. Add note to TODO (Ed)\n216. Update Makefile message to suggest using generic.  unix/Makefile (Ed)\n217. Update text output of manual.  zip.txt (Ed)\n218. Update VMS section.  INSTALL (SMS, Ed)\n219. Minor changes in vms/install_vms.txt (SMS, Ed)\n220. Update VMS install information.  INSTALL, vms/install_vms.txt (SMS, Ed)\n221. Do not use _stati64 under Cygwin.  win32/osdep.h (Cosmin)\n222. Add note to Makefile to use generic first.  unix/Makefile (Ed)\n223. Add Test option for VMS CLI.  vms/cmdline.c (SMS, ?)\n224. Add noconfirm to deletes, define symbol edit.  vms/descrip.mms (SMS)\n225. Changes to vms/install_vms.txt (SMS)\n226. Add note on symbols to VMS.  INSTALL (SMS)\n227. Update license headers.  vms/osdep.h, vms/vms.h, vms/vmsmunch.c,\n     vms/zipup.h, vms/vmszip.c, vms/vms.c, vms/vms_im.c, vms/vms_pk.c,\n     vms/command.c (Ed)\n228. Add stsdef.h include for VMS and convert unzip test return to VMS\n     result for VMS.  zip.c (SMS)\n229. Add const to ziperr().  amiga/amiga.c (Paul)\n230. Clean up makefile.  amiga/makefile.azt (Paul)\n231. Don't try Amiga large file support.  amiga/osdep.h (Paul)\n232. Add note on -V and -VV.  vms/notes.txt (SMS)\n233. Small update.  vms/zip_cli.help (SMS)\n234. Format Windows warning message.  msdos/msdos.c (Christian)\n235. Format changes.  util.c (Christian)\n236. Update VMS.  INSTALL (SMS)\n237. Add creation of intermediate object directories.  msdos/makefile.wat\n     (Christian)\n238. Add void * cast.  msdos/msdos.c (Christian)\n239. Add include for mktemp().  msdos/osdep.h (Christian)\n240. Fix __RSXNT__ and WIN32_OEM define blocks.  win32/win32.c (Christian)\n241. Fix __RSXNT__ and WIN32_OEM define blocks.  win32/win32zip.c (Christian)\n242. Add != NULL to check.  zip.c (Christian)\n243. Fix WIN32_OEM.  zipfile.c (Christian)\n---------------------- October 11th 2005 version 3.0f01 ----------------------\n(the internal betas may be merged later)\n 1. Add DSEG for Watcom data segment.  msdos/makefile.wat (Christian)\n 2. Add -zq and use assembler.  os2/makefile.os2 (Christian)\n 3. Update header.  os2/match32.asm (Christian)\n 4. Change len from int to unsigned int.  os2/os2.c (Christian)\n 5. In GetLongPathEA() limit tempbuf to CCHMAXPATH.  os2/os2.c (Christian)\n 6. Add DWATCOM_DSEG to use data segment.  win32/makefile.wat (Christian)\n 7. Update header and add DGROUP.  win32/match32.asm (Christian)\n 8. Add UNICODE_SUPPORT define.  zip.h, zip.c (Ed)\n 9. Add oname to f and z structs for the display name to use in messages.\n    Change z->zname to z->oname in messages.  fileio.c, zip.c, win32zip.c,\n    zipup.c, zipfile.c, zip.h (Ed)\n10. Move multi-byte defines to make global (they were needed with wide\n    characters but that was taken out and left them where they are).\n    fileio.c, zip.h\n11. Add copy_args(), free_args(), and insert_arg() to create copy of argv\n    that can free() and to support inserting \"@\" in get_option for lists.\n    fileio.c, zip.h\n12. Insert arg \"@\" after list if not followed by option.  fileio.c\n13. Add args variable and copy argv to args so can use insert_arg(). zip.c\n14. Add MKS Korn Shell note.  zip.c\n15. Change cast of option in add_filter() calls from char to int. zip.c\n16. Implement multi-byte version of Unicode support.  To support Win32 NT\n    wide calls will require additional work not planned for this release.\n    Changes include (Ed):\n    - Add use_wide_to_mb_default flag.  globals.c, zip.h\n    - Add compiler UNICODE_SUPPORT version information.  zip.c\n    - Add uname to f and z structs for UTF-8 name. zip.c\n    - Moved some defines out of ZIP64 section.  zipfile.c\n    - Add define UTF8_PATH_EF_TAG for Unicode Path extra field.  Currently\n      the tag is 0x7075 which is 'u' 'p' for Unicode path and seems\n      free according to the AppNote.  The extra field is\n        tag (2 bytes 'u' 'p')\n        size (2 bytes)\n        Unicode Path size (2 bytes)\n        unused (2 bytes set to 0)\n        unused (2 bytes set to 0)\n        Unicode path (variable)\n      The unused locations also serve as a check in case the tag is in\n      use already.\n    - Add add_Unicode_Path_local_extra_field() and\n      add_Unicode_Path_cen_extra_field() functions. zipfile.c\n    - Add read_Unicode_Path_entry() function. zipfile.c\n    - Set uname and oname in scanzipf_ref(). zipfile.c\n    - Add define wide_to_mb_default.  Add zchar but not used. win32/osdep.h\n    - Add wide command line reading but don't use. win32/win32.c\n    - Add port functions for Unicode, including local_to_utf8_string(),\n      wide_to_escape_string() (for converting a wide character that can't be\n      converted to mb in the local character set to a reversable escape string),\n      escape_string_to_wide(), wide_to_local_string(), local_to_display_string()\n      (for creating the display version of name), utf8_to_local_string(),\n      local_to_wide_string(), wide_to_utf8_string() (NOT IMPLEMENTED), and\n      utf8_to_wide_string() (NOT IMPLEMENTED).  win32/win32.c\n    - Implement attempt at escape function.  Whenever a wide character can't\n      be mapped to the local character set, this function gets called.\n      Currently the wide character is converted to a string of hex digits.\n      If the wide can fit in 2 bytes then the form #1234 is used.  If not,\n      the 4-byte form #L12345678 is used.\n    It compiles but needs the utf8 functions implemented.  Also needs testing\n    in a multi-byte environment and only Windows is implemented so need to at\n    least do Unix. (Ed)\n17. Update freeup() to include uname and oname.  zip.c\n18. Move define wide_to_mb_default so default for all is '_'. zip.h (Ed)\n19. No changes needed to osdep.h and update unix/unix.c but not tested. (Ed)\n---------------------- October 19th 2005 version 3.0f02 ----------------------\n 1. Remove null value check for split_size as get_option() already checks.\n    zip.c (Ed)\n 2. Update f$search().  vms/descrip.mms (SMS)\n 3. Save parse name before search and use that on failure.  Change name parsing\n    in ziptyp() to solve a problem with search-list logical name device directory\n    specs.  vms/vms.c (SMS)\n 4. Compile in UNICODE_SUPPORT if have wchar_t and mbstowcs().  unix/configure (Ed)\n 5. Move Unicode defines to zip.h and functions to fileio.c so generic.  Create\n    a new OEM function for Windows.  fileio.c, zip.h, tailor.h, win32/win32.c (Ed)\n 6. Add UTF-8 functions.  fileio.c (Paul)\n 7. Convert Unicode functions to use zwchar defined as unsigned long for wide\n    char.  fileio.c, zip.h (Ed)\n 8. Add wchar_t check for Unix.  unix/configure (Ed)\n 9. Add default when zwchar (4 bytes) is too big for wchar_t (2 bytes).  zip.h (Ed)\n10. Allow for states for wide characters but surrogates not done.  fileio.c (Ed)\n11. Update WhatsNew (Ed)\n---------------------- December 16th 2005 version 3.0f03 ----------------------\n 1. Fix broke encryption when ZIP64_SUPPORT enabled by accounting for need for\n    data description when encrypting.  Data description is not required for\n    encryption (WinZip does not use one) but seems needed by Zip for some reason.\n    zipfile.c (Ed)\n 2. Add function bfwrite() to do buffered fwrite().  Most output already is\n    written by zfwrite used by crypt.c which now calls bfwrite.  All splitting\n    and new byte counts are done in bfwrite.  fileio.c (Ed)\n 3. Move some functions out of ZIP64_SUPPORT defines for use with UNICODE_SUPPORT.\n    zipfile.c, zip.h (Ed)\n 4. Add is_ascii_string() and only create Unicode extra field if z->iname is\n    not ascii.  zipfile.c, zip.h, fileio.c,  (Ed)\n 5. Add parameter rewrite to putlocal() to note when rewriting bytes so the bytes\n    rewritten are not counted in output totals.  zipfile.c, zip.h (Ed)\n 6. Handle VMS ... wildcard.  util.c (SMS)\n 7. Make tempzip file name global.  zip.c, globals.c, zip.h (Ed)\n 8. Add out_path global and -O path option to allow the output archive to have a\n    different name than the input archive, if there is one.  This allows\n    updating a split archive, since output to the same split name would otherwise\n    be complicated and not user friendly.  Use out_path for output.  zip.h,\n    zip.c, globals.c (Ed)\n 9. Many output functions that had output file y as parameter, such as zipup(),\n    zipcopy(), putlocal(), putcentral(), and putend(), now do not as y is\n    now global.  This allows changing y as splits are created.  zip.c (Ed)\n10. Add function zipmessage() for writing messages like zipwarn() but are\n    informational.  zip.c (Ed)\n11. Minor changes to help.  zip.c (Ed)\n12. Add SPLIT_SUPPORT to version output.  zip.c (Ed)\n13. Add rename_split() to rename and set attributes for a split.  zip.c (Ed)\n14. Add set_filetype() to set attributes of split.  zip.c (Ed)\n15. Change variable a (holds attributes) to zipfile_attributes and make global.\n    zip.c, zip.h, globals.c (Ed)\n16. Add key_needed flag for encryption and move setting key to after\n    command line processed.  zip.c (SMS)\n17. Initialize dot size using default only if dot_size not set.  zip.c (Ed)\n18. Change command line processing so that last -P or -e is used.  zip.c\n    (Ed)\n19. Fix broke writing of 4-byte spanning signature at the beginning of the archive\n    if splitting.  zip.c (Ed)\n20. Use bfcopy() instead of fcopy() to copy archive beginning.  bfcopy() uses\n    global y.  zip.c (Ed)\n21. It looks like tempzf is no longer used.  zip.c (Ed)\n22. Account for SUNPRO_C and DECC_VER.  Change SPARC to Sparc.  unix/unix.c (SMS)\n23. Remove GNUC.  vms/cmdline.c (SMS)\n24. Change case of system calls.  vms/vms.c (SMS)\n25. Add fix for VMS ... matching, but may change Zip to avoid ex2in() and in2ex()\n    for pattern matching in future.  vms/vmszip.c (SMS)\n26. Remove /NODIRNAMES and /DIRNAMES from VMS help.  vms/zip_cli.help (SMS)\n27. Define new globals zip64_eocd_disk, zip64_eocd_offset, current_local_tempname,\n    bytes_this_split, and bytes_this_entry for splits.  globals.c, zip.h (Ed)\n28. Add SUNPRO C and DEC C compile checks.  unix/configure (SMS)\n29. Add CFLAGS_NOOPT for removing optimization for configure.  unix/Makefile (SMS)\n30. Modify crypthead() to use bfwrite().  crypt.h, crypt.c (Ed)\n31. Modify zfwrite() to use global output file.  crypt.h, crypt.c (Ed)\n32. Modify zfwrite() when no encryption to use bfwrite().  crypt.h (Ed)\n33. Add bfcopy() to copy to y.  fileio.c (Ed)\n34. Add close_split() and bfwrite() for splits.  fileio.c (Ed)\n35. Add is_ascii_string() to check if UTF-8 extra field is needed.  fileio.c (Ed)\n36. Change Unicode escape of 2-byte wide from #1234 to #U1234.  fileio.c (Ed)\n37. Add read_Unicode_Path_entry() to read the UTF-8 path extra field.  zipfile.c (Ed)\n38. Latest Unicode Path extra field format is\n      1 byte     Version of Unicode Path Extra Field\n      2 bytes    Name Field Checksum\n      variable   UTF-8 Version of Name\n39. Use CRC-32 for Unicode Path Checksum and AND halves.  zipfile.c (Paul)\n40. Add Unicode Path Checksum check to make sure extra field applies to Name field\n    still.  zipfile.c (Christian)\n41. Move get_extra_field() out of Zip64 block and make available for splits.\n    zipfile.c (Ed)\n42. Check in putlocal() using is_ascii_string() and don't create Unicode path\n    extra field if name is ASCII characters.  zipfile.c (Ed)\n43. If local header for split is on another disk and using split method 1, close\n    that split in putlocal() after rewrite local header.  zipfile.c (Ed)\n44. Fix data descriptor bug when encrypting where putextended() did not handle the\n    not Zip64 case, which mostly only happens now for encryption.  zipfile.c (Ed)\n45. Check for ASCII name using is_ascii_string() in putcentral() for Unicode path\n    extra field.  zipfile.c (Ed)\n46. Instead of single disk values, update putend() to use real split values for\n    current_disk, cd-start_disk, cd_entries_this_disk, cd_start_offset,\n    zip64_eocd_disk, zip64_eocd_offset, and current_disk and allow for\n    needing Zip64 if exceed standard max values for current_disk, cd_start_disk,\n    cd_entries_this_disk, total_cd_entries, and cd_start_offset.  zipfile.c (Ed)\n47. Use current_local_offset and current_local_disk for z->off and z->dsk in\n    zipup().  zipup.c (Ed)\n48. Fix bug where force_zip64 was used to determine descriptor size but can have\n    Zip64 entry without force_zip64 so use zip64_entry.  zipup.c (Ed)\n49. Change the p - o != s compression size test for splits to bytes_this_entry\n    != (key ? s + 12 : s) and avoid ftell() in split.  zipup.c (Ed)\n50. If local header is on a previous split and split method 1 do the seek on that\n    split to update header.  zipup.c (Ed)\n51. For streaming, only force Zip64 if reading stdin and writing a non-seekable\n    device.  In other cases can detect either the input file size and set Zip64\n    if needed or seek in the output to update the local headers.  zipup.c,\n    zipfile.c, zipup.c (Ed)\n52. Allow creation of stored archives with descriptors for testing.  Currently\n    they can't reliably be read but this is planned.  zipup.c, zipfile.c, zip.c\n    (Ed)\n53. Update help, adding in -e, -P, -s splitsize, -sp, and -sv options.  zip.c (Ed)\n54. Spelling fix in zipsplit man page.  man/zipsplit.1, zipsplit.txt (Ed)\n55. New option -sv and variable noisy_splits to enable verbose splitting.\n    Default is to quietly create splits, unless -sp set to pause between splits.\n    zip.h, zip.c, globals.c, fileio.c (Ed)\n---------------------- December 23rd 2005 version 3.0f04 ----------------------\n 1. Move inlined text-vs-binary checks from file_read() into a separate,\n    new function named is_text_buf().  zipup.c, util.c, zip.h (Cosmin)\n 2. Fix calls to putlocal to remove the removed dest parameter.  crypt.c (Ed)\n 3. Add get_split_path() to get the path for a split given the disk number.\n    fileio.c, zip.h (Ed)\n 4. Change formatting of zipmessage() to remove tabbing and add formatting\n    to call to zipmessage().  fileio.c, zip.c (Ed)\n 5. Initialize many variables such as y and tempzip.  zip.c, fileio.c,\n    zipfile.c (Ed)\n 6. Add loop to pause during split method 2 to allow changing disk or changing\n    the path for the next split.  fileio.c (Ed)\n 7. If after starting new split there is not enough room for the remaining buffer\n    for split method 1 display error and exit and for split method 2 we can\n    display a warning and user can replace disk or change path.  fileio.c (Ed)\n 8. Add list to store input file arguments using add_name() to add the name to\n    filelist_struc filelist and then process the names after the input archive\n    is read.  zip.c (Ed)\n 9. Fix infinite loop when opening a log file whose name contains multiple '/'.\n    zip.c (Cosmin)\n10. Move split size message lower and only output if option sv sets\n    noisy splits.  zip.c (Ed)\n11. Set y to output file, remove output file from zipcopy(), putlocal(),\n    putcentral(), and putend().  zipsplit.c, zipnote.c, zipcloak.c (Ed)\n12. Add code for not SPLIT_SUPPORT case.  zipfile.c, zipup.c (Ed)\n13. Prepend '-' to commands from target clean.\n    win32/makefile.w32, win32/makenoas.w32, win32/makefile.bor (Cosmin)\n14. Must not call putenv() in iz_w32_prepareTZenv() under Cygwin.\n    win32/osdep.h (Cosmin)\n15. Add browse info in Visual C++ 6 project.  win32/vc6/zip*.dsp (Cosmin)\n---------------------- December 27th 2005 version 3.0f05 ----------------------\n 1. Add proposed changes to License (Ed)\n 2. Fix -l corruption bug by using memcpy() instead of wrongly changing the\n    buffer pointer.  Fix was left out of last beta.  zipup.c (Cosmin)\n 3. Fix get_split_path() parameter.  zip.h (SMS, Ed)\n 4. Add -dg and display_globaldots to display dots globally for entire archive\n    instead of for each file.  Is not affected by noisy flag.  globals.c,\n    zip.h, zip.c, zipup.c, fileio.c (Ed)\n 5. Make dot_count and dot_size uzoff_t, dot_count because with global dots\n    dot_count does not reset and with terabyte files the number of buffers\n    could exceed 2G, dot_size to allow use of ReadNumString() to read number.\n    zip.c, zip.h, globals.c (Ed)\n 6. Add Deletion to help.  zip.c (Ed)\n 7. Fix delete date.  zip.c (Ed)\n 8. For streaming, need to assume Zip64 if writing a non-seekable device so\n    extra field for Zip64 is created if needed.  zipup.c, zipfile.c, zipup.c (Ed)\n 9. Add remove_local_extra_field() and remove_central_extra_field().\n    zipfile.c (Ed)\n10. Remove disabled copyright from license().  zip.c (Ed)\n11. Clean up recent changes.  zip.c, zipfile.c, fileio.c, zip.h, zipup.c (Ed)\n12. Create scanzipf_regnew() for new file scan.  zipfile.c (Ed)\n---------------------- December 29th 2005 version 3.0f06 ----------------------\n 1. Change dot_size and dot_count from uzoff_t to zoff_t to allow use of\n    negative flag values.  globals.c, zip.h (SMS, Ed)\n 2. Remove file parameter to bfwrite() in putend().  zipfile.c (SMS, Ed)\n 3. Add back code for not SPLIT_SUPPORT to putend().  zipfile.c (SMS, Ed)\n 4. Change tag from ush to ulg in remove_local_extra_field() and\n    remove_central_extra_field() to avoid parameter problems.  zipfile.c (Ed)\n 5. Add allow_empty_archive to flag when want to create an empty archive.\n    globals.c, zip.h (Ed)\n 6. Set allow_empty_archive when using -i and expecting an archive to be\n    created.  This is in response to the 2/14/05 email.  zip.c (Ed)\n 7. Make before and after variables that hold the dates of files to\n    process or delete global so can use them in scanzipf_regnew().  zip.h,\n    zip.c, globals.c (Ed)\n 8. Change scanzipf_regnew() to be based on scanzipf_fix() which seems closer.\n    Still have not coded the new regular zipfile reader.  zipfile.c (Ed)\n 9. For new reader first get add list and then read old archive and filter\n    as reading old entries.  zip.c, zipfile.c (Ed)\n10. Define USE_NEW_READ to turn on using new reader, which is being\n    created.  This allows all to work while the new reader is being worked\n    on.  zip.c, zipfile.c (Ed)\n---------------------- January 9th 2006 version 3.0f07 ----------------------\n 1. Remove dest parameter from crypthead() and zipcopy().  crypt.c (SMS, Ed)\n 2. Change -ds to handle dots for as small as every 32 KB.  zip.c (Ed)\n 3. Add ask_for_split_write_path() and ask_for_split_read_path()  for\n    asking where to put the next write split and for locating the next\n    read split.  zip.h, fileio.c (Ed)\n 4. Add in_path to track where reading splits from. zip.h, globals.c, zip.c (Ed)\n 5. Update copyright date on changed files to include 2006 (Ed)\n 6. Replace stderr with mesg for most output messages.  deflate.c, fileio.c,\n    trees.c, util.c, zip.c, zipcloak.c, zipfile.c, zipnote.c, zipsplit.c\n 7. Add mesg_line_started to track if need new line on mesg output and update\n    zipmessage() and zipwarn() to use it.  Set mesg_line_started to 1 when\n    newline not last character written to mesg and 0 when it is.  deflate.c,\n    zip.h, zip.c, globals.c, zipup(), fileio.c (Ed)\n 8. Include base_path as parameter for get_split_path().  fileio.c (Ed)\n 9. Account for VMS version in split path.  Add vms_file_version().  fileio.c,\n    zip.c, vms/vms.c, vms/vms.h (SMS)\n10. Create crc16f() to create ANDed halves crc32 for Unicode using copy\n    of crc32() but may change to use main copy.  zipfile.c, zip.h,\n    fileio.c (Ed)\n11. Close in_path and out_path in finish() and ziperr().  zip.c (Ed)\n12. Change perror() to strerror() and print to mesg in ziperr().  zip.c (Ed)\n13. Add find_next_signature() to find the next signature when reading a\n    zip file.  zipfile.c (Ed)\n14. Add find_signature() to find a given signature from current point in\n    archive.  zipfile.c (Ed)\n15. Add at_signature() to check if at a given signature in archive.\n    zipfile.c (Ed)\n16. Changes to scanzipf_regnew() but far from done.  zipfile.c (Ed)\n17. Changes to readzipfile() to close input archive file and allow new\n    zipfile reader to open and close files as goes through splits.\n    zipfile.c (Ed)\n18. Change -s to default to MB and set minimum split size to 64k.\n    zip.c (Ed)\n19. Add link to user32.lib for CharToOem().  makefile.w32, makenoas.w32\n    (Cosmin)\n20. Remove unused Z64_EFPos.  globals.c (Ed)\n---------------------- February 13th 2006 version 3.0f08 ----------------------\n 1. Move option checks before any work is done.  zip.c (Ed)\n 2. Update bfcopy() to handle reading splits and remove input file\n    parameter and use global in_file.  fileio.c (Ed)\n 3. Change ask_for_split_read_path() to allow user aborting.  fileio.c (Ed)\n 4. Change get_split_path() to use standard file extensions from most\n    recent AppNote of .z01, .z02, ..., .z99, .z100, .z101, ... fileio.c (Ed)\n 5. Change is_ascii_string to use 0x7F for ASCII detection.  fileio.c (Ed)\n 6. Add copy_only global for when -O is used to change the format of an\n    archive without changing the contents.  This allows for converting an\n    archive to a split archive for instance.  The global copy_only is used\n    to output status information for copies when normally copied files\n    have no status messages.  globals.c (Ed)\n 7. Add in_file, split_path, total_disks, current_in_disk, and\n    current_in_offset as globals to track reading splits.  zip.h,\n    globals.c (Ed)\n 8. Update copyright date.  revision.h (Ed)\n 9. Close in_file if open in finish().  zip.c (Ed)\n10. Add -O (big o) to extended help.  zip.c (Ed)\n11. Remove readzipfile() from zipstdout() and use main call later down.\n    zip.c (Ed)\n12. Move archive reading and file scanning after command line checks.\n    zip.c (Ed)\n13. If -O out_zip and so have_out is set then set copy_only and allow\n    copying instead of error message *Nothing to do*.  zip.c (Ed)\n14. If zipbeg is just 4 bytes and spanning then assume is spanning\n    signature and set zipbeg to 0 to ignore.  zip.c (Ed)\n15. Don't open initial write test as modify if have_out is set and so have\n    a separate output file.  zip.c (Ed)\n16. If zipbeg is 0 and nothing at beginning of archive to copy then don't\n    open input file until zipcopy() does.  zip.c (Ed)\n17. If stuff at beginning then copy and close input file.  Should be able\n    to keep it open but easier to close it and let zipcopy() reopen it.\n    zip.c (Ed)\n18. Add status message when copy_only set so something is displayed.\n    zip.c (Ed)\n19. Instead of closing x at bottom close in_file.  The variable x was used\n    inconsistently and it seemed easier to make in_file global instead.\n    Then again y remains the global output variable.  zip.c (Ed)\n20. Update copyright.  zipnote.c, zipsplit.c, zipcloak.c (Ed)\n21. Change adjust_zip_local_entry() to return 1 if the entry is Zip64 and\n    0 if not.  This is needed to know how large the extended local header\n    is later.  zipfile.c (Ed)\n22. Add read_Unicode_Path_local_entry() to read the local version of the\n    Unicode Path extra field.  zipfile.c (Ed)\n23. Handle disk in adjust_zip_central_entry().  zipfile.c (Ed)\n24. Change USE_NEW_READ to SPLIT_SUPPORT as splits seems to be stable more\n    or less.  zipfile.c (Ed)\n25. Add is_signature() to compate signatures.  zipfile.c (Ed)\n26. Create scanzipf_fixnew().  It should look like scanzipf_regnew().\n    zipfile.c (Ed)\n27. Change scanzipf_regnew() to read the central directory and create zlist\n    and handle reading traditionally.  Allows using central directory\n    information, in particular file sizes, in zipcopy() while reading\n    entries.  Use global in_file instead of f for input file and set to NULL\n    when not a valid file so finish() only tries to close it if needed.\n    Check to make sure the End Of Central Directory record found is infact\n    the last one in case a stored archive is in the last 64 KB.  Refuse\n    to update a split archive but recommend using -O instead.  zipfile.c (Ed)\n28. Change readable check in readzipfile() to require input archive to exist\n    if using -O out_archive.  zipfile.c (Ed)\n29. Change putlocal() to not create a Zip64 extra field unless needed and\n    on rewriting the local header to remove Zip64 extra field if was created\n    but not needed.  Add check if assumed entry does not need Zip64 but does,\n    meaning probably the uncompressed size is less than 4 GB but the\n    compressed size is over 4 GB.  zipfile.c (Ed)\n30. Change zipcopy() to use the global in_file and y files and to open and\n    close read splits as needed.  Checks the local header against the\n    central directory header to verify same file, which should be as using\n    the disk and offset values from the central directory.  Update disk and\n    offset in central directory.  zipfile.c (Ed)\n31. Change out_path and out_len to base_path and base_len in\n    get_split_path().  fileio.c (SMS)\n32. Update command line options for VMS to include verbose splitting.\n    vms/zip_cli.cmd, vms/cmdline.c (SMS)\n33. Handle HP.  unix/unix.c (SMS)\n34. Add adler16() checksum function.  util.c (Cosmin)\n35. Use FILE_FLAG_BACKUP_SEMANTICS and a less demanding access mode\n    in CreateFile() when retrieving file attributes.  Fixes a problem\n    when adding a directory entry from an NTFS or a CDFS partition\n    (i.e. one that stores timestamps using universal time), and the\n    directory timestamp is not the same daylight savings time setting.\n    The effect is an offset in the timestamp by one hour, if zip is\n    built using NT_TZBUG_WORKAROUND. The problem is not exposed,\n    however, if NO_W32TIMES_IZFIX is defined.  win32/win32.c (Cosmin)\n---------------------- March 19th 2006 version 3.0f09 ----------------------\n 1. Fix encryption problem where a large file with uncompressable data\n    can cause deflate to store bad data.  See crypt.c for details.\n    Thanks to the nice people at WinZip for finding and providing the\n    details of this problem.  crypt.c (Ed)\n 2. Add note at top of Extended Help to refer to the Zip Manual.  zip.c\n    (Ed)\n 3. Update extended help for delete.  zip.c (Ed)\n 4. Change crypthead() to use buffer and bfwrite() which is split aware.\n    crypt.c (Ed)\n 5. Create SPLIT_SUPPORT version of zipcloak() and zipbare() and read\n    local header rather than assume data using central header.  crypt.c (Ed)\n 6. Change zfwrite() to use global output file y.  crypt.c (Ed)\n 7. Remove in and out parameters from zipcloak() and zipbare() for\n    splits.  crypt.h, zipcloak.c (Ed)\n 8. Change get_split_path() to get_in_split_path() and get_out_split_path().\n    zipfile.c, fileio.c, zip.h (Ed)\n 9. Change crc32f() to crc32u().  fileio.c, zip.h (Ed)\n10. Add encryption overwrite fix to copy_block() and remove from zfwrite().\n    crypt.c, tree.c (Ed, Christian)\n11. Add note on bug fix.  WhatsNew (Ed)\n12. Add copy_only mode.  zip.c (Ed)\n13. Make SPLIT_SUPPORT the default.  zip.h (Ed)\n14. Add set_filetype(), rename_split(), and zipmessage().  zipcloak.c,\n    zipnote.c, zipsplit.c (Ed)\n15. Add long option support.  zipcloak.c (Ed)\n16. Set in_path.  zipcloak.c, zipnote.c, zipsplit.c (Ed)\n17. Use SPLIT_SUPPORT calls.  zipcloak.c, zipnote.c, zipsplit.c (Ed)\n18. Set current_disk, cd_start_disk, and cd_entries_this_disk for use\n    by putend() and bytes_this_split for putcentral().  zipsplit.c (Ed)\n19. Include ctype.h for toupper().  zipfile.c (Ed)\n20. Add readlocal() for utilities to read local header.  zipfile.c (Ed)\n21. Put Zip64 variables and code in ZIP64_SUPPORT ifdef in scanzipf_regnew().\n    zipfile.c (Ed, SMS)\n22. Use zip_fzofft() for converting offset.  zipfile.c (Ed, SMS)\n23. Add casts to many append to memory calls.  zipfile.c (Ed)\n24. Move handling of .zip split to get_in_split_path() and\n    get_out_split_path().  zipfile.c (Ed)\n25. Handle fix = 3 case for ZipNote that renames entries in zipcopy().\n    zipfile.c (Ed)\n26. Restore clearing of extended local header bit when not encrypting.  When\n    encrypting need to output extended local header using putextended() in\n    zipcopy().  zipfile.c (Ed)\n27. Add notes on using file time for encrypting.  zipup.c (Ed)\n28. Remove extended local header bit separately for z->lflg (local flags)\n    and z->flg (central directory flags).  These should be the same but\n    could be different.  zipup.c (Ed)\n29. Suppress command line globbing for MINGW.  win32/win32.c (Christian)\n30. Add EF UT time fix for delete.  zip.c (Christian)\n---------------------- April 28th 2006 version 3.0f10 ----------------------\n 1. Add note to extended help to escape [ as [[] or use -nw.  zip.c (Ed)\n 2. Remove local declaration of tempfile as now global.  zipnote.c,\n    zipcloak.c (SMS)\n 3. Add zip_fzofft() for outputting uzoff_t bin size c.  zipsplit.c (SMS)\n 4. Add only_archive_set and clear_archive_bits to do Window archive bit\n    selection and clearing.  Add -AS option to require DOS Archive bit\n    be set and -AC to clear archive bits of included files.  Add\n    ClearArchiveBit() to clear archive bits after archive created.\n    Only Win32.  globals.c, zip.h, zip.c, win32zip.c, win32.c (Ed)\n 5. Change procname_win32() and readd() to check archive bit.\n    win32/win32zip.c (Ed)\n 6. Update copyright.  win32/win32zip.h (Ed)\n 7. Add mesg_line_started = 0 to stats to remove blank line when clearing\n    archive bits.  zipup.c (Ed)\n 8. Add zip_fzofft() to format split size.  zipsplit.c (SMS)\n 9. Update help for splits and archive bit and add note on escaping [.\n    zip.c (Ed)\n10. Add -M option and bad_open_is_error to exit with error if any input\n    file unreadable.  Also error if -M and would get \"name not matched\"\n    warning.  zip.c (Ed)\n11. Copy Zip 2.32 csharp example, though it is designed for zip32.dll and\n    not zip32z64.dll from Zip 3.0.  Updated note.  windll/csharp (Ed)\n12. Change -M to -MM and define -mm to avoid accidental use of -m.\n    zip.c (Ed)\n13. Define split_method -1 to not allow splitting, mainly used when reading\n    a split archive to stop automatic splitting of output with same\n    split size.  Now -s=0 or -s- disables splitting.  zip.h, globals.c,\n    zip.c (Ed)\n14. Add fflush() after dots displayed.  deflate.c, fileio.c, zipup.c (Ed)\n15. Instead of assuming buffer size as 32 KB for dots, use WSIZE for\n    compressing and SBSZ for storing and calculate as dots are counted.\n    Now dot_count and dot_size are bytes instead of buffers.  Add dots\n    to Delete and Archive modes.  zip.c, zipup.c, deflate.c, fileio.c (Ed)\n16. If reading a split archive and split size has not been given, get\n    size of first split read by zipcopy(), which should be the first\n    split, and set split size to that, making the output archive the same\n    split size as the input archive.  Delay -sv split size message\n    if split size is 0 at first but then changed.  zipfile.c (Ed)\n17. Add proc_archive_name() for new archive mode to process names in old\n    archive only and skip looking on the file system.  Easier than modifying\n    the various port codes.  fileio.c (Ed)\n18. Fix cd_start_offset bug.  fileio.c (Ed)\n19. Create new action ARCHIVE that looks for matches only in old archive\n    for Copy Mode.  If no input paths and there is an output archive,\n    Copy Mode is assumed even without ARCHIVE.  Old default Copy Mode\n    when no input files updated to work like -U mode and allow filters.\n    New global copy_only currently only used to control global dots.\n    zip.c, fileio.c, globals.c, zip.h (Ed)\n20. Update help.  Change extended help to more help.  Update more help\n    to include internal modes delete and new Archive.  Update help for\n    formatting options.  Update help for wildcards.  Remove streaming\n    examples from top basic section.  Indent examples.  Help for new\n    --out and Copy Mode.  Add warnings that output using data descriptors\n    may not be compatible with some unzips.  Update dots help and add\n    warning that dot size is approximate.  Add help for new DOS archive\n    bit options.  More help for -b and -MM.  zip.c (Ed)\n21. Add support for Unix FIFO (named pipe).  Add set_extra_field() stat\n    name ending in '/' fix found in Zip 2.32.  unix/unix.c (Ed)\n22. Add check to not allow setting -U (internal copy) in similar cases to\n    -d (delete).  zip.c (Ed)\n23. Add counts for internal modes Delete and Archive.  Byte counts for -db\n    remain uncompressed size for external modes, but internal modes Delete\n    and Archive now use compressed sizes as these copy that many bytes.\n    zip.c (Ed)\n24. Add check for when ftell() wraps. zipup.c (Ed)\n25. Add mesg_line_started = 0 to result percentage message.  zipup.c (Ed)\n26. Update contact information.  unix/packaging/preinstall.in (SMS, Ed)\n27. A few Zip64 fixes to set Zip64 correctly and fix disk and offset of\n    Zip64 End Of Central Directory.  zipsplit.c (Ed)\n28. Update comments for get_option().  fileio.c (Ed)\n29. Update DLL version.  windll/windll.rc (SMS, Ed)\n30. New option -sf shows files that would be operated on.  zip.c (Ed)\n---------------------- May 5th 2006 version 3.0f11 ----------------------\n 1. Use C prototypes for Unicode functions.  fileio.c (SMS)\n 2. Change constant for mask in set_file_type from unsigned to signed.\n    trees.c (SMS)\n 3. Use C prototypes for zip_fzofft() and zip_fuzofft() signed and\n    unsigned zoff_t formatting functions.  util.c (SMS)\n 4. Remove U from constants in Adler16 code.  util.c, zip.h (SMS)\n 5. Add spaces to VMS usage to avoid misinterpretation.  zip.c (SMS)\n 6. Add OF() to at_signature().  zipfile.c (SMS)\n 7. Use zip_zofft() for entries error.  zipfile.c (SMS)\n 8. Remove U in constants in percent().  zipup.c (SMS)\n 9. VMS command line updates.  vms/cmdline.c, vms/descrip_deps.mms,\n    vms/vms_zip.rnh, zip_cli.cld, vms/zip_cli.help (SMS)\n10. Update to VMS help.  vms/zip_cli.help (Ed)\n11. Check for memmove() and strerror().  Remove specific 64-bit support\n    for SunOS, as large file support now does.  unix/configure (SMS)\n12. Add emergency replacements for memmove() and strerror().\n    unix/unix.c (SMS)\n13. Remove old not SPLIT_SUPPORT code.  globals.c, zipnote.c, fileio.c,\n    crypt.h, crypt.c, zipcloak.c, zip.h, zip.c, zipup.c, zipsplit.c,\n    zipfile.c (Ed)\n---------------------- May 12th 2006 version 3.0f12 ----------------------\n 1. Add UNICODE_SUPPORT ifdef around uname in zipup().  zip.c (SMS)\n 2. Change size from uzoff_t to zoff_t in zipcopy().  zipfile.c (SMS, Ed)\n 3. Fix a bug where filetime() returns -1 for device but not handled in\n    byte counts.  zip.c (Ed)\n 4. Add check for UnZip version and exit if not 6.00 or later if\n    a Zip64 archive.  Define popen() and pclose() in Win32 to native\n    _popen() and _pclose().  ziperr.h, zip.c, win32/osdep.h (Ed)\n 5. Add -sb option to ring bell when pause to change disk.  Use new\n    global split_bell.  global.c, zip.h, zip.c, fileio.c (Ed)\n 6. Enable crc32u() and use for Unicode extra field.  fileio.c (Ed)\n 7. Add -dv to display volume being written to.  zip.c, zip.h,\n    globals.c (Ed)\n 8. Update WhatsNew.  WhatsNew (Ed)\n 9. Help updates.  zip.c (Ed)\n10. Create option -X- (negated -X) to keep old extra fields and remove\n    -XX which is now -X.  Make get_extra_field() global.  Add\n    copy_nondup_extra_fields()to copy old extra fields not already\n    in new extra fields.  zipup.c, zip.c, zipfile.c (Ed)\n11. Use output name oname for -sf option to show files that would be\n    worked on.  zip.c (Ed)\n12. When updating or freshening old entries, read the old local header\n    with readlocal() to get local flags and extra fields.  zip.c (Ed)\n13. Add UNICODE_SUPPORT ifdefs around uname code.  zip.c (SMS, Ed)\n14. If WIN32_OEM set then on WIN32 store OEM name in archive.  As read\n    DOS or WIN32 archives convert assumed OEM paths to ANSI.  Remove old\n    WIN32_OEM code.  Make oem_to_local_string() global for WIN32_OEM and\n    local_to_oem_string() global for WIN32_OEM and UNICODE_SUPPORT.\n    zip.h, zipfile.c, zipup.c, win32/win32.c, win32/win32zip.c (Ed)\n15. Update error 8 to include wrong unzip.  ziperr.h (Ed)\n16. Change checksum for Unicode extra field to standard crc32 using\n    C version crc32u().  Add crctab.c.  win32/vc6/zipnote.dsp,\n    win32/vc6/zipsplit.dsp, zipfile.c\n17. Update readlocal() to handle multi-disk archives if not UTIL.\n    zipfile.c (Ed)\n18. Convert size to signed zoff_t in zipcopy().  Update note.\n    zipfile.c (Ed)\n19. Update Readme.  Readme (Ed)\n20. Add crctab.o to zipsplit and zipnote.  unix/Makefile (Ed)\n21. Proposed update to license.  License (Ed)\n---------------------- May 20th 2006 version 3.0f13 ----------------------\n 1. Reformat License file.  License (Cosmin)\n 2. Change %d to %lu for disk number and add cast.  zip.c (Cosmin, Ed)\n 3. Display Scanning files message after delay at start based on\n    suggestion from Greg.  Currently the time is checked every 100\n    entries processed.  After 100 entries the start time is saved.\n    After 5 seconds or 100 entries after that, whichever takes\n    longer, the Scanning files message is displayed and every 2 seconds\n    or 100 entries, whichever takes longer, after that a dot is displayed.\n    fileio.c, zip.c, globals.c, zip.h (Greg, Ed)\n 4. Add Unicode mismatch flag and option -UN.  Default is now a Unicode\n    mismatch is an error.  -UN=warn outputs warnings and continues,\n    -UN=ignore disables warnings, and -UN=no ignores the Unicode extra\n    fields.  globals.c, zip.h, zipfile.c (Ed)\n 5. Add options for VMS.  vms/cmdline.c, vms/zip_cld.cld (SMS)\n 6. Add casts to percent().  zipup.c (Ed)\n 7. Minor changes to logfile formatting.  zip.c (Ed)\n 8. Update help.  zip.c (Ed)\n 9. Add -Z=compression-method option.  zip.c (Ed)\n10. Add sd: to -sd status messages.  zip.c (Ed)\n11. Instead of original argv[] use args[] for -sc show command line\n    to show final command line.  zip.c (Ed)\n12. Change argv[] to args[] for logfile.  zip.c (Ed)\n13. Put results of -sf show files in log file if open.  zip.c (Ed)\n14. Add Johnny's bzip2 patch but not tested.  win32/makefile, zip.c,\n    zip.h, zipup.c (Johnny)\n15. Minor tweeks to bzip2 to work with latest beta.  zip.c, zipup.c (Ed)\n16. Add -sf- to list files that would be included only in log file\n    and not on stdout as list can be long.  Only list totals on stdout.\n    zip.c (Ed)\n17. Create check_unzip_version().  Fix Unix check.  Zip still creates\n    the temporary archive then does the check, and if it fails\n    the archive is deleted, even if the check fails because of the wrong\n    verion of UnZip.  On Unix only 'unzip' the system version of UnZip\n    is checked, not './unzip' which would allow putting a local more\n    up to date version of UnZip in the current directory for the check.\n    There should be a way to override the system version of UnZip for\n    the -T test.  zip.c (Ed)\n---------------------- July 12th 2006 version 3.0f14 ----------------------\n 1. Change crypt version from 2.10 to 2.91 to match Zip 2.32 and avoid\n    confusion.  crypt.h (Cosmin)\n 2. Add abbrevmatch() to handle option values that can be abbreviated\n    like compression method.  util.c, zip.h, zip.c (Ed)\n 3. Change USE_BZIP2 to BZIP2_SUPPORT as USE_BZIP2 implies it replaces\n    deflation maybe.  zip.c, zip.h, zipup.c (Ed)\n 4. Update man page.  man/zip.1, zip.txt (Ed)\n 5. Add bzip2 to VMS.  vms/build_zip.com, vms/bzlib.h, vms/cmdline.c,\n    vms/descrip.mms, vms/descrip_src.mms, vms/find_bzip2_lib.com,\n    vms/install_vms.txt, vms/zip_cli.cld (SMS)\n 6. Remove zipfile parameter from bzfilecompress().  Add unsigned\n    cast for EOF in bzip2 code.  Add bzip2 version information.\n    zipup.c, zip.c (SMS)\n 7. Add bzip2 to Unix.  unix/configure (SMS)\n 8. Add and update bzip2 descriptions.  INSTALL, README, WhatsNew,\n    bzip2/install.txt (SMS, Ed)\n 9. Add vc6bz2 projects for compiling bzip2 code into zip (not the\n    best approach perhaps).  win32/vc6/readmevc.txt,\n    win32/vc6bz2/readvcbz.txt, win32/vc6bz2/zip.dsp, win32/vc6bz2/zip.dsw,\n    win32/vc6bz2/zipcloak.dsp, win32/vc6bz2/zipnote.dsp,\n    win32/vc6bz2/zipsplit.dsp (Ed)\n10. Add support for VC++ 2005 by disabling deprecation.  win32/osdep.h\n    (Cosmin)\n11. Update instructions for makefile.  unix/Makefile (Ed)\n12. Update todo list.  todo30.txt (Ed)\n13. Reduce #if 0 block to now allow extra data message.  zipfile.c (Ed)\n14. Add note that readlocal() reads local headers.  zipfile.c (Ed)\n15. Archive comment was not being read by new scanzipf_regew().  Added.\n    zipfile.c (Ed)\n16. Handle reading and writing OEM comments.  zipfile.c (Ed)\n17. Update Zip64 data descriptor note.  zipfile.c (Ed)\n18. Format filetypes() check.  zipup.c (Ed)\n19. Update note to remember to force deflation for descriptors by\n    release.  zipup.c (Ed)\n20. In compression code using libraries, enable dots for noisy also.\n    zipup.c (Ed)\n21. Update extended help to add more of the basic options and\n    compression method.  zip.c (Ed)\n22. Add additional lines bz_opt_ver2 and bz_opt_ver3 to bzip2\n    version to give credit to bzip2.  zip.c (Ed)\n23. Add descriptions to version information for USE_EF_UT_TIME,\n    NTSD_EAS, WILD_STOP_AT_DIR, WIN32_OEM, LARGE_FILE_SUPPORT,\n    ZIP64_SUPPORT, and UNICODE_SUPPORT similar to how UnZip does.\n    zip.c (Ed)\n24. Add note that crypt is modified in Zip 3.  zip.c (Ed)\n25. Use abbrevmatch() and update warnings for compression\n    method selection.  zip.c (Ed)\n26. Update config to handle either using IZ_BZIP2 to define\n    the location of the bzip2 files or the bzip2 directory.\n    unix/configure, zipup.c, zip.c (SMS, Ed)\n---------------------- July 14th 2006 version 3.0f15 ----------------------\n 1. Change USE_BZIP2 to BZIP2_SUPPORT in VMS.  vms/descrip_src.mms,\n    vms/build_zip.com (SMS)\n 2. Add SYS$DISK:.  vms/descrip.mms, vms/build_zip.com (SMS)\n 3. Change vms/install.txt to [.vms]install.txt.  bzip2/install.txt (SMS)\n 4. Change VMS files to lower case.  vms/mod_dep.com, vms/install_vms.txt,\n    vms/zip.opt, vms/hlp_lib_next.com, vms/notes.txt, vms/unixlib_gcc.h,\n    vms/unixio_gcc.h (SMS)\n 5. Remove old VMS files.  vms/descrip-old.mms (removed),\n    vms/link_zip.com (removed), vms/make_zip.com (removed),\n    vms/makefile.vms (removed) (SMS)\n---------------------- July 24th 2006 version 3.0f16 ----------------------\n 1. Fix global dots so can set with dot size.  deflate.c, fileio.c (Ed)\n 2. Update License top line to refer only to license.  License (Cosmin)\n 3. Update License.  License (Ed)\n 4. Implement zero length UTF-8 path length as flag standard path is UTF-8\n    and should use that.  This allows Zip to use the standard path as\n    UTF-8 when the local character set is UTF-8.  zipfile.c (Ed)\n 5. Update WhatsNew.  WhatsNew (Ed)\n 6. Change case of bzip2/install.txt.  INSTALL (Ed)\n 7. Change MANUAL.txt to ZIP.txt and update ftp site.  README (Ed)\n 8. Update announcement.  zip30f.ann (Ed)\n 9. Now also check if OS has bzip2 library and can use that.\n    unix/configure, zip.c (Mark Adler, Ed)\n10. Add fix from akt@m5.dion.ne.jp in Japan to recurse on doublebyte\n    characters without processing in recmatch().  This should not be needed\n    unless the rest of the code in there is broke for Japanese character\n    sets in some way.  Need to test.  util.c (Ed)\n11. Add note for bzip2.  zip.c (Ed)\n12. Do not do seek wrap test if ftell() returns -1 as from a pipe.  Add\n    output of last ftell() and current ftell() for zipfile too big seek\n    error.  zipup.c (Ed)\n13. Add version to the options table.  Remove the check to display version\n    before the command line is processed.  Add to option -v a check to\n    display the version if that is the only argument.  Can still enable\n    verbose with piping by using zip -v - - format.  zip.c (Ed)\n14. Add abbrevmatch() for -UN option.  zip.c (Ed)\n---------------------- August 7th 2006 version 3.0f17 ----------------------\n 1. Change license modifications to retain intent of copyright holders, as\n    any major change in license conditions would require contacting all\n    copyright holders.  LICENSE (Greg, Ed)\n 2. Move debugging statement after zipstdout() where mesg is set to stderr.\n    Add mesg and fflush() to sd messages where needed so that messages go\n    to stderr when piping.  zip.c (Ed)\n 3. Update encryption comment.  zipup.c (Ed)\n 4. Do not use data descriptors for directories.  zipup.c (Mark, Ed)\n 5. Update Q & A to match license.  README (Ed)\n 6. Update WhatsNew.  WHATSNEW (Ed)\n 7. Add ifndef around version_info() for dll.  zip.c (Ed)\n 8. Add -TT (--unzip-path) to allow setting the unzip command to use with\n    -T to test the archive.  zip.c (Ed)\n 9. Add -DF (--difference-archive) which requires --out and turns off\n    copying unchanged entries to the new archive creating an archive with\n    just the changes and additions since the original archive was created.\n    zip.c, globals.c, zip.h (Ed)\n10. Update help.  zip.c (Ed)\n---------------------- September 7th 2006 version 3.0f18 ----------------------\n 1. Split -t and -tt options and remove limitation that only one can be\n    used to allow setting a date range.  zip.c, WhatsNew (Ed)\n 2. Minor changes in comments.  zipfile.c (Ed)\n 3. Add entries for format of Unicode Path and Unicode Comment extra fields.\n    proginfo/extrafld.txt (Ed)\n 4. Change note at top of infozip.who, but needs to be updated with all new\n    contributors.  proginfo/infozip.who (Ed)\n 5. Note Zip 3 and UnZip 6 now support Zip64.  proginfo/ziplimit.txt (Ed)\n 6. Add note on Unicode.  README (Ed)\n 7. Update WHATSNEW.  WHATSNEW (Ed)\n 8. Update help.  zip.c (Ed)\n 9. Add {} support to -TT option, allowing insertion of temp archive path\n    into the command string to -TT similar to Unix find does.  zip.c (Ed)\n10. Start changes for -F fix option.  Add checks when reading input archive\n    and skip bad central directory entries and bad local entries.  Currently\n    -F requires the central directory to be intact (except for bad CD entries\n    that will be skipped) and local entries and data to be where the\n    central directory say they are.  This allows all recovered entries to\n    be complete with all central directory information.  Calculate CRC of\n    input entry and compare to CRC from central directory.  Allow skipping\n    split disks the user may not have.  Store state of output archive\n    before each local entry and data are read, allowing seeking back and\n    restoring state to skip bad entries.  fileio.c, global.c, zipfile.c,\n    zip.h (Ed)\n11. Started changes for fixfix.  fileio.c (Ed)\n12. Update help on -t and -tt.  zip.c (Ed)\n13. Add note on Unicode support, but may change if add handling of names\n    with characters not supported in current character set.  README (Ed)\n14. Combined ToDo30.txt and ToDo but more to be done.  TODO (Ed)\n15. Update ToDo list.  ToDo30.txt (Ed)\n16. Add -F and -FF to help.  zip.c (Ed)\n17. Run fix mode in copy mode, as it is copying from one archive to\n    another, and use those checks.  zip.c (Ed)\n18. Add Try -F and Try -FF warnings in places.  zipfile.c (Ed)\n19. Allow reading version 4.6 (bzip2) archives.  zipfile.c (Ed)\n20. Add Unicode Path and Unicode Comment extra field descriptions.\n    proginfo/extrafld.txt (Ed)\n21. First attempt at updating the Who file.  proginfo/infozip.who (Ed)\n22. Add note to top of ziplimit.txt.  proginfo/ziplimit.txt (Ed)\n23. Add possible fix for paths returned by the Win32 directory scan with\n    '?' in the name.  These are characters in the Unicode name stored on\n    disk but not represented in the multi-byte character set used by zip\n    for the scan.  In this case, return the short name in 8.3 format so\n    directory scan can continue.  Could put the Unicode name in the Unicode\n    extra field, but not done.  Add warning when long name is replaced\n    by short name.  Not fully tested.  win32/win32zip.c, zip.h, zip.c,\n    fileio.c (Ed)\n24. If archive name and -sf are the only parameters, list archive contents.\n    zip.c (Ed)\n---------------------- September 8th 2006 version 3.0f19 ----------------------\n 1. Fix error message.  zipfile.c (SMS, Ed)\n 2. Put crc32() in ifndef UTIL as only needed for fix.  fileio.c (SMS, Ed)\n---------------------- November 3rd 2006 version 3.0f20 -----------------------\n 1. Fix comment.  vms/vmszip.c (SMS)\n 2. Include oem_to_local_string() if UNICODE_SUPPORT.  win32/win32.c,\n    zip.h (Ed)\n 3. Modify procname_win32() to flag a path not supported by the local\n    character set so can get Unicode for it.  Check Unicode names.\n    win32/win32zip.c (Ed)\n 4. Add matching of escaped Unicode names to proc_archive_name() that\n    reads entries from an archive.  Add sorted zlist zusort.\n    globals.c, fileio.c, zip.h, zipfile.c (Ed)\n 5. Add support for non-local character set names and paths for WIN32,\n    getting and storing the UTF-8 path when needed.  Use 8.3 name\n    when normal name has characters not supported in current local\n    character set.  Note when short name used.  zip.c, fileio.c (Ed)\n 6. Add support for fix = 2 which reads local headers first to\n    bfcopy().  fileio.c, zip.h (Ed)\n 7. Allow selection of .zip split in ask_for_split_read_path() when\n    reading a split archive that has no end records giving the total\n    split count.  fileio.c (Ed)\n 8. Add zoff_t casts to dot counts.  fileio.c (Ed)\n 9. Comment changes for Unicode.  fileio.c (Ed)\n10. Call wide_to_local_string() separately in utf8_to_local_string()\n    to free up temp value.  fileio.c (Ed)\n11. Support new AppNote bit 11 for forcing UTF-8, but needs finishing.\n    globals.c (Ed)\n12. Add to zlist struct zuname for the escaped version of the UTF-8\n    name in uname and add ouname for the display version of zuname.\n    zip.c, zip.h, zipfile.c (Ed)\n13. Add zipmessage_nl() that can output to the screen and to the log\n    file like zipmessage(), but can write lines without a newline.\n    zip.c, zip.h, zipcloak.c, zipnote.c, zipsplit.c (Ed)\n14. Update help for -FF and Unicode.  zip.c (Ed)\n15. Change > to >= for byte message check to avoid -0 (negative zero).\n    zip.c (Ed)\n16. Add -su show unicode option which adds escaped unicode paths to\n    -sf.  Also uses show_files = 3.  zip.c (Ed)\n17. Update comments for -UN and -X.  zip.c (Ed)\n18. Add support for new AppNote bit 11 that says standard path and\n    comment have UTF-8 when -UN=f is used.  zip.c (Ed)\n19. Fix zipfile name message by replacing value with zipfile.\n    zip.c (Ed)\n20. Add new code for -FF, which processes archives by trying to read\n    the EOCDR to get split count, then starting with the local\n    entries.  This option does not use the standard code but does\n    everything itself.  Add scanzipf_fixnew(), which tries to read\n    the EOCDR, then the local entries, then the central directory.\n    zip.c, zipfile.c (Ed)\n21. Update note for ZIP64_CENTRAL_DIR_TAIL_SIZE.  zipfile.c (Ed)\n22. Put read_Unicode_Path_entry() and read_Unicode_Path_local_entry()\n    into UNICODE_SUPPORT ifdef.  zipfile.c (Ed)\n23. Add zuqcmp() and zubcmp() to support Unicode sorted list of\n    paths.  zipfile.c (Ed)\n24. Update zsearch() to also search unicode paths.  zipfile.c (Ed)\n25. Split out iname in read_Unicode_Path_entry() for debugging.\n    Should put it back.  Update Unicode mismatch warning.\n    zipfile.c (Ed)\n26. Update Unicode in readlocal().  zipfile.c (Ed)\n27. Add more Unicode support to scanzipf_regnew().  zipfile.c (Ed)\n28. Add support for fix = 2 to zipcopy().  Add checks and warnings,\n    but allow scan to continue when can.  Use local data to fill\n    in central directory fields in case no central directory entry\n    for local entry.  zipfile.c (Ed)\n29. Add get_win32_utf8path() to get UTF-8 from Windows if can.\n    zipfile.c (Ed)\n---------------------- November 7th 2006 version 3.0f21 -----------------------\n 1. Add crude data descriptor support to -FF in bfcopy() that should be\n    updated by release.  fileio.c (Ed)\n 2. Change %d to %s and use zip_fzofft() to format zoff_t byte count.\n    zipfile.c (SMS, Ed)\n 3. Call local_to_oem_string() for only WIN32 in zipcopy().  zipfile.c\n    (SMS, Ed)\n---------------------- November 29th 2006 version 3.0f22 -----------------------\n 1. Change ' to \" in extended help.  zip.c (Ed)\n 2. Change -dv disk number display to indisk>outdisk.  zip.c (Ed)\n 3. Finish -FF fix option.  Move detailed output to require -v.  zip.c (Ed)\n 4. Add note to help to use -v with -FF to see details.  zip.c (Ed)\n 5. Add -sU option to view only Unicode names when exist.  zip.c (Ed)\n 6. Change default dot size in verbose from every buffer to 10 MB.  zip.c (Ed)\n 7. Exit if --out and in path same as out path.  zip.c (Ed)\n 8. Remove verbose information when fixing archive.  zip.c (Ed)\n 9. Initialize in disk to 0, but still problem with disk number of first entry\n    for each disk lagging by 1.  zip.c (Ed)\n10. Consistently use ZE error codes for exit from ask_for_split_read_path.\n    zipfile.c, zip.c (Ed)\n11. Seek back when fix finds bad entries.  Also skip last entry of split\n    if next split is missing.  Should check if entry completed.  zip.c (Ed)\n12. Add messages to -sd for writing the central directory, replacing the old\n    zip file, and setting file type.  zip.c (Ed)\n13. Don't set file type on stdout.  zip.c (Ed)\n14. Increase errbuf from FNMAX + 81 to FNMAX + 4081.  zip.h (Ed)\n15. Add skip_this_disk, des_good, des_crc, des_csize, and des_usize globals\n    for -FF and reading data descriptors.  Change note on display_volume.\n    Add global skip_current_disk.  zip.h, globals.c (Ed)\n16. BFWRITE_HEADER define now also does data descriptor.  zip.h (Ed)\n17. Skip zipoddities() if fix.  Maybe can later add back.  zipfile.c (Ed)\n18. Update fix messages.  zipfile.c (Ed)\n19. Allow user to end archive early using ZE_EOF.  zipfile.c, fileio.c (Ed)\n20. Only show split numbers and offsets for -FF if verbose.  zipfile.c (Ed)\n21. Handle spanning signature at top of split archive.  zipfile.c (Ed)\n22. Only close in_file if open.  zipfile.c (Ed)\n23. Add note if no .zip and only splits suggest use -FF.  zipfile.c (Ed)\n24. In putlocal() and putcentral() only convert to OEM if z->vem == 20.\n    zipfile.c (Ed)\n25. Do not OEM convert archive comment as PKWare says this should\n    be ASCII.  zipfile.c (Ed)\n26. Fix swap of siz and len and LOCSIZ and LOCLEN.  zipfile.c (Ed)\n27. Call read_Unicode_Path_local_entry() before OEM conversion so Unicode\n    checksum checks iname before conversion.  zipfile.c (Ed)\n28. Only check if local and central crc match if not stream entry.\n    zipfile.c (Ed)\n29. Keep data descriptors if fix == 2, but need to look at this.\n    zipfile.c (Ed)\n30. Fix bug adding up header bytes in n by adding 4 for signature.\n    zipfile.c (Ed)\n31. If fix == 2 use local crc for central, otherwise use central crc\n    for local.  zipfile.c (Ed)\n32. In zipcopy(), check data descriptor and skip if not correct one.\n    zipfile.c (Ed)\n33. Add SH, LG, and LLG macros from zipfile.c to allow reading the data in\n    the data descriptor.  fileio.c (Ed)\n34. In bfcopy(), read and check the data descriptor if n == -2.  If\n    run out of bytes before find descriptor, return error.  fileio.c (Ed)\n35. In ask_for_split_read_path(), increase buf to SPLIT_MAX_PATH + 100,\n    fix bug by adding \"- 1\", set split_dir = \"\" if current directory,\n    and update prompts to add skip and end choices.  Add skip and end\n    choices.  fileio.c (Ed)\n36. Increase buffer for fgets to SPLIT_MAXPATH.  fileio.c (Ed)\n37. Update WhatsNew.  WhatsNew (Ed)\n---------------------- December 10th 2006 version 3.0f23 -----------------------\n 1. Handle additional ODS5 issues by upper casing many symbols and file names.\n    vms/build_zip.com, vms/collect_deps.com, vms/descrip.mms,\n    vms/descrip_mkdeps.mms, vms/descrip_src.mms, vms/find_bzip2_lib.com (SMS)\n 2. Update VMS Find Help Library code.  vms/hlp_lib_next.com (SMS)\n 3. Instead of tempname use temp_name as parameter to avoid function\n    tempname().  zipsplit.c, zipnote.c, zipcloak.c, zip.c (Ed)\n 4. If fixing archive with -FF and no EOCDR to get disk count, see if top of\n    archive has spanning signature or local header and guess if it is\n    single-disk archive, then ask user to confirm.  zipfile.c (Ed)\n 5. For Unix where NO_MKSTEMP is not defined, replace mktemp() with mkstemp()\n    that avoids a race condition.  zip.c, zipcloak.c, zipnote.c, fileio.c (Ed)\n 6. Eliminate mkstemp() warning by using mkstemp() instead of mktemp() for\n    Unix.  Only for UNIX and if NO_MKSTEMP is not defined.  Many OS do not\n    have mkstemp().  zipcloak.c, zipnote.c, zip.c, fileio.c (Ed)\n 7. If UNICODE_SUPPORT and UNIX then try to switch to UTF-8 locale to allow\n    displaying of Unicode, otherwise just get escapes.  This results in some\n    characters displaying as whitespace if needed fonts, such as East Asian,\n    are not installed.  zip.c (Ed)\n 8. If new global unicode_escape_all is set, then escape all non-ASCII\n    characters when converting Unicode file path.  This allows viewing paths\n    as escapes on Unix that would otherwise be white space.  If not set, any\n    characters that map to the current locale are returned as is.  Can only\n    display if either supported as base by the OS or fonts installed.  Set\n    using -UN=escape option.  zip.c, fileio.c, zip.h, globals.c (Ed)\n 9. Update extended help for Unicode.  zip.c (Ed)\n10. All variables used by Win32 in global.c should now be initialized at\n    start so dll is initialized each call.  zip.c (Ed)\n---------------------- January 1st 2007 version 3.0f24 -----------------------\n 1. Fix a problem when building with (old, obsolete) IM attribute encoding\n    combined with bzip2 support.  vms/descrip_src.mms (SMS)\n 2. Update WHATSNEW.  WhatsNew (Ed)\n 3. Update README.  ReadMe (Ed)\n 4. Remove in_crc code.  Too involved to implement but may look at later.\n    fileio.c, globals.c, zip.c (Ed)\n 5. Use 0x50 and 0x4b for 'P' and 'K' in signatures to handle EBCDIC case.\n    zipfile.c, fileio.c (Ed)\n 6. Implement new -FS file sync option that deletes entries missing on the\n    file system from an archive being updated.  globals.c, zip.c (?, Ed)\n 7. Update help.  zip.h, zip.c (Ed)\n 8. Include scanning files dots when update small but new file scan long.\n    zip.c (Ed)\n 9. Ask if single-file archive when using -FF and can't tell.  zipfile.c (Ed)\n10. Display message when entry would be truncated.  zipfile.c (Ed)\n11. Check for VMS_IM_EXTRA.  Update bzip2 support for VMS.  Change\n    destination directory if large-file enabled.  vms/build_zip.com,\n    vms/descrip_src.mms (SMS)\n12. Change parameters for VMS bzip2 search.  vms/find_bzip2_lib.com (SMS)\n---------------------- January 12th 2007 version 3.0f25 -----------------------\n 1. Incorporate faster crc32.c including the Rodney Brown changes (originally\n    implemented in the zlib project) from UnZip, which includes the\n    IZ_CRC_BE_OPTIMIZ and IZ_CRC_LE_OPTIMIZ optimizations when those symbols\n    are defined.  These modifications include:\n     - enlarge unrolling of loops to do 16 bytes per turn\n     - use offsets to access each item\n     - add support for \"unfolded tables\" optimization variant\n    crc32.c  (Christian)\n 2. As the crc32.c module now includes crc table generation, remove crctab.c.\n    crctab.c (remove) (Christian)\n 3. Update crc i386 assembler code from UnZip (details see above).\n    win32/crc_lcc.asm, win32/crc_i386.asm, win32/crc_i386.c, crc_i386.S\n    (Christian)\n 4. Guard against redefinition of symbols @CodeSize and @DataSize in memory\n    model setup section to work around Open Watcom (version 1.6) wasm\n    assembler problem.  msdos/crc_i86.asm (Christian)\n 5. Change type of keys[] array for new crc, add IZ_CRC_BE_OPTIMIZ, and\n    use new crypt crc table.  Use header buffer instead of buf for header.\n    crypt.c, crypt.h (Christian)\n 6. Update version and remove crc table.  crypt.h (Christian)\n 7. Add crc32.h, change sprintf() format for disk number from d to lu as\n    can go over 16-bit, remove crc32u().  fileio.c (Christian)\n 8. Update to use new crc.  msdos/makefile.bor, msdos/makefile.dj1,\n    msdos/makefile.dj2, msdos/makefile.emx, msdos/makefile.msc,\n    msdos/makefile.tc, msdos/makefile.wat, unix/Makefile,\n    vms/build_zip.com, vms/descrip_deps.mms, vms/descrip_src.mms,\n    vms/osdep.h, win32/makefile.bor, win32/makefile.dj, win32/makefile.emx,\n    win32/makefile.gcc, win32/makefile.ibm, win32/makefile.lcc,\n    win32/makefile.w10, win32/makefile.w32, win32/makefile.wat,\n    win32/makenoas.w32, win32/vc6/zip.dsp,\n    win32/vc6/zipcloak.dsp, win32/vc6/zipnote.dsp, win32/vc6/zipsplit.dsp,\n    win32/vc6bz2/zip.dsp, win32/vc6bz2/zipcloak.dsp, win32/vc6bz2/zipnote.dsp,\n    win32/vc6bz2/zipsplit.dsp, windll/visualc/dll/zip32.dsp,\n    windll/visualc/dll/zip32.mak, windll/visualc/lib/zip32.dsp,\n    win32/visualc/lib/zip32.mak (Christian)\n 9. Include crc32.h.  Make variable uname local in proc_archive_name().\n    Remove unused num and new_base_path.  Change %02d to %02l2 for\n    disk number in print format.  Remove crc32u() as now use crc32().\n    Add parentheses around conditions in loops.  Use 0 instead of NULL\n    for zwchar.  fileio.c (Christian)\n10. Add z_uint4 defines from crypt.c to tailor.h.  Move uch, ush, and ulg\n    typedefs before tailor.h include which needs them.  tailor.h, zip.h (SMS)\n11. Include crc32.h.  change add_name() to return not int but long\n    since number of command line arguments can exceed 16 bits.  Cast\n    variable option to (int) for subtraction.  Change 0x400 to 0x400L.\n    Add braces to show_files print block.  zip.c (Christian)\n12. Add warning if use -F or -FF without --out.  Change defined(NO_MKSTEMP)\n    to !defined(NO_MKSTEMP).  zip.c (Ed)\n13. Define EC64LOC and EC64REC for size of Zip64 EOCD Locator and Zip64\n    EOCD Record.  Add extern for crc_32_tab.  Move crc32() to crc32.h.\n    zip.h (Christian)\n14. Add crc.h.  zipcloak.c (Christian)\n15. Include crc32.h.  Comment out scanzipf_reg() and scanzipf_fix() as\n    no longer used, which are left in for now for comparison.  Cast\n    blocksize to extent for malloc().  Instead of 0x10000 malloc 0xFFFF for\n    extra field block so fits in 16 bits.  Instead of crc32u() use crc32().\n    Only do lflg != flg check for fix == 2.  Add comments to various #endif.\n    Indent comment.  Comment out copy_sig() which is not used.  Reduce size\n    of SCAN_BUFSIZE to EC64REC for MEMORY16.  Use ENDHEAD for EOCDR size.\n    Change %u to %lu in print formats for disk count.  Use EC64LOC for size\n    of Zip64 EOCD Locator.  Use EC64REC for size of Zip64 EOCD Record.\n    Add streaming and was_zip64 to ZIP64_SUPPORT.  Remove lflg != flg check\n    in zipcopy().  zipfile.c (Christian)\n16. Add note that z-flg & ~0xf check will fail if new bit 12 for UTF-8 paths\n    and comments is set.  Update -FF warning.  zipfile.c (Ed)\n17. Include crc32.h.  Modify tempzn update.  Fix comment.  Set\n    z->lflg = z->flg after deflate as deflate may have set bits in z->flg\n    [Ed, Christian].  Include BZIP2_SUPPORT block in !UTIL block.  zipup.c\n    (Christian)\n18. Changes to use crc32.c.  acorn/gmakefile, acorn/makefile, amiga/lmkfile,\n    amiga/makefile.azt, amiga/smakefile, aosvs/make.cli, atari/makefile,\n    atheos/makefile, beos/makefile, cmsmvs/cczip.exec, cmsmvs/mvs.mki,\n    cmsmvs/zip.makefile, cmsmvs/zipmvsc.job, cmsmvs/zipvmc.exec,\n    human68k/makefile, human68k/makefile.gcc, novell/makefile, novell/zip.lnk,\n    os2/makefile.os2, qdos/makefile.qdos, qdos/makefile.qlzip, tandem/history,\n    tandem/macros, tandem/tandem.h, theos/makefile, tops20/make.mic,\n    unix/configure, unix/makefile, win32/makefile.a64 (Christian)\n19. Add note to use BZ_NO_STDIO.  bzip2/install.txt (Ed)\n20. Remove crctab.  cmsmvs/zipvmc.exec (Ed)\n21. Update comment.  macos/source/pathname.c (Christian)\n22. Start of manual update.  Zip.1 (Ed)\n23. Changes to use crc32.c.  vms/descrip.mms, vms/descrip_deps.mms,\n    vms/descrip_mkdeps.mms, vms/descrip_src.mms, vms/vms.c (SMS)\n---------------------- January 17th 2007 version 3.0f26 -----------------------\n 1. Add note for UnZip.  crypt.c (Christian)\n 2. Change current_disk and disk_number from int to ulg.  Change num from int\n    to unsigned int.  [Even though a 16-bit system likely won't see more than\n    64k disks, it probably should be ulg - Ed]  Remove unused mbsize.  Change\n    match from long to int as the number of possible options should always fit\n    in that.  fileio.c, globals.c (Christian)\n 3. Use -Gt to force some data into separate data segments so all data fits.\n    msdos/makefile.msc (Christian)\n 4. Move some copyright constants to far to save near space.\n    revision.h (Christian)\n 5. Change u for character from int to unsigned int.  util.c (Christian)\n 6. Move include of crc32.h from vms/vms.c to vms/vms_pk.c.  vms/vms.c,\n    vms/vms_pk.c (Christian)\n 7. Update crci386_.o.  win32/makefile.gcc (Christian)\n 8. Use NOASM=1 to disable assembler and clear variables when do not.\n    win32/makefile.w32 (Christian)\n 9. Remove unused totalslashes and returnslashes from get_win32_utf8path().\n    win32/win32zip.c (Christian)\n10. Remove local versions of tempzip and tempzf.\n    zip.c (Christian)\n11. Make options[] far.  Change cd_start_disk from int to ulg.  Cast -1 to\n    (ulg) for cd_start_disk.  Put here = zftello() in DEBUG defines.\n    zip.h, zip.c (Christian)\n12. Change length of zipfile comment parameter from ush to extent.  Change\n    disk numbers from int to ulg in close_split(), ask_for_split_read_path(),\n    ask_for_split_write_path(), get_in_split_path(), find_in_split_path(),\n    get_out_split_path().  Add Far to longopt and name strings in\n    option_struct.  zip.h (Christian)\n13. Add far to options[].  zipcloak.c (Christian, Ed)\n14. Define write_string_to_mem() only for UNICODE_SUPPORT.  Change ulg to\n    extent for append to mem memory offset and blocksize parameters.  Make\n    at_signature() local.  Cast usValue to char.  Remove unused oname in\n    read_Unicode_Path_local_entry().  Remove local definitions of zip64_entry\n    as Zip is always processing one entry at a time and this is a global\n    flag for the current entry.  Make find_next_signature() and\n    find_signature() local.  Add ZCONST to signature parameter.  Make\n    is_signature() and at_signature() local.  Change m, result of fread(),\n    from int to extent.  Reduce SCAN_BUFSIZE from 0x40000 to the size of the\n    largest header being read.  As find_next_signature() is used to scan for\n    the next signature and that reads a byte at a time, the scan buf is only\n    used to read in the found headers.  Since we skip the extra parts of the\n    Zip64 EOCDR, all headers are a fixed size.  Remove unused variables from\n    scanzipf_fixnew().  Use ENDCOM for end comment offset.  Instead of 64 KB\n    seek back 128 KB to find EOCDR.  Use ENDOFF and ENDTOT for offsets in\n    EOCDR.  Remove tabs.  Merge versions of putend().  Update Amiga SFX.\n    Remove unused offset in zipcopy().  Make size local in zipcopy().\n    zipfile.c (Christian)\n15. Update putend() comment.  zipfile.c (Ed)\n16. Add far to options[].  zipnote.c, zipsplit.c (Christian)\n17. Add NO_ASM versions of Win32 zipnote, zipsplit, and zipcloak projects.\n    Add crc32.h and crc32.c to zipsplit and zipnote projects.\n    win32/vc6/zipsplit.dsp, win32/vc6/zipnote.dsp, win32/vc6/zipcloak.dsp (Ed)\n18. Add NO_ASM versions of Win32 bzip2 zipnote, zipsplit, and Zipcloak\n    projects.  Add crc32.h and crc32.c.  win32/vc6bz2/zipsplit.dsp,\n    win32/vc6bz2/zipnote.dsp, win32/vc6bz2/zipcloak.dsp (Ed)\n19. Update Win32 dll and lib projects and make files.\n    windll/visualc/lib/zip32.dsp, windll/visualc/lib/zip32.mak,\n    windll/visualc/dll/zip32.dsp, windll/visualc/dll/zip32.mak (Ed)\n20. Remove space in front of #ifdef and other conditionals that slipped in.\n    zipfile.c, zipup.c (SMS)\n21. Updates for bzip2.  vms/bzlib.h, vms/install_vms.txt (SMS)\n22. Updates.  vms/notes.txt (SMS)\n23. Update copyrights.  crc32.c, deflate.c, globals.c, revision.h, ziperr.h,\n    trees.c, win32/nt.c, win32/win32.c, win32/win32i64.c, win32/win32zip.h,\n    win32/zipup.h (Ed)\n24. Update WhatsNew.  WHATSNEW (Ed)\n---------------------- February 4th 2007 version 3.0f27 -----------------------\n 1. Fix array sizes and loop lengths in wide_to_escape_string().  fileio.c\n    (Johnny, Ed)\n 2. Fix escape_string_to_wide() to handle hex strings, then comment out as\n    not used.  zip.h, fileio.c (Ed)\n 3. Use ZIPERRORS() macro instead of ziperrors[] array.  zip.c, zipcloak.c,\n    zipnote.c, zipsplit.c (SMS)\n 4. Add VMS-compatible \"severity\" values, add new ZE_SEV_PERR define to\n    set when perror() needs to be called, add ZIPERRORS() macro, change\n    PERR() to use ZE_SEV_PERR, change ziperrors[] to new structure array\n    to hold error strings, add new VMS facility names and severity codes\n    assigned by HP to ziperrors[] array, and add new official\n    VMS_MSG_IDENT.  ziperr.h (SMS)\n 5. Change ZE_SEV defines to ZE_S to save space and reformat ziperrors[].\n    ziperr.h (Ed)\n 6. Update install.txt to include generic Unix case.  bzip2/install.txt (Ed)\n 7. Add creation of message file and add NOMSG message.  vms/build_zip.com,\n    vms/descrip.mms, vms/install_vms.txt (SMS)\n 8. Update notes.txt to add changes to program exit status values and changes\n    to messages.  vms/notes.txt (SMS)\n 9. Include crc32.h, include ssdef.h, instead of FAB_OR_NAM use FAB_OR_NAML,\n    add status code summary note detailing old versus new error codes, and if\n    CTL_FAC_IZ_ZIP is 0x7FFF and OLD_STATUS is defined use old VMS error codes.\n    vms/vms.c (SMS)\n10. Change FAB_OR_NAM to FAB_OR_NAML and remove NAME_DNA, NAME_DNS, NAME_FNA,\n    and NAME_FNS.  vms/vms.h (SMS)\n11. Change FAB_OR_NAM to FAB_OR_NAML.  vms/vms_im.c, vms/vms_pk.c,\n    vms/vmszip.c (SMS)\n12. Fix compile warning on VC 2005.  win32/makefile.w32 (Johnny)\n13. Update readmevb.txt and readvb64.txt.  windll/vb/readmevb.txt,\n    windll/vbz64/readvb64.txt (Ed)\n14. Change tch from int to ulg in utf8_from_ucs4_char().  Move comments to keep\n    line lengths to 80 characters.  fileio.c (Christian)\n15. Update comment for total_cd_entries.  global.c, zip.c, zip.h (Christian)\n16. Comment out unused Adler-16 code.  util.c, zip.h (Christian)\n17. Add InterlockedExchangePointer() macro if not defined.  Update Initialize()\n    to use macro.  nt.c (Christian)\n18. Move zip64 eocd disk and offset variables next to input archive variables.\n    zip.c (Ed)\n19. Remove zipbegset from scanzipf_fixnew() as offsets are ignored when this\n    is fixing archives.  Add comment to cd_total_entries.  Remove local\n    cd_start_disk and cd_start_offset as these are already global.  Use\n    ZIP_UWORD16_MAX when disk number exceeds this to flag use of Zip64.\n    zipfile.c (Christian)\n20. Some comment changes.  zipfile.c (Ed)\n21. Fix indentation in places.  zipsplit.c (Christian)\n22. Remove unused variable zfile.  zipup.c (Christian)\n23. Update manual.  zip.1, zip.txt, zipsplit.txt (Ed)\n---------------------- February 22nd 2007 version 3.0f28 ----------------------\n 1. Update notes.  vms/notes.txt (SMS)\n 2. Add stream_lf.fdl to specify carriage control.  vms/stream_lf.fdl (SMS)\n 3. Update License to also refer to www.info-zip.org and to hopefully provide\n    an example of misrepresentative use.  LICENSE (Ed)\n 4. Update Readme.  README (Ed)\n 5. Update WhatsNew.  WHATSNEW (Ed)\n 6. Change output archive cd_start_disk and cd_start_offset to input archive\n    local in_cd_start_disk and in_cd_start_offset in scanzipf_fixnew() and\n    scanzipf_regnew() to avoid mixing in and out.  zipfile.c (Ed)\n 7. Update copyright.  Remove crc32.h include.  vms/vms.c (Christian)\n 8. Changes for new crc32.  Remove CRC32.  Add CRCA_0 and CRCAUO.  Add\n    compiling of crc_i386.S.  win32/makefile.emx. (Christian)\n 9. Add handlers for better RSXNT and Windows OEM conversions.  Add detailed\n    comments on conversions.  win32/osdef.h (Christian)\n10. Define CP_UTF8.  win32/rsxntwin.h (Christian)\n11. Define WIN32_LEAN_AND_MEAN to reduce size of Windows includes.\n    win32/win32.c, win32/win32zip.c, zip.c (Christian)\n12. Use only standard FAT attributes if OEM.  win32/win32zip.c (Christian)\n13. Add use of INTERN_TO_OEM() and related OEM changes.  Add console comment.\n    zip.c (Christian)\n14. Change severity from char to int.  Update macros.  ziperror.h. (Christian)\n15. Update Visual Basic project to clarify some of the code.\n    windll/vbz64/vbzip.vbp, windll/vbz64/vbzipbas.bas,\n    windll/vbz64/vbzipfrm.frm (Ed)\n16. Update copyright.  api.c (Ed)\n17. Update format for duplicate entry warning.  fileio.c (Ed)\n18. Instead of ifdef __RSXNT__ use ifdef WIN32.  Define WIN32_LEAN_AND_MEAN.\n    Use WIN32_CRT_OEM.  Change OEM check from vem == 20 to vem & 0xff00 == 0\n    and instead of local_to_oem_string() use _INTERN_OEM().  Remove unused\n    first_CD in scanzipf_fixnew().  Instead of oem_to_local_string() use\n    Ext_ASCII_TO_Native().  Instead of local_to_oem_string() use\n    INTERN_TO_OEM().  zipfile.c (Christian)\n19. Replace escape from zipsplit man page with '.  zipsplit.txt (Christian)\n20. Instead of using 20 every time, account for dosify when setting vem.\n    Update FAT comment.  zipup.c (Christian)\n------------------------ March 3rd 2007 version 3.0f29 -------------------------\n 1. Remove crctab.c.  vms/build_zip.com (SMS)\n 2. Add LFLAGS_ARCH.  vms/descrip.mms (SMS)\n 3. Remove redundant includes descrip.h, rms.h, and atrdef.h.\n    vms/vmsmunch.c (SMS)\n 4. Remove includes descrip.h and rms.h.  vms/vmszip.c (SMS)\n 5. Only define NO_UNISTD_H if __VAX defined or __CRTL_VER is\n    less than 70301000, allowing support of the new symbolic\n    links in VMS.  Also use unlink instead of delete if version\n    above 70000000.  vms/osdep.h (SMS)\n 6. Formatting changes.  vms/notes.txt, vms/install_vms.txt (Christian)\n 7. Remove spaces before tabs.  win32/makefile.emx (Christian)\n 8. Formatting change.  win32/osdep.h (Christian)\n 9. If -y on VMS open the link not the target file.  vms/vms_im.c (SMS)\n10. If -y on VMS search for the link, not the target file.  vms/vms_pk.c (SMS)\n11. Change default for Unicode path mismatch from error to warning, so\n    processing will continue.  zip.c, globals.c (Ed)\n------------------------ March 12th 2007 version 3.0f30 ------------------------\n 1. Add bzip2 support for the reduced no stdio bzip2 library for VMS and Unix.\n    Use libbz2_ns_.olb for VMS bzip2 library which is compiled from the VMS\n    version of bzip2 with the BZ_NO_STDIO flag set.  This flag removes most\n    standard bzip2 stdio support and enables using a callback routine for\n    errors.  zbz2err.c, unix/Makefile, vms/build_zip.com, vms/descrip.mms,\n    vms/descrip_deps.mms, vms/descrip_src.mms (SMS)\n 2. Add zbz2err.c to Win32 vc6bz2 project for support of BZ_NO_STDIO for bzip2.\n    Modify zbz2err.c to handle different ports.  zbz2err.c (Ed)\n 3. Update license.  zip.h (Ed)\n 4. Update copyright.  zip.c, zipfile.c, zipup.c, zbz2err.c, revision.h (Ed)\n 5. Fix bug where directories got set to ver 4.6 in local headers instead of\n    ver 1.0 when using bzip2.  zipfile.c, zipup.c (Ed)\n 6. Minor updates to INSTALL.  INSTALL (Ed)\n 7. Minor updates to README.  README (Ed)\n 8. Add BZ_NO_STDIO to vc6bz2 projects.  Error routine seems to work.\n    win32/vc6bz2 (Ed)\n 9. Set bit FAB$M_BIO (.fab$v_bio) in the FAB when using sys$open() on a\n    symlink.  vms/vms_im.c (SMS)\n10. Change sys$disk to SYS$DISK.  vms/build_zip.com (SMS)\n11. Update extended help.  zip.c (Ed)\n12. Update bzip2 install.  bzip2/install.txt (Ed)\n------------------------ March 19th 2007 version 3.0f31 ------------------------\n 1. Define bz2_olb as LIBBZ2_NS.OLB.  Change LIBBZ2.OLB to bz2_olb.  Use\n    ZZBZ2ERR.C error callback for bzip2.  vms/build_zip.com (SMS)\n 2. Change NO_SYMLINK to NO_SYMLINKS to be consistent with UnZip.  tailor.h,\n    acorn/osdep.h, macos/osdep.h, tops20/osdep.h, vms/osdep.h (SMS)\n 3. Minor note changes.  Add section on Symbolic Links.  vms/notes.txt (SMS)\n 4. Update copyright.  globals.c (Ed)\n 5. Update License with official copy.  LICENSE (Greg, Ed)\n 6. Update Readme.  README (Ed)\n 7. Add support for NO_BZIP2_SUPPORT.  tailor.h (Ed)\n 8. Add common compiler flags to Install.  INSTALL (Ed)\n 9. Remove SPLIT_FILE define.  zip.c (Ed)\n10. Minor updates to extended help.  zip.c (Ed)\n11. Modify Makefile to also build bzip2 library if found.  Split $MAKE\n    (\"make -f unix/Makefile\") into $MAKE and $MAKEF, leaving $MAKE as defined by\n    Make and defining $MAKEF to \"-f unix/Makefile\".  Add clean_bzip2 target.\n    unix/Makefile (SMS)\n12. Modify configure to handle compiling bzip2.  unix/configure (SMS)\n13. Remove linking bzip2 with utilities.  Other changes.  unix/Makefile (Ed)\n14. Change bzip2 wrong library errors to warnings.  Put back OS bzip2 library\n    check.  Only compile bzip2 if in bzip2 directory.  unix/configure (Ed)\n15. More modifications to Makefile and configure to only allow compiling in\n    the bzip2 directory.  unix/Makefile, unix/configure (Ed)\n------------------------ March 27th 2007 version 3.0f32 ------------------------\n 1. Modify configure and Makefile to only allow compiling bzip2 in the Zip bzip2\n    source directory.  unix/Makefile, unix/configure (SMS, Ed)\n 2. Update bzip2 installation instructions.  bzip2/install.txt (SMS, Ed)\n 3. Remove need for BZIP2_USEBZIP2DIR define by using an appropiate include dir\n    specification (-I ../../bzip2) when needed.  zip.c, win32/vc6bz2/zip.dsp,\n    unix/configure (SMS, Ed, Christian)\n 4. Update VC6 readme.  win32/readmeVC.txt (Christian, Ed)\n 5. Add crc32.h to VC projects.  Add assembler group to zipcloak, zipnote, and\n    zipsplit projects.  Add BZ_NO_STDIO to all configurations with bzip2 so\n    reduced bzip2 code is used.  win32/vc6/zip.dsp, win32/vc6/zipcloak.dsp,\n    win32/vc6/zipnote.dsp, win32/vc6/zipsplit.dsp (Christian)\n 6. Update VC6bz2 readme.  win32/readVCBZ.txt (Christian, Ed)\n 7. Modify bzip2 VC6 workspace to use standard zipcloak, zipnote, and zipsplit\n    projects as they don't need bzip2.  win32/vc6bz2/zip.dsw (Christian)\n 8. Fix zlib flag problem by properly setting and clearing deflInit flag to\n    initialize and release resources.  zipup.c (Bill Brinzer, Christian)\n 9. Update copyright.  crypt.h, api.c, tailor.h, fileio.c, ziperr.h,\n    zipsplit.c, zipnote.c, zipcloak.c, util.c (Ed)\n------------------------ April 25th 2007 version 3.0f33 ------------------------\n 1. Fix -dd display_dots option for VMS.  Fix adding value for -ds to command\n    line.  Fix /NAMES = AS_IS for older header files.  cmdline.c (SMS)\n 2. Add Win32 wide scan support.  In fileio.c add Win32 wide functions lastw(),\n    msnamew(), newnamew(), wchar_to_wide_string(), is_ascii_stringw(),\n    wchar_to_local_string(), and wchar_to_utf8_string().  In globals.c\n    add no_win32_wide that is true if the wide versions of calls like\n    GetFileAttributesW() do not work as on Win9x without the Unicode kit.\n    In tailor.h define zwstat for stats that use wchar_t strings and\n    defines SSTATW and LSSTATW.  In util.c add isshexpw() and recmatchw()\n    and dosmatchw() for matching using wchar_t strings.  In win32.c add\n    FSusesLocalTimeW(), IsFileSystemOldFATW(), GetFileModeW(), GetLongPathEAW(),\n    and zstat_zipwin32w().  In win32zip.c add zdirscanw structure,\n    GetDirAttribsW(), zDIRSCANW, readdw(), wild_recursew(), procname_win32w(),\n    OpenDirScanW(), GetNextDirEntryW(), CloseDirScanW(), procnamew(),\n    local_to_wchar_string(), wchar_to_utf8_string(), in wild() code to\n    check if W versions are supported and send zip down byte or wide path,\n    ex2inw(), in2exw(), and filetimew().  In zipup.h define zwopen to use\n    wide paths.  In zipup.c if supported use filetimew() and zwopen().\n    In zip.h add namew, inamew, and znamew to zlist and flist.  In zip.c\n    remove duplicate initialization of use_wide_to_mb_default, force_zip64,\n    zip64_entry, and zip64_archive.  Use filetimew() if UNICODE_SUPPORT and\n    using wide paths for directory scan.  Remove old 8.3 path Unicode fix as\n    now use wide paths and get all where the 8.3 kluge missed paths where\n    characters in path needed multiple code pages.  Changes to bit 11 Unicode\n    but still not ready.  fileio.c, globals.c, tailor.h, util.c, zipup.h,\n    win32/win32.c, win32/win32zip.c, win32/win32.h, zipup.c, zip.c (Ed)\n 3. Update copyright.  Don't define UNICODE_SUPPORT if already defined.\n    Define MATCHW and zstat_zipwin32w().  win32/osdep.h (Ed)\n------------------------ April 29th 2007 version 3.0f34 ------------------------\n 1. Add temporary option -sC to test Unicode file creation enabled with\n    UNICODE_TEST define.  zip.c, fileio.c (Ed)\n 2. On Unix display control characters as ^X as UnZip.  (SMS) fileio.c\n 3. Update extended help.  zip.c (Ed)\n 4. Fix bugs in Unicode changes.  zip.c, fileio.c (SMS, Ed)\n 5. Add NAMES AS_IS support.  Handle root dir [000000].  zip.h,\n    vms/install_vms.txt, vms/vmszip.c, vms/vmsmunch.c (SMS)\n 6. Add global zipfile_exists to handle missing zipfile errors better.  zip.h,\n    globals.c, zip.c (Ed)\n 7. Add functions utf8_to_escape_string(), wide_to_escape_string(),\n    local_to_escape_string(), utf8_to_wchar_string(), and\n    rename wide_to_escape_string() to wide_char_to_escape_string().  fileio.c,\n    win32/win32zip.c, zip.h (Ed)\n 9. Free f->inamew in fexpel().  Use zuname for matching.  fileio.c (Ed)\n10. Fix memory bug by setting z->namew, z->inamew, and z->znamew to NULL.\n    Set f->namew, f->inamew, and f->znamew to NULL for new file in newname().\n    Free wide_string in local_to_utf8().  Other Unicode fixes.  Add namew,\n    inamew, and znamew to freeup().  fileio.c, win32/win32zip.c, zip.h (Ed)\n11. Move wchar functions only used by Windows to win32zip.c.  fileio.c,\n    zip.h (Ed)\n12. Fix spelling in manual.  zip.1 (SMS, Ed)\n13. Add zuebcmp() for Unicode.  zipfile.c\n14. Open files to read using wide name as input path.  zipup.c (Ed)\n15. Update help.  zip.c (Ed)\n16. Change -TT long option from --unzip-path to --unzip-command.  zip.c (Ed)\n17. Update Manual to include section on Unicode, add -TT option, make some\n    changes to Unicode in other sections, update copyright at bottom, and\n    some small changes to wording and examples.  man/zip.1, zip.txt (Ed)\n18. Put #ifdef WIN32 around WIN32 blocks.  zipfile.c (Ed)\n------------------------- May 14th 2007 version 3.0f35 -------------------------\n 1. Update VMS to include new options.  vms/cmdline.c, vms/zip_cli.cld (SMS)\n 2. Update VMS help.  vms/vms_zip.rnh (SMS)\n 3. Minor updates to VMS help.  vms/vms_zip.rnh (Ed)\n 4. Create global filter_match_case that defaults to 1 (case-sensitive).  zip.c\n    zip.h, globals.c (Ed)\n 5. Add option -fc to fold case for case-insensitive matching in filter().\n    Currently enabled only for WIN32.  zip.c, win32/osdep.h (Ed)\n 6. Change (action == DELETE || action == FRESHEN) to filter_match_case in\n    PROCNAME() define.  I just couldn't figure out what was going on here and\n    why the case flag was controlled by this.  zip.c (Ed)\n 7. Update WhatsNew.  WHATSNEW (Ed)\n------------------------- May 17th 2007 version 3.0f36 -------------------------\n 1. Touch date on generated file.  vms/ZIP_MSG.MSG (SMS, Ed)\n 2. Update Betas readme to include Release Candidates.  Betas_Readme.txt (Ed)\n 3. Update Zip 3.0f announcement.  zip30f.ann (Ed)\n 4. Minor updates to VMS help.  vms/cvthelp.tpu, vms/vms_zip.rnh (SMS)\n 5. Major changes to VMS CLI help.  vms/zip_cli.help (SMS, Ed)\n 6. Update license.  revision.h (Ed)\n------------------------- May 21st 2007 version 3.0f37 -------------------------\n 1. Rename -fc (fold case) to -ic (ignore case) which may be more intuitive.\n    zip.c (Ed)\n 2. VMS CLI updates for new options.  vms/cmdline.c, vms/vms_zip.rnh,\n    vms/zip_cli.cld, vms/zip_cli.help (SMS)\n 3. Updates to support Watcom C, mingw, djgppv2 and msc-16-bit, including\n    supporting wide stat and compare calls and work-around for problem with\n    \"no symlink support\" detection.  tailor.h, util.c, zip.c, win32/osdep.h,\n    win32/win32.c, win32/win32/zipup.h (Christian)\n------------------------- May 29th 2007 version 3.0f38 -------------------------\n 1. Update description.  file_id.diz (Ed)\n 2. Handle better when not splitting and run out of disk space.  Also, for split\n    method 1 (automatically write all splits to same place) exit if run out of\n    space instead of filling available space with near empty splits.  For split\n    method 2 require splits to be at least 64K bytes (the minimum split size).\n    fileio.c (Ed)\n 3. Add line break in ziperr() if message line has been started.  zip.c (Ed)\n 4. In ziperr() don't close output handle y if same as current_local_file handle\n    and just closed that.  zip.c (Ed)\n 5. Change default definition of PROCNAME() to handle new filter_match_case flag\n    and restore backward compatibility.  zip.c (Christian, Ed)\n 6. Add note detailing definition of PROCNAME().  zip.c (Ed)\n 7. Remove nonlocalpath parameter from procname_win32() and procname_win32w()\n    and variables nonlocal_path and nonlocal_name as this is not used now that\n    unicode is implemented in WIN32 using the wide calls.\n 8. Enable ignore case option for VMS.  zip.c (SMS)\n 9. Update -v and other updates in manual.  man/zip.1 (Christian, Ed)\n10. Updates for Watcom C and Win32 symlinks.  win32/osdep.h (Christian)\n11.  Fix historic problem with VAX seeking.  zipfile.c (SMS)\n12. Add NAM_M_EXP_DEV.  Add determination if device is in file specification.\n    If device name in file specification do ODS2 and ODS5 down-casing.\n    Define explicite_dev().  vms/vms.h, vms/vmszip.c (SMS)\n------------------------- June 4th 2007 version 3.0f39 -------------------------\n 1. Update osdep.h to use new filter_match_case flag.  vms/osdep.h (SMS)\n 2. Fix unterminated string bug and trim extra allocated space in\n    local_to_display_string().  fileio.c (Ed)\n 3. Updated extended help for -u and -ic options.  zip.c (Ed)\n 4. Update Manual.  man/zip.1, zip.txt (Ed)\n------------------------- June 15th 2007 version 3.0f40 -------------------------\n 1. Update Unicode Path and Unicode Comment descriptions based on suggestions\n    from WinZip.  proginfo/extrafld.txt (Steve Gross, Ed)\n 2. Update descriptions for Add, Update, and Freshen in the manual.  man/zip.1\n    (Christian)\n 3. Update default definition of PROCNAME() to use filter_case_match flag to\n    turn off case matching in filter().  zip.c (Christian)\n 4. Update WhatsNew.  WHATSNEW (Ed)\n 5. Update announcement.  zip30f.ann (Ed)\n 6. Update manual.  man/zip.1, zip.txt (Ed)\n------------------------- July 7th 2007 version 3.0f41 -------------------------\n 1. Use File Name as Unicode path if UTF-8 flag is set in header.  zip.c,\n    globals.c, zipfile.c, zip.h (Ed)\n 2. Update ToDo.  TODO (Ed)\n 3. Update WhatsNew.  WHATSNEW (Ed)\n 4. Update ReadMe.  README (Ed)\n 5. Fix problems with incompatible stat types on Win32.  fileio.c, tailor.h,\n    zip.h, win32/win32.c, win32/win32zip.c, win32/osdep.h (Ed)\n 6. Define NO_STREAMING_STORE to turn off storing while streaming.\n    INSTALL, zipup.c (Ed)\n 7. Define UNICODE_ALLOW_FORCE to enable -UN=force option which is now\n    disabled and would need work.  globals.c, zip.h (Ed)\n 8. Add global using_utf8 to flag when OS current character set is UTF-8.\n    If an existing entry has the UTF-8 flag set the flag is kept.  If a new\n    entry needs Unicode and on a UTF-8 system assume the strings are UTF-8\n    and set the UTF-8 flag.  globals.c, zip.h (Ed)\n 9. Update Unicode extra field descriptions.  proginfo/extrafld.txt (Ed)\n10. Add include directory so can find bzip2 header file when using bzip2\n    directory.  unix/configure (Ed)\n11. Fix wide character wild(), wild_recursew() and OpenDirScanW() for Win32 so\n    work like the regular versions.  win32/win32zip.c (Ed)\n12. Update Unicode in manual.  Update -W description in manual  zip.1\n13. Flush logfile writing.  zip.c (Ed)\n14. Update extended help for -UN option.  Update help for Update to note it\n    updates files where the OS has a later date.  Chance -UN=Exit to -UN=Quit\n    so can abbreviate to first letter.  zip.c (Ed)\n15. Fix a bug in readzipfile() when zip used in pipe.  Other pipe fixes.  zip.c,\n    zipfile.c (Ed)\n------------------------ August 10th 2007 version 3.0f42 -----------------------\n 1. Update error message for -DF.  zip.c (Ed)\n 2. Add bzipped message to write to log file.  zipup.c (Ed)\n 3. Update bzip2 install instructions.  bzip2/install.txt (Ed)\n 4. Move local.h include to tailor.h to fix compiler multiple define.  tailor.h,\n    zip.c (SMS)\n 5. Add additional C compiler checks for GNU and HP.  unix/configure (SMS)\n 6. Fix to build libbz2.a.  unix/Makefile (SMS)\n 7. Update copyright.  acorn/osdep.h, macos/osdep.h, tops20/osdep.h,\n    vms/vmszip.c, vms/vmsmunch.c, vms/vms_pk.c, vms/vms_im.c, vms/vms.h,\n    vms/vms.c, vms/osdep.h, win32/rsxntwin.h, win32/osdep.h, win32/nt.c (Ed)\n 8. Change zfeeko(file, 0, SEEK_SET) to rewind(file) in ffile_size() so\n    EOF is always reset.  This was creating problems in WIN32 when\n    NO_ZIP64_SUPPORT was set but LARGE_FILE_SUPPORT was set.  zipfile.c (Ed)\n 9. Update compile -v descriptions for LARGE_FILE_SUPPORT and ZIP64_SUPPORT to\n    be more specific as to what each does.  zip.c (Ed)\n10. Fix bug that added the local header size to the next entry compressed size\n    giving a wrong compressed size error if splitting and the split occurs when\n    writing a local header.  fileio.c (Ed)\n11. Remove UNICODE_TEST define from VC 6 projects.  win32/vc6/zip.dsp,\n    win32/vc6/zipcloak.dsp, win32/vc6/zipnote.dsp, win32/vc6/zipsplit.dsp (Ed)\n12. Update extended help.  zip.c (Ed)\n13. Only output -FF central directory messages in verbose mode.  zipfile.c (Ed)\n14. Add note about possible bug when copying entries from a split archive.\n    WHATSNEW (Ed)\n------------------------ August 11th 2007 version 3.0f43 -----------------------\n 1. Display locale inside check to avoid NULL locale.  zip.c (SMS, Ed)\n 2. Add include wchar.h to tailor.h.  tailor.h (SMS)\n------------------------ August 21st 2007 version 3.0f44 -----------------------\n 1. Remove verbose messages when setting locale as verbose flag is not set yet.\n    zip.c (SMS, Ed)\n 2. Change reading splits message \"abort archive\" to \"abort archive - quit\" and\n    change selection letter from a to q so q quits consistently.  For quit,\n    don't confirm as more annoying than helpful.  fileio.c (Ed)\n 3. In bfwrite() handle case where a split ends at the end of one entry and\n    trying to write the next local header forces opening next split.  This\n    caused copying entries from one archive to another to fail if this came up.\n    Also handle case where a new split is needed while writing central directory\n    entries.  Now close last split and update pointers to point to the new\n    split.  fileio.c (Ed)\n 4. Update use of mesg_line_started and add new logfile_line_started to account\n    for line ends in logfile.  fflush() output.  zip.c, zip.h, globals.c (Ed)\n 5. Move setting split size if input archive is split and split_size not set\n    to after archive is read.  zipfile.c, zip.c (Ed)\n 6. Update Manual to describe Unicode as implemented and note that old splits\n    are not automatically excluded.  man/zip.1, zip.txt (Ed)\n 7. Update WhatsNew to remove note that creating and copying split archives\n    is broke as it seems fully working now.  WHATSNEW (Ed)\n 8. Update announcement.  zip30f.ann (Ed)\n------------------------ August 31st 2007 version 3.0f45 -----------------------\n 1. Unicode fix for VMS.  tailor.h (SMS)\n 2. Add member current to zlist structure to flag when an archive entry is\n    current with the matching OS file using file time and size.  This is used by\n    File Sync to copy current entries from archive.  zip.h, zip.c (Ed)\n 3. Comment out zip info verbose extra data message as this message does not\n    seem to add much.  zipfile.c (Ed)\n 4. Add local and central directory Version Needed To Extract to mismatch\n    warning.  Update warning text.  zipfile.c (Ed)\n 5. Add function BlankRunningStats() to output blanks for the running stats\n    part of the line to use when displaying stats for entries not on the mark\n    list so all output lines up.  zip.c\n 6. Add -FS to extended help as new mode.  zip.c (Ed)\n 7. Update description of -FF to remove Assume Worst.  zip.c (Ed)\n 8. Add all_current flag that is set if all entries in archive are current and\n    skip updating archive if -FS and all entries are current.  zip.c (Ed)\n 9. Change argv[] to args[] for \"try: zip\" error message as message depends on\n    new argument order in args where options are now at beginning.  zip.c (Ed)\n10. For File Sync, copy entries to new archive if file time and size are the\n    same.  If verbose, output ok when copying current entries, otherwise no\n    message when current_entry.  Set all_current to 0 if an entry not marked or\n    a file not on OS as need to avoid the All Current message in these cases to\n    catch only deletions.  zip.c (Ed)\n11. Initialize variables excluding zipstate and setjmp() if USE_ZIPMAIN defined\n    to fix bug when recall zipmain().  zip.c (Ed)\n12. Update Manual.  zip.1, zip.txt (Ed)\n13. Update WhatsNew.  WHATSNEW (Ed)\n14. Update announcement.  zip30f.ann (Ed)\n----------------------- September 5th 2007 version 3.0f46 ----------------------\n 1. Move write of local header after when GPB11 UTF-8 bit set in putlocal().\n    zipfile.c (Ed)\n 2. Change to uppercase for compatibility.  vms/install_vms.txt (SMS)\n 3. Set cenbeg and bytes_this_split to fix grow.  Check if grow split archive.\n    zipfile.c, zip.c (Ed)\n----------------------- September 14th 2007 version 3.0f47 --------------------\n 1. Include address for new Info-ZIP forum.  Add note on 16-bit OS support.\n    Add note about text file line ends.  README (Ed)\n 2. Update WhatsNew to include latest on Unicode.  Add section on plans for\n    Zip 3.1.  WHATSNEW (Ed)\n 3. Minor change in note for Unicode in extended help.  zip.c (Ed)\n 4. Modify definitions of Unicode extra fields based on discussions with PKWare\n    and WinZip.  proginfo/extrafld.txt (Ed)\n 5. Add note on UTF-8 flag.  INSTALL (Ed)\n 6. Minor updates to ToDo list.  Needs more work.  TODO (Ed)\n 7. Update announcement.  zip30f.ann (Ed)\n 8. Change definition of IZ_OUR_BZIP2_DIR to be compatible with Configure and\n    to work with HP-UX.  unix/Makefile (SMS)\n------------------------ September 24th 2007 version 3.0f ---------------------\n 1. Update extended help Unicode description.  zip.c (Ed)\n 2. Update Readme.  README (Ed)\n 3. Fix case of define identifying IA64.  vms/vms.c (SMS)\n 4. Update announcement date.  zip30f.ann (Ed)\n 5. Update Unicode extra field definitions based on changes proposed for\n    AppNote.  extrafld.txt (Ed)\n------------------------ October 17th 2007 version 3.0g01 ---------------------\n 1. Can get stuck on open Unix FIFO so default to skip and add option -FI to\n    enable reading FIFO.  Add global allow_fifo.  zip.c, zip.h, globals.c\n    (Willus 0, Ed)\n 2. As problems with MinGW with wide-character paths, disable wide-character\n    Unicode support.  zip.c, unix/unix.c (Willus 0, Ed)\n 3. Update manual installs to include zipcloak.1, zipnote.1, and zipsplit.1\n    pages.  unix/Makefile (Ed)\n 4. Update Solaris packages.  unix/Packaging/pkginfo.in,\n    unix/Packaging/postinstall, unix/Packaging/preinstall.in,\n    unix/Packaging/prototype (SMS)\n------------------------ October 30th 2007 version 3.0g02 ---------------------\n 1. Fix bug in get_in_split_path() where look for .zip split when attempting\n    to open archives without a .zip extension, even when a single file archive\n    like jar file.  fileio.c (Gabriele (balducci@units.it), Ed)\n 2. Fix bug where temp file got created in current working directory on Unix\n    by giving entire archive path to mkstemp() as template.  fileio.c, zip.c\n    (Willus, Ed)\n 3. Use 64-bit output functions for bits_sent.  trees.c (SMS)\n 4. Add -FF to fixfix -sd messages to make different from identical main\n    messages. zip.c (SMS, Ed)\n 5. If quiet do not ask for splits and all splits must be in same location.\n    zipfile.c (Ed)\n 6. Clean up making zip manuals.  unix/Makefile (Ed, SMS)\n 7. Add clean_exe to make.  unix/Makefile (SMS)\n 8. Update to VMS Notes, including adding details on symlinks, -V, and UTC\n    dates times.  vms/notes.txt (SMS)\n 9. Fix bug in wild() when calling wile_recursew() where qw should be\n    pointing inside pw.  win32/win32zip.c (Willus, Ed)\n10. Fix bug where is_ascii_string() fails when passed a NULL string.  This\n    may fix problem where the CentOS mbstowcs() function is returning -1 when\n    trying to convert a file name with a bad character (0xe6), causing\n    local_to_wide_string() and then local_to_utf8_string() to return NULL, so\n    f->uname gets NULL and so is_ascii_string() fails with SIGSEGV.  fileio.c\n    (Willus, Ed)\n------------------------ October 31st 2007 version 3.0g03 ---------------------\n 1. Add handling of -b temp directory when opening splits in bfwrite() using\n    mkstemp().  fileio.c (SMS, Ed)\n------------------------ November 3rd 2007 version 3.0g04 ---------------------\n 1. Move show_files to global so can avoid split warning for -sf.  zip.c,\n    globals.c, zip.h, zipfile.c (Ed)\n 2. Account for -b tempath when opening temp file.  zip.c, zipnote.c,\n    zipcloak.c (SMS, Ed)\n------------------------ November 4th 2007 version 3.0g05 ---------------------\n 1. Minor fixes to fdopen calls.  zipcloak.c, zipnote.c (SMS, Ed)\n------------------------ November 4th 2007 version 3.0g06 ---------------------\n 1. Add negation to -db, -dc, -dd, -dg, -du, -dv display options.  zip.c (Ed)\n 2. Put back UNICODE_SUPPORT no_win32_wide code left out in previous fix.\n    win32/win32zip.c (Willus, Ed)\n------------------------ November 21st 2007 version 3.0g07 ---------------------\n 1. Fix bug preventing newline in some cases in zipmessage().  zip.c (Ed)\n 2. Update Unicode help.  zip.c (Ed)\n 3. Update -sd messages.  zip.c (Ed)\n 4. Add filetimew() for Unicode case.  zip.c (Ed)\n 5. Add ClearArchiveBitW() for Win32 wide.  zip.c, zip.h, win32/win32.c (Ed)\n 6. Only ask for .zip split if path ends in .znn or .znnn where n 0 to 9.  This\n    allows -FF to work on .exe sfx files without adding .zip.  zipfile.c (Ed)\n 7. Fix bug where only backed up 20 bytes to find Z64 EOCD Locator.  Now back\n    up 24 bytes to include size of Z64 EOCD Locator signature.  This prevented\n    reading and updating archives greater than 4 GB.  zipfile.c (Ed)\n 8. If -FF on Win32 initialize wide strings namew, inamew, and znamew to NULL.\n    zipfile.c (Ed)\n 9. Add #include <wctype.h> to support towupper().  tailor.h (SMS)\n------------------------ December 4th 2007 version 3.0g08 ---------------------\n 1. Update dot_size comment.  globals.c (Ed)\n 2. Update Compression in extended help.  zip.c (Ed)\n 3. Add extended help on self extractor -A and -J.  zip.c (Ed)\n 4. Update VMS SYMLINK version information.  zip.c (SMS)\n 5. Remove not final from Unicode version information as final now.  zip.c (Ed)\n 6. Remove apparently not needed WINDLL variable retcode.  zip.c (Ed)\n 7. Fix -A to calculate sfx offset and adjust offsets as it should.  zip.c (Ed)\n 8. Split -F and -FF used with -A warning to separate warnings.  zip.c (Ed)\n 9. Add adjusting to can't to that to split archive error.  zip.c (Ed)\n10. Fix bug for -A that tries to open split by asking for disk 0 instead of\n    disk 1.  Add adjust_offset and cd_total_size variables.  Calculate\n    sfx offset by determining offset of start of central directory.  Archives\n    larger than 4 GB are not supported as sfx archives but these don't seem\n    to work anyway.  Add adjust_offset to Zip64 EOCDR offset and central\n    directory offsets.  zip.c, zipfile.c (Ed)\n11. Comment out here debug variable in find_next_signature().  zipfile.c (Ed)\n12. Change %2x to %02x as format for parts of a signature in error messages.\n    zipfile.c (SMS)\n13. Add warning adjusting split archives not yet supported.  zipfile.c (Ed)\n14. Add period to central directory comment.  zipfile.c (Ed)\n15. Update readme for vb Zip64 project.  windll/vbz64/readvb64.txt (Ed)\n16. Update comments of VB for Zip64 example.  Add SplitSize to VB Zip64\n    example.  windll/vbz64/vbzipbas.bas, windll/vbz64/vbzipfrm.frm  (Ed)\n17. Add SourceForge to comment noting where can get the source code.\n    windll/vbz64/vbzipfrm.frm (Ed)\n18. Update WhatsNew.  WHATSNEW (Ed)\n------------------------ December 12th 2007 version 3.0g09 --------------------\n 1. A few minor changes to extended help.  zip.c (Ed)\n 2. Uppercase beginning of most -sd messages.  zip.c (Ed)\n 3. Add spaces between options in some error messages.  zip.c (Ed)\n 4. Update comments in scanzipf_regnew().  zipfile.c (Ed)\n 5. Update scanzipf_regnew() to figure out sfx offset. (Ed)\n 6. Uppercase VMS RUNOFF file as apparently needed.  VMS_ZIP.RNH (SMS)\n 7. Add comments to zipmessage().  zip.c (Ed)\n 8. Update extended help and option descriptions.  zip.c (Ed)\n------------------------ December 20th 2007 version 3.0g10 --------------------\n 1. Fix -F to include -A adjustment check.  zipfile.c (Ed)\n 2. Change -FF message when find EOCDR.  zipfile.c (Ed)\n 3. For -FF, reset first CD entry flag in_central_directory when a local entry\n    is found after CD entries so that another CD entry forces sorting of all\n    local entries to that point.  This allows files with multiple archives in\n    them to be processed.  zipfile.c (Ed)\n 4. Add message when a local entry is found after a central directory.\n    zipfile.c (Ed)\n 5. Remove word offset from disk offset location messages.  zipfile.c (Ed)\n 6. Make Adjust offset message more descriptive.  zipfile.c (SMS, Ed)\n 7. In scanzipf_regnew(), if adjustment to offsets, add it to\n    in_cd_start_offset.  zipfile.c (Ed)\n 8. Allocate cextra only if localz->ext not 0 in zipcopy().  zipfile.c (Ed)\n------------------------ December 28th 2007 version 3.0g11 --------------------\n 1. Include definitions of zip64_eocdr_start and z64eocdl_offset in\n    ZIP64_SUPPORT ifdef block.  Add comments for End Of CD Record (EOCDR).\n    Update comments for adjust offset detection.  zipfile.c (Ed)\n 2. Change ((uzoff_t)1 << 32) to 0xFFFFFFFF.  zipfile.c (SMS, Ed)\n 3. Leave off local header detection as not useful when searching for start\n    of central directory to get adjust offset.  Looks like all expected cases\n    are now covered as long as archive is intact.  zipfile.c (Ed)\n 4. Update some warning messages.  Simplify adjust offset information message.\n    zipfile.c (Ed)\n 5. Add braces to unicode_mismatch if block.  zipfile.c (Christian)\n 6. Add (void *) cast in InterlockedExchangePointer() mutex calls to fix\n    compile warnings in MinGW (GCC 3.4.4).  win32/nt.c (Christian)\n 7. Remove unused nonlocalpath variable.  win32/win32zip.c (Christian)\n 8. Update betas readme file.  betas_readme.txt (Ed)\n 9. Partial update to Who list of contributors.  proginfo/infozip.who (Ed)\n10. Update ReadMe.  Create Announcement.  README, zip30g.ann (Ed)\n11. Update WhatsNew.  WHATSNEW (Ed)\n------------------------ January 7th 2008 version 3.0g12 --------------------\n 1. Convert Scanning files message to use standard zipmessage_nl() so line\n    ends are generated when needed.  fileio.c (Ed)\n 2. Add line ends in DisplayRunningStats() if a display line has been\n    started.  zip.c (Ed)\n 3. For the command line listed at the top of the log file, add double\n    quotes around any arguments that have spaces in them.\n    zip.c (Ed)\n 4. Instead of stdout use standard mesg output stream for show files.\n    Output new line for show files for display and log file if there was\n    output on the current line.  zip.c (Ed)\n 5. Comment out new line output code after zipup() and replace with\n    call to zipmessage_nl(\"\", 1) to output new line if needed.\n    zip.c (Ed)\n 6. In GetFileMode() and GetFileModeW() when get attributes fails\n    instead of fprintf(mesg, ...) use zipwarn() so error goes in\n    log file and new lines are displayed when needed.  win32/win32.c (Ed)\n 7. In GetSD(), change cbytes from long to ulg.  Check cbytes (the\n    compressed size of the security descriptor) and issue warning if\n    the compressed security descriptor is greater than 0x7FFF (32k)\n    as the entire header this extra field is in needs to fit in the\n    64k header.  Should be a check on the running size of the header\n    so the actual space remaining is tracked.  Maybe in Zip 3.1.  If\n    cbytes OK cast to ush and store.  win32/win32zip.c (Ed)\n 8. Use zipmessage_nl() for bytes security message so new lines are\n    handled and message goes in log file.  win32/win32zip.c (Ed)\n 9. Add new option -RE to enable [list] (regex) matching in DOS and\n    WIN32 but disable [list] matching otherwise.  Default behavior\n    is restored if ALLOW_REGEX is defined.  globals.c, util.c,\n    zip.h, zip.c (Ed)\n------------------------ January 20th 2008 version 3.0g13 --------------------\n 1. Update copyrights to 2008.  zip.c, zipcloak.c, zipfile.c, zipnote.c,\n    zipsplit.c, zipup.c, README (Ed)\n 2. Update Who.  proginfo/infozip.who (Ed)\n------------------------ January 30th 2008 version 3.0g14 --------------------\n 1. Update copyrights.  fileio.c, globals.c, revision.h, util.c, zip.h,\n    win32/win32.c, win32/win32zip.c (Ed)\n 2. Updates.  README, proginfo/infozip.who (Ed)\n 3. Update announcement and WhatsNew.  zip30g.ann, WHATSNEW (Ed)\n 4. Add ALLOW_REGEX to INSTALL define list.  INSTALL (Ed)\n 5. Change -sd message.  zip.c (Ed)\n 6. For bzip2 check for binary and set binary/text flag.  Handle -l and -ll\n    line end conversions for bzip2.  zipup.c (Ed)\n------------------------ February 3rd 2008 version 3.0g --------------------\n 1. Change && to || to fix logic bug in show files.  zip.c (Johnny)\n 2. Add CLEAN and CLEAN_ALL VMS targets.  vms/descrip_mkdeps.mms (SMS)\n----------------------- February 22nd 2008 version 3.0h01 --------------------\n 1. Update some echo statements to use CFLAGS_OPT.  Add GNUC check.\n    unix/configure (SMS)\n 2. Only store UID and GID if 16 bit.  unix/unix.c (Ed)\n----------------------- March 21st 2008 version 3.0h02 --------------------\n 1. Change long Unicode escapes from 8 characters to 6 characters based on\n    change in UnZip 6.0.  fileio.c (Ed)\n 2. Put zuebcmp() declaration in #if 0 block as definition already is.  This\n    function would be used to allow Unicode escapes on the command line\n    without using the -UN=escape option, but the utility of this is still\n    being determined.  zipfile.c (SMS, Ed)\n 3. Remove declaration for unused bz_deflate_init().  zipup.c (SMS, Ed)\n 4. Add release announcement file, anticipating the long-awaited release.\n    zip30.ann (Ed)\n 5. Update WhatsNew.  WHATSNEW (Ed)\n----------------------- March 24th 2008 version 3.0h03 --------------------\n 1. Update Unix configure script to better test for modern HP-UX compiler.\n    unix/configure (SMS)\n 2. Updated Beta Readme.  betas_readme.txt (Ed)\n 3. Update Install.  INSTALL (Ed)\n 4. Update ReadMe.  README (Ed)\n 5. Small change to main help screen.  zip.c (Ed)\n 6. Small update to top of ToDo list.  Actual updating of items still\n    needs to be done.  TODO (Ed)\n----------------------- April 2nd 2008 version 3.0h04 --------------------\n 1. Update copyright.  crc32.h (Christian)\n 2. Remove zip.h include.  crc32.h (Christian)\n 3. Add local prototypes for Unicode functions.  Add cast for split size\n    check.  Make many Unicode functions local.  #if 0 out currently unused\n    utf8_chars().  Fix memory leak in wide_to_local_string() by adding\n    free() for buffer on error return.  Fix memory leak in copy_args() on\n    error return by adding free-args().  Add ZCONST to arg in\n    insert_arg().  Shorten some lines to less than 80 characters.  Add\n    free() to get_longopt() to fix memory leak.  fileio.c (Christian)\n 4. Create Win32 versions of wide_to_local_string() and\n    local_to_wide_string() so can use Win32 conversion functions.\n    fileio.c, win32/win32.c (Christian)\n 5. Update comments for get_option().  fileio.c (Ed)\n 6. Update encryption code readme.  README.cr (Ed)\n 7. Add prototype for recmatchw().  util.c (Christian)\n 8. Change count_args() from static to local.  util.c (Christian)\n 9. Change ifdefs for includes for prototypes for version_info(),\n    zipstdout(), and check_zipfile() for WINDLL and MACOS and add\n    check_unzip_version().  zip.c (Christian)\n10. Change ifndef NO_SYMLINKS to ifdef S_IFLNK for determining compiler\n    information.  zip.c (Christian)\n11. Change UTF-8 locale from en_GB.UTF-8 to .UTF-8.  zip.c (Christian)\n12. Change cast of -1 for dot_size from uzoff_t to zoff_t.\n    zip.c (Christian)\n13. Change prototype for set_filetype to include parameter char *.\n    Change prototype of has_win32_wide to include parameter void.\n    zip.h (Christian)\n14. Add prototypes for find_next_signature(), find_signature(),\n    and is_signature().  Change duplicate prototype scanzipf_regnew()\n    to missing prototype scanzipf_fixnew().  Change comment for Adler-16\n    checksum to CRC-32 checksum as that is being used at that point in\n    the code.  Move multiple uname assignments to common assignment.\n    Add inameLocal for WIN32_OEM and use define for inameLocal if not\n    to save memory allocation when not not using WIN32_OEM.  Also\n    change _INTERN_OEM(str1) to INTERN_TO_OEM(src, dst) for OEM\n    conversion.  Format comment for vem to fit in 80 character lines.\n    zipfile.c (Christian)\n15. Change variable a from buffer to a pointer and add abf as the\n    buffer for zgetline() to handle NULL case.  zipnote.c (Christian)\n16. Change comments to zipentry comments and zipfile comment in\n    messages.  zipnote.c (Ed)\n17. Use uidgid_16bit as flag variable instead of uid_size.  Modify\n    size check that prevents saving Unix UIDs and GIDs in the old\n    Unix extra field if they are not 16 bits.  Change memory\n    allocation based on uidgid_16bit.  Delete unused code for memory\n    copy for extra field.  unix/unix.c (Christian, Ed)\n18. Change compiler flag from -zp8 to -Zp8 for LCC Win32.\n    win32/makefile.lcc (Christian)\n19. Add ifndef debug.  Add bzip2 support.  Add additional compiler\n    flags.  win32/makenoas.w32 (Christian)\n----------------------- April 10th 2008 version 3.0h05 --------------------\n 1. Fix bug found by forum poster where Zip stops recursing down a tree\n    when option -AS is set and a directory without the Windows archive\n    bit is reached.  Now Zip continues down the tree to include files with\n    the bit set.  win32/win32zip.c (forum poster, Ed)\n 2. Update comments.  win32/osdep.h (Ed)\n 3. Update VMS notes to better organize and add information about file\n    name case.  Additional small updates.  vms/notes.txt (SMS)\n 4. Fix bugs from previous changes to unix.  unix/unix.c (SMS, Christian,\n    Ed)\n 5. Add unix IBM support.  unix/unix.c (SMS)\n 6. Update INSTALL to account for new distribution structure and other\n    changes. INSTALL (SMS, Ed)\n 7. Update bzip2 install readme.  bzip2/install.txt (SMS, Ed)\n 8. Fix bug noted in forum where -@ and -x generated a \"nothing to\n    select from error\" by also checking filelist variable populated by\n    -@ for entries.  zip.c (forum poster, Ed)\n----------------------- April 20th 2008 version 3.0h06 --------------------\n 1. Start announcement for Zip 3.0h public beta.  zip30h.ann (Ed)\n 2. Update beta readme.  betas_readme.txt (Ed)\n 3. Update case of README.CR.  INSTALL (Ed)\n 4. Change -W to -ws for option to stop wildcards from scanning directory\n    boundaries in path.  This frees up -W for later use, maybe as extendted\n    option introducer.  zip.c, man/zip.1 (Ed)\n 5. Updated date in announcement to May 4th.  zip30.ann (Ed)\n 6. Added announcement for public beta Zip 3.0h.  zip30h.ann (Ed)\n 7. Fix large file support for MinGW by checking for compiler environments\n    before the check for (generic) gcc.  zipup.c, win32/osdep.h\n    (Will, Christian)\n 8. Fix large file support for bzip2.  Additionally, the \"dot printout\"\n    code has also been adapted for LARGE_FILE support.  zipup.c\n    (Will, Christian)\n 9. Add comments to top of configure.  unix/configure (Ed)\n10. Move comment and comment out value size check for UID/GID extra field.\n    unix/unix.c (Ed)\n11. Change case of file ToDo to TODO for consistency and to work with Unix\n    package.  TODO (SMS, Ed)\n----------------------- April 26th 2008 version 3.0h07 --------------------\n 1. For -AS, which for Windows only includes files with the archive bit\n    set, exclude directory entries (by setting -D) as some directories may\n    not have any files with the archive bit set and so the directory would\n    be empty.  zip.c (Ed)\n 2. Fix UID/GID size detection to use byte sizes and remove data fit test.\n    unix/unix.c (Ed)\n 3. Update announcement.  zip30h.ann (Ed)\n 4. Add new unix extra field with tag 'ux' that stores UIDs/GIDs of 1 to 4\n    bytes (8 to 32 bits).  unix/unix.c (Ed)\n 5. Update VB readme.  windll/vbz64/readVB64.txt (Ed)\n 6. For Unicode escaped output also show escape for ASCII 7-bit if\n    isprintable() is false.  fileio.c (Ed)\n 7. Use locale \"en_US.UTF-8\" for Unix.  zip.c (Ed)\n 8. Also show escaped Unicode for new files in found list.  zip.c (Ed)\n 9. Update manual.  man/zip.1, zip.txt (Ed)\n------------------------ May 4th 2008 version 3.0h08 -----------------------\n 1. Handle when a bad Unicode string in archive forces\n    utf8_to_wide_string() to return a NULL string.  Give warning if UTF-8\n    in existing archive is bad.  Put WIN32 wide local header initializations\n    in UNICODE_SUPPORT block.  fileio.c, zipfile.c (Ed)\n 2. Leave out Unicode escape code if not Unicode enabled.  zip.c (Ed)\n 3. Enable oem_to_local_string() and local_to_oem_string() for WIN32\n    even if no Unicode.  zip.h, win32/win32.c (Christian, Ed)\n 4. Update comment about encryption code.  zipcloak.c (Ed)\n 4. Update zipmessage_nl() and zipmessage() from zip.c.  zipcloak.c,\n    zipnote.c, zipsplit.c (Ed)\n 5. Add Mac OS X library check.  unix/configure (SMS)\n 6. Add 16-bit UID/GID check.  unix/configure (Christian, Ed)\n 7. Format echo and comment statements a bit.  unix/configure (Ed)\n 8. Only compile in old 16-bit UID/GID code if new define UIDGID_NOT_16BIT\n    from unix configure script is not defined.  unix/unix.c (Christian)\n 9. A couple changes to updated 16-bit UID/GID code.  Add 64-bit\n    UID/GID support to new Unix extra field.  unix/unix.c (Ed)\n10. Remove redundant \"license\" from options table.  zipcloak.c (Ed)\n11. Remove old unix build files.  unix/configure-orig, unix/Makefile-orig\n    (Christian)\n12. Add -O (--output-file) option to ZipCloak.  Fix bug by setting\n    out_path.  zipcloak.c (Ed)\n------------------------ May 8th 2008 version 3.0h09 -----------------------\n 1. Update copyright.  Add check for NO_UNICODE_SUPPORT.  tailor.h (Ed)\n 2. Fix bug where Unicode General Purpose Bit Flag 11 should force keeping\n    the old name field but it was being overwritten by the escaped name\n    in the central directory header.  Fixed some ZIPERR() calls in\n    putcentral() that referred to putlocal().  zipfile.c (Ed)\n 3. Add comment about OCRCU8 and OCRCTB.  unix/configure (Ed)\n 4. Change line in instructions to note that manuals should be made after\n    Zip is made.  Change OCRTB to OCRCTB.  Add $(OCRCTB) to rule for\n    zipcloak$E so crc32_.o is linked in.  Add comment for NO_UNICODE_SUPPORT\n    flag.  unix/makefile (Ed)\n 5. Update WhatsNew.  Add additional items to the Zip 3.1 list.  Add note\n    about Zip 2.4.  WHATSNEW (Ed)\n 6. Update Zip 3.0h announcement.  zip30h.ann (Ed)\n 7. Update manual pages.  man/zip.1, man/zipsplit.1, man/zipnote.1,\n    man/zipcloak.1 (Ed)\n 8. Add noted for UTF-8 locale.  zip.c (Ed)\n 9. Set UTF-8 locale for Unix in utilities if UNICODE_SUPPORT enabled\n    so can display and process paths in archives correctly.  zipsplit.c,\n    zipcloak.c, zipnote.c (Ed)\n------------------------ May 12th 2008 version 3.0h10 ----------------------\n 1. Add use of new Unix UID/GID extra field and of old Unix 16-bit UID/GID\n    extra field when system uses 16-bit UIDs/GIDs to version information.\n    zip.c (SMS, Ed)\n 2. Add Unicode Path and Unicode Comment extra fields to extra fields list.\n    Update new Unix extra field revision date.  proginfo/extrafld.txt (Ed)\n 3. Add Mac hardware platform to version information.  unix/unix.c (SMS)\n------------------------ May 19th 2008 version 3.0h11 ----------------------\n 1. Initialize f->namew when streaming stdin to fix bug.  fileio.c (Ed)\n 2. Change force_zip64 to start as -1 as unset, then use 1 for forcing use\n    of Zip64 and 0 for disabling use of Zip64.  Add negation of -fz to\n    prevent use of Zip64 during streaming from stdin to a non-seekable\n    output where data descriptors will be used, which allows creating\n    archives with the old stream format but will fail if a large file is\n    streamed.  Default is still to force Zip64 data descriptors when\n    streaming, which covers all cases but requires a Zip64 compatible\n    unzip.  zip.c, globals.c, zipfile.c (Ed)\n 3. Handle case of bad Unicode in archive.  zipfile.c (Ed)\n------------------------ May 22nd 2008 version 3.0h12 ----------------------\n 1. Fix bug introduced last beta that prevented streaming large files.  Use\n    separate error message depending on if -fz- was used.  zipfile.c (Ed)\n 2. Change non existent to nonexistent.  unix/configure (SMS)\n 3. Don't output blank line when zipmessage_nl() gets passed an empty\n    string.  This removes blank lines for skipped entries when -FS used.\n    zip.c (Ed)\n------------------------ May 27th 2008 version 3.0h13 ----------------------\n 1. Change UNICODE_ALLOW_FORCE to UNICODE_SUPPORT, -UN=force to -UN=UTF8,\n    and unicode_force to utf8_force.  This option now standard with Unicode\n    support and forces Zip to save UTF-8 paths and comments, when not ASCII,\n    as if UTF-8 were the native character set.  globals.c, zip.c, zip.h (Ed)\n 2. Add note to Todo that it's out of date.  TODO (Ed)\n 3. Update WhatsNew.  WHATSNEW (Ed)\n 4. Update Unicode help in extended help.  zip.c (Ed)\n 5. Update announcements.  zip30h.ann, zip30.ann (Ed)\n 6. Fix bug with -UN=UTF8.  zip.c, zipfile.c (Ed)\n 7. Update Zip manual.  man/zip.1, zip.txt (Ed)\n 8. Attempt an update to zip limits document.  proginfo/ziplimit.txt (Ed)\n 9. Update README regarding forum postings.  README (Ed)\n10. Remove duplicate initialization lines for found and fnxt.  zip.c (SMS)\n------------------------ May 28th 2008 version 3.0h14 ----------------------\n 1. Remove >= 0 check from wide character check as value is unsigned.\n    fileio.c (SMS)\n 2. In putlocal(), move nam and use_uname to UNICODE_SUPPORT block.  If\n    no UNICODE_SUPPORT use z->nam instead of nam.  zipfile.c (SMS, Ed)\n 3. Update announcement date for beta.  zip30h.ann (Ed)\n------------------------ May 31st 2008 version 3.0h ------------------------\n 1. In putlocal() if using UTF-8 bit then also set UTF-8 bit in z->lflg so\n    is set in local header for streaming.  zipfile.c (Ed)\n 2. Update announcement date for beta.  zip30h.ann (Ed)\n 3. Rename lib and dll projects to zip32z64 and update project files so\n    project name is same as lib and dll libraries.  Export make files.\n    windll/visualc/dll/zip32z64.dsp, windll/visualc/dll/zip32z64.dsw,\n    windll/visualc/dll/zip32z64.mak, windll/visualc/libzip32z64.dsp,\n    windll/visualc/libzip32z64.dsw, windll/visualc/libzip32z64.mak (Ed)\n------------------------ June 7th 2008 version 3.0i01 ----------------------\n 1. Update Mac ReadMe to note Mac OS X uses Unix port.  macos/readme.1st (Ed)\n 2. Change UNIX to Unix in manual.  Update dates in manual and add note\n    about Mac OS X. Change switch to switches.  zip.1 (SMS, Ed)\n 3. Add version information under Windows by adding a version resource.\n    win32/vc6/zip.dsp, win32/vc6bz2/zip.dsp, win32/zip.rc (Ed)\n------------------------ June 15th 2008 version 3.0i02 ----------------------\n 1. Update Install instructions.  INSTALL (Ed)\n 2. Update ReadMe.  README (Ed)\n 3. Update ToDo list.  TODO (Ed)\n 4. Update WhatsNew.  WHATSNEW (Ed)\n 5. Add note to WHERE.  WHERE (Ed)\n 6. Update announcement.  zip30.ann (Ed)\n 7. Review man pages and update Zip man page.  Compile text files from man\n    pages.  man/zip.1, zip.txt, zipnote.txt, zipsplit.txt, zipcloak.txt (Ed)\n 8. Update extended help.  zip.c (Ed)\n------------------------ June 17th 2008 version 3.0i03 ----------------------\n 1. Fix bug where UTF-8 flag was not being set when using_utf8 was set as\n    result of UTF-8 being current character set.  zipfile.c (Ed)\n 2. Update man page globbing description.  man/zip.1, zip.txt (SMS, Ed)\n 3. Update web address to bzip2 package for VMS.  vms/install_vms.txt (SMS)\n------------------------ June 21st 2008 version 3.0i04 ----------------------\n 1. Update comments.  zbz2err.c (Christian)\n 2. Put use_uname in UNICODE_SUPPORT block.  zipfile.c (Christian)\n 3. Increase st to 0x1400.  msdos/makefile.msc (Christian)\n 4. Update copyright and put @CodeSize and @DataSize into ifndef blocks for\n    Huge, Large, Compact, Medium, and Small.  msdos/match.asm (Christian)\n 5. Add check to disable symbolic links.  msdos/osdep.h (Christian)\n 6. Put Mac OS X compiler check into if Mac OS X block to avoid problems on\n    some other Unix ports with the check.  unix/configure (SMS)\n 7. Move set_extra_field() to fix compile problem.  unix/unix.c (SMS)\n 8. Update USEBZIP2 to USEBZ2 and -DUSE_BZIP2 to -DBZIP2_SUPPORT.  Drop\n    -DMSDOS compile flag.  win32/makefile.w32 (Christian)\n 9. Change BZIP2_SUPPORT to USEBZ2.  win32/makenoas.w32 (Christian)\n------------------------ June 23rd 2008 version 3.0i05 ----------------------\n 1. Update and unify resources.  Remove any MFC dependencies from the resource\n    files zip.rc and windll.rc.  win32/zip.rc and windll/windll.rc now read\n    the version info from revision.h.  windll.rc internal flags modified to\n    \"32-bit dll\".  zip.rc internal flags liberated from \"winnt 32-bit\"\n    to \"generic 32-bit windows\".  Win32 zip.exe also supported on Win9x\n    (32-bit).  Update makefiles for Borland, MSC, GCC(mingw32), Watcom\n    to support inclusion of zip.rc version resources into zip.exe binary.\n    revision.h, msdos/osdep.h, win32/makefile.bor, win32/makefile.gcc,\n    win32/makefile.w10, win32/makefile.w32, win32/makefile.wat,\n    win32/makenoas.w32, win32/zip.rc, windll/windll.rc (Christian)\n 2. Remove unused files.  win32/resource.h, windll/resource.h,\n    windll/windll.aps, windll/zipver.h, windll/visualc/dll/zip32z64.mak,\n    windll/visualc/lib/zip32z64.mak (Christian)\n 3. Update VMS.  vms/descrip_deps.mms (SMS)\n------------------------ June 26th 2008 version 3.0i06 ----------------------\n 1. Update Install and Readme in preparation for release.  Update WhatsNew.\n    INSTALL, README, WHATSNEW (Ed)\n 2. Update announcement.  zip30.ann (Ed)\n 3. Update original Visual Basic project comments and documentation.\n    windll/vb/readmevb.txt, windll/vb/vbzip.vbp, windll/vb/vbzip.vbw,\n    windll/vb/vbzipbas.bas, windll/vb/vbzipfrm.frm (Ed)\n 4. Add bzip2 version of djgpp 2.x makefile thanks to Robert.  Assumes a\n    standard djgpp installation.  msdos/makebz2.dj2 (Robert Riebisch, Ed)\n------------------------ June 27th 2008 version 3.0i07 ----------------------\n 1. Add DJGPP to bzip2 install instructions.  bzip2/install.txt,\n    msdos/makebz2.dj2 (Robert, Ed)\n------------------------- July 5th 2008 version 3.0 -------------------------\n 1. Add -sd to extended help.  zip.c (Will, Ed)\n 2. Fix memory bug when rebuilding Zip64 central directory extra field which\n    can crash MinGW and other ports when processing large files.  zipfile.c\n    (Will)\n 3. Fix -v bug preventing display of version information when options in\n    environment variables.  zip.c (Ed)\n 4. Update WhatsNew.  WHATSNEW (Ed)\n 5. Update announcement.  zip30.ann (Ed)\n"
  },
  {
    "path": "deps/infozip/zip30/INSTALL",
    "content": "HOW TO INSTALL ZIP\n\n     Zip is distributed as C source code that can be compiled on a\n     wide range of systems:  Unix, VMS, MSDOS, OS/2, NT, Amiga, Atari,\n     BeOS, VM/CMS, ...  You will need Unzip 5.0p1 or later (under any\n     system) or PKUNZIP 2.04g or later (under MSDOS) to unpack the\n     distribution file, in this case zip30.zip.  But since you read this,\n     you have unpacked it already, or you cheated and got a tar.Z file...\n\n     Note:  Zip 3.0 distribution kits (unlike previously distributed\n     Zip 2.x kits) are created with a top-level directory (\"zip30\") in\n     the archive, making the creating of the zipsrc directory optional.\n\nInstallation on Unix (see below for installation on other systems)\n\n     Let's assume that you start from scratch and have not yet unpacked\n     the sources.  First step, then, is to unpack Zip.  The following\n     assumes that you have zip30.zip in the current directory.\n\n     For example, to extract to a new zipsrc directory (assuming\n     zip30.zip is in the current directory):\n\n          mkdir zipsrc\n          cd zipsrc\n          cp ../zip30.zip .\n          unzip zip30.zip\n          cd zip30\n\n     To extract in an existing directory, such as /usr/local/src/zip:\n\n          cd /usr/local/src/zip\n          (copy zip30.zip here)\n          unzip zip30.zip\n          cd zip30\n\n     The first extracts all source files and documentation to the\n     directory \"zipsrc/zip30\".  The second places the zip30 directory\n     in the \"/usr/local/src/zip\" directory.  Both then cd in to the\n     zip30 directory where Zip will be built.\n\n     Note:  This release now includes the standard encryption code\n     previously in the separate package zcrypt29.zip, but you still\n     can decide whether to activate the crypt code or not.  Crypt is\n     enabled by default, but you may disable it by specifying the\n     option -DNO_CRYPT in the LOCAL_ZIP environment variable (or by\n     adding this option to the compilation options in the appropiate\n     makefile).  See README.CR for more on crypt.\n\n     You then do:\n\n          make -f unix/Makefile system\n\n     where \"system\" is one of:  generic, generic_gcc,\n     att6300, coherent, cray_v3, minix, sco_x286, xenix, zilog.\n\n     For Unix systems where \"cc\" is the preferred C compiler command,\n     try\n\n          make -f unix/Makefile generic\n\n     first.  If \"gcc\" is preferred, specify \"generic_gcc\" instead of\n     \"generic\".  This should work on most systems and automatically\n     selects compilation options based on a set of tests (in\n     unix/configure), including detection of large file support\n     sufficient to enable Zip64 large archive features.  If \"generic\"\n     (or \"generic_gcc\" if that is used) fail, then one of the special\n     targets given above may work.\n\n     Among other special systems are Cray Unicos, Zilog Zeus and MINIX.\n\n     The optimization settings for many systems should be close, but\n     if you see optimization for your system is not ideal, send in\n     the changes so we can improve it.\n\n     By default, Zip uses the \"deflate\" compression method.  To add\n     the additional optional \"bzip2\" compression method, see the file\n     bzip2/install.txt.  Note that bzip2 support is provided by\n     compiling or linking in the bzip2 library.  See the bzip2 site\n     (http://www.bzip.org/) for more on bzip2.\n\n     If you get error messages such as \"constant expected\" in\n     deflate.c, add -DDYN_ALLOC to CFLAGS in your makefile entry.\n\n     If you have lots of memory, try compiling with -DBIG_MEM. If your\n     system supports mmap(), try compiling with -DMMAP. This generally\n     gives faster compression but uses more memory. See the unix/Makefile\n     entry mmap_gcc for an example.\n\n     If none of these compiles, links, and functions properly on\n     your Unix system, then your system apparently has specific\n     requirements we did not account for.  See the file README for how\n     to get help.\n\n     If the appropriate system was selected, then the executables zip,\n     zipnote, zipcloak, and zipsplit will be created.  You can copy\n     them to an appropriate directory in the search path using:\n\n          make -f unix/Makefile install\n\n     The defaults are /usr/local/bin for the executables and\n     /usr/local/man/man1 for the manual pages. Change the macros\n     BINDIR and MANDIR in makefile to change these if needed.\n\n     If necessary, add the directory with the Zip executables to your\n     shell's PATH (or \"path\") variable.  (C-shell users may need to\n     use the \"rehash\" command so csh can find the new command in the\n     path.)  You should now be ready to use Zip.\n\n     You can get rid of the now unnecessary source and object files\n     with:\n\n          cd ..\n          rm -r zip30\n\n     This will remove the directory zip30 and its contents created\n     by unzip.  You should keep the zip30.zip file around though,\n     in case you need to build it again or want to give it to a\n     colleague.\n\n     You can add the following lines to the file /etc/magic for\n     usage by the 'file' command:\n\n0       string          PK              Zip archive\n>4      byte            011             (at least v0.9 to extract)\n>4      byte            012             (at least v1.0 to extract)\n>4      byte            013             (at least v1.1 to extract)\n>4      byte            024             (at least v2.0 to extract)\n>4      byte            025             (at least v2.1 to extract)\n\n\nInstallation on other systems\n\n     The steps for installation under VMS, MSDOS, OS/2, NT, Amiga and\n     Atari are similar to the above:  first unzip the distribution\n     files into their own directory.  The system-dependent files are\n     stored in special subdirectories.\n\n     For all the non-Unix ports which support the creation of \"UT\" extra\n     fields (these ports contain USE_EF_UT_TIME in the list of optional\n     features displayed with \"zip -v\"), the timezone environment variable TZ\n     should be set according to the local timezone in order for the -f, -u,\n     -o, and similar options to work correctly.  This is not needed for the\n     WIN32 and WinDLL ports, since they get the timezone information from\n     the OS by other means.\n\n\n  MSDOS:\n\n     Do one of:\n\n          make msdos\\makefile.msc               (Microsoft C 5.1)\n          nmake -f msdos\\makefile.msc           (Microsoft C 6.0 and newer)\n          make -fmsdos\\makefile.bor -DCC_REV=1  (Borland Turbo C++ 1.0)\n          make -fmsdos\\makefile.bor             (Borland C++ 2.0 and newer)\n          make -fmsdos\\makefile.tc              (Borland Turbo C 2.0x)\n          make -f msdos/makefile.dj1            (DJGPP v1.12m4)\n          make -f msdos/makefile.dj2            (DJGPP v2.01 and newer)\n          make -f msdos/makefile.emx            (gcc/emx 0.9b and newer)\n          make -f os2/makefile.os2 gccdos       (gcc/emx 0.9b and newer)\n          wmake -f msdos\\makefile.wat           (Watcom C 11.x 16-bit)\n          wmake -f msdos\\makefile.wat PM=1      (Watcom C 11.x 32-bit, PMODE/W)\n\n     for Microsoft, Borland C++ and Turbo C, Watcom C/C++ and the various\n     free GNU C implementations, respectively.  More detailed instructions\n     can be found in the respective makefiles.\n\n\n  WIN32 (Windows NT/2K/XP/2K3 and Windows 95/98/ME):\n\n     Supported compilers are Microsoft Visual C++, Borland C++, Watcom C/C++,\n     and miscellaneous free GNU C implementations (gcc/mingw, CygWin, ...).\n     The makefiles supplied in the win32/ subdirectory contain further\n     information.\n\n\n  Windows DLL (WIN32):\n\n     Supported environments are Visual C++ (32-bit only, 5.x and newer).\n     For instructions how to build the DLLs and where find the makefiles,\n     look into windll/contents.\n\n\n  OS/2:\n\n     Type\n\n          {make} -f os2/makefile.os2\n\n     to get a list of supported targets/compiling environments.\n     (replace \"{make}\" with the name of your OS/2 make utility.)\n\n     To initiate the actual compiling process, you have to specify\n     a system target:\n\n          {make} -f os2/makefile.os2 {system}\n\n     An example: type\n\n          nmake -f os2/makefile.os2 msc\n\n     for Microsoft C 6.00.\n\n\n  VMS (OpenVMS):\n\n     The most complete information on building and installing Zip on VMS\n     is in [.vms]install_vms.txt.  Optimists in a hurry may wish to try\n     commands like these:\n\n           @ [.VMS]BUILD_ZIP.COM\n     or:\n           MMS /DESCRIP = [.VMS]DESCRIP.MMS CLEAN        ! Or MMK ...\n           MMS /DESCRIP = [.VMS]DESCRIP.MMS              ! Or MMK ...\n\n     When the executables have been created (or located if already installed),\n     most users define foreign command symbols for the Zip executables, like\n     this:\n\n          ZIP :== $ dev:[dir]ZIP.EXE            ! UNIX-like command line.\n     or:\n          ZIP :== $ dev:[dir]ZIP_CLI.EXE        ! VMS-like command line.\n\n     Such symbol definitions are often added to a user's\n     SYS$LOGIN:LOGIN.COM procedure, or to a common, site-specific\n     procedure, like SYS$MANAGER:SYLOGIN.COM.\n\n     Additional installation options are described in install_vms.txt.\n\n     The builders create help text files, ZIP.HLP and ZIP_CLI.HLP.  Also\n     see install_vms.txt for how to create the help libraries.\n\n\nMac OS:\n\n     Mac OS X is part of the Unix port, so use the Unix installation above.\n\n     Mac OS before Mac OS X use the Mac OS port, though little testing has\n     been done for that port recently.  See macos/README.TXT for more on\n     this port.\n\n\nCompiler Flags\n\n  Zip should compile fine out of the box for your port.  In particular,\n  for Unix the command\n    make -f unix/Makefile generic\n  should automatically detect the features available on your system and\n  set the flags appropriately.  In some cases, however, you may need to\n  set one or more compiler flags yourself to get Zip to compile or to\n  add features you want or remove features that cause trouble for your\n  port.  Below are the more common compiler macros you can set.\n\n  LARGE_FILE_SUPPORT\n    Tell Zip that the OS supports large files (generally files larger\n    than 4 GB).  Zip will try to compile in the large file calls\n    (typically 64-bit) for the OS instead of using the standard\n    (typically 32-bit) file calls.  On Unix Zip tries to switch over to\n    the 64-bit file environment.  If setting this flag causes errors\n    or Zip still can't handle large files on that port, then probably\n    either Zip doesn't have the code to support large files on your OS\n    (write a patch and send it in to us) or your OS doesn't support large\n    files.\n\n    Note that the flag ZIP64_SUPPORT must also be set to create archives\n    with large files.\n\n    This flag should be set automatically on Unix, Win32, and some\n    other ports.  Setting NO_LARGE_FILE_SUPPORT turns this flag off.\n\n  ZIP64_SUPPORT\n    Enable the Zip64 code in Zip that supports the Zip64 extensions noted\n    in the PKWare AppNote.  These extensions allow storing files larger\n    than 4 GB in archives and the creating of archives larger than 4 GB.\n    They also allow storing more than 64K files in an archive.  Currently\n    Zip does not handle archives of PKZip version 4.5 or later unless\n    this flag is set.\n\n    To enable large file support in Zip, you generally need to set both\n    LARGE_FILE_SUPPORT (to read and write large files) and ZIP64_SUPPORT\n    (to store them in and read them from archives).  Files larger than\n    4 GB may be invisible to Zip (directory scans don't see them) if\n    LARGE_FILE_SUPPORT is not enabled.\n\n    Keeping LARGE_FILE_SUPPORT and ZIP64_SUPPORT separate allows easier\n    debugging of these features.  When testing large file support on an\n    OS, first set just LARGE_FILE_SUPPORT to test the file calls (all\n    should compile and work as before with small files), then turn on\n    ZIP64_SUPPORT to let Zip recognize and handle large files.\n\n    This flag should be set automatically on most ports if\n    LARGE_FILE_SUPPORT is set.  Setting NO_ZIP64_SUPPORT turns this flag\n    off.\n\n  UNICODE_SUPPORT\n    Enable storing and using UTF-8 paths.  These paths are stored in\n    a backward-compatible way so that archives with UTF-8 paths still\n    work on zips and unzips that don't support Unicode.  This support\n    follows the recent additions to the PKWare AppNote for Unicode\n    support, except that Unicode comments on systems where UTF-8 is\n    not the current character set is not implemented in this release.\n\n    On some ports UNICODE_SUPPORT is set automatically if wide characters\n    are supported.  Setting NO_UNICODE_SUPPORT turns off this flag.\n\n  USE_EF_UT_TIME\n    Enables storing UT time in an extra field.  This becomes useful\n    for ports that normally store file times as local time, resulting\n    in problems when files are moved across time zones and when\n    there are daylight savings time changes.  Zip and UnZip will\n    automatically correct for time zone changes when UT time is stored.\n\n    This is usually set by default.  Use NO_EF_UT_TIME to turn this off.\n\n  NTSD_EAS (Win32 only)\n    Enable storing Windows NT file security descriptors.  This allows\n    restoring the descriptors (file ACL's, etc.).\n\n    This is on by default for Win32.  Use NO_NTSD_EAS to turn this off.\n\n  BZIP2_SUPPORT\n    Enable compressing zip entries using the bzip2 library.  You must get\n    the bzip2 library from somewhere else as we only provide a way to\n    compile or link the library in and compress files using bzip2.  Enables\n    a new compression method, bzip2, that can be used instead of the default\n    Zip compression method deflate.\n\n    This flag is set on Unix, including Mac OS X, when compiling using\n    generic if the bzip2 library is found.  Set on Win32 if the bzip2\n    projects are used.  See the VMS documentation for when VMS sets this\n    flag.  Setting NO_BZIP2_SUPPORT turns this off.\n\n    See bzip2/install.txt for more on installing bzip2 support.\n\n  WIN32_OEM (Win32 only)\n    Enable saving paths on Win32 in the OEM character set.  Zip has stored\n    paths using the standard ANSI local character set, but other zips have\n    used the OEM character set on MSDOS and Win32.  This flag should make\n    Zip more compatible with other DOS and Win32 zips and unzips.  It also\n    enables the translation of OEM paths in DOS archives to ANSI and should\n    eliminate some problems with funny characters showing up in path names.\n\n    If Unicode is enabled and used, Unicode paths generally override\n    local paths using OEM character sets.\n\n    This flag is on by default on most Win32 ports.  Some ports apparently\n    have problems with OEM conversions.  If your port or compiler does\n    funny things with file names, you may want to turn this off.  Defining\n    NO_WIN32_OEM turns this flag off.\n\n  NO_STREAMING_STORE\n    Because storing zip archives inside a zip entry adds \"false\" signatures\n    and this causes problems when using data descriptors if the archive\n    needs fixing, this option is provided to force deflating when streaming.\n    This version of Zip includes an advanced algorithm for correctly finding\n    these signatures, but if an archive is \"broke\", there is no telling\n    what's where.  This is only a problem if an archive becomes broke for\n    some reason, but to be safe define this.\n\n  ALLOW_REGEX\n    For MSDOS and Windows, now \"[list]\" wildcard matching (where any\n    character between [ and ] can be used to match the character at that\n    position) is turned off unless the new -RE option is used.  Defining\n    this flag forces \"[list]\" matching to be always on as in previous\n    releases.\n\n\nFor command help on any of the zip* utilities, simply enter\nthe name with no arguments.\n"
  },
  {
    "path": "deps/infozip/zip30/LICENSE",
    "content": "This is version 2007-Mar-4 of the Info-ZIP license.\nThe definitive version of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and\na copy at http://www.info-zip.org/pub/infozip/license.html.\n\n\nCopyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n\n   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n   Rich Wales, Mike White.\n\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held liable\nfor any direct, indirect, incidental, special or consequential damages\narising out of the use of or inability to use this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  The sole exception to this condition\n       is redistribution of a standard UnZipSFX binary (including SFXWiz) as\n       part of a self-extracting archive; that is permitted without inclusion\n       of this license, as long as the normal SFX banner has not been removed\n       from the binary or disabled.\n\n    3. Altered versions--including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP--must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases--including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n\n    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"\n       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its\n       own source and binary releases.\n"
  },
  {
    "path": "deps/infozip/zip30/README",
    "content": "Zip 3.0 is the first Zip update adding large file support.  For now Zip 2.3x\nremains available and supported, but users should switch to this new release.\n\nTesting for Zip 3.0 has focused mainly on Unix, VMS, Max OS X, and Win32,\nand some other ports may not be fully supported yet.  If you find your\nfavorite port is broke, send us the details or, better, send bug fixes.  It's\npossible that support for some older ports may be dropped in the future.\n\n\n\nCopyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\nSee the accompanying file LICENSE (the contents of which are also included\nin unzip.h, zip.h and wiz.h) for terms of use.  If, for some reason, all\nof these files are missing, the Info-ZIP license also may be found at:\nftp://ftp.info-zip.org/pub/infozip/license.html and\nhttp://www.info-zip.org/pub/infozip/license.html.\n\n\nZip 3.0 is a compression and file packaging utility.  It is compatible with\nPKZIP 2.04g (Phil Katz ZIP) for MSDOS systems.  There is a companion to zip\ncalled unzip (of course) which you should be able to find in the same place\nyou got zip.  See the file 'WHERE' for details on ftp sites and mail\nservers.\n\nSo far zip has been ported to a wide array of Unix and other mainframes,\nminis, and micros including VMS, OS/2, Minix, MSDOS, Windows, Atari, Amiga,\nBeOS and VM/CMS.  Although highly compatible with PKware's PKZIP and PKUNZIP\nutilities of MSDOS fame, our primary objective has been one of portability\nand other-than-MSDOS functionality.  Features not found in the PKWare version\ninclude creation of zip files in a pipe or on a device; VMS, BeOS and OS/2\nextended file attributes; conversion from Unix to MSDOS text file format; and,\nof course, the ability to run on most of your favorite operating systems.  And\nit's free.\n\nSee the file zip30.ann for a summary of new features in Zip 3.0 and WhatsNew\nfor the detailed list of new features and changes since Zip 2.32.  The file\nCHANGES details all day-to-day changes during development.\n\nNotes:\n\nMulti-volume support.  This version does not support multi-volume spanned\narchives as in pkzip 2.04g, and there is no intention at this point to support\nspanned archives, but Zip 3.0 supports split archives.  A split archive is an\narchive split into a set of files, each file a piece of the archive and each\nfile using an extension, such as .z02 as in the file name archive.z02, that\nprovides the order of the splits.  In contrast, a spanned archive is the\noriginal multi-floppy archive supported by pkzip 2.0g where the split order\nis contained in the volume labels.  The contents of split and spanned archives\nare mostly identical and there is a simple procedure to convert between the\nformats.  Many current unzips now support split archives.\n\nZip64 support.  This version supports Zip64 archives as described in the\nPKWare AppNote.  These archives use additional fields to support archives\ngreater than 2 GB and files in archives over the 2 GB previous limit (4 GB\non some ports).  The Zip64 format also allows more than 64k entries in an\narchive.  Support by the OS for files larger than 4 GB is needed for Zip to\ncreate and read large files and archives.  On Unix, Win32, and some other\nports, large file and Zip64 support is automatically checked for and\ncompiled in if available.  Use of Zip64 by Zip is automatic and to maximize\nbackward compatibility the Zip64 fields will only be used if needed.  A\nZip64 archive requires a pkzip 4.5 compatible unzip, such as UnZip 6.0.\n\nUnicode support.  This version has initial Unicode support.  This allows\npaths and names of files in other character sets to be accurately recreated\non OS that have sufficient character set support.  On Win32, if wide\ncharacter calls are supported (not Win 9x unless Unicode support has been\nadded) all files (including paths with illegal characters in the current\ncharacter set) should now be readable by zip.  Unicode support is provided\nusing a new set of UTF-8 path and comment extra fields and a new UTF-8 bit\nfor flagging when the current character set is already UTF-8.  Zip 3.0\nmaintains backward compatibility with older archives and is mostly compliant\nwith the new Unicode additions in the latest PKWare AppNote.  The exception\nis UTF-8 comments, which are not supported if UTF-8 is not the native\ncharacter set, but should be fully implemented in Zip 3.1.\n\n16-bit OS support.  Though Zip 3.0 is designed to support the latest zip\nstandards and modern OS, some effort has been made to maintain support\nfor older and smaller systems.  If you find Zip 3.0 does not fit on or\notherwise does not work well on a particular OS, send in the details and\nwe might be able to help.\n\nCompression methods.  In addition to the standard store and deflate methods,\nZip now can use the bzip2 compression format using the bzip2 library.  Though\nbzip2 compression generally takes longer, in many cases using bzip2 results\nin much better compression.  However, many unzips may not yet support\nbzip2 compressed entries in archives, so test your unzip first before using\nbzip2 compression.\n\nInstallation.  Please read the file INSTALL for information on how to compile\nand install zip, zipsplit, zipcloak, and zipnote and please read the manual\npages ZIP.txt, ZIPSPLIT.txt, ZIPCLOAK.txt, and ZIPNOTE.txt for information on\nhow to use them.  Also, if you are using MSDOS or Windows, note that text\nfiles in the distribution are generally in Unix line end format (LF only)\nand Windows and DOS users will need to either convert the files as needed to\nDOS line ends (CR LF) or extract the distribution contents using unzip -a.\n\nUtilities.  At this point zipsplit, zipcloak, and zipnote should work with\nlarge files, but they currently do not handle split archives.  A work around\nis to use zip to convert a split archive to a single file archive and then use\nthe utilities on that archive.\n\nEncryption.  This version supports standard zip encryption.  Until recently\nthe encryption code was distributed separately because of the US export\nregulations but now is part of the main distribution.  See crypt.c for\ndetails.  Decryption can be made with unzip 5.0p1 or later, or with zipcloak.\n\nBug reports.  All bug reports or patches should go to zip-bugs via the web\nsite contact form at http://www.info-zip.org/zip-bug.html (we have discontinued\nthe old email address zip-bugs@lists.wku.edu because of too much spam lately)\nand suggestions for new features can be submitted there also (although we don't\npromise to use all of them).  We also are on SourceForge at\nhttp://sourceforge.net/projects/infozip/ and now automatically get Bug Reports\nand Feature Requests submitted there.  In addition, a new Info-ZIP discussion\nforum is available as well.  See below.  Though bug reports can be posted there,\nwe don't have automatic monitoring of all postings set up yet so you may want\nto use the web form or SoureForge for a quicker response.  A good approach may\nbe to post the details on the forum so others can benefit from the posting,\nthen use the web reply form to let us know you did that if you don't get a\nreply in a reasonable time.\n\nPorts.  If you're considering a port, please check in with zip-bugs FIRST,\nsince the code is constantly being updated behind the scenes.  We'll\narrange to give you access to the latest source.\n\nDiscussion group.  If you'd like to keep up to date with our Zip (and companion\nUnZip utility) development, join the ranks of BETA testers, add your own\nthoughts and contributions, etc., check out the new discussion forum.  This is\nthe latest offering, after the various Info-ZIP mailing-lists on\nmxserver@lists.wku.edu (courtesy of Hunter Goatley) were no longer available\nand the temporary QuickTopic discussion group for Info-ZIP issues at\nhttp://www.quicktopic.com/27/H/V6ZQZ54uKNL died a horrible death due to large\namounts of spam.  The new discussion forum is now available at\nhttp://www.info-zip.org/board/board.pl (thanks again to Hunter Goatley) and\ncan be used to discuss issues, request features, and is one place new betas\nand releases are announced.  It also is a place to post bug reports, and\npatches can be submitted as attachments.  However, we don't yet get\nautomatic notification of all postings there so try one of the other methods\nif you don't get a response.  You can also post Bug Reports and Feature\nRequests at Source Forge.  However, the web site contact form remains\navailable if you would rather not post on the public forums.\n\nFrequently asked questions on zip and unzip:\n\nQ. When unzipping I get an error message about \"compression method 8\".\n\nA. This is standard deflate, which has been around for awhile.  Please\n   get a current version of unzip.  See the file 'WHERE' for details.\n\n\nQ. How about \"compression method 12\"?\n\nA. Compression method 12 is bzip2 and requires a relatively modern unzip.\n   Please get the latest version of unzip.\n\n\nQ. I can't extract this zip file that I just downloaded.  I get\n   \"zipfile is part of multi-disk archive\" or some other message.\n\nA. Please make sure that you made the transfer in binary mode.  Check\n   in particular that your copy has exactly the same size as the original.\n   Note that the above message also may actually mean you have only part\n   of a multi-part archive.  Also note that UnZip 5.x does not and UnZip 6.0\n   probably won't have multi-disk (split) archive support.  A work around\n   is to use Zip 3.0 to convert the split archive to a single-file archive\n   then use UnZip on that archive.  As a last result, if there's something\n   readable in what you have, zip -FF should be able to recover it.\n\n\nQ. When running unzip, I get a message about \"End-of-central-directory\n   signature not found\".\n\nA. This usually means that your zip archive is damaged, or that you\n   have an uncompressed file with the same name in the same directory.\n   In the first case, it makes more sense to contact the person you\n   obtained the zip file from rather than the Info-ZIP software\n   developers, and to make sure that your copy is strictly identical to\n   the original.  In the second case, use \"unzip zipfile.zip\" instead\n   of \"unzip zipfile\", to let unzip know which file is the zip archive\n   you want to extract.\n\n\nQ. Why doesn't zip do <something> just like PKZIP does?\n\nA. Zip is not a PKZIP clone and is not intended to be one.  In some\n   cases we feel PKZIP does not do the right thing (e.g., not\n   including pathnames by default); in some cases the operating system\n   itself is responsible (e.g., under Unix it is the shell which\n   expands wildcards, not zip).  Info-ZIP's and PKWARE's zipfiles\n   are interchangeable, not the programs.\n\n   For example, if you are used to the following PKZIP command:\n               pkzip -rP foo *.c\n   you must use instead on Unix:\n               zip -R foo \"*.c\"\n   (the quotes are needed to let the shell know that it should\n    not expand the *.c argument but instead pass it on to the program,\n    but are not needed on ports that do not expand file paths like\n    MSDOS)\n\n\nQ. Can I distribute zip and unzip sources and/or executables?\n\nA. You may redistribute the latest official distributions without any\n   modification, without even asking us for permission. You can charge\n   for the cost of the media (CDROM, diskettes, etc...) and a small copying\n   fee.  If you want to distribute modified versions please contact us at\n   www.Info-ZIP.org first. You must not distribute beta versions.\n   The latest official distributions are always on ftp.Info-ZIP.org in\n   directory /pub/infozip and subdirectories and at SourceForge.\n\n\nQ. Can I use the executables of zip and unzip to distribute my software?\n\nA. Yes, so long as it is made clear in the product documentation that\n   zip or unzip are not being sold, that the source code is freely\n   available, and that there are no extra or hidden charges resulting\n   from its use by or inclusion with the commercial product.  See the\n   Info-ZIP license for more.  Here is an example of a suitable notice:\n\n     NOTE:  <Product> is packaged on this CD using Info-ZIP's compression\n     utility.  The installation program uses UnZip to read zip files from\n     the CD.  Info-ZIP's software (Zip, UnZip and related utilities) is\n     freely distributed under the Info-ZIP license and can be obtained as\n     source code or executables from various anonymous-ftp sites,\n     including ftp://ftp.info-zip.org/pub/infozip.\n\n\nQ. Can I use the source code of zip and unzip in my commercial application?\n\nA. Yes, as long as the conditions in the Info-ZIP license are met.  We\n   recommend you include in your product documentation an acknowledgment\n   and note that the original compression sources are available at\n   www.Info-ZIP.org. If you have special requirements contact us.\n"
  },
  {
    "path": "deps/infozip/zip30/README.CR",
    "content": "_____________________________________________________________________________\n\n  This is Info-ZIP's README.CR for zcrypt29.zip, last updated 27 March 2008.\n_____________________________________________________________________________\n\n\nThe files described below contain the encryption/decryption code for Zip 2.31,\nUnZip 5.52, and WiZ 5.02 (and later).  These files are included in the main\nsource distributions for all of these now, but the encryption patch is still\navailable for earlier versions of these.  This file both describes the history\nof the encryption package and notes the current conditions for use.  Check\nthe comments at the top of crypt.c and crypt.h for additional information.\n\nAs of version 2.9, this encryption source code is copyrighted by Info-ZIP;\nsee the enclosed LICENSE file for details.  Older versions remain in the pub-\nlic domain.  Zcrypt was originally written in Europe and, as of April 2000,\ncan be freely distributed from the US as well as other countries.\n\n(The ability to export from the US is new and is due to a change in the Bureau\nof Export Administration's regulations, as published in Volume 65, Number\n10, of the Federal Register [14 January 2000].  Info-ZIP filed the required\nnotification via e-mail on 9 April 2000; see the USexport.msg file in this\narchive.  However, as of June 2002, it can now be freely distributed in both\nsource and object forms from any country, including the USA under License\nException TSU of the U.S. Export Administration Regulations (section 740.13(e))\nof 6 June 2002.)\n\n    LIKE ANYTHING ELSE THAT IS FREE, ZIP, UNZIP AND THEIR ASSOCIATED\n    UTILITIES ARE PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND,\n    EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE AUTHORS BE LIABLE\n    FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.\n\nThe encryption code is a direct transcription of the algorithm from\nRoger Schlafly, described by Phil Katz in the file appnote.txt.  This\nfile is distributed with the PKZIP program (even in the version without\nencryption capabilities).  Note that the encryption will probably resist\nattacks by amateurs if the password is well chosen and long enough (at \nleast 8 characters) but it will probably not resist attacks by experts.\nPaul Kocher has made available information concerning a known-plaintext\nattack for the PKWARE encryption scheme; see http://www.cryptography.com/\nfor details.)  Short passwords consisting of lowercase letters only can be\nrecovered in a few hours on any workstation.  But for casual cryptography\ndesigned to keep your mother from reading your mail, it's OK.\n\nFor more serious encryption, check into PGP (Pretty Good Privacy), a\npublic-key-based encryption system available from various Internet sites.\nPGP has Zip and UnZip built into it.  The most recent version at the time\nthis was originally written was 6.5, although older versions were still\nwidespread.  At the time of this writing there are now GPG, PGP Universal\n2.0, and various others based on OpenPGP.\n\nWe are looking at adding AES strong encryption to future versions of Zip and\nUnZip.\n\nZip 2.3x and UnZip 5.5x and later are compatible with PKZIP 2.04g.  (Thanks\nto Phil Katz for accepting our suggested minor changes to the zipfile format.)\n\nIMPORTANT NOTE:\n\n  Zip archives produced by Zip 2.0 or later must not be *updated* by\n  Zip 1.1 or PKZIP 1.10 or PKZIP 1.93a, if they contain encrypted members\n  or if they have been produced in a pipe or on a non-seekable device.\n  The old versions of Zip or PKZIP would destroy the zip structure.  The\n  old versions can list the contents of the zipfile but cannot extract\n  it anyway (because of the new compression algorithm).  If you do not\n  use encryption and compress regular disk files, you need not worry about\n  this problem.\n\n\nContents that were distributed and now are part of the main source files:\n\n  file           what it is\n  ----           ----------\n  README.CR      this file\n  LICENSE        Info-ZIP license (terms of reuse and redistribution)\n  USexport.msg   export notice sent to US Bureau of Export Administration\n  WHERE          where Zip/UnZip/WiZ and related utilities can be found\n  crypt.c        code for encryption and decryption\n  crypt.h        code for encryption and decryption\n  file_id.diz    description file for some BBSes\n\nMost all of the files are in Unix (LF only) format.  On MSDOS systems, you\ncan use the -a option of UnZip to convert the source files to CRLF\nformat.  This is only necessary if you wish to edit the files -- they\nwill compile as is with Microsoft C and Turbo/Borland C++ 1.0 or\nlater.  However, you will have to convert the files (using \"unzip -a\")\nto the CRLF format to compile with the older Turbo C 1.0 or 2.0.  You\nshould be able to find Zip and UnZip in the same place you found this \n(see ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html or the file\n\"WHERE\" for details).\n\nCurrent releases all have encryption built in.  To update previous versions\nusing the zcrypt sources:\n\n  (1) Get the main sources (e.g., Zip 2.3) and unpack into a working\n      directory, as usual.\n\n  (2) Overwrite the dummy crypt.c and crypt.h from the main sources with \n      the versions from this package.  If you want to overwrite directly\n      out of the zcrypt29 archive, do not use UnZip's freshen/updating\n      option; the dummy files may be newer than the real sources in\n      zcrypt29.  (\"unzip -o zcrypt29 -d /your/working/dir\" will do the\n      Right Thing in most cases, although it may overwrite a newer WHERE\n      file under some circumstances.)\n\n  (3) Read the main INSTALL document and compile normally!  No makefile\n      changes are necessary on account of the zcrypt sources.  You can\n      check that the version you just compiled has encryption or decryption\n      support enabled by typing \"zip -v\" or \"unzip -v\" and verifying that\n      the last \"special compilation option\" says encryption or decryption\n      is included.\n\nEncryption enables new \"-e\" and \"-P password\" options in Zip, and a new\n\"-P password\" option in UnZip--see the normal Zip and UnZip documentation\nfor details.  (Note that passing a plaintext password on the command line\nis potentially much more insecure than being prompted for it interactively,\nwhich is the default for UnZip and for Zip with \"-e\".  Also note that the\ninteractive method allows UnZip to deal with archives that use different\npasswords for different files.)\n"
  },
  {
    "path": "deps/infozip/zip30/TODO",
    "content": "Todo list (last updated 12 June 2008).\n\nFeatures for next official version:\n\n- Extended attributes for Windows, Linux, and Mac OS X.\n- Win32 ACL rewrite to use backup api to create new and more useful extra\n  field (need unzip support) (Kai).\n- Allow -d@ to read in a list of names to delete (11/17/2005).\n- AES encryption (3/19/05).\n\nFeatures that may make the next release:\n\n- Allow reading in list of files using @filename.\n- When -R, -x, or -i pattern ends in a directory add / to the end\n      (11/5/2004 Nehal).\n- Decide if -R, -i and -x should use external rather than internal patterns.\n      Also, change pattern matching to not do ex2in() and then in2ex() if\n      appropriate.  (12/26/2005 SMS)\n- Though Unicode paths have been implemented and tested, Unicode comments\n      are not yet supported (except for comments on UTF-8 native systems which\n      are supported).\n- Verbose mode -v may still need work.\n\n- Add C# example for Zip 3.0 (need to be converted to new DLLs) - original\n      C# example added with note.\n- Path Prefix maybe, so entries added to an archive can have a directory\n      path string prepended to each path so can zip multiple drives and avoid\n      name conflicts (4/17/2006).\n- UNC paths like \\\\server\\path (4/26/2005).\n- Support for other languages maybe.\n\n- Add About page option similar to -h2 and -v but lists Info-ZIP\n      information (could be -sa) (4/29/2006).\n- Update utilities ZipSplit, ZipNote, and ZipCloak to handle split archives.\n- Update ziperr and finish if needed.\n- Review memory allocation and fill in memory leaks if any.\n- Enhance -FF to fix common problems such as archives ftp in text mode\n      and fixing checksums so entries can be extracted if that makes\n      sense (6/17/2007).\n- Add \\ to / conversion in zipsplit to fix problem in\n      1/29/2004 email.\n- Encryption bug with small stored file (12/27/2005) (fixed?).\n\n- When updating large archives with few entries being\n      updated maybe display something in large periods of\n      quiet (1/23/2006).\n- Windows OEM comments (5/17/2006).\n- Example of using MVS zip and unzip (3/30/2004) (Need one).\n- UTF-8 comments need to be implemented (6/17/2007)\n- Maybe convert ../ in archive (5/20/2006).\n- Per so many buffers dll callback (12/23/2005 Ale).\n- Allow rename stdin \"-\" to something else (12/27/2005 gregor).\n- Check for possible buffer overrun weaknesses while reading zip files.\n- Do Active Template Library (ATL) (4/27/2005).\n- Flush Win16 support - to be determined (Mike).\n- Way to convert file names on input, converting foo.c to dir/foo_bar.c\n      for instance (4/8/2004, 3/12/2004).\n- French WiZ (not a Zip thing actually but dependent on zip and unzip).\n- Then there is that wierd ^D being converted to \\000 error reported\n      in 6/21/2003 email when Zip is outputted into a pipe on Windows ports.\n\nOld list:\n\nMain features still missing for next official version (last updated 2/11/2001):\n\n- what about the binary/text detection ? (seems done)\n- -b and -t options in help screen (covered in -h2)\n- findfirst/findnext and after that LSSTAT (performance!!)\n- use IS_EXEC from djgpp stat.h\n- use install in unix/Makefile instead of mkdir -p, look at install sh script.\n- #elif for those ports that can handle it.\n- what about zopen vs. fopen ?\n- Add zcreate or zfcreate for win32.\n- Assembler stuff in match.S (subexpressions)\n- zipping huge files (> 2G, unsigned 32bit) (done)\n- Testsuite for zip and unzip (John D. Mitchell)\n- make a version.c or version.h that includes all the compiler names\n- run utils with dmalloc().\n- what to do with zip -F and zip -FF (readzipfile2()) ? (done?)\n- profiling of the code\n- multi disk zip files (could be done)\n- zipfile modification tool (Greg)\n- Implement -- option (Thomas Klauser, wiz@danbala.tuwien.ac.at) (could be done)\n- don't add files with \"Archive bit\" or add files with \"Archive bit\"\n\t(uwe.becher@metronet.de) (could be done with -AS and -AC)\n- 32 bit file attributes\n- generate output without having to seek at all (this seems to be stream output)\n- remove contractions from zip error messages, make them clearer (Steve)\n- display \"[text]\" for ascii files when not quiet (no -q) (Timo Salmi)\n- does zipnote accept names with version number?\n- for a WORM, zip should create temp file only when updating; new archives\n\tshould be created directly.\n- APPNOTE.TXT specifies \"4) The entries in the central directory may\n      not necessarily be in the same order that files appear in the zipfile\"\n      but readzipfile() relies on same order. (new read does not, and now\n      the read for -FF searches for central directory matches rather than\n      rely on the order)\n- on Mac, MPW C 3.3.1 requires #if (a || b)  [\"#if a || b\" taken as \"#if a\"]\n- on Unix, let -S be \"include non-regular files without reading from them\"\n\t(as pkzip on Unix). This requires unzip support.\n- zip -l should do ebcdic->ascii translation on CMS and MVS\n- zip as subroutine (zdig/241) (some work done on this)\n- accept k and M in zipsplit\n- store / (part of file name) as ! in OS/2 (problem only with -E ?)\n- in addition to -l (LF to CR LF) and -ll (CR LF to LF) add -lc\n\t(LF to CR LF but CR LF remains unchanged)\n\nKnown bugs:\n\n- On VMS, zip fails reading some files with \"byte record too large for\n\tuser's buffer\". You must use the \"-V\" option for such files.\n\t(many changes to VMS so may be fixed)\n\n- on MSDOS, zip386.exe does not like \"zip -bc: foo ...\"\n\n- on MSDOS, zip386.exe is sometimes much slower than zip.exe. This is\n\tprobably a problem with DJGPP (to be investigated).\n\n- on NT with C shell, zip should not do file name expansion again.\n\n- zip zipfile ... ignores existing zipfile if name does not have an extension\n      (except for the -A option, generally used on self-extracting files).\n      (archives should probably have extensions.  Things like archive.jar work)\n\n- For an sfx file without extension, \"zip -A sfx\" works but \"zip sfx -A\"\n\tdoesn't.  (because options were required first, but now both OK)\n\n- When storing files in a zipfile (-0), zip marks all of them as binary.\n\n- On VMS, some indexed files are not restored correctly after zip -V and unzip.\n\t(This is now known to be a problem of UnZip. The workaround for Zip 2.2\n\tand newer is to use PK-style VMS extra fields; this is now the default.\n\tNOTE that UnZip 5.32 has been fixed [971019]!) (many VMS changes so\n\tthis may be fixed)\n\n- zip and unzip should use the same pattern matching rules, particularly\n\ton MSDOS and OS/2. On OS/2, \"zip foo *.*\" should also match files\n\twithout extension.\n\tPartially DONE (OS/2 \"*.*\" matches \"*\".)\n\n- there should be a way to avoid updating archive members (only addition\n\tof new files allowed)\n"
  },
  {
    "path": "deps/infozip/zip30/USexport.msg",
    "content": "From roelofs (at) sonic.net  Tue Jun 17 08:26:55 2003\nDate: Tue, 17 Jun 2003 08:26:50 -0700\nMessage-Id: <200306171526.h5HFQoaw014091 (at) bolt.sonic.net>\nFrom: Greg Roelofs <newt (at) pobox.com>\nReply-To: Greg Roelofs <newt (at) pobox.com>\nTo: crypt (at) bis.doc.gov, enc (at) ncsc.mil, web_site (at) bis.doc.gov\nSubject: TSU NOTIFICATION - Encryption (Info-ZIP zcrypt.zip)\nCc: newt (at) pobox.com, zip-bugs (at) lists.wku.edu\n\n\n   SUBMISSION TYPE:       TSU\n   SUBMITTED BY:          Greg Roelofs\n   SUBMITTED FOR:         the Info-ZIP group (an informal, Internet-based\n                          collection of software developers with the contact\n                          address given in next item)\n   POINT OF CONTACT:      Zip-Bugs (at) lists.wku.edu\n   PHONE and/or FAX:      n/a\n   MANUFACTURER:          n/a\n   PRODUCT NAME/MODEL #:  zcrypt\n   ECCN:                  5D002\n\n   NOTIFICATION:\n\n\tftp://ftp.info-zip.org/pub/infozip/src/zcrypt.zip\n\n\nFURTHER COMMENTS:\n\n(1) This notice is being sent in order to ensure that we may legally\n    take advantage of the 6 June 2002 amendment to 740.13 regarding\n    \"corresponding object code.\"  The encryption code in question is\n    unchanged since our original notification of 9 April 2000, appended\n    below and also reproduced within the above zcrypt.zip archive.\n    (Indeed, there has been no change to the core encryption/decryption\n    code in well over five years.)\n\n(2) The (larger) source archives for Zip, UnZip, MacZip, WiZ, and\n    potentially other packages, currently available in the same ftp\n    directory given above, also contain (or may contain) copies of\n    the same zcrypt source code.\n\n(3) ftp.info-zip.org currently points to a site in Germany, so techni-\n    cally it is not involved in \"US export\" in any direct way.  However,\n    we encourage other sites to \"mirror\" our software, and some of these\n    mirror sites may be US-based (and therefore involved in reexport of\n    the code in question).  In addition, some Info-ZIP members reside in\n    the US, and www.info-zip.org currently points to a site in Kentucky.\n\n\nORIGINAL NOTIFICATION:\n\nFrom roelofs (at) sonic.net  Sun Apr  9 15:11:45 2000\nDate: Sun, 9 Apr 2000 15:11:27 -0700\nMessage-Id: <200004092211.PAA20023 (at) sonic.net>\nFrom: Greg Roelofs <newt (at) pobox.com>\nTo: crypt (at) bxa.doc.gov\nSubject: notice of export of unrestricted encryption source code\nCc: newt (at) pobox.com, zip-bugs (at) lists.wku.edu\n\nThe Info-ZIP group, an informal, Internet-based collection of software\ndevelopers with contact address Zip-Bugs (at) lists.wku.edu, hereby notifies\nthe US Bureau of Export Administration (BXA) of the posting of freely\navailable encryption source code on the Internet under License Exception\nTSU, to commence later today at this location:\n\n\tftp://ftp.info-zip.org/pub/infozip/src/zcrypt.zip\n\nThis notification is in accordance with section 740.13(e) of the amended\nExport Administration Regulations, as published in the 14 January 2000\nissue of the Federal Register.\n\n-- \nGreg Roelofs            newt (at) pobox.com            http://pobox.com/~newt/\nNewtware, PNG Group, Info-ZIP, Philips Research, ...\n\n"
  },
  {
    "path": "deps/infozip/zip30/WHATSNEW",
    "content": "What's New\n\nLast updated 1 July 2008\n\nThis file is the full list of new features and major changes for Zip 3.0\nby beta release.  See the announcement file zip30.ann for a quick summary\nof all features and changes in Zip 3.0.  Also see the file README for\nrelease information, INSTALL for installation procedures, and the manual\npages zip.txt, zipsplit.txt, zipcloak.txt, and zipnote.txt for how to use\nthe new features.  The file CHANGES has all the day-to-day changes made\nduring development.\n\n\nBelow are some of the more significant items on the list for Zip 3.1\n(see ToDo for a more complete list):\n\n- AES encryption.\n- Extended attributes for Windows, Linux, and Mac OS X.\n- Support -d@ for deleting list of files.\n- Decide if -R, -i and -x should use external rather than internal patterns.\n- Though Unicode paths have been implemented and tested, Unicode comments\n  are not yet supported (except for comments on UTF-8 native systems which\n  are supported).\n- Verbose mode -v may still need work.\n- When pattern is directory add end / automatically.\n- Add C# example for Zip 3.0 (need to be converted to new DLLs) - original\n  C# example added with note.\n- Path Prefix maybe, so entries added to an archive can have a directory\n  path string prepended to each path.\n- UNC path support maybe.\n- Support for other languages maybe.\n- Send in your suggestions.\n- ...\n\n\nMAJOR CHANGES BY BETA VERSION\n-----------------------------\n\nNew things in Zip 3.0 since Zip 3.0h:\n\n- Unicode fixes.\n- Test and fix various ports as needed.\n- Update Win32 resource to support more Windows ports.\n- Add djgpp 2.x makefile that includes bzip2.\n- Add Win32 version resource to Win32 executable.\n- Bug fixes.\n- Documentation updates.\n- Package for release.\n\n\nNew things in Zip 3.0h\n\n- Allow -@ and -x to work together.\n- Unicode code cleanup.\n- Allow forcing use of UTF-8 storage in standard path and comment.\n- Update symbolic link checks.\n- Add support for storing 32-bit UIDs/GIDs using new extra field.\n  Backward compatible support for the old 16-bit UID/GID extra field\n  remains if Zip is compiled on an OS that has 16-bit UID/GID\n  storage.\n- Update VMS notes.\n- Directory scan using -AS (include only files with Windows archive\n  bit set) now ignores archive bit on directories to include all files\n  with archive bit set in all directories.  Also, to avoid empty\n  directories being created, -AS now does not store directory\n  entries.\n- Add Unix IBM support.\n- Change -W to -ws to free -W for later use.\n- Fix large file support for MinGW.\n- Fix large file support for bzip2.\n- Fix compile error in ZipCloak when UNICODE_SUPPORT is not enabled.\n- Fix Unicode bug in ZipCloak involving Unicode paths.\n- Long Unicode escapes changed from #Lxxxxxxxx to #Lxxxxxx to shorten\n  paths with escaped Unicode.\n- Bug fixes.\n\n\nNew things in Zip 3.0g\n\n- Add split support to VB project for Zip64.\n- Disable reading of Unix FIFOs unless new -FI option used to avoid an\n  archiving operation stopping when it hits an active unfed FIFO.\n- The \"[list]\" wildcard expression (regular expression matching of any\n  character or range of characters in list) is now disabled on DOS and\n  Windows as it has caused confusion when filenames have [ and ] in\n  them.  The new -RE option reenables it.\n- Add negation to many display options such as -dc and -db.\n- Allow -FF to read and fix archives having local entries that appear\n  after central directory entries.\n- Bug fixes.\n\n\nNew things in Zip 3.0f\n\n- bzip2 - The bzip2 compression method looks supported for at least\n  Windows, Unix, and VMS using the bzip2 library.  A new option, -Z cm,\n  selects the compression method.\n\n- Split archives - Can now use -s to create a split archive.  The\n  default is to update split files as the archive is being written,\n  which requires all splits to remain open until the archive is done.\n  This should be no problem when writing the archive to a hard drive,\n  for example, and this approach creates archives that should be\n  supported by all unzips that support splits.  Adding the -sp option\n  enables split pause mode that instead writes splits that do not\n  need updating and pauses Zip after each split.  This allows splits\n  to be written directly to removable media, however -sp archives\n  may not be as universally compatible.\n\n- Unicode support - Zip now stores Unicode paths that should be more\n  portable across character sets and languages.  The unzip must have\n  Unicode support enabled or the Unicode paths are ignored.  If\n  reading an archive with Unicode paths, unsupported characters are\n  replaced by #Uxxxx and #Lxxxxxxxx escapes in the file name.  Option\n  -UN controls how Unicode is handled.  Also, on systems where the\n  current character set is UTF-8, preliminary support for the new\n  General Purpose Bit Flag, bit 11, UTF-8 flag, that indicates UTF-8\n  is stored in the path and comment fields is implemented for paths.\n- Unicode on Win32 - On WIN32 systems that support the wide character\n  calls (mainly NT and later systems using NTFS), when UNICODE SUPPORT\n  is enabled Zip will now do directory scans using Unicode and convert\n  the Unicode paths to the local character set for storage in the standard\n  path field and store UTF-8 in the Unicode extra field.  This allows\n  directory scans to complete successfully regardless of the character\n  set the path is in.  On Win9x systems wide character scans are not\n  generally supported and Zip automatically uses a local character scan\n  instead.\n\n- Keep extra fields option - The default operation has been, and continues\n  to be, to read then strip old extra fields when reading entries from an\n  existing archive and then recreate the extra fields that Zip knows about.\n  Extra fields specific to each operating system get added by default also.\n  The new option -X- (negated -X) keeps any old extra fields, copying\n  them to the updated archive unchanged (unless Zip has updated them).\n  The unnegated -X still strips most all extra fields except Zip64,\n  Unicode, and UT time.\n\n- License - minor updates to the license.\n\n- Windows OEM - When compiled with WIN32_OEM (the default for WIN32),\n  Zip on WIN32 now stores OEM paths, which should be more compatible\n  with other zips and should fix some character set problems.\n- Windows Archive Bit support - On Windows can now use new -AS\n  (include if archive bit set) option to select files with the DOS\n  archive bit set and use new -AC (clear archive bits) option to clear\n  the archive bits on files after the archive has been created.\n  But -DF is probably better.\n\n- Difference mode - A new option -DF (--dif) creates an output archive\n  that includes only files changed or new since the input archive was\n  created.  Can use to create incremental backups.\n- File Sync - The new option -FS enables File Sync, a new mode that\n  synchronizes the entries in an archive with the files on the file\n  system, adding updating, and deleting entries as needed.  This\n  should create the same results as creating a new archive, but\n  since existing entries are copied, may be much faster.\n\n- Copy Mode - A new --out option allows creating a new archive with a\n  different name than the input archive, leaving the input archive\n  unchanged.  This allows updating split archives.  It also allows\n  for a new copy mode to select entries in one archive and copy them\n  directly to a new archive.\n- Empty archives - Now an empty archive is created when -i or -i@ is used\n  and the file patterns given do not match anything.  This has been\n  requested to support scripts.\n\n- Global dots - A new -dg option now displays progress dots as -dd does,\n  but instead of displaying them for each file, the dots track the total\n  bytes read for the archive.  The -dg option also works when -q is used\n  to disable most output, which allows for something like zip -qdgds 100m\n  to be used to not display specific files but display a dot every 100 MB\n  as a global status.\n- Date range - Can now use -t and -tt to set a date range\n- Fix options - Option -F redone and can recover files from an archive\n  with a mostly complete central directory more reliably, but no longer\n  can handle truncated archives.  Option -FF redone and now can salvage\n  files from slightly more damaged archives, including truncated archives.\n  In some ways -F is less powerful but more stable than it was and -FF will\n  be needed where -F in Zip 2.32 was enough.  One big change is -F and -FF\n  both now support split archives.\n- Console writing - Updates to how messages are written to the console have\n  been made including more consistent handling of line breaks.\n- Show Files options - Option -sf lists the files that would be operated\n  on.  This option can be used alone to list the files in an archive.\n  Also see options -su and -sU for showing Unicode paths.\n- UnZip Check - Now check that UnZip 6.00 or later is being used for\n  unzip if testing a Zip64 archive.  A new option -TT can be used to set\n  the unzip to use with the -T check.  Currently UnZip does not support\n  split archives so split archives can't be tested by UnZip.\n- Streaming - Directories are now handled better when streaming.\n- Case matching - Normally all matching against archive entries is case\n  sensitive, so *.BAR will not match or find foo.bar in an archive\n  when deleting, copying, or freshening entries (deleting and copying\n  only on VMS).  New option -ic (--ignore-case) enables case insensitive\n  matching.  Currently -ic is only implemented on WIN32 and VMS.\n\n- Delete date bug fixed - Bug when using -d to delete files while\n  using -t or -tt to select the files based on date is fixed\n- Large file encryption bug fixed - Fix for bug that very rarely\n  results in bad data being stored when deflating and encrypting\n  uncompressable data and resulting in CRC errors when extracting,\n  but the chance of error increases with file size (thanks to\n  WinZip for finding this bug).  See CHANGES for details.\n\n\nNew things in Zip 3.0e\n\n- Bugs described in Debian patches 004 (unix configure script update) and\n  005 (large path bug) fixed\n- Various fixes\n- Add optional running stats and also end stats if not all files could\n  be read\n- Options -l and -ll now do quick binary check on first buffer and skip\n  formatting if first buffer has binary - still check at end to note\n  if formatting was done on file that was later determined to be binary,\n  but now potential file corruption is generally avoided\n- Main binary check now uses new algorithm that should also treat UTF-8 and\n  other similar encodings as text, allowing proper line end translation\n  for UTF-8 files\n- When output is not updatable by seeking back and Zip64 is enabled, output\n  is forced to Zip64 to avoid possible later need for Zip64 when not enabled\n- More work on splits, but still not usable\n- Fixes for djgpp\n- Add log file capability to save all errors and optionally messages\n- Add code to test for a Zip64 archive when compiled without Zip64 support\n- New VC6 projects for Win32 and WinDLL\n- Updates to extended help\n- Changes to force-zip64 option\n- ZE_BIG error now given also for files too big to read or write\n- Fix file delete bug\n- Update license\n- Update export documentation\n- Add VMS extended filename support\n- Add directory traversal improvements, some for Win32 ports and some for\n  all ports, that can result in a 10 times increase in speed in some cases\n\n\nNew things in Zip 3.0d\n\n- Some large file crypt fixes\n- Some updates to support WiZ\n- On VMS, changed -V (/VMS) processing to truncate file at EOF, allowing\n  greater compatability with non-VMS systems.  New -VV (/VMS=ALL) option\n  saves all allocated blocks in a file.  (Previously, -V did neither.)\n- On VMS, pushed 2GB file size limit with -V out to 4GB\n- On VMS (recent, non-VAX), with SET PROCESS /PARSE = EXTEND,\n  command-line case is preserved.  This obviates quoting upper-case\n  options, like -V, when enabled\n- On VMS, fixed problems with mixed-case directory names.  Also changed\n  to keep ODS5 extended file name escape characters (\"^\") out of the\n  archived names in simple cases\n- Changes to the display dots\n- Option -W should now force wildcard matching to not cross directory\n  separators.  For example, a/b*r/d will match a/bar/d but not a/ba/r/d\n- Option -nw should turn off all wildcard matching so foo[bar] is matched\n  literally and [bar] is not considered a regular expression\n- Atheos port\n- Debugging of Unix and VMS large file ports.  Most features may work now\n  on these ports for large files.  Still need to fix 2 GB to 4 GB when not\n  compiled with large file support\n- On VMS, added an open callback function which (where supported) senses\n  the process RMS_DEFAULT values for file extend quantity (deq)\n  multi-block count (mbc), and multi-buffer count (mbf), and sets the\n  FAB/RAB parameters accordingly.  The default deq is now much larger\n  than before (16384 blocks, was none), and the default mbc is now 127\n  (up from 64), speeding creation of a large archive file.  The \"-v\"\n  option shows some of the activity.  On old VMS versions, RMS_DEFAULT\n  sensing (GETJPI) fails (silently, without \"-v\"), and no changes will\n  be made.  Even there, (DCL) SET RMS /EXTEND = <big> can help\n  performance.  RMS_DEFAULT values override built-in default values.\n\n\nNew things in Zip 3.0c\n\n- Converted to using 64-bit file environment instead of transitional functions\n  like fseeko64 for ports that support it\n- Added \"--\" argument to read all following arguments as paths\n- Second help page added\n- Binary detection adjusted from 20% binary is binary to 2%\n- When -R and -i used together now -i has precedence over -R\n- Archive names with spaces can now be tested on MSDOS and Win32\n\n\nNew things in Zip 3.0b\n\n- Fixed ifdefs so can test base code by compiling with NO_LARGE_FILE_SUPPORT, then\n  compiling with NO_ZIP64_SUPPORT to test 64-bit file calls (if port enables) but\n  otherwise use base code, and compiling normally to enable Zip64 code\n- Unix Zip64 fixes - should now be able to create and read large files\n- WinDLL changes to support Zip64.  Zip 3.0 dll named Zip32z64.dll\n- New VB example to show use of Zip32z64.dll\n- New options -sc (show final command line and exit) and -sd (show each\n  step zip is doing, a little different than verbose which is still there) added\n  to help debug but both or at least -sd might go away in the release\n- Some minor posted bugs fixed (see Changes)\n\n\nNew things in Zip 3.0a\n\n- Initial Zip64 support allowing large files and large numbers of files\n- New command line processor\n- Other changes, see file Changes\n\n\nNote:  Zip 2.4 was never released.  That code was the start of the Zip 3.0\neffort above.\n\n\nNew things in Zip 2.3\n\n- IBM OS/390 port (Unix like, but EBCDIC) by Paul von Behren\n- Apple Macintosh (MACOS) port by Dirk Haase\n- Theos port by Jean-Michel Dubois\n- Multibyte characterset support by Yoshioka Tsuneo\n- Support for ISO 8601 date format with -t and -tt options\n- Info-ZIP license\n\n\nNew things in Zip 2.2\n\n- BEOS port by Chris Herborth\n- QDOS port by Jonathan Hudson\n- TANDEM port by Dave Smith\n- WINDLL port (16-bit Win 3.x and 32-bit WinNT/Win95) by Mike White\n- SYSV packages support by John Bush\n- zip -P SeCrEt encrypts entries in the zip file with password SeCrEt\n  (WARNING: THIS IS INSECURE, use at your own risk)\n- zip -R recurses into subdirectories of current dir like \"PKZIP -rP\"\n- zip -x@exclude.lst excludes files specified in the file exclude.lst\n- zip -i@include.lst includes files specified in the file include.lst\n- zip -@ only handles one filename per line, but supports whitespace in names\n- zip -t mmddyyyy, 4 digit year number for uniqueness of years beyond 2000\n- zip -tt mmddyyyy only includes files before a specified date\n"
  },
  {
    "path": "deps/infozip/zip30/WHERE",
    "content": "__________________________________________________________________________\n\n   This is the Info-ZIP file ``WHERE,'' last updated on 1 March 2005.\n__________________________________________________________________________\n\n   This file is out of date.  We plan to update the structure of the ftp\n   site shortly and should be updating this file as soon as that's done.\n\n   The latest version of this file can be found online at:\n\n           ftp://ftp.info-zip.org/pub/infozip/doc/WHERE\n\n   Note that some ftp sites may not yet have the latest versions of Zip\n   and UnZip when you read this.  The latest versions always appear in\n   ftp://ftp.info-zip.org/pub/infozip/ (and subdirectories thereof) first,\n   except for encryption binaries, which always appear in\n   ftp://ftp.icce.rug.nl/infozip/ (and subdirectories) first.\n\n   IF YOU FIND AN ERROR:  please let us know!  We don't have time to\n   check each and every site personally (or even collectively), so any\n   number of the sites listed below may have moved or disappeared en-\n   tirely.  E-mail to Zip-Bugs@lists.wku.edu and we'll update this file.\n__________________________________________________________________________\n\n\nInfo-ZIP's home WWW site is listed on Yahoo and is at:\n\n   ftp://ftp.info-zip.org/pub/infozip/Info-ZIP.html  (master version)\n   http://ftp.info-zip.org/pub/infozip/              (master version)\n   http://www.info-zip.org/\n\nNote that the old sites at http://www.cdrom.com/pub/infozip/ and\nhttp://www.freesoftware.com/pub/infozip are PERMANENTLY BROKEN.  They\ncannot be updated or removed, apparently.\n\nThe Zip and UnZip pages have links to most known mirror sites carrying our\nsource and/or binary distributions, and they generally are more up-to-date\nand have better information than what you are reading:\n\n   ftp://ftp.info-zip.org/pub/infozip/Zip.html\n   ftp://ftp.info-zip.org/pub/infozip/UnZip.html\n\nThe related zlib package by Info-ZIP's Jean-loup Gailly and Mark Adler is at:\n\n   http://www.zlib.net/\n\nSource-code archives for Info-ZIP's portable Zip, UnZip, and related\nutilities:\n\n   zip231.zip        Zip 2.31 (deflation; includes zipnote/zipsplit/zipcloak)\n   zip231.tar.Z      ditto, compress'd tar format\n\n   zip11.zip         Zip 1.1 (shrinking, implosion; compatible w. PKUNZIP 1.1)\n   zip11.tar.Z       ditto, compress'd tar format\n\n   unzip552.zip      UnZip 5.52 (all methods[*]; unzip/funzip/unzipsfx/zipgrep)\n   unzip552.tar.gz   ditto, gzip'd tar format\n   unzip552.tar.Z    ditto, compress'd tar format\n\n   unred552.zip      UnZip 5.52 add-on, contains copyrighted unreduce support\n\n   zcrypt29.zip      encryption support for Zip 2.3[**]\n   zcrypt10.zip      encryption support for Zip 1.1\n\n   MacZip106src.zip  contains all the GUI stuff and the project files to build\n                     the MacZip main-app.  To build MacZip successfully, both\n                     the Zip 2.31 and UnZip 5.52 sources are required, too.\n\n   wiz502.zip        WiZ 5.02, Windows 9x/NT GUI front-end for Info-ZIP DLLs\n   wiz502+dlls.zip   WiZ 5.02, Windows 9x/NT GUI front-end plus DLL sources\n\n[*] Unreducing is disabled by default, but is available as add-on.\n    As of July 2004, Unisys's LZW patent was expired worldwide, and\n    unshrinking is turned on by default since the release of UnZip 5.52.\n    See UnZip's INSTALL file for details.\n\n[**] As of January 2000, US export regulations were amended to allow export\n     of free encryption source code from the US.  As of June 2002, these\n     regulations were further relaxed to allow export of encryption binaries\n     associated with free encryption source code.  The Zip 2.31, UnZip 5.52\n     and Wiz 5.02 archives now include full crypto source code.  As of the\n     Zip 2.31 release, all official binaries include encryption support; the\n     former \"zcr\" archives ceased to exist.\n     (Note that restrictions may still exist in other countries, of course.)\n\nExecutables archives (and related files) for Info-ZIP's software; not all\nof these will be immediately available due to lack of access to appropriate\nsystems on the part of Info-ZIP members.\n\n   zip231x.zip       MSDOS executables and docs\n   zip231x1.zip      OS/2 1.x (16-bit) executables and docs\n   zip231x2.zip      OS/2 2/3/4.x (32-bit) executables and docs\n   zip231xA.zip      Amiga executables and docs\n   zip231xB.zip      BeOS executables and docs\n   zip231xC.zip      VM/CMS executable and docs\n   zip231xK.zip      Tandem NSK executables and docs\n   zip231xM.xmit     MVS classic executable\n   zip231xM-docs.zip MVS classic port, docs only\n   zip231dN.zip      WinNT/Win9x (Intel) DLL, header files, docs\n   zip231xN.zip      WinNT/Win9x (Intel) executables and docs\n   zip231xN-axp.zip  WinNT (Alpha AXP) executables and docs\n   zip231xN-mip.zip  WinNT (MIPS R4000) executables and docs\n   zip231xN-ppc.zip  WinNT (PowerPC) executables and docs\n   zip231xO.zip      IBM OS/390 Open Edition binaries and docs\n   zip231xQ.zip      SMS/QDOS executables and docs\n   zip231xR.zip      Acorn RISC OS executables and docs\n   zip231xT.zip      Atari TOS executables and docs\n   zip231-vms-axp-obj.zip\n                     VMS (Alpha AXP) object libs, link procedure and docs\n   zip231-vms-axp-exe.zip\n                     VMS (Alpha AXP) executables for VMS 6.1 or later and docs\n   zip231-vms-vax-decc-obj.zip\n                     VMS (VAX) object libs (new DEC C), link procedure and docs\n   zip231-vms-vax-decc-exe.zip\n                     VMS (VAX) executables (DEC C) for VMS 6.1 or later; docs\n   zip231-vms-vax-vaxc-obj.zip\n                     VMS (VAX) object libs (old VAX C), link procedure and docs\n   zip231x.hqx       Macintosh BinHex'd executables and docs\n\n   unz552x.exe       MSDOS self-extracting executable (16-bit unzip, ..., docs)\n   unz552x3.exe      MSDOS self-extracting executable (16-, 32-bit unzip, docs)\n   unz552x1.exe      OS/2 1.x (16-bit) self-extracting executables and docs\n   unz552x2.exe      OS/2 2/3/4.x (32-bit) self-extracting executables and docs\n   unz552d2.zip      OS/2 2/3/4.x (32-bit) DLL, header file, demo exe and docs\n   unz552xA.ami      Amiga self-extracting executables and docs\n   unz552xA.lha      Amiga executables and docs, LHa archive\n   unz552xB.sfx      BeOS self-extracting executables and docs\n   unz552xB.tar.gz   BeOS executables and docs, gzip'd tar archive\n   unz552xC.mod      VM/CMS executable module in \"packed\" format\n   unz552xC-docs.zip VM/CMS docs, only\n   unz552xF.zip      FlexOS executable and docs\n   unz552xK.zip      Tandem NSK executable and docs\n   unz552xM.xmit     MVS classic executable\n   unz552xM-docs.zip MVS classic port, docs only\n   unz552dN.zip      NT4/W2K/XP/2K3/W9x (32-bit Intel) DLL, header files, docs\n   unz552xN.exe      NT/2K/XP/2K3/W9x self-extracting i386 executables and docs\n   unz552xN-axp.exe  WinNT (Alpha AXP) self-extracting executables and docs\n   unz552xN-mip.exe  WinNT (MIPS R4000) self-extracting executables and docs\n   unz552xN-ppc.exe  WinNT (PowerPC) self-extracting executables and docs\n   unz552xQ.sfx      SMS/QDOS self-extracting executables and docs\n   unz552xO.tar.Z    IBM OS/390 Open edition (Unix-like), exes and docs\n   unz552xR.exe      Acorn RISC OS self-extracting executables and docs\n   unz552xR.spk      Acorn RISC OS Spark'd executables and docs\n   unz552xT.tos      Atari TOS self-extracting executables and docs\n   unz552x-vms-axp-obj.bck    VMS backup saveset,\n                     contains UnZip (Alpha) obj libs, link procedure, docs\n   unz552x-vms-axp-obj.exe    VMS (Alpha AXP) SFX archive (statically linked),\n                     contains UnZip (Alpha) obj libs, link procedure, docs\n   unz552x-vms-axp-exe.exe    VMS (Alpha AXP) SFX archive (dynamically linked),\n                     contains UnZip (Alpha AXP, DEC C) executables and docs,\n                     smaller than object archive, but requires VMS 6.1\n   unz552x-vms-vax-decc-obj.bck   VMS backup saveset,\n                     contains UnZip (new DEC C) obj libs, link procedure, docs\n   unz552x-vms-vax-decc-obj.exe   VMS (VAX) SFX archive (statically linked),\n                     contains UnZip (new DEC C) obj libs, link procedure, docs\n   unz552x-vms-vax-decc-exe.exe   VMS (VAX) SFX archive (dynamically linked),\n                     contains UnZip (new DEC C) executables and docs,\n                     smaller than object archive, but requires VMS 6.1\n   unz552x-vms-vax-vaxc-obj.bck   VMS backup saveset,\n                     contains UnZip (old VAX C) obj libs, link procedure, docs\n   unz552x-vms-vax-vaxc-obj.exe   VMS (VAX) SFX archive (statically linked),\n                     contains UnZip (old VAX C) obj libs, link procedure, docs\n   unz552x.hqx       Macintosh BinHex'd executables and docs for unzip\n  (unz552x.tar.{Z,gz}  Unix exes/docs for Solaris 2.x, SCO Unix, Linux, etc.,\n                     depending on directory/location; generally only provided\n                     in cases where the OS does *not* ship with a bundled C\n                     compiler)\n\n   MacZip106nc.hqx   Macintosh combined Zip&UnZip application with GUI,\n                     executables and docs (no encryption)\n   MacZip106c.hqx    Macintosh combined Zip&UnZip application with GUI,\n                     executables and docs (with encryption)\n\n   wiz502xN.exe      WiZ 5.02 32-bit (Win9x/NT/2K/XP/2K3) app+docs (self-extr.)\n\n   UnzpHist.zip      complete changes-history of UnZip and its precursors\n   ZipHist.zip       complete changes-history of Zip\n\nftp/web sites for the US-exportable sources and executables:\n\n   NOTE:  Look for the Info-ZIP file names given above (not PKWARE or third-\n   party stuff) in the following locations.  Some sites like to use slightly\n   different names, such as zip-2.31.tar.gz instead of zip231.tar.Z.\n\n   ftp://ftp.info-zip.org/pub/infozip/                 [THE INFO-ZIP HOME SITE]\n   ftp://sunsite.doc.ic.ac.uk/packages/zip/    [MIRRORS THE INFO-ZIP HOME SITE]\n   ftp://unix.hensa.ac.uk/mirrors/uunet/pub/archiving/zip/\n\n   ftp://ftp.cmdl.noaa.gov/aerosol/doc/archiver/{all,dos,os2,mac,vax_alpha}/\n   ftp://garbo.uwasa.fi/pc/arcers/                    [AND OTHER GARBO MIRRORS]\n   ftp://garbo.uwasa.fi/unix/arcers/                  [AND OTHER GARBO MIRRORS]\n   ftp://ftp.elf.stuba.sk/pub/pc/pack/                [AND OTHER STUBA MIRRORS]\n   ftp://ftp-os2.cdrom.com/pub/os2/archiver/\n   ftp://ftp-os2.nmsu.edu/os2/archiver/\n   ftp://ftp.informatik.tu-muenchen.de/pub/comp/os/os2/archiver/\n   ftp://sumex-aim.stanford.edu/info-mac/cmp/\n   ftp://ftp.wustl.edu/pub/aminet/util/arc/          [AND OTHER AMINET MIRRORS]\n   ftp://atari.archive.umich.edu/pub/Archivers/       [AND OTHER UMICH MIRRORS]\n   http://www.umich.edu/~archive/atari/Archivers/\n   ftp://jake.educom.com.au/pub/infozip/acorn/                  [Acorn RISC OS]\n   http://www.sitec.net/maczip/                                   [MacZip port]\n\nftp/web sites for the encryption and decryption sources and/or executables:\n\n   Outside the US:\n      ftp://ftp.info-zip.org/pub/infozip/   [THE INFO-ZIP HOME SITE]\n      ftp://ftp.icce.rug.nl/infozip/        [THE INFO-ZIP ENCRYPTION HOME SITE]\n      ftp://ftp.elf.stuba.sk/pub/pc/pack/\n      ftp://garbo.uwasa.fi/pc/arcers/\n      ftp://ftp.inria.fr/system/arch-compr/\n      ftp://ftp.leo.org/pub/comp/os/os2/leo/archiver/\n        (mail server at ftp-mailer@ftp.leo.org)\n\n      ftp://ftp.win.tue.nl/pub/compression/zip/\n      ftp://ftp.uni-erlangen.de/pub/pc/msdos/arc-utils/zip/\n\n\nThe primary distribution site for the MacZip port can be found at:\n\n   http://www.sitec.net/maczip/\n\nftp sites for VMS-format Zip and UnZip packages (sources, object files and\nexecutables, no encryption/decryption--see also \"Mail servers\" section below):\n\n   ftp.spc.edu [192.107.46.27] and ftp.wku.edu:\n\n   [.MACRO32]AAAREADME.TXT\n   [.MACRO32.SAVESETS]UNZIP.BCK  or  UNZIP.ZIP  (if already have older version)\n   [.MACRO32.SAVESETS]ZIP.ZIP\n\nTo find other ftp/web sites:\n\n   The \"archie\" ftp database utility can be used to find an ftp site near\n   you (although the command-line versions always seem to find old ver-\n   sions...the `FTPsearch' server at http://ftpsearch.ntnu.no/ftpsearch\n   --formerly `Archie 95'--is quite up-to-date, however).  Or check a stan-\n   dard WWW search engine like AltaVista (http://www.altavista.digital.com/)\n   or Yahoo (http://www.yahoo.com/).  If you don't know how to use these,\n   DON'T ASK US--read the web sites' help pages or check the Usenet groups\n   news.announce.newusers or news.answers or some such, or ask your system\n   administrator.\n\nMail servers:\n\n   To get the encryption sources by e-mail, send the following commands\n   to ftp-mailer@informatik.tu-muenchen.de:\n\n      get /pub/comp/os/os2/archiver/zcrypt29.zip\n      quit\n\n   To get the VMS Zip/UnZip package by e-mail, send the following\n   commands in the body of a mail message to fileserv@wku.edu (the\n   \"HELP\" command is also accepted):\n\n      SEND FILESERV_TOOLS\n      SEND UNZIP\n      SEND ZIP\n\n   To get Atari executables by e-mail, send a message to\n   atari@atari.archive.umich.edu for information about the mail server.\n__________________________________________________________________________\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/GMakefile",
    "content": "# Makefile for Zip, ZipNote, ZipCloak and ZipSplit\n\n# add -g to CC to debug\n# add -d to BIND to debug\nCC   = gcc -mlibscl\nBIND = $(CC)\nAS   = $(CC) -c\nASM  = AS\nSQUEEZE = squeeze -v\nE    =\n\n# flags\n#   CFLAGS    flags for C compile\n#   LFLAGS1   flags after output file spec, before obj file list\n#   LFLAGS2   flags after obj file list (libraries, etc)\n#\nLIB      =\nCFLAGS   = -O2 -mthrowback -DASMV\nASMFLAGS = -throwback -objasm -upper\nLFLAGS1  = \nLFLAGS2  = $(LIB)\n\n# Uncomment the following line to enable support for Unix\n# Extra Field (Timezone)\n#CFLAGS  = $(CFLAGS) -DUSE_EF_UT_TIME\n\n# object file lists\nOBJZ = o.zip o.zipfile o.zipup o.fileio o.util o.globals o.crc32 \\\n       o.crypt o.ttyio o.riscos o.acornzip o.swiven\n\nOBJI = o.deflate o.trees\nOBJA = o.match o.sendbits\nOBJU = o.zipfile_ o.fileio_ o.util_ o.globals o.riscos o.acornzip_ o.swiven\nOBJN = o.zipnote  $(OBJU)\nOBJC = o.zipcloak $(OBJU) o.crc32_ o.crypt_ o.ttyio\nOBJS = o.zipsplit $(OBJU)\n\nZIP_H = h.zip h.ziperr h.tailor acorn.h.osdep acorn.h.riscos acorn.h.swiven\n\nall:      zip zipnote zipsplit zipcloak\n\ninstall:  %.zip %.zipnote %.zipsplit %.zipcloak %.acorn.zipsfx \\\n          zip zipnote zipsplit zipcloak acorn.zipsfx\n\t$(SQUEEZE) zip %.zip\n\t$(SQUEEZE) zipnote %.zipnote\n\t$(SQUEEZE) zipsplit %.zipsplit\n\t$(SQUEEZE) zipcloak %.zipcloak\n\tcopy acorn.zipsfx %.zipsfx ~CVF\n\n# rules for zip, zipnote, zipcloak and zipsplit\n\no.api:\t\tc.api\n\t$(CC) $(CFLAGS) -c c.api -o o.api\no.crc32:\tc.crc32 $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -c c.crc32 -o o.crc32\no.crypt:\tc.crypt $(ZIP_H) h.crypt h.crc32 h.ttyio\n\t$(CC) $(CFLAGS) -c c.crypt -o o.crypt\no.deflate:\tc.deflate $(ZIP_H)\n\t$(CC) $(CFLAGS) -c c.deflate -o o.deflate\no.fileio:\tc.fileio $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -c c.fileio -o o.fileio\no.globals:\tc.globals $(ZIP_H)\n\t$(CC) $(CFLAGS) -c c.globals -o o.globals\no.mktime:\tc.mktime\n\t$(CC) $(CFLAGS) -c c.mktime -o o.mktime\no.trees:\tc.trees $(ZIP_H)\n\t$(CC) $(CFLAGS) -c c.trees -o o.trees\no.ttyio:\tc.ttyio $(ZIP_H) h.crypt\n\t$(CC) $(CFLAGS) -c c.ttyio -o o.ttyio\no.util:\t\tc.util $(ZIP_H)\n\t$(CC) $(CFLAGS) -c c.util -o o.util\no.zip:\t\tc.zip $(ZIP_H) h.crc32 h.crypt h.revision h.ttyio\n\t$(CC) $(CFLAGS) -c c.zip -o o.zip\no.zipcloak:\tc.zipcloak $(ZIP_H) h.crc32 h.crypt h.revision h.ttyio\n\t$(CC) $(CFLAGS) -c c.zipcloak -o o.zipcloak\no.zipfile:\tc.zipfile $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -c c.zipfile -o o.zipfile\no.zipnote:\tc.zipnote $(ZIP_H) h.revision\n\t$(CC) $(CFLAGS) -c c.zipnote -o o.zipnote\no.zipsplit:\tc.zipsplit $(ZIP_H) h.revision\n\t$(CC) $(CFLAGS) -c c.zipsplit -o o.zipsplit\no.zipup:\tc.zipup $(ZIP_H) h.crc32 h.crypt h.revision\n\t$(CC) $(CFLAGS) -c c.zipup -o o.zipup\n\no.crc32_: c.crc32 $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -DUTIL -c c.crc32 -o o.crc32_\no.crypt_: c.crypt $(ZIP_H) h.crypt h.crc32 h.ttyio\n\t$(CC) $(CFLAGS) -DUTIL -c c.crypt -o o.crypt_\no.util_: c.util $(ZIP_H)\n\t$(CC) $(CFLAGS) -DUTIL -c c.util -o o.util_\no.fileio_: c.fileio $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -DUTIL -c c.fileio -o o.fileio_\no.zipfile_: c.zipfile $(ZIP_H) h.crc32\n\t$(CC) $(CFLAGS) -DUTIL -c c.zipfile -o o.zipfile_\no.acornzip_: acorn.c.acornzip $(ZIP_H)\n\t$(CC) $(CFLAGS) -I@ -DUTIL -c acorn.c.acornzip -o o.acornzip_\n\no.riscos: acorn.c.riscos acorn.h.riscos $(ZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c acorn.c.riscos -o o.riscos\n\no.acornzip: acorn.c.acornzip $(ZIP_H)\n\t$(CC) $(CFLAGS) -I@ -c acorn.c.acornzip -o o.acornzip\n\no.match: acorn.s.match\n\t$(ASM) $(ASMFLAGS) -I@ acorn.s.match -o o.match\n\no.sendbits: acorn.s.sendbits\n\t$(ASM) $(ASMFLAGS) -I@ acorn.s.sendbits -o o.sendbits\n\no.swiven: acorn.s.swiven\n\t$(ASM) $(ASMFLAGS) -I@ acorn.s.swiven -o o.swiven\n\nzip:\t$(OBJZ) $(OBJI) $(OBJA)\n\t$(BIND) -o zip$(E) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)\nzipnote:  $(OBJN)\n\t$(BIND) -o zipnote$(E) $(LFLAGS1) $(OBJN) $(LFLAGS2)\nzipcloak: $(OBJC)\n\t$(BIND) -o zipcloak$(E) $(LFLAGS1) $(OBJC) $(LFLAGS2)\nzipsplit: $(OBJS)\n\t$(BIND) -o zipsplit$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)\n\nclean:\t\n\tremove zip\n\tremove zipcloak\t\n\tremove zipsplit\n\tremove zipnote\n\tcreate o.!fake! 0\n\twipe o.* ~cf\n\n# end of Makefile\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/ReadMe",
    "content": "Acorn-specific compile instructions\n-----------------------------------\n\nUse the \"RunMe1st\" file (it is an Obey file) to convert all the files from\n\"filename/[chs]\" to \"[chs].filename\" (so that zip could be easily compiled\nunder RISC OS). It will also set the correct makefile.\n\nTo compile just set the CSD to the main zip directory and run 'amu'.\n\nCurrently only the Acorn C V5 compiler has been tested but probably also\nAcorn C V4 and the Acorn Assembler V2 will be able to compile zip.\n\nThe default makefile is configured without the support for the\nExtended Timestamp Extra Field. If you wan to enable it you have to\nadd \"-DUSE_EF_UT_TIME\" to CFLAGS (see makefile). Without the Extended\nTimestamp Field support, zipfiles created by zip are identical to the\nzipfiles created by SparkFS. However, the Extended Timestamp Field can\nbe useful if you are going to unzip your zipfiles on a non-RISC OS machine\nsince the correct time stamp will be preserved across different timezones.\nNote that in this case, both the SparkFS Extra Field and the Extended\nTimestamp Extra Field will be used, so the zipfiles will still be fully\ncompatible with SparkFS and with the RISC OS version of unzip.\n\nThe executables-only distributions will be compiled without the support for\nthe Extended Timestamp Extra Field. If you need it but you can't compile zip\nyourself, you can contact the authors at the Info-ZIP address who will do it\nfor you.\n\n\nAcorn-specific usage instructions\n---------------------------------\n\nAn extra option ('I') has been added to the Acorn port: if it is specified\nzip will not consider Image files (eg. DOS partitions or Spark archives when\nSparkFS is loaded) as directories but will store them as single files. This\nmeans that if you have, say, SparkFS loaded, zipping a Spark archive will\nresult in a zipfile containing a directory (and its content) while using the\n'I' option will result in a zipfile containing a Spark archive. Obviously\nthis second case will also be obtained (without the 'I' option) if SparkFS\nisn't loaded.\n\nWhen adding files to a zipfile; to maintain FileCore compliance, all\nfiles named \"file/ext\" will be added to the archive as \"file.ext\".\nThis presents no problem if you wish to use unzip to extract them on any\nother machine, as the files are correctly named. This also presents no\nproblem if you use unzip for RISC OS, as the files are converted back to\n\"file/ext\" format. The only problem appears when you use SparkFS to\ndecompress the files, as a file called \"file.ext\" will be extracted as\n\"file_ext\", not what it was added as. You must be careful about this.\n\nCase Specific. Depending on how you type the command, files will be added\nexactly as named; in this example:\n*zip new/zip newfile\n*zip new/zip NewFile\n*zip new/zip NEWFILE\nwill create an archive containing 3 copies of the same Risc OS file 'newfile'\ncalled 'newfile', 'NewFile' and 'NEWFILE'. Please be careful.\n\nThe Acorn port conserves file attributes, including filetype, so if you\nzip on an Acorn, and unzip on another Acorn, filetypes will be maintained\nprecisely as if you used uncompressed files. If you de-archive on another\nmachine (PC, Mac, Unix etc..), filetypes will be ignored, but the files\nwill be identical despite this. This feature is fully compatible with\nSparkFS, so zipfiles created by zip will be correctly uncompressed (including\nfiletype, etc.) by SparkFS.\n\nAn additional feature went into this port to cope better with C-code\nand extensions. This allows the acorn files \"c.foo\" to be added to the\narchive as \"foo/c\", eventually appearing in the archive as \"foo.c\", allowing\nfor better handling of C or C++ code. Example:\n*Set Zip$Exts \"dir1:dir2:dir3\"\n*zip new/zip dir1.file\n*zip new/zip dir2.help\n*zip new/zip dir3.textfile\nCreates a zipfile new/zip, with entries file.dir1, help.dir2, textfile.dir3.\nThe usual settings for Zip$Exts are \"h:o:s:c\", allowing C code to be added\nto the archive in standard form.\n\nA final note about the Acorn port regards the use of the 'n' option: this is\nused to specify a list of suffixes that will not be compressed (eg. .ZIP,\nsince it is already a compressed file). Since RISC OS uses filetypes instead\nof suffixes, this list of suffixes is actually considered as a list of\nfiletypes (3 hex digit format). By default, zip doesn't compress filetypes\nDDC (Archive, Spark or Zip), D96 (CFS files) and 68E (PackDir).\n\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/ReadMe.GMakefile",
    "content": "GMakefile is for use with Acorn RISC OS and the forthcoming\npost-Acorn RISC OS for the compilation of both the current release and\ndevelopment versions of zip.\n\nIt is recommended that you use gcc 2.95.4 or higher and you will need a \nsuitable 'make' utility. Both are available from \n<URL:http://hard-mofo.dsvr.net/gcc/>.\n\nYou will need the files gcc.zip and cc1.zip for the C compiler with the\ndocumentation available in the gccdoc.zip archive. GNU make can be \nfound in the utils.zip archive, although most versions of 'make' should be\nfine.\n\nWhen using gcc, check RunMe1st for two lines which need uncommenting.\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/RunMe1st",
    "content": "| This Obey file prepares the zip port for a Desktop C re-compile.\n| Run it and it will copy all the needed files into the correct\n| place.\n\n| Set the correct type of 'srcrename' so that the only requirement\n| for the user is to set 'RunMe1st' to Obey\nSetType <Obey$Dir>.srcrename FF8\n\n| Run 'srcrename' on the main zip directory with recursion enabled\n/<Obey$Dir>.srcrename -r -e c:h:s:o <Obey$Dir>.^\n\n| Create the 'o' directory\nCDir <Obey$Dir>.^.o\n\n| Put the Makefile in its correct place and set the correct filetype\nCopy <Obey$Dir>.makefile <Obey$Dir>.^.makefile ~C ~V F\n\n| Uncomment the following lines if you're using gcc\n|| Put the Makefile in its correct place and set the correct filetype\n|Copy <Obey$Dir>.GMakefile <Obey$Dir>.^.makefile ~C~VF\n\nSetType <Obey$Dir>.^.makefile FE1\nSetType <Obey$Dir>.zipsfx Obey\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/acornzip.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include <stdlib.h>\n#include <string.h>\n#include \"zip.h\"\n\n#ifndef UTIL\n\n#define PAD 0\n#define PATH_END '/'\n\n\nlocal int wild_recurse(char *whole, char *wildtail);\nlocal int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\nchar *readd(DIR *d)\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n   struct dirent *e;\n\n   e = readdir(d);\n   return (e == NULL ? (char *) NULL : e->d_name);\n}\n\n/* What we have here is a mostly-generic routine using opend()/readd() and */\n/* isshexp()/MATCH() to find all the files matching a multi-part filespec  */\n/* using the portable pattern syntax.  It shouldn't take too much fiddling */\n/* to make it usable for any other platform that has directory hierarchies */\n/* but no shell-level pattern matching.  It works for patterns throughout  */\n/* the pathname, such as \"foo:*.?/source/x*.[ch]\".                         */\n\n/* whole is a pathname with wildcards, wildtail points somewhere in the  */\n/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */\n\nlocal int wild_recurse(whole, wildtail) char *whole; char *wildtail;\n{\n    DIR *dir;\n    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;\n    ush newlen, amatch = 0;\n    struct stat statb;\n    int disk_not_mounted=0;\n    int e = ZE_MISS;\n\n    if (!isshexp(wildtail)) {\n        if (stat(whole,&statb)==0 && (statb.st_mode & S_IREAD)!=0) {\n            return procname(whole, 0);\n        } else\n            return ZE_MISS;                     /* woops, no wildcards! */\n    }\n\n    /* back up thru path components till existing dir found */\n    do {\n        name = wildtail + strlen(wildtail) - 1;\n        for (;;)\n            if (name-- <= wildtail || *name == '.') {\n                subwild = name + 1;\n                plug2 = *subwild;\n                *subwild = 0;\n                break;\n            }\n        if (glue)\n            *glue = plug;\n        glue = subwild;\n        plug = plug2;\n        dir = opendir(whole);\n    } while (!dir && !disk_not_mounted && subwild > wildtail);\n    wildtail = subwild;                 /* skip past non-wild components */\n\n    if ((subwild = strchr(wildtail + 1, '.')) != NULL) {\n        /* this \"+ 1\" dodges the   ^^^ hole left by *glue == 0 */\n        *(subwild++) = 0;               /* wildtail = one component pattern */\n        newlen = strlen(whole) + strlen(subwild) + 32;\n    } else\n        newlen = strlen(whole) + 31;\n    if (!dir || !(newwhole = malloc(newlen))) {\n        if (glue)\n            *glue = plug;\n        e = dir ? ZE_MEM : ZE_MISS;\n        goto ohforgetit;\n    }\n    strcpy(newwhole, whole);\n    newlen = strlen(newwhole);\n    if (glue)\n        *glue = plug;                           /* repair damage to whole */\n    if (!isshexp(wildtail)) {\n        e = ZE_MISS;                            /* non-wild name not found */\n        goto ohforgetit;\n    }\n\n    while (name = readd(dir)) {\n        if (MATCH(wildtail, name, 0)) {\n            strcpy(newwhole + newlen, name);\n            if (subwild) {\n                name = newwhole + strlen(newwhole);\n                *(name++) = '.';\n                strcpy(name, subwild);\n                e = wild_recurse(newwhole, name);\n            } else\n                e = procname(newwhole, 0);\n            newwhole[newlen] = 0;\n            if (e == ZE_OK)\n                amatch = 1;\n            else if (e != ZE_MISS)\n                break;\n        }\n    }\n\n  ohforgetit:\n    if (dir) closedir(dir);\n    if (subwild) *--subwild = '.';\n    if (newwhole) free(newwhole);\n    if (e == ZE_MISS && amatch)\n        e = ZE_OK;\n    return e;\n}\n\nint wild(p)\nchar *p;\n{\n  char *path;\n  int toret;\n\n  /* special handling of stdin request */\n  if (strcmp(p, \"-\") == 0)   /* if compressing stdin */\n    return newname(p, 0, 0);\n\n  path=p;\n  if (strchr(p, ':')==NULL && *p!='@') {\n    if (!(path=malloc(strlen(p)+3))) {\n      return ZE_MEM;\n    }\n    strcpy(path,\"@.\");\n    strcat(path,p);\n  }\n\n  toret=wild_recurse(path, path);\n\n  if (path!=p) {\n    free(path);\n  }\n  return toret;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '.')\n        strcpy(a, \".\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  char *tmp;\n  int dosflag;\n  char *lastlastdir=NULL;   /* pointer to 2 dirs before... */\n  char *lastdir=NULL;       /* pointer to last dir... */\n\n  /* Malloc space for internal name and copy it */\n  if ((tmp = malloc(strlen(x) + 1)) == NULL)\n    return NULL;\n  strcpy(tmp, x);\n\n  dosflag = dosify; /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for(t=tmp;*t;t++) {\n    if (*t=='/') {\n      *t='.';\n    }\n    else if (*t=='.') {\n      *t='/';\n      lastlastdir=lastdir;\n      lastdir=t+1;\n    }\n  }\n\n  t=strchr(tmp,'$');      /* skip FS name */\n  if (t!=NULL)\n    t+=2;                 /* skip '.' after '$' */\n  else\n    t=tmp;\n  if (*t=='@')            /* skip @. at the beginning of filenames */\n    t+=2;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n\n  /* return a pointer to '\\0' if the file is a directory with the same\n     same name as an extension to swap (eg. 'c', 'h', etc.) */\n  if (isdir && exts2swap!=NULL) {\n    if (lastlastdir==NULL)\n      lastlastdir=t;\n    if (checkext(lastlastdir)) {\n      free((void *)tmp);\n      n=malloc(1);\n      if (n!=NULL)\n        *n='\\0';\n      return n;\n    }\n  }\n\n  if (exts2swap!=NULL && lastdir!=NULL) {\n    if (lastlastdir==NULL)\n      lastlastdir=t;\n    if (checkext(lastlastdir)) {\n      if (swapext(lastlastdir,lastdir-1)) {\n        free((void *)tmp);\n        return NULL;\n      }\n    }\n  }\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL) {\n    free((void *)tmp);\n    return NULL;\n  }\n  strcpy(n, t);\n\n  free((void *)tmp);\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n  char *t;              /* scans name */\n  char *lastext=NULL;   /* pointer to last extension */\n  char *lastdir=NULL;   /* pointer to last dir */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n\n  for(t=x;*t;t++) {\n    if (*t=='.') {\n      *t='/';\n      lastext=t+1;\n    }\n    else if (*t=='/') {\n      *t='.';\n      lastdir=t+1;\n    }\n  }\n\n  if (exts2swap!=NULL && (int)lastext>(int)lastdir) {\n    if (lastdir==NULL)\n      lastdir=x;\n    if (checkext(lastext)) {\n      if (swapext(lastdir,lastext-1)) {\n        free((void *)x);\n        return NULL;\n      }\n    }\n  }\n\n  return x;\n}\n\nlocal int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut)\n{\n  unsigned timlo;       /* 3 lower bytes of acorn file-time plus carry byte */\n  unsigned timhi;       /* 2 high bytes of acorn file-time */\n\n  timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U;\n  timhi = ((unsigned)ut >> 24);\n  timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);\n  if (timhi & 0xffff0000U)\n      return 1;         /* calculation overflow, do not change time */\n\n  /* insert the five time bytes into loadaddr and execaddr variables */\n  *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);\n  *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU);\n\n  return 0;             /* subject to future extension to signal overflow */\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  time_t m_time;\n  unsigned int loadaddr, execaddr;\n  int attr;\n\n  /* Convert DOS time to time_t format in m_time */\n  m_time = dos2unixtime(d);\n\n  /* set the file's modification time */\n  SWI_OS_File_5(f,NULL,&loadaddr,NULL,NULL,&attr);\n\n  if (uxtime2acornftime(&execaddr, &loadaddr, m_time) != 0)\n      return;\n\n  SWI_OS_File_1(f,loadaddr,execaddr,attr);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  unsigned int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '.')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n  /* forge stat values for stdin since Amiga and RISCOS have no fstat() */\n    s.st_mode = (S_IREAD|S_IWRITE|S_IFREG);\n    s.st_size = -1;\n    s.st_mtime = time(&s.st_mtime);\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFDIR) != 0) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime((time_t *) &s.st_mtime);\n}\n\nint set_extra_field(z, z_utim)\n        struct zlist far *z;\n        iztimes *z_utim;\n{\n#ifdef USE_EF_UT_TIME\n  char *eb_ptr;\n#endif /* USE_EF_UT_TIME */\n  char *name;\n  extra_block *block;\n\n#define EB_SPARK_LEN    20\n#define EB_SPARK_SIZE (EB_HEADSIZE+EB_SPARK_LEN)\n#ifdef USE_EF_UT_TIME\n# ifdef IZ_CHECK_TZ\n#  define EB_UTTIME_SIZE (zp_tz_is_valid ? EB_HEADSIZE+EB_UT_LEN(1) : 0)\n# else\n#  define EB_UTTIME_SIZE (EB_HEADSIZE+EB_UT_LEN(1))\n# endif\n#else\n#  define EB_UTTIME_SIZE 0\n#endif\n#define EF_SPARK_TOTALSIZE (EB_SPARK_SIZE + EB_UTTIME_SIZE)\n\n  if ((name=(char *)malloc(strlen(z->name)+1))==NULL) {\n    fprintf(stderr,\" set_extra_field: not enough memory for directory name\\n\");\n    return ZE_MEM;\n  }\n\n  strcpy(name,z->name);\n\n  if (name[strlen(name)-1]=='.') {  /* remove the last '.' in directory names */\n    name[strlen(name)-1]=0;\n  }\n\n  z->extra=(char *)malloc(EF_SPARK_TOTALSIZE);\n  if (z->extra==NULL) {\n    fprintf(stderr,\" set_extra_field: not enough memory\\n\");\n    free(name);\n    return ZE_MEM;\n  }\n  z->cextra = z->extra;\n  z->cext = z->ext = EF_SPARK_TOTALSIZE;\n\n  block=(extra_block *)z->extra;\n  block->ID=SPARKID;\n  block->size=EB_SPARK_LEN;\n  block->ID_2=SPARKID_2;\n  block->zero=0;\n\n  if (SWI_OS_File_5(name,NULL,&block->loadaddr,&block->execaddr,\n                    NULL,&block->attr) != NULL) {\n    fprintf(stderr,\" OS error while set_extra_field of %s\\n\",name);\n  }\n\n  free(name);\n\n#ifdef USE_EF_UT_TIME\n# ifdef IZ_CHECK_TZ\n  if (zp_tz_is_valid) {\n# endif\n    eb_ptr = z->extra + EB_SPARK_SIZE;\n\n    eb_ptr[0]  = 'U';\n    eb_ptr[1]  = 'T';\n    eb_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n    eb_ptr[3]  = 0;\n    eb_ptr[4]  = EB_UT_FL_MTIME;\n    eb_ptr[5]  = (char)(z_utim->mtime);\n    eb_ptr[6]  = (char)(z_utim->mtime >> 8);\n    eb_ptr[7]  = (char)(z_utim->mtime >> 16);\n    eb_ptr[8]  = (char)(z_utim->mtime >> 24);\n# ifdef IZ_CHECK_TZ\n  }\n# endif\n#endif /* USE_EF_UT_TIME */\n\n  return ZE_OK;\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n\n    printf(CompiledWith,\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  ifdef __CC_NORCROFT\n      \"Norcroft \", \"cc\",\n#  else\n      \"cc\", \"\",\n#  endif\n#endif\n\n      \"RISC OS\",\n\n      \" (Acorn Computers Ltd)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/match.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; match.s for ARM by Sergio Monesi.\n\nr0 RN 0\nr1 RN 1\nr2 RN 2\nr3 RN 3\nr4 RN 4\nr5 RN 5\nr6 RN 6\nr7 RN 7\nr8 RN 8\nr9 RN 9\nsl RN 10\nfp RN 11\nip RN 12\nsp RN 13\nlr RN 14\npc RN 15\n\nMAX_DIST   EQU  32506\nWMASK      EQU  32767\nMAX_MATCH  EQU  258\n\n                AREA    |C$$code|, CODE, READONLY\n\n\n; r1 = chain_lenght\n; r2 = scan\n; r3 = match\n; r4 = len (tmp)\n; r5 = best_len\n; r6 = limit\n; r7 = strend\n; r8 = scan_end1\n; r9 = scan_end\n; lr = window\n; fp = prev\n\n|__max_chain_length|\n        IMPORT  max_chain_length\n        DCD     max_chain_length\n|__window|\n        IMPORT  window\n        DCD     window\n|__prev|\n        IMPORT  prev\n        DCD     prev\n|__prev_length|\n        IMPORT  prev_length\n        DCD     prev_length\n|__strstart|\n        IMPORT  strstart\n        DCD     strstart\n|__good_match|\n        IMPORT  good_match\n        DCD     good_match\n|__nice_match|\n        IMPORT  nice_match\n        DCD     nice_match\n|__match_start|\n        IMPORT  match_start\n        DCD     match_start\n\n        DCB     \"longest_match\"\n        DCB     &00,&00,&00\n        DCD     &ff000010\n\n        EXPORT  longest_match\nlongest_match\n        STMFD   sp!, {r4-r9,fp,lr}\n\n        LDR     fp, [pc, #|__prev|-.-8]\n\n        LDR     r1, [pc, #|__max_chain_length|-.-8]\n        LDR     r1, [r1]\n        LDR     lr, [pc, #|__window|-.-8]\n\n        LDR     ip, [pc, #|__strstart|-.-8]\n        LDR     ip, [ip]\n        ADD     r2, lr, ip\n        LDR     r5, [pc, #|__prev_length|-.-8]\n        LDR     r5, [r5]\n        SUBS    ip, ip, #MAX_DIST-250       ; if r6 > MAX_DIST\n        SUBCSS  r6, ip, #250                ; r6 = r6 - MAXDIST\n        MOVLS   r6, #0                      ; else r6 = 0\n\n        ADD     r7, r2, #MAX_MATCH-256\n        ADD     r7, r7, #256                ; r7 = r2 + MAX_MATCH (=258);\n\n        SUB     ip, r5, #1\n        LDRB    r8, [r2, ip]\n        LDRB    r9, [r2, r5]\n\n        LDR     ip, [pc, #|__good_match|-.-8]\n        LDR     ip, [ip]\n        CMP     r5, ip\n        MOVCS   r1, r1, LSR #2\n\ncycle\n        ADD     r3, lr, r0\n\n        LDRB    ip, [r3, r5]\n        CMP     ip, r9\n        BNE     cycle_end\n\n        SUB     ip, r5, #1\n        LDRB    ip, [r3, ip]\n        CMP     ip, r8\n        BNE     cycle_end\n\n        LDRB    ip, [r2]\n        LDRB    r4, [r3]\n        CMP     ip, r4\n        BNE     cycle_end\n\n        LDRB    ip, [r3, #1]\n        LDRB    r4, [r2, #1]\n        CMP     ip, r4\n        BNE     cycle_end\n\n        ADD     r2, r2, #2\n        ADD     r3, r3, #2\n\ninn_cycle\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        LDRB    ip, [r2, #1]!\n        LDRB    r4, [r3, #1]!\n        CMP     ip, r4\n        BNE     exit_inn_cycle\n\n        CMP     r2, r7\n        BCC     inn_cycle\n\nexit_inn_cycle\n        SUB     r4, r2, r7               ; len = MAX_MATCH - (int)(strend - scan);\n        ADD     r4, r4, #MAX_MATCH-256\n        ADD     r4, r4, #256\n\n        SUB     r2, r2, r4               ; scan = strend - MAX_MATCH\n\n        CMP     r4, r5                   ; if (len > best_len) {\n        BLE     cycle_end\n\n        LDR     ip, [pc, #|__match_start|-.-8]  ; match_start = cur_match;\n        STR     r0, [ip]\n        MOV     r5, r4                          ; best_len = len;\n\n        LDR     ip, [pc, #|__nice_match|-.-8]   ; if (len >= nice_match)\n        LDR     ip, [ip]\n        CMP     r4, ip\n        BGE     exit_match                      ;   break;\n\n        SUB     ip, r5, #1                      ; scan_end1  = scan[best_len-1];\n        LDRB    r8, [r2, ip]\n        LDRB    r9, [r2, r5]                    ; scan_end   = scan[best_len];\n\ncycle_end\n        MOV     ip, r0, LSL #17          ; cur_match & WMASK\n        MOV     ip, ip, LSR #17\n\n        LDR     r0, [fp, ip, ASL #1]     ; cur_match = prev[cur_match & WMASK]\n        MOV     r0, r0, ASL #16\n        MOV     r0, r0, LSR #16\n\n        CMP     r0, r6                  ; cur_match > limit\n        BLS     exit_match\n        SUBS    r1, r1, #1              ; --chain_length\n        BNE     cycle                   ; chain_length != 0\n\nexit_match\n        MOV     r0, r5\n\n        LDMFD   sp!, {r4-r9,fp,pc}^\n\n        END\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include \"riscos.h\"\n\n#define RISCOS\n#define NO_SYMLINKS\n#define NO_FCNTL_H\n#define NO_UNISTD_H\n#define NO_MKTEMP\n\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#define isatty(a) 1\n#define fseek(f,o,t) riscos_fseek((f),(o),(t))\n\n#define localtime riscos_localtime\n#define gmtime riscos_gmtime\n\n#ifdef ZCRYPT_INTERNAL\n#  define ZCR_SEED2     (unsigned)3141592654L   /* use PI as seed pattern */\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/riscos.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* riscos.c */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"zip.h\"\n#include \"riscos.h\"\n\n#define MAXEXT 256\n\n/* External globals */\nextern int scanimage;\n\n/* Local globals (!?!?) */\nchar *exts2swap = NULL; /* Extensions to swap (actually, directory names) */\n\nint stat(char *filename,struct stat *res)\n{\n int attr;              /* object attributes */\n unsigned int load;     /* load address */\n unsigned int exec;     /* exec address */\n int type;              /* type: 0 not found, 1 file, 2 dir, 3 image */\n\n if (!res)\n   return -1;\n\n if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL)\n   return -1;\n\n if (type==0)\n   return -1;\n\n res->st_dev=0;\n res->st_ino=0;\n res->st_nlink=0;\n res->st_uid=1;\n res->st_gid=1;\n res->st_rdev=0;\n res->st_blksize=1024;\n\n res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) |\n                ((attr & 0020) >> 2) | ((attr & 0040) >> 4);\n\n switch (type) {\n   case 1:                        /* File */\n    res->st_mode |= S_IFREG;\n    break;\n   case 2:                        /* Directory */\n    res->st_mode |= S_IFDIR | 0700;\n    break;\n   case 3:                        /* Image file */\n    if (scanimage)\n      res->st_mode |= S_IFDIR | 0700;\n    else\n      res->st_mode |= S_IFREG;\n    break;\n }\n\n if ((((unsigned int) load) >> 20) == 0xfff) {     /* date stamped file */\n   unsigned int t1, t2, tc;\n\n   t1 = (unsigned int) (exec);\n   t2 = (unsigned int) (load & 0xff);\n\n   tc = 0x6e996a00U;\n   if (t1 < tc)\n     t2--;\n   t1 -= tc;\n   t2 -= 0x33;          /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */\n\n   t1 = (t1 / 100) + (t2 * 42949673U);  /* 0x100000000 / 100 = 42949672.96 */\n   t1 -= (t2 / 25);             /* compensate for .04 error */\n\n   res->st_atime = res->st_mtime = res->st_ctime = t1;\n }\n else\n   res->st_atime = res->st_mtime = res->st_ctime = 0;\n\n return 0;\n}\n\n#ifndef SFX\n\nDIR *opendir(char *dirname)\n{\n DIR *thisdir;\n int type;\n int attr;\n os_error *er;\n\n thisdir=(DIR *)malloc(sizeof(DIR));\n if (thisdir==NULL)\n   return NULL;\n\n thisdir->dirname=(char *)malloc(strlen(dirname)+1);\n if (thisdir->dirname==NULL) {\n   free(thisdir);\n   return NULL;\n }\n\n strcpy(thisdir->dirname,dirname);\n if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.')\n   thisdir->dirname[strlen(thisdir->dirname)-1]=0;\n\n if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL ||\n     type<=1 || (type==3 && !scanimage))\n {\n   free(thisdir->dirname);\n   free(thisdir);\n   return NULL;\n }\n\n thisdir->buf=malloc(DIR_BUFSIZE);\n if (thisdir->buf==NULL) {\n   free(thisdir->dirname);\n   free(thisdir);\n   return NULL;\n }\n\n thisdir->size=DIR_BUFSIZE;\n thisdir->offset=0;\n thisdir->read=0;\n\n return thisdir;\n}\n\nstruct dirent *readdir(DIR *d)\n{\n static struct dirent dent;\n\n if (d->read==0) {    /* no more objects read in the buffer */\n   if (d->offset==-1) {    /* no more objects to read */\n     return NULL;\n   }\n\n   d->read=255;\n   if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL)\n     return NULL;\n\n   if (d->read==0) {\n     d->offset=-1;\n     return NULL;\n   }\n   d->read--;\n   d->act=(char *)d->buf;\n }\n else {     /* some object is ready in buffer */\n   d->read--;\n   d->act=(char *)(d->act+strlen(d->act)+1);\n }\n\n strcpy(dent.d_name,d->act);\n dent.d_namlen=strlen(dent.d_name);\n\n return &dent;\n}\n\nvoid closedir(DIR *d)\n{\n if (d->buf!=NULL)\n   free(d->buf);\n if (d->dirname!=NULL)\n   free(d->dirname);\n free(d);\n}\n\nint unlink(f)\nchar *f;                /* file to delete */\n/* Delete the file *f, returning non-zero on failure. */\n{\n os_error *er;\n char canon[256];\n int size=255;\n\n er=SWI_OS_FSControl_37(f,canon,&size);\n if (er==NULL) {\n   er=SWI_OS_FSControl_27(canon,0x100);\n }\n else {\n   er=SWI_OS_FSControl_27(f,0x100);\n }\n return (int)er;\n}\n\nint deletedir(char *d)\n{\n int objtype;\n char *s;\n int len;\n os_error *er;\n\n len = strlen(d);\n if ((s = malloc(len + 1)) == NULL)\n   return -1;\n\n strcpy(s,d);\n if (s[len-1]=='.')\n   s[len-1]=0;\n\n if (er=SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL),er!=NULL) {\n   free(s);\n   return -1;\n }\n if (objtype<2 || (!scanimage && objtype==3)) {\n   /* this is a file or it doesn't exist */\n   free(s);\n   return -1;\n }\n\n if (er=SWI_OS_File_6(s),er!=NULL) {\n   /* maybe this is a problem with the DDEUtils module, try to canonicalise the path */\n   char canon[256];\n   int size=255;\n\n   if (er=SWI_OS_FSControl_37(s,canon,&size),er!=NULL) {\n     free(s);\n     return -1;\n   }\n   if (er=SWI_OS_File_6(canon),er!=NULL) {\n     free(s);\n     return -1;\n   }\n }\n free(s);\n return 0;\n}\n\n#endif /* !SFX */\n\nint chmod(char *file, int mode)\n{\n/*************** NOT YET IMPLEMENTED!!!!!! ******************/\n/* I don't know if this will be needed or not... */\n file=file;\n mode=mode;\n return 0;\n}\n\nvoid setfiletype(char *fname,int ftype)\n{\n char str[256];\n sprintf(str,\"SetType %s &%3.3X\",fname,ftype);\n SWI_OS_CLI(str);\n}\n\nvoid getRISCOSexts(char *envstr)\n{\n char *envptr;                               /* value returned by getenv */\n\n envptr = getenv(envstr);\n if (envptr == NULL || *envptr == 0) return;\n\n exts2swap=malloc(1+strlen(envptr));\n if (exts2swap == NULL)\n   return;\n\n strcpy(exts2swap, envptr);\n}\n\nint checkext(char *suff)\n{\n register char *extptr=exts2swap;\n register char *suffptr;\n register int e,s;\n\n if (extptr != NULL) while(*extptr) {\n   suffptr=suff;\n   e=*extptr; s=*suffptr;\n   while (e && e!=':' && s && s!='.' && s!='/' && e==s) {\n     e=*++extptr; s=*++suffptr;\n   }\n   if (e==':') e=0;\n   if (s=='.' || s=='/') s=0;\n   if (!e && !s) {\n     return 1;\n   }\n   while(*extptr!=':' && *extptr!='\\0')    /* skip to next extension */\n     extptr++;\n   if (*extptr!='\\0')\n     extptr++;\n }\n return 0;\n}\n\nint swapext(char *name, char *exptr)\n{\n char *ext;\n char *p1=exptr;\n char *p2;\n int extchar=*exptr;\n unsigned int i=0;\n\n while(*++p1 && *p1!='.' && *p1!='/')\n   ;\n ext=malloc(i=p1-exptr);\n if (!ext)\n   return 1;\n memcpy(ext, exptr+1, i);\n p2=exptr-1;\n p1=exptr+i-1;\n while(p2 >= name)\n   *p1--=*p2--;\n strcpy(name,ext);\n *p1=(extchar=='/'?'.':'/');\n free(ext);\n return 0;\n}\n\nvoid remove_prefix(void)\n{\n SWI_DDEUtils_Prefix(NULL);\n}\n\nvoid set_prefix(void)\n{\n char *pref;\n int size=0;\n\n if (SWI_OS_FSControl_37(\"@\",pref,&size)!=NULL)\n   return;\n\n size=1-size;\n\n if (pref=malloc(size),pref!=NULL) {\n   if (SWI_OS_FSControl_37(\"@\",pref,&size)!=NULL) {\n     free(pref);\n     return;\n   }\n\n   if (SWI_DDEUtils_Prefix(pref)==NULL) {\n     atexit(remove_prefix);\n   }\n\n   free(pref);\n }\n}\n\n#ifdef localtime\n#  undef localtime\n#endif\n\n#ifdef gmtime\n#  undef gmtime\n#endif\n\n/* Acorn's implementation of localtime() and gmtime()\n * doesn't consider the timezone offset, so we have to\n * add it before calling the library functions\n */\n\nstruct tm *riscos_localtime(const time_t *timer)\n{\n time_t localt=*timer;\n\n localt+=SWI_Read_Timezone()/100;\n\n return localtime(&localt);\n}\n\nstruct tm *riscos_gmtime(const time_t *timer)\n{\n time_t localt=*timer;\n\n localt+=SWI_Read_Timezone()/100;\n\n return gmtime(&localt);\n}\n\n\nint riscos_fseek(FILE *fd, long offset, int whence)\n{\n  int ret;\n  switch (whence)\n  {\n    case SEEK_END:\n      ret = (fseek) (fd, 0, SEEK_END);\n      if (ret)\n        return ret;\n      /* fall through */\n    case SEEK_CUR:\n      offset += ftell (fd);\n      /* fall through */\n    default: /* SEEK_SET */\n      return (fseek) (fd, offset < 0 ? 0 : offset, SEEK_SET);\n  }\n}\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/riscos.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* riscos.h */\n\n#ifndef __riscos_h\n#define __riscos_h\n\n#include <time.h>\n#include <stdio.h>\n\ntypedef struct {\n  int errnum;\n  char errmess[252];\n} os_error;\n\n#ifndef __swiven_h\n#  include \"swiven.h\"\n#endif\n\n#define MAXPATHLEN 256\n#define MAXFILENAMELEN 64  /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */\n#define DIR_BUFSIZE 1024   /* this should be enough to read a whole E-Format directory */\n\nstruct stat {\n  unsigned int st_dev;\n  int st_ino;\n  unsigned int st_mode;\n  int st_nlink;\n  unsigned short st_uid;\n  unsigned short st_gid;\n  unsigned int st_rdev;\n  unsigned int st_size;\n  unsigned int st_blksize;\n  time_t st_atime;\n  time_t st_mtime;\n  time_t st_ctime;\n};\n\ntypedef struct {\n  char *dirname;\n  void *buf;\n  int size;\n  char *act;\n  int offset;\n  int read;\n} DIR;\n\n#define dstrm DIR\n\nstruct dirent {\n  unsigned int d_off;          /* offset of next disk directory entry */\n  int d_fileno;                /* file number of entry */\n  size_t d_reclen;             /* length of this record */\n  size_t d_namlen;             /* length of d_name */\n  char d_name[MAXFILENAMELEN]; /* name */\n};\n\ntypedef struct {\n  unsigned int load_addr;\n  unsigned int exec_addr;\n  int lenght;\n  int attrib;\n  int objtype;\n  char name[13];\n} riscos_direntry;\n\n#define SPARKID   0x4341        /* = \"AC\" */\n#define SPARKID_2 0x30435241    /* = \"ARC0\" */\n\ntypedef struct {\n  short         ID;\n  short         size;\n  int           ID_2;\n  unsigned int  loadaddr;\n  unsigned int  execaddr;\n  int           attr;\n  int           zero;\n} extra_block;\n\n\n#define S_IFMT  0770000\n\n#define S_IFDIR 0040000\n#define S_IFREG 0100000  /* 0200000 in UnixLib !?!?!?!? */\n\n#ifndef S_IEXEC\n#  define S_IEXEC  0000100\n#  define S_IWRITE 0000200\n#  define S_IREAD  0000400\n#endif\n\nextern char *exts2swap; /* Extensions to swap */\n\nint stat(char *filename,struct stat *res);\nDIR *opendir(char *dirname);\nstruct dirent *readdir(DIR *d);\nchar *readd(DIR *d);\nvoid closedir(DIR *d);\nint unlink(char *f);\nint chmod(char *file, int mode);\nvoid setfiletype(char *fname,int ftype);\nvoid getRISCOSexts(char *envstr);\nint checkext(char *suff);\nint swapext(char *name, char *exptr);\nvoid remove_prefix(void);\nvoid set_prefix(void);\nstruct tm *riscos_localtime(const time_t *timer);\nstruct tm *riscos_gmtime(const time_t *timer);\n\nint riscos_fseek(FILE *fd, long offset, int whence);\n/* work around broken assumption that fseek() is OK with -ve file offsets */\n\n#endif /* !__riscos_h */\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/sendbits.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; sendbits.s for ARM by Sergio Monesi and Darren Salt.\n\nr0      RN      0\nr1      RN      1\nr2      RN      2\nr3      RN      3\nr4      RN      4\nr5      RN      5\nr6      RN      6\nr7      RN      7\nr8      RN      8\nr9      RN      9\nsl      RN      10\nfp      RN      11\nip      RN      12\nsp      RN      13\nlr      RN      14\npc      RN      15\n\n        AREA    |Asm$$Code|, CODE, READONLY\n\n        =       \"send_bits\",0\n        ALIGN\n        &       &FF00000C\n\n        IMPORT  __rt_stkovf_split_small\n        IMPORT  flush_outbuf\n\n        IMPORT  bi_valid\n        IMPORT  bi_buf\n        IMPORT  out_size\n        IMPORT  out_offset\n        IMPORT  out_buf\n\n        EXPORT  send_bits\nsend_bits\n        MOV     ip,sp\n        STMDB   sp!,{r4,r5,fp,ip,lr,pc}\n        SUB     fp,ip,#4\n        LDR     r5,=bi_buf\n        LDR     r3,=bi_valid\n        LDR     r4,[r5]\n        LDR     r2,[r3]\n        ORR     r4,r4,r0,LSL r2 ; |= value<<bi_valid\n        ADD     r2,r2,r1        ; += length\n        CMP     r2,#&10\n        STRLE   r2,[r3]         ; short? store & return\n        STRLE   r4,[r5]\n        LDMLEDB fp,{r4,r5,fp,sp,pc}^\n\n        SUB     r2,r2,#&10      ; adjust bi_valid, bi_buf\n        MOV     ip,r4,LSR #16   ;  (done early, keeping the old bi_buf\n        STR     r2,[r3]         ;  in R4 for later storage)\n        STR     ip,[r5]\n\n        LDR     r0,=out_size\n        LDR     r1,=out_offset\n        LDR     r0,[r0]\n        LDR     r2,[r1]\n        SUB     r0,r0,#1\n        CMP     r2,r0           ; if out_offset >= out_size-1\n        LDRHS   r0,=out_buf\n        LDRHS   r0,[r0]\n        BLHS    flush_outbuf    ; then flush the buffer\n        LDR     r0,=out_buf\n        LDR     r1,=out_offset\n        LDR     r0,[r0]\n        LDR     r2,[r1]\n        MOV     r5,r4,LSR #8\n        STRB    r4,[r0,r2]!     ; store 'old' bi_buf\n        STRB    r5,[r0,#1]\n        ADD     r2,r2,#2\n        STR     r2,[r1]\n\n        LDMDB   fp,{r4,r5,fp,sp,pc}^\n\n\nptr_bi          &       bi_valid\n                &       bi_buf\n\n\n        =       \"bi_reverse\",0\n        ALIGN\n        &       &FF00000C\n\n        EXPORT  bi_reverse\nbi_reverse\n        MOV     r2,#0\nloop    MOVS    r0,r0,LSR #1\n        ADCS    r2,r2,r2\n        SUBS    r1,r1,#1\n        BNE     loop\n        MOV     r0,r2\n        MOVS    pc,lr\n\n\n        END\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/swiven.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/* swiven.h */\n\n#ifndef __swiven_h\n#define __swiven_h\n\nos_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);\n/* copy */\n\nos_error *SWI_OS_FSControl_27(char *filename, int actionmask);\n/* wipe */\n\nos_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,\n                        int *offset, int size, char *match);\n/* read dir */\n\nos_error *SWI_OS_File_1(char *filename, unsigned int loadaddr,\n                        unsigned int execaddr, int attrib);\n/* write file attributes */\n\nos_error *SWI_OS_File_5(char *filename, int *objtype, unsigned int *loadaddr,\n                        unsigned int *execaddr, int *length, int *attrib);\n/* read file info */\n\nos_error *SWI_OS_File_6(char *filename);\n/* delete */\n\nos_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);\n/* create an empty file */\n\nos_error *SWI_OS_CLI(char *cmd);\n/* execute a command */\n\nint SWI_OS_ReadC(void);\n/* get a key from the keyboard buffer */\n\nos_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);\n/* reads an OS varibale */\n\nos_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);\n/* reads the path of a specified directory */\n\nos_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);\n/* canonicalise path */\n\nos_error *SWI_DDEUtils_Prefix(char *dir);\n/* sets the 'prefix' directory */\n\nint SWI_Read_Timezone(void);\n/* returns the timezone offset (centiseconds) */\n\n#endif /* !__swiven_h */\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/swiven.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; SWI veneers used by Zip/Unzip\n;\n\nr0              RN      0\nr1              RN      1\nr2              RN      2\nr3              RN      3\nr4              RN      4\nr5              RN      5\nr6              RN      6\nr7              RN      7\nr8              RN      8\nr9              RN      9\nr10             RN      10\nr11             RN      11\nr12             RN      12\nsp              RN      13\nlr              RN      14\npc              RN      15\n\nsl              RN      10\nfp              RN      11\nip              RN      12\n\n\nXOS_Bit                         EQU &020000\n\nOS_GBPB                         EQU &00000C\nOS_File                         EQU &000008\nOS_FSControl                    EQU &000029\nOS_CLI                          EQU &000005\nOS_ReadC                        EQU &000004\nOS_ReadVarVal                   EQU &000023\nDDEUtils_Prefix                 EQU &042580\nTerritory_ReadCurrentTimeZone   EQU &043048\n\n        MACRO\n        STARTCODE $name\n        EXPORT $name\n$name\n        MEND\n\n\n                AREA    |C$$code|, CODE, READONLY\n\n; os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);\n\n        STARTCODE SWI_OS_FSControl_26\n\n        MOV     ip, lr\n\n        MOV     r3, r2\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #26\n\n        SWI     OS_FSControl + XOS_Bit\n\n        MOVVC   r0, #0\n\n        MOVS    pc, ip\n\n\n; os_error *SWI_OS_FSControl_27(char *filename, int actionmask);\n\n        STARTCODE SWI_OS_FSControl_27\n\n        MOV     ip, lr\n\n        MOV     r3, r1\n        MOV     r1, r0\n        MOV     r0, #27\n\n        SWI     OS_FSControl + XOS_Bit\n\n        MOVVC   r0, #0\n\n        MOVS    pc, ip\n\n\n; os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,\n;                         int *offset, int size, char *match);\n\n        STARTCODE SWI_OS_GBPB_9\n\n        MOV     ip, sp\n        STMFD   sp!, {r2-r6,lr}\n        LDMIA   ip, {r5,r6}\n        LDR     r4, [r3]\n        LDR     r3, [r2]\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #9\n        SWI     OS_GBPB + XOS_Bit\n        LDMVSFD sp!, {r2-r6,pc}^\n        MOV     r0, #0\n        LDMFD   sp, {r5,r6}\n        STR     r3, [r5]\n        STR     r4, [r6]\n        LDMFD   sp!, {r2-r6,pc}^\n\n\n; os_error *SWI_OS_File_1(char *filename, int loadaddr, int execaddr, int attrib);\n\n        STARTCODE SWI_OS_File_1\n\n        STMFD   sp!, {r5,lr}\n        MOV     r5, r3\n        MOV     r3, r2\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #1\n        SWI     OS_File + XOS_Bit\n        MOVVC   r0, #0\n        LDMFD   sp!, {r5,pc}^\n\n\n\n; os_error *SWI_OS_File_5(char *filename, int *objtype, int *loadaddr,\n;                         int *execaddr, int *length, int *attrib);\n\n        STARTCODE SWI_OS_File_5\n\n        STMFD   sp!, {r1-r5,lr}\n        MOV     r1, r0\n        MOV     r0, #5\n        SWI     OS_File + XOS_Bit\n        LDMVSFD sp!, {r1-r5,pc}^\n        LDR     lr, [sp]\n        TEQ     lr, #0\n        STRNE   r0, [lr]\n        LDR     lr, [sp, #4]\n        TEQ     lr ,#0\n        STRNE   r2, [lr]\n        LDR     lr, [sp, #8]\n        TEQ     lr, #0\n        STRNE   r3, [lr]\n        LDR     lr, [sp ,#24]\n        TEQ     lr, #0\n        STRNE   r4, [lr]\n        LDR     lr, [sp ,#28]\n        TEQ     lr, #0\n        STRNE   r5, [lr]\n        MOV     r0, #0\n        LDMFD   sp!, {r1-r5,pc}^\n\n\n; os_error *SWI_OS_File_6(char *filename);\n\n        STARTCODE SWI_OS_File_6\n\n        STMFD   sp!, {r4-r5,lr}\n        MOV     r1, r0\n        MOV     r0, #6\n        SWI     OS_File + XOS_Bit\n        MOVVC   r0, #0\n        LDMFD   sp!, {r4-r5,pc}^\n\n\n; os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);\n\n        STARTCODE SWI_OS_File_7\n\n        STMFD   sp!, {r4-r5,lr}\n        MOV     r5, r3\n        MOV     r4, #0\n        MOV     r3, r2\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #7\n        SWI     OS_File + XOS_Bit\n        MOVVC   r0, #0\n        LDMFD   sp!, {r4-r5,pc}^\n\n\n; os_error *SWI_OS_CLI(char *cmd);\n\n        STARTCODE SWI_OS_CLI\n\n        MOV     ip, lr\n        SWI     OS_CLI + XOS_Bit\n        MOVVC   r0, #0\n        MOVS    pc, ip\n\n\n; int SWI_OS_ReadC(void);\n\n        STARTCODE SWI_OS_ReadC\n\n        MOV     ip, lr\n        SWI     OS_ReadC + XOS_Bit\n        MOVS    pc, ip\n\n\n; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);\n\n        STARTCODE SWI_OS_ReadVarVal\n\n        STMFD   sp!, {r4,lr}\n        MOV     ip, r3\n        MOV     r3, #0\n        MOV     r4, #0\n        SWI     OS_ReadVarVal + XOS_Bit\n        LDMVSFD sp!, {r4,pc}^\n        TEQ     ip, #0\n        STRNE   r2, [ip]\n        MOV     r0, #0\n        LDMFD   sp!, {r4,pc}^\n\n\n; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);\n\n        STARTCODE SWI_OS_FSControl_54\n\n        STMFD   sp!, {r3-r6,lr}\n        LDR     r5, [r3]\n        MOV     r3, r2\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #54\n        SWI     OS_FSControl + XOS_Bit\n        LDMVSFD sp!, {r3-r6,pc}^\n        MOV     r0, #0\n        LDMFD   sp!, {r3}\n        STR     r5, [r3]\n        LDMFD   sp!, {r4-r6,pc}^\n\n\n; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);\n\n        STARTCODE SWI_OS_FSControl_37\n\n        STMFD   sp!, {r2,r3-r5,lr}\n        LDR     r5, [r2]\n        MOV     r3, #0\n        MOV     r4, #0\n        MOV     r2, r1\n        MOV     r1, r0\n        MOV     r0, #37\n        SWI     OS_FSControl + XOS_Bit\n        LDMVSFD sp!, {r2,r3-r5,pc}^\n        MOV     r0, #0\n        LDMFD   sp!, {r2}\n        STR     r5, [r2]\n        LDMFD   sp!, {r3-r5,pc}^\n\n\n; os_error *SWI_DDEUtils_Prefix(char *dir);\n\n        STARTCODE SWI_DDEUtils_Prefix\n\n        MOV     ip, lr\n        SWI     DDEUtils_Prefix + XOS_Bit\n        MOVVC   r0, #0\n        MOVS    pc, ip\n\n; int SWI_Read_Timezone(void);\n\n        STARTCODE SWI_Read_Timezone\n\n        MOV     ip, lr\n        SWI     Territory_ReadCurrentTimeZone + XOS_Bit\n        MOVVC   r0, r1\n        MOVVS   r0, #0\n        MOVS    pc, ip\n\n\n        END\n"
  },
  {
    "path": "deps/infozip/zip30/acorn/zipsfx",
    "content": "| zipsfx 0.1\n| Written by Darren Salt\n| Assumes that unzipsfx is on Run$Path (eg. in !Boot.Library)\n| Assumes that IfThere is available as either *command or utility\n\nIf \"%1\" = \"\" Then Error 220 Syntax: zipsfx |<archive> |<SEA>\nIf \"%0\" = \"\" Then Error 220 Syntax: zipsfx |<archive> |<SEA>\nCopy Run:unzipsfx %1 A~C~D~F~L~N~R~S~T~V\nPrint %0 { >> %1 }"
  },
  {
    "path": "deps/infozip/zip30/acorn/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow \"r\"\n#define fbad (NULL)\ntypedef FILE *ftype;\n#define zopen(n,p) fopen(n,p)\n#define zread(f,b,n) fread((b),1,(n),(FILE*)(f))\n#define zclose(f) fclose(f)\n#define zerr(f) (k==(extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/LMKfile",
    "content": "# Makefile for Zip, ZipNote, ZipCloak and ZipSplit, Amiga SAS/C 5.10b\n# See the master Makefile under the top level Zip/Unzip source directory\n# for more information on compiler macros and flags for this version.\n# Last update: Jan 07, 2007\n# -John Bush, <J.Bush@MD-B.Prime.COM>, <JBush@BIX.COM>\n\n\n#######################\n# MACROBE DEFINITIONS #\n#######################\n\n# Compiler and loader debug flags.  Omit comments as req'd.\n# Do not set when building production version.\n# CDBG = -d3\n# LDBG = ADDSYM\n\nDEFINES = -DNO_MKTEMP\nCC = lc\nOPT = -O\nCFLAGS = $(OPT) $(DEFINES) $(CDBG) -v -mat -cuisf -b0 -j85i86i87i100i\n\nLD = blink\nLDSTART = LIB:c.o\nLDFLAGS = LIB LIB:lc.lib+LIB:amiga.lib\n\nTMPFILE = ram:MakeZip.tmp\n\n###############################################\n# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #\n###############################################\n\n# default C rules\n.c.o:\n        $(CC) $(CFLAGS) -o$@ $*.c\n\n# Alternate rules for routines containing entries needed by utilities\n.c.oo:\n        $(CC) $(CFLAGS) -DUTIL -o$*.oo $*.c\n\n# object file macrough lists\n\nHFILES = zip.h ziperr.h tailor.h revision.h crc32.h crypt.h ttyio.h \\\n         amiga/amiga.h amiga/zipup.h amiga/osdep.h\n\nOBJA = zipfile.o zipup.o fileio.o util.o globals.o crc32.o crypt.o \\\n       timezone.o ttyio.o amiga.o amigazip.o filedate.o\nOBJI = deflate.o trees.o\nOBJU = zipfile.oo fileio.oo util.oo globals.o timezone.o \\\n       amiga.o amigazip.oo filedate.o\n\nOBJZ = zip.o $(OBJA) $(OBJI)\n\nOBJN = zipnote.o  $(OBJU)\nOBJC = zipcloak.o $(OBJU) crc32.oo crypt.oo ttyio.o\nOBJS = zipsplit.o $(OBJU)\n\nZIPS = zip zipnote zipcloak zipsplit\n\nall:      Message $(ZIPS)\n\nMessage:\n       -echo \" \"\n       -echo \"WARNING: Lattice 5.x HAS NOT BEEN TESTED WITH THIS ZIP VERSION\"\n       -echo \"Report problems to <zip-bugs@lists.wku.edu>\"\n       -echo \" \"\n\nzip: $(OBJZ) $(HFILES)\n        -echo \"$(OBJZ)\" > $(TMPFILE)\n\t$(LD) TO Zip      FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)\n        -delete $(TMPFILE) Zip.info\n\nzipnote: $(OBJN) $(HFILES)\n        -echo \"$(OBJN)\" > $(TMPFILE)\n\t$(LD) TO ZipNote  FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)\n        -delete $(TMPFILE) ZipNote.info\n\nzipcloak: $(OBJC) $(HFILES)\n        -echo \"$(OBJC)\" > $(TMPFILE)\n\t$(LD) TO ZipCloak FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)\n        -delete $(TMPFILE) ZipCloak.info\n\nzipsplit: $(OBJS) $(HFILES)\n        -echo \"$(OBJS)\" > $(TMPFILE)\n\t$(LD) TO ZipSplit FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)\n        -delete $(TMPFILE) ZipSplit.info\n\nclean:\n       -delete $(OBJZ) all quiet force >nil:\n       -delete $(OBJU) all quiet force >nil:\n       -delete $(OBJA) all quiet force >nil:\n       -delete $(OBJI) all quiet force >nil:\n       -delete $(OBJN) all quiet force >nil:\n       -delete $(OBJC) all quiet force >nil:\n       -delete $(OBJS) all quiet force >nil:\n\nzip.o:      zip.c      $(HFILES)\nzipnote.o:  zipnote.c  $(HFILES)\nzipcloak.o: zipcloak.c $(HFILES)\ncrypt.o:    crypt.c    $(HFILES)\nttyio.o:    ttyio.c    $(HFILES)\nzipsplit.o: zipsplit.c $(HFILES)\ndeflate.o:  deflate.c  $(HFILES)\ntrees.o:    trees.c    $(HFILES)\nzipfile.o:  zipfile.c  $(HFILES)\nzipup.o:    zipup.c    $(HFILES)\nfileio.o:   fileio.c   $(HFILES)\nutil.o:     util.c     $(HFILES)\ntimezone.o: timezone.c $(HFILES) timezone.h\ncrc32.o:    crc32.c    $(HFILES)\ncrctab.o:   crctab.c   $(HFILES)\nglobals.o:  globals.c  $(HFILES)\n\n# Amiga specific objects\namiga.o: amiga/amiga.c $(HFILES)\namigazip.o: amiga/amigazip.c $(HFILES)\n\n# end of Makefile\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/README",
    "content": "the -A option currently does not work for the amiga.\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/amiga.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* OS specific routines for AMIGA platform.\n *\n * John Bush    <John.Bush@east.sun.com>  BIX: jbush\n * Paul Kienitz <kie@pacbell.net>\n *\n * History:\n *\n * Date     DoBee    Comments\n * -------  -------- -----------------------------------------------\n * 21Jan93  JBush    Original coding.\n *                   Incorporated filedate.c (existing routine).\n *\n * 31Jan93  JBush    Made filedate.c include unconditional.\n *\n * 18Jul93  PaulK    Moved Aztec _abort() here from stat.c because we\n *                   can't share the same one between Zip and UnZip.\n *                   Added close_leftover_open_dirs() call to it.\n *\n * 17Apr95  PaulK    Added Amiga internal version string so that\n *                   installer programs can compare the version being\n *                   installed to see if the copy the user already has\n *                   is older or newer.  Added Prestart_Hook to support\n *                   debug tracing in deflate.a.\n *\n *  6May95  PaulK    Added GetComment() for filenote support.\n *\n * 12Nov95  PaulK    Added #define ZIP in front of filedate.c, for\n *                   new options in there; removed declare of set_con()\n *                   since echon() no longer expands to it (or anything).\n *\n * 12Feb96  PaulK    Removed call of echon() entirely.\n *\n * 12Jul97  PaulK    Made both Aztec and SAS define USE_TIME_LIB for filedate.c\n *\n * 26Aug97  PaulK    Added ClearIOErr_exit()\n *\n *  2Jan98  HWalt    Adapted for SAS/C using stat.c replacement functions\n *\n *  6Jun00  PaulK    Removed references to time_lib, since new filedate.c\n *                   supercedes it\n */\n\n#include <exec/memory.h>\n#ifdef AZTEC_C\n#  include <libraries/dos.h>\n#  include <libraries/dosextens.h>\n#  include <clib/exec_protos.h>\n#  include <clib/dos_protos.h>\n#  include <pragmas/exec_lib.h>\n#  include <pragmas/dos_lib.h>\n#else\n#  include <proto/exec.h>\n#  include <proto/dos.h>\n#endif\n#include <stdlib.h>\n#include \"ziperr.h\"\nvoid ziperr(int c, const char *h);\n\n#define ZIP\n#if !defined(UTIL)\n#  define NO_MKTIME\n#endif\n\n#ifdef AZTEC_C\n\n/* ============================================================= */\n/* filedate.c is an external file, since it's shared with UnZip. */\n/* Aztec includes it here, but SAS/C now compiles it separately. */\n#  include \"amiga/filedate.c\"\n\n/* the same applies to stat.c                                    */\n#  include \"amiga/stat.c\"\n\n#  define setenv BOGUS_INCOMPATIBLE_setenv\n#  include <fcntl.h>\n#  undef setenv\n#  ifdef DEBUG\n#    define PRESTART_HOOK\n#  endif\n#endif\n\nextern void close_leftover_open_dirs(void);\n\n\n/* the following handles cleanup when a ^C interrupt happens: */\n\nvoid _abort(void)               /* called when ^C is pressed */\n{\n    close_leftover_open_dirs();\n    ziperr(ZE_ABORT, \"^C\");\n}\n\nvoid ClearIOErr_exit(int e)     /* EXIT is defined as this */\n{\n    if (!e)\n        ((struct Process *) FindTask(NULL))->pr_Result2 = 0;\n    /* we clear IoErr() since we are successful, in a 1.x-compatible way */\n    exit(e);\n}\n\n\n/* Make sure the version number here matches the number in revision.h */\n/* as closely as possible in strict decimal \"#.#\" form:               */\nconst char version_id[] = \"\\0$VER: Zip 2.3 (\"\n#  include \"env:VersionDate\"\n\")\\r\\n\";\n\n/* call this with an arg of NULL to free storage: */\n\nchar *GetComment(char *filename)\n{\n    BPTR lk;\n    static struct FileInfoBlock *fib = NULL;\n\n    if (!filename) {\n        if (fib) FreeMem(fib, sizeof(*fib));\n        fib = NULL;\n        return NULL;\n    }\n    if (!fib) {\n        if (!(fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)))\n            ziperr(ZE_MEM, \"was checking filenotes\");\n    }\n    if (!(lk = Lock(filename, ACCESS_READ)))\n        return NULL;\n    if (!Examine(lk, fib))\n        fib->fib_Comment[0] = '\\0';\n    UnLock(lk);\n    return fib->fib_Comment[0] ? &fib->fib_Comment[0] : NULL;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/amiga.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef __amiga_amiga_h\n#define __amiga_amiga_h\n\n/* amiga.h\n *\n * Globular definitions that affect all of AmigaDom.\n *\n * Originally included in unzip.h, extracted for simplicity and eeze of\n * maintenance by John Bush.\n *\n * This version is for use with Zip.  It is not globally included, but used\n * only by functions in amiga/amigazip.c.  Much material that was needed for\n * UnZip is absent here.\n *\n */\n\n#include <fcntl.h>          /* O_BINARY for open() w/o CR/LF translation */\n#include \"amiga/z-stat.h\"  /* substitute for <stat.h> and <dire(c|n)t.h> */\n#define direct dirent\n\n#ifndef MODERN\n#  define MODERN\n#endif\n\n#ifdef AZTEC_C                          /* Manx Aztec C, 5.0 or newer only */\n#  include <clib/dos_protos.h>\n#  include <pragmas/dos_lib.h>          /* do inline dos.library calls */\n#  define O_BINARY 0\n#endif /* AZTEC_C */\n\n\n#ifdef __SASC\n#  include <dirent.h>\n#  include <dos.h>\n#  define disk_not_mounted 0\n#  if ( (!defined(O_BINARY)) && defined(O_RAW))\n#    define O_BINARY O_RAW\n#  endif\n#endif /* SASC */\n\n\n/* Funkshine Prough Toe Taipes */\n\nLONG FileDate (char *, time_t[]);\n\n#endif /* __amiga_amiga_h */\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/amigazip.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include \"zip.h\"\n#include \"amiga/amiga.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#define utime FileDate\n\n#define PAD 0\n#define PATH_END '/'\n\n/* Local globals (kinda like \"military intelligence\" or \"broadcast quality\") */\n\nextern char *label;             /* still declared in fileio.c */\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\nlocal int wild_recurse OF((char *, char *));\n\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\n\n/* What we have here is a mostly-generic routine using opendir()/readd() and */\n/* isshexp()/MATCH() to find all the files matching a multi-part filespec  */\n/* using the portable pattern syntax.  It shouldn't take too much fiddling */\n/* to make it usable for any other platform that has directory hierarchies */\n/* but no shell-level pattern matching.  It works for patterns throughout  */\n/* the pathname, such as \"foo:*.?/source/x*.[ch]\".                         */\n\n#define ONENAMELEN 30\n/* the length of one filename component on the Amiga */\n\n/* whole is a pathname with wildcards, wildtail points somewhere in the  */\n/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */\n\nlocal int wild_recurse(whole, wildtail) char *whole; char *wildtail;\n{\n    DIR *dir;\n    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;\n    ush newlen, amatch = 0;\n    BPTR lok;\n    int e = ZE_MISS;\n\n    if (!isshexp(wildtail))\n        if (lok = Lock(whole, ACCESS_READ)) {       /* p exists? */\n            UnLock(lok);\n            return procname(whole, 0);\n        } else\n            return ZE_MISS;                     /* woops, no wildcards! */\n\n    /* back up thru path components till existing dir found */\n    do {\n        name = wildtail + strlen(wildtail) - 1;\n        for (;;)\n            if (name-- <= wildtail || *name == PATH_END) {\n                subwild = name + 1;\n                plug2 = *subwild;\n                *subwild = 0;\n                break;\n            }\n        if (glue)\n            *glue = plug;\n        glue = subwild;\n        plug = plug2;\n        dir = opendir(whole);\n    } while (!dir && !disk_not_mounted && subwild > wildtail);\n    wildtail = subwild;                 /* skip past non-wild components */\n\n    if ((subwild = strchr(wildtail + 1, PATH_END)) != NULL) {\n        /* this \"+ 1\" dodges the   ^^^ hole left by *glue == 0 */\n        *(subwild++) = 0;               /* wildtail = one component pattern */\n        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);\n    } else\n        newlen = strlen(whole) + (ONENAMELEN + 1);\n    if (!dir || !(newwhole = malloc(newlen))) {\n        if (glue)\n            *glue = plug;\n\n        e = dir ? ZE_MEM : ZE_MISS;\n        goto ohforgetit;\n    }\n    strcpy(newwhole, whole);\n    newlen = strlen(newwhole);\n    if (glue)\n        *glue = plug;                           /* repair damage to whole */\n    if (!isshexp(wildtail)) {\n        e = ZE_MISS;                            /* non-wild name not found */\n        goto ohforgetit;\n    }\n\n    while (name = readd(dir)) {\n        if (MATCH(wildtail, name, 0)) {\n            strcpy(newwhole + newlen, name);\n            if (subwild) {\n                name = newwhole + strlen(newwhole);\n                *(name++) = PATH_END;\n                strcpy(name, subwild);\n                e = wild_recurse(newwhole, name);\n            } else\n                e = procname(newwhole, 0);\n            newwhole[newlen] = 0;\n            if (e == ZE_OK)\n                amatch = 1;\n            else if (e != ZE_MISS)\n                break;\n        }\n    }\n\n  ohforgetit:\n    if (dir) closedir(dir);\n    if (subwild) *--subwild = PATH_END;\n    if (newwhole) free(newwhole);\n    if (e == ZE_MISS && amatch)\n        e = ZE_OK;\n    return e;\n}\n\nint wild(p) char *p;\n{\n    char *use;\n\n    /* special handling of stdin request */\n    if (strcmp(p, \"-\") == 0)    /* if compressing stdin */\n        return newname(p, 0, 0);\n\n    /* wild_recurse() can't handle colons in wildcard part: */\n    if (use = strchr(p, ':')) {\n        if (strchr(++use, ':'))\n            return ZE_PARMS;\n    } else\n        use = p;\n\n    return wild_recurse(p, use);\n}\n\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    strcpy(p, n);\n    a = p + strlen(p);\n    if (*p && a[-1] != '/' && a[-1] != ':')\n      strcpy(a, \"/\");\n    if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n      free((zvoid *)p);\n      return m;\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n        {\n          closedir(d);\n          free((zvoid *)p);\n          return ZE_MEM;\n        }\n        strcat(strcpy(a, p), e);\n        if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n        {\n          if (m == ZE_MISS)\n            zipwarn(\"name not matched: \", a);\n          else\n            ziperr(m, a);\n        }\n        free((zvoid *)a);\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  dosflag = dosify;     /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  if ((t = strrchr(x, ':')) != NULL)    /* reject \":\" */\n    t++;\n  else\n    t = x;\n  {                                     /* reject \"//\" */\n    char *tt = t;\n    while (tt = strchr(tt, '/'))\n      while (*++tt == '/')\n        t = tt;\n  }\n  while (*t == '/')             /* reject leading \"/\" on what's left */\n    t++;\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n  strcpy(x, n);\n  return x;\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  time_t u[2];          /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u */\n  u[0] = u[1] = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0)\n      error(\"fstat(stdin)\");\n  } else if (SSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFDIR) != 0) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n   return unix2dostime(&s.st_mtime);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n#ifdef USE_EF_UT_TIME\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */\n#endif\n\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n\n  z->cextra = z->extra;\n  z->cext = z->ext  = (EB_HEADSIZE+EB_UT_LEN(1));\n\n  return ZE_OK;\n#else /* !USE_EF_UT_TIME */\n  return (int)(z-z);\n#endif /* ?USE_EF_UT_TIME */\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return rmdir(d);\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\n\n/* NOTE:  the following include depends upon the environment\n *        variable $Workbench to be set correctly.  (Set by\n *        default, by Version command in Startup-sequence.)\n */\nint WBversion = (int)\n#include \"ENV:Workbench\"\n;\n\nvoid version_local()\n{\n   static ZCONST char CompiledWith[] = \"Compiled with %s%s under %s%s%s%s.\\n\\n\";\n\n/* Define buffers. */\n\n   char buf1[16];  /* compiler name */\n   char buf2[16];  /* revstamp */\n   char buf3[16];  /* OS */\n   char buf4[16];  /* Date */\n/*   char buf5[16];  /* Time */\n\n/* format \"with\" name strings */\n\n#ifdef AMIGA\n# ifdef __SASC\n   strcpy(buf1,\"SAS/C \");\n# else\n#  ifdef LATTICE\n    strcpy(buf1,\"Lattice C \");\n#  else\n#   ifdef AZTEC_C\n     strcpy(buf1,\"Manx Aztec C \");\n#   else\n     strcpy(buf1,\"UNKNOWN \");\n#   endif\n#  endif\n# endif\n/* \"under\" */\n  sprintf(buf3,\"AmigaDOS v%d\",WBversion);\n#else\n  strcpy(buf1,\"Unknown compiler \");\n  strcpy(buf3,\"Unknown OS\");\n#endif\n\n/* Define revision, date, and time strings.\n * NOTE:  Do not calculate run time, be sure to use time compiled.\n * Pass these strings via your makefile if undefined.\n */\n\n#if defined(__VERSION__) && defined(__REVISION__)\n  sprintf(buf2,\"version %d.%d\",__VERSION__,__REVISION__);\n#else\n# ifdef __VERSION__\n  sprintf(buf2,\"version %d\",__VERSION__);\n# else\n  sprintf(buf2,\"unknown version\");\n# endif\n#endif\n\n#ifdef __DATE__\n  sprintf(buf4,\" on %s\",__DATE__);\n#else\n  strcpy(buf4,\" unknown date\");\n#endif\n\n/******\n#ifdef __TIME__\n  sprintf(buf5,\" at %s\",__TIME__);\n#else\n  strcpy(buf5,\" unknown time\");\n#endif\n******/\n\n/* Print strings using \"CompiledWith\" mask defined above.\n *  (\"Compiled with %s%s under %s%s%s%s.\")\n */\n\n   printf(CompiledWith,\n     buf1,\n     buf2,\n     buf3,\n     buf4,\n     /* buf5, */ \"\",\n     \"\" );  /* buf6 not used */\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/filedate.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Low-level Amiga routines shared between Zip and UnZip.\n *\n * Contains:  FileDate()\n *            getenv()          [replaces inadequate standard library version]\n *            setenv()          [SAS/C only, replaces standard library version]\n *            set_TZ()          [SAS/C only]\n *            GetPlatformLocalTimezone() [callback from timezone.c tzset()]\n *            time()\n *            sendpkt()\n *            Agetch()\n *\n * The first five are used by most Info-ZIP programs except fUnZip.\n * The last two are used by all except the non-CRYPT version of fUnZip.\n * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...\n * sendpkt() is used by Agetch() and FileDate(), and by screensize() in\n * amiga/amiga.c (UnZip); time() is used only by Zip.\n */\n\n\n/* HISTORY/CHANGES\n *  2 Sep 92, Greg Roelofs, Original coding.\n *  6 Sep 92, John Bush, Incorporated into UnZip 5.1\n *  6 Sep 92, John Bush, Interlude \"FileDate()\" defined, which calls or\n *            redefines SetFileDate() depending upon AMIGADOS2 definition.\n * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining\n *            revision via OpenLibrary() call.  Now only one version of\n *            the program runs on both platforms (1.3.x vs. 2.x)\n * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing\n *            to take time_t input instead of struct DateStamp.\n *            Arg passing made to conform with utime().\n * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some\n *            lint-ish errors; simplified test for AmigaDOS version.\n * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and\n *            UnZip's \"More\" prompt -- simplifies crypt.h and avoids\n *            use of library code redundant with sendpkt().  Made it\n *            available to fUnZip, which does not use FileDate().\n * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current\n *            timezone from the Locale preferences.  These exist only under\n *            AmigaDOS 2.1 and up, but it is probably correctly set on more\n *            Amigas than the TZ environment variable is.  We check that\n *            only if TZ is not validly set.  We do not parse daylight\n *            savings syntax except to check for presence vs. absence of a\n *            DST part; United States rules are assumed.  This is better\n *            than the tzset()s in the Amiga compilers' libraries do.\n * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level\n *            sendpkt() (when FileDate(), Agetch() or windowheight() is used),\n *            and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).\n * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved\n *            stuff around for clarity.\n * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the\n *            new tzset(), because Aztec's is hopelessly broken.  Also\n *            gmtime(), which localtime() calls.\n * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.\n * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns\n *            local time instead of GMT.  That's why their localtime() was bad,\n *            because it assumed time_t was already local, and gmtime() was\n *            the one that checked TZ.\n * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.\n *            Currently, the UnZip sources do not make use of time() (and do\n *            not supply the working mktime() replacement, either!).\n * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that\n *            was previously embedded in tzset(), for reliable global test\n *            of whether TZ is set or not.\n * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.\n *  7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.\n *  4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.\n * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding\n *            mkgmtime() so localtime() could be used.\n * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;\n *            the Zip sources supply this function as part of util.c.\n * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved\n *            set_TZ() to time_lib.c.\n * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.\n * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).\n * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.\n * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.\n * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to\n *            Amiga file-time directly.\n * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().\n * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined\n *            header inclusion sequence that resolves all header dependencies.\n * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license,\n *            moved set_TZ() back here, replaced minimal tzset() and localtime()\n *            with new versions derived from GNU glibc source.  Gave locale_TZ()\n *            reasonable European defaults for daylight savings.\n * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL\n *            virus, replaced with similar functions based on the public domain\n *            timezone code at ftp://elsie.nci.nih.gov/pub.  As with the GNU\n *            stuff, support for timezone files and leap seconds was removed.\n * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate\n *            platform-independent module 'timezone.c'.\n * 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions\n *            back in here, from 'timezone.c'.\n * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include \"timezone.h\"\n *            and \"symbolic\" preprocessor constants for time calculations.\n * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation\n *            for Zip utilities (when \"defined(UTIL)\")\n */\n\n#ifndef __amiga_filedate_c\n#define __amiga_filedate_c\n\n\n#include \"zip.h\"\n#include <ctype.h>\n#include <errno.h>\n\n#include <exec/types.h>\n#include <exec/execbase.h>\n#include <exec/memory.h>\n#include <dos/dosextens.h>\n\n#ifdef AZTEC_C\n#  include <libraries/dos.h>\n#  include <libraries/dosextens.h>\n#  include <clib/exec_protos.h>\n#  include <clib/dos_protos.h>\n#  include <clib/locale_protos.h>\n#  include <pragmas/exec_lib.h>\n#  include <pragmas/dos_lib.h>\n#  include <pragmas/locale_lib.h>\n#  define ESRCH  ENOENT\n#  define EOSERR EIO\n#endif\n\n#ifdef __SASC\n#  include <stdlib.h>\n#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))\n                            /* on 68020 or higher processors it is faster   */\n#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */\n#  endif                    /* to access functions of the exec.library      */\n#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */\n#  include <proto/dos.h>\n#  include <proto/locale.h>\n#  ifdef DEBUG\n#     include <sprof.h>\n#  endif\n#  ifdef MWDEBUG\n#    include <stdio.h>      /* include both before memwatch.h again just */\n#    include <stdlib.h>     /* to be safe */\n#    include \"memwatch.h\"\n#  endif /* MWDEBUG */\n#endif /* __SASC */\n\n#include \"crypt.h\"            /* just so we can tell if CRYPT is supported */\n\n\n#if (!defined(FUNZIP) && !defined(UTIL))\n\n#include \"timezone.h\"         /* for AMIGA-specific timezone callbacks */\n\n#ifndef SUCCESS\n#  define SUCCESS (-1L)\n#  define FAILURE 0L\n#endif\n\n#define ReqVers 36L        /* required library version for SetFileDate() */\n#define ENVSIZE 100        /* max space allowed for an environment var   */\n\nextern struct ExecBase *SysBase;\n\n#ifndef min\n#  define min(a, b)  ((a) < (b) ? (a) : (b))\n#  define max(a, b)  ((a) < (b) ? (b) : (a))\n#endif\n\n#if defined(ZIP) || defined(HAVE_MKTIME)\nstatic const unsigned short ydays[] =\n    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };\n#else\nextern const unsigned short ydays[];  /* in unzip's fileio.c */\n#endif\n\n#define LEAP(y)     (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n#define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y)))\n/* Number of leap years from 1978 to `y' (not including `y' itself). */\n#define ANLEAP(y)   (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)\n#define SECSPERMIN  60\n#define MINSPERHOUR 60\n#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)\n#define SECSPERDAY  86400L\n\n/* prototypes */\nchar *getenv(const char *var);\n#ifdef __SASC\n/*  XXX !!  We have really got to find a way to operate without these. */\nint setenv(const char *var, const char *value, int overwrite);\nvoid set_TZ(long time_zone, int day_light);\n#endif\n\nLONG FileDate(char *filename, time_t u[]);\nLONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\nint Agetch(void);\n\n/* =============================================================== */\n\n/***********************/\n/* Function filedate() */\n/***********************/\n\n/*  FileDate() (originally utime.c), by Paul Wells.  Modified by John Bush\n *  and others (see also sendpkt() comments, below); NewtWare SetFileDate()\n *  clone cheaply ripped off from utime().\n */\n\n/* DESCRIPTION\n * This routine chooses between 2 methods to set the file date on AMIGA.\n * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36\n * and higher).  Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()\n * must be accomplished by constructing a message packet and sending it\n * to the file system handler of the file to be stamped.\n *\n * The system's ROM version is extracted from the external system Library\n * base.\n *\n * NOTE:  although argument passing conforms with utime(), note the\n *        following differences:\n *          - Return value is boolean success/failure.\n *          - If a structure or array is passed, only the first value\n *            is used, which *may* correspond to date accessed and not\n *            date modified.\n */\n\nLONG FileDate(filename, u)\n    char *filename;\n    time_t u[];\n{\n    LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);\n    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n    struct MsgPort *taskport;\n    BPTR dirlock, lock;\n    struct FileInfoBlock *fib;\n    LONG pktargs[4];\n    UBYTE *ptr;\n    long ret;\n\n    struct DateStamp pDate;\n    struct tm *ltm;\n    int years;\n\n    tzset();\n    /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):\n     * 8 years and 2 leapdays difference from Unix time.\n     */\n    ltm = localtime(&u[0]);\n    years = ltm->tm_year + 1900;\n    if (years < 1978)\n        pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;\n    else {\n        pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) +\n                        YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1);\n        pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;\n        pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;\n    }\n\n    if (SysBase->LibNode.lib_Version >= ReqVers)\n    {\n        return (SetFileDate(filename,&pDate));  /* native routine at 2.0+ */\n    }\n    else  /* !(SysBase->lib_Version >=ReqVers) */\n    {\n        if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )\n        {\n            errno = ESRCH;          /* no such process */\n            return FAILURE;\n        }\n\n        if( !(lock = Lock(filename,SHARED_LOCK)) )\n        {\n            errno = ENOENT;         /* no such file */\n            return FAILURE;\n        }\n\n        if( !(fib = (struct FileInfoBlock *)AllocMem(\n            (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )\n        {\n            errno = ENOMEM;         /* insufficient memory */\n            UnLock(lock);\n            return FAILURE;\n        }\n\n        if( Examine(lock,fib)==FAILURE )\n        {\n            errno = EOSERR;         /* operating system error */\n            UnLock(lock);\n            FreeMem(fib,(long)sizeof(*fib));\n            return FAILURE;\n        }\n\n        dirlock = ParentDir(lock);\n        ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);\n        strcpy((ptr+1),fib->fib_FileName);\n        *ptr = strlen(fib->fib_FileName);\n        FreeMem(fib,(long)sizeof(*fib));\n        UnLock(lock);\n\n        /* now fill in argument array */\n\n        pktargs[0] = 0;\n        pktargs[1] = (LONG)dirlock;\n        pktargs[2] = (LONG)&ptr[0] >> 2;\n        pktargs[3] = (LONG)&pDate;\n\n        errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);\n\n        FreeMem(ptr,64L);\n        UnLock(dirlock);\n\n        return SUCCESS;\n    }  /* ?(SysBase->lib_Version >= ReqVers) */\n} /* FileDate() */\n\n\nchar *getenv(const char *var)         /* not reentrant! */\n{\n    static char space[ENVSIZE];\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    char *ret = NULL;\n\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (SysBase->LibNode.lib_Version >= ReqVers) {\n        if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0)\n            ret = space;\n    } else {                    /* early AmigaDOS, get env var the crude way */\n        BPTR hand, foot, spine;\n        int z = 0;\n        if (foot = Lock(\"ENV:\", ACCESS_READ)) {\n            spine = CurrentDir(foot);\n            if (hand = Open((char *) var, MODE_OLDFILE)) {\n                z = Read(hand, space, ENVSIZE - 1);\n                Close(hand);\n            }\n            UnLock(CurrentDir(spine));\n        }\n        if (z > 0) {\n            space[z] = '\\0';\n            ret = space;\n        }\n    }\n    me->pr_WindowPtr = old_window;\n    return ret;\n}\n\n#ifdef __SASC\nint setenv(const char *var, const char *value, int overwrite)\n{\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    int ret = -1;\n\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (SysBase->LibNode.lib_Version >= ReqVers)\n        ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR);\n    else {\n        BPTR hand, foot, spine;\n        long len = value ? strlen(value) : 0;\n        if (foot = Lock(\"ENV:\", ACCESS_READ)) {\n            spine = CurrentDir(foot);\n            if (len) {\n                if (hand = Open((char *) var, MODE_NEWFILE)) {\n                    ret = Write(hand, (char *) value, len + 1) >= len;\n                    Close(hand);\n                }\n            } else\n                ret = DeleteFile((char *) var);\n            UnLock(CurrentDir(spine));\n        }\n    }\n    me->pr_WindowPtr = old_window;\n    return ret;\n}\n\n/* Stores data from timezone and daylight to ENV:TZ.                  */\n/* ENV:TZ is required to exist by some other SAS/C library functions, */\n/* like stat() or fstat().                                            */\nvoid set_TZ(long time_zone, int day_light)\n{\n    char put_tz[MAXTIMEZONELEN];  /* string for putenv: \"TZ=aaabbb:bb:bbccc\" */\n    int offset;\n    void *exists;     /* dummy ptr to see if global envvar TZ already exists */\n    exists = (void *)getenv(TZ_ENVVAR);\n    /* see if there is already an envvar TZ_ENVVAR. If not, create it */\n    if (exists == NULL) {\n        /* create TZ string by pieces: */\n        sprintf(put_tz, \"GMT%+ld\", time_zone / 3600L);\n        if (time_zone % 3600L) {\n            offset = (int) labs(time_zone % 3600L);\n            sprintf(put_tz + strlen(put_tz), \":%02d\", offset / 60);\n            if (offset % 60)\n                sprintf(put_tz + strlen(put_tz), \":%02d\", offset % 60);\n        }\n        if (day_light)\n            strcat(put_tz,\"DST\");\n        setenv(TZ_ENVVAR, put_tz, 1);\n    }\n}\n#endif /* __SASC */\n\n/* set state as well as possible from settings found in locale.library */\nint GetPlatformLocalTimezone(sp, fill_tzstate_from_rules)\n     register struct state * ZCONST sp;\n     void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                     ZCONST struct rule * ZCONST start,\n                                     ZCONST struct rule * ZCONST end);\n{\n    struct Library *LocaleBase;\n    struct Locale *ll;\n    struct Process *me = (void *) FindTask(NULL);\n    void *old_window = me->pr_WindowPtr;\n    BPTR eh;\n    int z, valid = FALSE;\n\n    /* read timezone from locale.library if TZ envvar missing */\n    me->pr_WindowPtr = (void *) -1;   /* suppress any \"Please insert\" popups */\n    if (LocaleBase = OpenLibrary(\"locale.library\", 0)) {\n        if (ll = OpenLocale(NULL)) {\n            z = ll->loc_GMTOffset;    /* in minutes */\n            if (z == -300) {\n                if (eh = Lock(\"ENV:sys/locale.prefs\", ACCESS_READ)) {\n                    UnLock(eh);\n                    valid = TRUE;\n                } else\n                    z = 300; /* bug: locale not initialized, default bogus! */\n            } else\n                valid = TRUE;\n            if (valid) {\n                struct rule startrule, stoprule;\n\n                sp->timecnt = 0;\n                sp->typecnt = 1;\n                sp->charcnt = 2;\n                sp->chars[0] = sp->chars[1] = '\\0';\n                sp->ttis[0].tt_abbrind = 0;\n                sp->ttis[1].tt_abbrind = 1;\n                sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR;\n                sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR;\n                sp->ttis[0].tt_isdst = 0;\n                sp->ttis[1].tt_isdst = 1;\n                stoprule.r_type = MONTH_NTH_DAY_OF_WEEK;\n                stoprule.r_day = 0;\n                stoprule.r_week = 5;\n                stoprule.r_mon = 10;\n                stoprule.r_time = 2 * SECSPERHOUR;\n                startrule = stoprule;\n                startrule.r_mon = 4;\n                startrule.r_week = 1;\n                if (z >= -180 && z < 150) {\n                    /* At this point we make a really gratuitous assumption: */\n                    /* if the time zone could be Europe, we use the European */\n                    /* Union rules without checking what country we're in.   */\n                    /* The AmigaDOS locale country codes do not, at least in */\n                    /* 2.x versions of the OS, recognize very many countries */\n                    /* outside of Europe and North America.                  */\n                    sp->typecnt = 2;\n                    startrule.r_mon = 3;   /* one week earlier than US DST */\n                    startrule.r_week = 5;\n                } else if (z >= 150 && z <= 480 &&\n                           /* no DST in alaska, hawaii */\n                           (ll->loc_CountryCode == 0x55534100 /*\"USA\"*/ ||\n                            ll->loc_CountryCode == 0x43414E00 /*\"CAN\"*/))\n                    sp->typecnt = 2;\n                    /* We check the country code for U.S. or Canada because */\n                    /* most of Latin America has no DST.  Even in these two */\n                    /* countries there are some exceptions...               */\n                /* else if...  Feel free to add more cases here! */\n\n                if (sp->typecnt > 1)\n                    (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);\n            }\n            CloseLocale(ll);\n        }\n        CloseLibrary(LocaleBase);\n    }\n    me->pr_WindowPtr = old_window;\n    return valid;\n}\n\n#ifdef ZIP\ntime_t time(time_t *tp)\n{\n    time_t t;\n    struct DateStamp ds;\n    DateStamp(&ds);\n    t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60\n                                      + (ds.ds_Days + 2922) * SECSPERDAY;\n    t = mktime(gmtime(&t));\n    /* gmtime leaves ds in the local timezone, mktime converts it to GMT */\n    if (tp) *tp = t;\n    return t;\n}\n#endif /* ZIP */\n\n#endif /* !FUNZIP && !UTIL */\n\n\n#if CRYPT || !defined(FUNZIP)\n\n/*  sendpkt.c\n *  by A. Finkel, P. Lindsay, C. Sheppner\n *  returns Res1 of the reply packet\n */\n/*\n#include <exec/types.h>\n#include <exec/memory.h>\n#include <libraries/dos.h>\n#include <libraries/dosextens.h>\n#include <proto/exec.h>\n#include <proto/dos.h>\n*/\n\nLONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n\nLONG sendpkt(pid,action,args,nargs)\nstruct MsgPort *pid;           /* process identifier (handler message port) */\nLONG action,                   /* packet type (desired action)              */\n     *args,                    /* a pointer to argument list                */\n     nargs;                    /* number of arguments in list               */\n{\n\n    struct MsgPort *replyport, *CreatePort(UBYTE *, long);\n    void DeletePort(struct MsgPort *);\n    struct StandardPacket *packet;\n    LONG count, *pargs, res1;\n\n    replyport = CreatePort(NULL,0L);\n    if( !replyport ) return(0);\n\n    packet = (struct StandardPacket *)AllocMem(\n            (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);\n    if( !packet )\n    {\n        DeletePort(replyport);\n        return(0);\n    }\n\n    packet->sp_Msg.mn_Node.ln_Name  = (char *)&(packet->sp_Pkt);\n    packet->sp_Pkt.dp_Link          = &(packet->sp_Msg);\n    packet->sp_Pkt.dp_Port          = replyport;\n    packet->sp_Pkt.dp_Type          = action;\n\n    /* copy the args into the packet */\n    pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of 1st argument */\n    for( count=0; count<nargs; count++ )\n        pargs[count] = args[count];\n\n    PutMsg(pid,(struct Message *)packet);   /* send packet */\n\n    WaitPort(replyport);\n    GetMsg(replyport);\n\n    res1 = packet->sp_Pkt.dp_Res1;\n\n    FreeMem((char *)packet,(long)sizeof(*packet));\n    DeletePort(replyport);\n\n    return(res1);\n\n} /* sendpkt() */\n\n#endif /* CRYPT || !FUNZIP */\n\n\n#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))\n\n/* Agetch() reads one raw keystroke -- uses sendpkt() */\n\nint Agetch(void)\n{\n    LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);\n    struct Task *me = FindTask(NULL);\n    struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);\n    BPTR fh = cli->cli_StandardInput;   /* this is immune to < redirection */\n    void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;\n    char longspace[8];\n    long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */\n    UBYTE c;\n\n    *flag = 1;\n    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);         /* assume success */\n    Read(fh, &c, 1);\n    *flag = 0;\n    sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);\n    if (c == 3)                                         /* ^C in input */\n        Signal(me, SIGBREAKF_CTRL_C);\n    return c;\n}\n\n#endif /* CRYPT || (UNZIP && !FUNZIP) */\n\n#endif /* __amiga_filedate_c*/\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/makefile.azt",
    "content": "# Makefile for Zip, ZipNote, ZipCloak, ZipSplit for Aztec C 5.2\n# Also ZipLM, a version of Zip that needs much less free memory\n#   -- Paul Kienitz, last updated 07 Jan 2007\n\n# Make sure platform is defined correctly, and select memory usage options:\nDEFINES = -d AMIGA -d DYN_ALLOC -d ASM_CRC\n\nCC = cc\nAS = as\nLD = ln\nLDLIBS = -lc16\n\n\n# -------- RELEASE VERSION:\nCFLAGS = -psb0e -sabfmnpu -wcr0u $(DEFINES)\n# -pbs means unsigned chars and short ints, -sabfmnpu is various small\n# optimizations, -wcr0u adjusts type checking strictness\nASOPTS = -n -eAMIGA -eDYN_ALLOC -eCPUTEST -eINT16\nLDFLAGS = -m +q\n\n# -------- DEBUG VERSION:\nCFLAGD = -bs -psb0e -s0f0n -wcr0u $(DEFINES)\n# -bs is include source debugging info, -s0f0n is avoid hard-to-debug\n# optimizations\nLDFLAGD = -m +q -g -w\n\n# -------- MINIMUM MEMORY USAGE RELEASE VERSION:\nWSIZ = WSIZE=4096\nLOWFLAGS = $(CFLAGS) -d $(WSIZ) -d SMALL_MEM\nLOWASOPTS = $(ASOPTS) -e$(WSIZ) -eSMALL_MEM\n# Options used for assembling amiga/deflate.a; must generally match the\n# settings in DEFINES.\n\n# -------- MINIMUM MEMORY USAGE DEBUG VERSION:\nLOWFLAGD = $(CFLAGD) -d $(WSIZ) -d SMALL_MEM\n\n# the directory where we stick all the object files:\nO = obA/\n\n\n# default C rules\n.c.o :\n\t$(CC) $(CFLAGS) -o $@ $*.c\n\n# rules for routines containing entries needed by utilities\n.c.oo :\n\t$(CC) $(CFLAGS) -d UTIL -o $@ $*.c\n\n# rules for the low-memory version:\n\n.c.ol :\n\t$(CC) $(LOWFLAGS) -o $@ $*.c\n\n# default C rules for debugging\n.c.od :\n\t$(CC) $(CFLAGD) -o $@ $*.c\n\n# debugging rules for routines containing entries needed by utilities\n.c.dd :\n\t$(CC) $(CFLAGD) -d UTIL -o $@ $*.c\n\n# rules for the debugging low-memory version:\n\n.c.dl :\n\t$(CC) $(LOWFLAGD) -o $@ $*.c\n\n\n# object file lists\n\nZIP_H = zip.h ziperr.h tailor.h amiga/osdep.h amiga/z-stat.h\n\n\nOBJZ = $(O)zip.o $(O)deflate.o \\\n        $(O)trees.o $(O)zipfile.o $(O)zipup.o $(O)util.o $(O)timezone.o \\\n        $(O)fileio.o $(O)globals.o $(O)crc32.o $(O)crypt.o $(O)ttyio.o \\\n        $(O)amiga.o $(O)amigazip.o $(O)crc_68.o\n\nOBJL = $(O)zip.ol $(O)deflate.ol \\\n        $(O)trees.ol $(O)zipfile.ol $(O)zipup.ol $(O)util.ol $(O)timezone.ol \\\n        $(O)fileio.ol $(O)globals.ol $(O)crc32.ol $(O)crypt.ol $(O)ttyio.ol \\\n        $(O)amiga.ol $(O)amigazip.ol $(O)crc_68.o\n\nOBJU = $(O)zipfile.oo $(O)fileio.oo \\\n        $(O)util.oo $(O)globals.o $(O)amiga.oo $(O)amigazip.oo\nOBJN = $(O)zipnote.o  $(OBJU)\nOBJC = $(O)zipcloak.o $(OBJU) $(O)crc32.oo \\\n        $(O)crypt.oo $(O)ttyio.o\nOBJS = $(O)zipsplit.o $(OBJU)\n\n# These are the debuggable versions:\n\nDBJZ = $(O)zip.od $(O)deflate.od \\\n        $(O)trees.od $(O)zipfile.od $(O)zipup.od $(O)util.od $(O)timezone.od \\\n        $(O)fileio.od $(O)globals.od $(O)crc32.od $(O)crypt.od $(O)ttyio.od \\\n        $(O)amiga.od $(O)amigazip.od $(O)crc_68.o\n\nDBJL = $(O)zip.dl $(O)deflate.dl \\\n        $(O)trees.dl $(O)zipfile.dl $(O)zipup.dl $(O)util.dl $(O)timezone.dl \\\n        $(O)fileio.dl $(O)globals.dl $(O)crc32.dl $(O)crypt.dl $(O)ttyio.dl \\\n        $(O)amiga.dl $(O)amigazip.dl $(O)crc_68.o\n\nDBJU = $(O)zipfile.dd $(O)fileio.dd \\\n        $(O)util.dd $(O)globals.od $(O)amiga.dd $(O)amigazip.dd\nDBJN = $(O)zipnote.od  $(DBJU)\nDBJC = $(O)zipcloak.od $(DBJU) $(O)crc32.dd \\\n        $(O)crypt.dd $(O)ttyio.od\nDBJS = $(O)zipsplit.od $(DBJU)\n\n\n#  HERE WE GO:\n\nall : Zip ZipNote ZipSplit ZipCloak ZipLM\n\nz : Zip\n\nn : ZipNote\n\ns : ZipSplit\n\nc : ZipCloak\n\nl : ZipLM\n\n# Debug versions:\n\ndall : Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg ZipLM.dbg\n\ndz : Zip.dbg\n\ndn : ZipNote.dbg\n\nds : ZipSplit.dbg\n\ndc : ZipCloak.dbg\n\ndl : ZipLM.dbg\n\n\nZip : $(OBJZ) $(ZIP_H)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJZ) $(LDLIBS)\n\t-@delete Zip.dbg\n\nZipNote : $(OBJN) $(ZIP_H)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJN) $(LDLIBS)\n\t-@delete ZipNote.dbg\n\nZipSplit : $(OBJS) $(ZIP_H)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)\n\t-@delete ZipSplit.dbg\n\nZipCloak : $(OBJC) $(ZIP_H)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJC) $(LDLIBS)\n\t-@delete ZipCloak.dbg\n\nZipLM : $(OBJL) $(ZIP_H)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJL) $(LDLIBS)\n\t-@delete ZipLM.dbg\n\n\nZip.dbg : $(DBJZ) $(ZIP_H)\n\t$(LD) $(LDFLAGD) -o Zip $(DBJZ) $(LDLIBS)\n\nZipNote.dbg : $(DBJN) $(ZIP_H)\n\t$(LD) $(LDFLAGD) -o ZipNote $(DBJN) $(LDLIBS)\n\nZipSplit.dbg : $(DBJS) $(ZIP_H)\n\t$(LD) $(LDFLAGD) -o ZipSplit $(DBJS) $(LDLIBS)\n\nZipCloak.dbg : $(DBJC) $(ZIP_H)\n\t$(LD) $(LDFLAGD) -o ZipCloak $(DBJC) $(LDLIBS)\n\nZipLM.dbg : $(DBJL) $(ZIP_H)\n\t$(LD) $(LDFLAGD) -o ZipLM $(DBJL) $(LDLIBS)\n\n\nclean : bugclean\n\t-delete quiet $(OBJZ)\n\t-delete quiet $(OBJL)\n\t-delete quiet $(O)zipnote.o $(O)zipcloak.o $(O)zipsplit.o \\\n                       $(O)crypt.oo $(OBJU)\n\nbugclean :\n\t-delete quiet $(DBJZ)\n\t-delete quiet $(DBJL)\n\t-delete quiet $(O)zipnote.od $(O)zipcloak.od $(O)zipsplit.od \\\n                       $(O)crypt.dd $(DBJU)\n\ncleaner : clean\n\t-delete quiet Zip ZipNote ZipSplit ZipCloak ZipLM\n\t-delete quiet Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg ZipLM.dbg\n\n\n# header dependencies:\n\n$(O)zip.o $(O)zipnote.o $(O)zipcloak.o $(O)zipsplit.o $(O)crypt.o $(O)ttyio.o \\\n   $(O)deflate.o $(O)trees.o $(O)zipfile.o $(O)zipup.o $(O)fileio.o $(O)util.o \\\n   $(O)timezone.o $(O)crc32.o $(O)globals.o $(O)amiga.o : $(ZIP_H)\n\n$(O)zip.ol $(O)zipnote.ol $(O)zipcloak.ol $(O)zipsplit.ol $(O)crypt.ol \\\n   $(O)ttyio.ol $(O)deflate.ol $(O)trees.ol $(O)zipfile.ol $(O)zipup.ol \\\n   $(O)fileio.ol $(O)util.ol $(O)timezone.ol $(O)crc32.ol $(O)globals.ol \\\n   $(O)amiga.ol : $(ZIP_H)\n\n$(O)crc32.oo $(O)crypt.oo $(O)zipfile.oo $(O)fileio.oo $(O)util.oo : $(ZIP_H)\n\n$(O)amigazip.o $(O)amigazip.ol $(O)amigazip.oo : amiga/amiga.h $(ZIP_H)\n\n$(O)zip.o $(O)zipnote.o $(O)zipcloak.o $(O)zipsplit.o $(O)zipup.o \\\n   $(O)zip.ol $(O)zipnote.ol $(O)zipcloak.ol $(O)zipsplit.ol \\\n   $(O)zipup.ol : revision.h\n\n$(O)amiga.o $(O)amiga.ol : crypt.h\n\n$(O)crc32.o $(O)crc32.oo $(O)crc32.ol $(O)crypt.o $(O)crypt.oo $(O)crypt.ol \\\n   $(O)zipcloak.o $(O)zipcloak.ol $(O)zip.o $(O)zip.ol \\\n   $(O)zipup.o $(O)zipup.ol \\\n   $(O)zipfile.o $(O)zipfile.oo $(O)zipfile.ol \\\n   $(O)fileio.o $(O)fileio.oo $(O)fileio.ol : crc32.h\n\n$(O)crypt.o $(O)crypt.oo $(O)crypt.ol $(O)ttyio.o $(O)ttyio.ol \\\n   $(O)zipcloak.o $(O)zipcloak.ol $(O)zip.o $(O)zip.ol \\\n   $(O)zipup.o $(O)zipup.ol : crypt.h ttyio.h\n\n$(O)timezone.o $(O)timezone.ol $(O)timezone.od $(O)timezone.dl \\\n   $(O)amiga.o $(O)amiga.ol $(O)amiga.oo : timezone.h\n\n$(O)zipup.o $(O)zipup.ol : amiga/zipup.h\n\n\n# SPECIAL CASES:\n\n# -mr changes expression parsing; avoids a bogus \"expression too complex\" error:\n$(O)trees.o : trees.c\n\t$(CC) $(CFLAGS) -mr -o $@ trees.c\n\n$(O)trees.ol : trees.c\n\t$(CC) $(LOWFLAGS) -mr -o $@ trees.c\n\n$(O)trees.od : trees.c\n\t$(CC) $(CFLAGD) -mr -o $@ trees.c\n\n$(O)trees.ld : trees.c\n\t$(CC) $(LOWFLAGD) -mr -o $@ trees.c\n\n# Substitute the assembly version of deflate.c: (but not in debug version)\n$(O)deflate.o : amiga/deflate.a\n\t$(AS) $(ASOPTS) -o $@ amiga/deflate.a\n\n$(O)deflate.ol : amiga/deflate.a\n\t$(AS) $(LOWASOPTS) -o $@ amiga/deflate.a\n\n# The assembly CRC function:\n$(O)crc_68.o : amiga/crc_68.a\n\t$(AS) -n -o $@ amiga/crc_68.a\n\n# Put the Amiga internal version data with today's date into amiga.c:\n$(O)amiga.o : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(CFLAGS) -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n$(O)amiga.ol : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(LOWFLAGS) -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n$(O)amiga.od : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(CFLAGD) -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n$(O)amiga.ld : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(LOWFLAGD) -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n$(O)amiga.oo : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(CFLAGS) -d UTIL -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n$(O)amiga.dd : amiga/amiga.c amiga/filedate.c amiga/stat.c\n\trx > env:VersionDate \"say '\"\"'translate(date('E'), '.', '/')'\"\"'\"\n\t$(CC) $(CFLAGD) -d UTIL -o $@ amiga/amiga.c\n\tdelete env:VersionDate\n\n# Put the compiler version number into amigazip.c:\n$(O)amigazip.o : amiga/amigazip.c\n\t$(CC) $(CFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n\n$(O)amigazip.ol : amiga/amigazip.c\n\t$(CC) $(LOWFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n\n$(O)amigazip.od : amiga/amigazip.c\n\t$(CC) $(CFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n\n$(O)amigazip.ld : amiga/amigazip.c\n\t$(CC) $(LOWFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n\n$(O)amigazip.oo : amiga/amigazip.c\n\t$(CC) $(CFLAGS) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n\n$(O)amigazip.dd : amiga/amigazip.c\n\t$(CC) $(CFLAGD) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __amiga_osdep_h\n#define __amiga_osdep_h\n\n/* default to MEDIUM_MEM, but allow makefile override */\n#if ( (!defined(BIG_MEM)) && (!defined(SMALL_MEM)))\n#  define MEDIUM_MEM\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#ifndef IZTZ_GETLOCALETZINFO\n#  define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone\n#endif\n\n/* AmigaDOS can't even support disk partitions over 4GB, let alone files */\n#define NO_LARGE_FILE_SUPPORT\n#ifdef LARGE_FILE_SUPPORT\n#  undef LARGE_FILE_SUPPORT\n#endif\n\n#define USE_CASE_MAP\n#define USE_EF_UT_TIME\n#define HANDLE_AMIGA_SFX\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n#define EXIT(e) ClearIOErr_exit(e)\nvoid ClearIOErr_exit(int e);\n\n#include \"amiga/z-stat.h\"\n\n#ifdef __SASC\n#  include <sys/types.h>\n#  include <exec/execbase.h>\n#  if (defined(_M68020) && (!defined(__USE_SYSBASE)))\n                            /* on 68020 or higher processors it is faster   */\n#    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */\n#  endif                    /* to access functions of the exec.library      */\n#  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */\n#  include <proto/dos.h>\n#  if (defined(_M68020) && !defined(UNALIGNED_OK))\n#     define UNALIGNED_OK\n#  endif\n#  ifndef REENTRANT\n#    define REENTRANT\n#  endif\n#  if (defined(_NEAR_DATA) && !defined(DYN_ALLOC))\n#    define DYN_ALLOC\n#  endif\n#  ifdef DEBUG\n#    include <sprof.h>      /* profiler header file */\n#  endif\n#  ifndef IZTZ_SETLOCALTZINFO\n     /*  XXX !!  We have really got to find a way to operate without these. */\n#    define IZTZ_SETLOCALTZINFO\n#  endif\n\n/*\n A word on short-integers and SAS/C (a bug of [mc]alloc?)\n Using short integers (i.e. compiling with option SHORT-INTEGERS) is\n *not* recommended. To get maximum compression ratio the window size stored\n in WSIZE should be 32k (0x8000). However, since the size of the window[]\n array is 2*WSIZE, 65536 bytes must be allocated. The calloc function can\n only allocate UINT_MAX (defined in limits.h) bytes which is one byte short\n (65535) of the maximum window size if you are compiling with short-ints.\n You'll get an error message \"Out of memory (window allocation)\" whenever\n you try to deflate. Note that the compiler won't produce any warning.\n The maximum window size with short-integers is therefore 32768 bytes.\n The following is only implemented to allow the use of short-integers but\n it is once again not recommended because of a loss in compression ratio.\n*/\n#  if (defined(_SHORTINT) && !defined(WSIZE))\n#    define WSIZE 0x4000        /* only half of maximum window size */\n#  endif                        /* possible with short-integers     */\n#endif /* __SASC */\n/*\n With Aztec C, using short integers imposes no size limits and makes\n the program run faster, even with 32 bit CPUs, so it's recommended.\n*/\n#ifdef AZTEC_C\n#  define NO_UNISTD_H\n#  define NO_RMDIR\n#  define BROKEN_FSEEK\n#  ifndef IZTZ_DEFINESTDGLOBALS\n#    define IZTZ_DEFINESTDGLOBALS\n#  endif\n#endif\n\nextern int real_timezone_is_set;\nvoid tzset(void);\n#define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set)\n\n#ifdef ZCRYPT_INTERNAL\n#  ifndef CLIB_EXEC_PROTOS_H\n     void *FindTask(void *);\n#  endif\n#  define ZCR_SEED2     (unsigned)(ulg)FindTask(NULL)\n#endif\n\nint Agetch(void);               /* getch() like function, in amiga/filedate.c */\nchar *GetComment(char *);\n\n#define FOPR \"rb\"\n#define FOPM \"rb+\"\n#define FOPW \"wb\"\n/* prototype for ctrl-C trap function */\nvoid _abort(void);\n\n#endif /* !__amiga_osdep_h */\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/smakefile",
    "content": "#===========================================================================\n# Makefile for Zip, ZipNote, ZipCloak, ZipSplit     AMIGA SAS/C Version 6.58\n# Version:  2.3                                   last revised:  07 Jan 2007\n#===========================================================================\n# -John Bush, <John.Bush@East.Sun.COM>\n#         or: <JBush@Bix.COM>\n\n# updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40)\n# by Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>\n\n# additional supplements and maintenance by Paul Kienitz\n\n# This makefile should work with at least AmigaDOS 2.04 (V37)  (not tested)\n# and will probably not work with AmigaDOS 1.3 (V34)\n\n# If you have any improvements, critics or else please feel free to mail.\n# Any response is appreciated. Haidinger Walter <walthaid@unix.ict.tuwien.ac.at>\n\n# Available targets:\n# all           builds all executeables below\n# zip           builds zip executeable\n# zipsplit      builds zipsplit executeable\n# zipcloak      builds zipcloak executeable\n# zipnote       builds zipnote executeable\n# ziplm         builds low memory version of zip executable\n# clean         remove all files created by the compilation\n# spotless      like clean target but removes binaries too\n\n\n##########################\n# USER MACRO DEFINITIONS #\n##########################\n\n# *** NOTE ***\n# The assembly version is not implemented yet.\n# (Un)commenting the assembler macros has no effect unless the\n# file dependencies are changed too.\n# Most of the amiga/*.a files do not assmble with 68000 instructions.\n# Any help is appreciated, of course.\n\n# Set the processor to generate code for.\n# Compiler:    ANY 68000 68010 68020 68030 68040 68060\n# Assembler:     0     0     1     2     3     4   n/a\n# Defaults: ANY and 0\n#\nCUSECPU = ANY\nAUSECPU = 0\n\n# UNCOMMENT to use 68020 instructions in the assembly version of deflate.o\n# Only use if code is generated for 68020 or higher processors above.\n# Note: You could use CPUTEST too to enable runtime cpu detection.\n# However, it is not recommended since both 68000 and 68020 code will be\n# included which would be an unnecessary increase in size.\n# (see amiga/deflate.a for more information)\n#\n#AUSE020 = CPU020\n\n# To disable the assembler replacements and use the standard C source,\n# you have to change the Zip and ZipLM dependencies. See below for details.\n# (remember that assembler use is *not* implemented yet)\n\n# Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+\n# The utility.library is *not* used for UnZipSFX to ensure maximum portability\n# between the different Amiga systems (minimal config: 68000 and OS 1.2).\n# You can change this by adding the $(LUTIL) macro in the UnZipSFX linking\n# rules (See below: Final output targets, UnZipSFX:).\n# WARNINGS when using the utility library:\n# 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher.\n# 2. You *need not* compile/link with short-integers using the\n#    utility.library. It will crash your machine. See Libraries below.\n#\n# Default: commented (not used)\n#\n#CUTIL = UTILLIB DEFINE=_UTILLIB\n#LUTIL = WITH SC:LIB/utillib.with    # include necessary linker defines\n# Choose one stack-handling method (default=faster)\n# StackExtend: Dynamic runtime stack extension. You won't notice stack overflows.\n# StackCheck: On a stack overflow a requester appears which allows you to exit.\n# Note that either stack watching will slow down your executable because of the\n# extra code run on each function entry. On the other hand, you won't crash\n# anymore due to stack overflows. However, you should not have *any* stack\n# problems with Info-ZIP programs if you raise your stack to 10000 (which I'd\n# recommend as a minimum default stack for all applications) or more using the\n# shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup.\n# BTW: Typing 'Stack' prints your current stack size.\n#\nCSTACK = NOSTACKCHECK STACKEXTEND     # slow, but always works\n#CSTACK = STACKCHECK NOSTACKEXTEND    # slow, requester & graceful exit\n#CSTACK = NOSTACKCHECK NOSTACKEXTEND  # faster but relies on larger stack (>=10K)\n\n\n#\n# LIBRARIES\n# ---------\n\n# Choose one DATAOPTS , SASLIB , ASMOPTS and LSTARTUP\n# Always comment/uncomment all macros of a set.\n\n# Library to use with near data and 2-byte integers\n# Notes: o  slower than 4-byte integers with 68000 cpu\n#        o  *not* recommended due to poor overall performance\n#        o  see comment in amiga/osdep.h\n#DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA\n#SASLIB   = scs\n#ASMOPTS  = -dINT16\n#LSTARTUP = cres.o\n\n# Library to use with near data and 4-byte integers (DEFAULT)\n# *** use this with the utility.library ***\nDATAOPTS = DATA=NEAR DEF=_NEAR_DATA\nSASLIB   = sc\nASMOPTS  =\nLSTARTUP = cres.o\n\n# Library to use with far data and 2-byte integers\n# use if DYN_ALLOC is not defined\n# old default - far data always works but is slower\n#DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA\n#SASLIB   = scsnb\n#ASMOPTS  = -dINT16\n#LSTARTUP = c.o\n\n# Library to use with far data and 4-byte integers\n# if everything else fails: try this\n#DATAOPTS = DATA=FAR DEF=_FAR_DATA\n#SASLIB   = scnb\n#ASMOPTS  =\n#LSTARTUP = c.o\n\n\n#\n# DEBUGGING\n# ---------\n\n# Default: No debugging information added.\n# The three macros below will be overwritten if you choose to add\n# debug info, therefore no need to comment.\n\nCDBG = NODEBUG NOPROFILE NOCOVERAGE    # default: no debug info\nADBG =\nLDBG = STRIPDEBUG                      # default: no debug info\n\n# Compiler and loader debug flags.  Uncomment as needed.  Recomment when done.\n# Optimization disabled for faster compilation (by using NOOPT)\n\n#CDBG1 = DEF=DEBUG DEF=DEBUG_TIME     # enables Info-Zip's debug output\n\n# Enable profiling and coverage when desired. Option COVERAGE commented\n# seperately because running coverage may corrupt your drive in case of a\n# system crash since a file 'cover.dat' is created in your working directory.\n# Note that the use of COVERAGE forces the use of the c.o startup module.\n\n#CDBG2 = PROFILE\n#CDBG3 = COVERAGE        # must use c.o startup code:\n#LSTARTUP = c.o          # Uncomment *only* when you use COVERAGE\n\n# *Uncomment* here macros CDBG, ADBG and LDBG to include debugging information\n\n#CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT\n#ADBG = DEBUG\n#LDBG = ADDSYM\n\n# Optional use of memwatch.library which can be found in your\n# sc:extras/memlib directory. Please read the short docs (memlib.doc).\n# Note that memwatch.library has a small bug: MWTerm() displays always\n# the first entry.\n# Get the latest version from aminet (dev/debug/memlib.lha) or\n# contact me to get the patch. Uncomment all macros to use.\n#CMEMLIB  = DEFINE=MWDEBUG=1       # define to enable library\n#LMEMLIB  = SC:LIB/memwatch.lib       # path to library\n#LSTARTUP = c.o                    # must use c.o with memlib!\n\n\n#\n# MAPPING\n# -------\n\n# Map filenames used when mapping (no need to comment)\n#\nMAPFZ = zip.map                # Zip      map filename\nMAPFN = zipnote.map            # ZipNote  map filename\nMAPFC = zipcloak.map           # ZipCloak map filename\nMAPFS = zipsplit.map           # ZipSplit map filename\nMAPFL = ziplm.map              # Zip low memory version map filename\n\n# Map file output: Uncomment to highlight and bold headings.\n#\n#MAPFSTYLE = FANCY\n\n# Map flags for each EXECUTABLE. Uncomment to enable mapping.\n# For map options please refer to:\n# SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map\n# Default: all options enabled: f,h,l,o,s,x\n#                                 |-> options start here\n#LMAPZ = $(MAPFSTYLE) MAP $(MAPFZ) f,h,l,o,s,x   # Zip      maps\n#LMAPN = $(MAPFSTYLE) MAP $(MAPFN) f,h,l,o,s,x   # ZipNote  maps\n#LMAPC = $(MAPFSTYLE) MAP $(MAPFC) f,h,l,o,s,x   # ZipCloak maps\n#LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x   # ZipSplit maps\n#LMAPL = $(MAPFSTYLE) MAP $(MAPFL) f,h,l,o,s,x   # Zip lowmem maps\n\n#\n# LISTINGS\n# --------\n\n# Listfile-extensions for each executable (enter *with* dot)\n#\nLISTEXTZ = .lst   # extension for Zip listfiles\nLISTEXTU = .ulst  # extension for utility listfiles (ZipNote,ZipCloak,ZipSplit)\nLISTEXTL = .llst  # extension for Zip low memory listfiles\n\n\n# List files and cross references for each OBJECT.\n# Add/remove flags as needed. Not all listed by default.\n# Use LISTINCLUDES to determine the dependencies for smake\n#\nCLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES\nCXREFOPT = XHEAD XSYS\n#\n# Uncomment to enable listing (default: commented)\n# *** WARNING: List files require *lots* of disk space!\n#\n#CLIST = LIST $(CLISTOPT)\n#CXREF = XREF $(CXREFOPT)\n\n\n#\n# SUPPRESSED COMPILER WARNINGS\n# ----------------------------\n\n# Compiler warnings to ignore\n#\n# Warning 105 : module does not define any externally-known symbols\n# Warning 304 : Dead assignment eliminated...\n# Note    306 : ...function inlined...\n# Warning 317 : possibly uninitialized variable...\n# Comment to enable.\n#\nCIGNORE = IGNORE=105,304,306,317\n\n\n#\n# OBJECT EXTENSIONS\n#\n\n# Extensions used for objects of each executeable.\n# Transformation rules require unique extensions.\n# Enter *with* dot.\n#\nO  = .o     # extension for Zip     objects\nOU = .uo    # extension for utility objects (ZipNote, ZipSplit and ZipCloak)\nOL = .lo    # extension for low memory Zip objects\n\n\n# Filename used to store converted options from environment variable\n# LOCAL_ZIP. Default: scoptions_local_zip\n#\nCWITHOPT = scoptions_local_zip\n\n\n# Filenames to store compiler options to prevent command line overflow\n#\n# Common options file for Zip and other executables\nCFILE = scoptions-zip\n\n\n# Temp filenames for object lists to load using linker \"WITH\" command.\nOBJLISTZ = zip_objlist.with            # Zip      object list\nOBJLISTN = zipnote_objlist.with        # ZipNote  object list\nOBJLISTC = zipcloak_objlist.with       # ZipCloak object list\nOBJLISTS = zipsplit_objlist.with       # ZipSplit object list\nOBJLISTL = ziplm_objlist.with          # Zip low-mem object list\n\n\n# Filenames to store linker options\n#\nLWITHZ = zip.lnk                       # zip      linker options\nLWITHN = zipnote.lnk                   # zipnote  linker options\nLWITHC = zipcloak.lnk                  # zipcloak linker options\nLWITHS = zipsplit.lnk                  # zipsplit linker options\nLWITHL = ziplm.lnk                     # zip low-mem linker options\n\n\n# Define AMIGA_BETA to print \"Beta Notice\" up front.  See tailor.h.\n# Undefine AMIGA_BETA when building a released version.\n#CDEFBETA = DEF=AMIGA_BETA\n\n#####################################\n# NOTHING TO CHANGE BEYOND HERE ... #\n#####################################\n# (except for C/asm dependencies)\n\n# Define MEDIUM_MEM for production release (per Paul Kienitz).\n# This reduces runtime memory requirement but not speed or compression.\n# Note: Do *not* use BIG_MEM or MMAP since it isn't yet supported by the\n        assembler version of deflate.c : amiga/deflate.a\nCUSEMEM = DEF=MEDIUM_MEM\nAUSEMEM = -DMEDIUM_MEM       # for asm deflate.o, must match above\n\n\n# Defines for building low-memory use version of Zip\nWSIZEL   = WSIZE=4096     # deflate.c window size for low-mem version\nCLOWMEM = DEF=SMALL_MEM DEF=$(WSIZEL)\nALOWMEM = -DSMALL_MEM   -D$(WSIZEL)  # for asm deflate.o, must match above\n\n\n# Compiler definitions\n#\nCC = sc\n#\n# Optimizer flags\n#\nOPTPASSES = 6     # set number of global optimizer passes\n#\nOPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED\nOPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES)\nOPT  = $(OPT1) $(OPT2)\n\n\n# Compiler flags\n#\nCDEFINES = $(CMEMLIB) $(CDEFBETA) DEF=AMIGA\nCOPTIONS = $(DATAOPTS) CODE=NEAR CPU=$(CUSECPU) VERBOSE PARAMETERS=BOTH NOMINC\nCOPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF)\nCOPTIONS = $(COPTIONS) $(CSTACK) $(CUTIL) STRICT UNSCHAR NOICONS STRINGMERGE\nCFLAGS = $(CDEFINES) $(COPTIONS) $(OPT) $(CDBG) $(CIGNORE)\n\n\n# Linker definitions\n#  See SASLIB definition above\n#\nLD = slink\n# special linker flags for pure (i.e. resident) binary.\nLDFLAGSS = FROM SC:LIB/$(LSTARTUP)\n# common linker flags for all other executeables\nLDFLAGSC = FROM SC:LIB/c.o\nLDFLAGS2 = NOICONS $(LDBG)\nLIBFLAGS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib\n\n\n# Assembler definitions\n#\nASM = asm\n#\n# Options used for assembling amiga/deflate.a\n# Must match defines in C-Source.\n#\nAFLAGS0  = -d__SASC -dSASC -dAMIGA\nAFLAGS1  = $(AUSE020) $(ASMOPTS) $(ADBG)\nAFLAGS2  = -m$(AUSECPU) -jm -iINCLUDE:\nAFLAGS   = $(AFLAGS0) $(AFLAGS1) $(AFLAGS2)\nASMOPTSZ = $(AFLAGS) $(AUSEMEM) -dDYN_ALLOC     # Zip asm flags\nASMOPTSL = $(AFLAGS) $(ALOWMEM)                 # Zip low-mem version asm flags\n\n\n##################\n# TARGET OBJECTS #\n##################\n\n\n# Zip objects\nOBJZ1 = zip$(O) zipfile$(O) zipup$(O) fileio$(O) util$(O) globals$(O)\nOBJZ2 = crc32$(O) crypt$(O) timezone$(O) ttyio$(O)\nOBJZI = deflate$(O) trees$(O)\nOBJZA = amiga$(O) amigazip$(O) stat$(O) filedate$(O)\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZI) $(OBJZA)\n\n# Shared utility objects for ZipNote, ZipCloak and ZipSplit\nOBJU1 = globals$(O)\nOBJUU = zipfile$(OU) fileio$(OU) timezone$(O) util$(OU)\nOBJUA = amigazip$(OU) amiga$(O) stat$(O) filedate$(O)\nOBJU  = $(OBJU1) $(OBJUU) $(OBJUA)\n\n# ZipNote objects\nOBJN1 = zipnote$(O)\nOBJN  = $(OBJN1) $(OBJU)\n\n# ZipCloak objects\nOBJC1 = zipcloak$(O)\nOBJCU = $(OBJU) crypt$(OU)\nOBJCS = crc32$(OU) ttyio$(O)\nOBJC  = $(OBJC1) $(OBJCU) $(OBJCS)\n\n#ZipSplit objects\nOBJS1 = zipsplit$(O)\nOBJS  = $(OBJS1) $(OBJU)\n\n# ZipLM objects\nOBJL1 = zip$(OL) zipfile$(OL) zipup$(OL) fileio$(OL) util$(OL) globals$(OL)\nOBJL2 = crc32$(OL) crypt$(OL) timezone$(OL) ttyio$(OL)\nOBJLI = deflate$(OL) trees$(OL)\nOBJLA = amiga$(OL) amigazip$(OL) stat$(OL) filedate$(OL)\nOBJL  = $(OBJL1) $(OBJL2) $(OBJLI) $(OBJLA)\n\n# Common header files\nZIP_H1 = zip.h ziperr.h tailor.h\nZIP_HA = amiga/osdep.h amiga/z-stat.h\nZIP_H  = $(ZIP_H1) $(ZIP_HA)\n\n# Output targets\nZIPS  = Zip ZipNote ZipCloak ZipSplit ZipLM\n\n\n# Temp filenames for object lists to load using linker \"WITH\" command.\nOBJLISTZ = zip_objlist.with            # Zip      object list\nOBJLISTN = zipnote_objlist.with        # ZipNote  object list\nOBJLISTC = zipcloak_objlist.with       # ZipCloak object list\nOBJLISTS = zipsplit_objlist.with       # ZipSplit object list\nOBJLISTL = ziplm_objlist.with          # Zip low-mem object list\n\n#######################################\n# DEFAULT TARGET AND PROCESSING RULES #\n#######################################\n\nall: request flush $(ZIPS)\n\n# Zip transformation rules\n#\n.c$(O):\n      $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c\n\n# Zip low-memory version transformation rules\n#\n.c$(OL):\n      $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c\n\n# Utilities (ZipNote, ZipCloak and ZipSplit) transformation rules\n#\n.c$(OU):\n      $(CC) WITH=$(CFILE) $(CUSEMEM) DEF=UTIL LISTFILE=$>$(LISTEXTU) OBJNAME=$@ $*.c\n\n\n#########################\n# Final output targets. #\n#########################\n\n\nzip:      local_zip CommonFlags $(OBJZ)\n          @Echo \"$(OBJZ)\" > $(OBJLISTZ)\n          Type $(OBJLISTZ)\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTZ) $(LIBFLAGS)\" \\\n                \"$(LDFLAGS2) $(LMAPZ)\" >$(LWITHZ)\n          Type $(LWITHZ)\n          $(LD) TO Zip      WITH $(LWITHZ)\n\nzipnote:  local_zip CommonFlags $(OBJN)\n          @Echo \"$(OBJN)\" > $(OBJLISTN)\n          Type $(OBJLISTN)\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTN) $(LIBFLAGS) \" \\\n                \"$(LDFLAGS2) $(LMAPN)\" >$(LWITHN)\n          Type $(LWITHN)\n          $(LD) TO ZipNote  WITH $(LWITHN)\n\nzipcloak: local_zip CommonFlags $(OBJC)\n          @Echo \"$(OBJC)\" > $(OBJLISTC)\n          Type $(OBJLISTC)\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTC) $(LIBFLAGS) \" \\\n                \"$(LDFLAGS2) $(LMAPC)\" >$(LWITHC)\n          Type $(LWITHC)\n          $(LD) TO ZipCloak WITH $(LWITHC)\n\nzipsplit: local_zip CommonFlags $(OBJS)\n          @Echo \"$(OBJS)\" > $(OBJLISTS)\n          Type $(OBJLISTS)\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGS) \" \\\n                \"$(LDFLAGS2) $(LMAPS)\" >$(LWITHS)\n          Type $(LWITHS)\n          $(LD) TO ZipSplit WITH $(LWITHS)\n\nziplm:    local_zip CommonFlags $(OBJL)\n          @Echo \"$(OBJL)\" > $(OBJLISTL)\n          Type $(OBJLISTL)\n          @Echo \"$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTL) $(LIBFLAGS) \" \\\n                \"$(LDFLAGS2) $(LMAPL)\" >$(LWITHL)\n          Type $(LWITHL)\n          $(LD) TO ZipLM    WITH $(LWITHL)\n\n\nclean:\n        -Delete >nil: $(OBJZ) quiet\n        -Delete >nil: $(OBJN) quiet\n        -Delete >nil: $(OBJC) quiet\n        -Delete >nil: $(OBJS) quiet\n        -Delete >nil: $(OBJL) quiet\n        -Delete >nil: $(OBJLISTZ) $(OBJLISTL) $(OBJLISTN) $(OBJLISTS) $(OBJLISTC) quiet\n        -Delete >nil: $(MAPFZ) $(MAPFN) $(MAPFC) $(MAPFS) $(MAPFL) quiet\n        -Delete >nil: \\#?$(LISTEXTZ) \\#?$(LISTEXTU) \\#?$(LISTEXTL) quiet\n        -Delete >nil: $(CWITHOPT) $(CFILE) quiet\n        -Delete >nil: $(LWITHZ) $(LWITHN) $(LWITHC) $(LWITHS) $(LWITHL) quiet\n        -Delete >nil: env:VersionDate quiet\n        -Delete >nil: \\#?.q.?? \\#?.tmp \\#?.cov quiet\n\nspotless: clean\n        -Delete >nil: $(ZIPS) quiet\n\n\n################\n# DEPENDENCIES #\n################\n\n# To change between the assembler and C sources, you have to comment/uncomment\n# the approprite lines. C sources are marked by #C-src and assembler sources\n# #asm-src at the end.\n# Zip dependencies:\n#\n\nzip$(O):        zip.c      $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipup$(O):      zipup.c    $(ZIP_H) revision.h crc32.h crypt.h amiga/zipup.h\nzipfile$(O):    zipfile.c  $(ZIP_H) revision.h crc32.h\ncrypt$(O):      crypt.c    $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(O):      ttyio.c    $(ZIP_H) crypt.h ttyio.h\ndeflate$(O):    deflate.c  $(ZIP_H)                          #C-src\ntrees$(O):      trees.c    $(ZIP_H)\nfileio$(O):     fileio.c   $(ZIP_H) crc32.h\nutil$(O):       util.c     $(ZIP_H)\ncrc32$(O):      crc32.c    $(ZIP_H) crc32.h\nglobals$(O):    globals.c  $(ZIP_H)\ntimezone$(O):   timezone.c $(ZIP_H) timezone.h\n# Amiga specific objects\nstat$(O):       amiga/stat.c     amiga/z-stat.h\nfiledate$(O):   amiga/filedate.c crypt.h timezone.h\namiga$(O):      amiga/amiga.c    ziperr.h\namigazip$(O):   amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench\n# Substitute assembly version of deflate.c:\n#deflate$(O):  amiga/deflate.a                               #asm-src\n#        $(ASM) $(ASMOPTSZ) -o$@ $*.a                        #asm-src\n\n\n# Utility (ZipNote, ZipCloak, ZipSplit) dependencies:\n#\nzipnote$(O):    zipnote.c  $(ZIP_H) revision.h\nzipcloak$(O):   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipsplit$(O):   zipsplit.c $(ZIP_H) revision.h\nzipfile$(OU):   zipfile.c  $(ZIP_H) revision.h crc32.h\nfileio$(OU):    fileio.c   $(ZIP_H) crc32.h\nutil$(OU):      util.c     $(ZIP_H)\ncrc32$(OU):     crc32.c    $(ZIP_H) crc32.h\ncrypt$(OU):     crypt.c    $(ZIP_H) crypt.h crc32.h ttyio.h\n# Amiga specific objects\namigazip$(OU):   amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench\n\n# ZipLM dependencies:\n#\nzip$(OL):       zip.c      $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipup$(OL):     zipup.c    $(ZIP_H) revision.h crc32.h crypt.h amiga/zipup.h\nzipfile$(OL):   zipfile.c  $(ZIP_H) revision.h crc32.h\ncrypt$(OL):     crypt.c    $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(OL):     ttyio.c    $(ZIP_H) crypt.h ttyio.h\ndeflate$(OL):   deflate.c  $(ZIP_H)\ntrees$(OL):     trees.c    $(ZIP_H)\nfileio$(OL):    fileio.c   $(ZIP_H) crc32.h\nutil$(OL):      util.c     $(ZIP_H)\ncrc32$(OL):     crc32.c    $(ZIP_H)\nglobals$(OL):   globals.c  $(ZIP_H)\ntimezone$(OL):  timezone.c $(ZIP_H) timezone.h\n# Amiga specific objects\nstat$(OL):      amiga/stat.c     amiga/z-stat.h\nfiledate$(OL):  amiga/filedate.c crypt.h timezone.h\namiga$(OL):     amiga/amiga.c    ziperr.h\n# Substitute assembly version of deflate.c:\n#deflate$(OL): amiga/deflate.a\n#        $(ASM) $(ASMOPTSL) -o$@ $*.a\n\n\n########################\n# DEPENDECIES END HERE #\n########################\n\n# flush all libraries to provide more mem for compilation\nflush:\n        @Avail flush >nil:\n\n# write common compiler flags to file and echo to user\nCommonFlags:\n        @Echo \"$(CFLAGS)\"    >$(CFILE)\n        @Type \"$(CWITHOPT)\" >>$(CFILE)\n        -Type $(CFILE)\n\n\n# special rules for adding Amiga internal version number to amiga/amiga.c\namiga$(O):\n         rx > env:VersionDate \"say '\"\"'translate(date('E'),'.','/')'\"\"'\"\n         $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c\n         -Delete env:VersionDate\n\namiga$(OL):\n         rx > env:VersionDate \"say '\"\"'translate(date('E'),'.','/')'\"\"'\"\n         $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c\n         -Delete env:VersionDate\n\n\n# needed in amiga/amigazip.c\n# should be set in startup-sequence, but just in case:\n# (only works with OS 2.0 and above)\n\nenv\\:WorkBench:\n        @Execute < < (Workbench_smk.tmp)\n           FailAt 21\n           If not exists ENV:Workbench\n              Version >nil:\n              SetEnv Workbench $$Workbench\n           Endif\n        <\n\n\n# Read environment variable LOCAL_ZIP and convert options to SAS format\n#\n# e.g.: to define FOO_ONE and FOO_TWO enter:\n#\n# SetEnv LOCAL_ZIP \"-DFOO_ONE -DFOO_TWO\"\n#\n# Put the statement into your startup-sequence or (for AmigaDOS 2.0 or higher\n# only) make sure LOCAL_ZIP is stored in the ENVARC: directory\n# ( Copy ENV:LOCAL_ZIP ENVARC: )\n#\n\nlocal_zip:\n        @Execute < < (Local_Zip_smk.tmp)\n           Failat 21\n           If exists ENV:LOCAL_ZIP\n              Echo \"Using environment variable LOCAL_ZIP !\"\n              Copy >NIL: ENV:LOCAL_ZIP SASCOPTS\n           Else\n              Echo \"You could use envvar ZIP_OPT to set your special compilation options.\"\n              Delete >nil: SASCOPTS quiet\n           Endif\n           ; Do not remove the lctosc command! If LOCAL_ZIP is unset, an\n           ; empty file is created which needed by CommonFlags !\n           lctosc >$(CWITHOPT)\n        <\n\n\n\n# Echo request to the user\n#\nrequest:\n        @Echo \"\"\n        @Echo \" This makefile is for use with SAS/C version 6.58.\"\n        @Echo \" If you still have an older version, please upgrade!\"\n        @Echo \" Patches are available on the Aminet under biz/patch/sc\\#?.\"\n        @Echo \"\"\n        @Echo \" Just a simple request...\"\n        @Echo \" Please give me a mail that you compiled whether you encounter any errors\"\n        @Echo \" or not. I'd just like to know how many Amiga users actually make use of\"\n        @Echo \" this makefile.\"\n        @Echo \" If you mail me, I'll put you on my mailing-list and notify you whenever\"\n        @Echo \" new versions of Info-Zip are released.\"\n        @Echo \" Have a look at the makefile for changes like CPU type, UtilLib, etc.\"\n        @Echo \" Feel free to mail comments, suggestions, etc.\"\n        @Echo \" Enjoy Info-Zip !\"\n        @Echo \" Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>\"\n        @Echo \"\"\n\n\n# Echo help in case of an error\n#\n.ONERROR:\n        @Echo \"\"\n        @Echo \"[sigh] An error running this makefile was detected.\"\n        @Echo \"This message may also appear if you interrupted smake by pressing CTRL-C.\"\n        @Echo \"Contact Info-Zip authors at Zip-Bugs@lists.wku.edu or me for help.\"\n        @Echo \"Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>\"\n\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/stat.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Here we have a handmade stat() function because Aztec's c.lib stat() */\n/* does not support an st_mode field, which we need... also a chmod().  */\n\n/* This stat() is by Paul Wells, modified by Paul Kienitz. */\n/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01  */\n/* Adapted for SAS/C 6.5x by Haidinger Walter */\n\n/* POLICY DECISION: We will not attempt to remove global variables from */\n/* this source file for Aztec C.  These routines are essentially just   */\n/* augmentations of Aztec's c.lib, which is itself not reentrant.  If   */\n/* we want to produce a fully reentrant UnZip, we will have to use a    */\n/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */\n\n#ifndef __amiga_stat_c\n#define __amiga_stat_c\n\n#include <exec/types.h>\n#include <exec/memory.h>\n#include \"amiga/z-stat.h\"             /* fake version of stat.h */\n#include <string.h>\n\n#ifdef AZTEC_C\n#  include <libraries/dos.h>\n#  include <libraries/dosextens.h>\n#  include <clib/exec_protos.h>\n#  include <clib/dos_protos.h>\n#  include <pragmas/exec_lib.h>\n#  include <pragmas/dos_lib.h>\n#endif\n#ifdef __SASC\n#  include <sys/dir.h>               /* SAS/C dir function prototypes */\n#  include <sys/types.h>\n#  include <proto/exec.h>\n#  include <proto/dos.h>\n#endif\n\n#ifndef SUCCESS\n#  define SUCCESS (-1)\n#  define FAILURE (0)\n#endif\n\n\nvoid close_leftover_open_dirs(void);    /* prototype */\n\nstatic DIR *dir_cleanup_list = NULL;    /* for resource tracking */\n\n/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */\nvoid close_leftover_open_dirs(void)\n{\n    while (dir_cleanup_list)\n        closedir(dir_cleanup_list);\n}\n\n\nunsigned short disk_not_mounted;\n\nextern int stat(const char *file, struct stat *buf);\n\nstat(file,buf)\nconst char *file;\nstruct stat *buf;\n{\n\n        struct FileInfoBlock *inf;\n        BPTR lock;\n        time_t ftime;\n        struct tm local_tm;\n\n        if( (lock = Lock((char *)file,SHARED_LOCK))==0 )\n                /* file not found */\n                return(-1);\n\n        if( !(inf = (struct FileInfoBlock *)AllocMem(\n                (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )\n        {\n                UnLock(lock);\n                return(-1);\n        }\n\n        if( Examine(lock,inf)==FAILURE )\n        {\n                FreeMem((char *)inf,(long)sizeof(*inf));\n                UnLock(lock);\n                return(-1);\n        }\n\n        /* fill in buf */\n        buf->st_dev         =\n        buf->st_nlink       =\n        buf->st_uid         =\n        buf->st_gid         =\n        buf->st_rdev        = 0;\n        buf->st_ino         = inf->fib_DiskKey;\n        buf->st_blocks      = inf->fib_NumBlocks;\n        buf->st_size        = inf->fib_Size;\n\n        /* now the date.  AmigaDOS has weird datestamps---\n         *      ds_Days is the number of days since 1-1-1978;\n         *      however, as Unix wants date since 1-1-1970...\n         */\n\n        ftime =\n                (inf->fib_Date.ds_Days * 86400 )                +\n                (inf->fib_Date.ds_Minute * 60 )                 +\n                (inf->fib_Date.ds_Tick / TICKS_PER_SECOND )     +\n                (86400 * 8 * 365 )                              +\n                (86400 * 2 );  /* two leap years */\n\n        /* tzset(); */  /* this should be handled by mktime(), instead */\n        /* ftime += timezone; */\n        local_tm = *gmtime(&ftime);\n        local_tm.tm_isdst = -1;\n        ftime = mktime(&local_tm);\n\n        buf->st_ctime =\n        buf->st_atime =\n        buf->st_mtime = ftime;\n\n        buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR);\n\n        /* lastly, throw in the protection bits */\n        buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF);\n\n        FreeMem((char *)inf, (long)sizeof(*inf));\n        UnLock((BPTR)lock);\n\n        return(0);\n\n}\n\nint fstat(int handle, struct stat *buf)\n{\n    /* fake some reasonable values for stdin */\n    buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG);\n    buf->st_size = -1;\n    buf->st_mtime = time(&buf->st_mtime);\n    return 0;\n}\n\n\n/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */\n\nDIR *opendir(const char *path)\n{\n    DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC);\n    if (!dd) return NULL;\n    if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) {\n        disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED;\n        FreeMem(dd, sizeof(DIR));\n        return NULL;\n    } else\n        disk_not_mounted = 0;\n    if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) {\n        UnLock(dd->d_parentlock);\n        FreeMem(dd, sizeof(DIR));\n        return NULL;\n    }\n    dd->d_cleanuplink = dir_cleanup_list;       /* track them resources */\n    if (dir_cleanup_list)\n        dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink;\n    dd->d_cleanupparent = &dir_cleanup_list;\n    dir_cleanup_list = dd;\n    return dd;\n}\n\nvoid closedir(DIR *dd)\n{\n    if (dd) {\n        if (dd->d_cleanuplink)\n            dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent;\n        *(dd->d_cleanupparent) = dd->d_cleanuplink;\n        if (dd->d_parentlock)\n            UnLock(dd->d_parentlock);\n        FreeMem(dd, sizeof(DIR));\n    }\n}\n\nstruct dirent *readdir(DIR *dd)\n{\n    return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL);\n}\n\n\n#ifdef AZTEC_C\n\nint rmdir(const char *path)\n{\n    return (DeleteFile((char *)path) ? 0 : IoErr());\n}\n\nint chmod(const char *filename, int bits)       /* bits are as for st_mode */\n{\n    long protmask = (bits & 0xFF) ^ 0xF;\n    return !SetProtection((char *)filename, protmask);\n}\n\n\n/* This here removes unnecessary bulk from the executable with Aztec: */\nvoid _wb_parse(void)  { }\n\n/* fake a unix function that does not apply to amigados: */\nint umask(void)  { return 0; }\n\n\n#  include <signal.h>\n\n/* C library signal() messes up debugging yet adds no actual usefulness */\ntypedef void (*__signal_return_type)(int);\n__signal_return_type signal()  { return SIG_ERR; }\n\n\n/* The following replaces Aztec's argv-parsing function for compatibility with\nUnix-like syntax used on other platforms.  It also fixes the problem the\nstandard _cli_parse() has of accepting only lower-ascii characters. */\n\nint _argc, _arg_len;\nchar **_argv, *_arg_lin;\n\nvoid _cli_parse(struct Process *pp, long alen, register UBYTE *aptr)\n{\n    register UBYTE *cp;\n    register struct CommandLineInterface *cli;\n    register short c;\n    register short starred = 0;\n#  ifdef PRESTART_HOOK\n    void Prestart_Hook(void);\n#  endif\n\n    cli = (struct CommandLineInterface *) (pp->pr_CLI << 2);\n    cp = (UBYTE *) (cli->cli_CommandName << 2);\n    _arg_len = cp[0] + alen + 2;\n    if (!(_arg_lin = AllocMem((long) _arg_len, 0L)))\n        return;\n    c = cp[0];\n    strncpy(_arg_lin, cp + 1, c);\n    _arg_lin[c] = 0;\n    for (cp = _arg_lin + c + 1; alen && (*aptr < '\\n' || *aptr > '\\r'); alen--)\n        *cp++ = *aptr++;\n    *cp = 0;\n    aptr = cp = _arg_lin + c + 1;\n    for (_argc = 1; ; _argc++) {\n        while (*cp == ' ' || *cp == '\\t')\n            cp++;\n        if (!*cp)\n            break;\n        if (*cp == '\"') {\n            cp++;\n            while (c = *cp++) {\n                if (c == '\"' && !starred) {\n                    *aptr++ = 0;\n                    starred = 0;\n                    break;\n                } else if (c == '\\\\' && !starred)\n                    starred = 1;\n                else {\n                    *aptr++ = c;\n                    starred = 0;\n                }\n            }\n        } else {\n            while ((c = *cp++) && c != ' ' && c != '\\t')\n                *aptr++ = c;\n            *aptr++ = 0;\n        }\n        if (c == 0)\n            --cp;\n    }\n    *aptr = 0;\n    if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) {\n        _argc = 0;\n        return;\n    }\n    for (c = 0, cp = _arg_lin; c < _argc; c++) {\n        _argv[c] = cp;\n        cp += strlen(cp) + 1;\n    }\n    _argv[c] = NULL;\n#  ifdef PRESTART_HOOK\n    Prestart_Hook();\n#  endif\n}\n\n#endif /* AZTEC_C */\n\n#endif /* __amiga_stat_c */\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/z-stat.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __amiga_z_stat_h\n#define __amiga_z_stat_h\n\n/* Since older versions of the Lattice C compiler for Amiga, and all current */\n/* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */\n/* function or provide one inadequate for unzip (Aztec's has no st_mode      */\n/* field), we provide our own stat() function in stat.c by Paul Wells, and   */\n/* this fake stat.h file by Paul Kienitz.  Paul Wells originally used the    */\n/* Lattice stat.h but that does not work for Aztec and is not distributable  */\n/* with this package, so I made a separate one.  This has to be pulled into  */\n/* unzip.h when compiling an Amiga version, as \"amiga/z-stat.h\".             */\n\n/* We also provide here a \"struct dirent\" for use with opendir() & readdir() */\n/* functions included in amiga/stat.c.  If you use amiga/stat.c, this must   */\n/* be included wherever you use either readdir() or stat().                  */\n\n#ifdef AZTEC_C\n#  define __STAT_H\n#else  /* __SASC */\n/* do not include the following header, replacement definitions are here */\n#  define _STAT_H      /* do not include SAS/C <stat.h> */\n#  define _DIRENT_H    /* do not include SAS/C <dirent.h> */\n#  define _SYS_DIR_H   /* do not include SAS/C <sys/dir.h> */\n#  define _COMMIFMT_H  /* do not include SAS/C <sys/commifmt.h> */\n#  include <dos.h>\n#endif\n#include <libraries/dos.h>\n#include <time.h>\n\n\nstruct stat {\n    unsigned short st_mode;\n    time_t st_ctime, st_atime, st_mtime;\n    long st_size;\n    long st_ino;\n    long st_blocks;\n    short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev;\n};\n\n#define S_IFDIR  (1<<11)\n#define S_IFREG  (1<<10)\n\n#if 0\n   /* these values here are totally random: */\n#  define S_IFLNK  (1<<14)\n#  define S_IFSOCK (1<<13)\n#  define S_IFCHR  (1<<8)\n#  define S_IFIFO  (1<<7)\n#  define S_IFMT   (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK)\n#else\n#  define S_IFMT   (S_IFDIR|S_IFREG)\n#endif\n\n#define S_IHIDDEN    (1<<7)\n#define S_ISCRIPT    (1<<6)\n#define S_IPURE      (1<<5)\n#define S_IARCHIVE   (1<<4)\n#define S_IREAD      (1<<3)\n#define S_IWRITE     (1<<2)\n#define S_IEXECUTE   (1<<1)\n#define S_IDELETE    (1<<0)\n\nint stat(const char *name, struct stat *buf);\nint fstat(int handle, struct stat *buf);      /* returns dummy values */\n\ntypedef struct dirent {\n    struct dirent       *d_cleanuplink,\n                       **d_cleanupparent;\n    BPTR                 d_parentlock;\n    struct FileInfoBlock d_fib;\n} DIR;\n#define                  d_name  d_fib.fib_FileName\n\nextern unsigned short disk_not_mounted;         /* flag set by opendir() */\n\nDIR *opendir(const char *);\nvoid closedir(DIR *);\nvoid close_leftover_open_dirs(void);    /* call this if aborted in mid-run */\nstruct dirent *readdir(DIR *);\nint umask(void);\n\n#ifdef AZTEC_C\nint rmdir(const char *);\nint chmod(const char *filename, int bits);\n#endif\n\n#endif /* __amiga_z_stat_h */\n"
  },
  {
    "path": "deps/infozip/zip30/amiga/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef __amiga_zipup_h\n#define __amiga_zipup_h\n\n#ifndef O_RAW\n#  define O_RAW      0\n#endif\n#define fhow         (O_RDONLY | O_RAW)\n#define fbad         (-1)\ntypedef int          ftype;\n#define zopen(n,p)   open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f)    close(f)\n#define zerr(f)      (k == (extent)(-1L))\n#define zstdin       0\n\n#endif /* __amiga_zipup_h */\n\n"
  },
  {
    "path": "deps/infozip/zip30/aosvs/aosvs.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include <dirent.h>\n#include <time.h>\n\n#include \"zip.h\"\n#include <paru.h>                 /* parameter definitions */\n#include <sys_calls.h>            /* AOS/VS system call interface */\n#include <packets/filestatus.h>   /* AOS/VS ?FSTAT packet defs */\n\n#ifndef UTIL            /* AOS/VS specific fileio code not needed for UTILs */\n\n#define PAD 0\n#define PATH_END ':'\n\n/*\n * could probably avoid the union -\n * all are same size & we're going to assume this\n */\ntypedef union zvsfstat_stru\n{\n     P_FSTAT        norm_fstat_packet;      /* normal fstat packet */\n     P_FSTAT_DIR    dir_fstat_packet;       /* DIR/CPD fstat packet */\n     P_FSTAT_UNIT   unit_fstat_packet;      /* unit (device) fstat packet */\n     P_FSTAT_IPC    ipc_fstat_packet;       /* IPC file fstat packet */\n} ZVSFSTAT_STRU;\n\ntypedef struct zextrafld\n{\n     char           extra_header_id[2]; /* set to VS - in theory, an int */\n     char           extra_data_size[2]; /* size of rest, in Intel little-endian order */\n     char           extra_sentinel[4];  /* set to FCI w/ trailing null */\n     unsigned char  extra_rev;          /* set to 10 for rev 1.0 */\n     ZVSFSTAT_STRU  fstat_packet;       /* the fstat packet */\n     char           aclbuf[$MXACL];     /* raw ACL, or link-resolution name */\n} ZEXTRAFLD;\n\n#define ZEXTRA_HEADID   \"VS\"\n#define ZEXTRA_SENTINEL \"FCI\"\n#define ZEXTRA_REV      (unsigned char) 10\n\nlocal ZEXTRAFLD   zzextrafld;         /* buffer for extra field containing\n                                         ?FSTAT packet & ACL buffer */\nlocal char        zlinkres[$MXPL];    /* buf for link resolution contents */\nlocal char        znamebuf[$MXPL];    /* buf for AOS/VS filename */\nstatic char     vsnamebuf[$MXPL];\nstatic char     uxnamebuf[FNMAX];\nstatic P_FSTAT  vsfstatbuf;\n\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\n\nchar *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *strlower(s)\nchar *s;                /* string to convert */\n/* Convert all uppercase letters to lowercase in string s */\n{\n  char *p;              /* scans string */\n\n  for (p = s; *p; p++)\n    if (*p >= 'A' && *p <= 'Z')\n      *p += 'a' - 'A';\n  return s;\n}\n\nchar *strupper(s)\nchar *s;                /* string to convert */\n/* Convert all lowercase letters to uppercase in string s */\n{\n  char *p;              /* scans string */\n\n  for (p = s; *p; p++)\n    if (*p >= 'a' && *p <= 'z')\n      *p -= 'a' - 'A';\n  return s;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  dosflag = dosify; /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for (t = x; *t == '/'; t++)\n    ;\n\n  if (*t == '=')                /* AOS/VS for ./ */\n    t++;\n  else if (*t == ':')           /* AOS/VS for / */\n    t++;\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  if (*t == '^')        /* AOS/VS for ../ */\n  {\n    if ((n = malloc(strlen(t) + 3)) == NULL)\n      return NULL;\n    strcpy(n, \"../\");\n    strcpy(n + 3, t + 1);\n  }\n  else if (*t == '@')   /* AOS/VS for :PER:, kind of like /dev/ */\n  {\n    if ((n = malloc(strlen(t) + 5)) == NULL)\n      return NULL;\n    strcpy(n, \"/PER/\");\n    strcpy(n + 5, t + 1);\n  }\n  else\n  {\n    if ((n = malloc(strlen(t) + 1)) == NULL)\n      return NULL;\n    strcpy(n, t);\n  }\n  /* now turn AOS/VS dir separators (colons) into slashes */\n  for (t = n;  *t != '\\0';  t++)\n    if (*t == ':')\n      *t = '/';\n  /*\n   * Convert filename to uppercase (for correct matching).\n   * (It may make more sense to patch the matching code, since\n   * we may want those filenames in uppercase on the target system,\n   * but this seems better at present.  If we're converting, uppercase\n   * also seems to make sense.)\n   */\n  strupper(n);\n\n\n  if (dosify)\n    msname(n);\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n  strcpy(x, n);\n\n  return x;\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  time_t u[2];          /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u */\n  u[0] = u[1] = dos2unixtime(d);\n  utime(f, u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0)\n      error(\"fstat(stdin)\");\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFDIR) != 0) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime(&s.st_ctime);\n}\n\nint deletedir(d)\nchar *d;\n{\n   return rmdir(d);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n  /* NOTE: this AOS/VS version assumes the pathname in z->name is an\n   * AOS/VS pathname, not a unix-style one.  Since you can zip up using\n   * unix-style pathnames, this may create problems occasionally.\n   * We COULD add code to parse back to AOS/VS format ...\n   * (This might also fail for other reasons such as access denied, but\n   * that should already have occurred.)\n   * We set the central-dir extra fld pointer & length here to the same data.\n   */\n{\n  int             aclend = 0;\n/*\n * use this to simplify because different calls depending on\n * whether links are resolved\n */\n  unsigned short  errc;\n\n  z->ext = 0;               /* init to no extra field */\n/* get the ?FSTAT info & the acl - if no errors, get memory & store.\n * (first, we have to cut off the trailing slash that was added if\n * it's a dir, since AOS/VS doesn't accept that kind of thing)\n */\n  strncpy(znamebuf, z->name, $MXPL);\n  znamebuf[$MXPL-1] = '\\0';\n  if (znamebuf[strlen(znamebuf)-1] == '/')\n    znamebuf[strlen(znamebuf)-1] = '\\0';\n  if (linkput)\n    errc = sys_fstat(znamebuf, BIT1, &(zzextrafld.fstat_packet));\n  else\n    errc = sys_fstat(znamebuf, 0, &(zzextrafld.fstat_packet));\n  if (errc)\n  {\n    fprintf(stderr,\n            \"\\n    Warning: can't get ?FSTAT info & acl of %s - error %d\\n    \",\n            znamebuf, errc);\n    perror(\"sys_fstat()\");\n  }\n  else\n  {\n    /* store the ACL - or, if a link (no ACL!), store the resolution name */\n    if (zzextrafld.fstat_packet.norm_fstat_packet.styp_type != $FLNK)\n    {\n      if ((errc = sys_gacl(znamebuf, zzextrafld.aclbuf)) != 0)\n      {\n        fprintf(stderr, \"\\n    Warning: can't get acl of %s - error %d\\n    \",\n                z->name, errc);\n        perror(\"sys_gacl()\");\n      }\n      else\n      {\n        /* find length of ACL - ends with double-null */\n        while (aclend++ < $MXACL  &&\n               (zzextrafld.aclbuf[aclend - 1] != '\\0'  ||\n                zzextrafld.aclbuf[aclend] != '\\0'))\n          /* EMPTY LOOP */ ;\n        if ((z->cextra = z->extra =\n             malloc(sizeof(ZEXTRAFLD) - $MXACL + aclend + 4)) != NULL)\n        {\n          strncpy(zzextrafld.extra_header_id, ZEXTRA_HEADID,\n                  sizeof(zzextrafld.extra_header_id));\n          strncpy(zzextrafld.extra_sentinel, ZEXTRA_SENTINEL,\n                  sizeof(zzextrafld.extra_sentinel));\n          zzextrafld.extra_rev = ZEXTRA_REV;    /* this is a char, no need\n                                                   to worry about byte order */\n          /* set size (Intel (little-endian)) 2-byte int, which we've set\n             as array to make it easier */\n          errc = (unsigned short) (sizeof(ZEXTRAFLD) - $MXACL + aclend + 4 -\n                                   sizeof(zzextrafld.extra_header_id) -\n                                   sizeof(zzextrafld.extra_data_size));\n          zzextrafld.extra_data_size[0] = errc & 0xFF;  /* low-order byte */\n          zzextrafld.extra_data_size[1] = errc >> 8;    /* high-order byte */\n          memcpy((char *) z->extra, (char *) &zzextrafld,\n                 sizeof(ZEXTRAFLD) - $MXACL + aclend + 4);\n          z->cext = z->ext = sizeof(ZEXTRAFLD) - $MXACL + aclend + 4;\n        }\n      }\n    }\n    else /* a link */\n    {\n      if ((errc = sys_glink(z->name, zzextrafld.aclbuf)) != 0)\n      {\n        fprintf(stderr,\n              \"\\n    Warning: can't get link-resolution of %s - error %d\\n    \",\n                z->name, errc);\n        perror(\"sys_glink()\");\n      }\n      else\n      {\n        aclend = strlen(zzextrafld.aclbuf) + 1;\n        if ((z->extra = malloc(sizeof(ZEXTRAFLD) - $MXACL + aclend + 4))\n            != NULL)\n        {\n          strncpy(zzextrafld.extra_header_id, ZEXTRA_HEADID,\n                  sizeof(zzextrafld.extra_header_id));\n          strncpy(zzextrafld.extra_sentinel, ZEXTRA_SENTINEL,\n                  sizeof(zzextrafld.extra_sentinel));\n          zzextrafld.extra_rev = ZEXTRA_REV;    /* this is a char, no need\n                                                   to worry about byte order */\n          /* set size (Intel (little-endian)) 2-byte int, which we've set\n             as array to make it easier */\n          errc = (unsigned short) (sizeof(ZEXTRAFLD) - $MXACL + aclend + 4 -\n                                   sizeof(zzextrafld.extra_header_id) -\n                                   sizeof(zzextrafld.extra_data_size));\n          zzextrafld.extra_data_size[0] = errc & 0xFF;  /* low-order byte */\n          zzextrafld.extra_data_size[1] = errc >> 8;    /* high-order byte */\n          memcpy((char *) z->extra, (char *) &zzextrafld,\n                 sizeof(ZEXTRAFLD) - $MXACL + aclend + 4);\n          z->ext = sizeof(ZEXTRAFLD) - $MXACL + aclend + 4;\n        }\n      }\n    }\n  }\n  return ZE_OK;\n}\n\n#endif /* !UTIL */\n\nvoid version_local()\n{\n    printf(\"Compiled with %s under %s.\\n\",\n      \"a C compiler\",\n      \"AOS/VS\"\n    );\n}\n\n\n/*\n * This file defines for AOS/VS two Unix functions relating to links;\n * the calling code should have the following defines:\n *\n *    #define       lstat(path,buf)             zvs_lstat(path,buf)\n *    #define       readlink(path,buf,nbytes)   zvs_readlink(path,buf,nbytes)\n *\n * For these functions, I'm going to define yet 2 MORE filename buffers\n * and also insert code to change pathnames to Unix & back.  This is\n * easier than changing all the other places this kind of thing happens to\n * be efficient.  This is a kludge.  I'm also going to put the functions\n * here for my immediate convenience rather than somewhere else for\n * someone else's.\n *\n * WARNING: the use of static buffers means that you'd better get your\n * data out of these buffers before the next call to any of these functions!\n *\n */\n\n/* =========================================================================\n * ZVS_LSTAT() - get (or simulate) stat information WITHOUT following symlinks\n *      This is intended to look to the outside like the unix lstat()\n *      function.  We do a quick-&-dirty filename conversion.\n *\n *      If the file is NOT a symbolic link, we can just do a stat() on it and\n *      that should be fine.  But if it IS a link, we have to set the elements\n *      of the stat struct ourselves, since AOS/VS doesn't have a built-in\n *      lstat() function.\n *\n *      RETURNS: 0 on success, or -1 otherwise\n *\n */\n\nint zvs_lstat(char *path, struct stat *buf)\n{\n    char        *cp_vs = vsnamebuf;\n    char        *cp_ux = path;\n    int         mm, dd, yy;\n\n    /*\n     * Convert the Unix pathname to an AOS/VS pathname.\n     * This is quick & dirty; it won't handle (for instance) pathnames with\n     * ../ in the middle of them, and may choke on other Unixisms.  We hope\n     * they're unlikely.\n     */\n    if (!strncmp(cp_ux, \"../\", 3))\n    {\n        *cp_vs++ = '^';        /* AOS/VS for ../ */\n        cp_ux += 3;\n    }\n    else if (!strncmp(cp_ux, \"./\", 2))\n    {\n        *cp_vs++ = '=';        /* AOS/VS for ./ */\n        cp_ux += 2;\n    }\n\n    do\n    {\n        if (*cp_ux == '/')\n        {\n            *cp_vs++ = ':';\n        }\n        else\n        {\n            *cp_vs++ = (char) toupper(*cp_ux);\n        }\n\n    } while (*cp_ux++ != '\\0'  &&  cp_vs - vsnamebuf < sizeof(vsnamebuf));\n\n    /* If Unix name was too long for our buffer, return an error return */\n    if (cp_vs - vsnamebuf >= sizeof(vsnamebuf)  &&  *(cp_vs - 1) != '\\0')\n        return (-1);     /* error */\n\n    /* Make AOS/VS ?FSTAT call that won't follow links & see if we find\n     * anything.  If not, we return error.\n     */\n    if (sys_fstat(vsnamebuf,\n                  BIT1,                 /* BIT1 says to not resolve links */\n                  &vsfstatbuf))\n        return (-1);     /* error */\n\n    /* If we DID find the file but it's not a link,\n     * call stat() and return its value.\n     */\n    if (vsfstatbuf.styp_type != $FLNK)\n        return (stat(path, buf));        /* call with Unix pathname ... */\n\n    /* Otherwise, we have to kludge up values for the stat structure */\n    memset((char *) buf, 0, sizeof(*buf));   /* init to nulls (0 values) */\n    buf->st_mode = S_IFLNK | 0777;           /* link and rwxrwxrwx */\n    buf->st_uid = -1;                        /* this is what we get on AOS/VS\n                                                anyway (maybe unless we set up\n                                                a dummy password file?) */\n    buf->st_nlink = 1;\n    /* The DG date we've got is days since 12/31/67 and seconds/2.  So we\n     * need to subtract 732 days (if that's not negative), convert to seconds,\n     * and add adjusted seconds.\n     */\n    if (vsfstatbuf.stch.short_time[0] < 732)\n        buf->st_ctime = buf->st_mtime = buf->st_atime = 0L;\n    else\n    {\n        buf->st_ctime = buf->st_mtime = buf->st_atime =\n                ((long) vsfstatbuf.stch.short_time[0] - 732L) * 24L * 3600L +\n                2L * (long) vsfstatbuf.stch.short_time[1];\n    }\n\n    /* And we need to get the filename linked to and use its length as\n     * the file size.  We'll use the Unix pathname buffer for this - hope\n     * it's big enough.  (We won't overwrite anything, but we could get a\n     * truncated path.)  If there's an error, here's our last chance to\n     * say anything.\n     */\n    if ((buf->st_size = zvs_readlink(vsnamebuf, uxnamebuf, FNMAX)) < 0)\n        return (-1);\n    else\n        return (0);\n\n} /* end zvs_lstat() */\n\n/* =========================================================================\n * ZVS_READLINK() - get pathname pointed to by an AOS/VS link file\n *      This is intended to look to the outside like the unix readlink()\n *      function.  We do a quick-&-dirty filename conversion.\n *\n *      RETURNS: the length of the output path (in bytes), or -1 if an error\n *\n */\n\nint zvs_readlink(char *path, char *buf, int nbytes)\n{\n    char    *cp_vs = vsnamebuf;\n    char    *cp_ux = buf;\n\n    /* This is called with z->name, the filename the user gave, so we'll get\n     * the link-resolution name on the assumption that it's a valid AOS/VS\n     * name. We're also assuming a reasonable value (> 5) for nbytes.\n     */\n    if (sys_glink(path, vsnamebuf))\n        return (-1);     /* readlink() is supposed to return -1 on error */\n\n    /* Now, convert the AOS/VS pathname to a Unix pathname.\n     * Note that sys_glink(), unlike readlink(), does add a null.\n     */\n    if (*cp_vs == '^')        /* AOS/VS for ../ */\n    {\n        strncpy(cp_ux, \"../\", 3);\n        cp_ux += 3;\n        cp_vs++;\n    }\n    else if (*cp_vs == '@')   /* AOS/VS for :PER:, kind of like /dev/ */\n    {\n        strncpy(cp_ux, \"/PER/\", 5);\n        cp_ux += 5;\n        cp_vs++;\n    }\n    else if (*cp_vs == '=')   /* AOS/VS for ./ */\n    {\n        strncpy(cp_ux, \"./\", 2);\n        cp_ux += 2;\n        cp_vs++;\n    }\n    while (*cp_vs != '\\0'  &&  cp_ux - buf < nbytes)\n    {\n        if (*cp_vs == ':')\n        {\n            *cp_ux++ = '/';\n        }\n        else\n        {\n            *cp_ux++ = (char) toupper(*cp_vs);\n        }\n        cp_vs++;\n    }\n\n    return (cp_ux - buf);   /* # characters in Unix path (no trailing null) */\n\n} /* end zvs_readlink() */\n"
  },
  {
    "path": "deps/infozip/zip30/aosvs/make.cli",
    "content": "push\nprompt pop\nsea :c_4.10 :c_4.10:lang_rt [!sea]\ncc%0/%/link/NOUNX AOS_VS/DEFINE NODIR/DEFINE <ZIP CRC32 CRYPT DEFLATE FILEIO GLOBALS MKTIME TREES TTYIO UTIL ZIPFILE ZIPUP AOSVS>.C\npop\n"
  },
  {
    "path": "deps/infozip/zip30/api.c",
    "content": "/*\n  api.c - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  api.c\n\n  This module supplies a Zip dll engine for use directly from C/C++\n  programs.\n\n  The entry points are:\n\n    ZpVer *ZpVersion(void);\n    int EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc);\n    int EXPENTRY ZpArchive(ZCL C, LPZPOPT Opts);\n\n  This module is currently only used by the Windows dll, and is not used at\n  all by any of the other platforms, although it should be easy enough to\n  implement this on most platforms.\n\n  ---------------------------------------------------------------------------*/\n#define __API_C\n\n#include <malloc.h>\n#ifdef WINDLL\n#  include <windows.h>\n#  include \"windll/windll.h\"\n#endif\n\n#ifdef OS2\n#  define  INCL_DOSMEMMGR\n#  include <os2.h>\n#endif\n\n#ifdef __BORLANDC__\n#include <dir.h>\n#endif\n#include <direct.h>\n#include <ctype.h>\n#include \"api.h\"                /* this includes zip.h */\n#include \"crypt.h\"\n#include \"revision.h\"\n#ifdef USE_ZLIB\n#  include \"zlib.h\"\n#endif\n\n\nDLLPRNT *lpZipPrint;\nDLLPASSWORD *lpZipPassword;\nextern DLLCOMMENT *lpComment;\nZIPUSERFUNCTIONS ZipUserFunctions, far * lpZipUserFunctions;\n\nint ZipRet;\nchar szOrigDir[PATH_MAX];\nBOOL fNo_int64 = FALSE; /* flag for DLLSERVICE_NO_INT64 */\n\n/* Local forward declarations */\nextern int  zipmain OF((int, char **));\nint AllocMemory(unsigned int, char *, char *, BOOL);\nint ParseString(LPSTR, unsigned int);\nvoid FreeArgVee(void);\n\nZPOPT Options;\nchar **argVee;\nunsigned int argCee;\n\n/*---------------------------------------------------------------------------\n    Local functions\n  ---------------------------------------------------------------------------*/\n\nchar szRootDir[PATH_MAX], szExcludeList[PATH_MAX], szIncludeList[PATH_MAX], szTempDir[PATH_MAX];\n\nint ParseString(LPSTR s, unsigned int ArgC)\n{\nunsigned int i;\nint root_flag, m, j;\nchar *str1, *str2, *str3;\nsize_t size;\n\ni = ArgC;\nstr1 = (char *) malloc(lstrlen(s)+4);\nlstrcpy(str1, s);\nlstrcat(str1, \" @\");\n\nif ((szRootDir != NULL) && (szRootDir[0] != '\\0'))\n    {\n    root_flag = TRUE;\n    if (szRootDir[lstrlen(szRootDir)-1] != '\\\\')\n        lstrcat(szRootDir, \"\\\\\");\n    }\nelse\n    root_flag = FALSE;\n\nstr2 = strchr(str1, '\\\"'); /* get first occurance of double quote */\n\nwhile ((str3 = strchr(str1, '\\t')) != NULL)\n    {\n    str3[0] = ' '; /* Change tabs into a single space */\n    }\n\n/* Note that if a quoted string contains multiple adjacent spaces, they\n   will not be removed, because they could well point to a valid\n   folder/file name.\n*/\nwhile ((str2 = strchr(str1, '\\\"')) != NULL)\n    /* Found a double quote if not NULL */\n    {\n    str3 = strchr(str2+1, '\\\"'); /* Get the second quote */\n    if (str3 == NULL)\n        {\n        free(str1);\n        return ZE_PARMS; /* Something is screwy with the\n                            string, bail out */\n        }\n    str3[0] = '\\0';  /* terminate str2 with a NULL */\n\n    /* strip unwanted fully qualified path from entry */\n    if (root_flag)\n        if ((_strnicmp(szRootDir, str2+1, lstrlen(szRootDir))) == 0)\n            {\n            m = 0;\n            str2++;\n            for (j = lstrlen(szRootDir); j < lstrlen(str2); j++)\n                str2[m++] = str2[j];\n            str2[m] = '\\0';\n            str2--;\n            }\n    size = _msize(argVee);\n    if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n        {\n        fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n        return ZE_MEM;\n        }\n    /* argCee is incremented in AllocMemory */\n    if (AllocMemory(i, str2+1, \"Creating file list from string\", TRUE) != ZE_OK)\n        {\n        free(str1);\n        return ZE_MEM;\n        }\n    i++;\n    str3+=2;        /* Point past the whitespace character */\n    str2[0] = '\\0'; /* Terminate str1 */\n    lstrcat(str1, str3);\n    }    /* end while */\n\n/* points to first occurance of a space */\nstr2 = strchr(str1, ' ');\n\n/*  Go through the string character by character, looking for instances\n    of two spaces together. Terminate when you find the trailing @\n*/\nwhile ((str2[0] != '\\0') && (str2[0] != '@'))\n    {\n    while ((str2[0] == ' ') && (str2[1] == ' '))\n        {\n        str3 = &str2[1];\n        str2[0] = '\\0';\n        lstrcat(str1, str3);\n        }\n    str2++;\n    }\n\n/* Do we still have a leading space? */\nif (str1[0] == ' ')\n    {\n    str3 = &str1[1];\n    lstrcpy(str1, str3); /* Dump the leading space */\n    }\n\n\n/* Okay, now we have gotten rid of any tabs and replaced them with\n   spaces, and have replaced multiple spaces with a single space. We\n   couldn't do this before because the folder names could have actually\n   contained these characters.\n*/\n\nstr2 = str3 = str1;\n\nwhile ((str2[0] != '\\0') && (str3[0] != '@'))\n    {\n    str3 = strchr(str2+1, ' ');\n    str3[0] = '\\0';\n    /* strip unwanted fully qualified path from entry */\n    if (root_flag)\n        if ((_strnicmp(szRootDir, str2, lstrlen(szRootDir))) == 0)\n           {\n            m = 0;\n            for (j = lstrlen(Options.szRootDir); j < lstrlen(str2); j++)\n            str2[m++] = str2[j];\n            str2[m] = '\\0';\n            }\n    size = _msize(argVee);\n    if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n        {\n        fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n        return ZE_MEM;\n        }\n    if (AllocMemory(i, str2, \"Creating file list from string\", TRUE) != ZE_OK)\n        {\n        free(str1);\n        return ZE_MEM;\n        }\n    i++;\n    str3++;\n    str2 = str3;\n    }\nfree(str1);\nreturn ZE_OK;\n}\n\nint AllocMemory(unsigned int i, char *cmd, char *str, BOOL IncrementArgCee)\n{\nif ((argVee[i] = (char *) malloc( sizeof(char) * strlen(cmd)+1 )) == NULL)\n   {\n   if (IncrementArgCee)\n       argCee++;\n   FreeArgVee();\n   fprintf(stdout, \"Unable to allocate memory in zip library at %s\\n\", str);\n   return ZE_MEM;\n   }\nstrcpy( argVee[i], cmd );\nargCee++;\nreturn ZE_OK;\n}\n\nvoid FreeArgVee(void)\n{\nunsigned i;\n\n/* Free the arguments in the array */\nfor (i = 0; i < argCee; i++)\n    {\n    free (argVee[i]);\n    argVee[i] = NULL;\n    }\n/* Then free the array itself */\nfree(argVee);\n\n/* Restore the original working directory */\nchdir(szOrigDir);\n#ifdef __BORLANDC__\nsetdisk(toupper(szOrigDir[0]) - 'A');\n#endif\n\n}\n\n\n/*---------------------------------------------------------------------------\n    Documented API entry points\n  ---------------------------------------------------------------------------*/\n\nint EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc)\n{\nZipUserFunctions = *lpZipUserFunc;\nlpZipUserFunctions = &ZipUserFunctions;\n\nif (!lpZipUserFunctions->print ||\n    !lpZipUserFunctions->comment)\n    return FALSE;\n\nreturn TRUE;\n}\n\nint EXPENTRY ZpArchive(ZCL C, LPZPOPT Opts)\n/* Add, update, freshen, or delete zip entries in a zip file.  See the\n   command help in help() zip.c */\n{\nint k, j, m;\nsize_t size;\n\nOptions = *Opts; /* Save off options, and make them available locally */\nszRootDir[0] = '\\0';\nszExcludeList[0] = '\\0';\nszIncludeList[0] = '\\0';\nszTempDir[0] = '\\0';\nif (Options.szRootDir) lstrcpy(szRootDir, Options.szRootDir);\nif (Options.szExcludeList) lstrcpy(szExcludeList, Options.szExcludeList);\nif (Options.szIncludeList) lstrcpy(szIncludeList, Options.szIncludeList);\nif (Options.szTempDir) lstrcpy(szTempDir, Options.szTempDir);\n\ngetcwd(szOrigDir, PATH_MAX); /* Save current drive and directory */\n\nif ((szRootDir != NULL) && (szRootDir[0] != '\\0'))\n   {\n   /* Make sure there isn't a trailing slash */\n   if (szRootDir[lstrlen(szRootDir)-1] == '\\\\')\n       szRootDir[lstrlen(szRootDir)-1] = '\\0';\n\n   chdir(szRootDir);\n#ifdef __BORLANDC__\n   setdisk(toupper(szRootDir[0]) - 'A');\n#endif\n   }\n\nargCee = 0;\n\n/* malloc additional 40 to allow for additional command line arguments. Note\n   that we are also adding in the count for the include lists as well as the\n   exclude list. */\nif ((argVee = (char **)malloc((C.argc+40)*sizeof(char *))) == NULL)\n   {\n   fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n   return ZE_MEM;\n   }\nif ((argVee[argCee] = (char *) malloc( sizeof(char) * strlen(\"wiz.exe\")+1 )) == NULL)\n   {\n   free(argVee);\n   fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n   return ZE_MEM;\n   }\nstrcpy( argVee[argCee], \"wiz.exe\" );\nargCee++;\n\n\n/* Set compression level efficacy -0...-9 */\nif (AllocMemory(argCee, \"-0\", \"Compression\", FALSE) != ZE_OK)\n    return ZE_MEM;\n\n/* Check to see if the compression level is set to a valid value. If\n not, then set it to the default.\n*/\nif ((Options.fLevel < '0') || (Options.fLevel > '9'))\n    {\n    Options.fLevel = '6';\n    if (!Options.fDeleteEntries)\n        fprintf(stdout, \"Compression level set to invalid value. Setting to default\\n\");\n    }\n\nargVee[argCee-1][1] = Options.fLevel;\n\nif (Options.fOffsets)    /* Update offsets for SFX prefix */\n   {\n   if (AllocMemory(argCee, \"-A\", \"Offsets\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.fDeleteEntries)    /* Delete files from zip file -d */\n   {\n   if (AllocMemory(argCee, \"-d\", \"Delete\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fNoDirEntries) /* Do not add directory entries -D */\n   {\n        if (AllocMemory(argCee, \"-D\", \"No Dir Entries\", FALSE) != ZE_OK)\n            return ZE_MEM;\n   }\nif (Options.fFreshen) /* Freshen zip file--overwrite only -f */\n   {\n   if (AllocMemory(argCee, \"-f\", \"Freshen\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fRepair)  /* Fix archive -F or -FF */\n   {\n   if (Options.fRepair == 1)\n      {\n      if (AllocMemory(argCee, \"-F\", \"Repair\", FALSE) != ZE_OK)\n          return ZE_MEM;\n      }\n   else\n      {\n      if (AllocMemory(argCee, \"-FF\", \"Repair\", FALSE) != ZE_OK)\n        return ZE_MEM;\n      }\n   }\nif (Options.fGrow) /* Allow appending to a zip file -g */\n   {\n   if (AllocMemory(argCee, \"-g\", \"Appending\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fJunkDir) /* Junk directory names -j */\n   {\n   if (AllocMemory(argCee, \"-j\", \"Junk Dir Names\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fEncrypt) /* encrypt -e */\n   {\n   if (AllocMemory(argCee, \"-e\", \"Encrypt\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fJunkSFX) /* Junk sfx prefix */\n   {\n   if (AllocMemory(argCee, \"-J\", \"Junk SFX\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n\nif (Options.fForce) /* Make entries using DOS names (k for Katz) -k */\n   {\n   if (AllocMemory(argCee, \"-k\", \"Force DOS\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n\nif (Options.fLF_CRLF) /* Translate LF_CRLF -l */\n   {\n   if (AllocMemory(argCee, \"-l\", \"LF-CRLF\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fCRLF_LF) /* Translate CR/LF to LF -ll */\n   {\n   if (AllocMemory(argCee, \"-ll\", \"CRLF-LF\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fMove) /* Delete files added to or updated in zip file -m */\n   {\n   if (AllocMemory(argCee, \"-m\", \"Move\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n\nif (Options.fLatestTime) /* Set zip file time to time of latest file in it -o */\n   {\n   if (AllocMemory(argCee, \"-o\", \"Time\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n\nif (Options.fComment) /* Add archive comment \"-z\" */\n   {\n   if (AllocMemory(argCee, \"-z\", \"Comment\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n\nif (Options.fQuiet) /* quiet operation -q */\n   {\n   if (AllocMemory(argCee, \"-q\", \"Quiet\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fRecurse == 1) /* recurse into subdirectories -r */\n   {\n   if (AllocMemory(argCee, \"-r\", \"Recurse -r\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nelse if (Options.fRecurse == 2) /* recurse into subdirectories -R */\n   {\n   if (AllocMemory(argCee, \"-R\", \"Recurse -R\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fSystem)  /* include system and hidden files -S */\n   {\n   if (AllocMemory(argCee, \"-S\", \"System\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\nif (Options.fExcludeDate)    /* Exclude files newer than specified date -tt */\n   {\n     if ((Options.Date != NULL) && (Options.Date[0] != '\\0'))\n        {\n        if (AllocMemory(argCee, \"-tt\", \"Date\", FALSE) != ZE_OK)\n            return ZE_MEM;\n        if (AllocMemory(argCee, Options.Date, \"Date\", FALSE) != ZE_OK)\n            return ZE_MEM;\n        }\n   }\n\nif (Options.fIncludeDate)    /* include files newer than specified date -t */\n   {\n     if ((Options.Date != NULL) && (Options.Date[0] != '\\0'))\n        {\n        if (AllocMemory(argCee, \"-t\", \"Date\", FALSE) != ZE_OK)\n            return ZE_MEM;\n       if (AllocMemory(argCee, Options.Date, \"Date\", FALSE) != ZE_OK)\n            return ZE_MEM;\n        }\n   }\n\nif (Options.fUpdate) /* Update zip file--overwrite only if newer -u */\n    {\n    if (AllocMemory(argCee, \"-u\", \"Update\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.fVerbose)  /* Mention oddities in zip file structure -v */\n    {\n    if (AllocMemory(argCee, \"-v\", \"Verbose\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.fVolume)  /* Include volume label -$ */\n    {\n    if (AllocMemory(argCee, \"-$\", \"Volume\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.szSplitSize != NULL)   /* Turn on archive splitting */\n    {\n    if (AllocMemory(argCee, \"-s\", \"Splitting\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    if (AllocMemory(argCee, Options.szSplitSize, \"Split size\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (lpZipUserFunctions->split != NULL)   /* Turn on archive split destinations select */\n    {\n    if (AllocMemory(argCee, \"-sp\", \"Split Pause Select Destination\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\n#ifdef WIN32\nif (Options.fPrivilege)  /* Use privileges -! */\n   {\n   if (AllocMemory(argCee, \"-!\", \"Privileges\", FALSE) != ZE_OK)\n        return ZE_MEM;\n   }\n#endif\nif (Options.fExtra)  /* Exclude extra attributes -X */\n    {\n    if (AllocMemory(argCee, \"-X\", \"Extra\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.IncludeList != NULL) /* Include file list -i */\n    {\n    if (AllocMemory(argCee, \"-i\", \"Include file list\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    k = 0;\n    if (Options.IncludeListCount > 0)\n        while ((Options.IncludeList[k] != NULL) && (Options.IncludeListCount != k+1))\n            {\n            size = _msize(argVee);\n            if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n                {\n                fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n                return ZE_MEM;\n                }\n            if (AllocMemory(argCee, Options.IncludeList[k], \"Include file list array\", TRUE) != ZE_OK)\n                {\n                return ZE_MEM;\n                }\n            k++;\n            }\n    else\n        while (Options.IncludeList[k] != NULL)\n            {\n            size = _msize(argVee);\n            if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n                {\n                FreeArgVee();\n                fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n                return ZE_MEM;\n                }\n            if (AllocMemory(argCee, Options.IncludeList[k], \"Include file list array\", TRUE) != ZE_OK)\n                return ZE_MEM;\n            k++;\n            }\n\n    if (AllocMemory(argCee, \"@\", \"End of Include List\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (Options.ExcludeList != NULL)  /* Exclude file list -x */\n    {\n    if (AllocMemory(argCee, \"-x\", \"Exclude file list\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    k = 0;\n    if (Options.ExcludeListCount > 0)\n        while ((Options.ExcludeList[k] != NULL) && (Options.ExcludeListCount != k+1))\n            {\n            size = _msize(argVee);\n            if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n                {\n                fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n                return ZE_MEM;\n                }\n            if (AllocMemory(argCee, Options.ExcludeList[k], \"Exclude file list array\", TRUE) != ZE_OK)\n                return ZE_MEM;\n            k++;\n            }\n    else\n        while (Options.ExcludeList[k] != NULL)\n            {\n            size = _msize(argVee);\n            if ((argVee = (char **)realloc(argVee, size + sizeof(char *))) == NULL)\n                {\n                FreeArgVee();\n                fprintf(stdout, \"Unable to allocate memory in zip dll\\n\");\n                return ZE_MEM;\n                }\n            if (AllocMemory(argCee, Options.ExcludeList[k], \"Exclude file list array\", TRUE) != ZE_OK)\n                return ZE_MEM;\n            k++;\n            }\n   if (AllocMemory(argCee, \"@\", \"End of Exclude List\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\n\nif (szIncludeList != NULL && szIncludeList[0] != '\\0') /* Include file list -i */\n    {\n    if (AllocMemory(argCee, \"-i\", \"Include file list\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    if ((k = ParseString(szIncludeList, argCee)) != ZE_OK)\n        return k;  /* Something was screwy with the parsed string\n                      bail out */\n    if (AllocMemory(argCee, \"@\", \"End of Include List\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\nif (szExcludeList != NULL && szExcludeList[0] != '\\0')  /* Exclude file list -x */\n    {\n    if (AllocMemory(argCee, \"-x\", \"Exclude file list\", FALSE) != ZE_OK)\n        return ZE_MEM;\n\n    if ((k = ParseString(szExcludeList, argCee)) != ZE_OK)\n        return k;  /* Something was screwy with the parsed string\n                      bail out */\n\n    if (AllocMemory(argCee, \"@\", \"End of Exclude List\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\n\nif ((szTempDir != NULL) && (szTempDir[0] != '\\0')\n     && Options.fTemp) /* Use temporary directory -b */\n    {\n    if (AllocMemory(argCee, \"-b\", \"Temp dir switch command\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    if (AllocMemory(argCee, szTempDir, \"Temporary directory\", FALSE) != ZE_OK)\n        return ZE_MEM;\n    }\n\nif (AllocMemory(argCee, C.lpszZipFN, \"Zip file name\", FALSE) != ZE_OK)\n    return ZE_MEM;\n\nif ((szRootDir != NULL) && (szRootDir[0] != '\\0'))\n    {\n    if (szRootDir[lstrlen(szRootDir)-1] != '\\\\')\n         lstrcat(szRootDir, \"\\\\\"); /* append trailing \\\\ */\n    if (C.FNV != NULL)\n        {\n        for (k = 0; k < C.argc; k++)\n            {\n            if (AllocMemory(argCee, C.FNV[k], \"Making argv\", FALSE) != ZE_OK)\n                return ZE_MEM;\n            if ((_strnicmp(szRootDir, C.FNV[k], lstrlen(szRootDir))) == 0)\n                {\n                m = 0;\n                for (j = lstrlen(szRootDir); j < lstrlen(C.FNV[k]); j++)\n                    argVee[argCee-1][m++] = C.FNV[k][j];\n                argVee[argCee-1][m] = '\\0';\n                }\n            }\n        }\n\n    }\nelse\n  if (C.FNV != NULL)\n    for (k = 0; k < C.argc; k++)\n        {\n        if (AllocMemory(argCee, C.FNV[k], \"Making argv\", FALSE) != ZE_OK)\n            return ZE_MEM;\n        }\n\nif (C.lpszAltFNL != NULL)\n    {\n    if ((k = ParseString(C.lpszAltFNL, argCee)) != ZE_OK)\n        return k;  /* Something was screwy with the parsed string\n                      bail out\n                    */\n    }\n\n\n\nargVee[argCee] = NULL;\n\nZipRet = zipmain(argCee, argVee);\n\n/* Free the arguments in the array. Note this also restores the\n   current directory\n */\nFreeArgVee();\n\nreturn ZipRet;\n}\n\n#if CRYPT\nint encr_passwd(int modeflag, char *pwbuf, int size, const char *zfn)\n    {\n    return (*lpZipUserFunctions->password)(pwbuf, size, ((modeflag == ZP_PW_VERIFY) ?\n                  \"Verify password: \" : \"Enter password: \"),\n                  (char *)zfn);\n    }\n#endif /* CRYPT */\n\nvoid EXPENTRY ZpVersion(ZpVer far * p)   /* should be pointer to const struct */\n    {\n    p->structlen = ZPVER_LEN;\n\n#ifdef BETA\n    p->flag = 1;\n#else\n    p->flag = 0;\n#endif\n#ifdef CRYPT\n    p->fEncryption = TRUE;\n#else\n    p->fEncryption = FALSE;\n#endif\n    lstrcpy(p->betalevel, Z_BETALEVEL);\n    lstrcpy(p->date, REVDATE);\n\n#ifdef ZLIB_VERSION\n    lstrcpy(p->zlib_version, ZLIB_VERSION);\n    p->flag |= 2;\n#else\n    p->zlib_version[0] = '\\0';\n#endif\n\n#ifdef ZIP64_SUPPORT\n    p->flag |= 4; /* Flag that ZIP64 was compiled in. */\n#endif\n\n    p->zip.major = Z_MAJORVER;\n    p->zip.minor = Z_MINORVER;\n    p->zip.patchlevel = Z_PATCHLEVEL;\n\n#ifdef OS2\n    p->os2dll.major = D2_MAJORVER;\n    p->os2dll.minor = D2_MINORVER;\n    p->os2dll.patchlevel = D2_PATCHLEVEL;\n#endif\n#ifdef WINDLL\n    p->windll.major = DW_MAJORVER;\n    p->windll.minor = DW_MINORVER;\n    p->windll.patchlevel = DW_PATCHLEVEL;\n#endif\n    }\n"
  },
  {
    "path": "deps/infozip/zip30/api.h",
    "content": "/*\n  api.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Only the Windows DLL is currently supported */\n#ifndef _ZIPAPI_H\n#define _ZIPAPI_H\n\n#include \"zip.h\"\n\n#ifdef WIN32\n#   ifndef PATH_MAX\n#      define PATH_MAX 260\n#   endif\n#else\n#   ifndef PATH_MAX\n#      define PATH_MAX 128\n#   endif\n#endif\n\n#if defined(WINDLL) || defined(API)\n#include <windows.h>\n/* Porting definations between Win 3.1x and Win32 */\n#ifdef WIN32\n#  define far\n#  define _far\n#  define __far\n#  define near\n#  define _near\n#  define __near\n#endif\n\n/*---------------------------------------------------------------------------\n    Prototypes for public Zip API (DLL) functions.\n  ---------------------------------------------------------------------------*/\n\n#define ZPVER_LEN    sizeof(ZpVer)\n/* These defines are set to zero for now, until OS/2 comes out\n   with a dll.\n */\n#define D2_MAJORVER 0\n#define D2_MINORVER 0\n#define D2_PATCHLEVEL 0\n\n/* intended to be a private struct: */\ntypedef struct _zip_ver {\n    uch major;              /* e.g., integer 5 */\n    uch minor;              /* e.g., 2 */\n    uch patchlevel;         /* e.g., 0 */\n    uch not_used;\n} _zip_version_type;\n\ntypedef struct _ZpVer {\n    ulg structlen;          /* length of the struct being passed */\n    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */\n    char betalevel[10];     /* e.g., \"g BETA\" or \"\" */\n    char date[20];          /* e.g., \"4 Sep 95\" (beta) or \"4 September 1995\" */\n    char zlib_version[10];  /* e.g., \"0.95\" or NULL */\n    BOOL fEncryption;       /* TRUE if encryption enabled, FALSE otherwise */\n    _zip_version_type zip;\n    _zip_version_type os2dll;\n    _zip_version_type windll;\n} ZpVer;\n\n#  ifndef EXPENTRY\n#    define EXPENTRY WINAPI\n#  endif\n\n#ifndef DEFINED_ONCE\n#define DEFINED_ONCE\ntypedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);\ntypedef int (WINAPI DLLPASSWORD) (LPSTR, int, LPCSTR, LPCSTR);\n#endif\n#ifdef ZIP64_SUPPORT\ntypedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned __int64);\ntypedef int (WINAPI DLLSERVICE_NO_INT64) (LPCSTR, unsigned long, unsigned long);\n#else\ntypedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned long);\n#endif\ntypedef int (WINAPI DLLSPLIT) (LPSTR);\ntypedef int (WINAPI DLLCOMMENT)(LPSTR);\n\n/* Structures */\n\ntypedef struct {        /* zip options */\nLPSTR Date;             /* Date to include after */\nLPSTR szRootDir;        /* Directory to use as base for zipping */\nLPSTR szTempDir;        /* Temporary directory used during zipping */\nBOOL fTemp;             /* Use temporary directory '-b' during zipping */\nBOOL fSuffix;           /* include suffixes (not implemented) */\nBOOL fEncrypt;          /* encrypt files */\nBOOL fSystem;           /* include system and hidden files */\nBOOL fVolume;           /* Include volume label */\nBOOL fExtra;            /* Exclude extra attributes */\nBOOL fNoDirEntries;     /* Do not add directory entries */\nBOOL fExcludeDate;      /* Exclude files newer than specified date */\nBOOL fIncludeDate;      /* Include only files newer than specified date */\nBOOL fVerbose;          /* Mention oddities in zip file structure */\nBOOL fQuiet;            /* Quiet operation */\nBOOL fCRLF_LF;          /* Translate CR/LF to LF */\nBOOL fLF_CRLF;          /* Translate LF to CR/LF */\nBOOL fJunkDir;          /* Junk directory names */\nBOOL fGrow;             /* Allow appending to a zip file */\nBOOL fForce;            /* Make entries using DOS names (k for Katz) */\nBOOL fMove;             /* Delete files added or updated in zip file */\nBOOL fDeleteEntries;    /* Delete files from zip file */\nBOOL fUpdate;           /* Update zip file--overwrite only if newer */\nBOOL fFreshen;          /* Freshen zip file--overwrite only */\nBOOL fJunkSFX;          /* Junk SFX prefix */\nBOOL fLatestTime;       /* Set zip file time to time of latest file in it */\nBOOL fComment;          /* Put comment in zip file */\nBOOL fOffsets;          /* Update archive offsets for SFX files */\nBOOL fPrivilege;        /* Use privileges (WIN32 only) */\nBOOL fEncryption;       /* TRUE if encryption supported, else FALSE.\n                           this is a read only flag */\nLPSTR szSplitSize;      /* This string contains the size that you want to\n                           split the archive into. i.e. 100 for 100 bytes,\n                           2K for 2 k bytes, where K is 1024, m for meg\n                           and g for gig. If this string is not NULL it\n                           will automatically be assumed that you wish to\n                           split an archive. */\nLPSTR szIncludeList;    /* Pointer to include file list string (for VB) */\nlong IncludeListCount;  /* Count of file names in the include list array */\nchar **IncludeList;     /* Pointer to include file list array. Note that the last\n                           entry in the array must be NULL */\nLPSTR szExcludeList;    /* Pointer to exclude file list (for VB) */\nlong ExcludeListCount;  /* Count of file names in the include list array */\nchar **ExcludeList;     /* Pointer to exclude file list array. Note that the last\n                           entry in the array must be NULL */\nint  fRecurse;          /* Recurse into subdirectories. 1 => -r, 2 => -R */\nint  fRepair;           /* Repair archive. 1 => -F, 2 => -FF */\nchar fLevel;            /* Compression level (0 - 9) */\n} ZPOPT, _far *LPZPOPT;\n\ntypedef struct {\n  int  argc;            /* Count of files to zip */\n  LPSTR lpszZipFN;      /* name of archive to create/update */\n  char **FNV;           /* array of file names to zip up */\n  LPSTR lpszAltFNL;     /* pointer to a string containing a list of file\n                           names to zip up, separated by whitespace. Intended\n                           for use only by VB users, all others should set this\n                           to NULL. */\n} ZCL, _far *LPZCL;\n\ntypedef struct {\n  DLLPRNT *print;\n  DLLCOMMENT *comment;\n  DLLPASSWORD *password;\n  DLLSPLIT *split;      /* This MUST be set to NULL unless you want to be queried\n                           for a destination for each split archive. */\n#ifdef ZIP64_SUPPORT\n  DLLSERVICE *ServiceApplication64;\n  DLLSERVICE_NO_INT64 *ServiceApplication64_No_Int64;\n#else\n  DLLSERVICE *ServiceApplication;\n#endif\n} ZIPUSERFUNCTIONS, far * LPZIPUSERFUNCTIONS;\n\nextern LPZIPUSERFUNCTIONS lpZipUserFunctions;\n\nvoid  EXPENTRY ZpVersion(ZpVer far *);\nint   EXPENTRY ZpInit(LPZIPUSERFUNCTIONS lpZipUserFunc);\nint   EXPENTRY ZpArchive(ZCL C, LPZPOPT Opts);\n\n#if defined(ZIPLIB) || defined(COM_OBJECT)\n#   define ydays zp_ydays\n#endif\n\n\n\n/* Functions not yet supported */\n#if 0\nint      EXPENTRY ZpMain            (int argc, char **argv);\nint      EXPENTRY ZpAltMain         (int argc, char **argv, ZpInit *init);\n#endif\n#endif /* WINDLL? || API? */\n\n#endif /* _ZIPAPI_H */\n"
  },
  {
    "path": "deps/infozip/zip30/atari/README",
    "content": "From: harry@hal.westfalen.de (Harald Denker)\n\nThe old zip ATARI port is based on TurboC which is no more\nsupported (for more than 3 years). I used the GNU gcc 2.5.8 and\nMiNTlibs PL46.\n"
  },
  {
    "path": "deps/infozip/zip30/atari/atari.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n#include <errno.h>\n#include <dirent.h>\n#include <mintbind.h>\n#include <osbind.h>\n#include <ostruct.h>\n\n\n#define PAD 0\n#define PATH_END '/'\n\nextern char *label;     /* defined in fileio.c */\n\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nlocal char *getVolumeLabel(drive, vtime, vmode, utim)\n  int drive;  /* drive name: 'A' .. 'Z' or '\\0' for current drive */\n  ulg *vtime; /* volume label creation time (DOS format) */\n  ulg *vmode; /* volume label file mode */\n  time_t utim;/* volume label creation time (UNIX format) */\n\n/* If a volume label exists for the given drive, return its name and\n   set its time and mode. The returned name must be static data. */\n{\n  static char vol[14];\n  _DTA *dtaptr;\n\n  if (drive) {\n    vol[0] = (char)drive;\n    strcpy(vol+1, \":/\");\n  } else {\n    strcpy(vol, \"/\");\n  }\n  strcat(vol, \"*.*\");\n  if (Fsfirst(vol, FA_LABEL) == 0) {\n    dtaptr = Fgetdta();\n    strncpy(vol, dtaptr->dta_name, sizeof(vol)-1);\n    *vtime = ((ulg)dtaptr->dta_date << 16) |\n             ((ulg)dtaptr->dta_time & 0xffff);\n    *vmode = (ulg)dtaptr->dta_attribute;\n    return vol;\n  }\n  return NULL;\n}\n\nchar GetFileMode(char *name)\n{\n   struct stat sb;\n\n   sb.st_attr = 0;\n   Fxattr(linkput ? 1 : 0, name, &sb);\n   if (errno == EINVAL) {\n      _DTA *dtaptr, *old;\n      old = Fgetdta();\n      Fsfirst(name, FA_RDONLY+FA_HIDDEN+FA_SYSTEM+FA_DIR);\n      dtaptr = Fgetdta();\n      sb.st_attr = dtaptr->dta_attribute;\n      Fsetdta(old);\n   }\n   return sb.st_attr & 0x3f;\n}\n\n\nint wild2(w)\nchar *w;                /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\n  DIR *d;               /* stream for reading directory */\n  char *e;              /* name found in directory */\n  int r;                /* temporary variable */\n  char *n;              /* constructed name from directory */\n  int f;                /* true if there was a match */\n  char *a;              /* alloc'ed space for name */\n  char *p;              /* path */\n  char *q;              /* name */\n  char v[5];            /* space for device current directory */\n\n  if (volume_label == 1) {\n    volume_label = 2;\n    label = getVolumeLabel(w[1] == ':' ? to_up(w[0]) : '\\0',\n                           &label_time, &label_mode, &label_utim);\n    if (label != NULL) {\n       newname(label, 0, 0);\n    }\n    if (w[1] == ':' && w[2] == '\\0') return ZE_OK;\n    /* \"zip -$ foo a:\" can be used to force drive name */\n  }\n\n  /* special handling of stdin request */\n  if (strcmp(w, \"-\") == 0)   /* if compressing stdin */\n    return newname(w, 0, 0);\n\n  /* Allocate and copy pattern */\n  if ((p = a = malloc(strlen(w) + 1)) == NULL)\n    return ZE_MEM;\n  strcpy(p, w);\n\n  /* Normalize path delimiter as '/'. */\n  for (q = p; *q; q++)                  /* use / consistently */\n    if (*q == '\\\\')\n      *q = '/';\n\n  /* Only name can have special matching characters */\n  if ((q = isshexp(p)) != NULL &&\n      (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))\n  {\n    free((zvoid *)a);\n    return ZE_PARMS;\n  }\n\n  /* Separate path and name into p and q */\n  if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))\n  {\n    *q++ = '\\0';                        /* path/name -> path, name */\n    if (*p == '\\0')                     /* path is just / */\n      p = strcpy(v, \"/.\");\n  }\n  else if ((q = strrchr(p, ':')) != NULL)\n  {                                     /* has device and no or root path */\n    *q++ = '\\0';\n    p = strcat(strcpy(v, p), \":\");      /* copy device as path */\n    if (*q == '/')                      /* -> device:/., name */\n    {\n      strcat(p, \"/\");\n      q++;\n    }\n    strcat(p, \".\");\n  }\n  else if (recurse && (strcmp(p, \".\") == 0 ||  strcmp(p, \"..\") == 0))\n  {                                    /* current or parent directory */\n    /* I can't understand Mark's code so I am adding a hack here to get\n     * \"zip -r foo .\" to work. Allow the dubious \"zip -r foo ..\" but\n     * reject \"zip -rm foo ..\".\n     */\n    if (dispose && strcmp(p, \"..\") == 0)\n       ziperr(ZE_PARMS, \"cannot remove parent directory\");\n    q = \"*.*\";\n  }\n  else                                  /* no path or device */\n  {\n    q = p;\n    p = strcpy(v, \".\");\n  }\n  if (recurse && *q == '\\0') {\n    q = \"*.*\";\n  }\n  /* Search that level for matching names */\n  if ((d = opendir(p)) == NULL)\n  {\n    free((zvoid *)a);\n    return ZE_MISS;\n  }\n  if ((r = strlen(p)) > 1 &&\n      (strcmp(p + r - 2, \":.\") == 0 || strcmp(p + r - 2, \"/.\") == 0))\n    *(p + r - 1) = '\\0';\n  f = 0;\n  while ((e = readd(d)) != NULL) {\n    if (strcmp(e, \".\") && strcmp(e, \"..\") && MATCH(q, e, 0))\n    {\n      f = 1;\n      if (strcmp(p, \".\") == 0) {                /* path is . */\n        r = procname(e, 0);                     /* name is name */\n        if (r) {\n           f = 0;\n           break;\n        }\n      } else\n      {\n        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)\n        {\n          free((zvoid *)a);\n          closedir(d);\n          return ZE_MEM;\n        }\n        n = strcpy(n, p);\n        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')\n          strcat(n, \"/\");\n        r = procname(strcat(n, e), 0);          /* name is path/name */\n        free((zvoid *)n);\n        if (r) {\n          f = 0;\n          break;\n        }\n      }\n    }\n  }\n  closedir(d);\n\n  /* Done */\n  free((zvoid *)a);\n  return f ? ZE_OK : ZE_MISS;\n}\n\n\n#include <regexp.h>\n#include <osbind.h>\n\nvoid regerror( char ZCONST *msg ) {\n   perror( msg );\n}\n\nstatic int    ret;\nstatic regexp *regptr;\nstatic short  is_w, ind_w;\nstatic char   fullpath[FILENAME_MAX], file_arg[FILENAME_MAX];\n\n#define FTW_F   0\n#define FTW_D   1\n#define FTW_DNR 2\n#define FTW_NS  3\n\nstatic int ftwfunc( struct stat *stats, int ftw_status )\n{\n   char *path = &fullpath[0];\n\n   if (strncmp(path, \"./\", 2) == 0) path += 2;\n   switch (ftw_status) {\n   case FTW_NS:\n      zipwarn(\"can't stat file: \", path);\n      ret = ZE_MISS;\n      return 0;\n   case FTW_F:\n      if (!is_w || regexec(regptr, path, 1)) {\n#if 0\n         char fn[FILENAME_MAX];\n         int  k;\n         if (S_ISLNK(stats->st_mode) &&\n             (k = readlink(path, fn, FILENAME_MAX)) > 0) {\n            int l = strlen(path);\n            fn[k] = '\\0';\n            strcat(strcat(path, \" -> \"), fn);\n            ret = newname(path, 0, 0); /* procname(path, 0); */\n            path[l] = '\\0';\n         } else\n#endif\n            ret = newname(path, 0, 0); /* procname(path, 0); */\n      }\n      return 0;\n   case FTW_DNR:\n      zipwarn(\"can't open directory: \", path);\n      ret = ZE_MISS;\n      return 0;\n   case FTW_D:\n      if (strcmp(path, \".\") == 0) return 0;\n      if (is_w && ind_w > 0 && strncmp(path, file_arg, ind_w) != 0)\n         return 4;\n   }\n   return 0;\n}\n\nstatic int myftw( int depth )\n{\n   register DIR   *dirp;\n   struct dirent  *entp;\n   struct stat    stats;\n   register char  *p,*q;\n   register long  i;\n\n   if (LSSTAT(fullpath, &stats) < 0)\n      return ftwfunc(&stats, FTW_NS);\n\n   if (!S_ISDIR(stats.st_mode))\n      return ftwfunc(&stats, FTW_F);\n\n   if ((dirp = opendir(fullpath)) == NULL)\n      return ftwfunc(&stats, FTW_DNR);\n\n   if (i = ftwfunc(&stats, FTW_D)) {\n      closedir(dirp);\n      return (i == 4 ? 0 : (int)i);\n   }\n   i = strlen(fullpath);\n   p = &fullpath[i];\n   *p++ = '/'; *p = '\\0';\n   if (dirnames && i > 1) {\n      q = (strncmp(fullpath, \"./\", 2) == 0 ? &fullpath[2] : &fullpath[0]);\n      ret = newname(q, 1, 0);\n   }\n   i = 0;\n   while (depth > 0 && (entp = readdir(dirp)) != 0)\n      if (strcmp(entp->d_name,\".\") != 0 && strcmp(entp->d_name,\"..\") != 0) {\n         strcpy(p, entp->d_name);\n         if (i = myftw(depth-1))\n            depth = 0;       /* force User's finish */\n      }\n   closedir(dirp);\n   return (int)i;\n}\n\nint wild( char *p )\n{\n   char *d;\n\n   ret = ZE_OK;\n   if (p == NULL) p = \"*\";\n\n   if (strcmp(p, \"-\") == 0)     /* if compressing stdin */\n      ret = newname(p, 0, 0);\n\n   strcpy(fullpath, p);\n   /* now turning UNIX-Wildcards into basic regular expressions */\n   for (is_w = ind_w = 0, d = &file_arg[0]; *p; d++, p++)\n      switch (*p) {\n      case '*': *d++ = '.'; *d = *p; is_w = 1;  break;\n      case '?': *d = '.';            is_w = 1;  break;\n      case '[': *d = *p;\n                if (*(p+1) == '!') {\n                   *++d = '^'; p++;\n                }                    is_w = 1;  break;\n      case '.': *d++ = '\\\\'; *d = *p;           break;\n      default : *d = *p;\n                if (!is_w) ind_w++;\n      }\n   *++d = '\\0';\n   if (is_w) {\n      strcat( file_arg, \"$\" );           /* to get things like *.[ch] work */\n      if ((regptr = regcomp( file_arg )) == NULL)\n         return ZE_MEM;\n      strcpy( fullpath, \".\" );\n      myftw( recurse ? 99 : 1 );\n      free(regptr);\n   } else if (recurse) {\n      myftw( 99 );\n   } else\n      myftw( 1 ); /* ret = procname( fullpath, 0 ); */\n   return ret;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; p++)          /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n  if (!S_ISDIR(s.st_mode))\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t, *p;          /* shortened name */\n  int dosflag;\n\n  dosflag = 0;\n\n  /* Find starting point in name before doing malloc */\n  t = *x && *(x + 1) == ':' ? x + 2 : x;\n  while (*t == '/' || *t == '\\\\')\n    t++;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (n = t; *n; n++)\n    if (*n == '\\\\')\n      *n = '/';\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n#if 0\n  if (p = strstr(t, \" -> \"))       /* shorten \"link -> data\" to \"link\" */\n    *p = '\\0';\n#endif\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n  strcpy(x, n);\n  return x;\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  struct utimbuf u;     /* argument for utime()  const ?? */\n\n  /* Convert DOS time to time_t format in u[0] and u[1] */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, &u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n/*  *a = ((ulg)s.st_mode << 16) | (ulg)GetFileMode(name); */\n    *a = ((ulg)s.st_mode << 16) | (ulg)s.st_attr;\n  }\n  free(name);\n  if (n != NULL)\n    *n = S_ISREG(s.st_mode) ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n#ifdef USE_EF_UT_TIME\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */\n#endif\n\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(2))) == NULL)\n    return ZE_MEM;\n  if ((z->cextra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(2);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n  z->extra[9]  = (char)(z_utim->atime);\n  z->extra[10] = (char)(z_utim->atime >> 8);\n  z->extra[11] = (char)(z_utim->atime >> 16);\n  z->extra[12] = (char)(z_utim->atime >> 24);\n\n  z->ext = (EB_HEADSIZE+EB_UX_LEN(2));\n\n  memcpy(z->cextra, z->extra, (EB_HEADSIZE+EB_UT_LEN(1)));\n  z->cextra[EB_LEN] = EB_UT_LEN(1);\n  z->cext = (EB_HEADSIZE+EB_UX_LEN(1));\n\n  return ZE_OK;\n#else /* !USE_EF_UT_TIME */\n  return (int)(z-z);\n#endif /* ?USE_EF_UT_TIME */\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return rmdir(d);\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#ifdef __TURBOC__\n    char buf[40];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n#  ifdef __TURBOC__\n      \"Turbo C\", (sprintf(buf, \" (0x%04x = %d)\", __TURBOC__, __TURBOC__), buf),\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#  endif\n#endif\n\n#ifdef __MINT__\n      \"Atari TOS/MiNT\",\n#else\n      \"Atari TOS\",\n#endif\n\n      \" (Atari ST/TT/Falcon030)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/atari/make_all.mup",
    "content": "rm -f *.o *.sym *.ttp\nmake370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-O -DATARI\" E=.ttp OBJA=atari.o zips\n#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.ttp OBJA=atari.o zip.ttp\n#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.sym OBJA=atari.o zip.sym LFLAGS2=\"-B/bin/sym-\"\n#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-O -DATARI\" E=.ttp OBJA=atari.o -n zips > make_all.mup\n#fixstk 32K pgp.ttp\nprgflags 017 007 *.ttp\n"
  },
  {
    "path": "deps/infozip/zip30/atari/make_zip.mup",
    "content": "#rm -f *.o *.sym *.ttp\n#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-O -DATARI\" E=.ttp OBJA=atari.o zips\nmake370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.ttp OBJA=atari.o zip.ttp\nmake370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-g -D__NO_INLINE__ -DATARI\" E=.sym OBJA=atari.o zip.sym LFLAGS2=\"-B/bin/sym-\"\n#make370 SHELL=/bin/mupfel.ttp CC=gcc CFLAGS=\"-O -DATARI\" E=.ttp OBJA=atari.o -n zips > make_all.mup\n#fixstk 32K pgp.ttp\nprgflags 017 007 *.ttp\n"
  },
  {
    "path": "deps/infozip/zip30/atari/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"wb\"\n\n#define DIRENT\n#define NO_TERMIO\n#define USE_CASE_MAP\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#include <sys/types.h>\n#include <sys/stat.h>\n"
  },
  {
    "path": "deps/infozip/zip30/atari/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  define O_RDONLY 0\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/atheos/README",
    "content": "Info-ZIP's zip for AtheOS/Syllable\n\nFEATURES\n  stores AtheOS/Syllable file attributes, compressing them if possible\n\nTODO\n----\nThere is only one thing to be fixed:\n  write_attr() should return count of writed bytes. However that's bug related with AFS only.\n\nPlease report any bugs to Info-ZIP at www.info-zip.org.\nIf this bug related with AtheOS/Syllable only, you can mail me directly: nruslan@hotbox.ru.\n\nVisit the Info-ZIP web site (http://www.info-zip.org) for all the\nlatest zip and unzip information, FAQs, source code and ready-to-run\nexecutables.\n\n- Ruslan Nickolaev (nruslan@hotbox.ru)\n  Sep 06/2004\n\n(updated 12 November 2004)\n"
  },
  {
    "path": "deps/infozip/zip30/atheos/atheos.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n\n  This AtheOS - specific file is based on unix.c and beos.c;\n  changes by Ruslan Nickolaev (nruslan@hotbox.ru)\n*/\n\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/errno.h>\n#include <limits.h>\n#include <sys/stat.h>\n#include <sys/fcntl.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include <atheos/fs_attribs.h>\n\n\n#define PAD 0\n#define PATH_END '/'\n\n/* Library functions not in (most) header files */\n\n#ifdef _POSIX_VERSION\n#  include <utime.h>\n#else\n   int utime OF((char *, time_t *));\n#endif\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\nlocal int get_attr_dir( const char *, char **, off_t * );\nlocal int add_UT_ef( struct zlist far * );\nlocal int add_Ux_ef( struct zlist far * );\nlocal int add_At_ef( struct zlist far * );\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFREG) == S_IFREG ||\n      (s.st_mode & S_IFLNK) == S_IFLNK)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  }\n  else if ((s.st_mode & S_IFDIR) == S_IFDIR)\n  {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) */\n  else\n    zipwarn(\"ignoring special file: \", n);\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t = NULL;       /* shortened name */\n  int dosflag;\n\n  dosflag = dosify;  /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  /* Strip \"//host/share/\" part of a UNC name */\n  if (!strncmp(x,\"//\",2) && (x[2] != '\\0' && x[2] != '/')) {\n    n = x + 2;\n    while (*n != '\\0' && *n != '/')\n      n++;              /* strip host name */\n    if (*n != '\\0') {\n      n++;\n      while (*n != '\\0' && *n != '/')\n        n++;            /* strip `share' name */\n    }\n    if (*n != '\\0')\n      t = n + 1;\n  } else\n      t = x;\n  while (*t == '/')\n    t++;                /* strip leading '/' chars to get a relative path */\n  while (*t == '.' && t[1] == '/')\n    t += 2;             /* strip redundant leading \"./\" sections */\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (isdir == 42) return n;    /* avoid warning on unused variable */\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n  return x;\n}\n\n/*\n * XXX use ztimbuf in both POSIX and non POSIX cases ?\n */\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n#ifdef _POSIX_VERSION\n  struct utimbuf u;     /* argument for utime()  const ?? */\n#else\n  time_t u[2];          /* argument for utime() */\n#endif\n\n  /* Convert DOS time to time_t format in u */\n#ifdef _POSIX_VERSION\n  u.actime = u.modtime = dos2unixtime(d);\n  utime(f, &u);\n#else\n  u[0] = u[1] = dos2unixtime(d);\n  utime(f, u);\n#endif\n\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  }\n  else if (LSSTAT(name, &s) != 0) {\n    /* Accept about any file kind including directories\n     * (stored with trailing / with -r option)\n     */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n#ifndef OS390\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n#else\n/*\n**  The following defines are copied from the unizip source and represent the\n**  legacy Unix mode flags.  These fixed bit masks are no longer required\n**  by XOPEN standards - the S_IS### macros being the new recommended method.\n**  The approach here of setting the legacy flags by testing the macros should\n**  work under any _XOPEN_SOURCE environment (and will just rebuild the same bit\n**  mask), but is required if the legacy bit flags differ from legacy Unix.\n*/\n#define UNX_IFDIR      0040000     /* Unix directory */\n#define UNX_IFREG      0100000     /* Unix regular file */\n#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */\n#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */\n#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */\n#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */\n#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */\n    {\n    mode_t legacy_modes;\n\n    /* Initialize with permission bits - which are not implementation optional */\n    legacy_modes = s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);\n    if (S_ISDIR(s.st_mode))\n      legacy_modes |= UNX_IFDIR;\n    if (S_ISREG(s.st_mode))\n      legacy_modes |= UNX_IFREG;\n    if (S_ISLNK(s.st_mode))\n      legacy_modes |= UNX_IFLNK;\n    if (S_ISBLK(s.st_mode))\n      legacy_modes |= UNX_IFBLK;\n    if (S_ISCHR(s.st_mode))\n      legacy_modes |= UNX_IFCHR;\n    if (S_ISFIFO(s.st_mode))\n      legacy_modes |= UNX_IFIFO;\n    if (S_ISSOCK(s.st_mode))\n      legacy_modes |= UNX_IFSOCK;\n    *a = ((ulg)legacy_modes << 16) | !(s.st_mode & S_IWRITE);\n    }\n#endif\n    if ((s.st_mode & S_IFMT) == S_IFDIR) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */\n  }\n  return unix2dostime(&s.st_mtime);\n}\n\n/* ----------------------------------------------------------------------\n\nReturn a malloc()'d buffer containing all of the attributes and their names\nfor the file specified in name.  You have to free() this yourself.  The length\nof the buffer is also returned.\n\nIf get_attr_dir() fails, the buffer will be NULL, total_size will be 0,\nand an error will be returned:\n\n    EOK    - no errors occurred\n    EINVAL - attr_buff was pointing at a buffer\n    ENOMEM - insufficient memory for attribute buffer\n\nOther errors are possible (whatever is returned by the fs_attrib.h functions).\n\nPROBLEMS:\n\n- pointers are 32-bits; attributes are limited to ssize_t in size so it's\n  possible to overflow... in practice, this isn't too likely... your\n  machine will thrash like hell before that happens\n\n*/\n\n#define INITIAL_BUFF_SIZE 65536\n\nint get_attr_dir( const char *name, char **attr_buff, off_t *total_size )\n{\n    int               retval = EOK;\n    int               fd;\n    DIR              *fa_dir;\n    struct dirent    *fa_ent;\n    off_t             attrs_size = 0;\n    size_t           entname_size;\n    char             *ptr;\n    struct attr_info  fa_info;\n\n    *total_size = 0;\n\n    /* ----------------------------------------------------------------- */\n    /* Sanity-check.                                                     */\n    if( *attr_buff != NULL ) {\n        return EINVAL;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Can we open the file/directory?                                   */\n    /*                                                                   */\n    /* linkput is a zip global; it's set to 1 if we're storing symbolic  */\n    /* links as symbolic links (instead of storing the thing the link    */\n    /* points to)... if we're storing the symbolic link as a link, we'll */\n    /* want the link's file attributes, otherwise we want the target's.  */\n\n    fd = open( name, linkput ? O_RDONLY | O_NOTRAVERSE : O_RDONLY );\n    if( fd < 0 ) {\n        return errno;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Allocate an initial buffer; 64k should usually be enough.         */\n    *attr_buff = (char *)malloc( INITIAL_BUFF_SIZE );\n    ptr        = *attr_buff;\n    if( ptr == NULL ) {\n        close( fd );\n\n        return ENOMEM;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Open the attributes directory for this file.                      */\n    fa_dir = open_attrdir( fd );\n    if( fa_dir == NULL ) {\n        close( fd );\n\n        free( ptr );\n        *attr_buff = NULL;\n\n        return retval;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Read all the attributes; the buffer could grow > 64K if there are */\n    /* many and/or they are large.                                       */\n    while( ( fa_ent = read_attrdir( fa_dir ) ) != NULL ) {\n        retval = stat_attr( fd, fa_ent->d_name, &fa_info );\n        /* TODO: check retval != EOK */\n\n        entname_size = strlen( fa_ent->d_name ) + 1;\n        attrs_size += entname_size + sizeof( struct attr_info ) + fa_info.ai_size;\n\n        if( attrs_size > INITIAL_BUFF_SIZE ) {\n            unsigned long offset = ptr - *attr_buff;\n\n            *attr_buff = (char *)realloc( *attr_buff, attrs_size );\n            if( *attr_buff == NULL ) {\n                retval = close_attrdir( fa_dir );\n                /* TODO: check retval != EOK */\n                close( fd );\n                return ENOMEM;\n            }\n\n            ptr = *attr_buff + offset;\n        }\n\n        /* Now copy the data for this attribute into the buffer. */\n        strcpy( ptr, fa_ent->d_name );\n        ptr += entname_size;\n\n  memcpy( ptr, &fa_info, sizeof( struct attr_info ) );\n        ptr += sizeof( struct attr_info );\n\n        if( fa_info.ai_size > 0 ) {\n            ssize_t read_bytes = read_attr( fd, fa_ent->d_name, fa_info.ai_type, ptr, 0, fa_info.ai_size );\n            if( read_bytes != fa_info.ai_size ) {\n                /* print a warning about mismatched sizes */\n                char buff[80];\n                sprintf( buff, \"read %d, expected %d\", read_bytes, (ssize_t)fa_info.ai_size );\n                zipwarn( \"attribute size mismatch: \", buff );\n            }\n\n            ptr += fa_info.ai_size;\n        }\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Close the attribute directory.                                    */\n    retval = close_attrdir( fa_dir );\n    /* TODO: check retval != EOK */\n\n    /* ----------------------------------------------------------------- */\n    /* If the buffer is too big, shrink it.                              */\n    if( attrs_size < INITIAL_BUFF_SIZE ) {\n        *attr_buff = (char *)realloc( *attr_buff, attrs_size );\n        if( *attr_buff == NULL ) {\n            close( fd );\n            return ENOMEM;\n        }\n    }\n\n    *total_size = attrs_size;\n\n    close( fd );\n\n    return EOK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'UT' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))\n#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n\nlocal int add_UT_ef( struct zlist far *z )\n{\n    char        *l_ef = NULL;\n    char        *c_ef = NULL;\n    struct stat  s;\n\n#ifdef IZ_CHECK_TZ\n    if (!zp_tz_is_valid)\n        return ZE_OK;           /* skip silently if no valid TZ info */\n#endif\n\n    /* We can't work if there's no entry to work on. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_UT_SIZE > USHRT_MAX ||\n        z->cext + EB_C_UT_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* stat() the file (or the symlink) to get the data; if we can't get */\n    /* the data, there's no point in trying to fill out the fields.      */\n    if(LSSTAT( z->name, &s ) ) {\n        return ZE_OPEN;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_UT_SIZE );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_UT_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'U';\n    *l_ef++ = 'T';\n    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */\n    *l_ef++ = (char)0;\n    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n    *l_ef++ = (char)(s.st_mtime);\n    *l_ef++ = (char)(s.st_mtime >> 8);\n    *l_ef++ = (char)(s.st_mtime >> 16);\n    *l_ef++ = (char)(s.st_mtime >> 24);\n    *l_ef++ = (char)(s.st_atime);\n    *l_ef++ = (char)(s.st_atime >> 8);\n    *l_ef++ = (char)(s.st_atime >> 16);\n    *l_ef++ = (char)(s.st_atime >> 24);\n\n    z->ext += EB_L_UT_SIZE;\n\n    /* Now add the central version. */\n    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);\n    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */\n\n    z->cext += EB_C_UT_SIZE;\n\n    return ZE_OK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'Ux' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)\n#define EB_C_UX2_SIZE   (EB_HEADSIZE)\n\nlocal int add_Ux_ef( struct zlist far *z )\n{\n    char        *l_ef = NULL;\n    char        *c_ef = NULL;\n    struct stat  s;\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_UX2_SIZE > USHRT_MAX ||\n        z->cext + EB_C_UX2_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* stat() the file (or the symlink) to get the data; if we can't get */\n    /* the data, there's no point in trying to fill out the fields.      */\n    if(LSSTAT( z->name, &s ) ) {\n        return ZE_OPEN;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UX2_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_UX2_SIZE );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UX2_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_UX2_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'U';\n    *l_ef++ = 'x';\n    *l_ef++ = (char)(EB_UX2_MINLEN);\n    *l_ef++ = (char)(EB_UX2_MINLEN >> 8);\n    *l_ef++ = (char)(s.st_uid);\n    *l_ef++ = (char)(s.st_uid >> 8);\n    *l_ef++ = (char)(s.st_gid);\n    *l_ef++ = (char)(s.st_gid >> 8);\n\n    z->ext += EB_L_UX2_SIZE;\n\n    /* Now add the central version of the field. */\n    *c_ef++ = 'U';\n    *c_ef++ = 'x';\n    *c_ef++ = 0;\n    *c_ef++ = 0;\n\n    z->cext += EB_C_UX2_SIZE;\n\n    return ZE_OK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'At' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_AT_SIZE    (EB_HEADSIZE + EB_L_AT_LEN) /* + attr size */\n#define EB_C_AT_SIZE    (EB_HEADSIZE + EB_C_AT_LEN)\n\n#define MEMCOMPRESS_HEADER      6   /* ush compression type, ulg CRC */\n#define DEFLAT_WORSTCASE_ADD    5   /* byte blocktype, 2 * ush blocklength */\n#define MEMCOMPRESS_OVERHEAD    (MEMCOMPRESS_HEADER + DEFLAT_WORSTCASE_ADD)\n\nlocal int add_At_ef( struct zlist far *z )\n{\n    char *l_ef       = NULL;\n    char *c_ef       = NULL;\n    char *attrbuff   = NULL;\n    off_t attrsize   = 0;\n    char *compbuff   = NULL;\n    ush   compsize   = 0;\n    uch   flags      = 0;\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_AT_SIZE > USHRT_MAX ||\n        z->cext + EB_C_AT_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* Attempt to load up a buffer full of the file's attributes. */\n    {\n        if (get_attr_dir( z->name, &attrbuff, &attrsize) != EOK ) {\n            return ZE_OPEN;\n        }\n        if (attrsize == 0) {\n            return ZE_OK;\n        }\n        if (attrbuff == NULL) {\n            return ZE_LOGIC;\n        }\n\n        /* Check for way too much data. */\n        if (attrsize > (off_t)ULONG_MAX) {\n            zipwarn( \"uncompressed attributes truncated\", \"\" );\n            attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD);\n        }\n    }\n\n    if (verbose) {\n        printf( \"\\t[in=%lu]\", (unsigned long)attrsize );\n    }\n\n    /* Try compressing the data */\n    compbuff = (char *)malloc( (size_t)attrsize + MEMCOMPRESS_OVERHEAD );\n    if( compbuff == NULL ) {\n        return ZE_MEM;\n    }\n    compsize = memcompress( compbuff,\n                            (size_t)attrsize + MEMCOMPRESS_OVERHEAD,\n                            attrbuff,\n                            (size_t)attrsize );\n    if (verbose) {\n        printf( \" [out=%u]\", compsize );\n    }\n\n    /* Attempt to optimise very small attributes. */\n    if (compsize > attrsize) {\n        free( compbuff );\n        compsize = (ush)attrsize;\n        compbuff = attrbuff;\n\n        flags = EB_AT_FL_NATURAL;\n    }\n\n    /* Check to see if we really have enough room in the EF for the data. */\n    if( ( z->ext + compsize + EB_L_AT_LEN ) > USHRT_MAX ) {\n        compsize = USHRT_MAX - EB_L_AT_LEN - z->ext;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_AT_SIZE + compsize );\n    } else {\n        l_ef = (char *)malloc( EB_L_AT_SIZE + compsize );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_AT_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_AT_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'A';\n    *l_ef++ = 't';\n    *l_ef++ = (char)(compsize + EB_L_AT_LEN);\n    *l_ef++ = (char)((compsize + EB_L_AT_LEN) >> 8);\n    *l_ef++ = (char)((unsigned long)attrsize);\n    *l_ef++ = (char)((unsigned long)attrsize >> 8);\n    *l_ef++ = (char)((unsigned long)attrsize >> 16);\n    *l_ef++ = (char)((unsigned long)attrsize >> 24);\n    *l_ef++ = flags;\n    memcpy( l_ef, compbuff, (size_t)compsize );\n\n    z->ext += EB_L_AT_SIZE + compsize;\n\n    /* And the central version. */\n    *c_ef++ = 'A';\n    *c_ef++ = 't';\n    *c_ef++ = (char)(EB_C_AT_LEN);\n    *c_ef++ = (char)(EB_C_AT_LEN >> 8);\n    *c_ef++ = (char)compsize;\n    *c_ef++ = (char)(compsize >> 8);\n    *c_ef++ = (char)(compsize >> 16);\n    *c_ef++ = (char)(compsize >> 24);\n    *c_ef++ = flags;\n\n    z->cext += EB_C_AT_SIZE;\n\n    return ZE_OK;\n}\n\n/* Extra field info:\n   - 'UT' - UNIX time extra field\n   - 'Ux' - UNIX uid/gid extra field\n   - 'At' - AtheOS file attributes extra field\n\n   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields\n   (full data in local header, only modification time in central header),\n   with the 'At' field added to the end and the size of the 'At' field\n   in the central header.\n\n   See the end of atheos/osdep.h for a simple explanation of the 'At' EF\n   layout.\n */\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* store full data in local header but just modification time stamp info\n     in central header */\n{\n    int retval;\n\n    /* Check to make sure z is valid. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    retval = add_UT_ef(z);\n    if( retval != ZE_OK ) {\n        return retval;\n    }\n\n    retval = add_Ux_ef(z);\n    if( retval != ZE_OK ) {\n        return retval;\n    }\n\n    return add_At_ef(z); /* last function; we can use return value directly */\n}\n\n/* ---------------------------------------------------------------------- */\n/* Set a file's MIME type.                                                */\nvoid setfiletype(const char *file, const char *type)\n{\n    int fd;\n    off_t nLen;\n    ssize_t nError;\n\n    fd = open( file, O_RDWR );\n\n    if (fd < 0) {\n        zipwarn( \"can't open zipfile to write file type\", \"\" );\n    }\n\n    else\n    {\n        nLen = strlen( type );\n        /* FIXME: write_attr() should return count of writed bytes */\n        nError = write_attr( fd, \"os::MimeType\", O_TRUNC, ATTR_TYPE_STRING, type, 0, nLen );\n        if (nError < 0) {\n            zipwarn( \"couldn't write complete file type\", \"\" );\n        }\n        close( fd );\n    }\n}\n\n#endif /* !UTIL */\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n      \"(unknown compiler)\", \"\",\n#endif\n\n      \"Syllable\",\n\n#if defined(i486) || defined(__i486) || defined(__i486__) || defined(i386) || defined(__i386) || defined(__i386__)\n      \" (x86)\",\n#else\n      \" (unknown platform)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/atheos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n\n#ifndef _OSDEP_H_\n#define _OSDEP_H_\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <sys/unistd.h>\n\n#define USE_EF_UT_TIME          /* Enable use of \"UT\" extra field time info */\n\n#define EB_L_AT_LEN 5           /* min size is an unsigned long and flag */\n#define EB_C_AT_LEN 5           /* Length of data in local EF and flag.  */\n\n#define EB_AT_FL_NATURAL    0x01    /* data is 'natural' (not compressed) */\n#define EB_AT_FL_BADBITS    0xfe    /* bits currently undefined           */\n\n#ifndef ZP_NEED_MEMCOMPR\n  define ZP_NEED_MEMCOMPR\n#endif\n\n#define deletedir(d) rmdir(d);\n\n/* Set a file's MIME type. */\nvoid setfiletype( const char *file, const char *type );\n\n/*\n'At' extra-field layout:\n\n'At'      - signature\nef_size   - size of data in this EF (little-endian unsigned short)\nfull_size - uncompressed data size (little-endian unsigned long)\nflag      - flags (byte)\n            flags & EB_AT_FL_NATURAL    = the data is not compressed\n            flags & EB_AT_FL_BADBITS    = the data is corrupted or we\n                                          can't handle it properly\ndata      - compressed or uncompressed file attribute data\n\nIf flag & EB_AT_FL_NATURAL, the data is not compressed; this optimisation is\nnecessary to prevent wasted space for files with small attributes. In this\ncase, there should be ( ef_size - EB_L_AT_LEN ) bytes of data, and full_size\nshould equal ( ef_size - EB_L_AT_LEN ).\n\nIf the data is compressed, there will be ( ef_size - EB_L_AT_LEN ) bytes of\ncompressed data, and full_size bytes of uncompressed data.\n\nIf a file has absolutely no attributes, there will not be a 'At' extra field.\n\nThe uncompressed data is arranged like this:\n\nattr_name\\0 - C string\nstruct attr_info (little-endian)\nattr_data (length in attr_info.ai_size)\n*/\n\n#endif\n\n"
  },
  {
    "path": "deps/infozip/zip30/atheos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef _ZIPUP_H_\n#define _ZIPUP_H_\n\n#ifndef O_RDONLY\n#  include <sys/fcntl.h>\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n\n#endif /* _ZIPUP_H_ */\n"
  },
  {
    "path": "deps/infozip/zip30/beos/Contents",
    "content": "Contents of the \"beos\" sub-directory for Zip 2.2 and later:\n\n  Contents      this file\n  README        Notes from the author of the BeOS port\n  Makefile      makefile for building (sorry, no project files)\n  beos.c        BeOS-specific routines (similar to the UNIX ones)\n  osdep.h       BeOS-specific includes and whatnot\n  zipup.h       Definitions for zip routines\n\nThis port supports both Metrowerks CodeWarrior and GNU C as the compiler,\nand PowerPC and x86 architectures.\n\n- Chris Herborth (chrish@pobox.com)\n  June 24, 1998\n"
  },
  {
    "path": "deps/infozip/zip30/beos/README",
    "content": "Info-ZIP's zip for BeOS\n\nKNOWN BUGS\n\n- None! (as of zip 2.21)\n\n- building on x86 BeOS generates a hell of a lot of bugs; I'm not going to\n  worry about them until Be fixes their headers though...\n\nFEATURES\n\n- stores BeOS file attributes, compressing them if possible (as of 2.21,\n  this works properly for symbolic links, too; as of 2.3, this works\n  properly for symbolic links whether you're storing them as links or not)\n\n- zip files are created with the correct file type (application/zip)\n\n- supports both Metrowerks CodeWarrior (PowerPC platform) and GNU C\n  (x86 platform), automatically picking the default compiler for each\n  architecture\n\nPlease report any bugs to the Zip-Bugs mailing list; our email address is\nzip-bugs@lists.wku.edu.  If it's something BeOS-specific, you could email\nme directly.\n\nVisit the Info-ZIP web site (http://www.cdrom.com/pub/infozip/) for all the\nlatest zip and unzip information, FAQs, source code and ready-to-run\nexecutables.\n\n- Chris Herborth (chrish@pobox.com)\n  April 2/1999\n"
  },
  {
    "path": "deps/infozip/zip30/beos/beos.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n\n This BeOS-specific file is based on unix.c in the unix directory; changes\n by Chris Herborth (chrish@pobox.com).\n\n*/\n\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n#include <dirent.h>\n#include <errno.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n\n#include <dirent.h>\n\n#include <kernel/fs_attr.h>\n#include <storage/Mime.h>\n#include <support/byteorder.h>\n\n\n#define PAD 0\n#define PATH_END '/'\n\n/* Library functions not in (most) header files */\n\n#ifdef _POSIX_VERSION\n#  include <utime.h>\n#else\n   int utime OF((char *, time_t *));\n#endif\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\nlocal int get_attr_dir( const char *, char **, off_t * );\nlocal int add_UT_ef( struct zlist far * );\nlocal int add_Ux_ef( struct zlist far * );\nlocal int add_Be_ef( struct zlist far * );\n\n\n#ifdef NO_DIR                    /* for AT&T 3B1 */\n#include <sys/dir.h>\n#ifndef dirent\n#  define dirent direct\n#endif\ntypedef FILE DIR;\n/*\n**  Apparently originally by Rich Salz.\n**  Cleaned up and modified by James W. Birdsall.\n*/\n\n#define opendir(path) fopen(path, \"r\")\n\nstruct dirent *readdir(dirp)\nDIR *dirp;\n{\n  static struct dirent entry;\n\n  if (dirp == NULL)\n    return NULL;\n  for (;;)\n    if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)\n      return NULL;\n    else if (entry.d_ino)\n      return (&entry);\n} /* end of readdir() */\n\n#define closedir(dirp) fclose(dirp)\n#endif /* NO_DIR */\n\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  dosflag = dosify;  /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for (t = x; *t == '/'; t++)\n    ;                   /* strip leading '/' chars to get a relative path */\n  while (*t == '.' && t[1] == '/')\n    t += 2;             /* strip redundant leading \"./\" sections */\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (isdir == 42) return n;    /* avoid warning on unused variable */\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n  return x;\n}\n\n/*\n * XXX use ztimbuf in both POSIX and non POSIX cases ?\n */\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n#ifdef _POSIX_VERSION\n  struct utimbuf u;     /* argument for utime()  const ?? */\n#else\n  time_t u[2];          /* argument for utime() */\n#endif\n\n  /* Convert DOS time to time_t format in u */\n#ifdef _POSIX_VERSION\n  u.actime = u.modtime = dos2unixtime(d);\n  utime(f, &u);\n#else\n  u[0] = u[1] = dos2unixtime(d);\n  utime(f, u);\n#endif\n\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNAMX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFMT) == S_IFDIR) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_mtime;   /* best guess (s.st_ctime: last status change!) */\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\n/* ----------------------------------------------------------------------\n\nReturn a malloc()'d buffer containing all of the attributes and their names\nfor the file specified in name.  You have to free() this yourself.  The length\nof the buffer is also returned.\n\nIf get_attr_dir() fails, the buffer will be NULL, total_size will be 0,\nand an error will be returned:\n\n    EOK    - no errors occurred\n    EINVAL - attr_buff was pointing at a buffer\n    ENOMEM - insufficient memory for attribute buffer\n\nOther errors are possible (whatever is returned by the fs_attr.h functions).\n\nPROBLEMS:\n\n- pointers are 32-bits; attributes are limited to off_t in size so it's\n  possible to overflow... in practice, this isn't too likely... your\n  machine will thrash like hell before that happens\n\n*/\n\n#define INITIAL_BUFF_SIZE 65536\n\nint get_attr_dir( const char *name, char **attr_buff, off_t *total_size )\n{\n    int               retval = EOK;\n    int               fd;\n    DIR              *fa_dir;\n    struct dirent    *fa_ent;\n    off_t             attrs_size;\n    off_t             this_size;\n    char             *ptr;\n    struct attr_info  fa_info;\n    struct attr_info  big_fa_info;\n\n    retval      = EOK;\n    attrs_size  = 0;    /* gcc still says this is used uninitialized... */\n    *total_size = 0;\n\n    /* ----------------------------------------------------------------- */\n    /* Sanity-check.                                                     */\n    if( *attr_buff != NULL ) {\n        return EINVAL;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Can we open the file/directory?                                   */\n    /*                                                                   */\n    /* linkput is a zip global; it's set to 1 if we're storing symbolic  */\n    /* links as symbolic links (instead of storing the thing the link    */\n    /* points to)... if we're storing the symbolic link as a link, we'll */\n    /* want the link's file attributes, otherwise we want the target's.  */\n    if( linkput ) {\n        fd = open( name, O_RDONLY | O_NOTRAVERSE );\n    } else {\n        fd = open( name, O_RDONLY );\n    }\n    if( fd < 0 ) {\n        return errno;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Allocate an initial buffer; 64k should usually be enough.         */\n    *attr_buff = (char *)malloc( INITIAL_BUFF_SIZE );\n    ptr        = *attr_buff;\n    if( ptr == NULL ) {\n        close( fd );\n\n        return ENOMEM;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Open the attributes directory for this file.                      */\n    fa_dir = fs_fopen_attr_dir( fd );\n    if( fa_dir == NULL ) {\n        close( fd );\n\n        free( ptr );\n        *attr_buff = NULL;\n\n        return retval;\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Read all the attributes; the buffer could grow > 64K if there are */\n    /* many and/or they are large.                                       */\n    fa_ent = fs_read_attr_dir( fa_dir );\n    while( fa_ent != NULL ) {\n        retval = fs_stat_attr( fd, fa_ent->d_name, &fa_info );\n        /* TODO: check retval != EOK */\n\n        this_size  = strlen( fa_ent->d_name ) + 1;\n        this_size += sizeof( struct attr_info );\n        this_size += fa_info.size;\n\n        attrs_size += this_size;\n\n        if( attrs_size > INITIAL_BUFF_SIZE ) {\n            unsigned long offset = ptr - *attr_buff;\n\n            *attr_buff = (char *)realloc( *attr_buff, attrs_size );\n            if( *attr_buff == NULL ) {\n                retval = fs_close_attr_dir( fa_dir );\n                /* TODO: check retval != EOK */\n                close( fd );\n\n                return ENOMEM;\n            }\n\n            ptr = *attr_buff + offset;\n        }\n\n        /* Now copy the data for this attribute into the buffer. */\n        strcpy( ptr, fa_ent->d_name );\n        ptr += strlen( fa_ent->d_name );\n        *ptr++ = '\\0';\n\n        /* We need to put a big-endian version of the fa_info data into */\n        /* the archive.                                                 */\n        big_fa_info.type = B_HOST_TO_BENDIAN_INT32( fa_info.type );\n        big_fa_info.size = B_HOST_TO_BENDIAN_INT64( fa_info.size );\n        memcpy( ptr, &big_fa_info, sizeof( struct attr_info ) );\n        ptr += sizeof( struct attr_info );\n\n        if( fa_info.size > 0 ) {\n            ssize_t read_bytes;\n\n            read_bytes = fs_read_attr( fd, fa_ent->d_name, fa_info.type, 0,\n                                       ptr, fa_info.size );\n            if( read_bytes != fa_info.size ) {\n                /* print a warning about mismatched sizes */\n                char buff[80];\n\n                sprintf( buff, \"read %ld, expected %ld\",\n                         (ssize_t)read_bytes, (ssize_t)fa_info.size );\n                zipwarn( \"attribute size mismatch: \", buff );\n            }\n\n            /* Wave my magic wand... this swaps all the Be types to big- */\n            /* endian automagically.                                     */\n            (void)swap_data( fa_info.type, ptr, fa_info.size,\n                             B_SWAP_HOST_TO_BENDIAN );\n\n            ptr += fa_info.size;\n        }\n\n        fa_ent = fs_read_attr_dir( fa_dir );\n    }\n\n    /* ----------------------------------------------------------------- */\n    /* Close the attribute directory.                                    */\n    retval = fs_close_attr_dir( fa_dir );\n    /* TODO: check retval != EOK */\n\n    /* ----------------------------------------------------------------- */\n    /* If the buffer is too big, shrink it.                              */\n    if( attrs_size < INITIAL_BUFF_SIZE ) {\n        *attr_buff = (char *)realloc( *attr_buff, attrs_size );\n        if( *attr_buff == NULL ) {\n            /* This really shouldn't happen... */\n            close( fd );\n\n            return ENOMEM;\n        }\n    }\n\n    *total_size = attrs_size;\n\n    close( fd );\n\n    return EOK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'UT' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))\n#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n\nlocal int add_UT_ef( struct zlist far *z )\n{\n    char        *l_ef = NULL;\n    char        *c_ef = NULL;\n    struct stat  s;\n\n#ifdef IZ_CHECK_TZ\n    if (!zp_tz_is_valid)\n        return ZE_OK;           /* skip silently if no valid TZ info */\n#endif\n\n    /* We can't work if there's no entry to work on. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_UT_SIZE > USHRT_MAX ||\n        z->cext + EB_C_UT_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* stat() the file (or the symlink) to get the data; if we can't get */\n    /* the data, there's no point in trying to fill out the fields.      */\n    if(LSSTAT( z->name, &s ) ) {\n        return ZE_OPEN;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_UT_SIZE );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_UT_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'U';\n    *l_ef++ = 'T';\n    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */\n    *l_ef++ = (char)0;\n    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_ATIME);\n    *l_ef++ = (char)(s.st_mtime);\n    *l_ef++ = (char)(s.st_mtime >> 8);\n    *l_ef++ = (char)(s.st_mtime >> 16);\n    *l_ef++ = (char)(s.st_mtime >> 24);\n    *l_ef++ = (char)(s.st_atime);\n    *l_ef++ = (char)(s.st_atime >> 8);\n    *l_ef++ = (char)(s.st_atime >> 16);\n    *l_ef++ = (char)(s.st_atime >> 24);\n\n    z->ext += EB_L_UT_SIZE;\n\n    /* Now add the central version. */\n    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);\n    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */\n\n    z->cext += EB_C_UT_SIZE;\n\n    return ZE_OK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'Ux' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)\n#define EB_C_UX2_SIZE   (EB_HEADSIZE)\n\nlocal int add_Ux_ef( struct zlist far *z )\n{\n    char        *l_ef = NULL;\n    char        *c_ef = NULL;\n    struct stat  s;\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_UX2_SIZE > USHRT_MAX ||\n        z->cext + EB_C_UX2_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* stat() the file (or the symlink) to get the data; if we can't get */\n    /* the data, there's no point in trying to fill out the fields.      */\n    if(LSSTAT( z->name, &s ) ) {\n        return ZE_OPEN;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UX2_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_UX2_SIZE );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UX2_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_UX2_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'U';\n    *l_ef++ = 'x';\n    *l_ef++ = (char)(EB_UX2_MINLEN);\n    *l_ef++ = (char)(EB_UX2_MINLEN >> 8);\n    *l_ef++ = (char)(s.st_uid);\n    *l_ef++ = (char)(s.st_uid >> 8);\n    *l_ef++ = (char)(s.st_gid);\n    *l_ef++ = (char)(s.st_gid >> 8);\n\n    z->ext += EB_L_UX2_SIZE;\n\n    /* Now add the central version of the field. */\n    *c_ef++ = 'U';\n    *c_ef++ = 'x';\n    *c_ef++ = 0;\n    *c_ef++ = 0;\n\n    z->cext += EB_C_UX2_SIZE;\n\n    return ZE_OK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'Be' extra field to the zlist data pointed to by z.              */\n\n#define EB_L_BE_SIZE    (EB_HEADSIZE + EB_L_BE_LEN) /* + attr size */\n#define EB_C_BE_SIZE    (EB_HEADSIZE + EB_C_BE_LEN)\n\n/* maximum memcompress overhead is the sum of the compression header length */\n/* (6 = ush compression type, ulg CRC) and the worstcase deflate overhead   */\n/* when uncompressible data are kept in 2 \"stored\" blocks (5 per block =    */\n/* byte blocktype + 2 * ush blocklength) */\n#define MEMCOMPRESS_OVERHEAD    (EB_MEMCMPR_HSIZ + EB_DEFLAT_EXTRA)\n\nlocal int add_Be_ef( struct zlist far *z )\n{\n    char *l_ef       = NULL;\n    char *c_ef       = NULL;\n    char *attrbuff   = NULL;\n    off_t attrsize   = 0;\n    char *compbuff   = NULL;\n    ush   compsize   = 0;\n    uch   flags      = 0;\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_BE_SIZE > USHRT_MAX ||\n        z->cext + EB_C_BE_SIZE > USHRT_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* Attempt to load up a buffer full of the file's attributes. */\n    {\n        int retval;\n\n        retval = get_attr_dir( z->name, &attrbuff, &attrsize );\n        if( retval != EOK ) {\n            return ZE_OPEN;\n        }\n        if( attrsize == 0 ) {\n            return ZE_OK;\n        }\n        if( attrbuff == NULL ) {\n            return ZE_LOGIC;\n        }\n\n        /* Check for way too much data. */\n        if( attrsize > (off_t)ULONG_MAX ) {\n            zipwarn( \"uncompressed attributes truncated\", \"\" );\n            attrsize = (off_t)(ULONG_MAX - MEMCOMPRESS_OVERHEAD);\n        }\n    }\n\n    if( verbose ) {\n        printf( \"\\t[in=%lu]\", (unsigned long)attrsize );\n    }\n\n    /* Try compressing the data */\n    compbuff = (char *)malloc( (size_t)attrsize + MEMCOMPRESS_OVERHEAD );\n    if( compbuff == NULL ) {\n        return ZE_MEM;\n    }\n    compsize = memcompress( compbuff,\n                            (size_t)attrsize + MEMCOMPRESS_OVERHEAD,\n                            attrbuff,\n                            (size_t)attrsize );\n    if( verbose ) {\n        printf( \" [out=%u]\", compsize );\n    }\n\n    /* Attempt to optimise very small attributes. */\n    if( compsize > attrsize ) {\n        free( compbuff );\n        compsize = (ush)attrsize;\n        compbuff = attrbuff;\n\n        flags = EB_BE_FL_NATURAL;\n    }\n\n    /* Check to see if we really have enough room in the EF for the data. */\n    if( ( z->ext + compsize + EB_L_BE_LEN ) > USHRT_MAX ) {\n        compsize = USHRT_MAX - EB_L_BE_LEN - z->ext;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_BE_SIZE + compsize );\n    } else {\n        l_ef = (char *)malloc( EB_L_BE_SIZE + compsize );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_BE_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_BE_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'B';\n    *l_ef++ = 'e';\n    *l_ef++ = (char)(compsize + EB_L_BE_LEN);\n    *l_ef++ = (char)((compsize + EB_L_BE_LEN) >> 8);\n    *l_ef++ = (char)((unsigned long)attrsize);\n    *l_ef++ = (char)((unsigned long)attrsize >> 8);\n    *l_ef++ = (char)((unsigned long)attrsize >> 16);\n    *l_ef++ = (char)((unsigned long)attrsize >> 24);\n    *l_ef++ = flags;\n    memcpy( l_ef, compbuff, (size_t)compsize );\n\n    z->ext += EB_L_BE_SIZE + compsize;\n\n    /* And the central version. */\n    *c_ef++ = 'B';\n    *c_ef++ = 'e';\n    *c_ef++ = (char)(EB_C_BE_LEN);\n    *c_ef++ = (char)(EB_C_BE_LEN >> 8);\n    *c_ef++ = (char)compsize;\n    *c_ef++ = (char)(compsize >> 8);\n    *c_ef++ = (char)(compsize >> 16);\n    *c_ef++ = (char)(compsize >> 24);\n    *c_ef++ = flags;\n\n    z->cext += EB_C_BE_SIZE;\n\n    return ZE_OK;\n}\n\n/* Extra field info:\n   - 'UT' - UNIX time extra field\n   - 'Ux' - UNIX uid/gid extra field\n   - 'Be' - BeOS file attributes extra field\n\n   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields\n   (full data in local header, only modification time in central header),\n   with the 'Be' field added to the end and the size of the 'Be' field\n   in the central header.\n\n   See the end of beos/osdep.h for a simple explanation of the 'Be' EF\n   layout.\n */\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* store full data in local header but just modification time stamp info\n     in central header */\n{\n    int retval;\n\n    /* Tell picky compilers to shut up about unused variables. */\n    z_utim = z_utim;\n\n    /* Check to make sure z is valid. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    /* This function is much simpler now that I've moved the extra fields */\n    /* out... it simplified the 'Be' code, too.                           */\n    retval = add_UT_ef( z );\n    if( retval != ZE_OK ) {\n        return retval;\n    }\n\n    retval = add_Ux_ef( z );\n    if( retval != ZE_OK ) {\n        return retval;\n    }\n\n    retval = add_Be_ef( z );\n    if( retval != ZE_OK ) {\n        return retval;\n    }\n\n    return ZE_OK;\n}\n\n/* ---------------------------------------------------------------------- */\n/* Set a file's MIME type.                                                */\nvoid setfiletype( const char *file, const char *type )\n{\n    int fd;\n    attr_info fa;\n    ssize_t wrote_bytes;\n\n    fd = open( file, O_RDWR );\n    if( fd < 0 ) {\n        zipwarn( \"can't open zipfile to write file type\", \"\" );\n        return;\n    }\n\n    fa.type = B_MIME_STRING_TYPE;\n    fa.size = (off_t)(strlen( type ) + 1);\n\n    wrote_bytes = fs_write_attr( fd, BE_FILE_TYPE_NAME, fa.type, 0,\n                                 type, fa.size );\n    if( wrote_bytes != (ssize_t)fa.size ) {\n        zipwarn( \"couldn't write complete file type\", \"\" );\n    }\n\n    close( fd );\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n# ifdef NO_RMDIR\n    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */\n    int r, len;\n    char *s;              /* malloc'd string for system command */\n\n    len = strlen(d);\n    if ((s = malloc(len + 34)) == NULL)\n      return 127;\n\n    sprintf(s, \"IFS=\\\" \\t\\n\\\" /bin/rmdir %s 2>/dev/null\", d);\n    r = system(s);\n    free(s);\n    return r;\n# else /* !NO_RMDIR */\n    return rmdir(d);\n# endif /* ?NO_RMDIR */\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n\n    printf(CompiledWith,\n\n#ifdef __MWERKS__\n      \"Metrowerks CodeWarrior\", \"\",\n#else\n#  ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#  endif\n#endif\n\n      \"BeOS\",\n\n#ifdef __POWERPC__\n      \" (PowerPC)\",\n#else\n#  ifdef __INTEL__\n      \" (x86)\",\n#  else\n      \" (UNKNOWN!)\",\n#  endif\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/beos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <support/Errors.h>     /* for B_NO_ERROR */\n\n#define USE_EF_UT_TIME          /* Enable use of \"UT\" extra field time info */\n\n#define EB_L_BE_LEN 5           /* min size is an unsigned long and flag */\n#define EB_C_BE_LEN 5           /* Length of data in local EF and flag.  */\n\n#define EB_BE_FL_NATURAL    0x01    /* data is 'natural' (not compressed) */\n#define EB_BE_FL_BADBITS    0xfe    /* bits currently undefined           */\n\n#ifndef ZP_NEED_MEMCOMPR\n#  define ZP_NEED_MEMCOMPR\n#endif\n\n/* Set a file's MIME type. */\n#define BE_FILE_TYPE_NAME   \"BEOS:TYPE\"\nvoid setfiletype( const char *file, const char *type );\n\n/*\nDR9 'Be' extra-field layout:\n\n'Be'      - signature\nef_size   - size of data in this EF (little-endian unsigned short)\nfull_size - uncompressed data size (little-endian unsigned long)\nflag      - flags (byte)\n            flags & EB_BE_FL_NATURAL    = the data is not compressed\n            flags & EB_BE_FL_BADBITS    = the data is corrupted or we\n                                          can't handle it properly\ndata      - compressed or uncompressed file attribute data\n\nIf flag & EB_BE_FL_NATURAL, the data is not compressed; this optimisation is\nnecessary to prevent wasted space for files with small attributes (which\nappears to be quite common on the Advanced Access DR9 release).  In this\ncase, there should be ( ef_size - EB_L_BE_LEN ) bytes of data, and full_size\nshould equal ( ef_size - EB_L_BE_LEN ).\n\nIf the data is compressed, there will be ( ef_size - EB_L_BE_LEN ) bytes of\ncompressed data, and full_size bytes of uncompressed data.\n\nIf a file has absolutely no attributes, there will not be a 'Be' extra field.\n\nThe uncompressed data is arranged like this:\n\nattr_name\\0 - C string\nstruct attr_info (big-endian)\nattr_data (length in attr_info.size)\n*/\n"
  },
  {
    "path": "deps/infozip/zip30/beos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  include <fcntl.h>\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/bzip2/install.txt",
    "content": "HOW TO ADD BZIP2 SUPPORT TO ZIP\n\nThis document describes how to add bzip2 support to Zip.\n\nCompiling or linking in the bzip2 library adds an additional bzip2\ncompression method to Zip.  This new method can be selected instead\nof the Zip traditional compression method deflation to compress files\nand often gives a better compression ratio (perhaps at the cost of\ngreater CPU time).  The compression method is specified using the\n\"-Z method\" command-line option, where \"method\" may be either \"deflate\"\n(the default), or \"bzip2\" (if Zip is built with bzip2 support).  Zip\nhas been tested with bzip2 library 1.0.5 and earlier.\n\nNotes\n\nCompression method bzip2 requires a modern unzip.  Before using bzip2\ncompression in Zip, verify that a modern UnZip program with bzip2 support\nwill be used to read the resulting zip archive so that entries compressed\nwith bzip2 (compression method 12) can be read.  Older unzips probably\nwon't recognize the compression method and will skip those entries.\n\nThe Zip source kit does not include the bzip2 library or source files, but\nthese can be found at \"http://www.bzip.org/\" for example.  See below for\nhow to add bzip2 to Zip for various operating systems.\n\nZip using bzip2 compression is not compatible with the bzip2 application,\nbut instead provides an additional way to compress files before adding\nthem to a Zip archive.  It does not replace the bzip2 program itself,\nwhich creates bzip2 archives in a different format that are not\ncompatible with zip or unzip.\n \nThe bzip2 code and algorithms are provided under the bzip2 license\n(provided in the bzip2 source kit) and what is not covered by that license\nis covered under the Info-ZIP license.  Info-ZIP will look at issues\ninvolving the use of bzip2 compression in Zip, but any questions about\nthe bzip2 code and algorithms or bzip2 licensing, for example, should be\ndirected to the bzip2 maintainer.\n\n\nInstallation\n\nTo build Zip with bzip2 support, Zip generally needs one bzip2 header\nfile, \"bzlib.h\", and the object library, typically \"libbz2.a\", except\nin cases where the source files are compiled in directly.  If you\nare either compiling the bzip2 library or compiling in the bzip2\nsource files, we recommend defining the C macro BZ_NO_STDIO, which\nexcludes a lot of standalone error code (not used when bzip2 is\nused as a library and makes the library smaller) and provides hooks\nthat Zip can use to provide better error handling.  However, a\nstandard bzip2 object library will work, though any errors that bzip2\ngenerates may be more cryptic.\n\nBuilding the bzip2 library from the bzip2 source files (recommended):\n\n  Download the latest bzip2 package (from \"http://www.bzip.org/\", for\n  example).\n     \n  Unpack the bzip2 source kit (bzip2-1.0.5.tar.gz was current as of\n  this writing, but the latest should work).\n\n  Read the README file in the bzip2 source kit.\n\n  Compile the bzip2 library for your OS, preferably defining\n  BZ_NO_STDIO.  Note: On UNIX systems, this may be done automatically\n  when building Zip, as explained below.\n\n\nInstallation on UNIX (see below for installation on other systems):\n\n  Note:  Zip on UNIX uses the \"bzlib.h\" include file and the compiled\n  \"libbz2.a\" library to static link to bzip2.  Currently we do not\n  support using the shared library (patches welcome).\n\n  The easiest approach may be to drop the two above files in the\n  bzip2 directory of the Zip source tree and build Zip using the\n  \"generic\" target, that is, using a command like\n    make -f unix/Makefile generic\n  If all goes well, make should confirm that it found the files and\n  will be compiling in bzip2 by setting the BZIP2_SUPPORT flag and\n  then including the libraries while compiling and linking Zip.\n\n  To use bzlib.h and libbz2.a from somewhere else on your system,\n  define the \"make\" macro IZ_BZIP2 to point to that directory.  For\n  example:\n    make -f unix/Makefile generic IZ_BZIP2=/mybz2\n  where /mybz2 might be \"/usr/local/src/bzip2/bzip2-1.0.5\" on some\n  systems.  Only a compiled bzip2 library can be pointed to using\n  IZ_BZIP2 and Zip will not compile bzip2 source in other than the\n  bzip2 directory.\n\n  If IZ_BZIP2 is not defined, Zip will look for the bzip2 files in\n  the \"bzip2\" directory in the Zip source directory.  The bzip2\n  directory is empty in the Zip source distribution (except for\n  this install.txt file) and is provided as a place to put the\n  bzip2 files.  To use this directory, either drop bzlib.h and\n  libbz2.a in it to use the compiled library as noted above or drop\n  the contents of the bzip2 source kit in this directory so that\n  bzlib.h is directly in the bzip2 directory and Zip will try to\n  compile it if no compiled library is already there.\n\n\n  Unpacking bzip2 so Zip compiles it:\n\n  To make this work, the bzip2 source kit must be unpacked directly\n  into the Zip \"bzip2\" directory.  For example:\n\n      # Unpack the Zip source kit.\n      gzip -cd zip30.tar-gz | tar xfo -\n      # Move down to the Zip kit's \"bzip2\" directory, ...\n      cd zip30/bzip2\n      # ... and unpack the bzip2 source kit there.\n      gzip -cd ../../bzip2-1.0.5.tar.gz | tar xfo -\n      # Move the bzip2 source files up to the Zip kit's bzip2 directory.\n      cd bzip2-1.0.5\n      mv * ..\n      # Return to the Zip source kit directory, ready to build.\n      cd ../..\n      # Build Zip.\n      make -f unix/Makefile generic\n\n\n  Using a system bzip2 library:\n\n  If IZ_BZIP2 is not defined and both a compiled library and the bzip2\n  source files are missing from the Zip bzip2 directory, Zip will test\n  to see if bzip2 is globally defined on the system in the default\n  include and library paths and, if found, link in the system bzip2\n  library.  This is automatic.\n\n\n  Preventing inclusion of bzip2:\n\n  To build Zip with _no_ bzip2 support on a system where the automatic\n  bzip2 detection scheme will find bzip2, you can specify a bad\n  IZ_BZIP2 directory.  For example:\n\n      make -f unix/Makefile generic IZ_BZIP2=no_such_directory\n\n  You can also define NO_BZIP2_SUPPORT to exclude bzip2.\n\n\n  Verifying bzip2 support in Zip:\n\n  When the Zip build is complete, verify that bzip2 support has been\n  enabled by checking the feature list:\n\n      ./zip -v\n\n  If all went well, bzip2 (and its library version) should be listed.\n\n\nInstallation on other systems\n\n  MSDOS:\n\n  Thanks to Robert Riebisch, the DJGPP 2.x Zip port now supports bzip2.\n  To include bzip2, first install bzip2.  The new msdos/makebz2.dj2\n  makefile then looks in the standard bzip2 installation directories\n  for the needed files.  As he says:\n    It doesn't try to be clever about finding libbz2.a. It just\n    expects bzip2 stuff installed to the default include and library\n    folders, e.g., \"C:\\DJGPP\\include\" and \"C:\\DJGPP\\lib\" on DOS.\n\n  Given a standard DJGPP 2.x installation, this should create a\n  version of Zip 3.0 with bzip2 support.\n\n  The bzip2 library for DJGPP can be found on any DJGPP mirror in\n  \"current/v2apps\" (or \"beta/v2apps/\" for the latest beta). This\n  library has been ported to MSDOS/DJGPP by Juan Manuel Guerrero.\n\n\n  WIN32 (Windows NT/2K/XP/2K3/... and Windows 95/98/ME):\n\n  For Windows there seems to be two approaches, either use bzip2\n  as a dynamic link library or compile the bzip2 source in directly.\n  I have not gotten the static library libbz2.lib to work, but that\n  may be me.\n\n  Using bzip2 as a dynamic link library:\n\n    Building bzip2:\n\n    If you have the needed bzlib.h, libbz2.lib, and libbz2.dll files\n    you can skip building bzip2.  If not, open the libbz2.dsp project\n    and build libbz2.dll\n\n    This creates\n      debug/libbz2.lib\n    and\n      libbz2.dll\n\n\n    Building Zip:\n\n    Copy libbz2.lib to the bzip2 directory in the Zip source tree.  This\n    is needed to compile Zip with bzip2 support.  Also copy the matching\n    bzlib.h from the bzip2 source to the same directory.\n\n    Add libbz2.lib to the link list for whatever you are building.  Also\n    define the compiler define BZIP2_SUPPORT.\n\n    Build Zip.\n\n\n    Using Zip with bzip2 as dll:\n\n    Put libbz2.dll in your command path.  This is needed to run Zip with\n    bzip2 support.\n\n    Verify that bzip2 is enabled with the command\n\n      zip -v\n\n    You should see bzip2 listed.\n\n  Compiling in bzip2 from the bzip2 source:\n\n    This approach compiles in the bzip2 code directly.  No external\n    library is needed.\n\n    Get a copy of the bzip2 source and copy the contents to the bzip2\n    directory in the Zip source tree so that bzlib.h is directly in\n    the bzip2 directory.\n\n    Use the vc6bz2 project to build Zip.  This project knows of the\n    added bzip2 files.\n\n    Verify that bzip2 is enabled with the command\n\n      zip -v\n\n\n  Windows DLL (WIN32):\n\n  Nothing yet.\n\n\n  Mac OS X:\n\n  Follow the standard UNIX build procedure.  Mac OS X includes bzip2\n  and the UNIX builders should find the bzip2 files in the standard\n  places.  Note that the version of bzip2 on your OS may not be\n  current and you can instead specify a different library or compile\n  your own bzip2 library as noted in the Unix procedures above.\n\n\n  OS/2:\n\n  Nothing yet.\n\n\n  VMS (OpenVMS):\n\n  See [.vms]install_vms.txt for how to enable bzip2 support on VMS.\n\n\nLast updated 26 March 2007, 15 July 2007, 9 April 2008, 27 June 2008\nS. Schweda, E. Gordon\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/README.CMS",
    "content": "Using ZIP and UNZIP on VM/CMS\n=============================\n\n\nInstalling executables\n----------------------\n\nThe following CMS MODULEs are available:\n   ZIP\n   ZIPNOTE\n   ZIPCLOAK\n   ZIPSPLIT\n   UNZIP\n\nIn addition to these, each MODULE file also has an EXEC with the same\nname.  These EXECs are front-ends to the MODULES that will attempt to\nset up the required runtime libraries before running the MODULE.\nAll the EXECs are identical.  Only their names are different.\nThey are stored as plain text files.\n\nThe CMS MODULE files have been packed using the COPYFILE command to\nallow their file format to be properly restored, since variable length\nbinary files will not currently unzip properly (see below for details).\nThe MODULEs are shipped with a filetype or extension of CMO (for CMS\nMODULE).  Their names may vary on the distribution disk to indicate\ntheir level, etc.\n\nTo restore them to executable MODULEs on CMS, do the following:\n   1. Upload them to CMS with a Fixed record length with LRECL 1024.\n      Example, from a DOS or OS/2 window, type this:\n         SEND unzip.cmo A:unzip module a (RECFM F LRECL 1024\n\n      Example, using FTP from CMS, type this:\n         BINARY FIXED 1024\n         GET unzip.cmo unzip.module.a\n\n      Note:  Replace \"unzip.cmo\" with the actual name.\n\n   2. Use COPYFILE to unpack the file.\n      Example, in CMS type this:\n         COPYFILE UNZIP MODULE A (UNPACK REPLACE OLDDATE\n\n   3. Repeat steps 1-2 for each of the programs.\n\n   4. Build the ZIPINFO module by typing this:\n         COPYFILE UNZIP MODULE A ZIPINFO MODULE A (OLDDATE\n\n   5. Upload the EXECs to CMS as text files (with ASCII-to-EBCDIC\n      translation).\n      Example, from a DOS or OS/2 window, type this:\n         SEND unzip.exc A:unzip exec a (CRLF\n\n      Example, using FTP from CMS, type this:\n         GET unzip.exc unzip.exec.a\n\n   6. Repeat steps 4 for each of the EXECs.\n\n\nPreparing the environment\n-------------------------\n\nThe executables provided were compiled with IBM C 3.1.0 and\nrequire the the Language Environment (LE) runtime libraries.\n\nTo provide access to the runtime libraries:\n   1. Link to the disk containing the Language Environment files,\n      if necessary.\n\n   2. Use the command \"GLOBAL LOADLIB SCEERUN\"\n\n   These commands can be placed in your PROFILE EXEC.\n\n   Note:  EXECs have been provided called ZIP, UNZIP, etc. that\n   issue the GLOBAL LOADLIB statement.  This was done to alleviate\n   frustration of users that don't have the GLOBAL LOADLIB statement\n   in their PROFILE EXEC.  These EXECs may require changing for\n   your system.\n\n   Unfortunately, there is no way, using IBM C, to produce a MODULE\n   that doesn't require a runtime library.\n\n\nTesting\n-------\n\nTo test the MODULEs, just type ZIP or UNZIP.  They should\nshow help information on using the commands.\n\nIf you see something like this:\n   DMSLIO201W The following names are undefined:\n    CEEEV003\n   DMSABE155T User abend 4093 called from 00DCD298 reason code 000003EB\n\nThen you don't have access to the proper runtime libraries, as\ndescribed above.\n\nHere is additional information on the ZIP and UNZIP programs that\nmay assist support personnel:\n   - Compiled with IBM C V3R1M0 on VM/ESA 2.2.0 with\n     CMS level 13 Service Level 702.\n\n   - Require the SCEERUN LOADLIB runtime library.  This is\n     part of the Language Environment (LE).\n\n   - Linked with options RMODE ANY AMODE ANY RLDSAVE.\n\nIf you continue to have trouble, report the problem to Zip-Bugs\n(see the bottom of this document).\n\n\n\nCompiling the source on VM/CMS\n------------------------------\n\nThe source has been successfully compiled previously using\nC/370 2.1 and 2.2.  The source has been recently compiled using\nIBM C 3.1.0 on VM/ESA 2.2.0 with CMS level 13.  I don't have\naccess to an MVS system so the code hasn't been tested there\nin a while.\n\n 1. Unzip the source files required for CMS.  The root-level files\n    inside the ZIP file and the files in the CMSMVS subdirectory are\n    needed.  Example (use both commands):\n       unzip -aj zip23.zip -x */*   -dc\n       unzip -aj zip23.zip cmsmvs/* -dc\n\n    This example unzips the files to the C-disk, while translating\n    character data and ignoring paths.\n\n    If you don't already have a working UNZIP MODULE on CMS you will\n    have to unzip the files on another system and transport them\n    to CMS.  All the required files are plain text so they can\n    be transferred with ASCII-to-EBCDIC translations.\n\n 2. Repeat step 1 with the zip file containing the UNZIP code.\n    Unzip the files to a different disk than the disk used for the ZIP\n    code.\n\n 3. To compile the ZIP code, run the supplied CCZIP EXEC.\n    To compile the UNZIP code, run the supplied CCUNZIP EXEC.\n\nNOTE:\nSome of the ZIP and UNZIP source files have the same name.  It is\nrecommended that you keep the source from each on separate disks and\nmove the disk you are building from ahead of the other in the search\norder.\n\nFor example, you may have a 192 disk with the ZIP source code and\na 193 disk with the UNZIP source code.  To compile ZIP, access\nthe 192 disk as B, then run CCZIP.  This will create the following\nmodules:  ZIP, ZIPNOTE, ZIPSPLIT, ZIPCLOAK.\n\nTo compile UNZIP, access 193 as B, then run CCUNZIP.  This will create\nthe following modules:  UNZIP, ZIPINFO (a copy of UNZIP).\n\n\n=========================================================================\n\n\nUsing ZIP/UNZIP\n---------------\n\nDocumentation for the commands is in MANUAL NONAME (for ZIP) and in\nUNZIP DOC UNZIP.  INFOZIP DOC describes the use of the -Z option of\nUNZIP.\n\nThe rest of this section explains special notes concerning the VM/CMS\nversion of ZIP and UNZIP.\n\n\nFilenames and directories\n-------------------------\n\n 1. Specifying filenames\n\n    a. When specifying CMS files, use filename.filetype.filemode format\n       (separate the three parts of the name with a period and use no\n       spaces).  Example:  profile.exec.a\n\n       Unfortunately, this prevents you from using ZIP from\n       FILELIST.  To unzip a zip file, however, you can type something\n       like this next to it in FILELIST:\n          unzip /n -d c\n\n       This will unzip the contents of the current file to a C-disk.\n\n    b. It is possible to use DD names with ZIP and UNZIP on CMS, though\n       it can be cumbersome.  Example:\n          filedef out disk myzip zip a\n          zip dd:out file1.txt file2.txt\n\n       While you can also use a DD name for the input files, ZIP\n       currently does not correctly resolve the filename and will\n       store something like \"dd:in\" inside the ZIP file.  A file stored\n       in this manor cannot easily be unzipped, as \"dd:in\" is an invalid\n       filename.\n\n    c. In places where a directory name would be used on a PC, such as\n       for the ZIP -b (work path) option or the UNZIP -d (destination\n       path) options, use a filemode letter for CMS.  For example,\n       to unzip files onto a C-disk, you might type something like this:\n          unzip myzip.zip -d c\n\n       Currently, ZIP uses the A-disk for work files.  When zipping\n       large files, you may want to specify a larger disk for work files.\n       This example will use a C-disk for work files.\n          zip -b C myzip.zip.c test.dat.a\n\n\n 2. Filename conversions\n\n    a. Filemode letters are never stored into the zip file or take from\n       a zip file.  Only the filename and filetype are used.\n       ZIP removes the filemode when storing the filename into the\n       zip file.  UNZIP assumes \"A\" for the filemode unless the -d\n       option is used.\n\n    b. When unzipping, any path names are removed from the fileid\n       and the last two period-separated words are used as the\n       filename and filetype.  These are truncated to a maximum of\n       eight characters, if necessary.  If the filetype (extension)\n       is missing, then UNZIP uses \"NONAME\" for the filetype.\n       Any '(' or ')' characters are removed from the fileid.\n\n    c. All files are created in upper-case.  Files in mixed-case\n       cannot currently be stored into a ZIP file.\n\n    d. Shared File System (SFS) directories are not supported.\n       Files are always accessed by fn.ft.fm.  To use an SFS disk,\n       Assign it a filemode, then it can be used.\n\n\n 3. Wildcards in file names\n\n    a. Wildcards are not supported in the zip filename.  The full\n       filename of the zip file must be given (but the .zip is not\n       necessary).  So, you can't do this:\n          unzip -t *.zip\n\n    b. Wildcards CAN be used with UNZIP to select (or exclude) files\n       inside a zip file.  Examples:\n          unzip myzip *.c          - Unzip all .c files.\n          unzip myzip *.c -x z*.c  - Unzip all .c files but those\n                                     starting with Z.\n\n    c. Wildcards cannot currently be used to select files with ZIP.\n       So, you can't do this:\n          zip -a myzip *.exec\n\n       I expect to fix this for CMS in the future.\n\n\n 4. File timestamps\n\n    a. The dates and times of files being zipped or unzipped are not\n       currently read or set.  When a file is zipped, the timestamp\n       inside the zip file will always be the current system date and\n       time.  Likewise, when unzipping, the date and time of files\n       being unzipped will always be the current system date/time.\n\n    b. Existing files are assumed to be newer than files inside a zip\n       file when using the -f freshen option of UNZIP.  This will prevent\n       overwriting files that may be newer than the files inside the\n       zip file, but also effectively prevents the -f option from working.\n\n\n 5. ASCII, EBCDIC, and binary data\n\n    Background\n    ----------\n    Most systems create data files as just a stream of bytes.  Record\n    breaks happen when certain characters (new line and/or carriage\n    return characters) are encountered in the data.  How to interpret\n    the data in a file is up to the user.  The system must be told\n    to either notice new line characters in the data or to assume\n    that the data in the file is binary data and should be read or\n    written as-is.\n\n    CMS and MVS are record-based systems.  All files are composed\n    of data records.  These can be stored in fixed-length files or\n    in variable length files.  With fixed-length files, each record\n    is the same length.  The record breaks are implied by the\n    LRECL (logical record length) attribute associated with the file.\n    With variable-length files, each record contains the length of\n    that record.  The separation of records are not part of the\n    data, but part of the file structure.\n\n    This means you can store any type of data in either type of file\n    structure without having to worry about the data being interpreted\n    as a record break.  Fixed-length files may have padding at the\n    end of the file to make up a full record.  Variable-length files\n    have no padding, but require extra record length data be stored\n    with the file data.\n\n    Storing fixed-length files into a zip file is simple, because all\n    the data can just be dumped into the zip file and the record\n    format (RECFM) and logical record length (LRECL) can be stored\n    in the extra data area of the zip file so they can be restored\n    when UNZIP is used.\n\n    Storing variable-length data is harder.  There is no place to put\n    the record length data needed for each record of the file.  This\n    data could be written to the zip file as the first two bytes of\n    each record and interpreted that way by UNZIP.  That would make\n    the data unusable on systems other than CMS and MVS, though.\n\n    Currently, there isn't a solution to this problem.  Each record is\n    written to the zip file and the record length information is\n    discarded.  Binary data stored in variable-length files can't be put\n    into a zip file then later unzipped back into the proper records.\n    This is fine for binary data that will be read as a stream of bytes\n    but not OK where the records matter, such as with CMS MODULEs.\n\n    If the data is text (character data), there is a solution.\n    This data can be converted into ASCII when it's stored into\n    a zip file.  The end of each record is now marked in the file\n    by new line characters.  Another advantage of this method is\n    that the data is now accessible to non-EBCDIC systems.  When\n    the data is unzipped on CMS or MVS, it is converted back into\n    EBCDIC and the records are recreated into a variable-length file.\n\n\n    So, here's what we have...\n\n    a. To store readable text data into a zip file that can be used\n       on other platforms, use the -a option with ZIP to convert the\n       data to ASCII.  These files will unzip into variable-length\n       files on CMS and should not contain binary data or corruption\n       may occur.\n\n    b. Files that were zipped on an ASCII-based system will be\n       automatically translated to EBCDIC when unzipped.  To prevent\n       this (to unzip binary data on CMS that was sent from an\n       ASCII-based system), use the -B option with UNZIP to force Binary\n       mode.  To zip binary files on CMS, use the -B option with ZIP to\n       force Binary mode.  This will prevent any data conversions from\n       taking place.\n\n    c. When using the ZIP program without specifying the \"-a\" or \"-B\"\n       option, ZIP defaults to \"native\" (EBCDIC) mode and tries to\n       preserve the file information (RECFM, LRECL, and BLKSIZE).  So\n       when you unzip a file zipped with ZIP under CMS or MVS, UNZIP\n       restores the file info.  The output will be fixed-length if the\n       original was fixed and variable-length if the original was\n       variable.\n\n    If UNZIP gives a \"write error (disk full?)\"  message, you may be\n    trying to unzip a binary file that was zipped as a text file\n    (without using the -B option)\n\n\n    Summary\n    -------\n    Here's how to ZIP the different types of files.\n\n    RECFM F text\n       Use the -a option with ZIP to convert to ASCII for use with other\n       platforms or no options for use on EBCDIC systems only.\n\n    RECFM V text\n       Use the -a option with ZIP to convert to ASCII for use with other\n       platforms or no options for use on EBCDIC systems only.\n\n\n    RECFM F binary\n       Use the -B option with ZIP (upper-case \"B\").\n\n    RECFM V binary\n       Use the -B option with ZIP.  Can be zipped OK but the record\n       structure is destroyed when unzipped.  This is OK for data files\n       read as binary streams but not OK for files such as CMS MODULEs.\n\n\n 6. Character Sets\n\n    If you are used to running UNZIP on systems like UNIX, DOS, OS/2 or\n    Windows, you will may have some problems with differences in the\n    character set.\n\n    There are a number of different EBCDIC code pages, like there are a\n    number of different ASCII code pages.  For example, there is a US\n    EBCDIC, a German EBCDIC, and a Swedish EBCDIC.  As long as you are\n    working with other people who use the same EBCDIC code page, you\n    will have no trouble.  If you work with people who use ASCII, or who\n    use a different EBCDIC code page, you may need to do some\n    translation.\n\n    UNZIP translates ASCII text files to and from Open Systems EBCDIC\n    (IBM-1047), which may not be the EBCDIC that you are using.  For\n    example, US EBCDIC (IBM-037) uses different character codes for\n    square brackets.  In such cases, you can use the ICONV utility\n    (supplied with IBM C) to translate between your EBCDIC character set\n    and IBM-1047.\n\n    If your installation does not use IBM-1047 EBCDIC, messages from\n    UNZIP may look a little odd.  For example, in a US EBCDIC\n    installation, an opening square bracket will become an i-acute and a\n    closing square bracket will become a u-grave.\n\n    The supplied ZIP and UNZIP EXECs attempt to correct this by setting\n    CMS INPUT and OUTPUT translations to adjust the display of left and\n    right brackets.  You may need to change this if brackets don't\n    display correctly on your system.\n\n\n 7. You can unzip using VM/CMS PIPELINES so unzip can be used as\n    a pipeline filter.  Example:\n       'PIPE COMMAND UNZIP -p test.zip george.test | Count Lines | Cons'\n\n\n\n\nPlease report all bugs and problems to:\n   Zip-Bugs@lists.wku.edu\n\n\n-----------------------------------------------------------------------\nOriginal CMS/MVS port by George Petrov.\ne-mail:  c888090@nlevdpsb.snads.philips.nl\ntel:     +31-40-781155\n\nPhilips C&P\nEindhoven\nThe Netherlands\n\n-----------------------------------------------------------------------\nAdditional fixes and README re-write (4/98) by Greg Hartwig.\ne-mail:  ghartwig@ix.netcom.com\n         ghartwig@vnet.ibm.com\n\n-----------------------------------------------------------------------\nAdditional notes from Ian E. Gorman.\ne-mail:  ian@iosphere.net\n\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/README.MVS",
    "content": "Thank you for trying this first port of ZIP for VM/CMS and MVS!\n\n\n                        Using under MVS:\n                    ---------------------------\n\n1. To use the Info-ZIP's ZIP under MVS you need:\n\n   - C/370 ver 2.1 compiler or another compatible compiler supporting\n     long names for function/variable names.\n\n2. To compile the program under MVS do :\n\n   - unzip all the files from zip22.zip file. They are stored as\n     ASCII format so you have to unzip them first on PC or other\n     system that already have UNZIP, and then upload them to the\n     mainframe with ASCII to EBCDIC conversion.\n\n   - Copy all the .C files in the PDS called youruserid.ZIP.C\n\n   - Copy all the .H files in the PDS called youruserid.ZIP.H\n\n   - adjust the job ZIPMVSC.JOB to work on your size. Change my\n     userid - C888090 to yours\n\n   - execute the job ZIPMVSC to compile and link all the sources.\n\n   - maybe you have to preallocate PDS datasets named:\n     youruserid.ZIP.OBJ and youruserid.ZIP.LOAD\n\n   - execute ZIPVMC to compile and link all the sources.\n\n   - if everything is ok you will get an ZIP MODULE\n\n   - the warnings about the duplicated ASCII and EBCDIC symbols\n     are OK :-)\n\n3. Using ZIP\n\n   - Just read MANUAL\n\n   - A few exceptions concerning MVS\n\n     3.1. if you want to make a portable zip file that is to be unzipped\n          on ASCII based systems use the -a option\n\n     3.2. If you want to zip the input files as binary ebcdic files\n          use the -B (capital letter) option\n\n     3.3. The date/end the time of the input files is set in the zip's\n          dir to the current system date/time\n\n     3.4. Without specifying the \"-a\" or \"-B\" option, the ZIP program\n          defaults to \"native\" (EBCDIC) mode and tries to preserve the\n          file information (LRECL,BLKSIZE..)\n          So when you UNZIP a file zipped with ZIP under VM/MVS it\n          restores the file info.\n\n          There currently some problems with file with RECFM=V*\n          I don't save the length of each record yet :-)\n\n     3.5. No wildcards are supported as input file names:\n\n          So you CAN'T use things like: zip myzip *.c\n\n     3.6. You can use DD names for zipfilename for example:\n\n          under tso/rexx:\n\n           \"alloc fi(input) da('myzip.zip')\"\n           \"zip dd:input file1.txt file2.txt ...\"\n\n          under Batch:\n\n           //MYZIP    JOB  (account)\n           //STEP1    EXEC PGM=ZIP,PARM='dd:input file1.txt file2.txt'\n           //STEPLIB  DD DSN=userid.UNZIP.LOAD,DISP=SHR\n           //INPUT    DD DSN=userid.MYZIP.ZIP,DISP=NEW,\n           //            SPACE=(15000,(15000,10000),RLSE),\n           //            DCB=(LRECL=80,RECFM=F)\n           //SYSPRINT DD SYSOUT=*\n\n\nPlease report all bugs and problems to :\n     zip-bugs@lists.wku.edu\n\nThat's all for now.\n\nHave fun!\n\n\nGeorge Petrov\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/README.MVS.LE",
    "content": "Notes on Zip under MVS Language Environment (LE).\n\nFirst see README.MVS.  This note describes just one beta test on OS/390\nV2R5 using IBM's C compiler (5647A01), V2R4.  The major difference is\nthe use of LE on the beta site, together with some MVS native mode\nfixes.  Changes have not been tested on CMS.\n\nSome of the notes are to clarify things that were not clear from the\nMANUAL or README.MVS.\n\n1.  By default, IBM C generates the same csect name for each input\n    source.  The prelink stage does not rename them and the linkage\n    editor throws away all but the first occurrence of each duplicate.\n    Oops, my code just disappeared :(.\n\n    To get around this \"feature\", compile with the CSECT option to\n    force sensible names on the code and data sections of each csect.\n    The name of the static data csect defaults to the source name in\n    lower case, the code csect defaults to the source name in upper\n    case.  These csect names still have to be unique, they cannot be\n    the same as function names.  Of course, several csects have a\n    function which is the same name as the source in lower case, not\n    exactly an unusual occurrence.  Therefore to make the csect name\n    unique, some of the sources have\n\n    #ifdef MVS\n    #  pragma csect(STATIC,xxxx_s)\n    #endif\n\n    Where xxxx is an abbreviation of the source name.  There has to be\n    a better way!\n\n2.  The prelink step always gets cond code 4.  It complains about\n    unresolved references, ignore it unless the linker also complains.\n    Prelink also complains about duplicate @@PPA2 sections and so does\n    the linker, but it seems to do no harm.  Compile and link steps\n    should get 0, just prelink gets 4.  See JCL at the bottom.\n\n3.  Under MVS native mode (not Open Edition), tmpnam() returns a quoted\n    name of 5 qualifiers.  The first is a HLQ chosen according to the\n    MVS LE algorithm (see below), the other qualifiers are time stamps.\n    If running on MVS and tmpnam() returns a quoted name with at leat\n    one '.', it is only safe to let the user change the high level\n    qualifier.  Therefore -b insists on a single qualifier without '.'\n    in the MVS native environment.\n\n4.  In Open Edition (OE) mode, the manual says that tmpnam() returns a\n    fully qualified name in directory TMPDIR or /tmp if TMPDIR is not\n    set.  There is no point in zip trying to override that name so -b\n    is ignored in MVS OE mode (untested).  The user should specify\n    environment variable TMPDIR instead.\n\n5.  The MVS LE algorithm for choosing the high level qualifier for\n    native filenames is interesting, as in \"May you live in interesting\n    times\".  The HLQ varies according to the environment the program is\n    running in, sometimes it is userid, sometimes it is TSO prefix.\n    See OS/390 C/C++ Programming Guide, Using a Data Set Name,\n    somewhere around section 2.9.\n\n    If in doubt, use fully qualified and quoted names.  Instead of\n    archive.zip, use 'prefix.archive.zip'.  For input files, instead of\n    filename, use 'prefix.filename'.  For PARM= in JCL, double up the\n    quotes.  You even have to quote filenames in stdin.\n\n6.  If your PARM includes any '/', make sure the PARM starts with '/'.\n    LE assumes anything before the first '/' is LE run time parameters.\n    It does no harm to always code a leading '/' for LE parms.\n\n7.  JCL limits a PARM= to 100 characters total with approx. 65 on a\n    single line.  Alas the syntax for continuing PARM= always embeds an\n    extra ',' somewhere in the parameters that the program finally\n    gets.  No workaround, limit your PARM to a single line.  With the\n    extra quotes around filenames, that does not leave much room.  In\n    most cases, you will have to use '-@' to read the list of filenames\n    from SYSIN (stdin), it will not fit on a single PARM line.\n\n8.  Filenames can be dataset names or you can refer to a ddname with\n    'DD:name', case insensitive for external files, case sensitive for\n    OE files.  You can even specify 'dd:name(mem)'.  No wildcards, to\n    zip a complete pds you have to specify each member individually.\n    Directory recursion in OE does not appear to work at the moment.\n\n9.  Zip attempts to map MVS filenames to Unix style names.  It did not\n    work correctly for quoted names, fixed.  Although you can pick up\n    an external (non-OE) file with a name using any case, be aware that\n    the mapping to a Unix style name faithfully follows the case you\n    supply.\n\n10. The archive file was being created with recfm=V and lrecl=32760.\n    32760 is not valid for recfm=V under MVS, I originally changed it\n    to lrecl=32756.  Then zip broke trying to fseek() over a record\n    boundary, I do not know whether this was a zip or LE bug.  Trial\n    and error showed that recfm=U with byteseek seems to work on MVS.\n    No BDW or RDW, just a byte stream.  The blocksize is always 6144.\n\n    NOTE: This is an incompatible change from the previous beta,\n          archive files used to be recfm=V.  That should not matter\n          because we just transfer the data, ignoring BDW and RDW\n          anyway.\n\n11. Zip used to complain about preallocated but empty archives, wrong\n    length records, no signature etc.  The usual IBM/360 problem of no\n    end of file marker in a new, unopened dataset.  Fixed, see routine\n    readzipfile in zipfile.c for the gory details.  PARM= works fine.\n\n12. Several source files have records that are more than 80 bytes long.\n    It works if you transfer to mainframe datasets with a larger lrecl,\n    I used recfm=fb,lrecl=120 for the .C and .H files.  To compile with\n    anything longer than 72 bytes, you need MVS C options NOMARGINS and\n    NOSEQUENCE (NOMAR,NOSEQ).\n\n13. cmsmvs was still using zname instead of name for open.  Fixed.\n\n14. zip has to jump through a lot of hoops to see if an existing\n    zipfile actually contains data.  A side effect of this is that\n    creating a zipfile with the RLSE parameter is a waste of time.\n\nKeith Owens <kaos@ocs.com.au>.  Not a maintainer, just a beta tester.\nMon Sep 14 19:31:30 EST 1998\n\n\nSample JCL to compile Zip under MVS LE.  You might need a large region,\nI used REGION=128M on the job card.  Also watch the output lines,\n75,000 with OPT(2), 100,000+ with OPT(2) replaced with DEF(DEBUG).  You\nneed to allocate prefix.ZIP.C.OBJ (recfm=FB, lrecl=80) and\nprefix.ZIP.LOAD (recfm=U, blksize is site defined).\n\n//CBC    JCLLIB ORDER=CBC.SCBCPRC\n//ZIP EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(ZIP)',\n//    OUTFILE='prefix.ZIP.C.OBJ(ZIP),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//CRYPT EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(CRYPT)',\n//    OUTFILE='prefix.ZIP.C.OBJ(CRYPT),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//TTYIO EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(TTYIO)',\n//    OUTFILE='prefix.ZIP.C.OBJ(TTYIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//TREES EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(TREES)',\n//    OUTFILE='prefix.ZIP.C.OBJ(TREES),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//DEFLATE EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(DEFLATE)',\n//    OUTFILE='prefix.ZIP.C.OBJ(DEFLATE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//FILEIO EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(FILEIO)',\n//    OUTFILE='prefix.ZIP.C.OBJ(FILEIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//GLOBALS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(GLOBALS)',\n//    OUTFILE='prefix.ZIP.C.OBJ(GLOBALS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//UTIL EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(UTIL)',\n//    OUTFILE='prefix.ZIP.C.OBJ(UTIL),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//CRC32 EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(CRC32)',\n//    OUTFILE='prefix.ZIP.C.OBJ(CRC32),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//CRCTAB EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(CRCTAB)',\n//    OUTFILE='prefix.ZIP.C.OBJ(CRCTAB),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//ZIPFILE EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(ZIPFILE)',\n//    OUTFILE='prefix.ZIP.C.OBJ(ZIPFILE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//ZIPUP EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(ZIPUP)',\n//    OUTFILE='prefix.ZIP.C.OBJ(ZIPUP),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//CMSMVS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(CMSMVS)',\n//    OUTFILE='prefix.ZIP.C.OBJ(CMSMVS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//MVS EXEC EDCC,COND=(0,NE),CREGSIZ='4M',\n//    INFILE='prefix.ZIP.C(MVS)',\n//    OUTFILE='prefix.ZIP.C.OBJ(MVS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE',\n//    CPARM2='OPT(2),DEF(MVS),NOMAR,NOSEQ,CSECT'\n//COMPILE.USERLIB DD DSN=prefix.ZIP.H,DISP=SHR\n//PLINK   EXEC  PROC=EDCPL,\n//    OUTFILE='prefix.ZIP.LOAD(ZIP),DISP=SHR',\n//    PREGSIZ=6M,\n//    PPARM='NONCAL,MAP,MEMORY',\n//    LPARM='LIST,MAP,XREF'\n//PLKED.SYSIN   DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIP)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRYPT)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(TREES)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(DEFLATE)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(FILEIO)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(GLOBALS)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(UTIL)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRC32)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CRCTAB)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIPFILE)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(ZIPUP)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(MVS)\n//              DD  DISP=SHR,DSN=prefix.ZIP.C.OBJ(CMSMVS)\n//LKED.SYSLIB   DD  DISP=SHR,DSN=CEE.SCEELKED\n//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(2,2))\n//\n\nSample JCL to zip the mainframe .C and .H files as ASCII (-a).  Delete\nany existing archive first, point the temporary file at a particular\nprefix (-b), use 'prefix.ARCHIVE.ZIP' for the archive file, read the\nlist of files to zip from stdin (SYSIN).\n\n//DELETE  EXEC PGM=IDCAMS\n//SYSPRINT DD  SYSOUT=*\n//SYSIN    DD  *\n DELETE prefix.ARCHIVE.ZIP\n SET MAXCC = 0\n//ZIP     EXEC PGM=ZIP,\n// PARM='/-a -v -b temppref ''prefix.ARCHIVE.ZIP'' -@'\n//STEPLIB  DD  DSN=prefix.ZIP.LOAD,DISP=SHR\n//SYSPRINT DD  SYSOUT=*\n//SYSOUT   DD  SYSOUT=*\n//CEEDUMP  DD  SYSOUT=*\n//ZIPC     DD  DISP=SHR,DSN=prefix.ZIP.C\n//ZIPH     DD  DISP=SHR,DSN=prefix.ZIP.H\n//SYSIN    DD  *\ndd:zipc(api)\ndd:zipc(cms)\ndd:zipc(cmsmvs)\ndd:zipc(crctab)\ndd:zipc(crc32)\ndd:zipc(crypt)\ndd:zipc(deflate)\ndd:zipc(fileio)\ndd:zipc(globals)\ndd:zipc(mktime)\ndd:zipc(mvs)\ndd:zipc(trees)\ndd:zipc(ttyio)\ndd:zipc(util)\ndd:zipc(zip)\ndd:zipc(zipcloak)\ndd:zipc(zipfile)\ndd:zipc(zipnote)\ndd:zipc(zipsplit)\ndd:zipc(zipup)\ndd:ziph(api)\ndd:ziph(cmsmvs)\ndd:ziph(crypt)\ndd:ziph(cstat)\ndd:ziph(ebcdic)\ndd:ziph(mvs)\ndd:ziph(revision)\ndd:ziph(stat)\ndd:ziph(tailor)\ndd:ziph(ttyio)\ndd:ziph(zip)\ndd:ziph(ziperr)\ndd:ziph(zipup)\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/cczip.exec",
    "content": "/* CCZIP    EXEC   Compile zip for VM/CMS                           */\n/*                 Author: George Petrov, 11 Apr 1995 (VMCOMPIL EXEC) */\n/* Modified for IBM C V3R1 by Ian E. Gorman, 2 Nov 1998\n   Facilities for compiling and testing were provided by\n      OmniMark Technologies Corporation, Ottawa, Canada\n*/\nAddress Command\nSignal On Error\n\n/* Allow longnames, compile re-entrant code.\n   globals.c and cmsmvs.c require EXTENDED features */\nCCopts = 'LONGNAME RENT LANGLVL(EXTENDED) NOEXECOPS'\n\n/* ZIP options -- VM_CMS, REENTRANT */\nCCopts = CCopts 'DEFINE(VM_CMS,REENTRANT)'\n\n/* Link the load module to run in more or less than 16MB memory */\nLINKopts = 'AMODE ANY RMODE ANY RLDSAVE'\n\n/* resources needed to build */\n'GLOBAL TXTLIB  SCEELKED CMSLIB'\n'GLOBAL LOADLIB SCEERUN'\n\n/* produce the TEXT (object) files */\nlinklist=''\nmodname='ZIP'\nSay 'Building' modname 'MODULE...'\nCall Compile 'ZIP'\nCall Compile 'CRC32'\nCall Compile 'CRYPT'\nCall Compile 'DEFLATE'\nCall Compile 'FILEIO'\nCall Compile 'GLOBALS'\nCall Compile 'TREES'\nCall Compile 'TTYIO'\nCall Compile 'UTIL'\nCall Compile 'ZIPUP'\nCall Compile 'ZIPFILE'\nCall Compile 'CMSMVS'\nCall Compile 'CMS'\n\nSay 'Linking...'\n'EXEC CMOD' linklist '(MODNAME' modname LINKopts\nSay modname 'built successfully.'\n\n\n/*---------------------------------------------------------------------*/\n/* Build utility programs                                              */\n/*---------------------------------------------------------------------*/\nCCopts = CCopts 'DEFINE(UTIL)'\n\n\nlinklist=''\nmodname='ZIPNOTE'\nSay\nSay 'Building' modname 'MODULE...'\nCall Compile 'ZIPNOTE'\nCall Compile 'ZIPFILE'\nCall Compile 'FILEIO'\nCall Compile 'UTIL'\nCall Compile 'GLOBALS'\nCall Compile 'CMSMVS'\n\nSay 'Linking...'\n'EXEC CMOD' linklist '(MODNAME' modname LINKopts\nSay modname 'built successfully.'\n\n\nlinklist=''\nmodname='ZIPSPLIT'\nSay\nSay 'Building' modname 'MODULE...'\nCall Compile 'ZIPSPLIT'\nCall Compile 'ZIPFILE'\nCall Compile 'FILEIO'\nCall Compile 'UTIL'\nCall Compile 'GLOBALS'\nCall Compile 'CMSMVS'\n\nSay 'Linking...'\n'EXEC CMOD' linklist '(MODNAME' modname LINKopts\nSay modname 'built successfully.'\n\n\nlinklist=''\nmodname='ZIPCLOAK'\nSay\nSay 'Building' modname 'MODULE...'\nCall Compile 'ZIPCLOAK'\nCall Compile 'ZIPFILE'\nCall Compile 'FILEIO'\nCall Compile 'UTIL'\nCall Compile 'GLOBALS'\nCall Compile 'CRC32'\nCall Compile 'CRYPT'\nCall Compile 'TTYIO'\nCall Compile 'CMSMVS'\n\nSay 'Linking...'\n'EXEC CMOD' linklist '(MODNAME' modname LINKopts\nSay modname 'built successfully.'\nSay 'Done.'\n\nExit rc\n\n\n\nerror:\n    Say 'Error' rc 'during compilation!'\n    Say 'Error in line' sigl':'\n    Say '   'Sourceline(sigl)\n    Exit rc\n\n\n\nCompile:  Procedure Expose CCopts LINKopts linklist\n    Parse arg filename filetype filemode .\n    If filetype='' Then filetype='C'\n    linklist = linklist filename\n\n    Say 'Compiling' filename filetype filemode '...'\n    'EXEC CC' filename filetype filemode '('CCopts\n    Return rc\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/cms.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n * VM/CMS specific things.\n */\n\n#include \"zip.h\"\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  FILE *stream;\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else {\n     if ((stream = fopen(n, \"r\")) != (FILE *)NULL)\n        {\n        fclose(stream);\n        return newname(n, 0, caseflag);\n        }\n     else return ZE_MISS;\n  }\n  return ZE_OK;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/cmsmvs.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n * routines common to VM/CMS and MVS\n */\n\n#include \"zip.h\"\n\n#include <stdio.h>\n#include <time.h>\n#include <errno.h>\n\n#ifndef MVS  /* MVS has perfectly good definitions of the following */\nint stat(const char *path, struct stat *buf)\n{\n   if ((buf->fp = fopen(path, \"r\")) != NULL) {\n      fldata_t fdata;\n      if (fldata( buf->fp, buf->fname, &fdata ) == 0) {\n         buf->st_dev  = fdata.__device;\n         buf->st_mode = *(short *)(&fdata);\n      }\n      strcpy( buf->fname, path );\n      fclose(buf->fp);\n   }\n   return (buf->fp != NULL ? 0 : 1);\n}\n#endif /* MVS */\n\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#define PAD 0\n#define PATH_END '/'\n\n/* Library functions not in (most) header files */\n\n#ifdef USE_ZIPMAIN\nint main OF((void));\n#endif\n\nint utime OF((char *, ztimbuf *));\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n#ifndef MVS  /* MVS has perfectly good definitions of the following */\nint fstat(int fd, struct stat *buf)\n{\n   fldata_t fdata;\n\n   if ((fd != -1) && (fldata( (FILE *)fd, buf->fname, &fdata ) == 0)) {\n      buf->st_dev  = fdata.__device;\n      buf->st_mode = *(short *)(&fdata);\n      buf->fp      = (FILE *)fd;\n      return 0;\n   }\n   return -1;\n}\n#endif /* MVS */\n\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n  char mem[10] = \"\";    /* member name */\n  char ext[10] = \"\";     /* extension name */\n\n  dosflag = dosify;  /* default for non-DOS non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for (t = x; *t == '/'; t++)\n    ;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n#ifdef MVS\n  /* strip quotes from name, non-OE format */\n  if (*n == '\\'' && (t = strrchr(n, '\\'')) != n) {\n    if (!*(t+1)) {\n      /* yes, it is a quoted name */\n      int l = strlen(n) - 2;\n      memmove(n, n+1, l);\n      *(n+l) = '\\0';\n    }\n  }\n  /* Change member names to fn.ext */\n  if (t = strrchr(n, '(')) {\n     *t = '\\0';\n     strcpy(mem,t+1);        /* Save member name */\n     if (t = strchr(mem, ')')) *t = '\\0';         /* Set end of mbr */\n     /* Save extension */\n     if (t = strrchr(n, '.')) t++;\n     else t = n;\n     strcpy(ext,t);\n     /* Build name as \"member.ext\" */\n     strcpy(t,mem);\n     strcat(t,\".\");\n     strcat(t,ext);\n  }\n\n  /* Change all but the last '.' to '/' */\n  if (t = strrchr(n, '.')) {\n     while (--t > n)\n        if (*t == '.')\n          *t = '/';\n  }\n#else\n  /* On CMS, remove the filemode (all past 2nd '.') */\n  if (t = strchr(n, '.'))\n     if (t = strchr(t+1, '.'))\n        *t = '\\0';\n  t = n;\n#endif\n\n  strcpy(n, t);\n\n  if (isdir == 42) return n;    /* avoid warning on unused variable */\n\n  if (dosify)\n    msname(n);                  /* msname() needs string in native charset */\n\n  strtoasc(n, n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strtoebc(x, n);\n  return x;\n}\n\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  ztimbuf u;            /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u.actime and u.modtime */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  utime(f, &u);\n}\n\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n{\n  FILE *stream;\n  time_t ltime;\n\n  if (strcmp(f, \"-\") != 0) {    /* if not compressing stdin */\n     Trace((mesg, \"opening file '%s' with '%s'\\n\", f, FOPR));\n     if ((stream = fopen(f, FOPR)) == (FILE *)NULL) {\n        return 0;\n     } else {\n        if (n != NULL) {\n           /* With byteseek, this will work */\n           fseek(stream, 0L, SEEK_END);\n           *n = ftell(stream);\n           Trace((mesg, \"file size = %lu\\n\", *((ulg *)n)));\n        }\n        fclose(stream);\n     }\n  }\n  else {\n     /* Reading from stdin */\n     if (n != NULL) {\n        *n = -1L;\n     }\n  }\n\n  /* Return current time for all the times -- for now */\n  time(&ltime);\n  if (t != NULL)\n     t->atime = t->mtime = t->ctime = ltime;\n\n  /* Set attributes (always a file) */\n  if (a != NULL)\n     *a = 0;\n\n  return unix2dostime(&ltime);\n}\n\n\n\nint set_extra_field(z, z_utim)\nstruct zlist far *z;\niztimes *z_utim;\n/* create extra field and change z->att if desired */\n{\n   fldata_t fdata;\n   FILE *stream;\n   char *eb_ptr;\n#ifdef USE_EF_UT_TIME\n   extent ef_l_len = (EB_HEADSIZE+EB_UT_LEN(1));\n#else /* !USE_EF_UT_TIME */\n   extent ef_l_len = 0;\n#endif /* ?USE_EF_UT_TIME */\n   int set_cmsmvs_eb = 0;\n\n/*translate_eol = 0;*/\n  if (aflag == ASCII) {\n     z->att = ASCII;\n  } else {\n    if (bflag)\n      z->att = BINARY;\n    else\n      z->att = __EBCDIC;\n    ef_l_len += sizeof(fdata)+EB_HEADSIZE;\n    set_cmsmvs_eb = 1;\n  }\n\n  if (ef_l_len > 0) {\n    z->extra = (char *)malloc(ef_l_len);\n    if (z->extra == NULL) {\n       printf(\"\\nFLDATA : Unable to allocate memory !\\n\");\n       return ZE_MEM;\n    }\n    z->cext = z->ext = ef_l_len;\n    eb_ptr = z->cextra = z->extra;\n\n    if (set_cmsmvs_eb) {\n      if (bflag)\n/***    stream = fopen(z->zname,\"rb,type=record\");   $RGH$ ***/\n        stream = fopen(z->name,\"rb\");\n      else\n        stream = fopen(z->name,\"r\");\n      if (stream == NULL) {\n        printf(\"\\nFLDATA : Could not open file : %s !\\n\",z->name);\n        printf(\"Error %d: '%s'\\n\", errno, strerror(errno));\n        return ZE_NONE;\n      }\n\n      fldata(stream,z->name,&fdata);\n      /*put the system ID */\n#ifdef VM_CMS\n      *(eb_ptr) = EF_VMCMS & 0xFF;\n      *(eb_ptr+1) = EF_VMCMS >> 8;\n#else\n      *(eb_ptr) = EF_MVS & 0xFF;\n      *(eb_ptr+1) = EF_MVS >> 8;\n#endif\n      *(eb_ptr+2) = sizeof(fdata) & 0xFF;\n      *(eb_ptr+3) = sizeof(fdata) >> 8;\n\n      memcpy(eb_ptr+EB_HEADSIZE,&fdata,sizeof(fdata));\n      fclose(stream);\n#ifdef USE_EF_UT_TIME\n      eb_ptr += (sizeof(fdata)+EB_HEADSIZE);\n#endif /* USE_EF_UT_TIME */\n    }\n#ifdef USE_EF_UT_TIME\n    eb_ptr[0]  = 0x55;                  /* ascii[(unsigned)('U')] */\n    eb_ptr[1]  = 0x54;                  /* ascii[(unsigned)('T')] */\n    eb_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n    eb_ptr[3]  = 0;\n    eb_ptr[4]  = EB_UT_FL_MTIME;\n    eb_ptr[5]  = (char)(z_utim->mtime);\n    eb_ptr[6]  = (char)(z_utim->mtime >> 8);\n    eb_ptr[7]  = (char)(z_utim->mtime >> 16);\n    eb_ptr[8]  = (char)(z_utim->mtime >> 24);\n#endif /* USE_EF_UT_TIME */\n  }\n\n  return ZE_OK;\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return 0;\n}\n\n#ifdef USE_ZIPMAIN\n/* This function is called as main() to parse arguments                */\n/* into argc and argv.  This is required for stand-alone               */\n/* execution.  This calls the \"real\" main() when done.                 */\n\nint main(void)\n   {\n    int  argc=0;\n    char *argv[50];\n\n    int  iArgLen;\n    char argstr[256];\n    char **pEPLIST, *pCmdStart, *pArgStart, *pArgEnd;\n\n   /* Get address of extended parameter list from S/370 Register 0 */\n   pEPLIST = (char **)__xregs(0);\n\n   /* Null-terminate the argument string */\n   pCmdStart = *(pEPLIST+0);\n   pArgStart = *(pEPLIST+1);\n   pArgEnd   = *(pEPLIST+2);\n   iArgLen   = pArgEnd - pCmdStart + 1;\n\n   /* Make a copy of the command string */\n   memcpy(argstr, pCmdStart, iArgLen);\n   argstr[iArgLen] = '\\0';  /* Null-terminate */\n\n   /* Store first token (cmd) */\n   argv[argc++] = strtok(argstr, \" \");\n\n   /* Store the rest (args) */\n   while (argv[argc-1])\n      argv[argc++] = strtok(NULL, \" \");\n   argc--;  /* Back off last NULL entry */\n\n   /* Call \"real\" main() function */\n   return zipmain(argc, argv);\n\n}\n#endif /* USE_ZIPMAIN */\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    char liblvlmsg [50+1];\n    char *compiler = \"?\";\n    char *platform = \"?\";\n    char complevel[64];\n\n    /* Map the runtime library level information */\n    union {\n       unsigned int iVRM;\n       struct {\n          unsigned int pd:4;    /* Product designation */\n          unsigned int vv:4;    /* Version             */\n          unsigned int rr:8;    /* Release             */\n          unsigned int mm:16;   /* Modification level  */\n       } xVRM;\n    } VRM;\n\n\n    /* Break down the runtime library level */\n    VRM.iVRM = __librel();\n    sprintf(liblvlmsg, \"Using runtime library level %s V%dR%dM%d\",\n            (VRM.xVRM.pd==1 ? \"LE\" : \"CE\"),\n            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);\n    /* Note:  LE = Language Environment, CE = Common Env. (C/370). */\n    /* This refers ONLY to the current runtimes, not the compiler. */\n\n\n#ifdef VM_CMS\n    platform = \"VM/CMS\";\n    #ifdef __IBMC__\n       compiler = \"IBM C\";\n    #else\n       compiler  = \"C/370\";\n    #endif\n#endif\n\n#ifdef MVS\n    platform = \"MVS\";\n    #ifdef __IBMC__\n       compiler = \"IBM C/C++\";\n    #else\n       compiler = \"C/370\";\n    #endif\n#endif\n\n#ifdef __COMPILER_VER__\n    VRM.iVRM = __COMPILER_VER__;\n    sprintf(complevel,\" V%dR%dM%d\",\n            VRM.xVRM.vv, VRM.xVRM.rr, VRM.xVRM.mm);\n#else\n#ifdef __IBMC__\n    sprintf(complevel,\" V%dR%d\", __IBMC__ / 100, (__IBMC__ % 100)/10);\n#else\n    complevel[0] = '\\0';\n#endif\n#endif\n\n\n    printf(\"Compiled with %s%s for %s%s%s.\\n\\n\",\n\n    /* Add compiler name and level */\n    compiler, complevel,\n\n    /* Add platform */\n    platform,\n\n    /* Add timestamp */\n#ifdef __DATE__\n      \" on \" __DATE__\n#ifdef __TIME__\n      \" at \" __TIME__\n#endif\n#endif\n      \".\\n\",\n      liblvlmsg\n    );\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/cmsmvs.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/* Include file for VM/CMS and MVS */\n\n/* This is normally named osdep.h on most systems.  Since CMS       */\n/* generally doesn't support directories, it's been given a unique  */\n/* name to avoid confusion.                                         */\n\n\n#ifndef __cmsmvs_h   /* prevent multiple inclusions */\n#define __cmsmvs_h\n\n#ifdef MVS\n#  define _POSIX_SOURCE    /* tell MVS we want full definitions */\n#  include <features.h>\n#endif /* MVS */\n\n#include <time.h>               /* the usual non-BSD time functions */\n/* cstat.h is not required for MVS and actually gets in the way.  Is it\n * needed for CMS?\n */\n#ifdef MVS\n#  include <sys/stat.h>\n#  include <sys/modes.h>\n#else /* !MVS */\n#  include \"cstat.h\"\n#endif\n\n\n/* Newer compiler version defines something for us */\n#if defined(__VM__) && !defined(VM_CMS)\n#  define VM_CMS\n#endif\n\n#define CMS_MVS\n#define EBCDIC\n\n#ifndef MVS  /* MVS has perfectly good definitions for the following */\n#  define NO_UNISTD_H\n#  define NO_FCNTL_H\n#endif /*MVS */\n\n/* If we're generating a stand-alone CMS module, patch in        */\n/* a new main() function before the real main() for arg parsing. */\n#ifdef CMS_STAND_ALONE\n#  define USE_ZIPMAIN\n#endif\n\n#ifndef NULL\n#  define NULL 0\n#endif\n\n#define PASSWD_FROM_STDIN\n                  /* Kludge until we know how to open a non-echo tty channel */\n\n/* definition for ZIP */\n#define getch() getc(stdin)\n#define MAXPATHLEN 128\n#define NO_RMDIR\n#define NO_MKTEMP\n#define USE_CASE_MAP\n#define isatty(t) 1\n\n#ifndef MVS  /* MVS has perfectly good definitions for the following */\n#  define fileno(x) (char *)(x)\n#  define fdopen fopen\n#  define unlink remove\n#  define link rename\n#  define utime(f,t)\n#endif /*MVS */\n#ifdef ZCRYPT_INTERNAL\n#  define ZCR_SEED2     (unsigned)3141592654L   /* use PI as seed pattern */\n#endif\n\n#ifdef MVS\n#  if defined(__CRC32_C)\n#    pragma csect(STATIC,\"crc32_s\")\n#  elif defined(__DEFLATE_C)\n#    pragma csect(STATIC,\"deflat_s\")\n#  elif defined(__ZIPFILE_C)\n#    pragma csect(STATIC,\"zipfil_s\")\n#  elif defined(__ZIPUP_C)\n#    pragma csect(STATIC,\"zipup_s\")\n#  endif\n#endif /* MVS */\n\n/* end defines for ZIP */\n\n\n\n#if 0  /*$RGH$*/\n/* RECFM=F, LRECL=1 works for sure */\n#define FOPR \"rb,recfm=fb\"\n#define FOPM \"r+\"\n#define FOPW \"wb,recfm=fb,lrecl=1\"\n#define FOPWT \"w\"\n#endif\n\n/* Try allowing ZIP files to be RECFM=V with \"byteseek\" for CMS, recfm=U for MVS */\n#define FOPR \"rb,byteseek\"\n#define FOPM \"r+,byteseek\"\n#ifdef MVS\n  #define FOPW \"wb,recfm=u,byteseek\"\n#else /* !MVS */\n  #define FOPW \"wb,recfm=v,lrecl=32760,byteseek\"\n#endif /* MVS */\n\n#if 0\n#define FOPW_TMP \"w,byteseek\"\n#else\n#define FOPW_TMP \"w,type=memory(hiperspace)\"\n#endif\n\n#define CBSZ 0x40000\n#define ZBSZ 0x40000\n\n#endif /* !__cmsmvs_h */\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/cstat.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*  cstat.h\n\n    Definitions used for file status functions\n\n*/\n\n#ifndef __STAT_H\n#define __STAT_H\n\n#include <stdio.h>\n\n#define S_IFMT  0xF000  /* file type mask */\n#define S_IFDIR 0x4000  /* directory */\n#define S_IFIFO 0x1000  /* FIFO special */\n#define S_IFCHR 0x2000  /* character special */\n#define S_IFBLK 0x3000  /* block special */\n#define S_IFREG 0x8000  /* or just 0x0000, regular */\n#define S_IREAD 0x0100  /* owner may read */\n#define S_IWRITE 0x0080 /* owner may write */\n#define S_IEXEC 0x0040  /* owner may execute <directory search> */\n\nstruct  stat\n{\n    short st_dev;      /* Drive number of disk containing the  */\n                       /* file or file handle if the file is   */\n                       /* on device                            */\n    short st_ino;      /* Not meaningfull for VM/CMS           */\n    short st_mode;     /* Bit mask giving information about    */\n                       /* the file's mode                      */\n    short st_nlink;    /* Set to the integer constant 1        */\n    int   st_uid;      /* Not meaningfull for VM/CMS           */\n    int   st_gid;      /* Not meaningfull for VM/CMS           */\n    short st_rdev;     /* Same as st_dev                       */\n    long  st_size;     /* Size of the file in bytes            */\n    long  st_atime;    /* Most recent access                   */\n    long  st_mtime;    /* Same as st_atime                     */\n    long  st_ctime;    /* Same as st_atime                     */\n    FILE  *fp;\n    char  fname[FILENAME_MAX];\n};\n\nint stat(const char *path, struct stat *sb);\nint fstat(int fd, struct stat *sb);\n\n#endif  /* __STAT_H */\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/mc.exec",
    "content": "/* MAKECPIP EXEC      Make program to build a C/370 module           */\n/*                    Author: George Petrov, 29 Sep 1994             */\n\narg fn . '(' cparms                   /* Filter name                 */\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| frlab GLOBALS:'||,\n    '| drop',\n    '| strip',\n    '| var globals'\ncparms = cparms globals\nsay ''\nsay 'Compile options : 'cparms\nsay ''\nif pos('REB',cparms) > 0 then do\nparse var cparms cp1 'REB' . ' ' cp2  /* REBuild options specified ? */\ncparms = cp1||cp2\npipe1=,\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| nfind *'||,                    /* the makefile and compile    */\n    '| frlab TEXT:'||,                /* only the those who are      */\n    '| r: tolab MODULE:'||,           /* changed or never compiled   */\n    '| drop',\n    '| o: fanout',\n    '| chop before str /(/',\n    '| statew',\n    '| c: fanout',                    /* compiled                    */\n    '| specs /Compiling / 1 w1-3 n / .../ n',\n    '| cons'\nend\nelse do\npipe1=,\n'pipe (end ?) < 'fn' makefile',       /* get all source files from   */\n    '| nfind *'||,                    /* the makefile and compile    */\n    '| frlab TEXT:'||,                /* only the those who are      */\n    '| r: tolab MODULE:'||,           /* changed or never compiled   */\n    '| drop',\n    '| o: fanout',\n    '| specs w1 1 /C/ nw w3 nw write w1 1 /TEXT A/ nw',\n    '| chop before str /(/',\n    '| statew',\n    '| change (57 66) / /0/',\n    '| sort 1.8 d',                  /* sort the date and time      */\n    '| uniq 1-17 singles',           /* if the first is a source    */\n    '| sort 1.8 d 64.2 d 57.2 d 60.2 d 66.8 d',    /* sort the date */\n    '| uniq 1-8 first',          /*    if the first is a source    */\n    '| locate 9.8 /C      /',         /* program then it has to be   */\n    '| c: fanout',                    /* compiled                    */\n    '| specs /Compiling / 1 w1-3 n / .../ n',\n    '| cons'\nend\npipe2= '?',\n    'r:',\n    '| drop',\n    '| specs w1 1',                 /* save the module name in var  */\n    '| var module',\n    '?',\n    'o:',\n    '| specs w1 1',\n    '| join * / /',\n    '| var texts',                  /* save all the text file names */\n    '?',                            /* for later include            */\n    'c:',\n    '| specs /CC / 1 w1-3 n /(NOTERM 'cparms'/ nw',   /* compile! */\n    '| err: cms | cons',\n    '?',\n    'err:',\n    '| strip both',\n    '| nfind 0'||,\n    '| var err',\n    '| specs /----> Errors found! RC=/ 1 1-* n',\n    '| cons'\n/*  '| g: gate'*/\npipe1 pipe2\nsay ''\nif symbol('err') = 'VAR' & err ^= 0 then do\n      say 'Errors found in source files - link aborted! RC = 'err\n      exit err\nend\nsay 'Generating module 'module\n'pipe cms cmod' fn texts' DMSCSL | > 'fn' LINK A'\n'set cmstype ht'\n'state 'fn' LINK A'\nrcc = rc\n'set cmstype rt'\nif rcc = 0 then do\n   say ''\n   say 'ERRORS discovered during linking!'\n   say 'See: 'fn' LINK A for more info'\nend\nexit rc\nerror:\nsay 'Error in REXX detected!'\nSay 'Syntax error on line' Sigl':' Sourceline(Sigl)\nSay 'Error was:' Errortext(RC)\nreturn rc\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/mvs.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n * MVS specific things\n */\n#include \"zip.h\"\n#include \"mvs.h\"\n#include <errno.h>\n\nstatic int gen_node( DIR *dirp, RECORD *recptr )\n{\n   char *ptr, *name, ttr[TTRLEN];\n   int skip, count = 2;\n   unsigned int info_byte, alias, ttrn;\n   struct dirent *new;\n\n   ptr = recptr->rest;\n   while (count < recptr->count) {\n      if (!memcmp( ptr, endmark, NAMELEN ))\n         return 1;\n      name = ptr;                    /* member name */\n      ptr += NAMELEN;\n      memcpy( ttr, ptr, TTRLEN );    /* ttr name    */\n      ptr += TTRLEN;\n      info_byte = (unsigned int) (*ptr);   /* info byte */\n      if ( !(info_byte & ALIAS_MASK) ) {   /* no alias  */\n         new = malloc( sizeof(struct dirent) );\n         if (dirp->D_list == NULL)\n            dirp->D_list = dirp->D_curpos = new;\n         else\n            dirp->D_curpos = (dirp->D_curpos->d_next = new);\n         new->d_next = NULL;\n         memcpy( new->d_name, name, NAMELEN );\n         new->d_name[NAMELEN] = '\\0';\n         if ((name = strchr( new->d_name, ' ' )) != NULL)\n            *name = '\\0';      /* skip trailing blanks */\n      }\n      skip = (info_byte & SKIP_MASK) * 2 + 1;\n      ptr += skip;\n      count += (TTRLEN + NAMELEN + skip);\n   }\n   return 0;\n}\n\nDIR *opendir(const char *dirname)\n{\n   int bytes, list_end = 0;\n   DIR *dirp;\n   FILE *fp;\n   RECORD rec;\n\n   fp = fopen( dirname, \"rb\" );\n   if (fp != NULL) {\n      dirp = malloc( sizeof(DIR) );\n      if (dirp != NULL) {\n         dirp->D_list = dirp->D_curpos = NULL;\n         strcpy( dirp->D_path, dirname );\n         do {\n            bytes = fread( &rec, 1, sizeof(rec), fp );\n            if (bytes == sizeof(rec))\n               list_end = gen_node( dirp, &rec );\n         } while (!feof(fp) && !list_end);\n         fclose( fp );\n         dirp->D_curpos = dirp->D_list;\n         return dirp;\n      }\n      fclose( fp );\n   }\n   return NULL;\n}\n\nstruct dirent *readdir(DIR *dirp)\n{\n   struct dirent *cur;\n\n   cur = dirp->D_curpos;\n   dirp->D_curpos = dirp->D_curpos->d_next;\n   return cur;\n}\n\nvoid rewinddir(DIR *dirp)\n{\n   dirp->D_curpos = dirp->D_list;\n}\n\nint closedir(DIR *dirp)\n{\n   struct dirent *node;\n\n   while (dirp->D_list != NULL) {\n      node = dirp->D_list;\n      dirp->D_list = dirp->D_list->d_next;\n      free( node );\n   }\n   free( dirp );\n   return 0;\n}\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n  int exists;           /* 1 if file exists */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (!(exists = (LSSTAT(n, &s) == 0)))\n  {\n#ifdef MVS\n    /* special case for MVS.  stat does not work on non-HFS files so if\n     * stat fails with ENOENT, try to open the file for reading anyway.\n     * If the user has no OMVS segment, stat gets an initialization error,\n     * even on external files.\n     */\n    if (errno == ENOENT || errno == EMVSINITIAL) {\n      FILE *f = fopen(n, \"r\");\n      if (f) {\n        /* stat got ENOENT but fopen worked, external file */\n        fclose(f);\n        exists = 1;\n        memset(&s, '\\0', sizeof(s));   /* stat data is unreliable for externals */\n        s.st_mode = S_IFREG;           /* fudge it */\n      }\n    }\n#endif /* MVS */\n  }\n  if (! exists) {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if (!S_ISDIR(s.st_mode))\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/mvs.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/* <dirent.h> definitions */\n\n#define NAMELEN     8\n\nstruct dirent {\n   struct dirent *d_next;\n   char   d_name[NAMELEN+1];\n};\n\ntypedef struct _DIR {\n   struct  dirent *D_list;\n   struct  dirent *D_curpos;\n   char            D_path[FILENAME_MAX];\n} DIR;\n\nDIR *          opendir(const char *dirname);\nstruct dirent *readdir(DIR *dirp);\nvoid           rewinddir(DIR *dirp);\nint            closedir(DIR *dirp);\nchar *         readd(DIR *dirp);\n\n#define ALIAS_MASK  (unsigned int) 0x80\n#define SKIP_MASK   (unsigned int) 0x1F\n#define TTRLEN      3\n#define RECLEN      254\n\ntypedef _Packed struct {\n   unsigned short int count;\n   char rest[RECLEN];\n} RECORD;\n\nchar    *endmark = \"\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\";\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/mvs.mki",
    "content": "# Makefile for the MVS (OS/390 Base) version of ZIP 2.3\n# Produced for C/C++ V3R2 in OS/390 1.2.0 by Ian E. Gorman, 2 Nov 1998\n# Facilities for compiling and testing were made available by\n#     OmniMark Technologies Corporation, Ottawa, Canada\n\n# NOTES\n#\n# The only tabs in this file are in the first character of each recipe\n# line, where they are required by make.\n#\n# Run this makefile in OpenMVS (OS/390 POSIX) using source files in the\n# HFS file system.  You can write the load module to either HFS file\n# system or to a PDS in the native MVS file system.  The PDS must have\n# sufficient free space to hold the load module.\n#\n# To compile to a member of a PDS:\n#   make\n# or\n#   make zip.mvs\n#\n# To compile a test version into the HFS file system:\n#   make hfs\n\n# ZIP options -- MVS, REENTRANT\nZIPOPTS=-DMVS -DREENTRANT\n\n# directories\n\n# generic source code\nSRC=..\nSRC_P=$(SRC)/\n\n# source code for MVS\nCMSMVS=../cmsmvs\nCMSMVS_P=$(CMSMVS)/\n\n# include files\nINCLS=-I$(SRC) -I$(CMSMVS)\n\n# object files and load modules\nBLD_P=../mvs/\n\n# Other options\n\n# Suffixes (E and O must be different)\nE=\nO=.o\n\n# Need EXTENDED features for global.c and vmvms.c, so not using c89\nCC=cc\nCFLAGS=-D_OPEN_SYS $(ZIPOPTS) $(INCLS)\n\nLD=cc\nLDFLAGS=\n\n# Files\n\n# object (TEXT) files\nOBJECTS= $(BLD_P)zip$(O) $(BLD_P)trees$(O) \\\n   $(BLD_P)crypt$(O)  $(BLD_P)ttyio$(O)   $(BLD_P)deflate$(O) \\\n   $(BLD_P)fileio$(O) $(BLD_P)globals$(O) $(BLD_P)util$(O) \\\n   $(BLD_P)crc32$(O)  $(BLD_P)zipfile$(O) \\\n   $(BLD_P)zipup$(O)  $(BLD_P)cmsmvs$(O)  $(BLD_P)mvs$(O)\n\n# Header files\nHFILES= $(SRC_P)api.h $(SRC_P)crc32.h $(SRC_P)crypt.h $(SRC_P)ebcdic.h \\\n    $(SRC_P)revision.h $(SRC_P)tailor.h $(SRC_P)ttyio.h \\\n    $(SRC_P)zip.h $(SRC_P)ziperr.h $(CMSMVS_P)cmsmvs.h \\\n    $(CMSMVS_P)cstat.h $(CMSMVS_P)mvs.h $(CMSMVS_P)zipup.h\n\n# Rules\n\nall:  $(BLD_P)zip.mvs$(E)\nhfs:  $(BLD_P)zip$(E)\n\n# link\n\n$(BLD_P)zip.mvs$(E):     $(OBJECTS)\n\t$(LD) -o \"//INFOZIP.LOAD(ZIP)\" $(LDFLAGS) $^\n\techo \"tso call \\\"infozip(zip)\\\" \\\"'\\\"\\\"\"\"$$\"\"@\"\"\\\"\\\"'\\\"\" > $%\n\tchmod a+x $%\n\n$(BLD_P)zip$(E):     $(OBJECTS)\n\t$(LD) -o $% $(LDFLAGS) $^\n\n# compile\n\n$(BLD_P)trees$(O):   $(SRC_P)trees.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)trees.c\n\n$(BLD_P)crypt$(O):   $(SRC_P)crypt.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)crypt.c\n\n$(BLD_P)ttyio$(O):   $(SRC_P)ttyio.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)ttyio.c\n\n$(BLD_P)deflate$(O): $(SRC_P)deflate.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)deflate.c\n\n$(BLD_P)fileio$(O):  $(SRC_P)fileio.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)fileio.c\n\n$(BLD_P)globals$(O): $(SRC_P)globals.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)globals.c\n\n$(BLD_P)zip$(O):     $(SRC_P)zip.c          $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)zip.c\n\n$(BLD_P)util$(O):    $(SRC_P)util.c         $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)util.c\n\n$(BLD_P)crc32$(O):   $(SRC_P)crc32.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)crc32.c\n\n$(BLD_P)zipfile$(O): $(SRC_P)zipfile.c      $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)zipfile.c\n\n$(BLD_P)zipup$(O):   $(SRC_P)zipup.c        $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(SRC_P)zipup.c\n\n$(BLD_P)cmsmvs$(O):  $(CMSMVS_P)cmsmvs.c    $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)cmsmvs.c\n\n$(BLD_P)mvs$(O):     $(CMSMVS_P)mvs.c       $(HFILES)\n\t$(CC) -c -o $% $(CFLAGS) $(CMSMVS_P)mvs.c\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/pipzip.rexx",
    "content": "/* PIPZIP REXX     Rexx filter to use ZIP                             */\n/*                 Author : George Petrov, 8 May 1995                 */\n\nparse arg opts\n'callpipe *:',\n   '| specs w1 1 /./ n w2 n',\n   '| join * / /',\n   '| specs /zip 'opts'/ 1 1-* nw',\n   '| cms',\n   '| *:'\n\nexit rc\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zip.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zip.makefile",
    "content": "* This is a comment\n* this makefile compiles filter ZIPME\n\nGLOBALS:\n   long def(VM_CMS)\nTEXT:\n   trees c\n   crypt c\n   ttyio c\n   deflate c\n   fileio c\n   globals c\n   zip c\n   util c\n   crc32.c\n   zipfile c\n   zipup c\n   cmsmvs c\n   cms c\nMODULE:\n   zip module\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipcloak.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipmvsc.job",
    "content": "//CCZIP JOB (BI09255),\n//        MSGLEVEL=(1,1),MSGCLASS=C,CLASS=D,NOTIFY=C888090\n//PROCLIB JCLLIB ORDER=(SYS1.C370.PROCLIB.M24)\n//ZIP EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(ZIP)',\n//    OUTFILE='C888090.ZIP.C.OBJ(ZIP),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//CRYPT EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(CRYPT)',\n//    OUTFILE='C888090.ZIP.C.OBJ(CRYPT),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//TTYIO EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(TTYIO)',\n//    OUTFILE='C888090.ZIP.C.OBJ(TTYIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//TREES EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(TREES)',\n//    OUTFILE='C888090.ZIP.C.OBJ(TREES),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//DEFLATE EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(DEFLATE)',\n//    OUTFILE='C888090.ZIP.C.OBJ(DEFLATE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//FILEIO EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(FILEIO)',\n//    OUTFILE='C888090.ZIP.C.OBJ(FILEIO),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//GLOBALS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(GLOBALS)',\n//    OUTFILE='C888090.ZIP.C.OBJ(GLOBALS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//UTIL EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(UTIL)',\n//    OUTFILE='C888090.ZIP.C.OBJ(UTIL),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//CRC32 EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(CRC32)',\n//    OUTFILE='C888090.ZIP.C.OBJ(CRC32),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//ZIPFILE EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(ZIPFILE)',\n//    OUTFILE='C888090.ZIP.C.OBJ(ZIPFILE),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//ZIPUP EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(ZIPUP)',\n//    OUTFILE='C888090.ZIP.C.OBJ(ZIPUP),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//CMSMVS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(CMSMVS)',\n//    OUTFILE='C888090.ZIP.C.OBJ(CMSMVS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//MVS EXEC EDCC,COND=(12,LE),CREGSIZ='4M',\n//    INFILE='C888090.ZIP.C(MVS)',\n//    OUTFILE='C888090.ZIP.C.OBJ(MVS),DISP=SHR',\n//    CPARM='LONG,NOTERM,LIST,XREF,SOURCE,OPT(2),DEF(MVS)'\n//COMPILE.USERLIB DD DSN=C888090.ZIP.H,DISP=SHR\n//PLINK   EXEC  PROC=EDCPL,COND=(12,LE),\n//    OUTFILE='C888090.ZIP.LOAD(ZIP),DISP=SHR',\n//    PPARM='NONCAL,MAP',\n//    LPARM='LIST,MAP,XREF'\n//SYSPRINT DD  SYSOUT=*\n//PLKED.SYSIN   DD  DSN=C888090.ZIP.C.OBJ(ZIP),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(BITS),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(CRYPT),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(TREES),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(DEFLATE),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(FILEIO),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(GLOBALS),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(UTIL),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(CRC32),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(ZIPFILE),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(ZIPUP),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(CMSMVS),DISP=SHR\n//              DD  DSN=C888090.ZIP.C.OBJ(MVS),DISP=SHR\n//PLKED.SYSLIB  DD  DSN=SYS1.C370.SEDCBASE,DISP=SHR\n//              DD  DSN=SYS1.PL1.SIBMBASE,DISP=SHR\n//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(2,2)),DISP=NEW\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipname.conven",
    "content": "\n         Zip file/directories name convention under MVS\n       ---------------------------------------------------\n                           Draft 1.1\n\n\n1. Translating native file names to Zip filenames.\n\n1.1 Zipping a PDS\n\nOn MVS there are directories called PDS (Partition Data Set) which have\nthe following format :   name1.name2.name3(mname)\nfor example:             myuserid.unzip.c(unzip)\n\nSo as you see the path delimiter is '.'. Each dir name can be max 8\nchars long beginning with a number.\n\nBetween '(' and ')' there is the so called member name - it is also 8\nchars long. This is the actual file name.\n\n\n1.1.1 Converting MVS PDS name to zip path/filename  (status: not implemented)\n\nThe PDS name is converted to zippath as follows:\nin the zip :     name1/name2/mname.name3\nbecomes on MVS:  name1.name2.name3(mname)\n\n\n1.2 Unzipping as PDS                                (status: implemented)\n\nWhen you unzip the file name myuserid/unzip/unzip.c the same process\nis done backwards, so you get : myuserid.unzip.c(unzip)\n\nNotice that the file extension is used as last dirname!\n\n\n1.2 Unzipping to a different PDS                    (status: implemented)\n\nYou can also use -d option while unzipping for example:\nunzip mytest myuserid/unzip/unzip.c -dnewdest.test\n\nthen the new name will become:\nnewdest.test.myuserid.unzip.c(unzip)\n\n              Second example:\n\nunzip mytest myuserid/unzip/*.c -dnewdest.test\n\nthen you get a PDS:\nnewdest.test.myuserid.unzip.c(...)\n\nwith all *.c files in it.\n\n\n1.3 Zipping a Sequential Dataset               (status: not implemented)\n\n  Sequential dataset is a dataset with NO members.\nSuch a dataset is translated from native MVS to zip format by replacing\nthe '.' (points) with '/' (backslash).\n\nExample:\non MVS:                  name1.name2.name3\nbecomes in the zip :     name1/name2/name3\n\nNOTE : The new filename in the zip has NO extension this way it can be\n       recognised as a Sequential dataset and not a PDS.\n       But this also means that all files in the zip archive that have\n       no extension will be unzipped as Sequential datasets!\n\n\n1.4 Using a DDNAMES for input.                  (status: not implemented)\n\nTo use DDNAMES as input file names put a 'dd:' before the ddname:\nexample: zip myzip dd:name1 dd:name2 dd:sales\n\nIn the Zip archive the ddnames are saved as name.DDNAME so if you try\nthe example above you will get in your zip file (when listing it) :\n\n..size .. date time .. crc .. NAME1.DDNAME\n..size .. date time .. crc .. NAME2.DDNAME\n..size .. date time .. crc .. SALES.DDNAME\n\n\n1.4 Using a DDNAMES as zip name                    (status: implemented)\n\nIt is allowed to use a DDNAME as zipfile, just put dd: before it\nexample: unzip dd:myzip *.c\n   this will unzip all .c files from ddname myzip\n\nexample2:   ZIP DD:MYZIP DD:MANE1 MYSOURCE.C MYDOC.TEXT(ZIPPING)\n   this will zip ddname name1 file mysource.c and PDS mydoc.text(zipping)\n   into as a zip file in the ddname myzip\n\n\n2. Converting longer path names (unix like)     (status: not implemented)\n   to native MVS names.\n\nWhen in the zip archive there are dirnames longer that 8 chars they are\nchopped at the 8 position. For example\n        MyLongZippath/WithLongFileName.text\nis translated to:\n        MYLONGZI.TEXT(WITHLONG)\n\nNotice that all chars are converted to uppercase.\n\n\n2.1 Using special characters                     (status: implemented)\n\nAlso all '_' (underscore), '+' (plus), '-' (minus), '(' and ')'\nfrom the file name/path in the zip archive are skipped because they\nare not valid in the MVS filenames.\n\n\n2.2 Numeric file names                        (status: not implemented)\n\nOn MVS no name can begin with a number, so when a dir/file name begins with\none, a leading letter 'N' is inserted.  For example:\n          Contents.512\nbecomes:\n          CONTENTS.N512\n\n\n\n\n        Zip file/directories name convention under VM/CMS\n       ---------------------------------------------------\n\n1. Translating native file names to Zip filenames.\n\nOn VM/CMS (not ESA ) there are NO directories so you got only disks\nand files.\n\nThe file names are delimited with spaces. But for use with unzip/zip\nyou have to use '.' points as delimiters.\n\nFor example on your A disk you have file called PROFILE EXEC\nif you want to zip it type : zip myzip profile.exec\n\nIf the same file is on your F disk you have to type:\nzip myzip profile.exec.f\n\nSo as you can see the general format is fname.ftype.fmode\n\nIn the zipfile the disk from which the file comes is not saved!\nSo only the fname.ftype is saved.\n\nIf you unzip and you want to give a different destination disk just use\nthe -d option like:\n\n                     unzip mytest *.c -df\n\nThis will unzip all *.c files to your F disk.\n\n\n2. Converting longer path names (unix like) to native VM/CMS names.\n\nWhen in the zip archive there are dirnames longer that 8 chars they are\nchopped at the 8 position. Also the path is removed. For example\n        Zippath/WithLongFileName.text\nis translated to:\n        WITHLONG.TEXT\n\nNotice that all chars are converted to uppercase.\n\nAlso all '+' (plus), '-' (minus), '(' and ')'\nfrom the file name/path in the zip archive are skipped because they\nare not valid in the VM/CMS filenames.\n\nIf there is no extension for the file name in the zip archive, unzip\nwill add .NONAME for example:\n        mypath/dir1/testfile\nbecomes:\n        TESTFILE.NONAME\n\n3. Future?\n\nThere is also discussion for a new option on ZIP that you can give\na virtual directory to be added before each file name that is zipped.\n\nFor example you want to zip a few .c file and put them in the zip\nstructure under the directory 'mydir/test', but you can't create dirs on\nVM/CMS so you have to the something like:\n\nZIP myzip file1.c file2.c -dmydir/test\n\nand you get in the zip archive files:\n\n       mydir/test/file1.c\n       mydir/test/file2.c\n\n-------------------------------------------------------------------------\n\n\nNOTE: Not all of those functions are implemented in the first beta\n      release of VM/MVS UNZIP/ZIP.\n\nEvery ideas/corrections/bugs will be appreciated.\nMail to maillist:  Info-ZIP@LISTS.WKU.EDU\n\nGeorge Petrov\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipnote.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipsplit.exec",
    "content": "/***********************************************************************/\n/*                                                                     */\n/* Front-end EXEC to set up linkage to the C runtime libraries         */\n/* before executing a MODULE generated from C code.                    */\n/*                                                                     */\n/* Copy this file as an EXEC with a filename matching the C MODULE.    */\n/*                                                                     */\n/* Greg Hartwig (ghartwig@vnet.ibm.com)   7/31/97, 4/24/98.            */\n/*                                                                     */\n/***********************************************************************/\nAddress Command\nParse Arg argstring\nParse Source . . myname .\n\n/* Set output and input character translation so brackets show up */\n'SET OUTPUT AD' 'BA'x\n'SET OUTPUT BD' 'BB'x\n'SET INPUT  BA   AD'\n'SET INPUT  BB   BD'\n\nCall CLIB\nIf rc<>0 Then Do\n   Say 'The required C runtime libraries don''t appear to be available.'\n   Say myname 'can not run.'\n   Exit 12\nEnd\n\n/* Run the command */\nmyname argstring\nExit rc\n\n\n\n\n/* Contents of the CLIB EXEC, modified for RC checking.        */\n/* Removed TXTLIB setting.  Only LOADLIB needed for execution. */\nCLIB:\n/***************************************************/\n/*      SET UP LIBRARIES FOR LE for MVS & VM       */\n/***************************************************/\nAddress COMMAND\n\nloadlib  ='EDCLINK'               /* C/370 runtime                 */\nloadlib  ='SCEERUN'               /* LE runtime                    */\n\n\ntheirs=queued()                           /* old stack contentsM068*/\n 'QUERY LOADLIB ( LIFO'                   /* old setting       M068*/\n LoadlibList=''                           /* init list         M068*/\nrc=0\n Do while queued()^=theirs                /* all lines from cmdM068*/\n   Parse upper pull 'LOADLIB' '=' Ltemp   /* get one line      M068*/\n   LoadlibList= Ltemp Loadliblist         /* was stacked LIFO  M068*/\n End                                                         /*M068*/\n If loadlibList='NONE' ,\n Then Do\n  'GLOBAL LOADLIB' Loadlib          /* enforce what we need         */\n End\n Else Do\n  Do xx=1 to Words(loadlib)\n  If Find(loadliblist,word(loadlib,xx)) = 0 ,\n   then loadliblist = loadliblist word(loadlib,xx)\n  End\n  'GLOBAL LOADLIB' loadliblist       /* enforce what we need         */\n End\nReturn\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow  \"r,byteseek\"\n#define fhowb \"rb,byteseek\"\n\n#define fbad NULL\ntypedef FILE *ftype;\n#define zopen(n,p)   (ftype)fopen((n),(p))\n#define zread(f,b,n) fread((b),1,(n),(FILE*)(f))\n#define zclose(f)    fclose((FILE*)(f))\n#define zerr(f)      ferror((FILE*)(f))\n#define zstdin       stdin\n"
  },
  {
    "path": "deps/infozip/zip30/cmsmvs/zipvmc.exec",
    "content": "/* VMCOMPIL EXEC   Unzip compile for VM/CMS                           */\n/*                 Author : George Petrov, 11 Apr 1995                */\n\nsignal on error\n\nparms = '(long def(VM_CMS)'\n\n/* Add local parms */\nparms = parms 'TARGET(COMPAT) SOURCE'\n\n\nsay 'Compiling TREES C...'\n'cc trees c 'parms\nsay 'Compiling CRYPT C...'\n'cc crypt c 'parms\nsay 'Compiling TTYIO C...'\n'cc ttyio c 'parms\nsay 'Compiling DEFLATE C...'\n'cc deflate c 'parms\nsay 'Compiling FILEIO C...'\n'cc fileio c 'parms\nsay 'Compiling GLOBALS C...'\n'cc globals c 'parms\nsay 'Compiling ZIP C...'\n'cc zip c 'parms\nsay 'Compiling UTIL C...'\n'cc util c 'parms\nsay 'Compiling CRC32 C...'\n'cc crc32 c 'parms\nsay 'Compiling ZIPFILE C...'\n'cc zipfile c 'parms\nsay 'Compiling ZIPUP C...'\n'cc zipup c 'parms\nsay 'Compiling CMSMVS C...'\n'cc cmsmvs c 'parms\nsay 'Compiling CMS C...'\n'cc cms c 'parms\n\nsay 'Linking all files...'\n'cmod zip zip trees crypt deflate fileio globals ttyio',\n           'util crc32 zipfile zipup cmsmvs cms'\nsay 'All Done!'\nsay \"To run enter : ZIP parms\"\nexit rc\n\nerror:\nsay 'Error durring compilation!'\nexit rc\n"
  },
  {
    "path": "deps/infozip/zip30/crc32.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc32.c -- compute the CRC-32 of a data stream\n * Copyright (C) 1995 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n *\n * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster\n * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing\n * tables for updating the shift register in one step with three exclusive-ors\n * instead of four steps with four exclusive-ors.  This results about a factor\n * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.\n */\n\n/* $Id: crc32.c,v 2.0 2007/01/07 05:20:36 spc Exp $ */\n\n#define __CRC32_C       /* identifies this source module */\n\n#include \"zip.h\"\n\n#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#include \"crc32.h\"\n\n/* When only the table of precomputed CRC values is needed, only the basic\n   system-independent table containing 256 entries is created; any support\n   for \"unfolding\" optimization is disabled.\n */\n#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n#    undef IZ_CRCOPTIM_UNFOLDTBL\n#  endif\n#endif /* (USE_ZLIB || CRC_TABLE_ONLY) */\n\n#if defined(IZ_CRCOPTIM_UNFOLDTBL)\n#  define CRC_TBLS  4\n#else\n#  define CRC_TBLS  1\n#endif\n\n\n/*\n  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:\n  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.\n\n  Polynomials over GF(2) are represented in binary, one bit per coefficient,\n  with the lowest powers in the most significant bit.  Then adding polynomials\n  is just exclusive-or, and multiplying a polynomial by x is a right shift by\n  one.  If we call the above polynomial p, and represent a byte as the\n  polynomial q, also with the lowest power in the most significant bit (so the\n  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,\n  where a mod b means the remainder after dividing a by b.\n\n  This calculation is done using the shift-register method of multiplying and\n  taking the remainder.  The register is initialized to zero, and for each\n  incoming bit, x^32 is added mod p to the register if the bit is a one (where\n  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by\n  x (which is shifting right by one and adding x^32 mod p if the bit shifted\n  out is a one).  We start with the highest power (least significant bit) of\n  q and repeat for all eight bits of q.\n\n  The first (or only) table is simply the CRC of all possible eight bit values.\n  This is all the information needed to generate CRC's on data a byte-at-a-time\n  for all combinations of CRC register values and incoming bytes.\n  The remaining 3 tables (if IZ_CRCOPTIM_UNFOLDTBL is enabled) allow for\n  word-at-a-time CRC calculation, where a word is four bytes.\n*/\n\n#ifdef DYNAMIC_CRC_TABLE\n\n/* =========================================================================\n * Make the crc table. This function is needed only if you want to compute\n * the table dynamically.\n */\n\nlocal void make_crc_table OF((void));\n\n#if (defined(DYNALLOC_CRCTAB) && defined(REENTRANT))\n   error: Dynamic allocation of CRC table not safe with reentrant code.\n#endif /* DYNALLOC_CRCTAB && REENTRANT */\n\n#ifdef DYNALLOC_CRCTAB\n   local ulg near *crc_table = NULL;\n# if 0          /* not used, since sizeof(\"near *\") <= sizeof(int) */\n   /* Use this section when access to a \"local int\" is faster than access to\n      a \"local pointer\" (e.g.: i86 16bit code with far pointers). */\n   local int crc_table_empty = 1;\n#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)\n#  define MARK_CRCTAB_FILLED    crc_table_empty = 0\n#  define MARK_CRCTAB_EMPTY     crc_table_empty = 1\n# else\n   /* Use this section on systems where the size of pointers and ints is\n      equal (e.g.: all 32bit systems). */\n#  define CRC_TABLE_IS_EMPTY    (crc_table == NULL)\n#  define MARK_CRCTAB_FILLED    crc_table = crctab_p\n#  define MARK_CRCTAB_EMPTY     crc_table = NULL\n# endif\n#else /* !DYNALLOC_CRCTAB */\n   local ulg near crc_table[CRC_TBLS*256];\n   local int crc_table_empty = 1;\n#  define CRC_TABLE_IS_EMPTY    (crc_table_empty != 0)\n#  define MARK_CRCTAB_FILLED    crc_table_empty = 0\n#endif /* ?DYNALLOC_CRCTAB */\n\n\nlocal void make_crc_table()\n{\n  ulg c;                /* crc shift register */\n  int n;                /* counter for all possible eight bit values */\n  int k;                /* byte being shifted into crc apparatus */\n#ifdef DYNALLOC_CRCTAB\n  ulg near *crctab_p;   /* temporary pointer to allocated crc_table area */\n#else /* !DYNALLOC_CRCTAB */\n# define crctab_p crc_table\n#endif /* DYNALLOC_CRCTAB */\n\n#ifdef COMPUTE_XOR_PATTERN\n  /* This piece of code has been left here to explain how the XOR pattern\n   * used in the creation of the crc_table values can be recomputed.\n   * For production versions of this function, it is more efficient to\n   * supply the resultant pattern at compile time.\n   */\n  ulg xor;              /* polynomial exclusive-or pattern */\n  /* terms of polynomial defining this crc (except x^32): */\n  static ZCONST uch p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};\n\n  /* make exclusive-or pattern from polynomial (0xedb88320L) */\n  xor = 0L;\n  for (n = 0; n < sizeof(p)/sizeof(uch); n++)\n    xor |= 1L << (31 - p[n]);\n#else\n# define xor 0xedb88320L\n#endif\n\n#ifdef DYNALLOC_CRCTAB\n  crctab_p = (ulg near *) nearmalloc (CRC_TBLS*256*sizeof(ulg));\n  if (crctab_p == NULL) {\n    ziperr(ZE_MEM, \"crc_table allocation\");\n  }\n#endif /* DYNALLOC_CRCTAB */\n\n  /* generate a crc for every 8-bit value */\n  for (n = 0; n < 256; n++) {\n    c = (ulg)n;\n    for (k = 8; k; k--)\n      c = c & 1 ? xor ^ (c >> 1) : c >> 1;\n    crctab_p[n] = REV_BE(c);\n  }\n\n#ifdef IZ_CRCOPTIM_UNFOLDTBL\n  /* generate crc for each value followed by one, two, and three zeros */\n  for (n = 0; n < 256; n++) {\n      c = crctab_p[n];\n      for (k = 1; k < 4; k++) {\n          c = CRC32(c, 0, crctab_p);\n          crctab_p[k*256+n] = c;\n      }\n  }\n#endif /* IZ_CRCOPTIM_UNFOLDTBL */\n\n  MARK_CRCTAB_FILLED;\n}\n\n#else /* !DYNAMIC_CRC_TABLE */\n\n#ifdef DYNALLOC_CRCTAB\n   error: Inconsistent flags, DYNALLOC_CRCTAB without DYNAMIC_CRC_TABLE.\n#endif\n\n/* ========================================================================\n * Table of CRC-32's of all single-byte values (made by make_crc_table)\n */\nlocal ZCONST ulg near crc_table[CRC_TBLS*256] = {\n# ifdef IZ_CRC_BE_OPTIMIZ\n    0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L,\n    0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L,\n    0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L,\n    0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L,\n    0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L,\n    0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L,\n    0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L,\n    0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L,\n    0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L,\n    0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L,\n    0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL,\n    0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L,\n    0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L,\n    0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L,\n    0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L,\n    0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L,\n    0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL,\n    0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L,\n    0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL,\n    0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L,\n    0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L,\n    0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L,\n    0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL,\n    0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL,\n    0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L,\n    0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL,\n    0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L,\n    0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL,\n    0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L,\n    0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L,\n    0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L,\n    0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L,\n    0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L,\n    0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL,\n    0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L,\n    0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L,\n    0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L,\n    0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L,\n    0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L,\n    0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L,\n    0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L,\n    0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L,\n    0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL,\n    0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L,\n    0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L,\n    0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L,\n    0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L,\n    0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L,\n    0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL,\n    0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L,\n    0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL,\n    0x8def022dL\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n    ,\n    0x00000000L, 0x41311b19L, 0x82623632L, 0xc3532d2bL, 0x04c56c64L,\n    0x45f4777dL, 0x86a75a56L, 0xc796414fL, 0x088ad9c8L, 0x49bbc2d1L,\n    0x8ae8effaL, 0xcbd9f4e3L, 0x0c4fb5acL, 0x4d7eaeb5L, 0x8e2d839eL,\n    0xcf1c9887L, 0x5112c24aL, 0x1023d953L, 0xd370f478L, 0x9241ef61L,\n    0x55d7ae2eL, 0x14e6b537L, 0xd7b5981cL, 0x96848305L, 0x59981b82L,\n    0x18a9009bL, 0xdbfa2db0L, 0x9acb36a9L, 0x5d5d77e6L, 0x1c6c6cffL,\n    0xdf3f41d4L, 0x9e0e5acdL, 0xa2248495L, 0xe3159f8cL, 0x2046b2a7L,\n    0x6177a9beL, 0xa6e1e8f1L, 0xe7d0f3e8L, 0x2483dec3L, 0x65b2c5daL,\n    0xaaae5d5dL, 0xeb9f4644L, 0x28cc6b6fL, 0x69fd7076L, 0xae6b3139L,\n    0xef5a2a20L, 0x2c09070bL, 0x6d381c12L, 0xf33646dfL, 0xb2075dc6L,\n    0x715470edL, 0x30656bf4L, 0xf7f32abbL, 0xb6c231a2L, 0x75911c89L,\n    0x34a00790L, 0xfbbc9f17L, 0xba8d840eL, 0x79dea925L, 0x38efb23cL,\n    0xff79f373L, 0xbe48e86aL, 0x7d1bc541L, 0x3c2ade58L, 0x054f79f0L,\n    0x447e62e9L, 0x872d4fc2L, 0xc61c54dbL, 0x018a1594L, 0x40bb0e8dL,\n    0x83e823a6L, 0xc2d938bfL, 0x0dc5a038L, 0x4cf4bb21L, 0x8fa7960aL,\n    0xce968d13L, 0x0900cc5cL, 0x4831d745L, 0x8b62fa6eL, 0xca53e177L,\n    0x545dbbbaL, 0x156ca0a3L, 0xd63f8d88L, 0x970e9691L, 0x5098d7deL,\n    0x11a9ccc7L, 0xd2fae1ecL, 0x93cbfaf5L, 0x5cd76272L, 0x1de6796bL,\n    0xdeb55440L, 0x9f844f59L, 0x58120e16L, 0x1923150fL, 0xda703824L,\n    0x9b41233dL, 0xa76bfd65L, 0xe65ae67cL, 0x2509cb57L, 0x6438d04eL,\n    0xa3ae9101L, 0xe29f8a18L, 0x21cca733L, 0x60fdbc2aL, 0xafe124adL,\n    0xeed03fb4L, 0x2d83129fL, 0x6cb20986L, 0xab2448c9L, 0xea1553d0L,\n    0x29467efbL, 0x687765e2L, 0xf6793f2fL, 0xb7482436L, 0x741b091dL,\n    0x352a1204L, 0xf2bc534bL, 0xb38d4852L, 0x70de6579L, 0x31ef7e60L,\n    0xfef3e6e7L, 0xbfc2fdfeL, 0x7c91d0d5L, 0x3da0cbccL, 0xfa368a83L,\n    0xbb07919aL, 0x7854bcb1L, 0x3965a7a8L, 0x4b98833bL, 0x0aa99822L,\n    0xc9fab509L, 0x88cbae10L, 0x4f5def5fL, 0x0e6cf446L, 0xcd3fd96dL,\n    0x8c0ec274L, 0x43125af3L, 0x022341eaL, 0xc1706cc1L, 0x804177d8L,\n    0x47d73697L, 0x06e62d8eL, 0xc5b500a5L, 0x84841bbcL, 0x1a8a4171L,\n    0x5bbb5a68L, 0x98e87743L, 0xd9d96c5aL, 0x1e4f2d15L, 0x5f7e360cL,\n    0x9c2d1b27L, 0xdd1c003eL, 0x120098b9L, 0x533183a0L, 0x9062ae8bL,\n    0xd153b592L, 0x16c5f4ddL, 0x57f4efc4L, 0x94a7c2efL, 0xd596d9f6L,\n    0xe9bc07aeL, 0xa88d1cb7L, 0x6bde319cL, 0x2aef2a85L, 0xed796bcaL,\n    0xac4870d3L, 0x6f1b5df8L, 0x2e2a46e1L, 0xe136de66L, 0xa007c57fL,\n    0x6354e854L, 0x2265f34dL, 0xe5f3b202L, 0xa4c2a91bL, 0x67918430L,\n    0x26a09f29L, 0xb8aec5e4L, 0xf99fdefdL, 0x3accf3d6L, 0x7bfde8cfL,\n    0xbc6ba980L, 0xfd5ab299L, 0x3e099fb2L, 0x7f3884abL, 0xb0241c2cL,\n    0xf1150735L, 0x32462a1eL, 0x73773107L, 0xb4e17048L, 0xf5d06b51L,\n    0x3683467aL, 0x77b25d63L, 0x4ed7facbL, 0x0fe6e1d2L, 0xccb5ccf9L,\n    0x8d84d7e0L, 0x4a1296afL, 0x0b238db6L, 0xc870a09dL, 0x8941bb84L,\n    0x465d2303L, 0x076c381aL, 0xc43f1531L, 0x850e0e28L, 0x42984f67L,\n    0x03a9547eL, 0xc0fa7955L, 0x81cb624cL, 0x1fc53881L, 0x5ef42398L,\n    0x9da70eb3L, 0xdc9615aaL, 0x1b0054e5L, 0x5a314ffcL, 0x996262d7L,\n    0xd85379ceL, 0x174fe149L, 0x567efa50L, 0x952dd77bL, 0xd41ccc62L,\n    0x138a8d2dL, 0x52bb9634L, 0x91e8bb1fL, 0xd0d9a006L, 0xecf37e5eL,\n    0xadc26547L, 0x6e91486cL, 0x2fa05375L, 0xe836123aL, 0xa9070923L,\n    0x6a542408L, 0x2b653f11L, 0xe479a796L, 0xa548bc8fL, 0x661b91a4L,\n    0x272a8abdL, 0xe0bccbf2L, 0xa18dd0ebL, 0x62defdc0L, 0x23efe6d9L,\n    0xbde1bc14L, 0xfcd0a70dL, 0x3f838a26L, 0x7eb2913fL, 0xb924d070L,\n    0xf815cb69L, 0x3b46e642L, 0x7a77fd5bL, 0xb56b65dcL, 0xf45a7ec5L,\n    0x370953eeL, 0x763848f7L, 0xb1ae09b8L, 0xf09f12a1L, 0x33cc3f8aL,\n    0x72fd2493L\n    ,\n    0x00000000L, 0x376ac201L, 0x6ed48403L, 0x59be4602L, 0xdca80907L,\n    0xebc2cb06L, 0xb27c8d04L, 0x85164f05L, 0xb851130eL, 0x8f3bd10fL,\n    0xd685970dL, 0xe1ef550cL, 0x64f91a09L, 0x5393d808L, 0x0a2d9e0aL,\n    0x3d475c0bL, 0x70a3261cL, 0x47c9e41dL, 0x1e77a21fL, 0x291d601eL,\n    0xac0b2f1bL, 0x9b61ed1aL, 0xc2dfab18L, 0xf5b56919L, 0xc8f23512L,\n    0xff98f713L, 0xa626b111L, 0x914c7310L, 0x145a3c15L, 0x2330fe14L,\n    0x7a8eb816L, 0x4de47a17L, 0xe0464d38L, 0xd72c8f39L, 0x8e92c93bL,\n    0xb9f80b3aL, 0x3cee443fL, 0x0b84863eL, 0x523ac03cL, 0x6550023dL,\n    0x58175e36L, 0x6f7d9c37L, 0x36c3da35L, 0x01a91834L, 0x84bf5731L,\n    0xb3d59530L, 0xea6bd332L, 0xdd011133L, 0x90e56b24L, 0xa78fa925L,\n    0xfe31ef27L, 0xc95b2d26L, 0x4c4d6223L, 0x7b27a022L, 0x2299e620L,\n    0x15f32421L, 0x28b4782aL, 0x1fdeba2bL, 0x4660fc29L, 0x710a3e28L,\n    0xf41c712dL, 0xc376b32cL, 0x9ac8f52eL, 0xada2372fL, 0xc08d9a70L,\n    0xf7e75871L, 0xae591e73L, 0x9933dc72L, 0x1c259377L, 0x2b4f5176L,\n    0x72f11774L, 0x459bd575L, 0x78dc897eL, 0x4fb64b7fL, 0x16080d7dL,\n    0x2162cf7cL, 0xa4748079L, 0x931e4278L, 0xcaa0047aL, 0xfdcac67bL,\n    0xb02ebc6cL, 0x87447e6dL, 0xdefa386fL, 0xe990fa6eL, 0x6c86b56bL,\n    0x5bec776aL, 0x02523168L, 0x3538f369L, 0x087faf62L, 0x3f156d63L,\n    0x66ab2b61L, 0x51c1e960L, 0xd4d7a665L, 0xe3bd6464L, 0xba032266L,\n    0x8d69e067L, 0x20cbd748L, 0x17a11549L, 0x4e1f534bL, 0x7975914aL,\n    0xfc63de4fL, 0xcb091c4eL, 0x92b75a4cL, 0xa5dd984dL, 0x989ac446L,\n    0xaff00647L, 0xf64e4045L, 0xc1248244L, 0x4432cd41L, 0x73580f40L,\n    0x2ae64942L, 0x1d8c8b43L, 0x5068f154L, 0x67023355L, 0x3ebc7557L,\n    0x09d6b756L, 0x8cc0f853L, 0xbbaa3a52L, 0xe2147c50L, 0xd57ebe51L,\n    0xe839e25aL, 0xdf53205bL, 0x86ed6659L, 0xb187a458L, 0x3491eb5dL,\n    0x03fb295cL, 0x5a456f5eL, 0x6d2fad5fL, 0x801b35e1L, 0xb771f7e0L,\n    0xeecfb1e2L, 0xd9a573e3L, 0x5cb33ce6L, 0x6bd9fee7L, 0x3267b8e5L,\n    0x050d7ae4L, 0x384a26efL, 0x0f20e4eeL, 0x569ea2ecL, 0x61f460edL,\n    0xe4e22fe8L, 0xd388ede9L, 0x8a36abebL, 0xbd5c69eaL, 0xf0b813fdL,\n    0xc7d2d1fcL, 0x9e6c97feL, 0xa90655ffL, 0x2c101afaL, 0x1b7ad8fbL,\n    0x42c49ef9L, 0x75ae5cf8L, 0x48e900f3L, 0x7f83c2f2L, 0x263d84f0L,\n    0x115746f1L, 0x944109f4L, 0xa32bcbf5L, 0xfa958df7L, 0xcdff4ff6L,\n    0x605d78d9L, 0x5737bad8L, 0x0e89fcdaL, 0x39e33edbL, 0xbcf571deL,\n    0x8b9fb3dfL, 0xd221f5ddL, 0xe54b37dcL, 0xd80c6bd7L, 0xef66a9d6L,\n    0xb6d8efd4L, 0x81b22dd5L, 0x04a462d0L, 0x33cea0d1L, 0x6a70e6d3L,\n    0x5d1a24d2L, 0x10fe5ec5L, 0x27949cc4L, 0x7e2adac6L, 0x494018c7L,\n    0xcc5657c2L, 0xfb3c95c3L, 0xa282d3c1L, 0x95e811c0L, 0xa8af4dcbL,\n    0x9fc58fcaL, 0xc67bc9c8L, 0xf1110bc9L, 0x740744ccL, 0x436d86cdL,\n    0x1ad3c0cfL, 0x2db902ceL, 0x4096af91L, 0x77fc6d90L, 0x2e422b92L,\n    0x1928e993L, 0x9c3ea696L, 0xab546497L, 0xf2ea2295L, 0xc580e094L,\n    0xf8c7bc9fL, 0xcfad7e9eL, 0x9613389cL, 0xa179fa9dL, 0x246fb598L,\n    0x13057799L, 0x4abb319bL, 0x7dd1f39aL, 0x3035898dL, 0x075f4b8cL,\n    0x5ee10d8eL, 0x698bcf8fL, 0xec9d808aL, 0xdbf7428bL, 0x82490489L,\n    0xb523c688L, 0x88649a83L, 0xbf0e5882L, 0xe6b01e80L, 0xd1dadc81L,\n    0x54cc9384L, 0x63a65185L, 0x3a181787L, 0x0d72d586L, 0xa0d0e2a9L,\n    0x97ba20a8L, 0xce0466aaL, 0xf96ea4abL, 0x7c78ebaeL, 0x4b1229afL,\n    0x12ac6fadL, 0x25c6adacL, 0x1881f1a7L, 0x2feb33a6L, 0x765575a4L,\n    0x413fb7a5L, 0xc429f8a0L, 0xf3433aa1L, 0xaafd7ca3L, 0x9d97bea2L,\n    0xd073c4b5L, 0xe71906b4L, 0xbea740b6L, 0x89cd82b7L, 0x0cdbcdb2L,\n    0x3bb10fb3L, 0x620f49b1L, 0x55658bb0L, 0x6822d7bbL, 0x5f4815baL,\n    0x06f653b8L, 0x319c91b9L, 0xb48adebcL, 0x83e01cbdL, 0xda5e5abfL,\n    0xed3498beL\n    ,\n    0x00000000L, 0x6567bcb8L, 0x8bc809aaL, 0xeeafb512L, 0x5797628fL,\n    0x32f0de37L, 0xdc5f6b25L, 0xb938d79dL, 0xef28b4c5L, 0x8a4f087dL,\n    0x64e0bd6fL, 0x018701d7L, 0xb8bfd64aL, 0xddd86af2L, 0x3377dfe0L,\n    0x56106358L, 0x9f571950L, 0xfa30a5e8L, 0x149f10faL, 0x71f8ac42L,\n    0xc8c07bdfL, 0xada7c767L, 0x43087275L, 0x266fcecdL, 0x707fad95L,\n    0x1518112dL, 0xfbb7a43fL, 0x9ed01887L, 0x27e8cf1aL, 0x428f73a2L,\n    0xac20c6b0L, 0xc9477a08L, 0x3eaf32a0L, 0x5bc88e18L, 0xb5673b0aL,\n    0xd00087b2L, 0x6938502fL, 0x0c5fec97L, 0xe2f05985L, 0x8797e53dL,\n    0xd1878665L, 0xb4e03addL, 0x5a4f8fcfL, 0x3f283377L, 0x8610e4eaL,\n    0xe3775852L, 0x0dd8ed40L, 0x68bf51f8L, 0xa1f82bf0L, 0xc49f9748L,\n    0x2a30225aL, 0x4f579ee2L, 0xf66f497fL, 0x9308f5c7L, 0x7da740d5L,\n    0x18c0fc6dL, 0x4ed09f35L, 0x2bb7238dL, 0xc518969fL, 0xa07f2a27L,\n    0x1947fdbaL, 0x7c204102L, 0x928ff410L, 0xf7e848a8L, 0x3d58149bL,\n    0x583fa823L, 0xb6901d31L, 0xd3f7a189L, 0x6acf7614L, 0x0fa8caacL,\n    0xe1077fbeL, 0x8460c306L, 0xd270a05eL, 0xb7171ce6L, 0x59b8a9f4L,\n    0x3cdf154cL, 0x85e7c2d1L, 0xe0807e69L, 0x0e2fcb7bL, 0x6b4877c3L,\n    0xa20f0dcbL, 0xc768b173L, 0x29c70461L, 0x4ca0b8d9L, 0xf5986f44L,\n    0x90ffd3fcL, 0x7e5066eeL, 0x1b37da56L, 0x4d27b90eL, 0x284005b6L,\n    0xc6efb0a4L, 0xa3880c1cL, 0x1ab0db81L, 0x7fd76739L, 0x9178d22bL,\n    0xf41f6e93L, 0x03f7263bL, 0x66909a83L, 0x883f2f91L, 0xed589329L,\n    0x546044b4L, 0x3107f80cL, 0xdfa84d1eL, 0xbacff1a6L, 0xecdf92feL,\n    0x89b82e46L, 0x67179b54L, 0x027027ecL, 0xbb48f071L, 0xde2f4cc9L,\n    0x3080f9dbL, 0x55e74563L, 0x9ca03f6bL, 0xf9c783d3L, 0x176836c1L,\n    0x720f8a79L, 0xcb375de4L, 0xae50e15cL, 0x40ff544eL, 0x2598e8f6L,\n    0x73888baeL, 0x16ef3716L, 0xf8408204L, 0x9d273ebcL, 0x241fe921L,\n    0x41785599L, 0xafd7e08bL, 0xcab05c33L, 0x3bb659edL, 0x5ed1e555L,\n    0xb07e5047L, 0xd519ecffL, 0x6c213b62L, 0x094687daL, 0xe7e932c8L,\n    0x828e8e70L, 0xd49eed28L, 0xb1f95190L, 0x5f56e482L, 0x3a31583aL,\n    0x83098fa7L, 0xe66e331fL, 0x08c1860dL, 0x6da63ab5L, 0xa4e140bdL,\n    0xc186fc05L, 0x2f294917L, 0x4a4ef5afL, 0xf3762232L, 0x96119e8aL,\n    0x78be2b98L, 0x1dd99720L, 0x4bc9f478L, 0x2eae48c0L, 0xc001fdd2L,\n    0xa566416aL, 0x1c5e96f7L, 0x79392a4fL, 0x97969f5dL, 0xf2f123e5L,\n    0x05196b4dL, 0x607ed7f5L, 0x8ed162e7L, 0xebb6de5fL, 0x528e09c2L,\n    0x37e9b57aL, 0xd9460068L, 0xbc21bcd0L, 0xea31df88L, 0x8f566330L,\n    0x61f9d622L, 0x049e6a9aL, 0xbda6bd07L, 0xd8c101bfL, 0x366eb4adL,\n    0x53090815L, 0x9a4e721dL, 0xff29cea5L, 0x11867bb7L, 0x74e1c70fL,\n    0xcdd91092L, 0xa8beac2aL, 0x46111938L, 0x2376a580L, 0x7566c6d8L,\n    0x10017a60L, 0xfeaecf72L, 0x9bc973caL, 0x22f1a457L, 0x479618efL,\n    0xa939adfdL, 0xcc5e1145L, 0x06ee4d76L, 0x6389f1ceL, 0x8d2644dcL,\n    0xe841f864L, 0x51792ff9L, 0x341e9341L, 0xdab12653L, 0xbfd69aebL,\n    0xe9c6f9b3L, 0x8ca1450bL, 0x620ef019L, 0x07694ca1L, 0xbe519b3cL,\n    0xdb362784L, 0x35999296L, 0x50fe2e2eL, 0x99b95426L, 0xfcdee89eL,\n    0x12715d8cL, 0x7716e134L, 0xce2e36a9L, 0xab498a11L, 0x45e63f03L,\n    0x208183bbL, 0x7691e0e3L, 0x13f65c5bL, 0xfd59e949L, 0x983e55f1L,\n    0x2106826cL, 0x44613ed4L, 0xaace8bc6L, 0xcfa9377eL, 0x38417fd6L,\n    0x5d26c36eL, 0xb389767cL, 0xd6eecac4L, 0x6fd61d59L, 0x0ab1a1e1L,\n    0xe41e14f3L, 0x8179a84bL, 0xd769cb13L, 0xb20e77abL, 0x5ca1c2b9L,\n    0x39c67e01L, 0x80fea99cL, 0xe5991524L, 0x0b36a036L, 0x6e511c8eL,\n    0xa7166686L, 0xc271da3eL, 0x2cde6f2cL, 0x49b9d394L, 0xf0810409L,\n    0x95e6b8b1L, 0x7b490da3L, 0x1e2eb11bL, 0x483ed243L, 0x2d596efbL,\n    0xc3f6dbe9L, 0xa6916751L, 0x1fa9b0ccL, 0x7ace0c74L, 0x9461b966L,\n    0xf10605deL\n#  endif /* IZ_CRCOPTIM_UNFOLDTBL */\n# else /* !IZ_CRC_BE_OPTIMIZ */\n    0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,\n    0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,\n    0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,\n    0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,\n    0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,\n    0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,\n    0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,\n    0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,\n    0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,\n    0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,\n    0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,\n    0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,\n    0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,\n    0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,\n    0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,\n    0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,\n    0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,\n    0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,\n    0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,\n    0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,\n    0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,\n    0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,\n    0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,\n    0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,\n    0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,\n    0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,\n    0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,\n    0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,\n    0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,\n    0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,\n    0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,\n    0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,\n    0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,\n    0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,\n    0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,\n    0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,\n    0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,\n    0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,\n    0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,\n    0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,\n    0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,\n    0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,\n    0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,\n    0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,\n    0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,\n    0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,\n    0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,\n    0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,\n    0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,\n    0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,\n    0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,\n    0x2d02ef8dL\n#  ifdef IZ_CRCOPTIM_UNFOLDTBL\n    ,\n    0x00000000L, 0x191b3141L, 0x32366282L, 0x2b2d53c3L, 0x646cc504L,\n    0x7d77f445L, 0x565aa786L, 0x4f4196c7L, 0xc8d98a08L, 0xd1c2bb49L,\n    0xfaefe88aL, 0xe3f4d9cbL, 0xacb54f0cL, 0xb5ae7e4dL, 0x9e832d8eL,\n    0x87981ccfL, 0x4ac21251L, 0x53d92310L, 0x78f470d3L, 0x61ef4192L,\n    0x2eaed755L, 0x37b5e614L, 0x1c98b5d7L, 0x05838496L, 0x821b9859L,\n    0x9b00a918L, 0xb02dfadbL, 0xa936cb9aL, 0xe6775d5dL, 0xff6c6c1cL,\n    0xd4413fdfL, 0xcd5a0e9eL, 0x958424a2L, 0x8c9f15e3L, 0xa7b24620L,\n    0xbea97761L, 0xf1e8e1a6L, 0xe8f3d0e7L, 0xc3de8324L, 0xdac5b265L,\n    0x5d5daeaaL, 0x44469febL, 0x6f6bcc28L, 0x7670fd69L, 0x39316baeL,\n    0x202a5aefL, 0x0b07092cL, 0x121c386dL, 0xdf4636f3L, 0xc65d07b2L,\n    0xed705471L, 0xf46b6530L, 0xbb2af3f7L, 0xa231c2b6L, 0x891c9175L,\n    0x9007a034L, 0x179fbcfbL, 0x0e848dbaL, 0x25a9de79L, 0x3cb2ef38L,\n    0x73f379ffL, 0x6ae848beL, 0x41c51b7dL, 0x58de2a3cL, 0xf0794f05L,\n    0xe9627e44L, 0xc24f2d87L, 0xdb541cc6L, 0x94158a01L, 0x8d0ebb40L,\n    0xa623e883L, 0xbf38d9c2L, 0x38a0c50dL, 0x21bbf44cL, 0x0a96a78fL,\n    0x138d96ceL, 0x5ccc0009L, 0x45d73148L, 0x6efa628bL, 0x77e153caL,\n    0xbabb5d54L, 0xa3a06c15L, 0x888d3fd6L, 0x91960e97L, 0xded79850L,\n    0xc7cca911L, 0xece1fad2L, 0xf5facb93L, 0x7262d75cL, 0x6b79e61dL,\n    0x4054b5deL, 0x594f849fL, 0x160e1258L, 0x0f152319L, 0x243870daL,\n    0x3d23419bL, 0x65fd6ba7L, 0x7ce65ae6L, 0x57cb0925L, 0x4ed03864L,\n    0x0191aea3L, 0x188a9fe2L, 0x33a7cc21L, 0x2abcfd60L, 0xad24e1afL,\n    0xb43fd0eeL, 0x9f12832dL, 0x8609b26cL, 0xc94824abL, 0xd05315eaL,\n    0xfb7e4629L, 0xe2657768L, 0x2f3f79f6L, 0x362448b7L, 0x1d091b74L,\n    0x04122a35L, 0x4b53bcf2L, 0x52488db3L, 0x7965de70L, 0x607eef31L,\n    0xe7e6f3feL, 0xfefdc2bfL, 0xd5d0917cL, 0xcccba03dL, 0x838a36faL,\n    0x9a9107bbL, 0xb1bc5478L, 0xa8a76539L, 0x3b83984bL, 0x2298a90aL,\n    0x09b5fac9L, 0x10aecb88L, 0x5fef5d4fL, 0x46f46c0eL, 0x6dd93fcdL,\n    0x74c20e8cL, 0xf35a1243L, 0xea412302L, 0xc16c70c1L, 0xd8774180L,\n    0x9736d747L, 0x8e2de606L, 0xa500b5c5L, 0xbc1b8484L, 0x71418a1aL,\n    0x685abb5bL, 0x4377e898L, 0x5a6cd9d9L, 0x152d4f1eL, 0x0c367e5fL,\n    0x271b2d9cL, 0x3e001cddL, 0xb9980012L, 0xa0833153L, 0x8bae6290L,\n    0x92b553d1L, 0xddf4c516L, 0xc4eff457L, 0xefc2a794L, 0xf6d996d5L,\n    0xae07bce9L, 0xb71c8da8L, 0x9c31de6bL, 0x852aef2aL, 0xca6b79edL,\n    0xd37048acL, 0xf85d1b6fL, 0xe1462a2eL, 0x66de36e1L, 0x7fc507a0L,\n    0x54e85463L, 0x4df36522L, 0x02b2f3e5L, 0x1ba9c2a4L, 0x30849167L,\n    0x299fa026L, 0xe4c5aeb8L, 0xfdde9ff9L, 0xd6f3cc3aL, 0xcfe8fd7bL,\n    0x80a96bbcL, 0x99b25afdL, 0xb29f093eL, 0xab84387fL, 0x2c1c24b0L,\n    0x350715f1L, 0x1e2a4632L, 0x07317773L, 0x4870e1b4L, 0x516bd0f5L,\n    0x7a468336L, 0x635db277L, 0xcbfad74eL, 0xd2e1e60fL, 0xf9ccb5ccL,\n    0xe0d7848dL, 0xaf96124aL, 0xb68d230bL, 0x9da070c8L, 0x84bb4189L,\n    0x03235d46L, 0x1a386c07L, 0x31153fc4L, 0x280e0e85L, 0x674f9842L,\n    0x7e54a903L, 0x5579fac0L, 0x4c62cb81L, 0x8138c51fL, 0x9823f45eL,\n    0xb30ea79dL, 0xaa1596dcL, 0xe554001bL, 0xfc4f315aL, 0xd7626299L,\n    0xce7953d8L, 0x49e14f17L, 0x50fa7e56L, 0x7bd72d95L, 0x62cc1cd4L,\n    0x2d8d8a13L, 0x3496bb52L, 0x1fbbe891L, 0x06a0d9d0L, 0x5e7ef3ecL,\n    0x4765c2adL, 0x6c48916eL, 0x7553a02fL, 0x3a1236e8L, 0x230907a9L,\n    0x0824546aL, 0x113f652bL, 0x96a779e4L, 0x8fbc48a5L, 0xa4911b66L,\n    0xbd8a2a27L, 0xf2cbbce0L, 0xebd08da1L, 0xc0fdde62L, 0xd9e6ef23L,\n    0x14bce1bdL, 0x0da7d0fcL, 0x268a833fL, 0x3f91b27eL, 0x70d024b9L,\n    0x69cb15f8L, 0x42e6463bL, 0x5bfd777aL, 0xdc656bb5L, 0xc57e5af4L,\n    0xee530937L, 0xf7483876L, 0xb809aeb1L, 0xa1129ff0L, 0x8a3fcc33L,\n    0x9324fd72L\n    ,\n    0x00000000L, 0x01c26a37L, 0x0384d46eL, 0x0246be59L, 0x0709a8dcL,\n    0x06cbc2ebL, 0x048d7cb2L, 0x054f1685L, 0x0e1351b8L, 0x0fd13b8fL,\n    0x0d9785d6L, 0x0c55efe1L, 0x091af964L, 0x08d89353L, 0x0a9e2d0aL,\n    0x0b5c473dL, 0x1c26a370L, 0x1de4c947L, 0x1fa2771eL, 0x1e601d29L,\n    0x1b2f0bacL, 0x1aed619bL, 0x18abdfc2L, 0x1969b5f5L, 0x1235f2c8L,\n    0x13f798ffL, 0x11b126a6L, 0x10734c91L, 0x153c5a14L, 0x14fe3023L,\n    0x16b88e7aL, 0x177ae44dL, 0x384d46e0L, 0x398f2cd7L, 0x3bc9928eL,\n    0x3a0bf8b9L, 0x3f44ee3cL, 0x3e86840bL, 0x3cc03a52L, 0x3d025065L,\n    0x365e1758L, 0x379c7d6fL, 0x35dac336L, 0x3418a901L, 0x3157bf84L,\n    0x3095d5b3L, 0x32d36beaL, 0x331101ddL, 0x246be590L, 0x25a98fa7L,\n    0x27ef31feL, 0x262d5bc9L, 0x23624d4cL, 0x22a0277bL, 0x20e69922L,\n    0x2124f315L, 0x2a78b428L, 0x2bbade1fL, 0x29fc6046L, 0x283e0a71L,\n    0x2d711cf4L, 0x2cb376c3L, 0x2ef5c89aL, 0x2f37a2adL, 0x709a8dc0L,\n    0x7158e7f7L, 0x731e59aeL, 0x72dc3399L, 0x7793251cL, 0x76514f2bL,\n    0x7417f172L, 0x75d59b45L, 0x7e89dc78L, 0x7f4bb64fL, 0x7d0d0816L,\n    0x7ccf6221L, 0x798074a4L, 0x78421e93L, 0x7a04a0caL, 0x7bc6cafdL,\n    0x6cbc2eb0L, 0x6d7e4487L, 0x6f38fadeL, 0x6efa90e9L, 0x6bb5866cL,\n    0x6a77ec5bL, 0x68315202L, 0x69f33835L, 0x62af7f08L, 0x636d153fL,\n    0x612bab66L, 0x60e9c151L, 0x65a6d7d4L, 0x6464bde3L, 0x662203baL,\n    0x67e0698dL, 0x48d7cb20L, 0x4915a117L, 0x4b531f4eL, 0x4a917579L,\n    0x4fde63fcL, 0x4e1c09cbL, 0x4c5ab792L, 0x4d98dda5L, 0x46c49a98L,\n    0x4706f0afL, 0x45404ef6L, 0x448224c1L, 0x41cd3244L, 0x400f5873L,\n    0x4249e62aL, 0x438b8c1dL, 0x54f16850L, 0x55330267L, 0x5775bc3eL,\n    0x56b7d609L, 0x53f8c08cL, 0x523aaabbL, 0x507c14e2L, 0x51be7ed5L,\n    0x5ae239e8L, 0x5b2053dfL, 0x5966ed86L, 0x58a487b1L, 0x5deb9134L,\n    0x5c29fb03L, 0x5e6f455aL, 0x5fad2f6dL, 0xe1351b80L, 0xe0f771b7L,\n    0xe2b1cfeeL, 0xe373a5d9L, 0xe63cb35cL, 0xe7fed96bL, 0xe5b86732L,\n    0xe47a0d05L, 0xef264a38L, 0xeee4200fL, 0xeca29e56L, 0xed60f461L,\n    0xe82fe2e4L, 0xe9ed88d3L, 0xebab368aL, 0xea695cbdL, 0xfd13b8f0L,\n    0xfcd1d2c7L, 0xfe976c9eL, 0xff5506a9L, 0xfa1a102cL, 0xfbd87a1bL,\n    0xf99ec442L, 0xf85cae75L, 0xf300e948L, 0xf2c2837fL, 0xf0843d26L,\n    0xf1465711L, 0xf4094194L, 0xf5cb2ba3L, 0xf78d95faL, 0xf64fffcdL,\n    0xd9785d60L, 0xd8ba3757L, 0xdafc890eL, 0xdb3ee339L, 0xde71f5bcL,\n    0xdfb39f8bL, 0xddf521d2L, 0xdc374be5L, 0xd76b0cd8L, 0xd6a966efL,\n    0xd4efd8b6L, 0xd52db281L, 0xd062a404L, 0xd1a0ce33L, 0xd3e6706aL,\n    0xd2241a5dL, 0xc55efe10L, 0xc49c9427L, 0xc6da2a7eL, 0xc7184049L,\n    0xc25756ccL, 0xc3953cfbL, 0xc1d382a2L, 0xc011e895L, 0xcb4dafa8L,\n    0xca8fc59fL, 0xc8c97bc6L, 0xc90b11f1L, 0xcc440774L, 0xcd866d43L,\n    0xcfc0d31aL, 0xce02b92dL, 0x91af9640L, 0x906dfc77L, 0x922b422eL,\n    0x93e92819L, 0x96a63e9cL, 0x976454abL, 0x9522eaf2L, 0x94e080c5L,\n    0x9fbcc7f8L, 0x9e7eadcfL, 0x9c381396L, 0x9dfa79a1L, 0x98b56f24L,\n    0x99770513L, 0x9b31bb4aL, 0x9af3d17dL, 0x8d893530L, 0x8c4b5f07L,\n    0x8e0de15eL, 0x8fcf8b69L, 0x8a809decL, 0x8b42f7dbL, 0x89044982L,\n    0x88c623b5L, 0x839a6488L, 0x82580ebfL, 0x801eb0e6L, 0x81dcdad1L,\n    0x8493cc54L, 0x8551a663L, 0x8717183aL, 0x86d5720dL, 0xa9e2d0a0L,\n    0xa820ba97L, 0xaa6604ceL, 0xaba46ef9L, 0xaeeb787cL, 0xaf29124bL,\n    0xad6fac12L, 0xacadc625L, 0xa7f18118L, 0xa633eb2fL, 0xa4755576L,\n    0xa5b73f41L, 0xa0f829c4L, 0xa13a43f3L, 0xa37cfdaaL, 0xa2be979dL,\n    0xb5c473d0L, 0xb40619e7L, 0xb640a7beL, 0xb782cd89L, 0xb2cddb0cL,\n    0xb30fb13bL, 0xb1490f62L, 0xb08b6555L, 0xbbd72268L, 0xba15485fL,\n    0xb853f606L, 0xb9919c31L, 0xbcde8ab4L, 0xbd1ce083L, 0xbf5a5edaL,\n    0xbe9834edL\n   ,\n    0x00000000L, 0xb8bc6765L, 0xaa09c88bL, 0x12b5afeeL, 0x8f629757L,\n    0x37def032L, 0x256b5fdcL, 0x9dd738b9L, 0xc5b428efL, 0x7d084f8aL,\n    0x6fbde064L, 0xd7018701L, 0x4ad6bfb8L, 0xf26ad8ddL, 0xe0df7733L,\n    0x58631056L, 0x5019579fL, 0xe8a530faL, 0xfa109f14L, 0x42acf871L,\n    0xdf7bc0c8L, 0x67c7a7adL, 0x75720843L, 0xcdce6f26L, 0x95ad7f70L,\n    0x2d111815L, 0x3fa4b7fbL, 0x8718d09eL, 0x1acfe827L, 0xa2738f42L,\n    0xb0c620acL, 0x087a47c9L, 0xa032af3eL, 0x188ec85bL, 0x0a3b67b5L,\n    0xb28700d0L, 0x2f503869L, 0x97ec5f0cL, 0x8559f0e2L, 0x3de59787L,\n    0x658687d1L, 0xdd3ae0b4L, 0xcf8f4f5aL, 0x7733283fL, 0xeae41086L,\n    0x525877e3L, 0x40edd80dL, 0xf851bf68L, 0xf02bf8a1L, 0x48979fc4L,\n    0x5a22302aL, 0xe29e574fL, 0x7f496ff6L, 0xc7f50893L, 0xd540a77dL,\n    0x6dfcc018L, 0x359fd04eL, 0x8d23b72bL, 0x9f9618c5L, 0x272a7fa0L,\n    0xbafd4719L, 0x0241207cL, 0x10f48f92L, 0xa848e8f7L, 0x9b14583dL,\n    0x23a83f58L, 0x311d90b6L, 0x89a1f7d3L, 0x1476cf6aL, 0xaccaa80fL,\n    0xbe7f07e1L, 0x06c36084L, 0x5ea070d2L, 0xe61c17b7L, 0xf4a9b859L,\n    0x4c15df3cL, 0xd1c2e785L, 0x697e80e0L, 0x7bcb2f0eL, 0xc377486bL,\n    0xcb0d0fa2L, 0x73b168c7L, 0x6104c729L, 0xd9b8a04cL, 0x446f98f5L,\n    0xfcd3ff90L, 0xee66507eL, 0x56da371bL, 0x0eb9274dL, 0xb6054028L,\n    0xa4b0efc6L, 0x1c0c88a3L, 0x81dbb01aL, 0x3967d77fL, 0x2bd27891L,\n    0x936e1ff4L, 0x3b26f703L, 0x839a9066L, 0x912f3f88L, 0x299358edL,\n    0xb4446054L, 0x0cf80731L, 0x1e4da8dfL, 0xa6f1cfbaL, 0xfe92dfecL,\n    0x462eb889L, 0x549b1767L, 0xec277002L, 0x71f048bbL, 0xc94c2fdeL,\n    0xdbf98030L, 0x6345e755L, 0x6b3fa09cL, 0xd383c7f9L, 0xc1366817L,\n    0x798a0f72L, 0xe45d37cbL, 0x5ce150aeL, 0x4e54ff40L, 0xf6e89825L,\n    0xae8b8873L, 0x1637ef16L, 0x048240f8L, 0xbc3e279dL, 0x21e91f24L,\n    0x99557841L, 0x8be0d7afL, 0x335cb0caL, 0xed59b63bL, 0x55e5d15eL,\n    0x47507eb0L, 0xffec19d5L, 0x623b216cL, 0xda874609L, 0xc832e9e7L,\n    0x708e8e82L, 0x28ed9ed4L, 0x9051f9b1L, 0x82e4565fL, 0x3a58313aL,\n    0xa78f0983L, 0x1f336ee6L, 0x0d86c108L, 0xb53aa66dL, 0xbd40e1a4L,\n    0x05fc86c1L, 0x1749292fL, 0xaff54e4aL, 0x322276f3L, 0x8a9e1196L,\n    0x982bbe78L, 0x2097d91dL, 0x78f4c94bL, 0xc048ae2eL, 0xd2fd01c0L,\n    0x6a4166a5L, 0xf7965e1cL, 0x4f2a3979L, 0x5d9f9697L, 0xe523f1f2L,\n    0x4d6b1905L, 0xf5d77e60L, 0xe762d18eL, 0x5fdeb6ebL, 0xc2098e52L,\n    0x7ab5e937L, 0x680046d9L, 0xd0bc21bcL, 0x88df31eaL, 0x3063568fL,\n    0x22d6f961L, 0x9a6a9e04L, 0x07bda6bdL, 0xbf01c1d8L, 0xadb46e36L,\n    0x15080953L, 0x1d724e9aL, 0xa5ce29ffL, 0xb77b8611L, 0x0fc7e174L,\n    0x9210d9cdL, 0x2aacbea8L, 0x38191146L, 0x80a57623L, 0xd8c66675L,\n    0x607a0110L, 0x72cfaefeL, 0xca73c99bL, 0x57a4f122L, 0xef189647L,\n    0xfdad39a9L, 0x45115eccL, 0x764dee06L, 0xcef18963L, 0xdc44268dL,\n    0x64f841e8L, 0xf92f7951L, 0x41931e34L, 0x5326b1daL, 0xeb9ad6bfL,\n    0xb3f9c6e9L, 0x0b45a18cL, 0x19f00e62L, 0xa14c6907L, 0x3c9b51beL,\n    0x842736dbL, 0x96929935L, 0x2e2efe50L, 0x2654b999L, 0x9ee8defcL,\n    0x8c5d7112L, 0x34e11677L, 0xa9362eceL, 0x118a49abL, 0x033fe645L,\n    0xbb838120L, 0xe3e09176L, 0x5b5cf613L, 0x49e959fdL, 0xf1553e98L,\n    0x6c820621L, 0xd43e6144L, 0xc68bceaaL, 0x7e37a9cfL, 0xd67f4138L,\n    0x6ec3265dL, 0x7c7689b3L, 0xc4caeed6L, 0x591dd66fL, 0xe1a1b10aL,\n    0xf3141ee4L, 0x4ba87981L, 0x13cb69d7L, 0xab770eb2L, 0xb9c2a15cL,\n    0x017ec639L, 0x9ca9fe80L, 0x241599e5L, 0x36a0360bL, 0x8e1c516eL,\n    0x866616a7L, 0x3eda71c2L, 0x2c6fde2cL, 0x94d3b949L, 0x090481f0L,\n    0xb1b8e695L, 0xa30d497bL, 0x1bb12e1eL, 0x43d23e48L, 0xfb6e592dL,\n    0xe9dbf6c3L, 0x516791a6L, 0xccb0a91fL, 0x740cce7aL, 0x66b96194L,\n    0xde0506f1L\n#  endif /* IZ_CRCOPTIM_UNFOLDTBL */\n# endif /* ? IZ_CRC_BE_OPTIMIZ */\n};\n#endif /* ?DYNAMIC_CRC_TABLE */\n\n/* use \"OF((void))\" here to work around a Borland TC++ 1.0 problem */\n#ifdef USE_ZLIB\nZCONST uLongf *get_crc_table OF((void))\n#else\nZCONST ulg near *get_crc_table OF((void))\n#endif\n{\n#ifdef DYNAMIC_CRC_TABLE\n  if (CRC_TABLE_IS_EMPTY)\n    make_crc_table();\n#endif\n#ifdef USE_ZLIB\n  return (ZCONST uLongf *)crc_table;\n#else\n  return crc_table;\n#endif\n}\n\n#ifdef DYNALLOC_CRCTAB\nvoid free_crc_table()\n{\n  if (!CRC_TABLE_IS_EMPTY)\n  {\n    nearfree((ulg near *)crc_table);\n    MARK_CRCTAB_EMPTY;\n  }\n}\n#endif\n\n#ifndef USE_ZLIB\n#ifndef CRC_TABLE_ONLY\n#ifndef ASM_CRC\n\n#define DO1(crc, buf)  crc = CRC32(crc, *buf++, crc_32_tab)\n#define DO2(crc, buf)  DO1(crc, buf); DO1(crc, buf)\n#define DO4(crc, buf)  DO2(crc, buf); DO2(crc, buf)\n#define DO8(crc, buf)  DO4(crc, buf); DO4(crc, buf)\n\n#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ))\n\n# ifdef IZ_CRCOPTIM_UNFOLDTBL\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n        c = crc_32_tab[c & 0xff] ^ crc_32_tab[256+((c>>8) & 0xff)] ^ \\\n            crc_32_tab[2*256+((c>>16) & 0xff)] ^ crc_32_tab[3*256+(c>>24)]\n#  else /* !IZ_CRC_BE_OPTIMIZ */\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n        c = crc_32_tab[3*256+(c & 0xff)] ^ crc_32_tab[2*256+((c>>8) & 0xff)] \\\n           ^ crc_32_tab[256+((c>>16) & 0xff)] ^ crc_32_tab[c>>24]\n#  endif /* ?IZ_CRC_BE_OPTIMIZ */\n# else /* !IZ_CRCOPTIM_UNFOLDTBL */\n#    define DO_OPT4(c, buf4)  c ^= *(buf4)++; \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab); \\\n       c = CRC32UPD(c, crc_32_tab)\n# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n\n# define DO_OPT16(crc, buf4) DO_OPT4(crc, buf4); DO_OPT4(crc, buf4); \\\n                             DO_OPT4(crc, buf4); DO_OPT4(crc, buf4);\n\n#endif /* (IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n\n\n/* ========================================================================= */\nulg crc32(crc, buf, len)\n    ulg crc;                    /* crc shift register */\n    register ZCONST uch *buf;   /* pointer to bytes to pump through */\n    extent len;                 /* number of bytes in buf[] */\n/* Run a set of bytes through the crc shift register.  If buf is a NULL\n   pointer, then initialize the crc shift register contents instead.\n   Return the current crc in either case. */\n{\n  register z_uint4 c;\n  register ZCONST ulg near *crc_32_tab;\n\n  if (buf == NULL) return 0L;\n\n  crc_32_tab = get_crc_table();\n\n  c = (REV_BE((z_uint4)crc) ^ 0xffffffffL);\n\n#if (defined(IZ_CRC_BE_OPTIMIZ) || defined(IZ_CRC_LE_OPTIMIZ))\n  /* Align buf pointer to next DWORD boundary. */\n  while (len && ((ptrdiff_t)buf & 3)) {\n    DO1(c, buf);\n    len--;\n  }\n  {\n    ZCONST z_uint4 *buf4 = (ZCONST z_uint4 *)buf;\n    while (len >= 16) {\n      DO_OPT16(c, buf4);\n      len -= 16;\n    }\n    while (len >= 4) {\n      DO_OPT4(c, buf4);\n      len -= 4;\n    }\n    buf = (ZCONST uch *)buf4;\n  }\n#else /* !(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n#ifndef NO_UNROLLED_LOOPS\n  while (len >= 8) {\n    DO8(c, buf);\n    len -= 8;\n  }\n#endif /* !NO_UNROLLED_LOOPS */\n#endif /* ?(IZ_CRC_BE_OPTIMIZ || IZ_CRC_LE_OPTIMIZ) */\n  if (len) do {\n    DO1(c, buf);\n  } while (--len);\n\n  return REV_BE(c) ^ 0xffffffffL;   /* (instead of ~c for 64-bit machines) */\n}\n#endif /* !ASM_CRC */\n#endif /* !CRC_TABLE_ONLY */\n#endif /* !USE_ZLIB */\n#endif /* !USE_ZLIB || USE_OWN_CRCTAB */\n"
  },
  {
    "path": "deps/infozip/zip30/crc32.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc32.h -- compute the CRC-32 of a data stream\n * Copyright (C) 1995 Mark Adler\n * For conditions of distribution and use, see copyright notice in zlib.h\n */\n\n#ifndef __crc32_h\n#define __crc32_h       /* identifies this source module */\n\n/* This header should be read AFTER zip.h resp. unzip.h\n * (the latter with UNZIP_INTERNAL defined...).\n */\n\n#ifndef OF\n#  define OF(a) a\n#endif\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#ifdef DYNALLOC_CRCTAB\n   void     free_crc_table  OF((void));\n#endif\n#ifndef USE_ZLIB\n   ZCONST ulg near *get_crc_table  OF((void));\n#endif\n#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))\n#  ifdef IZ_CRC_BE_OPTIMIZ\n#    undef IZ_CRC_BE_OPTIMIZ\n#  endif\n#else /* !(USE_ZLIB || CRC_TABLE_ONLY) */\n   ulg      crc32           OF((ulg crc, ZCONST uch *buf, extent len));\n#endif /* ?(USE_ZLIB || CRC_TABLE_ONLY) */\n\n#ifndef CRC_32_TAB\n#  define CRC_32_TAB     crc_32_tab\n#endif\n\n#ifdef CRC32\n#  undef CRC32\n#endif\n#ifdef IZ_CRC_BE_OPTIMIZ\n#  define CRC32UPD(c, crctab) (crctab[((c) >> 24)] ^ ((c) << 8))\n#  define CRC32(c, b, crctab) (crctab[(((int)(c) >> 24) ^ (b))] ^ ((c) << 8))\n#  define REV_BE(w) (((w)>>24)+(((w)>>8)&0xff00)+ \\\n                    (((w)&0xff00)<<8)+(((w)&0xff)<<24))\n#else\n#  define CRC32UPD(c, crctab) (crctab[((int)(c)) & 0xff] ^ ((c) >> 8))\n#  define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))\n#  define REV_BE(w) w\n#endif\n\n#endif /* !__crc32_h */\n"
  },
  {
    "path": "deps/infozip/zip30/crc_i386.S",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * crc_i386.S, optimized CRC calculation function for Zip and UnZip,\n * created by Paul Kienitz and Christian Spieler.  Last revised 07 Jan 2007.\n *\n * GRR 961110:  incorporated Scott Field optimizations from win32/crc_i386.asm\n *              => overall 6% speedup in \"unzip -tq\" on 9MB zipfile (486-66)\n *\n * SPC 970402:  revised for Rodney Brown's optimizations (32-bit-wide\n *              aligned reads for most of the data from buffer), can be\n *              disabled by defining the macro NO_32_BIT_LOADS\n *\n * SPC 971012:  added Rodney Brown's additional tweaks for 32-bit-optimized\n *              CPUs (like the Pentium Pro, Pentium II, and probably some\n *              Pentium clones). This optimization is controlled by the\n *              preprocessor switch \"__686\" and is disabled by default.\n *              (This default is based on the assumption that most users\n *              do not yet work on a Pentium Pro or Pentium II machine ...)\n *\n * COS 050116:  Enabled the 686 build by default, because there are hardly any\n *              pre-686 CPUs in serious use nowadays. (See SPC 970402 above.)\n *\n * SPC 060103:  Updated code to incorporate newer optimizations found in zlib.\n *\n * SPC 070107:  Added conditional switch to deactivate crc32() compilation.\n *\n * FLAT memory model assumed.  Calling interface:\n *   - args are pushed onto the stack from right to left,\n *   - return value is given in the EAX register,\n *   - all other registers (with exception of EFLAGS) are preserved. (With\n *     GNU C 2.7.x, %edx and %ecx are `scratch' registers, but preserving\n *     them nevertheless adds only 4 single byte instructions.)\n *\n * This source generates the function\n * ulg crc32(ulg crc, ZCONST uch *buf, extent len).\n *\n * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n * This results in shorter code at the expense of reduced performance.\n */\n\n/* This file is NOT used in conjunction with zlib, or when only creation of\n * the basic CRC_32_Table (for other purpose) is requested.\n */\n#if !defined(USE_ZLIB) && !defined(CRC_TABLE_ONLY)\n\n/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix\n * external symbols with an underline character '_'.\n */\n#if defined(NO_UNDERLINE) || defined(__ELF__)\n#  define _crc32            crc32\n#  define _get_crc_table    get_crc_table\n#endif\n/* Use 16-byte alignment if your assembler supports it. Warning: gas\n * uses a log(x) parameter (.align 4 means 16-byte alignment). On SVR4\n * the parameter is a number of bytes.\n */\n#ifndef ALIGNMENT\n#  define ALIGNMENT .align 4,0x90\n#endif\n\n#if defined(i386) || defined(_i386) || defined(_I386) || defined(__i386)\n\n/* This version is for 386 Unix, OS/2, MSDOS in 32 bit mode (gcc & gas).\n * Warning: it uses the AT&T syntax: mov source,dest\n * This file is only optional. If you want to use the C version,\n * remove -DASM_CRC from CFLAGS in Makefile and set OBJA to an empty string.\n */\n\n                .file   \"crc_i386.S\"\n\n#if !defined(PRE_686) && !defined(__686)\n   /* Optimize for Pentium Pro and compatible CPUs by default. */\n#  define __686\n#endif\n\n#if defined(NO_STD_STACKFRAME) && defined(USE_STD_STACKFRAME)\n#  undef USE_STACKFRAME\n#else\n   /* The default is to use standard stack frame entry, because it\n    * results in smaller code!\n    */\n#  ifndef USE_STD_STACKFRAME\n#    define USE_STD_STACKFRAME\n#  endif\n#endif\n\n#ifdef USE_STD_STACKFRAME\n#  define _STD_ENTRY    pushl   %ebp ; movl   %esp,%ebp\n#  define arg1  8(%ebp)\n#  define arg2  12(%ebp)\n#  define arg3  16(%ebp)\n#  define _STD_LEAVE    popl    %ebp\n#else /* !USE_STD_STACKFRAME */\n#  define _STD_ENTRY\n#  define arg1  24(%esp)\n#  define arg2  28(%esp)\n#  define arg3  32(%esp)\n#  define _STD_LEAVE\n#endif /* ?USE_STD_STACKFRAME */\n\n/*\n * These two (three) macros make up the loop body of the CRC32 cruncher.\n * registers modified:\n *   eax  : crc value \"c\"\n *   esi  : pointer to next data byte (or lword) \"buf++\"\n * registers read:\n *   edi  : pointer to base of crc_table array\n * scratch registers:\n *   ebx  : index into crc_table array\n *          (requires upper three bytes = 0 when __686 is undefined)\n */\n#ifndef __686   /* optimize for 386, 486, Pentium */\n#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\\\n                movb    %al, %bl                ;/* tmp = c & 0xFF  */\\\n                shrl    $8, %eax                ;/* c = (c >> 8)    */\\\n                xorl    (%edi, %ebx, 4), %eax   ;/* c ^= table[tmp] */\n#else   /* __686 : optimize for Pentium Pro and compatible CPUs */\n#define Do_CRC          /* c = (c >> 8) ^ table[c & 0xFF] */\\\n                movzbl  %al, %ebx               ;/* tmp = c & 0xFF  */\\\n                shrl    $8, %eax                ;/* c = (c >> 8)    */\\\n                xorl    (%edi, %ebx, 4), %eax   ;/* c ^=table[tmp]  */\n#endif  /* ?__686 */\n\n#define Do_CRC_byte             /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\\\n                xorb    (%esi), %al     ;/* c ^= *buf  */\\\n                incl    %esi            ;/* buf++      */\\\n                Do_CRC\n\n#define Do_CRC_byteof(ofs)      /* c = (c >> 8) ^ table[(c^*buf++)&0xFF] */\\\n                xorb    ofs(%esi), %al  ;/* c ^= *buf  */\\\n                incl    %esi            ;/* buf++      */\\\n                Do_CRC\n\n#ifndef  NO_32_BIT_LOADS\n# ifdef IZ_CRCOPTIM_UNFOLDTBL\n   /* the edx register is needed in crc calculation */\n#  define SavLen arg3\n#  define UpdCRC_lword \\\n                movzbl  %al, %ebx               ; \\\n                movl    3072(%edi,%ebx,4), %edx ; \\\n                movzbl  %ah, %ebx               ; \\\n                shrl    $16, %eax               ; \\\n                xor     2048(%edi,%ebx,4), %edx ; \\\n                movzbl  %al, %ebx               ; \\\n                shrl    $8,%eax                 ; \\\n                xorl    1024(%edi,%ebx,4), %edx ; \\\n                movl    (%edi,%eax,4), %eax     ; \\\n                xorl    %edx,%eax               ;\n#  define UpdCRC_lword_sh(dwPtrIncr) \\\n                movzbl  %al, %ebx               ; \\\n                movl    3072(%edi,%ebx,4), %edx ; \\\n                movzbl  %ah, %ebx               ; \\\n                shrl    $16, %eax               ; \\\n                xor     2048(%edi,%ebx,4), %edx ; \\\n                movzbl  %al, %ebx               ; \\\n                addl    $4*(dwPtrIncr), %esi    ;/* ((ulg *)buf)+=dwPtrIncr */\\\n                shrl    $8,%eax                 ; \\\n                xorl    1024(%edi,%ebx,4), %edx ; \\\n                movl    (%edi,%eax,4),%eax      ; \\\n                xorl    %edx,%eax               ;\n# else /* !IZ_CRCOPTIM_UNFOLDTBL */\n   /* the edx register is not needed anywhere else */\n#  define SavLen %edx\n#  define UpdCRC_lword \\\n                Do_CRC \\\n                Do_CRC \\\n                Do_CRC \\\n                Do_CRC\n#  define UpdCRC_lword_sh(dwPtrIncr) \\\n                Do_CRC \\\n                Do_CRC \\\n                addl    $4*(dwPtrIncr), %esi    ;/* ((ulg *)buf)++   */\\\n                Do_CRC \\\n                Do_CRC\n# endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n#define Do_CRC_lword \\\n                xorl    (%esi), %eax           ;/* c ^= *(ulg *)buf */\\\n                UpdCRC_lword_sh(1)              /* ... ((ulg *)buf)++ */\n#define Do_CRC_4lword \\\n                xorl    (%esi), %eax           ;/* c ^= *(ulg *)buf */\\\n                UpdCRC_lword \\\n                xorl    4(%esi), %eax          ;/* c ^= *((ulg *)buf+1) */\\\n                UpdCRC_lword \\\n                xorl    8(%esi), %eax          ;/* c ^= *((ulg *)buf+2) */\\\n                UpdCRC_lword \\\n                xorl    12(%esi), %eax         ;/* c ^= *((ulg *)buf]+3 */\\\n                UpdCRC_lword_sh(4)              /* ... ((ulg *)buf)+=4 */\n#endif  /* !NO_32_BIT_LOADS */\n\n\n                .text\n\n                .globl  _crc32\n\n_crc32:                         /* ulg crc32(ulg crc, uch *buf, extent len) */\n                _STD_ENTRY\n                pushl   %edi\n                pushl   %esi\n                pushl   %ebx\n                pushl   %edx\n                pushl   %ecx\n\n                movl    arg2, %esi           /* 2nd arg: uch *buf            */\n                subl    %eax, %eax           /* > if (!buf)                  */\n                testl   %esi, %esi           /* >   return 0;                */\n                jz      .L_fine              /* > else {                     */\n                call    _get_crc_table\n                movl    %eax, %edi\n                movl    arg1, %eax           /* 1st arg: ulg crc             */\n#ifndef __686\n                subl    %ebx, %ebx           /* ebx=0; bl usable as dword    */\n#endif\n                movl    arg3, %ecx           /* 3rd arg: extent len          */\n                notl    %eax                 /* >   c = ~crc;                */\n\n                testl   %ecx, %ecx\n#ifndef  NO_UNROLLED_LOOPS\n                jz      .L_bail\n#  ifndef  NO_32_BIT_LOADS\n                /* Assert now have positive length */\n.L_align_loop:\n                testl   $3, %esi        /* Align buf on lword boundary */\n                jz      .L_aligned_now\n                Do_CRC_byte\n                decl    %ecx\n                jnz     .L_align_loop\n.L_aligned_now:\n#  endif  /* !NO_32_BIT_LOADS */\n                movl    %ecx, SavLen         /* save current value of len */\n                shrl    $4, %ecx             /* ecx = len / 16   */\n                jz      .L_No_Sixteens\n/*  align loop head at start of 486 internal cache line !! */\n                ALIGNMENT\n.L_Next_Sixteen:\n#  ifndef NO_32_BIT_LOADS\n                 Do_CRC_4lword\n#  else   /* NO_32_BIT_LOADS */\n                 Do_CRC_byteof(0)\n                 Do_CRC_byteof(1)\n                 Do_CRC_byteof(2)\n                 Do_CRC_byteof(3)\n                 Do_CRC_byteof(4)\n                 Do_CRC_byteof(5)\n                 Do_CRC_byteof(6)\n                 Do_CRC_byteof(7)\n                 Do_CRC_byteof(8)\n                 Do_CRC_byteof(9)\n                 Do_CRC_byteof(10)\n                 Do_CRC_byteof(11)\n                 Do_CRC_byteof(12)\n                 Do_CRC_byteof(13)\n                 Do_CRC_byteof(14)\n                 Do_CRC_byteof(15)\n                 addl    $16,%esi        ;/* buf += 16 */\n#  endif  /* ?NO_32_BIT_LOADS */\n                decl    %ecx\n                jnz     .L_Next_Sixteen\n\n.L_No_Sixteens:\n                movl    SavLen, %ecx\n                andl    $15, %ecx         /* ecx = len % 16   */\n# ifndef NO_32_BIT_LOADS\n                shrl    $2,%ecx           /* ecx = len / 4    */\n                jz      .L_No_Fours\n.L_Next_Four:\n                Do_CRC_lword\n                decl    %ecx\n                jnz     .L_Next_Four\n.L_No_Fours:\n                movl    SavLen,%ecx\n                andl    $3,%ecx          /* ecx = len % 4 */\n# endif /* !NO_32_BIT_LOADS */\n#endif /* !NO_UNROLLED_LOOPS */\n                jz      .L_bail          /* > if (len)                       */\n/* align loop head at start of 486 internal cache line !! */\n                ALIGNMENT\n.L_loupe:                                /* >   do {                         */\n                 Do_CRC_byte             /*       c = CRC32(c,*buf++,crctab);*/\n                decl    %ecx             /* >   } while (--len);             */\n                jnz     .L_loupe\n\n.L_bail:                                 /* > }                              */\n                notl    %eax             /* > return ~c;                     */\n.L_fine:\n                popl    %ecx\n                popl    %edx\n                popl    %ebx\n                popl    %esi\n                popl    %edi\n                _STD_LEAVE\n                ret\n\n#else\n error: this asm version is for 386 only\n#endif /* i386 || _i386 || _I386 || __i386 */\n\n#endif /* !USE_ZLIB && !CRC_TABLE_ONLY */\n"
  },
  {
    "path": "deps/infozip/zip30/crypt.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n  crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]\n\n  The main encryption/decryption source code for Info-Zip software was\n  originally written in Europe.  To the best of our knowledge, it can\n  be freely distributed in both source and object forms from any country,\n  including the USA under License Exception TSU of the U.S. Export\n  Administration Regulations (section 740.13(e)) of 6 June 2002.\n\n  NOTE on copyright history:\n  Previous versions of this source package (up to version 2.8) were\n  not copyrighted and put in the public domain.  If you cannot comply\n  with the Info-Zip LICENSE, you may want to look for one of those\n  public domain versions.\n */\n\n/*\n  This encryption code is a direct transcription of the algorithm from\n  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\n  file (appnote.txt) is distributed with the PKZIP program (even in the\n  version without encryption capabilities).\n */\n\n#define ZCRYPT_INTERNAL\n#include \"zip.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n\n#if CRYPT\n\n#ifndef FALSE\n#  define FALSE 0\n#endif\n\n#ifdef ZIP\n   /* For the encoding task used in Zip (and ZipCloak), we want to initialize\n      the crypt algorithm with some reasonably unpredictable bytes, see\n      the crypthead() function. The standard rand() library function is\n      used to supply these `random' bytes, which in turn is initialized by\n      a srand() call. The srand() function takes an \"unsigned\" (at least 16bit)\n      seed value as argument to determine the starting point of the rand()\n      pseudo-random number generator.\n      This seed number is constructed as \"Seed = Seed1 .XOR. Seed2\" with\n      Seed1 supplied by the current time (= \"(unsigned)time()\") and Seed2\n      as some (hopefully) nondeterministic bitmask. On many (most) systems,\n      we use some \"process specific\" number, as the PID or something similar,\n      but when nothing unpredictable is available, a fixed number may be\n      sufficient.\n      NOTE:\n      1.) This implementation requires the availability of the following\n          standard UNIX C runtime library functions: time(), rand(), srand().\n          On systems where some of them are missing, the environment that\n          incorporates the crypt routines must supply suitable replacement\n          functions.\n      2.) It is a very bad idea to use a second call to time() to set the\n          \"Seed2\" number! In this case, both \"Seed1\" and \"Seed2\" would be\n          (almost) identical, resulting in a (mostly) \"zero\" constant seed\n          number passed to srand().\n\n      The implementation environment defined in the \"zip.h\" header should\n      supply a reasonable definition for ZCR_SEED2 (an unsigned number; for\n      most implementations of rand() and srand(), only the lower 16 bits are\n      significant!). An example that works on many systems would be\n           \"#define ZCR_SEED2  (unsigned)getpid()\".\n      The default definition for ZCR_SEED2 supplied below should be regarded\n      as a fallback to allow successful compilation in \"beta state\"\n      environments.\n    */\n#  include <time.h>     /* time() function supplies first part of crypt seed */\n   /* \"last resort\" source for second part of crypt seed pattern */\n#  ifndef ZCR_SEED2\n#    define ZCR_SEED2 (unsigned)3141592654L     /* use PI as default pattern */\n#  endif\n#  ifdef GLOBAL         /* used in Amiga system headers, maybe others too */\n#    undef GLOBAL\n#  endif\n#  define GLOBAL(g) g\n#else /* !ZIP */\n#  define GLOBAL(g) G.g\n#endif /* ?ZIP */\n\n\n#ifdef UNZIP\n   /* char *key = (char *)NULL; moved to globals.h */\n#  ifndef FUNZIP\n     local int testp OF((__GPRO__ ZCONST uch *h));\n     local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key));\n#  endif\n#else /* def UNZIP */           /* moved to globals.h for UnZip */\n   local z_uint4 keys[3];       /* keys defining the pseudo-random sequence */\n#endif /* def UNZIP [else] */\n\n#ifndef Trace\n#  ifdef CRYPT_DEBUG\n#    define Trace(x) fprintf x\n#  else\n#    define Trace(x)\n#  endif\n#endif\n\n#include \"crc32.h\"\n\n#ifdef IZ_CRC_BE_OPTIMIZ\n   local z_uint4 near crycrctab[256];\n   local z_uint4 near *cry_crctb_p = NULL;\n   local z_uint4 near *crytab_init OF((__GPRO));\n#  define CRY_CRC_TAB  cry_crctb_p\n#  undef CRC32\n#  define CRC32(c, b, crctab) (crctab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))\n#else\n#  define CRY_CRC_TAB  CRC_32_TAB\n#endif /* ?IZ_CRC_BE_OPTIMIZ */\n\n/***********************************************************************\n * Return the next byte in the pseudo-random sequence\n */\nint decrypt_byte(__G)\n    __GDEF\n{\n    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an\n                     * unpredictable manner on 16-bit systems; not a problem\n                     * with any known compiler so far, though */\n\n    temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2;\n    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);\n}\n\n/***********************************************************************\n * Update the encryption keys with the next byte of plain text\n */\nint update_keys(__G__ c)\n    __GDEF\n    int c;                      /* byte of plain text */\n{\n    GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c, CRY_CRC_TAB);\n    GLOBAL(keys[1]) = (GLOBAL(keys[1])\n                       + (GLOBAL(keys[0]) & 0xff))\n                      * 134775813L + 1;\n    {\n      register int keyshift = (int)(GLOBAL(keys[1]) >> 24);\n      GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift, CRY_CRC_TAB);\n    }\n    return c;\n}\n\n\n/***********************************************************************\n * Initialize the encryption keys and the random header according to\n * the given password.\n */\nvoid init_keys(__G__ passwd)\n    __GDEF\n    ZCONST char *passwd;        /* password string with which to modify keys */\n{\n#ifdef IZ_CRC_BE_OPTIMIZ\n    if (cry_crctb_p == NULL) {\n        cry_crctb_p = crytab_init(__G);\n    }\n#endif\n    GLOBAL(keys[0]) = 305419896L;\n    GLOBAL(keys[1]) = 591751049L;\n    GLOBAL(keys[2]) = 878082192L;\n    while (*passwd != '\\0') {\n        update_keys(__G__ (int)*passwd);\n        passwd++;\n    }\n}\n\n\n/***********************************************************************\n * Initialize the local copy of the table of precomputed crc32 values.\n * Whereas the public crc32-table is optimized for crc32 calculations\n * on arrays of bytes, the crypt code needs the crc32 values in an\n * byte-order-independent form as 32-bit unsigned numbers. On systems\n * with Big-Endian byte order using the optimized crc32 code, this\n * requires inverting the byte-order of the values in the\n * crypt-crc32-table.\n */\n#ifdef IZ_CRC_BE_OPTIMIZ\nlocal z_uint4 near *crytab_init(__G)\n    __GDEF\n{\n    int i;\n\n    for (i = 0; i < 256; i++) {\n        crycrctab[i] = REV_BE(CRC_32_TAB[i]);\n    }\n    return crycrctab;\n}\n#endif\n\n\n#ifdef ZIP\n\n/***********************************************************************\n * Write encryption header to file zfile using the password passwd\n * and the cyclic redundancy check crc.\n */\nvoid crypthead(passwd, crc)\n    ZCONST char *passwd;         /* password string */\n    ulg crc;                     /* crc of file being encrypted */\n{\n    int n;                       /* index in random header */\n    int t;                       /* temporary */\n    int c;                       /* random byte */\n    uch header[RAND_HEAD_LEN];   /* random header */\n    static unsigned calls = 0;   /* ensure different random header each time */\n\n    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the\n     * output of rand() to get less predictability, since rand() is\n     * often poorly implemented.\n     */\n    if (++calls == 1) {\n        srand((unsigned)time(NULL) ^ ZCR_SEED2);\n    }\n    init_keys(passwd);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++) {\n        c = (rand() >> 7) & 0xff;\n        header[n] = (uch)zencode(c, t);\n    }\n    /* Encrypt random header (last two bytes is high word of crc) */\n    init_keys(passwd);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++) {\n        header[n] = (uch)zencode(header[n], t);\n    }\n    header[RAND_HEAD_LEN-2] = (uch)zencode((int)(crc >> 16) & 0xff, t);\n    header[RAND_HEAD_LEN-1] = (uch)zencode((int)(crc >> 24) & 0xff, t);\n    bfwrite(header, 1, RAND_HEAD_LEN, BFWRITE_DATA);\n}\n\n\n#ifdef UTIL\n\n/***********************************************************************\n * Encrypt the zip entry described by z from file in_file to file y\n * using the password passwd.  Return an error code in the ZE_ class.\n */\nint zipcloak(z, passwd)\n    struct zlist far *z;    /* zip entry to encrypt */\n    ZCONST char *passwd;    /* password string */\n{\n    int c;                  /* input byte */\n    int res;                /* result code */\n    zoff_t n;               /* holds offset and counts size */\n    int t;                  /* temporary */\n    struct zlist far *localz; /* local header */\n    uch buf[1024];          /* write buffer */\n    int b;                  /* bytes in buffer */\n\n    /* Set encrypted bit, clear extended local header bit and write local\n       header to output file */\n    if ((n = (zoff_t)zftello(y)) == (zoff_t)-1L) return ZE_TEMP;\n\n    /* assume this archive is one disk and the file is open */\n\n    /* read the local header */\n    res = readlocal(&localz, z);\n\n    /* update disk and offset */\n    z->dsk = 0;\n    z->off = n;\n\n    /* Set encryption and unset any extended local header */\n    z->flg |= 1,  z->flg &= ~8;\n    localz->lflg |= 1, localz->lflg &= ~8;\n\n    /* Add size of encryption header */\n    localz->siz += RAND_HEAD_LEN;\n    z->siz = localz->siz;\n\n    /* Put the local header */\n    if ((res = putlocal(localz, PUTLOCAL_WRITE)) != ZE_OK) return res;\n\n    /* Initialize keys with password and write random header */\n    crypthead(passwd, localz->crc);\n\n    /* Encrypt data */\n    b = 0;\n    for (n = z->siz - RAND_HEAD_LEN; n; n--) {\n      if ((c = getc(in_file)) == EOF) {\n          return ferror(in_file) ? ZE_READ : ZE_EOF;\n      }\n      buf[b] = (uch)zencode(c, t);\n      b++;\n      if (b >= 1024) {\n        /* write the buffer */\n        bfwrite(buf, 1, b, BFWRITE_DATA);\n        b = 0;\n      }\n    }\n    if (b) {\n      /* write the buffer */\n      bfwrite(buf, 1, b, BFWRITE_DATA);\n      b = 0;\n    }\n\n    /* Since we seek to the start of each local header can skip\n       reading any extended local header */\n    /*\n    if ((flag & 8) != 0 && zfseeko(in_file, 16L, SEEK_CUR)) {\n        return ferror(in_file) ? ZE_READ : ZE_EOF;\n    }\n    if (fflush(y) == EOF) return ZE_TEMP;\n    */\n\n    /* Update number of bytes written to output file */\n    tempzn += (4 + LOCHEAD) + localz->nam + localz->ext + localz->siz;\n\n    /* Free local header */\n    if (localz->ext) free(localz->extra);\n    if (localz->nam) free(localz->iname);\n    if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n    if (localz->uname) free(localz->uname);\n#endif\n    free(localz);\n\n    return ZE_OK;\n}\n\n/***********************************************************************\n * Decrypt the zip entry described by z from file in_file to file y\n * using the password passwd.  Return an error code in the ZE_ class.\n */\nint zipbare(z, passwd)\n    struct zlist far *z;  /* zip entry to encrypt */\n    ZCONST char *passwd;  /* password string */\n{\n#ifdef ZIP10\n    int c0                /* byte preceding the last input byte */\n#endif\n    int c1;               /* last input byte */\n    /* all file offset and size now zoff_t - 8/28/04 EG */\n    zoff_t size;          /* size of input data */\n    struct zlist far *localz; /* local header */\n    uch buf[1024];        /* write buffer */\n    int b;                /* bytes in buffer */\n    zoff_t n;\n    int r;                /* size of encryption header */\n    int res;              /* return code */\n\n    /* Save position */\n    if ((n = (zoff_t)zftello(y)) == (zoff_t)-1L) return ZE_TEMP;\n\n    /* Read local header */\n    res = readlocal(&localz, z);\n\n    /* Update disk and offset */\n    z->dsk = 0;\n    z->off = n;\n\n    /* Initialize keys with password */\n    init_keys(passwd);\n\n    /* Decrypt encryption header, save last two bytes */\n    c1 = 0;\n    for (r = RAND_HEAD_LEN; r; r--) {\n#ifdef ZIP10\n        c0 = c1;\n#endif\n        if ((c1 = getc(in_file)) == EOF) {\n            return ferror(in_file) ? ZE_READ : ZE_EOF;\n        }\n        Trace((stdout, \" (%02x)\", c1));\n        zdecode(c1);\n        Trace((stdout, \" %02x\", c1));\n    }\n    Trace((stdout, \"\\n\"));\n\n    /* If last two bytes of header don't match crc (or file time in the\n     * case of an extended local header), back up and just copy. For\n     * pkzip 2.0, the check has been reduced to one byte only.\n     */\n#ifdef ZIP10\n    if ((ush)(c0 | (c1<<8)) !=\n        (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) {\n#else\n    if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) {\n#endif\n        if (zfseeko(in_file, n, SEEK_SET)) {\n            return ferror(in_file) ? ZE_READ : ZE_EOF;\n        }\n        if ((res = zipcopy(z)) != ZE_OK) {\n            ziperr(res, \"was copying an entry\");\n        }\n        return ZE_MISS;\n    }\n\n    z->siz -= RAND_HEAD_LEN;\n    localz->siz = z->siz;\n\n    localz->flg = z->flg &= ~9;\n    z->lflg = localz->lflg &= ~9;\n\n    if ((res = putlocal(localz, PUTLOCAL_WRITE)) != ZE_OK) return res;\n\n    /* Decrypt data */\n    b = 0;\n    for (size = z->siz; size; size--) {\n        if ((c1 = getc(in_file)) == EOF) {\n            return ferror(in_file) ? ZE_READ : ZE_EOF;\n        }\n        zdecode(c1);\n        buf[b] = c1;\n        b++;\n        if (b >= 1024) {\n          /* write the buffer */\n          bfwrite(buf, 1, b, BFWRITE_DATA);\n          b = 0;\n        }\n    }\n    if (b) {\n      /* write the buffer */\n      bfwrite(buf, 1, b, BFWRITE_DATA);\n      b = 0;\n    }\n    /* Since we seek to the start of each local header can skip\n         reading any extended local header */\n\n    /* Update number of bytes written to output file */\n    tempzn += (4 + LOCHEAD) + localz->nam + localz->ext + localz->siz;\n\n    /* Free local header */\n    if (localz->ext) free(localz->extra);\n    if (localz->nam) free(localz->iname);\n    if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n    if (localz->uname) free(localz->uname);\n#endif\n    free(localz);\n\n    return ZE_OK;\n}\n\n\n#else /* !UTIL */\n\n/***********************************************************************\n * If requested, encrypt the data in buf, and in any case call fwrite()\n * with the arguments to zfwrite().  Return what fwrite() returns.\n *\n * now write to global y\n *\n * A bug has been found when encrypting large files that don't\n * compress.  See trees.c for the details and the fix.\n */\nunsigned zfwrite(buf, item_size, nb)\n    zvoid *buf;                 /* data buffer */\n    extent item_size;           /* size of each item in bytes */\n    extent nb;                  /* number of items */\n#if 0\n    FILE *f;                    /* file to write to */\n#endif\n{\n    int t;                      /* temporary */\n\n    if (key != (char *)NULL) {  /* key is the global password pointer */\n        ulg size;               /* buffer size */\n        char *p = (char *)buf;  /* steps through buffer */\n\n        /* Encrypt data in buffer */\n        for (size = item_size*(ulg)nb; size != 0; p++, size--) {\n            *p = (char)zencode(*p, t);\n        }\n    }\n    /* Write the buffer out */\n    return bfwrite(buf, item_size, nb, BFWRITE_DATA);\n}\n\n#endif /* ?UTIL */\n#endif /* ZIP */\n\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n\n/***********************************************************************\n * Get the password and set up keys for current zipfile member.\n * Return PK_ class error.\n */\nint decrypt(__G__ passwrd)\n    __GDEF\n    ZCONST char *passwrd;\n{\n    ush b;\n    int n, r;\n    uch h[RAND_HEAD_LEN];\n\n    Trace((stdout, \"\\n[incnt = %d]: \", GLOBAL(incnt)));\n\n    /* get header once (turn off \"encrypted\" flag temporarily so we don't\n     * try to decrypt the same data twice) */\n    GLOBAL(pInfo->encrypted) = FALSE;\n    defer_leftover_input(__G);\n    for (n = 0; n < RAND_HEAD_LEN; n++) {\n        b = NEXTBYTE;\n        h[n] = (uch)b;\n        Trace((stdout, \" (%02x)\", h[n]));\n    }\n    undefer_input(__G);\n    GLOBAL(pInfo->encrypted) = TRUE;\n\n    if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */\n        GLOBAL(newzip) = FALSE;\n        if (passwrd != (char *)NULL) { /* user gave password on command line */\n            if (!GLOBAL(key)) {\n                if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) ==\n                    (char *)NULL)\n                    return PK_MEM2;\n                strcpy(GLOBAL(key), passwrd);\n                GLOBAL(nopwd) = TRUE;  /* inhibit password prompting! */\n            }\n        } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */\n            free(GLOBAL(key));\n            GLOBAL(key) = (char *)NULL;\n        }\n    }\n\n    /* if have key already, test it; else allocate memory for it */\n    if (GLOBAL(key)) {\n        if (!testp(__G__ h))\n            return PK_COOL;   /* existing password OK (else prompt for new) */\n        else if (GLOBAL(nopwd))\n            return PK_WARN;   /* user indicated no more prompting */\n    } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)\n        return PK_MEM2;\n\n    /* try a few keys */\n    n = 0;\n    do {\n        r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1,\n                             GLOBAL(zipfn), GLOBAL(filename));\n        if (r == IZ_PW_ERROR) {         /* internal error in fetch of PW */\n            free (GLOBAL(key));\n            GLOBAL(key) = NULL;\n            return PK_MEM2;\n        }\n        if (r != IZ_PW_ENTERED) {       /* user replied \"skip\" or \"skip all\" */\n            *GLOBAL(key) = '\\0';        /*   We try the NIL password, ... */\n            n = 0;                      /*   and cancel fetch for this item. */\n        }\n        if (!testp(__G__ h))\n            return PK_COOL;\n        if (r == IZ_PW_CANCELALL)       /* User replied \"Skip all\" */\n            GLOBAL(nopwd) = TRUE;       /*   inhibit any further PW prompt! */\n    } while (n > 0);\n\n    return PK_WARN;\n\n} /* end function decrypt() */\n\n\n\n/***********************************************************************\n * Test the password.  Return -1 if bad, 0 if OK.\n */\nlocal int testp(__G__ h)\n    __GDEF\n    ZCONST uch *h;\n{\n    int r;\n    char *key_translated;\n\n    /* On systems with \"obscure\" native character coding (e.g., EBCDIC),\n     * the first test translates the password to the \"main standard\"\n     * character coding. */\n\n#ifdef STR_TO_CP1\n    /* allocate buffer for translated password */\n    if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)\n        return -1;\n    /* first try, test password translated \"standard\" charset */\n    r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key)));\n#else /* !STR_TO_CP1 */\n    /* first try, test password as supplied on the extractor's host */\n    r = testkey(__G__ h, GLOBAL(key));\n#endif /* ?STR_TO_CP1 */\n\n#ifdef STR_TO_CP2\n    if (r != 0) {\n#ifndef STR_TO_CP1\n        /* now prepare for second (and maybe third) test with translated pwd */\n        if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL)\n            return -1;\n#endif\n        /* second try, password translated to alternate (\"standard\") charset */\n        r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key)));\n#ifdef STR_TO_CP3\n        if (r != 0)\n            /* third try, password translated to another \"standard\" charset */\n            r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key)));\n#endif\n#ifndef STR_TO_CP1\n        free(key_translated);\n#endif\n    }\n#endif /* STR_TO_CP2 */\n\n#ifdef STR_TO_CP1\n    free(key_translated);\n    if (r != 0) {\n        /* last resort, test password as supplied on the extractor's host */\n        r = testkey(__G__ h, GLOBAL(key));\n    }\n#endif /* STR_TO_CP1 */\n\n    return r;\n\n} /* end function testp() */\n\n\nlocal int testkey(__G__ h, key)\n    __GDEF\n    ZCONST uch *h;      /* decrypted header */\n    ZCONST char *key;   /* decryption password to test */\n{\n    ush b;\n#ifdef ZIP10\n    ush c;\n#endif\n    int n;\n    uch *p;\n    uch hh[RAND_HEAD_LEN]; /* decrypted header */\n\n    /* set keys and save the encrypted header */\n    init_keys(__G__ key);\n    memcpy(hh, h, RAND_HEAD_LEN);\n\n    /* check password */\n    for (n = 0; n < RAND_HEAD_LEN; n++) {\n        zdecode(hh[n]);\n        Trace((stdout, \" %02x\", hh[n]));\n    }\n\n    /* use fzofft to format zoff_t as strings - 10/19/04 from SMS */\n    Trace((stdout,\n      \"\\n  lrec.crc= %08lx  crec.crc= %08lx  pInfo->ExtLocHdr= %s\\n\",\n      GLOBAL(lrec.crc32), GLOBAL(pInfo->crc),\n      GLOBAL(pInfo->ExtLocHdr) ? \"true\":\"false\"));\n    Trace((stdout, \"  incnt = %d  unzip offset into zipfile = %s\\n\",\n      GLOBAL(incnt),\n      fzofft(GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)),\n             NULL, NULL)));\n\n    /* same test as in zipbare(): */\n\n#ifdef ZIP10 /* check two bytes */\n    c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1];\n    Trace((stdout,\n      \"  (c | (b<<8)) = %04x  (crc >> 16) = %04x  lrec.time = %04x\\n\",\n      (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16),\n      ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff))));\n    if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ?\n                           ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) :\n                           (ush)(GLOBAL(lrec.crc32) >> 16)))\n        return -1;  /* bad */\n#else\n    b = hh[RAND_HEAD_LEN-1];\n    Trace((stdout, \"  b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\\n\",\n      b, (ush)(GLOBAL(lrec.crc32) >> 24),\n      ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff));\n    if (b != (GLOBAL(pInfo->ExtLocHdr) ?\n        ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff :\n        (ush)(GLOBAL(lrec.crc32) >> 24)))\n        return -1;  /* bad */\n#endif\n    /* password OK:  decrypt current buffer contents before leaving */\n    for (n = (zoff_t)GLOBAL(incnt) > GLOBAL(csize) ?\n             (int)GLOBAL(csize) : GLOBAL(incnt),\n         p = GLOBAL(inptr); n--; p++)\n        zdecode(*p);\n    return 0;       /* OK */\n\n} /* end function testkey() */\n\n#endif /* UNZIP && !FUNZIP */\n\n#else /* !CRYPT */\n\n/* something \"externally visible\" to shut up compiler/linker warnings */\nint zcr_dummy;\n\n#endif /* ?CRYPT */\n"
  },
  {
    "path": "deps/infozip/zip30/crypt.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n  crypt.h (full version) by Info-ZIP.   Last revised:  [see CR_VERSION_DATE]\n\n  The main encryption/decryption source code for Info-Zip software was\n  originally written in Europe.  To the best of our knowledge, it can\n  be freely distributed in both source and object forms from any country,\n  including the USA under License Exception TSU of the U.S. Export\n  Administration Regulations (section 740.13(e)) of 6 June 2002.\n\n  NOTE on copyright history:\n  Previous versions of this source package (up to version 2.8) were\n  not copyrighted and put in the public domain.  If you cannot comply\n  with the Info-Zip LICENSE, you may want to look for one of those\n  public domain versions.\n */\n\n#ifndef __crypt_h   /* don't include more than once */\n#define __crypt_h\n\n#ifdef CRYPT\n#  undef CRYPT\n#endif\n/*\n   Logic of selecting \"full crypt\" code:\n   a) default behaviour:\n      - dummy crypt code when compiling UnZipSFX stub, to minimize size\n      - full crypt code when used to compile Zip, UnZip and fUnZip\n   b) USE_CRYPT defined:\n      - always full crypt code\n   c) NO_CRYPT defined:\n      - never full crypt code\n   NO_CRYPT takes precedence over USE_CRYPT\n */\n#if defined(NO_CRYPT)\n#  define CRYPT  0  /* dummy version */\n#else\n#if defined(USE_CRYPT)\n#  define CRYPT  1  /* full version */\n#else\n#if !defined(SFX)\n#  define CRYPT  1  /* full version for zip and main unzip */\n#else\n#  define CRYPT  0  /* dummy version for unzip sfx */\n#endif\n#endif /* ?USE_CRYPT */\n#endif /* ?NO_CRYPT */\n\n#if CRYPT\n/* full version */\n\n#ifdef CR_BETA\n#  undef CR_BETA    /* this is not a beta release */\n#endif\n\n#define CR_MAJORVER        2\n#define CR_MINORVER        91\n#ifdef CR_BETA\n#  define CR_BETA_VER      \"c BETA\"\n#  define CR_VERSION_DATE  \"05 Jan 2007\"       /* last real code change */\n#else\n#  define CR_BETA_VER      \"\"\n#  define CR_VERSION_DATE  \"05 Jan 2007\"       /* last public release date */\n#  define CR_RELEASE\n#endif\n\n#ifndef __G         /* UnZip only, for now (DLL stuff) */\n#  define __G\n#  define __G__\n#  define __GDEF\n#  define __GPRO    void\n#  define __GPRO__\n#endif\n\n#if defined(MSDOS) || defined(OS2) || defined(WIN32)\n#  ifndef DOS_OS2_W32\n#    define DOS_OS2_W32\n#  endif\n#endif\n\n#if defined(DOS_OS2_W32) || defined(__human68k__)\n#  ifndef DOS_H68_OS2_W32\n#    define DOS_H68_OS2_W32\n#  endif\n#endif\n\n#if defined(VM_CMS) || defined(MVS)\n#  ifndef CMS_MVS\n#    define CMS_MVS\n#  endif\n#endif\n\n/* To allow combining of Zip and UnZip static libraries in a single binary,\n * the Zip and UnZip versions of the crypt core functions have to be named\n * differently.\n */\n#ifdef ZIP\n#  ifdef REALLY_SHORT_SYMS\n#    define decrypt_byte   zdcrby\n#  else\n#    define decrypt_byte   zp_decrypt_byte\n#  endif\n#  define  update_keys     zp_update_keys\n#  define  init_keys       zp_init_keys\n#else /* !ZIP */\n#  ifdef REALLY_SHORT_SYMS\n#    define decrypt_byte   dcrbyt\n#  endif\n#endif /* ?ZIP */\n\n#define IZ_PWLEN  80    /* input buffer size for reading encryption key */\n#ifndef PWLEN           /* for compatibility with previous zcrypt release... */\n#  define PWLEN IZ_PWLEN\n#endif\n#define RAND_HEAD_LEN  12       /* length of encryption random header */\n\n/* the crc_32_tab array has to be provided externally for the crypt calculus */\n\n/* encode byte c, using temp t.  Warning: c must not have side effects. */\n#define zencode(c,t)  (t=decrypt_byte(__G), update_keys(c), t^(c))\n\n/* decode byte c in place */\n#define zdecode(c)   update_keys(__G__ c ^= decrypt_byte(__G))\n\nint  decrypt_byte OF((__GPRO));\nint  update_keys OF((__GPRO__ int c));\nvoid init_keys OF((__GPRO__ ZCONST char *passwd));\n\n#ifdef ZIP\n   void crypthead OF((ZCONST char *, ulg));\n#  ifdef UTIL\n     int zipcloak OF((struct zlist far *, ZCONST char *));\n     int zipbare OF((struct zlist far *, ZCONST char *));\n#  else\n     unsigned zfwrite OF((zvoid *, extent, extent));\n     extern char *key;\n#  endif\n#endif /* ZIP */\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n   int  decrypt OF((__GPRO__ ZCONST char *passwrd));\n#endif\n\n#ifdef FUNZIP\n   extern int encrypted;\n#  ifdef NEXTBYTE\n#    undef NEXTBYTE\n#  endif\n#  define NEXTBYTE \\\n   (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in))\n#endif /* FUNZIP */\n\n#else /* !CRYPT */\n/* dummy version */\n\n#define zencode\n#define zdecode\n\n#define zfwrite(b,s,c) bfwrite(b,s,c,BFWRITE_DATA)\n\n#endif /* ?CRYPT */\n#endif /* !__crypt_h */\n"
  },
  {
    "path": "deps/infozip/zip30/deflate.c",
    "content": "/*\n  deflate.c - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  deflate.c by Jean-loup Gailly.\n *\n *  PURPOSE\n *\n *      Identify new text as repetitions of old text within a fixed-\n *      length sliding window trailing behind the new text.\n *\n *  DISCUSSION\n *\n *      The \"deflation\" process depends on being able to identify portions\n *      of the input text which are identical to earlier input (within a\n *      sliding window trailing behind the input currently being processed).\n *\n *      The most straightforward technique turns out to be the fastest for\n *      most input files: try all possible matches and select the longest.\n *      The key feature of this algorithm is that insertions into the string\n *      dictionary are very simple and thus fast, and deletions are avoided\n *      completely. Insertions are performed at each input character, whereas\n *      string matches are performed only when the previous match ends. So it\n *      is preferable to spend more time in matches to allow very fast string\n *      insertions and avoid deletions. The matching algorithm for small\n *      strings is inspired from that of Rabin & Karp. A brute force approach\n *      is used to find longer strings when a small match has been found.\n *      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze\n *      (by Leonid Broukhis).\n *         A previous version of this file used a more sophisticated algorithm\n *      (by Fiala and Greene) which is guaranteed to run in linear amortized\n *      time, but has a larger average cost, uses more memory and is patented.\n *      However the F&G algorithm may be faster for some highly redundant\n *      files if the parameter max_chain_length (described below) is too large.\n *\n *  ACKNOWLEDGEMENTS\n *\n *      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and\n *      I found it in 'freeze' written by Leonid Broukhis.\n *      Thanks to many info-zippers for bug reports and testing.\n *\n *  REFERENCES\n *\n *      APPNOTE.TXT documentation file in PKZIP 1.93a distribution.\n *\n *      A description of the Rabin and Karp algorithm is given in the book\n *         \"Algorithms\" by R. Sedgewick, Addison-Wesley, p252.\n *\n *      Fiala,E.R., and Greene,D.H.\n *         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595\n *\n *  INTERFACE\n *\n *      void lm_init (int pack_level, ush *flags)\n *          Initialize the \"longest match\" routines for a new file\n *\n *      ulg deflate (void)\n *          Processes a new input file and return its compressed length. Sets\n *          the compressed length, crc, deflate flags and internal file\n *          attributes.\n */\n\n#define __DEFLATE_C\n\n#include \"zip.h\"\n\n#ifndef USE_ZLIB\n\n/* ===========================================================================\n * Configuration parameters\n */\n\n/* Compile with MEDIUM_MEM to reduce the memory requirements or\n * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the\n * entire input file can be held in memory (not possible on 16 bit systems).\n * Warning: defining these symbols affects HASH_BITS (see below) and thus\n * affects the compression ratio. The compressed output\n * is still correct, and might even be smaller in some cases.\n */\n\n#ifdef SMALL_MEM\n#   define HASH_BITS  13  /* Number of bits used to hash strings */\n#endif\n#ifdef MEDIUM_MEM\n#   define HASH_BITS  14\n#endif\n#ifndef HASH_BITS\n#   define HASH_BITS  15\n   /* For portability to 16 bit machines, do not use values above 15. */\n#endif\n\n#define HASH_SIZE (unsigned)(1<<HASH_BITS)\n#define HASH_MASK (HASH_SIZE-1)\n#define WMASK     (WSIZE-1)\n/* HASH_SIZE and WSIZE must be powers of two */\n\n#define NIL 0\n/* Tail of hash chains */\n\n#define FAST 4\n#define SLOW 2\n/* speed options for the general purpose bit flag */\n\n#ifndef TOO_FAR\n#  define TOO_FAR 4096\n#endif\n/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */\n\n#if (defined(ASMV) && !defined(MSDOS16) && defined(DYN_ALLOC))\n   error: DYN_ALLOC not yet supported in match.S or match32.asm\n#endif\n\n#ifdef MEMORY16\n#  define MAXSEG_64K\n#endif\n\n/* ===========================================================================\n * Local data used by the \"longest match\" routines.\n */\n\n#if defined(MMAP) || defined(BIG_MEM)\n  typedef unsigned Pos; /* must be at least 32 bits */\n#else\n  typedef ush Pos;\n#endif\ntypedef unsigned IPos;\n/* A Pos is an index in the character window. We use short instead of int to\n * save space in the various tables. IPos is used only for parameter passing.\n */\n\n#ifndef DYN_ALLOC\n  uch    window[2L*WSIZE];\n  /* Sliding window. Input bytes are read into the second half of the window,\n   * and move to the first half later to keep a dictionary of at least WSIZE\n   * bytes. With this organization, matches are limited to a distance of\n   * WSIZE-MAX_MATCH bytes, but this ensures that IO is always\n   * performed with a length multiple of the block size. Also, it limits\n   * the window size to 64K, which is quite useful on MSDOS.\n   * To do: limit the window size to WSIZE+CBSZ if SMALL_MEM (the code would\n   * be less efficient since the data would have to be copied WSIZE/CBSZ times)\n   */\n  Pos    prev[WSIZE];\n  /* Link to older string with same hash index. To limit the size of this\n   * array to 64K, this link is maintained only for the last 32K strings.\n   * An index in this array is thus a window index modulo 32K.\n   */\n  Pos    head[HASH_SIZE];\n  /* Heads of the hash chains or NIL. If your compiler thinks that\n   * HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC.\n   */\n#else\n  uch far * near window = NULL;\n  Pos far * near prev   = NULL;\n  Pos far * near head;\n#endif\nulg window_size;\n/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the\n * input file length plus MIN_LOOKAHEAD.\n */\n\nlong block_start;\n/* window position at the beginning of the current output block. Gets\n * negative when the window is moved backwards.\n */\n\nlocal int sliding;\n/* Set to false when the input file is already in memory */\n\nlocal unsigned ins_h;  /* hash index of string to be inserted */\n\n#define H_SHIFT  ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)\n/* Number of bits by which ins_h and del_h must be shifted at each\n * input step. It must be such that after MIN_MATCH steps, the oldest\n * byte no longer takes part in the hash key, that is:\n *   H_SHIFT * MIN_MATCH >= HASH_BITS\n */\n\nunsigned int near prev_length;\n/* Length of the best match at previous step. Matches not greater than this\n * are discarded. This is used in the lazy match evaluation.\n */\n\n      unsigned near strstart;      /* start of string to insert */\n      unsigned near match_start;   /* start of matching string */\nlocal int           eofile;        /* flag set at end of input file */\nlocal unsigned      lookahead;     /* number of valid bytes ahead in window */\n\nunsigned near max_chain_length;\n/* To speed up deflation, hash chains are never searched beyond this length.\n * A higher limit improves compression ratio but degrades the speed.\n */\n\nlocal unsigned int max_lazy_match;\n/* Attempt to find a better match only when the current match is strictly\n * smaller than this value. This mechanism is used only for compression\n * levels >= 4.\n */\n#define max_insert_length  max_lazy_match\n/* Insert new strings in the hash table only if the match length\n * is not greater than this length. This saves time but degrades compression.\n * max_insert_length is used only for compression levels <= 3.\n */\n\nunsigned near good_match;\n/* Use a faster search when the previous match is longer than this */\n\n#ifdef  FULL_SEARCH\n# define nice_match MAX_MATCH\n#else\n  int near nice_match; /* Stop searching when current match exceeds this */\n#endif\n\n\n/* Values for max_lazy_match, good_match, nice_match and max_chain_length,\n * depending on the desired pack level (0..9). The values given below have\n * been tuned to exclude worst case performance for pathological files.\n * Better values may be found for specific files.\n */\n\ntypedef struct config {\n   ush good_length; /* reduce lazy search above this match length */\n   ush max_lazy;    /* do not perform lazy search above this match length */\n   ush nice_length; /* quit search above this match length */\n   ush max_chain;\n} config;\n\nlocal config configuration_table[10] = {\n/*      good lazy nice chain */\n/* 0 */ {0,    0,  0,    0},  /* store only */\n/* 1 */ {4,    4,  8,    4},  /* maximum speed, no lazy matches */\n/* 2 */ {4,    5, 16,    8},\n/* 3 */ {4,    6, 32,   32},\n\n/* 4 */ {4,    4, 16,   16},  /* lazy matches */\n/* 5 */ {8,   16, 32,   32},\n/* 6 */ {8,   16, 128, 128},\n/* 7 */ {8,   32, 128, 256},\n/* 8 */ {32, 128, 258, 1024},\n/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */\n\n/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4\n * For deflate_fast() (levels <= 3) good is ignored and lazy has a different\n * meaning.\n */\n\n#define EQUAL 0\n/* result of memcmp for equal strings */\n\n/* ===========================================================================\n *  Prototypes for local functions.\n */\n\nlocal void fill_window   OF((void));\n\nlocal uzoff_t deflate_fast OF((void));    /* now use uzoff_t 7/24/04 EG */\n\n      int  longest_match OF((IPos cur_match));\n#if defined(ASMV) && !defined(RISCOS)\n      void match_init OF((void)); /* asm code initialization */\n#endif\n\n#ifdef DEBUG\nlocal  void check_match OF((IPos start, IPos match, int length));\n#endif\n\n/* ===========================================================================\n * Update a hash value with the given input byte\n * IN  assertion: all calls to to UPDATE_HASH are made with consecutive\n *    input characters, so that a running hash key can be computed from the\n *    previous key instead of complete recalculation each time.\n */\n#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)\n\n/* ===========================================================================\n * Insert string s in the dictionary and set match_head to the previous head\n * of the hash chain (the most recent string with same hash key). Return\n * the previous length of the hash chain.\n * IN  assertion: all calls to to INSERT_STRING are made with consecutive\n *    input characters and the first MIN_MATCH bytes of s are valid\n *    (except for the last MIN_MATCH-1 bytes of the input file).\n */\n#define INSERT_STRING(s, match_head) \\\n   (UPDATE_HASH(ins_h, window[(s) + (MIN_MATCH-1)]), \\\n    prev[(s) & WMASK] = match_head = head[ins_h], \\\n    head[ins_h] = (s))\n\n/* ===========================================================================\n * Initialize the \"longest match\" routines for a new file\n *\n * IN assertion: window_size is > 0 if the input file is already read or\n *    mmap'ed in the window[] array, 0 otherwise. In the first case,\n *    window_size is sufficient to contain the whole input file plus\n *    MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end\n *    of window[] when looking for matches towards the end).\n */\nvoid lm_init (pack_level, flags)\n    int pack_level; /* 0: store, 1: best speed, 9: best compression */\n    ush *flags;     /* general purpose bit flag */\n{\n    register unsigned j;\n\n    if (pack_level < 1 || pack_level > 9) error(\"bad pack level\");\n\n    /* Do not slide the window if the whole input is already in memory\n     * (window_size > 0)\n     */\n    sliding = 0;\n    if (window_size == 0L) {\n        sliding = 1;\n        window_size = (ulg)2L*WSIZE;\n    }\n\n    /* Use dynamic allocation if compiler does not like big static arrays: */\n#ifdef DYN_ALLOC\n    if (window == NULL) {\n        window = (uch far *) zcalloc(WSIZE,   2*sizeof(uch));\n        if (window == NULL) ziperr(ZE_MEM, \"window allocation\");\n    }\n    if (prev == NULL) {\n        prev   = (Pos far *) zcalloc(WSIZE,     sizeof(Pos));\n        head   = (Pos far *) zcalloc(HASH_SIZE, sizeof(Pos));\n        if (prev == NULL || head == NULL) {\n            ziperr(ZE_MEM, \"hash table allocation\");\n        }\n    }\n#endif /* DYN_ALLOC */\n\n    /* Initialize the hash table (avoiding 64K overflow for 16 bit systems).\n     * prev[] will be initialized on the fly.\n     */\n    head[HASH_SIZE-1] = NIL;\n    memset((char*)head, NIL, (unsigned)(HASH_SIZE-1)*sizeof(*head));\n\n    /* Set the default configuration parameters:\n     */\n    max_lazy_match   = configuration_table[pack_level].max_lazy;\n    good_match       = configuration_table[pack_level].good_length;\n#ifndef FULL_SEARCH\n    nice_match       = configuration_table[pack_level].nice_length;\n#endif\n    max_chain_length = configuration_table[pack_level].max_chain;\n    if (pack_level <= 2) {\n       *flags |= FAST;\n    } else if (pack_level >= 8) {\n       *flags |= SLOW;\n    }\n    /* ??? reduce max_chain_length for binary files */\n\n    strstart = 0;\n    block_start = 0L;\n#if defined(ASMV) && !defined(RISCOS)\n    match_init(); /* initialize the asm code */\n#endif\n\n    j = WSIZE;\n#ifndef MAXSEG_64K\n    if (sizeof(int) > 2) j <<= 1; /* Can read 64K in one step */\n#endif\n    lookahead = (*read_buf)((char*)window, j);\n\n    if (lookahead == 0 || lookahead == (unsigned)EOF) {\n       eofile = 1, lookahead = 0;\n       return;\n    }\n    eofile = 0;\n    /* Make sure that we always have enough lookahead. This is important\n     * if input comes from a device such as a tty.\n     */\n    if (lookahead < MIN_LOOKAHEAD) fill_window();\n\n    ins_h = 0;\n    for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);\n    /* If lookahead < MIN_MATCH, ins_h is garbage, but this is\n     * not important since only literal bytes will be emitted.\n     */\n}\n\n/* ===========================================================================\n * Free the window and hash table\n */\nvoid lm_free()\n{\n#ifdef DYN_ALLOC\n    if (window != NULL) {\n        zcfree(window);\n        window = NULL;\n    }\n    if (prev != NULL) {\n        zcfree(prev);\n        zcfree(head);\n        prev = head = NULL;\n    }\n#endif /* DYN_ALLOC */\n}\n\n/* ===========================================================================\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n */\n#ifndef ASMV\n/* For 80x86 and 680x0 and ARM, an optimized version is in match.asm or\n * match.S. The code is functionally equivalent, so you can use the C version\n * if desired.\n */\nint longest_match(cur_match)\n    IPos cur_match;                             /* current match */\n{\n    unsigned chain_length = max_chain_length;   /* max hash chain length */\n    register uch far *scan = window + strstart; /* current string */\n    register uch far *match;                    /* matched string */\n    register int len;                           /* length of current match */\n    int best_len = prev_length;                 /* best match length so far */\n    IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;\n    /* Stop when cur_match becomes <= limit. To simplify the code,\n     * we prevent matches with the string of window index 0.\n     */\n\n/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.\n * It is easy to get rid of this optimization if necessary.\n */\n#if HASH_BITS < 8 || MAX_MATCH != 258\n   error: Code too clever\n#endif\n\n#ifdef UNALIGNED_OK\n    /* Compare two bytes at a time. Note: this is not always beneficial.\n     * Try with and without -DUNALIGNED_OK to check.\n     */\n    register uch far *strend = window + strstart + MAX_MATCH - 1;\n    register ush scan_start = *(ush far *)scan;\n    register ush scan_end   = *(ush far *)(scan+best_len-1);\n#else\n    register uch far *strend = window + strstart + MAX_MATCH;\n    register uch scan_end1  = scan[best_len-1];\n    register uch scan_end   = scan[best_len];\n#endif\n\n    /* Do not waste too much time if we already have a good match: */\n    if (prev_length >= good_match) {\n        chain_length >>= 2;\n    }\n\n    Assert(strstart <= window_size-MIN_LOOKAHEAD, \"insufficient lookahead\");\n\n    do {\n        Assert(cur_match < strstart, \"no future\");\n        match = window + cur_match;\n\n        /* Skip to next match if the match length cannot increase\n         * or if the match length is less than 2:\n         */\n#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)\n        /* This code assumes sizeof(unsigned short) == 2. Do not use\n         * UNALIGNED_OK if your compiler uses a different size.\n         */\n        if (*(ush far *)(match+best_len-1) != scan_end ||\n            *(ush far *)match != scan_start) continue;\n\n        /* It is not necessary to compare scan[2] and match[2] since they are\n         * always equal when the other bytes match, given that the hash keys\n         * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at\n         * strstart+3, +5, ... up to strstart+257. We check for insufficient\n         * lookahead only every 4th comparison; the 128th check will be made\n         * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is\n         * necessary to put more guard bytes at the end of the window, or\n         * to check more often for insufficient lookahead.\n         */\n        scan++, match++;\n        do {\n        } while (*(ush far *)(scan+=2) == *(ush far *)(match+=2) &&\n                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&\n                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&\n                 *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&\n                 scan < strend);\n        /* The funny \"do {}\" generates better code on most compilers */\n\n        /* Here, scan <= window+strstart+257 */\n        Assert(scan <= window+(unsigned)(window_size-1), \"wild scan\");\n        if (*scan == *match) scan++;\n\n        len = (MAX_MATCH - 1) - (int)(strend-scan);\n        scan = strend - (MAX_MATCH-1);\n\n#else /* UNALIGNED_OK */\n\n        if (match[best_len]   != scan_end  ||\n            match[best_len-1] != scan_end1 ||\n            *match            != *scan     ||\n            *++match          != scan[1])      continue;\n\n        /* The check at best_len-1 can be removed because it will be made\n         * again later. (This heuristic is not always a win.)\n         * It is not necessary to compare scan[2] and match[2] since they\n         * are always equal when the other bytes match, given that\n         * the hash keys are equal and that HASH_BITS >= 8.\n         */\n        scan += 2, match++;\n\n        /* We check for insufficient lookahead only every 8th comparison;\n         * the 256th check will be made at strstart+258.\n         */\n        do {\n        } while (*++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 *++scan == *++match && *++scan == *++match &&\n                 scan < strend);\n\n        Assert(scan <= window+(unsigned)(window_size-1), \"wild scan\");\n\n        len = MAX_MATCH - (int)(strend - scan);\n        scan = strend - MAX_MATCH;\n\n#endif /* UNALIGNED_OK */\n\n        if (len > best_len) {\n            match_start = cur_match;\n            best_len = len;\n            if (len >= nice_match) break;\n#ifdef UNALIGNED_OK\n            scan_end = *(ush far *)(scan+best_len-1);\n#else\n            scan_end1  = scan[best_len-1];\n            scan_end   = scan[best_len];\n#endif\n        }\n    } while ((cur_match = prev[cur_match & WMASK]) > limit\n             && --chain_length != 0);\n\n    return best_len;\n}\n#endif /* ASMV */\n\n#ifdef DEBUG\n/* ===========================================================================\n * Check that the match at match_start is indeed a match.\n */\nlocal void check_match(start, match, length)\n    IPos start, match;\n    int length;\n{\n    /* check that the match is indeed a match */\n    if (memcmp((char*)window + match,\n                (char*)window + start, length) != EQUAL) {\n        fprintf(mesg,\n            \" start %d, match %d, length %d\\n\",\n            start, match, length);\n        error(\"invalid match\");\n    }\n    if (verbose > 1) {\n        fprintf(mesg,\"\\\\[%d,%d]\", start-match, length);\n#ifndef WINDLL\n        do { putc(window[start++], mesg); } while (--length != 0);\n#else\n        do { fprintf(stdout,\"%c\",window[start++]); } while (--length != 0);\n#endif\n    }\n}\n#else\n#  define check_match(start, match, length)\n#endif\n\n/* ===========================================================================\n * Flush the current block, with given end-of-file flag.\n * IN assertion: strstart is set to the end of the current match.\n */\n#define FLUSH_BLOCK(eof) \\\n   flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \\\n                (char*)NULL, (ulg)strstart - (ulg)block_start, (eof))\n\n/* ===========================================================================\n * Fill the window when the lookahead becomes insufficient.\n * Updates strstart and lookahead, and sets eofile if end of input file.\n *\n * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0\n * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n *    At least one byte has been read, or eofile is set; file reads are\n *    performed for at least two bytes (required for the translate_eol option).\n */\nlocal void fill_window()\n{\n    register unsigned n, m;\n    unsigned more;    /* Amount of free space at the end of the window. */\n\n    do {\n        more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);\n\n        /* If the window is almost full and there is insufficient lookahead,\n         * move the upper half to the lower one to make room in the upper half.\n         */\n        if (more == (unsigned)EOF) {\n            /* Very unlikely, but possible on 16 bit machine if strstart == 0\n             * and lookahead == 1 (input done one byte at time)\n             */\n            more--;\n\n        /* For MMAP or BIG_MEM, the whole input file is already in memory so\n         * we must not perform sliding. We must however call (*read_buf)() in\n         * order to compute the crc, update lookahead and possibly set eofile.\n         */\n        } else if (strstart >= WSIZE+MAX_DIST && sliding) {\n\n#ifdef FORCE_METHOD\n            /* When methods \"stored\" or \"store_block\" are requested, the\n             * current block must be flushed before sliding the window.\n             */\n            if (level <= 2) FLUSH_BLOCK(0), block_start = strstart;\n#endif\n            /* By the IN assertion, the window is not empty so we can't confuse\n             * more == 0 with more == 64K on a 16 bit machine.\n             */\n            memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);\n            match_start -= WSIZE;\n            strstart    -= WSIZE; /* we now have strstart >= MAX_DIST: */\n\n            block_start -= (long) WSIZE;\n\n            for (n = 0; n < HASH_SIZE; n++) {\n                m = head[n];\n                head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);\n            }\n            for (n = 0; n < WSIZE; n++) {\n                m = prev[n];\n                prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);\n                /* If n is not on any hash chain, prev[n] is garbage but\n                 * its value will never be used.\n                 */\n            }\n            more += WSIZE;\n            if (dot_size > 0 && !display_globaldots) {\n              /* initial space */\n              if (noisy && dot_count == -1) {\n#ifndef WINDLL\n                putc(' ', mesg);\n                fflush(mesg);\n#else\n                fprintf(stdout,\"%c\",' ');\n#endif\n                dot_count++;\n              }\n              dot_count++;\n              if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;\n            }\n            if ((verbose || noisy) && dot_size && !dot_count) {\n#ifndef WINDLL\n              putc('.', mesg);\n              fflush(mesg);\n#else\n              fprintf(stdout,\"%c\",'.');\n#endif\n              mesg_line_started = 1;\n            }\n        }\n        if (eofile) return;\n\n        /* If there was no sliding:\n         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n         *    more == window_size - lookahead - strstart\n         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n         * => more >= window_size - 2*WSIZE + 2\n         * In the MMAP or BIG_MEM case (not yet supported in gzip),\n         *   window_size == input_size + MIN_LOOKAHEAD  &&\n         *   strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD.\n         * Otherwise, window_size == 2*WSIZE so more >= 2.\n         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n         */\n        Assert(more >= 2, \"more < 2\");\n\n        n = (*read_buf)((char*)window+strstart+lookahead, more);\n        if (n == 0 || n == (unsigned)EOF) {\n            eofile = 1;\n        } else {\n            lookahead += n;\n        }\n    } while (lookahead < MIN_LOOKAHEAD && !eofile);\n}\n\n/* ===========================================================================\n * Processes a new input file and return its compressed length. This\n * function does not perform lazy evaluation of matches and inserts\n * new strings in the dictionary only for unmatched strings or for short\n * matches. It is used only for the fast compression options.\n */\nlocal uzoff_t deflate_fast()\n{\n    IPos hash_head = NIL;       /* head of the hash chain */\n    int flush;                  /* set if current block must be flushed */\n    unsigned match_length = 0;  /* length of best match */\n\n    prev_length = MIN_MATCH-1;\n    while (lookahead != 0) {\n        /* Insert the string window[strstart .. strstart+2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n#ifndef DEFL_UNDETERM\n        if (lookahead >= MIN_MATCH)\n#endif\n        INSERT_STRING(strstart, hash_head);\n\n        /* Find the longest match, discarding those <= prev_length.\n         * At this point we have always match_length < MIN_MATCH\n         */\n        if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n#ifndef HUFFMAN_ONLY\n#  ifndef DEFL_UNDETERM\n            /* Do not look for matches beyond the end of the input.\n             * This is necessary to make deflate deterministic.\n             */\n            if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;\n#  endif\n            match_length = longest_match (hash_head);\n            /* longest_match() sets match_start */\n            if (match_length > lookahead) match_length = lookahead;\n#endif\n        }\n        if (match_length >= MIN_MATCH) {\n            check_match(strstart, match_start, match_length);\n\n            flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);\n\n            lookahead -= match_length;\n\n            /* Insert new strings in the hash table only if the match length\n             * is not too large. This saves time but degrades compression.\n             */\n            if (match_length <= max_insert_length\n#ifndef DEFL_UNDETERM\n                && lookahead >= MIN_MATCH\n#endif\n                                                 ) {\n                match_length--; /* string at strstart already in hash table */\n                do {\n                    strstart++;\n                    INSERT_STRING(strstart, hash_head);\n                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n                     * always MIN_MATCH bytes ahead.\n                     */\n#ifdef DEFL_UNDETERM\n                    /* If lookahead < MIN_MATCH these bytes are garbage,\n                     * but it does not matter since the next lookahead bytes\n                     * will be emitted as literals.\n                     */\n#endif\n                } while (--match_length != 0);\n                strstart++;\n            } else {\n                strstart += match_length;\n                match_length = 0;\n                ins_h = window[strstart];\n                UPDATE_HASH(ins_h, window[strstart+1]);\n#if MIN_MATCH != 3\n                Call UPDATE_HASH() MIN_MATCH-3 more times\n#endif\n            }\n        } else {\n            /* No match, output a literal byte */\n            Tracevv((stderr,\"%c\",window[strstart]));\n            flush = ct_tally (0, window[strstart]);\n            lookahead--;\n            strstart++;\n        }\n        if (flush) FLUSH_BLOCK(0), block_start = strstart;\n\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (lookahead < MIN_LOOKAHEAD) fill_window();\n    }\n    return FLUSH_BLOCK(1); /* eof */\n}\n\n/* ===========================================================================\n * Same as above, but achieves better compression. We use a lazy\n * evaluation for matches: a match is finally adopted only if there is\n * no better match at the next window position.\n */\nuzoff_t deflate()\n{\n    IPos hash_head = NIL;       /* head of hash chain */\n    IPos prev_match;            /* previous match */\n    int flush;                  /* set if current block must be flushed */\n    int match_available = 0;    /* set if previous match exists */\n    register unsigned match_length = MIN_MATCH-1; /* length of best match */\n#ifdef DEBUG\n    extern uzoff_t isize;       /* byte length of input file, for debug only */\n#endif\n\n    if (level <= 3) return deflate_fast(); /* optimized for speed */\n\n    /* Process the input block. */\n    while (lookahead != 0) {\n        /* Insert the string window[strstart .. strstart+2] in the\n         * dictionary, and set hash_head to the head of the hash chain:\n         */\n#ifndef DEFL_UNDETERM\n        if (lookahead >= MIN_MATCH)\n#endif\n        INSERT_STRING(strstart, hash_head);\n\n        /* Find the longest match, discarding those <= prev_length.\n         */\n        prev_length = match_length, prev_match = match_start;\n        match_length = MIN_MATCH-1;\n\n        if (hash_head != NIL && prev_length < max_lazy_match &&\n            strstart - hash_head <= MAX_DIST) {\n            /* To simplify the code, we prevent matches with the string\n             * of window index 0 (in particular we have to avoid a match\n             * of the string with itself at the start of the input file).\n             */\n#ifndef HUFFMAN_ONLY\n#  ifndef DEFL_UNDETERM\n            /* Do not look for matches beyond the end of the input.\n             * This is necessary to make deflate deterministic.\n             */\n            if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;\n#  endif\n            match_length = longest_match (hash_head);\n            /* longest_match() sets match_start */\n            if (match_length > lookahead) match_length = lookahead;\n#endif\n\n#ifdef FILTERED\n            /* Ignore matches of length <= 5 */\n            if (match_length <= 5) {\n#else\n            /* Ignore a length 3 match if it is too distant: */\n            if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){\n#endif\n                /* If prev_match is also MIN_MATCH, match_start is garbage\n                 * but we will ignore the current match anyway.\n                 */\n                match_length = MIN_MATCH-1;\n            }\n        }\n        /* If there was a match at the previous step and the current\n         * match is not better, output the previous match:\n         */\n        if (prev_length >= MIN_MATCH && match_length <= prev_length) {\n#ifndef DEFL_UNDETERM\n            unsigned max_insert = strstart + lookahead - MIN_MATCH;\n\n#endif\n            check_match(strstart-1, prev_match, prev_length);\n\n            flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);\n\n            /* Insert in hash table all strings up to the end of the match.\n             * strstart-1 and strstart are already inserted.\n             */\n            lookahead -= prev_length-1;\n            prev_length -= 2;\n#ifndef DEFL_UNDETERM\n            do {\n                if (++strstart <= max_insert) {\n                    INSERT_STRING(strstart, hash_head);\n                    /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n                     * always MIN_MATCH bytes ahead.\n                     */\n                }\n            } while (--prev_length != 0);\n            strstart++;\n#else /* DEFL_UNDETERM */\n            do {\n                strstart++;\n                INSERT_STRING(strstart, hash_head);\n                /* strstart never exceeds WSIZE-MAX_MATCH, so there are\n                 * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH\n                 * these bytes are garbage, but it does not matter since the\n                 * next lookahead bytes will always be emitted as literals.\n                 */\n            } while (--prev_length != 0);\n            strstart++;\n#endif /* ?DEFL_UNDETERM */\n            match_available = 0;\n            match_length = MIN_MATCH-1;\n\n            if (flush) FLUSH_BLOCK(0), block_start = strstart;\n\n        } else if (match_available) {\n            /* If there was no match at the previous position, output a\n             * single literal. If there was a match but the current match\n             * is longer, truncate the previous match to a single literal.\n             */\n            Tracevv((stderr,\"%c\",window[strstart-1]));\n            if (ct_tally (0, window[strstart-1])) {\n                FLUSH_BLOCK(0), block_start = strstart;\n            }\n            strstart++;\n            lookahead--;\n        } else {\n            /* There is no previous match to compare with, wait for\n             * the next step to decide.\n             */\n            match_available = 1;\n            strstart++;\n            lookahead--;\n        }\n        Assert(strstart <= isize && lookahead <= isize, \"a bit too far\");\n\n        /* Make sure that we always have enough lookahead, except\n         * at the end of the input file. We need MAX_MATCH bytes\n         * for the next match, plus MIN_MATCH bytes to insert the\n         * string following the next match.\n         */\n        if (lookahead < MIN_LOOKAHEAD) fill_window();\n    }\n    if (match_available) ct_tally (0, window[strstart-1]);\n\n    return FLUSH_BLOCK(1); /* eof */\n}\n#endif /* !USE_ZLIB */\n"
  },
  {
    "path": "deps/infozip/zip30/ebcdic.h",
    "content": "/*\n  ebcdic.h\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/licen\n*/\n/*---------------------------------------------------------------------------\n\n  ebcdic.h\n\n  The CECP 1047 (Extended de-facto EBCDIC) <-> ISO 8859-1 conversion tables,\n  from ftp://aix1.segi.ulg.ac.be/pub/docs/iso8859/iso8859.networking\n\n  NOTES:\n  <Paul_von_Behren@stortek.com> (OS/390 port 12/97)\n   These table no longer represent the standard mappings (for example in the\n   OS/390 iconv utility).  In order to follow current standards I remapped\n     ebcdic x0a to ascii x15    and\n     ebcdic x85 to ascii x25    (and vice-versa)\n   Without these changes, newlines in auto-convert text files appeared\n   as literal \\045.\n   I'm not sure what effect this remap would have on the MVS and CMS ports, so\n   I ifdef'd these changes.  Hopefully these ifdef's can be removed when the\n   MVS/CMS folks test the new mappings.\n\n  Christian Spieler <spieler@ikp.tu-darmstadt.de>, 27-Apr-1998\n   The problem mentioned by Paul von Behren was already observed previously\n   on VM/CMS, during the preparation of the CMS&MVS port of UnZip 5.20 in\n   1996. At that point, the ebcdic tables were not changed since they seemed\n   to be an adopted standard (to my knowledge, these tables are still used\n   as presented in mainfraime KERMIT). Instead, the \"end-of-line\" conversion\n   feature of Zip's and UnZip's \"text-translation\" mode was used to force\n   correct mappings between ASCII and EBCDIC newline markers.\n   Before interchanging the ASCII mappings of the EBCDIC control characters\n   \"NL\" 0x25 and \"LF\" 0x15 according to the OS/390 setting, we have to\n   make sure that EBCDIC 0x15 is never used as line termination.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __ebcdic_h      /* prevent multiple inclusions */\n#define __ebcdic_h\n\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#ifdef EBCDIC\n#ifndef MTS             /* MTS uses a slightly \"special\" EBCDIC code page */\n\nZCONST uch ebcdic[] = {\n    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */\n#ifdef OS390\n    0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#else\n    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#endif\n    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */\n    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */\n    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */\n    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */\n    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */\n    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */\n    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */\n    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */\n    0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,  /* 58 - 5F */\n    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */\n    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */\n    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */\n    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */\n#ifdef OS390\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,  /* 80 - 87 */\n#else\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */\n#endif\n    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */\n    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */\n    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */\n    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */\n    0xBB, 0xB4, 0x9A, 0x8A, 0xB0, 0xCA, 0xAF, 0xBC,  /* A8 - AF */\n    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */\n    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */\n    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */\n    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */\n    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */\n    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xBA, 0xAE, 0x59,  /* D8 - DF */\n    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */\n    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */\n    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */\n    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */\n};\n\n#if (defined(ZIP) || CRYPT)\nZCONST uch ascii[] = {\n    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */\n    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n#ifdef OS390\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x0A, 0x08, 0x87,  /* 10 - 17 */\n#else\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */\n#endif\n    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n#ifdef OS390\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1B,  /* 20 - 27 */\n#else\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */\n#endif\n    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */\n    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */\n    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */\n    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */\n    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */\n    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */\n    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,  /* 58 - 5F */\n    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */\n    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */\n    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */\n    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */\n    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */\n    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */\n    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */\n    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */\n    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */\n    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0x5B, 0xDE, 0xAE,  /* A8 - AF */\n    0xAC, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */\n    0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D, 0xB4, 0xD7,  /* B8 - BF */\n    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */\n    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */\n    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */\n    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */\n    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */\n    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */\n    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */\n};\n#endif /* ZIP || CRYPT */\n\n#else /* MTS */\n\n/*\n * This is the MTS ASCII->EBCDIC translation table. It provides a 1-1\n * translation from ISO 8859/1 8-bit ASCII to IBM Code Page 37 EBCDIC.\n */\n\nZCONST uch ebcdic[] = {\n    0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,  /* 00 - 07 */\n    0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n    0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,  /* 10 - 17 */\n    0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,  /* 20 - 27 */\n    0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,  /* 28 - 2F */\n    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* 30 - 37 */\n    0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,  /* 38 - 3F */\n    0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 40 - 47 */\n    0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,  /* 48 - 4F */\n    0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,  /* 50 - 57 */\n    0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,  /* 58 - 5F */\n    0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,  /* 60 - 67 */\n    0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,  /* 68 - 6F */\n    0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,  /* 70 - 77 */\n    0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,  /* 78 - 7F */\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,  /* 80 - 87 */\n    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B,  /* 88 - 8F */\n    0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08,  /* 90 - 97 */\n    0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xFF,  /* 98 - 9F */\n    0x41, 0xAA, 0x4A, 0xB1, 0x9F, 0xB2, 0x6A, 0xB5,  /* A0 - A7 */\n    0xBD, 0xB4, 0x9A, 0x8A, 0x5F, 0xCA, 0xAF, 0xBC,  /* A8 - AF */\n    0x90, 0x8F, 0xEA, 0xFA, 0xBE, 0xA0, 0xB6, 0xB3,  /* B0 - B7 */\n    0x9D, 0xDA, 0x9B, 0x8B, 0xB7, 0xB8, 0xB9, 0xAB,  /* B8 - BF */\n    0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9E, 0x68,  /* C0 - C7 */\n    0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,  /* C8 - CF */\n    0xAC, 0x69, 0xED, 0xEE, 0xEB, 0xEF, 0xEC, 0xBF,  /* D0 - D7 */\n    0x80, 0xFD, 0xFE, 0xFB, 0xFC, 0xAD, 0xAE, 0x59,  /* D8 - DF */\n    0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9C, 0x48,  /* E0 - E7 */\n    0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,  /* E8 - EF */\n    0x8C, 0x49, 0xCD, 0xCE, 0xCB, 0xCF, 0xCC, 0xE1,  /* F0 - F7 */\n    0x70, 0xDD, 0xDE, 0xDB, 0xDC, 0x8D, 0x8E, 0xDF   /* F8 - FF */\n};\n\n#if (defined(ZIP) || CRYPT)\nZCONST uch ascii[] = {\n    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F,  /* 00 - 07 */\n    0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,  /* 08 - 0F */\n    0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,  /* 10 - 17 */\n    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,  /* 18 - 1F */\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B,  /* 20 - 27 */\n    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,  /* 28 - 2F */\n    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,  /* 30 - 37 */\n    0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,  /* 38 - 3F */\n    0x20, 0xA0, 0xE2, 0xE4, 0xE0, 0xE1, 0xE3, 0xE5,  /* 40 - 47 */\n    0xE7, 0xF1, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,  /* 48 - 4F */\n    0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF,  /* 50 - 57 */\n    0xEC, 0xDF, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,  /* 58 - 5F */\n    0x2D, 0x2F, 0xC2, 0xC4, 0xC0, 0xC1, 0xC3, 0xC5,  /* 60 - 67 */\n    0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,  /* 68 - 6F */\n    0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,  /* 70 - 77 */\n    0xCC, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,  /* 78 - 7F */\n    0xD8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,  /* 80 - 87 */\n    0x68, 0x69, 0xAB, 0xBB, 0xF0, 0xFD, 0xFE, 0xB1,  /* 88 - 8F */\n    0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,  /* 90 - 97 */\n    0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,  /* 98 - 9F */\n    0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,  /* A0 - A7 */\n    0x79, 0x7A, 0xA1, 0xBF, 0xD0, 0xDD, 0xDE, 0xAE,  /* A8 - AF */\n    0x5E, 0xA3, 0xA5, 0xB7, 0xA9, 0xA7, 0xB6, 0xBC,  /* B0 - B7 */\n    0xBD, 0xBE, 0x5B, 0x5D, 0xAF, 0xA8, 0xB4, 0xD7,  /* B8 - BF */\n    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,  /* C0 - C7 */\n    0x48, 0x49, 0xAD, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5,  /* C8 - CF */\n    0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,  /* D0 - D7 */\n    0x51, 0x52, 0xB9, 0xFB, 0xFC, 0xF9, 0xFA, 0xFF,  /* D8 - DF */\n    0x5C, 0xF7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,  /* E0 - E7 */\n    0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,  /* E8 - EF */\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,  /* F0 - F7 */\n    0x38, 0x39, 0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x9F   /* F8 - FF */\n};\n#endif /* ZIP || CRYPT */\n\n#endif /* ?MTS */\n#endif /* EBCDIC */\n\n/*---------------------------------------------------------------------------\n\n  The following conversion tables translate between IBM PC CP 850\n  (OEM codepage) and the \"Western Europe & America\" Windows codepage 1252.\n  The Windows codepage 1252 contains the ISO 8859-1 \"Latin 1\" codepage,\n  with some additional printable characters in the range (0x80 - 0x9F),\n  that is reserved to control codes in the ISO 8859-1 character table.\n\n  The ISO <--> OEM conversion tables were constructed with the help\n  of the WIN32 (Win16?) API's OemToAnsi() and AnsiToOem() conversion\n  functions and have been checked against the CP850 and LATIN1 tables\n  provided in the MS-Kermit 3.14 distribution.\n\n  ---------------------------------------------------------------------------*/\n\n#ifdef IZ_ISO2OEM_ARRAY\n#ifdef OEM_RUSS\nZCONST uch Far iso2oem[] = {\n    0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE,  /* 80 - 87 */\n    0xFD, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */\n    0x3F, 0x27, 0x27, 0x22, 0x22, 0xF9, 0x2D, 0x2D,  /* 90 - 97 */\n    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */\n    0xFF, 0xF6, 0xF7, 0x9C, 0xCF, 0xBE, 0xFE, 0xF5,  /* A0 - A7 */\n    0xF0, 0xB8, 0xF2, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,  /* A8 - AF */\n    0xF8, 0xFB, 0xF4, 0xF5, 0xEF, 0xE6, 0xF4, 0xFA,  /* B0 - B7 */\n    0xF1, 0xFC, 0xF3, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,  /* B8 - BF */\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x86, 0x86, 0x87,  /* C0 - C7 */\n    0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,  /* C8 - CF */\n    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,  /* D0 - D7 */\n    0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,  /* D8 - DF */\n    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,  /* E0 - E7 */\n    0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,  /* E8 - EF */\n    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,  /* F0 - F7 */\n    0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF   /* F8 - FF */\n};\n#else /* OEM_RUS */\nZCONST uch Far iso2oem[] = {\n    0x3F, 0x3F, 0x27, 0x9F, 0x22, 0x2E, 0xC5, 0xCE,  /* 80 - 87 */\n    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */\n    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */\n    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */\n    0xFF, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,  /* A0 - A7 */\n    0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,  /* A8 - AF */\n    0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,  /* B0 - B7 */\n    0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,  /* B8 - BF */\n    0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,  /* C0 - C7 */\n    0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,  /* C8 - CF */\n    0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,  /* D0 - D7 */\n    0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,  /* D8 - DF */\n    0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,  /* E0 - E7 */\n    0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,  /* E8 - EF */\n    0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,  /* F0 - F7 */\n    0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98   /* F8 - FF */\n};\n#endif /* OEM_RUS */\n#endif /* IZ_ISO2OEM_ARRAY */\n\n#ifdef IZ_OEM2ISO_ARRAY\n#ifdef OEM_RUSS\nZCONST uch Far oem2iso[] = {\n    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,  /* 80 - 87 */\n    0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,  /* 88 - 8F */\n    0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,  /* 90 - 97 */\n    0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,  /* 98 - 9F */\n    0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,  /* A0 - A7 */\n    0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,  /* A8 - AF */\n    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0,  /* B0 - B7 */\n    0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B,  /* B8 - BF */\n    0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3,  /* C0 - C7 */\n    0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4,  /* C8 - CF */\n    0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE,  /* D0 - D7 */\n    0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF,  /* D8 - DF */\n    0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,  /* E0 - E7 */\n    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,  /* E8 - EF */\n    0xA8, 0xB8, 0xAA, 0xBA, 0xB2, 0xB3, 0xA1, 0xA2,  /* F0 - F7 */\n    0xB0, 0x95, 0xB7, 0xB1, 0xB9, 0x88, 0xA6, 0xA0   /* F8 - FF */\n};\n#else /* OEM_RUS */\nZCONST uch Far oem2iso[] = {\n    0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,  /* 80 - 87 */\n    0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,  /* 88 - 8F */\n    0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,  /* 90 - 97 */\n    0xFF, 0xD6, 0xDC, 0xF8, 0xA3, 0xD8, 0xD7, 0x83,  /* 98 - 9F */\n    0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,  /* A0 - A7 */\n    0xBF, 0xAE, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,  /* A8 - AF */\n    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xC1, 0xC2, 0xC0,  /* B0 - B7 */\n    0xA9, 0xA6, 0xA6, 0x2B, 0x2B, 0xA2, 0xA5, 0x2B,  /* B8 - BF */\n    0x2B, 0x2D, 0x2D, 0x2B, 0x2D, 0x2B, 0xE3, 0xC3,  /* C0 - C7 */\n    0x2B, 0x2B, 0x2D, 0x2D, 0xA6, 0x2D, 0x2B, 0xA4,  /* C8 - CF */\n    0xF0, 0xD0, 0xCA, 0xCB, 0xC8, 0x69, 0xCD, 0xCE,  /* D0 - D7 */\n    0xCF, 0x2B, 0x2B, 0xA6, 0x5F, 0xA6, 0xCC, 0xAF,  /* D8 - DF */\n    0xD3, 0xDF, 0xD4, 0xD2, 0xF5, 0xD5, 0xB5, 0xFE,  /* E0 - E7 */\n    0xDE, 0xDA, 0xDB, 0xD9, 0xFD, 0xDD, 0xAF, 0xB4,  /* E8 - EF */\n    0xAD, 0xB1, 0x3D, 0xBE, 0xB6, 0xA7, 0xF7, 0xB8,  /* F0 - F7 */\n    0xB0, 0xA8, 0xB7, 0xB9, 0xB3, 0xB2, 0xA6, 0xA0   /* F8 - FF */\n};\n#endif /* OEM_RUS */\n#endif /* IZ_OEM2ISO_ARRAY */\n\n#if defined(THEOS) || defined(THEOS_SUPPORT)\n#  include \"theos/charconv.h\"\n#endif\n\n#endif /* __ebcdic_h  */\n"
  },
  {
    "path": "deps/infozip/zip30/file_id.diz",
    "content": "Info-ZIP's Zip 3.0: generic C sources.\n  Complete C source code for Info-ZIP's\n  PKZIP-compatible .zip archiver, for\n  all supported compilers and platforms\n  (Unix, OS/2, MS-DOS, NT, VMS, Amiga,\n  Atari, Mac, Acorn, VM/CMS, etc.), plus\n  lots of pretty decent documentation.\n  Includes Info-ZIP's ZCrypt 2.9 for\n  PKWARE-compatible standard encryption\n  and decryption support for Info-ZIP's\n  Zip 2.32, Zip 3.0, UnZip 5.52,\n  UnZip 6.0, and WiZ 5.02 (and later).\nThis is FREE (but copyrighted) software.\nSee LICENSE for details on distribution\nand reuse.\n"
  },
  {
    "path": "deps/infozip/zip30/fileio.c",
    "content": "/*\n  fileio.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  fileio.c by Mark Adler\n */\n#define __FILEIO_C\n\n#include \"zip.h\"\n#include \"crc32.h\"\n\n#ifdef MACOS\n#  include \"helpers.h\"\n#endif\n\n#ifdef VMS\n#  include \"vms/vms.h\"\n#endif /* def VMS */\n\n#include <time.h>\n\n#ifdef NO_MKTIME\ntime_t mktime OF((struct tm *));\n#endif\n\n#ifdef OSF\n#define EXDEV 18   /* avoid a bug in the DEC OSF/1 header files. */\n#else\n#include <errno.h>\n#endif\n\n#ifdef NO_ERRNO\nextern int errno;\n#endif\n\n/* -----------------------\n   For long option support\n   ----------------------- */\n#include <ctype.h>\n\n\n#if defined(VMS) || defined(TOPS20)\n#  define PAD 5\n#else\n#  define PAD 0\n#endif\n\n#ifdef NO_RENAME\nint rename OF((ZCONST char *, ZCONST char *));\n#endif\n\n\n/* Local functions */\nlocal int optionerr OF((char *, ZCONST char *, int, int));\nlocal unsigned long get_shortopt OF((char **, int, int *, int *, char **, int *, int));\nlocal unsigned long get_longopt OF((char **, int, int *, int *, char **, int *, int));\n\n#ifdef UNICODE_SUPPORT\nlocal int utf8_char_bytes OF((ZCONST char *utf8));\nlocal long ucs4_char_from_utf8 OF((ZCONST char **utf8 ));\nlocal int utf8_from_ucs4_char OF((char *utf8buf, ulg ch));\nlocal int utf8_to_ucs4_string OF((ZCONST char *utf8, ulg *usc4buf,\n                                  int buflen));\nlocal int ucs4_string_to_utf8 OF((ZCONST ulg *ucs4, char *utf8buf,\n                                  int buflen));\n#if 0\n  local int utf8_chars OF((ZCONST char *utf8));\n#endif\n#endif /* UNICODE_SUPPORT */\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\nlocal int fqcmp  OF((ZCONST zvoid *, ZCONST zvoid *));\nlocal int fqcmpz OF((ZCONST zvoid *, ZCONST zvoid *));\n\n\n/* Local module level variables. */\nchar *label = NULL;                /* global, but only used in `system'.c */\nlocal z_stat zipstatb;             /* now use z_stat globally - 7/24/04 EG */\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n local zw_stat zipstatbw;\n#endif\n#if (!defined(MACOS) && !defined(WINDLL))\nlocal int zipstate = -1;\n#else\nint zipstate;\n#endif\n/* -1 unknown, 0 old zip file exists, 1 new zip file */\n\n#if 0\nchar *getnam(n, fp)\nchar *n;                /* where to put name (must have >=FNMAX+1 bytes) */\n#endif\n\n/* converted to return string pointer from malloc to avoid\n   size limitation - 11/8/04 EG */\n#define GETNAM_MAX 9000 /* hopefully big enough for now */\nchar *getnam(fp)\n  FILE *fp;\n  /* Read a \\n or \\r delimited name from stdin into n, and return\n     n.  If EOF, then return NULL.  Also, if problem return NULL. */\n{\n  char name[GETNAM_MAX + 1];\n  int c;                /* last character read */\n  char *p;              /* pointer into name area */\n\n\n  p = name;\n  while ((c = getc(fp)) == '\\n' || c == '\\r')\n    ;\n  if (c == EOF)\n    return NULL;\n  do {\n    if (p - name >= GETNAM_MAX)\n      return NULL;\n    *p++ = (char) c;\n    c = getc(fp);\n  } while (c != EOF && (c != '\\n' && c != '\\r'));\n#ifdef WIN32\n/*\n * WIN32 strips off trailing spaces and periods in filenames\n * XXX what about a filename that only consists of spaces ?\n *     Answer: on WIN32, a filename must contain at least one non-space char\n */\n  while (p > name) {\n    if ((c = p[-1]) != ' ' && c != '.')\n      break;\n    --p;\n  }\n#endif\n  *p = 0;\n  /* malloc a copy */\n  if ((p = malloc(strlen(name) + 1)) == NULL) {\n    return NULL;\n  }\n  strcpy(p, name);\n  return p;\n}\n\nstruct flist far *fexpel(f)\nstruct flist far *f;    /* entry to delete */\n/* Delete the entry *f in the doubly-linked found list.  Return pointer to\n   next entry to allow stepping through list. */\n{\n  struct flist far *t;  /* temporary variable */\n\n  t = f->nxt;\n  *(f->lst) = t;                        /* point last to next, */\n  if (t != NULL)\n    t->lst = f->lst;                    /* and next to last */\n  if (f->name != NULL)                  /* free memory used */\n    free((zvoid *)(f->name));\n  if (f->zname != NULL)\n    free((zvoid *)(f->zname));\n  if (f->iname != NULL)\n    free((zvoid *)(f->iname));\n#ifdef UNICODE_SUPPORT\n  if (f->uname)\n    free((zvoid *)f->uname);\n# ifdef WIN32\n  if (f->namew)\n    free((zvoid *)f->namew);\n  if (f->inamew)\n    free((zvoid *)f->inamew);\n  if (f->znamew)\n    free((zvoid *)f->znamew);\n# endif\n#endif\n  farfree((zvoid far *)f);\n  fcount--;                             /* decrement count */\n  return t;                             /* return pointer to next */\n}\n\nlocal int fqcmp(a, b)\n  ZCONST zvoid *a, *b;          /* pointers to pointers to found entries */\n/* Used by qsort() to compare entries in the found list by name. */\n{\n  return strcmp((*(struct flist far **)a)->name,\n                (*(struct flist far **)b)->name);\n}\n\nlocal int fqcmpz(a, b)\n  ZCONST zvoid *a, *b;          /* pointers to pointers to found entries */\n/* Used by qsort() to compare entries in the found list by iname. */\n{\n  return strcmp((*(struct flist far **)a)->iname,\n                (*(struct flist far **)b)->iname);\n}\n\nchar *last(p, c)\n  char *p;                /* sequence of path components */\n  int c;                  /* path components separator character */\n/* Return a pointer to the start of the last path component. For a directory\n * name terminated by the character in c, the return value is an empty string.\n */\n{\n  char *t;              /* temporary variable */\n\n  if ((t = strrchr(p, c)) != NULL)\n    return t + 1;\n  else\n#ifndef AOS_VS\n    return p;\n#else\n/* We want to allow finding of end of path in either AOS/VS-style pathnames\n * or Unix-style pathnames.  This presents a few little problems ...\n */\n  {\n    if (*p == '='  ||  *p == '^')      /* like ./ and ../ respectively */\n      return p + 1;\n    else\n      return p;\n  }\n#endif\n}\n\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\nwchar_t *lastw(pw, c)\n  wchar_t *pw;            /* sequence of path components */\n  wchar_t c;              /* path components separator character */\n/* Return a pointer to the start of the last path component. For a directory\n * name terminated by the character in c, the return value is an empty string.\n */\n{\n  wchar_t *tw;            /* temporary variable */\n\n  if ((tw = wcsrchr(pw, c)) != NULL)\n    return tw + 1;\n  else\n# ifndef AOS_VS\n    return pw;\n# else\n/* We want to allow finding of end of path in either AOS/VS-style pathnames\n * or Unix-style pathnames.  This presents a few little problems ...\n */\n  {\n    if (*pw == (wchar_t)'='  ||  *pw == (wchar_t)'^')      /* like ./ and ../ respectively */\n      return pw + 1;\n    else\n      return pw;\n  }\n# endif\n}\n#endif\n\n\nchar *msname(n)\n  char *n;\n/* Reduce all path components to MSDOS upper case 8.3 style names. */\n{\n  int c;                /* current character */\n  int f;                /* characters in current component */\n  char *p;              /* source pointer */\n  char *q;              /* destination pointer */\n\n  p = q = n;\n  f = 0;\n  while ((c = (unsigned char)*POSTINCSTR(p)) != 0)\n    if (c == ' ' || c == ':' || c == '\"' || c == '*' || c == '+' ||\n        c == ',' || c == ';' || c == '<' || c == '=' || c == '>' ||\n        c == '?' || c == '[' || c == ']' || c == '|')\n      continue;                         /* char is discarded */\n    else if (c == '/')\n    {\n      *POSTINCSTR(q) = (char)c;\n      f = 0;                            /* new component */\n    }\n#ifdef __human68k__\n    else if (ismbblead(c) && *p)\n    {\n      if (f == 7 || f == 11)\n        f++;\n      else if (*p && f < 12 && f != 8)\n      {\n        *q++ = c;\n        *q++ = *p++;\n        f += 2;\n      }\n    }\n#endif /* __human68k__ */\n    else if (c == '.')\n    {\n      if (f == 0)\n        continue;                       /* leading dots are discarded */\n      else if (f < 9)\n      {\n        *POSTINCSTR(q) = (char)c;\n        f = 9;                          /* now in file type */\n      }\n      else\n        f = 12;                         /* now just excess characters */\n    }\n    else\n      if (f < 12 && f != 8)\n      {\n        f += CLEN(p);                   /* do until end of name or type */\n        *POSTINCSTR(q) = (char)(to_up(c));\n      }\n  *q = 0;\n  return n;\n}\n\n#ifdef UNICODE_SUPPORT\nwchar_t *msnamew(nw)\n  wchar_t *nw;\n/* Reduce all path components to MSDOS upper case 8.3 style names. */\n{\n  wchar_t c;            /* current character */\n  int f;                /* characters in current component */\n  wchar_t *pw;          /* source pointer */\n  wchar_t *qw;          /* destination pointer */\n\n  pw = qw = nw;\n  f = 0;\n  while ((c = (unsigned char)*pw++) != 0)\n    if (c == ' ' || c == ':' || c == '\"' || c == '*' || c == '+' ||\n        c == ',' || c == ';' || c == '<' || c == '=' || c == '>' ||\n        c == '?' || c == '[' || c == ']' || c == '|')\n      continue;                         /* char is discarded */\n    else if (c == '/')\n    {\n      *qw++ = c;\n      f = 0;                            /* new component */\n    }\n#ifdef __human68k__\n    else if (ismbblead(c) && *pw)\n    {\n      if (f == 7 || f == 11)\n        f++;\n      else if (*pw && f < 12 && f != 8)\n      {\n        *qw++ = c;\n        *qw++ = *pw++;\n        f += 2;\n      }\n    }\n#endif /* __human68k__ */\n    else if (c == '.')\n    {\n      if (f == 0)\n        continue;                       /* leading dots are discarded */\n      else if (f < 9)\n      {\n        *qw++ = c;\n        f = 9;                          /* now in file type */\n      }\n      else\n        f = 12;                         /* now just excess characters */\n    }\n    else\n      if (f < 12 && f != 8)\n      {\n        f++;                            /* do until end of name or type */\n        *qw++ = towupper(c);\n      }\n  *qw = 0;\n  return nw;\n}\n#endif\n\n\nint proc_archive_name(n, caseflag)\n  char *n;             /* name to process */\n  int caseflag;         /* true to force case-sensitive match */\n/* Process a name or sh expression in existing archive to operate\n   on (or exclude).  Return an error code in the ZE_ class. */\n{\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0) {   /* if compressing stdin */\n    zipwarn(\"Cannot select stdin when selecting archive entries\", \"\");\n    return ZE_MISS;\n  }\n  else\n  {\n    /* Search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->oname);\n        m = 0;\n      }\n    }\n#ifdef UNICODE_SUPPORT\n    /* also check escaped Unicode names */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (z->zuname) {\n#ifdef WIN32\n        /* It seems something is lost in going from a listed\n           name from zip -su in a console window to using that\n           name in a command line.  This kluge may fix it\n           and just takes zuname, converts to oem (i.e. ouname),\n           then converts it back which ends up not the same as\n           started with.\n         */\n        char *zuname = z->wuname;\n#else\n        char *zuname = z->zuname;\n#endif\n        if (MATCH(p, zuname, caseflag))\n        {\n          z->mark = pcount ? filter(zuname, caseflag) : 1;\n          if (verbose) {\n              fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n                 z->mark ? \"in\" : \"ex\", z->oname);\n              fprintf(mesg, \"     Escaped Unicode:  %s\\n\",\n                 z->ouname);\n          }\n          m = 0;\n        }\n      }\n    }\n#endif\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n}\n\n\nint check_dup()\n/* Sort the found list and remove duplicates.\n   Return an error code in the ZE_ class. */\n{\n  struct flist far *f;          /* steps through found linked list */\n  extent j, k;                  /* indices for s */\n  struct flist far **s;         /* sorted table */\n  struct flist far **nodup;     /* sorted table without duplicates */\n\n  /* sort found list, remove duplicates */\n  if (fcount)\n  {\n    extent fl_size = fcount * sizeof(struct flist far *);\n    if ((fl_size / sizeof(struct flist far *)) != fcount ||\n        (s = (struct flist far **)malloc(fl_size)) == NULL)\n      return ZE_MEM;\n    for (j = 0, f = found; f != NULL; f = f->nxt)\n      s[j++] = f;\n    /* Check names as given (f->name) */\n    qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp);\n    for (k = j = fcount - 1; j > 0; j--)\n      if (strcmp(s[j - 1]->name, s[j]->name) == 0)\n        /* remove duplicate entry from list */\n        fexpel(s[j]);           /* fexpel() changes fcount */\n      else\n        /* copy valid entry into destination position */\n        s[k--] = s[j];\n    s[k] = s[0];                /* First entry is always valid */\n    nodup = &s[k];              /* Valid entries are at end of array s */\n\n    /* sort only valid items and check for unique internal names (f->iname) */\n    qsort((char *)nodup, fcount, sizeof(struct flist far *), fqcmpz);\n    for (j = 1; j < fcount; j++)\n      if (strcmp(nodup[j - 1]->iname, nodup[j]->iname) == 0)\n      {\n        char tempbuf[FNMAX+4081];\n\n        sprintf(errbuf, \"  first full name: %s\\n\", nodup[j - 1]->name);\n        sprintf(tempbuf, \" second full name: %s\\n\", nodup[j]->name);\n        strcat(errbuf, \"                     \");\n        strcat(errbuf, tempbuf);\n#ifdef EBCDIC\n        strtoebc(nodup[j]->iname, nodup[j]->iname);\n#endif\n        sprintf(tempbuf, \"name in zip file repeated: %s\", nodup[j]->iname);\n        strcat(errbuf, \"                     \");\n        strcat(errbuf, tempbuf);\n        if (pathput == 0) {\n          strcat(errbuf, \"\\n                     this may be a result of using -j\");\n        }\n#ifdef EBCDIC\n        strtoasc(nodup[j]->iname, nodup[j]->iname);\n#endif\n        zipwarn(errbuf, \"\");\n        return ZE_PARMS;\n      }\n    free((zvoid *)s);\n  }\n  return ZE_OK;\n}\n\nint filter(name, casesensitive)\n  char *name;\n  int casesensitive;\n  /* Scan the -R, -i and -x lists for matches to the given name.\n     Return TRUE if the name must be included, FALSE otherwise.\n     Give precedence to -x over -i and -R.\n     Note that if both R and i patterns are given then must\n     have a match for both.\n     This routine relies on the following global variables:\n       patterns                 array of match pattern structures\n       pcount                   total number of patterns\n       icount                   number of -i patterns\n       Rcount                   number of -R patterns\n     These data are set up by the command line parsing code.\n   */\n{\n   unsigned int n;\n   int slashes;\n   char *p, *q;\n   /* without -i patterns, every name matches the \"-i select rules\" */\n   int imatch = (icount == 0);\n   /* without -R patterns, every name matches the \"-R select rules\" */\n   int Rmatch = (Rcount == 0);\n\n   if (pcount == 0) return TRUE;\n\n   for (n = 0; n < pcount; n++) {\n      if (!patterns[n].zname[0])        /* it can happen... */\n         continue;\n      p = name;\n      switch (patterns[n].select) {\n       case 'R':\n         if (Rmatch)\n            /* one -R match is sufficient, skip this pattern */\n            continue;\n         /* With -R patterns, if the pattern has N path components (that is,\n            N-1 slashes), then we test only the last N components of name.\n          */\n         slashes = 0;\n         for (q = patterns[n].zname; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q))\n            slashes++;\n         /* The name may have M path components (M-1 slashes) */\n         for (q = p; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q))\n            slashes--;\n         /* Now, \"slashes\" contains the difference \"N-M\" between the number\n            of path components in the pattern (N) and in the name (M).\n          */\n         if (slashes < 0)\n            /* We found \"M > N\"\n                --> skip the first (M-N) path components of the name.\n             */\n            for (q = p; (q = MBSCHR(q, '/')) != NULL; MB_NEXTCHAR(q))\n               if (++slashes == 0) {\n                  p = q + 1;    /* q points at '/', mblen(\"/\") is 1 */\n                  break;\n               }\n         break;\n       case 'i':\n         if (imatch)\n            /* one -i match is sufficient, skip this pattern */\n            continue;\n         break;\n      }\n      if (MATCH(patterns[n].zname, p, casesensitive)) {\n         switch (patterns[n].select) {\n            case 'x':\n               /* The -x match takes precedence over everything else */\n               return FALSE;\n            case 'R':\n               Rmatch = TRUE;\n               break;\n            default:\n               /* this must be a type -i match */\n               imatch = TRUE;\n               break;\n         }\n      }\n   }\n   return imatch && Rmatch;\n}\n\n\n#ifdef UNICODE_SUPPORT\n# ifdef WIN32\n\nint newnamew(namew, isdir, casesensitive)\n  wchar_t *namew;             /* name to add (or exclude) */\n  int  isdir;                 /* true for a directory */\n  int  casesensitive;         /* true for case-sensitive matching */\n/* Add (or exclude) the name of an existing disk file.  Return an error\n   code in the ZE_ class. */\n{\n  wchar_t *inamew = NULL;     /* internal name */\n  wchar_t *znamew = NULL;     /* external version of iname */\n  wchar_t *undosmw = NULL;    /* zname version with \"-j\" and \"-k\" options disabled */\n  char *oname = NULL;         /* iname converted for display */\n  char *name = NULL;\n  char *iname = NULL;\n  char *zname = NULL;\n  char *zuname = NULL;\n  char *undosm = NULL;\n  struct flist far *f;        /* where in found, or new found entry */\n  struct zlist far *z;        /* where in zfiles (if found) */\n  int dosflag;\n\n  /* Scanning files ...\n   *\n   * After 5 seconds output Scanning files...\n   * then a dot every 2 seconds\n   */\n  if (noisy) {\n    /* If find files then output message after delay */\n    if (scan_count == 0) {\n      time_t current = time(NULL);\n      scan_start = current;\n    }\n    scan_count++;\n    if (scan_count % 100 == 0) {\n      time_t current = time(NULL);\n\n      if (current - scan_start > scan_delay) {\n        if (scan_last == 0) {\n          zipmessage_nl(\"Scanning files \", 0);\n          scan_last = current;\n        }\n        if (current - scan_last > scan_dot_time) {\n          scan_last = current;\n          fprintf(mesg, \".\");\n          fflush(mesg);\n        }\n      }\n    }\n  }\n\n  /* Search for name in zip file.  If there, mark it, else add to\n     list of new names to do (or remove from that list). */\n  if ((inamew = ex2inw(namew, isdir, &dosflag)) == NULL)\n    return ZE_MEM;\n\n  /* Discard directory names with zip -rj */\n  if (*inamew == (wchar_t)'\\0') {\n\n /* If extensions needs to be swapped, we will have empty directory names\n    instead of the original directory. For example, zipping 'c.', 'c.main'\n    should zip only 'main.c' while 'c.' will be converted to '\\0' by ex2in. */\n\n    if (pathput && !recurse) error(\"empty name without -j or -r\");\n    free((zvoid *)inamew);\n    return ZE_OK;\n  }\n\n  if (dosflag || !pathput) {\n    int save_dosify = dosify, save_pathput = pathput;\n    dosify = 0;\n    pathput = 1;\n    /* zname is temporarly mis-used as \"undosmode\" iname pointer */\n    if ((znamew = ex2inw(namew, isdir, NULL)) != NULL) {\n      undosmw = in2exw(znamew);\n      free(znamew);\n    }\n    dosify = save_dosify;\n    pathput = save_pathput;\n  }\n  if ((znamew = in2exw(inamew)) == NULL)\n    return ZE_MEM;\n\n  /* Convert names from wchar_t to char */\n\n  name = wchar_to_local_string(namew);\n  iname = wchar_to_local_string(inamew);\n  zname = wchar_to_local_string(znamew);\n\n  oname = local_to_display_string(zname);\n\n  zuname = wchar_to_local_string(znamew);\n\n  if (undosmw == NULL)\n    undosmw = znamew;\n  undosm = wchar_to_local_string(undosmw);\n\n  if ((z = zsearch(zuname)) != NULL) {\n    if (pcount && !filter(undosm, casesensitive)) {\n      /* Do not clear z->mark if \"exclude\", because, when \"dosify || !pathput\"\n       * is in effect, two files with different filter options may hit the\n       * same z entry.\n       */\n      if (verbose)\n        fprintf(mesg, \"excluding %s\\n\", oname);\n    } else {\n      z->mark = 1;\n      if ((z->name = malloc(strlen(name) + 1 + PAD)) == NULL) {\n        if (undosmw != znamew)\n          free(undosmw);\n        if (undosm) free(undosm);\n        if (inamew) free(inamew);\n        if (znamew) free(znamew);\n        if (name) free(name);\n        if (iname) free(iname);\n        if (zname) free(zname);\n        if (oname) free(oname);\n        if (zuname) free(zuname);\n        return ZE_MEM;\n      }\n      strcpy(z->name, name);\n      z->oname = oname;\n      oname = NULL;\n      z->dosflag = dosflag;\n\n#ifdef FORCE_NEWNAME\n      free((zvoid *)(z->iname));\n      z->iname = iname;\n      iname = NULL;\n#else\n      /* Better keep the old name. Useful when updating on MSDOS a zip file\n       * made on Unix.\n       */\n#endif /* ? FORCE_NEWNAME */\n    }\n\n    if ((z->namew = (wchar_t *)malloc((wcslen(namew) + 1) * sizeof(wchar_t))) == NULL) {\n      if (undosmw != znamew)\n        free(undosmw);\n      if (undosm) free(undosm);\n      if (inamew) free(inamew);\n      if (znamew) free(znamew);\n      if (name) free(name);\n      if (iname) free(iname);\n      if (zname) free(zname);\n      if (oname) free(oname);\n      if (zuname) free(zuname);\n      return ZE_MEM;\n    }\n    wcscpy(z->namew, namew);\n    z->inamew = inamew;\n    inamew = NULL;\n    z->znamew = znamew;\n    znamew = NULL;\n    z->uname = wchar_to_utf8_string(z->inamew);\n    if (name == label) {\n       label = z->name;\n    }\n  } else if (pcount == 0 || filter(undosm, casesensitive)) {\n\n    /* Check that we are not adding the zip file to itself. This\n     * catches cases like \"zip -m foo ../dir/foo.zip\".\n     */\n/* Version of stat() for CMS/MVS isn't complete enough to see if       */\n/* files match.  Just let ZIP.C compare the filenames.  That's good    */\n/* enough for CMS anyway since there aren't paths to worry about.      */\n    zw_stat statbw;     /* need for wide stat */\n    wchar_t *zipfilew = local_to_wchar_string(zipfile);\n\n    if (zipstate == -1)\n       zipstate = strcmp(zipfile, \"-\") != 0 &&\n                   zwstat(zipfilew, &zipstatbw) == 0;\n    free(zipfilew);\n\n    if (zipstate == 1 && (statbw = zipstatbw, zwstat(namew, &statbw) == 0\n      && zipstatbw.st_mode  == statbw.st_mode\n      && zipstatbw.st_ino   == statbw.st_ino\n      && zipstatbw.st_dev   == statbw.st_dev\n      && zipstatbw.st_uid   == statbw.st_uid\n      && zipstatbw.st_gid   == statbw.st_gid\n      && zipstatbw.st_size  == statbw.st_size\n      && zipstatbw.st_mtime == statbw.st_mtime\n      && zipstatbw.st_ctime == statbw.st_ctime)) {\n      /* Don't compare a_time since we are reading the file */\n        if (verbose)\n          fprintf(mesg, \"file matches zip file -- skipping\\n\");\n        if (undosmw != znamew)\n          free(undosmw);\n        if (undosm) free(undosm);\n        if (inamew) free(inamew);\n        if (znamew) free(znamew);\n        if (name) free(name);\n        if (iname) free(iname);\n        if (zname) free(zname);\n        if (oname) free(oname);\n        if (zuname) free(zuname);\n        return ZE_OK;\n    }\n\n    /* allocate space and add to list */\n    if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||\n        fcount + 1 < fcount ||\n        (f->name = malloc(strlen(name) + 1 + PAD)) == NULL)\n    {\n      if (f != NULL)\n        farfree((zvoid far *)f);\n      if (undosmw != znamew)\n        free(undosmw);\n      if (undosm) free(undosm);\n      if (inamew) free(inamew);\n      if (znamew) free(znamew);\n      if (name) free(name);\n      if (iname) free(iname);\n      if (zname) free(zname);\n      if (oname) free(oname);\n      if (zuname) free(zuname);\n      return ZE_MEM;\n    }\n    if (undosmw != znamew)\n      free((zvoid *)undosmw);\n    strcpy(f->name, name);\n    f->iname = iname;\n    iname = NULL;\n    f->zname = zname;\n    zname = NULL;\n    /* Unicode */\n    if ((f->namew = (wchar_t *)malloc((wcslen(namew) + 1) * sizeof(wchar_t))) == NULL) {\n      if (f != NULL)\n        farfree((zvoid far *)f);\n      if (undosmw != znamew)\n        free(undosmw);\n      if (undosm) free(undosm);\n      if (inamew) free(inamew);\n      if (znamew) free(znamew);\n      if (name) free(name);\n      if (iname) free(iname);\n      if (zname) free(zname);\n      if (oname) free(oname);\n      if (zuname) free(zuname);\n      return ZE_MEM;\n    }\n    wcscpy(f->namew, namew);\n    f->znamew = znamew;\n    znamew = NULL;\n    f->uname = wchar_to_utf8_string(inamew);\n    f->inamew = inamew;\n    inamew = NULL;\n    f->oname = oname;\n    oname = NULL;\n    f->dosflag = dosflag;\n    *fnxt = f;\n    f->lst = fnxt;\n    f->nxt = NULL;\n    fnxt = &f->nxt;\n    fcount++;\n    if (name == label) {\n      label = f->name;\n    }\n  }\n  if (undosm) free(undosm);\n  if (inamew) free(inamew);\n  if (znamew) free(znamew);\n  if (name) free(name);\n  if (iname) free(iname);\n  if (zname) free(zname);\n  if (oname) free(oname);\n  if (zuname) free(zuname);\n  return ZE_OK;\n}\n\n# endif\n#endif\n\nint newname(name, isdir, casesensitive)\n  char *name;           /* name to add (or exclude) */\n  int  isdir;           /* true for a directory */\n  int  casesensitive;   /* true for case-sensitive matching */\n/* Add (or exclude) the name of an existing disk file.  Return an error\n   code in the ZE_ class. */\n{\n  char *iname, *zname;  /* internal name, external version of iname */\n  char *undosm;         /* zname version with \"-j\" and \"-k\" options disabled */\n  char *oname;          /* iname converted for display */\n  struct flist far *f;  /* where in found, or new found entry */\n  struct zlist far *z;  /* where in zfiles (if found) */\n  int dosflag;\n\n  /* Scanning files ...\n   *\n   * After 5 seconds output Scanning files...\n   * then a dot every 2 seconds\n   */\n  if (noisy) {\n    /* If find files then output message after delay */\n    if (scan_count == 0) {\n      time_t current = time(NULL);\n      scan_start = current;\n    }\n    scan_count++;\n    if (scan_count % 100 == 0) {\n      time_t current = time(NULL);\n\n      if (current - scan_start > scan_delay) {\n        if (scan_last == 0) {\n          zipmessage_nl(\"Scanning files \", 0);\n          scan_last = current;\n        }\n        if (current - scan_last > scan_dot_time) {\n          scan_last = current;\n          fprintf(mesg, \".\");\n          fflush(mesg);\n        }\n      }\n    }\n  }\n\n  /* Search for name in zip file.  If there, mark it, else add to\n     list of new names to do (or remove from that list). */\n  if ((iname = ex2in(name, isdir, &dosflag)) == NULL)\n    return ZE_MEM;\n\n  /* Discard directory names with zip -rj */\n  if (*iname == '\\0') {\n#ifndef AMIGA\n/* A null string is a legitimate external directory name in AmigaDOS; also,\n * a command like \"zip -r zipfile FOO:\" produces an empty internal name.\n */\n# ifndef RISCOS\n /* If extensions needs to be swapped, we will have empty directory names\n    instead of the original directory. For example, zipping 'c.', 'c.main'\n    should zip only 'main.c' while 'c.' will be converted to '\\0' by ex2in. */\n\n    if (pathput && !recurse) error(\"empty name without -j or -r\");\n\n# endif /* !RISCOS */\n#endif /* !AMIGA */\n    free((zvoid *)iname);\n    return ZE_OK;\n  }\n  undosm = NULL;\n  if (dosflag || !pathput) {\n    int save_dosify = dosify, save_pathput = pathput;\n    dosify = 0;\n    pathput = 1;\n    /* zname is temporarly mis-used as \"undosmode\" iname pointer */\n    if ((zname = ex2in(name, isdir, NULL)) != NULL) {\n      undosm = in2ex(zname);\n      free(zname);\n    }\n    dosify = save_dosify;\n    pathput = save_pathput;\n  }\n  if ((zname = in2ex(iname)) == NULL)\n    return ZE_MEM;\n#ifdef UNICODE_SUPPORT\n  /* Convert name to display or OEM name */\n  oname = local_to_display_string(iname);\n#else\n  if ((oname = malloc(strlen(zname) + 1)) == NULL)\n    return ZE_MEM;\n  strcpy(oname, zname);\n#endif\n  if (undosm == NULL)\n    undosm = zname;\n  if ((z = zsearch(zname)) != NULL) {\n    if (pcount && !filter(undosm, casesensitive)) {\n      /* Do not clear z->mark if \"exclude\", because, when \"dosify || !pathput\"\n       * is in effect, two files with different filter options may hit the\n       * same z entry.\n       */\n      if (verbose)\n        fprintf(mesg, \"excluding %s\\n\", oname);\n      free((zvoid *)iname);\n      free((zvoid *)zname);\n    } else {\n      z->mark = 1;\n      if ((z->name = malloc(strlen(name) + 1 + PAD)) == NULL) {\n        if (undosm != zname)\n          free((zvoid *)undosm);\n        free((zvoid *)iname);\n        free((zvoid *)zname);\n        return ZE_MEM;\n      }\n      strcpy(z->name, name);\n      z->oname = oname;\n      z->dosflag = dosflag;\n\n#ifdef FORCE_NEWNAME\n      free((zvoid *)(z->iname));\n      z->iname = iname;\n#else\n      /* Better keep the old name. Useful when updating on MSDOS a zip file\n       * made on Unix.\n       */\n      free((zvoid *)iname);\n      free((zvoid *)zname);\n#endif /* ? FORCE_NEWNAME */\n    }\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n    z->namew = NULL;\n    z->inamew = NULL;\n    z->znamew = NULL;\n#endif\n    if (name == label) {\n       label = z->name;\n    }\n  } else if (pcount == 0 || filter(undosm, casesensitive)) {\n\n    /* Check that we are not adding the zip file to itself. This\n     * catches cases like \"zip -m foo ../dir/foo.zip\".\n     */\n#ifndef CMS_MVS\n/* Version of stat() for CMS/MVS isn't complete enough to see if       */\n/* files match.  Just let ZIP.C compare the filenames.  That's good    */\n/* enough for CMS anyway since there aren't paths to worry about.      */\n    z_stat statb;      /* now use structure z_stat and function zstat globally 7/24/04 EG */\n\n    if (zipstate == -1)\n       zipstate = strcmp(zipfile, \"-\") != 0 &&\n                   zstat(zipfile, &zipstatb) == 0;\n\n    if (zipstate == 1 && (statb = zipstatb, zstat(name, &statb) == 0\n      && zipstatb.st_mode  == statb.st_mode\n#ifdef VMS\n      && memcmp(zipstatb.st_ino, statb.st_ino, sizeof(statb.st_ino)) == 0\n      && strcmp(zipstatb.st_dev, statb.st_dev) == 0\n      && zipstatb.st_uid   == statb.st_uid\n#else /* !VMS */\n      && zipstatb.st_ino   == statb.st_ino\n      && zipstatb.st_dev   == statb.st_dev\n      && zipstatb.st_uid   == statb.st_uid\n      && zipstatb.st_gid   == statb.st_gid\n#endif /* ?VMS */\n      && zipstatb.st_size  == statb.st_size\n      && zipstatb.st_mtime == statb.st_mtime\n      && zipstatb.st_ctime == statb.st_ctime)) {\n      /* Don't compare a_time since we are reading the file */\n         if (verbose)\n           fprintf(mesg, \"file matches zip file -- skipping\\n\");\n         if (undosm != zname)\n           free((zvoid *)zname);\n         if (undosm != iname)\n           free((zvoid *)undosm);\n         free((zvoid *)iname);\n         free(oname);\n         return ZE_OK;\n    }\n#endif  /* CMS_MVS */\n\n    /* allocate space and add to list */\n    if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||\n        fcount + 1 < fcount ||\n        (f->name = malloc(strlen(name) + 1 + PAD)) == NULL)\n    {\n      if (f != NULL)\n        farfree((zvoid far *)f);\n      if (undosm != zname)\n        free((zvoid *)undosm);\n      free((zvoid *)iname);\n      free((zvoid *)zname);\n      free(oname);\n      return ZE_MEM;\n    }\n    strcpy(f->name, name);\n    f->iname = iname;\n    f->zname = zname;\n#ifdef UNICODE_SUPPORT\n    /* Unicode */\n    f->uname = local_to_utf8_string(iname);\n#ifdef WIN32\n    f->namew = NULL;\n    f->inamew = NULL;\n    f->znamew = NULL;\n    if (strcmp(f->name, \"-\") == 0) {\n      f->namew = local_to_wchar_string(f->name);\n    }\n#endif\n\n#endif\n    f->oname = oname;\n    f->dosflag = dosflag;\n\n    *fnxt = f;\n    f->lst = fnxt;\n    f->nxt = NULL;\n    fnxt = &f->nxt;\n    fcount++;\n    if (name == label) {\n      label = f->name;\n    }\n  }\n  if (undosm != zname)\n    free((zvoid *)undosm);\n  return ZE_OK;\n}\n\nulg dostime(y, n, d, h, m, s)\nint y;                  /* year */\nint n;                  /* month */\nint d;                  /* day */\nint h;                  /* hour */\nint m;                  /* minute */\nint s;                  /* second */\n/* Convert the date y/n/d and time h:m:s to a four byte DOS date and\n   time (date in high two bytes, time in low two bytes allowing magnitude\n   comparison). */\n{\n  return y < 1980 ? DOSTIME_MINIMUM /* dostime(1980, 1, 1, 0, 0, 0) */ :\n        (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) |\n        ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1);\n}\n\n\nulg unix2dostime(t)\ntime_t *t;              /* unix time to convert */\n/* Return the Unix time t in DOS format, rounded up to the next two\n   second boundary. */\n{\n  time_t t_even;\n  struct tm *s;         /* result of localtime() */\n\n  t_even = (time_t)(((unsigned long)(*t) + 1) & (~1));\n                                /* Round up to even seconds. */\n  s = localtime(&t_even);       /* Use local time since MSDOS does. */\n  if (s == (struct tm *)NULL) {\n      /* time conversion error; use current time as emergency value\n         (assuming that localtime() does at least accept this value!) */\n      t_even = (time_t)(((unsigned long)time(NULL) + 1) & (~1));\n      s = localtime(&t_even);\n  }\n  return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,\n                 s->tm_hour, s->tm_min, s->tm_sec);\n}\n\nint issymlnk(a)\nulg a;                  /* Attributes returned by filetime() */\n/* Return true if the attributes are those of a symbolic link */\n{\n#ifndef QDOS\n#ifdef S_IFLNK\n#ifdef __human68k__\n  int *_dos_importlnenv(void);\n\n  if (_dos_importlnenv() == NULL)\n    return 0;\n#endif\n  return ((a >> 16) & S_IFMT) == S_IFLNK;\n#else /* !S_IFLNK */\n  return (int)a & 0;    /* avoid warning on unused parameter */\n#endif /* ?S_IFLNK */\n#else\n  return 0;\n#endif\n}\n\n#endif /* !UTIL */\n\n\n#if (!defined(UTIL) && !defined(ZP_NEED_GEN_D2U_TIME))\n   /* There is no need for dos2unixtime() in the ZipUtils' code. */\n#  define ZP_NEED_GEN_D2U_TIME\n#endif\n#if ((defined(OS2) || defined(VMS)) && defined(ZP_NEED_GEN_D2U_TIME))\n   /* OS/2 and VMS use a special solution to handle time-stams of files. */\n#  undef ZP_NEED_GEN_D2U_TIME\n#endif\n#if (defined(W32_STATROOT_FIX) && !defined(ZP_NEED_GEN_D2U_TIME))\n   /* The Win32 stat()-bandaid to fix stat'ing root directories needs\n    * dos2unixtime() to calculate the time-stamps. */\n#  define ZP_NEED_GEN_D2U_TIME\n#endif\n\n#ifdef ZP_NEED_GEN_D2U_TIME\n\ntime_t dos2unixtime(dostime)\nulg dostime;            /* DOS time to convert */\n/* Return the Unix time_t value (GMT/UTC time) for the DOS format (local)\n * time dostime, where dostime is a four byte value (date in most significant\n * word, time in least significant word), see dostime() function.\n */\n{\n  struct tm *t;         /* argument for mktime() */\n  ZCONST time_t clock = time(NULL);\n\n  t = localtime(&clock);\n  t->tm_isdst = -1;     /* let mktime() determine if DST is in effect */\n  /* Convert DOS time to UNIX time_t format */\n  t->tm_sec  = (((int)dostime) <<  1) & 0x3e;\n  t->tm_min  = (((int)dostime) >>  5) & 0x3f;\n  t->tm_hour = (((int)dostime) >> 11) & 0x1f;\n  t->tm_mday = (int)(dostime >> 16) & 0x1f;\n  t->tm_mon  = ((int)(dostime >> 21) & 0x0f) - 1;\n  t->tm_year = ((int)(dostime >> 25) & 0x7f) + 80;\n\n  return mktime(t);\n}\n\n#undef ZP_NEED_GEN_D2U_TIME\n#endif /* ZP_NEED_GEN_D2U_TIME */\n\n\n#ifndef MACOS\nint destroy(f)\n  char *f;             /* file to delete */\n/* Delete the file *f, returning non-zero on failure. */\n{\n  return unlink(f);\n}\n\n\nint replace(d, s)\nchar *d, *s;            /* destination and source file names */\n/* Replace file *d by file *s, removing the old *s.  Return an error code\n   in the ZE_ class. This function need not preserve the file attributes,\n   this will be done by setfileattr() later.\n */\n{\n  z_stat t;         /* results of stat() */\n#if defined(CMS_MVS)\n  /* cmsmvs.h defines FOPW_TEMP as memory(hiperspace).  Since memory is\n   * lost at end of run, always do copy instead of rename.\n   */\n  int copy = 1;\n#else\n  int copy = 0;\n#endif\n  int d_exists;\n\n#if defined(VMS) || defined(CMS_MVS)\n  /* stat() is broken on VMS remote files (accessed through Decnet).\n   * This patch allows creation of remote zip files, but is not sufficient\n   * to update them or compress remote files */\n  unlink(d);\n#else /* !(VMS || CMS_MVS) */\n  d_exists = (LSTAT(d, &t) == 0);\n  if (d_exists)\n  {\n    /*\n     * respect existing soft and hard links!\n     */\n    if (t.st_nlink > 1\n# ifdef S_IFLNK\n        || (t.st_mode & S_IFMT) == S_IFLNK\n# endif\n        )\n       copy = 1;\n    else if (unlink(d))\n       return ZE_CREAT;                 /* Can't erase zip file--give up */\n  }\n#endif /* ?(VMS || CMS_MVS) */\n#ifndef CMS_MVS\n  if (!copy) {\n      if (rename(s, d)) {               /* Just move s on top of d */\n          copy = 1;                     /* failed ? */\n#if !defined(VMS) && !defined(ATARI) && !defined(AZTEC_C)\n#if !defined(CMS_MVS) && !defined(RISCOS) && !defined(QDOS)\n    /* For VMS, ATARI, AMIGA Aztec, VM_CMS, MVS, RISCOS,\n       always assume that failure is EXDEV */\n          if (errno != EXDEV\n#  ifdef THEOS\n           && errno != EEXIST\n#  else\n#    ifdef ENOTSAM\n           && errno != ENOTSAM /* Used at least on Turbo C */\n#    endif\n#  endif\n              ) return ZE_CREAT;\n#endif /* !CMS_MVS && !RISCOS */\n#endif /* !VMS && !ATARI && !AZTEC_C */\n      }\n  }\n#endif /* !CMS_MVS */\n\n  if (copy) {\n    FILE *f, *g;        /* source and destination files */\n    int r;              /* temporary variable */\n\n#ifdef RISCOS\n    if (SWI_OS_FSControl_26(s,d,0xA1)!=NULL) {\n#endif\n\n    /* Use zfopen for almost all opens where fopen is used.  For\n       most OS that support large files we use the 64-bit file\n       environment and zfopen maps to fopen, but this allows\n       tweeking ports that don't do that.  7/24/04 */\n    if ((f = zfopen(s, FOPR)) == NULL) {\n      fprintf(mesg,\" replace: can't open %s\\n\", s);\n      return ZE_TEMP;\n    }\n    if ((g = zfopen(d, FOPW)) == NULL)\n    {\n      fclose(f);\n      return ZE_CREAT;\n    }\n\n    r = fcopy(f, g, (ulg)-1L);\n    fclose(f);\n    if (fclose(g) || r != ZE_OK)\n    {\n      unlink(d);\n      return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE;\n    }\n    unlink(s);\n#ifdef RISCOS\n    }\n#endif\n  }\n  return ZE_OK;\n}\n#endif /* !MACOS */\n\n\nint getfileattr(f)\nchar *f;                /* file path */\n/* Return the file attributes for file f or 0 if failure */\n{\n#ifdef __human68k__\n  struct _filbuf buf;\n\n  return _dos_files(&buf, f, 0xff) < 0 ? 0x20 : buf.atr;\n#else\n  z_stat s;\n\n  return SSTAT(f, &s) == 0 ? (int) s.st_mode : 0;\n#endif\n}\n\n\nint setfileattr(f, a)\nchar *f;                /* file path */\nint a;                  /* attributes returned by getfileattr() */\n/* Give the file f the attributes a, return non-zero on failure */\n{\n#if defined(TOPS20) || defined (CMS_MVS)\n  return 0;\n#else\n#ifdef __human68k__\n  return _dos_chmod(f, a) < 0 ? -1 : 0;\n#else\n  return chmod(f, a);\n#endif\n#endif\n}\n\n\n/* tempname */\n\n#ifndef VMS /* VMS-specific function is in VMS.C. */\n\nchar *tempname(zip)\n  char *zip;              /* path name of zip file to generate temp name for */\n\n/* Return a temporary file name in its own malloc'ed space, using tempath. */\n{\n  char *t = zip;   /* malloc'ed space for name (use zip to avoid warning) */\n\n# ifdef CMS_MVS\n  if ((t = malloc(strlen(tempath) + L_tmpnam + 2)) == NULL)\n    return NULL;\n\n#  ifdef VM_CMS\n  tmpnam(t);\n  /* Remove filemode and replace with tempath, if any. */\n  /* Otherwise A-disk is used by default */\n  *(strrchr(t, ' ')+1) = '\\0';\n  if (tempath!=NULL)\n     strcat(t, tempath);\n  return t;\n#  else   /* !VM_CMS */\n  /* For MVS */\n  tmpnam(t);\n  if (tempath != NULL)\n  {\n    int l1 = strlen(t);\n    char *dot;\n    if (*t == '\\'' && *(t+l1-1) == '\\'' && (dot = strchr(t, '.')))\n    {\n      /* MVS and not OE.  tmpnam() returns quoted string of 5 qualifiers.\n       * First is HLQ, rest are timestamps.  User can only replace HLQ.\n       */\n      int l2 = strlen(tempath);\n      if (strchr(tempath, '.') || l2 < 1 || l2 > 8)\n        ziperr(ZE_PARMS, \"On MVS and not OE, tempath (-b) can only be HLQ\");\n      memmove(t+1+l2, dot, l1+1-(dot-t));  /* shift dot ready for new hlq */\n      memcpy(t+1, tempath, l2);            /* insert new hlq */\n    }\n    else\n    {\n      /* MVS and probably OE.  tmpnam() returns filename based on TMPDIR,\n       * no point in even attempting to change it.  User should modify TMPDIR\n       * instead.\n       */\n      zipwarn(\"MVS, assumed to be OE, change TMPDIR instead of option -b: \",\n              tempath);\n    }\n  }\n  return t;\n#  endif  /* !VM_CMS */\n\n# else /* !CMS_MVS */\n\n#  ifdef TANDEM\n  char cur_subvol [FILENAME_MAX];\n  char temp_subvol [FILENAME_MAX];\n  char *zptr;\n  char *ptr;\n  char *cptr = &cur_subvol[0];\n  char *tptr = &temp_subvol[0];\n  short err;\n  FILE *tempf;\n  int attempts;\n\n  t = (char *)malloc(NAMELEN); /* malloc here as you cannot free */\n                               /* tmpnam allocated storage later */\n\n  zptr = strrchr(zip, TANDEM_DELIMITER);\n\n  if (zptr != NULL) {\n    /* ZIP file specifies a Subvol so make temp file there so it can just\n       be renamed at end */\n\n    *tptr = *cptr = '\\0';\n    strcat(cptr, getenv(\"DEFAULTS\"));\n\n    strncat(tptr, zip, _min(FILENAME_MAX, (zptr - zip)) ); /* temp subvol */\n    strncat(t, zip, _min(NAMELEN, ((zptr - zip) + 1)) );   /* temp stem   */\n\n    err = chvol(tptr);\n    ptr = t + strlen(t);  /* point to end of stem */\n  }\n  else\n    ptr = t;\n\n  /* If two zips are running in same subvol then we can get contention problems\n     with the temporary filename.  As a work around we attempt to create\n     the file here, and if it already exists we get a new temporary name */\n\n  attempts = 0;\n  do {\n    attempts++;\n    tmpnam(ptr);  /* Add filename */\n    tempf = zfopen(ptr, FOPW_TMP);    /* Attempt to create file */\n  } while (tempf == NULL && attempts < 100);\n\n  if (attempts >= 100) {\n    ziperr(ZE_TEMP, \"Could not get unique temp file name\");\n  }\n\n  fclose(tempf);\n\n  if (zptr != NULL) {\n    err = chvol(cptr);  /* Put ourself back to where we came in */\n  }\n\n  return t;\n\n#  else /* !CMS_MVS && !TANDEM */\n/*\n * Do something with TMPDIR, TMP, TEMP ????\n */\n  if (tempath != NULL)\n  {\n    if ((t = malloc(strlen(tempath) + 12)) == NULL)\n      return NULL;\n    strcpy(t, tempath);\n\n#   if (!defined(VMS) && !defined(TOPS20))\n#    ifdef MSDOS\n    {\n      char c = (char)lastchar(t);\n      if (c != '/' && c != ':' && c != '\\\\')\n        strcat(t, \"/\");\n    }\n#    else\n\n#     ifdef AMIGA\n    {\n      char c = (char)lastchar(t);\n      if (c != '/' && c != ':')\n        strcat(t, \"/\");\n    }\n#     else /* !AMIGA */\n#      ifdef RISCOS\n    if (lastchar(t) != '.')\n      strcat(t, \".\");\n#      else /* !RISCOS */\n\n#       ifdef QDOS\n    if (lastchar(t) != '_')\n      strcat(t, \"_\");\n#       else\n    if (lastchar(t) != '/')\n      strcat(t, \"/\");\n#       endif /* ?QDOS */\n#      endif /* ?RISCOS */\n#     endif  /* ?AMIGA */\n#    endif /* ?MSDOS */\n#   endif /* !VMS && !TOPS20 */\n  }\n  else\n  {\n    if ((t = malloc(12)) == NULL)\n      return NULL;\n    *t = 0;\n  }\n#   ifdef NO_MKTEMP\n  {\n    char *p = t + strlen(t);\n    sprintf(p, \"%08lx\", (ulg)time(NULL));\n    return t;\n  }\n#   else\n  strcat(t, \"ziXXXXXX\"); /* must use lowercase for Linux dos file system */\n#     if defined(UNIX) && !defined(NO_MKSTEMP)\n  /* tempname should not be called */\n  return t;\n#     else\n  return mktemp(t);\n#     endif\n#   endif /* NO_MKTEMP */\n#  endif /* TANDEM */\n# endif /* CMS_MVS */\n}\n#endif /* !VMS */\n\nint fcopy(f, g, n)\n  FILE *f, *g;            /* source and destination files */\n  /* now use uzoff_t for all file sizes 5/14/05 CS */\n  uzoff_t n;               /* number of bytes to copy or -1 for all */\n/* Copy n bytes from file *f to file *g, or until EOF if (zoff_t)n == -1.\n   Return an error code in the ZE_ class. */\n{\n  char *b;              /* malloc'ed buffer for copying */\n  extent k;             /* result of fread() */\n  uzoff_t m;            /* bytes copied so far */\n\n  if ((b = malloc(CBSZ)) == NULL)\n    return ZE_MEM;\n  m = 0;\n  while (n == (uzoff_t)(-1L) || m < n)\n  {\n    if ((k = fread(b, 1, n == (uzoff_t)(-1) ?\n                   CBSZ : (n - m < CBSZ ? (extent)(n - m) : CBSZ), f)) == 0)\n    {\n      if (ferror(f))\n      {\n        free((zvoid *)b);\n        return ZE_READ;\n      }\n      else\n        break;\n    }\n    if (fwrite(b, 1, k, g) != k)\n    {\n      free((zvoid *)b);\n      fprintf(mesg,\" fcopy: write error\\n\");\n      return ZE_TEMP;\n    }\n    m += k;\n  }\n  free((zvoid *)b);\n  return ZE_OK;\n}\n\n\n/* from zipfile.c */\n\n#ifdef THEOS\n /* Macros cause stack overflow in compiler */\n ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }\n ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }\n#else /* !THEOS */\n /* Macros for converting integers in little-endian to machine format */\n# define SH(a) ((ush)(((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8)))\n# define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))\n# ifdef ZIP64_SUPPORT           /* zip64 support 08/31/2003 R.Nausedat */\n#  define LLG(a) ((zoff_t)LG(a) | ((zoff_t)LG((a)+4) << 32))\n# endif\n#endif /* ?THEOS */\n\n\n/* always copies from global in_file to global output file y */\nint bfcopy(n)\n  /* now use uzoff_t for all file sizes 5/14/05 CS */\n  uzoff_t n;               /* number of bytes to copy or -1 for all */\n/* Copy n bytes from in_file to out_file, or until EOF if (zoff_t)n == -1.\n\n   Normally we have the compressed size from either the central directory\n   entry or the local header.\n\n   If n != -1 and EOF, close current split and open next and continue\n   copying.\n\n   If n == -2, copy until find the extended header (data descriptor).  Only\n   used for -FF when no size available.\n\n   If fix == 1 calculate CRC of input entry and verify matches.\n\n   If fix == 2 and this entry using data descriptor keep a sliding\n   window in the buffer for looking for signature.\n\n   Return an error code in the ZE_ class. */\n{\n  char *b;              /* malloc'ed buffer for copying */\n  extent k;             /* result of fread() */\n  uzoff_t m;            /* bytes copied so far */\n  extent brd;           /* bytes to read */\n  zoff_t data_start = 0;\n  zoff_t des_start = 0;\n  char *split_path;\n  extent kk;\n  int i;\n  char sbuf[4];         /* buffer for sliding signature window for fix = 2 */\n  int des = 0;          /* this entry has data descriptor to find */\n\n  if ((b = malloc(CBSZ)) == NULL)\n    return ZE_MEM;\n\n  if (copy_only && !display_globaldots) {\n    /* initialize dot count */\n    dot_count = -1;\n  }\n\n  if (fix == 2 && n == (uzoff_t) -2) {\n    data_start = zftello(in_file);\n    for (kk = 0; kk < 4; kk++)\n      sbuf[kk] = 0;\n    des = 1;\n  }\n\n  des_good = 0;\n\n  m = 0;\n  while (des || n == (uzoff_t)(-1L) || m < n)\n  {\n    if (des || n == (uzoff_t)(-1))\n      brd = CBSZ;\n    else\n      brd = (n - m < CBSZ ? (extent)(n - m) : CBSZ);\n\n    des_start = zftello(in_file);\n\n    if ((k = fread(b, 1, brd, in_file)) == 0)\n    {\n      if (fix == 2 && k < brd) {\n        free((zvoid *)b);\n        return ZE_READ;\n      }\n      else if (ferror(in_file))\n      {\n        free((zvoid *)b);\n        return ZE_READ;\n      }\n      else {\n        break;\n      }\n    }\n\n\n    /* end at extended local header (data descriptor) signature */\n    if (des) {\n      des_crc = 0;\n      des_csize = 0;\n      des_usize = 0;\n\n      /* If first 4 bytes in buffer are data descriptor signature then\n         try to read the data descriptor.\n         If not, scan for signature and break if found, let bfwrite flush\n         the data and then next read should put the data descriptor at\n         the beginning of the buffer.\n       */\n\n      if (\n          (b[0] != 0x50 /*'P' except EBCDIC*/ ||\n           b[1] != 0x4b /*'K' except EBCDIC*/ ||\n           b[2] != '\\07' ||\n           b[3] != '\\010')) {\n        /* buffer is not start of data descriptor */\n\n        for (kk = 0; kk < k; kk++) {\n          /* add byte to end of sbuf */\n          for (i = 0; i < 3; i++)\n            sbuf[i] = sbuf[i + 1];\n          sbuf[3] = b[kk];\n\n          /* see if this is signature */\n          if (\n              (sbuf[0] == 0x50 /*'P' except EBCDIC*/ &&\n               sbuf[1] == 0x4b /*'K' except EBCDIC*/ &&\n               sbuf[2] == '\\07' &&\n               sbuf[3] == '\\010')) {\n            kk -= 3;\n            if (zfseeko(in_file, bytes_this_split + kk, SEEK_SET) != 0) {\n              /* seek error */\n              ZIPERR(ZE_READ, \"seek failed reading descriptor\");\n            }\n            des_start = zftello(in_file);\n            k = kk;\n            break;\n          }\n        }\n      }\n      else\n\n      /* signature at start of buffer */\n      {\n        des_good = 0;\n\n#ifdef ZIP64_SUPPORT\n        if (zip64_entry) {\n\n          /* read Zip64 data descriptor */\n          if (k < 24) {\n            /* not enough bytes, so can't be data descriptor\n               as data descriptors can't be split across splits\n             */\n          }\n          else\n          {\n            /* read the Zip64 descriptor */\n\n            des_crc = LG(b + 4);\n            des_csize = LLG(b + 8);\n            des_usize = LLG(b + 16);\n\n            /* if this is the right data descriptor then the sizes should match */\n            if ((uzoff_t)des_start - (uzoff_t)data_start != des_csize) {\n              /* apparently this signature does not go with this data so skip */\n\n              /* write out signature as data */\n              k = 4;\n              if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) {\n                /* seek error */\n                ZIPERR(ZE_READ, \"seek failed reading descriptor\");\n              }\n              if (bfwrite(b, 1, k, BFWRITE_DATA) != k)\n              {\n                free((zvoid *)b);\n                fprintf(mesg,\" fcopy: write error\\n\");\n                return ZE_TEMP;\n              }\n              m += k;\n              continue;\n            }\n            else\n            {\n              /* apparently this is the correct data descriptor */\n\n              /* we should check the CRC but would need to inflate\n                 the data */\n\n              /* skip descriptor as will write out later */\n              des_good = 1;\n              k = 24;\n              data_start = zftello(in_file);\n              if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) {\n                /* seek error */\n                ZIPERR(ZE_READ, \"seek failed reading descriptor\");\n              }\n              data_start = zftello(in_file);\n            }\n          }\n\n        }\n        else\n#endif\n        {\n          /* read standard data descriptor */\n\n          if (k < 16) {\n            /* not enough bytes, so can't be data descriptor\n               as data descriptors can't be split across splits\n             */\n          }\n          else\n          {\n            /* read the descriptor */\n\n            des_crc = LG(b + 4);\n            des_csize = LG(b + 8);\n            des_usize = LG(b + 12);\n\n            /* if this is the right data descriptor then the sizes should match */\n            if ((uzoff_t)des_start - (uzoff_t)data_start != des_csize) {\n              /* apparently this signature does not go with this data so skip */\n\n              /* write out signature as data */\n              k = 4;\n              if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) {\n                /* seek error */\n                ZIPERR(ZE_READ, \"seek failed reading descriptor\");\n              }\n              if (bfwrite(b, 1, k, BFWRITE_DATA) != k)\n              {\n                free((zvoid *)b);\n                fprintf(mesg,\" fcopy: write error\\n\");\n                return ZE_TEMP;\n              }\n              m += k;\n              continue;\n            }\n            else\n            {\n              /* apparently this is the correct data descriptor */\n\n              /* we should check the CRC but this does not work for\n                 encrypted data */\n\n              /* skip descriptor as will write out later */\n              des_good = 1;\n              data_start = zftello(in_file);\n              k = 16;\n              if (zfseeko(in_file, des_start + k, SEEK_SET) != 0) {\n                /* seek error */\n                ZIPERR(ZE_READ, \"seek failed reading descriptor\");\n              }\n              data_start = zftello(in_file);\n            }\n          }\n\n\n        }\n      }\n    }\n\n\n    if (des_good) {\n      /* skip descriptor as will write out later */\n    } else {\n      /* write out apparently wrong descriptor as data */\n      if (bfwrite(b, 1, k, BFWRITE_DATA) != k)\n      {\n        free((zvoid *)b);\n        fprintf(mesg,\" fcopy: write error\\n\");\n        return ZE_TEMP;\n      }\n      m += k;\n    }\n\n    if (copy_only && !display_globaldots) {\n      if (dot_size > 0) {\n        /* initial space */\n        if (noisy && dot_count == -1) {\n#ifndef WINDLL\n          putc(' ', mesg);\n          fflush(mesg);\n#else\n          fprintf(stdout,\"%c\",' ');\n#endif\n          dot_count++;\n        }\n        dot_count += k;\n        if (dot_size <= dot_count) dot_count = 0;\n      }\n      if ((verbose || noisy) && dot_size && !dot_count) {\n#ifndef WINDLL\n        putc('.', mesg);\n        fflush(mesg);\n#else\n        fprintf(stdout,\"%c\",'.');\n#endif\n        mesg_line_started = 1;\n      }\n    }\n\n    if (des_good)\n      break;\n\n    if (des)\n      continue;\n\n    if ((des || n != (uzoff_t)(-1L)) && m < n && feof(in_file)) {\n      /* open next split */\n      current_in_disk++;\n\n      if (current_in_disk >= total_disks) {\n        /* done */\n        break;\n\n      } else if (current_in_disk == total_disks - 1) {\n        /* last disk is archive.zip */\n        if ((split_path = malloc(strlen(in_path) + 1)) == NULL) {\n          zipwarn(\"reading archive: \", in_path);\n          return ZE_MEM;\n        }\n        strcpy(split_path, in_path);\n      } else {\n        /* other disks are archive.z01, archive.z02, ... */\n        split_path = get_in_split_path(in_path, current_in_disk);\n      }\n\n      fclose(in_file);\n\n      /* open the split */\n      while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n        int r = 0;\n\n        /* could not open split */\n\n        if (fix == 1 && skip_this_disk) {\n          free(split_path);\n          free((zvoid *)b);\n          return ZE_FORM;\n        }\n\n        /* Ask for directory with split.  Updates in_path */\n        r = ask_for_split_read_path(current_in_disk);\n        if (r == ZE_ABORT) {\n          zipwarn(\"could not find split: \", split_path);\n          free(split_path);\n          free((zvoid *)b);\n          return ZE_ABORT;\n        }\n        if (r == ZE_EOF) {\n          zipmessage_nl(\"\", 1);\n          zipwarn(\"user ended reading - closing archive\", \"\");\n          free(split_path);\n          free((zvoid *)b);\n          return ZE_EOF;\n        }\n        if (fix == 2 && skip_this_disk) {\n          /* user asked to skip this disk */\n          zipwarn(\"skipping split file: \", split_path);\n          current_in_disk++;\n        }\n\n        if (current_in_disk == total_disks - 1) {\n          /* last disk is archive.zip */\n          if ((split_path = malloc(strlen(in_path) + 1)) == NULL) {\n            zipwarn(\"reading archive: \", in_path);\n            return ZE_MEM;\n          }\n          strcpy(split_path, in_path);\n        } else {\n          /* other disks are archive.z01, archive.z02, ... */\n          split_path = get_in_split_path(zipfile, current_in_disk);\n        }\n      }\n      if (fix == 2 && skip_this_disk) {\n        /* user asked to skip this disk */\n        free(split_path);\n        free((zvoid *)b);\n        return ZE_FORM;\n      }\n      free(split_path);\n    }\n  }\n  free((zvoid *)b);\n  return ZE_OK;\n}\n\n\n\n#ifdef NO_RENAME\nint rename(from, to)\nZCONST char *from;\nZCONST char *to;\n{\n    unlink(to);\n    if (link(from, to) == -1)\n        return -1;\n    if (unlink(from) == -1)\n        return -1;\n    return 0;\n}\n\n#endif /* NO_RENAME */\n\n\n#ifdef ZMEM\n\n/************************/\n/*  Function memset()   */\n/************************/\n\n/*\n * memset - for systems without it\n *  bill davidsen - March 1990\n */\n\nchar *\nmemset(buf, init, len)\nregister char *buf;     /* buffer loc */\nregister int init;      /* initializer */\nregister unsigned int len;   /* length of the buffer */\n{\n    char *start;\n\n    start = buf;\n    while (len--) *(buf++) = init;\n    return(start);\n}\n\n\n/************************/\n/*  Function memcpy()   */\n/************************/\n\nchar *\nmemcpy(dst,src,len)             /* v2.0f */\nregister char *dst, *src;\nregister unsigned int len;\n{\n    char *start;\n\n    start = dst;\n    while (len--)\n        *dst++ = *src++;\n    return(start);\n}\n\n\n/************************/\n/*  Function memcmp()   */\n/************************/\n\nint\nmemcmp(b1,b2,len)                     /* jpd@usl.edu -- 11/16/90 */\nregister char *b1, *b2;\nregister unsigned int len;\n{\n\n    if (len) do {       /* examine each byte (if any) */\n      if (*b1++ != *b2++)\n        return (*((uch *)b1-1) - *((uch *)b2-1));  /* exit when miscompare */\n    } while (--len);\n\n    return(0);          /* no miscompares, yield 0 result */\n}\n\n#endif  /* ZMEM */\n\n\n/*------------------------------------------------------------------\n * Split archives\n */\n\n\n/* ask_for_split_read_path\n *\n * If the next split file is not in the current directory, ask\n * the user where it is.\n *\n * in_path is the base path for reading splits and is usually\n * the same as zipfile.  The path in in_path must be the archive\n * file ending in .zip as this is assumed by get_in_split_path().\n *\n * Updates in_path if changed.  Returns ZE_OK if OK or ZE_ABORT if\n * user cancels reading archive.\n *\n * If fix = 1 then allow skipping disk (user may not have it).\n */\n\n#define SPLIT_MAXPATH (FNMAX + 4010)\n\nint ask_for_split_read_path(current_disk)\n  ulg current_disk;\n{\n  FILE *f;\n  int is_readable = 0;\n  int i;\n  char *split_dir = NULL;\n  char *archive_name = NULL;\n  char *split_name = NULL;\n  char *split_path = NULL;\n  char buf[SPLIT_MAXPATH + 100];\n\n  /* get split path */\n  split_path = get_in_split_path(in_path, current_disk);\n\n  /* get the directory */\n  if ((split_dir = malloc(strlen(in_path) + 40)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  strcpy(split_dir, in_path);\n\n  /* remove any name at end */\n  for (i = strlen(split_dir) - 1; i >= 0; i--) {\n    if (split_dir[i] == '/' || split_dir[i] == '\\\\'\n          || split_dir[i] == ':') {\n      split_dir[i + 1] = '\\0';\n      break;\n    }\n  }\n  if (i < 0)\n    split_dir[0] = '\\0';\n\n  /* get the name of the archive */\n  if ((archive_name = malloc(strlen(in_path) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  if (strlen(in_path) == strlen(split_dir)) {\n    archive_name[0] = '\\0';\n  } else {\n    strcpy(archive_name, in_path + strlen(split_dir));\n  }\n\n  /* get the name of the split */\n  if ((split_name = malloc(strlen(split_path) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  if (strlen(in_path) == strlen(split_dir)) {\n    split_name[0] = '\\0';\n  } else {\n    strcpy(split_name, split_path + strlen(split_dir));\n  }\n  if (i < 0) {\n    strcpy(split_dir, \"(current directory)\");\n  }\n\n  fprintf(mesg, \"\\n\\nCould not find:\\n\");\n  fprintf(mesg, \"  %s\\n\", split_path);\n  /*\n  fprintf(mesg, \"Please enter the path directory (. for cur dir) where\\n\");\n  fprintf(mesg, \"  %s\\n\", split_name);\n  fprintf(mesg, \"is located\\n\");\n  */\n  for (;;) {\n    if (is_readable) {\n      fprintf(mesg, \"\\nHit c      (change path to where this split file is)\");\n      fprintf(mesg, \"\\n    q      (abort archive - quit)\");\n      fprintf(mesg, \"\\n or ENTER  (continue with this split): \");\n    } else {\n      if (fix == 1) {\n        fprintf(mesg, \"\\nHit c      (change path to where this split file is)\");\n        fprintf(mesg, \"\\n    s      (skip this split)\");\n        fprintf(mesg, \"\\n    q      (abort archive - quit)\");\n        fprintf(mesg, \"\\n or ENTER  (try reading this split again): \");\n      } else if (fix == 2) {\n        fprintf(mesg, \"\\nHit c      (change path to where this split file is)\");\n        fprintf(mesg, \"\\n    s      (skip this split)\");\n        fprintf(mesg, \"\\n    q      (abort archive - quit)\");\n        fprintf(mesg, \"\\n    e      (end this archive - no more splits)\");\n        fprintf(mesg, \"\\n    z      (look for .zip split - the last split)\");\n        fprintf(mesg, \"\\n or ENTER  (try reading this split again): \");\n      } else {\n        fprintf(mesg, \"\\nHit c      (change path to where this split file is)\");\n        fprintf(mesg, \"\\n    q      (abort archive - quit)\");\n        fprintf(mesg, \"\\n or ENTER  (try reading this split again): \");\n      }\n    }\n    fflush(mesg);\n    fgets(buf, SPLIT_MAXPATH, stdin);\n    /* remove any newline */\n    for (i = 0; buf[i]; i++) {\n      if (buf[i] == '\\n') {\n        buf[i] = '\\0';\n        break;\n      }\n    }\n    if (toupper(buf[0]) == 'Q') {\n      return ZE_ABORT;\n    } else if ((fix == 1 || fix == 2) && toupper(buf[0]) == 'S') {\n    /*\n      fprintf(mesg, \"\\nSkip this split/disk?  (files in this split will not be recovered) [n/y] \");\n      fflush(mesg);\n      fgets(buf, SPLIT_MAXPATH, stdin);\n      if (buf[0] == 'y' || buf[0] == 'Y') {\n    */\n      skip_this_disk = current_in_disk + 1;\n      return ZE_FORM;\n    } else if (toupper(buf[0]) == 'C') {\n      fprintf(mesg, \"\\nEnter path where this split is (ENTER = same dir, . = current dir)\");\n      fprintf(mesg, \"\\n: \");\n      fflush(mesg);\n      fgets(buf, SPLIT_MAXPATH, stdin);\n      is_readable = 0;\n      /* remove any newline */\n      for (i = 0; buf[i]; i++) {\n        if (buf[i] == '\\n') {\n          buf[i] = '\\0';\n          break;\n        }\n      }\n      if (buf[0] == '\\0') {\n        /* Hit ENTER so try old path again - could be removable media was changed */\n        strcpy(buf, split_path);\n      }\n    } else if (fix == 2 && toupper(buf[0]) == 'E') {\n      /* no more splits to read */\n      return ZE_EOF;\n    } else if (fix == 2 && toupper(buf[0]) == 'Z') {\n      total_disks = current_disk + 1;\n      free(split_path);\n      split_path = get_in_split_path(in_path, current_disk);\n      buf[0] = '\\0';\n      strncat(buf, split_path, SPLIT_MAXPATH);\n    }\n    if (strlen(buf) > 0) {\n      /* changing path */\n\n      /* check if user wants current directory */\n      if (buf[0] == '.' && buf[1] == '\\0') {\n        buf[0] = '\\0';\n      }\n      /* remove any name at end */\n      for (i = strlen(buf); i >= 0; i--) {\n        if (buf[i] == '/' || buf[i] == '\\\\'\n             || buf[i] == ':') {\n          buf[i + 1] = '\\0';\n          break;\n        }\n      }\n      /* update base_path to newdir/split_name - in_path is the .zip file path */\n      free(in_path);\n      if (i < 0) {\n        /* just name so current directory */\n        strcpy(buf, \"(current directory)\");\n        if (archive_name == NULL) {\n          i = 0;\n        } else {\n          i = strlen(archive_name);\n        }\n        if ((in_path = malloc(strlen(archive_name) + 40)) == NULL) {\n          ZIPERR(ZE_MEM, \"split path\");\n        }\n        strcpy(in_path, archive_name);\n      } else {\n        /* not the current directory */\n        /* remove any name at end */\n        for (i = strlen(buf); i >= 0; i--) {\n          if (buf[i] == '/') {\n            buf[i + 1] = '\\0';\n            break;\n          }\n        }\n        if (i < 0) {\n          buf[0] = '\\0';\n        }\n        if ((in_path = malloc(strlen(buf) + strlen(archive_name) + 40)) == NULL) {\n          ZIPERR(ZE_MEM, \"split path\");\n        }\n        strcpy(in_path, buf);\n        strcat(in_path, archive_name);\n      }\n\n      free(split_path);\n\n      /* get split path */\n      split_path = get_in_split_path(in_path, current_disk);\n\n      free(split_dir);\n      if ((split_dir = malloc(strlen(in_path) + 40)) == NULL) {\n        ZIPERR(ZE_MEM, \"split path\");\n      }\n      strcpy(split_dir, in_path);\n      /* remove any name at end */\n      for (i = strlen(split_dir); i >= 0; i--) {\n        if (split_dir[i] == '/') {\n          split_dir[i + 1] = '\\0';\n          break;\n        }\n      }\n\n      /* try to open it */\n      if ((f = fopen(split_path, \"r\")) == NULL) {\n        fprintf(mesg, \"\\nCould not find or open\\n\");\n        fprintf(mesg, \"  %s\\n\", split_path);\n        /*\n        fprintf(mesg, \"Please enter the path (. for cur dir) where\\n\");\n        fprintf(mesg, \"  %s\\n\", split_name);\n        fprintf(mesg, \"is located\\n\");\n        */\n        continue;\n      }\n      fclose(f);\n      is_readable = 1;\n      fprintf(mesg, \"Found:  %s\\n\", split_path);\n    } else {\n      /* try to open it */\n      if ((f = fopen(split_path, \"r\")) == NULL) {\n        fprintf(mesg, \"\\nCould not find or open\\n\");\n        fprintf(mesg, \"  %s\\n\", split_path);\n        /*\n        fprintf(mesg, \"Please enter the path (. for cur dir) where\\n\");\n        fprintf(mesg, \"  %s\\n\", split_name);\n        fprintf(mesg, \"is located\\n\");\n        */\n        continue;\n      }\n      fclose(f);\n      is_readable = 1;\n      fprintf(mesg, \"\\nFound:  %s\\n\", split_path);\n      break;\n    }\n  }\n  free(archive_name);\n  free(split_dir);\n  free(split_name);\n\n  return ZE_OK;\n}\n\n\n/* ask_for_split_write_path\n *\n * Verify the directory for the next split.  Called\n * when -sp is used to pause between writing splits.\n *\n * Updates out_path and return 1 if OK or 0 if cancel\n */\nint ask_for_split_write_path(current_disk)\n  ulg current_disk;\n{\n  unsigned int num = (unsigned int)current_disk + 1;\n  int i;\n  char *split_dir = NULL;\n  char *split_name = NULL;\n  char buf[FNMAX + 40];\n\n  /* get the directory */\n  if ((split_dir = malloc(strlen(out_path) + 40)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  strcpy(split_dir, out_path);\n\n  /* remove any name at end */\n  for (i = strlen(split_dir); i >= 0; i--) {\n    if (split_dir[i] == '/' || split_dir[i] == '\\\\'\n          || split_dir[i] == ':') {\n      split_dir[i + 1] = '\\0';\n      break;\n    }\n  }\n\n  /* get the name of the split */\n  if ((split_name = malloc(strlen(out_path) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  if (strlen(out_path) == strlen(split_dir)) {\n    split_name[0] = '\\0';\n  } else {\n    strcpy(split_name, out_path + strlen(split_dir));\n  }\n  if (i < 0) {\n    strcpy(split_dir, \"(current directory)\");\n  }\n  if (mesg_line_started)\n    fprintf(mesg, \"\\n\");\n  fprintf(mesg, \"\\nOpening disk %d\\n\", num);\n  fprintf(mesg, \"Hit ENTER to write to default path of\\n\");\n  fprintf(mesg, \"  %s\\n\", split_dir);\n  fprintf(mesg, \"or enter a new directory path (. for cur dir) and hit ENTER\\n\");\n  for (;;) {\n    fprintf(mesg, \"\\nPath (or hit ENTER to continue): \");\n    fflush(mesg);\n    fgets(buf, FNMAX, stdin);\n    /* remove any newline */\n    for (i = 0; buf[i]; i++) {\n      if (buf[i] == '\\n') {\n        buf[i] = '\\0';\n        break;\n      }\n    }\n    if (strlen(buf) > 0) {\n      /* changing path */\n\n      /* current directory */\n      if (buf[0] == '.' && buf[1] == '\\0') {\n        buf[0] = '\\0';\n      }\n      /* remove any name at end */\n      for (i = strlen(buf); i >= 0; i--) {\n        if (buf[i] == '/' || buf[i] == '\\\\'\n             || buf[i] == ':') {\n          buf[i + 1] = '\\0';\n          break;\n        }\n      }\n      /* update out_path to newdir/split_name */\n      free(out_path);\n      if (i < 0) {\n        /* just name so current directory */\n        strcpy(buf, \"(current directory)\");\n        if (split_name == NULL) {\n          i = 0;\n        } else {\n          i = strlen(split_name);\n        }\n        if ((out_path = malloc(strlen(split_name) + 40)) == NULL) {\n          ZIPERR(ZE_MEM, \"split path\");\n        }\n        strcpy(out_path, split_name);\n      } else {\n        /* not the current directory */\n        /* remove any name at end */\n        for (i = strlen(buf); i >= 0; i--) {\n          if (buf[i] == '/') {\n            buf[i + 1] = '\\0';\n            break;\n          }\n        }\n        if (i < 0) {\n          buf[0] = '\\0';\n        }\n        if ((out_path = malloc(strlen(buf) + strlen(split_name) + 40)) == NULL) {\n          ZIPERR(ZE_MEM, \"split path\");\n        }\n        strcpy(out_path, buf);\n        strcat(out_path, split_name);\n      }\n      fprintf(mesg, \"Writing to:\\n  %s\\n\", buf);\n      free(split_name);\n      free(split_dir);\n      if ((split_dir = malloc(strlen(out_path) + 40)) == NULL) {\n        ZIPERR(ZE_MEM, \"split path\");\n      }\n      strcpy(split_dir, out_path);\n      /* remove any name at end */\n      for (i = strlen(split_dir); i >= 0; i--) {\n        if (split_dir[i] == '/') {\n          split_dir[i + 1] = '\\0';\n          break;\n        }\n      }\n      if ((split_name = malloc(strlen(out_path) + 1)) == NULL) {\n        ZIPERR(ZE_MEM, \"split path\");\n      }\n      strcpy(split_name, out_path + strlen(split_dir));\n    } else {\n      break;\n    }\n  }\n  free(split_dir);\n  free(split_name);\n\n  /* for now no way out except Ctrl C */\n  return 1;\n}\n\n\n/* split_name\n *\n * get name of split being read\n */\nchar *get_in_split_path(base_path, disk_number)\n  char *base_path;\n  ulg disk_number;\n{\n  char *split_path = NULL;\n  int base_len = 0;\n  int path_len = 0;\n  ulg num = disk_number + 1;\n  char ext[6];\n#ifdef VMS\n  int vers_len;                         /* File version length. */\n  char *vers_ptr;                       /* File version string. */\n#endif /* def VMS */\n\n  /*\n   * A split has extension z01, z02, ..., z99, z100, z101, ... z999\n   * We currently support up to .z99999\n   * WinZip will also read .100, .101, ... but AppNote 6.2.2 uses above\n   * so use that.  Means on DOS can only have 100 splits.\n   */\n\n  if (num == total_disks) {\n    /* last disk is base path */\n    if ((split_path = malloc(strlen(base_path) + 1)) == NULL) {\n      ZIPERR(ZE_MEM, \"base path\");\n    }\n    strcpy(split_path, base_path);\n\n    return split_path;\n  } else {\n    if (num > 99999) {\n      ZIPERR(ZE_BIG, \"More than 99999 splits needed\");\n    }\n    sprintf(ext, \"z%02lu\", num);\n  }\n\n  /* create path for this split - zip.c checked for .zip extension */\n  base_len = strlen(base_path) - 3;\n  path_len = base_len + strlen(ext);\n\n#ifdef VMS\n  /* On VMS, locate the file version, and adjust base_len accordingly.\n     Note that path_len is correct, as-is.\n  */\n  vers_ptr = vms_file_version( base_path);\n  vers_len = strlen( vers_ptr);\n  base_len -= vers_len;\n#endif /* def VMS */\n\n  if ((split_path = malloc(path_len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  /* copy base_path except for end zip */\n  strcpy(split_path, base_path);\n  split_path[base_len] = '\\0';\n  /* add extension */\n  strcat(split_path, ext);\n\n#ifdef VMS\n  /* On VMS, append (preserve) the file version. */\n  strcat(split_path, vers_ptr);\n#endif /* def VMS */\n\n  return split_path;\n}\n\n\n/* split_name\n *\n * get name of split being written\n */\nchar *get_out_split_path(base_path, disk_number)\n  char *base_path;\n  ulg disk_number;\n{\n  char *split_path = NULL;\n  int base_len = 0;\n  int path_len = 0;\n  ulg num = disk_number + 1;\n  char ext[6];\n#ifdef VMS\n  int vers_len;                         /* File version length. */\n  char *vers_ptr;                       /* File version string. */\n#endif /* def VMS */\n\n  /*\n   * A split has extension z01, z02, ..., z99, z100, z101, ... z999\n   * We currently support up to .z99999\n   * WinZip will also read .100, .101, ... but AppNote 6.2.2 uses above\n   * so use that.  Means on DOS can only have 100 splits.\n   */\n\n  if (num > 99999) {\n    ZIPERR(ZE_BIG, \"More than 99999 splits needed\");\n  }\n  sprintf(ext, \"z%02lu\", num);\n\n  /* create path for this split - zip.c checked for .zip extension */\n  base_len = strlen(base_path) - 3;\n  path_len = base_len + strlen(ext);\n\n#ifdef VMS\n  /* On VMS, locate the file version, and adjust base_len accordingly.\n     Note that path_len is correct, as-is.\n  */\n  vers_ptr = vms_file_version( base_path);\n  vers_len = strlen( vers_ptr);\n  base_len -= vers_len;\n#endif /* def VMS */\n\n  if ((split_path = malloc(path_len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"split path\");\n  }\n  /* copy base_path except for end zip */\n  strcpy(split_path, base_path);\n  split_path[base_len] = '\\0';\n  /* add extension */\n  strcat(split_path, ext);\n\n#ifdef VMS\n  /* On VMS, append (preserve) the file version. */\n  strcat(split_path, vers_ptr);\n#endif /* def VMS */\n\n  return split_path;\n}\n\n/* close_split\n *\n * close a split - assume that the paths needed for the splits are\n * available.\n */\nint close_split(disk_number, tempfile, temp_name)\n  ulg disk_number;\n  FILE *tempfile;\n  char *temp_name;\n{\n  char *split_path = NULL;\n\n  split_path = get_out_split_path(out_path, disk_number);\n\n  if (noisy_splits) {\n    zipmessage(\"\\tClosing split \", split_path);\n  }\n\n  fclose(tempfile);\n\n  rename_split(temp_name, split_path);\n  set_filetype(split_path);\n\n  return ZE_OK;\n}\n\n/* bfwrite\n   Does the fwrite but also counts bytes and does splits */\nsize_t bfwrite(buffer, size, count, mode)\n  ZCONST void *buffer;\n  size_t size;\n  size_t count;\n  int mode;\n{\n  size_t bytes_written = 0;\n  size_t r;\n  size_t b = size * count;\n  uzoff_t bytes_left_in_split = 0;\n  size_t bytes_to_write = b;\n\n\n  /* -------------------------------- */\n  /* local header */\n  if (mode == BFWRITE_LOCALHEADER) {\n    /* writing local header - reset entry data count */\n    bytes_this_entry = 0;\n    /* save start of local header so we can rewrite later */\n    current_local_file = y;\n    current_local_disk = current_disk;\n    current_local_offset = bytes_this_split;\n  }\n\n  if (split_size == 0)\n    bytes_left_in_split = bytes_to_write;\n  else\n    bytes_left_in_split = split_size - bytes_this_split;\n\n  if (bytes_to_write > bytes_left_in_split) {\n    if (mode == BFWRITE_HEADER ||\n        mode == BFWRITE_LOCALHEADER ||\n        mode == BFWRITE_CENTRALHEADER) {\n      /* if can't write entire header save for next split */\n      bytes_to_write = 0;\n    } else {\n      /* normal data so fill the split */\n      bytes_to_write = (size_t)bytes_left_in_split;\n    }\n  }\n\n  /* -------------------------------- */\n  /* central header */\n  if (mode == BFWRITE_CENTRALHEADER) {\n    /* set start disk for CD */\n    if (cd_start_disk == (ulg)-1) {\n      cd_start_disk = current_disk;\n      cd_start_offset = bytes_this_split;\n    }\n    cd_entries_this_disk++;\n    total_cd_entries++;\n  }\n\n  /* -------------------------------- */\n  if (bytes_to_write > 0) {\n    /* write out the bytes for this split */\n    r = fwrite(buffer, size, bytes_to_write, y);\n    bytes_written += r;\n    bytes_to_write = b - r;\n    bytes_this_split += r;\n    if (mode == BFWRITE_DATA)\n      /* if data descriptor do not include in count */\n      bytes_this_entry += r;\n  } else {\n    bytes_to_write = b;\n  }\n\n  if (bytes_to_write > 0) {\n    if (split_method) {\n      /* still bytes to write so close split and open next split */\n      bytes_prev_splits += bytes_this_split;\n\n      if (split_method == 1 && ferror(y)) {\n        /* if writing all splits to same place and have problem then bad */\n        ZIPERR(ZE_WRITE, \"Could not write split\");\n      }\n\n      if (split_method == 2 && ferror(y)) {\n        /* A split must be at least 64K except last .zip split */\n        if (bytes_this_split < 64 * (uzoff_t)0x400) {\n          ZIPERR(ZE_WRITE, \"Not enough space to write split\");\n        }\n      }\n\n      /* close this split */\n      if (split_method == 1 && current_local_disk == current_disk) {\n        /* keep split open so can update it */\n        current_local_tempname = tempzip;\n      } else {\n        /* close split */\n        close_split(current_disk, y, tempzip);\n        y = NULL;\n        free(tempzip);\n        tempzip = NULL;\n      }\n      cd_entries_this_disk = 0;\n      bytes_this_split = 0;\n\n      /* increment disk - disks are numbered 0, 1, 2, ... and\n         splits are 01, 02, ... */\n      current_disk++;\n\n      if (split_method == 2 && split_bell) {\n        /* bell when pause to ask for next split */\n        putc('\\007', mesg);\n        fflush(mesg);\n      }\n\n      for (;;) {\n        /* if method 2 pause and allow changing path */\n        if (split_method == 2) {\n          if (ask_for_split_write_path(current_disk) == 0) {\n            ZIPERR(ZE_ABORT, \"could not write split\");\n          }\n        }\n\n        /* open next split */\n#if defined(UNIX) && !defined(NO_MKSTEMP)\n        {\n          int yd;\n          int i;\n\n          /* use mkstemp to avoid race condition and compiler warning */\n\n          if (tempath != NULL)\n          {\n            /* if -b used to set temp file dir use that for split temp */\n            if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {\n              ZIPERR(ZE_MEM, \"allocating temp filename\");\n            }\n            strcpy(tempzip, tempath);\n            if (lastchar(tempzip) != '/')\n              strcat(tempzip, \"/\");\n          }\n          else\n          {\n            /* create path by stripping name and appending template */\n            if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {\n            ZIPERR(ZE_MEM, \"allocating temp filename\");\n            }\n            strcpy(tempzip, zipfile);\n            for(i = strlen(tempzip); i > 0; i--) {\n              if (tempzip[i - 1] == '/')\n                break;\n            }\n            tempzip[i] = '\\0';\n          }\n          strcat(tempzip, \"ziXXXXXX\");\n\n          if ((yd = mkstemp(tempzip)) == EOF) {\n            ZIPERR(ZE_TEMP, tempzip);\n          }\n          if ((y = fdopen(yd, FOPW_TMP)) == NULL) {\n            ZIPERR(ZE_TEMP, tempzip);\n          }\n        }\n#else\n        if ((tempzip = tempname(zipfile)) == NULL) {\n          ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        if ((y = zfopen(tempzip, FOPW_TMP)) == NULL) {\n          ZIPERR(ZE_TEMP, tempzip);\n        }\n#endif\n\n        r = fwrite((char *)buffer + bytes_written, 1, bytes_to_write, y);\n        bytes_written += r;\n        bytes_this_split += r;\n        if (!(mode == BFWRITE_HEADER ||\n              mode == BFWRITE_LOCALHEADER ||\n              mode == BFWRITE_CENTRALHEADER)) {\n          bytes_this_entry += r;\n        }\n        if (bytes_to_write > r) {\n          /* buffer bigger than split */\n          if (split_method == 2) {\n            /* let user choose another disk */\n            zipwarn(\"Not enough room on disk\", \"\");\n            continue;\n          } else {\n            ZIPERR(ZE_WRITE, \"Not enough room on disk\");\n          }\n        }\n        if (mode == BFWRITE_LOCALHEADER ||\n            mode == BFWRITE_HEADER ||\n            mode == BFWRITE_CENTRALHEADER) {\n          if (split_method == 1 && current_local_file &&\n              current_local_disk != current_disk) {\n            /* We're opening a new split because the next header\n               did not fit on the last split.  We need to now close\n               the last split and update the pointers for\n               the current split. */\n            close_split(current_local_disk, current_local_file,\n                        current_local_tempname);\n            free(current_local_tempname);\n          }\n          current_local_tempname = tempzip;\n          current_local_file = y;\n          current_local_offset = 0;\n          current_local_disk = current_disk;\n        }\n        break;\n      }\n    }\n    else\n    {\n      /* likely have more than fits but no splits */\n\n      /* probably already have error \"no space left on device\" */\n      /* could let flush_outbuf() handle error but bfwrite() is called for\n         headers also */\n      if (ferror(y))\n        ziperr(ZE_WRITE, \"write error on zip file\");\n    }\n  }\n\n\n  /* display dots for archive instead of for each file */\n  if (display_globaldots) {\n    if (dot_size > 0) {\n      /* initial space */\n      if (dot_count == -1) {\n#ifndef WINDLL\n        putc(' ', mesg);\n        fflush(mesg);\n#else\n        fprintf(stdout,\"%c\",' ');\n#endif\n        /* assume a header will be written first, so avoid 0 */\n        dot_count = 1;\n      }\n      /* skip incrementing dot count for small buffers like for headers */\n      if (size * count > 1000) {\n        dot_count++;\n        if (dot_size <= dot_count * (zoff_t)size * (zoff_t)count) dot_count = 0;\n      }\n    }\n    if (dot_size && !dot_count) {\n      dot_count++;\n#ifndef WINDLL\n      putc('.', mesg);\n      fflush(mesg);\n#else\n      fprintf(stdout,\"%c\",'.');\n#endif\n      mesg_line_started = 1;\n    }\n  }\n\n\n  return bytes_written;\n}\n\n\n#ifdef UNICODE_SUPPORT\n\n/*---------------------------------------------\n * Unicode conversion functions\n *\n * Provided by Paul Kienitz\n *\n * Some modifications to work with Zip\n *\n *---------------------------------------------\n */\n\n/*\n   NOTES APPLICABLE TO ALL STRING FUNCTIONS:\n\n   All of the x_to_y functions take parameters for an output buffer and\n   its available length, and return an int.  The value returned is the\n   length of the string that the input produces, which may be larger than\n   the provided buffer length.  If the returned value is less than the\n   buffer length, then the contents of the buffer will be null-terminated;\n   otherwise, it will not be terminated and may be invalid, possibly\n   stopping in the middle of a multibyte sequence.\n\n   In all cases you may pass NULL as the buffer and/or 0 as the length, if\n   you just want to learn how much space the string is going to require.\n\n   The functions will return -1 if the input is invalid UTF-8 or cannot be\n   encoded as UTF-8.\n*/\n\n/* utility functions for managing UTF-8 and UCS-4 strings */\n\n\n/* utf8_char_bytes\n *\n * Returns the number of bytes used by the first character in a UTF-8\n * string, or -1 if the UTF-8 is invalid or null.\n */\nlocal int utf8_char_bytes(utf8)\n  ZCONST char *utf8;\n{\n  int      t, r;\n  unsigned lead;\n\n  if (!utf8)\n    return -1;          /* no input */\n  lead = (unsigned char) *utf8;\n  if (lead < 0x80)\n    r = 1;              /* an ascii-7 character */\n  else if (lead < 0xC0)\n    return -1;          /* error: trailing byte without lead byte */\n  else if (lead < 0xE0)\n    r = 2;              /* an 11 bit character */\n  else if (lead < 0xF0)\n    r = 3;              /* a 16 bit character */\n  else if (lead < 0xF8)\n    r = 4;              /* a 21 bit character (the most currently used) */\n  else if (lead < 0xFC)\n    r = 5;              /* a 26 bit character (shouldn't happen) */\n  else if (lead < 0xFE)\n    r = 6;              /* a 31 bit character (shouldn't happen) */\n  else\n    return -1;          /* error: invalid lead byte */\n  for (t = 1; t < r; t++)\n    if ((unsigned char) utf8[t] < 0x80 || (unsigned char) utf8[t] >= 0xC0)\n      return -1;        /* error: not enough valid trailing bytes */\n  return r;\n}\n\n\n/* ucs4_char_from_utf8\n *\n * Given a reference to a pointer into a UTF-8 string, returns the next\n * UCS-4 character and advances the pointer to the next character sequence.\n * Returns ~0 and does not advance the pointer when input is ill-formed.\n *\n * Since the Unicode standard says 32-bit values won't be used (just\n * up to the current 21-bit mappings) changed this to signed to allow -1 to\n * be returned.\n */\nlong ucs4_char_from_utf8(utf8)\n  ZCONST char **utf8;\n{\n  ulg  ret;\n  int  t, bytes;\n\n  if (!utf8)\n    return -1;                          /* no input */\n  bytes = utf8_char_bytes(*utf8);\n  if (bytes <= 0)\n    return -1;                          /* invalid input */\n  if (bytes == 1)\n    ret = **utf8;                       /* ascii-7 */\n  else\n    ret = **utf8 & (0x7F >> bytes);     /* lead byte of a multibyte sequence */\n  (*utf8)++;\n  for (t = 1; t < bytes; t++)           /* consume trailing bytes */\n    ret = (ret << 6) | (*((*utf8)++) & 0x3F);\n  return (long) ret;\n}\n\n\n/* utf8_from_ucs4_char - Convert UCS char to UTF-8\n *\n * Returns the number of bytes put into utf8buf to represent ch, from 1 to 6,\n * or -1 if ch is too large to represent.  utf8buf must have room for 6 bytes.\n */\nlocal int utf8_from_ucs4_char(utf8buf, ch)\n  char *utf8buf;\n  ulg ch;\n{\n  int trailing = 0;\n  int leadmask = 0x80;\n  int leadbits = 0x3F;\n  ulg tch = ch;\n  int ret;\n\n  if (ch > 0x7FFFFFFF)\n    return -1;                /* UTF-8 can represent 31 bits */\n  if (ch < 0x7F)\n  {\n    *utf8buf++ = (char) ch;   /* ascii-7 */\n    return 1;\n  }\n  do {\n    trailing++;\n    leadmask = (leadmask >> 1) | 0x80;\n    leadbits >>= 1;\n    tch >>= 6;\n  } while (tch & ~leadbits);\n  ret = trailing + 1;\n  /* produce lead byte */\n  *utf8buf++ = (char) (leadmask | (ch >> (6 * trailing)));\n  /* produce trailing bytes */\n  while (--trailing >= 0)\n    *utf8buf++ = (char) (0x80 | ((ch >> (6 * trailing)) & 0x3F));\n  return ret;\n}\n\n\n/*===================================================================*/\n\n/* utf8_to_ucs4_string - convert UTF-8 string to UCS string\n *\n * Return UCS count.  Now returns int so can return -1.\n */\nlocal int utf8_to_ucs4_string(utf8, ucs4buf, buflen)\n  ZCONST char *utf8;\n  ulg *ucs4buf;\n  int buflen;\n{\n  int count = 0;\n\n  for (;;)\n  {\n    long ch = ucs4_char_from_utf8(&utf8);\n    if (ch == -1)\n      return -1;\n    else\n    {\n      if (ucs4buf && count < buflen)\n        ucs4buf[count] = ch;\n      if (ch == 0)\n        return count;\n      count++;\n    }\n  }\n}\n\n\n/* ucs4_string_to_utf8\n *\n *\n */\nlocal int ucs4_string_to_utf8(ucs4, utf8buf, buflen)\n  ZCONST ulg *ucs4;\n  char *utf8buf;\n  int buflen;\n{\n  char mb[6];\n  int  count = 0;\n\n  if (!ucs4)\n    return -1;\n  for (;;)\n  {\n    int mbl = utf8_from_ucs4_char(mb, *ucs4++);\n    int c;\n    if (mbl <= 0)\n      return -1;\n    /* We could optimize this a bit by passing utf8buf + count */\n    /* directly to utf8_from_ucs4_char when buflen >= count + 6... */\n    c = buflen - count;\n    if (mbl < c)\n      c = mbl;\n    if (utf8buf && count < buflen)\n      strncpy(utf8buf + count, mb, c);\n    if (mbl == 1 && !mb[0])\n      return count;           /* terminating nul */\n    count += mbl;\n  }\n}\n\n\n#if 0  /* currently unused */\n/* utf8_chars\n *\n * Wrapper: counts the actual unicode characters in a UTF-8 string.\n */\nlocal int utf8_chars(utf8)\n  ZCONST char *utf8;\n{\n  return utf8_to_ucs4_string(utf8, NULL, 0);\n}\n#endif\n\n\n/* --------------------------------------------------- */\n/* Unicode Support\n *\n * These functions common for all Unicode ports.\n *\n * These functions should allocate and return strings that can be\n * freed with free().\n *\n * 8/27/05 EG\n *\n * Use zwchar for wide char which is unsigned long\n * in zip.h and 32 bits.  This avoids problems with\n * different sizes of wchar_t.\n */\n\n#ifdef WIN32\n\nzwchar *wchar_to_wide_string(wchar_string)\n  wchar_t *wchar_string;\n{\n  int i;\n  int wchar_len;\n  zwchar *wide_string;\n\n  wchar_len = wcslen(wchar_string);\n\n  if ((wide_string = malloc((wchar_len + 1) * sizeof(zwchar))) == NULL) {\n    ZIPERR(ZE_MEM, \"wchar to wide conversion\");\n  }\n  for (i = 0; i <= wchar_len; i++) {\n    wide_string[i] = wchar_string[i];\n  }\n\n  return wide_string;\n}\n\n/* is_ascii_stringw\n * Checks if a wide string is all ascii\n */\nint is_ascii_stringw(wstring)\n  wchar_t *wstring;\n{\n  wchar_t *pw;\n  wchar_t cw;\n\n  if (wstring == NULL)\n    return 0;\n\n  for (pw = wstring; (cw = *pw) != '\\0'; pw++) {\n    if (cw > 0x7F) {\n      return 0;\n    }\n  }\n  return 1;\n}\n\n#endif\n\n/* is_ascii_string\n * Checks if a string is all ascii\n */\nint is_ascii_string(mbstring)\n  char *mbstring;\n{\n  char *p;\n  uch c;\n\n  if (mbstring == NULL)\n    return 0;\n\n  for (p = mbstring; (c = (uch)*p) != '\\0'; p++) {\n    if (c > 0x7F) {\n      return 0;\n    }\n  }\n  return 1;\n}\n\n/* local to UTF-8 */\nchar *local_to_utf8_string(local_string)\n  char *local_string;\n{\n  zwchar *wide_string = local_to_wide_string(local_string);\n  char *utf8_string = wide_to_utf8_string(wide_string);\n\n  free(wide_string);\n  return utf8_string;\n}\n\n/* wide_char_to_escape_string\n   provides a string that represents a wide char not in local char set\n\n   An initial try at an algorithm.  Suggestions welcome.\n\n   If not an ASCII char, probably need 2 bytes at least.  So if\n   a 2-byte wide encode it as 4 hex digits with a leading #U.\n   Since the Unicode standard has been frozen, it looks like 3 bytes\n   should be enough for any large Unicode character.  In these cases\n   prefix the string with #L.\n   So\n   #U1234\n   is a 2-byte wide character with bytes 0x12 and 0x34 while\n   #L123456\n   is a 3-byte wide with bytes 0x12, 0x34, and 0x56.\n   On Windows, wide that need two wide characters as a surrogate pair\n   to represent them need to be converted to a single number.\n  */\n\n /* set this to the max bytes an escape can be */\n#define MAX_ESCAPE_BYTES 8\n\nchar *wide_char_to_escape_string(wide_char)\n  zwchar wide_char;\n{\n  int i;\n  zwchar w = wide_char;\n  uch b[9];\n  char e[7];\n  int len;\n  char *r;\n\n  /* fill byte array with zeros */\n  for (len = 0; len < sizeof(zwchar); len++) {\n    b[len] = 0;\n  }\n  /* get bytes in right to left order */\n  for (len = 0; w; len++) {\n    b[len] = (char)(w % 0x100);\n    w /= 0x100;\n  }\n\n  if ((r = malloc(MAX_ESCAPE_BYTES + 8)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_char_to_escape_string\");\n  }\n  strcpy(r, \"#\");\n  /* either 2 bytes or 4 bytes */\n  if (len < 3) {\n    len = 2;\n    strcat(r, \"U\");\n  } else {\n    len = 3;\n    strcat(r, \"L\");\n  }\n  for (i = len - 1; i >= 0; i--) {\n    sprintf(e, \"%02x\", b[i]);\n    strcat(r, e);\n  }\n  return r;\n}\n\n#if 0\n/* returns the wide character represented by the escape string */\nzwchar escape_string_to_wide(escape_string)\n  char *escape_string;\n{\n  int i;\n  zwchar w;\n  char c;\n  char u;\n  int len;\n  char *e = escape_string;\n\n  if (e == NULL) {\n    return 0;\n  }\n  if (e[0] != '#') {\n    /* no leading # */\n    return 0;\n  }\n  len = strlen(e);\n  /* either #U1234 or #L123456 format */\n  if (len != 6 && len != 8) {\n    return 0;\n  }\n  w = 0;\n  if (e[1] == 'L') {\n    if (len != 8) {\n      return 0;\n    }\n    /* 3 bytes */\n    for (i = 2; i < 8; i++) {\n      c = e[i];\n      u = toupper(c);\n      if (u >= 'A' && u <= 'F') {\n        w = w * 0x10 + (zwchar)(u + 10 - 'A');\n      } else if (c >= '0' && c <= '9') {\n        w = w * 0x10 + (zwchar)(c - '0');\n      } else {\n        return 0;\n      }\n    }\n  } else if (e[1] == 'U') {\n    /* 2 bytes */\n    for (i = 2; i < 6; i++) {\n      c = e[i];\n      u = toupper(c);\n      if (u >= 'A' && u <= 'F') {\n        w = w * 0x10 + (zwchar)(u + 10 - 'A');\n      } else if (c >= '0' && c <= '9') {\n        w = w * 0x10 + (zwchar)(c - '0');\n      } else {\n        return 0;\n      }\n    }\n  }\n  return w;\n}\n#endif\n\n\nchar *local_to_escape_string(local_string)\n  char *local_string;\n{\n  zwchar *wide_string = local_to_wide_string(local_string);\n  char *escape_string = wide_to_escape_string(wide_string);\n\n  free(wide_string);\n  return escape_string;\n}\n\n#ifdef WIN32\nchar *wchar_to_local_string(wstring)\n  wchar_t *wstring;\n{\n  zwchar *wide_string = wchar_to_wide_string(wstring);\n  char *local_string = wide_to_local_string(wide_string);\n\n  free(wide_string);\n\n  return local_string;\n}\n#endif\n\n\n#ifndef WIN32   /* The Win32 port uses a system-specific variant. */\n/* convert wide character string to multi-byte character string */\nchar *wide_to_local_string(wide_string)\n  zwchar *wide_string;\n{\n  int i;\n  wchar_t wc;\n  int b;\n  int state_dependent;\n  int wsize = 0;\n  int max_bytes = MB_CUR_MAX;\n  char buf[9];\n  char *buffer = NULL;\n  char *local_string = NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if (MAX_ESCAPE_BYTES > max_bytes)\n    max_bytes = MAX_ESCAPE_BYTES;\n\n  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_to_local_string\");\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  /* set initial state if state-dependent encoding */\n  wc = (wchar_t)'a';\n  b = wctomb(NULL, wc);\n  if (b == 0)\n    state_dependent = 0;\n  else\n    state_dependent = 1;\n  for (i = 0; i < wsize; i++) {\n    if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {\n      /* wchar_t probably 2 bytes */\n      /* could do surrogates if state_dependent and wctomb can do */\n      wc = zwchar_to_wchar_t_default_char;\n    } else {\n      wc = (wchar_t)wide_string[i];\n    }\n    b = wctomb(buf, wc);\n    if (unicode_escape_all) {\n      if (b == 1 && (uch)buf[0] <= 0x7f) {\n        /* ASCII */\n        strncat(buffer, buf, b);\n      } else {\n        /* use escape for wide character */\n        char *e = wide_char_to_escape_string(wide_string[i]);\n        strcat(buffer, e);\n        free(e);\n      }\n    } else if (b > 0) {\n      /* multi-byte char */\n      strncat(buffer, buf, b);\n    } else {\n      /* no MB for this wide */\n      if (use_wide_to_mb_default) {\n        /* default character */\n        strcat(buffer, wide_to_mb_default_string);\n      } else {\n        /* use escape for wide character */\n        char *e = wide_char_to_escape_string(wide_string[i]);\n        strcat(buffer, e);\n        free(e);\n      }\n    }\n  }\n  if ((local_string = (char *)malloc(strlen(buffer) + 1)) == NULL) {\n    free(buffer);\n    ZIPERR(ZE_MEM, \"wide_to_local_string\");\n  }\n  strcpy(local_string, buffer);\n  free(buffer);\n\n  return local_string;\n}\n#endif /* !WIN32 */\n\n\n/* convert wide character string to escaped string */\nchar *wide_to_escape_string(wide_string)\n  zwchar *wide_string;\n{\n  int i;\n  int wsize = 0;\n  char buf[9];\n  char *buffer = NULL;\n  char *escape_string = NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if ((buffer = (char *)malloc(wsize * MAX_ESCAPE_BYTES + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_to_escape_string\");\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  for (i = 0; i < wsize; i++) {\n    if (wide_string[i] <= 0x7f && isprint((char)wide_string[i])) {\n      /* ASCII */\n      buf[0] = (char)wide_string[i];\n      buf[1] = '\\0';\n      strcat(buffer, buf);\n    } else {\n      /* use escape for wide character */\n      char *e = wide_char_to_escape_string(wide_string[i]);\n      strcat(buffer, e);\n      free(e);\n    }\n  }\n  if ((escape_string = (char *)malloc(strlen(buffer) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_to_escape_string\");\n  }\n  strcpy(escape_string, buffer);\n  free(buffer);\n\n  return escape_string;\n}\n\n\n/* convert local string to display character set string */\nchar *local_to_display_string(local_string)\n  char *local_string;\n{\n  char *temp_string;\n  char *display_string;\n\n  /* For Windows, OEM string should never be bigger than ANSI string, says\n     CharToOem description.\n     On UNIX, non-printable characters (0x00 - 0xFF) will be replaced by\n     \"^x\", so more space may be needed.  Note that \"^\" itself is a valid\n     name character, so this leaves an ambiguity, but UnZip displays\n     names this way, too.  (0x00 is not possible, I hope.)\n     For all other ports, just make a copy of local_string.\n  */\n\n#ifdef UNIX\n  char *cp_dst;                 /* Character pointers used in the */\n  char *cp_src;                 /*  copying/changing procedure.   */\n#endif\n\n  if ((temp_string = (char *)malloc(2 * strlen(local_string) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"local_to_display_string\");\n  }\n\n#ifdef WIN32\n  /* convert to OEM display character set */\n  local_to_oem_string(temp_string, local_string);\n#else\n# ifdef UNIX\n  /* Copy source string, expanding non-printable characters to \"^x\". */\n  cp_dst = temp_string;\n  cp_src = local_string;\n  while (*cp_src != '\\0') {\n    if ((unsigned char)*cp_src < ' ') {\n      *cp_dst++ = '^';\n      *cp_dst++ = '@'+ *cp_src++;\n    }\n    else {\n      *cp_dst++ = *cp_src++;\n    }\n  }\n  *cp_dst = '\\0';\n# else /* not UNIX */\n  strcpy(temp_string, local_string);\n# endif /* UNIX */\n#endif\n\n#ifdef EBCDIC\n  {\n    char *ebc;\n\n    if ((ebc = malloc(strlen(display_string) + 1)) ==  NULL) {\n      ZIPERR(ZE_MEM, \"local_to_display_string\");\n    }\n    strtoebc(ebc, display_string);\n    free(display_string);\n    display_string = ebc;\n  }\n#endif\n\n  if ((display_string = (char *)malloc(strlen(temp_string) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"local_to_display_string\");\n  }\n  strcpy(display_string, temp_string);\n  free(temp_string);\n\n  return display_string;\n}\n\n/* UTF-8 to local */\nchar *utf8_to_local_string(utf8_string)\n  char *utf8_string;\n{\n  zwchar *wide_string = utf8_to_wide_string(utf8_string);\n  char *loc = wide_to_local_string(wide_string);\n  if (wide_string)\n    free(wide_string);\n  return loc;\n}\n\n/* UTF-8 to local */\nchar *utf8_to_escape_string(utf8_string)\n  char *utf8_string;\n{\n  zwchar *wide_string = utf8_to_wide_string(utf8_string);\n  char *escape_string = wide_to_escape_string(wide_string);\n  free(wide_string);\n  return escape_string;\n}\n\n#ifndef WIN32   /* The Win32 port uses a system-specific variant. */\n/* convert multi-byte character string to wide character string */\nzwchar *local_to_wide_string(local_string)\n  char *local_string;\n{\n  int wsize;\n  wchar_t *wc_string;\n  zwchar *wide_string;\n\n  /* for now try to convert as string - fails if a bad char in string */\n  wsize = mbstowcs(NULL, local_string, MB_CUR_MAX );\n  if (wsize == (size_t)-1) {\n    /* could not convert */\n    return NULL;\n  }\n\n  /* convert it */\n  if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {\n    ZIPERR(ZE_MEM, \"local_to_wide_string\");\n  }\n  wsize = mbstowcs(wc_string, local_string, strlen(local_string) + 1);\n  wc_string[wsize] = (wchar_t) 0;\n\n  /* in case wchar_t is not zwchar */\n  if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) {\n    ZIPERR(ZE_MEM, \"local_to_wide_string\");\n  }\n  for (wsize = 0; (wide_string[wsize] = (zwchar)wc_string[wsize]); wsize++) ;\n  wide_string[wsize] = (zwchar)0;\n  free(wc_string);\n\n  return wide_string;\n}\n#endif /* !WIN32 */\n\n\n#if 0\n/* All wchar functions are only used by Windows and are\n   now in win32zip.c so that the Windows functions can\n   be used and multiple character wide characters can\n   be handled easily. */\n# ifndef WIN32\nchar *wchar_to_utf8_string(wstring)\n  wchar_t *wstring;\n{\n  zwchar *wide_string = wchar_to_wide_string(wstring);\n  char *local_string = wide_to_utf8_string(wide_string);\n\n  free(wide_string);\n\n  return local_string;\n}\n# endif\n#endif\n\n\n/* convert wide string to UTF-8 */\nchar *wide_to_utf8_string(wide_string)\n  zwchar *wide_string;\n{\n  int mbcount;\n  char *utf8_string;\n\n  /* get size of utf8 string */\n  mbcount = ucs4_string_to_utf8(wide_string, NULL, 0);\n  if (mbcount == -1)\n    return NULL;\n  if ((utf8_string = (char *) malloc(mbcount + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_to_utf8_string\");\n  }\n  mbcount = ucs4_string_to_utf8(wide_string, utf8_string, mbcount + 1);\n  if (mbcount == -1)\n    return NULL;\n\n  return utf8_string;\n}\n\n/* convert UTF-8 string to wide string */\nzwchar *utf8_to_wide_string(utf8_string)\n  char *utf8_string;\n{\n  int wcount;\n  zwchar *wide_string;\n\n  wcount = utf8_to_ucs4_string(utf8_string, NULL, 0);\n  if (wcount == -1)\n    return NULL;\n  if ((wide_string = (zwchar *) malloc((wcount + 2) * sizeof(zwchar))) == NULL) {\n    ZIPERR(ZE_MEM, \"utf8_to_wide_string\");\n  }\n  wcount = utf8_to_ucs4_string(utf8_string, wide_string, wcount + 1);\n\n  return wide_string;\n}\n\n\n#endif /* UNICODE_SUPPORT */\n\n\n/*---------------------------------------------------------------\n *  Long option support\n *  8/23/2003\n *\n *  Defines function get_option() to get and process the command\n *  line options and arguments from argv[].  The caller calls\n *  get_option() in a loop to get either one option and possible\n *  value or a non-option argument each loop.\n *\n *  This version does not include argument file support and can\n *  work directly on argv.  The argument file code complicates things and\n *  it seemed best to leave it out for now.  If argument file support (reading\n *  in command line arguments stored in a file and inserting into\n *  command line where @filename is found) is added later the arguments\n *  can change and a freeable copy of argv will be needed and can be\n *  created using copy_args in the left out code.\n *\n *  Supports short and long options as defined in the array options[]\n *  in zip.c, multiple short options in an argument (like -jlv), long\n *  option abbreviation (like --te for --temp-file if --te unique),\n *  short and long option values (like -b filename or --temp-file filename\n *  or --temp-file=filename), optional and required values, option negation\n *  by trailing - (like -S- to not include hidden and system files in MSDOS),\n *  value lists (like -x a b c), argument permuting (returning all options\n *  and values before any non-option arguments), and argument files (where any\n *  non-option non-value argument in form @path gets substituted with the\n *  white space separated arguments in the text file at path).  In this\n *  version argument file support has been removed to simplify development but\n *  may be added later.\n *\n *  E. Gordon\n */\n\n\n/* message output - char casts are needed to handle constants */\n#define oWARN(message) zipwarn((char *) message, \"\")\n#define oERR(err,message) ZIPERR(err, (char *) message)\n\n\n/* Although the below provides some support for multibyte characters\n   the proper thing to do may be to use wide characters and support\n   Unicode.  May get to it soon.  EG\n */\n\n/* For now stay with muti-byte characters.  May support wide characters\n   in Zip 3.1.\n */\n\n/* multibyte character set support\n   Multibyte characters use typically two or more sequential bytes\n   to represent additional characters than can fit in a single byte\n   character set.  The code used here is based on the ANSI mblen function. */\n#ifdef MULTIBYTE_GETOPTNS\n  int mb_clen(ptr)\n    ZCONST char *ptr;\n  {\n    /* return the number of bytes that the char pointed to is.  Return 1 if\n       null character or error like not start of valid multibyte character. */\n    int cl;\n\n    cl = mblen(ptr, MB_CUR_MAX);\n    return (cl > 0) ? cl : 1;\n  }\n#endif\n\n\n  /* moved to zip.h */\n#if 0\n#ifdef UNICODE_SUPPORT\n# define MB_CLEN(ptr) (1)\n# define MB_NEXTCHAR(ptr) ((ptr)++)\n# ifdef MULTIBYTE_GETOPTNS\n#    undef MULTIBYTE_GETOPTNS\n# endif\n#else\n# ifdef _MBCS\n#  ifndef MULTIBYTE_GETOPTNS\n#    define MULTIBYTE_GETOPTNS\n#  endif\n# endif\n/* multibyte character set support\n   Multibyte characters use typically two or more sequential bytes\n   to represent additional characters than can fit in a single byte\n   character set.  The code used here is based on the ANSI mblen function. */\n#  ifdef MULTIBYTE_GETOPTNS\n  local int mb_clen OF((ZCONST char *));  /* declare proto first */\n  local int mb_clen(ptr)\n    ZCONST char *ptr;\n  {\n    /* return the number of bytes that the char pointed to is.  Return 1 if\n       null character or error like not start of valid multibyte character. */\n    int cl;\n\n    cl = mblen(ptr, MB_CUR_MAX);\n    return (cl > 0) ? cl : 1;\n  }\n#  define MB_CLEN(ptr) mb_clen(ptr)\n#  define MB_NEXTCHAR(ptr) ((ptr) += MB_CLEN(ptr))\n# else\n#  define MB_CLEN(ptr) (1)\n#  define MB_NEXTCHAR(ptr) ((ptr)++)\n# endif\n#endif\n#endif\n\n\n/* constants */\n\n/* function get_args_from_arg_file() can return this in depth parameter */\n#define ARG_FILE_ERR -1\n\n/* internal settings for optchar */\n#define SKIP_VALUE_ARG   -1\n#define THIS_ARG_DONE    -2\n#define START_VALUE_LIST -3\n#define IN_VALUE_LIST    -4\n#define NON_OPTION_ARG   -5\n#define STOP_VALUE_LIST  -6\n/* 7/25/04 EG */\n#define READ_REST_ARGS_VERBATIM -7\n\n\n/* global veriables */\n\nint enable_permute = 1;                     /* yes - return options first */\n/* 7/25/04 EG */\nint doubledash_ends_options = 1;            /* when -- what follows are not options */\n\n/* buffer for error messages (this sizing is a guess but must hold 2 paths) */\n#define OPTIONERR_BUF_SIZE (FNMAX * 2 + 4000)\nlocal char Far optionerrbuf[OPTIONERR_BUF_SIZE + 1];\n\n/* error messages */\nstatic ZCONST char Far op_not_neg_err[] = \"option %s not negatable\";\nstatic ZCONST char Far op_req_val_err[] = \"option %s requires a value\";\nstatic ZCONST char Far op_no_allow_val_err[] = \"option %s does not allow a value\";\nstatic ZCONST char Far sh_op_not_sup_err[] = \"short option '%c' not supported\";\nstatic ZCONST char Far oco_req_val_err[] = \"option %s requires one character value\";\nstatic ZCONST char Far oco_no_mbc_err[] = \"option %s does not support multibyte values\";\nstatic ZCONST char Far num_req_val_err[] = \"option %s requires number value\";\nstatic ZCONST char Far long_op_ambig_err[] = \"long option '%s' ambiguous\";\nstatic ZCONST char Far long_op_not_sup_err[] = \"long option '%s' not supported\";\n\nstatic ZCONST char Far no_arg_files_err[] = \"argument files not enabled\\n\";\n\n\n/* below removed as only used for processing argument files */\n\n/* get_nextarg */\n/* get_args_from_string */\n/* insert_args */\n/* get_args_from_arg_file */\n\n\n/* copy error, option name, and option description if any to buf */\nlocal int optionerr(buf, err, optind, islong)\n  char *buf;\n  ZCONST char *err;\n  int optind;\n  int islong;\n{\n  char optname[50];\n\n  if (options[optind].name && options[optind].name[0] != '\\0') {\n    if (islong)\n      sprintf(optname, \"'%s' (%s)\", options[optind].longopt, options[optind].name);\n    else\n      sprintf(optname, \"'%s' (%s)\", options[optind].shortopt, options[optind].name);\n  } else {\n    if (islong)\n      sprintf(optname, \"'%s'\", options[optind].longopt);\n    else\n      sprintf(optname, \"'%s'\", options[optind].shortopt);\n  }\n  sprintf(buf, err, optname);\n  return 0;\n}\n\n\n/* copy_args\n *\n * Copy arguments in args, allocating storage with malloc.\n * Copies until a NULL argument is found or until max_args args\n * including args[0] are copied.  Set max_args to 0 to copy\n * until NULL.  Always terminates returned args[] with NULL arg.\n *\n * Any argument in the returned args can be freed with free().  Any\n * freed argument should be replaced with either another string\n * allocated with malloc or by NULL if last argument so that free_args\n * will properly work.\n */\nchar **copy_args(args, max_args)\n  char **args;\n  int max_args;\n{\n  int j;\n  char **new_args;\n\n  if (args == NULL) {\n    return NULL;\n  }\n\n  /* count args */\n  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ;\n\n  if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) {\n    oERR(ZE_MEM, \"ca\");\n  }\n\n  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) {\n    if (args[j] == NULL) {\n      /* null argument is end of args */\n      new_args[j] = NULL;\n      break;\n    }\n    if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) {\n      free_args(new_args);\n      oERR(ZE_MEM, \"ca\");\n    }\n    strcpy(new_args[j], args[j]);\n  }\n  new_args[j] = NULL;\n\n  return new_args;\n}\n\n\n/* free args - free args created with one of these functions */\nint free_args(args)\n  char **args;\n{\n  int i;\n\n  if (args == NULL) {\n    return 0;\n  }\n\n  for (i = 0; args[i]; i++) {\n    free(args[i]);\n  }\n  free(args);\n  return i;\n}\n\n\n/* insert_arg\n *\n * Insert the argument arg into the array args before argument at_arg.\n * Return the new count of arguments (argc).\n *\n * If free_args is true, this function frees the old args array\n * (but not the component strings).  DO NOT set free_args on original\n * argv but only on args allocated with malloc.\n */\n\nint insert_arg(pargs, arg, at_arg, free_args)\n   char ***pargs;\n   ZCONST char *arg;\n   int at_arg;\n   int free_args;\n{\n   char *newarg = NULL;\n   char **args;\n   char **newargs = NULL;\n   int argnum;\n   int newargnum;\n   int argcnt;\n   int newargcnt;\n\n   if (pargs == NULL) {\n     return 0;\n   }\n   args = *pargs;\n\n   /* count args */\n   if (args == NULL) {\n     argcnt = 0;\n   } else {\n     for (argcnt = 0; args[argcnt]; argcnt++) ;\n   }\n   if (arg == NULL) {\n     /* done */\n     return argcnt;\n   }\n   newargcnt = argcnt + 1;\n\n   /* get storage for new args */\n   if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL) {\n     oERR(ZE_MEM, \"ia\");\n   }\n\n   /* copy argument pointers from args to position at_arg, copy arg, then rest args */\n   argnum = 0;\n   newargnum = 0;\n   if (args) {\n     for (; args[argnum] && argnum < at_arg; argnum++) {\n       newargs[newargnum++] = args[argnum];\n     }\n   }\n   /* copy new arg */\n   if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) {\n     oERR(ZE_MEM, \"ia\");\n   }\n   strcpy(newarg, arg);\n\n   newargs[newargnum++] = newarg;\n   if (args) {\n     for ( ; args[argnum]; argnum++) {\n       newargs[newargnum++] = args[argnum];\n     }\n   }\n   newargs[newargnum] = NULL;\n\n   /* free old args array but not component strings - this assumes that\n      args was allocated with malloc as copy_args does.  DO NOT DO THIS\n      on the original argv.\n    */\n   if (free_args)\n     free(args);\n\n   *pargs = newargs;\n\n   return newargnum;\n}\n\n/* ------------------------------------- */\n\n\n\n\n/* get_shortopt\n *\n * Get next short option from arg.  The state is stored in argnum, optchar, and\n * option_num so no static storage is used.  Returns the option_ID.\n *\n * parameters:\n *    args        - argv array of arguments\n *    argnum      - index of current arg in args\n *    optchar     - pointer to index of next char to process.  Can be 0 or\n *                  const defined at top of this file like THIS_ARG_DONE\n *    negated     - on return pointer to int set to 1 if option negated or 0 otherwise\n *    value       - on return pointer to string set to value of option if any or NULL\n *                  if none.  If value is returned then the caller should free()\n *                  it when not needed anymore.\n *    option_num  - pointer to index in options[] of returned option or\n *                  o_NO_OPTION_MATCH if none.  Do not change as used by\n *                  value lists.\n *    depth       - recursion depth (0 at top level, 1 or more in arg files)\n */\nlocal unsigned long get_shortopt(args, argnum, optchar, negated, value,\n                                 option_num, depth)\n  char **args;\n  int argnum;\n  int *optchar;\n  int *negated;\n  char **value;\n  int *option_num;\n  int depth;\n{\n  char *shortopt;\n  int clen;\n  char *nextchar;\n  char *s;\n  char *start;\n  int op;\n  char *arg;\n  int match = -1;\n\n\n  /* get arg */\n  arg = args[argnum];\n  /* current char in arg */\n  nextchar = arg + (*optchar);\n  clen = MB_CLEN(nextchar);\n  /* next char in arg */\n  (*optchar) +=  clen;\n  /* get first char of short option */\n  shortopt = arg + (*optchar);\n  /* no value */\n  *value = NULL;\n\n  if (*shortopt == '\\0') {\n    /* no more options in arg */\n    *optchar = 0;\n    *option_num = o_NO_OPTION_MATCH;\n    return 0;\n  }\n\n  /* look for match in options */\n  clen = MB_CLEN(shortopt);\n  for (op = 0; options[op].option_ID; op++) {\n    s = options[op].shortopt;\n    if (s && s[0] == shortopt[0]) {\n      if (s[1] == '\\0' && clen == 1) {\n        /* single char match */\n        match = op;\n      } else {\n        /* 2 wide short opt.  Could support more chars but should use long opts instead */\n        if (s[1] == shortopt[1]) {\n          /* match 2 char short opt or 2 byte char */\n          match = op;\n          if (clen == 1) (*optchar)++;\n          break;\n        }\n      }\n    }\n  }\n\n  if (match > -1) {\n    /* match */\n    clen = MB_CLEN(shortopt);\n    nextchar = arg + (*optchar) + clen;\n    /* check for trailing dash negating option */\n    if (*nextchar == '-') {\n      /* negated */\n      if (options[match].negatable == o_NOT_NEGATABLE) {\n        if (options[match].value_type == o_NO_VALUE) {\n          optionerr(optionerrbuf, op_not_neg_err, match, 0);\n          if (depth > 0) {\n            /* unwind */\n            oWARN(optionerrbuf);\n            return o_ARG_FILE_ERR;\n          } else {\n            oERR(ZE_PARMS, optionerrbuf);\n          }\n        }\n      } else {\n        *negated = 1;\n        /* set up to skip negating dash */\n        (*optchar) += clen;\n        clen = 1;\n      }\n    }\n\n    /* value */\n    clen = MB_CLEN(arg + (*optchar));\n    /* optional value, one char value, and number value must follow option */\n    if (options[match].value_type == o_ONE_CHAR_VALUE) {\n      /* one char value */\n      if (arg[(*optchar) + clen]) {\n        /* has value */\n        if (MB_CLEN(arg + (*optchar) + clen) > 1) {\n          /* multibyte value not allowed for now */\n          optionerr(optionerrbuf, oco_no_mbc_err, match, 0);\n          if (depth > 0) {\n            /* unwind */\n            oWARN(optionerrbuf);\n            return o_ARG_FILE_ERR;\n          } else {\n            oERR(ZE_PARMS, optionerrbuf);\n          }\n        }\n        if ((*value = (char *) malloc(2)) == NULL) {\n          oERR(ZE_MEM, \"gso\");\n        }\n        (*value)[0] = *(arg + (*optchar) + clen);\n        (*value)[1] = '\\0';\n        *optchar += clen;\n        clen = 1;\n      } else {\n        /* one char values require a value */\n        optionerr(optionerrbuf, oco_req_val_err, match, 0);\n        if (depth > 0) {\n          oWARN(optionerrbuf);\n          return o_ARG_FILE_ERR;\n        } else {\n          oERR(ZE_PARMS, optionerrbuf);\n        }\n      }\n    } else if (options[match].value_type == o_NUMBER_VALUE) {\n      /* read chars until end of number */\n      start = arg + (*optchar) + clen;\n      if (*start == '+' || *start == '-') {\n        start++;\n      }\n      s = start;\n      for (; isdigit(*s); MB_NEXTCHAR(s)) ;\n      if (s == start) {\n        /* no digits */\n        optionerr(optionerrbuf, num_req_val_err, match, 0);\n        if (depth > 0) {\n          oWARN(optionerrbuf);\n          return o_ARG_FILE_ERR;\n        } else {\n          oERR(ZE_PARMS, optionerrbuf);\n        }\n      }\n      start = arg + (*optchar) + clen;\n      if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) {\n        oERR(ZE_MEM, \"gso\");\n      }\n      *optchar += (int)(s - start);\n      strncpy(*value, start, (int)(s - start));\n      (*value)[(int)(s - start)] = '\\0';\n      clen = MB_CLEN(s);\n    } else if (options[match].value_type == o_OPTIONAL_VALUE) {\n      /* optional value */\n      /* This seemed inconsistent so now if no value attached to argument look\n         to the next argument if that argument is not an option for option\n         value - 11/12/04 EG */\n      if (arg[(*optchar) + clen]) {\n        /* has value */\n        /* add support for optional = - 2/6/05 EG */\n        if (arg[(*optchar) + clen] == '=') {\n          /* skip = */\n          clen++;\n        }\n        if (arg[(*optchar) + clen]) {\n          if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))\n              == NULL) {\n            oERR(ZE_MEM, \"gso\");\n          }\n          strcpy(*value, arg + (*optchar) + clen);\n        }\n        *optchar = THIS_ARG_DONE;\n      } else if (args[argnum + 1] && args[argnum + 1][0] != '-') {\n        /* use next arg for value */\n        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {\n          oERR(ZE_MEM, \"gso\");\n        }\n        /* using next arg as value */\n        strcpy(*value, args[argnum + 1]);\n        *optchar = SKIP_VALUE_ARG;\n      }\n    } else if (options[match].value_type == o_REQUIRED_VALUE ||\n               options[match].value_type == o_VALUE_LIST) {\n      /* see if follows option */\n      if (arg[(*optchar) + clen]) {\n        /* has value following option as -ovalue */\n        /* add support for optional = - 6/5/05 EG */\n        if (arg[(*optchar) + clen] == '=') {\n          /* skip = */\n          clen++;\n        }\n          if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))\n              == NULL) {\n          oERR(ZE_MEM, \"gso\");\n        }\n        strcpy(*value, arg + (*optchar) + clen);\n        *optchar = THIS_ARG_DONE;\n      } else {\n        /* use next arg for value */\n        if (args[argnum + 1]) {\n          if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {\n            oERR(ZE_MEM, \"gso\");\n          }\n          strcpy(*value, args[argnum + 1]);\n          if (options[match].value_type == o_VALUE_LIST) {\n            *optchar = START_VALUE_LIST;\n          } else {\n            *optchar = SKIP_VALUE_ARG;\n          }\n        } else {\n          /* no value found */\n          optionerr(optionerrbuf, op_req_val_err, match, 0);\n          if (depth > 0) {\n            oWARN(optionerrbuf);\n            return o_ARG_FILE_ERR;\n          } else {\n            oERR(ZE_PARMS, optionerrbuf);\n          }\n        }\n      }\n    }\n\n    *option_num = match;\n    return options[match].option_ID;\n  }\n  sprintf(optionerrbuf, sh_op_not_sup_err, *shortopt);\n  if (depth > 0) {\n    /* unwind */\n    oWARN(optionerrbuf);\n    return o_ARG_FILE_ERR;\n  } else {\n    oERR(ZE_PARMS, optionerrbuf);\n  }\n  return 0;\n}\n\n\n/* get_longopt\n *\n * Get the long option in args array at argnum.\n * Parameters same as for get_shortopt.\n */\n\nlocal unsigned long get_longopt(args, argnum, optchar, negated, value,\n                                option_num, depth)\n  char **args;\n  int argnum;\n  int *optchar;\n  int *negated;\n  char **value;\n  int *option_num;\n  int depth;\n{\n  char *longopt;\n  char *lastchr;\n  char *valuestart;\n  int op;\n  char *arg;\n  int match = -1;\n  *value = NULL;\n\n  if (args == NULL) {\n    *option_num = o_NO_OPTION_MATCH;\n    return 0;\n  }\n  if (args[argnum] == NULL) {\n    *option_num = o_NO_OPTION_MATCH;\n    return 0;\n  }\n  /* copy arg so can chop end if value */\n  if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) {\n    oERR(ZE_MEM, \"glo\");\n  }\n  strcpy(arg, args[argnum]);\n\n  /* get option */\n  longopt = arg + 2;\n  /* no value */\n  *value = NULL;\n\n  /* find = */\n  for (lastchr = longopt, valuestart = longopt;\n       *valuestart && *valuestart != '=';\n       lastchr = valuestart, MB_NEXTCHAR(valuestart)) ;\n  if (*valuestart) {\n    /* found =value */\n    *valuestart = '\\0';\n    valuestart++;\n  } else {\n    valuestart = NULL;\n  }\n\n  if (*lastchr == '-') {\n    /* option negated */\n    *negated = 1;\n    *lastchr = '\\0';\n  } else {\n    *negated = 0;\n  }\n\n  /* look for long option match */\n  for (op = 0; options[op].option_ID; op++) {\n    if (options[op].longopt && strcmp(options[op].longopt, longopt) == 0) {\n      /* exact match */\n      match = op;\n      break;\n    }\n    if (options[op].longopt && strncmp(options[op].longopt, longopt, strlen(longopt)) == 0) {\n      if (match > -1) {\n        sprintf(optionerrbuf, long_op_ambig_err, longopt);\n        free(arg);\n        if (depth > 0) {\n          /* unwind */\n          oWARN(optionerrbuf);\n          return o_ARG_FILE_ERR;\n        } else {\n          oERR(ZE_PARMS, optionerrbuf);\n        }\n      }\n      match = op;\n    }\n  }\n\n  if (match == -1) {\n    sprintf(optionerrbuf, long_op_not_sup_err, longopt);\n    free(arg);\n    if (depth > 0) {\n      oWARN(optionerrbuf);\n      return o_ARG_FILE_ERR;\n    } else {\n      oERR(ZE_PARMS, optionerrbuf);\n    }\n  }\n\n  /* one long option an arg */\n  *optchar = THIS_ARG_DONE;\n\n  /* if negated then see if allowed */\n  if (*negated && options[match].negatable == o_NOT_NEGATABLE) {\n    optionerr(optionerrbuf, op_not_neg_err, match, 1);\n    free(arg);\n    if (depth > 0) {\n      /* unwind */\n      oWARN(optionerrbuf);\n      return o_ARG_FILE_ERR;\n    } else {\n      oERR(ZE_PARMS, optionerrbuf);\n    }\n  }\n  /* get value */\n  if (options[match].value_type == o_OPTIONAL_VALUE) {\n    /* optional value in form option=value */\n    if (valuestart) {\n      /* option=value */\n      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {\n        free(arg);\n        oERR(ZE_MEM, \"glo\");\n      }\n      strcpy(*value, valuestart);\n    }\n  } else if (options[match].value_type == o_REQUIRED_VALUE ||\n             options[match].value_type == o_NUMBER_VALUE ||\n             options[match].value_type == o_ONE_CHAR_VALUE ||\n             options[match].value_type == o_VALUE_LIST) {\n    /* handle long option one char and number value as required value */\n    if (valuestart) {\n      /* option=value */\n      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {\n        free(arg);\n        oERR(ZE_MEM, \"glo\");\n      }\n      strcpy(*value, valuestart);\n    } else {\n      /* use next arg */\n      if (args[argnum + 1]) {\n        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {\n          free(arg);\n          oERR(ZE_MEM, \"glo\");\n        }\n        /* using next arg as value */\n        strcpy(*value, args[argnum + 1]);\n        if (options[match].value_type == o_VALUE_LIST) {\n          *optchar = START_VALUE_LIST;\n        } else {\n          *optchar = SKIP_VALUE_ARG;\n        }\n      } else {\n        /* no value found */\n        optionerr(optionerrbuf, op_req_val_err, match, 1);\n        free(arg);\n        if (depth > 0) {\n          /* unwind */\n          oWARN(optionerrbuf);\n          return o_ARG_FILE_ERR;\n        } else {\n          oERR(ZE_PARMS, optionerrbuf);\n        }\n      }\n    }\n  } else if (options[match].value_type == o_NO_VALUE) {\n    /* this option does not accept a value */\n    if (valuestart) {\n      /* --option=value */\n      optionerr(optionerrbuf, op_no_allow_val_err, match, 1);\n      free(arg);\n      if (depth > 0) {\n        oWARN(optionerrbuf);\n        return o_ARG_FILE_ERR;\n      } else {\n        oERR(ZE_PARMS, optionerrbuf);\n      }\n    }\n  }\n  free(arg);\n\n  *option_num = match;\n  return options[match].option_ID;\n}\n\n\n\n/* get_option\n *\n * Main interface for user.  Use this function to get options, values and\n * non-option arguments from a command line provided in argv form.\n *\n * To use get_option() first define valid options by setting\n * the global variable options[] to an array of option_struct.  Also\n * either change defaults below or make variables global and set elsewhere.\n * Zip uses below defaults.\n *\n * Call get_option() to get an option (like -b or --temp-file) and any\n * value for that option (like filename for -b) or a non-option argument\n * (like archive name) each call.  If *value* is not NULL after calling\n * get_option() it is a returned value and the caller should either store\n * the char pointer or free() it before calling get_option() again to avoid\n * leaking memory.  If a non-option non-value argument is returned get_option()\n * returns o_NON_OPTION_ARG and value is set to the entire argument.\n * When there are no more arguments get_option() returns 0.\n *\n * The parameters argnum (after set to 0 on initial call),\n * optchar, first_nonopt_arg, option_num, and depth (after initial\n * call) are set and maintained by get_option() and should not be\n * changed.  The parameters argc, negated, and value are outputs and\n * can be used by the calling program.  get_option() returns either the\n * option_ID for the current option, a special value defined in\n * zip.h, or 0 when no more arguments.\n *\n * The value returned by get_option() is the ID value in the options\n * table.  This value can be duplicated in the table if different\n * options are really the same option.  The index into the options[]\n * table is given by option_num, though the ID should be used as\n * option numbers change when the table is changed.  The ID must\n * not be 0 for any option as this ends the table.  If get_option()\n * finds an option not in the table it calls oERR to post an\n * error and exit.  Errors also result if the option requires a\n * value that is missing, a value is present but the option does\n * not take one, and an option is negated but is not\n * negatable.  Non-option arguments return o_NON_OPTION_ARG\n * with the entire argument in value.\n *\n * For Zip, permuting is on and all options and their values are\n * returned before any non-option arguments like archive name.\n *\n * The arguments \"-\" alone and \"--\" alone return as non-option arguments.\n * Note that \"-\" should not be used as part of a short option\n * entry in the table but can be used in the middle of long\n * options such as in the long option \"a-long-option\".  Now \"--\" alone\n * stops option processing, returning any arguments following \"--\" as\n * non-option arguments instead of options.\n *\n * Argument file support is removed from this version. It may be added later.\n *\n * After each call:\n *   argc       is set to the current size of args[] but should not change\n *                with argument file support removed,\n *   argnum     is the index of the current arg,\n *   value      is either the value of the returned option or non-option\n *                argument or NULL if option with no value,\n *   negated    is set if the option was negated by a trailing dash (-)\n *   option_num is set to either the index in options[] for the option or\n *                o_NO_OPTION_MATCH if no match.\n * Negation is checked before the value is read if the option is negatable so\n * that the - is not included in the value.  If the option is not negatable\n * but takes a value then the - will start the value.  If permuting then\n * argnum and first_nonopt_arg are unreliable and should not be used.\n *\n * Command line is read from left to right.  As get_option() finds non-option\n * arguments (arguments not starting with - and that are not values to options)\n * it moves later options and values in front of the non-option arguments.\n * This permuting is turned off by setting enable_permute to 0.  Then\n * get_option() will return options and non-option arguments in the order\n * found.  Currently permuting is only done after an argument is completely\n * processed so that any value can be moved with options they go with.  All\n * state information is stored in the parameters argnum, optchar,\n * first_nonopt_arg and option_num.  You should not change these after the\n * first call to get_option().  If you need to back up to a previous arg then\n * set argnum to that arg (remembering that args may have been permuted) and\n * set optchar = 0 and first_nonopt_arg to the first non-option argument if\n * permuting.  After all arguments are returned the next call to get_option()\n * returns 0.  The caller can then call free_args(args) if appropriate.\n *\n * get_option() accepts arguments in the following forms:\n *  short options\n *       of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single\n *       leading -, as in -abccdba.  In this example if 'b' is followed by 'a'\n *       it matches short option 'ba' else it is interpreted as short option\n *       b followed by another option.  The character - is not legal as a\n *       short option or as part of a 2 character short option.\n *\n *       If a short option has a value it immediately follows the option or\n *       if that option is the end of the arg then the next arg is used as\n *       the value.  So if short option e has a value, it can be given as\n *             -evalue\n *       or\n *             -e value\n *       and now\n *             -e=value\n *       but now that = is optional a leading = is stripped for the first.\n *       This change allows optional short option values to be defaulted as\n *             -e=\n *       Either optional or required values can be specified.  Optional values\n *       now use both forms as ignoring the later got confusing.  Any\n *       non-value short options can preceed a valued short option as in\n *             -abevalue\n *       Some value types (one_char and number) allow options after the value\n *       so if oc is an option that takes a character and n takes a number\n *       then\n *             -abocVccn42evalue\n *       returns value V for oc and value 42 for n.  All values are strings\n *       so programs may have to convert the \"42\" to a number.  See long\n *       options below for how value lists are handled.\n *\n *       Any short option can be negated by following it with -.  Any - is\n *       handled and skipped over before any value is read unless the option\n *       is not negatable but takes a value and then - starts the value.\n *\n *       If the value for an optional value is just =, then treated as no\n *       value.\n *\n *  long options\n *       of arbitrary length are assumed if an arg starts with -- but is not\n *       exactly --.  Long options are given one per arg and can be abbreviated\n *       if the abbreviation uniquely matches one of the long options.\n *       Exact matches always match before partial matches.  If ambiguous an\n *       error is generated.\n *\n *       Values are specified either in the form\n *             --longoption=value\n *       or can be the following arg if the value is required as in\n *             --longoption value\n *       Optional values to long options must be in the first form.\n *\n *       Value lists are specified by o_VALUE_LIST and consist of an option\n *       that takes a value followed by one or more value arguments.\n *       The two forms are\n *             --option=value\n *       or\n *             -ovalue\n *       for a single value or\n *             --option value1 value2 value3 ... --option2\n *       or\n *             -o value1 value2 value3 ...\n *       for a list of values.  The list ends at the next option, the\n *       end of the command line, or at a single \"@\" argument.\n *       Each value is treated as if it was preceeded by the option, so\n *             --option1 val1 val2\n *       with option1 value_type set to o_VALUE_LIST is the same as\n *             --option1=val1 --option1=val2\n *\n *       Long options can be negated by following the option with - as in\n *             --longoption-\n *       Long options with values can also be negated if this makes sense for\n *       the caller as:\n *             --longoption-=value\n *       If = is not followed by anything it is treated as no value.\n *\n *  @path\n *       When an argument in the form @path is encountered, the file at path\n *       is opened and white space separated arguments read from the file\n *       and inserted into the command line at that point as if the contents\n *       of the file were directly typed at that location.  The file can\n *       have options, files to zip, or anything appropriate at that location\n *       in the command line.  Since Zip has permuting enabled, options and\n *       files will propagate to the appropriate locations in the command\n *       line.\n *\n *       Argument files support has been removed from this version.  It may\n *       be added back later.\n *\n *  non-option argument\n *       is any argument not given above.  If enable_permute is 1 then\n *       these are returned after all options, otherwise all options and\n *       args are returned in order.  Returns option ID o_NON_OPTION_ARG\n *       and sets value to the argument.\n *\n *\n * Arguments to get_option:\n *  char ***pargs          - pointer to arg array in the argv form\n *  int *argc              - returns the current argc for args incl. args[0]\n *  int *argnum            - the index of the current argument (caller\n *                            should set = 0 on first call and not change\n *                            after that)\n *  int *optchar           - index of next short opt in arg or special\n *  int *first_nonopt_arg  - used by get_option to permute args\n *  int *negated           - option was negated (had trailing -)\n *  char *value            - value of option if any (free when done with it) or NULL\n *  int *option_num        - the index in options of the last option returned\n *                            (can be o_NO_OPTION_MATCH)\n *  int recursion_depth    - current depth of recursion\n *                            (always set to 0 by caller)\n *                            (always 0 with argument files support removed)\n *\n *  Caller should only read the returned option ID and the value, negated,\n *  and option_num (if required) parameters after each call.\n *\n *  Ed Gordon\n *  24 August 2003 (last updated 2 April 2008 EG)\n *\n */\n\nunsigned long get_option(pargs, argc, argnum, optchar, value,\n                         negated, first_nonopt_arg, option_num, recursion_depth)\n  char ***pargs;\n  int *argc;\n  int *argnum;\n  int *optchar;\n  char **value;\n  int *negated;\n  int *first_nonopt_arg;\n  int *option_num;\n  int recursion_depth;\n{\n  char **args;\n  unsigned long option_ID;\n\n  int argcnt;\n  int first_nonoption_arg;\n  char *arg = NULL;\n  int h;\n  int optc;\n  int argn;\n  int j;\n  int v;\n  int read_rest_args_verbatim = 0;  /* 7/25/04 - ignore options and arg files for rest args */\n\n  /* value is outdated.  The caller should free value before\n     calling get_option again. */\n  *value = NULL;\n\n  /* if args is NULL then done */\n  if (pargs == NULL) {\n    *argc = 0;\n    return 0;\n  }\n  args = *pargs;\n  if (args == NULL) {\n    *argc = 0;\n    return 0;\n  }\n\n  /* count args */\n  for (argcnt = 0; args[argcnt]; argcnt++) ;\n\n  /* if no provided args then nothing to do */\n  if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) {\n    *argc = argcnt;\n    /* return 0 to note that no args are left */\n    return 0;\n  }\n\n  *negated = 0;\n  first_nonoption_arg = *first_nonopt_arg;\n  argn = *argnum;\n  optc = *optchar;\n\n  if (optc == READ_REST_ARGS_VERBATIM) {\n    read_rest_args_verbatim = 1;\n  }\n\n  if (argn == -1 || (recursion_depth == 0 && argn == 0)) {\n    /* first call */\n    /* if depth = 0 then args[0] is argv[0] so skip */\n    *option_num = o_NO_OPTION_MATCH;\n    optc = THIS_ARG_DONE;\n    first_nonoption_arg = -1;\n  }\n\n  /* if option_num is set then restore last option_ID in case continuing value list */\n  option_ID = 0;\n  if (*option_num != o_NO_OPTION_MATCH) {\n    option_ID = options[*option_num].option_ID;\n  }\n\n  /* get next option if any */\n  for (;;)  {\n    if (read_rest_args_verbatim) {\n      /* rest of args after \"--\" are non-option args if doubledash_ends_options set */\n      argn++;\n      if (argn > argcnt || args[argn] == NULL) {\n        /* done */\n        option_ID = 0;\n        break;\n      }\n      arg = args[argn];\n      if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n        oERR(ZE_MEM, \"go\");\n      }\n      strcpy(*value, arg);\n      *option_num = o_NO_OPTION_MATCH;\n      option_ID = o_NON_OPTION_ARG;\n      break;\n\n    /* permute non-option args after option args so options are returned first */\n    } else if (enable_permute) {\n      if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE ||\n          optc == START_VALUE_LIST || optc == IN_VALUE_LIST ||\n          optc == STOP_VALUE_LIST) {\n        /* moved to new arg */\n        if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {\n          /* do the permuting - move non-options after this option */\n          /* if option and value separate args or starting list skip option */\n          if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) {\n            v = 1;\n          } else {\n            v = 0;\n          }\n          for (h = first_nonoption_arg; h < argn; h++) {\n            arg = args[first_nonoption_arg];\n            for (j = first_nonoption_arg; j < argn + v; j++) {\n              args[j] = args[j + 1];\n            }\n            args[j] = arg;\n          }\n          first_nonoption_arg += 1 + v;\n        }\n      }\n    } else if (optc == NON_OPTION_ARG) {\n      /* if not permuting then already returned arg */\n      optc = THIS_ARG_DONE;\n    }\n\n    /* value lists */\n    if (optc == STOP_VALUE_LIST) {\n      optc = THIS_ARG_DONE;\n    }\n\n    if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) {\n      if (optc == START_VALUE_LIST) {\n        /* already returned first value */\n        argn++;\n        optc = IN_VALUE_LIST;\n      }\n      argn++;\n      arg = args[argn];\n      /* if end of args and still in list and there are non-option args then\n         terminate list */\n      if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST)\n          && first_nonoption_arg > -1) {\n        /* terminate value list with @ */\n        /* this is only needed for argument files */\n        /* but is also good for show command line so command lines with lists\n           can always be read back in */\n        argcnt = insert_arg(&args, \"@\", first_nonoption_arg, 1);\n        argn++;\n        if (first_nonoption_arg > -1) {\n          first_nonoption_arg++;\n        }\n      }\n\n      arg = args[argn];\n      if (arg && arg[0] == '@' && arg[1] == '\\0') {\n          /* inserted arguments terminator */\n          optc = STOP_VALUE_LIST;\n          continue;\n      } else if (arg && arg[0] != '-') {  /* not option */\n        /* - and -- are not allowed in value lists unless escaped */\n        /* another value in value list */\n        if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {\n          oERR(ZE_MEM, \"go\");\n        }\n        strcpy(*value, args[argn]);\n        break;\n\n      } else {\n        argn--;\n        optc = THIS_ARG_DONE;\n      }\n    }\n\n    /* move to next arg */\n    if (optc == SKIP_VALUE_ARG) {\n      argn += 2;\n      optc = 0;\n    } else if (optc == THIS_ARG_DONE) {\n      argn++;\n      optc = 0;\n    }\n    if (argn > argcnt) {\n      break;\n    }\n    if (args[argn] == NULL) {\n      /* done unless permuting and non-option args */\n      if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {\n        /* return non-option arguments at end */\n        if (optc == NON_OPTION_ARG) {\n          first_nonoption_arg++;\n        }\n        /* after first pass args are permuted but skipped over non-option args */\n        /* swap so argn points to first non-option arg */\n        j = argn;\n        argn = first_nonoption_arg;\n        first_nonoption_arg = j;\n      }\n      if (argn > argcnt || args[argn] == NULL) {\n        /* done */\n        option_ID = 0;\n        break;\n      }\n    }\n\n    /* after swap first_nonoption_arg points to end which is NULL */\n    if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) {\n      /* only non-option args left */\n      if (optc == NON_OPTION_ARG) {\n        argn++;\n      }\n      if (argn > argcnt || args[argn] == NULL) {\n        /* done */\n        option_ID = 0;\n        break;\n      }\n      if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {\n        oERR(ZE_MEM, \"go\");\n      }\n      strcpy(*value, args[argn]);\n      optc = NON_OPTION_ARG;\n      option_ID = o_NON_OPTION_ARG;\n      break;\n    }\n\n    arg = args[argn];\n\n    /* is it an option */\n    if (arg[0] == '-') {\n      /* option */\n      if (arg[1] == '\\0') {\n        /* arg = - */\n        /* treat like non-option arg */\n        *option_num = o_NO_OPTION_MATCH;\n        if (enable_permute) {\n          /* permute args to move all non-option args to end */\n          if (first_nonoption_arg < 0) {\n            first_nonoption_arg = argn;\n          }\n          argn++;\n        } else {\n          /* not permute args so return non-option args when found */\n          if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n            oERR(ZE_MEM, \"go\");\n          }\n          strcpy(*value, arg);\n          optc = NON_OPTION_ARG;\n          option_ID = o_NON_OPTION_ARG;\n          break;\n        }\n\n      } else if (arg[1] == '-') {\n        /* long option */\n        if (arg[2] == '\\0') {\n          /* arg = -- */\n          if (doubledash_ends_options) {\n            /* Now -- stops permuting and forces the rest of\n               the command line to be read verbatim - 7/25/04 EG */\n\n            /* never permute args after -- and return as non-option args */\n            if (first_nonoption_arg < 1) {\n              /* -- is first non-option argument - 8/7/04 EG */\n              argn--;\n            } else {\n              /* go back to start of non-option args - 8/7/04 EG */\n              argn = first_nonoption_arg - 1;\n            }\n\n            /* disable permuting and treat remaining arguments as not\n               options */\n            read_rest_args_verbatim = 1;\n            optc = READ_REST_ARGS_VERBATIM;\n\n          } else {\n            /* treat like non-option arg */\n            *option_num = o_NO_OPTION_MATCH;\n            if (enable_permute) {\n              /* permute args to move all non-option args to end */\n              if (first_nonoption_arg < 0) {\n                first_nonoption_arg = argn;\n              }\n              argn++;\n            } else {\n              /* not permute args so return non-option args when found */\n              if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n                oERR(ZE_MEM, \"go\");\n              }\n              strcpy(*value, arg);\n              optc = NON_OPTION_ARG;\n              option_ID = o_NON_OPTION_ARG;\n              break;\n            }\n          }\n\n        } else {\n          option_ID = get_longopt(args, argn, &optc, negated, value, option_num, recursion_depth);\n          if (option_ID == o_ARG_FILE_ERR) {\n            /* unwind as only get this if recursion_depth > 0 */\n            return option_ID;\n          }\n          break;\n        }\n\n      } else {\n        /* short option */\n        option_ID = get_shortopt(args, argn, &optc, negated, value, option_num, recursion_depth);\n\n        if (option_ID == o_ARG_FILE_ERR) {\n          /* unwind as only get this if recursion_depth > 0 */\n          return option_ID;\n        }\n\n        if (optc == 0) {\n          /* if optc = 0 then ran out of short opts this arg */\n          optc = THIS_ARG_DONE;\n        } else {\n          break;\n        }\n      }\n\n#if 0\n    /* argument file code left out\n       so for now let filenames start with @\n    */\n\n    } else if (allow_arg_files && arg[0] == '@') {\n      /* arg file */\n      oERR(ZE_PARMS, no_arg_files_err);\n#endif\n\n    } else {\n      /* non-option */\n      if (enable_permute) {\n        /* permute args to move all non-option args to end */\n        if (first_nonoption_arg < 0) {\n          first_nonoption_arg = argn;\n        }\n        argn++;\n      } else {\n        /* no permute args so return non-option args when found */\n        if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {\n          oERR(ZE_MEM, \"go\");\n        }\n        strcpy(*value, arg);\n        *option_num = o_NO_OPTION_MATCH;\n        optc = NON_OPTION_ARG;\n        option_ID = o_NON_OPTION_ARG;\n        break;\n      }\n\n    }\n  }\n\n  *pargs = args;\n  *argc = argcnt;\n  *first_nonopt_arg = first_nonoption_arg;\n  *argnum = argn;\n  *optchar = optc;\n\n  return option_ID;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/globals.c",
    "content": "/*\n  globals.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  globals.c by Mark Adler\n */\n#define __GLOBALS_C\n\n#define GLOBALS         /* include definition of errors[] in zip.h */\n#ifndef UTIL\n#define UTIL            /* do not declare the read_buf variable */\n#endif\n\n#include \"zip.h\"\n\n\n/* Handy place to build error messages */\nchar errbuf[FNMAX+4081];\n\n/* Argument processing globals */\nint recurse = 0;        /* 1=recurse into directories encountered */\nint dispose = 0;        /* 1=remove files after put in zip file */\nint pathput = 1;        /* 1=store path with name */\n#ifdef RISCOS\nint scanimage = 1;      /* 1=scan through image files */\n#endif\nint method = BEST;      /* one of BEST, DEFLATE (only), or STORE (only) */\nint dosify = 0;         /* 1=make new entries look like MSDOS */\nint verbose = 0;        /* 1=report oddities in zip file structure */\nint fix = 0;            /* 1=fix the zip file, 2=FF, 3=ZipNote */\nint filesync = 0;       /* 1=file sync, delete entries not on file system */\nint adjust = 0;         /* 1=adjust offsets for sfx'd file (keep preamble) */\nint level = 6;          /* 0=fastest compression, 9=best compression */\nint translate_eol = 0;  /* Translate end-of-line LF -> CR LF */\n#ifdef VMS\n   int vmsver = 0;      /* 1=append VMS version number to file names */\n   int vms_native = 0;  /* 1=store in VMS format */\n   int vms_case_2 = 0;  /* ODS2 file name case in VMS.  -1: down. */\n   int vms_case_5 = 0;  /* ODS5 file name case in VMS.  +1: preserve. */\n#endif /* VMS */\n#if defined(OS2) || defined(WIN32)\n   int use_longname_ea = 0;  /* 1=use the .LONGNAME EA as the file's name */\n#endif\n/* 9/26/04 */\nint no_wild = 0;             /* 1 = wildcards are disabled */\nint allow_regex = 0;         /* 1 = allow [list] matching */\n#ifdef WILD_STOP_AT_DIR\n   int wild_stop_at_dir = 1; /* default wildcards do not include / in matches */\n#else\n   int wild_stop_at_dir = 0; /* default wildcards do include / in matches */\n#endif\n\n#ifdef UNICODE_SUPPORT\n   int using_utf8 = 0;       /* 1 if current character set UTF-8 */\n# ifdef WIN32\n   int no_win32_wide = -1; /* 1 = no wide functions, like GetFileAttributesW() */\n# endif\n#endif\n\nulg skip_this_disk = 0;\nint des_good = 0;       /* Good data descriptor found */\nulg des_crc = 0;        /* Data descriptor CRC */\nuzoff_t des_csize = 0;  /* Data descriptor csize */\nuzoff_t des_usize = 0;  /* Data descriptor usize */\n\n/* dots 10/20/04 */\nzoff_t dot_size = 0;          /* bytes processed in deflate per dot, 0 = no dots */\nzoff_t dot_count = 0;         /* buffers seen, recyles at dot_size */\n/* status 10/30/04 */\nint display_counts = 0;       /* display running file count */\nint display_bytes = 0;        /* display running bytes remaining */\nint display_globaldots = 0;   /* display dots for archive instead of each file */\nint display_volume = 0;       /* display current input and output volume (disk) numbers */\nint display_usize = 0;        /* display uncompressed bytes */\nulg files_so_far = 0;         /* files processed so far */\nulg bad_files_so_far = 0;     /* bad files skipped so far */\nulg files_total = 0;          /* files total to process */\nuzoff_t bytes_so_far = 0;     /* bytes processed so far (from initial scan) */\nuzoff_t good_bytes_so_far = 0;/* good bytes read so far */\nuzoff_t bad_bytes_so_far = 0; /* bad bytes skipped so far */\nuzoff_t bytes_total = 0;      /* total bytes to process (from initial scan) */\n\n/* logfile 6/5/05 */\nint logall = 0;               /* 0 = warnings/errors, 1 = all */\nFILE *logfile = NULL;         /* pointer to open logfile or NULL */\nint logfile_append = 0;       /* append to existing logfile */\nchar *logfile_path = NULL;    /* pointer to path of logfile */\n\nint hidden_files = 0;         /* process hidden and system files */\nint volume_label = 0;         /* add volume label */\nint dirnames = 1;             /* include directory entries by default */\nint filter_match_case = 1;    /* 1=match case when filter() */\nint diff_mode = 0;            /* 1=require --out and only store changed and add */\n#if defined(WIN32)\nint only_archive_set = 0;     /* include only files with DOS archive bit set */\nint clear_archive_bits = 0;   /* clear DOS archive bit of included files */\n#endif\nint linkput = 0;              /* 1=store symbolic links as such */\nint noisy = 1;                /* 0=quiet operation */\nint extra_fields = 1;         /* 0=create minimum, 1=don't copy old, 2=keep old */\nint use_descriptors = 0;      /* 1=use data descriptors 12/29/04 */\nint zip_to_stdout = 0;        /* output zipfile to stdout 12/30/04 */\nint allow_empty_archive = 0;  /* if no files, create empty archive anyway 12/28/05 */\nint copy_only = 0;            /* 1=copying archive entries only */\nint allow_fifo = 0;           /* 1=allow reading Unix FIFOs, waiting if pipe open */\nint show_files = 0;           /* show files to operate on and exit (=2 log only) */\n\nint output_seekable = 1;      /* 1 = output seekable 3/13/05 EG */\n\n#ifdef ZIP64_SUPPORT          /* zip64 support 10/4/03 */\n  int force_zip64 = -1;       /* if 1 force entries to be zip64, 0 force not zip64 */\n                              /* mainly for streaming from stdin */\n  int zip64_entry = 0;        /* current entry needs Zip64 */\n  int zip64_archive = 0;      /* if 1 then at least 1 entry needs zip64 */\n#endif\n\n#ifdef NTSD_EAS\n  int use_privileges = 0;     /* 1=use security privilege overrides */\n#endif\n#ifndef RISCOS\n#ifndef QDOS\n#ifndef TANDEM\nchar *special = \".Z:.zip:.zoo:.arc:.lzh:.arj\"; /* List of special suffixes */\n#else /* TANDEM */\nchar *special = \" Z: zip: zoo: arc: lzh: arj\"; /* List of special suffixes */\n#endif\n#else /* QDOS */\nchar *special = \"_Z:_zip:_zoo:_arc:_lzh:_arj\"; /* List of special suffixes */\n#endif\n#else /* RISCOS */\nchar *special = \"DDC:D96:68E\";\n#endif /* ?RISCOS */\nchar *key = NULL;       /* Scramble password if scrambling */\nchar *tempath = NULL;   /* Path for temporary files */\nFILE *mesg;             /* stdout by default, stderr for piping */\n\n#ifdef UNICODE_SUPPORT\n int utf8_force = 0;    /* 1=force storing UTF-8 as standard per AppNote bit 11 */\n#endif\nint unicode_escape_all = 0; /* 1=escape all non-ASCII characters in paths */\nint unicode_mismatch = 1; /* unicode mismatch is 0=error, 1=warn, 2=ignore, 3=no */\n\ntime_t scan_delay = 5;  /* seconds before display Scanning files message */\ntime_t scan_dot_time = 2; /* time in seconds between Scanning files dots */\ntime_t scan_start = 0;  /* start of scan */\ntime_t scan_last = 0;   /* time of last message */\nint scan_started = 0;   /* scan has started */\nuzoff_t scan_count = 0; /* Used for Scanning files ... message */\n\nulg before = 0;         /* 0=ignore, else exclude files before this time */\nulg after = 0;          /* 0=ignore, else exclude files newer than this time */\n\n/* Zip file globals */\nchar *zipfile;          /* New or existing zip archive (zip file) */\n\n/* zip64 support 08/31/2003 R.Nausedat */\n/* all are across splits - subtract bytes_prev_splits to get offsets for current disk */\nuzoff_t zipbeg;               /* Starting offset of zip structures */\nuzoff_t cenbeg;               /* Starting offset of central dir */\nuzoff_t tempzn;               /* Count of bytes written to output zip files */\n\n/* 10/28/05 */\nchar *tempzip = NULL;         /* name of temp file */\nFILE *y = NULL;               /* output file now global so can change in splits */\nFILE *in_file = NULL;         /* current input file for splits */\nchar *in_path = NULL;         /* base name of input archive file */\nchar *in_split_path = NULL;   /* in split path */\nchar *out_path = NULL;        /* base name of output file, usually same as zipfile */\nint zip_attributes = 0;\n\n/* in split globals */\n\nulg     total_disks = 0;        /* total disks in archive */\nulg     current_in_disk = 0;    /* current read split disk */\nuzoff_t current_in_offset = 0;  /* current offset in current read disk */\nulg     skip_current_disk = 0;  /* if != 0 and fix then skip entries on this disk */\n\n\n/* out split globals */\n\nulg     current_local_disk = 0;   /* disk with current local header */\n\nulg     current_disk = 0;         /* current disk number */\nulg     cd_start_disk = (ulg)-1;  /* central directory start disk */\nuzoff_t cd_start_offset = 0;      /* offset of start of cd on cd start disk */\nuzoff_t cd_entries_this_disk = 0; /* cd entries this disk */\nuzoff_t total_cd_entries = 0;     /* total cd entries in new/updated archive */\nulg     zip64_eocd_disk = 0;      /* disk with Zip64 End Of Central Directory Record */\nuzoff_t zip64_eocd_offset = 0;    /* offset for Zip64 EOCD Record */\n\n/* for split method 1 (keep split with local header open and update) */\nchar *current_local_tempname = NULL; /* name of temp file */\nFILE  *current_local_file = NULL; /* file pointer for current local header */\nuzoff_t current_local_offset = 0; /* offset to start of current local header */\n\n/* global */\nuzoff_t bytes_this_split = 0;     /* bytes written to the current split */\nint read_split_archive = 0;       /* 1=scanzipf_reg detected spanning signature */\nint split_method = 0;             /* 0=no splits, 1=seekable, 2=data desc, -1=no */\nuzoff_t split_size = 0;           /* how big each split should be */\nint split_bell = 0;               /* when pause for next split ring bell */\nuzoff_t bytes_prev_splits = 0;    /* total bytes written to all splits before this */\nuzoff_t bytes_this_entry = 0;     /* bytes written for this entry across all splits */\nint noisy_splits = 0;             /* note when splits are being created */\nint mesg_line_started = 0;        /* 1=started writing a line to mesg */\nint logfile_line_started = 0;     /* 1=started writing a line to logfile */\n\n#ifdef WIN32\n  int nonlocal_name = 0;          /* Name has non-local characters */\n  int nonlocal_path = 0;          /* Path has non-local characters */\n#endif\n#ifdef UNICODE_SUPPORT\n  int use_wide_to_mb_default = 0;\n#endif\n\nstruct zlist far *zfiles = NULL;  /* Pointer to list of files in zip file */\n/* The limit for number of files using the Zip64 format is 2^64 - 1 (8 bytes)\n   but extent is used for many internal sorts and other tasks and is generally\n   long on 32-bit systems.  Because of that, but more because of various memory\n   utilization issues limiting the practical number of central directory entries\n   that can be sorted, the number of actual entries that can be stored probably\n   can't exceed roughly 2^30 on 32-bit systems so extent is probably sufficient. */\nextent zcount;                    /* Number of files in zip file */\nint zipfile_exists = 0;           /* 1 if zipfile exists */\nush zcomlen;                      /* Length of zip file comment */\nchar *zcomment = NULL;            /* Zip file comment (not zero-terminated) */\nstruct zlist far **zsort;         /* List of files sorted by name */\n#ifdef UNICODE_SUPPORT\n  struct zlist far **zusort;      /* List of files sorted by zuname */\n#endif\n\n/* Files to operate on that are not in zip file */\nstruct flist far *found = NULL;   /* List of names found */\nstruct flist far * far *fnxt = &found;\n                                  /* Where to put next name in found list */\nextent fcount;                    /* Count of files in list */\n\n/* Patterns to be matched */\nstruct plist *patterns = NULL;  /* List of patterns to be matched */\nunsigned pcount = 0;            /* number of patterns */\nunsigned icount = 0;            /* number of include only patterns */\nunsigned Rcount = 0;            /* number of -R include patterns */\n\n#ifdef IZ_CHECK_TZ\nint zp_tz_is_valid;     /* signals \"timezone info is available\" */\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/Makefile.gcc",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for human68k\n# Written by NIIMI Satoshi <a01309@cfi.waseda.ac.jp>\n\nVPATH = human68k\n\nCC = gcc\nAS = as\n\n# if you are using mc68030 (or higher) based X68000,\n# uncomment following defines\n#CC = gcc -DUNALIGNED_OK\n#AS = as -s UNALIGNED_OK\n\nCFLAGS = -Wall -O -fomit-frame-pointer -fstrength-reduce -DASMV\nLDFLAGS = -s\nLIBS = -lsignal -lmb -ldos\n\n# object file lists\nOBJZ = zip.o zipfile.o zipup.o fileio.o util.o crc32.o globals.o \\\n\tcrypt.o ttyio.o\n\nOBJI = deflate.o trees.o\nOBJA = match.o human68k.o\nOBJU = zipfile_.o fileio_.o util_.o globals.o human68_.o\nOBJN = zipnote.o  $(OBJU)\nOBJC = zipcloak.o $(OBJU) crc32_.o crypt_.o ttyio.o\nOBJS = zipsplit.o $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h human68k/osdep.h\n\nall: zips\n\n.SUFFIXES: _.o .o .c\n.c_.o:\n\t$(CC) $(CFLAGS) -DUTIL -c $< -o $@\n.c.o:\n\t$(CC) $(CFLAGS) -c $< -o $@\n\nZIPS = zip.x zipnote.x zipsplit.x zipcloak.x\n\nzips: $(ZIPS)\n\nzip.x: $(OBJZ) $(OBJI) $(OBJA)\n\t$(CC) -o zip.x $(LDFLAGS) $(OBJZ) $(OBJI) $(OBJA) $(LIBS)\nzipnote.x: $(OBJN)\n\t$(CC) -o zipnote.x $(LDFLAGS) $(OBJN) $(LIBS)\nzipcloak.x: $(OBJC)\n\t$(CC) -o zipcloak.x $(LDFLAGS) $(OBJC) $(LIBS)\nzipsplit.x: $(OBJS)\n\t$(CC) -o zipsplit.x $(LDFLAGS) $(OBJS) $(LIBS)\n\nmatch.o: human68k/match.s\n\t$(AS) -o $@ $<\n\nhuman68_.o: human68k/human68k.c\n\t$(CC) $(CFLAGS) -DUTIL -c -o $@ $<\n\nclean:\n\trm -f *.o $(ZIPS)\n\nzip.bfd: $(ZIPS)\n\trm -f $@\n\tfor file in $(ZIPS); do \\\n\t\tbdif -A -R uploaded/$$file $$file $@; \\\n\tdone\n\n# rules for zip, zipnote, zipcloak, zipsplit.\n$(OBJZ): $(ZIP_H)\n$(OBJI): $(ZIP_H)\n$(OBJN): $(ZIP_H)\n$(OBJS): $(ZIP_H)\n$(OBJC): $(ZIP_H)\nzip.o crc32.o crypt.o fileio.o zipfile.o zipup.o: crc32.h\nzipcloak.o crc32_.o crypt_.o fileio_.o zipfile_.o: crc32.h\nzip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h\nzip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h\nzip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h\nzipup.o: human68k/zipup.h\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/crc_68.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_68 created by Paul Kienitz, last modified 04 Jan 96.\n;\n; Return an updated 32 bit CRC value, given the old value and a block of data.\n; The CRC table used to compute the value is gotten by calling get_crc_table().\n; This replaces the older updcrc() function used in Zip and fUnZip.  The\n; prototype of the function is:\n;\n;    ulg crc32(ulg crcval, uch *text, extent textlen);\n;\n; On the Amiga, type extent is always unsigned long, not unsigned int, because\n; int can be short or long at whim, but size_t is long.\n;\n; If using this source on a non-Amiga 680x0 system, note that we treat\n; a0/a1/d0/d1 as scratch registers not preserved across function calls.\n; We do not bother to support registerized arguments for crc32() -- the\n; textlen parm is usually large enough so that savings outside the loop\n; are pointless.\n;\n; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more\n; efficient on certain machines with dinky instruction caches ('020?), or for\n; processing short strings.  If loops are unrolled, the textlen parm must be\n; less than 512K; if not unrolled, it must be less than 64K.\n;\n; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.\n\n        xdef    _crc32          ; (ulg val, uch *buf, extent bufsize)\n\nDO_CRC0 MACRO\n        moveq  #0,ltemp\n        move.b (textbuf)+,ltemp\n        eor.b  crcval,ltemp\n        lsl.w  #2,ltemp\n        move.l (crc_table,ltemp.w),ltemp\n        lsr.l  #8,crcval\n        eor.l  ltemp,crcval\n        ENDM\n\n\nDO_CRC2 MACRO\n        move.b (textbuf)+,btemp\n        eor.b  crcval,btemp\n        lsr.l  #8,crcval\n        move.l (crc_table,btemp.w*4),ltemp\n        eor.l  ltemp,crcval\n        ENDM\n\ncrc_table       reg     a0      array of unsigned long\ncrcval          reg     d0      unsigned long initial value\ntextbuf         reg     a1      array of unsigned char\ntextbufsize     reg     d1      unsigned long (count of bytes in textbuf)\nbtemp           reg     d2\nltemp           reg     d3\n\n\n        xref    _get_crc_table  ; ulg *get_crc_table(void)\n\n\n\n        quad\n_crc32:\n        move.l  8(sp),d0\n        bne.s   valid\n;;;;;   moveq  #0,d0\n         rts\nvalid:  movem.l btemp/ltemp,-(sp)\n        jsr     _get_crc_table\n        movea.l d0,crc_table\n        move.l  12(sp),crcval\n        move.l  16(sp),textbuf\n        move.l  20(sp),textbufsize\n        not.l   crcval\n\n    ifdef   NO_UNROLLED_LOOPS\n\n    if CPU==68000\n        bra.s   decr\nloop:    DO_CRC0\ndecr:    dbra   textbufsize,loop\n        bra.s   done\n\n    else\ntwenty: moveq   #0,btemp\n        bra.s   decr2\nloop2:   DO_CRC2\ndecr2:   dbra   textbufsize,loop2\n    endif\n\n    ELSE    ; !NO_UNROLLED_LOOPS\n\n    if CPU==68000\n        moveq   #7,btemp\n        and     textbufsize,btemp\n        lsr.l   #3,textbufsize\n        bra     decr8\nloop8:   DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\n         DO_CRC0\ndecr8:   dbra   textbufsize,loop8\n        bra.s   decr1\nloop1:   DO_CRC0\ndecr1:   dbra   btemp,loop1\n        bra     done\n\n    else\ntwenty: moveq   #0,btemp\n        move.l  textbufsize,-(sp)\n        lsr.l   #3,textbufsize\n        bra     decr82\n         quad\nloop82:  DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\n         DO_CRC2\ndecr82:  dbra   textbufsize,loop82\n        moveq   #7,textbufsize\n        and.l   (sp)+,textbufsize\n        bra.s   decr12\nloop12:  DO_CRC2\ndecr12:  dbra   textbufsize,loop12\n    endif\n\n    ENDC    ; ?NO_UNROLLED_LOOPS\n\ndone:   movem.l (sp)+,btemp/ltemp\n        not.l   crcval\n;;;;;   move.l  crcval,d0               ; crcval already is d0\n        rts\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/deflate.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; This is a 680x0 assembly language translation of the Info-ZIP source file\n; deflate.c, by Paul Kienitz.  No rights reserved.  The function longest_match\n; is based in part on match.a by Carsten Steger, which in turn is partly based\n; on match.s for 386 by Jean-loup Gailly and Kai Uwe Rommel.  Mostly, however,\n; this material is based on deflate.c, by Gailly, Rommel, and Igor Mandrichenko.\n; This code is not commented very much; see deflate.c for comments that explain\n; what the functions are doing.\n;\n; The symbols that can be used to select different versions are as follows:\n;\n;   CPU020     if defined, use 68020 instructions always.\n;\n;   CPUTEST    if defined, check at runtime for CPU type.  Another symbol\n;               specifying the platform-specific test must be used with this.\n;               If neither of these is defined, use 68000 instructions only.\n;               Runtime test is nonportable; it is different for each OS.\n;\n;   AMIGA      use Amiga-specific test for 68020, if CPUTEST defined.  Also\n;               tells it that registers d0/a0/d1/a1 are not preserved by\n;               function calls.  At present, if AMIGA is not defined, it\n;               causes functions to preserve all registers.  ALL OF THIS CODE\n;               CURRENTLY ASSUMES THAT REGISTERS D2-D7/A2-A6 WILL BE PRESERVED\n;               BY ANY FUNCTIONS THAT IT CALLS.\n;\n;   DYN_ALLOC  should be defined here if it is defined for C source; tells us\n;               that big arrays are allocated instead of static.\n;\n;   WSIZE      must be defined as the same number used for WSIZE in the C\n;               source, and must be a power of two <= 32768.  As elsewhere,\n;               the default value is 32768.\n;\n;   INT16      define this if ints are 16 bits; otherwise 32 bit ints assumed.\n;\n;   SMALL_MEM  define this if it is defined in the C source; otherwise it uses\n;               the MEDIUM_MEM model.  BIG_MEM and MMAP are *not* supported.\n;               The FULL_SEARCH option in deflate.c is also not supported.\n;\n;   DEBUG      activates some tracing output, as in the C source.\n;\n;   QUADLONG   this selects a different version of the innermost longest_match\n;               loop code for 68020 operations, comparing bytes four at a time\n;               instead of two at a time.  It seems to be a tiny bit faster on\n;               average, but it's slower often enough that one can't generalize.\n;\n; This code currently assumes that function results are returned in D0 for\n; all platforms.  It assumes that args to functions are pushed onto the stack,\n; last arg first.  It also currently assumes that all C symbols have an\n; underscore prepended when referenced from assembly.\n;\n; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.\n\n    IFNDEF  CPU020\n     IFNDEF CPUTEST\nCPU000  equ     1\n     ENDC\n    ENDC\n\n; Use these macros for accessing variables of type int:\n    IFDEF   INT16\nMOVINT  MACRO   _1,_2\n        move.w  _1,_2\n        ENDM\nCLRINT  MACRO   _1\n        clr.w   _1\n        ENDM\nINTSIZE equ     2\n    ELSE    ; !INT16\nMOVINT  MACRO   _1,_2\n        move.l  _1,_2\n        ENDM\nCLRINT  MACRO   _1\n        clr.l   _1\n        ENDM\nINTSIZE equ     4\n    ENDC\n\n    IFDEF   DYN_ALLOC\nBASEPTR MACRO   _1,_2\n        move.l  _1,_2\n        ENDM\n    ELSE\nBASEPTR MACRO   _1,_2\n        lea     _1,_2\n        ENDM\n    ENDC\n\n; constants we use, many of them adjustable:\n\nMAX_MATCH       equ     258\nMIN_MATCH       equ     3\nTOO_FAR         equ     4096\n    IFNDEF  WSIZE\nWSIZE           equ     32768\n    ENDC\nWMASK           equ     WSIZE-1\nMAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1\nMIN_LOOKAHEAD   equ     MAX_MATCH+MIN_MATCH+1\n;    IFD     BIG_MEM      ; NOT supported -- type Pos needs to be 32 bits\n;HASH_BITS      equ     15\n;    ELSE\n    IFDEF  SMALL_MEM\nHASH_BITS       equ     13\n    ELSE\nHASH_BITS       equ     14      ; default -- MEDIUM_MEM\n    ENDC\n;    ENDC    ; BIG_MEM\nHASH_SIZE       equ     1<<HASH_BITS\nHASH_MASK       equ     HASH_SIZE-1\nH_SHIFT         equ     (HASH_BITS+MIN_MATCH-1)/MIN_MATCH\nB_SLOW          equ     1\nB_FAST          equ     2\nZE_MEM          equ     4\nEOF             equ     -1\n\n; struct config is defined by these offsets:\nGood_length     equ     0\nMax_lazy        equ     2\nNice_length     equ     4\nMax_chain       equ     6\nSizeof_config   equ     8\n\n\n; external functions we call:\n        xref    _ct_tally       ; int ct_tally(int, int)\n        xref    _flush_block    ; unsigned long F(char *, unsigned long, int)\n        xref    _ziperr         ; void ziperr(int, char *)\n        xref    _error          ; void error(char *)\n        xref    _calloc         ; stdlib function: void *calloc(size_t, size_t)\n        xref    _free           ; stdlib function: void free(void *)\n    IFDEF   DEBUG\n        xref    _fputc          ; stdio function: int fputc(int, FILE *)\n        xref    _stderr         ; pointer to FILE, which we pass to fputc\n    ENDC\n\n; our entry points:\n        xdef    _lm_init        ; void lm_init(int level, unsigned short *flags)\n        xdef    _lm_free        ; void lm_free(void)\n        xdef    _deflate        ; void deflate(void)  ...the big one\n        xdef    _fill_window    ; this line is just for debugging\n\n\n; ============================================================================\n; Here is where we have our global variables.\n\n;;;     section deflatevars,data\n\n; external global variables we reference:\n        xref    _verbose        ; signed int\n        xref    _level          ; signed int\n        xref    _read_buf       ; int (*read_buf)(char *, unsigned int)\n\n; global variables we make available:\n\n        xdef    _window\n        xdef    _prev\n        xdef    _head\n        xdef    _window_size\n        xdef    _block_start\n        xdef    _strstart\n\n        bss\n        quad\n\n    IFDEF   DYN_ALLOC\n_prev:          ds.l    1       ; pointer to calloc()'d unsigned short array\n_head:          ds.l    1       ; pointer to calloc()'d unsigned short array\n_window:        ds.l    1       ; pointer to calloc()'d unsigned char array\n    ELSE    ; !DYN_ALLOC\n_prev:          ds.w    WSIZE           ; array of unsigned short\n_head:          ds.w    HASH_SIZE       ; array of unsigned short\n_window:        ds.b    2*WSIZE         ; array of unsigned char\n    ENDC    ; ?DYN_ALLOC\n\n        text\n        quad\n_window_size:   ds.l    1               ; unsigned long\n_block_start:   ds.l    1               ; unsigned long\n_strstart:      ds.w    INTSIZE/2       ; unsigned int\n\n; Now here are our private variables:\n\n    IFDEF   CPUTEST\nis020:          ds.w    1       ; bool: CPU type is '020 or higher\n    ENDC\nins_h:          ds.w    1       ; unsigned short\nsliding:        ds.w    1       ; bool: the file is read a piece at a time\neofile:         ds.w    1       ; bool: we have read in the end of the file\nmax_lazy_match: ds.w    1       ; unsigned short\nlookahead:      ds.w    1       ; unsigned short\n\n; These are NOT DECLARED AS STATIC in deflate.c, but currently could be:\nmax_chain_len:  ds.w    1       ; unsigned short (unsigned int in deflate.c)\nprev_length:    ds.w    1       ; unsigned short (unsigned int in deflate.c)\ngood_match:     ds.w    1       ; unsigned short (unsigned int in deflate.c)\nnice_match:     ds.w    1       ; unsigned short (signed int in deflate.c)\nmatch_start:    ds.w    1       ; unsigned short (unsigned int in deflate.c)\n\n; This array of struct config is a constant and could be in the code section:\nconfig_table:   dc.w    0,0,0,0         ; level 0: store uncompressed\n                dc.w    4,4,8,4         ; level 1: fastest, loosest compression\n                dc.w    4,5,16,8        ; level 2\n                dc.w    4,6,32,32       ; level 3: highest to use deflate_fast\n                dc.w    4,4,16,16       ; level 4: lowest to use lazy matches\n                dc.w    8,16,32,32      ; level 5\n                dc.w    8,16,128,128    ; level 6: the default level\n                dc.w    8,32,128,256    ; level 7\n                dc.w    32,128,258,1024 ; level 8\n                dc.w    32,258,258,4096 ; level 9: maximum compression, slow\n\n\n;;CAL_SH  MACRO                   ; macro for calling zcalloc()\n;;     IFD    INT16\n;;        move.w  #2,-(sp)\n;;        move.w  #\\1,-(sp)\n;;        jsr     _zcalloc\n;;        addq    #4,sp\n;;     ELSE\n;;        pea     2\n;;        pea     \\1\n;;        jsr     _zcalloc\n;;        addq    #8,sp\n;;     ENDC\n;;        ENDM\n\nCAL_SH  MACRO   _1              ; Okay, we're back to using regular calloc()...\n        movem.l d2/a2,-(sp)\n        pea     2\n        pea     _1\n        jsr     _calloc\n        addq    #8,sp\n        movem.l (sp)+,d2/a2\n        ENDM\n\n; ============================================================================\n; And here we begin our functions.  match_init is for internal use only:\n\n;;      section deflate,code\n\nmatch_init:\n    IFDEF   CPUTEST             ; now check for platform type\n     IFDEF  AMIGA               ; Amiga specific test for '020 CPU:\n        xref    _SysBase\n        NOLIST\n        INCLUDE       'exec/execbase.i'\n        LIST\n\n        clr.w   is020                   ; default value is 68000\n        move.l  _SysBase,a0\n        btst    #AFB_68020,AttnFlags+1(a0)\n        beq.s   cheap\n        move.w  #1,is020\ncheap:\n     ELSE   ; !AMIGA\n\n        FAIL    Write an '020-detector for your system here!\n; On the Macintosh, I believe GetEnvironment() provides the information.\n\n     ENDC   ; AMIGA\n    ENDC    ; CPUTEST\n        rts     ; match_init consists only of rts if CPUTEST unset\n\n\n; ============================================================================\n; Here is longest_match(), the function that the rest of this was built up\n; from, the hottest hot spot in the program and therefore the most heavily\n; optimized.  It has two different versions, one for '020 and higher CPUs, and\n; one for 68000/68010.  It can test at runtime which version to use if you\n; create a test function in match_init for your platform.  Currently such a\n; test is implemented for the Amiga.  It can also be assembled to use '000 or\n; '020 code only.\n\nCur_Match       reg     d0              ; unsigned int, kept valid as long\nBest_Len        reg     d1              ; unsigned int, kept valid as long\nScan_Start      reg     d3              ; pair of bytes\nScan_End        reg     d4              ; pair of bytes\nLimit           reg     d5              ; unsigned int\nChain_Length    reg     d6              ; unsigned int\nScan_Test       reg     d7              ; counter, pair of bytes sometimes\nScan            reg     a0              ; pointer to unsigned char\nMatch           reg     a1              ; pointer to unsigned char\nPrev_Address    reg     a2              ; pointer to unsigned short\nScan_Ini        reg     a3              ; pointer to unsigned char\nMatch_Ini       reg     a5              ; pointer to unsigned char\n; Note: \"pair of bytes\" means the two low order bytes of the register in\n; 68020 code, but means the lowest and third lowest bytes on the 68000.\nSAVEREGS        reg     d3-d7/a2/a3/a5      ; don't protect d0/d1/a0/a1\n; d2, a4, a6 not used... on Amiga, a4 is used by small-data memory model\n\n\nlongest_match:\n        movem.l SAVEREGS,-(sp)\n\n; setup steps common to byte and word versions:\n    IFDEF   INT16\n        and.l   #$0000FFFF,Cur_Match    ; upper half must be zero!\n; we use an and.l down here for the sake of ATSIGN/REGARGS.\n        moveq   #0,Limit                ; so adding to Scan_Ini works\n    ENDC\n        move.w  (max_chain_len,pc),Chain_Length\n        move.w  (prev_length,pc),Best_Len\n        MOVINT  (_strstart,pc),Limit\n        BASEPTR _prev,Prev_Address\n        BASEPTR _window,Match_Ini\n        move.l  Match_Ini,Scan_Ini\n        addq    #MIN_MATCH,Match_Ini    ; optimizes inner loop\n        add.l   Limit,Scan_Ini\n        sub.w   #MAX_DIST,Limit\n        bhi.s   limit_ok\n        moveq   #0,Limit\nlimit_ok:\n        cmp.w   (good_match,pc),Best_Len\n        blo.s   length_ok\n        lsr.w   #2,Chain_Length\nlength_ok:\n        subq.w  #1,Chain_Length\n\n    IFDEF   CPUTEST\n        tst.w   is020                   ; can we use '020 stuff today?\n        bne     WORD_match\n    ENDC\n\n    IFNDEF  CPU020\n\n; for 68000 or 68010, use byte operations:\n        moveq   #0,Scan_Start           ; clear 2nd & 4th bytes, use 1st & 3rd\n        moveq   #0,Scan_End             ; likewise\n        moveq   #0,Scan_Test            ; likewise\n        move.b  (Scan_Ini),Scan_Start\n        swap    Scan_Start              ; swap is faster than 8 bit shift\n        move.b  1(Scan_Ini),Scan_Start\n        move.b  -1(Scan_Ini,Best_Len.w),Scan_End\n        swap    Scan_End\n        move.b  0(Scan_Ini,Best_Len.w),Scan_End\n        bra.s   bdo_scan\n\nblong_loop:\n        move.b  -1(Scan_Ini,Best_Len.w),Scan_End\n        swap    Scan_End\n        move.b  0(Scan_Ini,Best_Len.w),Scan_End\n\nbshort_loop:\n        add.w   Cur_Match,Cur_Match     ; assert value before doubling < 32K\n     IFNE   32768-WSIZE\n        and.w   #(WMASK*2),Cur_Match\n     ENDC\n        move.w  (Prev_Address,Cur_Match.l),Cur_Match\n        cmp.w   Limit,Cur_Match\n        dbls    Chain_Length,bdo_scan\n        bra     return\n\nbdo_scan:\n        move.l  Match_Ini,Match\n        add.l   Cur_Match,Match\n        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test\n        swap    Scan_Test\n        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test\n        cmp.l   Scan_Test,Scan_End\n        bne.s   bshort_loop\n        move.b  -MIN_MATCH(Match),Scan_Test\n        swap    Scan_Test\n        move.b  -MIN_MATCH+1(Match),Scan_Test\n        cmp.l   Scan_Test,Scan_Start\n        bne.s   bshort_loop\n        move.w  #(MAX_MATCH-3),Scan_Test\n        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop\n\nbscan_loop:\n        cmp.b   (Match)+,(Scan)+\n        dbne    Scan_Test,bscan_loop\n        subq    #1,Scan\n\n        sub.l   Scan_Ini,Scan           ; assert difference is 16 bits\n        cmp.w   Best_Len,Scan\n        bls.s   bshort_loop\n        MOVINT  Scan,Best_Len\n        move.w  Cur_Match,match_start\n        cmp.w   (nice_match,pc),Best_Len\n        blo.s   blong_loop\n     IFDEF  CPUTEST\n        bra     return\n     ENDC\n\n    ENDC    ; !CPU020\n\n    IFNDEF  CPU000\n;;;     MACHINE MC68020\n\n; for 68020 or higher, use word operations even on odd addresses:\nWORD_match:\n        move.w  (Scan_Ini),Scan_Start\n        move.w  -1(Scan_Ini,Best_Len.w),Scan_End\n        bra.s   wdo_scan\n\nwlong_loop:\n        move.w  -1(Scan_Ini,Best_Len.w),Scan_End\n\nwshort_loop:\n        and.w   #WMASK,Cur_Match\n        move.w  (Prev_Address,Cur_Match.w*2),Cur_Match  ; '020 addressing mode\n        cmp.w   Limit,Cur_Match\n        dbls    Chain_Length,wdo_scan\n        bra.s   return\n\nwdo_scan:\n        move.l  Match_Ini,Match\n        add.l   Cur_Match,Match\n        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End\n        bne.s   wshort_loop\n        cmp.w   -MIN_MATCH(Match),Scan_Start\n        bne.s   wshort_loop\n     IFDEF  QUADLONG\n; By some measurements, this version of the code is a little tiny bit faster.\n; But on some files it's slower.  It probably pays off only when there are\n; long match strings, and costs in the most common case of three-byte matches.\n        moveq   #((MAX_MATCH-MIN_MATCH)/16),Scan_Test     ; value = 15\n        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop\n\nwscan_loop:\n        cmp.l   (Match)+,(Scan)+                ; test four bytes at a time\n        bne.s   odd\n        cmp.l   (Match)+,(Scan)+\n        bne.s   odd\n        cmp.l   (Match)+,(Scan)+\n        bne.s   odd\n        cmp.l   (Match)+,(Scan)+\n        dbne    Scan_Test,wscan_loop            ; '020 can cache a bigger loop\nodd:\n        subq    #4,Scan\n        subq    #4,Match\n        cmp.b   (Match)+,(Scan)+        ; find good bytes in bad longword\n        bne.s   even\n        cmp.b   (Match)+,(Scan)+\n        bne.s   even\n        cmp.b   (Match)+,(Scan)+\n        beq.s   steven\neven:   subq    #1,Scan\n     ELSE   ; !QUADLONG\n        moveq   #((MAX_MATCH-MIN_MATCH)/2),Scan_Test    ; value = 127\n        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loop\n\nwscan_loop:\n        cmp.w   (Match)+,(Scan)+\n        dbne    Scan_Test,wscan_loop\n        subq    #2,Scan\n        move.b  -2(Match),Scan_Test\n        cmp.b   (Scan),Scan_Test\n        bne.s   steven\n        addq    #1,Scan\n     ENDC   ; ?QUADLONG\nsteven:\n        sub.l   Scan_Ini,Scan           ; assert: difference is 16 bits\n        cmp.w   Best_Len,Scan\n        bls.s   wshort_loop\n        MOVINT  Scan,Best_Len\n        move.w  Cur_Match,match_start\n        cmp.w   (nice_match,pc),Best_Len\n        blo.s   wlong_loop\n\n;;;     MACHINE MC68000\n    ENDC    ; !CPU000\n\nreturn:\n        MOVINT  Best_Len,d0         ; return value (upper half should be clear)\n        movem.l (sp)+,SAVEREGS\n        rts\n\n\n; =============================================================================\n; This is the deflate() function itself, our main entry point.  It calls\n; longest_match, above, and some outside functions.  It is a hot spot, but not\n; as hot as longest_match.  It uses no special '020 code.\n\n; ================== Several macros used in deflate() and later functions:\n\n; Arg 1 is D-reg that new ins_h value is to be left in,\n; arg 2 is the byte value to be hashed into it, which must not be the same reg\nUP_HASH MACRO   _1,_2\n        move.w  (ins_h,pc),_1\n        asl.w   #H_SHIFT,_1\n        eor.b   _2,_1\n        and.w   #HASH_MASK,_1           ; ((ins_h << H_SHIFT) ^ c) & HASH_MASK\n        move.w  _1,ins_h                ; ins_h = that\n        ENDM\n\n; Arg 1 is scratch A, arg 2 is scratch D\nIN_STR  MACRO   _1,_2\n        move.l  Strst,_2\n        addq.w  #MIN_MATCH-1,_2\n        move.b  (Window,_2.l),_2        ; window[strstart + MIN_MATCH - 1]\n        UP_HASH Head,_2\n        add.l   Head,Head               ; assert upper word is zero before add\n        BASEPTR _head,_1\n        add.l   Head,_1\n        move.w  (_1),Head               ; hash_head = head[ins_h]\n        move.w  Strst,(_1)              ; head[ins_h] = strstart\n        move.l  Strst,_2\n    IFNE    WSIZE-32768\n        and.w   #WMASK,_2\n    ENDC\n        add.w   _2,_2                   ; masks implicitly when WSIZE == 32768\n        move.w  Head,(Prev,_2.l)        ; prev[str_start & WMASK] = hash_head\n        ENDM\n\n; Arg 1 is bool (int) EOF flag, flush_block result is in d0, trashes d1/a0/a1\nFLUSH_B MACRO   _1\n        local   nenu,nun\n        movem.l d2/a2,-(sp)\n    IF      _1==0\n        CLRINT  -(sp)\n    ELSEIF (INTSIZE==4).and.(_1<$8000)\n        pea     (_1).w\n    ELSE\n        MOVINT  #_1,-(sp)\n    ENDC\n        move.l  (_block_start,pc),d0\n        blt.s   nenu\n        move.l  Window,a0\n        add.l   d0,a0\n        bra.s   nun\nnenu:   sub.l   a0,a0           ; if block_start < 0, push NULL\nnun:    sub.l   Strst,d0\n        neg.l   d0\n        move.l  d0,-(sp)\n        move.l  a0,-(sp)\n        jsr     _flush_block\n        lea     8+INTSIZE(sp),sp\n        movem.l (sp)+,d2/a2\n        ENDM\n\n; This expands to nothing unless DEBUG is defined.\n; Arg 1 is a byte to be trace-outputted -- if it is d0 it must be a valid int\nTRACE_C MACRO  _1\n        local  qui\n    IFDEF  DEBUG\n        cmp.w  #1,_verbose+INTSIZE-2    ; test lower word only\n        ble.s   qui\n        moveq   #0,d0\n        move.b  ea,d0\n        movem.l d2/a2,-(sp)\n        move.l  _stderr,-(sp)\n        MOVINT  d0,-(sp)\n        jsr     _fputc\n        addq.l  #4+INTSIZE,sp\n        movem.l (sp)+,d2/a2\nqui:\n    ENDC    ; DEBUG\n        ENDM\n\n; ================== Here are the register vars we use, and deflate() itself:\n\nWindow  reg     a2              ; cached address of window[]\nPrev    reg     a3              ; cached address of prev[]\nStrst   reg     d7              ; strstart cached as a longword\nLook    reg     d6              ; lookahead cached as short\nHead    reg     d5              ; local variable hash_head, short\nPrevL   reg     d4              ; prev_length cached as short\nMatchL  reg     d3              ; local variable match_length, unsigned short\nAvail   reg     d2              ; local variable available_match, bool\nPrevM   reg     a5              ; local variable prev_match, int in an A-reg\n\nDEFREGS reg     d3-d7/a3/a5\n\n\n_deflate:           ; first, setup steps common to deflate and deflate_fast:\n        movem.l DEFREGS,-(sp)\n    IFDEF   INT16\n        moveq   #0,Strst                ; make sure strstart is valid as a long\n    ENDC\n        moveq   #0,Head                 ; ditto for hash_head\n        MOVINT  (_strstart,pc),Strst\n        move.w  (lookahead,pc),Look\n        move.w  (prev_length,pc),PrevL\n        BASEPTR _window,Window\n        BASEPTR _prev,Prev\n        MOVINT  _level,d0\n        cmp.w   #3,d0\n        ble     deflate_fast\n        moveq   #MIN_MATCH-1,MatchL\n        moveq   #0,Avail\n\nlook_loop:\n        tst.w   Look\n        beq     last_tally\n        IN_STR  a0,d0\n        move.w  MatchL,PrevL\n        move.w  (match_start,pc),PrevM\n        move.w  #MIN_MATCH-1,MatchL\n\n        tst.w   Head\n        beq.s   no_new_match\n        cmp.w   (max_lazy_match,pc),PrevL\n        bhs.s   no_new_match\n        move.w  Strst,d0\n        sub.w   Head,d0\n        cmp.w   #MAX_DIST,d0\n        bhi.s   no_new_match\n        move.w  PrevL,prev_length       ; longest_match reads these variables\n        MOVINT  Strst,_strstart\n        MOVINT  Head,d0                 ; parm for longest_match\n        bsr     longest_match           ; sets match_start\n        cmp.w   Look,d0                 ; does length exceed valid data?\n        bls.s   stml\n        move.w  Look,d0\nstml:   move.w  d0,MatchL               ; valid length of match\n        cmp.w   #MIN_MATCH,MatchL       ; is the match only three bytes?\n        bne.s   no_new_match\n        move.w  (match_start,pc),d0\n        sub.w   Strst,d0\n        cmp.w   #-TOO_FAR,d0\n        bge.s   no_new_match\n        moveq   #MIN_MATCH-1,MatchL     ; mark the current match as no good\n\nno_new_match:\n        cmp.w   #MIN_MATCH,PrevL\n        blo     literal\n        cmp.w   MatchL,PrevL\n        blo     literal\n        ; CHECK_MATCH   Strst-1,PrevM,PrevL\n        MOVINT  Strst,_strstart         ; ct_tally reads this variable\n        move.l  PrevL,d0\n        subq.w  #MIN_MATCH,d0\n        movem.l d2/a2,-(sp)\n        MOVINT  d0,-(sp)\n        move.l  Strst,d0\n        sub.w   PrevM,d0\n        subq.w  #1,d0\n        MOVINT  d0,-(sp)\n        jsr     _ct_tally               ; sets d0 true if we have to flush\n        addq    #2*INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        subq.w  #3,PrevL                ; convert for dbra (prev_length - 2)\n        sub.w   PrevL,Look\n        subq.w  #2,Look\ninsertmatch:\n        addq.w  #1,Strst\n        IN_STR  a0,d1                   ; don't clobber d0\n        dbra    PrevL,insertmatch\n        moveq   #0,Avail\n        moveq   #0,PrevL                ; not needed?\n        moveq   #MIN_MATCH-1,MatchL\n        addq.w  #1,Strst\n        tst.w   d0\n        beq     refill\n        FLUSH_B 0\n        move.l  Strst,_block_start\n        bra.s   refill\n\nliteral:\n        tst.w   Avail\n        bne.s   yeslit\n        moveq   #1,Avail\n        bra.s   skipliteral\nyeslit: TRACE_C <-1(Window,Strst.l)>\n        MOVINT  Strst,_strstart         ; ct_tally reads this variable\n        moveq   #0,d0\n        move.b  -1(Window,Strst.l),d0\n        movem.l d2/a2,-(sp)\n        MOVINT  d0,-(sp)\n        CLRINT  -(sp)\n        jsr     _ct_tally\n        addq    #2*INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        tst.w   d0\n        beq.s   skipliteral\n        FLUSH_B 0\n        move.l  Strst,_block_start\nskipliteral:\n        addq.w  #1,Strst\n        subq.w  #1,Look\n\nrefill:\n        cmp.w   #MIN_LOOKAHEAD,Look\n        bhs     look_loop\n        bsr     fill_window\n        bra     look_loop\n\nlast_tally:\n        tst.w   Avail\n        beq     last_flush\n        MOVINT  Strst,_strstart         ; ct_tally reads this variable\n        moveq   #0,d0\n        move.b  -1(Window,Strst.l),d0\n        movem.l d2/a2,-(sp)\n        MOVINT  d0,-(sp)\n        CLRINT  -(sp)\n        jsr     _ct_tally\n        addq    #2*INTSIZE,sp\n        movem.l (sp)+,d2/a2\nlast_flush:\n        FLUSH_B 1\n        bra     deflate_exit\n\n; ================== This is another version used for low compression levels:\n\ndeflate_fast:\n        moveq   #0,MatchL\n        moveq   #MIN_MATCH-1,PrevL\nflook_loop:\n        tst.w   Look\n        beq     flast_flush\n\n        IN_STR  a0,d0\n        tst.w   Head\n        beq.s   fno_new_match\n        move.w  Strst,d0\n        sub.w   Head,d0\n        cmp.w   #MAX_DIST,d0\n        bhi.s   fno_new_match\n        move.w  PrevL,prev_length       ; longest_match reads these variables\n        MOVINT  Strst,_strstart\n        MOVINT  Head,d0                 ; parm for longest_match\n        bsr     longest_match           ; sets match_start\n        cmp.w   Look,d0                 ; does length exceed valid data?\n        bls.s   fstml\n        move.w  Look,d0\nfstml:  move.w  d0,MatchL               ; valid length of match\n\nfno_new_match:\n        cmp.w   #MIN_MATCH,MatchL\n        blo     fliteral\n        ; CHECK_MATCH   Strst,match_start,MatchL\n        MOVINT  Strst,_strstart         ; ct_tally reads this variable\n        move.l  MatchL,d0\n        subq.w  #MIN_MATCH,d0\n        movem.l d2/a2,-(sp)\n        MOVINT  d0,-(sp)\n        move.l  Strst,d0\n        sub.w   (match_start,pc),d0\n        MOVINT  d0,-(sp)\n        jsr     _ct_tally               ; sets d0 true if we have to flush\n        addq    #2*INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        sub.w   MatchL,Look\n        cmp.w   (max_lazy_match,pc),MatchL\n        bhi     ftoolong\n        subq.w  #2,MatchL\nfinsertmatch:\n        addq.w  #1,Strst\n        IN_STR  a0,d1                   ; preserve d0\n        dbra    MatchL,finsertmatch\n        moveq   #0,MatchL               ; not needed?\n        addq.w  #1,Strst\n        bra.s   flushfill\n\nftoolong:\n        add.w   MatchL,Strst\n        moveq   #0,MatchL\n        moveq   #0,d1                   ; preserve d0\n        move.b  (Window,Strst.l),d1\n        move.w  d1,ins_h\n; My assembler objects to passing <1(Window,Strst.l)> directly to UP_HASH...\n        move.b  1(Window,Strst.l),Avail ; Avail is not used in deflate_fast\n        UP_HASH d1,Avail                ; preserve d0\n    IFNE    MIN_MATCH-3\n        FAIL  needs to UP_HASH another MIN_MATCH-3 times, but with what arg?\n    ENDC\n        bra.s   flushfill\n\nfliteral:\n        TRACE_C <(Window,Strst.l)>\n        MOVINT  Strst,_strstart         ; ct_tally reads this variable\n        moveq   #0,d0\n        move.b  (Window,Strst.l),d0\n        movem.l d2/a2,-(sp)\n        MOVINT  d0,-(sp)\n        CLRINT  -(sp)\n        jsr     _ct_tally               ; d0 set if we need to flush\n        addq    #2*INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        addq.w  #1,Strst\n        subq.w  #1,Look\n\nflushfill:\n        tst.w   d0\n        beq.s   frefill\n        FLUSH_B 0\n        move.l  Strst,_block_start\nfrefill:\n        cmp.w   #MIN_LOOKAHEAD,Look\n        bhs     flook_loop\n        bsr     fill_window\n        bra     flook_loop\n\nflast_flush:\n        FLUSH_B 1                       ; sets our return value\n\ndeflate_exit:\n        MOVINT  Strst,_strstart         ; save back cached values\n        move.w  PrevL,prev_length\n        move.w  Look,lookahead\n        movem.l (sp)+,DEFREGS\n        rts\n\n\n; =========================================================================\n; void fill_window(void) calls the input function to refill the sliding\n; window that we use to find substring matches in.\n\nMore    reg     Head                    ; local variable in fill_window\nWindTop reg     Prev                    ; local variable used for sliding\nSlidIx  reg     PrevL                   ; local variable used for sliding\n\nFWREGS  reg     d2-d5/a2-a6             ; does NOT include Look and Strst\n; all registers available to be clobbered by the sliding operation:\n; we exclude More, WindTop, SlidIx, Look, Strst, Window, a4 and a7.\nSPAREGS reg     d0-d3/a0-a1/a5-a6\nSPCOUNT equ     8                       ; number of registers in SPAREGS\n\n\n_fill_window:                           ; C-callable entry point\n        movem.l Look/Strst,-(sp)\n    IFDEF   INT16\n        moveq   #0,Strst                ; Strst must be valid as a long\n    ENDC\n        MOVINT  (_strstart,pc),Strst\n        move.w  (lookahead,pc),Look\n        BASEPTR _window,Window\n        bsr.s   fill_window\n        MOVINT  Strst,_strstart\n        move.w  Look,lookahead\n        movem.l (sp)+,Look/Strst\n        rts\n\n; strstart, lookahead, and window must be cached in Strst, Look, and Window:\nfill_window:                            ; asm-callable entry point\n        movem.l FWREGS,-(sp)\n        move.w  (eofile,pc),d0          ; we put this up here for speed\n        bne     fwdone\n        and.l   #$FFFF,Look             ; make sure Look is valid as long\nfw_refill:\n        move.l  (_window_size,pc),More  ; <= 64K\n        sub.l   Look,More\n        sub.l   Strst,More              ; Strst is already valid as long\n        cmp.w   #EOF,More\n        bne.s   notboundary\n        subq.w  #1,More\n        bra     checkend\n\nnotboundary:\n        move.w  (sliding,pc),d0\n        beq     checkend\n        cmp.w   #WSIZE+MAX_DIST,Strst\n        blo     checkend\n    IF      (32768-WSIZE)>0\n        lea     WSIZE(Window),WindTop   ; WindTop is aligned when Window is\n    ELSE\n        move.l  Window,WindTop\n        add.l   #WSIZE,WindTop\n    ENDC\n        move.l  Window,d0\n        and.w   #3,d0\n        beq.s   isaligned\n        subq.w  #1,d0\nalign:  move.b  (WindTop)+,(Window)+    ; copy up to a longword boundary\n        dbra    d0,align\nisaligned:\n; This is faster than a simple move.l (WindTop)+,(Window)+ / dbra loop:\n        move.w  #(WSIZE-1)/(4*SPCOUNT),SlidIx\nslide:  movem.l (WindTop)+,SPAREGS      ; copy, 32 bytes at a time!\n        movem.l SPAREGS,(Window)        ; a slight overshoot doesn't matter.\n        lea     4*SPCOUNT(Window),Window        ; can't use (aN)+ as movem.l dest\n        dbra    SlidIx,slide\n        BASEPTR _window,Window                  ; restore cached value\n        sub.w   #WSIZE,match_start\n        sub.w   #WSIZE,Strst\n        sub.l   #WSIZE,_block_start\n        add.w   #WSIZE,More\n        BASEPTR _head,a0\n        move.w  #HASH_SIZE-1,d0\nfixhead:\n        move.w  (a0),d1\n        sub.w   #WSIZE,d1\n        bpl.s   headok\n        moveq   #0,d1\nheadok: move.w  d1,(a0)+\n        dbra    d0,fixhead\n        BASEPTR _prev,a0\n        move.w  #WSIZE-1,d0\nfixprev:\n        move.w  (a0),d1\n        sub.w   #WSIZE,d1\n        bpl.s   prevok\n        moveq   #0,d1\nprevok: move.w  d1,(a0)+\n        dbra    d0,fixprev\n        TRACE_C #'.'\n\n        move    _verbose+INTSIZE-2,d0\n        beq     checkend\n        movem.l d2/a2,-(sp)\n        xref    _print_period\n        jsr     _print_period\n        movem.l (sp)+,d2/a2\n\ncheckend:                               ; assert eofile is false\n        movem.l d2/a2,-(sp)\n        MOVINT  More,-(sp)              ; assert More's upper word is zero\n        move.l  Strst,d0\n        add.w   Look,d0\n        add.l   Window,d0\n        move.l  d0,-(sp)\n        move.l  _read_buf,a0\n        jsr     (a0)                    ; refill the upper part of the window\n        addq    #4+INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        tst.w   d0\n        beq.s   iseof\n        cmp.w   #EOF,d0\n        beq.s   iseof\n        add.w   d0,Look\n        cmp.w   #MIN_LOOKAHEAD,Look\n        blo     fw_refill               ; eofile is still false\n\n        bra.s   fwdone\niseof:  move.w  #1,eofile\nfwdone: movem.l (sp)+,FWREGS\n        rts\n\n\n; =========================================================================\n; void lm_free(void) frees dynamic arrays in the DYN_ALLOC version.\n\n;;;     xdef    _lm_free                ; the entry point\n\n_lm_free:\n    IFDEF   DYN_ALLOC\n        move.l  _window,d0\n        beq.s   lf_no_window\n        movem.l d2/a2,-(sp)\n        move.l  d0,-(sp)\n        jsr     _free\n        addq    #4,sp\n        movem.l (sp)+,d2/a2\n        clr.l   _window\nlf_no_window:\n        move.l  _prev,d0\n        beq.s   lf_no_prev\n        movem.l d2/a2,-(sp)\n        move.l  d0,-(sp)\n        jsr     _free\n        move.l  _head,(sp)              ; reuse the same stack arg slot\n        jsr     _free\n        addq    #4,sp\n        movem.l (sp)+,d2/a2\n        clr.l   _prev\n        clr.l   _head\nlf_no_prev:\n    ENDC\n        rts\n\n; ============================================================================\n; void lm_init(int pack_level, unsigned short *flags) allocates dynamic arrays\n; if any, and initializes all variables so that deflate() is ready to go.\n\n;;;     xdef    _lm_init                ; the entry point\n\nLevel   reg     d2\n;Window reg     a2      ; as in deflate()\n\n_lm_init:\n        MOVINT  4(sp),d0\n        move.l  4+INTSIZE(sp),a0\n        move.w  d0,Level\n        cmp.w   #1,Level\n        blt.s   levelerr\n        bgt.s   try9\n        bset.b  #B_FAST,1(a0)\ntry9:   cmp.w   #9,Level\n        bgt.s   levelerr\n        blt.s   levelok\n        bset.b  #B_SLOW,1(a0)\n        bra.s   levelok\nlevelerr:\n        pea     (level_message,pc)\n        jsr     _error                  ; never returns\nlevelok:\n        clr.w   sliding\n        move.l  (_window_size,pc),d0\n        bne.s   gotawindowsize\n        move.w  #1,sliding\n        move.l  #2*WSIZE,_window_size\ngotawindowsize:\n\n        BASEPTR _window,Window\n    IFDEF   DYN_ALLOC\n        move.l  Window,d0               ; fake tst.l\n        bne.s   gotsomewind\n        CAL_SH  WSIZE\n        move.l  d0,Window\n        move.l  d0,_window\n        bne.s   gotsomewind\n        pea     (window_message,pc)\n        bra     error\ngotsomewind:\n        tst.l   _prev\n        bne.s   gotsomehead\n        CAL_SH  WSIZE\n        move.l  d0,_prev\n        beq.s   nohead\n        CAL_SH  HASH_SIZE\n        move.l  d0,_head\n        bne.s   gotfreshhead            ; newly calloc'd memory is zeroed\nnohead: pea     (hash_message,pc)\nerror:  MOVINT  #ZE_MEM,-(sp)\n        jsr     _ziperr                 ; never returns\ngotsomehead:\n    ENDC    ; DYN_ALLOC\n\n        move.w  #(HASH_SIZE/2)-1,d0     ; two shortwords per loop\n        BASEPTR _head,a0\nwipeh:  clr.l   (a0)+\n        dbra    d0,wipeh\ngotfreshhead:\n        move.l  Level,d0\n    IFEQ    Sizeof_config-8\n        asl.l   #3,d0\n    ELSE\n        mulu    #Sizeof_config,d0\n    ENDC\n        lea     (config_table,pc),a0\n        add.l   d0,a0\n        move.w  Max_lazy(a0),max_lazy_match\n        move.w  Good_length(a0),good_match\n        move.w  Nice_length(a0),nice_match\n        move.w  Max_chain(a0),max_chain_len\n        CLRINT  _strstart\n        clr.l   _block_start\n        bsr     match_init\n\n        clr.w   eofile\n        movem.l d2/a2,-(sp)\n        MOVINT  #WSIZE,-(sp)    ; We read only 32K because lookahead is short\n        move.l  Window,-(sp)    ; even when int size is long, as if deflate.c\n        move.l  _read_buf,a0    ; were compiled with MAXSEG_64K defined.\n        jsr     (a0)\n        addq    #4+INTSIZE,sp\n        movem.l (sp)+,d2/a2\n        move.w  d0,lookahead\n        beq.s   noread\n        cmp.w   #EOF,d0\n        bne.s   irefill\nnoread: move.w  #1,eofile\n        clr.w   lookahead\n        bra.s   init_done\n\nirefill:\n        move.w  (lookahead,pc),d0\n        cmp.w   #MIN_LOOKAHEAD,d0\n        bhs.s   hashify\n        bsr     _fill_window            ; use the C-callable version\nhashify:\n        clr.w   ins_h\n        moveq   #MIN_MATCH-2,d0\nhash1:  move.b  (Window)+,d1\n        UP_HASH Level,d1\n        dbra    d0,hash1\n\ninit_done:\n        rts\n\n; strings for error messages:\n    IFDEF   DYN_ALLOC\nhash_message    dc.b    'hash table allocation',0\nwindow_message  dc.b    'window allocation',0\n    ENDC\nlevel_message   dc.b    'bad pack level',0\n\n        end\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/human68k.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#include <time.h>\n#include <stdio.h>\n#include <dirent.h>\n#ifndef UTIL\n#include <sys/dos.h>\n#endif\n\n#define MATCH shmatch\n\n#define PAD 0\n\n\n#ifndef UTIL\n\n/* Library functions not in (most) header files */\n\nint utime OF((char *, ztimbuf *));\n\n/* Local functions */\nlocal char *readd OF((DIR *));\n\nlocal char *readd(DIR* d)\n{\n   struct dirent* e = readdir(d);\n\n   return e == NULL ? NULL : e->d_name;\n}\n\nint wild(char* w)\n{\n  struct _filbuf inf;\n  /* convert FNAMX to malloc - 11/08/04 EG */\n  char *name;\n  char *p;\n\n  if (strcmp(w, \"-\") == 0)   /* if compressing stdin */\n    return newname(w, 0, 0);\n  if ((name = malloc(strlen(w) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wild\");\n  }\n  strcpy(name, w);\n  _toslash(name);\n\n  if ((p = strrchr(name, '/')) == NULL && (p = strrchr(name, ':')) == NULL)\n    p = name;\n  else\n    p++;\n  if (_dos_lfiles (&inf, w, 0xff) < 0) {\n    free(name);\n    return ZE_MISS;\n  }\n  do {\n    int r;\n\n    strcpy(p, inf.name);\n    r = procname(name, 0);\n    if (r != ZE_OK) {\n      free(name);\n      return r;\n    }\n  } while (_dos_nfiles(&inf) >= 0);\n  free(name);\n\n  return ZE_OK;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  _toslash(n);\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n\n  /* Find starting point in name before doing malloc */\n  t = (x[0] && x[1] == (char)':') ? x + 2 : x;\n  while (*t == (char)'/')\n    t++;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  _toslash(t);\n\n  if (!pathput)\n    t = last(t, '/');\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosify;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n  return strcpy(x, n);\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  ztimbuf u;            /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, &u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n  isstdin = !strcmp(f, \"-\");\n\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (isstdin) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n    int atr = _dos_chmod(name, -1);\n\n    if (atr < 0)\n      atr = 0x20;\n    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)atr);\n  }\n  free(name);\n  if (n != NULL)\n    *n = S_ISVOL(s.st_mode) ? -2L : S_ISREG(s.st_mode) ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n#ifdef USE_EF_UT_TIME\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n\n  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));\n  z->cextra = z->extra;\n\n  return ZE_OK;\n#else /* !USE_EF_UT_TIME */\n  return (int)(z-z);\n#endif /* ?USE_EF_UT_TIME */\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return rmdir(d);\n}\n\nvoid print_period(void)\n{\n  fputc('.', stderr);\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#if 0\n    char buf[40];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#endif\n\n      \"Human68k\",\n#ifdef __MC68020__\n      \" (X68030)\",\n#else\n      \" (X680x0)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/match.s",
    "content": "*===========================================================================\n* Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n*\n* See the accompanying file LICENSE, version 1999-Oct-05 or later\n* (the contents of which are also included in zip.h) for terms of use.\n* If, for some reason, both of these files are missing, the Info-ZIP license\n* also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*===========================================================================\n*\n* match.s -- optional optimized asm version of longest match in deflate.c\n* Written by Jean-loup Gailly\n*\n* Adapted for X68000 by NIIMI Satoshi <a01309@cfi.waseda.ac.jp>\n* Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>\n* using the code in match.S.\n* The major change in this code consists of removing all unaligned\n* word accesses, because they cause 68000-based machines to crash.\n* For maximum speed, UNALIGNED_OK can be defined.\n* The program will then only run on 68020-based machines, though.\n\n\nCur_Match       reg     d0      ; Must be in d0!\nBest_Len        reg     d1\nLoop_Counter    reg     d2\nScan_Start      reg     d3\nScan_End        reg     d4\nLimit           reg     d5\nChain_Length    reg     d6\nScan_Test       reg     d7\nScan            reg     a0\nMatch           reg     a1\nPrev_Address    reg     a2\nScan_Ini        reg     a3\nMatch_Ini       reg     a4\n\nMAX_MATCH       equ     258\nMIN_MATCH       equ     3\nWSIZE           equ     32768\nMAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1\n\n\n        .xref   _max_chain_length\n        .xref   _prev_length\n        .xref   _prev\n        .xref   _window\n        .xref   _strstart\n        .xref   _good_match\n        .xref   _match_start\n        .xref   _nice_match\n\n\n        .xdef   _match_init\n        .xdef   _longest_match\n\n        .text\n        .even\n\n\n_match_init:\n        rts\n\n\n_longest_match:\n        move.l  4(sp),Cur_Match\n.ifdef  UNALIGNED_OK\n        movem.l d2-d6/a2-a4,-(sp)\n.else\n        movem.l d2-d7/a2-a4,-(sp)\n.endif\n        move.l  _max_chain_length,Chain_Length\n        move.l  _prev_length,Best_Len\n        lea     _prev,Prev_Address\n        lea     _window+MIN_MATCH,Match_Ini\n        move.l  _strstart,Limit\n        move.l  Match_Ini,Scan_Ini\n        add.l   Limit,Scan_Ini\n        subi.w  #MAX_DIST,Limit\n        bhi.b   limit_ok\n        moveq   #0,Limit\nlimit_ok:\n        cmp.l   _good_match,Best_Len\n        bcs.b   length_ok\n        lsr.l   #2,Chain_Length\nlength_ok:\n        subq.l  #1,Chain_Length\n\n.ifdef  UNALIGNED_OK\n        move.w  -MIN_MATCH(Scan_Ini),Scan_Start\n        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End\n.else\n        move.b  -MIN_MATCH(Scan_Ini),Scan_Start\n        lsl.w   #8,Scan_Start\n        move.b  -MIN_MATCH+1(Scan_Ini),Scan_Start\n        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End\n        lsl.w   #8,Scan_End\n        move.b  -MIN_MATCH(Scan_Ini,Best_Len.w),Scan_End\n.endif\n\n        bra.b   do_scan\n\nlong_loop:\n\n.ifdef  UNALIGNED_OK\n        move.w  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End\n.else\n        move.b  -MIN_MATCH-1(Scan_Ini,Best_Len.w),Scan_End\n        lsl.w   #8,Scan_End\n        move.b  -MIN_MATCH(Scan_Ini,Best_Len.w),Scan_End\n.endif\n\nshort_loop:\n        lsl.w   #1,Cur_Match\n        move.w  0(Prev_Address,Cur_Match.l),Cur_Match\n        cmp.w   Limit,Cur_Match\n        dbls    Chain_Length,do_scan\n        bra.b   return\n\ndo_scan:\n        move.l  Match_Ini,Match\n        add.l   Cur_Match,Match\n\n.ifdef  UNALIGNED_OK\n        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End\n        bne.b   short_loop\n        cmp.w   -MIN_MATCH(Match),Scan_Start\n        bne.b   short_loop\n.else\n        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test\n        lsl.w   #8,Scan_Test\n        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test\n        cmp.w   Scan_Test,Scan_End\n        bne.b   short_loop\n        move.b  -MIN_MATCH(Match),Scan_Test\n        lsl.w   #8,Scan_Test\n        move.b  -MIN_MATCH+1(Match),Scan_Test\n        cmp.w   Scan_Test,Scan_Start\n        bne.b   short_loop\n.endif\n\n        move.w  #(MAX_MATCH-MIN_MATCH),Loop_Counter\n        move.l  Scan_Ini,Scan\nscan_loop:\n        cmpm.b  (Match)+,(Scan)+\n        dbne    Loop_Counter,scan_loop\n\n        sub.l   Scan_Ini,Scan\n        addq.l  #(MIN_MATCH-1),Scan\n        cmp.l   Best_Len,Scan\n        bls.b   short_loop\n        move.l  Scan,Best_Len\n        move.l  Cur_Match,_match_start\n        cmp.l   _nice_match,Best_Len\n        bcs.b   long_loop\nreturn:\n        move.l  Best_Len,d0\n.ifdef  UNALIGNED_OK\n        movem.l (sp)+,d2-d6/a2-a4\n.else\n        movem.l (sp)+,d2-d7/a2-a4\n.endif\n        rts\n\n        end\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include <io.h>\n#include <sys/stat.h>\n#include <sys/xglob.h>\n\n#ifdef ZCRYPT_INTERNAL\n#  include <process.h>          /* getpid() declaration for srand seed */\n#endif\n\n#define USE_CASE_MAP\n\n#define ROUNDED_TIME(time)  (((time) + 1) & (~1))\n\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#ifdef HAVE_MBCTYPE_H\n#  include <mbctype.h>\n#else\n#  define ismbblead(c) (0x80 <= (c) && ((c) < 0xa0 || 0xe0 <= (c)))\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/human68k/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow (O_RDONLY|O_BINARY)\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/macos/Contents",
    "content": "Contents of the \"macos\" sub-archive for Zip 2.3 and later:\n\n\nMacOS:\n\n  Contents          this file\n  readme.1st        Instruction to unpack mac specific files\n  README.TXT        Dirk Haase's infos on updated MacIntosh ports of Zip/UnZip\n  HISTORY.TXT       Dirk Haase's MacOS specific ChangeLog\n\n  zipup.h           MacOS\n  osdep.h           MacOS specific configuration and declarations\n\n  ZipLib.h          used to build a static library, global to the project\n  ZipSx.h           used to build a standalone App with MW Sioux, global\n                    to the project\n  ZpPrj.hqx         Metrowerks CodeWarrior pro3 project file (BinHex)\n\n\n  source/        subdirectory containing all sources:\n                  a) Zip specific code\n    extrafld.c      contains all code related to the mac extra field\n    extrafld.h\n    macglob.h\n    macopen.c       replaces fopen() and open()\n    macopen.h\n    macos.c         Macintosh-specific routines for use with Info-ZIP's Zip\n    MatWild.c       Pattern matching function\n    recurse.c       Functions to go through the directories\n    recurse.h\n    unixlike.c      This file provides a unix like file-stat routine\n    unixlike.h\n    VolWarn.h       contains the warning message, about volumes with the\n                    same name\n    zip_rc.hqx      resource file for Macintosh unzip (BinHex)\n\n\n                  b) general utilities shared between Zip and UnZip\n    charmap.h       character mapping tables ISO 8859-1 <--> MacRoman\n    helpers.c       some helper functions\n    helpers.h\n    macstuff.c      Mac filemanager routines copied from MoreFiles 1.4.8\n    macstuff.h\n    mactime.c       replacement for broken Metrowerks RTL time functions\n    pathname.c      functions for handling MacOS HFS path- /filenames\n    pathname.h\n\nThe new ZpPrj.hqx project file should be \"un-BinHex'ed\" into ZpPrj,\nwhich builds the following targets:\n        - Zip Lib (68K)   -> static library 68k\n        - Zip Lib (PPC)   -> static library PPC\n        - Zip Sioux (68K) -> MW Sioux standalone App, good for debugging\n        - Zip Sioux (PPC) -> MW Sioux standalone App, good for debugging\n\n\nThe resource files and the compiler project files are in BinHex form because\nthey contain Macintosh resource forks.  The resource info cannot be\nmaintained when handling (e.g. repacking) the master source collection on\nnon-Macintosh systems.  The BinHex form is the traditional way for\ntransferring such files via non-Macintosh systems.\nIt's also the safest since it uses only printable characters.  The \".hqx\"\nfiles must be converted with StuffitExpander or BinHex 4.0 (or equivalent)\non a Macintosh system before using them.\n"
  },
  {
    "path": "deps/infozip/zip30/macos/HISTORY.TXT",
    "content": "A free Macintosh Port of Info-ZIP's\nZip and UnZip\nBy Dirk Haase, d_haase@sitec.net\nHome page: www.sitec.net/maczip\nMirror page:\nwww.haase-online.de/dirk/maczip\n================================\n\n\n\n\n\nRelease MacZip ver1.07 beta 1\n22. Februray 2001\n-----------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.42\n\n2) CHG: {zip} switch to latest beta release\n         zip 2.40a\n\n\n\n\n\nRelease MacZip ver1.06 final\n22. Februray 2001\n-----------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.42\n\n2) CHG: switch to latest release of Apples\n        Universal Interfaces 3.3.2\n\n3) CHG: switch to latest release of\n        Morefiles 1.5\n\n\n\n\nRelease MacZip ver1.06 beta 2\n02. August 2000\n---------------\n\n1) CHG: {unzip} switch to latest beta release\n         unzip 5.42d\n\n\n\n\n\nRelease MacZip ver1.06 beta 1\n27. July 2000\n-------------\n\n1) CHG: {zip} switch to latest beta release\n         unzip 2.30\n\n2) CHG: {unzip} switch to latest beta release\n         unzip 5.42c\n\n\n\n\n\nRelease MacZip ver1.05 final\n27. July 2000\n-------------\n\n1) CHG: {unzip} switch to latest final release\n         unzip 5.41\n\n2) FIX: {unzip} Fixed \"unique unzip folder\" foldername handling\n\n3) FIX: {unzip} added prototype crc32() in macbin3.c\n\n4) CHG: {unzip/zip} added exported Codewarrior project-file in xml-format\n\n5) ADD: {unzip} added extra-field recognition for Mac SmartZip in\n         zipinfo.c and unzpriv.h.\n\n\n\n\n\nRelease MacZip ver1.04 final\n25. January 2000\n----------------\n\n\nFinal release of MacZip. All parts now\nin final release state !!\n\n1) Switch to MW Codewarrior pro 5.3\n\n2) CHG: {zip} switch (back) to latest final release\n         unzip 2.30\n\n3) CHG: {unzip} switch (back) to latest final release\n         unzip 5.40\n\n\n\n\nRelease MacZip ver1.04 beta 3\n05. October 1999\n----------------\n\n1) CHG: {zip} switch to latest source level\n         unzip 2.30o beta release\n\n2) CHG: {unzip} switch to latest source level\n         unzip 5.41c beta release\n\n3) ADD: {console} added menu to print the license\n\n\n\n\nRelease MacZip ver1.04 beta 2\n02. June 1999\n--------------\n\n1) FIX: {unzip} added one more criteria to make the recognition\n         of macbinary more save.\n\n2) FIX: {unzip} sometimes, archive entries without any extra field\n         caused problems; the default setting of the extra field\n         was not set back to 'unknown' properly.\n\n3) FIX: {zip} Archive filename with invalid characters like '/' gets\n         renamed. However, I do not check the complete path - needs\n         some more work here.\n\n4) FIX: {zip} Filename match was case sensitive.\n\n6) CHG: {zip} switch to latest source level\n         unzip 2.30m beta release\n\n7) CHG: {unzip} switch to latest source level\n         unzip 5.41b beta release\n\n8) FIX: {zip/unzip 68k only) I have found a wrong compiler setting\n         for the 68k version. Because of this wrong setting the 68k\n         version crashed.\n\n\n\n\nRelease MacZip ver1.04 beta 1\n30. March 1999\n--------------\n\n1) CHG: {unzip) switch to latest source level\n         unzip 5.41a beta release\n\n2) ADD: {all} Added message logging support for Syslogd\n        by Brian Bergstrand. Syslogd can be found at\n        http://www.classicalguitar.net/brian/apps/syslogd/\n        This feature is 'under construction'.\n\n3) FIX: {all} many small fixes and code cleanups\n\n\n\n\nRelease MacZip ver1.03\n27. March 1999\n--------------\n\n1) CHG: {console} Like Stuffit Expander MacZip quits automatically when\n         used with drag'n drop or as Helper App (Web-Browser).\n\n2) CHG: {console} Since Macintosh users are used to be guided by their\n        software in order not to do something stupid, I added a check\n        to post an extra warning if the options -m and data fork only\n        are both checked.\n        This behavior can be disabled: See Applescript example and\n        \"maczip.env\".\n\n3) CHG: {zip} switch from immediate deletion to moving to the\n        trash. Immediate deletion is now an option in \"maczip.env\".\n\n4) CHG: {zip} enhanced progress display.\n\n5) CHG: {zip) switch to latest source level\n         zip 2.3l beta release\n\n6) CHG: {unzip} The zip archive contains file names greater than\n        31 characters. When MacZip tries to unzip the file, the\n        FSpCreate command fails because the filename length is to\n        long. MacZip correct this problem by trying to truncate\n        the file names to the 31 character limit.\n\n7) FIX: {zip/console} A couple of minor fixes\n\n8) CHG: {zip} Switched file-globbing to the Info-ZIP version.\n\n\n\n\nRelease MacZip ver1.02\n14. February 1999\n-----------------\n\n1) CHG: {zip} Changed the rule of file inclusion if switch '-X'\n        is set. Following conditions are checked:\n        a) if length of resource-fork is equal zero *and* the\n              length of     data-fork is equal zero include the file.\n        b) if length of resource-fork  greater zero *and* the\n              length of     data-fork is equal zero don't include the file.\n        c) if length of     data-fork  greater zero include the file.\n\n2) CHG: {Console} Some users are very confused by the buttons \"START PATH\"\n        and \"ZIP ARCHIVE\". Somehow, it wasn't clear what the intended\n        meaning was. I changed the buttons to more clear labels on\n        them like: \"file or folder to compress\" and \"location of\n        compressed file\"\n\n3) CHG: {Console} I changed the menu structure to be more intuitive.\n\n4) FIX: {Console} Found a nasty bug which sometimes caused crashes\n        when the Zip / Unzip Dialogbox was used.\n\n5) CHG: {Console} Handling of file dialog is now a bit more restricted:\n        e.g: it's not possible to select a file if you have to select\n        a folder.\n\n\n\n\nRelease MacZip ver1.01\n30. January 1999\n----------------------\n\n1) CHG: {console} The use of the \"Current App\" mechanism was clumsy\n        and forces the user into the Zip or Unzip modes. This kind\n        of modality is not so good for the command line. It's now\n        neccessary to enter zip or unzip to choose the action.\n\n2) FIX: {console} When Applescript sends quit to MacZip the script\n        that is running shows a spinning cursor and MacZip\n        does not quit.\n\n3) FIX: {console} MacZip gots accidentally the wrong creator code\n        (from BBedit)\n\n\n\n\nFinal Release MacZip ver1.0\n---------------------------\n\nReleased 21. January 1999\n\n\n\n\n9. Beta release 06.December.1998\n---------------------------------\n\n1) CHG: {console} The checkbox of Filedialog (for extract path and file path)\n        \"Show all files\" is now selected by default.\n\n2) CHG: {unzip/standalone} changed prototypes of mac[f]printf() to return\n        an int number (better ANSI conformance);\n\n3) FIX: {unzip} repaired \"stdout/stderr\" mode of macwrite(). So func\n        MacMessagePrnt() is now obsolete and removed.\n\n4) ADD: {zip/unzip} Compressed Mac3 extra-fields are now supported\n        (Thanks to Christian Spieler)\n\n5) ADD: {unzip} Extraction of ZipIt archive are now supported. This support\n        is not complete: Filenames are correct but folder names are only\n        restored with the public directory names.\n\n6) ADD: {zip/unzip} Improved documentation.\n\n7) FIX: {unzip} Function isZipfile() is completely rewritten.\n\n8) CHG: {zip/unzip) switch to latest source level\n        zip 2.3i beta and unzip 5.4 final release\n\n9) ADD: Applescript event \"do_cmd\".\n\nUnless there are big bugs found, this release will be the last\nbeta release. The final release will come out in January 1999.\n\n\n\n\n8. Beta release 20.November.1998\n---------------------------------\n\n1) CHG: {zip/unzip) switch to latest source level\n        zip 2.3h beta and unzip 5.4 final release\n\n2) ADD: {zip} Zip finds \"namelocked\" files also, if switch \"-S\"\n        is set.\n\n3) FIX: {unzip} Function isZipfile() fails if the zip archive\n        has a comment.\n\n4) CHG: {zip} added some small speed improvements to pattern matching and\n        isZipFile() function.\n\n5) FIX: {unzip} Display of comments is fixed.\n        UzpMessagePrnt() is replaced by MacMessagePrnt(). I do not care\n        about ansi-bombs. I'm not sure, so this fix may be changed later.\n\n6) RMV: {unzip} Buildin More capability is removed since it's already built\n        into the GUI-App.\n\n\n\n7. Beta release 09.November.1998\n---------------------------------\n\n1) CHG: {all} switched to Metrowerks Codewarrior Pro 4\n\n2) FIX: {unzip} Display of comments stored in the zip-file is\n        now fixed\n\n3) FIX: {zip} Fixed display of the zip help-screen.\n\n4) CHG: {zip/unzip} Changed special dir 'Re$0urce.Fk' to 'XtraStuf.mac'\n        (see entry at 13.June.1998 item 3). I found it more descriptive for\n        users outside the mac-community.\n\n5) CHG: {all} switched to MoreFiles 1.4.9.\n\n6) CHG: {console} changed behaivor of the file open dialog: The select\n        button is now always enabled.\n\n7) ADD: {all} Environment variables are now supported.\n         Basically, it is possible to add timezone (= TZ environment variable)\n         support here, but it's not yet implemented.\n         See \"MacZip.Env\" for further info.\n\n8) RMV: {console} Targets \"zip only\" and \"unzip only\" are removed.\n\n\n\n6. Beta release 09.September.1998\n---------------------------------\n\n\n1) CHG: {Zip/Unzip} Metrowerks Standardlibrary time funktions are\n        rather broken and incomplete so I was forced to rewrite the\n        funktions: mktime(), localtime(), gmtime() and time().\n\n2) ADD: {Console} Added Pause Funktion for screen output.\n        The Pause-Function is selfadjusting: Count of lines is depending\n        on the window size.\n\n3) CHG: Extra-Field layout is changed: All datas are now in little-endian\n        format (see appnote)\n\n4) ADD: {Console} Added an option to test the archive automatically\n        after zipping. This option is only via Zip-Dialogbox available\n        because it needs the unzip-module also.\n\n5) CHG: {Zip} code is now up to date with the latest beta 2.3f.\n\n6) ADD: {Console} Added (drag'n) drop support. Drop on the MacZip icon.\n        The following situations are supported:\n                    1. drop of one or more zipfiles (action = unzip)\n                       each archive will be extracted in a separate folder\n                    2. drop of a folder (action = zip -r )\n                       The complete folder (inclusive sub-folders)\n                       will be zipped\n        Not (yet) supported is currently: dropping more than one file\n        to compress. Workaround: Put all your files in one folder and\n        drop that folder on MacZip.\n        MacZip recognize zip-archives automatically.\n\n\n5. Beta release 21.Aug.1998\n----------------------------\n\n\n1) ADD: {Console} Userinterface has now a Statusbar to show the\n        Progress.\n\n2) ADD: {Console} It's now possible to stop the run of Zip/Unzip\n        with the well known shortcut [Command] + [.]\n\n3) CHG: {Console} Improved user-entry routine.\n\n4) ADD: {Zip/Unzip} Crypt-code added. It's now possible to\n        encrypt/decrypt archives.\n\n5) RMV: {Unzip} Removed the warning of PKZip/Mac archive.\n        Unzip gets confused with the extra field of PKZip/Mac. So I assume\n        the extra field isn't compatible with Info-ZIP's definition.\n\n6) CHG: switched to Metrowerks Codewarrior Pro 3\n        this includes:\n        - new Universal Interfaces 3.1 Headers\n        - improved codegeneration\n\n7) CHG: {Zip} code is now up to date with the latest beta 2.3e.\n\n8) CHG: {Unzip} changed function names wprintf, wgets .. to macprintf, macgets ..\n        to avoid naming conflict standart library.\n\n9) ADD: {Zip/Unzip} FXinfo, Mac-Pathname, file-dates and Finder-Comments\n        are now stored in the extra-field. Extra-field layout is\n        changed accordingly. Unzip uses now the filename stored in the\n        extra-field when unzipping.\n\n10) CHG: {Unzip} code is now up to date with the latest beta 5.33g.\n\n11) CHG: {Unzip} code is (again) up to date with the latest beta 5.33h.\n\n12) ADD: {Unzip} following switches were added:\n       -J     [MacOS  only] ignore mac extra info. All macintosh\n              info are not restored. Datafork and resource-fork\n              are restored separatly.\n\n       -i     [MacOS  only] ignore filenames stored in mac extra\n              field. Use the most compatible filename stored in\n              the public field.\n\n       -E     [MacOS  only] show mac extra field during restoring\n\n13) ADD: {Zip/Unzip} Charset MacRoman to ISO8859 Latin and vice versa\n\n14) RMV: {Zip} -N option removed. This MacZip crashes using this option.\n         I will fix it later.\n\n\nI think I'm very close for a final release of \"MacZip 1.0\" :-)\n\n\n\n4. Beta release 27.June.1998\n----------------------------\n\n26.June.1998\n------------\n\n1) FIX: {Zip} extra field size value was wrong.\n\n\n\n25.June.1998\n------------\n\n1) CHG: {Zip} code is now up to date with the latest beta 2.3d.\n        So both modules, zip & unzip, uses now latest beta.\n\n2) ADD: {Zip} added a UT extra-field for better compatibility.\n\n3) CHG: {Unzip} changed the code to find the mac extra-field.\n        Unzip has to look for a mac extra-field because\n        mac-archives has now two extra-fields (UT + M3).\n\n4) CHG: {Unzip} changed the method to move extra-field data to\n        the internal extra-structure.\n        Old method was just BlockMove of the ef_structptr to ef_memptr.\n        This method was dangerous because not all members of the\n        structure seamless aligned. There are may be some fill\n        bytes in the structure depending on the compiler setting.\n\n5) ADD: {Unzip} added a warning if unzipping a ZipIt/PKZip archive.\n        ZipIt/PKZip archives are usually additionally coded somehow.\n        InfoZip's Unzip will *not* decode the files. So extracted\n        files are may be not decoded. (see also 6. and 7.)\n\n6) ADD: ZipIt (the Shareware Tool) has now a new extra-field signature:\n        0x2705. Found in \"ZipIt 1.3.8\". I added a new macro: EF_ZIPIT2\n\n7) ADD: Added PKWare's extra-field signature: 0xCF77.\n        Found in \"PKZIP v2.03\". I added a new macro: EF_PKMAC\n\n8) ADD: {console} It's now possible to save all screen outputs\n        to the disk.\n\n9) RMV: {console} this is the first beta without expire-date.\n\n\n16.June.1998\n------------\n\n1) FIX: {Unzip/console} Extract path now defaults to current-dir if\n        no path is given.\n\n2> CHG: {Unzip} creates now a extract-folder by default. This behavior\n        differs to the commandline tool of Unzip on other platforms.\n        However, for a mac-user is this behavior more convenient.\n\n\n3. Beta release 15.June.1998\n----------------------------\n\n15.June.1998\n------------\n\n1) CHG: {unzip/zip} I changed the layout of the extra field\n        to support more data.\n\n\n14.June.1998\n------------\n\n1) FIX: {Unzip} adjusted time_t value with an correct offset value.\n\n2) FIX: {Unzip} removed all unused code based on unfinished ideas by\n        former porter(s).\n\n3) CHG: use of shared code izshr 032.\n\n13.June.1998\n------------\n\n1) FIX: {Unzip} Filenames are only converted when needed. When zipping\n        with the switch 'datafork only' the filenames are shorted which\n        was wrong.\n\n2) CHG: {Unzip} code is now up to date with the latest beta 5.33f.\n\n3) CHG: {Zip} Changed the naming rule of filenames from old Johnny Lee's\n        to my implementation. Johnny Lee's idea is based on change of the\n        filenames which cases several problems when unziping on a non mac\n        plattform. My idea is to add a special directory: 'Re$0urce.Fk'.\n        For the future: Zip will create archives according the new nameing\n        rule. However unzip will be compatible with old nameing rule.\n        See also 4.\n\n4} ADD: {Unzip} Added a new nameing rule for resource forks filename.\n        Resource forks are now stored in a special directory: 'Re$0urce.Fk'.\n        This naming rule make it easier to for other platforms to use\n        mac zip-files.\n\n\n\n11.June.1998\n------------\n1) FIX: {Zip} Internal file attribute is set to BINARY by default\n        when zipping resource forks otherwise Unzip will create\n        sometimes wrong resource-forks.\n\n2) CHG: {Unzip} code is now up to date with the latest beta 5.33e.\n\n\n\n\n2. Beta release 10.June.1998\n--------------------------\n\n1) FIX: {Unzip} Long pathname fix solved. Unzip is now able to extract\n        archives with path longer than 256 chars.\n\n2) CHG: {Unzip} removed all conversion from c-style string to\n        pascal-string (see fix 1)\n\n3) ADD: {Unzip} Finderinfo of folders are also restored.\n\n4) ADD: {Console} Added info about current path in the command-line box.\n\n5) FIX: {Console} Construction of the command-line of the unzip-dialog\n        box fixed.\n\n\n\nFirst beta release 06.June.1998\n-----------------------------\n\nno history.\nJust to many code was neccessary to build the first mac-port.\n\n\nStart of the port MacZip\nFebruary 1998\n\n\n--------------------------------------------------------------------------------\nLegende:\n\nFIX: fixes a bug\nCHG: inform about changed items.\nADD: added feature\nRMV: removed Item\n\n{Unzip}   -> only related to the Unzip-module\n{Zip}     -> only related to the Zip-module\n             These are just libraries and are linked into the console-app.\n\n{Console} -> only related to the Userinterface (not SIOUX)\n             MacOS has no tool like a command-line. So it's neccessary\n             to write wrapper around the command-line tools.\n\n\n\n\nDirk Haase\n"
  },
  {
    "path": "deps/infozip/zip30/macos/README.TXT",
    "content": "A free Macintosh Port of Info-ZIP's\nZip and UnZip\nBy Dirk Haase, d_haase@sitec.net\nHome page: www.sitec.net/maczip\nMirror page:\nwww.haase-online.de/dirk/maczip\n================================\n\n\n\nAbstract:\n---------\nMacZip is a cross-platform compatible tool that includes\nboth Zip (for compression) and UnZip (for extraction).\n\nZip is a compression and file packaging utility for Unix,\nVMS, MSDOS, OS/2, Windows 9x, Windows NT, Atari, Macintosh,\nAmiga, Acorn RISC OS, and other systems.\n\nUnZip unpacks zip archives. The Zip and UnZip programs can\nprocess archives produced by PKZIP, and PKZIP and PKUNZIP\ncan work with archives produced by zip. Zip version 2.2 is\ncompatible with PKZIP 2.04.\n\nIf you are new to MacZip please read first the file\n\"ReadMe.1st\".\n\n\n\nLicense:\n--------\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in unzip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n\n\n\nRequirements\n------------\nMacZip requires at least System 7 and a Macintosh with a\nminimum of a Motorola 68020 or PowerPC 601 processor. Other\nconfigurations may work but it is not tested at all.\n\nThe application is distributed as a fat binary with both\nregular 68K and native PowerPC versions included.\n\n\n\nInstallation\n------------\nMove the executable(s) somewhere--for example, drag it (or\nthem) to your Applications folder.  For easy access, make an\nalias in the Launcher Control Panel or directly on your\ndesktop. The GUI is very simple. It was not my intention to\nmake a full-blown GUI, however I think it is comfortable\nenough to use it as regular tool.\n\nThis port supports also Apple-event. So you can install it\nin your WWW-Browser as a helper app.\n\nFor more Info about the contents of this package, take a\nlook into the \"macos/Contents\" (or :macos:Contents) file.\nSome notes on how to rebuild the Macintosh applications can\nbe found in INSTALL.\n\n\n\nUsage:\n------\n\nBasically there are four ways to start MacZip:\n\na) Drag'n Drop\nb) using the Dialog box (Menu: File -> Zip/Unzip):\n\nPlease read the file \"ReadMe.1st\"\nfor the description of the items a and b.\n\nc) Using the Command line (Menu: File->Command Line):\n   The Zip & UnZip tools are command line tools. So the\n   behavior is exactly the same like the Zip & UnZip tools on\n   Unix or Windows/DOS. This means, if you want to zip some\n   files, you have to write a command line like this: \"zip\n   [switches] path_to_zip_archive path_to_files_folders\"\n\n   - Go to \"File\", select \"Command Line\" and the\n     \"MacZip Entry box\" Dialog Box appears.\n\n   An example:\n\n   a: your zip may be created at\n           Macintosh HD:applications:archive.zip\n\n   b: your files may be found at\n           Macintosh HD:somewhere:my_folder_to_archive:*\n\n   Note: At the end of the path there must be a filename or\n         a wild card !\n   (see Footnotes: 1 wild card, 2 Mac path names)\n\n   So the command line should look like (one line!):\n\n   zip \"Macintosh HD:applications:archive.zip\" \"Macintosh HD:somewhere:my_folder_to_archive:*\"\n\n   - Click on \"Enter\" to start the task.\n\n   Since you can not set a default folder you have to enter\n   always a full qualified path names. Full-qualified path\n   names are path names including the Volume name ! (see\n   Footnote: 2 Mac path names)\n\n\n\nd) Using Applescript:\n\nThere is only one additional event defined: \"do_cmd\". You\ncan enter every valid command line. The first word must be\n\"zip\" or \"unzip\" to select the action (compress or\nextraction).\n\nSee sample Applescript:\n\n    tell application \"MacZip (PPC)\"\n        activate\n        with timeout of 90000 seconds\n            do_cmd \"zip -rjjN Volume:archive \\\"My Volume:*\\\" \"\n        end timeout\n    end tell\n\nThis script opens MacZip, brings it to the foreground on the\nMac, starts the zip action with the command line: zip -rjjN\nVolume:archive \"My Volume:*\" .\n\n\nA short introduction is also available online:\nhttp://www.sitec.net/maczip/How-To-Do/\n\nIt's possible to stop the run of Zip/Unzip with the well\nknown shortcut [Command] + [.].\n\n\n---------------------------------------------------------------------------\n\nThere are some Mac-specific switches available.\nZip Module:\n       -df    [MacOS] Include only data-fork of files zipped into\n              the  archive.   Good for exporting files to foreign\n              operating-systems.  Resource-forks will be  ignored\n              at all.\n\n       -jj    [MacOS] record Fullpath (+ Volname).  The  complete\n              path  including  volume  will be stored. By default\n              the relative path will be stored.\n\n       -S     [MSDOS, OS/2, WIN32 and ATARI] Include  system  and\n              hidden files.\n              [MacOS]  Includes finder invisible files, which are\n              ignored otherwise.\n\nUnzip Module:\n       -E     [MacOS only] display contents of MacOS extra  field\n              during restore operation.\n\n       -i     [MacOS only] ignore filenames stored in MacOS extra\n              fields.  Instead,  the  most  compatible   filename\n              stored in the generic part of the entry's header is\n              used.\n\n       -J     [MacOS only] ignore MacOS extra fields.  All Macin-\n              tosh  specific  info  is  skipped.  Data-fork   and\n              resource-fork are restored as separate files.\n\n\nSelect [File]->[Get Help on Zip/Unzip] for a complete list\nof switches.\n\n\n\nLimitations / Problems:\n-----------------------\n\n    - Aliases are not supported. I tried, but I got broken\n      aliases. This port will silently ignore all aliases.\n      It's on my to-do list for future releases.\n\n    - Zip needs much memory to compress many files: You may need\n      to increase the 'Preferred Size' in 'Get Info'. Values of 12\n      Megabytes or more are possible\n\n    - Unzip needs about 500 Kbytes of memory to unzip no matter\n      how many files were compressed and expanded.\n\n    - and finally one big macintosh-related problem:\n      This port has one weak point: It's based on path names.\n      As you may be already know: Path names are not unique on a Mac !\n      The main reason is that an attempt to implement support exact\n      saving of the MacOS specific internal file structures would\n      require a throughout rewrite of major parts of shared code,\n      probably sacrifying compatibility with other systems. I have\n      no solution at the moment. The port will just warn you if you\n      try zip from / to a volume which has a duplicate name.\n      MacZip has problems to find the archive or the files. My\n      (Big) recommendation: Name all your volumes with a unique\n      name and MacZip will run without any problem.\n\n\nKnown Bugs:\n\n    - crypted files in a zip archive are sometimes corrupt:\n      I get an error message: invalid compressed data to inflate.\n      Appearance of this error is purely be chance: I did a small\n      test: Unzipping an archive containing 3589 files 56 files\n      fails to unzip, so about 1.5%. Root cause is completely\n      unclear to me :(\n\nI strongly recommend to test your archive (e.g. unzip -t archive).\n\n\n\n\n\nZip Programs / Macintosh Extra-Data:\n-----------------------------------------\nA brief overview:\nCurrently, as far as I know, there are 6 Zip programs\navailable for the Macintosh platform. These programs build\n(of course) different variants of Zip files:\n\n    - Info-ZIP's first Port of Zip. Ported by Johnny Lee\n      This port is rather outdated and no longer supported (since 1992).\n      68K only. Only minimal Mac-info is stored\n      (Creator/Type, Finder attributes). Creator/Type: '????' / '????'\n      Until year 1998, only UnZip 5.32 survived.\n\n    - ZipIt by Tom Brown. This is Shareware and still supported I think.\n      ZipIt has a nice GUI, but I found it can't handle large Zip files\n      quite well. ZipIt compresses Macintosh files using the Mac Binary\n      format. So, transferring files to other platforms is not so easy.\n      Only minimal Mac-info is stored (Creator/Type, Finder attributes).\n      Mac filenames are changed to a most compatible filename.\n      Creator/Type: 'ZIP ' / 'ZIP '\n\n    - PKZIP/mac v2.03/210d. This is Shareware.\n      This Zip implementation for the Mac can be found on ASI's web site\n      (http://www.asizip.com/products/products.htm).  The name of this\n      program is misleading, it is NOT a product from PKWARE.  ASI's last\n      release version is v2.03, and they also offer a newer beta version\n      PKZIP/mac 210d. But even the Beta version is rather outdated (1995).\n      Only minimal Mac-info is stored (Creator/Type, Finder attributes).\n      The Zipfile format looks like incompatible to other platforms.\n      (More details about the compatibility issue can be found in\n      proginfo/3rdparty.bug!). Type: 'PKz1'\n      Mac filenames are restored without any change.\n\n    - Aladdin DropZip 1999, This is Shareware. Aladdin chose\n      the format of ZipIt. Therefore, it has the some drawbacks\n      like ZipIt.\n      Creator/Type: 'SITx' / 'ZIP '\n\n    - SmartZip 1.0 1999 - by Marco Bambini Vampire Software.\n      This is Shareware. SmartZip compresses Macintosh files using the\n      Mac Binary. Therefore, it has the same drawbacks like ZipIt.\n      Creator/Type: 'dZIP' / 'ZIP '\n\nand finally:\n    - Info-ZIP's latest Port of Zip. MacZip 1.0. Ported by me :-)\n      It is supported (of course) and up to date. Full set of macintosh\n      info is stored: Creator/Type, Finder attributes, Finder comments,\n      MacOS 8.0 Folder settings, Icon/Folder Positions ...\n      Mac filenames are restored without any change.\n      Creator/Type: 'IZip' / 'ZIP '\n\n\nCompatibility of my port; Extraction:\n   - Archives from Info-ZIP's first port (by Johnny Lee) are\n     still compatible.\n   - Extraction of ZipIt archives is supported. This support\n     is not complete: Filenames are correct but Directory names\n     are sometimes mangled to a DOS compatible form. Segmented\n     archives are not supported.\n   - PKZiP/mac archive files are extracted without resource-forks\n     and without any Finder info. I have no information about\n     that zip format.\n\nCompatibility of my port; Compression:\n   - My port supports only the new Info-ZIP format (introduced\n     with this port). Therefore archives created by MacZip 1.0\n     (March 1999) must be extracted with this version or later\n     releases of Info-ZIP's UnZip to restore the complete set of\n     Macintosh attributes.\n\nNote: This port is complete unrelated to the shareware ZipIt.\nEven more, handling of special Macintosh attributes is\nincompatible with ZipIt. This port (MacZip) may be used to\nextract archives created by ZipIt, but make sure that you\nget the result as you expected.\n\n\n\nMacintosh Files; File Forks:\n----------------------------\n\nAll Macintosh files comprise two forks, known as the data\nfork and the resource fork.  Unlike the bytes stored in the\nresource fork, the bytes in the data fork do not have to\nexhibit any particular internal structure. The application\nis responsible for interpreting the bytes in the data fork\nin whatever manner is appropriate. The bytes in the resource\nfork usually have a defined internal structure and contain\ndata object like menus, dialog boxes, icons and pictures.\nAlthough all Macintosh files contain both a data fork and a\nresource fork, one or both of these forks may be empty.\n\nMacZip stores data-forks and resource-forks separately. The\nZipfile format does not allow to store two archive entries\nusing exactly the same name. My solution is to modify the\nPath name of the resource-fork. All resource-fork names are\nprepended with a leading special directory named\n\"XtraStuf.mac\". So, when extracting on a Mac, you should\nnever see this directory \"XtraStuf.mac\" on your *disk*.\n\nOn all foreign systems that support directories in filenames\n(e.g.: OS/2, Unix, DOS/Windows, VMS) you will get a\ndirectory \"XtraStuf.mac\" when extracting MacZip archives.\nYou can delete the complete directory \"XtraStuf.mac\" since\nMac resources do not make much sense outside the MacOS\nworld.\n\n\n\nText encoding; Charsets of the Filenames:\n-----------------------------------------\n\nThe following information is only important if you plan to\ntransfer archives across different platforms/language systems:\n\nA typical Zip archive does not support different charsets.\nAll filenames stored in the public area (= accessible by\nforeign systems other than MacOS) must be coded in the\ncharset ISO-8859-1 (CP1252 in the Microsoft Windows world)\nor CP850 (DOSLatin1). The latter should only be used by Zip\nprograms that mark the archive entries as \"created under\nDOS\". Apart from Macs, the commonly used platforms either\nsupport ISO-8859-1 directly, or are compatible with it. To\nachieve maximum compatibility, MacZip convert filenames from\nthe Mac OS Roman character set to ISO-8859-1 and vice versa.\nBut not every char of the charset MacRoman has their\nequivalent in ISO-8859-1. To make the mapping in most cases\npossible, I chose most similar chars or at least the MIDDLE\nDOT.\n\nMac OS Roman character set is used for at least the\nfollowing Mac OS localizations: U.S., British, Canadian\nFrench, French, Swiss French, German, Swiss German, Italian,\nSwiss Italian, Dutch, Swedish, Norwegian, Danish, Finnish,\nSpanish, Catalan, Portuguese, Brazilian, and the default\nInternational system.\n\nIn all Mac OS encodings, character codes 0x00-0x7F are\nidentical to ASCII, except that\n  - in Mac OS Japanese, yen sign replaces reverse solidus\n  - in Mac OS Arabic, Farsi, and Hebrew, some of the\n    punctuation in this range is treated as having strong\n    left-right directionality, although the corresponding\n    Unicode characters have neutral directionality\nSo, for best compatibility, confine filenames to the standard\n7-bit ASCII character set.\n\nIf you generate a filename list of your archive (unzip -l),\nyou will see the converted filenames. Your can also extract\nthe archive with the switch '-i' (= ignore mac filenames),\nand test your result.\n\nThis MacZip port uses its own filename stored in the\narchive. At the moment, the filename will be not converted.\nHowever, I'm planning to add support for Unicode.\n\nCurrently, the following Mac OS encodings are NOT supported:\nJapanese, ChineseTrad, Korean, Arabic, Hebrew, Greek,\nCyrillic, Devanagari, Gurmukhi, Gujarati, Oriya, Bengali,\nTamil, Telugu Kannada, Malayalam, Sinhalese, Burmese, Khmer,\nThai, Laotian, Georgian, Armenian, ChineseSimp, Tibetan,\nMongolian, Ethiopic, Vietnamese, ExtArabic and finally:\nSymbol - this is the encoding for the font named \"Symbol\".\nDingbats - this is the encoding for the font named \"Zapf Dingbats\".\nIf you extract an archive coded with one of these\ncharsets you will probably get filenames with funny\ncharacters.\n\nThese problems apply only to filenames and NOT to the file\ncontent.\nof course: The content of the files will NEVER be converted !!\n\n\n\nFile-/Creator Type:\n-------------\n\nThis port uses the creator type 'IZip' and it is registered\nat Apple (since 08. March 1998). File types can not be\nregistered any more. This port uses 'ZIP ' for Zip archive\nfiles. The creator 'IZip' type should be used for all future\nversions of MacZip.\n\n\n\nHints for proper restoration of file-time stamps:\n-------------------------------------------------\n\nUnZip requires the host computer to have proper time zone\ninformation in order to handle certain tasks correctly (see\nunzip.txt).  To set the time zone on the Macintosh, go to\nthe Map Control Panel and enter the correct number of hours\n(and, in a few locales, minutes) offset from Universal\nTime/Greenwich Mean Time.  For example, the US Pacific time\nzone is -8 hours from UTC/GMT during standard (winter) time\nand -7 hours from UTC/GMT during Daylight Savings Time.  The\nUS Eastern time zone is -5 hours during the winter and -4\nhours during the summer.\n\nDiscussion of Daylight Savings Time\n-----------------------------------\nThe setting in the Date & Time control panel for Daylight\nSavings time is a universal setting. That is, it assumes\neverybody in the world is observing Daylight Savings time\nwhen its check box is selected.\n\nIf other areas of the world are not observing Daylight\nSavings time when the check box is selected in the Date &\nTime control panel, then the Map control panel will be off\nby an hour for all areas that are not recognizing Daylight\nSavings time.\n\nConversely, if you set the Map control panel to an area that\ndoes not observe Daylight Savings time and deselect/uncheck\nthe check box for Daylight Savings time in the Date & Time\ncontrol panel, then time in all areas celebrating Daylight\nSavings time will be off by an hour in the Map control\npanel.\n\nExample:\n     In the case of Hawaiians, sometimes they are three hours\n     behind Pacific Standard Time (PST) and sometimes two hours\n     behind Pacific Daylight Time (PDT). The Map control panel\n     can only calculate differences between time zones relative\n     to Greenwich Mean Time (GMT). Hawaii will always show up as\n     three hours past the Pacific time zone and five hours past\n     the Central time zone.\n\n     When Hawaiians are not observing Daylight Savings time, but\n     the rest of the country is, there is no combination of\n     settings in Map and Date & Time control panels which will\n     enable you to display Hawaiian local time correctly AND\n     concurrently display the correct time in other places that\n     do observe Daylight Savings time.\n\n     The knowledge about which countries observe Daylight Savings\n     time and which do not is not built into the Map control\n     panel, so it does not allow for such a complex calculation.\n\n     This same situation also occurs in other parts of the world\n     besides Hawaii. Phoenix, Arizona is an example of an area of\n     the U.S. which also does not observe Daylight Savings time.\n\nConclusion:\nMacZip only knows the GMT and DST offsets of the\ncurrent time, not for the time in question.\n\n\nProjects & Packages:\n--------------------\n\nA Note to version numbers: Version of MacZip is currently\n1.06 and is based on the zip code version 2.3 and unzip code\nversion 5.42. See About Box for current version and compiler\nbuild date.\n\nBecause of the amount of sources I splitted this port into\nseveral projects. See http://www.sitec.net/maczip for\nupdates.\n\n- core source parts:\n    unzxxx.zip\n    zipxxx.zip\n      These archives contains the main parts of the port. You can\n      build libraries and a standalone App with Metrowerks\n      standard console SIOUX. They contain only sources, no\n      executables. These archives are exact copies of the standard\n      Info-ZIP source distributions; they were only repackaged\n      under MacOS using MacZip, with one minor addition: For those\n      files that are stored in BinHex'ed format in the Info-ZIP\n      reference source archives, unpacked version that are ready\n      for use have been added.\n\n- additional source part:\n    MacZipxxx.zip: contains all the GUI stuff and the project\n      files to build the main-app.  Only sources of the GUI, no\n      zip or unzip code. To build MacZip successfully you will\n      need to also download the zip and unzip packages.\n\n- executables:\n    MacZipxxxnc.hqx: contains only executables and 'README.TXT',\n                     This version is without en-/decryption support !\n    MacZipxxxc.hqx:  contains only executables and 'README.TXT',\n                     This version supports en-/decryption !\n\n- encryption sources:\n    zcryptxx.zip: To build crypt versions of MacZip.\n    download from ftp://ftp.icce.rug.nl/infozip/ (and subdirectories)\n\n- documentation:\n    MacZipDocu.zip: contains some further docus about the algorithm,\n                    limits, Info-ZIP's appnote and a How-to-do Webpage.\n\n\nCredits:\n--------\n\nMacstuff.c and recurse.c: All the functions are from More Files.\nMore Files fixes many of the broken or underfunctional parts of\nthe file system. Thanks to Jim Luther. (see morefiles.doc)\n\n\n\n\n---------------------------------------------------------------------------\nFootnotes:\n\n1. wild card:\n    The '*' is a wild card and means 'all files'\n    Just in case you don't know wild cards:\n    '*' is a place holder for any character.\n    e.g.:\n    \"this*\" matches with \"this_file\" or  \"this_textfile\" but it\n    doesn't match with \"only_this_file\" or  \"first_this_textfile\"\n    \"*this*\" matches with \"this_file\" or  \"this_textfile\" AND\n    matches with \"only_this_file\" or  \"first_this_textfile\"\n\n\n2. Mac pathnames:\nThe following characteristics of Macintosh pathnames should\nbe noted:\n\n    A full pathname never begins with a colon, but must contain\n    at least one colon.\n    A partial pathname always begins with a colon separator except\n    in the case where the file partial pathname is a simple file or\n    directory name.\n    Single trailing separator colons in full or partial pathnames\n    are ignored except in the case of full pathnames to volumes.\n    In full pathnames to volumes, the trailing separator colon is\n    required.\n    Consecutive separator colons can be used to ascend a level\n    from a directory to its parent directory. Two consecutive\n    separator colons will ascend one level, three consecutive\n    separator colons will ascend two levels, and so on. Ascending\n    can only occur from a directory; not a file.\n\n\n\n\n\n---------------------------------------------------------------------------\n\nDirk Haase\n==========\n"
  },
  {
    "path": "deps/infozip/zip30/macos/ZipLib.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ZipLib.h\n\n  This header-files is global to the project ZipLib.\n\n  ---------------------------------------------------------------------------*/\n\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define MACOS\n#define MACZIP\n\n#define OLDROUTINENAMES     0           /* use new function names only */\n#define OLDROUTINELOCATIONS 0           /* use new headerlocations only */\n#define SystemSevenOrLater  1           /* Runs only on System 7.0 or later */\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing (see printf.c)  */\n#undef getc\n#undef getchar\n#undef putchar\n#undef putc\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#define NAME_MAX    1024\n\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <stdio.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n\n\n/* Many things are different for mac-users, so we need\n   special mac functions :-)  */\nint Zmacstat (const char *path, struct stat *buf);\n#define stat(path, bufPtr) Zmacstat(path, bufPtr)\n#define lstat(path, bufPtr) Zmacstat(path, bufPtr)\n\nint fprintf(FILE *file, const char *format, ...);\nint printf(const char *format, ...);\nvoid perror(const char *parm1);\n\n\n\n/*\n#define MAC_DEBUG  1\n#define DEBUG 1\n   */\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                                 \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                     msg, __FILE__, __LINE__);        \\\n        }\n\n\n\n\n#define Assert_it(cond,msg,kind)                                        \\\n        {                                                               \\\n        if (!(cond))                                                    \\\n            {                                                           \\\n            (void)Print2Syslog(LOG_DEBUG,\"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                          kind, msg, #cond, __FILE__, __LINE__);        \\\n            }                                                           \\\n        }\n\n\n\n\n\n#define AssertBool(b,msg) Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) ||  \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg)   Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n                ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n                ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n                ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n                ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n                ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n                ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg)  Assert_it ( \\\n        ((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), msg,(\"AssertIntRange \"))\n\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/ZipSx.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ZipSx.h\n\n  This header-files is global to the project ZipSioux.\n\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define MACOS\n#define USE_SIOUX\n#define MACZIP\n\n#define OLDROUTINENAMES     0           /* use new function names only */\n#define OLDROUTINELOCATIONS 0           /* use new headerlocations only */\n#define SystemSevenOrLater  1           /* Runs only on System 7.0 or later */\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing (see printf.c)  */\n#undef getc\n#undef getchar\n#undef putchar\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n#define NAME_MAX    1024\n\n\n/*****************************************************************************/\n/*  Includes standard headers                                                */\n/*****************************************************************************/\n#include <ansi_prefix.mac.h>\n#include <stdio.h>\n#include <TextUtils.h>\n#include <Folders.h>\n#include <Aliases.h>\n#include <Resources.h>\n#include <Gestalt.h>\n#include <Traps.h>\n#include <Processes.h>\n#include <MacWindows.h>\n\n\n/* Many things are different for mac-users, so we need\n   special mac functions :-)  */\nint Zmacstat (const char *path, struct stat *buf);\n#define stat(path, bufPtr) Zmacstat(path, bufPtr)\n#define lstat(path, bufPtr) Zmacstat(path, bufPtr)\n\nint fprintf(FILE *file, const char *format, ...);\nint printf(const char *format, ...);\nvoid perror(const char *parm1);\n\n\n\n/*\n#define MAC_DEBUG  1\n  */\n\n\n\n\n\n\n#ifdef MAC_DEBUG\n#define LOG_DEBUG   7   /* debug-level messages */\nint Print2Syslog(UInt8 priority, const char *format, ...);\n#include <ctype.h>\n\n\n#define Notify(msg)                                                 \\\n        {                                                           \\\n        (void)Print2Syslog(LOG_DEBUG, \"%s (file: %s line: %d)\",     \\\n                     msg, __FILE__, __LINE__);        \\\n        }\n\n\n\n\n#define Assert_it(cond,msg,kind)                                        \\\n        {                                                               \\\n        if (!(cond))                                                    \\\n            {                                                           \\\n            (void)Print2Syslog(LOG_DEBUG,\"%s failed: [%s] cond: [%s] (file: %s line: %d)\", \\\n                          kind, msg, #cond, __FILE__, __LINE__);        \\\n            }                                                           \\\n        }\n\n\n\n\n#define AssertBool(b,msg) Assert_it (((b) == TRUE) || ((b) == FALSE),(msg),(\"AssertBool \"))\n\n\n\n#define AssertStr(s,msg)                                            \\\n    {                                                               \\\n        int s_i = 0;                                                \\\n        Assert_it ((s),(msg),(\"1. AssertStr \"));                    \\\n        while ((s)[s_i]) {                                          \\\n            Assert_it ((!iscntrl((s)[s_i]) || ((s)[s_i] == 0x0A) ||  \\\n                       ((s)[s_i] == 0x0D)),(s),(\"2. AssertStr \"));  \\\n            s_i++;                                                  \\\n        }                                                           \\\n    }\n\n\n\n#define AssertTime(t,msg)   Assert_it (((t).tm_sec  >=  0) && ((t).tm_sec  < 62) &&   \\\n                ((t).tm_min  >=  0) && ((t).tm_min  < 60) &&   \\\n                ((t).tm_hour >=  0) && ((t).tm_hour < 24) &&   \\\n                ((t).tm_mday >=  1) && ((t).tm_mday < 32) &&   \\\n                ((t).tm_mon  >=  0) && ((t).tm_mon  < 12) &&   \\\n                ((t).tm_wday >=  0) && ((t).tm_wday < 7)  &&   \\\n                ((t).tm_yday >=  0) && ((t).tm_yday < 366),(msg),(\"AssertStr \"))\n\n\n\n#define AssertIntRange(myvalue,minimum,maximum, msg)  Assert_it ( \\\n        ((myvalue) >= (minimum)) && ((myvalue) <= (maximum)), msg,(\"AssertIntRange \"))\n\n\n\n\n#define AssertStrNoOverlap(str1,str2,msg)                           \\\n    {                                                               \\\n        long s_i = 0;                                               \\\n        AssertStr((str1),(msg))                                     \\\n        AssertStr((str2),(msg))                                     \\\n        if ((str1) < (str2))                                        \\\n            {                                                       \\\n            s_i = strlen((str2));                                   \\\n            Assert_it ( (((str1) + s_i) < (str2)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n        else                                                        \\\n            {                                                       \\\n            s_i = strlen((str1));                                   \\\n            Assert_it ( (((str2) + s_i) < (str1)),(msg),(\"AssertStrNoOverlap \"));   \\\n            }                                                       \\\n    }                                                               \\\n\n\n\n\n#else\n#define Assert_it(cond,msg,kind)\n#define AssertBool(b,msg)\n#define AssertStr(s,msg)\n#define AssertTime(t,msg)\n#define AssertIntRange(myvalue,minimum,maximum,msg)\n#define AssertStrNoOverlap(str1,str2,msg)\n#endif\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/ZpPrj.hqx",
    "content": "(This file must be converted with BinHex 4.0)\n:#9T`8(*U,R0TG!\"6594%8dP8)3#3\"&66!*!%Ip96593K!!%!!&66FNaKG3)!N!3\n@!*!$$39DF&\"bDJ#3!aEf1!,VX93!6&MU!*!$J!#3\"!,cIF3NA3#3'[q3\"%e08(*\n$9dP&!3b[H&ZZXklEb3#3\"3,E[3#3\"P40!!$hQ!#3\"L8D\"RMDS*NlIS6ISVG-[(8\nR+hBY21RaEd$i`XJbN!\"bQK8YHRN,mmTE(\"$HbP6f+lXeRq'lH*3I@AbbH%Ef3E+\nYif3KHp54hE%@hq8Fj,%GAml1RLpN-E,i(GQARdH@0q0,K(GffT%p5)X[RVFF@D4\nBKrHBaXd@6VD,AXpZB5d!C#'6K@abQi`@mJ[Cj$MPC!8iDT2X[EaXE0rjRCHM[$`\nEj#4Rp[RPjG6VcFj\"ITHAR9DQepPe(-SAiAji1arZ(-5ApPP[lbMciLAdmP)if0m\n4Z#m[-q'q[\"cNPGI1p`,!!JLip@eQPi2X'farqH4p\"**I)T!!,ckH3A`!+i#AjfI\n6V9BMbl,P@GDh0P[fhKZcCArkf5`lka2F0rFYkb28qpDfD[R@DP(8@d9PSQMYcUH\nl#l&K+CqqV@b6b'8EXQaE[)pm16Za$2kVE&Ajrhr50p-icq)mQh-k-9rKr#ThirR\nrPjaIiecK!m`jJh-@jcQFFcJAF-lMl1)dliLFcVQ\"F`IR*Xk0R\"GcEZCFalQ0mbl\n1fcR[i$c+q@,1jh$HcAQBm`MR4C`2FElF9MERGNj6amLPR&XjIj*c$@F2jmXiAm$\nj*XlAFlk\"mi@FrjhcMcNrbIN*cSpcISVc6cMr,HHpR$r0q3#eRXTrcYrLI$mR'2-\n,R+rKI\"hRIH3Bb9R2#IC-iM3GT%lK(-,CcQPUVdlJ(-lCbMQ1Xi(6p)BkME10Xj%\nc+PDCdr561TN6d2S-jjpa'Lb,I*!!mcpbrKVR@cNIiIaPcSFjIjhc9cKrNI2GR'r\nMr#$RKcMIc[R[1Aq9mbfFlq6m*Fi,1*Ga,Z@mKI0IFGl*#5!Dh)bmK[09R,GaAX,\nj\"jarb2RI1(q(FaIR4cJrb[Nqc[Gb(Z#mQA-Ijhl1Jp4a$2rr-qGri@idr`pa2Tr\nc#j`c1@GcRXXjPh-Kjha1dcX4X#IbK!KDTSmLi&#%2SXmRI-QcLq9Z!9QHAK&RJp\n`lZ(FbhNGjrfFi0ZA1@rJr$6RRh*qP[1jR(r\"H68Rb4GarLERAh1H6mK%r[mHjqp\nbAXYTHM*b(ZI2F2iXj`61[`QF)`)'4&l\"HCccMCcrM[2R16r(qAR1Rq!dI4jj2HF\npR$r&qmEbrbAmTmDmG5@R`BL)@2XZiLEchf\"#j+Fj$@j%`)h)-cJ0YN6%B*!!fZ\"\n0\"!b*Q-YJ5Z6l13f@4\"l,H6RRrq,m\"ZHMR,r0#FVclQpbISXh8X0[Fcl'q6MRDNj\nkp$ZFEqEm1FlAFVk)df\"Bj'l1*Cc,1EXjRmhj4Fi(1@rN[*lcMcMr0HFV1DrKT2p\nIcEQEmcpaIScc2h$Zj2`0c[G`AX&j+HFl*#EQK*KF5AfSiiFjrbYhe2BUcZFYQ8#\n8`\"SqHK\"mJ1I3kr3C28Brd%[d&(J&2Y#Ep#9p$1pa'!D(S)I\"!2UBIUI2k&ekQ$k\nNTkNhA)PD1m`$$m!AqJL1\"DHLhq&FB#FB#Zm#3m%Rq0Hr%%46EGlDqbRHVF#K%H!\njCH(Hi#JG!5E6*4lH8SZ90Sij`3pl6lJjll@6MSXbZAq0&J$qBllBSmf01Ffr4[l\nC`lkV[XcL4ASG'Uq6pdGP+lLTLlHfZ[CGhY-)T@1p\"c3qUpkHR1ZA[\"4,,hRFkea\nYBX@*hcX-dG\"#+9Im%9i\"mj8`IdC`pR\"ZifcRl1$Xj\"c&1CTc$1GBcR'FNcQl1'G\n`VZ*FcEQ@Fb2R*XiYR$GclZHmKI0@cJ1F\"cN2F4lQ[)hc+1IYR(G`2Src(Xjl19r\n!q41F@f-(QGk,(-FjM(-iCbXRM$VH@aj#JTLJCcJ!8S+3!+!HU!JLJMDJ)qJ*@MT\nN\"$e\"8C!!&83&)8&+Kk\"K\"%KC3E!i)0$PJemF2ha%-$h8ZV&k4A@S8HedmNlrlUV\nk4r+lI'5L-VEe@@SUj\"`H)5q\"0Af[ML&D&MAMJ*Q(BUqXb8H5K0BVJkB$kF&FTK+\nE1,G`MZBF`cQ@Fa,R+-j1cKXiEq5mQA-NjdE1rCbhF0l+HC!!Xiec'fF2Cc[R#-j\n9R$GacZ$FblQDFbhR2Xl*R)FjEq-mbRNAjpfFcq0m2ZFpR&XjQcLE1BG`YR!1j4`\nQQE%pEq+fM@mD(\"[Z(pkQ6*ArB1m@(2NMrbrTZlE[a'9UA)NZ-1G*h2#q2MlNie#\nFlAKr`'(q0ph`MVp(96SX3dYqJ(B)h'F3ShNX,hEQPI(CraA+,q4E26%a@U*4G2h\nS*GZQpp4VDZqA6Ni-IBGlai[LEVbSIX8L6)&*mGBRF[Cp'P`'R8-#ZKG'%!T3Na#\n3!-m)-8N-L68ZIi`Zd6(CV9@'cMfh-Y4UGPU0[2,dLj`Tq,X[KR+QI5p6KIl4ahY\nLPcQ1D'%LG1\"lQRGkkX`5C4jc2[L!DZG,#8B,5U,`Fq[1G#3r8(Mci'9Ud,jSF#T\nciQZmAjrirRI0jCeZYIacC+Q'iD#62CM9E%`2YX+JZLEVVGQjbYU*LD&c+[cadf`\nLhS-SY$AS24*%1!\"B$AaU%FbHEZBiI&Le*&2dm*m[h!(MBQeX&DQ`Q-m4dY!$bD8\nkHP%6%rda\"hqX)Y,(1*GLV%NarU3BRe1-mLR'G\"6MGiV4*m@3!)\"LY%a\"B48MHSS\n40SAJU\"bI-b0DLV%IaELIFKb+X6Xc5U8Bhe115CP42-9iN@)m66&kT4ME8S`!+ND\n`&'1!bP%MmhBlHQAHENIq6!ilBQEHEJF8c*[YH+'TL4e&-HqfSf(QcBaJ-HTRalI\n-QaR0XZ0rjXefp0#0fM&5apJFihD-d6&kamJGih@-\",S41aQYXQ09M1SaQXGB%f0\nhCUc,MZFamX5i(102M-iaYZG'X%`IfUkLVScJ-8E&'\"jMCi`p-N,'Q#)M9BcX-BV\n'Q\"BMLBaU-CE)q\"NMMibJ-IE)5\"TMN!#-G$%qb@JJif#-\"c++a@JM)f+-p6(ZaTJ\nKSh#-26)#akJG)cf-J$+'b\"JAii#-CXPS(b0DGM63M36#+mfiD'a8e)cUfE&(4Kd\nCKh5MMSa1-LV*b#0MNk!-Sj!!M&'kN8P'*\"Q9G118M&bD)4$'`aJTC265MR%bcZP\n'1aP9C066MABbqXIS'D10M!$+f+!Gph0MPS`&-QVTa[BB(@4-N4%h4J8CE@2Ncih\n9-3l(i)SE-Q%iaBfmqX-Q$+-`f-)J#i-SE[L%N8I'C\"PjC'5@m8FcHQK(%4PcC%5\n6F6X'BaM6C151N8h'laK*C-54N6Y'(XfiR\"fhBr5488I'm4LVBlb4F8Q898Bc'FY\nNh*049XBecBLQ(FQ%Kc2UL6M+q#hFJh%l0j,,+#lMSCR\"(KP@53lhm0'6rT!!Ma[\nUBD#(34i'HKMHBCL(34i'HK\"a'44#hN\"HmSGk'1Y&cf\"FQ2N+aL@4LKMrCE5BN@,\n'N4QbB-5Bd@)h&X`i-#2'M!XMmM*kc2JK)kb-*6,HbYJK+J9ML)`I-YTS4LJ91+[\n!9`@q+[\"9JFF+r&AJV!*R&6LV`'N&,L[`9S(h#Xa9B+i#Fa@iVm\"G\"8G3F!F&eLZ\niJS*$+,L&JPXSZ)@#@bK`AX%V&,a#`5Z8I)+4BS-IGPcBi!!MbBb1-Tl+q'Cb60[\nd$q2CGJcCi*%Ge6-iT-!K\"3iTm%H\"2`Vm8H#2!Rm8q+2!(`Aq+2$(MLFcrQS`5)&\n\"#Ja5i)S#Ea4iSm!E4@mSX%%jSQQ`4i%j#Xa4p)d#Fa5BSm!I\"HiSF%H\"1`VF8H#\n1!RF8Z+-F$6DiSm!G\"HiSF%H\"1mUH-pLM`\"d&lLK`4p'AM\"`UqPf\"!`SX925k!JF\n9Q+$!\"!8Q+,\"5JBm+E&$JJJ)A&,LJ`!-&(LM`3)%(#Ma3i)%#$a4iS-!$\"4iSm%#\n\"X3T-8'##!K-8H+$J&!T1SH!5#LkKY\"8`A%2\"+44F3X%I&0a!`8%82%,\")a3m3X%\nM&$a#`5-82%,\")a3m3X'R&(a+`DH8)r@')bNiNS+[+(Q5i5E+N@E$663pT1NK63p\nTHNM6EjVHd[55TTFd[D6T58hrDAT+de1DRY,dP+DR0$fPk5G02fRk5G02'KcAm'%\n06dC@e[\"L63pVkUDTQkCZQVTTq,1'2f[iS)C$DlLcKQYV1,D'3fXiY)C$DlLfT[i\nD,00`F!fHDALeKMYUZ,@'-fViYBCIDrLeKPpVq,@'[fTiVBD6DMLPKXYUH+@'9fT\niTBE[DRL`\"PmeZ+[Kq\"UFe'#N\"L-eA&1$NaUFe25LTKFe[DMT3Dd8ErTF`fXe[Dl\nTG3d@D$\"!dr1DRYId[!BM0&a4Jp%DM0$JY!B(0\"aCJ`-DRUc\"!Jd@D,\"!Jh%Dr02\nJP!EV0\"LSiG%D204`D3f(eR\"S$3CUF&1$QaVFe'#3!!Er0IL[`Am09pC`!#d(-\"U\n!JQmVH,L#0bXd!S8fS1$IL[STDU%F#6HDJD)HL[FUhUTiUq+YL[j8p*ULca4pT1J\nK43mTHNJjGXriY(Q[3RG3p)b#RbZiX,,Z\"XXdZ+2\",JfQDEL!KJYSY!X0(p\"`!3e\nId2!%$5I3F!)0*p$`#-dl0*a&`b-dr%H$[aVqSm&RMHDK`9)0(QY`@S2A'Pc@B,N\n'bc9BVZ&''McAe&C6Fdep0(LZ`A-0RQX`A-060(a,`m-d2%a66`dAdh!a$5jVF&Q\n$baTFe[\")$Br8p)Q'#fPiNSCVDMLQKYGSZ*''-fNiU+Eq'JkRiD!D(UIK8jUHdh!\nR66pU1*H'FfNiPiCcDAL@KQGTH*D'@fRk9F1[0$fVk9P0VfUiPSCVDEL@KQYT1+k\n'(fTiSBB6D[T3``Ze[*!!mAZM%5Pd(iAZSp!8&0U43[qaNaMS)%CV8'J-QJ!0RpE\n`E!hre[\"[$Ir@m'm0lpE`EJh[e[\"Y$Gr@m'd0hpEU*ZJ8B3GIH-fNB'1B3JRj'%8\naRe@'`bJ'fdl93qCGKdIr(k0G&iF0[#%M-bGm-JqU9h[+JqSeiaYjr%&'P,'fP!I\neE&M+JlTf@5p2X8P-&!VFXe-H9,V,8aj8[#Y6(T5qUe)He-#V8ai8`fY5(P6&De-\nH9-IV8Ki8h4Y6(Y6JQe)HP12l8Kl8cGHP2#LMVdTj8&6IP2+JVViQj8&jI8A+Jc,\nl`T3(pIDG[6c*-6!Ipe\"iVdM[339qIXU$8[lbP!FerD'8\"mApH-U$+[r6+3r+rBG\n5(Y6p$kBm6!$X6AQB%VJKj@'5i2U8KdQ$25N28`L[6hQB9(K$bX-Nd'G5(UDD4U8\nm6$f05hQBL*U8mM#jp2k8KmNUjfrAPiGTUkRIb12M+00CAFIbK\"Kqp3Y@*5%[Rr2\n%D'*LHfYpqd1Q'%8rU[TPTCU9!ZrB&'H)J%d0cjQiHAcFqDRB&leNmjEJSQ'UecM\nCQLfQFbPHr@*FabPMeHRc*Y[jG(e(hFQek)D4d@'j&[q0Q2c#a@3MMkmhTaZc05I\nD'Q*m6rbr,IjI&Iq[MIpAarm[@Ra(jh'GXKM83X+ha2rhaIpharmEirp0LqRE9p+\n+ebL#f'+Ck)liId6m2b2qEer-fV*LI2YZEIKFj6VMre(arqMiIdcm2cEq(lIiL+%\nq!PP&aq$*mArABT+aChCf9BZm9TR'hl5,@R8pUE+P'BEVKm9m,ieYpS,irfL-Zcr\nH(iVr$mIr0mIrpmErqq2r@q,r@q2r!r(r`F9kk-F-ETSFU3\"H4kT&[B5!ZXA`qZA\n\"AU-ZTQk0riI(rif,Z4U@\"am$Q`X(*[RI&2rEmX+B%cR9+L!QqAUp'\"dpr(VhhhD\nTq6pX-9IMiGF2MIq(a2mYLlQ'R,!jAd!C&4qcGAjq[ZpAGXmfpecHfH(mT08%'lH\nMKZq)!\"i#`hK'VKNDAcqmTV*QrH$8)(phM!a0+BL'U(aQTLGV3*0flr!0CV`6RKD\nki0la6eC+49ZBd)TjNY!!CKar%am6&-kZK6RZZZ9Mch%qRrR`k,*p'r84B-kl2PX\njV[V,2,2PlqCM2YNce[6Q[CXDkY+HUZXC0R[cfUi,m$j`mpI-q60rcBFRJ*P)DG)\nI!4m#TNliQ1e[rGV0jF`imqpYfhGlCEd)4Q3ri%JrmrTf@S3lTLJk-KL00dmF1D0\n9*Q3fedk!N!#$'@ZQ2,KM*Ye-FYKm+19MXTHeR\"p'(4lE,LHDm)H`8aIFiA(!c$G\nhq\"G-D&3P8ma'-`1q`RPL2\"-Q26Bl9DN)$i2*`IQ,qGY)KBHD'M&V5kpCc`J6BQI\n[D82QckGP0kiQMPR!b1Vjq6ZG'fAqRKPqFY\"rdaR5CDD1qINC38KKKYEdE11ERB2\n%0i,CIZBBm@%i9e6dCP-Mj`C2'qC1lD`rZI%LB1DI1fScKrFaPiL2`0b!&(91$-d\n,MKpeeSZDF-Im2pi!h$(PJ%F!GbJRH!9`\"kpF&0K\"R6i@LhAm-(Gi3P`3H%5G1,0\nNf6lEUNlI\"r`%$\"1Ydb-\"A`(Lm(GBPYei0VQLBYCbqX2d@p4T('EVJ5`m$&C52p0\n,8AR\"KF(\"*5T@@A`dG`K@6+\"`\"c)bZmmGRKV#DU*k5c$,cahH$!+j8AZ#(J35`8&\nQqlPMAKm\"KMY`%NQ%1l`pQ2AR$Qm-XHfUelH$k4(Z!$*kKcZm+*J#!@EaD3#[Z+-\n(K-Nhk!H#4`\"hH(2`GZl`bU$1h1&p)GTAJpL$K`\"hH%hJ*F!GrK(i#A$(Zr%9i)i\nDibrJi\"f0L$X`(FcKMNNZm*-lqJm[\"ZlJ%(JkF!F'iIR!(4J\"4q#1hXBEJM[k$Bm\n)lZJ0F)-lkQM\"hYcaCN3,lSM\"1i)lH!EH%G`a@5&#C+2H+Ki6L4b[M`VBcKfq+8b\nkF)GR#Ah+(6iN6+a`KhF+lq)1la3Q6lM$\"d@mS\"VY-cJ#GhL,#-YXe,X$0BFlq)V\n-4$EU6m+%#(IiH9!Vl[\"6`EF#kX58UUHr4%k3!*2K\"m-GrK,iaA#(PiF`Z5Ca6Ub\nQQm4FDXiGrK[icA!(IZ%l`adi!VrLMMk(Lh&(2m&aZ+2ZBTMEC)h!,ZjiJaK`0ZN\nPJcm0Gr3(rF8GILc`$ZlS$haVZ-0r\"EcL$Jm8m*ml2%c`Xq%1(aCmEEM$Xi3q09q\nc&\"C-jJjZK*m-Gr!aZ\"Khm#+i*(IiPH!h`aeiL4m0Gr3\"IMAFd3IieR!(VZ&I`af\nB!LC`4fq$eGc49rMCF%HYi92Fm@CmEEMM2A!ClZ$1q0a`\"jE!EER$CiGBlP\"&)$V\nF`A(\"(ql`Im%2KcY`'PmFl[\"h`4q(1caKm-RK$Zj)2jT[L2L\"p`phm'&i!AId\"pi\nrh)'le)3lZ!FFK$Y`'3mKlX![[)5iSmrKM0c4*h!dlRJRhN,Fi4-%$R\"(Vq-*`Kf\nH0IJ,FBFR$I8hAiXF!VmKlZKMq$jhm!EmKlL$@q*$a\"eiKKm4Gr!LhXXGh!1Zc4f\nB$Mjc\"fk#4Gb\"4hJ(F3F@L\"V9BKhKGp`4!aIQ$Tk(pa\"hq1R!hlQMcq#NjKZUPJ'\nqFBH4-jj%h+%hi%h%(AS*(NAF`62TFHlJBrJ6F3F[`UH)1hS1[b,Z`'@i'hIJ(6h\n&(4J%eq!1,)!cFNFIiQ[%(If![a&h[\"1I)ql`(!*EZ--R#El2(9J,0c6I-2%$rX)\nG@![[jJj0\"GcQMKVMBF3G(MqmLc[k%NmMlUJVRNEF`CI!-HlJ'23AGr3L(NIFJBP\nJ\"AGJ%lb*1rS5[b2ZU#1q4pca(VJ$GhJNiB0N[Z&b\"IJXGfJpk\"MFJArJ*hG`82U\nD1cJr[)`lH$9p`4dm&Tf\"1cJKh)3lF!@[+1lJ-r\"PlZ!9V(R!(CK16EJ$Bm\"UlX!\nJH\"phB!Gib\"hp$0IQM[i4,i6KeS,Hj!kY#mmZml@+2AKhFBH'KBFAGiM4j1'1'X-\nVZB-$@IFdFiIIM(F9q6jpC15bPAVMFfA[m,U4dHe@*rGNR,99rb\"C0k\"9Mb$4reV\neqa$pVe92$h&DD0@$4[5r9[eM42r$q\"SI,AZ(4jESIfek\"(Q,A841eGG(p,mfrA'\nB,1F1hae`L6[mHG!IZ'1b8I5r0MhAi-lFi@&KhQM[m$J5rDp0,a,4rpVd(8'li!j\n[($(TEG-M\"pcM$KmFdIrDp-!3r@m%pEAV+A#(Ra%H80cK833[i!lr(bDaZF26KfP\nVl[!KNY8K4ZJj*2VI#,hMd(bi`fF1[XmG[NkLrih3I`N[,qlS[j!!P8'%N!#!ch5\nZld9UKQh3UIlaLhZ90LfCB+HE04Mpm4GQjPMU'f(#A*C+bmcjdR*\"KRLhZmQ08,H\n[Ch*Nq,54CMF[QRQh-McAEV5+r0pRT[Ur6AP)1bHILaTp'0X(QAcISH&iEi$ZScF\nmlc8)0G[Md%K)frGH9Emd,R`-A'LIRcm3\"c&#fVlId9NjM3XIZD(i+B6ERML)&Y,\nfrD(ZffPFq+-ELX(2N!0r1!irK,&p''UB[j[90TPU,PNEQM`-RQb*HFS@L#B23bP\nEBakcfP!j$`-V25N2`bcE8Ki'AEDRqM$XXMrQDAM31X[NB4$QPT5()CPE8ak'CJk\nQ2!c8(%Tj',BjR2)`L(0EbX13!-k4P)F\"RU-T$m-kGkBm$2,FPI)`N!\"cImT$ql2\npLMH9AXQ$UAKGbS24H%[+Jq&i8mU$+IQ3!*3(dr,QP!GMmk'p2%@V4*1(3IJ$k6d\n-(Gk6mQ!!-5cP`FKKH-U$FAaVbS-C4&[+J`(pL*3(NrVfP)GKpcX5rM!dqjb8Kb(\njBbN2`q1hTc`-'ADN1Q+k2c,P`C5r)H9KkBXa+3p,B)a2H9JJBh,+``$j\"hTmVj`\n(+mI1p\"i'(UI&2%1qPBGP0kBFHdq)i4H'X#E+2fr\"9&SEjIYlr)6!I@'\"`h2@5$@\nXVIAp,b53!%`d$*`dZh&N+M[`fHJ8C,BRr2`AhD$'h(AM3,CdGYQ\"6pqFII`(Vqi\nkrM+\"V@0DaSBhE8%[[(kU@ZLPGYrNe1BRF[r3a)4HL*&hEklAp)TkY*Th4C82%iq\n2bFIE4DjReZFf0+VQrIV8Q(iBNDpGN4FG&*8KkiZ@8Zr8dQe2[QLp((qaRR$4hHA\n)KqGhG@rTUfMpEp565cp'kX-@1$-VjIicGLXF['%mMl&l5cA9mjfk9hqpPZKCC6h\n[6NY#rZjHS44HRrA9rYB4iH`*Vmmc#!5CUV+8f6pZ!a\"Ep$)@PCJ$HhV$[hmbHml\nYhaU[c1RhKTR3a&4,B%(QHX@DbarGGB)p\"0dhPY!2ZK)B9TMe*`h@Y!r&JV*KSYl\n8KKClZmEU4%[l9@chQXC'P!fX09ac&`0kX5`E-TBhAD%+Qpb@,UELh[T9N91i-[9\nNrEE)UPBRjrfXU49j6,h4m!j,aYE*A5hAVX)HX1fCGCF[X$E+)mCD9h$('N4Qci%\nEZZ4MIDE)k9bCfV#H915-Ur)K9j!!`TkdXe'h0U`&&APXc)GYiZMZd\"6eBmfSb&R\nGaQ9BeGCTIcHfhKbL0R9DXBdEkMDB$+l6&RKmBcCRkVK1'@4#im4*hP5RGHE%UEa\nM2Q`m*kd[P%RUY*HF2&98XEQYdj+aka3#c4f@J&K#QqQZU\"1i8jZeR0k+ZQVCY,V\n2L+a3fMKVfEihB+-B&H[%%XlD&SXPA&3l5,'%LfSTLBdhGr3L0QG'ZUNAJE\"bT)A\nj2f[C[YFbE9b[*H,Xl,JDr91[*DKB3YFl`5Dlb0CVIcShi%'ppTlc!Kl8Db-j2q\"\n\"[6,1JS!($8lK,Jaid1$+D1F(2'M3i@&4`)-'LlXii%'$0V!A\"$aSd,Cd5F#$\"Ud\neP`BmD,![Z`-H0'T&Z#cJ3D1iY6cJ3D0fDLX#(M4U&ESbp,He\"Vi`i%'MY9`9m+\"\n4kd`QE8hr0@TaZ5EQ`iCaEF#$*LHCe`8mD0,fqU+!\"dhfjIU!\"deDafi)H0#N4Hh\n'J!G0pZ@QJ!G0@S0Z$RM3T(hPPS!(eZjfDm#$CLd\"QB3e&U$0@U!bl@TUhDbe-KD\nfc&GKb`XZQhkfYV2)C)DR0@Z&#KBE'd9V)iZ9XTN5EpBpJ9SCI\"NLaQ!*E55i)GU\nYBJR08$a[`a,D@\"X1dIlbXN[c+qR4)IDPXB51JK0$l-[,4fEDp-d3mIk+LDd9F(b\n)eTeAATTG62eDV199MEBeE,'@9iHG&PVN%pFd@&r6h#%[AVZK-X)l@qJl,+(T[aD\nYG+m2q0HLGHDHJ(mYpZAH)&1fL$&Q1I)ZV(f(1K&qif6H*FP3qr+Q#TIQMYlBPdp\n@i5e$R8k&NaJq0&3,BV'%(UT0VPK#$p8'9LbKKfSh+TE3`m5BJjplRQX3$\"0E$l(\n&P*%kKr(f52YMChH`A\"dQ0lTYjlS+9Uc@k[3)2U1Q\"iD*-8GG0X,FB@plM0+Ep`l\n6J[9fHX[JeM\"Y3ZmBBE-#dl,djA2fV\"X%$iEEPhIZkSK,`m@#Zpbl`0a4ZqHLjCL\nq(QjIhKhH0e`Hmlc`2QXYq[afZdlGKfY9HSpl'aMUK&[!mBYRkp5j94jhEdCbF`F\nZL#9dUpa#,+&Ea6#aK'l9fPFXS9[P,Q)*MF@RXi4Zdkj6,+(EY(mA5qJf-88XSGZ\ndXaC,k$CYPX85ZNhF%N[S0RYG,+(Ej%CL#6e#e`'aK\"iK0a*,k\"&LQ9K#Mp\"'@bb\nK4fMT,*E3f'8k5qJ4@YH+*I3)E96&LDKG'9SXSG[P%')*hDiYV&K#YfZl,CE3l9S\npLb9dZdD3!')*hDjPVPK#Yf[I+TE3(ES)L#9dKha,,+%lP0A%%VV$(K0,k!kYPX8\n5ZN1X&8[S$Zeca4,DZTb+*I4)TAQaK\"iTpaG,k*(DUSXPp%Ml@5bK4jTA,+&(DQ8\nXPY!Mj59L#GdTrSQmhLPI&%[S6ZhZa4+k8qiVPY#GpVPB3RIk0V'%lY4#@5bK1m9\nAXB3H*4m95qK4FNkaK\"iPISXPp#KYf-85HT6p,*E3Shbc@%+2dNjC,+&(DI-VPY#\nMGI!35qM4fUD,*I4ShbIQRD2&2,'%(QhrLbAdD0mTPY#Ma3baK\"kYhDjB3Sq4GiS\nPp\"MjM9K#Me%E%8[S-H+J@%+2XFI%%RU-m@)*28D1,TE3Bm9TXB3H+fm@5qLa1UQ\n**I4BF8J'2FD+&f)*2GEDL5Ad@2QI@%*E&eZaK\"iR*a0,k((b','%(LG(%N[SFH+\nb@%+2Xmr&%RUFla&,k((D'SXPp(MjX9K#MpFH@LbKamZra4*k[2aE,+((LhGL#6h\nHAK*,k2(q&d[S#GUML#Ad\",&(,+%Rb&2&%RU#j&!XS5H)k@)*28&F%%[S#GC),+%\nRb\"h&%RULqS4B3Nq8CiXPp%6aALbK*fUR,jE3%m9VXB5H+,k)*I4%DbD@d1`$l5b\nK*pPRBJNp5@`35qK*BS0B3Nq51iNPp#5aALbK*iNMBJNpb6U+*I4NY65aK*kXTL1\nZ5*2&Bl'%RU`++jE3Nm9lXB5H,'F35qM*B*Q6r#E6Efk5QT@pR59dPfXDLN90&qp\ncFQfA&XaL#GhP'K0L#GhP@SJbG0)&6MK,k#jUjbbKTp\"ccK*kLZX-LLAd&0Fb&%[\nS+DlP+CE38l3r&N[S+DkI*jE38qKcC`NpPEc1%RUUkb++*I48ebB85qLTV[JTPY\"\n6A@94,+'RZK+M@%*2\"3HG*I48HXpC3Npcl85aK*lQqSCL#6h0e42&%RSDIHBXSDI\n4Cmi5HTUVm)NPp$4`bPP#RdAr1%[SXeb285bKch)94,'%2N[A$l'%2X[e3m85qLc\nAmK2plbcAk\"2plba`c9P#RdeIX9kM[@1e4V%j2PXR&Y(rcYCp\"%l%(DZ-bNSBCp[\n(S[qGE8q)rRFf1-9DMRc6U6[V1GSlqPK@`TMZ@SUb%XCd9f58P6#QZjUNV)3ahA8\n\"iHrFXDSL()FlJf@Xp-Jh`jj$cq'1pl'q!(IJK+b%-81A#h#E1pDDK(G`a`U#XK,\n'$([1p#cI6(#+G4hY(6dR+f(-G$e(@3PMTUY!bNSB-qdj@3PMTUY4bNSB-eeM8&E\n#Q+R&ZDb%F3kiaPU2pSkHNj8`cY%P4eE#1-F9)f8PM(0F+e9@`MM(05YP*BacA)G\n39X)iajk6P6$1\"DIX#L2FQEUc(U5p`ajG9X)iejk6P6$1eETG9X)i9aYd@3RMA&H\n%P*8`cVARC#@-@IDdV)3abji6*ljC[Np@`TLP8iQXK$(,062&hA1@Db$+5KLcA#p\n59X+BEFr*5KLcj41b%XCXHdj@`TLYKLmVBFc@qPa@`TKYcmP+',1eETH9-'DlSU5\n-)ThR#UDb%XCji\"TVAGSlHNkQ8Fl6CPe@`MM2e9e&rcY21h[4rmjc*8A4rmjcc8R\n4rqEBFl)5aKa`LV8`lCfT1qYKfMZXff8PM$RfR-bLc(&e@&N*BiiV@-UXaKbjKDb\n%-GHHNj8`jYV6XK,'A(Y19X+BkrYN*BbjmL&C#@1Z+cR+*-GFEHYP*BajFJYC#@1\nH25FVBFac$3\"C#@1H25%VBFbcjd6rQqIkRk,rcG2@Ar5rHDk\"+IVII,Q&k(rcAGP\n6p,rjFJ[4rqE,%8ArQbq1L[ihhe9#4IqE,dF8r@qqp[ULrbe`E9E4raCSSbrkh`*\nl6[5r\"Fk!L2kh3'iKqYm#ZBASI`YF@92d[`@ZXbMkhd*A%aApEk%p*rVI3YmRqYp\n#ZBASI`YGT96d[iAbCY(r&XSY42mlhp9K4Imlhp9'4Imlhji3rHpmHdld[r1T1bZ\nDfMZ`Ar5rmee,325rmm8jdIm@ZA+Xk(q,A*&8p,p&VJSUqYmLZB[SIi[NjD,r,A+\nPAG(r&SRpS[mY%SG%re[XbUDLrbffjd6r@qbk!U,r,CC$LrkhQ(jJ(94laqU@S[m\nYGK94dIm@ZckNk(mAf(1LrehJqd6rZd!q*rVI\"ESELIjh!E9QV8alaaUCS[pGi&U\nMS[pGJ)E#fTPm5q`2dIq@Z&+#k(p,A,Y8p,mPpU,SId[N(+,r,E'ZS[mYN4q)rVG\n%6LRkha*V,2VI%VQ)k(p,A,Y8p,mPVN8UqKqqkkbrDHrS,G(rPMV',2VI8PFm&Ie\n[UBjKS[mY&AY%re[U@JZLrbf9pi[qYe6X&re[+6'Xd@R[i!'Lrbfe[dArklBr42r\nVGL9AdIqkl3r4rlVP6+,rGDYYL2lA,GD+rYGYIiMqeff2L[lAEAq)rYGY286rklB\nHS[peLm'Lrbf6YiRqYmaq&Ie[QEa6p,pPVViUqYmb9h`9r@qCXf1Lrbd64dAr@bB\nI&Ie[QCJRqYmbqEVSIm[%E0(rPVRDTZKrbq9jS[mYPdH+rVIFZ624rjDVEBMqYe`\nR10(rPX[242pElMV)S[mYYcp%re[ZZJkLrbfh2d6r@klf*[VIFVQqk(mVe\"*%reX\nK4a6pEi9VdBVqYm+C*G(r9UKeLIkh`M@'42pEBHq+rVI#PCC&re[KfUVH9H3RAIY\n8p,m9VKNUJ5[!-PElY(F'#eMadpkCrQ(96hYRDX(+Rh`VAI06p,q9VLJUqYp+-)p\n931dGUkD+rVI5Y94&re[TUV#LrkedY9I4reDkJU[SIbYGV96d[j@ZmbVkhdVA(4A\npEb@pa9UPpXld-'Z1mPe),9LRe0ka)URSIaHkiURSIaGD$p(r,U4[@028hY%VS[p\nGk)U[S[pGk1UaS[pG#+k`[LRI+RU'P8hYRAN$Dj[D1eC@&Ie[P5ZrL[khbRP$dIp\n@ZFUXk(qVA-e8p,p9VJSVqYmUed)5r@m9[Fh+ThbVID[SIkYGJeAd[p@Z&#[khfT\n`La93l4hVd)VqYpS99NAr@qekV+,rVAD09Y(r9S0pV02+YiEqC1e@HfIHCYG8iSl\ne@%Ar@q1DXD,rVA%0@p(reYK2S[qYF9eDdIr@Z&kYk(pVa\"M4rpD!@DcYbVH@hQ0\ne9hYRmV,#UlfMaU,rVAApA0(reVVUVHKrDm8jdIr@LQfLrkeeV9c4rpEk9Y(reY'\nhV2aUlqJRdIr@ZEUYk(rVA)&Ap,peiTESIq[%+Y(reVNqV1KrkebY9[5rGI!+9Vl\nPBpNeeX+eG`B,@!rAhTQkXb+Z[@20@p(r,K)[4Iqlb09h4Iqlb(9K4Iqlb&9M4Iq\nlb,9e4Iqlb29j4IpE$qkc2Ukp-aM('VRfc[3`kq6D1r0qeXUeGkce+rVIHYIV&Ie\n[[D[$L[khAJiKqYpkelF9r@mpI)QeFrNfZ#kXk(mE`%h@d,9hF!A4rcEiEY(r0[K\nZdImfZ0U[k(mEd%&B1GMHXHDXk(mEA,p@p,m0m#T@&1EEk,UeS[pY\"0GB9GMHQ9j\nPC@&lCpl'kX,fMTi@r@qMDrk+rVI4eAj&rpYSEiRqYa(1b@V$I*[N!D,rEE+R4Ir\nE\"0D`mV#p-rh!kX2f$S`8r@q6EaApEj0i,2VI*[Q0k(qEa#h4rcD*@k,rE4BM4Ir\nEE$q*rVFCM'\"0BAYRHS\"eL1dGka+,rVGCr\"$pEl1i*IVICYI$&Ie[XlJPqYm@9li\n9r@q,DqU+rVI&GAY&rpX#\"YQCDqlJ(k,rED%@V&jXleM49r5r,Dj2,2VI&YFd&[e\n[Laa,p,qYiSISIeYGK9Id[kfZmb[kheE`MV@0lChT6eBfYRIJPZKr@ehE9r5rVDi\n9,2VI9VQ)k(pEIEISIcfq@r5r(R&,p,mHF9Vd[alV,ITI$lh01X$fcY51YAlY(9a\n%p,mHZBMSIcfZ#LckA`pmRY9mqEDj2V$SIpYmUqKrfjaY&re[QaJTqYmfDbckhcE\nHcfV(pSkH&[e[QcdYqYmf0![@2HEElYUqS[pY&lG%rp[ZQX5LrffhaU,rE3FI@AR\nChS%PS[pYTaDX[fc[i1LLrfehY@24rlDl3V$SIc[N(k,rlA!eBp(rGXJM4IrE)@D\n)rVH$AQ+GBR[(UX1Lrqe`c@E4rbjf2@(4rbjf4@,4rbjfY@E4rbjfK@R4rbkfEd6\nrZjMqBG9QH`IA&rh[B[Q6k(mlAA9Bp,qGVPJXqYp1hbIkhdljK1Kr1m&69SqfGh!\nQdIpfbZp&rpYTr86rfb@(%2e[PkXHLrkh5b0ddIpff4qLrqebr@R4rhEj2Y(rGP%\n[9Q+fGq#Ck(qla@r4rhEE(k,rlCDML2khfrH*rVGEc8$d[peb\"G(rGSXVS[rYMUX\n[fc[d#G(r,T&2LrjhLAaDp,p,A&GDp,p,A2YDp,p,`&r@TEChk#kLree#h9N&fpl\n\"+8ArHjDV*B[qpbaAB4Ep,r6Q-`KQ0P,F2ZP@IfB[aB0l[QX3&!Eka6G#-KJB+AG\nF$&YT!11#*+*UL0YR\"d$-'%Km(8V-im,H--&Bk\"cVYYF0$1c'Dfe1ClEC2pfD'@J\nAVGVXG,FcX,ZfCq##rJX'DUhTcN#eABqc)5%MAh&&Mj!!PXqbJ[!DZfUfq3L&@E-\nK$'(eJhT(&G1pPQimQGZcBF`b-KX)MM1rb0`LmiV-+9TI3R-bMmM-),1)c!XbHmJ\nX)[1#GJPkFc*hb'`JXi,-!M)rb\"bJc2q&+Rb0#j`NJcFRh62rH@q'TpdjRmU6UQS\n)h\"F@D&CX#&efAfA2Ir,[2RqIjE#%$3rr$f1UIBdPaIZAa9rX2S2K$NX0\"N5h8Y\"\n-T-NGqZ,XE0FFGa$B-p[SeYF0cADkVCQ+hU1(LKVZSVN8UkGCLreSCD,DeAdd&im\n(+rkMaR,ejZE1\"e+XVhYeR3kNa34iN!$ZKH%G+kS2a\"Zm0K&lmd[bjS2KkqSGVEm\n2E'p!%AYcb$\"EEc5+NR'4,E6*h-!H$V5TC1%\"ASC,UdAc`4U[h6!QlFK(EYTF'@p\nhkc2eUrlME4LE)jmG\"J*+iGALfIKRMAdpe*[cmr5j(G9Qh[KkNKh9cR5eFD6kNU+\n[r!`69PZBm-%@6X`MpNE['0l`8'LP38cikXl-0aYJChl9NHTILVXeaDeNZ21LThq\nlq)4A#NZdUjlmlbS4GDY@b-Q%aZkh(p**8!&dSQY`6S)UQ\"0HJA+Lbd$ZJLXBi$)\n%MH*L#deZQk)+i2(i)RlCq$ai%eH\"EU,,`\"d,,KHX!0S%$N!f+@U!R8K3+AFCV&e\n`IjZ@J0V&CQ%k&PKUK`T%%ed\"D+,li*Ri-MLli&)TI@\"1\"TYUpF-`#5S`6(30KNP\n3K@(#+c\"-G\"Q'AA#P[ef'S#PFE+8TUM!FMbrLNSh2`c\"a&4JQZJc$XH\"b`3S`61!\n!$*1L\"X1*\"*9bPf(B\"IHhD3Q'A@`@KQ1\"TADS`$$4&4JQZJq'L5r$X!XZPE)-`qX\n(Til#-!NU-%ad$BC*8)9K`LX`6(3CKPe`TEpGKU!TA'bP+DS`()m[iT+0cm-`F48\nB*VS-`l(JFX%+-%cJ!!b6SJE$L359FTGKf!AhYfN*KPeX&SCMJD9fU-!`d48B*VS\n2KSN[`l!,,T8b\"m1RC+P\"BHU80(9#R\"U8T`B%UY-59Ep)05\"6R45U6NT9&E&U8+l\nkVVKd5Pik*6!05%bR4DCqQDNU0!e)6B0Ldk$FG%Vk'44r6XNr*`5J33PS3!3k,32\ne#d%$8Y\"*-HLN(&34K!BPSHm+1+FNR&-LcS#-FeV)kCGbUQ,1J*`c+1J-5MURj*9\n\"JH@8a(*#C\"Q8@3D%PY055lrB-L#hR\"4F6NSZ&G&P8(EjVNKb5LBj*C3-5#@RaC*\nqZD3UQ!a)*S1LbD\"XNT`B,8NBk54jZ%YR+!*H1NN!HHN8HG\",CmM\"AMj\"[Krc@C)\nGQBp209kQF3,i+q4)BdXQK`q\"kGJm#+BcP'!`RDB)K-8NrHA+J@%q`FRfb`*L2Mi\n1L8&`AfrQB6'GS4mB+i*(1NNr-&C%Mh55!@$X&6l5'@V!@\"8rmPP+R9N83$+0-`#\n-C4%NNk-A'(Z&N!\"dKP2!@\"&$LNRkbe8$aUSNNXr5ehjPB#`+)lN%9@$X&8I5d*N\nEH3J5e2!j0IU3!!iZL2RT($P\"2jqJMerNK2ed(p5Uh$YM&@3)UPbH(%VRU&@j-%'\n8MkqU\"lND$ik[9!GB6JjN$)aNp!pP$)aP*!TINI$55IV*@dA'5bFC)'qp8Pik3if\nm9H@mI*B5)\"3P[8cM$*!!Yl+XPmR45pjkTEedKP2NV5,[&C2dPkY'hUSLAcj,ArZ\n9b9Y4kXXPU*+hV0bApiI*iQ+3!#-*Ld'#$#S'19+J''4)BQ)K`FfG9M0@Zr$%@h1\nXE-[K2U+@iT-GA8SL$9d+GbeED,F8QPC5a0#TN!$#`p)J0!QP33+IiTAMqdVS5&i\n3Qi2T)%X'TDXjDQhJBh3TrN4$*a#k&!j!Pf1VRC+%jb$\"#A41XqBJK8qE5r(9q[V\n%14-IL*j\"MKSr##62)%Fr2mJ+RS8%9AjJReMK\"aQjY\"4IJj1d@&S+Vl9E2cr)+k@\n&&%9qN!$95B-%II`JUh+9%q6j39'$$E)-mS0!J5hNU2+$J[jD5P*Yk\")rb)L[[I%\n9IT!!P9k$\"!2m)#-CPZ+VpHhM\"i'Z&Z5SmB0!93Ybp21$V+C@5&$P\"rD*&Ak3!&(\nN5[%e1%RVFDA`@V[emi1m'&G)8H3(@5NZ50$($l)DF6P\"RKm8CEiJbb!r#%5q3Si\nU2bK)I+8NeBBZmB1-[YFEAq%(*p5p[1SHT1MM\"fRG[46ZDJKiTA0Nq8'3!#2*$i)\n%'Ai3j%MaJb\"$NKm%#Ab!,m8RmD#842UP&&lVPa6!9e,%N!#YN!$#!rJJ0!R`33)\nIi-[aI59d!\"r%jJ!qb*)\"q'U1@K[i!&q+2p(3#B![K32`jGKUTb3\"2NL3!!6i)%%\nDi)-82X#AiU[e6IVbQAS1!Rb3!#-*m%'#$-!(19)!(f4)!Rb3!-!(q&*m%Jp+5D4\nI5Z'eINN\"I#9&$0N++6b!$d+6!\"mNm!'q(0pA3JI`3@`1i)-X'B#[jULeJ3r`TIJ\n6$Cd!q&)i!&q1VAC+%Z#$\"%Q!$a+N!6j)i30m+EjDhd%'ElYpDl@jFlDk-rmQ(X3\nbP0k`VMAp-+Vi1GK1*CK!F(&*8Z'#-N6#aDA)JiY+%JBAj*-%2bD*)hkJp*BINUe\nK#[46B6'%Li9ji1kZNi$ZJP)pPi`5D%r'C!T5DVBFI,[)$'5Ril*&p+(CMbQd83+\n#r4\"J0hQIVPB5APe3%P*G8\"T'ACJ2RAj-ZKBq4\")6f'5iZ#`X\"@BB,Li(5eR,#aH\n8JD@#XB8IQ+KKaViL9X-F,190+Q*KF9M+@P'iS\"`XC3E%Nc'CJJ5`9$5eF*%\",!A\n@&E'i0#`9$#Vm`(3EqE#8FCj)a+4J+HX[iB,bX*3CC[GMdV9)`e)!59Ni#U!S\"d0\nC#-V!6`&kdV#6JC`mh15K*J%c@BM*`8X'@V+`%N\"+%8i#+!PJ*!-K\"IK)3iF2'aR\n)b-*&$LTL5aS9@%Fm1XXpiU%\"!iP(jhK)2$E,4Z+K'8k5LXa#DLSm!@DT3\"p1%jA\n2FC9-F\",X%m&ahK)2bV+AH'L1`k4M%d`Q(9NXAF\"UiY&&EK12$aK10VUhp\"QfNiU\nX0QLDqD3#(Ip*4a@UQq9#mG\"HQ#Z4khKd,mb9L(BmZJ4c\"G)G$bh#A*Q!Tm+cA45\n3!2&%j8X`ed[-%m%CQ#Z3!24iD!RQ!X+HMLb@VJ*c&3SIMkr!A)R1*k),-&HQpUR\n`3S2QB#iJqmR)!1B+a(pVIIY$A-l&CL(1\"3B!jf*cm1BLXq$Q!M23jXGPqmB26R5\n0(qCh4kc118K,K5Dl1KBDKc-ANJ8c&jL$XQ4N!XL5F8'a!K\"cX88)Fp%\"J+9M#iA\n1J*FI9fl\"0($jB3kfNM(jDQBKb`9Q!@[Gk'KP,C(R2!\"CmHJXD-9$!pL+4qH!+ak\nEKDjiD!Dm8T(ChNQ&*lSR&HMh5U,b14$,\"#Hl1a%F\"l*i8\"E+iU%j-%[(*Z!X(9N\nXA3\"TmHJLU-AM!eM,4[H@2J0YUFKUJkEK,4AS!#iG9DKZ&Z6LS39H9K)IA'b\"Pj@\n%\"aGEj'8&dF%&\"VbX,$Mi`@P5%)J0X6SAH9Q[d\"!,6I'bJXMJ!SZm,\"!BNR&\"X8U\nmV#)YZ1J5,b[*#V(B2#mV5`TqF,i&-l`X%\"-5F6PH9K!5iKV$ZRcll-kGH9%*-*5\n1AMmemB!bNCmqL!GRCK\"5N4I06HHd[\"RG+V`X2Db3!!SX#S@9%K)GP,\"hVLFHA#b\nKLkb@-$m'P!S-q(433\"HE+Tq,bKI2K@C+jmF9#ZFRb!X$3G&+`\"'M,GQLpB+'#`f\n+9J--2d%H0BYJi5M0KNCV1pKGNcG0Q3j8Qc8I9j!!1$hQd+X@!p!$Mb5&HF1qmmD\nrT6p+JV,1+2%&h\"XSG%c+kLed,,jFD+F3$6bb9ZKdJ[,F3+l3[R4BU%\"5VmX@14Q\nG,l%[JG@Hee[HI(L[k&BXE3fUNT5h80SqQ2*CC1ejeG*@!#SIA@#@)23!FT46q05\nN9X'\"4bCTc-lC*KNb%&J)cr+f62$!``LI[k\"ZP%M%JV,VZQLl'iUUr#FG[r$\"QBE\nc+i1e@Yf-8RG$RG*PlAmp'ITH6hcKp35@AqqkT[4f&epmZBY1[pZ&e9lGefmZ[[,\nUI+qjX-+V`lbqh'j4N3heSU-fHp0-hZaQkm+DBE6rTTPfUqL@Ll,e6'bpjhT0YG&\nSi4Df-@qdXl'YPD#)fN5ASQ\"BfC!!@b2+49$fr05C$BV-CYAQ,CHfLNDYIjTellC\n@K[TPKHZVDjpD[rbLfMRpP-,'#FN``9k)8CR0reLZZIIN-Z8)AJ&6R01)1AD0M'r\nCCKBEQeNT*l,Z[SK-Aj!!*&ClZC6DFqXTPC&Y3q-E&KV!aXAl`5D9D[(!@29LYhE\nc[4ZVdrPLaIeQm,0kpA34UI+C4V2PbfcX%PRA@m`aPG%%jc)@RZ&D)p13!,'fNiF\nPZciINNP$Gq4$-QQSBMl%KjA$\"j1QA-d,9ZIj92&#T)0bUH,&5!GYU-lN*IXb3AI\nN\"9eYeLE(81p)cZUNM%dF+V*S`HH(G(ppEEdJ*TZ)!J8af858*iM*@jAi26lc`[V\npH*X+5SANE8dLk`Jm8LhUH@GG4$6hhh2-cF&q)U-Rr-5FG5f`'a[$JfAD&,Th(iD\n$iL0FE40AA@[(k0TE+j[bDZ%i8+lmX4GRHb!H@BT,i(iL@5`N8b9dX%20GBG)35Q\n*)`[9$V06HcNZN@kKFM91p-ck`bf6CJ@C[LQ&ji2&HL5blZ#&Q$ji!F$KFq[YrU*\n66*FAqrah3e&`FDaDCa9)Fh'S8mYMT1'GjYq0+2EHcHe'F(ecLi[EZr8'IfmU0ED\nMh1`TVQahqAqXHf@CB%marC3,`rpMeHeFl-eh0+TG(h1Xb(06APr[qVGlS5VfCPr\njekY,pd*KZJp@aZE`8NPYZ,,&k9kS6RFX6hH[2Yd(#p4pX%)Q`LX4&ek0ZRY&kMj\nBTHjBTKZVHmSiqHmpfUZ([6K3RHjdChIX)0CFlDfA98X%FHG&QBY$jFYL&h%3-E-\n,92&)8)RPdS(0NIb+HJHTLCFPlVc+QKKhBGj&!ab0&A\"h8S\"i+@bP[2ViY6*iF+M\n9f0kD+pXJGV82@H1'SUaAr-VGQ2caUpZEpEP'2E4,iLjfCC)PlZblVbX,',mbL'A\n+[@Hfk*5[L&qj'pX#lST'1TbcFkrA8pk9Zr(H*9IQ\"Nb3!##j1Pc8Qpfb4q-hZeU\nc\"@`cNGS2L6@0LdQ8aBAijABaLAC*[-C9a)A%X-i&a-!Q8j98S@*3NkP+)X6[c8a\n9dQ8R`'*c)NlZ$AqjP$&%2f-m*,8MYL8ImHZNBZd(`dr@6lB[hh'`X0!F`kRNJGh\nha1i*4(N1\"Eqq,&Xk9bEq-(6V)&U$Akp%61`Ud@'*Q)6Fl\"A-A@l)ZaYDphC\"2)3\nE#)VI2BQBj'#TpkciYHQbJke!3e*A4pZ0ZL3QF4@V51)PANI0T+95!6C$3XG1*,H\nj2'S%lh)APY6k!1%&q\"#BM[\"ca&Sj'4$,kEGP1Q*IPM[KZQF([54hA#9kbBp2\"AQ\n*BPG\"q,kib(YLr$@lfAYfr3YrMMFcZjZDedh1k'EQj6+@X9NhdB5cTKYP5mrGTQG\nYCEif2RbAmR2-'#HQ\"eLcIS+q-@$@#6(K#ZJF$K-1II%Te$flUX9-p4\"T@8Z)DC&\ni5*iLq5hU3V,FbQpc&j*P*$Rb%qIEQHFR8k6BQ'-mlMV,i(,X+8r&mTc4alTXL%P\nmY&Fc3G&dK%NV%I&H-h#qDblm0kK1#KI\"K4GLmL0XT9iN%BA*Xm+mQ%'b'jTA,$i\nL&R\"J@X3i8K*kpm\"ib!'(*2CFAK-824DH[!qQGA)61SQTR0#a5Cc3KUq*A@,VbSf\nRSb`-fl*dh*Ehhq'c#q5#\"k&[J*!!`)1'J!IGpDXkZiUJ+R4RJHQ'XH'\"q9[(AXZ\n+QF&M4H[jHE'R`d#A'FbrVR!fRm'1ZdTpfNb`l3Nbfej'4+qVjF85BfL4i!Ierid\n(4X)00k-,#6aJ(ra6H\"\"f4Ki6H+!#(RJ1,EHhRAS2Ba1A%RMJk3FKE!K3a!0lUE-\n60l@`GHVlkXE'*ST(ASfk[AYife4rifLHR#e$kV[hi$[Z1[U1[*P$pKfH\"D3hCeE\ni4Je16)`q8[PV19HhfrpCpbIHXAEmQMh(mKJI&!TEbl'fdAPiH1Rd1cE[,REdFcj\n6elEbV@[A,`h3(cXR0`mY$I!1Lc$AlcU+-,i,6qpRhh(6p*&hj,e*NPm-1IGeCai\n\"%IZ1r8HlqR6IK``JqB([`8Hm(J-F\"6HNlliM&)\"CA$ib86RfeX%qSqr0,1Ak4pl\n\"YlFe2IY)Mi',eMdM&1!GI(1Q'`aVrV#ZpKhlUppMThEZLRHB!G`IpePff$[cG5d\np`5KlaNB[2TBRl8C@V2b1dBH4kV[[#!eJJYX[h[KI#*bb95Ym1dCEfjF'U%G)\"6-\nG`2+NY9cY(E21A5VJ(Id&qIYhe)$mIlpMN!!422'1'qD1&Z68&cDJ*2b`le&X3JB\n8J)(Z5,ND9[[M-#iB)3([f(1N3`El)elA2EZqMBarril$4pMlB&eMl`J28%L1jMZ\nA#-#c8!#P*Aa#f6LkUr%`AdalFKBq()A#!Gl\"0iFQHDDZ1`kqidG0B[@'q$i%a54\n$PTj35%*101A`!!BA+U'pKLXJqHN[krH8q5BYqD%*QY,f9[jT6E$bMR#6kC!!Tc5\niFRGm6i-lmBiR0EJ6lhK5Jc[jMLFdZ-&hK&*SF29lEpR2\"&iNHrc@ekeF1hBUpar\n)([r'IGRM2RA0SET1ZR9p0VlbcK9hR2abiq[hhPCEU%F)J`CADE5R0EM\"GcbT`I8\nqi`FDh)Ph2+A\"&4m54U$\"pHF3rr16l`J&B0bBV!r@,'[%R[p#2l5m-U\"p6mZV-TQ\n`!#f[jb%T3VlfSG%YNipd%%`RI'+k+$aJ+LMXC(VQeU--cKKh-VNApr*-I6'Q%ci\naK@-mYhq-DGilISM!XHQCJ5QF[kY(q-hdc,'P!(`kc@)j#bqX,+k#NrP'ISF4Q)I\n81[ST4R$L(8mbJK2[H\",*6llM#53II%Gi!*+(,mc6pGBec''HVY*S6c1#`AFmb3K\nkRr%$4R$L(8pTHF@(a0ia)$1CGpL0P%lJd*(m5*raL\"Xk8C6SHdFSJ*E(&b)`,mC\n+'08[SGK8%Gqmip$fhGpqarEYZapqKdc[XkCANF)0r4p[&I1+5Sjrm&DT[H2dY-U\nJ@Ka#-+hb)`q5'00j`S1NeKrK!@Vk2hKeP1[a2Dq1@Pe2UpHRqjl[5Bq0@MhX1jl\n`aULp3hCeUJc#G5cj-3IR&6LSr02UGH8Gi44cF%pTAP5eGl,K(c@[%qpi8[-kmBi\nR0Dq6lhK#maTm4hM!r0T6@P9[2@)-lLP0TrFG2p\"d\"YpaNJP@J&@qN!!+Pk4`!#d\nQYAA!d%H\")&X(0#DRj0$6,l@HR,H1BmM+&`ShJf5r-lL,$65L0chhr0,pHY+CFbZ\nZZI[*h+r+6RrarZa(VQXFUZ[%keGRQfjrdiTRAhfAmG'EUTpCU-FCIm8''Xr80Fc\n\"YIS-h@8$M4#iVfGbC2LdN5BDpX'm@aQHDcGDaAGpIcI\"38KVZ%MSLPeUD-cA-($\n5l-D4UHc!THH(!'-frrR*Di1rG$IFDHRXXJ22I%Efm4qmZ[0f3LEdEFa1(K[HY!@\nRSHZRUS@Z-IG06Qeq)[F268b8cPV[f&b[UISm@XflSXU(L8H2qhLl++Fm2VHK86A\n[ekH3!&(-rmHCa$LDpI@GY,jS`BM9MkjBj+(4HVD+[pH8GrZc-rRlKM,`hZb(q2H\n0XQDcpF&@*j9hFl+ePDc[CmUlml+RmHr&-4p@qQq2GjZcl14ha#IZjY6Bjr,C!*!\n!0A`-k,lrlHYffqX'\"P5ejh4QQrhXiM'A)BZpXp2GcX$ZfTk\"#rS[')$*(afSYZX\n$5j)dJ%CS-+\"SIk%[hmJe3q2VKpG8eU`IR\"VNlik4SDNe5kXd3#-l*hKI$![-mN-\n)KrZP60k1-d@B-(P'm2H@P+HG[lHQ2#2jHc$PkH6[SC4R&(m2Tca`cpY5RM(m2C,\nbM1A[dC4R%Rr[6(NQmrHZP!ISZMrPJ5rAaccQUTaR0F&e+Fp'JTY5RNebq90jc)b\n`1M(PkH([JC4R'hr[5AQB+AX6JS'(Kj8mGa2HN!$HFar\"Be1HPa!m-Z9jJ1#1P1H\nPr,dqeI&\"`M[6Hhk+i#NTcrd%Mcq@j``)i8[YF0EbD\"*NKl2UAJ'KTamlR1'D9E2\n,$MIj3Z0QN!$1j#jf1(ZQVQ%11bHFD96XF&DrpjEpj4k9NlHqEZADX91jrd$fq$I\nZbalhU@X1eAA5VHZcmC9hVVMMj*FEAlrhYYT#2Fk-AhBiLpiA&3kd#FXePhHkeBI\ndZ*!!K)qp3N*N2SYTCb!)fmVpMiq'!,D9q`UEbrREbRhQCVH91qBfF'(UfmU&ebJ\n-pGRb93GYp@FLe*jcIiS,iaI#8\"Zeq1T`Z@hckS'!8\"JT[2NHk$E6p(RS([c#\"k!\npqCC,qUlY1h%C5mkj,k5JCbZ2!L8F8X6%N!\"5eH`3'cQLkdF[f6DpTekE+&UlYdi\nbZK*G%U\"`q[jKM[pAm1+kK6fFQcLhFDlLA-fjNA-,jpfFScR(F)lPR-3jQA-8CbG\nR1fFEj`M1NC`c1'rK[)rc*C`2F,k8md&i01XDARCX,6b6Kh80RjhbG2$hmT5(G3f\n[6(PBer#UP!IalHU8Kh80VdPj@0I`fT4R((q[5hPBer$'P!FamUD8\"ijiAmV$91c\nV8KkceQ(NG5N2`emReL%dHFckKj%hT$aQrF2)De)Hl%9HQ2+`rZ%9+3rV(cirjB(\naI#EPH5(KSe1H&r(h$5Q2@4-aFPh+BpBV2,R@SFPMeMp8I5N2DbGf(FYcjSh`SA2\n!$H&pjQcRl1$Xj\"c&1CTcM*`I2JpAKiI$XH(2F'0i,j`@[JSAK4I#qH\"cF$9iQ19\nBU686KckD\"&NcXES19HMTjiEU&erdX,0`@-NA#MH$C,m`932+-&V$Y-B!KXm`2XY\nd3L(S6ZScQaX0f65qDA\"XZ(pifcG`hNlH@[CVrXMrV*d4,hRb`C%$R(rqD1jLEG2\nS6Fmp[p3\"*jdjYq+DZjr-rDVXp\"I[chlNZXDKZNkmIR@fkIBhVAMfeAFC(lfTqTQ\n&HTca9kaYqNaG`aa@[6XMGeREp!`%BCR0,5b`bFFbQlZZ[AHCcBh2F*R0SfmR*,a\nNQFd`Qp8G)kG2GQYZmm,-c0&@)lp[QM@ffCieRq+NdbllNb83DK0HYlTM+!`'K-4\nmBET,iRA'T461l\"1B8qN,SpMX08aJ1BNcq35qH(+YNc2[\"8BCEX)+``MH-j(c#h&\n$V5r'kGqrF#mpmhdTX[-[Pa[c4V)[aXlkDScrbh#[IMM'I5h'ICeYfIRqUTaBMQ4\nha[ar(E[UEf+qEf52+IrrEAcR0m0rY6UqkqciIhVm2b2Qr9CmclGMh-3BpeKmrq1\naMYm*HEb1#G9P8Q&RAi`(0@qmZ$AEV'%T9NaNA38`46*XLSdP[c1rG@66qZCXB`N\n!\"l,3d!r\"+DA6%f#$E(4LU6FAP2P#!0Ce-kqUVrDhC[r[%H\"mcf$T31-@KJSGk*2\nHZc1lK1q-*81&5Ba0Kq'S-'Gf#9p)mIa,b)ZbmVekrYqlm,E[c(3\"!cc\"4B`(*55\nFaVR90SPDJ3fI$!,92Y4HqDVf`#@a+a`#&d*PqMl4UfG5%MJCl`SDZCd6Kfq'mh(\n%EZ$%+4ZAl$'FZ(@c-eJ(j`M1PSJ&Z(HhFJlPC0q`8C`iGSrN(-[Cb6PZ+BIb[Qf\n1lESL-jhZi9hIM[eUPUdf,MdK1KERmk('(6cF*M2j-j1iQqm0Dq\"p)q2lkQlV\"AD\nr`VE`hZI(+4E5Uir[mq0QdLI0qfHkjHD1#D4U)&rN,Z,BBM)4erK-rR60G$Z(mc@\nk$CV8bArIX\"qMc@I2Y$Z(ihEF4)[[RHRZ2&bR4VCDLjc+ZkPhiRe0lqI2Vmed'ke\nliaEZ*IqULG&10e[q\"AGIQacL1Rq$2h2+AGEU2[3HlXi,F3HI$p4X#R([(65(&cI\nbAm8J,qjAAX$Gh\"\"hP(k0V!jahcR(\"T2hI8aFmZ)qi@k$bf+q4rRc8\"NAIHSRZ9X\nHqjlpe6D(I!ql41D+%0IbjX9q5K#ECc1('1[,4&bcZ9eI*Z)Dpbhf65+ZjAf,IC1\n)fr2V[IlirFZiNeeqphbdeam(a9AC$(1IQ#Vpm4XIjUiRa\"e`efhTM`FrapeP-Hj\nRH[eal58@91*H[G!IGDqmNl[,Ber5Rejr4+IXb5Y#A)Fpj08TqT+riNj`m\"G@,p3\nTHVUB)CZUYPqd8+IS#phD8RC,I35mP$T&Alk&ZcXLlKVmN!!k45rl-qi-2YKm2pI\nVil2&0[+$kp4'k[4+0d58h9mll$q[6[T*Rq)12+&pIRDK6VV2A[pfL\"[bSB8kkCF\nkFrTBL*Yaad+Gp-@rc0hMXBrT6kp1H[LVh*PGk[L@[R1K6ZV2k5d(MGeLQeFRYCq\nP&Kh$(Q+0Qd,rIH9hL9XCFAU5A-UVklV2%bFlZcA*2b6IPrqCZ+YM(*[SHIRUAJY\nh8qAZGbD1hHfmI0'9p*EbAB5mTjI[VKF6*cMG4\"p,(far#RdJHq\"&6KBc[,KYY3Z\n)Hh1Xhk[i-cA8pHh'I65q!kiRrG&XAF&R)2'qKIl3,`*Ve0q%Z+%Z-1ReKci$6U6\nq0[)!qY*lRck0RPIr&2[l&EhhcB5R+V',IUAZdRm[\"`m82@*j#FZmbIZ@`@r99b*\n1rc*raT9aNAH!P9VqDm,(mGDfDd2FErdLFI\"Gmld+rY%3qLEb02L`PYqDI,2Jah0\n[$A&AITBiq+lj4T!!3adIiUk&HfKj-Hrq2B[VaGh`am5\"lF4pDU'ZN5IF5KbFQcJ\nifA$MMXrrfpR%JIrJUhQ61LlNqp3r%LFFZdQHXc,%(3*lY([rm3lUEYpKS28\"iLC\n%r[3R[%0f$A`aNp[DA4piKmNK1\"(jrp4'4r`B$BG6TiDii@ka*rJa\",i5Z6$%IC'\nHeR'Rf(fmThiLe1qVD!Mk#5(ZY@q&,lD(I!rF6Gc8%0FU\"lSqa+hm#q+Q44b#-bd\n*F4I6NeUmSNlS&F0Lhm`Qc[5)M3-RT-q@fdr6Babm6ITXrkZ*NfA[4UTcr(D)H`p\n[dq+YqFj'$e\"RKEK4p,D@Hj)2h(mia!eP0d)0[lCi4RpErR&mrN[`84ehqecm,Zk\nNRbDq4#iZIB-Z)6Md+*a@\"hkXR[A&(Jlp+9a,\"hkXpVb`Kd26fDT9\"hkXpY+[$SI\nQd%-kEUJi(plTF1J&Vb,1B,AY*lLAp-HGRb\"Z3Dc(bhVpd3'2e%q*G@9h4-'26R\"\nD2cA%E8,RF$Kd%Ea(Xd1LlH0hpA$SCA\"F(IF5(UDZ*1qiiUA%A4$L0X06(3jp4*b\n!2e)RH+h8qe*Lp)q(Z0Ir83q(ERdpFD)(Y)Q$JN-cl$p2$e$Ai4cLiC!!@9'$r[$\nd!(8pQaFk(2ShD\"XkkJ&M`\"k(3epq*A(#cpVNiB*$M@#\"M[bXaIF,$Mh(ZSTr3E[\ni+(dfrAELi)1d'$a-qZc2i-BkEPSl(ClUF1Kcm%XGYdImHIL3!-1KYlfE10Q%GXQ\n024cDLGDLikSI(El(im'4#ATBK`eXe9XqeX1Kc3HiJpp42rLcdcqmc6PX[VGm'Fc\nm303riR'40kZ2I6VU(iQi$KeDR2i4Mp1VA(GiAp3r%[R'LSq#IbhL)VU@HIH[`9m\nGrVd@(Up(3Yb(U+Z(ImIRri%lc@k5a2hqTKlqADA@*6V+'cl6`lpAQdpdP!jjTr6\nP#ML%MMV+-(QGlF[MmhI\"QcA[XR@LVi5(I84H*AZd[J9mF[MhN!$i,FXr,j!![`V\nqAB9fSXXG+mdlf#YIm1qem'1p1G6[@q#T`lqAL+qbIhi,f1EKhr(j[r`)FHKA*Y9\nMD+`1rqTrMMM`h(a,h5&6m'mY'S'@6jP8Mm2I(!rl@lL3!0iDqV*1(9,`le+iVik\nkdI9I1SKraqFr)$m6h@L2pE,iGhcqGM\"H4peS*(c&iGp9k-3kkNB,ZA0pGJ303$m\nRpJ&i)(hfQ(Km9BKlUhJLq(H*20[61I4ap+Z(ImIRhb0HHMU(2PiG3[\"[S4a,&SF\np+Mm8([B&qEfhEV-q!9cfm1rir#I4)(6Fd,VeAaEa,llITPi&$fLk,H*I)Zj4GCc\n24[b,ad9'hD$@i9mLhbKU%m1r4,iMERlTi9rG(iKcKYq4Ec3mAr![qMbd62fL%$I\nM,3[mVqjkZ)F15f[VTi'TJRpe0mK6Aa$LKS\"hJRr4Xq`ESrPBR(MP3Pp'XlmMcQ#\n[VCr*iI6#0m+9pG8acR!D`DhSFm3RlXhI&R\"+m#pk$KLKeAQS+hUKKhr4&k$&k*G\n&r%\"AN!\"hX$QT$MU62NqYb-1rZLqK9HMr&h%DMG29qeH*)cqdefJcJRr4R`!l0$c\n8pMhij1&Ip!`d\"5fI0Arh`Q@&rp@pPEN'$DFMEYk[,H\"Ih4[T-Id,i4e[**r`[qK\nb0!r0HrRHl2XprKGYJR&DcC0hdbFHrNA24[[3kUl`*(L&p0RH$a,h81`$F%[dc[2\n3ZE@m$lS06RMi&jeKGe-0CbGZ2ca@q&rGAm1400S&FEI)%ccmLfk&BfYe$qU%rLf\nkmLr\"bEAp6MkMK`VrUrX!ZE9e-(m2fK1HAKKj#4LQj4hQlf&Q1qSLRhL1ld!,jAe\nSXCiq&aN&Fl9kX[NHNFm,hSpr'h(SYm6\"ai6RAI%QiPi6hMId$rRRkAD4[@J6@Th\nIr$hI2[0dZmLBZSlT8q+1bVfN6S[S#DhHDrlH$MpdGET'r[(kq!jd5DR6@,LG9Qq\n(ek+h5CfDj8RHRUakcXehT%j[KPYVDQAMk$HTdb'iR9C$0Rr[kZQ,NBYqM`\"2(p9\nAbKfP6K2JkYSj#22hERLfUe1RrIe`L,Z(A[(UC2LCd@)d1'rj4a`r)Um'1c5kQFh\nh\"ldkGGe-!2Q*-jcHeHQ2k@hY,!Ed!Aj[kh4mrJjjfb-alS1p1Vd0E8@(29reci0\n9VNl23S28kY[d2Ea3k[40Z,j@4b81RLae@Lm2\"XISEhLMe1R6B)%11mAUUpACT8k\n[&+F0YK2h)R&@qZNAdBVdlm3q0K`dFXS-HjV(Z40apkR(I@QQHYr'fir)JcfFDhi\nE'V5'Aj!!lhki8AfSGr-Pe%kMT4$h-R6+ZX!2QRm*,926bm3pf01IQYk2VUc9YBL\nMRlak0rmQ'V4fYS8iH-A9)@kRZLNk$h(`L6H'Z!I%!h!2qN#pjAh[rJ)\"4YHbF3C\n2ACeZG6NKG\"jJhf#'e+RTYp'U0\"SbFDp5(jGk2b`rH(q-3kH81Xf#NqL`DDaq[EU\nfe1P+HPZr0mBaKq(9UHNVmM0i\",#2VLh[Hm\"h'pb`F8E2P6SeI36Xdmie!0HQ,ed\nrrD5D%r-[`#pp)rAq1*U)GTk)12LN9kHQVm)9p3GL($c%Ue26qq3I[a[MQ,f3!$T\np5pd4[3iHKQiZGCU#4U$9Bi(hH$mel9HI0[K'h-1pIQVq@IX!hBCh`0qN6Tm8bm&\nEm!bq,rh8U2i02`9qk6qTdjqM9@Zd'Z,HUZiMIIm+Z)K@*`GqdF'ppcAHBTfBU5%\n1r9IH[3*ZS1NG'iIZ+A'2q1k24(k*VL&a9cPRi-eKk0qbYlbjMBEIK`2V-)HKhiP\n1*('0Tk(Yk6#(SGmPGjGmAd-ld'%13pmJYjDicm*&0&SaFEr1ZpAji4hhUQ-C$B'\niGpJhZd2F,(NB1J\"aCMBLmUS3plKkkLG#h$[\"!q(aM4H+LfBHMEKh`IrGqckYR[(\n*%2GZF9EHph*a&ai(c$+(+1qE3UpUjKTXR1'\"lRdcl32$PBKl,rc%[HpCkVl-#J'\nrr*IhVD8(p+G$h2[8YH9pCm%4p5dacZ#1Hpm'iicH50a[dJrZIBqTVe0ri*Fj5RR\nI+p&H0E-*0Jlp5plh#E\"!bq1)-h0)lRd2b*rXM0lr\"`#3!edP!!!:\n"
  },
  {
    "path": "deps/infozip/zip30/macos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __MACOS_OSDEP_H\n#define __MACOS_OSDEP_H 1\n\n#ifndef MACOS\n#  define MACOS\n#endif\n\n\n#include <setjmp.h>\n#include <types.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <unix.h>\n#include <unistd.h>\n#include <console.h>\n\n#include <Errors.h>\n#include <Files.h>\n\n#include \"unixlike.h\"\n#include \"macglob.h\"\n\n#define NO_MKTEMP           1\n#define PASSWD_FROM_STDIN   1\n#define NO_SYMLINKS         1\n\n#define USE_ZIPMAIN         1\n\n#define USE_CASE_MAP        1  /* case_map is used to ignore case in comparisons */\n\n\n\n\n/*\n#define DEBUG_TIME\n */\n\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n\n#undef  IZ_CHECK_TZ\n\n#ifndef ZP_NEED_MEMCOMPR\n#  define ZP_NEED_MEMCOMPR\n#endif\n\n\n#define EXDEV  18\n\n#define PATHCUT ':'\n\n\n/* file operations use \"b\" for binary */\n#define FOPR  \"rb\"\n#define FOPM  \"r+b\"\n#define FOPW  \"wb\"\n\n/*\n#define DEBUG\n*/\n\n/* These functions are defined as a macro instead of a function.\nso we have to undefine them for replacing (see printf.c)  */\n#undef getc\n#undef getchar\n#undef putchar\n\n\n\nvoid setfiletype(char *file, unsigned long Creator, unsigned long Type);\n\nchar *GetZipVersionsInfo(void);\nchar *GetZipVersionLocal(void);\nchar *GetZipCopyright(void);\n\nvoid InitAllVars(void);\n\nvoid PrintFileInfo(void);\n\n\n\nint fprintf(FILE *file, const char *format, ...);\nint printf(const char *format, ...);\nvoid perror(const char *parm1);\nint macgetch(void);\n\n\nint MacOpen(const char *path,int oflag,...);\nFILE *MacFopen(const char *path,const char *mode);\n#define fopen(path, mode)   MacFopen(path, mode)\n#define open(path, oflag)   MacOpen(path, oflag)\n\n\nchar *GetComment(char *filename);\nint readlink(char *path, char *buf, int size);\n\nvoid PrintStatProgress(char *msg);\nvoid InformProgress(const long progressMax, const long progressSoFar );\nvoid ShowCounter(Boolean reset);\nvoid leftStatusString(char *status);\n\n\n\n\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#endif   /* __MACOS_OSDEP_H */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/readme.1st",
    "content": "This port is for Mac versions before Mac OS X.  As Mac OS X is build on Unix,\nuse the Unix port for Mac OS X. - 7 June 2008\n\n\nBefore you start:\n\nExtract \"*.hqx\" and \"source:*.hqx\" first and read the Readme.txt.\n\nThe resource file and the compiler project files are in BinHex form because\nthey contain Macintosh resource forks and as such can not be simply\nstored a normal file on a non-Macintosh system.  BinHex form is the\ntraditional way for transferring such files via non-Macintosh systems.\nIt's also the safest since it uses only printable characters.  The \".hqx\"\nfiles must be converted with StuffitExpander or BinHex 4.0 (or equivalent)\non a Macintosh system before using them.\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/VolWarn.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n\nThis is an Important note  about pathnames\n\n*/\n\nstatic char DuplicVolumeNote[] = {\n    \"\\rIMPORTANT NOTE:\" \\\n    \"\\r\" \\\n    \"\\r This port has one weak point: It is based on pathnames !! \" \\\n    \"\\r Because it's a port !! Unlike MacOS: As far as I know all other \"\\\n    \"\\r Operatingsystems  (eg.: Unix, DOS, OS/2, ...) are based on pathnames\" \\\n    \"\\r \" \\\n    /* a short quote from \"Inside Macintintosh, Files\"; slightly modified by me */\n    \"\\r On a Mac: Files and directories located in the same directory \" \\\n    \"\\r must all have unique names. However, there is no requirement \" \\\n    \"\\r that volumes have unique names. It is perfectly acceptable for two mounted\" \\\n    \"\\r volumes to have the same name. This is one reason why a application should \" \\\n    \"\\r use volume reference numbers rather than volume names to specify volumes,\" \\\n    \"\\r but for this Zip-Port I can't use reference numbers. \" \\\n    \"\\r \" \\\n    /* end quote */\n    \"\\r\" \\\n    \"\\r From the developers point of view:\"\\\n    \"\\r The use of pathnames, however, is highly discouraged. If the user changes\"\\\n    \"\\r names or moves things around, they are worthless.\" \\\n    \"\\r Full pathnames are particularly unreliable as a means of identifying files,\" \\\n    \"\\r directories or volumes within your application,\" \\\n    \"\\r for two primary reasons:\" \\\n    \"\\r\" \\\n    \"\\r*  The user can change the name of any element in the path at\" \\\n    \"\\r   virtually any time.\" \\\n    \"\\r*  Volume names on the Macintosh are *not* unique. Multiple\" \\\n    \"\\r   mounted volumes can have the same name. For this reason, the use of\" \\\n    \"\\r   a full pathname to identify a specific volume may not produce the\" \\\n    \"\\r   results you expect. If more than one volume has the same name and\" \\\n    \"\\r   a full pathname is used, the File Manager currently uses the first\" \\\n    \"\\r   mounted volume it finds with a matching name in the volume queue.\" \\\n    \"\\r\" \\\n    \"\\r\" \\\n    \"\\r The main reason is that an attempt to implement support exact saving of\" \\\n    \"\\r the MacOS specific internal file-structures would require a throughout\" \\\n    \"\\r rewrite of major parts of shared code, probably sacrifying compatibility\" \\\n    \"\\r with other systems.\" \\\n    \"\\r I have no solution at the moment. The port will just warn you if you try\" \\\n    \"\\r zip from / to a volume which has a duplicate name.\" \\\n    \"\\r MacZip has problems to find the archives and files.\" \\\n    \"\\r\" \\\n    \"\\r\" \\\n    \"\\r ... and the moral of this story:\" \\\n    \"\\r\" \\\n    \"\\r Don't mount multiple volumes with the same \" \\\n    \"\\r name while zip/unzip is running\" \\\n    \"\\r and \"\\\n    \"\\r My (Big) recommendation: Name all your volumes with a unique name \"\\\n    \"\\r (e.g: add a space character to the name) and\" \\\n    \"\\r MacZip will run without any problem.\" \\\n    \"\\r\" \\\n    \"\\r\" \\\n    \"\\r Dirk Haase\" \\\n    };\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/charmap.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __macos_charmap_h\n#define __macos_charmap_h\n\n/*\n\nConversion table from MacOS Roman to\n\"Western Europe & America\" Windows codepage 1252\n\n     Notes on Mac OS Roman:\n     ----------------------\n\n       Mac OS Roman character set is used for at least the following Mac OS\n       localizations: U.S., British, Canadian French, French, Swiss\n       French, German, Swiss German, Italian, Swiss Italian, Dutch,\n       Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,\n       Portuguese, Brazilian, and the default International system.\n\n       Not every char of the charset MacRoman has their equivalent\n       in Windows CodePage1252.\n       To make the mapping in most cases possible, I choosed\n       most similar chars or at least the BULLET. Chars that\n       do not have a direct match are marked with '***'\n\n       The Windows codepage 1252 contains the ISO 8859-1 \"Latin 1\" codepage,\n       with some additional printable characters in the range (0x80 - 0x9F),\n       that is reserved to control codes in the ISO 8859-1 character table.\n\nIn all Mac OS encodings, character codes 0x00-0x7F are identical to ASCII\n\n*/\n\n\n\nZCONST unsigned char MacRoman_to_WinCP1252[128] = {\n/*  Win CP1252          UniCode  UniCode Names       */\n    0xC4    ,       /*  0x00C4  #LATIN CAPITAL LETTER A WITH DIAERESIS      */\n    0xC5    ,       /*  0x00C5  #LATIN CAPITAL LETTER A WITH RING ABOVE     */\n    0xC7    ,       /*  0x00C7  #LATIN CAPITAL LETTER C WITH CEDILLA        */\n    0xC9    ,       /*  0x00C9  #LATIN CAPITAL LETTER E WITH ACUTE      */\n    0xD1    ,       /*  0x00D1  #LATIN CAPITAL LETTER N WITH TILDE      */\n    0xD6    ,       /*  0x00D6  #LATIN CAPITAL LETTER O WITH DIAERESIS      */\n    0xDC    ,       /*  0x00DC  #LATIN CAPITAL LETTER U WITH DIAERESIS      */\n    0xE1    ,       /*  0x00E1  #LATIN SMALL LETTER A WITH ACUTE        */\n    0xE0    ,       /*  0x00E0  #LATIN SMALL LETTER A WITH GRAVE        */\n    0xE2    ,       /*  0x00E2  #LATIN SMALL LETTER A WITH CIRCUMFLEX       */\n    0xE4    ,       /*  0x00E4  #LATIN SMALL LETTER A WITH DIAERESIS        */\n    0xE3    ,       /*  0x00E3  #LATIN SMALL LETTER A WITH TILDE        */\n    0xE5    ,       /*  0x00E5  #LATIN SMALL LETTER A WITH RING ABOVE       */\n    0xE7    ,       /*  0x00E7  #LATIN SMALL LETTER C WITH CEDILLA      */\n    0xE9    ,       /*  0x00E9  #LATIN SMALL LETTER E WITH ACUTE        */\n    0xE8    ,       /*  0x00E8  #LATIN SMALL LETTER E WITH GRAVE        */\n    0xEA    ,       /*  0x00EA  #LATIN SMALL LETTER E WITH CIRCUMFLEX       */\n    0xEB    ,       /*  0x00EB  #LATIN SMALL LETTER E WITH DIAERESIS        */\n    0xED    ,       /*  0x00ED  #LATIN SMALL LETTER I WITH ACUTE        */\n    0xEC    ,       /*  0x00EC  #LATIN SMALL LETTER I WITH GRAVE        */\n    0xEE    ,       /*  0x00EE  #LATIN SMALL LETTER I WITH CIRCUMFLEX       */\n    0xEF    ,       /*  0x00EF  #LATIN SMALL LETTER I WITH DIAERESIS        */\n    0xF1    ,       /*  0x00F1  #LATIN SMALL LETTER N WITH TILDE        */\n    0xF3    ,       /*  0x00F3  #LATIN SMALL LETTER O WITH ACUTE        */\n    0xF2    ,       /*  0x00F2  #LATIN SMALL LETTER O WITH GRAVE        */\n    0xF4    ,       /*  0x00F4  #LATIN SMALL LETTER O WITH CIRCUMFLEX       */\n    0xF6    ,       /*  0x00F6  #LATIN SMALL LETTER O WITH DIAERESIS        */\n    0xF5    ,       /*  0x00F5  #LATIN SMALL LETTER O WITH TILDE        */\n    0xFA    ,       /*  0x00FA  #LATIN SMALL LETTER U WITH ACUTE        */\n    0xF9    ,       /*  0x00F9  #LATIN SMALL LETTER U WITH GRAVE        */\n    0xFB    ,       /*  0x00FB  #LATIN SMALL LETTER U WITH CIRCUMFLEX       */\n    0xFC    ,       /*  0x00FC  #LATIN SMALL LETTER U WITH DIAERESIS        */\n    0x86    ,       /*  0x2020  #DAGGER     */\n    0xB0    ,       /*  0x00B0  #DEGREE SIGN        */\n    0xA2    ,       /*  0x00A2  #CENT SIGN      */\n    0xA3    ,       /*  0x00A3  #POUND SIGN     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  #BULLET     */\n    0xB6    ,       /*  0x00B6  #PILCROW SIGN       */\n    0xDF    ,       /*  0x00DF  #LATIN SMALL LETTER SHARP S     */\n    0xAE    ,       /*  0x00AE  #REGISTERED SIGN        */\n    0xA9    ,       /*  0x00A9  #COPYRIGHT SIGN     */\n    0x99    ,       /*  0x2122  #TRADE MARK SIGN        */\n    0xB4    ,       /*  0x00B4  #ACUTE ACCENT       */\n    0xA8    ,       /*  0x00A8  #DIAERESIS      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xC6    ,       /*  0x00C6  #LATIN CAPITAL LETTER AE        */\n    0xD8    ,       /*  0x00D8  #LATIN CAPITAL LETTER O WITH STROKE     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xB1    ,       /*  0x00B1  #PLUS-MINUS SIGN        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x00A5  #YEN SIGN       */\n    0xB5    ,       /*  0x00B5  #MICRO SIGN     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xAA    ,       /*  0x00AA  #FEMININE ORDINAL INDICATOR     */\n    0xBA    ,       /*  0x00BA  #MASCULINE ORDINAL INDICATOR        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xE6    ,       /*  0x00E6  #LATIN SMALL LETTER AE      */\n    0xF8    ,       /*  0x00F8  #LATIN SMALL LETTER O WITH STROKE       */\n    0xBF    ,       /*  0x00BF  #INVERTED QUESTION MARK     */\n    0xA1    ,       /*  0x00A1  #INVERTED EXCLAMATION MARK      */\n    0xAC    ,       /*  0x00AC  #NOT SIGN       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x83    ,       /*  0x0192  #LATIN SMALL LETTER F WITH HOOK     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xAB    ,       /*  0x00AB  #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK      */\n    0xBB    ,       /*  0x00BB  #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK     */\n    0x85    ,       /*  0x2026  #HORIZONTAL ELLIPSIS        */\n    0xA0    ,       /*  0x00A0  #NO-BREAK SPACE     */\n    0xC0    ,       /*  0x00C0  #LATIN CAPITAL LETTER A WITH GRAVE      */\n    0xC3    ,       /*  0x00C3  #LATIN CAPITAL LETTER A WITH TILDE      */\n    0xD5    ,       /*  0x00D5  #LATIN CAPITAL LETTER O WITH TILDE      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x96    ,       /*  0x2013  #EN DASH        */\n    0x97    ,       /*  0x2014  #EM DASH        */\n    0x93    ,       /*  0x201C  #LEFT DOUBLE QUOTATION MARK     */\n    0x94    ,       /*  0x201D  #RIGHT DOUBLE QUOTATION MARK        */\n    0x91    ,       /*  0x2018  #LEFT SINGLE QUOTATION MARK     */\n    0x92    ,       /*  0x2019  #RIGHT SINGLE QUOTATION MARK        */\n    0xF7    ,       /*  0x00F7  #DIVISION SIGN      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xFF    ,       /*  0x00FF  #LATIN SMALL LETTER Y WITH DIAERESIS        */\n    0x9F    ,       /*  0x0178  #LATIN CAPITAL LETTER Y WITH DIAERESIS      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xA4    ,       /*  0x00A4  #CURRENCY SIGN      */\n    0x8B    ,       /*  0x2039  #SINGLE LEFT-POINTING ANGLE QUOTATION MARK      */\n    0x9B    ,       /*  0x203A  #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x87    ,       /*  0x2021  #DOUBLE DAGGER      */\n    0xB7    ,       /*  0x00B7  #MIDDLE DOT     */\n    0x82    ,       /*  0x201A  #SINGLE LOW-9 QUOTATION MARK        */\n    0x84    ,       /*  0x201E  #DOUBLE LOW-9 QUOTATION MARK        */\n    0x89    ,       /*  0x2030  #PER MILLE SIGN     */\n    0xC2    ,       /*  0x00C2  #LATIN CAPITAL LETTER A WITH CIRCUMFLEX     */\n    0xCA    ,       /*  0x00CA  #LATIN CAPITAL LETTER E WITH CIRCUMFLEX     */\n    0xC1    ,       /*  0x00C1  #LATIN CAPITAL LETTER A WITH ACUTE      */\n    0xCB    ,       /*  0x00CB  #LATIN CAPITAL LETTER E WITH DIAERESIS      */\n    0xC8    ,       /*  0x00C8  #LATIN CAPITAL LETTER E WITH GRAVE      */\n    0xCD    ,       /*  0x00CD  #LATIN CAPITAL LETTER I WITH ACUTE      */\n    0xCE    ,       /*  0x00CE  #LATIN CAPITAL LETTER I WITH CIRCUMFLEX     */\n    0xCF    ,       /*  0x00CF  #LATIN CAPITAL LETTER I WITH DIAERESIS      */\n    0xCC    ,       /*  0x00CC  #LATIN CAPITAL LETTER I WITH GRAVE      */\n    0xD3    ,       /*  0x00D3  #LATIN CAPITAL LETTER O WITH ACUTE      */\n    0xD4    ,       /*  0x00D4  #LATIN CAPITAL LETTER O WITH CIRCUMFLEX     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xD2    ,       /*  0x00D2  #LATIN CAPITAL LETTER O WITH GRAVE      */\n    0xDA    ,       /*  0x00DA  #LATIN CAPITAL LETTER U WITH ACUTE      */\n    0xDB    ,       /*  0x00DB  #LATIN CAPITAL LETTER U WITH CIRCUMFLEX     */\n    0xD9    ,       /*  0x00D9  #LATIN CAPITAL LETTER U WITH GRAVE      */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x88    ,       /*  0x02C6  #MODIFIER LETTER CIRCUMFLEX ACCENT      */\n    0x98    ,       /*  0x02DC  #SMALL TILDE        */\n    0xAF    ,       /*  0x00AF  #MACRON     */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0xB8    ,       /*  0x00B8  #CEDILLA        */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95    ,       /*  0x2022  # ***  BULLET       */\n    0x95            /*  0x2022  # ***  BULLET       */\n };\n\n\n\nZCONST unsigned char WinCP1252_to_MacRoman[128] = {\n/*  Mac Roman           UniCode  UniCode Names       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xE2    ,       /*  0x201A  # SINGLE LOW-9 QUOTATION MARK       */\n    0xC4    ,       /*  0x0192  # LATIN SMALL LETTER F WITH HOOK        */\n    0xE3    ,       /*  0x201E  # DOUBLE LOW-9 QUOTATION MARK       */\n    0xC9    ,       /*  0x2026  # HORIZONTAL ELLIPSIS       */\n    0xA0    ,       /*  0x2020  # DAGGER        */\n    0xE0    ,       /*  0x2021  # DOUBLE DAGGER     */\n    0xF6    ,       /*  0x02C6  # MODIFIER LETTER CIRCUMFLEX ACCENT     */\n    0xE4    ,       /*  0x2030  # PER MILLE SIGN        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xDC    ,       /*  0x2039  # SINGLE LEFT-POINTING ANGLE QUOTATION MARK     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD4    ,       /*  0x2018  # LEFT SINGLE QUOTATION MARK        */\n    0xD5    ,       /*  0x2019  # RIGHT SINGLE QUOTATION MARK       */\n    0xD2    ,       /*  0x201C  # LEFT DOUBLE QUOTATION MARK        */\n    0xD3    ,       /*  0x201D  # RIGHT DOUBLE QUOTATION MARK       */\n    0xA5    ,       /*  0x2022  # BULLET        */\n    0xD0    ,       /*  0x2013  # EN DASH       */\n    0xD1    ,       /*  0x2014  # EM DASH       */\n    0xF7    ,       /*  0x02DC  # SMALL TILDE       */\n    0xAA    ,       /*  0x2122  # TRADE MARK SIGN       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xDD    ,       /*  0x203A  # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD9    ,       /*  0x0178  # LATIN CAPITAL LETTER Y WITH DIAERESIS     */\n    0xCA    ,       /*  0x00A0  # NO-BREAK SPACE        */\n    0xC1    ,       /*  0x00A1  # INVERTED EXCLAMATION MARK     */\n    0xA2    ,       /*  0x00A2  # CENT SIGN     */\n    0xA3    ,       /*  0x00A3  # POUND SIGN        */\n    0xDB    ,       /*  0x00A4  # CURRENCY SIGN     */\n    0xB4    ,       /*  0x00A5  # YEN SIGN      */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAC    ,       /*  0x00A8  # DIAERESIS     */\n    0xA9    ,       /*  0x00A9  # COPYRIGHT SIGN        */\n    0xBB    ,       /*  0x00AA  # FEMININE ORDINAL INDICATOR        */\n    0xC7    ,       /*  0x00AB  # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK     */\n    0xC2    ,       /*  0x00AC  # NOT SIGN      */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA8    ,       /*  0x00AE  # REGISTERED SIGN       */\n    0xF8    ,       /*  0x00AF  # MACRON        */\n    0xA1    ,       /*  0x00B0  # DEGREE SIGN       */\n    0xB1    ,       /*  0x00B1  # PLUS-MINUS SIGN       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAB    ,       /*  0x00B4  # ACUTE ACCENT      */\n    0xB5    ,       /*  0x00B5  # MICRO SIGN        */\n    0xA6    ,       /*  0x00B6  # PILCROW SIGN      */\n    0xE1    ,       /*  0x00B7  # MIDDLE DOT        */\n    0xFC    ,       /*  0x00B8  # CEDILLA       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xBC    ,       /*  0x00BA  # MASCULINE ORDINAL INDICATOR       */\n    0xC8    ,       /*  0x00BB  # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK        */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xC0    ,       /*  0x00BF  # INVERTED QUESTION MARK        */\n    0xCB    ,       /*  0x00C0  # LATIN CAPITAL LETTER A WITH GRAVE     */\n    0xE7    ,       /*  0x00C1  # LATIN CAPITAL LETTER A WITH ACUTE     */\n    0xE5    ,       /*  0x00C2  # LATIN CAPITAL LETTER A WITH CIRCUMFLEX        */\n    0xCC    ,       /*  0x00C3  # LATIN CAPITAL LETTER A WITH TILDE     */\n    0x80    ,       /*  0x00C4  # LATIN CAPITAL LETTER A WITH DIAERESIS     */\n    0x81    ,       /*  0x00C5  # LATIN CAPITAL LETTER A WITH RING ABOVE        */\n    0xAE    ,       /*  0x00C6  # LATIN CAPITAL LETTER AE       */\n    0x82    ,       /*  0x00C7  # LATIN CAPITAL LETTER C WITH CEDILLA       */\n    0xE9    ,       /*  0x00C8  # LATIN CAPITAL LETTER E WITH GRAVE     */\n    0x83    ,       /*  0x00C9  # LATIN CAPITAL LETTER E WITH ACUTE     */\n    0xE6    ,       /*  0x00CA  # LATIN CAPITAL LETTER E WITH CIRCUMFLEX        */\n    0xE8    ,       /*  0x00CB  # LATIN CAPITAL LETTER E WITH DIAERESIS     */\n    0xED    ,       /*  0x00CC  # LATIN CAPITAL LETTER I WITH GRAVE     */\n    0xEA    ,       /*  0x00CD  # LATIN CAPITAL LETTER I WITH ACUTE     */\n    0xEB    ,       /*  0x00CE  # LATIN CAPITAL LETTER I WITH CIRCUMFLEX        */\n    0xEC    ,       /*  0x00CF  # LATIN CAPITAL LETTER I WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0x84    ,       /*  0x00D1  # LATIN CAPITAL LETTER N WITH TILDE     */\n    0xF1    ,       /*  0x00D2  # LATIN CAPITAL LETTER O WITH GRAVE     */\n    0xEE    ,       /*  0x00D3  # LATIN CAPITAL LETTER O WITH ACUTE     */\n    0xEF    ,       /*  0x00D4  # LATIN CAPITAL LETTER O WITH CIRCUMFLEX        */\n    0xCD    ,       /*  0x00D5  # LATIN CAPITAL LETTER O WITH TILDE     */\n    0x85    ,       /*  0x00D6  # LATIN CAPITAL LETTER O WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xAF    ,       /*  0x00D8  # LATIN CAPITAL LETTER O WITH STROKE        */\n    0xF4    ,       /*  0x00D9  # LATIN CAPITAL LETTER U WITH GRAVE     */\n    0xF2    ,       /*  0x00DA  # LATIN CAPITAL LETTER U WITH ACUTE     */\n    0xF3    ,       /*  0x00DB  # LATIN CAPITAL LETTER U WITH CIRCUMFLEX        */\n    0x86    ,       /*  0x00DC  # LATIN CAPITAL LETTER U WITH DIAERESIS     */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA7    ,       /*  0x00DF  # LATIN SMALL LETTER SHARP S        */\n    0x88    ,       /*  0x00E0  # LATIN SMALL LETTER A WITH GRAVE       */\n    0x87    ,       /*  0x00E1  # LATIN SMALL LETTER A WITH ACUTE       */\n    0x89    ,       /*  0x00E2  # LATIN SMALL LETTER A WITH CIRCUMFLEX      */\n    0x8B    ,       /*  0x00E3  # LATIN SMALL LETTER A WITH TILDE       */\n    0x8A    ,       /*  0x00E4  # LATIN SMALL LETTER A WITH DIAERESIS       */\n    0x8C    ,       /*  0x00E5  # LATIN SMALL LETTER A WITH RING ABOVE      */\n    0xBE    ,       /*  0x00E6  # LATIN SMALL LETTER AE     */\n    0x8D    ,       /*  0x00E7  # LATIN SMALL LETTER C WITH CEDILLA     */\n    0x8F    ,       /*  0x00E8  # LATIN SMALL LETTER E WITH GRAVE       */\n    0x8E    ,       /*  0x00E9  # LATIN SMALL LETTER E WITH ACUTE       */\n    0x90    ,       /*  0x00EA  # LATIN SMALL LETTER E WITH CIRCUMFLEX      */\n    0x91    ,       /*  0x00EB  # LATIN SMALL LETTER E WITH DIAERESIS       */\n    0x93    ,       /*  0x00EC  # LATIN SMALL LETTER I WITH GRAVE       */\n    0x92    ,       /*  0x00ED  # LATIN SMALL LETTER I WITH ACUTE       */\n    0x94    ,       /*  0x00EE  # LATIN SMALL LETTER I WITH CIRCUMFLEX      */\n    0x95    ,       /*  0x00EF  # LATIN SMALL LETTER I WITH DIAERESIS       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0x96    ,       /*  0x00F1  # LATIN SMALL LETTER N WITH TILDE       */\n    0x98    ,       /*  0x00F2  # LATIN SMALL LETTER O WITH GRAVE       */\n    0x97    ,       /*  0x00F3  # LATIN SMALL LETTER O WITH ACUTE       */\n    0x99    ,       /*  0x00F4  # LATIN SMALL LETTER O WITH CIRCUMFLEX      */\n    0x9B    ,       /*  0x00F5  # LATIN SMALL LETTER O WITH TILDE       */\n    0x9A    ,       /*  0x00F6  # LATIN SMALL LETTER O WITH DIAERESIS       */\n    0xD6    ,       /*  0x00F7  # DIVISION SIGN     */\n    0xBF    ,       /*  0x00F8  # LATIN SMALL LETTER O WITH STROKE      */\n    0x9D    ,       /*  0x00F9  # LATIN SMALL LETTER U WITH GRAVE       */\n    0x9C    ,       /*  0x00FA  # LATIN SMALL LETTER U WITH ACUTE       */\n    0x9E    ,       /*  0x00FB  # LATIN SMALL LETTER U WITH CIRCUMFLEX      */\n    0x9F    ,       /*  0x00FC  # LATIN SMALL LETTER U WITH DIAERESIS       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xA5    ,       /*  0x2022  # ***  BULLET       */\n    0xD8            /*  0x00FF  # LATIN SMALL LETTER Y WITH DIAERESIS       */\n };\n\n\n/*\n\nThe following characters has no equivalent\nto each other:\n\nMacCodes\n164 0xA4    0x00A7  # SECTION SIGN\n253 0xFD    0x02DD  # DOUBLE ACUTE ACCENT\n189 0xBD    0x03A9  # GREEK CAPITAL LETTER OMEGA\n185 0xB9    0x03C0  # GREEK SMALL LETTER PI\n255 0xFF    0x02C7  # CARON\n249 0xF9    0x02D8  # BREVE\n250 0xFA    0x02D9  # DOT ABOVE\n251 0xFB    0x02DA  # RING ABOVE\n254 0xFE    0x02DB  # OGONEK\n218 0xDA    0x2044  # FRACTION SLASH\n182 0xB6    0x2202  # PARTIAL DIFFERENTIAL\n198 0xC6    0x2206  # INCREMENT\n184 0xB8    0x220F  # N-ARY PRODUCT\n183 0xB7    0x2211  # N-ARY SUMMATION\n195 0xC3    0x221A  # SQUARE ROOT\n176 0xB0    0x221E  # INFINITY\n186 0xBA    0x222B  # INTEGRAL\n197 0xC5    0x2248  # ALMOST EQUAL TO\n173 0xAD    0x2260  # NOT EQUAL TO\n178 0xB2    0x2264  # LESS-THAN OR EQUAL TO\n179 0xB3    0x2265  # GREATER-THAN OR EQUAL TO\n215 0xD7    0x25CA  # LOZENGE\n240 0xF0    0xF8FF  # Apple logo\n222 0xDE    0xFB01  # LATIN SMALL LIGATURE FI\n223 0xDF    0xFB02  # LATIN SMALL LIGATURE FL\n245 0xF5    0x0131  # LATIN SMALL LETTER DOTLESS I\n206 0xCE    0x0152  # LATIN CAPITAL LIGATURE OE\n207 0xCF    0x0153  # LATIN SMALL LIGATURE OE\n\nWinCodes\n129 0x81            #UNDEFINED\n141 0x8D            #UNDEFINED\n143 0x8F            #UNDEFINED\n144 0x90            #UNDEFINED\n157 0x9D            #UNDEFINED\n167 0xA7    0x00A7  #SECTION SIGN\n173 0xAD    0x00AD  #SOFT HYPHEN\n178 0xB2    0x00B2  #SUPERSCRIPT TWO\n179 0xB3    0x00B3  #SUPERSCRIPT THREE\n185 0xB9    0x00B9  #SUPERSCRIPT ONE\n188 0xBC    0x00BC  #VULGAR FRACTION ONE QUARTER\n189 0xBD    0x00BD  #VULGAR FRACTION ONE HALF\n190 0xBE    0x00BE  #VULGAR FRACTION THREE QUARTERS\n208 0xD0    0x00D0  #LATIN CAPITAL LETTER ETH\n215 0xD7    0x00D7  #MULTIPLICATION SIGN\n221 0xDD    0x00DD  #LATIN CAPITAL LETTER Y WITH ACUTE\n222 0xDE    0x00DE  #LATIN CAPITAL LETTER THORN\n240 0xF0    0x00F0  #LATIN SMALL LETTER ETH\n253 0xFD    0x00FD  #LATIN SMALL LETTER Y WITH ACUTE\n254 0xFE    0x00FE  #LATIN SMALL LETTER THORN\n140 0x8C    0x0152  #LATIN CAPITAL LIGATURE OE\n156 0x9C    0x0153  #LATIN SMALL LIGATURE OE\n138 0x8A    0x0160  #LATIN CAPITAL LETTER S WITH CARON\n154 0x9A    0x0161  #LATIN SMALL LETTER S WITH CARON\n142 0x8E    0x017D  #LATIN CAPITAL LETTER Z WITH CARON\n158 0x9E    0x017E  #LATIN SMALL LETTER Z WITH CARON\n128 0x80    0x20AC  #EURO SIGN\n166 0xA6    0x00A6  #BROKEN BAR\n\n\n*/\n\n\n\n\n#endif /* !__macos_charmap_h */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/extrafld.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  extrafld.c\n\n  contains functions to build extra-fields.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <sound.h>\n#include \"zip.h\"\n#include \"unixlike.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'MAC3' extra field to the zlist data pointed to by z.            */\n/* This is the (new) Info-zip extra block for Macintosh */\n#define EB_MAC3_HLEN          14    /* fixed length part of MAC3's header */\n#define EB_L_MAC3_FINFO_LEN   52    /* fixed part of MAC3 compressible data */\n\n#define EB_MAX_OF_VARDATA   1300    /* max possible datasize */\n\n#define EB_L_MAC3_SIZE    (EB_HEADSIZE + EB_MAC3_HLEN)\n#define EB_C_MAC3_SIZE    (EB_HEADSIZE + EB_MAC3_HLEN)\n\n/* maximum memcompress overhead is the sum of the compression header length */\n/* (6 = ush compression type, ulg CRC) and the worstcase deflate overhead   */\n/* when uncompressible data are kept in 2 \"stored\" blocks (5 per block =    */\n/* byte blocktype + 2 * ush blocklength) */\n#define MEMCOMPRESS_OVERHEAD    (EB_MEMCMPR_HSIZ + EB_DEFLAT_EXTRA)\n\n#define EB_M3_FL_COMPRESS   0x00\n#define EB_M3_FL_DATFRK     0x01    /* data is data-fork */\n#define EB_M3_FL_NOCHANGE   0x02    /* filename will be not changed */\n#define EB_M3_FL_UNCMPR     0x04    /* data is 'natural' (not compressed) */\n#define EB_M3_FL_TIME64     0x08    /* time is coded in 64 bit */\n#define EB_M3_FL_NOUTC      0x10    /* only 'local' time-stamps are stored */\n\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))\n#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n\n/* disable compressing of extra field\n#define MAC_EXTRAFLD_UNCMPR       */\n\n/* ---------------------------------------------------------------------- */\n/* Add a 'JLEE' extra field to the zlist data pointed to by z.            */\n/* This is the (old) Info-zip resource-fork extra block for Macintosh\n(last Revision 1996-09-22) Layout made by Johnny Lee, Code made by me :-)  */\n#define EB_L_JLEE_LEN  40       /* fixed length of JLEE's header */\n#define EB_C_JLEE_LEN  40       /* fixed length of JLEE's header */\n\n#define EB_L_JLEE_SIZE    (EB_HEADSIZE + EB_L_JLEE_LEN)\n#define EB_C_JLEE_SIZE    (EB_HEADSIZE + EB_C_JLEE_LEN)\n\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nextern MacZipGlobals    MacZip;\nextern unsigned long count_of_Zippedfiles;\n\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nstatic int add_UT_ef(struct zlist far *z, iztimes *z_utim);\nstatic int add_JLEE_ef(struct zlist far *z);  /* old mac extra field */\nstatic int add_MAC3_ef(struct zlist far *z);  /* new mac extra field */\n\nstatic void make_extrafield_JLEE(char *l_ef);\nstatic unsigned make_extrafield_MAC3(char *ef);\nstatic char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,\n                               unsigned flag);\n\nstatic void print_extra_info(void);\nvoid UserStop(void);\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/*\n* Set the extra-field's for each compressed file\n*/\nint set_extra_field(struct zlist far *z, iztimes *z_utim)\n  /* store full data in local header but just modification time stamp info\n     in central header */\n{\n    int retval;\n\n    Assert_it(z, \"set_extra_field\",\"\")\n    Assert_it(z_utim, \"set_extra_field\",\"\")\n\n    z_utim = z_utim;\n\n    /* Check to make sure z is valid. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    /* Resource forks are always binary */\n    if (MacZip.CurrentFork == ResourceFork) z->att = BINARY;\n\n    if (noisy)\n        {\n        count_of_Zippedfiles++;\n        InformProgress(MacZip.RawCountOfItems, count_of_Zippedfiles );\n        }\n\n    /*\n    PrintFileInfo();\n    */\n    switch (MacZip.MacZipMode)\n        {\n        case JohnnyLee_EF:\n            {\n            retval = add_JLEE_ef( z );\n            if (retval != ZE_OK) return retval;\n            break;\n            }\n        case NewZipMode_EF:\n            {     /*  */\n#ifdef USE_EF_UT_TIME\n            retval = add_UT_ef(z, z_utim);\n            if (retval != ZE_OK) return retval;\n#endif\n\n            retval = add_MAC3_ef( z );\n            if (retval != ZE_OK) return retval;\n            break;\n            }\n        default:\n            {\n            printerr(\"Unknown Extrafieldmode\", -1, -1, __LINE__, __FILE__, \"\");\n            return ZE_LOGIC;  /* function should never reach this point */\n            }\n    }\n\n    /* MacStat information is now outdated and\n       must be refreshed for the next file */\n    MacZip.isMacStatValid = false;\n\n    return ZE_OK;\n}\n\n\n\n\n#ifdef USE_EF_UT_TIME\n/*\n* Build and add the Unix time extra-field. This extra field\n* will be included be default. Johnny Lee's implementation does\n* not use this kind of extra-field.\n* All datas are in Intel (=little-endian) format\n\n Extra field info:\n   - 'UT' - UNIX time extra field\n\n   This is done the same way ../unix/unix.c stores the 'UT'/'Ux' fields\n   (full data in local header, only modification time in central header),\n   with the 'M3' field added to the end and the size of the 'M3' field\n   in the central header.\n */\n\nstatic int add_UT_ef(struct zlist far *z, iztimes *z_utim)\n{\n    char        *l_ef = NULL;\n    char        *c_ef = NULL;\n\n    Assert_it(z, \"add_UT_ef\",\"\")\n\n#ifdef IZ_CHECK_TZ\n    if (!zp_tz_is_valid)\n        return ZE_OK;           /* skip silently if no valid TZ info */\n#endif\n\n    /* We can't work if there's no entry to work on. */\n    if( z == NULL ) {\n        return ZE_LOGIC;\n    }\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + EB_L_UT_SIZE > EF_SIZE_MAX ||\n        z->cext + EB_C_UT_SIZE > EF_SIZE_MAX ) {\n        return ZE_MEM;\n    }\n\n    /* Allocate memory for the local and central extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_UT_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_UT_SIZE );\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_UT_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_UT_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /* Now add the local version of the field. */\n    *l_ef++ = 'U';\n    *l_ef++ = 'T';\n    *l_ef++ = (char)(EB_UT_LEN(2)); /* length of data in local EF */\n    *l_ef++ = (char)0;\n    *l_ef++ = (char)(EB_UT_FL_MTIME | EB_UT_FL_CTIME);\n    *l_ef++ = (char)(z_utim->mtime);\n    *l_ef++ = (char)(z_utim->mtime >> 8);\n    *l_ef++ = (char)(z_utim->mtime >> 16);\n    *l_ef++ = (char)(z_utim->mtime >> 24);\n    *l_ef++ = (char)(z_utim->ctime);\n    *l_ef++ = (char)(z_utim->ctime >> 8);\n    *l_ef++ = (char)(z_utim->ctime >> 16);\n    *l_ef++ = (char)(z_utim->ctime >> 24);\n\n    z->ext += EB_L_UT_SIZE;\n\n    /* Now add the central version. */\n    memcpy(c_ef, l_ef-EB_L_UT_SIZE, EB_C_UT_SIZE);\n    c_ef[EB_LEN] = (char)(EB_UT_LEN(1)); /* length of data in central EF */\n\n    z->cext += EB_C_UT_SIZE;\n\n    return ZE_OK;\n}\n#endif /* USE_EF_UT_TIME */\n\n\n/*\n* Build and add the old 'Johnny Lee' Mac extra field\n* All native datas are in Motorola (=big-endian) format\n*/\n\nstatic int add_JLEE_ef( struct zlist far *z )\n{\n    char *l_ef       = NULL;\n    char *c_ef       = NULL;\n\n    Assert_it(z, \"add_JLEE_ef\",\"\")\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if ( z->ext + EB_L_JLEE_SIZE > EF_SIZE_MAX ||\n         z->cext + EB_C_JLEE_SIZE > EF_SIZE_MAX ) {\n        return ZE_MEM;\n    }\n\n\n    /* Allocate memory for the local extra fields. */\n    if ( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext + EB_L_JLEE_SIZE );\n    } else {\n        l_ef = (char *)malloc( EB_L_JLEE_SIZE );\n        z->ext = 0;\n    }\n    if ( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    /* Allocate memory for the  central extra fields. */\n    if ( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_JLEE_SIZE );\n    } else {\n        c_ef = (char *)malloc( EB_C_JLEE_SIZE );\n        z->cext = 0;\n    }\n    if ( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n\n    if ( verbose ) {\n        print_extra_info();\n    }\n\n\n    /**\n    **\n    **  Now add the local version of the field.\n    **/\n    make_extrafield_JLEE(l_ef);\n    z->ext += EB_L_JLEE_SIZE;\n\n\n    /**\n    **\n    **  Now add the central version of the field.\n    **  It's identical to the local header. I wonder why ??\n    *  the first two fields are in Intel little-endian format  */\n    make_extrafield_JLEE(c_ef);\n    z->cext += EB_C_JLEE_SIZE;\n\n    return ZE_OK;\n}\n\n\n\n/*\n* This is an implementation of Johnny Lee's extra field.\n* I never saw Johnny Lee's code. My code is based on the extra-field\n* definition mac (see latest appnote 1997-03-11)\n* and on some experiments with Johnny Lee's Zip-app version 1.0, 1992\n*\n* Unfortunately I cannot agree with his extra-field layout.\n*   - it wasted space\n*   - and holds not all mac-specific information\n*\n* I coded this extra-field only for testing purposes.\n* I don't want support this extra-field. Please use my implementation.\n*\n* This is old implementation of Johnny Lee's extra field.\n* All native datas are in Motorola (=big-endian) format\n*/\n\nstatic void make_extrafield_JLEE(char *ef)\n{\n\n    Assert_it(ef, \"make_extrafield_JLEE\",\"\")\n\n    if (MacZip.isMacStatValid == false)\n        {\n        fprintf(stderr,\"Internal Logic Error: [%d/%s] MacStat is out of sync !\",\n                        __LINE__,__FILE__);\n        exit(-1);\n        }\n\n\n    /*  the first two fields are in Intel little-endian format  */\n    *ef++ = 0xC8;                             /* tag for this extra block */\n    *ef++ = 0x07;\n\n    *ef++ = (char)(EB_L_JLEE_LEN);            /* total data size this block */\n    *ef++ = (char)((EB_L_JLEE_LEN) >> 8);\n\n     /*  the following fields are in motorola big-endian format  */\n        *ef++ = 'J';                /* extra field signature:       4 Bytes */\n        *ef++ = 'L';                /* the old style extra field */\n        *ef++ = 'E';\n        *ef++ = 'E';\n\n                /* Start Macintosh Finder FInfo structure   16 Bytes overall */\n                                    /* Type:                        4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);\n\n                                    /* Creator:                     4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);\n\n                                     /* file Finder Flags:                2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);\n\n                                     /* Finders Icon position of a file*/\n                                     /* V/Y-Position:                2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);\n                                     /* H/X-Position:                2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);\n\n                               /* fdFldr Folder containing file    2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);\n                /* End Macintosh Finder FInfo structure */\n\n\n                                                  /* Creation-time  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);\n\n                                              /* Modification-time  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);\n\n                                     /* info Bits                    4 Bytes */\n    *ef++ = 0x00;\n    *ef++ = 0x00;\n    *ef++ = 0x00;\n    if (MacZip.DataForkOnly)\n        {          /* don't convert filename for unzipping */\n                   /* 0x01 = data-fork; 0x00 = resource-fork */\n        *ef++ = (char) (MacZip.CurrentFork == DataFork) | 2;\n        }\n    else\n        {\n        *ef++ = (char) (MacZip.CurrentFork == DataFork);\n        }\n\n                                  /* file's location folder ID  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlParID);\n                                                          /* ============  */\n                                                          /*     40 Bytes  */\n}\n\n\n\n/*\n* Build and add the new mac extra field\n* All native data are stored in Intel (=little-endian) format\n*/\n\nstatic int add_MAC3_ef( struct zlist far *z )\n{\n    char *l_ef        = NULL;\n    char *c_ef        = NULL;\n    char *attrbuff    = NULL;\n    off_t attrsize    = (EB_L_MAC3_FINFO_LEN + EB_MAX_OF_VARDATA);\n    char *compbuff    = NULL;\n    unsigned compsize = 0;\n    unsigned m3_compr;\n    Boolean compress_data = true;\n\n    Assert_it(z, \"add_MAC3_ef\",\"\")\n\n    UserStop();  /* do event handling and let the user stop */\n\n    if( verbose ) {\n        print_extra_info();\n    }\n\n    /* allocate temporary buffer to collect the Mac extra field info */\n    attrbuff = (char *)malloc( (size_t)attrsize );\n    if( attrbuff == NULL ) {\n        return ZE_MEM;\n    }\n\n    /* fill the attribute buffer, to get its (uncompressed) size */\n    attrsize = make_extrafield_MAC3(attrbuff);\n\n    if (compress_data &&\n        ((compbuff = (char *)malloc((size_t)attrsize + MEMCOMPRESS_OVERHEAD))\n         != NULL))\n        {\n        /* Try compressing the data */\n        compsize = memcompress( compbuff,\n                                (size_t)attrsize + MEMCOMPRESS_OVERHEAD,\n                                attrbuff,\n                                (size_t)attrsize );\n#ifdef MAC_EXTRAFLD_UNCMPR\n        compsize = attrsize;\n#endif\n        }\n    else\n        {\n        compsize = attrsize;\n        }\n\n    if ((compsize) < attrsize) {\n        /* compression gained some space ... */\n        free(attrbuff);         /* no longer needed ... */\n        m3_compr = EB_M3_FL_COMPRESS;\n    } else {\n        /* compression does not help, store data in uncompressed mode */\n        if (compbuff != NULL) free(compbuff);\n        compbuff = attrbuff;\n        compsize = attrsize;\n        m3_compr = EB_M3_FL_UNCMPR;\n    }\n\n    /* Check to make sure we've got enough room in the extra fields. */\n    if( z->ext + (EB_L_MAC3_SIZE + compsize) > EF_SIZE_MAX ||\n        z->cext + EB_C_MAC3_SIZE > EF_SIZE_MAX ) {\n        if (compbuff != NULL) free(compbuff);\n        return ZE_MEM;\n    }\n\n    /* Allocate memory for the local extra fields. */\n    if( z->extra && z->ext != 0 ) {\n        l_ef = (char *)realloc( z->extra, z->ext +\n                                EB_L_MAC3_SIZE + compsize);\n    } else {\n        l_ef = (char *)malloc( EB_L_MAC3_SIZE + compsize);\n        z->ext = 0;\n    }\n    if( l_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->extra = l_ef;\n    l_ef += z->ext;\n\n    /* Allocate memory for the  central extra fields. */\n    if( z->cextra && z->cext != 0 ) {\n        c_ef = (char *)realloc( z->cextra, z->cext + EB_C_MAC3_SIZE);\n    } else {\n        c_ef = (char *)malloc( EB_C_MAC3_SIZE );\n        z->cext = 0;\n    }\n    if( c_ef == NULL ) {\n        return ZE_MEM;\n    }\n    z->cextra = c_ef;\n    c_ef += z->cext;\n\n    /**\n    **  Now add the local version of the field.\n    **/\n    l_ef = make_EF_Head_MAC3(l_ef, compsize, (ulg)attrsize, m3_compr);\n    memcpy(l_ef, compbuff, (size_t)compsize);\n    l_ef += compsize;\n    z->ext += EB_L_MAC3_SIZE + compsize;\n    free(compbuff);\n    /* And the central version. */\n    c_ef = make_EF_Head_MAC3(c_ef, 0, (ulg)attrsize, m3_compr);\n    z->cext += EB_C_MAC3_SIZE;\n\n    return ZE_OK;\n}\n\n\n\n\n/*\n* Build the new mac local extra field header.\n* It's identical with the central extra field.\n* All native data are in Intel (=little-endian) format\n*/\nstatic char *make_EF_Head_MAC3(char *ef, unsigned compsize, ulg attrsize,\n                               unsigned flag)\n{\n    unsigned info_flag = flag;\n\n    Assert_it(ef, \"make_EF_Head_MAC3\",\"\")\n\n    /*  the first four fields are in Intel little-endian format  */\n    *ef++ = 'M';         /* tag for this extra block               2 Bytes */\n    *ef++ = '3';\n\n                                  /* total data size this block    2 Bytes */\n    *ef++ = (char) (EB_MAC3_HLEN + compsize);\n    *ef++ = (char)((EB_MAC3_HLEN + compsize) >> 8);\n\n    *ef++ = (char)(attrsize);\n    *ef++ = (char)(attrsize >> 8);\n    *ef++ = (char)(attrsize >> 16);\n    *ef++ = (char)(attrsize >> 24);\n\n                                   /* info Bits  (flags)           2 Bytes */\n\n    if (MacZip.DataForkOnly)            info_flag |= (EB_M3_FL_DATFRK |\n                                                      EB_M3_FL_NOCHANGE);\n    if (MacZip.CurrentFork == DataFork) info_flag |= EB_M3_FL_DATFRK;\n    if (!MacZip.HaveGMToffset)          info_flag |= EB_M3_FL_NOUTC;\n\n    *ef++ = (char)info_flag;\n    *ef++ = (char)0x00;            /* reserved at the moment */\n\n /* Note: Apple defined File-Type/-Creator as OSType ( =unsigned long,\n          see Universal Headers 3.1). However, File-Type/-Creator are a\n          unique four-character sequence. Therefore the byteorder of the\n          File-Type/-Creator are NOT changed. The native format is used.  */\n\n                                                       /* Type:    4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);\n\n                                                       /* Creator: 4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);\n\n    return ef;\n}\n\n\n\n\n\n/*\n* Build the new mac local extra field header.\n* All native data are in Intel (=little-endian) format\n*/\nunsigned make_extrafield_MAC3(char *ef)\n{\n    char *ef_m3_begin = ef;\n    char *temp_Pathname;\n    char tmp_buffer[NAME_MAX];\n    unsigned char comment[257];\n    unsigned short FLength = 0;\n    unsigned short CLength = 0;\n    short   tempFork;\n    OSErr       err;\n\n    Assert_it(ef, \"make_extrafield_MAC3\",\"\")\n\n    if (MacZip.isMacStatValid == false)\n    {\n        fprintf(stderr,\n                \"Internal Logic Error: [%d/%s] MacStat is out of sync !\",\n                __LINE__, __FILE__);\n        exit(-1);\n    }\n\n    /* Start Macintosh Finder FInfo structure except Type/Creator\n       (see make_EF_Head_MAC3()) 8 Bytes overall */\n\n                                             /* file Finder Flags: 2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags >> 8);\n\n                                    /* Finders Icon position of a file*/\n                                   /* V/Y-Position:                2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v >> 8);\n\n                                   /* H/X-Position:                2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h >> 8);\n\n                               /* fdFldr Folder containing file    2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFldr >> 8);\n\n                /* End Macintosh Finder FInfo structure */\n\n                                                    /*    8 Bytes so far ... */\n\n                /* Start Macintosh Finder FXInfo structure  16 Bytes overall */\n                                                    /* Icon ID:    2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdIconID >> 8);\n\n                                                        /* unused: 6 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0]);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[0] >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1]);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[1] >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2]);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdUnused[2] >> 8);\n                                                   /* Script flag: 1 Byte */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdScript);\n                                                /* More flag bits: 1 Byte */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdXFlags);\n                                                /* Comment ID      2 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdComment >> 8);\n\n                                                   /* Home Dir ID: 4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlXFndrInfo.fdPutAway >> 24);\n                /* End Macintosh Finder FXInfo structure */\n\n                                                    /*   24 Bytes so far ... */\n\n                                            /* file version number 1 Byte */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFVersNum);\n\n                                        /* directory access rights 1 Byte */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioACUser);\n\n                                                 /* Creation-time  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat  >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlCrDat >> 24);\n                                             /* Modification-time  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlMdDat >> 24);\n                                                   /* Backup-time  4 Bytes */\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 8);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 16);\n    *ef++ = (char)(MacZip.fpb.hFileInfo.ioFlBkDat >> 24);\n\n                                                    /*   38 Bytes so far ... */\n#ifdef USE_EF_UT_TIME\n    if (MacZip.HaveGMToffset) {\n                                              /* GMT-Offset times  12 Bytes */\n        *ef++ = (char)(MacZip.Cr_UTCoffs);\n        *ef++ = (char)(MacZip.Cr_UTCoffs >> 8);\n        *ef++ = (char)(MacZip.Cr_UTCoffs >> 16);\n        *ef++ = (char)(MacZip.Cr_UTCoffs >> 24);\n        *ef++ = (char)(MacZip.Md_UTCoffs);\n        *ef++ = (char)(MacZip.Md_UTCoffs >> 8);\n        *ef++ = (char)(MacZip.Md_UTCoffs >> 16);\n        *ef++ = (char)(MacZip.Md_UTCoffs >> 24);\n        *ef++ = (char)(MacZip.Bk_UTCoffs);\n        *ef++ = (char)(MacZip.Bk_UTCoffs >> 8);\n        *ef++ = (char)(MacZip.Bk_UTCoffs >> 16);\n        *ef++ = (char)(MacZip.Bk_UTCoffs >> 24);\n    }\n                                                    /*   50 Bytes so far ... */\n#endif\n\n                                  /* Text Encoding Base (charset)  2 Bytes */\n    *ef++ = (char)(MacZip.CurrTextEncodingBase);\n    *ef++ = (char)(MacZip.CurrTextEncodingBase >> 8);\n                                                    /*   52 Bytes so far ... */\n\n    /* MacZip.CurrentFork will be changed, so we have to save it  */\n    tempFork = MacZip.CurrentFork;\n    if (!MacZip.StoreFullPath)  {\n        temp_Pathname = StripPartialDir(tmp_buffer, MacZip.SearchDir,\n                                        MacZip.FullPath);\n    } else {\n        temp_Pathname = MacZip.FullPath;\n    }\n    MacZip.CurrentFork = tempFork;\n\n    FLength = strlen(temp_Pathname) + 1;\n    memcpy( ef, temp_Pathname, (size_t)FLength );\n    ef += FLength;          /* make room for the string -  variable length */\n\n    err = FSpLocationFromFullPath(strlen(MacZip.FullPath), MacZip.FullPath,\n                                  &MacZip.fileSpec);\n    printerr(\"FSpLocationFromFullPath:\", err, err,\n             __LINE__, __FILE__, tmp_buffer);\n\n    err = FSpDTGetComment(&MacZip.fileSpec, comment);\n    printerr(\"FSpDTGetComment:\", (err != -5012) && (err != 0), err,\n             __LINE__, __FILE__, \"\");\n    PToCCpy(comment,tmp_buffer);\n\n    CLength = strlen(tmp_buffer) + 1;\n    memcpy( ef, tmp_buffer, (size_t)CLength );\n    ef += CLength;          /* make room for the string -  variable length */\n\n    if (verbose) printf(\"\\n comment: [%s]\", tmp_buffer);\n\n    return (unsigned)(ef - ef_m3_begin);\n}\n\n\n\n\n\n\n/*\n* Print all native data of the new mac local extra field.\n* It's for debugging purposes and disabled by default.\n*/\n\nstatic void PrintFileInfo(void)\n{\nDateTimeRec  MacTime;\n\nprintf(\"\\n\\n---------------------------------------------\"\\\n       \"----------------------------------\");\nprintf(\"\\n FullPath Name =                   [%s]\",  MacZip.FullPath);\nprintf(\"\\n File Attributes =                  %s  0x%x  %d\",\n          sBit2Str(MacZip.fpb.hFileInfo.ioFlAttrib),\n          MacZip.fpb.hFileInfo.ioFlAttrib,\n          MacZip.fpb.hFileInfo.ioFlAttrib);\nprintf(\"\\n Enclosing Folder ID# =             0x%x  %d\",\n          MacZip.fpb.hFileInfo.ioFlParID,\n          MacZip.fpb.hFileInfo.ioFlParID);\n\nif (!MacZip.isDirectory)\n{\nprintf(\"\\n File Type =                        [%c%c%c%c]  0x%lx\",\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType);\n\nprintf(\"\\n File Creator =                     [%c%c%c%c]  0x%lx\",\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);\n\nprintf(\"\\n Data Fork :\" );\nprintf(\"\\n    Actual (Logical) Length =       %d  0x%x \",\n              MacZip.fpb.hFileInfo.ioFlLgLen,\n              MacZip.fpb.hFileInfo.ioFlLgLen);\nprintf(\"\\n    Allocated (Physical) Length =   %d  0x%x\",\n              MacZip.fpb.hFileInfo.ioFlPyLen,\n              MacZip.fpb.hFileInfo.ioFlPyLen);\nprintf(\"\\n Resource Fork :\" );\nprintf(\"\\n    Actual (Logical) Length =       %d  0x%x\",\n              MacZip.fpb.hFileInfo.ioFlRLgLen,\n              MacZip.fpb.hFileInfo.ioFlRLgLen );\nprintf(\"\\n    Allocated (Physical) Length =   %d  0x%x\",\n              MacZip.fpb.hFileInfo.ioFlRPyLen,\n              MacZip.fpb.hFileInfo.ioFlRPyLen );\n}\n\nprintf(\"\\n Dates :               \");\n\nSecondsToDate (MacZip.CreatDate, &MacTime);\nprintf(\"\\n    Created  =                       %4d/%2d/%2d %2d:%2d:%2d  \",\n    MacTime.year,\n    MacTime.month,\n    MacTime.day,\n    MacTime.hour,\n    MacTime.minute,\n    MacTime.second);\n\nSecondsToDate (MacZip.BackDate, &MacTime);\nprintf(\"\\n    Backup   =                       %4d/%2d/%2d %2d:%2d:%2d  \",\n    MacTime.year,\n    MacTime.month,\n    MacTime.day,\n    MacTime.hour,\n    MacTime.minute,\n    MacTime.second);\n\nSecondsToDate (MacZip.ModDate, &MacTime);\nprintf(\"\\n    Modified =                       %4d/%2d/%2d %2d:%2d:%2d  \",\n    MacTime.year,\n    MacTime.month,\n    MacTime.day,\n    MacTime.hour,\n    MacTime.minute,\n    MacTime.second);\n\nif (!MacZip.isDirectory)\n{\nprintf(\"\\n Finder Flags :                     %s  0x%x  %d\",\n          sBit2Str(MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags),\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags,\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags);\nprintf(\"\\n Finder Icon Position =          X: %d  0x%x \",\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h,\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.h);\nprintf(\"\\n                                  Y: %d  0x%x \",\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v,\n          MacZip.fpb.hFileInfo.ioFlFndrInfo.fdLocation.v);\n}\nelse\n{\nprintf(\"\\n Finder Flags :                     %s  0x%x  %d\",\n          sBit2Str(MacZip.fpb.dirInfo.ioDrUsrWds.frFlags),\n          MacZip.fpb.dirInfo.ioDrUsrWds.frFlags,\n          MacZip.fpb.dirInfo.ioDrUsrWds.frFlags);\nprintf(\"\\n Finder Icon Position =          X: %d  0x%x \",\n          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h,\n          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.h);\nprintf(\"\\n                                  Y: %d  0x%x \",\n          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v,\n          MacZip.fpb.dirInfo.ioDrUsrWds.frLocation.v);\n}\n\nprintf(\"\\n----------------------------------------------------\"\\\n        \"---------------------------\\n\");\n}\n\n\n\n/*\n* If the switch '-v' is used, print some more info.\n*/\n\nstatic void print_extra_info(void)\n{\nchar Fork[20];\n\nif (MacZip.CurrentFork == DataFork) sstrcpy(Fork,\"<DataFork>\");\nelse  sstrcpy(Fork,\"<ResourceFork>\");\n\nprintf(\"\\n%16s [%c%c%c%c]  [%c%c%c%c]\",Fork,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 24,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 16,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType >> 8,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType,\n\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 24,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 16,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator >> 8,\n    MacZip.fpb.hFileInfo.ioFlFndrInfo.fdCreator);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/getenv.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n\nThis file implements the getenv() function.\n\n#  Background:\n#  Under Unix: Each Process (= running Program) has a set of\n#  associated variables. The variables are called enviroment\n#  variables and, together, constitute the process environment.\n#  These variables include the search path, the terminal type,\n#  and the user's login name.\n\n#  Unfortunatelly the MacOS has no equivalent. So we need\n#  a file to define the environment variables.\n#  Name of this file is \"MacZip.Env\". It can be placed\n#  in the current folder of MacZip or in the\n#  preference folder of the system disk.\n#  If MacZip founds the \"MacZip.Env\" file in the current\n#  the folder of MacZip the \"MacZip.Env\" file in the\n#  preference folder will be ignored.\n\n#  An environment variable has a name and a value:\n#  Name=Value\n#  Note: Spaces are significant:\n#  ZIPOPT=-r  and\n#  ZIPOPT = -r are different !!!\n\n\n */\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <time.h>\n#include <unix.h>\n#include <Files.h>\n#include <Folders.h>\n\n#include \"pathname.h\"\n#include \"helpers.h\"\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\nstatic char ListAllKeyValues = 0;\nstatic unsigned LineNumber   = 0;\nstatic char CompletePath[NAME_MAX];\nBoolean IgnoreEnvironment    = false;  /* used by dialog.c and initfunc.c\n                                          of the Mainapp */\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\ntypedef struct _EnviromentPair {\n    char *key;\n    char *value;\n} EnviromentPair;\n\n\n#define MAX_COMMAND 1024\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\n\nint get_char(FILE *file);\nvoid unget_char(int ch,FILE *file);\nint get_string(char *string,int size, FILE *file, char *terms);\nvoid skip_comments(FILE *file);\nchar *load_entry(FILE *file);\nchar *getenv(const char *name);\nEnviromentPair *ParseLine(char *line);\nOSErr FSpFindFolder_Name(short vRefNum, OSType folderType,\n                         Boolean createFolder,FSSpec *spec, unsigned char *name);\nFILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);\nvoid ShowAllKeyValues(void);\nvoid Set_LineNum(unsigned ln);\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/* get_string(str, max, file, termstr) : like fgets() but\n *      (1) has terminator string which should include \\n\n *      (2) will always leave room for the null\n *      (3) uses get_char() so LineNumber will be accurate\n *      (4) returns EOF or terminating character, whichever\n */\nint get_string(char *string, int size, FILE *file, char *terms)\n{\n    int ch;\n\n    while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {\n        if (size > 1) {\n            *string++ = (char) ch;\n            size--;\n        }\n    }\n\n    if (size > 0)\n        {\n        *string = '\\0';\n        }\n\n    return ch;\n}\n\n\n\n\nvoid Set_LineNum(unsigned ln)\n{\n LineNumber = ln;\n}\n\n\n\n/* get_char(file) : like getc() but increment LineNumber on newlines\n */\nint get_char(FILE *file)\n{\n    int ch;\n\n    ch = getc(file);\n    if (ch == '\\n')\n        {\n        Set_LineNum(LineNumber + 1);\n        }\n\n    return ch;\n}\n\n\n\n\n/* skip_comments(file) : read past comment (if any)\n */\nvoid skip_comments(FILE *file)\n{\n    int ch;\n\n    while (EOF != (ch = get_char(file)))\n        {\n        /* ch is now the first character of a line.\n         */\n\n        while (ch == ' ' || ch == '\\t')\n            {\n            ch = get_char(file);\n            }\n\n        if (ch == EOF)\n            {\n            break;\n            }\n\n        /* ch is now the first non-blank character of a line.\n         */\n\n        if (ch != '\\n' && ch != '#')\n            {\n            break;\n            }\n\n        /* ch must be a newline or comment as first non-blank\n         * character on a line.\n         */\n\n        while (ch != '\\n' && ch != EOF)\n            {\n            ch = get_char(file);\n            }\n\n        /* ch is now the newline of a line which we're going to\n         * ignore.\n         */\n    }\n\n    if (ch != EOF)\n        {\n        unget_char(ch, file);\n        }\n}\n\n\n\n\n/* unget_char(ch, file) : like ungetc but do LineNumber processing\n */\nvoid unget_char(int ch, FILE *file)\n{\n    ungetc(ch, file);\n    if (ch == '\\n')\n        {\n        Set_LineNum(LineNumber - 1);\n        }\n}\n\n\n/* this function reads one file entry -- the next -- from a file.\n*  it skips any leading blank lines, ignores comments, and returns\n*  NULL if for any reason the entry can't be read and parsed.\n*/\n\nchar *load_entry(FILE *file)\n{\n    int ch;\n    static char cmd[MAX_COMMAND];\n\n    skip_comments(file);\n\n    ch = get_string(cmd, MAX_COMMAND, file, \"\\n\");\n\n    if (ch == EOF)\n        {\n        return NULL;\n        }\n\n    return cmd;\n}\n\n\n\n\n\nEnviromentPair *ParseLine(char *line)\n{\nchar *tmpPtr;\nstatic EnviromentPair *Env;\nunsigned short length = strlen(line);\n\nEnv->key   = \"\";\nEnv->value = \"\";\n\nfor (tmpPtr = line; *tmpPtr; tmpPtr++)\n    {\n    if (*tmpPtr == '=')\n        {\n        *tmpPtr = 0;\n        Env->key = line;\n        if (strlen(Env->key) < length)\n            {\n            Env->value = ++tmpPtr;\n            }\n        return Env;\n        }\n    }\nreturn Env;\n}\n\n\n\n\n\nchar *getenv(const char *name)\n{\nFILE *fp;\nchar *LineStr = NULL;\nEnviromentPair *Env1;\nFSSpec spec;\nOSErr err;\n\nif (IgnoreEnvironment)\n    return NULL;  /* user wants to ignore the environment vars */\n\nif (name == NULL)\n    return NULL;\n\nGetCompletePath(CompletePath,\"MacZip.Env\",&spec,&err);\n\n/* try open the file in the current folder */\nfp = FSp_fopen(&spec,\"r\");\nif (fp == NULL)\n    { /* Okey, lets try open the file in the preference folder */\n    FSpFindFolder_Name(\n                   kOnSystemDisk,\n                   kPreferencesFolderType,\n                   kDontCreateFolder,\n                   &spec,\n                   \"\\pMacZip.Env\");\n    fp = FSp_fopen(&spec,\"r\");\n    if (fp == NULL)\n        {\n        return NULL; /* there is no enviroment-file */\n        }\n    }\n\nLineStr = load_entry(fp);\nwhile (LineStr != NULL)\n    {   /* parse the file line by line */\n    Env1 = ParseLine(LineStr);\n    if (strlen(Env1->value) > 0)\n        {       /* we found a key/value pair */\n        if (ListAllKeyValues)\n            printf(\"\\n   Line:%3d   [%s] = [%s]\",LineNumber,Env1->key,Env1->value);\n        if (stricmp(name,Env1->key) == 0)\n            {   /* we found the value of a given key */\n            return Env1->value;\n            }\n        }\n    LineStr = load_entry(fp);  /* read next line */\n    }\nfclose(fp);\n\nreturn NULL;\n}\n\n\n\n\n\nOSErr FSpFindFolder_Name(\n    short vRefNum,          /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec,           /* Pointer to resulting directory. */\n    unsigned char *name)    /* Name of the file in the folder */\n{\n    short foundVRefNum;\n    long foundDirID;\n    OSErr err;\n\n    err = FindFolder(vRefNum, folderType, createFolder,\n                     &foundVRefNum, &foundDirID);\n    if (err != noErr)\n        {\n        return err;\n        }\n\n    err = FSMakeFSSpec(foundVRefNum, foundDirID, name, spec);\n    return err;\n}\n\n\n\n\nvoid ShowAllKeyValues(void)\n{\nOSErr err;\nFSSpec spec;\nBoolean tmpIgnoreEnvironment = IgnoreEnvironment;\n\nListAllKeyValues = 1;\nIgnoreEnvironment = false;\n\nGetCompletePath(CompletePath,\"MacZip.Env\",&spec,&err);\nif (err != 0)\n    { /* Okey, lets try open the file in the preference folder */\n    FSpFindFolder_Name(\n                   kOnSystemDisk,\n                   kPreferencesFolderType,\n                   kDontCreateFolder,\n                   &spec,\n                   \"\\pMacZip.Env\");\n    GetFullPathFromSpec(CompletePath,&spec, &err);\n    if (err != 0)\n        {\n        return; /* there is no enviroment-file */\n        }\n    }\n\nprintf(\"\\nLocation of the current \\\"MacZip.Env\\\" file:\\n [%s]\",CompletePath);\n\nprintf(\"\\n\\nList of all environment variables\\n\");\ngetenv(\" \");\nprintf(\"\\n\\nEnd\\n\\n\");\n\n/* restore used variables */\nListAllKeyValues = 0;\nLineNumber = 0;\nIgnoreEnvironment = tmpIgnoreEnvironment;\n}\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/helpers.c",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  helpers.c\n\n  Some useful functions Used by unzip and zip.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include \"zip.h\"\n#include <ctype.h>\n#include <time.h>\n#include <sound.h>\n\n#include \"macstuff.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\n\nextern int noisy;\nextern char MacPathEnd;\nextern char *zipfile;   /* filename of the Zipfile */\nextern char *tempzip;   /* Temporary zip file name */\nextern ZCONST unsigned char MacRoman_to_WinCP1252[128];\n\n\nstatic char         argStr[1024];\nstatic char         *argv[MAX_ARGS + 1];\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/*\n**  Copy a C string to a Pascal string\n**\n*/\n\nunsigned char *CToPCpy(unsigned char *pstr, char *cstr)\n{\n    register char *dptr;\n    register unsigned len;\n\n        len=0;\n        dptr=(char *)pstr+1;\n    while (len<255 && (*dptr++ = *cstr++)!='\\0') ++len;\n    *pstr= (unsigned char)len;\n  return pstr;\n}\n\n\n/*\n**  Copy a Pascal string to a C string\n**\n*/\n\nchar *PToCCpy(unsigned char *pstr, char *cstr)\n{\nstrncpy(cstr, (char *) &pstr[1], *pstr);\n    cstr[pstr[0]] = '\\0';  /* set endmarker for c-string */\nreturn cstr;\n}\n\n\n/*\n**  strcpy() and strcat() work-alikes which allow overlapping buffers.\n*/\n\nchar *sstrcpy(char *to,const char *from)\n{\n    memmove(to, from, 1+strlen(from));\n    return to;\n}\n\nchar *sstrcat(char *to,const char *from)\n{\n    sstrcpy(to + strlen(to), from);\n    return to;\n}\n\n\n\n/*\n**  Alloc memory and init it\n**\n*/\n\nchar *StrCalloc(unsigned short size)\n{\nchar *strPtr = NULL;\n\nif ((strPtr = calloc(size, sizeof(char))) == NULL)\n    printerr(\"StrCalloc failed:\", -1, size, __LINE__, __FILE__, \"\");\n\nAssert_it(strPtr,\"strPtr == NULL\",\"\")\nreturn strPtr;\n}\n\n\n\n/*\n**  Release only non NULL pointers\n**\n*/\n\nchar *StrFree(char *strPtr)\n{\n\nif (strPtr != NULL)\n    {\n    free(strPtr);\n    }\n\nreturn NULL;\n}\n\n\n\n\n/*\n**  Return a value in a binary string\n**\n*/\n\nchar *sBit2Str(unsigned short value)\n{\n  static char str[sizeof(value)*8];\n  int biz    = 16;\n  int strwid = 16;\n  int i, j;\n  char *tempPtr = str;\n\n      j = strwid - (biz + (biz >> 2)- (biz % 4 ? 0 : 1));\n\n      for (i = 0; i < j; i++) {\n            *tempPtr++ = ' ';\n      }\n      while (--biz >= 0)\n      {\n            *tempPtr++ = ((value >> biz) & 1) + '0';\n            if (!(biz % 4) && biz) {\n                  *tempPtr++ = ' ';\n            }\n      }\n      *tempPtr = '\\0';\n\n  return str;\n}\n\n\n\n\n/*\n**  Parse commandline style arguments\n**\n*/\n\nint ParseArguments(char *s, char ***arg)\n{\n    int  n = 1, Quote = 0;\n    char *p = s, *p1, c;\n\n    argv[0] = GetAppName();\n\n    *arg = argv;\n\n    p1 = (char *) argStr;\n    while ((c = *p++) != 0) {\n        if (c==' ') continue;\n        argv[n++] = p1;\n        if (n > MAX_ARGS)\n            return (n-1);\n        do {\n            if (c=='\\\\' && *p++)\n                c = *p++;\n            else\n                if ((c=='\"') || (c == '\\'')) {\n                    if (!Quote) {\n                        Quote = c;\n                        continue;\n                    }\n                    if (c == Quote) {\n                        Quote = 0;\n                        continue;\n                    }\n                }\n            *p1++ = c;\n        } while (*p && ((c = *p++) != ' ' || Quote));\n        *p1++ = '\\0';\n    }\n    return n;\n}\n\n\n\n/*\n**  Print commandline style arguments\n**\n*/\n\nvoid PrintArguments(int argc, char **argv)\n{\n\nprintf(\"\\n Arguments:\");\nprintf(\"\\n --------------------------\");\n\nwhile(--argc >= 0)\n    printf(\"\\n argc: %d  argv: [%s]\", argc, &*argv[argc]);\n\nprintf(\"\\n --------------------------\\n\\n\");\nreturn;\n}\n\n\n\n/*\n**  return some error-msg on file-system\n**\n*/\n\nint PrintUserHFSerr(int cond, int err, char *msg2)\n{\nchar *msg;\n\nif (cond != 0)\n    {\n    switch (err)\n        {\n         case -35:\n            msg = \"No such Volume\";\n         break;\n\n         case -56:\n            msg = \"No such Drive\";\n         break;\n\n         case -37:\n            msg = \"Bad Volume Name\";\n         break;\n\n         case -49:\n            msg = \"File is already open for writing\";\n         break;\n\n         case -43:\n            msg = \"Directory/File not found\";\n         break;\n\n         case -120:\n            msg = \"Directory/File not found or incomplete pathname\";\n         break;\n\n        default: return err;\n         }\n    fprintf(stderr, \"\\n\\n Error: %s ->%s\", msg, msg2);\n    exit(err);\n    }\n\nreturn 0;\n}\n\n\n\n/*\n**  Check mounted volumes and return number of volumes\n**  with the same name.\n*/\n\nshort CheckMountedVolumes(char *FullPath)\n{\nFSSpec  volumes[50];        /* 50 Volumes should be enough */\nchar VolumeName[257], volume[257];\nshort actVolCount, volIndex = 1, VolCount = 0;\nOSErr err;\nint i;\n\nGetVolumeFromPath(FullPath, VolumeName);\n\nerr = OnLine(volumes, 50, &actVolCount, &volIndex);\nprinterr(\"OnLine:\", (err != -35) && (err != 0), err, __LINE__, __FILE__, \"\");\n\nfor (i=0; i < actVolCount; i++)\n    {\n    PToCCpy(volumes[i].name,volume);\n    if (stricmp(volume, VolumeName) == 0) VolCount++;\n    }\nprinterr(\"OnLine: \", (VolCount == 0), VolCount, __LINE__, __FILE__, FullPath);\n\nreturn VolCount;\n}\n\n\n\n\n\n\n\n\n/*\n**  compares strings, ignoring differences in case\n**\n*/\n\nint stricmp(const char *p1, const char *p2)\n{\nint diff;\n\nwhile (*p1 && *p2)\n    {\n    if (*p1 != *p2)\n        {\n        if (isalpha(*p1) && isalpha(*p2))\n            {\n            diff = toupper(*p1) - toupper(*p2);\n            if (diff) return diff;\n            }\n            else break;\n        }\n        p1++;\n        p2++;\n    }\nreturn *p1 - *p2;\n}\n\n\n\n/*\n** Convert the MacOS-Strings (Filenames/Findercomments) to a most compatible.\n** These strings will be stored in the public area of the zip-archive.\n** Every foreign platform (outside macos) will access these strings\n** for extraction.\n*/\n\nvoid MakeCompatibleString(char *MacOS_Str,\n            const char SpcChar1, const char SpcChar2,\n            const char SpcChar3, const char SpcChar4,\n            short CurrTextEncodingBase)\n{\n    char *tmpPtr;\n    register uch curch;\n\n    Assert_it(MacOS_Str,\"MakeCompatibleString MacOS_Str == NULL\",\"\")\n    for (tmpPtr = MacOS_Str; (curch = *tmpPtr) != '\\0'; tmpPtr++)\n    {\n        if (curch == SpcChar1)\n            *tmpPtr = SpcChar2;\n        else\n        if (curch == SpcChar3)\n            *tmpPtr = SpcChar4;\n        else  /* default */\n        /* now convert from MacRoman to ISO-8859-1 */\n        /* but convert only if MacRoman is activ */\n            if ((CurrTextEncodingBase == kTextEncodingMacRoman) &&\n                (curch > 127))\n                   {\n                    *tmpPtr = (char)MacRoman_to_WinCP1252[curch - 128];\n                   }\n    }  /* end for */\n}\n\n\n\n\nBoolean CheckForSwitch(char *Switch, int argc, char **argv)\n{\n  char *p;              /* steps through option arguments */\n  int i;                /* arg counter, root directory flag */\n\n  for (i = 1; i < argc; i++)\n  {\n    if (argv[i][0] == '-')\n    {\n      if (argv[i][1])\n        {\n        for (p = argv[i]+1; *p; p++)\n            {\n            if (*p == Switch[0])\n                {\n                return true;\n                }\n            if ((Switch[1] != NULL) &&\n                ((*p == Switch[0]) && (*p == Switch[1])))\n                {\n                return true;\n                }\n            }\n         }\n     }\n  }\n\nreturn false;\n}\n\n\n\n\n\n\n\n#if (defined(USE_SIOUX) || defined(MACUNZIP_STANDALONE))\n\n/*\n**  checks the condition and returns an error-msg\n**  this function is for internal use only\n*/\n\nOSErr printerr(const char *msg, int cond, int err, int line, char *file,\n              const char *msg2)\n{\n\nif (cond != 0)\n    {\n    fprintf(stderr, \"\\nint err: %d: %s %d [%d/%s] {%s}\\n\", clock(), msg, err,\n            line, file, msg2);\n    }\n\nreturn cond;\n}\n\n\n/*\nfake-functions:\nNot Implemented for metrowerks SIOUX\n*/\n\nvoid leftStatusString(char *status)\n{\nstatus = status;\n}\n\n\nvoid rightStatusString(char *status)\n{\nstatus = status;\n}\n\n\n\nvoid DoWarnUserDupVol( char *FullPath )\n{\n  char VolName[257];\n  GetVolumeFromPath(FullPath,  VolName);\n\n  printf(\"\\n There are more than one volume that has the same name !!\\n\");\n\n  printf(\"\\n Volume: %s\\n\",VolName);\n\n  printf(\"\\n This port has one weak point:\");\n  printf(\"\\n It is based on pathnames. As you may be already know:\");\n  printf(\"\\n Pathnames are not unique on a Mac !\");\n  printf(\"\\n MacZip has problems to find the correct location of\");\n  printf(\"\\n the archive or the files.\\n\");\n\n  printf(\"\\n My (Big) recommendation:  Name all your volumes with an\");\n  printf(\"\\n unique name and MacZip will run without any problem.\");\n}\n\n\n\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/helpers.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef HELPERS_H\n#define HELPERS_H       1\n\n /* Convert a C string to a Pascal string */\nunsigned char *CToPCpy(unsigned char *pstr, char *cstr);\n\n /* Convert a Pascal string to a C string */\nchar *PToCCpy(unsigned char *pstr, char *cstr);\n\nchar *sstrcpy(char *to,const char *from);\nchar *sstrcat(char *to,const char *from);\n\nchar *StrCalloc(unsigned short size);\nchar *StrFree(char *strPtr);\n\nchar *sBit2Str(unsigned short value);\n\nvoid print_extra_info(void);\n\nint ParseArguments(char *s, char ***arg);\nvoid PrintArguments(int argc, char **argv);\n\nBoolean IsZipFile(char *name);\nOSErr printerr(const char *msg, int cond, int err, int line, char *file,\n               const char *msg2);\nint PrintUserHFSerr(int cond, int err, char *msg2);\n\nshort CheckMountedVolumes(char *FullPath);\nvoid DoWarnUserDupVol(char *path);\n\nvoid PrintFileInfo(void);\n\nint stricmp(const char *p1, const char *p2);\nvoid leftStatusString(char *status);\nvoid rightStatusString(char *status);\n\nBoolean isZipFile(FSSpec *fileToOpen);\n\nunsigned long MacFileDate_to_UTime(unsigned long mactime);\nBoolean CheckForSwitch(char *Switch, int argc, char **argv);\n\nvoid MakeCompatibleString(char *MacOS_Str,\n            const char SpcChar1, const char SpcChar2,\n            const char SpcChar3, const char SpcChar4,\n            short CurrTextEncodingBase);\n\n#define     MAX_ARGS    25\n\n#endif   /*  HELPERS_H   */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macglob.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef _MACGLOBAL_\n#define _MACGLOBAL_\n\n#include <time.h>\n\n/*\nall my Global vars are defined here.\n*/\n\n#define ResourceFork    -1\n#define DataFork        1\n#define NoFork          0\n\n/*\nall my Global vars are defined here.\n*/\ntypedef struct {\n    short       CurrentFork;\n    short       MacZipMode;\n\n    Boolean     isMacStatValid;\n    Boolean     HaveGMToffset;\n\n    short CurrTextEncodingBase;\n\n    /* info about the current file */\n    Boolean         isDirectory;\n    char            FullPath[NAME_MAX];\n    char            FileName[NAME_MAX];\n    FSSpec          fileSpec;\n\n    long            dirID;\n    CInfoPBRec      fpb;\n\n    /* time infos about the current file */\n    time_t          CreatDate;\n    time_t          ModDate;\n    time_t          BackDate;\n    long            Cr_UTCoffs; /* offset \"local time - UTC\" for CreatDate */\n    long            Md_UTCoffs; /* offset \"local time - UTC\" for ModDate */\n    long            Bk_UTCoffs; /* offset \"local time - UTC\" for BackDate */\n\n    /* some statistics over all*/\n    unsigned long   FoundFiles;\n    unsigned long   FoundDirectories;\n    unsigned long   RawCountOfItems;\n    unsigned long   BytesOfData;\n\n    unsigned long   attrsize;\n\n    /* some switches and user parameters */\n    Boolean         DataForkOnly;\n    Boolean         StoreFullPath;\n    Boolean         StoreFoldersAlso;  /* internal switch is true if '-r' is set */\n    unsigned short  SearchLevels;\n    char            Pattern[NAME_MAX];\n    Boolean         IncludeInvisible;\n    Boolean         StatingProgress;\n\n    char            SearchDir[NAME_MAX];\n    char            CurrentPath[NAME_MAX];\n\n    /* current zip / tempzip file info */\n    char            ZipFullPath[NAME_MAX];\n\n    FSSpec          ZipFileSpec;\n    unsigned long   ZipFileType;\n    char            TempZipFullPath[NAME_MAX];\n    FSSpec          TempZipFileSpec;\n\n} MacZipGlobals;\n\n\n\nvoid UserStop(void);\n\n\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macopen.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*** macopen.c; stuff only required for the Mac port ***/\n\n#include \"zip.h\"\n\n#include <string.h>\n#include <fcntl.h>\n#include <unix.h>\n#include <sound.h>\n\n#include \"helpers.h\"\n#include \"pathname.h\"\n#include \"macopen.h\"\n#include \"macstuff.h\"\n\n#ifdef MACZIP\n#include \"macglob.h\"\n\nextern char *zipfile;   /* filename of the Zipfile */\nextern char *tempzip;   /* Temporary zip file name */\n\nextern MacZipGlobals    MacZip;\n\n\n/* don't include \"osdep.h\" otherwise we will trap into endless loop */\n#undef open\n#undef fopen\n\n\n\nFILE *MacFopen(const char *path, const char *mode)\n{\nstatic char TruncPath[NAME_MAX];\nOSErr   err = 0;\n\nAssertStr(path,path)\n\n            /* open zipfile or tempzip */\nif (strcmp(zipfile,path) == 0)\n    {\n    GetCompletePath(MacZip.ZipFullPath,path,&MacZip.ZipFileSpec,&err);\n    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);\n    printerr(\"GetCompletePath:\",err,err,__LINE__,__FILE__,path);\n    if (CheckMountedVolumes(MacZip.ZipFullPath) > 1)\n        DoWarnUserDupVol(MacZip.ZipFullPath);\n\n    /* tempfile should appear in the same directory of the zipfile\n       -> save path of zipfile */\n    TruncFilename(TruncPath, MacZip.ZipFullPath);\n    return fopen(MacZip.ZipFullPath, mode);\n    }\n\nif (strcmp(tempzip,path) == 0)\n    {  /* add path of zipfile */\n    sstrcat(TruncPath,tempzip);\n    GetCompletePath(MacZip.TempZipFullPath,TruncPath,&MacZip.TempZipFileSpec,&err);\n    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);\n    printerr(\"GetCompletePath:\",err,err,__LINE__,__FILE__,path);\n\n    return fopen(MacZip.TempZipFullPath, mode);\n    }\n\nprinterr(\"MacFopen:\",err,err,__LINE__,__FILE__,path);\nreturn NULL;\n}\n\n\n\n\nint MacOpen(const char *path,int oflag, ...)\n{\nchar RealFname[NAME_MAX];\n\nAssertStr(path,path)\n\nRfDfFilen2Real(RealFname,path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);\n/* convert to real fname and init global var  MacZip.CurrentFork  !!  */\n\nswitch (MacZip.CurrentFork)\n    {\n    case DataFork:\n        {\n        return my_open(RealFname, oflag);\n        break;\n        }\n    case ResourceFork:\n        {\n        return my_open( RealFname, oflag | O_RSRC);\n        break;\n        }\n    default:  /* for now (Zip ver 2.3b) MacOpen should never reach this point */\n        {     /* however, this may change in the future ... */\n        printerr(\"open: no resource / datafork \",-1,-1,__LINE__,__FILE__,path);\n        return -1;\n        }\n    }\n}\n\n\n#ifdef muell\n /* file to delete */\nint destroy(char *path)\n{\nstatic char lastpath[NAME_MAX];\nchar    currpath[NAME_MAX];\nstatic Boolean FirstCall = true;\nlong rc;\n\nAssertStr(path,path)\n\nRfDfFilen2Real(currpath, path, MacZip.MacZipMode, MacZip.DataForkOnly, &MacZip.CurrentFork);\n\nif (FirstCall == true)\n    {\n    FirstCall = false;\n    rc = remove(currpath);\n    }\nelse if (strcmp(currpath,lastpath) == 0) return 0; /* ignore, file is already deleted */\n        else rc = remove(currpath); /* we are removeing all the files only by their\n        pathname this is dangerous on a mac but there is no other way without\n         a complete rewrite of the port  */\n\nstrcpy(lastpath,currpath);\n\nreturn rc;\n}\n#endif\n\n\n\n\n/* this function replaces the function \"replace()\" defined in fileio.c */\nint replace(char *new_f, char *temp_f)  /* destination and source file names */\n{\nOSErr   err = 0;\nchar    newfname[NAME_MAX];\n\nAssertStr(new_f,new_f)\nAssertStr(temp_f,temp_f)\n\nUserStop();\n\nGetFilename(newfname, new_f);\n\n/* check zipfile name and tempfile name */\n/* we are using this function only for replacing the tempfile with the zipfile */\nif ((strcmp(zipfile,new_f) == 0) || (strcmp(tempzip,temp_f) == 0))\n    {\n    remove(MacZip.ZipFullPath);\n\n    /* rename the temp file to the zip file */\n    err = rename(MacZip.TempZipFullPath,MacZip.ZipFullPath);\n    printerr(\"rename:\",err,err,__LINE__,__FILE__,MacZip.TempZipFullPath);\nif (err != 0) return ZE_CREAT;\n    else return ZE_OK;\n    }\nelse return ZE_CREAT;\n}\n\n\n\n /* file to delete */\n /* we are removeing all the files only by their\n    pathname this is dangerous on a mac but there is no\n    other way without a complete rewrite of the port  */\n\nint destroy(char *path)\n{\nstatic char lastpath[NAME_MAX];\nstatic FSSpec  trashfolder;\nstatic Boolean FirstCall = true;\nstatic char Num = 0;\nstatic Boolean  Immediate_File_Deletion = false;\nchar    currpath[NAME_MAX], *envptr;\nFSSpec  fileToDelete;\nOSErr   err;\n\n/* init this function */\nif ((path == NULL) ||\n    (strlen(path) == 0))\n    {\n    FirstCall = true;\n    Num = 0;\n    return -1;\n    }\n\nUserStop();\n\nRfDfFilen2Real(currpath, path, MacZip.MacZipMode,\n                MacZip.DataForkOnly, &MacZip.CurrentFork);\nGetCompletePath(currpath,currpath,&fileToDelete, &err);\n\nif (FirstCall == true)\n    {\n    FirstCall = false;\n    sstrcpy(lastpath,currpath);\n    err = FSpFindFolder(fileToDelete.vRefNum, kTrashFolderType,\n                      kDontCreateFolder,&trashfolder);\n    printerr(\"FSpFindFolder:\",err,err,__LINE__,__FILE__,path);\n\n    envptr = getenv(\"Immediate_File_Deletion\");\n    if (!(envptr == (char *)NULL || *envptr == '\\0'))\n        {\n        if (stricmp(envptr,\"yes\") == 0)\n            Immediate_File_Deletion = true;\n        else\n            Immediate_File_Deletion = false;\n        }\n\n    if (Immediate_File_Deletion)\n        {\n        err = FSpDelete(&fileToDelete);\n        return err;\n        }\n\n    err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,\n                   fileToDelete.name, trashfolder.parID, trashfolder.name);\n    return err;\n    }\n\nif (strcmp(currpath,lastpath) == 0)\n    {\n    return 0; /* ignore, file is already deleted */\n    }\nelse\n    {\n\n    if (Immediate_File_Deletion)\n        {\n        err = FSpDelete(&fileToDelete);\n        sstrcpy(lastpath,path);\n        return err;\n        }\n\n    err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,\n                   fileToDelete.name, trashfolder.parID, trashfolder.name);\n\n    /* -48 = file is already existing so we have to rename it before\n       moving the file */\n    if (err == -48)\n        {\n        Num++;\n        if (fileToDelete.name[0] >= 28) /* cut filename if to long */\n            fileToDelete.name[0] = 28;\n        P2CStr(fileToDelete.name);\n        sprintf(currpath,\"%s~%d\",(char *)fileToDelete.name,Num);\n        C2PStr(currpath);\n        C2PStr((char *)fileToDelete.name);\n        err = HRename (fileToDelete.vRefNum, fileToDelete.parID,\n                       fileToDelete.name, (unsigned char *) currpath);\n        err = CatMove (fileToDelete.vRefNum, fileToDelete.parID,\n                       (unsigned char *) currpath, trashfolder.parID,\n                       trashfolder.name);\n        }\n    }\n\nsstrcpy(lastpath,currpath);\nreturn err;\n}\n\n\n\n#endif  /* #ifdef MACZIP */\n\n\n\n\n/*\n *  int open(const char *path, int oflag)\n *\n *      Opens a file stream.\n */\nint my_open(char *path, int oflag)\n{\n    FSSpec          spec;\n    char            permission;\n    HParamBlockRec  hpb;\n    OSErr           err, errno;\n    Boolean targetIsFolder, wasAliased;\n\n    AssertStr(path,path)\n\n    /* Setup permission */\n    if ((oflag & 0x03) == O_RDWR)\n        permission = fsRdWrPerm;\n    else\n        permission = (oflag & O_RDONLY) ? fsRdPerm : 0 + (oflag & O_WRONLY) ? fsWrPerm : 0;\n\n        FSpLocationFromFullPath(strlen(path),path, &spec);\n        if ((oflag & (O_ALIAS | O_NRESOLVE)) == 0)\n            ResolveAliasFile(&spec, true, &targetIsFolder, &wasAliased);\n        hpb.fileParam.ioNamePtr = spec.name;\n        hpb.fileParam.ioVRefNum = spec.vRefNum;\n        hpb.fileParam.ioDirID = spec.parID;\n        hpb.ioParam.ioPermssn = permission;\n\n        if (oflag & O_RSRC)         /* open the resource fork of the file */\n            err = PBHOpenRFSync(&hpb);\n        else                        /* open the data fork of the file */\n            err = PBHOpenDFSync(&hpb);\n\n    if ((err == fnfErr) && (oflag & O_CREAT)) {\n        hpb.fileParam.ioFlVersNum = 0;\n        err = PBHCreateSync(&hpb);\n        if (err == noErr) {\n            /* Set the finder info */\n            unsigned long secs;\n            unsigned long isbinary = oflag & O_BINARY;\n\n            hpb.fileParam.ioFlFndrInfo.fdType = '\\?\\?\\?\\?';\n            hpb.fileParam.ioFlFndrInfo.fdCreator = '\\?\\?\\?\\?';\n            hpb.fileParam.ioFlFndrInfo.fdFlags = 0;\n            if (oflag & O_ALIAS)        /* set the alias bit */\n                hpb.fileParam.ioFlFndrInfo.fdFlags = kIsAlias;\n            else                                        /* clear all flags */\n                hpb.fileParam.ioFlFndrInfo.fdFlags = 0;\n\n            GetDateTime(&secs);\n            hpb.fileParam.ioFlCrDat = hpb.fileParam.ioFlMdDat = secs;\n            PBHSetFInfoSync(&hpb);\n        }\n\n        if (err && (err != dupFNErr)) {\n            errno = err; return -1;\n        }\n\n            if (oflag & O_RSRC)         /* open the resource fork of the file */\n                err = PBHOpenRFSync(&hpb);\n            else                        /* open the data fork of the file */\n                err = PBHOpenDFSync(&hpb);\n    }\n\n    if (err && (err != dupFNErr) && (err != opWrErr)) {\n        errno = err; return -1;\n    }\n\n    if (oflag & O_TRUNC) {\n        IOParam pb;\n\n        pb.ioRefNum = hpb.ioParam.ioRefNum;\n        pb.ioMisc = 0L;\n        err = PBSetEOFSync((ParmBlkPtr)&pb);\n        if (err != noErr) {\n            errno = err; return -1;\n        }\n    }\n\n    if (oflag & O_APPEND) lseek(hpb.ioParam.ioRefNum,0,SEEK_END);\n\n    return (hpb.ioParam.ioRefNum);\n}\n\n\n\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macopen.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef __MACOPEN_H__\n#define __MACOPEN_H__\n\n#include <stdio.h>\n#include <Files.h>\n\n\nFILE *MacFopen(const char *path, const char *mode);\nint MacOpen(const char *path, int oflag, ...);\n\nint my_open(char *path, int oflag);\n\n#endif /* __MACOPEN_H__  */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macos.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  macos.c\n\n  Macintosh-specific routines for use with Info-ZIP's Zip 2.3 and later.\n\n  ---------------------------------------------------------------------------*/\n\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include \"zip.h\"\n\n#include \"revision.h\"\n#include \"crypt.h\"\n\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sound.h>\n\n#include <unistd.h>\n\n#include <Strings.h>\n#include <setjmp.h>\n\n/* #include \"charmap.h\" */\n#include \"helpers.h\"\n#include \"macstuff.h\"\n#include \"pathname.h\"\n#include \"recurse.h\"\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n#define PATH_END   MacPathEnd\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nint error_level;   /* used only in ziperr() */\n\n\n/*  Note: sizeof() returns the size of this allusion\n          13 is current length of \"XtraStuf.mac:\"      */\nextern const char ResourceMark[13]; /* var is initialized in file pathname.c */\n\n\nextern jmp_buf EnvForExit;\nMacZipGlobals   MacZip;\n\nunsigned long count_of_Zippedfiles = 0;\n\n\n/*****************************************************************************/\n/*  Module level Vars                                                        */\n/*****************************************************************************/\n\nstatic const char MacPathEnd = ':';   /* the Macintosh dir separator */\n\n/*  Inform Progress vars */\nlong    estTicksToFinish;\nlong    createTime;\nlong    updateTicks;\n\nstatic char *Time_Est_strings[] = {\n        \"Zipping Files; Items done:\",\n        \"More than 24 hours\",\n        \"More than %s hours\",\n        \"About %s hours, %s minutes\",\n        \"About an hour\",\n        \"Less than an hour\",\n        \"About %s minutes, %s seconds\",\n        \"About a minute\",\n        \"Less than a minute\",\n        \"About %s seconds\",\n        \"About a second\",\n        \"About 1 minute, %s seconds\"};\n\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nint DoCurrentDir(void);\n\nvoid DoAboutBox(void);\nvoid DoQuit(void);\nvoid DoEventLoop(void);\n\nvoid ZipInitAllVars(void);\nvoid UserStop(void);\nBoolean IsZipFile(char *name);\n\nstatic long EstimateCompletionTime(const long progressMax,\n                            const long progressSoFar, unsigned char percent);\nstatic void UpdateTimeToComplete(void);\n\n\n\n\n#ifdef USE_SIOUX\n#include <sioux.h>\nvoid DoWarnUserDupVol( char *FullPath );\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n/*\n** Standalone Unzip with Metrowerks SIOUX starts here\n**\n*/\nint main(int argc, char **argv)\n{\n    int return_code;\n\n    SIOUXSettings.asktosaveonclose = FALSE;\n    SIOUXSettings.showstatusline = TRUE;\n\n    SIOUXSettings.columns = 100;\n    SIOUXSettings.rows    = 40;\n\n    /* 30 = MacZip Johnny Lee's; 40 = new (my) MacZip */\n    MacZip.MacZipMode = NewZipMode_EF;\n\n    argc = ccommand(&argv);\n    if (verbose) PrintArguments(argc, argv);\n\n    ZipInitAllVars();\n\n    return_code = zipmain(argc, argv);\n\n    if (verbose) printf(\"\\n\\n Finish\");\n    return return_code;\n}\n\n\n\n/*\n** SIOUX needs no extra event handling\n**\n*/\n\nvoid UserStop(void)\n{\n};\n\n\n\n\n/*\n** Password enter function '*' printed for each char\n**\n*/\n\nint macgetch(void)\n{\n    WindowPtr whichWindow;\n    EventRecord theEvent;\n    char c;                     /* one-byte buffer for read() to use */\n\n    do {\n        SystemTask();\n        if (!GetNextEvent(everyEvent, &theEvent))\n            theEvent.what = nullEvent;\n        else {\n            switch (theEvent.what) {\n            case keyDown:\n                c = theEvent.message & charCodeMask;\n                break;\n            case mouseDown:\n                if (FindWindow(theEvent.where, &whichWindow) ==\n                    inSysWindow)\n                    SystemClick(&theEvent, whichWindow);\n                break;\n            case updateEvt:\n                break;\n            }\n        }\n    } while (theEvent.what != keyDown);\n\n    printf(\"*\");\n    fflush(stdout);\n\n    return (int)c;\n}\n\n#endif\n\n\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\n/*\n** Print Compilers version and compile time/date\n**\n*/\n\nvoid version_local()\n{\n/* prints e.g:\nCompiled with  Metrowerks CodeWarrior version 2000 for  PowerPC Processor\n compile time:  Feb  4 1998 17:49:49.\n*/\n\nstatic ZCONST char CompiledWith[] =\n                        \"\\n\\nCompiled with %s %x for %s \\n %s %s %s.\\n\\n\";\n\n    printf(CompiledWith,\n\n\n#ifdef __MWERKS__\n      \" Metrowerks CodeWarrior version\", __MWERKS__,\n#endif\n\n\n#ifdef __MC68K__\n      \" MC68K Processor\",\n#else\n      \" PowerPC Processor\",\n#endif\n\n#ifdef __DATE__\n      \"compile time: \", __DATE__, __TIME__\n#else\n      \"\", \"\", \"\"\n#endif\n    );\n} /* end function version_local() */\n\n\n\n\n\n/*\n** Deletes a dir if the switch '-m' is used\n**\n*/\n\nint deletedir(char *path)\n{\nstatic char     Num = 0;\nstatic FSSpec   trashfolder;\nstatic Boolean  FirstCall = true;\nstatic Boolean  Immediate_File_Deletion = false;\nOSErr           err;\nFSSpec          dirToDelete;\nchar            currpath[NAME_MAX], *envptr;\nCInfoPBRec      fpb;\n\n/* init this function */\nif ((path == NULL) ||\n    (strlen(path) == 0))\n    {\n    Num = 0;\n    FirstCall = true;\n    return -1;\n    }\n\nUserStop();\n\nGetCompletePath(currpath,path,&dirToDelete, &err);\n\nif (FirstCall == true)\n    {\n    FirstCall = false;\n    envptr = getenv(\"Immediate_File_Deletion\");\n    if (!(envptr == (char *)NULL || *envptr == '\\0'))\n        {\n        if (stricmp(envptr,\"yes\") == 0)\n            Immediate_File_Deletion = true;\n        else\n            Immediate_File_Deletion = false;\n        }\n    err = FSpFindFolder(dirToDelete.vRefNum, kTrashFolderType,\n                      kDontCreateFolder,&trashfolder);\n    printerr(\"FSpFindFolder:\",err,err,__LINE__,__FILE__,path);\n    }\n\n    fpb.dirInfo.ioNamePtr   = dirToDelete.name;\n    fpb.dirInfo.ioVRefNum   = dirToDelete.vRefNum;\n    fpb.dirInfo.ioDrDirID   = dirToDelete.parID;\n    fpb.dirInfo.ioFDirIndex = 0;\n\n    err = PBGetCatInfoSync(&fpb);\n    printerr(\"PBGetCatInfo deletedir \", err, err,\n             __LINE__, __FILE__, \"\");\n\nif (fpb.dirInfo.ioDrNmFls > 0)\n    {\n    return 0;  /* do not move / delete folders which are not empty */\n    }\n\nif (Immediate_File_Deletion)\n    {\n    err = FSpDelete(&dirToDelete);\n    return err;\n    }\n\nerr = CatMove (dirToDelete.vRefNum, dirToDelete.parID,\n               dirToDelete.name, trashfolder.parID, trashfolder.name);\n\n/* -48 = file is already existing so we have to rename it before\n   moving the file */\nif (err == -48)\n    {\n    Num++;\n    if (dirToDelete.name[0] >= 28) /* cut foldername if to long */\n        dirToDelete.name[0] = 28;\n    P2CStr(dirToDelete.name);\n    sprintf(currpath,\"%s~%d\",(char *)dirToDelete.name,Num);\n    C2PStr(currpath);\n    C2PStr((char *)dirToDelete.name);\n    err = HRename (dirToDelete.vRefNum, dirToDelete.parID,\n                   dirToDelete.name, (unsigned char *) currpath);\n\n    err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,\n                   (unsigned char *) currpath, trashfolder.parID,\n                   trashfolder.name);\n    }\n\nreturn err;\n}\n\n\n\n\n/*\n** Set the file-type so the archive will get the correct icon, type\n** and creator code.\n*/\n\nvoid setfiletype(char *new_f, unsigned long Creator, unsigned long Type)\n{\nOSErr   err;\n\nif (strcmp(zipfile, new_f) == 0)\n    err = FSpChangeCreatorType(&MacZip.ZipFileSpec, Creator, Type);\nprinterr(\"FSpChangeCreatorType:\", err, err, __LINE__, __FILE__, new_f);\n\nreturn;\n}\n\n\n\n\n\n/*\n** Convert the external (native) filename into Zip's internal Unix compatible\n** name space.\n*/\n\nchar *ex2in(char *externalFilen, int isdir, int *pdosflag)\n/* char *externalFilen     external file name */\n/* int isdir               input: externalFilen is a directory */\n/* int *pdosflag           output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *internalFilen;              /* internal file name (malloc'ed) */\n  char *t;                          /* shortened name */\n  char *Pathname;\n  char buffer[NAME_MAX];\n  int dosflag;\n\n  AssertStr(externalFilen, externalFilen)\n  AssertBool(isdir,\"\")\n\n  dosflag = dosify;  /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for (t = externalFilen; *t == PATH_END; t++)\n      ;\n\n  if (!MacZip.StoreFullPath)\n        {\n        Pathname = StripPartialDir(buffer, MacZip.SearchDir,t);\n        }\n  else\n        {\n        Pathname = t;\n        }\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    {\n    t = last(Pathname, PATH_END);\n    }\n  else t = Pathname;\n\n  /* Malloc space for internal name and copy it */\n  if ((internalFilen = malloc(strlen(t) + 10 + strlen(ResourceMark) )) == NULL)\n    return NULL;\n\n  sstrcpy(internalFilen, t);\n\n    /* we have to eliminate illegal chars:\n     * The name space for Mac filenames and Zip filenames (unix style names)\n     * do both include all printable extended-ASCII characters.  The only\n     * difference we have to take care of is the single special character\n     * used as path delimiter:\n     * ':' on MacOS and '/' on Unix and '\\' on Dos.\n     * So, to convert between Mac filenames and Unix filenames without any\n     * loss of information, we simply interchange ':' and '/'.  Additionally,\n     * we try to convert the coding of the extended-ASCII characters into\n     * InfoZip's standard ISO 8859-1 codepage table.\n     */\n  MakeCompatibleString(internalFilen, ':', '/', '/', ':',\n                       MacZip.CurrTextEncodingBase);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n\n  if (isdir)\n    {\n    return internalFilen;      /* avoid warning on unused variable */\n    }\n\n  if (dosify)\n    {\n    msname(internalFilen);\n    printf(\"\\n ex2in: %s\",internalFilen);\n    }\n\n  return internalFilen;\n}\n\n\n\n/*\n** Collect all filenames. Go through all directories\n**\n*/\n\nint wild(char *Pathpat)\n                /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\nFSSpec Spec;\nchar fullpath[NAME_MAX];\nOSErr   err;\n\nAssertStr(Pathpat, Pathpat);\n\nif (noisy) printf(\"%s \\n\\n\",GetZipVersionsInfo());\n\nif (extra_fields == 0)\n    {\n    MacZip.DataForkOnly = true;\n    }\n\n/* for switch '-R' -> '.' means current dir */\nif (strcmp(Pathpat,\".\") == 0) sstrcpy(Pathpat,\"*\");\n\nsstrcpy(MacZip.Pattern,Pathpat);\n\nif (recurse)\n    {\n    MacZip.StoreFoldersAlso = true;\n    MacZip.SearchLevels = 0; /* if 0 we aren't checking levels */\n    }\nelse\n    {\n    MacZip.StoreFoldersAlso = false;\n    MacZip.SearchLevels = 1;\n    }\n\n/* make complete path */\nGetCompletePath(fullpath, MacZip.Pattern, &Spec,&err);\nerr = PrintUserHFSerr((err != -43) && (err != 0), err, MacZip.Pattern);\nprinterr(\"GetCompletePath:\", err, err, __LINE__, __FILE__, fullpath);\n\n/* extract the filepattern */\nGetFilename(MacZip.Pattern, fullpath);\n\n/* extract Path and get FSSpec of search-path */\n/* get FSSpec of search-path  ; we need a dir to start\n   searching for filenames */\nTruncFilename(MacZip.SearchDir, fullpath);\nGetCompletePath(MacZip.SearchDir, MacZip.SearchDir, &Spec,&err);\n\nif (noisy) {\n    if (MacZip.SearchLevels == 0)\n        {\n        printf(\"\\nSearch Pattern: [%s]   Levels: all\", MacZip.Pattern);\n        }\n    else\n        {\n        printf(\"\\nSearch Pattern: [%s]   Levels: %d\", MacZip.Pattern,\n               MacZip.SearchLevels);\n        }\n    printf(\"\\nSearch Path:    [%s]\", MacZip.SearchDir);\n    printf(\"\\nZip-File:       [%s] \\n\",MacZip.ZipFullPath);\n\n}\n\n/* we are working only with pathnames;\n * this can cause big problems on a mac ...\n */\nif (CheckMountedVolumes(MacZip.SearchDir) > 1)\n    DoWarnUserDupVol(MacZip.SearchDir);\n\n/* start getting all filenames */\nerr = FSpRecurseDirectory(&Spec, MacZip.SearchLevels);\nprinterr(\"FSpRecurseDirectory:\", err, err, __LINE__, __FILE__, \"\");\n\nreturn ZE_OK;\n}\n\n\n\n/*\n** Convert the internal filename into a external (native).\n** The user will see this modified filename.\n** For more performance:\n** I do not completly switch back to the native macos filename.\n** The user will still see directory separator '/' and the converted\n** charset.\n*/\n\nchar *in2ex(char *n)    /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  AssertStr(n,n)\n\n  if ((x = malloc(strlen(n) + 1)) == NULL)\n    return NULL;\n\n  RfDfFilen2Real(x, n, MacZip.MacZipMode, MacZip.DataForkOnly,\n                 &MacZip.CurrentFork);\n\n  return x;\n}\n\n\n\n\n/*\n** Process on filenames. This function will be called to collect\n** the filenames.\n*/\n\nint procname(char *filename,         /* name to process */\n             int caseflag)           /* true to force case-sensitive match\n                                        (always false on a Mac) */\n/* Process a name .  Return\n   an error code in the ZE_ class. */\n{\n  int rc;                /* matched flag */\n\nAssertBool(caseflag,\"caseflag\")\nAssertStr(filename,filename)\n\n        /* add or remove name of file */\nrc = newname(filename, MacZip.isDirectory, caseflag);\n\nreturn rc;\n}\n\n\n\n\nulg filetime(\nchar *f,                /* name of file to get info on */\nulg *a,                 /* return value: file attributes */\nlong *n,                /* return value: file size */\niztimes *t)             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n\n  AssertStr(f,f)\n\n  if (strlen(f) == 0) return 0;\n\n  if (SSTAT(f, &s) != 0)\n             /* Accept about any file kind including directories\n              * (stored with trailing : with -r option)\n              */\n    return 0;\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if (MacZip.isDirectory) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & UNX_IFMT) == UNX_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;   /* on Mac, st_ctime contains creation time! */\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\n\n\nvoid stamp(char *f, ulg d)\n/* char *f;                name of file to change */\n/* ulg d;                  dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  time_t u[2];          /* argument for utime() */\n\nf = f;\n\n  /* Convert DOS time to time_t format in u */\n\n  u[0] = u[1] = dos2unixtime(d);\n/*  utime(f, u);  */\n}\n\n\n\n\n/*\n**  return only the longest part of the path:\n**  second parameter: Volume:test folder:second folder:\n**  third parameter:  Volume:test folder:second folder:third folder:file\n**  result will be:   third folder:file\n**  first parameter:  contains string buffer that will be used to prepend\n**                    the \"resource mark\" part in front of the result when\n**                    a resource fork is processed in \"M3\" mode.\n**\n*/\n\nchar *StripPartialDir(char *CompletePath,\n                      const char *PartialPath, const char *FullPath)\n{\nconst char *tmpPtr1 = PartialPath;\nconst char *tmpPtr2 = FullPath;\nint     result;\n\nAssert_it(CompletePath,\"StripPartialDir\",\"\")\nAssertStrNoOverlap(FullPath,PartialPath,PartialPath)\n\nif (MacZip.DataForkOnly)\n        {\n        tmpPtr2 += strlen(tmpPtr1);\n        return (char *)tmpPtr2;\n        }\n\nswitch (MacZip.MacZipMode)\n    {\n    case JohnnyLee_EF:\n        {\n        tmpPtr2 += strlen(tmpPtr1);\n        return (char *)tmpPtr2;\n        break;\n        }\n\n    case NewZipMode_EF:\n        {           /* determine Fork type */\n        result = strncmp(FullPath, ResourceMark, sizeof(ResourceMark)-2);\n        if (result != 0)\n            {                               /* data fork  */\n            MacZip.CurrentFork = DataFork;\n            tmpPtr2 += strlen(tmpPtr1);\n             return (char *)tmpPtr2;\n            }\n        else\n            {                                /* resource fork  */\n            MacZip.CurrentFork = ResourceFork;\n            sstrcpy(CompletePath, ResourceMark);\n            tmpPtr2 += strlen(tmpPtr1);\n            tmpPtr2 += sizeof(ResourceMark);\n            sstrcat(CompletePath, tmpPtr2);\n            return (char *)CompletePath;\n            }\n        break;\n        }\n    }\n\n return NULL;    /* function should never reach this point */\n}\n\n\n\n\n/*\n** Init all global variables\n** Must be called for each zip-run\n*/\n\nvoid ZipInitAllVars(void)\n{\ngetcwd(MacZip.CurrentPath, sizeof(MacZip.CurrentPath));\n/* MacZip.MacZipMode = JohnnyLee_EF;     */\nMacZip.MacZipMode = NewZipMode_EF;\n\nMacZip.DataForkOnly = false;\nMacZip.CurrentFork = NoFork;\n\nMacZip.StoreFoldersAlso = false;\n\nMacZip.FoundFiles = 0;\nMacZip.FoundDirectories = 0;\nMacZip.RawCountOfItems = 0;\nMacZip.BytesOfData = 0;\n\nMacZip.StoreFullPath = false;\nMacZip.StatingProgress = false;\nMacZip.IncludeInvisible = false;\n\nMacZip.isMacStatValid = false;\n\nMacZip.CurrTextEncodingBase = FontScript();\n\nMacZip.HaveGMToffset = false;\n\ncreateTime = TickCount();\nestTicksToFinish = -1;\nupdateTicks = 0;\n\n/* init some functions */\nIsZipFile(NULL);\n\ndestroy(NULL);\ndeletedir(NULL);\nShowCounter(true);\n\nextra_fields = 1;\nerror_level = 0;\ncount_of_Zippedfiles = 0;\n}\n\n\n\n\n/*\n** Get the findercomment and store it as file-comment in the Zip-file\n**\n*/\nchar *GetComment(char *filename)\n{\nOSErr       err;\nstatic char buffer[NAME_MAX];\nchar buffer2[NAME_MAX];\nchar *tmpPtr;\n\nif (filename == NULL) return NULL;\n\n    /* now we can convert Unix-Path in HFS-Path */\nfor (tmpPtr = filename; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == '/')\n      *tmpPtr = ':';\n\nif (MacZip.StoreFullPath)\n    {  /* filename is already a fullpath */\n    sstrcpy(buffer,filename);\n    }\nelse\n    {  /* make a fullpath */\n    sstrcpy(buffer,MacZip.SearchDir);\n    sstrcat(buffer,filename);\n    }\n\n/* make fullpath and get FSSpec */\n/* Unfortunately: I get only the converted filename here */\n/* so filenames with extended characters can not be found  */\nGetCompletePath(buffer2,buffer, &MacZip.fileSpec, &err);\nprinterr(\"GetCompletePath:\",(err != -43) && (err != -120) && (err != 0) ,\n          err,__LINE__,__FILE__,buffer);\n\nerr = FSpDTGetComment(&MacZip.fileSpec, (unsigned char *) buffer);\nprinterr(\"FSpDTGetComment:\", (err != -5012) && (err != 0), err,\n         __LINE__, __FILE__, filename);\nP2CStr((unsigned char *) buffer);\nif (err == -5012) return NULL;  /* no finder-comments found */\n\nif (noisy) printf(\"\\n%32s -> %s\",filename, buffer);\n/*\nBeside the script change we need only to change 0x0d in 0x0a\nso the last two arguments are not needed and does nothing.\n*/\nMakeCompatibleString(buffer, 0x0d, 0x0a, ' ', ' ',\n                     MacZip.CurrTextEncodingBase);\n\nreturn buffer;\n}\n\n\n\n\n/*\n** Print a progress indicator for stating the files\n**\n*/\n\nvoid PrintStatProgress(char *msg)\n{\n\nif (!noisy) return;     /* do no output if noisy is false */\n\nMacZip.StatingProgress = true;\n\nif (strcmp(msg,\"done\") == 0)\n    {\n    MacZip.StatingProgress = false;\n    printf(\"\\n ... done \\n\\n\");\n    }\nelse printf(\"\\n %s\",msg);\n\n}\n\n\n\n\nvoid InformProgress(const long progressMax, const long progressSoFar )\n{\nint curr_percent;\nchar no_time[5] = \"...\";\n\ncurr_percent = percent(progressMax, progressSoFar);\n\nif (curr_percent < 95)\n    {\n    estTicksToFinish = EstimateCompletionTime(progressMax,\n                                                  progressSoFar, curr_percent);\n    }\nelse\n    {\n    rightStatusString(no_time);\n    leftStatusString(no_time);\n    }\n\nupdateTicks = TickCount() + 60;\nreturn;\n}\n\n\nvoid ShowCounter(Boolean reset)\n{\nstatic char statusline[100];\nstatic unsigned long filecount = 0;\n\nif (reset)\n        {\n        filecount = 0;\n        return;\n        }\n\nif (noisy)\n    {\n    sprintf(statusline, \"%6d\", filecount++);\n    rightStatusString(statusline);\n    }\n}\n\n\nstatic long EstimateCompletionTime(const long progressMax,\n                                const long progressSoFar,\n                                unsigned char curr_percent)\n{\n    long  max = progressMax, value = progressSoFar;\n    static char buf[100];\n    unsigned long ticksTakenSoFar = TickCount() - createTime;\n    float currentRate = (float) ticksTakenSoFar / (float) value;\n    long  newEst = (long)( currentRate * (float)( max - value ));\n\n    sprintf(buf, \"%d [%d%%]\",progressSoFar, curr_percent);\n    rightStatusString(buf);\n\n    estTicksToFinish = newEst;\n\n    UpdateTimeToComplete();\n\nreturn estTicksToFinish;\n}\n\n\n\n\n\nstatic void UpdateTimeToComplete(void)\n{\n    short       days, hours, minutes, seconds;\n    char    estStr[255];\n    Str15   xx, yy;\n    short   idx = 0;\n\n    if ( estTicksToFinish == -1 )\n        return;\n\n    days    =   estTicksToFinish / 5184000L;\n    hours   = ( estTicksToFinish - ( days * 5184000L )) / 216000L;\n    minutes = ( estTicksToFinish - ( days * 5184000L ) -\n              ( hours * 216000L )) / 3600L;\n    seconds = ( estTicksToFinish - ( days * 5184000L ) -\n              ( hours * 216000L ) - ( minutes * 3600L )) / 60L;\n\n        xx[0] = 0;\n        yy[0] = 0;\n\n        if ( days )\n        {\n            /* \"more than 24 hours\" */\n\n            idx = 1;\n            goto setEstTimeStr;\n        }\n\n        if ( hours >= 8 )\n        {\n            /* \"more than x hours\" */\n\n            NumToString( hours, xx );\n            idx = 2;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 252000L  )      /* > 1hr, 10 minutes */\n        {\n            /* \"about x hours, y minutes\" */\n\n            NumToString( hours, xx );\n            NumToString( minutes, yy );\n            idx = 3;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 198000L )   /* > 55 minutes */\n        {\n            /* \"about an hour\" */\n            idx = 4;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 144000L )   /* > 40 minutes */\n        {\n            /* \"less than an hour\" */\n\n            idx = 5;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 4200L )     /* > 1 minute, 10 sec */\n        {\n            /* \"about x minutes, y seconds */\n\n            NumToString( minutes, xx );\n            NumToString( seconds, yy );\n\n            if ( minutes == 1 )\n                idx = 11;\n            else\n                idx = 6;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 3000L )     /* > 50 seconds */\n        {\n            /* \"about a minute\" */\n\n            idx = 7;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 1500L )     /* > 25 seconds */\n        {\n            /* \"less than a minute\" */\n\n            idx = 8;\n            goto setEstTimeStr;\n        }\n\n        if ( estTicksToFinish > 120L )      /* > 2 seconds */\n        {\n            NumToString( seconds, xx );\n            idx = 9;\n            goto setEstTimeStr;\n        }\n\n        idx = 10;\n\n    setEstTimeStr:\n        sprintf(estStr,Time_Est_strings[idx],P2CStr(xx),P2CStr(yy));\n        leftStatusString((char *)estStr);\n}\n\n\n\n\n\n/*\n** Just return the zip version\n**\n*/\n\nchar *GetZipVersionsInfo(void)\n{\nstatic char ZipVersion[100];\n\nsprintf(ZipVersion, \"Zip Module\\n%d.%d%d%s of %s\", Z_MAJORVER, Z_MINORVER,\n        Z_PATCHLEVEL, Z_BETALEVEL, REVDATE);\n\nreturn ZipVersion;\n}\n\n\n\n\n#ifndef USE_SIOUX\n\n/*\n** Just return the copyright message\n**\n*/\n\nchar *GetZipCopyright(void)\n{\nstatic char CopyR[300];\n\nsstrcpy(CopyR, copyright[0]);\nsstrcat(CopyR, copyright[1]);\nsstrcat(CopyR, \"\\r\\rPlease send bug reports to the authors at\\r\"\\\n              \"Zip-Bugs@lists.wku.edu\");\n\nreturn CopyR;\n}\n\n\n\n\n/*\n** Just return the compilers date/time\n**\n*/\n\nchar *GetZipVersionLocal(void)\n{\nstatic char ZipVersionLocal[50];\n\nsprintf(ZipVersionLocal, \"[%s %s]\", __DATE__, __TIME__);\n\nreturn ZipVersionLocal;\n}\n\n#endif  /*   #ifndef USE_SIOUX  */\n\n\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macstuff.c",
    "content": "/*\nThese Functions were originally part of More Files version 1.4.8\n\nMore Files fixes many of the broken or underfunctional\nparts of the file system.\n\nMore Files\n\nA collection of File Manager and related routines\n\nby Jim Luther (Apple Macintosh Developer Technical Support Emeritus)\nwith significant code contributions by Nitin Ganatra\n(Apple Macintosh Developer Technical Support Emeritus)\nCopyright  1992-1998 Apple Computer, Inc.\nPortions copyright  1995 Jim Luther\nAll rights reserved.\n\nThe Package \"More Files\" is distributed under the following\nlicense terms:\n\n         \"You may incorporate this sample code into your\n          applications without restriction, though the\n          sample code has been provided \"AS IS\" and the\n          responsibility for its operation is 100% yours.\n          However, what you are not permitted to do is to\n          redistribute the source as \"DSC Sample Code\" after\n          having made changes. If you're going to\n          redistribute the source, we require that you make\n          it clear in the source that the code was descended\n          from Apple Sample Code, but that you've made\n          changes.\"\n\n\nThe following changes are made by Info-ZIP:\n\n- The only changes are made by pasting the functions\n  (mostly found in MoreFilesExtras.c / MoreFiles.c)\n  directly into macstuff.c / macstuff.h and slightly\n  reformatting the text (replacement of TABs by spaces,\n  removal/replacement of non-ASCII characters).\n  The code itself is NOT changed.\n\nThis file has been modified by Info-ZIP for use in MacZip.\nThis file is NOT part of the original package More Files.\n\nMore Files can be found on the MetroWerks CD and Developer CD from\nApple. You can also download the latest version from:\n\n    http://members.aol.com/JumpLong/#MoreFiles\n\nJim Luther's Home-page:\n    http://members.aol.com/JumpLong/\n\n\n*/\n\n#include <string.h>\n\n\n#include \"macstuff.h\"\n\n\n\nextern int errno;\n\nstatic  OSErr   GetCommentFromDesktopFile(short vRefNum,\n                                          long dirID,\n                                          ConstStr255Param name,\n                                          Str255 comment);\n\nstatic  OSErr   GetCommentID(short vRefNum,\n                             long dirID,\n                             ConstStr255Param name,\n                             short *commentID);\n\nstatic  OSErr   GetDesktopFileName(short vRefNum,\n                                   Str255 desktopName);\n\n\nenum\n{\n    kBNDLResType    = 'BNDL',\n    kFREFResType    = 'FREF',\n    kIconFamResType = 'ICN#',\n    kFCMTResType    = 'FCMT',\n    kAPPLResType    = 'APPL'\n};\n\n\n/*****************************************************************************/\n\n/*\n**  File Manager FSp calls\n*/\n\n/*****************************************************************************/\n\npascal  OSErr   FSMakeFSSpecCompat(short vRefNum,\n                                   long dirID,\n                                   ConstStr255Param fileName,\n                                   FSSpec *spec)\n{\n    OSErr   result;\n\n#if !__MACOSSEVENORLATER\n    if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )\n    {\n        Boolean isDirectory;\n\n        result = GetObjectLocation(vRefNum, dirID, fileName,\n                                    &(spec->vRefNum), &(spec->parID), spec->name,\n                                    &isDirectory);\n    }\n    else\n#endif  /* !__MACOSSEVENORLATER */\n    {\n     /* Let the file system create the FSSpec if it can since it does the job */\n     /* much more efficiently than I can. */\n        result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);\n\n        /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */\n        /* returned in the parID field when making an FSSpec to the volume's */\n        /* root directory by passing a full pathname in MakeFSSpec's */\n        /* fileName parameter. Fixed in Mac OS 8.1 */\n        if ( (result == noErr) && (spec->parID == 0) )\n            spec->parID = fsRtParID;\n    }\n    return ( result );\n}\n\n\n/*****************************************************************************/\n/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */\n\n#if !__MACOSSEVENORLATER\nstatic  Boolean FSHasFSSpecCalls(void)\n{\n    long            response;\n#if !GENERATENODATA\n    static Boolean  tested = false;\n    static Boolean  result = false;\n#else\n    Boolean result = false;\n#endif\n\n#if !GENERATENODATA\n    if ( !tested )\n    {\n        tested = true;\n#endif\n        if ( Gestalt(gestaltFSAttr, &response) == noErr )\n        {\n            result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);\n        }\n#if !GENERATENODATA\n    }\n#endif\n    return ( result );\n}\n#endif  /* !__MACOSSEVENORLATER */\n\n\n\n/*****************************************************************************/\n/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */\n/* except for FSpExchangeFiles. */\n\n#if !__MACOSSEVENORLATER\nstatic  Boolean QTHasFSSpecCalls(void)\n{\n    long            response;\n#if !GENERATENODATA\n    static Boolean  tested = false;\n    static Boolean  result = false;\n#else\n    Boolean result = false;\n#endif\n\n#if !GENERATENODATA\n    if ( !tested )\n    {\n        tested = true;\n#endif\n        result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);\n#if !GENERATENODATA\n    }\n#endif\n    return ( result );\n}\n#endif  /* !__MACOSSEVENORLATER */\n\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpGetDefaultDir --\n *\n *  This function gets the current default directory.\n *\n * Results:\n *  The provided FSSpec is changed to point to the \"default\"\n *  directory.  The function returns what ever errors\n *  FSMakeFSSpecCompat may encounter.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nint FSpGetDefaultDir(FSSpecPtr dirSpec) /* On return the default directory. */\n{\n    OSErr err;\n    short vRefNum = 0;\n    long int dirID = 0;\n\n    err = HGetVol(NULL, &vRefNum, &dirID);\n\n    if (err == noErr) {\n    err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,\n        dirSpec);\n    }\n\n    return err;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpSetDefaultDir --\n *\n *  This function sets the default directory to the directory\n *  pointed to by the provided FSSpec.\n *\n * Results:\n *  The function returns what ever errors HSetVol may encounter.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nint FSpSetDefaultDir(FSSpecPtr dirSpec) /* The new default directory. */\n{\n    OSErr err;\n\n    /*\n     * The following special case is needed to work around a bug\n     * in the Macintosh OS.  (Acutally PC Exchange.)\n     */\n\n    if (dirSpec->parID == fsRtParID) {\n    err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);\n    } else {\n    err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);\n    }\n\n    return err;\n}\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpFindFolder --\n *\n *  This function is a version of the FindFolder function that\n *  returns the result as a FSSpec rather than a vRefNum and dirID.\n *\n * Results:\n *  Results will be simaler to that of the FindFolder function.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nOSErr\nFSpFindFolder(\n    short vRefNum,      /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec)       /* Pointer to resulting directory. */\n{\n    short foundVRefNum;\n    long foundDirID;\n    OSErr err;\n\n    err = FindFolder(vRefNum, folderType, createFolder,\n        &foundVRefNum, &foundDirID);\n    if (err != noErr) {\n    return err;\n    }\n\n    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, \"\\p\", spec);\n    return err;\n}\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpPathFromLocation --\n *\n *  This function obtains a full path name for a given macintosh\n *  FSSpec.  Unlike the More Files function FSpGetFullPath, this\n *  function will return a C string in the Handle.  It also will\n *  create paths for FSSpec that do not yet exist.\n *\n * Results:\n *  OSErr code.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nOSErr\nFSpPathFromLocation(\n    FSSpec *spec,       /* The location we want a path for. */\n    int *length,        /* Length of the resulting path. */\n    Handle *fullPath)       /* Handle to path. */\n{\n    OSErr err;\n    FSSpec tempSpec;\n    CInfoPBRec pb;\n\n    *fullPath = NULL;\n\n    /*\n     * Make a copy of the input FSSpec that can be modified.\n     */\n    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));\n\n    if (tempSpec.parID == fsRtParID) {\n    /*\n     * The object is a volume.  Add a colon to make it a full\n     * pathname.  Allocate a handle for it and we are done.\n     */\n    tempSpec.name[0] += 2;\n    tempSpec.name[tempSpec.name[0] - 1] = ':';\n    tempSpec.name[tempSpec.name[0]] = '\\0';\n\n    err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);\n    } else {\n    /*\n     * The object isn't a volume.  Is the object a file or a directory?\n     */\n    pb.dirInfo.ioNamePtr = tempSpec.name;\n    pb.dirInfo.ioVRefNum = tempSpec.vRefNum;\n    pb.dirInfo.ioDrDirID = tempSpec.parID;\n    pb.dirInfo.ioFDirIndex = 0;\n    err = PBGetCatInfoSync(&pb);\n\n    if ((err == noErr) || (err == fnfErr)) {\n        /*\n         * If the file doesn't currently exist we start over.  If the\n         * directory exists everything will work just fine.  Otherwise we\n         * will just fail later.  If the object is a directory, append a\n         * colon so full pathname ends with colon.\n         */\n        if (err == fnfErr) {\n        BlockMoveData(spec, &tempSpec, sizeof(FSSpec));\n        } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {\n        tempSpec.name[0] += 1;\n        tempSpec.name[tempSpec.name[0]] = ':';\n        }\n\n        /*\n         * Create a new Handle for the object - make it a C string.\n         */\n        tempSpec.name[0] += 1;\n        tempSpec.name[tempSpec.name[0]] = '\\0';\n        err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);\n        if (err == noErr) {\n        /*\n         * Get the ancestor directory names - loop until we have an\n         * error or find the root directory.\n         */\n        pb.dirInfo.ioNamePtr = tempSpec.name;\n        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;\n        pb.dirInfo.ioDrParID = tempSpec.parID;\n        do {\n            pb.dirInfo.ioFDirIndex = -1;\n            pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;\n            err = PBGetCatInfoSync(&pb);\n            if (err == noErr) {\n            /*\n             * Append colon to directory name and add\n             * directory name to beginning of fullPath.\n             */\n            ++tempSpec.name[0];\n            tempSpec.name[tempSpec.name[0]] = ':';\n\n            (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],\n                tempSpec.name[0]);\n            err = MemError();\n            }\n        } while ( (err == noErr) &&\n            (pb.dirInfo.ioDrDirID != fsRtDirID) );\n        }\n    }\n    }\n\n    /*\n     * On error Dispose the handle, set it to NULL & return the err.\n     * Otherwise, set the length & return.\n     */\n    if (err == noErr) {\n    *length = GetHandleSize(*fullPath) - 1;\n    } else {\n    if ( *fullPath != NULL ) {\n        DisposeHandle(*fullPath);\n    }\n    *fullPath = NULL;\n    *length = 0;\n    }\n\n    return err;\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   FSpGetDirectoryID(const FSSpec *spec,\n                                  long *theDirID,\n                                  Boolean *isDirectory)\n{\n    return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,\n             theDirID, isDirectory) );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   GetDirectoryID(short vRefNum,\n                               long dirID,\n                               ConstStr255Param name,\n                               long *theDirID,\n                               Boolean *isDirectory)\n{\n    CInfoPBRec pb;\n    OSErr error;\n\n    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);\n    if ( error == noErr )\n    {\n        *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;\n        if ( *isDirectory )\n        {\n            *theDirID = pb.dirInfo.ioDrDirID;\n        }\n        else\n        {\n            *theDirID = pb.hFileInfo.ioFlParID;\n        }\n    }\n\n    return ( error );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr GetCatInfoNoName(short vRefNum,\n                               long dirID,\n                               ConstStr255Param name,\n                               CInfoPBPtr pb)\n{\n    Str31 tempName;\n    OSErr error;\n\n    /* Protection against File Sharing problem */\n    if ( (name == NULL) || (name[0] == 0) )\n    {\n        tempName[0] = 0;\n        pb->dirInfo.ioNamePtr = tempName;\n        pb->dirInfo.ioFDirIndex = -1;   /* use ioDirID */\n    }\n    else\n    {\n        pb->dirInfo.ioNamePtr = (StringPtr)name;\n        pb->dirInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */\n    }\n    pb->dirInfo.ioVRefNum = vRefNum;\n    pb->dirInfo.ioDrDirID = dirID;\n    error = PBGetCatInfoSync(pb);\n    pb->dirInfo.ioNamePtr = NULL;\n    return ( error );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   GetObjectLocation(short vRefNum,\n                                  long dirID,\n                                  ConstStr255Param pathname,\n                                  short *realVRefNum,\n                                  long *realParID,\n                                  Str255 realName,\n                                  Boolean *isDirectory)\n{\n    OSErr error;\n    CInfoPBRec pb;\n    Str255 tempPathname;\n\n    /* clear results */\n    *realVRefNum = 0;\n    *realParID = 0;\n    realName[0] = 0;\n\n    /*\n    **  Get the real vRefNum\n    */\n    error = DetermineVRefNum(pathname, vRefNum, realVRefNum);\n    if ( error == noErr )\n    {\n        /*\n        **  Determine if the object already exists and if so,\n        **  get the real parent directory ID if it's a file\n        */\n\n        /* Protection against File Sharing problem */\n        if ( (pathname == NULL) || (pathname[0] == 0) )\n        {\n            tempPathname[0] = 0;\n            pb.hFileInfo.ioNamePtr = tempPathname;\n            pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */\n        }\n        else\n        {\n            pb.hFileInfo.ioNamePtr = (StringPtr)pathname;\n            pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */\n        }\n        pb.hFileInfo.ioVRefNum = vRefNum;\n        pb.hFileInfo.ioDirID = dirID;\n        error = PBGetCatInfoSync(&pb);\n        if ( error == noErr )\n        {\n            /*\n            **  The file system object is present and we have the file's\n            **  real parID\n            */\n\n            /*  Is it a directory or a file? */\n            *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;\n            if ( *isDirectory )\n            {\n                /*\n                **  It's a directory, get its name and parent dirID, and then\n                **  we're done\n                */\n\n                pb.dirInfo.ioNamePtr = realName;\n                pb.dirInfo.ioVRefNum = *realVRefNum;\n                /* pb.dirInfo.ioDrDirID already contains the dirID of the\n                   directory object */\n                pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */\n                error = PBGetCatInfoSync(&pb);\n\n                /* get the parent ID here, because the file system can return the */\n                /* wrong parent ID from the last call. */\n                *realParID = pb.dirInfo.ioDrParID;\n            }\n            else\n            {\n                /*\n                **  It's a file - use the parent directory ID from the last call\n                **  to GetCatInfoparse, get the file name, and then we're done\n                */\n                *realParID = pb.hFileInfo.ioFlParID;\n                error = GetFilenameFromPathname(pathname, realName);\n            }\n        }\n        else if ( error == fnfErr )\n        {\n            /*\n            **  The file system object is not present - see if its parent is present\n            */\n\n            /*\n            **  Parse to get the object name from end of pathname\n            */\n            error = GetFilenameFromPathname(pathname, realName);\n\n            /* if we can't get the object name from the end, we can't continue */\n            if ( error == noErr )\n            {\n                /*\n                **  What we want now is the pathname minus the object name\n                **  for example:\n                **  if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:'\n                **  if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:'\n                **  if pathname is ':dir:file' tempPathname becomes ':dir:'\n                **  if pathname is ':dir:file:' tempPathname becomes ':dir:'\n                **  if pathname is ':file' tempPathname becomes ':'\n                **  if pathname is 'file or file:' tempPathname becomes ''\n                */\n\n                /* get a copy of the pathname */\n                BlockMoveData(pathname, tempPathname, pathname[0] + 1);\n\n                /* remove the object name */\n                tempPathname[0] -= realName[0];\n                /* and the trailing colon (if any) */\n                if ( pathname[pathname[0]] == ':' )\n                {\n                    --tempPathname[0];\n                }\n\n                /* OK, now get the parent's directory ID */\n\n                /* Protection against File Sharing problem */\n                pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname;\n                if ( tempPathname[0] != 0 )\n                {\n                    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */\n                }\n                else\n                {\n                    pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */\n                }\n                pb.hFileInfo.ioVRefNum = vRefNum;\n                pb.hFileInfo.ioDirID = dirID;\n                error = PBGetCatInfoSync(&pb);\n                *realParID = pb.dirInfo.ioDrDirID;\n\n                *isDirectory = false;   /* we don't know what the object is\n                                           really going to be */\n            }\n\n            if ( error != noErr )\n            {\n                error = dirNFErr;   /* couldn't find parent directory */\n            }\n            else\n            {\n                error = fnfErr; /* we found the parent, but not the file */\n            }\n        }\n    }\n\n    return ( error );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   DetermineVRefNum(ConstStr255Param pathname,\n                                 short vRefNum,\n                                 short *realVRefNum)\n{\n    HParamBlockRec pb;\n    OSErr error;\n\n    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);\n    if ( error == noErr )\n    {\n        *realVRefNum = pb.volumeParam.ioVRefNum;\n    }\n    return ( error );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   GetFilenameFromPathname(ConstStr255Param pathname,\n                                        Str255 filename)\n{\n    short   index;\n    short   nameEnd;\n    OSErr   error;\n\n    /* default to no filename */\n    filename[0] = 0;\n\n    /* check for no pathname */\n    if ( pathname != NULL )\n    {\n        /* get string length */\n        index = pathname[0];\n\n        /* check for empty string */\n        if ( index != 0 )\n        {\n            /* skip over last trailing colon (if any) */\n            if ( pathname[index] == ':' )\n            {\n                --index;\n            }\n\n            /* save the end of the string */\n            nameEnd = index;\n\n            /* if pathname ends with multiple colons, then this pathname refers */\n            /* to a directory, not a file */\n            if ( pathname[index] != ':' )\n            {\n                /* parse backwards until we find a colon or hit the beginning\n                   of the pathname */\n                while ( (index != 0) && (pathname[index] != ':') )\n                {\n                    --index;\n                }\n\n                /* if we parsed to the beginning of the pathname and the\n                   pathname ended */\n                /* with a colon, then pathname is a full pathname to a volume,\n                   not a file */\n                if ( (index != 0) || (pathname[pathname[0]] != ':') )\n                {\n                    /* get the filename and return noErr */\n                    filename[0] = (char)(nameEnd - index);\n                    BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index);\n                    error = noErr;\n                }\n                else\n                {\n                    /* pathname to a volume, not a file */\n                    error = notAFileErr;\n                }\n            }\n            else\n            {\n                /* directory, not a file */\n                error = notAFileErr;\n            }\n        }\n        else\n        {\n            /* empty string isn't a file */\n            error = notAFileErr;\n        }\n    }\n    else\n    {\n        /* NULL pathname isn't a file */\n        error = notAFileErr;\n    }\n\n    return ( error );\n}\n\n\n\n/*****************************************************************************/\n\n/*\n**  GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync\n**  in cases where the returned volume name is not needed by the caller.\n**  The pathname and vRefNum parameters are not touched, and the pb\n**  parameter is initialized by PBHGetVInfoSync except that ioNamePtr in\n**  the parameter block is always returned as NULL (since it might point\n**  to the local tempPathname).\n**\n**  I noticed using this code in several places, so here it is once.\n**  This reduces the code size of MoreFiles.\n*/\npascal  OSErr   GetVolumeInfoNoName(ConstStr255Param pathname,\n                                    short vRefNum,\n                                    HParmBlkPtr pb)\n{\n    Str255 tempPathname;\n    OSErr error;\n\n    /* Make sure pb parameter is not NULL */\n    if ( pb != NULL )\n    {\n        pb->volumeParam.ioVRefNum = vRefNum;\n        if ( pathname == NULL )\n        {\n            pb->volumeParam.ioNamePtr = NULL;\n            pb->volumeParam.ioVolIndex = 0;     /* use ioVRefNum only */\n        }\n        else\n        {                                   /* make a copy of the string and */\n            BlockMoveData(pathname, tempPathname, pathname[0] + 1);\n                                    /* use the copy so original isn't trashed */\n            pb->volumeParam.ioNamePtr = (StringPtr)tempPathname;\n                                       /* use ioNamePtr/ioVRefNum combination */\n            pb->volumeParam.ioVolIndex = -1;\n        }\n        error = PBHGetVInfoSync(pb);\n        pb->volumeParam.ioNamePtr = NULL;   /* ioNamePtr may point to local\n                                            tempPathname, so don't return it */\n    }\n    else\n    {\n        error = paramErr;\n    }\n    return ( error );\n}\n\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   FSpGetFullPath(const FSSpec *spec,\n                               short *fullPathLength,\n                               Handle *fullPath)\n{\n    OSErr       result;\n    OSErr       realResult;\n    FSSpec      tempSpec;\n    CInfoPBRec  pb;\n\n    *fullPathLength = 0;\n    *fullPath = NULL;\n\n    /* Default to noErr */\n    realResult = noErr;\n\n    /* Make a copy of the input FSSpec that can be modified */\n    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));\n\n    if ( tempSpec.parID == fsRtParID )\n    {\n        /* The object is a volume */\n\n        /* Add a colon to make it a full pathname */\n        ++tempSpec.name[0];\n        tempSpec.name[tempSpec.name[0]] = ':';\n\n        /* We're done */\n        result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);\n    }\n    else\n    {\n        /* The object isn't a volume */\n\n        /* Is the object a file or a directory? */\n        pb.dirInfo.ioNamePtr = tempSpec.name;\n        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;\n        pb.dirInfo.ioDrDirID = tempSpec.parID;\n        pb.dirInfo.ioFDirIndex = 0;\n        result = PBGetCatInfoSync(&pb);\n        /* Allow file/directory name at end of path to not exist. */\n        realResult = result;\n        if ( (result == noErr) || (result == fnfErr) )\n        {\n            /* if the object is a directory, append a colon so full pathname\n               ends with colon */\n            if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )\n            {\n                ++tempSpec.name[0];\n                tempSpec.name[tempSpec.name[0]] = ':';\n            }\n\n            /* Put the object name in first */\n            result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);\n            if ( result == noErr )\n            {\n                /* Get the ancestor directory names */\n                pb.dirInfo.ioNamePtr = tempSpec.name;\n                pb.dirInfo.ioVRefNum = tempSpec.vRefNum;\n                pb.dirInfo.ioDrParID = tempSpec.parID;\n                do  /* loop until we have an error or find the root directory */\n                {\n                    pb.dirInfo.ioFDirIndex = -1;\n                    pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;\n                    result = PBGetCatInfoSync(&pb);\n                    if ( result == noErr )\n                    {\n                        /* Append colon to directory name */\n                        ++tempSpec.name[0];\n                        tempSpec.name[tempSpec.name[0]] = ':';\n\n                        /* Add directory name to beginning of fullPath */\n                        (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],\n                                      tempSpec.name[0]);\n                        result = MemError();\n                    }\n                } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );\n            }\n        }\n    }\n    if ( result == noErr )\n    {\n        /* Return the length */\n        *fullPathLength = InlineGetHandleSize(*fullPath);\n        result = realResult;    /* return realResult in case it was fnfErr */\n    }\n    else\n    {\n        /* Dispose of the handle and return NULL and zero length */\n        if ( *fullPath != NULL )\n        {\n            DisposeHandle(*fullPath);\n        }\n        *fullPath = NULL;\n        *fullPathLength = 0;\n    }\n\n    return ( result );\n}\n\n\n\n/*****************************************************************************/\n\npascal OSErr FSpLocationFromFullPath(short fullPathLength,\n                                     const void *fullPath,\n                                     FSSpec *spec)\n{\n    AliasHandle alias;\n    OSErr       result;\n    Boolean     wasChanged;\n    Str32       nullString;\n\n    /* Create a minimal alias from the full pathname */\n    nullString[0] = 0;  /* null string to indicate no zone or server name */\n    result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString,\n                                         nullString, &alias);\n\n    if ( result == noErr )\n    {\n        /* Let the Alias Manager resolve the alias. */\n        result = ResolveAlias(NULL, alias, spec, &wasChanged);\n\n        DisposeHandle((Handle)alias);   /* Free up memory used */\n    }\n\n    return ( result );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   GetFullPath(short vRefNum,\n                            long dirID,\n                            ConstStr255Param name,\n                            short *fullPathLength,\n                            Handle *fullPath)\n{\n    OSErr       result;\n    FSSpec      spec;\n\n    *fullPathLength = 0;\n    *fullPath = NULL;\n\n    result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);\n    if ( (result == noErr) || (result == fnfErr) )\n    {\n        result = FSpGetFullPath(&spec, fullPathLength, fullPath);\n    }\n\n    return ( result );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   ChangeCreatorType(short vRefNum,\n                                  long dirID,\n                                  ConstStr255Param name,\n                                  OSType creator,\n                                  OSType fileType)\n{\n    CInfoPBRec pb;\n    OSErr error;\n    short realVRefNum;\n    long parID;\n\n    pb.hFileInfo.ioNamePtr = (StringPtr)name;\n    pb.hFileInfo.ioVRefNum = vRefNum;\n    pb.hFileInfo.ioDirID = dirID;\n    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */\n    error = PBGetCatInfoSync(&pb);\n    if ( error == noErr )\n    {\n        if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 )   /* if file */\n        {                            /* save parent dirID for BumpDate call */\n            parID = pb.hFileInfo.ioFlParID;\n\n            /* If creator not 0x00000000, change creator */\n            if ( creator != (OSType)0x00000000 )\n            {\n                pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;\n            }\n\n            /* If fileType not 0x00000000, change fileType */\n            if ( fileType != (OSType)0x00000000 )\n            {\n                pb.hFileInfo.ioFlFndrInfo.fdType = fileType;\n            }\n\n            pb.hFileInfo.ioDirID = dirID;\n            error = PBSetCatInfoSync(&pb);  /* now, save the new information\n                                               back to disk */\n\n            if ( (error == noErr) && (parID != fsRtParID) ) /* can't\n                                                            bump fsRtParID */\n            {\n                /* get the real vRefNum in case a full pathname was passed */\n                error = DetermineVRefNum(name, vRefNum, &realVRefNum);\n                if ( error == noErr )\n                {\n                    error = BumpDate(realVRefNum, parID, NULL);\n                        /* and bump the parent directory's mod date to wake\n                           up the Finder */\n                        /* to the change we just made */\n                }\n            }\n        }\n        else\n        {\n            /* it was a directory, not a file */\n            error = notAFileErr;\n        }\n    }\n\n    return ( error );\n}\n\n/*****************************************************************************/\n\npascal  OSErr   FSpChangeCreatorType(const FSSpec *spec,\n                                     OSType creator,\n                                     OSType fileType)\n{\n    return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name,\n             creator, fileType) );\n}\n\n/*****************************************************************************/\n\npascal  OSErr   BumpDate(short vRefNum,\n                         long dirID,\n                         ConstStr255Param name)\n/* Given a file or directory, change its modification date to the\n   current date/time. */\n{\n    CInfoPBRec pb;\n    Str31 tempName;\n    OSErr error;\n    unsigned long secs;\n\n    /* Protection against File Sharing problem */\n    if ( (name == NULL) || (name[0] == 0) )\n    {\n        tempName[0] = 0;\n        pb.hFileInfo.ioNamePtr = tempName;\n        pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */\n    }\n    else\n    {\n        pb.hFileInfo.ioNamePtr = (StringPtr)name;\n        pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */\n    }\n    pb.hFileInfo.ioVRefNum = vRefNum;\n    pb.hFileInfo.ioDirID = dirID;\n    error = PBGetCatInfoSync(&pb);\n    if ( error == noErr )\n    {\n        GetDateTime(&secs);\n        /* set mod date to current date, or one second into the future\n            if mod date = current date */\n        pb.hFileInfo.ioFlMdDat =\n                          (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs);\n        if ( pb.dirInfo.ioNamePtr == tempName )\n        {\n            pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID;\n        }\n        else\n        {\n            pb.hFileInfo.ioDirID = dirID;\n        }\n        error = PBSetCatInfoSync(&pb);\n    }\n\n    return ( error );\n}\n\n/*****************************************************************************/\n\npascal  OSErr   FSpBumpDate(const FSSpec *spec)\n{\n    return ( BumpDate(spec->vRefNum, spec->parID, spec->name) );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   OnLine(FSSpecPtr volumes,\n                       short reqVolCount,\n                       short *actVolCount,\n                       short *volIndex)\n{\n    HParamBlockRec pb;\n    OSErr error = noErr;\n    FSSpec *endVolArray;\n\n    if ( *volIndex > 0 )\n    {\n        *actVolCount = 0;\n        for ( endVolArray = volumes + reqVolCount;\n              (volumes < endVolArray) && (error == noErr); ++volumes )\n        {\n            pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name;\n            pb.volumeParam.ioVolIndex = *volIndex;\n            error = PBHGetVInfoSync(&pb);\n            if ( error == noErr )\n            {\n                volumes->parID = fsRtParID;     /* the root directory's\n                                                   parent is 1 */\n                volumes->vRefNum = pb.volumeParam.ioVRefNum;\n                ++*volIndex;\n                ++*actVolCount;\n            }\n        }\n    }\n    else\n    {\n        error = paramErr;\n    }\n\n    return ( error );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   DTGetComment(short vRefNum,\n                             long dirID,\n                             ConstStr255Param name,\n                             Str255 comment)\n{\n    DTPBRec pb;\n    OSErr error;\n    short dtRefNum;\n    Boolean newDTDatabase;\n\n    if (comment != NULL)\n    {\n        comment[0] = 0; /* return nothing by default */\n\n        /* attempt to open the desktop database */\n        error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);\n        if ( error == noErr )\n        {\n            /* There was a desktop database and it's now open */\n\n            if ( !newDTDatabase )\n            {\n                pb.ioDTRefNum = dtRefNum;\n                pb.ioNamePtr = (StringPtr)name;\n                pb.ioDirID = dirID;\n                pb.ioDTBuffer = (Ptr)&comment[1];\n                /*\n                **  IMPORTANT NOTE #1: Inside Macintosh says that comments\n                **  are up to 200 characters. While that may be correct for\n                **  the HFS file system's Desktop Manager, other file\n                **  systems (such as Apple Photo Access) return up to\n                **  255 characters. Make sure the comment buffer is a Str255\n                **  or you'll regret it.\n                **\n                **  IMPORTANT NOTE #2: Although Inside Macintosh doesn't\n                **  mention it, ioDTReqCount is a input field to\n                **  PBDTGetCommentSync. Some file systems (like HFS) ignore\n                **  ioDTReqCount and always return the full comment --\n                **  others (like AppleShare) respect ioDTReqCount and only\n                **  return up to ioDTReqCount characters of the comment.\n                */\n                pb.ioDTReqCount = sizeof(Str255) - 1;\n                error = PBDTGetCommentSync(&pb);\n                if (error == noErr)\n                {\n                    comment[0] = (unsigned char)pb.ioDTActCount;\n                }\n            }\n        }\n        else\n        {\n            /* There is no desktop database - try the Desktop file */\n            error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment);\n            if ( error != noErr )\n            {\n                error = afpItemNotFound;    /* return an expected error */\n            }\n        }\n    }\n    else\n    {\n        error = paramErr;\n    }\n\n    return (error);\n}\n\n/*****************************************************************************/\n\npascal  OSErr   FSpDTGetComment(const FSSpec *spec,\n                              Str255 comment)\n{\n    return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment));\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   DTSetComment(short vRefNum,\n                             long dirID,\n                             ConstStr255Param name,\n                             ConstStr255Param comment)\n{\n    DTPBRec pb;\n    OSErr error;\n    short dtRefNum;\n    Boolean newDTDatabase;\n\n    error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);\n    if ( error == noErr )\n    {\n        pb.ioDTRefNum = dtRefNum;\n        pb.ioNamePtr = (StringPtr)name;\n        pb.ioDirID = dirID;\n        pb.ioDTBuffer = (Ptr)&comment[1];\n        /* Truncate the comment to 200 characters just in case */\n        /* some file system doesn't range check */\n        if ( comment[0] <= 200 )\n        {\n            pb.ioDTReqCount = comment[0];\n        }\n        else\n        {\n            pb.ioDTReqCount = 200;\n        }\n        error = PBDTSetCommentSync(&pb);\n    }\n    return (error);\n}\n\n/*****************************************************************************/\n\npascal  OSErr   FSpDTSetComment(const FSSpec *spec,\n                              ConstStr255Param comment)\n{\n    return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment));\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   DTOpen(ConstStr255Param volName,\n                       short vRefNum,\n                       short *dtRefNum,\n                       Boolean *newDTDatabase)\n{\n    OSErr error;\n    GetVolParmsInfoBuffer volParmsInfo;\n    long infoSize;\n    DTPBRec pb;\n\n    /* Check for volume Desktop Manager support before calling */\n    infoSize = sizeof(GetVolParmsInfoBuffer);\n    error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize);\n    if ( error == noErr )\n    {\n        if ( hasDesktopMgr(volParmsInfo) )\n        {\n            pb.ioNamePtr = (StringPtr)volName;\n            pb.ioVRefNum = vRefNum;\n            error = PBDTOpenInform(&pb);\n            /* PBDTOpenInform informs us if the desktop was just created */\n            /* by leaving the low bit of ioTagInfo clear (0) */\n            *newDTDatabase = ((pb.ioTagInfo & 1L) == 0);\n            if ( error == paramErr )\n            {\n                error = PBDTGetPath(&pb);\n                /* PBDTGetPath doesn't tell us if the database is new */\n                /* so assume it is not new */\n                *newDTDatabase = false;\n            }\n            *dtRefNum = pb.ioDTRefNum;\n        }\n        else\n        {\n            error = paramErr;\n        }\n    }\n    return ( error );\n}\n\n/*****************************************************************************/\n\n/*\n**  GetCommentFromDesktopFile\n**\n**  Get a file or directory's Finder comment field (if any) from the\n**  Desktop file's 'FCMT' resources.\n*/\nstatic  OSErr   GetCommentFromDesktopFile(short vRefNum,\n                                          long dirID,\n                                          ConstStr255Param name,\n                                          Str255 comment)\n{\n    OSErr error;\n    short commentID;\n    short realVRefNum;\n    Str255 desktopName;\n    short savedResFile;\n    short dfRefNum;\n    StringHandle commentHandle;\n\n    /* Get the comment ID number */\n    error = GetCommentID(vRefNum, dirID, name, &commentID);\n    if ( error == noErr )\n    {\n        if ( commentID != 0 )   /* commentID == 0 means there's no comment */\n        {\n            error = DetermineVRefNum(name, vRefNum, &realVRefNum);\n            if ( error == noErr )\n            {\n                error = GetDesktopFileName(realVRefNum, desktopName);\n                if ( error == noErr )\n                {\n                    savedResFile = CurResFile();\n                    /*\n                    **  Open the 'Desktop' file in the root directory. (because\n                    **  opening the resource file could preload unwanted resources,\n                    **  bracket the call with SetResLoad(s))\n                    */\n                    SetResLoad(false);\n                    dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName,\n                                            fsRdPerm);\n                    SetResLoad(true);\n\n                    if ( dfRefNum != -1)\n                    {\n                        /* Get the comment resource */\n                        commentHandle = (StringHandle)Get1Resource(kFCMTResType,\n                                                                   commentID);\n                        if ( commentHandle != NULL )\n                        {\n                            if ( InlineGetHandleSize((Handle)commentHandle) > 0 )\n                            {\n                                BlockMoveData(*commentHandle, comment,\n                                              *commentHandle[0] + 1);\n                            }\n                            else\n                            {                       /* no comment available */\n                                error = afpItemNotFound;\n                            }\n                        }\n                        else\n                        {                           /* no comment available */\n                            error = afpItemNotFound;\n                        }\n\n                        /* restore the resource chain and close\n                           the Desktop file */\n                        UseResFile(savedResFile);\n                        CloseResFile(dfRefNum);\n                    }\n                    else\n                    {\n                        error = afpItemNotFound;\n                    }\n                }\n                else\n                {\n                    error = afpItemNotFound;\n                }\n            }\n        }\n        else\n        {\n            error = afpItemNotFound;    /* no comment available */\n        }\n    }\n\n    return ( error );\n}\n\n/*****************************************************************************/\n\npascal  OSErr   HGetVolParms(ConstStr255Param volName,\n                             short vRefNum,\n                             GetVolParmsInfoBuffer *volParmsInfo,\n                             long *infoSize)\n{\n    HParamBlockRec pb;\n    OSErr error;\n\n    pb.ioParam.ioNamePtr = (StringPtr)volName;\n    pb.ioParam.ioVRefNum = vRefNum;\n    pb.ioParam.ioBuffer = (Ptr)volParmsInfo;\n    pb.ioParam.ioReqCount = *infoSize;\n    error = PBHGetVolParmsSync(&pb);\n    if ( error == noErr )\n    {\n        *infoSize = pb.ioParam.ioActCount;\n    }\n    return ( error );\n}\n\n/*****************************************************************************/\n/*\n**  GetCommentID\n**\n**  Get the comment ID number for the Desktop file's 'FCMT' resource ID from\n**  the file or folders fdComment (frComment) field.\n*/\nstatic  OSErr   GetCommentID(short vRefNum,\n                             long dirID,\n                             ConstStr255Param name,\n                             short *commentID)\n{\n    CInfoPBRec pb;\n    OSErr error;\n\n    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);\n    *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment;\n    return ( error );\n}\n\n/*****************************************************************************/\n\n/*\n**  GetDesktopFileName\n**\n**  Get the name of the Desktop file.\n*/\nstatic  OSErr   GetDesktopFileName(short vRefNum,\n                                   Str255 desktopName)\n{\n    OSErr           error;\n    HParamBlockRec  pb;\n    short           index;\n    Boolean         found;\n\n    pb.fileParam.ioNamePtr = desktopName;\n    pb.fileParam.ioVRefNum = vRefNum;\n    pb.fileParam.ioFVersNum = 0;\n    index = 1;\n    found = false;\n    do\n    {\n        pb.fileParam.ioDirID = fsRtDirID;\n        pb.fileParam.ioFDirIndex = index;\n        error = PBHGetFInfoSync(&pb);\n        if ( error == noErr )\n        {\n            if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') &&\n                 (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') )\n            {\n                found = true;\n            }\n        }\n        ++index;\n    } while ( (error == noErr) && !found );\n\n    return ( error );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   XGetVInfo(short volReference,\n                          StringPtr volName,\n                          short *vRefNum,\n                          UnsignedWide *freeBytes,\n                          UnsignedWide *totalBytes)\n{\n    OSErr           result;\n    long            response;\n    XVolumeParam    pb;\n\n    /* See if large volume support is available */\n    if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) )\n    {\n        /* Large volume support is available */\n        pb.ioVRefNum = volReference;\n        pb.ioNamePtr = volName;\n        pb.ioXVersion = 0;  /* this XVolumeParam version (0) */\n        pb.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */\n        result = PBXGetVolInfoSync(&pb);\n        if ( result == noErr )\n        {\n            /* The volume name was returned in volName (if not NULL) and */\n            /* we have the volume's vRefNum and allocation block size */\n            *vRefNum = pb.ioVRefNum;\n\n            /* return the freeBytes and totalBytes */\n            *totalBytes = pb.ioVTotalBytes;\n            *freeBytes = pb.ioVFreeBytes;\n        }\n    }\n    else\n    {\n        /* No large volume support */\n\n        /* Use HGetVInfo to get the results */\n        result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);\n        if ( result == noErr )\n        {\n            /* zero the high longs of totalBytes and freeBytes */\n            totalBytes->hi = 0;\n            freeBytes->hi = 0;\n        }\n    }\n    return ( result );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   HGetVInfo(short volReference,\n                          StringPtr volName,\n                          short *vRefNum,\n                          unsigned long *freeBytes,\n                          unsigned long *totalBytes)\n{\n    HParamBlockRec  pb;\n    unsigned long   allocationBlockSize;\n    unsigned short  numAllocationBlocks;\n    unsigned short  numFreeBlocks;\n    VCB             *theVCB;\n    Boolean         vcbFound;\n    OSErr           result;\n\n    /* Use the File Manager to get the real vRefNum */\n    pb.volumeParam.ioVRefNum = volReference;\n    pb.volumeParam.ioNamePtr = volName;\n    pb.volumeParam.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */\n    result = PBHGetVInfoSync(&pb);\n\n    if ( result == noErr )\n    {\n        /* The volume name was returned in volName (if not NULL) and */\n        /* we have the volume's vRefNum and allocation block size */\n        *vRefNum = pb.volumeParam.ioVRefNum;\n        allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;\n\n        /* System 7.5 (and beyond) pins the number of allocation blocks and */\n        /* the number of free allocation blocks returned by PBHGetVInfo to */\n        /* a value so that when multiplied by the allocation block size, */\n        /* the volume will look like it has $7fffffff bytes or less. This */\n        /* was done so older applications that use signed math or that use */\n        /* the GetVInfo function (which uses signed math) will continue to work. */\n        /* However, the unpinned numbers (which we want) are always available */\n        /* in the volume's VCB so we'll get those values from the VCB if possible. */\n\n        /* Find the volume's VCB */\n        vcbFound = false;\n        theVCB = (VCB *)(GetVCBQHdr()->qHead);\n        while ( (theVCB != NULL) && !vcbFound )\n        {\n            /* Check VCB signature before using VCB. Don't have to check for */\n            /* MFS (0xd2d7) because they can't get big enough to be pinned */\n            if ( theVCB->vcbSigWord == 0x4244 )\n            {\n                if ( theVCB->vcbVRefNum == *vRefNum )\n                {\n                    vcbFound = true;\n                }\n            }\n\n            if ( !vcbFound )\n            {\n                theVCB = (VCB *)(theVCB->qLink);\n            }\n        }\n\n        if ( theVCB != NULL )\n        {\n            /* Found a VCB we can use. Get the un-pinned number of allocation blocks */\n            /* and the number of free blocks from the VCB. */\n            numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;\n            numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;\n        }\n        else\n        {\n            /* Didn't find a VCB we can use. Return the number of allocation blocks */\n            /* and the number of free blocks returned by PBHGetVInfoSync. */\n            numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;\n            numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;\n        }\n\n        /* Now, calculate freeBytes and totalBytes using unsigned values */\n        *freeBytes = numFreeBlocks * allocationBlockSize;\n        *totalBytes = numAllocationBlocks * allocationBlockSize;\n    }\n\n    return ( result );\n}\n\n\n/*\n**  PBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync\n**  File Manager requests from CFM-based programs. At some point, Apple\n**  will get around to adding this to the standard libraries you link with\n**  and you'll get a duplicate symbol link error. At that time, just delete\n**  this code (or comment it out).\n**\n**  Non-CFM 68K programs don't needs this glue (and won't get it) because\n**  they instead use the inline assembly glue found in the Files.h interface\n**  file.\n*/\n\n#if __WANTPASCALELIMINATION\n#undef  pascal\n#endif\n\n#if GENERATINGCFM\npascal OSErr PBXGetVolInfoSync(XVolumeParamPtr paramBlock)\n{\n    enum\n    {\n        kXGetVolInfoSelector = 0x0012,  /* Selector for XGetVolInfo */\n\n        uppFSDispatchProcInfo = kRegisterBased\n             | REGISTER_RESULT_LOCATION(kRegisterD0)\n             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))\n             | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))  /* trap word */\n             | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long)))  /* selector */\n             | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr)))\n    };\n\n    return ( CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap),\n                                        uppFSDispatchProcInfo,\n                                        _FSDispatch,\n                                        kXGetVolInfoSelector,\n                                        paramBlock) );\n}\n#endif\n\n#if __WANTPASCALELIMINATION\n#define pascal\n#endif\n\n/*****************************************************************************/\n\npascal  OSErr   GetDirName(short vRefNum,\n                           long dirID,\n                           Str31 name)\n{\n    CInfoPBRec pb;\n    OSErr error;\n\n    if ( name != NULL )\n    {\n        pb.dirInfo.ioNamePtr = name;\n        pb.dirInfo.ioVRefNum = vRefNum;\n        pb.dirInfo.ioDrDirID = dirID;\n        pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */\n        error = PBGetCatInfoSync(&pb);\n    }\n    else\n    {\n        error = paramErr;\n    }\n\n    return ( error );\n}\n\n\n/*****************************************************************************/\n\npascal  OSErr   GetVolFileSystemID(ConstStr255Param pathname,\n                                   short vRefNum,\n                                   short *fileSystemID)\n{\n    HParamBlockRec pb;\n    OSErr error;\n\n    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);\n    if ( error == noErr )\n    {\n        *fileSystemID = pb.volumeParam.ioVFSID;\n    }\n\n    return ( error );\n}\n\n/*****************************************************************************/\n\npascal  OSErr GetDInfo(short vRefNum,\n                       long dirID,\n                       ConstStr255Param name,\n                       DInfo *fndrInfo)\n{\n    CInfoPBRec pb;\n    OSErr error;\n\n    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);\n    if ( error == noErr )\n    {\n        if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 )\n        {\n            /* it's a directory, return the DInfo */\n            *fndrInfo = pb.dirInfo.ioDrUsrWds;\n        }\n        else\n        {\n            /* oops, a file was passed */\n            error = dirNFErr;\n        }\n    }\n\n    return ( error );\n}\n\n/*****************************************************************************/\n\npascal  OSErr FSpGetDInfo(const FSSpec *spec,\n                          DInfo *fndrInfo)\n{\n    return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) );\n}\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/macstuff.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _MACSTUFF_H\n#define _MACSTUFF_H     1\n\n#include \"MoreFilesExtras.h\"\n#include \"MoreDesktopMgr.h\"\n#include \"MoreFiles.h\"\n#include \"FSpCompat.h\"\n#include \"FullPath.h\"\n\n#endif               /*  _MACSTUFF_H  */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/mactime.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* -----------------------------------------------------------------------------\n\nThe original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,\nmktime and time do not work correctly. The supplied link library mactime.c\ncontains replacement functions for them.\n\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n\n------------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <time.h>\n#include <OSUtils.h>\n\n#include \"mactime.h\"\n\n\n/*\nThe MacOS function GetDateTime returns  the\nnumber of seconds elapsed since midnight, January 1, 1904.\n*/\nconst unsigned long MacOS_2_Unix = 2082844800L;\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n\n#ifndef TEST_TIME_LIB\n#define my_gmtime    gmtime\n#define my_localtime localtime\n#define my_mktime    mktime\n#define my_time      time\n#endif\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n/* internal prototypes */\nstatic void clear_tm(struct tm * tm);\nstatic long GMTDelta(void);\nstatic Boolean DaylightSaving(void);\nstatic time_t GetTimeMac(void);\nstatic time_t Mactime(time_t *timer);\nstatic void   normalize(int *i,int *j,int norm);\nstatic struct tm *time2tm(const time_t *timer);\nstatic time_t tm2time(struct tm *tp);\n\n/* Because serial port and SLIP conflict with ReadXPram calls,\n   we cache the call here so we don't hang on calling ReadLocation()  */\nstatic void myReadLocation(MachineLocation * loc);\n\n\n/* prototypes for STD lib replacement functions */\nstruct tm *my_gmtime(const time_t *t);\nstruct tm *my_localtime(const time_t *t);\ntime_t my_mktime(struct tm *tp);\ntime_t my_time(time_t *t);\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n /*\n *  Mac file times are based on 1904 Jan 1 00:00 local time,\n *  not 1970 Jan 1 00:00 UTC.\n *  So we have to convert the time stamps into UNIX UTC\n *  compatible values.\n */\ntime_t MacFtime2UnixFtime(unsigned long macftime)\n{\n    long UTCoffset;\n\n    GetGMToffsetMac(macftime, &UTCoffset);\n    MACOS_TO_UNIX(macftime);\n    macftime -= UTCoffset;\n\n    return macftime;\n}\n\n\n /*\n *  Mac file times are based on 1904 Jan 1 00:00 local time,\n *  not 1970 Jan 1 00:00 UTC.\n *  So we have to convert the time stamps into MacOS local\n *  compatible values.\n */\nunsigned long UnixFtime2MacFtime(time_t unxftime)\n{\n    long UTCoffset;\n    unsigned long macftime = unxftime;\n\n    UNIX_TO_MACOS(macftime);\n    GetGMToffsetMac(macftime, &UTCoffset);\n    macftime += UTCoffset;\n\n    return macftime;\n}\n\n\n\n\n\n/*\n* This function convert a file-localtime to an another\n* file-localtime.\n*/\ntime_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)\n{\n    time_t MacGMTTime;\n    long UTCoffset;\n\n    /* convert macloctim into corresponding UTC value */\n    MacGMTTime = macloctim - s_gmtoffs;\n    GetGMToffsetMac(macloctim, &UTCoffset);\n\n    return (MacGMTTime + UTCoffset);\n} /* AdjustForTZmove() */\n\n\n\n\n/*\n * This function calculates the difference between the supplied Mac\n * ftime value (local time) and the corresponding UTC time in seconds.\n */\nBoolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)\n{\n\nmactime = mactime;\n/*\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n May be later I can include a support of GMT offset calculation for the\n time in question here.\n*/\n    *UTCoffset = GMTDelta();\n\n    return true;\n}\n\n\n\n\n\n\n\n/*****************************************************************************\n *  Standard Library Replacement Functions\n *  gmtime(), mktime(), localtime(), time()\n *\n *  The unix epoch is used here.\n *  These functions gmtime(), mktime(), localtime() and time()\n *  expects and returns unix times.\n *\n * At midnight Jan. 1, 1970 GMT, the local time was\n *    midnight Jan. 1, 1970 + GMTDelta().\n *\n *\n *****************************************************************************/\n\n\nstruct tm *my_gmtime(const time_t *timer)\n{\n    return time2tm(timer);\n}\n\n\n\n\nstruct tm *my_localtime(const time_t *timer)\n{\n    time_t maclocal;\n\n    maclocal = *timer;\n    maclocal += GMTDelta();\n\n    return time2tm(&maclocal);\n}\n\n\n\n\ntime_t my_mktime(struct tm *tp)\n{\n    time_t maclocal;\n\n    maclocal = tm2time(tp);\n    maclocal -= GMTDelta();\n\n    return maclocal;\n}\n\n\n\n\n\n\ntime_t my_time(time_t *time)\n{\ntime_t tmp_time;\n\nGetDateTime(&tmp_time);\n\nMACOS_TO_UNIX(tmp_time);\n\nif (time)\n    {\n    *time = tmp_time;\n    }\n\nreturn tmp_time;\n}\n\n\n\n/*****************************************************************************/\n/*  static module level functions\n/*****************************************************************************/\n\n\n/*\n * The geographic location and time zone information of a Mac\n * are stored in extended parameter RAM.  The ReadLocation\n * produdure uses the geographic location record, MachineLocation,\n * to read the geographic location and time zone information in\n * extended parameter RAM.\n *\n * Because serial port and SLIP conflict with ReadXPram calls,\n * we cache the call here.\n *\n * Caveat: this caching will give the wrong result if a session\n * extend across the DST changeover time, but\n * this function resets itself every 2 hours.\n */\nstatic void myReadLocation(MachineLocation * loc)\n{\n    static MachineLocation storedLoc;   /* InsideMac, OSUtilities, page 4-20  */\n    static time_t first_call = 0, last_call = 86400;\n\n    if ((last_call - first_call) > 7200)\n        {\n        GetDateTime(&first_call);\n        ReadLocation(&storedLoc);\n        }\n\n    GetDateTime(&last_call);\n    *loc = storedLoc;\n}\n\n\n\n\nstatic Boolean DaylightSaving(void)\n{\n    MachineLocation loc;\n    unsigned char dlsDelta;\n\n    myReadLocation(&loc);\n    dlsDelta =  loc.u.dlsDelta;\n\n    return (dlsDelta != 0);\n}\n\n\n\n\n/* current local time = GMTDelta() + GMT\n   GMT = local time - GMTDelta()    */\nstatic long GMTDelta(void)\n{\n    MachineLocation loc;\n    long gmtDelta;\n\n    myReadLocation(&loc);\n\n    /*\n     * On a Mac, the GMT value is in seconds east of GMT.  For example,\n     * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)\n     * east of GMT.  The gmtDelta field is a 3-byte value contained in a\n     * long word, so you must take care to get it properly.\n     */\n    gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;\n    if ((gmtDelta & 0x00800000) != 0)\n        {\n        gmtDelta |= 0xFF000000;\n        }\n\n    return gmtDelta;\n}\n\n\n\n/* This routine simulates stdclib time(), time in seconds since 1.1.1970\n   The time is in GMT  */\nstatic time_t GetTimeMac(void)\n{\n    unsigned long maclocal;\n\n\n    /*\n     * Get the current time expressed as the number of seconds\n     * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).\n     * On a Mac, current time accuracy is up to a second.\n     */\n\n    GetDateTime(&maclocal);     /* Get Mac local time  */\n    maclocal -= GMTDelta();     /* Get Mac GMT  */\n    MACOS_TO_UNIX(maclocal);\n\n    return maclocal;            /* return unix GMT  */\n}\n\n\n\n\n/*\n *  clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00\n */\n\nstatic void clear_tm(struct tm * tm)\n{\n    tm->tm_sec   =  0;\n    tm->tm_min   =  0;\n    tm->tm_hour  =  0;\n    tm->tm_mday  =  1;\n    tm->tm_mon   =  0;\n    tm->tm_year  =  0;\n    tm->tm_wday  =  1;\n    tm->tm_yday  =  0;\n    tm->tm_isdst = -1;\n}\n\n\nstatic void normalize(int *i,int *j,int norm)\n{\n  while(*i < 0)\n    {\n    *i += norm;\n    (*j)--;\n    }\n\n  while(*i >= norm)\n    {\n    *i -= norm;\n    (*j)++;\n    }\n}\n\n\n\n/*  Returns the GMT times  */\nstatic time_t Mactime(time_t *timer)\n{\n    time_t t = GetTimeMac();\n\n    if (timer != NULL)\n        *timer = t;\n\n    return t;\n}\n\n\n\n\nstatic struct tm *time2tm(const time_t *timer)\n{\n    DateTimeRec dtr;\n    MachineLocation loc;\n    time_t macLocal = *timer;\n\n    static struct tm statictime;\n    static const short monthday[12] =\n        {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};\n\n    UNIX_TO_MACOS(macLocal);\n    SecondsToDate(macLocal, &dtr);\n\n    statictime.tm_sec  = dtr.second;         /* second, from 0 to 59 */\n    statictime.tm_min  = dtr.minute;         /* minute, from 0 to 59 */\n    statictime.tm_hour = dtr.hour;           /* hour, from 0 to 23 */\n    statictime.tm_mday = dtr.day;            /* day of the month, from 1 to 31 */\n    statictime.tm_mon  = dtr.month     - 1;  /* month, 1= January and 12 = December */\n    statictime.tm_year = dtr.year   - 1900;  /* year, ranging from 1904 to 2040 */\n    statictime.tm_wday = dtr.dayOfWeek - 1;  /* day of the week, 1 = Sun, 7 = Sat */\n\n    statictime.tm_yday = monthday[statictime.tm_mon]\n                         + statictime.tm_mday - 1;\n\n    if (2 < statictime.tm_mon && !(statictime.tm_year & 3))\n        {\n        ++statictime.tm_yday;\n        }\n\n    myReadLocation(&loc);\n    statictime.tm_isdst = DaylightSaving();\n\n    return(&statictime);\n}\n\n\n\n\n\nstatic time_t tm2time(struct tm *tp)\n{\ntime_t intMacTime;\nDateTimeRec  dtr;\n\n normalize(&tp->tm_sec, &tp->tm_min, 60);\n normalize(&tp->tm_min, &tp->tm_hour,60);\n normalize(&tp->tm_hour,&tp->tm_mday,24);\n normalize(&tp->tm_mon, &tp->tm_year,12);\n\n dtr.year    = tp->tm_year + 1900;  /* years since 1900 */\n dtr.month   = tp->tm_mon  +    1;  /* month, 0 = January and 11 = December */\n dtr.day     = tp->tm_mday;         /* day of the month, from 1 to 31 */\n dtr.hour    = tp->tm_hour;         /* hour, from 0 to 23 */\n dtr.minute  = tp->tm_min;          /* minute, from 0 to 59 */\n dtr.second  = tp->tm_sec;          /* second, from 0 to 59 */\n\n DateToSeconds(&dtr, &intMacTime);\n\n MACOS_TO_UNIX(intMacTime);\n\n return intMacTime;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/mactime.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _MACTIME_H_\n#define _MACTIME_H_\n/* -----------------------------------------------------------------------------\n\nThe original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,\nmktime and time do not work correctly. The supplied link library mactime.c\ncontains replacement functions for them.\n\n *     Caveat: On a Mac, we only know the GMT and DST offsets for\n *     the current time, not for the time in question.\n *     Mac has no support for DST handling.\n *     DST changeover is all manually set by the user.\n\n\n------------------------------------------------------------------------------*/\n\n#include <time.h>\n#include <mactypes.h>\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n\n  /*\n   * ARGH.  Mac times are based on 1904 Jan 1 00:00, not 1970 Jan 1 00:00.\n   *  So we have to diddle time_t's appropriately:  add or subtract 66 years'\n   *  worth of seconds == number of days times 86400 == (66*365 regular days +\n   *  17 leap days ) * 86400 == (24090 + 17) * 86400 == 2082844800L seconds.\n   *  We hope time_t is an unsigned long (ulg) on the Macintosh...\n   */\n/*\nThis Offset is only used by MacFileDate_to_UTime()\n*/\n\n#define MACOS_TO_UNIX(x)  (x) -= (unsigned long)MacOS_2_Unix\n#define UNIX_TO_MACOS(x)  (x) += (unsigned long)MacOS_2_Unix\n\n/*\nThe MacOS function GetDateTime returns  the\nnumber of seconds elapsed since midnight, January 1, 1904.\n*/\nextern const unsigned long MacOS_2_Unix;\n\n\n/* prototypes for public utility functions */\ntime_t MacFtime2UnixFtime(unsigned long macftime);\nunsigned long UnixFtime2MacFtime(time_t unxftime);\ntime_t  AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs);\nBoolean GetGMToffsetMac(unsigned long macftime, long *UTCoffset);\n\n\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/pathname.c",
    "content": "/*\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  pathname.c\n\n  Function dealing with the pathname. Mostly C-string work.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <string.h>\n#include <stdio.h>\n#include <unistd.h>\n#include <sound.h>\n\n#include \"pathname.h\"\n#include \"helpers.h\"\n#include \"macstuff.h\"\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nconst char  ResourceMark[] = \"XtraStuf.mac:\";  /* see also macos.c */\n\n\n#include \"zip.h\"\n\n\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n/*\n *----------------------------------------------------------------------\n *\n * FSpFindFolder --\n *\n *  This function is a version of the FindFolder function that\n *  returns the result as a FSSpec rather than a vRefNum and dirID.\n *\n * Results:\n *  Results will be simaler to that of the FindFolder function.\n *\n * Side effects:\n *  None.\n *\n *----------------------------------------------------------------------\n */\n\nOSErr\nFSpFindFolder(\n    short vRefNum,      /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec)       /* Pointer to resulting directory. */\n{\n    short foundVRefNum;\n    long foundDirID;\n    OSErr err;\n\n    err = FindFolder(vRefNum, folderType, createFolder,\n        &foundVRefNum, &foundDirID);\n    if (err != noErr) {\n    return err;\n    }\n\n    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, \"\\p\", spec);\n    return err;\n}\n\n\n/*\n**  return volumename from pathname\n**\n*/\n\nunsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)\n{\nconst char *VolEnd, *tmpPtr1;\nchar *tmpPtr2 = VolumeName;\n\nAssertStr(FullPath,\"GetVolumeFromPath\")\n\nfor (VolEnd = FullPath; *VolEnd != '\\0' && *VolEnd != ':'; VolEnd++)\n      ;\nif (*VolEnd == '\\0') return 0;\n\nfor (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)\n    {\n    *tmpPtr2++ = *tmpPtr1++;\n    }\n\n*tmpPtr2 = '\\0';\n\nreturn (unsigned short) strlen(VolumeName);\n}\n\n\n\n/***********************************/\n/* Function FindNewExtractFolder() */\n/***********************************/\n\nchar *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder)\n{\nchar buffer[NAME_MAX], *tmpPtr, *namePtr;\nchar *last_dotpos         = ExtractPath;\nshort count = 0, folderCount = 0;\nOSErr err;\nFSSpec Spec;\nlong theDirID;\nBoolean isDirectory;\nunsigned short namelen, pathlen = strlen(ExtractPath);\nunsigned long ext_length  = 0;\nunsigned long num_to_cut  = 0;\nlong firstpart_length = pathlen;\n\nAssertStr(ExtractPath,\"FindNewExtractFolder ExtractPath == NULL\")\n\nfor (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        {\n        folderCount++;\n        namePtr = tmpPtr;\n        }\n\nif (folderCount > 1) {\n    namelen = strlen(namePtr);\n} else {\n    namelen = strlen(ExtractPath);\n}\n\nif (uniqueFolder) {\n    for (count = 0; count < 99; count++)\n        {\n        memset(buffer,0,sizeof(buffer));\n\n        if (namelen >= 28)\n            ExtractPath[pathlen-2] = 0x0;\n        else\n            ExtractPath[pathlen-1] = 0x0;\n\n        sprintf(buffer,\"%s%d\",ExtractPath,count);\n        GetCompletePath(ExtractPath, buffer, &Spec,&err);\n        err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);\n        if (err == -43) break;\n        }\n} else {\n    /* Look for the last extension pos */\n    for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)\n        if (*tmpPtr == '.') last_dotpos = tmpPtr;\n\n    ext_length = strlen(last_dotpos);\n\n    if (ext_length < 6) {  /* up to 5 chars are treated as a */\n                           /* normal extension like \".html\" or \".class\"  */\n        int nameLength = last_dotpos - ExtractPath;\n        if (nameLength > 1) {\n            ExtractPath[nameLength] = 0x0;\n        } else {\n            ExtractPath[pathlen-1] = 0x0;\n        }\n    } else {\n        ExtractPath[pathlen-1] = 0x0;\n    }\n\n    GetCompletePath(ExtractPath, ExtractPath, &Spec,&err);\n}\n\n/* Foldernames must always end with a colon  */\nsstrcat(ExtractPath,\":\");\nreturn ExtractPath;\n}\n\n\n\n/*\n**  creates an archive file name\n**\n*/\n\nvoid createArchiveName(char *thePath)\n{\nchar *tmpPtr, *namePtr;\nshort folderCount = 0;\nunsigned short namelen, pathlen = strlen(thePath);\n\nif (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;\n\nfor (tmpPtr = thePath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        {\n        folderCount++;\n        namePtr = tmpPtr;\n        }\n\nnamelen = strlen(namePtr);\n\n    /* we have to eliminate illegal chars:\n     * The name space for Mac filenames and Zip filenames (unix style names)\n     * do both include all printable extended-ASCII characters.  The only\n     * difference we have to take care of is the single special character\n     * used as path delimiter:\n     * ':' on MacOS and '/' on Unix and '\\\\' on Dos.\n     * So, to convert between Mac filenames and Unix filenames without any\n     * loss of information, we simply interchange ':' and '/'.  Additionally,\n     * we try to convert the coding of the extended-ASCII characters into\n     * InfoZip's standard ISO 8859-1 codepage table.\n     */\n  MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);\n\n /* Avoid filenames like: \"Archive..zip\"  */\nif (thePath[pathlen-1] == '.')\n    {\n    thePath[pathlen-1] = 0;\n    }\n\nif (folderCount >= 1)\n    { /* path contains at least one folder */\n\n    if (namelen >= 28)\n        {\n        pathlen = pathlen-4;\n        }\n\n    thePath[pathlen]   = '.';\n    thePath[pathlen+1] = 'z';\n    thePath[pathlen+2] = 'i';\n    thePath[pathlen+3] = 'p';\n    thePath[pathlen+4] = 0x0;\n    return;\n    }\nelse\n    {  /* path contains no folder */\n    FindDesktopFolder(thePath);\n    createArchiveName(thePath);\n    }\n}\n\n\n\n/*\n** finds the desktop-folder on a volume with\n** largest amount of free-space.\n*/\n\nvoid FindDesktopFolder(char *Path)\n{\nchar buffer[255];\nFSSpec  volumes[50];        /* 50 Volumes should be enough */\nshort   actVolCount, volIndex = 1, VolCount = 0;\nOSErr   err;\nshort     i, foundVRefNum;\nFSSpec spec;\nUInt64 freeBytes;\nUInt64 totalBytes;\nUInt64 MaxFreeBytes;\n\nerr = OnLine(volumes, 50, &actVolCount, &volIndex);\nprinterr(\"OnLine:\", (err != -35) && (err != 0), err, __LINE__, __FILE__, \"\");\n\nMaxFreeBytes = 0;\n\nfor (i=0; i < actVolCount; i++)\n    {\n    XGetVInfo(volumes[i].vRefNum,\n              volumes[i].name,\n              &volumes[i].vRefNum,\n              &freeBytes,\n              &totalBytes);\n\n    if (MaxFreeBytes < freeBytes) {\n        MaxFreeBytes = freeBytes;\n        foundVRefNum = volumes[i].vRefNum;\n    }\n\n    if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) {\n        MaxFreeBytes = freeBytes;\n        foundVRefNum = volumes[i].vRefNum;\n    }\n\n}\n\n FSpFindFolder(foundVRefNum, kDesktopFolderType,\n            kDontCreateFolder,&spec);\n\n GetFullPathFromSpec(buffer, &spec , &err);\n sstrcat(buffer,Path);\n sstrcpy(Path,buffer);\n}\n\n\n/*\n**  return the path without the filename\n**\n*/\n\nchar *TruncFilename(char *DirPath, const char *FilePath)\n{\nchar *tmpPtr;\nchar *dirPtr = NULL;\n\nAssertStr(DirPath,\"TruncFilename\")\nAssert_it(Spec,\"TruncFilename\",\"\")\n\nsstrcpy(DirPath, FilePath);\n\nfor (tmpPtr = DirPath; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':')\n        dirPtr = tmpPtr;\n\nif (dirPtr)\n    *++dirPtr = '\\0';\nelse\n    printerr(\"TruncFilename: FilePath has no Folders\", -1,\n         -1, __LINE__, __FILE__, FilePath);\n\nreturn DirPath;\n}\n\n\n\n/*\n**  return only filename\n**\n*/\n\nchar *GetFilename(char *FileName, const char *FilePath)\n{\nconst char *tmpPtr;\nconst char *dirPtr = NULL;\n\nAssert_it(FileName,\"GetFilename\",\"\")\nAssert_it(FilePath,\"GetFilename\",\"\")\n\nfor (tmpPtr = FilePath; *tmpPtr; tmpPtr++)\n    {\n    if (*tmpPtr == ':')\n        {\n        dirPtr = tmpPtr;\n        }\n    }\n\nif (dirPtr)\n    {\n    ++dirPtr;  /* jump over the ':' */\n    }\nelse\n    {\n    return strcpy(FileName, FilePath); /* FilePath has no Folders */\n    }\n\nreturn strcpy(FileName, dirPtr);\n}\n\n\n\n/*\n**  return fullpathname from folder/dir-id\n**\n*/\n\nchar *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,\n                        ConstStr255Param name, OSErr *err)\n{\nFSSpec      spec;\n\n    *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);\n    printerr(\"FSMakeFSSpecCompat:\", (*err != -43) && (*err != 0), *err,\n             __LINE__, __FILE__, \"\");\n    if ( (*err == noErr) || (*err == fnfErr) )\n        {\n        return GetFullPathFromSpec(CompletePath, &spec, err);\n        }\n\nreturn NULL;\n}\n\n\n\n/*\n**  convert real-filename to archive-filename\n**\n*/\n\nchar *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,\n                    short CurrentFork, short MacZipMode, Boolean DataForkOnly)\n{\n\nAssertStr(RealPath,\"Real2RfDfFilen\")\nAssertStr(RfDfFilen,\"Real2RfDfFilen\")\n\nif (DataForkOnly) /* make no changes */\n    {\n    return sstrcpy(RfDfFilen, RealPath);\n    }\n\nswitch (MacZipMode)\n    {\n    case JohnnyLee_EF:\n        {\n        sstrcpy(RfDfFilen, RealPath);\n        if (CurrentFork == DataFork)            /* data-fork  */\n            return sstrcat(RfDfFilen, \"d\");\n        if (CurrentFork == ResourceFork)        /* resource-fork */\n            return sstrcat(RfDfFilen, \"r\");\n        break;\n        }\n\n    case NewZipMode_EF:\n        {\n        switch (CurrentFork)\n            {\n            case DataFork:\n                {\n                sstrcpy(RfDfFilen, RealPath);\n                return RfDfFilen;  /* data-fork  */\n                break;\n                }\n            case ResourceFork:\n                {\n                sstrcpy(RfDfFilen, ResourceMark);\n                sstrcat(RfDfFilen, RealPath);  /* resource-fork */\n                return RfDfFilen;\n                break;\n                }\n            default:\n                {\n                printerr(\"Real2RfDfFilen:\", -1, -1,\n                         __LINE__, __FILE__, RealPath);\n                return NULL;  /* function should never reach this point */\n                }\n            }\n        break;\n        }\n    default:\n        {\n        printerr(\"Real2RfDfFilen:\", -1, -1, __LINE__, __FILE__, RealPath);\n        return NULL;  /* function should never reach this point */\n        }\n    }\n\nprinterr(\"Real2RfDfFilen:\", -1, -1, __LINE__, __FILE__, RealPath);\nreturn NULL;  /* function should never come reach this point */\n}\n\n\n\n/*\n**  convert archive-filename into a real filename\n**\n*/\n\nchar *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,\n                     Boolean DataForkOnly, short *CurrentFork)\n{\nshort   length;\nint     result;\n\nAssertStr(RfDfFilen,\"RfDfFilen2Real\")\n\nif (DataForkOnly ||\n    (MacZipMode == UnKnown_EF) ||\n    (MacZipMode < JohnnyLee_EF))\n    {\n    *CurrentFork = DataFork;\n    return sstrcpy(RealFn,RfDfFilen);\n    }\n\nresult = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);\nif (result == 0)\n    {\n    MacZipMode = NewZipMode_EF;\n    }\n\nswitch (MacZipMode)\n    {\n    case JohnnyLee_EF:\n        {\n        sstrcpy(RealFn, RfDfFilen);\n        length = strlen(RealFn);       /* determine Fork type */\n        if (RealFn[length-1] == 'd') *CurrentFork = DataFork;\n        else *CurrentFork = ResourceFork;\n        RealFn[length-1] = '\\0';       /* simply cut one char  */\n        return RealFn;\n        break;\n        }\n\n    case NewZipMode_EF:\n        {                                   /* determine Fork type */\n        result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);\n        if (result != 0)\n            {\n            *CurrentFork = DataFork;\n            sstrcpy(RealFn, RfDfFilen);\n            return RealFn;  /* data-fork  */\n            }\n        else\n            {\n            *CurrentFork = ResourceFork;\n            if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))\n                {\n                sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);\n                }\n            else RealFn[0] = '\\0';\n            return RealFn;  /* resource-fork */\n            }\n        break;\n        }\n    default:\n        {\n        *CurrentFork = NoFork;\n        printerr(\"RfDfFilen2Real():\", -1, MacZipMode,\n                 __LINE__, __FILE__, RfDfFilen);\n        return NULL;  /* function should never reach this point */\n        }\n    }\n\nprinterr(\"RfDfFilen2Real():\", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);\nreturn NULL;  /* function should never reach this point */\n}\n\n\n\n/*\n**  return the applications name (argv[0])\n**\n*/\n\nchar *GetAppName(void)\n{\nProcessSerialNumber psn;\nstatic Str255       AppName;\nProcessInfoRec      pinfo;\nOSErr               err;\n\nGetCurrentProcess(&psn);\npinfo.processName = AppName;\npinfo.processInfoLength = sizeof(pinfo);\npinfo.processAppSpec = NULL;\n\nerr = GetProcessInformation(&psn,&pinfo);\nAppName[AppName[0]+1] = 0x00;\n\nreturn (char *)&AppName[1];\n}\n\n\n\n/*\n**  return fullpathname from FSSpec\n**\n*/\n\nchar *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)\n{\nHandle hFullPath;\nshort len;\n\nAssert_it(Spec,\"GetFullPathFromSpec\",\"\")\n\n*err = FSpGetFullPath(Spec, &len, &hFullPath);\nprinterr(\"FSpGetFullPath:\", (*err != -43) && (*err != 0), *err,\n         __LINE__, __FILE__, \"\");\n\nmemmove(FullPath, (Handle) *hFullPath, len);\nFullPath[len] = '\\0';  /* make c-string */\n\nDisposeHandle((Handle)hFullPath);   /* we don't need it any more */\n\nprinterr(\"Warning path length exceeds limit: \", len >= NAME_MAX, len,\n         __LINE__, __FILE__, \" chars \");\n\nreturn FullPath;\n}\n\n\n\n\n/*\n* This function expands a given partial path to a complete path.\n* Path expansions are relative to the running app.\n* This function follows the notation:\n*   1. relative path:\n*       a: \":subfolder:filename\"    -> \":current folder:subfolder:filename\"\n*       b: \"::folder2:filename\"     -> folder2 is beside the current\n*                                      folder on the same level\n*       c: \"filename\"               -> in current folder\n*\n* An absolute path will be returned.\n\nThe following characteristics of Macintosh pathnames should be noted:\n\n       A full pathname never begins with a colon, but must contain at\n       least one colon.\n       A partial pathname always begins with a colon separator except in\n       the case where the file partial pathname is a simple file or\n       directory name.\n       Single trailing separator colons in full or partial pathnames are\n       ignored except in the case of full pathnames to volumes.\n       In full pathnames to volumes, the trailing separator colon is required.\n       Consecutive separator colons can be used to ascend a level from a\n       directory to its parent directory. Two consecutive separator colons\n       will ascend one level, three consecutive separator colons will ascend\n       two levels, and so on. Ascending can only occur from a directory;\n       not a file.\n*/\n\nchar *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,\n                      OSErr *err)\n{\nBoolean hasDirName = false;\nchar currentdir[NAME_MAX];\nchar *tmpPtr;\nunsigned short pathlen;\n\nAssertStr(name,\"GetCompletePath\")\nAssert_it(Spec,\"GetCompletePath\",\"\")\nAssert_it((CompletePath != name),\"GetCompletePath\",\"\")\n\nfor (tmpPtr = name; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == ':') hasDirName = true;\n\nif (name[0] != ':')   /* case c: path including volume name or only filename */\n    {\n    if (hasDirName)\n        {   /* okey, starts with volume name, so it must be a complete path */\n        sstrcpy(CompletePath, name);\n        }\n    else\n        {   /* only filename: add cwd and return */\n        getcwd(currentdir, NAME_MAX);\n        sstrcat(currentdir, name);\n        sstrcpy(CompletePath, currentdir);\n        }\n    }\nelse if (name[1] == ':')    /* it's case b: \"::folder2:filename\"  */\n    {\n    printerr(\"GetCompletePath \", -1, *err, __LINE__, __FILE__, \"not implemented\");\n            /* it's not yet implemented; do we really need this case ?*/\n    return NULL;\n    }\nelse                        /* it's case a: \":subfolder:filename\" */\n    {\n    getcwd(CompletePath, NAME_MAX);     /* we don't need a second colon */\n    CompletePath[strlen(CompletePath)-1] = '\\0';\n    sstrcat(CompletePath, name);\n    }\n\npathlen = strlen(CompletePath);\n*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);\n\nreturn CompletePath;\n}\n\n\n\nchar *MakeFilenameShorter(const char *LongFilename)\n{\nstatic char filename[35];  /* contents should be never longer than 32 chars */\nstatic unsigned char Num = 0; /* change the number for every call */\n                              /* this var will rollover without a problem */\nchar tempLongFilename[1024], charnum[5];\nchar *last_dotpos         = tempLongFilename;\nunsigned long full_length = strlen(LongFilename);\nunsigned long ext_length  = 0;\nunsigned long num_to_cut  = 0;\nlong firstpart_length;\nchar *tmpPtr;\nshort MaxLength = 31;\n\nif (full_length <= MaxLength) /* filename is not long */\n    {\n    return strcpy(filename,LongFilename);\n    }\n\nNum++;\nstrcpy(tempLongFilename,LongFilename);\n\n/* Look for the last extension pos */\nfor (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)\n    if (*tmpPtr == '.') last_dotpos = tmpPtr;\n\next_length = strlen(last_dotpos);\nfirstpart_length = last_dotpos - tempLongFilename;\n\nif (ext_length > 6)  /* up to 5 chars are treated as a */\n    {                /* normal extension like \".html\" or \".class\"  */\n    firstpart_length = 0;\n    }\n\nnum_to_cut = full_length - MaxLength;\n\n/* number the files to make the names unique */\nsprintf(charnum,\"~%x\", Num);\nnum_to_cut += strlen(charnum);\n\nif (firstpart_length == 0)\n    {\n    firstpart_length = full_length;\n    tempLongFilename[firstpart_length - num_to_cut] = 0;\n    sprintf(filename,\"%s%s\", tempLongFilename, charnum);\n    }\nelse\n    {\n    tempLongFilename[firstpart_length - num_to_cut] = 0;\n    sprintf(filename,\"%s%s%s\", tempLongFilename, charnum, last_dotpos);\n    }\n\nreturn filename;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/pathname.h",
    "content": "/*\n  Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef PATHNAME_H\n#define PATHNAME_H 1\n\n\nchar *StripPartialDir(char *CompletePath,\n                      const char *PartialPath, const char *FullPath);\n\nchar *Real2RfDfFilen(char *RfDfFilen, const char *RealPath, short CurrentFork,\n                     short MacZipMode, Boolean DataForkOnly);\nchar *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,\n                     Boolean DataForkOnly, short *CurrentFork);\n\nunsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName);\nchar *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,\n                      OSErr *err);\nchar *TruncFilename(char *DirPath, const char *FilePath);\nchar *GetFilename(char *CompletePath, const char *name);\nchar *GetFullPathFromSpec(char *CompletePath, FSSpec *Spec, OSErr *err);\nchar *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,\n                        ConstStr255Param name, OSErr *err);\n\nchar *GetAppName(void);\nvoid createArchiveName(char *Path);\nvoid FindDesktopFolder(char *Path);\nchar *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder);\nOSErr FSpFindFolder(\n    short vRefNum,          /* Volume reference number. */\n    OSType folderType,      /* Folder type taken by FindFolder. */\n    Boolean createFolder,   /* Should we create it if non-existant. */\n    FSSpec *spec);          /* Pointer to resulting directory. */\n\nchar *MakeFilenameShorter(const char *LongFilename);\n\n/*\nRule: UnKnown_EF should always be zero.\n      JohnnyLee_EF, NewZipMode_EF should always greater than all\n      other definitions\n*/\n#define UnKnown_EF           0\n#define TomBrownZipIt1_EF   10\n#define TomBrownZipIt2_EF   20\n#define JohnnyLee_EF        30\n#define NewZipMode_EF       40\n\n\n\n#define ResourceFork    -1\n#define DataFork        1\n#define NoFork          0\n\n\n#ifndef NAME_MAX\n#define NAME_MAX    1024\n#endif\n\n#endif   /*  PATHNAME_H  */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/recurse.c",
    "content": "/*\nThese functions are based on Jim Luther's IterateDirectory() found in MoreFiles\nHowever, it's heavily modified by Dirk Haase\n*/\n\n/*\n**  IterateDirectory: File Manager directory iterator routines.\n**\n**  by Jim Luther\n**\n**  File:       IterateDirectory.c\n**\n**  Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.\n**  All rights reserved.\n**\n**  You may incorporate this sample code into your applications without\n**  restriction, though the sample code has been provided \"AS IS\" and the\n**  responsibility for its operation is 100% yours.\n**\n**  IterateDirectory is designed to drop into the MoreFiles sample code\n**  library I wrote while in Apple Developer Technical Support\n*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include <Types.h>\n#include <Errors.h>\n#include <Files.h>\n#include <stdio.h>\n#include <string.h>\n\n\n#include \"zip.h\"\n#include \"macstuff.h\"\n#include \"helpers.h\"\n#include \"recurse.h\"\n#include \"macglob.h\"\n#include \"pathname.h\"\n\n\n\n\n/*****************************************************************************/\n/*  Macros, typedefs                                                         */\n/*****************************************************************************/\n\n/* The RecurseGlobals structure is used to minimize the amount of\n** stack space used when recursively calling RecurseDirectoryLevel\n** and to hold global information that might be needed at any time.\n*/\nstruct RecurseGlobals\n{\n    short                   vRefNum;\n    CInfoPBRec              cPB;            /* the parameter block used for\n                                               PBGetCatInfo calls */\n    unsigned char           *itemName;      /* the name of the current item */\n    char                    *FullPath;\n    short                   FullPathLen;\n    OSErr                   result;         /* temporary holder of results -\n                                            saves 2 bytes of stack each level */\n    Boolean                 quitFlag;       /* set to true if filter wants to\n                                               kill interation */\n    unsigned short          maxLevels;      /* Maximum levels to\n                                               iterate through */\n    unsigned short          currentLevel;   /* The current level\n                                               IterateLevel is on */\n};\n\ntypedef struct RecurseGlobals RecurseGlobals;\ntypedef RecurseGlobals *RecurseGlobalsPtr;\n\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nextern MacZipGlobals    MacZip;\nextern const char ResourceMark[13]; /* \"XtraStuf.mac:\" var is initialized in file pathname.c */\nextern int extra_fields;            /* do not create extra fields if false */\n\nstatic RecurseGlobals theGlobals;\n\nstatic unsigned long    DirLevels = 0;\nstatic char *buffer;\nextern int verbose;        /* 1=report oddities in zip file structure */\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\nint procname(char *filename, int caseflag);\nint MatchWild( char *pPat, char *pStr, int case_sens);\nBoolean IsZipFile(char *name);\n\nstatic  void    RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals);\nstatic Boolean isRegularItem( RecurseGlobals *Globals);\nstatic void ProcessFiles(RecurseGlobals *Globals,\n                         Boolean hasDataFork, Boolean hasResourceFork);\nstatic void ProcessDirectory(RecurseGlobals *Globals,\n                             Boolean IncludeItem, long DirID);\nstatic void ProcessItem(RecurseGlobals *Globals, long DirID);\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\nstatic  void    RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals)\n{\nchar buffer2[23];\n\n                 /* if maxLevels is zero, we aren't checking levels */\n    if ( (Globals->maxLevels == 0) ||\n                 /* if currentLevel < maxLevels, look at this level */\n         (Globals->currentLevel < Globals->maxLevels) )\n    {\n        short index = 1;\n\n        ++Globals->currentLevel;    /* go to next level */\n        if (DirLevels < Globals->currentLevel) DirLevels = Globals->currentLevel;\n        sprintf(buffer2,\"Globals->currentLevel: %d\",Globals->currentLevel);\n\n        do\n        {   /* Isn't C great... What I'd give for a \"WITH\n                theGlobals DO\" about now... */\n\n            /* Get next source item at the current directory level */\n            Globals->cPB.dirInfo.ioFDirIndex = index;\n            Globals->cPB.dirInfo.ioDrDirID = DirID;\n            Globals->result = PBGetCatInfoSync((CInfoPBPtr)&Globals->cPB);\n\n                        ShowCounter(false);\n\n            if ( Globals->result == noErr )\n                {\n                ProcessItem(Globals, DirID);\n                } /* if ( Globals->result == noErr ) */\n\n            ++index; /* prepare to get next item */\n                                         /* time to fall back a level? */\n        } while ( (Globals->result == noErr) && (!Globals->quitFlag) );\n\n        if ( (Globals->result == fnfErr) || /* fnfErr is OK -\n                                               it only means we hit\n                                               the end of this level */\n             (Globals->result == afpAccessDenied) ) /* afpAccessDenied is OK,\n                      too - it only means we cannot see inside a directory */\n        {\n            Globals->result = noErr;\n        }\n\n        --Globals->currentLevel;    /* return to previous level as we leave */\n    }\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   RecurseDirectory(short vRefNum,\n                                 long thedirID,\n                                 ConstStr255Param name,\n                                 unsigned short maxLevels)\n{\n    OSErr           result;\n    short           theVRefNum;\n    Boolean         isDirectory;\n    long            DirID;\n\n        /* Get the real directory ID and make sure it is a directory */\n        result = GetDirectoryID(vRefNum, thedirID, name, &DirID, &isDirectory);\n        if ( result == noErr )\n        {\n            if ( isDirectory == true )\n            {\n                /* Get the real vRefNum */\n                result = DetermineVRefNum(name, vRefNum, &theVRefNum);\n                if ( result == noErr )\n                {\n                    /* Set up the globals we need to access from\n                       the recursive routine. */\n                    theGlobals.cPB.hFileInfo.ioNamePtr = theGlobals.itemName;\n                    theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;\n                    theGlobals.itemName[0] = 0;\n                    theGlobals.result = noErr;\n                    theGlobals.quitFlag = false;\n                    theGlobals.maxLevels = maxLevels;\n                    theGlobals.currentLevel = 0;    /* start at level 0 */\n\n                    /* Here we go into recursion land... */\n                    RecurseDirectoryLevel(DirID, &theGlobals);\n\n                    result = theGlobals.result; /* set the result */\n                }\n            }\n            else\n            {\n                result = dirNFErr;  /* a file was passed instead\n                                       of a directory */\n            }\n        }\n\n    return ( result );\n}\n\n\n\n/*****************************************************************************/\n\npascal  OSErr   FSpRecurseDirectory(const FSSpec *spec,\n                                    unsigned short maxLevels)\n{\n    OSErr rc;\n\n    theGlobals.vRefNum = spec->vRefNum;\n\n    /* make room for pathnames  */\n    theGlobals.itemName = (unsigned char *) StrCalloc(NAME_MAX);\n    theGlobals.FullPath = StrCalloc(NAME_MAX);\n    buffer = StrCalloc(NAME_MAX);\n\n\n    if ((noisy) && (MacZip.DataForkOnly))\n        printf(\"\\n Warning: Datafork only \\n\");\n\n    /* reset the count to zero */\n    ShowCounter(true);\n\n    if (noisy) leftStatusString(\"Build File List; Items done:\");\n    if (noisy) printf(\"\\n Collecting Filenames ...\");\n    rc = RecurseDirectory(spec->vRefNum, spec->parID, spec->name,maxLevels);\n    printerr(\"RecurseDirectory:\",rc,rc,__LINE__,__FILE__,\"\");\n\n    if (noisy) printf(\"\\n... done \\n\\n %6d matched files found  \\n\",\n                      MacZip.FoundFiles);\n    if (noisy) printf(\" %6d folders found in %d Levels \\n\",\n                         MacZip.FoundDirectories,DirLevels);\n\n    if (MacZip.BytesOfData > (1024*1024))\n        if (noisy) printf(\" %4.3f MBytes unzipped size\\n\\n\",\n                            (float) MacZip.BytesOfData/(1024*1024));\n    else\n        if (noisy) printf(\" %4.3f KBytes unzipped size\\n\\n\",\n                           (float) MacZip.BytesOfData/1024);\n\n    /* free all memory of pathnames  */\n    theGlobals.itemName = (unsigned char *) StrFree((char *)theGlobals.itemName);\n    theGlobals.FullPath = StrFree(theGlobals.FullPath);\n    buffer = StrFree(buffer);\n\n    return rc;\n}\n\n\n\n\n/*\n* Return true if filename == zipfile\n* After the first match no further check will be done !\n*\n*/\nBoolean IsZipFile(char *filen)\n{\nstatic firstMatch = false;\n\nif (filen == NULL)\n    firstMatch = false;\n\nif (!firstMatch)\n    {\n    if (stricmp(filen, MacZip.ZipFullPath) == 0)\n        {\n        firstMatch = true;\n        return true;\n        }\n    }\n\nreturn false;\n}\n\n\n\nstatic Boolean isRegularItem( RecurseGlobals *Globals)\n{\nBoolean     isInvisible = false,\n            isAlias     = false,\n            isSystem    = false;\n\nisSystem    = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &\n              (1 << 12)) == 0 );\nisInvisible = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &\n              (1 << 14)) == 0 );\nisAlias     = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &\n              (1 << 15)) == 0);\n\nif (isAlias == true)\n    {\n    return false;\n    }\n\nif (MacZip.IncludeInvisible == true)\n    {\n    return true;\n    }\n\nif  ((isSystem == true) ||\n    (isInvisible == true))\n    {\n    return false;\n    }\n\nreturn true;\n}\n\n\n\n\nstatic void ProcessFiles(RecurseGlobals *Globals,\n                         Boolean hasDataFork, Boolean hasResourceFork)\n{\n /* some file statistics */\nMacZip.FoundFiles++;\n\nif (hasDataFork == true)\n    {\n    MacZip.BytesOfData =\n                Globals->cPB.hFileInfo.ioFlLgLen +\n                MacZip.BytesOfData;\n    MacZip.CurrentFork = DataFork;\n    MacZip.RawCountOfItems++;\n\n    if (MacZip.DataForkOnly == true)\n        {\n        procname(Globals->FullPath, false);\n        hasResourceFork = false;\n        }\n        else\n        {\n        procname(Real2RfDfFilen(buffer,Globals->FullPath,\n                 DataFork, MacZip.MacZipMode,\n                 MacZip.DataForkOnly), false);\n        }\n    }\n\nif (hasResourceFork == true)\n    {\n    MacZip.BytesOfData =\n                Globals->cPB.hFileInfo.ioFlRLgLen +\n                MacZip.BytesOfData;\n    MacZip.CurrentFork = ResourceFork;\n    MacZip.RawCountOfItems++;\n\n    procname(Real2RfDfFilen(buffer, Globals->FullPath,\n             ResourceFork, MacZip.MacZipMode,\n             MacZip.DataForkOnly), false);\n    }\n}\n\n\n\n\nstatic void ProcessDirectory(RecurseGlobals *Globals,\n                             Boolean IncludeItem, long DirID)\n{\nOSErr       rc;\n\nMacZip.isDirectory = true;\n\nGetFullPathFromID(Globals->FullPath,Globals->vRefNum, DirID,\n                  Globals->itemName, &rc);\n\nMacZip.RawCountOfItems++;\nMacZip.FoundDirectories++;\n\nif  (MacZip.StoreFoldersAlso)\n    {\n    procname(Globals->FullPath, false);\n    }\n\n     /* We have a directory */\n    if ( !Globals->quitFlag && IncludeItem)\n    {\n   /* Dive again if the IterateFilterProc didn't say \"quit\" and dir is\n      not an alias */\n        RecurseDirectoryLevel(Globals->cPB.dirInfo.ioDrDirID,\n                              Globals);\n    }\n}\n\n\n\nstatic void ProcessItem(RecurseGlobals *Globals, long DirID)\n{\nOSErr rc;\nBoolean     IncludeItem = false, hasDataFork = false;\nBoolean     hasResourceFork = false;\n\nIncludeItem = isRegularItem(Globals);\n\n/* Is it a File? */\nif ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) == 0 )\n    {\n    PToCCpy(Globals->itemName,MacZip.FileName);\n    MacZip.isDirectory = false;\n\n    hasDataFork     = (Globals->cPB.hFileInfo.ioFlLgLen != 0);\n    hasResourceFork = (Globals->cPB.hFileInfo.ioFlRLgLen != 0);\n\n    /* include also files with zero recource- and data-fork */\n    if ((hasDataFork == 0) && (hasResourceFork == 0))\n        hasDataFork = true;\n\n    if ((hasDataFork     == 0) &&\n        (hasResourceFork != 0) &&\n        (extra_fields    == false))\n        {\n        IncludeItem = false;\n        }\n\n    GetFullPathFromID(Globals->FullPath,Globals->vRefNum,\n                      DirID, Globals->itemName, &rc);\n    printerr(\"GetFullPathFromID:\",rc,rc,__LINE__,\n              __FILE__,MacZip.FileName);\n\n    if  (IncludeItem  &&       /* don't include the zipfile itself */\n        (!IsZipFile(Globals->FullPath))   )\n        {\n        if (MATCH(MacZip.Pattern, MacZip.FileName, false) == true)\n            {\n            ProcessFiles(Globals, hasDataFork, hasResourceFork);\n            } /* if (MatchWild( MacZip.FileName,MacZip.Pattern ) ==\n                    true) */\n        }  /* if (!IsZipFile(Globals->FullPath)) */\n    } /* Is it a File? */\n\n/* Is it a directory? */\nif ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )\n    {\n    ProcessDirectory(Globals,IncludeItem, DirID);\n    } /* Is it a directory? */\n}\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/recurse.h",
    "content": "/*\n**  IterateDirectory: File Manager directory iterator routines.\n**\n**  by Jim Luther\n**\n**  File:       IterateDirectory.h\n**\n**  Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.\n**  All rights reserved.\n**\n**  You may incorporate this sample code into your applications without\n**  restriction, though the sample code has been provided \"AS IS\" and the\n**  responsibility for its operation is 100% yours.\n**\n**  IterateDirectory is designed to drop into the MoreFiles sample code\n**  library I wrote while in Apple Developer Technical Support\n*/\n\n#ifndef __RECURSEDIRECTORY__\n#define __RECURSEDIRECTORY__\n\n#include <Types.h>\n#include <Files.h>\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/*****************************************************************************/\n\npascal  OSErr   RecurseDirectory(short vRefNum,\n                                 long dirID,\n                                 ConstStr255Param name,\n                                 unsigned short maxLevels );\n/*   Iterate (scan) through a directory's content.\n    The IterateDirectory function performs a recursive iteration (scan) of\n    the specified directory and calls your IterateFilterProc function once\n    for each file and directory found.\n\n    The maxLevels parameter lets you control how deep the recursion goes.\n    If maxLevels is 1, IterateDirectory only scans the specified directory;\n    if maxLevels is 2, IterateDirectory scans the specified directory and\n    one subdirectory below the specified directory; etc. Set maxLevels to\n    zero to scan all levels.\n\n    The yourDataPtr parameter can point to whatever data structure you might\n    want to access from within the IterateFilterProc.\n\n    vRefNum         input:  Volume specification.\n    dirID           input:  Directory ID.\n    name            input:  Pointer to object name, or nil when dirID\n                            specifies a directory that's the object.\n    maxLevels       input:  Maximum number of directory levels to scan or\n                            zero to scan all directory levels.\n    iterateFilter   input:  A pointer to the routine you want called once\n                            for each file and directory found by\n                            IterateDirectory.\n    yourDataPtr     input:  A pointer to whatever data structure you might\n                            want to access from within the IterateFilterProc.\n\n    Result Codes\n        noErr               0       No error\n        nsvErr              -35     No such volume\n        ioErr               -36     I/O error\n        bdNamErr            -37     Bad filename\n        fnfErr              -43     File not found\n        paramErr            -50     No default volume or iterateFilter was NULL\n        dirNFErr            -120    Directory not found or incomplete pathname\n                                    or a file was passed instead of a directory\n        afpAccessDenied     -5000   User does not have the correct access\n        afpObjectTypeErr    -5025   Directory not found or incomplete pathname\n\n    __________\n\n    See also:   RecurseFilterProcPtr, FSpRecurseDirectory\n*/\n\n/*****************************************************************************/\n\npascal  OSErr   FSpRecurseDirectory(const FSSpec *spec,\n                                    unsigned short maxLevels);\n/*   Iterate (scan) through a directory's content.\n    The FSpIterateDirectory function performs a recursive iteration (scan)\n    of the specified directory and calls your IterateFilterProc function once\n    for each file and directory found.\n\n    The maxLevels parameter lets you control how deep the recursion goes.\n    If maxLevels is 1, FSpIterateDirectory only scans the specified directory;\n    if maxLevels is 2, FSpIterateDirectory scans the specified directory and\n    one subdirectory below the specified directory; etc. Set maxLevels to\n    zero to scan all levels.\n\n    The yourDataPtr parameter can point to whatever data structure you might\n    want to access from within the IterateFilterProc.\n\n    spec            input:  An FSSpec record specifying the directory to scan.\n    maxLevels       input:  Maximum number of directory levels to scan or\n                            zero to scan all directory levels.\n    iterateFilter   input:  A pointer to the routine you want called once\n                            for each file and directory found by\n                            FSpIterateDirectory.\n    yourDataPtr     input:  A pointer to whatever data structure you might\n                            want to access from within the IterateFilterProc.\n\n    Result Codes\n        noErr               0       No error\n        nsvErr              -35     No such volume\n        ioErr               -36     I/O error\n        bdNamErr            -37     Bad filename\n        fnfErr              -43     File not found\n        paramErr            -50     No default volume or iterateFilter was NULL\n        dirNFErr            -120    Directory not found or incomplete pathname\n        afpAccessDenied     -5000   User does not have the correct access\n        afpObjectTypeErr    -5025   Directory not found or incomplete pathname\n\n    __________\n\n    See also:   RecurseFilterProcPtr, RecurseDirectory\n*/\n\n\n\n/*****************************************************************************/\n\n\n\n#endif /* __RECURSEDIRECTORY__ */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/unixlike.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  unixlike.c\n\n  Macintosh-specific routines to emulate unixfunctions.\n\n  ---------------------------------------------------------------------------*/\n\n/*****************************************************************************/\n/*  Includes                                                                 */\n/*****************************************************************************/\n\n#include \"zip.h\"\n\n#include <string.h>\n#include <stdio.h>\n#include <sound.h>\n\n#include \"unixlike.h\"\n#include \"helpers.h\"\n#include \"pathname.h\"\n#include \"macstuff.h\"\n#include \"macglob.h\"\n#include \"mactime.h\"\n\n/*****************************************************************************/\n/*  Global Vars                                                              */\n/*****************************************************************************/\n\nextern MacZipGlobals    MacZip;\nextern int errno;\n\n\n/*****************************************************************************/\n/*  Prototypes                                                               */\n/*****************************************************************************/\n\n\n/*****************************************************************************/\n/*  Functions                                                                */\n/*****************************************************************************/\n\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * MacStat --\n *\n *  This function replaces the library version of stat.  The stat\n *  function provided by most Mac compiliers is rather broken and\n *  incomplete.\n *\n * Results:\n *  See stat documentation.\n *\n * Side effects:\n *  See stat documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint Zmacstat(const char *Fname, struct stat *buf)\n{\n    OSErr           err, rc;\n    short           fullPathLength;\n    Handle          hFullPath;\n    char            path[NAME_MAX], path2[NAME_MAX];\n    HVolumeParam    vpb;\n    static unsigned long count_of_files = 0;\n\n    AssertStr(Fname,Fname)\n    Assert_it(buf,\"\",\"\")\n\n    UserStop();\n\n    memset(buf, 0, sizeof(buf));    /* zero out all fields */\n\n    RfDfFilen2Real(path2, Fname, MacZip.MacZipMode, MacZip.DataForkOnly,\n                   &MacZip.CurrentFork);\n    GetCompletePath(path, path2, &MacZip.fileSpec, &err);\n    err = PrintUserHFSerr((err != -43) && (err != 0), err, path);\n    printerr(\"GetCompletePath:\", err, err, __LINE__, __FILE__, path);\n\n    if (err != noErr) {\n        errno = err;\n        return -1;\n    }\n\n    /*  Collect here some more information, it's not related to Macstat.\n        (note: filespec gets changed later in this function) */\n    /* clear string-buffer */\n    memset(MacZip.FullPath, 0x00, sizeof(MacZip.FullPath));\n    rc = FSpGetFullPath(&MacZip.fileSpec, &fullPathLength, &hFullPath);\n    strncpy(MacZip.FullPath, *hFullPath, fullPathLength);\n    DisposeHandle(hFullPath);   /* we don't need it any more */\n    /*  Collect some more information not related to Macstat */\n\n\n    /*\n     * Fill the fpb & vpb struct up with info about file or directory.\n     */\n\n    FSpGetDirectoryID(&MacZip.fileSpec, &MacZip.dirID, &MacZip.isDirectory);\n    vpb.ioVRefNum = MacZip.fpb.hFileInfo.ioVRefNum =  MacZip.fileSpec.vRefNum;\n    vpb.ioNamePtr = MacZip.fpb.hFileInfo.ioNamePtr =  MacZip.fileSpec.name;\n\n    if (MacZip.isDirectory) {\n        MacZip.fpb.hFileInfo.ioDirID =  MacZip.fileSpec.parID;\n        /*\n         * Directories are executable by everyone.\n         */\n        buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH | UNX_IFDIR;\n    } else {\n        MacZip.fpb.hFileInfo.ioDirID = MacZip.dirID;\n    }\n\n    MacZip.fpb.hFileInfo.ioFDirIndex = 0;\n    err = PBGetCatInfoSync((CInfoPBPtr)&MacZip.fpb);\n\n    if (err == noErr) {\n        vpb.ioVolIndex = 0;\n        err = PBHGetVInfoSync((HParmBlkPtr)&vpb);\n        if (err == noErr && buf != NULL) {\n            /*\n             * Files are always readable by everyone.\n             */\n            buf->st_mode |= UNX_IRUSR | UNX_IRGRP | UNX_IROTH;\n\n            /*\n             * Use the Volume Info & File Info to fill out stat buf.\n             */\n            if (MacZip.fpb.hFileInfo.ioFlAttrib & 0x10) {\n                buf->st_mode |= UNX_IFDIR;\n                buf->st_nlink = 2;\n            } else {\n                buf->st_nlink = 1;\n                if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) {\n                    buf->st_mode |= UNX_IFLNK;\n                } else {\n                    buf->st_mode |= UNX_IFREG;\n                }\n            }\n\n            if (MacZip.fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL') {\n                /*\n                 * Applications are executable by everyone.\n                 */\n                buf->st_mode |= UNX_IXUSR | UNX_IXGRP | UNX_IXOTH;\n            }\n            if ((MacZip.fpb.hFileInfo.ioFlAttrib & 0x01) == 0){\n                /*\n                 * If not locked, then everyone has write acces.\n                 */\n                buf->st_mode |= UNX_IWUSR | UNX_IWGRP | UNX_IWOTH;\n            }\n\n            buf->st_ino = MacZip.fpb.hFileInfo.ioDirID;\n            buf->st_dev = MacZip.fpb.hFileInfo.ioVRefNum;\n            buf->st_uid = -1;\n            buf->st_gid = -1;\n            buf->st_rdev = 0;\n\n            if (MacZip.CurrentFork == ResourceFork)\n                buf->st_size = MacZip.fpb.hFileInfo.ioFlRLgLen;\n            else\n                buf->st_size = MacZip.fpb.hFileInfo.ioFlLgLen;\n\n            buf->st_blksize = vpb.ioVAlBlkSiz;\n            buf->st_blocks = (buf->st_size + buf->st_blksize - 1)\n                            / buf->st_blksize;\n\n            /*\n             * The times returned by the Mac file system are in the\n             * local time zone.  We convert them to GMT so that the\n             * epoch starts from GMT.  This is also consistent with\n             * what is returned from \"clock seconds\".\n             */\n            if (!MacZip.isDirectory) {\n                MacZip.CreatDate  = MacZip.fpb.hFileInfo.ioFlCrDat;\n                MacZip.ModDate    = MacZip.fpb.hFileInfo.ioFlMdDat;\n                MacZip.BackDate   = MacZip.fpb.hFileInfo.ioFlBkDat;\n            } else {\n                MacZip.CreatDate  = MacZip.fpb.dirInfo.ioDrCrDat;\n                MacZip.ModDate    = MacZip.fpb.dirInfo.ioDrMdDat;\n                MacZip.BackDate   = MacZip.fpb.dirInfo.ioDrBkDat;\n            }\n\n#ifdef IZ_CHECK_TZ\n            if (!zp_tz_is_valid)\n            {\n                MacZip.HaveGMToffset = false;\n                MacZip.Md_UTCoffs = 0L;\n                MacZip.Cr_UTCoffs = 0L;\n                MacZip.Bk_UTCoffs = 0L;\n            }\n            else\n#endif\n            {\n                /* Do not use GMT offsets when Md_UTCoffs calculation\n                 * fails, since this time stamp is used for time\n                 * comparisons in Zip and UnZip operations.\n                 * We do not bother when GMT offset calculation fails for\n                 * any other time stamp value. Instead we simply assume\n                 * a default value of 0.\n                 */\n                MacZip.HaveGMToffset =\n                    GetGMToffsetMac(MacZip.ModDate, &MacZip.Md_UTCoffs);\n                if (MacZip.HaveGMToffset) {\n                    GetGMToffsetMac(MacZip.CreatDate, &MacZip.Cr_UTCoffs);\n                    GetGMToffsetMac(MacZip.BackDate, &MacZip.Bk_UTCoffs);\n                } else {\n                    MacZip.Cr_UTCoffs = 0L;\n                    MacZip.Bk_UTCoffs = 0L;\n                }\n            }\n#ifdef DEBUG_TIME\n            {\n            printf(\"\\nZmacstat:  MacZip.HaveGMToffset: %d\",\n               MacZip.HaveGMToffset);\n            printf(\"\\nZmacstat:  Mac modif: %lu local -> UTOffset: %d\",\n              MacZip.ModDate, MacZip.Md_UTCoffs);\n            printf(\"\\nZmacstat:  Mac creat: %lu local -> UTOffset: %d\",\n              MacZip.CreatDate, MacZip.Cr_UTCoffs);\n            printf(\"\\nZmacstat:  Mac  back: %lu local -> UTOffset: %d\",\n              MacZip.BackDate, MacZip.Bk_UTCoffs);\n            }\n#endif /* DEBUG_TIME */\n\n\n            buf->st_mtime = MacFtime2UnixFtime(MacZip.ModDate);\n            buf->st_ctime = MacFtime2UnixFtime(MacZip.CreatDate);\n            buf->st_atime = buf->st_mtime;\n\n#ifdef DEBUG_TIME\n            {\n            printf(\"\\nZmacstat:  Unix modif: %lu UTC; Mac: %lu local\",\n              buf->st_mtime, MacZip.ModDate);\n            printf(\"\\nZmacstat:  Unix creat: %lu UTC; Mac: %lu local\\n\",\n              buf->st_ctime, MacZip.CreatDate);\n            }\n#endif /* DEBUG_TIME */\n\n            if (noisy)\n            {\n                if (MacZip.StatingProgress)\n                {\n                    count_of_files++;\n                    InformProgress(MacZip.RawCountOfItems, count_of_files );\n                }\n                else\n                    count_of_files = 0;\n            }\n        }\n    }\n\n    if (err != noErr) {\n        errno = err;\n    }\n\n    MacZip.isMacStatValid = true;\n    return (err == noErr ? 0 : -1);\n}\n\n\n\n\n\n/*\n *----------------------------------------------------------------------\n *\n * chmod --\n *\n * Results:\n *  See chmod documentation.\n *\n * Side effects:\n *  See chmod documentation.\n *\n *----------------------------------------------------------------------\n */\n\nint chmod(char *path, int mode)\n{\n    HParamBlockRec hpb;\n    OSErr err;\n\n    hpb.fileParam.ioNamePtr = C2PStr(path);\n    hpb.fileParam.ioVRefNum = 0;\n    hpb.fileParam.ioDirID = 0;\n\n    if (mode & 0200) {\n        err = PBHRstFLockSync(&hpb);\n    } else {\n        err = PBHSetFLockSync(&hpb);\n    }\n\n    if (err != noErr) {\n        errno = err;\n        return -1;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/unixlike.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n *      Directory Operations for Mac based on BSD 4.3   <macdir.h>\n *      By Jason Linhart, January 1997\n */\n\n#ifndef _UNIXLIKE_H\n#define _UNIXLIKE_H       1\n\n#include <stat.h>\n\n#ifndef NAME_MAX\n#define NAME_MAX    2048\n#endif\n\n#define UNX_IFMT        0170000     /* Unix file type mask */\n#define UNX_IFSOCK      0140000     /* Unix socket (BSD, not SysV or Amiga) */\n#define UNX_IFLNK       0120000     /* Unix symbolic link (not SysV, Amiga) */\n#define UNX_IFREG       0100000     /* Unix regular file */\n#define UNX_IFBLK       0060000     /* Unix block special       (not Amiga) */\n#define UNX_IFDIR       0040000     /* Unix directory */\n#define UNX_IFCHR       0020000     /* Unix character special   (not Amiga) */\n#define UNX_IFIFO       0010000     /* Unix fifo    (BCC, not MSC or Amiga) */\n\n#define UNX_ISUID       04000       /* Unix set user id on execution */\n#define UNX_ISGID       02000       /* Unix set group id on execution */\n#define UNX_ISVTX       01000       /* Unix directory permissions control */\n#define UNX_ENFMT       UNX_ISGID   /* Unix record locking enforcement flag */\n\n#define UNX_IRWXU       00700       /* Unix read, write, execute: owner */\n#define UNX_IRUSR       00400       /* Unix read permission: owner */\n#define UNX_IWUSR       00200       /* Unix write permission: owner */\n#define UNX_IXUSR       00100       /* Unix execute permission: owner */\n\n#define UNX_IRWXG       00070       /* Unix read, write, execute: group */\n#define UNX_IRGRP       00040       /* Unix read permission: group */\n#define UNX_IWGRP       00020       /* Unix write permission: group */\n#define UNX_IXGRP       00010       /* Unix execute permission: group */\n\n#define UNX_IRWXO       00007       /* Unix read, write, execute: other */\n#define UNX_IROTH       00004       /* Unix read permission: other */\n#define UNX_IWOTH       00002       /* Unix write permission: other */\n#define UNX_IXOTH       00001       /* Unix execute permission: other */\n\n/* historical file modes */\n#define S_IREAD    0x100\n#define S_IWRITE   0x80\n#define S_IEXEC    0x40\n\n\n#define isatty(arg) 1\n\n\n#define EINVAL          22      /* Invalid argument */\n#define ENAMETOOLONG    63      /* File name too long */\n\n\nstruct dirent {\n        char            d_name[NAME_MAX];\n};\n\n/*\n * The following definitions are usually found in fcntl.h.\n * However, MetroWerks has screwed that file up a couple of times\n * and all we need are the defines.\n */\n#define O_APPEND  0x0100    /* open the file in append mode */\n#define O_CREAT   0x0200    /* create the file if it doesn't exist */\n#define O_EXCL    0x0400    /* if the file exists don't create it again */\n#define O_TRUNC   0x0800    /* truncate the file after opening it */\n\n\nint Zmacstat (const char *path, struct stat *buf);\nint chmod(char *path, int mode);\n\n\n#include \"macstuff.h\"\n\n#endif /* _UNIXLIKE_H  */\n"
  },
  {
    "path": "deps/infozip/zip30/macos/source/zip_rc.hqx",
    "content": "(This file must be converted with BinHex 4.0)\n:#RTTF#jbBbjcDA3!8dP84&0*9#%!N!3([`#3\"&(E8dP8)3!\"!!!([h*-BA8#Q3#\n3!aDCQ3d!\"RTTF#jbB`!!&[Bi\"2[rG!\"-5QS!N!1!!*!%\"32,j+m2!*!Drj!%8P0\n53e*6483\"\",#mXHDaqlGG!!!GmJ#3\"JFj!*!%6Mi!N!MGc!`!P@6pq1R*k4&+Z,d\np\"5$(b(-Upcc#j%EiHCfjPTq%8h+X8d)MR$`rF[b9Vh`pTLc2jqZ9r'RNq9VN1'&\n'MMmj6Sk6#5HFc0J4lN8iHFU2--,*K%Z1NIR+#1XNR(\"#bE-)2I+FF$*G@H6BL+`\n*!&6IV1ml1d+22#-$4UEm*#01\"T`m*4`Ji(03ThM'$-EBilf-V8-e6Q8bXEVD@Xi\n2bilcmGEY\"lV6QGjZrK)I1CKZ$BfR4pSbLD'f`F'qVPKb+*(-*V2CPLfaGj1CE+a\nZ+-$kpr4hpHrCf@d%f66E!A2P-rA6phmUj)QrdYP4r[6)H+cZF\"hRV``NHSG5`b!\nF6-0YBZ$!JH&%#frIb,2TmH4`LVGN4c1(%U1Q8#cf)P44dU\"#-`D)I($H4I5qc[j\nNJLI5)qpN5)Ic[S(-`-&1H(U2L*U'-H`1Y1p&qc#*YVk4(RNUbp(ae(#'R,B[d%B\n(Nd40$id1C`FhmUlKNBmbkAf$Sra8qpDYcm0,H%GIhbiej(!EESbmC+a*'3dqdlC\nj)%*H#+!,D!K4#J#3!$9H-J)mB*6L!50R\"%\"&hi6DD*61[-qq22%f1hkXPq@r)'`\n(1hjQJ19cKP'bY0#60RQ3!&kd,r))mj-X,LBCCa&CeiX#f`ibZ$9##+[1HUJ34G5\n584+#&@p9i[UDj-&PD2rAi0qYdMpMQ\"\"M8FLBT`#FUMje-i6rVXl2qI`jK@XY#eH\n+%JH[5(`6,qEcH@K,(FfA4rZDNG,4mp60fALH@TT,SC!!5Sf0$HHP31&mP\"AfKN)\nK-!N[&XjM@##`1I,(a\"V\"#L%@#U9'*'lT-5CaU8GqpLTFkUP\"%klmfMLJ1QpH5r2\ndjNdfhIXJFIqqN!!&1QHe$jUlHF`jZ2I41X8k$@ZbKF1C2\"Cq6YZaF(Z+5Yra&63\n\"alCh62Vm6N(RqR90&)#m`cE3mILqV`@qBmcQkf0\"9Ei%#**RRRpcS0DmV!N6DB-\n&#R112Ym4-1d)GJ(R0,i,0!TEJ!%$#Mj$SFqp80)XU4&\"+j!!DmFJk)S2*[(KNMR\nmHApd)4Im@I2aqEBrpd,EVi3ehd@qETI[eprhmmlp0UGjqhe`q#[[Ljk#GDclAll\n[P91j$d[[ir`4X1LcbmVcI$8cCd49rY*`E2l+F1l-Uk0CV,edY8%d('d@pD*qVRk\nL@64FE9KlU9Q%E`3$i@+cD\"BSp)'26f,8K%[iL[#3!$-h&aDPY5L2CJBBpF5Kh5k\n+ASJVqckQ9kG`*C95rEka+29B5U+f\"eYIqF&ZC()P-%GbHXQ44)a!l[Z9q3[c5Z!\naN!!pGHT\"X#q,IJ$8lG#i224dkNXMhd,#3I\"ap4JkEk@YlrKEp1r14erRqIYVJY@\nRbX4G0GVTc4A5A20`[E`GcX60GGI#0@$KHMqfFB9BIV4&%kr6+kH*J`(FR3lKcJj\npNqpN!JiZ-`'&1jQ!a*e-31RCQB$%R8c!dY1CJ19(C`+@AjGIa[qCCq8qH,K8FA%\nLH$LpGbZiFpp0ehUR[lZTL-[HU3T8q*FVkd5&AaDBjrX##ha2S$UImK6,r-Z9MDM\n#PaVqNfUH+VqmXplAGpG!G`k,I&I!i[ZC`J,Iba3@rEQC`J,Iba5@rFQGIhNq5h`\nr-lM2ArAJIYjp(jEjYX!5he+i`cIhZRrjYq)%rjNh@\"K4Ej!!V8&p!,8@0C*$l3L\nbk#`f\"%i9DMaRk,i*YC&aj0dFH6G(hXf4Gh2Nh4ajYp5aY(5[I@a#hBBDeh9E'*X\nKq3q,)QS*99$0SCj&R68Va[9Ie6lJ9444KDk%dDE9%CrPQhJ,hbD#)RJ8936RJK1\nbjb%HMTILXr&#r&Um++SIZ#*1fAP1hM-c'CG*VekG*BkGApkj'DZA13GkPA1JPcN\n(iC4c%*m@1&[2l0@LLCK%pFUBG%kj4M@2,@pY&UjA+*Y2#Zil5%pF&GI[LBAVh-2\n$3I\"aCG,5ekC[qL[MlZ1QRP32Ga5YQFY`Cf-[rZ!JX+GrCir-1R)J6J!jdY[ekRU\nIXFT6',*jNmH[B69Hq&&6$N-NlS3K8Xm03mM2+VTKb253!iSqNDRHIKqNq$hqV6$\n%pVF8KPMc@68N$0Q#[KXH1UJL$1P'',*PpB``C\"5M'eXG)JbTfDal(BB!AfdN$-'\ncjq2P-%6bli8Kq,pej\"NCErJr%NGk[[Pkpa44M+pBl4Mq$SC![ij'pZ[3j20d)N[\ni$qR%J5hSI`01r3hJcl+!m54`kMY9f'+N1PrYaRqe4SCq@E8Hr)$%dK,,5@`LdR2\nb$cBKPr+\"5-q*AH`)BBm-4AUqlG-DHk\"a9QQ`Yi\"0+Beefb-pTlj6'Z(2`,ZS0\"j\n+!KY9'SpQ-0f,5U2Q'(Lr+Sd(h`3fV65DpX2VT0+)[!EHKdUMS4ABTdVMX4IJG8T\nT'*pJ6K'P8IXk0+iTMFB8I'L[i9r!Qp6c`!dlH9,2idGJTp9PD'b(MjH9AZ0cQ02\nTqYdI$#8c2*2-$Kr+**,r!`#3!dm4!!!:\n"
  },
  {
    "path": "deps/infozip/zip30/macos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  include <fcntl.h>\n#endif\n\n#define fhow            (O_RDONLY|O_BINARY)\n#define fbad            (-1)\n\ntypedef int ftype;\n\n\n#define zopen(n,p)      MacOpen(n,p)\n#define zread(f,b,n)    read(f,b,n)\n#define zclose(f)       close(f)\n#define zerr(f)         (k == (extent)(-1L))\n#define zstdin          0\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/man/zip.1",
    "content": ".\\\" =========================================================================\n.\\\" Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n.\\\"\n.\\\" See the accompanying file LICENSE, version 2007-Mar-4 or later\n.\\\" (the contents of which are also included in zip.h) for terms of use.\n.\\\" If, for some reason, all these files are missing, the Info-ZIP license\n.\\\" also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n.\\\" ==========================================================================\n.\\\"\n.\\\" zip.1 by Mark Adler, Jean-loup Gailly and  R. P. C. Rodgers\n.\\\" updated by E. Gordon for Zip 3.0 (8 May 2005, 24 December 2006,\n.\\\" 4 February 2007, 27 May 2007, 4 June 2007 by EG; 12 June 2007 by CS;\n.\\\" 30 August 2007, 27 April 2008, 25 May 2008, 27 May 2008 by EG,\n.\\\" 7 June 2008 by SMS and EG; 12 June 2008 by EG)\n.\\\"\n.TH ZIP 1L \"16 June 2008 (v3.0)\" Info-ZIP\n.SH NAME\nzip \\- package and compress (archive) files\n.SH SYNOPSIS\n.B zip\n.RB [\\- aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$ ]\n[\\-\\-longoption ...]\n.RB [\\- b \" path]\"\n.RB [\\- n \" suffixes]\"\n.RB [\\- t \" date]\"\n.RB [\\- tt \" date]\"\n[\\fIzipfile\\fR [\\fIfile\\fR \\.\\|.\\|.]]\n[\\fB-xi\\fR list]\n.PP\n.B zipcloak\n(see separate man page)\n.PP\n.B zipnote\n(see separate man page)\n.PP\n.B zipsplit\n(see separate man page)\n.PP\nNote:  Command line processing in\n.I zip\nhas been changed to support long options and handle all\noptions and arguments more consistently.  Some old command\nlines that depend on command line inconsistencies may no longer\nwork.\n.SH DESCRIPTION\n.I zip\nis a compression and file packaging utility for Unix, VMS, MSDOS,\nOS/2, Windows 9x/NT/XP, Minix, Atari, Macintosh, Amiga, and Acorn\nRISC OS.  It is analogous to a combination of the Unix commands\n.IR tar (1)\nand\n.IR compress (1)\nand is compatible with PKZIP (Phil Katz's ZIP for MSDOS systems).\n.LP\nA companion program\n.RI ( unzip (1L))\nunpacks\n.I zip\narchives.\nThe\n.I zip\nand\n.IR unzip (1L)\nprograms can work with archives produced by PKZIP (supporting\nmost PKZIP features up to PKZIP version 4.6),\nand PKZIP and PKUNZIP can work with archives produced by\n\\fIzip\\fP (with some exceptions, notably streamed archives,\nbut recent changes in the zip file standard may facilitate\nbetter compatibility).\n.I zip\nversion 3.0 is compatible with PKZIP 2.04 and also supports\nthe Zip64 extensions of PKZIP 4.5 which allow archives\nas well as files to exceed the previous 2 GB limit (4 GB in\nsome cases).  \\fIzip\\fP also now supports \\fBbzip2\\fP compression\nif the \\fBbzip2\\fP library is included when \\fIzip\\fP is compiled.\nNote that PKUNZIP 1.10 cannot extract files produced by\nPKZIP 2.04 or\n\\fIzip\\ 3.0\\fP. You must use PKUNZIP 2.04g or\n\\fIunzip\\ 5.0p1\\fP (or later versions) to extract them.\n.PP\nSee the \\fBEXAMPLES\\fP section at the bottom of this page\nfor examples of some typical uses of \\fIzip\\fP.\n.PP\n\\fBLarge\\ Archives\\ and\\ Zip64.\\fP\n.I zip\nautomatically uses the Zip64 extensions when files larger than 4 GB are\nadded to an archive, an archive containing Zip64 entries is updated\n(if the resulting archive still needs Zip64),\nthe size of the archive will exceed 4 GB, or when the\nnumber of entries in the archive will exceed about 64K.\nZip64 is also used for archives streamed from standard input as the size\nof such archives are not known in advance, but the option \\fB\\-fz\\-\\fP can\nbe used to force \\fIzip\\fP to create PKZIP 2 compatible archives (as long\nas Zip64 extensions are not needed).  You must use a PKZIP 4.5\ncompatible unzip, such as \\fIunzip\\ 6.0\\fP or later, to extract files\nusing the Zip64 extensions.\n.PP\nIn addition, streamed archives, entries encrypted with standard encryption,\nor split archives created with the pause option may not be compatible with\nPKZIP as data descriptors are used\nand PKZIP at the time of this writing does not support data descriptors\n(but recent changes in the PKWare published zip standard now include some\nsupport for the data descriptor format \\fIzip\\fP uses).\n\n.PP\n\\fBMac OS X.\\fP  Though previous Mac versions had their own \\fIzip\\fP port,\n\\fIzip\\fP supports Mac OS X as part of the Unix port and most Unix features\napply.  References to \"MacOS\" below generally refer to MacOS versions older\nthan OS X.  Support for some Mac OS features in the Unix Mac OS X port, such\nas resource forks, is expected in the next \\fIzip\\fP release.\n\n.PP\nFor a brief help on \\fIzip\\fP and \\fIunzip\\fP,\nrun each without specifying any parameters on the command line.\n\n.SH \"USE\"\n.PP\nThe program is useful for packaging a set of files for distribution;\nfor archiving files;\nand for saving disk space by temporarily\ncompressing unused files or directories.\n.LP\nThe\n.I zip\nprogram puts one or more compressed files into a single\n.I zip\narchive,\nalong with information about the files\n(name, path, date, time of last modification, protection,\nand check information to verify file integrity).\nAn entire directory structure can be packed into a\n.I zip\narchive with a single command.\nCompression ratios of 2:1 to 3:1 are common for text files.\n.I zip\nhas one compression method (deflation) and can also store files without\ncompression.  (If \\fBbzip2\\fP support is added, \\fIzip\\fP can also\ncompress using \\fBbzip2\\fP compression, but such entries require a\nreasonably modern unzip to decompress.  When \\fBbzip2\\fP compression\nis selected, it replaces deflation as the default method.)\n.I zip\nautomatically chooses the better of the two (deflation or store or, if\n\\fBbzip2\\fP is selected, \\fBbzip2\\fP or store) for each file to be\ncompressed.\n.LP\n\\fBCommand\\ format.\\fP  The basic command format is\n.IP\n\\fBzip\\fR options archive inpath inpath ...\n.LP\nwhere \\fBarchive\\fR is a new or existing \\fIzip\\fR archive\nand \\fBinpath\\fR is a directory or file path optionally including wildcards.\nWhen given the name of an existing\n.I zip\narchive,\n.I zip\nwill replace identically named entries in the\n.I zip\narchive (matching the relative names as stored in\nthe archive) or add entries for new names.\nFor example,\nif\n.I foo.zip\nexists and contains\n.I foo/file1\nand\n.IR foo/file2 ,\nand the directory\n.I foo\ncontains the files\n.I foo/file1\nand\n.IR foo/file3 ,\nthen:\n.IP\n\\fCzip -r foo.zip foo\\fP\n.LP\nor more concisely\n.IP\n\\fCzip -r foo foo\\fP\n.LP\nwill replace\n.I foo/file1\nin\n.I foo.zip\nand add\n.I foo/file3\nto\n.IR foo.zip .\nAfter this,\n.I foo.zip\ncontains\n.IR foo/file1 ,\n.IR foo/file2 ,\nand\n.IR foo/file3 ,\nwith\n.I foo/file2\nunchanged from before.\n.LP\nSo if before the zip command is executed \\fIfoo.zip\\fP has:\n.IP\n\\fC foo/file1 foo/file2\n.LP\nand directory foo has:\n.IP\n\\fC file1 file3\\fP\n.LP\nthen \\fIfoo.zip\\fP will have:\n.IP\n\\fC foo/file1 foo/file2 foo/file3\\fP\n.LP\nwhere \\fIfoo/file1\\fP is replaced and\n\\fIfoo/file3\\fP is new.\n.LP\n\\fB\\-@\\ file\\ lists.\\fP  If a file list is specified as\n\\fB\\-@\\fP\n[Not on MacOS],\n.I zip\ntakes the list of input files from standard input instead of from\nthe command line.  For example,\n.IP\n\\fCzip -@ foo\\fP\n.LP\nwill store the files listed one per line on stdin in \\fIfoo.zip\\fP.\n.LP\nUnder Unix,\nthis option can be used to powerful effect in conjunction with the\n\\fIfind\\fP\\ (1)\ncommand.\nFor example,\nto archive all the C source files in the current directory and\nits subdirectories:\n.IP\n\\fCfind . -name \"*.[ch]\" -print | zip source -@\\fP\n.LP\n(note that the pattern must be quoted to keep the shell from expanding it).\n.LP\n\\fBStreaming\\ input\\ and\\ output.\\fP\n.I zip\nwill also accept a single dash (\"-\") as the zip file name, in which case it\nwill write the zip file to standard output, allowing the output to be piped\nto another program. For example:\n.IP\n\\fCzip -r - . | dd of=/dev/nrst0 obs=16k\\fP\n.LP\nwould write the zip output directly to a tape with the specified block size\nfor the purpose of backing up the current directory.\n.LP\n.I zip\nalso accepts a single dash (\"-\") as the name of a file to be compressed, in\nwhich case it will read the file from standard input, allowing zip to take\ninput from another program. For example:\n.IP\n\\fCtar cf - . | zip backup -\\fP\n.LP\nwould compress the output of the tar command for the purpose of backing up\nthe current directory. This generally produces better compression than\nthe previous example using the -r option because\n.I zip\ncan take advantage of redundancy between files. The backup can be restored\nusing the command\n.IP\n\\fCunzip -p backup | tar xf -\\fP\n.LP\nWhen no zip file name is given and stdout is not a terminal,\n.I zip\nacts as a filter, compressing standard input to standard output.\nFor example,\n.IP\n\\fCtar cf - . | zip | dd of=/dev/nrst0 obs=16k\\fP\n.LP\nis equivalent to\n.IP\n\\fCtar cf - . | zip - - | dd of=/dev/nrst0 obs=16k\\fP\n.LP\n.I zip\narchives created in this manner can be extracted with the program\n.I funzip\nwhich is provided in the\n.I unzip\npackage, or by\n.I gunzip\nwhich is provided in the\n.I gzip\npackage (but some\n.I gunzip\nmay not support this if\n.I zip\nused the Zip64 extensions). For example:\n.IP\n\\fPdd if=/dev/nrst0  ibs=16k | funzip | tar xvf -\\fC\n.LP\nThe stream can also be saved to a file and\n.I unzip\nused.\n.LP\nIf Zip64 support for large files and archives is enabled and\n\\fIzip\\fR is used as a filter, \\fIzip\\fR creates a Zip64 archive\nthat requires a PKZIP 4.5 or later compatible unzip to read it.  This is\nto avoid amgibuities in the zip file structure as defined in the current\nzip standard (PKWARE AppNote) where the decision to use Zip64 needs to\nbe made before data is written for the entry, but for a stream the size\nof the data is not known at that point.  If the data is known to be smaller\nthan 4 GB, the option \\fB\\-fz\\-\\fP can be used to prevent use of Zip64,\nbut \\fIzip\\fP will exit with an error if Zip64 was in fact needed.\n\\fIzip\\ 3\\fR and \\fIunzip\\ 6\\fR and later can read archives with Zip64\nentries.  Also, \\fIzip\\fP removes the Zip64 extensions if not needed\nwhen archive entries are copied (see the \\fB\\-U\\fP (\\fB\\-\\-copy\\fP)\noption).\n.LP\nWhen directing the output to another file, note that all options should be\nbefore the redirection including \\fB-x\\fP.  For example:\n.IP\n\\fPzip archive \"*.h\" \"*.c\" -x donotinclude.h orthis.h > tofile\\fC\n.LP\n\\fBZip\\ files.\\fP  When changing an existing\n.I zip\narchive,\n.I zip\nwill write a temporary file with the new contents,\nand only replace the old one when the process of creating the new version\nhas been completed without error.\n.LP\nIf the name of the\n.I zip\narchive does not contain an extension, the extension\n\\fB.zip\\fP\nis added. If the name already contains an extension other than\n\\fB.zip\\fP,\nthe existing extension is kept unchanged.  However, split archives\n(archives split over multiple files) require the \\fB.zip\\fP extension\non the last split.\n.PP\n\\fBScanning\\ and\\ reading\\ files.\\fP\nWhen \\fIzip\\fP starts, it scans for files to process (if needed).  If\nthis scan takes longer than about 5 seconds, \\fIzip\\fP will display\na \"Scanning files\" message and start displaying progress dots every 2 seconds\nor every so many entries processed, whichever takes longer.  If there is more\nthan 2 seconds between dots it could indicate that finding each file is taking\ntime and could mean a slow network connection for example.\n(Actually the initial file scan is\na two-step process where the directory scan is followed by a sort and these\ntwo steps are separated with a space in the dots.  If updating an existing\narchive, a space also appears between the existing file scan and the new\nfile scan.)  The scanning files dots are not controlled by the \\fB\\-ds\\fP\ndot size option, but the dots are turned off by the \\fB\\-q\\fP quiet option.  The\n\\fB\\-sf\\fP show files option can be used to scan for files and get the list of\nfiles scanned without actually processing them.\n.LP\nIf \\fIzip\\fR is not able to read a file, it\nissues a warning but\ncontinues.  See the \\fB\\-MM\\fP option below for more on how \\fIzip\\fP handles\npatterns that are not matched and files that are not readable.\nIf some files were skipped, a\nwarning is issued at the end of the zip operation noting how many files\nwere read and how many skipped.\n.PP\n\\fBCommand\\ modes.\\fP  \\fIzip\\fP now supports two distinct types of command\nmodes, \\fBexternal\\fP and \\fBinternal\\fP.  The \\fBexternal\\fP modes\n(add, update, and freshen) read files from the file system (as well as from an\nexisting archive) while the \\fBinternal\\fP modes (delete and copy) operate\nexclusively on entries in an existing archive.\n.LP\n.TP\n.BI add\\ \\ \\ \\ \\ \\ \nUpdate existing entries and add new files.  If the archive does not exist\ncreate it.  This is the default mode.\n.TP\n.BI update\\ \\fP(\\fB\\-u\\fP)\nUpdate existing entries if newer on the file system and add new files.  If\nthe archive does not exist issue warning then create a new archive.\n.TP\n.BI freshen\\ \\fP(\\fB\\-f\\fP)\nUpdate existing entries of an archive if newer on the file system.\nDoes not add new files to the archive.\n.TP\n.BI delete\\ \\fP(\\fB\\-d\\fP)\nSelect entries in an existing archive and delete them.\n.TP\n.BI copy\\ \\fP(\\fB\\-U\\fP)\nSelect entries in an existing archive and copy them to a new archive.\nThis new mode is similar to \\fBupdate\\fP but command line patterns\nselect entries in the existing archive rather than files from\nthe file system and it uses the \\fB\\-\\-out\\fP option to write the\nresulting archive to a new file rather than update the existing\narchive, leaving the original archive unchanged.\n.LP\nThe new File Sync option (\\fB\\-FS\\fP) is also considered a new mode,\nthough it is similar to \\fBupdate\\fP.  This mode synchronizes the\narchive with the files on the OS, only replacing files in the\narchive if the file time or size of the OS file is different, adding\nnew files, and deleting entries from the archive where there is\nno matching file.  As this mode can delete entries from the archive,\nconsider making a backup copy of the archive.\n\nAlso see \\fB\\-DF\\fP for creating difference archives.\n\nSee each option description below for details and the \\fBEXAMPLES\\fP section\nbelow for examples.\n.PP\n\\fBSplit\\ archives.\\fP  \\fIzip\\fP version 3.0 and later can create split\narchives.  A\n\\fBsplit archive\\fP is a standard zip archive split over multiple\nfiles.  (Note that split archives are not just archives split in to\npieces, as the offsets of entries are now based on the start of each\nsplit.  Concatenating the pieces together will invalidate these offsets,\nbut \\fIunzip\\fP can usually deal with it.  \\fIzip\\fP will usually refuse\nto process such a spliced archive unless the \\fB\\-FF\\fP fix option is\nused to fix the offsets.)\n.LP\nOne use of split archives is storing a large archive on multiple\nremovable media.\nFor a split archive with 20 split files the files are typically named (replace\nARCHIVE with the name of your archive) ARCHIVE.z01, ARCHIVE.z02, ..., ARCHIVE.z19,\nARCHIVE.zip.  Note that the last file is the \\fB.zip\\fP file.  In contrast,\n\\fBspanned archives\\fP are the original multi-disk archive generally requiring\nfloppy disks and using volume labels to store disk numbers.  \\fIzip\\fP supports\nsplit archives but not spanned archives, though a procedure exists for converting\nsplit archives of the right size to spanned archives.  The reverse is also true,\nwhere each file of a spanned archive can be copied in order to files with the\nabove names to create a split archive.\n.LP\nUse \\fB\\-s\\fP to set the split size and create a split archive.  The size is\ngiven as a number followed optionally by one of k (kB), m (MB), g (GB), or t (TB)\n(the default is m).  The \\fB\\-sp\\fP option can be used to pause \\fIzip\\fP between\nsplits to allow changing removable media, for example, but read the descriptions\nand warnings for both \\fB\\-s\\fP and \\fB\\-sp\\fP below.\n.LP\nThough \\fIzip\\fP does not update split archives, \\fIzip\\fP provides the new\noption \\fB\\-O\\fP (\\fB\\-\\-output\\-file\\fP or \\fB\\-\\-out\\fP) to allow split archives\nto be updated and saved in a new archive.  For example,\n.IP\n\\fCzip inarchive.zip foo.c bar.c \\-\\-out outarchive.zip\\fP\n.LP\nreads archive \\fBinarchive.zip\\fP, even if split, adds the files \\fBfoo.c\\fP and\n\\fBbar.c\\fP, and writes the resulting archive to \\fBoutarchive.zip\\fP.  If\n\\fBinarchive.zip\\fP is split then \\fBoutarchive.zip\\fP defaults to the same\nsplit size.  Be aware that if \\fBoutarchive.zip\\fP and any split files that are\ncreated with it already exist, these are always overwritten as needed without\nwarning.  This may be changed in the future.\n.PP\n\\fBUnicode.\\fP  Though the zip standard requires storing paths in an archive using\na specific character set, in practice zips have stored paths in archives in whatever\nthe local character set is.  This creates problems when an archive is created or\nupdated on a system using one character set and then extracted on another system\nusing a different character set.  When compiled with Unicode support enabled on\nplatforms that support wide characters, \\fIzip\\fP now stores, in addition to the\nstandard local path for backward compatibility, the UTF-8 translation of the path.\nThis provides a common universal character set for storing paths that allows these\npaths to be fully extracted on other systems that support Unicode and to match as\nclose as possible on systems that don't.\n\nOn Win32 systems where paths are internally stored as Unicode but represented in\nthe local character set, it's possible that some paths will be skipped during a\nlocal character set directory scan.  \\fIzip\\fP with Unicode support now can read\nand store these paths.  Note that Win 9x systems and FAT file systems don't fully\nsupport Unicode.\n\nBe aware that console windows on Win32 and Unix, for example, sometimes don't\naccurately show all characters due to how each operating system switches in\ncharacter sets for display.  However, directory navigation tools should show the\ncorrect paths if the needed fonts are loaded.\n.PP\n\\fBCommand line format.\\fP  This version of\n.I zip\nhas updated command line processing and support for long options.\n.PP\nShort options take the form\n.IP\n\\fC-s[-][s[-]...][value][=value][\\ value]\\fP\n.LP\nwhere s is a one or two character short option.  A short option\nthat takes a value is last in an argument and anything after it is\ntaken as the value.  If the option can be negated and \"-\" immediately\nfollows the option, the option is negated.\nShort options can also be given as separate arguments\n.IP\n\\fC-s[-][value][=value][\\ value]\\ -s[-][value][=value][\\ value]\\ ...\\fP\n.LP\nShort options in general take values either as part of the same\nargument or as the following argument.  An optional = is also supported.\nSo\n.IP\n\\fC-ttmmddyyyy\\fP\n.LP\nand\n.IP\n\\fC-tt=mmddyyyy\\fP\n.LP\nand\n.IP\n\\fC-tt mmddyyyy\\fP\n.LP\nall work.  The \\fB\\-x\\fP and \\fB\\-i\\fP options accept lists of values\nand use a slightly different format described below.  See the\n\\fB\\-x\\fP and \\fB\\-i\\fP options.\n.PP\nLong options take the form\n.IP\n\\fC--longoption[-][=value][ value]\\fP\n.LP\nwhere the option starts with --, has a multicharacter name, can\ninclude a trailing dash to negate the option (if the option\nsupports it), and can have a value (option argument) specified by\npreceeding it with = (no spaces).  Values can also follow the\nargument.  So\n.IP\n\\fC--before-date=mmddyyyy\\fP\n.LP\nand\n.IP\n\\fC--before-date mmddyyyy\\fP\n.LP\nboth work.\n\nLong option names can be shortened to the shortest unique\nabbreviation.  See the option descriptions below for which\nsupport long options.  To avoid confusion, avoid abbreviating\na negatable option with an embedded dash (\"-\") at the dash\nif you plan to negate it (the parser would consider\na trailing dash, such as for the option \\fB\\-\\-some\\-option\\fP using\n\\fB\\-\\-some\\-\\fP as the option, as part of the name rather\nthan a negating dash).  This may be changed to force the last\ndash in \\fB\\-\\-some\\-\\fP to be negating in the future.\n.SH \"OPTIONS\"\n.TP\n.PD 0\n.BI \\-a\n.TP\n.PD\n.B \\-\\-ascii\n[Systems using EBCDIC] Translate file to ASCII format.\n\n.TP\n.PD 0\n.B \\-A\n.TP\n.PD\n.B \\-\\-adjust-sfx\nAdjust self-extracting executable archive.\nA self-extracting executable archive is created by prepending\nthe SFX stub to an existing archive. The\n.B \\-A\noption tells\n.I zip\nto adjust the entry offsets stored\nin the archive to take into account this \"preamble\" data.\n.LP\nNote: self-extracting archives for the Amiga are a special case.\nAt present, only the Amiga port of \\fIzip\\fP is capable of adjusting\nor updating these without corrupting them. -J can be used to remove\nthe SFX stub if other updates need to be made.\n\n.TP\n.PD 0\n.B \\-AC\n.TP\n.PD\n.B \\-\\-archive-clear\n[WIN32]  Once archive is created (and tested if \\fB\\-T\\fP is used,\nwhich is recommended), clear the archive bits of files processed.  WARNING:\nOnce the bits are cleared they are cleared.  You may want to use the\n\\fB\\-sf\\fP show files option to store the list of files processed in case\nthe archive operation must be repeated.  Also consider using\nthe \\fB\\-MM\\fP must match option.  Be sure to check out \\fB\\-DF\\fP as a\npossibly better way to do incremental backups.\n\n.TP\n.PD 0\n.B \\-AS\n.TP\n.PD\n.B \\-\\-archive-set\n[WIN32]  Only include files that have the archive bit set.  Directories\nare not stored when \\fB\\-AS\\fP is used, though by default the paths\nof entries, including directories, are stored as usual and can be used\nby most unzips to recreate directories.\n\nThe archive bit is set by the operating system when a file is modified\nand, if used with \\fB\\-AC\\fP, \\fB\\-AS\\fP can provide an\nincremental backup capability.  However, other applications can\nmodify the archive bit and it may not be a reliable indicator of\nwhich files have changed since the last archive operation.  Alternative\nways to create incremental backups are using \\fB\\-t\\fP to use file dates,\nthough this won't catch old files copied to directories being archived,\nand \\fB\\-DF\\fP to create a differential archive.\n\n.TP\n.PD 0\n.B \\-B\n.TP\n.PD\n.B \\-\\-binary\n[VM/CMS and MVS] force file to be read binary (default is text).\n\n.TP\n.B \\-B\\fRn\n[TANDEM] set Edit/Enscribe formatting options with n defined as\n.RS\nbit  0: Don't add delimiter (Edit/Enscribe)\n.RE\n.RS\nbit  1: Use LF rather than CR/LF as delimiter (Edit/Enscribe)\n.RE\n.RS\nbit  2: Space fill record to maximum record length (Enscribe)\n.RE\n.RS\nbit  3: Trim trailing space (Enscribe)\n.RE\n.RS\nbit  8: Force 30K (Expand) large read for unstructured files\n.RE\n\n.TP\n.PD 0\n.BI \\-b\\ \\fRpath\n.TP\n.PD\n.B \\-\\-temp-path\\ \\fRpath\nUse the specified\n.I path\nfor the temporary\n.I zip\narchive. For example:\n.RS\n.IP\n\\fCzip -b /tmp stuff *\\fP\n.RE\n.IP\nwill put the temporary\n.I zip\narchive in the directory\n.IR /tmp ,\ncopying over\n.I stuff.zip\nto the current directory when done. This option is useful when\nupdating an existing archive and the file system containing this\nold archive does not have enough space to hold both old and new archives\nat the same time.  It may also be useful when streaming in some\ncases to avoid the need for data descriptors.  Note that using\nthis option may require \\fIzip\\fP take additional time to copy\nthe archive file when done to the destination file system.\n\n.TP\n.PD 0\n.B \\-c\n.TP\n.PD\n.B \\-\\-entry-comments\nAdd one-line comments for each file.\nFile operations (adding, updating) are done first,\nand the user is then prompted for a one-line comment for each file.\nEnter the comment followed by return, or just return for no comment.\n\n.TP\n.PD 0\n.B \\-C\n.TP\n.PD\n.B \\-\\-preserve-case\n[VMS]  Preserve case all on VMS.  Negating this option\n(\\fB\\-C-\\fP) downcases.\n\n.TP\n.PD 0\n.B \\-C2\n.TP\n.PD\n.BI \\-\\-preserve-case-2\n[VMS]  Preserve case ODS2 on VMS.  Negating this option\n(\\fB\\-C2-\\fP) downcases.\n\n.TP\n.PD 0\n.B \\-C5\n.TP\n.PD\n.B \\-\\-preserve-case-5\n[VMS]  Preserve case ODS5 on VMS.  Negating this option\n(\\fB\\-C5-\\fP) downcases.\n\n.TP\n.PD 0\n.B \\-d\n.TP\n.PD\n.B \\-\\-delete\nRemove (delete) entries from a\n.I zip\narchive.\nFor example:\n.RS\n.IP\n\\fCzip -d foo foo/tom/junk foo/harry/\\\\* \\\\*.o\\fP\n.RE\n.IP\nwill remove the entry\n.IR foo/tom/junk ,\nall of the files that start with\n.IR foo/harry/ ,\nand all of the files that end with\n.B \\&.o\n(in any path).\nNote that shell pathname expansion has been inhibited with backslashes,\nso that\n.I zip\ncan see the asterisks,\nenabling\n.I zip\nto match on the contents of the\n.I zip\narchive instead of the contents of the current directory.\n(The backslashes are not used on MSDOS-based platforms.)\nCan also use quotes to escape the asterisks as in\n.RS\n.IP\n\\fCzip -d foo foo/tom/junk \"foo/harry/*\" \"*.o\"\\fP\n.RE\n.IP\nNot escaping the asterisks on a system where the shell expands\nwildcards could result in the asterisks being converted to a\nlist of files in the current directory and that list used to\ndelete entries from the archive.\n.IP\nUnder MSDOS,\n.B \\-d\nis case sensitive when it matches names in the\n.I zip\narchive.\nThis requires that file names be entered in upper case if they were\nzipped by PKZIP on an MSDOS system.  (We considered making this\ncase insensitive on systems where paths were case insensitive,\nbut it is possible the archive came from a system where case does\nmatter and the archive could include both \\fBBar\\fP and \\fBbar\\fP\nas separate files in the archive.)  But see the new option \\fB\\-ic\\fP\nto ignore case in the archive.\n\n.TP\n.PD 0\n.B \\-db\n.TP\n.PD\n.B \\-\\-display-bytes\nDisplay running byte counts showing the bytes zipped and the bytes to go.\n\n.TP\n.PD 0\n.B \\-dc\n.TP\n.PD\n.B \\-\\-display-counts\nDisplay running count of entries zipped and entries to go.\n\n.TP\n.PD 0\n.B \\-dd\n.TP\n.PD\n.B \\-\\-display-dots\nDisplay dots while each entry is zipped (except on ports that have their own\nprogress indicator).  See \\fB-ds\\fR below for setting dot size.  The default is\na dot every 10 MB of input file processed.  The \\fB-v\\fR option\nalso displays dots (previously at a much higher rate than this but now \\fB\\-v\\fP\nalso defaults to 10 MB) and this rate is also controlled by \\fB-ds\\fR.\n\n.TP\n.PD 0\n.B \\-df\n.TP\n.PD\n.B \\-\\-datafork\n[MacOS] Include only data-fork of files zipped into the archive.\nGood for exporting files to foreign operating-systems.\nResource-forks will be ignored at all.\n\n.TP\n.PD 0\n.B \\-dg\n.TP\n.PD\n.B \\-\\-display-globaldots\nDisplay progress dots for the archive instead of for each file.  The command\n.RS\n.IP\n    zip -qdgds 10m\n.RE\n.IP\nwill turn off most output except dots every 10 MB.\n\n.TP\n.PD 0\n.B \\-ds\\ \\fRsize\n.TP\n.PD\n.B \\-\\-dot-size\\ \\fRsize\nSet amount of input file processed for each dot displayed.  See \\fB-dd\\fR to\nenable displaying dots.  Setting this option implies \\fB-dd\\fR.  Size is\nin the format nm where n is a number and m is a multiplier.  Currently m can\nbe k (KB), m (MB), g (GB), or t (TB), so if n is 100 and m is k, size would be\n100k which is 100 KB.  The default is 10 MB.\n.IP\nThe \\fB-v\\fR option also displays dots and now defaults to\n10 MB also.  This rate is also controlled by this option.  A size of 0 turns dots off.\n.IP\nThis option does not control the dots from the \"Scanning files\" message as\n\\fIzip\\fP scans for input files.  The dot size for that is fixed at 2 seconds\nor a fixed number of entries, whichever is longer.\n\n.TP\n.PD 0\n.B \\-du\n.TP\n.PD\n.B \\-\\-display-usize\nDisplay the uncompressed size of each entry.\n\n.TP\n.PD 0\n.B \\-dv\n.TP\n.PD\n.B \\-\\-display-volume\nDisplay the volume (disk) number each entry is being read from,\nif reading an existing archive, and being written to.\n\n.TP\n.PD 0\n.B \\-D\n.TP\n.PD\n.B \\-\\-no-dir-entries\nDo not create entries in the\n.I zip\narchive for directories.  Directory entries are created by default so that\ntheir attributes can be saved in the zip archive.\nThe environment variable ZIPOPT can be used to change the default options. For\nexample under Unix with sh:\n.RS\n.IP\nZIPOPT=\"-D\"; export ZIPOPT\n.RE\n.IP\n(The variable ZIPOPT can be used for any option, including \\fB\\-i\\fP and \\fB\\-x\\fP\nusing a new option format detailed below, and can include several options.) The option\n.B \\-D\nis a shorthand\nfor\n.B \\-x\n\"*/\" but the latter previously could not be set as default in the ZIPOPT\nenvironment variable as the contents of ZIPOPT gets inserted near the beginning\nof the command line and the file list had to end at the end of the line.\n.IP\nThis version of\n.I zip\ndoes allow\n.B \\-x\nand\n.B \\-i\noptions in ZIPOPT if the form\n.IP\n\\fC\n.BR \\-x \\ file\\ file\\ ... \\ @\\fP\n.IP\nis used, where the @ (an argument that is just @) terminates\nthe list.\n\n.TP\n.PD 0\n.B \\-DF\n.TP\n.PD\n.B \\-\\-difference-archive\nCreate an archive that contains all new and changed files since\nthe original archive was created.  For this to work, the input\nfile list and current directory must be the same as during the\noriginal \\fIzip\\fP operation.\n.IP\nFor example, if the existing archive was created using\n.RS\n.IP\n\\fCzip -r foofull .\n.RE\n.IP\nfrom the \\fIbar\\fP directory, then the command\n.RS\n.IP\n\\fCzip -r foofull . -DF --out foonew\n.RE\n.IP\nalso from the \\fIbar\\fP directory creates the archive \\fIfoonew\\fP\nwith just the files not in \\fIfoofull\\fP and the files where\nthe size or file time of the files do not match those in \\fIfoofull\\fP.\n\nNote that the timezone environment variable TZ should be set according to\nthe local timezone in order for this option to work correctly.  A\nchange in timezone since the original archive was created could\nresult in no times matching and all files being included.\n\nA possible approach to backing up a directory might be to create\na normal archive of the contents of the directory as a full\nbackup, then use this option to create incremental backups.\n\n.TP\n.PD 0\n.B \\-e\n.TP\n.PD\n.B \\-\\-encrypt\nEncrypt the contents of the\n.I zip\narchive using a password which is entered on the terminal in response\nto a prompt\n(this will not be echoed; if standard error is not a tty,\n.I zip\nwill exit with an error).\nThe password prompt is repeated to save the user from typing errors.\n\n.TP\n.PD 0\n.B \\-E\n.TP\n.PD\n.B \\-\\-longnames\n[OS/2] Use the .LONGNAME Extended Attribute (if found) as filename.\n\n.TP\n.PD 0\n.B \\-f\n.TP\n.PD\n.B \\-\\-freshen\nReplace (freshen) an existing entry in the\n.I zip\narchive only if it has been modified more recently than the\nversion already in the\n.I zip\narchive;\nunlike the update option\n.RB ( \\-u )\nthis will not add files that are not already in the\n.I zip\narchive.\nFor example:\n.RS\n.IP\n\\fCzip -f foo\\fP\n.RE\n.IP\nThis command should be run from the same directory from which the original\n.I zip\ncommand was run, since paths stored in\n.I zip\narchives are always relative.\n.IP\nNote that the timezone environment variable TZ should be set according to\nthe local timezone in order for the\n\\fB\\-f\\fP, \\fB\\-u\\fP and \\fB\\-o\\fP\noptions to work correctly.\n.IP\nThe reasons behind this are somewhat subtle but have to do with the differences\nbetween the Unix-format file times (always in GMT) and most of the other\noperating systems (always local time) and the necessity to compare the two.\nA typical TZ value is ``MET-1MEST'' (Middle European time with automatic\nadjustment for ``summertime'' or Daylight Savings Time).\n.IP\nThe format is TTThhDDD, where TTT is the time zone such as MET, hh is the\ndifference between GMT and local time such as -1 above, and DDD is\nthe time zone when daylight savings time is in effect.  Leave off\nthe DDD if there is no daylight savings time.  For the US Eastern\ntime zone EST5EDT.\n\n.TP\n.PD 0\n.B \\-F\n.TP\n.B \\-\\-fix\\ \\ \\ \\ \\ \\ \n.TP\n.B \\-FF\n.TP\n.PD\n.B \\-\\-fixfix\\ \\ \nFix the\n.I zip\narchive. The \\fB\\-F\\fP option can be used if some portions of the archive\nare missing, but requires a reasonably intact central directory.\nThe input archive is scanned as usual, but \\fIzip\\fP will ignore\nsome problems.  The resulting archive should be valid, but any\ninconsistent entries will be left out.\n.IP\nWhen doubled as in\n\\fB\\-FF\\fP,\nthe archive is scanned from the beginning and \\fIzip\\fP scans for special\nsignatures to identify the limits between the archive members. The\nsingle\n.B \\-F\nis more reliable if the archive is not too much damaged, so try this\noption first.\n.IP\nIf the archive is too damaged or the end has been truncated, you\nmust use \\fB\\-FF\\fP.  This is a change from \\fIzip\\ 2.32\\fP, where\nthe \\fB\\-F\\fP option is able to read a truncated archive.  The\n\\fB\\-F\\fP option now more reliably fixes archives with minor\ndamage and the \\fB\\-FF\\fP option is needed to fix archives where\n\\fB\\-F\\fP might have been sufficient before.\n.IP\nNeither option will recover archives that have been incorrectly\ntransferred in ascii mode instead of binary. After the repair, the\n.B \\-t\noption of\n.I unzip\nmay show that some files have a bad CRC. Such files cannot be recovered;\nyou can remove them from the archive using the\n.B \\-d\noption of\n\\fIzip\\fP.\n.IP\nNote that \\fB\\-FF\\fP may have trouble fixing archives that include an\nembedded zip archive that was stored (without compression) in the archive\nand, depending on the damage, it may find the entries in the embedded\narchive rather than the archive itself.  Try \\fB\\-F\\fP first as it\ndoes not have this problem.\n.IP\nThe format of the fix commands have changed.  For example, to fix\nthe damaged archive \\fIfoo.zip\\fP,\n.RS\n.IP\n\\fCzip -F foo --out foofix\n.RE\n.IP\ntries to read the entries normally, copying good entries to the\nnew archive \\fIfoofix.zip\\fP.  If this doesn't work, as when the\narchive is truncated, or if some entries you know are in the archive\nare missed, then try\n.RS\n.IP\n\\fCzip -FF foo --out foofixfix\n.RE\n.IP\nand compare the resulting archive to the archive created by \\fB\\-F\\fP.  The\n\\fB\\-FF\\fP option may create an inconsistent archive.  Depending on\nwhat is damaged, you can then use the \\fB\\-F\\fP option to fix that archive.\n.IP\nA split archive with missing split files can be fixed using\n\\fB\\-F\\fP if you have the last split of the archive (the \\fB\\.zip\\fP file).\nIf this file is missing, you must use \\fB\\-FF\\fP to fix the archive,\nwhich will prompt you for the splits you have.\n.IP\nCurrently the fix options can't recover entries that have a bad checksum\nor are otherwise damaged.\n\n.TP\n.PD 0\n.B \\-FI\n.TP\n.PD\n.B \\-\\-fifo\n[Unix]  Normally \\fIzip\\fP skips reading any FIFOs (named pipes) encountered, as\n\\fIzip\\fP can hang if the FIFO is not being fed.  This option tells \\fIzip\\fP to\nread the contents of any FIFO it finds.\n\n.TP\n.PD 0\n.B \\-FS\n.TP\n.PD\n.B \\-\\-filesync\nSynchronize the contents of an archive with the files on the OS.\nNormally when an archive is updated, new files are added and changed\nfiles are updated but files that no longer exist on the OS are not\ndeleted from the archive.  This option enables a new mode that checks\nentries in the archive against the file system.  If the file time and\nfile size of the entry matches that of the OS file, the entry is\ncopied from the old archive instead of being read from the file system\nand compressed.  If the OS file has changed, the entry is read and\ncompressed as usual.  If the entry in the archive does not match a\nfile on the OS, the entry is deleted.  Enabling this option should\ncreate archives that are the same as new archives, but since existing\nentries are copied instead of compressed, updating an existing archive\nwith \\fB\\-FS\\fP can be much faster than creating a new archive.  Also\nconsider using \\fB\\-u\\fP for updating an archive.\n.IP\nFor this option to work, the archive should be updated from the same\ndirectory it was created in so the relative paths match.  If few files\nare being copied from the old archive, it may be faster to create a\nnew archive instead.\n.IP\nNote that the timezone environment variable TZ should be set according to\nthe local timezone in order for this option to work correctly.  A\nchange in timezone since the original archive was created could\nresult in no times matching and recompression of all files.\n.IP\nThis option deletes files from the archive.  If you need to preserve\nthe original archive, make a copy of the archive first or use the\n\\fB\\-\\-out\\fP option to output the updated archive to a new file.\nEven though it may be slower, creating a new archive with a new archive\nname is safer, avoids mismatches between archive and OS paths, and\nis preferred.\n\n.TP\n.PD 0\n.B \\-g\n.TP\n.PD\n.B \\-\\-grow \\ \\ \\ \\ \\ \\ \nGrow (append to) the specified\n.I zip\narchive, instead of creating a new one. If this operation fails,\n.I zip\nattempts to restore the archive to its original state. If the restoration\nfails, the archive might become corrupted. This option is ignored when\nthere's no existing archive or when at least one archive member must be\nupdated or deleted.\n\n.TP\n.PD 0\n.B \\-h\n.TP\n.PD 0\n.B \\-?\n.TP\n.PD\n.B \\-\\-help \\ \\ \\ \\ \\ \\ \nDisplay the\n.I zip\nhelp information (this also appears if\n.I zip\nis run with no arguments).\n\n.TP\n.PD 0\n.B \\-h2\n.TP\n.PD\n.B \\-\\-more-help\nDisplay extended help including more on command line format, pattern matching, and\nmore obscure options.\n\n.TP\n.PD 0\n.B \\-i\\ \\fRfiles\n.TP\n.PD\n.B \\-\\-include\\ \\fRfiles\nInclude only the specified files, as in:\n.RS\n.IP\n\\fCzip -r foo . -i \\\\*.c\\fP\n.RE\n.IP\nwhich will include only the files that end in\n.IR \\& .c\nin the current directory and its subdirectories. (Note for PKZIP\nusers: the equivalent command is\n.RS\n.IP\n\\fCpkzip -rP foo *.c\\fP\n.RE\n.IP\nPKZIP does not allow recursion in directories other than the current one.)\nThe backslash avoids the shell filename substitution, so that the\nname matching is performed by\n.I zip\nat all directory levels.\n[This is for Unix and other systems where \\\\  escapes the\nnext character.  For other systems where the shell does not\nprocess * do not use \\\\ and the above is\n.RS\n.IP\n\\fCzip -r foo . -i *.c\\fP\n.RE\n.IP\nExamples are for Unix unless otherwise specified.]  So to include dir,\na directory directly under the current directory, use\n.RS\n.IP\n\\fCzip -r foo . -i dir/\\\\*\n.RE\n.IP\nor\n.RS\n.IP\n\\fCzip -r foo . -i \"dir/*\"\n.RE\n.IP\nto match paths such as dir/a and dir/b/file.c [on\nports without wildcard expansion in the shell such as MSDOS and Windows\n.RS\n.IP\n\\fCzip -r foo . -i dir/*\n.RE\n.IP\nis used.]  Note that currently the trailing / is needed\nfor directories (as in\n.RS\n.IP\n\\fCzip -r foo . -i dir/\n.RE\n.IP\nto include directory dir).\n.IP\nThe long option form of the first example is\n.RS\n.IP\n\\fCzip -r foo . --include \\\\*.c\n.RE\n.IP\nand does the same thing as the short option form.\n.IP\nThough the command syntax used to require \\fB-i\\fR at\nthe end of the command line, this version actually\nallows \\fB\\-i\\fP (or \\fB\\-\\-include\\fP) anywhere.  The\nlist of files terminates at the next argument starting\nwith \\fB-\\fR, the end of the command line, or the list\nterminator \\fB@\\fR (an argument that is just @).  So\nthe above can be given as\n.RS\n.IP\nzip -i \\\\*.c @ -r foo .\\fP\n.RE\n.IP\nfor example.  There must be a space between\nthe option and the first file of a list.  For just\none file you can use the single value form\n.RS\n.IP\n\\fCzip -i\\\\*.c -r foo .\\fP\n.RE\n.IP\n(no space between option and value) or\n.RS\n.IP\n\\fCzip --include=\\\\*.c -r foo .\\fP\n.RE\n.IP\nas additional examples.  The single value forms are\nnot recommended because they can be confusing and,\nin particular, the \\fB\\-ifile\\fP format can cause\nproblems if the first letter of \\fBfile\\fP combines with\n\\fBi\\fP to form a two-letter option starting with\n\\fBi\\fP.  Use \\fB\\-sc\\fP to see how your command line\nwill be parsed.\n.IP\nAlso possible:\n.RS\n.IP\n\\fCzip -r foo  . -i@include.lst\\fP\n.RE\n.IP\nwhich will only include the files in the current directory and its\nsubdirectories that match the patterns in the file include.lst.\n.IP\nFiles to \\fB\\-i\\fR and \\fB\\-x\\fR are patterns matching internal archive paths.  See\n\\fB-R\\fR for more on patterns.\n\n.TP\n.PD 0\n.B \\-I\n.TP\n.PD\n.B \\-\\-no-image\n[Acorn RISC OS] Don't scan through Image files.  When used, \\fIzip\\fP will not\nconsider Image files (eg. DOS partitions or Spark archives when SparkFS\nis loaded) as directories but will store them as single files.\n\nFor example, if you have SparkFS loaded, zipping a Spark archive will result\nin a zipfile containing a directory (and its content) while using the 'I'\noption will result in a zipfile containing a Spark archive. Obviously this\nsecond case will also be obtained (without the 'I' option) if SparkFS isn't\nloaded.\n\n.TP\n.PD 0\n.B \\-ic\n.TP\n.PD\n.B \\-\\-ignore-case\n[VMS, WIN32] Ignore case when matching archive entries.  This option is\nonly available on systems where the case of files is ignored.  On systems\nwith case-insensitive file systems, case is normally ignored when matching files\non the file system but is not ignored for -f (freshen), -d (delete), -U (copy),\nand similar modes when matching against archive entries (currently -f\nignores case on VMS) because archive entries can be from systems where\ncase does matter and names that are the same except for case can exist\nin an archive.  The \\fB\\-ic\\fR option makes all matching case insensitive.\nThis can result in multiple archive entries matching a command line pattern.\n\n.TP\n.PD 0\n.B \\-j\n.TP\n.PD\n.B \\-\\-junk-paths\nStore just the name of a saved file (junk the path), and do not store\ndirectory names. By default,\n.I zip\nwill store the full path (relative to the current directory).\n\n.TP\n.PD 0\n.B \\-jj\n.TP\n.PD\n.B \\-\\-absolute-path\n[MacOS] record Fullpath (+ Volname). The complete path including\nvolume will be stored. By default the relative path will be stored.\n\n.TP\n.PD 0\n.B \\-J\n.TP\n.PD\n.B \\-\\-junk-sfx\nStrip any prepended data (e.g. a SFX stub) from the archive.\n.TP\n.PD 0\n.B \\-k\n.TP\n.PD\n.B \\-\\-DOS-names\nAttempt to convert the names and paths to conform to MSDOS,\nstore only the MSDOS attribute (just the user write attribute from Unix),\nand mark the entry as made under MSDOS (even though it was not);\nfor compatibility with PKUNZIP under MSDOS which cannot handle certain\nnames such as those with two dots.\n.TP\n.PD 0\n.B \\-l\n.TP\n.PD\n.B \\-\\-to-crlf\nTranslate the Unix end-of-line character LF into the\nMSDOS convention CR LF. This option should not be used on binary files.\nThis option can be used on Unix if the zip file is intended for PKUNZIP\nunder MSDOS. If the input files already contain CR LF, this option adds\nan extra CR. This is to ensure that\n\\fBunzip -a\\fP\non Unix will get back an exact copy of the original file,\nto undo the effect of\n\\fBzip -l\\fP.  See \\fB-ll\\fR for how binary files are handled.\n.TP\n.PD 0\n.B \\-la\n.TP\n.PD\n.B \\-\\-log-append\nAppend to existing logfile.  Default is to overwrite.\n.TP\n.PD 0\n.B \\-lf\\ \\fPlogfilepath\n.TP\n.PD\n.B \\-\\-logfile-path\\ \\fPlogfilepath\nOpen a logfile at the given path.  By default any existing file at that location\nis overwritten, but the \\fB\\-la\\fP option will result in an existing file being\nopened and the new log information appended to any existing information.\nOnly warnings and errors are written to the log unless the \\fB\\-li\\fP option is\nalso given, then all information messages are also written to the log.\n.TP\n.PD 0\n.B \\-li\n.TP\n.PD\n.B \\-\\-log-info\nInclude information messages, such as file names being zipped, in the log.\nThe default is to only include the command line, any warnings and errors, and\nthe final status.\n.TP\n.PD 0\n.B \\-ll\n.TP\n.PD\n.B \\-\\-from-crlf\nTranslate the MSDOS end-of-line CR LF into Unix LF.\nThis option should not be used on binary files.\nThis option can be used on MSDOS if the zip file is intended for unzip\nunder Unix.  If the file is converted and the file is later determined\nto be binary a warning is issued and the file is probably\ncorrupted.  In this release if \\fB-ll\\fR detects binary in the first buffer\nread from a file, \\fIzip\\fR now issues a warning and skips line end\nconversion on the file.  This check seems to catch all binary files\ntested, but the original check remains and if a converted file is\nlater determined to be binary that warning is still issued.  A new algorithm\nis now being used for binary detection that should allow line end conversion\nof text files in \\fBUTF-8\\fR and similar encodings.\n.TP\n.PD 0\n.B \\-L\n.TP\n.PD\n.B \\-\\-license\nDisplay the\n.I zip\nlicense.\n.TP\n.PD 0\n.B \\-m\n.TP\n.PD\n.B \\-\\-move \\ \\ \\ \nMove the specified files into the\n.I zip\narchive; actually,\nthis deletes the target directories/files after making the specified\n.I zip\narchive. If a directory becomes empty after removal of the files, the\ndirectory is also removed. No deletions are done until\n.I zip\nhas created the archive without error.\nThis is useful for conserving disk space,\nbut is potentially dangerous so it is recommended to use it in\ncombination with\n.B \\-T\nto test the archive before removing all input files.\n.TP\n.PD 0\n.B \\-MM\n.TP\n.PD\n.B \\-\\-must-match\nAll input patterns must match at least one file and all input files\nfound must be readable.  Normally when an input pattern does not match\na file the \"name not matched\" warning is issued and when an input file\nhas been found but later is missing or not readable a missing or not\nreadable warning is issued.  In either case\n.I zip\ncontinues creating the archive, with missing or unreadable new files\nbeing skipped and files already in the archive remaining unchanged.\nAfter the archive is created, if any files were not readable\n.I zip\nreturns the OPEN error code (18 on most systems) instead of the normal\nsuccess return (0 on most systems).  With \\fB\\-MM\\fP set,\n.I zip\nexits as soon as an input pattern is not matched (whenever the\n\"name not matched\" warning would be issued) or when an input file is\nnot readable.  In either case \\fIzip\\fR exits with an OPEN error\nand no archive is created.\n.IP\nThis option is useful when a known list of files is to be zipped so\nany missing or unreadable files will result in an error.  It is less\nuseful when used with wildcards, but \\fIzip\\fR will still exit with an\nerror if any input pattern doesn't match at least one file and if any\nmatched files are unreadable.  If you want to create the archive\nanyway and only need to know if files were skipped, don't use\n.B \\-MM\nand just check the return code.  Also \\fB\\-lf\\fP could be useful.\n.TP\n.PD 0\n.BI \\-n\\ \\fRsuffixes\n.TP\n.PD\n.B \\-\\-suffixes\\ \\fRsuffixes\nDo not attempt to compress files named with the given\n\\fBsuffixes\\fR.\nSuch files are simply stored (0% compression) in the output zip file,\nso that\n.I zip\ndoesn't waste its time trying to compress them.\nThe suffixes are separated by\neither colons or semicolons.  For example:\n.RS\n.IP\n\\fCzip -rn .Z:.zip:.tiff:.gif:.snd  foo foo\\fP\n.RE\n.IP\nwill copy everything from\n.I foo\ninto\n.IR foo.zip ,\nbut will store any files that end in\n.IR .Z ,\n.IR .zip ,\n.IR .tiff ,\n.IR .gif ,\nor\n.I .snd\nwithout trying to compress them\n(image and sound files often have their own specialized compression methods).\nBy default,\n.I zip\ndoes not compress files with extensions in the list\n.I .Z:.zip:.zoo:.arc:.lzh:.arj.\nSuch files are stored directly in the output archive.\nThe environment variable ZIPOPT can be used to change the default options. For\nexample under Unix with csh:\n.RS\n.IP\nsetenv ZIPOPT \"-n .gif:.zip\"\n.RE\n.IP\nTo attempt compression on all files, use:\n.RS\n.IP\nzip -n : foo\n.RE\n.IP\nThe maximum compression option\n.B \\-9\nalso attempts compression on all files regardless of extension.\n.IP\nOn Acorn RISC OS systems the suffixes are actually filetypes (3 hex digit\nformat). By default, \\fIzip\\fP does not compress files with filetypes in the list\nDDC:D96:68E (i.e. Archives, CFS files and PackDir files).\n.TP\n.PD 0\n.B \\-nw\n.TP\n.PD\n.B \\-\\-no-wild\nDo not perform internal wildcard processing (shell processing of wildcards is still done\nby the shell unless the arguments are escaped).  Useful if a list of paths is being\nread and no wildcard substitution is desired.\n.TP\n.PD 0\n.B \\-N\n.TP\n.PD\n.B \\-\\-notes\n[Amiga, MacOS] Save Amiga or MacOS filenotes as zipfile comments. They can be\nrestored by using the -N option of \\fIunzip\\fP. If -c is used also, you are\nprompted for comments only for those files that do not have filenotes.\n.TP\n.PD 0\n.B \\-o\n.TP\n.PD\n.B \\-\\-latest-time\nSet the \"last modified\" time of the\n.I zip\narchive to the latest (oldest) \"last modified\" time\nfound among the entries in the\n.I zip\narchive.\nThis can be used without any other operations, if desired.\nFor example:\n.IP\n\\fCzip -o foo\\fP\n.IP\nwill change the last modified time of\n\\fBfoo.zip\\fP\nto the latest time of the entries in\n.BR foo.zip .\n.TP\n.PD 0\n.B \\-O \\fPoutput-file\n.TP\n.PD\n.B \\-\\-output-file \\fPoutput-file\nProcess the archive changes as usual, but instead of updating the existing archive,\noutput the new archive to output-file.  Useful for updating an archive\nwithout changing the existing archive and the input archive must be a different file\nthan the output archive.\n\nThis option can be used to create updated split archives.\nIt can also be used with \\fB\\-U\\fP to copy entries from an existing archive to a new\narchive.  See the \\fBEXAMPLES\\fP section below.\n\nAnother use is converting \\fIzip\\fP files from one split size to another.  For instance,\nto convert an archive with 700 MB CD splits to one with 2 GB DVD splits, can use:\n.RS\n.IP\nzip -s 2g cd-split.zip --out dvd-split.zip\n.RE\n.IP\nwhich uses copy mode.  See \\fB\\-U\\fP below.  Also:\n.RS\n.IP\nzip -s 0 split.zip --out unsplit.zip\n.RE\n.IP\nwill convert a split archive to a single-file archive.\n\nCopy mode will convert stream entries (using data descriptors and which\nshould be compatible with most unzips) to normal entries (which should\nbe compatible\nwith all unzips), except if standard encryption was used.  For archives\nwith encrypted entries, \\fIzipcloak\\fP will decrypt the entries and convert\nthem to normal entries.\n.TP\n.PD 0\n.B \\-p\n.TP\n.PD\n.B \\-\\-paths\nInclude relative file paths as part of the names of files stored in the archive.\nThis is the default.  The \\fB\\-j\\fP option junks the paths and just stores the\nnames of the files.\n.TP\n.PD 0\n.B \\-P\\ \\fRpassword\n.TP\n.PD\n.B \\-\\-password\\ \\fRpassword\nUse \\fIpassword\\fP to encrypt zipfile entries (if any).  \\fBTHIS IS\nINSECURE!\\fP  Many multi-user operating systems provide ways for any user to\nsee the current command line of any other user; even on stand-alone systems\nthere is always the threat of over-the-shoulder peeking.  Storing the plaintext\npassword as part of a command line in an automated script is even worse.\nWhenever possible, use the non-echoing, interactive prompt to enter passwords.\n(And where security is truly important, use strong encryption such as Pretty\nGood Privacy instead of the relatively weak standard encryption provided by\nzipfile utilities.)\n.TP\n.PD 0\n.B \\-q\n.TP\n.PD\n.B \\-\\-quiet\nQuiet mode;\neliminate informational messages and comment prompts.\n(Useful, for example, in shell scripts and background tasks).\n.TP\n.PD 0\n.BI \\-Q\\fRn\n.TP\n.PD\n.B \\-\\-Q\\-flag\\ \\fRn\n[QDOS] store information about the file in the file header with n defined as\n.RS\nbit  0: Don't add headers for any file\n.RE\n.RS\nbit  1: Add headers for all files\n.RE\n.RS\nbit  2: Don't wait for interactive key press on exit\n.RE\n.TP\n.PD 0\n.B \\-r\n.TP\n.PD\n.B \\-\\-recurse\\-paths\nTravel the directory structure recursively;\nfor example:\n.RS\n.IP\nzip -r foo.zip foo\n.RE\n.IP\nor more concisely\n.RS\n.IP\nzip -r foo foo\n.RE\n.IP\nIn this case, all the files and directories in\n.B foo\nare saved in a\n.I zip\narchive named \\fBfoo.zip\\fP,\nincluding files with names starting with \\fB\".\"\\fP,\nsince the recursion does not use the shell's file-name substitution mechanism.\nIf you wish to include only a specific subset of the files in directory\n\\fBfoo\\fP\nand its subdirectories, use the\n\\fB\\-i\\fP\noption to specify the pattern of files to be included.\nYou should not use\n\\fB\\-r\\fP\nwith the name \\fB\".*\"\\fP,\nsince that matches \\fB\"..\"\\fP\nwhich will attempt to zip up the parent directory\n(probably not what was intended).\n.IP\nMultiple source directories are allowed as in\n.RS\n.IP\n\\fCzip -r foo foo1 foo2\\fP\n.RE\n.IP\nwhich first zips up \\fBfoo1\\fP and then \\fBfoo2\\fP, going down each directory.\n.IP\nNote that while wildcards to \\fB-r\\fR are typically resolved while recursing down\ndirectories in the file system, any \\fB-R\\fN, \\fB-x\\fR, and \\fB-i\\fR wildcards\nare applied to internal archive pathnames once the directories are scanned.\nTo have wildcards apply to files in subdirectories when recursing on\nUnix and similar systems where the shell does wildcard substitution, either\nescape all wildcards or put all arguments with wildcards in quotes.  This lets\n\\fIzip\\fR see the wildcards and match files in subdirectories using them as\nit recurses.\n.TP\n.PD 0\n.B \\-R\n.TP\n.PD\n.B \\-\\-recurse\\-patterns\nTravel the directory structure recursively starting at the\ncurrent directory;\nfor example:\n.RS\n.IP\n\\fCzip -R foo \"*.c\"\\fP\n.RE\n.IP\nIn this case, all the files matching \\fB*.c\\fP in the tree starting at the\ncurrent directory are stored into a\n.I zip\narchive named\n\\fBfoo.zip\\fP.\nNote that \\fB*.c\\fP will match \\fBfile.c\\fP, \\fBa/file.c\\fP\nand \\fBa/b/.c\\fP.  More than one pattern can be listed as separate\narguments.\nNote for PKZIP users: the equivalent command is\n.RS\n.IP\n\\fCpkzip -rP foo *.c\\fP\n.RE\n.IP\nPatterns are relative file paths as they appear in the archive, or will after\nzipping, and can have optional wildcards in them.  For example, given\nthe current directory is \\fBfoo\\fP and under it are directories \\fBfoo1\\fP and \\fBfoo2\\fP\nand in \\fBfoo1\\fP is the file \\fBbar.c\\fP,\n.RS\n.IP\n\\fCzip -R foo/*\\fP\n.RE\n.IP\nwill zip up \\fBfoo\\fP, \\fBfoo/foo1\\fP, \\fBfoo/foo1/bar.c\\fP, and \\fBfoo/foo2\\fP.\n.RS\n.IP\n\\fCzip -R */bar.c\\fP\n.RE\n.IP\nwill zip up \\fBfoo/foo1/bar.c\\fP.  See the note for \\fB-r\\fR on escaping wildcards.\n\n.TP\n.PD 0\n.B \\-RE\n.TP\n.PD\n.B \\-\\-regex\n[WIN32]  Before \\fIzip\\fP \\fI3.0\\fP, regular expression list matching was\nenabled by default on Windows platforms.  Because of confusion resulting\nfrom the need to escape \"[\" and \"]\" in names, it is now off by default for\nWindows so \"[\" and \"]\" are just normal characters in names.  This option\nenables [] matching again.\n\n.TP\n.PD 0\n.B \\-s\\ \\fPsplitsize\n.TP\n.PD\n.B \\-\\-split\\-size\\ \\fPsplitsize\nEnable creating a split archive and set the split size.  A split archive is an archive\nthat could be split over many files.  As the archive is created, if the size of the\narchive reaches the specified split size, that split is closed and the next split\nopened.  In general all splits but the last will be the split size and the last\nwill be whatever is left.  If the entire archive is smaller than the split size a\nsingle-file archive is created.\n\nSplit archives are stored in numbered files.  For example, if the output\narchive is named \\fBarchive\\fP and three splits are required, the resulting\narchive will be in the three files \\fBarchive.z01\\fP, \\fBarchive.z02\\fP, and\n\\fBarchive.zip\\fP.  Do not change the numbering of these files or the archive\nwill not be readable as these are used to determine the order the splits are read.\n\nSplit size is a number optionally followed by a multiplier.  Currently the\nnumber must be an integer.  The multiplier can currently be one of\n\\fBk\\fP (kilobytes), \\fBm\\fP (megabytes), \\fBg\\fP (gigabytes), or \\fBt\\fP\n(terabytes).  As 64k is the minimum split size, numbers without multipliers\ndefault to megabytes.  For example, to create a split archive called \\fBfoo\\fP\nwith the contents of the \\fBbar\\fP directory with splits of 670 MB that might\nbe useful for burning on CDs, the command:\n.RS\n.IP\nzip -s 670m -r foo bar\n.RE\n.IP\ncould be used.\n\nCurrently the old splits of a split archive are not excluded from a new\narchive, but they can be specifically excluded.  If possible, keep\nthe input and output archives out of the path being zipped when creating\nsplit archives.\n\nUsing \\fB\\-s\\fP without \\fB\\-sp\\fP as above creates all the splits where\n\\fBfoo\\fP is being written, in this case the current directory.  This split\nmode updates the splits as the archive is being created, requiring all\nsplits to remain writable, but creates split archives that are readable by\nany unzip that supports split archives.  See \\fB\\-sp\\fP below for enabling\nsplit pause mode which allows splits to be written directly to removable\nmedia.\n\nThe option \\fB\\-sv\\fP can be used to enable verbose splitting and provide details of\nhow the splitting is being done.  The \\fB\\-sb\\fP option can be used to ring the bell\nwhen \\fIzip\\fP pauses for the next split destination.\n\nSplit archives cannot be updated, but see the \\fB\\-O\\fP (\\fB\\-\\-out\\fP) option for\nhow a split archive can be updated as it is copied to a new archive.\nA split archive can also be converted into a single-file archive using a\nsplit size of 0 or negating the \\fB\\-s\\fP option:\n.RS\n.IP\nzip -s 0 split.zip --out single.zip\n.RE\n.IP\nAlso see \\fB\\-U\\fP (\\fB\\-\\-copy\\fP) for more on using copy mode.\n.TP\n.PD 0\n.B \\-sb\n.TP\n.PD\n.B \\-\\-split\\-bell\nIf splitting and using split pause mode, ring the bell when \\fIzip\\fP pauses\nfor each split destination.\n.TP\n.PD 0\n.B \\-sc\n.TP\n.PD\n.B \\-\\-show\\-command\nShow the command line starting \\fIzip\\fP as processed and exit.  The new command parser\npermutes the arguments, putting all options and any values associated with them\nbefore any non-option arguments.  This allows an option to appear anywhere in the\ncommand line as long as any values that go with the option go with it.  This option\ndisplays the command line as \\fIzip\\fP sees it, including any arguments from\nthe environment such as from the \\fBZIPOPT\\fP variable.  Where allowed, options later\nin the command line can override options earlier in the command line.\n.TP\n.PD 0\n.B \\-sf\n.TP\n.PD\n.B \\-\\-show\\-files\nShow the files that would be operated on, then exit.  For instance, if creating\na new archive, this will list the files that would be added.  If the option is\nnegated, \\fB\\-sf\\-\\fP, output only to an open log file.  Screen display is\nnot recommended for large lists.\n.TP\n.PD 0\n.B \\-so\n.TP\n.PD\n.B \\-\\-show\\-options\nShow all available options supported by \\fIzip\\fP as compiled on the current system.\nAs this command reads the option table, it should include all options.  Each line\nincludes the short option (if defined), the long option (if defined), the format\nof any value that goes with the option, if the option can be negated, and a\nsmall description.  The value format can be no value, required value, optional\nvalue, single character value, number value, or a list of values.  The output of\nthis option is not intended to show how to use any option but only\nshow what options are available.\n.TP\n.PD 0\n.B \\-sp\n.TP\n.PD\n.B \\-\\-split\\-pause\nIf splitting is enabled with \\fB\\-s\\fP, enable split pause mode.  This\ncreates split archives as \\fB\\-s\\fP does, but stream writing is used so each\nsplit can be closed as soon as it is written and \\fIzip\\fP will pause between each\nsplit to allow changing split destination or media.\n\nThough this split mode allows writing splits directly to removable media, it\nuses stream archive format that may not be readable by some unzips.  Before\nrelying on splits created with \\fB\\-sp\\fP, test a split archive with the unzip\nyou will be using.\n\nTo convert a stream split archive (created with \\fB\\-sp\\fP) to a standard archive\nsee the \\fB\\-\\-out\\fP option.\n.TP\n.PD 0\n.B \\-su\n.TP\n.PD\n.B \\-\\-show\\-unicode\nAs \\fB\\-sf\\fP, but also show Unicode version of the path if exists.\n.TP\n.PD 0\n.B \\-sU\n.TP\n.PD\n.B \\-\\-show\\-just\\-unicode\nAs \\fB\\-sf\\fP, but only show Unicode version of the path if exists, otherwise show\nthe standard version of the path.\n.TP\n.PD 0\n.B \\-sv\n.TP\n.PD\n.B \\-\\-split\\-verbose\nEnable various verbose messages while splitting, showing how the splitting is being\ndone.\n.TP\n.PD 0\n.B \\-S\n.TP\n.PD\n.B \\-\\-system-hidden\n[MSDOS, OS/2, WIN32 and ATARI] Include system and hidden files.\n.RS\n[MacOS] Includes finder invisible files, which are ignored otherwise.\n.RE\n.TP\n.PD 0\n.BI \\-t\\ \\fRmmddyyyy\n.TP\n.PD\n.B \\-\\-from\\-date\\ \\fRmmddyyyy\nDo not operate on files modified prior to the specified date,\nwhere\n.B mm\nis the month (00-12),\n.B dd\nis the day of the month (01-31),\nand\n.B yyyy\nis the year.\nThe\n.I ISO\\ 8601\ndate format\n.B yyyy\\-mm\\-dd\nis also accepted.\nFor example:\n.RS\n.IP\n\\fCzip -rt 12071991 infamy foo\\fP\n\n\\fCzip -rt 1991-12-07 infamy foo\\fP\n.RE\n.IP\nwill add all the files in\n.B foo\nand its subdirectories that were last modified on or after 7 December 1991,\nto the\n.I zip\narchive\n.BR infamy.zip .\n.TP\n.PD 0\n.BI \\-tt\\ \\fRmmddyyyy\n.TP\n.PD\n.B \\-\\-before\\-date\\ \\fRmmddyyyy\nDo not operate on files modified after or at the specified date,\nwhere\n.B mm\nis the month (00-12),\n.B dd\nis the day of the month (01-31),\nand\n.B yyyy\nis the year.\nThe\n.I ISO\\ 8601\ndate format\n.B yyyy\\-mm\\-dd\nis also accepted.\nFor example:\n.RS\n.IP\n\\fCzip -rtt 11301995 infamy foo\\fP\n\n\\fCzip -rtt 1995-11-30 infamy foo\\fP\n.RE\n.IP\nwill add all the files in\n.B foo\nand its subdirectories that were last modified before 30 November 1995,\nto the\n.I zip\narchive\n.BR infamy.zip .\n.TP\n.PD 0\n.B \\-T\n.TP\n.PD\n.B \\-\\-test\\ \\ \\ \\ \nTest the integrity of the new zip file. If the check fails, the old zip file\nis unchanged and (with the\n.B -m\noption) no input files are removed.\n.TP\n.PD 0\n.B \\-TT\\ \\fPcmd\n.TP\n.PD\n.B \\-\\-unzip-command\\ \\fPcmd\nUse command cmd instead of 'unzip -tqq' to test an archive when the \\fB\\-T\\fP\noption is used.  On Unix, to use a copy of unzip in the current directory instead\nof the standard system unzip, could use:\n.IP\n\\fC zip archive file1 file2 -T -TT \"./unzip -tqq\"\\fP\n.IP\nIn cmd, {} is replaced by the name of the temporary archive, otherwise the name\nof the archive is appended to the end of the command.\nThe return code is checked for success (0 on Unix).\n.TP\n.PD 0\n.B \\-u\n.TP\n.PD\n.B \\-\\-update\nReplace (update) an existing entry in the\n.I zip\narchive only if it has been modified more recently\nthan the version already in the\n.I zip\narchive.\nFor example:\n.RS\n.IP\n\\fCzip -u stuff *\\fP\n.RE\n.IP\nwill add any new files in the current directory,\nand update any files which have been modified since the\n.I zip\narchive\n.I stuff.zip\nwas last created/modified (note that\n.I zip\nwill not try to pack\n.I stuff.zip\ninto itself when you do this).\n.IP\nNote that the\n.B \\-u\noption with no input file arguments acts like the\n.B \\-f\n(freshen) option.\n.TP\n.PD 0\n.B \\-U\n.TP\n.PD\n.B \\-\\-copy\\-entries\nCopy entries from one archive to another.  Requires the \\fB\\-\\-out\\fP\noption to specify a different output file than the input archive.  Copy\nmode is the reverse of \\fB\\-d\\fP delete.  When delete is being used\nwith \\fB\\-\\-out\\fP, the selected entries are deleted from the archive\nand all other entries are copied to the new archive, while copy mode\nselects the files to include in the new archive.  Unlike \\fB\\-u\\fP\nupdate, input patterns on the command line are matched against archive\nentries only and not the file system files.  For instance,\n.RS\n.IP\n\\fCzip inarchive \"*.c\" --copy --out outarchive\\fP\n.RE\n.IP\ncopies entries with names ending in \\fB\\.c\\fP from \\fBinarchive\\fP\nto \\fBoutarchive\\fP.  The wildcard must be escaped on some systems\nto prevent the shell from substituting names of files from the\nfile system which may have no relevance to the entries in the archive.\n\nIf no input files appear on the command line and \\fB\\-\\-out\\fP is\nused, copy mode is assumed:\n.RS\n.IP\n\\fCzip inarchive --out outarchive\\fP\n.RE\n.IP\nThis is useful for changing split size for instance.  Encrypting\nand decrypting entries is not yet supported using copy mode.  Use\n\\fIzipcloak\\fP for that.\n.TP\n.PD 0\n.B \\-UN\\ \\fRv\n.TP\n.PD\n.B \\-\\-unicode\\ \\fRv\nDetermine what \\fIzip\\fP should do with Unicode file names.\n\\fIzip\\ 3.0\\fP, in addition to the standard file path, now\nincludes the UTF\\-8 translation of the path if the entry path\nis not entirely 7-bit ASCII.  When an entry\nis missing the Unicode path, \\fIzip\\fP reverts back to the\nstandard file path.  The problem with using the standard path\nis this path is in the local character set of the zip that created\nthe entry, which may contain characters that are not valid in\nthe character set being used by the unzip.  When \\fIzip\\fP is\nreading an archive, if an entry also has a Unicode path,\n\\fIzip\\fP now defaults to using the Unicode path to recreate\nthe standard path using the current local character set.\n\nThis option can be used to determine what \\fIzip\\fP should do\nwith this path if there is a mismatch between the stored standard path\nand the stored UTF-8 path (which can happen if the standard path was\nupdated).  In all cases, if there is a mismatch it is\nassumed that the standard path is more current and\n\\fIzip\\fP uses that.  Values for \\fBv\\fP are\n.RS\n.IP\nq \\- quit if paths do not match\n.IP\nw \\- warn, continue with standard path\n.IP\ni \\- ignore, continue with standard path\n.IP\nn \\- no Unicode, do not use Unicode paths\n.RE\n.IP\nThe default is to warn and continue.\n\nCharacters that are not valid in the current character set are\nescaped as \\fB#Uxxxx\\fP and \\fB#Lxxxxxx\\fP, where x is an\nASCII character for a hex digit.  The first is used if a 16-bit\ncharacter number is sufficient to represent the Unicode character\nand the second if the character needs more than 16 bits to\nrepresent it's Unicode character code.  Setting \\fB\\-UN\\fP to\n.RS\n.IP\ne \\- escape\n.RE\n.IP\nas in\n.RS\n.IP\n\\fCzip archive -sU -UN=e\\fP\n.RE\n.IP\nforces \\fIzip\\fP to escape all characters that are not printable 7-bit\nASCII.\n\nNormally \\fIzip\\fP stores UTF\\-8 directly in the standard path field\non systems where UTF\\-8 is the current character set and stores the\nUTF\\-8 in the new extra fields otherwise.  The option\n.RS\n.IP\nu \\- UTF\\-8\n.RE\n.IP\nas in\n.RS\n.IP\n\\fCzip archive dir -r -UN=UTF8\\fP\n.RE\n.IP\nforces \\fIzip\\fP to store UTF\\-8 as native in the archive.  Note that\nstoring UTF\\-8 directly is the default on Unix systems that support it.\nThis option could be useful on Windows systems where the escaped\npath is too large to be a valid path and the UTF\\-8 version of the\npath is smaller, but native UTF\\-8 is not backward compatible on\nWindows systems.\n\n.TP\n.PD 0\n.B \\-v\n.TP\n.PD\n.B \\-\\-verbose\nVerbose mode or print diagnostic version info.\n.IP\nNormally, when applied to real operations, this option enables the display of a\nprogress indicator during compression (see \\fB-dd\\fR for more on dots) and\nrequests verbose diagnostic info about zipfile structure oddities.\n.IP\nHowever, when\n.B \\-v\nis the only command line argument a diagnostic screen is printed instead.  This\nshould now work even if stdout is redirected to a file, allowing easy saving\nof the information for sending with bug reports to Info-ZIP.  The version\nscreen provides the help screen header with program name, version, and release\ndate, some pointers to the Info-ZIP home and distribution sites, and shows\ninformation about the target environment (compiler type and version, OS\nversion, compilation date and the enabled optional features used to create the\n.I zip\nexecutable).\n.TP\n.PD 0\n.B \\-V\n.TP\n.PD\n.B \\-\\-VMS\\-portable\n[VMS] Save VMS file attributes.\n(Files are  truncated at EOF.)   When a -V archive is unpacked on a\nnon-VMS system,  some file types (notably Stream_LF\ntext files  and  pure binary files  like fixed-512)\nshould be extracted intact.  Indexed files and file\ntypes with embedded record sizes (notably variable-length record types)\nwill probably be seen as corrupt elsewhere.\n.TP\n.PD 0\n.B \\-VV\n.TP\n.PD\n.B \\-\\-VMS\\-specific\n[VMS] Save VMS file attributes, and  all allocated\nblocks in a file,  including  any  data beyond EOF.\nUseful for moving ill-formed files  among  VMS systems.   When a -VV archive is\nunpacked on a non-VMS system, almost all files will appear corrupt.\n.TP\n.PD 0\n.B \\-w\n.TP\n.PD\n.B \\-\\-VMS\\-versions\n[VMS] Append the version number of the files to the name,\nincluding multiple versions of files.  Default is to use only\nthe most recent version of a specified file.\n.TP\n.PD 0\n.B \\-ww\n.TP\n.PD\n.B \\-\\-VMS\\-dot\\-versions\n[VMS] Append the version number of the files to the name,\nincluding multiple versions of files, using the \\.nnn format.\nDefault is to use only the most recent version of a specified\nfile.\n.TP\n.PD 0\n.BI \\-ws\n.TP\n.PD\n.B \\-\\-wild\\-stop\\-dirs\nWildcards match only at a directory level.  Normally \\fIzip\\fP handles\npaths as strings and given the paths\n.RS\n.IP\n/foo/bar/dir/file1.c\n.IP\n/foo/bar/file2.c\n.RE\n.IP\nan input pattern such as\n.RS\n.IP\n/foo/bar/*\n.RE\n.IP\nnormally would match both paths, the * matching \\fBdir/file1.c\\fP\nand \\fBfile2.c\\fP.  Note that in the first case a directory\nboundary (/) was crossed in the match.  With \\fB\\-ws\\fP no\ndirectory bounds will be included in the match, making\nwildcards local to a specific directory level.  So, with\n\\fB\\-ws\\fP enabled, only the second path would be matched.\n\nWhen using \\fB\\-ws\\fP, use ** to match across directory boundaries as\n* does normally.\n.TP\n.PD 0\n.BI \\-x\\ \\fRfiles\n.TP\n.PD\n.B \\-\\-exclude\\ \\fRfiles\nExplicitly exclude the specified files, as in:\n.RS\n.IP\n\\fCzip -r foo foo -x \\\\*.o\\fP\n.RE\n.IP\nwhich will include the contents of\n.B foo\nin\n.B foo.zip\nwhile excluding all the files that end in\n\\fB.o\\fP.\nThe backslash avoids the shell filename substitution, so that the\nname matching is performed by\n.I zip\nat all directory levels.\n.IP\nAlso possible:\n.RS\n.IP\n\\fCzip -r foo foo -x@exclude.lst\\fP\n.RE\n.IP\nwhich will include the contents of\n.B foo\nin\n.B foo.zip\nwhile excluding all the files that match the patterns in the file\n\\fBexclude.lst\\fP.\n.IP\nThe long option forms of the above are\n.RS\n.IP\n\\fCzip -r foo foo --exclude \\\\*.o\\fP\n.RE\n.IP\nand\n.RS\n.IP\n\\fCzip -r foo foo --exclude @exclude.lst\\fP\n.RE\n.IP\nMultiple patterns can be specified, as in:\n.RS\n.IP\n\\fCzip -r foo foo -x \\\\*.o \\\\*.c\\fP\n.RE\n.IP\nIf there is no space between \\fB\\-x\\fP and\nthe pattern, just one value is assumed (no list):\n.RS\n.IP\n\\fCzip -r foo foo -x\\\\*.o\\fP\n.RE\n.IP\n.IP\nSee \\fB-i\\fR for more on include and exclude.\n.TP\n.PD 0\n.B \\-X\n.TP\n.PD\n.B \\-\\-no\\-extra\nDo not save extra file attributes (Extended Attributes on OS/2, uid/gid\nand file times on Unix).  The zip format uses extra fields to include\nadditional information for each entry.  Some extra fields are specific\nto particular systems while others are applicable to all systems.\nNormally when \\fIzip\\fP reads entries from an existing archive, it\nreads the extra fields it knows, strips the rest, and adds\nthe extra fields applicable to that system.  With \\fB\\-X\\fP, \\fIzip\\fP strips\nall old fields and only includes the Unicode and Zip64 extra fields\n(currently these two extra fields cannot be disabled).\n\nNegating this option, \\fB\\-X\\-\\fP, includes all the default extra fields,\nbut also copies over any unrecognized extra fields.\n.TP\n.PD 0\n.B \\-y\n.TP\n.PD\n.B \\-\\-symlinks\nFor UNIX and VMS (V8.3 and later), store symbolic links as such in the\n.I zip\narchive, instead of compressing and storing the file referred to by\nthe link.  This can avoid multiple copies of files being included in\nthe archive as \\fIzip\\fP recurses the directory trees and accesses\nfiles directly and by links.\n.TP\n.PD 0\n.B \\-z\n.TP\n.PD\n.B \\-\\-archive\\-comment\nPrompt for a multi-line comment for the entire\n.I zip\narchive.\nThe comment is ended by a line containing just a period,\nor an end of file condition (^D on Unix, ^Z on MSDOS, OS/2, and VMS).\nThe comment can be taken from a file:\n.RS\n.IP\n\\fCzip -z foo < foowhat\\fP\n.RE\n.TP\n.PD 0\n.B \\-Z\\ \\fRcm\n.TP\n.PD\n.B \\-\\-compression\\-method\\ \\fRcm\nSet the default compression method.  Currently the main methods supported\nby \\fIzip\\fP are \\fBstore\\fP and \\fBdeflate\\fP.  Compression method\ncan be set to:\n\n\\fBstore\\fP \\- Setting the compression method to \\fBstore\\fP forces\n\\fIzip\\fP to store entries with no compression.  This is generally\nfaster than compressing entries, but results in no space savings.\nThis is the same as using \\fB\\-0\\fP (compression level zero).\n\n\\fBdeflate\\fP \\- This is the default method for \\fIzip\\fP.  If \\fIzip\\fP\ndetermines that storing is better than deflation, the entry will be\nstored instead.\n\n\\fBbzip2\\fP \\- If \\fBbzip2\\fP support is compiled in, this compression\nmethod also becomes available.  Only some modern unzips currently support\nthe \\fBbzip2\\fP compression method, so test the unzip you will be using\nbefore relying on archives using this method (compression method 12).\n\nFor example, to add \\fBbar.c\\fP to archive \\fBfoo\\fP using \\fBbzip2\\fP\ncompression:\n.RS\n.IP\nzip -Z bzip2 foo bar.c\n.RE\n.IP\nThe compression method can be abbreviated:\n.RS\n.IP\nzip -Zb foo bar.c\n.RE\n.IP\n.TP\n.PD 0\n.BI \\-#\n.TP\n.PD\n.B (\\-0, \\-1, \\-2, \\-3, \\-4, \\-5, \\-6, \\-7, \\-8, \\-9)\nRegulate the speed of compression using the specified digit\n.BR # ,\nwhere\n.B \\-0\nindicates no compression (store all files),\n.B \\-1\nindicates the fastest compression speed (less compression)\nand\n.B \\-9\nindicates the slowest compression speed (optimal compression, ignores\nthe suffix list). The default compression level is\n.BR \\-6.\n\nThough still being worked, the intention is this setting will control\ncompression speed for all compression methods.  Currently only\ndeflation is controlled.\n.TP\n.PD 0\n.B \\-!\n.TP\n.PD\n.B \\-\\-use\\-privileges\n[WIN32] Use priviliges (if granted) to obtain all aspects of WinNT security.\n.TP\n.PD 0\n.B \\-@\n.TP\n.PD\n.B \\-\\-names\\-stdin\nTake the list of input files from standard input. Only one filename per line.\n.TP\n.PD 0\n.B \\-$\n.TP\n.PD\n.B \\-\\-volume\\-label\n[MSDOS, OS/2, WIN32] Include the volume label for the drive holding\nthe first file to be compressed.  If you want to include only the volume\nlabel or to force a specific drive, use the drive name as first file name,\nas in:\n.RS\n.IP\n\\fCzip -$ foo a: c:bar\\fP\n.RE\n.IP\n.SH \"EXAMPLES\"\nThe simplest example:\n.IP\n\\fCzip stuff *\\fP\n.LP\ncreates the archive\n.I stuff.zip\n(assuming it does not exist)\nand puts all the files in the current directory in it, in compressed form\n(the\n\\fB\\&.zip\\fP\nsuffix is added automatically, unless the archive name contains\na dot already;\nthis allows the explicit specification of other suffixes).\n.LP\nBecause of the way the shell on Unix does filename substitution,\nfiles starting with \".\" are not included;\nto include these as well:\n.IP\n\\fCzip stuff .* *\\fP\n.LP\nEven this will not include any subdirectories from the current directory.\n.LP\nTo zip up an entire directory, the command:\n.IP\n\\fCzip -r foo foo\\fP\n.LP\ncreates the archive\n.IR foo.zip ,\ncontaining all the files and directories in the directory\n.I foo\nthat is contained within the current directory.\n.LP\nYou may want to make a\n.I zip\narchive that contains the files in\n.IR foo ,\nwithout recording the directory name,\n.IR foo .\nYou can use the\n.B \\-j\noption to leave off the paths,\nas in:\n.IP\n\\fCzip -j foo foo/*\\fP\n.LP\nIf you are short on disk space,\nyou might not have enough room to hold both the original directory\nand the corresponding compressed\n.I zip\narchive.\nIn this case, you can create the archive in steps using the\n.B \\-m\noption.\nIf\n.I foo\ncontains the subdirectories\n.IR tom ,\n.IR dick ,\nand\n.IR harry ,\nyou can:\n.IP\n\\fCzip -rm foo foo/tom\\fP\n.br\n\\fCzip -rm foo foo/dick\\fP\n.br\n\\fCzip -rm foo foo/harry\\fP\n.LP\nwhere the first command creates\n.IR foo.zip ,\nand the next two add to it.\nAt the completion of each\n.I zip\ncommand,\nthe last created archive is deleted,\nmaking room for the next\n.I zip\ncommand to function.\n\n\n\n.LP\nUse \\fB\\-s\\fP to set the split size and create a split archive.  The size is given as\na number followed optionally by one of k (kB), m (MB), g (GB), or t (TB).\nThe command\n.IP\n\\fCzip -s 2g -r split.zip foo\\fP\n.LP\ncreates a split archive of the directory foo with splits no bigger than 2\\ GB each.  If\nfoo contained 5\\ GB of contents and the contents were stored in the split archive without\ncompression (to make this example simple), this would create three splits, split.z01 at 2\\ GB,\nsplit.z02 at 2\\ GB, and split.zip at a little over 1\\ GB.\n.LP\nThe \\fB\\-sp\\fP option can be used to pause \\fIzip\\fP between splits to allow changing\nremovable media, for example, but read the descriptions and warnings for both \\fB\\-s\\fP\nand \\fB\\-sp\\fP below.\n.LP\nThough \\fIzip\\fP does not update split archives, \\fIzip\\fP provides the new option \\fB\\-O\\fP\n(\\fB\\-\\-output\\-file\\fP) to allow split archives to be updated and saved in a new archive.  For example,\n.IP\n\\fCzip inarchive.zip foo.c bar.c \\-\\-out outarchive.zip\\fP\n.LP\nreads archive \\fBinarchive.zip\\fP, even if split, adds the files \\fBfoo.c\\fP and\n\\fBbar.c\\fP, and writes the resulting archive to \\fBoutarchive.zip\\fP.  If\n\\fBinarchive.zip\\fP is split then \\fBoutarchive.zip\\fP defaults\nto the same split size.  Be aware that \\fBoutarchive.zip\\fP and any split files\nthat are created with it are always overwritten without warning.  This may be changed\nin the future.\n\n\n\n\n.SH \"PATTERN MATCHING\"\nThis section applies only to Unix.\nWatch this space for details on MSDOS and VMS operation.\nHowever, the special wildcard characters \\fB*\\fR and \\fB[]\\fR below apply\nto at least MSDOS also.\n.LP\nThe Unix shells (\\fIsh\\fP, \\fIcsh\\fP, \\fIbash\\fP, and others) normally\ndo filename substitution (also called \"globbing\") on command arguments.\nGenerally the special characters are:\n.TP\n.B ?\nmatch any single character\n.TP\n.B *\nmatch any number of characters (including none)\n.TP\n.B []\nmatch any character in the range indicated within the brackets\n(example: [a\\-f], [0\\-9]).  This form of wildcard matching\nallows a user to specify a list of characters between square brackets and\nif any of the characters match the expression matches.  For example:\n.RS\n.IP\n\\fCzip archive \"*.[hc]\"\\fP\n.RE\n.IP\nwould archive all files in the current directory that end in\n\\fB.h\\fP or \\fB.c\\fP.\n\nRanges of characters are supported:\n.RS\n.IP\n\\fCzip archive \"[a\\-f]*\"\\fP\n.RE\n.IP\nwould add to the archive all files starting with \"a\" through \"f\".\n\nNegation is also supported, where any character in that position not in\nthe list matches.  Negation is supported by adding \\fB!\\fP or \\fB^\\fP\nto the beginning of the list:\n.RS\n.IP\n\\fCzip archive \"*.[!o]\"\\fP\n.RE\n.IP\nmatches files that don't end in \".o\".\n\nOn WIN32, [] matching needs to be turned on with the -RE option to avoid\nthe confusion that names with [ or ] have caused.\n\n.LP\nWhen these characters are encountered\n(without being escaped with a backslash or quotes),\nthe shell will look for files relative to the current path\nthat match the pattern,\nand replace the argument with a list of the names that matched.\n.LP\nThe\n.I zip\nprogram can do the same matching on names that are in the\n.I zip\narchive being modified or,\nin the case of the\n.B \\-x\n(exclude) or\n.B \\-i\n(include) options, on the list of files to be operated on, by using\nbackslashes or quotes to tell the shell not to do the name expansion.\nIn general, when\n.I zip\nencounters a name in the list of files to do, it first looks for the name in\nthe file system.  If it finds it, it then adds it to the list of files to do.\nIf it does not find it, it looks for the name in the\n.I zip\narchive being modified (if it exists), using the pattern matching characters\ndescribed above, if present.  For each match, it will add that name to the\nlist of files to be processed, unless this name matches one given\nwith the\n.B \\-x\noption, or does not match any name given with the\n.B \\-i\noption.\n.LP\nThe pattern matching includes the path,\nand so patterns like \\\\*.o match names that end in \".o\",\nno matter what the path prefix is.\nNote that the backslash must precede every special character (i.e. ?*[]),\nor the entire argument must be enclosed in double quotes (\"\").\n.LP\nIn general, use backslashes or double quotes for paths\nthat have wildcards to make\n.I zip\ndo the pattern matching for file paths, and always for\npaths and strings that have spaces or wildcards for\n\\fB\\-\\i\\fP, \\fB\\-x\\fP, \\fB\\-R\\fP, \\fB\\-d\\fP, and \\fB\\-U\\fP\nand anywhere \\fIzip\\fP needs to process the wildcards.\n.SH \"ENVIRONMENT\"\n.LP\nThe following environment variables are read and used by\n.I zip\nas described.\n.TP\n.B ZIPOPT\\ \\ \ncontains default options that will be used when running\n\\fIzip\\fR.  The contents of this environment variable will get\nadded to the command line just after the \\fBzip\\fR command.\n.TP\n.B ZIP\\ \\ \\ \\ \\ \n[Not on RISC OS and VMS] see ZIPOPT\n.TP\n.B Zip$Options\n[RISC OS] see ZIPOPT\n.TP\n.B Zip$Exts\n[RISC OS] contains extensions separated by a : that will cause\nnative filenames with one of the specified extensions to\nbe added to the zip file with basename and extension swapped.\n.TP\n.B ZIP_OPTS\n[VMS] see ZIPOPT\n.SH \"SEE ALSO\"\ncompress(1),\nshar(1L),\ntar(1),\nunzip(1L),\ngzip(1L)\n.SH DIAGNOSTICS\nThe exit status (or error level) approximates the exit codes defined by PKWARE\nand takes on the following values, except under VMS:\n.RS\n.IP 0\nnormal; no errors or warnings detected.\n.IP 2\nunexpected end of zip file.\n.IP 3\na generic error in the zipfile format was detected.  Processing may have\ncompleted successfully anyway; some broken zipfiles created by other\narchivers have simple work-arounds.\n.IP 4\n\\fIzip\\fP was unable to allocate memory for one or more buffers during\nprogram initialization.\n.IP 5\na severe error in the zipfile format was detected.  Processing probably\nfailed immediately.\n.IP 6\nentry too large to be processed (such as input files larger than 2 GB when\nnot using Zip64 or trying to read an existing archive that is too large) or\nentry too large to be split with \\fIzipsplit\\fP\n.IP 7\ninvalid comment format\n.IP 8\n\\fIzip\\fP -T failed or out of memory\n.IP 9\nthe user aborted \\fIzip\\fP prematurely with control-C (or similar)\n.IP 10\n\\fIzip\\fP encountered an error while using a temp file\n.IP 11\nread or seek error\n.IP 12\n\\fIzip\\fP has nothing to do\n.IP 13\nmissing or empty zip file\n.IP 14\nerror writing to a file\n.IP 15\n\\fIzip\\fP was unable to create a file to write to\n.IP 16\nbad command line parameters\n.IP 18\n\\fIzip\\fP could not open a specified file to read\n.IP 19\n\\fIzip\\fP was compiled with options not supported on this system\n.RE\n.PP\nVMS interprets standard Unix (or PC) return values as other, scarier-looking\nthings, so \\fIzip\\fP instead maps them into VMS-style status codes.  In\ngeneral, \\fIzip\\fP sets VMS Facility = 1955 (0x07A3), Code = 2* Unix_status,\nand an appropriate Severity (as specified in ziperr.h).  More details are\nincluded in the VMS-specific documentation.  See [.vms]NOTES.TXT and\n[.vms]vms_msg_gen.c.\n.PD\n.SH BUGS\n.I zip\n3.0 is not compatible with PKUNZIP 1.10. Use\n.I zip\n1.1 to produce\n.I zip\nfiles which can be extracted by PKUNZIP 1.10.\n.PP\n.I zip\nfiles produced by\n.I zip\n3.0 must not be\n.I updated\nby\n.I zip\n1.1 or PKZIP 1.10, if they contain\nencrypted members or if they have been produced in a pipe or on a non-seekable\ndevice. The old versions of\n.I zip\nor PKZIP would create an archive with an incorrect format.\nThe old versions can list the contents of the zip file\nbut cannot extract it anyway (because of the new compression algorithm).\nIf you do not use encryption and use regular disk files, you do\nnot have to care about this problem.\n.LP\nUnder VMS,\nnot all of the odd file formats are treated properly.\nOnly stream-LF format\n.I zip\nfiles are expected to work with\n.IR zip .\nOthers can be converted using Rahul Dhesi's BILF program.\nThis version of\n.I zip\nhandles some of the conversion internally.\nWhen using Kermit to transfer zip files from VMS to MSDOS, type \"set\nfile type block\" on VMS.  When transfering from MSDOS to VMS, type\n\"set file type fixed\" on VMS.  In both cases, type \"set file type\nbinary\" on MSDOS.\n.LP\nUnder some older VMS versions, \\fIzip\\fP may hang for file\nspecifications that use DECnet syntax\n.I foo::*.*.\n.LP\nOn OS/2, zip cannot match some names, such as those including an\nexclamation mark or a hash sign.  This is a bug in OS/2 itself: the\n32-bit DosFindFirst/Next don't find such names.  Other programs such\nas GNU tar are also affected by this bug.\n.LP\nUnder OS/2, the amount of Extended Attributes displayed by DIR is (for\ncompatibility) the amount returned by the 16-bit version of\nDosQueryPathInfo(). Otherwise OS/2 1.3 and 2.0 would report different\nEA sizes when DIRing a file.\nHowever, the structure layout returned by the 32-bit DosQueryPathInfo()\nis a bit different, it uses extra padding bytes and link pointers (it's\na linked list) to have all fields on 4-byte boundaries for portability\nto future RISC OS/2 versions. Therefore the value reported by\n.I zip\n(which uses this 32-bit-mode size) differs from that reported by DIR.\n.I zip\nstores the 32-bit format for portability, even the 16-bit\nMS-C-compiled version running on OS/2 1.3, so even this one shows the\n32-bit-mode size.\n.SH AUTHORS\nCopyright (C) 1997-2008 Info-ZIP.\n.LP\nCurrently distributed under the Info-ZIP license.\n.LP\nCopyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,\nOnno van der Linden, Kai Uwe Rommel, Igor Mandrichenko, John Bush and\nPaul Kienitz.\n.LP\nOriginal copyright:\n.LP\nPermission is granted to any individual or institution to use, copy, or\nredistribute this software so long as all of the original files are included,\nthat it is not sold for profit, and that this copyright notice\nis retained.\n.LP\nLIKE ANYTHING ELSE THAT'S FREE, ZIP AND ITS ASSOCIATED UTILITIES ARE\nPROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR\nIMPLIED. IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES\nRESULTING FROM THE USE OF THIS SOFTWARE.\n.LP\nPlease send bug reports and comments using the web page at:\n.IR www.info-zip.org .\nFor bug reports, please include the version of\n.IR zip\n(see \\fIzip\\ \\-h\\fR),\nthe make options used to compile it (see \\fIzip\\ \\-v\\fR),\nthe machine and operating system in use,\nand as much additional information as possible.\n.SH ACKNOWLEDGEMENTS\nThanks to R. P. Byrne for his\n.I Shrink.Pas\nprogram, which inspired this project,\nand from which the shrink algorithm was stolen;\nto Phil Katz for placing in the public domain the\n.I zip\nfile format, compression format, and .ZIP filename extension, and for\naccepting minor changes to the file format; to Steve Burg for\nclarifications on the deflate format; to Haruhiko Okumura and Leonid\nBroukhis for providing some useful ideas for the compression\nalgorithm; to Keith Petersen, Rich Wales, Hunter Goatley and Mark\nAdler for providing a mailing list and\n.I ftp\nsite for the Info-ZIP group to use; and most importantly, to the\nInfo-ZIP group itself (listed in the file\n.IR infozip.who )\nwithout whose tireless testing and bug-fixing efforts a portable\n.I zip\nwould not have been possible.\nFinally we should thank (blame) the first Info-ZIP moderator,\nDavid Kirschbaum,\nfor getting us into this mess in the first place.\nThe manual page was rewritten for Unix by R. P. C. Rodgers and\nupdated by E. Gordon for \\fIzip\\fR 3.0.\n.\\\" end of file\n"
  },
  {
    "path": "deps/infozip/zip30/man/zipcloak.1",
    "content": ".TH zipcloak 1 \"v3.0 of 8 May 2008\"\n.SH NAME\nzipcloak \\- encrypt entries in a zipfile\n\n.SH SYNOPSIS\n.I zipcloak\n.RB [ \\-d ]\n.RB [ \\-b\\ path ]\n.RB [ \\-h ]\n.RB [ \\-v ]\n.RB [ \\-L ]\nzipfile\n\n.SH ARGUMENTS\n.in +13\n.ti -13\nzipfile  Zipfile to encrypt entries in\n\n.SH OPTIONS\n.TP\n.PD 0\n.B \\-b\\ \\fPpath\n.TP\n.PD\n.B \\-\\-temp\\-path \\fPpath\nUse the directory given by path for the temporary zip file.\n\n.TP\n.PD 0\n.B \\-d\n.TP\n.PD\n.B \\-\\-decrypt\nDecrypt encrypted entries (copy if given wrong password).\n\n.TP\n.PD 0\n.B \\-h\n.TP\n.PD\n.B \\-\\-help\\ \nShow a short help.\n\n.TP\n.PD 0\n.B \\-L\n.TP\n.PD\n.B \\-\\-license\nShow software license.\n\n.TP\n.PD 0\n.B \\-O\\ \\fPpath\n.TP\n.PD\n.B \\-\\-output\\-file\\ \\fPzipfile\nWrite output to new archive zipfile, leaving original archive as is.\n\n.TP\n.PD 0\n.B \\-q\n.TP\n.PD\n.B \\-\\-quiet\nQuiet operation.  Suppresses some informational messages.\n\n.TP\n.PD 0\n.B \\-v\n.TP\n.PD\n.B \\-\\-version\nShow version information.\n\n.SH DESCRIPTION\n.I zipcloak\nencrypts all unencrypted entries in the zipfile.  This is the default action.\n\n.TP\nThe \\-d option is used to decrypt encrypted entries in the zipfile.\n\n.TP\n\\fIzipcloak \\fBuses original zip encryption which is considered weak.\n\n.TP\nNote:\nThe encryption code of this program is not copyrighted and is put in\nthe public domain.  It was originally written in Europe and can be freely\ndistributed from any country including the U.S.A.  (Previously if this\nprogram was imported into the U.S.A, it could not be re-exported from\nthe U.S.A to another country.)  See the file README.CR included in the\nsource distribution for more on this.  Otherwise, the Info-ZIP license\napplies.\n\n.SH EXAMPLES\nTo be added.\n\n.SH BUGS\nLarge files (> 2 GB) and large archives not yet supported.\n\nSplit archives not yet supported.  A work around is to convert the\nsplit archive to a single-file archive using \\fIzip\\fP and then\nuse \\fIzipcloak\\fP on the single-file archive.  If needed, the\nresulting archive can then be split again using \\fIzip\\fP.\n\n\n.SH SEE ALSO\nzip(1), unzip(1)\n.SH AUTHOR\nInfo-ZIP\n"
  },
  {
    "path": "deps/infozip/zip30/man/zipnote.1",
    "content": ".TH zipnote 1 \"v3.0 of 8 May 2008\"\n.SH NAME\nzipnote \\- write the comments in zipfile to stdout, edit comments and rename files in zipfile\n\n.SH SYNOPSIS\n.I zipnote\n.RB [ \\-w ]\n.RB [ \\-b\\ path ]\n.RB [ \\-h ]\n.RB [ \\-v ]\n.RB [ \\-L ]\nzipfile\n\n.SH ARGUMENTS\n.in +13\n.ti -13\nzipfile  Zipfile to read comments from or edit.\n\n.SH OPTIONS\n.TP\n.BI \\-w\nWrite comments to a zipfile from stdin (see below).\n.TP\n.BI \\-b\\ \\fRpath\nUse path for the temporary zip file.\n.TP\n.BI \\-h\nShow a short help.\n.TP\n.BI \\-v\nShow version information.\n.TP\n.BI \\-L\nShow software license.\n\n.SH DESCRIPTION\n.I zipnote\nwrites the comments in a zipfile to stdout.  This is the default mode.  A second mode\nallows updating the comments in a zipfile as well as allows changing the names\nof the files in the zipfile.  These modes are described below.\n\n.SH EXAMPLES\nTo write all comments in a zipfile to stdout use for example\n.LP\n.nf\n     zipnote foo.zip > foo.tmp\n.fi\n.LP\nThis writes all comments in the zipfile\n.I foo.zip\nto the file\n.I foo.tmp\nin a specific format.\n\n.LP\nIf desired, this file can then be edited to change the comments and then used\nto update the zipfile.\n.LP\n.nf\n     zipnote -w foo.zip < foo.tmp\n.fi\n.LP\nThe names of the files in the zipfile can also be changed in this way.  This is done by\nfollowing lines like\n.nf\n     \"@ name\"\n.fi\nin the created temporary file (called\n.I foo.tmp\nhere) with lines like\n.nf\n     \"@=newname\"\n.fi\nand then using the -w option as above.\n\n.SH BUGS\nThe temporary file format is rather specific and zipnote is rather picky about it.\nIt should be easier to change file names in a script.\n\nDoes not yet support large (> 2 GB) or split archives.\n\n.SH SEE ALSO\nzip(1), unzip(1)\n.SH AUTHOR\nInfo-ZIP\n"
  },
  {
    "path": "deps/infozip/zip30/man/zipsplit.1",
    "content": ".TH zipnote 1 \"v3.0 of 8 May 2008\"\n.SH NAME\nzipsplit \\- split a zipfile into smaller zipfiles\n\n.SH SYNOPSIS\n.I zipsplit\n.RB [ \\-t ]\n.RB [ \\-i ]\n.RB [ \\-p ]\n.RB [ \\-s ]\n.RB [ \\-n\\ size ]\n.RB [ \\-r\\ room ]\n.RB [ \\-b\\ path ]\n.RB [ \\-h ]\n.RB [ \\-v ]\n.RB [ \\-L ]\nzipfile\n\n.SH ARGUMENTS\n.in +13\n.ti -13\nzipfile  Zipfile to split.\n\n.SH OPTIONS\n.TP\n.BI \\-t\nReport how many files it will take, but don't make them.\n.TP\n.BI \\-i\nMake index (zipsplit.idx) and count its size against first zip file.\n.TP\n.BI \\-n\\ \\fRsize\nMake zip files no larger than \"size\" (default = 36000).\n.TP\n.BI \\-r\\ \\fRroom\nLeave room for \"room\" bytes on the first disk (default = 0).\n.TP\n.BI \\-b\\ \\fRpath\nUse path for the output zip files.\n.TP\n.BI \\-p\nPause between output zip files.\n.TP\n.BI \\-s\nDo a sequential split even if it takes more zip files.\n.TP\n.BI \\-h\nShow a short help.\n.TP\n.BI \\-v\nShow version information.\n.TP\n.BI \\-L\nShow software license.\n\n.SH DESCRIPTION\n.I zipsplit\nreads a zipfile and splits it into smaller zipfiles.\n\n.SH EXAMPLES\nTo be filled in.\n\n.SH BUGS\nDoes not yet support large (> 2 GB) or split archives.\n\n.SH SEE ALSO\nzip(1), unzip(1)\n.SH AUTHOR\nInfo-ZIP\n"
  },
  {
    "path": "deps/infozip/zip30/match.S",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2004-May-22 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/*\n * match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.\n * The 68020 version has been written by Francesco Potorti` <pot@cnuce.cnr.it>\n * with adaptations by Carsten Steger <stegerc@informatik.tu-muenchen.de>,\n * Andreas Schwab <schwab@lamothe.informatik.uni-dortmund.de> and\n * Kristoffer Eriksson <ske@pkmab.se>\n */\n\n/* This file is NOT used in conjunction with zlib. */\n#ifndef USE_ZLIB\n\n/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix\n * external symbols with an underline character '_'.\n */\n#if defined(NO_UNDERLINE) || defined(__ELF__)\n#  define _prev             prev\n#  define _window           window\n#  define _match_start      match_start\n#  define _prev_length      prev_length\n#  define _good_match       good_match\n#  define _nice_match       nice_match\n#  define _strstart         strstart\n#  define _max_chain_length max_chain_length\n\n#  define _match_init       match_init\n#  define _longest_match    longest_match\n#endif\n\n#ifdef DYN_ALLOC\n  error: DYN_ALLOC not yet supported in match.s\n#endif\n\n/* Use 16-bytes alignment if your assembler supports it. Warning: gas\n * uses a log(x) parameter (.align 4 means 16-bytes alignment). On SVR4\n * the parameter is a number of bytes.\n */\n#ifndef ALIGNMENT\n#  define ALIGNMENT 4\n#endif\n\n\n#ifndef WSIZE\n# define WSIZE          32768\n#endif\n#define MIN_MATCH       3\n#define MAX_MATCH       258\n#define MIN_LOOKAHEAD   (MAX_MATCH + MIN_MATCH + 1)\n#define MAX_DIST        (WSIZE - MIN_LOOKAHEAD)\n\n#if defined(i386) || defined(_I386) || defined(_i386) || defined(__i386)\n\n/* This version is for 386 Unix or OS/2 in 32 bit mode.\n * Warning: it uses the AT&T syntax: mov source,dest\n * This file is only optional. If you want to force the C version,\n * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.\n * If you have reduced WSIZE in (g)zip.h, then make sure this is\n * assembled with an equivalent -DWSIZE=<whatever>.\n * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).\n */\n\n        .file   \"match.S\"\n\n        .globl  _match_init\n        .globl  _longest_match\n\n        .text\n\n_match_init:\n        ret\n\n/*-----------------------------------------------------------------------\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n */\n\n        .align  ALIGNMENT\n\n_longest_match: /* int longest_match(cur_match) */\n\n#define cur_match   20(%esp)\n     /* return address */               /* esp+16 */\n        push    %ebp                    /* esp+12 */\n        push    %edi                    /* esp+8  */\n        push    %esi                    /* esp+4  */\n        push    %ebx                    /* esp    */\n\n/*\n *      match        equ esi\n *      scan         equ edi\n *      chain_length equ ebp\n *      best_len     equ ebx\n *      limit        equ edx\n */\n        mov     cur_match,%esi\n        mov     _strstart,%edx\n        mov     _max_chain_length,%ebp /* chain_length = max_chain_length */\n        mov     %edx,%edi\n        sub     $(MAX_DIST),%edx       /* limit = strstart-MAX_DIST */\n        cld                            /* string ops increment si and di */\n        jae     limit_ok\n        sub     %edx,%edx              /* limit = NIL */\nlimit_ok:\n        add     $2+_window,%edi        /* edi = offset(window+strstart+2) */\n        mov     _prev_length,%ebx      /* best_len = prev_length */\n        movw    -2(%edi),%cx           /* cx = scan[0..1] */\n        movw    -3(%ebx,%edi),%ax      /* ax = scan[best_len-1..best_len] */\n        cmp     _good_match,%ebx       /* do we have a good match already? */\n        jb      do_scan\n        shr     $2,%ebp                /* chain_length >>= 2 */\n        jmp     do_scan\n\n        .align  ALIGNMENT\nlong_loop:\n/* at this point, edi == scan+2, esi == cur_match */\n        movw    -3(%ebx,%edi),%ax       /* ax = scan[best_len-1..best_len] */\n        movw     -2(%edi),%cx           /* cx = scan[0..1] */\nshort_loop:\n/*\n * at this point, di == scan+2, si == cur_match,\n * ax = scan[best_len-1..best_len] and cx = scan[0..1]\n */\n        and     $(WSIZE-1), %esi\n        dec     %ebp                    /* --chain_length */\n        movw    _prev(,%esi,2),%si      /* cur_match = prev[cur_match] */\n                                        /* top word of esi is still 0 */\n        jz      the_end\n        cmp     %edx,%esi               /* cur_match <= limit ? */\n        jbe     the_end\ndo_scan:\n        cmpw    _window-1(%ebx,%esi),%ax/* check match at best_len-1 */\n        jne     short_loop\n        cmpw    _window(%esi),%cx       /* check min_match_length match */\n        jne     short_loop\n\n        add     $2+_window,%esi         /* si = match */\n        mov     $((MAX_MATCH>>1)-1),%ecx/* scan for at most MAX_MATCH bytes */\n        mov     %edi,%eax               /* ax = scan+2 */\n        repe;   cmpsw                   /* loop until mismatch */\n        je      maxmatch                /* match of length MAX_MATCH? */\nmismatch:\n        movb    -2(%edi),%cl        /* mismatch on first or second byte? */\n        xchg    %edi,%eax           /* edi = scan+2, eax = end of scan */\n        subb    -2(%esi),%cl        /* cl = 0 if first bytes equal */\n        sub     %edi,%eax           /* eax = len */\n        sub     $2+_window,%esi     /* esi = cur_match + len */\n        sub     %eax,%esi           /* esi = cur_match */\n        subb    $1,%cl              /* set carry if cl == 0 (cannot use DEC) */\n        adc     $0,%eax             /* eax = carry ? len+1 : len */\n        cmp     %ebx,%eax           /* len > best_len ? */\n        jle     long_loop\n        mov     %esi,_match_start       /* match_start = cur_match */\n        mov     %eax,%ebx               /* ebx = best_len = len */\n#ifdef FULL_SEARCH\n        cmp     $(MAX_MATCH),%eax       /* len >= MAX_MATCH ? */\n#else\n        cmp     _nice_match,%eax        /* len >= nice_match ? */\n#endif\n        jl      long_loop\nthe_end:\n        mov     %ebx,%eax               /* result = eax = best_len */\n        pop     %ebx\n        pop     %esi\n        pop     %edi\n        pop     %ebp\n        ret\n        .align  ALIGNMENT\nmaxmatch:\n        cmpsb\n        jmp     mismatch\n\n#else /* !(i386 || _I386 || _i386 || __i386) */\n\n/* ======================== 680x0 version ================================= */\n\n#if defined(m68k)||defined(mc68k)||defined(__mc68000__)||defined(__MC68000__)\n#  ifndef mc68000\n#    define mc68000\n#  endif\n#endif\n\n#if defined(__mc68020__) || defined(__MC68020__) || defined(sysV68)\n#  ifndef mc68020\n#    define mc68020\n#  endif\n#endif\n\n#if defined(mc68020) || defined(mc68000)\n\n#if (defined(mc68020) || defined(NeXT)) && !defined(UNALIGNED_OK)\n#  define UNALIGNED_OK\n#endif\n\n#ifdef sysV68  /* Try Motorola Delta style */\n\n#  define GLOBAL(symbol)        global  symbol\n#  define TEXT                  text\n#  define FILE(filename)        file    filename\n#  define invert_maybe(src,dst) dst,src\n#  define imm(data)             &data\n#  define reg(register)         %register\n\n#  define addl                  add.l\n#  define addql                 addq.l\n#  define blos                  blo.b\n#  define bhis                  bhi.b\n#  define bras                  bra.b\n#  define clrl                  clr.l\n#  define cmpmb                 cmpm.b\n#  define cmpw                  cmp.w\n#  define cmpl                  cmp.l\n#  define lslw                  lsl.w\n#  define lsrl                  lsr.l\n#  define movel                 move.l\n#  define movew                 move.w\n#  define moveb                 move.b\n#  define moveml                movem.l\n#  define subl                  sub.l\n#  define subw                  sub.w\n#  define subql                 subq.l\n\n#  define IndBase(bd,An)        (bd,An)\n#  define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l)\n#  define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w)\n#  define predec(An)            -(An)\n#  define postinc(An)           (An)+\n\n#else /* default style (Sun 3, NeXT, Amiga, Atari) */\n\n#  define GLOBAL(symbol)        .globl  symbol\n#  define TEXT                  .text\n#  define FILE(filename)        .even\n#  define invert_maybe(src,dst) src,dst\n#  if defined(sun) || defined(mc68k)\n#    define imm(data)           #data\n#  else\n#    define imm(data)           \\#data\n#  endif\n#  define reg(register)         register\n\n#  define blos                  bcss\n#  if defined(sun) || defined(mc68k)\n#    define movel               movl\n#    define movew               movw\n#    define moveb               movb\n#  endif\n#  define IndBase(bd,An)        An@(bd)\n#  define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l)\n#  define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w)\n#  define predec(An)            An@-\n#  define postinc(An)           An@+\n\n#endif  /* styles */\n\n#define Best_Len        reg(d0)         /* unsigned */\n#define Cur_Match       reg(d1)         /* Ipos */\n#define Loop_Counter    reg(d2)         /* int */\n#define Scan_Start      reg(d3)         /* unsigned short */\n#define Scan_End        reg(d4)         /* unsigned short */\n#define Limit           reg(d5)         /* IPos */\n#define Chain_Length    reg(d6)         /* unsigned */\n#define Scan_Test       reg(d7)\n#define Scan            reg(a0)         /* *uch */\n#define Match           reg(a1)         /* *uch */\n#define Prev_Address    reg(a2)         /* *Pos */\n#define Scan_Ini        reg(a3)         /* *uch */\n#define Match_Ini       reg(a4)         /* *uch */\n#define Stack_Pointer   reg(sp)\n\n        GLOBAL  (_match_init)\n        GLOBAL  (_longest_match)\n\n        TEXT\n\n        FILE    (\"match.S\")\n\n_match_init:\n        rts\n\n/*-----------------------------------------------------------------------\n * Set match_start to the longest match starting at the given string and\n * return its length. Matches shorter or equal to prev_length are discarded,\n * in which case the result is equal to prev_length and match_start is\n * garbage.\n * IN assertions: cur_match is the head of the hash chain for the current\n *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n */\n\n/* int longest_match (cur_match) */\n\n#ifdef UNALIGNED_OK\n#  define pushreg       15928           /* d2-d6/a2-a4 */\n#  define popreg        7292\n#else\n#  define pushreg       16184           /* d2-d7/a2-a4 */\n#  define popreg        7420\n#endif\n\n_longest_match:\n        movel   IndBase(4,Stack_Pointer),Cur_Match\n        moveml  imm(pushreg),predec(Stack_Pointer)\n        movel   _max_chain_length,Chain_Length\n        movel   _prev_length,Best_Len\n        movel   imm(_prev),Prev_Address\n        movel   imm(_window+MIN_MATCH),Match_Ini\n        movel   _strstart,Limit\n        movel   Match_Ini,Scan_Ini\n        addl    Limit,Scan_Ini\n        subw    imm(MAX_DIST),Limit\n        bhis    L__limit_ok\n        clrl    Limit\nL__limit_ok:\n        cmpl    invert_maybe(_good_match,Best_Len)\n        blos    L__length_ok\n        lsrl    imm(2),Chain_Length\nL__length_ok:\n        subql   imm(1),Chain_Length\n#ifdef UNALIGNED_OK\n        movew   IndBase(-MIN_MATCH,Scan_Ini),Scan_Start\n        movew   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End\n#else\n        moveb   IndBase(-MIN_MATCH,Scan_Ini),Scan_Start\n        lslw    imm(8),Scan_Start\n        moveb   IndBase(-MIN_MATCH+1,Scan_Ini),Scan_Start\n        moveb   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End\n        lslw    imm(8),Scan_End\n        moveb   IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End\n#endif\n        bras    L__do_scan\n\nL__long_loop:\n#ifdef UNALIGNED_OK\n        movew   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End\n#else\n        moveb   IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End\n        lslw    imm(8),Scan_End\n        moveb   IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End\n#endif\n\nL__short_loop:\n        lslw    imm(1),Cur_Match\n        movew   IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match\n        cmpw    invert_maybe(Limit,Cur_Match)\n        dbls    Chain_Length,L__do_scan\n        bras    L__return\n\nL__do_scan:\n        movel   Match_Ini,Match\n        addl    Cur_Match,Match\n#ifdef UNALIGNED_OK\n        cmpw    invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End)\n        bne     L__short_loop\n        cmpw    invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start)\n        bne     L__short_loop\n#else\n        moveb   IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_Test\n        lslw    imm(8),Scan_Test\n        moveb   IndBaseNdxw(-MIN_MATCH,Match,Best_Len),Scan_Test\n        cmpw    invert_maybe(Scan_Test,Scan_End)\n        bne     L__short_loop\n        moveb   IndBase(-MIN_MATCH,Match),Scan_Test\n        lslw    imm(8),Scan_Test\n        moveb   IndBase(-MIN_MATCH+1,Match),Scan_Test\n        cmpw    invert_maybe(Scan_Test,Scan_Start)\n        bne     L__short_loop\n#endif\n\n        movew   imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter\n        movel   Scan_Ini,Scan\nL__scan_loop:\n        cmpmb   postinc(Match),postinc(Scan)\n        dbne    Loop_Counter,L__scan_loop\n\n        subl    Scan_Ini,Scan\n        addql   imm(MIN_MATCH-1),Scan\n        cmpl    invert_maybe(Best_Len,Scan)\n        bls     L__short_loop\n        movel   Scan,Best_Len\n        movel   Cur_Match,_match_start\n#ifdef FULL_SEARCH\n        cmpl    invert_maybe(imm(MAX_MATCH),Best_Len)\n#else\n        cmpl    invert_maybe(_nice_match,Best_Len)\n#endif\n        blos    L__long_loop\nL__return:\n        moveml  postinc(Stack_Pointer),imm(popreg)\n        rts\n\n#else\n error: this asm version is for 386 or 680x0 only\n#endif /* mc68000 || mc68020 */\n#endif /* i386 || _I386 || _i386 || __i386  */\n\n#endif /* !USE_ZLIB */\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/README.DOS",
    "content": "README.DOS\n\nSome notes about the supplied MSDOS executables and their compilers:\n\nA) The 32-bit DOS executables \"zip.exe\" and the auxilary utilities\n   \"zipnote.exe\", \"zipsplit.exe\", \"zipcloak.exe\" (crypt-enabled distribution\n   only) were compiled with DJGPP v 2.03, using gcc 2.95.3 as compiler.\n   They require a DPMI server to run, e.g.: a DOS command prompt window\n   under WINDOWS 3.x or Windows 9x.  To use this program under plain DOS,\n   you should install the free (GPL'ed) DPMI server CWSDPMI.EXE.  Look\n   for \"csdpmi5b.zip\" under \"simtelnet/gnu/djgpp/v2misc/\" on the SimTelNet\n   home site \"ftp.cdrom.com\" or any mirror site of the SimtelNet archive.\n\n   We have decided to provide 32-bit rather than 16-bit executables of\n   the auxilary tools for the following reasons:\n   - Nowadays, it has become quite unlikely to find PC computers \"in action\"\n     that do not at least have an i386 CPU.\n   - the 32-bit versions do not impose additional archive handling limits\n     beyond those defined by the Zip archive format\n   - the 32-bit DJGPP executables can handle long filenames on systems running\n     Windows 95/98/Me and Windows 2K/XP.\n\nB) There are two 16-bit MSDOS executables provided in zcr2?x.zip:\n     zip16.exe     regular Zip program, requires ca. 455 KBytes of contiguous\n                   free DOS memory or more.\n     zip16-sm.exe  a variant that was compiled with the SMALL_MEM option\n                   for minimal memory consumption; requires at minimum\n                   322 KBytes of contiguous free DOS memory.\n\n   The SMALL_MEM variant requires much less space for the compression\n   buffers, but at the cost of some compression efficiency.\n   Therefore, we recommend to use the \"SMALL_MEM\" 16-bit \"zip16-sm.exe\" only\n   in case of \"out of memory\" problems (DOS memory is low and/or very large\n   number of archive entries), when the 32-bit program cannot be used for\n   some reason (286 or older; no DPMI server; ...).\n\nC) Hard limits of the Zip archive format:\n   Number of entries in Zip archive:            64 k (2^16 - 1 entries)\n   Compressed size of archive entry:            4 GByte (2^32 - 1 Bytes)\n   Uncompressed size of entry:                  4 GByte (2^32 - 1 Bytes)\n   Size of single-volume Zip archive:           4 GByte (2^32 - 1 Bytes)\n   Per-volume size of multi-volume archives:    4 GByte (2^32 - 1 Bytes)\n   Number of parts for multi-volume archives:   64 k (1^16 - 1 parts)\n   Total size of multi-volume archive:          256 TByte (4G * 64k)\n\n   The number of archive entries and of multivolume parts are limited by\n   the structure of the \"end-of-central-directory\" record, where the these\n   numbers are stored in 2-Byte fields.\n   Some Zip and/or UnZip implementations (for example Info-ZIP's) allow\n   handling of archives with more than 64k entries.  (The information\n   from \"number of entries\" field in the \"end-of-central-directory\" record\n   is not really neccessary to retrieve the contents of a Zip archive;\n   it should rather be used for consistency checks.)\n\n   Length of an archive entry name:             64 kByte (2^16 - 1)\n   Length of archive member comment:            64 kByte (2^16 - 1)\n   Total length of \"extra field\":               64 kByte (2^16 - 1)\n   Length of a single e.f. block:               64 kByte (2^16 - 1)\n   Length of archive comment:                   64 KByte (2^16 - 1)\n\n   Additional limitation claimed by PKWARE:\n     Size of local-header structure (fixed fields of 30 Bytes + filename\n      local extra field):                     < 64 kByte\n     Size of central-directory structure (46 Bytes + filename +\n      central extra field + member comment):  < 64 kByte\n\nD) Implementation limits of the Zip executables:\n\n 1. Size limits caused by file I/O and compression handling:\n   Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)\n   Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)\n   Uncompressed size of entry:          2 GByte (2^31 - 1 Bytes),\n                                        (could/should be 4 GBytes...)\n   Multi-volume archive creation is not supported.\n\n 2. Limits caused by handling of archive contents lists\n\n 2.1. Number of archive entries (freshen, update, delete)\n     a) 16-bit executable:              64k (2^16 -1) or 32k (2^15 - 1),\n                                        (unsigned vs. signed type of size_t)\n     a1) 16-bit executable:             <16k ((2^16)/4)\n         (The smaller limit a1) results from the array size limit of\n         the \"qsort()\" function.)\n         32-bit executables             <1G ((2^32)/4)\n         (usual system limit of the \"qsort()\" function on 32-bit systems)\n\n     b) stack space needed by qsort to sort list of archive entries\n\n     NOTE: In the current executables, overflows of limits a) and b) are NOT\n           checked!\n\n     c) amount of free memory to hold \"central directory information\" of\n        all archive entries; one entry needs:\n        96 bytes (32-bit) resp. 80 bytes (16-bit)\n        + 3 * length of entry name\n        + length of zip entry comment (when present)\n        + length of extra field(s) (when present, e.g.: UT needs 9 bytes)\n        + some bytes for book-keeping of memory allocation\n\n   Conclusion:\n     For systems with limited memory space (MSDOS, small AMIGAs, other\n     environments without virtual memory), the number of archive entries\n     is most often limited by condition c).\n     For example, with approx. 100 kBytes of free memory after loading and\n     initializing the program, a 16-bit DOS Zip cannot process more than 600\n     to 1000 (+) archive entries.  (For the 16-bit Windows DLL or the 16-bit\n     OS/2 port, limit c) is less important because Windows or OS/2 executables\n     are not restricted to the 1024k area of real mode memory.  These 16-bit\n     ports are limited by conditions a1) and b), say: at maximum approx.\n     16000 entries!)\n\n\n 2.2. Number of \"new\" entries (add operation)\n     In addition to the restrictions above (2.1.), the following limits\n     caused by the handling of the \"new files\" list apply:\n\n     a) 16-bit executable:              <16k ((2^64)/4)\n\n     b) stack size required for \"qsort\" operation on \"new entries\" list.\n\n     NOTE: In the current executables, the overflow checks for these limits\n           are missing!\n\n     c) amount of free memory to hold the directory info list for new entries;\n        one entry needs:\n        24 bytes (32-bit) resp. 22 bytes (16-bit)\n        + 3 * length of filename\n\n\nPlease report any problems to:  Zip-Bugs@lists.wku.edu\n\nLast updated:  07 July 2001\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/crc_i86.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; Created by Christian Spieler, last modified 07 Jan 2007.\n;\n        TITLE   crc_i86.asm\n        NAME    crc_i86\n;\n; Optimized 8086 assembler version of the CRC32 calculation loop, intended\n; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions).\n; Supported compilers are Microsoft C (DOS real mode) and Borland C(++)\n; (Turbo C). Watcom C (16bit) should also work.\n; This module was inspired by a similar module for the Amiga (Paul Kienitz).\n;\n; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function\n; in crc32.c.\n;\n; In March/April 1997, the code has been revised to incorporate Rodney Brown's\n; ideas for optimized access to the data buffer. For 8086 real mode code,\n; the data buffer is now accessed by aligned word-wide read operations.\n; This new optimization may be turned off by defining the macro switch\n; NO_16_BIT_LOADS.\n;\n; In December 1998, the loop branch commands were changed from \"loop dest\"\n; into \"dec cx; jnz dest\". On modern systems (486 and newer), the latter\n; code is usually much faster (e.g. 1 clock cycle compared to 5 for \"loop\"\n; on Pentium MMX). For the 286, the penalty of \"dec cx; jnz\" is one clock\n; cycle (12 vs. 11 cycles); on an 8088 the cycle counts are 22 (dec cx; jnz)\n; vs. 18 (loop). I decided to optimize for newer CPU models by default, because\n; I expect that old 80286 or 8088 dinosaurier machines may be rarely used\n; nowadays. In case you want optimum performance for these old CPU models\n; you should define the OPTIMIZE_286_88 macro switch on the assembler's\n; command line.\n; Likewise, \"jcxz\" was replaced by \"jz\", because the latter is faster on\n; 486 and newer CPUs (without any penalty on 80286 and older CPU models).\n;\n; In January 2007, the \"hand-made\" memory model setup section has been guarded\n; against redefinition of @CodeSize and @DataSize symbols, to work around a\n; problem with current Open Watcom (version 1.6) wasm assembler.\n;\n; The code in this module should work with all kinds of C memory models\n; (except Borland's __HUGE__ model), as long as the following\n; restrictions are not violated:\n;\n; - The implementation assumes that the char buffer is confined to a\n;   64k segment. The pointer `s' to the buffer must be in a format that\n;   all bytes can be accessed by manipulating the offset part, only.\n;   This means:\n;   + no huge pointers\n;   + char buffer size < 64 kByte\n;\n; - Since the buffer size argument `n' is of type `size_t' (= unsigned short)\n;   for this routine, the char buffer size is limited to less than 64 kByte,\n;   anyway. So, the assumption above should be easily fulfilled.\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used,\n; or only the precomputed CRC_32_Table is needed.\n;\nifndef USE_ZLIB\nifndef CRC_TABLE_ONLY\n;\n; Setup of amount of assemble time informational messages:\n;\nifdef     DEBUG\n  VERBOSE_INFO EQU 1\nelse\n  ifdef _AS_MSG_\n    VERBOSE_INFO EQU 1\n  else\n    VERBOSE_INFO EQU 0\n  endif\nendif\n;\n; Selection of memory model, and initialization of memory model\n; related macros:\n;\nifndef __SMALL__\n  ifndef __COMPACT__\n    ifndef __MEDIUM__\n      ifndef __LARGE__\n        ifndef __HUGE__\n;         __SMALL__ EQU 1\n        endif\n      endif\n    endif\n  endif\nendif\n\nifdef __HUGE__\n; .MODEL Huge\n   ifndef @CodeSize\n    @CodeSize  EQU 1\n   endif\n   ifndef @DataSize\n    @DataSize  EQU 1\n   endif\n   Save_DS    EQU 1\n   if VERBOSE_INFO\n    if1\n      %out Assembling for C, Huge memory model\n    endif\n   endif\nelse\n   ifdef __LARGE__\n;      .MODEL Large\n      ifndef @CodeSize\n       @CodeSize  EQU 1\n      endif\n      ifndef @DataSize\n       @DataSize  EQU 1\n      endif\n      if VERBOSE_INFO\n       if1\n         %out Assembling for C, Large memory model\n       endif\n      endif\n   else\n      ifdef __COMPACT__\n;         .MODEL Compact\n         ifndef @CodeSize\n          @CodeSize  EQU 0\n         endif\n         ifndef @DataSize\n          @DataSize  EQU 1\n         endif\n         if VERBOSE_INFO\n          if1\n            %out Assembling for C, Compact memory model\n          endif\n         endif\n      else\n         ifdef __MEDIUM__\n;            .MODEL Medium\n            ifndef @CodeSize\n             @CodeSize  EQU 1\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Medium memory model\n             endif\n            endif\n         else\n;            .MODEL Small\n            ifndef @CodeSize\n             @CodeSize  EQU 0\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Small memory model\n             endif\n            endif\n         endif\n      endif\n   endif\nendif\n\nif @CodeSize\n        LCOD_OFS        EQU     2\nelse\n        LCOD_OFS        EQU     0\nendif\n\nIF @DataSize\n        LDAT_OFS        EQU     2\nelse\n        LDAT_OFS        EQU     0\nendif\n\nifdef Save_DS\n;                       (di,si,ds)+(size, return address)\n        SAVE_REGS       EQU     6+(4+LCOD_OFS)\nelse\n;                       (di,si)+(size, return address)\n        SAVE_REGS       EQU     4+(4+LCOD_OFS)\nendif\n\n;\n; Selection of the supported CPU instruction set and initialization\n; of CPU type related macros:\n;\nifdef __686\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on Pentium II/III/IV\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __586\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on Pentium\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __486\n        Use_286_code     EQU    1\n        Align_Size       EQU    4       ; dword alignment on 32 bit processors\n        Alig_PARA        EQU    1       ; paragraph aligned code segment\nelse\nifdef __386\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on 32 bit processors\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __286\n        Use_286_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\nifdef __186\n        Use_186_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nendif   ;?__186\nendif   ;?__286\nendif   ;?__386\nendif   ;?__486\nendif   ;?__586\nendif   ;?__686\n\nifdef Use_286_code\n        .286\n        Have_80x86      EQU     1\nelse\nifdef Use_186_code\n        .186\n        Have_80x86      EQU     1\nelse\n        .8086\n        Have_80x86      EQU     0\nendif   ;?Use_186_code\nendif   ;?Use_286_code\n\n;\n; Declare the segments used in this module:\n;\nif @CodeSize\nif Alig_PARA\nCRC32_TEXT      SEGMENT  PARA PUBLIC 'CODE'\nelse\nCRC32_TEXT      SEGMENT  WORD PUBLIC 'CODE'\nendif\nCRC32_TEXT      ENDS\nelse    ;!@CodeSize\nif Alig_PARA\n_TEXT   SEGMENT  PARA PUBLIC 'CODE'\nelse\n_TEXT   SEGMENT  WORD PUBLIC 'CODE'\nendif\n_TEXT   ENDS\nendif   ;?@CodeSize\n_DATA   SEGMENT  WORD PUBLIC 'DATA'\n_DATA   ENDS\n_BSS    SEGMENT  WORD PUBLIC 'BSS'\n_BSS    ENDS\nDGROUP  GROUP   _BSS, _DATA\nif @DataSize\n        ASSUME  DS: nothing, SS: DGROUP\nelse\n        ASSUME  DS: DGROUP, SS: DGROUP\nendif\n\nif @CodeSize\nEXTRN   _get_crc_table:FAR\nelse\nEXTRN   _get_crc_table:NEAR\nendif\n\n\nDo_CRC  MACRO\n        mov     bl,al\n        sub     bh,bh\nif Have_80x86\n        shl     bx,2\nelse\n        shl     bx,1\n        shl     bx,1\nendif\n        mov     al,ah\n        mov     ah,dl\n        mov     dl,dh\n        sub     dh,dh\n        xor     ax,WORD PTR [bx][si]\n        xor     dx,WORD PTR [bx+2][si]\n        ENDM\n;\nDo_1    MACRO\nif @DataSize\n        xor     al,BYTE PTR es:[di]\nelse\n        xor     al,BYTE PTR [di]\nendif\n        inc     di\n        Do_CRC\n        ENDM\n;\nDo_2    MACRO\nifndef NO_16_BIT_LOADS\nif @DataSize\n        xor     ax,WORD PTR es:[di]\nelse\n        xor     ax,WORD PTR [di]\nendif\n        add     di,2\n        Do_CRC\n        Do_CRC\nelse\n        Do_1\n        Do_1\nendif\n        ENDM\n;\nDo_4    MACRO\n        Do_2\n        Do_2\n        ENDM\n;\n\nIF @CodeSize\nCRC32_TEXT      SEGMENT\n        ASSUME  CS: CRC32_TEXT\nelse\n_TEXT   SEGMENT\n        ASSUME  CS: _TEXT\nendif\n; Line 37\n\n;\n;ulg crc32(ulg crc,\n;    ZCONST uch *buf,\n;    extent len)\n;\n        PUBLIC  _crc32\nif @CodeSize\n_crc32  PROC FAR\nelse\n_crc32  PROC NEAR\nendif\nif Have_80x86\n        enter   WORD PTR 0,0\nelse\n        push    bp\n        mov     bp,sp\nendif\n        push    di\n        push    si\nif @DataSize\n;       crc = 4+LCOD_OFS        DWORD (unsigned long)\n;       buf = 8+LCOD_OFS        DWORD PTR BYTE (uch *)\n;       len = 12+LCOD_OFS       WORD (unsigned int)\nelse\n;       crc = 4+LCOD_OFS        DWORD (unsigned long)\n;       buf = 8+LCOD_OFS        WORD PTR BYTE (uch *)\n;       len = 10+LCOD_OFS       WORD (unsigned int)\nendif\n;\nif @DataSize\n        mov     ax,WORD PTR [bp+8+LCOD_OFS]     ; buf\n        or      ax,WORD PTR [bp+10+LCOD_OFS]    ;     == NULL ?\nelse\n        cmp     WORD PTR [bp+8+LCOD_OFS],0      ; buf == NULL ?\nendif\n        jne     crc_update\n        sub     ax,ax                           ; crc = 0\n        cwd\nifndef NO_UNROLLED_LOOPS\n        jmp     fine\nelse\n        jmp     SHORT fine\nendif\n;\ncrc_update:\n        call     _get_crc_table\n;  When used with compilers that conform to the Microsoft/Borland standard\n;  C calling convention, model-dependent handling is not needed, because\n;   _get_crc_table returns NEAR pointer.\n;  But Watcom C is different and does not allow one to assume DS pointing to\n;  DGROUP. So, we load DS with DGROUP, to be safe.\n;if @DataSize\n;       push    ds\n;       mov     ds,dx\n;       ASSUME  DS: nothing\n;endif\n        mov     si,ax                           ;crc_table\nif @DataSize\n        push    ds\n        mov     ax,SEG DGROUP\n        mov     ds,ax\n        ASSUME  DS: DGROUP\nendif\n;\n        mov     ax,WORD PTR [bp+4+LCOD_OFS]     ;crc\n        mov     dx,WORD PTR [bp+6+LCOD_OFS]\n        not     ax\n        not     dx\nif @DataSize\n        les     di,DWORD PTR [bp+8+LCOD_OFS]    ;buf\n        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len\nelse\n        mov     di,WORD PTR [bp+8+LCOD_OFS]     ;buf\n        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len\nendif\n;\nifndef NO_UNROLLED_LOOPS\nifndef NO_16_BIT_LOADS\n        test    cx,cx\n        jnz     start\n        jmp     done\nstart:  test    di,1\n        jz      is_wordaligned\n        dec     cx\n        Do_1\n        mov     WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cx\nis_wordaligned:\nendif ; !NO_16_BIT_LOADS\nif Have_80x86\n        shr     cx,2\nelse\n        shr     cx,1\n        shr     cx,1\nendif\n        jz      No_Fours\n;\n        align   Align_Size              ; align destination of branch\nNext_Four:\n        Do_4\nifndef OPTIMIZE_286_88\n        dec     cx                      ; on 286, \"loop Next_Four\" needs 11\n        jnz     Next_Four               ;  clocks, one less than this code\nelse\n        loop    Next_Four\nendif\n;\nNo_Fours:\nif @DataSize\n        mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len\nelse\n        mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len\nendif\n        and     cx,00003H\nendif ; !NO_UNROLLED_LOOPS\n        jz      done\n;\n        align   Align_Size              ; align destination of branch\nNext_Byte:\n        Do_1\nifndef OPTIMIZE_286_88\n        dec     cx                      ; on 286, \"loop Next_Four\" needs 11\n        jnz     Next_Byte               ;  clocks, one less than this code\nelse\n        loop    Next_Four\nendif\n;\ndone:\nif @DataSize\n        pop     ds\n;       ASSUME  DS: DGROUP\n        ASSUME  DS: nothing\nendif\n        not     ax\n        not     dx\n;\nfine:\n        pop     si\n        pop     di\nif Have_80x86\n        leave\nelse\n        mov     sp,bp\n        pop     bp\nendif\n        ret\n\n_crc32  ENDP\n\nif @CodeSize\nCRC32_TEXT      ENDS\nelse\n_TEXT   ENDS\nendif\n;\nendif ;!CRC_TABLE_ONLY\nendif ;!USE_ZLIB\n;\nEND\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makebz2.dj2",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# djgpp 2.x\n#\n# This simple modified version of makefile.dj2 adds bzip2 support\n# to Zip for djgpp 2.x and was donated by Robert Riebisch.\n#\n# Given standard djgpp 2.x and bzip2 installations, this should create a\n# version of Zip 3.0 with bzip2 support.  Additional information is in\n# bzip2/install.txt.\n#\n# 27 June 2008\n\nVPATH=.;msdos\n# ------------- djgpp -------------\nCPPFLAGS=-I. -DDOS -DASM_CRC -DBZIP2_SUPPORT $(LOCAL_ZIP)\nASFLAGS=$(CPPFLAGS)\nCFLAGS=-Wall -O2 $(CPPFLAGS)\nUTILFLAGS=-c -DUTIL $(CFLAGS) -o\nCC=gcc\nLD=gcc\nLDFLAGS=-s\n\n# ------------- file packer --------\n# Laszlo Molnar who wrote DJ Packer and Markus F. X. J. Oberhumer who wrote\n# the compression library used by the DJ Packer have collaborated on the\n# Ultimate Packer for eXecutables, which has recently been released.  Look\n# for upx???d.zip at     http://upx.sourceforge.net\n# As an alternative, look for \"djp.exe\", now two years old, in the archive\n# mlp107[b,s].zip, found in the same location as csdpmi?[b,s].zip (see below).\n# If you have got an executable packer in your PATH, you may reduce the\n# size of the disk image of the zip*.exe's by uncommenting the lines\n# containing $(DJP) below where the exe's are built.\n#DJP=djp -q\nDJP=upx -qq --best\n\n# variables\n\n#set CRC32 to crc_gcc.o or nothing, depending on whether ASM_CRC is defined:\nCRCA_O = crc_gcc.o\n\nOBJZ = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \\\n\tcrc32.o $(CRCA_O) globals.o\nOBJI = deflate.o trees.o match.o msdos.o\nOBJU = zipfile_.o fileio_.o util_.o globals.o msdos_.o\nOBJN = zipnote.o $(OBJU)\nOBJC = zipcloak.o crc32_.o crypt_.o ttyio.o $(OBJU)\nOBJS = zipsplit.o $(OBJU)\nLIBS = -lbz2\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\n# rules\n\n.SUFFIXES:    # Delete make's default suffix list\n.SUFFIXES:    .exe .out .a .ln .o .c .cc .C .p .f .F .y .l .s .S .h\n\n.c.o:\n\t$(CC) -c $(CFLAGS) $< -o $@\n\nzips:\tzip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip.o:\t      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipfile.o:    zipfile.c $(ZIP_H) crc32.h\n\nzipup.o:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\nfileio.o:     fileio.c $(ZIP_H) crc32.h\n\nutil.o:       util.c $(ZIP_H)\n\nglobals.o:    globals.c $(ZIP_H)\n\ndeflate.o:    deflate.c $(ZIP_H)\n\ntrees.o:      trees.c $(ZIP_H)\n\ncrc_gcc.o:    crc_i386.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\ncrc32.o:      crc32.c $(ZIP_H) crc32.h\n\ncrypt.o:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\nttyio.o:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nmsdos.o:      msdos/msdos.c $(ZIP_H)\n\nzipcloak.o:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipnote.o:    zipnote.c $(ZIP_H) revision.h\n\nzipsplit.o:   zipsplit.c $(ZIP_H) revision.h\n\nzipfile_.o:   zipfile.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ zipfile.c\n\nfileio_.o:    fileio.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ fileio.c\n\nutil_.o:      util.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ util.c\n\ncrc32_.o:     crc32.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ crc32.c\n\ncrypt_.o:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) $(UTILFLAGS) $@ crypt.c\n\nmsdos_.o:     msdos/msdos.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ msdos/msdos.c\n\n\nmatch.o:      match.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzip.exe: $(OBJZ) $(OBJI)\n\techo $(OBJZ) > zip.rsp\n\techo $(OBJI) >> zip.rsp\n\techo $(LIBS) >> zip.rsp\n\t$(LD) $(LDFLAGS) -o $@ @zip.rsp\n\tdel zip.rsp\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) $(OBJC) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) $(OBJN) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) $(OBJS) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\n# These stand alone executables require dpmi services to run.  When\n# running in a DOS window under windows 3.1 or later, the dpmi server\n# is automatically present.  Under DOS, if a dpmi server is not installed,\n# by default the program will look for \"cwsdpmi.exe.\" If found, it will\n# be loaded for the duration of the program.\n# cwsdpmi is a \"free\" dpmi server written by Charles W. Sandmann\n# (sandman@clio.rice.edu).  It may be found, among other sites, on SimTel\n# and its mirrors in the .../vendors/djgpp/v2misc directory.\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.bor",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# Borland (Turbo) C++ 1.0 or 2.0.\n# Warning: this file is not suitable for Turbo C 2.0. Use makefile.tc instead.\n\n# To use, do \"make -fmakefile.bor\"\n\n# WARNING: the small model is not supported.\n# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce\n# the memory requirements.\n# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if\n# you do not have tasm.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = -DDOS -DNO_SECURE_TESTS $(LOCAL_ZIP)\n\n# Zip requires compact or large memory model.\n# with 2.1, compact model exceeds 64k code segment; use large model\nZIPMODEL=l\t# large model for Zip and ZipUtils\n\n# name of Flag to select memory model for assembler compiles, supported\n# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :\nASMODEL=__LARGE__\t\t# keep in sync with ZIPMODEL definition !!\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\nCRCA_O = crc_i86.obj\nASMOBJS = match.obj $(CRCA_O)\n\nASCPUFLAG = __$(CPU_TYP)86\n!if $(CPU_TYP) != 0\nCC_CPUFLG = -$(CPU_TYP)\n!endif\n\nVPATH=.;msdos\n# ------------- Turbo C++, Borland C++ -------------\n!if $(CC_REV) == 1\nCC = tcc\n!else\n! if !$(CC_REV)\nCC_REV = 3\n! endif\nCC = bcc\n!endif\n\nMODEL=-m$(ZIPMODEL)\n!if $(CC_REV) == 1\nCFLAGS=-w -w-eff -w-def -w-sig -w-cln -a -d -G -O -Z $(CC_CPUFLG) $(MODEL) $(LOC)\n!else\nCFLAGS=-w -w-cln -O2 -Z $(CC_CPUFLG) $(MODEL) $(LOC)\n!endif\nUTILFLAGS=-DUTIL $(CFLAGS) -o\n# for Turbo C++ 1.0, replace bcc with tcc and use the upper version of CFLAGS\n\nAS=tasm\nASFLAGS=-ml -t -m2 -DDYN_ALLOC -DSS_NEQ_DS -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)\n\nLD=$(CC)\nLDFLAGS=$(MODEL)\n\n# ------------- Common declarations:\nSTRIP=@rem\n#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:\n#    (NOTE: upx needs a 386 or higher system to run the exe compressor)\n#STRIP=upx --8086 --best\n#    or\n#STRIP=lzexe\n#    or (if you've registered PKLITE)\n#STRIP=pklite\n#    This makes a big difference in .exe size (and possibly load time)\n\n# ------------- Used by install rule\n# set BIN to the directory you want to install the executables to\nBIN = c:\\util\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n\tcrc32.obj globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj globals.obj msdos_.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crc32_.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:\t$(ZIPS)\n\nzip.obj:\tzip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:\tzipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nutil.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:\tglobals.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:\tdeflate.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:\ttrees.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:\tttyio.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nmsdos.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) msdos/$*.c\n\nzipcloak.obj:\tzipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:\tzipnote.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:\tzipsplit.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* zipfile.c\n\nfileio_.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* fileio.c\n\nutil_.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$* util.c\n\ncrc32_.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS)$* crypt.c\n\nmsdos_.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$* msdos/msdos.c\n\ncrc_i86.obj:\tmsdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) msdos\\crc_i86.asm ;\n\nmatch.obj:\tmsdos/match.asm\n\t$(AS) $(ASFLAGS) msdos\\match.asm ;\n\n# we must cut the command line to fit in the MS/DOS 128 byte limit:\nzip.exe: $(OBJZ) $(OBJI)\n\techo $(OBJZ) > zip.rsp\n\techo $(OBJI) >> zip.rsp\n\t$(LD) $(LDFLAGS) @zip.rsp\n\tdel zip.rsp\n\t$(STRIP) zip.exe\n\nzipcloak.exe: $(OBJC)\n\techo $(OBJC) > zipc.rsp\n\t$(LD) $(LDFLAGS) @zipc.rsp\n\tdel zipc.rsp\n\t$(STRIP) zipcloak.exe\n\nzipnote.exe: $(OBJN)\n\techo $(OBJN) > zipn.rsp\n\t$(LD) $(LDFLAGS) @zipn.rsp\n\tdel zipn.rsp\n\t$(STRIP) zipnote.exe\n\nzipsplit.exe: $(OBJS)\n\techo $(OBJS) > zips.rsp\n\t$(LD) $(LDFLAGS) @zips.rsp\n\tdel zips.rsp\n\t$(STRIP) zipsplit.exe\n\ninstall:\t$(ZIPS)\n\tcopy /b *.exe $(BIN)\n\nclean:\n\tdel *.obj\n\tdel *.exe\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.dj1",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# djgpp 1.x\nVPATH=.;msdos\n# ------------- djgpp -------------\nCPPFLAGS=-I. -DDOS -DASM_CRC $(LOCAL_ZIP)\nASFLAGS=$(CPPFLAGS)\nCFLAGS=-Wall -O2 -m486 $(CPPFLAGS)\nUTILFLAGS=-c -DUTIL $(CFLAGS) -o\nCC=gcc\nLD=gcc\nLDFLAGS=-s\n\nSTRIP=strip\n\n# Change the STUBIFY definition to the upper version if you want to create\n# executables which can be used without any external extender file.\n# >>> NOTE: Either copy the go32 extender into your build directory, or\n# >>>       edit the STUBIFY macro and add the correct path to \"go32.exe\".\n#STUBIFY=coff2exe -s go32.exe\nSTUBIFY=coff2exe\n\n# variables\n\n#set CRCA_O to crc_gcc.o or nothing, depending on whether ASM_CRC is defined:\nCRCA_O = crc_gcc.o\n\nOBJZ = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \\\n\tcrc32.o $(CRCA_O) globals.o\nOBJI = deflate.o trees.o match.o msdos.o\nOBJU = zipfile_.o fileio_.o util_.o globals.o msdos_.o\nOBJN = zipnote.o $(OBJU)\nOBJC = zipcloak.o crc32_.o crypt_.o ttyio.o $(OBJU)\nOBJS = zipsplit.o $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\n# rules\n\n.SUFFIXES:    # Delete make's default suffix list\n.SUFFIXES:    .exe .out .a .ln .o .c .cc .C .p .f .F .y .l .s .S .h\n\n.c.o:\n\t$(CC) -c $(CFLAGS) $< -o $@\n\nzips:\tzip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip.o:\t      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipfile.o:    zipfile.c $(ZIP_H) crc32.h\n\nzipup.o:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\nfileio.o:     fileio.c $(ZIP_H)\n\nutil.o:       util.c $(ZIP_H)\n\nglobals.o:    globals.c $(ZIP_H)\n\ndeflate.o:    deflate.c $(ZIP_H)\n\ntrees.o:      trees.c $(ZIP_H)\n\ncrc_gcc.o:    crc_i386.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\ncrc32.o:      crc32.c $(ZIP_H) crc32.h\n\ncrypt.o:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\nttyio.o:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nmsdos.o:      msdos/msdos.c $(ZIP_H)\n\nzipcloak.o:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipnote.o:    zipnote.c $(ZIP_H) revision.h\n\nzipsplit.o:   zipsplit.c $(ZIP_H) revision.h\n\nzipfile_.o:   zipfile.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ zipfile.c\n\nfileio_.o:    fileio.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ fileio.c\n\nutil_.o:      util.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ util.c\n\ncrc32_.o:     crc32.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ crc32.c\n\ncrypt_.o:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) $(UTILFLAGS) $@ crypt.c\n\nmsdos_.o:     msdos/msdos.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ msdos/msdos.c\n\nmatch.o:      match.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzip.exe: $(OBJZ) $(OBJI)\n\techo $(OBJZ) > zip.rsp\n\techo $(OBJI) >> zip.rsp\n\t$(LD) $(LDFLAGS) -o zip @zip.rsp\n\tdel zip.rsp\n\t$(STRIP) zip\n\t$(STUBIFY) zip\n\tdel zip\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) $(OBJC) -o zipcloak\n\t$(STRIP) zipcloak\n\t$(STUBIFY) zipcloak\n\tdel zipcloak\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) $(OBJN) -o zipnote\n\t$(STRIP) zipnote\n\t$(STUBIFY) zipnote\n\tdel zipnote\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) $(OBJS) -o zipsplit\n\t$(STRIP) zipsplit\n\t$(STUBIFY) zipsplit\n\tdel zipsplit\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.dj2",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# djgpp 2.x\nVPATH=.;msdos\n# ------------- djgpp -------------\nCPPFLAGS=-I. -DDOS -DASM_CRC $(LOCAL_ZIP)\nASFLAGS=$(CPPFLAGS)\nCFLAGS=-Wall -O2 $(CPPFLAGS)\nUTILFLAGS=-c -DUTIL $(CFLAGS) -o\nCC=gcc\nLD=gcc\nLDFLAGS=-s\n\n# ------------- file packer --------\n# Laszlo Molnar who wrote DJ Packer and Markus F. X. J. Oberhumer who wrote\n# the compression library used by the DJ Packer have collaborated on the\n# Ultimate Packer for eXecutables, which has recently been released.  Look\n# for upx???d.zip at     http://upx.sourceforge.net\n# As an alternative, look for \"djp.exe\", now two years old, in the archive\n# mlp107[b,s].zip, found in the same location as csdpmi?[b,s].zip (see below).\n# If you have got an executable packer in your PATH, you may reduce the\n# size of the disk image of the zip*.exe's by uncommenting the lines\n# containing $(DJP) below where the exe's are built.\n#DJP=djp -q\nDJP=upx -qq --best\n\n# variables\n\n#set CRC32 to crc_gcc.o or nothing, depending on whether ASM_CRC is defined:\nCRCA_O = crc_gcc.o\n\nOBJZ = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \\\n\tcrc32.o $(CRCA_O) globals.o\nOBJI = deflate.o trees.o match.o msdos.o\nOBJU = zipfile_.o fileio_.o util_.o globals.o msdos_.o\nOBJN = zipnote.o $(OBJU)\nOBJC = zipcloak.o crc32_.o crypt_.o ttyio.o $(OBJU)\nOBJS = zipsplit.o $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\n# rules\n\n.SUFFIXES:    # Delete make's default suffix list\n.SUFFIXES:    .exe .out .a .ln .o .c .cc .C .p .f .F .y .l .s .S .h\n\n.c.o:\n\t$(CC) -c $(CFLAGS) $< -o $@\n\nzips:\tzip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip.o:\t      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipfile.o:    zipfile.c $(ZIP_H) crc32.h\n\nzipup.o:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\nfileio.o:     fileio.c $(ZIP_H) crc32.h\n\nutil.o:       util.c $(ZIP_H)\n\nglobals.o:    globals.c $(ZIP_H)\n\ndeflate.o:    deflate.c $(ZIP_H)\n\ntrees.o:      trees.c $(ZIP_H)\n\ncrc_gcc.o:    crc_i386.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\ncrc32.o:      crc32.c $(ZIP_H) crc32.h\n\ncrypt.o:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\nttyio.o:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nmsdos.o:      msdos/msdos.c $(ZIP_H)\n\nzipcloak.o:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\nzipnote.o:    zipnote.c $(ZIP_H) revision.h\n\nzipsplit.o:   zipsplit.c $(ZIP_H) revision.h\n\nzipfile_.o:   zipfile.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ zipfile.c\n\nfileio_.o:    fileio.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ fileio.c\n\nutil_.o:      util.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ util.c\n\ncrc32_.o:     crc32.c $(ZIP_H) crc32.h\n\t$(CC) $(UTILFLAGS) $@ crc32.c\n\ncrypt_.o:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) $(UTILFLAGS) $@ crypt.c\n\nmsdos_.o:     msdos/msdos.c $(ZIP_H)\n\t$(CC) $(UTILFLAGS) $@ msdos/msdos.c\n\n\nmatch.o:      match.S\n\t$(CC) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzip.exe: $(OBJZ) $(OBJI)\n\techo $(OBJZ) > zip.rsp\n\techo $(OBJI) >> zip.rsp\n\t$(LD) $(LDFLAGS) -o $@ @zip.rsp\n\tdel zip.rsp\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) $(OBJC) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) $(OBJN) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) $(OBJS) -o $@\n#\tstubedit $@ dpmi=cwsdpmi.exe\n#\t$(DJP) $@\n\n# These stand alone executables require dpmi services to run.  When\n# running in a DOS window under windows 3.1 or later, the dpmi server\n# is automatically present.  Under DOS, if a dpmi server is not installed,\n# by default the program will look for \"cwsdpmi.exe.\" If found, it will\n# be loaded for the duration of the program.\n# cwsdpmi is a \"free\" dpmi server written by Charles W. Sandmann\n# (sandman@clio.rice.edu).  It may be found, among other sites, on SimTel\n# and its mirrors in the .../vendors/djgpp/v2misc directory.\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.emx",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit\n# using emx 0.9c for DOS.\n# By Kai-Uwe Rommel, Chr. Spieler, E-Yen Tan (and others).\n# Last updated 7th January 2007.\n#\n# This Makefile is a stripped down version of win32/Makefile.emx that\n# builds executables applying the default MSDOS emx setup.  For variant\n# targets (using zlib), and cross-compilation for WIN32 or OS/2, take a\n# look into \"win32/makefile.emx\" resp. \"os2/makefile.os2\".\n#\n# Supported Make utilities:\n# - Microsoft/IBM nmake (e.g. from MSC 6.0 or newer)\n# - dmake 3.8 or higher\n# - GNU make, at least version 3.68 (GNUish 16-bit port, RSXNT Make 3.75 in a\n#   Win95/WinNT DOS box, DJGPP v1.12 Make 3.71, some versions of DJGPP v2.x\n#   32-bit Make; current DJGPP v2.01 Make 3.76.1 does NOT work)\n# - NOT watcom make\n# The \"smart\" Make utilities mentioned below are Christian Spieler's\n# enhanced version of GNUish 16-bit Make (3.74) and his adaption of these\n# GNU Make sources to EMX (32-bit).\n\n# Supported 32-bit C Compilers for MSDOS:\n# - GNU gcc (emx kit 0.9c or newer, 32-bit)\n\n# Supported Assemblers:\n# - GNU as with GNU gcc\n\n\n# To use, enter \"make/nmake/dmake -f msdos/makefile.emx\"\n# (this makefile depends on its name being \"msdos/makefile.emx\").\n\n# emx 0.9c, gcc, a.out format, for MS-DOS\nCC=gcc -O2 -m486 -Wall\nCFLAGS=-DDOS -DMSDOS -DASM_CRC\nAS=gcc\nASFLAGS=-Di386\nLDFLAGS=-o ./\nLDFLAGS2=-s -Zsmall-conv\nOUT=-o\nOBJ=.o\nCRCA_O=crc_gcc.o\nOBJA=matchgcc.o\nOBJZS=msdos.o\nOBJUS=msdos_.o\nOSDEP_H=msdos/osdep.h\nZIPUP_H=msdos/zipup.h\n\n#default settings for target dependent macros:\nDIRSEP = /\nAS_DIRSEP = /\nRM = del\nLOCAL_OPTS = $(LOCAL_ZIP)\nCCFLAGS = $(CFLAGS) $(LOCAL_OPTS)\n\n\nOBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \\\n\tcrc32$(OBJ) $(CRCA_O)\nOBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \\\n\tttyio$(OBJ)\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)\n\nOBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)\nOBJU  = $(OBJU1) $(OBJUS)\n\nOBJN  = zipnote$(OBJ) $(OBJU)\nOBJS  = zipsplit$(OBJ) $(OBJU)\nOBJC1 = zipcloak$(OBJ) crc32_$(OBJ) crypt_$(OBJ) ttyio$(OBJ)\nOBJC  = $(OBJC1) $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES: .c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c -I. $(CCFLAGS) $(OUT)$@ $<\n\n# targets\n\nall:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip$(OBJ):      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile$(OBJ):  zipfile.c $(ZIP_H) crc32.h\nzipup$(OBJ):    zipup.c $(ZIP_H) revision.h crc32.h crypt.h $(ZIPUP_H)\nfileio$(OBJ):   fileio.c $(ZIP_H) crc32.h\nutil$(OBJ):     util.c $(ZIP_H)\nglobals$(OBJ):  globals.c $(ZIP_H)\ndeflate$(OBJ):  deflate.c $(ZIP_H)\ntrees$(OBJ):    trees.c $(ZIP_H)\ncrc32$(OBJ):    crc32.c $(ZIP_H) crc32.h\ncrypt$(OBJ):    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(OBJ):    ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nmsdos$(OBJ):    msdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c\n\nwin32zip$(OBJ): win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c\n\nwin32$(OBJ):    win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c\n\nnt$(OBJ):       win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c\n\ncrc_gcc$(OBJ):  crc_i386.S                                      # 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\nmatchgcc$(OBJ): match.S\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzipcloak$(OBJ): zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipnote$(OBJ):  zipnote.c $(ZIP_H) revision.h\nzipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h\n\nzipfile_$(OBJ): zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c\n\nfileio_$(OBJ):  fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c\n\nutil_$(OBJ):    util.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c\n\ncrc32_$(OBJ):   crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):   crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c\n\nmsdos_$(OBJ):   msdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nwin32_$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c\n\n# This next bit is nasty, but is needed to overcome the MS-DOS command\n# line limit as response files for emx's gcc seem to only work if each\n# file is on a different line. DJGPP doesn't do this (if you are at all\n# interested).\n\nzip.exe: $(OBJZ)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zip.rsp\n\t@for %%f in ($(OBJZ1)) do echo %%f >> zip.rsp\n\t@for %%f in ($(OBJZ2)) do echo %%f >> zip.rsp\n\t@for %%f in ($(OBJZS) $(OBJA)) do echo %%f >> zip.rsp\n\t$(CC) $(LDFLAGS)$@ @zip.rsp $(LDFLAGS2)\n\t@$(RM) zip.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJZ) $(LDFLAGS2)\n\nzipcloak.exe: $(OBJC)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zipcloak.rsp\n\t@for %%f in ($(OBJC1)) do echo %%f >> zipcloak.rsp\n\t@for %%f in ($(OBJU1)) do echo %%f >> zipcloak.rsp\n\t@for %%f in ($(OBJUS)) do echo %%f >> zipcloak.rsp\n\t$(CC) $(LDFLAGS)$@ @zipcloak.rsp $(LDFLAGS2)\n\t@$(RM) zipcloak.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)\n\nzipnote.exe: $(OBJN)\n\t$(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)\n\nzipsplit.exe: $(OBJS)\n\t$(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.msc",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# Microsoft C 5.1 and above.\n\n# To use, do \"make makefile.msc\"\n\n# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce\n# the memory requirements.\n# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if\n# you do not have masm.\n#\n# If you want link Zip against zlib to replace the built-in deflate routines,\n# the following changes are required:\n# - in the definition of \"LOC\", add \"-DUSE_ZLIB\" and remove \"-DNO_SECURE_TESTS\"\n# - comment out the \"ASMOBJS\" symbol definition\n# - modify the linking command blocks for zip and zipcloak according to\n#   the following scheme:\n#   add a command line \"echo ,,,zlib_$(ZIPMODEL); >> zip[c].rsp\" just\n#   before the \"$(LD)...\" line; and remove the semicolon character from the\n#   \"echo ...\" line immediately preceding the just inserted command\n\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = -DDOS -DDYN_ALLOC -DNO_SECURE_TESTS $(LOCAL_ZIP)\n\n# Zip requires compact or large memory model.\n# with 2.1, compact model exceeds 64k code segment; use large model\nZIPMODEL=L\t# large model for Zip and ZipUtils\n\n# name of Flag to select memory model for assembler compiles, supported\n# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :\nASMODEL=__LARGE__\t\t# keep in sync with ZIPMODEL definition !!\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\nASMOBJS = match.obj crc_i86.obj\n\nASCPUFLAG = __$(CPU_TYP)86\n\n# ------------- Microsoft C 5.1, 6.0, 7.0 and VC++ Pro 1.0 -------------\nCC=cl\nMODEL=-A$(ZIPMODEL)\nFP=\n# With the feature additions of Zip 3, the default data segment gets occupied\n# with too much initialized data to fit into 64k. As a workaround, for some\n# source files with large amount of message strings, -Gt<num> is used to\n# force data items of size <num> or larger into their own data segments.\nCOMMON_CFLAGS=-nologo -I. $(MODEL) $(FP) -DMSC $(LOC) -W3 -G$(CPU_TYP)\nCFLAGS=$(COMMON_CFLAGS) -Ox\nSPECFLAGS=$(COMMON_CFLAGS) -Oaict -Gs\n# For MSC/C++ 7.0 and VC++ no special flags are needed:\n# SPECFLAGS=$(CFLAGS)\nUTILFLAGS=-DUTIL $(CFLAGS) -Fo\n\nAS=masm\nASFLAGS=-ml -t -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)\n#     For MSC 6.0, use:\n#AS=ml\n#ASFLAGS=-c -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)\n# Supress -DDYN_ALLOC in ASFLAGS if you have suppressed it in CFLAGS\n\nLD=link\nLDFLAGS=/noi/farcall/packcode/e/st:0x1400/m\n#     If you use an exe packer as recommended below, remove /e from LDFLAGS\n\n# ------------- Common declarations:\nSTRIP=rem\n#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:\n#    (NOTE: upx needs a 386 or higher system to run the exe compressor)\n#STRIP=upx --8086 --best\n#    or\n#STRIP=lzexe\n#    or (if you've registered PKLITE)\n#STRIP=pklite\n#    and remove /e from LDFLAGS.\n#    This makes a big difference in .exe size (and possibly load time)\n\n# ------------- Used by install rule\n# set BIN to the directory you want to install the executables to\nBIN = c:\\util\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n\tcrc32.obj globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj globals.obj msdos_.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crc32_.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:\t$(ZIPS)\n\nzip.obj:\tzip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -Gt65 $*.c\n\n# MSC 5.1 generates bad code on zipfile with -Ox\nzipfile.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(SPECFLAGS) $*.c\n\nzipup.obj:\tzipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nutil.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:\tglobals.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:\tdeflate.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:\ttrees.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:\tttyio.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nmsdos.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) msdos/$*.c\n\nzipcloak.obj:\tzipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:\tzipnote.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\n# MSC 5.1 dies on zipsplit with -Ox\nzipsplit.obj:\tzipsplit.c $(ZIP_H) revision.h\n\t$(CC) -c $(SPECFLAGS) $*.c\n\n# MSC 5.1 generates bad code on zipfile with -Ox\nzipfile_.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(SPECFLAGS) -DUTIL -Fo$@ zipfile.c\n\nfileio_.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$@ fileio.c\n\nutil_.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$@ util.c\n\ncrc32_.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$@ crc32.c\n\ncrypt_.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS)$@ crypt.c\n\nmsdos_.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$@ msdos/msdos.c\n\ncrc_i86.obj:\tmsdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) msdos\\crc_i86.asm ;\n\nmatch.obj:\tmsdos/match.asm\n\t$(AS) $(ASFLAGS) msdos\\match.asm ;\n\n# we must cut the command line to fit in the MS/DOS 128 byte limit:\nzip.exe: $(OBJZ) $(OBJI)\n\techo $(OBJZ)+ > zip.rsp\n\techo $(OBJI); >> zip.rsp\n\t$(LD) $(LDFLAGS) @zip.rsp\n\tdel zip.rsp\n\t$(STRIP) zip.exe\n\nzipcloak.exe: $(OBJC)\n\techo $(OBJC); > zipc.rsp\n\t$(LD) $(LDFLAGS) @zipc.rsp\n\tdel zipc.rsp\n\t$(STRIP) zipcloak.exe\n\nzipnote.exe: $(OBJN)\n\techo $(OBJN); > zipn.rsp\n\t$(LD) $(LDFLAGS) @zipn.rsp\n\tdel zipn.rsp\n\t$(STRIP) zipnote.exe\n\nzipsplit.exe: $(OBJS)\n\techo $(OBJS); > zips.rsp\n\t$(LD) $(LDFLAGS) @zips.rsp\n\tdel zips.rsp\n\t$(STRIP) zipsplit.exe\n\n# No `install' and `clean' target possible as long as MSC's old MAKE utility\n# is supported (MSC 5.1 Make always tries to update ALL targets. The result\n# is that install and clean are always executed, unless an error occured.)\n#install:\t$(ZIPS)\n#\tcopy /b *.exe $(BIN)\n#\n#clean:\n#\tdel *.obj\n#\tdel *.exe\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.tc",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# Turbo C 2.0. (Thanks to Andrew Cadach <kadach@isi.itfs.nsk.su>)\n\n# To use, do \"make -fmakefile.tc\"\n\n# WARNING: the small model is not supported. You must use the large model.\n# Add -DSMALL_MEM or -DMEDIUM_MEM to the LOC macro if you wish to reduce\n# the memory requirements.\n# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if\n# you do not have tasm.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = -DDOS -DNO_SECURE_TESTS $(LOCAL_ZIP)\n\n# Zip requires compact or large memory model.\n# with 2.1, compact model exceeds 64k code segment; use large model\nZIPMODEL=l\t# large model for Zip and ZipUtils\n\n# name of Flag to select memory model for assembler compiles, supported\n# values are __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__ :\nASMODEL=__LARGE__\t\t# keep in sync with ZIPMODEL definition !!\n\n# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc.\nCPU_TYP = 0\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\nASMOBJS = match.obj crc_i86.obj\n\nASCPUFLAG = __$(CPU_TYP)86\n\n# ------------- Turbo C 2.0 -------------\nMODEL=-m$(ZIPMODEL)\nCFLAGS=-w -w-eff -w-def -w-sig -w-cln -a -d -G -O -Z $(MODEL) $(LOC)\nUTILFLAGS=-DUTIL $(CFLAGS) -o\nCC=tcc\n\n# Old versions of tasm (prior to 2.01) may not like the \"-m2\" option...\nAS=tasm\nASFLAGS=-ml -t -m2 -DDYN_ALLOC -DSS_NEQ_DS -D$(ASCPUFLAG) -D$(ASMODEL) $(LOC)\n\nLD=tcc\nLDFLAGS=$(MODEL)\n\n# ------------- Common declarations:\nSTRIP=rem\n#    If you don't have UPX, LZEXE, or PKLITE, get one of them. Then define:\n#    (NOTE: upx needs a 386 or higher system to run the exe compressor)\n#STRIP=upx --8086 --best\n#    or\n#STRIP=lzexe\n#    or (if you've registered PKLITE)\n#STRIP=pklite\n#    This makes a big difference in .exe size (and possibly load time)\n\n# ------------- Used by install rule\n# set BIN to the directory you want to install the executables to\nBIN = c:\\util\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n\tcrc32.obj globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) msdos.obj\n\nOBJU = _zipfile.obj _fileio.obj _util.obj globals.obj _msdos.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj _crc32.obj _crypt.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h msdos/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:\t$(ZIPS)\n\nzip.obj:\tzip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:\tzipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos/zipup.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nutil.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:\tglobals.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:\tdeflate.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:\ttrees.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:\tttyio.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nmsdos.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) msdos/$*.c\n\nzipcloak.obj:\tzipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) -o$* $*.c\n\nzipnote.obj:\tzipnote.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) -o$* $*.c\n\nzipsplit.obj:\tzipsplit.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) -o$* $*.c\n\n_zipfile.obj:\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* zipfile.c\n\n_fileio.obj:\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* fileio.c\n\n_util.obj:\tutil.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$* util.c\n\n_crc32.obj:\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* crc32.c\n\n_crypt.obj:\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS)$* crypt.c\n\n_msdos.obj:\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$* msdos/msdos.c\n\ncrc_i86.obj:\tmsdos/crc_i86.asm\n\t$(AS) $(ASFLAGS) msdos\\crc_i86.asm ;\n\nmatch.obj:\tmsdos/match.asm\n\t$(AS) $(ASFLAGS) msdos\\match.asm ;\n\n# make sure the command line fits in the MS/DOS 128 byte limit:\nzip.exe: $(OBJZ) $(OBJI)\n\trem   ignore any warnings in the following renaming commands:\n\tren _*.obj _*.ob\n\tren zipcloak.obj *.ob\n\tren zipnote.obj *.ob\n\tren zipsplit.obj *.ob\n\t$(LD) $(LDFLAGS) -ezip.exe *.obj\n\tren _*.ob _*.obj\n\tren zip???*.ob *.obj\n\t$(STRIP) zip.exe\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) -ezipcloak.exe $(OBJC)\n\t$(STRIP) zipcloak.exe\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) -ezipnote.exe $(OBJN)\n\t$(STRIP) zipnote.exe\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) -ezipsplit.exe $(OBJS)\n\t$(STRIP) zipsplit.exe\n\ninstall:        $(ZIPS)\n\tcopy /b *.exe $(BIN)\n\nclean:\n\tdel *.obj\n\tdel *.exe\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/makefile.wat",
    "content": "# WMAKE makefile for 16 bit MSDOS or 32 bit DOS extender (PMODE/W or DOS/4GW)\n# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 07 Aug 2005.\n# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.\n#\n# Invoke from Zip source dir with \"WMAKE -F MSDOS\\MAKEFILE.WAT [targets]\"\n# To build with debug info use \"WMAKE DEBUG=1 ...\"\n# To build with no assembly modules use \"WMAKE NOASM=1 ...\"\n# To make the PMODE/W version use \"WMAKE PM=1 ...\"\n# To make the DOS/4GW version use \"WMAKE GW=1 ...\" (overrides PM=1)\n#   Note: specifying PM or GW without NOASM requires that the win32 source\n#   directory be present, so it can access the 32 bit assembly sources.\n#   PMODE/W is recommended over DOS/4GW for best performance.\n# To create a low memory usage version of Zip, use \"WMAKE WSIZE=8192 ...\"\n#   (or whatever power of two less than 32768 you wish) -- this also causes\n#   SMALL_MEM to be defined.  Compression performance will be reduced.\n#   This currently is not supported with PM=1 or GW=1.\n#\n# Other options to be fed to the compiler and assembler can be specified in\n# an environment variable called LOCAL_ZIP.\n\nvariation = $(%LOCAL_ZIP)\n\n# Stifle annoying \"Delete this file?\" questions when errors occur:\n.ERASE\n\n.EXTENSIONS:\n.EXTENSIONS: .exe .obj .c .h .asm\n\n# We maintain multiple sets of object files in different directories so that\n# we can compile msdos, dos/4gw or pmode/w, and win32 versions of Zip without\n# their object files interacting.  The following var must be a directory name\n# ending with a backslash.  All object file names must include this macro\n# at the beginning, for example \"$(O)foo.obj\".\n\n!ifdef GW\nPM = 1      # both protected mode formats use the same object files\n!endif\n\n!ifdef DEBUG\n!  ifdef PM\nOBDIR = od32d\n!  else\n!    ifdef WSIZE\nOBDIR = od16l\nsize = -DWSIZE=$(WSIZE) -DSMALL_MEM\n!    else\nOBDIR = od16d\nsize = -DMEDIUM_MEM\n!    endif\n!  endif\n!else\n!  ifdef PM\nOBDIR = ob32d\n!  else\n!    ifdef WSIZE\nOBDIR = ob16l\nsize = -DWSIZE=$(WSIZE) -DSMALL_MEM\n!    else\nOBDIR = ob16d\nsize = -DMEDIUM_MEM\n!    endif\n!  endif\n!endif\nO = $(OBDIR)\\   # comment here so backslash won't continue the line\n\n# The assembly hot-spot code in crc_i[3]86.asm and match[32].asm is\n# optional.  This section controls its usage.\n\n!ifdef NOASM\n  # C source\nasmob =\ncvars = $+$(cvars)$- -DDYN_ALLOC -DNO_ASM   # or ASM_CRC might default on!\n# \"$+$(foo)$-\" means expand foo as it has been defined up to now; normally,\n# this make defers inner expansion until the outer macro is expanded.\n!else  # !NOASM\nasmob = $(O)crc.obj $(O)match.obj\n!  ifdef PM\ncvars = $+$(cvars)$- -DASM_CRC -DASMV       # no DYN_ALLOC with match32.asm\ncrc_s = win32\\crc_i386.asm   # requires that the win32 directory be present\nmat_s = win32\\match32.asm    # ditto\n!  else\ncvars = $+$(cvars)$- -DDYN_ALLOC -DASM_CRC -DASMV\navars = $+$(avars)$- -DDYN_ALLOC\ncrc_s = msdos\\crc_i86.asm\nmat_s = msdos\\match.asm\n!  endif\n!endif\n\n# Now we have to pick out the proper compiler and options for it.  This gets\n# pretty complicated with the PM, GW, DEBUG, and NOASM options...\n\nlink   = wlink\nasm    = wasm\n\n!ifdef PM\ncc     = wcc386\n# Use Pentium Pro timings, register args, static strings in code:\ncflags = -bt=DOS -mf -6r -zt -zq\naflags = -bt=DOS -mf -3 -zq\ncvars  = $+$(cvars)$- -DDOS $(variation)\navars  = $+$(avars)$- -DWATCOM_DSEG $(variation)\n\n!  ifdef GW\nlflags = sys DOS4G\n!  else\n# THIS REQUIRES THAT PMODEW.EXE BE FINDABLE IN THE COMMAND PATH.\n# It does NOT require you to add a pmodew entry to wlink.lnk or wlsystem.lnk.\ndefaultlibs = libpath %WATCOM%\\lib386 libpath %WATCOM%\\lib386\\dos\nlflags = format os2 le op osname='PMODE/W' op stub=pmodew.exe $(defaultlibs)\n!  endif\n\n!else   # plain 16-bit DOS:\n\ncc     = wcc\n# Use plain 8086 instructions, large memory model, static strings in code:\ncflags = -bt=DOS -ml -0 -zt -zq\naflags = -bt=DOS -ml -0 -zq\ncvars  = $+$(cvars)$- -DDOS $(size) $(variation)\navars  = $+$(avars)$- $(size) $(variation)\nlflags = sys DOS\n!endif  # !PM\n\n# Specify optimizations, or a nonoptimized debugging version:\n\n!ifdef DEBUG\ncdebug = -od -d2\nldebug = d w all op symf\n!else\n!  ifdef PM\ncdebug = -s -obhikl+rt -oe=100 -zp8\n# -oa helps slightly but might be dangerous.\n!  else\ncdebug = -s -oehiklrt\n!  endif\nldebug = op el\n!endif\n\n# How to compile most sources:\n.c.obj:\n\t$(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@\n\n# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for\n# ZipNote, and OBJS is for ZipSplit:\n\nOBJZ2 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)zipfile.obj $(O)zipup.obj\nOBJZA = $(OBJZ2) $(O)util.obj $(O)fileio.obj $(O)deflate.obj\nOBJZB = $(O)trees.obj $(O)globals.obj $(O)crc32.obj $(asmob) $(O)msdos.obj\n\nOBJU2 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)globals.obj\nOBJ_U = $(OBJU2) $(O)msdos_.obj\n\nOBJC  = $(O)zipcloak.obj $(O)crc32_.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)\n\nOBJN  = $(O)zipnote.obj $(OBJ_U)\n\nOBJS  = $(O)zipsplit.obj $(OBJ_U)\n\n# Common header files included by all C sources:\n\nZIP_H = zip.h ziperr.h tailor.h msdos\\osdep.h\n\n\n# HERE WE GO!  By default, make all targets:\nall: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe\n\n# Convenient shorthand options for single targets:\nz:   Zip.exe       .SYMBOLIC\nn:   ZipNote.exe   .SYMBOLIC\nc:   ZipCloak.exe  .SYMBOLIC\ns:   ZipSplit.exe  .SYMBOLIC\n\nZip.exe:\t$(OBDIR) $(OBJZA) $(OBJZB) $(OBJV)\n\tset WLK_VA=file {$(OBJZA)}\n\tset WLK_VB=file {$(OBJZB) $(OBJV)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VA @WLK_VB\n\tset WLK_VA=\n\tset WLK_VB=\n# We use WLK_VA and WLK_VB to keep the size of each command under 256 chars.\n\nZipNote.exe:\t$(OBDIR) $(OBJN)\n\tset WLK_VAR=file {$(OBJN)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VAR\n\tset WLK_VAR=\n\nZipCloak.exe:\t$(OBDIR) $(OBJC)\n\tset WLK_VAR=file {$(OBJC)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VAR\n\tset WLK_VAR=\n\nZipSplit.exe:\t$(OBDIR) $(OBJS)\n\tset WLK_VAR=file {$(OBJS)}\n\t$(link) $(lflags) $(ldebug) name $@ @WLK_VAR\n\tset WLK_VAR=\n\n# Source dependencies:\n\n$(O)crc32.obj:    crc32.c $(ZIP_H) crc32.h\n$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n$(O)deflate.obj:  deflate.c $(ZIP_H)\n$(O)fileio.obj:   fileio.c $(ZIP_H) crc32.h\n$(O)globals.obj:  globals.c $(ZIP_H)\n$(O)trees.obj:    trees.c $(ZIP_H)\n$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h\n$(O)util.obj:     util.c $(ZIP_H)\n$(O)zip.obj:      zip.c $(ZIP_H) crc32.h crypt.h revision.h ttyio.h\n$(O)zipfile.obj:  zipfile.c $(ZIP_H) crc32.h\n$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crc32.h crypt.h msdos\\zipup.h\n$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h\n$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h\n\n# Special case object files:\n\n$(O)msdos.obj:    msdos\\msdos.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) msdos\\msdos.c -fo=$@\n\n$(O)match.obj:    $(mat_s)\n\t$(asm) $(aflags) $(avars) $(mat_s) -fo=$@\n\n$(O)crc.obj:      $(crc_s)\n\t$(asm) $(aflags) $(avars) $(crc_s) -fo=$@\n\n# Variant object files for ZipNote, ZipCloak, and ZipSplit:\n\n$(O)zipfile_.obj: zipfile.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@\n\n$(O)fileio_.obj:  fileio.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@\n\n$(O)util_.obj:    util.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@\n\n$(O)crc32_.obj:   crc32.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crc32.c -fo=$@\n\n$(O)crypt_.obj:   crypt.c $(ZIP_H) crc32.h crypt.h ttyio.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@\n\n$(O)msdos_.obj:   msdos\\msdos.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL msdos\\msdos.c -fo=$@\n\n# Creation of subdirectory for intermediate files\n$(OBDIR):\n\t-mkdir $@\n\n# Unwanted file removal:\n\nclean:     .SYMBOLIC\n\tdel $(O)*.obj\n\ncleaner:   clean  .SYMBOLIC\n\tdel Zip.exe\n\tdel ZipNote.exe\n\tdel ZipCloak.exe\n\tdel ZipSplit.exe\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/match.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2007-Mar-04 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n;\n; match.asm by Jean-loup Gailly.\n\n; match.asm, optimized version of longest_match() in deflate.c\n; Must be assembled with masm -ml. To be used only with C compact model\n; or large model. (For large model, assemble with -D__LARGE__).\n; This file is only optional. If you don't have masm or tasm, use the\n; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj\n; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is\n; assembled with an equivalent -DWSIZE=<whatever>.\n;\n; The code has been prepared for two different C compiler calling conventions\n; and contains some support for dynamically allocated working space.\n; The different environments are selected by two conditional flags:\n;   DYN_ALLOC  : select support for malloc'ed working space\n;   SS_NEQ_DS  : relaxes assumption that stack and default data segments\n;                are identical\n; When SS_NEQ_DS is defined, the code segment is used to store some\n; local variables. This (bad) coding practice is very likely to break any\n; `segment protection scheme', it will most probably only work for real\n; mode programs.\n;\n; Turbo C 2.0 does not support static allocation of more than 64K bytes per\n; file, and does not have SS == DS. So TC and BC++ users must use:\n;   tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match;\n;\n; To simplify the code, the option -DDYN_ALLOC is supported for OS/2\n; only if the arrays are guaranteed to have zero offset (allocated by\n; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C.\n;\n; Per default, test code is included to check if the above requirements are\n; fulfilled. This test code can be disabled by defining the compile time\n; option flag NO_SECURE_TESTS when compiling for a production executable.\n; This shortens the code size (but the performance gain is neglectable).\n; The security tests should remain enabled, when a new C compiler\n; and/or a new set of compilation options is tried.\n\n        name    match\n\n; Do NOT assemble this source if external crc32 routine from zlib gets used.\n;\nifndef USE_ZLIB\n\nifdef     DEBUG\n  VERBOSE_INFO EQU 1\nelse\n  ifdef _AS_MSG_\n    VERBOSE_INFO EQU 1\n  else\n    VERBOSE_INFO EQU 0\n  endif\nendif\n\nifndef __SMALL__\n  ifndef __COMPACT__\n    ifndef __MEDIUM__\n      ifndef __LARGE__\n        ifndef __HUGE__\n;         __SMALL__ EQU 1\n        endif\n      endif\n    endif\n  endif\nendif\n\nifdef __HUGE__\n; .MODEL Huge\n   ifndef @CodeSize\n    @CodeSize  EQU 1\n   endif\n   ifndef @DataSize\n    @DataSize  EQU 1\n   endif\n   Save_DS    EQU 1\n   if VERBOSE_INFO\n    if1\n      %out Assembling for C, Huge memory model\n    endif\n   endif\nelse\n   ifdef __LARGE__\n;      .MODEL Large\n      ifndef @CodeSize\n       @CodeSize  EQU 1\n      endif\n      ifndef @DataSize\n       @DataSize  EQU 1\n      endif\n      if VERBOSE_INFO\n       if1\n         %out Assembling for C, Large memory model\n       endif\n      endif\n   else\n      ifdef __COMPACT__\n;         .MODEL Compact\n         ifndef @CodeSize\n          @CodeSize  EQU 0\n         endif\n         ifndef @DataSize\n          @DataSize  EQU 1\n         endif\n         if VERBOSE_INFO\n          if1\n            %out Assembling for C, Compact memory model\n          endif\n         endif\n      else\n         ifdef __MEDIUM__\n;            .MODEL Medium\n            ifndef @CodeSize\n             @CodeSize  EQU 1\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Medium memory model\n             endif\n            endif\n         else\n;            .MODEL Small\n            ifndef @CodeSize\n             @CodeSize  EQU 0\n            endif\n            ifndef @DataSize\n             @DataSize  EQU 0\n            endif\n            if VERBOSE_INFO\n             if1\n               %out Assembling for C, Small memory model\n             endif\n            endif\n         endif\n      endif\n   endif\nendif\n\nif @CodeSize\n        LCOD_OFS        EQU     2\nelse\n        LCOD_OFS        EQU     0\nendif\n\nIF @DataSize\n        LDAT_OFS        EQU     2\nelse\n        LDAT_OFS        EQU     0\nendif\n\nifdef Save_DS\n;                       (di,si,ds)+(size, return address)\n        SAVE_REGS       EQU     6+(4+LCOD_OFS)\nelse\n;                       (di,si)+(size, return address)\n        SAVE_REGS       EQU     4+(4+LCOD_OFS)\nendif\n\n;\n; Selection of the supported CPU instruction set and initialization\n; of CPU type related macros:\n;\nifdef __586\n        Use_286_code    EQU     1\n        Align_Size      EQU     16      ; paragraph alignment on Pentium\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __486\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on 32 bit processors\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __386\n        Use_286_code    EQU     1\n        Align_Size      EQU     4       ; dword alignment on 32 bit processors\n        Alig_PARA       EQU     1       ; paragraph aligned code segment\nelse\nifdef __286\n        Use_286_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\nifdef __186\n        Use_186_code    EQU     1\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nelse\n        Align_Size      EQU     2       ; word alignment on 16 bit processors\n        Alig_PARA       EQU     0       ; word aligned code segment\nendif   ;?__186\nendif   ;?__286\nendif   ;?__386\nendif   ;?__486\nendif   ;?__586\n\nifdef Use_286_code\n        .286\n        Have_80x86      EQU     1\nelse\nifdef Use_186_code\n        .186\n        Have_80x86      EQU     1\nelse\n        .8086\n        Have_80x86      EQU     0\nendif   ;?Use_186_code\nendif   ;?Use_286_code\n\nifndef DYN_ALLOC\n        extrn   _prev         : word\n        extrn   _window       : byte\n        prev    equ  _prev    ; offset part\n        window  equ  _window\nendif\n\n_DATA    segment  word public 'DATA'\n        extrn   _nice_match   : word\n        extrn   _match_start  : word\n        extrn   _prev_length  : word\n        extrn   _good_match   : word\n        extrn   _strstart     : word\n        extrn   _max_chain_length : word\nifdef DYN_ALLOC\n        extrn   _prev         : word\n        extrn   _window       : word\n        prev    equ 0         ; offset forced to zero\n        window  equ 0\n        window_seg equ _window[2]\n        window_off equ 0\nelse\n        wseg    dw seg _window\n        window_seg equ wseg\n        window_off equ offset _window\nendif\n_DATA    ends\n\nDGROUP  group _DATA\n\nif @CodeSize\nif Alig_PARA\nMATCH_TEXT      SEGMENT  PARA PUBLIC 'CODE'\nelse\nMATCH_TEXT      SEGMENT  WORD PUBLIC 'CODE'\nendif\n        assume  cs: MATCH_TEXT, ds: DGROUP\nelse    ;!@CodeSize\nif Alig_PARA\n_TEXT   segment para public 'CODE'\nelse\n_TEXT   segment word public 'CODE'\nendif\n        assume  cs: _TEXT, ds: DGROUP\nendif   ;?@CodeSize\n\n        public  _match_init\n        public  _longest_match\n\nifndef      WSIZE\n        WSIZE         equ 32768         ; keep in sync with zip.h !\nendif\n        MIN_MATCH     equ 3\n        MAX_MATCH     equ 258\n        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)\n        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)\n\nifdef DYN_ALLOC\n  ifdef SS_NEQ_DS\n    prev_ptr    dw  seg _prev           ; pointer to the prev array\n  endif\nelse\n    prev_ptr    dw  seg _prev           ; pointer to the prev array\nendif\nifdef SS_NEQ_DS\n    match_start dw  0                   ; copy of _match_start if SS != DS\n    nice_match  dw  0                   ; copy of _nice_match  if SS != DS\nendif\n\n; initialize or check the variables used in match.asm.\n\nif @CodeSize\n_match_init proc far                    ; 'proc far' for large model\nelse\n_match_init proc near                   ; 'proc near' for compact model\nendif\nifdef SS_NEQ_DS\n        ma_start equ cs:match_start     ; does not work on OS/2\n        nice     equ cs:nice_match\nelse\n        assume ss: DGROUP\n        ma_start equ ss:_match_start\n        nice     equ ss:_nice_match\n  ifndef NO_SECURE_TESTS\n        mov     ax,ds\n        mov     bx,ss\n        cmp     ax,bx                   ; SS == DS?\n        jne     fatal_err\n  endif\nendif\nifdef DYN_ALLOC\n  ifndef NO_SECURE_TESTS\n        cmp     _prev[0],0              ; verify zero offset\n        jne     fatal_err\n        cmp     _window[0],0\n        jne     fatal_err\n  endif\n  ifdef SS_NEQ_DS\n        mov     ax,_prev[2]             ; segment value\n        mov     cs:prev_ptr,ax          ; ugly write to code, crash on OS/2\n        prev_seg  equ cs:prev_ptr\n  else\n        prev_seg  equ ss:_prev[2]       ; works on OS/2 if SS == DS\n  endif\nelse\n        prev_seg  equ cs:prev_ptr\nendif\n        ret\nifndef NO_SECURE_TESTS\nif @CodeSize\n        extrn   _exit : far             ; 'far' for large model\nelse\n        extrn   _exit : near            ; 'near' for compact model\nendif\nfatal_err:                              ; (quiet) emergency stop:\n        call    _exit                   ; incompatible \"global vars interface\"\nendif\n\n_match_init endp\n\n; -----------------------------------------------------------------------\n; Set match_start to the longest match starting at the given string and\n; return its length. Matches shorter or equal to prev_length are discarded,\n; in which case the result is equal to prev_length and match_start is\n; garbage.\n; IN assertions: cur_match is the head of the hash chain for the current\n;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n\n; int longest_match(cur_match)\n\n        align   Align_Size\n\nif @CodeSize\n_longest_match  proc far                 ; 'proc far' for large model\nelse\n_longest_match  proc near                ; 'proc near' for compact model\nendif\n        push    bp\n        mov     bp,sp\n        push    di\n        push    si\n        push    ds\n\nif @CodeSize\n        cur_match    equ word ptr [bp+6] ; [bp+6] for large model\nelse\n        cur_match    equ word ptr [bp+4] ; [bp+4] for compact model\nendif\n\n;       window       equ es:window (es:0 for DYN_ALLOC)\n;       prev         equ ds:prev\n;       match        equ es:si\n;       scan         equ es:di\n;       chain_length equ bp\n;       best_len     equ bx\n;       limit        equ dx\n\n        mov     si,cur_match            ; use bp before it is destroyed\nifdef SS_NEQ_DS\n        mov     ax,_nice_match\n        mov     nice,ax                 ; ugly write to code, crash on OS/2\nendif\n        mov     dx,_strstart\n        mov     bp,_max_chain_length    ; chain_length = max_chain_length\n        mov     di,dx\n        sub     dx,MAX_DIST             ; limit = strstart-MAX_DIST\n        cld                             ; string ops increment si and di\n        jae     limit_ok\n        sub     dx,dx                   ; limit = NIL\nlimit_ok:\n        add     di,2+window_off         ; di = offset(window + strstart + 2)\n        mov     bx,_prev_length         ; best_len = prev_length\n        mov     es,window_seg\n        mov     ax,es:[bx+di-3]         ; ax = scan[best_len-1..best_len]\n        mov     cx,es:[di-2]            ; cx = scan[0..1]\n        cmp     bx,_good_match          ; do we have a good match already?\n        mov     ds,prev_seg             ; (does not destroy the flags)\n        assume  ds: nothing\n        jb      do_scan                 ; good match?\nif Have_80x86\n        shr     bp,2                    ; chain_length >>= 2\nelse\n        shr     bp,1                    ; chain_length >>= 2\n        shr     bp,1\nendif\n        jmp     short do_scan\n\n        align   Align_Size              ; align destination of branch\nlong_loop:\n; at this point, ds:di == scan+2, ds:si == cur_match\n        mov     ax,[bx+di-3]            ; ax = scan[best_len-1..best_len]\n        mov     cx,[di-2]               ; cx = scan[0..1]\n        mov     ds,prev_seg             ; reset ds to address the prev array\nshort_loop:\n; at this point, di == scan+2, si = cur_match,\n; ax = scan[best_len-1..best_len] and cx = scan[0..1]\nif (WSIZE-32768)\n        and     si,WSIZE-1              ; not needed if WSIZE=32768\nendif\n        shl     si,1                    ; cur_match as word index\n        dec     bp                      ; --chain_length\n        mov     si,prev[si]             ; cur_match = prev[cur_match]\n        jz      the_end\n        cmp     si,dx                   ; cur_match <= limit ?\n        jbe     the_end\ndo_scan:\n        cmp     ax,word ptr es:window[bx+si-1] ; check match at best_len-1\n        jne     short_loop\n        cmp     cx,word ptr es:window[si]      ; check min_match_length match\n        jne     short_loop\n\n        mov     cx,es\n        add     si,2+window_off         ; si = match\n        mov     ds,cx                   ; ds = es = window\n        mov     cx,(MAX_MATCH-2)/2      ; scan for at most MAX_MATCH bytes\n        mov     ax,di                   ; ax = scan+2\n        repe    cmpsw                   ; loop until mismatch\n        je      maxmatch                ; match of length MAX_MATCH?\nmismatch:\n        mov     cl,[di-2]               ; mismatch on first or second byte?\n        xchg    ax,di                   ; di = scan+2, ax = end of scan\n        sub     cl,[si-2]               ; cl = 0 if first bytes equal\n        sub     ax,di                   ; ax = len\n        sub     si,2+window_off         ; si = cur_match + len\n        sub     si,ax                   ; si = cur_match\n        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)\n        adc     ax,0                    ; ax = carry ? len+1 : len\n        cmp     ax,bx                   ; len > best_len ?\n        jle     long_loop\n        mov     ma_start,si             ; match_start = cur_match\n        mov     bx,ax                   ; bx = best_len = len\n        cmp     ax,nice                 ; len >= nice_match ?\n        jl      long_loop\nthe_end:\n        pop     ds\n        assume  ds: DGROUP\nifdef SS_NEQ_DS\n        mov     ax,ma_start             ; garbage if no match found\n        mov     ds:_match_start,ax\nendif\n        pop     si\n        pop     di\n        pop     bp\n        mov     ax,bx                   ; result = ax = best_len\n        ret\nmaxmatch:                               ; come here if maximum match\n        cmpsb                           ; increment si and di\n        jmp     mismatch                ; force match_length = MAX_LENGTH\n\n_longest_match  endp\n\nif @CodeSize\nMATCH_TEXT      ENDS\nelse\n_TEXT   ENDS\nendif\n;\nendif ;!USE_ZLIB\n;\nend\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/msdos.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* little or no material in this file is used by UTIL */\n\n#include <dos.h>\n#include <time.h>\n\n\n#if defined(__GO32__) || defined(__TURBOC__)\n#  include <dir.h> /* prototypes of find*() */\n   typedef struct ffblk   ff_dir;\n#  define FATTR (hidden_files ? FA_HIDDEN+FA_SYSTEM+FA_DIREC : FA_DIREC)\n#  define FFIRST(n,d,a)   findfirst(n,(struct ffblk *)d,a)\n#  define FNEXT(d)        findnext((struct ffblk *)d)\n#  if (defined(__TURBOC__) || (defined(__DJGPP__) && (__DJGPP__ >=2)))\n#    if (defined(__DJGPP__) && (__DJGPP__ == 2) && (__DJGPP_MINOR__ == 0))\n#      include <libc/dosio.h>\n#    endif\n#    define GetFileMode(name) _chmod(name, 0)\n#    define SetFileMode(name, attr) _chmod(name, 1, attr)\n#  else /* DJGPP v1.x */\n#    define GetFileMode(name) bdosptr(0x43, (name), 0)\n#  endif\n#endif /* __GO32__ || __TURBOC__ */\n\n#if defined(MSC) || defined(__WATCOMC__)\n   typedef struct find_t  ff_dir;\n#  define FATTR (hidden_files ? _A_HIDDEN+_A_SYSTEM+_A_SUBDIR : _A_SUBDIR)\n#  ifndef FA_LABEL\n#    define FA_LABEL      _A_VOLID\n#  endif\n#  define FFIRST(n,d,a)   _dos_findfirst(n,a,(struct find_t *)d)\n#  define FNEXT(d)        _dos_findnext((struct find_t *)d)\n#  define ff_name         name\n#  define ff_fdate        wr_date\n#  define ff_ftime        wr_time\n#  define ff_attrib       attrib\n#endif /* MSC || __WATCOMC__ */\n\n#ifdef __EMX__\n#  ifdef EMX_OBSOLETE           /* emx 0.9b or earlier */\n#    define size_t xxx_size_t\n#    define wchar_t xxx_wchar_t\n#    define tm xxx_tm\n#    include <sys/emx.h>\n#    undef size_t\n#    undef wchar_t\n#    undef tm\n#  else /* !EMX_OBSOLETE */     /* emx 0.9c or newer */\n#    include <emx/syscalls.h>\n#  endif /* ?EMX_OBSOLETE */\n   typedef struct _find   ff_dir;\n#  define FATTR (hidden_files ? _A_HIDDEN+_A_SYSTEM+_A_SUBDIR : _A_SUBDIR)\n#  define FA_LABEL        _A_VOLID\n#  define FFIRST(n,d,a)   __findfirst(n,a,d)\n#  define FNEXT(d)        __findnext(d)\n#  define ff_name         name\n#  define ff_fdate        date\n#  define ff_ftime        time\n#  define ff_attrib       attr\n#  define GetFileMode(name) __chmod(name, 0, 0)\n#  define SetFileMode(name, attr) __chmod(name, 1, attr)\n#endif /* __EMX__ */\n\n#ifndef SetFileMode\n#  define SetFileMode(name, attr) _dos_setfileattr(name, attr)\n#endif\n\n\n#define PAD  0\n#define PATH_END '/'\n\n/* Library functions not in (most) header files */\nint rmdir OF((const char *));\nint utime OF((char *, ztimbuf *));\n\n/* Local functions */\n#ifndef GetFileMode\nint GetFileMode OF((char *name));\n#endif /* !GetFileMode */\n\nlocal int  initDirSearch OF((char *name, ff_dir *ff_context_p));\nlocal char *getVolumeLabel OF((int, ulg *, ulg *, time_t *));\nlocal int  wild_recurse OF((char *, char *));\nlocal int procname_dos OF((char *n, int caseflag, unsigned attribs));\nlocal int is_running_on_windows OF((void));\n\n#define MSDOS_INVALID_ATTR      0xFF\n#define getDirEntryAttr(d)      ((d)->ff_attrib)\n\n/* Module level variables */\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Module level constants */\nlocal ZCONST char wild_match_all[] = \"*.*\";\n\n\n#ifndef GetFileMode\nint GetFileMode(char *name)\n{\n  unsigned int attr = 0;\n  return (_dos_getfileattr(name, &attr) ? -1 : attr);\n}\n#endif /* !GetFileMode */\n\nlocal int initDirSearch(name, ff_context_p)\n  char *name;                   /* name of directory to scan */\n  ff_dir *ff_context_p;         /* pointer to FFIRST/FNEXT context structure */\n{\n  int r;                        /* FFIRST return value */\n  char *p, *q;                  /* temporary copy of name, and aux pointer */\n\n  if ((p = malloc(strlen(name) + (2 + sizeof(wild_match_all)))) == NULL)\n    return ZE_MEM;\n\n  strcpy(p, name);\n  q = p + strlen(p);\n  if (q[-1] == ':')\n    *q++ = '.';\n  if ((q - p) > 0 && *(q - 1) != '/')\n    *q++ = '/';\n  strcpy(q, wild_match_all);\n  r = FFIRST(p, ff_context_p, FATTR);\n  free((zvoid *)p);\n\n  return (r ? ZE_MISS : ZE_OK);\n}\n\nlocal char *getVolumeLabel(drive, vtime, vmode, vutim)\n  int drive;    /* drive name: 'A' .. 'Z' or '\\0' for current drive */\n  ulg *vtime;   /* volume label creation time (DOS format) */\n  ulg *vmode;   /* volume label file mode */\n  time_t *vutim;/* volume label creation time (UNIX format) */\n\n/* If a volume label exists for the given drive, return its name and\n   set its time and mode. The returned name must be static data. */\n{\n  static char vol[14];\n  ff_dir d;\n  char *p;\n\n  if (drive) {\n    vol[0] = (char)drive;\n    strcpy(vol+1, \":/\");\n  } else {\n    strcpy(vol, \"/\");\n  }\n  strcat(vol, wild_match_all);\n  if (FFIRST(vol, &d, FA_LABEL) == 0) {\n    strncpy(vol, d.ff_name, sizeof(vol)-1);\n    vol[sizeof(vol)-1] = '\\0';   /* just in case */\n    if ((p = strchr(vol, '.')) != NULL) /* remove dot, though PKZIP doesn't */\n      strcpy(p, p + 1);\n    *vtime = ((ulg)d.ff_fdate << 16) | ((ulg)d.ff_ftime & 0xffff);\n    *vmode = (ulg)d.ff_attrib;\n    *vutim = dos2unixtime(*vtime);\n    return vol;\n  }\n  return NULL;\n}\n\n\n#ifdef MSDOS16\n#define ONENAMELEN 12   /* no 16-bit compilers supports LFN */\n#else\n#define ONENAMELEN 255\n#endif\n\n/* whole is a pathname with wildcards, wildtail points somewhere in the  */\n/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */\n\nlocal int wild_recurse(whole, wildtail)\nchar *whole;\nchar *wildtail;\n{\n    ff_dir dir;\n    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;\n    ush newlen, amatch = 0;\n    int e = ZE_MISS;\n\n    if (!isshexp(wildtail)) {\n        struct stat s;                          /* dummy buffer for stat() */\n\n        if (!LSSTAT(whole, &s))                 /* file exists ? */\n            return procname(whole, 0);\n        else\n            return ZE_MISS;                     /* woops, no wildcards! */\n    }\n\n    /* back up thru path components till existing dir found */\n    do {\n        name = wildtail + strlen(wildtail) - 1;\n        for (;;)\n            if (name-- <= wildtail || *name == PATH_END) {\n                subwild = name + 1;\n                plug2 = *subwild;\n                *subwild = 0;\n                break;\n            }\n        if (glue)\n            *glue = plug;\n        glue = subwild;\n        plug = plug2;\n        e = initDirSearch(whole, &dir);\n    } while (e == ZE_MISS && subwild > wildtail);\n    wildtail = subwild;                 /* skip past non-wild components */\n    if (e != ZE_OK) {\n        if (glue)\n            *glue = plug;\n        goto ohforgetit;\n    }\n    subwild = strchr(wildtail + 1, PATH_END);\n    /* this \"+ 1\" dodges the  ^^^ hole left by *glue == 0 */\n    if (subwild != NULL) {\n        *(subwild++) = 0;               /* wildtail = one component pattern */\n        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);\n    } else\n        newlen = strlen(whole) + (ONENAMELEN + 1);\n    if ((newwhole = malloc(newlen)) == NULL) {\n        if (glue)\n            *glue = plug;\n        e = ZE_MEM;\n        goto ohforgetit;\n    }\n    strcpy(newwhole, whole);\n    newlen = strlen(newwhole);\n    if (glue)\n        *glue = plug;                           /* repair damage to whole */\n    if (!isshexp(wildtail)) {\n        e = ZE_MISS;                            /* non-wild name not found */\n        goto ohforgetit;\n    }\n\n    do {\n        if (strcmp(dir.ff_name, \".\") && strcmp(dir.ff_name, \"..\")\n                                  && MATCH(wildtail, dir.ff_name, 0)) {\n            strcpy(newwhole + newlen, dir.ff_name);\n            if (subwild) {\n                name = newwhole + strlen(newwhole);\n                *(name++) = PATH_END;\n                strcpy(name, subwild);\n                e = wild_recurse(newwhole, name);\n            } else\n                e = procname_dos(newwhole, 0, getDirEntryAttr(&dir));\n            newwhole[newlen] = 0;\n            if (e == ZE_OK)\n                amatch = 1;\n            else if (e != ZE_MISS)\n                break;\n        }\n    } while (FNEXT(&dir) == 0);\n\n  ohforgetit:\n    if (subwild)\n        *--subwild = PATH_END;\n    if (newwhole)\n        free(newwhole);\n    if (e == ZE_MISS && amatch)\n        e = ZE_OK;\n    return e;\n}\n\nint wild(w)\nchar *w;                /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\n    char *p;            /* path */\n    char *q;            /* diskless path */\n    int e;              /* result */\n\n    if (volume_label == 1) {\n      volume_label = 2;\n      label = getVolumeLabel((w != NULL && w[1] == ':') ? to_up(w[0]) : '\\0',\n                             &label_time, &label_mode, &label_utim);\n      if (label != NULL)\n        (void)newname(label, 0, 0);\n      if (w == NULL || (w[1] == ':' && w[2] == '\\0')) return ZE_OK;\n      /* \"zip -$ foo a:\" can be used to force drive name */\n    }\n    /* special handling of stdin request */\n    if (strcmp(w, \"-\") == 0)   /* if compressing stdin */\n        return newname(w, 0, 0);\n\n    /* Allocate and copy pattern, leaving room to add \".\" if needed */\n    if ((p = malloc(strlen(w) + 2)) == NULL)\n        return ZE_MEM;\n    strcpy(p, w);\n\n    /* Normalize path delimiter as '/' */\n    for (q = p; *q; q++)                  /* use / consistently */\n        if (*q == '\\\\')\n            *q = '/';\n\n    /* Separate the disk part of the path */\n    q = strchr(p, ':');\n    if (q != NULL) {\n        if (strchr(++q, ':'))     /* sanity check for safety of wild_recurse */\n            return ZE_MISS;\n    } else\n        q = p;\n\n    /* Normalize bare disk names */\n    if (q > p && !*q)\n        strcpy(q, \".\");\n\n    /* Here we go */\n    e = wild_recurse(p, q);\n    free((zvoid *)p);\n    return e;\n}\n\nlocal int procname_dos(n, caseflag, attribs)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\nunsigned attribs;       /* file attributes, if available */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  ff_dir *d;            /* control structure for FFIRST/FNEXT */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  int ff_status;        /* return value of FFIRST/FNEXT */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */\n    return ZE_OK;\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (*n == '\\0') return ZE_MISS;\n  else if (attribs != MSDOS_INVALID_ATTR)\n  {\n    /* Avoid calling stat() for performance reasons when it is already known\n       (from a previous directory scan) that the passed name corresponds to\n       a \"real existing\" file.  The only information needed further down in\n       this function is the distinction between directory entries and other\n       (typically normal file) entries.  This distinction can be derived from\n       the file's attributes that the directory lookup has already provided\n       \"for free\".\n     */\n    s.st_mode = ((attribs & MSDOS_DIR_ATTR) ? S_IFDIR : S_IFREG);\n  }\n  else if (LSSTAT(n, &s)\n#ifdef __TURBOC__\n           /* For this compiler, stat() succeeds on wild card names! */\n           || isshexp(n)\n#endif\n          )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    if (caseflag) {\n      p = malloc(strlen(n) + 1);\n      if (p != NULL)\n        strcpy(p, n);\n    } else\n      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (z->mark) z->dosflag = 1;    /* force DOS attribs for incl. names */\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; p++)          /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0 || strcmp(n, \"/.\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse)\n    {\n      if ((d = malloc(sizeof(ff_dir))) == NULL ||\n          (m = initDirSearch(n, d)) == ZE_MEM)\n      {\n        if (d != NULL)\n          free((zvoid *)d);\n        free((zvoid *)p);\n        return ZE_MEM;\n      }\n      for (e = d->ff_name, ff_status = m;\n           ff_status == 0;\n           ff_status = FNEXT(d))\n      {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            free((zvoid *)d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname_dos(a, caseflag, getDirEntryAttr(d)))\n              != ZE_OK)         /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      free((zvoid *)d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n{\n  return procname_dos(n, caseflag, MSDOS_INVALID_ATTR);\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  dosflag = 1;\n\n  /* Find starting point in name before doing malloc */\n  /* Strip drive specification */\n  t = *x && *(x + 1) == ':' ? x + 2 : x;\n  /* Strip \"//host/share/\" part of a UNC name */\n  if ((!strncmp(x,\"//\",2) || !strncmp(x,\"\\\\\\\\\",2)) &&\n      (x[2] != '\\0' && x[2] != '/' && x[2] != '\\\\')) {\n    n = x + 2;\n    while (*n != '\\0' && *n != '/' && *n != '\\\\')\n      n++;              /* strip host name */\n    if (*n != '\\0') {\n      n++;\n      while (*n != '\\0' && *n != '/' && *n != '\\\\')\n        n++;            /* strip `share' name */\n    }\n    if (*n != '\\0')\n      t = n + 1;\n  }\n  /* Strip leading \"/\" to convert an absolute path into a relative path */\n  while (*t == '/' || *t == '\\\\')\n    t++;\n  /* Skip leading \"./\" as well */\n  while (*t == '.' && (t[1] == '/' || t[1] == '\\\\'))\n    t += 2;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (n = t; *n; n++)\n    if (*n == '\\\\')\n      *n = '/';\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (isdir == 42) return n;      /* avoid warning on unused variable */\n\n  if (dosify)\n    msname(n);\n  else\n#if defined(__DJGPP__) && __DJGPP__ >= 2\n    if (_USE_LFN == 0)\n#endif\n      strlwr(n);\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n  strcpy(x, n);\n\n  return x;\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n#if defined(__TURBOC__) || defined(__GO32__)\n  int h;                /* file handle */\n\n  if ((h = open(f, 0)) != -1)\n  {\n    setftime(h, (struct ftime *)(void *)&d);\n    close(h);\n  }\n#else /* !__TURBOC__ && !__GO32__ */\n  ztimbuf u;            /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u.actime and u.modtime */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, &u);\n#endif /* ?(__TURBOC__ || __GO32__) */\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n  int isstdin = !strcmp(f, \"-\");\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (isstdin) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n    time((time_t *)&s.st_mtime);       /* some fstat()s return time zero */\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));\n#if (S_IFREG != 0x8000)\n    /* kludge to work around non-standard S_IFREG flag used in DJGPP V2.x */\n    if ((s.st_mode & S_IFMT) == S_IFREG) *a |= 0x80000000L;\n#endif\n  }\n  free(name);\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime((time_t *)&s.st_mtime);\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n */\n{\n    return rmdir(d);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n#ifdef USE_EF_UT_TIME\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */\n#endif\n\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n\n  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));\n  z->cextra = z->extra;\n\n  return ZE_OK;\n#else /* !USE_EF_UT_TIME */\n  return (int)(z-z);\n#endif /* ?USE_EF_UT_TIME */\n}\n\n\n#ifdef MY_ZCALLOC       /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */\n\n#if defined(__TURBOC__) && !defined(OS2)\n/* Small and medium model are for now limited to near allocation with\n * reduced MAX_WBITS and MAX_MEM_LEVEL\n */\n\n/* Turbo C malloc() does not allow dynamic allocation of 64K bytes\n * and farmalloc(64K) returns a pointer with an offset of 8, so we\n * must fix the pointer. Warning: the pointer must be put back to its\n * original form in order to free it, use zcfree().\n */\n\n#define MAX_PTR 10\n/* 10*64K = 640K */\n\nlocal int next_ptr = 0;\n\ntypedef struct ptr_table_s {\n    zvoid far *org_ptr;\n    zvoid far *new_ptr;\n} ptr_table;\n\nlocal ptr_table table[MAX_PTR];\n/* This table is used to remember the original form of pointers\n * to large buffers (64K). Such pointers are normalized with a zero offset.\n * Since MSDOS is not a preemptive multitasking OS, this table is not\n * protected from concurrent access. This hack doesn't work anyway on\n * a protected system like OS/2. Use Microsoft C instead.\n */\n\nzvoid far *zcalloc (unsigned items, unsigned size)\n{\n    zvoid far *buf;\n    ulg bsize = (ulg)items*size;\n\n    if (bsize < (65536L-16L)) {\n        buf = farmalloc(bsize);\n        if (*(ush*)&buf != 0) return buf;\n    } else {\n        buf = farmalloc(bsize + 16L);\n    }\n    if (buf == NULL || next_ptr >= MAX_PTR) return NULL;\n    table[next_ptr].org_ptr = buf;\n\n    /* Normalize the pointer to seg:0 */\n    *((ush*)&buf+1) += ((ush)((uch*)buf-NULL) + 15) >> 4;\n    *(ush*)&buf = 0;\n    table[next_ptr++].new_ptr = buf;\n    return buf;\n}\n\nzvoid zcfree (zvoid far *ptr)\n{\n    int n;\n    if (*(ush*)&ptr != 0) { /* object < 64K */\n        farfree(ptr);\n        return;\n    }\n    /* Find the original pointer */\n    for (n = next_ptr - 1; n >= 0; n--) {\n        if (ptr != table[n].new_ptr) continue;\n\n        farfree(table[n].org_ptr);\n        while (++n < next_ptr) {\n            table[n-1] = table[n];\n        }\n        next_ptr--;\n        return;\n    }\n    ziperr(ZE_MEM, \"zcfree: ptr not found\");\n}\n#endif /* __TURBOC__ */\n\n#if defined(MSC) || defined(__WATCOMC__)\n#if (!defined(_MSC_VER) || (_MSC_VER < 700))\n#  define _halloc  halloc\n#  define _hfree   hfree\n#endif\n\nzvoid far *zcalloc (unsigned items, unsigned size)\n{\n    return (zvoid far *)_halloc((long)items, size);\n}\n\nzvoid zcfree (zvoid far *ptr)\n{\n    _hfree((void huge *)ptr);\n}\n#endif /* MSC || __WATCOMC__ */\n\n#endif /* MY_ZCALLOC */\n\n#if (defined(__WATCOMC__) && defined(ASMV) && !defined(__386__))\n/* This is a hack to connect \"call _exit\" in match.asm to exit() */\n#pragma aux xit \"_exit\" parm caller []\nvoid xit(void)\n{\n    exit(20);\n}\n#endif\n\nlocal int is_running_on_windows(void)\n{\n    char * var = getenv(\"OS\");\n\n    /* if the OS env.var says 'Windows_NT' then */\n    /* we're likely running on a variant of WinNT */\n\n    if ((NULL != var) && (0 == strcmp(\"Windows_NT\", var)))\n    {\n        return 1;\n    }\n\n    /* if the windir env.var is non-null then */\n    /* we're likely running on a variant of Win9x */\n    /* DOS mode of Win9x doesn't define windir, only winbootdir */\n    /* NT's command.com can't see lowercase env. vars */\n\n    var = getenv(\"windir\");\n    if ((NULL != var) && (0 != var[0]))\n    {\n        return 1;\n    }\n\n    return 0;\n}\n\nvoid check_for_windows(char *app)\n{\n    /* Print a warning for users running under Windows */\n    /* to reduce bug reports due to running DOS version */\n    /* under Windows, when Windows version usually works correctly */\n\n    /* This is only called from the DOS version */\n\n    if (is_running_on_windows())\n    {\n        printf(\"\\nzip warning:  You are running MSDOS %s on Windows.\\n\"\n               \"Try the Windows version before reporting any problems.\\n\",\n               app);\n    }\n}\n\n#endif /* !UTIL */\n\n\n#ifndef WINDLL\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nstatic ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s.\\n\\n\";\n                        /* At module level to keep Turbo C++ 1.0 happy !! */\n\nvoid version_local()\n{\n#if defined(__DJGPP__) || defined(__WATCOMC__) || \\\n    (defined(_MSC_VER) && (_MSC_VER != 800))\n    char buf[80];\n#endif\n\n/* Define the compiler name and version strings */\n#if defined(__GNUC__)\n#  if defined(__DJGPP__)\n    sprintf(buf, \"djgpp v%d.%02d / gcc \", __DJGPP__, __DJGPP_MINOR__);\n#    define COMPILER_NAME1      buf\n#  elif defined(__GO32__)         /* __GO32__ is defined as \"1\" only (sigh) */\n#    define COMPILER_NAME1      \"djgpp v1.x / gcc \"\n#  elif defined(__EMX__)          /* ...so is __EMX__ (double sigh) */\n#    define COMPILER_NAME1      \"emx+gcc \"\n#  else\n#    define COMPILER_NAME1      \"gcc \"\n#  endif\n#  define COMPILER_NAME2        __VERSION__\n#elif defined(__WATCOMC__)\n#  if (__WATCOMC__ % 10 > 0)\n/* We do this silly test because __WATCOMC__ gives two digits for the  */\n/* minor version, but Watcom packaging prefers to show only one digit. */\n    sprintf(buf, \"Watcom C/C++ %d.%02d\", __WATCOMC__ / 100,\n            __WATCOMC__ % 100);\n#  else\n    sprintf(buf, \"Watcom C/C++ %d.%d\", __WATCOMC__ / 100,\n            (__WATCOMC__ % 100) / 10);\n#  endif\n#  define COMPILER_NAME1        buf\n#  define COMPILER_NAME2        \"\"\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n#    define COMPILER_NAME1      \"Borland C++\"\n#    if (__BORLANDC__ < 0x0200)\n#      define COMPILER_NAME2    \" 1.0\"\n#    elif (__BORLANDC__ == 0x0200)   /* James:  __TURBOC__ = 0x0297 */\n#      define COMPILER_NAME2    \" 2.0\"\n#    elif (__BORLANDC__ == 0x0400)\n#      define COMPILER_NAME2    \" 3.0\"\n#    elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */\n#      define COMPILER_NAME2    \" 3.1\"\n#    elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */\n#      define COMPILER_NAME2    \" 4.0 or 4.02\"\n#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */\n#      define COMPILER_NAME2    \" 4.5\"\n#    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */\n#      define COMPILER_NAME2    \" 5.0\"\n#    else\n#      define COMPILER_NAME2    \" later than 5.0\"\n#    endif\n#  else\n#    define COMPILER_NAME1      \"Turbo C\"\n#    if (__TURBOC__ > 0x0401)\n#      define COMPILER_NAME2    \"++ later than 3.0\"\n#    elif (__TURBOC__ == 0x0401)     /* Kevin:  3.0 -> 0x0401 */\n#      define COMPILER_NAME2    \"++ 3.0\"\n#    elif (__TURBOC__ == 0x0296)     /* [662] checked by SPC */\n#      define COMPILER_NAME2    \"++ 1.01\"\n#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */\n#      define COMPILER_NAME2    \"++ 1.0\"\n#    elif (__TURBOC__ == 0x0201)     /* Brian:  2.01 -> 0x0201 */\n#      define COMPILER_NAME2    \" 2.01\"\n#    elif ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200)) /* James: 0x0200 */\n#      define COMPILER_NAME2    \" 2.0\"\n#    elif (__TURBOC__ > 0x0100)\n#      define COMPILER_NAME2    \" 1.5\"          /* James:  0x0105? */\n#    else\n#      define COMPILER_NAME2    \" 1.0\"          /* James:  0x0100 */\n#    endif\n#  endif\n#elif defined(MSC)\n#  if defined(_QC) && !defined(_MSC_VER)\n#    define COMPILER_NAME1      \"Microsoft Quick C\"\n#    define COMPILER_NAME2      \"\"      /* _QC is defined as 1 */\n#  else\n#    define COMPILER_NAME1      \"Microsoft C \"\n#    ifdef _MSC_VER\n#      if (_MSC_VER == 800)\n#        define COMPILER_NAME2  \"8.0/8.0c (Visual C++ 1.0/1.5)\"\n#      else\n#        define COMPILER_NAME2 \\\n           (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf)\n#      endif\n#    else\n#      define COMPILER_NAME2    \"5.1 or earlier\"\n#    endif\n#  endif\n#else\n#    define COMPILER_NAME1      \"unknown compiler\"\n#    define COMPILER_NAME2      \"\"\n#endif\n\n/* Define the OS name and memory environment strings */\n#if defined(__WATCOMC__) || defined(__TURBOC__) || defined(MSC) || \\\n    defined(__GNUC__)\n#  define OS_NAME1      \"\\nMS-DOS\"\n#else\n#  define OS_NAME1      \"MS-DOS\"\n#endif\n\n#if (defined(__GNUC__) || (defined(__WATCOMC__) && defined(__386__)))\n#  define OS_NAME2      \" (32-bit)\"\n#elif defined(M_I86HM) || defined(__HUGE__)\n#  define OS_NAME2      \" (16-bit, huge)\"\n#elif defined(M_I86LM) || defined(__LARGE__)\n#  define OS_NAME2      \" (16-bit, large)\"\n#elif defined(M_I86MM) || defined(__MEDIUM__)\n#  define OS_NAME2      \" (16-bit, medium)\"\n#elif defined(M_I86CM) || defined(__COMPACT__)\n#  define OS_NAME2      \" (16-bit, compact)\"\n#elif defined(M_I86SM) || defined(__SMALL__)\n#  define OS_NAME2      \" (16-bit, small)\"\n#elif defined(M_I86TM) || defined(__TINY__)\n#  define OS_NAME2      \" (16-bit, tiny)\"\n#else\n#  define OS_NAME2      \" (16-bit)\"\n#endif\n\n/* Define the compile date string */\n#ifdef __DATE__\n#  define COMPILE_DATE \" on \" __DATE__\n#else\n#  define COMPILE_DATE \"\"\n#endif\n\n    printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2,\n           OS_NAME1, OS_NAME2, COMPILE_DATE);\n\n} /* end function version_local() */\n#endif /* !WINDLL */\n\n\n#if 0 /* inserted here for future use (clearing of archive bits) */\n#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))\n\n#include <errno.h>\nint volatile _doserrno;\n\nunsigned _dos_setfileattr(char *name, unsigned attr)\n{\n#if 0   /* stripping of trailing '/' is not needed for zip-internal use */\n    unsigned namlen = strlen(name);\n    char *i_name = alloca(namlen + 1);\n\n    strcpy(i_name, name);\n    if (namlen > 1 && i_name[namlen-1] == '/' && i_name[namlen-2] != ':')\n        i_name[namlen-1] = '\\0';\n    asm(\"movl %0, %%edx\": : \"g\" (i_name));\n#else\n    asm(\"movl %0, %%edx\": : \"g\" (name));\n#endif\n    asm(\"movl %0, %%ecx\": : \"g\" (attr));\n    asm(\"movl $0x4301, %eax\");\n    asm(\"int $0x21\": : : \"%eax\", \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\");\n    _doserrno = 0;\n    asm(\"jnc 1f\");\n    asm(\"movl %%eax, %0\": \"=m\" (_doserrno));\n    switch (_doserrno) {\n    case 2:\n    case 3:\n           errno = ENOENT;\n           break;\n    case 5:\n           errno = EACCES;\n           break;\n    }\n    asm(\"1:\");\n    return (unsigned)_doserrno;\n}\n\n#endif /* DJGPP v1.x */\n#endif /* never (not yet used) */\n\n\n#if (defined(__DJGPP__) && (__DJGPP__ >= 2))\n\n/* Disable determination of \"x\" bit in st_mode field for [f]stat() calls. */\nint _is_executable (const char *path, int fhandle, const char *ext)\n{\n    return 0;\n}\n\n/* Prevent globbing of filenames.  This gives the same functionality as\n * \"stubedit <program> globbing=no\" did with DJGPP v1.\n */\n#ifndef USE_DJGPP_GLOB\nchar **__crt0_glob_function(char *_arg)\n{\n    return NULL;\n}\n#endif\n\n/* Reduce the size of the executable and remove the functionality to read\n * the program's environment from whatever $DJGPP points to.\n */\n#if !defined(USE_DJGPP_ENV) || defined(UTIL)\nvoid __crt0_load_environment_file(char *_app_name)\n{\n}\n#endif\n\n#endif /* __DJGPP__ >= 2 */\n\n\n#if defined(_MSC_VER) && _MSC_VER == 700\n\n/*\n * ARGH.  MSC 7.0 libraries think times are based on 1899 Dec 31 00:00, not\n *  1970 Jan 1 00:00.  So we have to diddle time_t's appropriately:  add\n *  70 years' worth of seconds for localtime() wrapper function;\n *  (70*365 regular days + 17 leap days + 1 1899 day) * 86400 ==\n *  (25550 + 17 + 1) * 86400 == 2209075200 seconds.\n *  Let time() and stat() return seconds since 1970 by using our own\n *  _dtoxtime() which is the routine that is called by these two functions.\n */\n\n\n#ifdef UTIL\n#  include <time.h>\n#endif\n\n#ifndef UTIL\n#undef localtime\nstruct tm *localtime(const time_t *);\n\nstruct tm *msc7_localtime(const time_t *clock)\n{\n   time_t t = *clock;\n\n   t += 2209075200L;\n   return localtime(&t);\n}\n#endif /* !UTIL */\n\n\nvoid __tzset(void);\nint _isindst(struct tm *);\n\nextern int _days[];\n\n/* Nonzero if `y' is a leap year, else zero. */\n#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n\n/* Number of leap years from 1970 to `y' (not including `y' itself). */\n#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)\n\ntime_t _dtoxtime(year, month, mday, hour, min, sec)\nint year, month, mday, year, hour, min, sec;\n{\n   struct tm tm;\n   time_t t;\n   int days;\n\n   days = _days[month - 1] + mday;\n   year += 1980;\n   if (leap(year) && month > 2)\n     ++days;\n   tm.tm_yday = days;\n   tm.tm_mon = month - 1;\n   tm.tm_year = year - 1900;\n   tm.tm_hour = hour;\n   __tzset();\n   days += 365 * (year - 1970) + nleap (year);\n   t = 86400L * days + 3600L * hour + 60 * min + sec + _timezone;\n   if (_daylight && _isindst(&tm))\n      t -= 3600;\n   return t;\n}\n\n#endif /* _MSC_VER && _MSC_VER == 700 */\n\n\n#ifdef __WATCOMC__\n\n/* This papers over a bug in Watcom 10.6's standard library... sigh */\n/* Apparently it applies to both the DOS and Win32 stat()s.         */\n\nint stat_bandaid(const char *path, struct stat *buf)\n{\n  char newname[4];\n  if (!stat(path, buf))\n    return 0;\n  else if (!strcmp(path, \".\") || (path[0] && !strcmp(path + 1, \":.\"))) {\n    strcpy(newname, path);\n    newname[strlen(path) - 1] = '\\\\';   /* stat(\".\") fails for root! */\n    return stat(newname, buf);\n  } else\n    return -1;\n}\n\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* The symbol DOS is used throughout the Zip source to identify code portions\n * specific to the MSDOS port.\n * Just to make sure, we check that it is set.\n * (Currently, this should should not be neccessary, since currently it has\n * to be set on the compiler command line to get this file read in.)\n */\n#ifndef DOS\n#  define DOS\n#endif\n\n/* The symbol MSDOS is consistently used in the generic source files\n * to identify code to support for MSDOS (and MSDOS related) stuff.\n * e.g: FAT or (FAT like) file systems,\n *      '\\\\' as directory separator in paths,\n *      \"\\r\\n\" as record (line) terminator in text files, ...\n *\n * IMPORTANT Note:\n *  This symbol is not unique for the MSDOS port !!!!!!\n *  It is also defined by ports to some other OS which are (to some extend)\n *  considered DOS compatible.\n *  Examples are: OS/2 (OS2), Windows NT and Windows 95 (WIN32).\n *\n */\n#ifndef MSDOS\n#  define MSDOS\n#endif\n\n/* Power C is similar to Turbo C */\n#ifdef __POWERC\n#  define __TURBOC__\n#endif /* __POWERC */\n\n/* Automatic setting of the common Microsoft C idenfifier MSC.\n * NOTE: Watcom also defines M_I*86 !\n */\n#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))\n#  ifndef MSC\n#    define MSC                 /* This should work for older MSC, too!  */\n#  endif\n#endif\n\n#if !defined(__GO32__) && !defined(__EMX__)\n#  define NO_UNISTD_H\n#endif\n\n#if defined(__WATCOMC__) && defined(__386__)\n#  define WATCOMC_386\n#endif\n\n#ifdef WINDLL\n#  define MSWIN\n#  define MEMORY16\n#endif\n\n\n#if !defined(__EMX__) && !defined(__GO32__) && !defined(WATCOMC_386)\n#if !defined(WINDLL)\n#  define MSDOS16 /* 16 bit MSDOS only */\n#  define MEMORY16\n#endif\n#endif\n\n#if !defined(NO_ASM) && !defined(ASMV)\n#  define ASMV\n#endif\n\n/* enable creation of UTC time fields unless explicitely suppressed */\n#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)\n#  define USE_EF_UT_TIME\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#ifdef MEMORY16\n#  ifndef NO_ASM\n#    define ASM_CRC 1\n#  endif /* ?NO_ASM */\n#  ifdef __TURBOC__\n#    include <alloc.h>\n#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#      if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)\n        error: No dynamic CRC table allocation with Borland C far data models.\n#      endif /* DYNAMIC_CRC_TABLE */\n#    endif /* Turbo/Borland C far data memory models */\n#    define nearmalloc malloc\n#    define nearfree   free\n#    define DYN_ALLOC\n#  else /* !__TURBOC__ */\n#    include <malloc.h>\n#    define nearmalloc _nmalloc\n#    define nearfree   _nfree\n#    define farmalloc  _fmalloc\n#    define farfree    _ffree\n#  endif /* ?__TURBOC__ */\n#  define MY_ZCALLOC 1\n#  ifdef SMALL_MEM\n#    define CBSZ 2048\n#    define ZBSZ 2048\n#  endif\n#  ifdef MEDIUM_MEM\n#    define CBSZ 4096\n#    define ZBSZ 4096\n#  endif\n#  ifndef CBSZ\n#    define CBSZ 8192\n#    define ZBSZ 8192\n#  endif\n#endif /* MEMORY16 */\n\n\n/* Symbolic links are not supported, but some compilers may define S_IFLNK. */\n#ifndef NO_SYMLINKS\n# define NO_SYMLINKS\n#endif\n\n#ifdef MATCH\n#  undef MATCH\n#endif\n#define MATCH dosmatch          /* use DOS style wildcard matching */\n\n#define USE_CASE_MAP\n\n#define ROUNDED_TIME(time)  (((time) + 1) & (~1))\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"wb\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <io.h>\n\n#ifdef ZCRYPT_INTERNAL\n#  ifdef WINDLL\n#    define ZCR_SEED2     (unsigned)3141592654L /* use PI as seed pattern */\n#  else\n#    ifndef __GO32__\n#      include <process.h>      /* getpid() declaration for srand seed */\n#    endif\n#  endif\n#endif\n\n/*\n * djgpp 1.x did not declare these\n */\n#if defined(__GO32__) && !defined(__DJGPP__)\nchar *strlwr(char *);\nint setmode(int, int);\n#endif\n\n#ifdef __WATCOMC__\n#  define NO_MKTEMP\n#  define HAS_OPENDIR\n#  define SSTAT stat_bandaid\n   int stat_bandaid(const char *path, struct stat *buf);\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#  ifdef __386__\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] modify []\n#      pragma aux longest_match \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  else /* !__386__ */\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] loadds modify [ax bx]\n#      pragma aux longest_match \"_*\" parm caller [] loadds value [ax] \\\n                                      modify [ax bx cx dx es]\n#    endif /* ASMV */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [ax dx] \\\n                                      modify [ax bx cx dx es]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [ax] \\\n                                      modify [ax bx cx dx]\n#    endif /* !USE_ZLIB */\n#  endif /* ?__386__ */\n#endif /* __WATCOMC__ */\n\n/*\n * Wrapper function to get around the MSC7 00:00:00 31 Dec 1899 time base,\n * see msdos.c for more info\n */\n\n#if defined(_MSC_VER) && _MSC_VER == 700\n#  define localtime(t) msc7_localtime(t)\n#endif\n\n#ifdef __TURBOC__\n#  ifdef __FILEIO_C\n#    include <dir.h>    /* supplies mktemp() prototype */\n#  endif\n#endif\n\n#if (defined(__TURBOC__) && !defined(__BORLANDC__) && __TURBOC__ <= 0x0201)\n#  ifndef NO_MKTIME\n#    define NO_MKTIME           /* TC 2.01 and earlier do not supply mktime() */\n#  endif\n#endif\n\nvoid check_for_windows(char *app);\n"
  },
  {
    "path": "deps/infozip/zip30/msdos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow         (O_RDONLY|O_BINARY)\n#define fbad         (-1)\ntypedef int          ftype;\n#define zopen(n,p)   open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f)    close(f)\n#define zerr(f)      (k == (extent)(-1L))\n#define zstdin       0\n"
  },
  {
    "path": "deps/infozip/zip30/novell/MAKEINIT",
    "content": "#\n#   makeinit file for makefiles created with QMK386\n#\n#   Novell's NetWare SDK - Release 15\n#\n#   Directories for both the WATCOM and NOVELL tools\n#\nwat386loc = e:\\watcom\\\nnlm386loc = c:\\novell\\ndk\\nwsdk\\\nnlm386hdr = $(nlm386loc)INCLUDE\\NLM;$(nlm386loc)INCLUDE;.\nnlm386imp = $(nlm386loc)IMPORTS\nnlm386lib = $(wat386loc)LIB386;$(wat386loc)LIB386\\NETWARE\n#\n#   Define this macro with your copyright statement\n#\n#copyright = (C) Copyright 199x NONAME, INC.  All Rights Reserved\n#\n#   Macros that point to various tools we'll need to compile\n#\nwcc386r = WCC386                            # location of 386 real mode compiler\nwcc386p = WCC386P                           # protected compiler (last avail on Watcom v9.5\nwcc386 = $(wcc386r)                         # version we want to use\n \nlinkr = WLINK                               # location of real mode linker\nlinkp = WLINKP                              # protected linker (last avail on Watcom v9.5\nlinker = $(linkr)                           # version we want to use\nnlmlinkr = $(nlm386loc)TOOLS\\NLMLINKR       # location of real mode Novell linker\nnlmlinkp = $(nlm386loc)TOOLS\\NLMLINKX       # location of protected Novell linker\nnlmlinker = $(nlmlinkr)                     # version we want to use\n \nnlmpackr = $(nlm386loc)TOOLS\\NLMPACK        # location of real mode NLM compression utility\nnlmpackp = $(nlm386loc)TOOLS\\NLMPACKP       # location of protected NLM compression utility\nnlmpack = $(nlmpackr)                       # location of NLM compression utility\n \ninc_386 = $(nlm386hdr)\nlib_386 = $(nlm386lib)\ncode_386 = $(wat386loc)BIN\\386WCGL.EXE      # code generator (last avail on Watcom v9.01\nlibrarian = $(wat386loc)BINB\\WLIB           # location of librarian\n#\n#   NLM Import Files\n#\nstartup = $(nlm386imp)\\PRELUDE.OBJ          # other option is nwpre.obj\nallimp = $(nlm386imp)\\ALL.IMP               # import to include all imports\nclibimp = $(nlm386imp)\\CLIB.IMP             # the clib import file\ntliimp = $(nlm386imp)\\TLI.IMP               # the tli import file\naioimp = $(nlm386imp)\\AIO.IMP               # the aio import file\nsocklibimp = $(nlm386imp)\\SOCKLIB.IMP       # the socket import file\nmathlibimp = $(nlm386imp)\\MATHLIB.IMP       # the math library import file\ndsapiimp = $(nlm386imp)\\DSAPI.IMP           # the NDS import file\nnutimp = $(nlm386imp)\\NWSNUT.IMP            # the NWSNUT import file\nappleimp = $(nlm386imp)\\APPLTLK.IMP         # the AppleTalk import file\nnitimp = $(nlm386imp)\\NIT.IMP               # the legacy NLM import file\nnlmlibimp = $(nlm386imp)\\NLMLIB.IMP         # the NLM-specific import file\nrequesterimp = $(nlm386imp)\\REQUESTR.IMP    # the Requester import file\nfpsmimp = $(nlm386imp)\\FPSM.IMP             # floating point support import file\nthreadsimp = $(nlm386imp)\\THREADS.IMP       # the threads import file\ndseventimp = $(nlm386imp)\\DSEVENT.IMP       # DS Events import file\npsrvimp = $(nlm386imp)\\NWPSRV.IMP           # print services import file\npsrv3ximp = $(nlm386imp)\\NWPSRV3X.IMP       # 3.x print services import file\nstreamsimp = $(nlm386imp)\\STREAMS.IMP       # streams import file\nunicodeimp = $(nlm386imp)\\UNICODE.IMP       # unicode import file\nagentimp = $(nlm386imp)\\agent.imp           # SNMP Agent import file\nsmileimp = $(nlm386imp)\\smile.imp           # SMILE (SNMP) import file\n#\n#   Cross-platform Import Files\n#\naudnlm32imp = $(nlm386imp)\\AUDNLM32.IMP     # auditing import file\ncalnlm32imp = $(nlm386imp)\\CALNLM32.IMP     # NWCALLS import file\nclxnlm32imp = $(nlm386imp)\\CLXNLM32.IMP     # NWCLIENT import file\nlocnlm32imp = $(nlm386imp)\\LOCNLM32.IMP     # NWLOCALE import file\nnetnlm32imp = $(nlm386imp)\\NETNLM32.IMP     # NWNET import file\n"
  },
  {
    "path": "deps/infozip/zip30/novell/Netware.c",
    "content": "#include <stdio.h> \n#include <stdlib.h> \n#include <string.h>\n#include <ntypes.h>\n#include <nwconio.h> \n#include <ctype.h>\n#include <unistd.h>\n#include <nit\\nwdir.h>\n#include <dirent.h>\n#include <nwnamspc.h> \n#include <locale.h>\n#include <nwlocale.h>\n#include <time.h>\n\nextern void UseAccurateCaseForPaths(int);\n\n#include \"zip.h\"\n\n   /*------------------------------------------------------------------\n   **   Global Variables\n   */\n\n#define   skipspace( x )  while( isspace( *x ) ) ++x\n#define   nextspace( x )  while( *x && !isspace( *x ) ) ++x\n#define   CWS     0\n#define   CWV     1\n#define   CWP     2\n#define   ALL     99\n\n/* Globals */\nextern      char   *GetWorkArea(void);\nextern      char   *next_arg(char *);\nextern\t\tint NLM_exiting;\nchar        fid[100];\nstatic      breakkey = FALSE;\n\n#define MATCH shmatch\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n#define PAD 0\n#define PATH_END '/'\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nvoid findzip(char *s)\n{\n   dowhereis(s);\n} \n\nvoid dowhereis(char *s)\n{\n   char    dir[_MAX_PATH];\n   char    fsv[_MAX_SERVER+_MAX_VOLUME+1];\n   char    fdir[_MAX_PATH];\n   char    fname[_MAX_FNAME],fext[_MAX_EXT], both[_MAX_FNAME+_MAX_EXT];\n   char    *p = next_arg(s); /* point at argument */\n\n   if(!*p)\n   {\n      printf(\"No filename specified!\");\n      return;\n   }\n\n   //setlocale (LC_ALL, \"NORWAY\");\n   NWLsetlocale (LC_ALL, \"NORWAY\");\n\n   strcpy(dir,GetWorkArea());\n\n   /* get the file name specification */\n   _splitpath(p,fsv,fdir,fname,fext);\n\n   //printf (\"p %s, fsv %s, fdir %s, fname %s, fext %s\\n\", p,fsv,fdir,fname,fext);\n   //getch();\n   \n   sprintf(both,\"%s%s\",strupr(fname),strupr(fext));\n\n   breakkey = FALSE;\n\n   /* startup the recursive file find operation */\n   chdir(fsv);\n   UseAccurateCaseForPaths(1);\n   SetCurrentNameSpace (NW_NS_LONG);\n   chdir(fdir);\n   findit(both);\n}\n\nchar *GetWorkArea(void)\n{\n   static  char   cwd[_MAX_PATH];\n   static  char   serverName[_MAX_SERVER];\n   static  char   volumeName[_MAX_VOLUME + 1];\n   static  char   dirName[_MAX_DIR];\n\n   if(getcwd(cwd,_MAX_PATH) == NULL) \n      return NULL;\n\n   ParsePath(cwd,serverName,volumeName,dirName);   /* shouldn't fail! */\n\n   return cwd;\n}\n\nchar *next_arg(char *s)\n{\n   char    *p;\n\n   skipspace(s);     /* ignore white */\n   p = s;\n   nextspace(s);     /* find next blank */\n   *s = NULL;\n   return(p);\n}\n\nstatic void findit(char *what)\n{\n   char dir[_MAX_PATH];\n   char zipdir[_MAX_PATH];\n   char szzipfile[_MAX_PATH];\n   char *psz;\n   DIR *dirStructPtr;\n   DIR *dirStructPtrSave;\n   int r;\n\n   getcwd(dir,_MAX_PATH);\n\n   psz = dir;\n\n\t  while (*psz)\n\t  {\n\t\t  if (*psz == ':')\n\t\t  {\n\t\t\t  strcpy (zipdir, psz + 1);\n\t\t\t  break;\n\t\t  }\n\t\t  psz++;\n\t  }\n\n   dirStructPtrSave = dirStructPtr = opendir(what);\n\n\t/*\n\t_A_NORMAL Normal file; read/write permitted \n\t_A_RDONLY Read-only file \n\t_A_HIDDEN Hidden file \n\t_A_SYSTEM System file \n\t_A_VOLID Volume ID entry \n\t_A_SUBDIR Subdirectory \n\t_A_ARCH Archive file \n\t*/\n\n   if (hidden_files)\n\t  SetReaddirAttribute (dirStructPtr, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);\n   else\n\t  SetReaddirAttribute (dirStructPtr, _A_NORMAL | _A_ARCH);\n\n   //while(dirStructPtr && !breakkey)\n   while(dirStructPtr && !NLM_exiting)\n   {\n\t  //printf (\"\\n NLM_exiting test Line 167.... \\n\");\n\t   \n      dirStructPtr = readdir(dirStructPtr);\n      if((dirStructPtr == NULL) || (dirStructPtr == -1))\n         break;\n      \n\t  /* Filen er funnet */\n      if(dirStructPtr->d_attr & _A_SUBDIR)\n\t\tcontinue;\n\n\t  strcpy (szzipfile, zipdir);\n\t  strcat (szzipfile, \"/\");\n\t  strcat (szzipfile, dirStructPtr->d_name);\n\t  procnamehho (szzipfile);\n\n\t  //ThreadSwitchWithDelay();\n\n      //if(kbhit() && getch() == 3) \n        // printf(\"^C\\n\",breakkey = TRUE);\n   }\n\n   if(dirStructPtrSave) \n      closedir(dirStructPtrSave);\n\n   if (!recurse)\n\t   return;\n\n   /*  Now traverse the directories in this path */\n\n   dirStructPtrSave = dirStructPtr = opendir(\"*.*\");\n   if(dirStructPtr == NULL) \n      return;\n\n   if (hidden_files)\n\t\tSetReaddirAttribute (dirStructPtr, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH | _A_SUBDIR);\n\t else\n\t\tSetReaddirAttribute (dirStructPtr, _A_NORMAL | _A_ARCH | _A_SUBDIR);\n\n   //ThreadSwitchWithDelay();\n\n   while(!NLM_exiting)\n   {\n\t  //printf (\"\\n NLM_exiting test Line 204.... \\n\"); getch ();\n\n      dirStructPtr = readdir(dirStructPtr);\n      if((dirStructPtr == NULL) || (dirStructPtr == -1))\n         break;\n      \n      if(dirStructPtr->d_attr & _A_SUBDIR)\n      {\n\t\t strcpy (szzipfile, zipdir);\n\t\t strcat (szzipfile, \"/\");\n\t\t strcat (szzipfile, dirStructPtr->d_name);\n\t  \t procnamehho (szzipfile);\n\n         chdir(dirStructPtr->d_name);\n         findit(what);                \n         chdir(\"..\");\n      }\n\n      //if(kbhit() && getch() == 3) \n        // printf(\"^C\\n\",breakkey = TRUE);\n   }\n\n   if(dirStructPtrSave) \n      closedir(dirStructPtrSave);\n} \n\n\nint wild(w)\nchar *w;                /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\n  DIR *d;               /* stream for reading directory */\n  char *e;              /* name found in directory */\n  int r;                /* temporary variable */\n  char *n;              /* constructed name from directory */\n  int f;                /* true if there was a match */\n  char *a;              /* alloc'ed space for name */\n  //char *p;              /* path */\n  char *q;              /* name */\n  char v[5];            /* space for device current directory */\n\n\n  char    dir[_MAX_PATH];\n  char    fsv[_MAX_SERVER+_MAX_VOLUME+1];\n  char    fdir[_MAX_PATH];\n  char    fname[_MAX_FNAME],fext[_MAX_EXT], both[_MAX_FNAME+_MAX_EXT];\n  char    *p; /* point at argument */\n\n  p = w;\n\n\n  /* Test HHO */\n  findzip(p);\n\n  return ZE_OK;\n\n\n  strcpy(dir,GetWorkArea());\n\n   /* get the file name specification */\n\n   _splitpath(p,fsv,fdir,fname,fext);\n   sprintf(both,\"%s%s\",strupr(fname),strupr(fext));\n\n   /* startup the recursive file find operation */\n\n   chdir(fsv);\n   \n  /* Search that level for matching names */\n  if ((d = opendir(both)) == NULL)\n  {\n    free((zvoid *)a);\n    return ZE_MISS;\n  }\n  \n  f = 0;\n  while ((e = readd(d)) != NULL) {\n    if (strcmp(e, \".\") && strcmp(e, \"..\") && MATCH(q, e))\n    {\n      f = 1;\n      if (strcmp(p, \".\") == 0) {                /* path is . */\n        r = procname(e);                        /* name is name */\n        if (r) {\n           f = 0;\n           break;\n        }\n      } else\n      {\n        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)\n        {\n          free((zvoid *)a);\n          closedir(d);\n          return ZE_MEM;\n        }\n        n = strcpy(n, p);\n        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')\n          strcat(n, \"/\");\n        r = procname(strcat(n, e));             /* name is path/name */\n        free((zvoid *)n);\n        if (r) {\n          f = 0;\n          break;\n        }\n      }\n    }\n  }\n  closedir(d);\n\n  /* Done */\n  free((zvoid *)a);\n  return f ? ZE_OK : ZE_MISS;\n}\n\nint procnamehho (char *n)\n{\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  char *a;\n\n  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */\n    return ZE_OK;\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0);\n  else if (stat(n, &s)\n#if defined(__TURBOC__) || defined(__WATCOMC__)\n           /* For these 2 compilers, stat() succeeds on wild card names! */\n           || isshexp(n)\n#endif\n          )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname))\n      {\n        z->mark = pcount ? filter(z->zname) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; p++)          /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n\n  //printf (\"\\nHHO %s\\n\", n);\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n\t//printf (\"\\nHHO1 %s\\n\", n);\n    /* add or remove name of file */\n\t//printf (\"\\nAdding name %s to list.\\n\", n);\n    if ((m = newname(n, 0)) != ZE_OK)\n      return m;\n  } else {\n    \n\t/* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n     return ZE_MEM;\n    if (strcmp(n, \".\") == 0 || strcmp(n, \"/.\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n    //if (dirnames && (m = newname(p, 1)) != ZE_OK) {\n\t  if ((m = newname(p, 1)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n\t  free ((zvoid *)p);\n    }\n      \n\treturn ZE_OK;\n  }\n  return ZE_OK;\n}\n\nint procname(n)\nchar *n;                /* name to process */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */\n    return ZE_OK;\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0);\n  else if (stat(n, &s)\n#if defined(__TURBOC__) || defined(__WATCOMC__)\n           /* For these 2 compilers, stat() succeeds on wild card names! */\n           || isshexp(n)\n#endif\n          )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname))\n      {\n        z->mark = pcount ? filter(z->zname) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; p++)          /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0 || strcmp(n, \"/.\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *szRelativParameter;\nchar szRelativ[512];\nint\tiRelativOK = FALSE;\nint\tiRelativPakking = FALSE;\n\nint fixRelativpath ()\n{\n\tchar *szp;\n\t\n\tszp = szRelativParameter;\n\n\tif (szRelativParameter[0] == '/' || szRelativParameter[0] == '\\\\')\n\t\tszp++;\n\n\twhile (*szp) {\n\t\tif (*szp == '\\\\')\n\t\t\t*szp = '/';\n\t\tszp++;\n\t}\n\n\tszp = szRelativParameter;\n\tif (szRelativParameter[0] == '/')\n\t\tszp++;\n\n\tstrcpy (szRelativ, szp);\n\n\tif (strlen(szp) == 0) {\n\t\tszRelativ[0] = '\\0';\n\t\treturn FALSE;\n\t}\n\treturn TRUE;\n}\n\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n  char *sztUpper;\n  \n  \n  /* Find starting point in name before doing malloc */\n  t = *x && *(x + 1) == ':' ? x + 2 : x;\n  while (*t == '/' || *t == '\\\\')\n    t++;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (n = t; *n; n++)\n    if (*n == '\\\\')\n      *n = '/';\n\t\n  if (iRelativPakking) {\n\t  //printf (\"\\n LINE 516  *ex2ex Internt navn %s external name %s.\\n\", t, x); getch ();\n\t  if (!iRelativOK) {\n\t\t  if (!fixRelativpath()) {\n\t\t\tiRelativOK = FALSE;\n\t\t\tiRelativPakking = FALSE;\n\t\t  }\n\t\t  else {\n\t\t\tsztUpper = malloc (strlen(t) + 10);\n\t\t\tstrcpy (sztUpper, t);\n\t\t\tNWLstrupr (sztUpper);\n\t\t\tNWLstrupr (szRelativ);\n\t\t\tif (strncmp (sztUpper, szRelativ, strlen(szRelativ)) == 0) {\n\t\t\t\tt = t + strlen(szRelativ);\n\t\t\t\tiRelativPakking = TRUE;\n\t\t\t\tiRelativOK = TRUE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tiRelativOK = FALSE;\n\t\t\t\tiRelativPakking = FALSE;\n\t\t\t}\n\t\t\tfree (sztUpper);\n\t\t  }\n\t  }\n\t  else \n\t  {\n\t\tt = t + strlen(szRelativ);\n\t  }\n  }\n  \n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n\n  //if ( !IsFileNameValid(x) )\n    //ChangeNameForFAT(x);\n\n  //printf (\"\\n *in2ex Internt navn %s external name %s.\\n\", n, x); getch ();\n\n  return x;\n}\n\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  //SetFileTime(f, d);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0)\n      error(\"fstat(stdin)\");\n  }\n  else if (stat(name, &s) != 0) {\n    /* Accept about any file kind including directories\n     * (stored with trailing / with -r option)\n     */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n\t  *a = s.st_attr; // << 16) | !(s.st_mode & S_IWRITE);\n    //*a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    //if ((s.st_mode & S_IFMT) == S_IFDIR) {\n    //*a |= MSDOS_DIR_ATTR;\n    //}\n  }\n  if (n != NULL)\n\t  *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n\t    \n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */\n  }\n  return unix2dostime(&s.st_mtime);\n}\n\n\nulg filetimeHHO(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  char *name;\n  int len = strlen(f), isstdin = !strcmp(f, \"-\");\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetimeHHO\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (isstdin) {\n    /* it is common for some PC based compilers to \n       fail with fstat() on devices or pipes */\n    if (fstat(fileno(stdin), &s) != 0) {\n      s.st_mode = S_IFREG; s.st_size = -1L;\n    }\n    time(&s.st_ctime);\n    s.st_atime = s.st_mtime = s.st_ctime;\n  } else if (stat(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n    //*a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));\n\t//*a = (ulg)s.st_mode;\n\t  *a = s.st_attr;\n  }\n\n  printf (\"\\nDette er en test LINE : 721 \\n\"); getch();\n\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n#ifdef __WATCOMC__\n  /* of course, Watcom always has to make an exception */\n  if (s.st_atime == 312764400)\n    s.st_atime = s.st_mtime;\n  if (s.st_ctime == 312764400)\n    s.st_ctime = s.st_mtime;\n#endif\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  printf (\"\\nDette er en test LINE : 735 \\n\"); getch();\n\n  //return GetFileTime(name);\n  free(name);\n  return t->atime;\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n */\n{\n    return rmdir(d);\n}\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n#ifdef USE_EF_UT_TIME\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n\n  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));\n  z->cextra = z->extra;\n\n  return ZE_OK;\n#else /* !USE_EF_UT_TIME */\n  return (int)(z-z);\n#endif /* ?USE_EF_UT_TIME */\n}\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nstatic ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n                        /* At module level to keep Turbo C++ 1.0 happy !! */\n\nvoid version_local()\n{\n#if defined(__DJGPP__) || defined(__WATCOMC__) || \\\n    (defined(_MSC_VER) && (_MSC_VER != 800))\n    char buf[80];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n#  if defined(__DJGPP__)\n      (sprintf(buf, \"djgpp v%d / gcc \", __DJGPP__), buf),\n#  elif defined(__GO32__)\n      \"djgpp v1.x / gcc \",\n#  elif defined(__EMX__)            /* ...so is __EMX__ (double sigh) */\n      \"emx+gcc \",\n#  else\n      \"gcc \",\n#  endif\n      __VERSION__,\n#elif defined(__WATCOMC__)\n#  if (__WATCOMC__ % 10 > 0)\n/* We do this silly test because __WATCOMC__ gives two digits for the  */\n/* minor version, but Watcom packaging prefers to show only one digit. */\n      (sprintf(buf, \"Watcom C/C++ %d.%02d\", __WATCOMC__ / 100,\n               __WATCOMC__ % 100), buf), \"\",\n#  else\n      (sprintf(buf, \"Watcom C/C++ %d.%d\", __WATCOMC__ / 100,\n               (__WATCOMC__ % 100) / 10), buf), \"\",\n#  endif\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n      \"Borland C++\",\n#    if (__BORLANDC__ < 0x0200)\n        \" 1.0\",\n#    elif (__BORLANDC__ == 0x0200)   /* James:  __TURBOC__ = 0x0297 */\n        \" 2.0\",\n#    elif (__BORLANDC__ == 0x0400)\n        \" 3.0\",\n#    elif (__BORLANDC__ == 0x0410)   /* __BCPLUSPLUS__ = 0x0310 */\n        \" 3.1\",\n#    elif (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */\n        \" 4.0 or 4.02\",\n#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */\n        \" 4.5\",\n#    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */\n        \" 5.0\",\n#    else\n        \" later than 5.0\",\n#    endif\n#  else\n      \"Turbo C\",\n#    if (__TURBOC__ > 0x0401)\n        \"++ later than 3.0\"\n#    elif (__TURBOC__ == 0x0401)     /* Kevin:  3.0 -> 0x0401 */\n        \"++ 3.0\",\n#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */\n        \"++ 1.0\",\n#    elif ((__TURBOC__ >= 0x018d) && (__TURBOC__ <= 0x0200)) /* James: 0x0200 */\n        \" 2.0\",\n#    elif (__TURBOC__ > 0x0100)\n        \" 1.5\",                    /* James:  0x0105? */\n#    else\n        \" 1.0\",                    /* James:  0x0100 */\n#    endif\n#  endif\n#elif defined(MSC)\n      \"Microsoft C \",\n#  ifdef _MSC_VER\n#    if (_MSC_VER == 800)\n        \"(Visual C++ v1.1)\",\n#    elif (_MSC_VER == 850)\n        \"(Windows NT v3.5 SDK)\",\n#    elif (_MSC_VER == 900)\n        \"(Visual C++ v2.0/v2.1)\",\n#    elif (_MSC_VER > 900)\n        (sprintf(buf2, \"(Visual C++ v%d.%d)\", _MSC_VER/100 - 6,\n          _MSC_VER%100/10), buf2),\n#    else\n        (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf),\n#    endif\n#  else\n      \"5.1 or earlier\",\n#  endif\n#else\n      \"unknown compiler\", \"\",\n#endif\n\n      \"MS-DOS\",\n\n#if (defined(__GNUC__) || (defined(__WATCOMC__) && defined(__386__)))\n      \" (32-bit)\",\n#elif defined(M_I86HM) || defined(__HUGE__)\n      \" (16-bit, huge)\",\n#elif defined(M_I86LM) || defined(__LARGE__)\n      \" (16-bit, large)\",\n#elif defined(M_I86MM) || defined(__MEDIUM__)\n      \" (16-bit, medium)\",\n#elif defined(M_I86CM) || defined(__COMPACT__)\n      \" (16-bit, compact)\",\n#elif defined(M_I86SM) || defined(__SMALL__)\n      \" (16-bit, small)\",\n#elif defined(M_I86TM) || defined(__TINY__)\n      \" (16-bit, tiny)\",\n#else\n      \" (16-bit)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n} /* end function version_local() */\n\n\n#ifdef __WATCOMC__\n\n/* This papers over a bug in Watcom 10.6's standard library... sigh */\n/* Apparently it applies to both the DOS and Win32 stat()s.         */\n\nint stat_bandaid(const char *path, struct stat *buf)\n{\n  char newname[4];\n  if (!stat(path, buf))\n    return 0;\n  else if (!strcmp(path, \".\") || (path[0] && !strcmp(path + 1, \":.\"))) {\n    strcpy(newname, path);\n    newname[strlen(path) - 1] = '\\\\';   /* stat(\".\") fails for root! */\n    return stat(newname, buf);\n  } else\n    return -1;\n}\n\n#endif\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/novell/README",
    "content": "Unfinished integration into zip 2.4 of novell port to zip 2.2.\n\nTODO:\n\nToo much novell specific stuff via ifdef into the main sourcecode,\nuse atexit() and setjmp()/longjmp() constructions instead.\n\nIf a function doesn't exist (e.g. isatty), just write a wrapper\nand put it in Netware.c\n"
  },
  {
    "path": "deps/infozip/zip30/novell/m.cmd",
    "content": "wmake\n\ncopy zip.nlm f:\n\nattrib -r -h -s g:\\hho\\*.* /s\ndel g:\\hho\\Attrib\\*.*\ndel g:\\hho\\Attrib\\*.*\nrmdir g:\\hho\\Attrib\n\n"
  },
  {
    "path": "deps/infozip/zip30/novell/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/* The symbol DOS is used throughout the Zip source to identify code portions\n * specific to the MSDOS port.\n * Just to make sure, we check that it is set.\n * (Currently, this should should not be neccessary, since currently it has\n * to be set on the compiler command line to get this file read in.)\n */\n#ifndef DOS\n#  define DOS\n#endif\n\n/* The symbol MSDOS is consistently used in the generic source files\n * to identify code to support for MSDOS (and MSDOS related) stuff.\n * e.g: FAT or (FAT like) file systems,\n *      '\\\\' as directory separator in paths,\n *      \"\\r\\n\" as record (line) terminator in text files, ...\n *\n * IMPORTANT Note:\n *  This symbol is not unique for the MSDOS port !!!!!!\n *  It is also defined by ports to some other OS which are (to some extend)\n *  considered DOS compatible.\n *  Examples are: OS/2 (OS2), Windows NT and Windows 95 (WIN32).\n *\n */\n#ifndef MSDOS\n#  define MSDOS\n#endif\n\n/* Power C is similar to Turbo C */\n#ifdef __POWERC\n#  define __TURBOC__\n#endif /* __POWERC */\n\n/* Automatic setting of the common Microsoft C idenfifier MSC.\n * NOTE: Watcom also defines M_I*86 !\n */\n#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))\n#  ifndef MSC\n#    define MSC                 /* This should work for older MSC, too!  */\n#  endif\n#endif\n\n#if !defined(__GO32__) && !defined(__EMX__)\n#  define NO_UNISTD_H\n#endif\n\n#if defined(__WATCOMC__) && defined(__386__)\n#  define WATCOMC_386\n#endif\n\n#ifdef WINDLL\n#  define MSWIN\n#  define MEMORY16\n#endif\n\n\n#if !defined(__EMX__) && !defined(__GO32__) && !defined(WATCOMC_386)\n#if !defined(WINDLL)\n#  define MSDOS16 /* 16 bit MSDOS only */\n#  define MEMORY16\n#endif\n#endif\n\n#if !defined(NO_ASM) && !defined(ASMV)\n#  define ASMV\n#endif\n\n/* enable creation of UTC time fields unless explicitely suppressed */\n#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)\n#  define USE_EF_UT_TIME\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#ifdef MEMORY16\n#  ifndef NO_ASM\n#    define ASM_CRC 1\n#  endif /* ?NO_ASM */\n#  ifdef __TURBOC__\n#    include <alloc.h>\n#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#      if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)\n        error: No dynamic CRC table allocation with Borland C far data models.\n#      endif /* DYNAMIC_CRC_TABLE */\n#    endif /* Turbo/Borland C far data memory models */\n#    define nearmalloc malloc\n#    define nearfree   free\n#    define DYN_ALLOC\n#  else /* !__TURBOC__ */\n#    include <malloc.h>\n#    define nearmalloc _nmalloc\n#    define nearfree   _nfree\n#    define farmalloc  _fmalloc\n#    define farfree    _ffree\n#  endif /* ?__TURBOC__ */\n#  define MY_ZCALLOC 1\n#  ifdef SMALL_MEM\n#    define CBSZ 2048\n#    define ZBSZ 2048\n#  endif\n#  ifdef MEDIUM_MEM\n#    define CBSZ 4096\n#    define ZBSZ 4096\n#  endif\n#  ifndef CBSZ\n#    define CBSZ 8192\n#    define ZBSZ 8192\n#  endif\n#endif /* MEMORY16 */\n\n\n#ifdef MATCH\n#  undef MATCH\n#endif\n#define MATCH dosmatch          /* use DOS style wildcard matching */\n\n#define USE_CASE_MAP\n\n#define ROUNDED_TIME(time)  (((time) + 1) & (~1))\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"wb\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <io.h>\n\n#ifdef ZCRYPT_INTERNAL\n#  ifdef WINDLL\n#    define ZCR_SEED2     (unsigned)3141592654L /* use PI as seed pattern */\n#  else\n#    ifndef __GO32__\n#      include <process.h>      /* getpid() declaration for srand seed */\n#    endif\n#  endif\n#endif\n\n/*\n * djgpp 1.x did not declare these\n */\n#if defined(__GO32__) && !defined(__DJGPP__)\nchar *strlwr(char *);\nint setmode(int, int);\n#endif\n\n#ifdef __WATCOMC__\n#  define NO_MKTEMP\n#  define HAS_OPENDIR\n#  define SSTAT stat_bandaid\n   int stat_bandaid(const char *path, struct stat *buf);\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#  ifdef __386__\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] modify []\n#      pragma aux longest_match \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  else /* !__386__ */\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] loadds modify [ax bx]\n#      pragma aux longest_match \"_*\" parm caller [] loadds value [ax] \\\n                                      modify [ax bx cx dx es]\n#    endif /* ASMV */\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [ax dx] \\\n                                      modify [ax bx cx dx es]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [ax] \\\n                                      modify [ax bx cx dx]\n#    endif /* !USE_ZLIB */\n#  endif /* ?__386__ */\n#endif /* __WATCOMC__ */\n\n/*\n * Wrapper function to get around the MSC7 00:00:00 31 Dec 1899 time base,\n * see msdos.c for more info\n */\n\n#if defined(_MSC_VER) && _MSC_VER == 700\n#  define localtime(t) msc7_localtime(t)\n#endif\n\n#if (defined(__TURBOC__) && !defined(__BORLANDC__) && __TURBOC__ <= 0x0201)\n#  ifndef NO_MKTIME\n#    define NO_MKTIME           /* TC 2.01 and earlier do not supply mktime() */\n#  endif\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/novell/signal.c",
    "content": "#include <nwthread.h>\n#include <nwerrno.h>\n\n/*******************************/\n/*  Interupt handler\t\t   */\n/*******************************/\n\nint NLM_mainThreadGroupID;\nint NLM_threadCnt = 0;\nint NLM_exiting = FALSE;\n\n#pragma off(unreferenced);\nvoid NLM_SignalHandler(int sig)\n#pragma on(unreferenced);\n{\n\tint handlerThreadGroupID;\n\n\tswitch(sig)\n\t{\n\tcase SIGTERM:\n\t\tNLM_exiting = TRUE;\n\t\thandlerThreadGroupID = GetThreadGroupID();\n\t\tSetThreadGroupID(NLM_mainThreadGroupID);\n\n\t\t/* NLM SDK functions may be called here */\n\n\t\twhile (NLM_threadCnt != 0) \n\t\t\tThreadSwitchWithDelay();\n\t\tSetThreadGroupID(handlerThreadGroupID);\n\t\tbreak;\n\tcase SIGINT:\n\t\tsignal(SIGINT, NLM_SignalHandler);\n\t\tbreak;\n\t}\n\treturn;\n}\n\nvoid NLMsignals(void)\n{\n    ++NLM_threadCnt;\n    NLM_mainThreadGroupID = GetThreadGroupID();\n    signal(SIGTERM, NLM_SignalHandler);\n    signal(SIGINT, NLM_SignalHandler);\n}\n\nvoid NLMexit(void)\n{\n   --NLM_threadCnt;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/novell/zip.lnk",
    "content": "Form Novell NLM 'zip'\nName zip\nOp ScreenName 'zip'\nOp ThreadName 'zip__P '\nOp Stack = 8k\nOp Version = 1.00.3\nOp Caseexact\nOp Nod\nFile BITS.OBJ\nFile CRC_i386.OBJ\nFile CRYPT.OBJ\nFile DEFLATE.OBJ\nFile FILEIO.OBJ\nFile GLOBALS.OBJ\nFile MKTIME.OBJ\nFile NETWARE.OBJ\nFile TREES.OBJ\nFile TTYIO.OBJ\nFile UTIL.OBJ\nFile ZIP.OBJ\nFile ZIPFILE.OBJ\nFile ZIPUP.OBJ\nFile c:\\novell\\ndk\\nwsdk\\IMPORTS\\PRELUDE.OBJ\nImport @c:\\novell\\ndk\\nwsdk\\IMPORTS\\ALL.IMP\nModule CLib\n"
  },
  {
    "path": "deps/infozip/zip30/novell/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow         (O_RDONLY|O_BINARY)\n#define fbad         (-1)\ntypedef int          ftype;\n#define zopen(n,p)   open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f)    close(f)\n#define zerr(f)      (k == (extent)(-1L))\n#define zstdin       0\n"
  },
  {
    "path": "deps/infozip/zip30/os2/makefile.os2",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit\n\n# Supported Make utilities:\n# - Microsoft/IBM nmake\n# - dmake 3.8 or higher\n# - GNU make, at least version 3.68\n# - NOT watcom make\n# For Microsoft and Watcom C, better use NMAKE,\n# otherwise it doesn't matter.\n\n# Supported 16-bit C Compilers (created programs run under OS/2 1.x and 2.x):\n# - Microsoft C 6.00A\n# - Watcom C/C++ 16-bit\n\n# Supported 32-bit C Compilers (created programs run under OS/2 2.x only):\n# - GNU gcc (emx kit 0.9c or newer)\n# - IBM C Set/2 or C Set++   - does not yet work with ASM code\n# - Watcom C/C++ 32-bit      - does not yet work with ASM code\n# - Borland C++              - no ASM code yet\n# - MetaWare High C/C++      - no ASM code yet\n\n# Supported Cross-Compilers for MS-DOS:\n# - Microsoft C 6.00A (16-bit)\n# - Watcom C/C++ (16- and 32-bit)\n# - GNU gcc (emx kit 0.9c or newer, 32-bit)\n\n# Supported Cross-Compilers for Win32 (WinNT/Win95):\n# - GNU gcc (emx kit 0.9c or newer, with RSXNT 1.4 or newer)\n\n# Supported Assemblers:\n# - Microsoft MASM 6.00 with Microsoft C, IBM C\n# - Watcom WASM with Watcom C/C++\n# - GNU as with GNU gcc\n\n# To use MASM 5.x instead of MASM 6.00:\n# - set AS=\"masm -T -Ml\"\n# - set ASEOL=\";\"\n\n\n# To use, enter \"make/nmake/dmake -f os2/makefile.os2\"\n# (this makefile depends on its name being \"os2/makefile.os2\").\n\n# Add -DNO_ASM to CFLAGS and define OBJA to `nothing' if you do not have\n# masm or ml.\n# Add -DDYN_ALLOC to ASFLAGS if you have defined it in tailor.h or CFLAGS\n\n# Note: assembly language modules are really only supported for\n# Microsoft 16-bit and GNU gcc 32-bit compilation.\n\n# Notes on 16-bit (Microsoft C 6.00) compilation:\n\n#   The resulting programs can be used under OS/2 protected mode only.\n#   A larger stack has to be used for OS/2 because system calls\n#   use more stack than under DOS, 8k is recommended by Microsoft.\n#   Note that __STDC__ has to be defined explicitly with C 6.00 when -Ze\n#   is given, because Microsoft disables __STDC__ when their extensions\n#   are enabled. This is different from the C 5.10 behaviour.\n\n# Notes on 32-bit OS/2 compilation:\n\n#   The resulting programs can be used under OS/2 protected\n#   mode of OS/2 2.x only, not under 1.x and not under DOS.\n#   It makes no difference if __STDC__ is defined or not.\n#   Borland C++ works with DYN_ALLOC only.\n\n# Special Notes on IBM C/C++ compilation:\n\n#   The older C compiler (C Set/2) breaks, while optimizing, on deflate.c\n#   and trees.c (generates incorrect code). The newer C++ compiler (C Set++)\n#   doesn't but instead breaks on crypt.c in the initial version and up to\n#   CSD level 003. Starting with CSD level 004, it doesn't break any longer.\n\n# Notes on Watcom C/C++ compilation for DOS with the PMODE/W extender:\n#\n#   You need to add the following section to your \\watcom\\binb\\wlsystem.lnk\n#   file and also need to copy pmodew.exe to the same directory:\n#\n#   system begin pmodew\n#       option osname='PMODE/W'\n#       libpath %WATCOM%\\lib386\n#       libpath %WATCOM%\\lib386\\dos\n#       op stub=pmodew.exe\n#       format os2 le\n#   end\n#\n#   PMODE/W 1.16 or higher is required.\n\n\ndefault:\n\t@echo \"Enter $(MAKE) -f os2/makefile.os2 target\"\n\t@echo \"where target is one of:\"\n\t@echo \"   msc mscdos ibm ibmdyn ibmdebug ibmprof metaware borland\"\n\t@echo \"   gcc gccdyn gcczlib gccdebug gccdos gccwin32 gccw32dyn\"\n\t@echo \"   watcom watcom16 watcomdos watcom16dos pmodew\"\n\n# MS C 6.00 for OS/2, 16-bit\nmsc:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"cl -nologo -AL -Ocegit -Gs $(FP)\" \\\n\tCFLAGS=\"-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"-D__LARGE__ -D__286\" \\\n\tLDFLAGS=\"-F 2000 -Lp -Fe\" \\\n\tLDFLAGS2=\"-link /noe /pm:vio\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJA=\"match.obj\" \\\n\tDEF=\"os2\\zip.def\"\n\n# MS C 6.00 for OS/2, 16-bit, debug\nmscdebug:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"cl -nologo -AL -Zi -Od $(FP)\" \\\n\tCFLAGS=\"-W1 -Zep -J -G2 -D__STDC__ -DOS2 -DASM_CRC\" \\\n\tAS=\"ml -nologo -c -Zim -Cp\" \\\n\tASFLAGS=\"-D__LARGE__ -D__286\" \\\n\tLDFLAGS=\"-F 2000 -Lp -Fe\" \\\n\tLDFLAGS2=\"-link /noe /pm:vio\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJA=\"match.obj\" \\\n\tDEF=\"os2\\zip.def\"\n\n# crosscompilation for MS-DOS with MS C 6.00\nmscdos:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"cl -nologo -AL -Ocegit -Gs $(FP)\" \\\n\tCFLAGS=\"-W1 -Zep -J -D__STDC__ -DDOS -DASM_CRC -DDYN_ALLOC\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"-D__LARGE__ -DDYN_ALLOC\" \\\n\tLDFLAGS=\"-F 2000 -Lr -Fe\" \\\n\tLDFLAGS2=\"-link /noe /exe\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i86.obj\" \\\n\tOBJA=\"match.obj\" \\\n\tOBJ2=\"msdos.obj\" OBJU2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/osdep.h\" ZIPUP_H=\"msdos/zipup.h\"\n\n\n# IBM C Set/2, statically linked runtime\nibm:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"icc -Q -O -Gs\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 -DNO_ASM\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDEF=\"os2/zip.def\"\n\n# IBM C Set/2, dynamically linked runtime\nibmdyn:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"icc -Q -O -Gd -Gs\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 -DNO_ASM\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDEF=\"os2/zip.def\"\n\n# IBM C Set/2, debug version\nibmdebug:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"icc -Q -Ti\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 -DNO_ASM -Tm\" \\\n\tAS=\"ml -nologo -c -Zim -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDEF=\"os2/zip.def\"\n\n# IBM C Set/2, profiling version for PROFIT\nibmprof:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"icc -Q -O -Gs -Gh -Ti\" \\\n\tCFLAGS=\"-Sm -Sp1 -DOS2 -DNO_ASM\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-B/ST:0x50000 -Fe\" \\\n\tLDFLAGS2=\"profit.obj\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDEF=\"os2/zip.def\"\n\n# Watcom C/386 9.0 or higher\nwatcom:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"wcl386 -bt=os2v2 -zq -Ox -s\" \\\n\tCFLAGS=\"-Zp1 -DOS2 -DNO_ASM\" \\\n\tAS=\"wasm -zq -bt=os2v2 -3p\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=os2v2 -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/286 9.0 or higher\nwatcom16:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"wcl -bt=os2 -zq -ml -Ox -s\" \\\n\tCFLAGS=\"-Zp1 -DOS2 -DNO_ASM\" \\\n\tAS=\"wasm -zq -bt=os2 -2p -ml\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"/\\\"option newfiles\\\" -k0x3000 -x -l=os2 -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/386 9.0 or higher, crosscompilation for DOS, DOS4GW extender\nwatcomdos:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"wcl386 -bt=dos4g -zq -Ox -s\" \\\n\tCFLAGS=\"-Zp1 -DDOS -DMSDOS -DASM_CRC\" \\\n\tAS=\"wasm -zq -bt=dos4g -3p\" \\\n\tASFLAGS=\"-DWATCOM_DSEG\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=dos4g -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tOBJA=\"match32.obj\" \\\n\tOBJ2=\"msdos.obj\" \\\n\tOBJU2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/386 9.0 or higher, crosscompilation for DOS, PMODE/W extender\npmodew:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"wcl386 -bt=dos4g -zq -Ox -s\" \\\n\tCFLAGS=\"-Zp1 -DDOS -DMSDOS -DASM_CRC\" \\\n\tAS=\"wasm -zq -bt=dos4g -3p\" \\\n\tASFLAGS=\"-DWATCOM_DSEG\" \\\n\tLDFLAGS=\"-k0x50000 -x -l=pmodew -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_i386.obj\" \\\n\tOBJA=\"match32.obj\" \\\n\tOBJ2=\"msdos.obj\" \\\n\tOBJU2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# Watcom C/286 9.0 or higher, crosscompilation for DOS\nwatcom16dos:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"wcl -bt=dos -zq -ml -Ox -s\" \\\n\tCFLAGS=\"-Zp1 -DDOS -DMSDOS -DDYN_ALLOC -DNO_ASM\" \\\n\tAS=\"wasm -zq -bt=dos -2 -ml\" \\\n\tASFLAGS=\"-DDYN_ALLOC\" \\\n\tLDFLAGS=\"-k0x2000 -x -l=dos -Fe=\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-Fo\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tOBJ2=\"msdos.obj\" \\\n\tOBJU2=\"msdos_.obj\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\" \\\n\tDIRSEP=\"\\\\\" \\\n\tAS_DIRSEP=\"\\\\\"\n\n# MetaWare High C/C++ 3.2\nmetaware:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"hc -O2\" \\\n\tCFLAGS=\"-D__32BIT__ -DOS2 -DNO_ASM\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-o \" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-o ./\" \\\n\tOBJ=\".obj\" \\\n\tDEF=\"-Hdef=os2/zip.def\"\n\n# Borland C++\nborland:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"bcc -O\" \\\n\tCFLAGS=\"-w- -DOS2 -DDYN_ALLOC -DNO_ASM\" \\\n\tAS=\"ml -nologo -c -Zm -Cp\" \\\n\tASFLAGS=\"\" \\\n\tLDFLAGS=\"-e\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tOBJA=\"\" \\\n\tDEF=\"-sDos2/zip.def\"\n\n# emx 0.9c, gcc, OMF format, statically linked C runtime and emx\ngcc:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -Zomf -O -Wimplicit\" \\\n\tCFLAGS=\"-DOS2 -DASM_CRC\" \\\n\tAS=\"gcc -Zomf\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zsys -Zstack 320 -s -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_gcc.obj\" \\\n\tOBJA=\"matchgcc.obj\" \\\n\tDEF=\"os2/zip.def\"\n\n# emx 0.9c, gcc, OMF format, dynamically linked C runtime and emx\ngccdyn:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -Zomf -O -Wimplicit\" \\\n\tCFLAGS=\"-DOS2 -DASM_CRC\" \\\n\tAS=\"gcc -Zomf\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-Zcrtdll -Zstack 320 -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"crc_gcc.obj\" \\\n\tOBJA=\"matchgcc.obj\" \\\n\tDEF=\"os2/zip.def\"\n\n# emx 0.9c, gcc, OMF format, statically linked zlib, C runtime, and emx\ngcczlib:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -Zomf -O -Wimplicit\" \\\n\tCFLAGS=\"-DOS2 -DUSE_ZLIB\" \\\n\tAS=\"gcc -Zomf\" \\\n\tASFLAGS=\"-Di386 -DUSE_ZLIB\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-L. -lzlib -Zsys -Zstack 320 -s -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".obj\" \\\n\tCRCA_O=\"\" \\\n\tOBJA=\"\" \\\n\tDEF=\"os2/zip.def\"\n\n# emx 0.9c, gcc, a.out format, with debug info for gdb\ngccdebug:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -g -Wimplicit\" \\\n\tCFLAGS=\"-DOS2 -DASM_CRC\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tDEF=\"os2/zip.def\"\n\n# emx 0.9c, gcc, a.out format, for MS-DOS\ngccdos:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -O -Wimplicit\" \\\n\tCFLAGS=\"-DDOS -DMSDOS -DASM_CRC\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-s -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tOBJ2=\"msdos.o\" \\\n\tOBJU2=\"msdos_.o\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\"\n\n# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32\ngccwin32:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -Zwin32 -O -m486 -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DASM_CRC\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -Zsys -Zsmall-conv -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tOBJ2=\"win32zip.o win32.o nt.o\" \\\n\tOBJU2=\"win32_.o\" \\\n\tOSDEP_H=\"win32/osdep.h\" \\\n\tZIPUP_H=\"win32/zipup.h\" \\\n\tDEF=\"win32/zip.def\"\n\n# emx 0.9c, gcc, RSXNT 1.4, cross-compilation for Win32, use emx C rtl DLL\ngccw32dyn:\n\t$(MAKE) -f os2/makefile.os2 zips \\\n\tCC=\"gcc -Zwin32 -Zcrtdll=crtrsxnt -O -m486 -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DASM_CRC\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tOBJ2=\"win32zip.o win32.o nt.o\" \\\n\tOBJU2=\"win32_.o\" \\\n\tOSDEP_H=\"win32/osdep.h\" \\\n\tZIPUP_H=\"win32/zipup.h\" \\\n\tDEF=\"win32/zip.def\"\n\n# VPATH = .;os2\n\n# variables\n\n#default settings for target dependent macros:\nDIRSEP = /\nAS_DIRSEP = /\n# LOCAL_OPTS =\nCCFLAGS = $(CFLAGS) $(LOCAL_OPTS)\n\nOSDEP_H = os2/osdep.h\nZIPUP_H = os2/os2zip.h os2/zipup.h\nCRCA_O  =\n\n\nOBJZ =  zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \\\n        crc32$(OBJ) $(CRCA_O) globals$(OBJ) \\\n\tdeflate$(OBJ) trees$(OBJ) crypt$(OBJ) ttyio$(OBJ)\nOBJ2 =\tos2zip$(OBJ) os2$(OBJ) os2acl$(OBJ)\n\nOBJU =  zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) globals$(OBJ)\nOBJU2 = os2zip_$(OBJ)\n\nOBJN =  zipnote$(OBJ) $(OBJU) $(OBJU2)\nOBJS =  zipsplit$(OBJ) $(OBJU) $(OBJU2)\nOBJC =  zipcloak$(OBJ) crc32_$(OBJ) crypt_$(OBJ) ttyio$(OBJ) $(OBJU) $(OBJU2)\n\nZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES: .c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c -I. $(CCFLAGS) $<\n\n.asm$(OBJ):\n\t$(AS) $(ASFLAGS) $< $(ASEOL)\n\n# targets\n\nzips:\tzip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip$(OBJ):\tzip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile$(OBJ):\tzipfile.c $(ZIP_H) crc32.h\nzipup$(OBJ):\tzipup.c $(ZIP_H) revision.h crc32.h crypt.h $(ZIPUP_H)\nfileio$(OBJ):\tfileio.c $(ZIP_H) crc32.h\nutil$(OBJ):\tutil.c $(ZIP_H)\nglobals$(OBJ):\tglobals.c $(ZIP_H)\ndeflate$(OBJ):\tdeflate.c $(ZIP_H)\ntrees$(OBJ):\ttrees.c $(ZIP_H)\ncrc32$(OBJ):\tcrc32.c $(ZIP_H) crc32.h\ncrypt$(OBJ):\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(OBJ):\tttyio.c $(ZIP_H) crypt.h ttyio.h\n\nos2zip$(OBJ):\tos2/os2zip.c $(ZIP_H) os2/os2zip.h os2/os2acl.h\n\t$(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2zip.c\n\nos2$(OBJ):\tos2/os2.c $(ZIP_H) os2/os2zip.h\n\t$(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2.c\n\nos2acl$(OBJ):\tos2/os2acl.c os2/os2acl.h\n\t$(CC) -c -I. $(CCFLAGS) os2$(DIRSEP)os2acl.c\n\nmsdos$(OBJ):\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c\n\nwin32zip$(OBJ):\twin32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c\n\nwin32$(OBJ):\twin32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c\n\nnt$(OBJ):\twin32/nt.c win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c\n\ncrc_i86$(OBJ):\tmsdos/crc_i86.asm\t\t\t\t# 16bit only\n\t$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)crc_i86.asm $(ASEOL)\n\ncrc_i386$(OBJ):\twin32/crc_i386.asm\t\t\t\t# 32bit, MASM\n\t$(AS) $(ASFLAGS) win32$(AS_DIRSEP)crc_i386.asm $(ASEOL)\n\ncrc_gcc$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\nmatch$(OBJ):\tmsdos/match.asm\n\t$(AS) $(ASFLAGS) msdos$(AS_DIRSEP)match.asm $(ASEOL)\n\nmatch32$(OBJ):\twin32/match32.asm\n\t$(AS) $(ASFLAGS) win32$(AS_DIRSEP)match32.asm\n\nmatchgcc$(OBJ):\tmatch.S\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzipcloak$(OBJ):\tzipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipnote$(OBJ):\tzipnote.c $(ZIP_H) revision.h\nzipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h\n\nzipfile_$(OBJ):\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c\n\nfileio_$(OBJ):\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c\n\nutil_$(OBJ):\tutil.c $(ZIP_H) os2/os2zip.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c\n\ncrc32_$(OBJ):\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c\n\nos2zip_$(OBJ):\tos2/os2zip.c $(ZIP_H) os2/os2zip.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ os2$(DIRSEP)os2zip.c\n\nmsdos_$(OBJ):\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nwin32_$(OBJ):\twin32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c\n\nzip.exe: $(OBJZ) $(OBJ2) $(OBJA)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJZ) $(OBJ2) $(OBJA) $(LDFLAGS2)\n\nzipcloak.exe: $(OBJC)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJC) $(LDFLAGS2)\n\nzipnote.exe: $(OBJN)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJN) $(LDFLAGS2)\n\nzipsplit.exe: $(OBJS)\n\t$(CC) $(LDFLAGS)$@ $(DEF) $(OBJS) $(LDFLAGS2)\n"
  },
  {
    "path": "deps/infozip/zip30/os2/match32.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2005-Feb-10 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n;\n; match32.asm by Jean-loup Gailly.\n\n; match32.asm, optimized version of longest_match() in deflate.c\n; To be used only with 32 bit flat model. To simplify the code, the option\n; -DDYN_ALLOC is not supported.\n; This file is only optional. If you don't have an assembler, use the\n; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o\n; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is\n; assembled with an equivalent -DWSIZE=<whatever>.\n\n; Caution: this module works for IBM's C/C++ compiler versions 2 and 3\n; and for Watcom's 32-bit C/C++ compiler. Both pass the first (and only)\n; argument for longest_match in the EAX register, not on the stack, with\n; the default calling conventions (_System would use the stack).\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used.\n;\n    IFNDEF USE_ZLIB\n;\n        .386\n\n        name    match\n\nBSS32   segment  dword USE32 public 'BSS'\n        extrn   window       : byte\n        extrn   prev         : word\n        extrn   prev_length  : dword\n        extrn   strstart     : dword\n        extrn   match_start  : dword\n        extrn   max_chain_length : dword\n        extrn   good_match   : dword\n        extrn   nice_match   : dword\nBSS32   ends\n\nCODE32  segment dword USE32 public 'CODE'\n        assume cs:CODE32, ds:FLAT, ss:FLAT\n\n        public  match_init\n        public  longest_match\n\n    ifndef      WSIZE\n        WSIZE         equ 32768         ; keep in sync with zip.h !\n    endif\n        MIN_MATCH     equ 3\n        MAX_MATCH     equ 258\n        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)\n        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)\n\n; initialize or check the variables used in match.asm.\n\nmatch_init proc near\n        ret\nmatch_init endp\n\n; -----------------------------------------------------------------------\n; Set match_start to the longest match starting at the given string and\n; return its length. Matches shorter or equal to prev_length are discarded,\n; in which case the result is equal to prev_length and match_start is\n; garbage.\n; IN assertions: cur_match is the head of the hash chain for the current\n;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n\n; int longest_match(cur_match)\n\nlongest_match proc near\n\n        ; return address                ; esp+16\n        push    ebp                     ; esp+12\n        push    edi                     ; esp+8\n        push    esi                     ; esp+4\n\n        lea     ebx,window\n        add     ebx,2\n        window_off equ dword ptr [esp]\n        push    ebx                     ; esp\n\n;       match        equ esi\n;       scan         equ edi\n;       chain_length equ ebp\n;       best_len     equ ebx\n;       limit        equ edx\n\n        mov     esi,eax                 ; cur_match\n        mov     edx,strstart\n        mov     ebp,max_chain_length    ; chain_length = max_chain_length\n        mov     edi,edx\n        sub     edx,MAX_DIST            ; limit = strstart-MAX_DIST\n        cld                             ; string ops increment esi and edi\n        jae     short limit_ok\n        sub     edx,edx                 ; limit = NIL\nlimit_ok:\n        add     edi,window_off          ; edi = offset(window + strstart + 2)\n        mov     ebx,prev_length         ; best_len = prev_length\n        mov     cx,[edi-2]              ; cx = scan[0..1]\n        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]\n        cmp     ebx,good_match          ; do we have a good match already?\n        jb      do_scan\n        shr     ebp,2                   ; chain_length >>= 2\n        jmp     short do_scan\n\n        align   4                       ; align destination of branch\nlong_loop:\n; at this point, edi == scan+2, esi == cur_match\n        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]\n        mov     cx,[edi-2]              ; cx = scan[0..1]\nshort_loop:\n; at this point, edi == scan+2, esi == cur_match,\n; ax = scan[best_len-1..best_len] and cx = scan[0..1]\n        and     esi,WSIZE-1             ; not needed if WSIZE=32768\n        dec     ebp                     ; --chain_length\n        shl     esi,1                   ; cur_match as word index\n        mov     si,prev[esi]            ; cur_match = prev[cur_match]\n                                        ; top word of esi is still 0\n        jz      the_end\n        cmp     esi,edx                 ; cur_match <= limit ?\n        jbe     short the_end\ndo_scan:\n        cmp     ax,word ptr window[ebx+esi-1]   ; check match at best_len-1\n        jne     short_loop\n        cmp     cx,word ptr window[esi]         ; check min_match_length match\n        jne     short_loop\n\n        add     esi,window_off          ; esi = match\n        mov     ecx,(MAX_MATCH-2)/2     ; scan for at most MAX_MATCH bytes\n        mov     eax,edi                 ; eax = scan+2\n        repe    cmpsw                   ; loop until mismatch\n        je      maxmatch                ; match of length MAX_MATCH?\nmismatch:\n        mov     cl,[edi-2]              ; mismatch on first or second byte?\n        xchg    eax,edi                 ; edi = scan+2, eax = end of scan\n        sub     cl,[esi-2]              ; cl = 0 if first bytes equal\n        sub     eax,edi                 ; eax = len\n        sub     esi,window_off          ; esi = match - (2 + offset(window))\n        sub     esi,eax                 ; esi = cur_match (= match - len)\n        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)\n        adc     eax,0                   ; eax = carry ? len+1 : len\n        cmp     eax,ebx                 ; len > best_len ?\n        jle     long_loop\n        mov     match_start,esi         ; match_start = cur_match\n        mov     ebx,eax                 ; ebx = best_len = len\n    ifdef FULL_SEARCH\n        cmp     eax,MAX_MATCH           ; len >= MAX_MATCH ?\n    else\n        cmp     eax,nice_match          ; len >= nice_match ?\n    endif\n        jl      long_loop\nthe_end:\n        mov     eax,ebx                 ; result = eax = best_len\n        pop     ebx\n        pop     esi\n        pop     edi\n        pop     ebp\n        ret\nmaxmatch:                               ; come here if maximum match\n        cmpsb                           ; increment esi and edi\n        jmp     mismatch                ; force match_length = MAX_LENGTH\n\nlongest_match endp\n\nCODE32  ends\n;\n    ENDIF ; !USE_ZLIB\n;\n        end\n"
  },
  {
    "path": "deps/infozip/zip30/os2/os2.c",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n#if defined(__IBMC__) || defined(MSC)\n#include <direct.h>\n#endif\n\n/* Extra malloc() space in names for cutpath() */\n#define PAD 0\n#define PATH_END '/'\n\n\n#include \"os2zip.h\"\n\n/* Library functions not in (most) header files */\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\n\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint wild(w)\nchar *w;                /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\n  DIR *d;               /* stream for reading directory */\n  char *e;              /* name found in directory */\n  int r;                /* temporary variable */\n  char *n;              /* constructed name from directory */\n  int f;                /* true if there was a match */\n  char *a;              /* alloc'ed space for name */\n  char *p;              /* path */\n  char *q;              /* name */\n  char v[5];            /* space for device current directory */\n\n  if (volume_label == 1) {\n    volume_label = 2;\n    label = getVolumeLabel((w != NULL && w[1] == ':') ? to_up(w[0]) : '\\0',\n                           &label_time, &label_mode, &label_utim);\n    if (label != NULL) {\n       newname(label, 0, 0);\n    }\n    if (w == NULL || (w[1] == ':' && w[2] == '\\0')) return ZE_OK;\n    /* \"zip -$ foo a:\" can be used to force drive name */\n  }\n\n  if (w == NULL)\n    return ZE_OK;\n\n  /* special handling of stdin request */\n  if (strcmp(w, \"-\") == 0)   /* if compressing stdin */\n    return newname(w, 0, 0);\n\n  /* Allocate and copy pattern */\n  if ((p = a = malloc(strlen(w) + 1)) == NULL)\n    return ZE_MEM;\n  strcpy(p, w);\n\n  /* catch special case: treat \"*.*\" as \"*\" for DOS-impaired people */\n  r = strlen(p);\n  if (strcmp(p + r - 3, \"*.*\") == 0)\n    p[r - 2] = '\\0';\n\n  /* Normalize path delimiter as '/'. */\n  for (q = p; *q; q++)                  /* use / consistently */\n    if (*q == '\\\\')\n      *q = '/';\n\n  /* Only name can have special matching characters */\n  if ((q = isshexp(p)) != NULL &&\n      (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))\n  {\n    free((zvoid *)a);\n    return ZE_PARMS;\n  }\n\n  /* Separate path and name into p and q */\n  if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))\n  {\n    *q++ = '\\0';                        /* path/name -> path, name */\n    if (*p == '\\0')                     /* path is just / */\n      p = strcpy(v, \"/.\");\n  }\n  else if ((q = strrchr(p, ':')) != NULL)\n  {                                     /* has device and no or root path */\n    *q++ = '\\0';\n    p = strcat(strcpy(v, p), \":\");      /* copy device as path */\n    if (*q == '/')                      /* -> device:/., name */\n    {\n      strcat(p, \"/\");\n      q++;\n    }\n    strcat(p, \".\");\n  }\n  else if (recurse && (strcmp(p, \".\") == 0 ||  strcmp(p, \"..\") == 0))\n  {                                    /* current or parent directory */\n    /* I can't understand Mark's code so I am adding a hack here to get\n     * \"zip -r foo .\" to work. Allow the dubious \"zip -r foo ..\" but\n     * reject \"zip -rm foo ..\".\n     */\n    if (dispose && strcmp(p, \"..\") == 0)\n       ziperr(ZE_PARMS, \"cannot remove parent directory\");\n    q = \"*\";\n  }\n  else                                  /* no path or device */\n  {\n    q = p;\n    p = strcpy(v, \".\");\n  }\n  if (recurse && *q == '\\0') {\n    q = \"*\";\n  }\n  /* Search that level for matching names */\n  if ((d = opendir(p)) == NULL)\n  {\n    free((zvoid *)a);\n    return ZE_MISS;\n  }\n  if ((r = strlen(p)) > 1 &&\n      (strcmp(p + r - 2, \":.\") == 0 || strcmp(p + r - 2, \"/.\") == 0))\n    *(p + r - 1) = '\\0';\n  f = 0;\n  while ((e = readd(d)) != NULL) {\n    if (strcmp(e, \".\") && strcmp(e, \"..\") && MATCH(q, e, 0))\n    {\n      f = 1;\n      if (strcmp(p, \".\") == 0) {                /* path is . */\n        r = procname(e, 0);                     /* name is name */\n        if (r) {\n           f = 0;\n           break;\n        }\n      } else\n      {\n        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)\n        {\n          free((zvoid *)a);\n          closedir(d);\n          return ZE_MEM;\n        }\n        n = strcpy(n, p);\n        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')\n          strcat(n, \"/\");\n        r = procname(strcat(n, e), 0);          /* name is path/name */\n        free((zvoid *)n);\n        if (r) {\n          f = 0;\n          break;\n        }\n      }\n    }\n  }\n  closedir(d);\n\n  /* Done */\n  free((zvoid *)a);\n  return f ? ZE_OK : ZE_MISS;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (n == NULL)        /* volume_label request in freshen|delete mode ?? */\n    return ZE_OK;\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s)\n#if defined(__TURBOC__) || defined(__WATCOMC__)\n           /* For these 2 compilers, stat() succeeds on wild card names! */\n           || isshexp(n)\n#endif\n          )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; p++)          /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0 || strcmp(n, \"/.\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  dosflag = dosify || IsFileSystemFAT(x) || (x == label);\n  if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)\n  {\n    x = t;\n    dosflag = 0;\n  }\n\n  /* Find starting point in name before doing malloc */\n  /* Strip drive specification */\n  t = *x && *(x + 1) == ':' ? x + 2 : x;\n  /* Strip \"//host/share/\" part of a UNC name */\n  if ((!strncmp(x,\"//\",2) || !strncmp(x,\"\\\\\\\\\",2)) &&\n      (x[2] != '\\0' && x[2] != '/' && x[2] != '\\\\')) {\n    n = x + 2;\n    while (*n != '\\0' && *n != '/' && *n != '\\\\')\n      n++;              /* strip host name */\n    if (*n != '\\0') {\n      n++;\n      while (*n != '\\0' && *n != '/' && *n != '\\\\')\n        n++;            /* strip `share' name */\n    }\n    if (*n != '\\0')\n      t = n + 1;\n  }\n  /* Strip leading \"/\" to convert an absolute path into a relative path */\n  while (*t == '/' || *t == '\\\\')\n    t++;\n  /* Strip leading \"./\" as well as drive letter */\n  while (*t == '.' && (t[1] == '/' || t[1] == '\\\\'))\n    t += 2;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (n = t; *n; n++)\n    if (*n == '\\\\')\n      *n = '/';\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n\n  return x;\n}\n\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  SetFileTime(f, d);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  char *name;\n  ulg r;\n  unsigned int len = strlen(f);\n  int isstdin = !strcmp(f, \"-\");\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (isstdin) {\n    /* it is common for some PC based compilers to\n       fail with fstat() on devices or pipes */\n    if (fstat(fileno(stdin), &s) != 0) {\n      s.st_mode = S_IFREG; s.st_size = -1L;\n    }\n    time(&s.st_ctime);\n    s.st_atime = s.st_mtime = s.st_ctime;\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n#ifdef __WATCOMC__\n  /* of course, Watcom always has to make an exception */\n  if (s.st_atime == 312764400)\n    s.st_atime = s.st_mtime;\n  if (s.st_ctime == 312764400)\n    s.st_ctime = s.st_mtime;\n#endif\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  r = GetFileTime(name);\n  free(name);\n\n  return r;\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n */\n{\n    return rmdir(d);\n}\n\n\n#if defined MY_ZCALLOC /* Special zcalloc function for MEMORY16 (MSDOS/OS2) */\n\n#ifdef MSC  /* Microsoft C */\n\nzvoid far *zcalloc (unsigned items, unsigned size)\n{\n    return (zvoid far *)halloc((long)items, size);\n}\n\nzvoid zcfree (zvoid far *ptr)\n{\n    hfree((void huge *)ptr);\n}\n\n#endif /* MSC */\n\n#endif /* MY_ZCALLOC */\n\n#endif /* !UTIL */\n"
  },
  {
    "path": "deps/infozip/zip30/os2/os2acl.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* os2acl.c - access to OS/2 (LAN Server) ACLs\n *\n * Author:  Kai Uwe Rommel <rommel@ars.de>\n * Created: Mon Aug 08 1994\n *\n */\n\n/*\n * supported 32-bit compilers:\n * - emx+gcc\n * - IBM C Set++ 2.1 or newer\n * - Watcom C/C++ 10.0 or newer\n *\n * supported 16-bit compilers:\n * - MS C 6.00A\n * - Watcom C/C++ 10.0 or newer\n *\n * supported OS/2 LAN environments:\n * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server)\n * - IBM Peer 1.0 (Warp Connect)\n */\n\n#ifdef KUR\n   static char *rcsid =\n   \"$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $\";\n   static char *rcsrev = \"$Revision: 1.3 $\";\n#endif\n\n/*\n * $Log: os2acl.c,v $\n * Revision 1.3  1996/04/03 19:18:27  rommel\n * minor fixes\n *\n * Revision 1.2  1996/03/30 22:03:52  rommel\n * avoid frequent dynamic allocation for every call\n * streamlined code\n *\n * Revision 1.1  1996/03/30 09:35:00  rommel\n * Initial revision\n *\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <malloc.h>\n\n#define INCL_NOPM\n#define INCL_DOS\n#define INCL_DOSERRORS\n#include <os2.h>\n\n#include \"os2/os2acl.h\"\n\n#define UNLEN 20\n\n#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__)\n#define __32BIT__\n#endif\n\n#ifdef __32BIT__\ntypedef ULONG U_INT;\n#ifdef __EMX__\n#define PSTR16 _far16ptr\n#define PTR16(x) _emx_32to16(x)\n#else /* other 32-bit */\n#define PSTR16 PCHAR16\n#define PTR16(x) ((PCHAR16)(x))\n#endif\n#else /* 16-bit */\ntypedef USHORT U_INT;\n#define PSTR16 PSZ\n#define PTR16(x) (x)\n#endif\n\ntypedef struct access_list\n{\n  char acl_ugname[UNLEN+1];\n  char acl_pad;\n  USHORT acl_access;\n}\nACCLIST;\n\ntypedef struct access_info\n{\n  PSTR16 acc_resource_name;\n  USHORT acc_attr;\n  USHORT acc_count;\n}\nACCINFO;\n\nstatic ACCINFO *ai;\nstatic char *path, *data;\n\n#ifdef __32BIT__\n\n#ifdef __EMX__\n\nstatic USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);\nstatic USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nstatic USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);\n\nUSHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,\n                        PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+4+2+4+2+4);\n           _THUNK_FLAT (pszServer);\n           _THUNK_FLAT (pszResource);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_FLAT (pcbTotalAvail);\n           _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo)));\n}\n\nUSHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel,\n                        PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+4+2+4+2+2);\n           _THUNK_FLAT (pszServer);\n           _THUNK_FLAT (pszResource);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_SHORT (sParmNum);\n           _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo)));\n}\n\nUSHORT NetAccessAdd(PSZ pszServer, USHORT sLevel,\n                    PVOID pbBuffer, USHORT cbBuffer)\n{\n  return (USHORT)\n          (_THUNK_PROLOG (4+2+4+2);\n           _THUNK_FLAT (pszServer);\n           _THUNK_SHORT (sLevel);\n           _THUNK_FLAT (pbBuffer);\n           _THUNK_SHORT (cbBuffer);\n           _THUNK_CALLI (_emx_32to16(_NetAccessAdd)));\n}\n\n#else /* other 32-bit */\n\nAPIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail);\nAPIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nAPIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer,\n  USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer);\n\n#define _NetAccessGetInfo NetAccessGetInfo\n#define _NetAccessSetInfo NetAccessSetInfo\n#define _NetAccessAdd NetAccessAdd\n\n#if !defined(__IBMC__) || !defined(__TILED__)\n#define _tmalloc malloc\n#define _tfree free\n#endif\n\n#endif\n#else /* 16-bit */\n\nUSHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail);\nUSHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum);\nUSHORT (APIENTRY *NetAccessAdd)(PSZ pszServer,\n  USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer);\n\n#define _NetAccessGetInfo NetAccessGetInfo\n#define _NetAccessSetInfo NetAccessSetInfo\n#define _NetAccessAdd NetAccessAdd\n\n#define _tmalloc malloc\n#define _tfree free\n\n#define DosQueryProcAddr(handle, ord, name, funcptr) \\\n        DosGetProcAddr(handle, name, funcptr)\n#define DosQueryCurrentDir DosQCurDir\n#define DosQueryCurrentDisk DosQCurDisk\n\n#endif\n\n\nstatic BOOL acl_init(void)\n{\n  static BOOL initialized, netapi_avail;\n  HMODULE netapi;\n  char buf[256];\n\n  if (initialized)\n    return netapi_avail;\n\n  initialized = TRUE;\n\n  if (DosLoadModule(buf, sizeof(buf), \"NETAPI\", &netapi))\n    return FALSE;\n\n  if (DosQueryProcAddr(netapi, 0, \"NETACCESSGETINFO\", (PFN *) &_NetAccessGetInfo) ||\n      DosQueryProcAddr(netapi, 0, \"NETACCESSSETINFO\", (PFN *) &_NetAccessSetInfo) ||\n      DosQueryProcAddr(netapi, 0, \"NETACCESSADD\", (PFN *) &_NetAccessAdd))\n    return FALSE;\n\n#if defined(__WATCOMC__) && defined(__386__)\n  NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo;\n  NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo;\n  NetAccessAdd     = (PVOID) (ULONG) (PVOID16) NetAccessAdd;\n#endif\n\n  if ((path = _tmalloc(CCHMAXPATH)) == NULL)\n    return FALSE;\n  if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL)\n    return FALSE;\n  if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL)\n    return -1;\n\n  netapi_avail = TRUE;\n\n  return netapi_avail;\n}\n\nstatic void acl_mkpath(char *buffer, const char *source)\n{\n  char *ptr;\n  static char cwd[CCHMAXPATH];\n  static U_INT cwdlen;\n  U_INT cdrive;\n  ULONG drivemap;\n\n  if (isalpha((int)source[0]) && source[1] == ':')\n    buffer[0] = 0; /* fully qualified names */\n  else\n  {\n    if (cwd[0] == 0)\n    {\n      DosQueryCurrentDisk(&cdrive, &drivemap);\n      cwd[0] = (char)(cdrive + '@');\n      cwd[1] = ':';\n      cwd[2] = '\\\\';\n      cwdlen = sizeof(cwd) - 3;\n      DosQueryCurrentDir(0, cwd + 3, &cwdlen);\n      cwdlen = strlen(cwd);\n    }\n\n    if (source[0] == '/' || source[0] == '\\\\')\n    {\n      if (source[1] == '/' || source[1] == '\\\\')\n        buffer[0] = 0; /* UNC names */\n      else\n      {\n        strncpy(buffer, cwd, 2);\n        buffer[2] = 0;\n      }\n    }\n    else\n    {\n      strcpy(buffer, cwd);\n      if (cwd[cwdlen - 1] != '\\\\' && cwd[cwdlen - 1] != '/')\n        strcat(buffer, \"/\");\n    }\n  }\n\n  strcat(buffer, source);\n\n  for (ptr = buffer; *ptr; ptr++)\n    if (*ptr == '/')\n      *ptr = '\\\\';\n\n  if (ptr[-1] == '\\\\')\n    ptr[-1] = 0;\n\n  strupr(buffer);\n}\n\nstatic int acl_bin2text(char *data, char *text)\n{\n  ACCINFO *ai;\n  ACCLIST *al;\n  U_INT cnt, offs;\n\n  ai = (ACCINFO *) data;\n  al = (ACCLIST *) (data + sizeof(ACCINFO));\n\n  offs = sprintf(text, \"ACL1:%X,%d\\n\",\n                 ai -> acc_attr, ai -> acc_count);\n\n  for (cnt = 0; cnt < ai -> acc_count; cnt++)\n    offs += sprintf(text + offs, \"%s,%X\\n\",\n                    al[cnt].acl_ugname, al[cnt].acl_access);\n\n  return strlen(text);\n}\n\nint acl_get(char *server, const char *resource, char *buffer)\n{\n  USHORT datalen;\n  PSZ srv = NULL;\n  int rc;\n\n  if (!acl_init())\n    return -1;\n\n  if (server)\n    srv = server;\n\n  acl_mkpath(path, resource);\n  datalen = 0;\n\n  rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen);\n\n  if (rc == 0)\n    acl_bin2text(data, buffer);\n\n  return rc;\n}\n\nstatic int acl_text2bin(char *data, char *text, char *path)\n{\n  ACCINFO *ai;\n  ACCLIST *al;\n  char *ptr, *ptr2;\n  U_INT cnt;\n\n  ai = (ACCINFO *) data;\n  ai -> acc_resource_name = PTR16(path);\n\n  if (sscanf(text, \"ACL1:%hX,%hd\",\n             &ai -> acc_attr, &ai -> acc_count) != 2)\n    return ERROR_INVALID_PARAMETER;\n\n  al = (ACCLIST *) (data + sizeof(ACCINFO));\n  ptr = strchr(text, '\\n') + 1;\n\n  for (cnt = 0; cnt < ai -> acc_count; cnt++)\n  {\n    ptr2 = strchr(ptr, ',');\n    strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr);\n    al[cnt].acl_ugname[ptr2 - ptr] = 0;\n    sscanf(ptr2 + 1, \"%hx\", &al[cnt].acl_access);\n    ptr = strchr(ptr, '\\n') + 1;\n  }\n\n  return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST);\n}\n\nint acl_set(char *server, const char *resource, char *buffer)\n{\n  USHORT datalen;\n  PSZ srv = NULL;\n\n  if (!acl_init())\n    return -1;\n\n  if (server)\n    srv = server;\n\n  acl_mkpath(path, resource);\n\n  ai -> acc_resource_name = PTR16(path);\n  ai -> acc_attr = 0;\n  ai -> acc_count = 0;\n\n  NetAccessAdd(srv, 1, ai, sizeof(ACCINFO));\n  /* Ignore any errors, most probably because ACL already exists. */\n  /* In any such case, try updating the existing ACL. */\n\n  datalen = acl_text2bin(data, buffer, path);\n\n  return NetAccessSetInfo(srv, path, 1, data, datalen, 0);\n}\n\n/* end of os2acl.c */\n"
  },
  {
    "path": "deps/infozip/zip30/os2/os2acl.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* os2acl.h\n *\n * Author:  Kai Uwe Rommel <rommel@ars.de>\n * Created: Fri Mar 29 1996\n */\n\n/* $Id: os2acl.h,v 1.1 1996/03/30 09:35:00 rommel Exp rommel $ */\n\n/*\n * $Log: os2acl.h,v $\n * Revision 1.1  1996/03/30 09:35:00  rommel\n * Initial revision\n *\n */\n\n#ifndef _OS2ACL_H\n#define _OS2ACL_H\n\n#define ACL_BUFFERSIZE 4096\n\nint acl_get(char *server, const char *resource, char *buffer);\nint acl_set(char *server, const char *resource, char *buffer);\n\n#endif /* _OS2ACL_H */\n\n/* end of os2acl.h */\n"
  },
  {
    "path": "deps/infozip/zip30/os2/os2zip.c",
    "content": "/*\n * @(#)dir.c 1.4 87/11/06 Public Domain.\n *\n *  A public domain implementation of BSD directory routines for\n *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),\n *  August 1987\n *\n *  Ported to OS/2 by Kai Uwe Rommel\n *  Addition of other OS/2 file system specific code\n *  Placed into the public domain\n */\n\n/* does also contain EA access code for use in ZIP */\n\n\n#ifdef OS2\n\n\n#if defined(__EMX__) && !defined(__32BIT__)\n#  define __32BIT__\n#endif\n\n#include \"zip.h\"\n\n#include <stdlib.h>\n#include <time.h>\n#include <ctype.h>\n#ifndef __BORLANDC__\n#include <malloc.h>\n#endif\n\n#define INCL_NOPM\n#define INCL_DOSNLS\n#define INCL_DOSERRORS\n#include <os2.h>\n\n#include \"os2zip.h\"\n#include \"os2acl.h\"\n\n\n#ifndef max\n#define max(a, b) ((a) < (b) ? (b) : (a))\n#endif\n\n\n#ifdef __32BIT__\n#define DosFindFirst(p1, p2, p3, p4, p5, p6) \\\n        DosFindFirst(p1, p2, p3, p4, p5, p6, 1)\n#else\n#define DosQueryCurrentDisk DosQCurDisk\n#define DosQueryFSAttach(p1, p2, p3, p4, p5) \\\n        DosQFSAttach(p1, p2, p3, p4, p5, 0)\n#define DosQueryFSInfo(d, l, b, s) \\\n        DosQFSInfo(d, l, b, s)\n#define DosQueryPathInfo(p1, p2, p3, p4) \\\n        DosQPathInfo(p1, p2, p3, p4, 0)\n#define DosSetPathInfo(p1, p2, p3, p4, p5) \\\n        DosSetPathInfo(p1, p2, p3, p4, p5, 0)\n#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \\\n        DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)\n#define DosFindFirst(p1, p2, p3, p4, p5, p6) \\\n        DosFindFirst(p1, p2, p3, p4, p5, p6, 0)\n#define DosMapCase DosCaseMap\n#endif\n\n\n#ifndef UTIL\n\nextern int noisy;\n\n#ifndef S_IFMT\n#define S_IFMT 0xF000\n#endif\n\nstatic int attributes = _A_DIR | _A_HIDDEN | _A_SYSTEM;\n\nstatic char *getdirent(char *);\nstatic void free_dircontents(struct _dircontents *);\n\n#ifdef __32BIT__\nstatic HDIR hdir;\nstatic ULONG count;\nstatic FILEFINDBUF3 find;\n#else\nstatic HDIR hdir;\nstatic USHORT count;\nstatic FILEFINDBUF find;\n#endif\n\nDIR *opendir(const char *name)\n{\n  struct stat statb;\n  DIR *dirp;\n  char c;\n  char *s;\n  struct _dircontents *dp;\n  char nbuf[MAXPATHLEN + 1];\n  int len;\n\n  attributes = hidden_files ? (_A_DIR | _A_HIDDEN | _A_SYSTEM) : _A_DIR;\n\n  strcpy(nbuf, name);\n  if ((len = strlen(nbuf)) == 0)\n    return NULL;\n\n  if (((c = nbuf[len - 1]) == '\\\\' || c == '/') && (len > 1))\n  {\n    nbuf[len - 1] = 0;\n    --len;\n\n    if (nbuf[len - 1] == ':')\n    {\n      strcpy(nbuf+len, \"\\\\.\");\n      len += 2;\n    }\n  }\n  else\n    if (nbuf[len - 1] == ':')\n    {\n      strcpy(nbuf+len, \".\");\n      ++len;\n    }\n\n#ifndef __BORLANDC__\n  /* when will we ever see a Borland compiler that can properly stat !!! */\n  if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)\n    return NULL;\n#endif\n\n  if ((dirp = malloc(sizeof(DIR))) == NULL)\n    return NULL;\n\n  if (nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.'))\n    strcpy(nbuf+len-1, \"*.*\");\n  else\n    if (((c = nbuf[len - 1]) == '\\\\' || c == '/') && (len == 1))\n      strcpy(nbuf+len, \"*\");\n    else\n      strcpy(nbuf+len, \"\\\\*\");\n\n  /* len is no longer correct (but no longer needed) */\n\n  dirp -> dd_loc = 0;\n  dirp -> dd_contents = dirp -> dd_cp = NULL;\n\n  if ((s = getdirent(nbuf)) == NULL)\n    return dirp;\n\n  do\n  {\n    if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||\n        ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )\n    {\n      if (dp)\n        free(dp);\n      free_dircontents(dirp -> dd_contents);\n\n      return NULL;\n    }\n\n    if (dirp -> dd_contents)\n    {\n      dirp -> dd_cp -> _d_next = dp;\n      dirp -> dd_cp = dirp -> dd_cp -> _d_next;\n    }\n    else\n      dirp -> dd_contents = dirp -> dd_cp = dp;\n\n    strcpy(dp -> _d_entry, s);\n    dp -> _d_next = NULL;\n\n    dp -> _d_size = find.cbFile;\n    dp -> _d_mode = find.attrFile;\n    dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);\n    dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);\n  }\n  while ((s = getdirent(NULL)) != NULL);\n\n  dirp -> dd_cp = dirp -> dd_contents;\n\n  return dirp;\n}\n\nvoid closedir(DIR * dirp)\n{\n  free_dircontents(dirp -> dd_contents);\n  free(dirp);\n}\n\nstruct dirent *readdir(DIR * dirp)\n{\n  static struct dirent dp;\n\n  if (dirp -> dd_cp == NULL)\n    return NULL;\n\n  dp.d_namlen = dp.d_reclen =\n    strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));\n\n  dp.d_ino = 0;\n\n  dp.d_size = dirp -> dd_cp -> _d_size;\n  dp.d_mode = dirp -> dd_cp -> _d_mode;\n  dp.d_time = dirp -> dd_cp -> _d_time;\n  dp.d_date = dirp -> dd_cp -> _d_date;\n\n  dirp -> dd_cp = dirp -> dd_cp -> _d_next;\n  dirp -> dd_loc++;\n\n  return &dp;\n}\n\nvoid seekdir(DIR * dirp, long off)\n{\n  long i = off;\n  struct _dircontents *dp;\n\n  if (off >= 0)\n  {\n    for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);\n\n    dirp -> dd_loc = off - (i + 1);\n    dirp -> dd_cp = dp;\n  }\n}\n\nlong telldir(DIR * dirp)\n{\n  return dirp -> dd_loc;\n}\n\nstatic void free_dircontents(struct _dircontents * dp)\n{\n  struct _dircontents *odp;\n\n  while (dp)\n  {\n    if (dp -> _d_entry)\n      free(dp -> _d_entry);\n\n    dp = (odp = dp) -> _d_next;\n    free(odp);\n  }\n}\n\nstatic char *getdirent(char *dir)\n{\n  int done;\n  static int lower;\n\n  if (dir != NULL)\n  {                                    /* get first entry */\n    hdir = HDIR_SYSTEM;\n    count = 1;\n    done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);\n    lower = IsFileSystemFAT(dir);\n  }\n  else                                 /* get next entry */\n    done = DosFindNext(hdir, &find, sizeof(find), &count);\n\n  if (done == 0)\n  {\n    if (lower)\n      StringLower(find.achName);\n    return find.achName;\n  }\n  else\n  {\n    DosFindClose(hdir);\n    return NULL;\n  }\n}\n\n/* FAT / HPFS detection */\n\nint IsFileSystemFAT(char *dir)\n{\n  static USHORT nLastDrive = -1, nResult;\n  ULONG lMap;\n  BYTE bData[64];\n  char bName[3];\n#ifdef __32BIT__\n  ULONG nDrive, cbData;\n  PFSQBUFFER2 pData = (PFSQBUFFER2) bData;\n#else\n  USHORT nDrive, cbData;\n  PFSQBUFFER pData = (PFSQBUFFER) bData;\n#endif\n\n  /* We separate FAT and HPFS+other file systems here.\n     at the moment I consider other systems to be similar to HPFS,\n     i.e. support long file names and being case sensitive */\n\n  if (isalpha(dir[0]) && (dir[1] == ':'))\n    nDrive = to_up(dir[0]) - '@';\n  else\n    DosQueryCurrentDisk(&nDrive, &lMap);\n\n  if (nDrive == nLastDrive)\n    return nResult;\n\n  bName[0] = (char) (nDrive + '@');\n  bName[1] = ':';\n  bName[2] = 0;\n\n  nLastDrive = nDrive;\n  cbData = sizeof(bData);\n\n  if (!DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData))\n    nResult = !strcmp((char *) pData -> szFSDName + pData -> cbName, \"FAT\");\n  else\n    nResult = FALSE;\n\n  /* End of this ugly code */\n  return nResult;\n}\n\n/* access mode bits and time stamp */\n\nint GetFileMode(char *name)\n{\n#ifdef __32BIT__\n  FILESTATUS3 fs;\n  return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;\n#else\n  USHORT mode;\n  return DosQFileMode(name, &mode, 0L) ? -1 : mode;\n#endif\n}\n\nulg GetFileTime(char *name)\n{\n#ifdef __32BIT__\n  FILESTATUS3 fs;\n#else\n  FILESTATUS fs;\n#endif\n  USHORT nDate, nTime;\n  DATETIME dtCurrent;\n\n  if (strcmp(name, \"-\") == 0)\n  {\n    DosGetDateTime(&dtCurrent);\n    fs.fdateLastWrite.day     = dtCurrent.day;\n    fs.fdateLastWrite.month   = dtCurrent.month;\n    fs.fdateLastWrite.year    = dtCurrent.year - 1980;\n    fs.ftimeLastWrite.hours   = dtCurrent.hours;\n    fs.ftimeLastWrite.minutes = dtCurrent.minutes;\n    fs.ftimeLastWrite.twosecs = dtCurrent.seconds / 2;\n  }\n  else\n    if (DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)))\n      return -1;\n\n  nDate = * (USHORT *) &fs.fdateLastWrite;\n  nTime = * (USHORT *) &fs.ftimeLastWrite;\n\n  return ((ULONG) nDate) << 16 | nTime;\n}\n\nvoid SetFileTime(char *path, ulg stamp)\n{\n  FILESTATUS fs;\n  USHORT fd, ft;\n\n  if (DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)))\n    return;\n\n  fd = (USHORT) (stamp >> 16);\n  ft = (USHORT) stamp;\n  fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;\n  fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;\n\n  DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);\n}\n\n/* read volume label */\n\nchar *getVolumeLabel(int drive, unsigned long *vtime, unsigned long *vmode,\n                     time_t *utim)\n{\n  static FSINFO fi;\n\n  if (DosQueryFSInfo(drive ? drive - 'A' + 1 : 0,\n                     FSIL_VOLSER, (PBYTE) &fi, sizeof(fi)))\n    return NULL;\n\n  time(utim);\n  *vtime = unix2dostime(utim);\n  *vmode = _A_VOLID | _A_ARCHIVE;\n\n  return (fi.vol.cch > 0) ? fi.vol.szVolLabel : NULL;\n}\n\n/* FAT / HPFS name conversion stuff */\n\nint IsFileNameValid(char *name)\n{\n  HFILE hf;\n#ifdef __32BIT__\n  ULONG uAction;\n#else\n  USHORT uAction;\n#endif\n\n  switch(DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,\n                 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0))\n  {\n  case ERROR_INVALID_NAME:\n  case ERROR_FILENAME_EXCED_RANGE:\n    return FALSE;\n  case NO_ERROR:\n    DosClose(hf);\n  default:\n    return TRUE;\n  }\n}\n\nvoid ChangeNameForFAT(char *name)\n{\n  char *src, *dst, *next, *ptr, *dot, *start;\n  static char invalid[] = \":;,=+\\\"[]<>| \\t\";\n\n  if (isalpha(name[0]) && (name[1] == ':'))\n    start = name + 2;\n  else\n    start = name;\n\n  src = dst = start;\n  if ((*src == '/') || (*src == '\\\\'))\n    src++, dst++;\n\n  while (*src)\n  {\n    for (next = src; *next && (*next != '/') && (*next != '\\\\'); next++);\n\n    for (ptr = src, dot = NULL; ptr < next; ptr++)\n      if (*ptr == '.')\n      {\n        dot = ptr; /* remember last dot */\n        *ptr = '_';\n      }\n\n    if (dot == NULL)\n      for (ptr = src; ptr < next; ptr++)\n        if (*ptr == '_')\n          dot = ptr; /* remember last _ as if it were a dot */\n\n    if (dot && (dot > src) &&\n        ((next - dot <= 4) ||\n         ((next - src > 8) && (dot - src > 3))))\n    {\n      if (dot)\n        *dot = '.';\n\n      for (ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++)\n        *dst++ = *ptr;\n\n      for (ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++)\n        *dst++ = *ptr;\n    }\n    else\n    {\n      if (dot && (next - src == 1))\n        *dot = '.';           /* special case: \".\" as a path component */\n\n      for (ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++)\n        *dst++ = *ptr;\n    }\n\n    *dst++ = *next; /* either '/' or 0 */\n\n    if (*next)\n    {\n      src = next + 1;\n\n      if (*src == 0) /* handle trailing '/' on dirs ! */\n        *dst = 0;\n    }\n    else\n      break;\n  }\n\n  for (src = start; *src != 0; ++src)\n    if ((strchr(invalid, *src) != NULL) || (*src == ' '))\n      *src = '_';\n}\n\n/* .LONGNAME EA code */\n\ntypedef struct\n{\n  ULONG cbList;               /* length of value + 22 */\n#ifdef __32BIT__\n  ULONG oNext;\n#endif\n  BYTE fEA;                   /* 0 */\n  BYTE cbName;                /* length of \".LONGNAME\" = 9 */\n  USHORT cbValue;             /* length of value + 4 */\n  BYTE szName[10];            /* \".LONGNAME\" */\n  USHORT eaType;              /* 0xFFFD for length-preceded ASCII */\n  USHORT eaSize;              /* length of value */\n  BYTE szValue[CCHMAXPATH];\n}\nFEALST;\n\ntypedef struct\n{\n  ULONG cbList;\n#ifdef __32BIT__\n  ULONG oNext;\n#endif\n  BYTE cbName;\n  BYTE szName[10];            /* \".LONGNAME\" */\n}\nGEALST;\n\nchar *GetLongNameEA(const char *name)\n{\n  EAOP eaop;\n  GEALST gealst;\n  static FEALST fealst;\n  char *ptr;\n\n  eaop.fpGEAList = (PGEALIST) &gealst;\n  eaop.fpFEAList = (PFEALIST) &fealst;\n  eaop.oError = 0;\n\n  strcpy((char *) gealst.szName, \".LONGNAME\");\n  gealst.cbName  = (BYTE) strlen((char *) gealst.szName);\n#ifdef __32BIT__\n  gealst.oNext   = 0;\n#endif\n\n  gealst.cbList  = sizeof(gealst);\n  fealst.cbList  = sizeof(fealst);\n\n  if (DosQueryPathInfo(name, FIL_QUERYEASFROMLIST,\n                       (PBYTE) &eaop, sizeof(eaop)))\n    return NULL;\n\n  if (fealst.cbValue > 4 && fealst.eaType == 0xFFFD)\n  {\n    fealst.szValue[fealst.eaSize] = 0;\n\n    for (ptr = fealst.szValue; *ptr; ptr++)\n      if (*ptr == '/' || *ptr == '\\\\')\n        *ptr = '!';\n\n    return (char *) fealst.szValue;\n  }\n\n  return NULL;\n}\n\nchar *GetLongPathEA(const char *name)\n{\n  static char nbuf[CCHMAXPATH + 1];\n  char tempbuf[CCHMAXPATH + 1];\n  char *comp, *next, *ea, sep;\n  BOOL bFound = FALSE;\n\n  nbuf[0] = 0;\n  strncpy(tempbuf, name, CCHMAXPATH);\n  tempbuf[CCHMAXPATH] = '\\0';\n  next = tempbuf;\n\n  while (*next)\n  {\n    comp = next;\n\n    while (*next != '\\\\' && *next != '/' && *next != 0)\n      next++;\n\n    sep = *next;\n    *next = 0;\n\n    ea = GetLongNameEA(tempbuf);\n    strcat(nbuf, ea ? ea : comp);\n    bFound = bFound || (ea != NULL);\n\n    if (sep)\n    {\n      strcat(nbuf, \"\\\\\");\n      *next++ = sep;\n    }\n  }\n\n  return (nbuf[0] != 0) && bFound ? nbuf : NULL;\n}\n\n/* general EA code */\n\ntypedef struct\n{\n  USHORT nID;\n  USHORT nSize;\n  ULONG lSize;\n}\nEFHEADER, *PEFHEADER;\n\n#ifdef __32BIT__\n\n/* Perhaps due to bugs in the current OS/2 2.0 kernel, the success or\n   failure of the DosEnumAttribute() and DosQueryPathInfo() system calls\n   depends on the area where the return buffers are allocated. This\n   differs for the various compilers, for some alloca() works, for some\n   malloc() works, for some, both work. We'll have to live with that. */\n\n/* The use of malloc() is not very convenient, because it requires\n   backtracking (i.e. free()) at error returns. We do that for system\n   calls that may fail, but not for malloc() calls, because they are VERY\n   unlikely to fail. If ever, we just leave some memory allocated\n   over the usually short lifetime of a zip process ... */\n\n#ifdef __GNUC__\n#define alloc(x) alloca(x)\n#define unalloc(x)\n#else\n#define alloc(x) malloc(x)\n#define unalloc(x) free(x)\n#endif\n\nvoid GetEAs(char *path, char **bufptr, size_t *size,\n                        char **cbufptr, size_t *csize)\n{\n  FILESTATUS4 fs;\n  PDENA2 pDENA, pFound;\n  EAOP2 eaop;\n  PGEA2 pGEA;\n  PGEA2LIST pGEAlist;\n  PFEA2LIST pFEAlist;\n  PEFHEADER pEAblock;\n  ULONG ulAttributes, ulMemoryBlock;\n  ULONG nLength;\n  ULONG nBlock;\n  char szName[CCHMAXPATH];\n\n  *size = *csize = 0;\n\n  strcpy(szName, path);\n  nLength = strlen(szName);\n  if (szName[nLength - 1] == '/')\n    szName[nLength - 1] = 0;\n\n  if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs)))\n    return;\n  nBlock = max(fs.cbList, 65535);\n  if ((pDENA = alloc((size_t) nBlock)) == NULL)\n    return;\n\n  ulAttributes = -1;\n\n  if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, nBlock,\n                       &ulAttributes, ENUMEA_LEVEL_NO_VALUE)\n    || ulAttributes == 0\n    || (pGEAlist = alloc((size_t) nBlock)) == NULL)\n  {\n    unalloc(pDENA);\n    return;\n  }\n\n  pGEA = pGEAlist -> list;\n  memset(pGEAlist, 0, nBlock);\n  pFound = pDENA;\n\n  while (ulAttributes--)\n  {\n    if (!(strcmp(pFound -> szName, \".LONGNAME\") == 0 && use_longname_ea))\n    {\n      pGEA -> cbName = pFound -> cbName;\n      strcpy(pGEA -> szName, pFound -> szName);\n\n      nLength = sizeof(GEA2) + strlen(pGEA -> szName);\n      nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);\n\n      pGEA -> oNextEntryOffset = ulAttributes ? nLength : 0;\n      pGEA   = (PGEA2)  ((PCH) pGEA + nLength);\n    }\n\n    pFound = (PDENA2) ((PCH) pFound + pFound -> oNextEntryOffset);\n  }\n\n  if (pGEA == pGEAlist -> list) /* no attributes to save */\n  {\n    unalloc(pDENA);\n    unalloc(pGEAlist);\n    return;\n  }\n\n  pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;\n\n  pFEAlist = (PVOID) pDENA;  /* reuse buffer */\n  pFEAlist -> cbList = nBlock;\n\n  eaop.fpGEA2List = pGEAlist;\n  eaop.fpFEA2List = pFEAlist;\n  eaop.oError = 0;\n\n  if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,\n                       (PBYTE) &eaop, sizeof(eaop)))\n  {\n    unalloc(pDENA);\n    unalloc(pGEAlist);\n    return;\n  }\n\n  /* The maximum compressed size is (in case of STORE type) the\n     uncompressed size plus the size of the compression type field\n     plus the size of the CRC field + 2*5 deflate overhead bytes\n     for uncompressable data.\n     (5 bytes per 32Kb block, max compressed size = 2 blocks) */\n\n  ulAttributes = pFEAlist -> cbList;\n  ulMemoryBlock = ulAttributes +\n                  sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;\n  pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER) + ulMemoryBlock);\n\n  if (pEAblock == NULL)\n  {\n    unalloc(pDENA);\n    unalloc(pGEAlist);\n    return;\n  }\n\n  *bufptr = (char *) pEAblock;\n  *size = sizeof(EFHEADER);\n\n  pEAblock -> nID = EF_OS2EA;\n  pEAblock -> nSize = sizeof(pEAblock -> lSize);\n  pEAblock -> lSize = ulAttributes; /* uncompressed size */\n\n  nLength = memcompress((char *) (pEAblock + 1), ulMemoryBlock,\n                        (char *) pFEAlist, ulAttributes);\n  *size += nLength;\n  pEAblock -> nSize += nLength;\n\n  if ((pEAblock = (PEFHEADER) malloc(sizeof(EFHEADER))) == NULL)\n  {\n    unalloc(pDENA);\n    unalloc(pGEAlist);\n    return;\n  }\n\n  *cbufptr = (char *) pEAblock;\n  *csize = sizeof(EFHEADER);\n\n  pEAblock -> nID = EF_OS2EA;\n  pEAblock -> nSize = sizeof(pEAblock -> lSize);\n  pEAblock -> lSize = ulAttributes;\n\n  if (noisy)\n    printf(\" (%ld bytes EA's)\", ulAttributes);\n\n  unalloc(pDENA);\n  unalloc(pGEAlist);\n}\n\n#else /* !__32BIT__ */\n\ntypedef struct\n{\n  ULONG oNextEntryOffset;\n  BYTE fEA;\n  BYTE cbName;\n  USHORT cbValue;\n  CHAR szName[1];\n}\nFEA2, *PFEA2;\n\ntypedef struct\n{\n  ULONG cbList;\n  FEA2 list[1];\n}\nFEA2LIST, *PFEA2LIST;\n\nvoid GetEAs(char *path, char **bufptr, size_t *size,\n                        char **cbufptr, size_t *csize)\n{\n  FILESTATUS2 fs;\n  PDENA1 pDENA, pFound;\n  EAOP eaop;\n  PGEALIST pGEAlist;\n  PGEA pGEA;\n  PFEALIST pFEAlist;\n  PFEA pFEA;\n  PFEA2LIST pFEA2list;\n  PFEA2 pFEA2;\n  EFHEADER *pEAblock;\n  ULONG ulAttributes;\n  USHORT nLength, nMaxSize;\n  char szName[CCHMAXPATH];\n\n  *size = *csize = 0;\n\n  strcpy(szName, path);\n  nLength = strlen(szName);\n  if (szName[nLength - 1] == '/')\n    szName[nLength - 1] = 0;\n\n  if (DosQueryPathInfo(szName, FIL_QUERYEASIZE, (PBYTE) &fs, sizeof(fs))\n      || fs.cbList <= 2 * sizeof(ULONG))\n    return;\n\n  ulAttributes = -1;\n  nMaxSize = (USHORT) min(fs.cbList * 2, 65520L);\n\n  if ((pDENA = malloc((size_t) nMaxSize)) == NULL)\n    return;\n\n  if (DosEnumAttribute(ENUMEA_REFTYPE_PATH, szName, 1, pDENA, fs.cbList,\n                       &ulAttributes, ENUMEA_LEVEL_NO_VALUE)\n    || ulAttributes == 0\n    || (pGEAlist = malloc(nMaxSize)) == NULL)\n  {\n    free(pDENA);\n    return;\n  }\n\n  pGEA = pGEAlist -> list;\n  pFound = pDENA;\n\n  while (ulAttributes--)\n  {\n    nLength = strlen(pFound -> szName);\n\n    if (!(strcmp(pFound -> szName, \".LONGNAME\") == 0 && use_longname_ea))\n    {\n      pGEA -> cbName = pFound -> cbName;\n      strcpy(pGEA -> szName, pFound -> szName);\n\n      pGEA++;\n      pGEA = (PGEA) (((PCH) pGEA) + nLength);\n    }\n\n    pFound++;\n    pFound = (PDENA1) (((PCH) pFound) + nLength);\n  }\n\n  if (pGEA == pGEAlist -> list)\n  {\n    free(pDENA);\n    free(pGEAlist);\n    return;\n  }\n\n  pGEAlist -> cbList = (PCH) pGEA - (PCH) pGEAlist;\n\n  pFEAlist = (PFEALIST) pDENA; /* reuse buffer */\n  pFEAlist -> cbList = fs.cbList;\n  pFEA = pFEAlist -> list;\n\n  eaop.fpGEAList = pGEAlist;\n  eaop.fpFEAList = pFEAlist;\n  eaop.oError = 0;\n\n  if (DosQueryPathInfo(szName, FIL_QUERYEASFROMLIST,\n                       (PBYTE) &eaop, sizeof(eaop)))\n  {\n    free(pDENA);\n    free(pGEAlist);\n    return;\n  }\n\n  /* now convert into new OS/2 2.0 32-bit format */\n\n  pFEA2list = (PFEA2LIST) pGEAlist;  /* reuse buffer */\n  pFEA2 = pFEA2list -> list;\n\n  while ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList)\n  {\n    nLength = sizeof(FEA) + pFEA -> cbName + 1 + pFEA -> cbValue;\n    memcpy((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset), pFEA, nLength);\n    memset((PCH) pFEA2 + sizeof(pFEA2 -> oNextEntryOffset) + nLength, 0, 3);\n    pFEA = (PFEA) ((PCH) pFEA + nLength);\n\n    nLength = sizeof(FEA2) + pFEA2 -> cbName + 1 + pFEA2 -> cbValue;\n    nLength = ((nLength - 1) / sizeof(ULONG) + 1) * sizeof(ULONG);\n    /* rounded up to 4-byte boundary */\n    pFEA2 -> oNextEntryOffset =\n      ((PCH) pFEA - (PCH) pFEAlist < pFEAlist -> cbList) ? nLength : 0;\n    pFEA2 = (PFEA2) ((PCH) pFEA2 + nLength);\n  }\n\n  pFEA2list -> cbList = (PCH) pFEA2 - (PCH) pFEA2list;\n  ulAttributes = pFEA2list -> cbList;\n\n  pEAblock = (PEFHEADER) pDENA; /* reuse buffer */\n\n  *bufptr = (char *) pEAblock;\n  *size = sizeof(EFHEADER);\n\n  pEAblock -> nID = EF_OS2EA;\n  pEAblock -> nSize = sizeof(pEAblock -> lSize);\n  pEAblock -> lSize = ulAttributes; /* uncompressed size */\n\n  nLength = (USHORT) memcompress((char *) (pEAblock + 1),\n    nMaxSize - sizeof(EFHEADER), (char *) pFEA2list, ulAttributes);\n\n  *size += nLength;\n  pEAblock -> nSize += nLength;\n\n  pEAblock = (PEFHEADER) pGEAlist;\n\n  *cbufptr = (char *) pEAblock;\n  *csize = sizeof(EFHEADER);\n\n  pEAblock -> nID = EF_OS2EA;\n  pEAblock -> nSize = sizeof(pEAblock -> lSize);\n  pEAblock -> lSize = ulAttributes;\n\n  if (noisy)\n    printf(\" (%ld bytes EA's)\", ulAttributes);\n}\n\n#endif /* __32BIT__ */\n\nvoid GetACL(char *path, char **bufptr, size_t *size,\n                        char **cbufptr, size_t *csize)\n{\n  static char *buffer;\n  char *cbuffer;\n  long bytes, cbytes;\n  PEFHEADER pACLblock;\n\n  if (buffer == NULL) /* avoid frequent allocation (for every file) */\n    if ((buffer = malloc(ACL_BUFFERSIZE)) == NULL)\n      return;\n\n  if (acl_get(NULL, path, buffer))\n    return; /* this will be the most likely case */\n\n  bytes = strlen(buffer);\n\n  /* The maximum compressed size is (in case of STORE type) the\n     uncompressed size plus the size of the compression type field\n     plus the size of the CRC field + 2*5 deflate overhead bytes\n     for uncompressable data.\n     (5 bytes per 32Kb block, max compressed size = 2 blocks) */\n\n  cbytes = bytes + sizeof(USHORT) + sizeof(ULONG) + EB_DEFLAT_EXTRA;\n  if ((*bufptr = realloc(*bufptr, *size + sizeof(EFHEADER) + cbytes)) == NULL)\n    return;\n\n  pACLblock = (PEFHEADER) (*bufptr + *size);\n\n  cbuffer = (char *) (pACLblock + 1);\n  cbytes = memcompress(cbuffer, cbytes, buffer, bytes);\n\n  *size += sizeof(EFHEADER) + cbytes;\n\n  pACLblock -> nID = EF_ACL;\n  pACLblock -> nSize = sizeof(pACLblock -> lSize) + cbytes;\n  pACLblock -> lSize = bytes; /* uncompressed size */\n\n  if ((*cbufptr = realloc(*cbufptr, *csize + sizeof(EFHEADER))) == NULL)\n    return;\n\n  pACLblock = (PEFHEADER) (*cbufptr + *csize);\n  *csize += sizeof(EFHEADER);\n\n  pACLblock -> nID = EF_ACL;\n  pACLblock -> nSize = sizeof(pACLblock -> lSize);\n  pACLblock -> lSize = bytes;\n\n  if (noisy)\n    printf(\" (%ld bytes ACL)\", bytes);\n}\n\n#ifdef USE_EF_UT_TIME\n\nint GetExtraTime(struct zlist far *z, iztimes *z_utim)\n{\n  int eb_c_size = EB_HEADSIZE + EB_UT_LEN(1);\n  int eb_l_size = eb_c_size;\n  char *eb_c_ptr;\n  char *eb_l_ptr;\n  unsigned long ultime;\n\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently no correct tz info */\n#endif\n\n  eb_c_ptr = realloc(z->cextra, (z->cext + eb_c_size));\n  if (eb_c_ptr == NULL)\n    return ZE_MEM;\n  z->cextra = eb_c_ptr;\n  eb_c_ptr += z->cext;\n  z->cext += eb_c_size;\n\n  eb_c_ptr[0]  = 'U';\n  eb_c_ptr[1]  = 'T';\n  eb_c_ptr[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  eb_c_ptr[3]  = 0;\n  eb_c_ptr[4]  = EB_UT_FL_MTIME;\n  ultime = (unsigned long) z_utim->mtime;\n  eb_c_ptr[5]  = (char)(ultime);\n  eb_c_ptr[6]  = (char)(ultime >> 8);\n  eb_c_ptr[7]  = (char)(ultime >> 16);\n  eb_c_ptr[8]  = (char)(ultime >> 24);\n\n  if (z_utim->mtime != z_utim->atime || z_utim->mtime != z_utim->ctime)\n  {\n    eb_c_ptr[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;\n    eb_l_size = EB_HEADSIZE + EB_UT_LEN(3); /* only on HPFS they can differ */\n  /* so only then it makes sense to store all three time stamps */\n  }\n\n  eb_l_ptr = realloc(z->extra, (z->ext + eb_l_size));\n  if (eb_l_ptr == NULL)\n    return ZE_MEM;\n  z->extra = eb_l_ptr;\n  eb_l_ptr += z->ext;\n  z->ext += eb_l_size;\n\n  memcpy(eb_l_ptr, eb_c_ptr, eb_c_size);\n\n  if (eb_l_size > eb_c_size)\n  {\n    eb_l_ptr[2]  = EB_UT_LEN(3);\n    ultime = (unsigned long) z_utim->atime;\n    eb_l_ptr[9]  = (char)(ultime);\n    eb_l_ptr[10] = (char)(ultime >> 8);\n    eb_l_ptr[11] = (char)(ultime >> 16);\n    eb_l_ptr[12] = (char)(ultime >> 24);\n    ultime = (unsigned long) z_utim->ctime;\n    eb_l_ptr[13] = (char)(ultime);\n    eb_l_ptr[14] = (char)(ultime >> 8);\n    eb_l_ptr[15] = (char)(ultime >> 16);\n    eb_l_ptr[16] = (char)(ultime >> 24);\n  }\n\n  return ZE_OK;\n}\n\n#endif /* USE_EF_UT_TIME */\n\nint set_extra_field(struct zlist far *z, iztimes *z_utim)\n{\n  /* store EA data in local header, and size only in central headers */\n  GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);\n\n  /* store ACL data in local header, and size only in central headers */\n  GetACL(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);\n\n#ifdef USE_EF_UT_TIME\n  /* store extended time stamps in both headers */\n  return GetExtraTime(z, z_utim);\n#else /* !USE_EF_UT_TIME */\n  return ZE_OK;\n#endif /* ?USE_EF_UT_TIME */\n}\n\n#endif /* !UTIL */\n\n/* Initialize the table of uppercase characters including handling of\n   country dependent characters. */\n\nvoid init_upper()\n{\n  COUNTRYCODE cc;\n  unsigned nCnt, nU;\n\n  for (nCnt = 0; nCnt < sizeof(upper); nCnt++)\n    upper[nCnt] = lower[nCnt] = (unsigned char) nCnt;\n\n  cc.country = cc.codepage = 0;\n  DosMapCase(sizeof(upper), &cc, (PCHAR) upper);\n\n  for (nCnt = 0; nCnt < 256; nCnt++)\n  {\n    nU = upper[nCnt];\n    if (nU != nCnt && lower[nU] == (unsigned char) nU)\n      lower[nU] = (unsigned char) nCnt;\n  }\n\n  for (nCnt = 'A'; nCnt <= 'Z'; nCnt++)\n    lower[nCnt] = (unsigned char) (nCnt - 'A' + 'a');\n}\n\nchar *StringLower(char *szArg)\n{\n  unsigned char *szPtr;\n  for (szPtr = (unsigned char *) szArg; *szPtr; szPtr++)\n    *szPtr = lower[*szPtr];\n  return szArg;\n}\n\n#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)\nvoid DebugMalloc(void)\n{\n  _dump_allocated(0); /* print out debug malloc memory statistics */\n}\n#endif\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#if defined(__IBMC__) || defined(__WATCOMC__) || defined(_MSC_VER)\n    char buf[80];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n#  ifdef __EMX__  /* __EMX__ is defined as \"1\" only (sigh) */\n      \"emx+gcc \", __VERSION__,\n#  else\n      \"gcc/2 \", __VERSION__,\n#  endif\n#elif defined(__IBMC__)\n      \"IBM \",\n#  if (__IBMC__ < 200)\n      (sprintf(buf, \"C Set/2 %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  elif (__IBMC__ < 300)\n      (sprintf(buf, \"C Set++ %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  else\n      (sprintf(buf, \"Visual Age C++ %d.%02d\", __IBMC__/100,__IBMC__%100), buf),\n#  endif\n#elif defined(__WATCOMC__)\n      \"Watcom C\", (sprintf(buf, \" (__WATCOMC__ = %d)\", __WATCOMC__), buf),\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n      \"Borland C++\",\n#    if (__BORLANDC__ < 0x0460)\n        \" 1.0\",\n#    elif (__BORLANDC__ == 0x0460)\n        \" 1.5\",\n#    else\n        \" 2.0\",\n#    endif\n#  else\n      \"Turbo C\",\n#    if (__TURBOC__ >= 661)\n       \"++ 1.0 or later\",\n#    elif (__TURBOC__ == 661)\n       \" 3.0?\",\n#    elif (__TURBOC__ == 397)\n       \" 2.0\",\n#    else\n       \" 1.0 or 1.5?\",\n#    endif\n#  endif\n#elif defined(MSC)\n      \"Microsoft C \",\n#  ifdef _MSC_VER\n      (sprintf(buf, \"%d.%02d\", _MSC_VER/100, _MSC_VER%100), buf),\n#  else\n      \"5.1 or earlier\",\n#  endif\n#else\n      \"unknown compiler\", \"\",\n#endif /* __GNUC__ */\n\n      \"OS/2\",\n\n/* GRR:  does IBM C/2 identify itself as IBM rather than Microsoft? */\n#if (defined(MSC) || (defined(__WATCOMC__) && !defined(__386__)))\n#  if defined(M_I86HM) || defined(__HUGE__)\n      \" (16-bit, huge)\",\n#  elif defined(M_I86LM) || defined(__LARGE__)\n      \" (16-bit, large)\",\n#  elif defined(M_I86MM) || defined(__MEDIUM__)\n      \" (16-bit, medium)\",\n#  elif defined(M_I86CM) || defined(__COMPACT__)\n      \" (16-bit, compact)\",\n#  elif defined(M_I86SM) || defined(__SMALL__)\n      \" (16-bit, small)\",\n#  elif defined(M_I86TM) || defined(__TINY__)\n      \" (16-bit, tiny)\",\n#  else\n      \" (16-bit)\",\n#  endif\n#else\n      \" 2.x/3.x (32-bit)\",\n#endif\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n    );\n\n    /* temporary debugging code for Borland compilers only */\n#ifdef __TURBOC__\n    printf(\"\\t(__TURBOC__ = 0x%04x = %d)\\n\", __TURBOC__, __TURBOC__);\n#ifdef __BORLANDC__\n    printf(\"\\t(__BORLANDC__ = 0x%04x)\\n\",__BORLANDC__);\n#else\n    printf(\"\\tdebug(__BORLANDC__ not defined)\\n\");\n#endif\n#ifdef __TCPLUSPLUS__\n    printf(\"\\t(__TCPLUSPLUS__ = 0x%04x)\\n\", __TCPLUSPLUS__);\n#else\n    printf(\"\\tdebug(__TCPLUSPLUS__ not defined)\\n\");\n#endif\n#ifdef __BCPLUSPLUS__\n    printf(\"\\t(__BCPLUSPLUS__ = 0x%04x)\\n\\n\", __BCPLUSPLUS__);\n#else\n    printf(\"\\tdebug(__BCPLUSPLUS__ not defined)\\n\\n\");\n#endif\n#endif /* __TURBOC__ */\n\n} /* end function version_local() */\n\n#endif /* OS2 */\n"
  },
  {
    "path": "deps/infozip/zip30/os2/os2zip.h",
    "content": "/*\n * @(#) dir.h 1.4 87/11/06   Public Domain.\n *\n *  A public domain implementation of BSD directory routines for\n *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),\n *  August 1987\n *\n *  Ported to OS/2 by Kai Uwe Rommel\n *  Addition of other OS/2 file system specific code\n *  Placed into the public domain\n */\n\n\n#define MAXNAMLEN  256\n#define MAXPATHLEN 256\n\n#define _A_RONLY    0x01\n#define _A_HIDDEN   0x02\n#define _A_SYSTEM   0x04\n#define _A_VOLID    0x08\n#define _A_DIR      0x10\n#define _A_ARCHIVE  0x20\n\n\nstruct dirent\n{\n  ino_t    d_ino;                   /* a bit of a farce */\n  int      d_reclen;                /* more farce */\n  int      d_namlen;                /* length of d_name */\n  char     d_name[MAXNAMLEN + 1];   /* null terminated */\n  /* nonstandard fields */\n  long     d_size;                  /* size in bytes */\n  unsigned d_mode;                  /* DOS or OS/2 file attributes */\n  unsigned d_time;\n  unsigned d_date;\n};\n\n/* The fields d_size and d_mode are extensions by me (Kai Uwe Rommel).\n * The find_first and find_next calls deliver this data without any extra cost.\n * If this data is needed, these fields save a lot of extra calls to stat()\n * (each stat() again performs a find_first call !).\n */\n\nstruct _dircontents\n{\n  char *_d_entry;\n  long _d_size;\n  unsigned _d_mode, _d_time, _d_date;\n  struct _dircontents *_d_next;\n};\n\ntypedef struct _dirdesc\n{\n  int  dd_id;                   /* uniquely identify each open directory */\n  long dd_loc;                  /* where we are in directory entry is this */\n  struct _dircontents *dd_contents;   /* pointer to contents of dir */\n  struct _dircontents *dd_cp;         /* pointer to current position */\n}\nDIR;\n\n\nextern DIR *opendir(const char *);\nextern struct dirent *readdir(DIR *);\nextern void seekdir(DIR *, long);\nextern long telldir(DIR *);\nextern void closedir(DIR *);\n#define rewinddir(dirp) seekdir(dirp, 0L)\n\nint GetFileMode(char *name);\nulg GetFileTime(char *name);\nvoid SetFileTime(char *path, ulg stamp);\nchar *getVolumeLabel(int drive, unsigned long *time, unsigned long *mode,\n                     time_t *utim);\n\nint IsFileNameValid(char *name);\nint IsFileSystemFAT(char *dir);\nvoid ChangeNameForFAT(char *name);\n\nchar *GetLongNameEA(const char *name);\nchar *GetLongPathEA(const char *name);\nvoid GetEAs(char *name, char **bufptr, size_t *size,\n                        char **cbufptr, size_t *csize);\n\nchar *StringLower(char *);\n"
  },
  {
    "path": "deps/infozip/zip30/os2/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#if defined(__OS2__) && !defined(OS2)\n#  define OS2\n#endif\n\n/* Automatic setting of the common Microsoft C idenfifier MSC.\n * NOTE: Watcom also defines M_I*86 !\n */\n#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))\n#  ifndef MSC\n#    define MSC                 /* This should work for older MSC, too!  */\n#  endif\n#endif\n\n#if defined(__WATCOMC__) && defined(__386__)\n#  define WATCOMC_386\n#endif\n\n#if defined(__EMX__) || defined(WATCOMC_386) || defined(__BORLANDC__)\n#  if (defined(OS2) && !defined(__32BIT__))\n#    define __32BIT__\n#  endif\n#endif\n\n#if defined(OS2) && !defined(__32BIT__)\n#  define MEMORY16\n#endif\n\n#ifndef NO_ASM\n#  define ASMV\n/* #  define ASM_CRC */\n#endif\n\n/* enable creation of UTC time fields unless explicitely suppressed */\n#if (!defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n\n/* check that TZ environment variable is defined before using UTC times */\n#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))\n#  define IZ_CHECK_TZ\n#endif\n\n#ifndef ZP_NEED_MEMCOMPR\n#  define ZP_NEED_MEMCOMPR\n#endif\n\n#ifdef MEMORY16\n#  ifdef __TURBOC__\n#    include <alloc.h>\n#    if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)\n#      if defined(DYNAMIC_CRC_TABLE) && defined(DYNALLOC_CRCTAB)\n        error: No dynamic CRC table allocation with Borland C far data models.\n#      endif /* DYNAMIC_CRC_TABLE */\n#    endif /* Turbo/Borland C far data memory models */\n#    define nearmalloc malloc\n#    define nearfree   free\n#    define DYN_ALLOC\n#  else /* !__TURBOC__ */\n#    include <malloc.h>\n#    define nearmalloc _nmalloc\n#    define nearfree   _nfree\n#    define farmalloc  _fmalloc\n#    define farfree    _ffree\n#  endif /* ?__TURBOC__ */\n#  define MY_ZCALLOC 1\n#endif /* MEMORY16 */\n\n\n/* The symbol MSDOS is consistently used in the generic source files\n * to identify code to support for MSDOS (and MSDOS related) stuff.\n * e.g: FAT or (FAT like) file systems,\n *      '\\\\' as directory separator in paths,\n *      \"\\r\\n\" as record (line) terminator in text files, ...\n *\n * MSDOS is defined anyway with MS C 16-bit. So the block above works.\n * For the 32-bit compilers, MSDOS must not be defined in the block above.\n */\n#if (defined(OS2) && !defined(MSDOS))\n#  define MSDOS\n/* inherit MS-DOS file system etc. stuff */\n#endif\n\n#define USE_CASE_MAP\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n\n/* time stamp resolution of file system is 2 seconds */\n#define ROUNDED_TIME(time)  ((time_t)(((unsigned long)(time) + 1) & (~1)))\n\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"wb\"\n\n#ifdef __32BIT__\n#  define CBSZ 0x40000\n#  define ZBSZ 0x40000\n#else\n#  define CBSZ 0xE000\n#  define ZBSZ 0x7F00 /* Some libraries do not allow a buffer size > 32K */\n#endif\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <io.h>\n\n#ifdef ZCRYPT_INTERNAL\n#  ifndef __GO32__\n#    include <process.h>        /* getpid() declaration for srand seed */\n#  endif\n#endif\n\n/* for some (all ?) versions of IBM C Set/2 and IBM C Set++ */\n#ifndef S_IFMT\n#  define S_IFMT 0xF000\n#endif /* !S_IFMT */\n\n#ifdef MSC\n#  define NO_UNISTD_H\n#endif\n\n#ifdef __WATCOMC__\n#  define NO_MKTEMP\n/* Get asm routines to link properly without using \"__cdecl\": */\n#  ifdef __386__\n#    ifdef ASMV\n#      pragma aux window \"*\";\n#      pragma aux prev \"*\";\n#      pragma aux prev_length \"*\";\n#      pragma aux strstart \"*\";\n#      pragma aux match_start \"*\";\n#      pragma aux max_chain_length \"*\";\n#      pragma aux good_match \"*\";\n#      pragma aux nice_match \"*\";\n#      pragma aux match_init \"*\";\n#      pragma aux longest_match \"*\";\n#    endif\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* !USE_ZLIB */\n#  else /* !__386__ */\n#    if defined(ASMV) || defined(ASM_CRC)\n/*#      error 16 bit assembly modules currently DO NOT WORK with Watcom C. */\n#    endif\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] loadds modify [ax bx]\n#      pragma aux longest_match \"_*\" parm caller [] loadds value [ax] \\\n                                      modify [ax bx cx dx es]\n#    endif\n#    ifndef USE_ZLIB\n#      pragma aux crc32         \"_*\" parm caller [] value [ax dx] \\\n                                      modify [ax bx cx dx es]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [ax] \\\n                                      modify [ax bx cx dx]\n#    endif /* !USE_ZLIB */\n#  endif /* ?__386__ */\n#endif\n\n#ifdef __IBMC__\n#  define NO_UNISTD_H\n#  define NO_MKTEMP\n#  define timezone _timezone            /* (underscore names work with    */\n#  define tzset _tzset                  /*  all versions of C Set)        */\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/os2/zip.def",
    "content": "NAME WINDOWCOMPAT NEWFILES\nDESCRIPTION 'The world-famous zip utilities from Info-ZIP'\n; STACKSIZE 0x50000\n"
  },
  {
    "path": "deps/infozip/zip30/os2/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define fhow (O_RDONLY|O_BINARY)\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/3rdparty.bug",
    "content": "Known, current PKZIP bugs/limitations:\n-------------------------------------\n\n - PKUNZIP 2.04g is reported to corrupt some files when compressing them with\n   the -ex option; when tested, the files fail the CRC check, and comparison\n   with the original file shows bogus data (6K in one case) embedded in the\n   middle.  PKWARE apparently characterized this as a \"known problem.\"\n\n - PKUNZIP 2.04g considers volume labels valid only if originated on a FAT\n   file system, but other OSes and file systems (e.g., Amiga and OS/2 HPFS)\n   support volume labels, too.\n\n - PKUNZIP 2.04g can restore volume labels created by Zip 2.x but not by\n   PKZIP 2.04g (OS/2 DOS box only??).\n\n - PKUNZIP 2.04g gives an error message for stored directory entries created\n   under other OSes (although it creates the directory anyway), and PKZIP -vt\n   does not report the directory attribute bit as being set, even if it is.\n\n - PKZIP 2.04g mangles unknown extra fields (especially OS/2 extended attri-\n   butes) when adding new files to an existing zipfile [example:  Walnut Creek\n   Hobbes March 1995 CD-ROM, FILE_ID.DIZ additions].\n\n - PKUNZIP 2.04g is unable to detect or deal with prepended junk in a zipfile,\n   reporting CRC errors in valid compressed data.\n\n - PKUNZIP 2.04g (registered version) incorrectly updates/freshens the AV extra\n   field in authenticated archives.  The resultant extra block length and total\n   extra field length are inconsistent.\n\n - [Windows version 2.01] Win95 long filenames (VFAT) are stored OK, but the\n   file system is always listed as ordinary DOS FAT.\n\n - [Windows version 2.50] NT long filenames (NTFS) are stored OK, but the\n   file system is always listed as ordinary DOS FAT.\n\n - PKZIP 2.04 for DOS encrypts using the OEM code page for 8-bit passwords,\n   while PKZIP 2.50 for Windows uses Latin-1 (ISO 8859-1).  This means an\n   archive encrypted with an 8-bit password with one of the two PKZIP versions\n   cannot be decrypted with the other version.\n\n - PKZIP for Windows GUI (v 2.60), PKZIP for Windows command line (v 2.50) and\n   PKZIP for Unix (v 2.51) save the host's native file timestamps, but\n   only in a local extra field. Thus, timestamp-related selections (update\n   or freshen, both in extraction or archiving operations) use the DOS-format\n   localtime records in the Zip archives for comparisons. This may result\n   in wrong decisions of the program when updating archives that were\n   previously created in a different local time zone.\n\n - PKZIP releases newer than PKZIP for DOS 2.04g (PKZIP for Windows, both\n   GUI v 2.60 and console v 2.50; PKZIP for Unix v 2.51; probably others too)\n   use different code pages for storing filenames in central (OEM Codepage)\n   and local (ANSI / ISO 8859-1 Codepage) headers. When a stored filename\n   contains extended-ASCII characters, the local and central filename fields\n   do not match. As a consequence, Info-ZIP's Zip program considers such\n   archives as being corrupt and does not allow to modify them. Beginning\n   with release 5.41, Info-ZIP's UnZip contains a workaround to list AND\n   extract such archives with the correct filenames.\n   Maybe PKWARE has implemented this \"feature\" to allow extraction of their\n   \"made-by-PKZIP for Unix/Windows\" archives using old (v5.2 and earlier)\n   versions of Info-ZIP's UnZip for Unix/WinNT ??? (UnZip versions before\n   v 5.3 assumed that all archive entries were encoded in the codepage of\n   the UnZip program's host system.)\n\n - PKUNZIP 2.04g is reported to have problems with archives created on and/or\n   copied from Iomega ZIP drives (irony, eh?).\n\nKnown, current WinZip bugs/limitations:\n--------------------------------------\n\n - [16-bit version 6.1a] NT short filenames (FAT) are stored OK, but the\n   file system is always listed as NTFS.\n\n - WinZip doesn't allow 8-bit passwords, which means it cannot decrypt an\n   archive created with an 8-bit password (by PKZIP or Info-ZIP's Zip).\n\n - WinZip (at least Versions 6.3 PL1, 7.0 SR1) fails to remove old extra\n   fields when freshening existing archive entries. When updating archives\n   created by Info-ZIP's Zip that contain UT time stamp extra field blocks,\n   UnZip cannot display or restore the updated (DOS) time stamps of the\n   freshened archive members.\n\nKnown, current other third-party Zip utils bugs/limitations:\n------------------------------------------------------------\n\n - Asi's PKZip clones for Macintosh (versions 2.3 and 2.10d) are thoroughly\n   broken. They create invalid Zip archives!\n   a) For the first entry, both compressed size and uncompressed length\n      are recorded as 0, despite the fact that compressed data of non-zero\n      length has been added.\n   b) Their program creates extra fields with an (undocumented) internal\n      structure that violates the requirements of PKWARE's Zip format\n      specification document \"appnote.txt\": Their extra field seems to\n      contain pure data; the 4-byte block header consisting of block ID\n      and data length is missing.\n\nPossibly current PKZIP bugs:\n---------------------------\n\n - PKZIP (2.04g?) can silently ignore read errors on network drives, storing\n   the correct CRC and compressed length but an incorrect and inconsistent\n   uncompressed length.\n\n - PKZIP (2.04g?), when deleting files from within a zipfile on a Novell\n   drive, sometimes only zeros out the data while failing to shrink the\n   zipfile.\n\nOther limitations:\n-----------------\n\n - PKZIP 1.x and 2.x encryption has been cracked (known-plaintext approach;\n   see http://www.cryptography.com/ for details).\n\n[many other bugs in PKZIP 1.0, 1.1, 1.93a, 2.04c and 2.04e]\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/ZipPorts",
    "content": "__________________________________________________________________________\n\n  This is the Info-ZIP file ZipPorts, last updated on 17 February 1996.\n__________________________________________________________________________\n\n\nThis document defines a set of rules and guidelines for those who wish to\ncontribute patches to Zip and UnZip (or even entire ports to new operating\nsystems).  The list below is something between a style sheet and a \"Miss\nManners\" etiquette guide.  While Info-ZIP encourages contributions and\nfixes from anyone who finds something worth changing, we are also aware\nof the fact that no two programmers have the programming style and that\nunrestrained changes by a few dozen contributors would result in hideously\nugly (and unmaintainable) Frankenstein code.  So consider the following an\nattempt by the maintainers to maintain sanity as well as useful code.\n\n(The first version of this document was called either \"ZipRules\" or the\n\"No Feelthy ...\" file and was compiled by David Kirschbaum in consulta-\ntion with Mark Adler, Cave McNewt and others.  The current incarnation\nexpands upon the original with insights gained from a few more years of\nhappy hacking...)\n\n\nSummary:\n\n  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS\n(0.1) The Golden Rule:    DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE\n(0.2) The Silver Rule:    DO UNTO THE LATEST BETA CODE\n(0.3) The Bronze Rule:    NO FEELTHY PIGGYBACKS\n\n  (1) NO FEELTHY TABS\n  (2) NO FEELTHY CARRIAGE RETURNS\n  (3) NO FEELTHY 8-BIT CHARS\n  (4) NO FEELTHY LEFT-JUSTIFIED DASHES\n  (5) NO FEELTHY FANCY_FILENAMES\n  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS\n  (7) NO FEELTHY E-MAIL BINARIES\n\n\nExplanations:\n\n  (0) The Platinum Rule:  DON'T BREAK EXISTING PORTS\n\n      No doubt about it, this is the one which really pisses us off and\n      pretty much guarantees that your port or patch will be ignored and/\n      or laughed at.  Examples range from the *really* severe cases which\n      \"port\" by ripping out all of the existing multi-OS code, to more\n      subtle oopers like relying on a local capability which doesn't exist\n      on other OSes or in older compilers (e.g., the use of ANSI \"#elif\"\n      or \"#pragma\" or \"##\" constructs, C++ comments, GNU extensions, etc.).\n      As to the former, use #ifdefs for your new code (see rule 0.3).  And\n      as to the latter, trust us--there are few things we'd like better\n      than to be able to use some of the elegant \"new\" features out there\n      (many of which have been around for a decade or more).  But our code\n      still compiles on machines dating back even longer, at least in spirit\n      --e.g., the AT&T 3B1 family and Dynix/ptx.  Until we say otherwise,\n      dinosaurs are supported.\n\n\n(0.1) The Golden Rule:  DO UNTO THE CODE AS OTHERS HAVE DONE BEFORE\n\n      In other words, try to fit into the local style of programming--no\n      matter how painful it may be.  This includes cosmetic aspects like\n      indenting the same amount (both in the main C code and in the in-\n      clude files), using braces and comments similarly, NO TABS (see rule\n      #1), etc.; but also more substantive things like (for UnZip) putting\n      character strings into static (far) variables and using the LoadFar-\n      String macros to avoid overflowing limited MS-DOS data segments, and\n      using the ugly Info() macro instead of the more usual *printf()\n      functions so that dynamic-link-library ports are simpler.  NEVER put\n      single-OS code (e.g., OS/2) of more than two or three lines into the\n      main (generic) modules; those are shared by everybody, and nobody else\n      cares about it or wants to see it.\n\n      Note that not only do Zip and UnZip differ in these respects, so do\n      individual parts of each program.  While it would be nice to have\n      global consistency, cosmetic changes are not a high priority; for\n      now we'll settle for local consistency--i.e., don't make things any\n      worse than they already are.\n\n      Exception (BIG exception):  single-letter variable names.  Despite\n      the prevailing practice in much of Zip and parts of UnZip, and de-\n      spite the fact that one-letter variables allow you to pack really\n      cool, compact and complicated expressions onto one line, they also\n      make the code very difficult to maintain and are therefore *strongly*\n      discouraged.  Don't ask us who is responsible in the first place;\n      while this sort of brain damage is not uncommon among former BASIC\n      programmers, it is nevertheless a lifelong embarrassment, and we do\n      try to pity the poor sod (that is, when we're not chasing bugs and\n      cursing him).  :-)\n\n\n(0.2) The Silver Rule:  DO UNTO THE LATEST BETA CODE\n\n      Few things are as annoying as receiving a large patch which obviously\n      represents a lot of time and careful work but which is relative to\n      an old version of Info-ZIP code.  As wonderful as Larry Wall's patch\n      program is at applying context diffs to modified code, we regularly\n      make near-global changes and/or reorganize big chunks of the sources\n      (particularly in UnZip), and \"patch\" can't work miracles--big changes\n      invariably break any patch which is relative to an old version of the\n      code.\n\n      Bottom line:  contact the Info-ZIP core team FIRST (via the zip-bugs\n      e-mail address) and get up to date with the latest code before begin-\n      ning a big new port.  And try to *stay* up to date while working on\n      your port--at least, as much as possible.\n\n\n(0.3) The Bronze Rule:  NO FEELTHY PIGGYBACKS\n\n      UnZip is currently ported to something like 12 operating systems\n      (a few more or less depending on how one counts), and each of these,\n      with the possible exception of VM/CMS, has a unique macro identifying\n      it:  AMIGA, ATARI_ST, __human68k__, MACOS, MSDOS, MVS, OS2, TOPS20,\n      UNIX, VMS, WIN32.  Zip is moving in the same direction.  New ports\n      should NOT piggyback one of the existing ports unless they are sub-\n      stantially similar--for example, Minix and Coherent are basically Unix\n      and therefore are included in the UNIX macro, but DOS djgpp ports and\n      OS/2 emx ports (both of which use the Unix-originated GNU C compiler\n      and often have \"unix\" defined by default) are obviously *not* Unix.\n      [The existing MTS port is a special exception; basically only one per-\n      son knows what MTS really is, and he's not telling.  Presumably it's\n      not very close to Unix, but it's not worth arguing about it now.]\n      Along the same lines, neither OS/2 nor Human68K is the same as (or\n      even close to) MS-DOS.  MVS and VM/CMS, on the other hand, are quite\n      similar to each other and are therefore combined in most places.\n\n      Bottom line:  when adding a new port (e.g., QDOS), create a new macro\n      for it (\"QDOS\"), a new subdirectory (\"qdos\") and a new source file for\n      OS-specific code (\"qdos/qdos.c\").  Use #ifdefs to fit any OS-specific\n      changes into the existing code (e.g., unzpriv.h).  If it's close enough\n      to an existing port that piggybacking is a temptation, define a new\n      \"combination macro\" (e.g., \"CMS_MVS\") and replace the old macros as\n      required.  (This last applies to UnZip, at least; the old preference\n      in Zip was fewer macros and long #ifdef lines, so talk to Onno or Jean-\n      loup about that.)  See also rule 0.1.\n\n      (Note that, for UnZip, new ports need not attempt to deal with all\n      features.  Among other things, the wildcard-zipfile code in do_wild()\n      may be replaced with a supplied dummy version, since opendir/readdir/\n      closedir() or the equivalent can be difficult to implement.)\n\n\n  (1) NO FEELTHY TABS\n\n      Some editors and e-mail systems either have no capability to use\n      and/or display tab characters (ASCII 9) correctly, or they use non-\n      standard or variable-width tab columns, or other horrors.  Some edi-\n      tors auto-convert spaces to tabs, after which the blind use of \"diff\n      -c\" results in a huge and mostly useless patch.  Yes, *we* know about\n      diff's \"-b\" option, but not everyone does.  And yes, we also know this\n      makes the source files bigger, even after compression; so be it.  If\n      we *really* cared that much about the size of the sources, we'd still\n      be writing Unix-only utilities.\n\n      Bottom line:  use spaces, not tabs.\n\n      Exception:  some of the makefiles (the Unix one in particular) require\n      tabs as part of the syntax.\n\n      Related utility programs:\n          Unix, OS/2 and MS-DOS:  expand, unexpand.\n          MS-DOS:  Buerg's TABS; Toad Hall's TOADSOFT.\n          And some editors have the conversion built-in.\n\n\n  (2) NO FEELTHY CARRIAGE RETURNS\n\n      All source, documentation and other text files shall have Unix style\n      line endings (LF only, a.k.a. ctrl-J), not the DOS/OS2/NT CR+LF or Mac\n      CR-only line endings.\n\n      Reason:  \"real programmers\" in any environment can convert back and\n      forth between Unix and DOS/Mac style.  All PC compilers but a few old\n      Borland versions can use either Unix or MS-DOS end-of-lines.  Buerg's\n      LIST (file-display utility) for MS-DOS can use Unix or MS-DOS EOLs.\n      Both Zip and UnZip can convert line-endings as appropriate.  But Unix\n      utilities like diff and patch die a horrible death (or produce horrible\n      output) if the target files have CRs.\n\n      Related utilities:  flip for Unix, OS/2 and MS-DOS; Unix \"tr\".\n\n      Exceptions:  documentation in pre-compiled binary distributions should\n      be in the local (target) format.\n\n\n  (3) NO FEELTHY 8-BIT CHARS\n\n      Do all your editing in a plain-text ASCII editor.  No WordPerfect, MS\n      Word, WordStar document mode, or other word processor files, thenkyew.\n      No desktop publishing.  *Especially* no EBCDIC.  No TIFFs, no GIFs, no\n      embedded pictures or dancing ladies (too bad, Cave Newt).  [Sigh... -CN]\n\n      Reason:  compatibility with different consoles.  My old XT clone is\n      the most limited!\n\n      Exceptions:  some Macintosh makefiles apparently require some 8-bit\n      characters; the Human68k port uses 8-bit characters for Kanji or Kana\n      comments (I think); etc.\n\n      Related utilities:  vi, emacs, EDLIN, Turbo C editor, other programmers'\n      editors, various word processor -> text conversion utilities.\n\n\n  (4) NO FEELTHY LEFT-JUSTIFIED DASHES\n\n      Always precede repeated dashes (------) with one or more leading non-\n      dash characters:  spaces, tabs, pound signs (#), comments (/*), what-\n      ever.\n\n      Reason:  sooner or later your source file will be e-mailed through an\n      undigestifier utility, most of which treat leading dashes as end-of-\n      message separators.  We'd rather not have your code broken up into a\n      dozen separate untitled messages, thank you.\n\n\n  (5) NO FEELTHY FANCY_FILENAMES\n\n      Assume the worst:  that someone on a brain-damaged DOS system has to\n      work with everything your magic fingers produced.  Keep the filenames\n      unimaginative and within MS-DOS limits (i.e., ordinary A..Z, 1..9,\n      \"-$_!\"-type characters, in the 8.3 \"filename.ext\" format).  Mac and\n      Unix users, giggle all you want, but no spaces or multiple dots.\n\n      Reason:  compatibility with different file systems.  MS-DOS FAT is the\n      most limited, with the exception of CompuServe (6.3, argh).\n\n      Exceptions:  slightly longer names are occasionally acceptable within\n      OS-specific subdirectories, but don't do that unless there's a good\n      reason for it.\n\n\n  (6) NO FEELTHY NON-ZIPFILES AND NO FEELTHY E-MAIL BETAS\n\n      Beta testers and developers are in general expected to have both\n      ftp capability and the ability to deal with zipfiles.  Those without\n      should either find a friend who does or else learn about ftp-mailers.\n\n      Reason:  the core development team barely has time to work on the\n      code, much less prepare oddball formats and/or mail betas out (and\n      the situation is getting worse, sigh).\n\n      Exceptions:  anyone seriously proposing to do a new port will be\n      given special treatment, particularly with respect to UnZip; we\n      obviously realize that bootstrapping a completely new port can be\n      quite difficult and have no desire to make it even harder due to\n      lack of access to the latest code (rule 0.2).\n\n      Public releases of UnZip, on the other hand, will be available in\n      two formats:  .tar.Z (16-bit compress'd tar) and .zip (either \"plain\"\n      or self-extracting).  Zip sources and executables will generally only\n      be distributed in .zip format, since Zip is pretty much useless without\n      UnZip.\n\n\n  (7) NO FEELTHY E-MAIL BINARIES\n\n      Binary files (e.g., executables, test zipfiles, etc.) should NEVER\n      be mailed raw.  Where possible, they should be uploaded via ftp in\n      BINARY mode; if that's impossible, Mark's \"ship\" ASCII-encoder should\n      be used; and if that's unavailable, uuencode or xxencode should be\n      used.  Weirdo NeXTmail, mailtool and MIME formats are also Right Out.\n\n      Files larger than 50KB may need to be broken into pieces for mailing\n      (be sure to label them in order!), unless \"ship\" is used (it can\n      auto-split, label and mail files if told to do so).  If Down Under\n      is involved, files must be broken into under-20KB chunks.\n\n      Reasons:  to prevent sounds of gagging mailers from resounding through-\n      out the land.  To be relatively efficient in the binary->ASCII conver-\n      sion.  (Yeah, yeah, I know, there's better conversions out there.  But\n      not as widely known, and they often break on BITNET gateways.)\n\n      Related utilities:  ship, uuencode, uudecode, uuxfer20, quux, others.\n      Just make sure they don't leave embedded or trailing spaces (that is,\n      they should use the \"`\" character in place of ASCII 32).  Otherwise\n      mailers are prone to truncate or whatever.\n\n\nGreg Roelofs (a.k.a. Cave Newt)\nInfo-ZIP UnZip maintainer\n\nDavid Kirschbaum\nformer Info-ZIP Coordinator\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/algorith.txt",
    "content": "Zip's deflation algorithm is a variation of LZ77 (Lempel-Ziv 1977, see\nreference below). It finds duplicated strings in the input data.  The\nsecond occurrence of a string is replaced by a pointer to the previous\nstring, in the form of a pair (distance, length).  Distances are\nlimited to 32K bytes, and lengths are limited to 258 bytes. When a\nstring does not occur anywhere in the previous 32K bytes, it is\nemitted as a sequence of literal bytes.  (In this description,\n'string' must be taken as an arbitrary sequence of bytes, and is not\nrestricted to printable characters.)\n\nLiterals or match lengths are compressed with one Huffman tree, and\nmatch distances are compressed with another tree. The trees are stored\nin a compact form at the start of each block. The blocks can have any\nsize (except that the compressed data for one block must fit in\navailable memory). A block is terminated when zip determines that it\nwould be useful to start another block with fresh trees. (This is\nsomewhat similar to compress.)\n\nDuplicated strings are found using a hash table. All input strings of\nlength 3 are inserted in the hash table. A hash index is computed for\nthe next 3 bytes. If the hash chain for this index is not empty, all\nstrings in the chain are compared with the current input string, and\nthe longest match is selected.\n\nThe hash chains are searched starting with the most recent strings, to\nfavor small distances and thus take advantage of the Huffman encoding.\nThe hash chains are singly linked. There are no deletions from the\nhash chains, the algorithm simply discards matches that are too old.\n\nTo avoid a worst-case situation, very long hash chains are arbitrarily\ntruncated at a certain length, determined by a runtime option (zip -1\nto -9). So zip does not always find the longest possible match but\ngenerally finds a match which is long enough.\n\nzip also defers the selection of matches with a lazy evaluation\nmechanism. After a match of length N has been found, zip searches for a\nlonger match at the next input byte. If a longer match is found, the\nprevious match is truncated to a length of one (thus producing a single\nliteral byte) and the longer match is emitted afterwards.  Otherwise,\nthe original match is kept, and the next match search is attempted only\nN steps later.\n\nThe lazy match evaluation is also subject to a runtime parameter. If\nthe current match is long enough, zip reduces the search for a longer\nmatch, thus speeding up the whole process. If compression ratio is more\nimportant than speed, zip attempts a complete second search even if\nthe first match is already long enough.\n\nThe lazy match evaluation is not performed for the fastest compression\nmodes (speed options -1 to -3). For these fast modes, new strings\nare inserted in the hash table only when no match was found, or\nwhen the match is not too long. This degrades the compression ratio\nbut saves time since there are both fewer insertions and fewer searches.\n\nJean-loup Gailly\njloup@chorus.fr\n\nReferences:\n\n[LZ77] Ziv J., Lempel A., \"A Universal Algorithm for Sequential Data\nCompression\", IEEE Transactions on Information Theory\", Vol. 23, No. 3,\npp. 337-343.\n\nAPPNOTE.TXT documentation file in PKZIP 1.93a. It is available by\nftp in ftp.cso.uiuc.edu:/pc/exec-pc/pkz193a.exe [128.174.5.59]\n\n'Deflate' Compressed Data Format Specification:\nftp://ftp.uu.net/pub/archiving/zip/doc/deflate-1.1.doc\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/ebcdic.msg",
    "content": "From dima@mitrah.ru  Mon Nov 10 02:25:38 2003\nReturn-Path: <dima@mitrah.ru>\nReceived: from b.mx.sonic.net (eth0.b.mx.sonic.net [209.204.159.4])\n\tby eth0.a.lds.sonic.net (8.12.10/8.12.9) with ESMTP id hAAAPccT025257\n\tfor <roelofs@lds.sonic.net>; Mon, 10 Nov 2003 02:25:38 -0800\nReceived: from icicle.pobox.com (icicle.pobox.com [207.8.214.2])\n\tby b.mx.sonic.net (8.12.10/8.12.7) with ESMTP id hAAAPar9007141\n\tfor <roelofs@sonic.net>; Mon, 10 Nov 2003 02:25:37 -0800\nReceived: from icicle.pobox.com (localhost[127.0.0.1])\n\tby icicle.pobox.com (Postfix) with ESMTP id 9BA347A96B\n\tfor <roelofs@sonic.net>; Sat,  8 Nov 2003 06:15:13 -0500 (EST)\nDelivered-To: newt@pobox.com\nReceived: from mail.ropnet.ru (mail.ropnet.ru[212.42.37.90])\n\tby icicle.pobox.com (Postfix) with ESMTP id A96817A8F7\n\tfor <newt@pobox.com>; Sat,  8 Nov 2003 06:15:04 -0500 (EST)\nReceived: from d34-67.ropnet.ru (d34-67.ropnet.ru [212.42.34.67])\n\tby mail.ropnet.ru (8.11.7/8.11.7) with ESMTP id hA8BEjF76200\n\tfor <newt@pobox.com>; Sat, 8 Nov 2003 14:14:46 +0300 (MSK)\nResent-Date: Sat, 8 Nov 2003 14:14:46 +0300 (MSK)\nResent-Message-Id: <200311081114.hA8BEjF76200@mail.ropnet.ru>\nDate: Sat, 8 Nov 2003 14:18:18 +0300\nFrom: Dmitri Koulikov <dima@mitrah.ru>\nX-Mailer: The Bat! (v1.62r) Personal\nReply-To: Dmitri Koulikov <dima@mitrah.ru>\nX-Priority: 3 (Normal)\nMessage-ID: <815640011.20031108141818@mitrah.ru>\nTo: newt@pobox.com\nSubject: unzip and zip lack NLS - 2\nResent-From: Dmitri Koulikov <dima@mitrah.ru>\nMIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"----------EB1581C42AB86662\"\nStatus: R\n\n------------EB1581C42AB86662\nContent-Type: text/plain; charset=us-ascii\nContent-Transfer-Encoding: 7bit\n\nHello Greg Roelofs,\n\n   By mistake I sent you wrong version of ebcdic.h. Now it is as it\nhave to.\n   Additionally I found that zip works with Russian filenames good.\nBut fails to process -D switch. So I have to chahge zipfile.c. Most\nprobably this is not good but it works.\n\n-- \nBest regards,\n Dmitri \n\nmailto:dima@mitrah.ru\n------------EB1581C42AB86662\nContent-Type: application/octet-stream; name=\"ebcdic.h\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; filename=\"ebcdic.h\"\n\n------------EB1581C42AB86662\nContent-Type: application/octet-stream; name=\"zipfile.c\"\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; filename=\"zipfile.c\"\n\n------------EB1581C42AB86662--\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/extrafld.txt",
    "content": "The following are the known types of zipfile extra fields as of this\nwriting.  Extra fields are documented in PKWARE's appnote.txt and are\nintended to allow for backward- and forward-compatible extensions to\nthe zipfile format.  Multiple extra-field types may be chained together,\nprovided that the total length of all extra-field data is less than 64KB.\n(In fact, PKWARE requires that the total length of the entire file header,\nincluding timestamp, file attributes, filename, comment, extra field, etc.,\nbe no more than 64KB.)\n\nEach extra-field type (or subblock) must contain a four-byte header con-\nsisting of a two-byte header ID and a two-byte length (little-endian) for\nthe remaining data in the subblock.  If there are additional subblocks\nwithin the extra field, the header for each one will appear immediately\nfollowing the data for the previous subblock (i.e., with no padding for\nalignment).\n\nAll integer fields in the descriptions below are in little-endian (Intel)\nformat unless otherwise specified.  Note that \"Short\" means two bytes,\n\"Long\" means four bytes, and \"Long-Long\" means eight bytes, regardless\nof their native sizes.  Unless specifically noted, all integer fields should\nbe interpreted as unsigned (non-negative) numbers.\n\nChristian Spieler, 20010517\n\nUpdated to include the Unicode extra fields.  Added new Unix extra field.\n\nEd Gordon, 20060819, 20070607, 20070909, 20080426, 20080509\n\n                        -------------------------\n\n          Header ID's of 0 thru 31 are reserved for use by PKWARE.\n          The remaining ID's can be used by third party vendors for\n          proprietary usage.\n\n          The current Header ID mappings defined by PKWARE are:\n\n          0x0001        ZIP64 extended information extra field\n          0x0007        AV Info\n          0x0009        OS/2 extended attributes      (also Info-ZIP)\n          0x000a        NTFS (Win9x/WinNT FileTimes)\n          0x000c        OpenVMS                       (also Info-ZIP)\n          0x000d        Unix\n          0x000f        Patch Descriptor\n          0x0014        PKCS#7 Store for X.509 Certificates\n          0x0015        X.509 Certificate ID and Signature for\n                        individual file\n          0x0016        X.509 Certificate ID for Central Directory\n\n          The Header ID mappings defined by Info-ZIP and third parties are:\n\n          0x0065        IBM S/390 attributes - uncompressed\n          0x0066        IBM S/390 attributes - compressed\n          0x07c8        Info-ZIP Macintosh (old, J. Lee)\n          0x2605        ZipIt Macintosh (first version)\n          0x2705        ZipIt Macintosh v 1.3.5 and newer (w/o full filename)\n          0x334d        Info-ZIP Macintosh (new, D. Haase's 'Mac3' field )\n          0x4154        Tandem NSK\n          0x4341        Acorn/SparkFS (David Pilling)\n          0x4453        Windows NT security descriptor (binary ACL)\n          0x4704        VM/CMS\n          0x470f        MVS\n          0x4854        Theos, old inofficial port\n          0x4b46        FWKCS MD5 (see below)\n          0x4c41        OS/2 access control list (text ACL)\n          0x4d49        Info-ZIP OpenVMS (obsolete)\n          0x4d63        Macintosh SmartZIP, by Macro Bambini\n          0x4f4c        Xceed original location extra field\n          0x5356        AOS/VS (binary ACL)\n          0x5455        extended timestamp\n          0x5855        Info-ZIP Unix (original; also OS/2, NT, etc.)\n          0x554e        Xceed unicode extra field\n          0x6375        Info-ZIP Unicode Comment\n          0x6542        BeOS (BeBox, PowerMac, etc.)\n          0x6854        Theos\n          0x7075        Info-ZIP Unicode Path\n          0x756e        ASi Unix\n          0x7855        Info-ZIP Unix (previous new)\n          0x7875        Info-ZIP Unix (new)\n          0xfb4a        SMS/QDOS\n\nThe following are detailed descriptions of the known extra-field block types:\n\n         -OS/2 Extended Attributes Extra Field:\n          ====================================\n\n          The following is the layout of the OS/2 extended attributes \"extra\"\n          block.  (Last Revision 19960922)\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (OS/2)  0x0009        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed EA data size\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed EA data\n          (var.)        variable    compressed EA data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (OS/2)  0x0009        Short       tag for this extra block type\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local EA data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n\n          The OS/2 extended attribute structure (FEA2LIST) is compressed and\n          then stored in its entirety within this structure.  There will only\n          ever be one block of data in the variable-length field.\n\n\n         -OS/2 Access Control List Extra Field:\n          ====================================\n\n          The following is the layout of the OS/2 ACL extra block.\n          (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (ACL)   0x4c41        Short       tag for this extra block type (\"AL\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed ACL data size\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed ACL data\n          (var.)        variable    compressed ACL data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (ACL)   0x4c41        Short       tag for this extra block type (\"AL\")\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local ACL data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n\n          The uncompressed ACL data consist of a text header of the form\n          \"ACL1:%hX,%hd\\n\", where the first field is the OS/2 ACCINFO acc_attr\n          member and the second is acc_count, followed by acc_count strings\n          of the form \"%s,%hx\\n\", where the first field is acl_ugname (user\n          group name) and the second acl_access.  This block type will be\n          extended for other operating systems as needed.\n\n\n         -Windows NT Security Descriptor Extra Field:\n          ==========================================\n\n          The following is the layout of the NT Security Descriptor (another\n          type of ACL) extra block.  (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (SD)    0x4453        Short       tag for this extra block type (\"SD\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed SD data size\n          Version       Byte        version of uncompressed SD data format\n          CType         Short       compression type\n          EACRC         Long        CRC value for uncompressed SD data\n          (var.)        variable    compressed SD data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (SD)    0x4453        Short       tag for this extra block type (\"SD\")\n          TSize         Short       total data size for this block (4)\n          BSize         Long        size of uncompressed local SD data\n\n          The value of CType is interpreted according to the \"compression\n          method\" section above; i.e., 0 for stored, 8 for deflated, etc.\n          Version specifies how the compressed data are to be interpreted\n          and allows for future expansion of this extra field type.  Currently\n          only version 0 is defined.\n\n          For version 0, the compressed data are to be interpreted as a single\n          valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative\n          format.\n\n\n         -PKWARE Win95/WinNT Extra Field:\n          ==============================\n\n          The following description covers PKWARE's \"NTFS\" attributes\n          \"extra\" block, introduced with the release of PKZIP 2.50 for\n          Windows. (Last Revision 20001118)\n\n          (Note: At this time the Mtime, Atime and Ctime values may\n          be used on any WIN32 system.)\n         [Info-ZIP note: In the current implementations, this field has\n          a fixed total data size of 32 bytes and is only stored as local\n          extra field.]\n\n          Value         Size        Description\n          -----         ----        -----------\n  (NTFS)  0x000a        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          Reserved      Long        for future use\n          Tag1          Short       NTFS attribute tag value #1\n          Size1         Short       Size of attribute #1, in bytes\n          (var.)        SubSize1    Attribute #1 data\n          .\n          .\n          .\n          TagN          Short       NTFS attribute tag value #N\n          SizeN         Short       Size of attribute #N, in bytes\n          (var.)        SubSize1    Attribute #N data\n\n          For NTFS, values for Tag1 through TagN are as follows:\n          (currently only one set of attributes is defined for NTFS)\n\n          Tag        Size       Description\n          -----      ----       -----------\n          0x0001     2 bytes    Tag for attribute #1\n          Size1      2 bytes    Size of attribute #1, in bytes (24)\n          Mtime      8 bytes    64-bit NTFS file last modification time\n          Atime      8 bytes    64-bit NTFS file last access time\n          Ctime      8 bytes    64-bit NTFS file creation time\n\n          The total length for this block is 28 bytes, resulting in a\n          fixed size value of 32 for the TSize field of the NTFS block.\n\n          The NTFS filetimes are 64-bit unsigned integers, stored in Intel\n          (least significant byte first) byte order. They determine the\n          number of 1.0E-07 seconds (1/10th microseconds!) past WinNT \"epoch\",\n          which is \"01-Jan-1601 00:00:00 UTC\".\n\n\n         -PKWARE OpenVMS Extra Field:\n          ==========================\n\n          The following is the layout of PKWARE's OpenVMS attributes \"extra\"\n          block.  (Last Revision 12/17/91)\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (VMS)   0x000c        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          CRC           Long        32-bit CRC for remainder of the block\n          Tag1          Short       OpenVMS attribute tag value #1\n          Size1         Short       Size of attribute #1, in bytes\n          (var.)        Size1       Attribute #1 data\n          .\n          .\n          .\n          TagN          Short       OpenVMS attribute tage value #N\n          SizeN         Short       Size of attribute #N, in bytes\n          (var.)        SizeN       Attribute #N data\n\n          Rules:\n\n          1. There will be one or more of attributes present, which\n             will each be preceded by the above TagX & SizeX values.\n             These values are identical to the ATR$C_XXXX and\n             ATR$S_XXXX constants which are defined in ATR.H under\n             OpenVMS C.  Neither of these values will ever be zero.\n\n          2. No word alignment or padding is performed.\n\n          3. A well-behaved PKZIP/OpenVMS program should never produce\n             more than one sub-block with the same TagX value.  Also,\n             there will never be more than one \"extra\" block of type\n             0x000c in a particular directory record.\n\n\n         -Info-ZIP VMS Extra Field:\n          ========================\n\n          The following is the layout of Info-ZIP's VMS attributes extra\n          block for VAX or Alpha AXP.  The local-header and central-header\n          versions are identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (VMS2)  0x4d49        Short       tag for this extra block type (\"JM\")\n          TSize         Short       total data size for this block\n          ID            Long        block ID\n          Flags         Short       info bytes\n          BSize         Short       uncompressed block size\n          Reserved      Long        (reserved)\n          (var.)        variable    compressed VMS file-attributes block\n\n          The block ID is one of the following unterminated strings:\n\n                \"VFAB\"          struct FAB\n                \"VALL\"          struct XABALL\n                \"VFHC\"          struct XABFHC\n                \"VDAT\"          struct XABDAT\n                \"VRDT\"          struct XABRDT\n                \"VPRO\"          struct XABPRO\n                \"VKEY\"          struct XABKEY\n                \"VMSV\"          version (e.g., \"V6.1\"; truncated at hyphen)\n                \"VNAM\"          reserved\n\n          The lower three bits of Flags indicate the compression method.  The\n          currently defined methods are:\n\n                0       stored (not compressed)\n                1       simple \"RLE\"\n                2       deflated\n\n          The \"RLE\" method simply replaces zero-valued bytes with zero-valued\n          bits and non-zero-valued bytes with a \"1\" bit followed by the byte\n          value.\n\n          The variable-length compressed data contains only the data corre-\n          sponding to the indicated structure or string.  Typically multiple\n          VMS2 extra fields are present (each with a unique block type).\n\n\n         -Info-ZIP Macintosh Extra Field:\n          ==============================\n\n          The following is the layout of the (old) Info-ZIP resource-fork extra\n          block for Macintosh.  The local-header and central-header versions\n          are identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac)   0x07c8        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          \"JLEE\"        beLong      extra-field signature\n          FInfo         16 bytes    Macintosh FInfo structure\n          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat\n          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat\n          Flags         beLong      info bits\n          DirID         beLong      HParamBlockRec fileParam.ioDirID\n          VolName       28 bytes    volume name (optional)\n\n          All fields but the first two are in native Macintosh format\n          (big-endian Motorola order, not little-endian Intel).  The least\n          significant bit of Flags is 1 if the file is a data fork, 0 other-\n          wise.  In addition, if this extra field is present, the filename\n          has an extra 'd' or 'r' appended to indicate data fork or resource\n          fork.  The 28-byte VolName field may be omitted.\n\n\n         -ZipIt Macintosh Extra Field (long):\n          ==================================\n\n          The following is the layout of the ZipIt extra block for Macintosh.\n          The local-header and central-header versions are identical.\n          (Last Revision 19970130)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac2)  0x2605        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          \"ZPIT\"        beLong      extra-field signature\n          FnLen         Byte        length of FileName\n          FileName      variable    full Macintosh filename\n          FileType      Byte[4]     four-byte Mac file type string\n          Creator       Byte[4]     four-byte Mac creator string\n\n\n         -ZipIt Macintosh Extra Field (short):\n          ===================================\n\n          The following is the layout of a shortened variant of the\n          ZipIt extra block for Macintosh (without \"full name\" entry).\n          This variant is used by ZipIt 1.3.5 and newer for entries that\n          do not need a \"full Mac filename\" record.\n          The local-header and central-header versions are identical.\n          (Last Revision 19980903)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac2b) 0x2705        Short       tag for this extra block type\n          TSize         Short       total data size for this block (12)\n          \"ZPIT\"        beLong      extra-field signature\n          FileType      Byte[4]     four-byte Mac file type string\n          Creator       Byte[4]     four-byte Mac creator string\n\n\n         -Info-ZIP Macintosh Extra Field (new):\n          ====================================\n\n          The following is the layout of the (new) Info-ZIP extra\n          block for Macintosh, designed by Dirk Haase.\n          All values are in little-endian.\n          (Last Revision 19981005)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac3)  0x334d        Short       tag for this extra block type (\"M3\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed finder attribute data size\n          Flags         Short       info bits\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n          (CType)       Short       compression type\n          (CRC)         Long        CRC value for uncompressed MacOS data\n          Attribs       variable    finder attribute data (see below)\n\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Mac3)  0x334d        Short       tag for this extra block type (\"M3\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed finder attribute data size\n          Flags         Short       info bits\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n\n          The third bit of Flags in both headers indicates whether\n          the LOCAL extra field is uncompressed (and therefore whether CType\n          and CRC are omitted):\n\n          Bits of the Flags:\n              bit 0           if set, file is a data fork; otherwise unset\n              bit 1           if set, filename will be not changed\n              bit 2           if set, Attribs is uncompressed (no CType, CRC)\n              bit 3           if set, date and times are in 64 bit\n                              if zero date and times are in 32 bit.\n              bit 4           if set, timezone offsets fields for the native\n                              Mac times are omitted (UTC support deactivated)\n              bits 5-15       reserved;\n\n\n          Attributes:\n\n          Attribs is a Mac-specific block of data in little-endian format with\n          the following structure (if compressed, uncompress it first):\n\n          Value         Size        Description\n          -----         ----        -----------\n          fdFlags       Short       Finder Flags\n          fdLocation.v  Short       Finder Icon Location\n          fdLocation.h  Short       Finder Icon Location\n          fdFldr        Short       Folder containing file\n\n          FXInfo        16 bytes    Macintosh FXInfo structure\n            FXInfo-Structure:\n                fdIconID        Short\n                fdUnused[3]     Short       unused but reserved 6 bytes\n                fdScript        Byte        Script flag and number\n                fdXFlags        Byte        More flag bits\n                fdComment       Short       Comment ID\n                fdPutAway       Long        Home Dir ID\n\n          FVersNum      Byte        file version number\n                                    may be not used by MacOS\n          ACUser        Byte        directory access rights\n\n          FlCrDat       ULong       date and time of creation\n          FlMdDat       ULong       date and time of last modification\n          FlBkDat       ULong       date and time of last backup\n            These time numbers are original Mac FileTime values (local time!).\n            Currently, date-time width is 32-bit, but future version may\n            support be 64-bit times (see flags)\n\n          CrGMTOffs     Long(signed!)   difference \"local Creat. time - UTC\"\n          MdGMTOffs     Long(signed!)   difference \"local Modif. time - UTC\"\n          BkGMTOffs     Long(signed!)   difference \"local Backup time - UTC\"\n            These \"local time - UTC\" differences (stored in seconds) may be\n            used to support timestamp adjustment after inter-timezone transfer.\n            These fields are optional; bit 4 of the flags word controls their\n            presence.\n\n          Charset       Short       TextEncodingBase (Charset)\n                                    valid for the following two fields\n\n          FullPath      variable    Path of the current file.\n                                    Zero terminated string (C-String)\n                                    Currently coded in the native Charset.\n\n          Comment       variable    Finder Comment of the current file.\n                                    Zero terminated string (C-String)\n                                    Currently coded in the native Charset.\n\n\n         -SmartZIP Macintosh Extra Field:\n          ====================================\n\n          The following is the layout of the SmartZIP extra\n          block for Macintosh, designed by Marco Bambini.\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n          0x4d63        Short       tag for this extra block type (\"cM\")\n          TSize         Short       total data size for this block (64)\n          \"dZip\"        beLong      extra-field signature\n          fdType        Byte[4]     Type of the File (4-byte string)\n          fdCreator     Byte[4]     Creator of the File (4-byte string)\n          fdFlags       beShort     Finder Flags\n          fdLocation.v  beShort     Finder Icon Location\n          fdLocation.h  beShort     Finder Icon Location\n          fdFldr        beShort     Folder containing file\n          CrDat         beLong      HParamBlockRec fileParam.ioFlCrDat\n          MdDat         beLong      HParamBlockRec fileParam.ioFlMdDat\n          frScroll.v    Byte        vertical pos. of folder's scroll bar\n          fdScript      Byte        Script flag and number\n          frScroll.h    Byte        horizontal pos. of folder's scroll bar\n          fdXFlags      Byte        More flag bits\n          FileName      Byte[32]    full Macintosh filename (pascal string)\n\n          All fields but the first two are in native Macintosh format\n          (big-endian Motorola order, not little-endian Intel).\n          The extra field size is fixed to 64 bytes.\n          The local-header and central-header versions are identical.\n\n\n         -Acorn SparkFS Extra Field:\n          =========================\n\n          The following is the layout of David Pilling's SparkFS extra block\n          for Acorn RISC OS.  The local-header and central-header versions are\n          identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Acorn) 0x4341        Short       tag for this extra block type (\"AC\")\n          TSize         Short       total data size for this block (20)\n          \"ARC0\"        Long        extra-field signature\n          LoadAddr      Long        load address or file type\n          ExecAddr      Long        exec address\n          Attr          Long        file permissions\n          Zero          Long        reserved; always zero\n\n          The following bits of Attr are associated with the given file\n          permissions:\n\n                bit 0           user-writable ('W')\n                bit 1           user-readable ('R')\n                bit 2           reserved\n                bit 3           locked ('L')\n                bit 4           publicly writable ('w')\n                bit 5           publicly readable ('r')\n                bit 6           reserved\n                bit 7           reserved\n\n\n         -VM/CMS Extra Field:\n          ==================\n\n          The following is the layout of the file-attributes extra block for\n          VM/CMS.  The local-header and central-header versions are\n          identical.  (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n (VM/CMS) 0x4704        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          flData        variable    file attributes data\n\n          flData is an uncompressed fldata_t struct.\n\n\n         -MVS Extra Field:\n          ===============\n\n          The following is the layout of the file-attributes extra block for\n          MVS.  The local-header and central-header versions are identical.\n          (Last Revision 19960922)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (MVS)   0x470f        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          flData        variable    file attributes data\n\n          flData is an uncompressed fldata_t struct.\n\n\n         -PKWARE Unix Extra Field:\n          ========================\n\n          The following is the layout of PKWARE's Unix \"extra\" block.\n          It was introduced with the release of PKZIP for Unix 2.50.\n          Note: all fields are stored in Intel low-byte/high-byte order.\n          (Last Revision 19980901)\n\n          This field has a minimum data size of 12 bytes and is only stored\n          as local extra field.\n\n          Value         Size        Description\n          -----         ----        -----------\n (Unix0)  0x000d        Short       Tag for this \"extra\" block type\n          TSize         Short       Total Data Size for this block\n          AcTime        Long        time of last access (UTC/GMT)\n          ModTime       Long        time of last modification (UTC/GMT)\n          UID           Short       Unix user ID\n          GID           Short       Unix group ID\n          (var)         variable    Variable length data field\n\n          The variable length data field will contain file type\n          specific data.  Currently the only values allowed are\n          the original \"linked to\" file names for hard or symbolic\n          links, and the major and minor device node numbers for\n          character and block device nodes.  Since device nodes\n          cannot be either symbolic or hard links, only one set of\n          variable length data is stored.  Link files will have the\n          name of the original file stored.  This name is NOT NULL\n          terminated.  Its size can be determined by checking TSize -\n          12.  Device entries will have eight bytes stored as two 4\n          byte entries (in little-endian format).  The first entry\n          will be the major device number, and the second the minor\n          device number.\n\n         [Info-ZIP note: The fixed part of this field has the same layout as\n          Info-ZIP's abandoned \"Unix1 timestamps & owner ID info\" extra field;\n          only the two tag bytes are different.]\n\n\n         -PATCH Descriptor Extra Field:\n          ============================\n\n          The following is the layout of the Patch Descriptor \"extra\"\n          block.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Patch) 0x000f        Short       Tag for this \"extra\" block type\n          TSize         Short       Size of the total \"extra\" block\n          Version       Short       Version of the descriptor\n          Flags         Long        Actions and reactions (see below)\n          OldSize       Long        Size of the file about to be patched\n          OldCRC        Long        32-bit CRC of the file about to be patched\n          NewSize       Long        Size of the resulting file\n          NewCRC        Long        32-bit CRC of the resulting file\n\n\n          Actions and reactions\n\n          Bits          Description\n          ----          ----------------\n          0             Use for autodetection\n          1             Treat as selfpatch\n          2-3           RESERVED\n          4-5           Action (see below)\n          6-7           RESERVED\n          8-9           Reaction (see below) to absent file\n          10-11         Reaction (see below) to newer file\n          12-13         Reaction (see below) to unknown file\n          14-15         RESERVED\n          16-31         RESERVED\n\n          Actions\n\n          Action       Value\n          ------       -----\n          none         0\n          add          1\n          delete       2\n          patch        3\n\n          Reactions\n\n          Reaction     Value\n          --------     -----\n          ask          0\n          skip         1\n          ignore       2\n          fail         3\n\n\n         -PKCS#7 Store for X.509 Certificates:\n          ===================================\n\n          This field is contains the information about each\n          certificate a file is signed with.  This field should only\n          appear in the first central directory record, and will be\n          ignored in any other record.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Store) 0x0014        2 bytes     Tag for this \"extra\" block type\n          SSize         2 bytes     Size of the store data\n          SData         (variable)  Data about the store\n\n          SData\n          Value         Size        Description\n          -----         ----        -----------\n          Version       2 bytes     Version number, 0x0001 for now\n          StoreD        (variable)  Actual store data\n\n          The StoreD member is suitable for passing as the pbData\n          member of a CRYPT_DATA_BLOB to the CertOpenStore() function\n          in Microsoft's CryptoAPI.  The SSize member above will be\n          cbData + 6, where cbData is the cbData member of the same\n          CRYPT_DATA_BLOB.  The encoding type to pass to\n          CertOpenStore() should be\n          PKCS_7_ANS_ENCODING | X509_ASN_ENCODING.\n\n\n         -X.509 Certificate ID and Signature for individual file:\n          ======================================================\n\n          This field contains the information about which certificate\n          in the PKCS#7 Store was used to sign the particular file.\n          It also contains the signature data.  This field can appear\n          multiple times, but can only appear once per certificate.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (CID)   0x0015        2 bytes     Tag for this \"extra\" block type\n          CSize         2 bytes     Size of Method\n          Method        (variable)\n\n          Method\n          Value         Size        Description\n          -----         ----        -----------\n          Version       2 bytes     Version number, for now 0x0001\n          AlgID         2 bytes     Algorithm ID used for signing\n          IDSize        2 bytes     Size of Certificate ID data\n          CertID        (variable)  Certificate ID data\n          SigSize       2 bytes     Size of Signature data\n          Sig           (variable)  Signature data\n\n          CertID\n          Value         Size        Description\n          -----         ----        -----------\n          Size1         4 bytes     Size of CertID, should be (IDSize - 4)\n          Size1         4 bytes     A bug in version one causes this value\n                                    to appear twice.\n          IssSize       4 bytes     Issuer data size\n          Issuer        (variable)  Issuer data\n          SerSize       4 bytes     Serial Number size\n          Serial        (variable)  Serial Number data\n\n          The Issuer and IssSize members are suitable for creating a\n          CRYPT_DATA_BLOB to be the Issuer member of a CERT_INFO\n          struct. The Serial and SerSize members would be the\n          SerialNumber member of the same CERT_INFO struct.  This\n          struct would be used to find the certificate in the store\n          the file was signed with.  Those structures are from the MS\n          CryptoAPI.\n\n          Sig and SigSize are the actual signature data and size\n          generated by signing the file with the MS CryptoAPI using a\n          hash created with the given AlgID.\n\n\n         -X.509 Certificate ID and Signature for central directory:\n          ========================================================\n\n          This field contains the information about which certificate\n          in the PKCS#7 Store was used to sign the central directory.\n          It should only appear with the first central directory\n          record, along with the store.  The data structure is the\n          same as the CID, except that SigSize will be 0, and there\n          will be no Sig member.\n\n          This field is also kept after the last central directory\n          record, as the signature data (ID 0x05054b50, it looks like\n          a central directory record of a different type).  This\n          second copy of the data is the Signature Data member of the\n          record, and will have a SigSize that is non-zero, and will\n          have Sig data.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value         Size        Description\n          -----         ----        -----------\n  (CDID)  0x0016        2 bytes     Tag for this \"extra\" block type\n          CSize         2 bytes     Size of Method\n          Method       (variable)\n\n\n         -ZIP64 Extended Information Extra Field:\n          ======================================\n\n          The following is the layout of the ZIP64 extended\n          information \"extra\" block. If one of the size or\n          offset fields in the Local or Central directory\n          record is too small to hold the required data,\n          a ZIP64 extended information record is created.\n          The order of the fields in the ZIP64 extended\n          information record is fixed, but the fields will\n          only appear if the corresponding Local or Central\n          directory record field is set to 0xFFFF or 0xFFFFFFFF.\n\n          Note: all fields stored in Intel low-byte/high-byte order.\n\n          Value      Size       Description\n          -----      ----       -----------\n  (ZIP64) 0x0001     2 bytes    Tag for this \"extra\" block type\n          Size       2 bytes    Size of this \"extra\" block\n          Original\n          Size       8 bytes    Original uncompresseed file size\n          Compressed\n          Size       8 bytes    Size of compressed data\n          Relative Header\n          Offset     8 bytes    Offset of local header record\n          Disk Start\n          Number     4 bytes    Number of the disk on which\n                                this file starts\n\n          This entry in the Local header must include BOTH original\n          and compressed file sizes.\n\n\n         -Extended Timestamp Extra Field:\n          ==============================\n\n          The following is the layout of the extended-timestamp extra block.\n          (Last Revision 19970118)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (time)  0x5455        Short       tag for this extra block type (\"UT\")\n          TSize         Short       total data size for this block\n          Flags         Byte        info bits\n          (ModTime)     Long        time of last modification (UTC/GMT)\n          (AcTime)      Long        time of last access (UTC/GMT)\n          (CrTime)      Long        time of original creation (UTC/GMT)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (time)  0x5455        Short       tag for this extra block type (\"UT\")\n          TSize         Short       total data size for this block\n          Flags         Byte        info bits (refers to local header!)\n          (ModTime)     Long        time of last modification (UTC/GMT)\n\n          The central-header extra field contains the modification time only,\n          or no timestamp at all.  TSize is used to flag its presence or\n          absence.  But note:\n\n              If \"Flags\" indicates that Modtime is present in the local header\n              field, it MUST be present in the central header field, too!\n              This correspondence is required because the modification time\n              value may be used to support trans-timezone freshening and\n              updating operations with zip archives.\n\n          The time values are in standard Unix signed-long format, indicating\n          the number of seconds since 1 January 1970 00:00:00.  The times\n          are relative to Coordinated Universal Time (UTC), also sometimes\n          referred to as Greenwich Mean Time (GMT).  To convert to local time,\n          the software must know the local timezone offset from UTC/GMT.\n\n          The lower three bits of Flags in both headers indicate which time-\n          stamps are present in the LOCAL extra field:\n\n                bit 0           if set, modification time is present\n                bit 1           if set, access time is present\n                bit 2           if set, creation time is present\n                bits 3-7        reserved for additional timestamps; not set\n\n          Those times that are present will appear in the order indicated, but\n          any combination of times may be omitted.  (Creation time may be\n          present without access time, for example.)  TSize should equal\n          (1 + 4*(number of set bits in Flags)), as the block is currently\n          defined.  Other timestamps may be added in the future.\n\n\n         -Info-ZIP Unix Extra Field (type 1):\n          ==================================\n\n          The following is the layout of the old Info-ZIP extra block for\n          Unix.  It has been replaced by the extended-timestamp extra block\n          (0x5455) and the Unix type 2 extra block (0x7855).\n          (Last Revision 19970118)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix1) 0x5855        Short       tag for this extra block type (\"UX\")\n          TSize         Short       total data size for this block\n          AcTime        Long        time of last access (UTC/GMT)\n          ModTime       Long        time of last modification (UTC/GMT)\n          UID           Short       Unix user ID (optional)\n          GID           Short       Unix group ID (optional)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix1) 0x5855        Short       tag for this extra block type (\"UX\")\n          TSize         Short       total data size for this block\n          AcTime        Long        time of last access (GMT/UTC)\n          ModTime       Long        time of last modification (GMT/UTC)\n\n          The file access and modification times are in standard Unix signed-\n          long format, indicating the number of seconds since 1 January 1970\n          00:00:00.  The times are relative to Coordinated Universal Time\n          (UTC), also sometimes referred to as Greenwich Mean Time (GMT).  To\n          convert to local time, the software must know the local timezone\n          offset from UTC/GMT.  The modification time may be used by non-Unix\n          systems to support inter-timezone freshening and updating of zip\n          archives.\n\n          The local-header extra block may optionally contain UID and GID\n          info for the file.  The local-header TSize value is the only\n          indication of this.  Note that Unix UIDs and GIDs are usually\n          specific to a particular machine, and they generally require root\n          access to restore.\n\n          This extra field type is obsolete, but it has been in use since\n          mid-1994.  Therefore future archiving software should continue to\n          support it.  Some guidelines:\n\n              An archive member should either contain the old \"Unix1\"\n              extra field block or the new extra field types \"time\" and/or\n              \"Unix2\".\n\n              If both the old \"Unix1\" block type and one or both of the new\n              block types \"time\" and \"Unix2\" are found, the \"Unix1\" block\n              should be considered invalid and ignored.\n\n              Unarchiving software should recognize both old and new extra\n              field block types, but the info from new types overrides the\n              old \"Unix1\" field.\n\n              Archiving software should recognize \"Unix1\" extra fields for\n              timestamp comparison but never create it for updated, freshened\n              or new archive members.  When copying existing members to a new\n              archive, any \"Unix1\" extra field blocks should be converted to\n              the new \"time\" and/or \"Unix2\" types.\n\n\n         -Info-ZIP Unix Extra Field (type 2):\n          ==================================\n\n          The following is the layout of the new Info-ZIP extra block for\n          Unix.  (Last Revision 19960922)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix2) 0x7855        Short       tag for this extra block type (\"Ux\")\n          TSize         Short       total data size for this block (4)\n          UID           Short       Unix user ID\n          GID           Short       Unix group ID\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix2) 0x7855        Short       tag for this extra block type (\"Ux\")\n          TSize         Short       total data size for this block (0)\n\n          The data size of the central-header version is zero; it is used\n          solely as a flag that UID/GID info is present in the local-header\n          extra field.  If additional fields are ever added to the local\n          version, the central version may be extended to indicate this.\n\n          Note that Unix UIDs and GIDs are usually specific to a particular\n          machine, and they generally require root access to restore.\n\n\n         -ASi Unix Extra Field:\n          ====================\n\n          The following is the layout of the ASi extra block for Unix.  The\n          local-header and central-header versions are identical.\n          (Last Revision 19960916)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Unix3) 0x756e        Short       tag for this extra block type (\"nu\")\n          TSize         Short       total data size for this block\n          CRC           Long        CRC-32 of the remaining data\n          Mode          Short       file permissions\n          SizDev        Long        symlink'd size OR major/minor dev num\n          UID           Short       user ID\n          GID           Short       group ID\n          (var.)        variable    symbolic link filename\n\n          Mode is the standard Unix st_mode field from struct stat, containing\n          user/group/other permissions, setuid/setgid and symlink info, etc.\n\n          If Mode indicates that this file is a symbolic link, SizDev is the\n          size of the file to which the link points.  Otherwise, if the file\n          is a device, SizDev contains the standard Unix st_rdev field from\n          struct stat (includes the major and minor numbers of the device).\n          SizDev is undefined in other cases.\n\n          If Mode indicates that the file is a symbolic link, the final field\n          will be the name of the file to which the link points.  The file-\n          name length can be inferred from TSize.\n\n          [Note that TSize may incorrectly refer to the data size not counting\n           the CRC; i.e., it may be four bytes too small.]\n\n\n         -BeOS Extra Field:\n          ================\n\n          The following is the layout of the file-attributes extra block for\n          BeOS.  (Last Revision 19970531)\n\n          Local-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (BeOS)  0x6542        Short       tag for this extra block type (\"Be\")\n          TSize         Short       total data size for this block\n          BSize         Long        uncompressed file attribute data size\n          Flags         Byte        info bits\n          (CType)       Short       compression type\n          (CRC)         Long        CRC value for uncompressed file attribs\n          Attribs       variable    file attribute data\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (BeOS)  0x6542        Short       tag for this extra block type (\"Be\")\n          TSize         Short       total data size for this block (5)\n          BSize         Long        size of uncompr. local EF block data\n          Flags         Byte        info bits\n\n          The least significant bit of Flags in both headers indicates whether\n          the LOCAL extra field is uncompressed (and therefore whether CType\n          and CRC are omitted):\n\n                bit 0           if set, Attribs is uncompressed (no CType, CRC)\n                bits 1-7        reserved; if set, assume error or unknown data\n\n          Currently the only supported compression types are deflated (type 8)\n          and stored (type 0); the latter is not used by Info-ZIP's Zip but is\n          supported by UnZip.\n\n          Attribs is a BeOS-specific block of data in big-endian format with\n          the following structure (if compressed, uncompress it first):\n\n              Value     Size        Description\n              -----     ----        -----------\n              Name      variable    attribute name (null-terminated string)\n              Type      Long        attribute type (32-bit unsigned integer)\n              Size      Long Long   data size for this sub-block (64 bits)\n              Data      variable    attribute data\n\n          The attribute structure is repeated for every attribute.  The Data\n          field may contain anything--text, flags, bitmaps, etc.\n\n\n         -SMS/QDOS Extra Field:\n          ====================\n\n          The following is the layout of the file-attributes extra block for\n          SMS/QDOS.  The local-header and central-header versions are identical.\n          (Last Revision 19960929)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (QDOS)  0xfb4a        Short       tag for this extra block type\n          TSize         Short       total data size for this block\n          LongID        Long        extra-field signature\n          (ExtraID)     Long        additional signature/flag bytes\n          QDirect       64 bytes    qdirect structure\n\n          LongID may be \"QZHD\" or \"QDOS\".  In the latter case, ExtraID will\n          be present.  Its first three bytes are \"02\\0\"; the last byte is\n          currently undefined.\n\n          QDirect contains the file's uncompressed directory info (qdirect\n          struct).  Its elements are in native (big-endian) format:\n\n          d_length      beLong          file length\n          d_access      byte            file access type\n          d_type        byte            file type\n          d_datalen     beLong          data length\n          d_reserved    beLong          unused\n          d_szname      beShort         size of filename\n          d_name        36 bytes        filename\n          d_update      beLong          time of last update\n          d_refdate     beLong          file version number\n          d_backup      beLong          time of last backup (archive date)\n\n\n         -AOS/VS Extra Field:\n          ==================\n\n          The following is the layout of the extra block for Data General\n          AOS/VS.  The local-header and central-header versions are identical.\n          (Last Revision 19961125)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (AOSVS) 0x5356        Short       tag for this extra block type (\"VS\")\n          TSize         Short       total data size for this block\n          \"FCI\\0\"       Long        extra-field signature\n          Version       Byte        version of AOS/VS extra block (10 = 1.0)\n          Fstat         variable    fstat packet\n          AclBuf        variable    raw ACL data ($MXACL bytes)\n\n          Fstat contains the file's uncompressed fstat packet, which is one of\n          the following:\n\n                normal fstat packet             (P_FSTAT struct)\n                DIR/CPD fstat packet            (P_FSTAT_DIR struct)\n                unit (device) fstat packet      (P_FSTAT_UNIT struct)\n                IPC file fstat packet           (P_FSTAT_IPC struct)\n\n          AclBuf contains the raw ACL data; its length is $MXACL.\n\n\n         -Tandem NSK Extra Field:\n          ======================\n\n          The following is the layout of the file-attributes extra block for\n          Tandem NSK.  The local-header and central-header versions are\n          identical.  (Last Revision 19981221)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (TA)    0x4154        Short       tag for this extra block type (\"TA\")\n          TSize         Short       total data size for this block (20)\n          NSKattrs      20 Bytes    NSK attributes\n\n\n         -THEOS Extra Field:\n          =================\n\n          The following is the layout of the file-attributes extra block for\n          Theos.  The local-header and central-header versions are identical.\n          (Last Revision 19990206)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (Theos) 0x6854        Short       'Th' signature\n          size          Short       size of extra block\n          flags         Byte        reserved for future use\n          filesize      Long        file size\n          fileorg       Byte        type of file (see below)\n          keylen        Short       key length for indexed and keyed files,\n                                    data segment size for 16 bits programs\n          reclen        Short       record length for indexed,keyed and direct,\n                                    text segment size for 16 bits programs\n          filegrow      Byte        growing factor for indexed,keyed and direct\n          protect       Byte        protections (see below)\n          reserved      Short       reserved for future use\n\n            File types\n            ==========\n\n            0x80  library (keyed access list of files)\n            0x40  directory\n            0x10  stream file\n            0x08  direct file\n            0x04  keyed file\n            0x02  indexed file\n            0x0e  reserved\n            0x01  16 bits real mode program (obsolete)\n            0x21  16 bits protected mode program\n            0x41  32 bits protected mode program\n\n            Protection codes\n            ================\n\n            User protection\n            ---------------\n            0x01  non readable\n            0x02  non writable\n            0x04  non executable\n            0x08  non erasable\n\n            Other protection\n            ----------------\n            0x10  non readable\n            0x20  non writable\n            0x40  non executable Theos before 4.0\n            0x40  modified Theos 4.x\n            0x80  not hidden\n\n\n         -THEOS old inofficial Extra Field:\n          ================================\n\n          The following is the layout of an inoffical former version of a\n          Theos file-attributes extra blocks.  This layout was never published\n          and is no longer created. However, UnZip can optionally support it\n          when compiling with the option flag OLD_THEOS_EXTRA defined.\n          Both the local-header and central-header versions are identical.\n          (Last Revision 19990206)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (THS0)  0x4854        Short       'TH' signature\n          size          Short       size of extra block\n          flags         Short       reserved for future use\n          filesize      Long        file size\n          reclen        Short       record length for indexed,keyed and direct,\n                                    text segment size for 16 bits programs\n          keylen        Short       key length for indexed and keyed files,\n                                    data segment size for 16 bits programs\n          filegrow      Byte        growing factor for indexed,keyed and direct\n          reserved      3 Bytes     reserved for future use\n\n\n         -FWKCS MD5 Extra Field:\n          =====================\n\n          The FWKCS Contents_Signature System, used in automatically\n          identifying files independent of filename, optionally adds\n          and uses an extra field to support the rapid creation of\n          an enhanced contents_signature.\n          There is no local-header version; the following applies\n          only to the central header.  (Last Revision 19961207)\n\n          Central-header version:\n\n          Value         Size        Description\n          -----         ----        -----------\n  (MD5)   0x4b46        Short       tag for this extra block type (\"FK\")\n          TSize         Short       total data size for this block (19)\n          \"MD5\"         3 bytes     extra-field signature\n          MD5hash       16 bytes    128-bit MD5 hash of uncompressed data\n                                    (low byte first)\n\n          When FWKCS revises a .ZIP file central directory to add\n          this extra field for a file, it also replaces the\n          central directory entry for that file's uncompressed\n          file length with a measured value.\n\n          FWKCS provides an option to strip this extra field, if\n          present, from a .ZIP file central directory. In adding\n          this extra field, FWKCS preserves .ZIP file Authenticity\n          Verification; if stripping this extra field, FWKCS\n          preserves all versions of AV through PKZIP version 2.04g.\n\n          FWKCS, and FWKCS Contents_Signature System, are\n          trademarks of Frederick W. Kantor.\n\n          (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer\n              Science and RSA Data Security, Inc., April 1992.\n              ll.76-77: \"The MD5 algorithm is being placed in the\n              public domain for review and possible adoption as a\n              standard.\"\n\n\n         -Info-ZIP Unicode Path Extra Field:\n          =================================\n\n          Stores the UTF-8 version of the entry path as stored in the\n          local header and central directory header.\n          (Last Revision 20070912)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (UPath) 0x7075        Short       tag for this extra block type (\"up\")\n          TSize         Short       total data size for this block\n          Version       1 byte      version of this extra field, currently 1\n          NameCRC32     4 bytes     File Name Field CRC32 Checksum\n          UnicodeName   Variable    UTF-8 version of the entry File Name\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          The NameCRC32 is the standard zip CRC32 checksum of the File Name\n          field in the header.  This is used to verify that the header\n          File Name field has not changed since the Unicode Path extra field\n          was created.  This can happen if a utility renames the entry but\n          does not update the UTF-8 path extra field.  If the CRC check fails,\n          this UTF-8 Path Extra Field should be ignored and the File Name field\n          in the header used instead.\n\n          The UnicodeName is the UTF-8 version of the contents of the File Name\n          field in the header.  As UnicodeName is defined to be UTF-8, no UTF-8\n          byte order mark (BOM) is used.  The length of this field is determined\n          by subtracting the size of the previous fields from TSize.  If both\n          the File Name and Comment fields are UTF-8, the new General Purpose\n          Bit Flag, bit 11 (Language encoding flag (EFS)), can be used to\n          indicate that both the header File Name and Comment fields are UTF-8\n          and, in this case, the Unicode Path and Unicode Comment extra fields\n          are not needed and should not be created.  Note that, for backward\n          compatibility, bit 11 should only be used if the native character set\n          of the paths and comments being zipped up are already in UTF-8.  The\n          same method, either bit 11 or extra fields, should be used in both\n          the local and central directory headers.\n\n\n         -Info-ZIP Unicode Comment Extra Field:\n          ====================================\n\n          Stores the UTF-8 version of the entry comment as stored in the\n          central directory header.\n          (Last Revision 20070912)\n\n          Value         Size        Description\n          -----         ----        -----------\n   (UCom) 0x6375        Short       tag for this extra block type (\"uc\")\n          TSize         Short       total data size for this block\n          Version       1 byte      version of this extra field, currently 1\n          ComCRC32      4 bytes     Comment Field CRC32 Checksum\n          UnicodeCom    Variable    UTF-8 version of the entry comment\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          The ComCRC32 is the standard zip CRC32 checksum of the Comment\n          field in the central directory header.  This is used to verify that\n          the comment field has not changed since the Unicode Comment extra field\n          was created.  This can happen if a utility changes the Comment field\n          but does not update the UTF-8 Comment extra field.  If the CRC check\n          fails, this Unicode Comment extra field should be ignored and the\n          Comment field in the header used.\n\n          The UnicodeCom field is the UTF-8 version of the entry comment field\n          in the header.  As UnicodeCom is defined to be UTF-8, no UTF-8 byte\n          order mark (BOM) is used.  The length of this field is determined by\n          subtracting the size of the previous fields from TSize.  If both the\n          File Name and Comment fields are UTF-8, the new General Purpose Bit\n          Flag, bit 11 (Language encoding flag (EFS)), can be used to indicate\n          both the header File Name and Comment fields are UTF-8 and, in this\n          case, the Unicode Path and Unicode Comment extra fields are not\n          needed and should not be created.  Note that, for backward\n          compatibility, bit 11 should only be used if the native character set\n          of the paths and comments being zipped up are already in UTF-8.  The\n          same method, either bit 11 or extra fields, should be used in both\n          the local and central directory headers.\n\n\n         -Info-ZIP New Unix Extra Field:\n          ====================================\n\n          Currently stores Unix UIDs/GIDs up to 32 bits.\n          (Last Revision 20080509)\n\n          Value         Size        Description\n          -----         ----        -----------\n  (UnixN) 0x7875        Short       tag for this extra block type (\"ux\")\n          TSize         Short       total data size for this block\n          Version       1 byte      version of this extra field, currently 1\n          UIDSize       1 byte      Size of UID field\n          UID           Variable    UID for this entry\n          GIDSize       1 byte      Size of GID field\n          GID           Variable    GID for this entry\n\n          Currently Version is set to the number 1.  If there is a need\n          to change this field, the version will be incremented.  Changes\n          may not be backward compatible so this extra field should not be\n          used if the version is not recognized.\n\n          UIDSize is the size of the UID field in bytes.  This size should\n          match the size of the UID field on the target OS.\n\n          UID is the UID for this entry in standard little endian format.\n\n          GIDSize is the size of the GID field in bytes.  This size should\n          match the size of the GID field on the target OS.\n\n          GID is the GID for this entry in standard little endian format.\n\n          If both the old 16-bit Unix extra field (tag 0x7855, Info-ZIP Unix)\n          and this extra field are present, the values in this extra field\n          supercede the values in that extra field.\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/fileinfo.cms",
    "content": "[Quoting from a C/370 manual, courtesy of Carl Forde.]\n\n  C/370 supports three types of input and output: text streams, binary\n  streams, and record I/O.  Text and binary streams are both ANSI\n  standards; record I/O is a C/370 extension.\n\n[...]\n\n  Record I/O is a C/370 extension to the ANSI standard.  For files\n  opened in record format, C/370 reads and writes one record at a\n  time.  If you try to write more data to a record than the record\n  can hold, the data is truncated.  For record I/O, C/370 only allows\n  the use of fread() and fwrite() to read and write to the files.  Any\n  other functions (such as fprintf(), fscanf(), getc(), and putc())\n  fail.  For record-orientated files, records do not change size when\n  you update them.  If the new data has fewer characters than the\n  original record, the new data fills the first n characters, where\n  n is the number of characters of the new data.  The record will\n  remain the same size, and the old characters (those after) n are\n  left unchanged.  A subsequent update begins at the next boundary.\n  For example, if you have the string \"abcdefgh\":\n\n  abcdefgh\n\n  and you overwrite it with the string \"1234\", the record will look\n  like this:\n\n  1234efgh\n\n  C/370 record I/O is binary.  That is, it does not interpret any of\n  the data in a record file and therefore does not recognize control\n  characters.\n\n\n  The record model consists of:\n\n  * A record, which is the unit of data transmitted to and from a\n    program\n  * A block, which is the unit of data transmitted to and from a\n    device.  Each block may contain one or more records.\n\n  In the record model of I/O, records and blocks have the following\n  attributes:\n\n  RECFM   Specifies the format of the data or how the data is organized\n          on the physical device.\n  LRECL   Specifies the length of logical records (as opposed to\n          physical ones).\n\n  BLKSIZE Specifies the length of physical records (blocks on the\n          physical device).\n\n\n  Opening a File by Filename\n\n  The filename that you specify on the call to fopen() or freopen()\n  must be in the following format:\n\n  >> ----filename---- ----filetype--------------------\n                   |   |             |             |\n                   --.--             -- --filemode--\n                                     |   |\n                                     --.--\n  where\n\n  filename is a 1- to 8-character string of any of the characters,\n  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it\n  from the filetype with one or more spaces, or with a period.\n  [Further note:  filenames are fully case-sensitive, as in Unix.]\n\n  filetype is a 1- to 8-character string of any of the characters,\n  A-Z, a-z, 0-9, and +, -, $, #, @, :, and _.  You can separate it\n  from the filemode with one or more spaces, or with a period. The\n  separator between filetype and filemode must be the same as the\n  one between filename and filetype.\n\n  filemode is a 1- to 2-character string.  The first must be any of\n  the characters A-Z, a-z, or *.  If you use the asis parameter on\n  the fopen() or freopen() call, the first character of the filemode\n  must be a capital letter or an asterisk.  Otherwise, the function\n  call fails.  The second character of filemode is optional; if you\n  specify it, it must be any of the digits 0-6.  You cannot specify\n  the second character if you have specified * for the first one.\n\n  If you do not use periods as separators, there is no limit to how\n  much whitespace you can have before and after the filename, the\n  filetype, and filemode.\n\n\n  Opening a File without a File Mode Specified\n\n  If you omit the file mode or specify * for it, C/370 does one\n  of the following when you call fopen() or freopen():\n\n  * If you have specified a read mode, C/370 looks for the named file\n    on all the accessed readable disks, in order.  If it does not find\n    the file, the fopen() or freopen() call fails.\n  * If you have specified any of the write modes, C/370 writes the file\n    on the first writable disk you have accessed.  Specifying a write\n    mode on an fopen() or freopen() call that contains the filename of\n    an existing file destroys that file.  If you do not have any\n    writable disks accessed, the call fails.\n\n\n  fopen() and freopen() parameters\n\n  recfm\n     CMS supports only two RECFMs, V and F.  [note that MVS supports\n     27(!) different RECFMs.]  If you do not specify the RECFM for a\n     file, C/370 determines whether is is in fixed or variable format.\n\n  lrecl and blksize\n     For files in fixed format, CMS allows records to be read and\n     written in blocks.  To have a fixed format CMS file treated as a\n     fixed blocked CMS file, you can open the file with recfm=fb and\n     specify the lrecl and blksize.  If you do not specify a recfm on\n     the open, the blksize can be a multiple of the lrecl, and the\n     file is treated as if it were blocked.\n\n     For files in variable format, the CMS LRECL is different from the\n     LRECL for the record model.  In the record model, the LRECL is\n     equal to the data length plus 4 bytes (for the record descriptor\n     word), and the BLKSIZE  is equal to the LRECL plus 4 bytes (for\n     the block descriptor word).  In CMS, BDWs and RDWs do not exist,\n     but because CMS follows the record model, you must still account\n     for them.  When you specify V, you must still allocate the record\n     descriptor word and block descriptor word.  That is, if you want\n     a maximum of n bytes per record, you must specify a minimum LRECL\n     of n+4 and a minimum BLKSIZE of n+8.\n\n     When you are appending to V files, you can enlarge the record size\n     dynamically, but only if you have not specified LRECL or BLKSIZE\n     on the fopen() or freopen() command that opened the file.\n\n  type\n     If you specify this parameter, the only valid value for CMS disk\n     files is type =record. This opens a file for record I/O.\n\n  asis\n     If you use this parameter, you can open files with mixed-case\n     filenames such as JaMeS dAtA or pErCy.FILE.  If you specify this\n     parameter, the file mode that you specify must be a capital letter\n     (if it is not an asterisk); otherwise; the function call fails and\n     the value returned is NULL.\n\n\n  Reading from Record I/O Files\n     fread() is the only interface allowed for reading record I/O files.\n     Each time you call fread() for a record I/O file, fread() reads\n     one record from the system.  If you call fread() with a request for\n     less than a complete record, the requested bytes are copied to your\n     buffer, and the file position is set to the start fo the next\n     record.  If the request is for more bytes that are in the record,\n     one record is read and the position is set to the start of the next\n     record.  C/370 does not strip any blank characters or interpret any\n     data.\n\n     fread() returns the number of items read successfully, so if you\n     pass a size argument equal to 1 and a count argument equal to the\n     maximum expected length of the record, fread() returns the length,\n     in bytes, of the record read.  If you pass a size argument equal\n     to the maximum expected length of the record, and a count argument\n     equal to 1, fread() returns either 0 or 1, indicating whether a\n     record of length size read.  If a record is read successfully but\n     is less than size bytes long, fread() returns 0.\n\n\n  Writing to Record I/O Files\n     fwrite() is the only interface allowed for writing to a file\n     opened for record I/O.  Only one record is written at a time.  If\n     you attempt to write more new data than a full record can hold or\n     try to update a record with more data than it currently has, C/370\n     truncates your output at the record boundary.  When C/370 performs\n     a truncation, it sets errno and raises SIGIOERR, if SIGIOERR is not\n     set to SIG_IGN.\n\n     When you are writing new records to a fixed-record I/O file, if you\n     try to write a short record, C/370 pads the record with nulls out\n     to LRECL.\n\n     At the completion of an fwrite(), the file position is at the start\n     of the next record.  For new data, the block is flushed out to the\n     system as soon as it is full.\n\n\n  fldata() Behavior\n     When you call the fldata() function for an open CMS minidisk file,\n     it returns a data structure that looks like this:\n\n     struct __filedata {\n          unsigned int   __recfmF      : 1, /* fixed length records */\n                         __recfmV      : 1, /* variable length records */\n                         __recfmU      : 1, /* n/a */\n                         __recfmS      : 1, /* n/a */\n                         __recfmBlk    : 1, /* n/a */\n                         __recfmASA    : 1, /* text mode and ASA */\n                         __recfmM      : 1, /* n/a */\n                         __dsorgPO     : 1, /* n/a */\n                         __dsorgPDSmem : 1, /* n/a */\n                         __dsorgPDSdir : 1, /* n/a */\n                         __dsorgPS     : 1, /* sequential data set */\n                         __dsorgConcat : 1, /* n/a */\n                         __dsorgMem    : 1, /* n/a */\n                         __dsorgHiper  : 1, /* n/a */\n                         __dsorgTemp   : 1, /* created with tmpfile() */\n                         __dsorgVSAM   : 1, /* n/a */\n                         __reserve1    : 1, /* n/a */\n                         __openmode    : 2, /* see below 1 */\n                         __modeflag    : 4, /* see below 2 */\n                         __reserve2    : 9, /* n/a */\n\n          char           __device;  __DISK\n          unsigned long  __blksize,         /* see below 3 */\n                         __maxreclen;       /* see below 4 */\n          unsigned short __vsamtype;        /* n/a */\n          unsigned long  __vsamkeylen;      /* n/a */\n          unsigned long  __vsamRKP;         /* n/a */\n          char *         __dsname;          /* fname ftype fmode */\n          unsigned int   __reserve4;        /* n/a */\n\n          /* note 1: values are: __TEXT, __BINARY, __RECORD\n             note 2: values are: __READ, __WRITE, __APPEND, __UPDATE\n                     these values can be added together to determine\n                     the return value; for example, a file opened with\n                     a+ will have the value __READ + __APPEND.\n             note 3: total block size of the file, including ASA\n                     characters as well as RDW information\n             note 4: maximum record length of the data only (includes\n                     ASA characters but excludes RDW information).\n          */\n       };\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/infozip.who",
    "content": "These members of the Info-ZIP group contributed to the development and\ntesting of portable Zip.  They are responsible for whatever works in\nZip.  Whatever doesn't work is solely the fault of the authors of Zip\n(Mark Adler, Rich Wales, Jean-loup Gailly, Kai Uwe Rommel, Igor Mandrichenko,\nOnno van der Linden, Christian Spieler, John Bush, Paul Kienitz, Sergio Monesi\nand Karl Davis, but see the license for the latest list).  If you have\ncontributed and your name has been forgotten, please send a reminder to us\nusing the contact information in the Readme file.  The names are given here\nin alphabetical order, because it's impossible to classify them by importance\nof the contribution.  Some have made a complete port to a new target, some\nhave provided a one line fix.  All are to be thanked.\n\n\nMark Adler              madler@tybalt.caltech.edu       NeXT 2.x, Mac\n                        alan@spri.levels.unisa.edu.au   Linux\nJeffrey Altman          jaltman@watsun.cc.columbia.edu  fseek bug on NT\nGlenn J. Andrews        oper1%drcv06.decnet@drcvax.af.mil       VAX VMS\nJames Van Artsdalen     james@raid.dell.com             bug report\nEric Backus             ericb@lsid.hp.com               bug report\nQuentin Barnes          qbarnes@urbana.css.mot.com      unix/Makefile mode of\n                                                        installed files\nElmar Bartel            bartel@informatik.tu-muenchen.de\nMark E. Becker          mbecker@cs.uml.edu              bug report\nPaul von Behren         Paul_von_Behren@stortek.com     OS/390 port\nJon Bell                swy@wsdot.wa.gov                Intergraph/CLIX\nMyles Bennett           -                               Initial UnZip 6.0 large\n                                                        files beta\nMichael Bernardi        mike@childsoc.demon.co.uk       RS6000\nTom Betz                marob!upaya!tbetz@phri.nyu.edu  SCO Xenix 2.3.1\nJames Birdsall          jwbirdsa@picarefy.com           AT&T 3B1\nGeorge                  boer@fwi.uva.nl                 OS/2\nMichael Bolton          bolton@vaxc.erim.org            VAX/VMS\nWim Bonner              27313853@WSUVM1.CSC.WSU.EDU     HP 9000/840a HPUX\nPaul Borman             prb@cray.com                    Cray-X/YMP,2 UNICOS 6-8\nKurt Van den Branden    kvd2@bipsy.se.bel.alcatel.be    VAX VMS\nScott Briggs            briggs@nashua.progress.com      Windows NT\nLeslie C. Brown         lbrown@BRL.MIL                  Pyramid MIS-4\nRalf Brown              ralf@b.gp.cs.cmu.edu            Pyramid MIS-4\nRodney Brown            rdb@cmutual.com.au              SunOS 4.1.3 DGUX OSF/1\n                                                        HP-UX  CRC optimization\nJeremy Daniel Buhler    jbuhler@owlnet.rice.edu         BC++\nJohn Bush               john.bush@east.sun.com          Amiga (SAS/C)\nPietro Caselli          zaphod@petruz.sublink.org       Minix 1.5.10\nAndrew A. Chernov       ache@astral.msk.su              FreeBSD\nJeff Coffler            jeffcof@microsoft.com           Windows NT\nDavid Dachtera          David.Dachtera@advocatehealth.com  VMS\n                                                        link_zip.com bug\nBill Davidsen           davidsen@crdos1.crd.ge.com      Xenix (on what?)\nKarl Davis              riscman@geko.com.au             Acorn\nDaniel Deimert          daniel@pkmab.se                 zeus3.21 Zilog S8000\nDavid Denholm           denholm@sotona.physics.southampton.ac.uk   VMS\nHarald Denker           harry@hal.westfalen.de          ATARI\nMatthew J. D'Errico     doc@magna.com                   Bull\nL. Peter Deutsch        ghost@aladdin.com               Linux\nUwe Doering             gemini@geminix.in-berlin.de     386 Unix\nJean-Michel Dubois      jmdubois@ibcfrance.fr           Theos support\nJames P. Dugal          jpd@usl.edu                     Pyramid 90X OSx4.1\n\"Evil Ed\"               esaffle@gmuvax2.gmu.edu         Ultrix-32 V3.1 (Rev. 9)\nPatrick Ellis           pellis@aic.mdc.com              VMS zip -h appearance\nThomas Esken            esken@uni-muenster.de           Acorn fix\nDwight Estep            estep@dlo10.enet.dec.com        MSDOS\nDavid A. Feinleib       t-davefe@microsoft.com          Windows NT\nJoshua Felsteiner       joshua@phys1.technion.ac.il     Linux\nGreg Flint              afc@klaatu.cc.purdue.edu        ETA-10P* hybrid Sys V\nCarl Forde              cforde@bcsc02.gov.bc.ca         VM/CMS\nJeff Foy                jfoy@glia.biostr.washington.edu IRIX Sys V Rel 3.3.1\nMike Freeman            mikef@pacifier.com              Vax VMS\nKevin M. Fritz          kmfritz@apgea.army.mil          Turbo C++ 1.0\n                                                        Pyramid\nJean-loup Gailly        jloup@chorus.fr                 MS-DOS Microsoft C 5.1\nScott D. Galloway       sgallowa@letterkenn-emh1.army.mil   Sperry 5000 SysV.3\nRainer Gerling          gerling@faupt101.physik.uni-erlangen.de   HPUX, MSDOS\nHenry Gessau            henryg@kullmar.kullmar.se       Windows NT\nEd Gordon               -                               Zip 3.0, VB, Unicode,\n                                                        large files, splits, DLLs\nIan E. Gorman           ian@iosphere.net                ported zip 2.2 to VM/CMS\nWayne R. Graves         graves@csa2.lbl.gov             Vax VMS\nGeorge Grimes           grimes@netcom.com               Apollo Domain SR10.4\nHunter Goatley          goathunter@MadGoat.com          VMS (VAX & Alpha),\n                                                        web and ftp sites\nArnt Gulbrandsen        agulbra@pvv.unit.no             Linux\nDavid Gundlach          david@rolf.stat.uga.edu         Sun SS1+ SunOS 4.1\nPeter Gutmann           pgut1@cs.aukuni.ac.nz           bug report\nDirk Haase              d_haase@sitec.de                MacOS port\nMark Hanning-Lee        markhl@iris-355.jpl.nasa.gov    SGI\nWalter Haidinger        e9225662@student.tuwien.ac.at   Amiga and general fixes\nCharles Hannum          mycroft@ai.mit.edu              bug report\nGreg Hartwig            ghartwig@ix.netcom.com          VM/CMS cleanup\nTanvir Hassan           tanvir.hassan@autodesk.com      NT\nBob Hardy               hardy@lucid.com                 Power C on MSDOS\nZachary Heilig          heilig@plains.nodak.edu         Turbo C++ 3.0\nChris Herborth          chrish@pobox.com                BeOS port\nJonathan Hudson         jrhudson@bigfoot.com            QDOS port\nMark William Jacobs     mark@mensch.stanford.edu        MSDOS\nAubrey Jaffer           jaffer@martigny.ai.mit.edu      Pixel\nPeter Jones             jones.peter@uqam.ca             MIPS UMIPS 4.0\n                                                        +Onolimit fix for HP-UX\nKjetil W. J{\\o}rgensen  jorgens@lise.unit.no            OSF/1, DJGPP v2\nBruce Kahn              bkahn@archive.webo.dg.com       MS-DOS Microsoft C 5.1\nJonathan I. Kamens      jik@pit-manager.mit.edu         ultrix on DECstation\nDave Kapalko            d.kapalko@att.com               bug report\nBob Kemp                Robert.V.Kemp@att.com           AT&T 3B2 SysV 3.2v2\nVivek Khera             khera@cs.duke.edu               SunOS\nEarl Kiech              KIECH@utkvx.utk.edu             VAX VMS V5.4-1A\nPaul Kienitz            Paul.Kienitz@shelter.sf.ca.us   Amiga, Watcom C\nDavid Kirschbaum        kirsch@usasoc.soc.mil           He got us all in this\n                                                        mess in the first place\nThomas Klausner         wiz@danbala.tuwien.ac.at        cygwin32 and -k fix\nD. Krumbholz            krumbh00@marvin.informatik.uni-dortmund.de\n                                                        Acorn filetype and\n                                                        timestamp bug report\n\nBo Kullmar              bk@kullmar.se                   DNIX 5.3, SunOS 4.1\nBaden Kudrenecky        baden@unixg.ubc.ca              OS/2\nGiuseppe La Sala        lasala@mail.esa.esrin.it        VMS\nJean-Marc Lasgouttes    jean-marc.lasgouttes@inria.fr   Bug report\nHarry Langenbacher      harry@neuron6.Jpl.Nasa.Gov      Sun SS1+ SunOS 4.1\nMichael D. Lawler       mdlawler@gwmicro.com            Mt.Xinu BSD 4.3 on VAX\n                                                        Borland C++ 4.51\nJohnny Lee              johnnyl@microsoft.com           Microsoft C 7.0\nMichael Lemke           michael@io.as.utexas.edu        VMS\nDavid Lemson            lemson@ux1.cso.uiuc.edu         Sequent Dynix 3.0.17\nTai-Shan Lin            tlin@snakeyes.eecs.wsu.edu      OS/2\nOnno van der Linden     onno@simplex.nl                 NetBSD, Borland C++,\n                                                        MSC 7.0, DJGPP 2\n\nMichel                  loehden%mv13.decnet@vax.hrz.uni-marburg.de  VMS\nWarner Losh             imp@Solbourne.COM               packing algorithm help\nDave Lovelace           davel@grex.cyberspace.org       DG AOS/VS\nErik Luijten            erik@tntnhb3.tn.tudelft.nl      problem report\nJohn Lundin             lundin@urvax.urich.edu          VAX VMS\nIgor Mandrichenko       mandrichenko@m10.ihep.su        VAX VMS\nCliff Manis             root@csoftec.csf.com            SCO 2.3.1 (386)\nFulvio Marino           fulvio@iconet.ico.olivetti.it   X/OS 2.3 & 2.4\nBill Marsh              bmarsh@cod.nosc.mil             SGI Iris 4D35\nMichael Mauch           mauch@gmx.de                    djgpp LFN attribute fix\nPeter Mauzey            ptm@mtdcr.mt.lucent.com         AT&T 6300, 7300\nRafal Z. Maszkowski     rzm@mat.torun.edu.pl            Convex\nRobert McBroom (?)      rm3@ornl.gov                    DECsystem 5810\nTom McConnell           tmcconne@sedona.intel.com       NCR SVR4\nFrank P. McIngvale      frankm@eng.auburn.edu           Bug report\nConor McMenamin         C.S.McMenamin@sussex.ac.uk      MSDOS\nWill Menninger                                          Win32, MinGW\nJohn Messenger          jlm@proteon.com                 Bug report\nMichael                 kuch@mailserv.zdv.uni-tuebingen.de SGI\nDan Mick                dmick@pongo.west.sun.com        Solaris\nAlan Modra              alan@spri.levels.unisa.edu.au   Linux\nLaszlo Molnar           lmolnar@goliat.eik.bme.hu       DJGPP v2\nJim Mollmann            jmq@nccibm1.bitnet              OS/2 & MVS\nSergio Monesi           pel0015@cdc8g5.cdc.polimi.it    Acorn\nJ. Mukherjee            jmukherj@ringer.cs.utsa.edu     OS/2\nAnthony Naggs           amn@ubik.demon.co.uk            bug report\nMatti Narkia            matti.narkia@ntc.nokia.com      VAX VMS\nRainer Nausedat                                         Zip 3.0, large files\nRobert E. Newman Jr.    newmanr@ssl.msfc.nasa.gov       bug report\nRobert Nielsen          NielsenRJ@ems.com               2.2 -V VMS bug report\nChristian Michel        cmichel@de.ibm.com              2.2 check_dup OS/2 bug\n                                                        report\nThomas S. Opheys        opheys@kirk.fmi.uni-passau.de   OS/2\nHumberto Ortiz-Zuazaga  zuazaga@ucunix.san.uc.edu       Linux\nJames E. O'Dell         jim@fpr.com                     MacOS\nWilliam O'Shaughnessy   williamo@hpcupt1.cup.hp.com     HPUX\nNeil Parks              neil.parks@pcohio.com           MSDOS\nEnrico Renato Palmerini palmer@vxscaq.cineca.it         UNISYS 7000 Sys 5 r2.3\nGeoff Pennington        Geoff.Pennington@sgcs.co.uk     -q output bug\nKeith Petersen          w8sdz@simtel20.army.mil         Pyramid UCB OSx4.4c\nGeorge Petrov                                           VM/CMS, MVS\nAlan Phillips           postmaster@lancaster.ac.uk      Dynix/ptx 1.3\nBruno Pillard           bp@chorus.fr                    SunOS 4.1\nPiet W. Plomp           piet@icce.rug.nl                MSC 7.0, SCO 3.2v4.0\nJohn Poltorak           j.poltorak@bradford.ac.uk       problem report\nKenneth Porter          72420.2436@compuserve.com       OS/2\nNorbert Pueschel        pueschel@imsdd.meb.uni-bonn.de  Amiga time.lib\nYuval Rakavy            yuval@cs.huji.ac.il             MSDOS\nDavid A Rasmussen       dave@convex.csd.uwm.edu         Convex C220 with 9.0 OS\nEric Raymond            esr@snark.thyrsus.com           Unix\nJim Read                74312.3103@compuserve.com       OS/2\nMichael Regoli          mr@cica.indiana.edu             Ultrix 3.1 VAX 8650\n                                                        BSD 4.3 IBM RT/125\n                                                        BSD 4.3 MicroVAX 3500\n                                                        SunOS 4.0.3 Sun 4/330\nJochen Roderburg        roderburg@rrz.uni-koeln.de      Digital Unix with\n                                                        AFS/NFS converter\nRick Rodgers            rodgers@maxwell.mmwb.ucsf.EDU   Unix man page\nGreg Roelofs            roe2@midway.uchicago.edu        SunOS 4.1.1,4.1.2 Sun 4\n                                                        Unicos 5.1--6.1.5 Cray\n                                                        OS/2 1.3 MS C 6.0\n                                                        Ultrix 4.1,4.2 DEC 5810\n                                                        VMS 5.2, 5.4 VAX 8600\n                                                        Irix 3.3.2, SGI Iris 4D\n                                                        UTS 1.2.4 Amdahl 5880\nPhil Ritzenthaler       phil@cgrg.ohio-state.edu        SYSV\nKai Uwe Rommel          rommel@ars.de or rommel@leo.org OS/2\nMarkus Ruppel           m.ruppel@imperial.ac.uk         OS/2\nShimazaki Ryo           eririn@ma.mailbank.ne.jp        human68k\nJon Saxton              jrs@panix.com                   Microsoft C 6.0\nSteve Salisbury         stevesa@msn.com                 Microsoft C 8.0\nTimo Salmi              ts@uwasa.fi                     bug report\nDarren Salt             ds@youmustbejoking.demon.co.uk  RISC OS\nNIIMI Satoshi           a01309@cfi.waseda.ac.jp         Human68K\nTom Schmidt             tschmidt@micron.com             SCO 286\nMartin Schulz           martin.schulz@isltd.insignia.com Windows NT, Atari\nSteven Schweda                                          VMS, Unix, large files\nDan Seyb                dseyb@halnet.com                AIX\nMark Shadley            shadcat@catcher.com             unix fixes\nTimur Shaporev          tim@rd.relcom.msk.su            MSDOS\nW. T. Sidney            sidney@picard.med.ge.com        bug report\nDave Sisson             daves@vtcosy.cns.vt.edu         AIX 1.1.1 PS/2 & 3090\nDave Smith              smithdt@bp.com                  Tandem port\nFred Smith              fredex@fcshome.stoneham.ma.us   Coherent\nChristian Spieler       spieler@ikp.tu-darmstadt.de     VMS, MSDOS, emx, djgpp,\n                                                        WIN32, Linux\nRon Srodawa             srodawa@vela.acs.oakland.edu    SCO Xenix/386 2.3.3\nAdam Stanley            astanley@winternet.com          MSDOS\nBertil Stenstr|m        stenis@heron.dafa.se            HP-UX 7.0 HP9000/835\nCarl Streeter           streeter@oshkoshw.bitnet        OS/2\nReuben Sumner           rasumner@undergrad.math.uwaterloo.ca  Suggestions\nE-Yen Tan               e-yen.tan@brasenose.oxford.ac.uk Borland C++ win32\nYoshioka Tsuneo         tsuneo-y@is.aist-nara.ac.jp     Multibyte charset\n                                                        support\nPaul Telles             paul@pubnet.com                 SCO Xenix\nJulian Thompson         jrt@oasis.icl.co.uk             bug report\nChristopher C. Tjon     tjon@plains.nodak.edu           bug report\nRobert F Tobler         rft@cs.stanford.edu             bug report\nEric  Tomio             tomio@acri.fr                   bug report\nCosmin Truta            cosmint@cs.ubbcluj.ro           win32 gcc based + asm\nAnthony R. Venson       cevens@unix1.sncc.lsu.edu       MSDOS/emx\nAntoine Verheijen       antoine@sysmail.ucs.ualberta.ca envargs fix\nArjan de Vet            devet@info.win.tue.nl           SunOS 4.1, MSC 5.1\nSantiago Vila Doncel    sanvila@ba.unex.es              MSDOS\nJohan Vromans           jv@mh.nl                        bug report\nRich Wales              wales@cs.ucla.edu               SunOS 4.0.3 Sun-3/50\nScott Walton            scottw@io.com                   BSD/386\nFrank J. Wancho         wancho@wsmr-simtel20.army.mil   TOPS-20\n                        oyvind@stavanger.sgp.slb.com    Bug report.\nTakahiro Watanabe       wata@first.tsukuba.ac.jp        fixes for INSTALL\nMike White              mwhite@pumatech.com             wizzip DLL\nRay Wickert             wickert@dc-srv.pa-x.dec.com     MSDOS/DJGPP\nWinfried Winkler        willi@wap0109.chem.tu-berlin.de AIX\nNorman J. Wong          as219@freenet.carleton.ca       MSDOS\nMartin Zinser           m.zinser@gsi.de                 VMS 7.x\n\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/ntsd.txt",
    "content": "Info-ZIP portable Zip/UnZip Windows NT security descriptor support\n==================================================================\nScott Field (sfield@microsoft.com), 8 October 1996\n\n\nThis version of Info-ZIP's Win32 code allows for processing of Windows\nNT security descriptors if they were saved in the .zip file using the\nappropriate Win32 Zip running under Windows NT.  This also requires\nthat the file system that Zip/UnZip operates on supports persistent\nAcl storage.  When the operating system is not Windows NT and the\ntarget file system does not support persistent Acl storage, no security\ndescriptor processing takes place.\n\nA Windows NT security descriptor consists of any combination of the\nfollowing components:\n\n       an owner (Sid)\n       a primary group (Sid)\n       a discretionary ACL (Dacl)\n       a system ACL (Sacl)\n       qualifiers for the preceding items\n\nBy default, Zip will save all aspects of the security descriptor except\nfor the Sacl.  The Sacl contains information pertaining to auditing of\nthe file, and requires a security privilege be granted to the calling\nuser in addition to being enabled by the calling application.  In order\nto save the Sacl during Zip, the user must specify the -! switch on the\nZip commandline.  The user must also be granted either the SeBackupPrivilege\n\"Backup files and directories\" or the SeSystemSecurityPrivilege \"Manage\nauditing and security log\".\n\nBy default, UnZip will not restore any aspects of the security descriptor.\nIf the -X option is specified to UnZip, the Dacl is restored to the file.\nThe other items in the security descriptor on the new file will receive\ndefault values.  If the -XX option is specified to UnZip, as many aspects\nof the security descriptor as possible will be restored.  If the calling\nuser is granted the SeRestorePrivilege \"Restore files and directories\",\nall aspects of the security descriptor will be restored.  If the calling\nuser is only granted the SeSystemSecurityPrivilege \"Manage auditing and\nsecurity log\", only the Dacl and Sacl will be restored to the new file.\n\nNote that when operating on files that reside on remote volumes, the\nprivileges specified above must be granted to the calling user on that\nremote machine.  Currently, there is no way to directly test what privileges\nare present on a remote machine, so Zip and UnZip make a remote privilege\ndetermination based on an indirect method.\n\nUnZip considerations\n--------------------\n\nIn order for file security to be processed correctly, any directory entries\nthat have a security descriptor will be processed at the end of the unzip\ncycle.  This allows for unzip to process files within the newly created\ndirectory regardless of the security descriptor associated with the directory\nentry.  This also prevents security inheritance problems that can occur as\na result of creating a new directory and then creating files in that directory\nthat will inherit parent directory permissions; such inherited permissions may\nprevent the security descriptor taken from the zip file from being applied\nto the new file.\n\nIf directories exist which match directory/extract paths in the .zip file,\nfile security is not updated on the target directory.  It is assumed that if\nthe target directory already exists, then appropriate security has already\nbeen applied to that directory.\n\n\"unzip -t\" will test the integrity of stored security descriptors when\npresent and the operating system is Windows NT.\n\nZipInfo (unzip -Z) will display information on stored security descriptor\nwhen \"unzip -Zv\" is specifed.\n\n\nPotential uses\n==============\n\nThe obvious use for this new support is to better support backup and restore\noperations in a Windows NT environment where NTFS file security is utilized.\nThis allows individuals and organizations to archive files in a portable\nfashion and transport these files across the organization.\n\nAnother potential use of this support is setup and installation.  This\nallows for distribution of Windows NT based applications that have preset\nsecurity on files and directories.  For example, prior to creation of the\n.zip file, the user can set file security via File Manager or Explorer on\nthe files to be contained in the .zip file.  In many cases, it is appropriate\nto only grant Everyone Read access to .exe and .dll files, while granting\nAdministrators Full control.  Using this support in conjunction with the\nunzipsfx.exe self-extractor stub can yield a useful and powerful way to\ninstall software with preset security (note that -X or -XX should be\nspecified on the self-extractor commandline).\n\nWhen creating .zip files with security which are intended for transport\nacross systems, it is important to take into account the relevance of\naccess control entries and the associated Sid of each entry.  For example,\nif a .zip file is created on a Windows NT workstation, and file security\nreferences local workstation user accounts (like an account named Fred),\nthis access entry will not be relevant if the .zip file is transported to\nanother machine.  Where possible, take advantage of the built-in well-known\ngroups, like Administrators, Everyone, Network, Guests, etc.  These groups\nhave the same meaning on any Windows NT machine.  Note that the names of\nthese groups may differ depending on the language of the installed Windows\nNT, but this isn't a problem since each name has well-known ID that, upon\nrestore, translates to the correct group name regardless of locale.\n\nWhen access control entries contain Sid entries that reference Domain\naccounts, these entries will only be relevant on systems that recognize\nthe referenced domain.  Generally speaking, the only side effects of\nirrelevant access control entries is wasted space in the stored security\ndescriptor and loss of complete intended access control.  Such irrelevant\naccess control entries will show up as \"Account Unknown\" when viewing file\nsecurity with File Manager or Explorer.\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/perform.dos",
    "content": "Date: Wed, 27 Mar 1996 01:31:50 CET +0100\nFrom: Christian Spieler (IKDA, THD, D-64289 Darmstadt)\nSubject: More detailed comparison of MSDOS Info-ZIP programs' performance\n\nHello all,\n\nIn response to some additional questions and requests concerning\nmy previous message about DOS performance of 16/32-bit Info-ZIP programs,\nI have produced a more detailed comparison:\n\nSystem:\nCx486DX-40, VL-bus, 8MB; IDE hard disk;\nDOS 6.2, HIMEM, EMM386 NOEMS NOVCPI, SMARTDRV 3MB, write back.\n\nI have used the main directory of UnZip 5.20p as source, including the\nobjects and executable of an EMX compile for unzip.exe (to supply some\nbinary test files).\n\nTested programs were (my current updated sources!) Zip 2.0w and UnZip 5.20p\n- 16-bit MSC 5.1, compressed with LZEXE 0.91e\n- 32-bit Watcom C 10.5, as supplied by Kai Uwe Rommel (PMODE 1.22)\n- 32-bit EMX 0.9b\n- 32-bit DJGPP v2\n- 32-bit DJGPP v1.12m4\n\nThe EMX and DJ1 (GO32) executables were bound with the full extender, to\ncreate standalone executables.\n\nA) Tests of Zip\n  Command :  \"<system>\\zip.exe -q<#> tes.zip unz/*\"  (unz/*.* for Watcom!!)\n             where <#> was: 0, 1, 6, 9.\n             The test archive \"tes.zip\" was never deleted, this test\n             measured \"time to update archive\".\n\n  The following table contains average execution seconds (averaged over\n  at least 3 runs, with the first run discarted to fill disk cache);\n  numbers in parenteses specify the standard deviation of the last\n  digits.\n\n  cmpr level|      0     |      1     |      6     |      9\n ===============================================================\n  EMX win95 |   7.77     |   7.97     |  12.82     |  22.31\n ---------------------------------------------------------------\n  EMX       |   7.15(40) |   8.00(6)  |  12.52(25) |  20.93\n  DJ2       |  13.50(32) |  14.20(7)  |  19.05     |  28.48(9)\n  DJ1       |  13.56(30) |  14.48(3)  |  18.70     |  27.43(13)\n  WAT       |   6.94(22) |   8.93     |  15.73(34) |  30.25(6)\n  MSC       |   5.99(82) |   9.40(4)  |  13.59(9)  |  20.77(4)\n ===============================================================\n\n The \"EMX win95\" line was created for comparison, to check the performance\n of emx 0.9 with the RSX extender in a DPMI environment. (This line was\n produced by applying the \"stubbed\" EMX executable in a full screen DOS box.)\n\n\nB) Tests of UnZip\n  Commands :  <system>\\unzip.exe -qt tes.zip         (testing performance)\n              <system>\\unzip.exe -qo tes.zip -dtm    (extracting performance)\n\n  The tes.zip archive created by maximum compression with the Zip test\n  was used as example archive. Contents (archive size was 347783 bytes):\n   1028492 bytes uncompressed, 337235 bytes compressed, 67%, 85 files\n\n  The extraction directory tm was not deleted between the individual runs,\n  thus this measurement checks the \"overwrite all\" time.\n\n           |     testing               |          extracting\n  ===================================================================\n  EMX      |       1.98                |         6.43(8)\n  DJ2      |       2.09                |        11.85(39)\n  DJ1      |       2.09                |         7.46(9)\n  WAT      |       2.42                |         7.10(27)\n  MSC      |       4.94                |         9.57(31)\n\nRemarks:\n\nThe executables compiled by me were generated with all \"performance\"\noptions enabled (ASM_CRC, and ASMV for Zip), and with full crypt support.\nFor DJ1 and DJ2, the GCC options were \"-O2 -m486\", for EMX \"-O -m486\".\n\nThe Watcom UnZip was compiled with ASM_CRC code enabled as well,\nbut the Watcom Zip example was made without any optional assembler code!\n\n\n\nDiscussion of the results:\n\nIn overall performance, the EMX executables clearly win.\nFor UnZip, emx is by far the fastest program, and the Zip performance is\ncomparable to the 16-bit \"reference\".\n\nWhenever \"real\" work including I/O is requested, the DJGPP versions\nlose badly because of poor I/O performance, this is the case especially\nfor the \"newer\" DJGPP v2 !!!\n(I tried to tweak with the transfer buffer size, but without any success.)\nAn interesting result is that DJ v1 UnZip works remarkably better than\nDJ v2 (in contrast to Zip, where both executables' performance is\napproximately equal).\n\nThe Watcom C programs show a clear performance deficit in the \"computational\npart\" (Watcom C compiler produces code that is far from optimal), but\nthe extender (which is mostly responsible for the I/O throughput) seems\nto be quite fast.\n\nThe \"natural\" performance deficit of the 16-bit MSC code, which can be\nclearly seen in the \"testing task\" comparison for UnZip, is (mostly,\nfor Zip more than) compensated by the better I/O throughput (due to the\n\"direct interface\" between \"C RTL\" and \"DOS services\", without any mode\nswitching).\n\nBut performance is only one aspect when choosing which compiler should\nbe used for official distribution:\n\nSizes of the executables:\n    |             Zip                ||           UnZip\n    | standalone           stub      || standalone    |     stub\n======================================================================\nEMX | 143,364  (1) |    94,212       ||  159,748  (1) |   110,596\nDJ2 | 118,272  (2) |       --        ||  124,928  (2) |      --\nDJ1 | 159,744      |    88,064       ||  177,152      |   105,472\nWAT | 140,073      |       --        ||  116,231      |      --\nMSC |  49,212  (3) |       --        ||   45,510  (3) |      --\n\n(1) does not run in \"DPMI only\" environment (Windows DOS box)\n(2) requires externally supplied DPMI server\n(3) compressed with LZexe 0.91\n\nCaveats/Bugs/Problems of the different extenders:\n\nEMX:\n- requires two different extenders to run in all DOS-compatible environments,\n  EMX for \"raw/himem/vcpi\" and RSX for \"dpmi\" (Windows).\n- does not properly support time zones (no daylight savings time)\n\nDJv2:\n- requires an external (freely available) DPMI extender when run on plain\n  DOS; this extender cannot (currently ??) be bound into the executable.\n\nDJv1:\n- uses up large amount of \"low\" dos memory (below 1M) when spawning\n  another program, each instance of a DJv1 program requires its private\n  GO32 extender copy in low dos memory (may be problem for the zip\n  \"-T\" feature)\n\nWatcom/PMODE:\n- extended memory is allocated statically (default: ALL available memory)\n  This means that a spawned program does not get any extended memory.\n  You can work around this problem by setting a hard limit on the amount\n  of extended memory available to the PMODE program, but this limit is\n  \"hard\" and restricts the allocatable memory for the program itself.\n  In detail:\n  The Watcom zip.exe as distributed did not allow the \"zip -T\" feature;\n  there was no extended memory left to spawn unzip.\n  I could work around this  problem by applying PMSETUP to change the\n  amount of allocated extended memory to 2.0 MByte (I had 4MB free extended\n  memory on my test system). But, this limit cannot be enlarged at\n  runtime, when zip needs more memory to store \"header info\" while\n  zipping up a huge drive, and on a system with less free memory, this\n  method is not applicable, either.\n\nSummary:\n\nFor Zip:\nUse the 16-bit executable whenever possible (unless you need the\nlarger memory capabilities when zipping up a huge amount of files)\n\nAs 32-bit executable, we may distribute Watcom C (after we have confirmed\nthat enabling ASMV and ASM_CRC give us some better computational\nperformance.)\nThe alternative for 32-bit remains DJGPP v1, which shows the least problems\n(to my knowledge); v2 and EMX cannot be used because of their lack of\n\"universality\".\n\nFor UnZip:\nHere, the Watcom C 32-bit executable is probably the best compromise,\nbut DJ v1 could be used as well.\nAnd, after all, the 16-bit version does not lose badly when doing\n\"real\" extraction! For the SFX stub, the 16-bit version remains first\nchoice because of its much smaller size!\n\nBest regards\n\nChristian Spieler\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/timezone.txt",
    "content": "Timezone strings:\n-----------------\nThis is a description of valid timezone strings for ENV[ARC]:TZ:\n\"XPG3TZ - time zone information\"\nThe form of the time zone information is based on the XPG3 specification of\nthe TZ environment variable.  Spaces are allowed only in timezone\ndesignations, where they are significant.  The following description\nclosely follows the XPG3 specification, except for the paragraphs starting\n**CLARIFICATION**.\n\n<std><offset>[<dst>[<offset>],<start>[/<time>],<end>[/<time>]]\n\nWhere:\n<std> and <dst>\n      Are each three or more bytes that are the designation for the\n      standard (<std>) and daylight savings time (<dst>) timezones.\n      Only <std> is required - if <dst> is missing, then daylight\n      savings time does not apply in this locale.  Upper- and\n      lower-case letters are allowed.  Any characters except a\n      leading colon (:), digits, a comma (,), a minus (-) or a plus\n      (+) are allowed.\n      **CLARIFICATION**  The two-byte designation `UT' is permitted.\n<offset>\n      Indicates the value one must add to the local time to arrive\n      at Coordinated Universal Time.  The offset has the form:\n      <hh>[:<mm>[:<ss>]]\n      The minutes <mm> and seconds <ss> are optional.  The hour <hh>\n      is required and may be a single digit.  The offset following\n      <std> is required.  If no offset follows <dst>, daylight savings\n      time is assumed to be one hour ahead of standard time.  One or\n      more digits may be used; the value is always interpreted as a\n      decimal number.  The hour must be between 0 and 24, and the\n      minutes (and seconds) if present between 0 and 59.  Out of\n      range values may cause unpredictable behavior.  If preceded by\n      a `-', the timezone is east of the Prime Meridian; otherwise\n      it is west (which may be indicated by an optional preceding\n      `+' sign).\n      **CLARIFICATION**  No more than two digits are allowed in any\n      of <hh>, <mm> or <ss>.  Leading zeros are permitted.\n<start>/<time> and <end>/<time>\n      Indicates when to change to and back from daylight savings\n      time, where <start>/<time> describes when the change from\n      standard time to daylight savings time occurs, and\n      <end>/<time> describes when the change back happens.  Each\n      <time> field describes when, in current local time, the change\n      is made.\n      **CLARIFICATION**  It is recognized that in the Southern\n      hemisphere <start> will specify a date later than <end>.\n      The formats of <start> and <end> are one of the following:\n      J<n>    The Julian day <n> (1 <= <n> <= 365).  Leap days are not\n              counted.  That is, in all years, February 28 is day 59\n              and March 1 is day 60.  It is impossible to refer to\n              the occasional February 29.\n      <n>     The zero-based Julian day (0 <= <n> <= 365).  Leap days\n              are counted, and it is possible to refer to February\n              29.\n      M<m>.<n>.<d>\n              The <d>th day, (0 <= <d> <= 6) of week <n> of month <m>\n              of the year (1 <= <n> <= 5, 1 <= <m> <= 12), where week\n              5 means `the last <d>-day in month <m>' (which may\n              occur in either the fourth or the fifth week).  Week 1\n              is the first week in which the <d>th day occurs.  Day\n              zero is Sunday.\n              **CLARIFICATION**  Neither <n> nor <m> may have a\n              leading zero.  <d> must be a single digit.\n              **CLARIFICATION**  The default <start> and <end> values\n              are from the first Sunday in April until the last Sunday\n              in October.  This allows United States users to leave out\n              the <start> and <end> parts, as most are accustomed to\n              doing.\n      <time> has the same format as <offset> except that no leading\n      sign (`-' or `+') is allowed.  The default, if <time> is not\n      given is 02:00:00.\n      **CLARIFICATION**  The number of hours in <time> may be up\n      to 167, to allow encoding of rules such as `00:00hrs on the\n      Sunday after the second Friday in September'\n\nExample (for Central Europe):\n-----------------------------\nMET-1MEST,M3.5.0,M10.5.0/03\n\nAnother example, for the US East Coast:\n---------------------------------------\nEST5EDT4,M4.1.0/02,M10.5.0/02\nThis string describes the default values when no time zone is set.\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/txtvsbin.txt",
    "content": "A Fast Method of Identifying Plain Text Files\n=============================================\n\n\nIntroduction\n------------\n\nGiven a file coming from an unknown source, it is generally impossible\nto conclude automatically, and with 100% accuracy, whether that file is\na plain text file, without performing a heavy-duty semantic analysis on\nthe file contents.  It is, however, possible to obtain a fairly high\ndegree of accuracy, by employing various simple heuristics.\n\nPrevious versions of the zip tools were using a crude detection scheme,\noriginally used by PKWare in its PKZip programs: if more than 80% (4/5)\nof the bytes are within the range [7..127], the file is labeled as plain\ntext, otherwise it is labeled as binary.  A prominent limitation of this\nscheme is the restriction to Latin-based alphabets.  Other alphabets,\nlike Greek, Cyrillic or Asian, make extensive use of the bytes within\nthe range [128..255], and texts using these alphabets are most often\nmis-identified by this scheme; in other words, the rate of false\nnegatives is sometimes too high, which means that the recall is low.\nAnother weakness of this scheme is a reduced precision, due to the false\npositives that may occur when binary files containing a large amount of\ntextual characters are mis-identified as plain text.\n\nIn this article we propose a new detection scheme, with a much increased\naccuracy and precision, and a near-100% recall.  This scheme is designed\nto work on ASCII and ASCII-derived alphabets, and it handles single-byte\nalphabets (ISO-8859, OEM, KOI-8, etc.), and variable-sized alphabets\n(DBCS, UTF-8, etc.).  However, it cannot handle fixed-sized, multi-byte\nalphabets (UCS-2, UCS-4), nor UTF-16.  The principle used by this scheme\ncan easily be adapted to non-ASCII alphabets like EBCDIC.\n\n\nThe Algorithm\n-------------\n\nThe algorithm works by dividing the set of bytes [0..255] into three\ncategories:\n- The white list of textual bytecodes:\n  9 (TAB), 10 (LF), 13 (CR), 20 (SPACE) to 255\n- The gray list of tolerated bytecodes:\n  7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC)\n- The black list of undesired, non-textual bytecodes:\n  0 (NUL) to 6, 14 to 31.\n\nIf a file contains at least one byte that belongs to the white list, and\nno byte that belongs to the black list, then the file is categorized as\nplain text.  Otherwise, it is categorized as binary.\n\n\nRationale\n---------\n\nThe idea behind this algorithm relies on two observations.\n\nThe first observation is that, although the full range of 7-bit codes\n(0..127) is properly specified by the ASCII standard, most control\ncharacters in the range 0..31 are not used in practice.  The only\nwidely-used, almost universally-portable control codes are 9 (TAB),\n10 (LF), and 13 (CR).  There are a few more control codes that are\nrecognized on a reduced range of platforms and text viewers/editors:\n7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), and 27 (ESC); but these\ncodes are rarely (if ever) used alone, without being accompanied by\nsome printable text.  Even the newer, portable text formats, such as\nXML, avoid using control characters outside the list mentioned here.\n\nThe second observation is that most of the binary files tend to contain\ncontrol characters, especially 0 (NUL); even though the older text\ndetection schemes observe the presence of non-ASCII codes from the range\n[128..255], the precision rarely has to suffer if this upper range is\nlabeled as textual, because the files that are genuinely binary tend to\ncontain both control characters, and codes from the upper range.  On the\nother hand, the upper range needs to be labeled as textual,  because it\nis being used by virtually all ASCII extensions.  In particular, this\nrange is being heavily used to encode non-Latin scripts.\n\nGiven the two observations, the plain text detection algorithm becomes\nstraightforward.  There must be at least some printable material, or\nsome portable whitespace such as TAB, CR or LF, otherwise the file is\nnot labeled as plain text.  (The boundary case, when the file is empty,\nautomatically falls into this category.)  However, there must be no\nnon-portable control characters, otherwise it's very likely that the\nintended reader of that file is a machine, rather than a human.\n\nSince there is no counting involved, other than simply observing the\npresence or the absence of some byte values, the algorithm produces\nuniform results on any particular text file, no matter what alphabet\nencoding is being used for that text.  (In contrast, if counting were\ninvolved, it could be possible to obtain different results on a text\nencoded, say, using ISO-8859-2 versus UTF-8.)  There is the category\nof plain text files that are \"polluted\" with one or a few black-listed\ncodes, either by mistake, or by peculiar design considerations.  In such\ncases, a scheme that tolerates a small percentage of black-listed codes\nwould provide an increased recall (i.e. more true positives).  This,\nhowever, incurs a reduced precision, since false positives are also more\nlikely to appear in binary files that contain large chunks of textual\ndata.  \"Polluted\" plain text may, in fact, be regarded as binary, on\nwhich text conversions should not be performed.  Under this premise, it\nis safe to say that the detection method provides a near-100% recall.\n\nExperiments have been run on a large set of files of various categories,\nincluding plain old texts, system logs, source code, formatted office\ndocuments, compiled object code, etcetera.  The results confirm the\noptimistic assumptions about the high accuracy, precision and recall\noffered by this algorithm.\n\n\n--\nCosmin Truta\nLast updated: 2005-Feb-27\n"
  },
  {
    "path": "deps/infozip/zip30/proginfo/ziplimit.txt",
    "content": "ziplimit.txt\n\nZip 3 and UnZip 6 now support many of the extended limits of Zip64.\n\nA) Hard limits of the Zip archive format:\n\n   Number of entries in Zip archive:            64 k (2^16 - 1 entries)\n   Compressed size of archive entry:            4 GByte (2^32 - 1 Bytes)\n   Uncompressed size of entry:                  4 GByte (2^32 - 1 Bytes)\n   Size of single-volume Zip archive:           4 GByte (2^32 - 1 Bytes)\n   Per-volume size of multi-volume archives:    4 GByte (2^32 - 1 Bytes)\n   Number of parts for multi-volume archives:   64 k (1^16 - 1 parts)\n   Total size of multi-volume archive:          256 TByte (4G * 64k)\n\n   The number of archive entries and of multivolume parts are limited by\n   the structure of the \"end-of-central-directory\" record, where the these\n   numbers are stored in 2-Byte fields.\n   Some Zip and/or UnZip implementations (for example Info-ZIP's) allow\n   handling of archives with more than 64k entries.  (The information\n   from \"number of entries\" field in the \"end-of-central-directory\" record\n   is not really neccessary to retrieve the contents of a Zip archive;\n   it should rather be used for consistency checks.)\n\n   Length of an archive entry name:             64 kByte (2^16 - 1)\n   Length of archive member comment:            64 kByte (2^16 - 1)\n   Total length of \"extra field\":               64 kByte (2^16 - 1)\n   Length of a single e.f. block:               64 kByte (2^16 - 1)\n   Length of archive comment:                   64 KByte (2^16 - 1)\n\n   Additional limitation claimed by PKWARE:\n     Size of local-header structure (fixed fields of 30 Bytes + filename\n      local extra field):                     < 64 kByte\n     Size of central-directory structure (46 Bytes + filename +\n      central extra field + member comment):  < 64 kByte\n\n   Note:\n   In 2001, PKWARE has published version 4.5 of the Zip format specification\n   (together with the release of PKZIP for Windows 4.5).  This specification\n   defines new extra field blocks that allow to break the size limits of the\n   standard zipfile structures.  In this extended Zip format, the size limits\n   of zip entries (and the complete zip archive) have been extended to\n   (2^64 - 1) Bytes and the maximum number of archive entries to (2^32-1).\n   Zip 3.0 supports these Zip64 extensions and should be released shortly.\n   UnZip 6.0 should support these standards.\n\nB) Implementation limits of UnZip:\n\n   Note:\n   This section should be updated when UnZip 6.0 is near release.\n\n 1. Size limits caused by file I/O and decompression handling:\n   Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)\n   Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)\n\n   Note: On some systems, UnZip may support archive sizes up to 4 GByte.\n         To get this support, the target environment has to meet the following\n         requirements:\n         a) The compiler's intrinsic \"long\" data types must be able to hold\n            integer numbers of 2^32. In other words - the standard intrinsic\n            integer types \"long\" and \"unsigned long\" have to be wider than\n            32 bit.\n         b) The system has to supply a C runtime library that is compatible\n            with the more-than-32-bit-wide \"long int\" type of condition a)\n         c) The standard file positioning functions fseek(), ftell() (and/or\n            the Unix style lseek() and tell() functions) have to be capable\n            to move to absolute file offsets of up to 4 GByte from the file\n            start.\n         On 32-bit CPU hardware, you generally cannot expect that a C compiler\n         provides a \"long int\" type that is wider than 32-bit. So, many of the\n         most popular systems (i386, PowerPC, 680x0, et. al) are out of luck.\n         You may find environment that provide all requirements on systems\n         with 64-bit CPU hardware. Examples might be Cray number crunchers\n         or Compaq (former DEC) Alpha AXP machines.\n\n   The number of Zip archive entries is unlimited. The \"number-of-entries\"\n   field of the \"end-of-central-dir\" record is checked against the \"number\n   of entries found in the central directory\" modulus 64k (2^16).\n\n   Multi-volume archive extraction is not supported.\n\n   Memory requirements are mostly independent of the archive size\n   and archive contents.\n   In general, UnZip needs a fixed amount of internal buffer space\n   plus the size to hold the complete information of the currently\n   processed entry's local header. Here, a large extra field\n   (could be up to 64 kByte) may exceed the available memory\n   for MSDOS 16-bit executables (when they were compiled in small\n   or medium memory model, with a fixed 64kByte limit on data space).\n\n   The other exception where memory requirements scale with \"larger\"\n   archives is the \"restore directory attributes\" feature. Here, the\n   directory attributes info for each restored directory has to be held\n   in memory until the whole archive has been processed. So, the amount\n   of memory needed to keep this info scales with the number of restored\n   directories and may cause memory problems when a lot of directories\n   are restored in a single run.\n\nC) Implementation limits of the Zip executables:\n\n   Note:\n   This section has been updated to reflect Zip 3.0.\n\n 1. Size limits caused by file I/O and compression handling:\n   Without Zip64 extensions:\n    Size of Zip archive:                 2 GByte (2^31 - 1 Bytes)\n    Compressed size of archive entry:    2 GByte (2^31 - 1 Bytes)\n    Uncompressed size of entry:          2 GByte (2^31 - 1 Bytes),\n                                         (could/should be 4 GBytes...)\n   Using Zip64 extensions:\n    Size of Zip archive:                 2^63 - 1 Bytes\n    Compressed size of archive entry:    2^63 - 1 Bytes\n    Uncompressed size of entry:          2^63 - 1 Bytes\n   \n   Multi-volume archive creation now supported in the form of split\n   archvies.  Currently up to 99,999 splits are supported.\n\n 2. Limits caused by handling of archive contents lists\n\n 2.1. Number of archive entries (freshen, update, delete)\n     a) 16-bit executable:              64k (2^16 -1) or 32k (2^15 - 1),\n                                        (unsigned vs. signed type of size_t)\n     a1) 16-bit executable:             <16k ((2^16)/4)\n         (The smaller limit a1) results from the array size limit of\n         the \"qsort()\" function.)\n\n         32-bit executables:            <1G ((2^32)/4)\n         (usual system limit of the \"qsort()\" function on 32-bit systems)\n\n     b) stack space needed by qsort to sort list of archive entries\n\n     NOTE: In the current executables, overflows of limits a) and b) are NOT\n           checked!\n\n     c) amount of free memory to hold \"central directory information\" of\n        all archive entries; one entry needs:\n        96 bytes (32-bit) resp. 80 bytes (16-bit)\n        + 3 * length of entry name\n        + length of zip entry comment (when present)\n        + length of extra field(s) (when present, e.g.: UT needs 9 bytes)\n        + some bytes for book-keeping of memory allocation\n\n   Conclusion:\n     For systems with limited memory space (MSDOS, small AMIGAs, other\n     environments without virtual memory), the number of archive entries\n     is most often limited by condition c).\n     For example, with approx. 100 kBytes of free memory after loading and\n     initializing the program, a 16-bit DOS Zip cannot process more than 600\n     to 1000 (+) archive entries.  (For the 16-bit Windows DLL or the 16-bit\n     OS/2 port, limit c) is less important because Windows or OS/2 executables\n     are not restricted to the 1024k area of real mode memory.  These 16-bit\n     ports are limited by conditions a1) and b), say: at maximum approx.\n     16000 entries!)\n\n\n 2.2. Number of \"new\" entries (add operation)\n     In addition to the restrictions above (2.1.), the following limits\n     caused by the handling of the \"new files\" list apply:\n\n     a) 16-bit executable:              <16k ((2^64)/4)\n\n     b) stack size required for \"qsort\" operation on \"new entries\" list.\n\n     NOTE: In the current executables, the overflow checks for these limits\n           are missing!\n\n     c) amount of free memory to hold the directory info list for new entries;\n        one entry needs:\n        24 bytes (32-bit) resp. 22 bytes (16-bit)\n        + 3 * length of filename\n\n     NOTE: For larger systems, the actual limits may be more performance\n     issues (how long you want to wait) rather than available memory and other\n     resources.\n\nD) Some technical remarks:\n\n 1. For executables compiled without LARGE_FILE_SUPPORT and ZIP64_SUPPORT\n    enabled, the 2GByte size limit on archive files is a consequence of\n    the portable C implementation of the Info-ZIP programs.  Zip archive\n    processing requires random access to the archive file for jumping\n    between different parts of the archive's structure.  In standard C,\n    this is done via stdio functions fseek()/ftell() resp. unix-io functions\n    lseek()/tell().  In many (most?) C implementations, these functions use\n    \"signed long\" variables to hold offset pointers into sequential files.\n    In most cases, this is a signed 32-bit number, which is limited to\n    ca. 2E+09.  There may be specific C runtime library implementations\n    that interpret the offset numbers as unsigned, but for us, this is not\n    reliable in the context of portable programming.\n\n    If LARGE_FILE_SUPPORT and ZIP64_SUPPORT are defined and supported by\n    the system, 64-bit off_t file offsets are supported and the above\n    larger limits are supported.  As off_t is signed, the maximum offset\n    is usually limited to 2^63 - 1.\n\n 2. The 2GByte limit on the size of a single compressed archive member\n    is again a consequence of the implementation in C.\n    The variables used internally to count the size of the compressed\n    data stream are of type \"long\", which is guaranted to be at least\n    32-bit wide on all supported environments.\n\n    But, why do we use \"signed\" long and not \"unsigned long\"?\n\n    Throughout the I/O handling of the compressed data stream, the\n    sign bit of the \"long\" numbers is (mis-)used as a kind of overflow\n    detection. In the end, this is caused by the fact that standard C\n    lacks any overflow checking on integer arithmetics and does not\n    support access to the underlying hardware's overflow detection\n    (the status bits, especially \"carry\" and \"overflow\" of the CPU's\n    flags-register) in a system-independent manner.\n\n    So, we \"misuse\" the most-significant bit of the compressed data\n    size counters as carry bit for efficient overflow/underflow detection.\n    We could change the code to a different method of overflow detection,\n    by using a bunch of \"sanity\" comparisons (kind of \"is the calculated\n    result plausible when compared with the operands\"). But, this would\n    \"blow up\" the code of the \"inner loop\", with remarkable loss of\n    processing speed. Or, we could reduce the amount of consistency checks\n    of the compressed data (e.g. detection of premature end of stream) to\n    an absolute minimum, at the cost of the programs' stability when\n    processing corrupted data.\n\n    Summary: Changing the compression/decompression core routines to\n    be \"unsigned safe\" would require excessive recoding, with little\n    gain on maximum processable uncompressed size (a gain can only be\n    expected for hardly compressable data), but at severe costs on\n    performance, stability and maintainability.  Therefore, it is\n    quite unlikely that this will ever happen for Zip/UnZip.\n\n    With LARGE_FILE_SUPPORT and ZIP64_SUPPORT enabled and supported,\n    the above arguments still apply, but the limits are based on 64 bits\n    instead of 32 and should allow most large files and archives to be\n    processed.\n\n    Anyway, the Zip archive format is more and more showing its age...\n    The effort to lift the 2GByte limits should be better invested in\n    creating a successor for the Zip archive format and tools.  But given\n    the latest improvements to the format and the wide acceptance of zip\n    files, the format will probably be around for awhile more.\n\nPlease report any problems using the web contact form at:  www.Info-ZIP.org\n\nLast updated:  26 January 2002, Christian Spieler\n               25 May 2008, Ed Gordon\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/IZREADME.SMS",
    "content": "IZREADME_SMS (IZREADME.SMS): Info-ZIP for SMS/QDOS,   last revised: 15-Jun-1998\n===============================================================================\n[was \"InfoZIP_SMSQDOS_ReadMe\" in J. Hudson's original ports, ca. 08/1995]\n\nInfo-ZIP Programs\n=================\n\nZip\nUnZip\nUnZipSFX\nfUnZip\n\nIntroduction\n------------\n\nThis archive is a result of frustrations with contemporary (August 95)\nversions of Zip and UnZip. While they use the same compression\nalgorithms as the Info-ZIP programs, there the compatibility ends. If\nyou just use Zip/UnZip only on SMS/QDOS, then perhaps this is not a\nproblem (but I know for some users it still is); if you use Zip/UnZip\nto transport source code and data between diverse systems, then the\ndisregard for Info-ZIP standards is inconvenient, particularly the\nfact that directories are not supported and files are always stored\nunderscored.\n\nThis release of Zip/UnZip offers:\n\n    o   zipfile/directory compatibility with all other supported\n        platforms\n\n    o   SMS/QDOS compatibility and back-compatible with earlier\n        versions.\n\n    o   Improved performance (Zip is typically 50% faster)\n\n    o   Command-line compatibility with Info-ZIP\n\n    o   Self-extracting archives (but not very elegantly)\n\n    o   Archives are marked as 'created by SMS/QDOS'.\n\n    o   Optional recursion into directories\n\n    o   Directory structure restored on unzip of Info-ZIP/PKZIP-\n        compatible archives.\n\n    o   Config'urable for listing and unpack formats (Info-ZIP (.) or\n        SMS/QDOS (_) and 'Press any key' timeouts. Override options\n        from command line.\n\nInfo-ZIP Standards\n------------------\n\nThis (rather long-winded and waffling) section discusses the\nconventions and standards used by Info-ZIP-compatible archivers and how\n\"Info-ZIP for SMS/QDOS\" achieves compatibility.\n\nInfo-ZIP Zip/UnZip on all supported platforms (Unix, DOS, OS/2, NT,\nVAX/VMS, Amiga etc etc), works in a specific way. (Until now SMS/QDOS\nwas neither 'supported' nor Info-ZIP-compliant.)\n\n    a. The zipfile directory is in (/.) (Unix) format.\n\n    b. When zips are listed, it is in 'zipfile' (Unix) format.\n\n    c. When files are added, they are defined in native format.\n\n    d. When files are added, this is shown in 'zipfile' format.\n\n    e. When files are unpacked, this is done to native format, but\n       selection is done in 'zipfile' format.\n\nBasically, the listing and stored format of a file is that of the\ndestination.\n\nSo, given a file structure at some arbitrary 'root' level.\n\n    Makefile\n    src (Dir)\n        afile.c\n        bfile.c\n        docs (Dir)\n             prog.txt\n    hdr (Dir)\n        cfile.h\n        dfile.h\n\nThen these would be in Unix (and Amiga) as\n\n     Makefile\n     src/afile.c\n     src/bfile.c\n     src/docs/prog.txt\n     hdr/cfile.h\n     hdr/dfile.h\n\nThis is also how the zipfile directory appears.\n\nAnd in DOS/OS2/NT\n\n    Makefile\n    src\\afile.c\n    src\\docs\\prog.txt\n    hdr\\cfile.h         .. etc\n\nAnd in VMS      (we SHOUT in VMS and have a silly file system)\n\n    MAKEFILE\n    [SRC]AFILE.C\n    [SRC.DOC]PROG.TXT\n    [HDR]CFILE.H        .. etc\n                        (OK VMS purist, [.SRC] etc. Only an example)\n\nAnd in SMS/QDOS (quiet again, but slightly ludicrous !)\n\n    Makefile\n    src_afile_c\n    src_doc_prog_txt\n    hdr_cfile_h         .. etc\n\nThe main problem regarding SMS/QDOS is not that of extensions - (after\nall, only VMS and DOS _really_ have extensions; Unix, AmigaDOS, NT and\nOS/2 (and Win95) allow multiple '.' in.long.file.names.\n\nThe SMS/QDOS problem is that '_' is both a legal file name character\nand a directory separator. This creates the difficulties, as\ndirectories and files are somewhat different objects.\n\nIt is the intention that these versions of SMS/QDOS Zip/UnZip will\nfollow the Info-ZIP rules, thus providing compatibility with the other\nplatforms. It is possible to zip the file structure described above on\nSMS/QDOS and unpack it on VMS and get the VMS structure as shown in the\nexample (and vice-versa). [We only choose the most obtuse file\nsystems for the examples].\n\nIn order to achieve this, SMS/QDOS names are mapped into Unix-style\nones when the zipfile is created and un-mapped when it is unpacked.\nThere is an option to unpack in 'zipfile' format (i.e. with '.' rather\nthan '_'), but there will be no option to pack to all '_'. That would\ncontravene the standard.  However, a file\n\n        src_split_name_c        (which is src->split_name_c !)\n                                          src/split_name.c)\n\nwhere src is a hard directory, would be stored in the zip directory as\n\n      src/split_name.c\n\nIt does handle '_' with a little intelligence.\n\nThe default UnZip option will be to translate '.' to '_'; this is\nbecause there are still many QDOS/Minerva users that cannot handle '.'\nwithout quotes, which is immensely inconvenient. For many SMS users\n'_' is also the most natural and convenient option. It also means that\nSMS/QDOS <-> SMS/QDOS Zip - UnZip sequences are transparent.\n\nThere will, however, be two ways around this in UnZip.\n\n      1. It is possible to Config the UnZip default to be '.'\n         translations (or not).\n\n      2.  The UnZip -Q1 option will toggle the default (Config'ed)\n          state.\n\nExamples:\n\nGiven that we want/have\n\n     Makefile                   (Makefile)\n     src/afile.c                (src_afile_c)\n     src/bfile.c                (src_bfile_c)\n     src/docs/prog.txt          (src_docs_prog_txt)\n     hdr/cfile.h                (hdr_cfile_h)\n     hdr/dfile.h                (hdr_dfile_h)\n\nThen on SMS/QDOS we might have added the *.c files as\n\n     ex zip;'-r test *_c'\n\n(or VMS, just to do something different)\n\n    zip -r test [.src]*.c\n\nIn both cases the file lists as above (left).\n\nTo unpack on SMS/QDOS (just the _c/.c files)\n\n   ex unzip;'test src/*.c'\n\n   (and VMS, unzip test src/*.c)\n\ni.e. in both cases using the 'zipfile' format. As a concession to\nSMS/QDOS, you could also have:\n\n   ex unzip;'test src_*_c'\n\n        but not unzip test [.src]*.c on VMS !!!!! Sorry, dinosaurs.\n\nBoth SMS/QDOS commands unpack to\n\n     src_afile_c etc, where src_ is a hard sub-directory.\n\n(and the VMS example would unpack to [.src]afile.c, (or to src\\afile.c on\nDOS/NT/OS2 etc).\n\nOptions & SMS/QDOS Features\n---------------------------\n\nThe options supported by Zip/UnZip are basically those documented in\nthe Info-ZIP documents and shown in on-line 'usage'. In particular, -r\nand -j work as intended.\n\nPLEASE NOTE: Previous SMS/QDOS zip/unzips have NOT followed these\nconventions, for example -r was not implemented and -j was reversed.\n\nA number of -Q (SMS/QDOS-specific) options (not yet in the current\ndocuments or usage screens) are implemented.\n\nThe Zip 2.0.1 (and later) default is to add SMS/QDOS headers where\nfile type = 1 (exe) or 2 (rel) or (type > 0 && != 255 and (filesize %\n64) != 0). Directories are included anyway, unless you zip -D.\n\nWhere a header is added for an 'exe' file a '*' is displayed after the\nname in the zip display  (and '#' for 'rel' files).\n\nThe -Q options for Zip are:\n\n    -Q1  Don't add headers for ANY files\n    -Q2  Add headers for all files\n    -Q4  Don't wait for interactive key press\n\n    (additive, so -Q5 => no headers, no wait, -Q6 all headers,\n     no wait etc)\n\n    (the default is exec/rel headers, 5 sec wait)\n\nZip has rationalised the file header storage in zipfiles. The\nprevious Zip used to store a QDOS header for each file. This was very\nwasteful, for example compressing a SMS/QDOS release of PGP in this\nway came to 730Kb, too large for a DD disk. Changing the Zip program\njust to add a header record for the single PGP exe and the zipfile\nsize went down to around 690Kb.\n\nAnd for UnZip\n\n    -Q1 Toggle unpack format status ('.' <-> '_')\n    -Q2 Toggle listing format\n    -Q4 Don't wait for key press\n\nFiles Types\n-----------\n\nThe history of QDOS suffers from incompatible feature\nimplementations. For example, Thor directories have file type 3, CST\nhave type 4 and Level 2 have type 255. Some software writers (both\namateur and otherwise) have used type 3 or 4 for other purposes\n(backward compatibility ?? who cares ??).\n\nIn order to bypass problems cause by incompatible (inconsiderate ?)\nusage of file types, the file type denoting a directory is a\nConfig'urable item. The default is set to -1 (65535 in Config terms),\nwhich means \"determine directory type from the file header of the root\ndirectory\". If this is appears unsuccessful on your system, the value\ncan be Config'ed in the range 3-255.\n\nZip assumes a file is a directory if:\n\n        ((type == CONFIGed_type) && (file_size % 64) == 0)\n\nIf you are unfortunate enough have files of that pass this test but\nare not directories, then Zip will loop endless, as SMS/QDOS opens the\nroot directory again !!! (recursion: see recursion etc).\n\nI suggest you refrain from zipping such files and contact the software\nsupplier and point out the error of their ways.\n\nFile Naming Issues\n------------------\n\nZip will append a '_zip' suffix to the archive filename when the\nsupplied name (i.e. excluding device/directory parts) does not\ncontain a '_' or a '.'. This is broadly compatible with Info-ZIP,\ntaking into account the '_' aberation.\n\nSo\n        ex zip;'ram2_test ...'          >> ram2_test_zip\n\n        ex zip;'ram2_test.zip ...'      >> ram2_test.zip\n\n        ex zip;'ram2_test_rep ... '     >> ram2_test_rep\n\n        ex zip;'ram2_fdbbs.rep ... '    >> ram2_fdbbs.rep\n\n        ex zip;'ram2_test_rep.zip ...'  >> ram2_test_rep.zip\n\nThis implies that if a file ram2_test.zip exists, and you do:\n\n        ex zip;'ram2_test ...'\n\nThen a new file (test_zip) is created, rather than 'test.zip' being\nupdated.\n\nZip supports extensive recursive wild-carding, again the fact that '_'\ncan be a directory separator as well as part of a file name makes this\na bit tricky, but given the example:\n\n     test1_bas\n     test2_bas\n     dir1->demo1_bas            where -> indicates a sub dir\n     dir2->demo2_bas\n\n     ex zip;'ram2_test *_bas'\n     just finds test1_bas, test2_bas\n\n     ex zip;'-r ram2_test *_bas'\n     recurses and finds all the files\n\nYou might think that\n\n    ex zip;'-r ram2_test *_*_bas'\n\nwould just find the files in the subdirectories--well yes, but it will\nalso find very other sub-dir'ed _bas file on the disk too. This is\na feature.\n\nThe pattern matching supports Unix-style 'regex' so you could:\n\n        ex zip;'ram2_test dir?_*_bas'\n        or\n        ex zip;'ram2_test dir[12]_*_bas\n\n\nUnZip has now got a fixed -d option. This is used to specify the\ndirectory to unpack the zipfile into, it must follow immediately\nafter the zip name.\n\n        ex unzip;'ram2_test_zip -d ram3_ *_txt'\n\nwould unpack all *_txt files to ram3_ .\n\nIt is not necessary to set the default directory to pack files, Zip\nwill remove any device names (and store any hard directory names,\nunless you zip -j).\n\n        ex zip;'ram1_test flp1_*'\n\n                ----->\n                        adding: file.dat (deflated 50%)\n                        adding: menu.rext # (deflated xx%)\n                        adding: zip * (deflated yy%)\n                        adding: hard_one (stored 0%)\n                        adding: hard_one/stuff.bas (deflated ...)\n\nDue to the way the file-mapping is implemented, it is not supported\nover the nX_ type network device.\n\nConfig Options\n--------------\n\nA limited number of SMS/QDOS specific functions can be set using the\nQJump Config program.\n\n      For Zip:\n\n      Timeout for interactive 'Press any key' prompt\n\n       65535                  Wait forever      (aka -1)\n       0                      No wait\n       n (1-32767)            Wait for 'n' clocks (1/50 sec)\n\n       Other values are unsupported. Note Config works on 'unsigned'\n       integer values (at least according to my manual).\n\n       Directory file type key.\n\n       Config will accept any value in the range 3-255, known useful\n       values are 3 (Thor), 4 (CST) and 255 (Level 2 devices). A value\n       of 65535 (aka -1) means \"determine from device info\".\n\n       For UnZip:\n\n       Timeout as above\n\n       Unpack mode (SMS/QOS ('_') or Info-ZIP ('.')\n\n       List format (Info-ZIP ('.') or SMS/QDOS ('_')\n\n\nWhen the 'Press a key' text is displayed, if you press ESC, then it\nwaits until you press any other key, infinite timeout. This may be\nuseful if you want (much) more time to study a listing etc.\n\nDefaults for timeout and directory type are 250 and -1 respectively.\n\nMore Goodies\n------------\n\nPart of the Zip compression code is now in assembler; it runs\nnoticably faster than the previous version. Compressing some arbitrary\nfiles with the previous Zip it took 251 seconds, with Zip 2.0.1 it\ntook (a mere) 170 seconds (68008 QL).\n\nMore good news is that SMS/QDOS is just another system option on top\nof standard Info-ZIP, unlike the previous ports that were much more\nSMS/QDOS specific. For example, compiling the standard source with c68\n(i.e. #define QDOS), then you get an SMS/QDOS version.\n\nCompile with Linux/gcc and get the standard Linux version. Now, here's\nthe cool bit; compile with Linux/gcc and \"-DQLZIP\", and get a standard\nLinux Zip/UnZip with SMS/QDOS (header) extensions.\n\nso, on Linux:\n\n            zip -Q stuff.zip qtpi zip unzip\n\nthe -Q tells Zip to look for XTc68/Lux68 cross-compiler data size\nblocks and produce a zipfile with SMS/QDOS headers in it (for exec\ntype programs). This works for exec files produced by the XTc68/Lux68\ncross compilers and ANY SMS/QDOS files copied to a Unix or MS-DOS disk\nfrom an SMS/QDOS floppy using 'qltools v2.2' (or later).\n\nSelf Extracting Archives\n------------------------\n\nInfo-ZIP self-extracting archives (_sfx) are created in a rather\n'brute-force' way. The UnZipSFX program is prepended to a zipfile.\n\ni.e.          file_sfx = unzipsfx + file_zip\n              ex file_sfx\n\nAlthough the UnZipSFX program is a cut-down UnZip, it is still around\n30Kb - 50Kb, depending on platform.\n\nThe success of this approach depends on how the operating system\nloader loads executable files. On most systems where the loader only\nloads the actual program part (Unix, VMS, DOS et al), the this is\nquite efficient; if you make, say, a 4Mb zipfile and prepend a 30Kb\nUnZipSFX image, then the system only loads the 30Kb program and the\nprocess is efficient as the zipped data part is still unpacked from\ndisk. These systems also supply the running UnZipSFX program stub with\nthe path name of the file it was loaded from, so the program knows\nwhat it has to unpack (so on Linux, for example):\n\n     cat /usr/bin/unzipsfx test.zip > test.sfx  # concatenate the files\n     chmod 755 test.sfx                         # make executable\n     test.sfx                                   # to extract, it\n                                                # 'knows' it is \"test.sfx\"\n\nUnfortunately, the more simplistic nature of SMS/QDOS makes this much\nmore difficult and rather less efficient as: (see note 1)\n\n     a. The SMS/QDOS 'loader' loads the whole file into memory.\n\n     b. The SMS/DOS 'loader'/c68 run-time system does not return the\n        name of the file from which it was loaded.\n\n     c. You cannot so easily create a image file by concatenating two\n        files, it is also necessary to ensure the executable file\n        header is set correctly.\n\n     d. The show stopper. The data space required for the\n        self-extracting archive is required, as not easily maintained\n        during electronic transfer.\n\n\nIf anyone is still interested, then the following support for UnZipSFX\nis provided.\n\n o A program 'makesfx' will combine a stub (callstub), UnZipSFX image\n   and a zipfile to produce a sfx (self-extracting zip) file.\n\n o A callable interface is supplied. The user calls the SFX file,\n   which creates the files necessary to do the extraction.\n\nThe makesfx program concatenates the supplied files to standard\noutput.\n\nSo, to create a sfx of all the _c files in the default directory.\n\n # 1st create a zipfile of the required files\n\n ex zip;'ram1_test_zip *_c'\n\n # Now create the sfx file (ram2_test_sfx)\n # our UnZipSFX image is in 'win1_bin'\n # as is the call stub.\n\nex makesfx;'-o test_sfx -x win1_bin_unzipsfx -s win1_bin_callstub -z ram1_test_zip'\n\nThe arguments to makesfx are:\n\n    -s stubfile\n    -x UnZipSFX_program\n    -z Zip_file\n    -o Output_file\n\nYou can now unpack the _sfx file on any SMS/QDOS-compatible\nsystem.\n\n        f$ = \"win2_tmp_test_sfx\"\n        a = alchp(flen(\\f$))\n        lbytes f$,a\n        call a\n        rechp(a)\n\nZipInfo\n-------\n\nGiven the above note concerning SMS/QDOS programs not knowing the name\nby which the program was invoked, then the usual symbolic-link-of-unzip-\nto-zipinfo trick is unavailable (presupposing there is some some SMS/QDOS\ntrick to emulate symbolic links).\n\nZipInfo functionality is only available via 'unzip -Z'. There is no\nseparate ZipInfo program.\n\nCaveat ATP Users\n----------------\n\nATP for SMS/QDOS users should pay particular attention to the\nZip/UnZip options in their atprc and compare with Info-ZIP Zip/UnZip\nusage. Older versions of Zip/UnZip screwed up -j.\n\n\n        zip -jk\n        unzip -jo\n\nDistribution & Copyright\n------------------------\n\nThis software is written by and largely copyrighted by the 'Info-ZIP'\ngroup whose members are noted in the accompanying documentation. This\nparticular SMS/QDOS port plus 'makesfx' was written by, but is not\ncopyrighted by, Jonathan R Hudson. The SMS/QDOS code in this release\nis written from scratch and is not dependent on previous SMS/QDOS\nreleases, but is (largely) compatible.\n\nAs a courtesy to the authors of this package, please ensure that the\ndocumentation is supplied when it is re-distributed.\n\nIn particular, if this archive is split into Zip and UnZip components,\nensure that this document (\"IZREADME_SMS\") is supplied in\neach component.\n\nSMS/QDOS version by:\nJonathan R Hudson (jrhudson@bigfoot.com)\n\nI am grateful to Graham Goodwin for finding some most imaginative\nmeans of breaking the beta code.\n\nI'd also like to thank Thierry Godefroy for providing the 2.1/5.2\nsource code and making the initial contact with the Info-ZIP group.\n\nAnd of course, many, many thanks to the Info-ZIP workers for making\nthis code freely available.\n\nNote 1\n------\n\nThe 'C' language FAQ ('frequently asked questions' [comp.lang.c])\nnotes on the matter of obtaining the load file name of a 'C' program:\n\n16.5:   How can my program discover the complete pathname to the\n        executable file from which it was invoked?\n\nA:      argv[0] may contain all or part of the pathname, or it may\n        contain nothing.  You may be able to duplicate the command\n        language interpreter's search path logic to locate the\n        executable if the name in argv[0] is present but incomplete.\n        However, there is no guaranteed or portable solution.\n                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nNote 2\n------\n\nNUL files for SMS2. There appears to be a conflict between SMS2/LBASIC\ncompiled programs and c68 programs using nul as stdin.\n\n        EW zip,nul;'ram1_test *_bas'    # will not work\n\n                                        # This does work !\n        EW zip,#FOP_IN('nul');'ram2_test *_bas' : CLOSE\n\nNote 3\n------\n\nversion number incremented to 2.0.1a and 5.12a to accomodate Erling\nJacobsen's exit message requirements\n\nversion number incremented to Zip 2.0.1b to fix bug on zipping files\nstarting with leading underscore.\n\nversion number incremented to UnZip 5.12b to fix UnZip problem on\nfiles zipped with leading './', and linked with revised (fixed) c68\n'utime' function (could corrupt level 1 files). (source code _only_ as\nIZQ004.zip).\n\nPorted Zip 2.1 and UnZip 5.2 (July 1996). Released as INZIP005.zip\n\nAll later versions --- see Info-ZIP release notes and documentation.\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/Makefile.qdos",
    "content": "include /etc/ql.mak\n\n# Makefile for Zip, ZipNote, ZipCloak and ZipSplit\n\nMAKE = make\nSHELL = /bin/sh\n\n#\nBIND = $(CC)\n\n# probably can change this to 'install' if you have it\nINSTALL = cp\n\n# target directories - where to install executables and man pages to\nBINDIR =\nmanext=1\nMANDIR =\nZIPMANUAL = MANUAL\n\n# flags\n#   CFLAGS    flags for C compile\n#   LFLAGS1   flags after output file spec, before obj file list\n#   LFLAGS2   flags after obj file list (libraries, etc)\nCFLAGS = -O -DASMV -DASM_CRC\nLFLAGS1 = -v\n#LFLAGS2 = -lutime\n\nall: zip\n\n# object file lists\nOBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o qdos.o ttyio.o\nOBJI = deflate.o trees.o qfileio.o crc32.o\nOBJA = config.o crc68.o match.o\n#  crc32.o\nOBJQ = qdos_.o config.o qfileio_.o\nOBJU = zipfile_.o fileio_.o util_.o globals.o $(OBJQ)\nOBJN = zipnote.o  $(OBJU)\nOBJC = zipcloak.o $(OBJU) crc32_.o crypt_.o\nOBJS = zipsplit.o $(OBJU)\n\n\n# suffix rules\n.SUFFIXES:\n.SUFFIXES: _.o .o .c .doc .1\n.c_.o:\n\trm -f $*_.c; ln $< $*_.c\n\t$(CC) $(CFLAGS) -DUTIL -c $*_.c\n\trm -f $*_.c\n.c.o:\n\t$(CC) $(CFLAGS) -c $<\n\n.1.doc:\n\tnroff -man $< | col -b | uniq > $@\n\n# rules for zip, zipnote, zipcloak, zipsplit, and zip.doc.\n$(OBJZ): zip.h ziperr.h tailor.h\n$(OBJI): zip.h ziperr.h tailor.h\n$(OBJN): zip.h ziperr.h tailor.h\n$(OBJS): zip.h ziperr.h tailor.h\n$(OBJC): zip.h ziperr.h tailor.h\nzip.o zipup.o crc32.o crypt.o fileio.o zipfile.o:  crc32.h\nzipcloak.o crc32_.o crypt_.o fileio_.o zipfile_.o:  crc32.h\nzip.o zipup.o crypt.o zipup_.o zipcloak.o crypt_.o:  crypt.h\n\nqfileio.o: qdos/qfileio.c\n\tcp qdos/qfileio.c qfileio.c\n\t$(CC) $(CFLAGS) -c qfileio.c\n\trm -f qfileio.c\n\nqfileio_.o: qdos/qfileio.c\n\tcp qdos/qfileio.c qfileio_.c\n\t$(CC) $(CFLAGS) -DUTIL -c qfileio_.c\n\trm -f qfileio_.c\n\nmatch.o: qdos/match.s\n\tcp qdos/match.s ./_match.s\n\t$(AS) _match.s -o match.o\n\trm -f _match.s\n\ncrc68.o: qdos/crc68.s\n\tcp qdos/crc68.s ./crc68.s\n\t$(AS) crc68.s -o crc68.o\n\trm -f crc68.s\n\nconfig.o: qdos/config.s\n\tcp qdos/config.s ./config.x\n\t$(CC) -c -DZIP config.x -o config.o\n\trm -f config.x\n\nZIPS = zip$E zipnote$E zipsplit$E zipcloak$E\n\nzip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h\nzips: $(ZIPS)\nzipsman: $(ZIPS) $(ZIPMANUAL)\n\nqdos.o:   qdos/qdos.c\n\tcp qdos/qdos.c .\n\t$(CC) -c -oqdos.o qdos.c\n\trm -f qdos.c\n\nqdos_.o:  qdos/qdos.c\n\tcp qdos/qdos.c ./qdos_.c\n\t$(CC) -DUTIL -c -oqdos_.o qdos_.c\n\trm -f qdos_.c\n\nzip$E: $(OBJZ) $(OBJI) $(OBJA)\n\t$(BIND) -o zip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)\nzipnote$E: $(OBJN)\n\t$(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)\nzipcloak$E: $(OBJC)\n\t$(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)\nzipsplit$E: $(OBJS)\n\t$(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)\n\n$(ZIPMANUAL): man/zip.1\n\tnroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)\n\n# install\ninstall:        $(ZIPS)\n\t$(INSTALL) $(ZIPS) $(BINDIR)\n\t$(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)\n\nuninstall:\n\t-cd $(BINDIR); rm -f $(ZIPS)\n\t-cd $(MANDIR); rm -f zip.$(manext)\n\nflags:  configure\n\tsh configure flags\n\n# These symbols, when #defined using -D have these effects on compilation:\n# ZMEM          - includes C language versions of memset(), memcpy(), and\n#                 memcmp() (util.c).\n# SYSV          - use <sys/dirent.h> and the library opendir()\n# DIRENT        - use <sys/dirent.h> and getdents() instead of <sys/dir.h>\n#                 and opendir(), etc. (fileio.c).\n# NODIR         - used for 3B1, which has neither getdents() nor opendir().\n# NDIR          - use \"ndir.h\" instead of <sys/dir.h> (fileio.c).\n# UTIL          - select routines for utilities (note, cloak, and split).\n# PROTO         - enable function prototypes.\n# RMDIR         - remove directories using a system(\"rmdir ...\") call.\n# CONVEX        - for Convex make target.\n# AIX           - for AIX make target.\n# LINUX         - for linux make target.\n\n# end of Makefile\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/Makefile.qlzip",
    "content": "# Makefile for Zip, ZipNote, ZipCloak and ZipSplit\n\n# what you can make ...\nall: zip\n\n#MAKE = make -f unix/Makefile\nSHELL = /bin/sh\n\n# (to use the Gnu compiler, change cc to gcc in CC and BIND)\nCC = cc\nBIND = $(CC)\nAS = $(CC) -c\nE =\nCPP = /lib/cpp\n\n# probably can change this to 'install' if you have it\nINSTALL = cp\n\n# target directories - where to install executables and man pages to\nprefix = /usr/local\nBINDIR = $(prefix)/bin\nmanext=1\nMANDIR = $(prefix)/man/man$(manext)\nZIPMANUAL = MANUAL\n\n# flags\n#   CFLAGS    flags for C compile\n#   LFLAGS1   flags after output file spec, before obj file list\n#   LFLAGS2   flags after obj file list (libraries, etc)\nCFLAGS = -O2 -fno-strength-reduce -I. -DUNIX -DQLZIP -DASM_CRC\nLFLAGS1 =\nLFLAGS2 = -s\n\n# object file lists\nOBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crypt.o ttyio.o \\\n       unix.o crc_gcc.o crc32.o qdos.o\nOBJI = deflate.o trees.o\nOBJA =\nOBJU = zipfile_.o fileio_.o util_.o globals.o unix_.o\nOBJN = zipnote.o  $(OBJU)\nOBJC = zipcloak.o $(OBJU) crc32_.o crypt_.o ttyio.o\nOBJS = zipsplit.o $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h unix/osdep.h\n\n# suffix rules\n.SUFFIXES:\n.SUFFIXES: _.o .o .c .doc .1\n.c_.o:\n\trm -f $*_.c; ln $< $*_.c\n\t$(CC) -c $(CFLAGS) -DUTIL $*_.c\n\trm -f $*_.c\n.c.o:\n\t$(CC) -c $(CFLAGS) $<\n\n.1.doc:\n\tnroff -man $< | col -b | uniq > $@\n\n# rules for zip, zipnote, zipcloak, zipsplit, and the Zip MANUAL.\n$(OBJZ): $(ZIP_H)\n$(OBJI): $(ZIP_H)\n$(OBJN): $(ZIP_H)\n$(OBJS): $(ZIP_H)\n$(OBJC): $(ZIP_H)\nzip.o zipup.o crypt.o fileio.o zipfile.o: crc32.h\nzipcloak.o crc32_.o crypt_.o fileio_.o zipfile_.o: crc32.h\nzip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h\nzip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h\nzip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h\nzipup.o: unix/zipup.h\n\nmatch.o: match.S\n\t$(CPP) match.S > _match.s\n\t$(AS) _match.s\n\tmv _match.o match.o\n\trm -f _match.s\n\nunix.o: unix/unix.c\n\t$(CC) -c $(CFLAGS) unix/unix.c\n\nunix_.o: unix/unix.c\n\trm -f $*_.c; ln unix/unix.c $*_.c\n\t$(CC) -c $(CFLAGS) -DUTIL $*_.c\n\trm -f $*_.c\n\nqdos.o: qdos/qdos.c\n\t$(CC) -c $(CFLAGS) qdos/qdos.c\n\ncrc_gcc.o: crc_i386.S\t\t\t# 32bit, GNU AS\n\tgcc -O3 -I. -DASM_CRC -Di386 -x assembler-with-cpp -c -o $@ crc_i386.S\n\nZIPS = zip$E zipnote$E zipsplit$E zipcloak$E\n\nzips: $(ZIPS)\nzipsman: $(ZIPS) $(ZIPMANUAL)\n\nzip$E: $(OBJZ) $(OBJI) $(OBJA)\n\t$(BIND) -o qlzip$E $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)\nzipnote$E: $(OBJN)\n\t$(BIND) -o zipnote$E $(LFLAGS1) $(OBJN) $(LFLAGS2)\nzipcloak$E: $(OBJC)\n\t$(BIND) -o zipcloak$E $(LFLAGS1) $(OBJC) $(LFLAGS2)\nzipsplit$E: $(OBJS)\n\t$(BIND) -o zipsplit$E $(LFLAGS1) $(OBJS) $(LFLAGS2)\n\n$(ZIPMANUAL): man/zip.1\n\tnroff -man man/zip.1 | col -b | uniq > $(ZIPMANUAL)\n\n# install\ninstall:        $(ZIPS)\n\t$(INSTALL) $(ZIPS) $(BINDIR)\n\t$(INSTALL) man/zip.1 $(MANDIR)/zip.$(manext)\n\nuninstall:\n\t-cd $(BINDIR); rm -f $(ZIPS)\n\t-cd $(MANDIR); rm -f zip.$(manext)\n\ndist:\n\tzip -u9T zip`sed -e '/VERSION/!d' -e 's/.*\"\\(.*\\)\".*/\\1/' \\\n\t\t\t  -e s/[.]//g -e q revision.h` \\\n\t  `awk '/^Makefile/,/vms_zip.rnh/ {print $$1}' < contents`\n\nflags:  unix/configure\n\tsh unix/configure \"${CC}\" \"${CFLAGS}\"\n\n# These symbols, when #defined using -D have these effects on compilation:\n# ZMEM                  - includes C language versions of memset(), memcpy(),\n#                         and memcmp() (util.c).\n# HAVE_DIRENT_H         - use <dirent.h> instead of <sys/dir.h>\n# NODIR                 - for 3B1, which has neither getdents() nor opendir().\n# HAVE_NDIR_H           - use <ndir.h> (unix/unix.c).\n# HAVE_SYS_DIR_H        - use <sys/dir.h>\n# HAVE_SYS_NDIR_H       - use <sys/ndir.h>\n# UTIL                  - select routines for utilities (note, cloak, split)\n# NO_RMDIR              - remove directories using a system(\"rmdir ...\") call.\n# NO_PROTO              - cannot handle ANSI prototypes\n# NO_CONST              - cannot handle ANSI const\n\n#               Generic targets:\n\n# end of Makefile\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/config.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n#\n.globl _qlflag\n.globl _qlwait\n#ifdef ZIP\n.globl _dtype\n#endif\n\n.data\n        ds.w    0\n        dc.b    '<<QCFX>>01'\n#ifdef ZIP\n        dc.w    8\n        dc.b    'Info-ZIP'\n*                12345678901234567890\n        ds.w    0\n        dc.w    4\n        dc.b    'qdos'\n        ds.w    0\n#else\n        dc.w    10\n        dc.b    'Info-UNZIP'\n*                12345678901234567890\n        ds.w    0\n        dc.w    4\n        dc.b    'qdos'\n        ds.w    0\n#endif\n        dc.b    10\n        dc.b    0\nl_4:    dc.w    _qlwait-l_4\n        dc.w    0\n        dc.w    0\nl_5:    dc.w    hpt-l_5\nl_6:    dc.w    hxx-l_6\n\n#ifdef ZIP\n        dc.b    10\n        dc.b    0\nd_4:    dc.w    _dtype-d_4\n        dc.w    0\n        dc.w    0\nd_5:    dc.w    dpt-d_5\nd_6:    dc.w    dxx-d_6\n\n#else\n        dc.b    4\n        dc.b    0\nl5:\n        dc.w    list1-l5\n        dc.w    0\nl5a:\n        dc.w    Postit-l5a              ; post proc\nl6:\n        dc.w    apt-l6\nl7:\n        dc.w    axx-l7\n* -------------------------------------\n        dc.b    4\n        dc.b    0\nl8:\n        dc.w    list2-l8\n        dc.w    0\nl8a:\n        dc.w    Postit-l8a              ; post proc\nl9:\n        dc.w    bpt-l9\nla:\n        dc.w    bxx-la\n* -------------------------------------\n#endif\n        dc.w    -1                          ; end\n\n_qlflag:\n        dc.w    0\n_qlwait:\n        dc.w    250\n_dtype:\n        dc.w    255\n\nhpt:    dc.w    10\n        dc.b    'Exit Delay'\n*                12345678901234567890\n        ds.w    0\nhxx:    dc.w    0\n        dc.w    $ffff\n        dc.w    -1\n#ifdef  ZIP\ndpt:    dc.w    14\n        dc.b    'Directory Type'\n*                12345678901234567890\n        ds.w    0\ndxx:    dc.w    3\n        dc.w    $ff\n        dc.w    -1\n#else\n\nlist1:\n        dc.b    0\nlist2:\n        dc.b    0\n\napt:\n        dc.w    11\n        dc.b    'Unpack Mode'\n*                12345678901234567890\n.even\naxx:    dc.b    0\n        dc.b    0\n        dc.w    8\n        dc.b    'SMS/QDOS'\n.even\n        dc.b    1\n        dc.b    0\n        dc.w    7\n        dc.b    'Default'\n.even\n        dc.w    -1\n.even\nbpt:\n        dc.w    12\n        dc.b    'Listing Mode'\n*                12345678901234567890\n.even\nbxx:\n        dc.w    0\n        dc.w    7\n        dc.b    'Default'\n.even\n        dc.b    2\n        dc.b    0\n        dc.w    8\n        dc.b    'SMS/QDOS'\n*                12345678901234567890\n.even\n         dc.w    -1\nPostit:\n        lea.l   _qlflag,a0\n        move.b  list1,d0\n        move.b  d0,(a0)\n        move.b  list2,d0\n        or.b    d0,(a0)\n        moveq   #0,d0\n        rts\n#endif\n        end\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/crc68.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n.text\n\n.globl  _crc32          ; (ulg val, uch *buf, extent bufsize)\n.globl  _get_crc_table  ; ulg *get_crc_table(void)\n\n_crc32:\n        move.l  8(sp),d0\n        bne    valid\n        moveq  #0,d0\n        rts\nvalid:  movem.l d2/d3,-(sp)\n        jsr     _get_crc_table\n        move.l  d0,a0\n        move.l  12(sp),d0\n        move.l  16(sp),a1\n        move.l  20(sp),d1\n        not.l   d0\n\n        move.l  d1,d2\n        lsr.l   #3,d1\n        bra     decr8\nloop8:  moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\n        moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\ndecr8:  dbra   d1,loop8\n        and.w   #7,d2\n        bra     decr1\nloop1:  moveq  #0,d3\n        move.b (a1)+,d3\n        eor.b  d0,d3\n        lsl.w  #2,d3\n        move.l 0(a0,d3.w),d3\n        lsr.l  #8,d0\n        eor.l  d3,d0\ndecr1:  dbra   d2,loop1\ndone:   movem.l (sp)+,d2/d3\n        not.l   d0\n        rts\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/match.s",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; match.a -- optional optimized asm version of longest match in deflate.c\n; Written by Jean-loup Gailly\n;\n; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>\n; using the code in match.S.\n; The major change in this code consists of removing all unaligned\n; word accesses, because they cause 68000-based Amigas to crash.\n; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.\n; The program will then only run on 68020-based Amigas, though.\n;\n; This code will run with registerized parameters too, unless SAS\n; changes parameter passing conventions between new releases of SAS/C.\n\n\n;;Cur_Match      equr     d0      ; Must be in d0!\n;;Best_Len       equr     d1\n;;Loop_Counter   equr     d2\n;;Scan_Start     equr     d3\n;;Scan_End       equr     d4\n;;Limit          equr     d5\n;;Chain_Length   equr     d6\n;;Scan_Test      equr     d7\n;;Scan           equr     a0\n;;Match          equr     a1\n;;Prev_Address   equr     a2\n;;Scan_Ini       equr     a3\n;;Match_Ini      equr     a4\n\nMAX_MATCH       equ     258\nMIN_MATCH       equ     3\nWSIZE           equ     32768\nMAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1\n\n\n        .globl    _max_chain_length\n        .globl    _prev_length\n        .globl    _prev\n        .globl    _window\n        .globl    _strstart\n        .globl    _good_match\n        .globl    _match_start\n        .globl    _nice_match\n\n        .text\n        .globl   _match_init\n        .globl   _longest_match\n\n_match_init:\n        rts\n\n\n_longest_match:\n        move.l  4(sp),d0\n        movem.l d2-d7/a2-a4,-(sp)\n        move.l  _max_chain_length,d6\n        move.l  _prev_length,d1\n        lea     _prev,a2\n        lea     _window+MIN_MATCH,a4\n        move.l  _strstart,d5\n        move.l  a4,a3\n        add.l   d5,a3\n        subi.w  #MAX_DIST,d5\n        bhi     limit_ok\n        moveq   #0,d5\nlimit_ok:\n        cmp.l   _good_match,d1\n        bcs     length_ok\n        lsr.l   #2,d6\nlength_ok:\n        subq.l  #1,d6\n\n        move.b  -MIN_MATCH(a3),d3\n        lsl.w   #8,d3\n        move.b  -MIN_MATCH+1(a3),d3\n        move.b  -MIN_MATCH-1(a3,d1),d4\n        lsl.w   #8,d4\n        move.b  -MIN_MATCH(a3,d1),d4\n\n        bra     do_scan\n\nlong_loop:\n\n        move.b  -MIN_MATCH-1(a3,d1),d4\n        lsl.w   #8,d4\n        move.b  -MIN_MATCH(a3,d1),d4\n\nshort_loop:\n        lsl.w   #1,d0\n        move.w  0(a2,d0.l),d0\n        cmp.w   d5,d0\n        dbls    d6,do_scan\n        bra     return\n\ndo_scan:\n        move.l  a4,a1\n        add.l   d0,a1\n\n        move.b  -MIN_MATCH-1(a1,d1),d7\n        lsl.w   #8,d7\n        move.b  -MIN_MATCH(a1,d1),d7\n        cmp.w   d7,d4\n        bne     short_loop\n        move.b  -MIN_MATCH(a1),d7\n        lsl.w   #8,d7\n        move.b  -MIN_MATCH+1(a1),d7\n        cmp.w   d7,d3\n        bne     short_loop\n\n        move.w  #(MAX_MATCH-MIN_MATCH),d2\n        move.l  a3,a0\n\nscan_loop:\n        cmpm.b  (a1)+,(a0)+\n        dbne    d2,scan_loop\n\n        sub.l   a3,a0\n        addq.l  #(MIN_MATCH-1),a0\n        cmp.l   d1,a0\n        bls     short_loop\n        move.l  a0,d1\n        move.l  d0,_match_start\n        cmp.l   _nice_match,d1\n        bcs     long_loop\nreturn:\n        move.l  d1,d0\n        movem.l (sp)+,d2-d7/a2-a4\n        rts\n        end\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef _QDOS_OPDEP\n#define _QDOS_OPDEP\n\n#include <stdlib.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <string.h>\n#include <ctype.h>\n\nchar * ql2Unix(char *);\nchar * Unix2ql(char *, char **);\nint wild (char *);\nchar *LastDir(char *);\nvoid QDOSexit(void);\nshort devlen(char *);\n\n/*\n * XXX NO_RENAME instead of the following define ?\n */\n#define link rename\n#define USE_CASE_MAP\n#define USE_EF_UT_TIME\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, 1))\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/qdos.c",
    "content": "/*\n  qdos/qdos.c\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * Yes this  file is necessary; the QDOS file system is the most\n * ludicrous known to man (even more so than VMS!).\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <dirent.h>\n#include <unistd.h>\n\n#include \"zip.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n\n#ifdef QDOS\n\n# include <qdos.h>\n\n#if CRYPT\n\nchar *getp(m, p, n)\n    ZCONST char *m;              /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    int c;                      /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n\n    /* get password */\n    w = \"\";\n    sd_cure(getchid(0), -1);    /* enable cursor */\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* display prompt and flush */\n        fflush(stderr);\n        i = 0;\n        do {\n            c = getch();\n            if (c == 0xc2) {\n                if (i > 0) {\n                    i--; /* the `del' keys works */\n                    fputs(\"\\b \\b\", stderr);\n                }\n            }\n            else if (i < n) {\n                p[i++] = c;     /* truncate past n */\n                if(c != '\\n') putc('*', stderr);\n            }\n        } while (c != '\\n');\n\n        putc('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n\n    p[i-1] = 0;                 /* terminate at newline */\n    sd_curs(getchid(0), -1);    /* suppress cursor */\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* CRYPT */\n\n\n#define __attribute__(p)\n\nint newname(char *, int, int);\n\n#else /* !QDOS */\n#define QDOS_FLMAX 36\n\nshort qlflag = 0;\n\nstruct qdirect  {\n    long            d_length __attribute__ ((packed));  /* file length */\n    unsigned char   d_access __attribute__ ((packed));  /* file access type */\n    unsigned char   d_type __attribute__ ((packed));    /* file type */\n    long            d_datalen __attribute__ ((packed)); /* data length */\n    long            d_reserved __attribute__ ((packed));/* Unused */\n    short           d_szname __attribute__ ((packed));  /* size of name */\n    char            d_name[QDOS_FLMAX] __attribute__ ((packed));/* name area */\n    long            d_update __attribute__ ((packed));  /* last update */\n    long            d_refdate __attribute__ ((packed));\n    long            d_backup __attribute__ ((packed));   /* EOD */\n    } ;\n#endif /* ?QDOS */\n\n#define SHORTID 0x4afb          /* in big-endian order !! */\n#define LONGID  \"QDOS02\"\n#define EXTRALEN (sizeof(struct qdirect) + 8)\n\ntypedef struct\n{\n    unsigned short shortid __attribute__ ((packed));\n    struct\n    {\n        unsigned char lo __attribute__ ((packed));\n        unsigned char hi __attribute__ ((packed));\n    } len __attribute__ ((packed));\n    char        longid[8] __attribute__ ((packed));\n    struct      qdirect     header __attribute__ ((packed));\n} qdosextra;\n\n#ifdef USE_EF_UT_TIME\nlocal int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg);\n#endif\n\n#ifdef QDOS\n\n#define rev_short(x) (x)\n#define rev_long(x) (x)\n\nchar _prog_name[] = \"zip\";\nchar _copyright[] = \"(c) Info-ZIP Group\";\nlong _stack = 16*1024;\nchar *  _endmsg = NULL;\n\nextern void consetup_title(chanid_t,struct WINDOWDEF *);\nvoid (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;\n\nstruct WINDOWDEF _condetails =\n{\n    2,\n    1,\n    0,\n    7,\n    500,\n    220,\n    2,\n    30\n};\n\nextern short qlwait;\nextern short dtype;\n\n#define CHECKDIR(p1) (((p1).d_type == dtype) && (((p1).d_length % 64) == 0))\n\nchar * stpcpy (char *d, ZCONST char *s)\n{\n    while(*d++ = *s++)\n        ; /* Null loop */\n    return d-1;\n}\n\nstatic jobid_t chowner(chanid_t chan)\n{\n    extern char *_sys_var;\n    char *scht;\n    long *cdb;\n    long jid;\n\n    scht = *((char **)(_sys_var + 0x78));\n    cdb = *(long **)((long *)scht  + (chan & 0xffff));\n    jid = *(cdb + 2);\n    return jid;\n}\n\nvoid QDOSexit(void)\n{\n    jobid_t me,you;\n\n    me = getpid();\n    you = chowner(getchid(0));\n\n    if((me == you) && ((qlflag & 4) == 0))\n    {\n        if(isatty(0) && isatty(2) && qlwait)\n        {\n            char c = 0;\n            fputs(\"Press a key to exit\", stderr);\n            if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)\n            {\n                io_fbyte(getchid(0), -1, &c);\n            }\n        }\n    }\n    exit(ZE_OK);\n}\n\n/* Access seems to be *always* broken in c68 */\n/* Not accurate, just works */\n\nint access (char *f, int mode)\n{\n    struct stat st;\n    int fd;\n\n    if((fd = stat(f, &st)) == 0)\n    {\n        switch(fd)\n        {\n        case F_OK:\n            break;\n        case R_OK:\n            fd = (st.st_mode & 0444) == 0;\n            break;\n        case W_OK:\n            fd = (st.st_mode & 0222) == 0;\n            break;\n        case X_OK:\n            fd = (st.st_mode & 0111) == 0;\n            break;\n        default:\n            fd = -1;\n            break;\n        }\n    }\n    return fd;\n}\n\n/* Fixup a Mickey Mouse file naming system */\n\nchar * Unix2ql (char *qlname, char **dot)\n{\n    static char path[64];\n    char name[64];\n    char *q, *r, *s;\n\n    strcpy(name, qlname);\n    if(*name == '~')\n    {\n        r = name+1;\n        getcwd(path, sizeof(path));\n        q = path + strlen(path);\n        if(*(q-1) != '_')\n        {\n            *q++ = '_';\n        }\n    }\n    else\n    {\n        q = path;\n        r = name;\n    }\n\n    if(*r == '/')\n    {\n        r++;\n    }\n\n    strcpy(q, r);\n\n    while (*q)\n    {\n        if(*q == '/' || *q == '.')\n        {\n            if(*q == '.' && dot)\n            {\n                *dot = name + (q - path);\n            }\n            *q = '_';\n        }\n\n        q++;\n    }\n    return path;\n}\n\n#if 0                                 /* Not used in ZIP */\n\nGuessAltName(char *name, char *dot)\n{\n    if(dot)\n    {\n        *dot = '.';\n    }\n    else\n    {\n        if((dot = strrchr(name, '_')))\n        {\n            *dot = '.';\n        }\n    }\n}\n\n#endif /* 0 */\n\nshort devlen(char *p)\n{\n    char defpath[40];\n    short deflen = 0, ok = 0;\n\n    getcwd(defpath, sizeof(defpath));\n    deflen = strlen(defpath);\n    if(deflen)\n    {\n        if(strnicmp(p, defpath, deflen) == 0)\n        {\n            ok = 1;\n        }\n    }\n\n    if(!ok)\n    {\n        if(isdirdev(p))\n        {\n            deflen = 5;\n        }\n        else\n        {\n            deflen = 0;\n        }\n    }\n    return deflen;\n}\n\nchar * ql2Unix (char *qlname)\n{\n    struct stat st;\n    int sts;\n    char *p, *r, *s, *ldp;\n    char *pnam = NULL;\n    static char path[64];\n    short  deflen;\n    char name[64];\n\n    strcpy(name, qlname);\n    strcpy(path, name);\n\n    deflen = devlen(qlname);\n\n    p = name + deflen;\n    pnam = path + deflen;\n\n    if(s = strrchr(p, '_'))\n    {\n        *s = 0;\n        sts = stat(name, &st);\n        if(deflen && sts ==0 && (st.st_mode & S_IFDIR))\n        {\n            *(path+(s-name)) = '/';\n        }\n        else\n        {\n            *(path+(s-name)) = '.';\n        }\n    }\n\n    ldp = p;\n    for(r = p; *r; r++)\n    {\n        if(r != ldp && *r == '_')\n        {\n            *r = 0;\n            if(deflen)\n            {\n                sts = stat(name, &st);\n            }\n            else\n                sts = -1;\n\n            if(sts ==0 && (st.st_mode & S_IFDIR))\n            {\n                *(path+(r-name)) = '/';\n                ldp = r + 1;\n            }\n            else\n            {\n                *(path+(r-name)) = '_';\n            }\n            *r = '_';\n        }\n    }\n    return pnam;\n}\n\nchar *LastDir(char *ws)\n{\n    char *p;\n    char *q = ws;\n    struct stat s;\n\n    for(p = ws; *p; p++)\n    {\n        if(p != ws && *p == '_')\n        {\n            char c;\n\n            p++;\n            c = *p;\n            *p = 0;\n            if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))\n            {\n                q = p;\n            }\n            *p = c;\n        }\n    }\n    return q;\n}\n\n# ifndef UTIL\n\nstatic int add_dir(char * dnam)\n{\n    int e = ZE_OK;\n    char *p;\n    short nlen;\n\n    nlen = strlen(dnam);\n    if(p = malloc(nlen + 2))\n    {\n        strncpy (p, dnam, nlen);\n        if(*(p+nlen) != '_')\n        {\n            *(p+nlen) = '_';\n            *(p+nlen+1) = '\\0';\n        }\n        if ((e = newname(p, 1, 0)) != ZE_OK)\n        {\n                free(p);\n        }\n    }\n    else\n    {\n        e = ZE_MEM;\n    }\n    return e;\n}\n\nint qlwild (char *dnam, short dorecurse, short l)\n{\n    static char match[40] = {0};\n    static char ddev[8] =  {0};\n    static short nc;\n    static short llen;\n    static char base[40];\n\n    int chid;\n    struct qdirect qd;\n    char *dp;\n    int e = ZE_MISS;\n\n    if (l == 0)\n    {\n        nc = 0;\n        *base = '\\0';\n        if (isdirdev (dnam))\n        {\n            dp = dnam;\n            strncpy (ddev, dnam, 5);\n        }\n        else\n        {\n\n            char *p;\n            char temp[40];\n\n            getcwd (temp, 40);\n\n            llen = strlen(temp);\n            p = (temp + llen - 1);\n            if (*p != '_')\n            {\n                *p++ = '_';\n                *p = 0;\n            }\n\n            strncpy (ddev, temp, 5);\n            dp = base;\n            p = stpcpy (dp, temp);\n            strcpy (p, dnam);\n        }\n\n        {\n            char *q = isshexp (dp);\n            if(q)\n            {\n                strcpy (match, dp + 5);\n                if (q)\n                {\n                    while (q != dp && *q != '_')\n                    {\n                        q--;\n                    }\n                    *(++q) = '\\0';\n                }\n            }\n            else\n            {\n                struct stat s;\n                if (stat(dp, &s) == 0)\n                {\n                    if (!(s.st_mode & S_IFDIR))\n                    {\n                        return procname(dp, 0);\n                    }\n                }\n                else\n                {\n                    return ZE_MISS;  /* woops, no wildcards! */\n                }\n            }\n\n        }\n    }\n    else\n    {\n        dp = dnam;\n    }\n\n    if ((chid = io_open (dp, 4L)) > 0)\n    {\n        int id = 0;\n        while (io_fstrg (chid, -1, &qd, 64) > 0)\n        {\n            short j;\n\n            if (qd.d_szname)\n            {\n                if (CHECKDIR(qd))\n                {\n                    if(dorecurse)\n                    {\n                        char fnam[256], *p;\n\n                        p = stpcpy (fnam, ddev);\n                        strncpy (p, qd.d_name, qd.d_szname);\n                        *(p + qd.d_szname) = 0;\n                        e = qlwild (fnam, dorecurse, l+1);\n                    }\n                    else\n                    {\n                        continue;\n                    }\n                }\n                else\n                {\n                    char nam[48];\n                    strcpy(nam, ddev);\n\n                    strncpy (nam + 5, qd.d_name, qd.d_szname);\n                    *(nam + 5 + qd.d_szname) = 0;\n\n                    if (MATCH (match, nam + 5, 0) == 1)\n                    {\n                        if(dirnames && l && id == 0)\n                        {\n                            id = 1;\n                            if((e = add_dir(dp)) != ZE_OK)\n                            {\n                                return e;\n                            }\n                        }\n\n                        if((e = procname(nam, 0)) == ZE_OK)\n                        {\n                            nc++;\n                        }\n                    }\n                }\n            }\n        }\n        io_close (chid);\n    }\n\n    if (l == 0)\n    {\n        *ddev = 0;\n        *match = 0;\n        e = (nc) ? ZE_OK : ZE_MISS;\n    }\n    return e;\n\n}\n\nint wild(char *p)\n{\n    return qlwild(p, recurse, 0);\n}\n# endif /* !UTIL */\n\n/*\n * Return QDOS error, 0 if exec 1 if found but not exe or rel\n */\nint qlstat(char *name, struct qdirect *qs, char *flag)\n{\n    int r;\n    r = qstat(name, qs);\n    if(r == 0)\n    {\n        if(qs->d_type == 0)\n        {\n            r = 1;\n        }\n        else if(CHECKDIR(*qs))\n        {\n            r = 255;\n        }\n    }\n    return r;\n}\n\n#else /* !QDOS */\n\nlong rev_long (ulg l)\n{\n    uch cc[4];\n    cc[0] = (uch)(l >> 24);\n    cc[1] = (uch)((l >> 16) & 0xff);\n    cc[2] = (uch)((l >> 8) & 0xff);\n    cc[3] = (uch)(l & 0xff);\n    return *(ulg *)cc;\n}\n\nshort rev_short (ush s)\n{\n    uch cc[2];\n    cc[0] = (uch)((s >> 8) & 0xff);\n    cc[1] = (uch)(s & 0xff);\n    return *(ush *)cc;\n}\n\n#define O_BINARY 0\n\nint qlstat(char *name, struct qdirect *qs, char *flag)\n{\n    int r = -1;\n    int n, fd;\n    struct stat s;\n    struct _ntc_\n    {\n        long id;\n        long dlen;\n    } ntc;\n\n    *flag = 0;\n    if((fd = open(name, O_RDONLY | O_BINARY)) > 0)\n    {\n        short nl;\n\n        fstat(fd, &s);\n        lseek(fd, -8, SEEK_END);\n        read(fd, &ntc, 8);\n        qs->d_length = rev_long(s.st_size);\n        qs->d_update = rev_long(s.st_ctime + 283996800);\n\n        nl = strlen(name);\n        if(nl > QDOS_FLMAX)\n        {\n            nl = QDOS_FLMAX;\n            *flag = 1;\n        }\n        qs->d_szname = rev_short(nl);\n        memcpy(qs->d_name, name, nl);\n\n        if(ntc.id == *(long *)\"XTcc\")\n        {\n            qs->d_datalen = ntc.dlen;    /* This is big endian */\n            qs->d_type = 1;\n            r = 0;\n        }\n        else\n        {\n            qs->d_type = 0;\n            qs->d_datalen = 0;\n            r = 1;\n        }\n        close(fd);\n        return r;\n    }\n    else\n    {\n        fprintf(stderr, \"Fails %d\\n\", fd);\n        return r;\n    }\n}\n\n#endif /* ?QDOS */\n\n#ifdef USE_EF_UT_TIME\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + eb_l_ut_len)\n#define EB_C_UT_SIZE    (EB_HEADSIZE + eb_c_ut_len)\n\n#ifdef UNIX\n#define EB_L_UX2_SIZE     (EB_HEADSIZE + EB_UX2_MINLEN)\n#define EB_C_UX2_SIZE     EB_HEADSIZE\n#define EF_L_UT_UX2_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)\n#define EF_C_UT_UX2_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)\n#else\n#define EF_L_UT_UX2_SIZE  EB_L_UT_SIZE\n#define EF_C_UT_UX2_SIZE  EB_C_UT_SIZE\n#endif\n\nlocal int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg)\n{\n  char *eb_l_ptr;\n  char *eb_c_ptr;\n  char *eb_pt;\n  extent eb_l_ut_len = 0;\n  extent eb_c_ut_len = 0;\n\n#ifdef UNIX\n  struct stat s;\n\n  /* For the full sized UT local field including the UID/GID fields, we\n   * have to stat the file, again.  */\n  if (stat(z->name, &s))\n    return ZE_OPEN;\n  /* update times in z_utim, stat() call might have changed atime... */\n  z_utim->mtime = s.st_mtime;\n  z_utim->atime = s.st_atime;\n  z_utim->ctime = s.st_mtime;   /* best guess (st_ctime != creation time) */\n#endif /* UNIX */\n\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid)\n    ut_flg = 0;          /* disable UT e.f creation if no valid TZ info */\n#endif\n  if (ut_flg != 0) {\n    if (ut_flg & EB_UT_FL_MTIME)\n      eb_l_ut_len = eb_c_ut_len = 1;\n    if (ut_flg & EB_UT_FL_ATIME)\n      eb_l_ut_len++;\n    if (ut_flg & EB_UT_FL_CTIME)\n      eb_l_ut_len++;\n\n    eb_l_ut_len = EB_UT_LEN(eb_l_ut_len);\n    eb_c_ut_len = EB_UT_LEN(eb_c_ut_len);\n  }\n\n  if (EF_L_UT_UX2_SIZE > EB_HEADSIZE) {\n    if(z->ext)\n      eb_l_ptr = realloc(z->extra, (z->ext + EF_L_UT_UX2_SIZE));\n    else\n      eb_l_ptr = malloc(EF_L_UT_UX2_SIZE);\n\n    if (eb_l_ptr == NULL)\n      return ZE_MEM;\n\n    if(z->cext)\n      eb_c_ptr = realloc(z->cextra, (z->cext + EF_C_UT_UX2_SIZE));\n    else\n      eb_c_ptr = malloc(EF_C_UT_UX2_SIZE);\n\n    if (eb_c_ptr == NULL)\n      return ZE_MEM;\n\n    z->extra = eb_l_ptr;\n    eb_l_ptr += z->ext;\n    z->ext += EF_L_UT_UX2_SIZE;\n\n    if (ut_flg != 0) {\n      eb_l_ptr[0]  = 'U';\n      eb_l_ptr[1]  = 'T';\n      eb_l_ptr[2]  = eb_l_ut_len;       /* length of data part of e.f. */\n      eb_l_ptr[3]  = 0;\n      eb_l_ptr[4]  = ut_flg;\n      eb_pt = eb_l_ptr + 5;\n      if (ut_flg & EB_UT_FL_MTIME) {\n        *eb_pt++ = (char)(z_utim->mtime);\n        *eb_pt++ = (char)(z_utim->mtime >> 8);\n        *eb_pt++ = (char)(z_utim->mtime >> 16);\n        *eb_pt++ = (char)(z_utim->mtime >> 24);\n      }\n      if (ut_flg & EB_UT_FL_ATIME) {\n        *eb_pt++ = (char)(z_utim->atime);\n        *eb_pt++ = (char)(z_utim->atime >> 8);\n        *eb_pt++ = (char)(z_utim->atime >> 16);\n        *eb_pt++ = (char)(z_utim->atime >> 24);\n      }\n      if (ut_flg & EB_UT_FL_CTIME) {\n        *eb_pt++ = (char)(z_utim->ctime);\n        *eb_pt++ = (char)(z_utim->ctime >> 8);\n        *eb_pt++ = (char)(z_utim->ctime >> 16);\n        *eb_pt++ = (char)(z_utim->ctime >> 24);\n      }\n    }\n#ifdef UNIX\n    else {\n      eb_pt = eb_l_ptr;\n    }\n    *eb_pt++ = 'U';\n    *eb_pt++ = 'x';\n    *eb_pt++ = EB_UX2_MINLEN;            /* length of data part of local e.f. */\n    *eb_pt++  = 0;\n    *eb_pt++ = (char)(s.st_uid);\n    *eb_pt++ = (char)(s.st_uid >> 8);\n    *eb_pt++ = (char)(s.st_gid);\n    *eb_pt++ = (char)(s.st_gid >> 8);\n#endif /* UNIX */\n\n    z->cextra = eb_c_ptr;\n    eb_c_ptr += z->cext;\n    z->cext += EF_C_UT_UX2_SIZE;\n\n    if (ut_flg != 0) {\n      memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);\n      eb_c_ptr[EB_LEN] = eb_c_ut_len;\n    }\n#ifdef UNIX\n    memcpy(eb_c_ptr+EB_C_UT_SIZE, eb_l_ptr+EB_L_UT_SIZE, EB_C_UX2_SIZE);\n    eb_c_ptr[EB_LEN+EB_C_UT_SIZE] = 0;\n#endif /* UNIX */\n  }\n\n  return ZE_OK;\n}\n\n#endif /* USE_EF_UT_TIME */\n\n\nint set_extra_field (struct zlist *z, iztimes *z_utim )\n{\n    int rv = 0;\n    int last_rv = 0;\n    char flag = 0;\n\n    if ((qlflag & 3) != 1)\n    {\n        qdosextra       *lq, *cq;\n        if ((lq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)\n            return ZE_MEM;\n        if ((cq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)\n            return ZE_MEM;\n\n        rv = qlstat(z->name, &(lq->header), &flag);\n\n        if (rv == 0 || (rv == 1 && (qlflag & 2)))\n        {\n            lq->shortid = rev_short((short) SHORTID);\n            lq->len.lo  = (unsigned char)(EXTRALEN & 0xff);\n            lq->len.hi  = (unsigned char)(EXTRALEN >> 8);\n            strcpy(lq->longid, LONGID);\n\n            memcpy(cq, lq, sizeof(qdosextra));\n\n            z->ext      =   sizeof(qdosextra);\n            z->cext     =   sizeof(qdosextra);\n            z->extra    =   (void *) lq;\n            z->cextra   =   (void *) cq;\n            fprintf (stderr, \" %c\",\n                     lq->header.d_datalen ? '*' : '#');\n        }\n        else if (rv == -1)\n        {\n            fprintf(stderr,\n                    \"%s: warning: cannot stat %s, no file header added\\n\",\n                    \"zip\", z->name);\n        }\n        if(flag)\n        {\n            fputs (\" !\", stderr);\n        }\n     }\n    last_rv = (rv == -1 ? ZE_OPEN : ZE_OK);\n\n#ifdef USE_EF_UT_TIME\n# ifdef QDOS\n#   define IZ_UT_FLAGS EB_UT_FL_MTIME\n# endif\n# ifdef UNIX\n#   define IZ_UT_FLAGS (EB_UT_FL_MTIME | EB_UT_FL_ATIME)\n# endif\n# ifndef IZ_UT_FLAGS\n#   define IZ_UT_FLAGS EB_UT_FL_MTIME\n# endif\n\n    rv = GetExtraTime(z, z_utim, IZ_UT_FLAGS);\n    if (rv != ZE_OK)\n        last_rv = rv;\n#endif /* USE_EF_UT_TIME */\n\n    return last_rv;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/qfileio.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n#include <utime.h>\n\n#include <errno.h>\n\n#ifdef S_IWRITE\n# undef S_IWRITE\n#endif /* S_IWRITE */\n#define S_IWRITE S_IWUSR\n\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n\ntypedef time_t statime;\n#define PAD 0\n#define PATH_END '/'\n\n/* Local functions */\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (SSTAT(n, &s) )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free(p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  }\n  return ZE_OK;\n}\n\n\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  t = ql2Unix(x);\n\n  dosflag = dosify; /* default for non-DOS and non-OS/2 */\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Discard directory names with zip -rj */\n  if (*t == '\\0')\n    return t;\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n       return NULL;\n  strcpy(x, Unix2ql(n, NULL));\n  return x;\n}\n\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  struct utimbuf u;     /* argument for utime()  const ?? */\n\n  /* Convert DOS time to time_t format in u */\n  u.actime = u.modtime = dos2unixtime(d);\n  utime(f, &u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* from FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFMT) == S_IFDIR) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return rmdir(d);\n}\n\n#endif /* !UTIL */\n\n\nvoid version_local()\n{\n    puts (\"Compiled with c68 v4.2x on \" __DATE__);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/qdos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  define O_RDONLY 0\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/revision.h",
    "content": "/*\n  revision.h - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  revision.h by Mark Adler.\n */\n\n#ifndef __revision_h\n#define __revision_h 1\n\n/* For api version checking */\n#define Z_MAJORVER   3\n#define Z_MINORVER   0\n#define Z_PATCHLEVEL 0\n#define Z_BETALEVEL \"i BETA\"\n\n#define VERSION \"3.0\"\n#define REVDATE \"July 5th 2008\"\n\n#define DW_MAJORVER    Z_MAJORVER\n#define DW_MINORVER    Z_MINORVER\n#define DW_PATCHLEVEL  Z_PATCHLEVEL\n\n#ifndef IZ_COMPANY_NAME               /* might be already defined... */\n#  define IZ_COMPANY_NAME \"Info-ZIP\"\n#endif\n\n#if !defined(WINDLL) && !defined(IZ_VERSION_SYMBOLS_ONLY)\n/* Copyright notice for binary executables--this notice only applies to\n * those (zip, zipcloak, zipsplit, and zipnote), not to this file\n * (revision.h).\n */\n\n#ifndef DEFCPYRT\n/* copyright[] et.al. get defined only once ! */\n/* keep array sizes in sync with number of text */\n/* lines in the array definitions below !!      */\nextern ZCONST char *copyright[1];\nextern ZCONST char * far swlicense[50];\nextern ZCONST char * far versinfolines[7];\nextern ZCONST char * far cryptnote[7];\n\n#else /* DEFCPYRT */\n\nZCONST char *copyright[] = {\n\"Copyright (c) 1990-2008 Info-ZIP - Type '%s \\\"-L\\\"' for software license.\"\n/* XXX still necessary ???? */\n#ifdef AZTEC_C\n,        /* extremely lame compiler bug workaround */\n#endif\n};\n\nZCONST char * far versinfolines[] = {\n\"This is %s %s (%s), by Info-ZIP.\",\n\"Currently maintained by E. Gordon.  Please send bug reports to\",\n\"the authors using the web page at www.info-zip.org; see README for details.\",\n\"\",\n\"Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip,\",\n\"as of above date; see http://www.info-zip.org/ for other sites.\",\n\"\"\n};\n\n/* new notice - 4 March 2007 */\nZCONST char * far cryptnote[] = {\n\"Encryption notice:\",\n\"\\tThe encryption code of this program is not copyrighted and is\",\n\"\\tput in the public domain.  It was originally written in Europe\",\n\"\\tand, to the best of our knowledge, can be freely distributed\",\n\"\\tin both source and object forms from any country, including\",\n\"\\tthe USA under License Exception TSU of the U.S. Export\",\n\"\\tAdministration Regulations (section 740.13(e)) of 6 June 2002.\"\n};\n\nZCONST char * far swlicense[] = {\n\"Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\",\n\"\",\n\"For the purposes of this copyright and license, \\\"Info-ZIP\\\" is defined as\",\n\"the following set of individuals:\",\n\"\",\n\"   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\",\n\"   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\",\n\"   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\",\n\"   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\",\n\"   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\",\n\"   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\",\n\"   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\",\n\"   Rich Wales, Mike White\",\n\"\",\n\"This software is provided \\\"as is,\\\" without warranty of any kind, express\",\n\"or implied.  In no event shall Info-ZIP or its contributors be held liable\",\n\"for any direct, indirect, incidental, special or consequential damages\",\n\"arising out of the use of or inability to use this software.\",\n\"\",\n\"Permission is granted to anyone to use this software for any purpose,\",\n\"including commercial applications, and to alter it and redistribute it\",\n\"freely, subject to the above disclaimer and the following restrictions:\",\n\"\",\n\"    1. Redistributions of source code (in whole or in part) must retain\",\n\"       the above copyright notice, definition, disclaimer, and this list\",\n\"       of conditions.\",\n\"\",\n\"    2. Redistributions in binary form (compiled executables and libraries)\",\n\"       must reproduce the above copyright notice, definition, disclaimer,\",\n\"       and this list of conditions in documentation and/or other materials\",\n\"       provided with the distribution.  The sole exception to this condition\",\n\"       is redistribution of a standard UnZipSFX binary (including SFXWiz) as\",\n\"       part of a self-extracting archive; that is permitted without inclusion\",\n\"       of this license, as long as the normal SFX banner has not been removed\",\n\"       from the binary or disabled.\",\n\"\",\n\"    3. Altered versions--including, but not limited to, ports to new operating\",\n\"       systems, existing ports with new graphical interfaces, versions with\",\n\"       modified or added functionality, and dynamic, shared, or static library\",\n\"       versions not from Info-ZIP--must be plainly marked as such and must not\",\n\"       be misrepresented as being the original source or, if binaries,\",\n\"       compiled from the original source.  Such altered versions also must not\",\n\"       be misrepresented as being Info-ZIP releases--including, but not\",\n\"       limited to, labeling of the altered versions with the names \\\"Info-ZIP\\\"\",\n\"       (or any variation thereof, including, but not limited to, different\",\n\"       capitalizations), \\\"Pocket UnZip,\\\" \\\"WiZ\\\" or \\\"MacZip\\\" without the\",\n\"       explicit permission of Info-ZIP.  Such altered versions are further\",\n\"       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\",\n\"       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\",\n\"       will provide support for the altered versions.\",\n\"\",\n\"    4. Info-ZIP retains the right to use the names \\\"Info-ZIP,\\\" \\\"Zip,\\\" \\\"UnZip,\\\"\",\n\"       \\\"UnZipSFX,\\\" \\\"WiZ,\\\" \\\"Pocket UnZip,\\\" \\\"Pocket Zip,\\\" and \\\"MacZip\\\" for its\",\n\"       own source and binary releases.\"\n};\n#endif /* DEFCPYRT */\n#endif /* !WINDLL && !IZ_VERSION_SYMBOLS_ONLY */\n#endif /* !__revision_h */\n"
  },
  {
    "path": "deps/infozip/zip30/tailor.h",
    "content": "/*\n  tailor.h - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* Some compiler distributions for Win32/i386 systems try to emulate\n * a Unix (POSIX-compatible) environment.\n */\n#if (defined(WIN32) && defined(UNIX))\n   /* Zip does not support merging both ports in a single executable. */\n#  if (defined(FORCE_WIN32_OVER_UNIX) && defined(FORCE_UNIX_OVER_WIN32))\n     /* conflicting choice requests -> we prefer the Win32 environment */\n#    undef FORCE_UNIX_OVER_WIN32\n#  endif\n#  ifdef FORCE_WIN32_OVER_UNIX\n     /* native Win32 support was explicitely requested... */\n#    undef UNIX\n#  else\n     /* use the POSIX (Unix) emulation features by default... */\n#    undef WIN32\n#  endif\n#endif\n\n\n/* UNICODE */\n#ifdef NO_UNICODE_SUPPORT\n# ifdef UNICODE_SUPPORT\n#   undef UNICODE_SUPPORT\n# endif\n#endif\n\n\n#ifdef AMIGA\n#include \"amiga/osdep.h\"\n#endif\n\n#ifdef AOSVS\n#include \"aosvs/osdep.h\"\n#endif\n\n#ifdef ATARI\n#include \"atari/osdep.h\"\n#endif\n\n#ifdef __ATHEOS__\n#include \"atheos/osdep.h\"\n#endif\n\n#ifdef __BEOS__\n#include \"beos/osdep.h\"\n#endif\n\n#ifdef DOS\n#include \"msdos/osdep.h\"\n#endif\n\n#ifdef __human68k__\n#include \"human68k/osdep.h\"\n#endif\n\n#if ((defined(__MWERKS__) && defined(macintosh)) || defined(MACOS))\n#include \"macos/osdep.h\"\n#endif\n\n#ifdef NLM\n#include \"novell/osdep.h\"\n#endif\n\n#ifdef OS2\n#include \"os2/osdep.h\"\n#endif\n\n#ifdef __riscos\n#include \"acorn/osdep.h\"\n#endif\n\n#ifdef QDOS\n#include \"qdos/osdep.h\"\n#endif\n\n#ifdef __TANDEM\n#include \"tandem.h\"\n#include \"tanzip.h\"\n#endif\n\n#ifdef UNIX\n#include \"unix/osdep.h\"\n#endif\n\n#if defined(__COMPILER_KCC__) || defined(TOPS20)\n#include \"tops20/osdep.h\"\n#endif\n\n#if defined(VMS) || defined(__VMS)\n#include \"vms/osdep.h\"\n#endif\n\n#if defined(__VM__) || defined(VM_CMS) || defined(MVS)\n#include \"cmsmvs.h\"\n#endif\n\n#ifdef WIN32\n#include \"win32/osdep.h\"\n#endif\n\n#ifdef THEOS\n#include \"theos/osdep.h\"\n#endif\n\n\n/* generic LARGE_FILE_SUPPORT defines\n   These get used if not defined above.\n   7/21/2004 EG\n*/\n/* If a port hasn't defined ZOFF_T_FORMAT_SIZE_PREFIX\n   then probably need to define all of these. */\n#ifndef ZOFF_T_FORMAT_SIZE_PREFIX\n\n# ifdef LARGE_FILE_SUPPORT\n    /* Probably passed in from command line instead of in above\n       includes if get here.  Assume large file support and hope. 8/14/04 EG */\n\n    /* Set the Large File Summit (LFS) defines to turn on large file support\n       in case it helps. */\n\n#   define _LARGEFILE_SOURCE    /* some OSes need this for fseeko */\n#   define _LARGEFILE64_SOURCE\n#   define _FILE_OFFSET_BITS 64 /* select default interface as 64 bit */\n#   define _LARGE_FILES         /* some OSes need this for 64-bit off_t */\n\n    typedef off_t zoff_t;\n    typedef unsigned long long uzoff_t;  /* unsigned zoff_t (12/29/04 EG) */\n\n    /* go with common prefix */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n\n# else\n    /* Default type for offsets and file sizes was ulg but reports\n       of using ulg to create files from 2 GB to 4 GB suggest\n       it doesn't work well.  Now just switch to Zip64 or not\n       support over 2 GB.  7/24/04 EG */\n    /* Now use uzoff_t for unsigned things.  12/29/04 EG */\n    typedef long zoff_t;\n    typedef unsigned long uzoff_t;\n\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"l\"\n\n# endif\n\n  typedef struct stat z_stat;\n\n  /* flag that we are defaulting */\n# define USING_DEFAULT_LARGE_FILE_SUPPORT\n#endif\n\n\n#if (defined(USE_ZLIB) && defined(ASM_CRC))\n#  undef ASM_CRC\n#endif\n\n#if (defined(USE_ZLIB) && defined(ASMV))\n#  undef ASMV\n#endif\n\n/* When \"void\" is an alias for \"int\", prototypes cannot be used. */\n#if (defined(NO_VOID) && !defined(NO_PROTO))\n#  define NO_PROTO\n#endif\n\n/* Used to remove arguments in function prototypes for non-ANSI C */\n#ifndef NO_PROTO\n#  define OF(a) a\n#  define OFT(a) a\n#else /* NO_PROTO */\n#  define OF(a) ()\n#  define OFT(a)\n#endif /* ?NO_PROTO */\n\n/* If the compiler can't handle const define ZCONST in osdep.h */\n/* Define const itself in case the system include files are bonkers */\n#ifndef ZCONST\n#  ifdef NO_CONST\n#    define ZCONST\n#    define const\n#  else\n#    define ZCONST const\n#  endif\n#endif\n\n/*\n * Some compiler environments may require additional attributes attached\n * to declarations of runtime libary functions (e.g. to prepare for\n * linking against a \"shared dll\" version of the RTL).  Here, we provide\n * the \"empty\" default for these attributes.\n */\n#ifndef IZ_IMP\n#  define IZ_IMP\n#endif\n\n/*\n * case mapping functions. case_map is used to ignore case in comparisons,\n * to_up is used to force upper case even on Unix (for dosify option).\n */\n#ifdef USE_CASE_MAP\n#  define case_map(c) upper[(c) & 0xff]\n#  define to_up(c)    upper[(c) & 0xff]\n#else\n#  define case_map(c) (c)\n#  define to_up(c)    ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))\n#endif /* USE_CASE_MAP */\n\n/* Define void, zvoid, and extent (size_t) */\n#include <stdio.h>\n\n#ifndef NO_STDDEF_H\n#  include <stddef.h>\n#endif /* !NO_STDDEF_H */\n\n#ifndef NO_STDLIB_H\n#  include <stdlib.h>\n#endif /* !NO_STDLIB_H */\n\n#ifndef NO_UNISTD_H\n#  include <unistd.h> /* usually defines _POSIX_VERSION */\n#endif /* !NO_UNISTD_H */\n\n#ifndef NO_FCNTL_H\n#  include <fcntl.h>\n#endif /* !NO_FNCTL_H */\n\n#ifndef NO_STRING_H\n#  include <string.h>\n#else\n#  include <strings.h>\n#endif /* NO_STRING_H */\n\n#ifdef NO_VOID\n#  define void int\n   typedef char zvoid;\n#else /* !NO_VOID */\n# ifdef NO_TYPEDEF_VOID\n#  define zvoid void\n# else\n   typedef void zvoid;\n# endif\n#endif /* ?NO_VOID */\n\n#ifdef NO_STRRCHR\n#  define strrchr rindex\n#endif\n\n#ifdef NO_STRCHR\n#  define strchr index\n#endif\n\n/*\n * A couple of forward declarations that are needed on systems that do\n * not supply C runtime library prototypes.\n */\n#ifdef NO_PROTO\nIZ_IMP char *strcpy();\nIZ_IMP char *strcat();\nIZ_IMP char *strrchr();\n/* XXX use !defined(ZMEM) && !defined(__hpux__) ? */\n#if !defined(ZMEM) && defined(NO_STRING_H)\nIZ_IMP char *memset();\nIZ_IMP char *memcpy();\n#endif /* !ZMEM && NO_STRING_H */\n\n/* XXX use !defined(__hpux__) ? */\n#ifdef NO_STDLIB_H\nIZ_IMP char *calloc();\nIZ_IMP char *malloc();\nIZ_IMP char *getenv();\nIZ_IMP long atol();\n#endif /* NO_STDLIB_H */\n\n#ifndef NO_MKTEMP\nIZ_IMP char *mktemp();\n#endif /* !NO_MKTEMP */\n\n#endif /* NO_PROTO */\n\n/*\n * SEEK_* macros, should be defined in stdio.h\n */\n/* Define fseek() commands */\n#ifndef SEEK_SET\n#  define SEEK_SET 0\n#endif /* !SEEK_SET */\n\n#ifndef SEEK_CUR\n#  define SEEK_CUR 1\n#endif /* !SEEK_CUR */\n\n#ifndef FALSE\n#  define FALSE 0\n#endif\n\n#ifndef TRUE\n#  define TRUE 1\n#endif\n\n#ifdef NO_SIZE_T\n   typedef unsigned int extent;\n   /* define size_t 3/17/05 EG */\n   typedef unsigned int size_t;\n#else\n   typedef size_t extent;\n#endif\n\n#ifdef NO_TIME_T\n   typedef long time_t;\n#endif\n\n/* DBCS support for Info-ZIP's zip  (mainly for japanese (-: )\n * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)\n * This code is public domain!   Date: 1998/12/20\n */\n\n/* 2007-07-29 SMS.\n * Include <locale.h> here if it will be needed later for Unicode.\n * Otherwise, SETLOCALE may be defined here, and then defined again\n * (differently) when <locale.h> is read later.\n */\n#ifdef UNICODE_SUPPORT\n# if defined( UNIX) || defined( VMS)\n#   include <locale.h>\n# endif /* defined( UNIX) || defined( VMS) */\n# include <wchar.h>\n# include <wctype.h>\n#endif /* def UNICODE_SUPPORT */\n\n#ifdef _MBCS\n#   include <locale.h>\n\n    /* Multi Byte Character Set */\n    extern char *___tmp_ptr;\n    unsigned char *zmbschr OF((ZCONST unsigned char *, unsigned int));\n    unsigned char *zmbsrchr OF((ZCONST unsigned char *, unsigned int));\n#   define CLEN(ptr) mblen((ZCONST char *)ptr, MB_CUR_MAX)\n#   define PREINCSTR(ptr) (ptr += CLEN(ptr))\n#   define POSTINCSTR(ptr) (___tmp_ptr=(char *)ptr,ptr += CLEN(ptr),___tmp_ptr)\n    int lastchar OF((ZCONST char *ptr));\n#   define MBSCHR(str,c) (char *)zmbschr((ZCONST unsigned char *)(str), c)\n#   define MBSRCHR(str,c) (char *)zmbsrchr((ZCONST unsigned char *)(str), (c))\n#   ifndef SETLOCALE\n#      define SETLOCALE(category, locale) setlocale(category, locale)\n#   endif /* ndef SETLOCALE */\n#else /* !_MBCS */\n#   define CLEN(ptr) 1\n#   define PREINCSTR(ptr) (++(ptr))\n#   define POSTINCSTR(ptr) ((ptr)++)\n#   define lastchar(ptr) ((*(ptr)=='\\0') ? '\\0' : ptr[strlen(ptr)-1])\n#   define MBSCHR(str, c) strchr(str, c)\n#   define MBSRCHR(str, c) strrchr(str, c)\n#   ifndef SETLOCALE\n#      define SETLOCALE(category, locale)\n#   endif /* ndef SETLOCALE */\n#endif /* ?_MBCS */\n#define INCSTR(ptr) PREINCSTR(ptr)\n\n\n/* System independent replacement for \"struct utimbuf\", which is missing\n * in many older OS environments.\n */\ntypedef struct ztimbuf {\n    time_t actime;              /* new access time */\n    time_t modtime;             /* new modification time */\n} ztimbuf;\n\n/* This macro round a time_t value to the OS specific resolution */\n#ifndef ROUNDED_TIME\n#  define ROUNDED_TIME(time)   (time)\n#endif\n\n/* Some systems define S_IFLNK but do not support symbolic links */\n#if defined (S_IFLNK) && defined(NO_SYMLINKS)\n#  undef S_IFLNK\n#endif\n\n#ifndef Z_UINT4_DEFINED\n#  if !defined(NO_LIMITS_H)\n#    if (defined(UINT_MAX) && (UINT_MAX == 0xffffffffUL))\n       typedef unsigned int     z_uint4;\n#      define Z_UINT4_DEFINED\n#    else\n#      if (defined(ULONG_MAX) && (ULONG_MAX == 0xffffffffUL))\n         typedef unsigned long    z_uint4;\n#        define Z_UINT4_DEFINED\n#      else\n#        if (defined(USHRT_MAX) && (USHRT_MAX == 0xffffffffUL))\n           typedef unsigned short   z_uint4;\n#          define Z_UINT4_DEFINED\n#        endif\n#      endif\n#    endif\n#  endif /* !defined(NO_LIMITS_H) */\n#endif /* ndef Z_UINT4_DEFINED */\n#ifndef Z_UINT4_DEFINED\n  typedef ulg                z_uint4;\n# define Z_UINT4_DEFINED\n#endif\n\n#ifndef FOPR    /* fallback default definitions for FOPR, FOPM, FOPW: */\n#  define FOPR \"r\"\n#  define FOPM \"r+\"\n#  define FOPW \"w\"\n#endif /* fallback definition */\n\n#ifndef FOPW_TMP    /* fallback default for opening writable temp files */\n#  define FOPW_TMP FOPW\n#endif\n\n/* Open the old zip file in exclusive mode if possible (to avoid adding\n * zip file to itself).\n */\n#ifdef OS2\n#  define FOPR_EX FOPM\n#else\n#  define FOPR_EX FOPR\n#endif\n\n\n/* MSDOS file or directory attributes */\n#define MSDOS_HIDDEN_ATTR 0x02\n#define MSDOS_DIR_ATTR 0x10\n\n\n/* Define this symbol if your target allows access to unaligned data.\n * This is not mandatory, just a speed optimization. The compressed\n * output is strictly identical.\n */\n#if (defined(MSDOS) && !defined(WIN32)) || defined(i386)\n#    define UNALIGNED_OK\n#endif\n#if defined(mc68020) || defined(vax)\n#    define UNALIGNED_OK\n#endif\n\n#if (defined(SMALL_MEM) && !defined(CBSZ))\n#   define CBSZ 2048 /* buffer size for copying files */\n#   define ZBSZ 2048 /* buffer size for temporary zip file */\n#endif\n\n#if (defined(MEDIUM_MEM) && !defined(CBSZ))\n#  define CBSZ 8192\n#  define ZBSZ 8192\n#endif\n\n#ifndef CBSZ\n#  define CBSZ 16384\n#  define ZBSZ 16384\n#endif\n\n#ifndef SBSZ\n#  define SBSZ CBSZ     /* copy buf size for STORED entries, see zipup() */\n#endif\n\n#ifndef MEMORY16\n#  ifdef __WATCOMC__\n#    undef huge\n#    undef far\n#    undef near\n#  endif\n#  ifdef THEOS\n#    undef far\n#    undef near\n#  endif\n#  if (!defined(__IBMC__) || !defined(OS2))\n#    ifndef huge\n#      define huge\n#    endif\n#    ifndef far\n#      define far\n#    endif\n#    ifndef near\n#      define near\n#    endif\n#  endif\n#  define nearmalloc malloc\n#  define nearfree free\n#  define farmalloc malloc\n#  define farfree free\n#endif /* !MEMORY16 */\n\n#ifndef Far\n#  define Far far\n#endif\n\n/* MMAP and BIG_MEM cannot be used together -> let MMAP take precedence */\n#if (defined(MMAP) && defined(BIG_MEM))\n#  undef BIG_MEM\n#endif\n\n#if (defined(BIG_MEM) || defined(MMAP)) && !defined(DYN_ALLOC)\n#   define DYN_ALLOC\n#endif\n\n\n/* LARGE_FILE_SUPPORT\n *\n * Types are in osdep.h for each port\n *\n * LARGE_FILE_SUPPORT and ZIP64_SUPPORT are automatically\n * set in osdep.h (for some ports) based on the port and compiler.\n *\n * Function prototypes are below as OF is defined earlier in this file\n * but after osdep.h is included.  In the future ANSI prototype\n * support may be required and the OF define may then go away allowing\n * the function defines to be in the port osdep.h.\n *\n * E. Gordon 9/21/2003\n * Updated 7/24/04 EG\n */\n#ifdef LARGE_FILE_SUPPORT\n  /* 64-bit Large File Support */\n\n  /* Arguments for all functions are assumed to match the actual\n     arguments of the various port calls.  As such only the\n     function names are mapped below. */\n\n/* ---------------------------- */\n# ifdef UNIX\n\n  /* Assume 64-bit file environment is defined.  The below should all\n     be set to their 64-bit versions automatically.  Neat.  7/20/2004 EG */\n\n    /* 64-bit stat functions */\n#   define zstat stat\n#   define zfstat fstat\n#   define zlstat lstat\n\n# if defined(__alpha) && defined(__osf__)  /* support for osf4.0f */\n    /* 64-bit fseek */\n#   define zfseeko fseek\n\n    /* 64-bit ftell */\n#   define zftello ftell\n\n# else\n     /* 64-bit fseeko */\n#   define zfseeko fseeko\n\n     /* 64-bit ftello */\n#   define zftello ftello\n# endif                                    /* __alpha && __osf__ */\n\n    /* 64-bit fopen */\n#   define zfopen fopen\n#   define zfdopen fdopen\n\n# endif /* UNIX */\n\n/* ---------------------------- */\n# ifdef VMS\n\n    /* 64-bit stat functions */\n#   define zstat stat\n#   define zfstat fstat\n#   define zlstat lstat\n\n    /* 64-bit fseeko */\n#   define zfseeko fseeko\n\n    /* 64-bit ftello */\n#   define zftello ftello\n\n    /* 64-bit fopen */\n#   define zfopen fopen\n#   define zfdopen fdopen\n\n# endif /* def VMS */\n\n/* ---------------------------- */\n# ifdef WIN32\n\n#   if defined(__MINGW32__)\n    /* GNU C, linked against \"msvcrt.dll\" */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n# ifdef UNICODE_SUPPORT\n#     define zwfstat _fstati64\n#     define zwstat _wstati64\n#     define zw_stat struct _stati64\n# endif\n#     define zfstat _fstati64\n#     define zlstat lstat\n\n      /* 64-bit fseeko */\n      /* function in win32.c */\n      int zfseeko OF((FILE *, zoff_t, int));\n\n      /* 64-bit ftello */\n      /* function in win32.c */\n      zoff_t zftello OF((FILE *));\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n\n#   if defined(__CYGWIN__)\n    /* GNU C, CygWin with its own POSIX compatible runtime library */\n\n      /* 64-bit stat functions */\n#     define zstat stat\n#     define zfstat fstat\n#     define zlstat lstat\n\n      /* 64-bit fseeko */\n#     define zfseeko fseeko\n\n      /* 64-bit ftello */\n#     define zftello ftello\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n\n#   ifdef __WATCOMC__\n    /* WATCOM C */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n# ifdef UNICODE_SUPPORT\n#     define zwfstat _fstati64\n#     define zwstat _wstati64\n#     define zw_stat struct _stati64\n# endif\n#     define zfstat _fstati64\n#     define zlstat lstat\n\n      /* 64-bit fseeko */\n      /* function in win32.c */\n      int zfseeko OF((FILE *, zoff_t, int));\n\n      /* 64-bit ftello */\n      /* function in win32.c */\n      zoff_t zftello OF((FILE *));\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n\n#   ifdef _MSC_VER\n    /* MS C and VC */\n\n      /* 64-bit stat functions */\n#     define zstat _stati64\n# ifdef UNICODE_SUPPORT\n#     define zwfstat _fstati64\n#     define zwstat _wstati64\n#     define zw_stat struct _stati64\n# endif\n#     define zfstat _fstati64\n#     define zlstat lstat\n\n      /* 64-bit fseeko */\n      /* function in win32.c */\n      int zfseeko OF((FILE *, zoff_t, int));\n\n      /* 64-bit ftello */\n      /* function in win32.c */\n      zoff_t zftello OF((FILE *));\n\n      /* 64-bit fopen */\n#     define zfopen fopen\n#     define zfdopen fdopen\n\n#   endif\n\n#   ifdef __IBMC__\n      /* IBM C */\n\n      /* 64-bit stat functions */\n\n      /* 64-bit fseeko */\n      /* function in win32.c */\n      int zfseeko OF((FILE *, zoff_t, int));\n\n      /* 64-bit ftello */\n      /* function in win32.c */\n      zoff_t zftello OF((FILE *));\n\n      /* 64-bit fopen */\n\n#   endif\n\n# endif /* WIN32 */\n\n#else\n  /* No Large File Support or default for 64-bit environment */\n\n# define zstat stat\n# define zfstat fstat\n# define zlstat lstat\n# define zfseeko fseek\n# define zftello ftell\n# define zfopen fopen\n# define zfdopen fdopen\n# ifdef UNICODE_SUPPORT\n#   define zwfstat _fstat\n#   define zwstat _wstat\n#   define zw_stat struct _stat\n# endif\n\n#endif\n\n#ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/2003 */\n\n# ifndef SSTAT\n#  define SSTAT      zstat\n#  ifdef UNICODE_SUPPORT\n#    define SSTATW   zwstat\n#  endif\n# endif\n# ifdef S_IFLNK\n#  define LSTAT      zlstat\n#  define LSSTAT(n, s)  (linkput ? zlstat((n), (s)) : SSTAT((n), (s)))\n# else\n#  define LSTAT      SSTAT\n#  define LSSTAT     SSTAT\n#  ifdef UNICODE_SUPPORT\n#    define LSSTATW  SSTATW\n#  endif\n# endif\n\n#else /* no LARGE_FILE_SUPPORT */\n\n# ifndef SSTAT\n#  define SSTAT      stat\n# endif\n# ifdef S_IFLNK\n#  define LSTAT      lstat\n#  define LSSTAT(n, s)  (linkput ? lstat((n), (s)) : SSTAT((n), (s)))\n# else\n#  define LSTAT      SSTAT\n#  define LSSTAT     SSTAT\n#  ifdef UNICODE_SUPPORT\n#    define LSSTATW  SSTATW\n#  endif\n# endif\n\n#endif\n\n\n/*---------------------------------------------------------------------*/\n\n\n/* 2004-12-01 SMS.\n * Added fancy zofft() macros, et c.\n */\n\n/* Default fzofft() format selection.\n * Modified 2004-12-27 EG\n */\n\n#ifndef FZOFFT_FMT\n# define FZOFFT_FMT      ZOFF_T_FORMAT_SIZE_PREFIX /* printf for zoff_t values */\n\n# ifdef LARGE_FILE_SUPPORT\n#   define FZOFFT_HEX_WID_VALUE     \"16\"  /* width of 64-bit hex values */\n# else\n#   define FZOFFT_HEX_WID_VALUE     \"8\"   /* digits in 32-bit hex values */\n# endif\n\n#endif /* ndef FZOFFT_FMT */\n\n#define FZOFFT_HEX_WID ((char *) -1)\n#define FZOFFT_HEX_DOT_WID ((char *) -2)\n\n\n\n\n/* The following default definition of the second input for the crypthead()\n * random seed computation can be used on most systems (all those that\n * supply a UNIX compatible getpid() function).\n */\n#ifdef ZCRYPT_INTERNAL\n#  ifndef ZCR_SEED2\n#    define ZCR_SEED2     (unsigned) getpid()   /* use PID as seed pattern */\n#  endif\n#endif /* ZCRYPT_INTERNAL */\n\n/* The following OS codes are defined in pkzip appnote.txt */\n#ifdef AMIGA\n#  define OS_CODE  0x100\n#endif\n#ifdef VMS\n#  define OS_CODE  0x200\n#endif\n/* unix    3 */\n#ifdef VM_CMS\n#  define OS_CODE  0x400\n#endif\n#ifdef ATARI\n#  define OS_CODE  0x500\n#endif\n#ifdef OS2\n#  define OS_CODE  0x600\n#endif\n#ifdef MACOS\n#  define OS_CODE  0x700\n#endif\n/* z system 8 */\n/* cp/m     9 */\n#ifdef TOPS20\n#  define OS_CODE  0xa00\n#endif\n#ifdef WIN32\n#  define OS_CODE  0xb00\n#endif\n#ifdef QDOS\n#  define OS_CODE  0xc00\n#endif\n#ifdef RISCOS\n#  define OS_CODE  0xd00\n#endif\n#ifdef VFAT\n#  define OS_CODE  0xe00\n#endif\n#ifdef MVS\n#  define OS_CODE  0xf00\n#endif\n#ifdef __BEOS__\n#  define OS_CODE  0x1000\n#endif\n#ifdef TANDEM\n#  define OS_CODE  0x1100\n#endif\n#ifdef THEOS\n#  define OS_CODE  0x1200\n#endif\n/* Yes, there is a gap here. */\n#ifdef __ATHEOS__\n#  define OS_CODE  0x1E00\n#endif\n\n#define NUM_HOSTS 31\n/* Number of operating systems. Should be updated when new ports are made */\n\n#if defined(DOS) && !defined(OS_CODE)\n#  define OS_CODE  0x000\n#endif\n\n#ifndef OS_CODE\n#  define OS_CODE  0x300  /* assume Unix */\n#endif\n\n/* can't use \"return 0\" from main() on VMS */\n#ifndef EXIT\n#  define EXIT  exit\n#endif\n#ifndef RETURN\n#  define RETURN return\n#endif\n\n#ifndef ZIPERR\n#  define ZIPERR ziperr\n#endif\n\n#if (defined(USE_ZLIB) && defined(MY_ZCALLOC))\n   /* special zcalloc function is not needed when linked against zlib */\n#  undef MY_ZCALLOC\n#endif\n\n#if (!defined(USE_ZLIB) && !defined(MY_ZCALLOC))\n   /* Any system without a special calloc function */\n#  define zcalloc(items,size) \\\n          (zvoid far *)calloc((unsigned)(items), (unsigned)(size))\n#  define zcfree    free\n#endif /* !USE_ZLIB && !MY_ZCALLOC */\n\n/* end of tailor.h */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/HISTORY",
    "content": "Tandem Port History\n===================\n\nHi, I'm Dave Smith and I work at BP Oil UK, looking after their European card\nprocessing system since 1992.  We need to send lots of files via FTP to other\nBP machines (Novell, NT, Sun...). Sending large files was frowned upon, so the\nsearch for a zip product was on.\n\nWe tried the GZIP product from Twinsoft Netherlands but it was complicated to\nuse and it was not widely known by other arts of BP.\n\nWhat we really wanted was a PKZIP compatible product, as this is a widely known\nproduct.  By chance when surfing the web I discovered the Info-ZIP web site.\nThis claimed PKZIP 2.04g compatibility and had a number of ports, was free, and\neven had source code, but unfortunately no Tandem version :-(\n\nThus in the autumn 1996 I bit the bullet and took on the job of porting the\ncode to Tandem NSK (Guardian).  This meant dusting off my circa 1985 'C'\nprogramming skills and firing up the Tandem 'C' compiler - not known for its\nease of use, especially debugging 8-;  This was all on D30 by the way.\n\nTo start this off I had to choose an existing port to base te Tandem one on.\nNearest (?) was the VM-CMS/MVS port by George Petrov.  The main similarity\nbeing that these machines are record based, and have a similarish filing system\nto Guardian.\n\nFirst to be tackled was ZIP.  By the end of 1996 I had a version which compiled\nand ran (giving the program banner) - which seemed like a major acheivement at\nthe time.\n\nIn December 1996 I forwarded a version of ZIP to Info-ZIP which wor\nked only on Edit files, and had no concept of directories.  Became ZIP 2.1\n\nBy March 1997 I had improved ZIP so that it could cope with Unstructured files\nas well (Became ZIP 2.2).  I also had ported a version of UNZIP which could\ncreate Unstructured files (not Edit) - UNZIP 5.20\n\nAt the start of September 1997 I sent UNZIP with Edit file support to Info-ZIP\n(incorporated into 5.32)\n\nIn March 1998 I submitted file I/O improvements (SBB) for ZIP (2.3a)\n\nIn August 1998 I added Tandem DEFINE processing for ZIP (2.3e).  This was a\nfeature required by BP to allow them to store files with a different internal\nname than the physical file being zipped (without renaming it).\nAlso added storing of proper UTC timestamps which allow for DST & timezone.\n\nAlso in August I added the same file I/O improvements for UNZIP (5.33f)\n\nI then added the ability to update the unzipped files last modified and last\nopen timestamps - this required help from TNSC to allow me access to the\npriviliged procedure call.  Also can give the files back to the original user\nby use of the '-X' flag.\n\nAt the end of 1998 I was given the go ahead to add the zipping of Enscribe\nfiles.  This first version stores all Enscribe file attributes EXCEPT SQL, alt\nkey and partition information.\n\nZIP now uses its own Guardian I/O (rather than the 'C'library) for the reading\nof files to be zipped.\n\nUnstructured files use Large Transfer mode and READ (56K or 30K reads)\nEdit files use IOEdit routines\nEnscribe files use READ and SBB and add LF to the end of each record.\n\nUNZIP has the ability to update the filecode of files restored to ther original\nvalue (Unstructured only)\n\n\nTo Do ZIP\n===========\n1. Change I/O to use NSK/Large Transfer mode in fwrite of ZIP file itself- this\n   will dramaticaly speed up updating an existing zipfile. When updating an\n   existing zipfile it copies it to a temporary file currently using only SBB.\n2. Add raw binary mode to allow storing of raw data in zip file - e.g. only to\n   be unzipped on Tandem !  This is simplest/fastest way to provide full\n   Enscribe support for Tandem platform - with no cross-platform support.\n3. Add SQL support !!\n\nTo Do UNZIP\n===========\n1. Re-write the I/O routines to use NSK to recreate the original Enscribe file\n   structure.\n2. Use NSK Large Transfer mode I/O for reading/writing of ZIP file\n3. Add raw binary mode to allow restoration of Tandem file from previous raw\n   data ZIP (see above)\n4. Add SQL support !!\n\n\n\nCurrent Versions on Website\n===========================\n\nZIP 2.3\nUNZIP 5.5\n\nAs of February 17th 2002\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/README",
    "content": "Tandem Port of Info ZIP (zip)\n=======================\n\nHistory:\n1. Tidy up COMMACS/MACROS/MAKE\n2. Changes for version 5.32d affected files:\n- TANDEMC     (changes to stat() for UNZIP)\n- ZIPUPC      (changes to use REVISIOH rather than REVISEH)\n- ZIPFILEC    (don't add \".zip\" to ZIP name)\n- FILEIOC     (cosmetic missing \"*/\")\n3. Fix to allow zipping of files called ZIP (e.g. DAVES.ZIP)\n03/08/98  2.3e   Process Tandem DEFINE names - use define name as internal name\n                 Remove BITSO from build of ZIPLIB\n                 New DOIT macro for extracting files from archive\n17/08/98  2.3e   Set USE_EF_UT_TIME to allow for timezone changes\n18/08/98  2.3e   Use define LICENSED to build object able to update timestamps\n30/11/98  2.3h   Updated mapname/chmod/in2ex, include licensing in MAKE\n21/12/98  2.3i   Add simple Enscribe file handling, consisting of:\n                 - storing Enscribe files as LF delimited text files\n                 - adding Tandem Extra Field, holding Enscribe file attributes\n                 Create ZIP file with Tandem File Code 1001\n                 Rationalised TANDEMH and TANDEMC wth UNZIP 5.40d\n12/01/99  2.3i   Correct bug stopping setting of last open timestamp\n25/01/99  2.3k   Add '-B' flag to zip Enscribe files with no record delimiters\n26/01/99  2.3k   Make CRLF the default delimiter for Structured and Text files\n01/02/99  2.3k   Use maximum size large transfer read (57344) as default, allow\n                 smaller value as option\n01/02/99  2.3k   Redefine -B flag for Edit/Enscribe files as in table below.\n                 Default (-B or -B0 or no flag) is add CR/LF\n\n                 -B<number> options at present are:\n                 Bit 0 -  Don't add delimiter (Edit/Enscribe)\n                 Bit 1 -  Use LF rather than CR/LF as delimiter (Edit/Enscribe)\n                 Bit 2 -  Space fill record to max record length (Enscribe)\n                 Bit 3 -  Trim trailing space (Edit/Enscribe)\n\n                 Bit 8 -  Force 30K (Expand) large read for Unstructured files\n\n06/02/99  2.3k   Attempt to catch Large Transfer mode failure (err 21) when\n                 attempting 56K reads, add substitute 30K reads (Expand files)\n24/03/99  2.3m   Split TANDEMC into TANDEMC/TANZIPC/TANUNZC\n24/03/99  2.3m   Added TANNSKH to allow for declarations which require\n                 structures defined in ZIPH after call to TANDEMH\n11/05/99  2.3m   Change zopen in TANZIPC to allow opening of files with\n                 missing alt keys (err 4)\n                 Assume not DST if can't resolve time (no DST table available)\n27/09/99  2.3o   Fixed bug in -B0 option causing files to be stored rather than\n                 deflated. Created TANZIPH\n29/04/02  2.4g   Fixed contention on temporary file when multiple ZIPs run\n\nA few notes about the files on this subvol\n\nCOMMACS   -  used by MAKE (compiler)\nDOIT      -  macro to extract required Tandem files from archive and rename\nMACROS    -  used by MAKE (bind)\nMAKE      -  recompile ZIP code, attempts to only recompile changed code\nREADME    -  this file\nZIPLIB    -  library of ZIP compiled routines, used by ZIP/ZIPNOTE etc\nZIPL      -  ZIP object (bound using LARGE memory model)\nZIPNOTE   -  ZIPNOTE object (bound using LARGE memory model)\n\n*C        -  Source file\n*H        -  Header files\n*O        -  Individual object files (when compiled by MAKE)\n\nInstall Notes:\n==============\nStage 1 - get ZIP object onto Tandem\n- download Tandem Zip executables archive from Web\n- using PC unzip program (e.g. pkunzip/WinZip) extract ZIP\n- copy ZIP from PC to Tandem in Binary mode s(FTP/IXF)\n- alter file code to 100\n- optionally place in $SYSTEM.SYSTEM to allow easy access from command line\n\nStage 2 - (optional) compile source code (requires UNZIP on Tandem)\n- download ZIP source archive fwom web - contains all supported platforms\n- copy archive onto Tandem as Binary\n- extract Tandem DOIT macro ( UNZIP -j <archive> tandem/DOIT )\n- update DOIT macro to point at archive file\n- restore relevant files by running DOIT\n- NOTE that revision.h must be restored as REVISIOH\n- replace references to $T with a collector on your system\n- replace references to SUPER.DAVES with whatever user id you use\n- to compile run MAKE (compiles, accelerates, licences)\n- NOTE:  Always run the accelerated object on TNS/R systems, otherwise\n         it runs extremely slow.\n\n\nAdditional Notes - LICENSE the object:\n======================================\nIf you wish to be able to update the last modified time of the zip file\n(-o option) you need to add the line \"#define LICENSED\" to the TANDEMH file.\nIf you set this option then you MUST FUP LICENSE the file as SUPER.SUPER.\nThis is a Tandem restriction since we have to call a PRIV procedure to update\nthe file label.  For ZIP the define is setup (default) in tandem.h\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/commacs",
    "content": "?section CC ROUTINE\n#FRAME\n[#PUSH file stem src obj htime file prev time stime otime\n       comp out options sup buf col locn group\n]\n\n[#IF [#ARGUMENT /VALUE file/ WORD /SPACE/ END]]\n[#IF [#EMPTYV file] |THEN|\n  #OUTPUT Syntax: CC <file> <collector> <comp-options>\n  #RESET FRAMES\n  #RETURN\n]\n\n[#IF NOT [#FILEINFO /EXISTENCE/ [file]]\n|THEN|\n  #OUTPUT [file] does not exist !\n  #RESET FRAMES\n  #RETURN\n]\n\n#PUSH #DEFAULTS vol subvol\n#SETMANY vol subvol src, [#FILEINFO /VOLUME, SUBVOL, FILE/ [file]]\nVOLUME [vol].[subvol]\n\n#SETV stem file\n#CHARDEL stem [#CHARCOUNT stem]\n#SET obj [stem]O\n#SETV stem src\n#CHARDEL stem [#CHARCOUNT stem]\n\n[#IF [#ARGUMENT /VALUE out/ DEVICE END]]\n[#IF [#EMPTYV out] |THEN| #SET out $T.#C]\n\n#SETMANY col group, [#FILEINFO /VOLUME, SUBVOL/ [out]]\n#SET locn [group].[stem]\n#SET sup [#LOOKUPPROCESS /ANCESTOR/ [col]]\n\n#SET options [#REST]\n\n== Find newest Header file\n#SET htime 0\n#SET file [#FILENAMES /MAXIMUM 1/ *H]\n[#LOOP |WHILE| NOT [#EMPTYV file]\n|DO|\n  #SET time [#FILEINFO /MODIFICATION/ [file]]\n  [#IF time > htime |THEN| #SETV htime time]\n\n  #SETV prev file\n  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ *H]\n]\n\n#SET stime [#FILEINFO /MODIFICATION/ [src]]\n#SET otime [#FILEINFO /MODIFICATION/ [obj]]\n\n#SET comp 0\n\n[#IF otime < htime\n|THEN|\n  #OUTPUT Header file(s) changed since object [obj] compiled\n  #SET comp -1\n]\n\n[#IF otime < stime\n|THEN|\n  #OUTPUT Source file [src] changed since object [obj] compiled\n  #SET comp -1\n]\n\n[#IF comp\n|THEN|\n  SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !\n  #SET buf\n  #OUTPUT Compiling [src]... [options]\n  C /IN [src], OUT [out].[stem]/[obj];SYMBOLS,HIGHPIN [options]\n  [#CASE [tacl^completioncode]\n  | 0 |\n    #OUTPUT Compiled OK: [src]\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS,DELETE !\n    #SET _completion:completioncode 0\n  | 1 |\n    #OUTPUT [src]: Compile Warnings\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS\n    #OUTPUTV buf\n  |OTHERWISE|\n    #OUTPUT [src]: Compile FAILED !\n    SPOOLCOM /OUTV buf/ OPEN [sup];JOB (OWNER, LOC [locn]),STATUS\n    #OUTPUTV buf\n  ]\n|ELSE|\n  #OUTPUT Object file [obj] is up to date\n  #SET _completion:completioncode 0\n]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/doit",
    "content": "?tacl macro\n#frame\n#push zipfile\n#SET zipfile [#FILEINFO /SUBVOL/ A]\n\nunzip -a [zipfile] *.c  -x */*\n== Following not required\nRENAME apic     apicz\nRENAME timezonc timezonz\n\nunzip -a [zipfile] *.h -x */*\n== Following not required\nRENAME apih    apizh\n\nunzip -aj [zipfile] tandem/*.h\n\nunzip -aj [zipfile] tandem/*.c\n\nunzip -aj [zipfile] tandem/* -x tandem/*.*\n\n#unframe\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/macros",
    "content": "?section ADD^LIST routine\n[#IF [#ARGUMENT /VALUE item/ WORD/SPACE/]]\n#APPEND bin ADD * FROM [item]\n#SET itime [#FILEINFO /MODIFICATION/ [item]]\n[#IF itime > ntime |THEN| #SETV ntime itime]\n\n?section BBZIPLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list CRYPTO\nadd^list DEFLATEO\nadd^list FILEIOO\nadd^list GLOBALSO\nadd^list TANDEMO\nadd^list TANZIPO\nadd^list TREESO\nadd^list TTYIOO\nadd^list UTILO\nadd^list ZIPFILEO\nadd^list ZIPUPO\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBZIP MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM ZIPO\n#APPEND bin select search ($system.system.c%2%, [lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ ZIPO] |THEN|\n  #OUTPUT %1% is older than ZIPO\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section BBANY MACRO\n#FRAME\n#push bin memory anytime build\n#SET build 0\n#SETMANY memory, %2% LARGE\n#OUTPUT Building %1% with [memory] memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM %1%O\n#APPEND bin select search ($system.system.c[memory],[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET anytime [#FILEINFO /MODIFICATION/ %1%]\n[#IF anytime < [#FILEINFO /MODIFICATION/ %1%O] |THEN|\n  #OUTPUT %1% is older than %1%O\n  #SET build -1\n]\n[#IF anytime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n\n?section BBUNZIPLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list CRYPTO\nadd^list ENVARGSO\nadd^list EXPLODEO\nadd^list EXTRACTO\nadd^list FILEIOO\nadd^list GLOBALSO\nadd^list INFLATEO\nadd^list LISTO\nadd^list MATCHO\nadd^list PROCESSO\nadd^list TANDEMO\nadd^list TANUNZO\nadd^list TTYIOO\nadd^list UNSHRINO\nadd^list ZIPINFOO\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBUNZIP MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM UNZIPO\n#APPEND bin select search ($system.system.c%2%,[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPO] |THEN|\n  #OUTPUT %1% is older than UNZIPO\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section BBSFXLIB MACRO\n#FRAME\n#push bin item ntime itime libtime\n#SET ntime 0\n\n#OUTPUT Building [lib]\n#APPEND bin CLEAR\nadd^list CRC32O\nadd^list EXTRACTX\nadd^list FILEIOX\nadd^list GLOBALSX\nadd^list INFLATEX\nadd^list MATCHX\nadd^list PROCESSX\nadd^list TANDEMX\nadd^list TANUNZX\nadd^list TTYIOX\n#APPEND bin INFO UNRESOLVED *\n#APPEND bin BUILD [lib] ! , LIST * OFF\n\n#SET libtime [#FILEINFO /MODIFICATION/ [lib]]\n[#IF libtime < ntime\n|THEN|\n  #OUTPUT [lib] needs re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound [lib] OK\n  | 1         | #OUTPUT [lib]: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT [lib]: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT [lib] is up to date\n]\n\n#UNFRAME\n\n?section BBSFX MACRO\n#FRAME\n#push bin ziptime build\n#SET build 0\n#OUTPUT Building %1% with %2% memory model\n#APPEND bin CLEAR\n#APPEND bin ADD * FROM UNZIPX\n#APPEND bin select search ($system.system.c%2%,[lib])\n#APPEND bin select runnable object on\n#APPEND bin select list * off\n#APPEND bin set heap 20 pages\n#APPEND bin set symbols on\n#APPEND bin set saveabend on\n#APPEND bin set inspect on\n#APPEND bin info unresolved *\n#APPEND bin BUILD %1%   !\n\n#SET ziptime [#FILEINFO /MODIFICATION/ %1%]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ UNZIPX] |THEN|\n  #OUTPUT %1% is older than UNZIPX\n  #SET build -1\n]\n[#IF ziptime < [#FILEINFO /MODIFICATION/ [lib]] |THEN|\n  #OUTPUT %1% is older than [lib]\n  #SET build -1\n]\n[#IF build\n|THEN|\n  #OUTPUT %1% is out of date, re-building\n  BIND /NAME,INV BIN/\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Bound %1% OK\n  | 1         | #OUTPUT %1%: BIND Failed with Warnings\n  | OTHERWISE | #OUTPUT %1%: BIND Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %1% is up to date, no re-build required\n]\n\n#UNFRAME\n\n?section accel^file MACRO\n#FRAME\n#PUSH buf\n[#IF [#FILEINFO /MODIFICATION/ %1%]\n   > [#FILEINFO /MODIFICATION/ %2%]\n|THEN|\n  #OUTPUT %2% is older than %1%\n  #OUTPUT Accelerating %1% to %2%\n  AXCEL /OUTV buf/ %1%,%2%\n  #OUTPUTV buf\n  [#CASE [tacl^completioncode]\n  | 0         | #OUTPUT Accelerated %2% OK\n  | 1         | #OUTPUT %2%: AXCEL Failed with Warnings\n  | OTHERWISE | #OUTPUT %2%: AXCEL Failed with ERRORS !\n  ]\n|ELSE|\n  #OUTPUT %2% is up to date\n]\n\n#UNFRAME\n\n?section fup^license ROUTINE\n#FRAME\n#PUSH #DEFAULTS filename old^user current^user\n\n[#IF [#ARGUMENT /VALUE filename/ FILENAME]]\n\n#SET old^user [#USERNAME [#PROCESSINFO /PAID/]]\n#SETV current^user old^user\n[#LOOP |WHILE| current^user '<>' \"SUPER.SUPER\"\n               AND NOT [#INPUTEOF]\n|DO|\n  #OUTPUT Please log on as SUPER.SUPER (CTRL-Y aborts)\n  logon SUPER.SUPER\n  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]\n  #OUTPUT\n]\n\n[#IF current^user '=' \"SUPER.SUPER\" |THEN|\n  #OUTPUT Licensing [filename]\n  $SYSTEM.SYSTEM.FUP LICENSE [filename]\n]\n\n[#LOOP |WHILE| current^user '<>' old^user\n               AND NOT [#INPUTEOF]\n|DO|\n  #OUTPUT Please log on as [old^user] (CTRL-Y aborts)\n  logon [old^user]\n  #SET current^user [#USERNAME [#PROCESSINFO /PAID/]]\n  #OUTPUT\n]\n\n#UNFRAME\n\n\n?section CODE routine\n#FRAME\n#PUSH delta arg\n\n#SET /TYPE delta/ DELTA\n\n[#LOOP |WHILE| [#COMPUTE [#ARGUMENT /VALUE arg/ NUMBER END] = 1 ]\n|DO|\n  #APPEND DELTA [arg]I\n]\n\n#RESULT [#DELTA /COMMANDS DELTA/]\n\n#UNFRAME\n\n\n?section TACL^COMPLETIONCODE routine\n#RESULT [_completion:completioncode]\n\n?SECTION INCREMENT routine\n#FRAME\n#PUSH increment_variable increment_value\n\n[#IF [#ARGUMENT /VALUE increment_variable/ VARIABLE]]\n[#IF [#EMPTYV [increment_variable]]|THEN|#SET [increment_variable] 0]\n[#IF [#MORE]\n  |THEN|\n    [#IF [#ARGUMENT /VALUE increment_value/ NUMBER]]\n  |ELSE|\n    #SET increment_value 1\n]\n[#IF [#ARGUMENT END]]\n\n#SET [increment_variable] [#COMPUTE [increment_variable] + [increment_value]]\n\n#UNFRAME\n\n?section ERROR^IN^FUP^OUTPUT routine\n#FRAME\n#PUSH err output last line type\n\n#SETMANY err output, 0 0\n\n[#LOOP |WHILE| NOT [#EMPTYV fup^out]\n|DO|\n   #EXTRACTV fup^out line\n   [#SETMANY type, [#CHARGET line 1 TO 7] .]\n   [#CASE [type]\n     | ERROR     | #SETMANY output err, -1 -1\n     | WARNING   | #SET output -1\n     | OTHERWISE |\n   ]\n   [#IF output |THEN|\n     #OUTPUTV last\n     #OUTPUTV line\n     #SET output 0\n     #EXTRACTV fup^out line\n   ]\n   #SETV last line\n]\n\n#RESULT [err]\n\n#UNFRAME\n\n?section SECURE^FILE routine\n#FRAME\n\n[#DEF fup^out TEXT |BODY|]\n[#DEF fup^buf TEXT |BODY|]\n\n[#DEF fup^cmd MACRO |BODY|\n  FUP /OUTV fup^out/ %*%\n  #SETV fup^buf fup^out\n  [#IF [error^in^fup^output]\n  |THEN|\n    #OUTPUT Error detected in FUP output, ABORTING !!\n    #OUTPUT ..............................................................\n    #OUTPUTV fup^buf\n    #OUTPUT ..............................................................\n    #RAISE _BREAK\n  ]\n]\n\n[#DEF display^action MACRO |BODY|\n  [#IF NOT action |THEN|\n    #OUTPUT /HOLD/ Updating [file] ...\n    #SET action -1\n    #SET count 0\n  ]\n  #OUTPUT /COLUMN 3/ ... %*%\n]\n\n[#DEF display^noaction MACRO |BODY|\n  [#IF count\n  |THEN|\n    increment count\n  |ELSE|\n    #OUTPUT\n    #SET count 1\n  ]\n  [#IF count |THEN|\n    #OUTPUT /COLUMN [count]/ [code 27]A.\n    [#IF count > 75\n    |THEN|\n      #SET count 0\n    ]\n  ]\n]\n\n[#DEF process^file TEXT |BODY|\n  #SET action 0\n  #SETMANY cur^owner cur^security cur^license cur^progid, &\n    [#FILEINFO /OWNER, SECURITY, LICENSED, PROGID/ [file]]\n\n  #SET cur^owner [#USERNAME [cur^owner]]\n\n  [#IF NOT [#EMPTYV owner]\n  |THEN|\n    [#IF owner '<>' cur^owner\n    |THEN|\n      display^action giving to [owner]  (was [cur^owner])\n      fup^cmd GIVE [file], [owner]\n      [#IF cur^progid\n      |THEN|\n        #OUTPUT /COLUMN 3/... WARNING!  Loss of PROGID flag\n        #SET cur^progid 0\n      ]\n    ]\n  ]\n  [#IF NOT [#EMPTYV security]\n  |THEN|\n    [#IF security '<>' cur^security\n    |THEN|\n      display^action securing to [security] (was [cur^security])\n      fup^cmd SECURE [file], [security]\n    ]\n  ]\n  [#IF license |THEN|\n    [#IF NOT cur^license\n    |THEN|\n      display^action licensed\n      fup^cmd LICENSE [file]\n    ]\n  ]\n  [#IF progid |THEN|\n    [#IF NOT cur^progid\n    |THEN|\n      display^action PROGID flag set\n      fup^cmd SECURE [file],, PROGID\n    ]\n  ]\n  [#IF action\n  |THEN|\n    fup^cmd INFO [file]\n  |ELSE|\n    [#IF tflag\n    |THEN|\n      display^noaction\n    |ELSE|\n      #OUTPUT  /HOLD/ Unchanged : [file]\n      [#IF cur^progid  |THEN| #OUTPUT /COLUMN 39,HOLD/ P]\n      [#IF cur^license |THEN| #OUTPUT /COLUMN 40,HOLD/ L]\n      #OUTPUTV /COLUMN 43,HOLD/ cur^security\n      #OUTPUTV /COLUMN 50,HOLD/ cur^owner\n      #OUTPUT\n    ]\n ]\n]\n\n#PUSH arg template file security owner progid license prev action count tflag\n#PUSH cur^security cur^owner cur^license cur^progid\n\n#SETMANY license progid, 0 0\n#SET count 0\n#SET tflag 0\n\n[#LOOP |WHILE| [#MORE]\n|DO|\n  [#CASE [#ARGUMENT /VALUE arg/ FILENAME\n                                USER /USERNAME/\n                                USER\n                                SECURITY\n                                KEYWORD /WORDLIST LICENSE/\n                                KEYWORD /WORDLIST PROGID/\n                                TEMPLATE\n         ]\n  | 1 | #SETV file     arg\n  | 2 | #SETV owner    arg\n  | 3 | #SET  owner [#USERNAME [arg]]\n  | 4 | #SETV security arg\n  | 5 | #SET  license  -1\n  | 6 | #SET  progid   -1\n  | 7 | #SETV template arg\n  ]\n]\n[#IF [#ARGUMENT END]]\n\n\n[#IF [#EMPTYV template]\n|THEN|\n  #SETV template file\n|ELSE|\n  #SET tflag -1\n  #OUTPUT /HOLD/ Template : [template]\n  [#IF progid  |THEN| #OUTPUT /COLUMN 39,HOLD/ P]\n  [#IF license |THEN| #OUTPUT /COLUMN 40,HOLD/ L]\n  [#IF NOT [#EMPTYV security] |THEN| #OUTPUTV /HOLD/ \"  \"[security]\"\"]\n  [#IF NOT [#EMPTYV owner]    |THEN| #OUTPUTV /HOLD/ \"  [owner]\"]\n  #OUTPUT\n]\n\n[#IF [#EMPTYV template]\n|THEN|\n  #OUTPUT ERROR!  No filename specified\n  #RESET FRAMES\n  #RETURN\n|ELSE|\n  #SET file [#FILENAMES /MAXIMUM 1/ [template]]\n  [#LOOP |WHILE| NOT [#EMPTYV file]\n  |DO|\n    process^file\n    #SETV prev file\n    #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ [template]]\n  ]\n]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/make",
    "content": "?tacl routine\n#FRAME\nSINK [#LOAD /keep 1/ commacs]\nSINK [#LOAD /keep 1/ macros]\n\n[#PUSH file prev memory clib OK model zip lib accel unlicensed licensed\n       options fileset nocrypt crypt\n]\n#PUSH #DEFAULTS\n\n#SET OK -1\n\n[#IF [#ARGUMENT /VALUE memory/ KEYWORD /WORDLIST LARGE SMALL/ OTHERWISE ]]\n[#IF [#ARGUMENT /VALUE model/ KEYWORD /WORDLIST NOWIDE WIDE/ OTHERWISE ]]\n[#IF [#ARGUMENT /VALUE unlicensed/ KEYWORD /WORDLIST UNLICENSED/ OTHERWISE ]]\n[#IF [#ARGUMENT /VALUE nocrypt/ KEYWORD /WORDLIST NOCRYPT/ OTHERWISE ]]\n[#IF [#ARGUMENT /VALUE fileset/ TEMPLATE FILENAME OTHERWISE ]]\n\n[#IF [#EMPTYV memory] |THEN| #SET memory LARGE]\n[#IF [#EMPTYV model] |THEN| #SET model NOWIDE]\n\n[#IF model '=' \"WIDE\"\n  |THEN| #SETV clib model\n  |ELSE| #SETV clib memory\n]\n\n[#IF model '=' \"WIDE\"\n|THEN|\n  #SET zip ZIPW\n|ELSE|\n  #SET zip ZIPL\n]\n#SET lib [zip]B\n#SET accel ZIP\n#SET options [options], [model]\n\n[#IF unlicensed '=' \"UNLICENSED\"\n|THEN|\n  #SET zip [zip]U\n  #SET accel [accel]U\n  #SET lib   [lib]U\n|ELSE|\n  #SET licensed LICENSED\n  #SET options [options], define [licensed]\n]\n\n[#IF nocrypt '=' \"NOCRYPT\"\n|THEN|\n|ELSE|\n  #SET crypt USE_CRYPT\n  #SET options [options], define [crypt]\n]\n\n[#IF [#EMPTYV fileset] |THEN| #SET fileset *C]\n\n#OUTPUT Files to compile: [fileset]\n#OUTPUT Pointer Model   : [model]\n#OUTPUT Memory Model    : [memory]\n#OUTPUT C Library       : [clib]\n#OUTPUT Axcel Object    : [accel]\n#OUTPUT Run Object      : [zip]\n#OUTPUT Library Object  : [lib]\n#OUTPUT Compile Options : [options]\n#OUTPUT\n\n#SET file [#FILENAMES /MAXIMUM 1/ [fileset]]\n[#loop |while| NOT [#EMPTYV file]\n|do|\n  #SETV prev file\n  CC [file] $T.#ZIP [options]\n  [#IF [tacl^completioncode] > 1 |THEN| #set OK 0 ]\n  #SET file [#FILENAMES /MAXIMUM 1, PREVIOUS [prev]/ [fileset]]\n]\n\n[#IF OK |THEN|\n  BBZIPLIB\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n#PUSH #PROCESSFILESECURITY\nVOLUME ,\"NUNU\"\n\n[#IF OK |THEN|\n  BBZIP [zip] [clib]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n[#IF OK |THEN|\n  secure^file [accel] \"UUUU\" SUPER.DAVES\n  accel^file [zip] [accel]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n[#IF OK\n  |THEN| #OUTPUT Successfully produced Accelerated Object [accel]\n         secure^file [accel] \"UUUU\" SUPER.DAVES\n         [#IF [#INTERACTIVE] |THEN|\n           [#IF licensed '=' \"LICENSED\" |THEN|\n             #OUTPUT [accel] will not run without being LICENSED\n             [#IF [#FILEINFO /LICENSED/ [accel]]\n             |THEN|\n               #OUTPUT [accel] already LICENSED\n             |ELSE|\n               [#IF [#MATCH Y* [#INPUT [accel] License [accel] ?]] |THEN|\n                 fup^license [accel]\n               ]\n             ]\n           ]\n         ]\n  |ELSE| #OUTPUT Failed to produce Accelerated Object [accel]\n]\n\n#OUTPUT Finished\n\n#OUTPUT Setting up additonal utilities\n== ZIPNOTE\nCC ZIPNOTEC $T.#ZIP [options]\n#SET zip ZIPNOTE\n#SET accel ZIPNOTE\n[#IF OK |THEN|\n  BBANY [zip] [clib]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n[#IF OK |THEN|\n  secure^file [accel] \"UUUU\" SUPER.DAVES\n  accel^file [zip] [accel]\n  [#IF [tacl^completioncode] > 0 |THEN| #SET OK 0]\n]\n\n#UNFRAME\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/tandem.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * routines common to TANDEM (ZIP and UNZIP)\n */\n\n#include \"zip.h\"   /* This sets up ZIP / UNZIP define */\n\n#include <tal.h>\n#include \"$system.zsysdefs.zsysc\" nolist\n#include <cextdecs> nolist\n#include \"tannsk.h\"\n\nstatic time_t gmt_to_time_t (long long *);\n\nint isatty (fnum)\nint fnum;\n{\n  return 1;\n}\n\n/********************/\n/* Function in2ex() */\n/********************/\n\n#ifdef UNZIP\nchar *in2ex(__G__ n)\n  __GDEF\n#else\nchar *in2ex(n)\n#endif\n  char *n;              /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name buffer */\n  char *y;              /* pointer to external buffer */\n  char *max;            /* pointer to max end of next file part */\n  char *t;              /* pointer to internal - start of substring */\n  char *p;              /* pointer to internal - TANDEM delimiter */\n  char *e;              /* pointer to internal - DOS extension delimiter */\n  char *z;              /* pointer to internal - end of substring */\n  int len;              /* length of substring to copy to external name */\n  int allow_dollar;     /* $ symbol allowed as next character */\n\n  if ((x = malloc(strlen(n) + 4)) == NULL)  /* + 4 for safety */\n    return NULL;\n\n  *x = '\\0';\n\n  /* Junk pathname as requested */\n#ifdef UNZIP\n  if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)\n    ++t;\n  else\n    t = n;\n#endif /* UNZIP */\n#ifdef ZIP\n  if (!pathput)\n    t = last(n, INTERNAL_DELIMITER);\n  else\n    t = n;\n#endif /* ZIP */\n\n  allow_dollar = TRUE;\n\n  while (*t != '\\0') {  /* File part could be sys, vol, subvol or file */\n    if (*t == INTERNAL_DELIMITER) {    /* System, Volume or Subvol Name */\n      t++;\n      if (*t == INTERNAL_DELIMITER) {  /* System */\n        strcat(x, TANDEM_NODE_STR);\n        t++;\n      }\n      else {\n        strcat(x, TANDEM_DELIMITER_STR);\n        allow_dollar = FALSE;\n      }\n    }\n    /* Work out where end of current external string is */\n    y = x + strlen(x);\n\n    /* Work out substring to copy and externalise */\n    p = strchr(t, INTERNAL_DELIMITER);\n    e = strchr(t, DOS_EXTENSION);\n    if (p != NULL) {\n      if (e > p)\n        e = NULL;\n    }\n\n    z = e;\n    if (z == NULL)\n      z = p;\n    if (z == NULL)\n      z = t + strlen(t);\n\n    /* can't have Tandem name longer than 8 characters */\n    max = y + MAXFILEPARTLEN;\n\n    /* Allow $ symbol as first character in some cases */\n    if (*t == '$') {\n      if (allow_dollar)\n        *y++ = *t++;\n      else;\n        *t++;\n    }\n\n    /* Make sure first real character is alpha */\n    if (! isalpha(*t) )\n      *y++ = 'A';\n\n    /* Characters left to process */\n    len = z - t;\n\n    while ( len > 0 ) {\n      if ( isalnum(*t) ) {\n        *y++ = toupper(*t++);\n        if (y >= max)\n          break;\n      }\n      else\n        t++;\n      len--;\n    }\n    *y = '\\0';\n    t = p;\n\n    if (p == NULL) {\n      /* Last part of filename, store pseudo extension if available */\n      if (e != NULL) {\n        strcat(x, TANDEM_EXTENSION_STR);\n        y = x + strlen(x);\n\n        /* no restriction on extension length as its virtual */\n        z = e + 1;\n        while ( *z != '\\0' ) {\n          *y++ = toupper(*z++);\n        }\n        *y = '\\0';\n      }\n      break;\n    }\n  }\n\n  return x;\n}\n\nvoid zexit(status)\n  int status;\n{\n  /* Exit(>0) creates saveabend files */\n  terminate_program (0,0,(short)status,,,);\n}\n\n/************************/\n/*  Function zputc()    */\n/************************/\n\n#ifdef putc\n#  undef putc\n#endif\n\nint zputc(ch, fptr)\n  int ch;\n  FILE *fptr;\n{\n  int err;\n  err = putc(ch,fptr);\n  fflush(fptr);\n  return err;\n}\n#define putc zputc\n\n#ifdef LICENSED\n_tal _priv short FILE_CHANGELABEL_ (\n short,          /* IN */\n short,          /* IN */\n const short _far *    /* IN */\n );\n\n_c _callable int changelabel OF((short, const short *, const short *));\n\n_c _callable int changelabel(fnum, modtime, actime)\n  short fnum;\n  const short *modtime;\n  const short *actime;\n{\n  int err;\n\n  err = FILE_CHANGELABEL_(fnum, 16, modtime);\n  if (!err)\n    err = FILE_CHANGELABEL_(fnum, 17, actime);\n  return err;\n}\n\nint islicensed(void)\n{\n  #define plist_items 1\n  #define plist_size 10\n\n  short myphandle[ZSYS_VAL_PHANDLE_WLEN];\n  short licensetag[plist_items] = {37};\n  short licensed[plist_size];\n  short maxlen = plist_size;\n  short items = plist_items;\n  short resultlen[1], err;\n\n  err = PROCESSHANDLE_NULLIT_(myphandle);\n\n  if (!err)\n    err = PROCESS_GETINFO_(myphandle);\n\n  if (!err)\n    err = PROCESS_GETINFOLIST_(/*cpu*/,\n                               /*pin*/,\n                               /*nodename*/,\n                               /*nodenamelen*/,\n                               myphandle,\n                               licensetag,\n                               items,\n                               licensed,\n                               maxlen,\n                               resultlen\n                              );\n\n  if (err != 0)\n    return 0;\n  else\n    return licensed[0];\n}\n#endif /* LICENSED */\n\nint utime(file, time)\n  const char *file;\n  const ztimbuf *time;\n{\n#ifdef LICENSED\n  int result, err;\n  union timestamp_ov {\n    long long fulltime;\n    short wordtime[4];\n  };\n  union timestamp_ov lasttime, opentime;\n  struct tm *modt, *opent;\n  short datetime[8], errormask[1];\n  short len, fnum, access, exclus, options;\n  char fname[FILENAME_MAX + 1];\n  short extension;\n  char ext[EXTENSION_MAX + 1];\n\n  if (islicensed() ) {\n    /* Attempt to update file label */\n    modt = gmtime( &time->modtime );\n\n    datetime[0] = modt->tm_year + 1900;\n    datetime[1] = modt->tm_mon + 1;\n    datetime[2] = modt->tm_mday;\n    datetime[3] = modt->tm_hour;\n    datetime[4] = modt->tm_min;\n    datetime[5] = modt->tm_sec;\n    datetime[6] = datetime[7] = 0;\n    errormask[0] = 0;\n    lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);\n\n    opent = gmtime( &time->actime );\n\n    datetime[0] = opent->tm_year + 1900;\n    datetime[1] = opent->tm_mon + 1;\n    datetime[2] = opent->tm_mday;\n    datetime[3] = opent->tm_hour;\n    datetime[4] = opent->tm_min;\n    datetime[5] = opent->tm_sec;\n    datetime[6] = datetime[7] = 0;\n    errormask[0] = 0;\n    opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);\n\n    /* Remove any (pseudo) file extension */\n    extension = parsename (file,fname,ext);\n    len = strlen(fname);\n\n    access = NSK_WRONLY;\n    exclus = NSK_SHARED;\n    options = NSK_NOUPDATEOPENTIME;\n\n    extension = parsename (file,fname,ext);\n    len = strlen(fname);\n\n    err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n    result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);\n    err = FILE_CLOSE_(fnum);\n    return result;\n  }\n  return -1;\n#else  /* !LICENSED */\n  return 0;             /* \"no error\", to suppress annoying failure messages */\n#endif  /* ?LICENSED */\n}\n\n/* TANDEM version of chmod() function */\n\nint chmod(file, unix_sec)\n  const char *file;\n  mode_t unix_sec;\n{\n  FILE *stream;\n  struct nsk_sec_type {\n    unsigned progid : 1;\n    unsigned clear  : 1;\n    unsigned null   : 2;\n    unsigned read   : 3;\n    unsigned write  : 3;\n    unsigned execute: 3;\n    unsigned purge  : 3;\n  };\n  union nsk_sec_ov {\n    struct nsk_sec_type bit_ov;\n    short int_ov;\n  };\n  union nsk_sec_ov nsk_sec;\n  short fnum, err, nsk_sec_int;\n  short len, access, exclus, extension, options;\n  char fname[FILENAME_MAX + 1];\n  char ext[EXTENSION_MAX + 1];\n\n  nsk_sec.bit_ov.progid = 0;\n  nsk_sec.bit_ov.clear  = 0;\n  nsk_sec.bit_ov.null   = 0;\n\n  /*  4=\"N\", 5=\"C\", 6=\"U\", 7=\"-\"   */\n\n  if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;\n  else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;\n  else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;\n  else nsk_sec.bit_ov.read = 7;\n\n  if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;\n  else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;\n  else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;\n  else nsk_sec.bit_ov.write = 7;\n\n  if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;\n  else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;\n  else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;\n  else nsk_sec.bit_ov.execute = 7;\n\n  nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;\n\n  nsk_sec_int = nsk_sec.int_ov;\n\n  access = NSK_RDONLY;\n  exclus = NSK_SHARED;\n  options = NSK_NOUPDATEOPENTIME;\n\n  extension = parsename (file,fname,ext);\n  len = strlen(fname);\n\n  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n  err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE);\n  err = FILE_CLOSE_(fnum);\n\n  return (err != 0 ? -1 : 0);\n}\n\n/* TANDEM version of chown() function */\n\nint chown(file, uid, gid)\n  const char *file;\n  uid_t uid;\n  gid_t gid;\n{\n  FILE *stream;\n  struct nsk_own_type {\n    unsigned group  : 8;\n    unsigned user   : 8;\n  };\n  union nsk_own_ov {\n    struct nsk_own_type bit_ov;\n    short int_ov;\n  };\n  union nsk_own_ov nsk_own;\n  short fnum, err, nsk_own_int;\n  short len, access, exclus, extension, options;\n  char fname[FILENAME_MAX + 1];\n  char ext[EXTENSION_MAX + 1];\n\n  nsk_own.bit_ov.group = gid;\n  nsk_own.bit_ov.user  = uid;\n\n  nsk_own_int = nsk_own.int_ov;\n\n  access = NSK_RDONLY;\n  exclus = NSK_SHARED;\n  options = NSK_NOUPDATEOPENTIME;\n\n  extension = parsename (file,fname,ext);\n  len = strlen(fname);\n\n  err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);\n  err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE);\n  err = FILE_CLOSE_(fnum);\n  return (err != 0 ? -1 : 0);\n}\n\n/* TANDEM version of getch() - non-echo character reading */\nint zgetch(void)\n{\n  char ch;\n  short f, err, count, fnum, rlen;\n\n  rlen = 1;\n  f = (short)fileno(stdin);\n  fnum = fdtogfn (f);\n  #define ECHO_MODE 20\n  err = (SETMODE(fnum, ECHO_MODE, 0) != CCE);\n  err = (READX(fnum, &ch, rlen, (short *) &count) != CCE);\n  err = (SETMODE(fnum, ECHO_MODE, 1) != CCE);\n\n  if (err)\n    if (err != 1)\n      return EOF;\n    else\n      ch = 'q';\n  else\n    if (count == 0)\n      ch = '\\r';\n\n  return (int)ch;\n}\n\nshort parsename(srce, fname, ext)\n  const char *srce;\n  char *fname;\n  char *ext;\n{\n  /* As a way of supporting DOS extensions from Tandem we look for a space\n     separated extension string after the Guardian filename\n     e.g. ZIP ZIPFILE \"$DATA4.TESTING.INVOICE TXT\"\n  */\n\n  char *fstart;\n  char *fptr;\n  short extension = 0;\n\n  *fname = *ext = '\\0';  /* set to null string */\n\n  fstart = (char *) srce;\n\n  if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {\n    extension = 1;\n\n    fptr++;\n    strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));\n\n    fptr = strchr(fstart, TANDEM_EXTENSION);  /* End of filename */\n    strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));\n  }\n  else {\n    /* just copy string */\n    strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));\n  }\n\n  return extension;\n}\n\nstatic time_t gmt_to_time_t (gmt)\n  long long *gmt;\n{\n  #define GMT_TO_LCT 0\n  #define GMT_TO_LST 1\n\n  struct tm temp_tm;\n  short  date_time[8];\n  long   julian_dayno;\n  long long lct, lst, itime;\n  short  err[1], type;\n\n  type = GMT_TO_LCT;\n  lct = CONVERTTIMESTAMP(*gmt, type,, err);\n\n  if (!err[0]) {\n    type = GMT_TO_LST;\n    lst = CONVERTTIMESTAMP(*gmt, type,, err);\n  }\n\n  itime = (err[0] ? *gmt : lct);\n  /* If we have no DST in force then make sure we give it a value,\n     else mktime screws up if we set the isdst flag to -1 */\n  temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1));\n\n  julian_dayno = INTERPRETTIMESTAMP(itime, date_time);\n\n  temp_tm.tm_sec   = date_time[5];\n  temp_tm.tm_min   = date_time[4];\n  temp_tm.tm_hour  = date_time[3];\n  temp_tm.tm_mday  = date_time[2];\n  temp_tm.tm_mon   = date_time[1] - 1;     /* C's so sad */\n  temp_tm.tm_year  = date_time[0] - 1900;  /* it's almost funny */\n\n  return (mktime(&temp_tm));\n}\n\n/* TANDEM version of stat() function */\nint stat(n, s)\n  const char *n;\n  struct stat *s;\n{\n  #define ilist_items 26\n  #define klist_items 4\n  #define slist_items 3\n  #define ulist_items 1\n  #define flist_size 100\n\n  short err, i, extension;\n  char fname[FILENAME_MAX + 1];\n  short fnamelen;\n  char ext[EXTENSION_MAX + 1];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44,\n                            50, 51, 52, 61, 63, 66, 67, 70, 72, 73,\n                            74, 75, 76, 77, 78, 79                 };\n  short ilen[ilist_items] ={ 4,  4,  4,  2,  1,  2,  1,  1,  1,  1,\n                             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\n                             1,  1,  1,  1,  1,  1                 };\n  short ioff[ilist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short klist[klist_items]={45, 46, 68, 69                         };\n  short klen[klist_items] ={ 1,  1,  1,  1                         };\n  short koff[klist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short slist[slist_items]={43, 80, 90                             };\n  short slen[slist_items] ={ 1,  1,  1                             };\n  short soff[slist_items];\n\n                         /* #0  #1  #2  #3  #4  #5  #6  #7  #8  #9 */\n  short ulist[ulist_items]={65                                     };\n  short ulen[ulist_items] ={ 1                                     };\n  short uoff[ulist_items];\n\n  short flist[flist_size];\n  short extra[2];\n  short *rlen=&extra[0];\n  short *err_item=&extra[1];\n  unsigned short *fowner;\n  unsigned short *fprogid;\n  char *fsec;\n\n  nsk_stat_ov *nsk_ov;\n  nsk_file_attrs *nsk_attr;\n\n  short end, count, kind, level, options, searchid;\n  short info[5];\n\n  /* Initialise stat structure */\n  s->st_dev = _S_GUARDIANOBJECT;\n  s->st_ino = 0;\n  s->st_nlink = 0;\n  s->st_rdev = 0;\n  s->st_uid = s->st_gid = 0;\n  s->st_size = 0;\n  s->st_atime = s->st_ctime = s->st_mtime = 0;\n  s->st_reserved[0] = 0;\n  s->st_reserved[1] = 0;\n  s->st_reserved[2] = 0;\n  nsk_ov = (nsk_stat_ov *)&s->st_reserved[0];\n  nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region;\n\n  /* Check to see if name contains a (pseudo) file extension */\n  extension = parsename (n,fname,ext);\n\n  fnamelen = strlen(fname);\n\n  options = 3; /* Allow Subvols and Templates */\n  err = FILENAME_SCAN_( fname,\n                        fnamelen,\n                        &count,\n                        &kind,\n                        &level,\n                        options\n                      );\n\n  /* allow kind == 2 (DEFINE names) */\n  if (err != 0) return -1;\n\n  if (kind == 1 || (kind == 0 && level < 2)) {\n    /* Pattern, Subvol Name or One part Filename - lets see if it exists */\n    err = FILENAME_FINDSTART_ ( &searchid,\n                                fname,\n                                fnamelen,\n                                ,\n                                DISK_DEVICE\n                              );\n\n    if (err != 0) {\n      end = FILENAME_FINDFINISH_ ( searchid );\n      return -1;\n    }\n\n    err = FILENAME_FINDNEXT_ ( searchid,\n                               fname,\n                               FILENAME_MAX,\n                               &fnamelen,\n                               info\n                              );\n    end = FILENAME_FINDFINISH_ ( searchid );\n\n    if (err != 0)\n      return -1;  /* Non existing template, subvol or file */\n\n    if (kind == 1 || info[2] == -1) {\n      s->st_mode = S_IFDIR;    /* Its an existing template or directory */\n      return 0;\n    }\n\n    /* Must be a real file so drop to code below to get info on it */\n  }\n\n  err = FILE_GETINFOLISTBYNAME_( fname,\n                                 fnamelen,\n                                 ilist,\n                                 ilist_items,\n                                 flist,\n                                 flist_size,\n                                 rlen,\n                                 err_item\n                               );\n  if (err != 0) return -1;\n\n  ioff[0] = 0;\n\n  /*  Build up table of offets into result list */\n  for (i=1; i < ilist_items; i++)\n    ioff[i] = ioff[i-1] + ilen[i-1];\n\n  /* Set up main stat fields */\n\n  /* Setup timestamps */\n  s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]);\n  s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]);\n  nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]);\n\n  s->st_size = *(off_t *)&flist[ioff[3]];\n\n  fowner = (unsigned short *)&flist[ioff[4]];\n  s->st_uid = *fowner & 0x00ff;\n  s->st_gid = *fowner >> 8;\n\n  /* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */\n  fsec = (char *)&flist[ioff[5]];\n  fprogid = (unsigned short *)&flist[ioff[6]];\n\n  s->st_mode = S_IFREG |  /* Regular File */\n  /*  Parse Read Flag */\n               ((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |\n               ((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |\n               ((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |\n  /*  Parse Write Flag */\n               ((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |\n               ((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |\n               ((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |\n  /*  Parse Execute Flag */\n               ((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |\n               ((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |\n               ((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |\n  /*  Parse Progid */\n               (*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;\n\n  /* Set up NSK additional stat fields */\n  nsk_attr->progid   = (unsigned) flist[ioff[6]];\n  nsk_attr->filetype = (unsigned) flist[ioff[7]];\n  nsk_attr->filecode = (unsigned) flist[ioff[8]];\n  nsk_attr->block    = (unsigned short) flist[ioff[9]];\n  nsk_attr->priext   = (unsigned short) flist[ioff[10]];\n  nsk_attr->secext   = (unsigned short) flist[ioff[11]];\n  nsk_attr->maxext   = (unsigned short) flist[ioff[12]];\n  nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]];\n  nsk_attr->licensed     = (unsigned) flist[ioff[14]];\n  nsk_attr->flags.audited      = (unsigned) flist[ioff[15]];\n  nsk_attr->flags.acompress    = (unsigned) flist[ioff[16]];\n  nsk_attr->flags.refresheof   = (unsigned) flist[ioff[17]];\n  nsk_attr->flags.buffered     = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0);\n  nsk_attr->flags.verified     = (unsigned) flist[ioff[19]];\n  nsk_attr->flags.serial       = (unsigned) flist[ioff[20]];\n  nsk_attr->flags.crashopen    = (unsigned) flist[ioff[22]];\n  nsk_attr->flags.rollforward  = (unsigned) flist[ioff[23]];\n  nsk_attr->flags.broken       = (unsigned) flist[ioff[24]];\n  nsk_attr->flags.corrupt      = (unsigned) flist[ioff[25]];\n  nsk_attr->fileopen     = (unsigned) flist[ioff[21]];\n\n\n  if (nsk_attr->filetype == NSK_UNSTRUCTURED) {\n    /* extra info for Unstructured files */\n    err = FILE_GETINFOLISTBYNAME_( fname,\n                                   fnamelen,\n                                   ulist,\n                                   ulist_items,\n                                   flist,\n                                   flist_size,\n                                   rlen,\n                                   err_item\n                                 );\n    if (err != 0) return -1;\n\n    uoff[0] = 0;\n\n    /*  Build up table of offets into result list */\n    for (i=1; i < ulist_items; i++)\n      uoff[i] = uoff[i-1] + ulen[i-1];\n  }\n  else {\n    /* extra info for Structured files */\n    err = FILE_GETINFOLISTBYNAME_( fname,\n                                   fnamelen,\n                                   slist,\n                                   slist_items,\n                                   flist,\n                                   flist_size,\n                                   rlen,\n                                   err_item\n                                 );\n    if (err != 0) return -1;\n\n    soff[0] = 0;\n\n    /*  Build up table of offets into result list */\n    for (i=1; i < slist_items; i++)\n      soff[i] = soff[i-1] + slen[i-1];\n\n    nsk_attr->reclen   = (unsigned) flist[soff[0]];\n    nsk_attr->flags.secpart   = (unsigned) flist[soff[1]];\n    nsk_attr->flags.primpart  = (unsigned)\n     ( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 );\n\n    if (nsk_attr->filetype == NSK_KEYSEQUENCED) {\n      /* extra info for Key Sequenced files */\n      err = FILE_GETINFOLISTBYNAME_( fname,\n                                     fnamelen,\n                                     klist,\n                                     klist_items,\n                                     flist,\n                                     flist_size,\n                                     rlen,\n                                     err_item\n                                   );\n      if (err != 0) return -1;\n\n      koff[0] = 0;\n\n      /*  Build up table of offets into result list */\n      for (i=1; i < klist_items; i++)\n        koff[i] = koff[i-1] + klen[i-1];\n\n      nsk_attr->keyoff   = (unsigned) flist[koff[0]];\n      nsk_attr->keylen   = (unsigned) flist[koff[1]];\n      nsk_attr->flags.dcompress = (unsigned) flist[koff[2]];\n      nsk_attr->flags.icompress = (unsigned) flist[koff[3]];\n    }\n  }\n\n  return 0;\n}\n\n#ifndef SFX\n/* TANDEM Directory processing */\n\nDIR *opendir(const char *dirname)\n{\n   short i, resolve;\n   char sname[FILENAME_MAX + 1];\n   short snamelen;\n   char fname[FILENAME_MAX + 1];\n   short fnamelen;\n   char *p;\n   short searchid, err, end;\n   struct dirent *entry;\n   DIR *dirp;\n   char ext[EXTENSION_MAX + 1];\n   short extension;\n\n   extension = parsename(dirname, sname, ext);\n   snamelen = strlen(sname);\n\n   /*  First we work out how detailed the template is...\n    *  e.g. If the template is DAVES*.* we want the search result\n    *       in the same format\n    */\n\n   p = sname;\n   i = 0;\n   while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){\n     i++;\n     p++;\n   };\n   resolve = 2 - i;\n\n   /*  Attempt to start a filename template */\n   err = FILENAME_FINDSTART_ ( &searchid,\n                               sname,\n                               snamelen,\n                               resolve,\n                               DISK_DEVICE\n                             );\n   if (err != 0) {\n     end = FILENAME_FINDFINISH_(searchid);\n     return NULL;\n   }\n\n   /* Create DIR structure */\n   if ((dirp = malloc(sizeof(DIR))) == NULL ) {\n     end = FILENAME_FINDFINISH_(searchid);\n     return NULL;\n   }\n   dirp->D_list = dirp->D_curpos = NULL;\n   strcpy(dirp->D_path, dirname);\n\n   while ((err = FILENAME_FINDNEXT_(searchid,\n                                    fname,\n                                    FILENAME_MAX,\n                                    &fnamelen\n                                   )\n           ) == 0 ){\n     /*  Create space for entry */\n     if ((entry = malloc (sizeof(struct dirent))) == NULL) {\n       end = FILENAME_FINDFINISH_(searchid);\n       return NULL;\n     }\n\n     /*  Link to last entry */\n     if (dirp->D_curpos == NULL)\n       dirp->D_list = dirp->D_curpos = entry;  /* First name */\n     else {\n       dirp->D_curpos->d_next = entry;         /* Link */\n       dirp->D_curpos = entry;\n     };\n     /* Add directory entry */\n     *dirp->D_curpos->d_name = '\\0';\n     strncat(dirp->D_curpos->d_name,fname,fnamelen);\n     if (extension) {\n       strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);\n       strcat(dirp->D_curpos->d_name,ext);\n     };\n     dirp->D_curpos->d_next = NULL;\n   };\n\n   end = FILENAME_FINDFINISH_(searchid);\n\n   if (err == 1) {  /*  Should return EOF at end of search */\n     dirp->D_curpos = dirp->D_list;        /* Set current pos to start */\n     return dirp;\n   }\n   else\n     return NULL;\n}\n\nstruct dirent *readdir(DIR *dirp)\n{\n   struct dirent *cur;\n\n   cur = dirp->D_curpos;\n   dirp->D_curpos = dirp->D_curpos->d_next;\n   return cur;\n}\n\nvoid rewinddir(DIR *dirp)\n{\n   dirp->D_curpos = dirp->D_list;\n}\n\nint closedir(DIR *dirp)\n{\n   struct dirent *node;\n\n   while (dirp->D_list != NULL) {\n      node = dirp->D_list;\n      dirp->D_list = dirp->D_list->d_next;\n      free( node );\n   }\n   free( dirp );\n   return 0;\n}\n\n#endif /* !SFX */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/tandem.h",
    "content": "/*\n  Copyright (c) 1990-2006 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __tandem_h   /* prevent multiple inclusions */\n#define __tandem_h\n\n#ifndef TANDEM\n#  define TANDEM     /* better than __TANDEM */\n#endif\n\n/* LICENSED define now supplied by compile time option (MAKE) */\n\n#define NO_UNISTD_H\n#define NO_RMDIR\n#define NO_MKTEMP\n\n/* TANDEM supplies proper UTC vs. local time conversion, so enable Info-ZIP's\n   UT e.f. support unless explicitly suppressed by a compilation option. */\n#if (!defined(USE_EF_UT_TIME) && !defined(NO_EF_UT_TIME))\n#  define USE_EF_UT_TIME\n#endif\n#if (defined(NO_EF_UT_TIME) && defined(USE_EF_UT_TIME))\n#  undef USE_EF_UT_TIME\n#endif\n\n/* Include file for TANDEM */\n\n#ifndef NULL\n#  define NULL 0\n#endif\n\n#include <time.h>               /* the usual non-BSD time functions */\n#include <stdio.h>\n#include <sysstat.h>\n#include <unistd.h>\n#include <errno.h>\n#include <ctype.h>\n\n#define PASSWD_FROM_STDIN\n                  /* Kludge until we know how to open a non-echo tty channel */\n\n#define NSK_UNSTRUCTURED   0\n#define NSK_RELATIVE       1\n#define NSK_ENTRYSEQUENCED 2\n#define NSK_KEYSEQUENCED   3\n#define NSK_OBJECTFILECODE 100\n#define NSK_EDITFILECODE   101\n#define NSK_ZIPFILECODE    1001\n#define TANDEM_BLOCKSIZE   4096\n#define MAX_NORMAL_READ    4096\n#define MAX_EDIT_READ      255\n#define MAX_LARGE_READ        57344\n#define MAX_LARGE_READ_EXPAND 30720\n\n#define MAXFILEPARTLEN     8\n#define MAXPATHLEN         128\n#define EXTENSION_MAX      3\n/* FILENAME_MAX is defined in stdio.h */\n\n#define EXIT zexit      /*  To stop creation of Abend files */\n#define RETURN zexit    /*  To stop creation of Abend files */\n#define putc zputc      /*  To allow us to auto flush  */\n\n\n#define FOPR \"rb\"\n#define FOPM \"r+\"\n#define FOPW \"wb\"\n#define FOPWT \"w\"\n\n#define NAMELEN FILENAME_MAX+1+EXTENSION_MAX   /* allow for space extension */\n\nstruct dirent {\n   struct dirent *d_next;\n   char   d_name[NAMELEN+1];\n};\n\ntypedef struct _DIR {\n   struct  dirent *D_list;\n   struct  dirent *D_curpos;\n   char            D_path[NAMELEN+1];\n} DIR;\n\nDIR *          opendir(const char *dirname);\nstruct dirent *readdir(DIR *dirp);\nvoid           rewinddir(DIR *dirp);\nint            closedir(DIR *dirp);\nchar *         readd(DIR *dirp);\n\n#define DISK_DEVICE         3\n\n/* SETMODE Literals */\n#define SET_FILE_SECURITY   1\n#define SET_FILE_OWNER      2\n#define SET_FILE_BUFFERED   90\n#define SET_FILE_MAXEXTENTS 92\n#define SET_FILE_BUFFERSIZE 93\n#define SET_LARGE_TRANSFERS 141\n\n/* FILE_OPEN_ Literals */\n#define NSK_RDWR             0\n#define NSK_RDONLY           1\n#define NSK_WRONLY           2\n#define NSK_APPEND           3\n#define NSK_SHARED           0\n#define NSK_EXCLUSIVE        1\n#define NSK_PROCESSEXCLUSIVE 2\n#define NSK_PROTECTED        3\n#define NSK_UNSTRUCTUREDACCESS 0x8000\n#define NSK_NOUPDATEOPENTIME   0x2000\n\n#define NSK_NO_DELIMITER        0x0001\n#define NSK_USE_FF_DELIMITER    0x0002\n#define NSK_SPACE_FILL          0x0004\n#define NSK_TRIM_TRAILING_SPACE 0x0008\n#define NSK_LARGE_READ_EXPAND   0x0100     /* use smaller value for Expand */\n\n#define DOS_EXTENSION      '.'\n#define TANDEM_EXTENSION   ' '\n#define TANDEM_DELIMITER   '.'\n#define TANDEM_NODE        '\\\\'\n#define INTERNAL_DELIMITER '/'\n#define INTERNAL_NODE      '//'\n#define TANDEM_WILD_1      '*'\n#define TANDEM_WILD_2      '?'\n\n#define DOS_EXTENSION_STR      \".\"\n#define TANDEM_EXTENSION_STR   \" \"\n#define TANDEM_DELIMITER_STR   \".\"\n#define TANDEM_NODE_STR        \"\\\\\"\n#define INTERNAL_DELIMITER_STR \"/\"\n#define INTERNAL_NODE_STR      \"//\"\n\n/* Use 'spare' area at end of stat structure to hold additional Tandem/NSK\n   file details. Initially used to hold Creation time, now also holds most\n   Enscribe details */\n\nstruct nsk_stat_reserved\n{\n  int64_t spare[3];\n};\n\n#pragma FIELDALIGN SHARED8 nsk_owner\nstruct nsk_owner\n{\n  unsigned group   : 8;\n  unsigned user    : 8;\n};\n\n#pragma FIELDALIGN SHARED8 nsk_file_flags\nstruct nsk_file_flags\n{\n  unsigned buffered    : 1;\n  unsigned audited     : 1;\n  unsigned acompress   : 1;\n  unsigned icompress   : 1;\n  unsigned dcompress   : 1;\n  unsigned oddunstr    : 1;\n  unsigned verified    : 1;\n  unsigned serial      : 1;\n  unsigned refresheof  : 1;\n  unsigned broken      : 1;\n  unsigned corrupt     : 1;\n  unsigned primpart    : 1;\n  unsigned secpart     : 1;\n  unsigned crashopen   : 1;\n  unsigned rollforward : 1;\n  unsigned clearonpurge: 1;\n};\n\n#pragma FIELDALIGN SHARED8 nsk_file_attrs_def\nstruct nsk_file_attrs_def\n{\n  unsigned short filecode;  /* 16 */\n  unsigned short block;     /* 16 */  /* Allow of block > 4096 one day ! */\n  struct nsk_file_flags flags;     /* 16 */\n  struct nsk_owner owner;   /* 16 */\n  unsigned short priext;    /* 16 */\n  unsigned short secext;    /* 16 */\n  unsigned maxext    : 10;\n  unsigned read      : 3;\n  unsigned write     : 3;\n  unsigned execute   : 3;\n  unsigned delete    : 3;\n  unsigned licensed  : 1;\n  unsigned progid    : 1;\n  unsigned keylen    : 8;\n  unsigned           : 5;\n  unsigned keyoff    : 11;\n  unsigned           : 1;\n  unsigned filetype  : 2;\n  unsigned fileopen  : 1;\n  unsigned reclen    : 12;\n};\ntypedef struct nsk_file_attrs_def nsk_file_attrs;\n\n#pragma FIELDALIGN SHARED8 nsk_stat_overlay\nstruct nsk_stat_overlay\n{\n  time_t creation_time;       /* 32 bits */\n  nsk_file_attrs nsk_ef_region;\n /*  char   nsk_ef_region[20]; *//* EF region */\n};\n\ntypedef union\n{\n  struct nsk_stat_reserved reserved;\n  struct nsk_stat_overlay  ov;\n} nsk_stat_ov;\n\n/* Prototype function declarations */\n\nvoid zexit (int);\n\nint zputc(\n  int,\n  FILE *\n);\n\nint zgetch (void);\n\nshort parsename(\n  const char *,\n  char *,\n  char *\n);\n\nint islicensed (void);\n\n/* End of prototype function declarations */\n\n#endif /* !__tandem_h */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/tannsk.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  Header declaration(s) which are forced to go after earlier includes\n */\n\n#ifndef __tannsk_h   /* prevent multiple inclusions */\n#define __tannsk_h\n\n/* ztimbuf is declared in zip\\tailor.h after include of tandem.h */\nint utime (const char *, const ztimbuf *);\n\n#endif /* !__tannsk_h */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/tanzip.c",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n * routines only used by TANDEM ZIP\n */\n\n#include \"zip.h\"\n#include \"crypt.h\"\n#include <tal.h>\n#include \"$system.zsysdefs.zsysc\" nolist\n#include <cextdecs> nolist\n#include \"tannsk.h\"\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#if 0\n    char buf[40];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n     \"C \", \"T9255D44 - (16OCT98)\",\n#endif\n\n     \"NonStop \", \"(Tandem/NSK)\",\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n\n\n/************************/\n/*  Function nskopen()  */\n/************************/\n\n#ifdef fopen\n#  undef fopen\n#endif\n\nFILE *nskopen(fname, opt)\nconst char *fname;\nconst char *opt;\n{\n  int fdesc;\n  short fnum, err, len;\n  int priext, secext;\n  short maxext, filecode, blocksize;\n\n  #define alist_items 1\n  #define vlist_bytes 2\n  short alist[alist_items]={42};\n  unsigned short vlist[alist_items];\n  short extra, *err_item=&extra;\n\n  char nsk_work[FILENAME_MAX + 1], *nsk_fname=&nsk_work[0];\n\n  /* See if we want to create a new file */\n  if ((strcmp(opt,FOPW) == 0) || (strcmp(opt,FOPWT) == 0)) {\n    blocksize = TANDEM_BLOCKSIZE;\n    priext = 100;\n    secext = 500;\n    maxext = 978;\n    filecode = NSK_ZIPFILECODE;\n\n    if ((fdesc = creat(fname,,priext,secext)) != -1){\n      fnum = fdtogfn ((short)fdesc);\n      err = (SETMODE (fnum, SET_FILE_BUFFERSIZE, blocksize) != CCE);\n      err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 0) != CCE);\n      err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 1) != CCE);\n      err = (SETMODE (fnum, SET_FILE_MAXEXTENTS, maxext) != CCE);\n      err = close(fdesc);\n\n      vlist[0] = filecode;\n\n      /* Note that FILE_ALTERLIST_ expects uppercase names */\n      /* Need to call strlen and upshift                   */\n      len = strlen(fname);\n      err = STRING_UPSHIFT_((char *)fname,\n                            len,\n                            nsk_fname,\n                            len);\n\n      err = FILE_ALTERLIST_(nsk_fname,\n                            len,\n                            alist,\n                            alist_items,\n                            vlist,\n                            vlist_bytes,\n                            ,\n                            err_item);\n    };\n  };\n\n  return fopen(fname,opt);\n}\n#define fopen nskopen\n\n\n  int Bflag = 0;            /* Special formatting options for Tandem        */\n                            /* Bit 0 = Add delimiter (0 = Yes, 1 = No)      */\n                            /* Bit 1 = Delimiter Type (0 = CR/LF, 1 = LF)   */\n                            /* Bit 2 = Space Fill records (0 = No, 1 = Yes) */\n                            /* Bit 3 = Trim trailing space(0 = No, 1 = Yes) */\n                            /* Thus, default is to add CR/LF, no padding    */\n                            /* Bit 8 = Use 'safe' large read size (Expand)  */\n  char nsk_delim[2] = {'\\r', '\\n'}; /* CR/LF */\n  int nsk_delim_len = 2;\n  int nsk_space_fill = 0;   /* 0 = No, 1 = Yes          */\n  int nsk_trim_space = 0;   /* 0 = No, 1 = Yes          */\n  unsigned short nsk_large_read = MAX_LARGE_READ;\n\n  /* Following holds details of file currently used by zopen & zread */\n  struct stat znsk_stat;\n  nsk_stat_ov *znsk_ov = (nsk_stat_ov *)&znsk_stat.st_reserved[0];\n  nsk_file_attrs *znsk_attr = (nsk_file_attrs *)\n    ( (char *)(&znsk_stat.st_reserved[0]) +\n      offsetof (struct nsk_stat_overlay, nsk_ef_region) );\n\n  /* Following items used by zread to avoid overwriting window */\n  char zreadbuf[MAX_LARGE_READ];       /* Buffer as large as biggest read */\n  char *zreadptr = (char *) zreadbuf;  /* pointer to start of buffer      */\n  char *zread_ovptr = NULL;            /* pointer to left overs           */\n  long zread_ovlen = 0;                /* size of remaining left overs    */\n\n  int zopen (filename, opt)\n    const char *filename;\n    int opt;\n  {\n    /* Currently ignore opt.  Choose method of I/O based on NSK file type */\n    short err, len, fnum, access, exclus, bufferlen, options;\n    long recnum;\n    char fname[FILENAME_MAX + 1];\n    short extension;\n    char ext[EXTENSION_MAX + 1];\n\n    /* Remove any (pseudo) file extension */\n    extension = parsename (filename,fname,ext);\n    len = strlen(fname);\n\n    fnum = 0;\n    access = NSK_RDONLY;\n    exclus = NSK_SHARED;\n\n    err = stat(fname, &znsk_stat); /* Setup global struct, used by zread */\n\n    if (znsk_attr->filetype == NSK_UNSTRUCTURED)\n      if (znsk_attr->filecode == NSK_EDITFILECODE) {\n        /* Edit File */\n        fnum = -1; /* Ask OPENEDIT_ to open the file for us */\n        err = OPENEDIT_ ((char *)fname, len, &fnum, access, exclus);\n        if (!err) {\n          recnum = -1; /* Position to first line */\n          err = POSITIONEDIT (fnum, recnum);\n        }\n      }\n      else {\n        /* Unstructured File */\n        options = NSK_UNSTRUCTUREDACCESS;\n        err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,\n                         ,,options,,,);\n        if (!err)\n          /* Ask for large transfer mode */\n          err = (SETMODE (fnum, SET_LARGE_TRANSFERS, 1) != CCE);\n      }\n    else {\n      /* Structured File */\n      bufferlen = 4096;  /* request SBB */\n      err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,\n                       ,,,, bufferlen ,);\n      if (err == 4)\n        err = 0;  /* Allow saving of files that have missing altkeys */\n    }\n\n    return (err == 0 ? (int)fnum : -1);\n  }\n\n  unsigned zread (fnum, buf, len)\n    int fnum;\n    char *buf;\n    unsigned len;\n  {\n    short err, trail;\n    long total, movelen;\n    unsigned short countread;\n    unsigned readlen;  /* typed to match incoming arg */\n    char *bufptr, *readptr;\n\n    total = err = 0;\n    bufptr = buf;\n\n    /* We use a separate buffer to read in data as it can be larger than\n       WSIZE, and hence would overwrite memory */\n\n    /* We always attempt to give the user the exact requested size\n       Hence we make use of an overfow buffer for previously truncated data */\n\n    /* see if we have some left over characters from last time */\n    if (zread_ovlen) {\n       movelen = _min(len,zread_ovlen);\n       memcpy(bufptr, zread_ovptr, movelen);\n       bufptr += movelen;\n       total += movelen;\n       zread_ovptr += movelen;\n       zread_ovlen -= movelen;\n    }\n\n    while (!err && (total < len)) {\n      readptr = zreadptr;\n\n      if (znsk_attr->filetype == NSK_UNSTRUCTURED)\n        if (znsk_attr->filecode == NSK_EDITFILECODE){\n          /* Edit File */\n          trail = 1;\n          readlen = MAX_EDIT_READ; /* guarantee it fits in buffer */\n\n          /* get line and preserve any trailing space characters */\n          err = READEDIT (fnum,, zreadptr, (short) readlen,\n                            (short *) &countread,,, trail);\n          /* if countread is ever negative then we will skip a line */\n\n          if (!err) {\n            readptr = zreadptr + countread;\n            /* Note it is possible for Edit files to hold trailing space */\n            if (nsk_trim_space)\n              while (*(readptr-1) == ' ') {\n                readptr--;\n                countread--;\n              }\n\n            if (nsk_delim_len) {\n              memcpy(readptr, nsk_delim, nsk_delim_len);\n              readptr += nsk_delim_len;\n              countread += nsk_delim_len;\n            }\n          }\n        }\n        else {\n          /* Unstructured File */\n\n          /* Using large transfer mode so we have to use 2K multiples\n             Use largest size possible and put remains in overflow    */\n\n          readlen = nsk_large_read; /* use largest read, overflow into buffer*/\n\n          err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE);\n          if (err && (errno == EINVAL)) {\n            /* Read too big so scale back to smaller value */\n            readlen = nsk_large_read = MAX_LARGE_READ_EXPAND;\n            err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE);\n          }\n          if (!err)\n            readptr = zreadptr + countread;\n        }\n      else {\n        /* Structured File */\n        readlen = znsk_attr->reclen;\n\n        err = (READX(fnum, zreadptr, readlen, (short *)&countread)!= CCE);\n\n        if (!err) {\n          readptr = zreadptr + countread;\n          if (nsk_space_fill)\n            while (countread < readlen) {\n              *readptr++ = ' ';\n              countread++;\n            }\n          else\n            if (nsk_trim_space)\n              while (*(readptr-1) == ' ') {\n                readptr--;\n                countread--;\n              }\n\n          if (nsk_delim_len) {\n            memcpy(readptr, nsk_delim, nsk_delim_len);\n            readptr += nsk_delim_len;\n            countread += nsk_delim_len;\n          }\n        }\n      }\n      if (!err) {\n         movelen = _min((len-total), countread);\n         memcpy(bufptr, zreadptr, movelen);\n         bufptr += movelen;\n         total += movelen;\n         if (movelen < countread) { /* still stuff in Read buffer */\n           zread_ovptr = zreadptr + movelen;   /* pointer to whats left */\n           zread_ovlen = countread - movelen;  /* how much is left      */\n         }\n      }\n    }\n\n    return ((unsigned)total);\n  }\n\n  int zclose (fnum)\n    int fnum;\n  {\n    short err;\n\n    if ((znsk_attr->filetype == NSK_UNSTRUCTURED)\n      && (znsk_attr->filecode == NSK_EDITFILECODE))\n      err = CLOSEEDIT_(fnum);\n    else\n      err = FILE_CLOSE_(fnum);\n\n    return (err != 0);\n  }\n\n/* modified to work with get_option which returns\n   a string with the number value without leading option */\nvoid nskformatopt(p)\nchar *p;\n{\n  /* set up formatting options for ZIP */\n\n  Bflag = 0; /* default option */\n\n  Bflag = strtoul(p, NULL, 10);\n\n  if (Bflag & NSK_SPACE_FILL)\n    nsk_space_fill = 1;\n  else\n    nsk_space_fill = 0;\n\n  if (Bflag & NSK_TRIM_TRAILING_SPACE)\n    nsk_trim_space = 1;\n  else\n    nsk_trim_space = 0;\n\n  if (Bflag & NSK_NO_DELIMITER)\n    nsk_delim_len = 0;\n  else {\n    if (Bflag & NSK_USE_FF_DELIMITER) {\n      nsk_delim[0] = '\\n';\n      nsk_delim_len = 1;\n    }\n    else {   /* CR/LF */\n      nsk_delim[0] = '\\r';\n      nsk_delim[1] = '\\n';\n      nsk_delim_len = 2;\n    }\n  }\n\n  if (Bflag & NSK_LARGE_READ_EXPAND)\n    nsk_large_read = MAX_LARGE_READ_EXPAND;\n  else\n    nsk_large_read = MAX_LARGE_READ;\n\n}\n\n\n  int deletedir(d)\n    char *d;                /* directory to delete */\n  /* Delete the directory *d if it is empty, do nothing otherwise.\n     Return the result of rmdir(), delete(), or system().\n     For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n   */\n  {\n      return rmdir(d);\n  }\n\n  local char *readd(d)\n    DIR *d;                 /* directory stream to read from */\n  /* Return a pointer to the next name in the directory stream d, or NULL if\n     no more entries or an error occurs. */\n  {\n    struct dirent *e;\n\n    e = readdir(d);\n    return e == NULL ? (char *) NULL : e->d_name;\n  }\n\n  int procname(n, caseflag)\n    char *n;                /* name to process */\n    int caseflag;           /* true to force case-sensitive match */\n  /* Process a name or sh expression to operate on (or exclude).  Return\n     an error code in the ZE_ class. */\n  {\n    char *a;              /* path and name for recursion */\n    DIR *d;               /* directory stream from opendir() */\n    char *e;              /* pointer to name from readd() */\n    int m;                /* matched flag */\n    char *p;              /* path for recursion */\n    struct stat s;        /* result of stat() */\n    struct zlist far *z;  /* steps through zfiles list */\n\n    if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n      return newname(n, 0, caseflag);\n    else if (stat(n, &s))\n    {\n      /* Not a file or directory--search for shell expression in zip file */\n      p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n      m = 1;\n      for (z = zfiles; z != NULL; z = z->nxt) {\n        if (MATCH(p, z->zname, caseflag))\n        {\n          z->mark = pcount ? filter(z->zname, caseflag) : 1;\n          if (verbose)\n              fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n                 z->mark ? \"in\" : \"ex\", z->name);\n          m = 0;\n        }\n      }\n      free((zvoid *)p);\n      return m ? ZE_MISS : ZE_OK;\n    }\n\n    /* Live name--use if file, recurse if directory */\n    if ((s.st_mode & S_IFDIR) == 0)\n    {\n      /* add or remove name of file */\n      if ((m = newname(n, 0, caseflag)) != ZE_OK)\n        return m;\n    } else {\n      if ((p = malloc(strlen(n)+4)) == NULL)\n        return ZE_MEM;\n\n      strcpy(p, n);\n\n      /* No concept of directories on Tandem - so do not store them ...*/\n      /* code removed from which attempted to save dir name if dirnames set */\n\n      /*  Test for recurse being set removed, since Tandem has no dir concept*/\n      /*  recurse into template */\n      if ((d = opendir(n)) != NULL)\n      {\n        while ((e = readd(d)) != NULL) {\n          if ((m = procname(e, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", e);\n            else\n              ziperr(m, e);\n          }\n        }\n        closedir(d);\n      }\n      free((zvoid *)p);\n    } /* (s.st_mode & S_IFDIR) == 0) */\n    return ZE_OK;\n  }\n\n  char *ex2in(x, isdir, pdosflag)\n    char *x;                /* external file name */\n    int isdir;              /* input: x is a directory */\n    int *pdosflag;          /* output: force MSDOS file attributes? */\n  /* Convert the external file name to a zip file name, returning the malloc'ed\n     string or NULL if not enough memory. */\n  {\n    char *n;              /* internal file name (malloc'ed) */\n    char *t;              /* shortened name */\n    int dosflag;\n    char *p;               /* pointer to temp area */\n    char fname[FILENAME_MAX + 1]= \"\"; /* file name */\n    char ext[EXTENSION_MAX + 1] = \"\"; /* extension name */\n    short extension;    /* does the filename contain an extension */\n\n    dosflag = dosify;  /* default for non-DOS non-OS/2 */\n\n    /* Find starting point in name before doing malloc */\n    if (*x == '=')\n      t = x + 1;   /* store DEFINE names without the '=' */\n    else\n      t = x;\n\n    /* Make changes, if any, to the copied name (leave original intact) */\n\n    if (!pathput)\n      t = last(t, TANDEM_DELIMITER);\n\n    /* Malloc space for internal name and copy it */\n    if ((n = malloc(strlen(t) + 4)) == NULL) /* + 4 for safety */\n      return NULL;\n\n    extension = parsename(t,fname,ext);\n    t = fname;\n\n    *n= '\\0';\n\n    while (*t != '\\0') {  /* File part could be sys,vol,subvol or file */\n      if (*t == TANDEM_NODE) {    /* System Name */\n        strcat(n, INTERNAL_NODE_STR);\n        t++;\n      }\n      else if (*t == TANDEM_DELIMITER) {  /* Volume or Subvol */\n             strcat(n, INTERNAL_DELIMITER_STR);\n             t++;\n           };\n      p = strchr(t,TANDEM_DELIMITER);\n      if (p == NULL) break;\n      strncat(n,t,(p - t));\n      t = p;\n    }\n\n    strcat(n,t);  /* mop up any left over characters */\n\n    if (extension) {\n      strcat(n,DOS_EXTENSION_STR);\n      strcat(n,ext);\n    };\n\n    if (isdir == 42) return n;      /* avoid warning on unused variable */\n\n    if (dosify)\n      msname(n);\n\n    /* Returned malloc'ed name */\n    if (pdosflag)\n      *pdosflag = dosflag;\n\n    return n;\n  }\n\n  void stamp(f, d)\n    char *f;                /* name of file to change */\n    ulg d;                  /* dos-style time to change it to */\n  /* Set last updated and accessed time of file f to the DOS time d. */\n  {\n    ztimbuf u;            /* argument for utime() */\n\n    /* Convert DOS time to time_t format in u.actime and u.modtime */\n    u.actime = u.modtime = dos2unixtime(d);\n\n    utime(f, &u);\n  }\n\n  ulg filetime(f, a, n, t)\n    char *f;                /* name of file to get info on */\n    ulg *a;                 /* return value: file attributes */\n    long *n;                /* return value: file size */\n    iztimes *t;             /* return value: access and modification time */\n  {\n    struct stat s;\n    nsk_stat_ov *nsk_ov;\n\n    if (strcmp(f, \"-\") == 0) {    /* if compressing stdin */\n      if (n != NULL) {\n        *n = -1L;\n      }\n    }\n\n    if (stat(f, &s) != 0) return 0;\n\n    if (a!= NULL) {\n      *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWUSR);\n      if ((s.st_mode & S_IFMT) == S_IFDIR) {\n        *a |= MSDOS_DIR_ATTR;\n      }\n    }\n\n    if (n!= NULL)\n      *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n\n    if (t != NULL) {\n      t->atime = s.st_atime;\n      t->mtime = s.st_mtime;\n      nsk_ov = (nsk_stat_ov *)&s.st_reserved[0];\n      t->ctime = nsk_ov->ov.creation_time;\n    }\n\n    return unix2dostime(&s.st_mtime);\n  }\n\n  int set_extra_field(z, z_utim)\n    struct zlist far *z;\n    iztimes *z_utim;\n    /* create extra field and change z->att if desired */\n    /* store full data in local header but just modification time stamp info\n       in central header */\n  {\n    struct stat s;\n    nsk_stat_ov *nsk_ov = (nsk_stat_ov *)&s.st_reserved[0];\n    nsk_file_attrs *nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region;\n    char *ext, *cext;\n    int lsize, csize;\n#ifdef USE_EF_UT_TIME\n    char *UTptr, *Uxptr;\n#endif /* USE_EF_UT_TIME */\n\n    /* For the Tandem and UT local field including the UID/GID fields, we\n       have to stat the file again. */\n    if (LSSTAT(z->name, &s))\n      return ZE_OPEN;\n\n    z->ext = z->cext = 0;\n\n  #define EB_TANDEM_SIZE 20\n  #define EF_TANDEM_SIZE (EB_HEADSIZE + EB_TANDEM_SIZE)\n\n    /* allocate size of buffers to allow Tandem field */\n    lsize = EF_TANDEM_SIZE;\n    csize = EF_TANDEM_SIZE;\n\n#ifdef USE_EF_UT_TIME\n\n  #define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(3))\n  #define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n  #define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)\n  #define EB_C_UX2_SIZE   EB_HEADSIZE\n  #define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)\n  #define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)\n\n    /* resize to allow for UT fields */\n    lsize += EF_L_UNIX_SIZE;\n    csize += EF_C_UNIX_SIZE;\n\n#endif /* USE_EF_UT_TIME */\n\n    if ((z->extra = (char *)malloc(lsize)) == NULL)\n      return ZE_MEM;\n    ext = z->extra;\n\n    if ((z->cextra = (char *)malloc(csize)) == NULL)\n      return ZE_MEM;\n    cext = z->cextra;\n\n    /* Place Tandem field first so its on an even boundary */\n    *ext++ = *cext++ = 'T';\n    *ext++ = *cext++ = 'A';\n    *ext++ = *cext++ = (char)EB_TANDEM_SIZE;  /*length of data part of e.f.*/\n    *ext++ = *cext++  = 0;\n\n    /* Copy Tandem specific file information */\n    memcpy(ext, (char *)nsk_attr, EB_TANDEM_SIZE);\n    ext += EB_TANDEM_SIZE;\n    z->ext += EF_TANDEM_SIZE;\n\n    /* Copy same data to central field */\n    memcpy(cext, (char *)nsk_attr, EB_TANDEM_SIZE);\n    cext += EB_TANDEM_SIZE;\n    z->cext += EF_TANDEM_SIZE;\n\n#ifdef USE_EF_UT_TIME\n    UTptr = ext;\n    *ext++  = 'U';\n    *ext++  = 'T';\n    *ext++  = (char)EB_UT_LEN(3);    /* length of data part of local e.f. */\n    *ext++  = 0;\n    *ext++  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;\n    *ext++  = (char)(s.st_mtime);\n    *ext++  = (char)(s.st_mtime >> 8);\n    *ext++  = (char)(s.st_mtime >> 16);\n    *ext++  = (char)(s.st_mtime >> 24);\n    *ext++  = (char)(s.st_atime);\n    *ext++ = (char)(s.st_atime >> 8);\n    *ext++ = (char)(s.st_atime >> 16);\n    *ext++ = (char)(s.st_atime >> 24);\n\n    *ext++ = (char)(nsk_ov->ov.creation_time);\n    *ext++ = (char)(nsk_ov->ov.creation_time >> 8);\n    *ext++ = (char)(nsk_ov->ov.creation_time >> 16);\n    *ext++ = (char)(nsk_ov->ov.creation_time >> 24);\n\n    Uxptr = ext;\n    *ext++ = 'U';\n    *ext++ = 'x';\n    *ext++ = (char)EB_UX2_MINLEN;   /* length of data part of local e.f. */\n    *ext++ = 0;\n    *ext++ = (char)(s.st_uid);\n    *ext++ = (char)(s.st_uid >> 8);\n    *ext++ = (char)(s.st_gid);\n    *ext++ = (char)(s.st_gid >> 8);\n\n    z->ext += EF_L_UNIX_SIZE;\n\n    memcpy(cext, UTptr, EB_C_UT_SIZE);\n    cext[EB_LEN] = (char)EB_UT_LEN(1);\n    memcpy(cext+EB_C_UT_SIZE, Uxptr, EB_C_UX2_SIZE);\n    cext[EB_LEN+EB_C_UT_SIZE] = 0;\n\n    z->cext += EF_C_UNIX_SIZE;\n    cext += EF_C_UNIX_SIZE;\n\n#endif /* USE_EF_UT_TIME */\n\n    return ZE_OK;\n  }\n\n#if CRYPT\n  /* getpid() only available on OSS so make up dummy version using NSK PID */\n  unsigned zgetpid (void)\n  {\n    short myphandle[ZSYS_VAL_PHANDLE_WLEN];\n    short err;\n    unsigned retval;\n\n    err = PROCESSHANDLE_NULLIT_(myphandle);\n\n    if (!err)\n      err = PROCESS_GETINFO_(myphandle);\n\n    if (!err)\n      retval = (unsigned) myphandle[ZSYS_VAL_PHANDLE_WLEN - 3];\n    else\n#ifndef __INT32\n      retval = (unsigned) 31415;\n#else\n      retval = (unsigned) 3141592654L;\n#endif /* __INT32 */\n\n    return retval;\n  }\n#endif  /* CRYPT */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/tanzip.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __tanzip_h   /* prevent multiple inclusions */\n#define __tanzip_h\n\n# define fopen nskopen  /*  To allow us to set extent sizes */\n\n#  define USE_CASE_MAP\n\n  FILE     *nskopen(const char *, const char *);\n  int       zopen  (const char *, int);\n  int       zclose (int);\n  unsigned  zread (int, char *, unsigned);\n  void      nskformatopt(char *);\n\n  #define   getpid  zgetpid\n  unsigned  zgetpid (void);\n\n#define CBSZ 0x10000  /* Was used for both fcopy and file_read.        */\n                      /* Created separate define (SBSZ) for file_read  */\n                      /* fcopy param is type size_t (unsigned long)    */\n                      /* For Guardian we choose a multiple of 4K       */\n\n#define ZBSZ 0x10000  /* This is used in call to setvbuf, 64K seems to work  */\n                      /* in all memory models. Again it is an unsigned long  */\n                      /* For Guardian we choose a multiple of 4K             */\n\n#ifndef __INT32\n#define SBSZ 0x0e000  /* Maximum of size unsigned (int). Only used in STORE  */\n                      /* method.  We can use up to 56K bytes thanks to large */\n                      /* transfer mode.  Note WSIZE is limited to 32K, which */\n                      /* limits the DEFLATE read size to same value.         */\n#else\n#define SBSZ 0x10000  /* WIDE model so we can use 64K                        */\n#endif /* __INT32 */\n\n#endif /* !__tanzip_h */\n"
  },
  {
    "path": "deps/infozip/zip30/tandem/zipup.h",
    "content": "/*\n  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  define O_RDONLY 0\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n\n/* Now we create Guardian versions of zopen, zread, zclose instead\n   moved prototypes to tanzip.h as they are now coded in tanzip.c\n   #define zopen(n,p) open(n,p)\n   #define zread(f,b,n) read(f,b,n)\n   #define zclose(f) close(f)\n*/\n\n\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n\n"
  },
  {
    "path": "deps/infozip/zip30/theos/README",
    "content": "This Theos port supports all the unusual features of Theos filesystem.\n\nUnder Theos filesystem files are typed. Types include :\n- stream\n- relative\n- keyed\n- indexed (ISAM)\n- program (86 real mode, 16 bits protected mode, 32 bits protected mode)\n- directory\n- library (contains files of any other types librry and directory excepted).\n\nMost of the information on the type and on the structure of a file are not\ncontained in the file itself but its in directory entry. For all types of\nfiles, directory and stream files excepted, this information is vital. If it\nis lost, the file can no longer be usable.\n\nIn zip files the information is stored in an extra block with type \"Th\".\n\nA few years ago I ported ZIP for internal use and spreaded it a little around\nme. It was using a non portable extra block structure. Its type was \"TH\".\nFor backward compatibility it is supported by UNZIP 5.4.0 port to Theos.\nZIP archives created with ZIP 2.3 port MUST be unzipped with 5.4.0 or a later\nversion.\n\nAlso disk search sequence is supported. The disk name is not stored into\nthe zip archive.\n\nThanks to Bob Baker from Stockboy Services who spent his time to check this\nport under other conditions than mines.\n\nJean-Michel Dubois\nIBC France / THEOS France\njmdubois@ibcfrance.fr\njean-michel-dubois@wanadoo.fr\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_chmod.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/* Change UNIX modes */\n\n#pragma library\n\n#include <sc.h>\n\nint _chmod(const char *fname, short mask)\n{\n    extern char _um2tm_(short);\n\n    return _filechange(fname,'p',(size_t) _um2tm_(mask)|0x80);\n}\n\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_fprintf.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include <stdio.h>\n#include <stdarg.h>\n\n/* for Info and similar macroes. fprintf is already a macro and fprintf x\n * fools the preprocessor\n */\n\nint _fprintf(FILE* fp, const char* fmt, ...)\n{\n    va_list ap;\n    long n;\n\n    va_start(ap, fmt);\n    n = vfprintf(fp, fmt, (long*) ap);\n    va_end(ap);\n    return n;\n}\n\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_isatty.c",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* replace standard library function who needs a FILE* */\n\n#pragma library\n\n#include <stdio.h>\n#include <fcntl.h>\n#include <sc.h>\n#include <lub.h>\n\nshort _isatty(int fd)\n{\n    register short lub;\n\n    lub = (int) _fcntl(&stdin[fd], 5, (size_t) 0);\n    return (lub >= CONIN && lub <= CONOUT)\n        || (lub >= COM1 && lub <= COM4)\n        || (lub >= COM5 && lub <= COM16);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_rename.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <errno.h>\n\n#define EXDEV 590\n\n#define _sys_rename()   _sc_140()\nextern unsigned short   _sys_rename(const char _far *oldfn, char *newfn);\n\n/* rename a file. Report an error on cross disk renames */\n\nstatic void _n_(const char* fn, char* bfn)\n{\n    if (*fn != '.' && *fn != '/')\n        strcpy(bfn, \"./\");\n    else\n        *bfn = '\\0';\n    strcat(bfn, fn);\n}\n\nint _rename(const char* old, const char* new)\n{\n    char* p;\n    char* q;\n    char* r;\n    char olddrv, newdrv;\n    char dir[FILENAME_MAX];\n    short status;\n    char bold[FILENAME_MAX], bnew[FILENAME_MAX];\n\n    p = strrchr(old, ':');\n    q = strrchr(new, ':');\n\n    /* if at least one path includes a disk name, check for equality */\n    if (p != NULL || q != NULL) {\n        /* getcwd return a NULL pointer for /:S */\n        getcwd(dir, FILENAME_MAX);\n        r = strrchr(dir, ':');\n\n        if (p == NULL)\n            p = r;\n        olddrv = p ? p[1] : 'S';\n\n        if (q == NULL)\n            q = r;\n        newdrv = q ? q[1] : 'S';\n\n        /* return an error if uppercased disk names are not the same */\n        if ((old & ~0x20) != (new & ~0x20)) {\n            _errarg = NULL;\n            return errno = _errnum = EXDEV;\n        }\n    }\n    /* prepend ./ if there is no path to force rename to work on files\n     * in the current directory instead of default library\n     */\n    _n_(old, bold);\n    _n_(new, bnew);\n\n    status = _sys_rename(bold, bnew);\n    /* can be :\n     *  0 no error\n     * 19 \"old\" file not found\n     * 44 \"new\" file already exist\n     * 45 \"new\" filename missing\n     * 46 \"old\" file name missing\n     */\n    if (status) {\n        errno = _errnum = status;\n        _errarg = (status == 44 || status == 45) ? new : old;\n    }\n\n    return status;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_setargv.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n * __setargv.c - command argument expander\n *\n * Author  : Jean-Michel Dubois\n * Date    : 09/26/92\n *\n * Function: Expands the command line arguments by replacing any filename\n *           including wilcards by the sorted list of matching files name.\n *           Strings beginning by a dash are considered as options and left\n *           unchanged.\n *\n * Syntax  : void _setargv(int *argc, char ***argv);\n *\n * Returns : new argc. Caller's argc and argv are updated.\n *           If a insufficient memory condition occurs, return 0 and errno\n *           is set to ENOMEM.\n *\n * Example :\n *              main(int argc, char **argv)\n *              {\n *                      if (_setargv(&argc, &argv)) {\n *                              ...\n */\n#pragma library\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n#include <errno.h>\n#include <scr.h>\n#include <peek.h>\n\n/* Allocate argv array in 16 entries chunks */\n\nstatic int allocarg(int n, int l, char ***nargv, char *s)\n{\n    if ((n+1) > l) {    /* If array full */\n        l += 16;        /* increase size and reallocate */\n        if (!(*nargv = (char **) realloc(*nargv,l * sizeof (void *)))) {\n            errno = _errnum = ENOMEM;    /* Not enough memory */\n            return 0;\n        }\n    }\n    (*nargv)[n] = strdup(s);    /* Save argument */\n    return l;            /* Return new maxsize */\n}\n\n/* Comparison function for qsort */\n\nstatic int sortcmp(char **p, char **q)\n{\n    return stricmp(*p,*q);\n}\n\n/* Main body of the function */\n\nint _setargv(int *argc, char ***argv)\n{\n    register int nargc;     /* New arguments counter */\n    char **nargv;           /* New arguments pointers */\n    register int i, l, base;\n    char *p, *q, *r;\n    char path[FILENAME_MAX];\n\n    _errnum = 0;\n    nargc = 0;          /* Initialise counter, size counter */\n    l = *argc;          /* and new argument vector to the */\n                        /* current argv array size */\n\n    if ((nargv = (char **) calloc((size_t) *argc, sizeof (void *))) != NULL) {\n        /* For each initial argument */\n        for (i = 0; i < *argc; i++) {\n            q = (*argv)[i];\n            if (q[0] == '-' || ! testwild(q)) {\n                /* if it begins with a dash or doesnt include\n                 * wildcard simply add it to the new array\n                 */\n                if (! (l = allocarg(nargc, l, &nargv, q)))\n                    return 0;    /* Not enough memory */\n                nargc++;\n            } else {\n                /* else keep current counter for qsort */\n                base = nargc;\n                /* open directory with argument */\n                diropen(q);\n                while ((r = dirread()) != NULL) {\n                    /* reduce path to given one */\n                    if ((p = strrchr(q, '/')) != NULL) {\n                        strncpy(path, q, p-q+1);\n                        path[p-q+1] = '\\0';\n                    } else\n                        path[0] = '\\0';\n\n                    if ((p = strrchr(r, '/')) != NULL)\n                        strcat(path, p+1);\n                    else\n                        strcat(path, r);\n\n                    if (peekscr(&SCR->searchseq[1]) == 255\n                     && strchr(q, ':') == NULL) {\n                        *strchr(path, ':') = '\\0';\n                    }\n                    /* and add each matching filename. */\n                    if (! (l = allocarg(nargc,l,&nargv,path)))\n                        return 0;/* Not enough memory */\n                    nargc++;\n                }\n                if (nargc == base) {\n                    /* if no match found include wild card name */\n                    if (! (l = allocarg(nargc, l, &nargv, q)))\n                        return 0;    /* Not enough memory */\n                    nargc++;\n                } else if ((nargc - base) > 1)\n                    /* If more than one file name matchs */\n                    /* sort arguments. */\n                    qsort(&(nargv[base]),(size_t)nargc-base,\n                        sizeof(void *),sortcmp);\n                dirclose();\n            }\n        }\n        /* Update caller's parameters */\n        *argc = nargc;\n        *argv = nargv;\n        /* and sign on success */\n        return nargc;\n    }\n\n    /* If it is not possible to allocate initial array, sign on error */\n    _errnum = ENOMEM;\n    return 0;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/theos/_stat.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#pragma library\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <string.h>\n#include <sc.h>\n#include <peek.h>\n#include <lub.h>\n#include <fdb.h>\n#include <fsa.h>\n#include \"theos/stat.h\"\n\n/* replacement for standard library functions stat and fstat */\n\nint _stat_(struct stat* st, struct fdb* fdb);\nint _dstat_(struct stat* st);\n\n#define peekucb() peeknuc()\n\n/* map THEOS protection code to Unix modes */\n\nunsigned short _tm2um_(char protect)\n{\n    unsigned short umask = 0;\n\n    if (!(protect & _FDB_READ_PROTECT))\n        umask = S_IRUSR|S_IRGRP;\n\n    if (!(protect & _FDB_WRITE_PROTECT))\n        umask |= S_IWUSR|S_IWGRP;\n\n    if (!(protect & _FDB_EXECUTE_PROTECT))\n        umask |= S_IXUSR|S_IXGRP;\n\n    if (!(protect & _FDB_ERASE_PROTECT))\n        umask |= S_IEUSR|S_IEGRP;\n\n    if (!(protect & _FDB_SHARED_READ_PROTECT)) {\n        if (_osmajor > 3)\n            umask |= S_IROTH|S_IXOTH;\n        else\n            umask |= S_IROTH;\n    }\n\n    if (!(protect & _FDB_SHARED_WRITE_PROTECT))\n        umask |= S_IWOTH;\n\n    if (!(protect & _FDB_MODIFIED)) {\n        if (_osmajor > 3)\n            umask |= S_IMODF;\n        else\n            umask |= S_IXOTH;\n    }\n\n    if (protect & _FDB_NOT_HIDDEN)\n        umask |= S_INHID;\n\n    return umask;\n}\n\n/* map Unix modes to THEOS protections */\n\nchar _um2tm_(unsigned short mask)\n{\n    char protect = 0;\n\n    if (!(mask & (S_IRUSR|S_IRGRP)))\n        protect |= _FDB_READ_PROTECT;\n\n    if (!(mask & (S_IWUSR|S_IWGRP)))\n        protect |= _FDB_WRITE_PROTECT;\n\n    if (!(mask & (S_IXUSR|S_IXGRP)))\n        protect |= _FDB_EXECUTE_PROTECT;\n\n    if (!(mask & (S_IEUSR|S_IEGRP)))\n        protect |= _FDB_ERASE_PROTECT;\n\n    if (_osmajor < 4) {\n        if (!(mask & S_IROTH))\n            protect |= _FDB_SHARED_READ_PROTECT;\n    } else {\n        if (!(mask & (S_IROTH|S_IXOTH)))\n            protect |= _FDB_SHARED_READ_PROTECT;\n    }\n\n    if (!(mask & S_IWOTH))\n        protect |= _FDB_SHARED_WRITE_PROTECT;\n\n    if (mask & S_IMODF && _osmajor > 3)\n        protect |= _FDB_MODIFIED;\n\n    if (mask & S_INHID && _osmajor > 3)\n        protect |= _FDB_NOT_HIDDEN;\n\n    return protect;\n}\n\n/* root directory stat */\n\nstatic int rdirstat(const char* fn, struct stat *st)\n{\n    register char* p = strchr(fn, ':');\n    char drive;\n\n    drive = p ? p[1] : 'S';\n\n    if (drive >= 'a' && drive <= 'Z')\n        drive -= 0x40;\n\n    memset(st, 0, sizeof(struct stat));\n\n    if (getlub(drive - 'A') != 255) {\n        st->st_org = _FDB_STAT_DIRECTORY;\n        st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;\n        st->st_nlink = 1;\n        st->st_dev = st->st_rdev = drive - 'A';\n        st->st_uid = st->st_gid = getuid();\n        st->st_protect = _FDB_ERASE_PROTECT;\n        return 0;\n    }\n    errno = _errnum = ENOENT;\n    _errarg = fn;\n    return -1;\n}\n\n#ifdef LOCATE_BUG\n\n/* locate fails when stating a file in root dir from a directory with a\n * relative path. Workaround by setting directory to root dir\n * getting the file directory block, then restoring the current directory.\n */\n\nstruct fdb* __locate(const char* fn, char* buf, short* drv)\n{\n    struct fdb* fdb;\n    char buf2[FILENAME_MAX];\n    char cwd[FILENAME_MAX];\n    char drive[3];\n    char* p;\n    char* q;\n\n    /* return if file found */\n    if (fdb = _locate(fn, buf, drv))\n        return fdb;\n\n    /* if file name does not contain a path delimiter it really does not exist.\n     */\n    strcpy(buf2, fn);\n\n    if ((p = strrchr(buf2, '/')) == NULL)\n        return NULL;\n\n    /* get drive name from file path */\n    q = strrchr(buf2, ':');\n\n    /* cat drive name if any to directory path */\n    if (q) {\n        strncpy(drive, q, 2);\n        drive[2] = '\\0';\n        strcpy(p, q);\n    } else\n        *p = '\\0';\n    /* save current directory */\n    getcwd(cwd, FILENAME_MAX);\n    /* chdir to directory path */\n    chdir(buf2);\n    /* get File Directory Block */\n    p = strrchr(fn, '/');\n    fdb = _locate(p + 1, buf, drv);\n    /* restore current directory */\n    chdir(cwd);\n    return fdb;\n}\n\n#undef _locate\n#define _locate() __locate()\n\n/* same cause, same consequence for fopen and open.\n*/\n\nFILE* _fopen(const char* fn, const char* mode)\n{\n    FILE* fp;\n    char buf[FILENAME_MAX];\n    short drv;\n\n    /* prepend a path to current dir to avoid use of default library */\n    if (*fn != '.' && *fn != '/') {\n        strcpy(buf, \"./\");\n        strcat(buf, fn);\n        return fopen(buf, mode);\n    }\n\n    if (fp = fopen(fn, mode))\n        return fp;\n\n    /* see comment for _locate */\n    if (_locate(fn, buf, &drv)) {\n        fn = strrchr(fn, '/');\n        return fopen(fn, mode);\n    }\n    return NULL;\n}\n\n#undef open\nint open(const char*, int, ...);\n\nint __open(const char* fn, int mode)\n{\n    int fd;\n    char buf[FILENAME_MAX];\n    short drv;\n\n    /* prepend a path to current dir to avoid use of default library */\n    if (*fn != '.' && *fn != '/') {\n        strcpy(buf, \"./\");\n        strcat(buf, fn);\n        return open(buf, mode);\n    }\n\n    if ((fd = open(fn, mode)) != EOF)\n        return fd;\n\n    /* see comment for _locate */\n    if (_locate(fn, buf, &drv)) {\n        fn = strrchr(fn, '/');\n        if (fn)\n            return open(fn, mode);\n    }\n    return EOF;\n}\n#endif\n\n/* replacement for standard file stat */\n\nint _stat(const char *_fn, struct stat *st)\n{\n    char buf[FILENAME_MAX], buf2[FILENAME_MAX], buf3[FILENAME_MAX];\n    register struct fdb* fdb;\n    register char* p;\n    register char* fn;\n\n    fn = strcpy(buf3, _fn);\n\n    if (p = strrchr(fn, ':'))\n        *p = 0;\n\n    /* on current drive ./:d and .:m point to current dir\n     * on another drive to root directory, workaround to avoid it */\n\n    if (! strcmp(fn, \"/\") || ! strcmp(fn, \".\") || ! strcmp(fn, \"./\")) {\n        if (p == NULL) {\n            /* current dir on current drive */\n            fn = getcwd(buf2, FILENAME_MAX);\n            /* getcwd returns NULL on root dir on drive S */\n            if (fn == NULL)\n                fn = strcpy(buf2, \"/:S\");\n            /* getcwd returns /:d on root dir on any other drive */\n            if (fn[1] == ':')\n                return rdirstat(fn, st);\n        } else {\n            *p = ':';\n            return rdirstat(fn, st);\n        }\n        if (p)\n            *p = ':';\n    } else {\n        if (p)\n            *p = ':';\n        if (*fn != '.' && *fn != '/') {\n            strcpy(buf2, \"./\");\n            fn = strcat(buf2, fn);\n        }\n    }\n\n    if (buf2 != fn)\n        strcpy(buf2, fn);\n    /* remove trailing slash before optional disk name */\n    if (p = strrchr(buf2, '/')) {\n        if (p[1] == ':') {\n            *p = p[1];\n            p[1] = p[2];\n            p[2] = p[3];\n        } else if (p[1] == '\\0')\n            *p = '\\0';\n    }\n    /* if fn is a file get file directory block structure and device */\n    if (fdb = _locate(buf2, buf, &st->st_dev)) {\n        /* is it a file from another user... */\n        if (strchr(buf2, '\\\\')\n        /* a public system file... */\n         || fdb->fileowner == 0\n        /* or a file from the current user account ? */\n         || fdb->fileowner == getuid())\n        /* yes, return stat */\n            return _stat_(st, fdb);\n        else {\n            /* no, say file doesn't exist */\n            errno = _errnum = ENOENT;\n            _errarg = fn;\n            return -1;\n        }\n    }\n    /* else should be a device, get device number from device name */\n    st->st_rdev = st->st_dev = _lub_name(*fn == ':' ? fn+1 : fn);\n    /* if it is really a device return device status */\n    if (st->st_dev != -1 && getlub(st->st_dev) != 255)\n        return _dstat_(st);\n    /* neither an existing file or a device name, return EOF */\n    st->st_rdev = st->st_dev = 0;\n    errno = _errnum = ENOENT;\n    _errarg = fn;\n    return -1;\n}\n\n/* replacement for fstat */\n\nint _fstat(int fd, struct stat *st)\n{\n    unsigned short fsanum;\n    struct fsa fsa;\n    register FILE *fp;\n    int status;\n    register int i;\n    register char *p;\n\n    if (fd < FOPEN_MAX) {\n        fp = &stdin[fd];\n        /* get File Save Area number */\n        if (_fcntl(fp,1,0) & 0x80) {\n            fsanum = (unsigned short) _fcntl(fp,83,0);\n            st->st_dev = (unsigned short) _fcntl(fp,5,0);\n\n            if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {\n                /* if opened file is a disk file */\n                /* copy far fsa in protected segment to local fsa */\n                for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;\n                     i < (sizeof(fsa));\n                     i++, fsanum++, p++)\n                    *p = _peekfsa((char *) fsanum);\n                /* build stat structure from fsa */\n                status = _stat_(st, (struct fdb*) &fsa);\n                /* get blocksize */\n                if ((st->st_blksize = _fcntl(fp,817,0)) == 0)\n                    st->st_blksize = BUFSIZ;\n                return status;\n            }\n            /* return device status */\n            return _dstat_(st);\n        }\n    }\n    errno = _errnum = EBADF;\n    return -1;\n}\n\nstatic int _isprt(int dev)\n{\n    return IS_PRT_LUB(dev);\n}\n\n/* device stat */\n\nint _dstat_(st)\nregister struct stat* st;\n{\n    register struct ucb* ucb;\n\n    ucb = getucb(st->st_dev);\n    st->st_ino = 0;\n    if (st->st_dev <= Z_DISK\n     || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {\n        st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;\n        if (peekucb(&ucb->devowner) == 255)\n            st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;\n    } else {\n        st->st_mode = S_IFCHR | S_IWUSR;\n        if (_isprt(st->st_dev))\n            st->st_mode |= S_IRUSR;\n        if (peekucb(&ucb->devowner) == 255) {\n            st->st_mode |= S_IWGRP | S_IWOTH;\n            if (_isprt(st->st_dev))\n                st->st_mode |= S_IRGRP | S_IROTH;\n        }\n    }\n    st->st_nlink = 1;\n    st->st_uid = st->st_gid = getuid();\n    st->st_size = 0;\n    st->st_atime = st->st_mtime = st->st_ctime = 0;\n    st->st_rlen = 0;\n    st->st_klen = 0;\n    st->st_grow = 0;\n    st->st_blksize = 0;\n    return 0;\n}\n\n/* regular file stat */\n\nint _stat_(st, fdb)\nregister struct stat* st;\nregister struct fdb* fdb;\n{\n    st->st_rdev = st->st_dev;\n    st->st_ino = 0;\n    st->st_org = fdb->filestat;\n\n    /* map fdb file status to stat mode */\n    switch (fdb->filestat) {\n    case _FDB_STAT_LIBRARY:         st->st_mode = S_IFLIB;    break;\n    case _FDB_STAT_DIRECTORY:       st->st_mode = S_IFDIR;    break;\n    case _FDB_STAT_STREAM:          st->st_mode = S_IFREG;    break;\n    case _FDB_STAT_RELATIVE:        st->st_mode = S_IFREL;    break;\n    case _FDB_STAT_KEYED:           st->st_mode = S_IFKEY;    break;\n    case _FDB_STAT_INDEXED:         st->st_mode = S_IFIND;    break;\n    case _FDB_STAT_RANDOM:          st->st_mode = S_IFRND;    break;\n    case _FDB_STAT_PROGRAM:         st->st_mode = S_IFR16;    break;\n    case _FDB_STAT_16_BIT_PROGRAM:  st->st_mode = S_IFP16;    break;\n    case _FDB_STAT_32_BIT_PROGRAM:  st->st_mode = S_IFP32;    break;\n    }\n\n    /* map theos file protection codes to stat mode */\n    st->st_mode |= _tm2um_(st->st_protect = fdb->protect);\n    st->st_nlink = 1;\n    st->st_uid = st->st_gid = fdb->fileowner;\n    st->st_size = fdb->filesize;\n    st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);\n    st->st_blksize = 0;\n    /* specific theos information */\n    st->st_rlen = fdb->reclen;\n    st->st_klen = fdb->keylen;\n    st->st_grow = fdb->filegrow;\n    return 0;\n}\n\n#include <direct.h>\n\n/* standard diropen fails on path endung with a '/', workaround */\n\nstruct dirent* _opendir(const char* dirpath)\n{\n    int l;\n    char dirp[FILENAME_MAX];\n    struct dirent* dir;\n\n    if (dirpath && (l = strlen(dirpath))) {\n        if (dirpath[l - 1] == '/') {\n            strcpy(dirp, dirpath);\n            dirp[l - 1] = '\\0';\n            return opendir(dirp);\n        }\n    }\n    return opendir(dirpath);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/theos/charconv.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#ifdef IZ_THS2ISO_ARRAY\nZCONST uch Far ths2iso[] = {\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 80 - 87 */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 88 - 8F */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 90 - 97 */\n    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* 98 - 9F */\n    0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,  /* A0 - A7 */\n    0x2B, 0x2D, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B, 0x23,  /* A8 - AF */\n    0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,  /* B0 - B7 */\n    0x3D, 0x23, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,  /* B8 - BF */\n    0xC4, 0xE4, 0xE2, 0xE0, 0xE1, 0xC9, 0xEB, 0xEA,  /* C0 - C7 */\n    0xE8, 0xE9, 0xEF, 0xEE, 0xEC, 0xED, 0xD6, 0xF6,  /* C8 - CF */\n    0xF4, 0xF2, 0xF3, 0xDC, 0xFC, 0xFB, 0xF9, 0xFA,  /* D0 - D7 */\n    0xC7, 0xE7, 0xD1, 0xF1, 0xC6, 0xE6, 0xC5, 0xE5,  /* D8 - DF */\n    0xDF, 0xBF, 0xA1, 0xA2, 0xA3, 0xA5, 0xB5, 0xA4,  /* E0 - E7 */\n    0xBC, 0xBD, 0xFF, 0xA7, 0xB0, 0xB2, 0x20, 0x20,  /* E8 - EF */\n    0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,  /* F0 - F7 */\n    0x20, 0x20, 0xB7, 0x20, 0x20, 0x20, 0x20, 0x20   /* F8 - FF */\n};\n#endif /* IZ_THS2ISO_ARRAY */\n\n#ifdef IZ_THS2OEM_ARRAY\nZCONST uch Far ths2oem[] = {\n    254,254,254,254, 254,254,134,135,   /* 80 - 87 */\n    136,137,138,139, 140,141,142,143,   /* 88 - 8F */\n    144,145,146,147, 148,149,150,151,   /* 90 - 97 */\n    152,153,154,155, 156,157,158,159,   /* 98 - 9F */\n    218,191,217,192, 197,195,180,194,   /* A0 - A7 */\n    193,196,179,218, 191,217,192,201,   /* A8 - AF */\n    183,188,200,206, 199,182,203,202,   /* B0 - B7 */\n    205,186,186,187, 188,189,190,191,   /* B8 - BF */\n    142,132,131,133, 160,144,137,136,   /* C0 - C7 */\n    138,130,139,140, 141,161,153,148,   /* C8 - CF */\n    147,149,162,154, 129,150,151,163,   /* D0 - D7 */\n    128,135,165,164, 146,145,143,134,   /* D8 - DF */\n    225,168,173,155, 156,157,158, 31,   /* E0 - E7 */\n    172,171,152, 21, 248,253,238,239,   /* E8 - EF */\n    240,241,242,243, 244,245,246,247,   /* F0 - F7 */\n    248,249,250,251, 252,253,254,255    /* F8 - FF */\n};\n#endif /* IZ_THS2OEM_ARRAY */\n\n#ifdef IZ_ISO2THS_ARRAY\nZCONST uch Far iso2ths[] = {\n    0x3F, 0x3F, 0x27, 0x3F, 0x22, 0x2E, 0xA4, 0xB3,  /* 80 - 87 */\n    0x5E, 0x25, 0x53, 0x3C, 0x4F, 0x3F, 0x3F, 0x3F,  /* 88 - 8F */\n    0x3F, 0x27, 0x27, 0x22, 0x22, 0x07, 0x2D, 0x2D,  /* 90 - 97 */\n    0x7E, 0x54, 0x73, 0x3E, 0x6F, 0x3F, 0x3F, 0x59,  /* 98 - 9F */\n    0x20, 0xE2, 0xE3, 0xE4, 0xE7, 0xE5, 0x7C, 0xEB,  /* A0 - A7 */\n    0x20, 0x20, 0x20, 0x22, 0x20, 0x2D, 0x20, 0x2D,  /* A8 - AF */\n    0xEC, 0xF1, 0xED, 0x20, 0x20, 0xE6, 0x20, 0xFA,  /* B0 - B7 */\n    0x20, 0x20, 0x20, 0x22, 0xE8, 0xE9, 0x20, 0xE1,  /* B8 - BF */\n    0xC3, 0xC4, 0xC2, 0x41, 0xC0, 0xDE, 0xDC, 0xD8,  /* C0 - C7 */\n    0xC8, 0xC5, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* C8 - CF */\n    0x44, 0xDA, 0xD1, 0xD2, 0xD0, 0x4F, 0xCE, 0x78,  /* D0 - D7 */\n    0x4F, 0xD6, 0xD7, 0xD5, 0xD3, 0x59, 0x20, 0xE0,  /* D8 - DF */\n    0xC3, 0xC4, 0xC2, 0x61, 0xC1, 0xDF, 0xDD, 0xD9,  /* E0 - E7 */\n    0xC8, 0xC9, 0xC7, 0xC6, 0xCC, 0xCD, 0xCB, 0xCA,  /* E8 - EF */\n    0x64, 0xDB, 0xD1, 0xD2, 0xD0, 0x4F, 0xCF, 0xF1,  /* F0 - F7 */\n    0x6F, 0xD6, 0xD7, 0xD5, 0xD4, 0x79, 0x20, 0xEA   /* F8 - FF */\n};\n#endif /* IZ_ISO2THS_ARRAY */\n\n#ifdef IZ_OEM2THS_ARRAY\nZCONST uch Far oem2ths[] = {\n    216,212,201,194, 193,195,223,217,   /* 80 - 87 */\n    199,198,200,202, 203,204,192,222,   /* 88 - 8F */\n    197,221,220,208, 207,209,213,214,   /* 90 - 97 */\n    234,206,211,227, 228,229,230,159,   /* 98 - 9F */\n    196,205,210,215, 219,218,254,254,   /* A0 - A7 */\n    225,254,254,233, 232,226, 34, 34,   /* A8 - AF */\n    254,254,254,170, 166,166,181,176,   /* B0 - B7 */\n    161,181,185,176, 177,177,162,161,   /* B8 - BF */\n    163,168,167,165, 169,164,165,180,   /* C0 - C7 */\n    178,175,183,182, 180,184,179,168,   /* C8 - CF */\n    183,167,182,178, 163,160,175,179,   /* D0 - D7 */\n    164,162,160,254, 254,254,254,254,   /* D8 - DF */\n    254,224,254,254, 254,254,254, 31,   /* E0 - E7 */\n    254,254,254, 21, 254,254,238,239,   /* E8 - EF */\n    240,241,242,243, 244,245,246,247,   /* F0 - F7 */\n    236,249,250,251, 252,237,254,255    /* F8 - FF */\n};\n#endif /* IZ_OEM2THS_ARRAY */\n\n"
  },
  {
    "path": "deps/infozip/zip30/theos/osdep.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n * XXX this should somehow depend on the stuff in revision.h\n */\n#pragma prog 2.3,0,0,0\n\n/* use argument expansion */\n#if !defined(UTIL) && !defined(MAINWA_BUG)\n#  pragma wild argv\n#endif\n\n#include <stdio.h>\n#include <malloc.h>\n#include <handle.h>\n#include <conio.h>>\n#include <locale.h>\n#include <sys/types.h>\n#include \"theos/stat.h\" /* use JMD's extended stat function */\n\n#define isatty() _isatty() /* THEOS isatty uses a FILE* instead of a fd */\nint _isatty(int fd);\n\n#define deletedir(d) rmdir(d)\n\n/* will come later */\n#if 0\n#define USE_EF_UT_TIME          /* Enable use of \"UT\" extra field time info */\n#endif\n\n#if DEBUG\nint _fprintf(FILE* fp, const char* fmt, ...);\n#endif\n\n/* for rename() replacement. Standard function is bugged */\n\nint _rename(const char* old, const char* new);\n#define rename(a,b) _rename(a,b)\n\n#ifdef LOCATE_BUG\n/* for fopen replacement. Standard function fails on relative path pointing\n * to root directory.\n */\n#undef _fopen\n#undef open\n#define fopen() _fopen()\nFILE* _fopen(const char*, const char*);\n#define open() __open()\nFILE* __open(const char*, int);\n#endif\n\n#define EXDEV   10000\n"
  },
  {
    "path": "deps/infozip/zip30/theos/stat.h",
    "content": "#ifndef __theos_stat_h\n#define __theos_stat_h\n/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* extended stat structure for stat, fstat, chmod */\n/* Written by Jean-Michel Dubois */\n\n#pragma field word\nstruct stat {\n    unsigned short  st_mode;        /* file attributes */\n        #define S_IFMT      0xf000      /* file type mask */\n        #define S_IFIFO     0x1000      /* pipe */\n        #define S_IFCHR     0x2000      /* char device */\n        #define S_IFSOCK    0x3000      /* socket */\n        #define S_IFDIR     0x4000      /* directory */\n        #define S_IFLIB     0x5000      /* library */\n        #define S_IFBLK     0x6000      /* block device */\n        #define S_IFREG     0x8000      /* regular file */\n        #define S_IFREL     0x9000      /* relative (direct) */\n        #define S_IFKEY     0xA000      /* keyed */\n        #define S_IFIND     0xB000      /* indexed */\n        #define S_IFRND     0xC000      /* ???? */\n        #define S_IFR16     0xD000      /* 16 bit real mode program */\n        #define S_IFP16     0xE000      /* 16 bit protected mode prog */\n        #define S_IFP32     0xF000      /* 32 bit protected mode prog */\n\n        #define S_ISUID     0x0800      /* meaningless */\n        #define S_ISGID     0x0400      /* meaningless */\n        #define S_ISVTX     0x0200      /* meaningless */\n\n        #define S_IMODF     0x0800      /* modified */\n        #define S_INHID     0x0400      /* not hidden */\n\n        #define S_IRWXU     0x03c0      /* read,write,execute: owner */\n        #define S_IEUSR     0x0200      /* erase permission: owner */\n        #define S_IRUSR     0x0100      /* read permission: owner */\n        #define S_IWUSR     0x0080      /* write permission: owner */\n        #define S_IXUSR     0x0040      /* execute permission: owner */\n    /* group permissions */\n        #define S_IRWXG     0x0238\n        #define S_IEGRP     0x0200\n        #define S_IRGRP     0x0020\n        #define S_IWGRP     0x0010\n        #define S_IXGRP     0x0008\n    /* other never has erase permission */\n        #define S_IRWXO     0x0207      /* read,write,execute: other */\n        #define S_IROTH     0x0004      /* read permission: other */\n        #define S_IWOTH     0x0002      /* write permission: other */\n        #define S_IXOTH     0x0001      /* execute permission: other */\n\n        #define S_IREAD     0x0100      /* read permission, owner */\n        #define S_IEXEC     0x0040      /* execute permission, owner */\n        #define S_IWRITE    0x0080      /* write permission, owner */\n    short           st_ino;         /* not used */\n    short           st_dev;         /* not used */\n    short           st_rdev;        /* not used */\n    short           st_nlink;       /* not used */\n    short           st_uid;         /* owner id */\n    short           st_gid;         /* not used */\n    unsigned long   st_size;        /* size of file */\n    unsigned long   st_atime;       /* not used */\n    unsigned long   st_mtime;       /* date & time last modified */\n    unsigned long   st_ctime;       /* not used */\n    unsigned long   st_blksize;     /* buffer size */\n    unsigned short  st_org;         /* organization */\n    unsigned short  st_rlen;        /* record size */\n    unsigned short  st_klen;        /* key size */\n    char            st_grow;        /* growing factor */\n    char            st_protect;     /* native protections */\n};\n#pragma field\n\n#define S_ISREG(m)      (((m) & S_IFMT) >= S_IFREG)\n#define S_ISLIB(m)      (((m) & S_IFMT) == S_IFLIB)\n#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)\n#define S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)\n#define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)\n\n#define S_ISSEQ(m)      (((m) & S_IFMT) == S_IFREG)\n#define S_ISREL(m)      (((m) & S_IFMT) == S_IFREL)\n#define S_ISKEY(m)      (((m) & S_IFMT) == S_IFKEY)\n#define S_ISIND(m)      (((m) & S_IFMT) == S_IFIND)\n#define S_ISPRG(m)      (((m) & S_IFMT) >= S_IFP16)\n#define S_ISLNK(m)      0\n\n/* avoid conflict with original THEOS functions */\n\n#define stat(a,b)       _stat(a,b)\n#define fstat(a,b)      _fstat(a,b)\n#define chmod(a,b)      _chmod(a,b)\n\nextern int _stat(const char *file, struct stat *statptr);\nextern int _fstat(int fd, struct stat *statptr);\nextern int _chmod(const char *file, short mask);\n\n#define _chstat(a,b)    ((int) _sc_168(a,'p',(size_t)(b)))\nextern unsigned short   _sc_168(const char _far *fn, int cmd, size_t value);\n\n#endif /* !__theos_stat_h */\n"
  },
  {
    "path": "deps/infozip/zip30/theos/theos.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  theos.c (zip)\n\n  Contribution by Jean-Michel Dubois. 20-Jun-1995, 20-Dec-98\n\n  THEOS specific extra informations\n\n  ---------------------------------------------------------------------------*/\n\n\n#include <stdio.h>\n\n#ifndef UTIL\n\n#include \"zip.h\"\n\n#include <stdlib.h>\n#include <ctype.h>\n#include <time.h>\n#include <sc.h>\n#include <direct.h>\n#include <sys/utime.h>\n\n#define opendir(a) _opendir(a)\nextern struct dirent* _opendir(char* fname);\n\n#define PAD 0\n\n#define RET_ERROR 1\n#define RET_SUCCESS 0\n#define RET_EOF 0\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* match from Phase One Systems */\n\nint match(char *s, char *p)    /*S Returns non-zero if string matches\n                                   the literal mask */\n{\n  int matched, k;\n\n  if (!(*p))\n    return 1;\n  for(;;) {\n    if ( (!(*s)) && (!(*p)) )\n      return(1);\n    else if ( !(*p) )\n      return(0);\n    else if (*p == '*') {\n      if (!*(p+1))\n        return(1);\n      k=0;\n      do {\n        matched = match(s+k,p+1);\n        k++;\n      } while ( (!matched) && *(s+k));\n      return(matched);\n    } else if (*p == '@') {\n      if (!((*s >= 'a' && *s <= 'z')\n          ||(*s >= 'A' && *s <= 'Z')))\n        return(0);\n    } else if (*p == '#') {\n      if (*s < '0' || *s > '9')\n        return(0);\n    } else if (*p != '?') {\n      if (tolower(*s) != tolower(*p))\n        return(0);\n    }\n    s++; p++;\n  }\n}\n\nlocal char *readd(d)\nDIR *d; /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\n/* check if file is a member of a library */\n\nint ismember(char* path)\n{\n    char* p;\n\n    if ((p = strrchr(path, '/')) == NULL)\n        p = path;\n    return ((p = strchr(p, '.')) && (p = strchr(p + 1, '.')));\n}\n\n/* extract library name from a file name */\n\nchar* libname(char* path)\n{\n    char* p;\n    static char lib[FILENAME_MAX];\n    char drive[3];\n\n    strcpy(lib, path);\n    if (p = strrchr(lib, ':')) {\n        strncpy(drive, p, 2);\n        drive[2] = '\\0';\n        *p = '\\0' ;\n    } else\n        drive[0] = '\\0';\n\n    if ((p = strrchr(lib, '/')) == NULL)\n        p = lib;\n\n    p = strchr(p, '.');\n    p = strchr(p + 1, '.');\n    *p = 0;\n    strcat(lib, drive);\n    return lib;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist *z;      /* steps through zfiles list */\n  struct flist *f;      /* steps through files list */\n  char* path;           /* full name */\n  char drive[3];        /* drive name */\n  int recursion;        /* save recurse flag */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s)) {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (match(z->iname, p))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory or library */\n  if (S_ISREG(s.st_mode)) {\n    if ((path = malloc(strlen(n) + 2)) == NULL)\n      return ZE_MEM;\n\n    strcpy(path, n);\n\n    /* if member name, include library name before any member name */\n    if (ismember(path)) {\n      strcpy(path, libname(path));\n      /* mask recursion flag to avoid endless loop recursion\n       * if -r is used with member names\n       */\n      recursion = recurse;\n      recurse = FALSE;\n      if ((m = procname(path, caseflag)) != ZE_OK)   /* recurse on name */\n      {\n        if (m == ZE_MISS)\n          zipwarn(\"name not matched: \", path);\n        else\n          ziperr(m, a);\n      }\n      /* restore recursion flag */\n      recurse = recursion;\n    }\n\n    strcpy(path, n);\n\n    if ((p = strchr(path, ':')) != NULL) {\n      p[2] = '\\0';\n      strcpy(drive, p);\n    } else\n      drive[0] = '\\0';\n\n    /* remove trailing dot in flat file name */\n    p = strend(path) - 1;\n    if (*p == '.')\n      *p = '\\0';\n\n    strcat(path, drive);\n    /* add or remove name of file */\n    if ((m = newname(path, 0, caseflag)) != ZE_OK) {\n      free(path);\n      return m;\n    }\n    free(path);\n  } else if (S_ISLIB(s.st_mode)) {\n    if ((path = malloc(strlen(n) + 2)) == NULL)\n      return ZE_MEM;\n\n    strcpy(path, n);\n\n    if ((p = strchr(path, ':')) != NULL) {\n      p[2] = '\\0';\n      strcpy(drive, p);\n    } else\n      drive[0] = '\\0';\n\n    /* add a trailing dot in flat file name... */\n    p = strend(path) - 1;\n    if (*p != '/')\n      strcat(path, \"/\");\n    p = strend(path);\n    /* ... then add drive name */\n    strcpy(p, drive);\n\n    /* don't include the library name twice... or more */\n    for (f = found; f != NULL; f = f->nxt) {\n      if (! stricmp(path, f->name)) {\n        free(path);\n        return ZE_OK;\n      }\n    }\n    /* add or remove name of library */\n    if ((m = newname(path, 0, caseflag)) != ZE_OK) {\n      free(path);\n      return m;\n    }\n    /* recurse into library if required */\n    strcpy(p - 1, \".*\");\n    strcat(p, drive);\n    if (recurse && diropen(path) == 0)\n    {\n      while ((e = dirread()) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if (*drive == '\\0')\n            *strchr(e, ':') = '\\0';\n          if ((a = malloc(strlen(e) + 1)) == NULL)\n          {\n            dirclose();\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcpy(a, e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      dirclose();\n    }\n    free(path);\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  }\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  char *p;\n  int dosflag;\n\n  dosflag = dosify;  /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  for (t = x; *t == '/'; t++)\n    ;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, '/');\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n\n  strcpy(n, t);\n  if (p = strchr(n, ':'))\n    *p = '\\0';\n  for (p = n; *p = tolower(*p); p++);\n\n  if (isdir == 42) return n;      /* avoid warning on unused variable */\n\n  if (dosify)\n    msname(n);\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n  return x;\n}\n\n/*\n * XXX use ztimbuf in both POSIX and non POSIX cases ?\n */\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  struct utimbuf u;     /* argument for utime()  const ?? */\n\n  /* Convert DOS time to time_t format in u */\n  u.actime = u.modtime = dos2unixtime(d);\n  utime(f, &u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes. Bits 8 to 15 contains native THEOS protection\n   code. If n is not NULL, store the file size there.  If t is not NULL,\n   the file's access, modification and creation times are stored there as\n   UNIX time_t values. If f is \"-\", use standard input as the file. If f is\n   a device, return a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* from FNMAX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n\n  if (name[len - 1] == '/' || name[len - 1] == '.')\n    name[len - 1] = '\\0';\n\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n    /* Accept about any file kind including directories\n     * (stored with trailing / with -r option)\n     */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFMT) == S_IFDIR\n     || (s.st_mode & S_IFMT) == S_IFLIB) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n    /* Map Theos' hidden attribute to DOS's hidden attribute */\n    if (!(st.st_protect & 0x80))\n      *a |= MSDOS_HIDDEN_ATTR;\n    *a |= ((ulg) s.st_protect) << 8;\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */\n  }\n  return unix2dostime(&s.st_mtime);\n}\n/*\n *      Get file THEOS attributes and store them into extent fields.\n *      On error leave z intact.\n */\n\n/*\n*   Extra record format\n*   ===================\n*   signature       (2 bytes)   = 'T','h'\n*   size            (2 bytes)\n*   flags           (1 byte)\n*   filesize        (4 bytes)\n*   keylen          (2 bytes)\n*   reclen          (2 bytes)\n*   filegrow        (1 byte)\n*   reserved        (4 bytes)\n*/\n\n#define EB_L_THSIZE     4\n#define EB_L_TH_SIZE    14\n\nint set_extra_field(z, z_utim)\n  struct zlist *z;\n  iztimes *z_utim;\n  /* store full data in local header but just modification time stamp info\n     in central header */\n{\n  char *extra = NULL;\n  char *p;\n  char c;\n  struct stat st;\n  int status;\n\n  if (status = stat(z->name, &st)) {\n    p = &z->name[strlen(z->name) - 1];\n    if (*p == '/' || *p == '.') {\n      c = *p;\n      *p = '\\0';\n      status = stat(z->name, &st);\n      *p = c;\n    }\n#ifdef DEBUG\n    fprintf(stderr, \"set_extra_field: stat for file %s:\\n status = %d\\n\",\n        z->name, status);\n#endif\n    if (status)\n      return RET_ERROR;\n  }\n\n  if ((extra = malloc(EB_L_TH_SIZE)) == NULL ) {\n    fprintf(stderr, \"set_extra_field: Insufficient memory.\\n\" );\n    return RET_ERROR;\n  }\n\n\n  extra[0] = 'T';\n  extra[1] = 'h';\n  extra[2] = EB_L_TH_SIZE;\n  extra[3] = EB_L_TH_SIZE >> 8;\n  extra[4] = 0;\n  extra[5] = st.st_size;\n  extra[6] = st.st_size >> 8;\n  extra[7] = st.st_size >> 16;\n  extra[8] = st.st_size >> 24;\n  extra[9] = st.st_org;\n  extra[10] = st.st_rlen;\n  extra[11] = st.st_rlen >> 8;\n  extra[12] = st.st_klen;\n  extra[13] = st.st_klen >> 8;\n  extra[14] = st.st_grow;\n  extra[15] = st.st_protect;\n  extra[16] = 0;\n  extra[17] = 0;\n  z->ext = z->cext = EB_L_TH_SIZE + EB_HEADSIZE;\n  z->extra = z->cextra = extra;\n  return RET_SUCCESS;\n}\n#endif\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n  printf(\"Compiled with THEOS C 5.28 for THEOS 4.x on %s %s.\\n\\n\",\n    __DATE__, __TIME__);\n}\n\n"
  },
  {
    "path": "deps/infozip/zip30/theos/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  define O_RDONLY 0\n#endif\n#define fhow O_RDONLY\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/timezone.c",
    "content": "/*\n  timezone.c - Zip 3\n\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* Replacement time library functions, based on platform independent public\n * domain timezone code from ftp://elsie.nci.nih.gov/pub, with mktime and\n * mkgmtime from our own mktime.c in Zip.\n *\n * Contains:  tzset()\n *            __tzset()\n *            gmtime()\n *            localtime()\n *            mktime()\n *            mkgmtime()\n *            GetPlatformLocalTimezone()  [different versions]\n */\n\n/* HISTORY/CHANGES\n * 17 Jun 00, Paul Kienitz, added the PD-based tzset(), localtime(), and so on\n *            to amiga/filedate.c, replacing GNU-based functions which had\n *            replaced time_lib.c, both having been rejected for licensing\n *            reasons.  Support for timezone files and leap seconds was removed.\n *\n * 23 Aug 00, Paul Kienitz, split into separate timezone.c file, made platform\n *            independent, copied in mktime() and mkgmtime() from Zip, renamed\n *            locale_TZ as GetPlatformLocalTimezone(), for use as a generic\n *            hook by other platforms.\n */\n\n#ifndef __timezone_c\n#define __timezone_c\n\n\n#include \"zip.h\"\n#include \"timezone.h\"\n#include <ctype.h>\n#include <errno.h>\n\n#ifdef IZTZ_DEFINESTDGLOBALS\nlong timezone = 0;\nint daylight = 0;\nchar *tzname[2];\n#endif\n\n#ifndef IZTZ_GETLOCALETZINFO\n#  define IZTZ_GETLOCALETZINFO(ptzstruct, pgenrulefunct) (FALSE)\n#endif\n\nint real_timezone_is_set = FALSE;       /* set by tzset() */\n\n\n#define TZDEFRULESTRING \",M4.1.0,M10.5.0\"\n#define TZDEFAULT       \"EST5EDT\"\n\n#define SECSPERMIN      60\n#define MINSPERHOUR     60\n#define HOURSPERDAY     24\n#define DAYSPERWEEK     7\n#define DAYSPERNYEAR    365\n#define DAYSPERLYEAR    366\n#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)\n#define SECSPERDAY      ((long) SECSPERHOUR * HOURSPERDAY)\n#define MONSPERYEAR 12\n\n#define EPOCH_WDAY      4     /* Jan 1, 1970 was thursday */\n#define EPOCH_YEAR      1970\n#define TM_YEAR_BASE    1900\n#define FIRST_GOOD_YEAR ((time_t) -1 < (time_t) 1 ? EPOCH_YEAR-68 : EPOCH_YEAR)\n#define LAST_GOOD_YEAR  (EPOCH_YEAR + ((time_t) -1 < (time_t) 1 ? 67 : 135))\n\n#define YDAYS(month, year) yr_days[leap(year)][month]\n\n/* Nonzero if `y' is a leap year, else zero. */\n#define leap(y)  (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)\n\n/* Number of leap years from EPOCH_YEAR  to `y' (not including `y' itself). */\n#define _P4      ((EPOCH_YEAR / 4) * 4 + 1)\n#define _P100    ((EPOCH_YEAR / 100) * 100 + 1)\n#define _P400    ((EPOCH_YEAR / 400) * 400 + 1)\n#define nleap(y) (((y) - _P4) / 4 - ((y) - _P100) / 100 + ((y) - _P400) / 400)\n\n/* Length of month `m' (0 .. 11) */\n#define monthlen(m, y) (yr_days[0][(m)+1] - yr_days[0][m] + \\\n                        ((m) == 1 && leap(y)))\n\n/* internal module-level constants */\n#ifndef IZ_MKTIME_ONLY\nstatic ZCONST char  gmt[] = \"GMT\";\nstatic ZCONST int    mon_lengths[2][MONSPERYEAR] = {\n    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },\n    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }\n};\n#endif /* !IZ_MKTIME_ONLY */\nstatic ZCONST int    yr_days[2][MONSPERYEAR+1] = {\n    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },\n    { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }\n};\n#ifndef IZ_MKTIME_ONLY\nstatic ZCONST int   year_lengths[2] = {\n    DAYSPERNYEAR, DAYSPERLYEAR\n};\n\n/* internal variables */\nstatic struct state statism;\n\n\n/* prototypes of static functions */\nstatic time_t transtime OF((ZCONST time_t janfirst, ZCONST int year,\n                            ZCONST struct rule * ZCONST rulep,\n                            ZCONST long offset));\nstatic void generate_transitions OF((register struct state * ZCONST sp,\n                                     ZCONST struct rule * ZCONST start,\n                                     ZCONST struct rule * ZCONST end));\nstatic ZCONST char *getzname OF((ZCONST char *strp));\nstatic ZCONST char *getnum OF((ZCONST char *strp, int * ZCONST nump,\n                               ZCONST int min, ZCONST int max));\nstatic ZCONST char *getsecs OF((ZCONST char *strp, long * ZCONST secsp));\nstatic ZCONST char *getoffset OF((ZCONST char *strp, long * ZCONST offsetp));\nstatic ZCONST char *getrule OF((ZCONST char *strp, struct rule * ZCONST rulep));\nstatic int Parse_TZ OF((ZCONST char *name, register struct state * ZCONST sp));\n\n\nstatic time_t transtime(janfirst, year, rulep, offset)\n     ZCONST time_t janfirst;\n     ZCONST int year;\n     ZCONST struct rule * ZCONST rulep;\n     ZCONST long offset;\n{\n    register int    leapyear;\n    register time_t value;\n    register int    i;\n    int             d, m1, yy0, yy1, yy2, dow;\n\n    value = 0;\n    leapyear = leap(year);\n    switch (rulep->r_type) {\n\n    case JULIAN_DAY:\n        /*\n        ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap\n        ** years.\n        ** In non-leap years, or if the day number is 59 or less, just\n        ** add SECSPERDAY times the day number-1 to the time of\n        ** January 1, midnight, to get the day.\n        */\n        value = janfirst + (rulep->r_day - 1) * SECSPERDAY;\n        if (leapyear && rulep->r_day >= 60)\n            value += SECSPERDAY;\n        break;\n\n    case DAY_OF_YEAR:\n        /*\n        ** n - day of year.\n        ** Just add SECSPERDAY times the day number to the time of\n        ** January 1, midnight, to get the day.\n        */\n        value = janfirst + rulep->r_day * SECSPERDAY;\n        break;\n\n    case MONTH_NTH_DAY_OF_WEEK:\n        /*\n        ** Mm.n.d - nth \"dth day\" of month m.\n        */\n        value = janfirst;\n/*\n        for (i = 0; i < rulep->r_mon - 1; ++i)\n            value += mon_lengths[leapyear][i] * SECSPERDAY;\n*/\n        value += yr_days[leapyear][rulep->r_mon - 1] * SECSPERDAY;\n\n        /*\n        ** Use Zeller's Congruence to get day-of-week of first day of\n        ** month.\n        */\n        m1 = (rulep->r_mon + 9) % 12 + 1;\n        yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;\n        yy1 = yy0 / 100;\n        yy2 = yy0 % 100;\n        dow = ((26 * m1 - 2) / 10 +\n            1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;\n        if (dow < 0)\n            dow += DAYSPERWEEK;\n\n        /*\n        ** \"dow\" is the day-of-week of the first day of the month.  Get\n        ** the day-of-month (zero-origin) of the first \"dow\" day of the\n        ** month.\n        */\n        d = rulep->r_day - dow;\n        if (d < 0)\n            d += DAYSPERWEEK;\n        for (i = 1; i < rulep->r_week; ++i) {\n            if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1])\n                break;\n            d += DAYSPERWEEK;\n        }\n\n        /*\n        ** \"d\" is the day-of-month (zero-origin) of the day we want.\n        */\n        value += d * SECSPERDAY;\n        break;\n    }\n\n    /*\n    ** \"value\" is the Epoch-relative time of 00:00:00 UTC on the day in\n    ** question.  To get the Epoch-relative time of the specified local\n    ** time on that day, add the transition time and the current offset\n    ** from UTC.\n    */\n    return value + rulep->r_time + offset;\n}\n\nstatic void generate_transitions(sp, start, end)\n     register struct state * ZCONST sp;\n     ZCONST struct rule * ZCONST start;\n     ZCONST struct rule * ZCONST end;\n{\n    register int             year;\n    register time_t          janfirst;\n    time_t                   starttime;\n    time_t                   endtime;\n    long                     stdoffset = -sp->ttis[0].tt_gmtoff;\n    long                     dstoffset = -sp->ttis[1].tt_gmtoff;\n    register time_t *        atp;\n    register unsigned char * typep;\n\n    /*\n    ** Two transitions per year, from EPOCH_YEAR to LAST_GOOD_YEAR.\n    */\n    sp->timecnt = 2 * (LAST_GOOD_YEAR - EPOCH_YEAR + 1);\n    atp = sp->ats;\n    typep = sp->types;\n    janfirst = 0;\n    for (year = EPOCH_YEAR; year <= LAST_GOOD_YEAR; ++year) {\n        starttime = transtime(janfirst, year, start, stdoffset);\n        endtime = transtime(janfirst, year, end, dstoffset);\n        if (starttime > endtime) {\n            *atp++ = endtime;\n            *typep++ = 0;   /* DST ends */\n            *atp++ = starttime;\n            *typep++ = 1;   /* DST begins */\n        } else {\n            *atp++ = starttime;\n            *typep++ = 1;   /* DST begins */\n            *atp++ = endtime;\n            *typep++ = 0;   /* DST ends */\n        }\n        janfirst += year_lengths[leap(year)] * SECSPERDAY;\n    }\n}\n\nstatic ZCONST char *getzname(strp)\n     ZCONST char *strp;\n{\n    register char   c;\n\n    while ((c = *strp) != '\\0' && !isdigit(c) && c != ',' && c != '-' &&\n        c != '+')\n            ++strp;\n    return strp;\n}\n\nstatic ZCONST char *getnum(strp, nump, min, max)\n     ZCONST char *strp;\n     int * ZCONST nump;\n     ZCONST int min;\n     ZCONST int max;\n{\n    register char   c;\n    register int    num;\n\n    if (strp == NULL || !isdigit(c = *strp))\n        return NULL;\n    num = 0;\n    do {\n        num = num * 10 + (c - '0');\n        if (num > max)\n            return NULL;    /* illegal value */\n        c = *++strp;\n    } while (isdigit(c));\n    if (num < min)\n        return NULL;        /* illegal value */\n    *nump = num;\n    return strp;\n}\n\nstatic ZCONST char *getsecs(strp, secsp)\n     ZCONST char *strp;\n     long * ZCONST secsp;\n{\n    int num;\n\n    /*\n    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like\n    ** \"M10.4.6/26\", which does not conform to Posix,\n    ** but which specifies the equivalent of\n    ** ``02:00 on the first Sunday on or after 23 Oct''.\n    */\n    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);\n    if (strp == NULL)\n        return NULL;\n    *secsp = num * (long) SECSPERHOUR;\n    if (*strp == ':') {\n        ++strp;\n        strp = getnum(strp, &num, 0, MINSPERHOUR - 1);\n        if (strp == NULL)\n            return NULL;\n        *secsp += num * SECSPERMIN;\n        if (*strp == ':') {\n            ++strp;\n            /* `SECSPERMIN' allows for leap seconds.  */\n            strp = getnum(strp, &num, 0, SECSPERMIN);\n            if (strp == NULL)\n                return NULL;\n            *secsp += num;\n        }\n    }\n    return strp;\n}\n\nstatic ZCONST char *getoffset(strp, offsetp)\n     ZCONST char *strp;\n     long * ZCONST offsetp;\n{\n    register int    neg = 0;\n\n    if (*strp == '-') {\n        neg = 1;\n        ++strp;\n    } else if (*strp == '+')\n        ++strp;\n    strp = getsecs(strp, offsetp);\n    if (strp == NULL)\n        return NULL;        /* illegal time */\n    if (neg)\n        *offsetp = -*offsetp;\n    return strp;\n}\n\nstatic ZCONST char *getrule(strp, rulep)\n     ZCONST char *strp;\n     struct rule * ZCONST rulep;\n{\n    if (*strp == 'J') {\n        /*\n        ** Julian day.\n        */\n        rulep->r_type = JULIAN_DAY;\n        ++strp;\n        strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);\n    } else if (*strp == 'M') {\n        /*\n        ** Month, week, day.\n        */\n        rulep->r_type = MONTH_NTH_DAY_OF_WEEK;\n        ++strp;\n        strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);\n        if (strp == NULL)\n            return NULL;\n        if (*strp++ != '.')\n            return NULL;\n        strp = getnum(strp, &rulep->r_week, 1, 5);\n        if (strp == NULL)\n            return NULL;\n        if (*strp++ != '.')\n            return NULL;\n        strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);\n    } else if (isdigit(*strp)) {\n        /*\n        ** Day of year.\n        */\n        rulep->r_type = DAY_OF_YEAR;\n        strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);\n    } else  return NULL;        /* invalid format */\n    if (strp == NULL)\n        return NULL;\n    if (*strp == '/') {\n        /*\n        ** Time specified.\n        */\n        ++strp;\n        strp = getsecs(strp, &rulep->r_time);\n    } else\n        rulep->r_time = 2 * SECSPERHOUR;    /* default = 2:00:00 */\n    return strp;\n}\n\nstatic int Parse_TZ(name, sp)\n     ZCONST char *name;\n     register struct state * ZCONST sp;\n{\n    ZCONST char *            stdname;\n    ZCONST char *            dstname;\n    size_t                   stdlen;\n    size_t                   dstlen;\n    long                     stdoffset;\n    long                     dstoffset;\n    register char *          cp;\n\n    dstname = NULL;\n    stdname = name;\n    name = getzname(name);\n    stdlen = name - stdname;\n    if (stdlen < 3)\n        return -1;\n    if (*name == '\\0')\n        return -1;\n    name = getoffset(name, &stdoffset);\n    if (name == NULL)\n        return -1;\n    if (*name != '\\0') {\n        dstname = name;\n        name = getzname(name);\n        dstlen = name - dstname;    /* length of DST zone name */\n        if (dstlen < 3)\n            return -1;\n        if (*name != '\\0' && *name != ',' && *name != ';') {\n            name = getoffset(name, &dstoffset);\n            if (name == NULL)\n                return -1;\n        } else\n            dstoffset = stdoffset - SECSPERHOUR;\n        if (*name == '\\0')\n            name = TZDEFRULESTRING;\n        if (*name == ',' || *name == ';') {\n            struct rule     start;\n            struct rule     end;\n\n            ++name;\n            if ((name = getrule(name, &start)) == NULL)\n                return -1;\n            if (*name++ != ',')\n                return -1;\n            if ((name = getrule(name, &end)) == NULL)\n                return -1;\n            if (*name != '\\0')\n                return -1;\n            sp->typecnt = 2;    /* standard time and DST */\n            sp->ttis[0].tt_gmtoff = -stdoffset;\n            sp->ttis[0].tt_isdst = 0;\n            sp->ttis[0].tt_abbrind = 0;\n            sp->ttis[1].tt_gmtoff = -dstoffset;\n            sp->ttis[1].tt_isdst = 1;\n            sp->ttis[1].tt_abbrind = stdlen + 1;\n            generate_transitions(sp, &start, &end);\n        }\n    } else {\n        dstlen = 0;\n        sp->typecnt = 1;        /* only standard time */\n        sp->timecnt = 0;\n        sp->ttis[0].tt_gmtoff = -stdoffset;\n        sp->ttis[0].tt_isdst = 0;\n        sp->ttis[0].tt_abbrind = 0;\n    }\n    sp->charcnt = stdlen + 1;\n    if (dstlen != 0)\n        sp->charcnt += dstlen + 1;\n    if ((size_t) sp->charcnt > sizeof(sp->chars))\n        return -1;\n    cp = sp->chars;\n    (void) strncpy(cp, stdname, stdlen);\n    cp += stdlen;\n    *cp++ = '\\0';\n    if (dstlen != 0) {\n        (void) strncpy(cp, dstname, dstlen);\n        *(cp + dstlen) = '\\0';\n    }\n    return 0;\n}\n\nvoid tzset()\n{\n    char *TZstring;\n    int dstfirst;\n    static char *old_TZstring = NULL;\n\n    TZstring = getenv(\"TZ\");    /* read TZ envvar */\n    if (old_TZstring && TZstring && !strcmp(old_TZstring, TZstring))\n        /* do not repeatedly parse an unchanged TZ specification */\n        return;\n    if ((TZstring && TZstring[0] && Parse_TZ(TZstring, &statism) == 0)\n                || IZTZ_GETLOCALETZINFO(&statism, generate_transitions)\n                || Parse_TZ(gmt, &statism) == 0) {\n        daylight  = statism.typecnt > 1;\n        dstfirst  = daylight && statism.ttis[0].tt_isdst && !statism.ttis[1].tt_isdst;\n        timezone  = -statism.ttis[dstfirst].tt_gmtoff;\n        tzname[0] = statism.chars + statism.ttis[dstfirst].tt_abbrind;\n        tzname[1] = statism.chars + statism.ttis[!dstfirst].tt_abbrind;\n        real_timezone_is_set = TRUE;\n        if (TZstring) {\n            if (old_TZstring)\n                old_TZstring = realloc(old_TZstring, strlen(TZstring) + 1);\n            else\n                old_TZstring = malloc(strlen(TZstring) + 1);\n            if (old_TZstring)\n                strcpy(old_TZstring, TZstring);\n        }\n    } else {\n        timezone = 0;   /* default is GMT0 which means no offsets */\n        daylight = 0;   /* from local system time                 */\n        real_timezone_is_set = FALSE;\n        if (old_TZstring) {\n            free(old_TZstring);\n            old_TZstring = NULL;\n        }\n    }\n#ifdef IZTZ_SETLOCALTZINFO\n    /* Some SAS/C library functions, e.g. stat(), call library       */\n    /* __tzset() themselves. So envvar TZ *must* exist in order to   */\n    /* to get the right offset from GMT.  XXX  TRY HARD to fix this! */\n    set_TZ(timezone, daylight);\n#endif /* IZTZ_SETLOCALTZINFO */\n}\n\n/* XXX  Does this also help SAS/C library work? */\nvoid __tzset()\n{\n    if (!real_timezone_is_set) tzset();\n}\n\nstatic struct tm _tmbuf;\n\nstruct tm *gmtime(when)\n     ZCONST time_t *when;\n{\n    long days = *when / SECSPERDAY;\n    long secs = *when % SECSPERDAY;\n    int isleap;\n\n    memset(&_tmbuf, 0, sizeof(_tmbuf));   /* get any nonstandard fields */\n    _tmbuf.tm_wday = (days + EPOCH_WDAY) % 7;\n    _tmbuf.tm_year = EPOCH_YEAR - TM_YEAR_BASE;\n    isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE);\n    while (days >= year_lengths[isleap]) {\n        days -= year_lengths[isleap];\n        _tmbuf.tm_year++;\n        isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE);\n    }\n    _tmbuf.tm_mon = 0;\n    _tmbuf.tm_yday = days;\n    while (days >= mon_lengths[isleap][_tmbuf.tm_mon])\n        days -= mon_lengths[isleap][_tmbuf.tm_mon++];\n    _tmbuf.tm_mday = days + 1;\n    _tmbuf.tm_isdst = 0;\n    _tmbuf.tm_sec = secs % SECSPERMIN;\n    _tmbuf.tm_min = (secs / SECSPERMIN) % SECSPERMIN;\n    _tmbuf.tm_hour = secs / SECSPERHOUR;\n    return &_tmbuf;\n}\n\nstruct tm *localtime(when)\n     ZCONST time_t *when;\n{\n    time_t     localwhen = *when;\n    int        timetype;\n    struct tm *ret;\n\n    __tzset();\n    if (statism.timecnt == 0 || localwhen < statism.ats[0])\n        timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 &&\n                   !statism.ttis[1].tt_isdst;\n    else {\n        for (timetype = 1; timetype < statism.timecnt; ++timetype)\n            if (localwhen < statism.ats[timetype])\n                break;\n        timetype = statism.types[timetype - 1];\n    }\n    localwhen += statism.ttis[timetype].tt_gmtoff;\n    ret = gmtime(&localwhen);\n    ret->tm_isdst = statism.ttis[timetype].tt_isdst;\n    return ret;\n}\n\n#ifdef NEED__ISINDST\nint _isindst(tb)\n    struct tm *tb;\n{\n    time_t     localt;          /* time_t equivalent of given tm struct */\n    time_t     univt;           /* assumed UTC value of given time */\n    long       tzoffset_adj;    /* timezone-adjustment `remainder' */\n    int        bailout_cnt;     /* counter of tries for tz correction */\n    int        timetype;\n\n    __tzset();\n\n    /* when DST is unsupported in current timezone, DST is always off */\n    if (statism.typecnt <= 1) return FALSE;\n\n    localt = mkgmtime(tb);\n    if (localt == (time_t)-1)\n        /* specified time is out-of-range, default to FALSE */\n        return FALSE;\n\n    univt = localt - statism.ttis[0].tt_gmtoff;\n    bailout_cnt = 3;\n    do {\n        if (statism.timecnt == 0 || univt < statism.ats[0])\n            timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 &&\n                       !statism.ttis[1].tt_isdst;\n        else {\n            for (timetype = 1; timetype < statism.timecnt; ++timetype)\n                if (univt < statism.ats[timetype])\n                    break;\n            timetype = statism.types[timetype - 1];\n        }\n        if ((tzoffset_adj = localt - univt - statism.ttis[timetype].tt_gmtoff)\n            == 0L)\n            break;\n        univt += tzoffset_adj;\n    } while (--bailout_cnt > 0);\n\n    /* return TRUE when DST is active at given time */\n    return (statism.ttis[timetype].tt_isdst);\n}\n#endif /* NEED__ISINDST */\n#endif /* !IZ_MKTIME_ONLY */\n\n/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT\n   of the local time and date in the exploded time structure `tm',\n   adjust out of range fields in `tm' and set `tm->tm_yday', `tm->tm_wday'.\n   If `tm->tm_isdst < 0' was passed to mktime(), the correct setting of\n   tm_isdst is determined and returned. Otherwise, mktime() assumes this\n   field as valid; its information is used when converting local time\n   to UTC.\n   Return -1 if time in `tm' cannot be represented as time_t value. */\n\ntime_t mktime(tm)\n     struct tm *tm;\n{\n  struct tm *ltm;               /* Local time. */\n  time_t loctime;               /* The time_t value of local time. */\n  time_t then;                  /* The time to return. */\n  long tzoffset_adj;            /* timezone-adjustment `remainder' */\n  int bailout_cnt;              /* counter of tries for tz correction */\n  int save_isdst;               /* Copy of the tm->isdst input value */\n\n  save_isdst = tm->tm_isdst;\n  loctime = mkgmtime(tm);\n  if (loctime == -1) {\n    tm->tm_isdst = save_isdst;\n    return (time_t)-1;\n  }\n\n  /* Correct for the timezone and any daylight savings time.\n     The correction is verified and repeated when not correct, to\n     take into account the rare case that a change to or from daylight\n     savings time occurs between when it is the time in `tm' locally\n     and when it is that time in Greenwich. After the second correction,\n     the \"timezone & daylight\" offset should be correct in all cases. To\n     be sure, we allow a third try, but then the loop is stopped. */\n  bailout_cnt = 3;\n  then = loctime;\n  do {\n    ltm = localtime(&then);\n    if (ltm == (struct tm *)NULL ||\n        (tzoffset_adj = loctime - mkgmtime(ltm)) == 0L)\n      break;\n    then += tzoffset_adj;\n  } while (--bailout_cnt > 0);\n\n  if (ltm == (struct tm *)NULL || tzoffset_adj != 0L) {\n    /* Signal failure if timezone adjustment did not converge. */\n    tm->tm_isdst = save_isdst;\n    return (time_t)-1;\n  }\n\n  if (save_isdst >= 0) {\n    if (ltm->tm_isdst  && !save_isdst)\n    {\n      if (then + 3600 < then)\n        then = (time_t)-1;\n      else\n        then += 3600;\n    }\n    else if (!ltm->tm_isdst && save_isdst)\n    {\n      if (then - 3600 > then)\n        then = (time_t)-1;\n      else\n        then -= 3600;\n    }\n    ltm->tm_isdst = save_isdst;\n  }\n\n  if (tm != ltm)  /* `tm' may already point to localtime's internal storage */\n    *tm = *ltm;\n\n  return then;\n}\n\n\n#ifndef NO_TIME_T_MAX\n   /* Provide default values for the upper limit of the time_t range.\n      These are the result of the decomposition into a `struct tm' for\n      the time value 0xFFFFFFFEL ( = (time_t)-2 ).\n      Note: `(time_t)-1' is reserved for \"invalid time\"!  */\n#  ifndef TM_YEAR_MAX\n#    define TM_YEAR_MAX         2106\n#  endif\n#  ifndef TM_MON_MAX\n#    define TM_MON_MAX          1       /* February */\n#  endif\n#  ifndef TM_MDAY_MAX\n#    define TM_MDAY_MAX         7\n#  endif\n#  ifndef TM_HOUR_MAX\n#    define TM_HOUR_MAX         6\n#  endif\n#  ifndef TM_MIN_MAX\n#    define TM_MIN_MAX          28\n#  endif\n#  ifndef TM_SEC_MAX\n#    define TM_SEC_MAX          14\n#  endif\n#endif /* NO_TIME_T_MAX */\n\n/* Adjusts out-of-range values for `tm' field `tm_member'. */\n#define ADJUST_TM(tm_member, tm_carry, modulus) \\\n  if ((tm_member) < 0) { \\\n    tm_carry -= (1 - ((tm_member)+1) / (modulus)); \\\n    tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \\\n  } else if ((tm_member) >= (modulus)) { \\\n    tm_carry += (tm_member) / (modulus); \\\n    tm_member = (tm_member) % (modulus); \\\n  }\n\n/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT\n   of the Greenwich Mean time and date in the exploded time structure `tm'.\n   This function does always put back normalized values into the `tm' struct,\n   parameter, including the calculated numbers for `tm->tm_yday',\n   `tm->tm_wday', and `tm->tm_isdst'.\n   Returns -1 if the time in the `tm' parameter cannot be represented\n   as valid `time_t' number. */\n\ntime_t mkgmtime(tm)\n     struct tm *tm;\n{\n  int years, months, days, hours, minutes, seconds;\n\n  years = tm->tm_year + TM_YEAR_BASE;   /* year - 1900 -> year */\n  months = tm->tm_mon;                  /* 0..11 */\n  days = tm->tm_mday - 1;               /* 1..31 -> 0..30 */\n  hours = tm->tm_hour;                  /* 0..23 */\n  minutes = tm->tm_min;                 /* 0..59 */\n  seconds = tm->tm_sec;                 /* 0..61 in ANSI C. */\n\n  ADJUST_TM(seconds, minutes, 60)\n  ADJUST_TM(minutes, hours, 60)\n  ADJUST_TM(hours, days, 24)\n  ADJUST_TM(months, years, 12)\n  if (days < 0)\n    do {\n      if (--months < 0) {\n        --years;\n        months = 11;\n      }\n      days += monthlen(months, years);\n    } while (days < 0);\n  else\n    while (days >= monthlen(months, years)) {\n      days -= monthlen(months, years);\n      if (++months >= 12) {\n        ++years;\n        months = 0;\n      }\n    }\n\n  /* Restore adjusted values in tm structure */\n  tm->tm_year = years - TM_YEAR_BASE;\n  tm->tm_mon = months;\n  tm->tm_mday = days + 1;\n  tm->tm_hour = hours;\n  tm->tm_min = minutes;\n  tm->tm_sec = seconds;\n\n  /* Set `days' to the number of days into the year. */\n  days += YDAYS(months, years);\n  tm->tm_yday = days;\n\n  /* Now calculate `days' to the number of days since Jan 1, 1970. */\n  days = (unsigned)days + 365 * (unsigned)(years - EPOCH_YEAR) +\n         (unsigned)(nleap (years));\n  tm->tm_wday = ((unsigned)days + EPOCH_WDAY) % 7;\n  tm->tm_isdst = 0;\n\n  if (years < EPOCH_YEAR)\n    return (time_t)-1;\n\n#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))\n#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))\n  if (years > TM_YEAR_MAX ||\n      (years == TM_YEAR_MAX &&\n       (tm->tm_yday > (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) ||\n        (tm->tm_yday == (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) &&\n         (hours > TM_HOUR_MAX ||\n          (hours == TM_HOUR_MAX &&\n           (minutes > TM_MIN_MAX ||\n            (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))\n    return (time_t)-1;\n#endif\n#endif\n\n  return (time_t)(SECSPERDAY * (unsigned long)(unsigned)days +\n                  SECSPERHOUR * (unsigned long)hours +\n                  (unsigned long)(SECSPERMIN * minutes + seconds));\n}\n\n#endif /* __timezone_c */\n"
  },
  {
    "path": "deps/infozip/zip30/timezone.h",
    "content": "/*\n  timezone.h - Zip 3\n\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __timezone_h\n#define __timezone_h\n\n#ifndef IZ_MKTIME_ONLY\n\n/* limits for our timezone info data:\n * we support only basic standard and daylight time, with max 2 transitions\n * per year, but for the maximum range of years a 32-bit second counter\n * can cover (these are 136 years plus a bit more than one month)\n */\n#define TZ_MAX_TIMES    272 /* (=2*(LastGoodYr + 1 - FirstGoodYr) */\n#define TZ_MAX_TYPES    2   /* We only support basic standard and daylight */\n#ifdef WIN32    /* Win32 tzinfo supplies at max (2 * 32) chars of tz names */\n#define TZ_MAX_CHARS    64  /* Maximum number of abbreviation characters */\n#else\n#define TZ_MAX_CHARS    50  /* Maximum number of abbreviation characters */\n#endif\n\n/* supported types of transition rules */\n#define JULIAN_DAY              0   /* Jn - Julian day */\n#define DAY_OF_YEAR             1   /* n - day of year */\n#define MONTH_NTH_DAY_OF_WEEK   2   /* Mm.n.d - month, week, day of week */\n\n\nstruct ttinfo {\n    long            tt_gmtoff;  /* UTC offset in seconds */\n    int             tt_isdst;   /* used to set tm_isdst */\n    int             tt_abbrind; /* abbreviation list index */\n};\n\nstruct state {\n    int             timecnt;\n    int             typecnt;\n    int             charcnt;\n    time_t          ats[TZ_MAX_TIMES];\n    unsigned char   types[TZ_MAX_TIMES];\n    struct ttinfo   ttis[TZ_MAX_TYPES];\n    char            chars[TZ_MAX_CHARS];\n};\n\nstruct rule {\n    int             r_type;     /* type of rule--JULIAN_DAY etc */\n    int             r_day;      /* day number of rule */\n    int             r_week;     /* week number of rule */\n    int             r_mon;      /* month number of rule */\n    long            r_time;     /* transition time of rule */\n};\n\nextern int real_timezone_is_set;        /* set by tzset() */\n\n\n/* prototypes of functions not in time.h */\n\nvoid __tzset OF((void));\n\n#ifdef NEED__ISINDST\nint _isindst OF((struct tm *tb));\n#endif\n\n/* callback function to be supplied by the program that uses this library */\nint GetPlatformLocalTimezone OF((register struct state * ZCONST sp,\n        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                        ZCONST struct rule * ZCONST start,\n                                        ZCONST struct rule * ZCONST end)));\n#ifdef IZTZ_SETLOCALTZINFO\nvoid set_TZ OF((long time_zone, int day_light));\n#endif\n\n#endif /* !IZ_MKTIME_ONLY */\n\ntime_t mkgmtime OF((struct tm *tm));\n\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/tops20/make.mic",
    "content": "@te no pau e\n@cc -c -q zip\n@cc -c -q zipfil\n@cc -c -q zipup\n@cc -c -q fileio\n@cc -c -q util\n@cc -c -q crc32\n@cc -c -q global\n@cc -c -q deflat\n@cc -c -q trees\n@cc -c -q crypt\n@cc -c -q ttyio\n@cc -c -q tops20\n@cc -i -o zip zip.rel zipfil.rel zipup.rel fileio.rel util.rel crc32.rel global.rel deflat.rel trees.rel crypt.rel ttyio.rel tops20.rel\n@cc -c -q zipnot\n@rename zipfil.c zipfix.c\n@rename fileio.c filiox.c\n@rename util.c utilx.c\n@rename tops20.c tops2x.c\n@cc -c -q -DUTIL zipfix\n@cc -c -q -DUTIL filiox\n@cc -c -q -DUTIL utilx\n@cc -c -q -DUTIL tops2x\n@rename zipfix.c zipfil.c\n@rename filiox.c fileio.c\n@rename utilx.c util.c\n@rename tops2x.c tops20.c\n@cc -i -o zipnot zipnot.rel zipfix.rel filiox.rel utilx.rel global.rel tops2x.rel\n@reset\n@rename zipnot.exe zipnote.exe\n@cc -c -q zipspl\n@cc -i -o zipspl zipspl.rel zipfix.rel filiox.rel utilx.rel global.rel tops2x.rel\n@reset\n@rename zipspl.exe zipsplit.exe\n@kmic\n"
  },
  {
    "path": "deps/infozip/zip30/tops20/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef TOPS20\n#define TOPS20\n#endif\n\n#define NO_PROTO\n#define NO_SYMLINKS\n#define NO_TERMIO\n#define DIRENT\n#define BIG_MEM\n#define REALLY_SHORT_SYMS\n#define window_size winsiz\n\nextern int isatty();\n\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"w8\"\n\n#define CBSZ 524288\n#define ZBSZ 524288\n\n#include <sys/types.h>\n#include <sys/stat.h>\n"
  },
  {
    "path": "deps/infozip/zip30/tops20/rename.mic",
    "content": "@rename zipfile.c zipfil.c\n@rename globals.c global.c\n@rename deflate.c deflat.c\n@rename zipnote.c zipnot.c\n@rename zipsplit.c zipspl.c\n@kmic\n"
  },
  {
    "path": "deps/infozip/zip30/tops20/tops20.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n\n#define PATH_START '<'\n#define PATH_END   '>'\n\n/* Extra malloc() space in names for cutpath() */\n#define PAD 5         /* may have to change .FOO] to ]FOO.DIR;1 */\n\n\n#define TRUE 1\n#define FALSE 0\n#define O_RDONLY (0)\n#define O_T20_WILD (1<<18)\n#include <monsym.h>    /* Get amazing monsym() macro */\nextern int jsys(), fstat();\nextern char *getcwd();\nextern int _gtjfn(), _rljfn();\n#define JSYS_CLASS    0070000000000\n#define FLD(val,mask) (((unsigned)(val)*((mask)&(-(mask))))&(mask))\n#define _DEFJS(name,class) (FLD(class, JSYS_CLASS) | (monsym(name)&0777777))\n#define JFNS  _DEFJS(\"JFNS%\", 1)\n#define GNJFN _DEFJS(\"GNJFN%\", 0)\nstatic int wfopen(), wfnext(), strlower(), strupper();\nstatic char *wfname();\ntypedef struct {\n   int  wfjfn;\n   int  more;\n} DIR;\n\n/* Library functions not in (most) header files */\n\nextern int stat(), chmod(), toupper(), tolower();\n\nint utime OF((char *, ztimbuf *));\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\n\n\nlocal DIR *opendir(n)\nchar *n;                /* directory name to open */\n/* Open the directory *n, returning a pointer to an allocated DIR, or\n   NULL if error. */\n{\n    DIR *d;             /* pointer to malloc'ed directory stream */\n    char    *c;                         /* scans TOPS20 path */\n    int     m;                          /* length of name */\n    char    *p;                         /* temp string */\n\n    if (((d = (DIR *)malloc(sizeof(DIR))) == NULL) ||\n        ((p = (char *)malloc((m = strlen(n)) + 4)) == NULL)) {\n            return NULL;\n    }\n\n/* Directory may be in form \"<DIR.SUB1.SUB2>\" or \"<DIR.SUB1>SUB2.DIRECTORY\".\n** If latter, convert to former. */\n\n    if ((m > 0)  &&  (*(c = strcpy(p,n) + m-1) != '>')) {\n        c -= 10;\n        *c-- = '\\0';        /* terminate at \"DIRECTORY.1\" */\n        *c = '>';           /* \".\" --> \">\" */\n        while ((c > p)  &&  (*--c != '>'));\n        *c = '.';           /* \">\" --> \".\" */\n    }\n    strcat(p, \"*.*\");\n    if ((d->wfjfn = wfopen(p)) == 0) {\n        free((zvoid *)d);\n        free((zvoid *)p);\n        return NULL;\n    }\n    free((zvoid *)p);\n    d->more = TRUE;\n    return (d);\n}\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  char    *p;\n  if ((d->more == FALSE) || ((p = wfname(d->wfjfn)) == NULL)) {\n      return NULL;\n  }\n  if (wfnext(d->wfjfn) == 0) {\n      d->more = FALSE;\n  }\n  return p;\n}\n\n\nlocal void closedir(d)\nDIR *d;                 /* directory stream to close */\n/* Close the directory stream */\n{\n  free((zvoid *)d);\n}\n\n/* Wildcard filename routines */\n\n/* WFOPEN - open wild card filename\n**      Returns wild JFN for filespec, 0 if failure.\n*/\nstatic int\nwfopen(name)\nchar *name;\n{\n    return (_gtjfn(name, (O_RDONLY | O_T20_WILD)));\n}\n\n/* WFNAME - Return filename for wild JFN\n**      Returns pointer to dynamically allocated filename string\n*/\nstatic char *\nwfname(jfn)\nint jfn;\n{\n    char *fp, fname[200];\n    int ablock[5];\n\n    ablock[1] = (int) (fname - 1);\n    ablock[2] = jfn & 0777777;  /* jfn, no flags */\n    ablock[3] = 0111110000001;  /* DEV+DIR+NAME+TYPE+GEN, punctuate */\n    if (!jsys(JFNS, ablock))\n        return NULL;            /* something bad happened */\n    if ((fp = (char *)malloc(strlen(fname) + 1)) == NULL) {\n        return NULL;\n    }\n    strcpy(fp, fname);          /* copy the file name here */\n    return fp;\n}\n\n/* WFNEXT - Make wild JFN point to next real file\n**      Returns success or failure (not JFN)\n*/\nstatic int\nwfnext(jfn)\nint jfn;\n{\n    int ablock[5];\n\n    ablock[1] = jfn;            /* save jfn and flags */\n    return jsys(GNJFN, ablock);\n}\n\n\nstatic int\nstrupper(s)     /* Returns s in uppercase */\nchar *s;        /* String to be uppercased */\n{\n    char    *p;\n\n    p = s;\n    for (; *p; p++)\n        *p = toupper (*p);\n}\n\nstatic int\nstrlower(s)     /* Returns s in lowercase. */\nchar *s;        /* String to be lowercased */\n{\n    char    *p;\n\n    p = s;\n    for (; *p; p++)\n        *p = tolower (*p);\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    if (caseflag) {\n      p = malloc(strlen(n) + 1);\n      if (p != NULL)\n        strcpy(p, n);\n    } else\n      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    if (dirnames && (m = newname(n, 1, caseflag)) != ZE_OK) {\n      return m;\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if ((m = procname(e, caseflag)) != ZE_OK)     /* recurse on name */\n        {\n          closedir(d);\n          return m;\n        }\n      }\n      closedir(d);\n    }\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n  int jfn;\n  char *fp, fname[200];\n  int ablock[5];\n\n  jfn = _gtjfn(x, (O_RDONLY));\n  ablock[1] = (int) (fname - 1);\n  ablock[2] = jfn & 0777777;    /* jfn, no flags */\n  ablock[3] = 0111100000001;    /* DEV+DIR+NAME+TYPE, punctuate */\n  if (!jsys(JFNS, ablock)) {\n      _rljfn(jfn);\n      return NULL;              /* something bad happened */\n  }\n  _rljfn(jfn);\n  if ((fp = (char *)malloc(strlen(fname) + 1)) == NULL) {\n      return NULL;\n  }\n  strcpy(fp, fname);            /* copy the file name here */\n  x = fp;\n\n  dosflag = dosify; /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  t = x;\n  if ((n = strrchr(t, ':')) != NULL)\n    t = n + 1;\n  if (*t == PATH_START && (n = strrchr(t, PATH_END)) != NULL)\n    if (*(++t) == '.')\n      /* path is relative to current directory, skip leading '.' */\n      t++;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if ((t = strrchr(n, PATH_END)) != NULL)\n  {\n    *t = '/';\n    while (--t > n)\n      if (*t == '.')\n        *t = '/';\n  }\n\n  /* Fix from Greg Roelofs: */\n  /* Get current working directory and strip from n (t now = n) */\n  {\n    char cwd[256], *p, *q;\n    int c;\n\n    if (getcwd(cwd, 256) && ((p = strchr(cwd, PATH_START)) != NULL))\n    {\n      if (*(++p) == '.')\n        p++;\n      if ((q = strrchr(p, PATH_END)) != NULL)\n      {\n        *q = '/';\n        while (--q > p)\n          if (*q == '.')\n            *q = '/';\n\n        /* strip bogus path parts from n */\n        if (strncmp(n, p, (c=strlen(p))) == 0)\n        {\n          q = n + c;\n          while (*t++ = *q++)\n            ;\n        }\n      }\n    }\n  }\n  strlower(n);\n\n  if (isdir)\n  {\n    if (strcmp((t=n+strlen(n)-6), \".dir;1\"))\n      error(\"directory not version 1\");\n    else\n      strcpy(t, \"/\");\n  }\n\n  if ((t = strrchr(n, '.')) != NULL)\n  {\n    if ( t[1] == '\\0')             /* \"filename.\" -> \"filename\" */\n      *t = '\\0';\n  }\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n  return n;\n}\n\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n  char *t;              /* scans name */\n\n  if ((t = strrchr(n, '/')) == NULL)\n  {\n    if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n      return NULL;\n    strcpy(x, n);\n  }\n  else\n  {\n    if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)\n      return NULL;\n    x[0] = PATH_START;\n    x[1] = '.';\n    strcpy(x + 2, n);\n    *(t = x + 2 + (t - n)) = PATH_END;\n    while (--t > x)\n      if (*t == '/')\n        *t = '.';\n  }\n  strupper(x);\n\n  return x;\n}\n\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  ztimbuf u;            /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, &u);\n}\n\nulg filetime(f, a, n, t)\nchar *f;                /* name of file to get info on */\nulg *a;                 /* return value: file attributes */\nlong *n;                /* return value: file size */\niztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* converted from FNAMX to malloc - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFDIR) != 0) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n\n  return unix2dostime(&s.st_mtime);\n}\n\n#include <monsym.h>   /* Get amazing monsym() macro */\n#define       _FBBYV  monsym(\".FBBYV\")\n#define         FBBSZ_S       -24     /* Obsolete, replace by FLDGET! */\n#define         FBBSZ_M       077     /* ditto */\n\nextern int _gtjfn(), _rljfn(), _gtfdb(), stat();\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n  int jfn;\n\n  translate_eol = 0;\n  jfn = _gtjfn(z->name, O_RDONLY);\n  z->att = (((_gtfdb (jfn, _FBBYV) << FBBSZ_S) & FBBSZ_M) != 8) ?\n           ASCII :BINARY;\n  _rljfn(jfn);\n\n#ifdef USE_EF_UT_TIME\n  if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME;\n  z->extra[5]  = (char)(z_utim->mtime);\n  z->extra[6]  = (char)(z_utim->mtime >> 8);\n  z->extra[7]  = (char)(z_utim->mtime >> 16);\n  z->extra[8]  = (char)(z_utim->mtime >> 24);\n\n  z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));\n  z->cextra = z->extra;\n#endif /* USE_EF_UT_TIME */\n\n  return ZE_OK;\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    zipwarn(\"deletedir not implemented yet\", \"\");\n    return 127;\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#if 0\n    char buf[40];\n#endif\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if 0\n      \"cc \", (sprintf(buf, \" version %d\", _RELEASE), buf),\n#  else\n#  ifdef __COMPILER_KCC__\n      \"KCC\", \"\",\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#  endif\n#endif\n\n      \"TOPS-20\",\n\n#if defined(foobar) || defined(FOOBAR)\n      \" (Foo BAR)\",   /* OS version or hardware */\n#else\n      \"\",\n#endif /* Foo BAR */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n"
  },
  {
    "path": "deps/infozip/zip30/tops20/zipup.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n#define O_RDONLY (0)\n#define O_UNCONVERTED     (0400) /* Forced NO conversion requested */\n#define fhow (O_RDONLY | O_UNCONVERTED)\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/trees.c",
    "content": "/*\n  trees.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  trees.c by Jean-loup Gailly\n *\n *  This is a new version of im_ctree.c originally written by Richard B. Wales\n *  for the defunct implosion method.\n *  The low level bit string handling routines from bits.c (originally\n *  im_bits.c written by Richard B. Wales) have been merged into this version\n *  of trees.c.\n *\n *  PURPOSE\n *\n *      Encode various sets of source values using variable-length\n *      binary code trees.\n *      Output the resulting variable-length bit strings.\n *      Compression can be done to a file or to memory.\n *\n *  DISCUSSION\n *\n *      The PKZIP \"deflation\" process uses several Huffman trees. The more\n *      common source values are represented by shorter bit sequences.\n *\n *      Each code tree is stored in the ZIP file in a compressed form\n *      which is itself a Huffman encoding of the lengths of\n *      all the code strings (in ascending order by source values).\n *      The actual code strings are reconstructed from the lengths in\n *      the UNZIP process, as described in the \"application note\"\n *      (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.\n *\n *      The PKZIP \"deflate\" file format interprets compressed file data\n *      as a sequence of bits.  Multi-bit strings in the file may cross\n *      byte boundaries without restriction.\n *      The first bit of each byte is the low-order bit.\n *\n *      The routines in this file allow a variable-length bit value to\n *      be output right-to-left (useful for literal values). For\n *      left-to-right output (useful for code strings from the tree routines),\n *      the bits must have been reversed first with bi_reverse().\n *\n *      For in-memory compression, the compressed bit stream goes directly\n *      into the requested output buffer. The buffer is limited to 64K on\n *      16 bit machines; flushing of the output buffer during compression\n *      process is not supported.\n *      The input data is read in blocks by the (*read_buf)() function.\n *\n *      For more details about input to and output from the deflation routines,\n *      see the actual input functions for (*read_buf)(), flush_outbuf(), and\n *      the filecompress() resp. memcompress() wrapper functions which handle\n *      the I/O setup.\n *\n *  REFERENCES\n *\n *      Lynch, Thomas J.\n *          Data Compression:  Techniques and Applications, pp. 53-55.\n *          Lifetime Learning Publications, 1985.  ISBN 0-534-03418-7.\n *\n *      Storer, James A.\n *          Data Compression:  Methods and Theory, pp. 49-50.\n *          Computer Science Press, 1988.  ISBN 0-7167-8156-5.\n *\n *      Sedgewick, R.\n *          Algorithms, p290.\n *          Addison-Wesley, 1983. ISBN 0-201-06672-6.\n *\n *  INTERFACE\n *\n *      void ct_init (ush *attr, int *method)\n *          Allocate the match buffer, initialize the various tables and save\n *          the location of the internal file attribute (ascii/binary) and\n *          method (DEFLATE/STORE)\n *\n *      void ct_tally (int dist, int lc);\n *          Save the match info and tally the frequency counts.\n *\n *      uzoff_t flush_block (char *buf, ulg stored_len, int eof)\n *          Determine the best encoding for the current block: dynamic trees,\n *          static trees or store, and output the encoded block to the zip\n *          file. Returns the total compressed length for the file so far.\n *\n *      void bi_init (char *tgt_buf, unsigned tgt_size, int flsh_allowed)\n *          Initialize the bit string routines.\n *\n *    Most of the bit string output functions are only used internally\n *    in this source file, they are normally declared as \"local\" routines:\n *\n *      local void send_bits (int value, int length)\n *          Write out a bit string, taking the source bits right to\n *          left.\n *\n *      local unsigned bi_reverse (unsigned code, int len)\n *          Reverse the bits of a bit string, taking the source bits left to\n *          right and emitting them right to left.\n *\n *      local void bi_windup (void)\n *          Write out any remaining bits in an incomplete byte.\n *\n *      local void copy_block(char *buf, unsigned len, int header)\n *          Copy a stored block to the zip file, storing first the length and\n *          its one's complement if requested.\n *\n *    All output that exceeds the bitstring output buffer size (as initialized\n *    by bi_init() is fed through an externally provided transfer routine\n *    which flushes the bitstring output buffer on request and resets the\n *    buffer fill counter:\n *\n *      extern void flush_outbuf(char *o_buf, unsigned *o_idx);\n *\n */\n#define __TREES_C\n\n/* Put zip.h first as when using 64-bit file environment in unix ctype.h\n   defines off_t and then while other files are using an 8-byte off_t this\n   file gets a 4-byte off_t.  Once zip.h sets the large file defines can\n   then include ctype.h and get 8-byte off_t.  8/14/04 EG */\n#include \"zip.h\"\n#include <ctype.h>\n\n#ifndef USE_ZLIB\n\n/* ===========================================================================\n * Constants\n */\n\n#define MAX_BITS 15\n/* All codes must not exceed MAX_BITS bits */\n\n#define MAX_BL_BITS 7\n/* Bit length codes must not exceed MAX_BL_BITS bits */\n\n#define LENGTH_CODES 29\n/* number of length codes, not counting the special END_BLOCK code */\n\n#define LITERALS  256\n/* number of literal bytes 0..255 */\n\n#define END_BLOCK 256\n/* end of block literal code */\n\n#define L_CODES (LITERALS+1+LENGTH_CODES)\n/* number of Literal or Length codes, including the END_BLOCK code */\n\n#define D_CODES   30\n/* number of distance codes */\n\n#define BL_CODES  19\n/* number of codes used to transfer the bit lengths */\n\n\nlocal int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */\n   = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};\n\nlocal int near extra_dbits[D_CODES] /* extra bits for each distance code */\n   = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};\n\nlocal int near extra_blbits[BL_CODES]/* extra bits for each bit length code */\n   = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};\n\n#define STORED_BLOCK 0\n#define STATIC_TREES 1\n#define DYN_TREES    2\n/* The three kinds of block type */\n\n#ifndef LIT_BUFSIZE\n#  ifdef SMALL_MEM\n#    define LIT_BUFSIZE  0x2000\n#  else\n#  ifdef MEDIUM_MEM\n#    define LIT_BUFSIZE  0x4000\n#  else\n#    define LIT_BUFSIZE  0x8000\n#  endif\n#  endif\n#endif\n#define DIST_BUFSIZE  LIT_BUFSIZE\n/* Sizes of match buffers for literals/lengths and distances.  There are\n * 4 reasons for limiting LIT_BUFSIZE to 64K:\n *   - frequencies can be kept in 16 bit counters\n *   - if compression is not successful for the first block, all input data is\n *     still in the window so we can still emit a stored block even when input\n *     comes from standard input.  (This can also be done for all blocks if\n *     LIT_BUFSIZE is not greater than 32K.)\n *   - if compression is not successful for a file smaller than 64K, we can\n *     even emit a stored file instead of a stored block (saving 5 bytes).\n *   - creating new Huffman trees less frequently may not provide fast\n *     adaptation to changes in the input data statistics. (Take for\n *     example a binary file with poorly compressible code followed by\n *     a highly compressible string table.) Smaller buffer sizes give\n *     fast adaptation but have of course the overhead of transmitting trees\n *     more frequently.\n *   - I can't count above 4\n * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save\n * memory at the expense of compression). Some optimizations would be possible\n * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.\n */\n\n#define REP_3_6      16\n/* repeat previous bit length 3-6 times (2 bits of repeat count) */\n\n#define REPZ_3_10    17\n/* repeat a zero length 3-10 times  (3 bits of repeat count) */\n\n#define REPZ_11_138  18\n/* repeat a zero length 11-138 times  (7 bits of repeat count) */\n\n/* ===========================================================================\n * Local data\n */\n\n/* Data structure describing a single value and its code string. */\ntypedef struct ct_data {\n    union {\n        ush  freq;       /* frequency count */\n        ush  code;       /* bit string */\n    } fc;\n    union {\n        ush  dad;        /* father node in Huffman tree */\n        ush  len;        /* length of bit string */\n    } dl;\n} ct_data;\n\n#define Freq fc.freq\n#define Code fc.code\n#define Dad  dl.dad\n#define Len  dl.len\n\n#define HEAP_SIZE (2*L_CODES+1)\n/* maximum heap size */\n\nlocal ct_data near dyn_ltree[HEAP_SIZE];   /* literal and length tree */\nlocal ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */\n\nlocal ct_data near static_ltree[L_CODES+2];\n/* The static literal tree. Since the bit lengths are imposed, there is no\n * need for the L_CODES extra codes used during heap construction. However\n * The codes 286 and 287 are needed to build a canonical tree (see ct_init\n * below).\n */\n\nlocal ct_data near static_dtree[D_CODES];\n/* The static distance tree. (Actually a trivial tree since all codes use\n * 5 bits.)\n */\n\nlocal ct_data near bl_tree[2*BL_CODES+1];\n/* Huffman tree for the bit lengths */\n\ntypedef struct tree_desc {\n    ct_data near *dyn_tree;      /* the dynamic tree */\n    ct_data near *static_tree;   /* corresponding static tree or NULL */\n    int     near *extra_bits;    /* extra bits for each code or NULL */\n    int     extra_base;          /* base index for extra_bits */\n    int     elems;               /* max number of elements in the tree */\n    int     max_length;          /* max bit length for the codes */\n    int     max_code;            /* largest code with non zero frequency */\n} tree_desc;\n\nlocal tree_desc near l_desc =\n{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0};\n\nlocal tree_desc near d_desc =\n{dyn_dtree, static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS, 0};\n\nlocal tree_desc near bl_desc =\n{bl_tree, NULL,       extra_blbits, 0,         BL_CODES, MAX_BL_BITS, 0};\n\n\nlocal ush near bl_count[MAX_BITS+1];\n/* number of codes at each bit length for an optimal tree */\n\nlocal uch near bl_order[BL_CODES]\n   = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};\n/* The lengths of the bit length codes are sent in order of decreasing\n * probability, to avoid transmitting the lengths for unused bit length codes.\n */\n\nlocal int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */\nlocal int heap_len;               /* number of elements in the heap */\nlocal int heap_max;               /* element of largest frequency */\n/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n * The same heap array is used to build all trees.\n */\n\nlocal uch near depth[2*L_CODES+1];\n/* Depth of each subtree used as tie breaker for trees of equal frequency */\n\nlocal uch length_code[MAX_MATCH-MIN_MATCH+1];\n/* length code for each normalized match length (0 == MIN_MATCH) */\n\nlocal uch dist_code[512];\n/* distance codes. The first 256 values correspond to the distances\n * 3 .. 258, the last 256 values correspond to the top 8 bits of\n * the 15 bit distances.\n */\n\nlocal int near base_length[LENGTH_CODES];\n/* First normalized length for each code (0 = MIN_MATCH) */\n\nlocal int near base_dist[D_CODES];\n/* First normalized distance for each code (0 = distance of 1) */\n\n#ifndef DYN_ALLOC\n  local uch far l_buf[LIT_BUFSIZE];  /* buffer for literals/lengths */\n  local ush far d_buf[DIST_BUFSIZE]; /* buffer for distances */\n#else\n  local uch far *l_buf;\n  local ush far *d_buf;\n#endif\n\nlocal uch near flag_buf[(LIT_BUFSIZE/8)];\n/* flag_buf is a bit array distinguishing literals from lengths in\n * l_buf, and thus indicating the presence or absence of a distance.\n */\n\nlocal unsigned last_lit;    /* running index in l_buf */\nlocal unsigned last_dist;   /* running index in d_buf */\nlocal unsigned last_flags;  /* running index in flag_buf */\nlocal uch flags;            /* current flags not yet saved in flag_buf */\nlocal uch flag_bit;         /* current bit used in flags */\n/* bits are filled in flags starting at bit 0 (least significant).\n * Note: these flags are overkill in the current code since we don't\n * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.\n */\n\nlocal ulg opt_len;        /* bit length of current block with optimal trees */\nlocal ulg static_len;     /* bit length of current block with static trees */\n\n/* zip64 support 08/29/2003 R.Nausedat */\n/* now all file sizes and offsets are zoff_t 7/24/04 EG */\nlocal uzoff_t cmpr_bytelen;     /* total byte length of compressed file */\nlocal ulg cmpr_len_bits;        /* number of bits past 'cmpr_bytelen' */\n\n#ifdef DEBUG\nlocal uzoff_t input_len;        /* total byte length of input file */\n/* input_len is for debugging only since we can get it by other means. */\n#endif\n\nlocal ush *file_type;       /* pointer to UNKNOWN, BINARY or ASCII */\nlocal int *file_method;     /* pointer to DEFLATE or STORE */\n\n/* ===========================================================================\n * Local data used by the \"bit string\" routines.\n */\n\nlocal int flush_flg;\n\n#if (!defined(ASMV) || !defined(RISCOS))\nlocal unsigned bi_buf;\n#else\nunsigned bi_buf;\n#endif\n/* Output buffer. bits are inserted starting at the bottom (least significant\n * bits). The width of bi_buf must be at least 16 bits.\n */\n\n#define Buf_size (8 * 2*sizeof(char))\n/* Number of bits used within bi_buf. (bi_buf may be implemented on\n * more than 16 bits on some systems.)\n */\n\n#if (!defined(ASMV) || !defined(RISCOS))\nlocal int bi_valid;\n#else\nint bi_valid;\n#endif\n/* Number of valid bits in bi_buf.  All bits above the last valid bit\n * are always zero.\n */\n\n#if (!defined(ASMV) || !defined(RISCOS))\nlocal char *out_buf;\n#else\nchar *out_buf;\n#endif\n/* Current output buffer. */\n\n#if (!defined(ASMV) || !defined(RISCOS))\nlocal unsigned out_offset;\n#else\nunsigned out_offset;\n#endif\n/* Current offset in output buffer.\n * On 16 bit machines, the buffer is limited to 64K.\n */\n\n#if !defined(ASMV) || !defined(RISCOS)\nlocal unsigned out_size;\n#else\nunsigned out_size;\n#endif\n/* Size of current output buffer */\n\n/* Output a 16 bit value to the bit stream, lower (oldest) byte first */\n#define PUTSHORT(w) \\\n{ if (out_offset >= out_size-1) \\\n    flush_outbuf(out_buf, &out_offset); \\\n  out_buf[out_offset++] = (char) ((w) & 0xff); \\\n  out_buf[out_offset++] = (char) ((ush)(w) >> 8); \\\n}\n\n#define PUTBYTE(b) \\\n{ if (out_offset >= out_size) \\\n    flush_outbuf(out_buf, &out_offset); \\\n  out_buf[out_offset++] = (char) (b); \\\n}\n\n#ifdef DEBUG\nlocal uzoff_t bits_sent;   /* bit length of the compressed data */\nextern uzoff_t isize;      /* byte length of input file */\n#endif\n\nextern long block_start;       /* window offset of current block */\nextern unsigned near strstart; /* window offset of current string */\n\n\n/* ===========================================================================\n * Local (static) routines in this file.\n */\n\nlocal void init_block     OF((void));\nlocal void pqdownheap     OF((ct_data near *tree, int k));\nlocal void gen_bitlen     OF((tree_desc near *desc));\nlocal void gen_codes      OF((ct_data near *tree, int max_code));\nlocal void build_tree     OF((tree_desc near *desc));\nlocal void scan_tree      OF((ct_data near *tree, int max_code));\nlocal void send_tree      OF((ct_data near *tree, int max_code));\nlocal int  build_bl_tree  OF((void));\nlocal void send_all_trees OF((int lcodes, int dcodes, int blcodes));\nlocal void compress_block OF((ct_data near *ltree, ct_data near *dtree));\nlocal void set_file_type  OF((void));\n#if (!defined(ASMV) || !defined(RISCOS))\nlocal void send_bits      OF((int value, int length));\nlocal unsigned bi_reverse OF((unsigned code, int len));\n#endif\nlocal void bi_windup      OF((void));\nlocal void copy_block     OF((char *buf, unsigned len, int header));\n\n\n#ifndef DEBUG\n#  define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)\n   /* Send a code of the given tree. c and tree must not have side effects */\n\n#else /* DEBUG */\n#  define send_code(c, tree) \\\n     { if (verbose>1) fprintf(mesg,\"\\ncd %3d \",(c)); \\\n       send_bits(tree[c].Code, tree[c].Len); }\n#endif\n\n#define d_code(dist) \\\n   ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])\n/* Mapping from a distance to a distance code. dist is the distance - 1 and\n * must not have side effects. dist_code[256] and dist_code[257] are never\n * used.\n */\n\n#define Max(a,b) (a >= b ? a : b)\n/* the arguments must not have side effects */\n\n/* ===========================================================================\n * Allocate the match buffer, initialize the various tables and save the\n * location of the internal file attribute (ascii/binary) and method\n * (DEFLATE/STORE).\n */\nvoid ct_init(attr, method)\n    ush  *attr;   /* pointer to internal file attribute */\n    int  *method; /* pointer to compression method */\n{\n    int n;        /* iterates over tree elements */\n    int bits;     /* bit counter */\n    int length;   /* length value */\n    int code;     /* code value */\n    int dist;     /* distance index */\n\n    file_type = attr;\n    file_method = method;\n    cmpr_len_bits = 0L;\n    cmpr_bytelen = (uzoff_t)0;\n#ifdef DEBUG\n    input_len = (uzoff_t)0;\n#endif\n\n    if (static_dtree[0].Len != 0) return; /* ct_init already called */\n\n#ifdef DYN_ALLOC\n    d_buf = (ush far *) zcalloc(DIST_BUFSIZE, sizeof(ush));\n    l_buf = (uch far *) zcalloc(LIT_BUFSIZE/2, 2);\n    /* Avoid using the value 64K on 16 bit machines */\n    if (l_buf == NULL || d_buf == NULL)\n        ziperr(ZE_MEM, \"ct_init: out of memory\");\n#endif\n\n    /* Initialize the mapping length (0..255) -> length code (0..28) */\n    length = 0;\n    for (code = 0; code < LENGTH_CODES-1; code++) {\n        base_length[code] = length;\n        for (n = 0; n < (1<<extra_lbits[code]); n++) {\n            length_code[length++] = (uch)code;\n        }\n    }\n    Assert(length == 256, \"ct_init: length != 256\");\n    /* Note that the length 255 (match length 258) can be represented\n     * in two different ways: code 284 + 5 bits or code 285, so we\n     * overwrite length_code[255] to use the best encoding:\n     */\n    length_code[length-1] = (uch)code;\n\n    /* Initialize the mapping dist (0..32K) -> dist code (0..29) */\n    dist = 0;\n    for (code = 0 ; code < 16; code++) {\n        base_dist[code] = dist;\n        for (n = 0; n < (1<<extra_dbits[code]); n++) {\n            dist_code[dist++] = (uch)code;\n        }\n    }\n    Assert(dist == 256, \"ct_init: dist != 256\");\n    dist >>= 7; /* from now on, all distances are divided by 128 */\n    for ( ; code < D_CODES; code++) {\n        base_dist[code] = dist << 7;\n        for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {\n            dist_code[256 + dist++] = (uch)code;\n        }\n    }\n    Assert(dist == 256, \"ct_init: 256+dist != 512\");\n\n    /* Construct the codes of the static literal tree */\n    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;\n    n = 0;\n    while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;\n    while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;\n    while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;\n    while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;\n    /* Codes 286 and 287 do not exist, but we must include them in the\n     * tree construction to get a canonical Huffman tree (longest code\n     * all ones)\n     */\n    gen_codes((ct_data near *)static_ltree, L_CODES+1);\n\n    /* The static distance tree is trivial: */\n    for (n = 0; n < D_CODES; n++) {\n        static_dtree[n].Len = 5;\n        static_dtree[n].Code = (ush)bi_reverse(n, 5);\n    }\n\n    /* Initialize the first block of the first file: */\n    init_block();\n}\n\n/* ===========================================================================\n * Initialize a new block.\n */\nlocal void init_block()\n{\n    int n; /* iterates over tree elements */\n\n    /* Initialize the trees. */\n    for (n = 0; n < L_CODES;  n++) dyn_ltree[n].Freq = 0;\n    for (n = 0; n < D_CODES;  n++) dyn_dtree[n].Freq = 0;\n    for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0;\n\n    dyn_ltree[END_BLOCK].Freq = 1;\n    opt_len = static_len = 0L;\n    last_lit = last_dist = last_flags = 0;\n    flags = 0; flag_bit = 1;\n}\n\n#define SMALLEST 1\n/* Index within the heap array of least frequent node in the Huffman tree */\n\n\n/* ===========================================================================\n * Remove the smallest element from the heap and recreate the heap with\n * one less element. Updates heap and heap_len.\n */\n#define pqremove(tree, top) \\\n{\\\n    top = heap[SMALLEST]; \\\n    heap[SMALLEST] = heap[heap_len--]; \\\n    pqdownheap(tree, SMALLEST); \\\n}\n\n/* ===========================================================================\n * Compares to subtrees, using the tree depth as tie breaker when\n * the subtrees have equal frequency. This minimizes the worst case length.\n */\n#define smaller(tree, n, m) \\\n   (tree[n].Freq < tree[m].Freq || \\\n   (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))\n\n/* ===========================================================================\n * Restore the heap property by moving down the tree starting at node k,\n * exchanging a node with the smallest of its two sons if necessary, stopping\n * when the heap property is re-established (each father smaller than its\n * two sons).\n */\nlocal void pqdownheap(tree, k)\n    ct_data near *tree;  /* the tree to restore */\n    int k;               /* node to move down */\n{\n    int v = heap[k];\n    int j = k << 1;  /* left son of k */\n    int htemp;       /* required because of bug in SASC compiler */\n\n    while (j <= heap_len) {\n        /* Set j to the smallest of the two sons: */\n        if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++;\n\n        /* Exit if v is smaller than both sons */\n        htemp = heap[j];\n        if (smaller(tree, v, htemp)) break;\n\n        /* Exchange v with the smallest son */\n        heap[k] = htemp;\n        k = j;\n\n        /* And continue down the tree, setting j to the left son of k */\n        j <<= 1;\n    }\n    heap[k] = v;\n}\n\n/* ===========================================================================\n * Compute the optimal bit lengths for a tree and update the total bit length\n * for the current block.\n * IN assertion: the fields freq and dad are set, heap[heap_max] and\n *    above are the tree nodes sorted by increasing frequency.\n * OUT assertions: the field len is set to the optimal bit length, the\n *     array bl_count contains the frequencies for each bit length.\n *     The length opt_len is updated; static_len is also updated if stree is\n *     not null.\n */\nlocal void gen_bitlen(desc)\n    tree_desc near *desc; /* the tree descriptor */\n{\n    ct_data near *tree  = desc->dyn_tree;\n    int near *extra     = desc->extra_bits;\n    int base            = desc->extra_base;\n    int max_code        = desc->max_code;\n    int max_length      = desc->max_length;\n    ct_data near *stree = desc->static_tree;\n    int h;              /* heap index */\n    int n, m;           /* iterate over the tree elements */\n    int bits;           /* bit length */\n    int xbits;          /* extra bits */\n    ush f;              /* frequency */\n    int overflow = 0;   /* number of elements with bit length too large */\n\n    for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;\n\n    /* In a first pass, compute the optimal bit lengths (which may\n     * overflow in the case of the bit length tree).\n     */\n    tree[heap[heap_max]].Len = 0; /* root of the heap */\n\n    for (h = heap_max+1; h < HEAP_SIZE; h++) {\n        n = heap[h];\n        bits = tree[tree[n].Dad].Len + 1;\n        if (bits > max_length) bits = max_length, overflow++;\n        tree[n].Len = (ush)bits;\n        /* We overwrite tree[n].Dad which is no longer needed */\n\n        if (n > max_code) continue; /* not a leaf node */\n\n        bl_count[bits]++;\n        xbits = 0;\n        if (n >= base) xbits = extra[n-base];\n        f = tree[n].Freq;\n        opt_len += (ulg)f * (bits + xbits);\n        if (stree) static_len += (ulg)f * (stree[n].Len + xbits);\n    }\n    if (overflow == 0) return;\n\n    Trace((stderr,\"\\nbit length overflow\\n\"));\n    /* This happens for example on obj2 and pic of the Calgary corpus */\n\n    /* Find the first bit length which could increase: */\n    do {\n        bits = max_length-1;\n        while (bl_count[bits] == 0) bits--;\n        bl_count[bits]--;           /* move one leaf down the tree */\n        bl_count[bits+1] += (ush)2; /* move one overflow item as its brother */\n        bl_count[max_length]--;\n        /* The brother of the overflow item also moves one step up,\n         * but this does not affect bl_count[max_length]\n         */\n        overflow -= 2;\n    } while (overflow > 0);\n\n    /* Now recompute all bit lengths, scanning in increasing frequency.\n     * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all\n     * lengths instead of fixing only the wrong ones. This idea is taken\n     * from 'ar' written by Haruhiko Okumura.)\n     */\n    for (bits = max_length; bits != 0; bits--) {\n        n = bl_count[bits];\n        while (n != 0) {\n            m = heap[--h];\n            if (m > max_code) continue;\n            if (tree[m].Len != (ush)bits) {\n                Trace((stderr,\"code %d bits %d->%d\\n\", m, tree[m].Len, bits));\n                opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq;\n                tree[m].Len = (ush)bits;\n            }\n            n--;\n        }\n    }\n}\n\n/* ===========================================================================\n * Generate the codes for a given tree and bit counts (which need not be\n * optimal).\n * IN assertion: the array bl_count contains the bit length statistics for\n * the given tree and the field len is set for all tree elements.\n * OUT assertion: the field code is set for all tree elements of non\n *     zero code length.\n */\nlocal void gen_codes (tree, max_code)\n    ct_data near *tree;        /* the tree to decorate */\n    int max_code;              /* largest code with non zero frequency */\n{\n    ush next_code[MAX_BITS+1]; /* next code value for each bit length */\n    ush code = 0;              /* running code value */\n    int bits;                  /* bit index */\n    int n;                     /* code index */\n\n    /* The distribution counts are first used to generate the code values\n     * without bit reversal.\n     */\n    for (bits = 1; bits <= MAX_BITS; bits++) {\n        next_code[bits] = code = (ush)((code + bl_count[bits-1]) << 1);\n    }\n    /* Check that the bit counts in bl_count are consistent. The last code\n     * must be all ones.\n     */\n    Assert(code + bl_count[MAX_BITS]-1 == (1<< ((ush) MAX_BITS)) - 1,\n            \"inconsistent bit counts\");\n    Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n    for (n = 0;  n <= max_code; n++) {\n        int len = tree[n].Len;\n        if (len == 0) continue;\n        /* Now reverse the bits */\n        tree[n].Code = (ush)bi_reverse(next_code[len]++, len);\n\n        Tracec(tree != static_ltree, (stderr,\"\\nn %3d %c l %2d c %4x (%x) \",\n             n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));\n    }\n}\n\n/* ===========================================================================\n * Construct one Huffman tree and assigns the code bit strings and lengths.\n * Update the total bit length for the current block.\n * IN assertion: the field freq is set for all tree elements.\n * OUT assertions: the fields len and code are set to the optimal bit length\n *     and corresponding code. The length opt_len is updated; static_len is\n *     also updated if stree is not null. The field max_code is set.\n */\nlocal void build_tree(desc)\n    tree_desc near *desc; /* the tree descriptor */\n{\n    ct_data near *tree   = desc->dyn_tree;\n    ct_data near *stree  = desc->static_tree;\n    int elems            = desc->elems;\n    int n, m;          /* iterate over heap elements */\n    int max_code = -1; /* largest code with non zero frequency */\n    int node = elems;  /* next internal node of the tree */\n\n    /* Construct the initial heap, with least frequent element in\n     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n     * heap[0] is not used.\n     */\n    heap_len = 0, heap_max = HEAP_SIZE;\n\n    for (n = 0; n < elems; n++) {\n        if (tree[n].Freq != 0) {\n            heap[++heap_len] = max_code = n;\n            depth[n] = 0;\n        } else {\n            tree[n].Len = 0;\n        }\n    }\n\n    /* The pkzip format requires that at least one distance code exists,\n     * and that at least one bit should be sent even if there is only one\n     * possible code. So to avoid special checks later on we force at least\n     * two codes of non zero frequency.\n     */\n    while (heap_len < 2) {\n        int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);\n        tree[new].Freq = 1;\n        depth[new] = 0;\n        opt_len--; if (stree) static_len -= stree[new].Len;\n        /* new is 0 or 1 so it does not have extra bits */\n    }\n    desc->max_code = max_code;\n\n    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n     * establish sub-heaps of increasing lengths:\n     */\n    for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);\n\n    /* Construct the Huffman tree by repeatedly combining the least two\n     * frequent nodes.\n     */\n    do {\n        pqremove(tree, n);   /* n = node of least frequency */\n        m = heap[SMALLEST];  /* m = node of next least frequency */\n\n        heap[--heap_max] = n; /* keep the nodes sorted by frequency */\n        heap[--heap_max] = m;\n\n        /* Create a new node father of n and m */\n        tree[node].Freq = (ush)(tree[n].Freq + tree[m].Freq);\n        depth[node] = (uch) (Max(depth[n], depth[m]) + 1);\n        tree[n].Dad = tree[m].Dad = (ush)node;\n#ifdef DUMP_BL_TREE\n        if (tree == bl_tree) {\n            fprintf(mesg,\"\\nnode %d(%d), sons %d(%d) %d(%d)\",\n                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);\n        }\n#endif\n        /* and insert the new node in the heap */\n        heap[SMALLEST] = node++;\n        pqdownheap(tree, SMALLEST);\n\n    } while (heap_len >= 2);\n\n    heap[--heap_max] = heap[SMALLEST];\n\n    /* At this point, the fields freq and dad are set. We can now\n     * generate the bit lengths.\n     */\n    gen_bitlen((tree_desc near *)desc);\n\n    /* The field len is now set, we can generate the bit codes */\n    gen_codes ((ct_data near *)tree, max_code);\n}\n\n/* ===========================================================================\n * Scan a literal or distance tree to determine the frequencies of the codes\n * in the bit length tree. Updates opt_len to take into account the repeat\n * counts. (The contribution of the bit length codes will be added later\n * during the construction of bl_tree.)\n */\nlocal void scan_tree (tree, max_code)\n    ct_data near *tree; /* the tree to be scanned */\n    int max_code;       /* and its largest code of non zero frequency */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    if (nextlen == 0) max_count = 138, min_count = 3;\n    tree[max_code+1].Len = (ush)-1; /* guard */\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n+1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            bl_tree[curlen].Freq += (ush)count;\n        } else if (curlen != 0) {\n            if (curlen != prevlen) bl_tree[curlen].Freq++;\n            bl_tree[REP_3_6].Freq++;\n        } else if (count <= 10) {\n            bl_tree[REPZ_3_10].Freq++;\n        } else {\n            bl_tree[REPZ_11_138].Freq++;\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Send a literal or distance tree in compressed form, using the codes in\n * bl_tree.\n */\nlocal void send_tree (tree, max_code)\n    ct_data near *tree; /* the tree to be scanned */\n    int max_code;       /* and its largest code of non zero frequency */\n{\n    int n;                     /* iterates over all tree elements */\n    int prevlen = -1;          /* last emitted length */\n    int curlen;                /* length of current code */\n    int nextlen = tree[0].Len; /* length of next code */\n    int count = 0;             /* repeat count of the current code */\n    int max_count = 7;         /* max repeat count */\n    int min_count = 4;         /* min repeat count */\n\n    /* tree[max_code+1].Len = -1; */  /* guard already set */\n    if (nextlen == 0) max_count = 138, min_count = 3;\n\n    for (n = 0; n <= max_code; n++) {\n        curlen = nextlen; nextlen = tree[n+1].Len;\n        if (++count < max_count && curlen == nextlen) {\n            continue;\n        } else if (count < min_count) {\n            do { send_code(curlen, bl_tree); } while (--count != 0);\n\n        } else if (curlen != 0) {\n            if (curlen != prevlen) {\n                send_code(curlen, bl_tree); count--;\n            }\n            Assert(count >= 3 && count <= 6, \" 3_6?\");\n            send_code(REP_3_6, bl_tree); send_bits(count-3, 2);\n\n        } else if (count <= 10) {\n            send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);\n\n        } else {\n            send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);\n        }\n        count = 0; prevlen = curlen;\n        if (nextlen == 0) {\n            max_count = 138, min_count = 3;\n        } else if (curlen == nextlen) {\n            max_count = 6, min_count = 3;\n        } else {\n            max_count = 7, min_count = 4;\n        }\n    }\n}\n\n/* ===========================================================================\n * Construct the Huffman tree for the bit lengths and return the index in\n * bl_order of the last bit length code to send.\n */\nlocal int build_bl_tree()\n{\n    int max_blindex;  /* index of last bit length code of non zero freq */\n\n    /* Determine the bit length frequencies for literal and distance trees */\n    scan_tree((ct_data near *)dyn_ltree, l_desc.max_code);\n    scan_tree((ct_data near *)dyn_dtree, d_desc.max_code);\n\n    /* Build the bit length tree: */\n    build_tree((tree_desc near *)(&bl_desc));\n    /* opt_len now includes the length of the tree representations, except\n     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.\n     */\n\n    /* Determine the number of bit length codes to send. The pkzip format\n     * requires that at least 4 bit length codes be sent. (appnote.txt says\n     * 3 but the actual value used is 4.)\n     */\n    for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {\n        if (bl_tree[bl_order[max_blindex]].Len != 0) break;\n    }\n    /* Update opt_len to include the bit length tree and counts */\n    opt_len += 3*(max_blindex+1) + 5+5+4;\n    Tracev((stderr, \"\\ndyn trees: dyn %ld, stat %ld\", opt_len, static_len));\n\n    return max_blindex;\n}\n\n/* ===========================================================================\n * Send the header for a block using dynamic Huffman trees: the counts, the\n * lengths of the bit length codes, the literal tree and the distance tree.\n * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n */\nlocal void send_all_trees(lcodes, dcodes, blcodes)\n    int lcodes, dcodes, blcodes; /* number of codes for each tree */\n{\n    int rank;                    /* index in bl_order */\n\n    Assert(lcodes >= 257 && dcodes >= 1 && blcodes >= 4, \"not enough codes\");\n    Assert(lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,\n            \"too many codes\");\n    Tracev((stderr, \"\\nbl counts: \"));\n    send_bits(lcodes-257, 5);\n    /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */\n    send_bits(dcodes-1,   5);\n    send_bits(blcodes-4,  4); /* not -3 as stated in appnote.txt */\n    for (rank = 0; rank < blcodes; rank++) {\n        Tracev((stderr, \"\\nbl code %2d \", bl_order[rank]));\n        send_bits(bl_tree[bl_order[rank]].Len, 3);\n    }\n    Tracev((stderr, \"\\nbl tree: sent %s\",\n     zip_fuzofft(bits_sent, NULL, NULL)));\n\n    send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */\n    Tracev((stderr, \"\\nlit tree: sent %s\",\n     zip_fuzofft(bits_sent, NULL, NULL)));\n\n    send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */\n    Tracev((stderr, \"\\ndist tree: sent %ld\",\n     zip_fuzofft(bits_sent, NULL, NULL)));\n}\n\n/* ===========================================================================\n * Determine the best encoding for the current block: dynamic trees, static\n * trees or store, and output the encoded block to the zip file. This function\n * returns the total compressed length (in bytes) for the file so far.\n */\n/* zip64 support 08/29/2003 R.Nausedat */\nuzoff_t flush_block(buf, stored_len, eof)\n    char *buf;        /* input block, or NULL if too old */\n    ulg stored_len;   /* length of input block */\n    int eof;          /* true if this is the last block for a file */\n{\n    ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */\n    int max_blindex;  /* index of last bit length code of non zero freq */\n\n    flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */\n\n     /* Check if the file is ascii or binary */\n    if (*file_type == (ush)UNKNOWN) set_file_type();\n\n    /* Construct the literal and distance trees */\n    build_tree((tree_desc near *)(&l_desc));\n    Tracev((stderr, \"\\nlit data: dyn %ld, stat %ld\", opt_len, static_len));\n\n    build_tree((tree_desc near *)(&d_desc));\n    Tracev((stderr, \"\\ndist data: dyn %ld, stat %ld\", opt_len, static_len));\n    /* At this point, opt_len and static_len are the total bit lengths of\n     * the compressed block data, excluding the tree representations.\n     */\n\n    /* Build the bit length tree for the above two trees, and get the index\n     * in bl_order of the last bit length code to send.\n     */\n    max_blindex = build_bl_tree();\n\n    /* Determine the best encoding. Compute first the block length in bytes */\n    opt_lenb = (opt_len+3+7)>>3;\n    static_lenb = (static_len+3+7)>>3;\n#ifdef DEBUG\n    input_len += stored_len; /* for debugging only */\n#endif\n\n    Trace((stderr, \"\\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u \",\n            opt_lenb, opt_len, static_lenb, static_len, stored_len,\n            last_lit, last_dist));\n\n    if (static_lenb <= opt_lenb) opt_lenb = static_lenb;\n\n#ifndef PGP /* PGP can't handle stored blocks */\n    /* If compression failed and this is the first and last block,\n     * the whole file is transformed into a stored file:\n     */\n#ifdef FORCE_METHOD\n    if (level == 1 && eof && file_method != NULL &&\n        cmpr_bytelen == (uzoff_t)0 && cmpr_len_bits == 0L\n       ) { /* force stored file */\n#else\n    if (stored_len <= opt_lenb && eof && file_method != NULL &&\n        cmpr_bytelen == (uzoff_t)0 && cmpr_len_bits == 0L &&\n        seekable() && !use_descriptors) {\n#endif\n        /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */\n        if (buf == NULL) error (\"block vanished\");\n\n        copy_block(buf, (unsigned)stored_len, 0); /* without header */\n        cmpr_bytelen = stored_len;\n        *file_method = STORE;\n    } else\n#endif /* PGP */\n\n#ifdef FORCE_METHOD\n    if (level <= 2 && buf != (char*)NULL) { /* force stored block */\n#else\n    if (stored_len+4 <= opt_lenb && buf != (char*)NULL) {\n                       /* 4: two words for the lengths */\n#endif\n        /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n         * Otherwise we can't have processed more than WSIZE input bytes since\n         * the last block flush, because compression would have been\n         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n         * transform a block into a stored block.\n         */\n        send_bits((STORED_BLOCK<<1)+eof, 3);  /* send block type */\n        cmpr_bytelen += ((cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4;\n        cmpr_len_bits = 0L;\n\n        copy_block(buf, (unsigned)stored_len, 1); /* with header */\n\n#ifdef FORCE_METHOD\n    } else if (level == 3) { /* force static trees */\n#else\n    } else if (static_lenb == opt_lenb) {\n#endif\n        send_bits((STATIC_TREES<<1)+eof, 3);\n        compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree);\n        cmpr_len_bits += 3 + static_len;\n        cmpr_bytelen += cmpr_len_bits >> 3;\n        cmpr_len_bits &= 7L;\n    } else {\n        send_bits((DYN_TREES<<1)+eof, 3);\n        send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);\n        compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree);\n        cmpr_len_bits += 3 + opt_len;\n        cmpr_bytelen += cmpr_len_bits >> 3;\n        cmpr_len_bits &= 7L;\n    }\n    Assert(((cmpr_bytelen << 3) + cmpr_len_bits) == bits_sent,\n            \"bad compressed size\");\n    init_block();\n\n    if (eof) {\n#if defined(PGP) && !defined(MMAP)\n        /* Wipe out sensitive data for pgp */\n# ifdef DYN_ALLOC\n        extern uch *window;\n# else\n        extern uch window[];\n# endif\n        memset(window, 0, (unsigned)(2*WSIZE-1)); /* -1 needed if WSIZE=32K */\n#else /* !PGP */\n        Assert(input_len == isize, \"bad input size\");\n#endif\n        bi_windup();\n        cmpr_len_bits += 7;  /* align on byte boundary */\n    }\n    Tracev((stderr,\"\\ncomprlen %s(%s) \",\n     zip_fuzofft( cmpr_bytelen + (cmpr_len_bits>>3), NULL, NULL),\n     zip_fuzofft( (cmpr_bytelen << 3) + cmpr_len_bits - 7*eof, NULL, NULL)));\n    Trace((stderr, \"\\n\"));\n\n    return cmpr_bytelen + (cmpr_len_bits >> 3);\n}\n\n/* ===========================================================================\n * Save the match info and tally the frequency counts. Return true if\n * the current block must be flushed.\n */\nint ct_tally (dist, lc)\n    int dist;  /* distance of matched string */\n    int lc;    /* match length-MIN_MATCH or unmatched char (if dist==0) */\n{\n    l_buf[last_lit++] = (uch)lc;\n    if (dist == 0) {\n        /* lc is the unmatched char */\n        dyn_ltree[lc].Freq++;\n    } else {\n        /* Here, lc is the match length - MIN_MATCH */\n        dist--;             /* dist = match distance - 1 */\n        Assert((ush)dist < (ush)MAX_DIST &&\n               (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&\n               (ush)d_code(dist) < (ush)D_CODES,  \"ct_tally: bad match\");\n\n        dyn_ltree[length_code[lc]+LITERALS+1].Freq++;\n        dyn_dtree[d_code(dist)].Freq++;\n\n        d_buf[last_dist++] = (ush)dist;\n        flags |= flag_bit;\n    }\n    flag_bit <<= 1;\n\n    /* Output the flags if they fill a byte: */\n    if ((last_lit & 7) == 0) {\n        flag_buf[last_flags++] = flags;\n        flags = 0, flag_bit = 1;\n    }\n    /* Try to guess if it is profitable to stop the current block here */\n    if (level > 2 && (last_lit & 0xfff) == 0) {\n        /* Compute an upper bound for the compressed length */\n        ulg out_length = (ulg)last_lit*8L;\n        ulg in_length = (ulg)strstart-block_start;\n        int dcode;\n        for (dcode = 0; dcode < D_CODES; dcode++) {\n            out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);\n        }\n        out_length >>= 3;\n        Trace((stderr,\"\\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) \",\n               last_lit, last_dist, in_length, out_length,\n               100L - out_length*100L/in_length));\n        if (last_dist < last_lit/2 && out_length < in_length/2) return 1;\n    }\n    return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE);\n    /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K\n     * on 16 bit machines and because stored blocks are restricted to\n     * 64K-1 bytes.\n     */\n}\n\n/* ===========================================================================\n * Send the block data compressed using the given Huffman trees\n */\nlocal void compress_block(ltree, dtree)\n    ct_data near *ltree; /* literal tree */\n    ct_data near *dtree; /* distance tree */\n{\n    unsigned dist;      /* distance of matched string */\n    int lc;             /* match length or unmatched char (if dist == 0) */\n    unsigned lx = 0;    /* running index in l_buf */\n    unsigned dx = 0;    /* running index in d_buf */\n    unsigned fx = 0;    /* running index in flag_buf */\n    uch flag = 0;       /* current flags */\n    unsigned code;      /* the code to send */\n    int extra;          /* number of extra bits to send */\n\n    if (last_lit != 0) do {\n        if ((lx & 7) == 0) flag = flag_buf[fx++];\n        lc = l_buf[lx++];\n        if ((flag & 1) == 0) {\n            send_code(lc, ltree); /* send a literal byte */\n            Tracecv(isgraph(lc), (stderr,\" '%c' \", lc));\n        } else {\n            /* Here, lc is the match length - MIN_MATCH */\n            code = length_code[lc];\n            send_code(code+LITERALS+1, ltree); /* send the length code */\n            extra = extra_lbits[code];\n            if (extra != 0) {\n                lc -= base_length[code];\n                send_bits(lc, extra);        /* send the extra length bits */\n            }\n            dist = d_buf[dx++];\n            /* Here, dist is the match distance - 1 */\n            code = d_code(dist);\n            Assert(code < D_CODES, \"bad d_code\");\n\n            send_code(code, dtree);       /* send the distance code */\n            extra = extra_dbits[code];\n            if (extra != 0) {\n                dist -= base_dist[code];\n                send_bits(dist, extra);   /* send the extra distance bits */\n            }\n        } /* literal or match pair ? */\n        flag >>= 1;\n    } while (lx < last_lit);\n\n    send_code(END_BLOCK, ltree);\n}\n\n/* ===========================================================================\n * Set the file type to TEXT (ASCII) or BINARY, using following algorithm:\n * - TEXT, either ASCII or an ASCII-compatible extension such as ISO-8859,\n *   UTF-8, etc., when the following two conditions are satisfied:\n *    a) There are no non-portable control characters belonging to the\n *       \"black list\" (0..6, 14..25, 28..31).\n *    b) There is at least one printable character belonging to the\n *       \"white list\" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).\n * - BINARY otherwise.\n *\n * Note that the following partially-portable control characters form a\n * \"gray list\" that is ignored in this detection algorithm:\n * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).\n *\n * Also note that, unlike in the previous 20% binary detection algorithm,\n * any control characters in the black list will set the file type to\n * BINARY.  If a text file contains a single accidental black character,\n * the file will be flagged as BINARY in the archive.\n *\n * IN assertion: the fields freq of dyn_ltree are set.\n */\nlocal void set_file_type()\n{\n    /* bit-mask of black-listed bytes\n     * bit is set if byte is black-listed\n     * set bits 0..6, 14..25, and 28..31\n     * 0xf3ffc07f = binary 11110011111111111100000001111111\n     */\n    unsigned long mask = 0xf3ffc07fL;\n    int n;\n\n    /* Check for non-textual (\"black-listed\") bytes. */\n    for (n = 0; n <= 31; n++, mask >>= 1)\n        if ((mask & 1) && (dyn_ltree[n].Freq != 0))\n        {\n            *file_type = BINARY;\n            return;\n        }\n\n    /* Check for textual (\"white-listed\") bytes. */\n    *file_type = ASCII;\n    if (dyn_ltree[9].Freq != 0 || dyn_ltree[10].Freq != 0\n            || dyn_ltree[13].Freq != 0)\n        return;\n    for (n = 32; n < LITERALS; n++)\n        if (dyn_ltree[n].Freq != 0)\n            return;\n\n    /* This deflate stream is either empty, or\n     * it has tolerated (\"gray-listed\") bytes only.\n     */\n    *file_type = BINARY;\n}\n\n\n/* ===========================================================================\n * Initialize the bit string routines.\n */\nvoid bi_init (tgt_buf, tgt_size, flsh_allowed)\n    char *tgt_buf;\n    unsigned tgt_size;\n    int flsh_allowed;\n{\n    out_buf = tgt_buf;\n    out_size = tgt_size;\n    out_offset = 0;\n    flush_flg = flsh_allowed;\n\n    bi_buf = 0;\n    bi_valid = 0;\n#ifdef DEBUG\n    bits_sent = (uzoff_t)0;\n#endif\n}\n\n#if (!defined(ASMV) || !defined(RISCOS))\n/* ===========================================================================\n * Send a value on a given number of bits.\n * IN assertion: length <= 16 and value fits in length bits.\n */\nlocal void send_bits(value, length)\n    int value;  /* value to send */\n    int length; /* number of bits */\n{\n#ifdef DEBUG\n    Tracevv((stderr,\" l %2d v %4x \", length, value));\n    Assert(length > 0 && length <= 15, \"invalid length\");\n    bits_sent += (uzoff_t)length;\n#endif\n    /* If not enough room in bi_buf, use (bi_valid) bits from bi_buf and\n     * (Buf_size - bi_valid) bits from value to flush the filled bi_buf,\n     * then fill in the rest of (value), leaving (length - (Buf_size-bi_valid))\n     * unused bits in bi_buf.\n     */\n    bi_buf |= (value << bi_valid);\n    bi_valid += length;\n    if (bi_valid > (int)Buf_size) {\n        PUTSHORT(bi_buf);\n        bi_valid -= Buf_size;\n        bi_buf = (unsigned)value >> (length - bi_valid);\n    }\n}\n\n/* ===========================================================================\n * Reverse the first len bits of a code, using straightforward code (a faster\n * method would use a table)\n * IN assertion: 1 <= len <= 15\n */\nlocal unsigned bi_reverse(code, len)\n    unsigned code; /* the value to invert */\n    int len;       /* its bit length */\n{\n    register unsigned res = 0;\n    do {\n        res |= code & 1;\n        code >>= 1, res <<= 1;\n    } while (--len > 0);\n    return res >> 1;\n}\n#endif /* !ASMV || !RISCOS */\n\n/* ===========================================================================\n * Write out any remaining bits in an incomplete byte.\n */\nlocal void bi_windup()\n{\n    if (bi_valid > 8) {\n        PUTSHORT(bi_buf);\n    } else if (bi_valid > 0) {\n        PUTBYTE(bi_buf);\n    }\n    if (flush_flg) {\n        flush_outbuf(out_buf, &out_offset);\n    }\n    bi_buf = 0;\n    bi_valid = 0;\n#ifdef DEBUG\n    bits_sent = (bits_sent+7) & ~7;\n#endif\n}\n\n/* ===========================================================================\n * Copy a stored block to the zip file, storing first the length and its\n * one's complement if requested.\n *\n * Buffer Overwrite fix\n *\n * A buffer flush has been added to fix a bug when encrypting deflated files\n * with embedded \"copied blocks\".  When encrypting, the flush_out() routine\n * modifies its data buffer because encryption is done \"in-place\" in\n * zfwrite(), whereas without encryption, the flush_out() data buffer is\n * left unaltered.  This can be a problem as noted below by the submitter.\n *\n * \"But an exception comes when a block of stored data (data that could not\n * be compressed) is being encrypted. In this case, the data that is passed\n * to zfwrite (and is therefore encrypted-in-place) is actually a block of\n * data from within the sliding input window that is being managed by\n * deflate.c.\n *\n * \"Since part of the sliding input window has now been overwritten by\n * encrypted (and essentially random) data, deflate.c's search for previous\n * text that matches the current text will usually fail but on rare\n * occasions will find a match with something in the encrypted data. This\n * incorrect match then causes incorrect information to be placed in the\n * ZIP file.\"\n *\n * The problem results in the zip file having bad data and so a bad CRC.\n * This does not happen often and to recreate the problem a large file\n * with non-compressable data is needed so that deflate chooses to store the\n * data.  A test file of 400 MB seems large enough to recreate the problem\n * using a command such as\n *     zip -1 -e crcerror.zip testfile.dat\n * maybe half the time.\n *\n * This problem has been fixed by copying the data into the deflate output\n * buffer before calling flush_outbuf(), when encryption is enabled.\n *\n * Thanks to the nice people at WinZip for identifying the problem and\n * passing it on.  Also see Changes.\n *\n * 2006-03-06 EG, CS\n */\nlocal void copy_block(block, len, header)\n    char *block;  /* the input data */\n    unsigned len; /* its length */\n    int header;   /* true if block header must be written */\n{\n    bi_windup();              /* align on byte boundary */\n\n    if (header) {\n        PUTSHORT((ush)len);\n        PUTSHORT((ush)~len);\n#ifdef DEBUG\n        bits_sent += 2*16;\n#endif\n    }\n    if (flush_flg) {\n        flush_outbuf(out_buf, &out_offset);\n        if (key != (char *)NULL) {  /* key is the global password pointer */\n            /* Encryption modifies the data in the output buffer. But the\n             * copied input data must remain intact for further deflate\n             * string matching lookups.  Therefore, the input data is\n             * copied into the compression output buffer for flushing\n             * to the compressed/encrypted output stream.\n             */\n            while(len > 0) {\n                out_offset = (len < out_size ? len : out_size);\n                memcpy(out_buf, block, out_offset);\n                block += out_offset;\n                len -= out_offset;\n                flush_outbuf(out_buf, &out_offset);\n            }\n        } else {\n            /* Without encryption, the output routines do not touch the\n             * written data, so there is no need for an additional copy\n             * operation.\n             */\n            out_offset = len;\n            flush_outbuf(block, &out_offset);\n        }\n    } else if (out_offset + len > out_size) {\n        error(\"output buffer too small for in-memory compression\");\n    } else {\n        memcpy(out_buf + out_offset, block, len);\n        out_offset += len;\n    }\n#ifdef DEBUG\n    bits_sent += (ulg)len<<3;\n#endif\n}\n\n#endif /* !USE_ZLIB */\n"
  },
  {
    "path": "deps/infozip/zip30/ttyio.c",
    "content": "/*\n  ttyio.c - Zip 3\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  ttyio.c\n\n  This file contains routines for doing console input/output, including code\n  for non-echoing input.  It is used by the encryption/decryption code but\n  does not contain any restricted code itself.  This file is shared between\n  Info-ZIP's Zip and UnZip.\n\n  Contains:  echo()         (VMS only)\n             Echon()        (Unix only)\n             Echoff()       (Unix only)\n             screensize()   (Unix only)\n             zgetch()       (Unix, VMS, and non-Unix/VMS versions)\n             getp()         (\"PC,\" Unix/Atari/Be, VMS/VMCMS/MVS)\n\n  ---------------------------------------------------------------------------*/\n\n#define __TTYIO_C       /* identifies this source module */\n\n#include \"zip.h\"\n#include \"crypt.h\"\n\n#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))\n/* Non-echo console/keyboard input is needed for (en/de)cryption's password\n * entry, and for UnZip(SFX)'s MORE and Pause features.\n * (The corresponding #endif is found at the end of this module.)\n */\n\n#include \"ttyio.h\"\n\n#ifndef PUTC\n#  define PUTC putc\n#endif\n\n#ifdef ZIP\n#  ifdef GLOBAL          /* used in Amiga system headers, maybe others too */\n#    undef GLOBAL\n#  endif\n#  define GLOBAL(g) g\n#else\n#  define GLOBAL(g) G.g\n#endif\n\n#if (defined(__ATHEOS__) || defined(__BEOS__))  /* why yes, we do */\n#  define HAVE_TERMIOS_H\n#endif\n\n#ifdef _POSIX_VERSION\n#  ifndef USE_POSIX_TERMIOS\n#    define USE_POSIX_TERMIOS  /* use POSIX style termio (termios) */\n#  endif\n#  ifndef HAVE_TERMIOS_H\n#    define HAVE_TERMIOS_H     /* POSIX termios.h */\n#  endif\n#endif /* _POSIX_VERSION */\n\n#ifdef UNZIP            /* Zip handles this with the unix/configure script */\n#  ifndef _POSIX_VERSION\n#    if (defined(SYSV) || defined(CRAY)) &&  !defined(__MINT__)\n#      ifndef USE_SYSV_TERMIO\n#        define USE_SYSV_TERMIO\n#      endif\n#      ifdef COHERENT\n#        ifndef HAVE_TERMIO_H\n#          define HAVE_TERMIO_H\n#        endif\n#        ifdef HAVE_SYS_TERMIO_H\n#          undef HAVE_SYS_TERMIO_H\n#        endif\n#      else /* !COHERENT */\n#        ifdef HAVE_TERMIO_H\n#          undef HAVE_TERMIO_H\n#        endif\n#        ifndef HAVE_SYS_TERMIO_H\n#           define HAVE_SYS_TERMIO_H\n#        endif\n#      endif /* ?COHERENT */\n#    endif /* (SYSV || CRAY) && !__MINT__ */\n#  endif /* !_POSIX_VERSION */\n#  if !(defined(BSD4_4) || defined(SYSV) || defined(__convexc__))\n#    ifndef NO_FCNTL_H\n#      define NO_FCNTL_H\n#    endif\n#  endif /* !(BSD4_4 || SYSV || __convexc__) */\n#endif /* UNZIP */\n\n#ifdef HAVE_TERMIOS_H\n#  ifndef USE_POSIX_TERMIOS\n#    define USE_POSIX_TERMIOS\n#  endif\n#endif\n\n#if (defined(HAVE_TERMIO_H) || defined(HAVE_SYS_TERMIO_H))\n#  ifndef USE_SYSV_TERMIO\n#    define USE_SYSV_TERMIO\n#  endif\n#endif\n\n#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))\n#  include <sys/ioctl.h>\n#  define GOT_IOCTL_H\n   /* int ioctl OF((int, int, zvoid *));   GRR: may need for some systems */\n#endif\n\n#ifndef HAVE_WORKING_GETCH\n   /* include system support for switching of console echo */\n#  ifdef VMS\n#    include <descrip.h>\n#    include <iodef.h>\n#    include <ttdef.h>\n#    include <starlet.h>\n#    include <ssdef.h>\n#  else /* !VMS */\n#    ifdef HAVE_TERMIOS_H\n#      include <termios.h>\n#      define sgttyb termios\n#      define sg_flags c_lflag\n#      define GTTY(f, s) tcgetattr(f, (zvoid *) s)\n#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (zvoid *) s)\n#    else /* !HAVE_TERMIOS_H */\n#      ifdef USE_SYSV_TERMIO           /* Amdahl, Cray, all SysV? */\n#        ifdef HAVE_TERMIO_H\n#          include <termio.h>\n#        endif\n#        ifdef HAVE_SYS_TERMIO_H\n#          include <sys/termio.h>\n#        endif\n#        ifdef NEED_PTEM\n#          include <sys/stream.h>\n#          include <sys/ptem.h>\n#        endif\n#        define sgttyb termio\n#        define sg_flags c_lflag\n#        define GTTY(f,s) ioctl(f,TCGETA,(zvoid *)s)\n#        define STTY(f,s) ioctl(f,TCSETAW,(zvoid *)s)\n#      else /* !USE_SYSV_TERMIO */\n#        ifndef CMS_MVS\n#          if (!defined(MINIX) && !defined(GOT_IOCTL_H))\n#            include <sys/ioctl.h>\n#          endif\n#          include <sgtty.h>\n#          define GTTY gtty\n#          define STTY stty\n#          ifdef UNZIP\n             /*\n              * XXX : Are these declarations needed at all ????\n              */\n             /*\n              * GRR: let's find out...   Hmmm, appears not...\n             int gtty OF((int, struct sgttyb *));\n             int stty OF((int, struct sgttyb *));\n              */\n#          endif\n#        endif /* !CMS_MVS */\n#      endif /* ?USE_SYSV_TERMIO */\n#    endif /* ?HAVE_TERMIOS_H */\n#    ifndef NO_FCNTL_H\n#      ifndef UNZIP\n#        include <fcntl.h>\n#      endif\n#    else\n       char *ttyname OF((int));\n#    endif\n#  endif /* ?VMS */\n#endif /* !HAVE_WORKING_GETCH */\n\n\n\n#ifndef HAVE_WORKING_GETCH\n#ifdef VMS\n\nstatic struct dsc$descriptor_s DevDesc =\n        {11, DSC$K_DTYPE_T, DSC$K_CLASS_S, \"SYS$COMMAND\"};\n     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */\n\n/*\n * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c\n * and hence on Joe Meadows' file.c code.\n */\nint echo(opt)\n    int opt;\n{\n    /*\n     * For VMS v5.x:\n     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,\n     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6\n     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,\n     *     System Services Reference Manual, pp. sys-23, sys-379\n     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,\n     *     Intro to System Routines, sec. 2.9.2\n     * Greg Roelofs, 15 Aug 91\n     */\n\n    short           DevChan, iosb[4];\n    long            status;\n    unsigned long   ttmode[2];  /* space for 8 bytes */\n\n\n    /* assign a channel to standard input */\n    status = sys$assign(&DevDesc, &DevChan, 0, 0);\n    if (!(status & 1))\n        return status;\n\n    /* use sys$qio and the IO$_SENSEMODE function to determine the current\n     * tty status (for password reading, could use IO$_READVBLK function\n     * instead, but echo on/off will be more general)\n     */\n    status = sys$qiow(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,\n                     ttmode, 8, 0, 0, 0, 0);\n    if (!(status & 1))\n        return status;\n    status = iosb[0];\n    if (!(status & 1))\n        return status;\n\n    /* modify mode buffer to be either NOECHO or ECHO\n     * (depending on function argument opt)\n     */\n    if (opt == 0)   /* off */\n        ttmode[1] |= TT$M_NOECHO;                       /* set NOECHO bit */\n    else\n        ttmode[1] &= ~((unsigned long) TT$M_NOECHO);    /* clear NOECHO bit */\n\n    /* use the IO$_SETMODE function to change the tty status */\n    status = sys$qiow(0, DevChan, IO$_SETMODE, &iosb, 0, 0,\n                     ttmode, 8, 0, 0, 0, 0);\n    if (!(status & 1))\n        return status;\n    status = iosb[0];\n    if (!(status & 1))\n        return status;\n\n    /* deassign the sys$input channel by way of clean-up */\n    status = sys$dassgn(DevChan);\n    if (!(status & 1))\n        return status;\n\n    return SS$_NORMAL;   /* we be happy */\n\n} /* end function echo() */\n\n\n/*\n * Read a single character from keyboard in non-echoing mode (VMS).\n * (returns EOF in case of errors)\n */\nint tt_getch()\n{\n    short           DevChan, iosb[4];\n    long            status;\n    char            kbbuf[16];  /* input buffer with - some - excess length */\n\n    /* assign a channel to standard input */\n    status = sys$assign(&DevDesc, &DevChan, 0, 0);\n    if (!(status & 1))\n        return EOF;\n\n    /* read a single character from SYS$COMMAND (no-echo) and\n     * wait for completion\n     */\n    status = sys$qiow(0,DevChan,\n                      IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,\n                      &iosb, 0, 0,\n                      &kbbuf, 1, 0, 0, 0, 0);\n    if ((status&1) == 1)\n        status = iosb[0];\n\n    /* deassign the sys$input channel by way of clean-up\n     * (for this step, we do not need to check the completion status)\n     */\n    sys$dassgn(DevChan);\n\n    /* return the first char read, or EOF in case the read request failed */\n    return (int)(((status&1) == 1) ? (uch)kbbuf[0] : EOF);\n\n} /* end function tt_getch() */\n\n\n#else /* !VMS:  basically Unix */\n\n\n/* For VM/CMS and MVS, non-echo terminal input is not (yet?) supported. */\n#ifndef CMS_MVS\n\n#ifdef ZIP                      /* moved to globals.h for UnZip */\n   static int echofd=(-1);      /* file descriptor whose echo is off */\n#endif\n\n/*\n * Turn echo off for file descriptor f.  Assumes that f is a tty device.\n */\nvoid Echoff(__G__ f)\n    __GDEF\n    int f;                    /* file descriptor for which to turn echo off */\n{\n    struct sgttyb sg;         /* tty device structure */\n\n    GLOBAL(echofd) = f;\n    GTTY(f, &sg);             /* get settings */\n    sg.sg_flags &= ~ECHO;     /* turn echo off */\n    STTY(f, &sg);\n}\n\n/*\n * Turn echo back on for file descriptor echofd.\n */\nvoid Echon(__G)\n    __GDEF\n{\n    struct sgttyb sg;         /* tty device structure */\n\n    if (GLOBAL(echofd) != -1) {\n        GTTY(GLOBAL(echofd), &sg);    /* get settings */\n        sg.sg_flags |= ECHO;  /* turn echo on */\n        STTY(GLOBAL(echofd), &sg);\n        GLOBAL(echofd) = -1;\n    }\n}\n\n#endif /* !CMS_MVS */\n#endif /* ?VMS */\n\n\n#if (defined(UNZIP) && !defined(FUNZIP))\n\n#ifdef ATH_BEO_UNX\n#ifdef MORE\n\n/*\n * Get the number of lines on the output terminal.  SCO Unix apparently\n * defines TIOCGWINSZ but doesn't support it (!M_UNIX).\n *\n * GRR:  will need to know width of terminal someday, too, to account for\n *       line-wrapping.\n */\n\n#if (defined(TIOCGWINSZ) && !defined(M_UNIX))\n\nint screensize(tt_rows, tt_cols)\n    int *tt_rows;\n    int *tt_cols;\n{\n    struct winsize wsz;\n#ifdef DEBUG_WINSZ\n    static int firsttime = TRUE;\n#endif\n\n    /* see termio(4) under, e.g., SunOS */\n    if (ioctl(1, TIOCGWINSZ, &wsz) == 0) {\n#ifdef DEBUG_WINSZ\n        if (firsttime) {\n            firsttime = FALSE;\n            fprintf(stderr, \"ttyio.c screensize():  ws_row = %d\\n\",\n              wsz.ws_row);\n            fprintf(stderr, \"ttyio.c screensize():  ws_col = %d\\n\",\n              wsz.ws_col);\n        }\n#endif\n        /* number of rows */\n        if (tt_rows != NULL)\n            *tt_rows = (int)((wsz.ws_row > 0) ? wsz.ws_row : 24);\n        /* number of columns */\n        if (tt_cols != NULL)\n            *tt_cols = (int)((wsz.ws_col > 0) ? wsz.ws_col : 80);\n        return 0;    /* signal success */\n    } else {         /* this happens when piping to more(1), for example */\n#ifdef DEBUG_WINSZ\n        if (firsttime) {\n            firsttime = FALSE;\n            fprintf(stderr,\n              \"ttyio.c screensize():  ioctl(TIOCGWINSZ) failed\\n\"));\n        }\n#endif\n        /* VT-100 assumed to be minimal hardware */\n        if (tt_rows != NULL)\n            *tt_rows = 24;\n        if (tt_cols != NULL)\n            *tt_cols = 80;\n        return 1;       /* signal failure */\n    }\n}\n\n#else /* !TIOCGWINSZ: service not available, fall back to semi-bogus method */\n\nint screensize(tt_rows, tt_cols)\n    int *tt_rows;\n    int *tt_cols;\n{\n    char *envptr, *getenv();\n    int n;\n    int errstat = 0;\n\n    /* GRR:  this is overly simplistic, but don't have access to stty/gtty\n     * system anymore\n     */\n    if (tt_rows != NULL) {\n        envptr = getenv(\"LINES\");\n        if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {\n            /* VT-100 assumed to be minimal hardware */\n            *tt_rows = 24;\n            errstat = 1;    /* signal failure */\n        } else {\n            *tt_rows = n;\n        }\n    }\n    if (tt_cols != NULL) {\n        envptr = getenv(\"COLUMNS\");\n        if (envptr == (char *)NULL || (n = atoi(envptr)) < 5) {\n            *tt_cols = 80;\n            errstat = 1;    /* signal failure */\n        } else {\n            *tt_cols = n;\n        }\n    }\n    return errstat;\n}\n\n#endif /* ?(TIOCGWINSZ && !M_UNIX) */\n#endif /* MORE */\n\n\n/*\n * Get a character from the given file descriptor without echo or newline.\n */\nint zgetch(__G__ f)\n    __GDEF\n    int f;                      /* file descriptor from which to read */\n{\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    char oldmin, oldtim;\n#endif\n    char c;\n    struct sgttyb sg;           /* tty device structure */\n\n    GTTY(f, &sg);               /* get settings */\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    oldmin = sg.c_cc[VMIN];     /* save old values */\n    oldtim = sg.c_cc[VTIME];\n    sg.c_cc[VMIN] = 1;          /* need only one char to return read() */\n    sg.c_cc[VTIME] = 0;         /* no timeout */\n    sg.sg_flags &= ~ICANON;     /* canonical mode off */\n#else\n    sg.sg_flags |= CBREAK;      /* cbreak mode on */\n#endif\n    sg.sg_flags &= ~ECHO;       /* turn echo off, too */\n    STTY(f, &sg);               /* set cbreak mode */\n    GLOBAL(echofd) = f;         /* in case ^C hit (not perfect: still CBREAK) */\n\n    read(f, &c, 1);             /* read our character */\n\n#if (defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS))\n    sg.c_cc[VMIN] = oldmin;     /* restore old values */\n    sg.c_cc[VTIME] = oldtim;\n    sg.sg_flags |= ICANON;      /* canonical mode on */\n#else\n    sg.sg_flags &= ~CBREAK;     /* cbreak mode off */\n#endif\n    sg.sg_flags |= ECHO;        /* turn echo on */\n    STTY(f, &sg);               /* restore canonical mode */\n    GLOBAL(echofd) = -1;\n\n    return (int)(uch)c;\n}\n\n\n#else /* !ATH_BEO_UNX */\n#ifndef VMS     /* VMS supplies its own variant of getch() */\n\n\nint zgetch(__G__ f)\n    __GDEF\n    int f;    /* file descriptor from which to read (must be open already) */\n{\n    char c, c2;\n\n/*---------------------------------------------------------------------------\n    Get a character from the given file descriptor without echo; can't fake\n    CBREAK mode (i.e., newline required), but can get rid of all chars up to\n    and including newline.\n  ---------------------------------------------------------------------------*/\n\n    echoff(f);\n    read(f, &c, 1);\n    if (c != '\\n')\n        do {\n            read(f, &c2, 1);   /* throw away all other chars up thru newline */\n        } while (c2 != '\\n');\n    echon();\n    return (int)c;\n}\n\n#endif /* !VMS */\n#endif /* ?ATH_BEO_UNX */\n\n#endif /* UNZIP && !FUNZIP */\n#endif /* !HAVE_WORKING_GETCH */\n\n\n#if CRYPT                       /* getp() is only used with full encryption */\n\n/*\n * Simple compile-time check for source compatibility between\n * zcrypt and ttyio:\n */\n#if (!defined(CR_MAJORVER) || (CR_MAJORVER < 2) || (CR_MINORVER < 7))\n   error:  This Info-ZIP tool requires zcrypt 2.7 or later.\n#endif\n\n/*\n * Get a password of length n-1 or less into *p using the prompt *m.\n * The entered password is not echoed.\n */\n\n#ifdef HAVE_WORKING_GETCH\n/*\n * For the AMIGA, getch() is defined as Agetch(), which is in\n * amiga/filedate.c; SAS/C 6.x provides a getch(), but since Agetch()\n * uses the infrastructure that is already in place in filedate.c, it is\n * smaller.  With this function, echoff() and echon() are not needed.\n *\n * For the MAC, a non-echo macgetch() function is defined in the MacOS\n * specific sources which uses the event handling mechanism of the\n * desktop window manager to get a character from the keyboard.\n *\n * For the other systems in this section, a non-echo getch() function\n * is either contained the C runtime library (conio package), or getch()\n * is defined as an alias for a similar system specific RTL function.\n */\n\n#ifndef WINDLL   /* WINDLL does not support a console interface */\n#ifndef QDOS     /* QDOS supplies a variant of this function */\n\n/* This is the getp() function for all systems (with TTY type user interface)\n * that supply a working `non-echo' getch() function for \"raw\" console input.\n */\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n\n    /* get password */\n    w = \"\";\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* display prompt and flush */\n        fflush(stderr);\n        i = 0;\n        do {                    /* read line, keeping first n characters */\n            if ((c = (char)getch()) == '\\r')\n                c = '\\n';       /* until user hits CR */\n            if (c == 8 || c == 127) {\n                if (i > 0) i--; /* the `backspace' and `del' keys works */\n            }\n            else if (i < n)\n                p[i++] = c;     /* truncate past n */\n        } while (c != '\\n');\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* !QDOS */\n#endif /* !WINDLL */\n\n\n#else /* !HAVE_WORKING_GETCH */\n\n\n#if (defined(ATH_BEO_UNX) || defined(__MINT__))\n\n#ifndef _PATH_TTY\n#  ifdef __MINT__\n#    define _PATH_TTY ttyname(2)\n#  else\n#    define _PATH_TTY \"/dev/tty\"\n#  endif\n#endif\n\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n    int f;                      /* file descriptor for tty device */\n\n#ifdef PASSWD_FROM_STDIN\n    /* Read from stdin. This is unsafe if the password is stored on disk. */\n    f = 0;\n#else\n    /* turn off echo on tty */\n\n    if ((f = open(_PATH_TTY, 0)) == -1)\n        return NULL;\n#endif\n    /* get password */\n    w = \"\";\n    do {\n        fputs(w, stderr);       /* warning if back again */\n        fputs(m, stderr);       /* prompt */\n        fflush(stderr);\n        i = 0;\n        echoff(f);\n        do {                    /* read line, keeping n */\n            read(f, &c, 1);\n            if (i < n)\n                p[i++] = c;\n        } while (c != '\\n');\n        echon();\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n\n#ifndef PASSWD_FROM_STDIN\n    close(f);\n#endif\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* ATH_BEO_UNX || __MINT__ */\n\n\n\n#if (defined(VMS) || defined(CMS_MVS))\n\nchar *getp(__G__ m, p, n)\n    __GDEF\n    ZCONST char *m;             /* prompt for password */\n    char *p;                    /* return value: line input */\n    int n;                      /* bytes available in p[] */\n{\n    char c;                     /* one-byte buffer for read() to use */\n    int i;                      /* number of characters input */\n    char *w;                    /* warning on retry */\n    FILE *f;                    /* file structure for SYS$COMMAND device */\n\n#ifdef PASSWD_FROM_STDIN\n    f = stdin;\n#else\n    if ((f = fopen(ctermid(NULL), \"r\")) == NULL)\n        return NULL;\n#endif\n\n    /* get password */\n    fflush(stdout);\n    w = \"\";\n    do {\n        if (*w)                 /* bug: VMS apparently adds \\n to NULL fputs */\n            fputs(w, stderr);   /* warning if back again */\n        fputs(m, stderr);       /* prompt */\n        fflush(stderr);\n        i = 0;\n        echoff(f);\n        do {                    /* read line, keeping n */\n            if ((c = (char)getc(f)) == '\\r')\n                c = '\\n';\n            if (i < n)\n                p[i++] = c;\n        } while (c != '\\n');\n        echon();\n        PUTC('\\n', stderr);  fflush(stderr);\n        w = \"(line too long--try again)\\n\";\n    } while (p[i-1] != '\\n');\n    p[i-1] = 0;                 /* terminate at newline */\n#ifndef PASSWD_FROM_STDIN\n    fclose(f);\n#endif\n\n    return p;                   /* return pointer to password */\n\n} /* end function getp() */\n\n#endif /* VMS || CMS_MVS */\n#endif /* ?HAVE_WORKING_GETCH */\n#endif /* CRYPT */\n#endif /* CRYPT || (UNZIP && !FUNZIP) */\n"
  },
  {
    "path": "deps/infozip/zip30/ttyio.h",
    "content": "/*\n  ttyio.h - Zip 3\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n   ttyio.h\n */\n\n#ifndef __ttyio_h   /* don't include more than once */\n#define __ttyio_h\n\n#ifndef __crypt_h\n#  include \"crypt.h\"  /* ensure that encryption header file has been seen */\n#endif\n\n#if (CRYPT || (defined(UNZIP) && !defined(FUNZIP)))\n/*\n * Non-echo keyboard/console input support is needed and enabled.\n */\n\n#ifndef __G         /* UnZip only, for now (DLL stuff) */\n#  define __G\n#  define __G__\n#  define __GDEF\n#  define __GPRO    void\n#  define __GPRO__\n#endif\n\n#ifndef ZCONST      /* UnZip only (until have configure script like Zip) */\n#  define ZCONST const\n#endif\n\n#if (defined(MSDOS) || defined(OS2) || defined(WIN32))\n#  ifndef DOS_OS2_W32\n#    define DOS_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(__human68k__))\n#  ifndef DOS_H68_OS2_W32\n#    define DOS_H68_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_OS2_W32) || defined(FLEXOS))\n#  ifndef DOS_FLX_OS2_W32\n#    define DOS_FLX_OS2_W32\n#  endif\n#endif\n\n#if (defined(DOS_H68_OS2_W32) || defined(FLEXOS))\n#  ifndef DOS_FLX_H68_OS2_W32\n#    define DOS_FLX_H68_OS2_W32\n#  endif\n#endif\n\n#if (defined(__ATHEOS__) || defined(__BEOS__) || defined(UNIX))\n#  ifndef ATH_BEO_UNX\n#    define ATH_BEO_UNX\n#  endif\n#endif\n\n#if (defined(VM_CMS) || defined(MVS))\n#  ifndef CMS_MVS\n#    define CMS_MVS\n#  endif\n#endif\n\n\n/* Function prototypes */\n\n/* The following systems supply a `non-echo' character input function \"getch()\"\n * (or an alias) and do not need the echoff() / echon() function pair.\n */\n#ifdef AMIGA\n#  define echoff(f)\n#  define echon()\n#  define getch() Agetch()\n#  define HAVE_WORKING_GETCH\n#endif /* AMIGA */\n\n#ifdef ATARI\n#  define echoff(f)\n#  define echon()\n#  include <osbind.h>\n#  define getch() (Cnecin() & 0x000000ff)\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef MACOS\n#  define echoff(f)\n#  define echon()\n#  define getch() macgetch()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef NLM\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef QDOS\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef RISCOS\n#  define echoff(f)\n#  define echon()\n#  define getch() SWI_OS_ReadC()\n#  define HAVE_WORKING_GETCH\n#endif\n\n#ifdef DOS_H68_OS2_W32\n#  define echoff(f)\n#  define echon()\n#  ifdef WIN32\n#    ifndef getch\n#      define getch() getch_win32()\n#    endif\n#  else /* !WIN32 */\n#    ifdef __EMX__\n#      ifndef getch\n#        define getch() _read_kbd(0, 1, 0)\n#      endif\n#    else /* !__EMX__ */\n#      ifdef __GO32__\n#        include <pc.h>\n#        define getch() getkey()\n#      else /* !__GO32__ */\n#        include <conio.h>\n#      endif /* ?__GO32__ */\n#    endif /* ?__EMX__ */\n#  endif /* ?WIN32 */\n#  define HAVE_WORKING_GETCH\n#endif /* DOS_H68_OS2_W32 */\n\n#ifdef FLEXOS\n#  define echoff(f)\n#  define echon()\n#  define getch() getchar() /* not correct, but may not be on a console */\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* For VM/CMS and MVS, we do not (yet) have any support to switch terminal\n * input echo on and off. The following \"fake\" definitions allow inclusion\n * of crypt support and UnZip's \"pause prompting\" features, but without\n * any echo suppression.\n */\n#ifdef CMS_MVS\n#  define echoff(f)\n#  define echon()\n#endif\n\n#ifdef TANDEM\n#  define echoff(f)\n#  define echon()\n#  define getch() zgetch() /* defined in TANDEMC */\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* The THEOS C runtime library supplies the function conmask() to toggle\n * terminal input echo on (conmask(\"e\")) and off (conmask(\"n\")).  But,\n * since THEOS C RTL also contains a working non-echo getch() function,\n * the echo toggles are not needed.\n */\n#ifdef THEOS\n#  define echoff(f)\n#  define echon()\n#  define HAVE_WORKING_GETCH\n#endif\n\n/* VMS has a single echo() function in ttyio.c to toggle terminal\n * input echo on and off.\n */\n#ifdef VMS\n#  define echoff(f)  echo(0)\n#  define echon()    echo(1)\n#  define getch()    tt_getch()\n#  define FGETCH(f)  tt_getch()\n   int echo OF((int));\n   int tt_getch OF((void));\n#endif\n\n/* For all other systems, ttyio.c supplies the two functions Echoff() and\n * Echon() for suppressing and (re)enabling console input echo.\n */\n#ifndef echoff\n#  define echoff(f)  Echoff(__G__ f)\n#  define echon()    Echon(__G)\n   void Echoff OF((__GPRO__ int f));\n   void Echon OF((__GPRO));\n#endif\n\n/* this stuff is used by MORE and also now by the ctrl-S code; fileio.c only */\n#if (defined(UNZIP) && !defined(FUNZIP))\n#  ifdef HAVE_WORKING_GETCH\n#    define FGETCH(f)  getch()\n#  endif\n#  ifndef FGETCH\n     /* default for all systems where no getch()-like function is available */\n     int zgetch OF((__GPRO__ int f));\n#    define FGETCH(f)  zgetch(__G__ f)\n#  endif\n#endif /* UNZIP && !FUNZIP */\n\n#if (CRYPT && !defined(WINDLL))\n   char *getp OF((__GPRO__ ZCONST char *m, char *p, int n));\n#endif\n\n#else /* !(CRYPT || (UNZIP && !FUNZIP)) */\n\n/*\n * No need for non-echo keyboard/console input; provide dummy definitions.\n */\n#define echoff(f)\n#define echon()\n\n#endif /* ?(CRYPT || (UNZIP && !FUNZIP)) */\n\n#endif /* !__ttyio_h */\n"
  },
  {
    "path": "deps/infozip/zip30/unix/Packaging/README",
    "content": "Solaris packaging\n-----------------\n\nTo generate a Solaris package for Info-ZIP zip utilities,\nfirst see the top level INSTALL and README files.  Do a\n\"make solaris\", which will automatically build two Solaris\ninstallable package files for the package, IZzip.\n\n   IZzip     -- Solaris installable package in directory format.\n   IZzip_$(arch).pkg -- Solaris installable package in \"stream\" format.\n\n   Where:  $(arch) := system architecture, currently i386, sparc, or ppc.\n                      (use \"uname -p\" to determine)\n\nThe \".pkg\" file is a single file datastream that can be compressed\nand/or ftp'd.  This is the recommended form, because all required\nfiles are resident in the archive, and it is easily distributed.\n\nTo install, simply:\n\n    1)  copy the package to the target system's /tmp directory.\n    2)  login or su to root\n    3)  pkgadd -d /tmp/IZzip_$(arch).pkg\n    4)  add /opt/Info-ZIP/IZzip/bin to PATH\n    5)  add /opt/Info-ZIP/IZzip/man to MANPATH\n\nThis works for both SPARC and x86.\n\nOngoing maintenance:\n\n  Keep the files, \"prototype\" and \"pkginfo.in\" up to date.\n  Observe variable substitutions made by \"Makefile\".\n  See manpages for pkginfo(1), pkginfo(4), pkgmk(1), pkgproto(1)\n\nVariations:\n\n  If you wish the base directory to be set to something other than\n  /opt/Info-ZIP, change the setting BASEDIR in pkginfo.in and\n  re-run the make.\n\n\n-John Bush (John.Bush@East.Sun.COM)\n July 20, 1996\n\n"
  },
  {
    "path": "deps/infozip/zip30/unix/Packaging/pkginfo.in",
    "content": "PKG=IZzip\nNAME=Info-ZIP Zip Utilities\nCATEGORY=application\nVENDOR=Info-ZIP\nEMAIL=http://info-zip.org/zip-bug.html\nHOTLINE=http://info-zip.org/zip-bug.html\nDESC=Copyrighted FREEWARE.  See README, WHERE, and docs in pkg's doc dir.\nCLASSES=none\nBASEDIR=/opt/Info-ZIP\n#BASEDIR=/usr/local\nVERSION=\".VERSION.\"\nPSTAMP=\".PSTAMP.\"\nARCH=\".ARCH.\"\n"
  },
  {
    "path": "deps/infozip/zip30/unix/Packaging/postinstall",
    "content": "#!/bin/sh\n#\n# Info-ZIP Zip post-installation script.\n#\n# Last revised: 2007-09-29 SMS.  Zip 3.0.\n#\n# Post installation script (simply inform installer about PATH etc)\n#\necho ''\necho 'Installation is complete.  Users should adjust their environment'\necho 'variables to include these directories:'\necho \"   PATH:    ${BASEDIR}/${PKG}/bin\"\necho \"   MANPATH: ${BASEDIR}/${PKG}/man\"\necho ''\necho \"Commands like the following may be added to a user's shell start-up\"\necho 'file (.cshrc, .login, .profile, ...) to do this:'\necho ''\necho '   For a Bourne-like shell:'\necho \"      PATH=\\\"\\${PATH}:${BASEDIR}/${PKG}/bin\\\"\"\necho \"      MANPATH=\\\"\\${MANPATH}:${BASEDIR}/${PKG}/man\\\"\"\necho '      export PATH MANPATH'\necho ''\necho '   For a C shell:'\necho \"      setenv PATH \\\"\\${PATH}:${BASEDIR}/${PKG}/bin\\\"\"\necho \"      setenv MANPATH \\\"\\${MANPATH}:${BASEDIR}/${PKG}/man\\\"\"\necho ''\necho \"See the files under ${BASEDIR}/${PKG}/doc for more information.\"\necho ''\nexit 0\n"
  },
  {
    "path": "deps/infozip/zip30/unix/Packaging/preinstall.in",
    "content": "#!/bin/sh\n#\n# Info-ZIP Zip pre-installation script.\n#\n# Last revised: 2007-09-29 SMS.  Zip 3.0.\n#\n# pkgadd should set a good PATH, but just in case, ...\nPATH=\"/sbin:/usr/bin:${PATH}\"\nexport PATH\necho ''\necho 'Please report problems to Info-ZIP using:'\necho ''\necho '      http://info-zip.org/zip-bug.html'\necho ''\narch=`uname -p`\nif [ \"arch_${arch}\" != \"arch_.ARCH.\" ]; then\n   echo \"This product MUST be installed on a Solaris \\\".ARCH.\\\" system.\"\n   echo \"This system appears to have \\\"${arch}\\\" architecture, not \\\".ARCH.\\\".\"\n   echo \"Please install the version for the \\\".ARCH.\\\" architecture.\"\n   echo 'Aborting installation...'\n   returncode=1\nelse\n   echo \"Installing on \\\".ARCH.\\\" architecture...\"\n   returncode=0\nfi\necho ''\nsleep 4\nexit ${returncode:-1}\n#\n"
  },
  {
    "path": "deps/infozip/zip30/unix/Packaging/prototype",
    "content": "d none $BASEDIR 0755 root bin\nd none $PKG 0755 root bin\nd none $PKG/doc 0755 root bin\nf none $PKG/doc/BUGS=BUGS 0644 root bin\nf none $PKG/doc/CHANGES=CHANGES 0644 root bin\nf none $PKG/doc/INSTALL=INSTALL 0644 root bin\nf none $PKG/doc/LICENSE=LICENSE 0644 root bin\nf none $PKG/doc/README=README 0644 root bin\nf none $PKG/doc/TODO=TODO 0644 root bin\nf none $PKG/doc/USexport.msg=USexport.msg 0644 root bin\nf none $PKG/doc/WHATSNEW=WHATSNEW 0644 root bin\nf none $PKG/doc/WHERE=WHERE 0644 root bin\nf none $PKG/doc/zip.txt=zip.txt 0644 root bin\nd none $PKG/man 0755 root bin\nd none $PKG/man/man1 0755 root bin\nf none $PKG/man/man1/zip.1=man/zip.1 0644 root bin\nf none $PKG/man/man1/zipcloak.1=man/zipcloak.1 0644 root bin\nf none $PKG/man/man1/zipnote.1=man/zipnote.1 0644 root bin\nf none $PKG/man/man1/zipsplit.1=man/zipsplit.1 0644 root bin\nd none $PKG/bin 0755 root bin\nf none $PKG/bin/zip=zip 0755 root bin\nf none $PKG/bin/zipcloak=zipcloak 0755 root bin\nf none $PKG/bin/zipnote=zipnote 0755 root bin\nf none $PKG/bin/zipsplit=zipsplit 0755 root bin\ni README\ni pkginfo\ni prototype\ni preinstall\ni postinstall\n"
  },
  {
    "path": "deps/infozip/zip30/unix/README.OS390",
    "content": "\nOS/390 is IBM's follow-on to MVS and includes a POSIX, XOPEN,\nXPG4, build environment, a Unix-style filesystem (called HFS), and\na POSIX (Born) shell.  This port uses this environment and is a fairly\nstraight-forward port of ZIP's Unix port - but uses the existing EBCDIC\ncode.  This port does not work with non-HFS (traditional MVS)\nfilesystems.\n\nI believe all my changes are isolated with #ifdef's.\n\nHere's some text which might be useful for an OS390 README or\nthe manual.\n\nZIP for OS390 HFS datasets\n--------------------------\nAllows you to create ZIP archives from the OS/390 OpenEdition\ncommand prompt.  This port uses standard Unix-style I/O routines\nand only works with HFS files.\n\nUsage\n-----\nBy default, ZIP does not perform character-set translation, but has\noptions to make it easy to convert text files to be compatible with\nother systems\n  zip   zipfile list         # add the files in 'list' to archive 'zipfile'\n  zip -a zipfile list        # same as above, but translate files to ASCII\n  zip -al zipfile list       # same as above, translate linefeeds to DOS style\n  zip -all zipfile list      # same as '-a', translate linefeeds to UNIX style\n\nBuild process\n-------------\nAssuming GNU make is available in your path and is called \"gmake\" (See\nthe  notes on Makefile changes below) and a C compiler is available as\n\"cc\",  then type\n  gmake -f unix/Makefile MAKE=gmake os390\n\nIf GNU make is not available, the existing makefile can create zip, but will\nerror on the other executable (zipsplit, zipcloak, zipnote) if you type\n  make -f unix/Makefile os390\n\nOverview of Changes\n-------------------\nThe OS/390 port is treated as a variant of the Unix port.  EBCDIC support\nwas already implemented for CMS/MVS-batch ports.  The specific changes I\nmade are summarized below.\n\nunix/Makefile - zip uses a unusual _.o target which IBM's make can't handle.\nSince the Makefile has a macro called MAKE that is used for a recursive\ncall to make, I changed the MACRO to call \"gmake\" - GNU's make - which\ncan handle the _.o target.  If you don't have GNU make, you can\nworkaround by manually applying symlinks from whatever.c to whatever_.c.\nAlternatively, the whatever_.o files could be explicitely added for os390.\n\nI added an os390 target with appropriate defines.\n\nzipup.c - added code (#ifdef OS390) to convert test to ASCII if -a flag\nwas set.\n\nzip.c - changed logic which always used DOS-style newlines when -a was\nset to be consistent with other port (DOS newlines if -l option)\n\nzipfile.c - miscellaneous changes to force storing file names and\ndescriptions in ASCII in the zip directory. This makes zip files\nportable  across all platforms. This in turn meant names did not\nneed to be translated when displaying messages.\n\nzip.h - strtoasc was missing a closing parenthesis.\n\nebcdic.h - changed translation table to be consistent with current IBM\nrecommendations - exact same changes to ebcdic.h as in my unzip port.\n\ntailor.h - define huge/far/near to be empty\n\nunix/unix.c - substantial changes to deal with mode flags.  Under\nthe current XOPEN standards, some of the traditional unix file mode\nbits need not be in fixed locations, but standard access macros must be\navailable to access the values.  The old unix.c code just picked up these\nvalues and saved them as-is where unzip interpreted them.  Existing\nUnix system provided the macros for XOPEN compliance, but left the flags\nin their traditional locations.  OS/390 has a brand new filesystem which\nis XOPEN compliant without revealing the positions of these flags.\nTo create the bitmask in the same format unzip expects, the macros are\ntested one-by-one to set the appropriate bits.  This same logic should\nwork on any XOPEN system, but takes more instructions (I did test this\nlogic on Linux).\n"
  },
  {
    "path": "deps/infozip/zip30/unix/configure",
    "content": ":\n#!/bin/sh -x\n# The above : is necessary on some buggy systems.\n\n# configure: Guess values for system-dependent variables\n# Output the flag definitions to the file \"flags\".\n#\n# Parameters: $1 = $CC, $2 = $CFLAGS, $3 = $IZ_BZIP2\n#\n# This file is typically called from Makefile rather than executed\n# from the command line.\n#\n# To construct zip automatically using this file, type\n# \"make -f unix/Makefile generic\".\n# If this fails, then type \"make list\" to get a list of special targets.\n\ntrap \"rm -f conftest* core a.out; exit 1\" 1 2 3 15\n\nCC=${1-cc}\nCFLAGS=${2-\"-I. -DUNIX\"}\nLFLAGS1=''\nLFLAGS2=''\nLN=\"ln -s\"\n\nCFLAGS_OPT=''\n\n# bzip2\nIZ_BZIP2=${3-}\nCFLAGS_BZ=''\n\n\necho 'Check C compiler type (optimization options)'\n# Sun C?\ncat > conftest.c << _EOF_\nint main()\n{\n#ifndef __SUNPRO_C\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\nif test $? -eq 0; then\n  CFLAGS_OPT='-xO3'\n  echo \"  Sun C ($CFLAGS_OPT)\"\nelse\n  # Tru64 DEC/Compaq/HP C?\n  cat > conftest.c << _EOF_\nint main()\n{\n#ifndef __DECC\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n  $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n  if test $? -eq 0; then\n    CFLAGS_OPT='-O3'\n    echo \"  DEC C ($CFLAGS_OPT)\"\n  else\n    # HP-UX HP C?\n    cat > conftest.c << _EOF_\nint main()\n{\n#ifdef __GNUC__\n   bad code\n#endif\n#ifndef __hpux\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n    $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n    if test $? -eq 0; then\n      # HP-UX, not GCC.  Lame bundled or real ANSI compiler?\n      CFLAGS_OPT_TRY=\"+O3 +Onolimit\"\n      $CC $CFLAGS $CFLAGS_OPT_TRY -c conftest.c 2>&1 | \\\n       grep '(Bundled)' > /dev/null\n      if test $? -ne 0; then\n        CFLAGS_OPT=\"$CFLAGS_OPT_TRY\"\n        echo \"  HP-UX ANSI C ($CFLAGS_OPT)\"\n      else\n        echo '  HP-UX Bundled C (no opt)'\n      fi\n    else\n      # GNU C?\n      cat > conftest.c << _EOF_\nint main()\n{\n#ifndef __GNUC__\n   bad code\n#endif\n   return 0;\n}\n_EOF_\n      $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n      if test $? -eq 0; then\n        CFLAGS_OPT='-O3'\n        echo \"  GNU C ($CFLAGS_OPT)\"\n        # Special Mac OS X shared library \"ld\" option?\n        if test ` uname -s 2> /dev/null ` = 'Darwin'; then\n          lf='-Wl,-search_paths_first'\n          $CC $CFLAGS $lf conftest.c > /dev/null 2>/dev/null\n          if test $? -eq 0; then\n            LFLAGS2=\"${LFLAGS2} ${lf}\"\n          fi\n          rm -f conftest\n        fi\n      else\n        CFLAGS_OPT='-O'\n        echo \"  Other-unknown C ($CFLAGS_OPT)\"\n      fi\n    fi\n  fi\nfi\n\n# optimization flags\nif test -n \"${CFLAGS_OPT}\"; then\n  CFLAGS=\"${CFLAGS} ${CFLAGS_OPT}\"\n  CFLAGS_BZ=\"${CFLAGS_BZ} ${CFLAGS_OPT}\"\nfi\n\n\n# bzip2\n\necho \"Check bzip2 support\"\nCC_BZ=\"${CC}\"\nLIB_BZ=''\nif test -n \"${IZ_BZIP2}\"; then\n  echo \"  Check for bzip2 compiled library in IZ_BZIP2 (${IZ_BZIP2})\"\n  if test -f \"${IZ_BZIP2}/libbz2.a\"; then\n#\n#   A bzip2 library built with BZ_NO_STDIO should have an\n#   unresolved external, \"bz_internal_error\".  The default,\n#   full-function library will not mention it.\n#\n    nm ${IZ_BZIP2}/libbz2.a | grep bz_internal_error > /dev/null\n    if test $? -eq 0; then\n      echo \"    Found bzip2 BZ_NO_STDIO library, ${IZ_BZIP2}/libbz2.a\"\n    else\n      echo \"    Found bzip2 library, ${IZ_BZIP2}/libbz2.a,\"\n      echo \"      but library not compiled with BZ_NO_STDIO\"\n      echo \"    WARNING:  We recommend using a bzip2 library compiled\"\n      echo \"      with BZ_NO_STDIO defined for proper error handling\"\n      echo \"    Please see the Zip installation instructions in bzip2/install.txt\"\n      echo \"    Continuing anyway with standard bzip2 library...\"\n    fi\n    if test -f \"${IZ_BZIP2}/bzlib.h\"; then\n      CFLAGS=\"${CFLAGS} -I${IZ_BZIP2} -DBZIP2_SUPPORT\"\n      LFLAGS2=\"${LFLAGS2} -L${IZ_BZIP2} -lbz2\"\n      echo \"-- Found bzip2 library - linking in bzip2\"\n    else\n      echo \"    ${IZ_BZIP2}/bzlib.h not found\"\n      echo \"-- Since IZ_BZIP2 defined, skipping OS and bzip2 dir checks - no bzip2\"\n    fi\n  else\n    echo \"    ${IZ_BZIP2}/libbz2.a not found\"\n    echo \"-- Since IZ_BZIP2 defined, skipping OS and bzip2 checks - no bzip2\"\n  fi\nelse\n  echo \"  Check for bzip2 in bzip2 directory\"\n  IZ_BZIP2=bzip2\n  if test -f \"${IZ_BZIP2}/libbz2.a\"; then\n    nm ${IZ_BZIP2}/libbz2.a | grep bz_internal_error > /dev/null\n    if test $? -eq 0; then\n      echo \"    Found bzip2 BZ_NO_STDIO library in bzip2 directory\"\n    else\n      echo \"    Found bzip2 library in bzip2 directory,\"\n      echo \"      but not built with the BZ_NO_STDIO option\"\n      echo \"    WARNING:  We recommend using a bzip2 library compiled\"\n      echo \"      with BZ_NO_STDIO defined for proper error handling\"\n      echo \"    Please see the Zip installation instructions\"\n      echo \"    Continuing anyway with standard bzip2 library...\"\n    fi\n  fi\n  if test -f \"bzip2/bzlib.h\" -a -f \"bzip2/libbz2.a\"; then\n    CFLAGS=\"${CFLAGS} -I${IZ_BZIP2} -DBZIP2_SUPPORT\"\n    LFLAGS2=\"${LFLAGS2} -Lbzip2 -lbz2\"\n    echo \"-- Found bzip2 library - linking in bzip2\"\n  else\n    if test -f \"bzip2/bzlib.c\" -a -f \"bzip2/bzlib.h\"; then\n      echo \"-- No library, but found bzip2 source in bzip2 directory\"\n      echo \"-- Will try to build bzip2 library from source and link in\"\n#\n# Arrange to build a BZ_NO_STDIO bzip2 object library using the\n# same compiler and optimization options as used for Zip, and\n# to compile and link Zip with bzip2.\n#\n      CFLAGS_BZ=\"${CFLAGS_BZ} -DBZ_NO_STDIO\"\n      LIB_BZ=\"bzip2/libbz2.a\"\n      CFLAGS=\"${CFLAGS} -Ibzip2 -DBZIP2_SUPPORT\"\n      LFLAGS2=\"${LFLAGS2} -Lbzip2 -lbz2\"\n    else\n      echo \"  Check if OS already has bzip2 library installed\"\n      cat > conftest.c << _EOF_\n#include \"bzlib.h\"\nint main()\n{\n  bz_stream strm;\n  BZ2_bzCompressEnd(&strm);\n  return 0;\n}\n_EOF_\n      $CC $CFLAGS -o conftest conftest.c -lbz2 > /dev/null 2>/dev/null\n      if test $? -eq 0; then\n        echo \"-- OS supports bzip2 - linking in bzip2\"\n        CFLAGS=\"${CFLAGS} -DBZIP2_SUPPORT\"\n        LFLAGS2=\"${LFLAGS2} -lbz2\"\n      else\n        echo \"-- Either bzlib.h or libbz2.a not found - no bzip2\"\n      fi\n    fi\n  fi\nfi\n\n\necho Check for the C preprocessor\n# on SVR4, cc -E does not produce correct assembler files. Need /lib/cpp.\nCPP=\"${CC} -E\"\n# solaris as(1) needs -P, maybe others as well ?\n[ -f /usr/ccs/lib/cpp ] && CPP=\"/usr/ccs/lib/cpp -P\"\n[ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp\n[ -f /lib/cpp ] && CPP=/lib/cpp\n[ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp\n[ -f /xenix ] && CPP=\"${CC} -E\"\n[ -f /lynx.os ] && CPP=\"${CC} -E\"\n\necho \"#include <stdio.h>\" > conftest.c\n$CPP conftest.c >/dev/null 2>/dev/null || CPP=\"${CC} -E\"\n\n\necho Check if we can use asm code\nOBJA=\"\"\nOCRCU8=\"\"\nif eval \"$CPP match.S > _match.s 2>/dev/null\"; then\n  if test ! -s _match.s || grep error < _match.s > /dev/null; then\n    :\n  elif eval \"$CC -c _match.s >/dev/null 2>/dev/null\" && [ -f _match.o ]; then\n    CFLAGS=\"${CFLAGS} -DASMV\"\n    OBJA=\"match.o\"\n    echo \"int foo() { return 0;}\" > conftest.c\n    $CC -c conftest.c >/dev/null 2>/dev/null\n    echo Check if compiler generates underlines\n    nm conftest.o | grep \"(^|[^_])foo\" >/dev/null 2>/dev/null\n    [ $? -eq 0 ] && CPP=\"${CPP} -DNO_UNDERLINE\"\n    if eval \"$CPP crc_i386.S > _crc_i386.s 2>/dev/null\"; then\n      if eval \"$CC -c _crc_i386.s >/dev/null 2>/dev/null\" && [ -f _crc_i386.o ]\n      then\n        OBJA=\"$OBJA crc_i386.o\"\n        OCRCU8=\"crc_i386.o\"\n        CFLAGS=\"${CFLAGS} -DASM_CRC\"\n      fi\n    fi\n  fi\nfi\nrm -f _match.s _match.o _crc_i386.s _crc_i386.o\n\n\n# ANSI options for compilers that don't have __STDC__ defined by default\n# Currently HPUX, pyramid, Dynix, AIX, OSF/1 and ultrix\n\necho Check for ANSI options\ncat > conftest.c << _EOF_\nint main()\n{\n#ifndef __STDC__\n   forget it\n#endif\n   return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  for OPT in -Ae -Xa -qlanglvl=ansi -std1 -std\n  do\n    $CC $CFLAGS $OPT -c conftest.c > /dev/null 2>/dev/null\n    [ $? -eq 0 ] && CFLAGS=\"${CFLAGS} ${OPT}\" && break\n  done\nfi\n\n\necho Check for prototypes\necho \"int main(int argc, char *argv[]) { return 0; }\" > conftest.c\n$CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_PROTO\"\n\n# const check currently handles mips cc and non ANSI compilers.\n# does it need more ?\necho Check the handling of const\ncat > conftest.c << _EOF_\ntypedef int charset[2];\nint main()\n{\n  const charset x;\n  const char *foo;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_CONST\"\n\n\necho Check for time_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\n#include <time.h>\nint main()\n{\n  time_t t;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_TIME_T\"\n\n\necho Check for size_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\nint main()\n{\n  size_t s;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_SIZE_T\"\n\n\necho Check for off_t\ncat > conftest.c << _EOF_\n#include <sys/types.h>\nint main()\n{\n  off_t s;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_OFF_T\"\n\n\necho Check size of UIDs and GIDs\necho \"(Now zip stores variable size UIDs/GIDs using a new extra field.  This\"\necho \" tests if this OS uses 16-bit UIDs/GIDs and so if the old 16-bit storage\"\necho \" should also be used for backward compatibility.)\"\n# Added 2008-04-15 CS\ncat > conftest.c << _EOF_\n# define _LARGEFILE_SOURCE          /* some OSes need this for fseeko */\n# define _LARGEFILE64_SOURCE\n# define _FILE_OFFSET_BITS 64       /* select default interface as 64 bit */\n# define _LARGE_FILES               /* some OSes need this for 64-bit off_t */\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n#include <stdio.h>\nint main()\n{\n  struct stat s;\n\n  printf(\"  s.st_uid is %u bytes\\n\", sizeof(s.st_uid));\n  printf(\"  s.st_gid is %u bytes\\n\", sizeof(s.st_gid));\n\n  /* see if have 16-bit UID */\n  if (sizeof(s.st_uid) != 2) {\n    return 1;\n  }\n  /* see if have 16-bit GID */\n  if (sizeof(s.st_gid) != 2) {\n    return 2;\n  }\n  return 3;\n}\n_EOF_\n# compile it\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  echo -- UID/GID test failed on compile - disabling old 16-bit UID/GID support\n  CFLAGS=\"${CFLAGS} -DUIDGID_NOT_16BIT\"\nelse\n# run it\n  ./conftest\n  r=$?\n  if [ $r -eq 1 ]; then\n    echo -- UID not 2 bytes - disabling old 16-bit UID/GID support\n    CFLAGS=\"${CFLAGS} -DUIDGID_NOT_16BIT\"\n  elif [ $r -eq 2 ]; then\n    echo -- GID not 2 bytes - disabling old 16-bit UID/GID support\n    CFLAGS=\"${CFLAGS} -DUIDGID_NOT_16BIT\"\n  elif [ $r -eq 3 ]; then\n    echo -- 16-bit UIDs and GIDs - keeping old 16-bit UID/GID support\n  else\n    echo -- test failed - conftest returned $r - disabling old 16-bit UID/GID support\n    CFLAGS=\"${CFLAGS} -DUIDGID_NOT_16BIT\"\n  fi\nfi\n\n\n# Now we set the 64-bit file environment and check the size of off_t\n# Added 11/4/2003 EG\n# Revised 8/12/2004 EG\n\necho Check for Large File Support\ncat > conftest.c << _EOF_\n# define _LARGEFILE_SOURCE       /* some OSes need this for fseeko */\n# define _LARGEFILE64_SOURCE\n# define _FILE_OFFSET_BITS 64       /* select default interface as 64 bit */\n# define _LARGE_FILES        /* some OSes need this for 64-bit off_t */\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n#include <stdio.h>\nint main()\n{\n  off_t offset;\n  struct stat s;\n  /* see if have 64-bit off_t */\n  if (sizeof(offset) < 8)\n    return 1;\n  printf(\"  off_t is %d bytes\\n\", sizeof(off_t));\n  /* see if have 64-bit stat */\n  if (sizeof(s.st_size) < 8) {\n    printf(\"  s.st_size is %d bytes\\n\", sizeof(s.st_size));\n    return 2;\n  }\n  return 3;\n}\n_EOF_\n# compile it\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  echo -- no Large File Support\nelse\n# run it\n  ./conftest\n  r=$?\n  if [ $r -eq 1 ]; then\n    echo -- no Large File Support - no 64-bit off_t\n  elif [ $r -eq 2 ]; then\n    echo -- no Large File Support - no 64-bit stat\n  elif [ $r -eq 3 ]; then\n    echo -- yes we have Large File Support!\n    CFLAGS=\"${CFLAGS} -DLARGE_FILE_SUPPORT\"\n  else\n    echo -- no Large File Support - conftest returned $r\n  fi\nfi\n\n\n# Check for wide char for Unicode support\n# Added 11/24/2005 EG\n\necho Check for wide char support\ncat > conftest.c << _EOF_\n#include <stdlib.h>\n#include <stdio.h>\nint main()\n{\n  int wsize;\n  wchar_t *wide_string;\n\n  if ((wide_string = (wchar_t *)malloc(4 * sizeof(wchar_t))) == NULL) {\n    return 0;\n  }\n  /* get wide string */\n  wsize = mbstowcs(wide_string, \"foo\", 3);\n  wide_string[wsize] = (wchar_t) NULL;\n  return 1;\n}\n_EOF_\n# compile it\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\n# OCRCU8 is used by all utilities if Unicode is enabled\n# OCRCTB is only used by zipcloak\nif [ $? -ne 0 ]; then\n  echo -- no Unicode support\n  OCRCU8=\"\"\n  OCRCTB=\"crc32_.o\"\nelse\n# have wide char support\n  echo -- have wchar_t - enabling Unicode support\n  CFLAGS=\"${CFLAGS} -DUNICODE_SUPPORT\"\n  OCRCU8=\"crc32_.o ${OCRCU8}\"\n  OCRCTB=\"\"\nfi\n\n\n# from configure 2.4i (Onno) 12/5/04\n\necho Check for gcc no-builtin flag\n# -fno-builtin since version 2\ncat > conftest.c << _EOF_\nint main()\n{\n#if __GNUC__ >= 2\n   return 0;\n#else\n   forget it\n#endif\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -eq 0 ] && BFLAG=\"-fno-builtin\"\n\n\n# Check for missing functions\n# add NO_'function_name' to flags if missing\n\nfor func in rmdir strchr strrchr rename mktemp mktime mkstemp\ndo\n  echo Check for $func\n  echo \"int main(){ $func(); return 0; }\" > conftest.c\n  $CC $BFLAG -o conftest conftest.c >/dev/null 2>/dev/null\n  [ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_`echo $func | tr '[a-z]' '[A-Z]'`\"\ndone\n\n\necho Check for memset\necho \"int main(){ char k; memset(&k,0,0); return 0; }\" > conftest.c\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DZMEM\"\n\n\necho Check for memmove\ncat > conftest.c << _EOF_\n#include <string.h>\nint main() { int a; int b = 0; memmove( &a, &b, sizeof( a)); return a; }\n_EOF_\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNEED_MEMMOVE\"\n\n\necho Check for strerror\ncat > conftest.c << _EOF_\n#include <string.h>\nint main() { strerror( 0); return 0; }\n_EOF_\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNEED_STRERROR\"\n\necho Check for errno declaration\ncat > conftest.c << _EOF_\n#include <errno.h>\nmain()\n{\n  errno = 0;\n  return 0;\n}\n_EOF_\n$CC $CFLAGS -c conftest.c >/dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_ERRNO\"\n\n\necho Check for directory libraries\ncat > conftest.c << _EOF_\nint main() { return closedir(opendir(\".\")); }\n_EOF_\n\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  OPT=\"\"\n  for lib in ndir dir ucb bsd BSD PW x dirent\n  do\n    $CC -o conftest conftest.c -l$lib >/dev/null 2>/dev/null\n    [ $? -eq 0 ] && OPT=-l$lib && break\n  done\n  if [ ${OPT} ]; then\n    LFLAGS2=\"${LFLAGS2} ${OPT}\"\n  else\n    CFLAGS=\"${CFLAGS} -DNO_DIR\"\n  fi\nfi\n\n\n# Dynix/ptx 1.3 needed this\n\necho Check for readlink\necho \"int main(){ return readlink(); }\" > conftest.c\n$CC -o conftest conftest.c >/dev/null 2>/dev/null\nif [ $? -ne 0 ]; then\n  $CC -o conftest conftest.c -lseq >/dev/null 2>/dev/null\n  [ $? -eq 0 ] && LFLAGS2=\"${LFLAGS2} -lseq\"\nfi\n\n\necho Check for directory include file\nOPT=\"\"\nfor inc in dirent.h sys/ndir.h ndir.h sys/dir.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c > /dev/null 2>/dev/null\n   [ $? -eq 0 ] && OPT=\"-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`\" && break\ndone\nCFLAGS=\"${CFLAGS} ${OPT}\"\n\n\necho Check for nonexistent include files\nfor inc in stdlib.h stddef.h unistd.h fcntl.h string.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c >/dev/null 2>/dev/null\n   [ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_`echo $inc | tr '[a-z]./' '[A-Z]__'`\"\ndone\n\n\necho Check for term I/O include file\nOPT=\"\"\nfor inc in termios.h termio.h sgtty.h\ndo\n   echo \"#include <$inc>\" > conftest.c\n   $CPP conftest.c > /dev/null 2>/dev/null\n   [ $? -eq 0 ] && OPT=\"-DHAVE_`echo $inc | tr '[a-z]./' '[A-Z]__'`\" && break\ndone\nCFLAGS=\"${CFLAGS} ${OPT}\"\n\n\n# needed for AIX (and others ?) when mmap is used\n\necho Check for valloc\ncat > conftest.c << _EOF_\nmain()\n{\n#ifdef MMAP\n    valloc();\n#endif\n}\n_EOF_\n$CC ${CFLAGS} -c conftest.c > /dev/null 2>/dev/null\n[ $? -ne 0 ] && CFLAGS=\"${CFLAGS} -DNO_VALLOC\"\n\n\necho Check for /usr/local/bin and /usr/local/man\nBINDIR=$HOME/bin\n[ -d /usr/local/bin ] && BINDIR=/usr/local/bin\n\nMANDIR=manl\n[ -d /usr/man/manl ]       && MANDIR=/usr/man/manl\n[ -d /usr/local/man/manl ] && MANDIR=/usr/local/man/manl\n[ -d /usr/local/man/man1 ] && MANDIR=/usr/local/man/man1\n\n\necho Check for OS-specific flags\nif [ -f /usr/bin/hostinfo ]; then\n  if /usr/bin/hostinfo | grep NeXT > /dev/null; then\n    CFLAGS=\"${CFLAGS} -posix\"\n    LFLAGS1=\"${LFLAGS1} -posix -object\"\n  fi\n# XXX ATT6300, Cray\nelif [ -f /xenix ]; then\n  if uname -p | grep 286 > /dev/null; then\n    CFLAGS=\"${CFLAGS} -LARGE -Mel2 -DMEDIUM_MEM -DWSIZE=16384 -DNO_VOID\"\n    LFLAGS1=\"${LFLAGS1} -LARGE -Mel2\"\n  fi\nelif uname -X >/dev/null 2>/dev/null; then\n# SCO shared library check\n  echo \"int main() { return 0;}\" > conftest.c\n  $CC -o conftest conftest.c -lc_s -nointl >/dev/null 2> /dev/null\n  [ $? -eq 0 ] && LFLAGS2=\"-lc_s -nointl\"\nelse\n  SYSTEM=`uname -s 2>/dev/null` || SYSTEM=\"unknown\"\n  echo \"int main() { return 0;}\" > conftest.c\n  case $SYSTEM in\n     OSF1|ULTRIX)\n        echo Check for -Olimit option\n        $CC ${CFLAGS} -Olimit 1000 -o conftest conftest.c >/dev/null 2>/dev/null\n        [ $? -eq 0 ] && CFLAGS=\"${CFLAGS} -Olimit 1000\"\n        ;;\n###     HP-UX)\n###        echo Check for +Onolimit option\n###        $CC ${CFLAGS} +Onolimit -o conftest conftest.c >/dev/null 2>/dev/null\n###        [ $? -eq 0 ] && CFLAGS=\"${CFLAGS} +Onolimit\"\n###        ;;\n###     SunOS)\n###        CFLAGS=\"${CFLAGS} -D_FILE_OFFSET_BITS=64\"\n###        ;;\n  esac\nfi\n\n\necho Check for symbolic links\nln -s /dev/null null > /dev/null 2>/dev/null || LN=ln\n\n\nrm -f a.out conftest.c conftest.o conftest null\n\necho CC=\\\"${CC}\\\" CFLAGS=\\\"${CFLAGS}\\\"  CPP=\\\"${CPP}\\\" OBJA=\\\"${OBJA}\\\" \\\n       OCRCU8=\\\"${OCRCU8}\\\" OCRCTB=\\\"${OCRCTB}\\\" \\\n       BINDIR=${BINDIR} MANDIR=${MANDIR} LFLAGS1=\\\"${LFLAGS1}\\\" \\\n       LFLAGS2=\\\"${LFLAGS2}\\\" LN=\\\"${LN}\\\" \\\n       CC_BZ=\\\"${CC_BZ}\\\" CFLAGS_BZ=\\\"${CFLAGS_BZ}\\\" \\\n       IZ_BZIP2=\\\"${IZ_BZIP2}\\\" LIB_BZ=\\\"${LIB_BZ}\\\" > flags\n\n"
  },
  {
    "path": "deps/infozip/zip30/unix/osdep.h",
    "content": "/*\n  unix/osdep.h - Zip 3\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#ifdef NO_LARGE_FILE_SUPPORT\n# ifdef LARGE_FILE_SUPPORT\n#  undef LARGE_FILE_SUPPORT\n# endif\n#endif\n\n#ifdef LARGE_FILE_SUPPORT\n  /* 64-bit Large File Support */\n\n  /* The following Large File Summit (LFS) defines turn on large file support on\n     Linux (probably 2.4 or later kernel) and many other unixen */\n\n# define _LARGEFILE_SOURCE      /* some OSes need this for fseeko */\n# define _LARGEFILE64_SOURCE\n# define _FILE_OFFSET_BITS 64   /* select default interface as 64 bit */\n# define _LARGE_FILES           /* some OSes need this for 64-bit off_t */\n#endif\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n/* printf format size prefix for zoff_t values */\n#ifdef LARGE_FILE_SUPPORT\n# define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n#else\n# define ZOFF_T_FORMAT_SIZE_PREFIX \"l\"\n#endif\n\n#ifdef NO_OFF_T\n  typedef long zoff_t;\n  typedef unsigned long uzoff_t;\n#else\n  typedef off_t zoff_t;\n# if defined(LARGE_FILE_SUPPORT) && !(defined(__alpha) && defined(__osf__))\n  typedef unsigned long long uzoff_t;\n# else\n  typedef unsigned long uzoff_t;\n# endif\n#endif\n  typedef struct stat z_stat;\n\n\n/* Automatically set ZIP64_SUPPORT if LFS */\n\n#ifdef LARGE_FILE_SUPPORT\n# ifndef NO_ZIP64_SUPPORT\n#   ifndef ZIP64_SUPPORT\n#     define ZIP64_SUPPORT\n#   endif\n# else\n#   ifdef ZIP64_SUPPORT\n#     undef ZIP64_SUPPORT\n#   endif\n# endif\n#endif\n\n\n/* Process files in binary mode */\n#if defined(__DJGPP__) || defined(__CYGWIN__)\n#  define FOPR \"rb\"\n#  define FOPM \"r+b\"\n#  define FOPW \"wb\"\n#endif\n\n\n/* Enable the \"UT\" extra field (time info) */\n#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)\n#  define USE_EF_UT_TIME\n#endif\n"
  },
  {
    "path": "deps/infozip/zip30/unix/unix.c",
    "content": "/*\n  unix/unix.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#include \"zip.h\"\n\n#ifndef UTIL    /* the companion #endif is a bit of ways down ... */\n\n#include <time.h>\n\n#if defined(MINIX) || defined(__mpexl)\n#  ifdef S_IWRITE\n#    undef S_IWRITE\n#  endif /* S_IWRITE */\n#  define S_IWRITE S_IWUSR\n#endif /* MINIX */\n\n#if (!defined(S_IWRITE) && defined(S_IWUSR))\n#  define S_IWRITE S_IWUSR\n#endif\n\n#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)\n#  include <dirent.h>\n#else /* !HAVE_DIRENT_H */\n#  ifdef HAVE_NDIR_H\n#    include <ndir.h>\n#  endif /* HAVE_NDIR_H */\n#  ifdef HAVE_SYS_NDIR_H\n#    include <sys/ndir.h>\n#  endif /* HAVE_SYS_NDIR_H */\n#  ifdef HAVE_SYS_DIR_H\n#    include <sys/dir.h>\n#  endif /* HAVE_SYS_DIR_H */\n#  ifndef dirent\n#    define dirent direct\n#  endif\n#endif /* HAVE_DIRENT_H || _POSIX_VERSION */\n\n#define PAD 0\n#define PATH_END '/'\n\n/* Library functions not in (most) header files */\n\n#ifdef _POSIX_VERSION\n#  include <utime.h>\n#else\n   int utime OF((char *, time_t *));\n#endif\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Local functions */\nlocal char *readd OF((DIR *));\n\n\n#ifdef NO_DIR                    /* for AT&T 3B1 */\n#include <sys/dir.h>\n#ifndef dirent\n#  define dirent direct\n#endif\ntypedef FILE DIR;\n/*\n**  Apparently originally by Rich Salz.\n**  Cleaned up and modified by James W. Birdsall.\n*/\n\n#define opendir(path) fopen(path, \"r\")\n\nstruct dirent *readdir(dirp)\nDIR *dirp;\n{\n  static struct dirent entry;\n\n  if (dirp == NULL)\n    return NULL;\n  for (;;)\n    if (fread (&entry, sizeof (struct dirent), 1, dirp) == 0)\n      return NULL;\n    else if (entry.d_ino)\n      return (&entry);\n} /* end of readdir() */\n\n#define closedir(dirp) fclose(dirp)\n#endif /* NO_DIR */\n\n\nlocal char *readd(d)\nDIR *d;                 /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct dirent *e;\n\n  e = readdir(d);\n  return e == NULL ? (char *) NULL : e->d_name;\n}\n\nint procname(n, caseflag)\nchar *n;                /* name to process */\nint caseflag;           /* true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  DIR *d;               /* directory stream from opendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  z_stat s;             /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s))\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n#ifdef OS390\n  if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode))\n#else\n#  ifdef S_IFLNK\n  if ((s.st_mode & S_IFREG) == S_IFREG || (s.st_mode & S_IFLNK) == S_IFLNK)\n#  else\n  if ((s.st_mode & S_IFREG) == S_IFREG)\n#  endif\n#endif\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  }\n#ifdef OS390\n  else if (S_ISDIR(s.st_mode))\n#else\n  else if ((s.st_mode & S_IFDIR) == S_IFDIR)\n#endif\n  {\n    /* Add trailing / to the directory name */\n    if ((p = malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (a[-1] != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = opendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            closedir(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname(a, caseflag)) != ZE_OK)   /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      closedir(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) */\n#ifdef OS390\n  else if (S_ISFIFO(s.st_mode))\n#else\n  else if ((s.st_mode & S_IFIFO) == S_IFIFO)\n#endif\n  {\n    if (allow_fifo) {\n      /* FIFO (Named Pipe) - handle as normal file */\n      /* add or remove name of FIFO */\n      /* zip will stop if FIFO is open and wait for pipe to be fed and closed */\n      if (noisy) zipwarn(\"Reading FIFO (Named Pipe): \", n);\n      if ((m = newname(n, 0, caseflag)) != ZE_OK)\n        return m;\n    } else {\n      zipwarn(\"ignoring FIFO (Named Pipe) - use -FI to read: \", n);\n      return ZE_OK;\n    }\n  } /* S_IFIFO */\n  else\n    zipwarn(\"ignoring special file: \", n);\n  return ZE_OK;\n}\n\nchar *ex2in(x, isdir, pdosflag)\nchar *x;                /* external file name */\nint isdir;              /* input: x is a directory */\nint *pdosflag;          /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t = NULL;       /* shortened name */\n  int dosflag;\n\n  dosflag = dosify;     /* default for non-DOS and non-OS/2 */\n\n  /* Find starting point in name before doing malloc */\n  /* Strip \"//host/share/\" part of a UNC name */\n  if (!strncmp(x,\"//\",2) && (x[2] != '\\0' && x[2] != '/')) {\n    n = x + 2;\n    while (*n != '\\0' && *n != '/')\n      n++;              /* strip host name */\n    if (*n != '\\0') {\n      n++;\n      while (*n != '\\0' && *n != '/')\n        n++;            /* strip `share' name */\n    }\n    if (*n != '\\0')\n      t = n + 1;\n  } else\n      t = x;\n  while (*t == '/')\n    t++;                /* strip leading '/' chars to get a relative path */\n  while (*t == '.' && t[1] == '/')\n    t += 2;             /* strip redundant leading \"./\" sections */\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n\n#ifdef EBCDIC\n  strtoasc(n, n);       /* here because msname() needs native coding */\n#endif\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n\n  if (isdir) return n;  /* avoid warning on unused variable */\n  return n;\n}\n\nchar *in2ex(n)\nchar *n;                /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n#ifdef EBCDIC\n  strtoebc(x, n);\n#else\n  strcpy(x, n);\n#endif\n  return x;\n}\n\n/*\n * XXX use ztimbuf in both POSIX and non POSIX cases ?\n */\nvoid stamp(f, d)\nchar *f;                /* name of file to change */\nulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n#ifdef _POSIX_VERSION\n  struct utimbuf u;     /* argument for utime()  const ?? */\n#else\n  time_t u[2];          /* argument for utime() */\n#endif\n\n  /* Convert DOS time to time_t format in u */\n#ifdef _POSIX_VERSION\n  u.actime = u.modtime = dos2unixtime(d);\n  utime(f, &u);\n#else\n  u[0] = u[1] = dos2unixtime(d);\n  utime(f, u);\n#endif\n\n}\n\nulg filetime(f, a, n, t)\n  char *f;                /* name of file to get info on */\n  ulg *a;                 /* return value: file attributes */\n  zoff_t *n;              /* return value: file size */\n  iztimes *t;             /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  z_stat s;         /* results of stat() */\n  /* converted to pointer from using FNMAX - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (strcmp(f, \"-\") == 0) {\n    if (zfstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  }\n  else if (LSSTAT(name, &s) != 0) {\n    /* Accept about any file kind including directories\n     * (stored with trailing / with -r option)\n     */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n#ifndef OS390\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n#else\n/*\n**  The following defines are copied from the unizip source and represent the\n**  legacy Unix mode flags.  These fixed bit masks are no longer required\n**  by XOPEN standards - the S_IS### macros being the new recommended method.\n**  The approach here of setting the legacy flags by testing the macros should\n**  work under any _XOPEN_SOURCE environment (and will just rebuild the same bit\n**  mask), but is required if the legacy bit flags differ from legacy Unix.\n*/\n#define UNX_IFDIR      0040000     /* Unix directory */\n#define UNX_IFREG      0100000     /* Unix regular file */\n#define UNX_IFSOCK     0140000     /* Unix socket (BSD, not SysV or Amiga) */\n#define UNX_IFLNK      0120000     /* Unix symbolic link (not SysV, Amiga) */\n#define UNX_IFBLK      0060000     /* Unix block special       (not Amiga) */\n#define UNX_IFCHR      0020000     /* Unix character special   (not Amiga) */\n#define UNX_IFIFO      0010000     /* Unix fifo    (BCC, not MSC or Amiga) */\n    {\n    mode_t legacy_modes;\n\n    /* Initialize with permission bits--which are not implementation-optional */\n    legacy_modes = s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);\n    if (S_ISDIR(s.st_mode))\n      legacy_modes |= UNX_IFDIR;\n    if (S_ISREG(s.st_mode))\n      legacy_modes |= UNX_IFREG;\n    if (S_ISLNK(s.st_mode))\n      legacy_modes |= UNX_IFLNK;\n    if (S_ISBLK(s.st_mode))\n      legacy_modes |= UNX_IFBLK;\n    if (S_ISCHR(s.st_mode))\n      legacy_modes |= UNX_IFCHR;\n    if (S_ISFIFO(s.st_mode))\n      legacy_modes |= UNX_IFIFO;\n    if (S_ISSOCK(s.st_mode))\n      legacy_modes |= UNX_IFSOCK;\n    *a = ((ulg)legacy_modes << 16) | !(s.st_mode & S_IWRITE);\n    }\n#endif\n    if ((s.st_mode & S_IFMT) == S_IFDIR) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = t->mtime;   /* best guess, (s.st_ctime: last status change!!) */\n  }\n  return unix2dostime(&s.st_mtime);\n}\n\n\n#ifndef QLZIP /* QLZIP Unix2QDOS cross-Zip supplies an extended variant */\n\nint set_new_unix_extra_field(z, s)\n  struct zlist far *z;\n  z_stat *s;\n  /* New unix extra field.\n     Currently only UIDs and GIDs are stored. */\n{\n  int uid_size;\n  int gid_size;\n  int ef_data_size;\n  char *extra;\n  char *cextra;\n  ulg id;\n  int b;\n\n  uid_size = sizeof(s->st_uid);\n  gid_size = sizeof(s->st_gid);\n\n/* New extra field\n   tag       (2 bytes)\n   size      (2 bytes)\n   version   (1 byte)\n   uid_size  (1 byte - size in bytes)\n   uid       (variable)\n   gid_size  (1 byte - size in bytes)\n   gid       (variable)\n */\n   \n  ef_data_size = 1 + 1 + uid_size + 1 + gid_size;\n\n  if ((extra = (char *)malloc(z->ext + 4 + ef_data_size)) == NULL)\n    return ZE_MEM;\n  if ((cextra = (char *)malloc(z->ext + 4 + ef_data_size)) == NULL)\n    return ZE_MEM;\n\n  if (z->ext)\n    memcpy(extra, z->extra, z->ext);\n  if (z->cext)\n    memcpy(cextra, z->cextra, z->cext);\n\n  free(z->extra);\n  z->extra = extra;\n  free(z->cextra);\n  z->cextra = cextra;\n\n  z->extra[z->ext + 0] = 'u';\n  z->extra[z->ext + 1] = 'x';\n  z->extra[z->ext + 2] = (char)ef_data_size;     /* length of data part */\n  z->extra[z->ext + 3] = 0;\n  z->extra[z->ext + 4] = 1;                      /* version */\n\n  /* UID */\n  z->extra[z->ext + 5] = (char)(uid_size);       /* uid size in bytes */\n  b = 6;\n  id = (ulg)(s->st_uid);\n  z->extra[z->ext + b] = (char)(id & 0xFF);\n  if (uid_size > 1) {\n    b++;\n    id = id >> 8;\n    z->extra[z->ext + b] = (char)(id & 0xFF);\n    if (uid_size > 2) {\n      b++;\n      id = id >> 8;\n      z->extra[z->ext + b] = (char)(id & 0xFF);\n      b++;\n      id = id >> 8;\n      z->extra[z->ext + b] = (char)(id & 0xFF);\n      if (uid_size == 8) {\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n      }\n    }\n  }\n\n  /* GID */\n  b++;\n  z->extra[z->ext + b] = (char)(gid_size);       /* gid size in bytes */\n  b++;\n  id = (ulg)(s->st_gid);\n  z->extra[z->ext + b] = (char)(id & 0xFF);\n  if (gid_size > 1) {\n    b++;\n    id = id >> 8;\n    z->extra[z->ext + b] = (char)(id & 0xFF);\n    if (gid_size > 2) {\n      b++;\n      id = id >> 8;\n      z->extra[z->ext + b] = (char)(id & 0xFF);\n      b++;\n      id = id >> 8;\n      z->extra[z->ext + b] = (char)(id & 0xFF);\n      if (gid_size == 8) {\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n        b++;\n        id = id >> 8;\n        z->extra[z->ext + b] = (char)(id & 0xFF);\n      }\n    }\n  }\n\n  /* copy local extra field to central directory extra field */\n  memcpy((z->cextra) + z->cext, (z->extra) + z->ext, 4 + ef_data_size);\n\n  z->ext = z->ext + 4 + ef_data_size;\n  z->cext = z->cext + 4 + ef_data_size;\n\n  return ZE_OK;\n}\n\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* store full data in local header but just modification time stamp info\n     in central header */\n{\n  z_stat s;\n  char *name;\n  int len = strlen(z->name);\n\n  /* For the full sized UT local field including the UID/GID fields, we\n   * have to stat the file again. */\n\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"set_extra_field\");\n  }\n  strcpy(name, z->name);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n  if (LSSTAT(name, &s)) {\n    free(name);\n    return ZE_OPEN;\n  }\n  free(name);\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(2))\n#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n\n/* The flag UIDGID_NOT_16BIT should be set by the pre-compile configuration\n   script when it detects st_uid or st_gid sizes differing from 16-bit.\n */\n#ifndef UIDGID_NOT_16BIT\n  /* The following \"second-level\" check for st_uid and st_gid members being\n     16-bit wide is only added as a safety precaution in case the \"first-level\"\n     check failed to define the UIDGID_NOT_16BIT symbol.\n     The first-level check should have been implemented in the automatic\n     compile configuration process.\n   */\n# ifdef UIDGID_ARE_16B\n#  undef UIDGID_ARE_16B\n# endif\n  /* The following expression is a compile-time constant and should (hopefully)\n     get optimized away by any sufficiently intelligent compiler!\n   */\n# define UIDGID_ARE_16B  (sizeof(s.st_uid) == 2 && sizeof(s.st_gid) == 2)\n\n# define EB_L_UX2_SIZE   (EB_HEADSIZE + EB_UX2_MINLEN)\n# define EB_C_UX2_SIZE   EB_HEADSIZE\n# define EF_L_UNIX_SIZE  (EB_L_UT_SIZE + (UIDGID_ARE_16B ? EB_L_UX2_SIZE : 0))\n# define EF_C_UNIX_SIZE  (EB_C_UT_SIZE + (UIDGID_ARE_16B ? EB_C_UX2_SIZE : 0))\n#else\n# define EF_L_UNIX_SIZE EB_L_UT_SIZE\n# define EF_C_UNIX_SIZE EB_C_UT_SIZE\n#endif /* !UIDGID_NOT_16BIT */\n\n  if ((z->extra = (char *)malloc(EF_L_UNIX_SIZE)) == NULL)\n    return ZE_MEM;\n  if ((z->cextra = (char *)malloc(EF_C_UNIX_SIZE)) == NULL)\n    return ZE_MEM;\n\n  z->extra[0]  = 'U';\n  z->extra[1]  = 'T';\n  z->extra[2]  = (char)EB_UT_LEN(2);    /* length of data part of local e.f. */\n  z->extra[3]  = 0;\n  z->extra[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME;    /* st_ctime != creation */\n  z->extra[5]  = (char)(s.st_mtime);\n  z->extra[6]  = (char)(s.st_mtime >> 8);\n  z->extra[7]  = (char)(s.st_mtime >> 16);\n  z->extra[8]  = (char)(s.st_mtime >> 24);\n  z->extra[9]  = (char)(s.st_atime);\n  z->extra[10] = (char)(s.st_atime >> 8);\n  z->extra[11] = (char)(s.st_atime >> 16);\n  z->extra[12] = (char)(s.st_atime >> 24);\n\n#ifndef UIDGID_NOT_16BIT\n  /* Only store the UID and GID in the old Ux extra field if the runtime\n     system provides them in 16-bit wide variables.  */\n  if (UIDGID_ARE_16B) {\n    z->extra[13] = 'U';\n    z->extra[14] = 'x';\n    z->extra[15] = (char)EB_UX2_MINLEN; /* length of data part of local e.f. */\n    z->extra[16] = 0;\n    z->extra[17] = (char)(s.st_uid);\n    z->extra[18] = (char)(s.st_uid >> 8);\n    z->extra[19] = (char)(s.st_gid);\n    z->extra[20] = (char)(s.st_gid >> 8);\n  }\n#endif /* !UIDGID_NOT_16BIT */\n\n  z->ext = EF_L_UNIX_SIZE;\n\n  memcpy(z->cextra, z->extra, EB_C_UT_SIZE);\n  z->cextra[EB_LEN] = (char)EB_UT_LEN(1);\n#ifndef UIDGID_NOT_16BIT\n  if (UIDGID_ARE_16B) {\n    /* Copy header of Ux extra field from local to central */\n    memcpy(z->cextra+EB_C_UT_SIZE, z->extra+EB_L_UT_SIZE, EB_C_UX2_SIZE);\n    z->cextra[EB_LEN+EB_C_UT_SIZE] = 0;\n  }\n#endif\n  z->cext = EF_C_UNIX_SIZE;\n\n#if 0  /* UID/GID presence is now signaled by central EF_IZUNIX2 field ! */\n  /* lower-middle external-attribute byte (unused until now):\n   *   high bit        => (have GMT mod/acc times) >>> NO LONGER USED! <<<\n   *   second-high bit => have Unix UID/GID info\n   * NOTE: The high bit was NEVER used in any official Info-ZIP release,\n   *       but its future use should be avoided (if possible), since it\n   *       was used as \"GMT mod/acc times local extra field\" flags in Zip beta\n   *       versions 2.0j up to 2.0v, for about 1.5 years.\n   */\n  z->atx |= 0x4000;\n#endif /* never */\n\n  /* new unix extra field */\n  set_new_unix_extra_field(z, &s);\n\n  return ZE_OK;\n}\n\n#endif /* !QLZIP */\n\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n# ifdef NO_RMDIR\n    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */\n    int r, len;\n    char *s;              /* malloc'd string for system command */\n\n    len = strlen(d);\n    if ((s = malloc(len + 34)) == NULL)\n      return 127;\n\n    sprintf(s, \"IFS=\\\" \\t\\n\\\" /bin/rmdir %s 2>/dev/null\", d);\n    r = system(s);\n    free(s);\n    return r;\n# else /* !NO_RMDIR */\n    return rmdir(d);\n# endif /* ?NO_RMDIR */\n}\n\n#endif /* !UTIL */\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\n#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__386BSD__) || \\\n    defined(__OpenBSD__) || defined(__bsdi__)\n#include <sys/param.h> /* for the BSD define */\n/* if we have something newer than NET/2 we'll use uname(3) */\n#if (BSD > 199103)\n#include <sys/utsname.h>\n#endif /* BSD > 199103 */\n#endif /* __{Net,Free,Open,386}BSD__ || __bsdi__ */\n\nvoid version_local()\n{\n#ifdef __GNUC__\n#  ifdef NX_CURRENT_COMPILER_RELEASE\n    char compiler_name[80];\n#  endif\n#else\n#  if (defined( __SUNPRO_C))\n    char compiler_name[33];\n#  else\n#    if (defined( __HP_cc) || defined( __IBMC__))\n    char compiler_name[33];\n#    else\n#      if (defined( __DECC_VER))\n    char compiler_name[33];\n    int compiler_typ;\n#      else\n#        if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))\n    char compiler_name[40];\n#        endif\n#      endif\n#    endif\n#  endif\n#endif\n\n#ifdef BSD\n# if (BSD > 199103)\n    struct utsname u;\n    char os_name[40];\n# else\n# if defined(__NETBSD__))\n    static ZCONST char *netbsd[] = { \"_ALPHA\", \"\", \"A\", \"B\" };\n    char os_name[40];\n# endif /* __NETBSD__ */\n# endif /* BSD > 199103 */\n#else /* !BSD */\n#if ((defined(CRAY) || defined(cray)) && defined(_UNICOS))\n    char os_name[40];\n#endif /* (CRAY && defined(_UNICOS)) */\n#endif /* ?BSD */\n\n/* Define the compiler name and version string */\n#ifdef __GNUC__\n#  ifdef NX_CURRENT_COMPILER_RELEASE\n    sprintf(compiler_name, \"NeXT DevKit %d.%02d (gcc \" __VERSION__ \")\",\n     NX_CURRENT_COMPILER_RELEASE/100, NX_CURRENT_COMPILER_RELEASE%100);\n#    define COMPILER_NAME compiler_name\n#  else\n#    define COMPILER_NAME \"gcc \" __VERSION__\n#  endif\n#else /* !__GNUC__ */\n#  if defined(__SUNPRO_C)\n    sprintf( compiler_name, \"Sun C version %x\", __SUNPRO_C);\n#    define COMPILER_NAME compiler_name\n#  else\n#    if (defined( __HP_cc))\n    if ((__HP_cc% 100) == 0)\n    {\n      sprintf( compiler_name, \"HP C version A.%02d.%02d\",\n       (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100));\n    }\n    else\n    {\n      sprintf( compiler_name, \"HP C version A.%02d.%02d.%02d\",\n       (__HP_cc/ 10000), ((__HP_cc% 10000)/ 100), (__HP_cc% 100));\n    }\n#      define COMPILER_NAME compiler_name\n#    else\n#      if (defined( __DECC_VER))\n    sprintf( compiler_name, \"DEC C version %c%d.%d-%03d\",\n     ((compiler_typ = (__DECC_VER / 10000) % 10) == 6 ? 'T' :\n     (compiler_typ == 8 ? 'S' : 'V')),\n     __DECC_VER / 10000000,\n     (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000);\n#        define COMPILER_NAME compiler_name\n#      else\n#        if ((defined(CRAY) || defined(cray)) && defined(_RELEASE))\n    sprintf(compiler_name, \"cc version %d\", _RELEASE);\n#          define COMPILER_NAME compiler_name\n#        else\n#          ifdef __IBMC__\n    sprintf( compiler_name, \"IBM C version %d.%d.%d\",\n     (__IBMC__/ 100), ((__IBMC__/ 10)% 10), (__IBMC__% 10));\n#            define COMPILER_NAME compiler_name\n#          else\n#            ifdef __VERSION__\n#              define COMPILER_NAME \"cc \" __VERSION__\n#            else\n#              define COMPILER_NAME \"cc \"\n#            endif\n#          endif\n#        endif\n#      endif\n#    endif\n#  endif\n#endif /* ?__GNUC__ */\n\n\n/* Define the name to use for the OS we're compiling on */\n#if defined(sgi) || defined(__sgi)\n#  define OS_NAME \"Silicon Graphics IRIX\"\n#else\n#ifdef sun\n#  ifdef sparc\n#    ifdef __SVR4\n#      define OS_NAME \"Sun SPARC/Solaris\"\n#    else /* may or may not be SunOS */\n#      define OS_NAME \"Sun SPARC\"\n#    endif\n#  else\n#  if defined(sun386) || defined(i386)\n#    define OS_NAME \"Sun 386i\"\n#  else\n#  if defined(mc68020) || defined(__mc68020__)\n#    define OS_NAME \"Sun 3\"\n#  else /* mc68010 or mc68000:  Sun 2 or earlier */\n#    define OS_NAME \"Sun 2\"\n#  endif\n#  endif\n#  endif\n#else\n#ifdef __hpux\n#  define OS_NAME \"HP-UX\"\n#else\n#ifdef __osf__\n#  define OS_NAME \"DEC OSF/1\"\n#else\n#ifdef _AIX\n#  define OS_NAME \"IBM AIX\"\n#else\n#ifdef aiws\n#  define OS_NAME \"IBM RT/AIX\"\n#else\n#if defined(CRAY) || defined(cray)\n#  ifdef _UNICOS\n    sprintf(os_name, \"Cray UNICOS release %d\", _UNICOS);\n#    define OS_NAME os_name\n#  else\n#    define OS_NAME \"Cray UNICOS\"\n#  endif\n#else\n#if defined(uts) || defined(UTS)\n#  define OS_NAME \"Amdahl UTS\"\n#else\n#ifdef NeXT\n#  ifdef mc68000\n#    define OS_NAME \"NeXTStep/black\"\n#  else\n#    define OS_NAME \"NeXTStep for Intel\"\n#  endif\n#else\n#if defined(linux) || defined(__linux__)\n#  ifdef __ELF__\n#    define OS_NAME \"Linux ELF\"\n#  else\n#    define OS_NAME \"Linux a.out\"\n#  endif\n#else\n#ifdef MINIX\n#  define OS_NAME \"Minix\"\n#else\n#ifdef M_UNIX\n#  define OS_NAME \"SCO Unix\"\n#else\n#ifdef M_XENIX\n#  define OS_NAME \"SCO Xenix\"\n#else\n#ifdef BSD\n# if (BSD > 199103)\n#    define OS_NAME os_name\n    uname(&u);\n    sprintf(os_name, \"%s %s\", u.sysname, u.release);\n# else\n# ifdef __NetBSD__\n#   define OS_NAME os_name\n#   ifdef NetBSD0_8\n      sprintf(os_name, \"NetBSD 0.8%s\", netbsd[NetBSD0_8]);\n#   else\n#   ifdef NetBSD0_9\n      sprintf(os_name, \"NetBSD 0.9%s\", netbsd[NetBSD0_9]);\n#   else\n#   ifdef NetBSD1_0\n      sprintf(os_name, \"NetBSD 1.0%s\", netbsd[NetBSD1_0]);\n#   endif /* NetBSD1_0 */\n#   endif /* NetBSD0_9 */\n#   endif /* NetBSD0_8 */\n# else\n# ifdef __FreeBSD__\n#    define OS_NAME \"FreeBSD 1.x\"\n# else\n# ifdef __bsdi__\n#    define OS_NAME \"BSD/386 1.0\"\n# else\n# ifdef __386BSD__\n#    define OS_NAME \"386BSD\"\n# else\n#    define OS_NAME \"Unknown BSD\"\n# endif /* __386BSD__ */\n# endif /* __bsdi__ */\n# endif /* FreeBSD */\n# endif /* NetBSD */\n# endif /* BSD > 199103 */\n#else\n#ifdef __CYGWIN__\n#  define OS_NAME \"Cygwin\"\n#else\n#if defined(i686) || defined(__i686) || defined(__i686__)\n#  define OS_NAME \"Intel 686\"\n#else\n#if defined(i586) || defined(__i586) || defined(__i586__)\n#  define OS_NAME \"Intel 586\"\n#else\n#if defined(i486) || defined(__i486) || defined(__i486__)\n#  define OS_NAME \"Intel 486\"\n#else\n#if defined(i386) || defined(__i386) || defined(__i386__)\n#  define OS_NAME \"Intel 386\"\n#else\n#ifdef pyr\n#  define OS_NAME \"Pyramid\"\n#else\n#if defined(ultrix) || defined(__ultrix)\n#  if defined(mips) || defined(__mips)\n#    define OS_NAME \"DEC/MIPS\"\n#  else\n#  if defined(vax) || defined(__vax)\n#    define OS_NAME \"DEC/VAX\"\n#  else /* __alpha? */\n#    define OS_NAME \"DEC/Alpha\"\n#  endif\n#  endif\n#else\n#ifdef gould\n#  define OS_NAME \"Gould\"\n#else\n#ifdef MTS\n#  define OS_NAME \"MTS\"\n#else\n#ifdef __convexc__\n#  define OS_NAME \"Convex\"\n#else\n#ifdef __QNX__\n#  define OS_NAME \"QNX 4\"\n#else\n#ifdef __QNXNTO__\n#  define OS_NAME \"QNX Neutrino\"\n#else\n#ifdef __APPLE__\n#  ifdef __i386__\n#    define OS_NAME \"Mac OS X Intel\"\n#  else /* __i386__ */\n#    ifdef __ppc__\n#      define OS_NAME \"Mac OS X PowerPC\"\n#    else /* __ppc__ */\n#      ifdef __ppc64__\n#        define OS_NAME \"Mac OS X PowerPC64\"\n#      else /* __ppc64__ */\n#        define OS_NAME \"Mac OS X\"\n#      endif /* __ppc64__ */\n#    endif /* __ppc__ */\n#  endif /* __i386__ */\n#else\n#  define OS_NAME \"Unknown\"\n#endif /* Apple */\n#endif /* QNX Neutrino */\n#endif /* QNX 4 */\n#endif /* Convex */\n#endif /* MTS */\n#endif /* Gould */\n#endif /* DEC */\n#endif /* Pyramid */\n#endif /* 386 */\n#endif /* 486 */\n#endif /* 586 */\n#endif /* 686 */\n#endif /* Cygwin */\n#endif /* BSD */\n#endif /* SCO Xenix */\n#endif /* SCO Unix */\n#endif /* Minix */\n#endif /* Linux */\n#endif /* NeXT */\n#endif /* Amdahl */\n#endif /* Cray */\n#endif /* RT/AIX */\n#endif /* AIX */\n#endif /* OSF/1 */\n#endif /* HP-UX */\n#endif /* Sun */\n#endif /* SGI */\n\n\n/* Define the compile date string */\n#ifdef __DATE__\n#  define COMPILE_DATE \" on \" __DATE__\n#else\n#  define COMPILE_DATE \"\"\n#endif\n\n    printf(\"Compiled with %s for Unix (%s)%s.\\n\\n\",\n           COMPILER_NAME, OS_NAME, COMPILE_DATE);\n\n} /* end function version_local() */\n\n\n/* 2006-03-23 SMS.\n * Emergency replacement for strerror().  (Useful on SunOS 4.*.)\n * Enable by specifying \"LOCAL_UNZIP=-DNEED_STRERROR=1\" on the \"make\"\n * command line.\n */\n\n#ifdef NEED_STRERROR\n\nchar *strerror( err)\n  int err;\n{\n    extern char *sys_errlist[];\n    extern int sys_nerr;\n\n    static char no_msg[ 64];\n\n    if ((err >= 0) && (err < sys_nerr))\n    {\n        return sys_errlist[ err];\n    }\n    else\n    {\n        sprintf( no_msg, \"(no message, code = %d.)\", err);\n        return no_msg;\n    }\n}\n\n#endif /* def NEED_STRERROR */\n\n\n/* 2006-03-23 SMS.\n * Emergency replacement for memmove().  (Useful on SunOS 4.*.)\n * Enable by specifying \"LOCAL_UNZIP=-DNEED_MEMMOVE=1\" on the \"make\"\n * command line.\n */\n\n#ifdef NEED_MEMMOVE\n\n/* memmove.c -- copy memory.\n   Copy LENGTH bytes from SOURCE to DEST.  Does not null-terminate.\n   In the public domain.\n   By David MacKenzie <djm@gnu.ai.mit.edu>.\n   Adjusted by SMS.\n*/\n\nvoid *memmove(dest0, source0, length)\n  void *dest0;\n  void const *source0;\n  size_t length;\n{\n    char *dest = dest0;\n    char const *source = source0;\n    if (source < dest)\n        /* Moving from low mem to hi mem; start at end.  */\n        for (source += length, dest += length; length; --length)\n            *--dest = *--source;\n    else if (source != dest)\n    {\n        /* Moving from hi mem to low mem; start at beginning.  */\n        for (; length; --length)\n            *dest++ = *source++;\n    }\n    return dest0;\n}\n\n#endif /* def NEED_MEMMOVE */\n"
  },
  {
    "path": "deps/infozip/zip30/unix/zipup.h",
    "content": "/*\n  unix/zipup.h - Zip 3\n\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef O_RDONLY\n#  define O_RDONLY 0\n#endif\n#ifndef O_BINARY\n#  define O_BINARY 0\n#endif\n#define fhow (O_RDONLY|O_BINARY)\n#define fbad (-1)\ntypedef int ftype;\n#define zopen(n,p) open(n,p)\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f) close(f)\n#define zerr(f) (k == (extent)(-1L))\n#define zstdin 0\n"
  },
  {
    "path": "deps/infozip/zip30/util.c",
    "content": "/*\n  util.c\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  util.c by Mark Adler.\n */\n#define __UTIL_C\n\n#include \"zip.h\"\n#include \"ebcdic.h\"\n#include <ctype.h>\n\n#ifdef MSDOS16\n#  include <dos.h>\n#endif\n\n#ifdef NO_MKTIME\n#  ifndef IZ_MKTIME_ONLY\n#    define IZ_MKTIME_ONLY      /* only mktime() related code is pulled in */\n#  endif\n#  include \"timezone.c\"\n#endif\n\nuch upper[256], lower[256];\n/* Country-dependent case map table */\n\n\n#ifndef UTIL /* UTIL picks out namecmp code (all utils) */\n\n/* RISC OS uses # as its single-character wildcard */\n#ifdef RISCOS\n#  define WILDCHR_SINGLE '#'\n#  define WILDCHR_MULTI  '*'\n#  define DIRSEP_CHR '.'\n#endif\n\n#ifdef VMS\n#  define WILDCHR_SINGLE '%'\n#  define WILDCHR_MULTI  '*'\n#  define DIRSEP_CHR '.'\n#endif\n\n#ifndef WILDCHR_SINGLE\n#  define WILDCHR_SINGLE '?'\n#endif\n#ifndef WILDCHR_MULTI\n#  define WILDCHR_MULTI '*'\n#endif\n#ifndef DIRSEP_CHR\n#  define DIRSEP_CHR '/'\n#endif\n\n/* Local functions */\nlocal int recmatch OF((ZCONST char *, ZCONST char *, int));\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n  local long recmatchw OF((ZCONST wchar_t *, ZCONST wchar_t *, int));\n#endif\nlocal int count_args OF((char *s));\n\n#ifdef MSDOS16\n  local unsigned ident OF((unsigned chr));\n#endif\n\n#ifndef HAVE_FSEEKABLE\n\n/* 2004-11-12 SMS.\n   Changed to use z*o() functions, and ftell() test from >= 0 to != -1.\n   This solves problems with negative 32-bit offsets, even on small-file\n   products.\n*/\nint fseekable( fp)\nFILE *fp;\n{\n    zoff_t x;\n\n    return (fp == NULL ||\n     ((zfseeko( fp, ((zoff_t) -1), SEEK_CUR) == 0) &&   /* Seek ok. */\n     ((x = zftello( fp)) != ((zoff_t) -1)) &&           /* Tell ok. */\n     (zfseeko( fp, ((zoff_t) 1), SEEK_CUR) == 0) &&     /* Seek ok. */\n     (zftello( fp) == x+ 1)));                          /* Tells agree. */\n}\n#endif /* HAVE_FSEEKABLE */\n\n\nchar *isshexp(p)\nchar *p;                /* candidate sh expression */\n/* If p is a sh expression, a pointer to the first special character is\n   returned.  Otherwise, NULL is returned. */\n{\n  for (; *p; INCSTR(p))\n    if (*p == '\\\\' && *(p+1))\n      p++;\n#ifdef VMS\n    else if (*p == WILDCHR_SINGLE || *p == WILDCHR_MULTI)\n#else /* !VMS */\n    else if (*p == WILDCHR_SINGLE || *p == WILDCHR_MULTI || *p == '[')\n#endif /* ?VMS */\n      return p;\n  return NULL;\n}\n\n#ifdef UNICODE_SUPPORT\n# ifdef WIN32\n\nwchar_t *isshexpw(pw)\n  wchar_t *pw;          /* candidate sh expression */\n/* If pw is a sh expression, a pointer to the first special character is\n   returned.  Otherwise, NULL is returned. */\n{\n  for (; *pw; pw++)\n    if (*pw == (wchar_t)'\\\\' && *(pw+1))\n      pw++;\n    else if (*pw == (wchar_t)WILDCHR_SINGLE || *pw == (wchar_t)WILDCHR_MULTI ||\n             *pw == (wchar_t)'[')\n      return pw;\n  return NULL;\n}\n\n# endif\n#endif\n\n\n#ifdef UNICODE_SUPPORT\n# ifdef WIN32\n\nlocal long recmatchw(pw, sw, cs)\nZCONST wchar_t *pw;     /* sh pattern to match */\nZCONST wchar_t *sw;     /* string to match it to */\nint cs;                 /* flag: force case-sensitive matching */\n/* Recursively compare the sh pattern p with the string s and return 1 if\n   they match, and 0 or 2 if they don't or if there is a syntax error in the\n   pattern.  This routine recurses on itself no deeper than the number of\n   characters in the pattern. */\n{\n  long c;               /* pattern char or start of range in [-] loop */\n  /* Get first character, the pattern for new recmatch calls follows */\n\n  c = (long)*(pw++);\n\n  /* If that was the end of the pattern, match if string empty too */\n  if (c == 0)\n    return *sw == 0;\n\n  /* '?' matches any character (but not an empty string) */\n  if ((wchar_t)c == (wchar_t)WILDCHR_SINGLE) {\n    if (wild_stop_at_dir)\n      return (*sw && *sw != (wchar_t)DIRSEP_CHR) ? recmatchw(pw, sw + 1, cs) : 0;\n    else\n      return *sw ? recmatchw(pw, sw + 1, cs) : 0;\n  }\n\n  /* WILDCHR_MULTI ('*') matches any number of characters, including zero */\n  if (!no_wild && (wchar_t)c == (wchar_t)WILDCHR_MULTI)\n  {\n    if (wild_stop_at_dir) {\n      /* Check for an immediately following WILDCHR_MULTI */\n      if (*pw != (wchar_t)WILDCHR_MULTI) {\n        /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */\n        for (; *sw && *sw != (wchar_t)DIRSEP_CHR; sw++)\n          if ((c = recmatchw(pw, sw, cs)) != 0)\n            return c;\n        /* end of pattern: matched if at end of string, else continue */\n        if (*pw == 0)\n          return (*sw == 0);\n        /* continue to match if at DIRSEP_CHR in pattern, else give up */\n        return (*pw == (wchar_t)DIRSEP_CHR || (*pw == (wchar_t)'\\\\' &&\n                pw[1] == (wchar_t)DIRSEP_CHR))\n               ? recmatchw(pw, sw, cs) : 2;\n      }\n      /* Two consecutive WILDCHR_MULTI (\"**\"): this matches DIRSEP_CHR ('/') */\n      pw++;        /* move p past the second WILDCHR_MULTI */\n      /* continue with the normal non-WILD_STOP_AT_DIR code */\n    } /* wild_stop_at_dir */\n\n    /* Not wild_stop_at_dir */\n    if (*pw == 0)\n      return 1;\n    if (!isshexpw((wchar_t *)pw))\n    {\n      /* optimization for rest of pattern being a literal string */\n\n      /* optimization to handle patterns like *.txt */\n      /* if the first char in the pattern is '*' and there */\n      /* are no other shell expression chars, i.e. a literal string */\n      /* then just compare the literal string at the end */\n\n      ZCONST wchar_t *swrest;\n\n      swrest = sw + (wcslen(sw) - wcslen(pw));\n      if (swrest - sw < 0)\n        /* remaining literal string from pattern is longer than rest of\n           test string, there can't be a match\n         */\n        return 0;\n      else\n        /* compare the remaining literal pattern string with the last bytes\n           of the test string to check for a match */\n        return ((cs ? wcscmp(pw, swrest) : _wcsicmp(pw, swrest)) == 0);\n    }\n    else\n    {\n      /* pattern contains more wildcards, continue with recursion... */\n      for (; *sw; sw++)\n        if ((c = recmatchw(pw, sw, cs)) != 0)\n          return c;\n      return 2;           /* 2 means give up--shmatch will return false */\n    }\n  }\n\n  /* Parse and process the list of characters and ranges in brackets */\n  if (!no_wild && allow_regex && (wchar_t)c == '[')\n  {\n    int e;              /* flag true if next char to be taken literally */\n    ZCONST wchar_t *qw; /* pointer to end of [-] group */\n    int r;              /* flag true to match anything but the range */\n\n    if (*sw == 0)                        /* need a character to match */\n      return 0;\n    pw += (r = (*pw == (wchar_t)'!' || *pw == (wchar_t)'^')); /* see if reverse */\n    for (qw = pw, e = 0; *qw; qw++)         /* find closing bracket */\n      if (e)\n        e = 0;\n      else\n        if (*qw == (wchar_t)'\\\\')\n          e = 1;\n        else if (*qw == (wchar_t)']')\n          break;\n    if (*qw != (wchar_t)']')                      /* nothing matches if bad syntax */\n      return 0;\n    for (c = 0, e = *pw == (wchar_t)'-'; pw < qw; pw++)      /* go through the list */\n    {\n      if (e == 0 && *pw == (wchar_t)'\\\\')         /* set escape flag if \\ */\n        e = 1;\n      else if (e == 0 && *pw == (wchar_t)'-')     /* set start of range if - */\n        c = *(pw-1);\n      else\n      {\n        wchar_t cc = (cs ? *sw : towupper(*sw));\n        wchar_t uc = (wchar_t) c;\n\n        if (*(pw+1) != (wchar_t)'-')\n          for (uc = uc ? uc : *pw; cc <= *pw; uc++)\n            /* compare range */\n            if ((cs ? uc : towupper(uc)) == cc)\n              return r ? 0 : recmatchw(qw + 1, sw + 1, cs);\n        c = e = 0;                      /* clear range, escape flags */\n      }\n    }\n    return r ? recmatchw(qw + 1, sw + 1, cs) : 0;\n                                        /* bracket match failed */\n  }\n\n  /* If escape ('\\'), just compare next character */\n  if (!no_wild && (wchar_t)c == (wchar_t)'\\\\')\n    if ((c = *pw++) == '\\0')            /* if \\ at end, then syntax error */\n      return 0;\n\n  /* Just a character--compare it */\n  return (cs ? (wchar_t)c == *sw : towupper((wchar_t)c) == towupper(*sw)) ?\n          recmatchw(pw, sw + 1, cs) : 0;\n}\n\n# endif\n#endif\n\n\nlocal int recmatch(p, s, cs)\nZCONST char *p;         /* sh pattern to match */\nZCONST char *s;         /* string to match it to */\nint cs;                 /* flag: force case-sensitive matching */\n/* Recursively compare the sh pattern p with the string s and return 1 if\n   they match, and 0 or 2 if they don't or if there is a syntax error in the\n   pattern.  This routine recurses on itself no deeper than the number of\n   characters in the pattern. */\n{\n  int c;                /* pattern char or start of range in [-] loop */\n  /* Get first character, the pattern for new recmatch calls follows */\n\n  /* This fix provided by akt@m5.dion.ne.jp for Japanese.\n     See 21 July 2006 mail.\n     It only applies when p is pointing to a doublebyte character and\n     things like / and wildcards are not doublebyte.  This probably\n     should not be needed. */\n\n#ifdef _MBCS\n  if (CLEN(p) == 2) {\n    if (CLEN(s) == 2) {\n      return (*p == *s && *(p+1) == *(s+1)) ?\n        recmatch(p + 2, s + 2, cs) : 0;\n    } else {\n      return 0;\n    }\n  }\n#endif /* ?_MBCS */\n\n  c = *POSTINCSTR(p);\n\n  /* If that was the end of the pattern, match if string empty too */\n  if (c == 0)\n    return *s == 0;\n\n  /* '?' (or '%' or '#') matches any character (but not an empty string) */\n  if (c == WILDCHR_SINGLE) {\n    if (wild_stop_at_dir)\n      return (*s && *s != DIRSEP_CHR) ? recmatch(p, s + CLEN(s), cs) : 0;\n    else\n      return *s ? recmatch(p, s + CLEN(s), cs) : 0;\n  }\n\n  /* WILDCHR_MULTI ('*') matches any number of characters, including zero */\n#ifdef AMIGA\n  if (!no_wild && c == '#' && *p == '?')            /* \"#?\" is Amiga-ese for \"*\" */\n    c = WILDCHR_MULTI, p++;\n#endif /* AMIGA */\n  if (!no_wild && c == WILDCHR_MULTI)\n  {\n    if (wild_stop_at_dir) {\n      /* Check for an immediately following WILDCHR_MULTI */\n# ifdef AMIGA\n      if ((c = p[0]) == '#' && p[1] == '?') /* \"#?\" is Amiga-ese for \"*\" */\n        c = WILDCHR_MULTI, p++;\n      if (c != WILDCHR_MULTI) {\n# else /* !AMIGA */\n      if (*p != WILDCHR_MULTI) {\n# endif /* ?AMIGA */\n        /* Single WILDCHR_MULTI ('*'): this doesn't match slashes */\n        for (; *s && *s != DIRSEP_CHR; INCSTR(s))\n          if ((c = recmatch(p, s, cs)) != 0)\n            return c;\n        /* end of pattern: matched if at end of string, else continue */\n        if (*p == 0)\n          return (*s == 0);\n        /* continue to match if at DIRSEP_CHR in pattern, else give up */\n        return (*p == DIRSEP_CHR || (*p == '\\\\' && p[1] == DIRSEP_CHR))\n               ? recmatch(p, s, cs) : 2;\n      }\n      /* Two consecutive WILDCHR_MULTI (\"**\"): this matches DIRSEP_CHR ('/') */\n      p++;        /* move p past the second WILDCHR_MULTI */\n      /* continue with the normal non-WILD_STOP_AT_DIR code */\n    } /* wild_stop_at_dir */\n\n    /* Not wild_stop_at_dir */\n    if (*p == 0)\n      return 1;\n    if (!isshexp((char *)p))\n    {\n      /* optimization for rest of pattern being a literal string */\n\n      /* optimization to handle patterns like *.txt */\n      /* if the first char in the pattern is '*' and there */\n      /* are no other shell expression chars, i.e. a literal string */\n      /* then just compare the literal string at the end */\n\n      ZCONST char *srest;\n\n      srest = s + (strlen(s) - strlen(p));\n      if (srest - s < 0)\n        /* remaining literal string from pattern is longer than rest of\n           test string, there can't be a match\n         */\n        return 0;\n      else\n        /* compare the remaining literal pattern string with the last bytes\n           of the test string to check for a match */\n#ifdef _MBCS\n      {\n        ZCONST char *q = s;\n\n        /* MBCS-aware code must not scan backwards into a string from\n         * the end.\n         * So, we have to move forward by character from our well-known\n         * character position s in the test string until we have advanced\n         * to the srest position.\n         */\n        while (q < srest)\n          INCSTR(q);\n        /* In case the byte *srest is a trailing byte of a multibyte\n         * character, we have actually advanced past the position (srest).\n         * For this case, the match has failed!\n         */\n        if (q != srest)\n          return 0;\n        return ((cs ? strcmp(p, q) : namecmp(p, q)) == 0);\n      }\n#else /* !_MBCS */\n        return ((cs ? strcmp(p, srest) : namecmp(p, srest)) == 0);\n#endif /* ?_MBCS */\n    }\n    else\n    {\n      /* pattern contains more wildcards, continue with recursion... */\n      for (; *s; INCSTR(s))\n        if ((c = recmatch(p, s, cs)) != 0)\n          return c;\n      return 2;           /* 2 means give up--shmatch will return false */\n    }\n  }\n\n#ifndef VMS             /* No bracket matching in VMS */\n  /* Parse and process the list of characters and ranges in brackets */\n  if (!no_wild && allow_regex && c == '[')\n  {\n    int e;              /* flag true if next char to be taken literally */\n    ZCONST char *q;     /* pointer to end of [-] group */\n    int r;              /* flag true to match anything but the range */\n\n    if (*s == 0)                        /* need a character to match */\n      return 0;\n    p += (r = (*p == '!' || *p == '^')); /* see if reverse */\n    for (q = p, e = 0; *q; q++)         /* find closing bracket */\n      if (e)\n        e = 0;\n      else\n        if (*q == '\\\\')\n          e = 1;\n        else if (*q == ']')\n          break;\n    if (*q != ']')                      /* nothing matches if bad syntax */\n      return 0;\n    for (c = 0, e = *p == '-'; p < q; p++)      /* go through the list */\n    {\n      if (e == 0 && *p == '\\\\')         /* set escape flag if \\ */\n        e = 1;\n      else if (e == 0 && *p == '-')     /* set start of range if - */\n        c = *(p-1);\n      else\n      {\n        uch cc = (cs ? (uch)*s : case_map((uch)*s));\n        uch uc = (uch) c;\n        if (*(p+1) != '-')\n          for (uc = uc ? uc : (uch)*p; uc <= (uch)*p; uc++)\n            /* compare range */\n            if ((cs ? uc : case_map(uc)) == cc)\n              return r ? 0 : recmatch(q + CLEN(q), s + CLEN(s), cs);\n        c = e = 0;                      /* clear range, escape flags */\n      }\n    }\n    return r ? recmatch(q + CLEN(q), s + CLEN(s), cs) : 0;\n                                        /* bracket match failed */\n  }\n#endif /* !VMS */\n\n  /* If escape ('\\'), just compare next character */\n  if (!no_wild && c == '\\\\')\n    if ((c = *p++) == '\\0')             /* if \\ at end, then syntax error */\n      return 0;\n\n#ifdef VMS\n  /* 2005-11-06 SMS.\n     Handle \"...\" wildcard in p with \".\" or \"]\" in s.\n  */\n  if ((c == '.') && (*p == '.') && (*(p+ CLEN( p)) == '.') &&\n   ((*s == '.') || (*s == ']')))\n  {\n    /* Match \"...]\" with \"]\".  Continue after \"]\" in both. */\n    if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))\n      return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);\n\n    /* Else, look for a reduced match in s, until \"]\" in or end of s. */\n    for (; *s && (*s != ']'); INCSTR(s))\n      if (*s == '.')\n        /* If reduced match, then continue after \"...\" in p, \".\" in s. */\n        if ((c = recmatch( (p+ CLEN( p)), s, cs)) != 0)\n          return (int)c;\n\n    /* Match \"...]\" with \"]\".  Continue after \"]\" in both. */\n    if ((*(p+ 2* CLEN( p)) == ']') && (*s == ']'))\n      return recmatch( (p+ 3* CLEN( p)), (s+ CLEN( s)), cs);\n\n    /* No reduced match.  Quit. */\n    return 2;\n  }\n\n#endif /* def VMS */\n\n  /* Just a character--compare it */\n  return (cs ? c == *s : case_map((uch)c) == case_map((uch)*s)) ?\n          recmatch(p, s + CLEN(s), cs) : 0;\n}\n\n\nint shmatch(p, s, cs)\nZCONST char *p;         /* sh pattern to match */\nZCONST char *s;         /* string to match it to */\nint cs;                 /* force case-sensitive match if TRUE */\n/* Compare the sh pattern p with the string s and return true if they match,\n   false if they don't or if there is a syntax error in the pattern. */\n{\n  return recmatch(p, s, cs) == 1;\n}\n\n\n#if defined(DOS) || defined(WIN32)\n\n#ifdef UNICODE_SUPPORT\n\nint dosmatchw(pw, sw, cs)\nZCONST wchar_t *pw;     /* dos pattern to match    */\nZCONST wchar_t *sw;     /* string to match it to   */\nint cs;                 /* force case-sensitive match if TRUE */\n/* Treat filenames without periods as having an implicit trailing period */\n{\n  wchar_t *sw1;         /* revised string to match */\n  int r;                /* result */\n\n  if (wcschr(pw, (wchar_t)'.') && !wcschr(sw, (wchar_t)'.') &&\n      ((sw1 = (wchar_t *)malloc((wcslen(sw) + 2) * sizeof(wchar_t))) != NULL))\n  {\n    wcscpy(sw1, sw);\n    wcscat(sw1, L\".\");\n  }\n  else\n  {\n    /* will usually be OK */\n    sw1 = (wchar_t *)sw;\n  }\n\n  r = recmatchw(pw, sw1, cs) == 1;\n  if (sw != sw1)\n    free((zvoid *)sw1);\n  return r == 1;\n}\n\n#endif\n\n/* XXX  also suitable for OS2?  Atari?  Human68K?  TOPS-20?? */\n\nint dosmatch(p, s, cs)\nZCONST char *p;         /* dos pattern to match    */\nZCONST char *s;         /* string to match it to   */\nint cs;                 /* force case-sensitive match if TRUE */\n/* Treat filenames without periods as having an implicit trailing period */\n{\n  char *s1;             /* revised string to match */\n  int r;                /* result */\n\n  if (strchr(p, '.') && !strchr(s, '.') &&\n      ((s1 = malloc(strlen(s) + 2)) != NULL))\n  {\n    strcpy(s1, s);\n    strcat(s1, \".\");\n  }\n  else\n  {\n    /* will usually be OK */\n    s1 = (char *)s;\n  }\n\n  r = recmatch(p, s1, cs) == 1;\n  if (s != s1)\n    free((zvoid *)s1);\n  return r == 1;\n}\n\n#endif /* DOS || WIN32 */\n\nzvoid far **search(b, a, n, cmp)\nZCONST zvoid *b;        /* pointer to value to search for */\nZCONST zvoid far **a;   /* table of pointers to values, sorted */\nextent n;               /* number of pointers in a[] */\nint (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function */\n\n/* Search for b in the pointer list a[0..n-1] using the compare function\n   cmp(b, c) where c is an element of a[i] and cmp() returns negative if\n   *b < *c, zero if *b == *c, or positive if *b > *c.  If *b is found,\n   search returns a pointer to the entry in a[], else search() returns\n   NULL.  The nature and size of *b and *c (they can be different) are\n   left up to the cmp() function.  A binary search is used, and it is\n   assumed that the list is sorted in ascending order. */\n{\n  ZCONST zvoid far **i; /* pointer to midpoint of current range */\n  ZCONST zvoid far **l; /* pointer to lower end of current range */\n  int r;                /* result of (*cmp)() call */\n  ZCONST zvoid far **u; /* pointer to upper end of current range */\n\n  l = (ZCONST zvoid far **)a;  u = l + (n-1);\n  while (u >= l) {\n    i = l + ((unsigned)(u - l) >> 1);\n    if ((r = (*cmp)(b, (ZCONST char far *)*(struct zlist far **)i)) < 0)\n      u = i - 1;\n    else if (r > 0)\n      l = i + 1;\n    else\n      return (zvoid far **)i;\n  }\n  return NULL;          /* If b were in list, it would belong at l */\n}\n\n#endif /* !UTIL */\n\n#ifdef MSDOS16\n\nlocal unsigned ident(unsigned chr)\n{\n   return chr; /* in al */\n}\n\nvoid init_upper()\n{\n  static struct country {\n    uch ignore[18];\n    int (far *casemap)(int);\n    uch filler[16];\n  } country_info;\n\n  struct country far *info = &country_info;\n  union REGS regs;\n  struct SREGS sregs;\n  unsigned int c;\n\n  regs.x.ax = 0x3800; /* get country info */\n  regs.x.dx = FP_OFF(info);\n  sregs.ds  = FP_SEG(info);\n  intdosx(&regs, &regs, &sregs);\n  for (c = 0; c < 128; c++) {\n    upper[c] = (uch) toupper(c);\n    lower[c] = (uch) c;\n  }\n  for (; c < sizeof(upper); c++) {\n    upper[c] = (uch) (*country_info.casemap)(ident(c));\n    /* ident() required because casemap takes its parameter in al */\n    lower[c] = (uch) c;\n  }\n  for (c = 0; c < sizeof(upper); c++ ) {\n    unsigned int u = upper[c];\n    if (u != c && lower[u] == (uch) u) {\n      lower[u] = (uch)c;\n    }\n  }\n  for (c = 'A'; c <= 'Z'; c++) {\n    lower[c] = (uch) (c - 'A' + 'a');\n  }\n}\n#else /* !MSDOS16 */\n#  ifndef OS2\n\nvoid init_upper()\n{\n  unsigned int c;\n#if defined(ATARI) || defined(CMS_MVS)\n#include <ctype.h>\n/* this should be valid for all other platforms too.   (HD 11/11/95) */\n  for (c = 0; c< sizeof(upper); c++) {\n    upper[c] = islower(c) ? toupper(c) : c;\n    lower[c] = isupper(c) ? tolower(c) : c;\n  }\n#else\n  for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = (uch)c;\n  for (c = 'a'; c <= 'z';        c++) upper[c] = (uch)(c - 'a' + 'A');\n  for (c = 'A'; c <= 'Z';        c++) lower[c] = (uch)(c - 'A' + 'a');\n#endif\n}\n#  endif /* !OS2 */\n\n#endif /* ?MSDOS16 */\n\nint namecmp(string1, string2)\n  ZCONST char *string1, *string2;\n/* Compare the two strings ignoring case, and correctly taking into\n * account national language characters. For operating systems with\n * case sensitive file names, this function is equivalent to strcmp.\n */\n{\n  int d;\n\n  for (;;)\n  {\n    d = (int) (uch) case_map(*string1)\n      - (int) (uch) case_map(*string2);\n\n    if (d || *string1 == 0 || *string2 == 0)\n      return d;\n\n    string1++;\n    string2++;\n  }\n}\n\n#ifdef EBCDIC\nchar *strtoasc(char *str1, ZCONST char *str2)\n{\n  char *old;\n  old = str1;\n  while (*str1++ = (char)ascii[(uch)(*str2++)]);\n  return old;\n}\n\nchar *strtoebc(char *str1, ZCONST char *str2)\n{\n  char *old;\n  old = str1;\n  while (*str1++ = (char)ebcdic[(uch)(*str2++)]);\n  return old;\n}\n\nchar *memtoasc(char *mem1, ZCONST char *mem2, unsigned len)\n{\n  char *old;\n  old = mem1;\n  while (len--)\n     *mem1++ = (char)ascii[(uch)(*mem2++)];\n  return old;\n}\n\nchar *memtoebc(char *mem1, ZCONST char *mem2, unsigned len)\n{\n  char *old;\n  old = mem1;\n  while (len--)\n     *mem1++ = (char)ebcdic[(uch)(*mem2++)];\n  return old;\n}\n#endif /* EBCDIC */\n\n#ifdef IZ_ISO2OEM_ARRAY\nchar *str_iso_to_oem(dst, src)\n  ZCONST char *src;\n  char *dst;\n{\n  char *dest_start = dst;\n  while (*dst++ = (char)iso2oem[(uch)(*src++)]);\n  return dest_start;\n}\n#endif\n\n#ifdef IZ_OEM2ISO_ARRAY\nchar *str_oem_to_iso(dst, src)\n  ZCONST char *src;\n  char *dst;\n{\n  char *dest_start = dst;\n  while (*dst++ = (char)oem2iso[(uch)(*src++)]);\n  return dest_start;\n}\n#endif\n\n\n\n/* DBCS support for Info-ZIP's zip  (mainly for japanese (-: )\n * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)\n * This code is public domain!   Date: 1998/12/20\n */\n#ifdef _MBCS\n\nchar *___tmp_ptr;\n\nint lastchar(ptr)\n    ZCONST char *ptr;\n{\n    ZCONST char *oldptr = ptr;\n    while(*ptr != '\\0'){\n        oldptr = ptr;\n        INCSTR(ptr);\n    }\n    return (int)(unsigned)*oldptr;\n}\n\nunsigned char *zmbschr(str, c)\n    ZCONST unsigned char *str;\n    unsigned int c;\n{\n    while(*str != '\\0'){\n        if (*str == c) {return (unsigned char *)str;}\n        INCSTR(str);\n    }\n    return NULL;\n}\n\nunsigned char *zmbsrchr(str, c)\n    ZCONST unsigned char *str;\n    unsigned int c;\n{\n    unsigned char *match = NULL;\n    while(*str != '\\0'){\n        if (*str == c) {match = (unsigned char*)str;}\n        INCSTR(str);\n    }\n    return match;\n}\n#endif /* _MBCS */\n\n\n\n#ifndef UTIL\n\n/*****************************************************************\n | envargs - add default options from environment to command line\n |----------------------------------------------------------------\n | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.\n | This program is in the public domain.\n |----------------------------------------------------------------\n | Minor program notes:\n |  1. Yes, the indirection is a tad complex\n |  2. Parenthesis were added where not needed in some cases\n |     to make the action of the code less obscure.\n ****************************************************************/\n\nvoid envargs(Pargc, Pargv, envstr, envstr2)\n    int *Pargc;\n    char ***Pargv;\n    char *envstr;\n    char *envstr2;\n{\n    char *envptr;                     /* value returned by getenv */\n    char *bufptr;                     /* copy of env info */\n    int argc;                         /* internal arg count */\n    register int ch;                  /* spare temp value */\n    char **argv;                      /* internal arg vector */\n    char **argvect;                   /* copy of vector address */\n\n    /* see if anything in the environment */\n    envptr = getenv(envstr);\n    if (envptr != NULL)                                /* usual var */\n        while (isspace((uch)*envptr))      /* we must discard leading spaces */\n            envptr++;\n    if (envptr == NULL || *envptr == '\\0')\n        if ((envptr = getenv(envstr2)) != NULL)                 /* alternate */\n            while (isspace((uch)*envptr))\n                envptr++;\n    if (envptr == NULL || *envptr == '\\0')\n        return;\n\n    /* count the args so we can allocate room for them */\n    argc = count_args(envptr);\n    bufptr = malloc(1 + strlen(envptr));\n    if (bufptr == NULL)\n        ziperr(ZE_MEM, \"Can't get memory for arguments\");\n    strcpy(bufptr, envptr);\n\n    /* allocate a vector large enough for all args */\n    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));\n    if (argv == NULL) {\n        free(bufptr);\n        ziperr(ZE_MEM, \"Can't get memory for arguments\");\n    }\n    argvect = argv;\n\n    /* copy the program name first, that's always true */\n    *(argv++) = *((*Pargv)++);\n\n    /* copy the environment args first, may be changed */\n    do {\n#if defined(AMIGA) || defined(UNIX)\n        if (*bufptr == '\"') {\n            char *argstart = ++bufptr;\n            *(argv++) = argstart;\n            for (ch = *bufptr; ch != '\\0' && ch != '\\\"';\n                 ch = *PREINCSTR(bufptr))\n                if (ch == '\\\\' && bufptr[1] != '\\0')\n                    ++bufptr;               /* skip to char after backslash */\n            if (ch != '\\0')                       /* overwrite trailing '\"' */\n                *(bufptr++) = '\\0';\n\n            /* remove escape characters */\n            while ((argstart = MBSCHR(argstart, '\\\\')) != NULL) {\n                strcpy(argstart, argstart + 1);\n                if (*argstart)\n                    ++argstart;\n            }\n        } else {\n            *(argv++) = bufptr;\n            while ((ch = *bufptr) != '\\0' && !isspace((uch)ch)) INCSTR(bufptr);\n            if (ch != '\\0') *(bufptr++) = '\\0';\n        }\n#else\n#  ifdef WIN32\n        /* We do not support backslash-quoting of quotes in quoted */\n        /* strings under Win32, because backslashes are directory  */\n        /* separators and double quotes are illegal in filenames.  */\n        if (*bufptr == '\"') {\n            *(argv++) = ++bufptr;\n            while ((ch = *bufptr) != '\\0' && ch != '\\\"') INCSTR(bufptr);\n            if (ch != '\\0') *(bufptr++) = '\\0';\n        } else {\n            *(argv++) = bufptr;\n            while ((ch = *bufptr) != '\\0' && !isspace((uch)ch)) INCSTR(bufptr);\n            if (ch != '\\0') *(bufptr++) = '\\0';\n        }\n#  else\n        *(argv++) = bufptr;\n        while ((ch = *bufptr) != '\\0' && !isspace((uch)ch)) INCSTR(bufptr);\n        if (ch != '\\0') *(bufptr++) = '\\0';\n#  endif\n#endif /* ?(AMIGA || UNIX) */\n        while ((ch = *bufptr) != '\\0' && isspace((uch)ch)) INCSTR(bufptr);\n    } while (ch);\n\n    /* now save old argc and copy in the old args */\n    argc += *Pargc;\n    while (--(*Pargc)) *(argv++) = *((*Pargv)++);\n\n    /* finally, add a NULL after the last arg, like UNIX */\n    *argv = NULL;\n\n    /* save the values and return */\n    *Pargv = argvect;\n    *Pargc = argc;\n}\n\nlocal int count_args(s)\nchar *s;\n{\n    int count = 0;\n    char ch;\n\n    do {\n        /* count and skip args */\n        ++count;\n#if defined(AMIGA) || defined(UNIX)\n        if (*s == '\\\"') {\n            for (ch = *PREINCSTR(s); ch != '\\0' && ch != '\\\"';\n                 ch = *PREINCSTR(s))\n                if (ch == '\\\\' && s[1] != '\\0')\n                    INCSTR(s);\n            if (*s) INCSTR(s);  /* trailing quote */\n        } else\n            while ((ch = *s) != '\\0' && !isspace((uch)ch)) INCSTR(s);\n#else\n#  ifdef WIN32\n        if (*s == '\\\"') {\n            ++s;                /* leading quote */\n            while ((ch = *s) != '\\0' && ch != '\\\"') INCSTR(s);\n            if (*s) INCSTR(s);  /* trailing quote */\n        } else\n            while ((ch = *s) != '\\0' && !isspace((uch)ch)) INCSTR(s);\n#  else\n        while ((ch = *s) != '\\0' && !isspace((uch)ch)) INCSTR(s);\n#  endif\n#endif /* ?(AMIGA || UNIX) */\n        while ((ch = *s) != '\\0' && isspace((uch)ch)) INCSTR(s);\n    } while (ch);\n\n    return(count);\n}\n\n\n\n/* Extended argument processing -- by Rich Wales\n * This function currently deals only with the MKS shell, but could be\n * extended later to understand other conventions.\n *\n * void expand_args(int *argcp, char ***argvp)\n *\n *    Substitutes the extended command line argument list produced by\n *    the MKS Korn Shell in place of the command line info from DOS.\n *\n *    The MKS shell gets around DOS's 128-byte limit on the length of\n *    a command line by passing the \"real\" command line in the envi-\n *    ronment.  The \"real\" arguments are flagged by prepending a tilde\n *    (~) to each one.\n *\n *    This \"expand_args\" routine creates a new argument list by scanning\n *    the environment from the beginning, looking for strings begin-\n *    ning with a tilde character.  The new list replaces the original\n *    \"argv\" (pointed to by \"argvp\"), and the number of arguments\n *    in the new list replaces the original \"argc\" (pointed to by\n *    \"argcp\").\n */\nvoid expand_args(argcp, argvp)\n      int *argcp;\n      char ***argvp;\n{\n#ifdef DOS\n\n/* Do NEVER include (re)definiton of `environ' variable with any version\n   of MSC or BORLAND/Turbo C. These compilers supply an incompatible\n   definition in <stdlib.h>.  */\n#if defined(__GO32__) || defined(__EMX__)\n      extern char **environ;          /* environment */\n#endif /* __GO32__ || __EMX__ */\n      char        **envp;             /* pointer into environment */\n      char        **newargv;          /* new argument list */\n      char        **argp;             /* pointer into new arg list */\n      int           newargc;          /* new argument count */\n\n      /* sanity check */\n      if (environ == NULL\n          || argcp == NULL\n          || argvp == NULL || *argvp == NULL)\n              return;\n      /* find out how many environment arguments there are */\n      for (envp = environ, newargc = 0;\n           *envp != NULL && (*envp)[0] == '~';\n           envp++, newargc++) ;\n      if (newargc == 0)\n              return;                 /* no environment arguments */\n      /* set up new argument list */\n      newargv = (char **) malloc(sizeof(char **) * (newargc+1));\n      if (newargv == NULL)\n              return;                 /* malloc failed */\n      for (argp = newargv, envp = environ;\n           *envp != NULL && (*envp)[0] == '~';\n           *argp++ = &(*envp++)[1]) ;\n      *argp = NULL;                   /* null-terminate the list */\n      /* substitute new argument list in place of old one */\n      *argcp = newargc;\n      *argvp = newargv;\n#else /* !DOS */\n      if (argcp || argvp) return;\n#endif /* ?DOS */\n}\n\n\n/* Fast routine for detection of plain text\n * (ASCII or an ASCII-compatible extension such as ISO-8859, UTF-8, etc.)\n * Author: Cosmin Truta.\n * See \"proginfo/txtvsbin.txt\" for more information.\n *\n * This function returns the same result as set_file_type() in \"trees.c\".\n * Unlike in set_file_type(), however, the speed depends on the buffer size,\n * so the optimal implementation is different.\n */\nint is_text_buf(buf_ptr, buf_size)\n    ZCONST char *buf_ptr;\n    unsigned buf_size;\n{\n    int result = 0;\n    unsigned i;\n    unsigned char c;\n\n    for (i = 0; i < buf_size; ++i)\n    {\n        c = (unsigned char)buf_ptr[i];\n        if (c >= 32)    /* speed up the loop by checking this first */\n            result = 1; /* white-listed character found; keep looping */\n        else            /* speed up the loop by inlining the following check */\n        if ((c <= 6) || (c >= 14 && c <= 25) || (c >= 28 && c <= 31))\n            return 0;   /* black-listed character found; stop */\n    }\n\n    return result;\n}\n\n#endif /* UTIL */\n\n\n#ifdef DEBUGNAMES\n#undef free\nint Free(x)\nvoid *x;\n{\n    if (x == (void *) 0xdeadbeef)\n        exit(-1);\n    free(x);\n    return 0;\n}\n\nint printnames()\n{\n     struct zlist far *z;\n\n     for (z = zfiles; z != NULL; z = z->nxt)\n           fprintf(mesg, \"%s %s %s %p %p %p %08x %08x %08x\\n\",\n                            z->name, z->zname, z->iname,\n                            z->name, z->zname, z->iname,\n                            *((int *) z->name), *((int *) z->zname),\n                            *((int *) z->iname));\n     return 0;\n}\n\n#endif /* DEBUGNAMES */\n\n\n/* Below is used to format zoff_t values, which can be either long or long long\n   depending on if LARGE FILES are supported.  Function provided by SMS.\n   10/17/04 EG */\n\n/* 2004-12-01 SMS.\n * Brought in fancy fzofft() from UnZip.\n */\n\n/* This implementation assumes that no more than FZOFF_NUM values will be\n   needed in any printf using it.  */\n\n/* zip_fzofft(): Format a zoff_t value in a cylindrical buffer set.\n   This version renamed from fzofft because of name conflict in unzip\n   when combined in WiZ. */\n\n/* 2004-12-19 SMS.\n * I still claim than the smart move would have been to disable one or\n * the other instance with #if for Wiz.  But fine.  We'll change the\n * name.\n */\n\n/* This is likely not thread safe.  Needs to be done without static storage.\n   12/29/04 EG */\n\n/* zip_fzofft(): Format a zoff_t value in a cylindrical buffer set. */\n\n#define FZOFFT_NUM 4            /* Number of chambers. */\n#define FZOFFT_LEN 24           /* Number of characters/chamber. */\n\n\n/* Format a zoff_t value in a cylindrical buffer set. */\n\nchar *zip_fzofft( val, pre, post)\n  zoff_t val;\n  char *pre;\n  char *post;\n{\n    /* Storage cylinder. */\n    static char fzofft_buf[ FZOFFT_NUM][ FZOFFT_LEN];\n    static int fzofft_index = 0;\n\n    /* Temporary format string storage. */\n    static char fmt[ 16] = \"%\";\n\n    /* Assemble the format string. */\n    fmt[ 1] = '\\0';             /* Start after initial \"%\". */\n    if (pre == FZOFFT_HEX_WID)  /* Special hex width. */\n    {\n        strcat( fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex \".width\". */\n    {\n        strcat( fmt, \".\");\n        strcat( fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre != NULL)       /* Caller's prefix (width). */\n    {\n        strcat( fmt, pre);\n    }\n\n    strcat( fmt, FZOFFT_FMT);   /* Long or long-long or whatever. */\n\n    if (post == NULL)\n        strcat( fmt, \"d\");      /* Default radix = decimal. */\n    else\n        strcat( fmt, post);     /* Caller's radix. */\n\n    /* Advance the cylinder. */\n    fzofft_index = (fzofft_index+ 1)% FZOFFT_NUM;\n\n    /* Write into the current chamber. */\n    sprintf( fzofft_buf[ fzofft_index], fmt, val);\n\n    /* Return a pointer to this chamber. */\n    return fzofft_buf[ fzofft_index];\n}\n\n\n/* Format a uzoff_t value in a cylindrical buffer set. */\n/* Added to support uzoff_t type.  12/29/04 */\n\nchar *zip_fuzofft( val, pre, post)\n  uzoff_t val;\n  char *pre;\n  char *post;\n{\n    /* Storage cylinder. */\n    static char fuzofft_buf[ FZOFFT_NUM][ FZOFFT_LEN];\n    static int fuzofft_index = 0;\n\n    /* Temporary format string storage. */\n    static char fmt[ 16] = \"%\";\n\n    /* Assemble the format string. */\n    fmt[ 1] = '\\0';             /* Start after initial \"%\". */\n    if (pre == FZOFFT_HEX_WID)  /* Special hex width. */\n    {\n        strcat( fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex \".width\". */\n    {\n        strcat( fmt, \".\");\n        strcat( fmt, FZOFFT_HEX_WID_VALUE);\n    }\n    else if (pre != NULL)       /* Caller's prefix (width). */\n    {\n        strcat( fmt, pre);\n    }\n\n    strcat( fmt, FZOFFT_FMT);   /* Long or long-long or whatever. */\n\n    if (post == NULL)\n        strcat( fmt, \"u\");      /* Default radix = decimal. */\n    else\n        strcat( fmt, post);     /* Caller's radix. */\n\n    /* Advance the cylinder. */\n    fuzofft_index = (fuzofft_index+ 1)% FZOFFT_NUM;\n\n    /* Write into the current chamber. */\n    sprintf( fuzofft_buf[ fuzofft_index], fmt, val);\n\n    /* Return a pointer to this chamber. */\n    return fuzofft_buf[ fuzofft_index];\n}\n\n\n/* Display number to mesg stream\n   5/15/05 EG */\n\nint DisplayNumString(file, i)\n  FILE *file;\n  uzoff_t i;\n{\n  char tempstrg[100];\n  int j;\n  char *s = tempstrg;\n\n  WriteNumString(i, tempstrg);\n  /* skip spaces */\n  for (j = 0; j < 3; j++) {\n    if (*s != ' ') break;\n    s++;\n  }\n  fprintf(file, \"%s\", s);\n\n  return 0;\n}\n\n/* Read numbers with trailing size multiplier (like 10M) and return number.\n   10/30/04 EG */\n\nuzoff_t ReadNumString( numstring )\n  char *numstring;\n{\n  zoff_t num = 0;\n  char multchar = ' ';\n  int i;\n  uzoff_t mult = 1;\n\n  /* check if valid number (currently no negatives) */\n  if (numstring == NULL) {\n    zipwarn(\"Unable to read empty number in ReadNumString\", \"\");\n    return (uzoff_t)-1;\n  }\n  if (numstring[0] < '0' || numstring[0] > '9') {\n    zipwarn(\"Unable to read number (must start with digit): \", numstring);\n    return (uzoff_t)-1;\n  }\n  if (strlen(numstring) > 8) {\n    zipwarn(\"Number too long to read (8 characters max): \", numstring);\n    return (uzoff_t)-1;\n  }\n\n  /* get the number part */\n  num = atoi(numstring);\n\n  /* find trailing multiplier */\n  for (i = 0; numstring[i] && isdigit(numstring[i]); i++) ;\n\n  /* return if no multiplier */\n  if (numstring[i] == '\\0') {\n    return (uzoff_t)num;\n  }\n\n  /* nothing follows multiplier */\n  if (numstring[i + 1]) {\n    return (uzoff_t)-1;\n  }\n\n  /* get multiplier */\n  multchar = toupper(numstring[i]);\n\n  if (multchar == 'K') {\n    mult <<= 10;\n  } else if (multchar == 'M') {\n    mult <<= 20;\n  } else if (multchar == 'G') {\n    mult <<= 30;\n#ifdef LARGE_FILE_SUPPORT\n  } else if (multchar == 'T') {\n    mult <<= 40;\n#endif\n  } else {\n    return (uzoff_t)-1;\n  }\n\n  return (uzoff_t)num * mult;\n}\n\n\n/* Write the number as a string with a multiplier (like 10M) to outstring.\n   Always writes no more than 3 digits followed maybe by a multiplier and\n   returns the characters written or -1 if error.\n   10/30/04 EG */\n\nint WriteNumString( num, outstring )\n  uzoff_t num;\n  char *outstring;\n{\n  int mult;\n  int written = 0;\n  int i;\n  int j;\n  char digits[4];\n  int dig;\n\n  *outstring = '\\0';\n\n  /* shift number 1 K until less than 10000 */\n  for (mult = 0; num >= 10240; mult++) {\n    num >>= 10;\n  }\n\n  /* write digits as \"    0\" */\n  for (i = 1; i < 4; i++) {\n    digits[i] = ' ';\n  }\n  digits[0] = '0';\n\n  if (num >= 1000) {\n    i = 3;\n    num *= 10;\n    num >>= 10;\n    mult++;\n    digits[0] = (char) (num % 10) + '0';\n    digits[1] = '.';\n    digits[2] = (char) (num / 10) + '0';\n  } else {\n    for (i = 0; num; i++) {\n      dig = (int) (num % 10);\n      num /= 10;\n      digits[i] = dig + '0';\n    }\n  }\n  if (i == 0) i = 1;\n  for (j = i; j > 0; j--) {\n    *outstring = digits[j - 1];\n    outstring++;\n    written++;\n  }\n\n  /* output multiplier */\n  if (mult == 0) {\n  } else if (mult == 1) {\n    *outstring = 'K';\n    outstring++;\n    written++;\n  } else if (mult == 2) {\n    *outstring = 'M';\n    outstring++;\n    written++;\n  } else if (mult == 3) {\n    *outstring = 'G';\n    outstring++;\n    written++;\n  } else if (mult == 4) {\n    *outstring = 'T';\n    outstring++;\n    written++;\n  } else {\n    *outstring = '?';\n    outstring++;\n    written++;\n  }\n\n  *outstring = '\\0';\n\n  return written;\n}\n\n\n#if 0 /* not used anywhere, should get removed by next release... */\n\n/* Apply the Adler-16 checksum to a set of bytes.\n * Use this function as you would use crc32():\n * - First call this function by passing a NULL pointer instead of buf\n *   OR initialize the checksum register with ADLERVAL_INITIAL.\n * - Iteratively call this function for each buffer fragment.\n * This function returns the updated checksum.\n *\n * IN assertion: chksum is a valid Adler-16 checksum:\n *    (chksum & 0xffU) < ADLER16_BASE && ((chksum >> 8) & 0xffU) < ADLER16_BASE\n *\n * Author: Cosmin Truta.\n * See \"proginfo/adler16.txt\" for more information.\n */\n\n#define ADLER16_BASE 251        /* The largest prime smaller than 256 */\n\nunsigned int adler16(chksum, buf, len)\n    unsigned int chksum;\n    ZCONST uch *buf;\n    extent len;\n{\n    unsigned int sum1 = chksum & 0xff;\n    unsigned int sum2 = (chksum >> 8) & 0xff;\n    extent i;\n\n    Assert((sum1 < ADLER16_BASE) && (sum2 < ADLER16_BASE),\n           \"adler16: invalid checksum\");\n\n    if (buf == NULL)\n        return 1;\n\n    for (i = 0; i < len; ++i)\n    {\n        sum1 += buf[i];\n        if (sum1 >= ADLER16_BASE) /* this is faster than modulo ADLER16_BASE */\n            sum1 -= ADLER16_BASE;\n        sum2 += sum1;\n        if (sum2 >= ADLER16_BASE) /* ditto */\n            sum2 -= ADLER16_BASE;\n    }\n\n    return (sum2 << 8) | sum1;\n}\n\n#endif /* 0, not used anywhere */\n\n\n/* returns true if abbrev is abbreviation for matchstring */\nint abbrevmatch (matchstring, abbrev, case_sensitive, minmatch)\n  char *matchstring;\n  char *abbrev;\n  int case_sensitive;\n  int minmatch;\n{\n  int cnt = 0;\n  char *m;\n  char *a;\n\n  m = matchstring;\n  a = abbrev;\n\n  for (; *m && *a; m++, a++) {\n    cnt++;\n    if (case_sensitive) {\n      if (*m != *a) {\n        /* mismatch */\n        return 0;\n      }\n    } else {\n      if (toupper(*m) != toupper(*a)) {\n        /* mismatch */\n        return 0;\n      }\n    }\n  }\n  if (cnt < minmatch) {\n    /* not big enough string */\n    return 0;\n  }\n  if (*a != '\\0') {\n    /* abbreviation longer than match string */\n    return 0;\n  }\n  /* either abbreviation or match */\n  return 1;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/vms/NOTES.TXT",
    "content": "      VMS Notes for Info-ZIP Zip 3.0 and UnZip 6.0\n      ============================================\n\n   This document describes some VMS-specific behavior and implementation\ndetails of the Info-ZIP Zip and UnZip programs.\n\n   Last modified: 2008-04-10.\n\n\n   Command-line Case\n   -----------------\n\n   Zip and UnZip now include code which can preserve the case of\ncommand-line parameters and options, which obviates quoting upper-case\noptions like \"-V\" or \"-Z\".  This works on non-VAX systems with a\nsufficiently recent C RTL, and SET PROCESS /PARSE_STYLE = EXTENDED.\n(Sufficiently recent here means __CRTL_VER >= 70301000, which includes\nVMS V7.3-1 with a C Run Time Library ECO, or V7.3-2 or newer.)   This\ncode uses the decc$feature_set_value() function to enable the\nDECC$ARGV_PARSE_STYLE feature.  There is a small range of C RTL versions\nwhere this function is unavailable, but where manually setting the\nlogical name DECC$ARGV_PARSE_STYLE to \"ENABLE\" will work.   HELP CRTL\nleads to some additional information on these features.\n\n\n   File Name Case (ODS5)\n   ---------------------\n\n   In general, Zip 3.0 and UnZip 6.0 should handle file name case (and\nextended file names) in reasonable ways on ODS5 disks.\n\n   Zip offers a variety of \"-C\" (/PRESERVE_CASE) options to control how\ncase is handled when adding files to an archive.  The default settings\n(\"-C2-\", /PRESERVE_CASE = NOODS2, down-case ODS2 file names; \"-C5\",\n/PRESERVE_CASE = ODS5, preserve case of ODS5 file names) should be\nconsistent with previous Zip versions for files on ODS2 disks, and\nreasonable for files on ODS5 disks.\n\n   UnZip should preserve case when it extracts to an ODS5 destination\ndisk (unless \"-2\" (/ODS2) is specified).  (Note that previous UnZip\nversions, including version 5.52, did not properly preserve case for\ndirectories, which were always up-cased.)\n\n   The Zip and UnZip builders should work properly on ODS2 and ODS5\ndisks, with old (pre-ODS5) and new (case-conscious) versions of MMS (or\nMMK).  All testing was done with SET PROCESS /CASE_LOOKUP = BLIND. \nVarious problems may be expected with /CASE_LOOKUP = SENSITIVE.\n\n   For consistency, the builders should always create product files\n(.OBJ, .EXE, .HLB, and so on) with upper-case names, whether the build\nis done on an ODS2 or ODS5 disk.  Note, however, that in a world with\nboth ODS2 and ODS5 disks, and old and new Zip and UnZip versions, it's\npossible to encounter lower-case product file names.  For example, a VMS\nbinary kit could be created on an ODS2 disk, and a Zip archive created\nfrom that (using Zip 2.x, or Zip 3.x with default settings).  Such a Zip\narchive would contain down-cased names for those product files, and\nthose lower-case names would then normally be preserved when UnZip was\nused to extract that archive onto an ODS5 destination.  Normally, things\nwill work regardless of such case changes, but there may be some\nuntested combinations of unexpected name cases and quirky MMS (or MMK)\nbehavior, where something goes wrong.  Complaints are always welcome,\nbut it may not be possible to get everything to work as expected with\nevery version of VMS, MMS (or MMK), Zip, and UnZip, on every file\nsystem.\n\n   It might help matters if _all_ VMS binary kits were produced on ODS5\ndisks, and packaged using (case-preserving) Zip version 3.x, but this\nwould certainly be different from the way things have been done before,\nand maintaining control over this process is essentially impossible.\n\n\n   Symbolic Links (ODS5)\n   ---------------------\n\n   VMS V8.3 offers support for symbolic links (symlinks) on ODS5 disks.\nIn previous Zip and UnZip versions, the generic code for symlinks was\ndisabled, and there was no VMS-specific code for symlinks.  Now, by\ndefault, Zip and UnZip attempt to support symlinks wherever the C\nheaders and C run-time library include the functions needed for symlink\nsupport.  This means non-VAX systems with __CRTL_VER >= 70301000, so\nthis includes VMS V7.3-1 and up, and thus symlink-capable Zip and UnZip\nprograms may be built on systems which do not themselves offer symlink\nsupport.  (Various run-time failures may be expected if symlinks are\nencountered on pre-V8.3 systems, either in a file system or in a Zip\narchive.)\n\n   Symlink support can be disabled at build-time, if desired, by\ndefining the C macro NO_SYMLINKS.  (See comments in the builder\nregarding LOCAL_UNZIP or LOCAL_ZIP, as appropriate.)  For example, using\nMMS to build UnZip:\n\n      MMS /DESCRIP = [.VMS] /MACRO = (\"LOCAL_UNZIP=NO_SYMLINKS=1\")\n\nor, using the command procedure to build Zip:\n\n      LOCAL_ZIP == \"NO_SYMLINKS=1\"\n      @ [.VMS]BUILD_ZIP.COM\n      DELETE /SYMBOL /GLOBAL LOCAL_ZIP\n\n   The Zip \"-v\" (/VERBOSE) report should include SYMLINK_SUPPORT in its\nlist of \"Zip special compilation options\" if Zip was built with symlink\nsupport.  Currently, UnZip is less convenient, but searching the UnZip\nexecutable (or EXTRACT.OBJ) for \"symlink\" should fail if symlink support\nis missing (or succeed if it's present):\n\n      $ SEARCH /NOOUTPUT UNZIP.EXE SYMLINK      ! No symlink support.\n      %SEARCH-I-NOMATCHES, no strings matched\nor:\n      $ SEARCH /NOOUTPUT EXTRACT.OBJ SYMLINK    ! Symlink support.\n      $ SHOW SYMBOL $STATUS\n        $STATUS == \"%X00000001\"\n\n\n   File I/O Performance\n   --------------------\n\n   When compiled using DEC/Compaq/HP C (not GNU C or VAX C), the Zip and\nUnZip file I/O code now includes access callback functions which are\nused to try to set some RMS parameters to non-default values, with the\nintention of improving file I/O speed.  This affects reading an archive\nfile in UnZip and writing one in Zip.  (Reading and writing the\nindividual data files are handled in more exotic ways, making these\nparameters less important for them.)\n\n   Currently, the built-in default parameters enable read-ahead and\nwrite-behind, using a multi-buffer count of 2, and a multi-block count\nof 127 (the maximum).  For writing the archive, the default extend\nquantity is 16384 blocks (8MB), with truncation enabled.  This\ncombination is believed to be, at worst, fairly harmless for most\nsituations, and, in most cases, to provide a substantial speed\nimprovement, especially with large archives.\n\n   This code allows SET RMS_DEFAULT parameters to override the built-in\ndefault values.  On some old VMS versions, sys$getjpi() can not provide\nthe SET RMS_DEFAULT values, and in this situation, the callback function\nwill not try to use its improved parameter values.  Users on such old\nVMS versions who seek improved I/O speed may wish to bypass this check,\nwhich requires changing the code in the get_rms_defaults() function in\n[.VMS]VMS.C.  The \"-vv\" (/VERBOSE = MORE) option on both programs\nenables diagnostic messages which show the operation of the callback\nfunction.  A message showing a failure status from sys$getjpi()\nindicates this problem.\n\n   Sample results (UnZip shown, Zip similar):\n\n   VMS VAX V5.4, VAX C.  Callback code disabled, no messages:\n      WIMP $ unzip -tvv TESTMAKE.ZIP\n      Archive:  SYS$SYSDEVICE:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMS VAX V5.5-2, DEC C.  SYS$GETJPI() fails (%SYSTEM-F-BADPARAM):\n      WEAK $ unzip -tvv TESTMAKE.ZIP\n      Get RMS defaults.  getjpi sts = %x00000014.\n      Archive:  DUA1:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMS VAX V7.3, DEC/Compaq C.  Callback code works:\n      WUSS $ unzip -tvv TESTMAKE.ZIP\n      Get RMS defaults.  getjpi sts = %x00000001.\n                     Default: deq =      0, mbc =   0, mbf =   0.\n      Open callback.  ID = 1, deq =  16384, mbc = 127, mbf =   2.\n      Archive:  ALP$DKA0:[UTILITY.SOURCE.ZIP.UNZIP60C]TESTMAKE.ZIP;1\n      [...]\n\n   VMSV5.5-2 is too old.  V7.3 is new enough.  Anyone with more precise\ninformation is invited to contribute it.\n\n   Users who find other parameter sets more beneficial, or who find\nparticular problems with this set are welcome to comment.\n\n   In this version, as in previous versions, when UnZip expands a -V\narchive, it allocates the entire extent of a data file before writing\nany of its data.  In some previous versions, this could cause the\ndestination disk to be locked for a considerable time (minutes), if\nhighwater marking was enabled on that disk.  Now, the FAB SQO\n(\"sequential access only\") flag (or equivalent) is set, which prevents\nthis troublesome disk locking.\n\n   In some previous versions, when UnZip expanded a non-V archive, it\ndid no pre-allocation, and used the default extension quantity.  This\ncould slow file creation significantly for large files.  Now, space for\nextracted files is pre-allocated, and the same SQO (\"sequential access\nonly\") flag is set, as with a -V archive.\n\n\n   Changes to the \"-V\" (/VMS) Option\n   ---------------------------------\n\n   The intent of the \"-V\" (/VMS) option was to store VMS file attributes\nin a Zip archive, allowing UnZip to extract an exact copy of a file on a\nVMS system, including all its VMS attributes.\n\n   In Zip before version 2.31, using the \"-V\" (/VMS) option created an\narchive which usually contained data from beyond the EOF (End-of-File)\nmarker in a data file, but generally not all the disk blocks allocated\nfor the file.  When extracted on a VMS system, the result was usually\nacceptable (because the data from beyond the EOF marker were usually\nignored).  However, when extracted on a non-VMS system, the resulting\nfile was usually corrupted by being NUL-padded to the next larger 16KB\nmultiple in size.\n\n   Now (Zip 2.31 and later), with \"-V\" (/VMS), Zip truncates a data file\nat EOF, and portable-format files (Stream_LF, fixed-512) should be\nextracted properly on a non-VMS system.  On a VMS system, well-formed\nfiles (that is, those with no valid data beyond EOF) should also be\nrestored correctly.\n\n   With the new \"-VV\" (/VMS = ALL) option, the archive includes all\nallocated blocks for the file (including those beyond EOF).  When\nextracted on a VMS system, the original file should be reproduced with\nas much fidelity as possible, but on a non-VMS system, most files will\nbe seen as corrupt because of the data from beyond EOF.\n\n\n   Changes to Program Exit Status Values\n   -------------------------------------\n\n   Zip and UnZip exit with 32-bit VMS status values which are formed\nfrom their internal OS-independent status values.  In previous program\nversions, this was done by converting the internal success code (0) into\n%x00000001 (SS$_NORMAL), and converting the other internal warning and\nerror codes using an artificial control/facility code, 0x7FFF (which\nincludes some reserved bits), and a severity value which was determined\naccording to rules specified in the VMS-specific exit function.\nCuriously, the internal status codes were left-shifted by 4 bits instead\nof 3, so all the resulting VMS message codes (bits 13:3) were even.\n\n   Zip and UnZip now have facility names and codes assigned by HP\n(UnZip: IZ_UNZIP, 1954; Zip: IZ_ZIP, 1955).  Now, by default, the\nprograms exit with standard 32-bit VMS status values which differ from\nthe old ones in several ways: The official facility code is used, and\nthe facility-specific bit is set.  (For compatibility with older\nversions, the internal status codes are still left-shifted by 4 bits. \nThis also makes it easier to extract the internal status code from a\nhexadecimal representation of the VMS status code.)  The builders also\ncreate non-executable message files (UNZIP_MSG.EXE and ZIP_MSG.EXE) so\nthat, after a suitable SET MESSAGE command, the program messages will be\navailable from DCL.  For example:\n\n      $ SET MESSAGE dev:[dir]ZIP_MSG.EXE\n      $ ZIP FRED.ZIP no_such_file\n        zip warning: name not matched: no_such_file\n\n      zip error: Nothing to do!\n      (dev:[dir]FRED.ZIP;)\n\n      ALP $ WRITE SYS$OUTPUT F$MESSAGE( $STATUS)\n      %IZ_ZIP-W-NONE, Nothing to do\n\nThe message files may be copied into SYS$MESSAGE to make them generally\navailable, although this could cause some confusion if multiple versions\nof the programs are used on the system, and their error message source\nfiles differ.  Each different destination directory will get its own\nUNZIP_MSG.EXE or ZIP_MSG.EXE ([.ALPHA], [.ALPHAL], [.VAX], and so on),\nbut all of the same-architecture files are equivalent to each other.\nThat is, on an Alpha system, any of the [.ALPHA*]ZIP_MSG.EXE files could\nbe used; on an IA64 system, any of the [.IA64*]ZIP_MSG.EXE files could\nbe used; and on a VAX system, any of the [.VAX*]ZIP_MSG.EXE files could\nbe used.  (Similar for UNZIP_MSG.EXE, of course.)\n\n   If desired, the programs may be built to use the old exit status values\nby defining a C macro with the old facility value:\n\"CTL_FAC_IZ_UNZIP=0x7FFF\" (UnZip) or \"CTL_FAC_IZ_ZIP=0x7FFF\" (Zip).\n(See comments in the builder regarding LOCAL_UNZIP or LOCAL_ZIP, as\nappropriate.)  This will maintain compatibility with older program\nversions, but will make the programs incompatible with the new error\nmessage files.\n\n\n   VMS File Attribute Schemes\n   --------------------------\n\n   Zip's \"-V\" (/VMS) option causes VMS file attributes to be stored in\nan archive.  Since Zip version 2.2 (released in 1996), Zip has, by\ndefault, stored VMS file attributes using a scheme (\"PK\") which is\ncompatible with the one used by PKWARE in their PKZIP product.  Before\nthat, a different scheme (\"IM\") was used.  UnZip versions before 5.2\nsupport only the older IM scheme, but since UnZip version 5.2, both\nschemes have been supported by UnZip.\n\n   The IM scheme has not been well tested recently, but it is still\navailable.  Some problems were seen when the IM scheme was used with\nsymbolic links on VMS V8.3.  Details on how build Zip to use the IM\nscheme instead of the PK scheme are included in comments in the main\nbuilder files.  Look for VMS_IM_EXTRA in [.VMS]BUILD_ZIP.COM or IM in\n[.VMS]DESCRIP.MMS.\n\n   The \"special compilation options\" section of a \"zip -v\" (\"zip\n/verbose\") report should show either VMS_PK_EXTRA or VMS_IM_EXTRA,\naccording to how Zip was built.\n\n\n   UTC Date-Times\n   --------------\n\n   Zip archives traditionally include local (MS-DOS compatible)\ndate-time information for files.  Since Zip version 2.1, it has also\nbeen possible to store UTC date-time information in the archive, and\nsince UnZip version 5.2, UnZip has been able to use this UTC date-time\ninformation when extracting files.\n\n   On VMS, support in the C run-time environment for UTC became\navailable with VMS V7.0.  UTC support in Zip and UnZip is automatically\nenabled at compile time, if it is available on the system where the code\nis compiled (__CRTL_VER >= 70000000).  It may be disabled at compile\ntime by defining the C macro NO_EF_UT_TIME.  Details on how build Zip\nand UnZip with additional C macros defined are included in comments in\nthe main builder files.  Look for LOCAL_[UN]ZIP in\n[.VMS]BUILD_[UN]ZIP.COM or in [.VMS]DESCRIP.MMS.  For example, using MMS\nto build UnZip:\n\n      MMS /DESCRIP = [.VMS] /MACRO = (\"LOCAL_UNZIP=NO_EF_UT_TIME=1\")\n\nor, using the command procedure to build Zip:\n\n      LOCAL_ZIP == \"NO_EF_UT_TIME=1\"\n      @ [.VMS]BUILD_ZIP.COM\n      DELETE /SYMBOL /GLOBAL LOCAL_ZIP\n\n   The \"special compilation options\" section of a \"zip -v\" (\"zip\n/verbose\") or \"unzip -v\" (\"unzip /verbose\") report should show\nUSE_EF_UT_TIME if the program was built with UTC support.\n\n\n   Building with the LIST option using MMK or MMS\n   ----------------------------------------------\n\n   Currently, building with MMK or MMS using the LIST option (as in\n\"/MACRO = LIST=1\") may cause a failure for some old versions of the DEC\nC compiler.  The LIST option currently adds \"/show = (all, nomessages)\"\nto the CC command line, and some old DEC C compilers do not support the\n\"nomessages\" keyword.  When VAX C is used, this keyword is omitted, but\nthe builder does not distinguish between the various DEC/Compaq/HP C\nversions.  The work-arounds are to use BUILD_[UN]ZIP.COM, or edit\n[.VMS]DESCRIP_SRC.MMS to remove the troublesome keyword.\n\n\n   GNU C\n   -----\n\n   Zip and UnZip have been built using GNU C (VAX) version 2.3, mostly\nfor fun, but serious users are encouraged to report any interest in\ncontinuing this activity.  The GNU C 2.3 header files were missing some\nthings, including definitions of SEEK_CUR, SEEK_END, and SEEK_SET.  The\nVMS-specific code now expects to find unixio.h and unixlib.h, which were\nabsent from the GNU C 2.3 distribution.\n\n   To work around these difficulties, the Zip and UnZip kits include\nsome emergency replacement unixio.h and unixlib.h files which appear to\nwork for these programs, at least.  To install them, use commands like\nthe following:\n\n      COPY [.VMS]UNIXIO_GCC.H GNU_CC_INCLUDE:[000000]UNIXIO.H\n      COPY [.VMS]UNIXLIB_GCC.H GNU_CC_INCLUDE:[000000]UNIXLIB.H\n      SET PROTECTION W:RE GNU_CC_INCLUDE:[000000]UNIXIO.H, UNIXLIB.H\n\n   There may be an error in the GNU C header file ATRDEF.H which can\ncause Zip to fail, when making a \"-V\" archive, with a spurious \"could\nnot open for reading\" error message, followed by more bad behavior.  It\nprobably also causes trouble of some kind in UnZip.  To check the\nquestionable macro definition, use a command like the following:\n\n      SEARCH GNU_CC_INCLUDE:[000000]ATRDEF.H ATR$S_JOURNAL\n\nThis should show something equivalent to this:\n\n      #define ATR$S_JOURNAL           0x001\n\nIf you see \"0x002\" (or equivalent) instead of \"0x001\" (or equivalent),\nthen this value must be corrected in the file before building Zip or\nUnZip.\n\n   You may also see several warnings from the compiler caused by other\ndefects in the GNU C header files, such as:\n\n<various>: warning: passing arg 4 of `qsort' from incompatible pointer type\n\n[...]rab.h:134: warning: unnamed struct/union that defines no instances\n[...]rab.h:143: warning: unnamed struct/union that defines no instances\n\nThese warnings appear to be harmless.\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/VMS_ZIP.RNH",
    "content": ".!\n.!  File:       ZIP.RNH\n.!\n.!  Author:     Hunter Goatley\n.!\n.!  Date:       October 22, 1991\n.!\n.!  Description:\n.!\n.!      RUNOFF source file for portable ZIP on-line help for VMS.\n.!      Adapted from MANUAL, distributed with ZIP.\n.!\n.!      To build:       $ RUNOFF ZIP.RNH\n.!                      $ LIBR/HELP/INSERT libr ZIP\n.!\n.!  Modification history:\n.!\n.!      Hunter Goatley          22-OCT-1991 20:45\n.!              Genesis.\n.!      Jean-loup Gailly        25 March 92\n.!              Adaptation to zip 1.6.\n.!      Igor Mandrichenko       9-JUN-1992\n.!              Added explanation of -V option.\n.!      Jean-loup Gailly        14 June 92\n.!              Adaptation to zip 1.8.\n.!      Jean-loup Gailly        20 Aug 92\n.!              Adaptation to zip 1.9.\n.!      Jean-loup Gailly        31 Aug 93\n.!              Adaptation to zip 2.0.\n.!      Christian Spieler       20 Sep 93\n.!              Adaptation to zip 2.0 and OpenVMS completed.\n.!      Christian Spieler       05 Dec 95\n.!              Adaptation to zip 2.1, new options.\n.!      Christian Spieler       20 Jan 96\n.!              Changed -L and -v descriptions.\n.!      Christian Spieler       11 Feb 96\n.!              Added -X option.\n.!      Onno van der Linden,\n.!      Christian Spieler       13 Mar 96\n.!              Removed -ee option.\n.!      Christian Spieler       09 Feb 96\n.!              Updated copyright notice, Zip version.\n.!      Christian Spieler       21 Jul 97\n.!              Added -P, -R, -i@, -x@ and -tt options, modified for Zip 2.2.\n.!      Christian Spieler       14 Oct 97\n.!              unified spelling of \"Info-ZIP\", final cleanups for 2.2.\n.!      Steven Schweda          10 May 2007\n.!              General update for version 3.0.\n.!      Ed Gordon               12 May 2007\n.!              Minor updates for version 3.0.\n.!\n.noflags\n.lm4 .rm72\n.indent -4\n1 ZIP\n.br\nZip is a compression and file packaging utility for several operating\nsystems, including UNIX, VMS,  MSDOS, OS/2, Windows 9x/NT/XP, Minix, Atari,\nMacintosh, Amiga, and Acorn RISC OS.  It is analogous to a combination of\ntar and compress and is compatible with PKZIP (Phil Katz's ZIP) for\nMSDOS systems.\n.sk\nZip is useful for packaging a set of files for distribution, for\narchiving files, and for saving disk space by temporarily compressing\nunused files or directories.  A companion program, UnZip, unpacks Zip\narchives.\n.sk\nFor brief help on Zip or UnZip, run the program without specifying any\nparameters on the command line.\n.sk\nThis description covers the Zip program which uses a UNIX-style command\nline.  A separate program is available which provides a VMS-style CLI\ncommand line, and it has its own documentation.  Refer to the Zip\ninstallation instructions for details.\n.sk\nFormat\n.sk;.lm+2;.literal\nZIP [-options] archive inpath inpath ...\n.end literal;.lm-2\n.!------------------------------------------------------------------------------\n.indent -4\n2 Basic_Usage\n.br\nFormat\n.sk;.lm+2;.literal\nZIP [-options] archive inpath inpath ...\n.end literal;.lm-2\n.sk\nThe default action of Zip is to add or replace entries in \"archive\" from\nthe list of \"inpath\" file specifications, which can include directories\nand file names with VMS-style wildcards, or the special name -@ to read\nfile specifications from SYS$INPUT (stdin).\n.sk\nWith SET PROCESS /PARSE_STYLE = EXTENDED (available on recent non-VAX\nsystems), Zip preserves the case of the command line.  Otherwise, mixed-\nor upper-case options and arguments must be quoted.  For example,\n\"-V\".  Examples in this document generally do not show this quotation,\nso VAX and /PARSE_STYLE = TRADITIONAL users (that is, troglodytes) will\nneed to add quotation where needed when working with these examples.\n.sk\nGeneral\n.sk\nZip reads one or more files, compresses the data (normally), and stores\nthe compressed information into a single Zip archive file, along with\ninformation about each file (name, path, date and time of last\nmodification, protection, and check information to verify file\nintegrity).  On a VMS system, Zip can also save VMS/RMS file attributes,\nallowing UnZip to restore the files without loss of important file\nattributes.  Zip can pack an entire directory structure into a Zip\narchive with a single command.\n.sk\nCompression\n.sk\nCompression ratios of 2:1 to 3:1 are common for text files.  Zip has one\nstandard compression method (\"deflate\") and can also store files without\ncompression.  Zip (and UnZip) may be built with optional support for the\nbzip2 compression method.  Then, the user may select bzip2 compression\ninstead of the default \"deflate\" method.  Zip automatically chooses\nsimple storage over compression for a file, if the specified compression\nmethod does not actually compress the data in that file.\n.sk\nCompatibility\n.sk\nZip and UnZip can work with archives produced by PKZIP (supporting most\nPKZIP features up to PKZIP version 4.6), and PKZIP and PKUNZIP can work\nwith archives produced by Zip (with some exceptions, notably streamed\narchives, but recent changes in the .ZIP file standard may facilitate\nbetter compatibility).  Zip version 3.0 is compatible with PKZIP 2.04\nand also supports the Zip64 extensions of PKZIP 4.5 which allows\narchives as well as files to exceed the previous 2 GB limit (4 GB in\nsome cases).  Zip also supports bzip2 compression if the bzip2 library\nis included when Zip is built.  Note that PKUNZIP 1.10 cannot extract\nfiles produced by PKZIP 2.04 or Zip 3.0.  You must use PKUNZIP 2.04g or\nUnZip 5.0p1 (or later versions) to extract them.\n.sk\nLarge Archives and Zip64\n.sk\nWhere the operating system and C run-time support allow, Zip 3.0 and\nUnZip 6.0 (and later versions) support large files (input and archive),\nusing the Zip64 extensions to the original .ZIP file format.  On VMS,\nthis genarally means non-VAX systems with VMS V7.2 or later (perhaps\nrequiring a C RTL ECO before VMS V7.3-2).\n.sk\nZip automatically uses the Zip64 extensions when a file larger than 2 GB\nis added to an archive, an archive containing a Zip64 entry is updated\n(if the resulting archive still needs Zip64), the size of the archive\nwill exceed 4 GB, or when the number of entries in the archive will\nexceed about 64K.  Zip64 is also used for archives streamed to a\nnon-seekable output device.  You must use a 4.5 compatible UnZip to\nextract files using the Zip64 extensions such as UnZip 6.0 or later.\n.sk\nIn addition, streamed archives, entries encrypted with standard\nencryption, or split archives created with the pause option may not be\ncompatible with PKZIP as data descriptors are used, and PKZIP at the \ntime of this writing does not support data descriptors (but recent\nchanges in the PKWare published .ZIP file standard now include some\nsupport for the data descriptor format Zip uses).\n.!------------------------------------------------------------------------------\n.indent -4\n2 More_Usage\n.br\nHere is a very simple example of Zip use:\n.sk;.indent 10;\n$ zip stuff.zip *.*\n.sk\nThis will create the Zip archive \"stuff.zip\" (assuming it does not\nalready exist) and put all the (non-directory) files (\";0\") from the\ncurrent default directory into \"stuff.zip\" in a compressed form.  The\narchive is opened using a default file specification of\n\"SYS$DISK:[].zip\", so specifying \"stuff\" as the archive name would also\ncreate (or use an existing) \"stuff.zip\", but specifying \"stuff.other\"\nwould give you that name.  In general, Zip doesn't care about the type\nin the file specification, but for split archives (archives split over\nmultiple files), the user should normally specify a type-less name,\nbecause Zip will normally generate sequentially numbered types \".z01\",\n\".z02\", and so on for the early splits, and then the required \".zip\" for\nthe last split.  These file types are required by the Zip standard for\nsplit archives.\n.sk\nStandard VMS wildcard expansion ($SEARCH) is used to interpret the\n\"inpath\" file and directory specifications, like the \"*.*\" in this\nexample.\n.sk\nOn VMS, the most natural way to archive an entire directory tree is to\nuse a directory-depth wildcard (\"[...]\").  For example:\n.sk;.indent 10\nzip foo [...]*.*\n.sk\nThis will create the file \"foo.zip\" containing all the files (\";0\") and\ndirectories in and below the current default directory.  A more\nUNIX-like way to do this would be to use the -r (--recurse-paths)\noption:\n.sk;.indent 10\n$ zip -r foo *.*\n.sk\nZip avoids including its own output files when selecting files to\ninclude in the archive, so it should be safe, as in this case, to create\nthe archive in the same drectory as the input files.\n.sk\nOne or more specific files, directories, or subdirectories may also be\nspecified:\n.lm +10;.literal\nzip foo.zip readme.txt [www...]*.* [.ftp...]*.* -\n [.src]*.h [.src]*.c\n.end literal;.lm -10\n.sk\nFor security reasons, paths in Zip archives are always stored as\nrelative paths, so some care is needed when creating an archive so that\nit will create the intended directory structure when UnZip is used to\nunpack it.\n.sk\nTo use -r with a specific directory, the name of the directory file\nitself must be specified:\n.sk;.indent 10\nzip -r foo.zip [000000]www.dir ftp.dir\n.sk\nYou may want to make an archive that contains the files in [.foo], but not\nrecord the directory name, \"foo\".  You can use the -j (junk path) option\nto leave off the path:\n.sk;.indent 10\n$ zip -j foo [.foo]*.*\n.sk\nIf you are short on disk space, you might not have enough room to hold\nboth the original directory and the corresponding compressed Zip\narchive.  In this case, you can create the archive in steps, and use the\n-m option.  For example, if [.foo] contains the subdirectories [.tom],\n[.dick], and [.harry], you could:\n.sk\n.lm +10;.literal\nzip -m foo [.foo.tom...]*.*\nzip -m foo [.foo.dick...]*.*\nzip -m foo [.foo.harry...]*.*\n.end literal;.lm -10\n.sk\nThe first command would create foo.zip, and the next two would add to\nit.  The -m option means \"move\", and it will cause Zip to delete all\nfiles added to the archive after making or updating foo.zip.  No\ndeletions will be done until the Zip operation has completed with no\nerrors.  This option is obviously dangerous and should be used with\ncare, but it does reduce the need for free disk space.  When -m is\nused, the -T option is recommended and will test the resulting archive\nbefore deleting the input files.\n.sk\nIf a file specification list is too long to fit conveniently on the Zip\ncommand line, the -@ option can be used to cause Zip to read a list of\nfile specifications from SYS$INPUT (stdin).  If a DCL command procedure\nis used, the names can be specified in the procedure:\n.sk;\n.lm +10;.literal\n$ zip foo -@\n$ deck\nfile_spec_1\nfile_spec_2\nfile_spec_3\n$ eod\n.end literal;.lm -10\n.sk\nThe file specifications can also be put into a separate file, and fed\ninto Zip by explicitly defining SYS$INPUT, or by using PIPE.  For\nexample, with the list in foo.zfl:\n.sk;\n.lm +10;.literal\n$ define /user_mode sys$input foo.zfl\n$ zip foo -@\n.end literal;.lm -10;\nor:\n.lm +10;.literal\n$ pipe type foo.zfl | zip foo -@\n.end literal;.lm -10\n.sk\nIf Zip is not able to read a file, it issues a warning but continues.\nSee the -MM option for more on how Zip handles patterns that are not\nmatched and files that are not readable.  If some files were skipped, a\nwarning is issued at the end of the Zip operation noting how many files\nwere read and how many skipped.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Comments\n.br\nOne-line comments may be included in the archive for each file added,\nusing the -c (--entry-comments) option.  File operations (adding,\nupdating) are done first, and the user is then prompted for a one-line\ncomment for each file added or updated.  Enter the comment followed by\n<Return>, or just <Return> for no comment.\n.sk\nA single multi-line comment may be included for the archive as a whole,\nusing the -z (--archive-comment) option.  UnZip (including UnZip SFX)\nwill display this comment when it expands the archive.  The comment is\nread from SYS$INPUT (stdin), and is terminated by the usual end-of-file\ncharacter, CTRL/Z.  As usual, in a DCL command procedure, these data can\nbe included in-line in the procedure, or a user may DEFINE SYS$INPUT to\na file to get the comment from that file.  Where supported, the DCL PIPE\ncommand can also be used to redirect SYS$INPUT from a file.\n.sk\nNote that -z (--archive-comment) and -@ (read file specifications from\nSYS$INPUT (stdin)) can't be used together (successfully).\n.!------------------------------------------------------------------------------\n.indent -4\n2 Compression\n.br\nZip can archive files with or without compression.  The standard\ncompression method (\"deflate\") is compatible with all UnZip versions\n(except really old ones that only understand the \"store\" method). \nCurrent Zip and UnZip versions may be built with optional support for\nthe bzip2 compression method.  (The bzip2 method can compress better,\nespecially when compressing smaller files, but uses more CPU time, and\nrequires an UnZip which includes the optional bzip2 support.  See the\ninstallation instructions for details on adding bzip2 compression\nsupport at build time.)\n.sk\nNumeric compression level options control the effort put into data\ncompression, with -1 being the fastest, and -9 giving the most\ncompression.\n.sk\nCompression control options:\n.sk;.lm +10;.literal\n-Z mthd                      use compress method \"mthd\",\n--compression-method mthd    \"bzip2\" or \"deflate\" (default)\n\n-0  (--store)                no compression\n-1  (--compress-1)           compression level 1\n-2  (--compress-2)           compression level 2\n-3  (--compress-3)           compression level 3\n-4  (--compress-4)           compression level 4\n-5  (--compress-5)           compression level 5\n-6  (--compress-6)           compression level 6\n-7  (--compress-7)           compression level 7\n-8  (--compress-8)           compression level 8\n-9  (--compress-9)           compression level 9\n.end literal;.lm -10\n.sk\nNormally, a file which is already compressed will not be compressed much \nfurther (if at all) by Zip, and trying to do it can waste considerable\nCPU time.  Zip can suppress compression on files with particular types,\nspecified as a colon- or semi-colon-separated list of file types:\n.sk;.indent 10\n-n type1[:type2[...]]  (--suffixes type1[:type2[...]])\n.sk\nFor example:\n.sk;.indent 10\nzip -n .bz2:.gz:.jpeg:.jpg:.mp3:.zip foo [.foo]*.*\n.sk\nwill put everything (\";0\") from [.foo] into foo.zip, but will store any\nfiles that end in .bz2, .gz, .jpeg, .jpg, .mp3, or .zip, without trying\nto compress them.\n.sk\nThe default type list is .Z:.zip:.zoo:.arc:.lzh:.arj, and the comparison\nis case-insensitive.\n.sk\n-9 (--compress-9) will override -n (--suffixes), causing compression to\nbe attempted for all files.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Encryption\n.br\nZip offers optional encryption, using a method which by modern standards\nis generally considered to be weak.\n.sk;.literal\n-e  --encrypt\n.end literal;.br\nEncrypt new or updated archive entries using a password which is\nsupplied by the user interactively on the terminal in response to a\nprompt.  (The password will not be echoed.)  If SYS$COMMAND is not a\nterminal, Zip will exit with an error.  The password is verified before\nbeing accepted.\n.sk;.literal\n-P password  --password password\n.end literal;.br\nUse \"password\" to encrypt new or updated archive entries (if any). \nUSING -P IS INSECURE!   Many multi-user operating systems provide ways\nfor any user (or a privileged user) to see the current command line of\nany other user.  Even on more secure systems, there is always the threat\nof over-the-shoulder peeking.  Storing the plaintext password as part of \na command line in a command procedure is even less secure.  Whenever\npossible, use the non-echoing, interactive password entry method.\n.sk\nBecause standard Zip encryption is weak, where security is truly\nimportant, use a strong encryption program, such as Pretty Good Privacy\n(PGP) or GNU Privacy Guard (GnuPG), on an archive instead of standard\nZip encryption.  A stronger encryption method, such as AES, is planned\nfor Zip 3.1.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Exit_Status\n.br\nOn VMS, Zip's UNIX-style exit values are mapped into VMS-style status\ncodes with facility code 1955 = %x7A3, and with the inhibit-message\n(%x10000000) and facility-specific (%x00008000) bits set:\n.sk\n.literal\n   %x17A38001                        normal exit\n   %x17A38000+ 16* Zip_error_code    warnings\n   %x17A38002+ 16* Zip_error_code    normal errors\n   %x17A38004+ 16* Zip_error_code    fatal errors\n.end literal\n.sk\nNote that multiplying the UNIX-style Zip error code by 16 places it\nconveniently in the hexadecimal representation of the VMS exit code,\n\"__\" in %x17A38__s, where \"s\" is the severity code.  For example, a\ntruncated archive might cause Zip error code 2, which would be\ntransformed into the VMS exit status %x17A38024.\n.sk\nThe Zip VMS exit codes include severity values which approximate those\ndefined by PKWARE, as shown in the following table:\n.literal\n\n    VMS      Zip err\n  severity    code     Error description\n ----------+---------+----------------------------------------------\n  Success       0      Normal; no errors or warnings detected.\n  Fatal         2      Unexpected end of archive.\n  Error         3      A generic error in the  archive  format  was\n                       detected.   Processing  may  have  completed\n                       successfully anyway;  some  broken  archives\n                       created by other archivers have simple work-\n                       arounds.\n  Fatal         4      Zip was unable to allocate memory for one or\n                       more  buffers during program initialization.\n  Fatal         5      A severe error in  the  archive  format  was\n                       detected.   Processing probably failed imme-\n                       diately.\n  Error         6      Entry too large to be split with zipsplit.\n  Error         7      Invalid comment format.\n  Fatal         8      Zip -T failed or out of memory.\n  Error         9      The user aborted zip prematurely  with  con-\n                       trol-C (or equivalent).\n  Fatal        10      Zip  encountered an error while using a temp\n                       file.\n  Fatal        11      Read or seek error.\n  Warning      12      Zip has nothing to do.\n  Error        13      Missing or empty zip file.\n  Fatal        14      Error writing to a file.\n  Fatal        15      Zip was unable to create a file to write to.\n  Error        16      Bad command line parameters.\n  Error        18      Zip could not open a specified file to read.\n  Fatal        19      Zip was built with options not supported  on\n                       this system\n  Fatal        20      Attempt to read unsupported Zip64 archive\n.end literal\n.!------------------------------------------------------------------------------\n.indent -4\n2 Extra_Fields\n.br\nThe .ZIP file format allows some extra data to be stored with a file in\nthe archive.  For example, where local time zone information is\navailable, Zip can store UTC date-time data for files.  (Look for\nUSE_EF_UT_TIME in a \"zip -v\" report.)  On VMS, with -V or -VV, Zip will\nalso store VMS-specific file attributes.  These data are packaged as\n\"extra fields\" in the archive.  Some extra fields are specific to a\nparticular operating system (like VMS file attributes).  Large files\n(bigger than 4GB) on any OS require an extra field to hold their 64-bit\nsize data.  Depending on the capabilities of the UnZip program used to\nexpand the archive, these extra fields may be used or ignored when files\nare extracted from the archive.\n.sk\nSome extra fields, like UTC date-times or VMS file attributes, are\noptional.  Others, like the Zip64 extra field which holds 64-bit sizes\nfor a large file, are required.\n.sk\nThe -X (--strip-extra) option suppresses the saving of any optional\nextra fields in the archive.  (Thus, -X conflicts with -V or -VV.)\n.!------------------------------------------------------------------------------\n.indent -4\n2 Environment\n.br\nA user can specify default command-line options and arguments by\ndefining an \"environment variable\" (that is, a logical name or DCL\nsymbol), \"ZIP_OPTS\" or \"ZIPOPT\", to specify them.  If both \"ZIP_OPTS\" and\n\"ZIPOPT\" are specified, the definition of \"ZIPOPT\" prevails.\n.sk\nThe C RTL function getenv() is used to sense these variables, so its\nbehavior determines what happens if both a logical name and a symbol are\ndefined.  As of VMS V7.3, a logical name supercedes a symbol.\n.sk\nThe \"zip -v\" report should show the perceived settings of these\nvariables.\n.!------------------------------------------------------------------------------\n.indent -4\n2 File_Names\n.br\nZip deals with file names in the system file system and with file names\nin Zip archives.  File names in a Zip archive are stored in a UNIX-like\npath-name format.  For example, a VMS file specification like this:\n.sk;.indent 10\n[.zip30.vms]descrip.mms\n.sk\ncould appear in a Zip archive as:\n.sk;.indent 10\nzip30/vms/descrip.mms\n.sk\nFor security reasons, paths in Zip archives are always stored as\nrelative paths, so an absolute VMS directory specification will be\ntransformed to a relative path in the archive (that is, no leading \"/\"). \nFor example, the following absolute directory specification would give\nthe same archive path as the previous (relative) example:\n.sk;.indent 10\n[zip30.vms]descrip.mms\n.sk\nAlso, device names are dropped, so the following file specification\nwould also give the same archive path:\n.sk;.indent 10\nsys$sysdevice:[zip30.vms]descrip.mms\n.sk\nIf an archive is intended for use with PKUNZIP under MSDOS, then the -k\n(for \"Katz\", --DOS-names) option should be used to attempt to adjust the\nnames and paths to conform to MSDOS character-set and length\nlimitations, to store only the MSDOS file attributes (just the\nowner:write attribute from VMS), and to mark the entry as made under\nMSDOS (even though it wasn't).\n.sk\nNote that file specifications in the file system must be specified using\nVMS notation, but file names in an archive must be specified using the\nUNIX-like notation used in the archive.  For example, where a BACKUP\ncommand might look like this:\n.sk.indent 10\n$ back [.zip30...]*.* /excl = [...vms]*.c stuff.bck /save\n.sk\na corresponding Zip command might look like this:\n.sk;.indent 10;\n$ zip stuff.zip [.zip30...]*.* -x */vms/*.c\n.sk\nbecause the files to be added to the Zip archive are specified using VMS\nfile specifications, but the -x (--exclude) option excludes names based\non their archive path/file names.  Options dealing with archive names\ninclude -R (--recurse-patterns), -d (--delete), -i (--include), -x\n(--exclude), and -U (--copy-entries).\n.sk\nNote: By default, on VMS, archive name pattern matching (-R, -d, -i, -x,\nand -U) is case sensitive, even when the file system is not case\nsensitive (or even case preserving).  This allows accurate matching of\nmixed-case names in an archive which may have been created on a system\nwith a case sensitive file system, but it can involve extra effort on\nVMS, where it may be necessary to use unnatural case names (or the same\nnames in multiple cases, like \"*.obj *.OBJ\") for this kind of pattern\nmatching to give the desired behavior.  If completely case-blind pattern\nmatching behavior is desired, specify the -ic (--ignore-case) option.\n.!------------------------------------------------------------------------------\n.indent -4\n3 Case\n.br\nFor better compatibility with UNIX-like systems, Zip, by default,\ndown-cases ODS2 file names.  For example, the following file on an ODS2\nfile system:\n.sk;.indent 10\n[.ZIP30.VMS]DESCRIP.MMS\n.sk\nwould appear in an archive as:\n.sk;.indent 10\nzip30/vms/descrip.mms\n.sk\nZip versions before 3.0 down-cased all VMS file names.  Now, various\noptions give the user control over these conversions:\n.sk\n.lm +10;.literal\n-C    preserve case of all file names\n-C-   down-case all file names\n-C2   preserve case of ODS2 names\n-C2-  down-case ODS2 file names (default)\n-C5   preserve case of ODS5 names (default)\n-C5-  down-case ODS5 file names\n.end literal;.lm -10\n.sk\nCase is handled differently for archive member names, which the user\nspecifies with the -R, -d, -i, -x, and -U options.  By default, on VMS,\narchive name pattern matching is case sensitive, even when the file\nsystem is not case sensitive (or even case preserving).  This allows\naccurate matching of mixed-case names in an archive which may have been\ncreated on a system with a case sensitive file system, but it can\ninvolve extra effort on VMS, where it may be necessary to use unnatural\ncase names (or the same names in multiple cases, like \"*.obj *.OBJ\") for\nthis kind of pattern matching to give the desired behavior.  If\ncompletely case-blind pattern matching behavior is desired, specify the\n-ic (--ignore-case) option.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Fixing_Damage\n.br\nTwo options can be used to fix a damaged Zip archive.\n.sk;.literal\n-F  --fix\n-FF  --fixfix\n.end literal;.sk\nThe -F (--fix) option can be used if some portions of the archive are\nmissing, but it requires a reasonably intact central directory.  The\ninput archive is scanned as usual, but zip will ignore some problems. \nThe resulting archive should  be valid, but any inconsistent entries\nwill be left out.\n.sk\nIf the archive is too damaged or the end (where the central directory is\nsituated) has been truncated, you must use -FF (--fixfix).  This is a\nchange from zip 2.32, where the -F option is able to read a truncated\narchive.  The -F option now more reliably fixes archives with minor \ndamage, and the -FF option is needed to fix archives where -F and -FF\nwas used before.\n.sk\nWith -FF, the archive is scanned from the beginning and Zip scans for\nspecial signatures to identify the limits between the archive members.\nThe -F option is more reliable if the archive is not too much damaged,\nso try this option first.\n.sk\nNeither option will recover archives that have been incorrectly\ntransferred, such as by FTP in ASCII mode instead of binary.  After the\nrepair, the -t option of UnZip may show that some files have a bad CRC.\nSuch files cannot be recovered; you can remove them from the archive\nusing the -d option of Zip.\n.sk\nBecause of the uncertainty of the \"fixing\" process, it's required\nto specify an output archive, rather than risking further damage to the\noriginal damaged archive.  For example, to fix the damaged archive\nfoo.zip,\n.sk;.indent 10\nzip -F foo --out foo_fix\n.sk\ntries to read the entries normally, copying good entries to the new \narchive foo_fix.zip.  If this doesn't work, as when the archive is\ntruncated, or if some entries are missed because of bad central\ndirectory entries, try -FF:\n.sk;.indent 10\nzip -FF foo --out foo_fixfix\n.sk\nand compare the resulting archive to the archive created using -F. The\n-FF option may create an inconsistent archive.  Depending on what is\ndamaged, you can then use the -F option to fix that archive.\n.sk\nA split archive with missing split files can be fixed using -F if you\nhave the last split of the archive (the \".zip\" file).  If this file is\nmissing, you must use -FF to fix the archive, which will prompt you for\nthe splits you have.\n.sk\nCurrently, the fix options can't recover an entry which has a bad\nchecksum or is otherwise damaged.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Log_File\n.br\nZip normally sends messages to the user's terminal, but these may be\nalso directed to a log file.\n.sk;.literal\n-la  --log-append\n.end literal;.br\nAppend to an existing log file.  Default is to create a new version.\n.sk;.literal\n-lf logfilepath  --logfile-path logfilepath\n.end literal;.br\nOpen a logfile at the given path.  By default, a new version will be\ncreated, but with the -la option an existing file will be opened and the\nnew log information appended to any existing information.  Only\nwarnings and errors are written to the log unless the -li option is also\ngiven, then all information messages are also written to the log.\n.sk;.literal\n-li  --log-info\n.end literal;.br\nInclude information messages, such as file names being zipped, in the\nlog.  The default is to include only the command line, any warnings\nand errors, and the final status.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Modes_of_Operation\n.br\nZip supports two distinct types of command modes, external and \ninternal.  The external modes (update, grow, and freshen) read files\nfrom the file system (as well as from an existing archive) while the\ninternal modes (delete and copy) operate exclusively on entries in an\nexisting archive.\n.sk;.literal\n-u  --update\n.end literal;.br\nUpdate existing entries and add new files.  If the archive does not\nexist, create it.  This is the default mode, so -u is optional.\n.sk;.literal\n-g  --grow\n.end literal;.br\nGrow (append to) the specified Zip archive, instead of creating a new\none.  If this operation fails, Zip attempts to restore the archive to\nits original state.  If the restoration fails, the archive might become \ncorrupted.  This option is ignored when there's no existing archive or\nwhen at least one archive member must be updated or deleted.\n.sk;.literal\n-f  --freshen\n.end literal;.br\nUpdate existing entries in an existing archive.  Does not add new files\nto the archive.\n.sk;.literal\n-d  --delete\n.end literal;.br\nDelete entries from an existing archive.\n.sk;.literal\n-DF  --difference-archive\n.end literal;.br\nCreate an incremental backup-style archive, where the resulting archive \nwill contain all new and changed files since the original archive was\ncreated.  For this to work, the input file list and current directory \nmust be the same as during the original Zip operation.\n.sk\nFor example, if the existing archive was created using\n.sk;.indent 10\nzip foo_full.zip [.foo...]*.*\n.sk\nfrom just above the foo directory, then the command (also from just\nabove the foo directory):\n.sk;.indent 10\nzip foo_full.zip [.foo...]*.* -DF -O foo_incr.zip\n.sk\ncreates the archive foo_incr.zip with just the files not in foo_full.zip\nand the files where the size or date-time of the files does not match\nthat in foo_full.zip.  Note that in the \"zip -DF\" operation, the\noriginal full archive is specified as the input archive, and the -O\n(--output-file) option is used to specify the new (incremental) output\narchive.\n.sk;.literal\n-FS  --filesync\n.end literal;.br\nDelete entries in the archive that do not match files on the OS.\nNormally when an archive is updated, new files are added and changed\nfiles are updated but files that no longer exist on the OS are not\ndeleted from the archive.  This option enables deleting of entries that\nare not matched on the OS.  Enabling this option should create archives\nthat are the same as new archives, but since existing entries are copied\ninstead of compressed, updating an existing archive with -FS can be much\nfaster than creating a new archive.  If few files are being copied from\nthe old archive, it may be faster to create a new archive instead.\n.sk\nThis option deletes files from the archive.  If you need to preserve the\noriginal archive, make a copy of the archive first, or use the  -O\n(--output) option to output the new archive to a new file.  Even though\nit's slower, creating a new archive with a new archive name is safer, \navoids mismatches between archive and OS paths, and is preferred.\n.sk;.literal\n-U  --copy-entries\n.end literal;.br\nSelect entries in an existing archive and copy them to a new archive. \nCopy mode is like update mode, but entries in the existing archive are\nselected by command line patterns rather than files from the file system\nand it uses the -O (--output-file) option to write the resulting archive\nto a new file rather than updating the existing archive, leaving the\noriginal archive unchanged.\n.sk\nNormally, when updating an archive using relative file specifications\n(\"[]\", \"[.xxx]\", and so on), it helps to have the same default directory\nas when the archive was created, but this is not a strict requirement.\n.sk\nDate-time information in a Zip archive may be influenced by time zone.\n.!------------------------------------------------------------------------------\n.indent -4\n3 Examples\n.br\nWhen given the name of an existing archive, Zip will replace identically\nnamed entries in the archive or add entries for new names.  For example,\nif foo.zip exists and contains foo/file1 and foo/file2, and the\ndirectory [.foo] contains the files file1 and file3, then:\n.sk;.indent 10\n$ zip foo [.foo...]*.*\n.sk\nwill replace foo/file1 in foo.zip and add foo/file3 to foo.zip.  After\nthis, foo.zip contains foo/file1, foo/file2, and foo/file3, with foo/file2\nunchanged from before.  This is the default mode -u (update).\n.sk\nUpdate will add new entries to the archive and will replace\nexisting entries only if the modified date of the file is more recent than\nthe date recorded for that name in the archive.  For example:\n.sk;.indent 10\n$ zip -u stuff *.*\n.sk\nwill add any new files in the current directory, and update any changed\nfiles in the archive stuff.zip.  Note that Zip will not try to pack\nstuff.zip into itself when you do this.  Zip avoids including its own\noutput files when selecting files to include in the archive, so it\nshould be safe, as in this case, to have the archive included in the\nlist of input files.\n.sk\nA second mode, -f (freshen), like update will only\nreplace entries with newer files.  Unlike update, however, it will not\nadd files that are not already in the archive.  For example:\n.sk;.indent 10\n$ zip -f foo\n.sk\nNote that the -f option with no arguments freshens all the entries in the\narchive.  The same is true of -u, so \"zip -u foo\" and \"zip -f foo\" do\nthe same thing.\n.sk\nWhen these options are used, Zip should be run from the same directory\nas when the original Zip command was run, so that the path names in the\narchive will continue to agree with the path names in the file system. \nNormally, it's also a good idea to keep the other options the same (-V,\n-w, and the like), to keep the archive contents consistent.\n.sk\nThe -t (--from-date) and -tt (--before-date) options can also be used\nwith adding, updating, or freshening to restrict further the files to be\nincluded in the archive.  For example:\n.sk;.indent 10\n$ zip -rt 12071991 infamy [.FOO]*.*\n.sk\nwill add all the files in [.FOO] and its subdirectories that were last\nmodified on December 7, 1991, or later to the achive infamy.zip.  Dates\ncan be in format mmddyyyy or yyyy-mm-dd.\n.sk\nAlso, files can be explicitly excluded using the -x option:\n.sk;.indent 10\n$ zip -r foo [.FOO] -x *.obj\n.sk\nwhich will zip up the contents of [.FOO] into foo.zip but exclude all the\nfiles that end in \".obj\".\n.sk\nThe -d (delete) mode will remove entries from an\narchive.  An example might be:\n.sk;.indent 10\n$ zip -d foo foo/harry/*.* *.obj\n.sk\nwhich will remove all of the files that start with \"foo/harry/\" and all of\nthe files that end with \".obj\" (in any path).\n.sk\nThe last mode, -U (--copy-entries), selects entries from an existing\narchive and copies them to a new archive.\n.sk;.indent 10\n$ zip -U foo *.obj --out fooobj\n.sk\nwill copy all .obj entries from foo.zip and put them in the new archive\nfooobj.zip.\n.sk\nNote: By default, on VMS, archive name pattern matching (-R, -d, -i, -x,\nand -U) is case sensitive, even when the file system is not case\nsensitive (or even case preserving).  This allows accurate matching of\nmixed-case names in an archive which may have been created on a system\nwith a case sensitive file system, but it can involve extra effort on\nVMS, where it may be necessary to use unnatural case names (or the same\nnames in multiple cases, like \"*.obj *.OBJ\") for this kind of pattern\nmatching to give the desired behavior.  If completely case-blind pattern\nmatching behavior is desired, specify the -ic (--ignore-case) option.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Options_List\n.br\n\"zip -h\" provides a concise list of common command-line options.  \"zip\n-h2\" provides more details.  \"zip -so\" provides a list of all available\noptions.  \"zip -v\" shows the program version and available features. \n(The list below was derived from a \"zip -so\" listing.)\n.sk\nShort-form options begin with a single hyphen (\"-\").  Long-form option\nbegin with a double hyphen (\"--\"), and may be abbreviated to any\nunambiguous shorter string.  For example:\n.lm +10;.literal\n-v\n--verbose\n--verb\n.end literal;.lm -10\n.sk\nTo avoid confusion, if a negatable option contains an embedded hyphen\n(\"-\"), then avoid abbreviating it at the hyphen if you plan to negate\nit.  For example, if an option like --some-option were abbreviated to\n--some-, the parser would consider that trailing hyphen to be part of\nthe option name, rather than as a negating trailing hyphen.  This\nbehavior may change in the future, to interpret the trailing hyphen in\n--some- to be negating.  (So don't do it.)\n.sk\nSome options may be negated (or modified) by appending a \"-\":\n.lm +10;.literal\n-la-\n--show-files-\n.end literal;.lm -10\n.sk\nSome options take a value, which may immediately follow the option, or\nbe separated by a space or \"=\".  For example:\n.lm +10;.literal\n-ttmmddyyyy\n-tt mmddyyyy\n-tt=mmddyyyy\n.end literal;.lm -10\n.sk\n.lm -4;.literal\n Sh  Long                Description\n----+-------------------+--------------------------------------------------\n 0   store               store (instead of compress)\n 1   compress-1          compress faster (-2, -3, -4, ...)\n 9   compress-9          compress better\n ?                       show the Zip help screen\n @   names-stdin         read input file patterns from SYS$INPUT (1/line)\n A   adjust-sfx          adjust self-extracting executable\n b   temp-path  path     use \"path\" directory for temporary files\n C   preserve-case       preserve case of all file names added to archive\n C-  preserve-case-      down-case all file names added to archive\n C2  preserve-case-2     preserve case of ODS2 names added to archive\n C2- preserve-case-2-    down-case ODS2 file added to archive (default)\n C5  preserve-case-5     preserve case of ODS5 names added to archive (dflt)\n C5- preserve-case-5-    down-case ODS5 names added to archive\n c   entry-comments      add a comment for each entry added to archive\n D   no-dir-entries      do not add archive entries for directories\n DF  difference-archive  difference archive: add only changed or new files\n d   delete              delete entries in archive\n db  display-bytes       display running byte counts\n dc  display-counts      display running file counts\n dd  display-dots        display progress dots for files (dflt size = 10MB)\n dg  display-globaldots  display progress dots for archive, not each file\n ds  dot-size   size     set progress dot interval to \"size\" (MB)\n du  display-usize       display original uncompressed size for entries\n dv  display-volume      display volume (disk) number as in_disk>out_disk\n e   encrypt             encrypt entries, ask for password\n F   fix                 fix mostly intact archive (try F before FF)\n FF  fixfix              salvage what can be salvaged (not as reliable)\n FS  filesync            remove archive entries unmatched in file system\n f   freshen             update existing entries (only changed files)\n fd  force-descriptors   force data descriptors as if streaming\n fz  force-zip64         force use of Zip64 format\n g   grow                grow existing archive (unless updating or deleting)\n H                       show the Zip help screen\n h   help                show the Zip help screen\n h2  more-help           show extended Zip help\n i   include  pat1 [pat2 [...]]  include only names matching the patterns\n ic  ignore-case         ignore case (case-blind archive entry name matching)\n J   junk-sfx            junk (remove) archive preamble (unzipsfx)\n j   junk-paths          junk (don't store) directory names, only file names\n k   DOS-names           simulate PKZIP-made archive (DOS 8.3 names)\n L   license             show software license\n l   to-crlf             translate end-of-lines (LF -> CRLF)\n la  log-append          append to existing log file\n lf  logfile-path  lfile  log to log file at lfile (default: new version)\n li  log-info            include informational messages in log\n ll  from-crlf           translate end-of-lines (CRLF -> LF)\n MM  must-match          input file spec must exist (wildcards must match)\n m   move                delete files added to archive\n n   suffixes  sfx1[:sfx2[...]]  don't compress files with these suffixes\n nw  no-wild             no wildcards during add or update\n O   output-file  ozf  use \"ozf\" as the output archive (dflt = inp archive)\n o   latest-time         set archive date-time to match oldest entry\n P   password  password  encrypt with supplied \"password\" string\n q   quiet               quiet operation (no info messages)\n R   recurse-patterns    recurse into subdirs from cur dir, match names only\n r   recurse-paths       recurse into directories from specified path pats\n s   split-size  size    split archive at \"size\" (K/MB)  (0: don't split)\n sb  split-bell          ring terminal bell at pause for split medium change\n sc  show-command        show command line\n sd  show-debug          show debug messages\n sf  show-files          show files to process (only)\n so  show-options        show list of all command-line options\n sp  split-pause         pause to select split destination(s)\n sv  split-verbose       be verbose about creating splits\n T   test                test archive integrity (runs UnZip -T)\n t   from-date  mmddyyyy  only do files since (at or after) \"mmddyyyy\"\n tt  before-date  mmddyyyy  only do files before \"mmddyyyy\"\n u   update              update changed files, add new files (default mode)\n V   VMS-portable        save VMS file attributes\n VV  VMS-specific        save VMS file attributes and all allocated blocks\n v   verbose             verbose messages (print version info if only arg)\n w   VMS-versions        save VMS version numbers in archive\n ww  VMS-dot-versions    save VMS version numbers as \".nnn\", not \";nnn\"\n X   strip-extra         strip all but critical extra fields\n X-  strip-extra-        keep all extra fields\n x   exclude  pat1 [pat2 [...]]  exclude all names matching the patterns\n Z   compression-method mthd  use compress method \"mthd\" (bzip2 or deflate)\n z   archive-comment     ask for archive comment\n.end literal;.lm +4\n.!------------------------------------------------------------------------------\n.indent -4\n2 Miscellaneous_Options\n.sk;.literal\n-D  --no-dir-entries\n.end literal;.br\nDo not create entries in the archive for directories.  By default,\ndirectory entries are added to an archive, so that their attributes can\nbe saved in the archive.  When an archive is created using -D, UnZip\nwill still create directories as needed (subject to user control), but\nthey will get the default attributes (date-time, permissions, ...) on\nthe destination system, rather than their original atributes.\n.sk;.literal\n-MM  --must-match\n.end literal;.br\nAll input patterns must match at least one file and all input files \nfound must be readable.  Normally when an input pattern does not match\na file the \"name not matched\" warning is issued and when an input\nfile has been found but later is missing or not readable a \"missing or\nnot readable\" warning is issued.  In either case Zip continues\ncreating the archive, with missing or unreadable new files being skipped \nand files already in the archive remaining unchanged.  After the\narchive is created, if any files were not readable zip returns the OPEN\nerror code (18 on most systems) instead of the normal success return (0\non most systems).  With -MM, Zip exits as soon as an input pattern\nis not matched (whenever the \"name not matched\" warning would be issued)\nor when an input file is not readable. In either case Zip exits with\nan OPEN error and no archive is created.\n.sk\nThis option is useful when a known list of files is to be zipped so any\nmissing or unreadable files should result in an error.  It may be less\nuseful when used with wildcards, but Zip will still exit with an error\nif any input pattern doesn't match at least  one file or if any\nmatched files are unreadable.  If you want to create the archive anyway\nand only need to know if files were skipped, then don't use -MM and just\ncheck the exit status.  Also, a log file (see -lf (--logfile-path))\ncould be useful.\n.sk;.literal\n-O out_file  --output-file out_file\n.end literal;.br\nProcess the archive changes as usual, but instead of updating the\nexisting archive, send the output to a new archive, \"out_file\".  The\noutput archive specified must be a different file from the input\narchive.\n.sk\nThis option can be used to create updated split archives.  It can\nalso be used with -U to copy entries from an existing archive to\na new archive.  See the EXAMPLES section below.\n.sk\nAnother use is converting zip files from one split size to\nanother.  For instance, to convert an archive with 700MB CD splits\nto one with 2GB DVD splits, can use:\n.sk;.indent 10\nzip -s 2g cd-split.zip --out dvd-split.zip\n.sk\nwhich uses copy mode.  See -U below.  Also:\n.sk;.indent 10\nzip -s 0 split.zip --out unsplit.zip\n.sk\nwill convert a split archive to a single-file archive.\n.sk\nCopy mode will convert stream entries (using data descriptors and which\nmay be incompatible with some unzip programs) to normal entries (which\nshould be compatible with all unzip programs), except if standard\nencryption was  used.  For archives with encrypted entries, zipcloak\nwill decrypt the entries and convert them to normal entries.\n.sk;.literal\n-o  --latest-time\n.end literal;.br\nSet the modification date-time of the Zip archive file to the latest\n(newest) modification date-time found among the entries in the zip\narchive.  This can be used without any other operations, if\ndesired.  For example:\n.sk;.indent 10\nzip -o foo\n.sk\nwill change the modification date-time of foo.zip to the latest time of\nthe entries in foo.zip.\n.sk;.literal\n-q  --quiet\n.end literal;.br\nQuiet mode.  Eliminates informational messages and comment prompts. \nThis mode may be useful in command procedures, or if the Zip operation\nis being performed as a background task (\"$ spawn/nowait zip -q foo\n*.c\").\n.sk\n.sk;.literal\n-T  --test\n.end literal;.br\nTest the integrity of a zip archive (the new one, if -O (--output-file)\nis specified).  If the check fails, the old zip file is unchanged  and\n(with the -m option) no input files are removed.\n.sk\nImplementation\n.br\n\"zip -T\" actually runs an \"unzip -t\" command to do the testing, so UnZip\nmust be installed properly for this to work.\n.sk;.literal\n-TT unzip_cmd  --unzip-command unzip_cmd\n.end literal;.br\nSpecify the actual UnZip command, \"unzip_cmd\" (normally a DCL symbol) to\nuse for \"zip -T\".  This can be useful if multiple versions of UnZip are\ninstalled on a system, and the default DCL symbol \"UNZIP\" would run the\nwrong one (or the logical name DCL$PATH would lead to the wrong one).\n.sk\nIn \"unzip_cmd\", the string \"{}\" is replaced by the temporary name of the\narchive to be tested, otherwise the name of the archive is appended\nto the end of the command.  The exit status is checked for success severity.\n.sk;.literal\n-v  --verbose\n.end literal;.br\nVerbose mode or print diagnostic version info.\n.sk\nNormally, when applied to real operations, this option enables the \ndisplay of a progress indicator during compression (see -dd for more on\ndots) and requests verbose diagnostic info about archive structure\noddities.\n.sk\nWhen -v is the only command line argument, a diagnostic report is\ndisplayed, showing:\n.lm +3;.br;.indent -2\no Copyright and other legal notices\n.br;.indent -2\no Program name, version, and release date\n.br;.indent -2\no Pointers to Info-ZIP FTP and Web sites\n.br;.indent -2\no Program build information (compiler type and version, OS version, and\nthe compilation date\n.br;.indent -2\no Optional features enabled at compile-time\n.br;.indent -2\no Environment variable definitions (ZIP_OPTS, ZIPOPT)\n.lm -3;.br\n.sk\nThis information should be included in bug reports.\n.sk;.literal\n-y  --symlinks\n.end literal;.br\nStore symbolic links as such in the Zip archive, instead of compressing\nand storing the file referred to by the link.  A symbolic link normally\nrequires less storage than the actual file, both in the archive, and on\nthe destination file system.\n.sk\nOn VMS, symbolic links are supported on ODS5 disks where the C RTL\nsupports symbolic links.  Full support for symbolic links seems to\nrequire VMS V8.3, but a Zip program supporting symbolic links may be\nbuilt on VMS V7.3-2.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Progress_Display\n.br\nVarious options control the display of progress messages during Zip\noperation.\n.sk;.literal\n-db  --display-bytes\n.end literal;.br\nDisplay running byte counts showing the bytes processed and the bytes to\ngo.\n.sk;.literal\n-dc  --display-counts\n.end literal;.br\nDisplay running count of entries processed and entries to go.\n.sk;.literal\n-dd  --display-dots\n.end literal;.br\nDisplay dots while each entry is processed (except on ports that have \ntheir own progress indicator).  See -ds below for setting dot size.  The\ndefault is a dot every 10 MB of input file processed.  The -v\n(--verbose) option also displays dots and used to at a higher rate than\nthis (at the same rate as in previous versions of Zip) but this rate has\nbeen changed to the new 10 MB default, and is also controlled by -ds.\n.sk;.literal\n-dg  --display-globaldots\n.end literal;.br\nDisplay progress dots for the archive instead of for each file.  The\ncommand\n.sk;.indent 10\nzip -qdgds 10m\n.sk\nwill turn off most output except dots every 10 MB.\n.sk;.literal\n-ds size  --dot-size size\n.end literal;.br\nSet amount of input file processed for each dot displayed.  See -dd to\nenable displaying dots.  Setting this option implies -dd.  \"size\" is in\nthe format \"nm\" where n is a number and m is a multiplier.  Currently\n\"m\" can be k (KB), m (MB), g (GB), or t (TB), so if \"n\" is 100 and \"m\"\nis k, \"size\" would be 100k which is 100KB.  The default is 10MB.\n.sk\nThe -v (--verbose) option also displays dots and used to default to a\nhigher rate than this (at the same rate as in previous versions of Zip)\nbut now the default is 10 MB and the -v dots are also controlled by this\noption.  A \"size\" of 0 turns dots off.\n.sk\nThis option does not control the dots from the \"Scanning files\" message \nas Zip scans for input files.  The dot size for that is fixed at 2\nseconds or a fixed number of entries, whichever is longer.\n.sk;.literal\n-du  --display-usize\n.end literal;.br\nDisplay the uncompressed size of each entry.\n.sk;.literal\n-dv  --display-volume\n.end literal;.br\nDisplay the volume (disk) number each entry is being written to.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Self_Extracting_Archives\n.br\nA self-extracting archive (SFX) comprises a normal Zip archive appended\nto a special UnZip program (such as UNZIPSFX.EXE) for the intended\ntarget system.\n.sk\nThe UnZip distribution includes a VMS command procedure,\n[,vms]makesfx.com, which can be used directly or adapted to create an\nSFX archive from a normal Zip archive.\n.sk\nThe .ZIP file format includes offsets to data structures in the archive,\nand these offsets are measured from the start of the archive file. \nAppending an archive to an UnZip SFX executable effectively moves the\nstart of the archive file.  That makes the original offsets wrong, and\nthat will cause the UnZip SFX program to emit warning messages when it\ntries to unpack the archive.  Zip -A can be used to adjust these offsets\nin a self-extracting archive.  For example, to adjust the offsets in\nfoo.sfx_exe:\n.sk;.indent 10\nzip -A foo.sfx_exe\n.sk\nSimilarly, the UnZip SFX program can be removed from a self-extracting\narchive (and the offsets in the archive restored) using the -J\n(--junk-sfx) option.  For example:\n.sk;.indent 10\nzip -J foo.sfx_exe\n.sk\nNote that a self-extracting archive contains a normal Zip archive, and a\nnormal UnZip program can be used to expand it in the normal way.  You\nmay get a warning about extra bytes at the beginning of the archive (the\nUnZip SFX program), but UnZip should work properly after that.  This\nallows data in a self-extracting archive to be accessed on any system,\nnot just the target system where its embedded UnZip SFX program runs.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Split_Archives\n.br\nBeginning with version 3.0, Zip supports split archives.  A split\narchive is one which is divided into multiple files, usually to allow it\nto be stored on multiple storage media (floppy diskettes, CD-ROMs, or\nthe like) when a single medium would be too small to contain the whole\narchive.  (Note that split archives are not just unitary archives split\ninto pieces, as the .ZIP file format includes offsets to data structures\nin the archive, and for a split archive these are based on the start of\neach split, not on the start of the whole archive.  Concatenating the\npieces will invalidate these offsets, but UnZip can usually deal with\nit.  Zip will usually refuse to process such a spliced archive unless\nthe -FF fix option is used to fix the offsets.)\n.sk\nFor a split archive with, say, 20 split files, the files are typically\nnamed ARCHIVE.z01, ARCHIVE.z02, ..., ARCHIVE.z19, ARCHIVE.zip, where\n\"ARCHIVE\" is the archive name specified by the user on the Zip command\nline.  Note that the last split file is the \".zip\" file.  In contrast,\n\"spanned\" archives are the original multi-disk archive generally\nrequiring floppy disks and using volume labels to store disk numbers. \nZip supports split archives but not spanned archives, though a procedure\nexists for converting split archives of the right size to spanned\narchives.  The reverse is also true, where each file of a spanned\narchive can be copied in order to files with the above names to create a\nsplit archive.\n.!------------------------------------------------------------------------------\n.indent -4\n3 Options\n.br\nUse \"-s size\" to create a split archive (and to set the split size). \nThe size is given as a number followed optionally by a multiplier suffix\nof k (KB), m (MB, the default if no suffix is specified), g (GB), or t\n(TB).  (All are powers of 1024, not 1000).  64K is the minimum split\nsize.  For example, the following command could be used to create a\nsplit archive called \"foo\" from the contents of the \"bar\" directory with\nsplits of 670MB, which might be useful for burning on CDs:\n.sk;.indent 10\nzip -s 670m foo [.bar...]*.*\n.sk\nUsing -s without -sp as above creates all the splits in the directory\nspecified by \"foo\", in this case the current default directory.  This \nsplit mode updates the splits as the archive is being created, requiring\nall splits to remain writable, but creates split archives that are\nreadable by any UnZip that supports split archives.  See -sp below for\nenabling split pause mode which allows splits to be written directly to\nremovable media.\n.sk\nThe -sv option can be used to enable verbose splitting and display\ndetails of how the splitting is being done.  The -sb option can be used\nto ring the terminal bell when Zip pauses for the next split\ndestination.\n.sk\nThe -sp option can be used to pause Zip between splits to allow \nchanging removable media, for example, but read the descriptions and\nwarnings for both -s and -sp below.\n.sk\nThough Zip does not update split archives, Zip provides the option\n-O (--output-file) to allow split archives to be updated and saved in a\nnew archive.  For example:\n.sk;.indent 10\nzip inarchive.zip foo.c bar.c -O outarchive.zip\n.sk\nreads archive inarchive.zip, even if split, adds the files foo.c and\nbar.c, and writes the resulting archive to outarchive.zip.  If\ninarchive.zip is split, then outarchive.zip defaults to the same split\nsize.  Be aware that outarchive.zip and any split files that are created\nwith it are always overwritten without warning.  This may be changed in \nthe future.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Temporary_Files\n.br\nWhen creating a new archive or normally when changing an existing\narchive, Zip will write a temporary file in the archive destination\ndirectory (\"ZIxxxxxxxx\", where \"xxxxxxxx\" is the hexadecimal process ID)\nwith the new contents.  Then, if and when the Zip job has completed with\nno errors, it will rename the temporary file to the specified archive\nname (replacing the old archive, if any).\n.sk\nYou can use the -b (--temp-path) option to specify a different path\n(device and/or directory) for the temporary file, but specifying a\ndifferent device will force Zip to copy the temporary file to its final\ndestination instead of simply renaming it, and that copying will take\nmore time than renaming, especially for a large archive.  For example:\n.sk;.indent 10\n$ zip -b disk$scratch:[tmp] stuff *\n.sk\nwill cause Zip to put its temporary files in the directory\n\"disk$scratch:[tmp]\", copying the temporary file back to the current\ndirectory as stuff.zip when it's complete.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Text_Files\n.br\nZip offers some options to help deal with line endings in text files. \nThese may have limited utility on VMS.\n.sk;.literal\n-l  --to-crlf\n.end literal;.br\nTranslate the UNIX end-of-line character LF (CR on MAC) into the MSDOS\nconvention CR-LF.  This option should not be used on binary files.  This\noption can be used on UNIX if the Zip file is intended for PKUNZIP under\nMSDOS.  If the input files already contain CR-LF, this option adds an\nextra CR.  This ensure that \"unzip -a\" on Unix will get back an exact\ncopy of the original file, to undo the effect of \"zip -l\".  See -ll\nbelow for the binary checks.\n.sk;.literal\n-ll  --from-crlf\n.end literal;.br\nTranslate the MSDOS end-of-line CR LF into UNIX LF (CR on MAC).  This\noption should not be used on binary files.  This option can be used on\nMSDOS if the Zip archive is intended for UnZip under UNIX.\n.sk\nFor both -l and -ll, if the file is converted and the file is later\ndetermined to be binary, a warning is issued and the file is probably\ncorrupted.  If Zip with -l or -ll detects binary (non-text) in the first\nbuffer read from a file, it issues a warning and skips line-ending\nconversion on the file, avoiding corruption.  This check seems to catch\nall binary files tested, but the original check remains and if a\nconverted file is later determined to be binary, that warning is still\nissued.  The algorithm now being used for binary detection should allow\nline-ending conversion of text files in UTF-8 and similar encodings.\n.!------------------------------------------------------------------------------\n.indent -4\n2 VMS_Specifics\n.br\nVMS File Attributes\n.sk;.literal\n-V  --VMS-portable\n-VV --VMS-specific\n.end literal;.br\nThe -V and -VV options cause Zip to store VMS file atributes (such as\nfile organization, record format, carriage control, and so on) in\nVMS-specific \"extra fields\" in an archive along with the usual data. \nThese extra fields are ignored on non-VMS systems, but on a VMS system,\nthey allow UnZip to restore the files with their VMS attributes intact.\n.sk\nWith -V, Zip ignores any data in the file after the end-of-file (EOF)\npoint (defined by FAT$L_EFBLK and FAT$W_FFBYTE), which works well for\nwell-formed files (that is, those with no valid data beyond EOF). \nPortable-format files (Stream_LF, fixed-512) archived with -V should be\nextracted properly on a non-VMS system.  Files with more complex\nstructures, such as indexed files and files with embedded byte counts\nor other such data may be of limited use on other systems.  (UnZip on\nnon-VMS systems may be able to extract various VMS-format text files,\nhowever.)\n.sk\nWith -VV, Zip processes all allocated blocks for the file (including\nthose beyond EOF).  When extracted on a VMS system, the original file\nshould be reproduced with as much fidelity as possible, but on a non-VMS\nsystem, most files will be seen as corrupt because of the data from\nbeyond EOF.\n.sk\nVMS File Version Numbers\n.sk;.literal\n-w  --VMS-versions\n-ww  --VMS-dot-versions\n.end literal;.br\nBy default, for compatibility with non-VMS systems, Zip strips VMS file\nversion numbers from the names stored in an archive.  The -w\n(--VMS-versions) option causes Zip to retain file version numbers on\nnames in an archive. Without -w, a version number wildcard (\";*\") can\ncause errors when multiple versions of a single file are treated as\nmultiple files with the same name.\n.sk\nFor better compatibility with non-VMS systems where semi-colons are less\npopular in file names, the -ww (--VMS-dot-versions) option stores the\nfile version numbers with a dot (\".nnn\") instead of a semi-colon\n(\";nnn\").\n.!------------------------------------------------------------------------------\n.indent -4\n2 Copyright_and_License\n.br\nZip has an option to display its copyright and license.\n.sk;.literal\n-L  --license\n.end literal;.br\nThe license is reproduced below.\n.sk.lm +3\nThis is version 2007-Mar-4 of the Info-ZIP license. The definitive\nversion of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a copy\nat http://www.info-zip.org/pub/infozip/license.html.\n.lm -3;.sk\n--------------------------------------------------------\n.sk\nCopyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n.sk\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n.sk;.lm +3\n     Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n     Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n     Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n     David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n     Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n     Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n     Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n     Rich Wales, Mike White.\n.lm -3;.sk\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held\nliable for any direct, indirect, incidental, special or consequential\ndamages arising out of the use of or inability to use this software.\n.sk\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n.sk;.lm +7;.indent -4\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n.sk;.indent -4\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  The sole exception to this condition\n       is redistribution of a standard UnZipSFX binary (including SFXWiz) as\n       part of a self-extracting archive; that is permitted without inclusion\n       of this license, as long as the normal SFX banner has not been removed\n       from the binary or disabled.\n.sk;.indent -4\n    3. Altered versions -- including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP -- must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases -- including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n.sk;.indent -4\n       4. Info-ZIP retains the right to use the names \"Info-ZIP\", \"Zip\",\n       \"UnZip\", \"UnZipSFX\", \"WiZ\", \"Pocket UnZip\", \"Pocket Zip\", and\n       \"MacZip\" for its own source and binary releases.\n.lm -7;.sk\n.!------------------------------------------------------------------------------\n.indent -4\n2 Acknowledgements\n.br\n       Thanks to R. P. Byrne for his Shrink.Pas program, which\n       inspired this project, and from which the shrink algorithm\n       was stolen; to Phil Katz for placing in the public domain\n       the zip file format, compression format, and .ZIP filename\n       extension, and for accepting minor changes to the file\n       format; to Steve Burg for clarifications on the deflate\n       format; to Haruhiko Okumura and Leonid Broukhis for providing\n        some useful ideas for the compression algorithm; to\n       Keith Petersen, Rich Wales, Hunter Goatley and Mark Adler\n       for providing a mailing list and ftp site for the Info-ZIP\n       group to use; and most importantly, to the Info-ZIP group\n       itself (listed in the file infozip.who) without whose\n       tireless testing and bug-fixing efforts a portable zip\n       would not have been possible.  Finally we should thank\n       (blame) the first Info-ZIP moderator, David Kirschbaum,\n       for getting us into this mess in the first place.\n.!------------------------------------------------------------------------------\n.indent -4\n2 Bugs\n.br\nAll bug reports, patches, or suggestions should go to zip-bugs via the\nweb site contact form at http://www.Info-ZIP.org.  Patches should be\nsent as unified or context diffs only (diff -u or diff -c).\n.sk\nAny bug report should include the Zip version, any special compilation\noptions (see \"zip -v\" report), the host system type and operating system\nversion, and any other relevant information (compiler version, lunar\nphase, ...).  \n.!------------------------------------------------------------------------------\n"
  },
  {
    "path": "deps/infozip/zip30/vms/build_zip.com",
    "content": "$! BUILD_ZIP.COM\n$!\n$!     Build procedure for VMS versions of Zip.\n$!\n$!     last revised:  2007-03-15  SMS.\n$!\n$!     Command arguments:\n$!     - suppress help file processing: \"NOHELP\"\n$!     - suppress message file processing: \"NOMSG\"\n$!     - select link-only: \"LINK\"\n$!     - select compiler environment: \"VAXC\", \"DECC\", \"GNUC\"\n$!     - select large-file support: \"LARGE\"\n$!     - select compiler listings: \"LIST\"  Note that the whole argument\n$!       is added to the compiler command, so more elaborate options\n$!       like \"LIST/SHOW=ALL\" (quoted or space-free) may be specified.\n$!     - supply additional compiler options: \"CCOPTS=xxx\"  Allows the\n$!       user to add compiler command options like /ARCHITECTURE or\n$!       /[NO]OPTIMIZE.  For example, CCOPTS=/ARCH=HOST/OPTI=TUNE=HOST\n$!       or CCOPTS=/DEBUG/NOOPTI.  These options must be quoted or\n$!       space-free.\n$!     - supply additional linker options: \"LINKOPTS=xxx\"  Allows the\n$!       user to add linker command options like /DEBUG or /MAP.  For\n$!       example: LINKOPTS=/DEBUG or LINKOPTS=/MAP/CROSS.  These options\n$!       must be quoted or space-free.  Default is\n$!       LINKOPTS=/NOTRACEBACK, but if the user specifies a LINKOPTS\n$!       string, /NOTRACEBACK will not be included unless specified by\n$!       the user.\n$!     - select installation of CLI interface version of zip:\n$!       \"VMSCLI\" or \"CLI\"\n$!     - force installation of UNIX interface version of zip\n$!       (override LOCAL_ZIP environment): \"NOVMSCLI\" or \"NOCLI\"\n$!     - select BZIP2 support: \"IZ_BZIP2=dev:[dir]\", where \"dev:[dir]\"\n$!       (or a suitable logical name) tells where to find \"bzlib.h\".\n$!       The BZIP2 object library (LIBBZ2_NS.OLB) is expected to be in\n$!       a \"[.dest]\" directory under that one (\"dev:[dir.ALPHAL]\", for\n$!       example), or in that directory itself.\n$!\n$!     To specify additional options, define the global symbol\n$!     LOCAL_ZIP as a comma-separated list of the C macros to be\n$!     defined, and then run BUILD_ZIP.COM.  For example:\n$!\n$!             $ LOCAL_ZIP == \"VMS_IM_EXTRA\"\n$!             $ @ [.VMS]BUILD_ZIP.COM\n$!\n$!     Valid VMS-specific options include VMS_PK_EXTRA and VMS_IM_EXTRA. \n$!     See the INSTALL file for other options.  (VMS_PK_EXTRA is the\n$!     default.)\n$!\n$!     If editing this procedure to set LOCAL_ZIP, be sure to use only\n$!     one \"=\", to avoid affecting other procedures.  For example:\n$!             $ LOCAL_ZIP = \"VMS_IM_EXTRA\"\n$!\n$!     Note: This command procedure always generates both the \"default\"\n$!     Zip having the UNIX style command interface and the \"VMSCLI\" Zip\n$!     having the CLI compatible command interface.  There is no need to\n$!     add \"VMSCLI\" to the LOCAL_ZIP symbol.  (The only effect of\n$!     \"VMSCLI\" now is the selection of the CLI style Zip executable in\n$!     the foreign command definition.)\n$!\n$!\n$ on error then goto error\n$ on control_y then goto error\n$ OLD_VERIFY = f$verify( 0)\n$!\n$ edit := edit                  ! override customized edit commands\n$ say := write sys$output\n$!\n$!##################### Read settings from environment ########################\n$!\n$ if (f$type( LOCAL_ZIP) .eqs. \"\")\n$ then\n$     LOCAL_ZIP = \"\"\n$ else  ! Trim blanks and append comma if missing\n$     LOCAL_ZIP = f$edit( LOCAL_ZIP, \"TRIM\")\n$     if (f$extract( f$length( LOCAL_ZIP)- 1, 1, LOCAL_ZIP) .nes. \",\")\n$     then\n$         LOCAL_ZIP = LOCAL_ZIP + \",\"\n$     endif\n$ endif\n$!\n$! Check for the presence of \"VMSCLI\" in LOCAL_ZIP.  If yes, we will\n$! define the foreign command for \"zip\" to use the executable\n$! containing the CLI interface.\n$!\n$ len_local_zip = f$length( LOCAL_ZIP)\n$!\n$ pos_cli = f$locate( \"VMSCLI\", LOCAL_ZIP)\n$ if (pos_cli .ne. len_local_zip)\n$ then\n$     CLI_IS_DEFAULT = 1\n$     ! Remove \"VMSCLI\" macro from LOCAL_ZIP. The Zip executable\n$     ! including the CLI interface is now created unconditionally.\n$     LOCAL_ZIP = f$extract( 0, pos_cli, LOCAL_ZIP)+ -\n       f$extract( pos_cli+7, len_local_zip- (pos_cli+ 7), LOCAL_ZIP)\n$ else\n$     CLI_IS_DEFAULT = 0\n$ endif\n$ delete /symbol /local pos_cli\n$!\n$! Check for the presence of \"VMS_IM_EXTRA\" in LOCAL_ZIP.  If yes, we\n$! will (later) add \"I\" to the destination directory name.\n$!\n$ desti = \"\"\n$ pos_im = f$locate( \"VMS_IM_EXTRA\", LOCAL_ZIP)\n$ if (pos_im .ne. len_local_zip)\n$ then\n$    desti = \"I\"\n$ endif\n$!\n$ delete /symbol /local len_local_zip\n$!\n$!##################### Customizing section #############################\n$!\n$ zipx_unx = \"ZIP\"\n$ zipx_cli = \"ZIP_CLI\"\n$!\n$ CCOPTS = \"\"\n$ IZ_BZIP2 = \"\"\n$ LINKOPTS = \"/notraceback\"\n$ LINK_ONLY = 0\n$ LISTING = \" /nolist\"\n$ LARGE_FILE = 0\n$ MAKE_HELP = 1\n$ MAKE_MSG = 1\n$ MAY_USE_DECC = 1\n$ MAY_USE_GNUC = 0\n$!\n$! Process command line parameters requesting optional features.\n$!\n$ arg_cnt = 1\n$ argloop:\n$     current_arg_name = \"P''arg_cnt'\"\n$     curr_arg = f$edit( 'current_arg_name', \"UPCASE\")\n$     if (curr_arg .eqs. \"\") then goto argloop_out\n$!\n$     if (f$extract( 0, 5, curr_arg) .eqs. \"CCOPT\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         CCOPTS = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if f$extract( 0, 7, curr_arg) .eqs. \"IZ_BZIP\"\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         IZ_BZIP2 = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 5, curr_arg) .eqs. \"LARGE\")\n$     then\n$         LARGE_FILE = 1\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 7, curr_arg) .eqs. \"LINKOPT\")\n$     then\n$         opts = f$edit( curr_arg, \"COLLAPSE\")\n$         eq = f$locate( \"=\", opts)\n$         LINKOPTS = f$extract( (eq+ 1), 1000, opts)\n$         goto argloop_end\n$     endif\n$!\n$! Note: LINK test must follow LINKOPTS test.\n$!\n$     if (f$extract( 0, 4, curr_arg) .eqs. \"LINK\")\n$     then\n$         LINK_ONLY = 1\n$         goto argloop_end\n$     endif\n$!\n$     if (f$extract( 0, 4, curr_arg) .eqs. \"LIST\")\n$     then\n$         LISTING = \"/''curr_arg'\"      ! But see below for mods.\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"NOHELP\")\n$     then\n$         MAKE_HELP = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"NOMSG\")\n$     then\n$         MAKE_MSG = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"VAXC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"DECC\")\n$     then\n$         MAY_USE_DECC = 1\n$         MAY_USE_GNUC = 0\n$         goto argloop_end\n$     endif\n$!\n$     if (curr_arg .eqs. \"GNUC\")\n$     then\n$         MAY_USE_DECC = 0\n$         MAY_USE_GNUC = 1\n$         goto argloop_end\n$     endif\n$!\n$     if ((curr_arg .eqs. \"VMSCLI\") .or. (curr_arg .eqs. \"CLI\"))\n$     then\n$         CLI_IS_DEFAULT = 1\n$         goto argloop_end\n$     endif\n$!\n$     if ((curr_arg .eqs. \"NOVMSCLI\") .or. (curr_arg .eqs. \"NOCLI\"))\n$     then\n$         CLI_IS_DEFAULT = 0\n$         goto argloop_end\n$     endif\n$!\n$     say \"Unrecognized command-line option: ''curr_arg'\"\n$     goto error\n$!\n$     argloop_end:\n$     arg_cnt = arg_cnt + 1\n$ goto argloop\n$ argloop_out:\n$!\n$ if (CLI_IS_DEFAULT)\n$ then\n$     ZIPEXEC = zipx_cli\n$ else\n$     ZIPEXEC = zipx_unx\n$ endif\n$!\n$!#######################################################################\n$!\n$! Find out current disk, directory, compiler and options\n$!\n$ workdir = f$environment( \"default\")\n$ here = f$parse( workdir, , , \"device\")+ f$parse( workdir, , , \"directory\")\n$!\n$! Sense the host architecture (Alpha, Itanium, or VAX).\n$!\n$ if (f$getsyi( \"HW_MODEL\") .lt. 1024)\n$ then\n$     arch = \"VAX\"\n$ else\n$     if (f$getsyi( \"ARCH_TYPE\") .eq. 2)\n$     then\n$         arch = \"ALPHA\"\n$     else\n$         if (f$getsyi( \"ARCH_TYPE\") .eq. 3)\n$         then\n$             arch = \"IA64\"\n$         else\n$             arch = \"unknown_arch\"\n$         endif\n$     endif\n$ endif\n$!\n$ dest = arch\n$ cmpl = \"DEC/Compaq/HP C\"\n$ opts = \"\"\n$ if (arch .nes. \"VAX\")\n$ then\n$     HAVE_DECC_VAX = 0\n$     USE_DECC_VAX = 0\n$!\n$     if (MAY_USE_GNUC)\n$     then\n$         say \"GNU C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build Zip.\"\n$         goto error\n$     endif\n$!\n$     if (.not. MAY_USE_DECC)\n$     then\n$         say \"VAX C is not supported for ''arch'.\"\n$         say \"You must use DEC/Compaq/HP C to build Zip.\"\n$         goto error\n$     endif\n$!\n$     cc = \"cc /standard = relax /prefix = all /ansi\"\n$     defs = \"''LOCAL_ZIP' VMS\"\n$     if (LARGE_FILE .ne. 0)\n$     then\n$         defs = \"LARGE_FILE_SUPPORT, ''defs'\"\n$     endif\n$ else\n$     if (LARGE_FILE .ne. 0)\n$     then\n$        say \"LARGE_FILE_SUPPORT is not available on VAX.\"\n$        LARGE_FILE = 0\n$     endif\n$     HAVE_DECC_VAX = (f$search( \"SYS$SYSTEM:DECC$COMPILER.EXE\") .nes. \"\")\n$     HAVE_VAXC_VAX = (f$search( \"SYS$SYSTEM:VAXC.EXE\") .nes. \"\")\n$     MAY_HAVE_GNUC = (f$trnlnm( \"GNU_CC\") .nes. \"\")\n$     if (HAVE_DECC_VAX .and. MAY_USE_DECC)\n$     then\n$         ! We use DECC:\n$         USE_DECC_VAX = 1\n$         cc = \"cc /decc /prefix = all\"\n$         defs = \"''LOCAL_ZIP' VMS\"\n$     else\n$         ! We use VAXC (or GNU C):\n$         USE_DECC_VAX = 0\n$         defs = \"''LOCAL_ZIP' VMS\"\n$         if ((.not. HAVE_VAXC_VAX .and. MAY_HAVE_GNUC) .or. MAY_USE_GNUC)\n$         then\n$             cc = \"gcc\"\n$             opts = \"GNU_CC:[000000]GCCLIB.OLB /LIBRARY,\"\n$             dest = \"''dest'G\"\n$             cmpl = \"GNU C\"\n$         else\n$             if (HAVE_DECC_VAX)\n$             then\n$                 cc = \"cc /vaxc\"\n$             else\n$                 cc = \"cc\"\n$             endif\n$             dest = \"''dest'V\"\n$             cmpl = \"VAC C\"\n$         endif\n$         opts = \"''opts' SYS$DISK:[.''dest']VAXCSHR.OPT /OPTIONS,\"\n$     endif\n$ endif\n$!\n$! Change the destination directory, according to the VMS_IM_EXTRA and\n$! large-file options.  Set the bzip2 directory.\n$!\n$ dest = dest+ desti\n$ seek_bz = arch\n$ if (LARGE_FILE .ne. 0)\n$ then\n$     dest = dest+ \"L\"\n$     seek_bz = seek_bz+ \"L\"\n$ endif\n$!\n$! If BZIP2 support was selected, find the object library.\n$! Complain if things fail.\n$!\n$ cc_incl = \"[]\"\n$ incl_bzip2_m = \"\"\n$ lib_bzip2_opts = \"\"\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     bz2_olb = \"LIBBZ2_NS.OLB\"\n$     define incl_bzip2 'IZ_BZIP2'\n$     defs = \"''defs', BZIP2_SUPPORT\"\n$     @ [.VMS]FIND_BZIP2_LIB.COM 'IZ_BZIP2' 'seek_bz' 'bz2_olb' lib_bzip2\n$     if (f$trnlnm( \"lib_bzip2\") .eqs. \"\")\n$     then\n$         say \"Can't find BZIP2 object library.  Can't link.\"\n$         goto error\n$     else\n$         say \"BZIP2 dir = ''f$trnlnm( \"lib_bzip2\")'\"\n$         incl_bzip2_m = \", ZBZ2ERR\"\n$         lib_bzip2_opts = \"lib_bzip2:''bz2_olb' /library, \"\n$         cc_incl = cc_incl+ \", [.VMS]\"\n$     endif\n$ endif\n$!\n$! Reveal the plan.  If compiling, set some compiler options.\n$!\n$ if (LINK_ONLY)\n$ then\n$     say \"Linking on ''arch' for ''cmpl'.\"\n$ else\n$     say \"Compiling on ''arch' using ''cmpl'.\"\n$!\n$     DEF_UNX = \"/define = (''defs')\"\n$     DEF_CLI = \"/define = (''defs', VMSCLI)\"\n$     DEF_UTIL = \"/define = (''defs', UTIL)\"\n$ endif\n$!\n$! If [.'dest'] does not exist, either complain (link-only) or make it.\n$!\n$ if (f$search( \"''dest'.DIR;1\") .eqs. \"\")\n$ then\n$     if (LINK_ONLY)\n$     then\n$         say \"Can't find directory \"\"[.''dest']\"\".  Can't link.\"\n$         goto error\n$     else\n$         create /directory [.'dest']\n$     endif\n$ endif\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Arrange to get arch-specific list file placement, if LISTING, and if\n$! the user didn't specify a particular \"/LIST =\" destination.\n$!\n$     L = f$edit( LISTING, \"COLLAPSE\")\n$     if ((f$extract( 0, 5, L) .eqs. \"/LIST\") .and. -\n       (f$extract( 4, 1, L) .nes. \"=\"))\n$     then\n$         LISTING = \" /LIST = [.''dest']\"+ f$extract( 5, 1000, LISTING)\n$     endif\n$!\n$! Define compiler command.\n$!\n$     cc = cc+ \" /include = (''cc_incl')\"+ LISTING+ CCOPTS\n$!\n$ endif\n$!\n$! Define linker command.\n$!\n$ link = \"link ''LINKOPTS'\"\n$!\n$! Make a VAXCRTL options file for GNU C or VAC C, if needed.\n$!\n$ if ((opts .nes. \"\") .and. -\n   (f$locate( \"VAXCSHR\", f$edit( opts, \"UPCASE\")) .lt. f$length( opts)) .and. -\n   (f$search( \"[.''dest']VAXCSHR.OPT\") .eqs. \"\"))\n$ then\n$     open /write opt_file_ln [.'dest']VAXCSHR.OPT\n$     write opt_file_ln \"SYS$SHARE:VAXCRTL.EXE /SHARE\"\n$     close opt_file_ln\n$ endif\n$!\n$! Show interesting facts.\n$!\n$ say \"   architecture = ''arch' (destination = [.''dest'])\"\n$ if (.not. LINK_ONLY)\n$ then\n$     say \"   cc = ''cc'\"\n$ endif\n$ say \"   link = ''link'\"\n$ if (.not. MAKE_HELP)\n$ then\n$     say \"   Not making new help files.\"\n$ endif\n$ say \"\"\n$ if (.not. MAKE_MSG)\n$ then\n$     say \"   Not making new message files.\"\n$ endif\n$ say \"\"\n$!\n$ tmp = f$verify( 1)    ! Turn echo on to see what's happening.\n$!\n$!-------------------------------- Zip section -------------------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Process the help file, if desired.\n$!\n$     if (MAKE_HELP)\n$     then\n$         runoff /out = ZIP.HLP [.VMS]VMS_ZIP.RNH\n$     endif\n$!\n$! Process the message file, if desired.\n$!\n$     if (MAKE_MSG)\n$     then\n$!\n$! Create the message source file first, if it's not found.\n$!\n$         if (f$search( \"[.VMS]ZIP_MSG.MSG\") .eqs. \"\")\n$         then\n$             cc /include = [] /object = [.'dest']VMS_MSG_GEN.OBJ -\n               [.VMS]VMS_MSG_GEN.C\n$             link /executable = [.'dest']VMS_MSG_GEN.EXE -\n               [.'dest']VMS_MSG_GEN.OBJ\n$             create /fdl = [.VMS]STREAM_LF.FDL [.VMS]ZIP_MSG.MSG\n$             define /user_mode sys$output [.VMS]ZIP_MSG.MSG\n$             run [.'dest']VMS_MSG_GEN.EXE\n$             purge [.VMS]ZIP_MSG.MSG\n$             delete [.'dest']VMS_MSG_GEN.EXE;*, -\n               [.'dest']VMS_MSG_GEN.OBJ;*\n$         endif\n$!\n$         message /object = [.'dest']ZIP_MSG.OBJ /nosymbols -\n           [.VMS]ZIP_MSG.MSG\n$         link /shareable = [.'dest']ZIP_MSG.EXE [.'dest']ZIP_MSG.OBJ\n$     endif\n$!\n$! Compile the sources.\n$!\n$     cc 'DEF_UNX' /object = [.'dest']ZIP.OBJ ZIP.C\n$     cc 'DEF_UNX' /object = [.'dest']CRC32.OBJ CRC32.C\n$     cc 'DEF_UNX' /object = [.'dest']CRYPT.OBJ CRYPT.C\n$     cc 'DEF_UNX' /object = [.'dest']DEFLATE.OBJ DEFLATE.C\n$     cc 'DEF_UNX' /object = [.'dest']FILEIO.OBJ FILEIO.C\n$     cc 'DEF_UNX' /object = [.'dest']GLOBALS.OBJ GLOBALS.C\n$     cc 'DEF_UNX' /object = [.'dest']TREES.OBJ TREES.C\n$     cc 'DEF_UNX' /object = [.'dest']TTYIO.OBJ TTYIO.C\n$     cc 'DEF_UNX' /object = [.'dest']UTIL.OBJ UTIL.C\n$     cc 'DEF_UNX' /object = [.'dest']ZBZ2ERR.OBJ ZBZ2ERR.C\n$     cc 'DEF_UNX' /object = [.'dest']ZIPFILE.OBJ ZIPFILE.C\n$     cc 'DEF_UNX' /object = [.'dest']ZIPUP.OBJ ZIPUP.C\n$     cc /include = [] 'DEF_UNX' /object = [.'dest']VMS.OBJ -\n       [.VMS]VMS.C\n$     cc /include = [] 'DEF_UNX' /object = [.'dest']VMSMUNCH.OBJ -\n       [.VMS]VMSMUNCH.C\n$     cc /include = [] 'DEF_UNX' /object = [.'dest']VMSZIP.OBJ -\n       [.VMS]VMSZIP.C\n$!\n$! Create the object library.\n$!\n$     if (f$search( \"[.''dest']ZIP.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']ZIP.OLB\n$!\n$     libr /object /replace [.'dest']ZIP.OLB -\n       [.'dest']CRC32.OBJ, -\n       [.'dest']CRYPT.OBJ, -\n       [.'dest']DEFLATE.OBJ, -\n       [.'dest']FILEIO.OBJ, -\n       [.'dest']GLOBALS.OBJ, -\n       [.'dest']TREES.OBJ, -\n       [.'dest']TTYIO.OBJ, -\n       [.'dest']UTIL.OBJ, -\n       [.'dest']ZBZ2ERR.OBJ, -\n       [.'dest']ZIPFILE.OBJ, -\n       [.'dest']ZIPUP.OBJ, -\n       [.'dest']VMS.OBJ, -\n       [.'dest']VMSMUNCH.OBJ, -\n       [.'dest']VMSZIP.OBJ\n$!\n$ endif\n$!\n$! Link the executable.\n$!\n$ link /executable = [.'dest']'ZIPX_UNX'.EXE -\n   [.'dest']ZIP.OBJ, -\n   [.'dest']ZIP.OLB /include = (GLOBALS 'incl_bzip2_m') /library, -\n   'lib_bzip2_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]ZIP.OPT /options\n$!\n$!------------------------ Zip (CLI interface) section -----------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Process the CLI help file, if desired.\n$!\n$     if (MAKE_HELP)\n$     then\n$         set default [.VMS]\n$         edit /tpu /nosection /nodisplay /command = cvthelp.tpu -\n           zip_cli.help\n$         set default [-]\n$         runoff /output = ZIP_CLI.HLP [.VMS]ZIP_CLI.RNH\n$     endif\n$!\n$! Compile the CLI sources.\n$!\n$     cc 'DEF_CLI' /object = [.'dest']ZIPCLI.OBJ ZIP.C\n$     cc /include = [] 'DEF_CLI' /object = [.'dest']CMDLINE.OBJ -\n       [.VMS]CMDLINE.C\n$!\n$! Create the command definition object file.\n$!\n$     set command /object = [.'dest']ZIP_CLI.OBJ [.VMS]ZIP_CLI.CLD\n$!\n$! Create the CLI object library.\n$!\n$     if (f$search( \"[.''dest']ZIPCLI.OLB\") .eqs. \"\") then -\n       libr /object /create [.'dest']ZIPCLI.OLB\n$!\n$     libr /object /replace [.'dest']ZIPCLI.OLB -\n       [.'dest']ZIPCLI.OBJ, -\n       [.'dest']CMDLINE.OBJ, -\n       [.'dest']ZIP_CLI.OBJ\n$!\n$ endif\n$!\n$! Link the CLI executable.\n$!\n$ link /executable = [.'dest']'ZIPX_CLI'.EXE -\n   [.'dest']ZIPCLI.OBJ, -\n   [.'dest']ZIPCLI.OLB /library, -\n   [.'dest']ZIP.OLB /include = (GLOBALS 'incl_bzip2_m') /library, -\n   'lib_bzip2_opts' -\n   'opts' -\n   SYS$DISK:[.VMS]ZIP.OPT /options\n$!\n$!--------------------------- Zip utilities section --------------------------\n$!\n$ if (.not. LINK_ONLY)\n$ then\n$!\n$! Compile the variant Zip utilities library sources.\n$!\n$     cc 'DEF_UTIL' /object = [.'dest']CRC32_.OBJ CRC32.C\n$     cc 'DEF_UTIL' /object = [.'dest']CRYPT_.OBJ CRYPT.C\n$     cc 'DEF_UTIL' /object = [.'dest']FILEIO_.OBJ FILEIO.C\n$     cc 'DEF_UTIL' /object = [.'dest']UTIL_.OBJ UTIL.C\n$     cc 'DEF_UTIL' /object = [.'dest']ZIPFILE_.OBJ ZIPFILE.C\n$     cc 'DEF_UTIL' /include = [] /object = [.'dest']VMS_.OBJ [.VMS]VMS.C\n$!\n$! Create the Zip utilities object library.\n$!\n$     if f$search( \"[.''dest']ZIPUTILS.OLB\") .eqs. \"\" then -\n       libr /object /create [.'dest']ZIPUTILS.OLB\n$!\n$     libr /object /replace [.'dest']ZIPUTILS.OLB -\n       [.'dest']CRC32_.OBJ, -\n       [.'dest']CRYPT_.OBJ, -\n       [.'dest']FILEIO_.OBJ, -\n       [.'dest']GLOBALS.OBJ, -\n       [.'dest']TTYIO.OBJ, -\n       [.'dest']UTIL_.OBJ, -\n       [.'dest']ZIPFILE_.OBJ, -\n       [.'dest']VMS_.OBJ, -\n       [.'dest']VMSMUNCH.OBJ\n$!\n$! Compile the Zip utilities main program sources.\n$!\n$     cc 'DEF_UTIL' /object = [.'dest']ZIPCLOAK.OBJ ZIPCLOAK.C\n$     cc 'DEF_UTIL' /object = [.'dest']ZIPNOTE.OBJ ZIPNOTE.C\n$     cc 'DEF_UTIL' /object = [.'dest']ZIPSPLIT.OBJ ZIPSPLIT.C\n$!\n$ endif\n$!\n$! Link the Zip utilities executables.\n$!\n$ link /executable = [.'dest']ZIPCLOAK.EXE -\n   [.'dest']ZIPCLOAK.OBJ, -\n   [.'dest']ZIPUTILS.OLB /include = (GLOBALS) /library, -\n   'opts' -\n   SYS$DISK:[.VMS]ZIP.OPT /options\n$!\n$ link /executable = [.'dest']ZIPNOTE.EXE -\n   [.'dest']ZIPNOTE.OBJ, -\n   [.'dest']ZIPUTILS.OLB /include = (GLOBALS) /library, -\n   'opts' -\n   SYS$DISK:[.VMS]ZIP.OPT /OPTIONS\n$!\n$ LINK /EXECUTABLE = [.'DEST']ZIPSPLIT.EXE -\n   [.'DEST']ZIPSPLIT.OBJ, -\n   [.'DEST']ZIPUTILS.OLB /INCLUDE = (globals) /LIBRARY, -\n   'opts' -\n   SYS$DISK:[.VMS]ZIP.OPT /options\n$!\n$!----------------------- Logical name removal section -----------------------\n$!\n$ if (IZ_BZIP2 .nes. \"\")\n$ then\n$     if (f$trnlnm( \"incl_bzip2\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign incl_bzip2\n$     endif\n$     if (f$trnlnm( \"lib_bzip2\", \"LNM$PROCESS_TABLE\") .nes. \"\")\n$     then\n$         deassign lib_bzip2\n$     endif\n$ endif\n$!\n$!------------------------------ Symbols section -----------------------------\n$!\n$ there = here- \"]\"+ \".''dest']\"\n$!\n$! Define the foreign command symbols.  Similar commands may be useful\n$! in SYS$MANAGER:SYLOGIN.COM and/or users' LOGIN.COM.\n$!\n$ zip      == \"$''there'''ZIPEXEC'.exe\"\n$ zipcloak == \"$''there'zipcloak.exe\"\n$ zipnote  == \"$''there'zipnote.exe\"\n$ zipsplit == \"$''there'zipsplit.exe\"\n$!\n$! Restore the original default directory and DCL verify status.\n$!\n$ error:\n$!\n$ if (f$type( here) .nes. \"\")\n$ then\n$     if (here .nes. \"\")\n$     then\n$         set default 'here'\n$     endif\n$ endif\n$!\n$ if (f$type( OLD_VERIFY) .nes. \"\")\n$ then\n$     tmp = f$verify( OLD_VERIFY)\n$ endif\n$!\n$ exit\n$!\n"
  },
  {
    "path": "deps/infozip/zip30/vms/bzlib.h",
    "content": "/* 2007-01-13 SMS.\n * VMS-specific BZLIB.H jacket header file to ensure compatibility with\n * BZIP2 code compiled using /NAMES = AS_IS.\n *\n * The logical name INCL_BZIP2 must point to the BZIP2 source directory.\n *\n * A \"names as_is\" prototype for bz_internal_error() is included for the\n * same reason.  See bzip2 \"bzlib_private.h\".  Note that this \"names\n * as_is\" prototype must be the first to be read by the compiler, but\n * one or more other prototypes (perhaps with the default \"names\"\n * attributes) should cause no trouble.\n */\n\n#pragma names save\n#pragma names as_is\n\n#include \"INCL_BZIP2:BZLIB.H\"\n\nextern void bz_internal_error ( int errcode );\n\n#pragma names restore\n"
  },
  {
    "path": "deps/infozip/zip30/vms/cmdline.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/*\n   Test procedure:\n\n   Compile and link (in [.VMS] directory):\n\n      define vms SYS$DISK:[]\n      set command /object ZIP_CLI.CLD\n      cc /define = (TEST, VMSCLI) /include = [-] CMDLINE\n      link link CMDLINE.OBJ, ZIP_CLI.OBJ\n\n   Run:\n\n      exec*ute == \"$SYS$DISK:[]'\"\n      exec cmdline [options ...]\n\n*/\n\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n# define module_name VMS_ZIP_CMDLINE\n# define module_ident \"02-006\"\n#endif /* 0 */\n\n/*\n**\n**  Facility:   ZIP\n**\n**  Module:     VMS_ZIP_CMDLINE\n**\n**  Author:     Hunter Goatley <goathunter@MadGoat.com>\n**\n**  Date:       July 30, 1993\n**\n**  Abstract:   Routines to handle a VMS CLI interface for Zip.  The CLI\n**              command line is parsed and a new argc/argv are built and\n**              returned to Zip.\n**\n**  Modified by:\n**\n**      02-007          Steven Schweda          09-FEB-2005\n**              Added /PRESERVE_CASE.\n**      02-006          Onno van der Linden,\n**                      Christian Spieler       07-JUL-1998 23:03\n**              Support GNU CC 2.8 on Alpha AXP (vers-num unchanged).\n**      02-006          Johnny Lee              25-JUN-1998 07:40\n**              Fixed typo (superfluous ';') (vers-num unchanged).\n**      02-006          Christian Spieler       12-SEP-1997 23:17\n**              Fixed bugs in /BEFORE and /SINCE handlers (vers-num unchanged).\n**      02-006          Christian Spieler       12-JUL-1997 02:05\n**              Complete revision of the argv strings construction.\n**              Added handling of \"-P pwd\", \"-R\", \"-i@file\", \"-x@file\" options.\n**      02-005          Patrick Ellis           09-MAY-1996 22:25\n**              Show UNIX style help screen when UNIX style options are used.\n**      02-004          Onno van der Linden,\n**                      Christian Spieler       13-APR-1996 20:05\n**              Removed /ENCRYPT=VERIFY (\"-ee\" option).\n**      02-003          Christian Spieler       11-FEB-1996 23:05\n**              Added handling of /EXTRAFIELDS qualifier (\"-X\" option).\n**      02-002          Christian Spieler       09-JAN-1996 22:25\n**              Added \"#include crypt.h\", corrected typo.\n**      02-001          Christian Spieler       04-DEC-1995 16:00\n**              Fixed compilation in DEC CC's ANSI mode.\n**      02-000          Christian Spieler       10-OCT-1995 17:54\n**              Modified for Zip v2.1, added several new options.\n**      01-000          Hunter Goatley          30-JUL-1993 07:54\n**              Original version (for Zip v1.9p1).\n**\n*/\n\n\f\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n# if defined(__DECC) || defined(__GNUC__)\n#  pragma module module_name module_ident\n# else\n#  module module_name module_ident\n# endif\n#endif /* 0 */\n\n/* Accomodation for /NAMES = AS_IS with old header files. */\n\n#define lib$establish LIB$ESTABLISH\n#define lib$get_foreign LIB$GET_FOREIGN\n#define lib$get_input LIB$GET_INPUT\n#define lib$sig_to_ret LIB$SIG_TO_RET\n#define ots$cvt_tu_l OTS$CVT_TU_L\n#define str$concat STR$CONCAT\n#define str$find_first_substring STR$FIND_FIRST_SUBSTRING\n#define str$free1_dx STR$FREE1_DX\n\n#include \"zip.h\"\n#ifndef TEST\n#include \"crypt.h\"      /* for VMSCLI_help() */\n#include \"revision.h\"   /* for VMSCLI_help() */\n#endif /* !TEST */\n\n#include <ssdef.h>\n#include <descrip.h>\n#include <climsgdef.h>\n#include <clidef.h>\n#include <lib$routines.h>\n#include <ots$routines.h>\n#include <str$routines.h>\n\n#ifndef CLI$_COMMA\nglobalvalue CLI$_COMMA;\n#endif\n\n/*\n**  \"Macro\" to initialize a dynamic string descriptor.\n*/\n#define init_dyndesc(dsc) {\\\n        dsc.dsc$w_length = 0;\\\n        dsc.dsc$b_dtype = DSC$K_DTYPE_T;\\\n        dsc.dsc$b_class = DSC$K_CLASS_D;\\\n        dsc.dsc$a_pointer = NULL;}\n\n/*\n**  Memory allocation step for argv string buffer.\n*/\n#define ARGBSIZE_UNIT 256\n\n/*\n**  Memory reallocation macro for argv string buffer.\n*/\n#define CHECK_BUFFER_ALLOCATION(buf, reserved, requested) { \\\n    if ((requested) > (reserved)) { \\\n        char *save_buf = (buf); \\\n        (reserved) += ARGBSIZE_UNIT; \\\n        if (((buf) = (char *) realloc((buf), (reserved))) == NULL) { \\\n            if (save_buf != NULL) free(save_buf); \\\n            return (SS$_INSFMEM); \\\n        } \\\n    } \\\n}\n\n/*\n**  Define descriptors for all of the CLI parameters and qualifiers.\n*/\n$DESCRIPTOR(cli_delete,         \"DELETE\");              /* -d */\n$DESCRIPTOR(cli_freshen,        \"FRESHEN\");             /* -f */\n$DESCRIPTOR(cli_move,           \"MOVE\");                /* -m */\n$DESCRIPTOR(cli_update,         \"UPDATE\");              /* -u */\n$DESCRIPTOR(cli_exclude,        \"EXCLUDE\");             /* -x */\n$DESCRIPTOR(cli_include,        \"INCLUDE\");             /* -i */\n$DESCRIPTOR(cli_exlist,         \"EXLIST\");              /* -x@ */\n$DESCRIPTOR(cli_inlist,         \"INLIST\");              /* -i@ */\n$DESCRIPTOR(cli_adjust,         \"ADJUST_OFFSETS\");      /* -A */\n$DESCRIPTOR(cli_append,         \"APPEND\");              /* -g */\n$DESCRIPTOR(cli_batch,          \"BATCH\");               /* -@ */\n$DESCRIPTOR(cli_before,         \"BEFORE\");              /* -tt */\n$DESCRIPTOR(cli_comments,       \"COMMENTS\");            /* -c,-z */\n$DESCRIPTOR(cli_comment_archive,\"COMMENTS.ARCHIVE\");    /* -z */\n$DESCRIPTOR(cli_comment_zipfile,\"COMMENTS.ZIP_FILE\");   /* -z */\n$DESCRIPTOR(cli_comment_files,  \"COMMENTS.FILES\");      /* -c */\n$DESCRIPTOR(cli_compression,    \"COMPRESSION\");         /* -Z */\n$DESCRIPTOR(cli_compression_b,  \"COMPRESSION.BZIP2\");   /* -Zb */\n$DESCRIPTOR(cli_compression_d,  \"COMPRESSION.DEFLATE\"); /* -Zd */\n$DESCRIPTOR(cli_compression_s,  \"COMPRESSION.STORE\");   /* -Zs */\n$DESCRIPTOR(cli_copy_entries,   \"COPY_ENTRIES\");        /* -U */\n$DESCRIPTOR(cli_descriptors,    \"DESCRIPTORS\");         /* -fd */\n$DESCRIPTOR(cli_difference,     \"DIFFERENCE\");          /* -DF */\n$DESCRIPTOR(cli_dirnames,       \"DIRNAMES\");            /* -D */\n$DESCRIPTOR(cli_display,        \"DISPLAY\");             /* -d? */\n$DESCRIPTOR(cli_display_bytes,  \"DISPLAY.BYTES\");       /* -db */\n$DESCRIPTOR(cli_display_counts, \"DISPLAY.COUNTS\");      /* -dc */\n$DESCRIPTOR(cli_display_dots,   \"DISPLAY.DOTS\");        /* -dd,-ds */\n$DESCRIPTOR(cli_display_globaldots, \"DISPLAY.GLOBALDOTS\"); /* -dg */\n$DESCRIPTOR(cli_display_usize,  \"DISPLAY.USIZE\");       /* -du */\n$DESCRIPTOR(cli_display_volume, \"DISPLAY.VOLUME\");      /* -dv */\n$DESCRIPTOR(cli_dot_version,    \"DOT_VERSION\");         /* -ww */\n$DESCRIPTOR(cli_encrypt,        \"ENCRYPT\");             /* -e,-P */\n$DESCRIPTOR(cli_extra_fields,   \"EXTRA_FIELDS\");        /* -X [/NO] */\n$DESCRIPTOR(cli_extra_fields_normal, \"EXTRA_FIELDS.NORMAL\"); /* no -X */\n$DESCRIPTOR(cli_extra_fields_keep, \"EXTRA_FIELDS.KEEP_EXISTING\"); /* -X- */\n$DESCRIPTOR(cli_filesync,       \"FILESYNC\");            /* -FS */\n$DESCRIPTOR(cli_fix_archive,    \"FIX_ARCHIVE\");         /* -F[F] */\n$DESCRIPTOR(cli_fix_normal,     \"FIX_ARCHIVE.NORMAL\");  /* -F */\n$DESCRIPTOR(cli_fix_full,       \"FIX_ARCHIVE.FULL\");    /* -FF */\n$DESCRIPTOR(cli_full_path,      \"FULL_PATH\");           /* -p */\n$DESCRIPTOR(cli_grow,           \"GROW\");                /* -g */\n$DESCRIPTOR(cli_help,           \"HELP\");                /* -h */\n$DESCRIPTOR(cli_help_normal,    \"HELP.NORMAL\");         /* -h */\n$DESCRIPTOR(cli_help_extended,  \"HELP.EXTENDED\");       /* -h2 */\n$DESCRIPTOR(cli_junk,           \"JUNK\");                /* -j */\n$DESCRIPTOR(cli_keep_version,   \"KEEP_VERSION\");        /* -w */\n$DESCRIPTOR(cli_latest,         \"LATEST\");              /* -o */\n$DESCRIPTOR(cli_level,          \"LEVEL\");               /* -[0-9] */\n$DESCRIPTOR(cli_license,        \"LICENSE\");             /* -L */\n$DESCRIPTOR(cli_log_file,       \"LOG_FILE\");            /* -la,-lf,-li */\n$DESCRIPTOR(cli_log_file_append, \"LOG_FILE.APPEND\");    /* -la */\n$DESCRIPTOR(cli_log_file_file,  \"LOG_FILE.FILE\");       /* -lf */\n$DESCRIPTOR(cli_log_file_info,  \"LOG_FILE.INFORMATIONAL\"); /* -li */\n$DESCRIPTOR(cli_must_match,     \"MUST_MATCH\");          /* -MM */\n$DESCRIPTOR(cli_output,         \"OUTPUT\");              /* -O */\n$DESCRIPTOR(cli_patt_case,      \"PATTERN_CASE\");        /* -ic[-] */\n$DESCRIPTOR(cli_patt_case_blind, \"PATTERN_CASE.BLIND\"); /* -ic */\n$DESCRIPTOR(cli_patt_case_sensitive, \"PATTERN_CASE.SENSITIVE\"); /* -ic- */\n$DESCRIPTOR(cli_pkzip,          \"PKZIP\");               /* -k */\n$DESCRIPTOR(cli_pres_case,      \"PRESERVE_CASE\");       /* -C */\n$DESCRIPTOR(cli_pres_case_no2,  \"PRESERVE_CASE.NOODS2\");/* -C2- */\n$DESCRIPTOR(cli_pres_case_no5,  \"PRESERVE_CASE.NOODS5\");/* -C5- */\n$DESCRIPTOR(cli_pres_case_ods2, \"PRESERVE_CASE.ODS2\");  /* -C2 */\n$DESCRIPTOR(cli_pres_case_ods5, \"PRESERVE_CASE.ODS5\");  /* -C5 */\n$DESCRIPTOR(cli_quiet,          \"QUIET\");               /* -q */\n$DESCRIPTOR(cli_recurse,        \"RECURSE\");             /* -r,-R */\n$DESCRIPTOR(cli_recurse_path,   \"RECURSE.PATH\");        /* -r */\n$DESCRIPTOR(cli_recurse_fnames, \"RECURSE.FILENAMES\");   /* -R */\n$DESCRIPTOR(cli_show,           \"SHOW\");                /* -s? */\n$DESCRIPTOR(cli_show_command,   \"SHOW.COMMAND\");        /* -sc */\n$DESCRIPTOR(cli_show_debug,     \"SHOW.DEBUG\");          /* -sd */\n$DESCRIPTOR(cli_show_files,     \"SHOW.FILES\");          /* -sf */\n$DESCRIPTOR(cli_show_options,   \"SHOW.OPTIONS\");        /* -so */\n$DESCRIPTOR(cli_since,          \"SINCE\");               /* -t */\n$DESCRIPTOR(cli_split,          \"SPLIT\");               /* -s,-sb,-sp,-sv */\n$DESCRIPTOR(cli_split_bell,     \"SPLIT.BELL\");          /* -sb */\n$DESCRIPTOR(cli_split_pause,    \"SPLIT.PAUSE\");         /* -sp */\n$DESCRIPTOR(cli_split_size,     \"SPLIT.SIZE\");          /* -s */\n$DESCRIPTOR(cli_split_verbose,  \"SPLIT.VERBOSE\");       /* -sv */\n$DESCRIPTOR(cli_store_types,    \"STORE_TYPES\");         /* -n */\n$DESCRIPTOR(cli_sverbose,       \"SVERBOSE\");            /* -sv */\n$DESCRIPTOR(cli_symlinks,       \"SYMLINKS\");            /* -y */\n$DESCRIPTOR(cli_temp_path,      \"TEMP_PATH\");           /* -b */\n$DESCRIPTOR(cli_test,           \"TEST\");                /* -T */\n$DESCRIPTOR(cli_test_unzip,     \"TEST.UNZIP\");          /* -TT */\n$DESCRIPTOR(cli_translate_eol,  \"TRANSLATE_EOL\");       /* -l[l] */\n$DESCRIPTOR(cli_transl_eol_lf,  \"TRANSLATE_EOL.LF\");    /* -l */\n$DESCRIPTOR(cli_transl_eol_crlf,\"TRANSLATE_EOL.CRLF\");  /* -ll */\n$DESCRIPTOR(cli_unsfx,          \"UNSFX\");               /* -J */\n$DESCRIPTOR(cli_verbose,        \"VERBOSE\");             /* -v (?) */\n$DESCRIPTOR(cli_verbose_normal, \"VERBOSE.NORMAL\");      /* -v */\n$DESCRIPTOR(cli_verbose_more,   \"VERBOSE.MORE\");        /* -vv */\n$DESCRIPTOR(cli_verbose_debug,  \"VERBOSE.DEBUG\");       /* -vvv */\n$DESCRIPTOR(cli_verbose_command,\"VERBOSE.COMMAND\");     /* (none) */\n$DESCRIPTOR(cli_vms,            \"VMS\");                 /* -V */\n$DESCRIPTOR(cli_vms_all,        \"VMS.ALL\");             /* -VV */\n$DESCRIPTOR(cli_wildcard,       \"WILDCARD\");            /* -nw */\n$DESCRIPTOR(cli_wildcard_nospan,\"WILDCARD.NOSPAN\");     /* -W */\n\n$DESCRIPTOR(cli_yyz,            \"YYZ_ZIP\");\n\n$DESCRIPTOR(cli_zip64,          \"ZIP64\");               /* -fz */\n$DESCRIPTOR(cli_zipfile,        \"ZIPFILE\");\n$DESCRIPTOR(cli_infile,         \"INFILE\");\n$DESCRIPTOR(zip_command,        \"zip \");\n\nstatic int show_VMSCLI_help;\n\n#if !defined(zip_clitable)\n#  define zip_clitable ZIP_CLITABLE\n#endif\n#if defined(__DECC) || defined(__GNUC__)\nextern void *zip_clitable;\n#else\nglobalref void *zip_clitable;\n#endif\n\n/* extern unsigned long LIB$GET_INPUT(void), LIB$SIG_TO_RET(void); */\n\n#ifndef __STARLET_LOADED\n#ifndef sys$bintim\n#  define sys$bintim SYS$BINTIM\n#endif\n#ifndef sys$numtim\n#  define sys$numtim SYS$NUMTIM\n#endif\nextern int sys$bintim ();\nextern int sys$numtim ();\n#endif /* !__STARLET_LOADED */\n#ifndef cli$dcl_parse\n#  define cli$dcl_parse CLI$DCL_PARSE\n#endif\n#ifndef cli$present\n#  define cli$present CLI$PRESENT\n#endif\n#ifndef cli$get_value\n#  define cli$get_value CLI$GET_VALUE\n#endif\nextern unsigned long cli$dcl_parse ();\nextern unsigned long cli$present ();\nextern unsigned long cli$get_value ();\n\nunsigned long vms_zip_cmdline (int *, char ***);\nstatic unsigned long get_list (struct dsc$descriptor_s *,\n                               struct dsc$descriptor_d *, int,\n                               char **, unsigned long *, unsigned long *);\nstatic unsigned long get_time (struct dsc$descriptor_s *qual, char *timearg);\nstatic unsigned long check_cli (struct dsc$descriptor_s *);\nstatic int verbose_command = 0;\n\n\f\n#ifdef TEST\n\nchar errbuf[ FNMAX+ 81];        /* Error message buffer. */\n\nvoid ziperr( int c, char *h)    /* Error message display function. */\n{\n/* int c: error code from the ZE_ class */\n/* char *h: message about how it happened */\n\nprintf( \"%d: %s\\n\", c, h);\n}\n\nint\nmain(int argc, char **argv)     /* Main program. */\n{\n    return (vms_zip_cmdline(&argc, &argv));\n}\n\n#endif /* def TEST */\n\n\f\nunsigned long\nvms_zip_cmdline (int *argc_p, char ***argv_p)\n{\n/*\n**  Routine:    vms_zip_cmdline\n**\n**  Function:\n**\n**      Parse the DCL command line and create a fake argv array to be\n**      handed off to Zip.\n**\n**      NOTE: the argv[] is built as we go, so all the parameters are\n**      checked in the appropriate order!!\n**\n**  Formal parameters:\n**\n**      argc_p          - Address of int to receive the new argc\n**      argv_p          - Address of char ** to receive the argv address\n**\n**  Calling sequence:\n**\n**      status = vms_zip_cmdline (&argc, &argv);\n**\n**  Returns:\n**\n**      SS$_NORMAL      - Success.\n**      SS$_INSFMEM     - A malloc() or realloc() failed\n**      SS$_ABORT       - Bad time value\n**\n*/\n    register unsigned long status;\n    char options[ 64];\n    char *the_cmd_line;                 /* buffer for argv strings */\n    unsigned long cmdl_size;            /* allocated size of buffer */\n    unsigned long cmdl_len;             /* used size of buffer */\n    char *ptr;\n    int  x, len;\n\n    int new_argc;\n    char **new_argv;\n\n    struct dsc$descriptor_d work_str;\n    struct dsc$descriptor_d foreign_cmdline;\n\n    init_dyndesc(work_str);\n    init_dyndesc(foreign_cmdline);\n\n    /*\n    **  See if the program was invoked by the CLI (SET COMMAND) or by\n    **  a foreign command definition.  Check for /YYZ_ZIP, which is a\n    **  valid default qualifier solely for this test.\n    */\n    show_VMSCLI_help = TRUE;\n    status = check_cli(&cli_yyz);\n    if (!(status & 1)) {\n        lib$get_foreign(&foreign_cmdline);\n        /*\n        **  If nothing was returned or the first character is a \"-\", then\n        **  assume it's a UNIX-style command and return.\n        */\n        if (foreign_cmdline.dsc$w_length == 0)\n            return (SS$_NORMAL);\n        if ((*(foreign_cmdline.dsc$a_pointer) == '-') ||\n            ((foreign_cmdline.dsc$w_length > 1) &&\n             (*(foreign_cmdline.dsc$a_pointer) == '\"') &&\n             (*(foreign_cmdline.dsc$a_pointer + 1) == '-'))) {\n            show_VMSCLI_help = FALSE;\n            return (SS$_NORMAL);\n        }\n\n        str$concat(&work_str, &zip_command, &foreign_cmdline);\n        status = cli$dcl_parse(&work_str, &zip_clitable, lib$get_input,\n                        lib$get_input, 0);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  There's always going to be a new_argv[] because of the image name.\n    */\n    if ((the_cmd_line = (char *) malloc(cmdl_size = ARGBSIZE_UNIT)) == NULL)\n        return (SS$_INSFMEM);\n\n    strcpy(the_cmd_line, \"zip\");\n    cmdl_len = sizeof(\"zip\");\n\n    /*\n    **  First, check to see if any of the regular options were specified.\n    */\n\n    options[0] = '-';\n    ptr = &options[1];          /* Point to temporary buffer */\n\n    /*\n    **  Copy entries.\n    */\n    status = cli$present(&cli_copy_entries);\n    if (status & 1)\n        /* /COPY_ENTRIES */\n        *ptr++ = 'U';\n\n    /*\n    **  Delete the specified files from the zip file?\n    */\n    status = cli$present(&cli_delete);\n    if (status & 1)\n        /* /DELETE */\n        *ptr++ = 'd';\n\n    /*\n    **  Freshen (only changed files).\n    */\n    status = cli$present(&cli_freshen);\n    if (status & 1)\n        /* /FRESHEN */\n        *ptr++ = 'f';\n\n    /*\n    **  Delete the files once they've been added to the zip file.\n    */\n    status = cli$present(&cli_move);\n    if (status & 1)\n        /* /MOVE */\n        *ptr++ = 'm';\n\n    /*\n    **  Add changed and new files.\n    */\n    status = cli$present(&cli_update);\n    if (status & 1)\n        /* /UPDATE */\n        *ptr++ = 'u';\n\n    /*\n    **  Check for the compression level (-0 through -9).\n    */\n    status = cli$present(&cli_level);\n    if (status & 1) {\n        /* /LEVEL = value */\n\n        unsigned long binval;\n\n        status = cli$get_value(&cli_level, &work_str);\n        status = ots$cvt_tu_l(&work_str, &binval);\n        if (!(status & 1) || (binval > 9)) {\n           return (SS$_ABORT);\n        }\n        *ptr++ = binval + '0';\n    }\n\n    /*\n    **  Adjust offsets of zip archive entries.\n    */\n    status = cli$present(&cli_adjust);\n    if (status & 1)\n        /* /ADJUST_OFFSETS */\n        *ptr++ = 'A';\n\n    /*\n    **  Add comments?\n    */\n    status = cli$present(&cli_comments);\n    if (status & 1)\n    {\n        int archive_or_zip_file = 0;\n\n        if ((status = cli$present(&cli_comment_archive)) & 1)\n            /* /COMMENTS = ARCHIVE */\n            archive_or_zip_file = 1;\n        if ((status = cli$present(&cli_comment_zipfile)) & 1)\n            /* /COMMENTS = ZIP_FILE */\n            archive_or_zip_file = 1;\n        if (archive_or_zip_file != 0)\n            /* /COMMENTS = ARCHIVE */\n            *ptr++ = 'z';\n        if ((status = cli$present(&cli_comment_files)) & 1)\n            /* /COMMENTS = FILES */\n            *ptr++ = 'c';\n    }\n\n    /*\n    **  Preserve case in file names.\n    */\n#define OPT_C   \"-C\"            /* Preserve case all. */\n#define OPT_CN  \"-C-\"           /* Down-case all. */\n#define OPT_C2  \"-C2\"           /* Preserve case ODS2. */\n#define OPT_C2N \"-C2-\"          /* Down-case ODS2. */\n#define OPT_C5  \"-C5\"           /* Preserve case ODS5. */\n#define OPT_C5N \"-C5-\"          /* Down-case ODS5. */\n\n    status = cli$present( &cli_pres_case);\n    if ((status & 1) || (status == CLI$_NEGATED))\n    {\n        /* /[NO]PRESERVE_CASE */\n        char *opt;\n        int ods2 = 0;\n        int ods5 = 0;\n\n        if (status == CLI$_NEGATED)\n        {\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_CN)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_CN);\n        }\n        else\n        {\n            if (cli$present( &cli_pres_case_no2) & 1)\n            {\n                /* /PRESERVE_CASE = NOODS2 */\n                ods2 = -1;\n            }\n            if (cli$present( &cli_pres_case_no5) & 1)\n            {\n                /* /PRESERVE_CASE = NOODS5 */\n                ods5 = -1;\n            }\n            if (cli$present( &cli_pres_case_ods2) & 1)\n            {\n                /* /PRESERVE_CASE = ODS2 */\n                ods2 = 1;\n            }\n            if (cli$present( &cli_pres_case_ods5) & 1)\n            {\n                /* /PRESERVE_CASE = ODS5 */\n                ods5 = 1;\n            }\n\n            if (ods2 == ods5)\n            {\n                /* Plain \"-C[-]\". */\n                if (ods2 < 0)\n                    opt = OPT_CN;\n                else\n                    opt = OPT_C;\n\n                x = cmdl_len;\n                cmdl_len += strlen( opt)+ 1;\n                CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n                strcpy( &the_cmd_line[ x], opt);\n            }\n            else\n            {\n                if (ods2 != 0)\n                {\n                    /* \"-C2[-]\". */\n                    if (ods2 < 0)\n                        opt = OPT_C2N;\n                    else\n                        opt = OPT_C2;\n\n                    x = cmdl_len;\n                    cmdl_len += strlen( opt)+ 1;\n                    CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n                    strcpy( &the_cmd_line[ x], opt);\n                }\n\n                if (ods5 != 0)\n                {\n                    /* \"-C5[-]\". */\n                    if (ods5 < 0)\n                        opt = OPT_C5N;\n                    else\n                        opt = OPT_C5;\n\n                    x = cmdl_len;\n                    cmdl_len += strlen( opt)+ 1;\n                    CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n                    strcpy( &the_cmd_line[ x], opt);\n                }\n            }\n        }\n    }\n\n    /*\n    **  Pattern case sensitivity.\n    */\n#define OPT_IC  \"-ic\"           /* Case-insensitive pattern matching. */\n#define OPT_ICN \"-ic-\"          /* Case-sensitive pattern matching. */\n\n    status = cli$present( &cli_patt_case);\n    if (status & 1)\n    {\n        if (cli$present( &cli_patt_case_blind) & 1)\n        {\n            /* \"-ic\". */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_IC)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_IC);\n        }\n        else if (cli$present( &cli_patt_case_sensitive) & 1)\n        {\n            /* \"-ic-\". */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_ICN)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_ICN);\n        }\n    }\n\n    /*\n    **  Data descriptors.\n    */\n#define OPT_FD \"-fd\"\n\n    status = cli$present( &cli_descriptors);\n    if (status & 1)\n    {\n        /* /DESCRIPTORS */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_FD)+ 1;\n        CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x], OPT_FD);\n    }\n\n    /*\n    **  Difference archive.  Add only new or changed files.\n    */\n#define OPT_DF   \"-DF\"          /* Difference archive. */\n\n    if ((status = cli$present( &cli_difference)) & 1)\n    {\n        /* /DIFFERENCE */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_DF)+ 1;\n        CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x],  OPT_DF);\n    }\n\n    /*\n    **  Do not add/modify directory entries.\n    */\n    status = cli$present(&cli_dirnames);\n    if (!(status & 1))\n        /* /DIRNAMES */\n        *ptr++ = 'D';\n\n    /*\n    **  Encrypt?\n    */\n    status = cli$present(&cli_encrypt);\n    if (status & 1)\n        if ((status = cli$get_value(&cli_encrypt, &work_str)) & 1) {\n            /* /ENCRYPT = value */\n            x = cmdl_len;\n            cmdl_len += work_str.dsc$w_length + 4;\n            CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n            strcpy(&the_cmd_line[x], \"-P\");\n            strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,\n                    work_str.dsc$w_length);\n            the_cmd_line[cmdl_len-1] = '\\0';\n        } else {\n            /* /ENCRYPT */\n            *ptr++ = 'e';\n        }\n\n    /*\n    **  Fix the zip archive structure.\n    */\n    status = cli$present(&cli_fix_archive);\n    if (status & 1) {\n        *ptr++ = 'F';\n        /* /FIX_ARCHIVE = NORMAL */\n        if ((status = cli$present(&cli_fix_full)) & 1) {\n            /* /FIX_ARCHIVE = FULL */\n            *ptr++ = 'F';\n        }\n    }\n\n    /*\n    **  Filesync.  Delete archive entry if no such file.\n    */\n#define OPT_FS   \"-FS\"          /* Filesync. */\n\n    if ((status = cli$present( &cli_filesync)) & 1)\n    {\n        /* /FILESYNC */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_FS)+ 1;\n        CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x],  OPT_FS);\n    }\n\n    /*\n    **  Append (allow growing of existing zip file).\n    */\n    status = cli$present(&cli_append);\n    if (status & 1)\n        /* /APPEND */\n        *ptr++ = 'g';\n\n    status = cli$present(&cli_grow);\n    if (status & 1)\n        /* /GROW */\n        *ptr++ = 'g';\n\n    /*\n    **  Show the help.\n    */\n#define OPT_H2 \"-h2\"\n\n    status = cli$present(&cli_help);\n    if (status & 1)\n    {\n        status = cli$present( &cli_help_normal);\n        if (status & 1)\n        {\n            /* /HELP [= NORMAL] */\n            *ptr++ = 'h';\n        }\n        status = cli$present( &cli_help_extended);\n        if (status & 1)\n        {\n            /* /HELP = EXTENDED */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_H2)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_H2);\n        }\n    }\n\n    /*\n    **  Junk path names (directory specs).\n    */\n    status = cli$present(&cli_junk);\n    if (status & 1)\n        /* /JUNK */\n        *ptr++ = 'j';\n\n    /*\n    **  Simulate zip file made by PKZIP.\n    */\n    status = cli$present(&cli_pkzip);\n    if (status & 1)\n        /* /KEEP_VERSION */\n        *ptr++ = 'k';\n\n    /*\n    **  Translate end-of-line.\n    */\n    status = cli$present(&cli_translate_eol);\n    if (status & 1) {\n        /* /TRANSLATE_EOL [= LF]*/\n        *ptr++ = 'l';\n        if ((status = cli$present(&cli_transl_eol_crlf)) & 1) {\n            /* /TRANSLATE_EOL = CRLF */\n            *ptr++ = 'l';\n        }\n    }\n\n    /*\n    **  Show the software license.\n    */\n    status = cli$present(&cli_license);\n    if (status & 1)\n        /* /LICENSE */\n        *ptr++ = 'L';\n\n    /*\n    **  Set zip file time to time of latest file in it.\n    */\n    status = cli$present(&cli_latest);\n    if (status & 1)\n        /* /LATEST */\n        *ptr++ = 'o';\n\n    /*\n    **  Store full path (default).\n    */\n    status = cli$present(&cli_full_path);\n    if (status == CLI$_PRESENT)\n        /* /FULL_PATH */\n        *ptr++ = 'p';\n    else if (status == CLI$_NEGATED)\n        /* /NOFULL_PATH */\n        *ptr++ = 'j';\n\n    /*\n    **  Junk Zipfile prefix (SFX stub etc.).\n    */\n    status = cli$present(&cli_unsfx);\n    if (status & 1)\n        /* /UNSFX */\n        *ptr++ = 'J';\n\n    /*\n    **  Recurse through subdirectories.\n    */\n    status = cli$present(&cli_recurse);\n    if (status & 1) {\n        if ((status = cli$present(&cli_recurse_fnames)) & 1)\n            /* /RECURSE [= PATH] */\n            *ptr++ = 'R';\n        else\n            /* /RECURSE [= FILENAMES] */\n            *ptr++ = 'r';\n    }\n\n    /*\n    **  Test Zipfile.\n    */\n    status = cli$present(&cli_test);\n    if (status & 1) {\n        /* /TEST */\n        *ptr++ = 'T';\n    }\n\n    /*\n    **  Be verbose.\n    */\n    status = cli$present(&cli_verbose);\n    if (status & 1) {\n        int i;\n        int verbo = 0;\n\n        /* /VERBOSE */\n        if ((status = cli$present(&cli_verbose_command)) & 1)\n        {\n            /* /VERBOSE = COMMAND */\n            verbose_command = 1;\n        }\n\n        /* Note that any or all of the following options may be\n           specified, and the maximum one is used.\n        */\n        if ((status = cli$present(&cli_verbose_normal)) & 1)\n            /* /VERBOSE [ = NORMAL ] */\n            verbo = 1;\n        if ((status = cli$present(&cli_verbose_more)) & 1)\n            /* /VERBOSE = MORE */\n            verbo = 2;\n        if ((status = cli$present(&cli_verbose_debug)) & 1) {\n            /* /VERBOSE = DEBUG */\n            verbo = 3;\n        }\n        for (i = 0; i < verbo; i++)\n            *ptr++ = 'v';\n    }\n\n    /*\n    **  Quiet mode.\n    **  (Quiet mode is processed after verbose, because a \"-v\" modifier\n    **  resets \"noisy\" to 1.)\n    */\n    status = cli$present(&cli_quiet);\n    if (status & 1)\n        /* /QUIET */\n        *ptr++ = 'q';\n\n    /*\n    **  Save the VMS file attributes (and all allocated blocks?).\n    */\n    status = cli$present(&cli_vms);\n    if (status & 1) {\n        /* /VMS */\n        *ptr++ = 'V';\n        if ((status = cli$present(&cli_vms_all)) & 1) {\n            /* /VMS = ALL */\n            *ptr++ = 'V';\n        }\n    }\n\n    /*\n    **  Keep the VMS version number as part of the file name when stored.\n    */\n    status = cli$present(&cli_keep_version);\n    if (status & 1)\n        /* /KEEP_VERSION */\n        *ptr++ = 'w';\n\n    /*\n    **  Store symlinks as symlinks.\n    */\n    status = cli$present(&cli_symlinks);\n    if (status & 1)\n        /* /SYMLINKS */\n        *ptr++ = 'y';\n\n    /*\n    **  `Batch' processing: read filenames to archive from stdin\n    **  or the specified file.\n    */\n    status = cli$present(&cli_batch);\n    if (status & 1) {\n        /* /BATCH */\n        status = cli$get_value(&cli_batch, &work_str);\n        if (status & 1) {\n            /* /BATCH = value */\n            work_str.dsc$a_pointer[work_str.dsc$w_length] = '\\0';\n            if ((stdin = freopen(work_str.dsc$a_pointer, \"r\", stdin)) == NULL)\n            {\n                sprintf(errbuf, \"could not open list file: %s\",\n                        work_str.dsc$a_pointer);\n                ziperr(ZE_PARMS, errbuf);\n            }\n        }\n        *ptr++ = '@';\n    }\n\n    /*\n    **  Now copy the final options string to the_cmd_line.\n    */\n    len = ptr - &options[0];\n    if (len > 1) {\n        options[len] = '\\0';\n        x = cmdl_len;\n        cmdl_len += len + 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], options);\n    }\n\n    /*\n    **\n    **  OK.  We've done all the regular options, so check for -b (temporary\n    **  file path), -n (special suffixes), -O (output atchive file),\n    **  -t (exclude before time), -Z (compression method), zipfile,\n    **  files to zip, and exclude list.\n    **\n    */\n    status = cli$present(&cli_temp_path);\n    if (status & 1) {\n        /* /TEMP_PATH = value */\n        status = cli$get_value(&cli_temp_path, &work_str);\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-b\");\n        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    status = cli$present(&cli_output);\n    if (status & 1) {\n        /* /OUTPUT = value */\n        status = cli$get_value(&cli_output, &work_str);\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-O\");\n        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    /*\n    **  Handle \"-db\", \"-dc\", \"-dd\", \"-ds\".\n    */\n#define OPT_DB \"-db\"\n#define OPT_DC \"-dc\"\n#define OPT_DD \"-dd\"\n#define OPT_DG \"-dg\"\n#define OPT_DS \"-ds=\"\n#define OPT_DU \"-du\"\n#define OPT_DV \"-dv\"\n\n    status = cli$present( &cli_display);\n    if (status & 1)\n    {\n        if ((status = cli$present( &cli_display_bytes)) & 1)\n        {\n            /* /DISPLAY = BYTES */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DB)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_DB);\n        }\n\n        if ((status = cli$present( &cli_display_counts)) & 1)\n        {\n            /* /DISPLAY = COUNTS */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DC)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_DC);\n        }\n\n        if ((status = cli$present( &cli_display_dots)) & 1)\n        {\n            /* /DISPLAY = DOTS [= value] */\n            status = cli$get_value( &cli_display_dots, &work_str);\n\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DD)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_DD);\n\n            /* -dd[=value] now -dd -ds=value - 5/8/05 EG */\n            if (work_str.dsc$w_length > 0) {\n                x = cmdl_len;\n                cmdl_len += strlen( OPT_DS);\n                CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n                strcpy( &the_cmd_line[ x], OPT_DS);\n\n                x = cmdl_len;\n                cmdl_len += work_str.dsc$w_length+ 1;\n                CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n                strncpy( &the_cmd_line[ x],\n                 work_str.dsc$a_pointer, work_str.dsc$w_length);\n            }\n        }\n\n        if ((status = cli$present( &cli_display_globaldots)) & 1)\n        {\n            /* /DISPLAY = GLOBALDOTS */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DG)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_DG);\n        }\n\n        if ((status = cli$present( &cli_display_usize)) & 1)\n        {\n            /* /DISPLAY = USIZE */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DU)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_DU);\n        }\n\n        if ((status = cli$present( &cli_display_volume)) & 1)\n        {\n            /* /DISPLAY = VOLUME */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_DV)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_DV);\n        }\n    }\n\n    /*\n    **  Handle \"-la\", \"-lf\", \"-li\".\n    */\n#define OPT_LA \"-la\"\n#define OPT_LF \"-lf\"\n#define OPT_LI \"-li\"\n\n    status = cli$present( &cli_log_file);\n    if (status & 1)\n    {\n        /* /SHOW */\n        if ((status = cli$present( &cli_log_file_append)) & 1)\n        {\n            /* /LOG_FILE = APPEND */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_LA)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_LA);\n        }\n\n        status = cli$present(&cli_log_file_file);\n        if (status & 1) {\n            /* /LOG_FILE = FILE = file */\n            status = cli$get_value(&cli_log_file_file, &work_str);\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_LF)+ 2+ work_str.dsc$w_length;\n            CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n            strcpy(&the_cmd_line[x], OPT_LF);\n            strncpy(&the_cmd_line[x+strlen( OPT_LF)+ 1], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n            the_cmd_line[cmdl_len-1] = '\\0';\n        }\n\n        if ((status = cli$present( &cli_log_file_info)) & 1)\n        {\n            /* /LOG = INFO */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_LI)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_LI);\n        }\n    }\n\n    /*\n    **  Handle \"-s\", \"-sb\", \"-sp\", \"-sv\".\n    */\n#define OPT_S \"-s\"\n#define OPT_SB \"-sb\"\n#define OPT_SP \"-sp\"\n#define OPT_SV \"-sv\"\n\n    status = cli$present( &cli_split);\n    if (status & 1)\n    {\n        status = cli$present( &cli_split_bell);\n        if (status & 1)\n        {\n            /* /SPLIT = BELL */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SB)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SB);\n        }\n\n        status = cli$present( &cli_split_pause);\n        if (status & 1)\n        {\n            /* /SPLIT = PAUSE */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SP)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SP);\n        }\n\n        status = cli$present( &cli_split_size);\n        if (status & 1)\n        {\n            /* /SPLIT = SIZE = size */\n            status = cli$get_value( &cli_split_size, &work_str);\n\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_S)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_S);\n\n            x = cmdl_len;\n            cmdl_len += work_str.dsc$w_length+ 1;\n            strncpy( &the_cmd_line[ x],\n             work_str.dsc$a_pointer, work_str.dsc$w_length);\n        }\n\n        status = cli$present( &cli_split_verbose);\n        if (status & 1)\n        {\n            /* /SPLIT = VERBOSE */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SV)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SV);\n        }\n    }\n\n    /*\n    **  Handle \"-sc\", \"-sd\", \"-sf\", \"-so\".\n    */\n#define OPT_SC \"-sc\"\n#define OPT_SD \"-sd\"\n#define OPT_SF \"-sf\"\n#define OPT_SO \"-so\"\n\n    status = cli$present( &cli_show);\n    if (status & 1)\n    {\n        /* /SHOW */\n        if ((status = cli$present( &cli_show_command)) & 1)\n        {\n            /* /SHOW = COMMAND */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SC)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SC);\n        }\n\n        if ((status = cli$present( &cli_show_debug)) & 1)\n        {\n            /* /SHOW = DEBUG */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SD)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x],  OPT_SD);\n        }\n\n        if ((status = cli$present( &cli_show_files)) & 1)\n        {\n            /* /SHOW = FILES */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SF)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SF);\n        }\n\n        if ((status = cli$present( &cli_show_options)) & 1)\n        {\n            /* /SHOW = OPTIONS */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_SO)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_SO);\n        }\n    }\n\n    /*\n    **  Handle \"-fz\".\n    */\n#define OPT_FZ \"-fz\"\n\n    status = cli$present( &cli_zip64);\n    if (status & 1)\n    {\n        /* /ZIP64 */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_FZ)+ 1;\n        CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x], OPT_FZ);\n    }\n\n    /*\n    **  Handle \"-nw\" and \"-W\".\n    */\n#define OPT_NW \"-nw\"\n#define OPT_W \"-W\"\n\n    status = cli$present( &cli_wildcard);\n    if (status & 1)\n    {\n        if ((status = cli$present( &cli_wildcard_nospan)) & 1)\n        {\n            /* /WILDCARD = NOSPAN */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_W)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_W);\n        }\n    }\n    else if (status == CLI$_NEGATED)\n    {\n        /* /NOWILDCARD */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_NW)+ 1;\n        CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x], OPT_NW);\n    }\n\n    /*\n    **  Handle \"-MM\".\n    */\n#define OPT_MM  \"-MM\"\n\n    status = cli$present( &cli_must_match);\n    if (status & 1)\n    {\n        /* /MUST_MATCH */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_MM)+ 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x], OPT_MM);\n    }\n\n    /*\n    **  UnZip command for archive test.\n    */\n#define OPT_TT \"-TT\"\n\n    status = cli$present(&cli_test);\n    if (status & 1) {\n        /* /TEST */\n        status = cli$present(&cli_test_unzip);\n        if (status & 1) {\n            /* /TEST = UNZIP = value */\n            status = cli$get_value(&cli_test_unzip, &work_str);\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_TT)+ 2+ work_str.dsc$w_length;\n            CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n            strcpy(&the_cmd_line[x], OPT_TT);\n            strncpy(&the_cmd_line[x+strlen( OPT_TT)+ 1], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n            the_cmd_line[cmdl_len-1] = '\\0';\n        }\n    }\n\n    /*\n    **  Handle \"-Z\".\n    */\n#define OPT_ZB \"-Zb\"\n#define OPT_ZD \"-Zd\"\n#define OPT_ZS \"-Zs\"\n\n    status = cli$present( &cli_compression);\n    if (status & 1)\n    {\n        if ((status = cli$present( &cli_compression_b)) & 1)\n        {\n            /* /COMPRESSION = BZIP2 */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_ZB)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_ZB);\n        }\n\n        if ((status = cli$present( &cli_compression_d)) & 1)\n        {\n            /* /COMPRESSION = DEFLATE */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_ZD)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_ZD);\n        }\n\n        if ((status = cli$present( &cli_compression_s)) & 1)\n        {\n            /* /COMPRESSION = STORE */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_ZS)+ 1;\n            CHECK_BUFFER_ALLOCATION( the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_ZS);\n        }\n    }\n\n    /*\n    **  Handle \"-t mmddyyyy\".\n    */\n    status = cli$present(&cli_since);\n    if (status & 1) {\n        /* /SINCE = value */\n        char since_time[9];\n\n        status = get_time(&cli_since, &since_time[0]);\n        if (!(status & 1)) return (status);\n\n        /*\n        **  Now let's add the option \"-t mmddyyyy\" to the new command line.\n        */\n        x = cmdl_len;\n        cmdl_len += (3 + 9);\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-t\");\n        strcpy(&the_cmd_line[x+3], since_time);\n    }\n\n    /*\n    **  Handle \"-tt mmddyyyy\".\n    */\n    status = cli$present(&cli_before);\n    if (status & 1) {\n        /* /BEFORE = value */\n        char before_time[9];\n\n        status = get_time(&cli_before, &before_time[0]);\n        if (!(status & 1)) return (status);\n\n        /*\n        **  Now let's add the option \"-tt mmddyyyy\" to the new command line.\n        */\n        x = cmdl_len;\n        cmdl_len += (4 + 9);\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-tt\");\n        strcpy(&the_cmd_line[x+4], before_time);\n    }\n\n    /*\n    **  Handle \"-n suffix:suffix:...\".  (File types to store only.)\n    */\n    status = cli$present(&cli_store_types);\n    if (status & 1) {\n        /* /STORE_TYPES = value_list */\n        x = cmdl_len;\n        cmdl_len += 3;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-n\");\n\n        status = get_list(&cli_store_types, &foreign_cmdline, ':',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  Handle \"-X\", keep or strip extra fields.\n    */\n#define OPT_X  \"-X\"\n#define OPT_XN  \"-X-\"\n\n    status = cli$present(&cli_extra_fields);\n    if (status & 1) {\n        /* /EXTRA_FIELDS */\n        if ((status = cli$present( &cli_extra_fields_keep)) & 1) {\n            /* /EXTRA_FIELDS = KEEP_EXISTING */\n            x = cmdl_len;\n            cmdl_len += strlen( OPT_XN)+ 1;\n            CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n            strcpy( &the_cmd_line[ x], OPT_XN);\n        }\n    }\n    else if (status == CLI$_NEGATED) {\n        /* /NOEXTRA_FIELDS */\n        x = cmdl_len;\n        cmdl_len += strlen( OPT_X)+ 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy( &the_cmd_line[ x], OPT_X);\n    }\n\n    /*\n    **  Now get the specified zip file name.\n    */\n    status = cli$present(&cli_zipfile);\n    /* zipfile */\n    if (status & 1) {\n        status = cli$get_value(&cli_zipfile, &work_str);\n\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 1;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strncpy(&the_cmd_line[x], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n\n    }\n\n    /*\n    **  Run through the list of input files.\n    */\n    status = cli$present(&cli_infile);\n    if (status & 1) {\n        /* infile_list */\n        status = get_list(&cli_infile, &foreign_cmdline, '\\0',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  List file containing exclude patterns present? (\"-x@exclude.lst\")\n    */\n    status = cli$present(&cli_exlist);\n    if (status & 1) {\n        /* /EXLIST = list */\n        status = cli$get_value(&cli_exlist, &work_str);\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strncpy(&the_cmd_line[x], \"-x@\", 3);\n        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    /*\n    **  Any files to exclude? (\"-x file file\")\n    */\n    status = cli$present(&cli_exclude);\n    if (status & 1) {\n        /* /EXCLUDE = list */\n        x = cmdl_len;\n        cmdl_len += 3;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-x\");\n\n        status = get_list(&cli_exclude, &foreign_cmdline, '\\0',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n    /*\n    **  List file containing include patterns present? (\"-x@exclude.lst\")\n    */\n    status = cli$present(&cli_inlist);\n    if (status & 1) {\n        /* /INLIST = list */\n        status = cli$get_value(&cli_inlist, &work_str);\n        x = cmdl_len;\n        cmdl_len += work_str.dsc$w_length + 4;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strncpy(&the_cmd_line[x], \"-i@\", 3);\n        strncpy(&the_cmd_line[x+3], work_str.dsc$a_pointer,\n                work_str.dsc$w_length);\n        the_cmd_line[cmdl_len-1] = '\\0';\n    }\n\n    /*\n    **  Any files to include? (\"-i file file\")\n    */\n    status = cli$present(&cli_include);\n    if (status & 1) {\n        /* /INCLUDE = list */\n        x = cmdl_len;\n        cmdl_len += 3;\n        CHECK_BUFFER_ALLOCATION(the_cmd_line, cmdl_size, cmdl_len)\n        strcpy(&the_cmd_line[x], \"-i\");\n\n        status = get_list(&cli_exclude, &foreign_cmdline, '\\0',\n                          &the_cmd_line, &cmdl_size, &cmdl_len);\n        if (!(status & 1)) return (status);\n    }\n\n\n    /*\n    **  We have finished collecting the strings for the argv vector,\n    **  release unused space.\n    */\n    if ((the_cmd_line = (char *) realloc(the_cmd_line, cmdl_len)) == NULL)\n        return (SS$_INSFMEM);\n\n    /*\n    **  Now that we've built our new UNIX-like command line, count the\n    **  number of args and build an argv array.\n    */\n    for (new_argc = 0, x = 0; x < cmdl_len; x++)\n        if (the_cmd_line[x] == '\\0')\n            new_argc++;\n\n    /*\n    **  Allocate memory for the new argv[].  The last element of argv[]\n    **  is supposed to be NULL, so allocate enough for new_argc+1.\n    */\n    if ((new_argv = (char **) calloc(new_argc+1, sizeof(char *))) == NULL)\n        return (SS$_INSFMEM);\n\n    /*\n    **  For each option, store the address in new_argv[] and convert the\n    **  separating blanks to nulls so each argv[] string is terminated.\n    */\n    for (ptr = the_cmd_line, x = 0; x < new_argc; x++) {\n        new_argv[x] = ptr;\n        ptr += strlen(ptr) + 1;\n    }\n    new_argv[new_argc] = NULL;\n\n#if defined(TEST) || defined(DEBUG)\n    printf(\"new_argc    = %d\\n\", new_argc);\n    for (x = 0; x < new_argc; x++)\n        printf(\"new_argv[%d] = %s\\n\", x, new_argv[x]);\n#endif /* TEST || DEBUG */\n\n    /* Show the complete UNIX command line, if requested. */\n    if (verbose_command != 0)\n    {\n        printf( \"   UNIX command line args (argc = %d):\\n\", new_argc);\n        for (x = 0; x < new_argc; x++)\n            printf( \"%s\\n\", new_argv[ x]);\n        printf( \"\\n\");\n    }\n\n    /*\n    **  All finished.  Return the new argc and argv[] addresses to Zip.\n    */\n    *argc_p = new_argc;\n    *argv_p = new_argv;\n\n    return (SS$_NORMAL);\n}\n\n\n\f\nstatic unsigned long\nget_list (struct dsc$descriptor_s *qual, struct dsc$descriptor_d *rawtail,\n          int delim, char **p_str, unsigned long *p_size, unsigned long *p_end)\n{\n/*\n**  Routine:    get_list\n**\n**  Function:   This routine runs through a comma-separated CLI list\n**              and copies the strings to the argv buffer.  The\n**              specified separation character is used to separate\n**              the strings in the argv buffer.\n**\n**              All unquoted strings are converted to lower-case.\n**\n**  Formal parameters:\n**\n**      qual    - Address of descriptor for the qualifier name\n**      rawtail - Address of descriptor for the full command line tail\n**      delim   - Character to use to separate the list items\n**      p_str   - Address of pointer pointing to output buffer (argv strings)\n**      p_size  - Address of number containing allocated size for output string\n**      p_end   - Address of number containing used length in output buf\n**\n*/\n\n    register unsigned long status;\n    struct dsc$descriptor_d work_str;\n\n    init_dyndesc(work_str);\n\n    status = cli$present(qual);\n    if (status & 1) {\n\n        unsigned long len, old_len;\n        long ind, sind;\n        int keep_case;\n        char *src, *dst; int x;\n\n        /*\n        **  Just in case the string doesn't exist yet, though it does.\n        */\n        if (*p_str == NULL) {\n            *p_size = ARGBSIZE_UNIT;\n            if ((*p_str = (char *) malloc(*p_size)) == NULL)\n                return (SS$_INSFMEM);\n            len = 0;\n        } else {\n            len = *p_end;\n        }\n\n        while ((status = cli$get_value(qual, &work_str)) & 1) {\n            old_len = len;\n            len += work_str.dsc$w_length + 1;\n            CHECK_BUFFER_ALLOCATION(*p_str, *p_size, len)\n\n            /*\n            **  Look for the filename in the original foreign command\n            **  line to see if it was originally quoted.  If so, then\n            **  don't convert it to lowercase.\n            */\n            keep_case = FALSE;\n            str$find_first_substring(rawtail, &ind, &sind, &work_str);\n            if ((ind > 1 && *(rawtail->dsc$a_pointer + ind - 2) == '\"') ||\n                (ind == 0))\n                keep_case = TRUE;\n\n            /*\n            **  Copy the string to the buffer, converting to lowercase.\n            */\n            src = work_str.dsc$a_pointer;\n            dst = *p_str+old_len;\n            for (x = 0; x < work_str.dsc$w_length; x++) {\n                if (!keep_case && ((*src >= 'A') && (*src <= 'Z')))\n                    *dst++ = *src++ + 32;\n                else\n                    *dst++ = *src++;\n            }\n            if (status == CLI$_COMMA)\n                (*p_str)[len-1] = (char)delim;\n            else\n                (*p_str)[len-1] = '\\0';\n        }\n        *p_end = len;\n    }\n\n    return (SS$_NORMAL);\n\n}\n\n\f\nstatic unsigned long\nget_time (struct dsc$descriptor_s *qual, char *timearg)\n{\n/*\n**  Routine:    get_time\n**\n**  Function:   This routine reads the argument string of the qualifier\n**              \"qual\" that should be a VMS syntax date-time string.  The\n**              date-time string is converted into the standard format\n**              \"mmddyyyy\", specifying an absolute date.  The converted\n**              string is written into the 9 bytes wide buffer \"timearg\".\n**\n**  Formal parameters:\n**\n**      qual    - Address of descriptor for the qualifier name\n**      timearg - Address of a buffer carrying the 8-char time string returned\n**\n*/\n\n    register unsigned long status;\n    struct dsc$descriptor_d time_str;\n    struct quadword {\n        long high;\n        long low;\n    } bintimbuf = {0,0};\n#ifdef __DECC\n#pragma member_alignment save\n#pragma nomember_alignment\n#endif  /* __DECC */\n    struct tim {\n        short year;\n        short month;\n        short day;\n        short hour;\n        short minute;\n        short second;\n        short hundred;\n    } numtimbuf;\n#ifdef __DECC\n#pragma member_alignment restore\n#endif\n\n    init_dyndesc(time_str);\n\n    status = cli$get_value(qual, &time_str);\n    /*\n    **  If a date is given, convert it to 64-bit binary.\n    */\n    if (time_str.dsc$w_length) {\n        status = sys$bintim(&time_str, &bintimbuf);\n        if (!(status & 1)) return (status);\n        str$free1_dx(&time_str);\n    }\n    /*\n    **  Now call $NUMTIM to get the month, day, and year.\n    */\n    status = sys$numtim(&numtimbuf, (bintimbuf.low ? &bintimbuf : NULL));\n    /*\n    **  Write the \"mmddyyyy\" string to the return buffer.\n    */\n    if (!(status & 1)) {\n        *timearg = '\\0';\n    } else {\n        sprintf(timearg, \"%02d%02d%04d\", numtimbuf.month,\n                numtimbuf.day, numtimbuf.year);\n    }\n    return (status);\n}\n\n\f\nstatic unsigned long\ncheck_cli (struct dsc$descriptor_s *qual)\n{\n/*\n**  Routine:    check_cli\n**\n**  Function:   Check to see if a CLD was used to invoke the program.\n**\n**  Formal parameters:\n**\n**      qual    - Address of descriptor for qualifier name to check.\n**\n*/\n    lib$establish(lib$sig_to_ret);      /* Establish condition handler */\n    return (cli$present(qual));         /* Just see if something was given */\n}\n\n\f\n#ifndef TEST\n\nvoid VMSCLI_help(void)  /* VMSCLI version */\n/* Print help (along with license info) to stdout. */\n{\n  extent i;             /* counter for help array */\n\n  /* help array */\n  static char *text[] = {\n\"Zip %s (%s). Usage: (zip :== $ dev:[dir]zip_cli.exe)\",\n\"zip archive[.zip] [list] [/EXCL=(xlist)] /options /modifiers\",\n\"  The default action is to add or replace archive entries from list, except\",\n\"  those in xlist. The include file list may contain the special name \\\"-\\\" to\",\n\"  compress standard input.  If both archive and list are omitted, Zip\",\n\"  compresses stdin to stdout.\",\n\"  Type zip -h for Unix-style flags.\",\n\"  Major options include:\",\n\"    /COPY, /DELETE, /DIFFERENCE, /FILESYNC, /FRESHEN, /GROW, /MOVE, /UPDATE,\",\n\"    /ADJUST_OFFSETS, /FIX_ARCHIVE[={NORMAL|FULL}], /TEST[=UNZIP=cmd], /UNSFX,\",\n\"  Modifiers include:\",\n\"    /BATCH[=list_file], /BEFORE=creation_time, /COMMENTS[={ARCHIVE|FILES}],\",\n\"    /EXCLUDE=(file_list), /EXLIST=file, /INCLUDE=(file_list), /INLIST=file,\",\n\"    /LATEST, /OUTPUT=out_archive, /SINCE=creation_time, /TEMP_PATH=directory,\",\n\"    /LOG_FILE=(FILE=log_file[,APPEND][,INFORMATIONAL]), /MUST_MATCH,\",\n\"    /PATTERN_CASE={BLIND|SENSITIVE}, /NORECURSE|/RECURSE[={PATH|FILENAMES}],\",\n\"    /STORE_TYPES=(type_list),\",\n#if CRYPT\n\"\\\n    /QUIET, /VERBOSE[={MORE|DEBUG}], /[NO]DIRNAMES, /JUNK, /ENCRYPT[=\\\"pwd\\\"],\\\n\",\n#else /* !CRYPT */\n\"    /QUIET, /VERBOSE[={MORE|DEBUG}], /[NO]DIRNAMES, /JUNK,\",\n#endif /* ?CRYPT */\n\"    /COMPRESSION = {BZIP2|DEFLATE|STORE}, /LEVEL=[0-9], /NOVMS|/VMS[=ALL],\",\n\"    /STORE_TYPES=(type_list), /[NO]PRESERVE_CASE[=([NO]ODS{2|5}[,...])],\", \n\"    /[NO]PKZIP, /[NO]KEEP_VERSION, /DOT_VERSION, /TRANSLATE_EOL[={LF|CRLF}],\",\n\"    /DISPLAY=([BYTES][,COUNTS][,DOTS=mb_per_dot][,GLOBALDOTS][,USIZE]\",\n\"    [,VOLUME]), /DESCRIPTORS, /[NO]EXTRA_FIELDS, /ZIP64,\",\n#ifdef S_IFLNK\n\"    /SPLIT = (SIZE=ssize [,BELL] [,PAUSE] [,VERBOSE]), /SYMLINKS\"\n#else /* S_IFLNK */\n\"    /SPLIT = (SIZE=ssize [,BELL] [,PAUSE] [,VERBOSE])\"\n#endif /* S_IFLNK [else] */\n  };\n\n  if (!show_VMSCLI_help) {\n     help();\n     return;\n  }\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)\n  {\n    printf(copyright[i], \"zip\");\n    putchar('\\n');\n  }\n  for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n  {\n    printf(text[i], VERSION, REVDATE);\n    putchar('\\n');\n  }\n} /* end function VMSCLI_help() */\n\n#endif /* !TEST */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/collect_deps.com",
    "content": "$!                                              1 December 2006.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$!    For the product named by P1,\n$!    collect all source file dependencies specified by P3,\n$!    and add P4 prefix.\n$!    Convert absolute dependencies to relative from one level above P5.\n$!    P2 = output file specification.\n$!\n$! MMS /EXTENDED_SYNTAX can't easily pass a macro invocation for P4, so\n$! we remove any internal spaces which might have been added to prevent\n$! immediate evaluation of a macro invocation.\n$!\n$ prefix = f$edit( p4, \"COLLAPSE\")\n$!\n$ dev_lose = f$edit( f$parse( p5, , , \"DEVICE\", \"SYNTAX_ONLY\"), \"UPCASE\")\n$ dir_lose = f$edit( f$parse( p5, , , \"DIRECTORY\", \"SYNTAX_ONLY\"), \"UPCASE\")\n$ suffix = \".VMS]\"\n$ suffix_loc = f$locate( suffix, dir_lose)\n$ if (suffix_loc .lt f$length( dir_lose))\n$ then\n$    dev_dir_lose = dev_lose+ dir_lose- suffix\n$ else\n$    dev_dir_lose = dev_lose+ dir_lose- \"]\"\n$ endif\n$!\n$! For portability, make the output file record format Stream_LF.\n$!\n$ create /fdl = sys$input 'p2'\nRECORD\n        Carriage_Control carriage_return\n        Format stream_lf\n$!\n$ open /read /write /error = end_main deps_out 'p2'\n$ on error then goto loop_main_end\n$!\n$! Include proper-inclusion-check preface.\n$!\n$ incl_macro = \"INCL_\"+ f$parse( p2, , , \"NAME\", \"SYNTAX_ONLY\")\n$ write deps_out \"#\"\n$ write deps_out \"# ''p1' for VMS - MMS (or MMK) Source Dependency File.\"\n$ write deps_out \"#\"\n$ write deps_out \"\"\n$ write deps_out -\n   \"# This description file is included by other description files.  It is\"\n$ write deps_out -\n   \"# not intended to be used alone.  Verify proper inclusion.\"\n$ write deps_out \"\"\n$ write deps_out \".IFDEF ''incl_macro'\"\n$ write deps_out \".ELSE\"\n$ write deps_out -\n   \"$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\"\n$ write deps_out \".ENDIF\"\n$ write deps_out \"\"\n$!\n$! Actual dependencies from individual dependency files.\n$!\n$ loop_main_top:\n$    file = f$search( p3)\n$    if (file .eqs. \"\") then goto loop_main_end\n$!\n$    open /read /error = end_subs deps_in 'file'\n$    loop_subs_top:\n$       read /error = loop_subs_end deps_in line\n$       line_reduced = f$edit( line, \"COMPRESS, TRIM, UPCASE\")\n$       colon = f$locate( \" : \", line_reduced)\n$       d_d_l_loc = f$locate( dev_dir_lose, -\n         f$extract( (colon+ 3), 1000, line_reduced))\n$       if (d_d_l_loc .eq. 0)\n$       then\n$          front = f$extract( 0, (colon+ 3), line_reduced)\n$          back = f$extract( (colon+ 3+ f$length( dev_dir_lose)), -\n            1000, line_reduced)\n$          line = front+ \"[\"+ back\n$       endif\n$       write deps_out \"''prefix'\"+ \"''line'\"\n$    goto loop_subs_top\n$!\n$    loop_subs_end:\n$    close deps_in\n$!\n$ goto loop_main_top\n$!\n$ loop_main_end:\n$ close deps_out\n$!\n$ end_main:\n$!\n"
  },
  {
    "path": "deps/infozip/zip30/vms/cvthelp.tpu",
    "content": "!       TITLE   CVTHELP.TPU\n!       IDENT   01-001\n!\n!++\n! Copyright (c) 1990-2001 Info-ZIP.  All rights reserved.\n!\n! See the accompanying file LICENSE, version 2000-Apr-09 or later\n! (the contents of which are also included in zip.h) for terms of use.\n! If, for some reason, all these files are missing, the Info-ZIP license\n! also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n!\n!++\n!\n!  Program:     CVTHELP.TPU\n!\n!  Author:      Hunter Goatley\n!\n!  Date:        January 12, 1992\n!\n!  Purpose:     Convert .HELP files to RUNOFF .RNH files.  Substitutes\n!               RUNOFF commands for tags imbedded in the .HELP file.\n!\n!  Calling sequence:\n!\n!       $ EDIT/TPU/NOJOURNAL/NODISPLAY/COMMAND=CVTHELP file.HELP\n!\n!  Modified by:\n!\n!       01-001          Hunter Goatley            7-FEB-2001 15:40\n!               Added <NEXT> for qualifier separators.\n!\n!       01-000          Hunter Goatley           12-JAN-1992 15:15\n!               Original version.\n!\n!--\nProcedure eve_convert_help\nLocal   temp\n        ,x\n        ;\n\n   qualifier_level := 0;\n   hg$substitute_topic(current_buffer, \"<MAIN>\", \".indent-3\", \"1\");\n   hg$substitute_topic(current_buffer, \"<QUALIFIER>\", \".sk;.indent-3\", \"\");\n   hg$substitute_topic(current_buffer, \"<TOPIC>\", \".indent-3\", \"2\");\n   hg$substitute_topic(current_buffer, \"<SUBTOPIC>\", \".indent-3\", \"3\");\n   hg$substitute_topic(current_buffer, \"<SUBSUBTOPIC>\", \".indent-3\", \"4\");\n   hg$substitute_comment(current_buffer,\"<QUALIFIERS>\",\".indent-3;2 Qualifiers\");\n   hg$substitute_comment(current_buffer,\"<PARAMETER>\",\".indent-2\");\n   hg$substitute_comment(current_buffer,\"<PTEXT>\",\".lm+3\");\n   hg$substitute_comment(current_buffer,\"<TXETP>\",\".lm-3\");\n   hg$substitute_comment(current_buffer,\"<ETEXT>\",\".lm+4\");\n   hg$substitute_comment(current_buffer,\"<TXETE>\",\".lm-4\");\n   hg$substitute_comment(current_buffer,\"<INIT>\",\".noflags;.lm3;.rm70\");\n   hg$substitute_comment(current_buffer,\"<LITERAL>\",\".lm+4;.literal\");\n   hg$substitute_comment(current_buffer,\"<LARETIL>\",\".end literal;.lm-4\");\n   hg$substitute_comment(current_buffer,\"<LITERAL0>\",\".literal\");\n   hg$substitute_comment(current_buffer,\"<0LARETIL>\",\".end literal\");\n   hg$substitute_comment(current_buffer,\"<DOT1LIST>\",'.list 1,\"o\"');\n   hg$substitute_comment(current_buffer,\"<DOT0LIST>\",'.list 0,\"o\"');\n   hg$substitute_comment(current_buffer,\"<ENTRY>\",\".le\");\n   hg$substitute_comment(current_buffer,\"<TSIL>\",\".end list\");\n   hg$substitute_comment(current_buffer,\"<CENTER>\",\".center\");\n   hg$substitute_comment(current_buffer,\"<FORMAT>\",\".sk;.indent2\");\n   hg$substitute_comment(current_buffer,\"<NOTE>\",\".note\");\n   hg$substitute_comment(current_buffer,\"<ETON>\",\".end note\");\n   hg$substitute_comment(current_buffer, LINE_BEGIN & LINE_END,\".sk\");\n   hg$substitute_comment(current_buffer, LINE_BEGIN & \"|\", \"\");\n   hg$substitute_comment(current_buffer,\"<NEXT>\",\".br\");\n\nEndProcedure;           ! eve_convert_help\n\nProcedure hg$substitute_comment (the_buffer, target, new)\nLocal   temp\n        ,save_pos\n        ,x\n        ;\n  on_error;\n  endon_error;\n\n  save_pos := mark(none);\n  position(beginning_of(the_buffer));\n  loop\n        x := search(target, forward);\n        exitif x = 0;\n        position (x);\n        erase_character(length(x));\n        copy_text(new);\n  endloop;\n\n  position(save_pos);\n\nEndProcedure;           ! hg$substitute_comment\n\nProcedure hg$substitute_topic (the_buffer, target, new, level)\nLocal   temp\n        ,save_pos\n        ,x\n        ;\n  on_error;\n  endon_error;\n\n  save_pos := mark(none);\n  position(beginning_of(the_buffer));\n  loop\n        x := search(target, forward);\n        exitif x = 0;\n        position (x);\n        erase_character(length(x));\n        move_vertical(-1);\n        if (length(current_line) = 0)\n        then copy_text(\"|\");\n        endif;\n        move_vertical(1);\n        copy_text(\".!------------------------------------------------------\");\n        split_line;\n        copy_text(new);\n        move_horizontal(-current_offset);\n        move_vertical(1);\n        if level <> \"\" then\n                copy_text(level + \" \");\n!       else\n!           if qualifier_level = 0\n!           then\n!               copy_text(\"2 Qualifiers\");\n!               split_line; split_line;\n!               copy_text(new); split_line;\n!               qualifier_level := 1;\n!           endif;\n        endif;\n        move_horizontal(-current_offset);\n        move_vertical(1);\n        if length(current_line) = 0\n        then\n            if (target = \"<MAIN>\") OR (target = \"<TOPIC>\")\n                OR (target = \"<SUBTOPIC>\") or (target = \"<SUBSUBTOPIC>\")\n            then copy_text(\".br\");\n            else copy_text(\".sk\");\n            endif;\n        endif;\n  endloop;\n\n  position(save_pos);\n\nEndProcedure;           ! hg$substitute_topic\n\n!===============================================================================\nProcedure tpu$init_procedure\nLocal   temp\n        ,orig_filespec\n        ,f\n        ;\n\n   on_error\n   endon_error;\n\n !Prompt user for information\n\n  orig_filespec := get_info(command_line, \"file_name\");\n  if orig_filespec = \"\"\n  then\n        message(\"No .HELP file given\");\n        quit;\n  endif;\n  f := file_parse(orig_filespec, \".HELP\");              !Add .LIS ending\n\n    ! Create a buffer and window for editing\n\n  main_buf := create_buffer (\"MAIN\",f);\n  set (eob_text, main_buf, \"[End of buffer]\");\n\n  position (beginning_of(main_buf));\n\n  eve_convert_help;\n\n  f := file_parse(orig_filespec,\"\",\"\",NAME);\n\n  write_file (main_buf, f+\".RNH\");\n\n quit;\nEndProcedure;           !TPU$INIT_PROCEDURE\n\ntpu$init_procedure;\n"
  },
  {
    "path": "deps/infozip/zip30/vms/descrip.mms",
    "content": "#                                               23 February 2007.  SMS.\n#\n#    Zip 3.0 for VMS - MMS (or MMK) Description File.\n#\n# Usage:\n#\n#    MMS /DESCRIP = [.VMS]DESCRIP.MMS [/MACRO = (<see_below>)] [target]\n#\n# Note that this description file must be used from the main\n# distribution directory, not from the [.VMS] subdirectory.\n#\n# Optional macros:\n#\n#    CCOPTS=xxx     Compile with CC options xxx.  For example:\n#                   CCOPTS=/ARCH=HOST\n#\n#    DBG=1          Compile with /DEBUG /NOOPTIMIZE.\n#                   Link with /DEBUG /TRACEBACK.\n#                   (Default is /NOTRACEBACK.)\n#\n#    IM=1           Use the old \"IM\" scheme for storing VMS/RMS file\n#                   atributes, instead of the newer \"PK\" scheme.\n#\n#    IZ_BZIP2=dev:[dir]  Add optional BZIP2 support.  The valus of the\n#                        MMS macro IZ_BZIP2 (\"dev:[dir]\", or a suitable\n#                   logical name) tells where to find \"bzlib.h\".  The\n#                   BZIP2 object library (LIBBZ2_NS.OLB) is expected to\n#                   be in a \"[.dest]\" directory under that one\n#                   (\"dev:[dir.ALPHAL]\", for example), or in that\n#                   directory itself.\n#\n#    LARGE=1        Enable large-file (>2GB) support.  Non-VAX only.\n#\n#    LINKOPTS=xxx   Link with LINK options xxx.  For example:\n#                   LINKOPTS=/NOINFO   \n#\n#    LIST=1         Compile with /LIST /SHOW = (ALL, NOMESSAGES).\n#                   Link with /MAP /CROSS_REFERENCE /FULL.\n#\n#    \"LOCAL_ZIP=c_macro_1=value1 [, c_macro_2=value2 [...]]\"\n#                   Compile with these additional C macros defined.\n#\n# VAX-specific optional macros:\n#\n#    VAXC=1         Use the VAX C compiler, assuming \"CC\" runs it.\n#                   (That is, DEC C is not installed, or else DEC C is\n#                   installed, but VAX C is the default.)\n#\n#    FORCE_VAXC=1   Use the VAX C compiler, assuming \"CC /VAXC\" runs it.\n#                   (That is, DEC C is installed, and it is the\n#                   default, but you want VAX C anyway, you fool.)\n#\n#    GNUC=1         Use the GNU C compiler.  (Seriously under-tested.)\n#\n#\n# The default target, ALL, builds the selected product executables and\n# help files.\n#\n# Other targets:\n#\n#    CLEAN      deletes architecture-specific files, but leaves any\n#               individual source dependency files and the help files.\n#\n#    CLEAN_ALL  deletes all generated files, except the main (collected)\n#               source dependency file.\n#\n#    CLEAN_EXE  deletes only the architecture-specific executables. \n#               Handy if all you wish to do is re-link the executables.\n#\n# Example commands:\n#\n# To build the conventional small-file product using the DEC/Compaq/HP C\n# compiler (Note: DESCRIP.MMS is the default description file name.):\n#\n#    MMS /DESCRIP = [.VMS]\n#\n# To get the large-file executables (on a non-VAX system):\n#\n#    MMS /DESCRIP = [.VMS] /MACRO = (LARGE=1)\n#\n# To delete the architecture-specific generated files for this system\n# type:\n#\n#    MMS /DESCRIP = [.VMS] /MACRO = (LARGE=1) CLEAN     ! Large-file.\n# or\n#    MMS /DESCRIP = [.VMS] CLEAN                        ! Small-file.\n#\n# To build a complete small-file product for debug with compiler\n# listings and link maps:\n#\n#    MMS /DESCRIP = [.VMS] CLEAN\n#    MMS /DESCRIP = [.VMS] /MACRO = (DBG=1, LIST=1)\n#\n########################################################################\n\n# Include primary product description file.\n\nINCL_DESCRIP_SRC = 1\n.INCLUDE [.VMS]DESCRIP_SRC.MMS\n\n# Object library names.\n\nLIB_ZIP = [.$(DEST)]ZIP.OLB\nLIB_ZIPCLI = [.$(DEST)]ZIPCLI.OLB\nLIB_ZIPUTILS = [.$(DEST)]ZIPUTILS.OLB\n\n# Help file names.\n\nZIP_HELP = ZIP.HLP ZIP_CLI.HLP\n\n# Message file names.\n\nZIP_MSG_MSG = [.VMS]ZIP_MSG.MSG\nZIP_MSG_EXE = [.$(DEST)]ZIP_MSG.EXE\nZIP_MSG_OBJ = [.$(DEST)]ZIP_MSG.OBJ\n\n\n# TARGETS.\n\n# Default target, ALL.  Build All Zip executables, utility executables,\n# and help files.\n\nALL : $(ZIP) $(ZIP_CLI) $(ZIPUTILS) $(ZIP_HELP) $(ZIP_MSG_EXE)\n\t@ write sys$output \"Done.\"\n\n# CLEAN target.  Delete the [.$(DEST)] directory and everything in it.\n\nCLEAN :\n\tif (f$search( \"[.$(DEST)]*.*\") .nes. \"\") then -\n\t delete /noconfirm [.$(DEST)]*.*;*\n\tif (f$search( \"$(DEST).DIR\") .nes. \"\") then -\n\t set protection = w:d $(DEST).DIR;*\n\tif (f$search( \"$(DEST).DIR\") .nes. \"\") then -\n\t delete /noconfirm $(DEST).DIR;*\n\n# CLEAN_ALL target.  Delete:\n#    The [.$(DEST)] directories and everything in them.\n#    All help-related derived files,\n#    All individual C dependency files.\n# Also mention:\n#    Comprehensive dependency file.\n\nCLEAN_ALL :\n\tif (f$search( \"[.ALPHA*]*.*\") .nes. \"\") then -\n\t delete /noconfirm [.ALPHA*]*.*;*\n\tif (f$search( \"ALPHA*.DIR\", 1) .nes. \"\") then -\n\t set protection = w:d ALPHA*.DIR;*\n\tif (f$search( \"ALPHA*.DIR\", 2) .nes. \"\") then -\n\t delete /noconfirm ALPHA*.DIR;*\n\tif (f$search( \"[.IA64*]*.*\") .nes. \"\") then -\n\t delete /noconfirm [.IA64*]*.*;*\n\tif (f$search( \"IA64*.DIR\", 1) .nes. \"\") then -\n\t set protection = w:d IA64*.DIR;*\n\tif (f$search( \"IA64*.DIR\", 2) .nes. \"\") then -\n\t delete /noconfirm IA64*.DIR;*\n\tif (f$search( \"[.VAX*]*.*\") .nes. \"\") then -\n\t delete /noconfirm [.VAX*]*.*;*\n\tif (f$search( \"VAX*.DIR\", 1) .nes. \"\") then -\n\t set protection = w:d VAX*.DIR;*\n\tif (f$search( \"VAX*.DIR\", 2) .nes. \"\") then -\n\t delete /noconfirm VAX*.DIR;*\n\tif (f$search( \"[.vms]ZIP_CLI.RNH\") .nes. \"\") then -\n\t delete /noconfirm [.vms]ZIP_CLI.RNH;*\n\tif (f$search( \"ZIP_CLI.HLP\") .nes. \"\") then -\n\t delete /noconfirm ZIP_CLI.HLP;*\n\tif (f$search( \"ZIP.HLP\") .nes. \"\") then -\n\t delete /noconfirm ZIP.HLP;*\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete /noconfirm *.MMSD;*\n\tif (f$search( \"[.vms]*.MMSD\") .nes. \"\") then -\n\t delete /noconfirm [.vms]*.MMSD;*\n\t@ write sys$output \"\"\n\t@ write sys$output \"Note:  This procedure will not\"\n\t@ write sys$output \"   DELETE [.VMS]DESCRIP_DEPS.MMS;*\"\n\t@ write sys$output -\n \"You may choose to, but a recent version of MMS (V3.5 or newer?) is\"\n\t@ write sys$output -\n \"needed to regenerate it.  (It may also be recovered from the original\"\n\t@ write sys$output -\n \"distribution kit.)  See [.VMS]DESCRIP_MKDEPS.MMS for instructions on\"\n\t@ write sys$output -\n \"generating [.VMS]DESCRIP_DEPS.MMS.\"\n\t@ write sys$output \"\"\n\t@ write sys$output -\n \"It also does not delete the error message source file:\"\n\t@ write sys$output \"   DELETE [.VMS]ZIP_MSG.MSG;*\"\n\t@ write sys$output -\n \"but it can regenerate it if needed.\"\n\t@ write sys$output \"\"\n\n# CLEAN_EXE target.  Delete the executables in [.$(DEST)].\n\nCLEAN_EXE :\n\tif (f$search( \"[.$(DEST)]*.EXE\") .nes. \"\") then -\n\t delete /noconfirm [.$(DEST)]*.EXE;*\n\n\n# Object library module dependencies.\n\n$(LIB_ZIP) : $(LIB_ZIP)($(MODS_OBJS_LIB_ZIP))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(LIB_ZIPCLI) : $(LIB_ZIPCLI)($(MODS_OBJS_LIB_ZIPCLI))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n$(LIB_ZIPUTILS) : $(LIB_ZIPUTILS)($(MODS_OBJS_LIB_ZIPUTILS))\n\t@ write sys$output \"$(MMS$TARGET) updated.\"\n\n# Module ID options file.\n\nOPT_ID = SYS$DISK:[.VMS]ZIP.OPT\n\n# Default C compile rule.\n\n.C.OBJ :\n\t$(CC) $(CFLAGS) $(CDEFS_UNX) $(MMS$SOURCE)\n\n\n# Normal sources in [.VMS].\n\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.C\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]VMSMUNCH.C\n[.$(DEST)]VMSZIP.OBJ : [.VMS]VMSZIP.C\n\n# Command-line interface files.\n\n[.$(DEST)]CMDLINE.OBJ : [.VMS]CMDLINE.C\n\t$(CC) $(CFLAGS) $(CDEFS_CLI) $(MMS$SOURCE)\n\n[.$(DEST)]ZIPCLI.OBJ : ZIP.C\n\t$(CC) $(CFLAGS) $(CDEFS_CLI) $(MMS$SOURCE)\n\n[.$(DEST)]ZIP_CLI.OBJ : [.VMS]ZIP_CLI.CLD\n\n# Utility variant sources.\n\n[.$(DEST)]CRC32_.OBJ : CRC32.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]CRYPT_.OBJ : CRYPT.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]FILEIO_.OBJ : FILEIO.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]UTIL_.OBJ : UTIL.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]ZIPFILE_.OBJ : ZIPFILE.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n# Utility main sources.\n\n[.$(DEST)]ZIPCLOAK.OBJ : ZIPCLOAK.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]ZIPNOTE.OBJ : ZIPNOTE.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n[.$(DEST)]ZIPSPLIT.OBJ : ZIPSPLIT.C\n\t$(CC) $(CFLAGS) $(CDEFS_UTIL) $(MMS$SOURCE)\n\n# VAX C LINK options file.\n\n.IFDEF OPT_FILE\n$(OPT_FILE) :\n        open /write opt_file_ln  $(OPT_FILE)\n        write opt_file_ln \"SYS$SHARE:VAXCRTL.EXE /SHARE\"\n        close opt_file_ln\n.ENDIF\n\n# Normal Zip executable.\n\n$(ZIP) : [.$(DEST)]ZIP.OBJ $(LIB_ZIP) $(OPT_FILE)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_ZIP) /include = (GLOBALS $(INCL_BZIP2_M)) /library,  -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options\n\n# CLI Zip executable.\n\n$(ZIP_CLI) : [.$(DEST)]ZIPCLI.OBJ \\\n             $(LIB_ZIPCLI) $(OPT_ID) $(OPT_FILE)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_ZIPCLI) /library, -\n\t $(LIB_ZIP) /include = (GLOBALS $(INCL_BZIP2_M)) /library, -\n\t $(LIB_BZIP2_OPTS) -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options\n\n# Utility executables.\n\n[.$(DEST)]ZIPCLOAK.EXE : [.$(DEST)]ZIPCLOAK.OBJ \\\n                         $(LIB_ZIPUTILS) \\\n                         $(OPT_ID) $(OPT_FILE)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_ZIPUTILS) /include = (GLOBALS) /library, -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options\n\n[.$(DEST)]ZIPNOTE.EXE : [.$(DEST)]ZIPNOTE.OBJ \\\n                        $(LIB_ZIPUTILS) \\\n                        $(OPT_ID) $(OPT_FILE)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_ZIPUTILS) /include = (GLOBALS) /library, -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options\n\n[.$(DEST)]ZIPSPLIT.EXE : [.$(DEST)]ZIPSPLIT.OBJ \\\n                         $(LIB_ZIPUTILS) \\\n                         $(OPT_ID) $(OPT_FILE)\n\t$(LINK) $(LINKFLAGS) $(MMS$SOURCE), -\n\t $(LIB_ZIPUTILS) /include = (GLOBALS) /library, -\n\t $(LFLAGS_ARCH) -\n\t $(OPT_ID) /options\n\n# Help files.\n\nZIP.HLP : [.VMS]VMS_ZIP.RNH\n\trunoff /output = $(MMS$TARGET) $(MMS$SOURCE)\n\nZIP_CLI.HLP : [.VMS]ZIP_CLI.HELP [.VMS]CVTHELP.TPU\n\tedit := edit\n\tedit /tpu /nosection /nodisplay /command = [.VMS]CVTHELP.TPU -\n\t $(MMS$SOURCE)\n\trename /noconfirm ZIP_CLI.RNH; [.VMS];\n\tpurge /noconfirm /nolog /keep = 1 [.VMS]ZIP_CLI.RNH\n\trunoff /output = $(MMS$TARGET) [.VMS]ZIP_CLI.RNH\n\n# Message file.\n\n$(ZIP_MSG_EXE) : $(ZIP_MSG_OBJ)\n\tlink /shareable = $(MMS$TARGET) $(ZIP_MSG_OBJ)\n\n$(ZIP_MSG_OBJ) : $(ZIP_MSG_MSG)\n\tmessage /object = $(MMS$TARGET) /nosymbols $(ZIP_MSG_MSG)\n\n$(ZIP_MSG_MSG) : ZIPERR.H [.VMS]STREAM_LF.FDL [.VMS]VMS_MSG_GEN.C\n\t$(CC) /include = [] /object = [.$(DEST)]VMS_MSG_GEN.OBJ -\n\t [.VMS]VMS_MSG_GEN.C \n\t$(LINK) /executable = [.$(DEST)]VMS_MSG_GEN.EXE -\n\t $(LFLAGS_ARCH) -\n\t [.$(DEST)]VMS_MSG_GEN.OBJ\n\tcreate /fdl = [.VMS]STREAM_LF.FDL $(MMS$TARGET)\n\tdefine /user_mode sys$output $(MMS$TARGET)\n\trun [.$(DEST)]VMS_MSG_GEN.EXE\n\tpurge $(MMS$TARGET)\n\tdelete [.$(DEST)]VMS_MSG_GEN.EXE;*, [.$(DEST)]VMS_MSG_GEN.OBJ;*\n\n# Include generated source dependencies.\n\nINCL_DESCRIP_DEPS = 1\n.INCLUDE [.VMS]DESCRIP_DEPS.MMS\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/descrip_deps.mms",
    "content": "#\n# Zip for VMS - MMS (or MMK) Source Dependency File.\n#\n\n# This description file is included by other description files.  It is\n# not intended to be used alone.  Verify proper inclusion.\n\n.IFDEF INCL_DESCRIP_DEPS\n.ELSE\n$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\n.ENDIF\n\n[.$(DEST)]CRC32.OBJ : []CRC32.C\n[.$(DEST)]CRC32.OBJ : []ZIP.H\n[.$(DEST)]CRC32.OBJ : []TAILOR.H\n[.$(DEST)]CRC32.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]CRC32.OBJ : []ZIPERR.H\n[.$(DEST)]CRC32.OBJ : []CRC32.H\n[.$(DEST)]CRC32_.OBJ : []CRC32.C\n[.$(DEST)]CRC32_.OBJ : []ZIP.H\n[.$(DEST)]CRC32_.OBJ : []TAILOR.H\n[.$(DEST)]CRC32_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]CRC32_.OBJ : []ZIPERR.H\n[.$(DEST)]CRC32_.OBJ : []CRC32.H\n[.$(DEST)]CRYPT.OBJ : []CRYPT.C\n[.$(DEST)]CRYPT.OBJ : []ZIP.H\n[.$(DEST)]CRYPT.OBJ : []TAILOR.H\n[.$(DEST)]CRYPT.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]CRYPT.OBJ : []ZIPERR.H\n[.$(DEST)]CRYPT.OBJ : []CRYPT.H\n[.$(DEST)]CRYPT.OBJ : []TTYIO.H\n[.$(DEST)]CRYPT.OBJ : []CRC32.H\n[.$(DEST)]CRYPT_.OBJ : []CRYPT.C\n[.$(DEST)]CRYPT_.OBJ : []ZIP.H\n[.$(DEST)]CRYPT_.OBJ : []TAILOR.H\n[.$(DEST)]CRYPT_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]CRYPT_.OBJ : []ZIPERR.H\n[.$(DEST)]CRYPT_.OBJ : []CRYPT.H\n[.$(DEST)]CRYPT_.OBJ : []TTYIO.H\n[.$(DEST)]CRYPT_.OBJ : []CRC32.H\n[.$(DEST)]DEFLATE.OBJ : []DEFLATE.C\n[.$(DEST)]DEFLATE.OBJ : []ZIP.H\n[.$(DEST)]DEFLATE.OBJ : []TAILOR.H\n[.$(DEST)]DEFLATE.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]DEFLATE.OBJ : []ZIPERR.H\n[.$(DEST)]FILEIO.OBJ : []FILEIO.C\n[.$(DEST)]FILEIO.OBJ : []ZIP.H\n[.$(DEST)]FILEIO.OBJ : []TAILOR.H\n[.$(DEST)]FILEIO.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]FILEIO.OBJ : []ZIPERR.H\n[.$(DEST)]FILEIO.OBJ : []CRC32.H\n[.$(DEST)]FILEIO.OBJ : [.VMS]VMS.H\n[.$(DEST)]FILEIO_.OBJ : []FILEIO.C\n[.$(DEST)]FILEIO_.OBJ : []ZIP.H\n[.$(DEST)]FILEIO_.OBJ : []TAILOR.H\n[.$(DEST)]FILEIO_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]FILEIO_.OBJ : []ZIPERR.H\n[.$(DEST)]FILEIO_.OBJ : []CRC32.H\n[.$(DEST)]FILEIO_.OBJ : [.VMS]VMS.H\n[.$(DEST)]GLOBALS.OBJ : []GLOBALS.C\n[.$(DEST)]GLOBALS.OBJ : []ZIP.H\n[.$(DEST)]GLOBALS.OBJ : []TAILOR.H\n[.$(DEST)]GLOBALS.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]GLOBALS.OBJ : []ZIPERR.H\n[.$(DEST)]TREES.OBJ : []TREES.C\n[.$(DEST)]TREES.OBJ : []ZIP.H\n[.$(DEST)]TREES.OBJ : []TAILOR.H\n[.$(DEST)]TREES.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]TREES.OBJ : []ZIPERR.H\n[.$(DEST)]TTYIO.OBJ : []TTYIO.C\n[.$(DEST)]TTYIO.OBJ : []ZIP.H\n[.$(DEST)]TTYIO.OBJ : []TAILOR.H\n[.$(DEST)]TTYIO.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]TTYIO.OBJ : []ZIPERR.H\n[.$(DEST)]TTYIO.OBJ : []CRYPT.H\n[.$(DEST)]TTYIO.OBJ : []TTYIO.H\n[.$(DEST)]UTIL.OBJ : []UTIL.C\n[.$(DEST)]UTIL.OBJ : []ZIP.H\n[.$(DEST)]UTIL.OBJ : []TAILOR.H\n[.$(DEST)]UTIL.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]UTIL.OBJ : []ZIPERR.H\n[.$(DEST)]UTIL.OBJ : []EBCDIC.H\n[.$(DEST)]UTIL_.OBJ : []UTIL.C\n[.$(DEST)]UTIL_.OBJ : []ZIP.H\n[.$(DEST)]UTIL_.OBJ : []TAILOR.H\n[.$(DEST)]UTIL_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]UTIL_.OBJ : []ZIPERR.H\n[.$(DEST)]UTIL_.OBJ : []EBCDIC.H\n[.$(DEST)]ZBZ2ERR.OBJ : []ZBZ2ERR.C\n[.$(DEST)]ZBZ2ERR.OBJ : []ZIP.H\n[.$(DEST)]ZBZ2ERR.OBJ : []TAILOR.H\n[.$(DEST)]ZBZ2ERR.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZBZ2ERR.OBJ : []ZIPERR.H\n[.$(DEST)]ZIP.OBJ : []ZIP.C\n[.$(DEST)]ZIP.OBJ : []ZIP.H\n[.$(DEST)]ZIP.OBJ : []TAILOR.H\n[.$(DEST)]ZIP.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIP.OBJ : []ZIPERR.H\n[.$(DEST)]ZIP.OBJ : []REVISION.H\n[.$(DEST)]ZIP.OBJ : []CRC32.H\n[.$(DEST)]ZIP.OBJ : []CRYPT.H\n[.$(DEST)]ZIP.OBJ : []TTYIO.H\n[.$(DEST)]ZIP.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]ZIP.OBJ : [.VMS]VMS.H\n[.$(DEST)]ZIPCLI.OBJ : []ZIP.C\n[.$(DEST)]ZIPCLI.OBJ : []ZIP.H\n[.$(DEST)]ZIPCLI.OBJ : []TAILOR.H\n[.$(DEST)]ZIPCLI.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPCLI.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPCLI.OBJ : []REVISION.H\n[.$(DEST)]ZIPCLI.OBJ : []CRC32.H\n[.$(DEST)]ZIPCLI.OBJ : []CRYPT.H\n[.$(DEST)]ZIPCLI.OBJ : []TTYIO.H\n[.$(DEST)]ZIPCLI.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]ZIPCLI.OBJ : [.VMS]VMS.H\n[.$(DEST)]ZIPCLOAK.OBJ : []ZIPCLOAK.C\n[.$(DEST)]ZIPCLOAK.OBJ : []ZIP.H\n[.$(DEST)]ZIPCLOAK.OBJ : []TAILOR.H\n[.$(DEST)]ZIPCLOAK.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPCLOAK.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPCLOAK.OBJ : []REVISION.H\n[.$(DEST)]ZIPCLOAK.OBJ : []CRC32.H\n[.$(DEST)]ZIPCLOAK.OBJ : []CRYPT.H\n[.$(DEST)]ZIPCLOAK.OBJ : []TTYIO.H\n[.$(DEST)]ZIPFILE.OBJ : []ZIPFILE.C\n[.$(DEST)]ZIPFILE.OBJ : []ZIP.H\n[.$(DEST)]ZIPFILE.OBJ : []TAILOR.H\n[.$(DEST)]ZIPFILE.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPFILE.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPFILE.OBJ : []REVISION.H\n[.$(DEST)]ZIPFILE.OBJ : [.VMS]VMS.H\n[.$(DEST)]ZIPFILE.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]ZIPFILE.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]ZIPFILE_.OBJ : []ZIPFILE.C\n[.$(DEST)]ZIPFILE_.OBJ : []ZIP.H\n[.$(DEST)]ZIPFILE_.OBJ : []TAILOR.H\n[.$(DEST)]ZIPFILE_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPFILE_.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPFILE_.OBJ : []REVISION.H\n[.$(DEST)]ZIPFILE_.OBJ : [.VMS]VMS.H\n[.$(DEST)]ZIPFILE_.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]ZIPFILE_.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]ZIPNOTE.OBJ : []ZIPNOTE.C\n[.$(DEST)]ZIPNOTE.OBJ : []ZIP.H\n[.$(DEST)]ZIPNOTE.OBJ : []TAILOR.H\n[.$(DEST)]ZIPNOTE.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPNOTE.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPNOTE.OBJ : []REVISION.H\n[.$(DEST)]ZIPSPLIT.OBJ : []ZIPSPLIT.C\n[.$(DEST)]ZIPSPLIT.OBJ : []ZIP.H\n[.$(DEST)]ZIPSPLIT.OBJ : []TAILOR.H\n[.$(DEST)]ZIPSPLIT.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPSPLIT.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPSPLIT.OBJ : []REVISION.H\n[.$(DEST)]ZIPUP.OBJ : []ZIPUP.C\n[.$(DEST)]ZIPUP.OBJ : []ZIP.H\n[.$(DEST)]ZIPUP.OBJ : []TAILOR.H\n[.$(DEST)]ZIPUP.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]ZIPUP.OBJ : []ZIPERR.H\n[.$(DEST)]ZIPUP.OBJ : []REVISION.H\n[.$(DEST)]ZIPUP.OBJ : []CRC32.H\n[.$(DEST)]ZIPUP.OBJ : []CRYPT.H\n[.$(DEST)]ZIPUP.OBJ : [.VMS]ZIPUP.H\n[.$(DEST)]CMDLINE.OBJ : [.VMS]CMDLINE.C\n[.$(DEST)]CMDLINE.OBJ : []ZIP.H\n[.$(DEST)]CMDLINE.OBJ : []TAILOR.H\n[.$(DEST)]CMDLINE.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]CMDLINE.OBJ : []ZIPERR.H\n[.$(DEST)]CMDLINE.OBJ : []CRYPT.H\n[.$(DEST)]CMDLINE.OBJ : []REVISION.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.C\n[.$(DEST)]VMS.OBJ : []ZIP.H\n[.$(DEST)]VMS.OBJ : []TAILOR.H\n[.$(DEST)]VMS.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]VMS.OBJ : []ZIPERR.H\n[.$(DEST)]VMS.OBJ : [.VMS]ZIPUP.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS_PK.C\n[.$(DEST)]VMS.OBJ : []CRC32.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]VMS.OBJ : [.VMS]VMS_IM.C\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]VMSMUNCH.C\n[.$(DEST)]VMSMUNCH.OBJ : []ZIP.H\n[.$(DEST)]VMSMUNCH.OBJ : []TAILOR.H\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]VMSMUNCH.OBJ : []ZIPERR.H\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]VMSMUNCH.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]VMSZIP.OBJ : [.VMS]VMSZIP.C\n[.$(DEST)]VMSZIP.OBJ : []ZIP.H\n[.$(DEST)]VMSZIP.OBJ : []TAILOR.H\n[.$(DEST)]VMSZIP.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]VMSZIP.OBJ : []ZIPERR.H\n[.$(DEST)]VMSZIP.OBJ : [.VMS]VMSMUNCH.H\n[.$(DEST)]VMSZIP.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.C\n[.$(DEST)]VMS_.OBJ : []ZIP.H\n[.$(DEST)]VMS_.OBJ : []TAILOR.H\n[.$(DEST)]VMS_.OBJ : [.VMS]OSDEP.H\n[.$(DEST)]VMS_.OBJ : []ZIPERR.H\n[.$(DEST)]VMS_.OBJ : [.VMS]ZIPUP.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS_PK.C\n[.$(DEST)]VMS_.OBJ : []CRC32.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMSDEFS.H\n[.$(DEST)]VMS_.OBJ : [.VMS]VMS_IM.C\n"
  },
  {
    "path": "deps/infozip/zip30/vms/descrip_mkdeps.mms",
    "content": "#                                               1 February 2008.  SMS.\n#\n#    Zip 3.0 for VMS - MMS Dependency Description File.\n#\n#    MMS /EXTENDED_SYNTAX description file to generate a C source\n#    dependencies file.  Unsightly errors result when /EXTENDED_SYNTAX\n#    is not specified.  Typical usage:\n#\n#    $ MMS /EXTEND /DESCRIP = [.VMS]DESCRIP_MKDEPS.MMS /SKIP\n#\n# Note that this description file must be used from the main\n# distribution directory, not from the [.VMS] subdirectory.\n#\n# This description file uses these command procedures:\n#\n#    [.VMS]MOD_DEP.COM\n#    [.VMS]COLLECT_DEPS.COM\n#\n# MMK users without MMS will be unable to generate the dependencies file\n# using this description file, however there should be one supplied in\n# the kit.  If this file has been deleted, users in this predicament\n# will need to recover it from the original distribution kit.\n#\n# Note:  This dependency generation scheme assumes that the dependencies\n# do not depend on host architecture type or other such variables. \n# Therefore, no \"#include\" directive in the C source itself should be\n# conditional on such variables.\n#\n# The default target is the comprehensive source dependency file,\n# DEPS_FILE = [.VMS]DESCRIP_DEPS.MMS.\n#\n# Other targets:\n#\n#    CLEAN      deletes the individual source dependency files,\n#               *.MMSD;*, but leaves the comprehensive source dependency\n#               file.\n#\n#    CLEAN_ALL  deletes all source dependency files, including the\n#               individual *.MMSD;* files and the comprehensive file,\n#               DESCRIP_DEPS.MMS.*.\n#\n\n# Required command procedures.\n\nCOMS = [.VMS]MOD_DEP.COM [.VMS]COLLECT_DEPS.COM\n\n# Include the source file lists (among other data).\n\nINCL_DESCRIP_SRC = 1\n.INCLUDE [.VMS]DESCRIP_SRC.MMS\n\n# The ultimate product, a comprehensive dependency list.\n\nDEPS_FILE = [.VMS]DESCRIP_DEPS.MMS \n\n# Detect valid qualifier and/or macro options.\n\n.IF $(FINDSTRING Skip, $(MMSQUALIFIERS)) .eq Skip\nDELETE_MMSD = 1\n.ELSIF NOSKIP\nPURGE_MMSD = 1\n.ELSE\nUNK_MMSD = 1\n.ENDIF\n\n# Dependency suffixes and rules.\n#\n# .FIRST is assumed to be used already, so the MMS qualifier/macro check\n# is included in each rule (one way or another).\n\n.SUFFIXES_BEFORE .C .MMSD\n\n.C.MMSD :\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n\t$(CC) $(CFLAGS_INCL) $(MMS$SOURCE) /NOLIST /NOOBJECT -\n\t /MMS_DEPENDENCIES = (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\n# List of MMS dependency files.\n\n# In case it's not obvious...\n# To extract module name lists from object library module=object lists:\n# 1.  Transform \"module=[.dest]name.OBJ\" into \"module=[.dest] name\".\n# 2.  For [.VMS], add [.VMS] to name.\n# 3.  Delete \"*]\" words.\n#\n# A similar scheme works for executable lists.\n\nMODS_LIB_ZIP_N = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] *, $(MODS_OBJS_LIB_ZIP_N)))\n\nMODS_LIB_ZIP_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_ZIP_V)))\n\nMODS_LIB_ZIPUTILS_N = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] *, $(MODS_OBJS_LIB_ZIPUTILS_N)))\n\nMODS_LIB_ZIPUTILS_N_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_ZIPUTILS_N_V)))\n\nMODS_LIB_ZIPUTILS_U = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] *, $(MODS_OBJS_LIB_ZIPUTILS_U)))\n\nMODS_LIB_ZIPUTILS_U_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_ZIPUTILS_U_V)))\n\nMODS_LIB_ZIPCLI_V = $(FILTER-OUT *], \\\n $(PATSUBST *]*.OBJ, *] [.VMS]*, $(MODS_OBJS_LIB_ZIPCLI_C_V)))\n\nMODS_ZIP = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(ZIP)))\n\nMODS_ZIPUTILS = $(FILTER-OUT *], \\\n $(PATSUBST *]*.EXE, *] *, $(ZIPUTILS)))\n\n# Complete list of C object dependency file names.\n# Note that the CLI Zip main program object file is a special case.\n\nDEPS = $(FOREACH NAME, \\\n $(MODS_LIB_ZIP_N) $(MODS_LIB_ZIP_V) \\\n $(MODS_ZIPUTILS_N) $(MODS_ZIPUTILS_N_V) \\\n $(MODS_LIB_ZIPUTILS_U) $(MODS_LIB_ZIPUTILS_U_V) \\\n $(MODS_LIB_ZIPCLI_V) \\\n $(MODS_ZIP) ZIPCLI $(MODS_ZIPUTILS), \\\n $(NAME).MMSD)\n\n# Default target is the comprehensive dependency list.\n\n$(DEPS_FILE) : $(DEPS) $(COMS)\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete individual .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the individual .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n#\n#       Note that the space in P3, which prevents immediate macro\n#       expansion, is removed by COLLECT_DEPS.COM.\n#\n        @[.VMS]COLLECT_DEPS.COM \"Zip\" -\n         \"$(MMS$TARGET)\" \"[...]*.MMSD\" \"[.$ (DEST)]\" $(MMSDESCRIPTION_FILE)\n        @ write sys$output -\n         \"Created a new dependency file: $(MMS$TARGET)\"\n.IF DELETE_MMSD\n\t@ write sys$output -\n         \"Deleting intermediate .MMSD files...\"\n\tdelete /log *.MMSD;*, [.VMS]*.MMSD;*\n.ELSE\n\t@ write sys$output -\n         \"Purging intermediate .MMSD files...\"\n\tpurge /log *.MMSD, [.VMS]*.MMSD\n.ENDIF\n\n# CLEAN target.  Delete the individual C dependency files.\n\nCLEAN :\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete /log *.MMSD;*\n\tif (f$search( \"[.VMS]*.MMSD\") .nes. \"\") then -\n\t delete /log [.VMS]*.MMSD;*\n\n# CLEAN_ALL target.  Delete:\n#    The individual C dependency files.\n#    The collected source dependency file.\n\nCLEAN_ALL :\n\tif (f$search( \"*.MMSD\") .nes. \"\") then -\n\t delete /log *.MMSD;*\n\tif (f$search( \"[.VMS]*.MMSD\") .nes. \"\") then -\n\t delete /log [.VMS]*.MMSD;*\n\tif (f$search( \"[.VMS]DESCRIP_DEPS.MMS\") .nes. \"\") then -\n\t delete /log [.VMS]DESCRIP_DEPS.MMS;*\n\n# Explicit dependencies and rules for utility variant modules.\n#\n# The extra dependency on the normal dependency file obviates including\n# the /SKIP warning code in each rule here.\n\nCRC32_.MMSD : CRC32.C CRC32.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nCRYPT_.MMSD : CRYPT.C CRYPT.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nFILEIO_.MMSD : FILEIO.C FILEIO.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nUTIL_.MMSD : UTIL.C UTIL.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nZIPFILE_.MMSD : ZIPFILE.C ZIPFILE.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n[.VMS]VMS_.MMSD : [.VMS]VMS.C [.VMS]VMS.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\nZIPCLI.MMSD : ZIP.C ZIP.MMSD\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n# Special case.  No normal (non-CLI) version.\n\n[.VMS]CMDLINE.MMSD : [.VMS]CMDLINE.C\n.IF UNK_MMSD\n\t@ write sys$output -\n \"   /SKIP_INTERMEDIATES is expected on the MMS command line.\"\n\t@ write sys$output -\n \"   For normal behavior (delete .MMSD files), specify \"\"/SKIP\"\".\"\n\t@ write sys$output -\n \"   To retain the .MMSD files, specify \"\"/MACRO = NOSKIP=1\"\".\"\n\t@ exit %x00000004\n.ENDIF\n\t$(CC) $(CFLAGS_INCL) $(CFLAGS_CLI) $(MMS$SOURCE) -\n         /NOLIST /NOOBJECT /MMS_DEPENDENCIES = -\n         (FILE = $(MMS$TARGET), NOSYSTEM_INCLUDE_FILES)\n\t@[.VMS]MOD_DEP.COM $(MMS$TARGET) $(MMS$TARGET_NAME).OBJ $(MMS$TARGET)\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/descrip_src.mms",
    "content": "#                                               23 February 2007.  SMS.\n#\n#    Zip 3.0 for VMS - MMS (or MMK) Source Description File.\n#\n\n# This description file is included by other description files.  It is\n# not intended to be used alone.  Verify proper inclusion.\n\n.IFDEF INCL_DESCRIP_SRC\n.ELSE\n$$$$ THIS DESCRIPTION FILE IS NOT INTENDED TO BE USED THIS WAY.\n.ENDIF\n\n\n# Define MMK architecture macros when using MMS.\n\n.IFDEF __MMK__                  # __MMK__\n.ELSE                           # __MMK__\nALPHA_X_ALPHA = 1\nIA64_X_IA64 = 1\nVAX_X_VAX = 1\n.IFDEF $(MMS$ARCH_NAME)_X_ALPHA     # $(MMS$ARCH_NAME)_X_ALPHA\n__ALPHA__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_ALPHA\n.IFDEF $(MMS$ARCH_NAME)_X_IA64      # $(MMS$ARCH_NAME)_X_IA64\n__IA64__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_IA64\n.IFDEF $(MMS$ARCH_NAME)_X_VAX       # $(MMS$ARCH_NAME)_X_VAX\n__VAX__ = 1\n.ENDIF                              # $(MMS$ARCH_NAME)_X_VAX\n.ENDIF                          # __MMK__\n\n# Combine command-line VAX C compiler macros.\n\n.IFDEF VAXC                     # VAXC\nVAXC_OR_FORCE_VAXC = 1\n.ELSE                           # VAXC\n.IFDEF FORCE_VAXC                   # FORCE_VAXC\nVAXC_OR_FORCE_VAXC = 1\n.ENDIF                              # FORCE_VAXC\n.ENDIF                          # VAXC\n\n# Analyze architecture-related and option macros.\n\n.IFDEF __ALPHA__                # __ALPHA__\nDECC = 1\nDESTM = ALPHA\n.ELSE                           # __ALPHA__\n.IFDEF __IA64__                     # __IA64__\nDECC = 1\nDESTM = IA64\n.ELSE                               # __IA64__\n.IFDEF __VAX__                          # __VAX__\n.IFDEF VAXC_OR_FORCE_VAXC                   # VAXC_OR_FORCE_VAXC\nDESTM = VAXV\n.ELSE                                       # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                                     # GNUC\nCC = GCC\nDESTM = VAXG\n.ELSE                                           # GNUC\nDECC = 1\nDESTM = VAX\n.ENDIF                                          # GNUC\n.ENDIF                                      # VAXC_OR_FORCE_VAXC\n.ELSE                                   # __VAX__\nDESTM = UNK\nUNK_DEST = 1\n.ENDIF                                  # __VAX__\n.ENDIF                              # __IA64__\n.ENDIF                          # __ALPHA__\n\n.IFDEF IM                       # IM\nDESTI = I\n.ELSE                           # IM\nDESTI =\n.ENDIF                          # IM\n\n.IFDEF LARGE                    # LARGE\n.IFDEF __VAX__                      # __VAX__\nDESTL =\n.ELSE                               # __VAX__\nDESTL = L\n.ENDIF                              # __VAX__\n.ELSE                           # LARGE\nDESTL =\n.ENDIF                          # LARGE\n\nDEST = $(DESTM)$(DESTI)$(DESTL)\nSEEK_BZ = $(DESTM)$(DESTL)\n\n# Library module name suffix for XXX_.OBJ with GNU C.\n\n.IFDEF GNUC                     # GNUC\nGCC_ = _\n.ELSE                           # GNUC\nGCC_ =\n.ENDIF                          # GNUC\n\n# Check for option problems.\n\n.IFDEF __VAX__                  # __VAX__\n.IFDEF LARGE                        # LARGE\nLARGE_VAX = 1\n.ENDIF                              # LARGE\n.IFDEF VAXC_OR_FORCE_VAXC           # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                             # GNUC\nVAX_MULTI_CMPL = 1\n.ENDIF                                  # GNUC\n.ENDIF                              # VAXC_OR_FORCE_VAXC\n.ELSE                           # __VAX__\n.IFDEF VAXC_OR_FORCE_VAXC           # VAXC_OR_FORCE_VAXC\nNON_VAX_CMPL = 1\n.ELSE                               # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                             # GNUC\nNON_VAX_CMPL = 1\n.ENDIF                                  # GNUC\n.ENDIF                              # VAXC_OR_FORCE_VAXC\n.ENDIF                          # __VAX__\n\n# Complain if warranted.  Otherwise, show destination directory.\n# Make the destination directory, if necessary.\n\t\t\t\t\n.IFDEF UNK_DEST                 # UNK_DEST\n.FIRST\n\t@ write sys$output -\n \"   Unknown system architecture.\"\n.IFDEF __MMK__                      # __MMK__\n\t@ write sys$output -\n \"   MMK on IA64?  Try adding \"\"/MACRO = __IA64__\"\".\"\n.ELSE                               # __MMK__\n\t@ write sys$output -\n \"   MMS too old?  Try adding \"\"/MACRO = MMS$ARCH_NAME=ALPHA\"\",\"\n\t@ write sys$output -\n \"   or \"\"/MACRO = MMS$ARCH_NAME=IA64\"\", or \"\"/MACRO = MMS$ARCH_NAME=VAX\"\",\"\n\t@ write sys$output -\n \"   as appropriate.  (Or try a newer version of MMS.)\"\n.ENDIF                              # __MMK__\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                           # UNK_DEST\n.IFDEF VAX_MULTI_CMPL               # VAX_MULTI_CMPL\n.FIRST\n\t@ write sys$output -\n \"   Macro \"\"GNUC\"\" is incompatible with \"\"VAXC\"\" or \"\"FORCE_VAXC\"\".\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                               # VAX_MULTI_CMPL\n.IFDEF NON_VAX_CMPL                     # NON_VAX_CMPL\n.FIRST\n\t@ write sys$output -\n \"   Macros \"\"GNUC\"\", \"\"VAXC\"\", and \"\"FORCE_VAXC\"\" are valid only on VAX.\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                                   # NON_VAX_CMPL\n.IFDEF LARGE_VAX                            # LARGE_VAX\n.FIRST\n\t@ write sys$output -\n \"   Macro \"\"LARGE\"\" is invalid on VAX.\"\n\t@ write sys$output \"\"\n\tI_WILL_DIE_NOW.  /$$$$INVALID$$$$\n.ELSE                                       # LARGE_VAX\n.IFDEF IZ_BZIP2                                 # IZ_BZIP2\nCDEFS_BZ = , BZIP2_SUPPORT\nCFLAGS_INCL = /INCLUDE = ([], [.VMS])\nINCL_BZIP2_M = , ZBZ2ERR\nLIB_BZIP2_OPTS = LIB_BZIP2:LIBBZ2_NS.OLB /library,\n.FIRST\n\t@ define incl_bzip2 $(IZ_BZIP2)\n\t@ @[.VMS]FIND_BZIP2_LIB.COM $(IZ_BZIP2) $(SEEK_BZ) -\n\t   LIBBZ2_NS.OLB lib_bzip2\n\t@ write sys$output \"\"\n\t@ if (f$trnlnm( \"lib_bzip2\") .nes. \"\") then -\n\t   write sys$output \"   BZIP2 dir: ''f$trnlnm( \"lib_bzip2\")'\"\n\t@ if (f$trnlnm( \"lib_bzip2\") .eqs. \"\") then -\n\t   write sys$output \"   Can not find BZIP2 object library.\"\n\t@ write sys$output \"\"\n\t@ if (f$trnlnm( \"lib_bzip2\") .eqs. \"\") then -\n\t   I_WILL_DIE_NOW.  /$$$$INVALID$$$$\n\t@ write sys$output \"   Destination: [.$(DEST)]\"\n\t@ write sys$output \"\"\n\tif (f$search( \"$(DEST).DIR;1\") .eqs. \"\") then -\n\t create /directory [.$(DEST)]\n.ELSE                                           # IZ_BZIP2\nCDEFS_BZ =\nCFLAGS_INCL = /include = []\nINCL_BZIP2_M = , ZBZ2ERR\nLIB_BZIP2_OPTS =\n.FIRST\n\t@ write sys$output \"   Destination: [.$(DEST)]\"\n\t@ write sys$output \"\"\n\tif (f$search( \"$(DEST).DIR;1\") .eqs. \"\") then -\n\t create /directory [.$(DEST)]\n.ENDIF                                          # IZ_BZIP2\n.ENDIF                                      # LARGE_VAX\n.ENDIF                                  # NON_VAX_CMPL\n.ENDIF                              # VAX_MULTI_CMPL\n.ENDIF                          # UNK_DEST\n\n# DBG options.\n\n.IFDEF DBG                      # DBG\nCFLAGS_DBG = /debug /nooptimize\nLINKFLAGS_DBG = /debug /traceback\n.ELSE                           # DBG\nCFLAGS_DBG =\nLINKFLAGS_DBG = /notraceback\n.ENDIF                          # DBG\n\n# \"IM\" scheme for storing VMS/RMS file attributes.\n\n.IFDEF IM                       # IM\nCDEFS_IM = , VMS_IM_EXTRA\n.ELSE                           # IM\nCDEFS_IM =\n.ENDIF                          # IM\n\n# Large-file options.\n\n.IFDEF LARGE                    # LARGE\nCDEFS_LARGE = , LARGE_FILE_SUPPORT\n.ELSE                           # LARGE\nCDEFS_LARGE =\n.ENDIF                          # LARGE\n\n# C compiler defines.\n\n.IFDEF LOCAL_ZIP\nC_LOCAL_ZIP = , $(LOCAL_ZIP)\n.ELSE\nC_LOCAL_ZIP =\n.ENDIF\n\nCDEFS = VMS $(CDEFS_BZ) $(CDEFS_IM) $(CDEFS_LARGE) $(C_LOCAL_ZIP)\n\nCDEFS_UNX = /define = ($(CDEFS))\n\nCDEFS_CLI = /define = ($(CDEFS), VMSCLI)\n\nCDEFS_UTIL = /define = ($(CDEFS), UTIL)\n\n# Other C compiler options.\n\n.IFDEF DECC                             # DECC\nCFLAGS_ARCH = /decc /prefix = (all)\n.ELSE                                   # DECC\n.IFDEF FORCE_VAXC                           # FORCE_VAXC\nCFLAGS_ARCH = /vaxc\n.IFDEF VAXC                                     # VAXC\n.ELSE                                           # VAXC\nVAXC = 1\n.ENDIF                                          # VAXC\n.ELSE                                       # FORCE_VAXC\nCFLAGS_ARCH =\n.ENDIF                                      # FORCE_VAXC\n.ENDIF                                  # DECC\n\n.IFDEF VAXC_OR_FORCE_VAXC               # VAXC_OR_FORCE_VAXC\nOPT_FILE = [.$(DEST)]VAXCSHR.OPT\nLFLAGS_ARCH = $(OPT_FILE) /options, \n.ELSE                                   # VAXC_OR_FORCE_VAXC\n.IFDEF GNUC                                 # GNUC\nOPT_FILE = [.$(DEST)]VAXCSHR.OPT\nLFLAGS_GNU = GNU_CC:[000000]GCCLIB.OLB /LIBRARY\nLFLAGS_ARCH = $(LFLAGS_GNU), SYS$DISK:$(OPT_FILE) /options, \n.ELSE                                       # GNUC\nOPT_FILE =\nLFLAGS_ARCH =\n.ENDIF                                      # GNUC\n.ENDIF                                  # VAXC_OR_FORCE_VAXC\n\n# LIST options.\n\n.IFDEF LIST                     # LIST\n.IFDEF DECC                         # DECC\nCFLAGS_LIST = /list = $*.LIS /show = (all, nomessages)\n.ELSE                               # DECC\nCFLAGS_LIST = /list = $*.LIS /show = (all)\n.ENDIF                              # DECC\nLINKFLAGS_LIST = /map = $*.MAP /cross_reference /full\n.ELSE                           # LIST\nCFLAGS_LIST =\nLINKFLAGS_LIST =\n.ENDIF                          # LIST\n\n# Common CFLAGS and LINKFLAGS.\n\nCFLAGS = \\\n $(CFLAGS_ARCH) $(CFLAGS_DBG) $(CFLAGS_INCL) $(CFLAGS_LIST) $(CCOPTS) \\\n /object = $(MMS$TARGET)\n\nLINKFLAGS = \\\n $(LINKFLAGS_DBG) $(LINKFLAGS_LIST) $(LINKOPTS) \\\n /executable = $(MMS$TARGET)\n\n# Object library module=object lists.\n\n#    Primary object library, [].\n\nMODS_OBJS_LIB_ZIP_N = \\\n CRC32=[.$(DEST)]CRC32.OBJ \\\n CRYPT=[.$(DEST)]CRYPT.OBJ \\\n DEFLATE=[.$(DEST)]DEFLATE.OBJ \\\n FILEIO=[.$(DEST)]FILEIO.OBJ \\\n GLOBALS=[.$(DEST)]GLOBALS.OBJ \\\n TREES=[.$(DEST)]TREES.OBJ \\\n TTYIO=[.$(DEST)]TTYIO.OBJ \\\n UTIL=[.$(DEST)]UTIL.OBJ \\\n ZBZ2ERR=[.$(DEST)]ZBZ2ERR.OBJ \\\n ZIPFILE=[.$(DEST)]ZIPFILE.OBJ \\\n ZIPUP=[.$(DEST)]ZIPUP.OBJ\n\n#    Primary object library, [.VMS].\n                    \nMODS_OBJS_LIB_ZIP_V = \\\n VMS=[.$(DEST)]VMS.OBJ \\\n VMSMUNCH=[.$(DEST)]VMSMUNCH.OBJ \\\n VMSZIP=[.$(DEST)]VMSZIP.OBJ\n\nMODS_OBJS_LIB_ZIP = $(MODS_OBJS_LIB_ZIP_N) $(MODS_OBJS_LIB_ZIP_V)\n\n#    Utility object library, normal, [].\n\nMODS_OBJS_LIB_ZIPUTILS_N = \\\n GLOBALS=[.$(DEST)]GLOBALS.OBJ \\\n TTYIO=[.$(DEST)]TTYIO.OBJ\n\n#    Utility object library, variant, [].\n\nMODS_OBJS_LIB_ZIPUTILS_U = \\\n CRC32$(GCC_)=[.$(DEST)]CRC32_.OBJ \\\n CRYPT$(GCC_)=[.$(DEST)]CRYPT_.OBJ \\\n FILEIO$(GCC_)=[.$(DEST)]FILEIO_.OBJ \\\n UTIL$(GCC_)=[.$(DEST)]UTIL_.OBJ \\\n ZIPFILE$(GCC_)=[.$(DEST)]ZIPFILE_.OBJ\n\n#    Utility object library, normal, [.VMS].\n\nMODS_OBJS_LIB_ZIPUTILS_N_V = \\\n VMSMUNCH=[.$(DEST)]VMSMUNCH.OBJ\n\n#    Utility object library, variant, [.VMS].\n\nMODS_OBJS_LIB_ZIPUTILS_U_V = \\\n VMS$(GCC_)=[.$(DEST)]VMS_.OBJ\n\nMODS_OBJS_LIB_ZIPUTILS = $(MODS_OBJS_LIB_ZIPUTILS_N) \\\n $(MODS_OBJS_LIB_ZIPUTILS_U) \\\n $(MODS_OBJS_LIB_ZIPUTILS_N_V) \\\n $(MODS_OBJS_LIB_ZIPUTILS_U_V) \\\n\n#    CLI object library, [.VMS].\n\nMODS_OBJS_LIB_ZIPCLI_C_V = \\\n CMDLINE=[.$(DEST)]CMDLINE.OBJ\n\nMODS_OBJS_LIB_ZIPCLI_CLD_V = \\\n ZIP_CLITABLE=[.$(DEST)]ZIP_CLI.OBJ\n\nMODS_OBJS_LIB_ZIPCLI = \\\n $(MODS_OBJS_LIB_ZIPCLI_C_V) \\\n $(MODS_OBJS_LIB_ZIPCLI_CLD_V)\n\n# Executables.\n\nZIP = [.$(DEST)]ZIP.EXE\n\nZIP_CLI = [.$(DEST)]ZIP_CLI.EXE\n\nZIPUTILS = \\\n [.$(DEST)]ZIPCLOAK.EXE \\\n [.$(DEST)]ZIPNOTE.EXE \\\n [.$(DEST)]ZIPSPLIT.EXE\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/find_bzip2_lib.com",
    "content": "$!                                              28 December 2006.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$! Find the BZIP2 object library under P1, starting in the [.'P2']\n$! destination directory.  (We assume, initially, that the BZIP2\n$! directory has a destination directory structure like ours.)\n$!\n$! Set the P4 logical name to the directory where it was found.\n$! P5 and P6 may be used for qualifiers on the DEFINE command.\n$!\n$ bz_orig = p1\n$ dest = p2\n$ libbz2 = p3\n$!\n$! Remove any trailing colon, to allow logical name translation.\n$!\n$ bz_dev_dir = \"\"\n$ bz_base = bz_orig\n$ if (f$extract( (f$length( bz_base)- 1), 1, bz_base) .eqs. \":\")\n$ then\n$     bz_base = bz_base- \":\"\n$ endif\n$!\n$ bz_base_eqv = f$trnlnm( bz_base)\n$ if (bz_base_eqv .nes. \"\")\n$ then\n$     bz_orig = bz_base_eqv\n$     bz_base = bz_base_eqv\n$ endif\n$ bz_base = bz_base- \"]\"\n$!\n$! Candidate 1 = the actual analogue destination directory.\n$!\n$ bz_dev_dir_cand = bz_base+ \".\"+ dest+ \"]\"\n$ lib_cand = bz_dev_dir_cand+ libbz2\n$ if (f$search( lib_cand) .nes. \"\")\n$ then\n$     bz_dev_dir = bz_dev_dir_cand\n$ else\n$!\n$!     Candidate 2 = the actual analogue destination directory + \"L\".\n$!\n$     bz_dev_dir_cand = bz_base+ \".\"+ dest+ \"L]\"\n$     lib_cand = bz_dev_dir_cand+ libbz2\n$     if (f$search( lib_cand) .nes. \"\")\n$     then\n$         bz_dev_dir = bz_dev_dir_cand\n$     else\n$!\n$!         Candidate 3 = the actual user-specified directory.\n$!\n$         bz_dev_dir_cand = bz_orig\n$         lib_cand = bz_dev_dir_cand+ libbz2\n$         if (f$search( lib_cand) .nes. \"\")\n$         then\n$             bz_dev_dir = bz_dev_dir_cand\n$         endif\n$     endif\n$ endif\n$!\n$ if (bz_dev_dir .nes. \"\")\n$ then\n$     if (p4 .eqs. \"\")\n$     then\n$         write sys$output bz_dev_dir\n$     else\n$         define 'p5' 'p4' 'bz_dev_dir' 'p6'\n$     endif\n$ endif\n$!\n"
  },
  {
    "path": "deps/infozip/zip30/vms/hlp_lib_next.com",
    "content": "$!                                              21 November 2004.  SMS.\n$!\n$!    HLP_LIB_NEXT.COM\n$!\n$!    Find the next available HLP$LIBRARY[_*] logical name.\n$!\n$ base = \"HLP$LIBRARY\"\n$ candidate = base\n$ i = 0\n$!\n$ loop_top:\n$    if (i .gt. 0) then candidate = base+ \"_\"+ f$string( i)\n$    i = i+ 1\n$    if (f$trnlnm( candidate) .nes. \"\") then goto loop_top\n$!\n$ write sys$output candidate\n$!\n"
  },
  {
    "path": "deps/infozip/zip30/vms/install_vms.txt",
    "content": "\n  VMS (OpenVMS):\n\n  Building:\n\n     On VMS, two build methods are provided: a command procedure, and\n     description files for MMS or MMK.  Both methods must be run from\n     the main directory, not the [.VMS] subdirectory.\n\n     A simple build using the command procedure looks like this:\n          @ [.VMS]BUILD_ZIP.COM\n\n     A simple build using MMS or MMK looks like this:\n          MMS /DESCRIP = [.VMS]DESCRIP.MMS      ! Or, with MMK, ...\n          MMK /DESCRIP = [.VMS]DESCRIP.MMS\n\n     Various options for each build method are explained in comments in\n     the main builder file, either BUILD_ZIP.COM or DESCRIP.MMS.\n\n      Note that on non-VAX systems with VMS V7.2 or later (and with a\n      sufficiently new C compiler), Zip 3.0 can support files (both data\n      files and Zip archives) larger than 2GB.  For the greatest\n      compatibility with previous Zip versions, the builders by default\n      create old-style small-file programs.  The user must specify the\n      appropriate builder command-line option to create\n      large-file-capable programs.\n\n     Here are some more complex build examples:\n\n     o Build with the large-file option enabled (non-VAX only):\n\n          @ [.VMS]BUILD_ZIP LARGE\n       or:\n          MMS /DESC = [.VMS] /MACRO = LARGE=1\n\n     o Re-link the executables (small-file and large-file):\n\n          @ [.VMS]BUILD_ZIP LINK\n          @ [.VMS]BUILD_ZIP LARGE LINK\n       or\n          MMK /DESC = [.VMS] CLEAN_EXE  ! Deletes existing executables.\n          MMK /DESC = [.VMS]            ! Builds new executables.\n          MMK /DESC = [.VMS] /MACRO = LARGE=1 CLEAN_EXE\n          MMK /DESC = [.VMS] /MACRO = LARGE=1\n\n     o Build a large-file product from scratch, for debug, getting\n       compiler listings and link maps:\n\n          MMS /DESC = [.VMS] CLEAN\n          MMS /DESC = [.VMS] /MACRO = (DBG=1, LARGE=1. LIST=1)\n\n     On VAX, the builders attempt to cope with the various available C\n     compilers, DEC/Compaq/HP C, VAX C, or GNU C.  If DEC/Compaq/HP C is\n     not available or not desired, comments in the relevant builder file\n     explain the command-line options used to select a different\n     compiler.\n\n     By default, Zip uses the \"deflate\" compression method.  To add\n     support for the optional \"bzip2\" compression method, first obtain\n     and build the bzip2 software (http://www.bzip.org/ or, for a more\n     VMS-friendly kit, http://antinode.info/dec/sw/bzip2.html).  Then,\n     define the macro IZ_BZIP2 on the BUILD_ZIP.COM or MMS/MMK command\n     line to specify the directory where the bzip2 files may be found.\n     For example:\n\n          @ [.VMS]BUILD_ZIP LARGE -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_3C_VMS]\n       or:\n          MMS /DESC = [.VMS] /MACRO = (LARGE=1, -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_3C_VMS])\n\n     Note that historically, Zip has been built with the default\n     compiler option, /NAMES = UPPERCASE, while bzip2 is normally built\n     with /NAMES = AS_IS, to avoid name collisions.  With modern\n     compilers, the \"#pragma names\" directives in [.VMS]BZLIB.H will\n     handle these differences without user intervention.  An old\n     compiler (for example, DEC C V4.0-000) will emit complaints\n     %CC-I-UNKNOWNPRAGMA, and will mishandle the bzip2 library function\n     names, which will cause the link to fail.  To solve this problem,\n     either build the bzip2 BZ_NO_STDIO object library with /NAMES =\n     UPPERCASE, or else build Zip with /NAMES = AS_IS.  For example:\n\n          @ [.VMS]BUILD_ZIP LARGE \"CCOPTS=/NAMES=AS_IS\" -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_3C_VMS]\n       or:\n          MMS /DESC = [.VMS] /MACRO = (LARGE=1, \"CCOPTS=/NAMES=AS_IS\", -\n           IZ_BZIP2=SYS$SYSDEVICE:[UTILITY.SOURCE.BZIP2.BZIP2-1_0_3C_VMS])\n\n     System-architecture-specific files (like objects and executables)\n     are placed in separate directories, such as [.ALPHA], [.IA64], or\n     [.VAX].  Large-file products get their own directories, [.ALPHAL]\n     or [.IA64L].  On VAX, VAX C products are placed in [.VAXV], GNU C\n     products in [.VAXG].  Each product builder announces what the\n     destination directory will be when it is run.\n\n     Common files, such as the help libraries (ZIP.HLP for the default\n     UNIX-like command-line interface, ZIP_CLI.HLP for the VMS-like\n     command-line interface), are placed in the main directory.  With a\n     mixed-architecture VMS cluster, the same main directory on a shared\n     disk may be used by all system types.  (Using the NOHELP option\n     with BUILD_ZIP.COM can keep it from making the same help files\n     repeatedly.)  Building the help files is detailed below.\n\n  Completing installation:\n\n     To complete the installation, the executables may be left in place,\n     or moved (or copied) to a convenient place.  While other methods\n     (like DCL$PATH) exist, most users define symbols to make the Zip\n     executables available as foreign commands.  These symbol definitions\n     may be placed in a user's SYS$LOGIN:LOGIN.COM, or in a more central\n     location, like SYS$MANAGER:SYLOGIN.COM.  Typical symbol definitions\n     might look like these:\n\n           ZIP :== $ dev:[dir]ZIP.EXE            ! UNIX-like command line.\n   or:\n           ZIP :== $ dev:[dir]ZIP_CLI.EXE        ! VMS-like command line.\n\n     On a non-VAX system, different symbols could be defined for the\n     small-file and large-file programs.  For example:\n\n           ZIPS  :== $ dev:[dir.ALPHA]ZIP.EXE    ! ZIPS = small-file Zip.\n           ZIP*L :== $ dev:[dir.ALPHAL]ZIP.EXE   ! ZIP[L] = large-file Zip.\n\n     The builders create help text files, ZIP.HLP and ZIP_CLI.HLP.\n     These may be incorporated into an existing help library, or a separate\n     Zip help library may be created using commands like these, using\n     either ZIP.HLP (as shown) or ZIP_CLI.HLP:\n\n           $ LIBRARY /HELP dev:[dir]existing_library.HLB ZIP.HLP\n\n           $ LIBRARY /CREATE /HELP ZIP.HLB ZIP.HLP\n\n     Zip help may then be accessed from a separate Zip help library\n     using a command like:\n\n           $ HELP /LIBRARY = device:[directory]ZIP.HLB\n\n     For greater ease, the user (or system manager) may define a\n     HLP$LIBRARY logical name to allow the HELP utility to find the Zip\n     help library automatically.  See HELP HELP /USERLIBRARY for more\n     details.   The command procedure HLP_LIB_NEXT.COM may be used to\n     determine the next available HLP$LIBRARY logical name, and could be\n     adapted to define a HLP$LIBRARY logical name for a Zip help library.\n\n     The builders also create VMS message files, ZIP_MSG.EXE, in the\n     destination directory with the program executables.  A user may\n     gain DCL access to the Zip error messages using a command like:\n\n           $ SET MESSAGE device:[directory]ZIP_MSG.EXE\n\n     For system-wide access, the system manager may move or copy this\n     file to SYS$MESSAGE, although this could cause some confusion if\n     multiple versions of Zip are used on the system, and their error\n     message source files differ.\n\n     Some further information may be found in the files\n     [.VMS]00README.TXT and [.VMS]00BINARY.VMS, though much of what's\n     there is now obsolete.\n"
  },
  {
    "path": "deps/infozip/zip30/vms/mod_dep.com",
    "content": "$!                                              3 March 2005.  SMS.\n$!\n$! Info-ZIP VMS accessory procedure.\n$!\n$!    Modify a dependencies file (P1), changing the object file name to\n$!    P2.\n$!    P3 = output file specification.\n$!\n$!\n$ prefix = f$edit( p3, \"COLLAPSE\")\n$!\n$! Strip any device:[directory] from P2.\n$!\n$ obj_name = f$parse( P2, , , \"NAME\", \"SYNTAX_ONLY\")+ -\n   f$parse( P2, , , \"TYPE\", \"SYNTAX_ONLY\")\n$!\n$ open /read /error = end_main deps_in 'p1'\n$ open /write /error = end_main deps_out 'p3'\n$ on error then goto loop_main_end\n$ loop_main_top:\n$     read /error = loop_main_end deps_in line\n$     line_reduced = f$edit( line, \"COMPRESS, TRIM\")\n$     colon = f$locate( \" : \", line_reduced)\n$     line = obj_name+ f$extract( colon, 2000, line)\n$     write deps_out \"''line'\"\n$ goto loop_main_top\n$!\n$ loop_main_end:\n$ close deps_in\n$ close deps_out\n$!\n$ end_main:\n$!\n"
  },
  {
    "path": "deps/infozip/zip30/vms/osdep.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef VMS\n#  define VMS 1\n#endif\n\n#if (defined(__VMS_VER) && !defined(__CRTL_VER))\n#  define __CRTL_VER __VMS_VER\n#endif\n\n#if (defined(__VMS_VERSION) && !defined(VMS_VERSION))\n#  define VMS_VERSION __VMS_VERSION\n#endif\n\n#if !(defined(__DECC) || defined(__DECCXX) || defined(__GNUC__))\n     /* VAX C does not properly support the void keyword. (Only functions\n        are allowed to have the type \"void\".)  */\n#  ifndef NO_TYPEDEF_VOID\n#    define NO_TYPEDEF_VOID\n#  endif\n#  define NO_FCNTL_H        /* VAXC does not supply fcntl.h. */\n#endif /* VAX C */\n\n#define USE_CASE_MAP\n#define PROCNAME(n) \\\n (((action == ADD) || (action == UPDATE) || (action == FRESHEN)) ? \\\n wild(n) : procname(n, filter_match_case))\n\n/* 2004-11-09 SMS.\n   Large file support.\n*/\n#ifdef LARGE_FILE_SUPPORT\n\n#  define _LARGEFILE                   /* Define the pertinent macro. */\n\n/* LARGE_FILE_SUPPORT implies ZIP64_SUPPORT,\n   unless explicitly disabled by NO_ZIP64_SUPPORT.\n*/\n#  ifdef NO_ZIP64_SUPPORT\n#    ifdef ZIP64_SUPPORT\n#      undef ZIP64_SUPPORT\n#    endif /* def ZIP64_SUPPORT */\n#  else /* def NO_ZIP64_SUPPORT */\n#    ifndef ZIP64_SUPPORT\n#      define ZIP64_SUPPORT\n#    endif /* ndef ZIP64_SUPPORT */\n#  endif /* def NO_ZIP64_SUPPORT */\n\n#  define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n\n#else /* def LARGE_FILE_SUPPORT */\n\n#  define ZOFF_T_FORMAT_SIZE_PREFIX \"l\"\n\n#endif /* def LARGE_FILE_SUPPORT */\n\n/* Need _LARGEFILE for types.h. */\n\n#include <types.h>\n\n#ifdef __GNUC__\n#include <sys/types.h>\n#endif /* def __GNUC__ */\n\n/* Need types.h for off_t. */\n\n#ifdef LARGE_FILE_SUPPORT\n   typedef off_t zoff_t;\n   typedef unsigned long long uzoff_t;\n#else /* def LARGE_FILE_SUPPORT */\n   typedef long zoff_t;\n   typedef unsigned long uzoff_t;\n#endif /* def LARGE_FILE_SUPPORT */\n\n#include <stat.h>\n\ntypedef struct stat z_stat;\n\n#include <unixio.h>\n\n#if defined(__GNUC__) && !defined(ZCRYPT_INTERNAL)\n#  include <unixlib.h>          /* ctermid() declaration needed in ttyio.c */\n#endif\n#ifdef ZCRYPT_INTERNAL\n#  include <unixlib.h>          /* getpid() declaration for srand seed */\n#endif\n\n#if defined(_MBCS)\n#  undef _MBCS                 /* Zip on VMS does not support MBCS */\n#endif\n\n/* VMS is run on little-endian processors with 4-byte ints:\n * enable the optimized CRC-32 code */\n#ifdef IZ_CRC_BE_OPTIMIZ\n#  undef IZ_CRC_BE_OPTIMIZ\n#endif\n#if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ)\n#  define IZ_CRC_LE_OPTIMIZ\n#endif\n#if !defined(IZ_CRCOPTIM_UNFOLDTBL) && !defined(NO_CRC_OPTIMIZ)\n#  define IZ_CRCOPTIM_UNFOLDTBL\n#endif\n\n#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)\n#  if (defined(__CRTL_VER) && (__CRTL_VER >= 70000000))\n#    define USE_EF_UT_TIME\n#  endif\n#endif\n\n#if defined(VMS_PK_EXTRA) && defined(VMS_IM_EXTRA)\n#  undef VMS_IM_EXTRA                 /* PK style takes precedence */\n#endif\n#if !defined(VMS_PK_EXTRA) && !defined(VMS_IM_EXTRA)\n#  define VMS_PK_EXTRA 1              /* PK style VMS support is default */\n#endif\n\n/* 2007-02-22 SMS.\n * <unistd.h> is needed for symbolic link functions, so use it when the\n * symbolic link criteria are met.\n */\n#if defined(__VAX) || __CRTL_VER < 70301000\n#  define NO_UNISTD_H\n#  define NO_SYMLINKS\n#endif /* defined(__VAX) || __CRTL_VER < 70301000 */\n\n/* 2007-02-22 SMS.  Use delete() when unlink() is not available. */\n#if defined(NO_UNISTD_H) || (__CRTL_VER < 70000000)\n#  define unlink delete\n#endif /* defined(NO_UNISTD_H) || __CRTL_VER < 70000000) */\n\n#define SSTAT vms_stat\n#define EXIT(exit_code) vms_exit(exit_code)\n#define RETURN(exit_code) return (vms_exit(exit_code), 1)\n\n\n#ifdef __DECC\n\n/* File open callback ID values. */\n\n#  define FOPM_ID 1\n#  define FOPR_ID 2\n#  define FOPW_ID 3\n\n/* File open callback ID storage. */\n\nextern int fopm_id;\nextern int fopr_id;\nextern int fopw_id;\n\n/* File open callback ID function. */\n\nextern int acc_cb();\n\n/* Option macros for zfopen().\n * General: Stream access\n * Output: fixed-length, 512-byte records.\n *\n * Callback function (DEC C only) sets deq, mbc, mbf, rah, wbh, ...\n */\n\n#  define FOPM \"r+b\", \"ctx=stm\", \"rfm=fix\", \"mrs=512\", \"acc\", acc_cb, &fopm_id\n#  define FOPR \"rb\",  \"ctx=stm\", \"acc\", acc_cb, &fopr_id\n#  define FOPW \"wb\",  \"ctx=stm\", \"rfm=fix\", \"mrs=512\", \"acc\", acc_cb, &fopw_id\n\n#else /* def __DECC */ /* (So, GNU C, VAX C, ...)*/\n\n#  define FOPM \"r+b\", \"ctx=stm\", \"rfm=fix\", \"mrs=512\"\n#  define FOPR \"rb\",  \"ctx=stm\"\n#  define FOPW \"wb\",  \"ctx=stm\", \"rfm=fix\", \"mrs=512\"\n\n#endif /* def __DECC */\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/stream_lf.fdl",
    "content": "RECORD\n        Carriage_Control carriage_return\n        Format stream_lf\n"
  },
  {
    "path": "deps/infozip/zip30/vms/unixio_gcc.h",
    "content": "/* 2004-12-12 SMS.\n *\n * Emergency replacement UNIXIO.H for GNU C, for use as needed.\n * Install as GNU_CC_INCLUDE:[000000]UNIXIO.H\n */\n\n#ifndef __UNIXIO_LOADED\n#define __UNIXIO_LOADED 1\n\n#include <sys/types.h>\n\n#include <stdlib.h>\n\n#ifndef SEEK_SET\n# define SEEK_SET 0\n#endif /* ndef SEEK_SET */\n\n#ifndef SEEK_CUR\n# define SEEK_CUR 1\n#endif /* ndef SEEK_CUR */\n\n#ifndef SEEK_END\n# define SEEK_END 2\n#endif /* ndef SEEK_END */\n\n#endif  /* ndef __UNIXIO_LOADED */\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/unixlib_gcc.h",
    "content": "/* 2004-12-12 SMS.\n *\n * Emergency replacement UNIXLIB.H for GNU C, for use as needed.\n * Install as GNU_CC_INCLUDE:[000000]UNIXLIB.H\n */\n\n#ifndef __UNIXLIB_LOADED\n#define __UNIXLIB_LOADED 1\n\n#include <sys/types.h>\n#include <stdlib.h>\n\ntypedef struct stat stat_t;\n\n#endif  /* ndef __UNIXLIB_LOADED */\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vms.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  vms.c (zip) by Igor Mandrichenko    Version 2.2-2\n *\n *  Revision history:\n *  ...\n *  2.2-2       18-jan-1993     I.Mandrichenko\n *      vms_stat() added - version of stat() that handles special\n *      case when end-of-file-block == 0\n *\n *  3.0         11-oct-2004     SMS\n *      It would be nice to know why vms_stat() is needed.  If EOF can't\n *      be trusted for a zero-length file, why trust it for any file?\n *      Anyway, I removed the (int) cast on ->st_size, which may now be\n *      bigger than an int, just in case this code ever does get used.\n *      (A true zero-length file should still report zero length, even\n *      after the long fight with RMS.)\n *      Moved the VMS_PK_EXTRA test(s) into VMS_IM.C and VMS_PK.C to\n *      allow more general automatic dependency generation.\n */\n\n#ifdef VMS                      /* For VMS only ! */\n\n#define NO_ZIPUP_H              /* Prevent full inclusion of vms/zipup.h. */\n\n#include \"zip.h\"\n#include \"zipup.h\"              /* Only partial. */\n\n#include <stdio.h>\n#include <string.h>\n\n#include <jpidef.h>\n#include <fab.h>                /* Needed only in old environments. */\n#include <nam.h>                /* Needed only in old environments. */\n#include <starlet.h>\n#include <ssdef.h>\n#include <stsdef.h>\n\n/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.\n   Otherwise, lame system headers on VAX cause compiler warnings.\n   (GNU C may define vax but not __VAX.)\n*/\n#ifdef vax\n# define __VAX 1\n#endif /* def vax */\n\n#ifdef __VAX\n# define GVTC (unsigned int)\n#else /* def __VAX */\n# define GVTC\n#endif /* def __VAX */\n\n\n#ifdef UTIL\n\n/* For utilities, include only vms.h, as either of the vms_XX.c files\n * would do.\n */\n\n# include \"vms.h\"\n\n#else /* not UTIL */\n\n/* Include the `VMS attributes' preserving file-io code. We distinguish\n   between two incompatible flavours of storing VMS attributes in the\n   Zip archive:\n   a) The \"PKware\" style follows the extra field specification for\n      PKware's VMS Zip.\n   b) The \"IM (Info-ZIP)\" flavour was defined from scratch by\n      Igor Mandrichenko. This version has be used in official Info-ZIP\n      releases for several years and is known to work well.\n */\n\n/* Note that only one of these #include directives will include any\n * active code, depending on VMS_PK_EXTRA.  Both are included here (and\n * tested there) to allow more general automatic dependency generation.\n */\n\n#include \"vms_pk.c\"\n#include \"vms_im.c\"\n\n#endif /* not UTIL [else] */\n\n#ifndef ERR\n#define ERR(x) (((x)&1)==0)\n#endif\n\n#ifndef NULL\n#define NULL (void*)(0L)\n#endif\n\nint vms_stat( char *file, stat_t *s)\n{\n    int status;\n    int staterr;\n    struct FAB fab;\n    struct NAM_STRUCT nam;\n    struct XABFHC fhc;\n\n    /*\n     *  In simplest case when stat() returns \"ok\" and file size is\n     *  nonzero or this is directory, finish with this\n     */\n\n    if( (staterr=stat(file,s)) == 0\n        && ( s->st_size >= 0                      /* Size - ok */\n             || (s->st_mode & S_IFREG) == 0       /* Not a plain file */\n           )\n    ) return staterr;\n\n    /*\n     *  Get here to handle the special case when stat() returns\n     *  invalid file size. Use RMS to compute the size.\n     *  When EOF block is zero, set file size to its physical size.\n     *  One more case to get here is when this is remote file accessed\n     *  via DECnet.\n     */\n\n    fab = cc$rms_fab;\n    nam = CC_RMS_NAM;\n    fhc = cc$rms_xabfhc;\n    fab.FAB_NAM = &nam;\n    fab.fab$l_xab = (char*)(&fhc);\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = file;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( file);\n\n    fab.fab$b_fac = FAB$M_GET;\n\n    status = sys$open(&fab);\n    fab.fab$l_xab = (char*)0L;\n    sys$close(&fab);\n\n    if( !ERR(status) )\n    {\n        if( fhc.xab$l_ebk > 0 )\n            s->st_size = ( fhc.xab$l_ebk-1 ) * 512 + fhc.xab$w_ffb;\n        else if( fab.fab$b_org == FAB$C_IDX\n                 || fab.fab$b_org == FAB$C_REL\n                 || fab.fab$b_org == FAB$C_HSH )\n                /* Special case, when ebk=0: save entire allocated space */\n                    s->st_size = fhc.xab$l_hbk * 512;\n        else\n            s->st_size = fhc.xab$w_ffb;\n        return 0; /* stat() success code */\n    }\n    else\n        return status;\n}\n\n\n/*\n * 2007-01-29 SMS.\n *\n *  VMS Status Code Summary  (See STSDEF.H for details.)\n *\n *      Bits:   31:28    27:16     15:3     2:0\n *      Field:  Control  Facility  Message  Severity\n *\n *  In the Control field, bits 31:29 are reserved.  Bit 28 inhibits\n *  printing the message.  In the Facility field, bit 27 means\n *  customer-defined (not HP-assigned, like us).  In the Message field,\n *  bit 15 means facility-specific (which our messages are).  The\n *  Severity codes are 0 = Warning, 1 = Success, 2 = Error, 3 = Info,\n *  4 = Severe (fatal).\n *\n *  Previous versions of Info-ZIP programs used a generic (\"chosen (by\n *  experimentation)\") Control+Facility code of 0x7FFF, which included\n *  some reserved control bits, the inhibit-printing bit, and the\n *  customer-defined bit.\n *\n *  HP has now assigned official Facility names and corresponding\n *  Facility codes for the Info-ZIP products:\n *\n *      Facility Name    Facility Code\n *      IZ_UNZIP         1954 = 0x7A2\n *      IZ_ZIP           1955 = 0x7A3\n *\n *  Now, unless the CTL_FAC_IZ_ZIP macro is defined at build-time, we\n *  will use the official Facility code.\n *\n */\n\n/* Official HP-assigned Info-ZIP Zip Facility code. */\n#define FAC_IZ_ZIP 1955   /* 0x7A3 */\n\n#ifndef CTL_FAC_IZ_ZIP\n   /*\n    * Default is inhibit-printing with the official Facility code.\n    */\n#  define CTL_FAC_IZ_ZIP ((0x1 << 12)| FAC_IZ_ZIP)\n#  define MSG_FAC_SPEC 0x8000   /* Facility-specific code. */\n#else /* ndef CTL_FAC_IZ_ZIP */\n   /* Use the user-supplied Control+Facility code for err or warn. */\n#  define OLD_STATUS\n#  ifndef MSG_FAC_SPEC          /* Old default is not Facility-specific. */\n#    define MSG_FAC_SPEC 0x0    /* Facility-specific code.  Or 0x8000. */\n#  endif /* ndef MSG_FAC_SPEC */\n#endif /* ndef CTL_FAC_IZ_ZIP [else] */\n\n\n/* Return an intelligent status/severity code. */\n\nvoid vms_exit(e)\n   int e;\n{\n  {\n#ifndef OLD_STATUS\n\n    /*\n     * Exit with code comprising Control, Facility, (facility-specific)\n     * Message, and Severity.\n     */\n    exit( (CTL_FAC_IZ_ZIP << 16) |              /* Facility                */\n          MSG_FAC_SPEC |                        /* Facility-specific       */\n          (e << 4) |                            /* Message code            */\n          (ziperrors[ e].severity & 0x07)       /* Severity                */\n        );\n\n#else /* ndef OLD_STATUS */\n\n    /* 2007-01-17 SMS.\n     * Defining OLD_STATUS provides the same behavior as in Zip versions\n     * before an official VMS Facility code had been assigned, which\n     * means that Success (ZE_OK) gives a status value of 1 (SS$_NORMAL)\n     * with no Facility code, while any error or warning gives a status\n     * value which includes a Facility code.  (Curiously, under the old\n     * scheme, message codes were left-shifted by 4 instead of 3,\n     * resulting in all-even message codes.)  I don't like this, but I\n     * was afraid to remove it, as someone, somewhere may be depending\n     * on it.  Define CTL_FAC_IZ_ZIP as 0x7FFF to get the old behavior.\n     * Define only OLD_STATUS to get the old behavior for Success\n     * (ZE_OK), but using the official HP-assigned Facility code for an\n     * error or warning.  Define MSG_FAC_SPEC to get the desired\n     * behavior.\n     *\n     * Exit with simple SS$_NORMAL for ZE_OK.  Otherwise, exit with code\n     * comprising Control, Facility, Message, and Severity.\n     */\n    exit(\n         (e == ZE_OK) ? SS$_NORMAL :            /* Success (others below)  */\n         ((CTL_FAC_IZ_ZIP << 16) |              /* Facility                */\n          MSG_FAC_SPEC |                        /* Facility-specific (?)   */\n          (e << 4) |                            /* Message code            */\n          (ziperrors[ e].severity & 0x07)       /* Severity                */\n         )\n        );\n\n#endif /* ndef OLD_STATUS */\n   }\n}\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s%s.\\n\\n\";\n#ifdef VMS_VERSION\n    char *chrp1;\n    char *chrp2;\n    char buf[40];\n    char vms_vers[ 16];\n    int ver_maj;\n#endif\n#ifdef __DECC_VER\n    char buf2[40];\n    int  vtyp;\n#endif\n\n#ifdef VMS_VERSION\n    /* Truncate the version string at the first (trailing) space. */\n    strncpy( vms_vers, VMS_VERSION, sizeof( vms_vers));\n    chrp1 = strchr( vms_vers, ' ');\n    if (chrp1 != NULL)\n        *chrp1 = '\\0';\n\n    /* Determine the major version number. */\n    ver_maj = 0;\n    chrp1 = strchr( &vms_vers[ 1], '.');\n    for (chrp2 = &vms_vers[ 1];\n     chrp2 < chrp1;\n     ver_maj = ver_maj* 10+ *(chrp2++)- '0');\n\n#endif /* def VMS_VERSION */\n\n/*  DEC C in ANSI mode does not like \"#ifdef MACRO\" inside another\n    macro when MACRO is equated to a value (by \"#define MACRO 1\").   */\n\n    printf(CompiledWith,\n\n#ifdef __GNUC__\n      \"gcc \", __VERSION__,\n#else\n#  if defined(DECC) || defined(__DECC) || defined (__DECC__)\n      \"DEC C\",\n#    ifdef __DECC_VER\n      (sprintf(buf2, \" %c%d.%d-%03d\",\n               ((vtyp = (__DECC_VER / 10000) % 10) == 6 ? 'T' :\n                (vtyp == 8 ? 'S' : 'V')),\n               __DECC_VER / 10000000,\n               (__DECC_VER % 10000000) / 100000, __DECC_VER % 1000), buf2),\n#    else\n      \"\",\n#    endif\n#  else\n#  ifdef VAXC\n      \"VAX C\", \"\",\n#  else\n      \"unknown compiler\", \"\",\n#  endif\n#  endif\n#endif\n\n#ifdef VMS_VERSION\n#  if defined( __alpha)\n      \"OpenVMS\",\n      (sprintf( buf, \" (%s Alpha)\", vms_vers), buf),\n#  elif defined( __ia64) /* defined( __alpha) */\n      \"OpenVMS\",\n      (sprintf( buf, \" (%s IA64)\", vms_vers), buf),\n#  else /* defined( __alpha) */\n      (ver_maj >= 6) ? \"OpenVMS\" : \"VMS\",\n      (sprintf( buf, \" (%s VAX)\", vms_vers), buf),\n#  endif /* defined( __alpha) */\n#else\n      \"VMS\",\n      \"\",\n#endif /* def VMS_VERSION */\n\n#ifdef __DATE__\n      \" on \", __DATE__\n#else\n      \"\", \"\"\n#endif\n      );\n\n} /* end function version_local() */\n\n/* 2004-10-08 SMS.\n *\n *       tempname() for VMS.\n *\n *    Generate a temporary Zip archive file name, near the actual\n *    destination Zip archive file, or at \"tempath\", if specified.\n *\n *    Using sys$parse() is probably more work than it's worth, but it\n *    should also be ODS5-safe.\n *\n *    Note that the generic method using tmpnam() (in FILEIO.C)\n *    produces \"ziXXXXXX\", where \"XXXXXX\" is the low six digits of the\n *    decimal representation of the process ID.  This method produces\n *    \"ZIxxxxxxxx\", where \"xxxxxxxx\" is the (whole) eight-digit\n *    hexadecimal representation of the process ID.  More important, it\n *    actually uses the directory part of the argument or \"tempath\".\n */\n\n\nchar *tempname( char *zip)\n/* char *zip; */                /* Path name of Zip archive. */\n{\n    char *temp_name;            /* Return value. */\n    int sts;                    /* System service status. */\n\n    static int pid;             /* Process ID. */\n    static int pid_len;         /* Returned size of process ID. */\n\n    struct                      /* Item list for GETJPIW. */\n    {\n        short buf_len;          /* Buffer length. */\n        short itm_cod;          /* Item code. */\n        int *buf;               /* Buffer address. */\n        int *ret_len;           /* Returned length. */\n        int term;               /* Item list terminator. */\n    } jpi_itm_lst = { sizeof( pid), JPI$_PID, &pid, &pid_len };\n\n    /* ZI<UNIQUE> name storage. */\n    static char zip_tmp_nam[ 16] = \"ZI<unique>.;\";\n\n    struct FAB fab;             /* FAB structure. */\n    struct NAM_STRUCT nam;      /* NAM[L] structure. */\n\n    char exp_str[ NAM_MAXRSS+ 1];   /* Expanded name storage. */\n\n#ifdef VMS_UNIQUE_TEMP_BY_TIME\n\n    /* Use alternate time-based scheme to generate a unique temporary name. */\n    sprintf( &zip_tmp_nam[ 2], \"%08X\", time( NULL));\n\n#else /* def VMS_UNIQUE_TEMP_BY_TIME */\n\n    /* Use the process ID to generate a unique temporary name. */\n    sts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);\n    sprintf( &zip_tmp_nam[ 2], \"%08X\", pid);\n\n#endif /* def VMS_UNIQUE_TEMP_BY_TIME */\n\n    /* Smoosh the unique temporary name against the actual Zip archive\n       name (or \"tempath\") to create the full temporary path name.\n       (Truncate it at the file type to remove any file type.)\n    */\n    if (tempath != NULL)        /* Use \"tempath\", if it's been specified. */\n        zip = tempath;\n\n    /* Initialize the FAB and NAM[L], and link the NAM[L] to the FAB. */\n    fab = cc$rms_fab;\n    nam = CC_RMS_NAM;\n    fab.FAB_NAM = &nam;\n\n    /* Point the FAB/NAM[L] fields to the actual name and default name. */\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    /* Default name = Zip archive name. */\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNA = zip;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNS = strlen( zip);\n\n    /* File name = \"ZI<unique>,;\". */\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = zip_tmp_nam;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( zip_tmp_nam);\n\n    nam.NAM_ESA = exp_str;      /* Expanded name (result) storage. */\n    nam.NAM_ESS = NAM_MAXRSS;   /* Size of expanded name storage. */\n\n    nam.NAM_NOP = NAM_M_SYNCHK; /* Syntax-only analysis. */\n\n    temp_name = NULL;           /* Prepare for failure (unlikely). */\n    sts = sys$parse( &fab, 0, 0);       /* Parse the name(s). */\n\n    if ((sts& STS$M_SEVERITY) == STS$M_SUCCESS)\n    {\n        /* Overlay any resulting file type (typically \".ZIP\") with none. */\n        strcpy( nam.NAM_L_TYPE, \".;\");\n\n        /* Allocate temp name storage (as caller expects), and copy the\n           (truncated) temp name into the new location.\n        */\n        temp_name = malloc( strlen( nam.NAM_ESA)+ 1);\n\n        if (temp_name != NULL)\n        {\n            strcpy( temp_name, nam.NAM_ESA);\n        }\n    }\n    return temp_name;\n} /* tempname() for VMS. */\n\n\n/* 2005-02-17 SMS.\n *\n *       ziptyp() for VMS.\n *\n *    Generate a real Zip archive file name (exact, if it exists), using\n *    a default file name.\n *\n *    2005-02-17 SMS.  Moved to here from [-]ZIPFILE.C, to segregate\n *    better the RMS stuff.\n *\n *    Before 2005-02-17, if sys$parse() failed, ziptyp() returned a null\n *    string (\"&zero\", where \"static char zero = '\\0';\").  This\n *    typically caused Zip to proceed, but then the final rename() of\n *    the temporary archive would (silently) fail (null file name, after\n *    all), leaving only the temporary archive file, and providing no\n *    warning message to the victim.  Now, when sys$parse() fails,\n *    ziptyp() returns the original string, so a later open() fails, and\n *    a relatively informative message is provided.  (A VMS-specific\n *    message could also be provided here, if desired.)\n *\n *    2005-09-16 SMS.\n *    Changed name parsing in ziptyp() to solve a problem with a\n *    search-list logical name device-directory spec for the zipfile.\n *    Previously, when the zipfile did not exist (so sys$search()\n *    failed), the expanded name was used, but as it was\n *    post-sys$search(), it was based on the _last_ member of the search\n *    list instead of the first.  Now, the expanded name from the\n *    original sys$parse() (pre-sys$search()) is retained, and it is\n *    used if sys$search() fails.  This name is based on the first\n *    member of the search list, as a user might expect.\n */\n\n/* Default Zip archive file spec. */\n#define DEF_DEVDIRNAM \"SYS$DISK:[].zip\"\n\nchar *ziptyp( char *s)\n{\n    int status;\n    int exp_len;\n    struct FAB fab;\n    struct NAM_STRUCT nam;\n    char result[ NAM_MAXRSS+ 1];\n    char exp[ NAM_MAXRSS+ 1];\n    char *p;\n\n    fab = cc$rms_fab;                           /* Initialize FAB. */\n    nam = CC_RMS_NAM;                           /* Initialize NAM[L]. */\n    fab.FAB_NAM = &nam;                         /* FAB -> NAM[L] */\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna =(char *) -1;         /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;        /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    /* Argument file name and length. */\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = s;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( s);\n\n    /* Default file spec and length. */\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNA = DEF_DEVDIRNAM;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNS = sizeof( DEF_DEVDIRNAM)- 1;\n\n    nam.NAM_ESA = exp;                 /* Expanded name, */\n    nam.NAM_ESS = NAM_MAXRSS;          /* storage size. */\n    nam.NAM_RSA = result;              /* Resultant name, */\n    nam.NAM_RSS = NAM_MAXRSS;          /* storage size. */\n\n    status = sys$parse(&fab);\n    if ((status & 1) == 0)\n    {\n        /* Invalid file name.  Return (re-allocated) original, and hope\n           for a later error message.\n        */\n        if ((p = malloc( strlen( s)+ 1)) != NULL )\n        {\n            strcpy( p, s);\n        }\n        return p;\n    }\n\n    /* Save expanded name length from sys$parse(). */\n    exp_len = nam.NAM_ESL;\n\n    /* Leave expanded name as-is, in case of search failure. */\n    nam.NAM_ESA = NULL;                 /* Expanded name, */\n    nam.NAM_ESS = 0;                    /* storage size. */\n\n    status = sys$search(&fab);\n    if (status & 1)\n    {   /* Zip file exists.  Use resultant (complete, exact) name. */\n        if ((p = malloc( nam.NAM_RSL+ 1)) != NULL )\n        {\n            result[ nam.NAM_RSL] = '\\0';\n            strcpy( p, result);\n        }\n    }\n    else\n    {   /* New Zip file.  Use pre-search expanded name. */\n        if ((p = malloc( exp_len+ 1)) != NULL )\n        {\n            exp[ exp_len] = '\\0';\n            strcpy( p, exp);\n        }\n    }\n    return p;\n} /* ziptyp() for VMS. */\n\n\n/* 2005-12-30 SMS.\n *\n *       vms_file_version().\n *\n *    Return the \";version\" part of a VMS file specification.\n */\n\nchar *vms_file_version( char *s)\n{\n    int status;\n    struct FAB fab;\n    struct NAM_STRUCT nam;\n    char *p;\n\n    static char exp[ NAM_MAXRSS+ 1];    /* Expanded name storage. */\n\n\n    fab = cc$rms_fab;                   /* Initialize FAB. */\n    nam = CC_RMS_NAM;                   /* Initialize NAM[L]. */\n    fab.FAB_NAM = &nam;                 /* FAB -> NAM[L] */\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna =(char *) -1;         /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;        /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    /* Argument file name and length. */\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = s;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( s);\n\n    nam.NAM_ESA = exp;                 /* Expanded name, */\n    nam.NAM_ESS = NAM_MAXRSS;          /* storage size. */\n\n    nam.NAM_NOP = NAM_M_SYNCHK;        /* Syntax-only analysis. */\n\n    status = sys$parse(&fab);\n\n    if ((status & 1) == 0)\n    {\n        /* Invalid file name.  Return \"\". */\n        exp[ 0] = '\\0';\n        p = exp;\n    }\n    else\n    {\n        /* Success.  NUL-terminate, and return a pointer to the \";\" in\n           the expanded name storage buffer.\n        */\n        p = nam.NAM_L_VER;\n        p[ nam.NAM_B_VER] = '\\0';\n    }\n    return p;\n} /* vms_file_version(). */\n\n\n/* 2004-11-23 SMS.\n *\n *       get_rms_defaults().\n *\n *    Get user-specified values from (DCL) SET RMS_DEFAULT.  FAB/RAB\n *    items of particular interest are:\n *\n *       fab$w_deq         default extension quantity (blocks) (write).\n *       rab$b_mbc         multi-block count.\n *       rab$b_mbf         multi-buffer count (used with rah and wbh).\n */\n\n#define DIAG_FLAG (verbose >= 2)\n\n/* Default RMS parameter values. */\n\n#define RMS_DEQ_DEFAULT 16384   /* About 1/4 the max (65535 blocks). */\n#define RMS_MBC_DEFAULT 127     /* The max, */\n#define RMS_MBF_DEFAULT 2       /* Enough to enable rah and wbh. */\n\n/* GETJPI item descriptor structure. */\ntypedef struct\n    {\n    short buf_len;\n    short itm_cod;\n    void *buf;\n    int *ret_len;\n    } jpi_item_t;\n\n/* Durable storage */\n\nstatic int rms_defaults_known = 0;\n\n/* JPI item buffers. */\nstatic unsigned short rms_ext;\nstatic char rms_mbc;\nstatic unsigned char rms_mbf;\n\n/* Active RMS item values. */\nunsigned short rms_ext_active;\nchar rms_mbc_active;\nunsigned char rms_mbf_active;\n\n/* GETJPI item lengths. */\nstatic int rms_ext_len;         /* Should come back 2. */\nstatic int rms_mbc_len;         /* Should come back 1. */\nstatic int rms_mbf_len;         /* Should come back 1. */\n\n/* Desperation attempts to define unknown macros.  Probably doomed.\n * If these get used, expect sys$getjpiw() to return %x00000014 =\n * %SYSTEM-F-BADPARAM, bad parameter value.\n * They keep compilers with old header files quiet, though.\n */\n#ifndef JPI$_RMS_EXTEND_SIZE\n#  define JPI$_RMS_EXTEND_SIZE 542\n#endif /* ndef JPI$_RMS_EXTEND_SIZE */\n\n#ifndef JPI$_RMS_DFMBC\n#  define JPI$_RMS_DFMBC 535\n#endif /* ndef JPI$_RMS_DFMBC */\n\n#ifndef JPI$_RMS_DFMBFSDK\n#  define JPI$_RMS_DFMBFSDK 536\n#endif /* ndef JPI$_RMS_DFMBFSDK */\n\n/* GETJPI item descriptor set. */\n\nstruct\n    {\n    jpi_item_t rms_ext_itm;\n    jpi_item_t rms_mbc_itm;\n    jpi_item_t rms_mbf_itm;\n    int term;\n    } jpi_itm_lst =\n     { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len },\n       { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len },\n       { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len },\n       0\n     };\n\nint get_rms_defaults()\n{\nint sts;\n\n/* Get process RMS_DEFAULT values. */\n\nsts = sys$getjpiw( 0, 0, 0, &jpi_itm_lst, 0, 0, 0);\nif ((sts& STS$M_SEVERITY) != STS$M_SUCCESS)\n    {\n    /* Failed.  Don't try again. */\n    rms_defaults_known = -1;\n    }\nelse\n    {\n    /* Fine, but don't come back. */\n    rms_defaults_known = 1;\n    }\n\n/* Limit the active values according to the RMS_DEFAULT values. */\n\nif (rms_defaults_known > 0)\n    {\n    /* Set the default values. */\n\n    rms_ext_active = RMS_DEQ_DEFAULT;\n    rms_mbc_active = RMS_MBC_DEFAULT;\n    rms_mbf_active = RMS_MBF_DEFAULT;\n\n    /* Default extend quantity.  Use the user value, if set. */\n    if (rms_ext > 0)\n        {\n        rms_ext_active = rms_ext;\n        }\n\n    /* Default multi-block count.  Use the user value, if set. */\n    if (rms_mbc > 0)\n        {\n        rms_mbc_active = rms_mbc;\n        }\n\n    /* Default multi-buffer count.  Use the user value, if set. */\n    if (rms_mbf > 0)\n        {\n        rms_mbf_active = rms_mbf;\n        }\n    }\n\nif (DIAG_FLAG)\n    {\n    fprintf( stderr,\n     \"Get RMS defaults.  getjpi sts = %%x%08x.\\n\",\n     sts);\n\n    if (rms_defaults_known > 0)\n        {\n        fprintf( stderr,\n         \"               Default: deq = %6d, mbc = %3d, mbf = %3d.\\n\",\n         rms_ext, rms_mbc, rms_mbf);\n        }\n    }\nreturn sts;\n}\n\n#ifdef __DECC\n\n/* 2004-11-23 SMS.\n *\n *       acc_cb(), access callback function for DEC C zfopen().\n *\n *    Set some RMS FAB/RAB items, with consideration of user-specified\n * values from (DCL) SET RMS_DEFAULT.  Items of particular interest are:\n *\n *       fab$w_deq         default extension quantity (blocks).\n *       rab$b_mbc         multi-block count.\n *       rab$b_mbf         multi-buffer count (used with rah and wbh).\n *\n *    See also the FOP* macros in OSDEP.H.  Currently, no notice is\n * taken of the caller-ID value, but options could be set differently\n * for read versus write access.  (I assume that specifying fab$w_deq,\n * for example, for a read-only file has no ill effects.)\n */\n\n/* Global storage. */\n\nint fopm_id = FOPM_ID;          /* Callback id storage, modify. */\nint fopr_id = FOPR_ID;          /* Callback id storage, read. */\nint fopw_id = FOPW_ID;          /* Callback id storage, write. */\n\nint fhow_id = FHOW_ID;          /* Callback id storage, in read. */\n\n/* acc_cb() */\n\nint acc_cb( int *id_arg, struct FAB *fab, struct RAB *rab)\n{\nint sts;\n\n/* Get process RMS_DEFAULT values, if not already done. */\nif (rms_defaults_known == 0)\n    {\n    get_rms_defaults();\n    }\n\n/* If RMS_DEFAULT (and adjusted active) values are available, then set\n * the FAB/RAB parameters.  If RMS_DEFAULT values are not available,\n * suffer with the default parameters.\n */\nif (rms_defaults_known > 0)\n    {\n    /* Set the FAB/RAB parameters accordingly. */\n    fab-> fab$w_deq = rms_ext_active;\n    rab-> rab$b_mbc = rms_mbc_active;\n    rab-> rab$b_mbf = rms_mbf_active;\n\n    /* Truncate at EOF on close, as we'll probably over-extend. */\n    fab-> fab$v_tef = 1;\n\n    /* If using multiple buffers, enable read-ahead and write-behind. */\n    if (rms_mbf_active > 1)\n        {\n        rab-> rab$v_rah = 1;\n        rab-> rab$v_wbh = 1;\n        }\n\n    if (DIAG_FLAG)\n        {\n        fprintf( mesg,\n         \"Open callback.  ID = %d, deq = %6d, mbc = %3d, mbf = %3d.\\n\",\n         *id_arg, fab-> fab$w_deq, rab-> rab$b_mbc, rab-> rab$b_mbf);\n        }\n    }\n\n/* Declare success. */\nreturn 0;\n}\n\n#endif /* def __DECC */\n\n/*\n * 2004-09-19 SMS.\n *\n *----------------------------------------------------------------------\n *\n *       decc_init()\n *\n *    On non-VAX systems, uses LIB$INITIALIZE to set a collection of C\n *    RTL features without using the DECC$* logical name method.\n *\n *----------------------------------------------------------------------\n */\n\n#ifdef __DECC\n\n#ifdef __CRTL_VER\n\n#if !defined( __VAX) && (__CRTL_VER >= 70301000)\n\n#include <unixlib.h>\n\n/*--------------------------------------------------------------------*/\n\n/* Global storage. */\n\n/*    Flag to sense if decc_init() was called. */\n\nint decc_init_done = -1;\n\n/*--------------------------------------------------------------------*/\n\n/* decc_init()\n\n      Uses LIB$INITIALIZE to set a collection of C RTL features without\n      requiring the user to define the corresponding logical names.\n*/\n\n/* Structure to hold a DECC$* feature name and its desired value. */\n\ntypedef struct\n   {\n   char *name;\n   int value;\n   } decc_feat_t;\n\n/* Array of DECC$* feature names and their desired values. */\n\ndecc_feat_t decc_feat_array[] = {\n\n   /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */\n { \"DECC$ARGV_PARSE_STYLE\", 1 },\n\n   /* Preserve case for file names on ODS5 disks. */\n { \"DECC$EFS_CASE_PRESERVE\", 1 },\n\n   /* Enable multiple dots (and most characters) in ODS5 file names,\n      while preserving VMS-ness of \";version\". */\n { \"DECC$EFS_CHARSET\", 1 },\n\n   /* List terminator. */\n { (char *)NULL, 0 } };\n\n/* LIB$INITIALIZE initialization function. */\n\nstatic void decc_init( void)\n{\nint feat_index;\nint feat_value;\nint feat_value_max;\nint feat_value_min;\nint i;\nint sts;\n\n/* Set the global flag to indicate that LIB$INITIALIZE worked. */\n\ndecc_init_done = 1;\n\n/* Loop through all items in the decc_feat_array[]. */\n\nfor (i = 0; decc_feat_array[ i].name != NULL; i++)\n   {\n   /* Get the feature index. */\n   feat_index = decc$feature_get_index( decc_feat_array[ i].name);\n   if (feat_index >= 0)\n      {\n      /* Valid item.  Collect its properties. */\n      feat_value = decc$feature_get_value( feat_index, 1);\n      feat_value_min = decc$feature_get_value( feat_index, 2);\n      feat_value_max = decc$feature_get_value( feat_index, 3);\n\n      if ((decc_feat_array[ i].value >= feat_value_min) &&\n       (decc_feat_array[ i].value <= feat_value_max))\n         {\n         /* Valid value.  Set it if necessary. */\n         if (feat_value != decc_feat_array[ i].value)\n            {\n            sts = decc$feature_set_value( feat_index,\n             1,\n             decc_feat_array[ i].value);\n            }\n         }\n      else\n         {\n         /* Invalid DECC feature value. */\n         printf( \" INVALID DECC FEATURE VALUE, %d: %d <= %s <= %d.\\n\",\n          feat_value,\n          feat_value_min, decc_feat_array[ i].name, feat_value_max);\n         }\n      }\n   else\n      {\n      /* Invalid DECC feature name. */\n      printf( \" UNKNOWN DECC FEATURE: %s.\\n\", decc_feat_array[ i].name);\n      }\n   }\n}\n\n/* Get \"decc_init()\" into a valid, loaded LIB$INITIALIZE PSECT. */\n\n#pragma nostandard\n\n/* Establish the LIB$INITIALIZE PSECTs, with proper alignment and\n   other attributes.  Note that \"nopic\" is significant only on VAX.\n*/\n#pragma extern_model save\n\n#pragma extern_model strict_refdef \"LIB$INITIALIZ\" 2, nopic, nowrt\nconst int spare[ 8] = { 0 };\n\n#pragma extern_model strict_refdef \"LIB$INITIALIZE\" 2, nopic, nowrt\nvoid (*const x_decc_init)() = decc_init;\n\n#pragma extern_model restore\n\n/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */\n\n#pragma extern_model save\n\nint LIB$INITIALIZE( void);\n\n#pragma extern_model strict_refdef\nint dmy_lib$initialize = (int) LIB$INITIALIZE;\n\n#pragma extern_model restore\n\n#pragma standard\n\n#endif /* !defined( __VAX) && (__CRTL_VER >= 70301000) */\n\n#endif /* def __CRTL_VER */\n\n#endif /* def __DECC */\n\n#endif /* VMS */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vms.h",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vms.h\n\n  Generic VMS header file for Info-ZIP's Zip and UnZip.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vms_h\n#define __vms_h 1\n\n#ifndef __DESCRIP_LOADED\n#include <descrip.h>\n#endif\n#ifndef __STARLET_LOADED\n#include <starlet.h>\n#endif\n#ifndef __SYIDEF_LOADED\n#include <syidef.h>\n#endif\n#ifndef __ATRDEF_LOADED\n#include <atrdef.h>\n#endif\n#ifndef __FIBDEF_LOADED\n#include <fibdef.h>\n#endif\n#ifndef __IODEF_LOADED\n#include <iodef.h>\n#endif\n#if !defined(_RMS_H) && !defined(__RMS_LOADED)\n#include <rms.h>\n#endif\n\n#define ERR(s) !((s) & 1)       /* VMS system error */\n\n#ifndef SYI$_VERSION\n#define SYI$_VERSION 4096       /* VMS 5.4 definition */\n#endif\n\n/*\n *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions\n *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third\n *  party compilers which do not support `variant_union' define preprocessor\n *  symbols to `hide' the \"intermediate union/struct\" names from the\n *  programmer's API.\n *  We check the presence of these defines and for DEC's FIBDEF.H defining\n *  __union as variant_union to make sure we access the structure correctly.\n */\n#define variant_union 1\n#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))\n#  define FIB$W_DID     fib$w_did\n#  define FIB$W_FID     fib$w_fid\n#  define FIB$L_ACCTL   fib$l_acctl\n#  define FIB$W_EXCTL   fib$w_exctl\n#else\n#  define FIB$W_DID     fib$r_did_overlay.fib$w_did\n#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid\n#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl\n#  define FIB$W_EXCTL   fib$r_exctl_overlay.fib$w_exctl\n#endif\n#undef variant_union\n\n\n/* 2005-02-08 SMS.  Moved NAM[L] macros here from VMS.C. */\n\n/* Define macros for use with either NAM or NAML. */\n\n#ifdef NAML$C_MAXRSS            /* NAML is available.  Use it. */\n\n#  define NAM_STRUCT NAML\n\n#  define FAB_OR_NAML( fab, nam) nam\n#  define FAB_OR_NAML_DNA naml$l_long_defname\n#  define FAB_OR_NAML_DNS naml$l_long_defname_size\n#  define FAB_OR_NAML_FNA naml$l_long_filename\n#  define FAB_OR_NAML_FNS naml$l_long_filename_size\n\n#  define CC_RMS_NAM cc$rms_naml\n#  define FAB_NAM fab$l_naml\n#  define NAM_DID naml$w_did\n#  define NAM_DVI naml$t_dvi\n#  define NAM_ESA naml$l_long_expand\n#  define NAM_ESL naml$l_long_expand_size\n#  define NAM_ESS naml$l_long_expand_alloc\n#  define NAM_FID naml$w_fid\n#  define NAM_FNB naml$l_fnb\n#  define NAM_RSA naml$l_long_result\n#  define NAM_RSL naml$l_long_result_size\n#  define NAM_RSS naml$l_long_result_alloc\n#  define NAM_MAXRSS NAML$C_MAXRSS\n#  define NAM_NOP naml$b_nop\n#  define NAM_M_EXP_DEV NAML$M_EXP_DEV\n#  define NAM_M_SYNCHK NAML$M_SYNCHK\n#  define NAM_B_DEV naml$l_long_dev_size\n#  define NAM_L_DEV naml$l_long_dev\n#  define NAM_B_DIR naml$l_long_dir_size\n#  define NAM_L_DIR naml$l_long_dir\n#  define NAM_B_NAME naml$l_long_name_size\n#  define NAM_L_NAME naml$l_long_name\n#  define NAM_B_TYPE naml$l_long_type_size\n#  define NAM_L_TYPE naml$l_long_type\n#  define NAM_B_VER naml$l_long_ver_size\n#  define NAM_L_VER naml$l_long_ver\n\n#else /* def NAML$C_MAXRSS */   /* NAML is not available.  Use NAM. */\n\n#  define NAM_STRUCT NAM\n\n#  define FAB_OR_NAML( fab, nam) fab\n#  define FAB_OR_NAML_DNA fab$l_dna\n#  define FAB_OR_NAML_DNS fab$b_dns\n#  define FAB_OR_NAML_FNA fab$l_fna\n#  define FAB_OR_NAML_FNS fab$b_fns\n\n#  define CC_RMS_NAM cc$rms_nam\n#  define FAB_NAM fab$l_nam\n#  define NAM_DID nam$w_did\n#  define NAM_DVI nam$t_dvi\n#  define NAM_ESA nam$l_esa\n#  define NAM_ESL nam$b_esl\n#  define NAM_ESS nam$b_ess\n#  define NAM_FID nam$w_fid\n#  define NAM_FNB nam$l_fnb\n#  define NAM_RSA nam$l_rsa\n#  define NAM_RSL nam$b_rsl\n#  define NAM_RSS nam$b_rss\n#  define NAM_MAXRSS NAM$C_MAXRSS\n#  define NAM_NOP nam$b_nop\n#  define NAM_M_EXP_DEV NAM$M_EXP_DEV\n#  define NAM_M_SYNCHK NAM$M_SYNCHK\n#  define NAM_B_DEV nam$b_dev\n#  define NAM_L_DEV nam$l_dev\n#  define NAM_B_DIR nam$b_dir\n#  define NAM_L_DIR nam$l_dir\n#  define NAM_B_NAME nam$b_name\n#  define NAM_L_NAME nam$l_name\n#  define NAM_B_TYPE nam$b_type\n#  define NAM_L_TYPE nam$l_type\n#  define NAM_B_VER nam$b_ver\n#  define NAM_L_VER nam$l_ver\n\n#endif /* def NAML$C_MAXRSS */\n\n\nstruct EB_header    /* Common header of extra block */\n{   ush tag;\n    ush size;\n    uch data[1];\n};\n\n#ifndef EB_HEADSIZE\n#  define EB_HEADSIZE 4\n#endif\n\n/*------ Old style Info-ZIP extra field definitions -----*/\n\n#if (!defined(VAXC) && !defined(_RMS_H) && !defined(__RMS_LOADED))\n\nstruct XAB {                    /* This definition may be skipped */\n    unsigned char xab$b_cod;\n    unsigned char xab$b_bln;\n    short int xabdef$$_fill_1;\n    char *xab$l_nxt;\n};\n\n#endif /* !VAXC && !_RMS_H && !__RMS_LOADED */\n\n#ifndef EB_IZVMS_BCMASK\n#  define EB_IZVMS_BCMASK   07  /* 3 bits for compression type */\n#endif\n#ifndef EB_IZVMS_BCSTOR\n#  define EB_IZVMS_BCSTOR   0   /*  Stored */\n#endif\n#ifndef EB_IZVMS_BC00\n#  define EB_IZVMS_BC00     1   /*  0byte -> 0bit compression */\n#endif\n#ifndef EB_IZVMS_BCDEFL\n#  define EB_IZVMS_BCDEFL   2   /*  Deflated */\n#endif\n\n/*\n *  Extra record format\n *  ===================\n *  signature       (2 bytes)   = 'I','M'\n *  size            (2 bytes)\n *  block signature (4 bytes)\n *  flags           (2 bytes)\n *  uncomprssed size(2 bytes)\n *  reserved        (4 bytes)\n *  data            ((size-12) bytes)\n *  ....\n */\n\nstruct IZ_block                 /* Extra field block header structure */\n{\n    ush sig;\n    ush size;\n    ulg bid;\n    ush flags;\n    ush length;\n    ulg reserved;\n    uch body[1];                /* The actual size is unknown */\n};\n\n/*\n *   Extra field signature and block signatures\n */\n\n#define IZ_SIGNATURE \"IM\"\n#define FABSIG  \"VFAB\"\n#define XALLSIG \"VALL\"\n#define XFHCSIG \"VFHC\"\n#define XDATSIG \"VDAT\"\n#define XRDTSIG \"VRDT\"\n#define XPROSIG \"VPRO\"\n#define XKEYSIG \"VKEY\"\n#define XNAMSIG \"VNAM\"\n#define VERSIG  \"VMSV\"\n\n/*\n *   Block sizes\n */\n\n#define FABL    (cc$rms_fab.fab$b_bln)\n#define RABL    (cc$rms_rab.rab$b_bln)\n#define XALLL   (cc$rms_xaball.xab$b_bln)\n#define XDATL   (cc$rms_xabdat.xab$b_bln)\n#define XFHCL   (cc$rms_xabfhc.xab$b_bln)\n#define XKEYL   (cc$rms_xabkey.xab$b_bln)\n#define XPROL   (cc$rms_xabpro.xab$b_bln)\n#define XRDTL   (cc$rms_xabrdt.xab$b_bln)\n#define XSUML   (cc$rms_xabsum.xab$b_bln)\n#define EXTBSL  4               /* Block signature length */\n#define RESL    8               /* Reserved 8 bytes */\n#define EXTHL   (EB_HEADSIZE+EXTBSL+RESL)\n\ntypedef unsigned char byte;\n\nstruct iosb\n{\n    ush status;\n    ush count;\n    ulg spec;\n};\n\n/*------------ PKWARE extra block definitions ----------*/\n\n/* Structure of PKWARE extra header */\n\n#ifdef VMS_ZIP\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __nostandard\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n\n#ifdef VMS_ORIGINAL_PK_LAYOUT\n/*  The original order of ATR fields in the PKZIP VMS-extra field leads\n *  to unaligned fields in the PK_info structure representing the\n *  extra field layout.  When compiled for Alpha AXP, this results in\n *  some performance (and code size) penalty.  It is not allowed to\n *  apply structure padding, since this is explicitely forbidden in\n *  the specification (APPNOTE.TXT) for the PK VMS extra field.\n */\ntypedef struct\n{\n    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];\n    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];\n    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];\n    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];\n    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];\n    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];\n    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];\n    ush tag_rn; ush len_rn;     ush  rn;\n    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];\n    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];\n    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];\n} PK_info_t;\n#else /* !VMS_ORIGINAL_PK_LAYOUT */\n/*  The Info-ZIP support for the PK VMS extra field uses a reordered\n *  field layout to achieve ``natural alignment'' of the PK_info structure\n *  members whenever possible.  This rearrangement does not violate the\n *  PK's VMS extra field specification and should not break any ``well\n *  behaving'' (PK)Unzip utility. (`Well behaving' means that (PK)Unzip\n *  should use the field tag to identify the ATR$ field rather than\n *  assuming a fixed order of ATR$ fields in the PK VMS extra field.)\n */\ntypedef struct\n{\n    ush tag_ra; ush len_ra;     byte ra[ATR$S_RECATTR];\n    ush tag_uc; ush len_uc;     byte uc[ATR$S_UCHAR];\n    ush tag_cd; ush len_cd;     byte cd[ATR$S_CREDATE];\n    ush tag_rd; ush len_rd;     byte rd[ATR$S_REVDATE];\n    ush tag_ed; ush len_ed;     byte ed[ATR$S_EXPDATE];\n    ush tag_bd; ush len_bd;     byte bd[ATR$S_BAKDATE];\n    ush tag_rn; ush len_rn;     ush  rn;\n    ush tag_ui; ush len_ui;     byte ui[ATR$S_UIC];\n    ush tag_fp; ush len_fp;     byte fp[ATR$S_FPRO];\n    ush tag_rp; ush len_rp;     byte rp[ATR$S_RPRO];\n    ush tag_jr; ush len_jr;     byte jr[ATR$S_JOURNAL];\n} PK_info_t;\n#endif /* ?VMS_ORIGINAL_PK_LAYOUT */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __standard\n#endif /* __DECC || __DECCXX */\n\n#endif /* VMS_ZIP */\n\n/* PKWARE \"VMS\" tag */\n#define PK_SIGNATURE        0x000C\n\n/* Total number of attributes to be saved */\n#define VMS_ATTR_COUNT  11\n#define VMS_MAX_ATRCNT  20\n\nstruct PK_field\n{\n    ush         tag;\n    ush         size;\n    byte        value[1];\n};\n\n#define PK_FLDHDR_SIZE  4\n\nstruct PK_header\n{\n    ush tag;\n    ush size;\n    ulg crc32;\n    byte data[1];\n};\n\n#define PK_HEADER_SIZE  8\n\nchar *vms_file_version( char *s);\n\n#endif /* !__vms_h */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vms_im.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  vms_im.c (zip) by Igor Mandrichenko    Version 2.2-2\n *\n *  Revision history:\n *  ...\n *  2.1-1       16-feb-1993     I.Mandrichenko\n *      Get file size from XABFHC and check bytes rest in file before\n *      reading.\n *  2.1-2       2-mar-1993      I.Mandrichenko\n *      Make code more standard\n *  2.2         21-jun-1993     I.Mandrichenko\n *      Free all allocated space, use more static storage.\n *      Use memcompress() from bits.c (deflation) for block compression.\n *      To revert to old compression method #define OLD_COMPRESS\n *  2.2-2       28-sep-1995     C.Spieler\n *      Reorganized code for easier maintance of the two incompatible\n *      flavours (IM style and PK style) VMS attribute support.\n *      Generic functions (common to both flavours) are now collected\n *      in a `wrapper' source file that includes one of the VMS attribute\n *      handlers.\n *  3.0         23-Oct-2004     Steven Schweda\n *      Changed to maintain compatibility with VMS_PK.C.  Note that\n *      reading with sys$read() prevents getting any data past EOF,\n *      regardless of appearances.  Moved the VMS_PK_EXTRA test into\n *      here from VMS.C to allow more general automatic dependency\n *      generation.\n *              17-Feb-2005     Steven Schweda\n *      Added support for ODS5 extended names.\n */\n\n#ifdef VMS                      /* For VMS only ! */\n\n#ifndef VMS_PK_EXTRA\n\n#define OLD_COMPRESS            /*To use old compression method define it.*/\n\n#ifdef VMS_ZIP\n#undef VMS_ZIP                  /* do NOT include PK style Zip definitions */\n#endif\n\n#include \"vms.h\"\n\n#ifndef __LIB$ROUTINES_LOADED\n#include <lib$routines.h>\n#endif\n\n#ifndef UTIL\n\n#define RET_ERROR 1\n#define RET_SUCCESS 0\n#define RET_EOF 0\n\n#define Kbyte 1024\n\ntypedef struct XAB *xabptr;\n\n/*\n *   Block sizes\n */\n\n#define EXTL0   ((FABL + EXTHL)+        \\\n                (XFHCL + EXTHL)+        \\\n                (XPROL + EXTHL)+        \\\n                (XDATL + EXTHL)+        \\\n                (XRDTL + EXTHL))\n\n#ifdef OLD_COMPRESS\n#define PAD     sizeof(uch)\n#else\n#define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */\n#endif\n\n#define PAD0    (5*PAD)                 /* Reserve space for the case when\n                                         *  compression fails */\nstatic int _compress(uch *from, uch *to, int size);\n#ifdef DEBUG\nstatic void dump_rms_block(uch *p);\n#endif /* DEBUG */\n\n/********************************\n *   Function set_extra_field   *\n ********************************/\n/*\n |   2004-11-11 SMS.\n |   Changed to use separate storage for ->extra and ->cextra.  Zip64\n |   processing may move (reallocate) one and not the other.\n */\n\nstatic uch *_compress_block(register struct IZ_block *to,\n                            uch *from, int size, char *sig);\nstatic int get_vms_version(char *verbuf, int len);\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n/*\n *      Get file VMS file attributes and store them into extent fields.\n *      Store VMS version also.\n *      On error leave z intact.\n */\n{\n    int status;\n    uch *xtra;\n    uch *cxtra;\n    uch *scan;\n    extent extra_l;\n    static struct FAB fab;\n    static struct NAM_STRUCT nam;\n    static struct XABSUM xabsum;\n    static struct XABFHC xabfhc;\n    static struct XABDAT xabdat;\n    static struct XABPRO xabpro;\n    static struct XABRDT xabrdt;\n    xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;\n    int nk, na;\n    int i;\n    int rc=RET_ERROR;\n    char verbuf[80];\n    int verlen = 0;\n\n    if (!vms_native)\n    {\n#ifdef USE_EF_UT_TIME\n       /*\n        *  A `portable' zipfile entry is created. Create an \"UT\" extra block\n        *  containing UNIX style modification time stamp in UTC, which helps\n        *  maintaining the `real' \"last modified\" time when the archive is\n        *  transfered across time zone boundaries.\n        */\n#  ifdef IZ_CHECK_TZ\n        if (!zp_tz_is_valid)\n            return ZE_OK;       /* skip silently if no valid TZ info */\n#  endif\n        if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)\n            return ZE_MEM;\n\n        if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)\n            return ZE_MEM;\n\n        /* Fill xtra[] with data. */\n        xtra[ 0] = 'U';\n        xtra[ 1] = 'T';\n        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */\n        xtra[ 3] = 0;\n        xtra[ 4] = EB_UT_FL_MTIME;\n        xtra[ 5] = (uch) (z_utim->mtime);\n        xtra[ 6] = (uch) (z_utim->mtime >> 8);\n        xtra[ 7] = (uch) (z_utim->mtime >> 16);\n        xtra[ 8] = (uch) (z_utim->mtime >> 24);\n\n        /* Copy xtra[] data into cxtra[]. */\n        memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1)));\n\n        /* Set sizes and pointers. */\n        z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1));\n        z->extra = (char *) xtra;\n        z->cextra = (char *) cxtra;\n\n#endif /* USE_EF_UT_TIME */\n\n        return RET_SUCCESS;\n    }\n\n    /*\n     *  Initialize RMS control blocks and link them\n     */\n\n    fab =    cc$rms_fab;\n    nam =    CC_RMS_NAM;\n    xabsum = cc$rms_xabsum;\n    xabdat = cc$rms_xabdat;\n    xabfhc = cc$rms_xabfhc;\n    xabpro = cc$rms_xabpro;\n    xabrdt = cc$rms_xabrdt;\n\n    fab.FAB_NAM = &nam;\n    fab.fab$l_xab = (char*)&xabsum;\n    /*\n     *  Open the file and read summary information.\n     */\n\n#ifdef NAML$C_MAXRSS\n\n    fab.fab$l_dna = (char *) -1;    /* Using NAML for default name. */\n    fab.fab$l_fna = (char *) -1;    /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = z->name;\n    FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( z->name);\n\n#ifdef NAML$M_OPEN_SPECIAL\n    /* 2007-02-28 SMS.\n     * If processing symlinks as symlinks (\"-y\"), then $OPEN the\n     * link, not the target file.\n     *\n     * (nam.naml$v_open_special gets us the symlink itself instead of\n     * its target.  fab.fab$v_bio is necessary to allow sys$open() to\n     * work.  Without it, you get status %x0001860c, \"%RMS-F-ORG,\n     * invalid file organization value\".)\n     */\n    if (linkput)\n    {\n        nam.naml$v_open_special = 1;\n        fab.fab$v_bio = 1;\n    }\n#endif /* def NAML$M_OPEN_SPECIAL */\n\n    status = sys$open(&fab);\n    if (ERR(status))\n    {\n#ifdef DEBUG\n        printf(\"set_extra_field: sys$open for file %s:\\n  error status = %d\\n\",\n               z->name, status);\n#endif\n        goto err_exit;\n    }\n\n    nk = xabsum.xab$b_nok;\n    na = xabsum.xab$b_noa;\n#ifdef DEBUG\n    printf(\"%d keys, %d alls\\n\", nk, na);\n#endif\n\n    /*\n     *  Allocate XABKEY and XABALL blocks and link them\n     */\n\n    xabfhc.xab$l_nxt = (char*)&xabdat;\n    xabdat.xab$l_nxt = (char*)&xabpro;\n    xabpro.xab$l_nxt = (char*)&xabrdt;\n    xabrdt.xab$l_nxt = NULL;\n\n    xab_chain = (xabptr)(&xabfhc);\n    last_xab  = (xabptr)(&xabrdt);\n\n#define INIT(ptr,size,type,init)     \\\n        if ( (ptr = (type *)malloc(size)) == NULL )     \\\n        {                                               \\\n              printf( \"set_extra_field: Insufficient memory.\\n\" );   \\\n                      goto err_exit;                    \\\n        }                                               \\\n        *(ptr) = (init);\n    /*\n     *  Allocate and initialize all needed XABKEYs and XABALLs\n     */\n    for (i = 0; i < nk; i++)\n    {\n        struct XABKEY *k;\n        INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey);\n        k->xab$b_ref = i;\n        if (last_xab != NULL)\n            last_xab->xab$l_nxt = (char*)k;\n        last_xab = (xabptr)k;\n    }\n    for (i = 0; i < na; i++)\n    {\n        struct XABALL *a;\n        INIT(a, XALLL, struct XABALL, cc$rms_xaball);\n        a->xab$b_aid = i;\n        if (last_xab != NULL)\n            last_xab->xab$l_nxt = (char*)a;\n        last_xab = (xabptr)a;\n    }\n\n    fab.fab$l_xab = (char*)xab_chain;\n#ifdef DEBUG\n    printf(\"Dump of XAB chain before $DISPLAY:\\n\");\n    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)\n        dump_rms_block((uch *)x);\n#endif\n    /*\n     *  Get information on the file structure etc.\n     */\n    status = sys$display(&fab, 0, 0);\n    if (ERR(status))\n    {\n#ifdef DEBUG\n        printf(\"set_extra_field: sys$display for file %s:\\n  error status = %d\\n\",\n               z->name, status);\n#endif\n        goto err_exit;\n    }\n\n#ifdef DEBUG\n    printf(\"\\nDump of XAB chain after $DISPLAY:\\n\");\n    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)\n        dump_rms_block((uch *)x);\n#endif\n\n    fab.fab$l_xab = NULL;  /* Keep XABs */\n    status = sys$close(&fab);\n    if (ERR(status))\n    {\n#ifdef DEBUG\n        printf(\"set_extra_field: sys$close for file %s:\\n  error status = %d\\n\",\n               z->name, status);\n#endif\n        goto err_exit;\n    }\n\n    extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);\n#ifndef OLD_COMPRESS\n    extra_l += PAD0 + (nk+na) * PAD;\n#endif\n\n    if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 )\n    {\n        extra_l += verlen + EXTHL;\n#ifndef OLD_COMPRESS\n        extra_l += PAD;\n#endif\n    }\n\n    if ((scan = xtra = (uch *) malloc( extra_l)) == (uch*)NULL)\n    {\n#ifdef DEBUG\n        printf(\n         \"set_extra_field: Insufficient memory to allocate extra L buffer\\n\");\n#endif\n        goto err_exit;\n    }\n\n    if ((cxtra = (uch *) malloc( extra_l)) == (uch*)NULL)\n    {\n#ifdef DEBUG\n        printf(\n         \"set_extra_field: Insufficient memory to allocate extra C buffer\\n\");\n#endif\n        goto err_exit;\n    }\n\n    if (verlen > 0)\n        scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf,\n                               verlen, VERSIG);\n\n    /*\n     *  Zero all unusable fields to improve compression\n     */\n    fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;\n    fab.fab$w_ifi = 0;\n    fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;\n    fab.fab$l_dna = NULL;\n    fab.fab$l_fna = NULL;\n    fab.fab$l_nam = NULL;\n#ifdef NAML$C_MAXRSS\n    fab.fab$l_naml = NULL;\n#endif /* def NAML$C_MAXRSS */\n    fab.fab$l_xab = NULL;\n\n#ifdef DEBUG\n    dump_rms_block( (uch *)&fab );\n#endif\n    scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG);\n    for (x = xab_chain; x != NULL;)\n    {\n        int bln;\n        char *sig;\n        xabptr next;\n\n        next = (xabptr)(x->xab$l_nxt);\n        x->xab$l_nxt = 0;\n\n        switch (x->xab$b_cod)\n        {\n            case XAB$C_ALL:\n                bln = XALLL;\n                sig = XALLSIG;\n                break;\n            case XAB$C_KEY:\n                bln = XKEYL;\n                sig = XKEYSIG;\n                break;\n            case XAB$C_PRO:\n                bln = XPROL;\n                sig = XPROSIG;\n                break;\n            case XAB$C_FHC:\n                bln = XFHCL;\n                sig = XFHCSIG;\n                break;\n            case XAB$C_DAT:\n                bln = XDATL;\n                sig = XDATSIG;\n                break;\n            case XAB$C_RDT:\n                bln = XRDTL;\n                sig = XRDTSIG;\n                break;\n            default:\n                bln = 0;\n                sig = 0L;\n                break;\n        }\n        if (bln > 0)\n            scan = _compress_block((struct IZ_block *)scan, (uch *)x,\n                                   bln, sig);\n        x = next;\n    }\n\n    /* Copy xtra[] data into cxtra[]. */\n    memcpy( cxtra, xtra, (scan- xtra));\n\n    /* Set sizes and pointers. */\n    z->cext = z->ext = scan- xtra;\n    z->extra = (char*) xtra;\n    z->cextra = (char*) cxtra;\n\n    rc = RET_SUCCESS;\n\nerr_exit:\n    /*\n     *  Give up all allocated blocks\n     */\n    for (x = (struct XAB *)xab_chain; x != NULL; )\n    {\n        struct XAB *next;\n        next = (xabptr)(x->xab$l_nxt);\n        if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY)\n            free(x);\n        x = next;\n    }\n    return rc;\n}\n\nstatic int get_vms_version(verbuf, len)\nchar *verbuf;\nint len;\n{\n    int i = SYI$_VERSION;\n    int verlen = 0;\n    struct dsc$descriptor version;\n    char *m;\n\n    version.dsc$a_pointer = verbuf;\n    version.dsc$w_length  = len - 1;\n    version.dsc$b_dtype   = DSC$K_DTYPE_B;\n    version.dsc$b_class   = DSC$K_CLASS_S;\n\n    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)\n        return 0;\n\n    /* Cut out trailing spaces \"V5.4-3   \" -> \"V5.4-3\" */\n    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)\n        --m;\n    *m = 0;\n\n    /* Cut out release number \"V5.4-3\" -> \"V5.4\" */\n    if ((m = strrchr(verbuf, '-')) != NULL)\n        *m = 0;\n    return strlen(verbuf) + 1;  /* Transmit ending 0 too */\n}\n\n#define CTXSIG ((ulg)('CtXx'))\n\ntypedef struct user_context\n{\n    ulg sig;\n    struct FAB *fab;\n    struct NAM_STRUCT *nam;\n    struct RAB *rab;\n    uzoff_t size;\n    uzoff_t rest;\n    int status;\n} Ctx, *Ctxptr;\n\nCtx init_ctx =\n{\n        CTXSIG,\n        NULL,\n        NULL,\n        NULL,\n        0L,\n        0L,\n        0\n};\n\n#define CTXL    sizeof(Ctx)\n#define CHECK_RAB(_r) ( (_r) != NULL &&                         \\\n                        (_r) -> rab$b_bid == RAB$C_BID &&       \\\n                        (_r) -> rab$b_bln == RAB$C_BLN &&       \\\n                        (_r) -> rab$l_ctx != 0         &&       \\\n                        (_r) -> rab$l_fab != NULL )\n\n\n#define BLOCK_BYTES 512\n\n/**************************\n *   Function vms_open    *\n **************************/\nstruct RAB *vms_open(name)\n    char *name;\n{\n    struct FAB *fab;\n    struct NAM_STRUCT *nam;\n    struct RAB *rab;\n    struct XABFHC *fhc;\n    Ctxptr ctx;\n\n    if ((fab = (struct FAB *) malloc(FABL)) == NULL)\n        return NULL;\n\n    if ((nam =\n     (struct NAM_STRUCT *) malloc( sizeof( struct NAM_STRUCT))) == NULL)\n    {\n        free(fab);\n        return NULL;\n    }\n\n    if ((rab = (struct RAB *) malloc(RABL)) == NULL)\n    {\n        free(fab);\n        free(nam);\n        return NULL;\n    }\n\n    if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)\n    {\n        free(fab);\n        free(nam);\n        free(rab);\n        return (struct RAB *)NULL;\n    }\n    if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)\n    {\n        free(fab);\n        free(nam);\n        free(rab);\n        free(fhc);\n        return (struct RAB *)NULL;\n    }\n    *fab = cc$rms_fab;\n    *nam = CC_RMS_NAM;\n    *rab = cc$rms_rab;\n    *fhc = cc$rms_xabfhc;\n\n    fab->FAB_NAM = nam;\n\n#ifdef NAML$C_MAXRSS\n\n    fab->fab$l_dna = (char *) -1;   /* Using NAML for default name. */\n    fab->fab$l_fna = (char *) -1;   /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNA = name;\n    FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNS = strlen( name);\n\n    fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;\n    fab->fab$l_xab = (char*)fhc;\n\n#ifdef NAML$M_OPEN_SPECIAL\n    /* 2007-02-28 SMS.\n     * If processing symlinks as symlinks (\"-y\"), then $OPEN the\n     * link, not the target file.  (Note that here the required\n     * fab->fab$v_bio flag was set above.)\n     */\n    if (linkput)\n    {\n        nam->naml$v_open_special = 1;\n    }\n#endif /* def NAML$M_OPEN_SPECIAL */\n\n    if (ERR(sys$open(fab)))\n    {\n        sys$close(fab);\n        free(fab);\n        free(nam);\n        free(rab);\n        free(fhc);\n        free(ctx);\n        return (struct RAB *)NULL;\n    }\n\n    rab->rab$l_fab = fab;\n    rab->rab$l_rop = RAB$M_BIO;\n\n    if (ERR(sys$connect(rab)))\n    {\n        sys$close(fab);\n        free(fab);\n        free(nam);\n        free(rab);\n        free(ctx);\n        return (struct RAB *)NULL;\n    }\n\n    *ctx = init_ctx;\n    ctx->fab = fab;\n    ctx->nam = nam;\n    ctx->rab = rab;\n\n    if (fhc->xab$l_ebk == 0)\n    {\n        /* Only known size is all allocated blocks.\n           (This occurs with a zero-length file, for example.)\n        */\n        ctx->size =\n        ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES;\n    }\n    else\n    {\n        /* Store normal (used) size in ->size.\n           If only one -V, store normal (used) size in ->rest.\n           If -VV, store allocated-blocks size in ->rest.\n        */\n        ctx->size =\n         (((uzoff_t) fhc->xab$l_ebk)- 1)* BLOCK_BYTES+ fhc->xab$w_ffb;\n        if (vms_native < 2)\n            ctx->rest = ctx->size;\n        else\n            ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES;\n    }\n\n    free(fhc);\n    fab->fab$l_xab = NULL;\n    rab->rab$l_ctx = (unsigned) ctx;\n    return rab;\n}\n\n/**************************\n *   Function vms_close   *\n **************************/\nint vms_close(rab)\n    struct RAB *rab;\n{\n    struct FAB *fab;\n    struct NAM_STRUCT *nam;\n    Ctxptr ctx;\n\n    if (!CHECK_RAB(rab))\n        return RET_ERROR;\n    fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;\n    nam = (ctx = (Ctxptr)(rab->rab$l_ctx))->nam;\n    sys$close(fab);\n\n    free(fab);\n    free(nam);\n    free(rab);\n    free(ctx);\n\n    return RET_SUCCESS;\n}\n\n/**************************\n *   Function vms_rewind  *\n **************************/\nint vms_rewind(rab)\n    struct RAB *rab;\n{\n    Ctxptr ctx;\n\n    int status;\n    if (!CHECK_RAB(rab))\n        return RET_ERROR;\n\n    ctx = (Ctxptr) (rab->rab$l_ctx);\n    if (ERR(status = sys$rewind(rab)))\n    {\n        ctx->status = status;\n        return RET_ERROR;\n    }\n\n    ctx->status = 0;\n    ctx->rest = ctx->size;\n\n    return RET_SUCCESS;\n}\n\n\n#define KByte (2* BLOCK_BYTES)\n#define MAX_READ_BYTES (32* KByte)\n\n/**************************\n *   Function vms_read    *\n **************************/\nsize_t vms_read(rab, buf, size)\nstruct RAB *rab;\nchar *buf;\nsize_t size;\n/*\n *      size must be greater or equal to 512 !\n */\n{\n    int status;\n    Ctxptr ctx;\n\n    ctx = (Ctxptr)rab->rab$l_ctx;\n\n    if (!CHECK_RAB(rab))\n        return 0;\n\n    if (ctx -> rest == 0)\n        return 0;               /* Eof */\n\n    /* If request is smaller than a whole block, fail.\n       This really should never happen.  (assert()?)\n    */\n    if (size < BLOCK_BYTES)\n        return 0;\n\n    /* 2004-09-27 SMS.\n       Code here now resembles low-level QIO code in VMS_PK.C, but I\n       doubt that sys$read() will actually get past the official EOF.\n    */\n\n    /* Adjust request size as appropriate. */\n    if (size > MAX_READ_BYTES)\n    {\n        /* Restrict request to MAX_READ_BYTES. */\n        size = MAX_READ_BYTES;\n    }\n    else\n    {\n        /* Round odd-ball request up to the next whole block.\n           This really should never happen.  (assert()?)\n        */\n        size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);\n    }\n\n    /* Reduce \"size\" when next (last) read would overrun the EOF,\n       but never below one byte (so we'll always get a nice EOF).\n    */\n    if (size > ctx->rest)\n        size = ctx->rest;\n    if (size == 0)\n        size = 1;\n\n    rab->rab$l_ubf = buf;\n    rab->rab$w_usz = size;\n    status = sys$read(rab);\n\n    if (!ERR(status) && rab->rab$w_rsz > 0)\n    {\n        ctx -> status = 0;\n        ctx -> rest -= rab->rab$w_rsz;\n        return rab->rab$w_rsz;\n    }\n    else\n    {\n        ctx->status = (status==RMS$_EOF ? 0:status);\n        if (status == RMS$_EOF)\n                ctx -> rest = 0;\n        return 0;\n    }\n}\n\n/**************************\n *   Function vms_error   *\n **************************/\nint vms_error(rab)\n    struct RAB *rab;\n{\n    if (!CHECK_RAB(rab))\n        return RET_ERROR;\n    return ((Ctxptr) (rab->rab$l_ctx))->status;\n}\n\n\n#ifdef DEBUG\nstatic void dump_rms_block(p)\n    uch *p;\n{\n    uch bid, len;\n    int err;\n    char *type;\n    char buf[132];\n    int i;\n\n    err = 0;\n    bid = p[0];\n    len = p[1];\n    switch (bid)\n    {\n        case FAB$C_BID:\n            type = \"FAB\";\n            break;\n        case XAB$C_ALL:\n            type = \"xabALL\";\n            break;\n        case XAB$C_KEY:\n            type = \"xabKEY\";\n            break;\n        case XAB$C_DAT:\n            type = \"xabDAT\";\n            break;\n        case XAB$C_RDT:\n            type = \"xabRDT\";\n            break;\n        case XAB$C_FHC:\n            type = \"xabFHC\";\n            break;\n        case XAB$C_PRO:\n            type = \"xabPRO\";\n            break;\n        default:\n            type = \"Unknown\";\n            err = 1;\n            break;\n    }\n    printf(\"Block @%08X of type %s (%d).\", p, type, bid);\n    if (err)\n    {\n        printf(\"\\n\");\n        return;\n    }\n    printf(\" Size = %d\\n\", len);\n    printf(\" Offset - Hex - Dec\\n\");\n    for (i = 0; i < len; i += 8)\n    {\n        int j;\n\n        printf(\"%3d - \", i);\n        for (j = 0; j < 8; j++)\n            if (i + j < len)\n                printf(\"%02X \", p[i + j]);\n            else\n                printf(\"   \");\n        printf(\" - \");\n        for (j = 0; j < 8; j++)\n            if (i + j < len)\n                printf(\"%03d \", p[i + j]);\n            else\n                printf(\"    \");\n        printf(\"\\n\");\n    }\n}\n#endif /* DEBUG */\n\n#ifdef OLD_COMPRESS\n# define BC_METHOD      EB_IZVMS_BC00\n# define        COMP_BLK(to,tos,from,froms) _compress( from,to,froms )\n#else\n# define BC_METHOD      EB_IZVMS_BCDEFL\n# define        COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)\n#endif\n\nstatic uch *_compress_block(to,from,size,sig)\nregister struct IZ_block *to;\nuch *from;\nint size;\nchar *sig;\n{\n        ulg cl;\n        to -> sig =  *(ush*)IZ_SIGNATURE;\n        to -> bid =       *(ulg*)(sig);\n        to -> flags =           BC_METHOD;\n        to -> length =  size;\n#ifdef DEBUG\n        printf(\"\\nmemcompr(%d,%d,%d,%d)\\n\",&(to->body[0]),size+PAD,from,size);\n#endif\n        cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );\n#ifdef DEBUG\n        printf(\"Compressed to %d\\n\",cl);\n#endif\n        if (cl >= size)\n        {\n                memcpy(&(to->body[0]), from, size);\n                to->flags = EB_IZVMS_BCSTOR;\n                cl = size;\n#ifdef DEBUG\n                printf(\"Storing block...\\n\");\n#endif\n        }\n        return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + EB_HEADSIZE;\n}\n\n#define NBITS 32\n\nstatic int _compress(from,to,size)\nuch *from,*to;\nint size;\n{\n    int off=0;\n    ulg bitbuf=0;\n    int bitcnt=0;\n    int i;\n\n#define _BIT(val,len)   {                       \\\n        if (bitcnt + (len) > NBITS)             \\\n            while(bitcnt >= 8)                  \\\n            {                                   \\\n                to[off++] = (uch)bitbuf;        \\\n                bitbuf >>= 8;                   \\\n                bitcnt -= 8;                    \\\n            }                                   \\\n        bitbuf |= ((ulg)(val))<<bitcnt;         \\\n        bitcnt += len;                          \\\n    }\n\n#define _FLUSH  {                               \\\n            while(bitcnt>0)                     \\\n            {                                   \\\n                to[off++] = (uch)bitbuf;        \\\n                bitbuf >>= 8;                   \\\n                bitcnt -= 8;                    \\\n            }                                   \\\n        }\n\n    for (i=0; i<size; i++)\n    {\n        if (from[i])\n        {\n                _BIT(1,1);\n                _BIT(from[i],8);\n        }\n        else\n            _BIT(0,1);\n    }\n    _FLUSH;\n    return off;\n}\n\n#endif /* !UTIL */\n\n#endif /* ndef VMS_PK_EXTRA */\n\n#endif /* VMS */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vms_msg_gen.c",
    "content": "/*\n * VMS Message Source File Generator.\n *\n * 2007-01-29 SMS.\n *\n * Generates a VMS error message source file from data in \"ziperr.h\".\n *\n * On a VMS system, the standard builders should do the work.  On a\n * non-VMS system:\n *\n *    cc -I. vms/vms_msg_gen.c -o vms_msg_gen\n *    ./vms_msg_gen > vms/zip_msg.msg\n *    rm ./vms_msg_gen\n */\n\n#include <stdio.h>\n#include <string.h>\n\n#define GLOBALS         /* Include data for ziperrors[] in ziperr.h. */\n#include \"ziperr.h\"\n\nmain()\n{\n    int base_prev;\n    int code_vms;\n    int code_zip;\n    int i;\n\n    char *sev_str[ 8] = {\n     \"/WARNING\",\n     \"/SUCCESS\",\n     \"/ERROR\",\n     \"/INFORMATIONAL\",\n     \"/FATAL\",\n     \"/??????\",\n     \"/???????\",\n     \"/????????\"\n    };\n\n    char *text1[] = {\n\"!    VMS Error Message Source File for Zip\",\n\"!\",\n\"! Because the facility code was formally assigned by HP, the .FACILITY\",\n\"! directive below specifies /SYSTEM.  Because the messages are, in\",\n\"! general, specific to Zip, this file is not compiled with /SHARED.\",\n\"! For example:\",\n\"!\",\n\"!    MESSAGE /OBJECT = [.dest]ZIP_MSG.OBJ /NOSYMBOLS [.VMS]ZIP_MSG.MSG\",\n\"!\",\n\"!    LINK /SHAREABLE = [.dest]ZIP_MSG.EXE [.dest]ZIP_MSG.OBJ\",\n\"!\",\n\"!-----------------------------------------------------------------------\",\n\"\",\n\".TITLE  Info-ZIP Zip Error Messages\",\n\".FACILITY IZ_ZIP, 1955 /SYSTEM\",\nNULL                                            /* End-of-text marker. */\n};\n\n    /* Initialize the .BASE counter. */\n    base_prev = -2;\n\n    /* Put out the header text. */\n    for (i = 0; text1[ i] != NULL; i++)\n    {\n        printf( \"%s\\n\", text1[ i]);\n    }\n    printf( \".IDENT '%s'\\n\", VMS_MSG_IDENT);\n    printf( \"\\n\");\n\n    /* Put out the error messages. */\n    for (code_zip = 0; code_zip <= ZE_MAXERR; code_zip++)\n    {\n        if ((ziperrors[ code_zip].string != NULL) &&\n         (strlen(ziperrors[ code_zip].string) != 0))\n        {\n            code_vms = 2* code_zip;     /* 4-bit left-shift, not 3. */\n            if (code_vms != base_prev+ 1)\n            {\n                printf( \".BASE %d\\n\", code_vms);\n            }\n            printf( \"%-7s %-13s <%s>\\n\",\n             ziperrors[ code_zip].name,\n             sev_str[ ziperrors[ code_zip].severity & 0x07],\n             ziperrors[ code_zip].string);\n            base_prev = code_vms;\n        }\n    }\n    /* Put out the .END directive. */\n    printf( \"\\n\");\n    printf( \".END\\n\");\n}\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vms_pk.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *    vms_pk.c  by Igor Mandrichenko\n *\n *    version 2.0       20-Mar-1993\n *                      Generates PKWARE version of VMS attributes\n *                      extra field according to appnote 2.0.\n *                      Uses low level QIO-ACP interface.\n *    version 2.0-1     10-Apr-1993\n *                      Save ACLs\n *    version 2.1       24-Aug-1993\n *                      By default produce 0x010C extra record ID instead of\n *                      PKWARE's 0x000C. The format is mostly compatible with\n *                      PKWARE.\n *                      Incompatibility (?): zip produces multiple ACE\n *                      fields.\n *    version 2.1-1     Clean extra fields in vms_get_attributes().\n *                      Fixed bug with EOF.\n *    version 2.1-2     15-Sep-1995, Chr. Spieler\n *                      Removed extra fields cleanup from vms_get_attributes().\n *                      This is now done in zipup.c\n *                      Modified (according to UnZip's vms.[ch]) the fib stuff\n *                      for DEC C (AXP,VAX) support.\n *    version 2.2       28-Sep-1995, Chr. Spieler\n *                      Reorganized code for easier maintance of the two\n *                      incompatible flavours (IM style and PK style) VMS\n *                      attribute support.  Generic functions (common to\n *                      both flavours) are now collected in a `wrapper'\n *                      source file that includes one of the VMS attribute\n *                      handlers.\n *                      Made extra block header conforming to PKware's\n *                      specification (extra block header has a length\n *                      of four bytes, two bytes for a signature, and two\n *                      bytes for the length of the block excluding this\n *                      header.\n *    version 2.2-1     19-Oct-1995, Chr. Spieler\n *                      Fixed bug in CRC calculation.\n *                      Use official PK VMS extra field id.\n *    version 2.2-2     21-Nov-1997, Chr. Spieler\n *                      Fixed bug in vms_get_attributes() for directory\n *                      entries (access to uninitialized ioctx record).\n *                      Removed unused second arg for vms_open().\n *    version 2.2-3     04-Apr-1999, Chr. Spieler\n *                      Changed calling interface of vms_get_attributes()\n *                      to accept a void pointer as first argument.\n *    version 2.2-4     26-Jan-2002, Chr. Spieler\n *                      Modified vms_read() to handle files larger than 2GByte\n *                      (up to size limit of \"unsigned long\", resp. 4GByte).\n *    version 3.0       20-Oct-2004, Steven Schweda.\n *                      Changed vms_read() to read all the allocated\n *                      blocks in a file, for sure.  Changed the default\n *                      chunk size from 16K to 32K.  Changed to use the\n *                      new typedef for the ioctx structure.  Moved the\n *                      VMS_PK_EXTRA test into here from VMS.C to allow\n *                      more general automatic dependency generation.\n *                      08-Feb-2005, SMS.\n *                      Changed to accomodate ODS5 extended file names:\n *                      NAM structure -> NAM[L], and so on.  (VMS.H.)\n *                      Added some should-never-appear error messages in\n *                      vms_open().\n */\n\n#ifdef VMS                      /* For VMS only ! */\n\n#ifdef VMS_PK_EXTRA\n\n#include <ssdef.h>\n\n#ifndef VMS_ZIP\n#define VMS_ZIP\n#endif\n\n#include \"crc32.h\"\n#include \"vms.h\"\n#include \"vmsdefs.h\"\n\n#ifndef ERR\n#define ERR(x) (((x)&1)==0)\n#endif\n\n#ifndef NULL\n#define NULL (void*)(0L)\n#endif\n\n#ifndef UTIL\n\nstatic PK_info_t PK_def_info =\n{\n        ATR$C_RECATTR,  ATR$S_RECATTR,  {0},\n        ATR$C_UCHAR,    ATR$S_UCHAR,    {0},\n        ATR$C_CREDATE,  ATR$S_CREDATE,  {0},\n        ATR$C_REVDATE,  ATR$S_REVDATE,  {0},\n        ATR$C_EXPDATE,  ATR$S_EXPDATE,  {0},\n        ATR$C_BAKDATE,  ATR$S_BAKDATE,  {0},\n        ATR$C_ASCDATES, sizeof(ush),    0,\n        ATR$C_UIC,      ATR$S_UIC,      {0},\n        ATR$C_FPRO,     ATR$S_FPRO,     {0},\n        ATR$C_RPRO,     ATR$S_RPRO,     {0},\n        ATR$C_JOURNAL,  ATR$S_JOURNAL,  {0}\n};\n\n/* File description structure for Zip low level I/O */\ntypedef struct\n{\n    struct iosb         iosb;\n    long                vbn;\n    uzoff_t             size;\n    uzoff_t             rest;\n    int                 status;\n    ush                 chan;\n    ush                 chan_pad;       /* alignment member */\n    long                acllen;\n    uch                 aclbuf[ATR$S_READACL];\n    PK_info_t           PKi;\n} ioctx_t;\n\n\n/* Forward declarations of public functions: */\nioctx_t *vms_open(char *file);\nunsigned int  vms_read(register ioctx_t *ctx,\n                       register char *buf, register unsigned int size);\nint  vms_error(ioctx_t *ctx);\nint  vms_rewind(ioctx_t *ctx);\nint  vms_get_attributes(ioctx_t *ctx, struct zlist far *z,\n                        iztimes *z_utim);\nint  vms_close(ioctx_t *ctx);\n\n\n#define BLOCK_BYTES 512\n\n\n/*---------------*\n |  vms_open()   |\n *---------------*\n |  This routine opens file for reading fetching its attributes.\n |  Returns pointer to file description structure.\n */\n\nioctx_t *vms_open(file)\nchar *file;\n{\n    static struct atrdef        Atr[VMS_MAX_ATRCNT+1];\n    static struct NAM_STRUCT    Nam;\n    static struct fibdef        Fib;\n    static struct dsc$descriptor FibDesc =\n        {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};\n    static struct dsc$descriptor_s DevDesc =\n        {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.NAM_DVI[1]};\n    static char EName[NAM_MAXRSS];\n    static char RName[NAM_MAXRSS];\n\n    struct FAB Fab;\n    register ioctx_t *ctx;\n    register struct fatdef *fat;\n    int status;\n    int i;\n    ulg efblk;\n    ulg hiblk;\n\n    if ( (ctx=(ioctx_t *)malloc(sizeof(ioctx_t))) == NULL )\n        return NULL;\n    ctx -> PKi = PK_def_info;\n\n#define FILL_REQ(ix,id,b)   {       \\\n    Atr[ix].atr$l_addr = GVTC &(b);      \\\n    Atr[ix].atr$w_type = (id);      \\\n    Atr[ix].atr$w_size = sizeof(b); \\\n}\n\n    FILL_REQ(0, ATR$C_RECATTR,  ctx->PKi.ra);\n    FILL_REQ(1, ATR$C_UCHAR,    ctx->PKi.uc);\n    FILL_REQ(2, ATR$C_REVDATE,  ctx->PKi.rd);\n    FILL_REQ(3, ATR$C_EXPDATE,  ctx->PKi.ed);\n    FILL_REQ(4, ATR$C_CREDATE,  ctx->PKi.cd);\n    FILL_REQ(5, ATR$C_BAKDATE,  ctx->PKi.bd);\n    FILL_REQ(6, ATR$C_ASCDATES, ctx->PKi.rn);\n    FILL_REQ(7, ATR$C_JOURNAL,  ctx->PKi.jr);\n    FILL_REQ(8, ATR$C_RPRO,     ctx->PKi.rp);\n    FILL_REQ(9, ATR$C_FPRO,     ctx->PKi.fp);\n    FILL_REQ(10,ATR$C_UIC,      ctx->PKi.ui);\n    FILL_REQ(11,ATR$C_ACLLENGTH,ctx->acllen);\n    FILL_REQ(12,ATR$C_READACL,  ctx->aclbuf);\n\n    Atr[13].atr$w_type = 0;     /* End of ATR list */\n    Atr[13].atr$w_size = 0;\n    Atr[13].atr$l_addr = GVTC NULL;\n\n    /* Initialize RMS structures.  We need a NAM[L] to retrieve the FID. */\n    Fab = cc$rms_fab;\n    Nam = CC_RMS_NAM;\n    Fab.FAB_NAM = &Nam; /* FAB has an associated NAM[L]. */\n\n#ifdef NAML$C_MAXRSS\n\n    Fab.fab$l_dna =(char *) -1;         /* Using NAML for default name. */\n    Fab.fab$l_fna = (char *) -1;        /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n    FAB_OR_NAML( Fab, Nam).FAB_OR_NAML_FNA = file ;     /* File name. */\n    FAB_OR_NAML( Fab, Nam).FAB_OR_NAML_FNS = strlen(file);\n    Nam.NAM_ESA = EName; /* expanded filename */\n    Nam.NAM_ESS = sizeof(EName);\n    Nam.NAM_RSA = RName; /* resultant filename */\n    Nam.NAM_RSS = sizeof(RName);\n\n    /* Do $PARSE and $SEARCH here. */\n    status = sys$parse(&Fab);\n\n    if (!(status & 1))\n    {\n        fprintf( stderr,\n         \" vms_open(): $parse sts = %%x%08x.\\n\", status);\n        return NULL;\n    }\n\n#ifdef NAML$M_OPEN_SPECIAL\n    /* 2007-02-28 SMS.\n     * If processing symlinks as symlinks (\"-y\"), then $SEARCH for the\n     * link, not the target file.\n     */\n    if (linkput)\n    {\n        Nam.naml$v_open_special = 1;\n    }\n#endif /* def NAML$M_OPEN_SPECIAL */\n\n    /* Search for the first file.  If none, signal error. */\n    status = sys$search(&Fab);\n\n    if (!(status & 1))\n    {\n        fprintf( stderr,\n         \" vms_open(): $search sts = %%x%08x.\\n\", status);\n        return NULL;\n    }\n\n    /* Initialize Device name length.  Note that this points into the\n       NAM[L] to get the device name filled in by the $PARSE, $SEARCH\n       services.\n    */\n    DevDesc.dsc$w_length = Nam.NAM_DVI[0];\n\n    status = sys$assign(&DevDesc,&ctx->chan,0,0);\n\n    if (!(status & 1))\n    {\n        fprintf( stderr,\n         \" vms_open(): $assign sts = %%x%08x.\\n\", status);\n        return NULL;\n    }\n\n    /* Move the FID (and not the DID) into the FIB.\n       2005=02-08 SMS.\n       Note that only the FID is needed, not the DID, and not the file\n       name.  Setting these other items causes failures on ODS5.\n    */\n    Fib.FIB$L_ACCTL = FIB$M_NOWRITE;\n\n    for (i = 0; i < 3; i++)\n    {\n        Fib.FIB$W_FID[ i] = Nam.NAM_FID[ i];\n        Fib.FIB$W_DID[ i] = 0;\n    }\n\n    /* Use the IO$_ACCESS function to return info about the file. */\n    status = sys$qiow( 0, ctx->chan,\n     (IO$_ACCESS| IO$M_ACCESS), &ctx->iosb, 0, 0,\n     &FibDesc, 0, 0, 0, Atr, 0);\n\n    if (ERR(status) || ERR(status = ctx->iosb.status))\n    {\n        vms_close(ctx);\n        fprintf( stderr,\n         \" vms_open(): $qiow (access) sts = %%x%08x, iosb sts = %%x%08x.\\n\",\n         status, ctx->iosb.status);\n        return NULL;\n    }\n\n    fat = (struct fatdef *)&(ctx -> PKi.ra);\n\n#define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )\n\n    efblk = SWAPW(fat->fat$l_efblk);\n    hiblk = SWAPW(fat->fat$l_hiblk);\n\n    if (efblk == 0)\n    {\n        /* Only known size is all allocated blocks.\n           (This occurs with a zero-length file, for example.)\n        */\n        ctx -> size =\n        ctx -> rest = ((uzoff_t) hiblk)* BLOCK_BYTES;\n    }\n    else\n    {\n        /* Store normal (used) size in ->size.\n           If only one -V, store normal (used) size in ->rest.\n           If multiple -V, store allocated-blocks size in ->rest.\n        */\n        ctx -> size =\n         (((uzoff_t) efblk)- 1)* BLOCK_BYTES+ fat -> fat$w_ffbyte;\n\n        if (vms_native < 2)\n            ctx -> rest = ctx -> size;\n        else\n            ctx -> rest = ((uzoff_t) hiblk)* BLOCK_BYTES;\n    }\n\n    ctx -> status = SS$_NORMAL;\n    ctx -> vbn = 1;\n    return ctx;\n}\n\n\n#define KByte (2* BLOCK_BYTES)\n#define MAX_READ_BYTES (32* KByte)\n\n/*----------------*\n |   vms_read()   |\n *----------------*\n |   Reads file in (multi-)block-sized chunks into the buffer.\n |   Stops on EOF. Returns number of bytes actually read.\n |   Note: This function makes no sense (and will error) if the buffer\n |   size (\"size\") is not a multiple of the disk block size (512).\n */\n\nsize_t vms_read( ctx, buf, size)\nioctx_t *ctx;\nchar *buf;\nsize_t size;\n{\n    int act_cnt;\n    uzoff_t rest_rndup;\n    int status;\n    size_t bytes_read = 0;\n\n    /* If previous read hit EOF, fail early. */\n    if (ctx -> status == SS$_ENDOFFILE)\n        return 0;               /* EOF. */\n\n    /* If no more expected to be read, fail early. */\n    if (ctx -> rest == 0)\n        return 0;               /* Effective EOF. */\n\n    /* If request is smaller than a whole block, fail.\n       This really should never happen.  (assert()?)\n    */\n    if (size < BLOCK_BYTES)\n        return 0;\n\n    /* Note that on old VMS VAX versions (like V5.5-2), QIO[W] may fail\n       with status %x0000034c (= %SYSTEM-F-IVBUFLEN, invalid buffer\n       length) when size is not a multiple of 512.  Thus the requested\n       size is boosted as needed, but the IOSB byte count returned is\n       reduced when it exceeds the actual bytes remaining (->rest).\n    */\n\n    /* Adjust request size as appropriate. */\n    if (size > MAX_READ_BYTES)\n    {\n        /* Restrict request to MAX_READ_BYTES. */\n        size = MAX_READ_BYTES;\n    }\n    else\n    {\n        /* Round odd-ball request up to the next whole block.\n           This really should never happen.  (assert()?)\n        */\n        size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);\n    }\n    rest_rndup = (ctx -> rest+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1);\n\n    /* Read (QIOW) until error or \"size\" bytes have been read. */\n    do\n    {\n        /* Reduce \"size\" when next (last) read would overrun the EOF,\n           but never below one block (so we'll always get a nice EOF).\n        */\n        if (size > rest_rndup)\n            size = rest_rndup;\n\n        status = sys$qiow( 0, ctx->chan, IO$_READVBLK,\n            &ctx->iosb, 0, 0,\n            buf, size, ctx->vbn, 0, 0, 0);\n\n        /* If initial status was good, use final status. */\n        if ( !ERR(status) )\n                status = ctx->iosb.status;\n\n        if ( !ERR(status) || status == SS$_ENDOFFILE )\n        {\n            act_cnt = ctx->iosb.count;\n            /* Ignore whole-block boost when remainder is smaller. */\n            if (act_cnt > ctx->rest)\n            {\n                act_cnt = ctx->rest;\n                status = SS$_ENDOFFILE;\n            }\n            /* Adjust counters/pointers according to delivered bytes. */\n            size -= act_cnt;\n            buf += act_cnt;\n            bytes_read += act_cnt;\n            ctx->vbn += ctx->iosb.count/ BLOCK_BYTES;\n        }\n\n    } while ( !ERR(status) && (size > 0) );\n\n    if (!ERR(status))\n    {\n        /* Record any successful status as SS$_NORMAL. */\n        ctx -> status = SS$_NORMAL;\n    }\n    else if (status == SS$_ENDOFFILE)\n    {\n        /* Record EOF as SS$_ENDOFFILE.  (Ignore error status codes?) */\n        ctx -> status = SS$_ENDOFFILE;\n    }\n\n    /* Decrement bytes-to-read.  Return the total bytes read. */\n    ctx -> rest -= bytes_read;\n\n    return bytes_read;\n}\n\n/*-----------------*\n |   vms_error()   |\n *-----------------*\n |   Returns whether last operation on the file caused an error\n */\n\nint vms_error(ctx)\nioctx_t *ctx;\n{   /* EOF is not actual error */\n    return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);\n}\n\n/*------------------*\n |   vms_rewind()   |\n *------------------*\n |   Rewinds file to the beginning for the next vms_read().\n */\n\nint vms_rewind(ctx)\nioctx_t *ctx;\n{\n    ctx -> vbn = 1;\n    ctx -> rest = ctx -> size;\n    return 0;\n}\n\n/*--------------------------*\n |   vms_get_attributes()   |\n *--------------------------*\n |   Malloc a PKWARE extra field and fill with file attributes. Returns\n |   error number of the ZE_??? class.\n |   If the passed ioctx record \"FILE *\" pointer is NULL, vms_open() is\n |   called to fetch the file attributes.\n |   When `vms_native' is not set, a generic \"UT\" type timestamp extra\n |   field is generated instead.\n |\n |   2004-11-11 SMS.\n |   Changed to use separate storage for ->extra and ->cextra.  Zip64\n |   processing may move (reallocate) one and not the other.\n */\n\nint vms_get_attributes(ctx, z, z_utim)\nioctx_t *ctx;           /* Internal file control structure. */\nstruct zlist far *z;    /* Zip entry to compress. */\niztimes *z_utim;\n{\n    byte    *p;\n    byte    *xtra;\n    byte    *cxtra;\n    struct  PK_header    *h;\n    extent  l;\n    int     notopened;\n\n    if ( !vms_native )\n    {\n#ifdef USE_EF_UT_TIME\n        /*\n         *  A `portable' zipfile entry is created. Create an \"UT\" extra block\n         *  containing UNIX style modification time stamp in UTC, which helps\n         *  maintaining the `real' \"last modified\" time when the archive is\n         *  transfered across time zone boundaries.\n         */\n#  ifdef IZ_CHECK_TZ\n        if (!zp_tz_is_valid)\n            return ZE_OK;       /* skip silently if no valid TZ info */\n#  endif\n\n        if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)\n            return ZE_MEM;\n\n        if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)\n            return ZE_MEM;\n\n        /* Fill xtra[] with data. */\n        xtra[ 0] = 'U';\n        xtra[ 1] = 'T';\n        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */\n        xtra[ 3] = 0;\n        xtra[ 4] = EB_UT_FL_MTIME;\n        xtra[ 5] = (byte) (z_utim->mtime);\n        xtra[ 6] = (byte) (z_utim->mtime >> 8);\n        xtra[ 7] = (byte) (z_utim->mtime >> 16);\n        xtra[ 8] = (byte) (z_utim->mtime >> 24);\n\n        /* Copy xtra[] data into cxtra[]. */\n        memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1)));\n\n        /* Set sizes and pointers. */\n        z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1));\n        z->extra = (char*) xtra;\n        z->cextra = (char*) cxtra;\n\n#endif /* USE_EF_UT_TIME */\n\n        return ZE_OK;\n    }\n\n    notopened = (ctx == NULL);\n    if ( notopened && ((ctx = vms_open(z->name)) == NULL) )\n        return ZE_OPEN;\n\n    l = PK_HEADER_SIZE + sizeof(ctx->PKi);\n    if (ctx->acllen > 0)\n        l += PK_FLDHDR_SIZE + ctx->acllen;\n\n    if ((xtra = (uch *) malloc( l)) == NULL)\n        return ZE_MEM;\n\n    if ((cxtra = (uch *) malloc( l)) == NULL)\n        return ZE_MEM;\n\n    /* Fill xtra[] with data. */\n\n    h = (struct PK_header *) xtra;\n    h->tag = PK_SIGNATURE;\n    h->size = l - EB_HEADSIZE;\n    p = (h->data);\n\n    /* Copy default set of attributes */\n    memcpy(h->data, (char*)&(ctx->PKi), sizeof(ctx->PKi));\n    p += sizeof(ctx->PKi);\n\n    if ( ctx->acllen > 0 )\n    {\n        struct PK_field *f;\n\n        if (dosify)\n            zipwarn(\"file has ACL, may be incompatible with PKUNZIP\",\"\");\n\n        f = (struct PK_field *)p;\n        f->tag = ATR$C_ADDACLENT;\n        f->size = ctx->acllen;\n        memcpy((char *)&(f->value[0]), ctx->aclbuf, ctx->acllen);\n        p += PK_FLDHDR_SIZE + ctx->acllen;\n    }\n\n\n    h->crc32 = CRCVAL_INITIAL;                  /* Init CRC register */\n    h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);\n\n    /* Copy xtra[] data into cxtra[]. */\n    memcpy( cxtra, xtra, l);\n\n    /* Set sizes and pointers. */\n    z->ext = z->cext = l;\n    z->extra = (char *) xtra;\n    z->cextra = (char *) cxtra;\n\n    if (notopened)              /* close \"ctx\", if we have opened it here */\n        vms_close(ctx);\n\n    return ZE_OK;\n}\n\n\nint vms_close(ctx)\nioctx_t *ctx;\n{\n        sys$dassgn(ctx->chan);\n        free(ctx);\n        return 0;\n}\n\n#endif /* !_UTIL */\n\n#endif /* def VMS_PK_EXTRA */\n\n#endif /* VMS */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vmsdefs.h",
    "content": "/*\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vmsdefs.h\n\n  Contents of three header files from Joe\n  Meadows' FILE program.  Used by vmsmunch\n\n        06-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com\n                        Moved \"contents of three header files\" from\n                        VMSmunch.h to VMSdefs.h .\n\n        16-Sep-1995     Christian Spieler\n                        Added #pragma (no)member_alignment directives\n                        to achieve compatibility with DEC C and Alpha AXP\n\n        05-Oct-1995     Christian Spieler\n                        Revised fatdef, fchdef, fjndef to achieve closer\n                        compatibility with DEC's system include header files\n                        supplied with C version 4.0 and newer.\n\n        10-Oct-1995     Christian Spieler\n                        Use lowercase filenames for vms specific sources\n                        (VMSmunch.? -> vmsmunch.?, VMSdefs.h -> vmsdefs.h)\n\n        15-Dec-1995     Christian Spieler\n                        Removed the last \"tabs\" from the source.\n\n        24-Jun-1997     Onno van der Linden / Chr. Spieler\n                        Modifications to support the VMS port of GNU C 2.x.\n\n        27-Jul-1999     Chr. Spieler\n                        Added Info-ZIP copyright note for identification.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vmsdefs_h\n#define __vmsdefs_h 1\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __nostandard\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define __struct struct\n#define __union union\n#else\n#define __struct variant_struct\n#define __union variant_union\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#ifdef __cplusplus\n    extern \"C\" {\n#endif\n\n/*---------------------------------------------------------------------------\n    fatdef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FAT$K_LENGTH 32\n#define FAT$C_LENGTH 32\n#define FAT$S_FATDEF 32\n\nstruct fatdef {\n  __union  {\n    unsigned char fat$b_rtype;          /* record type                      */\n    __struct  {\n      unsigned fat$v_rtype : 4;         /* record type subfield             */\n      unsigned fat$v_fileorg : 4;       /* file organization                */\n    } fat$r_rtype_bits;\n  } fat$r_rtype_overlay;\n# define FAT$S_RTYPE 4\n# define FAT$V_RTYPE 0\n#   define FAT$C_UNDEFINED 0\n#   define FAT$C_FIXED 1\n#   define FAT$C_VARIABLE 2\n#   define FAT$C_VFC 3\n#   define FAT$C_STREAM 4\n#   define FAT$C_STREAMLF 5\n#   define FAT$C_STREAMCR 6\n# define FAT$S_FILEORG 4\n# define FAT$V_FILEORG 4\n#   define FAT$C_SEQUENTIAL 0\n#   define FAT$C_RELATIVE 1\n#   define FAT$C_INDEXED 2\n#   define FAT$C_DIRECT 3\n  __union  {\n    unsigned char fat$b_rattrib;        /* record attributes                */\n    __struct  {\n      unsigned fat$v_fortrancc : 1;\n      unsigned fat$v_impliedcc : 1;\n      unsigned fat$v_printcc : 1;\n      unsigned fat$v_nospan : 1;\n      unsigned fat$v_msbrcw : 1;\n    } fat$r_rattrib_bits;\n  } fat$r_rattrib_overlay;\n#   define FAT$V_FORTRANCC 0\n#   define FAT$M_FORTRANCC 1\n#   define FAT$V_IMPLIEDCC 1\n#   define FAT$M_IMPLIEDCC 2\n#   define FAT$V_PRINTCC 2\n#   define FAT$M_PRINTCC 4\n#   define FAT$V_NOSPAN 3\n#   define FAT$M_NOSPAN 8\n#   define FAT$V_MSBRCW 4\n#   define FAT$M_MSBRCW 16\n  unsigned short int fat$w_rsize;       /* record size in bytes             */\n  __union\n  {\n    unsigned long int fat$l_hiblk;      /* highest allocated VBN            */\n    __struct\n    {\n      unsigned short int fat$w_hiblkh;  /* high order word                  */\n      unsigned short int fat$w_hiblkl;  /* low order word                   */\n    } fat$r_hiblk_fields;\n  } fat$r_hiblk_overlay;\n  __union\n  {\n    unsigned long int fat$l_efblk;      /* end of file VBN                  */\n    __struct\n    {\n      unsigned short int fat$w_efblkh;  /* high order word                  */\n      unsigned short int fat$w_efblkl;  /* low order word                   */\n    } fat$r_efblk_fields;\n  } fat$r_efblk_overlay;\n  unsigned short int fat$w_ffbyte;      /* first free byte in EFBLK         */\n  unsigned char fat$b_bktsize;          /* bucket size in blocks            */\n  unsigned char fat$b_vfcsize;          /* # of control bytes in VFC record */\n  unsigned short int fat$w_maxrec;      /* maximum record size in bytes     */\n  unsigned short int fat$w_defext;      /* default extend quantity          */\n  unsigned short int fat$w_gbc;         /* global buffer count              */\n  char fat$fill[8];\n  unsigned short int fat$w_versions;\n};\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define fat$b_rtype fat$r_rtype_overlay.fat$b_rtype\n#define fat$v_rtype fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_rtype\n#define fat$v_fileorg fat$r_rtype_overlay.fat$r_rtype_bits.fat$v_fileorg\n#define fat$b_rattrib fat$r_rattrib_overlay.fat$b_rattrib\n#define fat$v_fortrancc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_fortrancc\n#define fat$v_impliedcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_impliedcc\n#define fat$v_printcc fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_printcc\n#define fat$v_nospan fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_nospan\n#define fat$v_msbrcw fat$r_rattrib_overlay.fat$r_rattrib_bits.fat$v_msbrcw\n#define fat$l_hiblk fat$r_hiblk_overlay.fat$l_hiblk\n#define fat$w_hiblkh fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkh\n#define fat$w_hiblkl fat$r_hiblk_overlay.fat$r_hiblk_fields.fat$w_hiblkl\n#define fat$l_efblk fat$r_efblk_overlay.fat$l_efblk\n#define fat$w_efblkh fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkh\n#define fat$w_efblkl fat$r_efblk_overlay.fat$r_efblk_fields.fat$w_efblkl\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#define __FATDEF_LOADED 1       /* prevent inclusion of DECC's fatdef.h */\n\n/*---------------------------------------------------------------------------\n    fchdef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FCH$V_BADACL 0x00B\n#define FCH$M_BADACL (1 << FCH$V_BADACL)\n#define FCH$V_BADBLOCK 0x00E\n#define FCH$M_BADBLOCK (1 << FCH$V_BADBLOCK)\n#define FCH$V_CONTIG 0x007\n#define FCH$M_CONTIG (1 << FCH$V_CONTIG)\n#define FCH$V_CONTIGB 0x005\n#define FCH$M_CONTIGB (1 << FCH$V_CONTIGB)\n#define FCH$V_DIRECTORY 0x00D\n#define FCH$M_DIRECTORY (1 << FCH$V_DIRECTORY)\n#define FCH$V_ERASE 0x011\n#define FCH$M_ERASE (1 << FCH$V_ERASE)\n#define FCH$V_LOCKED 0x006\n#define FCH$M_LOCKED (1 << FCH$V_LOCKED)\n#define FCH$V_MARKDEL 0x00F\n#define FCH$M_MARKDEL (1 << FCH$V_MARKDEL)\n#define FCH$V_NOBACKUP 0x001\n#define FCH$M_NOBACKUP (1 << FCH$V_NOBACKUP)\n#define FCH$V_NOCHARGE 0x010\n#define FCH$M_NOCHARGE (1 << FCH$V_NOCHARGE)\n#define FCH$V_READCHECK 0x003\n#define FCH$M_READCHECK (1 << FCH$V_READCHECK)\n#define FCH$V_SPOOL 0x00C\n#define FCH$M_SPOOL (1 << FCH$V_SPOOL)\n#define FCH$V_WRITCHECK 0x004\n#define FCH$M_WRITCHECK (1 << FCH$V_WRITCHECK)\n#define FCH$V_WRITEBACK 0x002\n#define FCH$M_WRITEBACK (1 << FCH$V_WRITEBACK)\n\nstruct fchdef  {\n  __union  {\n    int fch$$_fill_1;\n    __struct  {\n      unsigned fch$$_fill_31 : 8;\n      unsigned fch$v_vcc_state : 3;    /* VCC state bits              */\n      unsigned fch$$_fill_32 : 7;\n      unsigned fch$$_alm_state : 2;\n      unsigned fch$v_associated : 1;   /* ISO 9660 Associated file    */\n      unsigned fch$v_existence : 1;    /* ISO 9660 Existence file     */\n      unsigned fch$v_fill_6 : 2;\n    } fch$r_fill_1_chunks;\n    __struct  {\n      unsigned fch$v_wascontig : 1;\n      unsigned fch$v_nobackup : 1 ;\n      unsigned fch$v_writeback : 1;\n      unsigned fch$v_readcheck : 1;\n      unsigned fch$v_writcheck : 1;\n      unsigned fch$v_contigb : 1;\n      unsigned fch$v_locked : 1;\n      unsigned fch$v_contig : 1;\n      unsigned fch$$_fill_3 : 3;\n      unsigned fch$v_badacl : 1;\n      unsigned fch$v_spool : 1;\n      unsigned fch$v_directory : 1;\n      unsigned fch$v_badblock : 1;\n      unsigned fch$v_markdel : 1;\n      unsigned fch$v_nocharge : 1;\n      unsigned fch$v_erase : 1;\n      unsigned fch$$_fill_4 : 1;\n      unsigned fch$v_shelved : 1;\n      unsigned fch$v_scratch : 1;\n      unsigned fch$v_nomove : 1;\n      unsigned fch$v_noshelvable : 1;\n    } fch$r_fill_1_bits;\n  } fch$r_fch_union;\n};\n\n#if !(defined(__VAXC) || defined(VAXC)) || defined(__GNUC__)\n#define fch$v_vcc_state fch$r_fch_union.fch$r_fill_1_chunks.fch$v_vcc_state\n#define fch$v_associated fch$r_fch_union.fch$r_fill_1_chunks.fch$v_associated\n#define fch$v_existence fch$r_fch_union.fch$r_fill_1_chunks.fch$v_existence\n#define fch$v_wascontig fch$r_fch_union.fch$r_fill_1_bits.fch$v_wascontig\n#define fch$v_nobackup fch$r_fch_union.fch$r_fill_1_bits.fch$v_nobackup\n#define fch$v_writeback fch$r_fch_union.fch$r_fill_1_bits.fch$v_writeback\n#define fch$v_readcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_readcheck\n#define fch$v_writcheck fch$r_fch_union.fch$r_fill_1_bits.fch$v_writcheck\n#define fch$v_contigb fch$r_fch_union.fch$r_fill_1_bits.fch$v_contigb\n#define fch$v_locked fch$r_fch_union.fch$r_fill_1_bits.fch$v_locked\n#define fch$v_contig fch$r_fch_union.fch$r_fill_1_bits.fch$v_contig\n#define fch$v_badacl fch$r_fch_union.fch$r_fill_1_bits.fch$v_badacl\n#define fch$v_spool fch$r_fch_union.fch$r_fill_1_bits.fch$v_spool\n#define fch$v_directory fch$r_fch_union.fch$r_fill_1_bits.fch$v_directory\n#define fch$v_badblock fch$r_fch_union.fch$r_fill_1_bits.fch$v_badblock\n#define fch$v_markdel fch$r_fch_union.fch$r_fill_1_bits.fch$v_markdel\n#define fch$v_nocharge fch$r_fch_union.fch$r_fill_1_bits.fch$v_nocharge\n#define fch$v_erase fch$r_fch_union.fch$r_fill_1_bits.fch$v_erase\n#define fch$v_shelved fch$r_fch_union.fch$r_fill_1_bits.fch$v_shelved\n#define fch$v_scratch fch$r_fch_union.fch$r_fill_1_bits.fch$v_scratch\n#define fch$v_nomove fch$r_fch_union.fch$r_fill_1_bits.fch$v_nomove\n#define fch$v_noshelvable fch$r_fch_union.fch$r_fill_1_bits.fch$v_noshelvable\n#endif /* !(__VAXC || VAXC) || __GNUC__ */\n\n#define __FCHDEF_LOADED 1       /* prevent inclusion of DECC's fchdef.h */\n\n/*---------------------------------------------------------------------------\n    fjndef.h\n  ---------------------------------------------------------------------------*/\n\n/* This header file was created by Joe Meadows, and is not copyrighted\n   in any way. No guarantee is made as to the accuracy of the contents\n   of this header file. This header file was last modified on Sep. 22th,\n   1987. (Modified to include this statement) */\n\n#define FJN$M_ONLY_RU 1\n#define FJN$M_RUJNL 2\n#define FJN$M_BIJNL 4\n#define FJN$M_AIJNL 8\n#define FJN$M_ATJNL 16\n#define FJN$M_NEVER_RU 32\n#define FJN$M_JOURNAL_FILE 64\n#define FJN$S_FJNDEF 1\nstruct fjndef  {\n  unsigned fjn$v_only_ru : 1;\n  unsigned fjn$v_rujnl : 1;\n  unsigned fjn$v_bijnl : 1;\n  unsigned fjn$v_aijnl : 1;\n  unsigned fjn$v_atjnl : 1;\n  unsigned fjn$v_never_ru : 1;\n  unsigned fjn$v_journal_file : 1;\n  unsigned fjn$v_fill_7 : 1;\n} ;\n\n#define __FJNDEF_LOADED 1       /* prevent inclusion of DECC's fjndef.h */\n\n/*---------------------------------------------------------------------------*/\n\n#ifdef __cplusplus\n    }\n#endif\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __standard\n#endif /* __DECC || __DECCXX */\n\n#endif /* !__vmsdefs_h */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vmsmunch.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n# define module_name     VMSMUNCH\n# define module_version  \"V1.3-4\"\n#endif /* 0 */\n\n/*\n *  Modified by:\n *\n *    v1.3.1        O.v.d.Linden, C. Spieler            04-JUL-1998 14:35\n *            Modified check that decides on the type of definitions for\n *            FIB$W_FID etc. to support GNU C.\n *\n *    v1.3          Hunter Goatley                      14-SEP-1992 08:51\n *            Added definitions of FIB$W_FID, FIB$W_DID, and\n *            FIB$L_ACCTL to allow for the fact that fibdef\n *            contains variant_unions under Alpha.\n */\n/*---------------------------------------------------------------------------\n\n  vmsmunch.c                    version 1.2                     28 Apr 1992\n\n  This routine is a blatant and unrepentent appropriation of all the nasty\n  and difficult-to-do and complicated VMS shenanigans which Joe Meadows has\n  so magnificently captured in his FILE utility.  Not only that, it's even\n  allowed! (see below).  But let it be clear at the outset that Joe did all\n  the work; yea, verily, he is truly a godlike unit.\n\n  The appropriations and modifications herein were performed primarily by\n  him known as \"Cave Newt,\" although the Info-ZIP working group probably had\n  their fingers in it somewhere along the line.  The idea is to put the raw\n  power of Joe's original routine at the disposal of various routines used\n  by UnZip (and Zip, possibly), not least among them the utime() function.\n  Read on for details...\n\n        01-SEP-1994     Richard Levitte <levitte@e.kth.se>\n                        If one of the fields given to VMSmunch are NULL,\n                        do not update the corresponding daytime.\n\n        18-JUL-1994     Hunter Goatley <goathunter@WKU.EDU>\n                        Fixed IO$_ACCESS call.\n\n        18-Jul-1994     Richard Levitte levitte@e.kth.se\n                        Changed VMSmunch() to deassign the channel before\n                        returning when an error has occured.\n\n        02-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com\n                        Moved definition of VMStimbuf struct from here\n                        to vmsmunch.h\n  ---------------------------------------------------------------------------\n\n  Usage (i.e., \"interface,\" in geek-speak):\n\n     int VMSmunch( char *filename, int action, char *ptr );\n\n     filename   the name of the file on which to be operated, obviously\n     action     an integer which specifies what action to take\n     ptr        pointer to any extra item which may be needed (else NULL)\n\n  The possible values for the action argument are as follows:\n\n     GET_TIMES      get the creation and revision dates of filename; ptr\n                    must point to an empty VMStimbuf struct, as defined\n                    in vmsmunch.h\n                    (with room for at least 24 characters, including term.)\n     SET_TIMES      set the creation and revision dates of filename (utime\n                    option); ptr must point to a valid VMStimbuf struct,\n                    as defined in vmsmunch.h\n     GET_RTYPE      get the record type of filename; ptr must point to an\n                    integer which, on return, is set to the type (as defined\n                    in vmsdefs.h:  FAT$C_* defines)\n     CHANGE_RTYPE   change the record type to that specified by the integer\n                    to which ptr points; save the old record type (later\n                    saves overwrite earlier ones)\n     RESTORE_RTYPE  restore the record type to the previously saved value;\n                    or, if none, set it to \"fixed-length, 512-byte\" record\n                    format (ptr not used)\n\n  ---------------------------------------------------------------------------\n\n  Comments from FILE.C, a utility to modify file characteristics:\n\n     Written by Joe Meadows Jr, at the Fred Hutchinson Cancer Research Center\n     BITNET: JOE@FHCRCVAX\n     PHONE: (206) 467-4970\n\n     There are no restrictions on this code, you may sell it, include it\n     with any commercial package, or feed it to a whale.. However, I would\n     appreciate it if you kept this comment in the source code so that anyone\n     receiving this code knows who to contact in case of problems. Note that\n     I do not demand this condition..\n\n  ---------------------------------------------------------------------------*/\n\n\n/* 2004-12-13 SMS.\n * Disabled the module name macro to accommodate old GNU C which didn't\n * obey the directive, and thus confused MMS/MMK where the object\n * library dependencies need to have the correct module name.\n */\n#if 0\n# if defined(__DECC) || defined(__GNUC__)\n#  pragma module module_name module_version\n# else\n#  module module_name module_version\n# endif\n#endif /* 0 */\n\n/*****************************/\n/*  Includes, Defines, etc.  */\n/*****************************/\n\n/* Accomodation for /NAMES = AS_IS with old header files. */\n\n#define sys$asctim SYS$ASCTIM\n#define sys$assign SYS$ASSIGN\n#define sys$bintim SYS$BINTIM\n#define sys$dassgn SYS$DASSGN\n#define sys$parse SYS$PARSE\n#define sys$qiow SYS$QIOW\n#define sys$search SYS$SEARCH\n\n#include \"zip.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <iodef.h>\n#include <starlet.h>\n#include <fibdef.h>   /* this gets created with the c3.0 compiler */\n\n/*\n *  Under Alpha (DEC C in VAXC mode) and under `good old' VAXC, the FIB unions\n *  are declared as variant_unions.  DEC C (Alpha) in ANSI modes and third\n *  party compilers which do not support `variant_union' define preprocessor\n *  symbols to `hide' the \"intermediate union/struct\" names from the\n *  programmer's API.\n *  We check the presence of these defines and for DEC's FIBDEF.H defining\n *  __union as variant_union to make sure we access the structure correctly.\n */\n#if defined(fib$w_did) || (defined(__union) && (__union == variant_union))\n#  define FIB$W_DID     fib$w_did\n#  define FIB$W_FID     fib$w_fid\n#  define FIB$L_ACCTL   fib$l_acctl\n#else\n#  define FIB$W_DID     fib$r_did_overlay.fib$w_did\n#  define FIB$W_FID     fib$r_fid_overlay.fib$w_fid\n#  define FIB$L_ACCTL   fib$r_acctl_overlay.fib$l_acctl\n#endif\n\n#include \"vms.h\"\n#include \"vmsmunch.h\"  /* GET/SET_TIMES, RTYPE, etc. */\n#include \"vmsdefs.h\"   /* fatdef.h, etc. */\n\nstatic void asctim(char *time, long int binval[2]);\nstatic void bintim(char *time, long int binval[2]);\n\n/* from <ssdef.h> */\n#ifndef SS$_NORMAL\n#  define SS$_NORMAL    1\n#  define SS$_BADPARAM  20\n#endif\n\n\n/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.\n   Otherwise, lame system headers on VAX cause compiler warnings.\n   (GNU C may define vax but not __VAX.)\n*/\n#ifdef vax\n# define __VAX 1\n#endif /* def vax */\n\n#ifdef __VAX\n# define GVTC (unsigned int)\n#else /* def __VAX */\n# define GVTC\n#endif /* def __VAX */\n\n\n/*************************/\n/*  Function VMSmunch()  */\n/*************************/\n\nint VMSmunch(\n    char  *filename,\n    int   action,\n    char  *ptr )\n{\n\n    /* original file.c variables */\n\n    static struct FAB Fab;\n    static struct NAM_STRUCT Nam;\n    static struct fibdef Fib; /* short fib */\n\n    static struct dsc$descriptor FibDesc =\n      {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};\n    static struct dsc$descriptor_s DevDesc =\n      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.NAM_DVI[1]};\n    static struct fatdef Fat;\n    static union {\n      struct fchdef fch;\n      long int dummy;\n    } uchar;\n    static struct fjndef jnl;\n    static long int Cdate[2],Rdate[2],Edate[2],Bdate[2];\n    static short int revisions;\n    static unsigned long uic;\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __save\n#pragma __nomember_alignment\n#endif /* __DECC || __DECCXX */\n    static union {\n      unsigned short int value;\n      struct {\n        unsigned system : 4;\n        unsigned owner : 4;\n        unsigned group : 4;\n        unsigned world : 4;\n      } bits;\n    } prot;\n#if defined(__DECC) || defined(__DECCXX)\n#pragma __member_alignment __restore\n#endif /* __DECC || __DECCXX */\n\n    static struct atrdef Atr[] = {\n      {sizeof(Fat),ATR$C_RECATTR, GVTC &Fat},          /* record attributes */\n      {sizeof(uchar),ATR$C_UCHAR, GVTC &uchar},    /* File characteristics */\n      {sizeof(Cdate),ATR$C_CREDATE, GVTC &Cdate[0]},   /* Creation date */\n      {sizeof(Rdate),ATR$C_REVDATE, GVTC &Rdate[0]},   /* Revision date */\n      {sizeof(Edate),ATR$C_EXPDATE, GVTC &Edate[0]},   /* Expiration date */\n      {sizeof(Bdate),ATR$C_BAKDATE, GVTC &Bdate[0]},   /* Backup date */\n      {sizeof(revisions),ATR$C_ASCDATES, GVTC &revisions}, /* number of revs */\n      {sizeof(prot),ATR$C_FPRO, GVTC &prot},           /* file protection  */\n      {sizeof(uic),ATR$C_UIC, GVTC &uic},              /* file owner */\n      {sizeof(jnl),ATR$C_JOURNAL, GVTC &jnl},          /* journal flags */\n      {0,0,0}\n    } ;\n\n    static char EName[NAM_MAXRSS];\n    static char RName[NAM_MAXRSS];\n    static struct dsc$descriptor_s FileName =\n      {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};\n    static struct dsc$descriptor_s string = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};\n    static short int DevChan;\n    static short int iosb[4];\n\n    static long int i,status;\n/*  static char *retval;  */\n\n\n    /* new VMSmunch variables */\n\n    static int  old_rtype=FAT$C_FIXED;   /* storage for record type */\n\n\n\n/*---------------------------------------------------------------------------\n    Initialize attribute blocks, parse filename, resolve any wildcards, and\n    get the file info.\n  ---------------------------------------------------------------------------*/\n\n    /* Initialize RMS structures.  We need a NAM[L] to retrieve the FID. */\n    Fab = cc$rms_fab;\n    Fab.fab$l_fna = filename;\n    Fab.fab$b_fns = strlen(filename);\n    Fab.FAB_NAM = &Nam; /* FAB has an associated NAM[L]. */\n    Nam = CC_RMS_NAM;\n    Nam.NAM_ESA = EName; /* expanded filename */\n    Nam.NAM_ESS = sizeof(EName);\n    Nam.NAM_RSA = RName; /* resultant filename */\n    Nam.NAM_RSS = sizeof(RName);\n\n    /* do $PARSE and $SEARCH here */\n    status = sys$parse(&Fab);\n    if (!(status & 1)) return(status);\n\n    /* search for the first file.. If none signal error */\n    status = sys$search(&Fab);\n    if (!(status & 1)) return(status);\n\n    while (status & 1) {\n        /* initialize Device name length, note that this points into the NAM[L]\n           to get the device name filled in by the $PARSE, $SEARCH services */\n        DevDesc.dsc$w_length = Nam.NAM_DVI[0];\n\n        status = sys$assign(&DevDesc,&DevChan,0,0);\n        if (!(status & 1)) return(status);\n\n        FileName.dsc$a_pointer = Nam.NAM_L_NAME;\n        FileName.dsc$w_length = Nam.NAM_B_NAME+Nam.NAM_B_TYPE+Nam.NAM_B_VER;\n\n        /* Initialize the FIB */\n        for (i=0;i<3;i++) {\n            Fib.FIB$W_FID[i]=Nam.NAM_FID[i];\n            Fib.FIB$W_DID[i]=Nam.NAM_DID[i];\n        }\n\n        /* Use the IO$_ACCESS function to return info about the file */\n        /* Note, used this way, the file is not opened, and the expiration */\n        /* and revision dates are not modified */\n        status = sys$qiow(0,DevChan,IO$_ACCESS,&iosb,0,0,\n                          &FibDesc,&FileName,0,0,&Atr,0);\n        if (!(status & 1) || !((status = iosb[0]) & 1)) {\n            sys$dassgn(DevChan);\n            return(status);\n        }\n\n    /*-----------------------------------------------------------------------\n        We have the current information from the file:  now see what user\n        wants done with it.\n      -----------------------------------------------------------------------*/\n\n        switch (action) {\n\n          case GET_TIMES:   /* non-modifying */\n              asctim(((struct VMStimbuf *)ptr)->modtime, Cdate);\n              asctim(((struct VMStimbuf *)ptr)->actime, Rdate);\n              sys$dassgn(DevChan);\n              return RMS$_NORMAL;     /* return to user */\n              break;\n\n          case SET_TIMES:\n              if (((struct VMStimbuf *)ptr)->modtime != (char *)NULL)\n                  bintim(((struct VMStimbuf *)ptr)->modtime, Cdate);\n              if (((struct VMStimbuf *)ptr)->actime != (char *)NULL)\n                  bintim(((struct VMStimbuf *)ptr)->actime, Rdate);\n              break;\n\n          case GET_RTYPE:   /* non-modifying */\n              *(int *)ptr = Fat.fat$v_rtype;\n              sys$dassgn(DevChan);\n              return RMS$_NORMAL;     /* return to user */\n              break;\n\n          case CHANGE_RTYPE:\n              old_rtype = Fat.fat$v_rtype;              /* save current one */\n              if ((*(int *)ptr < FAT$C_UNDEFINED) ||\n                  (*(int *)ptr > FAT$C_STREAMCR))\n                  Fat.fat$v_rtype = FAT$C_STREAMLF;       /* Unix I/O happy */\n              else\n                  Fat.fat$v_rtype = *(int *)ptr;\n              break;\n\n          case RESTORE_RTYPE:\n              Fat.fat$v_rtype = old_rtype;\n              break;\n\n          default:\n              sys$dassgn(DevChan);\n              return SS$_BADPARAM;   /* anything better? */\n        }\n\n    /*-----------------------------------------------------------------------\n        Go back and write modified data to the file header.\n      -----------------------------------------------------------------------*/\n\n        /* note, part of the FIB was cleared by earlier QIOW, so reset it */\n        Fib.FIB$L_ACCTL = FIB$M_NORECORD;\n        for (i=0;i<3;i++) {\n            Fib.FIB$W_FID[i]=Nam.NAM_FID[i];\n            Fib.FIB$W_DID[i]=Nam.NAM_DID[i];\n        }\n\n        /* Use the IO$_MODIFY function to change info about the file */\n        /* Note, used this way, the file is not opened, however this would */\n        /* normally cause the expiration and revision dates to be modified. */\n        /* Using FIB$M_NORECORD prohibits this from happening. */\n        status = sys$qiow(0,DevChan,IO$_MODIFY,&iosb,0,0,\n                          &FibDesc,&FileName,0,0,&Atr,0);\n        if (!(status & 1) || !((status = iosb[0]) & 1)) {\n            sys$dassgn(DevChan);\n            return(status);\n        }\n\n        status = sys$dassgn(DevChan);\n        if (!(status & 1)) return(status);\n\n        /* look for next file, if none, no big deal.. */\n        status = sys$search(&Fab);\n    }\n    return(status);\n} /* end function VMSmunch() */\n\n\n\n\n\n/***********************/\n/*  Function asctim()  */\n/***********************/\n\nstatic void asctim(        /* convert 64-bit binval to string, put in time */\n    char *time,\n    long int binval[2] )\n{\n    static struct dsc$descriptor date_str={23,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};\n      /* dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer */\n\n    date_str.dsc$a_pointer = time;\n    sys$asctim(0, &date_str, binval, 0);\n    time[23] = '\\0';\n}\n\n\n\n\n\n/***********************/\n/*  Function bintim()  */\n/***********************/\n\nstatic void bintim(        /* convert time string to 64 bits, put in binval */\n    char *time,\n    long int binval[2] )\n{\n    static struct dsc$descriptor date_str={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};\n\n    date_str.dsc$w_length = strlen(time);\n    date_str.dsc$a_pointer = time;\n    sys$bintim(&date_str, binval);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vmsmunch.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  vmsmunch.h\n\n  A few handy #defines, plus the contents of three header files from Joe\n  Meadows' FILE program.  Used by VMSmunch and by various routines which\n  call VMSmunch (e.g., in Zip and UnZip).\n\n        02-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com\n                        Moved definition of VMStimbuf struct from vmsmunch.c\n                        to here.\n\n        06-Apr-1994     Jamie Hanrahan  jeh@cmkrnl.com\n                        Moved \"contents of three header files\" (not needed by\n                        callers of vmsmunch) to VMSdefs.h .\n\n        07-Apr-1994     Richard Levitte levitte@e.kth.se\n                        Inserted a forward declaration of VMSmunch.\n\n        17-Sep-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de\n                        Added wrapper to prevent multiple loading of this file.\n\n        10-Oct-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de\n                        Use lowercase names for all VMS specific source files\n\n        15-Dec-1995     Chr. Spieler    spieler@linac.ikp.physik.th-darmstadt.de\n                        Removed ALL \"tabs\" from source file.\n\n  ---------------------------------------------------------------------------*/\n\n#ifndef __vmsmunch_h\n#define __vmsmunch_h 1\n\n#define GET_TIMES       4\n#define SET_TIMES       0\n#define GET_RTYPE       1\n#define CHANGE_RTYPE    2\n#define RESTORE_RTYPE   3\n\nstruct VMStimbuf {      /* VMSmunch */\n    char *actime;       /* VMS revision date, ASCII format */\n    char *modtime;      /* VMS creation date, ASCII format */\n};\n\nextern int VMSmunch(char *filename, int action, char *ptr);\n\n#endif /* !__vmsmunch_h */\n"
  },
  {
    "path": "deps/infozip/zip30/vms/vmszip.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* 2005-02-14 SMS.\n   Added some ODS5 support.\n      Use longer name structures in NAML, where available.\n      Locate special characters mindful of \"^\" escapes.\n      Replaced compile-time case preservation (VMS_PRESERVE_CASE macro)\n      with command-line-specified case preservation (vms_case_x\n      variables).\n   Prototyped all functions.\n   Removed \"#ifndef UTIL\", as no one should be compiling it that way.\n*/\n\n#include \"zip.h\"\n#include \"vmsmunch.h\"\n#include \"vms.h\"\n\n#include <ctype.h>\n#include <time.h>\n#include <unixlib.h>\n\n/* Judge availability of str[n]casecmp() in C RTL.\n   (Note: This must follow a \"#include <decc$types.h>\" in something to\n   ensure that __CRTL_VER is as defined as it will ever be.  DEC C on\n   VAX may not define it itself.)\n*/\n#ifdef __CRTL_VER\n#if __CRTL_VER >= 70000000\n#define HAVE_STRCASECMP\n#endif /* __CRTL_VER >= 70000000 */\n#endif /* def __CRTL_VER */\n\n#ifdef HAVE_STRCASECMP\n#include <strings.h>    /* str[n]casecmp() */\n#endif /* def HAVE_STRCASECMP */\n\n#include <dvidef.h>\n#include <lib$routines.h>\n#include <ssdef.h>\n#include <stsdef.h>\n#include <starlet.h>\n\n/* Directory file type with version, and its strlen(). */\n#define DIR_TYPE_VER \".DIR;1\"\n#define DIR_TYPE_VER_LEN (sizeof( DIR_TYPE_VER)- 1)\n\n/* Extra malloc() space in names for cutpath().  (May have to change\n   \".FOO]\" to \"]FOO.DIR;1\".)\n*/\n#define DIR_PAD (DIR_TYPE_VER_LEN- 1)\n\n/* Hex digit table. */\n\nchar hex_digit[ 16] = {\n '0', '1', '2', '3', '4', '5', '6', '7',\n '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'\n};\n\n/* Character property table for (re-)escaping ODS5 extended file names.\n   Note that this table ignore Unicode, and does not identify invalid\n   characters.\n\n   ODS2 valid characters: 0-9 A-Z a-z $ - _\n\n   ODS5 Invalid characters:\n      C0 control codes (0x00 to 0x1F inclusive)\n      Asterisk (*)\n      Question mark (?)\n\n   ODS5 Invalid characters only in VMS V7.2 (which no one runs, right?):\n      Double quotation marks (\")\n      Backslash (\\)\n      Colon (:)\n      Left angle bracket (<)\n      Right angle bracket (>)\n      Slash (/)\n      Vertical bar (|)\n\n   Characters escaped by \"^\":\n      SP  !  #  %  &  '  (  )  +  ,  .  ;  =  @  [  ]  ^  `  {  }  ~\n\n   Either \"^_\" or \"^ \" is accepted as a space.  Period (.) is a special\n   case.  Note that un-escaped < and > can also confuse a directory\n   spec.\n\n   Characters put out as ^xx:\n      7F (DEL)\n      80-9F (C1 control characters)\n      A0 (nonbreaking space)\n      FF (Latin small letter y diaeresis)\n\n   Other cases:\n      Unicode: \"^Uxxxx\", where \"xxxx\" is four hex digits.\n\n    Property table values:\n      Normal escape:    1\n      Space:            2\n      Dot:              4\n      Hex-hex escape:   8\n      -------------------\n      Hex digit:       64\n*/\n\nunsigned char char_prop[ 256] = {\n\n/* NUL SOH STX ETX EOT ENQ ACK BEL   BS  HT  LF  VT  FF  CR  SO  SI */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB  CAN  EM SUB ESC  FS  GS  RS  US */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/*  SP  !   \"   #   $   %   &   '    (   )   *   +   ,   -   .   /  */\n    2,  1,  0,  1,  0,  1,  1,  1,   1,  1,  0,  1,  1,  0,  4,  0,\n\n/*  0   1   2   3   4   5   6   7    8   9   :   ;   <   =   >   ?  */\n   64, 64, 64, 64, 64, 64, 64, 64,  64, 64,  0,  1,  1,  1,  1,  1,\n\n/*  @   A   B   C   D   E   F   G    H   I   J   K   L   M   N   O  */\n    1, 64, 64, 64, 64, 64, 64,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/*  P   Q   R   S   T   U   V   W    X   Y   Z   [   \\   ]   ^   _  */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  1,  0,  1,  1,  0,\n\n/*  `   a   b   c   d   e   f   g    h   i   j   k   l   m   n   o  */\n    1, 64, 64, 64, 64, 64, 64,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n\n/*  p   q   r   s   t   u   v   w    x   y   z   {   |   }   ~  DEL */\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  1,  0,  1,  1,  8,\n\n    8,  8,  8,  8,  8,  8,  8,  8,   8,  8,  8,  8,  8,  8,  8,  8,\n    8,  8,  8,  8,  8,  8,  8,  8,   8,  8,  8,  8,  8,  8,  8,  8,\n    8,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,\n    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  8\n};\n\n/* The C RTL from OpenVMS 7.0 and newer supplies POSIX compatible versions of\n * opendir() et al. Thus, we have to use other names in our private code for\n * directory scanning to prevent symbol name conflicts at link time.\n * For now, we do not use the library supplied \"dirent.h\" functions, since\n * our private implementation provides some functionality which may not be\n * present in the library versions.  For example:\n * ==> zopendir(\"DISK:[DIR.SUB1]SUB2.DIR\") scans \"DISK:[DIR.SUB1.SUB2]\".\n */\n\ntypedef struct zdirent {\n  int d_wild;                /* flag for wildcard vs. non-wild */\n  struct FAB fab;\n  struct NAM_STRUCT nam;\n  char d_qualwildname[ NAM_MAXRSS+ 1];\n  char d_name[ NAM_MAXRSS+ 1];\n} zDIR;\n\nextern char *label;\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\nlocal int relative_dir_s = 0;   /* Relative directory spec. */\n\n/* Local functions */\nlocal void vms_wild OF((char *, zDIR *));\nlocal zDIR *zopendir OF((ZCONST char *));\nlocal char *readd OF((zDIR *));\nlocal char *strlower OF((char *));\nlocal char *strupper OF((char *));\n\n/* 2004-09-25 SMS.\n   str[n]casecmp() replacement for old C RTL.\n   Assumes a prehistorically incompetent toupper().\n*/\n#ifndef HAVE_STRCASECMP\n\nint strncasecmp( char *s1, char *s2, size_t n)\n{\n  /* Initialization prepares for n == 0. */\n  char c1 = '\\0';\n  char c2 = '\\0';\n\n  while (n-- > 0)\n  {\n    /* Set c1 and c2.  Convert lower-case characters to upper-case. */\n    if (islower( c1 = *s1))\n      c1 = toupper( c1);\n\n    if (islower( c2 = *s2))\n      c2 = toupper( c2);\n\n    /* Quit at inequality or NUL. */\n    if ((c1 != c2) || (c1 == '\\0'))\n      break;\n\n    s1++;\n    s2++;\n  }\nreturn ((unsigned int) c1- (unsigned int) c2);\n}\n\n#ifndef UINT_MAX\n#define UINT_MAX 4294967295U\n#endif\n\n#define strcasecmp( s1, s2) strncasecmp( s1, s2, UINT_MAX)\n\n#endif /* ndef HAVE_STRCASECMP */\n\n\n/* 2004-09-27 SMS.\n   eat_carets().\n\n   Delete ODS5 extended file name escape characters (\"^\") in the\n   original buffer.\n   Note that the current scheme does not handle all EFN cases, but it\n   could be made more complicated.\n*/\n\nlocal void eat_carets( char *str)\n/* char *str;      Source pointer. */\n{\n  char *strd;   /* Destination pointer. */\n  char hdgt;\n  unsigned char uchr;\n  unsigned char prop;\n\n  /* Skip ahead to the first \"^\", if any. */\n  while ((*str != '\\0') && (*str != '^'))\n     str++;\n\n  /* If no caret was found, quit early. */\n  if (*str != '\\0')\n  {\n    /* Shift characters leftward as carets are found. */\n    strd = str;\n    while (*str != '\\0')\n    {\n      uchr = *str;\n      if (uchr == '^')\n      {\n        /* Found a caret.  Skip it, and check the next character. */\n        uchr = *(++str);\n        prop = char_prop[ uchr];\n        if (prop& 64)\n        {\n          /* Hex digit.  Get char code from this and next hex digit. */\n          if (uchr <= '9')\n          {\n            hdgt = uchr- '0';           /* '0' - '9' -> 0 - 9. */\n          }\n          else\n          {\n            hdgt = ((uchr- 'A')& 7)+ 10;    /* [Aa] - [Ff] -> 10 - 15. */\n          }\n          hdgt <<= 4;                   /* X16. */\n          uchr = *(++str);              /* Next char must be hex digit. */\n          if (uchr <= '9')\n          {\n            uchr = hdgt+ uchr- '0';\n          }\n          else\n          {\n            uchr = hdgt+ ((uchr- 'A')& 15)+ 10;\n          }\n        }\n        else if (uchr == '_')\n        {\n          /* Convert escaped \"_\" to \" \". */\n          uchr = ' ';\n        }\n        else if (uchr == '/')\n        {\n          /* Convert escaped \"/\" (invalid Zip) to \"?\" (invalid VMS). */\n          uchr = '?';\n        }\n        /* Else, not a hex digit.  Must be a simple escaped character\n           (or Unicode, which is not yet handled here).\n        */\n      }\n      /* Else, not a caret.  Use as-is. */\n      *strd = uchr;\n\n      /* Advance destination and source pointers. */\n      strd++;\n      str++;\n    }\n    /* Terminate the destination string. */\n    *strd = '\\0';\n  }\n}\n\n\n/* 2007-05-22 SMS.\n * explicit_dev().\n *\n * Determine if an explicit device name is present in a (VMS) file\n * specification.\n */\nlocal int explicit_dev( char *file_spec)\n{\n  int sts;\n  struct FAB fab;               /* FAB. */\n  struct NAM_STRUCT nam;        /* NAM[L]. */\n\n  /* Initialize the FAB and NAM[L], and link the NAM[L] to the FAB. */\n  nam = CC_RMS_NAM;\n  fab = cc$rms_fab;\n  fab.FAB_NAM = &nam;\n\n  /* Point the FAB/NAM[L] fields to the actual name and default name. */\n\n#ifdef NAML$C_MAXRSS\n\n  fab.fab$l_dna = (char *) -1;  /* Using NAML for default name. */\n  fab.fab$l_fna = (char *) -1;  /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n  /* File name. */\n  FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = file_spec;\n  FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( file_spec);\n\n  nam.NAM_NOP = NAM_M_SYNCHK;   /* Syntax-only analysis. */\n  sts = sys$parse( &fab, 0, 0); /* Parse the file spec. */\n\n  /* Device found = $PARSE success and \"device was explicit\" flag. */\n  return (((sts& STS$M_SEVERITY) == STS$M_SUCCESS) &&\n   ((nam.NAM_FNB& NAM_M_EXP_DEV) != 0));\n}\n\n\n/* 2005-02-04 SMS.\n   find_dir().\n\n   Find directory boundaries in an ODS2 or ODS5 file spec.\n   Returns length (zero if no directory, negative if error),\n   and sets \"start\" argument to first character (typically \"[\") location.\n\n   No one will care about the details, but the return values are:\n\n       0  No dir.\n      -2  [, no end.              -3  <, no end.\n      -4  [, multiple start.      -5  <, multiple start.\n      -8  ], no start.            -9  >, no start.\n     -16  ], wrong end.          -17  >, wrong end.\n     -32  ], multiple end.       -33  >, multiple end.\n\n   Note that the current scheme handles only simple EFN cases, but it\n   could be made more complicated.\n*/\nint find_dir( char *file_spec, char **start)\n{\n  char *cp;\n  char chr;\n\n  char *end_tmp = NULL;\n  char *start_tmp = NULL;\n  int lenth = 0;\n\n  for (cp = file_spec; cp < file_spec+ strlen( file_spec); cp++)\n  {\n    chr = *cp;\n    if (chr == '^')\n    {\n      /* Skip ODS5 extended name escaped characters. */\n      cp++;\n      /* If escaped char is a hex digit, skip the second hex digit, too. */\n      if (char_prop[ (unsigned char) *cp]& 64)\n        cp++;\n    }\n    else if (chr == '[')\n    {\n      /* Found start. */\n      if (start_tmp == NULL)\n      {\n        /* First time.  Record start location. */\n        start_tmp = cp;\n        /* Error if no end. */\n        lenth = -2;\n      }\n      else\n      {\n        /* Multiple start characters.  */\n        lenth = -4;\n        break;\n      }\n    }\n    else if (chr == '<')\n    {\n      /* Found start. */\n      if (start_tmp == NULL)\n      {\n        /* First time.  Record start location. */\n        start_tmp = cp;\n        /* Error if no end. */\n        lenth = -3;\n      }\n      else\n      {\n        /* Multiple start characters.  */\n        lenth = -5;\n        break;\n      }\n    }\n    else if (chr == ']')\n    {\n      /* Found end. */\n      if (end_tmp == NULL)\n      {\n        /* First time. */\n        if (lenth == 0)\n        {\n          /* End without start. */\n          lenth = -8;\n          break;\n        }\n        else if (lenth != -2)\n        {\n          /* Wrong kind of end. */\n          lenth = -16;\n          break;\n        }\n        /* End ok.  Record end location. */\n        end_tmp = cp;\n        lenth = end_tmp+ 1- start_tmp;\n        /* Could break here, ignoring excessive end characters. */\n      }\n      else\n      {\n        /* Multiple end characters. */\n        lenth = -32;\n        break;\n      }\n    }\n    else if (chr == '>')\n    {\n      /* Found end. */\n      if (end_tmp == NULL)\n      {\n        /* First time. */\n        if (lenth == 0)\n        {\n          /* End without start. */\n          lenth = -9;\n          break;\n        }\n        else if (lenth != -3)\n        {\n          /* Wrong kind of end. */\n          lenth = -17;\n          break;\n        }\n        /* End ok.  Record end location. */\n        end_tmp = cp;\n        lenth = end_tmp+ 1- start_tmp;\n        /* Could break here, ignoring excessive end characters. */\n      }\n      else\n      {\n        /* Multiple end characters. */\n        lenth = -33;\n        break;\n      }\n    }\n  }\n\n  /* If both start and end were found,\n     then set result pointer where safe.\n  */\n  if (lenth > 0)\n  {\n    if (start != NULL)\n    {\n      *start = start_tmp;\n    }\n  }\n  return lenth;\n}\n\n\n/* 2005-02-08 SMS.\n   file_sys_type().\n\n   Determine the file system type for the (VMS) path name argument.\n*/\nlocal int file_sys_type( char *path)\n{\n  int acp_code;\n\n#ifdef DVI$C_ACP_F11V5\n\n/* Should know about ODS5 file system.  Do actual check.\n   (This should be non-VAX with __CRTL_VER >= 70200000.)\n*/\n\n  int sts;\n\n  struct dsc$descriptor_s dev_descr =\n   { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };\n\n  /* Load path argument into device descriptor. */\n  dev_descr.dsc$a_pointer = path;\n  dev_descr.dsc$w_length = strlen( dev_descr.dsc$a_pointer);\n\n  /* Get filesystem type code.\n     (Text results for this item code have been unreliable.)\n  */\n  sts = lib$getdvi( &((int) DVI$_ACPTYPE), 0, &dev_descr, &acp_code, 0, 0);\n\n  if ((sts & STS$M_SUCCESS) != STS$K_SUCCESS)\n  {\n    acp_code = -1;\n  }\n\n#else /* def DVI$C_ACP_F11V5 */\n\n/* Too old for ODS5 file system.  Must be ODS2. */\n\n  acp_code = DVI$C_ACP_F11V2;\n\n#endif /* def DVI$C_ACP_F11V5 */\n\n  return acp_code;\n}\n\n/*---------------------------------------------------------------------------\n\n    _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C\n    fwild() and fnext() routines (originally written by Martin Minow, poss-\n    ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg\n    Roelofs and are still in the public domain.  Routines approximate the\n    behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions.\n\n    2005-01-04 SMS.\n    Changed to use NAML instead of NAM, where available.\n\n  ---------------------------------------------------------------------------*/\n\nstatic char wild_version_part[10]=\"\\0\";\n\nlocal void vms_wild( char *p, zDIR *d)\n{\n  /*\n   * Do wildcard setup.\n   */\n  /* Set up the FAB and NAM[L] blocks. */\n  d->fab = cc$rms_fab;                  /* Initialize FAB. */\n  d->nam = CC_RMS_NAM;                  /* Initialize NAM[L]. */\n\n  d->fab.FAB_NAM = &d->nam;             /* FAB -> NAM[L] */\n\n#ifdef NAML$C_MAXRSS\n\n  d->fab.fab$l_dna =(char *) -1;        /* Using NAML for default name. */\n  d->fab.fab$l_fna = (char *) -1;       /* Using NAML for file name. */\n\n#endif /* def NAML$C_MAXRSS */\n\n  /* Argument file name and length. */\n  d->FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = p;\n  d->FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen(p);\n\n#define DEF_DEVDIR \"SYS$DISK:[]\"\n\n  /* Default file spec and length. */\n  d->FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNA = DEF_DEVDIR;\n  d->FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNS = sizeof( DEF_DEVDIR)- 1;\n\n  d->nam.NAM_ESA = d->d_qualwildname;   /* qualified wild name */\n  d->nam.NAM_ESS = NAM_MAXRSS;          /* max length */\n  d->nam.NAM_RSA = d->d_name;           /* matching file name */\n  d->nam.NAM_RSS = NAM_MAXRSS;          /* max length */\n\n  /* parse the file name */\n  if (sys$parse(&d->fab) != RMS$_NORMAL)\n    return;\n  /* Does this replace d->fab.fab$l_fna with a new string in its own space?\n     I sure hope so, since p is free'ed before this routine returns. */\n\n  /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate\n   * and set wild-flag */\n  d->d_qualwildname[d->nam.NAM_ESL] = '\\0';\n  d->d_wild = (d->nam.NAM_FNB & NAM$M_WILDCARD)? 1 : 0;   /* not used... */\n#ifdef DEBUG\n  fprintf(mesg, \"  incoming wildname:  %s\\n\", p);\n  fprintf(mesg, \"  qualified wildname:  %s\\n\", d->d_qualwildname);\n#endif /* DEBUG */\n}\n\nlocal zDIR *zopendir( ZCONST char *n)\n/* ZCONST char *n;         directory to open */\n/* Start searching for files in the VMS directory n */\n{\n  char *c;              /* scans VMS path */\n  zDIR *d;              /* malloc'd return value */\n  int m;                /* length of name */\n  char *p;              /* malloc'd temporary string */\n\n  if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL ||\n      (p = malloc((m = strlen(n)) + 4)) == NULL) {\n    if (d != NULL) free((zvoid *)d);\n    return NULL;\n  }\n  /* Directory may be in form \"[DIR.SUB1.SUB2]\" or \"[DIR.SUB1]SUB2.DIR;1\".\n     If latter, convert to former.\n     2005-01-31 SMS.  Changed to require \";1\", as VMS does, which\n     simplified the code slightly, too.  Note that ODS5 allows \".DIR\" in\n     any case (upper, lower, mixed).\n  */\n  if ((m > 0) && (*(c = strcpy(p,n)+m-1) != ']'))\n  {\n    if ((c- p < DIR_TYPE_VER_LEN) ||\n     strcasecmp((c+ 1- DIR_TYPE_VER_LEN), DIR_TYPE_VER))\n    {\n      free((zvoid *)d);  free((zvoid *)p);\n      return NULL;\n    }\n    c -= 4;             /* The \"D\". */\n    *c-- = '\\0';        /* terminate at \"DIR;1\" */\n    *c = ']';           /* \".\" --> \"]\" */\n\n    /* Replace the formerly last \"]\" with \".\".\n       For ODS5, ignore \"^]\".\n    */\n    while ((c > p) && ((*--c != ']') || (*(c- 1) == '^')))\n      ;\n    *c = '.';           /* \"]\" --> \".\" */\n  }\n  strcat(p, \"*.*\");\n  strcat(p, wild_version_part);\n  vms_wild(p, d);       /* set up wildcard */\n  free((zvoid *)p);\n  return d;\n}\n\nlocal char *readd( zDIR *d)\n/* zDIR *d;                directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  int r;                /* return code */\n\n  do {\n    d->fab.fab$w_ifi = 0;       /* internal file index:  what does this do? */\n/*\n  2005-02-04 SMS.\n\n  From the docs:\n\n        Note that you must close the file before invoking the Search\n        service (FAB$W_IFI must be 0). \n\n  The same is true for PARSE.  Most likely, it's cleared by setting\n  \"fab = cc$rms_fab\", and left that way, so clearing it here may very\n  well be pointless.  (I think it is, and I've never seen it explicitly\n  cleared elsewhere, but I haven't tested it everywhere either.)\n*/\n    /* get next match to possible wildcard */\n    if ((r = sys$search(&d->fab)) == RMS$_NORMAL)\n    {\n        d->d_name[d->nam.NAM_RSL] = '\\0';   /* null terminate */\n        return (char *)d->d_name;   /* OK */\n    }\n  } while (r == RMS$_PRV);\n  return NULL;\n}\n\n\nint wild( char *p)\n/* char *p;                path/pattern to match */\n/* Expand the pattern based on the contents of the file system.\n   Return an error code in the ZE_ class.\n   Note that any command-line file argument may need wildcard expansion,\n   so all user-specified constituent file names pass through here.\n*/\n{\n  zDIR *d;              /* stream for reading directory */\n  char *e;              /* name found in directory */\n  int f;                /* true if there was a match */\n\n  int dir_len;          /* Length of the directory part of the name. */\n  char *dir_start;      /* First character of the directory part. */\n\n  /* special handling of stdin request */\n  if (strcmp(p, \"-\") == 0)   /* if compressing stdin */\n    return newname(p, 0, 0);\n\n  /* Determine whether this name has an absolute or relative directory\n     spec.  It's relative if there is no directory, or if the directory\n     has a leading dot (\"[.\").\n  */\n  dir_len = find_dir( p, &dir_start);\n  relative_dir_s = ((dir_len <= 0)? 1 : (dir_start[ 1] == '.'));\n\n  /* Search given pattern for matching names */\n  if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL)\n    return ZE_MEM;\n  vms_wild(p, d);       /* pattern may be more than just directory name */\n\n  /*\n   * Save version specified by user to use in recursive drops into\n   * subdirectories.\n   */\n  strncpy(wild_version_part, d->nam.NAM_L_VER, d->nam.NAM_B_VER);\n  wild_version_part[d->nam.NAM_B_VER] = '\\0';\n\n  f = 0;\n  while ((e = readd(d)) != NULL)        /* \"dosmatch\" is already built in */\n    if (procname(e, 0) == ZE_OK)\n      f = 1;\n  free(d);\n\n  /* Done */\n  return f ? ZE_OK : ZE_MISS;\n}\n\nint procname( char *n, int caseflag)\n/* char *n;                name to process */\n/* int caseflag;           true to force case-sensitive match */\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  zDIR *d;              /* directory stream from zopendir() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  struct stat s;        /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (LSSTAT(n, &s)\n#if defined(__TURBOC__) || defined(VMS) || defined(__WATCOMC__)\n           /* For these 3 compilers, stat() succeeds on wild card names! */\n           || isshexp(n)\n#endif\n          )\n  {\n    /* Not a file or directory--search for shell expression in zip file */\n    if (caseflag) {\n      p = malloc(strlen(n) + 1);\n      if (p != NULL)\n        strcpy(p, n);\n    } else\n      p = ex2in(n, 0, (int *)NULL);     /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->name);\n        m = 0;\n      }\n    }\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add or remove name of file */\n    if ((m = newname(n, 0, caseflag)) != ZE_OK)\n      return m;\n  } else {\n    if (dirnames && (m = newname(n, 1, caseflag)) != ZE_OK) {\n      return m;\n    }\n    /* recurse into directory */\n    if (recurse && (d = zopendir(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if ((m = procname(e, caseflag)) != ZE_OK)     /* recurse on name */\n        {\n          free(d);\n          return m;\n        }\n      }\n      free(d);\n    }\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\n/* 2004-09-24 SMS.\n   Cuter strlower() and strupper() functions.\n*/\n\nlocal char *strlower( char *s)\n/* Convert all uppercase letters to lowercase in string s */\n{\n  for ( ; *s != '\\0'; s++)\n    if (isupper( *s))\n      *s = tolower( *s);\n\n  return s;\n}\n\nlocal char *strupper( char *s)\n/* Convert all lowercase letters to uppercase in string s */\n{\n  for ( ; *s != '\\0'; s++)\n    if (islower( *s))\n      *s = toupper( *s);\n\n  return s;\n}\n\nchar *ex2in( char *x, int isdir, int *pdosflag)\n/* char *x;                external file name */\n/* int isdir;              input: x is a directory */\n/* int *pdosflag;          output: force MSDOS file attributes? */\n\n/* Convert the external file name to a zip file name, returning the\n   malloc'ed string or NULL if not enough memory.\n\n   2005-02-09 SMS.\n   Added some ODS5 support.\n\n   Note that if we were really clever, we'd save the truncated original\n   file name for later use as \"iname\", instead of running the de-escaped\n   product back through in2ex() to recover it later.\n\n   2005-11-13 SMS.\n   Changed to translate \"[...\" into enough \"/\" characters to cause\n   in2ex() to reconstruct it.  This should not be needed, however, as\n   pattern matching really should avoid ex2in() and in2ex().\n*/\n{\n  char *n;                      /* Internal file name (malloc'ed). */\n  char *nn;                     /* Temporary \"n\"-like pointer. */\n  char *ext_dir_and_name;       /* External dir]name (less \"dev:[\"). */\n  char chr;                     /* Temporary character storage. */\n  int dosflag;\n  int down_case;                /* Resultant down-case flag. */\n  int dir_len;                  /* Directory spec length. */\n  int ods_level;                /* File system type. */\n\n  dosflag = dosify; /* default for non-DOS and non-OS/2 */\n\n  /* Locate the directory part of the external name. */\n  dir_len = find_dir( x, &ext_dir_and_name);\n  if (dir_len <= 0)\n  {\n    /* Directory not found.  Use whole external name. */\n    ext_dir_and_name = x;\n  }\n  else if (pathput)\n  {\n    /* Include directory. */\n    if (ext_dir_and_name[ 1] == '.')\n    {\n      /* Relative path.  If not a directory-depth wildcard, then drop\n         first \"[.\" (or \"<.\").  If \"[...\" (or \"<...\"), then preserve all\n         characters, including the first \"[\" (or \"<\") for special\n         handling below.\n      */\n      if ((ext_dir_and_name[ 2] != '.') || (ext_dir_and_name[ 3] != '.'))\n      {\n        /* Normal relative path.  Drop first \"[.\" (or \"<.\"). */\n        dir_len -= 2;\n        ext_dir_and_name += 2;\n      }\n    }\n    else\n    {\n      /* Absolute path.  Skip first \"[\" (or \"<\"). */\n      dir_len -= 1;\n      ext_dir_and_name += 1;\n\n      /* 2007-04-26 SMS.\n         Skip past \"000000.\" or \"000000]\" (or \"000000>\"), which should\n         not be stored in the archive.  This arises, for example, with\n         \"zip -r archive [000000]foo.dir\"\n      */\n#define MFD \"000000\"\n\n      if ((strncmp( ext_dir_and_name, MFD, strlen( MFD)) == 0) &&\n       ((ext_dir_and_name[ 6] == '.') ||\n       (ext_dir_and_name[ 6] == ']') ||\n       (ext_dir_and_name[ 6] == '>')))\n      {\n        dir_len -= 7;\n        ext_dir_and_name += 7;\n      } \n    }\n  }\n  else\n  {\n    /* Junking paths.  Skip the whole directory spec. */\n    ext_dir_and_name += dir_len;\n    dir_len = 0;\n  }\n\n  /* Malloc space for internal name and copy it. */\n  if ((n = malloc(strlen( ext_dir_and_name)+ 1)) == NULL)\n    return NULL;\n  strcpy( n, ext_dir_and_name);\n\n  /* Convert VMS directory separators (\".\") to \"/\". */\n  if (dir_len > 0)\n  {\n    for (nn = n; nn < n+ dir_len; nn++)\n    {\n      chr = *nn;\n      if (chr == '^')\n      {\n        /* Skip ODS5 extended name escaped characters. */\n        nn++;\n        /* If escaped char is a hex digit, skip the second hex digit, too. */\n        if (char_prop[ (unsigned char) *nn]& 64)\n          nn++;\n      }\n      else if ((chr == '.') || ((nn == n) && ((chr == '[') || (chr == '<'))))\n      {\n        /* Convert VMS directory separator (\".\", or initial \"[\" or \"<\"\n           of \"[...\" or \"<...\") to \"/\".\n        */\n        *nn = '/';\n      }\n    }\n    /* Replace directory end character (typically \"]\") with \"/\". */\n    n[ dir_len- 1] = '/';\n  }\n\n  /* If relative path, then strip off the current directory. */\n  if (relative_dir_s)\n  {\n    char cwd[ NAM_MAXRSS+ 1];\n    char *cwd_dir_only;\n    char *q;\n    int cwd_dir_only_len;\n\n    q = getcwd( cwd, (sizeof( cwd)- 1));\n\n    /* 2004-09-24 SMS.\n       With SET PROCESSS /PARSE = EXTENDED, getcwd() can return a\n       mixed-case result, confounding the comparisons below with an\n       all-uppercase name in \"n\".  Always use a case-insensitive\n       comparison around here.\n    */\n\n    /* Locate the directory part of the external name. */\n    dir_len = find_dir( q, &cwd_dir_only);\n    if (dir_len > 0)\n    {\n      /* Skip first \"[\" (or \"<\"). */\n      cwd_dir_only++;\n      /* Convert VMS directory separators (\".\") to \"/\". */\n      for (q = cwd_dir_only; q < cwd_dir_only+ dir_len; q++)\n      {\n        chr = *q;\n        if (chr == '^')\n        {\n          /* Skip ODS5 extended name escaped characters. */\n          q++;\n          /* If escaped char is a hex digit, skip the second hex digit, too. */\n          if (char_prop[ (unsigned char) *q]& 64)\n            q++;\n        }\n        else if (chr == '.')\n        {\n          /* Convert VMS directory separator (\".\") to \"/\". */\n          *q = '/';\n        }\n      }\n      /* Replace directory end character (typically \"]\") with \"/\". */\n      cwd_dir_only[ dir_len- 2] = '/';\n    }\n\n    /* If the slash-converted cwd matches the front of the internal\n       name, then shuffle the remainder of the internal name to the\n       beginning of the internal name storage.\n\n       Because we already know that the path is relative, this test may\n       always succeed.\n    */\n    cwd_dir_only_len = strlen( cwd_dir_only);\n    if (strncasecmp( n, cwd_dir_only, cwd_dir_only_len) == 0)\n    {\n       nn = n+ cwd_dir_only_len;\n       q = n;\n       while (*q++ = *nn++);\n    }\n  } /* (relative_dir_s) */\n\n  /* 2007-05-22 SMS.\n   * If a device name is present, assume that it's a real (VMS) file\n   * specification, and do down-casing according to the ODS2 or ODS5\n   * down-casing policy.  If no device name is present, assume that it's\n   * a pattern (\"-i\", ...), and do no down-casing here.  (Case\n   * sensitivity in patterns is handled elsewhere.)\n   */\n  if (explicit_dev( x))\n  {\n    /* If ODS5 is possible, do complicated down-case check.\n\n       Note that the test for ODS2/ODS5 is misleading and over-broad. \n       Here, \"ODS2\" includes anything from DVI$C_ACP_F11V1 (=1, ODS1) up\n       to (but not including) DVI$C_ACP_F11V5 (= 11, DVI$C_ACP_F11V5),\n       while \"ODS5\" includes anything from DVI$C_ACP_F11V5 on up.  See\n       DVIDEF.H.\n    */\n\n#if defined( DVI$C_ACP_F11V5) && defined( NAML$C_MAXRSS)\n\n    /* Check options and/or ODS level for down-case or preserve case. */\n    down_case = 0;      /* Assume preserve case. */\n    if ((vms_case_2 <= 0) && (vms_case_5 < 0))\n    {\n      /* Always down-case. */\n      down_case = 1;\n    }\n    else if ((vms_case_2 <= 0) || (vms_case_5 < 0))\n    {\n      /* Down-case depending on ODS level.  (Use (full) external name.) */\n      ods_level = file_sys_type( x);\n\n      if (ods_level > 0)\n      {\n        /* Valid ODS level.  (Name (full) contains device.)\n         * Down-case accordingly.\n         */\n        if (((ods_level < DVI$C_ACP_F11V5) && (vms_case_2 <= 0)) ||\n         ((ods_level >= DVI$C_ACP_F11V5) && (vms_case_5 < 0)))\n        {\n          /* Down-case for this ODS level. */\n          down_case = 1;\n        }\n      }\n    }\n\n#else /* defined( DVI$C_ACP_F11V5) && defined( NAML$C_MAXRSS) */\n\n/* No case-preserved names are possible (VAX).  Do simple down-case check. */\n\n    down_case = (vms_case_2 <= 0);\n\n#endif /* defined( DVI$C_ACP_F11V5) && defined( NAML$C_MAXRSS) [else] */\n\n    /* If down-casing, convert to lower case. */\n    if (down_case != 0)\n    {\n      strlower( n);\n    }\n  }\n\n  /* Remove simple ODS5 extended file name escape characters. */\n  eat_carets( n);\n\n  if (isdir)\n  {\n    if (strcasecmp( (nn = n+ strlen( n)- DIR_TYPE_VER_LEN), DIR_TYPE_VER))\n      error(\"directory not version 1\");\n    else\n      if (pathput)\n        strcpy( nn, \"/\");\n      else\n        *n = '\\0';              /* directories are discarded with zip -rj */\n  }\n  else if (vmsver == 0)\n  {\n    /* If not keeping version numbers, truncate the name at the \";\".\n       (No escaped characters are expected in the version.)\n    */\n    if ((ext_dir_and_name = strrchr( n, ';')) != NULL)\n      *ext_dir_and_name = '\\0';\n  }\n  else if (vmsver > 1)\n  {\n    /* Keeping version numbers, but as \".nnn\", not \";nnn\". */\n    if ((ext_dir_and_name = strrchr( n, ';')) != NULL)\n      *ext_dir_and_name = '.';\n  }\n\n  /* Remove a type-less dot. */\n  /* (Note that currently \"name..ver\" is not altered.) */\n  if ((ext_dir_and_name = strrchr( n, '.')) != NULL)\n  {\n    if (ext_dir_and_name[ 1] == '\\0')           /* \"name.\" -> \"name\" */\n      *ext_dir_and_name = '\\0';\n    else if (ext_dir_and_name[ 1] == ';')       /* \"name.;ver\" -> \"name;ver\" */\n    {\n      char *f = ext_dir_and_name+ 1;\n      while (*ext_dir_and_name++ = *f++);\n    }\n  }\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n\n  return n;\n}\n\n\nchar *in2ex( char *n)\n/* char *n;                internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;              /* external file name */\n  char *t;              /* scans name */\n  int i;\n  char chr;\n  char *endp;\n  char *last_slash;\n  char *versionp;\n\n#ifdef NAML$C_MAXRSS\n\n  char buf[ NAML$C_MAXRSS+ 1];\n  unsigned char prop;\n  unsigned char uchr;\n  char *last_dot;\n\n#endif /* def NAML$C_MAXRSS */\n\n  /* Locate the last slash. */\n  last_slash = strrchr( n, '/');\n\n/* If ODS5 is possible, replace escape carets in name. */\n\n#ifdef NAML$C_MAXRSS\n\n  endp = n+ strlen( n);\n\n  /* Locate the version delimiter, if one is expected. */\n  if (vmsver == 0)\n  { /* No version expected. */\n    versionp = endp;\n  }\n  else\n  {\n    if (vmsver > 1)\n    { /* Expect a dot-version, \".nnn\".  Locate the version \".\".\n         Temporarily terminate at this dot to allow the last-dot search\n         below to find the last non-version dot.\n      */\n      versionp = strrchr( n, '.');\n      if (versionp != NULL)     /* Can't miss. */\n      {\n        *versionp = '\\0';\n      }\n    }\n    else\n    { /* Expect a semi-colon-version, \";nnn\".  Locate the \";\".  */\n      versionp = strrchr( n, ';');\n    }\n    if ((versionp == NULL) || (versionp < last_slash))\n    { /* If confused, and the version delimiter was not in the name,\n         then ignore it.\n      */\n      versionp = endp;\n    }\n  }\n\n  /* No escape needed for the last dot, if it's part of the file name.\n     All dots in a directory must be escaped.\n  */\n  last_dot = strrchr( n, '.');\n\n  if ((last_dot != NULL) && (last_slash != NULL) && (last_dot < last_slash))\n  {\n    last_dot = last_slash;\n  }\n\n  /* Replace the version dot if necessary. */\n  if ((vmsver > 1) && (versionp != NULL) && (versionp < endp))\n  {\n    *versionp = '.';\n  }\n\n  /* Add ODS5 escape sequences.  Leave \"/\" and \"?\" for later.\n     The name here looks (roughly) like: dir1/dir2/a.b\n  */\n  t = n;\n  x = buf;\n  while (uchr = *t++)\n  {\n    /* Characters in the version do not need escaping. */\n    if (t <= versionp)\n    {\n      prop = char_prop[ uchr]& 31;\n      if (prop)\n      {\n        if (prop& 4)\n        { /* Dot. */\n          if (t < last_dot)\n          {\n            /* Dot which must be escaped. */\n            *x++ = '^';\n          }\n        }\n        else if (prop& 8)\n        {\n          /* Character needing hex-hex escape. */\n          *x++ = '^';\n          *x++ = hex_digit[ uchr>> 4];\n          uchr = hex_digit[ uchr& 15];\n        }\n        else\n        {\n          /* Non-dot character which must be escaped (and simple works).\n             \"?\" gains the caret but remains \"?\" until later.\n             (\"/\" remains (unescaped) \"/\".)\n          */\n          *x++ = '^';\n          if (prop& 2)\n          {\n            /* Escaped space (represented as \"^_\"). */\n            uchr = '_';\n          }\n        }\n      }\n    }\n    *x++ = uchr;\n  }\n  *x = '\\0';\n\n  /* Point \"n\" to altered name buffer, and re-find the last slash. */\n  n = buf;\n  last_slash = strrchr( n, '/');\n\n#endif /* def NAML$C_MAXRSS */\n\n  if ((t = last_slash) == NULL)\n  {\n    if ((x = malloc(strlen(n) + 1 + DIR_PAD)) == NULL)\n      return NULL;\n    strcpy(x, n);\n  }\n  else\n  {\n    if ((x = malloc(strlen(n) + 3 + DIR_PAD)) == NULL)\n      return NULL;\n\n    /* Begin with \"[\". */\n    x[ 0] = '[';\n    i = 1;\n    if (*n != '/')\n    {\n      /* Relative path.  Add \".\". */\n      x[ i++] = '.';\n    }\n    else\n    {\n      /* Absolute path.  Skip leading \"/\". */\n      n++;\n    }\n    strcpy( (x+ i), n);\n\n    /* Place the final ']'.  Remember where the name starts. */\n    *(t = x + i + (t - n)) = ']';\n    last_slash = t;\n\n    /* Replace \"/\" with \".\", and \"?\" with (now escaped) \"/\", in the\n       directory part of the name.\n    */\n    while (--t > x)\n    {\n      chr = *t;\n      if (chr == '/')\n      {\n        *t = '.';\n      }\n      else if (chr == '?')\n      {\n        *t = '/';\n      }\n    }\n\n    /* Replace \"?\" with (now escaped) \"/\", in the non-directory part of\n       the name.\n    */\n    while ((chr = *(++last_slash)) != '\\0')\n    {\n      if (chr == '?')\n      {\n        *last_slash = '/';\n      }\n    }\n  }\n\n/* If case preservation is impossible (VAX, say), and down-casing, then\n   up-case.  If case preservation is possible and wasn't done, then\n   there's no way to ensure proper restoration of original case, so\n   don't try.  This may differ from pre-3.0 behavior.\n*/\n#ifndef NAML$C_MAXRSS\n\n  if (vms_case_2 <= 0)\n  {\n    strupper( x);\n  }\n\n#endif /* ndef NAML$C_MAXRSS */\n\n  return x;\n}\n\nvoid stamp( char *f, ulg d)\n/* char *f;                name of file to change */\n/* ulg d;                  dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n  int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year;\n  char timbuf[24];\n  static ZCONST char *month[] = {\"JAN\", \"FEB\", \"MAR\", \"APR\", \"MAY\", \"JUN\",\n                                 \"JUL\", \"AUG\", \"SEP\", \"OCT\", \"NOV\", \"DEC\"};\n  struct VMStimbuf {\n      char *actime;           /* VMS revision date, ASCII format */\n      char *modtime;          /* VMS creation date, ASCII format */\n  } ascii_times;\n\n  ascii_times.actime = ascii_times.modtime = timbuf;\n\n  /* Convert DOS time to ASCII format for VMSmunch */\n  tm_sec = (int)(d << 1) & 0x3e;\n  tm_min = (int)(d >> 5) & 0x3f;\n  tm_hour = (int)(d >> 11) & 0x1f;\n  tm_mday = (int)(d >> 16) & 0x1f;\n  tm_mon = ((int)(d >> 21) & 0xf) - 1;\n  tm_year = ((int)(d >> 25) & 0x7f) + 1980;\n  sprintf(timbuf, \"%02d-%3s-%04d %02d:%02d:%02d.00\", tm_mday, month[tm_mon],\n    tm_year, tm_hour, tm_min, tm_sec);\n\n  /* Set updated and accessed times of f */\n  if (VMSmunch(f, SET_TIMES, (char *)&ascii_times) != RMS$_NMF)\n    zipwarn(\"can't set zipfile time: \", f);\n}\n\nulg filetime( char *f, ulg *a, zoff_t *n, iztimes *t)\n/* char *f;                name of file to get info on */\n/* ulg *a;                 return value: file attributes */\n/* zoff_t *n;              return value: file size */\n/* iztimes *t;             return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  struct stat s;        /* results of stat() */\n  /* convert to a malloc string dump FNMAX - 11/8/04 EG */\n  char *name;\n  int len = strlen(f);\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (name[len - 1] == '/')\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  if (strcmp(f, \"-\") == 0) {\n    if (fstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n  free(name);\n\n  if (a != NULL) {\n    *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);\n    if ((s.st_mode & S_IFDIR) != 0) {\n      *a |= MSDOS_DIR_ATTR;\n    }\n  }\n  if (n != NULL)\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1;\n  if (t != NULL) {\n    t->atime = s.st_mtime;\n#ifdef USE_MTIME\n    t->mtime = s.st_mtime;            /* Use modification time in VMS */\n#else\n    t->mtime = s.st_ctime;            /* Use creation time in VMS */\n#endif\n    t->ctime = s.st_ctime;\n  }\n\n#ifdef USE_MTIME\n  return unix2dostime((time_t *)&s.st_mtime); /* Use modification time in VMS */\n#else\n  return unix2dostime((time_t *)&s.st_ctime); /* Use creation time in VMS */\n#endif\n}\n\nint deletedir( char *d)\n/* char *d;                directory to delete */\n\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */\n    int r, len;\n    char *s;              /* malloc'd string for system command */\n\n    len = strlen(d);\n    if ((s = malloc(len + 34)) == NULL)\n      return 127;\n\n    system(strcat(strcpy(s, \"set prot=(o:rwed) \"), d));\n    r = delete(d);\n    free(s);\n    return r;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/vms/zip.opt",
    "content": "Ident = \"Zip 3.0\"\n"
  },
  {
    "path": "deps/infozip/zip30/vms/zip_cli.cld",
    "content": "\tModule\t\tZIP_CLITABLE\n\tIdent\t\t\"03-001\"\n\nDefine\tVerb\t\tZIP\n\tParameter\tP1, Label=ZIPFILE, Prompt=\"Zip file\"\n\tParameter\tP2, Label=INFILE, VALUE(list), Prompt=\"Files to Zip\"\n\tQualifier\tDELETE, NonNegatable\n\tQualifier\tFRESHEN, NonNegatable\n\tQualifier\tMOVE, NonNegatable\n\tQualifier\tUPDATE, NonNegatable\n\tQualifier\tEXCLUDE, NonNegatable, VALUE(required,list)\n\tQualifier\tINCLUDE, NonNegatable, VALUE(required,list)\n\tQualifier\tEXLIST, NonNegatable, VALUE(type=$FILE,required)\n\tQualifier\tINLIST, NonNegatable, VALUE(type=$FILE,required)\n\tQualifier\tADJUST_OFFSETS, NonNegatable\n\tQualifier\tAPPEND, NonNegatable\n\tQualifier\tBATCH, NonNegatable, VALUE(type=$FILE)\n\tQualifier\tBEFORE, NonNegatable, VALUE(type=$DATETIME)\n\tQualifier\tCOMMENTS, NonNegatable,\n\t\t\tVALUE(list,type=COMMENTS_KEYWORDS)\n\tQualifier\tCOMPRESSION, NonNegatable, VALUE(type=COMPRESS_OPTS)\n\tQualifier\tCOPY_ENTRIES, NonNegatable\n\tQualifier\tDESCRIPTORS, NonNegatable\n\tQualifier\tDIFFERENCE, NonNegatable\n\tQualifier\tDIRNAMES, Negatable, Default\n\tQualifier\tDISPLAY, NonNegatable,\n\t\t\t VALUE(type=DISPLAY_KEYWORDS, required, list)\n\tQualifier\tDOT_VERSION, NonNegatable\n\tQualifier\tENCRYPT, Negatable, VALUE\n\tQualifier\tEXTRA_FIELDS, Negatable, VALUE(type=EXTRA_OPTS)\n\tQualifier\tFILESYNC, NonNegatable\n\tQualifier\tFIX_ARCHIVE, NonNegatable, VALUE(type=FIX_OPTS)\n\tQualifier\tFULL_PATH, Negatable, Default\n\tQualifier\tGROW, NonNegatable\n\tQualifier\tHELP, NonNegatable, VALUE(type=HELP_OPTS)\n\tQualifier\tJUNK, NonNegatable\n\tQualifier\tKEEP_VERSION, Negatable\n\tQualifier\tLATEST, NonNegatable\n\tQualifier\tLEVEL, VALUE(type=$NUMBER,required)\n\tQualifier\tLICENSE, NonNegatable\n\tQualifier\tLOG_FILE, NonNegatable,\n\t\t\tVALUE(list, required, type=LOG_OPTS)\n\tQualifier\tMUST_MATCH, NonNegatable\n\tQualifier\tOUTPUT, VALUE(required,type=$FILE)\n\tQualifier\tPATTERN_CASE, NonNegatable, VALUE(type=PATT_CASE_OPTS)\n\tQualifier\tPAUSE, Negatable\n\tQualifier\tPKZIP, Negatable\n\tQualifier\tPRESERVE_CASE, Negatable,\n\t\t\t VALUE(type=PRES_CASE_OPTS, list)\n\tQualifier\tQUIET, NonNegatable\n\tQualifier\tRECURSE, Negatable, VALUE(type=RECURSE_OPTS)\n\tQualifier\tSHOW, NonNegatable,\n\t\t\t VALUE(type=SHOW_KEYWORDS, required, list)\n\tQualifier\tSINCE, NonNegatable, VALUE(type=$DATETIME)\n\tQualifier\tSPLIT, NonNegatable,\n\t\t\tVALUE(list, required, type=SPLIT_OPTS)\n\tQualifier\tSTORE_TYPES, NonNegatable, VALUE(required,list)\n\tQualifier\tSYMLINKS, NonNegatable\n\tQualifier\tTEMP_PATH, VALUE(required,type=$FILE)\n\tQualifier\tTEST, NonNegatable, VALUE(type=TEST_OPTS)\n\tQualifier\tTRANSLATE_EOL, NonNegatable,\n\t\t\tVALUE(type=EOL_KEYWORDS)\n\tQualifier\tUNSFX, NonNegatable\n\tQualifier\tVERBOSE, NonNegatable,\n\t\t\t VALUE(type=VERBOSE_OPTS, list)\n\tQualifier\tVMS, NonNegatable, VALUE(type=VMS_OPTS)\n\tQualifier\tWILDCARD, VALUE(type=WILDCARD_OPTS)\n\tQualifier\tYYZ_ZIP, NonNegatable, Default\n\tQualifier\tZIP64, NonNegatable\n\n\tDisallow\tCOPY_ENTRIES and (DELETE or FRESHEN or UPDATE)\n\tDisallow\tDELETE and (COPY_ENTRIES or FRESHEN or UPDATE)\n\tDisallow\tFRESHEN and (COPY_ENTRIES or DELETE or UPDATE)\n\tDisallow\tUPDATE and (COPY_ENTRIES or DELETE or FRESHEN)\n\tDisallow\tDIFFERENCE and (neg OUTPUT)\n\tDisallow\tDIFFERENCE and\n\t\t\t (FIX_ARCHIVE.NORMAL or FIX_ARCHIVE.FULL or\n\t\t\t COPY_ENTRIES or DELETE)\n\tDisallow\tAPPEND and GROW\n\tDisallow\tFIX_ARCHIVE.NORMAL and FIX_ARCHIVE.FULL\n\tDisallow\t(FIX_ARCHIVE.NORMAL or FIX_ARCHIVE.FULL) and\n\t\t\t (neg OUTPUT)\n\tDisallow\tTRANSLATE_EOL.LF and TRANSLATE_EOL.CRLF\n\tDisallow\tFULL_PATH and JUNK\n\tDisallow\tRECURSE.PATH and RECURSE.FILENAMES\n\tDisallow\t(neg EXTRA_FIELDS) and\n\t\t\t (KEEP_EXISTING or EXTRA_FIELDS.NORMAL)\n\nDefine\tType\t\tPATT_CASE_OPTS\n\tKeyword\t\tBLIND\n\tKeyword\t\tSENSITIVE, DEFAULT\n\nDefine\tType\t\tCOMMENTS_KEYWORDS\n\tKeyword\t\tARCHIVE, DEFAULT\n\tKeyword\t\tFILES\n\tKeyword\t\tZIP_FILE\n\nDefine\tType\t\tCOMPRESS_OPTS\n\tKeyword\t\tBZIP2\n\tKeyword\t\tDEFLATE, DEFAULT\n\tKeyword\t\tSTORE\n\nDefine\tType\t\tDISPLAY_KEYWORDS\n\tKeyword\t\tBYTES\n\tKeyword\t\tCOUNTS\n\tKeyword\t\tDOTS, VALUE\n\tKeyword\t\tGLOBALDOTS\n\tKeyword\t\tUSIZE\n\tKeyword\t\tVOLUME\n\nDefine\tType\t\tEOL_KEYWORDS\n\tKeyword\t\tLF, DEFAULT\n\tKeyword\t\tCRLF\n\nDefine\tType\t\tEXTRA_OPTS\n\tKeyword\t\tNORMAL, DEFAULT\n\tKeyword\t\tKEEP_EXISTING\n\nDefine\tType\t\tFIX_OPTS\n\tKeyword\t\tNORMAL, DEFAULT\n\tKeyword\t\tFULL\n\nDefine\tType\t\tHELP_OPTS\n\tKeyword\t\tNORMAL, DEFAULT\n\tKeyword\t\tEXTENDED\n\nDefine\tType\t\tLOG_OPTS\n\tKeyword\t\tAPPEND, Negatable\n\tKeyword\t\tINFORMATIONAL, Negatable\n\tKeyword\t\tFILE, NonNegatable, VALUE(required, type=$FILE)\n\nDefine\tType\t\tPRES_CASE_OPTS\n\tKeyword\t\tNOODS2\n\tKeyword\t\tNOODS5\n\tKeyword\t\tODS2\n\tKeyword\t\tODS5\n\nDefine\tType\t\tRECURSE_OPTS\n\tKeyword\t\tPATH, DEFAULT\n\tKeyword\t\tFILENAMES\n\nDefine\tType\t\tSHOW_KEYWORDS\n\tKeyword\t\tCOMMAND\n\tKeyword\t\tDEBUG\n\tKeyword\t\tFILES\n\tKeyword\t\tOPTIONS\n\nDefine\tType\t\tSPLIT_OPTS\n\tKeyword\t\tBELL, Negatable\n\tKeyword\t\tPAUSE, Negatable\n\tKeyword \tSIZE, VALUE(required)\n\tKeyword\t\tVERBOSE, Negatable\n\nDefine\tType\t\tTEST_OPTS\n\tKeyword\t\tUNZIP, VALUE(required)\n\nDefine\tType\t\tVERBOSE_OPTS\n\tKeyword\t\tNORMAL, DEFAULT\n\tKeyword\t\tMORE\n\tKeyword\t\tDEBUG\n\tKeyword\t\tCOMMAND\n\nDefine\tType\t\tVMS_OPTS\n\tKeyword\t\tALL\n\nDefine\tType\t\tWILDCARD_OPTS\n\tKeyword\t\tNOSPAN\n\n"
  },
  {
    "path": "deps/infozip/zip30/vms/zip_cli.help",
    "content": ".!\n.!  File:       ZIP_CLI.HELP\n.!\n.!  Author:     Christian Spieler\n.!\n.!  Date:       05 Dec 95 (orig. ZIP.RNH, 22 Oct 91)\n.!\n.!  Description:\n.!\n.!      TPU-processable source file to produce VMS on-line help for\n.!      portable Zip.  Adapted from ZIP.RNH, originally based on\n.!      ZIP.MAN (now MANUAL).\n.!\n.!      To build:\n.!          $ EDIT /TPU/NOSECTION/NODISPLAY/COMMAND=CVTHELP.TPU ZIP_CLI.HELP\n.!          $ RUNOFF /OUT=ZIP_CLI.HLP ZIP_CLI.RNH\n.!          $ LIBR /HELP/INSERT libr ZIP_CLI\n.!\n.!  Modification history:\n.!\n.!      01-001          Christian Spieler       05-DEC-1995 02:02\n.!              Genesis.\n.!      01-002          Christian Spieler       20-JAN-1996 03:09\n.!              Modified /LICENSE and /VERBOSE descriptions.\n.!      01-003          Christian Spieler       11-FEB-1996 23:09\n.!              Added /[NO]EXTRA_FIELDS description.\n.!      01-004          Christian Spieler       11-MAR-1996 20:08\n.!              Removed /ENCRYPT=VERIFY option.\n.!      01-005          Christian Spieler       11-MAY-1996 23:08\n.!              Corrected/enhanced info about how to get help on UNIX options.\n.!      01-006          Christian Spieler       21-JUL-1997 22:26\n.!              Updated for new options of Zip 2.2.\n.!      01-006          Christian Spieler       14-OCT-1997 22:04\n.!              Cleanups for Zip 2.2 release (no version change).\n.!      01-007          Steven Schweda          15-MAY-2007\n.!              Zip 3.0.\n.!      01-007          Ed Gordon               15-MAY-2007\n.!              Minor updates to Zip 3.0 help.\n.!\n<INIT>\n<MAIN>\nZIP\n\nZip is a compression and file packaging utility for several operating\nsystems, including UNIX, VMS,  MSDOS, OS/2, Windows 9x/NT/XP, Minix,\nAtari, Macintosh, Amiga, and Acorn RISC OS.  It is analogous to a\ncombination of tar and compress and is compatible with PKZIP (Phil\nKatz's ZIP) for MSDOS systems.\n\nZip is useful for packaging a set of files for distribution, for\narchiving files, and for saving disk space by temporarily compressing\nunused files or directories.  A companion program, UnZip, unpacks Zip\narchives.\n\nFor brief help on Zip or UnZip, run the program without specifying any\nparameters on the command line.\n\nThis description covers the Zip program which uses a VMS-style CLI\ncommand line.  The VMS CLI Zip program also accepts UNIX-style \"-opt\"\noptions, but a separate Zip program is available which provides only a\nUNIX-style  command line, and it has its own documentation.  Refer to\nthe Zip installation instructions for details.\n\n<FORMAT>\nZIP [/options] archive inpath, inpath ...\n\n.!\f\n\n<TOPIC>\nBasic_Usage\n\n<FORMAT>\nZIP [/options] archive inpath, inpath ...\n\nThe default action of Zip is to add or replace entries in \"archive\" from\nthe list of \"inpath\" file specifications, which can include directories\nand file names with VMS-style wildcards.  If /BATCH is specified, Zip\nwill read file specifications from a list file or from SYS$INPUT\n(stdin).\n\nWith SET PROCESS /PARSE_STYLE = EXTENDED (available on recent non-VAX\nsystems), Zip preserves the case of the command line.  Otherwise, mixed-\nor upper-case arguments (file names) must be quoted.  Examples in this\ndocument generally do not show this quotation, so VAX and /PARSE_STYLE =\nTRADITIONAL users (that is, troglodytes) will need to add quotation\nwhere needed when working with these examples.\n\nGeneral\n\nZip reads one or more files, compresses the data (normally), and stores\nthe compressed information into a single Zip archive file, along with\ninformation about each file (name, path, date and time of last\nmodification, protection, and check information to verify file\nintegrity).  On a VMS system, Zip can also save VMS/RMS file attributes,\nallowing UnZip to restore the files without loss of important file\nattributes.  Zip can pack an entire directory structure into a Zip\narchive with a single command.\n\nCompression\n\nCompression ratios of 2:1 to 3:1 are common for text files.  Zip has one\nstandard compression method (\"deflate\") and can also store files without\ncompression.  Zip (and UnZip) may be built with optional support for the\nbzip2 compression method.  Then, the user may select bzip2 compression\ninstead of the default \"deflate\" method.  Zip automatically chooses\nsimple storage over compression for a file, if the specified compression\nmethod does not actually compress the data in that file.\n\nCompatibility\n\nZip and UnZip can work with archives produced by PKZIP (supporting most\nPKZIP features up to PKZIP version 4.6), and PKZIP and PKUNZIP can work\nwith archives produced by Zip (with some exceptions, notably streamed\narchives, but recent changes in the .ZIP file standard may facilitate\nbetter compatibility).  Zip version 3.0 is compatible with PKZIP 2.04\nand also supports the Zip64 extensions of PKZIP 4.5 which allows\narchives as well as files to exceed the previous 2 GB limit (4 GB in\nsome cases).  Zip also supports bzip2 compression if the bzip2 library\nis included when Zip is built.  Note that PKUNZIP 1.10 cannot extract\nfiles produced by PKZIP 2.04 or Zip 3.0.  You must use PKUNZIP 2.04g or\nUnZip 5.0p1 (or later versions) to extract them.\n\nLarge Archives and Zip64\n\nWhere the operating system and C run-time support allow, Zip 3.0 and\nUnZip 6.0 (and later versions) support large files (input and archive),\nusing the Zip64 extensions to the original .ZIP file format.  On VMS,\nthis genarally means non-VAX systems with VMS V7.2 or later (perhaps\nrequiring a C RTL ECO before VMS V7.3-2).\n\nZip automatically uses the Zip64 extensions when a file 4 GB or larger\nis added to an archive, an archive containing a Zip64 entry is updated\n(if the resulting archive still needs Zip64), the size of the archive\nwill exceed 4 GB, or when the number of entries in the archive will\nexceed about 64K.  Zip64 is also used for archives streamed to a\nnon-seekable output device.  You must use a 4.5 compatible UnZip to\nextract files using the Zip64 extensions such as UnZip 6.0 or later.\n\nIn addition, streamed archives, entries encrypted with standard\nencryption, or split archives created with the pause option may not be\ncompatible with PKZIP as data descriptors are used, and PKZIP at the\ntime of this writing does not support data descriptors (but recent\nchanges in the PKWare published .ZIP file standard now include some\nsupport for the data descriptor format Zip uses).\n\n<TOPIC>\nMore_Usage\n\nHere is a very simple example of Zip use:\n\n<LITERAL>\n|  zip stuff.zip *.*\n<LARETIL>\n\nThis will create the Zip archive \"stuff.zip\" (assuming it does not\nalready exist) and put all the (non-directory) files (\";0\") from the\ncurrent default directory into \"stuff.zip\" in a compressed form.  The\narchive is opened using a default file specification of\n\"SYS$DISK:[].zip\", so specifying \"stuff\" as the archive name would also\ncreate (or use an existing) \"stuff.zip\", but specifying \"stuff.other\"\nwould give you that name.  In general, Zip doesn't care about the type\nin the file specification, but for split archives (archives split over\nmultiple files), the user should normally specify a type-less name,\nbecause Zip will normally generate sequentially numbered types \".z01\",\n\".z02\", and so on for the early splits, and then the required \".zip\" for\nthe last split.  These file types are required by the Zip standard for\nsplit archives.\n\nStandard VMS wildcard expansion ($SEARCH) is used to interpret the\n\"inpath\" file and directory specifications, like the \"*.*\" in this\nexample.\n\nOn VMS, the most natural way to archive an entire directory tree is to\nuse a directory-depth wildcard (\"[...]\").  For example:\n\n<LITERAL>\n|  zip foo [...]*.*\n<LARETIL>\n\nThis will create the file \"foo.zip\" containing all the files (\";0\") and\ndirectories in and below the current default directory.  A more\nUNIX-like way to do this would be to use the /RECURSE option:\n\n<LITERAL>\n|  zip /recurse foo *.*\n<LARETIL>\n\nZip avoids including its own output files when selecting files to\ninclude in the archive, so it should be safe, as in this case, to create\nthe archive in the same drectory as the input files.\n\nOne or more specific files, directories, or subdirectories may also be\nspecified:\n\n<LITERAL>\n|  zip foo.zip readme.txt, [www...]*.*, [.ftp...]*.*, -\n|   [.src]*.h, [.src]*.c\n<LARETIL>\n\nFor security reasons, paths in Zip archives are always stored as\nrelative paths, so some care is needed when creating an archive so that\nit will create the intended directory structure when UnZip is used to\nunpack it.\n\nTo use /RECURSE with a specific directory, the name of the directory\nfile itself must be specified:\n\n<LITERAL>\n|  zip /recurse foo.zip [000000]www.dir, ftp.dir\n<LARETIL>\n\nYou may want to make an archive that contains the files in [.foo], but\nnot record the directory name, \"foo\".  You can use the /JUNK (junk path)\noption to leave off the path:\n\n<LITERAL>\n|  zip /junk foo [.foo]*.*\n<LARETIL>\n\nIf you are short on disk space, you might not have enough room to hold\nboth the original directory and the corresponding compressed Zip\narchive.  In this case, you can create the archive in steps, and use the\n-m option.  For example, if [.foo] contains the subdirectories [.tom],\n[.dick], and [.harry], you could:\n\n<LITERAL>\n|  zip /move foo [.foo.tom...]*.*\n|  zip /move foo [.foo.dick...]*.*\n|  zip /move foo [.foo.harry...]*.*\n<LARETIL>\n\nThe first command would create foo.zip, and the next two would add to\nit.  The /MOVE option will cause Zip to delete all files added to the\narchive after making or updating foo.zip.  No deletions will be done\nuntil the Zip operation has completed with no errors.  This option is\nobviously dangerous and should be used with care, but it does reduce the\nneed for free disk space.  When /MOVE is used, the /TEST option is\nrecommended and will test the resulting archive before deleting the\ninput files.\n\nIf a file specification list is too long to fit conveniently on the Zip\ncommand line, the /BATCH option can be used to cause Zip to read a list\nof file specifications from a file or from SYS$INPUT (stdin).  If a DCL\ncommand procedure is used, the names can be specified in the procedure:\n\n<LITERAL>\n|  $ zip foo /batch\n|  $ deck\n|  file_spec_1\n|  file_spec_2\n|  file_spec_3\n|  $ eod\n<LARETIL>\n\nThe file specifications can also be put into a separate file, and fed\ninto Zip by specifying that file as \"/BATCH = list_file\", or by\nexplicitly defining SYS$INPUT, or by using PIPE.  For example, with the\nlist in foo.zfl:\n<LITERAL>\n|  zip foo /batch = foo.zfl\n<LARETIL>\nor:\n<LITERAL>\n|  define /user_mode sys$input foo.zfl\n|  zip foo /batch\n<LARETIL>\nor:\n<LITERAL>\n|  pipe type foo.zfl | zip foo /batch\n<LARETIL>\n\nIf Zip is not able to read a file, it issues a warning but continues.\nSee the /MUST_MATCH option for more on how Zip handles patterns that are\nnot matched and files that are not readable.  If some files were\nskipped, a warning is issued at the end of the Zip operation noting how\nmany files were read and how many skipped.\n<TOPIC>\nEnvironment\n\nA user can specify default command-line options and arguments by\ndefining an \"environment variable\" (that is, a logical name or DCL\nsymbol), \"ZIP_OPTS\" or \"ZIPOPT\", to specify them.  If both \"ZIP_OPTS\"\nand \"ZIPOPT\" are specified, the definition of \"ZIPOPT\" prevails.\n\nUNIX-style command-line options are required in these variables, even\nfor the VMS CLI Zip program.  For details, see the help topic\nUNIX_Options, or the separate Zip help for the UNIX-style command line.\n\nThe C RTL function getenv() is used to sense these variables, so its\nbehavior determines what happens if both a logical name and a symbol are\ndefined.  As of VMS V7.3, a logical name supercedes a symbol.\n\nThe \"zip /VERBOSE\" report should show the perceived settings of these\nvariables.\n\nFor example, the following will cause Zip to skip directories, include\nVMS portable attribute information, and perform all operations at\nquiet-level 1 by default:\n\n<LITERAL>\n|  $ define ZIP_OPTS \"-qDV\"\n<LARETIL>\n\nNote that the quotation marks here are required to preserve lowercase\noptions (opposite of the command-line behavior).\n\n<TOPIC>\nExit_Status\n\nOn VMS, Zip's UNIX-style exit values are mapped into VMS-style status\ncodes with facility code 1955 = %x7A3, and with the inhibit-message\n(%x10000000) and facility-specific (%x00008000) bits set:\n\n<LITERAL>\n|     %x17A38001                        normal exit\n|     %x17A38000+ 16* Zip_error_code    warnings\n|     %x17A38002+ 16* Zip_error_code    normal errors\n|     %x17A38004+ 16* Zip_error_code    fatal errors\n<LARETIL>\n\nNote that multiplying the UNIX-style Zip error code by 16 places it\nconveniently in the hexadecimal representation of the VMS exit code,\n\"__\" in %x17A38__s, where \"s\" is the severity code.  For example, a\ntruncated archive might cause Zip error code 2, which would be\ntransformed into the VMS exit status %x17A38024.\n\nThe Zip VMS exit codes include severity values which approximate those\ndefined by PKWARE, as shown in the following table:\n\n<LITERAL0>\n|  VMS      Zip err\n|severity    code     Error description\n|---------+---------+----------------------------------------------\n|Success       0      (OK) Normal; no errors or warnings detected.\n|Fatal         2      (EOF) Unexpected end of archive.\n|Error         3      (FORM) A generic error in the archive format\n|                     was detected.  Processing may have completed\n|                     successfully anyway;  some  broken  archives\n|                     created by other archivers have simple work-\n|                     arounds.\n|Fatal         4      (MEM) Zip was unable to allocate memory for\n|                     one or more buffers during program initializ-\n|                     ation.\n|Fatal         5      (LOGIC) A severe error in the archive format\n|                     was detected.  Processing  probably  failed\n|                     immediately.\n|Error         6      (BIG) Entry too large to  split,  read,  or\n|                     write.\n|Error         7      (NOTE) Invalid comment format.\n|Fatal         8      (TEST) Zip -T failed or out of memory.\n|Error         9      (ABORT) The user aborted  zip  prematurely\n|                     with  control-C (or equivalent).\n|Fatal        10      (TEMP) Zip  encountered an error while using\n|                     a tempfile.\n|Fatal        11      (READ) Read or seek error.\n|Warning      12      (NONE) Zip has nothing to do.\n|Error        13      (NAME) Missing or empty zip file.\n|Fatal        14      (WRITE) Error writing to a file.\n|Fatal        15      (CREAT) Zip was unable to create a file to\n|                     write to.\n|Error        16      (PARMS) Bad command line parameters.\n|Error        18      (OPEN) Zip could not open a specified file\n|                     to read.\n|Fatal        19      (COMPERR) Zip was built with options not\n|                     supported on this system.\n|Fatal        20      (ZIP64) Attempt to read unsupported Zip64\n|                     archive.\n<0LARETIL>\n\n<TOPIC>\nFile_Names\n\nZip deals with file names in the system file system and with file names\nin Zip archives.  File names in a Zip archive are stored in a UNIX-like\npath-name format.  For example, a VMS file specification like this:\n\n<LITERAL>\n[.zip30.vms]descrip.mms\n<LARETIL>\n\ncould appear in a Zip archive as:\n\n<LITERAL>\nzip30/vms/descrip.mms\n<LARETIL>\n\nFor security reasons, paths in Zip archives are always stored as\nrelative paths, so an absolute VMS directory specification will be\ntransformed to a relative path in the archive (that is, no leading \"/\").\nFor example, the following absolute directory specification would give\nthe same archive path as the previous (relative) example:\n\n<LITERAL>\n[zip30.vms]descrip.mms\n<LARETIL>\n\nAlso, device names are dropped, so the following file specification\nwould also give the same archive path:\n\n<LITERAL>\nsys$sysdevice:[zip30.vms]descrip.mms\n<LARETIL>\n\nIf an archive is intended for use with PKUNZIP under MSDOS, then the\n/PKZIP option should be used to attempt to adjust the names and paths to\nconform to MSDOS character-set and length limitations, to store only the\nMSDOS file attributes (just the owner:write attribute from VMS), and to\nmark the entry as made under MSDOS (even though it wasn't).\n\nNote that file specifications in the file system must be specified using\nVMS notation, but file names in an archive must be specified using the\nUNIX-like notation used in the archive.  For example, where a BACKUP\ncommand might look like this:\n\n<LITERAL>\n$ back [.zip30...]*.* /excl = [...vms]*.c stuff.bck /save\n<LARETIL>\n\na corresponding Zip command might look like this:\n\n<LITERAL>\n$ zip /exclude = \"*/vms/*.c\" stuff.zip [.zip30...]*.*\n<LARETIL>\n\nbecause the files to be added to the Zip archive are specified using VMS\nfile specifications, but the /EXCLUDE option excludes names based\non their archive path/file names.  Options dealing with archive names\ninclude /COPY_ENTRIES, /DELETE, /EXCLUDE, /INCLUDE, and\n/RECURSE=FILENAMES.\n\nNote that a UNIX-like path specification must be quoted, or else the\nslashes (\"/\") will confuse the command-line interpreter, causing errors\nlike \"%CLI-W-IVQUAL, unrecognized qualifier - check validity, spelling,\nand placement\".\n\nNote: By default, on VMS, archive name pattern matching (/COPY_ENTRIES,\n/DELETE, /EXCLUDE, /INCLUDE, and /RECURSE=FILENAMES) is case sensitive,\neven when the file system is not case sensitive (or even case\npreserving).  This allows accurate matching of mixed-case names in an\narchive which may have been created on a system with a case sensitive\nfile system, but it can involve extra effort on VMS, where it may be\nnecessary to use unnatural case names (or the same names in multiple\ncases, like \"*.obj *.OBJ\") for this kind of pattern matching to give the\ndesired behavior.  If completely case-blind pattern matching behavior is\ndesired, specify the /PATTERN_CASE=BLIND option.\n<TOPIC>\nModes_of_Operation\n\nZip supports two distinct types of command modes, external and\ninternal.  The external modes (update, grow, and freshen) read files\nfrom the file system (as well as from an existing archive) while the\ninternal modes (delete and copy) operate exclusively on entries in an\nexisting archive.\n\n<LITERAL>\n  /UPDATE\n<LARETIL>\n\nUpdate existing entries and add new files.  If the archive does not\nexist, create it.  This is the default mode, so /UPDATE is optional.\n\n<LITERAL>\n  /GROW\n<LARETIL>\n\nGrow (append to) the specified Zip archive, instead of creating a new\none.  If this operation fails, Zip attempts to restore the archive to\nits original state.  If the restoration fails, the archive might become\ncorrupted.  This option is ignored when there's no existing archive or\nwhen at least one archive member must be updated or deleted.\n\n<LITERAL>\n  /FRESHEN\n<LARETIL>\n\nUpdate existing entries in an existing archive.  Does not add new files\nto the archive.\n\n<LITERAL>\n  /DELETE\n<LARETIL>\n\nDelete entries from an existing archive.\n\n<LITERAL>\n  /COPY_ENTRIES\n<LARETIL>\n\nSelect entries in an existing archive and copy them to a new archive.\nCopy mode is like update mode, but entries in the existing archive are\nselected by command line patterns rather than files from the file system\nand it uses the /OUTPUT option to write the resulting archive to a new\nfile rather than updating the existing archive, leaving the original\narchive unchanged.\n\n<LITERAL>\n  /DIFFERENCE\n<LARETIL>\n\nCreate an incremental backup-style archive, where the resulting archive\nwill contain all new and changed files since the original archive was\ncreated.  For this to work, the input file list and current directory\nmust be the same as during the original Zip operation.\n\nFor example, if the existing archive was created using\n\n<LITERAL>\nzip foo_full.zip [.foo...]*.*\n<LARETIL>\n\nfrom just above the foo directory, then the command (also from just\nabove the foo directory):\n\n<LITERAL>\nzip /difference /output = foo_incr.zip foo_full.zip [.foo...]*.*\n<LARETIL>\n\ncreates the archive foo_incr.zip with just the files not in foo_full.zip\nand the files where the size or date-time of the files does not match\nthat in foo_full.zip.  Note that in the \"ZIP /DIFFERENCE\" operation, the\noriginal full archive is specified as the input archive, and the /OUTPUT\noption is used to specify the new (incremental) output archive.\n\n<LITERAL>\n  /FILESYNC\n<LARETIL>\n\nDelete entries in the archive that do not match files on the OS.\nNormally files already in an archive that are not updated remain\nin the archive unchanged.  The /FILESYNC option deletes files in\nthe archive that are not matched during the directory scan,\nresulting in the archive being updated having the same contents\nas a new archive would.  If much of the archive will remain\nunchanged, this can be faster than creating a new archive as\ncopying entries is faster than compressing and adding new files.\n\nNormally, when updating an archive using relative file specifications\n(\"[]\", \"[.xxx]\", and so on), it helps to have the same default directory\nas when the archive was created, but this is not a strict requirement.\n\n<TOPIC>\nSelf_Extracting_Archives\n\nA self-extracting archive (SFX) comprises a normal Zip archive appended\nto a special UnZip program (such as UNZIPSFX_CLI.EXE) for the intended\ntarget system.\n\nThe UnZip distribution includes a VMS command procedure,\n[,vms]makesfx.com, which can be used directly or adapted to create an\nSFX archive from a normal Zip archive.\n\nThe .ZIP file format includes offsets to data structures in the archive,\nand these offsets are measured from the start of the archive file.\nAppending an archive to an UnZip SFX executable effectively moves the\nstart of the archive file.  That makes the original offsets wrong, and\nthat will cause the UnZip SFX program to emit warning messages when it\ntries to unpack the archive.  Zip /ADJUST_OFFSETS can be used to adjust\nthese offsets in a self-extracting archive.  For example, to adjust the\noffsets in foo.sfx_exe:\n\n<LITERAL>\n|  zip /adjust_offsets foo.sfx_exe\n<LARETIL>\n\nSimilarly, the UnZip SFX program can be removed from a self-extracting\narchive (and the offsets in the archive restored) using the /UNSFX\noption.  For example:\n\n<LITERAL>\n|  zip /unsfx foo.sfx_exe\n<LARETIL>\n\nNote that a self-extracting archive contains a normal Zip archive, and a\nnormal UnZip program can be used to expand it in the normal way.  You\nmay get a warning about extra bytes at the beginning of the archive (the\nUnZip SFX program), but UnZip should work properly after that.  This\nallows data in a self-extracting archive to be accessed on any system,\nnot just the target system where its embedded UnZip SFX program runs.\n\n<TOPIC>\nSplit_Archives\n\nBeginning with version 3.0, Zip supports split archives.  A split\narchive is one which is divided into multiple files, usually to allow it\nto be stored on multiple storage media (floppy diskettes, CD-ROMs, or\nthe like) when a single medium would be too small to contain the whole\narchive.  (Note that split archives are not just unitary archives split\ninto pieces, as the .ZIP file format includes offsets to data structures\nin the archive, and for a split archive these are based on the start of\neach split, not on the start of the whole archive.  Concatenating the\npieces will invalidate these offsets, but UnZip can usually deal with\nit.  Zip will usually refuse to process such a spliced archive unless\nthe /FIX = FULL option is used to fix the offsets.)\n\nFor a split archive with, say, 20 split files, the files are typically\nnamed ARCHIVE.z01, ARCHIVE.z02, ..., ARCHIVE.z19, ARCHIVE.zip, where\n\"ARCHIVE\" is the archive name specified by the user on the Zip command\nline.  Note that the last split file is the \".zip\" file.  In contrast,\n\"spanned\" archives are the original multi-disk archive generally\nrequiring floppy disks and using volume labels to store disk numbers.\nZip supports split archives but not spanned archives, though a procedure\nexists for converting split archives of the right size to spanned\narchives.  The reverse is also true, where each file of a spanned\narchive can be copied in order to files with the above names to create a\nsplit archive.\n\n<QUALIFIERS>\n<QUALIFIER>\n/ADJUST_OFFSETS\n\n/ADJUST_OFFSETS\n\nAdjust internal offsets of the Zip archive members after some data\n(e.g. a SFX executable stub) has been prepended to the archive file.\n<QUALIFIER>\n/APPEND\n\n/APPEND\n/GROW\n\nGrow (append to) the specified Zip archive, instead of creating a new\none.  If this operation fails, Zip attempts to restore the archive to\nits original state.  If the restoration fails, the archive might become\ncorrupted.  This option is ignored when there's no existing archive or\nwhen at least one archive member must be updated or deleted.\n\nSee also /DELETE /DIFFERENCE, /FRESHEN, /UPDATE.\n<QUALIFIER>\n/BATCH\n\n/BATCH[=list_file]\n\nRead input file specifications (inpaths) from \"list_file\" (one per\nline).  The list_file defaults to SYS$INPUT.\n<QUALIFIER>\n/BEFORE\n\n/BEFORE=VMS_date_time\n\nRestricts the files by date-time when adding, updating, or freshening an\narchive.  Only files with modification date-times earlier than the\nspecified date-time are accepted.\n\nSee also /SINCE.\n<QUALIFIER>\n/COMMENTS\n\n/COMMENTS[=KEYWORD[,KEYWORD]]\n\nAdd comments to the Zip archive.\n\n<LITERAL>\n|  ARCHIVE   Add/replace the multi-line archive comment. (default)\n|  FILES     Add file comment to each updated/added archive member.\n<LARETIL>\n\nThe Zip program prompts for each comment to be added, which makes sense\nonly if Zip is run interactively.\n\nThe one-line file (archive member) comments are terminated by typing\n<Return>.  To skip a file comment, just type <Return> without entering\nany further characters.\n\nThe Zip archive comment may be multi-line. The comment is ended by a\nline containing just a period, or by an end-of-file character (CTRL/Z).\n<QUALIFIER>\n/COMPRESSION\n\n/COMPRESSION = {BZIP2|DEFLATE|STORE}\n\nSpecify the compression method to be used when adding or updating files\nin an archive.  STORE disables compression (like /LEVEL = 0).  Default:\n/COMPRESSION = DEFLATE.\n\nZip can archive files with or without compression.  The standard\ncompression method (\"deflate\") is compatible with all UnZip versions\n(except really old ones that only understand the \"store\" method).\nCurrent Zip and UnZip versions may be built with optional support for\nthe bzip2 compression method.  (The bzip2 method can compress better,\nespecially when compressing highly redundant files, but uses more CPU\ntime, and requires an UnZip which includes the optional bzip2 support.\nSee the installation instructions for details on adding bzip2\ncompression support at build time.)\n<QUALIFIER>\n/COPY_ENTRIES\n\n/COPY_ENTRIES\n\nSelect entries in an existing archive and copy them to a new archive.\nCopy mode is like update mode, but entries in the existing archive are\nselected by command line patterns rather than files from the file system\nand it uses the /OUTPUT option to write the resulting archive to a new\nfile rather than updating the existing archive, leaving the original\narchive unchanged.\n<QUALIFIER>\n/DELETE\n\n/DELETE\n\nDelete entries from archive.\n\nSee also /DIFFERENCE, /FRESHEN, /GROW, /UPDATE.\n<QUALIFIER>\n/DIFFERENCE\n\n/DIFFERENCE\n\nCreate an incremental backup-style archive, where the resulting archive\nwill contain all new and changed files since the original archive was\ncreated.  For this to work, the input file list and current directory\nmust be the same as during the original Zip operation.\n\nSee also /DELETE, /FRESHEN, /GROW, /UPDATE.\n<QUALIFIER>\n/DIRNAMES\n\n/DIRNAMES (default)\n/NODIRNAMES\n\nStore directory entries in the archive.\n<QUALIFIER>\n/DISPLAY\n\n/DISPLAY=(KEYWORD[,KEYWORD[...]])\n\nEnable display of progress messages.\n<LITERAL>\n|  BYTES        Running count of bytes processed and bytes to go.\n|  COUNTS       Running count of entries done and entries to go.\n|  DOTS = size  Dots every <size> MB while processing files.\n|               (0: no dots.)\n|  GLOBALDOTS   Progress dots reflect the whole archive instead of each\n|               file.\n|  USIZE        Uncompressed size of each entry.\n|  VOLUME       Display the volume (disk) number each entry is being\n|               written to.\n<LARETIL>\n\nThe default is a dot every 10 MB of input file processed.  The /VERBOSE\noption also displays dots and used to at a higher rate than this (at the\nsame rate as in previous versions of Zip) but this rate has been changed\nto the new 10 MB default, and is also controlled by /DISPLAY=DOTS=size.\n<QUALIFIER>\n/DOT_VERSION\n\n/DOT_VERSION\n\nDirects Zip to retain VMS file version numbers on names in an archive,\nbut as \".nnn\" instead of \";nnn\".  By default, for compatibility\nwith non-VMS systems, Zip strips VMS file version numbers from the names\nstored in an archive.  Thus, without /DOT_VERSION or /KEEP_VERSION, a\nversion number wildcard (\";*\") can cause errors when multiple versions\nof a single file are treated as multiple files with the same name.\n\nSee also /KEEP_VERSION.\n<QUALIFIER>\n/ENCRYPT\n\n/ENCRYPT[=\"password\"]\n\nEncrypt new or updated archive entries using a password which is\nsupplied by the user interactively on the terminal in response to a\nprompt.  (The password will not be echoed.)  If SYS$COMMAND is not a\nterminal, Zip will exit with an error.  The password is verified before\nbeing accepted.\n\nYou may specify the password on the command line, although we do not\nrecommend it because THIS IS INSECURE.  Remember to enclose the password\nstring with quotation marks (\"pass word\"), to prevent automatic\nconversion to upper case or misinterpretation of punctuation characters\nby DCL.\n\nBecause standard Zip encryption is weak, where security is truly\nimportant, use a strong encryption program, such as Pretty Good Privacy\n(PGP) or GNU Privacy Guard (GnuPG), on an archive instead of standard\nZip encryption.  A stronger encryption method, such as AES, is planned\nfor Zip 3.1.\n<QUALIFIER>\n/EXCLUDE\n\n/EXCLUDE=(file[,...])\n\nA comma-separated list of files to exclude when deleting, updating, or\nadding files in the archive.  If multiple files are specified, the list\nshould be enclosed in parentheses.\n<QUALIFIER>\n/EXLIST\n\n/EXLIST=list_file\n\nThe files matching the filename patterns listed in \"list_file\" are\nexcluded when deleting, updating or adding files in the archive.\nThe \"list_file\" is a normal text file with one filename pattern entry per\nline.  The name pattern entries are recognized exactly as found in\n\"list_file\", including leading, embedded, and trailing whitespace or most\ncontrol characters (with exception of LineFeed and probably CarriageReturn).\n<QUALIFIER>\n/EXTRA_FIELDS\n\n/EXTRA_FIELDS (default)\n/NOEXTRA_FIELDS\n\nAllows (or suppresses) the saving of any optional extra fields in the\narchive.  (/NOEXTRA_FIELDS conflicts with /VMS[=ALL].)\n\nThe .ZIP file format allows some extra data to be stored with a file in\nthe archive.  For example, where local time zone information is\navailable, Zip can store UTC date-time data for files.  (Look for\nUSE_EF_UT_TIME in a \"zip -v\" report.)  On VMS, with /VMS[=ALL], Zip will\nalso store VMS-specific file attributes.  These data are packaged as\n\"extra fields\" in the archive.  Some extra fields are specific to a\nparticular operating system (like VMS file attributes).  Large files\n(bigger than 4GB) on any OS require an extra field to hold their 64-bit\nsize data.  Depending on the capabilities of the UnZip program used to\nexpand the archive, these extra fields may be used or ignored when files\nare extracted from the archive.\n\nSome extra fields, like UTC date-times or VMS file attributes, are\noptional.  Others, like the Zip64 extra field which holds 64-bit sizes\nfor a large file, are required.\n<QUALIFIER>\n/FILESYNC\n\n/FILESYNC\n\nDelete entries in the archive that do not match files on the OS.\nNormally when an archive is updated, new files are added and changed\nfiles are updated but files that no longer exist on the OS are not\ndeleted from the archive.  This option enables deleting of entries that\nare not matched on the OS.  Enabling this option should create archives\nthat are the same as new archives, but since existing entries are copied\ninstead of compressed, updating an existing archive with /FILESYNC can\nbe much faster than creating a new archive.  If few files are being\ncopied from the old archive, it may be faster to create a new archive\ninstead.\n\nThis option deletes files from the archive.  If you need to preserve the\noriginal archive, make a copy of the archive first, or use the /OUTPUT\noption to output the new archive to a new file.  Even though it's\nslower, creating a new archive with a new archive name is safer, avoids\nmismatches between archive and OS paths, and is preferred.\n<QUALIFIER>\n/FIX_ARCHIVE\n\n/FIX=_ARCHIVE={NORMAL|FULL}\n\nThe /FIX_ARCHIVE=NORMAL option (NORMAL is the default) can be used if\nsome portions of the archive are missing, but it requires a reasonably\nintact central directory.  The input archive is scanned as usual, but\nzip will ignore some problems. The resulting archive should  be valid,\nbut any inconsistent entries will be left out.\n\nIf the archive is too damaged or the end (where the central directory is\nsituated) has been truncated, you must use /FIX_ARCHIVE=FULL.  This is\na change from zip 2.32, where the /FIX=NORMAL option was able to read a\ntruncated archive.  The /FIX=NORMAL option now more reliably fixes\narchives with minor damage, and the /FIX=FULL option is needed to fix\nsome archives where /FIX=NORMAL was sufficient before.\n\nWith /FIX=FULL, the archive is scanned from the beginning and Zip scans\nfor special signatures to identify the limits between the archive\nmembers. The /FIX=NORMAL option is more reliable if the archive is not\ntoo much damaged, so try this option first.\n\nNeither option will recover archives that have been incorrectly\ntransferred, such as by FTP in ASCII mode instead of binary.  After the\nrepair, the /TEST (-t) option of UnZip may show that some files have a\nbad CRC. Such files cannot be recovered; you can remove them from the\narchive using the /DELETE option of Zip.\n\nBecause of the uncertainty of the \"fixing\" process, it's required\nto specify an output archive, rather than risking further damage to the\noriginal damaged archive.  For example, to fix the damaged archive\nfoo.zip:\n\n<LITERAL>\nzip /fix_archive /output=foo_fix foo\n<LARETIL>\n\ntries to read the entries normally, copying good entries to the new\narchive foo_fix.zip.  If this doesn't work, as when the archive is\ntruncated, or if some entries are missed because of bad central\ndirectory entries, try /FIX_ARCHIVE=FULL:\n\n<LITERAL>\nzip /fix_archive=full /output=foo_fixfix foo\n<LARETIL>\n\nand compare the resulting archive to the archive created using\n/FIX=NORMAL.  The /FIX=FULL option may create an inconsistent archive. \nDepending on what is damaged, you can then use the /FIX=NORMAL option to\nfix that archive.\n\nA split archive with missing split files can be fixed using /FIX=NORMAL\nif you have the last split of the archive (the \".zip\" file).  If this\nfile is missing, you must use /FIX=FULL to fix the archive, which will\nprompt you for the splits you have.\n\nCurrently, the fix options can't recover an entry which has a bad\nchecksum or is otherwise damaged.\n<QUALIFIER>\n/FRESHEN\n\n/FRESHEN\n\nUpdate existing entries in an existing archive.  Does not add new files\nto the archive.\n\nSee also /DELETE, /DIFFERENCE, /GROW, /UPDATE.\n<QUALIFIER>\n/FULL_PATH\n\n/FULL_PATH  (default)\n/NOFULL_PATH\n\nDirects Zip to store the directory part of the file names (relative to\nthe current working directory) in the Zip archive.  With /NOFULL_PATH,\nZip stores only the file names, discarding any directory information.\n<QUALIFIER>\n/GROW\n\n/GROW\n/APPEND\n\nGrow (append to) the specified Zip archive, instead of creating a new\none.  If this operation fails, Zip attempts to restore the archive to\nits original state.  If the restoration fails, the archive might become\ncorrupted.  This option is ignored when there's no existing archive or\nwhen at least one archive member must be updated or deleted.\n\nSee also /DELETE, /DIFFERENCE, /FRESHEN, /UPDATE.\n<QUALIFIER>\n/HELP\n\n/HELP[=EXTENDED]\n\nDisplay Zip's help screen, including the version message.  With\n/HELP=EXTENDED, more detailed (longer) help information is shown.\n<QUALIFIER>\n/INCLUDE\n\n/INCLUDE=(file[,...])\n\nA comma-separated list of files to include when deleting, updating, or\nadding files in the archive.  If multiple files are specified, the list\nshould be enclosed in parentheses.\n<QUALIFIER>\n/INLIST\n\n/INLIST=list_file\n\nThe files matching the filename patterns listed in \"list_file\" are\nincluded when deleting, updating, or adding files in the archive.\nThe \"list_file\" is a normal text file with one filename pattern entry per\nline. The name pattern entries are recognized exactly as found in\n\"list_file\", including leading, embedded, and trailing whitespace or most\ncontrol characters (with exception of LineFeed and probably CarriageReturn).\n<QUALIFIER>\n/JUNK\n\n/JUNK\n/NOJUNK (default)\n\nJunk (discard) the directory part of the file names for added entries\n(do not not save the directory structure). The /JUNK qualifier is an\nalias for /NOFULL_PATH.\n<QUALIFIER>\n/KEEP_VERSION\n\n/KEEP_VERSION\n/NOKEEP_VERSION (default)\n\nDirects Zip to retain VMS file version numbers on names in an archive.\nBy default, for compatibility with non-VMS systems, Zip strips VMS\nfile version numbers from the names stored in an archive.  Thus, without\n/DOT_VERSION or /KEEP_VERSION, a version number wildcard (\";*\") can\ncause errors when multiple versions of a single file are treated as\nmultiple files with the same name.\n\nSee also /DOT_VERSION.\n<QUALIFIER>\n/LATEST\n\n/LATEST\n\nThe archive's creation and modification time is set to the latest\nmodification time of all archive members.\n<QUALIFIER>\n/LEVEL\n\n/LEVEL=number\n\nSpecifies the compression level:\n<LITERAL>\n|  0      Store\n|  1      Fastest compression (Defl:F)\n|  ...\n|  9      Best compression    (Defl:X)\n<LARETIL>\n\nThe default level is 6.\n<QUALIFIER>\n/LICENSE\n\n/LICENSE\n\nDisplays the Zip license.\n<QUALIFIER>\n/LOG_FILE\n\n/LOG_FILE=(FILE=log_file [, APPEND] [, INFORMATIONAL])\n\nZip normally sends messages to the user's terminal, but these may be\nalso directed to a log file.\n\n<LITERAL>\n  FILE=log_file\n<LARETIL>\n\nOpen a logfile at the given path.  By default, a new version will be\ncreated.  \n\n<LITERAL>\n  APPEND\n<LARETIL>\n\nAppend to an existing log file.  Default is to create a new version.\n\n<LITERAL>\n  INFORMATIONAL\n<LARETIL>\n\nOnly warnings and errors are written to the log unless the INFORMATIONAL\noption is also specified, then all information messages are also written\nto the log.\n<QUALIFIER>\n/MOVE\n\n/MOVE\n\nMove the specified files into the Zip archive.  That is, Zip will delete\nany files which are successfully added to or updated in the archive.  No\ndeletions will be done until the Zip operation has completed with no\nerrors.  This option is obviously dangerous and should be used with\ncare, but it does reduce the need for free disk space.  It's recommended\nthat /TEST also be used to test the archive before the input files are\ndeleted.\n<QUALIFIER>\n/MUST_MATCH\n\n/MUST_MATCH\n\nAll input patterns must match at least one file and all input files\nfound must be readable.  Normally when an input pattern does not match\na file the \"name not matched\" warning is issued and when an input\nfile has been found but later is missing or not readable a \"missing or\nnot readable\" warning is issued.  In either case Zip continues\ncreating the archive, with missing or unreadable new files being skipped\nand files already in the archive remaining unchanged.  After the\narchive is created, if any files were not readable zip returns the OPEN\nerror code (18 on most systems) instead of the normal success return (0\non most systems).  With /MUST_MATCH, Zip exits as soon as an input\npattern is not matched (whenever the \"name not matched\" warning would be\nissued) or when an input file is not readable.  In either case Zip exits\nwith an OPEN error and no archive is created.\n\nThis option is useful when a known list of files is to be zipped so any\nmissing or unreadable files should result in an error.  It may be less\nuseful when used with wildcards, but Zip will still exit with an error\nif any input pattern doesn't match at least  one file or if any\nmatched files are unreadable.  If you want to create the archive anyway\nand only need to know if files were skipped, then don't use /MUST_MATCH\nand just check the exit status.  Also, a log file (see /LOG_FILE) could\nbe useful.\n<QUALIFIER>\n/PATTERN_CASE\n\n/PATTERN_CASE={BLIND|SENSITIVE}\n\n<LITERAL>\n|  BLIND      Use case-blind pattern matching for archive entry names.\n|  SENSITIVE  Use case-sensitive pattern matching for archive entry\n|             names.  (Default.)\n<LARETIL>\n\nBy default, on VMS, archive name pattern matching (/COPY_ENTRIES,\n/DELETE, /EXCLUDE, /INCLUDE, and /RECURSE=FILENAMES) is case sensitive,\neven when the file system is not case sensitive (or even case\npreserving).  This allows accurate matching of mixed-case names in an\narchive which may have been created on a system with a case sensitive\nfile system, but it can involve extra effort on VMS, where it may be\nnecessary to use unnatural case names (or the same names in multiple\ncases, like \"*.obj *.OBJ\") for this kind of pattern matching to give the\ndesired behavior.  If completely case-blind pattern matching behavior is\ndesired, specify the /PATTERN_CASE=BLIND option.\n<QUALIFIER>\n/PKZIP\n\n/PKZIP\n/NOPKZIP (default)\n\nCreate PKZIP-compatible archive entries.  File names and paths are\nadjusted to conform to MSDOS character-set and length\nlimitations, to store only the MSDOS file attributes (just the\nowner:write attribute from VMS), and to mark the entry as made under\nMSDOS (even though it wasn't).\n<QUALIFIER>\n/PRESERVE_CASE\n\n/NOPRESERVE_CASE\n/PRESERVE_CASE[=(keyword[, ...])]\n\nDirects Zip to preserve the case of, or convert to lower-case, file names\nin the archive.  Optional keywords are:\n<LITERAL>\n|  NOODS2        Down-case ODS2 file names (default).\n|  NOODS5        Down-case ODS5 file names.\n|  ODS2          Preserve case of ODS2 file names.\n|  ODS5          Preserve case of ODS5 file names (default).\n<LARETIL>\n\nBy default, file names from an ODS2 file system are converted to lower\ncase for storage in an archive, while the case of file names from an\nODS5 file system is preserved.\n\n/NOPRESERVE_CASE is equivalent to /PRESERVE_CASE = (NOODS2, NOODS5),\nwhich causes all file names to be converted to lower-case.  This is\nequivalent to the behavior of Zip before version 3.0.\n\n/PRESERVE_CASE is equivalent to /PRESERVE_CASE = (ODS2, ODS5), which\npreserves the case of all file names.\n<QUALIFIER>\n/QUIET\n\n/QUIET\n\nQuiet mode.  Eliminates informational messages and comment prompts.\nThis mode may be useful in command procedures, or if the Zip operation\nis being performed as a background task (\"$ spawn/nowait zip /quiet foo\n*.c\").\n<QUALIFIER>\n/RECURSE\n\n/RECURSE[=KEYWORD]\n/NORECURSE (default)\n\nDirects Zip to recurse into subdirectories.\nThe optional keywords recognized are:\n<LITERAL>\n|  PATH      take patterns as full path specifiers (-r) (default)\n|  FILENAMES start from current dir;\n|            only use filename part of file patterns (-R)\n<LARETIL>\nThe optional FILENAMES keyword modifies the recursion algorithm to be\n(almost) compatible to PKZIP's behaviour on subdirectory recursion.\n\nOn VMS, directory recursion can also be requested by using the\ndirectory depth wildcard (\"[...]\") in an input file specification.\n<QUALIFIER>\n/SHOW\n\n/SHOW=(KEYWORD[,KEYWORD[...]])\n\nControls various diagnostic messages.\n\nThe keywords recognized are:\n<LITERAL>\n|  COMMAND  Show command line arguments as processed (only, then exit).\n|  DEBUG    Show Debug information.\n|  FILES    Show files to process (only, then exit).\n|  OPTIONS  Show all available command-line options on this system.\n<LARETIL>\n<QUALIFIER>\n/SINCE\n\n/SINCE=VMS_date_time\n\nRestricts the files by date-time when adding, updating, or freshening an\narchive.  Only files with modification date-times at or later than the\nspecified date-time are accepted.\n\nSee also /BEFORE.\n<QUALIFIER>\n/SPLIT\n\n/SPLIT = (SIZE=size [, PAUSE [, BELL]] [, VERBOSE])\n\nEnables split archives, specifies the size of the splits, and controls\nother related behavior.\n\nSIZE=size  specifies the split size.  The size is given as a number\nfollowed optionally by a multiplier suffix of k (KB), m (MB, the default\nif no suffix is specified), g (GB), or t (TB).  (All are powers of 1024,\nnot 1000).  64K is the minimum split size.  For example, the following\ncommand could be used to create a split archive called \"foo\" from the\ncontents of the \"bar\" directory with splits of 670MB, which might be\nuseful for burning on CDs:\n\n<LITERAL>\n|  zip /split = size = 670m foo [.bar...]*.*\n<LARETIL>\n\nUsing /SPLIT without PAUSE as above creates all the splits in the\ndirectory\nspecified by \"foo\", in this case the current default directory.  This\nsplit mode updates the splits as the archive is being created, requiring\nall splits to remain writable, but creates split archives that are\nreadable by any UnZip that supports split archives.  See PAUSE below for\nenabling split pause mode which allows splits to be written directly to\nremovable media.\n\nPAUSE  causes Zip to pause between splits to allow\nchanging removable media, for example.  PAUSE uses stream mode to\nwrite splits so unzips that can't read stream mode entries may not\nbe able to read some entries in the archive.  Unless standard encryption\nwas used, copy mode using /COPY_ENTRIES can convert stream mode entries\nto normal entries.\n\nBELL  ring the terminal bell when Zip pauses for the next split\ndestination.\n\nVERBOSE  enables verbose splitting and display details of how the\nsplitting is being done.\n\nThough Zip does not update split archives, Zip provides the option\n/OUTPUT to allow split archives to be updated and saved in a new\narchive.  For example:\n\n<LITERAL>\n|  zip inarchive.zip foo.c bar.c /output = outarchive.zip\n<LARETIL>\n\nreads archive inarchive.zip, even if split, adds the files foo.c and\nbar.c, and writes the resulting archive to outarchive.zip.  If\ninarchive.zip is split, then outarchive.zip defaults to the same split\nsize.  Be aware that outarchive.zip and any split files that are created\nwith it are always overwritten without warning.  This may be changed in\nthe future.\n<QUALIFIER>\n/STORE_TYPES\n\n/STORE_TYPES=(.ext1,.ext2,... )\n\nNormally, a file which is already compressed will not be compressed much\nfurther (if at all) by Zip, and trying to do it can waste considerable\nCPU time.  Zip can suppress compression on files with particular types,\nspecified with /STORE_TYPES.  The default list of types where\ncompression is suppressed is /STORE_TYPES=(.Z, .zip, .zoo, .arc, .lzh,\n .arj), and the comparison is case-insensitive.\n\n/LEVEL=9 will override /STORE_TYPES, causing compression to be attempted\nfor all files.\n<QUALIFIER>\n/SYMLINKS\n\n/SYMLINKS\n\nStore symbolic links as such in the Zip archive, instead of compressing\nand storing the file referred to by the link.  A symbolic link normally\nrequires less storage than the actual file, both in the archive, and on\nthe destination file system.\n\nOn VMS, symbolic links are supported on ODS5 disks where the C RTL\nsupports symbolic links.  Full support for symbolic links seems to\nrequire VMS V8.3, but a Zip program supporting symbolic links may be\nbuilt on VMS V7.3-2.\n<QUALIFIER>\n/TEMP_PATH\n\n/TEMP_PATH=temp_dir\n\nWhen creating a new archive or normally when changing an existing\narchive, Zip will write a temporary file in the archive destination\ndirectory (\"ZIxxxxxxxx\", where \"xxxxxxxx\" is the hexadecimal process ID)\nwith the new contents.  Then, if and when the Zip job has completed with\nno errors, it will rename the temporary file to the specified archive\nname (replacing the old archive, if any).\n\n/TEMP_PATH=temp_dir specifies an alternate device:[directory],\n\"temp_dir\", for the temporary file, but specifying a different device\nwill force Zip to copy the temporary file to its final destination\ninstead of simply renaming it, and that copying will take more time than\nrenaming, especially for a large archive.  For example:\n\n<LITERAL>\n|  zip /temp_path = disk$scratch:[tmp] stuff *\n<LARETIL>\n\nwill cause Zip to put its temporary files in the directory\n\"disk$scratch:[tmp]\", copying the temporary file back to the current\ndirectory as stuff.zip when it's complete.\n<QUALIFIER>\n/TEST\n\n/TEST[=UNZIP=unzip_cmd]\n\nTest the integrity of a Zip archive (the new one, if /OUTPUT is\nspecified).  If the check fails, the old archive is unchanged  and\n(with the /MOVE option) no input files are removed.\n\nImplementation\n\"zip /TEST\" actually runs an \"unzip -t\" command to do the testing, so\nUnZip must be installed properly for this to work.\n\nWith UNZIP=unzip_cmd, Zip uses the UnZip command specified by\n\"unzip_cmd\" (normally a DCL symbol), instead of the default command,\n\"unzip -t\".  This can be useful if multiple versions of UnZip are\ninstalled on a system, and the default DCL symbol \"UNZIP\" would run the\nwrong one (or the logical name DCL$PATH would lead to the wrong one).\n\nIn \"unzip_cmd\", the string \"{}\" is replaced by the name of the\n(temporary) archive to be tested, otherwise the name of the archive is\nappended to the end of the command.  The exit status is checked for\nsuccess severity.\n<QUALIFIER>\n/TRANSLATE_EOL\n\n/TRANSLATE_EOL[=KEYWORD]\n\nSelects conversion of the end-of-line markers in text files.  This\noption should be used on text files only.  The optional keywords\nrecognized are:\n<LITERAL>\n|  LF        convert LF -> CRLF (UNIX to DOS) (default)\n|  CRLF      convert CRLF -> LF, strip trailing CTRL-Z's (DOS to UNIX)\n<LARETIL>\n\nThe CRLF option may be useful when a DOS text file has been transfered\nto a VMS disk in stream (or stream_lf) format.\n<QUALIFIER>\n/UNSFX\n\n/UNSFX\n\nStrip any prepended data from the Zip archive.  ZIP /UNSFX is normally\nused to convert a self-extracting archive to a normal archive by\nremoving the UnZip SFX executable from the beginning of the SFX archive.\n\nNote that a self-extracting archive contains a normal Zip archive, and a\nnormal UnZip program can be used to expand it in the normal way.  You\nmay get a warning about extra bytes at the beginning of the archive (the\nUnZip SFX program), but UnZip should work properly after that.  This\nallows data in a self-extracting archive to be accessed on any system,\nnot just the target system where its embedded UnZip SFX program runs.\n<QUALIFIER>\n/UPDATE\n\n/UPDATE\n\nUpdate existing archive entries and add new files.  If the archive does\nnot exist, create it.  This is the default mode, so /UPDATE is optional.\n\nSee also /DELETE /DIFFERENCE, /GROW, /FRESHEN.\n<QUALIFIER>\n/VERBOSE\n\n/VERBOSE[=NORMAL|MORE|DEBUG] [, COMMAND]]\n\nVerbose mode or print diagnostic version info.\n\nNormally, when applied to real operations, this option enables the\ndisplay of a progress indicator during compression (see /DISPLAY=DOTS\nfor more on dots) and requests verbose diagnostic info about archive\nstructure oddities.\n\n/VERBOSE with no value is equivalent to /VERBOSE=NORMAL.  MORE adds more\nmessages, and DEBUG adds still more messages.\n\nWhen /VERBOSE is the only command line argument, a diagnostic report is\ndisplayed, showing:\n\n<LITERAL>\n|  o Copyright and other legal notices\n|  o Program name, version, and release date\n|  o Pointers to Info-ZIP FTP and Web sites\n|  o Program build information (compiler type and version, OS version,\n|    and the compilation date\n|  o Optional features enabled at compile-time\n|  o Environment variable definitions (ZIP_OPTS, ZIPOPT)\n<LARETIL>\n\nThis information should be included in bug reports.\n\n/VERBOSE=COMMAND causes Zip to display the UNIX-style command-line\nargument vector which is generated from the VMS-style CLI command line\nbefore executing the command.  This is of primary interest to program\ndevelopers debugging the CLI.\n<QUALIFIER>\n/VMS\n\n/VMS[=ALL]\n\nThe /VMS and /VMS=ALL options cause Zip to store VMS file atributes\n(such as file organization, record format, carriage control, and so on)\nin VMS-specific \"extra fields\" in an archive along with the usual data.\nThese extra fields are ignored on non-VMS systems, but on a VMS system,\nthey allow UnZip to restore the files with their VMS attributes intact.\n\nWith /VMS, Zip ignores any data in the file after the end-of-file (EOF)\npoint (defined by FAT$L_EFBLK and FAT$W_FFBYTE), which works well for\nwell-formed files (that is, those with no valid data beyond EOF).\nPortable-format files (Stream_LF, fixed-512) archived with /VMS should\nbe extracted properly on a non-VMS system.  Files with more complex\nstructures, such as indexed files and files with embedded byte counts or\nother such data may be of limited use on other systems.  (UnZip on\nnon-VMS systems may be able to extract various VMS-format text files,\nhowever.)\n\nWith /VMS=ALL, Zip processes all allocated blocks for the file\n(including those beyond EOF).  When extracted on a VMS system, the\noriginal file should be reproduced with as much fidelity as possible,\nbut on a non-VMS system, most files will be seen as corrupt because of\nthe data from beyond EOF.\n<QUALIFIER>\n/WILDCARD\n\n<LITERAL>\n/NOWILDCARD\n/WILDCARD=NOSPAN\n<LARETIL>\n\nControls wildcard processing.\n\n/NOWILDCARD  Wildcard processing is disabled.\n\n/WILDCARD=NOSPAN  Wildcards don't span directory boundaries in paths.\n<QUALIFIER>\n/ZIP64\n\n/ZIP64\n\nForces use of Zip64 archive format, even for small files.  This is\nmainly for testing and should never be used.  Zip will automatically\nuse Zip64 as needed without this option.\n<TOPIC>\nUNIX_Options\n\n\"zip -h\" provides a concise list of common command-line options.  \"zip\n-h2\" provides more details.  \"zip -so\" provides a list of all available\noptions.  \"zip -v\" shows the program version and available features.\n(The list below was derived from a \"zip -so\" listing.)\n\nShort-form options begin with a single hyphen (\"-\").  Long-form option\nbegin with a double hyphen (\"--\"), and may be abbreviated to any\nunambiguous shorter string.  For example:\n\n<LITERAL>\n|  -v\n|  --verbose\n|  --verb\n<LARETIL>\n\nTo avoid confusion, if a negatable option contains an embedded hyphen\n(\"-\"), then avoid abbreviating it at the hyphen if you plan to negate\nit.  For example, if an option like --some-option were abbreviated to\n--some-, the parser would consider that trailing hyphen to be part of\nthe option name, rather than as a negating trailing hyphen.  This\nbehavior may change in the future, to interpret the trailing hyphen in\n--some- to be negating.  (So don't do it.)\n\nSome options may be negated (or modified) by appending a \"-\":\n\n<LITERAL>\n|  -la-\n|  --show-files-\n<LARETIL>\n\nSome options take a value, which may immediately follow the option, or\nbe separated by a space or \"=\".  For example:\n<LITERAL>\n|  -ttmmddyyyy\n|  -tt mmddyyyy\n|  -tt=mmddyyyy\n<LARETIL>\n\n<LITERAL0>\n| Sh  Long                Description\n|----+-------------------+------------------------------------------------\n| 0   store               store (instead of compress)\n| 1   compress-1          compress faster (-2, -3, -4, ...)\n| 9   compress-9          compress better\n| ?                       show the Zip help screen\n| @   names-stdin         read input file patterns from SYS$INPUT (1/line)\n| A   adjust-sfx          adjust self-extracting executable\n| b   temp-path  path     use \"path\" directory for temporary files\n| C   preserve-case       preserve case of all file names added to archive\n| C-  preserve-case-      down-case all file names added to archive\n| C2  preserve-case-2     preserve case of ODS2 names added to archive\n| C2- preserve-case-2-    down-case ODS2 file added to archive (default)\n| C5  preserve-case-5     preserve case of ODS5 names added to arcv (dflt)\n| C5- preserve-case-5-    down-case ODS5 names added to archive\n| c   entry-comments      add a comment for each entry added to archive\n| D   no-dir-entries      do not add archive entries for directories\n| DF  difference-archive  difference archive: add only changed/new files\n| d   delete              delete entries in archive\n| db  display-bytes       display running byte counts\n| dc  display-counts      display running file counts\n| dd  display-dots        display progress dots for files (dflt sz = 10MB)\n| dg  display-globaldots  display progress dots for archive, not each file\n| ds  dot-size   size     set progress dot interval to \"size\" (MB)\n| du  display-usize       display original uncompressed size for entries\n| dv  display-volume      display volume (disk) number as in_disk>out_disk\n| e   encrypt             encrypt entries, ask for password\n| F   fix                 fix mostly intact archive (try F before FF)\n| FF  fixfix              salvage what can be salvaged (not as reliable)\n| FS  filesync            remove archive entries unmatched in file system\n| f   freshen             update existing entries (only changed files)\n| fd  force-descriptors   force data descriptors as if streaming\n| fz  force-zip64         force use of Zip64 format\n| g   grow                grow existing archive (unless update or delete)\n| H                       show the Zip help screen\n| h   help                show the Zip help screen\n| h2  more-help           show extended Zip help\n| i   include  pat1 [pat2 [...]]  include only names matching the patterns\n| J   junk-sfx            junk (remove) archive preamble (unzipsfx)\n| j   junk-paths          junk (don't store) dir names, only file names\n| k   DOS-names           simulate PKZIP-made archive (DOS 8.3 names)\n| L   license             show software license\n| l   to-crlf             translate end-of-lines (LF -> CRLF)\n| la  log-append          append to existing log file\n| lf  logfile-path  lfile  log to log file at lfile (default: new version)\n| li  log-info            include informational messages in log\n| ll  from-crlf           translate end-of-lines (CRLF -> LF)\n| MM  must-match          input file spec must exist (wildcrds must match)\n| m   move                delete files added to archive\n| n   suffixes  sfx1[:sfx2[...]]  don't compress files with these suffixes\n| nw  no-wild             no wildcards during add or update\n| O   output-file  ozf  use \"ozf\" as the output archive (dflt = inp archv)\n| o   latest-time         set archive date-time to match oldest entry\n| P   password  password  encrypt with supplied \"password\" string\n| q   quiet               quiet operation (no info messages)\n| R   recurse-patterns    recurse subdirs from cur dir, match names only\n| r   recurse-paths       recurse directories from specified path pats\n| s   split-size  size    split archive at \"size\" (K/MB)  (0: don't split)\n| sb  split-bell          ring termnl bell at pause for split medium chng\n| sc  show-command        show command line\n| sd  show-debug          show debug messages\n| sf  show-files          show files to process (only)\n| so  show-options        show list of all command-line options\n| sp  split-pause         pause to select split destination(s)\n| sv  split-verbose       be verbose about creating splits\n| T   test                test archive integrity (runs UnZip -T)\n| t   from-date  mmddyyyy  only do files since (at or after) \"mmddyyyy\"\n| tt  before-date  mmddyyyy  only do files before \"mmddyyyy\"\n| u   update              update changed files, add new files (default)\n| V   VMS-portable        save VMS file attributes\n| VV  VMS-specific        save VMS file attributes and all allocated blks\n| v   verbose             verbose messages (version info if only arg)\n| w   VMS-versions        save VMS version numbers in archive\n| ww  VMS-dot-versions    save VMS version numbers as \".nnn\", not \";nnn\"\n| X   strip-extra         strip all but critical extra fields\n| X-  strip-extra-        keep all extra fields\n| x   exclude  pat1 [pat2 [...]]  exclude all names matching the patterns\n| Z   compression-method mthd  use cmprs method \"mthd\" (bzip2 or deflate)\n| z   archive-comment     ask for archive comment\n<0LARETIL>\n\nWith SET PROCESS /PARSE_STYLE = EXTENDED (available on recent non-VAX\nsystems), Zip preserves the case of the command line.  Otherwise, mixed-\nor upper-case options and arguments must be quoted.  For example,\n\"-V\".  Examples in this document generally do not show this quotation.\n<TOPIC>\nCopyright_and_License\n\nZip has an option to display its copyright and license.\n\n<LITERAL>\n|  /LICENSE\n<LARETIL>\n\nThe license is reproduced below.\n\nThis is version 2007-Mar-4 of the Info-ZIP license. The definitive\nversion of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and a copy\nat http://www.info-zip.org/pub/infozip/license.html.\n\n--------------------------------------------------------\n<LITERAL0>\n|Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n|\n|For the purposes of this copyright and license, \"Info-ZIP\" is defined as\n|the following set of individuals:\n|\n|Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n|Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n|Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n|David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n|Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n|Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, \n|Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n|Rich Wales, Mike White.\n| \n|This software is provided \"as is,\" without warranty of any kind, express\n|or implied.  In no event shall Info-ZIP or its contributors be held\n|liable for any direct, indirect, incidental, special or consequential\n|damages arising out of the use of or inability to use this software.\n| \n|Permission is granted to anyone to use this software for any purpose,\n|including commercial applications, and to alter it and redistribute it\n|freely, subject to the above disclaimer and the following restrictions:\n| \n|1. Redistributions of source code (in whole or in part) must retain\n|   the above copyright notice, definition, disclaimer, and this list\n|   of conditions.\n| \n|2. Redistributions in binary form (compiled executables and libraries)\n|   must reproduce the above copyright notice, definition, disclaimer,\n|   and this list of conditions in documentation and/or other materials\n|   provided with the distribution.  The sole exception to this condition\n|   is redistribution of a standard UnZipSFX binary (including SFXWiz) as\n|   part of a self-extracting archive; that is permitted without inclusion\n|   of this license, as long as the normal SFX banner has not been removed\n|   from the binary or disabled.\n| \n|3. Altered versions -- including, but not limited to, ports to new\n|   operating systems, existing ports with new graphical interfaces,\n|   versions with modified or added functionality, and dynamic, shared,\n|   or static library versions not from Info-ZIP -- must be plainly marked\n|   as such and must not be misrepresented as being the original source\n|   or, if binaries, compiled from the original source.  Such altered\n|   versions also must not be misrepresented as being Info-ZIP releases --\n|   including, but not limited to, labeling of the altered versions with\n|   the names \"Info-ZIP\" (or any variation thereof, including, but not\n|   limited to, different capitalizations), \"Pocket UnZip,\" \"WiZ\" or\n|   \"MacZip\" without the explicit permission of Info-ZIP.  Such altered\n|   versions are further prohibited from misrepresentative use of the\n|   Zip-Bugs or Info-ZIP e-mail addresses or the Info-ZIP URL(s), such as\n|   to imply Info-ZIP will provide support for the altered versions.\n| \n|4. Info-ZIP retains the right to use the names \"Info-ZIP\", \"Zip\",\n|   \"UnZip\", \"UnZipSFX\", \"WiZ\", \"Pocket UnZip\", \"Pocket Zip\", and\n|   \"MacZip\" for its own source and binary releases.\n<0LARETIL>\n\n===\n"
  },
  {
    "path": "deps/infozip/zip30/vms/zip_msg.msg",
    "content": "!    VMS Error Message Source File for Zip\n!\n! Because the facility code was formally assigned by HP, the .FACILITY\n! directive below specifies /SYSTEM.  Because the messages are, in\n! general, specific to Zip, this file is not compiled with /SHARED.\n! For example:\n!\n!    MESSAGE /OBJECT = [.dest]ZIP_MSG.OBJ /NOSYMBOLS [.VMS]ZIP_MSG.MSG\n!\n!    LINK /SHAREABLE = [.dest]ZIP_MSG.EXE [.dest]ZIP_MSG.OBJ\n!\n!-----------------------------------------------------------------------\n\n.TITLE  Info-ZIP Zip Error Messages\n.FACILITY IZ_ZIP, 1955 /SYSTEM\n.IDENT 'V3.0-000'\n\n.BASE 0\nOK      /SUCCESS      <Normal successful completion>\n.BASE 4\nEOF     /FATAL        <Unexpected end of zip file>\n.BASE 6\nFORM    /ERROR        <Zip file structure invalid>\n.BASE 8\nMEM     /FATAL        <Out of memory>\n.BASE 10\nLOGIC   /FATAL        <Internal logic error>\n.BASE 12\nBIG     /ERROR        <Entry too big to split, read, or write>\n.BASE 14\nNOTE    /ERROR        <Invalid comment format>\n.BASE 16\nTEST    /FATAL        <Zip file invalid, could not spawn unzip, or wrong unzip>\n.BASE 18\nABORT   /ERROR        <Interrupted>\n.BASE 20\nTEMP    /FATAL        <Temporary file failure>\n.BASE 22\nREAD    /FATAL        <Input file read failure>\n.BASE 24\nNONE    /WARNING      <Nothing to do!>\n.BASE 26\nNAME    /ERROR        <Missing or empty zip file>\n.BASE 28\nWRITE   /FATAL        <Output file write failure>\n.BASE 30\nCREAT   /FATAL        <Could not create output file>\n.BASE 32\nPARMS   /ERROR        <Invalid command arguments>\n.BASE 36\nOPEN    /ERROR        <File not found or no read permission>\n.BASE 38\nCOMPERR /FATAL        <Not supported>\n.BASE 40\nZIP64   /FATAL        <Attempt to read unsupported Zip64 archive>\n\n.END\n"
  },
  {
    "path": "deps/infozip/zip30/vms/zipup.h",
    "content": "/*\n  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#ifndef __zipup_h\n#define __zipup_h 1\n\n#ifndef NO_ZIPUP_H\n\n#define fbad NULL\ntypedef void *ftype;\n#define zopen(n,p)   (vms_native?vms_open(n)    :(ftype)fopen((n), p))\n#define zread(f,b,n) (vms_native?vms_read(f,b,n):fread((b),1,(n),(FILE*)(f)))\n#define zclose(f)    (vms_native?vms_close(f)   :fclose((FILE*)(f)))\n#define zerr(f)      (vms_native?vms_error(f)   :ferror((FILE*)(f)))\n#define zstdin stdin\n\nftype vms_open OF((char *));\nunsigned int vms_read OF((ftype, char *, unsigned int));\nint vms_close OF((ftype));\nint vms_error OF((ftype));\n#ifdef VMS_PK_EXTRA\nint vms_get_attributes OF((ftype, struct zlist far *, iztimes *));\n#endif\n\n#endif /* !NO_ZIPUP_H */\n#endif /* !__zipup_h */\n\n\n#ifndef __zipup_cb_h\n#define __zipup_cb_h 1\n\n#ifdef __DECC\n\n/* File open callback ID values.  (See also OSDEP.H.) */\n\n#  define FHOW_ID 4\n\n/* File open callback ID storage. */\n\nextern int fhow_id;\n\n#define fhow \"r\", \"acc\", acc_cb, &fhow_id\n\n#else /* def __DECC */ /* (So, GNU C, VAX C, ...)*/\n\n#define fhow \"r\", \"mbc=60\"\n\n#endif /* def __DECC */\n\n#endif /* ndef __zipup_cb_h */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/README.NT",
    "content": "From: Michael Tibbott <tibbott@classifieds2000.com>\nSubject: Zip on Windows NT problem - here's the answer\nDate: Wed, 10 Dec 1997 15:24:29 -0800\n\nIf you're running NT Server (I am not sure about NT Workstation) then you\nshould do the following to prevent zip/unzip from page swapping itself to\ndeath. And as an added bonus, the zip was about 6% faster.\n\n- open the network control panel\n\n- Click on the services tab\n\n- double-click on the server item to open its properties\n\n- Click the \"maximize throughput for network applications\" radio button\n\n- save and reboot\n"
  },
  {
    "path": "deps/infozip/zip30/win32/README.TZ",
    "content": "From: paul.kienitz@shelter.sf.ca.us (Paul Kienitz)\n> It looks like I don't have to create a tzset() kluge for Watcom to check\n> the win32 API timezone information after all -- their new 10.6 release has\n> corrected this oversight.  The TZ variable overrides the API.  So the only\n> win32-related patch I want to make for Zip is just to use USE_EF_UT_TIME\n> unconditionally.  With this in place, timezone stuff is working flawlessly\n> with or without TZ being set.\n"
  },
  {
    "path": "deps/infozip/zip30/win32/README.txt",
    "content": "Win32/README.txt\n27 June 2008\n\nThe resource files zip.rc and windll.rc must not get edited and saved from\nMS Visual Studio.  MS VS automatically re-adds its specific MFC-related resource\ninfrastructure to the \"xx.rc\" files when saved after any modification.  The\ndependancies on MFC related headers break the compilation process, when you\ntry to use the freely available MS Visual Studio Express Editions (2005 or 2008)\nfor building Zip.  And, most third-party compilers also lack support for the\npropietary MFC environment.\n"
  },
  {
    "path": "deps/infozip/zip30/win32/crc_i386.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_i386.asm, optimized CRC calculation function for Zip and UnZip,\n; created by Paul Kienitz and Christian Spieler.  Last revised 07 Jan 2007.\n;\n; Revised 06-Oct-96, Scott Field (sfield@microsoft.com)\n;   fixed to assemble with masm by not using .model directive which makes\n;   assumptions about segment alignment.  Also,\n;   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather\n;   than lodsb, and other misc. changes resulting in the following performance\n;   increases:\n;\n;      unrolled loops                NO_UNROLLED_LOOPS\n;      *8    >8      <8              *8      >8      <8\n;\n;      +54%  +42%    +35%            +82%    +52%    +25%\n;\n;   first item in each table is input buffer length, even multiple of 8\n;   second item in each table is input buffer length, > 8\n;   third item in each table is input buffer length, < 8\n;\n; Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n;   Incorporated Rodney Brown's 32-bit-reads optimization as found in the\n;   UNIX AS source crc_i386.S. This new code can be disabled by defining\n;   the macro symbol NO_32_BIT_LOADS.\n;\n; Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n;   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs\n;   (like the Pentium Pro, Pentium II, and probably some Pentium clones).\n;   This optimization is controlled by the macro symbol __686 and is disabled\n;   by default. (This default is based on the assumption that most users\n;   do not yet work on a Pentium Pro or Pentium II machine ...)\n;\n; Revised 25-Mar-98, Cosmin Truta (cosmint@cs.ubbcluj.ro)\n;   Working without .model directive caused tasm32 version 5.0 to produce\n;   bad object code. The optimized alignments can be optionally disabled\n;   by defining NO_ALIGN, thus allowing to use .model flat. There is no need\n;   to define this macro if using other versions of tasm.\n;\n; Revised 16-Jan-2005, Cosmin Truta (cosmint@cs.ubbcluj.ro)\n;   Enabled the 686 build by default, because there are hardly any pre-686 CPUs\n;   in serious use nowadays. (See the 12-Oct-97 note above.)\n;\n; Revised 03-Jan-2006, Chr. Spieler\n;   Enlarged unrolling loops to \"do 16 bytes per turn\"; optimized access to\n;   data buffer in loop body (adjust pointer only once in loop body and use\n;   offsets to access each item); added additional support for the \"unfolded\n;   tables\" optimization variant (enabled by IZ_CRCOPTIM_UNFOLDTBL).\n;\n; Revised 07-Jan-2007, Chr. Spieler\n;   Recognize additional conditional flag CRC_TABLE_ONLY that prevents\n;   compilation of the crc32() function.\n;\n; FLAT memory model assumed.\n;\n; Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n; This results in shorter code at the expense of reduced performance.\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used,\n; or only the precomputed CRC_32_Table is needed.\n;\n    IFNDEF USE_ZLIB\n    IFNDEF CRC_TABLE_ONLY\n;\n        .386p\n        name    crc_i386\n\n    IFDEF NO_ALIGN\n        .model flat\n    ENDIF\n\n    IFNDEF PRE_686\n    IFNDEF __686\n__686   EQU     1 ; optimize for Pentium Pro, Pentium II and compatible CPUs\n    ENDIF\n    ENDIF\n\nextrn   _get_crc_table:near    ; ZCONST ulg near *get_crc_table(void);\n\n;\n    IFNDEF NO_STD_STACKFRAME\n        ; Use a `standard' stack frame setup on routine entry and exit.\n        ; Actually, this option is set as default, because it results\n        ; in smaller code !!\nSTD_ENTRY       MACRO\n                push    ebp\n                mov     ebp,esp\n        ENDM\n\n        Arg1    EQU     08H[ebp]\n        Arg2    EQU     0CH[ebp]\n        Arg3    EQU     10H[ebp]\n\nSTD_LEAVE       MACRO\n                pop     ebp\n        ENDM\n\n    ELSE  ; NO_STD_STACKFRAME\n\nSTD_ENTRY       MACRO\n        ENDM\n\n        Arg1    EQU     18H[esp]\n        Arg2    EQU     1CH[esp]\n        Arg3    EQU     20H[esp]\n\nSTD_LEAVE       MACRO\n        ENDM\n\n    ENDIF ; ?NO_STD_STACKFRAME\n\n; These two (three) macros make up the loop body of the CRC32 cruncher.\n; registers modified:\n;   eax  : crc value \"c\"\n;   esi  : pointer to next data byte (or dword) \"buf++\"\n; registers read:\n;   edi  : pointer to base of crc_table array\n; scratch registers:\n;   ebx  : index into crc_table array\n;          (requires upper three bytes = 0 when __686 is undefined)\n    IFNDEF  __686 ; optimize for 386, 486, Pentium\nDo_CRC  MACRO\n                mov     bl,al                ; tmp = c & 0xFF\n                shr     eax,8                ; c = (c >> 8)\n                xor     eax,[edi+ebx*4]      ;  ^ table[tmp]\n        ENDM\n    ELSE ; __686 : optimize for Pentium Pro, Pentium II and compatible CPUs\nDo_CRC  MACRO\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                shr     eax,8                  ; c = (c >> 8)\n                xor     eax,[edi+ebx*4]        ;  ^ table[tmp]\n        ENDM\n    ENDIF ; ?__686\nDo_CRC_byte     MACRO\n                xor     al, byte ptr [esi]     ; c ^= *buf\n                inc     esi                    ; buf++\n                Do_CRC                         ; c = (c >> 8) ^ table[c & 0xFF]\n        ENDM\nDo_CRC_byteof   MACRO   ofs\n                xor     al, byte ptr [esi+ofs] ; c ^= *(buf+ofs)\n                Do_CRC                         ; c = (c >> 8) ^ table[c & 0xFF]\n        ENDM\n    IFNDEF  NO_32_BIT_LOADS\n      IFDEF IZ_CRCOPTIM_UNFOLDTBL\n        ; the edx register is needed in crc calculation\n        SavLen  EQU     Arg3\n\nUpdCRC_dword    MACRO\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                mov     edx,[edi+ebx*4+3072]   ;  table[256*3+tmp]\n                movzx   ebx,ah                 ; tmp = (c>>8) & 0xFF\n                shr     eax,16                 ;\n                xor     edx,[edi+ebx*4+2048]   ;  ^ table[256*2+tmp]\n                movzx   ebx,al                 ; tmp = (c>>16) & 0xFF\n                shr     eax,8                  ; tmp = (c>>24)\n                xor     edx,[edi+ebx*4+1024]   ;  ^ table[256*1+tmp]\n                mov     eax,[edi+eax*4]        ;  ^ table[256*0+tmp]\n                xor     eax,edx                ; ..\n        ENDM\nUpdCRC_dword_sh MACRO   dwPtrIncr\n                movzx   ebx,al                 ; tmp = c & 0xFF\n                mov     edx,[edi+ebx*4+3072]   ;  table[256*3+tmp]\n                movzx   ebx,ah                 ; tmp = (c>>8) & 0xFF\n                xor     edx,[edi+ebx*4+2048]   ;  ^ table[256*2+tmp]\n                shr     eax,16                 ;\n                movzx   ebx,al                 ; tmp = (c>>16) & 0xFF\n                add     esi, 4*dwPtrIncr       ; ((ulg *)buf) += dwPtrIncr\n                shr     eax,8                  ; tmp = (c>>24)\n                xor     edx,[edi+ebx*4+1024]   ;  ^ table[256*1+tmp]\n                mov     eax,[edi+eax*4]        ;  ^ table[256*0+tmp]\n                xor     eax,edx                ; ..\n        ENDM\n      ELSE ; IZ_CRCOPTIM_UNFOLDTBL\n        ; the edx register is not needed anywhere else\n        SavLen  EQU     edx\n\nUpdCRC_dword    MACRO\n                Do_CRC\n                Do_CRC\n                Do_CRC\n                Do_CRC\n        ENDM\nUpdCRC_dword_sh MACRO   dwPtrIncr\n                Do_CRC\n                Do_CRC\n                add     esi, 4*dwPtrIncr       ; ((ulg *)buf) += dwPtrIncr\n                Do_CRC\n                Do_CRC\n        ENDM\n      ENDIF ; ?IZ_CRCOPTIM_UNFOLDTBL\nDo_CRC_dword    MACRO\n                xor     eax, dword ptr [esi]   ; c ^= *(ulg *)buf\n                UpdCRC_dword_sh 1              ; ... ((ulg *)buf)++\n        ENDM\nDo_CRC_4dword   MACRO\n                xor     eax, dword ptr [esi]    ; c ^= *(ulg *)buf\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+4]  ; c ^= *((ulg *)buf+1)\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+8]  ; c ^= *((ulg *)buf+2)\n                UpdCRC_dword\n                xor     eax, dword ptr [esi+12] ; c ^= *((ulg *)buf]+3\n                UpdCRC_dword_sh\t4               ; ... ((ulg *)buf)+=4\n        ENDM\n    ENDIF ; !NO_32_BIT_LOADS\n\n    IFNDEF NO_ALIGN\n_TEXT   segment use32 para public 'CODE'\n    ELSE\n_TEXT   segment use32\n    ENDIF\n        assume  CS: _TEXT\n\n        public  _crc32\n_crc32          proc    near  ; ulg crc32(ulg crc, ZCONST uch *buf, extent len)\n                STD_ENTRY\n                push    edi\n                push    esi\n                push    ebx\n                push    edx\n                push    ecx\n\n                mov     esi,Arg2            ; 2nd arg: uch *buf\n                sub     eax,eax             ;> if (!buf)\n                test    esi,esi             ;>   return 0;\n                jz      fine                ;> else {\n\n                call    _get_crc_table\n                mov     edi,eax\n                mov     eax,Arg1            ; 1st arg: ulg crc\n    IFNDEF __686\n                sub     ebx,ebx             ; ebx=0; make bl usable as a dword\n    ENDIF\n                mov     ecx,Arg3            ; 3rd arg: extent len\n                not     eax                 ;>   c = ~crc;\n\n                test    ecx,ecx\n    IFNDEF  NO_UNROLLED_LOOPS\n                jz      bail\n    IFNDEF  NO_32_BIT_LOADS\nalign_loop:\n                test    esi,3               ; align buf pointer on next\n                jz      SHORT aligned_now   ;  dword boundary\n                Do_CRC_byte\n                dec     ecx\n                jnz     align_loop\naligned_now:\n    ENDIF ; !NO_32_BIT_LOADS\n                mov     SavLen,ecx          ; save current len for later\n                shr     ecx,4               ; ecx = len / 16\n                jz      No_Sixteens\n    IFNDEF NO_ALIGN\n; align loop head at start of 486 internal cache line !!\n                align   16\n    ENDIF\nNext_Sixteen:\n    IFNDEF  NO_32_BIT_LOADS\n                Do_CRC_4dword\n    ELSE ; NO_32_BIT_LOADS\n                Do_CRC_byteof   0\n                Do_CRC_byteof   1\n                Do_CRC_byteof   2\n                Do_CRC_byteof   3\n                Do_CRC_byteof   4\n                Do_CRC_byteof   5\n                Do_CRC_byteof   6\n                Do_CRC_byteof   7\n                Do_CRC_byteof   8\n                Do_CRC_byteof   9\n                Do_CRC_byteof   10\n                Do_CRC_byteof   11\n                Do_CRC_byteof   12\n                Do_CRC_byteof   13\n                Do_CRC_byteof   14\n                Do_CRC_byteof   15\n                add     esi, 16                 ; buf += 16\n    ENDIF ; ?NO_32_BIT_LOADS\n                dec     ecx\n                jnz     Next_Sixteen\nNo_Sixteens:\n                mov     ecx,SavLen\n                and     ecx,00000000FH      ; ecx = len % 16\n    IFNDEF  NO_32_BIT_LOADS\n                shr     ecx,2               ; ecx = len / 4\n                jz      SHORT No_Fours\nNext_Four:\n                Do_CRC_dword\n                dec     ecx\n                jnz     Next_Four\nNo_Fours:\n                mov     ecx,SavLen\n                and     ecx,000000003H      ; ecx = len % 4\n    ENDIF ; !NO_32_BIT_LOADS\n    ENDIF ; !NO_UNROLLED_LOOPS\n                jz      SHORT bail          ;>   if (len)\n    IFNDEF NO_ALIGN\n; align loop head at start of 486 internal cache line !!\n                align   16\n    ENDIF\nloupe:                                      ;>     do {\n                Do_CRC_byte                 ;        c = CRC32(c,*buf++,crctab);\n                dec     ecx                 ;>     } while (--len);\n                jnz     loupe\n\nbail:                                       ;> }\n                not     eax                 ;> return ~c;\nfine:\n                pop     ecx\n                pop     edx\n                pop     ebx\n                pop     esi\n                pop     edi\n                STD_LEAVE\n                ret\n_crc32          endp\n\n_TEXT   ends\n;\n    ENDIF ; !CRC_TABLE_ONLY\n    ENDIF ; !USE_ZLIB\n;\nend\n"
  },
  {
    "path": "deps/infozip/zip30/win32/crc_i386.c",
    "content": "/*\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* crc_i386.c -- Microsoft 32-bit C/C++ adaptation of crc_i386.asm\n * Created by Rodney Brown from crc_i386.asm, modified by Chr. Spieler.\n * Last revised: 07-Jan-2007\n *\n * Original coded (in crc_i386.asm) and put into the public domain\n * by Paul Kienitz and Christian Spieler.\n *\n * Revised 06-Oct-96, Scott Field (sfield@microsoft.com)\n *   fixed to assemble with masm by not using .model directive which makes\n *   assumptions about segment alignment.  Also,\n *   avoid using loop, and j[e]cxz where possible.  Use mov + inc, rather\n *   than lodsb, and other misc. changes resulting in the following performance\n *   increases:\n *\n *      unrolled loops                NO_UNROLLED_LOOPS\n *      *8    >8      <8              *8      >8      <8\n *\n *      +54%  +42%    +35%            +82%    +52%    +25%\n *\n *   first item in each table is input buffer length, even multiple of 8\n *   second item in each table is input buffer length, > 8\n *   third item in each table is input buffer length, < 8\n *\n * Revised 02-Apr-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n *   Incorporated Rodney Brown's 32-bit-reads optimization as found in the\n *   UNIX AS source crc_i386.S. This new code can be disabled by defining\n *   the macro symbol NO_32_BIT_LOADS.\n *\n * Revised 12-Oct-97, Chr. Spieler, based on Rodney Brown (rdb@cmutual.com.au)\n *   Incorporated Rodney Brown's additional tweaks for 32-bit-optimized CPUs\n *   (like the Pentium Pro, Pentium II, and probably some Pentium clones).\n *   This optimization is controlled by the macro symbol __686 and is disabled\n *   by default. (This default is based on the assumption that most users\n *   do not yet work on a Pentium Pro or Pentium II machine ...)\n *\n * Revised 16-Nov-97, Chr. Spieler: Made code compatible with Borland C++\n *   32-bit, removed unneeded kludge for potentially unknown movzx mnemonic,\n *   confirmed correct working with MS VC++ (32-bit).\n *\n * Revised 22-May-98, Peter Kunath, Chr. Spieler: The 16-Nov-97 revision broke\n *   MSVC 5.0. Inside preprocessor macros, each instruction is enclosed in its\n *   own __asm {...} construct.  For MSVC, a \"#pragma warning\" was added to\n *   shut up the \"no return value\" warning message.\n *\n * Revised 13-Dec-98, Chr. Spieler: Modified path to \"zip.h\" header file.\n *\n * Revised 16-Jan-2005, Cosmin Truta: Added the ASM_CRC guard, for easier\n *   switching between ASM vs. non-ASM builds, when handling makefiles.\n *   Also enabled the 686 build by default, because there are hardly any\n *   pre-686 CPUs in serious use nowadays. (See the 12-Oct-97 note above.)\n *\n * Revised 03-Jan-2006, Chr. Spieler\n *   Enlarged unrolling loops to \"do 16 bytes per turn\"; optimized access to\n *   data buffer in loop body (adjust pointer only once in loop body and use\n *   offsets to access each item); added additional support for the \"unfolded\n *   tables\" optimization variant (enabled by IZ_CRCOPTIM_UNFOLDTBL).\n *\n * Revised 07-Jan-2007, Chr. Spieler\n *   Recognize additional conditional flag CRC_TABLE_ONLY that prevents\n *   compilation of the crc32() function.\n *\n * FLAT memory model assumed.\n *\n * Loop unrolling can be disabled by defining the macro NO_UNROLLED_LOOPS.\n * This results in shorter code at the expense of reduced performance.\n *\n */\n\n#include \"../zip.h\"\n#include \"../crc32.h\"\n\n#if defined(ASM_CRC) && !defined(USE_ZLIB) && !defined(CRC_TABLE_ONLY)\n\n#if !defined(PRE_686) && !defined(__686)\n#  define __686\n#endif\n\n#ifndef ZCONST\n#  define ZCONST const\n#endif\n\n/* Select wether the following inline-assember code is supported. */\n#if (defined(_MSC_VER) && _MSC_VER >= 700)\n#if (defined(_M_IX86) && _M_IX86 >= 300)\n#  define MSC_INLINE_ASM_32BIT_SUPPORT\n   /* Disable warning for no return value, typical of asm functions */\n#  pragma warning( disable : 4035 )\n#endif\n#endif\n\n#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)\n#  define MSC_INLINE_ASM_32BIT_SUPPORT\n#endif\n\n#ifdef MSC_INLINE_ASM_32BIT_SUPPORT\n/* This code is intended for Microsoft C/C++ (32-bit) compatible compilers. */\n\n/*\n * These two (three) macros make up the loop body of the CRC32 cruncher.\n * registers modified:\n *   eax  : crc value \"c\"\n *   esi  : pointer to next data byte (or dword) \"buf++\"\n * registers read:\n *   edi  : pointer to base of crc_table array\n * scratch registers:\n *   ebx  : index into crc_table array\n *          (requires upper three bytes = 0 when __686 is undefined)\n */\n#ifndef __686\n#define Do_CRC { \\\n  __asm { mov   bl, al }; \\\n  __asm { shr   eax, 8 }; \\\n  __asm { xor   eax, [edi+ebx*4] }; }\n#else /* __686 */\n#define Do_CRC { \\\n  __asm { movzx ebx, al }; \\\n  __asm { shr   eax, 8  }; \\\n  __asm { xor   eax, [edi+ebx*4] }; }\n#endif /* ?__686 */\n\n#define Do_CRC_byte { \\\n  __asm { xor   al, byte ptr [esi] }; \\\n  __asm { inc   esi }; \\\n  Do_CRC; }\n\n#define Do_CRC_byteof(ofs) { \\\n  __asm { xor   al, byte ptr [esi+(ofs)] }; \\\n  Do_CRC; }\n\n#ifndef NO_32_BIT_LOADS\n#ifdef IZ_CRCOPTIM_UNFOLDTBL\n# define SavLen  len            /* the edx register is needed elsewhere */\n# define UpdCRC_dword { \\\n   __asm { movzx   ebx,al }; \\\n   __asm { mov     edx,[edi+ebx*4+3072] }; \\\n   __asm { movzx   ebx,ah }; \\\n   __asm { shr     eax,16 }; \\\n   __asm { xor     edx,[edi+ebx*4+2048] }; \\\n   __asm { movzx   ebx,al }; \\\n   __asm { shr     eax,8 }; \\\n   __asm { xor     edx,[edi+ebx*4+1024] }; \\\n   __asm { mov     eax,[edi+eax*4] }; \\\n   __asm { xor     eax,edx }; }\n# define UpdCRC_dword_sh(dwPtrIncr) { \\\n   __asm { movzx   ebx,al }; \\\n   __asm { mov     edx,[edi+ebx*4+3072] }; \\\n   __asm { movzx   ebx,ah }; \\\n   __asm { xor     edx,[edi+ebx*4+2048] }; \\\n   __asm { shr     eax,16 }; \\\n   __asm { movzx   ebx,al }; \\\n   __asm { add     esi, 4*dwPtrIncr }; \\\n   __asm { shr     eax,8 }; \\\n   __asm { xor     edx,[edi+ebx*4+1024] }; \\\n   __asm { mov     eax,[edi+eax*4] }; \\\n   __asm { xor     eax,edx }; }\n#else /* !IZ_CRCOPTIM_UNFOLDTBL */\n# define SavLen  edx            /* the edx register is free for use here */\n# define UpdCRC_dword { \\\n    Do_CRC; \\\n    Do_CRC; \\\n    Do_CRC; \\\n    Do_CRC; }\n# define UpdCRC_dword_sh(dwPtrIncr) { \\\n    Do_CRC; \\\n    Do_CRC; \\\n    __asm { add   esi, 4*(dwPtrIncr) }; \\\n    Do_CRC; \\\n    Do_CRC; }\n#endif /* ?IZ_CRCOPTIM_UNFOLDTBL */\n\n#define Do_CRC_dword { \\\n  __asm { xor   eax, dword ptr [esi] }; \\\n  UpdCRC_dword_sh(1); }\n\n#define Do_CRC_4dword { \\\n  __asm { xor   eax, dword ptr [esi] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+4] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+8] }; \\\n  UpdCRC_dword; \\\n  __asm { xor   eax, dword ptr [esi+12] }; \\\n  UpdCRC_dword_sh(4); }\n#endif /* !NO_32_BIT_LOADS */\n\n/* ========================================================================= */\nulg crc32(crc, buf, len)\n    ulg crc;                    /* crc shift register */\n    ZCONST uch *buf;            /* pointer to bytes to pump through */\n    extent len;                 /* number of bytes in buf[] */\n/* Run a set of bytes through the crc shift register.  If buf is a NULL\n   pointer, then initialize the crc shift register contents instead.\n   Return the current crc in either case. */\n{\n    __asm {\n                push    edx\n                push    ecx\n\n                mov     esi,buf         ;/* 2nd arg: uch *buf              */\n                sub     eax,eax         ;/*> if (!buf)                     */\n                test    esi,esi         ;/*>   return 0;                   */\n                jz      fine            ;/*> else {                        */\n\n                call    get_crc_table\n                mov     edi,eax\n                mov     eax,crc         ;/* 1st arg: ulg crc               */\n#ifndef __686\n                sub     ebx,ebx         ;/* ebx=0; => bl usable as a dword */\n#endif\n                mov     ecx,len         ;/* 3rd arg: extent len            */\n                not     eax             ;/*>   c = ~crc;                   */\n\n                test    ecx,ecx\n#ifndef NO_UNROLLED_LOOPS\n                jz      bail\n#  ifndef NO_32_BIT_LOADS\nalign_loop:\n                test    esi,3           ;/* align buf pointer on next      */\n                jz      aligned_now     ;/*  dword boundary                */\n    }\n                Do_CRC_byte             ;\n    __asm {\n                dec     ecx\n                jnz     align_loop\naligned_now:\n#  endif /* !NO_32_BIT_LOADS */\n                mov     SavLen,ecx      ;/* save current len for later  */\n                shr     ecx,4           ;/* ecx = len / 16    */\n                jz      No_Sixteens\n; align loop head at start of 486 internal cache line !!\n                align   16\nNext_Sixteen:\n    }\n#  ifndef NO_32_BIT_LOADS\n                Do_CRC_4dword ;\n#  else /* NO_32_BIT_LOADS */\n                Do_CRC_byteof(0) ;\n                Do_CRC_byteof(1) ;\n                Do_CRC_byteof(2) ;\n                Do_CRC_byteof(3) ;\n                Do_CRC_byteof(4) ;\n                Do_CRC_byteof(5) ;\n                Do_CRC_byteof(6) ;\n                Do_CRC_byteof(7) ;\n                Do_CRC_byteof(8) ;\n                Do_CRC_byteof(9) ;\n                Do_CRC_byteof(10) ;\n                Do_CRC_byteof(11) ;\n                Do_CRC_byteof(12) ;\n                Do_CRC_byteof(13) ;\n                Do_CRC_byteof(14) ;\n                Do_CRC_byteof(15) ;\n    __asm {     add     esi,16 };\n#  endif /* ?NO_32_BIT_LOADS */\n    __asm {\n                dec     ecx\n                jnz     Next_Sixteen\nNo_Sixteens:\n                mov     ecx,SavLen\n                and     ecx,00000000FH  ;/* ecx = len % 16    */\n#  ifndef NO_32_BIT_LOADS\n                shr     ecx,2\n                jz      No_Fours\nNext_Four:\n    }\n                Do_CRC_dword ;\n    __asm {\n                dec     ecx\n                jnz     Next_Four\nNo_Fours:\n                mov     ecx,SavLen\n                and     ecx,000000003H  ;/* ecx = len % 4    */\n#  endif /* !NO_32_BIT_LOADS */\n#endif /* !NO_UNROLLED_LOOPS */\n                jz      bail            ;/*>  if (len)                       */\n; align loop head at start of 486 internal cache line !!\n                align   16\nloupe:                                  ;/*>    do {                         */\n    }\n                Do_CRC_byte             ;/*       c = CRC32(c,*buf++,crctab);*/\n    __asm {\n                dec     ecx             ;/*>    } while (--len);             */\n                jnz     loupe\n\nbail:                                   ;/*> }                               */\n                not     eax             ;/*> return ~c;                      */\nfine:\n                pop     ecx\n                pop     edx\n    }\n#ifdef NEED_RETURN\n    return _EAX;\n#endif\n}\n#endif /* MSC_INLINE_ASM_32BIT_SUPPORT */\n#if (defined(_MSC_VER) && _MSC_VER >= 700)\n#if (defined(_M_IX86) && _M_IX86 >= 300)\n   /* Reenable missing return value warning */\n#  pragma warning( default : 4035 )\n#endif\n#endif\n#endif /* ASM_CRC && !USE_ZLIB && !CRC_TABLE_ONLY */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/crc_lcc.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2006 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2000-Apr-09 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n; crc_lcc.asm, optimized CRC calculation function for Zip and UnZip,\n; created by Paul Kienitz and Christian Spieler.  Last revised 02 Jan 2006.\n;\n; The code in this file has been copied verbatim from crc_i386.{asm|S};\n; only the assembler syntax and metacommands have been adapted to\n; the habits of the free LCC-Win32 C compiler package.\n; This version of the code uses the \"optimized for i686\" variant of\n; crc_i386.{asm|S}.\n; IMPORTANT NOTE to the Info-ZIP editors:\n; The TAB characters in this source file are required by the parser of\n; the LCC-Win32 assembler program and MUST NOT be removed!!\n;\n; For more information (and a revision log), look into the original\n; source files.\n;\n\t.text\n\t.file \"crc32.c\"\n\t.text\n\t.type\t_crc32,function\n_crc32:\n\tpushl\t%ebp\n\tmovl\t%esp,%ebp\n\tpushl\t%ecx\n\tpushl\t%ebx\n\tpushl\t%esi\n\tpushl\t%edi\n\t.line\t34\n\t.line\t37\n\tmovl\t12(%ebp),%esi\n\tsubl\t%eax,%eax\n\ttestl\t%esi,%esi\n\tjz\t_$3\n\t.line\t39\n\tcall\t_get_crc_table\n\tmovl\t%eax,%edi\n\t.line\t41\n\tmovl\t8(%ebp),%eax\n\tmovl\t16(%ebp),%ecx\n\tnotl\t%eax\n\ttestl\t%ecx,%ecx\n\tjz\t_$4\n_$5:\n\ttestl\t$3,%esi\n\tjz\t_$6\n\txorb    (%esi),%al\n\tincl\t%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$5\n_$6:\n\tmovl\t%ecx,%edx\n\tshrl\t$4,%ecx\n\tjz\t_$8\n_$7:\n\txorl\t(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t4(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t8(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\txorl\t12(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\taddl\t$16,%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$7\n_$8:\n\tmovl\t%edx,%ecx\n\tandl\t$0x0f,%ecx\n        shrl\t$2,%ecx\n\tjz\t_$10\n_$9:\n\txorl\t(%esi),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\taddl\t$4,%esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$9\n_$10:\n\tmovl\t%edx,%ecx\n\tandl\t$0x03,%ecx\n\tjz\t_$4\n_$11:\n\txorb    (%esi),%al\n\tincl    %esi\n\tmovzbl\t%al,%ebx\n\tshrl\t$8,%eax\n\txorl\t(%edi,%ebx,4),%eax\n\tdecl\t%ecx\n\tjnz\t_$11\n_$4:\n\txorl\t$0xffffffff,%eax\n_$3:\n\t.line\t52\n\tpopl\t%edi\n\tpopl\t%esi\n\tpopl\t%ebx\n\tleave\n\tret\n_$34:\n\t.size\t_crc32,_$34-_crc32\n\t.globl\t_crc32\n\t.extern\t_get_crc_table\n"
  },
  {
    "path": "deps/infozip/zip30/win32/gvmat64.asm",
    "content": ";uInt longest_match_x64(\n;    deflate_state *s,\n;    IPos cur_match);                             /* current match */\n\n; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86\n; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.\n;\n; File written by Gilles Vollant, by converting to assembly the longest_match\n;  from Jean-loup Gailly in deflate.c of zLib and infoZip zip.\n;\n;  and by taking inspiration on asm686 with masm, optimised assembly code \n;        from Brian Raiter, written 1998\n;\n;         http://www.zlib.net\n;         http://www.winimage.com/zLibDll\n;         http://www.muppetlabs.com/~breadbox/software/assembly.html\n;\n; to compile this file for infozip Zip, I use option:\n;   ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm\n;\n; to compile this file for zLib, I use option:\n;   ml64.exe /Flgvmat64 /c /Zi gvmat64.asm\n; Be carrefull to adapt zlib1222add below to your version of zLib\n;   (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change\n;    value of zlib1222add later)\n;\n; This file compile with Microsoft Macro Assembler (x64) for AMD64\n;\n;   ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK\n;\n;   (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from\n;      http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)\n;\n\n\n;uInt longest_match(s, cur_match)\n;    deflate_state *s;\n;    IPos cur_match;                             /* current match */\n.code\nlongest_match PROC\n\n\n;LocalVarsSize   equ 88\n LocalVarsSize   equ 72\n\n; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12\n; free register :  r14,r15\n; register can be saved : rsp\n\n chainlenwmask   equ  rsp + 8 - LocalVarsSize    ; high word: current chain len\n                                                 ; low word: s->wmask\n;window          equ  rsp + xx - LocalVarsSize   ; local copy of s->window ; stored in r10\n;windowbestlen   equ  rsp + xx - LocalVarsSize   ; s->window + bestlen , use r10+r11\n;scanstart       equ  rsp + xx - LocalVarsSize   ; first two bytes of string ; stored in r12w\n;scanend         equ  rsp + xx - LocalVarsSize   ; last two bytes of string use ebx\n;scanalign       equ  rsp + xx - LocalVarsSize   ; dword-misalignment of string r13\n;bestlen         equ  rsp + xx - LocalVarsSize   ; size of best match so far -> r11d\n;scan            equ  rsp + xx - LocalVarsSize   ; ptr to string wanting match -> r9\nIFDEF INFOZIP\nELSE\n nicematch       equ  (rsp + 16 - LocalVarsSize) ; a good enough match size\nENDIF\n\nsave_rdi        equ  rsp + 24 - LocalVarsSize\nsave_rsi        equ  rsp + 32 - LocalVarsSize\nsave_rbx        equ  rsp + 40 - LocalVarsSize\nsave_rbp        equ  rsp + 48 - LocalVarsSize\nsave_r12        equ  rsp + 56 - LocalVarsSize\nsave_r13        equ  rsp + 64 - LocalVarsSize\n;save_r14        equ  rsp + 72 - LocalVarsSize\n;save_r15        equ  rsp + 80 - LocalVarsSize\n\n\n\n;  all the +4 offsets are due to the addition of pending_buf_size (in zlib\n;  in the deflate_state structure since the asm code was first written\n;  (if you compile with zlib 1.0.4 or older, remove the +4).\n;  Note : these value are good with a 8 bytes boundary pack structure\n\n\n    MAX_MATCH           equ     258\n    MIN_MATCH           equ     3\n    MIN_LOOKAHEAD       equ     (MAX_MATCH+MIN_MATCH+1)\n\n\n;;; Offsets for fields in the deflate_state structure. These numbers\n;;; are calculated from the definition of deflate_state, with the\n;;; assumption that the compiler will dword-align the fields. (Thus,\n;;; changing the definition of deflate_state could easily cause this\n;;; program to crash horribly, without so much as a warning at\n;;; compile time. Sigh.)\n\n;  all the +zlib1222add offsets are due to the addition of fields\n;  in zlib in the deflate_state structure since the asm code was first written\n;  (if you compile with zlib 1.0.4 or older, use \"zlib1222add equ (-4)\").\n;  (if you compile with zlib between 1.0.5 and 1.2.2.1, use \"zlib1222add equ 0\").\n;  if you compile with zlib 1.2.2.2 or later , use \"zlib1222add equ 8\").\n\n\nIFDEF INFOZIP\n\n_DATA   SEGMENT\nCOMM    window_size:DWORD\n; WMask ; 7fff\nCOMM    window:BYTE:010040H\nCOMM    prev:WORD:08000H\n; MatchLen : unused\n; PrevMatch : unused\nCOMM    strstart:DWORD\nCOMM    match_start:DWORD\n; Lookahead : ignore\nCOMM    prev_length:DWORD ; PrevLen\nCOMM    max_chain_length:DWORD\nCOMM    good_match:DWORD\nCOMM    nice_match:DWORD\nprev_ad equ OFFSET prev\nwindow_ad equ OFFSET window\nnicematch equ nice_match\n_DATA ENDS\nWMask equ 07fffh\n\nELSE\n\n  IFNDEF zlib1222add\n    zlib1222add equ 0\n  ENDIF\ndsWSize         equ 56+zlib1222add+(zlib1222add/2)\ndsWMask         equ 64+zlib1222add+(zlib1222add/2)\ndsWindow        equ 72+zlib1222add\ndsPrev          equ 88+zlib1222add\ndsMatchLen      equ 128+zlib1222add\ndsPrevMatch     equ 132+zlib1222add\ndsStrStart      equ 140+zlib1222add\ndsMatchStart    equ 144+zlib1222add\ndsLookahead     equ 148+zlib1222add\ndsPrevLen       equ 152+zlib1222add\ndsMaxChainLen   equ 156+zlib1222add\ndsGoodMatch     equ 172+zlib1222add\ndsNiceMatch     equ 176+zlib1222add\n\nwindow_size     equ [ rcx + dsWSize]\nWMask           equ [ rcx + dsWMask]\nwindow_ad       equ [ rcx + dsWindow]\nprev_ad         equ [ rcx + dsPrev]\nstrstart        equ [ rcx + dsStrStart]\nmatch_start     equ [ rcx + dsMatchStart]\nLookahead       equ [ rcx + dsLookahead] ; 0ffffffffh on infozip\nprev_length     equ [ rcx + dsPrevLen]\nmax_chain_length equ [ rcx + dsMaxChainLen]\ngood_match      equ [ rcx + dsGoodMatch]\nnice_match      equ [ rcx + dsNiceMatch]\nENDIF\n\n; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)\n\n; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and\n; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp\n;\n; All registers must be preserved across the call, except for\n;   rax, rcx, rdx, r8, r9, r10, and r11, which are scratch.\n\n\n\n;;; Save registers that the compiler may be using, and adjust esp to\n;;; make room for our stack frame.\n\n\n;;; Retrieve the function arguments. r8d will hold cur_match\n;;; throughout the entire function. edx will hold the pointer to the\n;;; deflate_state structure during the function's setup (before\n;;; entering the main loop.\n\n; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)\n\n; this clear high 32 bits of r8, which can be garbage in both r8 and rdx\n\n        mov [save_rdi],rdi\n        mov [save_rsi],rsi\n        mov [save_rbx],rbx\n        mov [save_rbp],rbp\nIFDEF INFOZIP\n        mov r8d,ecx\nELSE\n        mov r8d,edx\nENDIF\n        mov [save_r12],r12\n        mov [save_r13],r13\n;        mov [save_r14],r14\n;        mov [save_r15],r15\n\n\n;;; uInt wmask = s->w_mask;\n;;; unsigned chain_length = s->max_chain_length;\n;;; if (s->prev_length >= s->good_match) {\n;;;     chain_length >>= 2;\n;;; }\n\n        mov edi, prev_length\n        mov esi, good_match\n        mov eax, WMask\n        mov ebx, max_chain_length\n        cmp edi, esi\n        jl  LastMatchGood\n        shr ebx, 2\nLastMatchGood:\n\n;;; chainlen is decremented once beforehand so that the function can\n;;; use the sign flag instead of the zero flag for the exit test.\n;;; It is then shifted into the high word, to make room for the wmask\n;;; value, which it will always accompany.\n\n        dec ebx\n        shl ebx, 16\n        or  ebx, eax\n\n;;; on zlib only\n;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;\n\nIFDEF INFOZIP\n        mov [chainlenwmask], ebx\n; on infozip nice_match = [nice_match]\nELSE\n        mov eax, nice_match\n        mov [chainlenwmask], ebx\n        mov r10d, Lookahead\n        cmp r10d, eax\n        cmovnl r10d, eax\n        mov [nicematch],r10d\nENDIF\n\n;;; register Bytef *scan = s->window + s->strstart;\n        mov r10, window_ad\n        mov ebp, strstart\n        lea r13, [r10 + rbp]\n\n;;; Determine how many bytes the scan ptr is off from being\n;;; dword-aligned.\n\n         mov r9,r13\n         neg r13\n         and r13,3\n\n;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?\n;;;     s->strstart - (IPos)MAX_DIST(s) : NIL;\nIFDEF INFOZIP\n        mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1))\nELSE\n        mov eax, window_size\n        sub eax, MIN_LOOKAHEAD\nENDIF\n        xor edi,edi\n        sub ebp, eax\n\n        mov r11d, prev_length\n\n        cmovng ebp,edi\n\n;;; int best_len = s->prev_length;\n\n\n;;; Store the sum of s->window + best_len in esi locally, and in esi.\n\n       lea  rsi,[r10+r11]\n\n;;; register ush scan_start = *(ushf*)scan;\n;;; register ush scan_end   = *(ushf*)(scan+best_len-1);\n;;; Posf *prev = s->prev;\n\n        movzx r12d,word ptr [r9]\n        movzx ebx, word ptr [r9 + r11 - 1]\n\n        mov rdi, prev_ad\n\n;;; Jump into the main loop.\n\n        mov edx, [chainlenwmask]\n\n        cmp bx,word ptr [rsi + r8 - 1]\n        jz  LookupLoopIsZero\n\nLookupLoop1:\n        and r8d, edx\n\n        movzx   r8d, word ptr [rdi + r8*2]\n        cmp r8d, ebp\n        jbe LeaveNow\n        sub edx, 00010000h\n        js  LeaveNow\n\nLoopEntry1:\n        cmp bx,word ptr [rsi + r8 - 1]\n        jz  LookupLoopIsZero\n\nLookupLoop2:\n        and r8d, edx\n\n        movzx   r8d, word ptr [rdi + r8*2]\n        cmp r8d, ebp\n        jbe LeaveNow\n        sub edx, 00010000h\n        js  LeaveNow\n\nLoopEntry2:\n        cmp bx,word ptr [rsi + r8 - 1]\n        jz  LookupLoopIsZero\n\nLookupLoop4:\n        and r8d, edx\n\n        movzx   r8d, word ptr [rdi + r8*2]\n        cmp r8d, ebp\n        jbe LeaveNow\n        sub edx, 00010000h\n        js  LeaveNow\n\nLoopEntry4:\n\n        cmp bx,word ptr [rsi + r8 - 1]\n        jnz LookupLoop1\n        jmp LookupLoopIsZero\n\n\n;;; do {\n;;;     match = s->window + cur_match;\n;;;     if (*(ushf*)(match+best_len-1) != scan_end ||\n;;;         *(ushf*)match != scan_start) continue;\n;;;     [...]\n;;; } while ((cur_match = prev[cur_match & wmask]) > limit\n;;;          && --chain_length != 0);\n;;;\n;;; Here is the inner loop of the function. The function will spend the\n;;; majority of its time in this loop, and majority of that time will\n;;; be spent in the first ten instructions.\n;;;\n;;; Within this loop:\n;;; ebx = scanend\n;;; r8d = curmatch\n;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)\n;;; esi = windowbestlen - i.e., (window + bestlen)\n;;; edi = prev\n;;; ebp = limit\n\nLookupLoop:\n        and r8d, edx\n\n        movzx   r8d, word ptr [rdi + r8*2]\n        cmp r8d, ebp\n        jbe LeaveNow\n        sub edx, 00010000h\n        js  LeaveNow\n\nLoopEntry:\n\n        cmp bx,word ptr [rsi + r8 - 1]\n        jnz LookupLoop1\nLookupLoopIsZero:\n        cmp     r12w, word ptr [r10 + r8]\n        jnz LookupLoop1\n\n\n;;; Store the current value of chainlen.\n        mov [chainlenwmask], edx\n\n;;; Point edi to the string under scrutiny, and esi to the string we\n;;; are hoping to match it up with. In actuality, esi and edi are\n;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is\n;;; initialized to -(MAX_MATCH_8 - scanalign).\n\n        lea rsi,[r8+r10]\n        mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)\n        lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]\n        lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]\n\n        prefetcht1 [rsi+rdx]\n        prefetcht1 [rdi+rdx]\n        \n     \n;;; Test the strings for equality, 8 bytes at a time. At the end,\n;;; adjust rdx so that it is offset to the exact byte that mismatched.\n;;;\n;;; We already know at this point that the first three bytes of the\n;;; strings match each other, and they can be safely passed over before\n;;; starting the compare loop. So what this code does is skip over 0-3\n;;; bytes, as much as necessary in order to dword-align the edi\n;;; pointer. (rsi will still be misaligned three times out of four.)\n;;;\n;;; It should be confessed that this loop usually does not represent\n;;; much of the total running time. Replacing it with a more\n;;; straightforward \"rep cmpsb\" would not drastically degrade\n;;; performance.\n\n\nLoopCmps:\n        mov rax, [rsi + rdx]\n        xor rax, [rdi + rdx]\n        jnz LeaveLoopCmps\n\n        mov rax, [rsi + rdx + 8]\n        xor rax, [rdi + rdx + 8]\n        jnz LeaveLoopCmps8\n\n\n        mov rax, [rsi + rdx + 8+8]\n        xor rax, [rdi + rdx + 8+8]\n        jnz LeaveLoopCmps16\n\n        add rdx,8+8+8\n\n        jmp short LoopCmps\nLeaveLoopCmps16: add rdx,8\nLeaveLoopCmps8: add rdx,8\nLeaveLoopCmps:\n\n        test    eax, 0000FFFFh\n        jnz LenLower\n\n        test eax,0ffffffffh\n\n        jnz LenLower32\n\n        add rdx,4\n        shr rax,32\n        or ax,ax\n        jnz LenLower\n\nLenLower32:\n        shr eax,16\n        add rdx,2\nLenLower:   sub al, 1\n        adc rdx, 0\n;;; Calculate the length of the match. If it is longer than MAX_MATCH,\n;;; then automatically accept it as the best possible match and leave.\n\n        lea rax, [rdi + rdx]\n        sub rax, r9\n        cmp eax, MAX_MATCH\n        jge LenMaximum\n\n;;; If the length of the match is not longer than the best match we\n;;; have so far, then forget it and return to the lookup loop.\n;///////////////////////////////////\n\n        cmp eax, r11d\n        jg  LongerMatch\n\n        lea rsi,[r10+r11]\n\n        mov rdi, prev_ad\n        mov edx, [chainlenwmask]\n        jmp LookupLoop\n\n;;;         s->match_start = cur_match;\n;;;         best_len = len;\n;;;         if (len >= nice_match) break;\n;;;         scan_end = *(ushf*)(scan+best_len-1);\n\nLongerMatch:\n        mov r11d, eax\n        mov match_start, r8d\n        cmp eax, [nicematch]\n        jge LeaveNow\n\n        lea rsi,[r10+rax]\n\n        movzx   ebx, word ptr [r9 + rax - 1]\n        mov rdi, prev_ad\n        mov edx, [chainlenwmask]\n        jmp LookupLoop\n\n;;; Accept the current string, with the maximum possible length.\n\nLenMaximum:\n        mov r11d,MAX_MATCH\n        mov match_start, r8d\n\n;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;\n;;; return s->lookahead;\n\nLeaveNow:\nIFDEF INFOZIP\n        mov eax,r11d\nELSE\n        mov eax, Lookahead\n        cmp r11d, eax\n        cmovng eax, r11d\nENDIF\n\n;;; Restore the stack and return from whence we came.\n\n\n        mov rsi,[save_rsi]\n        mov rdi,[save_rdi]\n        mov rbx,[save_rbx]\n        mov rbp,[save_rbp]\n        mov r12,[save_r12]\n        mov r13,[save_r13]\n;        mov r14,[save_r14]\n;        mov r15,[save_r15]\n\n\n        ret 0\n; please don't remove this string !\n; Your can freely use gvmat64 in any free or commercial app\n; but it is far better don't remove the string in the binary!\n    db     0dh,0ah,\"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005\",0dh,0ah,0\nlongest_match   ENDP\n\nmatch_init PROC\n  ret 0\nmatch_init ENDP\n\n\nEND\n"
  },
  {
    "path": "deps/infozip/zip30/win32/lm32_lcc.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 1999-Oct-05 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, both of these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n;===========================================================================\n; match32.asm by Jean-loup Gailly.\n\n; match32.asm, optimized version of longest_match() in deflate.c\n; To be used only with 32 bit flat model. To simplify the code, the option\n; -DDYN_ALLOC is not supported.\n; This file is only optional. If you don't have an assembler, use the\n; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o\n; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is\n; assembled with an equivalent -DWSIZE=<whatever>.\n;\n; Win32 (Windows NT) version - 1994/04/13 by Steve Salisbury\n; * works with Microsoft MASM 6.1X and Microsoft Visual C++ / 32-bit edition\n;\n; The code in this file has been copied verbatim from match32.{asm|S};\n; only the assembler syntax and metacommands have been adapted to\n; the habits of the free LCC-Win32 C compiler package.\n; IMPORTANT NOTE to the Info-ZIP editors:\n; The TAB characters in this source file are required by the parser of\n; the LCC-Win32 assembler program and MUST NOT be removed!!\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used.\n;\n\n\n;/* This version is for 386 Unix or OS/2 in 32 bit mode.\n; * Warning: it uses the AT&T syntax: mov source,dest\n; * This file is only optional. If you want to force the C version,\n; * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.\n; * If you have reduced WSIZE in (g)zip.h, then make sure this is\n; * assembled with an equivalent -DWSIZE=<whatever>.\n; * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).\n; */\n\n        .text\n        .file\t\"match.S\"\n\n\n        .text\n        .type\t_match_init,function\n\n_match_init:\n        ret\n_$98:\n        .size\t_match_init,_$98-_match_init\n        .globl\t_match_init\n\n;/*-----------------------------------------------------------------------\n; * Set match_start to the longest match starting at the given string and\n; * return its length. Matches shorter or equal to prev_length are discarded,\n; * in which case the result is equal to prev_length and match_start is\n; * garbage.\n; * IN assertions: cur_match is the head of the hash chain for the current\n; *   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n; */\n\n        .align\t4\n        .type\t_longest_match,function\n\n_longest_match: ;/* int longest_match(cur_match) */\n\n;       cur_match     equ 20(%esp)\n;     /* return address */               /* esp+16 */\n        push    %ebp\n        push    %edi\n;/* esp+8  */\n        push    %esi\n;/* esp+4  */\n        push    %ebx\n;/* esp    */\n\n;/*\n; *      match        equ esi\n; *      scan         equ edi\n; *      chain_length equ ebp\n; *      best_len     equ ebx\n; *      limit        equ edx\n; */\n        mov     20(%esp),%esi\n        mov     _strstart,%edx\n        mov     _max_chain_length,%ebp\n        mov     %edx,%edi\n        sub     $(32768-262),%edx\n        cld\n        jae     limit_ok\n        sub     %edx,%edx\nlimit_ok:\n        add     $2+_window,%edi\n        mov     _prev_length,%ebx\n        movw    -2(%edi),%cx\n        movw    -3(%ebx,%edi),%ax\n        cmp     _good_match,%ebx\n        jb      do_scan\n        shr     $2,%ebp\n        jmp     do_scan\n\n        .align\t4\nlong_loop:\n;/* at this point, edi == scan+2, esi == cur_match */\n        movw    -3(%ebx,%edi),%ax\n        movw     -2(%edi),%cx\nshort_loop:\n;/*\n; * at this point, di == scan+2, si == cur_match,\n; * ax = scan[best_len-1..best_len] and cx = scan[0..1]\n; */\n        and     $(32768-1), %esi\n        dec     %ebp\n        movw    _prev(,%esi,2),%si\n        jz      the_end\n        cmp     %edx,%esi\n        jbe     the_end\ndo_scan:\n        cmpw    _window-1(%ebx,%esi),%ax\n        jne     short_loop\n        cmpw    _window(%esi),%cx\n        jne     short_loop\n\n        add     $2+_window,%esi\n        mov     $((258>>1)-1),%ecx\n        mov     %edi,%eax\n        repe;   cmpsw\n;/* loop until mismatch */\n        je      maxmatch\n;/* match of length MAX_MATCH? */\nmismatch:\n        movb    -2(%edi),%cl\n        xchg    %edi,%eax\n        subb    -2(%esi),%cl\n        sub     %edi,%eax\n        sub     $2+_window,%esi\n        sub     %eax,%esi\n        subb    $1,%cl\n        adc     $0,%eax\n        cmp     %ebx,%eax\n        jle     long_loop\n        mov     %esi,_match_start\n        mov     %eax,%ebx\n        cmp     _nice_match,%eax\n; /* len >= nice_match ? */\n        jl      long_loop\nthe_end:\n        mov     %ebx,%eax\n        pop     %ebx\n        pop     %esi\n        pop     %edi\n        pop     %ebp\n        ret\n        .align\t4\nmaxmatch:\n        cmpsb\n        jmp     mismatch\n_$99:\n\n        .size\t_longest_match,_$99-_longest_match\n        .globl\t_longest_match\n\n        .extern\t_nice_match\n        .extern\t_good_match\n        .extern\t_max_chain_length\n        .extern\t_match_start\n        .extern\t_strstart\n        .extern\t_prev_length\n        .extern\t_prev\n        .extern\t_window\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.a64",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# 32-bit Microsoft Visual C++\n\n# To use, do \"nmake -f makefile.w32\"\n\n# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if\n# you do not have masm 6.1X.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = $(LOCAL_ZIP)\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\nASMOBJS = gvmat64.obj\n\n# ------------- 32-bit Microsoft Visual C++ -------------\nCC=cl -nologo\nCFLAGS=-W3 -O2 -DNO_ASM_CRC -DASMV -DWIN32 $(LOC)\nUTILFLAGS=$(CFLAGS) -DUTIL -Fo$@\n\n# Remove \"-coff\" from ASFLAGS if you do not have MASM 6.11.\n\nAS=ml64 -nologo\nASFLAGS= /c /Zi /DINFOZIP\n\n# If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them\n# with the /KNOWEAS switch, you can build dual-mode MS-DOS/Win32 executables\n# by passing the -stub switch to the 32-bit linker to specify the 16-bit part.\n\nLD=link -nologo\nLDFLAGS=advapi32.lib\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n    crc32.obj globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crc32_.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:   $(ZIPS)\n\nzip.obj:        zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n    $(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:    zipfile.c $(ZIP_H) crc32.h\n    $(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\n    $(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:     fileio.c $(ZIP_H) crc32.h\n    $(CC) -c $(CFLAGS) $*.c\n\nutil.obj:       util.c $(ZIP_H)\n    $(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:    globals.c $(ZIP_H)\n    $(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:    deflate.c $(ZIP_H)\n    $(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:      trees.c $(ZIP_H)\n    $(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:      crc32.c $(ZIP_H) crc32.h\n    $(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n    $(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n    $(CC) -c $(CFLAGS) $*.c\n\nwin32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n    $(CC) -c $(CFLAGS) -I. win32/win32zip.c\n\nwin32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h\n    $(CC) -c $(CFLAGS) -I. win32/win32.c\n\nnt.obj:         win32/nt.c $(ZIP_H) win32/nt.h\n    $(CC) -c $(CFLAGS) -I. win32/nt.c\n\nzipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h\n    $(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:    zipnote.c $(ZIP_H) revision.h\n    $(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:   zipsplit.c $(ZIP_H) revision.h\n    $(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:   zipfile.c $(ZIP_H) crc32.h\n    $(CC) -c $(UTILFLAGS) zipfile.c\n\nfileio_.obj:    fileio.c $(ZIP_H) crc32.h\n    $(CC) -c $(UTILFLAGS) fileio.c\n\nutil_.obj:      util.c $(ZIP_H)\n    $(CC) -c $(UTILFLAGS) util.c\n\ncrc32_.obj:     crc32.c $(ZIP_H) crc32.h\n    $(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.obj:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n    $(CC) -c $(UTILFLAGS) crypt.c\n\nwin32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h\n    $(CC) -c $(UTILFLAGS) -I. win32/win32.c\n\ngvmat64.obj:    win32/gvmat64.asm\n    $(AS) $(ASFLAGS) win32\\gvmat64.asm\n\nzip.exe: $(OBJZ) $(OBJI)\n    $(LD) $(LDFLAGS) $(OBJZ) $(OBJI)\n\nzipcloak.exe: $(OBJC)\n    $(LD) $(LDFLAGS) $(OBJC)\n\nzipnote.exe: $(OBJN)\n    $(LD) $(LDFLAGS) $(OBJN)\n\nzipsplit.exe: $(OBJS)\n    $(LD) $(LDFLAGS) $(OBJS)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.bor",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# Borland C++ for Win32.\n# By E-Yen Tan.\n# Updated on 18 Dec 2005 by Cosmin Truta.\n# Last updated on 22 Jun 2008 by Christian Spieler.\n\n# To use, do \"make -fwin32\\makefile.bor\"\n\n# Add -DNO_ASM to LOC and comment out the ASMOBJS definition below\n# if you do not have tasm32.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\n!IF $(USEASM)\nLOC = $(LOCAL_ZIP)\n!ELSE\nLOC = -DNO_ASM $(LOCAL_ZIP)\n!ENDIF\n\n# CPU type: 3 (i386), 4 (i486), 5 (Pentium), etc.\nCPU_TYP = 6\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\n!IF $(USEASM)\nASMOBJS = match32.obj\nCRCA_O = crc_i386.obj\n!ENDIF\n\nASCPUFLAG = __$(CPU_TYP)86\n\nVPATH=.;win32\nCC = bcc32\nCFLAGS=-w -w-aus -w-ccc -w-par -w-sig -O2 -I. -DWIN32 $(LOC)\nUTILFLAGS=-DUTIL $(CFLAGS) -o\n\n!ifdef USETASM16\nAS=tasm\n!else\nAS=tasm32\n!endif\nASFLAGS=-ml -t -m2 -D$(ASCPUFLAG) $(LOC)\n\nLD=ilink32\nLDFLAGS=\n\n# variables\nOBJZ1 = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n\tcrc32.obj $(CRCA_O) globals.obj\nOBJZ2 = deflate.obj trees.obj $(ASMOBJS)\nOBJZS = win32zip.obj win32.obj win32i64.obj nt.obj\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS)\n\nOBJU  = zipfile_.obj fileio_.obj util_.obj crc32_.obj $(CRCA_O) globals.obj \\\n\twin32_.obj win32i64.obj\nOBJN  = zipnote.obj $(OBJU)\nOBJC  = zipcloak.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS  = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips: $(ZIPS)\n\nzip.obj:        zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:    zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:     fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nutil.obj:       util.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:    globals.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:    deflate.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:      trees.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:      crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nwin32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c $(CFLAGS) win32/$*.c\n\nwin32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(CFLAGS) win32/$*.c\n\nwin32i64.obj:   win32/win32i64.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) win32/$*.c\n\nnt.obj:         win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) win32/$*.c\n\nzipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:    zipnote.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:   zipsplit.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:   zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* zipfile.c\n\nfileio_.obj:    fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* fileio.c\n\nutil_.obj:      util.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS)$* util.c\n\ncrc32_.obj:     crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS)$* crc32.c\n\ncrypt_.obj:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS)$* crypt.c\n\nwin32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(UTILFLAGS)$* win32/win32.c\n\n!ifdef USEMASM\ncrc_i386.obj:   win32/crc_i386.asm\n\tmasm -ml win32/crc_i386.asm,$@;\n!else\n!ifndef ASMOVERBCC32\ncrc_i386.obj:   win32/crc_i386.asm\n\t$(AS) $(ASFLAGS) win32\\crc_i386.asm, $@ ;\n!else\ncrc_i386.obj:\twin32/crc_i386.c crc32.h\n\t$(CC) -c $(CFLAGS) -o$@ win32/crc_i386.c\n!endif\n!endif\n\n!ifdef USEMASM\nmatch32.obj:    win32/match32.asm\n\tmasm -ml win32/match32.asm,$@;\n!else\nmatch32.obj:    win32/match32.asm\n\t$(AS) $(ASFLAGS) win32\\match32.asm, $@ ;\n!endif\n\nzip.res:        win32/zip.rc revision.h\n\t$(RC) /l 0x409 /fo$@ /i win32 /d WIN32 win32/zip.rc\n\n# Split the command line to fit in the MS-DOS 128 byte limit by using\n# Borland-Make specific response file syntax:\nzip.exe: $(OBJZ) zip.res\n\t$(LD) -Gn -x -c -ap -Tpe @&&|\nc0x32.obj $(OBJZ),$@,,import32.lib cw32.lib,,zip.res\n|\n\nzipcloak.exe: $(OBJC)\n\t$(CC) $(LDFLAGS) @&&|\n$(OBJC)\n|\n\nzipnote.exe: $(OBJN)\n\t$(CC) $(LDFLAGS) @&&|\n$(OBJN)\n|\n\nzipsplit.exe: $(OBJS)\n\t$(CC) $(LDFLAGS) @&&|\n$(OBJS)\n|\n\nclean:\n\t-del *.obj\n\t-del *.res\n\t-del *.exe\n\t-del *.tds\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.dj",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit\n# for djgpp 2.01 and RSXNTDJ 1.3.1 under Windows 95 / Windows NT\n# Derived from makefile.os2 by E-Yen Tan. Last updated 07 Jan 2007.\n\nCC = gcc -O2 -m486 -Wall -Zwin32\nCFLAGS = -DWIN32 -DASM_CRC $(LOCAL_ZIP)\nAS = gcc\nASFLAGS = -Di386\nLDFLAGS = -o ./\nLDFLAGS2 =\nOBJ=.o\n\nCRC32=crc_gcc\nOBJA    = matchgcc.o\nOBJZS   = win32.o win32zip.o nt.o\nOBJUS   = win32_.o\nOSDEP_H = win32/osdep.h\n\nADVAPI32 = adv32\nADVAPI32LIB = lib$(ADVAPI32).a\nL_ADVAPI32 = -l$(ADVAPI32)\n\nOBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \\\n\tcrc32$(OBJ) $(CRCA_O)\nOBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \\\n\tttyio$(OBJ)\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)\n\nOBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) crc32$(OBJ) globals$(OBJ)\nOBJU  = $(OBJU1) $(OBJUS)\n\nOBJN =  zipnote$(OBJ) $(OBJU)\nOBJS =  zipsplit$(OBJ) $(OBJU)\nOBJC =  zipcloak$(OBJ) crc32_$(OBJ) crypt_$(OBJ) ttyio$(OBJ) $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES: .c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c -I. $(CFLAGS) $<\n\n.asm$(OBJ):\n\t$(AS) $(ASFLAGS) $<\n\nall:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip$(OBJ):      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile$(OBJ):  zipfile.c $(ZIP_H) crc32.h\nzipup$(OBJ):    zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\nfileio$(OBJ):   fileio.c $(ZIP_H) crc32.h\nutil$(OBJ):     util.c $(ZIP_H)\nglobals$(OBJ):  globals.c $(ZIP_H)\ndeflate$(OBJ):  deflate.c $(ZIP_H)\ntrees$(OBJ):    trees.c $(ZIP_H)\ncrc32$(OBJ):    crc32.c $(ZIP_H) crc32.h\ncrypt$(OBJ):    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(OBJ):    ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nwin32zip$(OBJ): win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c -I. $(CFLAGS) win32/win32zip.c\n\nwin32$(OBJ):    win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CFLAGS) win32/win32.c\n\nnt$(OBJ):       win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c -I. $(CFLAGS) win32/nt.c\n\ncrc_gcc$(OBJ):  crc_i386.S                                      # 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o$@ crc_i386.S\n\nmatchgcc$(OBJ): match.S\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o$@ match.S\n\nzipcloak$(OBJ): zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipnote$(OBJ):  zipnote.c $(ZIP_H) revision.h\nzipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h\n\nzipfile_$(OBJ): zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ zipfile.c\n\nfileio_$(OBJ):  fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ fileio.c\n\nutil_$(OBJ):    util.c $(ZIP_H) os2/os2zip.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ util.c\n\ncrc32_$(OBJ):   crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ crc32.c\n\ncrypt_$(OBJ):   crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ crypt.c\n\nwin32_$(OBJ):   win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CFLAGS) -DUTIL -o$@ win32/win32.c\n\n$(ADVAPI32LIB):\n\tmakelib \"$(windir)/system/advapi32.dll\" -o ./$@\n\nzip.exe: $(OBJZ) $(ADVAPI32LIB)\n\t$(CC) $(LDFLAGS)$@ $(OBJZ) $(L_ADVAPI32) $(LDFLAGS2)\n\nzipcloak.exe: $(OBJC)\n\t$(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)\n\nzipnote.exe: $(OBJN)\n\t$(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)\n\nzipsplit.exe: $(OBJS)\n\t$(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.emx",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit\n# using emx 0.9c+rsxnt for Windows 95/98 and Windows NT and emx 0.9c for DOS.\n# By Kai-Uwe Rommel, Chr. Spieler, E-Yen Tan (and others).\n# Last updated 18th February 2007.\n#\n# Supported Make utilities:\n# - Microsoft/IBM nmake (e.g. from MSC 6.0 or newer)\n# - dmake 3.8 or higher\n# - GNU make, at least version 3.68 (GNUish 16-bit port, RSXNT Make 3.75,\n#   DJGPP v1.12 Make 3.71, some versions of DJGPP v2.x 32-bit Make;\n#   current DJGPP v2.01 Make 3.76.1 does NOT work)\n# - NOT watcom make\n# The \"smart\" Make utilities mentioned below are Christian Spieler's\n# enhanced version of GNUish 16-bit Make (3.74) and his adaption of these\n# GNU Make sources to EMX (32-bit).\n\n# Supported 32-bit C Compilers (created programs run under WinNT/Win95 only):\n# - GNU gcc (emx/rsxnt kit 0.9c or newer)\n\n# Supported Cross-Compilers for MS-DOS:\n# - GNU gcc (emx kit 0.9c or newer, 32-bit)\n\n# Supported Assemblers:\n# - GNU as with GNU gcc\n\n\n# To use, enter \"make/nmake/dmake -f win32/makefile.emx\"\n# (this makefile depends on its name being \"win32/makefile.emx\").\n\n# Add -DDYN_ALLOC to ASFLAGS if you have defined it in tailor.h or CFLAGS\n\n# Note: assembly language modules are really only supported for\n# GNU gcc 32-bit compilation.\n\n\ndefault:\n\t@echo \"Enter $(MAKE) -f win32/makefile.emx target\"\n\t@echo \"where target is one of:\"\n\t@echo \"   gcc gccso gccdyn gccdebug gcczl gccdos gccdoszl\"\n\t@echo \"   -----------------------------------------------\"\n\t@echo \"Or, specify a specific target for a partial build,\"\n\t@echo \"This uses >gcc< setup (win32 statically linked binary)\"\n\n# emx 0.9c, gcc, PE format, statically linked C runtime and rsxnt.dll\ngcc:\tall\n\n# emx 0.9c, gcc, PE format, statically linked C runtime, standalone\ngccso:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -Zwin32 -Zsys -O2 -m486 -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DASM_CRC\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tCRCAUO=\"crcgcc_.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tDEF=\"win32/zip.def\"\n\n# emx 0.9c, gcc, PE format, dynamically linked C runtime and rsxnt.dll\ngccdyn:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -Zwin32 -Zcrtdll=crtrsxnt -O2 -m486 -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DASM_CRC\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tCRCAUO=\"crcgcc_.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tDEF=\"win32/zip.def\"\n\n# emx 0.9c, gcc, PE format, with debug info for gdb\ngccdebug:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -Zwin32 -O2 -g -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DASM_CRC\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-ladvapi32 -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tCRCAUO=\"crcgcc_.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tDEF=\"win32/zip.def\"\n\n# emx 0.9c, gcc, PE format,, statically linked zlib, C runtime, and rsxnt.dll\ngcczl:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -Zwin32 -O2 -m486 -Wall\" \\\n\tCFLAGS=\"-DWIN32 -DUSE_ZLIB\" \\\n\tAS=\"gcc -Zwin32\" \\\n\tASFLAGS=\"-Di386 -DUSE_ZLIB\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-L. -lzlib -ladvapi32 -s\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"\" \\\n\tCRCAUO=\"\" \\\n\tOBJA=\"\" \\\n\tDEF=\"win32/zip.def\"\n\n# emx 0.9c, gcc, a.out format, for MS-DOS\ngccdos:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -O2 -m486 -Wall\" \\\n\tCFLAGS=\"-DDOS -DMSDOS -DASM_CRC\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-s -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"crc_gcc.o\" \\\n\tCRCAUO=\"crcgcc_.o\" \\\n\tOBJA=\"matchgcc.o\" \\\n\tOBJZS=\"msdos.o\" \\\n\tOBJUS=\"msdos_.o\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\"\n\n# emx 0.9c, gcc, a.out format, for MS-DOS, using zlib\ngccdoszl:\n\t$(MAKE) -f win32/makefile.emx all \\\n\tCC=\"gcc -O2 -m486 -Wall\" \\\n\tCFLAGS=\"-DDOS -DMSDOS -DUSE_ZLIB\" \\\n\tAS=\"gcc\" \\\n\tASFLAGS=\"-Di386 -DUSE_ZLIB\" \\\n\tLDFLAGS=\"-o ./\" \\\n\tLDFLAGS2=\"-L. -lzlib -s -Zsmall-conv\" \\\n\tOUT=\"-o\" \\\n\tOBJ=\".o\" \\\n\tCRCA_O=\"\" \\\n\tCRCAUO=\"\" \\\n\tOBJA=\"\" \\\n\tOBJZS=\"msdos.o\" \\\n\tOBJUS=\"msdos_.o\" \\\n\tOSDEP_H=\"msdos/osdep.h\" \\\n\tZIPUP_H=\"msdos/zipup.h\"\n\n# VPATH = .;win32\n\n# variables\n\n#default settings for target dependent macros:\n\n# the \"gcc\" (statically linked Win32 executables) target:\nCC=gcc -Zwin32 -O2 -m486 -Wall\nCFLAGS=-DWIN32 -DASM_CRC\nAS=gcc -Zwin32\nASFLAGS=-Di386\nLDFLAGS=-o ./\nLDFLAGS2=-ladvapi32 -s -Zsmall-conv\nOUT=-o\nOBJ=.o\nCRCA_O=crc_gcc$(OBJ)\nCRCAUO=crcgcc_$(OBJ)\nOBJA=matchgcc$(OBJ)\nOSDEP_H=win32/osdep.h\nZIPUP_H=win32/zipup.h\nDEF=win32/zip.def\n\nDIRSEP = /\nAS_DIRSEP = /\nRM = del\nLOCAL_OPTS = $(LOCAL_ZIP)\nCCFLAGS = $(CFLAGS) $(LOCAL_OPTS)\n\n\nOBJZ1 = zip$(OBJ) zipfile$(OBJ) zipup$(OBJ) fileio$(OBJ) util$(OBJ) \\\n\tcrc32$(OBJ) $(CRCA_O)\nOBJZ2 = globals$(OBJ) deflate$(OBJ) trees$(OBJ) crypt$(OBJ) \\\n\tttyio$(OBJ)\nOBJZS =\twin32zip$(OBJ) win32$(OBJ) nt$(OBJ)\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS) $(OBJA)\n\nOBJU1 = zipfile_$(OBJ) fileio_$(OBJ) util_$(OBJ) crc32_$(OBJ) $(CRCAUO) \\\n\tglobals$(OBJ)\nOBJUS = win32_$(OBJ)\nOBJU  = $(OBJU1) $(OBJUS)\n\nOBJN  = zipnote$(OBJ) $(OBJU)\nOBJS  = zipsplit$(OBJ) $(OBJU)\nOBJC1 = zipcloak$(OBJ) crypt_$(OBJ) ttyio$(OBJ)\nOBJC  = $(OBJC1) $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)\n\n# rules\n\n.SUFFIXES: .c $(OBJ)\n\n.c$(OBJ):\n\t$(CC) -c -I. $(CCFLAGS) $(OUT)$@ $<\n\n# targets\n\nall:\tzip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip$(OBJ):\tzip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile$(OBJ):\tzipfile.c $(ZIP_H) crc32.h\nzipup$(OBJ):\tzipup.c $(ZIP_H) revision.h crc32.h crypt.h $(ZIPUP_H)\nfileio$(OBJ):\tfileio.c $(ZIP_H) crc32.h\nutil$(OBJ):\tutil.c $(ZIP_H)\nglobals$(OBJ):\tglobals.c $(ZIP_H)\ndeflate$(OBJ):\tdeflate.c $(ZIP_H)\ntrees$(OBJ):\ttrees.c $(ZIP_H)\ncrc32$(OBJ):\tcrc32.c $(ZIP_H) crc32.h\ncrypt$(OBJ):\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio$(OBJ):\tttyio.c $(ZIP_H) crypt.h ttyio.h\n\nmsdos$(OBJ):\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) msdos$(DIRSEP)msdos.c\n\nwin32zip$(OBJ):\twin32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32zip.c\n\nwin32$(OBJ):\twin32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)win32.c\n\nnt$(OBJ):\twin32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c -I. $(CCFLAGS) win32$(DIRSEP)nt.c\n\ncrc_gcc$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ crc_i386.S\n\nmatchgcc$(OBJ):\tmatch.S\n\t$(AS) $(ASFLAGS) -x assembler-with-cpp -c -o $@ match.S\n\nzipcloak$(OBJ):\tzipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h\nzipnote$(OBJ):\tzipnote.c $(ZIP_H) revision.h\nzipsplit$(OBJ): zipsplit.c $(ZIP_H) revision.h\n\nzipfile_$(OBJ):\tzipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ zipfile.c\n\nfileio_$(OBJ):\tfileio.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ fileio.c\n\nutil_$(OBJ):\tutil.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ util.c\n\ncrc32_$(OBJ):\tcrc32.c $(ZIP_H) crc32.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crc32.c\n\ncrypt_$(OBJ):\tcrypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ crypt.c\n\nmsdos_$(OBJ):\tmsdos/msdos.c $(ZIP_H)\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ msdos$(DIRSEP)msdos.c\n\nwin32_$(OBJ):\twin32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c -I. $(CCFLAGS) -DUTIL $(OUT)$@ win32$(DIRSEP)win32.c\n\ncrcgcc_$(OBJ):\tcrc_i386.S\t\t\t\t\t# 32bit, GNU AS\n\t$(AS) $(ASFLAGS) -DUTIL -x assembler-with-cpp -c -o $@ crc_i386.S\n\nzip.exe: $(OBJZ)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zip.rsp\n\t@for %%f in ($(OBJZ1)) do echo %%f >> zip.rsp\n\t@for %%f in ($(OBJZ2)) do echo %%f >> zip.rsp\n\t@for %%f in ($(OBJZS) $(OBJA)) do echo %%f >> zip.rsp\n\t$(CC) $(LDFLAGS)$@ @zip.rsp $(LDFLAGS2)\n\t@$(RM) zip.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJZ) $(LDFLAGS2)\n\nzipcloak.exe: $(OBJC)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zipcloak.rsp\n\t@for %%f in ($(OBJC1)) do echo %%f >> zipcloak.rsp\n\t@for %%f in ($(OBJU1)) do echo %%f >> zipcloak.rsp\n\t@for %%f in ($(OBJUS)) do echo %%f >> zipcloak.rsp\n\t$(CC) $(LDFLAGS)$@ @zipcloak.rsp $(LDFLAGS2)\n\t@$(RM) zipcloak.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJC) $(LDFLAGS2)\n\nzipnote.exe: $(OBJN)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zipnote.rsp\n\t@for %%f in ($(OBJN)) do echo %%f >> zipnote.rsp\n\t$(CC) $(LDFLAGS)$@ @zipnote.rsp $(LDFLAGS2)\n\t@$(RM) zipnote.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJN) $(LDFLAGS2)\n\nzipsplit.exe: $(OBJS)\n# for DUMB make utilities, uncomment the following commands:\n\t-@$(RM) zipsplit.rsp\n\t@for %%f in ($(OBJN)) do echo %%f >> zipsplit.rsp\n\t$(CC) $(LDFLAGS)$@ @zipsplit.rsp $(LDFLAGS2)\n\t@$(RM) zipsplit.rsp\n# smart make utilities (like well done ports of GNU Make) can use this:\n#\t$(CC) $(LDFLAGS)$@ $(OBJS) $(LDFLAGS2)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.gcc",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for port of gcc producing\n# native Win32-Intel binaries. Derived from makefile.w32.\n# Currently supported implementations: Cygwin and MinGW.\n# Authors: Cosmin Truta, Christian Spieler, and possibly others.\n# Last updated: 2008-Jun-22.\n#\n# To use, do \"make -f win32/makefile.gcc\".\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = $(LOCAL_ZIP)\n\n# ------------ GNU C ------------\nCC=gcc\nCFLAGS=-O2 -Wall -DWIN32 -DFORCE_WIN32_OVER_UNIX\nifndef USEZLIB\nCCFLAGS=$(CFLAGS) $(LOC)\nelse\nCCFLAGS=$(CFLAGS) -DUSE_ZLIB $(LOC)\nendif\nUTILFLAGS=$(CCFLAGS) -DUTIL -o$@\n\n#AS=as\nAS=$(CC)\nifndef USEZLIB\nASDEFS=\nelse\nASDEFS=-DUSE_ZLIB\nendif\nASFLAGS=-c $(ASDEFS) $(LOC)\n\nRC=windres\n\nLD=$(CC)\nLDFLAGS=-o$@ -s\nifndef USEZLIB\nLIBS=-luser32 -ladvapi32\nelse\nLIBS=-L. -lz -luser32 -ladvapi32\nendif\n\nOSDEP_H = win32/osdep.h\nZIPUP_H = win32/zipup.h\n\n# variables\nifndef USEZLIB\nCRCA_O = crc_i386.o\nCRCAUO = crci386_.o\nOBJA  = match.o $(CRCA_O)\nelse\nCRCA_O =\nCRCAUO =\nOBJA  =\nendif\n#use second definition for linking against libz\n\nOBJZ1 = zip.o crypt.o ttyio.o zipfile.o zipup.o fileio.o util.o \\\n\tcrc32.o globals.o\nOBJZ2 = deflate.o trees.o $(OBJA)\nOBJZS = win32.o win32zip.o win32i64.o nt.o\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZS)\n\nOBJU1 = zipfile_.o fileio_.o util_.o crc32_.o $(CRCAUO) globals.o\nOBJUS = win32_.o win32i64.o\nOBJU  = $(OBJU1) $(OBJUS)\n\nOBJN  = zipnote.o $(OBJU)\nOBJS  = zipsplit.o $(OBJU)\nOBJC1 = zipcloak.o crypt_.o ttyio.o\nOBJC  = $(OBJC1) $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h $(OSDEP_H)\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\n# rules\n\n.SUFFIXES: .c .o\n\n.c.o:\n\t$(CC) -c $(CCFLAGS) -I. -o$@ $<\n\n# targets\n\nzips: $(ZIPS)\n\nzip.o: zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile.o: zipfile.c $(ZIP_H) crc32.h\nzipup.o: zipup.c $(ZIP_H) revision.h crc32.h crypt.h $(ZIPUP_H)\nfileio.o: fileio.c $(ZIP_H) crc32.h\nutil.o: util.c $(ZIP_H)\nglobals.o: globals.c $(ZIP_H)\ndeflate.o: deflate.c $(ZIP_H)\ntrees.o: trees.c $(ZIP_H)\ncrc32.o: crc32.c $(ZIP_H) crc32.h\ncrypt.o: crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio.o: ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nwin32zip.o: win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c $(CCFLAGS) -I. win32/win32zip.c\n\nwin32.o: win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(CCFLAGS) -I. win32/win32.c\n\nwin32i64.o: win32/win32i64.c $(ZIP_H)\n\t$(CC) -c $(CCFLAGS) -I. win32/win32i64.c\n\nnt.o: win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c $(CCFLAGS) -I. win32/nt.c\n\nzipcloak.o: zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipnote.o: zipnote.c $(ZIP_H) revision.h\nzipsplit.o: zipsplit.c $(ZIP_H) revision.h\n\nzipfile_.o: zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) zipfile.c\n\nfileio_.o: fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) fileio.c\n\nutil_.o: util.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS) util.c\n\ncrc32_.o: crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.o: crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS) crypt.c\n\nwin32_.o: win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(UTILFLAGS) -I. win32/win32.c\n\nmatch.o: match.S\n\t$(AS) $(ASFLAGS) match.S\n\ncrc_i386.o: crc_i386.S\n\t$(AS) $(ASFLAGS) crc_i386.S\n\ncrci386_.o: crc_i386.S\n\t$(AS) $(ASFLAGS) -DUTIL -o$@ crc_i386.S\n\nziprc.o: win32/zip.rc revision.h\n\t- $(RC) -o $@ win32/zip.rc\n\nzip.exe: $(OBJZ) ziprc.o\n\t$(LD) $(LDFLAGS) $(OBJZ) ziprc.o $(LIBS)\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) $(OBJC) $(LIBS)\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) $(OBJN)\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) $(OBJS)\n\nclean:\n\trm -f *.o $(ZIPS)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.ibm",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# 32-bit IBM Visual Age C++\n\n# To use, do \"nmake -f win32\\makefile.ibm\"\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = $(LOCAL_ZIP)\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\n# ASMOBJS = match32.obj\n\n# ------------- 32-bit IBM Visual Age C++ -------------\nCC=icc -q -O\nCFLAGS=-W0 -DWIN32 -Sm -DNO_ASM -DNO_MKTEMP $(LOC)\nUTILFLAGS=$(CFLAGS) -DUTIL -Fo$@\nLDFLAGS=\nLIBS=advapi32.lib\nAS=ml -nologo\nASFLAGS=-c -Cx\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n\tcrc32.obj globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj globals.obj win32_.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crc32_.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:   $(ZIPS)\n\nzip.obj:        zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:    zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:     fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nutil.obj:       util.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:    globals.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:    deflate.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:      trees.c $(ZIP_H)\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:      crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nwin32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) -c $(CFLAGS) -I. win32/win32zip.c\n\nwin32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(CFLAGS) -I. win32/win32.c\n\nnt.obj:         win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) -c $(CFLAGS) -I. win32/nt.c\n\nzipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:    zipnote.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:   zipsplit.c $(ZIP_H) revision.h\n\t$(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:   zipfile.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) zipfile.c\n\nfileio_.obj:    fileio.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) fileio.c\n\nutil_.obj:      util.c $(ZIP_H)\n\t$(CC) -c $(UTILFLAGS) util.c\n\ncrc32_.obj:     crc32.c $(ZIP_H) crc32.h\n\t$(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.obj:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(CC) -c $(UTILFLAGS) crypt.c\n\nwin32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) -c $(UTILFLAGS) -I. win32/win32.c\n\nmatch32.obj:    win32/match32.asm\n\t$(AS) $(ASFLAGS) win32\\match32.asm\n\nzip.exe: $(OBJZ) $(OBJI)\n\t$(CC) -Fe $@ $(LDFLAGS) $(OBJZ) $(OBJI) $(LIBS)\n\nzipcloak.exe: $(OBJC)\n\t$(CC) -Fe $@ $(LDFLAGS) $(OBJC) $(LIBS)\n\nzipnote.exe: $(OBJN)\n\t$(CC) -Fe $@ $(LDFLAGS) $(OBJN) $(LIBS)\n\nzipsplit.exe: $(OBJS)\n\t$(CC) -Fe $@ $(LDFLAGS) $(OBJS) $(LIBS)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.lcc",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit using LCC-Win32.\n# By E-Yen Tan (3 June 1998).\n# Last updated 9 February 2008 (Christian Spieler).\n\n# This compiler evaluates #include locations relative to current working dir,\n# not relative to the location of the file containing the #include directive.\n# As a consequence, a \"-Iwin32\" option is required to allow compilation of\n# the WIN32 specific sources.\n\nCC = lcc\n# -O caused a segmentation violation with previous versions of lcc, but\n# now the optimizer seems to be fixed.\nCCFLAGS = -Zp8 -O -DWIN32\nAS = lcc\nASFLAGS =\nLD = lcclnk\nLDFLAGS = -s\n\n# Optional macros should be declared below.\n# LCC's Make will not read the LOCAL_ZIP environment variable.\nLOC = $(ASMFLG)\n\n# Options to select optimized assembler code for CRC32 calculation.\n#ifdef USEASM\nCRCA_O = crc_lcc.obj\nOBJA = lm32_lcc.obj\nASMFLG = -DASM_CRC -DASMV\n#else\n#CRCA_O =\n#OBJA =\n#ASMFLG = -DNO_ASM\n#endif\n\nCFLAGS = $(CCFLAGS) $(LOC)\n\nOBJZS = win32.obj win32zip.obj nt.obj $(OBJA)\nOBJUS = win32_.obj\n\nOBJZ1 = zip.obj zipfile.obj zipup.obj fileio.obj util.obj\nOBJZ2 = crc32.obj $(CRCA_O) globals.obj\nOBJZ3 = deflate.obj trees.obj crypt.obj ttyio.obj\nOBJZ  = $(OBJZ1) $(OBJZ2) $(OBJZ3) $(OBJZS)\n\nOBJU1 = zipfile_.obj fileio_.obj util_.obj crc32_.obj globals.obj\nOBJU  = $(OBJU1) $(OBJUS)\n\nOBJN =  zipnote.obj $(OBJU)\nOBJS =  zipsplit.obj $(OBJU)\nOBJK =  zipcloak.obj crypt_.obj ttyio.obj\nOBJC =  $(OBJK) $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\n# rules\n\n.SUFFIXES: .c .obj\n\n.c.obj:\n\t$(CC) $(CFLAGS) $<\n\n.asm.obj:\n\t$(AS) $(ASFLAGS) $<\n\nall:    zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzip.obj:      zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipfile.obj:  zipfile.c $(ZIP_H) crc32.h\nzipup.obj:    zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\nfileio.obj:   fileio.c $(ZIP_H) crc32.h\nutil.obj:     util.c $(ZIP_H)\nglobals.obj:  globals.c $(ZIP_H)\ndeflate.obj:  deflate.c $(ZIP_H)\ntrees.obj:    trees.c $(ZIP_H)\ncrc32.obj:    crc32.c $(ZIP_H) crc32.h\ncrypt.obj:    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\nttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h\n\nwin32.obj:    win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/win32.c\n\nwin32zip.obj: win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n\t$(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/win32zip.c\n\nnt.obj:       win32/nt.c $(ZIP_H) win32/nt.h\n\t$(CC) $(CFLAGS) -Iwin32 -Fo$@ win32/nt.c\n\ncrc_lcc.obj:\twin32/crc_lcc.asm\n\t$(AS) $(ASFLAGS) -Fo$@ win32/crc_lcc.asm\n\nlm32_lcc.obj:\twin32/lm32_lcc.asm\n\t$(AS) $(ASFLAGS) -Fo$@ win32/lm32_lcc.asm\n\nzipcloak.obj: zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\nzipnote.obj:  zipnote.c $(ZIP_H) revision.h\nzipsplit.obj: zipsplit.c $(ZIP_H) revision.h\n\nzipfile_.obj: zipfile.c $(ZIP_H) crc32.h\n\t$(CC) $(CFLAGS) -DUTIL -Fo$@ zipfile.c\n\nfileio_.obj:  fileio.c $(ZIP_H) crc32.h\n\t$(CC) $(CFLAGS) -DUTIL -Fo$@ fileio.c\n\nutil_.obj:    util.c $(ZIP_H)\n\t$(CC) $(CFLAGS) -DUTIL -Fo$@ util.c\n\ncrc32_.obj:   crc32.c $(ZIP_H) crc32.h\n\t$(CC) $(CFLAGS) -DUTIL -Fo$@ crc32.c\n\ncrypt_.obj:   crypt.c $(ZIP_H) crypt.h ttyio.h\n\t$(CC) $(CFLAGS) -DUTIL -Fo$@ crypt.c\n\nwin32_.obj:    win32/win32.c $(ZIP_H) win32/win32zip.h\n\t$(CC) $(CFLAGS) -DUTIL -Iwin32 -Fo$@ win32/win32.c\n\nzip.exe: $(OBJZ)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJZ)\n\nzipcloak.exe: $(OBJC)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJC)\n\nzipnote.exe: $(OBJN)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJN)\n\nzipsplit.exe: $(OBJS)\n\t$(LD) $(LDFLAGS) -o $@ $(OBJS)\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.w10",
    "content": "# WMAKE makefile for Windows 95 and Windows NT (Intel only)\n# using Watcom C/C++ v10.5+, by Paul Kienitz, last revised 22 Jun 2008.\n# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.\n#\n# Invoke from Zip source dir with \"WMAKE -F WIN32\\MAKEFILE.WAT [targets]\"\n# To build with debug info use \"WMAKE DEBUG=1 ...\"\n# To build without any assembly modules use \"WMAKE NOASM=1 ...\"\n#\n# Other options to be fed to the compiler can be specified in an environment\n# variable called LOCAL_ZIP.  One possibility \"-DDYN_ALLOC\", but currently\n# this is not supported unless NOASM is also used.\n\nvariation = $(%LOCAL_ZIP)\n\n# Stifle annoying \"Delete this file?\" questions when errors occur:\n.ERASE\n\n.EXTENSIONS:\n.EXTENSIONS: .exe .obj .c .h .asm\n\n# We maintain multiple sets of object files in different directories so that\n# we can compile msdos, dos/4gw, and win32 versions of Zip without their\n# object files interacting.  The following var must be a directory name\n# ending with a backslash.  All object file names must include this macro\n# at the beginning, for example \"$(O)foo.obj\".\n\n!ifdef DEBUG\nOBDIR = od32w\n!else\nOBDIR = ob32w\n!endif\nO = $(OBDIR)\\   # comment here so backslash won't continue the line\n\n# The assembly hot-spot code in crc_i386.asm and match32.asm is optional.\n# This section controls its usage.\n\n!ifdef NOASM\nasmob =\nasmco =\ncvars = $+$(cvars)$- -DNO_ASM   # otherwise ASM_CRC might default on!\n# \"$+$(foo)$-\" means expand foo as it has been defined up to now; normally,\n# this make defers inner expansion until the outer macro is expanded.\n!else  # !NOASM\nasmco = $(O)crc_i386.obj\nasmob = $(asmco) $(O)match32.obj\ncvars = $+$(cvars)$- -DASMV -DASM_CRC\n!endif\n\n# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for\n# ZipNote, and OBJS is for ZipSplit:\n\nOBJZ3 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)trees.obj $(O)zipup.obj\nOBJZ2 = $(OBJZ3) $(O)util.obj $(O)zipfile.obj $(O)fileio.obj $(O)deflate.obj\nOBJZ1 = $(OBJZ2) $(O)globals.obj $(O)crc32.obj $(asmob)\nOBJZ  = $(OBJZ1) $(O)win32zip.obj $(O)win32.obj $(O)win32i64.obj $(O)nt.obj\n\nOBJU1 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)crc32_.obj $(asmco)\nOBJ_U = $(OBJU1) $(O)globals.obj $(O)win32_.obj $(O)win32i64_.obj\n\nOBJC  = $(O)zipcloak.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)\n\nOBJN  = $(O)zipnote.obj $(OBJ_U)\n\nOBJS  = $(O)zipsplit.obj $(OBJ_U)\n\n# Common header files included by all C sources:\n\nZIP_H = zip.h ziperr.h tailor.h win32\\osdep.h\n\n# Now we have to pick out the proper compiler and options for it.\n\ncc     = wcc386\nlink   = wlink\nasm    = wasm\nrc     = wrc\n# Use Pentium Pro timings, register args, static strings in code:\ncflags = -bt=NT -6r -zt -zq\naflags = -bt=NT -mf -3 -zq\nrcflags= -bt=NT -DWIN32 -iwin32 -q\nlflags = sys NT\ncvars  = $+$(cvars)$- -DWIN32 $(variation)\navars  = $+$(avars)$- $(variation)\n\n# Specify optimizations, or a nonoptimized debugging version:\n\n!ifdef DEBUG\ncdebug = -od -d2\nldebug = d w all op symf\n!else\ncdebug = -s -oeilrt -zp4\n# note: -ol+ does not help.  -oa helps slightly but might be dangerous.\nldebug = op el\n!endif\n\n# How to compile sources:\n.c.obj:\n\t$(cc) $(cdebug) $(cflags) $(cvars) $< -fo=$@\n\n# Here we go!  By default, make all targets:\nall: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe\n\n# Convenient shorthand options for single targets:\nz:   Zip.exe       .SYMBOLIC\nn:   ZipNote.exe   .SYMBOLIC\nc:   ZipCloak.exe  .SYMBOLIC\ns:   ZipSplit.exe  .SYMBOLIC\n\nZip.exe:\t$(OBDIR) $(OBJZ) $(O)zip.res\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJZ)}\n\t$(rc) $(O)zip.res $@\n\nZipNote.exe:\t$(OBDIR) $(OBJN)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJN)}\n\nZipCloak.exe:\t$(OBDIR) $(OBJC)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJC)}\n\nZipSplit.exe:\t$(OBDIR) $(OBJS)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJS)}\n\n# Source dependencies:\n\n$(O)crc32.obj:    crc32.c $(ZIP_H) crc32.h      # only used if NOASM\n$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n$(O)deflate.obj:  deflate.c $(ZIP_H)\n$(O)fileio.obj:   fileio.c $(ZIP_H) crc32.h\n$(O)globals.obj:  globals.c $(ZIP_H)\n$(O)trees.obj:    trees.c $(ZIP_H)\n$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h\n$(O)util.obj:     util.c $(ZIP_H)\n$(O)zip.obj:      zip.c $(ZIP_H) crc32.h crypt.h revision.h ttyio.h\n$(O)zipfile.obj:  zipfile.c $(ZIP_H) crc32.h\n$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32\\zipup.h\n$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h\n$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h\n\n# Special case object files:\n\n$(O)win32.obj:    win32\\win32.c $(ZIP_H) win32\\win32zip.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32.c -fo=$@\n\n$(O)win32i64.obj: win32\\win32i64.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32i64.c -fo=$@\n\n$(O)win32zip.obj: win32\\win32zip.c $(ZIP_H) win32\\win32zip.h win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32zip.c -fo=$@\n\n$(O)nt.obj:       win32\\nt.c $(ZIP_H) win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\nt.c -fo=$@\n\n$(O)match32.obj:  win32\\match32.asm\n\t$(asm) $(aflags) $(avars) win32\\match32.asm -fo=$@\n\n$(O)crc_i386.obj: win32\\crc_i386.asm\n\t$(asm) $(aflags) $(avars) win32\\crc_i386.asm -fo=$@\n\n# Variant object files for ZipNote, ZipCloak, and ZipSplit:\n\n$(O)zipfile_.obj: zipfile.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@\n\n$(O)fileio_.obj:  fileio.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@\n\n$(O)util_.obj:    util.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@\n\n$(O)crc32_.obj:   crc32.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crc32.c -fo=$@\n\n$(O)crypt_.obj:   crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@\n\n$(O)win32_.obj:   win32\\win32.c $(ZIP_H) win32\\win32zip.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\\win32.c -fo=$@\n\n$(O)win32i64_.obj:   win32\\win32i64.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\\win32i64.c -fo=$@\n\n$(O)zip.res:\t  win32\\zip.rc revision.h\n\t$(rc) -r $(rcflags) -fo=$@ win32\\zip.rc\n\n# Creation of subdirectory for intermediate files\n$(OBDIR):\n\t-mkdir $@\n\n# Unwanted file removal:\n\nclean:     .SYMBOLIC\n\tdel $(O)*.obj\n\ncleaner:   clean  .SYMBOLIC\n\tdel Zip.exe\n\tdel ZipNote.exe\n\tdel ZipCloak.exe\n\tdel ZipSplit.exe\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.w32",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# 32-bit Microsoft Visual C++\n\n# To use, do \"nmake -f makefile.w32\"\n\n# Add \"NOASM=1\" to the nmake command to disable usage of assembler sources\n# if you do not have masm 6.1X.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = $(LOCAL_ZIP)\n\n!IFNDEF debug\nNODEBUG=1\n!ENDIF\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\n!IFDEF NOASM\nASMOBJS =\nCRCA_O =\nCFLG_ASM = -DNO_ASM\n!ELSE\nASMOBJS = match32.obj\nCRCA_O = crci386c.obj\nCFLG_ASM = -DASM_CRC\n!ENDIF\n\n!IFDEF USEBZ2\nLOC=$(LOC) -DBZIP2_SUPPORT\n!IFNDEF debug\nEXTLIB=$(EXTLIB) libbz2.lib\n!ELSE\nEXTLIB=$(EXTLIB) libbz2.lib\n!ENDIF\n!ENDIF\n\n!IFDEF USEZLIB\nLOC=$(LOC) -DUSE_ZLIB\nASMOBJS=\n!IFNDEF debug\nEXTLIB=$(EXTLIB) zlib.lib\n!ELSE\nEXTLIB=$(EXTLIB) zlib.lib\n!ENDIF\n!ENDIF\n\n!IFDEF USEZLIB\nUSE_MSVCRT=1\n!ELSE\n!IFDEF USEBZIP2\nUSE_MSVCRT=1\n!ELSE\nUSE_MSVCRT=0\n!ENDIF\n!ENDIF # USEZLIB\n\n!IF $(USE_MSVCRT) == 1\nCRTLIB=-MD\n!ELSE\n!IF \"$(VS80COMNTOOLS)\" == \"\"\nCRTLIB=-ML\n!ELSE\n# no single-threaded CRT static lib, only multi-threaded in VC8\nCRTLIB=-MT\n!ENDIF\n!ENDIF\n\n!IFDEF NODEBUG\ncdebug = -O2\ncdbgsz = -O1\n!ELSE\ncdebug = -Od\ncdbgsz = $(cdebug)\n!ENDIF\n\n# ------------- 32-bit Microsoft Visual C++ -------------\nCC=cl -nologo\nCFLAGS=-W3 $(cdebug) -DWIN32 $(CFLG_ASM) $(CRTLIB) $(LOC)\nUTILFLAGS=$(CFLAGS) -DUTIL -Fo$@\n\n# Remove \"-coff\" from ASFLAGS if you do not have MASM 6.11.\n\nAS=ml -nologo\nASFLAGS=-c -coff -Cx\n\nRC=rc\n\n# If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them\n# with the /KNOWEAS switch, you can build dual-mode MS-DOS/Win32 executables\n# by passing the -stub switch to the 32-bit linker to specify the 16-bit part.\n\nLD=link -nologo\nLDFLAGS=user32.lib advapi32.lib /OPT:NOWIN98 /INCREMENTAL:NO /PDB:$*.pdb $(EXTLIB)\nSYMS=/DEBUG:full /DEBUGTYPE:CV\n!IFDEF debug\nLDFLAGS=$(LDFLAGS) $(SYMS)\nCFLAGS=$(CFLAGS) /Zi\n!ELSE\nLDFLAGS=$(LDFLAGS) /RELEASE\n!IFDEF sym\nLDFLAGS=$(LDFLAGS) $(SYMS)\nCFLAGS=$(CFLAGS) /Zi\n!ENDIF\n!ENDIF\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n crc32.obj $(CRCA_O) globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj win32i64.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj crc32_.obj $(CRCA_O) globals.obj \\\n win32_.obj win32i64.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:   $(ZIPS)\n\nzip.obj:        zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:    zipfile.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\n $(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:     fileio.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\nutil.obj:       util.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:    globals.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:    deflate.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:      trees.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:      crc32.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nwin32i64.obj:   win32/win32i64.c $(ZIP_H)\n $(CC) -c $(CFLAGS) -I. win32/win32i64.c\n\nwin32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n $(CC) -c $(CFLAGS) -I. win32/win32zip.c\n\nwin32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h\n $(CC) -c $(CFLAGS) -I. win32/win32.c\n\nnt.obj:         win32/nt.c $(ZIP_H) win32/nt.h\n $(CC) -c $(CFLAGS) -I. win32/nt.c\n\nzipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:    zipnote.c $(ZIP_H) revision.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:   zipsplit.c $(ZIP_H) revision.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:   zipfile.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) zipfile.c\n\nfileio_.obj:    fileio.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) fileio.c\n\nutil_.obj:      util.c $(ZIP_H)\n $(CC) -c $(UTILFLAGS) util.c\n\ncrc32_.obj:     crc32.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.obj:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n $(CC) -c $(UTILFLAGS) crypt.c\n\nwin32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h\n $(CC) -c $(UTILFLAGS) -I. win32/win32.c\n\ncrci386c.obj:   win32/crc_i386.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) -I. -Fo$@ win32/crc_i386.c\n\ncrc_i386.obj:   win32/crc_i386.asm\n $(AS) $(ASFLAGS) win32\\crc_i386.asm\n\nmatch32.obj:    win32/match32.asm\n $(AS) $(ASFLAGS) win32\\match32.asm\n\nzip.res:        win32/zip.rc revision.h\n\t$(RC) /l 0x409 /fo$@ /i win32 /d WIN32 win32/zip.rc\n\nzip.exe: $(OBJZ) $(OBJI) zip.res\n $(LD) $(LDFLAGS) $(OBJZ) $(OBJI) zip.res\n\nzipcloak.exe: $(OBJC)\n $(LD) $(LDFLAGS) $(OBJC)\n\nzipnote.exe: $(OBJN)\n $(LD) $(LDFLAGS) $(OBJN)\n\nzipsplit.exe: $(OBJS)\n $(LD) $(LDFLAGS) $(OBJS)\n\nclean:\n -del *.obj\n -del *.exe\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makefile.wat",
    "content": "# WMAKE makefile for Windows 95 and Windows NT (Intel only)\n# using Watcom C/C++ v11.0+, by Paul Kienitz, last revised 22 Jun 2008.\n# Makes Zip.exe, ZipNote.exe, ZipCloak.exe, and ZipSplit.exe.\n#\n# Invoke from Zip source dir with \"WMAKE -F WIN32\\MAKEFILE.WAT [targets]\"\n# To build with debug info use \"WMAKE DEBUG=1 ...\"\n# To build without any assembly modules use \"WMAKE NOASM=1 ...\"\n#\n# Other options to be fed to the compiler can be specified in an environment\n# variable called LOCAL_ZIP.  One possibility \"-DDYN_ALLOC\", but currently\n# this is not supported unless NOASM is also used.\n\nvariation = $(%LOCAL_ZIP)\n\n# Stifle annoying \"Delete this file?\" questions when errors occur:\n.ERASE\n\n.EXTENSIONS:\n.EXTENSIONS: .exe .obj .c .h .asm\n\n# We maintain multiple sets of object files in different directories so that\n# we can compile msdos, dos/4gw, and win32 versions of Zip without their\n# object files interacting.  The following var must be a directory name\n# ending with a backslash.  All object file names must include this macro\n# at the beginning, for example \"$(O)foo.obj\".\n\n!ifdef DEBUG\nOBDIR = od32w\n!else\nOBDIR = ob32w\n!endif\nO = $(OBDIR)\\   # comment here so backslash won't continue the line\n\n# The assembly hot-spot code in crc_i386.asm and match32.asm is optional.\n# This section controls its usage.\n\n!ifdef NOASM\nasmob =\nasmco =\ncvars = $+$(cvars)$- -DNO_ASM   # otherwise ASM_CRC might default on!\n# \"$+$(foo)$-\" means expand foo as it has been defined up to now; normally,\n# this make defers inner expansion until the outer macro is expanded.\n!else  # !NOASM\nasmco = $(O)crc_i386.obj\nasmob = $(asmco) $(O)match32.obj\ncvars = $+$(cvars)$- -DASMV -DASM_CRC\n!endif\n\n# Our object files.  OBJZ is for Zip, OBJC is for ZipCloak, OBJN is for\n# ZipNote, and OBJS is for ZipSplit:\n\nOBJZ3 = $(O)zip.obj $(O)crypt.obj $(O)ttyio.obj $(O)trees.obj $(O)zipup.obj\nOBJZ2 = $(OBJZ3) $(O)util.obj $(O)zipfile.obj $(O)fileio.obj $(O)deflate.obj\nOBJZ1 = $(OBJZ2) $(O)globals.obj $(O)crc32.obj $(asmob)\nOBJZ  = $(OBJZ1) $(O)win32zip.obj $(O)win32.obj $(O)win32i64.obj $(O)nt.obj\n\nOBJU1 = $(O)zipfile_.obj $(O)fileio_.obj $(O)util_.obj $(O)crc32_.obj $(asmco)\nOBJ_U = $(OBJU1) $(O)globals.obj $(O)win32_.obj $(O)win32i64_.obj\n\nOBJC  = $(O)zipcloak.obj $(O)crypt_.obj $(O)ttyio.obj $(OBJ_U)\n\nOBJN  = $(O)zipnote.obj $(OBJ_U)\n\nOBJS  = $(O)zipsplit.obj $(OBJ_U)\n\n# Common header files included by all C sources:\n\nZIP_H = zip.h ziperr.h tailor.h win32\\osdep.h\n\n# Now we have to pick out the proper compiler and options for it.\n\ncc     = wcc386\nlink   = wlink\nasm    = wasm\nrc     = wrc\n# Use Pentium Pro timings, register args, static strings in code:\ncflags = -bt=NT -6r -zt -zq\naflags = -bt=NT -mf -3 -zq\nrcflags= -bt=NT -DWIN32 -iwin32 -q\nlflags = sys NT\ncvars  = $+$(cvars)$- -DWIN32 $(variation)\navars  = $+$(avars)$- -DWATCOM_DSEG $(variation)\n\n# Specify optimizations, or a nonoptimized debugging version:\n\n!ifdef DEBUG\ncdebug = -od -d2\nldebug = d w all op symf\n!else\ncdebug = -s -obhikl+rt -oe=100 -zp8\n# -oa helps slightly but might be dangerous.\nldebug = op el\n!endif\n\n# How to compile sources:\n.c.obj:\n\t$(cc) $(cdebug) $(cflags) $(cvars) $[@ -fo=$@\n\n# Here we go!  By default, make all targets:\nall: Zip.exe ZipNote.exe ZipCloak.exe ZipSplit.exe\n\n# Convenient shorthand options for single targets:\nz:   Zip.exe       .SYMBOLIC\nn:   ZipNote.exe   .SYMBOLIC\nc:   ZipCloak.exe  .SYMBOLIC\ns:   ZipSplit.exe  .SYMBOLIC\n\nZip.exe:\t$(OBDIR) $(OBJZ) $(O)zip.res\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJZ)}\n\t$(rc) $(O)zip.res $@\n\nZipNote.exe:\t$(OBDIR) $(OBJN)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJN)}\n\nZipCloak.exe:\t$(OBDIR) $(OBJC)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJC)}\n\nZipSplit.exe:\t$(OBDIR) $(OBJS)\n\t$(link) $(lflags) $(ldebug) name $@ file {$(OBJS)}\n\n# Source dependencies:\n\n$(O)crc32.obj:    crc32.c $(ZIP_H) crc32.h      # only used if NOASM\n$(O)crypt.obj:    crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n$(O)deflate.obj:  deflate.c $(ZIP_H)\n$(O)fileio.obj:   fileio.c $(ZIP_H) crc32.h\n$(O)globals.obj:  globals.c $(ZIP_H)\n$(O)trees.obj:    trees.c $(ZIP_H)\n$(O)ttyio.obj:    ttyio.c $(ZIP_H) crypt.h ttyio.h\n$(O)util.obj:     util.c $(ZIP_H)\n$(O)zip.obj:      zip.c $(ZIP_H) crc32.h crypt.h revision.h ttyio.h\n$(O)zipfile.obj:  zipfile.c $(ZIP_H) crc32.h\n$(O)zipup.obj:    zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32\\zipup.h\n$(O)zipnote.obj:  zipnote.c $(ZIP_H) revision.h\n$(O)zipcloak.obj: zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n$(O)zipsplit.obj: zipsplit.c $(ZIP_H) revision.h\n\n# Special case object files:\n\n$(O)win32.obj:    win32\\win32.c $(ZIP_H) win32\\win32zip.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32.c -fo=$@\n\n$(O)win32i64.obj: win32\\win32i64.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32i64.c -fo=$@\n\n$(O)win32zip.obj: win32\\win32zip.c $(ZIP_H) win32\\win32zip.h win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\win32zip.c -fo=$@\n\n$(O)nt.obj:       win32\\nt.c $(ZIP_H) win32\\nt.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) win32\\nt.c -fo=$@\n\n$(O)match32.obj:  win32\\match32.asm\n\t$(asm) $(aflags) $(avars) win32\\match32.asm -fo=$@\n\n$(O)crc_i386.obj: win32\\crc_i386.asm\n\t$(asm) $(aflags) $(avars) win32\\crc_i386.asm -fo=$@\n\n# Variant object files for ZipNote, ZipCloak, and ZipSplit:\n\n$(O)zipfile_.obj: zipfile.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL zipfile.c -fo=$@\n\n$(O)fileio_.obj:  fileio.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL fileio.c -fo=$@\n\n$(O)util_.obj:    util.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL util.c -fo=$@\n\n$(O)crc32_.obj:   crc32.c $(ZIP_H) crc32.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crc32.c -fo=$@\n\n$(O)crypt_.obj:   crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL crypt.c -fo=$@\n\n$(O)win32_.obj:   win32\\win32.c $(ZIP_H) win32\\win32zip.h\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\\win32.c -fo=$@\n\n$(O)win32i64_.obj:   win32\\win32i64.c $(ZIP_H)\n\t$(cc) $(cdebug) $(cflags) $(cvars) -DUTIL win32\\win32i64.c -fo=$@\n\n$(O)zip.res:\t  win32\\zip.rc revision.h\n\t$(rc) -r $(rcflags) -fo=$@ win32\\zip.rc\n\n# Creation of subdirectory for intermediate files\n$(OBDIR):\n\t-mkdir $@\n\n# Unwanted file removal:\n\nclean:     .SYMBOLIC\n\tdel $(O)*.obj\n\ncleaner:   clean  .SYMBOLIC\n\tdel Zip.exe\n\tdel ZipNote.exe\n\tdel ZipCloak.exe\n\tdel ZipSplit.exe\n"
  },
  {
    "path": "deps/infozip/zip30/win32/makenoas.w32",
    "content": "# Makefile for Zip, ZipCloak, ZipNote and ZipSplit for\n# 32-bit Microsoft Visual C++\n\n# To use, do \"nmake -f makefile.w32\"\n\n# This version disables assembly.\n# Add -DNO_ASM to CFLAGS and comment out the ASMOBJS definition if\n# you do not have masm 6.1X.\n\n# Optional nonstandard preprocessor flags (as -DMEDIUM_MEM or -DNO_ASM)\n# should be added to the environment via \"set LOCAL_ZIP=-DFOO\" or added\n# to the declaration of LOC here:\nLOC = $(LOCAL_ZIP)\n\n!IFNDEF debug\nNODEBUG=1\n!ENDIF\n\n# Uncomment the following macro to use the optimized assembler\n# routines in Zip:\n#ASMOBJS = match32.obj\nCRCA_O = crci386c.obj\nCFLG_ASM = -DASM_CRC\n\n!IFDEF USEBZ2\nLOC=$(LOC) -DBZIP2_SUPPORT\n!IFNDEF debug\nEXTLIB=$(EXTLIB) libbz2.lib\n!ELSE\nEXTLIB=$(EXTLIB) libbz2.lib\n!ENDIF\n!ENDIF\n\n!IFDEF USEZLIB\nLOC=$(LOC) -DUSE_ZLIB\nASMOBJS=\n!IFNDEF debug\nEXTLIB=$(EXTLIB) zlib.lib\n!ELSE\nEXTLIB=$(EXTLIB) zlib.lib\n!ENDIF\n!ENDIF\n\n!IFDEF USEZLIB\nUSE_MSVCRT=1\n!ELSE\n!IFDEF USEBZIP2\nUSE_MSVCRT=1\n!ELSE\nUSE_MSVCRT=0\n!ENDIF\n!ENDIF # USEZLIB\n\n!IF $(USE_MSVCRT) == 1\nCRTLIB=-MD\n!ELSE\n!IF \"$(VS80COMNTOOLS)\" == \"\"\nCRTLIB=-ML\n!ELSE\n# no single-threaded CRT static lib, only multi-threaded in VC8\nCRTLIB=-MT\n!ENDIF\n!ENDIF\n\n!IFDEF NODEBUG\ncdebug = -O2\ncdbgsz = -O1\n!ELSE\ncdebug = -Od\ncdbgsz = $(cdebug)\n!ENDIF\n\n# ------------- 32-bit Microsoft Visual C++ -------------\nCC=cl -nologo\nCFLAGS=-W3 $(cdebug) -DWIN32 $(CFLG_ASM) $(CRTLIB) $(LOC) -DNO_ASM\nUTILFLAGS=$(CFLAGS) -DUTIL -Fo$@\n\n# Remove \"-coff\" from ASFLAGS if you do not have MASM 6.11.\n\nAS=ml -nologo\nASFLAGS=-c -coff -Cx\n\nRC=rc\n\n# If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them\n# with the /KNOWEAS switch, you can build dual-mode MS-DOS/Win32 executables\n# by passing the -stub switch to the 32-bit linker to specify the 16-bit part.\n\nLD=link -nologo\nLDFLAGS=user32.lib advapi32.lib /OPT:NOWIN98 /INCREMENTAL:NO /PDB:$*.pdb $(EXTLIB)\nSYMS=/DEBUG:full /DEBUGTYPE:CV\n!IFDEF debug\nLDFLAGS=$(LDFLAGS) $(SYMS)\nCFLAGS=$(CFLAGS) /Zi\n!ELSE\nLDFLAGS=$(LDFLAGS) /RELEASE\n!IFDEF sym\nLDFLAGS=$(LDFLAGS) $(SYMS)\nCFLAGS=$(CFLAGS) /Zi\n!ENDIF\n!ENDIF\n\n# variables\nOBJZ = zip.obj crypt.obj ttyio.obj zipfile.obj zipup.obj fileio.obj util.obj \\\n crc32.obj $(CRCA_O) globals.obj\n\nOBJI = deflate.obj trees.obj $(ASMOBJS) win32.obj win32zip.obj nt.obj win32i64.obj\n\nOBJU = zipfile_.obj fileio_.obj util_.obj crc32_.obj $(CRCA_O) globals.obj \\\n win32_.obj win32i64.obj\nOBJN = zipnote.obj $(OBJU)\nOBJC = zipcloak.obj crypt_.obj ttyio.obj $(OBJU)\nOBJS = zipsplit.obj $(OBJU)\n\nZIP_H = zip.h ziperr.h tailor.h win32/osdep.h\n\nZIPS = zip.exe zipnote.exe zipsplit.exe zipcloak.exe\n\nzips:   $(ZIPS)\n\nzip.obj:        zip.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipfile.obj:    zipfile.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipup.obj:      zipup.c $(ZIP_H) revision.h crc32.h crypt.h win32/zipup.h\n $(CC) -c $(CFLAGS) $*.c\n\nfileio.obj:     fileio.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\nutil.obj:       util.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\nglobals.obj:    globals.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ndeflate.obj:    deflate.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ntrees.obj:      trees.c $(ZIP_H)\n $(CC) -c $(CFLAGS) $*.c\n\ncrc32.obj:      crc32.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) $*.c\n\ncrypt.obj:      crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nttyio.obj:      ttyio.c $(ZIP_H) crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nwin32i64.obj:   win32/win32i64.c $(ZIP_H)\n $(CC) -c $(CFLAGS) -I. win32/win32i64.c\n\nwin32zip.obj:   win32/win32zip.c $(ZIP_H) win32/win32zip.h win32/nt.h\n $(CC) -c $(CFLAGS) -I. win32/win32zip.c\n\nwin32.obj:      win32/win32.c $(ZIP_H) win32/win32zip.h\n $(CC) -c $(CFLAGS) -I. win32/win32.c\n\nnt.obj:         win32/nt.c $(ZIP_H) win32/nt.h\n $(CC) -c $(CFLAGS) -I. win32/nt.c\n\nzipcloak.obj:   zipcloak.c $(ZIP_H) revision.h crc32.h crypt.h ttyio.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipnote.obj:    zipnote.c $(ZIP_H) revision.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipsplit.obj:   zipsplit.c $(ZIP_H) revision.h\n $(CC) -c $(CFLAGS) $*.c\n\nzipfile_.obj:   zipfile.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) zipfile.c\n\nfileio_.obj:    fileio.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) fileio.c\n\nutil_.obj:      util.c $(ZIP_H)\n $(CC) -c $(UTILFLAGS) util.c\n\ncrc32_.obj:     crc32.c $(ZIP_H) crc32.h\n $(CC) -c $(UTILFLAGS) crc32.c\n\ncrypt_.obj:     crypt.c $(ZIP_H) crypt.h crc32.h ttyio.h\n $(CC) -c $(UTILFLAGS) crypt.c\n\nwin32_.obj:     win32/win32.c $(ZIP_H) win32/win32zip.h\n $(CC) -c $(UTILFLAGS) -I. win32/win32.c\n\ncrci386c.obj:   win32/crc_i386.c $(ZIP_H) crc32.h\n $(CC) -c $(CFLAGS) -I. -Fo$@ win32/crc_i386.c\n\ncrc_i386.obj:   win32/crc_i386.asm\n $(AS) $(ASFLAGS) win32\\crc_i386.asm\n\nmatch32.obj:    win32/match32.asm\n $(AS) $(ASFLAGS) win32\\match32.asm\n\nzip.res:        win32/zip.rc revision.h\n\t$(RC) /l 0x409 /fo$@ /i win32 /d WIN32 win32/zip.rc\n\nzip.exe: $(OBJZ) $(OBJI) zip.res\n $(LD) $(LDFLAGS) $(OBJZ) $(OBJI) zip.res\n\nzipcloak.exe: $(OBJC)\n $(LD) $(LDFLAGS) $(OBJC)\n\nzipnote.exe: $(OBJN)\n $(LD) $(LDFLAGS) $(OBJN)\n\nzipsplit.exe: $(OBJS)\n $(LD) $(LDFLAGS) $(OBJS)\n\nclean:\n -del *.obj\n -del *.exe\n"
  },
  {
    "path": "deps/infozip/zip30/win32/match32.asm",
    "content": ";===========================================================================\n; Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.\n;\n; See the accompanying file LICENSE, version 2005-Feb-10 or later\n; (the contents of which are also included in zip.h) for terms of use.\n; If, for some reason, all these files are missing, the Info-ZIP license\n; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n;===========================================================================\n;\n; match32.asm by Jean-loup Gailly.\n\n; match32.asm, optimized version of longest_match() in deflate.c\n; To be used only with 32 bit flat model. To simplify the code, the option\n; -DDYN_ALLOC is not supported.\n; This file is only optional. If you don't have an assembler, use the\n; C version (add -DNO_ASM to CFLAGS in makefile and remove match.o\n; from OBJI). If you have reduced WSIZE in zip.h, then make sure this is\n; assembled with an equivalent -DWSIZE=<whatever>.\n;\n; Win32 (Windows NT) version - 1994/04/13 by Steve Salisbury\n; * works with Microsoft MASM 6.1X and Microsoft Visual C++ / 32-bit edition\n;\n; Adapted to work with Borland Turbo Assembler 5.0 by Cosmin Truta, 1997\n;\n; Adapted to work with OpenWatcom WASM by Chr. Spieler, 2005\n; (Define the symbol WATCOM_DSEG to activate the specific Watcom C\n; data segment naming convention.)\n;\n;==============================================================================\n;\n; Do NOT assemble this source if external crc32 routine from zlib gets used.\n;\n    IFNDEF USE_ZLIB\n;\n        .386p\n    ifdef ASM_NEW\n        .MODEL  FLAT\n    endif\n\n        name    match\n\n    ifdef ASM_NEW\n_BSS    segment public use32\n    else\n_BSS    segment public use32 'DATA'\n    endif\n        extrn   _match_start  : dword\n        extrn   _prev_length  : dword\n        extrn   _good_match   : dword\n    ifndef FULL_SEARCH\n        extrn   _nice_match   : dword\n    endif\n        extrn   _strstart     : dword\n        extrn   _max_chain_length : dword\n        extrn   _prev         : word\n        extrn   _window       : byte\n_BSS    ends\n\n   ifdef WATCOM_DSEG\nDGROUP  group   _BSS\n   endif\n\n   ifdef ASM_NEW\n_TEXT   segment public use32\n   else\n_TEXT   segment para public use32 'CODE'\n   endif\n        assume CS: _TEXT\n        assume DS: _BSS, ES: _BSS, FS: _BSS\n        public  _match_init\n        public  _longest_match\n\n    ifndef      WSIZE\n        WSIZE         equ 32768         ; keep in sync with zip.h !\n    endif\n        MIN_MATCH     equ 3\n        MAX_MATCH     equ 258\n        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)\n        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)\n\n; initialize or check the variables used in match.asm.\n\n_match_init proc near\n        ret\n_match_init endp\n\n; -----------------------------------------------------------------------\n; Set match_start to the longest match starting at the given string and\n; return its length. Matches shorter or equal to prev_length are discarded,\n; in which case the result is equal to prev_length and match_start is\n; garbage.\n; IN assertions: cur_match is the head of the hash chain for the current\n;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1\n\n; int longest_match(cur_match)\n\n_longest_match proc near\n\n        cur_match    equ dword ptr [esp+20]\n        ; return address                ; esp+16\n        push    ebp                     ; esp+12\n        push    edi                     ; esp+8\n        push    esi                     ; esp+4\n        push    ebx                     ; esp\n\n;       match        equ esi\n;       scan         equ edi\n;       chain_length equ ebp\n;       best_len     equ ebx\n;       limit        equ edx\n\n        mov     esi,cur_match\n        mov     edx,_strstart\n        mov     ebp,_max_chain_length   ; chain_length = max_chain_length\n        mov     edi,edx\n        sub     edx,MAX_DIST            ; limit = strstart-MAX_DIST\n        cld                             ; string ops increment esi and edi\n        jae     short limit_ok\n        sub     edx,edx                 ; limit = NIL\nlimit_ok:\n        add     edi,2+offset _window    ; edi = offset(window + strstart + 2)\n        mov     ebx,_prev_length        ; best_len = prev_length\n        mov     cx,[edi-2]              ; cx = scan[0..1]\n        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]\n        cmp     ebx,_good_match         ; do we have a good match already?\n        jb      short do_scan\n        shr     ebp,2                   ; chain_length >>= 2\n        jmp     short do_scan\n\n        align   4                       ; align destination of branch\nlong_loop:\n; at this point, edi == scan+2, esi == cur_match\n        mov     ax,[ebx+edi-3]          ; ax = scan[best_len-1..best_len]\n        mov     cx,[edi-2]              ; cx = scan[0..1]\nshort_loop:\n; at this point, edi == scan+2, esi == cur_match,\n; ax = scan[best_len-1..best_len] and cx = scan[0..1]\n        and     esi,WSIZE-1\n        dec     ebp                     ; --chain_length\n        mov     si,_prev[esi+esi]       ; cur_match = prev[cur_match]\n                                        ; top word of esi is still 0\n        jz      short the_end\n        cmp     esi,edx                 ; cur_match <= limit ?\n        jbe     short the_end\ndo_scan:\n        cmp     ax,word ptr _window[ebx+esi-1]   ; check match at best_len-1\n        jne     short_loop\n        cmp     cx,word ptr _window[esi]         ; check min_match_length match\n        jne     short_loop\n\n        lea     esi,_window[esi+2]      ; esi = match\n        mov     ecx,(MAX_MATCH-2)/2     ; scan for at most MAX_MATCH bytes\n        mov     eax,edi                 ; eax = scan+2\n        repe    cmpsw                   ; loop until mismatch\n        je      short maxmatch          ; match of length MAX_MATCH?\nmismatch:\n        mov     cl,[edi-2]              ; mismatch on first or second byte?\n        xchg    eax,edi                 ; edi = scan+2, eax = end of scan\n        sub     cl,[esi-2]              ; cl = 0 if first bytes equal\n        sub     eax,edi                 ; eax = len\n        sub     esi,2+offset _window    ; esi = match - (2 + offset(window))\n        sub     esi,eax                 ; esi = cur_match (= match - len)\n        sub     cl,1                    ; set carry if cl == 0 (can't use DEC)\n        adc     eax,0                   ; eax = carry ? len+1 : len\n        cmp     eax,ebx                 ; len > best_len ?\n        jle     long_loop\n        mov     _match_start,esi        ; match_start = cur_match\n        mov     ebx,eax                 ; ebx = best_len = len\n    ifdef FULL_SEARCH\n        cmp     eax,MAX_MATCH           ; len >= MAX_MATCH ?\n    else\n        cmp     eax,_nice_match         ; len >= nice_match ?\n    endif\n        jl      long_loop\nthe_end:\n        mov     eax,ebx                 ; result = eax = best_len\n        pop     ebx\n        pop     esi\n        pop     edi\n        pop     ebp\n        ret\nmaxmatch:                               ; come here if maximum match\n        cmpsb                           ; increment esi and edi\n        jmp     mismatch                ; force match_length = MAX_LENGTH\n\n_longest_match endp\n\n_TEXT   ends\n;\n    ENDIF ; !USE_ZLIB\n;\nend\n"
  },
  {
    "path": "deps/infozip/zip30/win32/nt.c",
    "content": "/*\n  win32/nt.c - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*++\n\nCopyright (c) 1996  Scott Field\n\nModule Name:\n\n    nt.c (formerly nt_zip.c)\n\nAbstract:\n\n    This module implements WinNT security descriptor operations for the\n    Win32 Info-ZIP project.  Operation such as querying file security,\n    using/querying local and remote privileges.  The contents of this module\n    are only relevant when the code is running on Windows NT, and the target\n    volume supports persistent Acl storage.\n\n    User privileges that allow accessing certain privileged aspects of the\n    security descriptor (such as the Sacl) are only used if the user specified\n    to do so.\n\n    In the future, this module may be expanded to support storage of\n    OS/2 EA data, Macintosh resource forks, and hard links, which are all\n    supported by NTFS.\n\nAuthor:\n\n    Scott Field (sfield@microsoft.com)  27-Sep-96\n\n--*/\n\n#include \"../zip.h\"\n\n#define WIN32_LEAN_AND_MEAN\n#ifdef CR\n#undef CR\n#endif\n#include <windows.h>\n#ifdef __RSXNT__\n#  include \"../win32/rsxntwin.h\"\n#endif\n#include \"../win32/nt.h\"\n\n#ifdef NTSD_EAS         /* This file is only needed for NTSD handling */\n\n/* Borland C++ does not define FILE_SHARE_DELETE. Others also? */\n#ifndef FILE_SHARE_DELETE\n#  define FILE_SHARE_DELETE 0x00000004\n#endif\n\n/* This macro definition is missing in old versions of MS' winbase.h. */\n#ifndef InterlockedExchangePointer\n#  define InterlockedExchangePointer(Target, Value) \\\n      (PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))\n#endif\n\n/* private prototypes */\n\nstatic BOOL Initialize(VOID);\n#if 0   /* currently unused */\nstatic BOOL Shutdown(VOID);\n#endif\nstatic VOID GetRemotePrivilegesGet(CHAR *FileName, PDWORD dwRemotePrivileges);\nstatic VOID InitLocalPrivileges(VOID);\n\n\nBOOL bZipInitialized = FALSE;  /* module level stuff initialized? */\nHANDLE hZipInitMutex = NULL;   /* prevent multiple initialization */\n\nBOOL g_bBackupPrivilege = FALSE;    /* for local get file security override */\nBOOL g_bZipSaclPrivilege = FALSE;      /* for local get sacl operations, only when\n                                       backup privilege not present */\n\n/* our single cached volume capabilities structure that describes the last\n   volume root we encountered.  A single entry like this works well in the\n   zip/unzip scenario for a number of reasons:\n   1. typically one extraction path during unzip.\n   2. typically process one volume at a time during zip, and then move\n      on to the next.\n   3. no cleanup code required and no memory leaks.\n   4. simple code.\n\n   This approach should be reworked to a linked list approach if we expect to\n   be called by many threads which are processing a variety of input/output\n   volumes, since lock contention and stale data may become a bottleneck. */\n\nVOLUMECAPS g_VolumeCaps;\nCRITICAL_SECTION VolumeCapsLock;\n\n\nstatic BOOL Initialize(VOID)\n{\n    HANDLE hMutex;\n    HANDLE hOldMutex;\n\n    if(bZipInitialized) return TRUE;\n\n    hMutex = CreateMutex(NULL, TRUE, NULL);\n    if(hMutex == NULL) return FALSE;\n\n    hOldMutex = (HANDLE)InterlockedExchangePointer((void *)&hZipInitMutex,\n                                                   hMutex);\n\n    if(hOldMutex != NULL) {\n        /* somebody setup the mutex already */\n        InterlockedExchangePointer((void *)&hZipInitMutex,\n                                   hOldMutex);\n\n        CloseHandle(hMutex); /* close new, un-needed mutex */\n\n        /* wait for initialization to complete and return status */\n        WaitForSingleObject(hOldMutex, INFINITE);\n        ReleaseMutex(hOldMutex);\n\n        return bZipInitialized;\n    }\n\n    /* initialize module level resources */\n\n    InitializeCriticalSection( &VolumeCapsLock );\n    memset(&g_VolumeCaps, 0, sizeof(VOLUMECAPS));\n\n    InitLocalPrivileges();\n\n    bZipInitialized = TRUE;\n\n    ReleaseMutex(hMutex); /* release correct mutex */\n\n    return TRUE;\n}\n\n#if 0   /* currently not used ! */\nstatic BOOL Shutdown(VOID)\n{\n    /* really need to free critical sections, disable enabled privilges, etc,\n       but doing so brings up possibility of race conditions if those resources\n       are about to be used.  The easiest way to handle this is let these\n       resources be freed when the process terminates... */\n\n    return TRUE;\n}\n#endif /* never */\n\n\nstatic VOID GetRemotePrivilegesGet(char *FileName, PDWORD dwRemotePrivileges)\n{\n    HANDLE hFile;\n\n    *dwRemotePrivileges = 0;\n\n    /* see if we have the SeBackupPrivilege */\n\n    hFile = CreateFileA(\n        FileName,\n        ACCESS_SYSTEM_SECURITY | GENERIC_READ | READ_CONTROL,\n        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n        NULL,\n        OPEN_EXISTING,\n        FILE_FLAG_BACKUP_SEMANTICS,\n        NULL\n        );\n\n    if(hFile != INVALID_HANDLE_VALUE) {\n        /* no remote way to determine SeBackupPrivilege -- just try a read\n           to simulate it */\n        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;\n        PSECURITY_DESCRIPTOR sd;\n        DWORD cbBuf = 0;\n\n        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);\n\n        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {\n            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {\n                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {\n                    *dwRemotePrivileges |= OVERRIDE_BACKUP;\n                }\n                HeapFree(GetProcessHeap(), 0, sd);\n            }\n        }\n\n        CloseHandle(hFile);\n    } else {\n\n        /* see if we have the SeSecurityPrivilege */\n        /* note we don't need this if we have SeBackupPrivilege */\n\n        hFile = CreateFileA(\n            FileName,\n            ACCESS_SYSTEM_SECURITY,\n            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */\n            NULL,\n            OPEN_EXISTING,\n            0,\n            NULL\n            );\n\n        if(hFile != INVALID_HANDLE_VALUE) {\n            CloseHandle(hFile);\n            *dwRemotePrivileges |= OVERRIDE_SACL;\n        }\n    }\n}\n\n\nBOOL ZipGetVolumeCaps(\n    char *rootpath,         /* filepath, or NULL */\n    char *name,             /* filename associated with rootpath */\n    PVOLUMECAPS VolumeCaps  /* result structure describing capabilities */\n    )\n{\n    char TempRootPath[MAX_PATH + 1];\n    DWORD cchTempRootPath = 0;\n    BOOL bSuccess = TRUE;   /* assume success until told otherwise */\n\n    if(!bZipInitialized) if(!Initialize()) return FALSE;\n\n    /* process the input path to produce a consistent path suitable for\n       compare operations and also suitable for certain picky Win32 API\n       that don't like forward slashes */\n\n    if(rootpath != NULL && rootpath[0] != '\\0') {\n        DWORD i;\n\n        cchTempRootPath = lstrlen(rootpath);\n        if(cchTempRootPath > MAX_PATH) return FALSE;\n\n        /* copy input, converting forward slashes to back slashes as we go */\n\n        for(i = 0 ; i <= cchTempRootPath ; i++) {\n            if(rootpath[i] == '/') TempRootPath[i] = '\\\\';\n            else TempRootPath[i] = rootpath[i];\n        }\n\n        /* check for UNC and Null terminate or append trailing \\ as appropriate */\n\n        /* possible valid UNCs we are passed follow:\n           \\\\machine\\foo\\bar (path is \\\\machine\\foo\\)\n           \\\\machine\\foo     (path is \\\\machine\\foo\\)\n           \\\\machine\\foo\\\n           \\\\.\\c$\\           (FIXFIX: Win32API doesn't like this - GetComputerName())\n           LATERLATER: handling mounted DFS drives in the future will require\n                       slightly different logic which isn't available today.\n                       This is required because directories can point at\n                       different servers which have differing capabilities.\n         */\n\n        if(TempRootPath[0] == '\\\\' && TempRootPath[1] == '\\\\') {\n            DWORD slash = 0;\n\n            for(i = 2 ; i < cchTempRootPath ; i++) {\n                if(TempRootPath[i] == '\\\\') {\n                    slash++;\n\n                    if(slash == 2) {\n                        i++;\n                        TempRootPath[i] = '\\0';\n                        cchTempRootPath = i;\n                        break;\n                    }\n                }\n            }\n\n            /* if there was only one slash found, just tack another onto the end */\n\n            if(slash == 1 && TempRootPath[cchTempRootPath] != '\\\\') {\n                TempRootPath[cchTempRootPath] = TempRootPath[0]; /* '\\' */\n                TempRootPath[cchTempRootPath+1] = '\\0';\n                cchTempRootPath++;\n            }\n\n        } else {\n\n            if(TempRootPath[1] == ':') {\n\n                /* drive letter specified, truncate to root */\n                TempRootPath[2] = '\\\\';\n                TempRootPath[3] = '\\0';\n                cchTempRootPath = 3;\n            } else {\n\n                /* must be file on current drive */\n                TempRootPath[0] = '\\0';\n                cchTempRootPath = 0;\n            }\n\n        }\n\n    } /* if path != NULL */\n\n    /* grab lock protecting cached entry */\n    EnterCriticalSection( &VolumeCapsLock );\n\n    if(!g_VolumeCaps.bValid || lstrcmpi(g_VolumeCaps.RootPath, TempRootPath) != 0) {\n\n        /* no match found, build up new entry */\n\n        DWORD dwFileSystemFlags;\n        DWORD dwRemotePrivileges = 0;\n        BOOL bRemote = FALSE;\n\n        /* release lock during expensive operations */\n        LeaveCriticalSection( &VolumeCapsLock );\n\n        bSuccess = GetVolumeInformation(\n            (TempRootPath[0] == '\\0') ? NULL : TempRootPath,\n            NULL, 0,\n            NULL, NULL,\n            &dwFileSystemFlags,\n            NULL, 0);\n\n        /* only if target volume supports Acls, and we were told to use\n           privileges do we need to go out and test for the remote case */\n\n        if(bSuccess && (dwFileSystemFlags & FS_PERSISTENT_ACLS) && VolumeCaps->bUsePrivileges) {\n            if(GetDriveType( (TempRootPath[0] == '\\0') ? NULL : TempRootPath ) == DRIVE_REMOTE) {\n                bRemote = TRUE;\n\n                /* make a determination about our remote capabilities */\n\n                GetRemotePrivilegesGet(name, &dwRemotePrivileges);\n            }\n        }\n\n        /* always take the lock again, since we release it below */\n        EnterCriticalSection( &VolumeCapsLock );\n\n        /* replace the existing data if successful */\n        if(bSuccess) {\n\n            lstrcpynA(g_VolumeCaps.RootPath, TempRootPath, cchTempRootPath+1);\n            g_VolumeCaps.bProcessDefer = FALSE;\n            g_VolumeCaps.dwFileSystemFlags = dwFileSystemFlags;\n            g_VolumeCaps.bRemote = bRemote;\n            g_VolumeCaps.dwRemotePrivileges = dwRemotePrivileges;\n            g_VolumeCaps.bValid = TRUE;\n        }\n    }\n\n    if(bSuccess) {\n        /* copy input elements */\n        g_VolumeCaps.bUsePrivileges = VolumeCaps->bUsePrivileges;\n        g_VolumeCaps.dwFileAttributes = VolumeCaps->dwFileAttributes;\n\n        /* give caller results */\n        memcpy(VolumeCaps, &g_VolumeCaps, sizeof(VOLUMECAPS));\n    } else {\n        g_VolumeCaps.bValid = FALSE;\n    }\n\n    LeaveCriticalSection( &VolumeCapsLock ); /* release lock */\n\n    return bSuccess;\n}\n\nBOOL SecurityGet(\n    char *resource,\n    PVOLUMECAPS VolumeCaps,\n    unsigned char *buffer,\n    DWORD *cbBuffer\n    )\n{\n    HANDLE hFile;\n    DWORD dwDesiredAccess;\n    DWORD dwFlags;\n    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)buffer;\n    SECURITY_INFORMATION RequestedInfo;\n    BOOL bBackupPrivilege = FALSE;\n    BOOL bSaclPrivilege = FALSE;\n    BOOL bSuccess = FALSE;\n\n    DWORD cchResourceLen;\n\n    if(!bZipInitialized) if(!Initialize()) return FALSE;\n\n    /* see if we are dealing with a directory */\n    /* rely on the fact resource has a trailing [back]slash, rather\n       than calling expensive GetFileAttributes() */\n\n    cchResourceLen = lstrlenA(resource);\n\n    if(resource[cchResourceLen-1] == '/' || resource[cchResourceLen-1] == '\\\\')\n        VolumeCaps->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;\n\n    /* setup privilege usage based on if told we can use privileges, and if so,\n       what privileges we have */\n\n    if(VolumeCaps->bUsePrivileges) {\n        if(VolumeCaps->bRemote) {\n            /* use remotely determined privileges */\n            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_BACKUP)\n                bBackupPrivilege = TRUE;\n\n            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)\n                bSaclPrivilege = TRUE;\n        } else {\n            /* use local privileges */\n            bBackupPrivilege = g_bBackupPrivilege;\n            bSaclPrivilege = g_bZipSaclPrivilege;\n        }\n    }\n\n    /* always try to read the basic security information:  Dacl, Owner, Group */\n\n    dwDesiredAccess = READ_CONTROL;\n\n    RequestedInfo = OWNER_SECURITY_INFORMATION |\n                    GROUP_SECURITY_INFORMATION |\n                    DACL_SECURITY_INFORMATION;\n\n    /* if we have the SeBackupPrivilege or SeSystemSecurityPrivilege, read\n       the Sacl, too */\n\n    if(bBackupPrivilege || bSaclPrivilege) {\n        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;\n        RequestedInfo |= SACL_SECURITY_INFORMATION;\n    }\n\n    dwFlags = 0;\n\n    /* if we have the backup privilege, specify that */\n    /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */\n\n    if(bBackupPrivilege || (VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\n        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;\n\n    hFile = CreateFileA(\n        resource,\n        dwDesiredAccess,\n        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */\n        NULL,\n        OPEN_EXISTING,\n        dwFlags,\n        NULL\n        );\n\n    if(hFile == INVALID_HANDLE_VALUE) return FALSE;\n\n    if(GetKernelObjectSecurity(hFile, RequestedInfo, sd, *cbBuffer, cbBuffer)) {\n        *cbBuffer = GetSecurityDescriptorLength( sd );\n        bSuccess = TRUE;\n    }\n\n    CloseHandle(hFile);\n\n    return bSuccess;\n}\n\nstatic VOID InitLocalPrivileges(VOID)\n{\n    HANDLE hToken;\n    TOKEN_PRIVILEGES tp;\n\n    /* try to enable some interesting privileges that give us the ability\n       to get some security information that we normally cannot.\n\n       note that enabling privileges is only relevant on the local machine;\n       when accessing files that are on a remote machine, any privileges\n       that are present on the remote machine get enabled by default. */\n\n    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))\n        return;\n\n    tp.PrivilegeCount = 1;\n    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\n\n    /* try to enable SeBackupPrivilege.\n       if this succeeds, we can read all aspects of the security descriptor */\n\n    if(LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tp.Privileges[0].Luid)) {\n        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&\n           GetLastError() == ERROR_SUCCESS) g_bBackupPrivilege = TRUE;\n    }\n\n    /* try to enable SeSystemSecurityPrivilege if SeBackupPrivilege not present.\n       if this succeeds, we can read the Sacl */\n\n    if(!g_bBackupPrivilege &&\n        LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid)) {\n\n        if(AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL) &&\n           GetLastError() == ERROR_SUCCESS) g_bZipSaclPrivilege = TRUE;\n    }\n\n    CloseHandle(hToken);\n}\n#endif /* NTSD_EAS */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/nt.h",
    "content": "/*\n  win32/nt.h - Zip 3\n\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _NT_ZIP_H\n#define _NT_ZIP_H\n\n/* central header for EF_NTSD \"SD\" extra field */\n\n#define EF_NTSD_MAX_VER_SUPPORT (0)\n                        /* describes maximum ver# we know how to handle */\n\ntypedef struct\n{\n  USHORT nID;\n  USHORT nSize;\n  ULONG lSize;\n}\nEF_NTSD_C_HEADER, *PEF_NTSD_C_HEADER;\n\n#define EF_NTSD_C_LEN (sizeof(EF_NTSD_C_HEADER))\n\n/* local header for EF_NTSD \"SD\" extra field */\n\n#pragma pack(1) /* bytes following structure immediately follow BYTE Version */\n\ntypedef struct\n{\n  USHORT nID;   /* tag for this extra block type */\n  USHORT nSize; /* total data size for this block */\n  ULONG lSize;  /* uncompressed security descriptor data size */\n  BYTE Version; /* Version of uncompressed security descriptor data format */\n}\nIZ_PACKED EF_NTSD_L_HEADER, *PEF_NTSD_L_HEADER;\n\n#pragma pack()\n\n/*  ...followed by... */\n/*  SHORT CType;  compression type */\n/*  ULONG EACRC;  CRC value for uncompressed security descriptor data */\n/*  <var.> Variable length data */\n\n\n#define EF_NTSD_L_LEN (EF_NTSD_C_LEN + sizeof(BYTE))\n                                /* avoid alignment size computation */\n\n#define NTSD_BUFFERSIZE (1024)  /* threshold to cause malloc() */\n\n#define OVERRIDE_BACKUP     1   /* we have SeBackupPrivilege on remote */\n#define OVERRIDE_RESTORE    2   /* we have SeRestorePrivilege on remote */\n#define OVERRIDE_SACL       4   /* we have SeSystemSecurityPrivilege on remote */\n\ntypedef struct {\n    BOOL bValid;                /* are our contents valid? */\n    BOOL bProcessDefer;         /* process deferred entry yet? */\n    BOOL bUsePrivileges;        /* use privilege overrides? */\n    DWORD dwFileSystemFlags;    /* describes target file system */\n    BOOL bRemote;               /* is volume remote? */\n    DWORD dwRemotePrivileges;   /* relevant only on remote volumes */\n    DWORD dwFileAttributes;\n    char RootPath[MAX_PATH+1];  /* path to network / filesystem */\n} VOLUMECAPS, *PVOLUMECAPS, *LPVOLUMECAPS;\n\nBOOL SecurityGet(char *resource, PVOLUMECAPS VolumeCaps, unsigned char *buffer,\n                 DWORD *cbBuffer);\nBOOL ZipGetVolumeCaps(char *rootpath, char *name, PVOLUMECAPS VolumeCaps);\n\n#endif /* _NT_ZIP_H */\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/osdep.h",
    "content": "/*\n  win32/osdep.h\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/* Automatic setting of the common Microsoft C idenfifier MSC.\n * NOTE: Watcom also defines M_I*86 !\n */\n#if defined(_MSC_VER) || (defined(M_I86) && !defined(__WATCOMC__))\n#  ifndef MSC\n#    define MSC                 /* This should work for older MSC, too!  */\n#  endif\n#endif\n\n/* Tell Microsoft Visual C++ 2005 to leave us alone and\n * let us use standard C functions the way we're supposed to.\n */\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#  ifndef _CRT_SECURE_NO_DEPRECATE\n#    define _CRT_SECURE_NO_DEPRECATE\n#  endif\n#  ifndef _CRT_NONSTDC_NO_DEPRECATE\n#    define _CRT_NONSTDC_NO_DEPRECATE\n#  endif\n#endif\n\n#if defined(__WATCOMC__) && defined(__386__)\n#  define WATCOMC_386\n#endif\n\n#if (defined(__CYGWIN32__) && !defined(__CYGWIN__))\n#  define __CYGWIN__            /* compatibility for CygWin B19 and older */\n#endif\n\n/* enable multibyte character set support by default */\n#ifndef _MBCS\n#  define _MBCS\n#endif\n#if defined(__CYGWIN__)\n#  undef _MBCS\n#endif\n\n/* Get types and stat */\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <io.h>\n\n#ifndef MSDOS\n/*\n * Windows 95 (and Windows NT) file systems are (to some extend)\n * extensions of MSDOS. Common features include for example:\n *      FAT or (FAT like) file systems,\n *      '\\\\' as directory separator in paths,\n *      \"\\r\\n\" as record (line) terminator in text files, ...\n */\n#  define MSDOS\n/* inherit MS-DOS file system etc. stuff */\n#endif\n\n#define USE_CASE_MAP\n#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \\\n                     procname(n, filter_match_case))\n#define BROKEN_FSEEK\n#ifndef __RSXNT__\n#  define HAVE_FSEEKABLE\n#endif\n\n\n/* popen\n *\n * On Win32 must map to _popen() and _pclose()\n */\n#define popen _popen\n#define pclose _pclose\n\n/* WIN32_OEM\n *\n * This enables storing paths in archives on WIN32 in OEM format\n * which is more work but seems the standard now.  It also enables\n * converting paths in read DOS archives from assumed OEM to ANSI.\n */\n#ifndef NO_WIN32_OEM\n#  define WIN32_OEM\n#endif\n\n/* Large File Support\n *\n *  If this is set it is assumed that the port\n *  supports 64-bit file calls.  The types are\n *  defined here.  Any local implementations are\n *  in Win32.c and the prototypes for the calls are\n *  in tailor.h.  Note that a port must support\n *  these calls fully or should not set\n *  LARGE_FILE_SUPPORT.\n */\n\n/* Note also that ZOFF_T_FORMAT_SIZE_PREFIX has to be defined here\n   or tailor.h will define defaults */\n\n/* If port has LARGE_FILE_SUPPORT then define here\n   to make large file support automatic unless overridden */\n\n\n#ifndef LARGE_FILE_SUPPORT\n# ifndef NO_LARGE_FILE_SUPPORT\n    /* MS C and VC */\n#   if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)\n#     define LARGE_FILE_SUPPORT\n#   endif\n#   if defined(__WATCOMC__)\n#     define LARGE_FILE_SUPPORT\n#   endif\n# endif\n#endif\n\n#ifdef LARGE_FILE_SUPPORT\n  /* 64-bit Large File Support */\n\n  /* Only types and the printf format stuff go here.  Functions\n     go in tailor.h since ANSI prototypes are required and the OF define\n     is not defined here. */\n\n# if (defined(_MSC_VER) && (_MSC_VER >= 1100)) || defined(__MINGW32__)\n    /* MS C and VC, MinGW32 */\n    /* these compiler systems use the Microsoft C RTL */\n\n    /* base types for file offsets and file sizes */\n    typedef __int64             zoff_t;\n    typedef unsigned __int64    uzoff_t;\n\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n\n    /* printf format size prefix for zoff_t values */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"I64\"\n\n# elif (defined(__GNUC__) || defined(ULONG_LONG_MAX))\n    /* GNU C */\n\n    /* base types for file offsets and file sizes */\n    typedef long long           zoff_t;\n    typedef unsigned long long  uzoff_t;\n\n#  ifdef __CYGWIN__\n    /* Use Cygwin's own stat struct */\n     typedef struct stat z_stat;\n#  else\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n#  endif\n\n    /* printf format size prefix for zoff_t values */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n\n# elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n    /* WATCOM C */\n\n    /* base types for file offsets and file sizes */\n    typedef __int64             zoff_t;\n    typedef unsigned __int64    uzoff_t;\n\n    /* 64-bit stat struct */\n    typedef struct _stati64 z_stat;\n\n    /* printf format size prefix for zoff_t values */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n\n# elif (defined(__IBMC__) && (__IBMC__ >= 350))\n    /* IBM C */\n\n    /* base types for file offsets and file sizes */\n    typedef __int64             zoff_t;\n    typedef unsigned __int64    uzoff_t;\n\n    /* 64-bit stat struct */\n\n    /* printf format size prefix for zoff_t values */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"I64\"\n\n# else\n#   undef LARGE_FILE_SUPPORT\n# endif\n\n#endif\n\n#if 0\n# ifndef ZOFF_T_FORMAT_SIZE_PREFIX\n    /* unsupported WIN32 */\n\n    /* base types for file offsets and file sizes */\n    typedef long long           zoff_t;\n    typedef unsigned long long  uzoff_t;\n\n    /* 64-bit stat struct */\n    typedef struct stat z_stat;\n\n    /* printf format size prefix for zoff_t values */\n#   define ZOFF_T_FORMAT_SIZE_PREFIX \"ll\"\n# endif\n#endif\n\n\n/* Automatically set ZIP64_SUPPORT if supported */\n\n/* MS C and VC */\n#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__)\n# ifdef LARGE_FILE_SUPPORT\n#   ifndef NO_ZIP64_SUPPORT\n#     ifndef ZIP64_SUPPORT\n#       define ZIP64_SUPPORT\n#     endif\n#   endif\n# endif\n#endif\n\n\n#ifndef LARGE_FILE_SUPPORT\n  /* No Large File Support */\n\n  /* base type for file offsets and file sizes */\n  typedef long zoff_t;\n  typedef unsigned long uzoff_t;\n\n  /* stat struct */\n  typedef struct stat z_stat;\n\n  /* printf format size prefix for zoff_t values */\n# define ZOFF_T_FORMAT_SIZE_PREFIX \"l\"\n#endif\n\n\n  /* UNICODE */\n#ifdef WIN32\n  /* assume wide character conversion functions */\n# ifndef UNICODE_SUPPORT\n#   ifndef NO_UNICODE_SUPPORT\n#     define UNICODE_SUPPORT\n#   endif\n# endif\n#endif\n\n#if 0\n  /* this is now generic */\n# ifdef UNICODE_SUPPORT\n  /* Set up Unicode support - 9/27/05 EG */\n\n  /* type of wide string characters */\n#  define zchar wchar_t\n\n  /* default char string used if a wide char can't be converted */\n#  define zchar_default \"_\"\n\n# else\n#  define zchar char\n# endif\n#endif\n\n\n/* File operations--use \"b\" for binary if allowed or fixed length 512 on VMS\n *                  use \"S\" for sequential access on NT to prevent the NT\n *                  file cache eating up memory with large .zip files\n */\n#define FOPR \"rb\"\n#define FOPM \"r+b\"\n#define FOPW \"wbS\"\n\n#if (defined(__CYGWIN__) && !defined(NO_MKTIME))\n#  define NO_MKTIME             /* Cygnus' mktime() implementation is buggy */\n#endif\n#if (!defined(NT_TZBUG_WORKAROUND) && !defined(NO_NT_TZBUG_WORKAROUND))\n#  define NT_TZBUG_WORKAROUND\n#endif\n#if (defined(UTIL) && defined(NT_TZBUG_WORKAROUND))\n#  undef NT_TZBUG_WORKAROUND    /* the Zip utilities do not use time-stamps */\n#endif\n#if !defined(NO_EF_UT_TIME) && !defined(USE_EF_UT_TIME)\n#  define USE_EF_UT_TIME\n#endif\n#if (!defined(NO_NTSD_EAS) && !defined(NTSD_EAS))\n#  define NTSD_EAS\n#endif\n\n#if (defined(NTSD_EAS) && !defined(ZP_NEED_MEMCOMPR))\n#  define ZP_NEED_MEMCOMPR\n#endif\n\n#ifdef WINDLL\n# ifndef NO_ASM\n#   define NO_ASM\n# endif\n# ifndef MSWIN\n#   define MSWIN\n# endif\n# ifndef REENTRANT\n#   define REENTRANT\n# endif\n#endif /* WINDLL */\n\n/* Enable use of optimized x86 assembler version of longest_match() for\n   MSDOS, WIN32 and OS2 per default.  */\n#if !defined(NO_ASM) && !defined(ASMV)\n#  define ASMV\n#endif\n\n/* Enable use of optimized x86 assembler version of crc32() for\n   MSDOS, WIN32 and OS2 per default.  */\n#if !defined(NO_ASM) && !defined(ASM_CRC)  && !defined(NO_ASM_CRC)\n#  define ASM_CRC\n#endif\n\n#if !defined(__GO32__) && !defined(__EMX__) && !defined(__CYGWIN__)\n#  define NO_UNISTD_H\n#endif\n\n/* Microsoft C requires additional attributes attached to all RTL function\n * declarations when linking against the CRTL dll.\n */\n#ifdef MSC\n#  ifdef IZ_IMP\n#    undef IZ_IMP\n#  endif\n#  define IZ_IMP _CRTIMP\n#else\n# ifndef IZ_IMP\n#   define IZ_IMP\n# endif\n#endif\n\n/* WIN32 runs solely on little-endian processors; enable support\n * for the 32-bit optimized CRC-32 C code by default.\n */\n#ifdef IZ_CRC_BE_OPTIMIZ\n#  undef IZ_CRC_BE_OPTIMIZ\n#endif\n#if !defined(IZ_CRC_LE_OPTIMIZ) && !defined(NO_CRC_OPTIMIZ)\n#  define IZ_CRC_LE_OPTIMIZ\n#endif\n\n/* the following definitions are considered as \"obsolete\" by Microsoft and\n * might be missing in some versions of <windows.h>\n */\n#ifndef AnsiToOem\n#  define AnsiToOem CharToOemA\n#endif\n#ifndef OemToAnsi\n#  define OemToAnsi OemToCharA\n#endif\n\n/* handlers for OEM <--> ANSI string conversions */\n#if defined(__RSXNT__) || defined(WIN32_CRT_OEM)\n   /* RSXNT uses OEM coded strings in functions supplied by C RTL */\n#  ifdef CRTL_CP_IS_ISO\n#    undef CRTL_CP_IS_ISO\n#  endif\n#  ifndef CRTL_CP_IS_OEM\n#    define CRTL_CP_IS_OEM\n#  endif\n#else\n   /* \"real\" native WIN32 compilers use ANSI coded strings in C RTL calls */\n#  ifndef CRTL_CP_IS_ISO\n#    define CRTL_CP_IS_ISO\n#  endif\n#  ifdef CRTL_CP_IS_OEM\n#    undef CRTL_CP_IS_OEM\n#  endif\n#endif\n\n#ifdef CRTL_CP_IS_ISO\n   /* C RTL's file system support assumes ANSI coded strings */\n#  define ISO_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define OEM_TO_INTERN(src, dst)  OemToAnsi(src, dst)\n#  define INTERN_TO_ISO(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define INTERN_TO_OEM(src, dst)  AnsiToOem(src, dst)\n#  define _OEM_INTERN(str1) OEM_TO_INTERN(str1, str1)\n#  define _ISO_INTERN(str1) {;}\n#  define _INTERN_OEM(str1) INTERN_TO_OEM(str1, str1)\n#  define _INTERN_ISO(str1) {;}\n#endif /* CRTL_CP_IS_ISO */\n#ifdef CRTL_CP_IS_OEM\n   /* C RTL's file system support assumes OEM coded strings */\n#  define ISO_TO_INTERN(src, dst)  AnsiToOem(src, dst)\n#  define OEM_TO_INTERN(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define INTERN_TO_ISO(src, dst)  OemToAnsi(src, dst)\n#  define INTERN_TO_OEM(src, dst)  {if ((src) != (dst)) strcpy((dst), (src));}\n#  define _OEM_INTERN(str1) {;}\n#  define _ISO_INTERN(str1) ISO_TO_INTERN(str1, str1)\n#  define _INTERN_OEM(str1) {;}\n#  define _INTERN_ISO(str1) INTERN_TO_ISO(str1, str1)\n#endif /* CRTL_CP_IS_OEM */\n\n/* The following \"OEM vs. ISO Zip entry names\" code has been copied from UnZip.\n * It should be applicable to the generic Zip code. However, currently only\n * the Win32 port of Zip supplies the required charset conversion functions.\n * (The Win32 port uses conversion functions supplied by the OS.)\n */\n/* Convert filename (and file comment string) into \"internal\" charset.\n * This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)\n * codepage when made on\n *  -> DOS (this includes 16-bit Windows 3.1)  (FS_FAT_)\n *  -> OS/2                                    (FS_HPFS_)\n *  -> Win95/WinNT with Nico Mak's WinZip      (FS_NTFS_ && hostver == \"5.0\")\n * EXCEPTIONS:\n *  PKZIP for Windows 2.5, 2.6, and 4.0 flag their entries as \"FS_FAT_\", but\n *  the filename stored in the local header is coded in Windows ANSI (CP 1252\n *  resp. ISO 8859-1 on US and western Europe locale settings).\n *  Likewise, PKZIP for UNIX 2.51 flags its entries as \"FS_FAT_\", but the\n *  filenames stored in BOTH the local and the central header are coded\n *  in the local system's codepage (usually ANSI codings like ISO 8859-1,\n *  but could also be UTF-8 on \"modern\" setups...).\n *\n * All other ports are assumed to code zip entry filenames in ISO (8859-1\n * on \"Western\" localisations).\n */\n#define FS_FAT_           0    /* filesystem used by MS-DOS, OS/2, Win32 */\n#define FS_HPFS_          6    /* filesystem used by OS/2 (and NT 3.x) */\n#define FS_NTFS_          11   /* filesystem used by Windows NT */\n#ifndef Ext_ASCII_TO_Native\n#  define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \\\n    if (((hostnum) == FS_FAT_ && \\\n         !(((islochdr) || (isuxatt)) && \\\n           ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \\\n        (hostnum) == FS_HPFS_ || \\\n        ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \\\n        _OEM_INTERN((string)); \\\n    } else { \\\n        _ISO_INTERN((string)); \\\n    }\n#endif\n\n#if (defined(__RSXNT__) && defined(__CRTRSXNT__))\n#  include <crtrsxnt.h>\n#endif\n\n#ifdef _MBCS\n#  if (!defined(__EMX__) && !defined(__MINGW32__) && !defined(__CYGWIN__))\n#    include <stdlib.h>\n#    include <mbstring.h>\n#  endif\n#  if (defined(__MINGW32__) && !defined(MB_CUR_MAX))\n#    ifdef __MSVCRT__\n       IZ_IMP extern int *__p___mb_cur_max(void);\n#      define MB_CUR_MAX (*__p___mb_cur_max())\n#    else\n       IZ_IMP extern int *_imp____mb_cur_max_dll;\n#      define MB_CUR_MAX (*_imp____mb_cur_max_dll)\n#    endif\n#  endif\n#  if (defined(__LCC__) && !defined(MB_CUR_MAX))\n     IZ_IMP extern int *_imp____mb_cur_max;\n#    define MB_CUR_MAX (*_imp____mb_cur_max)\n#  endif\n#endif\n\n#ifdef __LCC__\n#  include <time.h>\n#  ifndef tzset\n#    define tzset _tzset\n#  endif\n#  ifndef utime\n#    define utime _utime\n#  endif\n#endif\n#ifdef __MINGW32__\n   IZ_IMP extern void _tzset(void);     /* this is missing in <time.h> */\n#  ifndef tzset\n#    define tzset _tzset\n#  endif\n#endif\n#if (defined(__RSXNT__) || defined(__EMX__)) && !defined(tzset)\n#  define tzset _tzset\n#endif\n#ifdef W32_USE_IZ_TIMEZONE\n#  ifdef __BORLANDC__\n#    define tzname tzname\n#    define IZTZ_DEFINESTDGLOBALS\n#  endif\n#  ifndef tzset\n#    define tzset _tzset\n#  endif\n#  ifndef timezone\n#    define timezone _timezone\n#  endif\n#  ifndef daylight\n#    define daylight _daylight\n#  endif\n#  ifndef tzname\n#    define tzname _tzname\n#  endif\n#  if (!defined(NEED__ISINDST) && !defined(__BORLANDC__))\n#    define NEED__ISINDST\n#  endif\n#  ifdef IZTZ_GETLOCALETZINFO\n#    undef IZTZ_GETLOCALETZINFO\n#  endif\n#  define IZTZ_GETLOCALETZINFO GetPlatformLocalTimezone\n#endif /* W32_USE_IZ_TIMEZONE */\n\n#ifdef MATCH\n#  undef MATCH\n#endif\n#define MATCH dosmatch          /* use DOS style wildcard matching */\n#ifdef UNICODE_SUPPORT\n# ifdef WIN32\n#   define MATCHW dosmatchw\n# endif\n#endif\n\n#ifdef ZCRYPT_INTERNAL\n#  ifdef WINDLL\n#    define ZCR_SEED2     (unsigned)3141592654L /* use PI as seed pattern */\n#  else\n#    include <process.h>        /* getpid() declaration for srand seed */\n#  endif\n#endif\n\n/* Up to now, all versions of Microsoft C runtime libraries lack the support\n * for customized (non-US) switching rules between daylight saving time and\n * standard time in the TZ environment variable string.\n * But non-US timezone rules are correctly supported when timezone information\n * is read from the OS system settings in the Win32 registry.\n * The following work-around deletes any TZ environment setting from\n * the process environment.  This results in a fallback of the RTL time\n * handling code to the (correctly interpretable) OS system settings, read\n * from the registry.\n */\n#ifdef USE_EF_UT_TIME\n# if (defined(__WATCOMC__) || defined(__CYGWIN__) || \\\n      defined(W32_USE_IZ_TIMEZONE))\n#   define iz_w32_prepareTZenv()\n# else\n#   define iz_w32_prepareTZenv()        putenv(\"TZ=\")\n# endif\n#endif\n\n/* This patch of stat() is useful for at least three compilers.  It is   */\n/* difficult to take a stat() of a root directory under Windows95, so  */\n/* zstat_zipwin32() detects that case and fills in suitable values.    */\n#ifndef __RSXNT__\n#  ifndef W32_STATROOT_FIX\n#    define W32_STATROOT_FIX\n#  endif\n#endif /* !__RSXNT__ */\n\n#if (defined(NT_TZBUG_WORKAROUND) || defined(W32_STATROOT_FIX))\n#  define W32_STAT_BANDAID\n#  ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/03 */\n   int zstat_zipwin32(const char *path, z_stat *buf);\n#  else\n   int zstat_zipwin32(const char *path, struct stat *buf);\n#  endif\n#  ifdef UNICODE_SUPPORT\n#   ifdef LARGE_FILE_SUPPORT\n     int zstat_zipwin32w(const wchar_t *pathw, struct _stati64 *buf);\n#   else\n     int zstat_zipwin32w(const wchar_t *pathw, struct _stat *buf);\n#   endif\n#  endif\n#  ifdef SSTAT\n#    undef SSTAT\n#  endif\n#  define SSTAT zstat_zipwin32\n#  ifdef UNICODE_SUPPORT\n#    define SSTATW zstat_zipwin32w\n#  endif\n#endif /* NT_TZBUG_WORKAROUND || W32_STATROOT_FIX */\n\nint getch_win32(void);\n\n#ifdef __GNUC__\n# define IZ_PACKED      __attribute__((packed))\n#else\n# define IZ_PACKED\n#endif\n\n/* for some (all ?) versions of IBM C Set/2 and IBM C Set++ */\n#ifndef S_IFMT\n#  define S_IFMT 0xF000\n#endif /* !S_IFMT */\n\n#ifdef __WATCOMC__\n#  include <stdio.h>    /* PATH_MAX is defined here */\n#  define NO_MKTEMP\n\n/* Get asm routines to link properly without using \"__cdecl\": */\n#  ifdef __386__\n#    ifdef ASMV\n#      pragma aux match_init    \"_*\" parm caller [] modify []\n#      pragma aux longest_match \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif\n#    if defined(ASM_CRC) && !defined(USE_ZLIB)\n#      pragma aux crc32         \"_*\" parm caller [] value [eax] modify [eax]\n#      pragma aux get_crc_table \"_*\" parm caller [] value [eax] \\\n                                      modify [eax ecx edx]\n#    endif /* ASM_CRC && !USE_ZLIB */\n#  endif /* __386__ */\n   /* Watcom C (like the other Win32 C compiler systems) does not support\n    * symlinks on Win32, but defines the S_IFLNK symbol nevertheless.\n    * However, the existence of this symbol is used as \"symlinks supported\"\n    * indicator in the generic Zip code (see tailor.h). So, for a simple\n    * work-around, this symbol is undefined here. */\n#  ifdef S_IFLNK\n#    undef S_IFLNK\n#  endif\n#  ifdef UNICODE_SUPPORT\n     /* Watcom C does not supply wide-char definitions in the \"standard\"\n      * headers like MSC; so we have to pull in a wchar-specific header.\n      */\n#    include <wchar.h>\n#  endif\n#endif /* __WATCOMC__ */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/readme.a64",
    "content": "readme.x64\n==========\n\n[Note - the gvmat64.asm longest_match routine in Windows 64-bit assembler\nand makefile.a64 used to compile it were provided at the last minute and\nare currently untested by Info-ZIP.  They are provided to allow testing of\nthis optimization which is planned for inclusion in Zip 3.0.\nUSE AT YOUR OWN RISK.  That said, thanks Gilles for providing this\noptimization and we plan to better support it in Zip 3.0.  2/28/2005 EG]\n\nmakefile.asm64 is a makefile for 64 bits optimized version of zip for \nMicrosoft Windows running on AMD64 (Athlon64/Opteron) and Intel EM64T\n(the Pentium 4 and Xeon with 64 bits extension)\n\nmakefile.asm64 contain a makefile for 64 Microsoft C++ for Windows 64 bits,\nextended edition (for both AMD64 and Intel EM64T), included in Visual\nStudio 2005\n\nto compile it, start the C++ AMD64 build environnement prompt,\ngo to the zip source directory and start\n\n   nmake -a -f makefile.a64\n\nThis makefile uses gvmat64.asm, which is the optimized longest_match written\nin assembly code for AMD64/Intel EM64T\n\ngvmat64.asm was tested by Gilles Vollant on AMD64 with infozip, and also tested\nwith a lot of file with zLib 1.2.2 on both AMD64 and Intel EM64T processor.\n\nIt was written by Gilles Vollant, by modifiying the longest_match\nfrom Jean-loup Gailly in deflate.c of zLib and infoZip zip.\nand modifying asm686 (1998), optimised assembly code from Brian Raiter,\n(see http://www.muppetlabs.com/~breadbox/software/assembly.html)\n\n\nGilles Vollant\ninfo@winimage.com\n\nhttp://www.winimage.com\nhttp://www.winimage.com/zLibdll\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/rsxntwin.h",
    "content": "/*\n  win32/rsxntwin.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/* rsxntwin.h\n *\n * fills some gaps in the rsxnt 1.3 win32 header files (<windows.h>) that are\n * required for compiling Info-ZIP sources for Win NT / Win 95\n */\n\n#ifdef __RSXNT__\n#if !defined (_RSXNTWIN_H)\n#define _RSXNTWIN_H\n\n#ifdef TFUNCT   /* TFUNCT is undefined when MSSDK headers are used */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define PASCAL __stdcall\n\n#define ANYSIZE_ARRAY 1\n\n#ifndef TIME_ZONE_ID_UNKNOWN\n#  define TIME_ZONE_ID_UNKNOWN  0\n#endif\n#ifndef TIME_ZONE_ID_INVALID\n#  define TIME_ZONE_ID_INVALID  (DWORD)0xFFFFFFFFL\n#endif\n\n#define FILE_ATTRIBUTE_HIDDEN   0x00000002\n#define FILE_ATTRIBUTE_SYSTEM   0x00000004\n\n#define FILE_SHARE_DELETE       0x00000004\n\n#define FILE_PERSISTENT_ACLS    0x00000008\n\n#define HFILE_ERROR        ((HFILE)-1)\n\n#define FS_PERSISTENT_ACLS      FILE_PERSISTENT_ACLS\n\n\nBOOL WINAPI DosDateTimeToFileTime(WORD, WORD, LPFILETIME);\n\n\n#ifndef SetVolumeLabel\n#define SetVolumeLabel TFUNCT(SetVolumeLabel)\n#endif\nBOOL WINAPI SetVolumeLabel(LPCTSTR, LPCTSTR);\n\n\n#ifndef GetDriveType\n#define GetDriveType TFUNCT(GetDriveType)\n#endif\nDWORD GetDriveType(LPCTSTR);\n\n#define DRIVE_UNKNOWN     0\n#define DRIVE_REMOVABLE   2\n#define DRIVE_FIXED       3\n#define DRIVE_REMOTE      4\n#define DRIVE_CDROM       5\n#define DRIVE_RAMDISK     6\n\n#ifndef SearchPath\n#define SearchPath TFUNCT(SearchPath)\n#endif\nBOOL WINAPI SearchPath(LPCTSTR, LPCTSTR, LPCTSTR, UINT, LPTSTR, LPTSTR *);\n\n#define ERROR_SUCCESS                   0\n#define ERROR_INSUFFICIENT_BUFFER       122\n\nLONG WINAPI InterlockedExchange(LPLONG, LONG);\n\n#define ACCESS_SYSTEM_SECURITY          0x01000000L\n\ntypedef PVOID PSECURITY_DESCRIPTOR;\ntypedef PVOID PSID;\ntypedef struct _ACL {\n    BYTE  AclRevision;\n    BYTE  Sbz1;\n    WORD   AclSize;\n    WORD   AceCount;\n    WORD   Sbz2;\n} ACL;\ntypedef ACL *PACL;\n\ntypedef struct _LUID {\n    DWORD LowPart;\n    LONG HighPart;\n} LUID, *PLUID;\n\ntypedef struct _LUID_AND_ATTRIBUTES {\n    LUID Luid;\n    DWORD Attributes;\n    } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;\n\ntypedef struct _TOKEN_PRIVILEGES {\n    DWORD PrivilegeCount;\n    LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];\n} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;\n\n#define TOKEN_QUERY             0x0008\n#define TOKEN_ADJUST_PRIVILEGES 0x0020\n\nBOOL WINAPI OpenProcessToken(HANDLE, DWORD, PHANDLE);\nBOOL WINAPI AdjustTokenPrivileges(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD,\n                PTOKEN_PRIVILEGES, PDWORD);\n\n#ifndef LookupPrivilegeValue\n#define LookupPrivilegeValue TFUNCT(LookupPrivilegeValue)\n#endif\nBOOL WINAPI LookupPrivilegeValue(LPCTSTR, LPCTSTR, PLUID);\n\ntypedef DWORD SECURITY_INFORMATION, *PSECURITY_INFORMATION;\n#define OWNER_SECURITY_INFORMATION      0x00000001L\n#define GROUP_SECURITY_INFORMATION      0x00000002L\n#define DACL_SECURITY_INFORMATION       0x00000004L\n#define SACL_SECURITY_INFORMATION       0x00000008L\n\ntypedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;\n#define SE_DACL_PRESENT         0x0004\n#define SE_SACL_PRESENT         0x0010\n\n#define SE_PRIVILEGE_ENABLED    0x00000002L\n\n#define SE_SECURITY_NAME                  TEXT(\"SeSecurityPrivilege\")\n#define SE_BACKUP_NAME                    TEXT(\"SeBackupPrivilege\")\n#define SE_RESTORE_NAME                   TEXT(\"SeRestorePrivilege\")\n\nBOOL WINAPI GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,\n                PSECURITY_DESCRIPTOR, DWORD, LPDWORD);\nBOOL WINAPI SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION,\n                PSECURITY_DESCRIPTOR);\nBOOL WINAPI IsValidSid(PSID);\nBOOL WINAPI IsValidAcl(PACL);\nBOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR);\nBOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);\nDWORD WINAPI GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR);\nBOOL WINAPI GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,\n                PSECURITY_DESCRIPTOR_CONTROL, LPDWORD);\nBOOL WINAPI SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,\n                SECURITY_DESCRIPTOR_CONTROL, SECURITY_DESCRIPTOR_CONTROL);\nBOOL WINAPI GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR,\n                                      LPBOOL, PACL *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);\nBOOL WINAPI GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR,\n                                      LPBOOL, PACL *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL);\nBOOL WINAPI GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, BOOL);\nBOOL WINAPI GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID *, LPBOOL);\nBOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, BOOL);\nVOID WINAPI InitializeCriticalSection();\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* TFUNCT */\n\n#ifndef CP_UTF8\n#  define CP_UTF8               65001           /* UTF-8 translation */\n#endif\n\n#endif /* !defined (_RSXNTWIN_H) */\n#endif /* __RSXNT__ */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/ReadmeVC.txt",
    "content": "VC6 Readme\n\nThis directory has a VC6 project list that can be used to compile Zip\nand the utilities.  It does not include bzip2 support.\n\nThe vc6bz2 directory provides a variant of this directory that includes\nthe settings needed for including bzip2 support in Zip.\n\nEd Gordon\n26 March 2007\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=zip - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zip.mak\" CFG=\"zip - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zip - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zip___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"zip___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zip___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"zip___Win32_ASM_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"ASM_CRC\" /D \"ASMV\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zip___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"zip___Win32_ASM_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zip___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"zip___Win32_ASM_Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"ASM_CRC\" /D \"ASMV\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zip___Win32_Release\"\n# PROP BASE Intermediate_Dir \"zip___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zip___Win32_Release\"\n# PROP Intermediate_Dir \"zip___Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"NO_ASM\" /D \"WIN32\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zip___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"zip___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zip___Win32_Debug\"\n# PROP Intermediate_Dir \"zip___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"NO_ASM\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zip - Win32 ASM Release\"\n# Name \"zip - Win32 ASM Debug\"\n# Name \"zip - Win32 Release\"\n# Name \"zip - Win32 Debug\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\deflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\trees.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zip.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipup.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\osdep.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\revision.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\tailor.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ziperr.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipup.h\n# End Source File\n# End Group\n# Begin Group \"Assembler Files\"\n\n# PROP Default_Filter \"asm;obj\"\n# Begin Source File\n\nSOURCE=..\\crc_i386.asm\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Release\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Debug\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release\"\n\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug\"\n\n# PROP Exclude_From_Build 1\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\match32.asm\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Release\nInputPath=..\\match32.asm\nInputName=match32\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Debug\nInputPath=..\\match32.asm\nInputName=match32\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release\"\n\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug\"\n\n# PROP Exclude_From_Build 1\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zip.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"zip\"=\".\\zip.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipcloak\"=\".\\zipcloak.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipnote\"=\".\\zipnote.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipsplit\"=\".\\zipsplit.dsp\" - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zip.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 2013\nVisualStudioVersion = 12.0.30110.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"zip\", \"zip.vcxproj\", \"{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tASM Debug|Win32 = ASM Debug|Win32\n\t\tASM Release|Win32 = ASM Release|Win32\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\t\tTemplate|Win32 = Template|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Debug|Win32.ActiveCfg = ASM Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Debug|Win32.Build.0 = ASM Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Release|Win32.ActiveCfg = ASM Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.ASM Release|Win32.Build.0 = ASM Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Release|Win32.Build.0 = Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Template|Win32.ActiveCfg = Release|Win32\n\t\t{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}.Template|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zip.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>\n    <SccProjectName />\n    <SccLocalPath />\n    <ProjectGuid>{A39FEE66-E8E0-4801-9A5E-EFA7482E4460}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v142</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\zip___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\zip___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\zip___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\zip___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\zip___Win32_Debug\\</OutDir>\n    <IntDir>.\\zip___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\zip___Win32_Release\\</OutDir>\n    <IntDir>.\\zip___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(UniversalCRT_IncludePath);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>WIN32;ASM_CRC;ASMV;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zip___Win32_ASM_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zip___Win32_ASM_Debug\\zip.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zip___Win32_ASM_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zip___Win32_ASM_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zip___Win32_ASM_Debug\\zip.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zip___Win32_ASM_Debug\\zip.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zip___Win32_ASM_Debug\\zip.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>WIN32;ASM_CRC;ASMV;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zip___Win32_ASM_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zip___Win32_ASM_Release\\zip.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zip___Win32_ASM_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zip___Win32_ASM_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zip___Win32_ASM_Release\\zip.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zip___Win32_ASM_Release\\zip.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zip___Win32_ASM_Release\\zip.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zip___Win32_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zip___Win32_Debug\\zip.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zip___Win32_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zip___Win32_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zip___Win32_Debug\\zip.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zip___Win32_Debug\\zip.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zip___Win32_Debug\\zip.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>NO_ASM;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zip___Win32_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zip___Win32_Release\\zip.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zip___Win32_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zip___Win32_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zip___Win32_Release\\zip.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zip___Win32_Release\\zip.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zip___Win32_Release\\zip.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\deflate.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\nt.c\" />\n    <ClCompile Include=\"..\\..\\trees.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\..\\util.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\win32zip.c\" />\n    <ClCompile Include=\"..\\..\\zip.c\" />\n    <ClCompile Include=\"..\\..\\zipfile.c\" />\n    <ClCompile Include=\"..\\..\\zipup.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"..\\zip.rc\">\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\\deps\\infozip\\zip30\\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\\deps\\infozip\\zip30\\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\\deps\\infozip\\zip30\\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\\deps\\infozip\\zip30\\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ResourceCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\nt.h\" />\n    <ClInclude Include=\"..\\osdep.h\" />\n    <ClInclude Include=\"..\\..\\revision.h\" />\n    <ClInclude Include=\"..\\..\\tailor.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\win32zip.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n    <ClInclude Include=\"..\\..\\ziperr.h\" />\n    <ClInclude Include=\"..\\zipup.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <CustomBuild Include=\"..\\crc_i386.asm\">\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">ml /nologo /c /Cx /coff /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </CustomBuild>\n    <CustomBuild Include=\"..\\match32.asm\">\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">true</ExcludedFromBuild>\n      <ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">true</ExcludedFromBuild>\n    </CustomBuild>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipcloak.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zipcloak\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=zipcloak - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zipcloak.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zipcloak.mak\" CFG=\"zipcloak - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zipcloak - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipcloak - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipcloak - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipcloak - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zipcloak - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipcloak___Win32_Release\"\n# PROP BASE Intermediate_Dir \"zipcloak___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipcloak___Win32_Release\"\n# PROP Intermediate_Dir \"zipcloak___Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipcloak___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"zipcloak___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipcloak___Win32_Debug\"\n# PROP Intermediate_Dir \"zipcloak___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipcloak___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"zipcloak___Win32_ASM_Debug\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipcloak___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"zipcloak___Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipcloak___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"zipcloak___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipcloak___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"zipcloak___Win32_ASM_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zipcloak - Win32 Release\"\n# Name \"zipcloak - Win32 Debug\"\n# Name \"zipcloak - Win32 ASM Debug\"\n# Name \"zipcloak - Win32 ASM Release\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipcloak.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipfile.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\osdep.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\revision.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\tailor.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ziperr.h\n# End Source File\n# End Group\n# Begin Group \"Assembler Files\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\crc_i386.asm\n\n!IF  \"$(CFG)\" == \"zipcloak - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 ASM Debug\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipcloak___Win32_ASM_Debug\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zipcloak - Win32 ASM Release\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipcloak___Win32_ASM_Release\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipcloak.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Template|Win32\">\n      <Configuration>Template</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <SccProjectName />\n    <SccLocalPath />\n    <ProjectGuid>{A08751EB-8B20-459E-95F0-7F86E58B1785}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\zipcloak___Win32_Debug\\</OutDir>\n    <IntDir>.\\zipcloak___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\zipcloak___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\zipcloak___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\zipcloak___Win32_Release\\</OutDir>\n    <IntDir>.\\zipcloak___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\zipcloak___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\zipcloak___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipcloak___Win32_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipcloak___Win32_Debug\\zipcloak.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipcloak___Win32_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipcloak___Win32_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipcloak___Win32_Debug\\zipcloak.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipcloak___Win32_Debug\\zipcloak.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipcloak___Win32_Debug\\zipcloak.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipcloak___Win32_ASM_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipcloak___Win32_ASM_Debug\\zipcloak.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipcloak___Win32_ASM_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipcloak___Win32_ASM_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipcloak___Win32_ASM_Debug\\zipcloak.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipcloak___Win32_ASM_Debug\\zipcloak.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipcloak___Win32_ASM_Debug\\zipcloak.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipcloak___Win32_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipcloak___Win32_Release\\zipcloak.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipcloak___Win32_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipcloak___Win32_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipcloak___Win32_Release\\zipcloak.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipcloak___Win32_Release\\zipcloak.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipcloak___Win32_Release\\zipcloak.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>WIN32;UTIL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipcloak___Win32_ASM_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipcloak___Win32_ASM_Release\\zipcloak.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipcloak___Win32_ASM_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipcloak___Win32_ASM_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipcloak___Win32_ASM_Release\\zipcloak.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipcloak___Win32_ASM_Release\\zipcloak.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipcloak___Win32_ASM_Release\\zipcloak.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\..\\crypt.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\ttyio.c\" />\n    <ClCompile Include=\"..\\..\\util.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\..\\zipcloak.c\" />\n    <ClCompile Include=\"..\\..\\zipfile.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\crypt.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\osdep.h\" />\n    <ClInclude Include=\"..\\..\\revision.h\" />\n    <ClInclude Include=\"..\\..\\tailor.h\" />\n    <ClInclude Include=\"..\\..\\ttyio.h\" />\n    <ClInclude Include=\"..\\win32zip.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n    <ClInclude Include=\"..\\..\\ziperr.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <CustomBuild Include=\"..\\crc_i386.asm\">\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n    </CustomBuild>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipnote.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zipnote\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=zipnote - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zipnote.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zipnote.mak\" CFG=\"zipnote - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zipnote - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipnote - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipnote - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipnote - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zipnote - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipnote___Win32_Release\"\n# PROP BASE Intermediate_Dir \"zipnote___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipnote___Win32_Release\"\n# PROP Intermediate_Dir \"zipnote___Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipnote___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"zipnote___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipnote___Win32_Debug\"\n# PROP Intermediate_Dir \"zipnote___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"NO_ASM\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipnote___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"zipnote___Win32_ASM_Debug\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipnote___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"zipnote___Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipnote___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"zipnote___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipnote___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"zipnote___Win32_ASM_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zipnote - Win32 Release\"\n# Name \"zipnote - Win32 Debug\"\n# Name \"zipnote - Win32 ASM Debug\"\n# Name \"zipnote - Win32 ASM Release\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipnote.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\osdep.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\revision.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\tailor.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ziperr.h\n# End Source File\n# End Group\n# Begin Group \"Assembler Files\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\crc_i386.asm\n\n!IF  \"$(CFG)\" == \"zipnote - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 ASM Debug\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipnote___Win32_ASM_Debug\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zipnote - Win32 ASM Release\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipnote___Win32_ASM_Release\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipnote.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Template|Win32\">\n      <Configuration>Template</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <SccProjectName />\n    <SccLocalPath />\n    <ProjectGuid>{79CBCAC7-19F5-4AC3-A5FE-DD0CFEFC77B6}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\zipnote___Win32_Debug\\</OutDir>\n    <IntDir>.\\zipnote___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\zipnote___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\zipnote___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\zipnote___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\zipnote___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\zipnote___Win32_Release\\</OutDir>\n    <IntDir>.\\zipnote___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipnote___Win32_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipnote___Win32_Debug\\zipnote.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipnote___Win32_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipnote___Win32_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipnote___Win32_Debug\\zipnote.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipnote___Win32_Debug\\zipnote.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipnote___Win32_Debug\\zipnote.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipnote___Win32_ASM_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipnote___Win32_ASM_Debug\\zipnote.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipnote___Win32_ASM_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipnote___Win32_ASM_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipnote___Win32_ASM_Debug\\zipnote.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipnote___Win32_ASM_Debug\\zipnote.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipnote___Win32_ASM_Debug\\zipnote.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>WIN32;UTIL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipnote___Win32_ASM_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipnote___Win32_ASM_Release\\zipnote.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipnote___Win32_ASM_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipnote___Win32_ASM_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipnote___Win32_ASM_Release\\zipnote.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipnote___Win32_ASM_Release\\zipnote.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipnote___Win32_ASM_Release\\zipnote.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipnote___Win32_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipnote___Win32_Release\\zipnote.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipnote___Win32_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipnote___Win32_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipnote___Win32_Release\\zipnote.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipnote___Win32_Release\\zipnote.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipnote___Win32_Release\\zipnote.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\util.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\..\\zipfile.c\" />\n    <ClCompile Include=\"..\\..\\zipnote.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\osdep.h\" />\n    <ClInclude Include=\"..\\..\\revision.h\" />\n    <ClInclude Include=\"..\\..\\tailor.h\" />\n    <ClInclude Include=\"..\\win32zip.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n    <ClInclude Include=\"..\\..\\ziperr.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <CustomBuild Include=\"..\\crc_i386.asm\">\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n    </CustomBuild>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipsplit.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zipsplit\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=zipsplit - Win32 ASM Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zipsplit.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zipsplit.mak\" CFG=\"zipsplit - Win32 ASM Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zipsplit - Win32 Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipsplit - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipsplit - Win32 ASM Debug\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zipsplit - Win32 ASM Release\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zipsplit - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipsplit___Win32_Release\"\n# PROP BASE Intermediate_Dir \"zipsplit___Win32_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipsplit___Win32_Release\"\n# PROP Intermediate_Dir \"zipsplit___Win32_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipsplit___Win32_Debug\"\n# PROP BASE Intermediate_Dir \"zipsplit___Win32_Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipsplit___Win32_Debug\"\n# PROP Intermediate_Dir \"zipsplit___Win32_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /D \"NO_ASM\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 ASM Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zipsplit___Win32_ASM_Debug\"\n# PROP BASE Intermediate_Dir \"zipsplit___Win32_ASM_Debug\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zipsplit___Win32_ASM_Debug\"\n# PROP Intermediate_Dir \"zipsplit___Win32_ASM_Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"UTIL\" /D \"WIN32\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 ASM Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zipsplit___Win32_ASM_Release\"\n# PROP BASE Intermediate_Dir \"zipsplit___Win32_ASM_Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zipsplit___Win32_ASM_Release\"\n# PROP Intermediate_Dir \"zipsplit___Win32_ASM_Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"UTIL\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zipsplit - Win32 Release\"\n# Name \"zipsplit - Win32 Debug\"\n# Name \"zipsplit - Win32 ASM Debug\"\n# Name \"zipsplit - Win32 ASM Release\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipsplit.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\osdep.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\revision.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\tailor.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ziperr.h\n# End Source File\n# End Group\n# Begin Group \"Assembler Files\"\n\n# PROP Default_Filter \"\"\n# Begin Source File\n\nSOURCE=..\\crc_i386.asm\n\n!IF  \"$(CFG)\" == \"zipsplit - Win32 Release\"\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 Debug\"\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 ASM Debug\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipsplit___Win32_ASM_Debug\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zipsplit - Win32 ASM Release\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zipsplit___Win32_ASM_Release\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6/zipsplit.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"ASM Debug|Win32\">\n      <Configuration>ASM Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"ASM Release|Win32\">\n      <Configuration>ASM Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Template|Win32\">\n      <Configuration>Template</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <SccProjectName />\n    <SccLocalPath />\n    <ProjectGuid>{51B4C04E-7390-4B02-9E3D-8EDFA96FCCC5}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <PlatformToolset>v120</PlatformToolset>\n    <UseOfMfc>false</UseOfMfc>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Template|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n    <Import Project=\"$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <OutDir>.\\zipsplit___Win32_Debug\\</OutDir>\n    <IntDir>.\\zipsplit___Win32_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <OutDir>.\\zipsplit___Win32_ASM_Release\\</OutDir>\n    <IntDir>.\\zipsplit___Win32_ASM_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <OutDir>.\\zipsplit___Win32_ASM_Debug\\</OutDir>\n    <IntDir>.\\zipsplit___Win32_ASM_Debug\\</IntDir>\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <OutDir>.\\zipsplit___Win32_Release\\</OutDir>\n    <IntDir>.\\zipsplit___Win32_Release\\</IntDir>\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipsplit___Win32_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipsplit___Win32_Debug\\zipsplit.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipsplit___Win32_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipsplit___Win32_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipsplit___Win32_Debug\\zipsplit.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipsplit___Win32_Debug\\zipsplit.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipsplit___Win32_Debug\\zipsplit.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>WIN32;UTIL;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipsplit___Win32_ASM_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipsplit___Win32_ASM_Release\\zipsplit.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipsplit___Win32_ASM_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipsplit___Win32_ASM_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipsplit___Win32_ASM_Release\\zipsplit.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipsplit___Win32_ASM_Release\\zipsplit.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipsplit___Win32_ASM_Release\\zipsplit.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <FunctionLevelLinking>false</FunctionLevelLinking>\n      <Optimization>Disabled</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <MinimalRebuild>true</MinimalRebuild>\n      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\n      <PreprocessorDefinitions>UTIL;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipsplit___Win32_ASM_Debug\\</AssemblerListingLocation>\n      <BrowseInformation>true</BrowseInformation>\n      <PrecompiledHeaderOutputFile>.\\zipsplit___Win32_ASM_Debug\\zipsplit.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipsplit___Win32_ASM_Debug\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipsplit___Win32_ASM_Debug\\</ProgramDataBaseFileName>\n      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipsplit___Win32_ASM_Debug\\zipsplit.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipsplit___Win32_ASM_Debug\\zipsplit.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipsplit___Win32_ASM_Debug\\zipsplit.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\n      <InlineFunctionExpansion>Default</InlineFunctionExpansion>\n      <StringPooling>true</StringPooling>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <Optimization>MaxSpeed</Optimization>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <WarningLevel>Level3</WarningLevel>\n      <PreprocessorDefinitions>UTIL;WIN32;NO_ASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AssemblerListingLocation>.\\zipsplit___Win32_Release\\</AssemblerListingLocation>\n      <PrecompiledHeaderOutputFile>.\\zipsplit___Win32_Release\\zipsplit.pch</PrecompiledHeaderOutputFile>\n      <ObjectFileName>.\\zipsplit___Win32_Release\\</ObjectFileName>\n      <ProgramDataBaseFileName>.\\zipsplit___Win32_Release\\</ProgramDataBaseFileName>\n    </ClCompile>\n    <Midl>\n      <TypeLibraryName>.\\zipsplit___Win32_Release\\zipsplit.tlb</TypeLibraryName>\n    </Midl>\n    <ResourceCompile>\n      <Culture>0x0409</Culture>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n    <Bscmake>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <OutputFile>.\\zipsplit___Win32_Release\\zipsplit.bsc</OutputFile>\n    </Bscmake>\n    <Link>\n      <SuppressStartupBanner>true</SuppressStartupBanner>\n      <SubSystem>Console</SubSystem>\n      <OutputFile>.\\zipsplit___Win32_Release\\zipsplit.exe</OutputFile>\n      <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\crc32.c\" />\n    <ClCompile Include=\"..\\..\\fileio.c\" />\n    <ClCompile Include=\"..\\..\\globals.c\" />\n    <ClCompile Include=\"..\\..\\util.c\" />\n    <ClCompile Include=\"..\\win32.c\" />\n    <ClCompile Include=\"..\\win32i64.c\" />\n    <ClCompile Include=\"..\\..\\zipfile.c\" />\n    <ClCompile Include=\"..\\..\\zipsplit.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\crc32.h\" />\n    <ClInclude Include=\"..\\..\\ebcdic.h\" />\n    <ClInclude Include=\"..\\osdep.h\" />\n    <ClInclude Include=\"..\\..\\revision.h\" />\n    <ClInclude Include=\"..\\..\\tailor.h\" />\n    <ClInclude Include=\"..\\win32zip.h\" />\n    <ClInclude Include=\"..\\..\\zip.h\" />\n    <ClInclude Include=\"..\\..\\ziperr.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <CustomBuild Include=\"..\\crc_i386.asm\">\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Release|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n      <Command Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">ml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)%(Filename).obj\" \"%(FullPath)\"</Command>\n      <Message Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">Assembling...</Message>\n      <Outputs Condition=\"'$(Configuration)|$(Platform)'=='ASM Debug|Win32'\">$(IntDir)\\$(InputName).obj;%(Outputs)</Outputs>\n    </CustomBuild>\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6bz2/ReadVCBZ.txt",
    "content": "VC6bz2 Readme\n\nThis directory has a VC6 project list that can be used to compile Zip\nand the utilities.  The Zip project includes support for the bzip2\ncompression method.\n\nTo include bzip2 support, get a copy of the bzip2 source (bzip2-1.0.4\nor later from http://www.bzip.org/ for instance), expand the bzip2\nsource into a directory, then copy the contents of the bzip2-1.0.4\ndirectory, for instance, into the zip bzip2 directory.  Use this\nproject to compile zip and bzip2 support should be included.  See\nbzip2/install.txt for additional information.\n\nThe vc6 directory is similar to this directory but does not include\nbzip2 support.  Use that if you do not have a copy of bzip2 or do not\nneed bzip2 support.\n\nEd Gordon\n26 March 2007\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6bz2/zip.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zip\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\n\nCFG=zip - Win32 Debug bzip2\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zip.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zip.mak\" CFG=\"zip - Win32 Debug bzip2\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zip - Win32 ASM Release bzip2\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 ASM Debug bzip2\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 Release bzip2\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \"zip - Win32 Debug bzip2\" (based on \"Win32 (x86) Console Application\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release bzip2\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zip___Win32_ASM_Release_bzip2\"\n# PROP BASE Intermediate_Dir \"zip___Win32_ASM_Release_bzip2\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zip___Win32_ASM_Release_bzip2\"\n# PROP Intermediate_Dir \"zip___Win32_ASM_Release_bzip2\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"ASM_CRC\" /D \"ASMV\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"ASM_CRC\" /D \"ASMV\" /D \"WIN32\" /D \"BZIP2_SUPPORT\" /D \"BZ_NO_STDIO\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug bzip2\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zip___Win32_ASM_Debug_bzip2\"\n# PROP BASE Intermediate_Dir \"zip___Win32_ASM_Debug_bzip2\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zip___Win32_ASM_Debug_bzip2\"\n# PROP Intermediate_Dir \"zip___Win32_ASM_Debug_bzip2\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"ASM_CRC\" /D \"ASMV\" /FR /FD /GZ /c\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"ASM_CRC\" /D \"ASMV\" /D \"WIN32\" /D \"BZIP2_SUPPORT\" /D \"BZ_NO_STDIO\" /FR /FD /GZ /c\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release bzip2\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"zip___Win32_Release_bzip2\"\n# PROP BASE Intermediate_Dir \"zip___Win32_Release_bzip2\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"zip___Win32_Release_bzip2\"\n# PROP Intermediate_Dir \"zip___Win32_Release_bzip2\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NO_ASM\" /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"../../bzip2\" /D \"NO_ASM\" /D \"WIN32\" /D \"BZIP2_SUPPORT\" /D \"BZ_NO_STDIO\" /FD /c\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug bzip2\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"zip___Win32_Debug_bzip2\"\n# PROP BASE Intermediate_Dir \"zip___Win32_Debug_bzip2\"\n# PROP BASE Ignore_Export_Lib 0\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"zip___Win32_Debug_bzip2\"\n# PROP Intermediate_Dir \"zip___Win32_Debug_bzip2\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"NO_ASM\" /D \"WIN32\" /FR /FD /GZ /c\n# SUBTRACT BASE CPP /WX\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../../bzip2\" /D \"NO_ASM\" /D \"WIN32\" /D \"BZIP2_SUPPORT\" /D \"BZ_NO_STDIO\" /FR /FD /GZ /c\n# SUBTRACT CPP /WX\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zip - Win32 ASM Release bzip2\"\n# Name \"zip - Win32 ASM Debug bzip2\"\n# Name \"zip - Win32 Release bzip2\"\n# Name \"zip - Win32 Debug bzip2\"\n# Begin Group \"Source Files\"\n\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\blocksort.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\bzlib.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\compress.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\crctable.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\decompress.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\deflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\huffman.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\randtable.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\trees.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zbz2err.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zip.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zipup.c\n# End Source File\n# End Group\n# Begin Group \"Header Files\"\n\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\n# Begin Source File\n\nSOURCE=..\\..\\bzip2\\bzlib.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crc32.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\crypt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ebcdic.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\nt.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\osdep.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\revision.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\tailor.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ttyio.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\win32zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\zip.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\ziperr.h\n# End Source File\n# Begin Source File\n\nSOURCE=..\\zipup.h\n# End Source File\n# End Group\n# Begin Group \"Assembler Files\"\n\n# PROP Default_Filter \"asm;obj\"\n# Begin Source File\n\nSOURCE=..\\crc_i386.asm\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release bzip2\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Release_bzip2\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug bzip2\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Debug_bzip2\nInputPath=..\\crc_i386.asm\nInputName=crc_i386\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release bzip2\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug bzip2\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ENDIF \n\n# End Source File\n# Begin Source File\n\nSOURCE=..\\match32.asm\n\n!IF  \"$(CFG)\" == \"zip - Win32 ASM Release bzip2\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Release_bzip2\nInputPath=..\\match32.asm\nInputName=match32\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 ASM Debug bzip2\"\n\n# Begin Custom Build - Assembling...\nIntDir=.\\zip___Win32_ASM_Debug_bzip2\nInputPath=..\\match32.asm\nInputName=match32\n\n\"$(IntDir)\\$(InputName).obj\" : $(SOURCE) \"$(INTDIR)\" \"$(OUTDIR)\"\n\tml /nologo /c /Cx /coff /Zi /Fo\"$(IntDir)\\$(InputName).obj\" \"$(InputPath)\"\n\n# End Custom Build\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Release bzip2\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ELSEIF  \"$(CFG)\" == \"zip - Win32 Debug bzip2\"\n\n# PROP BASE Exclude_From_Build 1\n# PROP Exclude_From_Build 1\n\n!ENDIF \n\n# End Source File\n# End Group\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/win32/vc6bz2/zip.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"zip\"=.\\zip.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipcloak\"=..\\vc6\\zipcloak.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipnote\"=..\\vc6\\zipnote.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nProject: \"zipsplit\"=..\\vc6\\zipsplit.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/win32.c",
    "content": "/*\n  win32/win32.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n/*\n * WIN32 specific functions for ZIP.\n *\n * The WIN32 version of ZIP heavily relies on the MSDOS and OS2 versions,\n * since we have to do similar things to switch between NTFS, HPFS and FAT.\n */\n\n\n#include \"../zip.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <limits.h>\n#include <time.h>\n#include <ctype.h>\n#define WIN32_LEAN_AND_MEAN\n#ifdef CR\n#undef CR\n#endif\n#include <windows.h>\n/* for LARGE_FILE_SUPPORT but may not be needed */\n#include <io.h>\n\n#ifdef __RSXNT__\n#  include <alloca.h>\n#  include \"../win32/rsxntwin.h\"\n#endif\n#include \"../win32/win32zip.h\"\n\n#define A_RONLY    0x01\n#define A_HIDDEN   0x02\n#define A_SYSTEM   0x04\n#define A_LABEL    0x08\n#define A_DIR      0x10\n#define A_ARCHIVE  0x20\n\n\n#define EAID     0x0009\n\n#if (defined(__MINGW32__) && !defined(USE_MINGW_GLOBBING))\n   int _CRT_glob = 0;   /* suppress command line globbing by C RTL */\n#endif\n\n#ifndef UTIL\n\nextern int noisy;\n\n#ifdef NT_TZBUG_WORKAROUND\nlocal int FSusesLocalTime(const char *path);\n#ifdef UNICODE_SUPPORt\nlocal int FSusesLocalTimeW(const wchar_t *path);\n#endif\n#endif\n#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))\nlocal int FileTime2utime(FILETIME *pft, time_t *ut);\n#endif\n#if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))\nlocal int VFatFileTime2utime(const FILETIME *pft, time_t *ut);\n#endif\n\n\n/* FAT / HPFS detection */\n\nint IsFileSystemOldFAT(char *dir)\n{\n  static char lastDrive = '\\0';    /* cached drive of last GetVolumeInformation call */\n  static int lastDriveOldFAT = 0;  /* cached OldFAT value of last GetVolumeInformation call */\n  char root[4];\n  DWORD vfnsize;\n  DWORD vfsflags;\n\n    /*\n     * We separate FAT and HPFS+other file systems here.\n     * I consider other systems to be similar to HPFS/NTFS, i.e.\n     * support for long file names and being case sensitive to some extent.\n     */\n\n    strncpy(root, dir, 3);\n    if ( isalpha((uch)root[0]) && (root[1] == ':') ) {\n      root[0] = to_up(dir[0]);\n      root[2] = '\\\\';\n      root[3] = 0;\n    }\n    else {\n      root[0] = '\\\\';\n      root[1] = 0;\n    }\n    if (lastDrive == root[0]) {\n      return lastDriveOldFAT;\n    }\n\n    if ( !GetVolumeInformation(root, NULL, 0,\n                               NULL, &vfnsize, &vfsflags,\n                               NULL, 0)) {\n        fprintf(mesg, \"zip diagnostic: GetVolumeInformation failed\\n\");\n        return(FALSE);\n    }\n\n    lastDrive = root[0];\n    lastDriveOldFAT = vfnsize <= 12;\n\n    return lastDriveOldFAT;\n}\n\n#ifdef UNICODE_SUPPORT\nint IsFileSystemOldFATW(wchar_t *dir)\n{\n  static wchar_t lastDrive = (wchar_t)'\\0';    /* cached drive of last GetVolumeInformation call */\n  static int lastDriveOldFAT = 0;  /* cached OldFAT value of last GetVolumeInformation call */\n  wchar_t root[4];\n  DWORD vfnsize;\n  DWORD vfsflags;\n\n    /*\n     * We separate FAT and HPFS+other file systems here.\n     * I consider other systems to be similar to HPFS/NTFS, i.e.\n     * support for long file names and being case sensitive to some extent.\n     */\n\n    wcsncpy(root, dir, 3);\n    if ( iswalpha(root[0]) && (root[1] == (wchar_t)':') ) {\n      root[0] = towupper(dir[0]);\n      root[2] = (wchar_t)'\\\\';\n      root[3] = 0;\n    }\n    else {\n      root[0] = (wchar_t)'\\\\';\n      root[1] = 0;\n    }\n    if (lastDrive == root[0]) {\n      return lastDriveOldFAT;\n    }\n\n    if ( !GetVolumeInformationW(root, NULL, 0,\n                                NULL, &vfnsize, &vfsflags,\n                                NULL, 0)) {\n        fprintf(mesg, \"zip diagnostic: GetVolumeInformation failed\\n\");\n        return(FALSE);\n    }\n\n    lastDrive = root[0];\n    lastDriveOldFAT = vfnsize <= 12;\n\n    return lastDriveOldFAT;\n}\n#endif\n\n\n/* access mode bits and time stamp */\n\nint GetFileMode(char *name)\n{\nDWORD dwAttr;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  char *ansi_name = (char *)alloca(strlen(name) + 1);\n\n  OemToAnsi(name, ansi_name);\n  name = ansi_name;\n#endif\n\n  dwAttr = GetFileAttributes(name);\n  if ( dwAttr == 0xFFFFFFFF ) {\n    zipwarn(\"reading file attributes failed: \", name);\n    /*\n    fprintf(mesg, \"zip diagnostic: GetFileAttributes failed\");\n    fflush();\n    */\n    return(0x20); /* the most likely, though why the error? security? */\n  }\n  return(\n          (dwAttr&FILE_ATTRIBUTE_READONLY  ? A_RONLY   :0)\n        | (dwAttr&FILE_ATTRIBUTE_HIDDEN    ? A_HIDDEN  :0)\n        | (dwAttr&FILE_ATTRIBUTE_SYSTEM    ? A_SYSTEM  :0)\n        | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR     :0)\n        | (dwAttr&FILE_ATTRIBUTE_ARCHIVE   ? A_ARCHIVE :0));\n}\n\n#ifdef UNICODE_SUPPORT\nint GetFileModeW(wchar_t *namew)\n{\nDWORD dwAttr;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  wchar_t *ansi_namew = (wchar_t *)alloca((wcslen(namew) + 1) * sizeof(wchar_t));\n\n  CharToAnsiW(namew, ansi_namew);\n  namew = ansi_namew;\n#endif\n\n  dwAttr = GetFileAttributesW(namew);\n  if ( dwAttr == 0xFFFFFFFF ) {\n    char *name = wchar_to_local_string(namew);\n    zipwarn(\"reading file attributes failed: \", name);\n    free(name);\n    return(0x20); /* the most likely, though why the error? security? */\n  }\n  return(\n          (dwAttr&FILE_ATTRIBUTE_READONLY  ? A_RONLY   :0)\n        | (dwAttr&FILE_ATTRIBUTE_HIDDEN    ? A_HIDDEN  :0)\n        | (dwAttr&FILE_ATTRIBUTE_SYSTEM    ? A_SYSTEM  :0)\n        | (dwAttr&FILE_ATTRIBUTE_DIRECTORY ? A_DIR     :0)\n        | (dwAttr&FILE_ATTRIBUTE_ARCHIVE   ? A_ARCHIVE :0));\n}\n#endif\n\n\nint ClearArchiveBitW(wchar_t *namew)\n{\nDWORD dwAttr;\n  dwAttr = GetFileAttributesW(namew);\n  if ( dwAttr == 0xFFFFFFFF ) {\n    fprintf(mesg, \"zip diagnostic: GetFileAttributes failed\\n\");\n    return(0);\n  }\n\n  if (!SetFileAttributesW(namew, (DWORD)(dwAttr & ~FILE_ATTRIBUTE_ARCHIVE))) {\n    fprintf(mesg, \"zip diagnostic: SetFileAttributes failed\\n\");\n    perror(\"SetFileAttributes\");\n    return(0);\n  }\n  return(1);\n}\n\nint ClearArchiveBit(char *name)\n{\nDWORD dwAttr;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  char *ansi_name = (char *)alloca(strlen(name) + 1);\n\n  OemToAnsi(name, ansi_name);\n  name = ansi_name;\n#endif\n\n  dwAttr = GetFileAttributes(name);\n  if ( dwAttr == 0xFFFFFFFF ) {\n    fprintf(mesg, \"zip diagnostic: GetFileAttributes failed\\n\");\n    return(0);\n  }\n\n  if (!SetFileAttributes(name, (DWORD)(dwAttr & ~FILE_ATTRIBUTE_ARCHIVE))) {\n    fprintf(mesg, \"zip diagnostic: SetFileAttributes failed\\n\");\n    perror(\"SetFileAttributes\");\n    return(0);\n  }\n  return(1);\n}\n\n\n#ifdef NT_TZBUG_WORKAROUND\nlocal int FSusesLocalTime(const char *path)\n{\n    char  *tmp0;\n    char   rootPathName[4];\n    char   tmp1[MAX_PATH], tmp2[MAX_PATH];\n    DWORD  volSerNo, maxCompLen, fileSysFlags;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n    char *ansi_path = (char *)alloca(strlen(path) + 1);\n\n    OemToAnsi(path, ansi_path);\n    path = ansi_path;\n#endif\n\n    if (isalpha((uch)path[0]) && (path[1] == ':'))\n        tmp0 = (char *)path;\n    else\n    {\n        GetFullPathName(path, MAX_PATH, tmp1, &tmp0);\n        tmp0 = &tmp1[0];\n    }\n    strncpy(rootPathName, tmp0, 3);   /* Build the root path name, */\n    rootPathName[3] = '\\0';           /* e.g. \"A:/\"                */\n\n    GetVolumeInformation((LPCTSTR)rootPathName, (LPTSTR)tmp1, (DWORD)MAX_PATH,\n                         &volSerNo, &maxCompLen, &fileSysFlags,\n                         (LPTSTR)tmp2, (DWORD)MAX_PATH);\n\n    /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in\n     * local time!\n     */\n    return !strncmp(strupr(tmp2), \"FAT\", 3) ||\n           !strncmp(tmp2, \"VFAT\", 4) ||\n           !strncmp(tmp2, \"HPFS\", 4);\n\n} /* end function FSusesLocalTime() */\n\n# ifdef UNICODE_SUPPORT\nlocal int FSusesLocalTimeW(const wchar_t *path)\n{\n    wchar_t  *tmp0;\n    wchar_t   rootPathName[4];\n    wchar_t   tmp1[MAX_PATH], tmp2[MAX_PATH];\n    DWORD  volSerNo, maxCompLen, fileSysFlags;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n    wchar_t *ansi_path = (wchar_t *)alloca((wcslen(path) + 1) * sizeof(wchar_t));\n\n    CharToAnsiW(path, ansi_path);\n    path = ansi_path;\n#endif\n\n    if (iswalpha(path[0]) && (path[1] == (wchar_t)':'))\n        tmp0 = (wchar_t *)path;\n    else\n    {\n        GetFullPathNameW(path, MAX_PATH, tmp1, &tmp0);\n        tmp0 = &tmp1[0];\n    }\n    wcsncpy(rootPathName, tmp0, 3);   /* Build the root path name, */\n    rootPathName[3] = (wchar_t)'\\0';           /* e.g. \"A:/\"                */\n\n    GetVolumeInformationW(rootPathName, tmp1, (DWORD)MAX_PATH,\n                         &volSerNo, &maxCompLen, &fileSysFlags,\n                         tmp2, (DWORD)MAX_PATH);\n\n    /* Volumes in (V)FAT and (OS/2) HPFS format store file timestamps in\n     * local time!\n     */\n    return !wcsncmp(_wcsupr(tmp2), L\"FAT\", 3) ||\n           !wcsncmp(tmp2, L\"VFAT\", 4) ||\n           !wcsncmp(tmp2, L\"HPFS\", 4);\n\n} /* end function FSusesLocalTimeW() */\n# endif\n\n#endif /* NT_TZBUG_WORKAROUND */\n\n\n#if (defined(USE_EF_UT_TIME) || defined(NT_TZBUG_WORKAROUND))\n\n#if (defined(__GNUC__) || defined(ULONG_LONG_MAX))\n   typedef long long            LLONG64;\n   typedef unsigned long long   ULLNG64;\n#elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100))\n   typedef __int64              LLONG64;\n   typedef unsigned __int64     ULLNG64;\n#elif (defined(_MSC_VER) && (_MSC_VER >= 1100))\n   typedef __int64              LLONG64;\n   typedef unsigned __int64     ULLNG64;\n#elif (defined(__IBMC__) && (__IBMC__ >= 350))\n   typedef __int64              LLONG64;\n   typedef unsigned __int64     ULLNG64;\n#else\n#  define NO_INT64\n#endif\n\n#  define UNIX_TIME_ZERO_HI  0x019DB1DEUL\n#  define UNIX_TIME_ZERO_LO  0xD53E8000UL\n#  define NT_QUANTA_PER_UNIX 10000000L\n#  define FTQUANTA_PER_UT_L  (NT_QUANTA_PER_UNIX & 0xFFFF)\n#  define FTQUANTA_PER_UT_H  (NT_QUANTA_PER_UNIX >> 16)\n#  define UNIX_TIME_UMAX_HI  0x0236485EUL\n#  define UNIX_TIME_UMAX_LO  0xD4A5E980UL\n#  define UNIX_TIME_SMIN_HI  0x0151669EUL\n#  define UNIX_TIME_SMIN_LO  0xD53E8000UL\n#  define UNIX_TIME_SMAX_HI  0x01E9FD1EUL\n#  define UNIX_TIME_SMAX_LO  0xD4A5E980UL\n\nlocal int FileTime2utime(FILETIME *pft, time_t *ut)\n{\n#ifndef NO_INT64\n    ULLNG64 NTtime;\n\n    NTtime = ((ULLNG64)pft->dwLowDateTime +\n              ((ULLNG64)pft->dwHighDateTime << 32));\n\n    /* underflow and overflow handling */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if (NTtime < ((ULLNG64)UNIX_TIME_SMIN_LO +\n                      ((ULLNG64)UNIX_TIME_SMIN_HI << 32))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        }\n        if (NTtime > ((ULLNG64)UNIX_TIME_SMAX_LO +\n                      ((ULLNG64)UNIX_TIME_SMAX_HI << 32))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if (NTtime < ((ULLNG64)UNIX_TIME_ZERO_LO +\n                      ((ULLNG64)UNIX_TIME_ZERO_HI << 32))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if (NTtime > ((ULLNG64)UNIX_TIME_UMAX_LO +\n                      ((ULLNG64)UNIX_TIME_UMAX_HI << 32))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n\n    NTtime -= ((ULLNG64)UNIX_TIME_ZERO_LO +\n               ((ULLNG64)UNIX_TIME_ZERO_HI << 32));\n    *ut = (time_t)(NTtime / (unsigned long)NT_QUANTA_PER_UNIX);\n    return TRUE;\n#else /* NO_INT64 (64-bit integer arithmetics may not be supported) */\n    /* nonzero if `y' is a leap year, else zero */\n#   define leap(y) (((y)%4 == 0 && (y)%100 != 0) || (y)%400 == 0)\n    /* number of leap years from 1970 to `y' (not including `y' itself) */\n#   define nleap(y) (((y)-1969)/4 - ((y)-1901)/100 + ((y)-1601)/400)\n    /* daycount at the end of month[m-1] */\n    static ZCONST ush ydays[] =\n      { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };\n\n    time_t days;\n    SYSTEMTIME w32tm;\n\n    /* underflow and overflow handling */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n\n    FileTimeToSystemTime(pft, &w32tm);\n\n    /* set `days' to the number of days into the year */\n    days = w32tm.wDay - 1 + ydays[w32tm.wMonth-1] +\n           (w32tm.wMonth > 2 && leap (w32tm.wYear));\n\n    /* now set `days' to the number of days since 1 Jan 1970 */\n    days += 365 * (time_t)(w32tm.wYear - 1970) +\n            (time_t)(nleap(w32tm.wYear));\n\n    *ut = (time_t)(86400L * days + 3600L * (time_t)w32tm.wHour +\n                   (time_t)(60 * w32tm.wMinute + w32tm.wSecond));\n    return TRUE;\n#endif /* ?NO_INT64 */\n} /* end function FileTime2utime() */\n#endif /* USE_EF_UT_TIME || NT_TZBUG_WORKAROUND */\n\n\n#if (defined(NT_TZBUG_WORKAROUND) && defined(W32_STAT_BANDAID))\n\nlocal int VFatFileTime2utime(const FILETIME *pft, time_t *ut)\n{\n    FILETIME lft;\n    SYSTEMTIME w32tm;\n    struct tm ltm;\n\n    FileTimeToLocalFileTime(pft, &lft);\n    FileTimeToSystemTime(&lft, &w32tm);\n    /* underflow and overflow handling */\n    /* TODO: The range checks are not accurate, the actual limits may\n     *       be off by one daylight-saving-time shift (typically 1 hour),\n     *       depending on the current state of \"is_dst\".\n     */\n#ifdef CHECK_UTIME_SIGNED_UNSIGNED\n    if ((time_t)0x80000000L < (time_t)0L)\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_SMIN_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMIN_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_SMIN_LO))) {\n            *ut = (time_t)LONG_MIN;\n            return FALSE;\n        if ((pft->dwHighDateTime > UNIX_TIME_SMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_SMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_SMAX_LO))) {\n            *ut = (time_t)LONG_MAX;\n            return FALSE;\n        }\n    }\n    else\n#endif /* CHECK_UTIME_SIGNED_UNSIGNED */\n    {\n        if ((pft->dwHighDateTime < UNIX_TIME_ZERO_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_ZERO_HI) &&\n             (pft->dwLowDateTime < UNIX_TIME_ZERO_LO))) {\n            *ut = (time_t)0;\n            return FALSE;\n        }\n        if ((pft->dwHighDateTime > UNIX_TIME_UMAX_HI) ||\n            ((pft->dwHighDateTime == UNIX_TIME_UMAX_HI) &&\n             (pft->dwLowDateTime > UNIX_TIME_UMAX_LO))) {\n            *ut = (time_t)ULONG_MAX;\n            return FALSE;\n        }\n    }\n    ltm.tm_year = w32tm.wYear - 1900;\n    ltm.tm_mon = w32tm.wMonth - 1;\n    ltm.tm_mday = w32tm.wDay;\n    ltm.tm_hour = w32tm.wHour;\n    ltm.tm_min = w32tm.wMinute;\n    ltm.tm_sec = w32tm.wSecond;\n    ltm.tm_isdst = -1;  /* let mktime determine if DST is in effect */\n    *ut = mktime(&ltm);\n\n    /* a cheap error check: mktime returns \"(time_t)-1L\" on conversion errors.\n     * Normally, we would have to apply a consistency check because \"-1\"\n     * could also be a valid time. But, it is quite unlikely to read back odd\n     * time numbers from file systems that store time stamps in DOS format.\n     * (The only known exception is creation time on VFAT partitions.)\n     */\n    return (*ut != (time_t)-1L);\n\n} /* end function VFatFileTime2utime() */\n#endif /* NT_TZBUG_WORKAROUND && W32_STAT_BANDAID */\n\n\n#if 0           /* Currently, this is not used at all */\n\nlong GetTheFileTime(char *name, iztimes *z_ut)\n{\nHANDLE h;\nFILETIME Modft, Accft, Creft, lft;\nWORD dh, dl;\n#ifdef __RSXNT__        /* RSXNT/EMX C rtl uses OEM charset */\n  char *ansi_name = (char *)alloca(strlen(name) + 1);\n\n  OemToAnsi(name, ansi_name);\n  name = ansi_name;\n#endif\n\n  h = CreateFile(name, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,\n                 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\n  if ( h != INVALID_HANDLE_VALUE ) {\n    BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);\n    CloseHandle(h);\n#ifdef USE_EF_UT_TIME\n    if (ftOK && (z_ut != NULL)) {\n      FileTime2utime(&Modft, &(z_ut->mtime));\n      if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n          FileTime2utime(&Accft, &(z_ut->atime));\n      else\n          z_ut->atime = z_ut->mtime;\n      if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n          FileTime2utime(&Creft, &(z_ut->ctime));\n      else\n          z_ut->ctime = z_ut->mtime;\n    }\n#endif\n    FileTimeToLocalFileTime(&ft, &lft);\n    FileTimeToDosDateTime(&lft, &dh, &dl);\n    return(dh<<16) | dl;\n  }\n  else\n    return 0L;\n}\n\n#endif /* never */\n\n\nvoid ChangeNameForFAT(char *name)\n{\n  char *src, *dst, *next, *ptr, *dot, *start;\n  static char invalid[] = \":;,=+\\\"[]<>| \\t\";\n\n  if ( isalpha((uch)name[0]) && (name[1] == ':') )\n    start = name + 2;\n  else\n    start = name;\n\n  src = dst = start;\n  if ( (*src == '/') || (*src == '\\\\') )\n    src++, dst++;\n\n  while ( *src )\n  {\n    for ( next = src; *next && (*next != '/') && (*next != '\\\\'); next++ );\n\n    for ( ptr = src, dot = NULL; ptr < next; ptr++ )\n      if ( *ptr == '.' )\n      {\n        dot = ptr; /* remember last dot */\n        *ptr = '_';\n      }\n\n    if ( dot == NULL )\n      for ( ptr = src; ptr < next; ptr++ )\n        if ( *ptr == '_' )\n          dot = ptr; /* remember last _ as if it were a dot */\n\n    if ( dot && (dot > src) &&\n         ((next - dot <= 4) ||\n          ((next - src > 8) && (dot - src > 3))) )\n    {\n      if ( dot )\n        *dot = '.';\n\n      for ( ptr = src; (ptr < dot) && ((ptr - src) < 8); ptr++ )\n        *dst++ = *ptr;\n\n      for ( ptr = dot; (ptr < next) && ((ptr - dot) < 4); ptr++ )\n        *dst++ = *ptr;\n    }\n    else\n    {\n      if ( dot && (next - src == 1) )\n        *dot = '.';           /* special case: \".\" as a path component */\n\n      for ( ptr = src; (ptr < next) && ((ptr - src) < 8); ptr++ )\n        *dst++ = *ptr;\n    }\n\n    *dst++ = *next; /* either '/' or 0 */\n\n    if ( *next )\n    {\n      src = next + 1;\n\n      if ( *src == 0 ) /* handle trailing '/' on dirs ! */\n        *dst = 0;\n    }\n    else\n      break;\n  }\n\n  for ( src = start; *src != 0; ++src )\n    if ( (strchr(invalid, *src) != NULL) || (*src == ' ') )\n      *src = '_';\n}\n\nchar *GetLongPathEA(char *name)\n{\n    return(NULL); /* volunteers ? */\n}\n\n#ifdef UNICODE_SUPPORT\nwchar_t *GetLongPathEAW(wchar_t *name)\n{\n    return(NULL); /* volunteers ? */\n}\n#endif\n\n\nint IsFileNameValid(x)\nchar *x;\n{\n    WIN32_FIND_DATA fd;\n    HANDLE h;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n    char *ansi_name = (char *)alloca(strlen(x) + 1);\n\n    OemToAnsi(x, ansi_name);\n    x = ansi_name;\n#endif\n\n    if ((h = FindFirstFile(x, &fd)) == INVALID_HANDLE_VALUE)\n        return FALSE;\n    FindClose(h);\n    return TRUE;\n}\n\nchar *getVolumeLabel(drive, vtime, vmode, vutim)\n  int drive;    /* drive name: 'A' .. 'Z' or '\\0' for current drive */\n  ulg *vtime;   /* volume label creation time (DOS format) */\n  ulg *vmode;   /* volume label file mode */\n  time_t *vutim;/* volume label creationtime (UNIX format) */\n\n/* If a volume label exists for the given drive, return its name and\n   pretend to set its time and mode. The returned name is static data. */\n{\n  char rootpath[4];\n  static char vol[14];\n  DWORD fnlen, flags;\n\n  *vmode = A_ARCHIVE | A_LABEL;           /* this is what msdos returns */\n  *vtime = dostime(1980, 1, 1, 0, 0, 0);  /* no true date info available */\n  *vutim = dos2unixtime(*vtime);\n  strcpy(rootpath, \"x:\\\\\");\n  rootpath[0] = (char)drive;\n  if (GetVolumeInformation(drive ? rootpath : NULL, vol, 13, NULL,\n                           &fnlen, &flags, NULL, 0))\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n    return (AnsiToOem(vol, vol), vol);\n#else\n    return vol;\n#endif\n  else\n    return NULL;\n}\n\n#endif /* !UTIL */\n\n\n\nint ZipIsWinNT(void)    /* returns TRUE if real NT, FALSE if Win95 or Win32s */\n{\n    static DWORD g_PlatformId = 0xFFFFFFFF; /* saved platform indicator */\n\n    if (g_PlatformId == 0xFFFFFFFF) {\n        /* note: GetVersionEx() doesn't exist on WinNT 3.1 */\n        if (GetVersion() < 0x80000000)\n            g_PlatformId = TRUE;\n        else\n            g_PlatformId = FALSE;\n    }\n    return (int)g_PlatformId;\n}\n\n\n#ifndef UTIL\n#ifdef __WATCOMC__\n#  include <io.h>\n#  define _get_osfhandle _os_handle\n/* gaah -- Watcom's docs claim that _get_osfhandle exists, but it doesn't.  */\n#endif\n\n#ifdef HAVE_FSEEKABLE\n/*\n * return TRUE if file is seekable\n */\nint fseekable(fp)\nFILE *fp;\n{\n    return GetFileType((HANDLE)_get_osfhandle(fileno(fp))) == FILE_TYPE_DISK;\n}\n#endif /* HAVE_FSEEKABLE */\n#endif /* !UTIL */\n\n\n#if 0 /* seems to be never used; try it out... */\nchar *StringLower(char *szArg)\n{\n  char *szPtr;\n/*  unsigned char *szPtr; */\n  for ( szPtr = szArg; *szPtr; szPtr++ )\n    *szPtr = lower[*szPtr];\n  return szArg;\n}\n#endif /* never */\n\n\n\n#ifdef W32_STAT_BANDAID\n\n/* All currently known variants of WIN32 operating systems (Windows 95/98,\n * WinNT 3.x, 4.0, 5.0) have a nasty bug in the OS kernel concerning\n * conversions between UTC and local time: In the time conversion functions\n * of the Win32 API, the timezone offset (including seasonal daylight saving\n * shift) between UTC and local time evaluation is erratically based on the\n * current system time. The correct evaluation must determine the offset\n * value as it {was/is/will be} for the actual time to be converted.\n *\n * The C runtime lib's stat() returns utc time-stamps so that\n * localtime(timestamp) corresponds to the (potentially false) local\n * time shown by the OS' system programs (Explorer, command shell dir, etc.)\n *\n * For the NTFS file system (and other filesystems that store time-stamps\n * as UTC values), this results in st_mtime (, st_{c|a}time) fields which\n * are not stable but vary according to the seasonal change of \"daylight\n * saving time in effect / not in effect\".\n *\n * To achieve timestamp consistency of UTC (UT extra field) values in\n * Zip archives, the Info-ZIP programs require work-around code for\n * proper time handling in stat() (and other time handling routines).\n */\n/* stat() functions under Windows95 tend to fail for root directories.   *\n * Watcom and Borland, at least, are affected by this bug.  Watcom made  *\n * a partial fix for 11.0 but still missed some cases.  This substitute  *\n * detects the case and fills in reasonable values.  Otherwise we get    *\n * effects like failure to extract to a root dir because it's not found. */\n\n#ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/03 */\n int zstat_zipwin32(const char *path, z_stat *buf)\n#else\n int zstat_zipwin32(const char *path, struct stat *buf)\n#endif\n{\n# ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/03 */\n    if (!zstat(path, buf))\n# else\n    if (!stat(path, buf))\n# endif\n    {\n#ifdef NT_TZBUG_WORKAROUND\n        /* stat was successful, now redo the time-stamp fetches */\n        int fs_uses_loctime = FSusesLocalTime(path);\n        HANDLE h;\n        FILETIME Modft, Accft, Creft;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(path) + 1);\n\n        OemToAnsi(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  path\n#endif\n\n        Trace((stdout, \"stat(%s) finds modtime %08lx\\n\", path, buf->st_mtime));\n        h = CreateFile(Ansi_Path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,\n                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\n        if (h != INVALID_HANDLE_VALUE) {\n            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);\n            CloseHandle(h);\n\n            if (ftOK) {\n                if (!fs_uses_loctime) {\n                    /*  On a filesystem that stores UTC timestamps, we refill\n                     *  the time fields of the struct stat buffer by directly\n                     *  using the UTC values as returned by the Win32\n                     *  GetFileTime() API call.\n                     */\n                    FileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        FileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        FileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    Tracev((stdout,\"NTFS, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                } else {\n                    /*  On VFAT and FAT-like filesystems, the FILETIME values\n                     *  are converted back to the stable local time before\n                     *  converting them to UTC unix time-stamps.\n                     */\n                    VFatFileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    Tracev((stdout, \"VFAT, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                }\n            }\n        }\n#       undef Ansi_Path\n#endif /* NT_TZBUG_WORKAROUND */\n        return 0;\n    }\n#ifdef W32_STATROOT_FIX\n    else\n    {\n        DWORD flags;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(path) + 1);\n\n        OemToAnsi(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  path\n#endif\n\n        flags = GetFileAttributes(Ansi_Path);\n        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {\n            Trace((stderr, \"\\nstat(\\\"%s\\\",...) failed on existing directory\\n\",\n                   path));\n#ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/03 */\n            memset(buf, 0, sizeof(z_stat));\n#else\n            memset(buf, 0, sizeof(struct stat));\n#endif\n            buf->st_atime = buf->st_ctime = buf->st_mtime =\n              dos2unixtime(DOSTIME_MINIMUM);\n            /* !!!   you MUST NOT add a cast to the type of \"st_mode\" here;\n             * !!!   different compilers do not agree on the \"st_mode\" size!\n             * !!!   (And, some compiler may not declare the \"mode_t\" type\n             * !!!   identifier, so you cannot use it, either.)\n             */\n            buf->st_mode = S_IFDIR | S_IREAD |\n                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);\n            return 0;\n        } /* assumes: stat() won't fail on non-dirs without good reason */\n#       undef Ansi_Path\n    }\n#endif /* W32_STATROOT_FIX */\n    return -1;\n}\n\n\n# ifdef UNICODE_SUPPORT\n\nint zstat_zipwin32w(const wchar_t *pathw, zw_stat *buf)\n{\n    if (!zwstat(pathw, buf))\n    {\n#ifdef NT_TZBUG_WORKAROUND\n        /* stat was successful, now redo the time-stamp fetches */\n        int fs_uses_loctime = FSusesLocalTimeW(pathw);\n        HANDLE h;\n        FILETIME Modft, Accft, Creft;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(pathw) + 1);\n\n        OemToAnsi(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  pathw\n#endif\n\n        Trace((stdout, \"stat(%s) finds modtime %08lx\\n\", pathw, buf->st_mtime));\n        h = CreateFileW(Ansi_Path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,\n                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);\n        if (h != INVALID_HANDLE_VALUE) {\n            BOOL ftOK = GetFileTime(h, &Creft, &Accft, &Modft);\n            CloseHandle(h);\n\n            if (ftOK) {\n                if (!fs_uses_loctime) {\n                    /*  On a filesystem that stores UTC timestamps, we refill\n                     *  the time fields of the struct stat buffer by directly\n                     *  using the UTC values as returned by the Win32\n                     *  GetFileTime() API call.\n                     */\n                    FileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        FileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        FileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    Tracev((stdout,\"NTFS, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                } else {\n                    /*  On VFAT and FAT-like filesystems, the FILETIME values\n                     *  are converted back to the stable local time before\n                     *  converting them to UTC unix time-stamps.\n                     */\n                    VFatFileTime2utime(&Modft, &(buf->st_mtime));\n                    if (Accft.dwLowDateTime != 0 || Accft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Accft, &(buf->st_atime));\n                    else\n                        buf->st_atime = buf->st_mtime;\n                    if (Creft.dwLowDateTime != 0 || Creft.dwHighDateTime != 0)\n                        VFatFileTime2utime(&Creft, &(buf->st_ctime));\n                    else\n                        buf->st_ctime = buf->st_mtime;\n                    Tracev((stdout, \"VFAT, recalculated modtime %08lx\\n\",\n                            buf->st_mtime));\n                }\n            }\n        }\n#       undef Ansi_Path\n#endif /* NT_TZBUG_WORKAROUND */\n        return 0;\n    }\n#ifdef W32_STATROOT_FIX\n    else\n    {\n        DWORD flags;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n        char *ansi_path = (char *)alloca(strlen(pathw) + 1);\n\n        OemToAnsi(path, ansi_path);\n#       define Ansi_Path  ansi_path\n#else\n#       define Ansi_Path  pathw\n#endif\n\n        flags = GetFileAttributesW(Ansi_Path);\n        if (flags != 0xFFFFFFFF && flags & FILE_ATTRIBUTE_DIRECTORY) {\n            Trace((stderr, \"\\nstat(\\\"%s\\\",...) failed on existing directory\\n\",\n                   pathw));\n#ifdef LARGE_FILE_SUPPORT         /* E. Gordon 9/12/03 */\n            memset(buf, 0, sizeof(z_stat));\n#else\n            memset(buf, 0, sizeof(struct stat));\n#endif\n            buf->st_atime = buf->st_ctime = buf->st_mtime =\n              dos2unixtime(DOSTIME_MINIMUM);\n            /* !!!   you MUST NOT add a cast to the type of \"st_mode\" here;\n             * !!!   different compilers do not agree on the \"st_mode\" size!\n             * !!!   (And, some compiler may not declare the \"mode_t\" type\n             * !!!   identifier, so you cannot use it, either.)\n             */\n            buf->st_mode = S_IFDIR | S_IREAD |\n                           ((flags & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE);\n            return 0;\n        } /* assumes: stat() won't fail on non-dirs without good reason */\n#       undef Ansi_Path\n    }\n#endif /* W32_STATROOT_FIX */\n    return -1;\n}\n\n# endif\n\n\n#endif /* W32_STAT_BANDAID */\n\n\n\n#ifdef W32_USE_IZ_TIMEZONE\n#include \"timezone.h\"\n#define SECSPERMIN      60\n#define MINSPERHOUR     60\n#define SECSPERHOUR     (SECSPERMIN * MINSPERHOUR)\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule);\n\nstatic void conv_to_rule(LPSYSTEMTIME lpw32tm, struct rule * ZCONST ptrule)\n{\n    if (lpw32tm->wYear != 0) {\n        ptrule->r_type = JULIAN_DAY;\n        ptrule->r_day = ydays[lpw32tm->wMonth - 1] + lpw32tm->wDay;\n    } else {\n        ptrule->r_type = MONTH_NTH_DAY_OF_WEEK;\n        ptrule->r_mon = lpw32tm->wMonth;\n        ptrule->r_day = lpw32tm->wDayOfWeek;\n        ptrule->r_week = lpw32tm->wDay;\n    }\n    ptrule->r_time = (long)lpw32tm->wHour * SECSPERHOUR +\n                     (long)(lpw32tm->wMinute * SECSPERMIN) +\n                     (long)lpw32tm->wSecond;\n}\n\nint GetPlatformLocalTimezone(register struct state * ZCONST sp,\n        void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,\n                                        ZCONST struct rule * ZCONST start,\n                                        ZCONST struct rule * ZCONST end))\n{\n    TIME_ZONE_INFORMATION tzinfo;\n    DWORD res;\n\n    /* read current timezone settings from registry if TZ envvar missing */\n    res = GetTimeZoneInformation(&tzinfo);\n    if (res != TIME_ZONE_ID_INVALID)\n    {\n        struct rule startrule, stoprule;\n\n        conv_to_rule(&(tzinfo.StandardDate), &stoprule);\n        conv_to_rule(&(tzinfo.DaylightDate), &startrule);\n        sp->timecnt = 0;\n        sp->ttis[0].tt_abbrind = 0;\n        if ((sp->charcnt =\n             WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1,\n                                 sp->chars, sizeof(sp->chars), NULL, NULL))\n            == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[1].tt_abbrind = sp->charcnt;\n        sp->charcnt +=\n            WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1,\n                                sp->chars + sp->charcnt,\n                                sizeof(sp->chars) - sp->charcnt, NULL, NULL);\n        if ((sp->charcnt - sp->ttis[1].tt_abbrind) == 0)\n            sp->chars[sp->charcnt++] = '\\0';\n        sp->ttis[0].tt_gmtoff = - (tzinfo.Bias + tzinfo.StandardBias)\n                                * MINSPERHOUR;\n        sp->ttis[1].tt_gmtoff = - (tzinfo.Bias + tzinfo.DaylightBias)\n                                * MINSPERHOUR;\n        sp->ttis[0].tt_isdst = 0;\n        sp->ttis[1].tt_isdst = 1;\n        sp->typecnt = (startrule.r_mon == 0 && stoprule.r_mon == 0) ? 1 : 2;\n\n        if (sp->typecnt > 1)\n            (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);\n        return TRUE;\n    }\n    return FALSE;\n}\n#endif /* W32_USE_IZ_TIMEZONE */\n\n\n\n#ifndef WINDLL\n/* This replacement getch() function was originally created for Watcom C\n * and then additionally used with CYGWIN. Since UnZip 5.4, all other Win32\n * ports apply this replacement rather that their supplied getch() (or\n * alike) function.  There are problems with unabsorbed LF characters left\n * over in the keyboard buffer under Win95 (and 98) when ENTER was pressed.\n * (Under Win95, ENTER returns two(!!) characters: CR-LF.)  This problem\n * does not appear when run on a WinNT console prompt!\n */\n\n/* Watcom 10.6's getch() does not handle Alt+<digit><digit><digit>. */\n/* Note that if PASSWD_FROM_STDIN is defined, the file containing   */\n/* the password must have a carriage return after the word, not a   */\n/* Unix-style newline (linefeed only).  This discards linefeeds.    */\n\nint getch_win32(void)\n{\n  HANDLE stin;\n  DWORD rc;\n  unsigned char buf[2];\n  int ret = -1;\n  DWORD odemode = ~(DWORD)0;\n\n#  ifdef PASSWD_FROM_STDIN\n  stin = GetStdHandle(STD_INPUT_HANDLE);\n#  else\n  stin = CreateFile(\"CONIN$\", GENERIC_READ | GENERIC_WRITE,\n                    FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\n  if (stin == INVALID_HANDLE_VALUE)\n    return -1;\n#  endif\n  if (GetConsoleMode(stin, &odemode))\n    SetConsoleMode(stin, ENABLE_PROCESSED_INPUT);  /* raw except ^C noticed */\n  if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)\n    ret = buf[0];\n  /* when the user hits return we get CR LF.  We discard the LF, not the CR,\n   * because when we call this for the first time after a previous input\n   * such as the one for \"replace foo? [y]es, ...\" the LF may still be in\n   * the input stream before whatever the user types at our prompt. */\n  if (ret == '\\n')\n    if (ReadFile(stin, &buf, 1, &rc, NULL) && rc == 1)\n      ret = buf[0];\n  if (odemode != ~(DWORD)0)\n    SetConsoleMode(stin, odemode);\n#  ifndef PASSWD_FROM_STDIN\n  CloseHandle(stin);\n#  endif\n  return ret;\n}\n\n\n\n/******************************/\n/*  Function version_local()  */\n/******************************/\n\nvoid version_local()\n{\n    static ZCONST char CompiledWith[] = \"Compiled with %s%s for %s%s%s.\\n\\n\";\n#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DJGPP__))\n    char buf[80];\n#if (defined(_MSC_VER) && (_MSC_VER > 900))\n    char buf2[80];\n#endif\n#endif\n\n/* Define the compiler name and version strings */\n#if defined(_MSC_VER)  /* MSC == MSVC++, including the SDK compiler */\n    sprintf(buf, \"Microsoft C %d.%02d \", _MSC_VER/100, _MSC_VER%100);\n#  define COMPILER_NAME1        buf\n#  if (_MSC_VER == 800)\n#    define COMPILER_NAME2      \"(Visual C++ v1.1)\"\n#  elif (_MSC_VER == 850)\n#    define COMPILER_NAME2      \"(Windows NT v3.5 SDK)\"\n#  elif (_MSC_VER == 900)\n#    define COMPILER_NAME2      \"(Visual C++ v2.x)\"\n#  elif (_MSC_VER > 900)\n    sprintf(buf2, \"(Visual C++ v%d.%d)\", _MSC_VER/100 - 6, _MSC_VER%100/10);\n#    define COMPILER_NAME2      buf2\n#  else\n#    define COMPILER_NAME2      \"(bad version)\"\n#  endif\n#elif defined(__WATCOMC__)\n#  if (__WATCOMC__ % 10 > 0)\n/* We do this silly test because __WATCOMC__ gives two digits for the  */\n/* minor version, but Watcom packaging prefers to show only one digit. */\n    sprintf(buf, \"Watcom C/C++ %d.%02d\", __WATCOMC__ / 100,\n            __WATCOMC__ % 100);\n#  else\n    sprintf(buf, \"Watcom C/C++ %d.%d\", __WATCOMC__ / 100,\n            (__WATCOMC__ % 100) / 10);\n#  endif /* __WATCOMC__ % 10 > 0 */\n#  define COMPILER_NAME1        buf\n#  define COMPILER_NAME2        \"\"\n#elif defined(__TURBOC__)\n#  ifdef __BORLANDC__\n#    define COMPILER_NAME1      \"Borland C++\"\n#    if (__BORLANDC__ == 0x0452)   /* __BCPLUSPLUS__ = 0x0320 */\n#      define COMPILER_NAME2    \" 4.0 or 4.02\"\n#    elif (__BORLANDC__ == 0x0460)   /* __BCPLUSPLUS__ = 0x0340 */\n#      define COMPILER_NAME2    \" 4.5\"\n#    elif (__BORLANDC__ == 0x0500)   /* __TURBOC__ = 0x0500 */\n#      define COMPILER_NAME2    \" 5.0\"\n#    elif (__BORLANDC__ == 0x0520)   /* __TURBOC__ = 0x0520 */\n#      define COMPILER_NAME2    \" 5.2 (C++ Builder 1.0)\"\n#    elif (__BORLANDC__ == 0x0530)   /* __BCPLUSPLUS__ = 0x0530 */\n#      define COMPILER_NAME2    \" 5.3 (C++ Builder 3.0)\"\n#    elif (__BORLANDC__ == 0x0540)   /* __BCPLUSPLUS__ = 0x0540 */\n#      define COMPILER_NAME2    \" 5.4 (C++ Builder 4.0)\"\n#    elif (__BORLANDC__ == 0x0550)   /* __BCPLUSPLUS__ = 0x0550 */\n#      define COMPILER_NAME2    \" 5.5 (C++ Builder 5.0)\"\n#    elif (__BORLANDC__ == 0x0551)   /* __BCPLUSPLUS__ = 0x0551 */\n#      define COMPILER_NAME2    \" 5.5.1 (C++ Builder 5.0.1)\"\n#    elif (__BORLANDC__ == 0x0560)   /* __BCPLUSPLUS__ = 0x0560 */\n#      define COMPILER_NAME2    \" 5.6 (C++ Builder 6)\"\n#    else\n#      define COMPILER_NAME2    \" later than 5.6\"\n#    endif\n#  else /* !__BORLANDC__ */\n#    define COMPILER_NAME1      \"Turbo C\"\n#    if (__TURBOC__ >= 0x0400)     /* Kevin:  3.0 -> 0x0401 */\n#      define COMPILER_NAME2    \"++ 3.0 or later\"\n#    elif (__TURBOC__ == 0x0295)     /* [661] vfy'd by Kevin */\n#      define COMPILER_NAME2    \"++ 1.0\"\n#    endif\n#  endif /* __BORLANDC__ */\n#elif defined(__GNUC__)\n#  ifdef __RSXNT__\n#    if (defined(__DJGPP__) && !defined(__EMX__))\n    sprintf(buf, \"rsxnt(djgpp v%d.%02d) / gcc \",\n            __DJGPP__, __DJGPP_MINOR__);\n#      define COMPILER_NAME1    buf\n#    elif defined(__DJGPP__)\n   sprintf(buf, \"rsxnt(emx+djgpp v%d.%02d) / gcc \",\n            __DJGPP__, __DJGPP_MINOR__);\n#      define COMPILER_NAME1    buf\n#    elif (defined(__GO32__) && !defined(__EMX__))\n#      define COMPILER_NAME1    \"rsxnt(djgpp v1.x) / gcc \"\n#    elif defined(__GO32__)\n#      define COMPILER_NAME1    \"rsxnt(emx + djgpp v1.x) / gcc \"\n#    elif defined(__EMX__)\n#      define COMPILER_NAME1    \"rsxnt(emx)+gcc \"\n#    else\n#      define COMPILER_NAME1    \"rsxnt(unknown) / gcc \"\n#    endif\n#  elif defined(__CYGWIN__)\n#      define COMPILER_NAME1    \"Cygnus win32 / gcc \"\n#  elif defined(__MINGW32__)\n#      define COMPILER_NAME1    \"mingw32 / gcc \"\n#  else\n#      define COMPILER_NAME1    \"gcc \"\n#  endif\n#  define COMPILER_NAME2        __VERSION__\n#elif defined(__LCC__)\n#  define COMPILER_NAME1        \"LCC-Win32\"\n#  define COMPILER_NAME2        \"\"\n#else\n#  define COMPILER_NAME1        \"unknown compiler (SDK?)\"\n#  define COMPILER_NAME2        \"\"\n#endif\n\n/* Define the compile date string */\n#ifdef __DATE__\n#  define COMPILE_DATE \" on \" __DATE__\n#else\n#  define COMPILE_DATE \"\"\n#endif\n\n    printf(CompiledWith, COMPILER_NAME1, COMPILER_NAME2,\n           \"\\nWindows 9x / Windows NT\", \" (32-bit)\", COMPILE_DATE);\n\n    return;\n\n} /* end function version_local() */\n#endif /* !WINDLL */\n\n\n/* --------------------------------------------------- */\n/* Large File Support\n *\n * Moved to Win32i64.c to avoid conflicts in same name functions\n * in WiZ using UnZip and Zip libraries.\n * 9/25/2003\n */\n\n\n/* --------------------------------------------------- */\n/* Unicode Support for Win32\n *\n */\n\n#ifdef UNICODE_SUPPORT\n# if 0\n\n  /* get the wide command line and convert to argvw */\n  /* windows ignores argv and gets argvw separately */\n  zchar **get_wide_argv(argv)\n    char **argv;\n  {\n    int i;\n    int argc;\n    int size;\n    zchar **argvw = NULL;\n    zchar *commandline = NULL;\n    zchar **a = NULL;\n\n    commandline = GetCommandLineW();\n    a = CommandLineToArgvW(commandline, &argc);\n\n    if (a == NULL) {\n      /* failed */\n      ZIPERR(ZE_COMPERR, \"get_wide_argv\");\n    }\n\n    /* copy args so can use free_args() */\n    if ((argvw = (zchar **)malloc((argc + 1) * sizeof(zchar *))) == NULL) {\n      ZIPERR(ZE_MEM, \"get_wide_argv\");\n    }\n    for (i = 0; i < argc; i++) {\n      size = zstrlen(a[i]) + 1;\n      if ((argvw[i] = (zchar *)malloc(size * sizeof(zchar))) == NULL) {\n        ZIPERR(ZE_MEM, \"get_wide_argv\");\n      }\n      if ((argvw[i] = copy_zstring(a[i])) == NULL) {\n        ZIPERR(ZE_MEM, \"get_wide_argv\");\n      }\n    }\n    argvw[argc] = L'\\0';\n\n    /* free original argvw */\n    LocalFree(a);\n\n    return argvw;\n  }\n# endif\n\n\n/* convert wide character string to multi-byte character string */\n/* win32 version */\nchar *wide_to_local_string(wide_string)\n  zwchar *wide_string;\n{\n  int i;\n  wchar_t wc;\n  int bytes_char;\n  int default_used;\n  int wsize = 0;\n  int max_bytes = 9;\n  char buf[9];\n  char *buffer = NULL;\n  char *local_string = NULL;\n\n  if (wide_string == NULL)\n    return NULL;\n\n  for (wsize = 0; wide_string[wsize]; wsize++) ;\n\n  if (max_bytes < MB_CUR_MAX)\n    max_bytes = MB_CUR_MAX;\n\n  if ((buffer = (char *)malloc(wsize * max_bytes + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"wide_to_local_string\");\n  }\n\n  /* convert it */\n  buffer[0] = '\\0';\n  for (i = 0; i < wsize; i++) {\n    if (sizeof(wchar_t) < 4 && wide_string[i] > 0xFFFF) {\n      /* wchar_t probably 2 bytes */\n      /* could do surrogates if state_dependent and wctomb can do */\n      wc = zwchar_to_wchar_t_default_char;\n    } else {\n      wc = (wchar_t)wide_string[i];\n    }\n    /* Unter some vendor's C-RTL, the Wide-to-MultiByte conversion functions\n     * (like wctomb() et. al.) do not use the same codepage as the other\n     * string arguments I/O functions (fopen, mkdir, rmdir etc.).\n     * Therefore, we have to fall back to the underlying Win32-API call to\n     * achieve a consistent behaviour for all supported compiler environments.\n     * Failing RTLs are for example:\n     *   Borland (locale uses OEM-CP as default, but I/O functions expect ANSI\n     *            names)\n     *   Watcom  (only \"C\" locale, wctomb() always uses OEM CP)\n     * (in other words: all supported environments except the Microsoft RTLs)\n     */\n    bytes_char = WideCharToMultiByte(\n                          CP_ACP, WC_COMPOSITECHECK,\n                          &wc, 1,\n                          (LPSTR)buf, sizeof(buf),\n                          NULL, &default_used);\n    if (default_used)\n      bytes_char = -1;\n    if (unicode_escape_all) {\n      if (bytes_char == 1 && (uch)buf[0] <= 0x7f) {\n        /* ASCII */\n        strncat(buffer, buf, 1);\n      } else {\n        /* use escape for wide character */\n        char *e = wide_char_to_escape_string(wide_string[i]);\n        strcat(buffer, e);\n        free(e);\n      }\n    } else if (bytes_char > 0) {\n      /* multi-byte char */\n      strncat(buffer, buf, bytes_char);\n    } else {\n      /* no MB for this wide */\n      if (use_wide_to_mb_default) {\n        /* default character */\n        strcat(buffer, wide_to_mb_default_string);\n      } else {\n        /* use escape for wide character */\n        char *e = wide_char_to_escape_string(wide_string[i]);\n        strcat(buffer, e);\n        free(e);\n      }\n    }\n  }\n  if ((local_string = (char *)realloc(buffer, strlen(buffer) + 1)) == NULL) {\n    free(buffer);\n    ZIPERR(ZE_MEM, \"wide_to_local_string\");\n  }\n\n  return local_string;\n}\n\n/* convert multi-byte character string to wide character string */\n/* win32 version */\nzwchar *local_to_wide_string(local_string)\n  char *local_string;\n{\n  int wsize;\n  wchar_t *wc_string;\n  zwchar *wide_string;\n\n  /* for now try to convert as string - fails if a bad char in string */\n  wsize = MultiByteToWideChar(CP_ACP, 0,\n                        local_string, -1, NULL, 0);\n  if (wsize == (size_t)-1) {\n    /* could not convert */\n    return NULL;\n  }\n\n  /* convert it */\n  if ((wc_string = (wchar_t *)malloc((wsize + 1) * sizeof(wchar_t))) == NULL) {\n    ZIPERR(ZE_MEM, \"local_to_wide_string\");\n  }\n  wsize = MultiByteToWideChar(CP_ACP, 0,\n           local_string, -1,\n           wc_string, wsize + 1);\n  wc_string[wsize] = (wchar_t) 0;\n\n  /* in case wchar_t is not zwchar */\n  if ((wide_string = (zwchar *)malloc((wsize + 1) * sizeof(zwchar))) == NULL) {\n    free(wc_string);\n    ZIPERR(ZE_MEM, \"local_to_wide_string\");\n  }\n  for (wsize = 0; (wide_string[wsize] = (zwchar)wc_string[wsize]); wsize++) ;\n  wide_string[wsize] = (zwchar)0;\n  free(wc_string);\n\n  return wide_string;\n}\n#endif /* UNICODE_SUPPORT */\n\n\n/*\n# if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)\n*/\n/* convert oem to ansi character string */\nchar *oem_to_local_string(local_string, oem_string)\n  char *local_string;\n  char *oem_string;\n{\n  /* convert OEM to ANSI character set */\n  OemToChar(oem_string, local_string);\n\n  return local_string;\n}\n/*\n# endif\n*/\n\n\n/*\n#if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)\n*/\n/* convert local to oem character string */\nchar *local_to_oem_string(oem_string, local_string)\n  char *oem_string;\n  char *local_string;\n{\n  /* convert to OEM display character set */\n  CharToOem(local_string, oem_string);\n  return oem_string;\n}\n/*\n#endif\n*/\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/win32i64.c",
    "content": "/*\n  win32/win32i64.c - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2005-Feb-10 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n\n#include \"../zip.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <limits.h>\n#include <time.h>\n#include <ctype.h>\n#ifdef CR\n#undef CR\n#endif\n#include <windows.h>\n/* for LARGE_FILE_SUPPORT but may not be needed */\n#include <io.h>\n\n\n/* --------------------------------------------------- */\n/* Large File Support\n *\n * Initial functions by E. Gordon and R. Nausedat\n * 9/10/2003\n *\n * These implement 64-bit file support for Windows.  The\n * defines and headers are in win32/osdep.h.\n *\n * These moved from win32.c by Mike White to avoid conflicts\n * in WiZ of same name functions in UnZip and Zip libraries.\n * 9/25/04 EG\n */\n\n#if defined(LARGE_FILE_SUPPORT) && !defined(__CYGWIN__)\n\n/* 64-bit buffered ftello\n *\n * Win32 does not provide a 64-bit buffered\n * ftell (in the published api anyway) so below provides\n * hopefully close version.\n * We have not gotten _telli64 to work with buffered\n * streams.  Below cheats by using fgetpos improperly and\n * may not work on other ports.\n */\n\nzoff_t zftello(stream)\n  FILE *stream;\n{\n  fpos_t fpos = 0;\n  \n  if (fgetpos(stream, &fpos) != 0) {\n    return -1L;\n  } else {\n    return fpos;\n  }\n}\n\n\n/* 64-bit buffered fseeko\n *\n * Win32 does not provide a 64-bit buffered\n * fseeko so use _lseeki64 and fflush.  Note\n * that SEEK_CUR can lose track of location\n * if fflush is done between the last buffered\n * io and this call.\n */\n\nint zfseeko(stream, offset, origin)\n  FILE *stream;\n  zoff_t offset;\n  int origin;\n{\n  zoff_t location;\n\n  location = zftello(stream);\n  fflush(stream);\n  if (origin == SEEK_CUR) {\n    /* instead of synching up lseek easier just to figure and\n       use an absolute offset */\n    offset = location + offset;\n    location = _lseeki64(fileno(stream), offset, SEEK_SET);\n  } else {\n    location = _lseeki64(fileno(stream), offset, origin);\n  }\n  if (location == -1L) {\n    return -1L;\n  } else {\n    return 0;\n  }\n}\n#endif  /* Win32 LARGE_FILE_SUPPORT */\n\n#if 0\nFILE* zfopen(filename,mode)\nchar *filename;\nchar *mode;\n{\nFILE* fTemp;\n  \n  fTemp = fopen(filename,mode);\n  if( fTemp == NULL )\n    return NULL;\n  \n  /* sorry, could not make VC60 and its rtl work properly without setting the file buffer to NULL. the  */\n  /* problem seems to be _telli64 which seems to return the max stream position, comments are welcome   */\n  setbuf(fTemp,NULL);\n\n  return fTemp;\n}\n#endif\n/* --------------------------------------------------- */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/win32zip.c",
    "content": "/*\n  win32/win32zip.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef UTIL    /* this file contains nothing used by UTIL */\n\n#include \"../zip.h\"\n\n#include <ctype.h>\n#if !defined(__EMX__) && !defined(__CYGWIN__)\n#include <direct.h>     /* for rmdir() */\n#endif\n#include <time.h>\n\n#ifndef __BORLANDC__\n#include <sys/utime.h>\n#else\n#include <utime.h>\n#endif\n#define WIN32_LEAN_AND_MEAN\n#ifdef CR\n#undef CR\n#endif\n#include <windows.h> /* for findfirst/findnext stuff */\n#ifdef __RSXNT__\n#  include \"../win32/rsxntwin.h\"\n#endif\n\n#include <io.h>\n\n#define PAD           0\n#define PATH_END      '/'\n#define HIDD_SYS_BITS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)\n\n\n#ifdef UNICODE_SUPPORT\ntypedef struct zdirscanw {\n  HANDLE d_hFindFile;\n  int    d_first;\n  WIN32_FIND_DATAW d_fdw;\n} zDIRSCANW;\n#endif\n\ntypedef struct zdirscan {\n  HANDLE d_hFindFile;\n  int    d_first;\n  WIN32_FIND_DATA d_fd;\n} zDIRSCAN;\n\n#define INVALID_WIN32_FILE_ATTRIBS ~0\n#ifdef UNICODE_SUPPORT\n#define GetDirAttribsW(d)   ((d)->d_fdw.dwFileAttributes)\n#endif\n#define GetDirAttribs(d)   ((d)->d_fd.dwFileAttributes)\n\n#include \"../win32/win32zip.h\"\n#include \"../win32/nt.h\"\n\n/* Local functions */\nlocal zDIRSCAN        * OpenDirScan      OF((ZCONST char *n));\nlocal struct zdirscan * GetNextDirEntry  OF((zDIRSCAN *d));\nlocal void              CloseDirScan     OF((zDIRSCAN *d));\n\n#ifdef UNICODE_SUPPORT\nlocal zDIRSCANW        * OpenDirScanW     OF((ZCONST wchar_t *wn));\nlocal struct zdirscanw * GetNextDirEntryW OF((zDIRSCANW *dw));\nlocal void               CloseDirScanW    OF((zDIRSCANW *dw));\n#endif\n\nlocal char           *readd        OF((zDIRSCAN *));\n#ifdef UNICODE_SUPPORT\nlocal wchar_t        *readdw       OF((zDIRSCANW *));\n#endif\n\nlocal int             wild_recurse OF((char *, char *));\n#ifdef UNICODE_SUPPORT\nlocal int             wild_recursew OF((wchar_t *, wchar_t *));\n#endif\n\n#ifdef NTSD_EAS\n   local void GetSD OF((char *path, char **bufptr, ush *size,\n                        char **cbufptr, ush *csize));\n#endif\n#ifdef USE_EF_UT_TIME\n   local int GetExtraTime OF((struct zlist far *z, iztimes *z_utim));\n#endif\nlocal int procname_win32 OF((char *n, int caseflag, DWORD attribs));\n#ifdef UNICODE_SUPPORT\nlocal int procname_win32w OF((wchar_t *n, int caseflag, DWORD attribs));\n#endif\n\n/* Module level variables */\nextern char *label /* = NULL */ ;       /* defined in fileio.c */\nlocal ulg label_time = 0;\nlocal ulg label_mode = 0;\nlocal time_t label_utim = 0;\n\n/* Module level constants */\nlocal ZCONST char wild_match_all[] = \"*.*\";\n\n\n#ifdef UNICODE_SUPPORT\n\nlocal zDIRSCANW *OpenDirScanW(nw)\nZCONST wchar_t *nw;          /* directory to open */\n/* Start searching for files in the MSDOS directory n */\n{\n  zDIRSCANW *dw;         /* malloc'd return value */\n  wchar_t *pw;              /* malloc'd temporary string */\n  wchar_t *qw;\n  size_t i;\n\n  if ((dw = (zDIRSCANW *)malloc(sizeof(zDIRSCANW))) == NULL) {\n    return NULL;\n  }\n\n  if ((pw = (wchar_t *)malloc(wcslen(nw) * sizeof(wchar_t) +\n      (2 + sizeof(wild_match_all)) * sizeof(wchar_t))) == NULL) {\n    if (dw != NULL) free((zvoid *)dw);\n    return NULL;\n  }\n  wcscpy(pw, nw);\n\n  qw = pw + wcslen(pw);\n  if ((qw - pw) > 0 && wcschr(pw, (wchar_t)':') == (qw - 1))\n      *qw++ = (wchar_t)'.';\n  if ((qw - pw) > 0 && wcschr(pw, (wchar_t)'/') != (qw - 1))\n    *qw++ = (wchar_t)'/';\n\n  for (i = 0; i < strlen(wild_match_all); i++) {\n    qw[i] = (wchar_t)wild_match_all[i];\n  }\n  qw[i] = (wchar_t)'\\0';\n\n  dw->d_hFindFile = FindFirstFileW(pw, &dw->d_fdw);\n  free((zvoid *)pw);\n\n  if (dw->d_hFindFile == INVALID_HANDLE_VALUE)\n  {\n    free((zvoid *)dw);\n    return NULL;\n  }\n\n  dw->d_first = 1;\n  return dw;\n}\n\n#endif\n\nlocal zDIRSCAN *OpenDirScan(n)\nZCONST char *n;          /* directory to open */\n/* Start searching for files in the MSDOS directory n */\n{\n  zDIRSCAN *d;          /* malloc'd return value */\n  char *p;              /* malloc'd temporary string */\n  char *q;\n\n  if ((d = (zDIRSCAN *)malloc(sizeof(zDIRSCAN))) == NULL ||\n      (p = malloc(strlen(n) + (2 + sizeof(wild_match_all)))) == NULL) {\n    if (d != NULL) free((zvoid *)d);\n    return NULL;\n  }\n  strcpy(p, n);\n  q = p + strlen(p);\n  if ((q - p) > 0 && MBSRCHR(p, ':') == (q - 1))\n      *q++ = '.';\n  if ((q - p) > 0 && MBSRCHR(p, '/') != (q - 1))\n    *q++ = '/';\n  strcpy(q, wild_match_all);\n\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  OemToAnsi(p, p);\n#endif\n  d->d_hFindFile = FindFirstFile(p, &d->d_fd);\n  free((zvoid *)p);\n\n  if (d->d_hFindFile == INVALID_HANDLE_VALUE)\n  {\n    free((zvoid *)d);\n    return NULL;\n  }\n\n  d->d_first = 1;\n  return d;\n}\n\n\n#ifdef UNICODE_SUPPORT\n\nlocal struct zdirscanw *GetNextDirEntryW(dw)\nzDIRSCANW *dw;            /* directory stream to read from */\n/* Return pointer to first or next directory entry, or NULL if end. */\n{\n  if (dw->d_first)\n    dw->d_first = 0;\n  else\n  {\n    if (!FindNextFileW(dw->d_hFindFile, &dw->d_fdw))\n        return NULL;\n  }\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  CharToOemW(dw->d_fdw.cFileName, dw->d_fdw.cFileName);\n#endif\n  return (struct zdirscanw *)dw;\n}\n\n#endif\n\nlocal struct zdirscan *GetNextDirEntry(d)\nzDIRSCAN *d;            /* directory stream to read from */\n/* Return pointer to first or next directory entry, or NULL if end. */\n{\n  if (d->d_first)\n    d->d_first = 0;\n  else\n  {\n    if (!FindNextFile(d->d_hFindFile, &d->d_fd))\n        return NULL;\n  }\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  AnsiToOem(d->d_fd.cFileName, d->d_fd.cFileName);\n#endif\n  return (struct zdirscan *)d;\n}\n\nlocal void CloseDirScan(d)\nzDIRSCAN *d;            /* directory stream to close */\n{\n  FindClose(d->d_hFindFile);\n  free((zvoid *)d);\n}\n\n#ifdef UNICODE_SUPPORT\n\nlocal void CloseDirScanW(dw)\nzDIRSCANW *dw;         /* directory stream to close */\n{\n  FindClose(dw->d_hFindFile);\n  free((zvoid *)dw);\n}\n\n#endif\n\n\n#ifdef UNICODE_SUPPORT\n\nlocal wchar_t *readdw(dw)\n  zDIRSCANW *dw;         /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream dw, or NULL if\n   no more entries or an error occurs. */\n{\n  struct zdirscanw *ew;\n\n  do\n    ew = GetNextDirEntryW(dw);\n  while (ew &&\n         ((!hidden_files && ew->d_fdw.dwFileAttributes & HIDD_SYS_BITS) ||\n          (only_archive_set &&\n           !(ew->d_fdw.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) &&\n           !(ew->d_fdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))));\n  if (ew == NULL)\n    return (wchar_t *) NULL;\n  return ew->d_fdw.cFileName;\n}\n\n#endif\n\nlocal char *readd(d)\nzDIRSCAN *d;            /* directory stream to read from */\n/* Return a pointer to the next name in the directory stream d, or NULL if\n   no more entries or an error occurs. */\n{\n  struct zdirscan *e;\n\n  do\n    e = GetNextDirEntry(d);\n  while (e &&\n         ((!hidden_files && e->d_fd.dwFileAttributes & HIDD_SYS_BITS) ||\n          (only_archive_set &&\n           !(e->d_fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) &&\n           !(e->d_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))));\n  /* When a wide character that is not supported by the current character\n     set is found, FindFirstFile and FindNextFile return a \"?\" in that spot.\n     A question mark is illegal in file names, so this flags that something\n     needs to be done.  It seems the fix is to use the 8.3 name in\n     this case, as that allows directory scans to continue.\n   */\n  if (e == NULL)\n    return (char *) NULL;\n  if (strchr(e->d_fd.cFileName, '?') && e->d_fd.cAlternateFileName) {\n    /* Have '?' in name, assume wide character we can't handle is in\n       the name and use short name if there is one.\n    */\n    return e->d_fd.cAlternateFileName;\n  }\n  return e->d_fd.cFileName;\n}\n\n\n#if 0\n/* scan for the file in p and return Windows long name */\nchar *get_win32_longpath(p, n)\n  char *p;               /* path to get short name path for */\n  char **n;              /* pointer to name in returned path */\n{\n  char  *q;              /* return string */\n  char  *c;\n  int    is_dir = 0;\n  char  *f;\n  char  *fp;\n  int    nr;\n  int    fplen;\n  int    fplen2;\n  HANDLE d_hFindFile;\n  WIN32_FIND_DATA d_fd;\n  int slashes = 0;\n  int returnslashes = 0;\n\n  if (p == NULL)\n    return NULL;\n\n  /* count path components */\n  for (f = p; *f; f++) {\n    if (*f == '/' || *f == '\\\\') {\n      slashes++;\n    }\n  }\n  /* Ignore trailing slash */\n  if (*p && (*(f - 1) == '/' || *(f - 1) == '\\\\'))\n    slashes--;\n\n  /* get the length of the full path */\n  fplen = GetFullPathName(p, 0, NULL, NULL);\n\n  if ((fp = malloc(fplen + 1)) == NULL) {\n    return NULL;\n  }\n  /* get full path */\n  fplen2 = GetFullPathName(p, fplen, fp, &f);\n  if (fplen2 > fplen) {\n    /* something changed */\n    free(fp);\n    return NULL;\n  }\n  c = fp + strlen(fp) - 1;\n  if (*c == '\\\\' || *c == '/') {\n    is_dir = 1;\n    *c = '\\0';\n  }\n\n  d_hFindFile = FindFirstFile(fp, &d_fd);\n  free(fp);\n\n  if (d_hFindFile == INVALID_HANDLE_VALUE)\n  {\n    return NULL;\n  }\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  AnsiToOem(d->d_fd.cFileName, d->d_fd.cFileName);\n#endif\n\n  FindClose(d_hFindFile);\n\n  if (d_fd.cFileName == NULL) {\n    return NULL;\n  }\n\n  /* get the length of the full path */\n  fplen = GetFullPathName(d_fd.cFileName, 0, NULL, NULL);\n\n  if ((fp = malloc(fplen + 1)) == NULL) {\n    return NULL;\n  }\n  /* get full path */\n  fplen2 = GetFullPathName(d_fd.cFileName, fplen, fp, &f);\n  if (fplen2 > fplen) {\n    /* something changed */\n    free(fp);\n    return NULL;\n  }\n\n  /* characters from end to start of last component */\n  nr = 0;\n\n  /* find start of relative path we came in with */\n  for (f = fp + strlen(fp); f != fp; f--) {\n    if (*f == ':')\n      break;\n    if (*f == '/' || *f == '\\\\') {\n      returnslashes++;\n      /* convert \\ to / */\n      *f = '/';\n      if (nr == 0)\n        /* first slash from end */\n        nr = strlen(fp) - (f - fp);\n      if (returnslashes > slashes)\n        break;\n    }\n    if (*f == '\\\\' && *(f + 1) == '\\\\')\n      break;\n  }\n  if (f != fp)\n    /* on slash in middle */\n    f++;\n\n  if ((q = malloc(strlen(f) + 2)) == NULL) {\n    return NULL;\n  }\n  strcpy(q, f);\n  *n = q + (strlen(q) - nr + 1);\n  if (is_dir) {\n    strcat(q, \"/\");\n  }\n  free(fp);\n\n  return q;\n}\n#endif\n\n\n#if 0\n/* scan for the file in p and return Windows UTF-8 name */\nchar *get_win32_utf8path(p)\n  char *p;               /* path to get utf-8 name for */\n{\n  char     *q;           /* return string */\n  char     *r = NULL;\n  int       is_dir = 0;\n  char     *f;\n  char     *fcp;\n  char     *fp;\n  wchar_t  *qw;\n  char     *lastc = '\\0';\n  int       fplen;\n  int       fplen2;\n  int       ulen;\n  int       ulenw;\n  HANDLE    d_hFindFile;\n  WIN32_FIND_DATAW d_fd;\n  int pathslashes = 0;\n  int componentslashes = 0;\n  int slashes = 0;\n\n  if (p == NULL)\n    return NULL;\n\n  /* count path components */\n  for (f = p; *f; PREINCSTR(f)) {\n    if (*f == '/' || *f == '\\\\') {\n      slashes++;\n    }\n    lastc = f;\n  }\n  /* do not count trailing / */\n  if (*lastc == '/' || *lastc == '\\\\') {\n    is_dir = 1;\n    slashes--;\n  }\n\n  /* Get the short path (as a bad long path could cause FindFirstFile to fail) */\n\n  /* get the length of the short path */\n  fplen = GetShortPathName(p, NULL, 0);\n\n  if ((fp = malloc(fplen + 1)) == NULL) {\n    return NULL;\n  }\n  /* get short path */\n  fplen2 = GetShortPathName(p, fp, fplen);\n  if (fplen2 > fplen) {\n    /* something changed */\n    free(fp);\n    return NULL;\n  }\n\n  for (pathslashes = 0; pathslashes <= slashes; pathslashes++)\n  {\n\n    /* get component path */\n    if ((fcp = malloc(fplen + 1)) == NULL) {\n      return NULL;\n    }\n    strcpy(fcp, fp);\n    componentslashes = 0;\n    for (f = fcp; *f; PREINCSTR(f)) {\n      if (*f == '/' || *f == '\\\\') {\n        componentslashes++;\n        if (componentslashes > pathslashes)\n          break;\n      }\n      lastc = f;\n    }\n    *f = '\\0';\n\n\n    /* Get information for the file, including wide path */\n\n    /* get length */\n    ulenw = MultiByteToWideChar(\n                CP_ACP,            /* ANSI code page */\n                0,                 /* flags for character-type options */\n                fcp,               /* string to convert */\n                -1,                /* string length (-1 = NULL terminated) */\n                NULL,              /* buffer */\n                0 );               /* buffer length (0 = return length) */\n    if (ulenw == 0) {\n      /* failed */\n      free(fcp);\n      free(fp);\n      return NULL;\n    }\n    ulenw++;\n    /* get length in bytes */\n    ulen = sizeof(wchar_t) * (ulenw + 1);\n    if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {\n      free(fcp);\n      free(fp);\n      return NULL;\n    }\n    /* convert multibyte to wide */\n    ulen = MultiByteToWideChar(\n               CP_ACP,            /* ANSI code page */\n               0,                 /* flags for character-type options */\n               fcp,               /* string to convert */\n               -1,                /* string length (-1 = NULL terminated) */\n               qw,                /* buffer */\n               ulenw);            /* buffer length (0 = return length) */\n    if (ulen == 0) {\n      /* failed */\n      free(qw);\n      free(fcp);\n      free(fp);\n      return 0;\n    }\n\n    d_hFindFile = FindFirstFileW(qw, &d_fd);\n    /* If this Win32 platform does not support Unicode wide paths\n       this returns INVALID_HANDLE_VALUE and the OS error is\n       \"No such file or directory\".  We return NULL and go with\n       the UTF-8 version of z->iname in f->uname.\n     */\n    free(qw);\n    free(fcp);\n    FindClose(d_hFindFile);\n\n    if (d_hFindFile == INVALID_HANDLE_VALUE)\n    {\n      return NULL;\n    }\n\n    /* Get buffer length */\n    ulen = WideCharToMultiByte(\n                    CP_UTF8,        /* UTF-8 code page */\n                    0,              /* flags */\n                    d_fd.cFileName, /* string to convert */\n                    -1,             /* input chars (-1 = NULL terminated) */\n                    NULL,           /* buffer */\n                    0,              /* size of buffer (0 = return needed size) */\n                    NULL,           /* default char */\n                    NULL);          /* used default char */\n    if (ulen == 0) {\n      /* failed */\n      return NULL;\n    }\n    ulen += 2;\n    if ((q = malloc(ulen + 1)) == NULL) {\n      return NULL;\n    }\n\n    /* Convert the Unicode string to UTF-8 */\n    if ((ulen = WideCharToMultiByte(\n                    CP_UTF8,        /* UTF-8 code page */\n                    0,              /* flags */\n                    d_fd.cFileName, /* string to convert */\n                    -1,             /* input chars (-1 = NULL terminated) */\n                    q,              /* buffer */\n                    ulen,           /* size of buffer (0 = return needed size) */\n                    NULL,           /* default char */\n                    NULL)) == 0)    /* used default char */\n    {\n      free(fp);\n      free(q);\n      return NULL;\n    }\n\n    if (r == NULL) {\n      /* first one */\n      r = q;\n    } else {\n      if ((r = realloc(r, strlen(r) + strlen(q) + 3)) == NULL) {\n        free(fp);\n        free(q);\n        return NULL;\n      }\n      strcat(r, \"/\");\n      strcat(r, q);\n      free(q);\n    }\n  }\n\n  free(fp);\n\n  if (is_dir) {\n    strcat(r, \"/\");\n  }\n\n  return r;\n}\n#endif\n\n\n#define ONENAMELEN 255\n\n/* whole is a pathname with wildcards, wildtail points somewhere in the  */\n/* middle of it.  All wildcards to be expanded must come AFTER wildtail. */\n\n\n#ifdef UNICODE_SUPPORT\n\nwchar_t *local_to_wchar_string(local_string)\n  char *local_string;       /* path to get utf-8 name for */\n{\n  wchar_t  *qw;\n  int       ulen;\n  int       ulenw;\n\n  if (local_string == NULL)\n    return NULL;\n\n    /* get length */\n    ulenw = MultiByteToWideChar(\n                CP_ACP,            /* ANSI code page */\n                0,                 /* flags for character-type options */\n                local_string,      /* string to convert */\n                -1,                /* string length (-1 = NULL terminated) */\n                NULL,              /* buffer */\n                0 );               /* buffer length (0 = return length) */\n    if (ulenw == 0) {\n      /* failed */\n      return NULL;\n    }\n    ulenw++;\n    /* get length in bytes */\n    ulen = sizeof(wchar_t) * (ulenw + 1);\n    if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {\n      return NULL;\n    }\n    /* convert multibyte to wide */\n    ulen = MultiByteToWideChar(\n               CP_ACP,            /* ANSI code page */\n               0,                 /* flags for character-type options */\n               local_string,      /* string to convert */\n               -1,                /* string length (-1 = NULL terminated) */\n               qw,                /* buffer */\n               ulenw);            /* buffer length (0 = return length) */\n    if (ulen == 0) {\n      /* failed */\n      free(qw);\n      return NULL;\n    }\n\n  return qw;\n}\n\n\nwchar_t *utf8_to_wchar_string(utf8_string)\n  char *utf8_string;       /* path to get utf-8 name for */\n{\n  wchar_t  *qw;\n  int       ulen;\n  int       ulenw;\n\n  if (utf8_string == NULL)\n    return NULL;\n\n    /* get length */\n    ulenw = MultiByteToWideChar(\n                CP_UTF8,           /* UTF-8 code page */\n                0,                 /* flags for character-type options */\n                utf8_string,       /* string to convert */\n                -1,                /* string length (-1 = NULL terminated) */\n                NULL,              /* buffer */\n                0 );               /* buffer length (0 = return length) */\n    if (ulenw == 0) {\n      /* failed */\n      return NULL;\n    }\n    ulenw++;\n    /* get length in bytes */\n    ulen = sizeof(wchar_t) * (ulenw + 1);\n    if ((qw = (wchar_t *)malloc(ulen + 1)) == NULL) {\n      return NULL;\n    }\n    /* convert multibyte to wide */\n    ulen = MultiByteToWideChar(\n               CP_UTF8,           /* UTF-8 code page */\n               0,                 /* flags for character-type options */\n               utf8_string,       /* string to convert */\n               -1,                /* string length (-1 = NULL terminated) */\n               qw,                /* buffer */\n               ulenw);            /* buffer length (0 = return length) */\n    if (ulen == 0) {\n      /* failed */\n      free(qw);\n      return NULL;\n    }\n\n  return qw;\n}\n\n\n\n/* Convert wchar_t string to utf8 using Windows calls\n   so any characters needing more than one wchar_t are\n   are handled by Windows */\nchar *wchar_to_utf8_string(wstring)\n  wchar_t *wstring;\n{\n  char     *q;           /* return string */\n  int       ulen;\n\n  if (wstring == NULL)\n    return NULL;\n\n  /* Get buffer length */\n  ulen = WideCharToMultiByte(\n                  CP_UTF8,        /* UTF-8 code page */\n                  0,              /* flags */\n                  wstring,        /* string to convert */\n                  -1,             /* input chars (-1 = NULL terminated) */\n                  NULL,           /* buffer */\n                  0,              /* size of buffer (0 = return needed size) */\n                  NULL,           /* default char */\n                  NULL);          /* used default char */\n  if (ulen == 0) {\n    /* failed */\n    return NULL;\n  }\n  ulen += 2;\n  if ((q = malloc(ulen + 1)) == NULL) {\n    return NULL;\n  }\n\n  /* Convert the Unicode string to UTF-8 */\n  if ((ulen = WideCharToMultiByte(\n                  CP_UTF8,        /* UTF-8 code page */\n                  0,              /* flags */\n                  wstring,        /* string to convert */\n                  -1,             /* input chars (-1 = NULL terminated) */\n                  q,              /* buffer */\n                  ulen,           /* size of buffer (0 = return needed size) */\n                  NULL,           /* default char */\n                  NULL)) == 0)    /* used default char */\n  {\n    free(q);\n    return NULL;\n  }\n\n  return q;\n}\n\n\nlocal int wild_recursew(whole, wildtail)\n  wchar_t *whole;\n  wchar_t *wildtail;\n{\n    zDIRSCANW *dirw;\n    wchar_t *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;\n    extent newlen;\n    int amatch = 0, e = ZE_MISS;\n\n    if (!isshexpw(wildtail)) {\n        if (GetFileAttributesW(whole) != 0xFFFFFFFF) {    /* file exists? */\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n            CharToOemW(whole, whole);\n#endif\n            return procnamew(whole, 0);\n        }\n        else\n            return ZE_MISS;                     /* woops, no wildcards! */\n    }\n\n    /* back up thru path components till existing dir found */\n    do {\n        name = wildtail + wcslen(wildtail) - 1;\n        for (;;)\n            if (name-- <= wildtail || *name == PATH_END) {\n                subwild = name + 1;\n                plug2 = *subwild;\n                *subwild = 0;\n                break;\n            }\n        if (glue)\n            *glue = plug;\n        glue = subwild;\n        plug = plug2;\n        dirw = OpenDirScanW(whole);\n    } while (!dirw && subwild > wildtail);\n    wildtail = subwild;                 /* skip past non-wild components */\n\n    if ((subwild = wcschr(wildtail + 1, PATH_END)) != NULL) {\n        /* this \"+ 1\" dodges the   ^^^ hole left by *glue == 0 */\n        *(subwild++) = 0;               /* wildtail = one component pattern */\n        newlen = wcslen(whole) + wcslen(subwild) + (ONENAMELEN + 2);\n    } else\n        newlen = wcslen(whole) + (ONENAMELEN + 1);\n    if (!dirw || ((newwhole = malloc(newlen * sizeof(wchar_t))) == NULL)) {\n        if (glue)\n            *glue = plug;\n        e = dirw ? ZE_MEM : ZE_MISS;\n        goto ohforgetit;\n    }\n    wcscpy(newwhole, whole);\n    newlen = wcslen(newwhole);\n    if (glue)\n        *glue = plug;                           /* repair damage to whole */\n    if (!isshexpw(wildtail)) {\n        e = ZE_MISS;                            /* non-wild name not found */\n        goto ohforgetit;\n    }\n\n    while ((name = readdw(dirw)) != NULL) {\n        if (wcscmp(name, L\".\") && wcscmp(name, L\"..\") &&\n            MATCHW(wildtail, name, 0)) {\n            wcscpy(newwhole + newlen, name);\n            if (subwild) {\n                name = newwhole + wcslen(newwhole);\n                *(name++) = (wchar_t)PATH_END;\n                wcscpy(name, subwild);\n                e = wild_recursew(newwhole, name);\n            } else\n                e = procname_win32w(newwhole, 0, GetDirAttribsW(dirw));\n            newwhole[newlen] = 0;\n            if (e == ZE_OK)\n                amatch = 1;\n            else if (e != ZE_MISS)\n                break;\n        }\n    }\n\n  ohforgetit:\n    if (dirw) CloseDirScanW(dirw);\n    if (subwild) *--subwild = PATH_END;\n    if (newwhole) free(newwhole);\n    if (e == ZE_MISS && amatch)\n        e = ZE_OK;\n    return e;\n}\n\n#endif\n\n\nlocal int wild_recurse(whole, wildtail)\n  char *whole;\n  char *wildtail;\n{\n    zDIRSCAN *dir;\n    char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;\n    extent newlen;\n    int amatch = 0, e = ZE_MISS;\n\n    if (!isshexp(wildtail)) {\n        if (GetFileAttributes(whole) != 0xFFFFFFFF) {    /* file exists? */\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n            AnsiToOem(whole, whole);\n#endif\n            return procname(whole, 0);\n        }\n        else\n            return ZE_MISS;                     /* woops, no wildcards! */\n    }\n\n    /* back up thru path components till existing dir found */\n    do {\n        name = wildtail + strlen(wildtail) - 1;\n        for (;;)\n            if (name-- <= wildtail || *name == PATH_END) {\n                subwild = name + 1;\n                plug2 = *subwild;\n                *subwild = 0;\n                break;\n            }\n        if (glue)\n            *glue = plug;\n        glue = subwild;\n        plug = plug2;\n        dir = OpenDirScan(whole);\n    } while (!dir && subwild > wildtail);\n    wildtail = subwild;                 /* skip past non-wild components */\n\n    if ((subwild = MBSCHR(wildtail + 1, PATH_END)) != NULL) {\n        /* this \"+ 1\" dodges the   ^^^ hole left by *glue == 0 */\n        *(subwild++) = 0;               /* wildtail = one component pattern */\n        newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);\n    } else\n        newlen = strlen(whole) + (ONENAMELEN + 1);\n    if (!dir || ((newwhole = malloc(newlen)) == NULL)) {\n        if (glue)\n            *glue = plug;\n        e = dir ? ZE_MEM : ZE_MISS;\n        goto ohforgetit;\n    }\n    strcpy(newwhole, whole);\n    newlen = strlen(newwhole);\n    if (glue)\n        *glue = plug;                           /* repair damage to whole */\n    if (!isshexp(wildtail)) {\n        e = ZE_MISS;                            /* non-wild name not found */\n        goto ohforgetit;\n    }\n\n    while ((name = readd(dir)) != NULL) {\n        if (strcmp(name, \".\") && strcmp(name, \"..\") &&\n            MATCH(wildtail, name, 0)) {\n            strcpy(newwhole + newlen, name);\n            if (subwild) {\n                name = newwhole + strlen(newwhole);\n                *(name++) = PATH_END;\n                strcpy(name, subwild);\n                e = wild_recurse(newwhole, name);\n            } else\n                e = procname_win32(newwhole, 0, GetDirAttribs(dir));\n            newwhole[newlen] = 0;\n            if (e == ZE_OK)\n                amatch = 1;\n            else if (e != ZE_MISS)\n                break;\n        }\n    }\n\n  ohforgetit:\n    if (dir) CloseDirScan(dir);\n    if (subwild) *--subwild = PATH_END;\n    if (newwhole) free(newwhole);\n    if (e == ZE_MISS && amatch)\n        e = ZE_OK;\n    return e;\n}\n\n\n#ifdef UNICODE_SUPPORT\nint has_win32_wide() {\n  DWORD r;\n\n  /* test if we have wide function support */\n\n  /* check if already set */\n  if (no_win32_wide != -1)\n    return !no_win32_wide;\n\n  /* assume we don't */\n  no_win32_wide = 1;\n\n  /* get attributes for this directory */\n  r = GetFileAttributes(\".\");\n\n  /* r should be 16 = FILE_ATTRIBUTE_DIRECTORY */\n  if (r == FILE_ATTRIBUTE_DIRECTORY) {\n    /* now see if it works for the wide version */\n    r = GetFileAttributesW(L\".\");\n    /* if this fails then we probably don't have wide functions */\n    if (r == 0xFFFFFFFF) {\n      /* error is probably \"This function is only valid in Win32 mode.\" */\n    } else if (r == FILE_ATTRIBUTE_DIRECTORY) {\n      /* worked, so assume we have wide support */\n      no_win32_wide = 0;\n    }\n  }\n\n  return !no_win32_wide;\n}\n#endif\n\n\nint wild(w)\n  char *w;               /* path/pattern to match */\n/* If not in exclude mode, expand the pattern based on the contents of the\n   file system.  Return an error code in the ZE_ class. */\n{\n    char *p;             /* path */\n    char *q;             /* diskless path */\n    int e;               /* result */\n#ifdef UNICODE_SUPPORT\n    wchar_t *pw;         /* wide path */\n    wchar_t *qw;         /* wide diskless path */\n#endif\n\n    if (volume_label == 1) {\n      volume_label = 2;\n      label = getVolumeLabel((w != NULL && isascii((uch)w[0]) && w[1] == ':')\n                             ? to_up(w[0]) : '\\0',\n                             &label_time, &label_mode, &label_utim);\n      if (label != NULL)\n        (void)newname(label, 0, 0);\n      if (w == NULL || (isascii((uch)w[0]) && w[1] == ':' && w[2] == '\\0'))\n        return ZE_OK;\n      /* \"zip -$ foo a:\" can be used to force drive name */\n    }\n    /* special handling of stdin request */\n    if (strcmp(w, \"-\") == 0)   /* if compressing stdin */\n        return newname(w, 0, 0);\n\n    /* Allocate and copy pattern, leaving room to add \".\" if needed */\n    if ((p = malloc(strlen(w) + 2)) == NULL)\n        return ZE_MEM;\n    strcpy(p, w);\n\n    /* Normalize path delimiter as '/' */\n    for (q = p; *q; INCSTR(q))            /* use / consistently */\n        if (*q == '\\\\')\n            *q = '/';\n\n#ifdef UNICODE_SUPPORT\n    if (!no_win32_wide) {\n      /* wide char version */\n      pw = local_to_wchar_string(p);\n\n      /* Separate the disk part of the path */\n      if ((qw = wcschr(pw, ':')) != NULL) {\n          if (wcschr(++qw, ':'))     /* sanity check for safety of wild_recurse */\n              return ZE_MISS;\n      } else\n          qw = pw;\n\n      /* Normalize bare disk names */\n      if (qw > pw && !*qw)\n          wcscpy(qw, L\".\");\n    } else {\n      /* multibyte version */\n      /* Separate the disk part of the path */\n      if ((q = MBSCHR(p, ':')) != NULL) {\n          if (MBSCHR(++q, ':'))     /* sanity check for safety of wild_recurse */\n              return ZE_MISS;\n      } else\n          q = p;\n\n      /* Normalize bare disk names */\n      if (q > p && !*q)\n          strcpy(q, \".\");\n    }\n#else\n    /* multibyte version */\n    /* Separate the disk part of the path */\n    if ((q = MBSCHR(p, ':')) != NULL) {\n        if (MBSCHR(++q, ':'))     /* sanity check for safety of wild_recurse */\n            return ZE_MISS;\n    } else\n        q = p;\n\n    /* Normalize bare disk names */\n    if (q > p && !*q)\n        strcpy(q, \".\");\n#endif\n\n    /* Here we go */\n#ifdef UNICODE_SUPPORT\n    if (!no_win32_wide) {\n      /* use wide Unicode directory scan */\n      e = wild_recursew(pw, qw);\n\n      free(pw);\n    } else {\n      /* use multibyte directory scan */\n      e = wild_recurse(p, q);\n    }\n#else\n    e = wild_recurse(p, q);\n#endif\n    free((zvoid *)p);\n    return e;\n}\n\n\nlocal int procname_win32(n, caseflag, attribs)\n  char *n;                /* name to process */\n  int caseflag;           /* true to force case-sensitive match */\n  DWORD attribs;\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  char *a;              /* path and name for recursion */\n  zDIRSCAN *d;          /* directory stream from OpenDirScan() */\n  char *e;              /* pointer to name from readd() */\n  int m;                /* matched flag */\n  char *p;              /* path for recursion */\n  z_stat s;             /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (strcmp(n, \"-\") == 0)   /* if compressing stdin */\n    return newname(n, 0, caseflag);\n  else if (attribs != INVALID_WIN32_FILE_ATTRIBS)\n  {\n    /* Avoid calling stat() for performance reasons when it is already known\n       (from a previous directory scan) that the passed name corresponds to\n       a \"real existing\" file.  The only information needed further down in\n       this function is the distinction between directory entries and other\n       (typically normal file) entries.  This distinction can be derived from\n       the file's attributes that the directory lookup has already provided\n       \"for free\".\n     */\n    s.st_mode = ((attribs & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG);\n  }\n  else if (LSSTAT(n, &s)\n#ifdef __TURBOC__\n           /* For this compiler, stat() succeeds on wild card names! */\n           /* Unfortunately, this causes failure on names containing */\n           /* square bracket characters, which are legal in win32.   */\n           || isshexp(n)\n#endif\n          )\n  {\n#ifdef UNICODE_SUPPORT\n    char *uname = NULL;\n#endif\n    /* Not a file or directory--search for shell expression in zip file */\n    p = ex2in(n, 0, (int *)NULL);       /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCH(p, z->iname, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->oname);\n        m = 0;\n      }\n    }\n#ifdef UNICODE_SUPPORT\n    /* also check escaped Unicode names */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (z->zuname) {\n#ifdef WIN32\n        /* It seems something is lost in going from a listed\n           name from zip -su in a console window to using that\n           name in a command line.  This kluge may fix it\n           and just takes zuname, converts to oem (i.e.ouname),\n           then converts it back which ends up not the same as\n           started with.\n         */\n        uname = z->wuname;\n#else\n        uname = z->zuname;\n#endif\n        if (MATCH(p, uname, caseflag))\n        {\n          z->mark = pcount ? filter(uname, caseflag) : 1;\n          if (verbose) {\n              fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n                 z->mark ? \"in\" : \"ex\", z->oname);\n              fprintf(mesg, \"     Escaped Unicode:  %s\\n\",\n                 z->ouname);\n          }\n          m = 0;\n        }\n      }\n    }\n#endif\n    free((zvoid *)p);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (p = n; *p; INCSTR(p))    /* use / consistently */\n    if (*p == '\\\\')\n      *p = '/';\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add exclusions in directory recurse but ignored for single file */\n    DWORD dwAttr;\n\n    dwAttr = GetFileMode(n);\n\n    if ((hidden_files ||\n         !(dwAttr & FILE_ATTRIBUTE_HIDDEN || dwAttr & FILE_ATTRIBUTE_SYSTEM)) &&\n        (!only_archive_set || (dwAttr & FILE_ATTRIBUTE_ARCHIVE)))\n    {\n      /* add or remove name of file */\n      if ((m = newname(n, 0, caseflag)) != ZE_OK)\n        return m;\n    }\n  } else {\n    /* Add trailing / to the directory name */\n    if ((p = (char *) malloc(strlen(n)+2)) == NULL)\n      return ZE_MEM;\n    if (strcmp(n, \".\") == 0 || strcmp(n, \"/.\") == 0) {\n      *p = '\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      strcpy(p, n);\n      a = p + strlen(p);\n      if (lastchar(p) != '/')\n        strcpy(a, \"/\");\n      if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)p);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (d = OpenDirScan(n)) != NULL)\n    {\n      while ((e = readd(d)) != NULL) {\n        if (strcmp(e, \".\") && strcmp(e, \"..\"))\n        {\n          if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)\n          {\n            CloseDirScan(d);\n            free((zvoid *)p);\n            return ZE_MEM;\n          }\n          strcat(strcpy(a, p), e);\n          if ((m = procname_win32(a, caseflag, GetDirAttribs(d)))\n              != ZE_OK)         /* recurse on name */\n          {\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", a);\n            else\n              ziperr(m, a);\n          }\n          free((zvoid *)a);\n        }\n      }\n      CloseDirScan(d);\n    }\n    free((zvoid *)p);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n\n\n#ifdef UNICODE_SUPPORT\nlocal int procname_win32w(nw, caseflag, attribs)\n  wchar_t *nw;             /* name to process */\n  int caseflag;           /* true to force case-sensitive match */\n  DWORD attribs;\n/* Process a name or sh expression to operate on (or exclude).  Return\n   an error code in the ZE_ class. */\n{\n  wchar_t *aw;          /* path and name for recursion */\n  zDIRSCANW *dw;        /* directory stream from OpenDirScan() */\n  wchar_t *ew;          /* pointer to name from readd() */\n  int m;                /* matched flag */\n  wchar_t *pw;          /* path for recursion */\n  zw_stat s;            /* result of stat() */\n  struct zlist far *z;  /* steps through zfiles list */\n\n  if (wcscmp(nw, L\"-\") == 0)   /* if compressing stdin */\n    return newnamew(nw, 0, caseflag);\n  else if (attribs != INVALID_WIN32_FILE_ATTRIBS)\n  {\n    /* Avoid calling stat() for performance reasons when it is already known\n       (from a previous directory scan) that the passed name corresponds to\n       a \"real existing\" file.  The only information needed further down in\n       this function is the distinction between directory entries and other\n       (typically normal file) entries.  This distinction can be derived from\n       the file's attributes that the directory lookup has already provided\n       \"for free\".\n     */\n    s.st_mode = ((attribs & FILE_ATTRIBUTE_DIRECTORY) ? S_IFDIR : S_IFREG);\n  }\n  else if (LSSTATW(nw, &s)\n#ifdef __TURBOC__\n           /* For this compiler, stat() succeeds on wild card names! */\n           /* Unfortunately, this causes failure on names containing */\n           /* square bracket characters, which are legal in win32.   */\n           || isshexpw(nw)\n#endif\n          )\n  {\n    wchar_t *unamew = NULL;\n    /* Not a file or directory--search for shell expression in zip file */\n    pw = ex2inw(nw, 0, (int *)NULL);     /* shouldn't affect matching chars */\n    m = 1;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (MATCHW(pw, z->znamew, caseflag))\n      {\n        z->mark = pcount ? filter(z->zname, caseflag) : 1;\n        if (verbose)\n            fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n               z->mark ? \"in\" : \"ex\", z->oname);\n        m = 0;\n      }\n    }\n    /* also check escaped Unicode names */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (z->zuname) {\n        unamew = z->znamew;\n        if (MATCHW(pw, unamew, caseflag))\n        {\n          z->mark = pcount ? filter(z->iname, caseflag) : 1;\n          if (verbose) {\n              fprintf(mesg, \"zip diagnostic: %scluding %s\\n\",\n                 z->mark ? \"in\" : \"ex\", z->oname);\n              fprintf(mesg, \"     Escaped Unicode:  %s\\n\",\n                 z->ouname);\n          }\n          m = 0;\n        }\n      }\n    }\n    free((zvoid *)pw);\n    return m ? ZE_MISS : ZE_OK;\n  }\n\n  /* Live name--use if file, recurse if directory */\n  for (pw = nw; *pw; pw++)    /* use / consistently */\n    if (*pw == (wchar_t)'\\\\')\n      *pw = (wchar_t)'/';\n  if ((s.st_mode & S_IFDIR) == 0)\n  {\n    /* add exclusions in directory recurse but ignored for single file */\n    DWORD dwAttr;\n\n    dwAttr = GetFileModeW(nw);\n\n    if ((hidden_files ||\n         !(dwAttr & FILE_ATTRIBUTE_HIDDEN || dwAttr & FILE_ATTRIBUTE_SYSTEM)) &&\n        (!only_archive_set || (dwAttr & FILE_ATTRIBUTE_ARCHIVE)))\n    {\n      /* add or remove name of file */\n      if ((m = newnamew(nw, 0, caseflag)) != ZE_OK)\n        return m;\n    }\n  } else {\n    /* Add trailing / to the directory name */\n    pw = (wchar_t *)malloc( (wcslen(nw)+2) * sizeof(wchar_t) );\n    if (pw == NULL)\n      return ZE_MEM;\n    if (wcscmp(nw, L\".\") == 0 || wcscmp(nw, L\"/.\") == 0) {\n      *pw = (wchar_t)'\\0';  /* avoid \"./\" prefix and do not create zip entry */\n    } else {\n      wcscpy(pw, nw);\n      aw = pw + wcslen(pw);\n      if (pw[wcslen(pw) - 1] != (wchar_t)'/')\n        wcscpy(aw, L\"/\");\n      if (dirnames && (m = newnamew(pw, 1, caseflag)) != ZE_OK) {\n        free((zvoid *)pw);\n        return m;\n      }\n    }\n    /* recurse into directory */\n    if (recurse && (dw = OpenDirScanW(nw)) != NULL)\n    {\n      while ((ew = readdw(dw)) != NULL) {\n        if (wcscmp(ew, L\".\") && wcscmp(ew, L\"..\"))\n        {\n          if ((aw = malloc((wcslen(pw) + wcslen(ew) + 1) * sizeof(wchar_t))) == NULL)\n          {\n            CloseDirScanW(dw);\n            free((zvoid *)pw);\n            return ZE_MEM;\n          }\n          wcscat(wcscpy(aw, pw), ew);\n          if ((m = procname_win32w(aw, caseflag, GetDirAttribsW(dw)))\n              != ZE_OK)         /* recurse on name */\n          {\n            char *a;\n            char *ad;\n\n            a = wchar_to_local_string(aw);\n            ad = local_to_display_string(a);\n\n            if (m == ZE_MISS)\n              zipwarn(\"name not matched: \", ad);\n            else\n              ziperr(m, a);\n            free(ad);\n            free(a);\n          }\n          free((zvoid *)aw);\n        }\n      }\n      CloseDirScanW(dw);\n    }\n    free((zvoid *)pw);\n  } /* (s.st_mode & S_IFDIR) == 0) */\n  return ZE_OK;\n}\n#endif\n\n\n#ifdef UNICODE_SUPPORT\nint procnamew(nw, caseflag)\n  wchar_t *nw;          /* name to process */\n  int caseflag;         /* true to force case-sensitive match */\n{\n    return procname_win32w(nw, caseflag, INVALID_WIN32_FILE_ATTRIBS);\n}\n#endif\n\nint procname(n, caseflag)\n  char *n;             /* name to process */\n  int caseflag;         /* true to force case-sensitive match */\n{\n    return procname_win32(n, caseflag, INVALID_WIN32_FILE_ATTRIBS);\n}\n\nchar *ex2in(x, isdir, pdosflag)\n  char *x;             /* external file name */\n  int isdir;            /* input: x is a directory */\n  int *pdosflag;        /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *n;              /* internal file name (malloc'ed) */\n  char *t;              /* shortened name */\n  int dosflag;\n\n\n  dosflag = dosify || IsFileSystemOldFAT(x);\n  if (!dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL)\n  {\n    x = t;\n    dosflag = 0;\n  }\n\n  /* Find starting point in name before doing malloc */\n  /* Strip drive specification */\n  t = *x && isascii((uch)*x) && *(x + 1) == ':' ? x + 2 : x;\n  /* Strip \"//host/share/\" part of a UNC name */\n  if ((!strncmp(x,\"//\",2) || !strncmp(x,\"\\\\\\\\\",2)) &&\n      (x[2] != '\\0' && x[2] != '/' && x[2] != '\\\\')) {\n    n = x + 2;\n    while (*n != '\\0' && *n != '/' && *n != '\\\\')\n      INCSTR(n);        /* strip host name */\n    if (*n != '\\0') {\n      INCSTR(n);\n      while (*n != '\\0' && *n != '/' && *n != '\\\\')\n        INCSTR(n);      /* strip `share' name */\n    }\n    if (*n != '\\0')\n      t = n + MB_CLEN(n);\n  }\n  /* Strip leading \"/\" to convert an absolute path into a relative path */\n  while (*t == '/' || *t == '\\\\')\n    t++;\n  /* Strip leading \"./\" as well as drive letter */\n  while (*t == '.' && (t[1] == '/' || t[1] == '\\\\'))\n    t += 2;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (n = t; *n; INCSTR(n))\n    if (*n == '\\\\')\n      *n = '/';\n\n  if (!pathput)\n    t = last(t, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((n = malloc(strlen(t) + 1)) == NULL)\n    return NULL;\n  strcpy(n, t);\n\n  if (dosify)\n    msname(n);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  OemToAnsi(n, n);\n#endif\n  return n;\n}\n\n#ifdef UNICODE_SUPPORT\nwchar_t *ex2inw(xw, isdir, pdosflag)\n  wchar_t *xw;          /* external file name */\n  int isdir;            /* input: x is a directory */\n  int *pdosflag;        /* output: force MSDOS file attributes? */\n/* Convert the external file name to a zip file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  wchar_t *nw;          /* internal file name (malloc'ed) */\n  wchar_t *tw;          /* shortened name */\n  int dosflag;\n\n\n  dosflag = dosify || IsFileSystemOldFATW(xw);\n  if (!dosify && use_longname_ea && (tw = GetLongPathEAW(xw)) != NULL)\n  {\n    xw = tw;\n    dosflag = 0;\n  }\n\n  /* Find starting point in name before doing malloc */\n  /* Strip drive specification */\n  tw = *xw && iswascii(*xw) && *(xw + 1) == (wchar_t)':' ? xw + 2 : xw;\n  /* Strip \"//host/share/\" part of a UNC name */\n  if ((!wcsncmp(xw,L\"//\",2) || !wcsncmp(xw,L\"\\\\\\\\\",2)) &&\n      (xw[2] != (wchar_t)'\\0' && xw[2] != (wchar_t)'/' && xw[2] != (wchar_t)'\\\\')) {\n    nw = xw + 2;\n    while (*nw != (wchar_t)'\\0' && *nw != (wchar_t)'/' && *nw != (wchar_t)'\\\\')\n      nw++;        /* strip host name */\n    if (*nw != (wchar_t)'\\0') {\n      nw++;\n      while (*nw != (wchar_t)'\\0' && *nw != (wchar_t)'/' && *nw != (wchar_t)'\\\\')\n        nw++;      /* strip `share' name */\n    }\n    if (*nw != (wchar_t)'\\0')\n      tw = nw++;\n  }\n  /* Strip leading \"/\" to convert an absolute path into a relative path */\n  while (*tw == (wchar_t)'/' || *tw == (wchar_t)'\\\\')\n    tw++;\n  /* Strip leading \"./\" as well as drive letter */\n  while (*tw == (wchar_t)'.' && (tw[1] == (wchar_t)'/' || tw[1] == (wchar_t)'\\\\'))\n    tw += 2;\n\n  /* Make changes, if any, to the copied name (leave original intact) */\n  for (nw = tw; *nw; nw++)\n    if (*nw == '\\\\')\n      *nw = '/';\n\n  if (!pathput)\n    tw = lastw(tw, PATH_END);\n\n  /* Malloc space for internal name and copy it */\n  if ((nw = malloc((wcslen(tw) + 1) * sizeof(wchar_t))) == NULL)\n    return NULL;\n  wcscpy(nw, tw);\n\n  if (dosify)\n    msnamew(nw);\n\n  /* Returned malloc'ed name */\n  if (pdosflag)\n    *pdosflag = dosflag;\n#if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  CharToAnsiW(nw, nw);\n#endif\n  return nw;\n}\n#endif\n\n\nchar *in2ex(n)\n  char *n;             /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  char *x;             /* external file name */\n\n  if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)\n    return NULL;\n  strcpy(x, n);\n# if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  AnsiToOem(x, x);\n# endif\n  return x;\n}\n\n#ifdef UNICODE_SUPPORT\nwchar_t *in2exw(nw)\n  wchar_t *nw;            /* internal file name */\n/* Convert the zip file name to an external file name, returning the malloc'ed\n   string or NULL if not enough memory. */\n{\n  wchar_t *xw;            /* external file name */\n\n  if ((xw = malloc((wcslen(nw) + 1 + PAD) * sizeof(wchar_t))) == NULL)\n    return NULL;\n  wcscpy(xw, nw);\n# if defined(__RSXNT__)  /* RSXNT/EMX C rtl uses OEM charset */\n  CharToOemW(xw, xw);\n# endif\n  return xw;\n}\n#endif\n\n\nvoid stamp(f, d)\n  char *f;                /* name of file to change */\n  ulg d;                  /* dos-style time to change it to */\n/* Set last updated and accessed time of file f to the DOS time d. */\n{\n#if defined(__TURBOC__) && !defined(__BORLANDC__)\n  int h;                /* file handle */\n\n  if ((h = open(f, 0)) != -1)\n  {\n    setftime(h, (struct ftime *)&d);\n    close(h);\n  }\n#else /* !__TURBOC__ */\n\n  struct utimbuf u;     /* argument for utime() */\n\n  /* Convert DOS time to time_t format in u.actime and u.modtime */\n  u.actime = u.modtime = dos2unixtime(d);\n\n  /* Set updated and accessed times of f */\n  utime(f, &u);\n#endif /* ?__TURBOC__ */\n}\n\nulg filetime(f, a, n, t)\n  char *f;              /* name of file to get info on */\n  ulg *a;               /* return value: file attributes */\n  zoff_t *n;            /* return value: file size */\n  iztimes *t;           /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  z_stat s;             /* results of zstat() */\n\n  /* converted to malloc instead of using FNMAX - 11/8/04 EG */\n  char *name;\n  unsigned int len = strlen(f);\n  int isstdin = !strcmp(f, \"-\");\n\n  if (f == label) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((name = malloc(len + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  strcpy(name, f);\n  if (MBSRCHR(name, '/') == (name + len - 1))\n    name[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  /* zip64 support 08/31/2003 R.Nausedat */\n  if (isstdin) {\n    if (zfstat(fileno(stdin), &s) != 0) {\n      free(name);\n      error(\"fstat(stdin)\");\n    }\n    time((time_t *)&s.st_mtime);       /* some fstat()s return time zero */\n  } else if (LSSTAT(name, &s) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(name);\n    return 0;\n  }\n\n  if (a != NULL) {\n#ifdef WIN32_OEM\n    /* When creating DOS-like archives with OEM-charset names, only the\n       standard FAT attributes should be used.\n       (Note: On a Win32 system, the UNIX style attributes from stat()\n              do not contain any additional information...)\n     */\n    *a = (isstdin ? 0L : (ulg)GetFileMode(name));\n#else\n    *a = ((ulg)s.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileMode(name));\n#endif\n  }\n  if (n != NULL)\n    /* device return -1 */\n    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;\n  if (t != NULL) {\n    t->atime = s.st_atime;\n    t->mtime = s.st_mtime;\n    t->ctime = s.st_ctime;\n  }\n  free(name);\n\n  return unix2dostime((time_t *)&s.st_mtime);\n}\n\n#ifdef UNICODE_SUPPORT\nulg filetimew(fw, a, n, t)\n  wchar_t *fw;          /* name of file to get info on */\n  ulg *a;               /* return value: file attributes */\n  zoff_t *n;            /* return value: file size */\n  iztimes *t;           /* return value: access, modific. and creation times */\n/* If file *f does not exist, return 0.  Else, return the file's last\n   modified date and time as an MSDOS date and time.  The date and\n   time is returned in a long with the date most significant to allow\n   unsigned integer comparison of absolute times.  Also, if a is not\n   a NULL pointer, store the file attributes there, with the high two\n   bytes being the Unix attributes, and the low byte being a mapping\n   of that to DOS attributes.  If n is not NULL, store the file size\n   there.  If t is not NULL, the file's access, modification and creation\n   times are stored there as UNIX time_t values.\n   If f is \"-\", use standard input as the file. If f is a device, return\n   a file size of -1 */\n{\n  zw_stat sw;           /* results of zstat() */\n\n  /* converted to malloc instead of using FNMAX - 11/8/04 EG */\n  wchar_t *namew;\n  unsigned int len = wcslen(fw);\n  int isstdin = !wcscmp(fw, L\"-\");\n  wchar_t *labelw = local_to_wchar_string(label);\n\n  if (labelw && wcscmp(fw, labelw) == 0) {\n    if (a != NULL)\n      *a = label_mode;\n    if (n != NULL)\n      *n = -2L; /* convention for a label name */\n    if (t != NULL)\n      t->atime = t->mtime = t->ctime = label_utim;\n    return label_time;\n  }\n  if ((namew = malloc((len + 1) * sizeof(wchar_t))) == NULL) {\n    ZIPERR(ZE_MEM, \"filetime\");\n  }\n  wcscpy(namew, fw);\n  if (wcsrchr(namew, (wchar_t)'/') == (namew + len - 1))\n    namew[len - 1] = '\\0';\n  /* not all systems allow stat'ing a file with / appended */\n\n  /* zip64 support 08/31/2003 R.Nausedat */\n  if (isstdin) {\n    if (zwfstat(fileno(stdin), &sw) != 0) {\n      free(namew);\n      error(\"fstat(stdin)\");\n    }\n    time((time_t *)&sw.st_mtime);       /* some fstat()s return time zero */\n  } else if (LSSTATW(namew, &sw) != 0) {\n             /* Accept about any file kind including directories\n              * (stored with trailing / with -r option)\n              */\n    free(namew);\n    return 0;\n  }\n\n  if (a != NULL) {\n#ifdef WIN32_OEM\n    /* When creating DOS-like archives with OEM-charset names, only the\n       standard FAT attributes should be used.\n       (Note: On a Win32 system, the UNIX style attributes from stat()\n              do not contain any additional information...)\n     */\n    *a = (isstdin ? 0L : (ulg)GetFileModeW(namew));\n#else\n    *a = ((ulg)sw.st_mode << 16) | (isstdin ? 0L : (ulg)GetFileModeW(namew));\n#endif\n  }\n  if (n != NULL)\n    /* device return -1 */\n    *n = (sw.st_mode & S_IFMT) == S_IFREG ? sw.st_size : -1L;\n  if (t != NULL) {\n    t->atime = sw.st_atime;\n    t->mtime = sw.st_mtime;\n    t->ctime = sw.st_ctime;\n  }\n  free(namew);\n\n  return unix2dostime((time_t *)&sw.st_mtime);\n}\n#endif\n\n\n\n#ifdef NTSD_EAS\n\n/* changed size, csize from size_t to ush 3/10/2005 EG */\nlocal void GetSD(char *path, char **bufptr, ush *size,\n                        char **cbufptr, ush *csize)\n{\n  unsigned char stackbuffer[NTSD_BUFFERSIZE];\n  unsigned long bytes = NTSD_BUFFERSIZE;\n  unsigned char *buffer = stackbuffer;\n  unsigned char *DynBuffer = NULL;\n  ulg cbytes;\n  PEF_NTSD_L_HEADER pLocalHeader;\n  PEF_NTSD_C_HEADER pCentralHeader;\n  VOLUMECAPS VolumeCaps;\n\n  /* check target volume capabilities */\n  if (!ZipGetVolumeCaps(path, path, &VolumeCaps) ||\n     !(VolumeCaps.dwFileSystemFlags & FS_PERSISTENT_ACLS)) {\n    return;\n  }\n\n  VolumeCaps.bUsePrivileges = use_privileges;\n  VolumeCaps.dwFileAttributes = 0;\n  /* should set to file attributes, if possible */\n\n  if (!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {\n\n    /* try to malloc the buffer if appropriate */\n    if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {\n        DynBuffer = malloc(bytes);\n        if(DynBuffer == NULL) return;\n\n        buffer = DynBuffer; /* switch to the new buffer and try again */\n\n        if(!SecurityGet(path, &VolumeCaps, buffer, (LPDWORD)&bytes)) {\n            free(DynBuffer);\n            return;\n        }\n\n    } else {\n        return; /* bail */\n    }\n  }\n\n  /* # bytes to compress: compress type, CRC, data bytes */\n  cbytes = (2 + 4 + EB_DEFLAT_EXTRA) + bytes;\n\n\n  /* our two possible failure points.  don't allow trashing of any data\n     if either fails - notice that *size and *csize don't get updated.\n     *bufptr leaks if malloc() was used and *cbufptr alloc fails - this\n     isn't relevant because it's probably indicative of a bigger problem. */\n\n  if(*size)\n    *bufptr = realloc(*bufptr, *size + EF_NTSD_L_LEN + cbytes);\n  else\n    *bufptr = malloc(EF_NTSD_L_LEN + cbytes);\n\n  if(*csize)\n    *cbufptr = realloc(*cbufptr, *csize + EF_NTSD_C_LEN);\n  else\n    *cbufptr = malloc(EF_NTSD_C_LEN);\n\n  if(*bufptr == NULL || *cbufptr == NULL) {\n    if(DynBuffer) free(DynBuffer);\n    return;\n  }\n\n  /* local header */\n\n  pLocalHeader = (PEF_NTSD_L_HEADER) (*bufptr + *size);\n\n  cbytes = memcompress(((char *)pLocalHeader + EF_NTSD_L_LEN), cbytes,\n                       (char *)buffer, bytes);\n\n  if (cbytes > 0x7FFF) {\n    sprintf(errbuf, \"security info too large to store (%ld bytes), %d max\", bytes, 0x7FFF);\n    zipwarn(errbuf, \"\");\n    zipwarn(\"security info not stored: \", path);\n    if(DynBuffer) free(DynBuffer);\n    return;\n  }\n\n  *size += EF_NTSD_L_LEN + (ush)cbytes;\n\n  pLocalHeader->nID = EF_NTSD;\n  pLocalHeader->nSize = (USHORT)(EF_NTSD_L_LEN - EB_HEADSIZE\n                                 + cbytes);\n  pLocalHeader->lSize = bytes; /* uncompressed size */\n  pLocalHeader->Version = 0;\n\n  /* central header */\n\n  pCentralHeader = (PEF_NTSD_C_HEADER) (*cbufptr + *csize);\n  *csize += EF_NTSD_C_LEN;\n\n  pCentralHeader->nID = EF_NTSD;\n  pCentralHeader->nSize = EF_NTSD_C_LEN - EB_HEADSIZE;  /* sbz */\n  pCentralHeader->lSize = bytes;\n\n  if (noisy) {\n    sprintf(errbuf, \" (%ld bytes security)\", bytes);\n    zipmessage_nl(errbuf, 0);\n  }\n\n  if(DynBuffer) free(DynBuffer);\n}\n#endif /* NTSD_EAS */\n\n\n#ifdef USE_EF_UT_TIME\n\n#define EB_L_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(3))\n#define EB_C_UT_SIZE    (EB_HEADSIZE + EB_UT_LEN(1))\n\nlocal int GetExtraTime(struct zlist far *z, iztimes *z_utim)\n{\n  char *eb_l_ptr;\n  char *eb_c_ptr;\n  ulg ultime;\n  /* brain-dead IBM compiler defines time_t as \"double\", so we have to convert\n   * it into unsigned long integer number...\n   */\n\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return ZE_OK;    /* skip silently if no valid TZ info */\n#endif\n\n  if(z->ext)\n    eb_l_ptr = realloc(z->extra, (z->ext + EB_L_UT_SIZE));\n  else\n    eb_l_ptr = malloc(EB_L_UT_SIZE);\n\n  if (eb_l_ptr == NULL)\n    return ZE_MEM;\n\n  if(z->cext)\n    eb_c_ptr = realloc(z->cextra, (z->cext + EB_C_UT_SIZE));\n  else\n    eb_c_ptr = malloc(EB_C_UT_SIZE);\n\n  if (eb_c_ptr == NULL)\n    return ZE_MEM;\n\n  z->extra = eb_l_ptr;\n  eb_l_ptr += z->ext;\n  z->ext += EB_L_UT_SIZE;\n\n  eb_l_ptr[0]  = 'U';\n  eb_l_ptr[1]  = 'T';\n  eb_l_ptr[2]  = EB_UT_LEN(3);          /* length of data part of e.f. */\n  eb_l_ptr[3]  = 0;\n  eb_l_ptr[4]  = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME;\n  ultime = (ulg)z_utim->mtime;\n  eb_l_ptr[5]  = (char)(ultime);\n  eb_l_ptr[6]  = (char)(ultime >> 8);\n  eb_l_ptr[7]  = (char)(ultime >> 16);\n  eb_l_ptr[8]  = (char)(ultime >> 24);\n  ultime = (ulg)z_utim->atime;\n  eb_l_ptr[9]  = (char)(ultime);\n  eb_l_ptr[10] = (char)(ultime >> 8);\n  eb_l_ptr[11] = (char)(ultime >> 16);\n  eb_l_ptr[12] = (char)(ultime >> 24);\n  ultime = (ulg)z_utim->ctime;\n  eb_l_ptr[13] = (char)(ultime);\n  eb_l_ptr[14] = (char)(ultime >> 8);\n  eb_l_ptr[15] = (char)(ultime >> 16);\n  eb_l_ptr[16] = (char)(ultime >> 24);\n\n  z->cextra = eb_c_ptr;\n  eb_c_ptr += z->cext;\n  z->cext += EB_C_UT_SIZE;\n\n  memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);\n  eb_c_ptr[EB_LEN] = EB_UT_LEN(1);\n\n  return ZE_OK;\n}\n\n#endif /* USE_EF_UT_TIME */\n\n\n\nint set_extra_field(z, z_utim)\n  struct zlist far *z;\n  iztimes *z_utim;\n  /* create extra field and change z->att if desired */\n{\n\n#ifdef NTSD_EAS\n  if(ZipIsWinNT()) {\n    /* store SECURITY_DECRIPTOR data in local header,\n       and size only in central headers */\n    GetSD(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);\n  }\n#endif /* NTSD_EAS */\n\n#ifdef USE_EF_UT_TIME\n  /* store extended time stamps in both headers */\n  return GetExtraTime(z, z_utim);\n#else /* !USE_EF_UT_TIME */\n  return ZE_OK;\n#endif /* ?USE_EF_UT_TIME */\n}\n\nint deletedir(d)\nchar *d;                /* directory to delete */\n/* Delete the directory *d if it is empty, do nothing otherwise.\n   Return the result of rmdir(), delete(), or system().\n   For VMS, d must be in format [x.y]z.dir;1  (not [x.y.z]).\n */\n{\n    return rmdir(d);\n}\n\n#endif /* !UTIL */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/win32zip.h",
    "content": "/*\n  win32/win32zip.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _WIN32ZIP_H\n#define _WIN32ZIP_H\n\n/*\n * NT specific functions for ZIP.\n */\n\nint GetFileMode(char *name);\n#ifdef UNICODE_SUPPORT\nint GetFileModeW(wchar_t *name);\n#endif\nlong GetTheFileTime(char *name, iztimes *z_times);\n\nint IsFileNameValid(char *name);\nint IsFileSystemOldFAT(char *dir);\n#ifdef UNICODE_SUPPORT\nint IsFileSystemOldFATW(wchar_t *dir);\n#endif\nvoid ChangeNameForFAT(char *name);\n\nchar *getVolumeLabel(int drive, ulg *vtime, ulg *vmode, time_t *vutim);\n\n#if 0 /* never used ?? */\nchar *StringLower(char *);\n#endif\n\nchar *GetLongPathEA(char *name);\n#ifdef UNICODE_SUPPORT\nwchar_t *GetLongPathEAW(wchar_t *name);\n#endif\n\n#endif /* _WIN32ZIP_H */\n"
  },
  {
    "path": "deps/infozip/zip30/win32/zip.def",
    "content": ";module-definition file for Windows Zip DLL -- used by link.exe\nDESCRIPTION 'The world-famous zip utilities from Info-ZIP'\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/win32/zip.rc",
    "content": "#include <windows.h>\n#if (defined(WIN32) && !defined(__EMX__) && !defined(__MINGW32__))\n#include <winver.h>\n#endif\n#define IZ_VERSION_SYMBOLS_ONLY\n#include \"../revision.h\"\n#undef IZ_VERSION_SYMBOLS_ONLY\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION Z_MAJORVER,Z_MINORVER,Z_PATCHLEVEL,0\n PRODUCTVERSION Z_MAJORVER,Z_MINORVER,Z_PATCHLEVEL,0\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS VOS__WINDOWS32\n FILETYPE VFT_APP\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        BLOCK \"040904B0\"\n#else\n        BLOCK \"040904E4\"\n#endif\n        BEGIN\n            VALUE \"CompanyName\", IZ_COMPANY_NAME \"\\0\"\n            VALUE \"FileDescription\", \"Info-ZIP Zip for Win32 console\\0\"\n            VALUE \"FileVersion\", VERSION \"\\0\"\n            VALUE \"InternalName\", \"zip\\0\"\n            VALUE \"LegalCopyright\", \"Copyright  Info-ZIP 1997 - 2008\\0\"\n            VALUE \"OriginalFilename\", \"zip.exe\\0\"\n            VALUE \"ProductName\", \"Zip\\0\"\n            VALUE \"ProductVersion\", VERSION \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        VALUE \"Translation\", 0x409, 1200\n#else\n        VALUE \"Translation\", 0x409, 1252\n#endif\n    END\nEND\n"
  },
  {
    "path": "deps/infozip/zip30/win32/zipup.h",
    "content": "/*\n  win32/zipup.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef __CYGWIN__\n#  include <share.h>\n#endif\n#ifndef O_RDONLY\n#  define O_RDONLY   0\n#endif\n#ifndef O_BINARY\n#  define O_BINARY   0\n#endif\n#if (defined(_SH_DENYNO) && !defined(SH_DENYNO))\n#  define SH_DENYNO _SH_DENYNO\n#endif\n#if (defined(SH_DENYNO) && !defined(_SH_DENYNO))\n#  define _SH_DENYNO SH_DENYNO\n#endif\n#define fhow         (O_RDONLY|O_BINARY)\n#define fbad         (-1)\ntypedef int          ftype;\n\n#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__EMX__)\n#  define zopen(n,p) sopen(n,p,SH_DENYNO)\n#elif defined(__CYGWIN__) || defined(__IBMC__)\n#  define zopen(n,p) open(n,p)\n#else\n#  define zopen(n,p) _sopen(n,p,_SH_DENYNO)\n#endif\n#ifdef UNICODE_SUPPORT\n# if defined(__CYGWIN__) || defined(__IBMC__)\n#  define zwopen(n,p) wopen(n,p)\n# else\n#  define zwopen(n,p) _wsopen(n,p,_SH_DENYNO)\n# endif\n#endif\n\n#define zread(f,b,n) read(f,b,n)\n#define zclose(f)    close(f)\n#define zerr(f)      (k == (extent)(-1L))\n#define zstdin       0\n"
  },
  {
    "path": "deps/infozip/zip30/windll/VBz64/VBZIP.VBP",
    "content": "Type=Exe\nForm=Vbzipfrm.frm\nModule=VBZipBas; VBZipBas.bas\nIconForm=\"Form1\"\nStartup=\"Form1\"\nHelpFile=\"\"\nTitle=\"VBZIP\"\nExeName32=\"VBZIP.exe\"\nCommand32=\"\"\nName=\"Project1\"\nHelpContextID=\"0\"\nCompatibleMode=\"0\"\nMajorVer=1\nMinorVer=0\nRevisionVer=0\nAutoIncrementVer=0\nServerSupportFiles=0\nVersionCompanyName=\"Mike\"\nCompilationType=-1\nOptimizationType=0\nFavorPentiumPro(tm)=0\nCodeViewDebugInfo=0\nNoAliasing=0\nBoundsCheck=0\nOverflowCheck=0\nFlPointCheck=0\nFDIVCheck=0\nUnroundedFP=0\nStartMode=0\nUnattended=0\nRetained=0\nThreadPerObject=0\nMaxNumberOfThreads=1\n"
  },
  {
    "path": "deps/infozip/zip30/windll/VBz64/VBZIP.vbw",
    "content": "Form1 = 7, 9, 712, 539, , 22, 22, 660, 466, C\nVBZipBas = 26, -4, 716, 492, \n"
  },
  {
    "path": "deps/infozip/zip30/windll/VBz64/VBZipBas.bas",
    "content": "Attribute VB_Name = \"VBZipBas\"\n\nOption Explicit\n\n'---------------------------------------------------------------\n'-- Please Do Not Remove These Comments!!!\n'---------------------------------------------------------------\n'-- Sample VB 6 code to drive zip32z64.dll\n'-- Based on the code contributed to the Info-ZIP project\n'-- by Mike Le Voi\n'--\n'-- See the original VB example in a separate directory for\n'-- more information\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'---------------------------------------------------------------\n'--\n'-- The Source Code Is Freely Available From Info-ZIP At:\n'-- ftp://ftp.info-zip.org/pub/infozip/infozip.html\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White Of The Info-ZIP\n'-- For Letting Me Use And Modify His Orginal\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'---------------------------------------------------------------\n\n'---------------------------------------------------------------\n' This example is redesigned to work with Zip32z64.dll compiled from\n' Zip 3.0 with Zip64 enabled.  This allows for archives with more\n' and larger files than allowed in previous versions.\n'\n' Modified 4/24/2004, 12/4/2007 by Ed Gordon\n'---------------------------------------------------------------\n\n'---------------------------------------------------------------\n' Usage notes:\n'\n' This code uses Zip32z64.dll.  You DO NOT need to register the\n' DLL to use it.  You also DO NOT need to reference it in your\n' VB project.  You DO have to copy the DLL to your SYSTEM\n' directory, your VB project directory, or place it in a directory\n' on your command PATH.\n'\n' Note that Zip32z64 is probably not thread safe so you should avoid\n' using the dll in multiple threads at the same time without first\n' testing for interaction.\n'\n' All code provided under the Info-Zip license.  If you have\n' any questions please contact Info-Zip.\n'\n' April 24 2004 EG\n'\n'---------------------------------------------------------------\n\n'-- C Style argv\n'-- Holds The Zip Archive Filenames\n'\n' Max for zFiles just over 8000 as each pointer takes up 4 bytes and\n' VB only allows 32 kB of local variables and that includes function\n' parameters.  - 3/19/2004 EG\n'\n' Can put names in strZipFileNames instead of using this array,\n' which avoids this limit.  File names are separated by spaces.\n' Enclose names in quotes if include spaces.\nPublic Type ZIPnames\n  zFiles(1 To 100) As String\nEnd Type\n\n'-- Call Back \"String\"\nPublic Type ZipCBChar\n  ch(4096) As Byte\nEnd Type\n\n'-- Version Structure\nPublic Type VerType\n  Major As Byte\n  Minor As Byte\n  PatchLevel As Byte\n  NotUsed As Byte\nEnd Type\nPublic Type ZipVerType\n  structlen       As Long         ' Length Of The Structure Being Passed\n  flag            As Long         ' Bit 0: is_beta  bit 1: uses_zlib\n  Beta            As String * 10  ' e.g., \"g BETA\" or \"\"\n  date            As String * 20  ' e.g., \"4 Sep 95\" (beta) or \"4 September 1995\"\n  ZLIB            As String * 10  ' e.g., \"1.0.5\" or NULL\n  encryption      As Long         ' 0 if encryption not available\n  ZipVersion      As VerType\n  os2dllVersion   As VerType\n  windllVersion   As VerType\nEnd Type\n\n'-- ZPOPT Is Used To Set The Options In The ZIP32z64.DLL\nPublic Type ZpOpt\n  date           As String ' Date in either US 12/31/98 or 1998-12-31 format\n  szRootDir      As String ' Root Directory Pathname (Up To 256 Bytes Long)\n  szTempDir      As String ' Temp Directory Pathname (Up To 256 Bytes Long)\n  fTemp          As Long   ' 1 If Temp dir Wanted, Else 0\n  fSuffix        As Long   ' Include Suffixes (Not Yet Implemented!)\n  fEncrypt       As Long   ' 1 If Encryption Wanted, Else 0\n  fSystem        As Long   ' 1 To Include System/Hidden Files, Else 0\n  fVolume        As Long   ' 1 If Storing Volume Label, Else 0\n  fExtra         As Long   ' 1 If Excluding Extra Attributes, Else 0\n  fNoDirEntries  As Long   ' 1 If Ignoring Directory Entries (end with /), Else 0\n  fExcludeDate   As Long   ' 1 If Excluding Files After Specified Date, Else 0\n  fIncludeDate   As Long   ' 1 If Including Files After Specified Date, Else 0\n  fVerbose       As Long   ' 1 If Full Messages Wanted, Else 0\n  fQuiet         As Long   ' 1 If Minimum Messages Wanted, Else 0\n  fCRLF_LF       As Long   ' 1 If Translate CR/LF To LF, Else 0\n  fLF_CRLF       As Long   ' 1 If Translate LF To CR/LF, Else 0\n  fJunkDir       As Long   ' 1 If Junking Directory Names on entries, Else 0\n  fGrow          As Long   ' 1 If Allow Appending To Zip File, Else 0\n  fForce         As Long   ' 1 If Making Entries Using DOS File Names, Else 0\n  fMove          As Long   ' 1 If Deleting Files Added Or Updated, Else 0\n  fDeleteEntries As Long   ' 1 If Files Passed Have To Be Deleted, Else 0\n  fUpdate        As Long   ' 1 If Updating Zip File-Overwrite Only If Newer, Else 0\n  fFreshen       As Long   ' 1 If Freshing Zip File-Overwrite Only, Else 0\n  fJunkSFX       As Long   ' 1 If Junking SFX Prefix, Else 0\n  fLatestTime    As Long   ' 1 If Setting Zip File Time To Time Of Latest File In Archive, Else 0\n  fComment       As Long   ' 1 If Putting Comment In Zip File, Else 0\n  fOffsets       As Long   ' 1 If Updating Archive Offsets For SFX Files, Else 0\n  fPrivilege     As Long   ' 1 If Not Saving Privileges, Else 0\n  fEncryption    As Long   ' Read Only Property!!!\n  szSplitSize    As String ' Size of split if splitting, Else NULL (empty string)\n                           ' This string contains the size that you want to\n                           ' split the archive into. i.e. 100 for 100 bytes,\n                           ' 2K for 2 k bytes, where K is 1024, m for meg\n                           ' and g for gig.\n  szIncludeList  As String ' If used, space separated list of Include filename\n                           ' patterns where match includes file - put quotes\n                           ' around each filename pattern.\n  IncludeListCount As Long ' place filler (not for VB) - (inits to 0) DO NOT USE\n  IncludeList    As Long   ' place filler (not for VB) - (inits to 0) DO NOT USE\n  szExcludeList  As String ' If used, space separated list of Exclude filename\n                           ' patterns where match excludes file - put quotes\n                           ' around each filename pattern.\n  ExcludeListCount As Long ' place filler (not for VB) - (inits to 0) DO NOT USE\n  ExcludeList    As Long   ' place filler (not for VB) - (inits to 0) DO NOT USE\n  fRecurse       As Long   ' 1 (-r), 2 (-R) If Recursing Into Sub-Directories, Else 0\n  fRepair        As Long   ' 1 = Fix Archive, 2 = Try Harder To Fix, Else 0\n  flevel         As Byte   ' Compression Level - 0 = Stored 6 = Default 9 = Max\nEnd Type\n\n\n' Used by SetZipOptions\nPublic Enum ZipModeType\n    Add = 0\n    Delete = 1\n    Update = 2\n    Freshen = 3\nEnd Enum\nPublic Enum CompressionLevelType\n    c0_NoCompression = 0\n    c1_Fast = 1\n    c2_Fast = 2\n    c3_Fast = 3\n    c4_Med = 4\n    c5_Med = 5\n    c6_Default = 6\n    c7_Extra = 7\n    c8_Extra = 8\n    c9_Max = 9\nEnd Enum\nPublic Enum Translate_LF_Type\n    No_Line_End_Trans = 0\n    LF_To_CRLF = 1\n    CRLF_To_LF = 2\nEnd Enum\nPublic Enum RepairType\n    NoRepair = 0\n    TryFix = 1\n    TryFixHarder = 2\nEnd Enum\nPublic Enum VerbosenessType\n    Quiet = 0\n    Normal = 1\n    Verbose = 2\nEnd Enum\nPublic Enum RecurseType\n    NoRecurse = 0\n    r_RecurseIntoSubdirectories = 1\n    R_RecurseUsingPatterns = 2\nEnd Enum\n\n\n'-- This Structure Is Used For The ZIP32z64.DLL Function Callbacks\n'   Assumes Zip32z64.dll with Zip64 enabled\nPublic Type ZIPUSERFUNCTIONS\n  ZDLLPrnt     As Long           ' Callback ZIP32z64.DLL Print Function\n  ZDLLCOMMENT  As Long           ' Callback ZIP32z64.DLL Comment Function\n  ZDLLPASSWORD As Long           ' Callback ZIP32z64.DLL Password Function\n  ZDLLSPLIT    As Long           ' Callback ZIP32z64.DLL Split Select Function\n  ' There are 2 versions of SERVICE, we use one does not need 64-bit data type\n  ZDLLSERVICE  As Long           ' Callback ZIP32z64.DLL Service Function\n  ZDLLSERVICE_NO_INT64  As Long  ' Callback ZIP32z64.DLL Service Function\nEnd Type\n\n'-- Default encryption password (used in callback if not empty string)\nPublic EncryptionPassword As String\n\n'-- For setting the archive comment\nPublic ArchiveCommentText\n\n'-- version info\nPublic ZipVersion As ZipVerType\n\n'-- Local Declarations\nPublic ZOPT  As ZpOpt\nPublic ZUSER As ZIPUSERFUNCTIONS\n\n'-- This Assumes ZIP32z64.DLL Is In Your \\windows\\system directory\n'-- or a copy is in the program directory or in some other directory\n'-- listed in PATH\nPrivate Declare Function ZpInit Lib \"zip32z64.dll\" _\n  (ByRef Zipfun As ZIPUSERFUNCTIONS) As Long '-- Set Zip Callbacks\n\nPrivate Declare Function ZpArchive Lib \"zip32z64.dll\" _\n  (ByVal argc As Long, ByVal funame As String, _\n   ByRef argv As ZIPnames, ByVal strNames As String, ByRef Opts As ZpOpt) As Long '-- Real Zipping Action\n\nPrivate Declare Sub ZpVersion Lib \"zip32z64.dll\" _\n  (ByRef ZipVersion As ZipVerType) '-- Version of DLL\n\n\n'-------------------------------------------------------\n'-- Public Variables For Setting The ZPOPT Structure...\n'-- (WARNING!!!) You Must Set The Options That You\n'-- Want The ZIP32.DLL To Do!\n'-- Before Calling VBZip32!\n'--\n'-- NOTE: See The Above ZPOPT Structure Or The VBZip32\n'--       Function, For The Meaning Of These Variables\n'--       And How To Use And Set Them!!!\n'-- These Parameters Must Be Set Before The Actual Call\n'-- To The VBZip32 Function!\n'-------------------------------------------------------\n\n'-- Public Program Variables\nPublic zArgc           As Integer     ' Number Of Files To Zip Up\nPublic zZipArchiveName As String      ' The Zip File Name ie: Myzip.zip\nPublic zZipFileNames   As ZIPnames    ' File Names To Zip Up\nPublic strZipFileNames As String      ' String of names to Zip Up\nPublic zZipInfo        As String      ' Holds The Zip File Information\n\n'-- Public Constants\n'-- For Zip & UnZip Error Codes!\nPublic Const ZE_OK = 0              ' Success (No Error)\nPublic Const ZE_EOF = 2             ' Unexpected End Of Zip File Error\nPublic Const ZE_FORM = 3            ' Zip File Structure Error\nPublic Const ZE_MEM = 4             ' Out Of Memory Error\nPublic Const ZE_LOGIC = 5           ' Internal Logic Error\nPublic Const ZE_BIG = 6             ' Entry Too Large To Split Error\nPublic Const ZE_NOTE = 7            ' Invalid Comment Format Error\nPublic Const ZE_TEST = 8            ' Zip Test (-T) Failed Or Out Of Memory Error\nPublic Const ZE_ABORT = 9           ' User Interrupted Or Termination Error\nPublic Const ZE_TEMP = 10           ' Error Using A Temp File\nPublic Const ZE_READ = 11           ' Read Or Seek Error\nPublic Const ZE_NONE = 12           ' Nothing To Do Error\nPublic Const ZE_NAME = 13           ' Missing Or Empty Zip File Error\nPublic Const ZE_WRITE = 14          ' Error Writing To A File\nPublic Const ZE_CREAT = 15          ' Could't Open To Write Error\nPublic Const ZE_PARMS = 16          ' Bad Command Line Argument Error\nPublic Const ZE_OPEN = 18           ' Could Not Open A Specified File To Read Error\n\n'-- These Functions Are For The ZIP32z64.DLL\n'--\n'-- Puts A Function Pointer In A Structure\n'-- For Use With Callbacks...\nPublic Function FnPtr(ByVal lp As Long) As Long\n    \n  FnPtr = lp\n\nEnd Function\n\n'-- Callback For ZIP32z64.DLL - DLL Print Function\nPublic Function ZDLLPrnt(ByRef fname As ZipCBChar, ByVal x As Long) As Long\n    \n  Dim s0 As String\n  Dim xx As Long\n    \n  '-- Always Put This In Callback Routines!\n  On Error Resume Next\n    \n  s0 = \"\"\n    \n  '-- Get Zip32.DLL Message For processing\n  For xx = 0 To x\n    If fname.ch(xx) = 0 Then\n      Exit For\n    Else\n      s0 = s0 + Chr(fname.ch(xx))\n    End If\n  Next\n    \n  '----------------------------------------------\n  '-- This Is Where The DLL Passes Back Messages\n  '-- To You! You Can Change The Message Printing\n  '-- Below Here!\n  '----------------------------------------------\n  \n  '-- Display Zip File Information\n  '-- zZipInfo = zZipInfo & s0\n  Form1.Print s0;\n    \n  DoEvents\n    \n  ZDLLPrnt = 0\n\nEnd Function\n\n'-- Callback For ZIP32z64.DLL - DLL Service Function\nPublic Function ZDLLServ(ByRef mname As ZipCBChar, _\n                         ByVal LowSize As Long, _\n                         ByVal HighSize As Long) As Long\n\n    Dim s0 As String\n    Dim xx As Long\n    Dim FS As Currency  ' for large file sizes\n    \n    '-- Always Put This In Callback Routines!\n    On Error Resume Next\n    \n    FS = (HighSize * &H10000 * &H10000) + LowSize\n '   Form1.Print \"ZDLLServ returned File Size High \" & HighSize & _\n '               \" Low \" & LowSize & \" = \" & FS & \" bytes\"\n    \n    s0 = \"\"\n    '-- Get Zip32.DLL Message For processing\n    For xx = 0 To 4096 ' x\n    If mname.ch(xx) = 0 Then\n        Exit For\n    Else\n        s0 = s0 + Chr(mname.ch(xx))\n    End If\n    Next\n    ' At this point, s0 contains the message passed from the DLL\n    ' It is up to the developer to code something useful here :)\n    ZDLLServ = 0 ' Setting this to 1 will abort the zip!\n    \nEnd Function\n\n'-- Callback For ZIP32z64.DLL - DLL Password Function\nPublic Function ZDLLPass(ByRef p As ZipCBChar, _\n  ByVal n As Long, ByRef m As ZipCBChar, _\n  ByRef Name As ZipCBChar) As Integer\n  \n  Dim filename   As String\n  Dim prompt     As String\n  Dim xx         As Integer\n  Dim szpassword As String\n  \n  '-- Always Put This In Callback Routines!\n  On Error Resume Next\n    \n  ZDLLPass = 1\n  \n  '-- User Entered A Password So Proccess It\n  \n  '-- Enter or Verify\n  For xx = 0 To 255\n    If m.ch(xx) = 0 Then\n      Exit For\n    Else\n      prompt = prompt & Chr(m.ch(xx))\n    End If\n  Next\n  \n  '-- If There Is A Password Have The User Enter It!\n  '-- This Can Be Changed\n  \n  '-- Now skip asking if default password set\n  If EncryptionPassword <> \"\" Then\n    szpassword = EncryptionPassword\n  Else\n    szpassword = InputBox(\"Please Enter The Password!\", prompt)\n  End If\n  \n  '-- The User Did Not Enter A Password So Exit The Function\n  If szpassword = \"\" Then Exit Function\n  \n  For xx = 0 To n - 1\n    p.ch(xx) = 0\n  Next\n  \n  For xx = 0 To Len(szpassword) - 1\n    p.ch(xx) = Asc(Mid(szpassword, xx + 1, 1))\n  Next\n  \n  p.ch(xx) = Chr(0) ' Put Null Terminator For C\n  \n  ZDLLPass = 0\n    \nEnd Function\n\n'-- Callback For ZIP32z64.DLL - DLL Comment Function\nPublic Function ZDLLComm(ByRef s1 As ZipCBChar) As Integer\n    \n    Dim comment As String\n    Dim xx%, szcomment$\n    \n    '-- Always Put This In Callback Routines!\n    On Error Resume Next\n    \n    ZDLLComm = 1\n    If Not IsEmpty(ArchiveCommentText) Then\n      ' use text given to SetZipOptions\n      szcomment = ArchiveCommentText\n    Else\n      For xx = 0 To 4095\n        szcomment = szcomment & Chr(s1.ch(xx))\n        If s1.ch(xx) = 0 Then\n          Exit For\n        End If\n      Next\n      comment = InputBox(\"Enter or edit the comment\", Default:=szcomment)\n      If comment = \"\" Then\n        ' either empty comment or Cancel button\n        If MsgBox(\"Remove comment?\" & Chr(13) & \"Hit No to keep existing comment\", vbYesNo) = vbYes Then\n            szcomment = comment\n        Else\n          Exit Function\n        End If\n      End If\n      szcomment = comment\n    End If\n    'If szcomment = \"\" Then Exit Function\n    For xx = 0 To Len(szcomment) - 1\n        s1.ch(xx) = Asc(Mid$(szcomment, xx + 1, 1))\n    Next xx\n    s1.ch(xx) = 0 ' Put null terminator for C\n\nEnd Function\n\n' This function can be used to set options in VB\nPublic Function SetZipOptions(ByRef ZipOpts As ZpOpt, _\n  Optional ByVal ZipMode As ZipModeType = Add, _\n  Optional ByVal RootDirToZipFrom As String = \"\", _\n  Optional ByVal CompressionLevel As CompressionLevelType = c6_Default, _\n  Optional ByVal RecurseSubdirectories As RecurseType = NoRecurse, _\n  Optional ByVal Verboseness As VerbosenessType = Normal, _\n  Optional ByVal i_IncludeFiles As String = \"\", _\n  Optional ByVal x_ExcludeFiles As String = \"\", _\n  Optional ByVal UpdateSFXOffsets As Boolean = False, Optional ByVal JunkDirNames As Boolean = False, _\n  Optional ByVal Encrypt As Boolean = False, Optional ByVal Password As String = \"\", _\n  Optional ByVal Repair As RepairType = NoRepair, Optional ByVal NoDirEntries As Boolean = False, _\n  Optional ByVal GrowExistingArchive As Boolean = False, _\n  Optional ByVal JunkSFXPrefix As Boolean = False, Optional ByVal ForceUseOfDOSNames As Boolean = False, _\n  Optional ByVal Translate_LF As Translate_LF_Type = No_Line_End_Trans, _\n  Optional ByVal Move_DeleteAfterAddedOrUpdated As Boolean = False, _\n  Optional ByVal SetZipTimeToLatestTime As Boolean = False, _\n  Optional ByVal IncludeSystemAndHiddenFiles As Boolean = False, _\n  Optional ByVal ExcludeEarlierThanDate As String = \"\", _\n  Optional ByVal IncludeEarlierThanDate As String = \"\", _\n  Optional ByVal IncludeVolumeLabel As Boolean = False, _\n  Optional ByVal ArchiveComment As Boolean = False, _\n  Optional ByVal ArchiveCommentTextString = Empty, _\n  Optional ByVal UsePrivileges As Boolean = False, _\n  Optional ByVal ExcludeExtraAttributes As Boolean = False, Optional ByVal SplitSize As String = \"\", _\n  Optional ByVal TempDirPath As String = \"\") As Boolean\n\n  Dim SplitNum As Long\n  Dim SplitMultS As String\n  Dim SplitMult As Long\n  \n  ' set some defaults\n  ZipOpts.date = vbNullString\n  ZipOpts.szRootDir = vbNullString\n  ZipOpts.szTempDir = vbNullString\n  ZipOpts.fTemp = 0\n  ZipOpts.fSuffix = 0\n  ZipOpts.fEncrypt = 0\n  ZipOpts.fSystem = 0\n  ZipOpts.fVolume = 0\n  ZipOpts.fExtra = 0\n  ZipOpts.fNoDirEntries = 0\n  ZipOpts.fExcludeDate = 0\n  ZipOpts.fIncludeDate = 0\n  ZipOpts.fVerbose = 0\n  ZipOpts.fQuiet = 0\n  ZipOpts.fCRLF_LF = 0\n  ZipOpts.fLF_CRLF = 0\n  ZipOpts.fJunkDir = 0\n  ZipOpts.fGrow = 0\n  ZipOpts.fForce = 0\n  ZipOpts.fMove = 0\n  ZipOpts.fDeleteEntries = 0\n  ZipOpts.fUpdate = 0\n  ZipOpts.fFreshen = 0\n  ZipOpts.fJunkSFX = 0\n  ZipOpts.fLatestTime = 0\n  ZipOpts.fComment = 0\n  ZipOpts.fOffsets = 0\n  ZipOpts.fPrivilege = 0\n  ZipOpts.szSplitSize = vbNullString\n  ZipOpts.IncludeListCount = 0\n  ZipOpts.szIncludeList = vbNullString\n  ZipOpts.ExcludeListCount = 0\n  ZipOpts.szExcludeList = vbNullString\n  ZipOpts.fRecurse = 0\n  ZipOpts.fRepair = 0\n  ZipOpts.flevel = 0\n  \n  If RootDirToZipFrom <> \"\" Then\n    ZipOpts.szRootDir = RootDirToZipFrom\n  End If\n  ZipOpts.flevel = Asc(CompressionLevel)\n  If UpdateSFXOffsets Then ZipOpts.fOffsets = 1\n  \n  If i_IncludeFiles <> \"\" Then\n    ZipOpts.szIncludeList = i_IncludeFiles\n  End If\n  If x_ExcludeFiles <> \"\" Then\n    ZipOpts.szExcludeList = x_ExcludeFiles\n  End If\n  \n  If ZipMode = Add Then\n    ' default\n  ElseIf ZipMode = Delete Then\n    ZipOpts.fDeleteEntries = 1\n  ElseIf ZipMode = Update Then\n    ZipOpts.fUpdate = 1\n  Else\n    ZipOpts.fFreshen = 1\n  End If\n  ZipOpts.fRepair = Repair\n  If GrowExistingArchive Then ZipOpts.fGrow = 1\n  If Move_DeleteAfterAddedOrUpdated Then ZipOpts.fMove = 1\n    \n  If Verboseness = Quiet Then\n    ZipOpts.fQuiet = 1\n  ElseIf Verboseness = Verbose Then\n    ZipOpts.fVerbose = 1\n  End If\n  \n  If ArchiveComment = False And Not IsEmpty(ArchiveCommentTextString) Then\n    MsgBox \"Must set ArchiveComment = True to set ArchiveCommentTextString\"\n    Exit Function\n  End If\n  If IsEmpty(ArchiveCommentTextString) Then\n    ArchiveCommentText = Empty\n  Else\n    ArchiveCommentText = ArchiveCommentTextString\n  End If\n  If ArchiveComment Then ZipOpts.fComment = 1\n  \n  If NoDirEntries Then ZipOpts.fNoDirEntries = 1\n  If JunkDirNames Then ZipOpts.fJunkDir = 1\n  If Encrypt Then ZipOpts.fEncrypt = 1\n  EncryptionPassword = Password\n  If JunkSFXPrefix Then ZipOpts.fJunkSFX = 1\n  If ForceUseOfDOSNames Then ZipOpts.fForce = 1\n  If Translate_LF = LF_To_CRLF Then ZipOpts.fLF_CRLF = 1\n  If Translate_LF = CRLF_To_LF Then ZipOpts.fCRLF_LF = 1\n  ZipOpts.fRecurse = RecurseSubdirectories\n  If IncludeSystemAndHiddenFiles Then ZipOpts.fSystem = 1\n  \n  If SetZipTimeToLatestTime Then ZipOpts.fLatestTime = 1\n  If ExcludeEarlierThanDate <> \"\" And IncludeEarlierThanDate <> \"\" Then\n    MsgBox \"Both ExcludeEarlierThanDate and IncludeEarlierThanDate not \" & Chr(10) & _\n           \"supported at same time\"\n    Exit Function\n  End If\n  If ExcludeEarlierThanDate <> \"\" Then\n    ZipOpts.fIncludeDate = 1\n    ZipOpts.date = ExcludeEarlierThanDate\n  End If\n  If IncludeEarlierThanDate <> \"\" Then\n    ZipOpts.fExcludeDate = 1\n    ZipOpts.date = IncludeEarlierThanDate\n  End If\n  \n  If TempDirPath <> \"\" Then\n    ZipOpts.szTempDir = TempDirPath\n    ZipOpts.fTemp = 1\n  End If\n  \n  If SplitSize <> \"\" Then\n    SplitSize = Trim(SplitSize)\n    SplitMultS = Right(SplitSize, 1)\n    SplitMultS = UCase(SplitMultS)\n    If (SplitMultS = \"K\") Then\n        SplitMult = 1024\n        SplitNum = Val(Left(SplitSize, Len(SplitSize) - 1))\n    ElseIf SplitMultS = \"M\" Then\n        SplitMult = 1024 * 1024&\n        SplitNum = Val(Left(SplitSize, Len(SplitSize) - 1))\n    ElseIf SplitMultS = \"G\" Then\n        SplitMult = 1024 * 1024 * 1024&\n        SplitNum = Val(Left(SplitSize, Len(SplitSize) - 1))\n    Else\n        SplitMult = 1024 * 1024&\n        SplitNum = Val(SplitSize)\n    End If\n    SplitNum = SplitNum * SplitMult\n    If SplitNum = 0 Then\n        MsgBox \"SplitSize of 0 not supported\"\n        Exit Function\n    ElseIf SplitNum < 64 * 1024& Then\n        MsgBox \"SplitSize must be at least 64k\"\n        Exit Function\n    End If\n    ZipOpts.szSplitSize = SplitSize\n  End If\n  \n  If IncludeVolumeLabel Then ZipOpts.fVolume = 1\n  If UsePrivileges Then ZipOpts.fPrivilege = 1\n  If ExcludeExtraAttributes Then ZipOpts.fExtra = 1\n  \n  SetZipOptions = True\n    \nEnd Function\n\nFunction ChopNulls(ByVal Str) As String\n  Dim A As Integer\n  Dim C As String\n    \n  For A = 1 To Len(Str)\n    If Mid(Str, A, 1) = Chr(0) Then\n      ChopNulls = Left(Str, A - 1)\n      Exit Function\n    End If\n  Next\n  ChopNulls = Str\n    \nEnd Function\nSub DisplayVersion()\n  \n  ' display version of DLL\n  Dim Beta As Boolean\n  Dim ZLIB As Boolean\n  Dim Zip64 As Boolean\n  Dim Flags As String\n  Dim A As Integer\n  \n  ZipVersion.structlen = Len(ZipVersion)\n  ZpVersion ZipVersion\n  ' Check flag\n  If ZipVersion.flag And 1 Then\n    Flags = Flags & \" Beta,\"\n    Beta = True\n  Else\n    Flags = Flags & \" No Beta,\"\n  End If\n  If ZipVersion.flag And 2 Then\n    Flags = Flags & \" ZLIB,\"\n    ZLIB = True\n  Else\n    Flags = Flags & \" No ZLIB,\"\n  End If\n  If ZipVersion.flag And 4 Then\n    Flags = Flags & \" Zip64, \"\n    Zip64 = True\n  Else\n    Flags = Flags & \" No Zip64, \"\n  End If\n  If ZipVersion.encryption Then\n    Flags = Flags & \"Encryption\"\n  Else\n    Flags = Flags & \" No encryption\"\n  End If\n  \n  Form1.Caption = \"Using Zip32z64.DLL Version \" & _\n                  ZipVersion.ZipVersion.Major & \".\" & ZipVersion.ZipVersion.Minor & \" \" & _\n                  ChopNulls(ZipVersion.Beta) & \"  [\" & ChopNulls(ZipVersion.date) & \"]\" & _\n                  \" - FLAGS: \" & Flags\n\n  If Not Zip64 Then\n    A = MsgBox(\"Zip32z64.dll not compiled with Zip64 enabled - continue?\", _\n               vbOKCancel, _\n               \"Wrong dll\")\n    If A = vbCancel Then\n        End\n    End If\n  End If\n  \nEnd Sub\n\n'-- Main ZIP32.DLL Subroutine.\n'-- This Is Where It All Happens!!!\n'--\n'-- (WARNING!) Do Not Change This Function!!!\n'--\nPublic Function VBZip32() As Long\n    \n  Dim retcode As Long\n  Dim FileNotFound As Boolean\n    \n  ' On Error Resume Next '-- Nothing Will Go Wrong :-)\n  On Error GoTo ZipError\n    \n  retcode = 0\n    \n  '-- Set Address Of ZIP32.DLL Callback Functions\n  '-- (WARNING!) Do Not Change!!! (except as noted below)\n  ZUSER.ZDLLPrnt = FnPtr(AddressOf ZDLLPrnt)\n  ZUSER.ZDLLPASSWORD = FnPtr(AddressOf ZDLLPass)\n  ZUSER.ZDLLCOMMENT = FnPtr(AddressOf ZDLLComm)\n  ZUSER.ZDLLSERVICE_NO_INT64 = FnPtr(AddressOf ZDLLServ)\n  \n  ' If you need to set destination of each split set this\n  'ZUSER.ZDLLSPLIT = FnPtr(AddressOf ZDLLSplitSelect)\n\n  '-- Set ZIP32.DLL Callbacks - return 1 if DLL loaded 0 if not\n  retcode = ZpInit(ZUSER)\n  If retcode = 0 And FileNotFound Then\n    MsgBox \"Probably could not find Zip32z64.DLL - have you copied\" & Chr(10) & _\n           \"it to the System directory, your program directory, \" & Chr(10) & _\n           \"or a directory on your command PATH?\"\n    VBZip32 = retcode\n    Exit Function\n  End If\n  \n  DisplayVersion\n    \n  If strZipFileNames = \"\" Then\n    ' not using string of names to zip (so using array of names)\n    strZipFileNames = vbNullString\n  End If\n  \n  '-- Go Zip It Them Up!\n  retcode = ZpArchive(zArgc, zZipArchiveName, zZipFileNames, strZipFileNames, ZOPT)\n  \n  '-- Return The Function Code\n  VBZip32 = retcode\n\n  Exit Function\n\nZipError:\n  MsgBox \"Error:  \" & Err.Description\n  If Err = 48 Then\n    FileNotFound = True\n  End If\n  Resume Next\n\nEnd Function\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/VBz64/Vbzipfrm.frm",
    "content": "VERSION 5.00\nBegin VB.Form Form1 \n   AutoRedraw      =   -1  'True\n   Caption         =   \"Form1\"\n   ClientHeight    =   3150\n   ClientLeft      =   60\n   ClientTop       =   345\n   ClientWidth     =   6570\n   BeginProperty Font \n      Name            =   \"MS Sans Serif\"\n      Size            =   9.75\n      Charset         =   0\n      Weight          =   700\n      Underline       =   0   'False\n      Italic          =   0   'False\n      Strikethrough   =   0   'False\n   EndProperty\n   LinkTopic       =   \"Form1\"\n   ScaleHeight     =   3150\n   ScaleWidth      =   6570\n   StartUpPosition =   1  'CenterOwner\nEnd\nAttribute VB_Name = \"Form1\"\nAttribute VB_GlobalNameSpace = False\nAttribute VB_Creatable = False\nAttribute VB_PredeclaredId = True\nAttribute VB_Exposed = False\n\nOption Explicit\n\n'---------------------------------------------------------------\n'-- Sample VB 6 code to drive zip32z64.dll\n'--\n'-- Based on code contributed to the Info-ZIP project by Mike Le Voi\n'--\n'-- See the Original VB example in a separate directory for\n'-- more information\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'---------------------------------------------------------------\n'--\n'-- The Source Code Is Freely Available From Info-ZIP At:\n'--   ftp://ftp.info-zip.org/pub/infozip/infozip.html\n'-- and\n'--   http://sourceforge.net/projects/infozip/\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White Of The Info-ZIP project\n'-- For Letting Me Use And Modify His Orginal\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'---------------------------------------------------------------\n'--\n'-- Contributed To The Info-ZIP Project By Raymond L. King\n'-- Modified June 21, 1998\n'-- By Raymond L. King\n'-- Custom Software Designers\n'--\n'-- Contact Me At: king@ntplx.net\n'-- ICQ 434355\n'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\n'--\n'---------------------------------------------------------------\n\n'---------------------------------------------------------------\n' Zip32z64.dll is the new Zip32.dll based on Zip 3.0 and compiled\n' with Zip64 support enabled.  See windll.txt in the windll directory\n' for more on Zip32z64 and the comments in VBZipBas.bas.\n'\n' Contact Info-Zip if problems.  This code is\n' provided under the Info-Zip license.\n'\n' 4/24/2004, 12/4/2007 EG\n'---------------------------------------------------------------\n\nPrivate Sub Form_Click()\n\n  Dim retcode As Integer  ' For Return Code From ZIP32.DLL\n  Dim iFiles As String\n  Dim FilesToZip() As String\n  Dim i As Long\n\n  Cls\n\n  '-- Set Options - Only The Common Ones Are Shown Here\n  '-- These Must Be Set Before Calling The VBZip32 Function\n  \n  ' In VB 6 you can see the list of possible options and the defaults\n  ' by adding a space between any parameters which should make the tip box\n  ' appear.  Delete a := and retype to see a list of choices.\n\n  ' Be warned:  There are bugs in the previous dll.  See the Original VB\n  ' example in the VB directory for details.\n  \n  If Not SetZipOptions(ZOPT, _\n                       ZipMode:=Add, _\n                       CompressionLevel:=c6_Default) Then\n           ' Some additional options ...\n           '            RootDirToZipFrom:=\"\", _\n           '   strip paths and just store names:\n           '            JunkDirNames:=False, _\n           '   do not store entries for the directories themselves:\n           '            NoDirEntries:=True _\n           '   include files only if match one of these patterns:\n           '            i_IncludeFiles:=\"*.vbp *.frm\", _\n           '   exclude files that match these patterns:\n           '            x_ExcludeFiles:=\"*.bas\", _\n           '            Verboseness:=Verbose, _\n           '            IncludeEarlierThanDate:=\"2004-4-1\", _\n           '            RecurseSubdirectories:=r_RecurseIntoSubdirectories, _\n           '            Encrypt:=False, _\n           '            ArchiveComment:=False\n           ' date example (format mmddyyyy or yyyy-mm-dd):\n           '           ExcludeEarlierThanDate:=\"2002-12-10\", _\n           ' split example (can only create, can't update split archives in VB):\n           '            SplitSize:=\"110k\", _\n' Delete\n ' If Not SetZipOptions(ZOPT, _\n '                      ZipMode:=Delete) Then\n \n    ' a problem if get here - error message already displayed so just exit\n    Exit Sub\n  End If\n  \n\n  '-- Select Some Files - Wildcards Are Supported\n  '-- Change The Paths Here To Your Directory\n  '-- And Files!!!\n\n  ' default to current (VB project) directory and zip up project files\n  zZipArchiveName = \"MyFirst.zip\"\n  \n  \n  ' Files to zip - use one of below\n  \n  '---------------\n  ' Example using file name array\n  \n  ' Store the file paths\n  ' Change Dim of zFiles at top of VBZipBas.bas if more than 100 files\n  ' See note at top of VBZipBas.bas for limit on number of files\n  \n'  zArgc = 2           ' Number Of file paths below\n'  zZipFileNames.zFiles(1) = \"*.bas\"\n'  zZipFileNames.zFiles(2) = \"*.frm\"\n  \n  '---------------\n  ' Example using file list string\n  \n  ' List of files to zip as string of names with space between\n  ' Set zArgc = 0 as not using array\n  ' Using string for file list avoids above array limit\n  \n  zArgc = 0\n'  ReDim FilesToZip(1)      ' dim to number of files below\n'  FilesToZip(1) = \"x:*.*\"\n  ReDim FilesToZip(2)      ' dim to number of files below\n  FilesToZip(1) = \"*.bas\"\n  FilesToZip(2) = \"*.frm\"\n \n  ' Build string of file names\n  ' Best to put double quotes around each in case of spaces\n  strZipFileNames = \"\"\n  For i = 1 To UBound(FilesToZip)\n    strZipFileNames = strZipFileNames & \"\"\"\" & FilesToZip(i) & \"\"\" \"\n  Next\n  '---------------\n  \n  '-- Go Zip Them Up!\n  retcode = VBZip32()\n\n  '-- Display The Returned Code Or Error!\n  Print \"Return code:\" & Str(retcode)\n\nEnd Sub\n\nPrivate Sub Form_Load()\n\n  Me.Show\n\n  Print \"Click me!\"\n\nEnd Sub\n"
  },
  {
    "path": "deps/infozip/zip30/windll/VBz64/readVB64.txt",
    "content": "On Windows open this file in WordPad.\n\nContents of the \"windll/vbz64\" sub-archive\n\nThis directory contains a Visual Basic project example for using the\nzip32z64.dll library (Zip 3.0 with Zip64 enabled).  See the comments in\nthe form and project files for details.\n\nThis new project and the new zip32z64.dll library are not compatible\nwith previous VB examples using the zip32.dll interface as this new\ninterface supports more files and handles file sizes larger than 2 GB.\nIt should be simple to convert a VB program using zip32.dll to\nzip32z64.dll but the program may need some changes.  For a compatible\nreplacement use the dll compiled from Zip 2.32 (released separately)\nand see the zip32.dll example in the VB directory of this source tree.\n\nNote that the files may be saved in unix format with carriage returns\nstripped.  These must be restored before the project can be successfully\nused.  This can be done by using the -a option to unzip.  Another way to\ndo this is to open each file in WordPad, select and cut a line, paste\nthe line back, and save the file.  This will force WordPad to change the\nline ends in the entire file.  Newer versions of WordPad may not do this.\n\nEd Gordon\n4/26/2008\n"
  },
  {
    "path": "deps/infozip/zip30/windll/Vb/VBZIP.vbw",
    "content": "Form1 = 0, 0, 0, 0, C, 22, 22, 563, 389, C\nVBZipBas = 44, 44, 659, 489, \n"
  },
  {
    "path": "deps/infozip/zip30/windll/Vb/VBZipBas.bas",
    "content": "Attribute VB_Name = \"VBZipBas\"\n\nOption Explicit\n\n'---------------------------------------------------------------\n'-- Please Do Not Remove These Comments!!!\n'---------------------------------------------------------------\n'-- Sample VB 5 code to drive zip32.dll\n'-- Contributed to the Info-ZIP project by Mike Le Voi\n'--\n'-- Contact me at: mlevoi@modemss.brisnet.org.au\n'--\n'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'---------------------------------------------------------------\n'--\n'-- The Source Code Is Freely Available From Info-ZIP At:\n'-- http://www.cdrom.com/pub/infozip/infozip.html\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White Of The Info-ZIP\n'-- For Letting Me Use And Modify His Orginal\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'---------------------------------------------------------------\n'--\n'-- Contributed To The Info-ZIP Project By Raymond L. King\n'-- Modified June 21, 1998\n'-- By Raymond L. King\n'-- Custom Software Designers\n'--\n'-- Contact Me At: king@ntplx.net\n'-- ICQ 434355\n'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\n'--\n'---------------------------------------------------------------\n'\n' This is the original example with some small changes.  Only\n' use with the original Zip32.dll (compiled from Zip 2.31 or\n' later).  Do not use this VB example with Zip32z64.dll\n' (compiled from Zip 3.0).  To check the version of a dll,\n' right click on the file and check properties.\n'\n' 6/24/2008 Ed Gordon\n\n'---------------------------------------------------------------\n' Usage notes:\n'\n' This code uses Zip32.dll.  You DO NOT need to register the\n' DLL to use it.  You also DO NOT need to reference it in your\n' VB project.  You DO have to copy the DLL to your SYSTEM\n' directory, your VB project directory, or place it in a directory\n' on your command PATH.\n'\n' A bug has been found in the Zip32.dll when called from VB.  If\n' you try to pass any values other than NULL in the ZPOPT strings\n' Date, szRootDir, or szTempDir they get converted from the\n' VB internal wide character format to temporary byte strings by\n' the calling interface as they are supposed to.  However when\n' ZpSetOptions returns the passed strings are deallocated unless the\n' VB debugger prevents it by a break between ZpSetOptions and\n' ZpArchive.  When Zip32.dll uses these pointers later it\n' can result in unpredictable behavior.  A kluge is available\n' for Zip32.dll, just replacing api.c in Zip 2.3, but better to just\n' use the new Zip32z64.dll where these bugs are fixed.  However,\n' the kluge has been added to Zip 2.31 and later and these are\n' now stable.  To determine the version of the dll you have\n' right click on it, select the Version tab, and verify the\n' Product Version is at least 2.31.\n'\n' Another bug is where -R is used with some other options and can\n' crash the dll.  This is a bug in how zip processes the command\n' line and should be mostly fixed in Zip 2.31.  If you run into\n' problems try using -r instead for recursion.  The bug is fixed\n' in Zip 3.0 but note that Zip 3.0 creates dll zip32z64.dll and\n' it is not compatible with older VB including this example.  See\n' the new VB example code included with Zip 3.0 for calling\n' interface changes.\n'\n' Note that Zip32 is probably not thread safe.  It may be made\n' thread safe in a later version, but for now only one thread in\n' one program should use the DLL at a time.  Unlike Zip, UnZip is\n' probably thread safe, but an exception to this has been\n' found.  See the UnZip documentation for the latest on this.\n'\n' All code in this VB project is provided under the Info-Zip license.\n'\n' If you have any questions please contact Info-Zip at\n' http://www.info-zip.org.\n'\n' 4/29/2004 EG (Updated 3/1/2005, 6/24/2008 EG)\n'\n'---------------------------------------------------------------\n\n\n'-- C Style argv\n'-- Holds The Zip Archive Filenames\n' Max for this just over 8000 as each pointer takes up 4 bytes and\n' VB only allows 32 kB of local variables and that includes function\n' parameters.  - 3/19/2004 EG\n'\nPublic Type ZIPnames\n  zFiles(0 To 99) As String\nEnd Type\n\n'-- Call Back \"String\"\nPublic Type ZipCBChar\n  ch(4096) As Byte\nEnd Type\n\n'-- ZPOPT Is Used To Set The Options In The ZIP32.DLL\nPublic Type ZPOPT\n  Date           As String ' US Date (8 Bytes Long) \"12/31/98\"?\n  szRootDir      As String ' Root Directory Pathname (Up To 256 Bytes Long)\n  szTempDir      As String ' Temp Directory Pathname (Up To 256 Bytes Long)\n  fTemp          As Long   ' 1 If Temp dir Wanted, Else 0\n  fSuffix        As Long   ' Include Suffixes (Not Yet Implemented!)\n  fEncrypt       As Long   ' 1 If Encryption Wanted, Else 0\n  fSystem        As Long   ' 1 To Include System/Hidden Files, Else 0\n  fVolume        As Long   ' 1 If Storing Volume Label, Else 0\n  fExtra         As Long   ' 1 If Excluding Extra Attributes, Else 0\n  fNoDirEntries  As Long   ' 1 If Ignoring Directory Entries, Else 0\n  fExcludeDate   As Long   ' 1 If Excluding Files Earlier Than Specified Date, Else 0\n  fIncludeDate   As Long   ' 1 If Including Files Earlier Than Specified Date, Else 0\n  fVerbose       As Long   ' 1 If Full Messages Wanted, Else 0\n  fQuiet         As Long   ' 1 If Minimum Messages Wanted, Else 0\n  fCRLF_LF       As Long   ' 1 If Translate CR/LF To LF, Else 0\n  fLF_CRLF       As Long   ' 1 If Translate LF To CR/LF, Else 0\n  fJunkDir       As Long   ' 1 If Junking Directory Names, Else 0\n  fGrow          As Long   ' 1 If Allow Appending To Zip File, Else 0\n  fForce         As Long   ' 1 If Making Entries Using DOS File Names, Else 0\n  fMove          As Long   ' 1 If Deleting Files Added Or Updated, Else 0\n  fDeleteEntries As Long   ' 1 If Files Passed Have To Be Deleted, Else 0\n  fUpdate        As Long   ' 1 If Updating Zip File-Overwrite Only If Newer, Else 0\n  fFreshen       As Long   ' 1 If Freshing Zip File-Overwrite Only, Else 0\n  fJunkSFX       As Long   ' 1 If Junking SFX Prefix, Else 0\n  fLatestTime    As Long   ' 1 If Setting Zip File Time To Time Of Latest File In Archive, Else 0\n  fComment       As Long   ' 1 If Putting Comment In Zip File, Else 0\n  fOffsets       As Long   ' 1 If Updating Archive Offsets For SFX Files, Else 0\n  fPrivilege     As Long   ' 1 If Not Saving Privileges, Else 0\n  fEncryption    As Long   ' Read Only Property!!!\n  fRecurse       As Long   ' 1 (-r), 2 (-R) If Recursing Into Sub-Directories, Else 0\n  fRepair        As Long   ' 1 = Fix Archive, 2 = Try Harder To Fix, Else 0\n  flevel         As Byte   ' Compression Level - 0 = Stored 6 = Default 9 = Max\nEnd Type\n\n'-- This Structure Is Used For The ZIP32.DLL Function Callbacks\nPublic Type ZIPUSERFUNCTIONS\n  ZDLLPrnt     As Long        ' Callback ZIP32.DLL Print Function\n  ZDLLCOMMENT  As Long        ' Callback ZIP32.DLL Comment Function\n  ZDLLPASSWORD As Long        ' Callback ZIP32.DLL Password Function\n  ZDLLSERVICE  As Long        ' Callback ZIP32.DLL Service Function\nEnd Type\n\n'-- Local Declarations\nPublic ZOPT  As ZPOPT\nPublic ZUSER As ZIPUSERFUNCTIONS\n\n'-- This Assumes ZIP32.DLL Is In Your \\Windows\\System Directory!\n'-- (alternatively, a copy of ZIP32.DLL needs to be located in the program\n'-- directory or in some other directory listed in PATH.)\nPrivate Declare Function ZpInit Lib \"zip32.dll\" _\n  (ByRef Zipfun As ZIPUSERFUNCTIONS) As Long '-- Set Zip Callbacks\n\nPrivate Declare Function ZpSetOptions Lib \"zip32.dll\" _\n  (ByRef Opts As ZPOPT) As Long '-- Set Zip Options\n\nPrivate Declare Function ZpGetOptions Lib \"zip32.dll\" _\n  () As ZPOPT '-- Used To Check Encryption Flag Only\n\nPrivate Declare Function ZpArchive Lib \"zip32.dll\" _\n  (ByVal argc As Long, ByVal funame As String, _\n   ByRef argv As ZIPnames) As Long '-- Real Zipping Action\n\n'-------------------------------------------------------\n'-- Public Variables For Setting The ZPOPT Structure...\n'-- (WARNING!!!) You Must Set The Options That You\n'-- Want The ZIP32.DLL To Do!\n'-- Before Calling VBZip32!\n'--\n'-- NOTE: See The Above ZPOPT Structure Or The VBZip32\n'--       Function, For The Meaning Of These Variables\n'--       And How To Use And Set Them!!!\n'-- These Parameters Must Be Set Before The Actual Call\n'-- To The VBZip32 Function!\n'-------------------------------------------------------\nPublic zDate         As String\nPublic zRootDir      As String\nPublic zTempDir      As String\nPublic zSuffix       As Integer\nPublic zEncrypt      As Integer\nPublic zSystem       As Integer\nPublic zVolume       As Integer\nPublic zExtra        As Integer\nPublic zNoDirEntries As Integer\nPublic zExcludeDate  As Integer\nPublic zIncludeDate  As Integer\nPublic zVerbose      As Integer\nPublic zQuiet        As Integer\nPublic zCRLF_LF      As Integer\nPublic zLF_CRLF      As Integer\nPublic zJunkDir      As Integer\nPublic zRecurse      As Integer\nPublic zGrow         As Integer\nPublic zForce        As Integer\nPublic zMove         As Integer\nPublic zDelEntries   As Integer\nPublic zUpdate       As Integer\nPublic zFreshen      As Integer\nPublic zJunkSFX      As Integer\nPublic zLatestTime   As Integer\nPublic zComment      As Integer\nPublic zOffsets      As Integer\nPublic zPrivilege    As Integer\nPublic zEncryption   As Integer\nPublic zRepair       As Integer\nPublic zLevel        As Integer\n\n'-- Public Program Variables\nPublic zArgc         As Integer     ' Number Of Files To Zip Up\nPublic zZipFileName  As String      ' The Zip File Name ie: Myzip.zip\nPublic zZipFileNames As ZIPnames    ' File Names To Zip Up\nPublic zZipInfo      As String      ' Holds The Zip File Information\n\n'-- Public Constants\n'-- For Zip & UnZip Error Codes!\nPublic Const ZE_OK = 0              ' Success (No Error)\nPublic Const ZE_EOF = 2             ' Unexpected End Of Zip File Error\nPublic Const ZE_FORM = 3            ' Zip File Structure Error\nPublic Const ZE_MEM = 4             ' Out Of Memory Error\nPublic Const ZE_LOGIC = 5           ' Internal Logic Error\nPublic Const ZE_BIG = 6             ' Entry Too Large To Split Error\nPublic Const ZE_NOTE = 7            ' Invalid Comment Format Error\nPublic Const ZE_TEST = 8            ' Zip Test (-T) Failed Or Out Of Memory Error\nPublic Const ZE_ABORT = 9           ' User Interrupted Or Termination Error\nPublic Const ZE_TEMP = 10           ' Error Using A Temp File\nPublic Const ZE_READ = 11           ' Read Or Seek Error\nPublic Const ZE_NONE = 12           ' Nothing To Do Error\nPublic Const ZE_NAME = 13           ' Missing Or Empty Zip File Error\nPublic Const ZE_WRITE = 14          ' Error Writing To A File\nPublic Const ZE_CREAT = 15          ' Could't Open To Write Error\nPublic Const ZE_PARMS = 16          ' Bad Command Line Argument Error\nPublic Const ZE_OPEN = 18           ' Could Not Open A Specified File To Read Error\n\n'-- These Functions Are For The ZIP32.DLL\n'--\n'-- Puts A Function Pointer In A Structure\n'-- For Use With Callbacks...\nPublic Function FnPtr(ByVal lp As Long) As Long\n    \n  FnPtr = lp\n\nEnd Function\n\n'-- Callback For ZIP32.DLL - DLL Print Function\nPublic Function ZDLLPrnt(ByRef fname As ZipCBChar, ByVal x As Long) As Long\n    \n  Dim s0 As String\n  Dim xx As Long\n    \n  '-- Always Put This In Callback Routines!\n  On Error Resume Next\n    \n  s0 = \"\"\n    \n  '-- Get Zip32.DLL Message For processing\n  For xx = 0 To x\n    If fname.ch(xx) = 0 Then\n      Exit For\n    Else\n      s0 = s0 + Chr(fname.ch(xx))\n    End If\n  Next\n    \n  '----------------------------------------------\n  '-- This Is Where The DLL Passes Back Messages\n  '-- To You! You Can Change The Message Printing\n  '-- Below Here!\n  '----------------------------------------------\n  \n  '-- Display Zip File Information\n  '-- zZipInfo = zZipInfo & s0\n  Form1.Print s0;\n    \n  DoEvents\n    \n  ZDLLPrnt = 0\n\nEnd Function\n\n'-- Callback For ZIP32.DLL - DLL Service Function\nPublic Function ZDLLServ(ByRef mname As ZipCBChar, ByVal x As Long) As Long\n\n    ' x is the size of the file\n    \n    Dim s0 As String\n    Dim xx As Long\n    \n    '-- Always Put This In Callback Routines!\n    On Error Resume Next\n    \n    s0 = \"\"\n    '-- Get Zip32.DLL Message For processing\n    For xx = 0 To 4096\n    If mname.ch(xx) = 0 Then\n        Exit For\n    Else\n        s0 = s0 + Chr(mname.ch(xx))\n    End If\n    Next\n    ' Form1.Print \"-- \" & s0 & \" - \" & x & \" bytes\"\n    \n    ' This is called for each zip entry.\n    ' mname is usually the null terminated file name and x the file size.\n    ' s0 has trimmed file name as VB string.\n\n    ' At this point, s0 contains the message passed from the DLL\n    ' It is up to the developer to code something useful here :)\n    ZDLLServ = 0 ' Setting this to 1 will abort the zip!\n    \nEnd Function\n\n'-- Callback For ZIP32.DLL - DLL Password Function\nPublic Function ZDLLPass(ByRef p As ZipCBChar, _\n  ByVal n As Long, ByRef m As ZipCBChar, _\n  ByRef Name As ZipCBChar) As Integer\n  \n  Dim prompt     As String\n  Dim xx         As Integer\n  Dim szpassword As String\n  \n  '-- Always Put This In Callback Routines!\n  On Error Resume Next\n    \n  ZDLLPass = 1\n  \n  '-- If There Is A Password Have The User Enter It!\n  '-- This Can Be Changed\n  szpassword = InputBox(\"Please Enter The Password!\")\n  \n  '-- The User Did Not Enter A Password So Exit The Function\n  If szpassword = \"\" Then Exit Function\n  \n  '-- User Entered A Password So Proccess It\n  For xx = 0 To 255\n    If m.ch(xx) = 0 Then\n      Exit For\n    Else\n      prompt = prompt & Chr(m.ch(xx))\n    End If\n  Next\n  \n  For xx = 0 To n - 1\n    p.ch(xx) = 0\n  Next\n  \n  For xx = 0 To Len(szpassword) - 1\n    p.ch(xx) = Asc(Mid(szpassword, xx + 1, 1))\n  Next\n  \n  p.ch(xx) = Chr(0) ' Put Null Terminator For C\n  \n  ZDLLPass = 0\n    \nEnd Function\n\n'-- Callback For ZIP32.DLL - DLL Comment Function\nPublic Function ZDLLComm(ByRef s1 As ZipCBChar) As Integer\n    \n    Dim xx%, szcomment$\n    \n    '-- Always Put This In Callback Routines!\n    On Error Resume Next\n    \n    ZDLLComm = 1\n    szcomment = InputBox(\"Enter the comment\")\n    If szcomment = \"\" Then Exit Function\n    For xx = 0 To Len(szcomment) - 1\n        s1.ch(xx) = Asc(Mid$(szcomment, xx + 1, 1))\n    Next xx\n    s1.ch(xx) = Chr(0) ' Put null terminator for C\n\nEnd Function\n\n'-- Main ZIP32.DLL Subroutine.\n'-- This Is Where It All Happens!!!\n'--\n'-- (WARNING!) Do Not Change This Function!!!\n'--\nPublic Function VBZip32() As Long\n    \n  Dim retcode As Long\n    \n  On Error Resume Next '-- Nothing Will Go Wrong :-)\n    \n  retcode = 0\n    \n  '-- Set Address Of ZIP32.DLL Callback Functions\n  '-- (WARNING!) Do Not Change!!!\n  ZUSER.ZDLLPrnt = FnPtr(AddressOf ZDLLPrnt)\n  ZUSER.ZDLLPASSWORD = FnPtr(AddressOf ZDLLPass)\n  ZUSER.ZDLLCOMMENT = FnPtr(AddressOf ZDLLComm)\n  ZUSER.ZDLLSERVICE = FnPtr(AddressOf ZDLLServ)\n    \n  '-- Set ZIP32.DLL Callbacks\n  retcode = ZpInit(ZUSER)\n  If retcode = 0 Then\n    MsgBox \"Zip32.dll did not initialize.  Is it in the current directory \" & _\n                \"or on the command path?\", vbOKOnly, \"VB Zip\"\n    Exit Function\n  End If\n    \n  '-- Setup ZIP32 Options\n  '-- (WARNING!) Do Not Change!\n  ZOPT.Date = zDate                  ' \"12/31/79\"? US Date?\n  ZOPT.szRootDir = zRootDir          ' Root Directory Pathname\n  ZOPT.szTempDir = zTempDir          ' Temp Directory Pathname\n  ZOPT.fSuffix = zSuffix             ' Include Suffixes (Not Yet Implemented)\n  ZOPT.fEncrypt = zEncrypt           ' 1 If Encryption Wanted\n  ZOPT.fSystem = zSystem             ' 1 To Include System/Hidden Files\n  ZOPT.fVolume = zVolume             ' 1 If Storing Volume Label\n  ZOPT.fExtra = zExtra               ' 1 If Including Extra Attributes\n  ZOPT.fNoDirEntries = zNoDirEntries ' 1 If Ignoring Directory Entries\n  ZOPT.fExcludeDate = zExcludeDate   ' 1 If Excluding Files Earlier Than A Specified Date\n  ZOPT.fIncludeDate = zIncludeDate   ' 1 If Including Files Earlier Than A Specified Date\n  ZOPT.fVerbose = zVerbose           ' 1 If Full Messages Wanted\n  ZOPT.fQuiet = zQuiet               ' 1 If Minimum Messages Wanted\n  ZOPT.fCRLF_LF = zCRLF_LF           ' 1 If Translate CR/LF To LF\n  ZOPT.fLF_CRLF = zLF_CRLF           ' 1 If Translate LF To CR/LF\n  ZOPT.fJunkDir = zJunkDir           ' 1 If Junking Directory Names\n  ZOPT.fGrow = zGrow                 ' 1 If Allow Appending To Zip File\n  ZOPT.fForce = zForce               ' 1 If Making Entries Using DOS Names\n  ZOPT.fMove = zMove                 ' 1 If Deleting Files Added Or Updated\n  ZOPT.fDeleteEntries = zDelEntries  ' 1 If Files Passed Have To Be Deleted\n  ZOPT.fUpdate = zUpdate             ' 1 If Updating Zip File-Overwrite Only If Newer\n  ZOPT.fFreshen = zFreshen           ' 1 If Freshening Zip File-Overwrite Only\n  ZOPT.fJunkSFX = zJunkSFX           ' 1 If Junking SFX Prefix\n  ZOPT.fLatestTime = zLatestTime     ' 1 If Setting Zip File Time To Time Of Latest File In Archive\n  ZOPT.fComment = zComment           ' 1 If Putting Comment In Zip File\n  ZOPT.fOffsets = zOffsets           ' 1 If Updating Archive Offsets For SFX Files\n  ZOPT.fPrivilege = zPrivilege       ' 1 If Not Saving Privelages\n  ZOPT.fEncryption = zEncryption     ' Read Only Property!\n  ZOPT.fRecurse = zRecurse           ' 1 or 2 If Recursing Into Subdirectories\n  ZOPT.fRepair = zRepair             ' 1 = Fix Archive, 2 = Try Harder To Fix\n  ZOPT.flevel = zLevel               ' Compression Level - (0 To 9) Should Be 0!!!\n    \n  '-- Set ZIP32.DLL Options\n  retcode = ZpSetOptions(ZOPT)\n    \n  '-- Go Zip It Them Up!\n  retcode = ZpArchive(zArgc, zZipFileName, zZipFileNames)\n  \n  '-- Return The Function Code\n  VBZip32 = retcode\n\nEnd Function\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/Vb/Vbzip.vbp",
    "content": "Type=Exe\nForm=Vbzipfrm.frm\nModule=VBZipBas; VBZipBas.bas\nIconForm=\"Form1\"\nStartup=\"Form1\"\nHelpFile=\"\"\nTitle=\"VBZIP\"\nExeName32=\"VBZIP.exe\"\nPath32=\"..\\..\\..\"\nCommand32=\"\"\nName=\"Project1\"\nHelpContextID=\"0\"\nCompatibleMode=\"0\"\nMajorVer=1\nMinorVer=0\nRevisionVer=0\nAutoIncrementVer=0\nServerSupportFiles=0\nVersionCompanyName=\"Mike\"\nCompilationType=-1\nOptimizationType=0\nFavorPentiumPro(tm)=0\nCodeViewDebugInfo=0\nNoAliasing=0\nBoundsCheck=0\nOverflowCheck=0\nFlPointCheck=0\nFDIVCheck=0\nUnroundedFP=0\nStartMode=0\nUnattended=0\nRetained=0\nThreadPerObject=0\nMaxNumberOfThreads=1\n"
  },
  {
    "path": "deps/infozip/zip30/windll/Vb/Vbzipfrm.frm",
    "content": "VERSION 5.00\nBegin VB.Form Form1 \n   AutoRedraw      =   -1  'True\n   Caption         =   \"Form1\"\n   ClientHeight    =   3150\n   ClientLeft      =   60\n   ClientTop       =   345\n   ClientWidth     =   6570\n   BeginProperty Font \n      Name            =   \"MS Sans Serif\"\n      Size            =   9.75\n      Charset         =   0\n      Weight          =   700\n      Underline       =   0   'False\n      Italic          =   0   'False\n      Strikethrough   =   0   'False\n   EndProperty\n   LinkTopic       =   \"Form1\"\n   ScaleHeight     =   3150\n   ScaleWidth      =   6570\n   StartUpPosition =   1  'CenterOwner\nEnd\nAttribute VB_Name = \"Form1\"\nAttribute VB_GlobalNameSpace = False\nAttribute VB_Creatable = False\nAttribute VB_PredeclaredId = True\nAttribute VB_Exposed = False\n\nOption Explicit\n\n'---------------------------------------------------------------\n'-- Please Do Not Remove These Comments!!!\n'---------------------------------------------------------------\n'-- Sample VB 5 code to drive zip32.dll\n'-- Contributed to the Info-ZIP project by Mike Le Voi\n'--\n'-- Contact me at: mlevoi@modemss.brisnet.org.au\n'--\n'-- Visit my home page at: http://modemss.brisnet.org.au/~mlevoi\n'--\n'-- Use this code at your own risk. Nothing implied or warranted\n'-- to work on your machine :-)\n'---------------------------------------------------------------\n'--\n'-- The Source Code Is Freely Available From Info-ZIP At:\n'-- http://www.cdrom.com/pub/infozip/infozip.html\n'--\n'-- A Very Special Thanks To Mr. Mike Le Voi\n'-- And Mr. Mike White Of The Info-ZIP project\n'-- For Letting Me Use And Modify His Orginal\n'-- Visual Basic 5.0 Code! Thank You Mike Le Voi.\n'---------------------------------------------------------------\n'--\n'-- Contributed To The Info-ZIP Project By Raymond L. King\n'-- Modified June 21, 1998\n'-- By Raymond L. King\n'-- Custom Software Designers\n'--\n'-- Contact Me At: king@ntplx.net\n'-- ICQ 434355\n'-- Or Visit Our Home Page At: http://www.ntplx.net/~king\n'--\n'---------------------------------------------------------------\n' This is the original VB example (with some changes) for use\n' with Zip32.dll (Zip 2.31) but not Zip32z64.dll (Zip 3.0).\n'\n' Minor changes to use current directory and VB project files\n' for the example and to turn off encryption.\n'\n' The VB example provided with Zip 3.0 is more extensive.  Even\n' if you plan to use the updated zip32.dll instead of the new\n' zip32z64.dll (Zip 3.0), there may be some things you might find\n' useful in the VB example there.\n'\n' 2/27/2005 Ed Gordon\n'---------------------------------------------------------------\n\nPrivate Sub Form_Click()\n\n  Dim retcode As Integer  ' For Return Code From ZIP32.DLL\n\n  Cls\n\n  '-- Set Options - Only The Common Ones Are Shown Here\n  '-- These Must Be Set Before Calling The VBZip32 Function\n  zDate = vbNullString\n  'zDate = \"2005-1-31\"\n  'zExcludeDate = 1\n  'zIncludeDate = 0\n  zJunkDir = 0     ' 1 = Throw Away Path Names\n  zRecurse = 0     ' 1 = Recurse -r 2 = Recurse -R 2 = Most Useful :)\n  zUpdate = 0      ' 1 = Update Only If Newer\n  zFreshen = 0     ' 1 = Freshen - Overwrite Only\n  zLevel = Asc(9)  ' Compression Level (0 - 9)\n  zEncrypt = 0     ' Encryption = 1 For Password Else 0\n  zComment = 0     ' Comment = 1 if required\n\n  '-- Select Some Files - Wildcards Are Supported\n  '-- Change The Paths Here To Your Directory\n  '-- And Files!!!\n  ' Change ZIPnames in VBZipBas.bas if need more than 100 files\n  zArgc = 2           ' Number Of Elements Of mynames Array\n  zZipFileName = \"MyFirst.zip\"\n  zZipFileNames.zFiles(0) = \"vbzipfrm.frm\"\n  zZipFileNames.zFiles(1) = \"vbzip.vbp\"\n  zRootDir = \"\"    ' This Affects The Stored Path Name\n  \n  ' Older versions of Zip32.dll do not handle setting\n  ' zRootDir to anything other than \"\".  If you need to\n  ' change root directory an alternative is to just change\n  ' directory.  This requires Zip32.dll to be on the command\n  ' path.  This should be fixed in Zip 2.31.  1/31/2005 EG\n\n  ' ChDir \"a\"\n\n  '-- Go Zip Them Up!\n  retcode = VBZip32\n\n  '-- Display The Returned Code Or Error!\n  Print \"Return code:\" & Str(retcode)\n\nEnd Sub\n\nPrivate Sub Form_Load()\n\n  Me.Show\n\n  Print \"Click me!\"\n\nEnd Sub\n"
  },
  {
    "path": "deps/infozip/zip30/windll/Vb/readmeVB.txt",
    "content": "On Windows open this file in WordPad.\n\nContents of the \"windll/vb\" sub-archive\n\nThis directory contains a Visual Basic project example for\nusing the zip32.dll library.  This project updates the Zip 2.3 VB\nproject example and includes some bug fixes and many additional notes\nbut is still compatible with zip32.dll.  See the comments in the form\nand project files for details.  It has been tested on VB 5 and VB 6.\n\nZip 2.31 itself had bug fixes as well, including some related to the\ndll, and you should now use a version of zip32.dll from that or later.\nThis dll includes a fix for the VB dll bug where Date, szRootDir, and\nszTempDir were not passed in correctly and setting these to anything\nbut NULL could impact the dll and maybe crash it.  You can tell which\nversion you have by right clicking on zip32.dll in a file listing,\nlooking at properties, selecting the Version tab, and verifying the\nProduct Version is at least 2.31.\n\nA new dll is available as part of this Zip 3.0 release and a\nnew VB project is included in the VBz64 directory.  This dll and\nproject supports Zip64 and large files but is not backward compatible\nwith Zip32.dll.  You will need the new zip32z64.dll to use this project,\nwhich can be compiled from Zip 3.0.  See windll/VBz64 for details.\n\nNote that the files may saved in unix format with carriage returns\nstripped.  These must be restored before the project can be successfully\nused.  This can be done by using the -a option to unzip.  Another way to\ndo this is to open each file in WordPad, select and cut a line, paste\nthe line back, and save the file.  This will force WordPad to format\nthe entire file.\n\nEd Gordon\n2/2/2007\n"
  },
  {
    "path": "deps/infozip/zip30/windll/contents",
    "content": "Contents of the \"windll\" sub-archive for Zip 2.2 and later:\n\n  contents       this file\n  windll16.def   definition file for 16-bit Zip DLL\n  windll32.def   definition file for 32-bit Zip DLL\n  windll.c       Contains the entry point for the DLL, \"fake\" printing,\n                 and password functions.\n  windll.h       header file for both 16 and 32-bit DLLs.\n  zipver.h       versioning information for resource file, and also\n                 used by WiZ application itself.\n  windll.rc      resource file for both 16 and 32-bit DLLs\n  windll.txt     simplistic explanation of how to use DLL.\n  structs.h      header file used by both the dll and by WiZ which defines\n                 several structures passed to the dll.\n  example.c      a very simplistic example of how to load the dll, and make\n                 a call into it.\n  example.h      header file for example.c\n\n  borland\\dll <dir> contains 16 and 32 bit make files for the zip dlls.\n  borland\\lib <dir> contains 32 bit make files for the zip32 static library\n  visualc\\dll <dir> contains Visual C++ 5.0 project and make files for\n                    zip32 dll.\n  visualc\\lib <dir> contains Visual C++ 5.0 project and make files for\n                    zip32 static library.\n\nThe Microsoft C port has not been tested as completely as the Borland port.\nNote that Borland C++ 5.0 is full of bugs version 4.5 is recommended instead.\nIf you must use Borland C++ 5.0, using the Intel optimizing compiler is\nrequired to avoid crashes (possibly due to a bug in the stat() function\nin the normal Borland compiler.) This does have the advantage of giving you\na smaller code size than the 4.52 compiler.\n\nBorland C++ 5.01 has resolved many of the problems seen with 5.0, and\ncan now reliably be used.\n\nNote that I have been singularly unsuccessful in getting this to compile\nand run under MSVC 1.52c.\n\nLast updated October 13, 1997\n\nMike White\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/example.c",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n A very simplistic example of how to load the zip dll and make a call into it.\n Note that none of the command line options are implemented in this example.\n\n */\n\n#ifndef WIN32\n#  define WIN32\n#endif\n#define API\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <time.h>\n#include <string.h>\n#ifdef __BORLANDC__\n#include <dir.h>\n#else\n#include <direct.h>\n#endif\n#include \"example.h\"\n#include \"zipver.h\"\n\n#ifdef WIN32\n#include <commctrl.h>\n#include <winver.h>\n#else\n#include <ver.h>\n#endif\n\n#ifdef WIN32\n#define ZIP_DLL_NAME \"ZIP32.DLL\\0\"\n#else\n#define ZIP_DLL_NAME \"ZIP16.DLL\\0\"\n#endif\n\n#define DLL_WARNING \"Cannot find %s.\"\\\n            \" The Dll must be in the application directory, the path, \"\\\n            \"the Windows directory or the Windows System directory.\"\n#define DLL_VERSION_WARNING \"%s has the wrong version number.\"\\\n            \" Insure that you have the correct dll's installed, and that \"\\\n            \"an older dll is not in your path or Windows System directory.\"\n\nint hFile;              /* file handle */\n\nZCL ZpZCL;\nLPZIPUSERFUNCTIONS lpZipUserFunctions;\nHANDLE hZUF = (HANDLE)NULL;\nHINSTANCE hUnzipDll;\nHANDLE hFileList;\nZPOPT ZpOpt;\n#ifdef WIN32\nDWORD dwPlatformId = 0xFFFFFFFF;\n#endif\nHINSTANCE hZipDll;\n\n\n/* Forward References */\n_DLL_ZIP ZipArchive;\n_ZIP_USER_FUNCTIONS ZipInit;\nZIPSETOPTIONS ZipSetOptions;\n\nvoid FreeUpMemory(void);\nint WINAPI DummyPassword(LPSTR, int, LPCSTR, LPCSTR);\nint WINAPI DummyPrint(char far *, unsigned long);\nint WINAPI WINAPI DummyComment(char far *);\n\n#ifdef WIN32\nBOOL IsNT(VOID);\n#endif\n\n/****************************************************************************\n\n    FUNCTION: Main(int argc, char **argv)\n\n****************************************************************************/\n#ifdef __BORLANDC__\n#  ifdef WIN32\n#pragma argsused\n#  endif\n#endif\nint main(int argc, char **argv)\n{\nLPSTR szFileList;\nchar **index, *sz;\nint retcode, i, cc;\nDWORD dwVerInfoSize;\nDWORD dwVerHnd;\nchar szFullPath[PATH_MAX];\n#ifdef WIN32\nchar *ptr;\n#else\nHFILE hfile;\nOFSTRUCT ofs;\n#endif\nHANDLE  hMem;         /* handle to mem alloc'ed */\n\nif (argc < 3)\n   return 0;           /* Exits if not proper number of arguments */\n\nhZUF = GlobalAlloc( GPTR, (DWORD)sizeof(ZIPUSERFUNCTIONS));\nif (!hZUF)\n   {\n   return 0;\n   }\nlpZipUserFunctions = (LPZIPUSERFUNCTIONS)GlobalLock(hZUF);\n\nif (!lpZipUserFunctions)\n   {\n   GlobalFree(hZUF);\n   return 0;\n   }\n\nlpZipUserFunctions->print = DummyPrint;\nlpZipUserFunctions->password = DummyPassword;\nlpZipUserFunctions->comment = DummyComment;\n\n/* Let's go find the dll */\n#ifdef WIN32\nif (SearchPath(\n    NULL,               /* address of search path               */\n    ZIP_DLL_NAME,       /* address of filename                  */\n    NULL,               /* address of extension                 */\n    PATH_MAX,           /* size, in characters, of buffer       */\n    szFullPath,         /* address of buffer for found filename */\n    &ptr                /* address of pointer to file component */\n   ) == 0)\n#else\nhfile = OpenFile(ZIP_DLL_NAME,  &ofs, OF_SEARCH);\nif (hfile == HFILE_ERROR)\n#endif\n   {\n   char str[256];\n   wsprintf (str, DLL_WARNING, ZIP_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return 0;\n   }\n#ifndef WIN32\nelse\n   lstrcpy(szFullPath, ofs.szPathName);\n_lclose(hfile);\n#endif\n\n/* Now we'll check the zip dll version information */\ndwVerInfoSize =\n    GetFileVersionInfoSize(szFullPath, &dwVerHnd);\n\nif (dwVerInfoSize)\n   {\n   BOOL  fRet, fRetName;\n   char str[256];\n   LPSTR   lpstrVffInfo; /* Pointer to block to hold info */\n   LPSTR lszVer = NULL;\n   LPSTR lszVerName = NULL;\n   UINT  cchVer = 0;\n\n   /* Get a block big enough to hold the version information */\n   hMem          = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);\n   lpstrVffInfo  = GlobalLock(hMem);\n\n   /* Get the version information */\n   GetFileVersionInfo(szFullPath, 0L, dwVerInfoSize, lpstrVffInfo);\n   fRet = VerQueryValue(lpstrVffInfo,\n              TEXT(\"\\\\StringFileInfo\\\\040904E4\\\\FileVersion\"),\n               (LPVOID)&lszVer,\n               &cchVer);\n   fRetName = VerQueryValue(lpstrVffInfo,\n               TEXT(\"\\\\StringFileInfo\\\\040904E4\\\\CompanyName\"),\n              (LPVOID)&lszVerName,\n              &cchVer);\n   if (!fRet || !fRetName ||\n      (lstrcmpi(lszVer, ZIP_DLL_VERSION) != 0) ||\n      (lstrcmpi(lszVerName, COMPANY_NAME) != 0))\n      {\n      wsprintf (str, DLL_VERSION_WARNING, ZIP_DLL_NAME);\n      printf(\"%s\\n\", str);\n      FreeUpMemory();\n      return 0;\n      }\n   /* free memory */\n   GlobalUnlock(hMem);\n   GlobalFree(hMem);\n   }\nelse\n   {\n   char str[256];\n   wsprintf (str, DLL_VERSION_WARNING, ZIP_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return 0;\n   }\n/* Okay, now we know that the dll exists, and has the proper version\n * information in it. We can go ahead and load it.\n */\nhZipDll = LoadLibrary(ZIP_DLL_NAME);\n#ifndef WIN32\nif (hZipDll > HINSTANCE_ERROR)\n#else\nif (hZipDll != NULL)\n#endif\n   {\n   (_DLL_ZIP)ZipArchive = (_DLL_ZIP)GetProcAddress(hZipDll, \"ZpArchive\");\n   (ZIPSETOPTIONS)ZipSetOptions = (ZIPSETOPTIONS)GetProcAddress(hZipDll, \"ZpSetOptions\");\n   if (!ZipArchive || !ZipSetOptions)\n      {\n      char str[256];\n      wsprintf (str, \"Could not get entry point to %s\", ZIP_DLL_NAME);\n      MessageBox((HWND)NULL, str, \"Info-ZIP Example\", MB_ICONSTOP | MB_OK);\n      FreeUpMemory();\n      return 0;\n      }\n   }\nelse\n   {\n   char str[256];\n   wsprintf (str, \"Could not load %s\", ZIP_DLL_NAME);\n   printf(\"%s\\n\", str);\n   FreeUpMemory();\n   return 0;\n   }\n\n(_ZIP_USER_FUNCTIONS)ZipInit = (_ZIP_USER_FUNCTIONS)GetProcAddress(hZipDll, \"ZpInit\");\nif (!ZipInit)\n   {\n   printf(\"Cannot get address of ZpInit in Zip dll. Terminating...\");\n   FreeLibrary(hZipDll);\n   FreeUpMemory();\n   return 0;\n   }\nif (!(*ZipInit)(lpZipUserFunctions))\n   {\n   printf(\"Application functions not set up properly. Terminating...\");\n   FreeLibrary(hZipDll);\n   FreeUpMemory();\n   return 0;\n   }\n\n/* Here is where the action starts */\nZpOpt.fSuffix = FALSE;        /* include suffixes (not yet implemented) */\nZpOpt.fEncrypt = FALSE;       /* true if encryption wanted */\nZpOpt.fSystem = FALSE;        /* true to include system/hidden files */\nZpOpt.fVolume = FALSE;        /* true if storing volume label */\nZpOpt.fExtra = FALSE;         /* true if including extra attributes */\nZpOpt.fNoDirEntries = FALSE;  /* true if ignoring directory entries */\nZpOpt.fVerbose = FALSE;       /* true if full messages wanted */\nZpOpt.fQuiet = FALSE;         /* true if minimum messages wanted */\nZpOpt.fCRLF_LF = FALSE;       /* true if translate CR/LF to LF */\nZpOpt.fLF_CRLF = FALSE;       /* true if translate LF to CR/LF */\nZpOpt.fJunkDir = FALSE;       /* true if junking directory names */\nZpOpt.fGrow = FALSE;          /* true if allow appending to zip file */\nZpOpt.fForce = FALSE;         /* true if making entries using DOS names */\nZpOpt.fMove = FALSE;          /* true if deleting files added or updated */\nZpOpt.fUpdate = FALSE;        /* true if updating zip file--overwrite only\n                                  if newer */\nZpOpt.fFreshen = FALSE;       /* true if freshening zip file--overwrite only */\nZpOpt.fJunkSFX = FALSE;       /* true if junking sfx prefix*/\nZpOpt.fLatestTime = FALSE;    /* true if setting zip file time to time of\n                                  latest file in archive */\nZpOpt.fComment = FALSE;       /* true if putting comment in zip file */\nZpOpt.fOffsets = FALSE;       /* true if updating archive offsets for sfx\n                                  files */\nZpOpt.fDeleteEntries = FALSE; /* true if deleting files from archive */\nZpOpt.fRecurse = 0;           /* subdir recursing mode: 1 = \"-r\", 2 = \"-R\" */\nZpOpt.fRepair = 0;            /* archive repair mode: 1 = \"-F\", 2 = \"-FF\" */\nZpOpt.Date = NULL;            /* Not using, set to NULL pointer */\ngetcwd(szFullPath, PATH_MAX); /* Set directory to current directory */\nZpOpt.szRootDir = szFullPath;\n\nZpZCL.argc = argc - 2;        /* number of files to archive - adjust for the\n                                  actual number of file names to be added */\nZpZCL.lpszZipFN = argv[1];    /* archive to be created/updated */\n\n/* Copy over the appropriate portions of argv, basically stripping out argv[0]\n   (name of the executable) and argv[1] (name of the archive file)\n */\nhFileList = GlobalAlloc( GPTR, 0x10000L);\nif ( hFileList )\n   {\n   szFileList = (char far *)GlobalLock(hFileList);\n   }\nindex = (char **)szFileList;\ncc = (sizeof(char *) * ZpZCL.argc);\nsz = szFileList + cc;\n\nfor (i = 0; i < ZpZCL.argc; i++)\n    {\n    cc = lstrlen(argv[i+2]);\n    lstrcpy(sz, argv[i+2]);\n    index[i] = sz;\n    sz += (cc + 1);\n    }\nZpZCL.FNV = (char **)szFileList;  /* list of files to archive */\n\n/* Set the options */\nZipSetOptions(&ZpOpt);\n\n/* Go zip 'em up */\nretcode = ZipArchive(ZpZCL);\nif (retcode != 0)\n   printf(\"Error in archiving\\n\");\n\nGlobalUnlock(hFileList);\nGlobalFree(hFileList);\nFreeUpMemory();\nFreeLibrary(hZipDll);\nreturn 1;\n}\n\nvoid FreeUpMemory(void)\n{\nif (hZUF)\n   {\n   GlobalUnlock(hZUF);\n   GlobalFree(hZUF);\n   }\n}\n\n#ifdef WIN32\n/* This simply determines if we are running on NT */\nBOOL IsNT(VOID)\n{\nif(dwPlatformId != 0xFFFFFFFF)\n   return dwPlatformId;\nelse\n/* note: GetVersionEx() doesn't exist on WinNT 3.1 */\n   {\n   if(GetVersion() < 0x80000000)\n      {\n      (BOOL)dwPlatformId = TRUE;\n      }\n   else\n      {\n      (BOOL)dwPlatformId = FALSE;\n      }\n    }\nreturn dwPlatformId;\n}\n#endif\n\n/* Password entry routine - see password.c in the wiz directory for how\n   this is actually implemented in Wiz. If you have an encrypted file,\n   this will probably give you great pain. Note that none of the\n   parameters are being used here, and this will give you warnings.\n */\nint WINAPI DummyPassword(LPSTR p, int n, LPCSTR m, LPCSTR name)\n{\nreturn 1;\n}\n\n/* Dummy \"print\" routine that simply outputs what is sent from the dll */\nint WINAPI DummyPrint(char far *buf, unsigned long size)\n{\nprintf(\"%s\", buf);\nreturn (unsigned int) size;\n}\n\n\n/* Dummy \"comment\" routine. See comment.c in the wiz directory for how\n   this is actually implemented in Wiz. This will probably cause you\n   great pain if you ever actually make a call into it.\n */\nint WINAPI DummyComment(char far *szBuf)\n{\nszBuf[0] = '\\0';\nreturn TRUE;\n}\n"
  },
  {
    "path": "deps/infozip/zip30/windll/example.h",
    "content": "/*\n  Copyright (c) 1990-1999 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 1999-Oct-05 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, both of these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.cdrom.com/pub/infozip/license.html\n*/\n/*\n Example header file\n*/\n#ifndef _EXAMPLE_H\n#define _EXAMPLE_H\n\n#include <windows.h>\n#include <assert.h>    /* required for all Windows applications */\n#include <stdlib.h>\n#include <stdio.h>\n#include <commdlg.h>\n#include <dlgs.h>\n#include <windowsx.h>\n\n#ifndef EXPENTRY\n#define EXPENTRY WINAPI\n#endif\n\n#include \"structs.h\"\n\n/* Defines */\n#ifndef MSWIN\n#define MSWIN\n#endif\n\ntypedef int (WINAPI * _DLL_ZIP)(ZCL);\ntypedef int (WINAPI * _ZIP_USER_FUNCTIONS)(LPZIPUSERFUNCTIONS);\ntypedef BOOL (WINAPI * ZIPSETOPTIONS)(LPZPOPT);\n\n/* Global variables */\n\nextern LPZIPUSERFUNCTIONS lpZipUserFunctions;\n\nextern HINSTANCE hZipDll;\n\nextern int hFile;                 /* file handle             */\n\n/* Global functions */\n\nint WINAPI DisplayBuf(char far *, unsigned long int);\nextern _DLL_ZIP ZipArchive;\nextern _ZIP_USER_FUNCTIONS ZipInit;\nextern ZIPSETOPTIONS ZipSetOptions;\n\n#endif /* _EXAMPLE_H */\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/structs.h",
    "content": "/*\n  windll/structs.h - Zip 3\n\n  Copyright (c) 1990-2003 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n#ifndef _ZIP_STRUCTS_H\n#define _ZIP_STRUCTS_H\n\n#ifndef Far\n#  define Far far\n#endif\n\n/* Porting definations between Win 3.1x and Win32 */\n#ifdef WIN32\n#  define far\n#  define _far\n#  define __far\n#  define near\n#  define _near\n#  define __near\n#endif\n\n#include \"../api.h\"\n\n#endif /* _ZIP_STRUCTS_H */\n"
  },
  {
    "path": "deps/infozip/zip30/windll/visualc/dll/zip32z64.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zip32z64\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Dynamic-Link Library\" 0x0102\n\nCFG=zip32z64 - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zip32z64.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zip32z64.mak\" CFG=\"zip32z64 - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zip32z64 - Win32 Release\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \"zip32z64 - Win32 Debug\" (based on \"Win32 (x86) Dynamic-Link Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nMTL=midl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zip32z64 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"..\\Release\\app\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Zp4 /MT /W3 /GX /O2 /I \"..\\..\\..\" /I \"..\\..\\..\\WINDLL\" /I \"..\\..\\..\\WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /D \"NO_ASM\" /D \"WINDLL\" /D \"MSDOS\" /D \"USE_ZIPMAIN\" /YX /FD /c\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\n# ADD RSC /l 0x409 /d \"NDEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /machine:I386\n\n!ELSEIF  \"$(CFG)\" == \"zip32z64 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"..\\Debug\\app\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Ignore_Export_Lib 0\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /Zp4 /MTd /W3 /Gm /GX /ZI /Od /I \"..\\..\\..\\ZIP\" /I \"..\\..\\..\\WINDLL\" /I \"..\\..\\..\\WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /D \"NO_ASM\" /D \"WINDLL\" /D \"MSDOS\" /D \"USE_ZIPMAIN\" /FR /YX /FD /c\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o \"NUL\" /win32\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\n# ADD RSC /l 0x409 /d \"_DEBUG\" /d \"WIN32\"\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLINK32=link.exe\n# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\n# ADD LINK32 kernel32.lib user32.lib advapi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:\"..\\Debug\\app/zip32z64.dll\" /pdbtype:sept\n# SUBTRACT LINK32 /map\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zip32z64 - Win32 Release\"\n# Name \"zip32z64 - Win32 Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\deflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\trees.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32i64.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll32.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipup.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/windll/visualc/dll/zip32z64.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"zip32z64\"=.\\zip32z64.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/visualc/lib/zip32z64.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"zip32z64\" - Package Owner=<4>\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\n# ** DO NOT EDIT **\n\n# TARGTYPE \"Win32 (x86) Static Library\" 0x0104\n\nCFG=zip32z64 - Win32 Debug\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\n!MESSAGE use the Export Makefile command and run\n!MESSAGE \n!MESSAGE NMAKE /f \"zip32z64.mak\".\n!MESSAGE \n!MESSAGE You can specify a configuration when running NMAKE\n!MESSAGE by defining the macro CFG on the command line. For example:\n!MESSAGE \n!MESSAGE NMAKE /f \"zip32z64.mak\" CFG=\"zip32z64 - Win32 Debug\"\n!MESSAGE \n!MESSAGE Possible choices for configuration are:\n!MESSAGE \n!MESSAGE \"zip32z64 - Win32 Release\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \"zip32z64 - Win32 Debug\" (based on \"Win32 (x86) Static Library\")\n!MESSAGE \n\n# Begin Project\n# PROP AllowPerConfigDependencies 0\n# PROP Scc_ProjName \"\"\n# PROP Scc_LocalPath \"\"\nCPP=cl.exe\nRSC=rc.exe\n\n!IF  \"$(CFG)\" == \"zip32z64 - Win32 Release\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 0\n# PROP BASE Output_Dir \"Release\"\n# PROP BASE Intermediate_Dir \"Release\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 0\n# PROP Output_Dir \"..\\Release\\libs\"\n# PROP Intermediate_Dir \"Release\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"NDEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /O2 /I \"..\\..\\..\" /I \"..\\..\\..\\win32\" /I \"..\\..\\..\\windll\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /D \"NO_ASM\" /D \"WINDLL\" /D \"MSDOS\" /D \"USE_ZIPMAIN\" /D \"ZIPLIB\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ELSEIF  \"$(CFG)\" == \"zip32z64 - Win32 Debug\"\n\n# PROP BASE Use_MFC 0\n# PROP BASE Use_Debug_Libraries 1\n# PROP BASE Output_Dir \"Debug\"\n# PROP BASE Intermediate_Dir \"Debug\"\n# PROP BASE Target_Dir \"\"\n# PROP Use_MFC 0\n# PROP Use_Debug_Libraries 1\n# PROP Output_Dir \"..\\Debug\\libs\"\n# PROP Intermediate_Dir \"Debug\"\n# PROP Target_Dir \"\"\n# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D \"_DEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /YX /FD /c\n# ADD CPP /nologo /W3 /GX /Z7 /Od /I \"..\\..\\..\" /I \"..\\..\\..\\win32\" /I \"..\\..\\..\\windll\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"WIN32\" /D \"NO_ASM\" /D \"WINDLL\" /D \"MSDOS\" /D \"USE_ZIPMAIN\" /D \"ZIPLIB\" /FD /c\n# SUBTRACT CPP /YX\n# ADD BASE RSC /l 0x409\n# ADD RSC /l 0x409\nBSC32=bscmake.exe\n# ADD BASE BSC32 /nologo\n# ADD BSC32 /nologo\nLIB32=link.exe -lib\n# ADD BASE LIB32 /nologo\n# ADD LIB32 /nologo\n\n!ENDIF \n\n# Begin Target\n\n# Name \"zip32z64 - Win32 Release\"\n# Name \"zip32z64 - Win32 Debug\"\n# Begin Source File\n\nSOURCE=..\\..\\..\\api.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crc32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\crypt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\deflate.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\fileio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\globals.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\nt.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\trees.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\ttyio.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\util.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\win32\\win32zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\windll.rc\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zip.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipfile.c\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\windll\\ziplib.def\n# End Source File\n# Begin Source File\n\nSOURCE=..\\..\\..\\zipup.c\n# End Source File\n# End Target\n# End Project\n"
  },
  {
    "path": "deps/infozip/zip30/windll/visualc/lib/zip32z64.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n###############################################################################\n\nProject: \"zip32z64\"=.\\zip32z64.dsp - Package Owner=<4>\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<4>\n{{{\n}}}\n\n###############################################################################\n\nGlobal:\n\nPackage=<5>\n{{{\n}}}\n\nPackage=<3>\n{{{\n}}}\n\n###############################################################################\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll.c",
    "content": "/*\n  windll/windll.c - Zip 3\n\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  windll.c by Mike White loosly based on Mark Adler's zip.c\n */\n#include <windows.h>\n#include <process.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <ctype.h>\n#include \"../zip.h\"\n#include \"windll.h\"\n\nHINSTANCE hCurrentInst;\n#ifdef ZIPLIB\n/*  DLL Entry Point */\n#ifdef __BORLANDC__\n#pragma argsused\n/* Borland seems to want DllEntryPoint instead of DllMain like MSVC */\n#define DllMain DllEntryPoint\n#endif\n#ifdef WIN32\nBOOL WINAPI DllMain( HINSTANCE hInstance,\n                     DWORD dwReason,\n                     LPVOID plvReserved)\n#else\nint WINAPI LibMain( HINSTANCE hInstance,\n                        WORD wDataSegment,\n                        WORD wHeapSize,\n                        LPSTR lpszCmdLine )\n#endif\n{\n#ifndef WIN32\n/* The startup code for the DLL initializes the local heap(if there is one)\n with a call to LocalInit which locks the data segment. */\n\nif ( wHeapSize != 0 )\n   {\n   UnlockData( 0 );\n   }\nhCurrentInst = hInstance;\nreturn 1;   /* Indicate that the DLL was initialized successfully. */\n#else\nBOOL rc = TRUE;\nswitch( dwReason )\n   {\n   case DLL_PROCESS_ATTACH:\n      // DLL is loaded. Do your initialization here.\n      // If cannot init, set rc to FALSE.\n      hCurrentInst = hInstance;\n      break;\n\n   case DLL_PROCESS_DETACH:\n      // DLL is unloaded. Do your cleanup here.\n      break;\n   default:\n      break;\n   }\nreturn rc;\n#endif\n}\n\n#ifdef __BORLANDC__\n#pragma argsused\n#endif\nint FAR PASCAL WEP ( int bSystemExit )\n{\nreturn 1;\n}\n#endif /* ZIPLIB */\n\nLPSTR szCommentBuf;\nHANDLE hStr;\n\nvoid comment(unsigned int comlen)\n{\nunsigned int i;\nif (comlen > 65534L)\n   comlen = (unsigned int) 65534L;\nhStr = GlobalAlloc( GPTR, (DWORD)65535L);\nif ( !hStr )\n   {\n   hStr = GlobalAlloc( GPTR, (DWORD) 2);\n   szCommentBuf = GlobalLock(hStr);\n   szCommentBuf[0] = '\\0';\n   return;\n   }\n\nszCommentBuf = GlobalLock(hStr);\nif (comlen)\n   {\n   for (i = 0; i < comlen; i++)\n       szCommentBuf[i] = zcomment[i];\n   szCommentBuf[comlen] = '\\0';\n   }\nelse\n   szCommentBuf[0] = '\\0';\nfree(zcomment);\nzcomment = malloc(1);\n*zcomment = 0;\nlpZipUserFunctions->comment(szCommentBuf);\nreturn;\n}\n\n#define STDIO_BUF_SIZE 16384\n\nint __far __cdecl printf(const char *format, ...)\n{\nva_list argptr;\nHANDLE hMemory;\nLPSTR pszBuffer;\nint len;\n\nva_start(argptr, format);\nhMemory = GlobalAlloc(GMEM_MOVEABLE, STDIO_BUF_SIZE);\nWinAssert(hMemory);\nif (!hMemory)\n   {\n   return 0;\n   }\npszBuffer = (LPSTR)GlobalLock(hMemory);\nWinAssert(pszBuffer);\nlen = wvsprintf(pszBuffer, format, argptr);\nva_end(argptr);\nWinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE);\nlen = lpZipUserFunctions->print(pszBuffer, len);\nGlobalUnlock(hMemory);\nGlobalFree(hMemory);\nreturn len;\n}\n\n/* fprintf clone for code in zip.c, etc. */\nint __far __cdecl fprintf(FILE *file, const char *format, ...)\n{\nva_list argptr;\nHANDLE hMemory;\nLPSTR pszBuffer;\nint len;\n\nva_start(argptr, format);\nhMemory = GlobalAlloc(GMEM_MOVEABLE, STDIO_BUF_SIZE);\nWinAssert(hMemory);\nif (!hMemory)\n   {\n   return 0;\n   }\npszBuffer = GlobalLock(hMemory);\nWinAssert(pszBuffer);\nlen = wvsprintf(pszBuffer, format, argptr);\nva_end(argptr);\nWinAssert(strlen(pszBuffer) < STDIO_BUF_SIZE);\nif ((file == stderr) || (file == stdout))\n   {\n   len = lpZipUserFunctions->print(pszBuffer, len);\n   }\nelse\n   len = write(fileno(file),(char far *)(pszBuffer), len);\nGlobalUnlock(hMemory);\nGlobalFree(hMemory);\nreturn len;\n}\n\nvoid __far __cdecl perror(const char *parm1)\n{\nprintf(\"%s\", parm1);\n}\n\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll.h",
    "content": "/*\n  windll/windll.h - Zip 3\n\n  Copyright (c) 1990-2004 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2003-May-08 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n WiZ 1.0 header file for zip dll\n*/\n#ifndef _WINDLL_H\n#define _WINDLL_H\n\n#include \"structs.h\"\n\n#ifndef MSWIN\n#define MSWIN\n#endif\n\n#ifndef USE_ZIPMAIN\n#   define USE_ZIPMAIN\n#endif\n\n#ifndef NDEBUG\n#  define WinAssert(exp) \\\n        {\\\n        if (!(exp))\\\n            {\\\n            char szBuffer[40];\\\n            sprintf(szBuffer, \"File %s, Line %d\",\\\n                    __FILE__, __LINE__) ;\\\n            if (IDABORT == MessageBox((HWND)NULL, szBuffer,\\\n                \"Assertion Error\",\\\n                MB_ABORTRETRYIGNORE|MB_ICONSTOP))\\\n                    FatalExit(-1);\\\n            }\\\n        }\n\n#else\n#  define WinAssert(exp)\n#endif\n\n#define cchFilesMax 4096\n\nextern int WINAPI ZpArchive(ZCL C, LPZPOPT Opts);\nextern HWND hGetFilesDlg;\nextern char szFilesToAdd[80];\nextern char rgszFiles[cchFilesMax];\nBOOL WINAPI CommentBoxProc(HWND hwndDlg, WORD wMessage, WPARAM wParam, LPARAM lParam);\nBOOL PasswordProc(HWND, WORD, WPARAM, LPARAM);\nvoid CenterDialog(HWND hwndParent, HWND hwndDlg);\nvoid comment(unsigned int);\n\nextern LPSTR szCommentBuf;\nextern HANDLE hStr;\nextern HWND hWndMain;\nvoid __far __cdecl perror(const char *);\n\n#endif /* _WINDLL_H */\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll.rc",
    "content": "#define APSTUDIO_READONLY_SYMBOLS\n#define APSTUDIO_HIDDEN_SYMBOLS\n#include <windows.h>\n#if (defined(WIN32) && !defined(__EMX__) && !defined(__MINGW32__))\n#include <winver.h>\n#endif\n#undef APSTUDIO_HIDDEN_SYMBOLS\n#include \"../revision.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION Z_MAJORVER,Z_MINORVER,Z_PATCHLEVEL,0\n PRODUCTVERSION Z_MAJORVER,Z_MINORVER,Z_PATCHLEVEL,0\n FILEFLAGSMASK 0x3L\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS VOS__WINDOWS32\n FILETYPE VFT_DLL\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        BLOCK \"040904B0\"\n#else\n        BLOCK \"040904E4\"\n#endif\n        BEGIN\n            VALUE \"CompanyName\", IZ_COMPANY_NAME \"\\0\"\n            VALUE \"FileDescription\", \"Info-ZIP's Zip dll\\0\"\n            VALUE \"FileVersion\", VERSION \"\\0\"\n            VALUE \"InternalName\", \"Zip32z64\\0\"\n            VALUE \"LegalCopyright\", \"Info-ZIP 1997 - 2008\\0\"\n            VALUE \"OriginalFilename\", \"ZIP32Z64.DLL\\0\"\n            VALUE \"ProductName\", \"Info-ZIP's WiZ\\0\"\n            VALUE \"ProductVersion\", VERSION \"\\0\"\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n#ifdef _UNICODE\n        VALUE \"Translation\", 0x409, 1200\n#else\n        VALUE \"Translation\", 0x409, 1252\n#endif\n    END\nEND\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll.txt",
    "content": "The code set out below is not intended to be compiled, but is only intended as\na very simplistic pointer to how to load and call the dll. You will have to\nlook in the files referenced below for actual, working code.\n\nThere is one entry point that uses the structure shown below:\n\ntypedef struct {\nLPSTR Date;             /* Date to include after */\nLPSTR szRootDir;        /* Directory to use as base for zipping */\nLPSTR szTempDir;        /* Temporary directory used during zipping */\nBOOL fTemp;             /* Use temporary directory '-b' during zipping */\nBOOL fSuffix;           /* include suffixes (not implemented in WiZ) */\nBOOL fEncrypt;          /* encrypt files */\nBOOL fSystem;           /* include system and hidden files */\nBOOL fVolume;           /* Include volume label */\nBOOL fExtra;            /* Exclude extra attributes */\nBOOL fNoDirEntries;     /* Do not add directory entries */\nBOOL fExcludeDate;      /* Exclude files earlier than specified date */\nBOOL fIncludeDate;      /* Include only files earlier than specified date */\nBOOL fVerbose;          /* Mention oddities in zip file structure */\nBOOL fQuiet;            /* Quiet operation */\nBOOL fCRLF_LF;          /* Translate CR/LF to LF */\nBOOL fLF_CRLF;          /* Translate LF to CR/LF */\nBOOL fJunkDir;          /* Junk directory names */\nBOOL fGrow;             /* Allow appending to a zip file */\nBOOL fForce;            /* Make entries using DOS names (k for Katz) */\nBOOL fMove;             /* Delete files added or updated in zip file */\nBOOL fDeleteEntries;    /* Delete files from zip file */\nBOOL fUpdate;           /* Update zip file--overwrite only if newer */\nBOOL fFreshen;          /* Freshen zip file--overwrite only */\nBOOL fJunkSFX;          /* Junk SFX prefix */\nBOOL fLatestTime;       /* Set zip file time to time of latest file in it */\nBOOL fComment;          /* Put comment in zip file */\nBOOL fOffsets;          /* Update archive offsets for SFX files */\nBOOL fPrivilege;        /* Use privileges (WIN32 only) */\nBOOL fEncryption;       /* TRUE if encryption supported, else FALSE.\n                           this is a read-only flag */\nLPSTR szSplitSize;\t\t/* This string contains the size that you want to \n\t\t\t\t\t\t   split the archive into. i.e. 100 for 100 bytes,\n\t\t\t\t\t\t   2K for 2 k bytes, where K is 1024, m for meg\n\t\t\t\t\t\t   and g for gig. If this string is not NULL it\n\t\t\t\t\t\t   will automatically be assumed that you wish to\n\t\t\t\t\t\t   split an archive. */\nLPSTR szIncludeList;    /* Pointer to include file list string (for VB) */\nlong IncludeListCount;  /* Count of file names in the include list array */\nchar **IncludeList;     /* Pointer to include file list array. Note that the last\n                           entry in the array must be NULL */\nLPSTR szExcludeList;    /* Pointer to exclude file list (for VB) */\nlong ExcludeListCount;  /* Count of file names in the include list array */\nchar **ExcludeList;     /* Pointer to exclude file list array. Note that the last\n                           entry in the array must be NULL */\nint  fRecurse;          /* Recurse into subdirectories. 1 => -r, 2 => -R */\nint  fRepair;           /* Repair archive. 1 => -F, 2 => -FF */\nchar fLevel;            /* Compression level (0 - 9) */\n} ZPOPT, _far *LPZPOPT;\n\nThe main entry point is ZpArchive(ZCL, *Opts) where the structure shown below\nis passed to the DLL when it is called.\n\ntypedef struct {\nint  argc;              = Count of files to zip\nLPSTR lpszZipFN;        = Archive file name\nchar **FNV;             = file names to zip up. Think of this an argv\nLPSTR lpszAltFNL;\t\t/* pointer to a string containing a list of file names to zip up,\n\t\t\t\t\t\t   separated by whitespace. Intended for use only by VB users, all\n\t\t\t\t\t\t   others should set this to NULL. */\n} ZCL, _far *LPZCL;\n\n\nFor examples of how the actual calls to the dll were set up in WiZ, look in\nthe file makezip.c in the WiZ source directory.\n\nFor examples of how the actual loading and unloading of the dll's themselves\nwas done, look in wizmain.c in the WiZ source directory. Note that WiZ looks\nspecifically for a particular version number of the dll, and also expects to\nfind the company name to be Info-ZIP. This is to protect from getting different\nversions of the dll loaded, with resulting unknown behavior.\n\nThere is a very simplistic example of how to load and call into the dll in\nexample.c and example.h. Note that this example does not implement any\ncommand line switches at all, and is merely intended as a guide for those\nbrave enough to enter a new world.\n\nThere are three additional (at the moment) entry points:\n\nZpInit, defined as\n\nint WINAPI ZpInit(ZIPUSERFUNCTIONS far * lpZipUserFunc);\n\nwhere ZIPUSERFUNCTIONS is defined as below.\n\nZpVersion, defined as\n\nZpVer * ZpVersion(void);\n\nwhere ZpVer is defined as:\n\ntypedef struct _ZpVer {\n    ulg structlen;          /* length of the struct being passed */\n    ulg flag;               /* bit 0: is_beta   bit 1: uses_zlib */\n    char *betalevel;        /* e.g., \"g BETA\" or \"\" */\n    char *date;             /* e.g., \"4 Sep 95\" (beta) or \"4 September 1995\" */\n    char *zlib_version;     /* e.g., \"0.95\" or NULL */\n    BOOL fEncryption;       /* TRUE if encryption enabled, FALSE otherwise */\n    _zip_version_type zip;\n    _zip_version_type os2dll;\n    _zip_version_type windll;\n} ZpVer;\n\nSee api.c for exactly what ZpVersion does, but the short version of\nwhat it does is return the zip and dll versions in the ZpVer structure.\nThe structure typedef's are in api.h. It will also tell you if encryption\nis enabled.\n\nThe typedef's for the function pointers in the structure ZIPUSERFUNCTIONS\nare shown immediately below.\n\ntypedef int (WINAPI DLLPRNT) (LPSTR, unsigned long);\ntypedef int (WINAPI DLLPASSWORD) (LPSTR, int, LPCSTR, LPCSTR);\ntypedef int (WINAPI DLLSPLIT) (LPSTR);\n#ifdef ZIP64_SUPPORT\ntypedef int (WINAPI DLLSERVICE) (LPCSTR, __int64);\ntypedef int (WINAPI DLLSERVICE_NO_INT64) (LPCSTR, unsigned long, unsigned long);\n#else\ntypedef int (WINAPI DLLSERVICE) (LPCSTR, unsigned long);\n#endif\n#endif\ntypedef int (WINAPI DLLCOMMENT)(LPSTR);\n\n\ntypedef struct {\nDLLPRNT *print;\nDLLCOMMENT *comment;\nDLLPASSWORD *password;\nDLLSPLIT *split;\t\t/* This MUST be set to NULL unless you want to be queried\n\t\t\t\t\t\t   for a destination for each split archive. */\n#ifdef ZIP64_SUPPORT\nDLLSERVICE *ServiceApplication64;\nDLLSERVICE_NO_INT64 *ServiceApplication64_No_Int64;\n#else\nDLLSERVICE *ServiceApplication;\n#endif\n} ZIPUSERFUNCTIONS, far * LPZIPUSERFUNCTIONS;\n\nLast revised April 26, 2004.\n\nMike White\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll16.def",
    "content": ";module-definition file for Windows Zip DLL -- used by link.exe\nLIBRARY ZIP16 ; Library module name\nDESCRIPTION 'Windows Info-ZIP Zip DLL 1.01 by Info-ZIP, Mike White 1996'\n\nCODE  PRELOAD FIXED\n\nDATA  PRELOAD MOVEABLE\n\nEXPORTS\n     ZpArchive\n     ZpVersion\n     ZpInit\n     ZpSetOptions\n     ZpGetOptions\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/windll32.def",
    "content": ";module-definition file for Windows Zip DLL -- used by link.exe\n\nLIBRARY ZIP32Z64 ; Library module name\nDESCRIPTION 'Windows Info-ZIP Zip DLL 3.0 by Info-ZIP, Mike White 2004'\n\n;CODE  PRELOAD FIXED\n\n;DATA  PRELOAD MOVEABLE\n\nEXPORTS\n     ZpArchive\n     ZpVersion\n     ZpInit\n\n"
  },
  {
    "path": "deps/infozip/zip30/windll/ziplib.def",
    "content": ";module-definition file for Windows Zip static library -- used by link.exe\nLIBRARY ZIP64 ; Library module name\nDESCRIPTION 'Windows Info-ZIP Zip Library 1.02 by Info-ZIP, Mike White 1997'\n\nCODE  PRELOAD FIXED\n\nDATA  PRELOAD MOVEABLE\n\nEXPORTS\n     ZpArchive\n     ZpVersion\n     ZpInit\n     ZpSetOptions\n     ZpGetOptions\n\n"
  },
  {
    "path": "deps/infozip/zip30/zbz2err.c",
    "content": "/*\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*---------------------------------------------------------------------------\n\n  zbz2err.c\n\n  This file contains the \"fatal error\" callback routine required by the\n  \"minimal\" (silent, non-stdio) setup of the bzip2 compression library.\n\n  The fatal bzip2 error bail-out routine is provided in a separate code\n  module, so that it can be easily overridden when the Zip package is\n  used as a static link library. One example is the WinDLL static library\n  usage for building a monolithic binary of the Windows application \"WiZ\"\n  that supports bzip2 both in compression and decompression operations.\n\n  Contains:  bz_internal_error()      (BZIP2_SUPPORT only)\n\n  Adapted from UnZip ubz2err.c, with all the DLL fine print stripped\n  out.\n\n  ---------------------------------------------------------------------------*/\n\n\n#define __ZBZ2ERR_C     /* identifies this source module */\n\n#include \"zip.h\"\n\n#ifdef BZIP2_SUPPORT\n# ifdef BZIP2_USEBZIP2DIR\n#   include \"bzip2/bzlib.h\"\n# else\n    /* If IZ_BZIP2 is defined as the location of the bzip2 files then\n       assume the location has been added to include path.  For Unix\n       this is done by the configure script. */\n    /* Also do not need path for bzip2 include if OS includes support\n       for bzip2 library. */\n#   include \"bzlib.h\"\n# endif\n\n/**********************************/\n/*  Function bz_internal_error()  */\n/**********************************/\n\n/* Call-back function for the bzip2 decompression code (compiled with\n * BZ_NO_STDIO), required to handle fatal internal bug-type errors of\n * the bzip2 library.\n */\nvoid bz_internal_error(errcode)\n    int errcode;\n{\n    sprintf(errbuf, \"fatal error (code %d) in bzip2 library\", errcode);\n    ziperr(ZE_LOGIC, errbuf);\n} /* end function bz_internal_error() */\n\n#endif /* def BZIP2_SUPPORT */\n"
  },
  {
    "path": "deps/infozip/zip30/zip.c",
    "content": "/*\n  zip.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  zip.c by Mark Adler.\n */\n#define __ZIP_C\n\n#include \"zip.h\"\n#include <time.h>       /* for tzset() declaration */\n#if defined(WIN32) || defined(WINDLL)\n#  define WIN32_LEAN_AND_MEAN\n#ifdef CR\n#undef CR\n#endif\n#  include <windows.h>\n#endif\n#ifdef WINDLL\n#  include <setjmp.h>\n#  include \"windll/windll.h\"\n#endif\n#define DEFCPYRT        /* main module: enable copyright string defines! */\n#include \"revision.h\"\n#include \"crc32.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n#include <ctype.h>\n#include <errno.h>\n#ifdef VMS\n#  include <stsdef.h>\n#  include \"vms/vmsmunch.h\"\n#  include \"vms/vms.h\"\n#endif\n\n#ifdef MACOS\n#  include \"macglob.h\"\n   extern MacZipGlobals MacZip;\n   extern int error_level;\n#endif\n\n#if (defined(MSDOS) && !defined(__GO32__)) || defined(__human68k__)\n#  include <process.h>\n#  if (!defined(P_WAIT) && defined(_P_WAIT))\n#    define P_WAIT _P_WAIT\n#  endif\n#endif\n\n#include <signal.h>\n#include <stdio.h>\n\n#ifdef UNICODE_TEST\n# ifdef WIN32\n#  include <direct.h>\n# endif\n#endif\n\n#ifdef BZIP2_SUPPORT\n  /* If IZ_BZIP2 is defined as the location of the bzip2 files then\n     assume the location has been added to include path.  For Unix\n     this is done by the configure script. */\n  /* Also do not need path for bzip2 include if OS includes support\n     for bzip2 library. */\n# include \"bzlib.h\"\n#endif\n\n#define MAXCOM 256      /* Maximum one-line comment size */\n\n\n/* Local option flags */\n#ifndef DELETE\n#define DELETE  0\n#endif\n#define ADD     1\n#define UPDATE  2\n#define FRESHEN 3\n#define ARCHIVE 4\nlocal int action = ADD; /* one of ADD, UPDATE, FRESHEN, DELETE, or ARCHIVE */\nlocal int comadd = 0;   /* 1=add comments for new files */\nlocal int zipedit = 0;  /* 1=edit zip comment and all file comments */\nlocal int latest = 0;   /* 1=set zip file time to time of latest file */\nlocal int test = 0;     /* 1=test zip file with unzip -t */\nlocal char *unzip_path = NULL; /* where to find unzip */\nlocal int tempdir = 0;  /* 1=use temp directory (-b) */\nlocal int junk_sfx = 0; /* 1=junk the sfx prefix */\n#if defined(AMIGA) || defined(MACOS)\nlocal int filenotes = 0; /* 1=take comments from AmigaDOS/MACOS filenotes */\n#endif\n\n#ifdef EBCDIC\nint aflag = __EBCDIC;   /* Convert EBCDIC to ASCII or stay EBCDIC ? */\n#endif\n#ifdef CMS_MVS\nint bflag = 0;          /* Use text mode as default */\n#endif\n\n#ifdef QDOS\nchar _version[] = VERSION;\n#endif\n\n#ifdef WINDLL\njmp_buf zipdll_error_return;\n#ifdef ZIP64_SUPPORT\n  unsigned long low, high; /* returning 64 bit values for systems without an _int64 */\n  uzoff_t filesize64;\n#endif\n#endif\n\n#if CRYPT\n/* Pointer to crc_table, needed in crypt.c */\n# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\nZCONST ulg near *crc_32_tab;\n# else\nZCONST uLongf *crc_32_tab;\n# endif\n#endif /* CRYPT */\n\n/* Local functions */\n\nlocal void freeup  OF((void));\nlocal int  finish  OF((int));\n#if (!defined(MACOS) && !defined(WINDLL))\nlocal void handler OF((int));\nlocal void license OF((void));\n#ifndef VMSCLI\nlocal void help    OF((void));\nlocal void help_extended OF((void));\n#endif /* !VMSCLI */\n#endif /* !MACOS && !WINDLL */\n\n/* prereading of arguments is not supported in new command\n   line interpreter get_option() so read filters as arguments\n   are processed and convert to expected array later */\nlocal int add_filter OF((int flag, char *pattern));\nlocal int filterlist_to_patterns OF((void));\n/* not used\n local int get_filters OF((int argc, char **argv));\n*/\n\n/* list to store file arguments */\nlocal long add_name OF((char *filearg));\n\n\nlocal int DisplayRunningStats OF((void));\nlocal int BlankRunningStats OF((void));\n\n#if !defined(WINDLL)\nlocal void version_info OF((void));\n# if !defined(MACOS)\nlocal void zipstdout OF((void));\n# endif /* !MACOS */\nlocal int check_unzip_version OF((char *unzippath));\nlocal void check_zipfile OF((char *zipname, char *zippath));\n#endif /* !WINDLL */\n\n/* structure used by add_filter to store filters */\nstruct filterlist_struct {\n  char flag;\n  char *pattern;\n  struct filterlist_struct *next;\n};\nstruct filterlist_struct *filterlist = NULL;  /* start of list */\nstruct filterlist_struct *lastfilter = NULL;  /* last filter in list */\n\n/* structure used by add_filearg to store file arguments */\nstruct filelist_struct {\n  char *name;\n  struct filelist_struct *next;\n};\nlong filearg_count = 0;\nstruct filelist_struct *filelist = NULL;  /* start of list */\nstruct filelist_struct *lastfile = NULL;  /* last file in list */\n\nlocal void freeup()\n/* Free all allocations in the 'found' list, the 'zfiles' list and\n   the 'patterns' list. */\n{\n  struct flist far *f;  /* steps through found list */\n  struct zlist far *z;  /* pointer to next entry in zfiles list */\n\n  for (f = found; f != NULL; f = fexpel(f))\n    ;\n  while (zfiles != NULL)\n  {\n    z = zfiles->nxt;\n    if (zfiles->zname && zfiles->zname != zfiles->name)\n      free((zvoid *)(zfiles->zname));\n    if (zfiles->name)\n      free((zvoid *)(zfiles->name));\n    if (zfiles->iname)\n      free((zvoid *)(zfiles->iname));\n    if (zfiles->cext && zfiles->cextra && zfiles->cextra != zfiles->extra)\n      free((zvoid *)(zfiles->cextra));\n    if (zfiles->ext && zfiles->extra)\n      free((zvoid *)(zfiles->extra));\n    if (zfiles->com && zfiles->comment)\n      free((zvoid *)(zfiles->comment));\n    if (zfiles->oname)\n      free((zvoid *)(zfiles->oname));\n#ifdef UNICODE_SUPPORT\n    if (zfiles->uname)\n      free((zvoid *)(zfiles->uname));\n    if (zfiles->zuname)\n      free((zvoid *)(zfiles->zuname));\n    if (zfiles->ouname)\n      free((zvoid *)(zfiles->ouname));\n# ifdef WIN32\n    if (zfiles->namew)\n      free((zvoid *)(zfiles->namew));\n    if (zfiles->inamew)\n      free((zvoid *)(zfiles->inamew));\n    if (zfiles->znamew)\n      free((zvoid *)(zfiles->znamew));\n# endif\n#endif\n    farfree((zvoid far *)zfiles);\n    zfiles = z;\n    zcount--;\n  }\n\n  if (patterns != NULL) {\n    while (pcount-- > 0) {\n      if (patterns[pcount].zname != NULL)\n        free((zvoid *)(patterns[pcount].zname));\n    }\n    free((zvoid *)patterns);\n    patterns = NULL;\n  }\n\n  /* close logfile */\n  if (logfile) {\n    fclose(logfile);\n  }\n}\n\nlocal int finish(e)\nint e;                  /* exit code */\n/* Process -o and -m options (if specified), free up malloc'ed stuff, and\n   exit with the code e. */\n{\n  int r;                /* return value from trash() */\n  ulg t;                /* latest time in zip file */\n  struct zlist far *z;  /* pointer into zfile list */\n\n  /* If latest, set time to zip file to latest file in zip file */\n  if (latest && zipfile && strcmp(zipfile, \"-\"))\n  {\n    diag(\"changing time of zip file to time of latest file in it\");\n    /* find latest time in zip file */\n    if (zfiles == NULL)\n       zipwarn(\"zip file is empty, can't make it as old as latest entry\", \"\");\n    else {\n      t = 0;\n      for (z = zfiles; z != NULL; z = z->nxt)\n        /* Ignore directories in time comparisons */\n#ifdef USE_EF_UT_TIME\n        if (z->iname[z->nam-1] != (char)0x2f)   /* ascii '/' */\n        {\n          iztimes z_utim;\n          ulg z_tim;\n\n          z_tim = ((get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?\n                   unix2dostime(&z_utim.mtime) : z->tim);\n          if (t < z_tim)\n            t = z_tim;\n        }\n#else /* !USE_EF_UT_TIME */\n        if (z->iname[z->nam-1] != (char)0x2f    /* ascii '/' */\n            && t < z->tim)\n          t = z->tim;\n#endif /* ?USE_EF_UT_TIME */\n      /* set modified time of zip file to that time */\n      if (t != 0)\n        stamp(zipfile, t);\n      else\n        zipwarn(\n         \"zip file has only directories, can't make it as old as latest entry\",\n         \"\");\n    }\n  }\n  if (tempath != NULL)\n  {\n    free((zvoid *)tempath);\n    tempath = NULL;\n  }\n  if (zipfile != NULL)\n  {\n    free((zvoid *)zipfile);\n    zipfile = NULL;\n  }\n  if (in_file != NULL)\n  {\n    fclose(in_file);\n    in_file = NULL;\n  }\n  if (in_path != NULL)\n  {\n    free((zvoid *)in_path);\n    in_path = NULL;\n  }\n  if (out_path != NULL)\n  {\n    free((zvoid *)out_path);\n    out_path = NULL;\n  }\n  if (zcomment != NULL)\n  {\n    free((zvoid *)zcomment);\n    zcomment = NULL;\n  }\n\n\n  /* If dispose, delete all files in the zfiles list that are marked */\n  if (dispose)\n  {\n    diag(\"deleting files that were added to zip file\");\n    if ((r = trash()) != ZE_OK)\n      ZIPERR(r, \"was deleting moved files and directories\");\n  }\n\n\n  /* Done! */\n  freeup();\n  return e;\n}\n\nvoid ziperr(c, h)\nint c;                  /* error code from the ZE_ class */\nZCONST char *h;         /* message about how it happened */\n/* Issue a message for the error, clean up files and memory, and exit. */\n{\n#ifndef WINDLL\n#ifndef MACOS\n  static int error_level = 0;\n#endif\n\n  if (error_level++ > 0)\n     /* avoid recursive ziperr() printouts (his should never happen) */\n     EXIT(ZE_LOGIC);  /* ziperr recursion is an internal logic error! */\n#endif /* !WINDLL */\n\n  if (mesg_line_started) {\n    fprintf(mesg, \"\\n\");\n    mesg_line_started = 0;\n  }\n  if (logfile && logfile_line_started) {\n    fprintf(logfile, \"\\n\");\n    logfile_line_started = 0;\n  }\n  if (h != NULL) {\n    if (PERR(c))\n      fprintf(mesg, \"zip I/O error: %s\", strerror(errno));\n      /* perror(\"zip I/O error\"); */\n    fflush(mesg);\n    fprintf(mesg, \"\\nzip error: %s (%s)\\n\", ZIPERRORS(c), h);\n#ifdef DOS\n    check_for_windows(\"Zip\");\n#endif\n    if (logfile) {\n      if (PERR(c))\n        fprintf(logfile, \"zip I/O error: %s\\n\", strerror(errno));\n      fprintf(logfile, \"\\nzip error: %s (%s)\\n\", ZIPERRORS(c), h);\n      logfile_line_started = 0;\n    }\n  }\n  if (tempzip != NULL)\n  {\n    if (tempzip != zipfile) {\n      if (current_local_file)\n        fclose(current_local_file);\n      if (y != current_local_file && y != NULL)\n        fclose(y);\n#ifndef DEBUG\n      destroy(tempzip);\n#endif\n      free((zvoid *)tempzip);\n    } else {\n      /* -g option, attempt to restore the old file */\n\n      /* zip64 support 09/05/2003 R.Nausedat */\n      uzoff_t k = 0;                        /* keep count for end header */\n      uzoff_t cb = cenbeg;                  /* get start of central */\n\n      struct zlist far *z;  /* steps through zfiles linked list */\n\n      fprintf(mesg, \"attempting to restore %s to its previous state\\n\",\n         zipfile);\n      if (logfile)\n        fprintf(logfile, \"attempting to restore %s to its previous state\\n\",\n           zipfile);\n\n      zfseeko(y, cenbeg, SEEK_SET);\n\n      tempzn = cenbeg;\n      for (z = zfiles; z != NULL; z = z->nxt)\n      {\n        putcentral(z);\n        tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;\n        k++;\n      }\n      putend(k, tempzn - cb, cb, zcomlen, zcomment);\n      fclose(y);\n      y = NULL;\n    }\n  }\n\n  if (key != NULL) {\n    free((zvoid *)key);\n    key = NULL;\n  }\n  if (tempath != NULL) {\n    free((zvoid *)tempath);\n    tempath = NULL;\n  }\n  if (zipfile != NULL) {\n    free((zvoid *)zipfile);\n    zipfile = NULL;\n  }\n  if (out_path != NULL) {\n    free((zvoid *)out_path);\n    out_path = NULL;\n  }\n  if (zcomment != NULL) {\n    free((zvoid *)zcomment);\n    zcomment = NULL;\n  }\n\n  freeup();\n#ifndef WINDLL\n  EXIT(c);\n#else\n  longjmp(zipdll_error_return, c);\n#endif\n}\n\n\nvoid error(h)\n  ZCONST char *h;\n/* Internal error, should never happen */\n{\n  ziperr(ZE_LOGIC, h);\n}\n\n#if (!defined(MACOS) && !defined(WINDLL))\nlocal void handler(s)\nint s;                  /* signal number (ignored) */\n/* Upon getting a user interrupt, turn echo back on for tty and abort\n   cleanly using ziperr(). */\n{\n#if defined(AMIGA) && defined(__SASC)\n   _abort();\n#else\n#if !defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS)\n  echon();\n  putc('\\n', mesg);\n#endif /* !MSDOS */\n#endif /* AMIGA && __SASC */\n  ziperr(ZE_ABORT, \"aborting\");\n  s++;                                  /* keep some compilers happy */\n}\n#endif /* !MACOS && !WINDLL */\n\nvoid zipmessage_nl(a, nl)\nZCONST char *a;     /* message string to output */\nint nl;             /* 1 = add nl to end */\n/* If nl false, print a message to mesg without new line.\n   If nl true, print and add new line.  If logfile is\n   open then also write message to log file. */\n{\n  if (noisy) {\n    if (a && strlen(a)) {\n      fprintf(mesg, \"%s\", a);\n      mesg_line_started = 1;\n    }\n    if (nl) {\n      if (mesg_line_started) {\n        fprintf(mesg, \"\\n\");\n        mesg_line_started = 0;\n      }\n    } else if (a && strlen(a)) {\n      mesg_line_started = 1;\n    }\n    fflush(mesg);\n  }\n  if (logfile) {\n    if (a && strlen(a)) {\n      fprintf(logfile, \"%s\", a);\n      logfile_line_started = 1;\n    }\n    if (nl) {\n      if (logfile_line_started) {\n        fprintf(logfile, \"\\n\");\n        logfile_line_started = 0;\n      }\n    } else if (a && strlen(a)) {\n      logfile_line_started = 1;\n    }\n    fflush(logfile);\n  }\n}\n\nvoid zipmessage(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a message to mesg and flush.  Also write to log file if\n   open.  Write new line first if current line has output already. */\n{\n  if (noisy) {\n    if (mesg_line_started)\n      fprintf(mesg, \"\\n\");\n    fprintf(mesg, \"%s%s\\n\", a, b);\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n  if (logfile) {\n    if (logfile_line_started)\n      fprintf(logfile, \"\\n\");\n    fprintf(logfile, \"%s%s\\n\", a, b);\n    logfile_line_started = 0;\n    fflush(logfile);\n  }\n}\n\nvoid zipwarn(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a warning message to mesg (usually stderr) and return. */\n{\n  if (noisy) {\n    if (mesg_line_started)\n      fprintf(mesg, \"\\n\");\n    fprintf(mesg, \"\\tzip warning: %s%s\\n\", a, b);\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n  if (logfile) {\n    if (logfile_line_started)\n      fprintf(logfile, \"\\n\");\n    fprintf(logfile, \"\\tzip warning: %s%s\\n\", a, b);\n    logfile_line_started = 0;\n    fflush(logfile);\n  }\n}\n\n#ifndef WINDLL\nlocal void license()\n/* Print license information to stdout. */\n{\n  extent i;             /* counter for copyright array */\n\n  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)\n    puts(swlicense[i]);\n}\n\n#ifdef VMSCLI\nvoid help()\n#else\nlocal void help()\n#endif\n/* Print help (along with license info) to stdout. */\n{\n  extent i;             /* counter for help array */\n\n  /* help array */\n  static ZCONST char *text[] = {\n#ifdef VMS\n\"Zip %s (%s). Usage: zip == \\\"$ disk:[dir]zip.exe\\\"\",\n#else\n\"Zip %s (%s). Usage:\",\n#endif\n#ifdef MACOS\n\"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]\",\n\"  The default action is to add or replace zipfile entries from list.\",\n\" \",\n\"  -f   freshen: only changed files  -u   update: only changed or new files\",\n\"  -d   delete entries in zipfile    -m   move into zipfile (delete OS files)\",\n\"  -r   recurse into directories     -j   junk (don't record) directory names\",\n\"  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)\",\n\"  -1   compress faster              -9   compress better\",\n\"  -q   quiet operation              -v   verbose operation/print version info\",\n\"  -c   add one-line comments        -z   add zipfile comment\",\n\"                                    -o   make zipfile as old as latest entry\",\n\"  -F   fix zipfile (-FF try harder) -D   do not add directory entries\",\n\"  -T   test zipfile integrity       -X   eXclude eXtra file attributes\",\n#  if CRYPT\n\"  -e   encrypt                      -n   don't compress these suffixes\"\n#  else\n\"  -h   show this help               -n   don't compress these suffixes\"\n#  endif\n,\" -h2  show more help\",\n\"  Macintosh specific:\",\n\"  -jj  record Fullpath (+ Volname)  -N store finder-comments as comments\",\n\"  -df  zip only datafork of a file  -S include finder invisible/system files\"\n#else /* !MACOS */\n#ifdef VM_CMS\n\"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]\",\n#else  /* !VM_CMS */\n\"zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]\",\n#endif /* ?VM_CMS */\n\"  The default action is to add or replace zipfile entries from list, which\",\n\"  can include the special name - to compress standard input.\",\n\"  If zipfile and list are omitted, zip compresses stdin to stdout.\",\n\"  -f   freshen: only changed files  -u   update: only changed or new files\",\n\"  -d   delete entries in zipfile    -m   move into zipfile (delete OS files)\",\n\"  -r   recurse into directories     -j   junk (don't record) directory names\",\n#ifdef THEOS\n\"  -0   store only                   -l   convert CR to CR LF (-ll CR LF to CR)\",\n#else\n\"  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)\",\n#endif\n\"  -1   compress faster              -9   compress better\",\n\"  -q   quiet operation              -v   verbose operation/print version info\",\n\"  -c   add one-line comments        -z   add zipfile comment\",\n\"  -@   read names from stdin        -o   make zipfile as old as latest entry\",\n\"  -x   exclude the following names  -i   include only the following names\",\n#ifdef EBCDIC\n#ifdef CMS_MVS\n\"  -a   translate to ASCII           -B   force binary read (text is default)\",\n#else  /* !CMS_MVS */\n\"  -a   translate to ASCII\",\n#endif /* ?CMS_MVS */\n#endif /* EBCDIC */\n#ifdef TANDEM\n\"                                    -Bn  set Enscribe formatting options\",\n#endif\n\"  -F   fix zipfile (-FF try harder) -D   do not add directory entries\",\n\"  -A   adjust self-extracting exe   -J   junk zipfile prefix (unzipsfx)\",\n\"  -T   test zipfile integrity       -X   eXclude eXtra file attributes\",\n#ifdef VMS\n\"  -C   preserve case of file names  -C-  down-case all file names\",\n\"  -C2  preserve case of ODS2 names  -C2- down-case ODS2 file names* (*=default)\",\n\"  -C5  preserve case of ODS5 names* -C5- down-case ODS5 file names\",\n\"  -V   save VMS file attributes (-VV also save allocated blocks past EOF)\",\n\"  -w   store file version numbers\\\n   -ww  store file version numbers as \\\".nnn\\\"\",\n#endif /* def VMS */\n#ifdef NTSD_EAS\n\"  -!   use privileges (if granted) to obtain all aspects of WinNT security\",\n#endif /* NTSD_EAS */\n#ifdef OS2\n\"  -E   use the .LONGNAME Extended attribute (if found) as filename\",\n#endif /* OS2 */\n#ifdef S_IFLNK\n\"  -y   store symbolic links as the link instead of the referenced file\",\n#endif /* !S_IFLNK */\n/*\n\"  -R   PKZIP recursion (see manual)\",\n*/\n#if defined(MSDOS) || defined(OS2)\n\"  -$   include volume label         -S   include system and hidden files\",\n#endif\n#ifdef AMIGA\n#  if CRYPT\n\"  -N   store filenotes as comments  -e   encrypt\",\n\"  -h   show this help               -n   don't compress these suffixes\"\n#  else\n\"  -N   store filenotes as comments  -n   don't compress these suffixes\"\n#  endif\n#else /* !AMIGA */\n#  if CRYPT\n\"  -e   encrypt                      -n   don't compress these suffixes\"\n#  else\n\"  -h   show this help               -n   don't compress these suffixes\"\n#  endif\n#endif /* ?AMIGA */\n#ifdef RISCOS\n,\"  -h2  show more help               -I   don't scan thru Image files\"\n#else\n,\"  -h2  show more help\"\n#endif\n#endif /* ?MACOS */\n#ifdef VMS\n,\"  (Must quote upper-case options, like \\\"-V\\\", unless SET PROC/PARSE=EXTEND)\"\n#endif /* def VMS */\n,\"  \"\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)\n  {\n    printf(copyright[i], \"zip\");\n    putchar('\\n');\n  }\n  for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n  {\n    printf(text[i], VERSION, REVDATE);\n    putchar('\\n');\n  }\n}\n\n#ifdef VMSCLI\nvoid help_extended()\n#else\nlocal void help_extended()\n#endif\n/* Print extended help to stdout. */\n{\n  extent i;             /* counter for help array */\n\n  /* help array */\n  static ZCONST char *text[] = {\n\"\",\n\"Extended Help for Zip\",\n\"\",\n\"See the Zip Manual for more detailed help\",\n\"\",\n\"\",\n\"Zip stores files in zip archives.  The default action is to add or replace\",\n\"zipfile entries.\",\n\"\",\n\"Basic command line:\",\n\"  zip options archive_name file file ...\",\n\"\",\n\"Some examples:\",\n\"  Add file.txt to z.zip (create z if needed):      zip z file.txt\",\n\"  Zip all files in current dir:                    zip z *\",\n\"  Zip files in current dir and subdirs also:       zip -r z .\",\n\"\",\n\"Basic modes:\",\n\" External modes (selects files from file system):\",\n\"        add      - add new files/update existing files in archive (default)\",\n\"  -u    update   - add new files/update existing files only if later date\",\n\"  -f    freshen  - update existing files only (no files added)\",\n\"  -FS   filesync - update if date or size changed, delete if no OS match\",\n\" Internal modes (selects entries in archive):\",\n\"  -d    delete   - delete files from archive (see below)\",\n\"  -U    copy     - select files in archive to copy (use with --out)\",\n\"\",\n\"Basic options:\",\n\"  -r        recurse into directories (see Recursion below)\",\n\"  -m        after archive created, delete original files (move into archive)\",\n\"  -j        junk directory names (store just file names)\",\n\"  -q        quiet operation\",\n\"  -v        verbose operation (just \\\"zip -v\\\" shows version information)\",\n\"  -c        prompt for one-line comment for each entry\",\n\"  -z        prompt for comment for archive (end with just \\\".\\\" line or EOF)\",\n\"  -@        read names to zip from stdin (one path per line)\",\n\"  -o        make zipfile as old as latest entry\",\n\"\",\n\"\",\n\"Syntax:\",\n\"  The full command line syntax is:\",\n\"\",\n\"    zip [-shortopts ...] [--longopt ...] [zipfile [path path ...]] [-xi list]\",\n\"\",\n\"  Any number of short option and long option arguments are allowed\",\n\"  (within limits) as well as any number of path arguments for files\",\n\"  to zip up.  If zipfile exists, the archive is read in.  If zipfile\",\n\"  is \\\"-\\\", stream to stdout.  If any path is \\\"-\\\", zip stdin.\",\n\"\",\n\"Options and Values:\",\n\"  For short options that take values, use -ovalue or -o value or -o=value\",\n\"  For long option values, use either --longoption=value or --longoption value\",\n\"  For example:\",\n\"    zip -ds 10 --temp-dir=path zipfile path1 path2 --exclude pattern pattern\",\n\"  Avoid -ovalue (no space between) to avoid confusion\",\n\"  In particular, be aware of 2-character options.  For example:\",\n\"    -d -s is (delete, split size) while -ds is (dot size)\",\n\"  Usually better to break short options across multiple arguments by function\",\n\"    zip -r -dbdcds 10m -lilalf logfile archive input_directory -ll\",\n\"\",\n\"  All args after just \\\"--\\\" arg are read verbatim as paths and not options.\",\n\"    zip zipfile path path ... -- verbatimpath verbatimpath ...\",\n\"  Use -nw to also disable wildcards, so paths are read literally:\",\n\"    zip zipfile -nw -- \\\"-leadingdashpath\\\" \\\"a[path].c\\\" \\\"path*withwildcard\\\"\",\n\"  You may still have to escape or quote arguments to avoid shell expansion\",\n\"\",\n\"Wildcards:\",\n\"  Internally zip supports the following wildcards:\",\n\"    ?       (or %% or #, depending on OS) matches any single character\",\n\"    *       matches any number of characters, including zero\",\n\"    [list]  matches char in list (regex), can do range [ac-f], all but [!bf]\",\n\"  If port supports [], must escape [ as [[] or use -nw to turn off wildcards\",\n\"  For shells that expand wildcards, escape (\\\\* or \\\"*\\\") so zip can recurse\",\n\"    zip zipfile -r . -i \\\"*.h\\\"\",\n\"\",\n\"  Normally * crosses dir bounds in path, e.g. 'a*b' can match 'ac/db'.  If\",\n\"   -ws option used, * does not cross dir bounds but ** does\",\n\"\",\n\"  For DOS and Windows, [list] is now disabled unless the new option\",\n\"  -RE       enable [list] (regular expression) matching\",\n\"  is used to avoid problems with file paths containing \\\"[\\\" and \\\"]\\\":\",\n\"    zip files_ending_with_number -RE foo[0-9].c\",\n\"\",\n\"Include and Exclude:\",\n\"  -i pattern pattern ...   include files that match a pattern\",\n\"  -x pattern pattern ...   exclude files that match a pattern\",\n\"  Patterns are paths with optional wildcards and match paths as stored in\",\n\"  archive.  Exclude and include lists end at next option, @, or end of line.\",\n\"    zip -x pattern pattern @ zipfile path path ...\",\n\"\",\n\"Case matching:\",\n\"  On most OS the case of patterns must match the case in the archive, unless\",\n\"  the -ic option is used.\",\n\"  -ic       ignore case of archive entries\",\n\"  This option not available on case-sensitive file systems.  On others, case\",\n\"  ignored when matching files on file system but matching against archive\",\n\"  entries remains case sensitive for modes -f (freshen), -U (archive copy),\",\n\"  and -d (delete) because archive paths are always case sensitive.  With\",\n\"  -ic, all matching ignores case, but it's then possible multiple archive\",\n\"  entries that differ only in case will match.\",\n\"\",\n\"End Of Line Translation (text files only):\",\n\"  -l        change CR or LF (depending on OS) line end to CR LF (Unix->Win)\",\n\"  -ll       change CR LF to CR or LF (depending on OS) line end (Win->Unix)\",\n\"  If first buffer read from file contains binary the translation is skipped\",\n\"\",\n\"Recursion:\",\n\"  -r        recurse paths, include files in subdirs:  zip -r a path path ...\",\n\"  -R        recurse current dir and match patterns:   zip -R a ptn ptn ...\",\n\"  Use -i and -x with either to include or exclude paths\",\n\"  Path root in archive starts at current dir, so if /a/b/c/file and\",\n\"   current dir is /a/b, 'zip -r archive .' puts c/file in archive\",\n\"\",\n\"Date filtering:\",\n\"  -t date   exclude before (include files modified on this date and later)\",\n\"  -tt date  include before (include files modified before date)\",\n\"  Can use both at same time to set a date range\",\n\"  Dates are mmddyyyy or yyyy-mm-dd\",\n\"\",\n\"Deletion, File Sync:\",\n\"  -d        delete files\",\n\"  Delete archive entries matching internal archive paths in list\",\n\"    zip archive -d pattern pattern ...\",\n\"  Can use -t and -tt to select files in archive, but NOT -x or -i, so\",\n\"    zip archive -d \\\"*\\\" -t 2005-12-27\",\n\"  deletes all files from archive.zip with date of 27 Dec 2005 and later\",\n\"  Note the * (escape as \\\"*\\\" on Unix) to select all files in archive\",\n\"\",\n\"  -FS       file sync\",\n\"  Similar to update, but files updated if date or size of entry does not\",\n\"  match file on OS.  Also deletes entry from archive if no matching file\",\n\"  on OS.\",\n\"    zip archive_to_update -FS -r dir_used_before\",\n\"  Result generally same as creating new archive, but unchanged entries\",\n\"  are copied instead of being read and compressed so can be faster.\",\n\"      WARNING:  -FS deletes entries so make backup copy of archive first\",\n\"\",\n\"Compression:\",\n\"  -0        store files (no compression)\",\n\"  -1 to -9  compress fastest to compress best (default is 6)\",\n\"  -Z cm     set compression method to cm:\",\n\"              store   - store without compression, same as option -0\",\n\"              deflate - original zip deflate, same as -1 to -9 (default)\",\n\"            if bzip2 is enabled:\",\n\"              bzip2 - use bzip2 compression (need modern unzip)\",\n\"\",\n\"Encryption:\",\n\"  -e        use standard (weak) PKZip 2.0 encryption, prompt for password\",\n\"  -P pswd   use standard encryption, password is pswd\",\n\"\",\n\"Splits (archives created as a set of split files):\",\n\"  -s ssize  create split archive with splits of size ssize, where ssize nm\",\n\"              n number and m multiplier (kmgt, default m), 100k -> 100 kB\",\n\"  -sp       pause after each split closed to allow changing disks\",\n\"      WARNING:  Archives created with -sp use data descriptors and should\",\n\"                work with most unzips but may not work with some\",\n\"  -sb       ring bell when pause\",\n\"  -sv       be verbose about creating splits\",\n\"      Split archives CANNOT be updated, but see --out and Copy Mode below\",\n\"\",\n\"Using --out (output to new archive):\",\n\"  --out oa  output to new archive oa\",\n\"  Instead of updating input archive, create new output archive oa.\",\n\"  Result is same as without --out but in new archive.  Input archive\",\n\"  unchanged.\",\n\"      WARNING:  --out ALWAYS overwrites any existing output file\",\n\"  For example, to create new_archive like old_archive but add newfile1\",\n\"  and newfile2:\",\n\"    zip old_archive newfile1 newfile2 --out new_archive\",\n\"  Cannot update split archive, so use --out to out new archive:\",\n\"    zip in_split_archive newfile1 newfile2 --out out_split_archive\",\n\"  If input is split, output will default to same split size\",\n\"  Use -s=0 or -s- to turn off splitting to convert split to single file:\",\n\"    zip in_split_archive -s 0 --out out_single_file_archive\",\n\"      WARNING:  If overwriting old split archive but need less splits,\",\n\"                old splits not overwritten are not needed but remain\",\n\"\",\n\"Copy Mode (copying from archive to archive):\",\n\"  -U        (also --copy) select entries in archive to copy (reverse delete)\",\n\"  Copy Mode copies entries from old to new archive with --out and is used by\",\n\"  zip when either no input files on command line or -U (--copy) used.\",\n\"    zip inarchive --copy pattern pattern ... --out outarchive\",\n\"  To copy only files matching *.c into new archive, excluding foo.c:\",\n\"    zip old_archive --copy \\\"*.c\\\" --out new_archive -x foo.c\",\n\"  If no input files and --out, copy all entries in old archive:\",\n\"    zip old_archive --out new_archive\",\n\"\",\n\"Streaming and FIFOs:\",\n\"  prog1 | zip -ll z -      zip output of prog1 to zipfile z, converting CR LF\",\n\"  zip - -R \\\"*.c\\\" | prog2   zip *.c files in current dir and stream to prog2 \",\n\"  prog1 | zip | prog2      zip in pipe with no in or out acts like zip - -\",\n\"  If Zip is Zip64 enabled, streaming stdin creates Zip64 archives by default\",\n\"   that need PKZip 4.5 unzipper like UnZip 6.0\",\n\"  WARNING:  Some archives created with streaming use data descriptors and\",\n\"            should work with most unzips but may not work with some\",\n\"  Can use -fz- to turn off Zip64 if input not large (< 4 GB):\",\n\"    prog_with_small_output | zip archive -fz-\",\n\"\",\n\"  Zip now can read Unix FIFO (named pipes).  Off by default to prevent zip\",\n\"  from stopping unexpectedly on unfed pipe, use -FI to enable:\",\n\"    zip -FI archive fifo\",\n\"\",\n\"Dots, counts:\",\n\"  -db       display running count of bytes processed and bytes to go\",\n\"              (uncompressed size, except delete and copy show stored size)\",\n\"  -dc       display running count of entries done and entries to go\",\n\"  -dd       display dots every 10 MB (or dot size) while processing files\",\n\"  -dg       display dots globally for archive instead of for each file\",\n\"    zip -qdgds 10m   will turn off most output except dots every 10 MB\",\n\"  -ds siz   each dot is siz processed where siz is nm as splits (0 no dots)\",\n\"  -du       display original uncompressed size for each entry as added\",\n\"  -dv       display volume (disk) number in format in_disk>out_disk\",\n\"  Dot size is approximate, especially for dot sizes less than 1 MB\",\n\"  Dot options don't apply to Scanning files dots (dot/2sec) (-q turns off)\",\n\"\",\n\"Logging:\",\n\"  -lf path  open file at path as logfile (overwrite existing file)\",\n\"  -la       append to existing logfile\",\n\"  -li       include info messages (default just warnings and errors)\",\n\"\",\n\"Testing archives:\",\n\"  -T        test completed temp archive with unzip before updating archive\",\n\"  -TT cmd   use command cmd instead of 'unzip -tqq' to test archive\",\n\"             On Unix, to use unzip in current directory, could use:\",\n\"               zip archive file1 file2 -T -TT \\\"./unzip -tqq\\\"\",\n\"             In cmd, {} replaced by temp archive path, else temp appended.\",\n\"             The return code is checked for success (0 on Unix)\",\n\"\",\n\"Fixing archives:\",\n\"  -F        attempt to fix a mostly intact archive (try this first)\",\n\"  -FF       try to salvage what can (may get more but less reliable)\",\n\"  Fix options copy entries from potentially bad archive to new archive.\",\n\"  -F tries to read archive normally and copy only intact entries, while\",\n\"  -FF tries to salvage what can and may result in incomplete entries.\",\n\"  Must use --out option to specify output archive:\",\n\"    zip -F bad.zip --out fixed.zip\",\n\"  Use -v (verbose) with -FF to see details:\",\n\"    zip reallybad.zip -FF -v --out fixed.zip\",\n\"  Currently neither option fixes bad entries, as from text mode ftp get.\",\n\"\",\n\"Difference mode:\",\n\"  -DF       (also --dif) only include files that have changed or are\",\n\"             new as compared to the input archive\",\n\"  Difference mode can be used to create incremental backups.  For example:\",\n\"    zip --dif full_backup.zip -r somedir --out diff.zip\",\n\"  will store all new files, as well as any files in full_backup.zip where\",\n\"  either file time or size have changed from that in full_backup.zip,\",\n\"  in new diff.zip.  Output archive not excluded automatically if exists,\",\n\"  so either use -x to exclude it or put outside what is being zipped.\",\n\"\",\n\"DOS Archive bit (Windows only):\",\n\"  -AS       include only files with the DOS Archive bit set\",\n\"  -AC       after archive created, clear archive bit of included files\",\n\"      WARNING: Once the archive bits are cleared they are cleared\",\n\"               Use -T to test the archive before the bits are cleared\",\n\"               Can also use -sf to save file list before zipping files\",\n\"\",\n\"Show files:\",\n\"  -sf       show files to operate on and exit (-sf- logfile only)\",\n\"  -su       as -sf but show escaped UTF-8 Unicode names also if exist\",\n\"  -sU       as -sf but show escaped UTF-8 Unicode names instead\",\n\"  Any character not in the current locale is escaped as #Uxxxx, where x\",\n\"  is hex digit, if 16-bit code is sufficient, or #Lxxxxxx if 24-bits\",\n\"  are needed.  If add -UN=e, Zip escapes all non-ASCII characters.\",\n\"\",\n\"Unicode:\",\n\"  If compiled with Unicode support, Zip stores UTF-8 path of entries.\",\n\"  This is backward compatible.  Unicode paths allow better conversion\",\n\"  of entry names between different character sets.\",\n\"\",\n\"  New Unicode extra field includes checksum to verify Unicode path\",\n\"  goes with standard path for that entry (as utilities like ZipNote\",\n\"  can rename entries).  If these do not match, use below options to\",\n\"  set what Zip does:\",\n\"      -UN=Quit     - if mismatch, exit with error\",\n\"      -UN=Warn     - if mismatch, warn, ignore UTF-8 (default)\",\n\"      -UN=Ignore   - if mismatch, quietly ignore UTF-8\",\n\"      -UN=No       - ignore any UTF-8 paths, use standard paths for all\",\n\"  An exception to -UN=N are entries with new UTF-8 bit set (instead\",\n\"  of using extra fields).  These are always handled as Unicode.\",\n\"\",\n\"  Normally Zip escapes all chars outside current char set, but leaves\",\n\"  as is supported chars, which may not be OK in path names.  -UN=Escape\",\n\"  escapes any character not ASCII:\",\n\"    zip -sU -UN=e archive\",\n\"  Can use either normal path or escaped Unicode path on command line\",\n\"  to match files in archive.\",\n\"\",\n\"  Zip now stores UTF-8 in entry path and comment fields on systems\",\n\"  where UTF-8 char set is default, such as most modern Unix, and\",\n\"  and on other systems in new extra fields with escaped versions in\",\n\"  entry path and comment fields for backward compatibility.\",\n\"  Option -UN=UTF8 will force storing UTF-8 in entry path and comment\",\n\"  fields:\",\n\"      -UN=UTF8     - store UTF-8 in entry path and comment fields\",\n\"  This option can be useful for multi-byte char sets on Windows where\",\n\"  escaped paths and comments can be too long to be valid as the UTF-8\",\n\"  versions tend to be shorter.\",\n\"\",\n\"  Only UTF-8 comments on UTF-8 native systems supported.  UTF-8 comments\",\n\"  for other systems planned in next release.\",\n\"\",\n\"Self extractor:\",\n\"  -A        Adjust offsets - a self extractor is created by prepending\",\n\"             the extractor executable to archive, but internal offsets\",\n\"             are then off.  Use -A to fix offsets.\",\n\"  -J        Junk sfx - removes prepended extractor executable from\",\n\"             self extractor, leaving a plain zip archive.\",\n\"\",\n\"More option highlights (see manual for additional options and details):\",\n\"  -b dir    when creating or updating archive, create the temp archive in\",\n\"             dir, which allows using seekable temp file when writing to a\",\n\"             write once CD, such archives compatible with more unzips\",\n\"             (could require additional file copy if on another device)\",\n\"  -MM       input patterns must match at least one file and matched files\",\n\"             must be readable or exit with OPEN error and abort archive\",\n\"             (without -MM, both are warnings only, and if unreadable files\",\n\"             are skipped OPEN error (18) returned after archive created)\",\n\"  -nw       no wildcards (wildcards are like any other character)\",\n\"  -sc       show command line arguments as processed and exit\",\n\"  -sd       show debugging as Zip does each step\",\n\"  -so       show all available options on this system\",\n\"  -X        default=strip old extra fields, -X- keep old, -X strip most\",\n\"  -ws       wildcards don't span directory boundaries in paths\",\n\"\"\n  };\n\n  for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n  {\n    printf(text[i]);\n    putchar('\\n');\n  }\n#ifdef DOS\n  check_for_windows(\"Zip\");\n#endif\n}\n\n/*\n * XXX version_info() in a separate file\n */\nlocal void version_info()\n/* Print verbose info about program version and compile time options\n   to stdout. */\n{\n  extent i;             /* counter in text arrays */\n  char *envptr;\n\n  /* Bzip2 option string storage (with version). */\n\n#ifdef BZIP2_SUPPORT\n  static char bz_opt_ver[81];\n  static char bz_opt_ver2[81];\n  static char bz_opt_ver3[81];\n#endif\n\n  /* Options info array */\n  static ZCONST char *comp_opts[] = {\n#ifdef ASM_CRC\n    \"ASM_CRC\",\n#endif\n#ifdef ASMV\n    \"ASMV\",\n#endif\n#ifdef DYN_ALLOC\n    \"DYN_ALLOC\",\n#endif\n#ifdef MMAP\n    \"MMAP\",\n#endif\n#ifdef BIG_MEM\n    \"BIG_MEM\",\n#endif\n#ifdef MEDIUM_MEM\n    \"MEDIUM_MEM\",\n#endif\n#ifdef SMALL_MEM\n    \"SMALL_MEM\",\n#endif\n#ifdef DEBUG\n    \"DEBUG\",\n#endif\n#ifdef USE_EF_UT_TIME\n    \"USE_EF_UT_TIME       (store Universal Time)\",\n#endif\n#ifdef NTSD_EAS\n    \"NTSD_EAS             (store NT Security Descriptor)\",\n#endif\n#if defined(WIN32) && defined(NO_W32TIMES_IZFIX)\n    \"NO_W32TIMES_IZFIX\",\n#endif\n#ifdef VMS\n#ifdef VMSCLI\n    \"VMSCLI\",\n#endif\n#ifdef VMS_IM_EXTRA\n    \"VMS_IM_EXTRA\",\n#endif\n#ifdef VMS_PK_EXTRA\n    \"VMS_PK_EXTRA\",\n#endif\n#endif /* VMS */\n#ifdef WILD_STOP_AT_DIR\n    \"WILD_STOP_AT_DIR     (wildcards do not cross directory boundaries)\",\n#endif\n#ifdef WIN32_OEM\n    \"WIN32_OEM            (store file paths on Windows as OEM)\",\n#endif\n#ifdef BZIP2_SUPPORT\n    bz_opt_ver,\n    bz_opt_ver2,\n    bz_opt_ver3,\n#endif\n#ifdef S_IFLNK\n# ifdef VMS\n    \"SYMLINK_SUPPORT      (symbolic links supported, if C RTL permits)\",\n# else\n    \"SYMLINK_SUPPORT      (symbolic links supported)\",\n# endif\n#endif\n#ifdef LARGE_FILE_SUPPORT\n# ifdef USING_DEFAULT_LARGE_FILE_SUPPORT\n    \"LARGE_FILE_SUPPORT (default settings)\",\n# else\n    \"LARGE_FILE_SUPPORT   (can read and write large files on file system)\",\n# endif\n#endif\n#ifdef ZIP64_SUPPORT\n    \"ZIP64_SUPPORT        (use Zip64 to store large files in archives)\",\n#endif\n#ifdef UNICODE_SUPPORT\n    \"UNICODE_SUPPORT      (store and read UTF-8 Unicode paths)\",\n#endif\n\n#ifdef UNIX\n    \"STORE_UNIX_UIDs_GIDs (store UID/GID sizes/values using new extra field)\",\n# ifdef UIDGID_NOT_16BIT\n    \"UIDGID_NOT_16BIT     (old Unix 16-bit UID/GID extra field not used)\",\n# else\n    \"UIDGID_16BIT         (old Unix 16-bit UID/GID extra field also used)\",\n# endif\n#endif\n\n#if CRYPT && defined(PASSWD_FROM_STDIN)\n    \"PASSWD_FROM_STDIN\",\n#endif /* CRYPT & PASSWD_FROM_STDIN */\n    NULL\n  };\n\n  static ZCONST char *zipenv_names[] = {\n#ifndef VMS\n#  ifndef RISCOS\n    \"ZIP\"\n#  else /* RISCOS */\n    \"Zip$Options\"\n#  endif /* ?RISCOS */\n#else /* VMS */\n    \"ZIP_OPTS\"\n#endif /* ?VMS */\n    ,\"ZIPOPT\"\n#ifdef AZTEC_C\n    ,     /* extremely lame compiler bug workaround */\n#endif\n#ifndef __RSXNT__\n# ifdef __EMX__\n    ,\"EMX\"\n    ,\"EMXOPT\"\n# endif\n# if (defined(__GO32__) && (!defined(__DJGPP__) || __DJGPP__ < 2))\n    ,\"GO32\"\n    ,\"GO32TMP\"\n# endif\n# if (defined(__DJGPP__) && __DJGPP__ >= 2)\n    ,\"TMPDIR\"\n# endif\n#endif /* !__RSXNT__ */\n#ifdef RISCOS\n    ,\"Zip$Exts\"\n#endif\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)\n  {\n    printf(copyright[i], \"zip\");\n    putchar('\\n');\n  }\n\n  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)\n  {\n    printf(versinfolines[i], \"Zip\", VERSION, REVDATE);\n    putchar('\\n');\n  }\n\n  version_local();\n\n  puts(\"Zip special compilation options:\");\n#if WSIZE != 0x8000\n  printf(\"\\tWSIZE=%u\\n\", WSIZE);\n#endif\n\n  /* Fill in bzip2 version.  (32-char limit valid as of bzip 1.0.3.) */\n#ifdef BZIP2_SUPPORT\n  sprintf( bz_opt_ver,\n   \"BZIP2_SUPPORT        (bzip2 library version %.32s)\", BZ2_bzlibVersion());\n  sprintf( bz_opt_ver2,\n   \"    bzip2 code and library copyright (c) Julian R Seward\");\n  sprintf( bz_opt_ver3,\n   \"    (See the bzip2 license for terms of use)\");\n#endif\n\n  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)\n  {\n    printf(\"\\t%s\\n\",comp_opts[i]);\n  }\n#ifdef USE_ZLIB\n  if (strcmp(ZLIB_VERSION, zlibVersion()) == 0)\n    printf(\"\\tUSE_ZLIB [zlib version %s]\\n\", ZLIB_VERSION);\n  else\n    printf(\"\\tUSE_ZLIB [compiled with version %s, using version %s]\\n\",\n      ZLIB_VERSION, zlibVersion());\n  i++;  /* zlib use means there IS at least one compilation option */\n#endif\n#if CRYPT\n  printf(\"\\t[encryption, version %d.%d%s of %s] (modified for Zip 3)\\n\\n\",\n            CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);\n  for (i = 0; i < sizeof(cryptnote)/sizeof(char *); i++)\n  {\n    printf(cryptnote[i]);\n    putchar('\\n');\n  }\n  ++i;  /* crypt support means there IS at least one compilation option */\n#endif /* CRYPT */\n  if (i == 0)\n      puts(\"\\t[none]\");\n\n  puts(\"\\nZip environment options:\");\n  for (i = 0; i < sizeof(zipenv_names)/sizeof(char *); i++)\n  {\n    envptr = getenv(zipenv_names[i]);\n    printf(\"%16s:  %s\\n\", zipenv_names[i],\n           ((envptr == (char *)NULL || *envptr == 0) ? \"[none]\" : envptr));\n  }\n#ifdef DOS\n  check_for_windows(\"Zip\");\n#endif\n}\n#endif /* !WINDLL */\n\n\n#ifndef PROCNAME\n/* Default to case-sensitive matching of archive entries for the modes\n   that specifically operate on archive entries, as this archive may\n   have come from a system that allows paths in the archive to differ\n   only by case.  Except for adding ARCHIVE (copy mode), this is how it\n   was done before.  Note that some case-insensitive ports (WIN32, VMS)\n   define their own PROCNAME() in their respective osdep.h that use the\n   filter_match_case flag set to FALSE by the -ic option to enable\n   case-insensitive archive entry mathing. */\n#  define PROCNAME(n) procname(n, (action == ARCHIVE || action == DELETE \\\n                                   || action == FRESHEN) \\\n                                  && filter_match_case)\n#endif /* PROCNAME */\n\n#ifndef WINDLL\n#ifndef MACOS\nlocal void zipstdout()\n/* setup for writing zip file on stdout */\n{\n  mesg = stderr;\n  if (isatty(1))\n    ziperr(ZE_PARMS, \"cannot write zip file to terminal\");\n  if ((zipfile = malloc(4)) == NULL)\n    ziperr(ZE_MEM, \"was processing arguments\");\n  strcpy(zipfile, \"-\");\n  /*\n  if ((r = readzipfile()) != ZE_OK)\n    ziperr(r, zipfile);\n  */\n}\n#endif /* !MACOS */\n\nlocal int check_unzip_version(unzippath)\n  char *unzippath;\n{\n#ifdef ZIP64_SUPPORT\n  /* Here is where we need to check for the version of unzip the user\n   * has.  If creating a Zip64 archive need UnZip 6 or may fail.\n   */\n    char cmd[4004];\n    FILE *unzip_out = NULL;\n    char buf[1001];\n    float UnZip_Version = 0.0;\n\n    cmd[0] = '\\0';\n    strncat(cmd, unzippath, 4000);\n    strcat(cmd, \" -v\");\n\n    if ((unzip_out = popen(cmd, \"r\")) == NULL) {\n      perror(\"unzip pipe error\");\n    } else {\n      if (fgets(buf, 1000, unzip_out) == NULL) {\n        zipwarn(\"failed to get information from UnZip\", \"\");\n      } else {\n        /* the first line should start with the version */\n        if (sscanf(buf, \"UnZip %f \", &UnZip_Version) < 1) {\n          zipwarn(\"unexpected output of UnZip -v\", \"\");\n        } else {\n          /* printf(\"UnZip %f\\n\", UnZip_Version); */\n\n          while (fgets(buf, 1000, unzip_out)) {\n          }\n        }\n      }\n      pclose(unzip_out);\n    }\n    if (UnZip_Version < 6.0 && zip64_archive) {\n      sprintf(buf, \"Found UnZip version %4.2f\", UnZip_Version);\n      zipwarn(buf, \"\");\n      zipwarn(\"Need UnZip 6.00 or later to test this Zip64 archive\", \"\");\n      return 0;\n    }\n#endif\n  return 1;\n}\n\nlocal void check_zipfile(zipname, zippath)\n  char *zipname;\n  char *zippath;\n  /* Invoke unzip -t on the given zip file */\n{\n#if (defined(MSDOS) && !defined(__GO32__)) || defined(__human68k__)\n  int status, len;\n  char *path, *p;\n  char *zipnam;\n\n  if ((zipnam = (char *)malloc(strlen(zipname) + 3)) == NULL)\n    ziperr(ZE_MEM, \"was creating unzip zipnam\");\n\n# ifdef MSDOS\n  /* Add quotes for MSDOS.  8/11/04 */\n  strcpy(zipnam, \"\\\"\");    /* accept spaces in name and path */\n  strcat(zipnam, zipname);\n  strcat(zipnam, \"\\\"\");\n# else\n  strcpy(zipnam, zipname);\n# endif\n\n  if (unzip_path) {\n    /* if user gave us the unzip to use go with it */\n    char *here;\n    int len;\n    char *cmd;\n\n    /* Replace first {} with archive name.  If no {} append name to string. */\n    here = strstr(unzip_path, \"{}\");\n\n    if ((cmd = (char *)malloc(strlen(unzip_path) + strlen(zipnam) + 3)) == NULL)\n      ziperr(ZE_MEM, \"was creating unzip cmd\");\n\n    if (here) {\n      /* have {} so replace with temp name */\n      len = here - unzip_path;\n      strcpy(cmd, unzip_path);\n      cmd[len] = '\\0';\n      strcat(cmd, \" \");\n      strcat(cmd, zipnam);\n      strcat(cmd, \" \");\n      strcat(cmd, here + 2);\n    } else {\n      /* No {} so append temp name to end */\n      strcpy(cmd, unzip_path);\n      strcat(cmd, \" \");\n      strcat(cmd, zipnam);\n    }\n\n    status = system(cmd);\n\n    free(unzip_path);\n    unzip_path = NULL;\n    free(cmd);\n  } else {\n    /* Here is where we need to check for the version of unzip the user\n     * has.  If creating a Zip64 archive need UnZip 6 or may fail.\n     */\n    if (check_unzip_version(\"unzip\") == 0)\n      ZIPERR(ZE_TEST, zipfile);\n\n    status = spawnlp(P_WAIT, \"unzip\", \"unzip\", verbose ? \"-t\" : \"-tqq\",\n                     zipnam, NULL);\n# ifdef __human68k__\n    if (status == -1)\n      perror(\"unzip\");\n# else\n/*\n * unzip isn't in PATH range, assume an absolute path to zip in argv[0]\n * and hope that unzip is in the same directory.\n */\n    if (status == -1) {\n      p = MBSRCHR(zippath, '\\\\');\n      path = MBSRCHR((p == NULL ? zippath : p), '/');\n      if (path != NULL)\n        p = path;\n      if (p != NULL) {\n        len = (int)(p - zippath) + 1;\n        if ((path = malloc(len + sizeof(\"unzip.exe\"))) == NULL)\n          ziperr(ZE_MEM, \"was creating unzip path\");\n        memcpy(path, zippath, len);\n        strcpy(&path[len], \"unzip.exe\");\n\n        if (check_unzip_version(path) == 0)\n          ZIPERR(ZE_TEST, zipfile);\n\n        status = spawnlp(P_WAIT, path, \"unzip\", verbose ? \"-t\" : \"-tqq\",\n                        zipnam, NULL);\n        free(path);\n      }\n      if (status == -1)\n        perror(\"unzip\");\n    }\n  }\n# endif /* ?__human68k__ */\n  free(zipnam);\n  if (status != 0) {\n\n#else /* (MSDOS && !__GO32__) || __human68k__ */\n  char *cmd;\n  int result;\n\n  /* Tell picky compilers to shut up about unused variables */\n  zippath = zippath;\n\n  if (unzip_path) {\n    /* user gave us a path to some unzip (may not be UnZip) */\n    char *here;\n    int len;\n\n    /* Replace first {} with archive name.  If no {} append name to string. */\n    here = strstr(unzip_path, \"{}\");\n\n    if ((cmd = malloc(strlen(unzip_path) + strlen(zipname) + 3)) == NULL) {\n      ziperr(ZE_MEM, \"building command string for testing archive\");\n    }\n\n    if (here) {\n      /* have {} so replace with temp name */\n      len = here - unzip_path;\n      strcpy(cmd, unzip_path);\n      cmd[len] = '\\0';\n      strcat(cmd, \" \");\n# ifdef UNIX\n      strcat(cmd, \"'\");    /* accept space or $ in name */\n      strcat(cmd, zipname);\n      strcat(cmd, \"'\");\n# else\n      strcat(cmd, zipname);\n# endif\n      strcat(cmd, \" \");\n      strcat(cmd, here + 2);\n    } else {\n      /* No {} so append temp name to end */\n      strcpy(cmd, unzip_path);\n      strcat(cmd, \" \");\n# ifdef UNIX\n      strcat(cmd, \"'\");    /* accept space or $ in name */\n      strcat(cmd, zipname);\n      strcat(cmd, \"'\");\n# else\n      strcat(cmd, zipname);\n# endif\n    }\n    free(unzip_path);\n    unzip_path = NULL;\n\n  } else {\n    if ((cmd = malloc(20 + strlen(zipname))) == NULL) {\n      ziperr(ZE_MEM, \"building command string for testing archive\");\n    }\n\n    strcpy(cmd, \"unzip -t \");\n# ifdef QDOS\n    strcat(cmd, \"-Q4 \");\n# endif\n    if (!verbose) strcat(cmd, \"-qq \");\n    if (check_unzip_version(\"unzip\") == 0)\n      ZIPERR(ZE_TEST, zipfile);\n\n# ifdef UNIX\n    strcat(cmd, \"'\");    /* accept space or $ in name */\n    strcat(cmd, zipname);\n    strcat(cmd, \"'\");\n# else\n    strcat(cmd, zipname);\n# endif\n  }\n\n  result = system(cmd);\n# ifdef VMS\n  /* Convert success severity to 0, others to non-zero. */\n  result = ((result & STS$M_SEVERITY) != STS$M_SUCCESS);\n# endif /* def VMS */\n  free(cmd);\n  cmd = NULL;\n  if (result) {\n#endif /* ?((MSDOS && !__GO32__) || __human68k__) */\n\n    fprintf(mesg, \"test of %s FAILED\\n\", zipfile);\n    ziperr(ZE_TEST, \"original files unmodified\");\n  }\n  if (noisy) {\n    fprintf(mesg, \"test of %s OK\\n\", zipfile);\n    fflush(mesg);\n  }\n  if (logfile) {\n    fprintf(logfile, \"test of %s OK\\n\", zipfile);\n    fflush(logfile);\n  }\n}\n#endif /* !WINDLL */\n\n/* get_filters() is replaced by the following\nlocal int get_filters(argc, argv)\n*/\n\n/* The filter patterns for options -x, -i, and -R are\n   returned by get_option() one at a time, so use a linked\n   list to store until all args are processed.  Then convert\n   to array for processing.\n */\n\n/* add a filter to the linked list */\nlocal int add_filter(flag, pattern)\n  int flag;\n  char *pattern;\n{\n  char *iname, *p = NULL;\n  FILE *fp;\n  struct filterlist_struct *filter = NULL;\n\n  /* should never happen */\n  if (flag != 'R' && flag != 'x' && flag != 'i') {\n    ZIPERR(ZE_LOGIC, \"bad flag to add_filter\");\n  }\n  if (pattern == NULL) {\n    ZIPERR(ZE_LOGIC, \"null pattern to add_filter\");\n  }\n\n  if (pattern[0] == '@') {\n    /* read file with 1 pattern per line */\n    if (pattern[1] == '\\0') {\n      ZIPERR(ZE_PARMS, \"missing file after @\");\n    }\n    fp = fopen(pattern + 1, \"r\");\n    if (fp == NULL) {\n      sprintf(errbuf, \"%c pattern file '%s'\", flag, pattern);\n      ZIPERR(ZE_OPEN, errbuf);\n    }\n    while ((p = getnam(fp)) != NULL) {\n      if ((filter = (struct filterlist_struct *) malloc(sizeof(struct filterlist_struct))) == NULL) {\n        ZIPERR(ZE_MEM, \"adding filter\");\n      }\n      if (filterlist == NULL) {\n        /* first filter */\n        filterlist = filter;         /* start of list */\n        lastfilter = filter;\n      } else {\n        lastfilter->next = filter;   /* link to last filter in list */\n        lastfilter = filter;\n      }\n      iname = ex2in(p, 0, (int *)NULL);\n      free(p);\n      if (iname != NULL) {\n        lastfilter->pattern = in2ex(iname);\n        free(iname);\n      } else {\n        lastfilter->pattern = NULL;\n      }\n      lastfilter->flag = flag;\n      pcount++;\n      lastfilter->next = NULL;\n    }\n    fclose(fp);\n  } else {\n    /* single pattern */\n    if ((filter = (struct filterlist_struct *) malloc(sizeof(struct filterlist_struct))) == NULL) {\n      ZIPERR(ZE_MEM, \"adding filter\");\n    }\n    if (filterlist == NULL) {\n      /* first pattern */\n      filterlist = filter;         /* start of list */\n      lastfilter = filter;\n    } else {\n      lastfilter->next = filter;   /* link to last filter in list */\n      lastfilter = filter;\n    }\n    iname = ex2in(pattern, 0, (int *)NULL);\n    if (iname != NULL) {\n       lastfilter->pattern = in2ex(iname);\n       free(iname);\n    } else {\n      lastfilter->pattern = NULL;\n    }\n    lastfilter->flag = flag;\n    pcount++;\n    lastfilter->next = NULL;\n  }\n\n  return pcount;\n}\n\n/* convert list to patterns array */\nlocal int filterlist_to_patterns()\n{\n  unsigned i;\n  struct filterlist_struct *next = NULL;\n\n  if (pcount == 0) {\n    patterns = NULL;\n    return 0;\n  }\n  if ((patterns = (struct plist *) malloc((pcount + 1) * sizeof(struct plist)))\n      == NULL) {\n    ZIPERR(ZE_MEM, \"was creating pattern list\");\n  }\n\n  for (i = 0; i < pcount && filterlist != NULL; i++) {\n    switch (filterlist->flag) {\n      case 'i':\n        icount++;\n        break;\n      case 'R':\n        Rcount++;\n        break;\n    }\n    patterns[i].select = filterlist->flag;\n    patterns[i].zname = filterlist->pattern;\n    next = filterlist->next;\n    free(filterlist);\n    filterlist = next;\n  }\n\n  return pcount;\n}\n\n\n/* add a file argument to linked list */\nlocal long add_name(filearg)\n  char *filearg;\n{\n  char *name = NULL;\n  struct filelist_struct *fileentry = NULL;\n\n  if ((fileentry = (struct filelist_struct *) malloc(sizeof(struct filelist_struct))) == NULL) {\n    ZIPERR(ZE_MEM, \"adding file\");\n  }\n  if ((name = malloc(strlen(filearg) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"adding file\");\n  }\n  strcpy(name, filearg);\n  fileentry->next = NULL;\n  fileentry->name = name;\n  if (filelist == NULL) {\n    /* first file argument */\n    filelist = fileentry;         /* start of list */\n    lastfile = fileentry;\n  } else {\n    lastfile->next = fileentry;   /* link to last filter in list */\n    lastfile = fileentry;\n  }\n  filearg_count++;\n\n  return filearg_count;\n}\n\n\n/* Running Stats\n   10/30/04 */\n\nlocal int DisplayRunningStats()\n{\n  char tempstrg[100];\n\n  if (mesg_line_started) {\n    fprintf(mesg, \"\\n\");\n    mesg_line_started = 0;\n  }\n  if (logfile_line_started) {\n    fprintf(logfile, \"\\n\");\n    logfile_line_started = 0;\n  }\n  if (display_volume) {\n    if (noisy) {\n      fprintf(mesg, \"%lu>%lu: \", current_in_disk + 1, current_disk + 1);\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"%lu>%lu: \", current_in_disk + 1, current_disk + 1);\n      logfile_line_started = 1;\n    }\n  }\n  if (display_counts) {\n    if (noisy) {\n      fprintf(mesg, \"%3ld/%3ld \", files_so_far, files_total - files_so_far);\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"%3ld/%3ld \", files_so_far, files_total - files_so_far);\n      logfile_line_started = 1;\n    }\n  }\n  if (display_bytes) {\n    /* since file sizes can change as we go, use bytes_so_far from\n       initial scan so all adds up */\n    WriteNumString(bytes_so_far, tempstrg);\n    if (noisy) {\n      fprintf(mesg, \"[%4s\", tempstrg);\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"[%4s\", tempstrg);\n      logfile_line_started = 1;\n    }\n    if (bytes_total >= bytes_so_far) {\n      WriteNumString(bytes_total - bytes_so_far, tempstrg);\n      if (noisy)\n        fprintf(mesg, \"/%4s] \", tempstrg);\n      if (logall)\n        fprintf(logfile, \"/%4s] \", tempstrg);\n    } else {\n      WriteNumString(bytes_so_far - bytes_total, tempstrg);\n      if (noisy)\n        fprintf(mesg, \"-%4s] \", tempstrg);\n      if (logall)\n        fprintf(logfile, \"-%4s] \", tempstrg);\n    }\n  }\n  if (noisy)\n      fflush(mesg);\n  if (logall)\n      fflush(logfile);\n\n  return 0;\n}\n\nlocal int BlankRunningStats()\n{\n  if (display_volume) {\n    if (noisy) {\n      fprintf(mesg, \"%lu>%lu: \", current_in_disk + 1, current_disk + 1);\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"%lu>%lu: \", current_in_disk + 1, current_disk + 1);\n      logfile_line_started = 1;\n    }\n  }\n  if (display_counts) {\n    if (noisy) {\n      fprintf(mesg, \"   /    \");\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"   /    \");\n      logfile_line_started = 1;\n    }\n  }\n  if (display_bytes) {\n    if (noisy) {\n      fprintf(mesg, \"     /      \");\n      mesg_line_started = 1;\n    }\n    if (logall) {\n      fprintf(logfile, \"     /      \");\n      logfile_line_started = 1;\n    }\n  }\n  if (noisy)\n      fflush(mesg);\n  if (logall)\n      fflush(logfile);\n\n  return 0;\n}\n\n#if CRYPT\n#ifndef WINDLL\nint encr_passwd(modeflag, pwbuf, size, zfn)\nint modeflag;\nchar *pwbuf;\nint size;\nZCONST char *zfn;\n{\n    char *prompt;\n\n    /* Tell picky compilers to shut up about unused variables */\n    zfn = zfn;\n\n    prompt = (modeflag == ZP_PW_VERIFY) ?\n              \"Verify password: \" : \"Enter password: \";\n\n    if (getp(prompt, pwbuf, size) == NULL) {\n      ziperr(ZE_PARMS, \"stderr is not a tty\");\n    }\n    return IZ_PW_ENTERED;\n}\n#endif /* !WINDLL */\n#else /* !CRYPT */\nint encr_passwd(modeflag, pwbuf, size, zfn)\nint modeflag;\nchar *pwbuf;\nint size;\nZCONST char *zfn;\n{\n    /* Tell picky compilers to shut up about unused variables */\n    modeflag = modeflag; pwbuf = pwbuf; size = size; zfn = zfn;\n\n    return ZE_LOGIC;    /* This function should never be called! */\n}\n#endif /* CRYPT */\n\n\n/* rename a split\n * A split has a tempfile name until it is closed, then\n * here rename it as out_path the final name for the split.\n */\nint rename_split(temp_name, out_path)\n  char *temp_name;\n  char *out_path;\n{\n  int r;\n  /* Replace old zip file with new zip file, leaving only the new one */\n  if ((r = replace(out_path, temp_name)) != ZE_OK)\n  {\n    zipwarn(\"new zip file left as: \", temp_name);\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    ZIPERR(r, \"was replacing split file\");\n  }\n  if (zip_attributes) {\n    setfileattr(out_path, zip_attributes);\n  }\n  return ZE_OK;\n}\n\n\nint set_filetype(out_path)\n  char *out_path;\n{\n#ifdef __BEOS__\n  /* Set the filetype of the zipfile to \"application/zip\" */\n  setfiletype( out_path, \"application/zip\" );\n#endif\n\n#ifdef __ATHEOS__\n  /* Set the filetype of the zipfile to \"application/x-zip\" */\n  setfiletype(out_path, \"application/x-zip\");\n#endif\n\n#ifdef MACOS\n  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */\n  setfiletype(out_path, 'IZip', 'ZIP ');\n#endif\n\n#ifdef RISCOS\n  /* Set the filetype of the zipfile to &DDC */\n  setfiletype(out_path, 0xDDC);\n#endif\n  return ZE_OK;\n}\n\n\n/*\n  -------------------------------------------------------\n  Command Line Options\n  -------------------------------------------------------\n\n  Valid command line options.\n\n  The function get_option() uses this table to check if an\n  option is valid and if it takes a value (also called an\n  option argument).  To add an option to zip just add it\n  to this table and add a case in the main switch to handle\n  it.  If either shortopt or longopt not used set to \"\".\n\n   The fields:\n       shortopt     - short option name (1 or 2 chars)\n       longopt      - long option name\n       value_type   - see zip.h for constants\n       negatable    - option is negatable with trailing -\n       ID           - unsigned long int returned for option\n       name         - short description of option which is\n                        returned on some errors and when options\n                        are listed with -so option, can be NULL\n*/\n\n/* Most option IDs are set to the shortopt char.  For\n   multichar short options set to arbitrary unused constant. */\n#define o_AC            0x101\n#define o_AS            0x102\n#define o_C2            0x103\n#define o_C5            0x104\n#define o_db            0x105\n#define o_dc            0x106\n#define o_dd            0x107\n#define o_des           0x108\n#define o_df            0x109\n#define o_DF            0x110\n#define o_dg            0x111\n#define o_ds            0x112\n#define o_du            0x113\n#define o_dv            0x114\n#define o_FF            0x115\n#define o_FI            0x116\n#define o_FS            0x117\n#define o_h2            0x118\n#define o_ic            0x119\n#define o_jj            0x120\n#define o_la            0x121\n#define o_lf            0x122\n#define o_li            0x123\n#define o_ll            0x124\n#define o_mm            0x125\n#define o_MM            0x126\n#define o_nw            0x127\n#define o_RE            0x128\n#define o_sb            0x129\n#define o_sc            0x130\n#define o_sd            0x131\n#define o_sf            0x132\n#define o_so            0x133\n#define o_sp            0x134\n#define o_su            0x135\n#define o_sU            0x136\n#define o_sv            0x137\n#define o_tt            0x138\n#define o_TT            0x139\n#define o_UN            0x140\n#define o_ve            0x141\n#define o_VV            0x142\n#define o_ws            0x143\n#define o_ww            0x144\n#define o_z64           0x145\n#ifdef UNICODE_TEST\n#define o_sC            0x146\n#endif\n\n\n/* the below is mainly from the old main command line\n   switch with a few changes */\nstruct option_struct far options[] = {\n  /* short longopt        value_type        negatable        ID    name */\n#ifdef EBCDIC\n    {\"a\",  \"ascii\",       o_NO_VALUE,       o_NOT_NEGATABLE, 'a',  \"to ascii\"},\n#endif /* EBCDIC */\n#ifdef CMS_MVS\n    {\"B\",  \"binary\",      o_NO_VALUE,       o_NOT_NEGATABLE, 'B',  \"binary\"},\n#endif /* CMS_MVS */\n#ifdef TANDEM\n    {\"B\",  \"\",            o_NUMBER_VALUE,   o_NOT_NEGATABLE, 'B',  \"nsk\"},\n#endif\n    {\"0\",  \"store\",       o_NO_VALUE,       o_NOT_NEGATABLE, '0',  \"store\"},\n    {\"1\",  \"compress-1\",  o_NO_VALUE,       o_NOT_NEGATABLE, '1',  \"compress 1\"},\n    {\"2\",  \"compress-2\",  o_NO_VALUE,       o_NOT_NEGATABLE, '2',  \"compress 2\"},\n    {\"3\",  \"compress-3\",  o_NO_VALUE,       o_NOT_NEGATABLE, '3',  \"compress 3\"},\n    {\"4\",  \"compress-4\",  o_NO_VALUE,       o_NOT_NEGATABLE, '4',  \"compress 4\"},\n    {\"5\",  \"compress-5\",  o_NO_VALUE,       o_NOT_NEGATABLE, '5',  \"compress 5\"},\n    {\"6\",  \"compress-6\",  o_NO_VALUE,       o_NOT_NEGATABLE, '6',  \"compress 6\"},\n    {\"7\",  \"compress-7\",  o_NO_VALUE,       o_NOT_NEGATABLE, '7',  \"compress 7\"},\n    {\"8\",  \"compress-8\",  o_NO_VALUE,       o_NOT_NEGATABLE, '8',  \"compress 8\"},\n    {\"9\",  \"compress-9\",  o_NO_VALUE,       o_NOT_NEGATABLE, '9',  \"compress 9\"},\n    {\"A\",  \"adjust-sfx\",  o_NO_VALUE,       o_NOT_NEGATABLE, 'A',  \"adjust self extractor offsets\"},\n#if defined(WIN32)\n    {\"AC\", \"archive-clear\", o_NO_VALUE,     o_NOT_NEGATABLE, o_AC, \"clear DOS archive bit of included files\"},\n    {\"AS\", \"archive-set\", o_NO_VALUE,       o_NOT_NEGATABLE, o_AS, \"include only files with archive bit set\"},\n#endif\n    {\"b\",  \"temp-path\",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'b',  \"dir to use for temp archive\"},\n    {\"c\",  \"entry-comments\", o_NO_VALUE,    o_NOT_NEGATABLE, 'c',  \"add comments for each entry\"},\n#ifdef VMS\n    {\"C\",  \"preserve-case\", o_NO_VALUE,     o_NEGATABLE,     'C',  \"Preserve (C-: down-) case all on VMS\"},\n    {\"C2\", \"preserve-case-2\", o_NO_VALUE,   o_NEGATABLE,     o_C2, \"Preserve (C2-: down-) case ODS2 on VMS\"},\n    {\"C5\", \"preserve-case-5\", o_NO_VALUE,   o_NEGATABLE,     o_C5, \"Preserve (C5-: down-) case ODS5 on VMS\"},\n#endif /* VMS */\n    {\"d\",  \"delete\",      o_NO_VALUE,       o_NOT_NEGATABLE, 'd',  \"delete entries from archive\"},\n    {\"db\", \"display-bytes\", o_NO_VALUE,     o_NEGATABLE,     o_db, \"display running bytes\"},\n    {\"dc\", \"display-counts\", o_NO_VALUE,    o_NEGATABLE,     o_dc, \"display running file count\"},\n    {\"dd\", \"display-dots\", o_NO_VALUE,      o_NEGATABLE,     o_dd, \"display dots as process each file\"},\n    {\"dg\", \"display-globaldots\",o_NO_VALUE, o_NEGATABLE,     o_dg, \"display dots for archive instead of files\"},\n    {\"ds\", \"dot-size\",     o_REQUIRED_VALUE, o_NOT_NEGATABLE, o_ds, \"set progress dot size - default 10M bytes\"},\n    {\"du\", \"display-usize\", o_NO_VALUE,     o_NEGATABLE,     o_du, \"display uncompressed size in bytes\"},\n    {\"dv\", \"display-volume\", o_NO_VALUE,    o_NEGATABLE,     o_dv, \"display volume (disk) number\"},\n#ifdef MACOS\n    {\"df\", \"datafork\",    o_NO_VALUE,       o_NOT_NEGATABLE, o_df, \"save datafork\"},\n#endif /* MACOS */\n    {\"D\",  \"no-dir-entries\", o_NO_VALUE,    o_NOT_NEGATABLE, 'D',  \"no entries for dirs themselves (-x */)\"},\n    {\"DF\", \"difference-archive\",o_NO_VALUE, o_NOT_NEGATABLE, o_DF, \"create diff archive with changed/new files\"},\n    {\"e\",  \"encrypt\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'e',  \"encrypt entries, ask for password\"},\n#ifdef OS2\n    {\"E\",  \"longnames\",   o_NO_VALUE,       o_NOT_NEGATABLE, 'E',  \"use OS2 longnames\"},\n#endif\n    {\"F\",  \"fix\",         o_NO_VALUE,       o_NOT_NEGATABLE, 'F',  \"fix mostly intact archive (try first)\"},\n    {\"FF\", \"fixfix\",      o_NO_VALUE,       o_NOT_NEGATABLE, o_FF, \"try harder to fix archive (not as reliable)\"},\n    {\"FI\", \"fifo\",        o_NO_VALUE,       o_NEGATABLE,     o_FI, \"read Unix FIFO (zip will wait on open pipe)\"},\n    {\"FS\", \"filesync\",    o_NO_VALUE,       o_NOT_NEGATABLE, o_FS, \"add/delete entries to make archive match OS\"},\n    {\"f\",  \"freshen\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'f',  \"freshen existing archive entries\"},\n    {\"fd\", \"force-descriptors\", o_NO_VALUE, o_NOT_NEGATABLE, o_des,\"force data descriptors as if streaming\"},\n#ifdef ZIP64_SUPPORT\n    {\"fz\", \"force-zip64\", o_NO_VALUE,       o_NEGATABLE,     o_z64,\"force use of Zip64 format, negate prevents\"},\n#endif\n    {\"g\",  \"grow\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'g',  \"grow existing archive instead of replace\"},\n#ifndef WINDLL\n    {\"h\",  \"help\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    {\"H\",  \"\",            o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    {\"?\",  \"\",            o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    {\"h2\", \"more-help\",   o_NO_VALUE,       o_NOT_NEGATABLE, o_h2, \"extended help\"},\n#endif /* !WINDLL */\n    {\"i\",  \"include\",     o_VALUE_LIST,     o_NOT_NEGATABLE, 'i',  \"include only files matching patterns\"},\n#if defined(VMS) || defined(WIN32)\n    {\"ic\", \"ignore-case\", o_NO_VALUE,       o_NEGATABLE,     o_ic, \"ignore case when matching archive entries\"},\n#endif\n#ifdef RISCOS\n    {\"I\",  \"no-image\",    o_NO_VALUE,       o_NOT_NEGATABLE, 'I',  \"no image\"},\n#endif\n    {\"j\",  \"junk-paths\",  o_NO_VALUE,       o_NOT_NEGATABLE, 'j',  \"strip paths and just store file names\"},\n#ifdef MACOS\n    {\"jj\", \"absolute-path\", o_NO_VALUE,     o_NOT_NEGATABLE, o_jj, \"MAC absolute path\"},\n#endif /* ?MACOS */\n    {\"J\",  \"junk-sfx\",    o_NO_VALUE,       o_NOT_NEGATABLE, 'J',  \"strip self extractor from archive\"},\n    {\"k\",  \"DOS-names\",   o_NO_VALUE,       o_NOT_NEGATABLE, 'k',  \"force use of 8.3 DOS names\"},\n    {\"l\",  \"to-crlf\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'l',  \"convert text file line ends - LF->CRLF\"},\n    {\"ll\", \"from-crlf\",   o_NO_VALUE,       o_NOT_NEGATABLE, o_ll, \"convert text file line ends - CRLF->LF\"},\n    {\"lf\", \"logfile-path\",o_REQUIRED_VALUE, o_NOT_NEGATABLE, o_lf, \"log to log file at path (default overwrite)\"},\n    {\"la\", \"log-append\",  o_NO_VALUE,       o_NEGATABLE,     o_la, \"append to existing log file\"},\n    {\"li\", \"log-info\",    o_NO_VALUE,       o_NEGATABLE,     o_li, \"include informational messages in log\"},\n#ifndef WINDLL\n    {\"L\",  \"license\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'L',  \"display license\"},\n#endif\n    {\"m\",  \"move\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'm',  \"add files to archive then delete files\"},\n    {\"mm\", \"\",            o_NO_VALUE,       o_NOT_NEGATABLE, o_mm, \"not used\"},\n    {\"MM\", \"must-match\",  o_NO_VALUE,       o_NOT_NEGATABLE, o_MM, \"error if in file not matched/not readable\"},\n    {\"n\",  \"suffixes\",    o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'n',  \"suffixes to not compress: .gz:.zip\"},\n    {\"nw\", \"no-wild\",     o_NO_VALUE,       o_NOT_NEGATABLE, o_nw, \"no wildcards during add or update\"},\n#if defined(AMIGA) || defined(MACOS)\n    {\"N\",  \"notes\",       o_NO_VALUE,       o_NOT_NEGATABLE, 'N',  \"add notes as entry comments\"},\n#endif\n    {\"o\",  \"latest-time\", o_NO_VALUE,       o_NOT_NEGATABLE, 'o',  \"use latest entry time as archive time\"},\n    {\"O\",  \"output-file\", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'O',  \"set out zipfile different than in zipfile\"},\n    {\"p\",  \"paths\",       o_NO_VALUE,       o_NOT_NEGATABLE, 'p',  \"store paths\"},\n    {\"P\",  \"password\",    o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'P',  \"encrypt entries, option value is password\"},\n#if defined(QDOS) || defined(QLZIP)\n    {\"Q\",  \"Q-flag\",      o_NUMBER_VALUE,   o_NOT_NEGATABLE, 'Q',  \"Q flag\"},\n#endif\n    {\"q\",  \"quiet\",       o_NO_VALUE,       o_NOT_NEGATABLE, 'q',  \"quiet\"},\n    {\"r\",  \"recurse-paths\", o_NO_VALUE,     o_NOT_NEGATABLE, 'r',  \"recurse down listed paths\"},\n    {\"R\",  \"recurse-patterns\", o_NO_VALUE,  o_NOT_NEGATABLE, 'R',  \"recurse current dir and match patterns\"},\n    {\"RE\", \"regex\",       o_NO_VALUE,       o_NOT_NEGATABLE, o_RE, \"allow [list] matching (regex)\"},\n    {\"s\",  \"split-size\",  o_REQUIRED_VALUE, o_NOT_NEGATABLE, 's',  \"do splits, set split size (-s=0 no splits)\"},\n    {\"sp\", \"split-pause\", o_NO_VALUE,       o_NOT_NEGATABLE, o_sp, \"pause while splitting to select destination\"},\n    {\"sv\", \"split-verbose\", o_NO_VALUE,     o_NOT_NEGATABLE, o_sv, \"be verbose about creating splits\"},\n    {\"sb\", \"split-bell\",  o_NO_VALUE,       o_NOT_NEGATABLE, o_sb, \"when pause for next split ring bell\"},\n    {\"sc\", \"show-command\",o_NO_VALUE,       o_NOT_NEGATABLE, o_sc, \"show command line\"},\n#ifdef UNICODE_TEST\n    {\"sC\", \"create-files\",o_NO_VALUE,       o_NOT_NEGATABLE, o_sC, \"create empty files using archive names\"},\n#endif\n    {\"sd\", \"show-debug\",  o_NO_VALUE,       o_NOT_NEGATABLE, o_sd, \"show debug\"},\n    {\"sf\", \"show-files\",  o_NO_VALUE,       o_NEGATABLE,     o_sf, \"show files to operate on and exit\"},\n    {\"so\", \"show-options\",o_NO_VALUE,       o_NOT_NEGATABLE, o_so, \"show options\"},\n#ifdef UNICODE_SUPPORT\n    {\"su\", \"show-unicode\", o_NO_VALUE,      o_NEGATABLE,     o_su, \"as -sf but also show escaped Unicode\"},\n    {\"sU\", \"show-just-unicode\", o_NO_VALUE, o_NEGATABLE,     o_sU, \"as -sf but only show escaped Unicode\"},\n#endif\n#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(ATARI)\n    {\"S\",  \"\",            o_NO_VALUE,       o_NOT_NEGATABLE, 'S',  \"include system and hidden\"},\n#endif /* MSDOS || OS2 || WIN32 || ATARI */\n    {\"t\",  \"from-date\",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 't',  \"exclude before date\"},\n    {\"tt\", \"before-date\", o_REQUIRED_VALUE, o_NOT_NEGATABLE, o_tt, \"include before date\"},\n    {\"T\",  \"test\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'T',  \"test updates before replacing archive\"},\n    {\"TT\", \"unzip-command\", o_REQUIRED_VALUE,o_NOT_NEGATABLE,o_TT, \"unzip command to use, name is added to end\"},\n    {\"u\",  \"update\",      o_NO_VALUE,       o_NOT_NEGATABLE, 'u',  \"update existing entries and add new\"},\n    {\"U\",  \"copy-entries\", o_NO_VALUE,      o_NOT_NEGATABLE, 'U',  \"select from archive instead of file system\"},\n#ifdef UNICODE_SUPPORT\n    {\"UN\", \"unicode\",     o_REQUIRED_VALUE, o_NOT_NEGATABLE, o_UN, \"UN=quit, warn, ignore, no, escape\"},\n#endif\n    {\"v\",  \"verbose\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'v',  \"display additional information\"},\n    {\"\",   \"version\",     o_NO_VALUE,       o_NOT_NEGATABLE, o_ve, \"(if no other args) show version information\"},\n#ifdef VMS\n    {\"V\",  \"VMS-portable\", o_NO_VALUE,      o_NOT_NEGATABLE, 'V',  \"Store VMS attributes, portable file format\"},\n    {\"VV\", \"VMS-specific\", o_NO_VALUE,      o_NOT_NEGATABLE, o_VV, \"Store VMS attributes, VMS specific format\"},\n    {\"w\",  \"VMS-versions\", o_NO_VALUE,      o_NOT_NEGATABLE, 'w',  \"store VMS versions\"},\n    {\"ww\", \"VMS-dot-versions\", o_NO_VALUE,  o_NOT_NEGATABLE, o_ww, \"store VMS versions as \\\".nnn\\\"\"},\n#endif /* VMS */\n    {\"ws\", \"wild-stop-dirs\", o_NO_VALUE,    o_NOT_NEGATABLE, o_ws,  \"* stops at /, ** includes any /\"},\n    {\"x\",  \"exclude\",     o_VALUE_LIST,     o_NOT_NEGATABLE, 'x',  \"exclude files matching patterns\"},\n/*    {\"X\",  \"no-extra\",    o_NO_VALUE,       o_NOT_NEGATABLE, 'X',  \"no extra\"},\n*/\n    {\"X\",  \"strip-extra\", o_NO_VALUE,       o_NEGATABLE,     'X',  \"-X- keep all ef, -X strip but critical ef\"},\n#ifdef S_IFLNK\n    {\"y\",  \"symlinks\",    o_NO_VALUE,       o_NOT_NEGATABLE, 'y',  \"store symbolic links\"},\n#endif /* S_IFLNK */\n    {\"z\",  \"archive-comment\", o_NO_VALUE,   o_NOT_NEGATABLE, 'z',  \"ask for archive comment\"},\n    {\"Z\",  \"compression-method\", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'Z', \"compression method\"},\n#if defined(MSDOS) || defined(OS2)\n    {\"$\",  \"volume-label\", o_NO_VALUE,      o_NOT_NEGATABLE, '$',  \"store volume label\"},\n#endif\n#ifndef MACOS\n    {\"@\",  \"names-stdin\", o_NO_VALUE,       o_NOT_NEGATABLE, '@',  \"get file names from stdin, one per line\"},\n#endif /* !MACOS */\n#ifdef NTSD_EAS\n    {\"!\",  \"use-privileges\", o_NO_VALUE,    o_NOT_NEGATABLE, '!',  \"use privileges\"},\n#endif\n#ifdef RISCOS\n    {\"/\",  \"exts-to-swap\", o_REQUIRED_VALUE, o_NOT_NEGATABLE, '/',  \"override Zip$Exts\"},\n#endif\n    /* the end of the list */\n    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */\n  };\n\n\n\n#ifndef USE_ZIPMAIN\nint main(argc, argv)\n#else\nint zipmain(argc, argv)\n#endif\nint argc;               /* number of tokens in command line */\nchar **argv;            /* command line tokens */\n/* Add, update, freshen, or delete zip entries in a zip file.  See the\n   command help in help() above. */\n{\n  int d;                /* true if just adding to a zip file */\n  char *e;              /* malloc'd comment buffer */\n  struct flist far *f;  /* steps through found linked list */\n  int i;                /* arg counter, root directory flag */\n  int kk;               /* next arg type (formerly another re-use of \"k\") */\n\n  /* zip64 support 09/05/2003 R.Nausedat */\n  uzoff_t c;            /* start of central directory */\n  uzoff_t t;            /* length of central directory */\n  zoff_t k;             /* marked counter, comment size, entry count */\n  uzoff_t n;            /* total of entry len's */\n\n  int o;                /* true if there were any ZE_OPEN errors */\n  char *p;              /* steps through option arguments */\n  char *pp;             /* temporary pointer */\n  int r;                /* temporary variable */\n  int s;                /* flag to read names from stdin */\n  uzoff_t csize;        /* compressed file size for stats */\n  uzoff_t usize;        /* uncompressed file size for stats */\n  ulg tf;               /* file time */\n  int first_listarg = 0;/* index of first arg of \"process these files\" list */\n  struct zlist far *v;  /* temporary variable */\n  struct zlist far * far *w;    /* pointer to last link in zfiles list */\n  FILE *x /*, *y */;    /* input and output zip files (y global) */\n  struct zlist far *z;  /* steps through zfiles linked list */\n  int bad_open_is_error = 0; /* if read fails, 0=warning, 1=error */\n#if 0\n  /* does not seem used */\n#ifdef WINDLL\n  int retcode;          /* return code for dll */\n#endif /* WINDLL */\n#endif\n#if (!defined(VMS) && !defined(CMS_MVS))\n  char *zipbuf;         /* stdio buffer for the zip file */\n#endif /* !VMS && !CMS_MVS */\n  FILE *comment_stream; /* set to stderr if anything is read from stdin */\n  int all_current;      /* used by File Sync to determine if all entries are current */\n\n  struct filelist_struct *filearg;\n\n/* used by get_option */\n  unsigned long option; /* option ID returned by get_option */\n  int argcnt = 0;       /* current argcnt in args */\n  int argnum = 0;       /* arg number */\n  int optchar = 0;      /* option state */\n  char *value = NULL;   /* non-option arg, option value or NULL */\n  int negated = 0;      /* 1 = option negated */\n  int fna = 0;          /* current first non-opt arg */\n  int optnum = 0;       /* index in table */\n\n  int show_options = 0; /* show options */\n  int show_what_doing = 0; /* show what doing */\n  int show_args = 0;    /* show command line */\n  int seen_doubledash = 0; /* seen -- argument */\n  int key_needed = 0;   /* prompt for encryption key */\n  int have_out = 0;     /* if set in_path and out_path different archive */\n#ifdef UNICODE_TEST\n  int create_files = 0;\n#endif\n\n  char **args = NULL;  /* could be wide argv */\n\n\n#ifdef THEOS\n  /* the argument expansion from the standard library is full of bugs */\n  /* use mine instead */\n  _setargv(&argc, &argv);\n  setlocale(LC_CTYPE, \"I\");\n#else\n  SETLOCALE(LC_CTYPE, \"\");\n#endif\n\n#ifdef UNICODE_SUPPORT\n# ifdef UNIX\n  /* For Unix, set the locale to UTF-8.  Any UTF-8 locale is\n     OK and they should all be the same.  This allows seeing,\n     writing, and displaying (if the fonts are loaded) all\n     characters in UTF-8. */\n  {\n    char *loc;\n\n    /*\n      loc = setlocale(LC_CTYPE, NULL);\n      printf(\"  Initial language locale = '%s'\\n\", loc);\n    */\n\n    loc = setlocale(LC_CTYPE, \"en_US.UTF-8\");\n\n    /*\n      printf(\"langinfo %s\\n\", nl_langinfo(CODESET));\n    */\n\n    if (loc != NULL) {\n      /* using UTF-8 character set so can set UTF-8 GPBF bit 11 */\n      using_utf8 = 1;\n      /*\n        printf(\"  Locale set to %s\\n\", loc);\n      */\n    } else {\n      /*\n        printf(\"  Could not set Unicode UTF-8 locale\\n\");\n      */\n    }\n  }\n# endif\n#endif\n\n#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)\n  {\n    extern void DebugMalloc(void);\n    atexit(DebugMalloc);\n  }\n#endif\n\n#ifdef QDOS\n  {\n    extern void QDOSexit(void);\n    atexit(QDOSexit);\n  }\n#endif\n\n#ifdef NLM\n  {\n    extern void NLMexit(void);\n    atexit(NLMexit);\n  }\n#endif\n\n#ifdef RISCOS\n  set_prefix();\n#endif\n\n#ifdef __human68k__\n  fflush(stderr);\n  setbuf(stderr, NULL);\n#endif\n\n/* Re-initialize global variables to make the zip dll re-entrant. It is\n * possible that we could get away with not re-initializing all of these\n * but better safe than sorry.\n */\n#if defined(MACOS) || defined(WINDLL) || defined(USE_ZIPMAIN)\n  action = ADD; /* one of ADD, UPDATE, FRESHEN, DELETE, or ARCHIVE */\n  comadd = 0;   /* 1=add comments for new files */\n  zipedit = 0;  /* 1=edit zip comment and all file comments */\n  latest = 0;   /* 1=set zip file time to time of latest file */\n  before = 0;   /* 0=ignore, else exclude files before this time */\n  after = 0;    /* 0=ignore, else exclude files newer than this time */\n  test = 0;     /* 1=test zip file with unzip -t */\n  unzip_path = NULL; /* where to look for unzip command path */\n  tempdir = 0;  /* 1=use temp directory (-b) */\n  junk_sfx = 0; /* 1=junk the sfx prefix */\n#if defined(AMIGA) || defined(MACOS)\n  filenotes = 0;/* 1=take comments from AmigaDOS/MACOS filenotes */\n#endif\n#ifndef USE_ZIPMAIN\n  zipstate = -1;\n#endif\n  tempzip = NULL;\n  fcount = 0;\n  recurse = 0;         /* 1=recurse into directories; 2=match filenames */\n  dispose = 0;         /* 1=remove files after put in zip file */\n  pathput = 1;         /* 1=store path with name */\n  method = BEST;       /* one of BEST, DEFLATE (only), or STORE (only) */\n  dosify = 0;          /* 1=make new entries look like MSDOS */\n  verbose = 0;         /* 1=report oddities in zip file structure */\n  fix = 0;             /* 1=fix the zip file */\n  adjust = 0;          /* 1=adjust offsets for sfx'd file (keep preamble) */\n  level = 6;           /* 0=fastest compression, 9=best compression */\n  translate_eol = 0;   /* Translate end-of-line LF -> CR LF */\n#if defined(OS2) || defined(WIN32)\n  use_longname_ea = 0; /* 1=use the .LONGNAME EA as the file's name */\n#endif\n#ifdef NTSD_EAS\n  use_privileges = 0;     /* 1=use security privileges overrides */\n#endif\n  no_wild = 0;            /* 1 = wildcards are disabled */\n#ifdef WILD_STOP_AT_DIR\n   wild_stop_at_dir = 1;  /* default wildcards do not include / in matches */\n#else\n   wild_stop_at_dir = 0;  /* default wildcards do include / in matches */\n#endif\n\n  skip_this_disk = 0;\n  des_good = 0;           /* Good data descriptor found */\n  des_crc = 0;            /* Data descriptor CRC */\n  des_csize = 0;          /* Data descriptor csize */\n  des_usize = 0;          /* Data descriptor usize */\n\n  dot_size = 0;           /* buffers processed in deflate per dot, 0 = no dots */\n  dot_count = 0;          /* buffers seen, recyles at dot_size */\n\n  display_counts = 0;     /* display running file count */\n  display_bytes = 0;      /* display running bytes remaining */\n  display_globaldots = 0; /* display dots for archive instead of each file */\n  display_volume = 0;     /* display current input and output volume (disk) numbers */\n  display_usize = 0;      /* display uncompressed bytes */\n\n  files_so_far = 0;       /* files processed so far */\n  bad_files_so_far = 0;   /* bad files skipped so far */\n  files_total = 0;        /* files total to process */\n  bytes_so_far = 0;       /* bytes processed so far (from initial scan) */\n  good_bytes_so_far = 0;  /* good bytes read so far */\n  bad_bytes_so_far = 0;   /* bad bytes skipped so far */\n  bytes_total = 0;        /* total bytes to process (from initial scan) */\n\n  logall = 0;             /* 0 = warnings/errors, 1 = all */\n  logfile = NULL;         /* pointer to open logfile or NULL */\n  logfile_append = 0;     /* append to existing logfile */\n  logfile_path = NULL;    /* pointer to path of logfile */\n\n  hidden_files = 0;       /* process hidden and system files */\n  volume_label = 0;       /* add volume label */\n  dirnames = 1;           /* include directory entries by default */\n#if defined(WIN32)\n  only_archive_set = 0;   /* only include if DOS archive bit set */\n  clear_archive_bits = 0; /* clear DOS archive bit of included files */\n#endif\n  linkput = 0;            /* 1=store symbolic links as such */\n  noisy = 1;              /* 0=quiet operation */\n  extra_fields = 1;       /* 0=create minimum, 1=don't copy old, 2=keep old */\n\n  use_descriptors = 0;    /* 1=use data descriptors 12/29/04 */\n  zip_to_stdout = 0;      /* output zipfile to stdout 12/30/04 */\n  allow_empty_archive = 0;/* if no files, create empty archive anyway 12/28/05 */\n  copy_only = 0;          /* 1=copying archive entries only */\n\n  output_seekable = 1;    /* 1 = output seekable 3/13/05 EG */\n\n#ifdef ZIP64_SUPPORT      /* zip64 support 10/4/03 */\n  force_zip64 = -1;       /* if 1 force entries to be zip64 */\n                          /* mainly for streaming from stdin */\n  zip64_entry = 0;        /* current entry needs Zip64 */\n  zip64_archive = 0;      /* if 1 then at least 1 entry needs zip64 */\n#endif\n\n#ifdef UNICODE_SUPPORT\n  utf8_force = 0;         /* 1=force storing UTF-8 as standard per AppNote bit 11 */\n#endif\n\n  unicode_escape_all = 0; /* 1=escape all non-ASCII characters in paths */\n  unicode_mismatch = 1;   /* unicode mismatch is 0=error, 1=warn, 2=ignore, 3=no */\n\n  scan_delay = 5;         /* seconds before display Scanning files message */\n  scan_dot_time = 2;      /* time in seconds between Scanning files dots */\n  scan_start = 0;         /* start of scan */\n  scan_last = 0;          /* time of last message */\n  scan_started = 0;       /* scan has started */\n  scan_count = 0;         /* Used for Scanning files ... message */\n\n  before = 0;             /* 0=ignore, else exclude files before this time */\n  after = 0;              /* 0=ignore, else exclude files newer than this time */\n\n  special = \".Z:.zip:.zoo:.arc:.lzh:.arj\"; /* List of special suffixes */\n  key = NULL;             /* Scramble password if scrambling */\n  key_needed = 0;         /* Need scramble password */\n  tempath = NULL;         /* Path for temporary files */\n  patterns = NULL;        /* List of patterns to be matched */\n  pcount = 0;             /* number of patterns */\n  icount = 0;             /* number of include only patterns */\n  Rcount = 0;             /* number of -R include patterns */\n\n  found = NULL;           /* List of names found, or new found entry */\n  fnxt = &found;\n\n  /* used by get_option */\n  argcnt = 0;             /* size of args */\n  argnum = 0;             /* current arg number */\n  optchar = 0;            /* option state */\n  value = NULL;           /* non-option arg, option value or NULL */\n  negated = 0;            /* 1 = option negated */\n  fna = 0;                /* current first nonopt arg */\n  optnum = 0;             /* option index */\n\n  show_options = 0;       /* 1 = show options */\n  show_what_doing = 0;    /* 1 = show what zip doing */\n  show_args = 0;          /* 1 = show command line */\n  seen_doubledash = 0;    /* seen -- argument */\n\n  zipfile = NULL;         /* path of usual in and out zipfile */\n  tempzip = NULL;         /* name of temp file */\n  y = NULL;               /* output file now global so can change in splits */\n  in_file = NULL;         /* current input file for splits */\n  in_split_path = NULL;   /* current in split path */\n  in_path = NULL;         /* used by splits to track changing split locations */\n  out_path = NULL;        /* if set, use -O out_path as output */\n  have_out = 0;           /* if set, in_path and out_path not the same archive */\n\n  total_disks = 0;        /* total disks in archive */\n  current_in_disk = 0;    /* current read split disk */\n  current_in_offset = 0;  /* current offset in current read disk */\n  skip_current_disk = 0;  /* if != 0 and fix then skip entries on this disk */\n\n  zip64_eocd_disk = 0;    /* disk with Zip64 End Of Central Directory Record */\n  zip64_eocd_offset = 0;  /* offset for Zip64 EOCD Record */\n\n  current_local_disk = 0; /* disk with current local header */\n\n  current_disk = 0;           /* current disk number */\n  cd_start_disk = (ulg)-1;    /* central directory start disk */\n  cd_start_offset = 0;        /* offset of start of cd on cd start disk */\n  cd_entries_this_disk = 0;   /* cd entries this disk */\n  total_cd_entries = 0;       /* total cd entries in new/updated archive */\n\n  /* for split method 1 (keep split with local header open and update) */\n  current_local_tempname = NULL; /* name of temp file */\n  current_local_file = NULL;  /* file pointer for current local header */\n  current_local_offset = 0;   /* offset to start of current local header */\n\n  /* global */\n  bytes_this_split = 0;       /* bytes written to the current split */\n  read_split_archive = 0;     /* 1=scanzipf_reg detected spanning signature */\n  split_method = 0;           /* 0=no splits, 1=update LHs, 2=data descriptors */\n  split_size = 0;             /* how big each split should be */\n  split_bell = 0;             /* when pause for next split ring bell */\n  bytes_prev_splits = 0;      /* total bytes written to all splits before this */\n  bytes_this_entry = 0;       /* bytes written for this entry across all splits */\n  noisy_splits = 0;           /* be verbose about creating splits */\n  mesg_line_started = 0;      /* 1=started writing a line to mesg */\n  logfile_line_started = 0;   /* 1=started writing a line to logfile */\n\n  filelist = NULL;\n  filearg_count = 0;\n  allow_empty_archive = 0;    /* if no files, allow creation of empty archive anyway */\n  bad_open_is_error = 0;      /* if read fails, 0=warning, 1=error */\n  unicode_mismatch = 0;       /* unicode mismatch is 0=error, 1=warn, 2=ignore, 3=no */\n  show_files = 0;             /* show files to operate on and exit */\n  scan_delay = 5;             /* seconds before display Scanning files message */\n  scan_dot_time = 2;          /* time in seconds between Scanning files dots */\n  scan_started = 0;           /* space at start of scan has been displayed */\n  scan_last = 0;              /* Time last dot displayed for Scanning files message */\n  scan_start = 0;             /* Time scanning started for Scanning files message */\n#ifdef UNICODE_SUPPORT\n  use_wide_to_mb_default = 0;\n#endif\n  filter_match_case = 1;      /* default is to match case when matching archive entries */\n  allow_fifo = 0;             /* 1=allow reading Unix FIFOs, waiting if pipe open */\n\n#if !defined(MACOS) && !defined(USE_ZIPMAIN)\n  retcode = setjmp(zipdll_error_return);\n  if (retcode) {\n    return retcode;\n  }\n#endif /* !MACOS */\n#endif /* MACOS || WINDLL */\n\n#if !defined(ALLOW_REGEX) && (defined(MSDOS) || defined(WIN32))\n  allow_regex = 0;        /* 1 = allow [list] matching (regex) */\n#else\n  allow_regex = 1;\n#endif\n\n  mesg = (FILE *) stdout; /* cannot be made at link time for VMS */\n  comment_stream = (FILE *)stdin;\n\n  init_upper();           /* build case map table */\n\n#ifdef LARGE_FILE_SUPPORT\n  /* test if we can support large files - 9/29/04 */\n  if (sizeof(zoff_t) < 8) {\n    ZIPERR(ZE_COMPERR, \"LARGE_FILE_SUPPORT enabled but OS not supporting it\");\n  }\n#endif\n  /* test if sizes are the same - 12/30/04 */\n  if (sizeof(uzoff_t) != sizeof(zoff_t)){\n    ZIPERR(ZE_COMPERR, \"uzoff_t not same size as zoff_t\");\n  }\n\n#if (defined(WIN32) && defined(USE_EF_UT_TIME))\n  /* For the Win32 environment, we may have to \"prepare\" the environment\n     prior to the tzset() call, to work around tzset() implementation bugs.\n   */\n  iz_w32_prepareTZenv();\n#endif\n\n#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))\n#  ifndef VALID_TIMEZONE\n#     define VALID_TIMEZONE(tmp) \\\n             (((tmp = getenv(\"TZ\")) != NULL) && (*tmp != '\\0'))\n#  endif\n  zp_tz_is_valid = VALID_TIMEZONE(p);\n#if (defined(AMIGA) || defined(DOS))\n  if (!zp_tz_is_valid)\n    extra_fields = 0;     /* disable storing \"UT\" time stamps */\n#endif /* AMIGA || DOS */\n#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */\n\n/* For systems that do not have tzset() but supply this function using another\n   name (_tzset() or something similar), an appropiate \"#define tzset ...\"\n   should be added to the system specifc configuration section.  */\n#if (!defined(TOPS20) && !defined(VMS))\n#if (!defined(RISCOS) && !defined(MACOS) && !defined(QDOS))\n#if (!defined(BSD) && !defined(MTS) && !defined(CMS_MVS) && !defined(TANDEM))\n  tzset();\n#endif\n#endif\n#endif\n\n#ifdef VMSCLI\n  {\n      ulg status = vms_zip_cmdline(&argc, &argv);\n      if (!(status & 1))\n            return status;\n  }\n#endif /* VMSCLI */\n\n  /*    Substitutes the extended command line argument list produced by\n   *    the MKS Korn Shell in place of the command line info from DOS.\n   */\n\n  /* extract extended argument list from environment */\n  expand_args(&argc, &argv);\n\n#ifndef WINDLL\n  /* Process arguments */\n  diag(\"processing arguments\");\n  /* First, check if just the help or version screen should be displayed */\n  if (argc == 1 && isatty(1))   /* no arguments, and output screen available */\n  {                             /* show help screen */\n# ifdef VMSCLI\n    VMSCLI_help();\n# else\n    help();\n# endif\n    EXIT(ZE_OK);\n  }\n  /* Check -v here as env arg can change argc.  Handle --version in main switch. */\n  else if (argc == 2 && strcmp(argv[1], \"-v\") == 0 &&\n           /* only \"-v\" as argument, and */\n           (isatty(1) || isatty(0)))\n           /* stdout or stdin is connected to console device */\n  {                             /* show diagnostic version info */\n    version_info();\n    EXIT(ZE_OK);\n  }\n# ifndef VMS\n#   ifndef RISCOS\n  envargs(&argc, &argv, \"ZIPOPT\", \"ZIP\");  /* get options from environment */\n#   else /* RISCOS */\n  envargs(&argc, &argv, \"ZIPOPT\", \"Zip$Options\");  /* get options from environment */\n  getRISCOSexts(\"Zip$Exts\");        /* get the extensions to swap from environment */\n#   endif /* ? RISCOS */\n# else /* VMS */\n  envargs(&argc, &argv, \"ZIPOPT\", \"ZIP_OPTS\");  /* 4th arg for unzip compat. */\n# endif /* ?VMS */\n#endif /* !WINDLL */\n\n  zipfile = tempzip = NULL;\n  y = NULL;\n  d = 0;                        /* disallow adding to a zip file */\n#if (!defined(MACOS) && !defined(WINDLL) && !defined(NLM))\n  signal(SIGINT, handler);\n#ifdef SIGTERM                  /* AMIGADOS and others have no SIGTERM */\n  signal(SIGTERM, handler);\n#endif\n# if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC))\n   signal(SIGABRT, handler);\n# endif\n# ifdef SIGBREAK\n   signal(SIGBREAK, handler);\n# endif\n# ifdef SIGBUS\n   signal(SIGBUS, handler);\n# endif\n# ifdef SIGILL\n   signal(SIGILL, handler);\n# endif\n# ifdef SIGSEGV\n   signal(SIGSEGV, handler);\n# endif\n#endif /* !MACOS && !WINDLL && !NLM */\n#ifdef NLM\n  NLMsignals();\n#endif\n\n\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n  /* check if this Win32 OS has support for wide character calls */\n  has_win32_wide();\n#endif\n\n  /* make copy of args that can use with insert_arg() used by get_option() */\n  args = copy_args(argv, 0);\n\n  kk = 0;                       /* Next non-option argument type */\n  s = 0;                        /* set by -@ */\n\n  /*\n  -------------------------------------------\n  Process command line using get_option\n  -------------------------------------------\n\n  Each call to get_option() returns either a command\n  line option and possible value or a non-option argument.\n  Arguments are permuted so that all options (-r, -b temp)\n  are returned before non-option arguments (zipfile).\n  Returns 0 when nothing left to read.\n  */\n\n  /* set argnum = 0 on first call to init get_option */\n  argnum = 0;\n\n  /* get_option returns the option ID and updates parameters:\n         args    - usually same as argv if no argument file support\n         argcnt  - current argc for args\n         value   - char* to value (free() when done with it) or NULL if no value\n         negated - option was negated with trailing -\n  */\n\n  while ((option = get_option(&args, &argcnt, &argnum,\n                              &optchar, &value, &negated,\n                              &fna, &optnum, 0)))\n  {\n    switch (option)\n    {\n#ifdef EBCDIC\n      case 'a':\n        aflag = ASCII;\n        printf(\"Translating to ASCII...\\n\");\n        break;\n#endif /* EBCDIC */\n#ifdef CMS_MVS\n        case 'B':\n          bflag = 1;\n          printf(\"Using binary mode...\\n\");\n          break;\n#endif /* CMS_MVS */\n#ifdef TANDEM\n        case 'B':\n          nskformatopt(value);\n          free(value);\n          break;\n#endif\n\n        case '0':\n          method = STORE; level = 0; break;\n        case '1':  case '2':  case '3':  case '4':\n        case '5':  case '6':  case '7':  case '8':  case '9':\n          /* Set the compression efficacy */\n          level = (int)option - '0';  break;\n        case 'A':   /* Adjust unzipsfx'd zipfile:  adjust offsets only */\n          adjust = 1; break;\n#if defined(WIN32)\n        case o_AC:\n          clear_archive_bits = 1; break;\n        case o_AS:\n          /* Since some directories could be empty if no archive bits are\n             set for files in a directory, don't add directory entries (-D).\n             Just files with the archive bit set are added, including paths\n             (unless paths are excluded).  All major unzips should create\n             directories for the paths as needed. */\n          dirnames = 0;\n          only_archive_set = 1; break;\n#endif /* MSDOS || OS2 || WIN32 */\n        case 'b':   /* Specify path for temporary file */\n          tempdir = 1;\n          tempath = value;\n          break;\n        case 'c':   /* Add comments for new files in zip file */\n          comadd = 1;  break;\n\n        /* -C, -C2, and -C5 are with -V */\n\n        case 'd':   /* Delete files from zip file */\n          if (action != ADD) {\n            ZIPERR(ZE_PARMS, \"specify just one action\");\n          }\n          action = DELETE;\n          break;\n#ifdef MACOS\n        case o_df:\n          MacZip.DataForkOnly = true;\n          break;\n#endif /* MACOS */\n        case o_db:\n          if (negated)\n            display_bytes = 0;\n          else\n            display_bytes = 1;\n          break;\n        case o_dc:\n          if (negated)\n            display_counts = 0;\n          else\n            display_counts = 1;\n          break;\n        case o_dd:\n          /* display dots */\n          display_globaldots = 0;\n          if (negated) {\n            dot_count = 0;\n          } else {\n            /* set default dot size if dot_size not set (dot_count = 0) */\n            if (dot_count == 0)\n              /* default to 10 MB */\n              dot_size = 10 * 0x100000;\n            dot_count = -1;\n          }\n          break;\n        case o_dg:\n          /* display dots globally for archive instead of for each file */\n          if (negated) {\n            display_globaldots = 0;\n          } else {\n            display_globaldots = 1;\n            /* set default dot size if dot_size not set (dot_count = 0) */\n            if (dot_count == 0)\n              dot_size = 10 * 0x100000;\n            dot_count = -1;\n          }\n          break;\n        case o_ds:\n          /* input dot_size is now actual dot size to account for\n             different buffer sizes */\n          if (value == NULL)\n            dot_size = 10 * 0x100000;\n          else if (value[0] == '\\0') {\n            /* default to 10 MB */\n            dot_size = 10 * 0x100000;\n            free(value);\n          } else {\n            dot_size = ReadNumString(value);\n            if (dot_size == (zoff_t)-1) {\n              sprintf(errbuf, \"option -ds (--dot-size) has bad size:  '%s'\",\n                      value);\n              free(value);\n              ZIPERR(ZE_PARMS, errbuf);\n            }\n            if (dot_size < 0x400) {\n              /* < 1 KB so there is no multiplier, assume MB */\n              dot_size *= 0x100000;\n\n            } else if (dot_size < 0x400L * 32) {\n              /* 1K <= dot_size < 32K */\n              sprintf(errbuf, \"dot size must be at least 32 KB:  '%s'\", value);\n              free(value);\n              ZIPERR(ZE_PARMS, errbuf);\n\n            } else {\n              /* 32K <= dot_size */\n            }\n            free(value);\n          }\n          dot_count = -1;\n          break;\n        case o_du:\n          if (negated)\n            display_usize = 0;\n          else\n            display_usize = 1;\n          break;\n        case o_dv:\n          if (negated)\n            display_volume = 0;\n          else\n            display_volume = 1;\n          break;\n        case 'D':   /* Do not add directory entries */\n          dirnames = 0; break;\n        case o_DF:  /* Create a difference archive */\n          diff_mode = 1;\n          allow_empty_archive = 1;\n          break;\n        case 'e':   /* Encrypt */\n#if !CRYPT\n          ZIPERR(ZE_PARMS, \"encryption not supported\");\n#else /* CRYPT */\n          if (key)\n            free(key);\n          key_needed = 1;\n#endif /* !CRYPT */\n          break;\n        case 'F':   /* fix the zip file */\n          fix = 1; break;\n        case o_FF:  /* try harder to fix file */\n          fix = 2; break;\n        case o_FI:\n          if (negated)\n            allow_fifo = 0;\n          else\n            allow_fifo = 1;\n          break;\n        case o_FS:  /* delete exiting entries in archive where there is\n                       no matching file on file system */\n          filesync = 1; break;\n        case 'f':   /* Freshen zip file--overwrite only */\n          if (action != ADD) {\n            ZIPERR(ZE_PARMS, \"specify just one action\");\n          }\n          action = FRESHEN;\n          break;\n        case 'g':   /* Allow appending to a zip file */\n          d = 1;  break;\n#ifndef WINDLL\n        case 'h': case 'H': case '?':  /* Help */\n#ifdef VMSCLI\n          VMSCLI_help();\n#else\n          help();\n#endif\n          RETURN(finish(ZE_OK));\n#endif /* !WINDLL */\n\n#ifndef WINDLL\n        case o_h2:  /* Extended Help */\n          help_extended();\n          RETURN(finish(ZE_OK));\n#endif /* !WINDLL */\n\n        /* -i is with -x */\n#if defined(VMS) || defined(WIN32)\n        case o_ic:  /* Ignore case (case-insensitive matching of archive entries) */\n          if (negated)\n            filter_match_case = 1;\n          else\n            filter_match_case = 0;\n          break;\n#endif\n#ifdef RISCOS\n        case 'I':   /* Don't scan through Image files */\n          scanimage = 0;\n          break;\n#endif\n#ifdef MACOS\n        case o_jj:   /* store absolute path including volname */\n            MacZip.StoreFullPath = true;\n            break;\n#endif /* ?MACOS */\n        case 'j':   /* Junk directory names */\n          pathput = 0;  break;\n        case 'J':   /* Junk sfx prefix */\n          junk_sfx = 1;  break;\n        case 'k':   /* Make entries using DOS names (k for Katz) */\n          dosify = 1;  break;\n        case 'l':   /* Translate end-of-line */\n          translate_eol = 1; break;\n        case o_ll:\n          translate_eol = 2; break;\n        case o_lf:\n          /* open a logfile */\n          /* allow multiple use of option but only last used */\n          if (logfile_path) {\n            free(logfile_path);\n          }\n          logfile_path = value;\n          break;\n        case o_la:\n          /* append to existing logfile */\n          if (negated)\n            logfile_append = 0;\n          else\n            logfile_append = 1;\n          break;\n        case o_li:\n          /* log all including informational messages */\n          if (negated)\n            logall = 0;\n          else\n            logall = 1;\n          break;\n#ifndef WINDLL\n        case 'L':   /* Show license */\n          license();\n          RETURN(finish(ZE_OK));\n#endif\n        case 'm':   /* Delete files added or updated in zip file */\n          dispose = 1;  break;\n        case o_mm:  /* To prevent use of -mm for -MM */\n          ZIPERR(ZE_PARMS, \"-mm not supported, Must_Match is -MM\");\n          dispose = 1;  break;\n        case o_MM:  /* Exit with error if input file can't be read */\n          bad_open_is_error = 1; break;\n        case 'n':   /* Don't compress files with a special suffix */\n          special = value;\n          /* special = NULL; */ /* will be set at next argument */\n          break;\n        case o_nw:  /* no wildcards - wildcards are handled like other characters */\n          no_wild = 1;\n          break;\n#if defined(AMIGA) || defined(MACOS)\n        case 'N':   /* Get zipfile comments from AmigaDOS/MACOS filenotes */\n          filenotes = 1; break;\n#endif\n        case 'o':   /* Set zip file time to time of latest file in it */\n          latest = 1;  break;\n        case 'O':   /* Set output file different than input archive */\n          out_path = ziptyp(value);\n          free(value);\n          have_out = 1;\n          break;\n        case 'p':   /* Store path with name */\n          break;            /* (do nothing as annoyance avoidance) */\n        case 'P':   /* password for encryption */\n          if (key != NULL) {\n            free(key);\n          }\n#if CRYPT\n          key = value;\n          key_needed = 0;\n#else\n          ZIPERR(ZE_PARMS, \"encryption not supported\");\n#endif /* CRYPT */\n          break;\n#if defined(QDOS) || defined(QLZIP)\n        case 'Q':\n          qlflag  = strtol(value, NULL, 10);\n       /* qlflag  = strtol((p+1), &p, 10); */\n       /* p--; */\n          if (qlflag == 0) qlflag = 4;\n          free(value);\n          break;\n#endif\n        case 'q':   /* Quiet operation */\n          noisy = 0;\n#ifdef MACOS\n          MacZip.MacZip_Noisy = false;\n#endif  /* MACOS */\n          if (verbose) verbose--;\n          break;\n        case 'r':   /* Recurse into subdirectories, match full path */\n          if (recurse == 2) {\n            ZIPERR(ZE_PARMS, \"do not specify both -r and -R\");\n          }\n          recurse = 1;  break;\n        case 'R':   /* Recurse into subdirectories, match filename */\n          if (recurse == 1) {\n            ZIPERR(ZE_PARMS, \"do not specify both -r and -R\");\n          }\n          recurse = 2;  break;\n\n        case o_RE:   /* Allow [list] matching (regex) */\n          allow_regex = 1; break;\n\n        case o_sc:  /* show command line args */\n          show_args = 1; break;\n#ifdef UNICODE_TEST\n        case o_sC:  /* create empty files from archive names */\n          create_files = 1;\n          show_files = 1; break;\n#endif\n        case o_sd:  /* show debugging */\n          show_what_doing = 1; break;\n        case o_sf:  /* show files to operate on */\n          if (!negated)\n            show_files = 1;\n          else\n            show_files = 2;\n          break;\n        case o_so:  /* show all options */\n          show_options = 1; break;\n#ifdef UNICODE_SUPPORT\n        case o_su:  /* -sf but also show Unicode if exists */\n          if (!negated)\n            show_files = 3;\n          else\n            show_files = 4;\n          break;\n        case o_sU:  /* -sf but only show Unicode if exists or normal if not */\n          if (!negated)\n            show_files = 5;\n          else\n            show_files = 6;\n          break;\n#endif\n\n        case 's':   /* enable split archives */\n          /* get the split size from value */\n          if (strcmp(value, \"-\") == 0) {\n            /* -s- do not allow splits */\n            split_method = -1;\n          } else {\n            split_size = ReadNumString(value);\n            if (split_size == (uzoff_t)-1) {\n              sprintf(errbuf, \"bad split size:  '%s'\", value);\n              ZIPERR(ZE_PARMS, errbuf);\n            }\n            if (split_size == 0) {\n              /* do not allow splits */\n              split_method = -1;\n            } else {\n              if (split_method == 0) {\n                split_method = 1;\n              }\n              if (split_size < 0x400) {\n                /* < 1 KB there is no multiplier, assume MB */\n                split_size *= 0x100000;\n              }\n              /* By setting the minimum split size to 64 KB we avoid\n                 not having enough room to write a header unsplit\n                 which is required */\n              if (split_size < 0x400L * 64) {\n                /* split_size < 64K */\n                sprintf(errbuf, \"minimum split size is 64 KB:  '%s'\", value);\n                free(value);\n                ZIPERR(ZE_PARMS, errbuf);\n              }\n            }\n          }\n          free(value);\n          break;\n        case o_sb:  /* when pause for next split ring bell */\n          split_bell = 1;\n          break;\n        case o_sp:  /* enable split select - pause splitting between splits */\n          use_descriptors = 1;\n          split_method = 2;\n          break;\n        case o_sv:  /* be verbose about creating splits */\n          noisy_splits = 1;\n          break;\n\n#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(ATARI)\n        case 'S':\n          hidden_files = 1; break;\n#endif /* MSDOS || OS2 || WIN32 || ATARI */\n#ifdef MACOS\n        case 'S':\n          MacZip.IncludeInvisible = true; break;\n#endif /* MACOS */\n        case 't':   /* Exclude files earlier than specified date */\n          {\n            int yyyy, mm, dd;       /* results of sscanf() */\n\n            /* Support ISO 8601 & American dates */\n            if ((sscanf(value, \"%4d-%2d-%2d\", &yyyy, &mm, &dd) != 3 &&\n                 sscanf(value, \"%2d%2d%4d\", &mm, &dd, &yyyy) != 3) ||\n                mm < 1 || mm > 12 || dd < 1 || dd > 31) {\n              ZIPERR(ZE_PARMS,\n                     \"invalid date entered for -t option - use mmddyyyy or yyyy-mm-dd\");\n            }\n            before = dostime(yyyy, mm, dd, 0, 0, 0);\n          }\n          free(value);\n          break;\n        case o_tt:  /* Exclude files at or after specified date */\n          {\n            int yyyy, mm, dd;       /* results of sscanf() */\n\n            /* Support ISO 8601 & American dates */\n            if ((sscanf(value, \"%4d-%2d-%2d\", &yyyy, &mm, &dd) != 3 &&\n                 sscanf(value, \"%2d%2d%4d\", &mm, &dd, &yyyy) != 3) ||\n                mm < 1 || mm > 12 || dd < 1 || dd > 31) {\n              ZIPERR(ZE_PARMS,\n                     \"invalid date entered for -tt option - use mmddyyyy or yyyy-mm-dd\");\n            }\n            after = dostime(yyyy, mm, dd, 0, 0, 0);\n          }\n          free(value);\n          break;\n        case 'T':   /* test zip file */\n          test = 1; break;\n        case o_TT:  /* command path to use instead of 'unzip -t ' */\n          if (unzip_path)\n            free(unzip_path);\n          unzip_path = value;\n          break;\n        case 'U':   /* Select archive entries to keep or operate on */\n          if (action != ADD) {\n            ZIPERR(ZE_PARMS, \"specify just one action\");\n          }\n          action = ARCHIVE;\n          break;\n#ifdef UNICODE_SUPPORT\n        case o_UN:   /* Unicode */\n          if (abbrevmatch(\"quit\", value, 0, 1)) {\n            /* Unicode path mismatch is error */\n            unicode_mismatch = 0;\n          } else if (abbrevmatch(\"warn\", value, 0, 1)) {\n            /* warn of mismatches and continue */\n            unicode_mismatch = 1;\n          } else if (abbrevmatch(\"ignore\", value, 0, 1)) {\n            /* ignore mismatches and continue */\n            unicode_mismatch = 2;\n          } else if (abbrevmatch(\"no\", value, 0, 1)) {\n            /* no use Unicode path */\n            unicode_mismatch = 3;\n          } else if (abbrevmatch(\"escape\", value, 0, 1)) {\n            /* escape all non-ASCII characters */\n            unicode_escape_all = 1;\n\n          } else if (abbrevmatch(\"UTF8\", value, 0, 1)) {\n            /* force storing UTF-8 as standard per AppNote bit 11 */\n            utf8_force = 1;\n\n          } else {\n            zipwarn(\"-UN must be Quit, Warn, Ignore, No, Escape, or UTF8: \", value);\n\n            free(value);\n            ZIPERR(ZE_PARMS, \"-UN (unicode) bad value\");\n          }\n          free(value);\n          break;\n#endif\n        case 'u':   /* Update zip file--overwrite only if newer */\n          if (action != ADD) {\n            ZIPERR(ZE_PARMS, \"specify just one action\");\n          }\n          action = UPDATE;\n          break;\n        case 'v':        /* Either display version information or */\n        case o_ve:       /* Mention oddities in zip file structure */\n          if (option == o_ve ||      /* --version */\n              (argcnt == 2 && strlen(args[1]) == 2)) { /* -v only */\n            /* display version */\n#ifndef WINDLL\n            version_info();\n#else\n            zipwarn(\"version information not supported for dll\", \"\");\n#endif\n            RETURN(finish(ZE_OK));\n          } else {\n            noisy = 1;\n            verbose++;\n          }\n          break;\n#ifdef VMS\n        case 'C':  /* Preserve case (- = down-case) all. */\n          if (negated)\n          { /* Down-case all. */\n            if ((vms_case_2 > 0) || (vms_case_5 > 0))\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C-)\");\n            }\n            vms_case_2 = -1;\n            vms_case_5 = -1;\n          }\n          else\n          { /* Not negated.  Preserve all. */\n            if ((vms_case_2 < 0) || (vms_case_5 < 0))\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C)\");\n            }\n            vms_case_2 = 1;\n            vms_case_5 = 1;\n          }\n          break;\n        case o_C2:  /* Preserve case (- = down-case) ODS2. */\n          if (negated)\n          { /* Down-case ODS2. */\n            if (vms_case_2 > 0)\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C2-)\");\n            }\n            vms_case_2 = -1;\n          }\n          else\n          { /* Not negated.  Preserve ODS2. */\n            if (vms_case_2 < 0)\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C2)\");\n            }\n            vms_case_2 = 1;\n          }\n          break;\n        case o_C5:  /* Preserve case (- = down-case) ODS5. */\n          if (negated)\n          { /* Down-case ODS5. */\n            if (vms_case_5 > 0)\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C5-)\");\n            }\n            vms_case_5 = -1;\n          }\n          else\n          { /* Not negated.  Preserve ODS5. */\n            if (vms_case_5 < 0)\n            {\n              ZIPERR( ZE_PARMS, \"Conflicting case directives (-C5)\");\n            }\n            vms_case_5 = 1;\n          }\n          break;\n        case 'V':   /* Store in VMS format.  (Record multiples.) */\n          vms_native = 1; break;\n          /* below does work with new parser but doesn't allow tracking\n             -VV separately, like adding a separate description */\n          /* vms_native++; break; */\n        case o_VV:  /* Store in VMS specific format */\n          vms_native = 2; break;\n        case 'w':   /* Append the VMS version number */\n          vmsver |= 1;  break;\n        case o_ww:   /* Append the VMS version number as \".nnn\". */\n          vmsver |= 3;  break;\n#endif /* VMS */\n        case o_ws:  /* Wildcards do not include directory boundaries in matches */\n          wild_stop_at_dir = 1;\n          break;\n\n        case 'i':   /* Include only the following files */\n          /* if nothing matches include list then still create an empty archive */\n          allow_empty_archive = 1;\n        case 'x':   /* Exclude following files */\n          add_filter((int) option, value);\n          free(value);\n          break;\n#ifdef S_IFLNK\n        case 'y':   /* Store symbolic links as such */\n          linkput = 1;  break;\n#endif /* S_IFLNK */\n        case 'z':   /* Edit zip file comment */\n          zipedit = 1;  break;\n        case 'Z':   /* Compression method */\n          if (abbrevmatch(\"deflate\", value, 0, 1)) {\n            /* deflate */\n            method = DEFLATE;\n          } else if (abbrevmatch(\"store\", value, 0, 1)) {\n            /* store */\n            method = STORE;\n          } else if (abbrevmatch(\"bzip2\", value, 0, 1)) {\n            /* bzip2 */\n#ifdef BZIP2_SUPPORT\n            method = BZIP2;\n#else\n            ZIPERR(ZE_COMPERR, \"Compression method bzip2 not enabled\");\n#endif\n          } else {\n#ifdef BZIP2_SUPPORT\n            zipwarn(\"valid compression methods are:  store, deflate, bzip2\", \"\");\n#else\n            zipwarn(\"valid compression methods are:  store, deflate)\", \"\");\n#endif\n            zipwarn(\"unknown compression method found:  \", value);\n            free(value);\n            ZIPERR(ZE_PARMS, \"Option -Z (--compression-method):  unknown method\");\n          }\n          free(value);\n          break;\n#if defined(MSDOS) || defined(OS2)\n        case '$':   /* Include volume label */\n          volume_label = 1; break;\n#endif\n#ifndef MACOS\n        case '@':   /* read file names from stdin */\n          comment_stream = NULL;\n          s = 1;          /* defer -@ until have zipfile name */\n          break;\n#endif /* !MACOS */\n        case 'X':\n          if (negated)\n            extra_fields = 2;\n          else\n            extra_fields = 0;\n          break;\n#ifdef OS2\n        case 'E':\n          /* use the .LONGNAME EA (if any) as the file's name. */\n          use_longname_ea = 1;\n          break;\n#endif\n#ifdef NTSD_EAS\n        case '!':\n          /* use security privilege overrides */\n          use_privileges = 1;\n          break;\n#endif\n#ifdef RISCOS\n        case '/':\n          exts2swap = value; /* override Zip$Exts */\n          break;\n#endif\n        case o_des:\n          use_descriptors = 1;\n          break;\n\n#ifdef ZIP64_SUPPORT\n        case o_z64:   /* Force creation of Zip64 entries */\n          if (negated) {\n            force_zip64 = 0;\n          } else {\n            force_zip64 = 1;\n          }\n          break;\n#endif\n\n        case o_NON_OPTION_ARG:\n          /* not an option */\n          /* no more options as permuting */\n          /* just dash also ends up here */\n\n          if (recurse != 2 && kk == 0 && patterns == NULL) {\n            /* have all filters so convert filterlist to patterns array\n               as PROCNAME needs patterns array */\n            filterlist_to_patterns();\n          }\n\n          /* \"--\" stops arg processing for remaining args */\n          /* ignore only first -- */\n          if (strcmp(value, \"--\") == 0 && seen_doubledash == 0) {\n            /* -- */\n            seen_doubledash = 1;\n            if (kk == 0) {\n              ZIPERR(ZE_PARMS, \"can't use -- before archive name\");\n            }\n\n            /* just ignore as just marks what follows as non-option arguments */\n\n          } else if (kk == 6) {\n            /* value is R pattern */\n            add_filter((int)'R', value);\n            free(value);\n            if (first_listarg == 0) {\n              first_listarg = argnum;\n            }\n          } else switch (kk)\n          {\n            case 0:\n              /* first non-option arg is zipfile name */\n#if (!defined(MACOS) && !defined(WINDLL))\n              if (strcmp(value, \"-\") == 0) {  /* output zipfile is dash */\n                /* just a dash */\n                zipstdout();\n              } else\n#endif /* !MACOS && !WINDLL */\n              {\n                /* name of zipfile */\n                if ((zipfile = ziptyp(value)) == NULL) {\n                  ZIPERR(ZE_MEM, \"was processing arguments\");\n                }\n                /* read zipfile if exists */\n                /*\n                if ((r = readzipfile()) != ZE_OK) {\n                  ZIPERR(r, zipfile);\n                }\n                */\n                free(value);\n              }\n              if (show_what_doing) {\n                fprintf(mesg, \"sd: Zipfile name '%s'\\n\", zipfile);\n                fflush(mesg);\n              }\n              /* if in_path not set, use zipfile path as usual for input */\n              /* in_path is used as the base path to find splits */\n              if (in_path == NULL) {\n                if ((in_path = malloc(strlen(zipfile) + 1)) == NULL) {\n                  ZIPERR(ZE_MEM, \"was processing arguments\");\n                }\n                strcpy(in_path, zipfile);\n              }\n              /* if out_path not set, use zipfile path as usual for output */\n              /* out_path is where the output archive is written */\n              if (out_path == NULL) {\n                if ((out_path = malloc(strlen(zipfile) + 1)) == NULL) {\n                  ZIPERR(ZE_MEM, \"was processing arguments\");\n                }\n                strcpy(out_path, zipfile);\n              }\n              kk = 3;\n              if (s)\n              {\n                /* do -@ and get names from stdin */\n                /* should be able to read names from\n                   stdin and output to stdout, but\n                   this was not allowed in old code.\n                   This check moved to kk = 3 case to fix. */\n                /* if (strcmp(zipfile, \"-\") == 0) {\n                  ZIPERR(ZE_PARMS, \"can't use - and -@ together\");\n                }\n                */\n                while ((pp = getnam(stdin)) != NULL)\n                {\n                  kk = 4;\n                  if (recurse == 2) {\n                    /* reading patterns from stdin */\n                    add_filter((int)'R', pp);\n                  } else {\n                    /* file argument now processed later */\n                    add_name(pp);\n                  }\n                  /*\n                  if ((r = PROCNAME(pp)) != ZE_OK) {\n                    if (r == ZE_MISS)\n                      zipwarn(\"name not matched: \", pp);\n                    else {\n                      ZIPERR(r, pp);\n                    }\n                  }\n                  */\n                  free(pp);\n                }\n                s = 0;\n              }\n              if (recurse == 2) {\n                /* rest are -R patterns */\n                kk = 6;\n              }\n              break;\n\n            case 3:  case 4:\n              /* no recurse and -r file names */\n              /* can't read filenames -@ and input - from stdin at\n                 same time */\n              if (s == 1 && strcmp(value, \"-\") == 0) {\n                ZIPERR(ZE_PARMS, \"can't read input (-) and filenames (-@) both from stdin\");\n              }\n              /* add name to list for later processing */\n              add_name(value);\n              /*\n              if ((r = PROCNAME(value)) != ZE_OK) {\n                if (r == ZE_MISS)\n                  zipwarn(\"name not matched: \", value);\n                else {\n                  ZIPERR(r, value);\n                }\n              }\n              */\n              if (kk == 3) {\n                first_listarg = argnum;\n                kk = 4;\n              }\n              break;\n\n            } /* switch kk */\n            break;\n\n        default:\n          /* should never get here as get_option will exit if not in table */\n          sprintf(errbuf, \"no such option ID: %ld\", option);\n          ZIPERR(ZE_PARMS, errbuf);\n\n     }  /* switch */\n  }\n\n\n  /* do processing of command line and one-time tasks */\n\n  /* Key not yet specified.  If needed, get/verify it now. */\n  if (key_needed) {\n    if ((key = malloc(IZ_PWLEN+1)) == NULL) {\n      ZIPERR(ZE_MEM, \"was getting encryption password\");\n    }\n    r = encr_passwd(ZP_PW_ENTER, key, IZ_PWLEN+1, zipfile);\n    if (r != IZ_PW_ENTERED) {\n      if (r < IZ_PW_ENTERED)\n        r = ZE_PARMS;\n      ZIPERR(r, \"was getting encryption password\");\n    }\n    if (*key == '\\0') {\n      ZIPERR(ZE_PARMS, \"zero length password not allowed\");\n    }\n    if ((e = malloc(IZ_PWLEN+1)) == NULL) {\n      ZIPERR(ZE_MEM, \"was verifying encryption password\");\n    }\n    r = encr_passwd(ZP_PW_VERIFY, e, IZ_PWLEN+1, zipfile);\n    if (r != IZ_PW_ENTERED && r != IZ_PW_SKIPVERIFY) {\n      free((zvoid *)e);\n      if (r < ZE_OK) r = ZE_PARMS;\n      ZIPERR(r, \"was verifying encryption password\");\n    }\n    r = ((r == IZ_PW_SKIPVERIFY) ? 0 : strcmp(key, e));\n    free((zvoid *)e);\n    if (r) {\n      ZIPERR(ZE_PARMS, \"password verification failed\");\n    }\n  }\n  if (key) {\n    /* if -P \"\" could get here */\n    if (*key == '\\0') {\n      ZIPERR(ZE_PARMS, \"zero length password not allowed\");\n    }\n  }\n\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Command line read\\n\");\n    fflush(mesg);\n  }\n\n  /* show command line args */\n  if (show_args) {\n    fprintf(mesg, \"command line:\\n\");\n    for (i = 0; args[i]; i++) {\n      fprintf(mesg, \"'%s'  \", args[i]);\n    }\n    fprintf(mesg, \"\\n\");\n    ZIPERR(ZE_ABORT, \"show command line\");\n  }\n\n  /* show all options */\n  if (show_options) {\n    printf(\"available options:\\n\");\n    printf(\" %-2s  %-18s %-4s %-3s %-30s\\n\", \"sh\", \"long\", \"val\", \"neg\", \"description\");\n    printf(\" %-2s  %-18s %-4s %-3s %-30s\\n\", \"--\", \"----\", \"---\", \"---\", \"-----------\");\n    for (i = 0; options[i].option_ID; i++) {\n      printf(\" %-2s  %-18s \", options[i].shortopt, options[i].longopt);\n      switch (options[i].value_type) {\n        case o_NO_VALUE:\n          printf(\"%-4s \", \"\");\n          break;\n        case o_REQUIRED_VALUE:\n          printf(\"%-4s \", \"req\");\n          break;\n        case o_OPTIONAL_VALUE:\n          printf(\"%-4s \", \"opt\");\n          break;\n        case o_VALUE_LIST:\n          printf(\"%-4s \", \"list\");\n          break;\n        case o_ONE_CHAR_VALUE:\n          printf(\"%-4s \", \"char\");\n          break;\n        case o_NUMBER_VALUE:\n          printf(\"%-4s \", \"num\");\n          break;\n        default:\n          printf(\"%-4s \", \"unk\");\n      }\n      switch (options[i].negatable) {\n        case o_NEGATABLE:\n          printf(\"%-3s \", \"neg\");\n          break;\n        case o_NOT_NEGATABLE:\n          printf(\"%-3s \", \"\");\n          break;\n        default:\n          printf(\"%-3s \", \"unk\");\n      }\n      if (options[i].name)\n        printf(\"%-30s\\n\", options[i].name);\n      else\n        printf(\"\\n\");\n    }\n    RETURN(finish(ZE_OK));\n  }\n\n\n  /* open log file */\n  if (logfile_path) {\n    char mode[10];\n    char *p;\n    char *lastp;\n\n    /* if no extension add .log */\n    p = logfile_path;\n    /* find last / */\n    lastp = NULL;\n    for (p = logfile_path; (p = MBSRCHR(p, '/')) != NULL; p++) {\n      lastp = p;\n    }\n    if (lastp == NULL)\n      lastp = logfile_path;\n    if (MBSRCHR(lastp, '.') == NULL) {\n      /* add .log */\n      if ((p = malloc(strlen(logfile_path) + 5)) == NULL) {\n        ZIPERR(ZE_MEM, \"logpath\");\n      }\n      strcpy(p, logfile_path);\n      strcat(p, \".log\");\n      free(logfile_path);\n      logfile_path = p;\n    }\n\n    if (logfile_append) {\n      sprintf(mode, \"a\");\n    } else {\n      sprintf(mode, \"w\");\n    }\n    if ((logfile = zfopen(logfile_path, mode)) == NULL) {\n      sprintf(errbuf, \"could not open logfile '%s'\", logfile_path);\n      ZIPERR(ZE_PARMS, errbuf);\n    }\n    {\n      /* At top put start time and command line */\n\n      /* get current time */\n      struct tm *now;\n      time_t clocktime;\n\n      time(&clocktime);\n      now = localtime(&clocktime);\n\n      fprintf(logfile, \"---------\\n\");\n      fprintf(logfile, \"Zip log opened %s\", asctime(now));\n      fprintf(logfile, \"command line arguments:\\n \");\n      for (i = 1; args[i]; i++) {\n        size_t j;\n        int has_space = 0;\n\n        for (j = 0; j < strlen(args[i]); j++) {\n          if (isspace(args[i][j])) {\n            has_space = 1;\n            break;\n          }\n        }\n        if (has_space)\n          fprintf(logfile, \"\\\"%s\\\" \", args[i]);\n        else\n          fprintf(logfile, \"%s \", args[i]);\n      }\n      fprintf(logfile, \"\\n\\n\");\n      fflush(logfile);\n    }\n  } else {\n    /* only set logall if logfile open */\n    logall = 0;\n  }\n\n\n  if (split_method && out_path) {\n    /* if splitting, the archive name must have .zip extension */\n    int plen = strlen(out_path);\n    char *out_path_ext;\n\n#ifdef VMS\n    /* On VMS, adjust plen (and out_path_ext) to avoid the file version. */\n    plen -= strlen( vms_file_version( out_path));\n#endif /* def VMS */\n    out_path_ext = out_path+ plen- 4;\n\n    if (plen < 4 ||\n        out_path_ext[0] != '.' ||\n        toupper(out_path_ext[1]) != 'Z' ||\n        toupper(out_path_ext[2]) != 'I' ||\n        toupper(out_path_ext[3]) != 'P') {\n      ZIPERR(ZE_PARMS, \"archive name must end in .zip for splits\");\n    }\n  }\n\n\n  if (verbose && (dot_size == 0) && (dot_count == 0)) {\n    /* now default to default 10 MB dot size */\n    dot_size = 10 * 0x100000;\n    /* show all dots as before if verbose set and dot_size not set (dot_count = 0) */\n    /* maybe should turn off dots in default verbose mode */\n    /* dot_size = -1; */\n  }\n\n  /* done getting -R filters so convert filterlist if not done */\n  if (pcount && patterns == NULL) {\n    filterlist_to_patterns();\n  }\n\n#if (defined(MSDOS) || defined(OS2)) && !defined(WIN32)\n  if ((kk == 3 || kk == 4) && volume_label == 1) {\n    /* read volume label */\n    PROCNAME(NULL);\n    kk = 4;\n  }\n#endif\n\n  if (have_out && kk == 3) {\n    copy_only = 1;\n    action = ARCHIVE;\n  }\n\n  if (have_out && namecmp(in_path, out_path) == 0) {\n    sprintf(errbuf, \"--out path must be different than in path: %s\", out_path);\n    ZIPERR(ZE_PARMS, errbuf);\n  }\n\n  if (fix && diff_mode) {\n    ZIPERR(ZE_PARMS, \"can't use --diff (-DF) with fix (-F or -FF)\");\n  }\n\n  if (action == ARCHIVE && !have_out && !show_files) {\n    ZIPERR(ZE_PARMS, \"-U (--copy) requires -O (--out)\");\n  }\n\n  if (fix && !have_out) {\n    zipwarn(\"fix options -F and -FF require --out:\\n\",\n            \"                     zip -F indamagedarchive --out outfixedarchive\");\n    ZIPERR(ZE_PARMS, \"fix options require --out\");\n  }\n\n  if (fix && !copy_only) {\n    ZIPERR(ZE_PARMS, \"no other actions allowed when fixing archive (-F or -FF)\");\n  }\n\n  if (!have_out && diff_mode) {\n    ZIPERR(ZE_PARMS, \"-DF (--diff) requires -O (--out)\");\n  }\n\n  if (diff_mode && (action == ARCHIVE || action == DELETE)) {\n    ZIPERR(ZE_PARMS, \"can't use --diff (-DF) with -d or -U\");\n  }\n\n  if (action != ARCHIVE && (recurse == 2 || pcount) && first_listarg == 0 &&\n      !filelist && (kk < 3 || (action != UPDATE && action != FRESHEN))) {\n    ZIPERR(ZE_PARMS, \"nothing to select from\");\n  }\n\n/*\n  -------------------------------------\n  end of new command line code\n  -------------------------------------\n*/\n\n#if (!defined(MACOS) && !defined(WINDLL))\n  if (kk < 3) {               /* zip used as filter */\n    zipstdout();\n    comment_stream = NULL;\n    if ((r = procname(\"-\", 0)) != ZE_OK) {\n      if (r == ZE_MISS) {\n        if (bad_open_is_error) {\n          zipwarn(\"name not matched: \", \"-\");\n          ZIPERR(ZE_OPEN, \"-\");\n        } else {\n          zipwarn(\"name not matched: \", \"-\");\n        }\n      } else {\n        ZIPERR(r, \"-\");\n      }\n    }\n    kk = 4;\n    if (s) {\n      ZIPERR(ZE_PARMS, \"can't use - and -@ together\");\n    }\n  }\n#endif /* !MACOS && !WINDLL */\n\n  if (zipfile && !strcmp(zipfile, \"-\")) {\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Zipping to stdout\\n\");\n      fflush(mesg);\n    }\n    zip_to_stdout = 1;\n  }\n\n  /* Check option combinations */\n  if (special == NULL) {\n    ZIPERR(ZE_PARMS, \"missing suffix list\");\n  }\n  if (level == 9 || !strcmp(special, \";\") || !strcmp(special, \":\"))\n    special = NULL; /* compress everything */\n\n  if (action == DELETE && (method != BEST || dispose || recurse ||\n      key != NULL || comadd || zipedit)) {\n    zipwarn(\"invalid option(s) used with -d; ignored.\",\"\");\n    /* reset flags - needed? */\n    method  = BEST;\n    dispose = 0;\n    recurse = 0;\n    if (key != NULL) {\n      free((zvoid *)key);\n      key   = NULL;\n    }\n    comadd  = 0;\n    zipedit = 0;\n  }\n  if (action == ARCHIVE && (method != BEST || dispose || recurse ||\n      comadd || zipedit)) {\n    zipwarn(\"can't set method, move, recurse, or comments with copy mode.\",\"\");\n    /* reset flags - needed? */\n    method  = BEST;\n    dispose = 0;\n    recurse = 0;\n    comadd  = 0;\n    zipedit = 0;\n  }\n  if (linkput && dosify)\n    {\n      zipwarn(\"can't use -y with -k, -y ignored\", \"\");\n      linkput = 0;\n    }\n  if (fix == 1 && adjust)\n    {\n      zipwarn(\"can't use -F with -A, -F ignored\", \"\");\n      fix = 0;\n    }\n  if (fix == 2 && adjust)\n    {\n      zipwarn(\"can't use -FF with -A, -FF ignored\", \"\");\n      fix = 0;\n    }\n  if (test && zip_to_stdout) {\n    test = 0;\n    zipwarn(\"can't use -T on stdout, -T ignored\", \"\");\n  }\n  if (split_method && (fix || adjust)) {\n    ZIPERR(ZE_PARMS, \"can't create split archive while fixing or adjusting\\n\");\n  }\n  if (split_method && (d || zip_to_stdout)) {\n    ZIPERR(ZE_PARMS, \"can't create split archive with -d or -g or on stdout\\n\");\n  }\n  if ((action != ADD || d) && filesync) {\n    ZIPERR(ZE_PARMS, \"can't use -d, -f, -u, -U, or -g with filesync -FS\\n\");\n  }\n  if ((action != ADD || d) && zip_to_stdout) {\n    ZIPERR(ZE_PARMS, \"can't use -d, -f, -u, -U, or -g on stdout\\n\");\n  }\n#if defined(EBCDIC)  && !defined(OS390)\n  if (aflag==ASCII && !translate_eol) {\n    /* Translation to ASCII implies EOL translation!\n     * (on OS390, consistent EOL translation is controlled separately)\n     * The default translation mode is \"UNIX\" mode (single LF terminators).\n     */\n    translate_eol = 2;\n  }\n#endif\n#ifdef CMS_MVS\n  if (aflag==ASCII && bflag)\n    ZIPERR(ZE_PARMS, \"can't use -a with -B\");\n#endif\n#ifdef VMS\n  if (!extra_fields && vms_native)\n    {\n      zipwarn(\"can't use -V with -X, -V ignored\", \"\");\n      vms_native = 0;\n    }\n  if (vms_native && translate_eol)\n    ZIPERR(ZE_PARMS, \"can't use -V with -l or -ll\");\n#endif\n\n  if (noisy) {\n    if (fix == 1)\n      zipmessage(\"Fix archive (-F) - assume mostly intact archive\", \"\");\n    else if (fix == 2)\n      zipmessage(\"Fix archive (-FF) - salvage what can\", \"\");\n  }\n\n  /* Read old archive */\n\n  /* Now read the zip file here instead of when doing args above */\n  /* Only read the central directory and build zlist */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Reading archive\\n\");\n    fflush(mesg);\n  }\n\n\n\n\n  /* If -FF we do it all here */\n  if (fix == 2) {\n\n    /* Open zip file and temporary output file */\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Open zip file and create temp file (-FF)\\n\");\n      fflush(mesg);\n    }\n    diag(\"opening zip file and creating temporary zip file\");\n    x = NULL;\n    tempzn = 0;\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Creating new zip file (-FF)\\n\");\n      fflush(mesg);\n    }\n#if defined(UNIX) && !defined(NO_MKSTEMP)\n    {\n      int yd;\n      int i;\n\n      /* use mkstemp to avoid race condition and compiler warning */\n\n      if (tempath != NULL)\n      {\n        /* if -b used to set temp file dir use that for split temp */\n        if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {\n          ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, tempath);\n        if (lastchar(tempzip) != '/')\n          strcat(tempzip, \"/\");\n      }\n      else\n      {\n        /* create path by stripping name and appending template */\n        if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {\n        ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, zipfile);\n        for(i = strlen(tempzip); i > 0; i--) {\n          if (tempzip[i - 1] == '/')\n            break;\n        }\n        tempzip[i] = '\\0';\n      }\n      strcat(tempzip, \"ziXXXXXX\");\n\n      if ((yd = mkstemp(tempzip)) == EOF) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n      if ((y = fdopen(yd, FOPW_TMP)) == NULL) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n    }\n#else\n    if ((tempzip = tempname(zipfile)) == NULL) {\n      ZIPERR(ZE_MEM, \"allocating temp filename\");\n    }\n    if ((y = zfopen(tempzip, FOPW_TMP)) == NULL) {\n      ZIPERR(ZE_TEMP, tempzip);\n    }\n#endif\n\n#if (!defined(VMS) && !defined(CMS_MVS))\n    /* Use large buffer to speed up stdio: */\n#if (defined(_IOFBF) || !defined(BUFSIZ))\n    zipbuf = (char *)malloc(ZBSZ);\n#else\n    zipbuf = (char *)malloc(BUFSIZ);\n#endif\n    if (zipbuf == NULL) {\n      ZIPERR(ZE_MEM, tempzip);\n    }\n# ifdef _IOFBF\n    setvbuf(y, zipbuf, _IOFBF, ZBSZ);\n# else\n    setbuf(y, zipbuf);\n# endif /* _IOBUF */\n#endif /* !VMS  && !CMS_MVS */\n\n\n    if ((r = readzipfile()) != ZE_OK) {\n      ZIPERR(r, zipfile);\n    }\n\n    /* Write central directory and end header to temporary zip */\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Writing central directory (-FF)\\n\");\n      fflush(mesg);\n    }\n    diag(\"writing central directory\");\n    k = 0;                        /* keep count for end header */\n    c = tempzn;                   /* get start of central */\n    n = t = 0;\n    for (z = zfiles; z != NULL; z = z->nxt)\n    {\n      if ((r = putcentral(z)) != ZE_OK) {\n        ZIPERR(r, tempzip);\n      }\n      tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;\n      n += z->len;\n      t += z->siz;\n      k++;\n    }\n    if (zcount == 0)\n      zipwarn(\"zip file empty\", \"\");\n    t = tempzn - c;               /* compute length of central */\n    diag(\"writing end of central directory\");\n    if ((r = putend(k, t, c, zcomlen, zcomment)) != ZE_OK) {\n      ZIPERR(r, tempzip);\n    }\n    if (fclose(y)) {\n      ZIPERR(d ? ZE_WRITE : ZE_TEMP, tempzip);\n    }\n    if (in_file != NULL) {\n      fclose(in_file);\n      in_file = NULL;\n    }\n\n    /* Replace old zip file with new zip file, leaving only the new one */\n    if (strcmp(zipfile, \"-\") && !d)\n    {\n      diag(\"replacing old zip file with new zip file\");\n      if ((r = replace(out_path, tempzip)) != ZE_OK)\n      {\n        zipwarn(\"new zip file left as: \", tempzip);\n        free((zvoid *)tempzip);\n        tempzip = NULL;\n        ZIPERR(r, \"was replacing the original zip file\");\n      }\n      free((zvoid *)tempzip);\n    }\n    tempzip = NULL;\n    if (zip_attributes && strcmp(zipfile, \"-\")) {\n      setfileattr(out_path, zip_attributes);\n#ifdef VMS\n      /* If the zip file existed previously, restore its record format: */\n      if (x != NULL)\n        (void)VMSmunch(out_path, RESTORE_RTYPE, NULL);\n#endif\n    }\n\n    set_filetype(out_path);\n\n    /* finish logfile (it gets closed in freeup() called by finish()) */\n    if (logfile) {\n        struct tm *now;\n        time_t clocktime;\n\n        fprintf(logfile, \"\\nTotal %ld entries (\", files_total);\n        DisplayNumString(logfile, bytes_total);\n        fprintf(logfile, \" bytes)\");\n\n        /* get current time */\n        time(&clocktime);\n        now = localtime(&clocktime);\n        fprintf(logfile, \"\\nDone %s\", asctime(now));\n        fflush(logfile);\n    }\n\n    RETURN(finish(ZE_OK));\n  }\n\n\n\n  /* read zipfile if exists */\n  if ((r = readzipfile()) != ZE_OK) {\n    ZIPERR(r, zipfile);\n  }\n\n#ifndef UTIL\n  if (split_method == -1) {\n    split_method = 0;\n  } else if (!fix && split_method == 0 && total_disks > 1) {\n    /* if input archive is multi-disk and splitting has not been\n       enabled or disabled (split_method == -1), then automatically\n       set split size to same as first input split */\n    zoff_t size = 0;\n\n    in_split_path = get_in_split_path(in_path, 0);\n\n    if (filetime(in_split_path, NULL, &size, NULL) == 0) {\n      zipwarn(\"Could not get info for input split: \", in_split_path);\n      return ZE_OPEN;\n    }\n    split_method = 1;\n    split_size = (uzoff_t) size;\n\n    free(in_split_path);\n    in_split_path = NULL;\n  }\n\n  if (noisy_splits && split_size > 0)\n    zipmessage(\"splitsize = \", zip_fuzofft(split_size, NULL, NULL));\n#endif\n\n  /* so disk display starts at 1, will be updated when entries are read */\n  current_in_disk = 0;\n\n  /* no input zipfile and showing contents */\n  if (!zipfile_exists && show_files && (kk == 3 || action == ARCHIVE)) {\n    ZIPERR(ZE_OPEN, zipfile);\n  }\n\n  if (zcount == 0 && (action != ADD || d)) {\n    zipwarn(zipfile, \" not found or empty\");\n  }\n\n  if (have_out && kk == 3) {\n    /* no input paths so assume copy mode and match everything if --out */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      z->mark = pcount ? filter(z->zname, filter_match_case) : 1;\n    }\n  }\n\n  /* Scan for new files */\n\n  /* Process file arguments from command line */\n  if (filelist) {\n    if (action == ARCHIVE) {\n      /* find in archive */\n      if (show_what_doing) {\n        fprintf(mesg, \"sd: Scanning archive entries\\n\");\n        fflush(mesg);\n      }\n      for (; filelist; ) {\n        if ((r = proc_archive_name(filelist->name, filter_match_case)) != ZE_OK) {\n          if (r == ZE_MISS) {\n            char *n = NULL;\n#ifdef WIN32\n            /* Win9x console always uses OEM character coding, and\n               WinNT console is set to OEM charset by default, too */\n            if ((n = malloc(strlen(filelist->name) + 1)) == NULL)\n              ZIPERR(ZE_MEM, \"name not matched error\");\n            INTERN_TO_OEM(filelist->name, n);\n#else\n            n = filelist->name;\n#endif\n            zipwarn(\"not in archive: \", n);\n#ifdef WIN32\n            free(n);\n#endif\n          }\n          else {\n            ZIPERR(r, filelist->name);\n          }\n        }\n        free(filelist->name);\n        filearg = filelist;\n        filelist = filelist->next;\n        free(filearg);\n      }\n    } else {\n      /* try find matching files on OS first then try find entries in archive */\n      if (show_what_doing) {\n        fprintf(mesg, \"sd: Scanning files\\n\");\n        fflush(mesg);\n      }\n      for (; filelist; ) {\n        if ((r = PROCNAME(filelist->name)) != ZE_OK) {\n          if (r == ZE_MISS) {\n            if (bad_open_is_error) {\n              zipwarn(\"name not matched: \", filelist->name);\n              ZIPERR(ZE_OPEN, filelist->name);\n            } else {\n              zipwarn(\"name not matched: \", filelist->name);\n            }\n          } else {\n            ZIPERR(r, filelist->name);\n          }\n        }\n        free(filelist->name);\n        filearg = filelist;\n        filelist = filelist->next;\n        free(filearg);\n      }\n    }\n  }\n\n  /* recurse from current directory for -R */\n  if (recurse == 2) {\n#ifdef AMIGA\n    if ((r = PROCNAME(\"\")) != ZE_OK)\n#else\n    if ((r = PROCNAME(\".\")) != ZE_OK)\n#endif\n    {\n      if (r == ZE_MISS) {\n        if (bad_open_is_error) {\n          zipwarn(\"name not matched: \", \"current directory for -R\");\n          ZIPERR(ZE_OPEN, \"-R\");\n        } else {\n          zipwarn(\"name not matched: \", \"current directory for -R\");\n        }\n      } else {\n        ZIPERR(r, \"-R\");\n      }\n    }\n  }\n\n\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Applying filters\\n\");\n    fflush(mesg);\n  }\n  /* Clean up selections (\"3 <= kk <= 5\" now) */\n  if (kk != 4 && first_listarg == 0 &&\n      (action == UPDATE || action == FRESHEN)) {\n    /* if -u or -f with no args, do all, but, when present, apply filters */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      z->mark = pcount ? filter(z->zname, filter_match_case) : 1;\n#ifdef DOS\n      if (z->mark) z->dosflag = 1;      /* force DOS attribs for incl. names */\n#endif\n    }\n  }\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Checking dups\\n\");\n    fflush(mesg);\n  }\n  if ((r = check_dup()) != ZE_OK) {     /* remove duplicates in found list */\n    if (r == ZE_PARMS) {\n      ZIPERR(r, \"cannot repeat names in zip file\");\n    }\n    else {\n      ZIPERR(r, \"was processing list of files\");\n    }\n  }\n\n  if (zcount)\n    free((zvoid *)zsort);\n\n\n/*\n * XXX make some kind of mktemppath() function for each OS.\n */\n\n#ifndef VM_CMS\n/* For CMS, leave tempath NULL.  A-disk will be used as default. */\n  /* If -b not specified, make temporary path the same as the zip file */\n#if defined(MSDOS) || defined(__human68k__) || defined(AMIGA)\n  if (tempath == NULL && ((p = MBSRCHR(zipfile, '/')) != NULL ||\n#  ifdef MSDOS\n                          (p = MBSRCHR(zipfile, '\\\\')) != NULL ||\n#  endif /* MSDOS */\n                          (p = MBSRCHR(zipfile, ':')) != NULL))\n  {\n    if (*p == ':')\n      p++;\n#else\n#ifdef RISCOS\n  if (tempath == NULL && (p = MBSRCHR(zipfile, '.')) != NULL)\n  {\n#else\n#ifdef QDOS\n  if (tempath == NULL && (p = LastDir(zipfile)) != NULL)\n  {\n#else\n  if (tempath == NULL && (p = MBSRCHR(zipfile, '/')) != NULL)\n  {\n#endif /* QDOS */\n#endif /* RISCOS */\n#endif /* MSDOS || __human68k__ || AMIGA */\n    if ((tempath = (char *)malloc((int)(p - zipfile) + 1)) == NULL) {\n      ZIPERR(ZE_MEM, \"was processing arguments\");\n    }\n    r = *p;  *p = 0;\n    strcpy(tempath, zipfile);\n    *p = (char)r;\n  }\n#endif /* VM_CMS */\n\n#if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME))\n  if (!zp_tz_is_valid) {\n    zipwarn(\"TZ environment variable not found, cannot use UTC times!!\",\"\");\n  }\n#endif /* IZ_CHECK_TZ && USE_EF_UT_TIME */\n\n  /* For each marked entry, if not deleting, check if it exists, and if\n     updating or freshening, compare date with entry in old zip file.\n     Unmark if it doesn't exist or is too old, else update marked count. */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Scanning files to update\\n\");\n    fflush(mesg);\n  }\n#ifdef MACOS\n  PrintStatProgress(\"Getting file information ...\");\n#endif\n  diag(\"stating marked entries\");\n  k = 0;                        /* Initialize marked count */\n  scan_started = 0;\n  scan_count = 0;\n  all_current = 1;\n  for (z = zfiles; z != NULL; z = z->nxt) {\n    /* if already displayed Scanning files in newname() then continue dots */\n    if (noisy && scan_last) {\n      scan_count++;\n      if (scan_count % 100 == 0) {\n        time_t current = time(NULL);\n\n        if (current - scan_last > scan_dot_time) {\n          if (scan_started == 0) {\n            scan_started = 1;\n            fprintf(mesg, \" \");\n            fflush(mesg);\n          }\n          scan_last = current;\n          fprintf(mesg, \".\");\n          fflush(mesg);\n        }\n      }\n    }\n    z->current = 0;\n    if (!(z->mark)) {\n      /* if something excluded run through the list to catch deletions */\n      all_current = 0;\n    }\n    if (z->mark) {\n#ifdef USE_EF_UT_TIME\n      iztimes f_utim, z_utim;\n      ulg z_tim;\n#endif /* USE_EF_UT_TIME */\n      Trace((stderr, \"zip diagnostics: marked file=%s\\n\", z->oname));\n\n      csize = z->siz;\n      usize = z->len;\n      if (action == DELETE) {\n        /* only delete files in date range */\n#ifdef USE_EF_UT_TIME\n        z_tim = (get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?\n                unix2dostime(&z_utim.mtime) : z->tim;\n#else /* !USE_EF_UT_TIME */\n#       define z_tim  z->tim\n#endif /* ?USE_EF_UT_TIME */\n        if (z_tim < before || (after && z_tim >= after)) {\n          /* include in archive */\n          z->mark = 0;\n        } else {\n          /* delete file */\n          files_total++;\n          /* ignore len in old archive and update to current size */\n          z->len = usize;\n          if (csize != (uzoff_t) -1 && csize != (uzoff_t) -2)\n            bytes_total += csize;\n          k++;\n        }\n      } else if (action == ARCHIVE) {\n        /* only keep files in date range */\n#ifdef USE_EF_UT_TIME\n        z_tim = (get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?\n                unix2dostime(&z_utim.mtime) : z->tim;\n#else /* !USE_EF_UT_TIME */\n#       define z_tim  z->tim\n#endif /* ?USE_EF_UT_TIME */\n        if (z_tim < before || (after && z_tim >= after)) {\n          /* exclude from archive */\n          z->mark = 0;\n        } else {\n          /* keep file */\n          files_total++;\n          /* ignore len in old archive and update to current size */\n          z->len = usize;\n          if (csize != (uzoff_t) -1 && csize != (uzoff_t) -2)\n            bytes_total += csize;\n          k++;\n        }\n      } else {\n        int isdirname = 0;\n\n        if (z->name && (z->name)[strlen(z->name) - 1] == '/') {\n          isdirname = 1;\n        }\n\n# if defined(UNICODE_SUPPORT) && defined(WIN32)\n        if (!no_win32_wide) {\n          if (z->namew == NULL) {\n            if (z->uname != NULL)\n              z->namew = utf8_to_wchar_string(z->uname);\n            else\n              z->namew = local_to_wchar_string(z->name);\n          }\n        }\n# endif\n\n#ifdef USE_EF_UT_TIME\n# if defined(UNICODE_SUPPORT) && defined(WIN32)\n        if (!no_win32_wide)\n          tf = filetimew(z->namew, (ulg *)NULL, (zoff_t *)&usize, &f_utim);\n        else\n          tf = filetime(z->name, (ulg *)NULL, (zoff_t *)&usize, &f_utim);\n# else\n        tf = filetime(z->name, (ulg *)NULL, (zoff_t *)&usize, &f_utim);\n# endif\n#else /* !USE_EF_UT_TIME */\n# if defined(UNICODE_SUPPORT) && defined(WIN32)\n        if (!no_win32_wide)\n          tf = filetimew(z->namew, (ulg *)NULL, (zoff_t *)&usize, NULL);\n        else\n          tf = filetime(z->name, (ulg *)NULL, (zoff_t *)&usize, NULL);\n# else\n        tf = filetime(z->name, (ulg *)NULL, (zoff_t *)&usize, NULL);\n# endif\n#endif /* ?USE_EF_UT_TIME */\n        if (tf == 0)\n          /* entry that is not on OS */\n          all_current = 0;\n        if (tf == 0 ||\n            tf < before || (after && tf >= after) ||\n            ((action == UPDATE || action == FRESHEN) &&\n#ifdef USE_EF_UT_TIME\n             ((get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?\n              f_utim.mtime <= ROUNDED_TIME(z_utim.mtime) : tf <= z->tim)\n#else /* !USE_EF_UT_TIME */\n             tf <= z->tim\n#endif /* ?USE_EF_UT_TIME */\n           ))\n        {\n          z->mark = comadd ? 2 : 0;\n          z->trash = tf && tf >= before &&\n                     (after ==0 || tf < after);   /* delete if -um or -fm */\n          if (verbose)\n            fprintf(mesg, \"zip diagnostic: %s %s\\n\", z->oname,\n                   z->trash ? \"up to date\" : \"missing or early\");\n          if (logfile)\n            fprintf(logfile, \"zip diagnostic: %s %s\\n\", z->oname,\n                   z->trash ? \"up to date\" : \"missing or early\");\n        }\n        else if (diff_mode && tf == z->tim &&\n                 ((isdirname && (zoff_t)usize == -1) || (usize == z->len))) {\n          /* if in diff mode only include if file time or size changed */\n          /* usize is -1 for directories */\n          z->mark = 0;\n        }\n        else {\n          /* usize is -1 for directories and -2 for devices */\n          if (tf == z->tim &&\n              ((z->len == 0 && (zoff_t)usize == -1)\n               || usize == z->len)) {\n            /* FileSync uses the current flag */\n            /* Consider an entry current if file time is the same\n               and entry size is 0 and a directory on the OS\n               or the entry size matches the OS size */\n            z->current = 1;\n          } else {\n            all_current = 0;\n          }\n          files_total++;\n          if (usize != (uzoff_t) -1 && usize != (uzoff_t) -2)\n            /* ignore len in old archive and update to current size */\n            z->len = usize;\n          else\n            z->len = 0;\n          if (usize != (uzoff_t) -1 && usize != (uzoff_t) -2)\n            bytes_total += usize;\n          k++;\n        }\n      }\n    }\n  }\n\n  /* Remove entries from found list that do not exist or are too old */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: fcount = %u\\n\", (unsigned)fcount);\n    fflush(mesg);\n  }\n\n  diag(\"stating new entries\");\n  scan_count = 0;\n  scan_started = 0;\n  Trace((stderr, \"zip diagnostic: fcount=%u\\n\", (unsigned)fcount));\n  for (f = found; f != NULL;) {\n    Trace((stderr, \"zip diagnostic: new file=%s\\n\", f->oname));\n\n    if (noisy) {\n      /* if updating archive and update was quick, scanning for new files\n         can still take a long time */\n      if (!zip_to_stdout && scan_last == 0 && scan_count % 100 == 0) {\n        time_t current = time(NULL);\n\n        if (current - scan_start > scan_delay) {\n          fprintf(mesg, \"Scanning files \");\n          fflush(mesg);\n          mesg_line_started = 1;\n          scan_last = current;\n        }\n      }\n      /* if already displayed Scanning files in newname() or above then continue dots */\n      if (scan_last) {\n        scan_count++;\n        if (scan_count % 100 == 0) {\n          time_t current = time(NULL);\n\n          if (current - scan_last > scan_dot_time) {\n            if (scan_started == 0) {\n              scan_started = 1;\n              fprintf(mesg, \" \");\n              fflush(mesg);\n            }\n            scan_last = current;\n            fprintf(mesg, \".\");\n            fflush(mesg);\n          }\n        }\n      }\n    }\n    tf = 0;\n    if (action != DELETE && action != FRESHEN) {\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n      if (!no_win32_wide)\n        tf = filetimew(f->namew, (ulg *)NULL, (zoff_t *)&usize, NULL);\n      else\n        tf = filetime(f->name, (ulg *)NULL, (zoff_t *)&usize, NULL);\n#else\n      tf = filetime(f->name, (ulg *)NULL, (zoff_t *)&usize, NULL);\n#endif\n    }\n\n    if (action == DELETE || action == FRESHEN ||\n        tf == 0 ||\n        tf < before || (after && tf >= after) ||\n        (namecmp(f->zname, zipfile) == 0 && !zip_to_stdout)\n       )\n      f = fexpel(f);\n    else {\n      /* ??? */\n      files_total++;\n      f->usize = 0;\n      if (usize != (uzoff_t) -1 && usize != (uzoff_t) -2) {\n        bytes_total += usize;\n        f->usize = usize;\n      }\n      f = f->nxt;\n    }\n  }\n  if (mesg_line_started) {\n    fprintf(mesg, \"\\n\");\n    mesg_line_started = 0;\n  }\n#ifdef MACOS\n  PrintStatProgress(\"done\");\n#endif\n\n  if (show_files) {\n    uzoff_t count = 0;\n    uzoff_t bytes = 0;\n\n    if (noisy) {\n      fflush(mesg);\n    }\n\n    if (noisy && (show_files == 1 || show_files == 3 || show_files == 5)) {\n      /* sf, su, sU */\n      if (mesg_line_started) {\n        fprintf(mesg, \"\\n\");\n        mesg_line_started = 0;\n      }\n      if (kk == 3)\n        /* -sf alone */\n        fprintf(mesg, \"Archive contains:\\n\");\n      else if (action == DELETE)\n        fprintf(mesg, \"Would Delete:\\n\");\n      else if (action == FRESHEN)\n        fprintf(mesg, \"Would Freshen:\\n\");\n      else if (action == ARCHIVE)\n        fprintf(mesg, \"Would Copy:\\n\");\n      else\n        fprintf(mesg, \"Would Add/Update:\\n\");\n      fflush(mesg);\n    }\n\n    if (logfile) {\n      if (logfile_line_started) {\n        fprintf(logfile, \"\\n\");\n        logfile_line_started = 0;\n      }\n      if (kk == 3)\n        /* -sf alone */\n        fprintf(logfile, \"Archive contains:\\n\");\n      else if (action == DELETE)\n        fprintf(logfile, \"Would Delete:\\n\");\n      else if (action == FRESHEN)\n        fprintf(logfile, \"Would Freshen:\\n\");\n      else if (action == ARCHIVE)\n        fprintf(logfile, \"Would Copy:\\n\");\n      else\n        fprintf(logfile, \"Would Add/Update:\\n\");\n      fflush(logfile);\n    }\n\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (z->mark || kk == 3) {\n        count++;\n        if ((zoff_t)z->len > 0)\n          bytes += z->len;\n        if (noisy && (show_files == 1 || show_files == 3))\n          /* sf, su */\n          fprintf(mesg, \"  %s\\n\", z->oname);\n        if (logfile && !(show_files == 5 || show_files == 6))\n          /* not sU or sU- show normal name in log */\n          fprintf(logfile, \"  %s\\n\", z->oname);\n\n#ifdef UNICODE_TEST\n        if (create_files) {\n          int r;\n          int dir = 0;\n          FILE *f;\n\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n          char *fn = NULL;\n          wchar_t *fnw = NULL;\n\n          if (!no_win32_wide) {\n            if ((fnw = malloc((wcslen(z->znamew) + 120) * sizeof(wchar_t))) == NULL)\n              ZIPERR(ZE_MEM, \"sC\");\n            wcscpy(fnw, L\"testdir/\");\n            wcscat(fnw, z->znamew);\n            if (fnw[wcslen(fnw) - 1] == '/')\n              dir = 1;\n            if (dir)\n              r = _wmkdir(fnw);\n            else\n              f = _wfopen(fnw, L\"w\");\n          } else {\n            if ((fn = malloc(strlen(z->zname) + 120)) == NULL)\n              ZIPERR(ZE_MEM, \"sC\");\n            strcpy(fn, \"testdir/\");\n            strcat(fn, z->zname);\n            if (fn[strlen(fn) - 1] == '/')\n              dir = 1;\n            if (dir)\n              r = mkdir(fn);\n            else\n              f = fopen(fn, \"w\");\n          }\n#else\n          char *fn = NULL;\n          if ((fn = malloc(strlen(z->zname) + 120)) == NULL)\n            ZIPERR(ZE_MEM, \"sC\");\n          strcpy(fn, \"testdir/\");\n          if (z->uname)\n            strcat(fn, z->uname);\n          else\n            strcat(fn, z->zname);\n\n          if (fn[strlen(fn) - 1] == '/')\n            dir = 1;\n          if (dir)\n            r = mkdir(fn, 0777);\n          else\n            f = fopen(fn, \"w\");\n#endif\n          if (dir) {\n            if (r) {\n              if (errno != 17) {\n                printf(\" - could not create directory testdir/%s\\n\", z->oname);\n                perror(\"    dir\");\n              }\n            } else {\n              printf(\" - created directory testdir/%s\\n\", z->oname);\n            }\n          } else {\n            if (f == NULL) {\n              printf(\" - could not open testdir/%s\\n\", z->oname);\n              perror(\"    file\");\n            } else {\n              fclose(f);\n              printf(\" - created testdir/%s\\n\", z->oname);\n              if (z->uname)\n                printf(\"   u - created testdir/%s\\n\", z->uname);\n            }\n          }\n        }\n#endif\n#ifdef UNICODE_SUPPORT\n        if (show_files == 3 || show_files == 4) {\n          /* su, su- */\n          /* Include escaped Unicode name if exists under standard name */\n          if (z->ouname) {\n            if (noisy && show_files == 3)\n              fprintf(mesg, \"     Escaped Unicode:  %s\\n\", z->ouname);\n            if (logfile)\n              fprintf(logfile, \"     Escaped Unicode:  %s\\n\", z->ouname);\n          }\n        }\n        if (show_files == 5 || show_files == 6) {\n          /* sU, sU- */\n          /* Display only escaped Unicode name if exists or standard name */\n          if (z->ouname) {\n            /* Unicode name */\n            if (noisy && show_files == 5) {\n              fprintf(mesg, \"  %s\\n\", z->ouname);\n            }\n            if (logfile) {\n              fprintf(logfile, \"  %s\\n\", z->ouname);\n            }\n          } else {\n            /* No Unicode name so use standard name */\n            if (noisy && show_files == 5) {\n              fprintf(mesg, \"  %s\\n\", z->oname);\n            }\n            if (logfile) {\n              fprintf(logfile, \"  %s\\n\", z->oname);\n            }\n          }\n        }\n#endif\n      }\n    }\n    for (f = found; f != NULL; f = f->nxt) {\n      count++;\n      if ((zoff_t)f->usize > 0)\n        bytes += f->usize;\n#ifdef UNICODE_SUPPORT\n      if (unicode_escape_all) {\n        char *escaped_unicode;\n        escaped_unicode = local_to_escape_string(f->zname);\n        if (noisy && (show_files == 1 || show_files == 3 || show_files == 5))\n          /* sf, su, sU */\n          fprintf(mesg, \"  %s\\n\", escaped_unicode);\n        if (logfile)\n          fprintf(logfile, \"  %s\\n\", escaped_unicode);\n        free(escaped_unicode);\n      } else {\n#endif\n        if (noisy && (show_files == 1 || show_files == 3 || show_files == 5))\n          /* sf, su, sU */\n          fprintf(mesg, \"  %s\\n\", f->oname);\n        if (logfile)\n          fprintf(logfile, \"  %s\\n\", f->oname);\n#ifdef UNICODE_SUPPORT\n      }\n#endif\n    }\n    if (noisy || logfile == NULL)\n      fprintf(mesg, \"Total %s entries (%s bytes)\\n\",\n                                          zip_fuzofft(count, NULL, NULL),\n                                          zip_fuzofft(bytes, NULL, NULL));\n    if (logfile)\n      fprintf(logfile, \"Total %s entries (%s bytes)\\n\",\n                                          zip_fuzofft(count, NULL, NULL),\n                                          zip_fuzofft(bytes, NULL, NULL));\n    RETURN(finish(ZE_OK));\n  }\n\n  /* Make sure there's something left to do */\n  if (k == 0 && found == NULL && !diff_mode &&\n      !(zfiles == NULL && allow_empty_archive) &&\n      !(zfiles != NULL &&\n        (latest || fix || adjust || junk_sfx || comadd || zipedit))) {\n    if (test && (zfiles != NULL || zipbeg != 0)) {\n#ifndef WINDLL\n      check_zipfile(zipfile, argv[0]);\n#endif\n      RETURN(finish(ZE_OK));\n    }\n    if (action == UPDATE || action == FRESHEN) {\n      RETURN(finish(ZE_NONE));\n    }\n    else if (zfiles == NULL && (latest || fix || adjust || junk_sfx)) {\n      ZIPERR(ZE_NAME, zipfile);\n    }\n#ifndef WINDLL\n    else if (recurse && (pcount == 0) && (first_listarg > 0)) {\n#ifdef VMS\n      strcpy(errbuf, \"try: zip \\\"\");\n      for (i = 1; i < (first_listarg - 1); i++)\n        strcat(strcat(errbuf, args[i]), \"\\\" \");\n      strcat(strcat(errbuf, args[i]), \" *.* -i\");\n#else /* !VMS */\n      strcpy(errbuf, \"try: zip\");\n      for (i = 1; i < first_listarg; i++)\n        strcat(strcat(errbuf, \" \"), args[i]);\n#  ifdef AMIGA\n      strcat(errbuf, \" \\\"\\\" -i\");\n#  else\n      strcat(errbuf, \" . -i\");\n#  endif\n#endif /* ?VMS */\n      for (i = first_listarg; i < argc; i++)\n        strcat(strcat(errbuf, \" \"), args[i]);\n      ZIPERR(ZE_NONE, errbuf);\n    }\n    else {\n      ZIPERR(ZE_NONE, zipfile);\n    }\n#endif /* !WINDLL */\n  }\n\n  if (filesync && all_current && fcount == 0) {\n    zipmessage(\"Archive is current\", \"\");\n    RETURN(finish(ZE_OK));\n  }\n\n  d = (d && k == 0 && (zipbeg || zfiles != NULL)); /* d true if appending */\n\n#if CRYPT\n  /* Initialize the crc_32_tab pointer, when encryption was requested. */\n  if (key != NULL) {\n    crc_32_tab = get_crc_table();\n#ifdef EBCDIC\n    /* convert encryption key to ASCII (ISO variant for 8-bit ASCII chars) */\n    strtoasc(key, key);\n#endif /* EBCDIC */\n  }\n#endif /* CRYPT */\n\n  /* Just ignore the spanning signature if a multi-disk archive */\n  if (zfiles && total_disks != 1 && zipbeg == 4) {\n    zipbeg = 0;\n  }\n\n  /* Before we get carried away, make sure zip file is writeable. This\n   * has the undesired side effect of leaving one empty junk file on a WORM,\n   * so when the zipfile does not exist already and when -b is specified,\n   * the writability check is made in replace().\n   */\n  if (strcmp(zipfile, \"-\"))\n  {\n    if (tempdir && zfiles == NULL && zipbeg == 0) {\n      zip_attributes = 0;\n    } else {\n      x = (have_out || (zfiles == NULL && zipbeg == 0)) ? zfopen(out_path, FOPW) :\n                                                          zfopen(out_path, FOPM);\n      /* Note: FOPW and FOPM expand to several parameters for VMS */\n      if (x == NULL) {\n        ZIPERR(ZE_CREAT, out_path);\n      }\n      fclose(x);\n      zip_attributes = getfileattr(out_path);\n      if (zfiles == NULL && zipbeg == 0)\n        destroy(out_path);\n    }\n  }\n  else\n    zip_attributes = 0;\n\n  /* Throw away the garbage in front of the zip file for -J */\n  if (junk_sfx) zipbeg = 0;\n\n  /* Open zip file and temporary output file */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Open zip file and create temp file\\n\");\n    fflush(mesg);\n  }\n  diag(\"opening zip file and creating temporary zip file\");\n  x = NULL;\n  tempzn = 0;\n  if (strcmp(zipfile, \"-\") == 0)\n  {\n#ifdef MSDOS\n    /* It is nonsense to emit the binary data stream of a zipfile to\n     * the (text mode) console.  This case should already have been caught\n     * in a call to zipstdout() far above.  Therefore, if the following\n     * failsafe check detects a console attached to stdout, zip is stopped\n     * with an \"internal logic error\"!  */\n    if (isatty(fileno(stdout)))\n      ZIPERR(ZE_LOGIC, \"tried to write binary zipfile data to console!\");\n    /* Set stdout mode to binary for MSDOS systems */\n#  ifdef __HIGHC__\n    setmode(stdout, _BINARY);\n#  else\n    setmode(fileno(stdout), O_BINARY);\n#  endif\n    y = zfdopen(fileno(stdout), FOPW);\n#else\n    y = stdout;\n#endif\n    /* tempzip must be malloced so a later free won't barf */\n    tempzip = malloc(4);\n    if (tempzip == NULL) {\n      ZIPERR(ZE_MEM, \"allocating temp filename\");\n    }\n    strcpy(tempzip, \"-\");\n  }\n  else if (d) /* d true if just appending (-g) */\n  {\n    if (total_disks > 1) {\n      ZIPERR(ZE_PARMS, \"cannot grow split archive\");\n    }\n    if ((y = zfopen(zipfile, FOPM)) == NULL) {\n      ZIPERR(ZE_NAME, zipfile);\n    }\n    tempzip = zipfile;\n    /*\n    tempzf = y;\n    */\n\n    if (zfseeko(y, cenbeg, SEEK_SET)) {\n      ZIPERR(ferror(y) ? ZE_READ : ZE_EOF, zipfile);\n    }\n    bytes_this_split = cenbeg;\n    tempzn = cenbeg;\n  }\n  else\n  {\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Creating new zip file\\n\");\n      fflush(mesg);\n    }\n    /* See if there is something at beginning of disk 1 to copy.\n       If not, do nothing as zipcopy() will open files to read\n       as needed. */\n    if (zipbeg) {\n      in_split_path = get_in_split_path(in_path, 0);\n\n      while ((in_file = zfopen(in_split_path, FOPR_EX)) == NULL) {\n        /* could not open split */\n\n        /* Ask for directory with split.  Updates in_path */\n        if (ask_for_split_read_path(0) != ZE_OK) {\n          ZIPERR(ZE_ABORT, \"could not open archive to read\");\n        }\n        free(in_split_path);\n        in_split_path = get_in_split_path(in_path, 1);\n      }\n    }\n#if defined(UNIX) && !defined(NO_MKSTEMP)\n    {\n      int yd;\n      int i;\n\n      /* use mkstemp to avoid race condition and compiler warning */\n\n      if (tempath != NULL)\n      {\n        /* if -b used to set temp file dir use that for split temp */\n        if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {\n          ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, tempath);\n        if (lastchar(tempzip) != '/')\n          strcat(tempzip, \"/\");\n      }\n      else\n      {\n        /* create path by stripping name and appending template */\n        if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {\n        ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, zipfile);\n        for(i = strlen(tempzip); i > 0; i--) {\n          if (tempzip[i - 1] == '/')\n            break;\n        }\n        tempzip[i] = '\\0';\n      }\n      strcat(tempzip, \"ziXXXXXX\");\n\n      if ((yd = mkstemp(tempzip)) == EOF) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n      if ((y = fdopen(yd, FOPW_TMP)) == NULL) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n    }\n#else\n    if ((tempzip = tempname(zipfile)) == NULL) {\n      ZIPERR(ZE_MEM, \"allocating temp filename\");\n    }\n    if ((y = zfopen(tempzip, FOPW_TMP)) == NULL) {\n      ZIPERR(ZE_TEMP, tempzip);\n    }\n#endif\n  }\n\n#if (!defined(VMS) && !defined(CMS_MVS))\n  /* Use large buffer to speed up stdio: */\n#if (defined(_IOFBF) || !defined(BUFSIZ))\n  zipbuf = (char *)malloc(ZBSZ);\n#else\n  zipbuf = (char *)malloc(BUFSIZ);\n#endif\n  if (zipbuf == NULL) {\n    ZIPERR(ZE_MEM, tempzip);\n  }\n# ifdef _IOFBF\n  setvbuf(y, zipbuf, _IOFBF, ZBSZ);\n# else\n  setbuf(y, zipbuf);\n# endif /* _IOBUF */\n#endif /* !VMS  && !CMS_MVS */\n\n  /* If not seekable set some flags 3/14/05 EG */\n  output_seekable = 1;\n  if (!is_seekable(y)) {\n    output_seekable = 0;\n    use_descriptors = 1;\n  }\n\n  /* Not needed.  Only need Zip64 when input file is larger than 2 GB or reading\n     stdin and writing stdout.  This is set in putlocal() for each file. */\n#if 0\n  /* If using descriptors and Zip64 enabled force Zip64 3/13/05 EG */\n# ifdef ZIP64_SUPPORT\n  if (use_descriptors && force_zip64 != 0) {\n    force_zip64 = 1;\n  }\n# endif\n#endif\n\n  /* if archive exists, not streaming and not deleting or growing, copy\n     any bytes at beginning */\n  if (strcmp(zipfile, \"-\") != 0 && !d)  /* this must go *after* set[v]buf */\n  {\n    /* copy anything before archive */\n    if (in_file && zipbeg && (r = bfcopy(zipbeg)) != ZE_OK) {\n      ZIPERR(r, r == ZE_TEMP ? tempzip : zipfile);\n    }\n    if (in_file) {\n      fclose(in_file);\n      in_file = NULL;\n      free(in_split_path);\n    }\n    tempzn = zipbeg;\n    if (split_method) {\n      /* add spanning signature */\n      if (show_what_doing) {\n        fprintf(mesg, \"sd: Adding spanning/splitting signature at top of archive\\n\");\n        fflush(mesg);\n      }\n      /* write the spanning signature at the top of the archive */\n      errbuf[0] = 0x50 /*'P' except for EBCDIC*/;\n      errbuf[1] = 0x4b /*'K' except for EBCDIC*/;\n      errbuf[2] = 7;\n      errbuf[3] = 8;\n      bfwrite(errbuf, 1, 4, BFWRITE_DATA);\n      /* tempzn updated below */\n      tempzn += 4;\n    }\n  }\n\n  o = 0;                                /* no ZE_OPEN errors yet */\n\n\n  /* Process zip file, updating marked files */\n#ifdef DEBUG\n  if (zfiles != NULL)\n    diag(\"going through old zip file\");\n#endif\n  if (zfiles != NULL && show_what_doing) {\n    fprintf(mesg, \"sd: Going through old zip file\\n\");\n    fflush(mesg);\n  }\n  w = &zfiles;\n  while ((z = *w) != NULL) {\n    if (z->mark == 1)\n    {\n      uzoff_t len;\n      if ((zoff_t)z->len == -1)\n        /* device */\n        len = 0;\n      else\n        len = z->len;\n\n      /* if not deleting, zip it up */\n      if (action != ARCHIVE && action != DELETE)\n      {\n        struct zlist far *localz; /* local header */\n\n        if (verbose || !(filesync && z->current))\n          DisplayRunningStats();\n        if (noisy)\n        {\n          if (action == FRESHEN) {\n            fprintf(mesg, \"freshening: %s\", z->oname);\n            mesg_line_started = 1;\n            fflush(mesg);\n          } else if (filesync && z->current) {\n            if (verbose) {\n              fprintf(mesg, \"      ok: %s\", z->oname);\n              mesg_line_started = 1;\n              fflush(mesg);\n            }\n          } else if (!(filesync && z->current)) {\n            fprintf(mesg, \"updating: %s\", z->oname);\n            mesg_line_started = 1;\n            fflush(mesg);\n          }\n        }\n        if (logall)\n        {\n          if (action == FRESHEN) {\n            fprintf(logfile, \"freshening: %s\", z->oname);\n            logfile_line_started = 1;\n            fflush(logfile);\n          } else if (filesync && z->current) {\n            if (verbose) {\n              fprintf(logfile, \" current: %s\", z->oname);\n              logfile_line_started = 1;\n              fflush(logfile);\n            }\n          } else {\n            fprintf(logfile, \"updating: %s\", z->oname);\n            logfile_line_started = 1;\n            fflush(logfile);\n          }\n        }\n\n        /* Get local header flags and extra fields */\n        if (readlocal(&localz, z) != ZE_OK) {\n          zipwarn(\"could not read local entry information: \", z->oname);\n          z->lflg = z->flg;\n          z->ext = 0;\n        } else {\n          z->lflg = localz->lflg;\n          z->ext = localz->ext;\n          z->extra = localz->extra;\n          if (localz->nam) free(localz->iname);\n          if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n          if (localz->uname) free(localz->uname);\n#endif\n          free(localz);\n        }\n\n        if (!(filesync && z->current) &&\n             (r = zipup(z)) != ZE_OK && r != ZE_OPEN && r != ZE_MISS)\n        {\n          zipmessage_nl(\"\", 1);\n          /*\n          if (noisy)\n          {\n            if (mesg_line_started) {\n#if (!defined(MACOS) && !defined(WINDLL))\n              putc('\\n', mesg);\n              fflush(mesg);\n#else\n              fprintf(stdout, \"\\n\");\n              fflush(stdout);\n#endif\n              mesg_line_started = 0;\n            }\n          }\n          if (logall) {\n            if (logfile_line_started) {\n              fprintf(logfile, \"\\n\");\n              logfile_line_started = 0;\n              fflush(logfile);\n            }\n          }\n          */\n          sprintf(errbuf, \"was zipping %s\", z->name);\n          ZIPERR(r, errbuf);\n        }\n        if (filesync && z->current)\n        {\n          /* if filesync if entry matches OS just copy */\n          if ((r = zipcopy(z)) != ZE_OK)\n          {\n            sprintf(errbuf, \"was copying %s\", z->oname);\n            ZIPERR(r, errbuf);\n          }\n          zipmessage_nl(\"\", 1);\n          /*\n          if (noisy)\n          {\n            if (mesg_line_started) {\n#if (!defined(MACOS) && !defined(WINDLL))\n              putc('\\n', mesg);\n              fflush(mesg);\n#else\n              fprintf(stdout, \"\\n\");\n              fflush(stdout);\n#endif\n              mesg_line_started = 0;\n            }\n          }\n          if (logall) {\n            if (logfile_line_started) {\n              fprintf(logfile, \"\\n\");\n              logfile_line_started = 0;\n              fflush(logfile);\n            }\n          }\n          */\n        }\n        if (r == ZE_OPEN || r == ZE_MISS)\n        {\n          o = 1;\n          zipmessage_nl(\"\", 1);\n          /*\n          if (noisy)\n          {\n#if (!defined(MACOS) && !defined(WINDLL))\n            putc('\\n', mesg);\n            fflush(mesg);\n#else\n            fprintf(stdout, \"\\n\");\n#endif\n            mesg_line_started = 0;\n          }\n          if (logall) {\n            fprintf(logfile, \"\\n\");\n            logfile_line_started = 0;\n            fflush(logfile);\n          }\n          */\n          if (r == ZE_OPEN) {\n            perror(z->oname);\n            zipwarn(\"could not open for reading: \", z->oname);\n            if (bad_open_is_error) {\n              sprintf(errbuf, \"was zipping %s\", z->name);\n              ZIPERR(r, errbuf);\n            }\n          } else {\n            zipwarn(\"file and directory with the same name: \", z->oname);\n          }\n          zipwarn(\"will just copy entry over: \", z->oname);\n          if ((r = zipcopy(z)) != ZE_OK)\n          {\n            sprintf(errbuf, \"was copying %s\", z->oname);\n            ZIPERR(r, errbuf);\n          }\n          z->mark = 0;\n        }\n        files_so_far++;\n        good_bytes_so_far += z->len;\n        bytes_so_far += len;\n        w = &z->nxt;\n      }\n      else if (action == ARCHIVE)\n      {\n#ifdef DEBUG\n        zoff_t here = zftello(y);\n#endif\n\n        DisplayRunningStats();\n        if (skip_this_disk - 1 != z->dsk)\n          /* moved to another disk so start copying again */\n          skip_this_disk = 0;\n        if (skip_this_disk - 1 == z->dsk) {\n          /* skipping this disk */\n          if (noisy) {\n            fprintf(mesg, \" skipping: %s\", z->oname);\n            mesg_line_started = 1;\n            fflush(mesg);\n          }\n          if (logall) {\n            fprintf(logfile, \" skipping: %s\", z->oname);\n            logfile_line_started = 1;\n            fflush(logfile);\n          }\n        } else {\n          /* copying this entry */\n          if (noisy) {\n            fprintf(mesg, \" copying: %s\", z->oname);\n            if (display_usize) {\n              fprintf(mesg, \" (\");\n              DisplayNumString(mesg, z->len );\n              fprintf(mesg, \")\");\n            }\n            mesg_line_started = 1;\n            fflush(mesg);\n          }\n          if (logall)\n          {\n            fprintf(logfile, \" copying: %s\", z->oname);\n            if (display_usize) {\n              fprintf(logfile, \" (\");\n              DisplayNumString(logfile, z->len );\n              fprintf(logfile, \")\");\n            }\n            logfile_line_started = 1;\n            fflush(logfile);\n          }\n        }\n\n        if (skip_this_disk - 1 == z->dsk)\n          /* skip entries on this disk */\n          z->mark = 0;\n        else if ((r = zipcopy(z)) != ZE_OK)\n        {\n          if (r == ZE_ABORT) {\n            ZIPERR(r, \"user requested abort\");\n          } else if (fix != 1) {\n            /* exit */\n            sprintf(errbuf, \"was copying %s\", z->oname);\n            zipwarn(\"(try -F to attempt to fix)\", \"\");\n            ZIPERR(r, errbuf);\n          }\n          else /* if (r == ZE_FORM) */ {\n#ifdef DEBUG\n            zoff_t here = zftello(y);\n#endif\n\n            /* seek back in output to start of this entry so can overwrite */\n            if (zfseeko(y, current_local_offset, SEEK_SET) != 0){\n              ZIPERR(r, \"could not seek in output file\");\n            }\n            zipwarn(\"bad - skipping: \", z->oname);\n#ifdef DEBUG\n            here = zftello(y);\n#endif\n            tempzn = current_local_offset;\n            bytes_this_split = current_local_offset;\n          }\n        }\n        if (skip_this_disk || !(fix == 1 && r != ZE_OK))\n        {\n          if (noisy && mesg_line_started) {\n            fprintf(mesg, \"\\n\");\n            mesg_line_started = 0;\n            fflush(mesg);\n          }\n          if (logall && logfile_line_started) {\n            fprintf(logfile, \"\\n\");\n            logfile_line_started = 0;\n            fflush(logfile);\n          }\n        }\n        /* input counts */\n        files_so_far++;\n        if (r != ZE_OK)\n          bad_bytes_so_far += z->siz;\n        else\n          good_bytes_so_far += z->siz;\n        bytes_so_far += z->siz;\n\n        if (r != ZE_OK && fix == 1) {\n          /* remove bad entry from list */\n          v = z->nxt;                     /* delete entry from list */\n          free((zvoid *)(z->iname));\n          free((zvoid *)(z->zname));\n          free(z->oname);\n#ifdef UNICODE_SUPPORT\n          if (z->uname) free(z->uname);\n#endif /* def UNICODE_SUPPORT */\n          if (z->ext)\n            /* don't have local extra until zipcopy reads it */\n            if (z->extra) free((zvoid *)(z->extra));\n          if (z->cext && z->cextra != z->extra)\n            free((zvoid *)(z->cextra));\n          if (z->com)\n            free((zvoid *)(z->comment));\n          farfree((zvoid far *)z);\n          *w = v;\n          zcount--;\n        } else {\n          w = &z->nxt;\n        }\n\n#ifdef WINDLL\n#ifdef ZIP64_SUPPORT\n        /* int64 support in caller */\n        if (lpZipUserFunctions->ServiceApplication64 != NULL)\n        {\n          if ((*lpZipUserFunctions->ServiceApplication64)(z->zname, z->siz))\n                    ZIPERR(ZE_ABORT, \"User terminated operation\");\n        }\n        else\n        {\n          /* no int64 support in caller */\n          filesize64 = z->siz;\n          low = (unsigned long)(filesize64 & 0x00000000FFFFFFFF);\n          high = (unsigned long)((filesize64 >> 32) & 0x00000000FFFFFFFF);\n          if (lpZipUserFunctions->ServiceApplication64_No_Int64 != NULL) {\n            if ((*lpZipUserFunctions->ServiceApplication64_No_Int64)(z->zname, low, high))\n                      ZIPERR(ZE_ABORT, \"User terminated operation\");\n          }\n        }\n#else\n        if (lpZipUserFunctions->ServiceApplication != NULL) {\n          if ((*lpZipUserFunctions->ServiceApplication)(z->zname, z->siz))\n            ZIPERR(ZE_ABORT, \"User terminated operation\");\n        }\n#endif /* ZIP64_SUPPORT - I added comments around // comments - does that help below? EG */\n/* strange but true: if I delete this and put these two endifs adjacent to\n   each other, the Aztec Amiga compiler never sees the second endif!  WTF?? PK */\n#endif /* WINDLL */\n      }\n      else\n      {\n        DisplayRunningStats();\n        if (noisy)\n        {\n          fprintf(mesg, \"deleting: %s\", z->oname);\n          if (display_usize) {\n            fprintf(mesg, \" (\");\n            DisplayNumString(mesg, z->len );\n            fprintf(mesg, \")\");\n          }\n          fflush(mesg);\n          fprintf(mesg, \"\\n\");\n        }\n        if (logall)\n        {\n          fprintf(logfile, \"deleting: %s\", z->oname);\n          if (display_usize) {\n            fprintf(logfile, \" (\");\n            DisplayNumString(logfile, z->len );\n            fprintf(logfile, \")\");\n          }\n          fprintf(logfile, \"\\n\");\n          fflush(logfile);\n        }\n        files_so_far++;\n        good_bytes_so_far += z->siz;\n        bytes_so_far += z->siz;\n#ifdef WINDLL\n#ifdef ZIP64_SUPPORT\n        /* int64 support in caller */\n        if (lpZipUserFunctions->ServiceApplication64 != NULL)\n        {\n          if ((*lpZipUserFunctions->ServiceApplication64)(z->zname, z->siz))\n                    ZIPERR(ZE_ABORT, \"User terminated operation\");\n        }\n        else\n        {\n          /* no int64 support in caller */\n          filesize64 = z->siz;\n          low = (unsigned long)(filesize64 & 0x00000000FFFFFFFF);\n          high = (unsigned long)((filesize64 >> 32) & 0x00000000FFFFFFFF);\n          if (lpZipUserFunctions->ServiceApplication64_No_Int64 != NULL) {\n            if ((*lpZipUserFunctions->ServiceApplication64_No_Int64)(z->zname, low, high))\n                      ZIPERR(ZE_ABORT, \"User terminated operation\");\n          }\n        }\n#else\n        if (lpZipUserFunctions->ServiceApplication != NULL) {\n          if ((*lpZipUserFunctions->ServiceApplication)(z->zname, z->siz))\n            ZIPERR(ZE_ABORT, \"User terminated operation\");\n        }\n#endif /* ZIP64_SUPPORT - I added comments around // comments - does that help below? EG */\n/* strange but true: if I delete this and put these two endifs adjacent to\n   each other, the Aztec Amiga compiler never sees the second endif!  WTF?? PK */\n#endif /* WINDLL */\n\n        v = z->nxt;                     /* delete entry from list */\n        free((zvoid *)(z->iname));\n        free((zvoid *)(z->zname));\n        free(z->oname);\n#ifdef UNICODE_SUPPORT\n        if (z->uname) free(z->uname);\n#endif /* def UNICODE_SUPPORT */\n        if (z->ext)\n          /* don't have local extra until zipcopy reads it */\n          if (z->extra) free((zvoid *)(z->extra));\n        if (z->cext && z->cextra != z->extra)\n          free((zvoid *)(z->cextra));\n        if (z->com)\n          free((zvoid *)(z->comment));\n        farfree((zvoid far *)z);\n        *w = v;\n        zcount--;\n      }\n    }\n    else\n    {\n      if (action == ARCHIVE) {\n        v = z->nxt;                     /* delete entry from list */\n        free((zvoid *)(z->iname));\n        free((zvoid *)(z->zname));\n        free(z->oname);\n#ifdef UNICODE_SUPPORT\n        if (z->uname) free(z->uname);\n#endif /* def UNICODE_SUPPORT */\n        if (z->ext)\n          /* don't have local extra until zipcopy reads it */\n          if (z->extra) free((zvoid *)(z->extra));\n        if (z->cext && z->cextra != z->extra)\n          free((zvoid *)(z->cextra));\n        if (z->com)\n          free((zvoid *)(z->comment));\n        farfree((zvoid far *)z);\n        *w = v;\n        zcount--;\n      }\n      else\n      {\n        if (filesync) {\n          /* Delete entries if don't match a file on OS */\n          BlankRunningStats();\n          if (noisy)\n          {\n            fprintf(mesg, \"deleting: %s\", z->oname);\n            if (display_usize) {\n              fprintf(mesg, \" (\");\n              DisplayNumString(mesg, z->len );\n              fprintf(mesg, \")\");\n            }\n            fflush(mesg);\n            fprintf(mesg, \"\\n\");\n            mesg_line_started = 0;\n          }\n          if (logall)\n          {\n            fprintf(logfile, \"deleting: %s\", z->oname);\n            if (display_usize) {\n              fprintf(logfile, \" (\");\n              DisplayNumString(logfile, z->len );\n              fprintf(logfile, \")\");\n            }\n            fprintf(logfile, \"\\n\");\n            fflush(logfile);\n            logfile_line_started = 0;\n          }\n        }\n        /* copy the original entry */\n        else if (!d && !diff_mode && (r = zipcopy(z)) != ZE_OK)\n        {\n          sprintf(errbuf, \"was copying %s\", z->oname);\n          ZIPERR(r, errbuf);\n        }\n        w = &z->nxt;\n      }\n    }\n  }\n\n\n  /* Process the edited found list, adding them to the zip file */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Zipping up new entries\\n\");\n    fflush(mesg);\n  }\n  diag(\"zipping up new entries, if any\");\n  Trace((stderr, \"zip diagnostic: fcount=%u\\n\", (unsigned)fcount));\n  for (f = found; f != NULL; f = fexpel(f))\n  {\n    uzoff_t len;\n    /* add a new zfiles entry and set the name */\n    if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n      ZIPERR(ZE_MEM, \"was adding files to zip file\");\n    }\n    z->nxt = NULL;\n    z->name = f->name;\n    f->name = NULL;\n#ifdef UNICODE_SUPPORT\n    z->uname = NULL;          /* UTF-8 name for extra field */\n    z->zuname = NULL;         /* externalized UTF-8 name for matching */\n    z->ouname = NULL;         /* display version of UTF-8 name with OEM */\n\n#if 0\n    /* New AppNote bit 11 allowing storing UTF-8 in path */\n    if (utf8_force && f->uname) {\n      if (f->iname)\n        free(f->iname);\n      if ((f->iname = malloc(strlen(f->uname) + 1)) == NULL)\n        ZIPERR(ZE_MEM, \"Unicode bit 11\");\n      strcpy(f->iname, f->uname);\n# ifdef WIN32\n      if (f->inamew)\n        free(f->inamew);\n      f->inamew = utf8_to_wchar_string(f->iname);\n# endif\n    }\n#endif\n\n    /* Only set z->uname if have a non-ASCII Unicode name */\n    /* The Unicode path extra field is created if z->uname is not NULL,\n       unless on a UTF-8 system, then instead of creating the extra field\n       set bit 11 in the General Purpose Bit Flag */\n    {\n      int is_ascii = 0;\n\n# ifdef WIN32\n      if (!no_win32_wide)\n        is_ascii = is_ascii_stringw(f->inamew);\n      else\n        is_ascii = is_ascii_string(f->uname);\n# else\n      is_ascii = is_ascii_string(f->uname);\n# endif\n\n      if (z->uname == NULL) {\n        if (!is_ascii)\n          z->uname = f->uname;\n        else\n          free(f->uname);\n      } else {\n        free(f->uname);\n      }\n    }\n    f->uname = NULL;\n\n#endif\n    z->iname = f->iname;\n    f->iname = NULL;\n    z->zname = f->zname;\n    f->zname = NULL;\n    z->oname = f->oname;\n    f->oname = NULL;\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n    z->namew = f->namew;\n    f->namew = NULL;\n    z->inamew = f->inamew;\n    f->inamew = NULL;\n    z->znamew = f->znamew;\n    f->znamew = NULL;\n#endif\n    z->ext = z->cext = z->com = 0;\n    z->extra = z->cextra = NULL;\n    z->mark = 1;\n    z->dosflag = f->dosflag;\n    /* zip it up */\n    DisplayRunningStats();\n    if (noisy)\n    {\n      fprintf(mesg, \"  adding: %s\", z->oname);\n      mesg_line_started = 1;\n      fflush(mesg);\n    }\n    if (logall)\n    {\n      fprintf(logfile, \"  adding: %s\", z->oname);\n      logfile_line_started = 1;\n      fflush(logfile);\n    }\n    /* initial scan */\n    len = f->usize;\n    if ((r = zipup(z)) != ZE_OK  && r != ZE_OPEN && r != ZE_MISS)\n    {\n      zipmessage_nl(\"\", 1);\n      /*\n      if (noisy)\n      {\n#if (!defined(MACOS) && !defined(WINDLL))\n        putc('\\n', mesg);\n        fflush(mesg);\n#else\n        fprintf(stdout, \"\\n\");\n#endif\n        mesg_line_started = 0;\n        fflush(mesg);\n      }\n      if (logall) {\n        fprintf(logfile, \"\\n\");\n        logfile_line_started = 0;\n        fflush(logfile);\n      }\n      */\n      sprintf(errbuf, \"was zipping %s\", z->oname);\n      ZIPERR(r, errbuf);\n    }\n    if (r == ZE_OPEN || r == ZE_MISS)\n    {\n      o = 1;\n      zipmessage_nl(\"\", 1);\n      /*\n      if (noisy)\n      {\n#if (!defined(MACOS) && !defined(WINDLL))\n        putc('\\n', mesg);\n        fflush(mesg);\n#else\n        fprintf(stdout, \"\\n\");\n#endif\n        mesg_line_started = 0;\n        fflush(mesg);\n      }\n      if (logall) {\n        fprintf(logfile, \"\\n\");\n        logfile_line_started = 0;\n        fflush(logfile);\n      }\n      */\n      if (r == ZE_OPEN) {\n        perror(\"zip warning\");\n        if (logfile)\n          fprintf(logfile, \"zip warning: %s\\n\", strerror(errno));\n        zipwarn(\"could not open for reading: \", z->oname);\n        if (bad_open_is_error) {\n          sprintf(errbuf, \"was zipping %s\", z->name);\n          ZIPERR(r, errbuf);\n        }\n      } else {\n        zipwarn(\"file and directory with the same name: \", z->oname);\n      }\n      files_so_far++;\n      bytes_so_far += len;\n      bad_files_so_far++;\n      bad_bytes_so_far += len;\n      free((zvoid *)(z->name));\n      free((zvoid *)(z->iname));\n      free((zvoid *)(z->zname));\n      free(z->oname);\n#ifdef UNICODE_SUPPORT\n      if (z->uname)\n        free(z->uname);\n# ifdef WIN32\n      if (z->namew)\n        free((zvoid *)(z->namew));\n      if (z->inamew)\n        free((zvoid *)(z->inamew));\n      if (z->znamew)\n        free((zvoid *)(z->znamew));\n# endif\n#endif\n      farfree((zvoid far *)z);\n    }\n    else\n    {\n      files_so_far++;\n      /* current size of file (just before reading) */\n      good_bytes_so_far += z->len;\n      /* size of file on initial scan */\n      bytes_so_far += len;\n      *w = z;\n      w = &z->nxt;\n      zcount++;\n    }\n  }\n  if (key != NULL)\n  {\n    free((zvoid *)key);\n    key = NULL;\n  }\n\n  /* final status 3/17/05 EG */\n  if (noisy && bad_files_so_far)\n  {\n    char tempstrg[100];\n\n    fprintf(mesg, \"\\nzip warning: Not all files were readable\\n\");\n    fprintf(mesg, \"  files/entries read:  %lu\", files_total - bad_files_so_far);\n    WriteNumString(good_bytes_so_far, tempstrg);\n    fprintf(mesg, \" (%s bytes)\", tempstrg);\n    fprintf(mesg, \"  skipped:  %lu\", bad_files_so_far);\n    WriteNumString(bad_bytes_so_far, tempstrg);\n    fprintf(mesg, \" (%s bytes)\\n\", tempstrg);\n    fflush(mesg);\n  }\n  if (logfile && bad_files_so_far)\n  {\n    char tempstrg[100];\n\n    fprintf(logfile, \"\\nzip warning: Not all files were readable\\n\");\n    fprintf(logfile, \"  files/entries read:  %lu\", files_total - bad_files_so_far);\n    WriteNumString(good_bytes_so_far, tempstrg);\n    fprintf(logfile, \" (%s bytes)\", tempstrg);\n    fprintf(logfile, \"  skipped:  %lu\", bad_files_so_far);\n    WriteNumString(bad_bytes_so_far, tempstrg);\n    fprintf(logfile, \" (%s bytes)\", tempstrg);\n  }\n\n  /* Get one line comment for each new entry */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Get comment if any\\n\");\n    fflush(mesg);\n  }\n#if defined(AMIGA) || defined(MACOS)\n  if (comadd || filenotes)\n  {\n    if (comadd)\n#else\n  if (comadd)\n  {\n#endif\n    {\n      if (comment_stream == NULL) {\n#ifndef RISCOS\n        comment_stream = (FILE*)fdopen(fileno(stderr), \"r\");\n#else\n        comment_stream = stderr;\n#endif\n      }\n      if ((e = malloc(MAXCOM + 1)) == NULL) {\n        ZIPERR(ZE_MEM, \"was reading comment lines\");\n      }\n    }\n#ifdef __human68k__\n    setmode(fileno(comment_stream), O_TEXT);\n#endif\n#ifdef MACOS\n    if (noisy) fprintf(mesg, \"\\nStart commenting files ...\\n\");\n#endif\n    for (z = zfiles; z != NULL; z = z->nxt)\n      if (z->mark)\n#if defined(AMIGA) || defined(MACOS)\n        if (filenotes && (p = GetComment(z->zname)))\n        {\n          if (z->comment = malloc(k = strlen(p)+1))\n          {\n            z->com = k;\n            strcpy(z->comment, p);\n          }\n          else\n          {\n            free((zvoid *)e);\n            ZIPERR(ZE_MEM, \"was reading filenotes\");\n          }\n        }\n        else if (comadd)\n#endif /* AMIGA || MACOS */\n        {\n          if (noisy)\n            fprintf(mesg, \"Enter comment for %s:\\n\", z->oname);\n          if (fgets(e, MAXCOM+1, comment_stream) != NULL)\n          {\n            if ((p = malloc((extent)(k = strlen(e))+1)) == NULL)\n            {\n              free((zvoid *)e);\n              ZIPERR(ZE_MEM, \"was reading comment lines\");\n            }\n            strcpy(p, e);\n            if (p[k-1] == '\\n')\n              p[--k] = 0;\n            z->comment = p;\n            /* zip64 support 09/05/2003 R.Nausedat */\n            z->com = (extent)k;\n          }\n        }\n#ifdef MACOS\n    if (noisy) fprintf(mesg, \"\\n...done\");\n#endif\n#if defined(AMIGA) || defined(MACOS)\n    if (comadd)\n      free((zvoid *)e);\n    GetComment(NULL);           /* makes it free its internal storage */\n#else\n    free((zvoid *)e);\n#endif\n  }\n\n  /* Get multi-line comment for the zip file */\n  if (zipedit)\n  {\n#ifndef WINDLL\n    if (comment_stream == NULL) {\n#ifndef RISCOS\n      comment_stream = (FILE*)fdopen(fileno(stderr), \"r\");\n#else\n      comment_stream = stderr;\n#endif\n    }\n    if ((e = malloc(MAXCOM + 1)) == NULL) {\n      ZIPERR(ZE_MEM, \"was reading comment lines\");\n    }\n    if (noisy && zcomlen)\n    {\n      fputs(\"current zip file comment is:\\n\", mesg);\n      fwrite(zcomment, 1, zcomlen, mesg);\n      if (zcomment[zcomlen-1] != '\\n')\n        putc('\\n', mesg);\n      free((zvoid *)zcomment);\n    }\n    if ((zcomment = malloc(1)) == NULL)\n      ZIPERR(ZE_MEM, \"was setting comments to null\");\n    zcomment[0] = '\\0';\n    if (noisy)\n      fputs(\"enter new zip file comment (end with .):\\n\", mesg);\n#if (defined(AMIGA) && (defined(LATTICE)||defined(__SASC)))\n    flushall();  /* tty input/output is out of sync here */\n#endif\n#ifdef __human68k__\n    setmode(fileno(comment_stream), O_TEXT);\n#endif\n#ifdef MACOS\n    printf(\"\\n enter new zip file comment \\n\");\n    if (fgets(e, MAXCOM+1, comment_stream) != NULL) {\n        if ((p = malloc((k = strlen(e))+1)) == NULL) {\n            free((zvoid *)e);\n            ZIPERR(ZE_MEM, \"was reading comment lines\");\n        }\n        strcpy(p, e);\n        if (p[k-1] == '\\n') p[--k] = 0;\n        zcomment = p;\n    }\n#else /* !MACOS */\n    while (fgets(e, MAXCOM+1, comment_stream) != NULL && strcmp(e, \".\\n\"))\n    {\n      if (e[(r = strlen(e)) - 1] == '\\n')\n        e[--r] = 0;\n      if ((p = malloc((*zcomment ? strlen(zcomment) + 3 : 1) + r)) == NULL)\n      {\n        free((zvoid *)e);\n        ZIPERR(ZE_MEM, \"was reading comment lines\");\n      }\n      if (*zcomment)\n        strcat(strcat(strcpy(p, zcomment), \"\\r\\n\"), e);\n      else\n        strcpy(p, *e ? e : \"\\r\\n\");\n      free((zvoid *)zcomment);\n      zcomment = p;\n    }\n#endif /* ?MACOS */\n    free((zvoid *)e);\n#else /* WINDLL */\n    comment(zcomlen);\n    if ((p = malloc(strlen(szCommentBuf)+1)) == NULL) {\n      ZIPERR(ZE_MEM, \"was setting comments to null\");\n    }\n    if (szCommentBuf[0] != '\\0')\n       lstrcpy(p, szCommentBuf);\n    else\n       p[0] = '\\0';\n    free((zvoid *)zcomment);\n    GlobalUnlock(hStr);\n    GlobalFree(hStr);\n    zcomment = p;\n#endif /* WINDLL */\n    zcomlen = strlen(zcomment);\n  }\n\n  if (display_globaldots) {\n#ifndef WINDLL\n    putc('\\n', mesg);\n#else\n    fprintf(stdout,\"%c\",'\\n');\n#endif\n    mesg_line_started = 0;\n  }\n\n  /* Write central directory and end header to temporary zip */\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Writing central directory\\n\");\n    fflush(mesg);\n  }\n  diag(\"writing central directory\");\n  k = 0;                        /* keep count for end header */\n  c = tempzn;                   /* get start of central */\n  n = t = 0;\n  for (z = zfiles; z != NULL; z = z->nxt)\n  {\n    if (z->mark || !(diff_mode || filesync)) {\n      if ((r = putcentral(z)) != ZE_OK) {\n        ZIPERR(r, tempzip);\n      }\n      tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;\n      n += z->len;\n      t += z->siz;\n      k++;\n    }\n  }\n\n  if (k == 0)\n    zipwarn(\"zip file empty\", \"\");\n  if (verbose) {\n    fprintf(mesg, \"total bytes=%s, compressed=%s -> %d%% savings\\n\",\n            zip_fzofft(n, NULL, \"u\"), zip_fzofft(t, NULL, \"u\"), percent(n, t));\n    fflush(mesg);\n  }\n  if (logall) {\n    fprintf(logfile, \"total bytes=%s, compressed=%s -> %d%% savings\\n\",\n            zip_fzofft(n, NULL, \"u\"), zip_fzofft(t, NULL, \"u\"), percent(n, t));\n    fflush(logfile);\n  }\n  t = tempzn - c;               /* compute length of central */\n  diag(\"writing end of central directory\");\n  if (show_what_doing) {\n    fprintf(mesg, \"sd: Writing end of central directory\\n\");\n    fflush(mesg);\n  }\n\n  if ((r = putend(k, t, c, zcomlen, zcomment)) != ZE_OK) {\n    ZIPERR(r, tempzip);\n  }\n\n  /*\n  tempzf = NULL;\n  */\n  if (fclose(y)) {\n    ZIPERR(d ? ZE_WRITE : ZE_TEMP, tempzip);\n  }\n  y = NULL;\n  if (in_file != NULL) {\n    fclose(in_file);\n    in_file = NULL;\n  }\n  /*\n  if (x != NULL)\n    fclose(x);\n  */\n\n  /* Free some memory before spawning unzip */\n#ifdef USE_ZLIB\n  zl_deflate_free();\n#else\n  lm_free();\n#endif\n#ifdef BZIP2_SUPPORT\n  bz_compress_free();\n#endif\n\n#ifndef WINDLL\n  /* Test new zip file before overwriting old one or removing input files */\n  if (test)\n    check_zipfile(tempzip, argv[0]);\n#endif\n  /* Replace old zip file with new zip file, leaving only the new one */\n  if (strcmp(zipfile, \"-\") && !d)\n  {\n    diag(\"replacing old zip file with new zip file\");\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Replacing old zip file\\n\");\n      fflush(mesg);\n    }\n    if ((r = replace(out_path, tempzip)) != ZE_OK)\n    {\n      zipwarn(\"new zip file left as: \", tempzip);\n      free((zvoid *)tempzip);\n      tempzip = NULL;\n      ZIPERR(r, \"was replacing the original zip file\");\n    }\n    free((zvoid *)tempzip);\n  }\n  tempzip = NULL;\n  if (zip_attributes && strcmp(zipfile, \"-\")) {\n    setfileattr(out_path, zip_attributes);\n#ifdef VMS\n    /* If the zip file existed previously, restore its record format: */\n    if (x != NULL)\n      (void)VMSmunch(out_path, RESTORE_RTYPE, NULL);\n#endif\n  }\n  if (strcmp(zipfile, \"-\")) {\n    if (show_what_doing) {\n      fprintf(mesg, \"sd: Setting file type\\n\");\n      fflush(mesg);\n    }\n\n    set_filetype(out_path);\n  }\n\n#if defined(WIN32)\n  /* All looks good so, if requested, clear the DOS archive bits */\n  if (clear_archive_bits) {\n    if (noisy)\n      zipmessage(\"Clearing archive bits...\", \"\");\n    for (z = zfiles; z != NULL; z = z->nxt)\n    {\n# ifdef UNICODE_SUPPORT\n      if (z->mark) {\n        if (!no_win32_wide) {\n          if (!ClearArchiveBitW(z->namew)){\n            zipwarn(\"Could not clear archive bit for: \", z->oname);\n          }\n        } else {\n          if (!ClearArchiveBit(z->name)){\n            zipwarn(\"Could not clear archive bit for: \", z->oname);\n          }\n        }\n      }\n# else\n      if (!ClearArchiveBit(z->name)){\n        zipwarn(\"Could not clear archive bit for: \", z->oname);\n      }\n# endif\n    }\n  }\n#endif\n\n  /* finish logfile (it gets closed in freeup() called by finish()) */\n  if (logfile) {\n      struct tm *now;\n      time_t clocktime;\n\n      fprintf(logfile, \"\\nTotal %ld entries (\", files_total);\n      if (good_bytes_so_far != bytes_total) {\n        fprintf(logfile, \"planned \");\n        DisplayNumString(logfile, bytes_total);\n        fprintf(logfile, \" bytes, actual \");\n        DisplayNumString(logfile, good_bytes_so_far);\n        fprintf(logfile, \" bytes)\");\n      } else {\n        DisplayNumString(logfile, bytes_total);\n        fprintf(logfile, \" bytes)\");\n      }\n\n      /* get current time */\n\n      time(&clocktime);\n      now = localtime(&clocktime);\n      fprintf(logfile, \"\\nDone %s\", asctime(now));\n  }\n\n  /* Finish up (process -o, -m, clean up).  Exit code depends on o. */\n#if (!defined(VMS) && !defined(CMS_MVS))\n  free((zvoid *) zipbuf);\n#endif /* !VMS && !CMS_MVS */\n  RETURN(finish(o ? ZE_OPEN : ZE_OK));\n}\n"
  },
  {
    "path": "deps/infozip/zip30/zip.h",
    "content": "/*\n  zip.h - Zip 3\n\n/---------------------------------------------------------------------/\n\nInfo-ZIP Licence\n\nThis is version 2007-Mar-4 of the Info-ZIP license.\nThe definitive version of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and\na copy at http://www.info-zip.org/pub/infozip/license.html.\n\n\nCopyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n\n   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n   Rich Wales, Mike White.\n\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held liable\nfor any direct, indirect, incidental, special or consequential damages\narising out of the use of or inability to use this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  The sole exception to this condition\n       is redistribution of a standard UnZipSFX binary (including SFXWiz) as\n       part of a self-extracting archive; that is permitted without inclusion\n       of this license, as long as the normal SFX banner has not been removed\n       from the binary or disabled.\n\n    3. Altered versions--including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP--must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases--including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n\n    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"\n       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its\n       own source and binary releases.\n\n/---------------------------------------------------------------------/\n\n*/\n\n/*\n *  zip.h by Mark Adler\n */\n#ifndef __zip_h\n#define __zip_h 1\n\n#define ZIP   /* for crypt.c:  include zip password functions, not unzip */\n\n/* Types centralized here for easy modification */\n#define local static            /* More meaningful outside functions */\ntypedef unsigned char uch;      /* unsigned 8-bit value */\ntypedef unsigned short ush;     /* unsigned 16-bit value */\ntypedef unsigned long ulg;      /* unsigned 32-bit value */\n\n/* Set up portability */\n#include \"tailor.h\"\n\n#ifdef USE_ZLIB\n#  include \"zlib.h\"\n#endif\n\n/* In the utilities, the crc32() function is only used for UNICODE_SUPPORT. */\n#if defined(UTIL) && !defined(UNICODE_SUPPORT)\n#  define CRC_TABLE_ONLY\n#endif\n\n#define MIN_MATCH  3\n#define MAX_MATCH  258\n/* The minimum and maximum match lengths */\n\n#ifndef WSIZE\n#  define WSIZE  (0x8000)\n#endif\n/* Maximum window size = 32K. If you are really short of memory, compile\n * with a smaller WSIZE but this reduces the compression ratio for files\n * of size > WSIZE. WSIZE must be a power of two in the current implementation.\n */\n\n#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)\n/* Minimum amount of lookahead, except at the end of the input file.\n * See deflate.c for comments about the MIN_MATCH+1.\n */\n\n#define MAX_DIST  (WSIZE-MIN_LOOKAHEAD)\n/* In order to simplify the code, particularly on 16 bit machines, match\n * distances are limited to MAX_DIST instead of WSIZE.\n */\n\n/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */\n#ifdef DOS\n#  define FNMAX 256\n#else\n#  define FNMAX 1024\n#endif\n\n#ifndef MATCH\n#  define MATCH shmatch         /* Default for pattern matching: UNIX style */\n#endif\n\n/* Structure carrying extended timestamp information */\ntypedef struct iztimes {\n   time_t atime;                /* new access time */\n   time_t mtime;                /* new modification time */\n   time_t ctime;                /* new creation time (!= Unix st.ctime) */\n} iztimes;\n\n/* Lengths of headers after signatures in bytes */\n#define LOCHEAD 26\n#define CENHEAD 42\n#define ENDHEAD 18\n#define EC64LOC 16\n#define EC64REC 52\n\n/* Structures for in-memory file information */\nstruct zlist {\n  /* See central header in zipfile.c for what vem..off are */\n  /* Do not rearrange these as less than smart coding in zipfile.c\n     in scanzipf_reg() depends on u being set to ver and then stepping\n     through as a byte array.  Ack.  Should be fixed.  5/25/2005 EG */\n  /* All the new read code does not rely on this order.  */\n  ush vem, ver, flg, how;\n  ulg tim, crc;\n  uzoff_t siz, len;             /* zip64 support 08/29/2003 R.Nausedat */\n  /* changed from extent to ush 3/10/2005 EG */\n  ush nam, ext, cext, com;      /* offset of ext must be >= LOCHEAD */\n  ulg dsk;                      /* disk number was ush but now ulg */\n  ush att, lflg;                /* offset of lflg must be >= LOCHEAD */\n  uzoff_t off;\n  ulg atx;\n  char *name;                   /* File name in zip file */\n  char *extra;                  /* Extra field (set only if ext != 0) */\n  char *cextra;                 /* Extra in central (set only if cext != 0) */\n  char *comment;                /* Comment (set only if com != 0) */\n  char *iname;                  /* Internal file name after cleanup (stored in archive) */\n  char *zname;                  /* External version of internal name */\n  char *oname;                  /* Display version of name used in messages */\n#ifdef UNICODE_SUPPORT\n  /* Unicode support */\n  char *uname;                  /* UTF-8 version of iname */\n  /* if uname has chars not in local char set, zuname can be different than zname */\n  char *zuname;                 /* Escaped Unicode zname from uname */\n  char *ouname;                 /* Display version of zuname */\n# ifdef WIN32\n  char *wuname;                 /* Converted back ouname for Win32 */\n  wchar_t *namew;               /* Windows wide character version of name */\n  wchar_t *inamew;              /* Windows wide character version of iname */\n  wchar_t *znamew;              /* Windows wide character version of zname */\n# endif\n#endif\n  int mark;                     /* Marker for files to operate on */\n  int trash;                    /* Marker for files to delete */\n  int current;                  /* Marker for files that are current to what is on OS (filesync) */\n  int dosflag;                  /* Set to force MSDOS file attributes */\n  struct zlist far *nxt;        /* Pointer to next header in list */\n};\nstruct flist {\n  char *name;                   /* Raw internal file name */\n  char *iname;                  /* Internal file name after cleanup */\n  char *zname;                  /* External version of internal name */\n  char *oname;                  /* Display version of internal name */\n#ifdef UNICODE_SUPPORT\n  char *uname;                  /* UTF-8 name */\n# ifdef WIN32\n  wchar_t *namew;               /* Windows wide character version of name */\n  wchar_t *inamew;              /* Windows wide character version of iname */\n  wchar_t *znamew;              /* Windows wide character version of zname */\n# endif\n#endif\n  int dosflag;                  /* Set to force MSDOS file attributes */\n  uzoff_t usize;                /* usize from initial scan */\n  struct flist far *far *lst;   /* Pointer to link pointing here */\n  struct flist far *nxt;        /* Link to next name */\n};\nstruct plist {\n  char *zname;                  /* External version of internal name */\n  int select;                   /* Selection flag ('i' or 'x') */\n};\n\n/* internal file attribute */\n#define UNKNOWN (-1)\n#define BINARY  0\n#define ASCII   1\n#define __EBCDIC 2\n\n/* extra field definitions */\n#define EF_VMCMS     0x4704   /* VM/CMS Extra Field ID (\"G\")*/\n#define EF_MVS       0x470f   /* MVS Extra Field ID (\"G\")   */\n#define EF_IZUNIX    0x5855   /* UNIX Extra Field ID (\"UX\") */\n#define EF_IZUNIX2   0x7855   /* Info-ZIP's new Unix (\"Ux\") */\n#define EF_TIME      0x5455   /* universal timestamp (\"UT\") */\n#define EF_OS2EA     0x0009   /* OS/2 Extra Field ID (extended attributes) */\n#define EF_ACL       0x4C41   /* ACL Extra Field ID (access control list, \"AL\") */\n#define EF_NTSD      0x4453   /* NT Security Descriptor Extra Field ID, (\"SD\") */\n#define EF_BEOS      0x6542   /* BeOS Extra Field ID (\"Be\") */\n#define EF_ATHEOS    0x7441   /* AtheOS Extra Field ID (\"At\") */\n#define EF_QDOS      0xfb4a   /* SMS/QDOS (\"J\\373\") */\n#define EF_AOSVS     0x5356   /* AOS/VS (\"VS\") */\n#define EF_SPARK     0x4341   /* David Pilling's Acorn/SparkFS (\"AC\") */\n#define EF_THEOS     0x6854   /* THEOS (\"Th\") */\n#define EF_TANDEM    0x4154   /* Tandem NSK (\"TA\") */\n\n/* Definitions for extra field handling: */\n#define EF_SIZE_MAX  ((unsigned)0xFFFF) /* hard limit of total e.f. length */\n#define EB_HEADSIZE       4     /* length of a extra field block header */\n#define EB_ID             0     /* offset of block ID in header */\n#define EB_LEN            2     /* offset of data length field in header */\n#define EB_MEMCMPR_HSIZ   6     /* header length for memcompressed data */\n#define EB_DEFLAT_EXTRA  10     /* overhead for 64kByte \"undeflatable\" data */\n\n#define EB_UX_MINLEN      8     /* minimal \"UX\" field contains atime, mtime */\n#define EB_UX_ATIME       0     /* offset of atime in \"UX\" extra field data */\n#define EB_UX_MTIME       4     /* offset of mtime in \"UX\" extra field data */\n\n#define EB_UX_FULLSIZE    12    /* full \"UX\" field (atime, mtime, uid, gid) */\n#define EB_UX_UID         8     /* byte offset of UID in \"UX\" field data */\n#define EB_UX_GID         10    /* byte offset of GID in \"UX\" field data */\n\n#define EB_UT_MINLEN      1     /* minimal UT field contains Flags byte */\n#define EB_UT_FLAGS       0     /* byte offset of Flags field */\n#define EB_UT_TIME1       1     /* byte offset of 1st time value */\n#define EB_UT_FL_MTIME    (1 << 0)      /* mtime present */\n#define EB_UT_FL_ATIME    (1 << 1)      /* atime present */\n#define EB_UT_FL_CTIME    (1 << 2)      /* ctime present */\n#define EB_UT_LEN(n)      (EB_UT_MINLEN + 4 * (n))\n\n#define EB_UX2_MINLEN     4     /* minimal Ux field contains UID/GID */\n#define EB_UX2_UID        0     /* byte offset of UID in \"Ux\" field data */\n#define EB_UX2_GID        2     /* byte offset of GID in \"Ux\" field data */\n#define EB_UX2_VALID      (1 << 8)      /* UID/GID present */\n\n/* ASCII definitions for line terminators in text files: */\n#define LF     10        /* '\\n' on ASCII machines; must be 10 due to EBCDIC */\n#define CR     13        /* '\\r' on ASCII machines; must be 13 due to EBCDIC */\n#define CTRLZ  26        /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */\n\n/* return codes of password fetches (negative: user abort; positive: error) */\n#define IZ_PW_ENTERED   0       /* got some PWD string, use/try it */\n#define IZ_PW_CANCEL    -1      /* no password available (for this entry) */\n#define IZ_PW_CANCELALL -2      /* no password, skip any further PWD request */\n#define IZ_PW_ERROR     5       /* = PK_MEM2 : failure (no mem, no tty, ...) */\n#define IZ_PW_SKIPVERIFY IZ_PW_CANCEL   /* skip encrypt. passwd verification */\n\n/* mode flag values of password prompting function */\n#define ZP_PW_ENTER     0       /* request for encryption password */\n#define ZP_PW_VERIFY    1       /* request for reentering password */\n\n/* Error return codes and PERR macro */\n#include \"ziperr.h\"\n\n#if 0            /* Optimization: use the (const) result of crc32(0L,NULL,0) */\n#  define CRCVAL_INITIAL  crc32(0L, (uch *)NULL, 0)\n# if 00 /* not used, should be removed !! */\n#  define ADLERVAL_INITIAL adler16(0U, (uch *)NULL, 0)\n# endif /* 00 */\n#else\n#  define CRCVAL_INITIAL  0L\n# if 00 /* not used, should be removed !! */\n#  define ADLERVAL_INITIAL 1\n# endif /* 00 */\n#endif\n\n#define DOSTIME_MINIMUM         ((ulg)0x00210000L)\n#define DOSTIME_2038_01_18      ((ulg)0x74320000L)\n\n\n/* Public globals */\nextern uch upper[256];          /* Country dependent case map table */\nextern uch lower[256];\n#ifdef EBCDIC\nextern ZCONST uch ascii[256];   /* EBCDIC <--> ASCII translation tables */\nextern ZCONST uch ebcdic[256];\n#endif /* EBCDIC */\n#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\n  extern ZCONST ulg near *crc_32_tab;\n#else\n  extern ZCONST ulg Far *crc_32_tab;\n#endif\n\n/* Are these ever used?  6/12/05 EG */\n#ifdef IZ_ISO2OEM_ARRAY         /* ISO 8859-1 (Win CP 1252) --> OEM CP 850 */\nextern ZCONST uch Far iso2oem[128];\n#endif\n#ifdef IZ_OEM2ISO_ARRAY         /* OEM CP 850 --> ISO 8859-1 (Win CP 1252) */\nextern ZCONST uch Far oem2iso[128];\n#endif\n\nextern char errbuf[FNMAX+4081]; /* Handy place to build error messages */\nextern int recurse;             /* Recurse into directories encountered */\nextern int dispose;             /* Remove files after put in zip file */\nextern int pathput;             /* Store path with name */\n\n#ifdef RISCOS\nextern int scanimage;           /* Scan through image files */\n#endif\n\n#define BEST -1                 /* Use best method (deflation or store) */\n#define STORE 0                 /* Store method */\n#define DEFLATE 8               /* Deflation method*/\n#define BZIP2 12                /* BZIP2 method */\n#ifdef BZIP2_SUPPORT\n#define LAST_KNOWN_COMPMETHOD   BZIP2\n#else\n#define LAST_KNOWN_COMPMETHOD   DEFLATE\n#endif\n\nextern int method;              /* Restriction on compression method */\n\nextern ulg skip_this_disk;\nextern int des_good;            /* Good data descriptor found */\nextern ulg des_crc;             /* Data descriptor CRC */\nextern uzoff_t des_csize;       /* Data descriptor csize */\nextern uzoff_t des_usize;       /* Data descriptor usize */\nextern int dosify;              /* Make new entries look like MSDOS */\nextern char *special;           /* Don't compress special suffixes */\nextern int verbose;             /* Report oddities in zip file structure */\nextern int fix;                 /* Fix the zip file */\nextern int filesync;            /* 1=file sync, delete entries not on file system */\nextern int adjust;              /* Adjust the unzipsfx'd zip file */\nextern int level;               /* Compression level */\nextern int translate_eol;       /* Translate end-of-line LF -> CR LF */\n#ifdef VMS\n   extern int vmsver;           /* Append VMS version number to file names */\n   extern int vms_native;       /* Store in VMS format */\n   extern int vms_case_2;       /* ODS2 file name case in VMS. -1: down. */\n   extern int vms_case_5;       /* ODS5 file name case in VMS. +1: preserve. */\n\n/* Accomodation for /NAMES = AS_IS with old header files. */\n# define cma$tis_errno_get_addr CMA$TIS_ERRNO_GET_ADDR\n# define lib$establish LIB$ESTABLISH\n# define lib$get_foreign LIB$GET_FOREIGN\n# define lib$get_input LIB$GET_INPUT\n# define lib$sig_to_ret LIB$SIG_TO_RET\n# define ots$cvt_tu_l OTS$CVT_TU_L\n# define str$concat STR$CONCAT\n# define str$find_first_substring STR$FIND_FIRST_SUBSTRING\n# define str$free1_dx STR$FREE1_DX\n# define sys$asctim SYS$ASCTIM\n# define sys$assign SYS$ASSIGN\n# define sys$bintim SYS$BINTIM\n# define sys$close SYS$CLOSE\n# define sys$connect SYS$CONNECT\n# define sys$dassgn SYS$DASSGN\n# define sys$display SYS$DISPLAY\n# define sys$getjpiw SYS$GETJPIW\n# define sys$open SYS$OPEN\n# define sys$parse SYS$PARSE\n# define sys$qiow SYS$QIOW\n# define sys$read SYS$READ\n# define sys$search SYS$SEARCH\n#endif /* VMS */\n#if defined(OS2) || defined(WIN32)\n   extern int use_longname_ea;   /* use the .LONGNAME EA as the file's name */\n#endif\n#if defined (QDOS) || defined(QLZIP)\nextern short qlflag;\n#endif\n/* 9/26/04 EG */\nextern int no_wild;             /* wildcards are disabled */\nextern int allow_regex;         /* 1 = allow [list] matching (regex) */\nextern int wild_stop_at_dir;    /* wildcards do not include / in matches */\n#ifdef UNICODE_SUPPORT\n  extern int using_utf8;        /* 1 if current character set is UTF-8 */\n# ifdef WIN32\n   extern int no_win32_wide;    /* 1 = no wide functions, like GetFileAttributesW() */\n# endif\n#endif\n/* 10/20/04 */\nextern zoff_t dot_size;         /* if not 0 then display dots every size buffers */\nextern zoff_t dot_count;        /* if dot_size not 0 counts buffers */\n/* status 10/30/04 */\nextern int display_counts;      /* display running file count */\nextern int display_bytes;       /* display running bytes remaining */\nextern int display_globaldots;  /* display dots for archive instead of for each file */\nextern int display_volume;      /* display current input and output volume (disk) numbers */\nextern int display_usize;       /* display uncompressed bytes */\nextern ulg files_so_far;        /* files processed so far */\nextern ulg bad_files_so_far;    /* files skipped so far */\nextern ulg files_total;         /* files total to process */\nextern uzoff_t bytes_so_far;    /* bytes processed so far (from initial scan) */\nextern uzoff_t good_bytes_so_far;/* good bytes read so far */\nextern uzoff_t bad_bytes_so_far;/* bad bytes skipped so far */\nextern uzoff_t bytes_total;     /* total bytes to process (from initial scan) */\n/* logfile 6/5/05 */\nextern int logall;          /* 0 = warnings/errors, 1 = all */\nextern FILE *logfile;           /* pointer to open logfile or NULL */\nextern int logfile_append;      /* append to existing logfile */\nextern char *logfile_path;      /* pointer to path of logfile */\n#ifdef WIN32\nextern int nonlocal_name;       /* Name has non-local characters */\nextern int nonlocal_path;       /* Path has non-local characters */\n#endif\n#ifdef UNICODE_SUPPORT\n/* Unicode 10/12/05 */\nextern int use_wide_to_mb_default;/* use the default MB char instead of escape */\n#endif\n\nextern int hidden_files;        /* process hidden and system files */\nextern int volume_label;        /* add volume label */\nextern int dirnames;            /* include directory names */\nextern int filter_match_case;   /* 1=match case when filter() */\nextern int diff_mode;           /* 1=require --out and only store changed and add */\n#if defined(WIN32)\nextern int only_archive_set;    /* only include if DOS archive bit set */\nextern int clear_archive_bits;   /* clear DOS archive bit of included files */\n#endif\nextern int linkput;             /* Store symbolic links as such */\nextern int noisy;               /* False for quiet operation */\nextern int extra_fields;        /* 0=create minimum, 1=don't copy old, 2=keep old */\n#ifdef NTSD_EAS\n extern int use_privileges;     /* use security privilege overrides */\n#endif\nextern int use_descriptors;     /* use data descriptors (extended headings) */\nextern int allow_empty_archive; /* if no files, create empty archive anyway */\nextern int copy_only;           /* 1 = copy archive with no changes */\nextern int zip_to_stdout;       /* output to stdout */\nextern int output_seekable;     /* 1 = output seekable 3/13/05 EG */\n#ifdef ZIP64_SUPPORT            /* zip64 globals 10/4/03 E. Gordon */\n extern int force_zip64;        /* force use of zip64 when streaming from stdin */\n extern int zip64_entry;        /* current entry needs Zip64 */\n extern int zip64_archive;      /* at least 1 entry needs zip64 */\n#endif\nextern int allow_fifo;          /* Allow reading Unix FIFOs, waiting if pipe open */\nextern int show_files;          /* show files to operate on and exit (=2 log only) */\n\nextern char *tempzip;           /* temp file name */\nextern FILE *y;                 /* output file now global for splits */\n\n#ifdef UNICODE_SUPPORT\n  extern int utf8_force;         /* 1=store UTF-8 as standard per AppNote bit 11 */\n#endif\nextern int unicode_escape_all;  /* 1=escape all non-ASCII characters in paths */\nextern int unicode_mismatch;    /* unicode mismatch is 0=error, 1=warn, 2=ignore, 3=no */\n\nextern time_t scan_delay;       /* seconds before display Scanning files message */\nextern time_t scan_dot_time;    /* time in seconds between Scanning files dots */\nextern time_t scan_start;       /* start of file scan */\nextern time_t scan_last;        /* time of last message */\nextern int scan_started;        /* scan has started */\nextern uzoff_t scan_count;      /* Used for \"Scanning files...\" message */\n\nextern ulg before;              /* 0=ignore, else exclude files before this time */\nextern ulg after;               /* 0=ignore, else exclude files newer than this time */\n\n/* in split globals */\n\nextern ulg total_disks;\n\nextern ulg current_in_disk;\nextern uzoff_t current_in_offset;\nextern ulg skip_current_disk;\n\n\n/* out split globals */\n\nextern ulg    current_local_disk; /* disk with current local header */\n\nextern ulg     current_disk;     /* current disk number */\nextern ulg     cd_start_disk;    /* central directory start disk */\nextern uzoff_t cd_start_offset;  /* offset of start of cd on cd start disk */\nextern uzoff_t cd_entries_this_disk; /* cd entries this disk */\nextern uzoff_t total_cd_entries; /* total cd entries in new/updated archive */\nextern ulg     zip64_eocd_disk;  /* disk with Zip64 EOCD Record */\nextern uzoff_t zip64_eocd_offset; /* offset of Zip64 EOCD Record */\n/* for split method 1 (keep split with local header open and update) */\nextern char *current_local_tempname; /* name of temp file */\nextern FILE  *current_local_file; /* file pointer for current local header */\nextern uzoff_t current_local_offset; /* offset to start of current local header */\n/* global */\nextern uzoff_t bytes_this_split; /* bytes written to current split */\nextern int read_split_archive;   /* 1=scanzipf_reg detected spanning signature */\nextern int split_method;         /* 0=no splits, 1=seekable, 2=data descs, -1=no */\nextern uzoff_t split_size;       /* how big each split should be */\nextern int split_bell;           /* when pause for next split ring bell */\nextern uzoff_t bytes_prev_splits; /* total bytes written to all splits before this */\nextern uzoff_t bytes_this_entry; /* bytes written for this entry across all splits */\nextern int noisy_splits;         /* note when splits are being created */\nextern int mesg_line_started;    /* 1=started writing a line to mesg */\nextern int logfile_line_started; /* 1=started writing a line to logfile */\nextern char *key;               /* Scramble password or NULL */\nextern char *tempath;           /* Path for temporary files */\nextern FILE *mesg;              /* Where informational output goes */\nextern char *zipfile;           /* New or existing zip archive (zip file) */\nextern FILE *in_file;           /* Current input file for spits */\nextern char *in_path;           /* Name of input archive, used to track reading splits */\nextern char *in_split_path;     /* in split path */\nextern char *out_path;          /* Name of output file, usually same as zipfile */\nextern int zip_attributes;\n\n/* zip64 support 08/31/2003 R.Nausedat */\nextern uzoff_t zipbeg;          /* Starting offset of zip structures */\nextern uzoff_t cenbeg;          /* Starting offset of central directory */\nextern uzoff_t tempzn;          /* Count of bytes written to output zip file */\n\n/* NOTE: zcount and fcount cannot exceed \"size_t\" (resp. \"extent\") range.\n   This is an internal limitation built into Zip's action handling:\n   Zip keeps \"{z|f}count * struct {z|f}list\" arrays in (flat) memory,\n   for sorting, file matching, and building the central-dir structures.\n */\n\nextern struct zlist far *zfiles;/* Pointer to list of files in zip file */\nextern extent zcount;           /* Number of files in zip file */\nextern int zipfile_exists;      /* 1 if zipfile exists */\nextern ush zcomlen;             /* Length of zip file comment */\nextern char *zcomment;          /* Zip file comment (not zero-terminated) */\nextern struct flist far **fsort;/* List of files sorted by name */\nextern struct zlist far **zsort;/* List of files sorted by name */\n#ifdef UNICODE_SUPPORT\nextern struct zlist far **zusort;/* List of files sorted by zuname */\n#endif\nextern struct flist far *found; /* List of names found */\nextern struct flist far *far *fnxt;     /* Where to put next in found list */\nextern extent fcount;           /* Count of names in found list */\n\nextern struct plist *patterns;  /* List of patterns to be matched */\nextern unsigned pcount;         /* number of patterns */\nextern unsigned icount;         /* number of include only patterns */\nextern unsigned Rcount;         /* number of -R include patterns */\n\n#ifdef IZ_CHECK_TZ\nextern int zp_tz_is_valid;      /* signals \"timezone info is available\" */\n#endif\n#if (defined(MACOS) || defined(WINDLL))\nextern int zipstate;            /* flag \"zipfile has been stat()'ed */\n#endif\n\n/* Diagnostic functions */\n#ifdef DEBUG\n# ifdef MSDOS\n#  undef  stderr\n#  define stderr stdout\n# endif\n#  define diag(where) fprintf(stderr, \"zip diagnostic: %s\\n\", where)\n#  define Assert(cond,msg) {if(!(cond)) error(msg);}\n# ifdef THEOS\n#  define Trace(x) _fprintf x\n#  define Tracev(x) {if (verbose) _fprintf x ;}\n#  define Tracevv(x) {if (verbose>1) _fprintf x ;}\n#  define Tracec(c,x) {if (verbose && (c)) _fprintf x ;}\n#  define Tracecv(c,x) {if (verbose>1 && (c)) _fprintf x ;}\n# else\n#  define Trace(x) fprintf x\n#  define Tracev(x) {if (verbose) fprintf x ;}\n#  define Tracevv(x) {if (verbose>1) fprintf x ;}\n#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}\n#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}\n# endif\n#else\n#  define diag(where)\n#  define Assert(cond,msg)\n#  define Trace(x)\n#  define Tracev(x)\n#  define Tracevv(x)\n#  define Tracec(c,x)\n#  define Tracecv(c,x)\n#endif\n\n#ifdef DEBUGNAMES\n#  define free(x) { int *v;Free(x); v=x;*v=0xdeadbeef;x=(void *)0xdeadbeef; }\n#endif\n\n/* Public function prototypes */\n\n#ifndef UTIL\n#ifdef USE_ZIPMAIN\nint zipmain OF((int, char **));\n#else\nint main OF((int, char **));\n#endif /* USE_ZIPMAIN */\n#endif\n\n#ifdef EBCDIC\nextern int aflag;\n#endif /* EBCDIC */\n#ifdef CMS_MVS\nextern int bflag;\n#endif /* CMS_MVS */\nvoid zipmessage_nl OF((ZCONST char *, int));\nvoid zipmessage OF((ZCONST char *, ZCONST char *));\nvoid zipwarn OF((ZCONST char *, ZCONST char *));\nvoid ziperr OF((int, ZCONST char *));\n#ifdef UTIL\n#  define error(msg)    ziperr(ZE_LOGIC, msg)\n#else\n   void error OF((ZCONST char *));\n#  ifdef VMSCLI\n     void help OF((void));\n#  endif\n   int encr_passwd OF((int, char *, int, ZCONST char *));\n#endif\n\n        /* in zipup.c */\n#ifndef UTIL\n  /* zip64 support 08/31/2003 R.Nausedat */\n   int percent OF((uzoff_t, uzoff_t));\n\n   int zipup OF((struct zlist far *));\n#  ifdef USE_ZLIB\n     void zl_deflate_free OF((void));\n#  else\n     void flush_outbuf OF((char *, unsigned *));\n     int seekable OF((void));\n     extern unsigned (*read_buf) OF((char *, unsigned int));\n#  endif /* !USE_ZLIB */\n#  ifdef ZP_NEED_MEMCOMPR\n     ulg memcompress OF((char *, ulg, char *, ulg));\n#  endif\n#  ifdef BZIP2_SUPPORT\n   void bz_compress_free OF((void));\n#  endif\n#endif /* !UTIL */\n\n        /* in zipfile.c */\n#ifndef UTIL\n   struct zlist far *zsearch OF((ZCONST char *));\n#  ifdef USE_EF_UT_TIME\n     int get_ef_ut_ztime OF((struct zlist far *, iztimes *));\n#  endif /* USE_EF_UT_TIME */\n   int trash OF((void));\n#endif /* !UTIL */\nchar *ziptyp OF((char *));\nint readzipfile OF((void));\nint putlocal OF((struct zlist far *, int));\nint putextended OF((struct zlist far *));\nint putcentral OF((struct zlist far *));\n/* zip64 support 09/05/2003 R.Nausedat */\nint putend OF((uzoff_t, uzoff_t, uzoff_t, extent, char *));\n/* moved seekable to separate function 3/14/05 EG */\nint is_seekable OF((FILE *));\nint zipcopy OF((struct zlist far *));\nint readlocal OF((struct zlist far **, struct zlist far *));\n/* made global for handling extra fields */\nchar *get_extra_field OF((ush, char *, unsigned));\nchar *copy_nondup_extra_fields OF((char *, unsigned, char *, unsigned, unsigned *));\n\n        /* in fileio.c */\n#ifndef UTIL\n   char *getnam OF((FILE *));\n   struct flist far *fexpel OF((struct flist far *));\n   char *last OF((char *, int));\n# ifdef UNICODE_SUPPORT\n   wchar_t *lastw OF((wchar_t *, wchar_t));\n# endif\n   char *msname OF((char *));\n# ifdef UNICODE_SUPPORT\n   wchar_t *msnamew OF((wchar_t *));\n# endif\n   int check_dup OF((void));\n   int filter OF((char *, int));\n   int newname OF((char *, int, int));\n# ifdef UNICODE_SUPPORT\n#  ifdef WIN32\n   int newnamew OF((wchar_t *, int, int));\n#  endif\n# endif\n   /* used by copy mode */\n   int proc_archive_name OF((char *, int));\n#endif /* !UTIL */\n#if (!defined(UTIL) || defined(W32_STATROOT_FIX))\n   time_t dos2unixtime OF((ulg));\n#endif\n#ifndef UTIL\n   ulg dostime OF((int, int, int, int, int, int));\n   ulg unix2dostime OF((time_t *));\n   int issymlnk OF((ulg a));\n#  ifdef S_IFLNK\n#    define rdsymlnk(p,b,n) readlink(p,b,n)\n/*   extern int readlink OF((char *, char *, int)); */\n#  else /* !S_IFLNK */\n#    define rdsymlnk(p,b,n) (0)\n#  endif /* !S_IFLNK */\n#endif /* !UTIL */\n\nint destroy OF((char *));\nint replace OF((char *, char *));\nint getfileattr OF((char *));\nint setfileattr OF((char *, int));\nchar *tempname OF((char *));\n\n/* for splits */\nint close_split OF((ulg, FILE *, char *));\nint ask_for_split_read_path OF((ulg));\nint ask_for_split_write_path OF((ulg));\nchar *get_in_split_path OF((char *, ulg));\nchar *find_in_split_path OF((char *, ulg));\nchar *get_out_split_path OF((char *, ulg));\nint rename_split OF((char *, char *));\nint set_filetype OF((char *));\n\nint bfcopy OF((uzoff_t));\n\nint fcopy OF((FILE *, FILE *, uzoff_t));\n\n#ifdef ZMEM\n   char *memset OF((char *, int, unsigned int));\n   char *memcpy OF((char *, char *, unsigned int));\n   int memcmp OF((char *, char *, unsigned int));\n#endif /* ZMEM */\n\n        /* in system dependent fileio code (<system>.c) */\n#ifndef UTIL\n# ifdef PROCNAME\n   int wild OF((char *));\n# endif\n   char *in2ex OF((char *));\n   char *ex2in OF((char *, int, int *));\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n   int has_win32_wide OF((void));\n   wchar_t *in2exw OF((wchar_t *));\n   wchar_t *ex2inw OF((wchar_t *, int, int *));\n   int procnamew OF((wchar_t *, int));\n#endif\n   int procname OF((char *, int));\n   void stamp OF((char *, ulg));\n\n   ulg filetime OF((char *, ulg *, zoff_t *, iztimes *));\n   /* Windows Unicode */\n# ifdef UNICODE_SUPPORT\n# ifdef WIN32\n   ulg filetimew OF((wchar_t *, ulg *, zoff_t *, iztimes *));\n   char *get_win32_utf8path OF((char *));\n   wchar_t *local_to_wchar_string OF ((char *));\n# endif\n# endif\n\n# if !(defined(VMS) && defined(VMS_PK_EXTRA))\n   int set_extra_field OF((struct zlist far *, iztimes *));\n# endif /* ?(VMS && VMS_PK_EXTRA) */\n   int deletedir OF((char *));\n# ifdef MY_ZCALLOC\n     zvoid far *zcalloc OF((unsigned int, unsigned int));\n     zvoid zcfree       OF((zvoid far *));\n# endif /* MY_ZCALLOC */\n#endif /* !UTIL */\nvoid version_local OF((void));\n\n        /* in util.c */\n#ifndef UTIL\nint   fseekable    OF((FILE *));\nchar *isshexp      OF((char *));\n#ifdef UNICODE_SUPPORT\n# ifdef WIN32\n   wchar_t *isshexpw     OF((wchar_t *));\n   int dosmatchw   OF((ZCONST wchar_t *, ZCONST wchar_t *, int));\n# endif\n#endif\nint   shmatch      OF((ZCONST char *, ZCONST char *, int));\n# if defined(DOS) || defined(WIN32)\n   int dosmatch    OF((ZCONST char *, ZCONST char *, int));\n# endif /* DOS || WIN32 */\n#endif /* !UTIL */\n\n/* functions to convert zoff_t to a string */\nchar *zip_fuzofft      OF((uzoff_t, char *, char*));\nchar *zip_fzofft       OF((zoff_t, char *, char*));\n\n/* read and write number strings like 10M */\nint DisplayNumString OF ((FILE *file, uzoff_t i));\nint WriteNumString OF((uzoff_t num, char *outstring));\nuzoff_t ReadNumString OF((char *numstring));\n\n/* returns true if abbrev is abbreviation for string */\nint abbrevmatch OF((char *, char *, int, int));\n\nvoid init_upper    OF((void));\nint  namecmp       OF((ZCONST char *string1, ZCONST char *string2));\n\n#ifdef EBCDIC\n  char *strtoasc     OF((char *str1, ZCONST char *str2));\n  char *strtoebc     OF((char *str1, ZCONST char *str2));\n  char *memtoasc     OF((char *mem1, ZCONST char *mem2, unsigned len));\n  char *memtoebc     OF((char *mem1, ZCONST char *mem2, unsigned len));\n#endif /* EBCDIC */\n#ifdef IZ_ISO2OEM_ARRAY\n  char *str_iso_to_oem    OF((char *dst, ZCONST char *src));\n#endif\n#ifdef IZ_OEM2ISO_ARRAY\n  char *str_oem_to_iso    OF((char *dst, ZCONST char *src));\n#endif\n\nzvoid far **search OF((ZCONST zvoid *, ZCONST zvoid far **, extent,\n                       int (*)(ZCONST zvoid *, ZCONST zvoid far *)));\nvoid envargs       OF((int *, char ***, char *, char *));\nvoid expand_args   OF((int *, char ***));\n\nint  is_text_buf   OF((ZCONST char *buf_ptr, unsigned buf_size));\n/* this is no longer used ...\nunsigned int adler16 OF((unsigned int, ZCONST uch *, extent));\n*/\n        /*  crc functions are now declared in crc32.h */\n\n#ifndef UTIL\n#ifndef USE_ZLIB\n        /* in deflate.c */\nvoid lm_init OF((int, ush *));\nvoid lm_free OF((void));\n\nuzoff_t deflate OF((void));\n\n        /* in trees.c */\nvoid     ct_init      OF((ush *, int *));\nint      ct_tally     OF((int, int));\nuzoff_t  flush_block  OF((char far *, ulg, int));\nvoid     bi_init      OF((char *, unsigned int, int));\n#endif /* !USE_ZLIB */\n#endif /* !UTIL */\n\n        /* in system specific assembler code, replacing C code in trees.c */\n#if defined(ASMV) && defined(RISCOS)\n  void     send_bits    OF((int, int));\n  unsigned bi_reverse   OF((unsigned int, int));\n#endif /* ASMV && RISCOS */\n\n/*---------------------------------------------------------------------------\n    VMS-only functions:\n  ---------------------------------------------------------------------------*/\n#ifdef VMS\n   int    vms_stat        OF((char *, stat_t *));              /* vms.c */\n   void   vms_exit        OF((int));                           /* vms.c */\n#ifndef UTIL\n#ifdef VMSCLI\n   ulg    vms_zip_cmdline OF((int *, char ***));                /* cmdline.c */\n   void   VMSCLI_help     OF((void));                           /* cmdline.c */\n#endif /* VMSCLI */\n#endif /* !UTIL */\n#endif /* VMS */\n\n/*\n#ifdef ZIP64_SUPPORT\n   update_local_Zip64_extra_field OF((struct zlist far *, FILE *));\n#endif\n*/\n\n/*---------------------------------------------------------------------------\n    WIN32-only functions:\n  ---------------------------------------------------------------------------*/\n#ifdef WIN32\n   int ZipIsWinNT         OF((void));                         /* win32.c */\n   int ClearArchiveBit    OF((char *));                       /* win32.c */\n# ifdef UNICODE_SUPPORT\n   int ClearArchiveBitW   OF((wchar_t *));                    /* win32.c */\n# endif\n#endif /* WIN32 */\n\n#if (defined(WINDLL) || defined(DLL_ZIPAPI))\n/*---------------------------------------------------------------------------\n    Prototypes for public Zip API (DLL) functions.\n  ---------------------------------------------------------------------------*/\n#include \"api.h\"\n#endif /* WINDLL || DLL_ZIPAPI */\n\n\n   /* WIN32_OEM */\n#ifdef WIN32\n/*\n# if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)\n*/\n  /* convert oem to ansi string */\n  char *oem_to_local_string OF((char *, char *));\n/*\n# endif\n*/\n#endif\n\n#ifdef WIN32\n/*\n# if defined(UNICODE_SUPPORT) || defined(WIN32_OEM)\n*/\n  /* convert local string to oem string */\n  char *local_to_oem_string OF((char *, char *));\n/*\n# endif\n*/\n#endif\n\n\n\n/*---------------------------------------------------------------------\n    Unicode Support\n    28 August 2005\n  ---------------------------------------------------------------------*/\n#ifdef UNICODE_SUPPORT\n\n  /* Default character when a zwchar too big for wchar_t */\n# define zwchar_to_wchar_t_default_char '_'\n\n  /* Default character string when wchar_t does not convert to mb */\n# define wide_to_mb_default_string \"_\"\n\n  /* wide character type */\n  typedef unsigned long zwchar;\n\n  /* check if string is all ASCII */\n  int is_ascii_string OF((char *));\n#ifdef WIN32\n  int is_ascii_stringw OF((wchar_t *));\n  zwchar *wchar_to_wide_string OF((wchar_t *));\n#endif\n\n  /* convert UTF-8 string to multi-byte string */\n  char *utf8_to_local_string OF((char *));\n  char *utf8_to_escape_string OF((char *));\n\n  /* convert UTF-8 string to wide string */\n  zwchar *utf8_to_wide_string OF((char *));\n\n  /* convert wide string to multi-byte string */\n  char *wide_to_local_string OF((zwchar *));\n  char *wide_to_escape_string OF((zwchar *));\n  char *local_to_escape_string OF((char *));\n#ifdef WIN32\n  /* convert UTF-8 to wchar */\n  wchar_t *utf8_to_wchar_string OF ((char *));\n\n  char *wchar_to_local_string OF((wchar_t *));\n#endif\n\n  /* convert local string to multi-byte display string */\n  char *local_to_display_string OF((char *));\n\n  /* convert wide character to escape string */\n  char *wide_char_to_escape_string OF((unsigned long));\n\n#if 0\n  /* convert escape string to wide character */\n  unsigned long escape_string_to_wide OF((char *));\n#endif\n\n  /* convert local to UTF-8 */\n  char *local_to_utf8_string OF ((char *));\n\n  /* convert local to wide string */\n  zwchar *local_to_wide_string OF ((char *));\n\n  /* convert wide string to UTF-8 */\n  char *wide_to_utf8_string OF((zwchar *));\n#ifdef WIN32\n  char *wchar_to_utf8_string OF((wchar_t *));\n#endif\n\n#endif /* UNICODE_SUPPORT */\n\n\n/*---------------------------------------------------\n * Split archives\n *\n * 10/20/05 EG\n */\n\n#define BFWRITE_DATA 0\n#define BFWRITE_LOCALHEADER 1\n#define BFWRITE_CENTRALHEADER 2\n#define BFWRITE_HEADER 3 /* data descriptor or end records */\n\nsize_t bfwrite OF((ZCONST void *buffer, size_t size, size_t count,\n                   int));\n\n/* for putlocal() */\n#define PUTLOCAL_WRITE 0\n#define PUTLOCAL_REWRITE 1\n\n\n/*--------------------------------------------------------------------\n    Long option support\n    23 August 2003\n    See fileio.c\n  --------------------------------------------------------------------*/\n\n/* The below is for use in the caller-provided options table */\n\n/* value_type - value is always returned as a string. */\n#define o_NO_VALUE        0   /* this option does not take a value */\n#define o_REQUIRED_VALUE  1   /* this option requires a value */\n#define o_OPTIONAL_VALUE  2   /* value is optional (see get_option() for details) */\n#define o_VALUE_LIST      3   /* this option takes a list of values */\n#define o_ONE_CHAR_VALUE  4   /* next char is value (does not end short opt string) */\n#define o_NUMBER_VALUE    5   /* value is integer (does not end short opt string) */\n\n\n/* negatable - a dash following the option (but before any value) sets negated. */\n#define o_NOT_NEGATABLE   0   /* trailing '-' to negate either starts value or generates error */\n#define o_NEGATABLE       1   /* trailing '-' sets negated to TRUE */\n\n\n/* option_num can be this when option not in options table */\n#define o_NO_OPTION_MATCH     -1\n\n/* special values returned by get_option - do not use these as option IDs */\n#define o_NON_OPTION_ARG      ((unsigned long) 0xFFFF)    /* returned for non-option\n                                                             args */\n#define o_ARG_FILE_ERR        ((unsigned long) 0xFFFE)    /* internal recursion\n                                                             return (user never sees) */\n\n/* options array is set in zip.c */\nstruct option_struct {\n  char *shortopt;           /* char * to sequence of char that is short option */\n  char Far *longopt;        /* char * to long option string */\n  int  value_type;          /* from above */\n  int  negatable;           /* from above */\n  unsigned long option_ID;  /* value returned by get_option when this option is found */\n  char Far *name;           /* optional string for option returned on some errors */\n};\nextern struct option_struct far options[];\n\n\n/* moved here from fileio.c to make global - 10/6/05 EG */\n\n/* If will support wide for Unicode then need to add */\n  /* multi-byte */\n#ifdef _MBCS\n# ifndef MULTIBYTE_GETOPTNS\n#   define MULTIBYTE_GETOPTNS\n# endif\n#endif\n#ifdef MULTIBYTE_GETOPTNS\n  int mb_clen OF((ZCONST char *));\n# define MB_CLEN(ptr) mb_clen(ptr)\n# define MB_NEXTCHAR(ptr) ((ptr) += MB_CLEN(ptr))\n#else\n  /* no multi-byte */\n# define MB_CLEN(ptr) (1)\n# define MB_NEXTCHAR(ptr) ((ptr)++)\n#endif\n\n\n/* function prototypes */\n\n/* get the next option from args */\nunsigned long get_option OF((char ***pargs, int *argc, int *argnum, int *optchar,\n                             char **value, int *negated, int *first_nonopt_arg,\n                             int *option_num, int recursion_depth));\n\n/* copy args - copy an args array, allocating space as needed */\nchar **copy_args OF((char **args, int max_args));\n\n/* free args - free args created with one of these functions */\nint free_args OF ((char **args));\n\n/* insert arg - copy an arg into args */\nint insert_arg OF ((char ***args, ZCONST char *arg, int insert_at,\n                    int free_args));\n\n\n/*--------------------------------------------------------------------\n    End of Long option support\n  --------------------------------------------------------------------*/\n\n\n#endif /* !__zip_h */\n/* end of zip.h */\n"
  },
  {
    "path": "deps/infozip/zip30/zip.txt",
    "content": "ZIP(1L)                                                                ZIP(1L)\n\nNAME\n       zip - package and compress (archive) files\n\nSYNOPSIS\n       zip  [-aABcdDeEfFghjklLmoqrRSTuvVwXyz!@$] [--longoption ...]  [-b path]\n       [-n suffixes] [-t date] [-tt date] [zipfile [file ...]]  [-xi list]\n\n       zipcloak (see separate man page)\n\n       zipnote (see separate man page)\n\n       zipsplit (see separate man page)\n\n       Note:  Command line processing in zip has been changed to support  long\n       options  and  handle all options and arguments more consistently.  Some\n       old command lines that depend on command line  inconsistencies  may  no\n       longer work.\n\nDESCRIPTION\n       zip  is  a compression and file packaging utility for Unix, VMS, MSDOS,\n       OS/2, Windows 9x/NT/XP, Minix, Atari, Macintosh, Amiga, and Acorn  RISC\n       OS.   It  is analogous to a combination of the Unix commands tar(1) and\n       compress(1) and is compatible with PKZIP (Phil  Katz's  ZIP  for  MSDOS\n       systems).\n\n       A  companion  program  (unzip(1L))  unpacks  zip archives.  The zip and\n       unzip(1L) programs can work with archives produced by PKZIP (supporting\n       most PKZIP features up to PKZIP version 4.6), and PKZIP and PKUNZIP can\n       work with archives produced  by  zip  (with  some  exceptions,  notably\n       streamed  archives,  but  recent  changes  in the zip file standard may\n       facilitate better compatibility).  zip version 3.0 is  compatible  with\n       PKZIP  2.04  and  also supports the Zip64 extensions of PKZIP 4.5 which\n       allow archives as well as files to exceed the previous 2 GB limit (4 GB\n       in  some  cases).  zip also now supports bzip2 compression if the bzip2\n       library is included when zip is compiled.  Note that PKUNZIP 1.10  can-\n       not extract files produced by PKZIP 2.04 or zip 3.0. You must use PKUN-\n       ZIP 2.04g or unzip 5.0p1 (or later versions) to extract them.\n\n       See the EXAMPLES section at the bottom of this  page  for  examples  of\n       some typical uses of zip.\n\n       Large Archives and Zip64.   zip automatically uses the Zip64 extensions\n       when files larger than 4 GB are added to an archive,  an  archive  con-\n       taining  Zip64 entries is updated (if the resulting archive still needs\n       Zip64), the size of the archive will exceed 4 GB, or when the number of\n       entries  in  the archive will exceed about 64K.  Zip64 is also used for\n       archives streamed from standard input as the size of such archives  are\n       not  known  in advance, but the option -fz- can be used to force zip to\n       create PKZIP 2 compatible archives (as long as Zip64 extensions are not\n       needed).   You must use a PKZIP 4.5 compatible unzip, such as unzip 6.0\n       or later, to extract files using the Zip64 extensions.\n\n       In addition, streamed archives, entries encrypted with standard encryp-\n       tion,  or  split archives created with the pause option may not be com-\n       patible with PKZIP as data descriptors are used and PKZIP at  the  time\n       of  this  writing does not support data descriptors (but recent changes\n       in the PKWare published zip standard now include some support  for  the\n       data descriptor format zip uses).\n\n       Mac  OS  X.   Though  previous Mac versions had their own zip port, zip\n       supports Mac OS X as part of the  Unix  port  and  most  Unix  features\n       apply.   References  to \"MacOS\" below generally refer to MacOS versions\n       older than OS X.  Support for some Mac OS features in the Unix Mac OS X\n       port, such as resource forks, is expected in the next zip release.\n\n       For  a  brief  help  on  zip and unzip, run each without specifying any\n       parameters on the command line.\n\nUSE\n       The program is useful for packaging a set of  files  for  distribution;\n       for archiving files; and for saving disk space by temporarily compress-\n       ing unused files or directories.\n\n       The zip program puts one or more compressed files  into  a  single  zip\n       archive, along with information about the files (name, path, date, time\n       of last modification, protection, and check information to verify  file\n       integrity).   An  entire  directory  structure can be packed into a zip\n       archive with a single command.  Compression ratios of 2:1  to  3:1  are\n       common  for text files.  zip has one compression method (deflation) and\n       can also store files without compression.  (If bzip2 support is  added,\n       zip can also compress using bzip2 compression, but such entries require\n       a reasonably modern unzip to decompress.   When  bzip2  compression  is\n       selected,  it replaces deflation as the default method.)  zip automati-\n       cally chooses the better of the two (deflation or store or, if bzip2 is\n       selected, bzip2 or store) for each file to be compressed.\n\n       Command format.  The basic command format is\n\n              zip options archive inpath inpath ...\n\n       where  archive  is a new or existing zip archive and inpath is a direc-\n       tory or file path optionally including wildcards.  When given the  name\n       of  an existing zip archive, zip will replace identically named entries\n       in the zip archive (matching  the  relative  names  as  stored  in  the\n       archive)  or add entries for new names.  For example, if foo.zip exists\n       and contains foo/file1 and foo/file2, and the  directory  foo  contains\n       the files foo/file1 and foo/file3, then:\n\n              zip -r foo.zip foo\n\n       or more concisely\n\n              zip -r foo foo\n\n       will  replace foo/file1 in foo.zip and add foo/file3 to foo.zip.  After\n       this,  foo.zip  contains  foo/file1,  foo/file2,  and  foo/file3,  with\n       foo/file2 unchanged from before.\n\n       So if before the zip command is executed foo.zip has:\n\n               foo/file1 foo/file2\n\n       and directory foo has:\n\n               file1 file3\n\n       then foo.zip will have:\n\n               foo/file1 foo/file2 foo/file3\n\n       where foo/file1 is replaced and foo/file3 is new.\n\n       -@ file lists.   If  a file list is specified as -@ [Not on MacOS], zip\n       takes the list of input files from standard input instead of  from  the\n       command line.  For example,\n\n              zip -@ foo\n\n       will store the files listed one per line on stdin in foo.zip.\n\n       Under  Unix,  this option can be used to powerful effect in conjunction\n       with the find (1) command.  For example, to archive all  the  C  source\n       files in the current directory and its subdirectories:\n\n              find . -name \"*.[ch]\" -print | zip source -@\n\n       (note  that the pattern must be quoted to keep the shell from expanding\n       it).\n\n       Streaming input and output.  zip will also accept a single  dash  (\"-\")\n       as the zip file name, in which case it will write the zip file to stan-\n       dard output, allowing the output to be piped to  another  program.  For\n       example:\n\n              zip -r - . | dd of=/dev/nrst0 obs=16k\n\n       would  write the zip output directly to a tape with the specified block\n       size for the purpose of backing up the current directory.\n\n       zip also accepts a single dash (\"-\") as the name of a file to  be  com-\n       pressed,  in  which  case  it  will  read the file from standard input,\n       allowing zip to take input from another program. For example:\n\n              tar cf - . | zip backup -\n\n       would compress the output of the tar command for the purpose of backing\n       up  the  current  directory. This generally produces better compression\n       than the previous example using the -r  option  because  zip  can  take\n       advantage of redundancy between files. The backup can be restored using\n       the command\n\n              unzip -p backup | tar xf -\n\n       When no zip file name is given and stdout is not a terminal,  zip  acts\n       as  a filter, compressing standard input to standard output.  For exam-\n       ple,\n\n              tar cf - . | zip | dd of=/dev/nrst0 obs=16k\n\n       is equivalent to\n\n              tar cf - . | zip - - | dd of=/dev/nrst0 obs=16k\n\n       zip archives created in this manner can be extracted with  the  program\n       funzip  which  is  provided in the unzip package, or by gunzip which is\n       provided in the gzip package (but some gunzip may not support  this  if\n       zip used the Zip64 extensions). For example:\n\n              dd if=/dev/nrst0  ibs=16k | funzip | tar xvf -\n\n       The stream can also be saved to a file and unzip used.\n\n       If  Zip64  support  for  large files and archives is enabled and zip is\n       used as a filter, zip creates a Zip64 archive that requires a PKZIP 4.5\n       or  later compatible unzip to read it.  This is to avoid amgibuities in\n       the zip file structure as defined in the current zip  standard  (PKWARE\n       AppNote)  where  the decision to use Zip64 needs to be made before data\n       is written for the entry, but for a stream the size of the data is  not\n       known at that point.  If the data is known to be smaller than 4 GB, the\n       option -fz- can be used to prevent use of Zip64, but zip will exit with\n       an  error if Zip64 was in fact needed.  zip 3 and unzip 6 and later can\n       read archives with Zip64 entries.  Also, zip removes the  Zip64  exten-\n       sions  if  not  needed  when  archive  entries  are  copied (see the -U\n       (--copy) option).\n\n       When directing the output to another file, note that all options should\n       be before the redirection including -x.  For example:\n\n              zip archive \"*.h\" \"*.c\" -x donotinclude.h orthis.h > tofile\n\n       Zip files.   When  changing  an  existing zip archive, zip will write a\n       temporary file with the new contents, and only replace the old one when\n       the  process  of  creating  the  new version has been completed without\n       error.\n\n       If the name of the zip archive  does  not  contain  an  extension,  the\n       extension  .zip  is  added.  If  the name already contains an extension\n       other than .zip, the existing extension is  kept  unchanged.   However,\n       split  archives  (archives  split over multiple files) require the .zip\n       extension on the last split.\n\n       Scanning and reading files.  When zip starts, it  scans  for  files  to\n       process  (if  needed).  If this scan takes longer than about 5 seconds,\n       zip will display  a  \"Scanning  files\"  message  and  start  displaying\n       progress  dots  every  2  seconds  or  every so many entries processed,\n       whichever takes longer.  If there is more than 2 seconds  between  dots\n       it  could indicate that finding each file is taking time and could mean\n       a slow network connection for example.  (Actually the initial file scan\n       is  a  two-step  process where the directory scan is followed by a sort\n       and these two steps are separated with a space in the dots.  If  updat-\n       ing an existing archive, a space also appears between the existing file\n       scan and the new file scan.)  The scanning  files  dots  are  not  con-\n       trolled  by the -ds dot size option, but the dots are turned off by the\n       -q quiet option.  The -sf show files option can be  used  to  scan  for\n       files  and  get  the  list of files scanned without actually processing\n       them.\n\n       If zip is not able to read a file, it issues a warning  but  continues.\n       See  the -MM option below for more on how zip handles patterns that are\n       not matched and files that  are  not  readable.   If  some  files  were\n       skipped, a warning is issued at the end of the zip operation noting how\n       many files were read and how many skipped.\n\n       Command modes.  zip now supports two distinct types of  command  modes,\n       external  and  internal.  The external modes (add, update, and freshen)\n       read files from the file system (as well as from an  existing  archive)\n       while  the  internal  modes  (delete  and  copy) operate exclusively on\n       entries in an existing archive.\n\n       add\n              Update existing entries and add new files.  If the archive  does\n              not exist create it.  This is the default mode.\n\n       update (-u)\n              Update  existing entries if newer on the file system and add new\n              files.  If the archive does not exist issue warning then  create\n              a new archive.\n\n       freshen (-f)\n              Update  existing entries of an archive if newer on the file sys-\n              tem.  Does not add new files to the archive.\n\n       delete (-d)\n              Select entries in an existing archive and delete them.\n\n       copy (-U)\n              Select entries in an existing archive and copy  them  to  a  new\n              archive.   This  new  mode is similar to update but command line\n              patterns select entries in  the  existing  archive  rather  than\n              files from the file system and it uses the --out option to write\n              the resulting archive to a  new  file  rather  than  update  the\n              existing archive, leaving the original archive unchanged.\n\n       The new File Sync option (-FS) is also considered a new mode, though it\n       is similar to update.  This mode  synchronizes  the  archive  with  the\n       files  on  the OS, only replacing files in the archive if the file time\n       or size of the OS file is different, adding  new  files,  and  deleting\n       entries from the archive where there is no matching file.  As this mode\n       can delete entries from the archive, consider making a backup  copy  of\n       the archive.\n\n       Also see -DF for creating difference archives.\n\n       See  each option description below for details and the EXAMPLES section\n       below for examples.\n\n       Split archives.  zip version 3.0 and later can create  split  archives.\n       A  split  archive  is a standard zip archive split over multiple files.\n       (Note that split archives are not just archives split in to pieces,  as\n       the  offsets of entries are now based on the start of each split.  Con-\n       catenating the pieces together will invalidate these offsets, but unzip\n       can  usually  deal  with it.  zip will usually refuse to process such a\n       spliced archive unless the -FF fix option is used to fix the  offsets.)\n\n       One use of split archives is storing a large archive on multiple remov-\n       able media.  For a split archive with 20 split files the files are typ-\n       ically   named   (replace  ARCHIVE  with  the  name  of  your  archive)\n       ARCHIVE.z01, ARCHIVE.z02, ..., ARCHIVE.z19, ARCHIVE.zip.  Note that the\n       last  file  is  the  .zip  file.  In contrast, spanned archives are the\n       original multi-disk archive generally requiring floppy disks and  using\n       volume  labels  to store disk numbers.  zip supports split archives but\n       not spanned archives, though a procedure exists  for  converting  split\n       archives  of  the  right size to spanned archives.  The reverse is also\n       true, where each file of a spanned archive can be copied  in  order  to\n       files with the above names to create a split archive.\n\n       Use  -s  to set the split size and create a split archive.  The size is\n       given as a number followed optionally by one of k (kB), m (MB), g (GB),\n       or  t (TB) (the default is m).  The -sp option can be used to pause zip\n       between splits to allow changing removable media, for example, but read\n       the descriptions and warnings for both -s and -sp below.\n\n       Though  zip does not update split archives, zip provides the new option\n       -O (--output-file or --out) to allow split archives to be  updated  and\n       saved in a new archive.  For example,\n\n              zip inarchive.zip foo.c bar.c --out outarchive.zip\n\n       reads  archive  inarchive.zip,  even if split, adds the files foo.c and\n       bar.c, and writes the resulting archive to  outarchive.zip.   If  inar-\n       chive.zip is split then outarchive.zip defaults to the same split size.\n       Be aware that if outarchive.zip and any split files  that  are  created\n       with  it  already exist, these are always overwritten as needed without\n       warning.  This may be changed in the future.\n\n       Unicode.  Though the zip standard requires storing paths in an  archive\n       using  a  specific character set, in practice zips have stored paths in\n       archives in whatever the local character set is.  This creates problems\n       when  an  archive is created or updated on a system using one character\n       set and then extracted on another system using  a  different  character\n       set.  When compiled with Unicode support enabled on platforms that sup-\n       port wide characters, zip now stores, in addition to the standard local\n       path  for  backward  compatibility,  the UTF-8 translation of the path.\n       This provides a common universal character set for storing  paths  that\n       allows  these paths to be fully extracted on other systems that support\n       Unicode and to match as close as possible on systems that don't.\n\n       On Win32 systems where paths are internally stored as Unicode but  rep-\n       resented in the local character set, it's possible that some paths will\n       be skipped during a local character set directory scan.  zip with  Uni-\n       code support now can read and store these paths.  Note that Win 9x sys-\n       tems and FAT file systems don't fully support Unicode.\n\n       Be aware that console windows on Win32 and Unix, for example, sometimes\n       don't  accurately  show all characters due to how each operating system\n       switches in character sets for display.  However, directory  navigation\n       tools should show the correct paths if the needed fonts are loaded.\n\n       Command line format.  This version of zip has updated command line pro-\n       cessing and support for long options.\n\n       Short options take the form\n\n              -s[-][s[-]...][value][=value][ value]\n\n       where s is a one or two character short option.  A  short  option  that\n       takes  a value is last in an argument and anything after it is taken as\n       the value.  If the option can be negated and  \"-\"  immediately  follows\n       the  option, the option is negated.  Short options can also be given as\n       separate arguments\n\n              -s[-][value][=value][ value] -s[-][value][=value][ value] ...\n\n       Short options in general take values either as part of the  same  argu-\n       ment  or  as  the following argument.  An optional = is also supported.\n       So\n\n              -ttmmddyyyy\n\n       and\n\n              -tt=mmddyyyy\n\n       and\n\n              -tt mmddyyyy\n\n       all work.  The -x and -i options accept  lists  of  values  and  use  a\n       slightly  different format described below.  See the -x and -i options.\n\n       Long options take the form\n\n              --longoption[-][=value][ value]\n\n       where the option starts with --, has a multicharacter name, can include\n       a  trailing  dash to negate the option (if the option supports it), and\n       can have a value (option argument) specified by preceeding  it  with  =\n       (no spaces).  Values can also follow the argument.  So\n\n              --before-date=mmddyyyy\n\n       and\n\n              --before-date mmddyyyy\n\n       both work.\n\n       Long option names can be shortened to the shortest unique abbreviation.\n       See the option descriptions below for which support long  options.   To\n       avoid confusion, avoid abbreviating a negatable option with an embedded\n       dash (\"-\") at the dash if you plan to negate it (the parser would  con-\n       sider  a  trailing  dash,  such  as  for the option --some-option using\n       --some- as the option, as part of  the  name  rather  than  a  negating\n       dash).   This  may  be  changed to force the last dash in --some- to be\n       negating in the future.\n\nOPTIONS\n       -a\n       --ascii\n              [Systems using EBCDIC] Translate file to ASCII format.\n\n       -A\n       --adjust-sfx\n              Adjust self-extracting executable  archive.   A  self-extracting\n              executable  archive  is created by prepending the SFX stub to an\n              existing archive. The -A option tells zip to  adjust  the  entry\n              offsets  stored in the archive to take into account this \"pream-\n              ble\" data.\n\n       Note: self-extracting archives for the Amiga are a  special  case.   At\n       present, only the Amiga port of zip is capable of adjusting or updating\n       these without corrupting them. -J can be used to remove the SFX stub if\n       other updates need to be made.\n\n       -AC\n       --archive-clear\n              [WIN32]   Once  archive  is  created  (and tested if -T is used,\n              which is recommended), clear the  archive  bits  of  files  pro-\n              cessed.   WARNING:  Once  the bits are cleared they are cleared.\n              You may want to use the -sf show files option to store the  list\n              of  files  processed  in  case  the  archive  operation  must be\n              repeated.  Also consider using the -MM must  match  option.   Be\n              sure to check out -DF as a possibly better way to do incremental\n              backups.\n\n       -AS\n       --archive-set\n              [WIN32]  Only include files  that  have  the  archive  bit  set.\n              Directories  are  not stored when -AS is used, though by default\n              the paths of entries, including directories, are stored as usual\n              and can be used by most unzips to recreate directories.\n\n              The  archive  bit  is set by the operating system when a file is\n              modified and, if used with -AC, -AS can provide  an  incremental\n              backup  capability.   However, other applications can modify the\n              archive bit and it may not be  a  reliable  indicator  of  which\n              files  have  changed since the last archive operation.  Alterna-\n              tive ways to create incremental backups are using -t to use file\n              dates,  though  this won't catch old files copied to directories\n              being archived, and -DF to create a differential archive.\n\n       -B\n       --binary\n              [VM/CMS and MVS] force file to be read binary (default is text).\n\n       -Bn    [TANDEM] set Edit/Enscribe formatting options with n defined as\n              bit  0: Don't add delimiter (Edit/Enscribe)\n              bit  1: Use LF rather than CR/LF as delimiter (Edit/Enscribe)\n              bit  2: Space fill record to maximum record length (Enscribe)\n              bit  3: Trim trailing space (Enscribe)\n              bit  8: Force 30K (Expand) large read for unstructured files\n\n       -b path\n       --temp-path path\n              Use  the specified path for the temporary zip archive. For exam-\n              ple:\n\n                     zip -b /tmp stuff *\n\n              will put the temporary zip archive in the directory /tmp,  copy-\n              ing  over  stuff.zip  to  the  current directory when done. This\n              option is useful when updating an existing archive and the  file\n              system containing this old archive does not have enough space to\n              hold both old and new archives at the same time.  It may also be\n              useful  when  streaming in some cases to avoid the need for data\n              descriptors.  Note that using this option may require  zip  take\n              additional time to copy the archive file when done to the desti-\n              nation file system.\n\n       -c\n       --entry-comments\n              Add one-line comments for each file.  File  operations  (adding,\n              updating)  are  done  first, and the user is then prompted for a\n              one-line comment for each file.  Enter the comment  followed  by\n              return, or just return for no comment.\n\n       -C\n       --preserve-case\n              [VMS]   Preserve  case  all  on VMS.  Negating this option (-C-)\n              downcases.\n\n       -C2\n       --preserve-case-2\n              [VMS]  Preserve case ODS2 on VMS.  Negating this  option  (-C2-)\n              downcases.\n\n       -C5\n       --preserve-case-5\n              [VMS]   Preserve  case ODS5 on VMS.  Negating this option (-C5-)\n              downcases.\n\n       -d\n       --delete\n              Remove (delete) entries from a zip archive.  For example:\n\n                     zip -d foo foo/tom/junk foo/harry/\\* \\*.o\n\n              will remove the entry foo/tom/junk, all of the files that  start\n              with  foo/harry/,  and all of the files that end with .o (in any\n              path).  Note that shell pathname expansion  has  been  inhibited\n              with  backslashes,  so  that zip can see the asterisks, enabling\n              zip to match on the contents of the zip archive instead  of  the\n              contents  of  the  current  directory.  (The backslashes are not\n              used on MSDOS-based platforms.)  Can also use quotes  to  escape\n              the asterisks as in\n\n                     zip -d foo foo/tom/junk \"foo/harry/*\" \"*.o\"\n\n              Not  escaping  the asterisks on a system where the shell expands\n              wildcards could result in the asterisks  being  converted  to  a\n              list  of  files  in  the current directory and that list used to\n              delete entries from the archive.\n\n              Under MSDOS, -d is case sensitive when it matches names  in  the\n              zip  archive.  This requires that file names be entered in upper\n              case if they were zipped by PKZIP on an MSDOS system.  (We  con-\n              sidered making this case insensitive on systems where paths were\n              case insensitive, but it is possible the  archive  came  from  a\n              system where case does matter and the archive could include both\n              Bar and bar as separate files in the archive.)  But see the  new\n              option -ic to ignore case in the archive.\n\n       -db\n       --display-bytes\n              Display  running  byte  counts  showing the bytes zipped and the\n              bytes to go.\n\n       -dc\n       --display-counts\n              Display running count of entries zipped and entries to go.\n\n       -dd\n       --display-dots\n              Display dots while each entry is zipped (except  on  ports  that\n              have  their  own progress indicator).  See -ds below for setting\n              dot size.  The default is a dot every 10 MB of input  file  pro-\n              cessed.   The -v option also displays dots (previously at a much\n              higher rate than this but now -v also defaults  to  10  MB)  and\n              this rate is also controlled by -ds.\n\n       -df\n       --datafork\n              [MacOS] Include only data-fork of files zipped into the archive.\n              Good  for  exporting   files   to   foreign   operating-systems.\n              Resource-forks will be ignored at all.\n\n       -dg\n       --display-globaldots\n              Display  progress dots for the archive instead of for each file.\n              The command\n\n                         zip -qdgds 10m\n\n              will turn off most output except dots every 10 MB.\n\n       -ds size\n       --dot-size size\n              Set amount of input file processed for each dot displayed.   See\n              -dd to enable displaying dots.  Setting this option implies -dd.\n              Size is in the format nm where n is a number and m is  a  multi-\n              plier.  Currently m can be k (KB), m (MB), g (GB), or t (TB), so\n              if n is 100 and m is k, size would be 100k which is 100 KB.  The\n              default is 10 MB.\n\n              The -v option also displays dots and now defaults to 10 MB also.\n              This rate is also controlled by this option.  A size of 0  turns\n              dots off.\n\n              This  option does not control the dots from the \"Scanning files\"\n              message as zip scans for input files.  The dot size for that  is\n              fixed  at  2  seconds or a fixed number of entries, whichever is\n              longer.\n\n       -du\n       --display-usize\n              Display the uncompressed size of each entry.\n\n       -dv\n       --display-volume\n              Display the volume (disk) number each entry is being read  from,\n              if reading an existing archive, and being written to.\n\n       -D\n       --no-dir-entries\n              Do  not  create  entries  in  the  zip  archive for directories.\n              Directory  entries  are  created  by  default  so   that   their\n              attributes  can  be  saved  in the zip archive.  The environment\n              variable ZIPOPT can be used to change the default  options.  For\n              example under Unix with sh:\n\n                     ZIPOPT=\"-D\"; export ZIPOPT\n\n              (The  variable  ZIPOPT  can be used for any option, including -i\n              and -x using a new option format detailed below, and can include\n              several  options.)  The option -D is a shorthand for -x \"*/\" but\n              the latter previously could not be set as default in the  ZIPOPT\n              environment  variable  as  the  contents of ZIPOPT gets inserted\n              near the beginning of the command line and the file list had  to\n              end at the end of the line.\n\n              This  version  of  zip does allow -x and -i options in ZIPOPT if\n              the form\n\n              -x file file ... @\n\n              is used, where the @ (an argument that is just @) terminates the\n              list.\n\n       -DF\n       --difference-archive\n              Create  an archive that contains all new and changed files since\n              the original archive was created.  For this to work,  the  input\n              file  list  and current directory must be the same as during the\n              original zip operation.\n\n              For example, if the existing archive was created using\n\n                     zip -r foofull .\n\n              from the bar directory, then the command\n\n                     zip -r foofull . -DF --out foonew\n\n              also from the bar directory creates the archive foonew with just\n              the  files  not  in foofull and the files where the size or file\n              time of the files do not match those in foofull.\n\n              Note that the timezone environment variable  TZ  should  be  set\n              according to the local timezone in order for this option to work\n              correctly.  A change in timezone since the original archive  was\n              created  could  result  in no times matching and all files being\n              included.\n\n              A possible approach to backing up a directory might be to create\n              a  normal  archive  of  the  contents of the directory as a full\n              backup, then use this option to create incremental backups.\n\n       -e\n       --encrypt\n              Encrypt the contents of the zip archive using a  password  which\n              is  entered  on  the terminal in response to a prompt (this will\n              not be echoed; if standard error is not a  tty,  zip  will  exit\n              with  an  error).   The  password prompt is repeated to save the\n              user from typing errors.\n\n       -E\n       --longnames\n              [OS/2] Use the .LONGNAME Extended Attribute (if found) as  file-\n              name.\n\n       -f\n       --freshen\n              Replace  (freshen)  an existing entry in the zip archive only if\n              it has been modified more recently than the version  already  in\n              the zip archive; unlike the update option (-u) this will not add\n              files that are not already in the zip archive.  For example:\n\n                     zip -f foo\n\n              This command should be run from the same  directory  from  which\n              the  original  zip  command  was  run, since paths stored in zip\n              archives are always relative.\n\n              Note that the timezone environment variable  TZ  should  be  set\n              according  to  the local timezone in order for the -f, -u and -o\n              options to work correctly.\n\n              The reasons behind this are somewhat subtle but have to do  with\n              the  differences  between  the Unix-format file times (always in\n              GMT) and most of the other operating systems (always local time)\n              and  the  necessity  to  compare the two.  A typical TZ value is\n              ``MET-1MEST'' (Middle European time  with  automatic  adjustment\n              for ``summertime'' or Daylight Savings Time).\n\n              The  format is TTThhDDD, where TTT is the time zone such as MET,\n              hh is the difference between GMT  and  local  time  such  as  -1\n              above, and DDD is the time zone when daylight savings time is in\n              effect.  Leave off the DDD if there is no daylight savings time.\n              For the US Eastern time zone EST5EDT.\n\n       -F\n       --fix\n       -FF\n       --fixfix\n              Fix  the zip archive. The -F option can be used if some portions\n              of the archive are missing, but  requires  a  reasonably  intact\n              central  directory.   The input archive is scanned as usual, but\n              zip will ignore some problems.  The resulting archive should  be\n              valid, but any inconsistent entries will be left out.\n\n              When  doubled  as in -FF, the archive is scanned from the begin-\n              ning and zip scans for special signatures to identify the limits\n              between  the  archive members. The single -F is more reliable if\n              the archive is not too much damaged, so try this option first.\n\n              If the archive is too damaged or the end has been truncated, you\n              must  use  -FF.   This  is  a change from zip 2.32, where the -F\n              option is able to read a truncated archive.  The -F  option  now\n              more  reliably  fixes  archives  with  minor  damage and the -FF\n              option is needed to fix archives where -F might have been suffi-\n              cient before.\n\n              Neither  option will recover archives that have been incorrectly\n              transferred in ascii mode instead of binary. After  the  repair,\n              the  -t option of unzip may show that some files have a bad CRC.\n              Such files cannot be recovered; you can  remove  them  from  the\n              archive using the -d option of zip.\n\n              Note  that  -FF may have trouble fixing archives that include an\n              embedded zip archive that was stored  (without  compression)  in\n              the  archive  and,  depending  on  the  damage,  it may find the\n              entries in the embedded archive rather than the archive  itself.\n              Try -F first as it does not have this problem.\n\n              The  format  of  the fix commands have changed.  For example, to\n              fix the damaged archive foo.zip,\n\n                     zip -F foo --out foofix\n\n              tries to read the entries normally, copying good entries to  the\n              new  archive  foofix.zip.   If  this  doesn't  work, as when the\n              archive is truncated, or if some entries you  know  are  in  the\n              archive are missed, then try\n\n                     zip -FF foo --out foofixfix\n\n              and  compare the resulting archive to the archive created by -F.\n              The -FF option may create an inconsistent archive.  Depending on\n              what  is  damaged,  you  can  then use the -F option to fix that\n              archive.\n\n              A split archive with missing split files can be fixed  using  -F\n              if  you  have the last split of the archive (the .zip file).  If\n              this file is missing, you must use -FF to fix the archive, which\n              will prompt you for the splits you have.\n\n              Currently  the fix options can't recover entries that have a bad\n              checksum or are otherwise damaged.\n\n       -FI\n       --fifo [Unix]  Normally zip  skips  reading  any  FIFOs  (named  pipes)\n              encountered, as zip can hang if the FIFO is not being fed.  This\n              option tells zip to read the contents of any FIFO it finds.\n\n       -FS\n       --filesync\n              Synchronize the contents of an archive with the files on the OS.\n              Normally  when  an  archive  is updated, new files are added and\n              changed files are updated but files that no longer exist on  the\n              OS  are not deleted from the archive.  This option enables a new\n              mode that checks entries in the archive against the file system.\n              If  the file time and file size of the entry matches that of the\n              OS file, the entry is copied from the  old  archive  instead  of\n              being  read from the file system and compressed.  If the OS file\n              has changed, the entry is read and compressed as usual.  If  the\n              entry  in the archive does not match a file on the OS, the entry\n              is deleted.  Enabling this option should  create  archives  that\n              are  the  same  as  new archives, but since existing entries are\n              copied instead of compressed, updating an existing archive  with\n              -FS  can  be much faster than creating a new archive.  Also con-\n              sider using -u for updating an archive.\n\n              For this option to work, the archive should be updated from  the\n              same  directory  it  was created in so the relative paths match.\n              If few files are being copied from the old archive,  it  may  be\n              faster to create a new archive instead.\n\n              Note  that  the  timezone  environment variable TZ should be set\n              according to the local timezone in order for this option to work\n              correctly.   A change in timezone since the original archive was\n              created could result in no times matching and  recompression  of\n              all files.\n\n              This option deletes files from the archive.  If you need to pre-\n              serve the original archive, make a copy of the archive first  or\n              use  the  --out  option  to  output the updated archive to a new\n              file.  Even though it may be slower, creating a new archive with\n              a  new  archive name is safer, avoids mismatches between archive\n              and OS paths, and is preferred.\n\n       -g\n       --grow\n              Grow (append to) the specified zip archive, instead of  creating\n              a  new one. If this operation fails, zip attempts to restore the\n              archive to its original state. If  the  restoration  fails,  the\n              archive  might  become  corrupted.  This  option is ignored when\n              there's no existing archive or when at least one archive  member\n              must be updated or deleted.\n\n       -h\n       -?\n       --help\n              Display  the  zip  help information (this also appears if zip is\n              run with no arguments).\n\n       -h2\n       --more-help\n              Display extended help including more  on  command  line  format,\n              pattern matching, and more obscure options.\n\n       -i files\n       --include files\n              Include only the specified files, as in:\n\n                     zip -r foo . -i \\*.c\n\n              which  will include only the files that end in .c in the current\n              directory and its subdirectories. (Note  for  PKZIP  users:  the\n              equivalent command is\n\n                     pkzip -rP foo *.c\n\n              PKZIP  does  not  allow  recursion in directories other than the\n              current one.)  The backslash avoids the shell filename substitu-\n              tion,  so  that  the  name  matching  is performed by zip at all\n              directory levels.  [This is for Unix and other systems  where  \\\n              escapes  the  next character.  For other systems where the shell\n              does not process * do not use \\ and the above is\n\n                     zip -r foo . -i *.c\n\n              Examples are  for  Unix  unless  otherwise  specified.]   So  to\n              include  dir,  a directory directly under the current directory,\n              use\n\n                     zip -r foo . -i dir/\\*\n\n              or\n\n                     zip -r foo . -i \"dir/*\"\n\n              to match paths such as dir/a and dir/b/file.c [on ports  without\n              wildcard expansion in the shell such as MSDOS and Windows\n\n                     zip -r foo . -i dir/*\n\n              is  used.]   Note  that  currently  the trailing / is needed for\n              directories (as in\n\n                     zip -r foo . -i dir/\n\n              to include directory dir).\n\n              The long option form of the first example is\n\n                     zip -r foo . --include \\*.c\n\n              and does the same thing as the short option form.\n\n              Though the command syntax used to require -i at the end  of  the\n              command  line,  this  version  actually allows -i (or --include)\n              anywhere.  The list of files terminates  at  the  next  argument\n              starting with -, the end of the command line, or the list termi-\n              nator @ (an argument that is just @).  So the above can be given\n              as\n\n                     zip -i \\*.c @ -r foo .\n\n              for  example.   There must be a space between the option and the\n              first file of a list.  For just one file you can use the  single\n              value form\n\n                     zip -i\\*.c -r foo .\n\n              (no space between option and value) or\n\n                     zip --include=\\*.c -r foo .\n\n              as  additional  examples.  The single value forms are not recom-\n              mended because they can be confusing  and,  in  particular,  the\n              -ifile  format  can  cause  problems if the first letter of file\n              combines with i to form a two-letter  option  starting  with  i.\n              Use -sc to see how your command line will be parsed.\n\n              Also possible:\n\n                     zip -r foo  . -i@include.lst\n\n              which  will  only include the files in the current directory and\n              its  subdirectories  that  match  the  patterns  in   the   file\n              include.lst.\n\n              Files to -i and -x are patterns matching internal archive paths.\n              See -R for more on patterns.\n\n       -I\n       --no-image\n              [Acorn RISC OS] Don't scan through Image files.  When used,  zip\n              will  not  consider  Image  files  (eg.  DOS partitions or Spark\n              archives when SparkFS is loaded) as directories but  will  store\n              them as single files.\n\n              For example, if you have SparkFS loaded, zipping a Spark archive\n              will result in a zipfile containing a directory  (and  its  con-\n              tent)  while  using the 'I' option will result in a zipfile con-\n              taining a Spark archive. Obviously this second case will also be\n              obtained (without the 'I' option) if SparkFS isn't loaded.\n\n       -ic\n       --ignore-case\n              [VMS,  WIN32]  Ignore  case when matching archive entries.  This\n              option is only available on systems where the case of  files  is\n              ignored.  On systems with case-insensitive file systems, case is\n              normally ignored when matching files on the file system  but  is\n              not  ignored for -f (freshen), -d (delete), -U (copy), and simi-\n              lar modes when matching against archive  entries  (currently  -f\n              ignores case on VMS) because archive entries can be from systems\n              where case does matter and names that are the  same  except  for\n              case can exist in an archive.  The -ic option makes all matching\n              case insensitive.  This can result in multiple  archive  entries\n              matching a command line pattern.\n\n       -j\n       --junk-paths\n              Store  just the name of a saved file (junk the path), and do not\n              store directory names. By default, zip will store the full  path\n              (relative to the current directory).\n\n       -jj\n       --absolute-path\n              [MacOS] record Fullpath (+ Volname). The complete path including\n              volume will be stored. By default  the  relative  path  will  be\n              stored.\n\n       -J\n       --junk-sfx\n              Strip any prepended data (e.g. a SFX stub) from the archive.\n\n       -k\n       --DOS-names\n              Attempt  to  convert  the  names  and paths to conform to MSDOS,\n              store only the MSDOS attribute (just the  user  write  attribute\n              from  Unix), and mark the entry as made under MSDOS (even though\n              it was not); for compatibility with PKUNZIP  under  MSDOS  which\n              cannot handle certain names such as those with two dots.\n\n       -l\n       --to-crlf\n              Translate  the Unix end-of-line character LF into the MSDOS con-\n              vention CR LF. This option should not be used on  binary  files.\n              This  option can be used on Unix if the zip file is intended for\n              PKUNZIP under MSDOS. If the input files already contain  CR  LF,\n              this option adds an extra CR. This is to ensure that unzip -a on\n              Unix will get back an exact copy of the original file,  to  undo\n              the effect of zip -l.  See -ll for how binary files are handled.\n\n       -la\n       --log-append\n              Append to existing logfile.  Default is to overwrite.\n\n       -lf logfilepath\n       --logfile-path logfilepath\n              Open a logfile at the given path.  By default any existing  file\n              at  that location is overwritten, but the -la option will result\n              in an existing file being opened and  the  new  log  information\n              appended  to any existing information.  Only warnings and errors\n              are written to the log unless the -li option is also given, then\n              all information messages are also written to the log.\n\n       -li\n       --log-info\n              Include  information  messages, such as file names being zipped,\n              in the log.  The default is to only include  the  command  line,\n              any warnings and errors, and the final status.\n\n       -ll\n       --from-crlf\n              Translate the MSDOS end-of-line CR LF into Unix LF.  This option\n              should not be used on binary files.  This option can be used  on\n              MSDOS  if the zip file is intended for unzip under Unix.  If the\n              file is converted and the file is later determined to be  binary\n              a warning is issued and the file is probably corrupted.  In this\n              release if -ll detects binary in the first buffer  read  from  a\n              file,  zip now issues a warning and skips line end conversion on\n              the file.  This check seems to catch all  binary  files  tested,\n              but  the original check remains and if a converted file is later\n              determined to be binary that warning is  still  issued.   A  new\n              algorithm  is  now  being  used for binary detection that should\n              allow line end conversion of text files  in  UTF-8  and  similar\n              encodings.\n\n       -L\n       --license\n              Display the zip license.\n\n       -m\n       --move\n              Move  the  specified  files into the zip archive; actually, this\n              deletes the target directories/files after making the  specified\n              zip  archive.  If a directory becomes empty after removal of the\n              files, the directory is also  removed.  No  deletions  are  done\n              until zip has created the archive without error.  This is useful\n              for conserving disk space, but is potentially dangerous so it is\n              recommended to use it in combination with -T to test the archive\n              before removing all input files.\n\n       -MM\n       --must-match\n              All input patterns must match at least one file  and  all  input\n              files  found  must  be readable.  Normally when an input pattern\n              does not match a file the \"name not matched\" warning  is  issued\n              and  when  an  input file has been found but later is missing or\n              not readable a missing or not readable warning  is  issued.   In\n              either  case zip continues creating the archive, with missing or\n              unreadable new files being skipped  and  files  already  in  the\n              archive  remaining  unchanged.  After the archive is created, if\n              any files were not readable zip returns the OPEN error code  (18\n              on most systems) instead of the normal success return (0 on most\n              systems).  With -MM set, zip exits as soon as an  input  pattern\n              is not matched (whenever the \"name not matched\" warning would be\n              issued) or when an input file is not readable.  In  either  case\n              zip exits with an OPEN error and no archive is created.\n\n              This option is useful when a known list of files is to be zipped\n              so any missing or unreadable files will result in an error.   It\n              is less useful when used with wildcards, but zip will still exit\n              with an error if any input pattern doesn't match  at  least  one\n              file  and  if  any matched files are unreadable.  If you want to\n              create the archive anyway and only need to know  if  files  were\n              skipped, don't use -MM and just check the return code.  Also -lf\n              could be useful.\n\n       -n suffixes\n       --suffixes suffixes\n              Do not attempt to compress files named with the given  suffixes.\n              Such  files are simply stored (0% compression) in the output zip\n              file, so that zip doesn't waste  its  time  trying  to  compress\n              them.   The  suffixes  are  separated  by either colons or semi-\n              colons.  For example:\n\n                     zip -rn .Z:.zip:.tiff:.gif:.snd  foo foo\n\n              will copy everything from foo into foo.zip, but will  store  any\n              files  that end in .Z, .zip, .tiff, .gif, or .snd without trying\n              to compress them (image and sound files  often  have  their  own\n              specialized compression methods).  By default, zip does not com-\n              press     files     with     extensions     in     the      list\n              .Z:.zip:.zoo:.arc:.lzh:.arj.   Such files are stored directly in\n              the output archive.  The environment variable ZIPOPT can be used\n              to change the default options. For example under Unix with csh:\n\n                     setenv ZIPOPT \"-n .gif:.zip\"\n\n              To attempt compression on all files, use:\n\n                     zip -n : foo\n\n              The  maximum  compression option -9 also attempts compression on\n              all files regardless of extension.\n\n              On Acorn RISC OS systems the suffixes are actually filetypes  (3\n              hex  digit format). By default, zip does not compress files with\n              filetypes in the list DDC:D96:68E (i.e. Archives, CFS files  and\n              PackDir files).\n\n       -nw\n       --no-wild\n              Do not perform internal wildcard processing (shell processing of\n              wildcards is still done by the shell unless  the  arguments  are\n              escaped).   Useful if a list of paths is being read and no wild-\n              card substitution is desired.\n\n       -N\n       --notes\n              [Amiga, MacOS] Save Amiga or MacOS  filenotes  as  zipfile  com-\n              ments.  They can be restored by using the -N option of unzip. If\n              -c is used also, you are prompted for comments  only  for  those\n              files that do not have filenotes.\n\n       -o\n       --latest-time\n              Set  the  \"last  modified\" time of the zip archive to the latest\n              (oldest) \"last modified\" time found among the entries in the zip\n              archive.   This  can  be  used  without any other operations, if\n              desired.  For example:\n\n              zip -o foo\n\n              will change the last modified time of foo.zip to the latest time\n              of the entries in foo.zip.\n\n       -O output-file\n       --output-file output-file\n              Process  the  archive  changes as usual, but instead of updating\n              the existing archive, output the  new  archive  to  output-file.\n              Useful  for  updating  an  archive without changing the existing\n              archive and the input archive must be a different file than  the\n              output archive.\n\n              This  option  can  be used to create updated split archives.  It\n              can also be used with  -U  to  copy  entries  from  an  existing\n              archive to a new archive.  See the EXAMPLES section below.\n\n              Another  use  is  converting  zip  files  from one split size to\n              another.  For instance, to convert an archive  with  700  MB  CD\n              splits to one with 2 GB DVD splits, can use:\n\n                     zip -s 2g cd-split.zip --out dvd-split.zip\n\n              which uses copy mode.  See -U below.  Also:\n\n                     zip -s 0 split.zip --out unsplit.zip\n\n              will convert a split archive to a single-file archive.\n\n              Copy  mode  will  convert stream entries (using data descriptors\n              and which should be  compatible  with  most  unzips)  to  normal\n              entries  (which should be compatible with all unzips), except if\n              standard encryption  was  used.   For  archives  with  encrypted\n              entries,  zipcloak  will decrypt the entries and convert them to\n              normal entries.\n\n       -p\n       --paths\n              Include relative file paths as part of the names of files stored\n              in  the  archive.  This is the default.  The -j option junks the\n              paths and just stores the names of the files.\n\n       -P password\n       --password password\n              Use password to encrypt zipfile entries (if any).  THIS IS INSE-\n              CURE!   Many  multi-user  operating systems provide ways for any\n              user to see the current command line of any other user; even  on\n              stand-alone  systems  there  is  always  the threat of over-the-\n              shoulder peeking.  Storing the plaintext password as part  of  a\n              command  line  in  an  automated script is even worse.  Whenever\n              possible, use the non-echoing, interactive prompt to enter pass-\n              words.   (And  where  security  is  truly  important, use strong\n              encryption such as Pretty Good Privacy instead of the relatively\n              weak standard encryption provided by zipfile utilities.)\n\n       -q\n       --quiet\n              Quiet   mode;   eliminate  informational  messages  and  comment\n              prompts.  (Useful, for example, in shell scripts and  background\n              tasks).\n\n       -Qn\n       --Q-flag n\n              [QDOS]  store information about the file in the file header with\n              n defined as\n              bit  0: Don't add headers for any file\n              bit  1: Add headers for all files\n              bit  2: Don't wait for interactive key press on exit\n\n       -r\n       --recurse-paths\n              Travel the directory structure recursively; for example:\n\n                     zip -r foo.zip foo\n\n              or more concisely\n\n                     zip -r foo foo\n\n              In this case, all the files and directories in foo are saved  in\n              a zip archive named foo.zip, including files with names starting\n              with \".\", since the recursion does not use the shell's file-name\n              substitution  mechanism.  If you wish to include only a specific\n              subset of the files in directory foo and its subdirectories, use\n              the  -i  option  to specify the pattern of files to be included.\n              You should not use -r with the name  \".*\",  since  that  matches\n              \"..\"   which will attempt to zip up the parent directory (proba-\n              bly not what was intended).\n\n              Multiple source directories are allowed as in\n\n                     zip -r foo foo1 foo2\n\n              which first zips up foo1 and then foo2, going down  each  direc-\n              tory.\n\n              Note  that  while  wildcards  to -r are typically resolved while\n              recursing down directories in the file system, any -R,  -x,  and\n              -i  wildcards are applied to internal archive pathnames once the\n              directories are scanned.  To have wildcards apply  to  files  in\n              subdirectories  when recursing on Unix and similar systems where\n              the shell does wildcard substitution, either  escape  all  wild-\n              cards  or put all arguments with wildcards in quotes.  This lets\n              zip see the wildcards and match files  in  subdirectories  using\n              them as it recurses.\n\n       -R\n       --recurse-patterns\n              Travel  the directory structure recursively starting at the cur-\n              rent directory; for example:\n\n                     zip -R foo \"*.c\"\n\n              In this case, all the files matching *.c in the tree starting at\n              the  current  directory  are  stored  into  a  zip archive named\n              foo.zip.  Note that *.c will match file.c, a/file.c and  a/b/.c.\n              More than one pattern can be listed as separate arguments.  Note\n              for PKZIP users: the equivalent command is\n\n                     pkzip -rP foo *.c\n\n              Patterns are relative file paths as they appear in the  archive,\n              or  will after zipping, and can have optional wildcards in them.\n              For example, given the current directory is foo and under it are\n              directories foo1 and foo2 and in foo1 is the file bar.c,\n\n                     zip -R foo/*\n\n              will zip up foo, foo/foo1, foo/foo1/bar.c, and foo/foo2.\n\n                     zip -R */bar.c\n\n              will  zip  up  foo/foo1/bar.c.   See the note for -r on escaping\n              wildcards.\n\n       -RE\n       --regex\n              [WIN32]  Before zip 3.0, regular expression  list  matching  was\n              enabled  by  default on Windows platforms.  Because of confusion\n              resulting from the need to escape \"[\" and \"]\" in  names,  it  is\n              now  off  by  default for Windows so \"[\" and \"]\" are just normal\n              characters in names.  This option enables [] matching again.\n\n       -s splitsize\n       --split-size splitsize\n              Enable creating a split archive and set the split size.  A split\n              archive  is  an archive that could be split over many files.  As\n              the archive is created, if the size of the archive  reaches  the\n              specified  split  size,  that split is closed and the next split\n              opened.  In general all splits but the last will  be  the  split\n              size  and  the  last  will  be  whatever is left.  If the entire\n              archive is smaller than the split size a single-file archive  is\n              created.\n\n              Split  archives  are  stored in numbered files.  For example, if\n              the output  archive  is  named  archive  and  three  splits  are\n              required,  the  resulting  archive  will  be  in the three files\n              archive.z01, archive.z02, and archive.zip.  Do  not  change  the\n              numbering  of these files or the archive will not be readable as\n              these are used to determine the order the splits are read.\n\n              Split size is a number  optionally  followed  by  a  multiplier.\n              Currently  the  number  must  be an integer.  The multiplier can\n              currently be one of k (kilobytes), m (megabytes), g (gigabytes),\n              or  t  (terabytes).   As  64k is the minimum split size, numbers\n              without multipliers default to megabytes.  For example, to  cre-\n              ate  a  split  archive  called  foo with the contents of the bar\n              directory with splits of 670 MB that might be useful for burning\n              on CDs, the command:\n\n                     zip -s 670m -r foo bar\n\n              could be used.\n\n              Currently  the  old  splits  of a split archive are not excluded\n              from a new archive, but they can be specifically  excluded.   If\n              possible,  keep  the  input  and output archives out of the path\n              being zipped when creating split archives.\n\n              Using -s without -sp as above creates all the splits  where  foo\n              is  being  written,  in  this  case the current directory.  This\n              split mode updates the splits as the archive is  being  created,\n              requiring  all  splits  to  remain  writable,  but creates split\n              archives that are readable by  any  unzip  that  supports  split\n              archives.   See  -sp  below  for enabling split pause mode which\n              allows splits to be written directly to removable media.\n\n              The option -sv can be used to enable verbose splitting and  pro-\n              vide details of how the splitting is being done.  The -sb option\n              can be used to ring the bell when zip pauses for the next  split\n              destination.\n\n              Split  archives cannot be updated, but see the -O (--out) option\n              for how a split archive can be updated as it is copied to a  new\n              archive.   A  split archive can also be converted into a single-\n              file archive using a split size of 0 or negating the -s option:\n\n                     zip -s 0 split.zip --out single.zip\n\n              Also see -U (--copy) for more on using copy mode.\n\n       -sb\n       --split-bell\n              If splitting and using split pause mode, ring the bell when  zip\n              pauses for each split destination.\n\n       -sc\n       --show-command\n              Show  the  command line starting zip as processed and exit.  The\n              new command parser permutes the arguments, putting  all  options\n              and  any values associated with them before any non-option argu-\n              ments.  This allows an option to appear anywhere in the  command\n              line  as  long as any values that go with the option go with it.\n              This option displays the command line as zip sees it,  including\n              any arguments from the environment such as from the ZIPOPT vari-\n              able.  Where allowed, options later  in  the  command  line  can\n              override options earlier in the command line.\n\n       -sf\n       --show-files\n              Show  the  files  that  would  be  operated  on, then exit.  For\n              instance, if creating a new archive, this will  list  the  files\n              that  would  be  added.   If the option is negated, -sf-, output\n              only to an open log file.  Screen display is not recommended for\n              large lists.\n\n       -so\n       --show-options\n              Show  all  available options supported by zip as compiled on the\n              current system.  As this command  reads  the  option  table,  it\n              should include all options.  Each line includes the short option\n              (if defined), the long option (if defined), the  format  of  any\n              value  that  goes with the option, if the option can be negated,\n              and a small description.  The value  format  can  be  no  value,\n              required  value,  optional value, single character value, number\n              value, or a list of values.  The output of this  option  is  not\n              intended  to  show  how  to  use  any  option but only show what\n              options are available.\n\n       -sp\n       --split-pause\n              If splitting is enabled with -s, enable split pause mode.   This\n              creates split archives as -s does, but stream writing is used so\n              each split can be closed as soon as it is written and  zip  will\n              pause  between each split to allow changing split destination or\n              media.\n\n              Though this split mode allows writing splits directly to  remov-\n              able  media, it uses stream archive format that may not be read-\n              able by some unzips.  Before relying on splits created with -sp,\n              test a split archive with the unzip you will be using.\n\n              To  convert a stream split archive (created with -sp) to a stan-\n              dard archive see the --out option.\n\n       -su\n       --show-unicode\n              As -sf, but also show Unicode version of the path if exists.\n\n       -sU\n       --show-just-unicode\n              As -sf, but only show Unicode version of  the  path  if  exists,\n              otherwise show the standard version of the path.\n\n       -sv\n       --split-verbose\n              Enable various verbose messages while splitting, showing how the\n              splitting is being done.\n\n       -S\n       --system-hidden\n              [MSDOS, OS/2, WIN32 and ATARI] Include system and hidden  files.\n              [MacOS]  Includes finder invisible files, which are ignored oth-\n              erwise.\n\n       -t mmddyyyy\n       --from-date mmddyyyy\n              Do not operate on files modified prior to  the  specified  date,\n              where  mm  is  the  month  (00-12),  dd  is the day of the month\n              (01-31), and  yyyy  is  the  year.   The  ISO 8601  date  format\n              yyyy-mm-dd is also accepted.  For example:\n\n                     zip -rt 12071991 infamy foo\n\n                     zip -rt 1991-12-07 infamy foo\n\n              will  add  all the files in foo and its subdirectories that were\n              last modified on or after 7 December 1991, to  the  zip  archive\n              infamy.zip.\n\n       -tt mmddyyyy\n       --before-date mmddyyyy\n              Do not operate on files modified after or at the specified date,\n              where mm is the month (00-12),  dd  is  the  day  of  the  month\n              (01-31),  and  yyyy  is  the  year.   The  ISO 8601  date format\n              yyyy-mm-dd is also accepted.  For example:\n\n                     zip -rtt 11301995 infamy foo\n\n                     zip -rtt 1995-11-30 infamy foo\n\n              will add all the files in foo and its subdirectories  that  were\n              last  modified  before  30  November  1995,  to  the zip archive\n              infamy.zip.\n\n       -T\n       --test\n              Test the integrity of the new zip file. If the check fails,  the\n              old  zip  file  is  unchanged  and (with the -m option) no input\n              files are removed.\n\n       -TT cmd\n       --unzip-command cmd\n              Use command cmd instead of 'unzip -tqq' to test an archive  when\n              the  -T  option is used.  On Unix, to use a copy of unzip in the\n              current directory instead of the standard  system  unzip,  could\n              use:\n\n               zip archive file1 file2 -T -TT \"./unzip -tqq\"\n\n              In  cmd,  {}  is  replaced by the name of the temporary archive,\n              otherwise the name of the archive is appended to the end of  the\n              command.  The return code is checked for success (0 on Unix).\n\n       -u\n       --update\n              Replace (update) an existing entry in the zip archive only if it\n              has been modified more recently than the version already in  the\n              zip archive.  For example:\n\n                     zip -u stuff *\n\n              will  add any new files in the current directory, and update any\n              files which have been modified since the zip  archive  stuff.zip\n              was  last  created/modified  (note that zip will not try to pack\n              stuff.zip into itself when you do this).\n\n              Note that the -u option with no input file arguments  acts  like\n              the -f (freshen) option.\n\n       -U\n       --copy-entries\n              Copy  entries  from  one archive to another.  Requires the --out\n              option to  specify  a  different  output  file  than  the  input\n              archive.  Copy mode is the reverse of -d delete.  When delete is\n              being used with --out, the selected entries are deleted from the\n              archive  and  all  other  entries are copied to the new archive,\n              while copy mode selects the files to include in the new archive.\n              Unlike -u update, input patterns on the command line are matched\n              against archive entries only and not the file system files.  For\n              instance,\n\n                     zip inarchive \"*.c\" --copy --out outarchive\n\n              copies  entries  with  names ending in .c from inarchive to out-\n              archive.  The wildcard must be escaped on some systems  to  pre-\n              vent  the  shell  from substituting names of files from the file\n              system which may  have  no  relevance  to  the  entries  in  the\n              archive.\n\n              If  no input files appear on the command line and --out is used,\n              copy mode is assumed:\n\n                     zip inarchive --out outarchive\n\n              This is useful for changing split size for instance.  Encrypting\n              and  decrypting  entries  is  not yet supported using copy mode.\n              Use zipcloak for that.\n\n       -UN v\n       --unicode v\n              Determine what zip should do with Unicode file names.   zip 3.0,\n              in  addition  to  the standard file path, now includes the UTF-8\n              translation of the path if the entry path is not entirely  7-bit\n              ASCII.   When  an entry is missing the Unicode path, zip reverts\n              back to the standard file path.   The  problem  with  using  the\n              standard  path is this path is in the local character set of the\n              zip that created the entry, which may  contain  characters  that\n              are  not  valid  in  the  character set being used by the unzip.\n              When zip is reading an archive, if an entry also has  a  Unicode\n              path, zip now defaults to using the Unicode path to recreate the\n              standard path using the current local character set.\n\n              This option can be used to determine what  zip  should  do  with\n              this  path  if  there  is a mismatch between the stored standard\n              path and the stored UTF-8 path (which can happen if the standard\n              path  was  updated).  In all cases, if there is a mismatch it is\n              assumed that the standard path is  more  current  and  zip  uses\n              that.  Values for v are\n\n                     q - quit if paths do not match\n\n                     w - warn, continue with standard path\n\n                     i - ignore, continue with standard path\n\n                     n - no Unicode, do not use Unicode paths\n\n              The default is to warn and continue.\n\n              Characters  that  are not valid in the current character set are\n              escaped as #Uxxxx and #Lxxxxxx, where x is  an  ASCII  character\n              for a hex digit.  The first is used if a 16-bit character number\n              is sufficient to represent the Unicode character and the  second\n              if  the character needs more than 16 bits to represent it's Uni-\n              code character code.  Setting -UN to\n\n                     e - escape\n\n              as in\n\n                     zip archive -sU -UN=e\n\n              forces zip to escape all characters that are not printable 7-bit\n              ASCII.\n\n              Normally zip stores UTF-8 directly in the standard path field on\n              systems where UTF-8 is the current character set and stores  the\n              UTF-8 in the new extra fields otherwise.  The option\n\n                     u - UTF-8\n\n              as in\n\n                     zip archive dir -r -UN=UTF8\n\n              forces  zip  to store UTF-8 as native in the archive.  Note that\n              storing UTF-8 directly is the default on Unix systems that  sup-\n              port  it.   This option could be useful on Windows systems where\n              the escaped path is too large to be a valid path and  the  UTF-8\n              version of the path is smaller, but native UTF-8 is not backward\n              compatible on Windows systems.\n\n       -v\n       --verbose\n              Verbose mode or print diagnostic version info.\n\n              Normally, when applied to real operations, this  option  enables\n              the  display of a progress indicator during compression (see -dd\n              for more on dots) and requests  verbose  diagnostic  info  about\n              zipfile structure oddities.\n\n              However,  when -v is the only command line argument a diagnostic\n              screen is printed instead.  This should now work even if  stdout\n              is redirected to a file, allowing easy saving of the information\n              for sending with bug reports to Info-ZIP.   The  version  screen\n              provides  the help screen header with program name, version, and\n              release date, some pointers to the Info-ZIP home  and  distribu-\n              tion  sites,  and shows information about the target environment\n              (compiler type and version, OS version, compilation date and the\n              enabled optional features used to create the zip executable).\n\n       -V\n       --VMS-portable\n              [VMS]  Save VMS file attributes.  (Files are  truncated at EOF.)\n              When a -V archive is unpacked on a non-VMS  system,   some  file\n              types  (notably  Stream_LF  text  files   and  pure binary files\n              like fixed-512) should be extracted intact.  Indexed  files  and\n              file  types  with embedded record sizes (notably variable-length\n              record types) will probably be seen as corrupt elsewhere.\n\n       -VV\n       --VMS-specific\n              [VMS] Save VMS file attributes, and  all allocated blocks  in  a\n              file,   including  any  data beyond EOF.  Useful for moving ill-\n              formed files  among   VMS  systems.    When  a  -VV  archive  is\n              unpacked  on a non-VMS system, almost all files will appear cor-\n              rupt.\n\n       -w\n       --VMS-versions\n              [VMS] Append the version  number  of  the  files  to  the  name,\n              including  multiple  versions  of files.  Default is to use only\n              the most recent version of a specified file.\n\n       -ww\n       --VMS-dot-versions\n              [VMS] Append the version  number  of  the  files  to  the  name,\n              including  multiple  versions  of  files, using the .nnn format.\n              Default is to use only the most recent version  of  a  specified\n              file.\n\n       -ws\n       --wild-stop-dirs\n              Wildcards match only at a directory level.  Normally zip handles\n              paths as strings and given the paths\n\n                     /foo/bar/dir/file1.c\n\n                     /foo/bar/file2.c\n\n              an input pattern such as\n\n                     /foo/bar/*\n\n              normally would match both paths, the * matching dir/file1.c  and\n              file2.c.   Note  that in the first case a directory boundary (/)\n              was crossed in the match.  With -ws no directory bounds will  be\n              included  in  the  match,  making  wildcards local to a specific\n              directory level.  So, with -ws enabled,  only  the  second  path\n              would be matched.\n\n              When using -ws, use ** to match across directory boundaries as *\n              does normally.\n\n       -x files\n       --exclude files\n              Explicitly exclude the specified files, as in:\n\n                     zip -r foo foo -x \\*.o\n\n              which will include the contents of foo in foo.zip while  exclud-\n              ing  all  the  files  that  end in .o.  The backslash avoids the\n              shell filename substitution, so that the name matching  is  per-\n              formed by zip at all directory levels.\n\n              Also possible:\n\n                     zip -r foo foo -x@exclude.lst\n\n              which  will include the contents of foo in foo.zip while exclud-\n              ing  all  the  files  that  match  the  patterns  in  the   file\n              exclude.lst.\n\n              The long option forms of the above are\n\n                     zip -r foo foo --exclude \\*.o\n\n              and\n\n                     zip -r foo foo --exclude @exclude.lst\n\n              Multiple patterns can be specified, as in:\n\n                     zip -r foo foo -x \\*.o \\*.c\n\n              If  there is no space between -x and the pattern, just one value\n              is assumed (no list):\n\n                     zip -r foo foo -x\\*.o\n\n              See -i for more on include and exclude.\n\n       -X\n       --no-extra\n              Do not save extra file attributes (Extended Attributes on  OS/2,\n              uid/gid  and  file  times  on  Unix).  The zip format uses extra\n              fields to include additional information for each  entry.   Some\n              extra fields are specific to particular systems while others are\n              applicable to all systems.  Normally when zip reads entries from\n              an  existing archive, it reads the extra fields it knows, strips\n              the rest, and adds the extra fields applicable to  that  system.\n              With -X, zip strips all old fields and only includes the Unicode\n              and Zip64 extra fields (currently these two extra fields  cannot\n              be disabled).\n\n              Negating  this  option,  -X-,  includes  all  the  default extra\n              fields, but also copies over any unrecognized extra fields.\n\n       -y\n       --symlinks\n              For UNIX and VMS (V8.3 and later), store symbolic links as  such\n              in  the zip archive, instead of compressing and storing the file\n              referred to by the link.  This  can  avoid  multiple  copies  of\n              files  being  included in the archive as zip recurses the direc-\n              tory trees and accesses files directly and by links.\n\n       -z\n       --archive-comment\n              Prompt for a multi-line comment for the entire zip archive.  The\n              comment  is  ended by a line containing just a period, or an end\n              of file condition (^D on Unix, ^Z on MSDOS, OS/2, and VMS).  The\n              comment can be taken from a file:\n\n                     zip -z foo < foowhat\n\n       -Z cm\n       --compression-method cm\n              Set  the default compression method.  Currently the main methods\n              supported by zip are store and deflate.  Compression method  can\n              be set to:\n\n              store  -  Setting  the compression method to store forces zip to\n              store entries with no compression.   This  is  generally  faster\n              than compressing entries, but results in no space savings.  This\n              is the same as using -0 (compression level zero).\n\n              deflate - This is the default method for zip.  If zip determines\n              that  storing is better than deflation, the entry will be stored\n              instead.\n\n              bzip2 - If bzip2 support is compiled in, this compression method\n              also  becomes available.  Only some modern unzips currently sup-\n              port the bzip2 compression method, so test the unzip you will be\n              using  before relying on archives using this method (compression\n              method 12).\n\n              For example, to add bar.c to archive foo  using  bzip2  compres-\n              sion:\n\n                     zip -Z bzip2 foo bar.c\n\n              The compression method can be abbreviated:\n\n                     zip -Zb foo bar.c\n\n       -#\n       (-0, -1, -2, -3, -4, -5, -6, -7, -8, -9)\n              Regulate  the  speed of compression using the specified digit #,\n              where -0 indicates no compression (store all  files),  -1  indi-\n              cates  the  fastest  compression speed (less compression) and -9\n              indicates the slowest compression  speed  (optimal  compression,\n              ignores the suffix list). The default compression level is -6.\n\n              Though  still  being  worked, the intention is this setting will\n              control compression speed for  all  compression  methods.   Cur-\n              rently only deflation is controlled.\n\n       -!\n       --use-privileges\n              [WIN32]  Use  priviliges  (if  granted) to obtain all aspects of\n              WinNT security.\n\n       -@\n       --names-stdin\n              Take the list of input files from standard input. Only one file-\n              name per line.\n\n       -$\n       --volume-label\n              [MSDOS,  OS/2,  WIN32]  Include  the  volume label for the drive\n              holding the first file to be compressed.  If you want to include\n              only  the  volume  label  or  to force a specific drive, use the\n              drive name as first file name, as in:\n\n                     zip -$ foo a: c:bar\n\nEXAMPLES\n       The simplest example:\n\n              zip stuff *\n\n       creates the archive stuff.zip (assuming it does not exist) and puts all\n       the  files in the current directory in it, in compressed form (the .zip\n       suffix is added automatically, unless the archive name contains  a  dot\n       already; this allows the explicit specification of other suffixes).\n\n       Because  of the way the shell on Unix does filename substitution, files\n       starting with \".\" are not included; to include these as well:\n\n              zip stuff .* *\n\n       Even this will not include any subdirectories from the  current  direc-\n       tory.\n\n       To zip up an entire directory, the command:\n\n              zip -r foo foo\n\n       creates  the  archive foo.zip, containing all the files and directories\n       in the directory foo that is contained within the current directory.\n\n       You may want to make a zip archive that  contains  the  files  in  foo,\n       without  recording  the directory name, foo.  You can use the -j option\n       to leave off the paths, as in:\n\n              zip -j foo foo/*\n\n       If you are short on disk space, you might not have enough room to  hold\n       both  the  original  directory  and  the  corresponding  compressed zip\n       archive.  In this case, you can create the archive in steps  using  the\n       -m  option.   If  foo contains the subdirectories tom, dick, and harry,\n       you can:\n\n              zip -rm foo foo/tom\n              zip -rm foo foo/dick\n              zip -rm foo foo/harry\n\n       where the first command creates foo.zip, and the next two  add  to  it.\n       At  the  completion  of  each  zip command, the last created archive is\n       deleted, making room for the next zip command to function.\n\n       Use -s to set the split size and create a split archive.  The  size  is\n       given as a number followed optionally by one of k (kB), m (MB), g (GB),\n       or t (TB).  The command\n\n              zip -s 2g -r split.zip foo\n\n       creates a split archive of the directory foo with splits no bigger than\n       2 GB  each.   If  foo  contained 5 GB of contents and the contents were\n       stored in the split archive without compression (to make  this  example\n       simple),  this  would create three splits, split.z01 at 2 GB, split.z02\n       at 2 GB, and split.zip at a little over 1 GB.\n\n       The -sp option can be used to pause zip between splits to allow  chang-\n       ing  removable  media, for example, but read the descriptions and warn-\n       ings for both -s and -sp below.\n\n       Though zip does not update split archives, zip provides the new  option\n       -O (--output-file) to allow split archives to be updated and saved in a\n       new archive.  For example,\n\n              zip inarchive.zip foo.c bar.c --out outarchive.zip\n\n       reads archive inarchive.zip, even if split, adds the  files  foo.c  and\n       bar.c,  and  writes  the resulting archive to outarchive.zip.  If inar-\n       chive.zip is split then outarchive.zip defaults to the same split size.\n       Be  aware that outarchive.zip and any split files that are created with\n       it are always overwritten without warning.  This may be changed in  the\n       future.\n\nPATTERN MATCHING\n       This  section  applies  only  to Unix.  Watch this space for details on\n       MSDOS and VMS operation.  However, the special  wildcard  characters  *\n       and [] below apply to at least MSDOS also.\n\n       The  Unix  shells (sh, csh, bash, and others) normally do filename sub-\n       stitution (also called \"globbing\") on command arguments.  Generally the\n       special characters are:\n\n       ?      match any single character\n\n       *      match any number of characters (including none)\n\n       []     match  any  character in the range indicated within the brackets\n              (example: [a-f], [0-9]).  This form of wildcard matching  allows\n              a  user  to specify a list of characters between square brackets\n              and if any of the characters match the expression matches.   For\n              example:\n\n                     zip archive \"*.[hc]\"\n\n              would  archive all files in the current directory that end in .h\n              or .c.\n\n              Ranges of characters are supported:\n\n                     zip archive \"[a-f]*\"\n\n              would add to the archive all files  starting  with  \"a\"  through\n              \"f\".\n\n              Negation is also supported, where any character in that position\n              not in the list matches.  Negation is supported by adding ! or ^\n              to the beginning of the list:\n\n                     zip archive \"*.[!o]\"\n\n              matches files that don't end in \".o\".\n\n              On  WIN32, [] matching needs to be turned on with the -RE option\n              to avoid the confusion that names with [ or ] have caused.\n\n       When these characters are encountered (without  being  escaped  with  a\n       backslash  or  quotes),  the  shell will look for files relative to the\n       current path that match the pattern, and replace the  argument  with  a\n       list of the names that matched.\n\n       The  zip  program can do the same matching on names that are in the zip\n       archive being modified or, in the  case  of  the  -x  (exclude)  or  -i\n       (include)  options,  on  the  list of files to be operated on, by using\n       backslashes or quotes to tell the shell not to do the  name  expansion.\n       In  general,  when zip encounters a name in the list of files to do, it\n       first looks for the name in the file system.  If it finds it,  it  then\n       adds  it  to the list of files to do.  If it does not find it, it looks\n       for the name in the zip archive being modified (if  it  exists),  using\n       the  pattern matching characters described above, if present.  For each\n       match, it will add that name to the list  of  files  to  be  processed,\n       unless  this  name  matches  one  given with the -x option, or does not\n       match any name given with the -i option.\n\n       The pattern matching includes the path, and so patterns like \\*.o match\n       names  that  end in \".o\", no matter what the path prefix is.  Note that\n       the backslash must precede every special character (i.e. ?*[]), or  the\n       entire argument must be enclosed in double quotes (\"\").\n\n       In  general, use backslashes or double quotes for paths that have wild-\n       cards to make zip do the pattern matching for file  paths,  and  always\n       for paths and strings that have spaces or wildcards for -i, -x, -R, -d,\n       and -U and anywhere zip needs to process the wildcards.\n\nENVIRONMENT\n       The following environment  variables  are  read  and  used  by  zip  as\n       described.\n\n       ZIPOPT\n              contains  default  options  that  will be used when running zip.\n              The contents of this environment variable will get added to  the\n              command line just after the zip command.\n\n       ZIP\n              [Not on RISC OS and VMS] see ZIPOPT\n\n       Zip$Options\n              [RISC OS] see ZIPOPT\n\n       Zip$Exts\n              [RISC  OS]  contains extensions separated by a : that will cause\n              native filenames with one of  the  specified  extensions  to  be\n              added to the zip file with basename and extension swapped.\n\n       ZIP_OPTS\n              [VMS] see ZIPOPT\n\nSEE ALSO\n       compress(1), shar(1L), tar(1), unzip(1L), gzip(1L)\n\nDIAGNOSTICS\n       The exit status (or error level) approximates the exit codes defined by\n       PKWARE and takes on the following values, except under VMS:\n\n              0      normal; no errors or warnings detected.\n\n              2      unexpected end of zip file.\n\n              3      a generic error in the zipfile format was detected.  Pro-\n                     cessing may have completed successfully anyway; some bro-\n                     ken zipfiles created by other archivers have simple work-\n                     arounds.\n\n              4      zip was unable to allocate memory for one or more buffers\n                     during program initialization.\n\n              5      a severe error in the zipfile format was detected.   Pro-\n                     cessing probably failed immediately.\n\n              6      entry  too  large  to  be  processed (such as input files\n                     larger than 2 GB when not using Zip64 or trying  to  read\n                     an existing archive that is too large) or entry too large\n                     to be split with zipsplit\n\n              7      invalid comment format\n\n              8      zip -T failed or out of memory\n\n              9      the user aborted zip prematurely with control-C (or simi-\n                     lar)\n\n              10     zip encountered an error while using a temp file\n\n              11     read or seek error\n\n              12     zip has nothing to do\n\n              13     missing or empty zip file\n\n              14     error writing to a file\n\n              15     zip was unable to create a file to write to\n\n              16     bad command line parameters\n\n              18     zip could not open a specified file to read\n\n              19     zip  was compiled with options not supported on this sys-\n                     tem\n\n       VMS interprets standard Unix (or PC) return values as  other,  scarier-\n       looking  things,  so zip instead maps them into VMS-style status codes.\n       In general, zip sets VMS Facility = 1955 (0x07A3), Code = 2*  Unix_sta-\n       tus,  and  an  appropriate  Severity  (as specified in ziperr.h).  More\n       details  are  included  in   the   VMS-specific   documentation.    See\n       [.vms]NOTES.TXT and [.vms]vms_msg_gen.c.\n\nBUGS\n       zip 3.0 is not compatible with PKUNZIP 1.10. Use zip 1.1 to produce zip\n       files which can be extracted by PKUNZIP 1.10.\n\n       zip files produced by zip 3.0 must not be updated by zip 1.1  or  PKZIP\n       1.10,  if  they contain encrypted members or if they have been produced\n       in a pipe or on a non-seekable device. The old versions of zip or PKZIP\n       would create an archive with an incorrect format.  The old versions can\n       list the contents of the zip file but cannot extract it anyway (because\n       of  the  new  compression algorithm).  If you do not use encryption and\n       use regular disk files, you do not have to care about this problem.\n\n       Under VMS, not all of the odd file formats are treated properly.   Only\n       stream-LF  format  zip files are expected to work with zip.  Others can\n       be converted using Rahul Dhesi's BILF program.   This  version  of  zip\n       handles some of the conversion internally.  When using Kermit to trans-\n       fer zip files from VMS to MSDOS, type \"set file  type  block\"  on  VMS.\n       When  transfering from MSDOS to VMS, type \"set file type fixed\" on VMS.\n       In both cases, type \"set file type binary\" on MSDOS.\n\n       Under some older VMS versions, zip may  hang  for  file  specifications\n       that use DECnet syntax foo::*.*.\n\n       On OS/2, zip cannot match some names, such as those including an excla-\n       mation mark or a hash sign.  This is a bug in OS/2 itself:  the  32-bit\n       DosFindFirst/Next  don't  find  such names.  Other programs such as GNU\n       tar are also affected by this bug.\n\n       Under OS/2, the amount of Extended Attributes displayed by DIR is  (for\n       compatibility)  the  amount returned by the 16-bit version of DosQuery-\n       PathInfo(). Otherwise OS/2 1.3 and 2.0 would report different EA  sizes\n       when  DIRing  a  file.   However,  the structure layout returned by the\n       32-bit DosQueryPathInfo() is a bit different,  it  uses  extra  padding\n       bytes  and  link  pointers  (it's  a linked list) to have all fields on\n       4-byte boundaries for portability to future RISC OS/2 versions.  There-\n       fore  the value reported by zip (which uses this 32-bit-mode size) dif-\n       fers from that reported by DIR.   zip  stores  the  32-bit  format  for\n       portability, even the 16-bit MS-C-compiled version running on OS/2 1.3,\n       so even this one shows the 32-bit-mode size.\n\nAUTHORS\n       Copyright (C) 1997-2008 Info-ZIP.\n\n       Currently distributed under the Info-ZIP license.\n\n       Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,\n       Onno  van  der Linden, Kai Uwe Rommel, Igor Mandrichenko, John Bush and\n       Paul Kienitz.\n\n       Original copyright:\n\n       Permission is granted to any individual or institution to use, copy, or\n       redistribute  this  software  so  long as all of the original files are\n       included, that it is not sold  for  profit,  and  that  this  copyright\n       notice is retained.\n\n       LIKE  ANYTHING  ELSE  THAT'S FREE, ZIP AND ITS ASSOCIATED UTILITIES ARE\n       PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY KIND, EITHER  EXPRESSED\n       OR  IMPLIED.  IN  NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\n       DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.\n\n       Please send bug reports and comments using the web page  at:  www.info-\n       zip.org.   For  bug  reports,  please  include  the version of zip (see\n       zip -h), the make options used to compile it (see zip -v), the  machine\n       and operating system in use, and as much additional information as pos-\n       sible.\n\nACKNOWLEDGEMENTS\n       Thanks to R. P. Byrne for his Shrink.Pas program, which  inspired  this\n       project,  and  from which the shrink algorithm was stolen; to Phil Katz\n       for placing in the public domain the zip file format, compression  for-\n       mat,  and  .ZIP  filename extension, and for accepting minor changes to\n       the file format; to Steve Burg for clarifications on the  deflate  for-\n       mat;  to Haruhiko Okumura and Leonid Broukhis for providing some useful\n       ideas for the compression algorithm; to  Keith  Petersen,  Rich  Wales,\n       Hunter Goatley and Mark Adler for providing a mailing list and ftp site\n       for the Info-ZIP group to use; and most importantly,  to  the  Info-ZIP\n       group  itself  (listed  in the file infozip.who) without whose tireless\n       testing and bug-fixing efforts a portable zip would not have been  pos-\n       sible.   Finally  we should thank (blame) the first Info-ZIP moderator,\n       David Kirschbaum, for getting us into this mess  in  the  first  place.\n       The  manual page was rewritten for Unix by R. P. C. Rodgers and updated\n       by E. Gordon for zip 3.0.\n\nInfo-ZIP                      16 June 2008 (v3.0)                      ZIP(1L)\n"
  },
  {
    "path": "deps/infozip/zip30/zip30.ann",
    "content": "Zip 3.0\n\nWe have posted Zip 3.0, July 5th 2008.  This is a major upgrade\nfrom Zip 2.32, the current Zip 2.x release.  A quick summary of\nfeatures is below, but see the file WhatsNew for the detailed list\nof major features and upgrades as well as what's on the list for\nZip 3.1.  Send in your feature suggestions and bug reports.\n\nQuick list of major changes in Zip 3.0:\n\n- Large files.  Support for files and archives greater than 2 GB using\n  large file I/O and the Zip64 extensions.  Also can now have more\n  than 64K entries in an archive.\n\n- Split archives.  Zip now supports split archives, zip archives\n  split into a set of files that can then be stored on removable media\n  for instance.\n\n- Unicode.  If Unicode support is enabled and supported on the system\n  Zip is run on, Zip now can read paths not in the current character\n  set and store those paths in portable UTF-8 format.  These Unicode\n  paths can then be used to partially or fully recreate the paths on\n  other systems depending on the character set support provided by\n  the unzip on the receiving system.  In particular, this allows\n  portability of paths between Windows and Unix.  Unicode comments\n  are also supported on systems where UTF-8 is the current character\n  set.  Unicode comment support for other systems is expected in\n  Zip 3.1.\n\n- New command line parser.  This new parser allows for command line\n  permuting, where options can appear almost anywhere on the command\n  line.  This allows adding options to the end of the command line,\n  for instance.  It also supports long options, allowing for\n  more readable command lines, and also allows lists for the -x\n  exclude and -i include options to appear not just at the end of\n  the command line.  And some bugs in command line processing in\n  Zip 2.32 have been fixed.\n\n- Unix 32-bit UIDs/GIDs.  Now UIDs/GIDs larger than 16 bits are\n  supported, but UnZip 6.0 is needed to restore these larger\n  UIDs/GIDs.  If Zip detects that the current system does not use\n  16-bit UIDs/GIDs, the old 16-bit UID/GID storage is not used\n  as putting 32-bit UIDs/GIDs into 16-bit fields can cause\n  problems.\n\n- New modes.  Additional archive modes have been added, including a\n  difference mode for supporting incremental backups, a file sync\n  mode for synchronizing an existing archive with the current file\n  system (which can be much faster than creating a new archive), and\n  a copy mode that allows copying entries from one archive to another.\n\n- Compression using bzip2.  Now can add bzip2 compression as a\n  compression option in Zip.  bzip2 compression can result in much\n  more compact entries in some cases, but the user should verify\n  that bzip2 is supported on the target unzip before using this new\n  compression choice.\n\n- New Windows dll.  The Windows dll has been updated to support the\n  new Zip64 large file and larger number of entries limits.  This\n  new dll is not backward compatible with the Zip 2.32 dll, as the\n  arguments to the dll have been updated to support the added\n  capabilities, but modifying existing programs to use the new dll\n  should be simple.  See the included Visual Basic example project\n  for details.\n\n- Better streaming and piping.  Zip now has better support of\n  streaming and piping and handles Unix FIFOs (named pipes) better.\n\n- Gobs of new progress information.  Zip can now output progress\n  information, such as how many entries processed and to go, how\n  many bytes processed and to go, and adjustable size progress\n  dots.  If the initial file scan takes longer than about 5\n  seconds, Zip now outputs dots during the scan to avoid a long\n  period of quiet.  Zip can also now generate log files.\n\n- Updated archive fixing.  The archive fixing capability is\n  slightly improved, and now can fix split archives.\n\n- Windows Archive bit support.  The Windows archive bit is now\n  supported, though the new difference mode is probably more\n  reliable than relying on the Windows archive bit for creating\n  incremental backups.\n\n- File lists.  Zip can list the files that would be added to an\n  archive as well as the files in an existing archive.\n\n- Extended help.  A new extended help option lists a very terse\n  summary of the major features of Zip and how to use them.\n\n- Many bug fixes.\n\nAs always, see the Zip manual page for details on what Zip has and\nhow to use all features.\n\nEnjoy!\n"
  },
  {
    "path": "deps/infozip/zip30/zip30f.ann",
    "content": "Zip 3.0f\n\nWe have posted Zip Beta 3.0f, September 24th 2007.  This is a beta\nrelease, but is more or less complete.  See the file WhatsNew for\na list of major features implemented and what's left.\n\nThe archive reading and writing code in this beta has been redone to\nsupport split archives.  We've extensively tested the code over the\nlast year, but you should thoroughly test it yourself before relying\non it.  Also note that Unicode support is preliminary and may change\nbefore release, but currently there seems agreement between Info-ZIP\nand others on how to handle storing UTF-8 paths and that approach is\nimplemented in Zip 3.0.\n\nPlease test this beta and let us know if we're ready to officially\nrelease Zip 3.0.\n\nNew things in Zip 3.0f\n- Split archives - Zip now can create and indirectly update split\n  archives\n- Unicode support - Zip now stores Unicode paths that should be more\n  portable across character sets and languages and Zip now can\n  read Windows file names in most all character sets using Unicode,\n  but this support is preliminary and may change by release\n- bzip2 - bzip2 compression is now supported\n- Console writing - Messages to the console are more consistently\n  formatted\n- Streaming - Directories are now handled better when streaming\n- Date range - Can now use -t and -tt to set a date range\n- UnZip Check - Check if UnZip 6.00 or later is available for\n  testing a Zip64 archive\n- License - minor updates to the license\n- Difference mode - A new option -DF (--dif) creates an output archive that\n  includes only files changed or added since the input archive was created,\n  and might be useful for incremental backups\n- File Sync - New option -FS synchronizes the entries in an archive with the\n  files on the file system, adding, updating, and deleting entries as needed,\n  creating an updated archive that should be the same as a new archive, but\n  since existing entries are copied and not recompressed it can be faster\n- Fix options - Options -F and -FF now fix split archives\n- Copy Mode - This new mode allows selecting archive entries to copy\n  to a new archive\n- Case matching - On Windows and VMS, option -ic (ignore case) turns off\n  case-sensitive matching of command line input patterns when matching\n  entries in an archive\n- Windows OEM - With this compile option, file names are saved on\n  Windows in the local OEM character set, as some other zips do\n- Windows Archive Bit support - On Windows can now select files\n  using the Windows archive bit\n- Global dots - Can now set quiet mode, but output progress dots every\n  so many bytes read, settable from KB to TB, allowing progress to be\n  displayed for large archives without the screen scrolling\n- Empty archives - Options -i or -i@ can now output empty archives,\n  which is useful in some scripts\n- Keep extra fields option - Option -X- allows passing through extra\n  fields that Zip does not process\n- Large file encryption bug fixed - Fix for bug that very rarely\n  results in bad data being stored when deflating and encrypting\n  uncompressable large amounts of data and resulting in CRC errors\n- Show Files option - Can list the files that would be operated on\n- Delete date bug fixed - Bug when using -d with -t or -tt is fixed\n"
  },
  {
    "path": "deps/infozip/zip30/zip30g.ann",
    "content": "Zip 3.0g\n\nWe have posted Zip Beta 3.0g, January 30th 2008.  This is a beta\nrelease, but is more or less complete and is considered a release\ncandidate.  See the file WhatsNew for a list of major features\nimplemented and what's left.\n\nThe archive reading and writing code in Zip 3.0 has been redone to\nsupport split archives.  We've extensively tested the code over the\nlast year, but you should thoroughly test it yourself before relying\non it.  Also note that Unicode support has been added and should comply\nwith the latest AppNote, but is still new and so may need refining.\n\nPlease test this beta and let us know if we're ready to officially\nrelease Zip 3.0.\n\nNew things in Zip 3.0g\n- Add split support to VB project for Zip64.\n\n- Disable reading of Unix FIFOs unless new -FI option used to avoid an\n  archiving operation stopping when it hits an active unfed FIFO.\n\n- The [list] wildcard expression (regular expression matching of any\n  character or range of characters in list) is now disabled on DOS and\n  Windows as it has caused confusion when filenames have [ and ] in\n  them.  The new -RE option reenables it.\n\n- Add negation to many display options such as -dc and -db.\n\n- Allow -FF to read and fix archives having local entries that appear\n  after central directory entries.\n\n- Many small bug fixes.\n"
  },
  {
    "path": "deps/infozip/zip30/zip30h.ann",
    "content": "Zip 3.0h\n\nWe have posted Zip Beta 3.0h, May 31st 2008.  This is a beta\nrelease, but is more or less complete and is considered a release\ncandidate.  See the file WhatsNew for a list of major features\nimplemented and what's left.\n\nThe archive reading and writing code in Zip 3.0 has been redone to\nsupport split archives.  We've extensively tested the code over the\nlast year, but you should thoroughly test it yourself before relying\non it.  Also note that Unicode support has been added and should comply\nwith the latest AppNote, but is still new and so may need refining.\n\nPlease test this beta and let us know if we're ready to officially\nrelease Zip 3.0.\n\nNew things in Zip 3.0h\n- Allow -@ and -x to work together.\n\n- Change long Unicode escapes from #Lxxxxxxxx to #Lxxxxxx.\n\n- Unicode code cleanup to support additional compilers and also\n  some memory leak fixes.\n\n- Update symbolic link checks.\n\n- Add support for 32-bit UIDs/GIDs.\n\n- Update VMS notes.\n\n- Fix bug where directory scan using -AS (include only files\n  with Windows archive bit set) would skip files in directories\n  with bit not set.\n\n- Add Unix IBM support.\n\n- Change -W to -ws to free -W for later use.\n\n- Fix large file support for MinGW.\n\n- Fix large file support for bzip2.\n\n- Fix compile error in ZipCloak when UNICODE_SUPPORT is not enabled.\n\n- Fix Unicode bug in ZipCloak involving Unicode paths.\n\n- Additional small bug fixes.\n"
  },
  {
    "path": "deps/infozip/zip30/zipcloak.c",
    "content": "/*\n  zipcloak.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n   This code was originally written in Europe and could be freely distributed\n   from any country except the U.S.A. If this code was imported into the U.S.A,\n   it could not be re-exported from the U.S.A to another country. (This\n   restriction might seem curious but this is what US law required.)\n\n   Now this code can be freely exported and imported.  See README.CR.\n */\n#define __ZIPCLOAK_C\n\n#ifndef UTIL\n# define UTIL\n#endif\n#include \"zip.h\"\n#define DEFCPYRT        /* main module: enable copyright string defines! */\n#include \"revision.h\"\n#include \"crc32.h\"\n#include \"crypt.h\"\n#include \"ttyio.h\"\n#include <signal.h>\n#ifndef NO_STDLIB_H\n#  include <stdlib.h>\n#endif\n\n#if CRYPT       /* defined (as TRUE or FALSE) in crypt.h */\n\nint main OF((int argc, char **argv));\n\nlocal void handler OF((int sig));\nlocal void license OF((void));\nlocal void help OF((void));\nlocal void version_info OF((void));\n\n/* Temporary zip file pointer */\nlocal FILE *tempzf;\n\n/* Pointer to CRC-32 table (used for decryption/encryption) */\n#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))\nZCONST ulg near *crc_32_tab;\n#else\nZCONST uLongf *crc_32_tab;\n#endif\n\nint set_filetype(out_path)\n  char *out_path;\n{\n#ifdef __BEOS__\n  /* Set the filetype of the zipfile to \"application/zip\" */\n  setfiletype( out_path, \"application/zip\" );\n#endif\n\n#ifdef __ATHEOS__\n  /* Set the filetype of the zipfile to \"application/x-zip\" */\n  setfiletype(out_path, \"application/x-zip\");\n#endif\n\n#ifdef MACOS\n  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */\n  setfiletype(out_path, 'IZip', 'ZIP ');\n#endif\n\n#ifdef RISCOS\n  /* Set the filetype of the zipfile to &DDC */\n  setfiletype(out_path, 0xDDC);\n#endif\n  return ZE_OK;\n}\n\n/* rename a split\n * A split has a tempfile name until it is closed, then\n * here rename it as out_path the final name for the split.\n */\nint rename_split(temp_name, out_path)\n  char *temp_name;\n  char *out_path;\n{\n  int r;\n  /* Replace old zip file with new zip file, leaving only the new one */\n  if ((r = replace(out_path, temp_name)) != ZE_OK)\n  {\n    zipwarn(\"new zip file left as: \", temp_name);\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    ZIPERR(r, \"was replacing split file\");\n  }\n  if (zip_attributes) {\n    setfileattr(out_path, zip_attributes);\n  }\n  return ZE_OK;\n}\n\nvoid zipmessage_nl(a, nl)\nZCONST char *a;     /* message string to output */\nint nl;             /* 1 = add nl to end */\n/* If nl false, print a message to mesg without new line.\n   If nl true, print and add new line. */\n{\n  if (noisy) {\n    fprintf(mesg, \"%s\", a);\n    if (nl) {\n      fprintf(mesg, \"\\n\");\n      mesg_line_started = 0;\n    } else {\n      mesg_line_started = 1;\n    }\n    fflush(mesg);\n  }\n}\n\nvoid zipmessage(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a message to mesg and flush.  Write new line first\n   if current line has output already. */\n{\n  if (noisy) {\n    if (mesg_line_started)\n      fprintf(mesg, \"\\n\");\n    fprintf(mesg, \"%s%s\\n\", a, b);\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n}\n\n/***********************************************************************\n * Issue a message for the error, clean up files and memory, and exit.\n */\nvoid ziperr(code, msg)\n    int code;               /* error code from the ZE_ class */\n    ZCONST char *msg;       /* message about how it happened */\n{\n    if (PERR(code)) perror(\"zipcloak error\");\n    fprintf(mesg, \"zipcloak error: %s (%s)\\n\", ZIPERRORS(code), msg);\n    if (tempzf != NULL) fclose(tempzf);\n    if (tempzip != NULL) {\n        destroy(tempzip);\n        free((zvoid *)tempzip);\n    }\n    if (zipfile != NULL) free((zvoid *)zipfile);\n    EXIT(code);\n}\n\n/***********************************************************************\n * Print a warning message to mesg (usually stderr) and return.\n */\nvoid zipwarn(msg1, msg2)\n    ZCONST char *msg1, *msg2;   /* message strings juxtaposed in output */\n{\n    fprintf(mesg, \"zipcloak warning: %s%s\\n\", msg1, msg2);\n}\n\n\n/***********************************************************************\n * Upon getting a user interrupt, turn echo back on for tty and abort\n * cleanly using ziperr().\n */\nlocal void handler(sig)\n    int sig;                  /* signal number (ignored) */\n{\n#if (!defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS))\n    echon();\n    putc('\\n', mesg);\n#endif\n    ziperr(ZE_ABORT +sig-sig, \"aborting\");\n    /* dummy usage of sig to avoid compiler warnings */\n}\n\n\nstatic ZCONST char *public[] = {\n\"The encryption code of this program is not copyrighted and is\",\n\"put in the public domain. It was originally written in Europe\",\n\"and can be freely distributed in both source and object forms\",\n\"from any country, including the USA under License Exception\",\n\"TSU of the U.S. Export Administration Regulations (section\",\n\"740.13(e)) of 6 June 2002.  (Prior to January 2000, re-export\",\n\"from the US was a violation of US law.)\"\n};\n\n/***********************************************************************\n * Print license information to stdout.\n */\nlocal void license()\n{\n    extent i;             /* counter for copyright array */\n\n    for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++) {\n        puts(swlicense[i]);\n    }\n    putchar('\\n');\n    printf(\"Export notice:\\n\");\n    for (i = 0; i < sizeof(public)/sizeof(char *); i++) {\n        puts(public[i]);\n    }\n}\n\n\nstatic ZCONST char *help_info[] = {\n\"\",\n\"ZipCloak %s (%s)\",\n#ifdef VM_CMS\n\"Usage:  zipcloak [-dq] [-b fm] zipfile\",\n#else\n\"Usage:  zipcloak [-dq] [-b path] zipfile\",\n#endif\n\"  the default action is to encrypt all unencrypted entries in the zip file\",\n\"\",\n\"  -d  --decrypt      decrypt encrypted entries (copy if given wrong password)\",\n#ifdef VM_CMS\n\"  -b  --temp-mode    use \\\"fm\\\" as the filemode for the temporary zip file\",\n#else\n\"  -b  --temp-path    use \\\"path\\\" for the temporary zip file\",\n#endif\n\"  -O  --output-file  write output to new zip file\",\n\"  -q  --quiet        quiet operation, suppress some informational messages\",\n\"  -h  --help         show this help\",\n\"  -v  --version      show version info\",\n\"  -L  --license      show software license\"\n  };\n\n/***********************************************************************\n * Print help (along with license info) to stdout.\n */\nlocal void help()\n{\n    extent i;             /* counter for help array */\n\n    for (i = 0; i < sizeof(help_info)/sizeof(char *); i++) {\n        printf(help_info[i], VERSION, REVDATE);\n        putchar('\\n');\n    }\n}\n\n\nlocal void version_info()\n/* Print verbose info about program version and compile time options\n   to stdout. */\n{\n  extent i;             /* counter in text arrays */\n\n  /* Options info array */\n  static ZCONST char *comp_opts[] = {\n#ifdef DEBUG\n    \"DEBUG\",\n#endif\n#if CRYPT && defined(PASSWD_FROM_STDIN)\n    \"PASSWD_FROM_STDIN\",\n#endif /* CRYPT && PASSWD_FROM_STDIN */\n    NULL\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)\n  {\n    printf(copyright[i], \"zipcloak\");\n    putchar('\\n');\n  }\n  putchar('\\n');\n\n  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)\n  {\n    printf(versinfolines[i], \"ZipCloak\", VERSION, REVDATE);\n    putchar('\\n');\n  }\n\n  version_local();\n\n  puts(\"ZipCloak special compilation options:\");\n  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)\n  {\n    printf(\"\\t%s\\n\",comp_opts[i]);\n  }\n  printf(\"\\t[encryption, version %d.%d%s of %s]\\n\",\n            CR_MAJORVER, CR_MINORVER, CR_BETA_VER, CR_VERSION_DATE);\n}\n\n/* options for zipcloak - 3/5/2004 EG */\nstruct option_struct far options[] = {\n  /* short longopt        value_type        negatable        ID    name */\n#ifdef VM_CMS\n    {\"b\",  \"temp-mode\",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'b',  \"temp file mode\"},\n#else\n    {\"b\",  \"temp-path\",   o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'b',  \"path for temp file\"},\n#endif\n    {\"d\",  \"decrypt\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'd',  \"decrypt\"},\n    {\"h\",  \"help\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    {\"L\",  \"license\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'L',  \"license\"},\n    {\"l\",  \"\",            o_NO_VALUE,       o_NOT_NEGATABLE, 'L',  \"license\"},\n    {\"O\",  \"output-file\", o_REQUIRED_VALUE, o_NOT_NEGATABLE, 'O',  \"output to new archive\"},\n    {\"v\",  \"version\",     o_NO_VALUE,       o_NOT_NEGATABLE, 'v',  \"version\"},\n    /* the end of the list */\n    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */\n  };\n\n\n/***********************************************************************\n * Encrypt or decrypt all of the entries in a zip file.  See the command\n * help in help() above.\n */\n\nint main(argc, argv)\n    int argc;                   /* number of tokens in command line */\n    char **argv;                /* command line tokens */\n{\n    int attr;                   /* attributes of zip file */\n    zoff_t start_offset;        /* start of central directory */\n    int decrypt;                /* decryption flag */\n    int temp_path;              /* 1 if next argument is path for temp files */\n    char passwd[IZ_PWLEN+1];    /* password for encryption or decryption */\n    char verify[IZ_PWLEN+1];    /* password for encryption or decryption */\n#if 0\n    char *q;                    /* steps through option arguments */\n    int r;                      /* arg counter */\n#endif\n    int res;                    /* result code */\n    zoff_t length;              /* length of central directory */\n    FILE *inzip, *outzip;       /* input and output zip files */\n    struct zlist far *z;        /* steps through zfiles linked list */\n    /* used by get_option */\n    unsigned long option; /* option ID returned by get_option */\n    int argcnt = 0;       /* current argcnt in args */\n    int argnum = 0;       /* arg number */\n    int optchar = 0;      /* option state */\n    char *value = NULL;   /* non-option arg, option value or NULL */\n    int negated = 0;      /* 1 = option negated */\n    int fna = 0;          /* current first non-opt arg */\n    int optnum = 0;       /* index in table */\n\n    char **args;               /* copy of argv that can be freed */\n\n#ifdef THEOS\n    setlocale(LC_CTYPE, \"I\");\n#endif\n\n#ifdef UNICODE_SUPPORT\n# ifdef UNIX\n  /* For Unix, set the locale to UTF-8.  Any UTF-8 locale is\n     OK and they should all be the same.  This allows seeing,\n     writing, and displaying (if the fonts are loaded) all\n     characters in UTF-8. */\n  {\n    char *loc;\n\n    /*\n      loc = setlocale(LC_CTYPE, NULL);\n      printf(\"  Initial language locale = '%s'\\n\", loc);\n    */\n\n    loc = setlocale(LC_CTYPE, \"en_US.UTF-8\");\n\n    /*\n      printf(\"langinfo %s\\n\", nl_langinfo(CODESET));\n    */\n\n    if (loc != NULL) {\n      /* using UTF-8 character set so can set UTF-8 GPBF bit 11 */\n      using_utf8 = 1;\n      /*\n        printf(\"  Locale set to %s\\n\", loc);\n      */\n    } else {\n      /*\n        printf(\"  Could not set Unicode UTF-8 locale\\n\");\n      */\n    }\n  }\n# endif\n#endif\n\n    /* If no args, show help */\n    if (argc == 1) {\n        help();\n        EXIT(ZE_OK);\n    }\n\n    /* Informational messages are written to stdout. */\n    mesg = stdout;\n\n    init_upper();               /* build case map table */\n\n    crc_32_tab = get_crc_table();\n                                /* initialize crc table for crypt */\n\n    /* Go through args */\n    zipfile = tempzip = NULL;\n    tempzf = NULL;\n#ifdef SIGINT\n    signal(SIGINT, handler);\n#endif\n#ifdef SIGTERM                  /* Some don't have SIGTERM */\n    signal(SIGTERM, handler);\n#endif\n#ifdef SIGABRT\n    signal(SIGABRT, handler);\n#endif\n#ifdef SIGBREAK\n    signal(SIGBREAK, handler);\n#endif\n#ifdef SIGBUS\n    signal(SIGBUS, handler);\n#endif\n#ifdef SIGILL\n    signal(SIGILL, handler);\n#endif\n#ifdef SIGSEGV\n    signal(SIGSEGV, handler);\n#endif\n    temp_path = decrypt = 0;\n#if 0\n    /* old command line */\n    for (r = 1; r < argc; r++) {\n        if (*argv[r] == '-') {\n            if (!argv[r][1]) ziperr(ZE_PARMS, \"zip file cannot be stdin\");\n            for (q = argv[r]+1; *q; q++) {\n                switch (*q) {\n                case 'b':   /* Specify path for temporary file */\n                    if (temp_path) {\n                        ziperr(ZE_PARMS, \"use -b before zip file name\");\n                    }\n                    temp_path = 1;          /* Next non-option is path */\n                    break;\n                case 'd':\n                    decrypt = 1;  break;\n                case 'h':   /* Show help */\n                    help();\n                    EXIT(ZE_OK);\n                case 'l': case 'L':  /* Show copyright and disclaimer */\n                    license();\n                    EXIT(ZE_OK);\n                case 'q':   /* Quiet operation, suppress info messages */\n                    noisy = 0;  break;\n                case 'v':   /* Show version info */\n                    version_info();\n                    EXIT(ZE_OK);\n                default:\n                    ziperr(ZE_PARMS, \"unknown option\");\n                } /* switch */\n            } /* for */\n\n        } else if (temp_path == 0) {\n            if (zipfile != NULL) {\n                ziperr(ZE_PARMS, \"can only specify one zip file\");\n\n            } else if ((zipfile = ziptyp(argv[r])) == NULL) {\n                ziperr(ZE_MEM, \"was processing arguments\");\n            }\n        } else {\n            tempath = argv[r];\n            temp_path = 0;\n        } /* if */\n    } /* for */\n\n#else\n\n    /* new command line */\n\n    zipfile = NULL;\n    out_path = NULL;\n\n    /* make copy of args that can use with insert_arg() */\n    args = copy_args(argv, 0);\n\n    /*\n    -------------------------------------------\n    Process command line using get_option\n    -------------------------------------------\n\n    Each call to get_option() returns either a command\n    line option and possible value or a non-option argument.\n    Arguments are permuted so that all options (-r, -b temp)\n    are returned before non-option arguments (zipfile).\n    Returns 0 when nothing left to read.\n    */\n\n    /* set argnum = 0 on first call to init get_option */\n    argnum = 0;\n\n    /* get_option returns the option ID and updates parameters:\n           args    - usually same as argv if no argument file support\n           argcnt  - current argc for args\n           value   - char* to value (free() when done with it) or NULL if no value\n           negated - option was negated with trailing -\n    */\n\n    while ((option = get_option(&args, &argcnt, &argnum,\n                                &optchar, &value, &negated,\n                                &fna, &optnum, 0)))\n    {\n      switch (option)\n      {\n        case 'b':   /* Specify path for temporary file */\n          if (temp_path) {\n            ziperr(ZE_PARMS, \"more than one temp_path\");\n          }\n          temp_path = 1;\n          tempath = value;\n          break;\n        case 'd':\n          decrypt = 1;  break;\n        case 'h':   /* Show help */\n          help();\n          EXIT(ZE_OK);\n        case 'l': case 'L':  /* Show copyright and disclaimer */\n          license();\n          EXIT(ZE_OK);\n        case 'O':   /* Output to new zip file instead of updating original zip file */\n          if ((out_path = ziptyp(value)) == NULL) {\n            ziperr(ZE_MEM, \"was processing arguments\");\n          }\n          free(value);\n          break;\n        case 'q':   /* Quiet operation, suppress info messages */\n          noisy = 0;  break;\n        case 'v':   /* Show version info */\n          version_info();\n          EXIT(ZE_OK);\n        case o_NON_OPTION_ARG:\n          /* not an option */\n          /* no more options as permuting */\n          /* just dash also ends up here */\n\n          if (strcmp(value, \"-\") == 0) {\n            ziperr(ZE_PARMS, \"zip file cannot be stdin\");\n          } else if (zipfile != NULL) {\n            ziperr(ZE_PARMS, \"can only specify one zip file\");\n          }\n\n          if ((zipfile = ziptyp(value)) == NULL) {\n            ziperr(ZE_MEM, \"was processing arguments\");\n          }\n          free(value);\n          break;\n\n        default:\n          ziperr(ZE_PARMS, \"unknown option\");\n      }\n    }\n\n    free_args(args);\n\n#endif\n\n    if (zipfile == NULL) ziperr(ZE_PARMS, \"need to specify zip file\");\n\n    /* in_path is the input zip file */\n    if ((in_path = malloc(strlen(zipfile) + 1)) == NULL) {\n      ziperr(ZE_MEM, \"input\");\n    }\n    strcpy(in_path, zipfile);\n\n    /* out_path defaults to in_path */\n    if (out_path == NULL) {\n      if ((out_path = malloc(strlen(zipfile) + 1)) == NULL) {\n        ziperr(ZE_MEM, \"output\");\n      }\n      strcpy(out_path, zipfile);\n    }\n\n    /* Read zip file */\n    if ((res = readzipfile()) != ZE_OK) ziperr(res, zipfile);\n    if (zfiles == NULL) ziperr(ZE_NAME, zipfile);\n\n    /* Check for something to do */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n        if (decrypt ? z->flg & 1 : !(z->flg & 1)) break;\n    }\n    if (z == NULL) {\n        ziperr(ZE_NONE, decrypt ? \"no encrypted files\"\n                       : \"all files encrypted already\");\n    }\n\n    /* Before we get carried away, make sure zip file is writeable */\n    if ((inzip = fopen(zipfile, \"a\")) == NULL) ziperr(ZE_CREAT, zipfile);\n    fclose(inzip);\n    attr = getfileattr(zipfile);\n\n    /* Open output zip file for writing */\n#if defined(UNIX) && !defined(NO_MKSTEMP)\n    {\n      int yd;\n      int i;\n\n      /* use mkstemp to avoid race condition and compiler warning */\n\n      if (tempath != NULL)\n      {\n        /* if -b used to set temp file dir use that for split temp */\n        if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {\n          ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, tempath);\n        if (lastchar(tempzip) != '/')\n          strcat(tempzip, \"/\");\n      }\n      else\n      {\n        /* create path by stripping name and appending template */\n        if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {\n        ZIPERR(ZE_MEM, \"allocating temp filename\");\n        }\n        strcpy(tempzip, zipfile);\n        for(i = strlen(tempzip); i > 0; i--) {\n          if (tempzip[i - 1] == '/')\n            break;\n        }\n        tempzip[i] = '\\0';\n      }\n      strcat(tempzip, \"ziXXXXXX\");\n\n      if ((yd = mkstemp(tempzip)) == EOF) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n      if ((y = tempzf = outzip = fdopen(yd, FOPW_TMP)) == NULL) {\n        ZIPERR(ZE_TEMP, tempzip);\n      }\n    }\n#else\n    if ((y = tempzf = outzip = fopen(tempzip = tempname(zipfile), FOPW)) == NULL) {\n        ziperr(ZE_TEMP, tempzip);\n    }\n#endif\n\n    /* Get password */\n    if (getp(\"Enter password: \", passwd, IZ_PWLEN+1) == NULL)\n        ziperr(ZE_PARMS,\n               \"stderr is not a tty (you may never see this message!)\");\n\n    if (decrypt == 0) {\n        if (getp(\"Verify password: \", verify, IZ_PWLEN+1) == NULL)\n               ziperr(ZE_PARMS,\n                      \"stderr is not a tty (you may never see this message!)\");\n\n        if (strcmp(passwd, verify))\n               ziperr(ZE_PARMS, \"password verification failed\");\n\n        if (*passwd == '\\0')\n               ziperr(ZE_PARMS, \"zero length password not allowed\");\n    }\n\n    /* Open input zip file again, copy preamble if any */\n    if ((in_file = fopen(zipfile, FOPR)) == NULL) ziperr(ZE_NAME, zipfile);\n\n    if (zipbeg && (res = bfcopy(zipbeg)) != ZE_OK)\n    {\n        ziperr(res, res == ZE_TEMP ? tempzip : zipfile);\n    }\n    tempzn = zipbeg;\n\n    /* Go through local entries, copying, encrypting, or decrypting */\n    for (z = zfiles; z != NULL; z = z->nxt) {\n        if (decrypt && (z->flg & 1)) {\n            printf(\"decrypting: %s\", z->zname);\n            fflush(stdout);\n            if ((res = zipbare(z, passwd)) != ZE_OK)\n            {\n                if (res != ZE_MISS) ziperr(res, \"was decrypting an entry\");\n                printf(\" (wrong password--just copying)\");\n                fflush(stdout);\n            }\n            putchar('\\n');\n\n        } else if ((!decrypt) && !(z->flg & 1)) {\n            printf(\"encrypting: %s\\n\", z->zname);\n            fflush(stdout);\n            if ((res = zipcloak(z, passwd)) != ZE_OK)\n            {\n                ziperr(res, \"was encrypting an entry\");\n            }\n        } else {\n            printf(\"   copying: %s\\n\", z->zname);\n            fflush(stdout);\n            if ((res = zipcopy(z)) != ZE_OK)\n            {\n                ziperr(res, \"was copying an entry\");\n            }\n        } /* if */\n    } /* for */\n\n    fclose(in_file);\n\n\n    /* Write central directory and end of central directory */\n\n    /* get start of central */\n    if ((start_offset = zftello(outzip)) == (zoff_t)-1)\n        ziperr(ZE_TEMP, tempzip);\n\n    for (z = zfiles; z != NULL; z = z->nxt) {\n        if ((res = putcentral(z)) != ZE_OK) ziperr(res, tempzip);\n    }\n\n    /* get end of central */\n    if ((length = zftello(outzip)) == (zoff_t)-1)\n        ziperr(ZE_TEMP, tempzip);\n\n    length -= start_offset;               /* compute length of central */\n    if ((res = putend((zoff_t)zcount, length, start_offset, zcomlen,\n                      zcomment)) != ZE_OK) {\n        ziperr(res, tempzip);\n    }\n    tempzf = NULL;\n    if (fclose(outzip)) ziperr(ZE_TEMP, tempzip);\n    if ((res = replace(out_path, tempzip)) != ZE_OK) {\n        zipwarn(\"new zip file left as: \", tempzip);\n        free((zvoid *)tempzip);\n        tempzip = NULL;\n        ziperr(res, \"was replacing the original zip file\");\n    }\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    setfileattr(zipfile, attr);\n#ifdef RISCOS\n    /* Set the filetype of the zipfile to &DDC */\n    setfiletype(zipfile, 0xDDC);\n#endif\n    free((zvoid *)in_path);\n    free((zvoid *)out_path);\n\n    free((zvoid *)zipfile);\n    zipfile = NULL;\n\n    /* Done! */\n    RETURN(0);\n}\n#else /* !CRYPT */\n\n\n/* below is only used if crypt is not enabled */\n\nstruct option_struct far options[] = {\n  /* short longopt        value_type        negatable        ID    name */\n    {\"h\",  \"help\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    /* the end of the list */\n    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */\n  };\n\n\nint main OF((void));\n\nvoid zipwarn(msg1, msg2)\nZCONST char  *msg1, *msg2;\n{\n    /* Tell picky compilers to shut up about unused variables */\n    msg1 = msg1; msg2 = msg2;\n}\n\nvoid ziperr(c, h)\nint  c;\nZCONST char *h;\n{\n    /* Tell picky compilers to shut up about unused variables */\n    c = c; h = h;\n}\n\nint main()\n{\n    fprintf(mesg, \"\\\nThis version of ZipCloak does not support encryption.  Get the current Zip\\n\\\nsource distribution and recompile ZipCloak after you have added an option to\\n\\\ndefine the symbol USE_CRYPT to the C compiler's command arguments.\\n\");\n    RETURN(1);\n}\n\n#endif /* ?CRYPT */\n"
  },
  {
    "path": "deps/infozip/zip30/zipcloak.txt",
    "content": "zipcloak(1)                                                        zipcloak(1)\n\nNAME\n       zipcloak - encrypt entries in a zipfile\n\nSYNOPSIS\n       zipcloak [-d] [-b path] [-h] [-v] [-L] zipfile\n\nARGUMENTS\n       zipfile  Zipfile to encrypt entries in\n\nOPTIONS\n       -b path\n       --temp-path path\n              Use the directory given by path for the temporary zip file.\n\n       -d\n       --decrypt\n              Decrypt encrypted entries (copy if given wrong password).\n\n       -h\n       --help\n              Show a short help.\n\n       -L\n       --license\n              Show software license.\n\n       -O path\n       --output-file zipfile\n              Write output to new archive zipfile, leaving original archive as\n              is.\n\n       -q\n       --quiet\n              Quiet operation.  Suppresses some informational messages.\n\n       -v\n       --version\n              Show version information.\n\nDESCRIPTION\n       zipcloak encrypts all unencrypted entries in the zipfile.  This is  the\n       default action.\n\n       The -d option is used to decrypt encrypted entries in the zipfile.\n\n       zipcloak uses original zip encryption which is considered weak.\n\n       Note:  The  encryption  code  of this program is not copyrighted and is\n              put in the public domain.  It was originally written  in  Europe\n              and  can  be  freely  distributed from any country including the\n              U.S.A.  (Previously if this program was imported into the U.S.A,\n              it  could not be re-exported from the U.S.A to another country.)\n              See the file README.CR included in the source  distribution  for\n              more on this.  Otherwise, the Info-ZIP license applies.\n\nEXAMPLES\n       To be added.\n\nBUGS\n       Large files (> 2 GB) and large archives not yet supported.\n\n       Split  archives  not  yet  supported.   A work around is to convert the\n       split archive to a single-file archive using zip and then use  zipcloak\n       on  the single-file archive.  If needed, the resulting archive can then\n       be split again using zip.\n\nSEE ALSO\n       zip(1), unzip(1)\n\nAUTHOR\n       Info-ZIP\n\n                              v3.0 of 8 May 2008                   zipcloak(1)\n"
  },
  {
    "path": "deps/infozip/zip30/ziperr.h",
    "content": "/*\n  ziperr.h - Zip 3\n\n  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  ziperr.h by Mark Adler\n */\n\n\n/*\n * VMS message file ident string.  (The \"-xxx\" suffix should be\n * incremented when messages are changed for a particular program\n * version.)  Used only when generating the VMS message source file, but\n * that can be done on a non-VMS system.\n */\n#define VMS_MSG_IDENT \"V3.0-000\"\n\n/* VMS-compatible \"severity\" values (bits 2:0): */\n#define ZE_S_WARNING 0x00\n#define ZE_S_SUCCESS 0x01\n#define ZE_S_ERROR   0x02\n#define ZE_S_INFO    0x03\n#define ZE_S_SEVERE  0x04\n#define ZE_S_UNUSED  0x07\n\n/* Flags: */\n#define ZE_S_PERR    0x10\n\n\n /* Error return values.  The values 0..4 and 12..18 follow the conventions\n   of PKZIP.   The values 4..10 are all assigned to \"insufficient memory\"\n   by PKZIP, so the codes 5..10 are used here for other purposes. */\n#define ZE_MISS         -1      /* used by procname(), zipbare() */\n#define ZE_OK           0       /* success */\n#define ZE_EOF          2       /* unexpected end of zip file */\n#define ZE_FORM         3       /* zip file structure error */\n#define ZE_MEM          4       /* out of memory */\n#define ZE_LOGIC        5       /* internal logic error */\n#define ZE_BIG          6       /* entry too large to split, read, or write */\n#define ZE_NOTE         7       /* invalid comment format */\n#define ZE_TEST         8       /* zip test (-T) failed or out of memory */\n#define ZE_ABORT        9       /* user interrupt or termination */\n#define ZE_TEMP         10      /* error using a temp file */\n#define ZE_READ         11      /* read or seek error */\n#define ZE_NONE         12      /* nothing to do */\n#define ZE_NAME         13      /* missing or empty zip file */\n#define ZE_WRITE        14      /* error writing to a file */\n#define ZE_CREAT        15      /* couldn't open to write */\n#define ZE_PARMS        16      /* bad command line */\n#define ZE_OPEN         18      /* could not open a specified file to read */\n#define ZE_COMPERR      19      /* error in compilation options */\n#define ZE_ZIP64        20      /* Zip64 not supported */\n\n#define ZE_MAXERR       20      /* the highest error number */\n\n\n/* Error messages for the ziperr() function in the zip programs. */\n\n#ifdef GLOBALS\nstruct\n{\n    char *name;\n    char *string;\n    int severity;\n} ziperrors[ZE_MAXERR + 1] = {\n/*  0 */ { \"OK\",      \"Normal successful completion\", ZE_S_SUCCESS },\n/*  1 */ { \"\",        \"\",                             ZE_S_UNUSED },\n/*  2 */ { \"EOF\",     \"Unexpected end of zip file\",   ZE_S_SEVERE },\n/*  3 */ { \"FORM\",    \"Zip file structure invalid\",   ZE_S_ERROR },\n/*  4 */ { \"MEM\",     \"Out of memory\",                ZE_S_SEVERE },\n/*  5 */ { \"LOGIC\",   \"Internal logic error\",         ZE_S_SEVERE },\n/*  6 */ { \"BIG\",     \"Entry too big to split, read, or write\",\n                                                      ZE_S_ERROR },\n/*  7 */ { \"NOTE\",    \"Invalid comment format\",       ZE_S_ERROR },\n/*  8 */ { \"TEST\",    \"Zip file invalid, could not spawn unzip, or wrong unzip\",\n                                                      ZE_S_SEVERE },\n/*  9 */ { \"ABORT\",   \"Interrupted\",                  ZE_S_ERROR },\n/* 10 */ { \"TEMP\",    \"Temporary file failure\",       ZE_S_SEVERE | ZE_S_PERR },\n/* 11 */ { \"READ\",    \"Input file read failure\",      ZE_S_SEVERE | ZE_S_PERR },\n/* 12 */ { \"NONE\",    \"Nothing to do!\",               ZE_S_WARNING },\n/* 13 */ { \"NAME\",    \"Missing or empty zip file\",    ZE_S_ERROR },\n/* 14 */ { \"WRITE\",   \"Output file write failure\",    ZE_S_SEVERE | ZE_S_PERR },\n/* 15 */ { \"CREAT\",   \"Could not create output file\", ZE_S_SEVERE | ZE_S_PERR },\n/* 16 */ { \"PARMS\",   \"Invalid command arguments\",    ZE_S_ERROR },\n/* 17 */ { \"\",        \"\",                             ZE_S_UNUSED },\n/* 18 */ { \"OPEN\",    \"File not found or no read permission\",\n                                                      ZE_S_ERROR | ZE_S_PERR },\n/* 19 */ { \"COMPERR\", \"Not supported\",                ZE_S_SEVERE },\n/* 20 */ { \"ZIP64\",   \"Attempt to read unsupported Zip64 archive\",\n                                                      ZE_S_SEVERE }\n#  ifdef AZTEC_C\n          ,     /* extremely lame compiler bug workaround */\n#  endif\n};\n#else /* !GLOBALS */\n/* Error messages for ziperr() */\nextern struct\n{\n    char *name;\n    char *string;\n    int severity;\n} ziperrors[ZE_MAXERR + 1];\n#endif /* ?GLOBALS */\n\n/* Macro to determine whether to call perror() or not. */\n#define PERR(e) (ziperrors[e].severity & ZE_S_PERR)\n\n/* Macro for easy access to the message string. */\n#define ZIPERRORS(e) ziperrors[e].string\n"
  },
  {
    "path": "deps/infozip/zip30/zipfile.c",
    "content": "/*\n  zipfile.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  zipfile.c by Mark Adler.\n */\n#define __ZIPFILE_C\n\n#include \"zip.h\"\n#include \"revision.h\"\n#ifdef UNICODE_SUPPORT\n# include \"crc32.h\"\n#endif\n\n/* for realloc 2/6/2005 EG */\n#include <stdlib.h>\n\n#include <errno.h>\n\n/* for toupper() */\n#include <ctype.h>\n\n#ifdef VMS\n#  include \"vms/vms.h\"\n#  include \"vms/vmsmunch.h\"\n#  include \"vms/vmsdefs.h\"\n#endif\n\n#ifdef WIN32\n#  define WIN32_LEAN_AND_MEAN\n\n#ifdef CR\n#undef CR\n#endif\n\n#  include <windows.h>\n#endif\n\n/*\n * XXX start of zipfile.h\n */\n#ifdef THEOS\n /* Macros cause stack overflow in compiler */\n ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }\n ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }\n#else /* !THEOS */\n /* Macros for converting integers in little-endian to machine format */\n# define SH(a) ((ush)(((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8)))\n# define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))\n# ifdef ZIP64_SUPPORT           /* zip64 support 08/31/2003 R.Nausedat */\n#  define LLG(a) ((zoff_t)LG(a) | ((zoff_t)LG((a)+4) << 32))\n# endif\n#endif /* ?THEOS */\n\n/* Macros for writing machine integers to little-endian format */\n#define PUTSH(a,f) {putc((char)((a) & 0xff),(f)); putc((char)((a) >> 8),(f));}\n#define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))}\n\n#ifdef ZIP64_SUPPORT           /* zip64 support 08/31/2003 R.Nausedat */\n# define PUTLLG(a,f) {PUTLG((a) & 0xffffffff,(f)) PUTLG((a) >> 32,(f))}\n#endif\n\n\n/* -- Structure of a ZIP file -- */\n\n/* Signatures for zip file information headers */\n#define LOCSIG     0x04034b50L\n#define CENSIG     0x02014b50L\n#define ENDSIG     0x06054b50L\n#define EXTLOCSIG  0x08074b50L\n\n/* Offsets of values in headers */\n/* local header */\n#define LOCVER  0               /* version needed to extract */\n#define LOCFLG  2               /* encrypt, deflate flags */\n#define LOCHOW  4               /* compression method */\n#define LOCTIM  6               /* last modified file time, DOS format */\n#define LOCDAT  8               /* last modified file date, DOS format */\n#define LOCCRC  10              /* uncompressed crc-32 for file */\n#define LOCSIZ  14              /* compressed size in zip file */\n#define LOCLEN  18              /* uncompressed size */\n#define LOCNAM  22              /* length of filename */\n#define LOCEXT  24              /* length of extra field */\n\n/* extended local header (data descriptor) following file data (if bit 3 set) */\n/* if Zip64 then all are 8 byte and not below - 11/1/03 EG */\n#define EXTCRC  0               /* uncompressed crc-32 for file */\n#define EXTSIZ  4               /* compressed size in zip file */\n#define EXTLEN  8               /* uncompressed size */\n\n/* central directory header */\n#define CENVEM  0               /* version made by */\n#define CENVER  2               /* version needed to extract */\n#define CENFLG  4               /* encrypt, deflate flags */\n#define CENHOW  6               /* compression method */\n#define CENTIM  8               /* last modified file time, DOS format */\n#define CENDAT  10              /* last modified file date, DOS format */\n#define CENCRC  12              /* uncompressed crc-32 for file */\n#define CENSIZ  16              /* compressed size in zip file */\n#define CENLEN  20              /* uncompressed size */\n#define CENNAM  24              /* length of filename */\n#define CENEXT  26              /* length of extra field */\n#define CENCOM  28              /* file comment length */\n#define CENDSK  30              /* disk number start */\n#define CENATT  32              /* internal file attributes */\n#define CENATX  34              /* external file attributes */\n#define CENOFF  38              /* relative offset of local header */\n\n/* end of central directory record */\n#define ENDDSK  0               /* number of this disk */\n#define ENDBEG  2               /* number of the starting disk */\n#define ENDSUB  4               /* entries on this disk */\n#define ENDTOT  6               /* total number of entries */\n#define ENDSIZ  8               /* size of entire central directory */\n#define ENDOFF  12              /* offset of central on starting disk */\n#define ENDCOM  16              /* length of zip file comment */\n\n/* zip64 support 08/31/2003 R.Nausedat */\n\n/* EOCDL_SIG used to detect Zip64 archive */\n#define ZIP64_EOCDL_SIG                  0x07064b50\n/* EOCDL size is used in the empty archive check */\n#define ZIP64_EOCDL_OFS_SIZE                20\n\n#define ZIP_UWORD16_MAX                  0xFFFF                        /* border value */\n#define ZIP_UWORD32_MAX                  0xFFFFFFFF                    /* border value */\n#define ZIP_EF_HEADER_SIZE               4                             /* size of pre-header of extra fields */\n\n#ifdef ZIP64_SUPPORT\n# define ZIP64_EXTCRC                    0                             /* uncompressed crc-32 for file */\n# define ZIP64_EXTSIZ                    4                             /* compressed size in zip file */\n# define ZIP64_EXTLEN                    12                            /* uncompressed size */\n# define ZIP64_EOCD_SIG                  0x06064b50\n# define ZIP64_EOCD_OFS_SIZE             40\n# define ZIP64_EOCD_OFS_CD_START         48\n# define ZIP64_EOCDL_OFS_SIZE                20\n# define ZIP64_EOCDL_OFS_EOCD_START      8\n# define ZIP64_EOCDL_OFS_TOTALDISKS      16\n# define ZIP64_MIN_VER                   45                            /* min version to set in the CD extra records */\n# define ZIP64_CENTRAL_DIR_TAIL_SIZE     (56 - 8 - 4)                  /* size of zip64 central dir tail, minus sig and size field bytes */\n# define ZIP64_CENTRAL_DIR_TAIL_SIG      0x06064B50L                   /* zip64 central dir tail signature */\n# define ZIP64_CENTRAL_DIR_TAIL_END_SIG  0x07064B50L                   /* zip64 end of cen dir locator signature */\n# define ZIP64_LARGE_FILE_HEAD_SIZE      32                            /* total size of zip64 extra field */\n# define ZIP64_EF_TAG                    0x0001                        /* ID for zip64 extra field */\n# define ZIP64_EFIELD_OFS_OSIZE          ZIP_EF_HEADER_SIZE            /* zip64 extra field: offset to original file size */\n# define ZIP64_EFIELD_OFS_CSIZE          (ZIP64_EFIELD_OFS_OSIZE + 8)  /* zip64 extra field: offset to compressed file size */\n# define ZIP64_EFIELD_OFS_OFS            (ZIP64_EFIELD_OFS_CSIZE + 8)  /* zip64 extra field: offset to offset in archive */\n# define ZIP64_EFIELD_OFS_DISK           (ZIP64_EFIELD_OFS_OFS + 8)    /* zip64 extra field: offset to start disk # */\n/* -------------------------------------------------------------------------------------------------------------------------- */\n local int adjust_zip_local_entry OF((struct zlist far *));\n local void adjust_zip_central_entry OF((struct zlist far *));\n#if 0\n local int remove_local_extra_field OF((struct zlist far *, ulg));\n local int remove_central_extra_field OF((struct zlist far *, ulg));\n#endif\n local int add_central_zip64_extra_field OF((struct zlist far *));\n local int add_local_zip64_extra_field OF((struct zlist far *));\n#endif /* ZIP64_SUPPORT */\n#ifdef UNICODE_SUPPORT\n# define UTF8_PATH_EF_TAG                0x7075                        /* ID for Unicode path (up) extra field */\n local int add_Unicode_Path_local_extra_field OF((struct zlist far *));\n local int add_Unicode_Path_cen_extra_field OF((struct zlist far *));\n#endif\n\n/* New General Purpose Bit Flag bit 11 flags when entry path and\n   comment are in UTF-8 */\n#define UTF8_BIT (1 << 11)\n\n/* moved out of ZIP64_SUPPORT - 2/6/2005 EG */\nlocal void write_ushort_to_mem OF((ush, char *));                      /* little endian conversions */\nlocal void write_ulong_to_mem OF((ulg, char *));\n#ifdef ZIP64_SUPPORT\n local void write_int64_to_mem OF((uzoff_t, char *));\n#endif /* def ZIP64_SUPPORT */\n#ifdef UNICODE_SUPPORT\n local void write_string_to_mem OF((char *, char *));\n#endif\n#if 0\nlocal char *get_extra_field OF((ush, char *, unsigned));           /* zip64 */\n#endif\n#ifdef UNICODE_SUPPORT\nlocal void read_Unicode_Path_entry OF((struct zlist far *));\nlocal void read_Unicode_Path_local_entry OF((struct zlist far *));\n#endif\n\n/* added these self allocators - 2/6/2005 EG */\nlocal void append_ushort_to_mem OF((ush, char **, extent *, extent *));\nlocal void append_ulong_to_mem OF((ulg, char **, extent *, extent *));\n#ifdef ZIP64_SUPPORT\n local void append_int64_to_mem OF((uzoff_t, char **, extent *, extent *));\n#endif /* def ZIP64_SUPPORT */\nlocal void append_string_to_mem OF((char *, int, char**, extent *, extent *));\n\n\n/* Local functions */\n\nlocal int find_next_signature OF((FILE *f));\nlocal int find_signature OF((FILE *, ZCONST char *));\nlocal int is_signature OF((ZCONST char *, ZCONST char *));\nlocal int at_signature OF((FILE *, ZCONST char *));\n\nlocal int zqcmp OF((ZCONST zvoid *, ZCONST zvoid *));\n#ifdef UNICODE_SUPPORT\nlocal int zuqcmp OF((ZCONST zvoid *, ZCONST zvoid *));\n#endif\n#if 0\n local int scanzipf_reg OF((FILE *f));\n#endif\nlocal int scanzipf_regnew OF((void));\n#ifndef UTIL\n local int rqcmp OF((ZCONST zvoid *, ZCONST zvoid *));\n local int zbcmp OF((ZCONST zvoid *, ZCONST zvoid far *));\n# ifdef UNICODE_SUPPORT\n local int zubcmp OF((ZCONST zvoid *, ZCONST zvoid far *));\n#  if 0\n local int zuebcmp OF((ZCONST zvoid *, ZCONST zvoid far *));\n#  endif\n# endif /* UNICODE_SUPPORT */\n local void zipoddities OF((struct zlist far *));\n# if 0\n  local int scanzipf_fix OF((FILE *f));\n# endif\n local int scanzipf_fixnew OF((void));\n# ifdef USE_EF_UT_TIME\n   local int ef_scan_ut_time OF((char *ef_buf, extent ef_len, int ef_is_cent,\n                                   iztimes *z_utim));\n# endif /* USE_EF_UT_TIME */\n local void cutpath OF((char *p, int delim));\n#endif /* !UTIL */\n\n/*\n * XXX end of zipfile.h\n */\n\n/* Local data */\n\n#ifdef HANDLE_AMIGA_SFX\n   ulg amiga_sfx_offset;        /* place where size field needs updating */\n#endif\n\nlocal int zqcmp(a, b)\nZCONST zvoid *a, *b;          /* pointers to pointers to zip entries */\n/* Used by qsort() to compare entries in the zfile list.\n * Compares the internal names z->iname */\n{\n  char *aname = (*(struct zlist far **)a)->iname;\n  char *bname = (*(struct zlist far **)b)->iname;\n\n  return namecmp(aname, bname);\n}\n\n#ifdef UNICODE_SUPPORT\nlocal int zuqcmp(a, b)\nZCONST zvoid *a, *b;          /* pointers to pointers to zip entries */\n/* Used by qsort() to compare entries in the zfile list.\n * Compares the internal names z->zuname */\n{\n  char *aname = (*(struct zlist far **)a)->iname;\n  char *bname = (*(struct zlist far **)b)->iname;\n\n  /* zuname could be NULL */\n  if ((*(struct zlist far **)a)->zuname)\n    aname = (*(struct zlist far **)a)->zuname;\n  if ((*(struct zlist far **)b)->zuname)\n    bname = (*(struct zlist far **)b)->zuname;\n  return namecmp(aname, bname);\n}\n#endif\n\n\n#ifndef UTIL\n\nlocal int rqcmp(a, b)\nZCONST zvoid *a, *b;          /* pointers to pointers to zip entries */\n/* Used by qsort() to compare entries in the zfile list.\n * Compare the internal names z->iname, but in reverse order. */\n{\n  return namecmp((*(struct zlist far **)b)->iname,\n                 (*(struct zlist far **)a)->iname);\n}\n\n\nlocal int zbcmp(n, z)\nZCONST zvoid *n;        /* string to search for */\nZCONST zvoid far *z;    /* pointer to a pointer to a zip entry */\n/* Used by search() to compare a target to an entry in the zfile list. */\n{\n  return namecmp((char *)n, ((struct zlist far *)z)->zname);\n}\n\n#ifdef UNICODE_SUPPORT\n/* search unicode paths */\nlocal int zubcmp(n, z)\nZCONST zvoid *n;        /* string to search for */\nZCONST zvoid far *z;    /* pointer to a pointer to a zip entry */\n/* Used by search() to compare a target to an entry in the zfile list. */\n{\n  char *zuname = ((struct zlist far *)z)->zuname;\n\n  /* zuname is NULL if no UTF-8 name */\n  if (zuname == NULL)\n    zuname = ((struct zlist far *)z)->zname;\n\n  return namecmp((char *)n, zuname);\n}\n\n#if 0\n/* search escaped unicode paths */\nlocal int zuebcmp(n, z)\nZCONST zvoid *n;        /* string to search for */\nZCONST zvoid far *z;    /* pointer to a pointer to a zip entry */\n/* Used by search() to compare a target to an entry in the zfile list. */\n{\n  char *zuname = ((struct zlist far *)z)->zuname;\n  char *zuename;\n  int k;\n\n  /* zuname is NULL if no UTF-8 name */\n  if (zuname == NULL)\n    zuname = ((struct zlist far *)z)->zname;\n  zuename = local_to_escape_string(zuname);\n  k = namecmp((char *)n, zuename);\n  free(zuename);\n\n  return k;\n}\n#endif\n#endif\n\n\nstruct zlist far *zsearch(n)\n  ZCONST char *n;      /* name to find */\n/* Return a pointer to the entry in zfile with the name n, or NULL if\n   not found. */\n{\n  zvoid far **p;        /* result of search() */\n\n  if (zcount) {\n    if ((p = search(n, (ZCONST zvoid far **)zsort, zcount, zbcmp)) != NULL)\n      return *(struct zlist far **)p;\n#ifdef UNICODE_SUPPORT\n    else if (unicode_mismatch != 3 && fix != 2 &&\n        (p = search(n, (ZCONST zvoid far **)zusort, zcount, zubcmp)) != NULL)\n      return *(struct zlist far **)p;\n#endif\n    else\n      return NULL;\n  }\n  return NULL;\n}\n\n#endif /* !UTIL */\n\n#ifndef VMS     /* See [.VMS]VMS.C for VMS-specific ziptyp(). */\n#  ifndef PATHCUT\n#    define PATHCUT '/'\n#  endif\n\nchar *ziptyp(s)\n  char *s;             /* file name to force to zip */\n/* If the file name *s has a dot (other than the first char), or if\n   the -A option is used (adjust self-extracting file) then return\n   the name, otherwise append .zip to the name.  Allocate the space for\n   the name in either case.  Return a pointer to the new name, or NULL\n   if malloc() fails. */\n{\n  char *q;              /* temporary pointer */\n  char *t;              /* pointer to malloc'ed string */\n#  ifdef THEOS\n  char *r;              /* temporary pointer */\n  char *disk;\n#  endif\n\n  if ((t = malloc(strlen(s) + 5)) == NULL)\n    return NULL;\n  strcpy(t, s);\n#  ifdef __human68k__\n  _toslash(t);\n#  endif\n#  ifdef MSDOS\n  for (q = t; *q; INCSTR(q))\n    if (*q == '\\\\')\n      *q = '/';\n#  endif /* MSDOS */\n#  if defined(__RSXNT__) || defined(WIN32_CRT_OEM)\n   /* RSXNT/EMX C rtl uses OEM charset */\n  AnsiToOem(t, t);\n#  endif\n  if (adjust) return t;\n#  ifndef RISCOS\n#    ifndef QDOS\n#      ifdef AMIGA\n  if ((q = MBSRCHR(t, '/')) == NULL)\n    q = MBSRCHR(t, ':');\n  if (MBSRCHR((q ? q + 1 : t), '.') == NULL)\n#      else /* !AMIGA */\n#        ifdef THEOS\n  /* the argument expansion add a dot to the end of file names when\n   * there is no extension and at least one of a argument has wild cards.\n   * So check for at least one character in the extension if there is a dot\n   * in file name */\n  if ((q = MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.')) == NULL\n    || q[1] == '\\0') {\n#        else /* !THEOS */\n#          ifdef TANDEM\n  if (MBSRCHR((q = MBSRCHR(t, '.')) == NULL ? t : q + 1, ' ') == NULL)\n#          else /* !TANDEM */\n  if (MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)\n#          endif /* ?TANDEM */\n#        endif /* ?THEOS */\n#      endif /* ?AMIGA */\n#      ifdef CMS_MVS\n    if (strncmp(t,\"dd:\",3) != 0 && strncmp(t,\"DD:\",3) != 0)\n#      endif /* CMS_MVS */\n#      ifdef THEOS\n    /* insert .zip extension before disk name */\n    if ((r = MBSRCHR(t, ':')) != NULL) {\n        /* save disk name */\n        if ((disk = strdup(r)) == NULL)\n            return NULL;\n        strcpy(r[-1] == '.' ? r - 1 : r, \".zip\");\n        strcat(t, disk);\n        free(disk);\n    } else {\n        if (q != NULL && *q == '.')\n          strcpy(q, \".zip\");\n        else\n          strcat(t, \".zip\");\n    }\n  }\n#      else /* !THEOS */\n#        ifdef TANDEM     /*  Tandem can't cope with extensions */\n    strcat(t, \" ZIP\");\n#        else /* !TANDEM */\n    strcat(t, \".zip\");\n#        endif /* ?TANDEM */\n#      endif /* ?THEOS */\n#    else /* QDOS */\n  q = LastDir(t);\n  if(MBSRCHR(q, '_') == NULL && MBSRCHR(q, '.') == NULL)\n  {\n      strcat(t, \"_zip\");\n  }\n#    endif /* QDOS */\n#  endif /* !RISCOS */\n  return t;\n}\n#endif  /* ndef VMS */\n\n/* ---------------------------------------------------- */\n\n/* moved out of ZIP64_SUPPORT - 2/6/2005 EG */\n\n/* 08/31/2003 R.Nausedat */\n\nlocal void write_ushort_to_mem( OFT( ush) usValue,\n                                OFT( char *)pPtr)\n#ifdef NO_PROTO\n  ush usValue;\n  char *pPtr;\n#endif /* def NO_PROTO */\n{\n  *pPtr++ = ((char)(usValue) & 0xff);\n  *pPtr = ((char)(usValue >> 8) & 0xff);\n}\n\nlocal void write_ulong_to_mem(uValue, pPtr)\nulg uValue;\nchar *pPtr;\n{\n  write_ushort_to_mem((ush)(uValue & 0xffff), pPtr);\n  write_ushort_to_mem((ush)((uValue >> 16) & 0xffff), pPtr + 2);\n}\n\n#ifdef ZIP64_SUPPORT\n\nlocal void write_int64_to_mem(l64Value,pPtr)\n  uzoff_t l64Value;\n  char *pPtr;\n{\n  write_ulong_to_mem((ulg)(l64Value & 0xffffffff),pPtr);\n  write_ulong_to_mem((ulg)((l64Value >> 32) & 0xffffffff),pPtr + 4);\n}\n\n#endif /* def ZIP64_SUPPORT */\n\n#ifdef UNICODE_SUPPORT\n\n/* Write a string to memory */\nlocal void write_string_to_mem(strValue, pPtr)\n  char *strValue;\n  char *pPtr;\n{\n  if (strValue != NULL) {\n    int ssize = strlen(strValue);\n    int i;\n\n    for (i = 0; i < ssize; i++) {\n      *(pPtr + i) = *(strValue + i);\n    }\n  }\n}\n\n#endif /* def UNICODE_SUPPORT */\n\n\n\n/* same as above but allocate memory as needed and keep track of current end\n   using offset - 2/6/05 EG */\n\n#if 0 /* ubyte version not used */\nlocal void append_ubyte_to_mem( OFT( unsigned char) ubValue,\n                                OFT( char **) pPtr,\n                                OFT( extent *) offset,\n                                OFT( extent *) blocksize)\n#ifdef NO_PROTO\n  unsigned char ubValue;  /* byte to append */\n  char **pPtr;            /* start of block */\n  extent *offset;         /* next byte to write */\n  extent *blocksize;      /* current size of block */\n#endif /* def NO_PROTO */\n{\n  if (*pPtr == NULL) {\n    /* malloc a 1K block */\n    (*blocksize) = 1024;\n    *pPtr = (char *) malloc(*blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ubyte_to_mem\");\n    }\n  }\n  /* if (*offset) + 1 > (*blocksize) - 1 */\n  else if ((*offset) > (*blocksize) - (1 + 1)) {\n    /* realloc a bigger block in 1 K increments */\n    (*blocksize) += 1024;\n    *pPtr = realloc(*pPtr, *blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ubyte_to_mem\");\n    }\n  }\n  *(*pPtr + *offset) = ubValue;\n  (*offset)++;\n}\n#endif\n\nlocal void append_ushort_to_mem( OFT( ush) usValue,\n                                 OFT( char **) pPtr,\n                                 OFT( extent *) offset,\n                                 OFT( extent *) blocksize)\n#ifdef NO_PROTO\n  ush usValue;\n  char **pPtr;\n  extent *offset;\n  extent *blocksize;\n#endif /* def NO_PROTO */\n{\n  if (*pPtr == NULL) {\n    /* malloc a 1K block */\n    (*blocksize) = 1024;\n    *pPtr = (char *) malloc(*blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ushort_to_mem\");\n    }\n  }\n  /* if (*offset) + 2 > (*blocksize) - 1 */\n  else if ((*offset) > (*blocksize) - (1 + 2)) {\n    /* realloc a bigger block in 1 K increments */\n    (*blocksize) += 1024;\n    *pPtr = realloc(*pPtr, (extent)*blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ushort_to_mem\");\n    }\n  }\n  write_ushort_to_mem(usValue, (*pPtr) + (*offset));\n  (*offset) += 2;\n}\n\nlocal void append_ulong_to_mem(uValue, pPtr, offset, blocksize)\n  ulg uValue;\n  char **pPtr;\n  extent *offset;\n  extent *blocksize;\n{\n  if (*pPtr == NULL) {\n    /* malloc a 1K block */\n    (*blocksize) = 1024;\n    *pPtr = (char *) malloc(*blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ulong_to_mem\");\n    }\n  }\n  else if ((*offset) > (*blocksize) - (1 + 4)) {\n    /* realloc a bigger block in 1 K increments */\n    (*blocksize) += 1024;\n    *pPtr = realloc(*pPtr, *blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_ulong_to_mem\");\n    }\n  }\n  write_ulong_to_mem(uValue, (*pPtr) + (*offset));\n  (*offset) += 4;\n}\n\n#ifdef ZIP64_SUPPORT\n\nlocal void append_int64_to_mem(l64Value, pPtr, offset, blocksize)\n  uzoff_t l64Value;\n  char **pPtr;\n  extent *offset;\n  extent *blocksize;\n{\n  if (*pPtr == NULL) {\n    /* malloc a 1K block */\n    (*blocksize) = 1024;\n    *pPtr = (char *) malloc(*blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_int64_to_mem\");\n    }\n  }\n  else if ((*offset) > (*blocksize) - (1 + 8)) {\n    /* realloc a bigger block in 1 K increments */\n    (*blocksize) += 1024;\n    *pPtr = realloc(*pPtr, *blocksize);\n    if (*pPtr == NULL) {\n      ziperr(ZE_MEM, \"append_int64_to_mem\");\n    }\n  }\n  write_int64_to_mem(l64Value, (*pPtr) + (*offset));\n  (*offset) += 8;\n}\n\n#endif /* def ZIP64_SUPPORT */\n\n/* Append a string to the memory block. */\nlocal void append_string_to_mem(strValue, strLength, pPtr, offset, blocksize)\n  char *strValue;\n  int  strLength;\n  char **pPtr;\n  extent *offset;\n  extent *blocksize;\n{\n  if (strValue != NULL) {\n    unsigned bsize = 1024;\n    unsigned ssize = strLength;\n    unsigned i;\n\n    if (ssize > bsize) {\n      bsize = ssize;\n    }\n    if (*pPtr == NULL) {\n      /* malloc a 1K block */\n      (*blocksize) = bsize;\n      *pPtr = (char *) malloc(*blocksize);\n      if (*pPtr == NULL) {\n        ziperr(ZE_MEM, \"append_string_to_mem\");\n      }\n    }\n    else if ((*offset) + ssize > (*blocksize) - 1) {\n      /* realloc a bigger block in 1 K increments */\n      (*blocksize) += bsize;\n      *pPtr = realloc(*pPtr, *blocksize);\n      if (*pPtr == NULL) {\n        ziperr(ZE_MEM, \"append_string_to_mem\");\n      }\n    }\n    for (i = 0; i < ssize; i++) {\n      *(*pPtr + *offset + i) = *(strValue + i);\n    }\n    (*offset) += ssize;\n  }\n}\n\n/* ---------------------------------------------------- */\n\n/* zip64 support 08/31/2003 R.Nausedat */\n/* moved out of zip64 support 10/22/05 */\n\n/* Searches pExtra for extra field with specified tag.\n * If it finds one it returns a pointer to it, else NULL.\n * Renamed and made generic.  10/3/03\n */\nchar *get_extra_field( OFT( ush) tag,\n                       OFT( char *) pExtra,\n                       OFT( unsigned) iExtraLen)\n#ifdef NO_PROTO\n  ush tag;              /* tag to look for */\n  char *pExtra;         /* pointer to extra field in memory */\n  unsigned iExtraLen;   /* length of extra field */\n#endif /* def NO_PROTO */\n{\n  char  *pTemp;\n  ush   usBlockTag;\n  ush   usBlockSize;\n\n  if( pExtra == NULL )\n    return NULL;\n\n  for (pTemp = pExtra; pTemp < pExtra  + iExtraLen - ZIP_EF_HEADER_SIZE;)\n  {\n    usBlockTag = SH(pTemp);       /* get tag */\n    usBlockSize = SH(pTemp + 2);  /* get field data size */\n    if (usBlockTag == tag)\n      return pTemp;\n    pTemp += (usBlockSize + ZIP_EF_HEADER_SIZE);\n  }\n  return NULL;\n}\n\n/* copy_nondup_extra_fields\n *\n * Copy any extra fields in old that are not in new to new.\n * Returns the new extra fields block and newLen is new length.\n */\nchar *copy_nondup_extra_fields(oldExtra, oldExtraLen, newExtra, newExtraLen, newLen)\n  char *oldExtra;       /* pointer to old extra fields */\n  unsigned oldExtraLen; /* length of old extra fields */\n  char *newExtra;       /* pointer to new extra fields */\n  unsigned newExtraLen; /* length of new extra fields */\n  unsigned *newLen;     /* length of new extra fields after copy */\n{\n  char *returnExtra = NULL;\n  ush   returnExtraLen = 0;\n  char *tempExtra;\n  char *pTemp;\n  ush   tag;\n  ush   blocksize;\n\n  if( oldExtra == NULL ) {\n    /* no old extra fields so return copy of newExtra */\n    if (newExtra == NULL || newExtraLen == 0) {\n      *newLen = 0;\n      return NULL;\n    } else {\n      if ((returnExtra = malloc(newExtraLen)) == NULL)\n        ZIPERR(ZE_MEM, \"extra field copy\");\n      memcpy(returnExtra, newExtra, newExtraLen);\n      returnExtraLen = newExtraLen;\n      *newLen = returnExtraLen;\n      return returnExtra;\n    }\n  }\n\n  /* allocate block large enough for all extra fields */\n  if ((tempExtra = malloc(0xFFFF)) == NULL)\n    ZIPERR(ZE_MEM, \"extra field copy\");\n\n  /* look for each old extra field in new block */\n  for (pTemp = oldExtra; pTemp < oldExtra  + oldExtraLen;)\n  {\n    tag = SH(pTemp);            /* get tag */\n    blocksize = SH(pTemp + 2);  /* get field data size */\n    if (get_extra_field(tag, newExtra, newExtraLen) == NULL) {\n      /* tag not in new block so add it */\n      memcpy(tempExtra + returnExtraLen, pTemp, blocksize + 4);\n      returnExtraLen += blocksize + 4;\n    }\n    pTemp += blocksize + 4;\n  }\n\n  /* copy all extra fields from new block */\n  memcpy(tempExtra + returnExtraLen, newExtra, newExtraLen);\n  returnExtraLen += newExtraLen;\n\n  /* copy tempExtra to returnExtra */\n  if ((returnExtra = malloc(returnExtraLen)) == NULL)\n    ZIPERR(ZE_MEM, \"extra field copy\");\n  memcpy(returnExtra, tempExtra, returnExtraLen);\n  free(tempExtra);\n\n  *newLen = returnExtraLen;\n  return returnExtra;\n}\n\n#ifdef UNICODE_SUPPORT\n\n/* The latest format is\n     1 byte     Version of Unicode Path Extra Field\n     4 bytes    Name Field CRC32 Checksum\n     variable   UTF-8 Version Of Name\n */\n\nlocal void read_Unicode_Path_entry(pZipListEntry)\n  struct zlist far *pZipListEntry;\n{\n  char *pTemp;\n  char *UPath;\n  char *iname;\n  ush ELen;\n  uch Version;\n  ush ULen;\n  ulg chksum = CRCVAL_INITIAL;\n  ulg iname_chksum;\n\n  /* check if we have a Unicode Path extra field ... */\n  pTemp = get_extra_field( UTF8_PATH_EF_TAG, pZipListEntry->cextra, pZipListEntry->cext );\n  pZipListEntry->uname = NULL;\n  if( pTemp == NULL ) {\n    return;\n  }\n\n  /* ... if so, update corresponding entries in struct zlist */\n\n  pTemp += 2;\n\n  /* length of this extra field */\n  ELen = SH(pTemp);\n  pTemp += 2;\n\n  /* version */\n  Version = (uch) *pTemp;\n  pTemp += 1;\n  if (Version > 1) {\n    zipwarn(\"Unicode Path Extra Field version > 1 - skipping\", pZipListEntry->oname);\n    return;\n  }\n\n  /* iname CRC */\n  iname_chksum = LG(pTemp);\n  pTemp += 4;\n\n  /*\n   * Compute the CRC-32 checksum of iname\n   */\n/*\n  crc_16 = crc16f((uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));\n */\n\n  if ((iname = malloc(strlen(pZipListEntry->iname) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"write Unicode\");\n  }\n  strcpy(iname, pZipListEntry->iname);\n\n  chksum = crc32(chksum, (uch *)(iname), strlen(iname));\n\n  free(iname);\n\n/*  chksum = adler16(ADLERVAL_INITIAL,\n    (uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));\n*/\n\n  /* If the checksums's don't match then likely iname has been modified and\n   * the Unicode Path is no longer valid\n   */\n  if (chksum != iname_chksum) {\n    printf(\"unicode_mismatch = %d\\n\", unicode_mismatch);\n    if (unicode_mismatch == 1) {\n      /* warn and continue */\n      zipwarn(\"Unicode does not match path - ignoring Unicode: \", pZipListEntry->oname);\n    } else if (unicode_mismatch == 2) {\n      /* ignore and continue */\n    } else if (unicode_mismatch == 0) {\n      /* error */\n      sprintf(errbuf, \"Unicode does not match path:  %s\\n\", pZipListEntry->oname);\n      strcat(errbuf,\n        \"                     Likely entry name changed but Unicode not updated\\n\");\n      strcat(errbuf,\n        \"                     Use -UN=i to ignore errors or n for no Unicode paths\");\n      zipwarn(errbuf, \"\");\n      ZIPERR(ZE_FORM, \"Unicode path error\");\n    }\n    return;\n  }\n\n  ULen = ELen - 5;\n\n  /* UTF-8 Path */\n  if (ULen == 0) {\n    /* standard path is UTF-8 so use that */\n    ULen = pZipListEntry->nam;\n    if ((UPath = malloc(ULen + 1)) == NULL) {\n      return;\n    }\n    strcpy(UPath, pZipListEntry->name);\n  } else {\n    /* use Unicode path */\n    if ((UPath = malloc(ULen + 1)) == NULL) {\n      return;\n    }\n    strncpy(UPath, pTemp, ULen);\n    UPath[ULen] = '\\0';\n  }\n  pZipListEntry->uname = UPath;\n  return;\n}\n\nlocal void read_Unicode_Path_local_entry(pZipListEntry)\n  struct zlist far *pZipListEntry;\n{\n  char *pTemp;\n  char *UPath;\n  char *iname;\n  ush ELen;\n  uch Version;\n  ush ULen;\n  ulg chksum = CRCVAL_INITIAL;\n  ulg iname_chksum;\n\n  /* check if we have a Unicode Path extra field ... */\n  pTemp = get_extra_field( UTF8_PATH_EF_TAG, pZipListEntry->extra, pZipListEntry->ext );\n  pZipListEntry->uname = NULL;\n  if( pTemp == NULL ) {\n    return;\n  }\n\n  /* ... if so, update corresponding entries in struct zlist */\n\n  pTemp += 2;\n\n  /* length of this extra field */\n  ELen = SH(pTemp);\n  pTemp += 2;\n\n  /* version */\n  Version = (uch) *pTemp;\n  pTemp += 1;\n  if (Version > 1) {\n    zipwarn(\"Unicode Path Extra Field version > 1 - skipping\", pZipListEntry->oname);\n    return;\n  }\n\n  /* iname CRC */\n  iname_chksum = LG(pTemp);\n  pTemp += 4;\n\n  /*\n   * Compute 32-bit crc of iname and AND halves to make 16-bit version\n   */\n  /*\n  chksum = adler16(ADLERVAL_INITIAL,\n    (uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));\n  */\n\n  if ((iname = malloc(strlen(pZipListEntry->iname) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"write Unicode\");\n  }\n  strcpy(iname, pZipListEntry->iname);\n\n  chksum = crc32(chksum, (uch *)(iname), strlen(iname));\n\n  free(iname);\n\n  /* If the checksums's don't match then likely iname has been modified and\n   * the Unicode Path is no longer valid\n   */\n  if (chksum != iname_chksum) {\n    if (unicode_mismatch == 1) {\n      /* warn and continue */\n      zipwarn(\"Unicode does not match path - ignoring Unicode: \", pZipListEntry->oname);\n    } else if (unicode_mismatch == 2) {\n      /* ignore and continue */\n    } else if (unicode_mismatch == 0) {\n      /* error */\n      sprintf(errbuf, \"Unicode does not match path:  %s\\n\", pZipListEntry->oname);\n      strcat(errbuf,\n        \"                     Likely entry name changed but Unicode not updated\\n\");\n      strcat(errbuf,\n        \"                     Use -UN=i to ignore errors or n for no Unicode paths\");\n      zipwarn(errbuf, \"\");\n      ZIPERR(ZE_FORM, \"Unicode path error\");\n    }\n    return;\n  }\n\n  ULen = ELen - 5;\n\n  /* UTF-8 Path */\n  if (ULen == 0) {\n    /* standard path is UTF-8 so use that */\n    ULen = pZipListEntry->nam;\n    if ((UPath = malloc(ULen + 1)) == NULL) {\n      return;\n    }\n    strcpy(UPath, pZipListEntry->name);\n  } else {\n    /* use Unicode path */\n    if ((UPath = malloc(ULen + 1)) == NULL) {\n      return;\n    }\n    strncpy(UPath, pTemp, ULen);\n    UPath[ULen] = '\\0';\n  }\n  pZipListEntry->uname = UPath;\n  return;\n}\n\n#endif /* def UNICODE_SUPPORT */\n\n#ifdef ZIP64_SUPPORT           /* zip64 support 08/31/2003 R.Nausedat */\n\n/* searches the cextra member of zlist for a zip64 extra field. if it finds one it  */\n/* updates the len, siz and off members of zlist with the corresponding values of   */\n/* the zip64 extra field, that is if either the len, siz or off member of zlist is  */\n/* set to its max value we have to use the corresponding value from the zip64 extra */\n/* field. as of now the dsk member of zlist is not much of interest since we should */\n/* not modify multi volume archives at all.                                         */\nlocal void adjust_zip_central_entry(pZipListEntry)\n  struct zlist far *pZipListEntry;\n{\n  char  *pTemp;\n\n  /* assume not using zip64 fields */\n  zip64_entry = 0;\n\n  /* check if we have a \"large file\" Zip64 extra field ... */\n  pTemp = get_extra_field( ZIP64_EF_TAG, pZipListEntry->cextra, pZipListEntry->cext );\n  if( pTemp == NULL )\n    return;\n\n  /* using zip64 field */\n  zip64_entry = 1;\n  pTemp += ZIP_EF_HEADER_SIZE;\n\n  /* ... if so, update corresponding entries in struct zlist */\n  if (pZipListEntry->len == ZIP_UWORD32_MAX)\n  {\n    pZipListEntry->len = LLG(pTemp);\n    pTemp += 8;\n  }\n\n  if (pZipListEntry->siz == ZIP_UWORD32_MAX)\n  {\n    pZipListEntry->siz = LLG(pTemp);\n    pTemp += 8;\n  }\n\n  if (pZipListEntry->off == ZIP_UWORD32_MAX)\n  {\n    pZipListEntry->off = LLG(pTemp);\n    pTemp += 8;\n  }\n\n  if (pZipListEntry->dsk == ZIP_UWORD16_MAX)\n  {\n    pZipListEntry->dsk = LG(pTemp);\n  }\n\n}\n\n\n/* adjust_zip_local_entry\n *\n * Return 1 if there is a Zip64 extra field and 0 if not\n */\nlocal int adjust_zip_local_entry(pZipListEntry)\n  struct zlist far *pZipListEntry;\n{\n  char  *pTemp;\n\n  /* assume not using zip64 fields */\n  zip64_entry = 0;\n\n  /* check if we have a \"large file\" Zip64 extra field ... */\n  pTemp = get_extra_field(ZIP64_EF_TAG, pZipListEntry->extra, pZipListEntry->ext );\n  if( pTemp == NULL )\n    return zip64_entry;\n\n  /* using zip64 field */\n  zip64_entry = 1;\n  pTemp += ZIP_EF_HEADER_SIZE;\n\n  /* ... if so, update corresponding entries in struct zlist */\n  if (pZipListEntry->len == ZIP_UWORD32_MAX)\n  {\n    pZipListEntry->len = LLG(pTemp);\n    pTemp += 8;\n  }\n\n  if (pZipListEntry->siz == ZIP_UWORD32_MAX)\n  {\n    pZipListEntry->siz = LLG(pTemp);\n    pTemp += 8;\n  }\n  return zip64_entry;\n}\n\n/* adds a zip64 extra field to the data the cextra member of zlist points to. If\n * there is already a zip64 extra field present delete it first.\n */\nlocal int add_central_zip64_extra_field(pZipListEntry)\n  struct zlist far *pZipListEntry;\n{\n  char   *pExtraFieldPtr;\n  char   *pTemp;\n  ush    usTemp;\n  ush    efsize = 0;\n  ush    esize;\n  ush    oldefsize;\n  extent len;\n  int    used_zip64 = 0;\n\n  /* get length of ef based on which fields exceed limits */\n  /* AppNote says:\n   *      The order of the fields in the ZIP64 extended\n   *      information record is fixed, but the fields will\n   *      only appear if the corresponding Local or Central\n   *      directory record field is set to 0xFFFF or 0xFFFFFFFF.\n   */\n  efsize = ZIP_EF_HEADER_SIZE;             /* type + size */\n  if (pZipListEntry->len > ZIP_UWORD32_MAX || force_zip64 == 1) {\n    /* compressed size */\n    efsize += 8;\n    used_zip64 = 1;\n  }\n  if (pZipListEntry->siz > ZIP_UWORD32_MAX) {\n    /* uncompressed size */\n    efsize += 8;\n    used_zip64 = 1;\n  }\n  if (pZipListEntry->off > ZIP_UWORD32_MAX) {\n    /* offset */\n    efsize += 8;\n    used_zip64 = 1;\n  }\n  if (pZipListEntry->dsk > ZIP_UWORD16_MAX) {\n    /* disk number */\n    efsize += 4;\n    used_zip64 = 1;\n  }\n\n  if (used_zip64 && force_zip64 == 0) {\n    zipwarn(\"Large entry support disabled using -fz- but needed\", \"\");\n    return ZE_BIG;\n  }\n\n  /* malloc zip64 extra field? */\n  if( pZipListEntry->cextra == NULL )\n  {\n    if (efsize == ZIP_EF_HEADER_SIZE) {\n      return ZE_OK;\n    }\n    if ((pExtraFieldPtr = pZipListEntry->cextra = (char *) malloc(efsize)) == NULL) {\n      return ZE_MEM;\n    }\n    pZipListEntry->cext = efsize;\n  }\n  else\n  {\n    /* check if we have a \"large file\" extra field ... */\n    pExtraFieldPtr = get_extra_field(ZIP64_EF_TAG, pZipListEntry->cextra, pZipListEntry->cext);\n    if( pExtraFieldPtr == NULL )\n    {\n      /* ... we don't, so re-malloc enough memory for the old extra data plus\n       * the size of the zip64 extra field\n       */\n      if ((pExtraFieldPtr = (char *) malloc(efsize + pZipListEntry->cext)) == NULL) {\n        return ZE_MEM;\n      }\n      /* move the old extra field */\n      memmove(pExtraFieldPtr, pZipListEntry->cextra, pZipListEntry->cext);\n      free(pZipListEntry->cextra);\n      pZipListEntry->cextra = pExtraFieldPtr;\n      pExtraFieldPtr += pZipListEntry->cext;\n      pZipListEntry->cext += efsize;\n    }\n    else\n    {\n      /* ... we have. sort out the existing zip64 extra field and remove it from\n       * pZipListEntry->cextra, re-malloc enough memory for the old extra data\n       * left plus the size of the zip64 extra field\n       */\n      usTemp = SH(pExtraFieldPtr + 2);\n      /* if pZipListEntry->cextra == pExtraFieldPtr and pZipListEntry->cext == usTemp + efsize\n       * we should have only one extra field, and this is a zip64 extra field. as some\n       * zip tools seem to require fixed zip64 extra fields we have to check if\n       * usTemp + ZIP_EF_HEADER_SIZE is equal to ZIP64_LARGE_FILE_HEAD_SIZE. if it\n       * isn't, we free the old extra field and allocate memory for a new one\n       */\n      if( pZipListEntry->cext == (extent)(usTemp + ZIP_EF_HEADER_SIZE) )\n      {\n        /* just Zip64 extra field in extra field */\n        if( pZipListEntry->cext != efsize )\n        {\n          /* wrong size */\n          if ((pExtraFieldPtr = (char *) malloc(efsize)) == NULL) {\n            return ZE_MEM;\n          }\n          free(pZipListEntry->cextra);\n          pZipListEntry->cextra = pExtraFieldPtr;\n          pZipListEntry->cext = efsize;\n        }\n      }\n      else\n      {\n        /* get the old Zip64 extra field out and add new */\n        oldefsize = usTemp + ZIP_EF_HEADER_SIZE;\n        if ((pTemp = (char *) malloc(pZipListEntry->cext - oldefsize + efsize)) == NULL) {\n          return ZE_MEM;\n        }\n        len = (extent)(pExtraFieldPtr - pZipListEntry->cextra);\n        memcpy(pTemp, pZipListEntry->cextra, len);\n        memcpy(pTemp + len, pExtraFieldPtr + oldefsize,\n          pZipListEntry->cext - oldefsize - len);\n        pZipListEntry->cext -= oldefsize;\n        pExtraFieldPtr = pTemp + pZipListEntry->cext;\n        pZipListEntry->cext += efsize;\n        free(pZipListEntry->cextra);\n        pZipListEntry->cextra = pTemp;\n      }\n    }\n  }\n\n  /* set zip64 extra field members */\n  write_ushort_to_mem(ZIP64_EF_TAG, pExtraFieldPtr);\n  write_ushort_to_mem((ush) (efsize - ZIP_EF_HEADER_SIZE), pExtraFieldPtr + 2);\n  esize = ZIP_EF_HEADER_SIZE;\n  if (pZipListEntry->len > ZIP_UWORD32_MAX || force_zip64 == 1) {\n    write_int64_to_mem(pZipListEntry->len, pExtraFieldPtr + esize);\n    esize += 8;\n  }\n  if (pZipListEntry->siz > ZIP_UWORD32_MAX) {\n    write_int64_to_mem(pZipListEntry->siz, pExtraFieldPtr + esize);\n    esize += 8;\n  }\n  if (pZipListEntry->off > ZIP_UWORD32_MAX) {\n    write_int64_to_mem(pZipListEntry->off, pExtraFieldPtr + esize);\n    esize += 8;\n  }\n  if (pZipListEntry->dsk > ZIP_UWORD16_MAX) {\n    write_ulong_to_mem(pZipListEntry->dsk, pExtraFieldPtr + esize);\n  }\n\n  /* un' wech */\n  return ZE_OK;\n}\n\n#if 0\n/* Remove extra field in local extra field\n * Return 1 if found, else 0\n * 12/28/05\n */\nlocal int remove_local_extra_field(pZEntry, tag)\n  struct zlist far *pZEntry;\n  ulg tag;\n{\n  char  *pExtra;\n  char  *pOldExtra;\n  char  *pOldTemp;\n  char  *pTemp;\n  ush   newEFSize;\n  ush   usTemp;\n  ush   blocksize;\n\n  /* check if we have the extra field ... */\n  pOldExtra = get_extra_field( (ush)tag, pZEntry->extra, pZEntry->ext );\n  if (pOldExtra)\n  {\n    /* We have. Get rid of it. */\n    blocksize = SH( pOldExtra + 2 );\n    newEFSize = pZEntry->ext - blocksize;\n    pExtra = (char *) malloc( newEFSize );\n    if( pExtra == NULL )\n      ziperr(ZE_MEM, \"Remove Local Extra Field\");\n    /* move all before EF */\n    usTemp = (extent) (pOldExtra - pZEntry->extra);\n    pTemp = pExtra;\n    memcpy( pTemp, pZEntry->extra, usTemp );\n    /* move all after old Zip64 EF */\n    pTemp = pExtra + usTemp;\n    pOldTemp = pOldExtra + blocksize;\n    usTemp = pZEntry->ext - usTemp - blocksize;\n    memcpy( pTemp, pOldTemp, usTemp);\n    /* replace extra fields */\n    pZEntry->ext = newEFSize;\n    free(pZEntry->extra);\n    pZEntry->extra = pExtra;\n    return 1;\n  } else {\n    return 0;\n  }\n}\n\n/* Remove extra field in central extra field\n * Return 1 if found, else 0\n * 12/28/05\n */\nlocal int remove_central_extra_field(pZEntry, tag)\n  struct zlist far *pZEntry;\n  ulg tag;\n{\n  char  *pExtra;\n  char  *pOldExtra;\n  char  *pOldTemp;\n  char  *pTemp;\n  ush   newEFSize;\n  ush   usTemp;\n  ush   blocksize;\n\n  /* check if we have the extra field ... */\n  pOldExtra = get_extra_field( (ush)tag, pZEntry->cextra, pZEntry->cext );\n  if (pOldExtra)\n  {\n    /* We have. Get rid of it. */\n    blocksize = SH( pOldExtra + 2 );\n    newEFSize = pZEntry->cext - blocksize;\n    pExtra = (char *) malloc( newEFSize );\n    if( pExtra == NULL )\n      ziperr(ZE_MEM, \"Remove Local Extra Field\");\n    /* move all before EF */\n    usTemp = (extent) (pOldExtra - pZEntry->cextra);\n    pTemp = pExtra;\n    memcpy( pTemp, pZEntry->cextra, usTemp );\n    /* move all after old Zip64 EF */\n    pTemp = pExtra + usTemp;\n    pOldTemp = pOldExtra + blocksize;\n    usTemp = pZEntry->cext - usTemp - blocksize;\n    memcpy( pTemp, pOldTemp, usTemp);\n    /* replace extra fields */\n    pZEntry->cext = newEFSize;\n    free(pZEntry->cextra);\n    pZEntry->cextra = pExtra;\n    return 1;\n  } else {\n    return 0;\n  }\n}\n#endif\n\n/* Add Zip64 extra field to local header\n * 10/5/03 EG\n */\nlocal int add_local_zip64_extra_field(pZEntry)\n  struct zlist far *pZEntry;\n{\n  char  *pZ64Extra;\n  char  *pOldZ64Extra;\n  char  *pOldTemp;\n  char  *pTemp;\n  ush   newEFSize;\n  ush   usTemp;\n  ush   blocksize;\n  ush   Z64LocalLen = ZIP_EF_HEADER_SIZE +  /* tag + EF Data Len */\n                      8 +                   /* original uncompressed length of file */\n                      8;                    /* compressed size of file */\n\n  /* malloc zip64 extra field? */\n  /* after the below pZ64Extra should point to start of Zip64 extra field */\n  if (pZEntry->ext == 0 || pZEntry->extra == NULL)\n  {\n    /* get new extra field */\n    pZ64Extra = pZEntry->extra = (char *) malloc(Z64LocalLen);\n    if (pZEntry->extra == NULL) {\n      ziperr( ZE_MEM, \"Zip64 local extra field\" );\n    }\n    pZEntry->ext = Z64LocalLen;\n  }\n  else\n  {\n    /* check if we have a Zip64 extra field ... */\n    pOldZ64Extra = get_extra_field( ZIP64_EF_TAG, pZEntry->extra, pZEntry->ext );\n    if (pOldZ64Extra == NULL)\n    {\n      /* ... we don't, so re-malloc enough memory for the old extra data plus */\n      /* the size of the zip64 extra field */\n      pZ64Extra = (char *) malloc( Z64LocalLen + pZEntry->ext );\n      if (pZ64Extra == NULL)\n        ziperr( ZE_MEM, \"Zip64 Extra Field\" );\n      /* move old extra field and update pointer and length */\n      memmove( pZ64Extra, pZEntry->extra, pZEntry->ext);\n      free( pZEntry->extra );\n      pZEntry->extra = pZ64Extra;\n      pZ64Extra += pZEntry->ext;\n      pZEntry->ext += Z64LocalLen;\n    }\n    else\n    {\n      /* ... we have. Sort out the existing zip64 extra field and remove it\n       * from pZEntry->extra, re-malloc enough memory for the old extra data\n       * left plus the size of the zip64 extra field */\n      blocksize = SH( pOldZ64Extra + 2 );\n      /* If the right length then go with it, else get rid of it and add a new extra field\n       * to existing block. */\n      if (blocksize == Z64LocalLen - ZIP_EF_HEADER_SIZE)\n      {\n        /* looks good */\n        pZ64Extra = pOldZ64Extra;\n      }\n      else\n      {\n        newEFSize = pZEntry->ext - (blocksize + ZIP_EF_HEADER_SIZE) + Z64LocalLen;\n        pZ64Extra = (char *) malloc( newEFSize );\n        if( pZ64Extra == NULL )\n          ziperr(ZE_MEM, \"Zip64 Extra Field\");\n        /* move all before Zip64 EF */\n        usTemp = (extent) (pOldZ64Extra - pZEntry->extra);\n        pTemp = pZ64Extra;\n        memcpy( pTemp, pZEntry->extra, usTemp );\n        /* move all after old Zip64 EF */\n        pTemp = pZ64Extra + usTemp;\n        pOldTemp = pOldZ64Extra + ZIP_EF_HEADER_SIZE + blocksize;\n        usTemp = pZEntry->ext - usTemp - blocksize;\n        memcpy( pTemp, pOldTemp, usTemp);\n        /* replace extra fields */\n        pZEntry->ext = newEFSize;\n        free(pZEntry->extra);\n        pZEntry->extra = pZ64Extra;\n        pZ64Extra = pTemp + usTemp;\n      }\n    }\n  }\n  /* set/update zip64 extra field members */\n  write_ushort_to_mem(ZIP64_EF_TAG, pZ64Extra);\n  write_ushort_to_mem((ush) (Z64LocalLen - ZIP_EF_HEADER_SIZE), pZ64Extra + 2);\n  write_int64_to_mem(pZEntry->len, pZ64Extra + 2 + 2);\n  write_int64_to_mem(pZEntry->siz, pZ64Extra + 2 + 2 + 8);\n\n  return ZE_OK;\n}\n\n# endif /* ZIP64_SUPPORT */\n\n#ifdef UNICODE_SUPPORT\n/* Add UTF-8 path extra field\n * 10/11/05\n */\nlocal int add_Unicode_Path_local_extra_field(pZEntry)\n  struct zlist far *pZEntry;\n{\n  char  *pUExtra;\n  char  *pOldUExtra;\n  char  *pOldTemp;\n  char  *pTemp;\n#ifdef WIN32_OEM\n  char  *inameLocal;\n#endif\n  ush   newEFSize;\n  ush   usTemp;\n  ush   ULen = strlen(pZEntry->uname);\n  ush   blocksize;\n  ulg   chksum = CRCVAL_INITIAL;\n  ush   ULocalLen = ZIP_EF_HEADER_SIZE +  /* tag + EF Data Len */\n                    1 +                   /* version */\n                    4 +                   /* iname chksum */\n                    ULen;                 /* UTF-8 path */\n\n  /* malloc Unicode Path extra field? */\n  /* after the below pUExtra should point to start of Unicode Path extra field */\n  if (pZEntry->ext == 0 || pZEntry->extra == NULL)\n  {\n    /* get new extra field */\n    pUExtra = pZEntry->extra = (char *) malloc(ULocalLen);\n    if (pZEntry->extra == NULL) {\n      ziperr( ZE_MEM, \"UTF-8 Path local extra field\" );\n    }\n    pZEntry->ext = ULocalLen;\n  }\n  else\n  {\n    /* check if we have a Unicode Path extra field ... */\n    pOldUExtra = get_extra_field( UTF8_PATH_EF_TAG, pZEntry->extra, pZEntry->ext );\n    if (pOldUExtra == NULL)\n    {\n      /* ... we don't, so re-malloc enough memory for the old extra data plus */\n      /* the size of the UTF-8 Path extra field */\n      pUExtra = (char *) malloc( ULocalLen + pZEntry->ext );\n      if (pUExtra == NULL)\n        ziperr( ZE_MEM, \"UTF-8 Path Extra Field\" );\n      /* move old extra field and update pointer and length */\n      memmove( pUExtra, pZEntry->extra, pZEntry->ext);\n      free( pZEntry->extra );\n      pZEntry->extra = pUExtra;\n      pUExtra += pZEntry->ext;\n      pZEntry->ext += ULocalLen;\n    }\n    else\n    {\n      /* ... we have. Sort out the existing UTF-8 Path extra field and remove it\n       * from pZEntry->extra, re-malloc enough memory for the old extra data\n       * left plus the size of the UTF-8 Path extra field */\n      blocksize = SH( pOldUExtra + 2 );\n      /* If the right length then go with it, else get rid of it and add a new extra field\n       * to existing block. */\n      if (blocksize == ULocalLen - ZIP_EF_HEADER_SIZE)\n      {\n        /* looks good */\n        pUExtra = pOldUExtra;\n      }\n      else\n      {\n        newEFSize = pZEntry->ext - (blocksize + ZIP_EF_HEADER_SIZE) + ULocalLen;\n        pUExtra = (char *) malloc( newEFSize );\n        if( pUExtra == NULL )\n          ziperr(ZE_MEM, \"UTF-8 Path Extra Field\");\n        /* move all before UTF-8 Path EF */\n        usTemp = (extent) (pOldUExtra - pZEntry->extra);\n        pTemp = pUExtra;\n        memcpy( pTemp, pZEntry->extra, usTemp );\n        /* move all after old UTF-8 Path EF */\n        pTemp = pUExtra + usTemp;\n        pOldTemp = pOldUExtra + ZIP_EF_HEADER_SIZE + blocksize;\n        usTemp = pZEntry->ext - usTemp - blocksize;\n        memcpy( pTemp, pOldTemp, usTemp);\n        /* replace extra fields */\n        pZEntry->ext = newEFSize;\n        free(pZEntry->extra);\n        pZEntry->extra = pUExtra;\n        pUExtra = pTemp + usTemp;\n      }\n    }\n  }\n\n  /*\n   * Compute the Adler-16 checksum of iname\n   */\n/*\n  chksum = adler16(ADLERVAL_INITIAL,\n                   (uch *)(pZEntry->iname), strlen(pZEntry->iname));\n*/\n\n#ifdef WIN32_OEM\n  if ((inameLocal = malloc(strlen(pZEntry->iname) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"write Unicode\");\n  }\n  /* if oem translation done convert back for checksum */\n  if ((pZEntry->vem & 0xff00) == 0) {\n    /* get original */\n    INTERN_TO_OEM(pZEntry->iname, inameLocal);\n  } else {\n    strcpy(inameLocal, pZEntry->iname);\n  }\n#else\n# define inameLocal (pZEntry->iname)\n#endif\n\n  chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));\n\n#ifdef WIN32_OEM\n  free(inameLocal);\n#else\n# undef inameLocal\n#endif\n\n  /* set/update UTF-8 Path extra field members */\n  /* tag header */\n  write_ushort_to_mem(UTF8_PATH_EF_TAG, pUExtra);\n  /* data size */\n  write_ushort_to_mem((ush) (ULocalLen - ZIP_EF_HEADER_SIZE), pUExtra + 2);\n  /* version */\n  *(pUExtra + 2 + 2) = 1;\n  /* iname chksum */\n  write_ulong_to_mem(chksum, pUExtra + 2 + 2 + 1);\n  /* UTF-8 path */\n  write_string_to_mem(pZEntry->uname, pUExtra + 2 + 2 + 1 + 4);\n\n  return ZE_OK;\n}\n\nlocal int add_Unicode_Path_cen_extra_field(pZEntry)\n  struct zlist far *pZEntry;\n{\n  char  *pUExtra;\n  char  *pOldUExtra;\n  char  *pOldTemp;\n  char  *pTemp;\n#ifdef WIN32_OEM\n  char  *inameLocal;\n#endif\n  ush   newEFSize;\n  ush   usTemp;\n  ush   ULen = strlen(pZEntry->uname);\n  ush   blocksize;\n  ulg   chksum = CRCVAL_INITIAL;\n  ush   UCenLen = ZIP_EF_HEADER_SIZE +  /* tag + EF Data Len */\n                  1 +                   /* version */\n                  4 +                   /* checksum */\n                  ULen;                 /* UTF-8 path */\n\n  /* malloc Unicode Path extra field? */\n  /* after the below pUExtra should point to start of Unicode Path extra field */\n  if (pZEntry->cext == 0 || pZEntry->cextra == NULL)\n  {\n    /* get new extra field */\n    pUExtra = pZEntry->cextra = (char *) malloc(UCenLen);\n    if (pZEntry->cextra == NULL) {\n      ziperr( ZE_MEM, \"UTF-8 Path cen extra field\" );\n    }\n    pZEntry->cext = UCenLen;\n  }\n  else\n  {\n    /* check if we have a Unicode Path extra field ... */\n    pOldUExtra = get_extra_field( UTF8_PATH_EF_TAG, pZEntry->cextra, pZEntry->cext );\n    if (pOldUExtra == NULL)\n    {\n      /* ... we don't, so re-malloc enough memory for the old extra data plus */\n      /* the size of the UTF-8 Path extra field */\n      pUExtra = (char *) malloc( UCenLen + pZEntry->cext );\n      if (pUExtra == NULL)\n        ziperr( ZE_MEM, \"UTF-8 Path Extra Field\" );\n      /* move old extra field and update pointer and length */\n      memmove( pUExtra, pZEntry->cextra, pZEntry->cext);\n      free( pZEntry->cextra );\n      pZEntry->cextra = pUExtra;\n      pUExtra += pZEntry->cext;\n      pZEntry->cext += UCenLen;\n    }\n    else\n    {\n      /* ... we have. Sort out the existing UTF-8 Path extra field and remove it\n       * from pZEntry->extra, re-malloc enough memory for the old extra data\n       * left plus the size of the UTF-8 Path extra field */\n      blocksize = SH( pOldUExtra + 2 );\n      /* If the right length then go with it, else get rid of it and add a new extra field\n       * to existing block. */\n      if (blocksize == UCenLen - ZIP_EF_HEADER_SIZE)\n      {\n        /* looks good */\n        pUExtra = pOldUExtra;\n      }\n      else\n      {\n        newEFSize = pZEntry->cext - (blocksize + ZIP_EF_HEADER_SIZE) + UCenLen;\n        pUExtra = (char *) malloc( newEFSize );\n        if( pUExtra == NULL )\n          ziperr(ZE_MEM, \"UTF-8 Path Extra Field\");\n        /* move all before UTF-8 Path EF */\n        usTemp = (extent) (pOldUExtra - pZEntry->cextra);\n        pTemp = pUExtra;\n        memcpy( pTemp, pZEntry->cextra, usTemp );\n        /* move all after old UTF-8 Path EF */\n        pTemp = pUExtra + usTemp;\n        pOldTemp = pOldUExtra + ZIP_EF_HEADER_SIZE + blocksize;\n        usTemp = pZEntry->cext - usTemp - blocksize;\n        memcpy( pTemp, pOldTemp, usTemp);\n        /* replace extra fields */\n        pZEntry->cext = newEFSize;\n        free(pZEntry->cextra);\n        pZEntry->cextra = pUExtra;\n        pUExtra = pTemp + usTemp;\n      }\n    }\n  }\n\n  /*\n   * Compute the CRC-32 checksum of iname\n   */\n#ifdef WIN32_OEM\n  if ((inameLocal = malloc(strlen(pZEntry->iname) + 1)) == NULL) {\n    ZIPERR(ZE_MEM, \"write Unicode\");\n  }\n  /* if oem translation done convert back for checksum */\n  if ((pZEntry->vem & 0xff00) == 0) {\n    /* get original */\n    INTERN_TO_OEM(pZEntry->iname, inameLocal);\n  } else {\n    strcpy(inameLocal, pZEntry->iname);\n  }\n#else\n# define inameLocal (pZEntry->iname)\n#endif\n\n  chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));\n\n#ifdef WIN32_OEM\n  free(inameLocal);\n#else\n# undef inameLocal\n#endif\n\n  /*\n   * Compute the Adler-16 checksum of iname\n   */\n/*\n  chksum = adler16(ADLERVAL_INITIAL,\n                   (uch *)(pZEntry->iname), strlen(pZEntry->iname));\n*/\n\n  /* set/update UTF-8 Path extra field members */\n  /* tag header */\n  write_ushort_to_mem(UTF8_PATH_EF_TAG, pUExtra);\n  /* data size */\n  write_ushort_to_mem((ush) (UCenLen - ZIP_EF_HEADER_SIZE), pUExtra + 2);\n  /* version */\n  *(pUExtra + 2 + 2) = 1;\n  /* iname checksum */\n  write_ulong_to_mem(chksum, pUExtra + 2 + 2 + 1);\n  /* UTF-8 path */\n  write_string_to_mem(pZEntry->uname, pUExtra + 2 + 2 + 1 + 4);\n\n  return ZE_OK;\n}\n#endif /* def UNICODE_SUPPORT */\n\n\nzoff_t ffile_size OF((FILE *));\n\n\n/* 2004-12-06 SMS.\n * ffile_size() returns reliable file size or EOF.\n * May be used to detect large files in a small-file program.\n */\nzoff_t ffile_size( file)\nFILE *file;\n{\n  int sts;\n  size_t siz;\n  zoff_t ofs;\n  char waste[ 4];\n\n  /* Seek to actual EOF. */\n  sts = zfseeko( file, 0, SEEK_END);\n  if (sts != 0)\n  {\n    /* fseeko() failed.  (Unlikely.) */\n    ofs = EOF;\n  }\n  else\n  {\n    /* Get apparent offset at EOF. */\n    ofs = zftello( file);\n    if (ofs < 0)\n    {\n      /* Offset negative (overflow).  File too big. */\n      ofs = EOF;\n    }\n    else\n    {\n      /* Seek to apparent EOF offset.\n         Won't be at actual EOF if offset was truncated.\n      */\n      sts = zfseeko( file, ofs, SEEK_SET);\n      if (sts != 0)\n      {\n        /* fseeko() failed.  (Unlikely.) */\n        ofs = EOF;\n      }\n      else\n      {\n        /* Read a byte at apparent EOF.  Should set EOF flag. */\n        siz = fread( waste, 1, 1, file);\n        if (feof( file) == 0)\n        {\n          /* Not at EOF, but should be.  File too big. */\n          ofs = EOF;\n        }\n      }\n    }\n  }\n  /* Seek to BOF.\n   *\n   * 2007-05-23 SMS.\n   * Note that a problem in a prehistoric VAX C run-time library\n   * requires that rewind() be used instead of fseek(), or else\n   * the EOF flag is not cleared properly.\n   */\n  /* As WIN32 has this same problem (EOF not being cleared) when\n   * NO_ZIP64_SUPPORT is set but LARGE_FILE_SUPPORT is set on a\n   * small file, seems no reason not to always use rewind().\n   * 8/5/07 EG\n   */\n#if 0\n#ifdef VAXC\n  sts = rewind( file);\n#else /* def VAXC */\n  sts = zfseeko( file, 0, SEEK_SET);\n#endif /* def VAXC [else] */\n#endif\n  rewind(file);\n\n  return ofs;\n}\n\n\n#ifndef UTIL\n\nlocal void zipoddities(z)\nstruct zlist far *z;\n{\n    if ((z->vem >> 8) >= NUM_HOSTS)\n    {\n        sprintf(errbuf, \"made by version %d.%d on system type %d: \",\n                (ush)(z->vem & 0xff) / (ush)10, (ush)(z->vem & 0xff) % (ush)10,\n                z->vem >> 8);\n        zipwarn(errbuf, z->oname);\n    }\n    if (z->ver != 10 && z->ver != 11 && z->ver != 20)\n    {\n        sprintf(errbuf, \"needs unzip %d.%d on system type %d: \",\n                (ush)(z->ver & 0xff) / (ush)10,\n                (ush)(z->ver & 0xff) % (ush)10, z->ver >> 8);\n        zipwarn(errbuf, z->oname);\n    }\n\n    if ((fix == 2) && (z->flg != z->lflg))\n    /* The comparision between central and local version of the\n       \"general purpose bit flag\" cannot be used from scanzipf_regnew(),\n       because in the \"regular\" zipfile processing, the local header reads\n       have been postponed until the actual entry processing takes place.\n       They have not yet been read when \"zipoddities()\" is called.\n       This change was neccessary to support multivolume archives.\n     */\n    {\n        sprintf(errbuf, \"local flags = 0x%04x, central = 0x%04x: \",\n                z->lflg, z->flg);\n        zipwarn(errbuf, z->oname);\n    }\n    else if (z->flg & ~0xf && (z->flg & ~0xf0) != UTF8_BIT)\n    /* Only bit in high byte we support is the new UTF-8 bit */\n    {\n        sprintf(errbuf, \"undefined bits used in flags = 0x%04x: \", z->flg);\n        zipwarn(errbuf, z->oname);\n    }\n    if (z->how > LAST_KNOWN_COMPMETHOD)    {\n        sprintf(errbuf, \"unknown compression method %u: \", z->how);\n        zipwarn(errbuf, z->oname);\n    }\n    if (z->dsk)\n    {\n        sprintf(errbuf, \"starts on disk %lu: \", z->dsk);\n        zipwarn(errbuf, z->oname);\n    }\n    if (z->att!=ASCII && z->att!=BINARY && z->att!=__EBCDIC)\n    {\n        sprintf(errbuf, \"unknown internal attributes = 0x%04x: \", z->att);\n        zipwarn(errbuf, z->oname);\n    }\n# if 0\n/* This test is ridiculous, it produces an error message for almost every */\n/* platform of origin other than MS-DOS, Unix, VMS, and Acorn!  Perhaps   */\n/* we could test \"if (z->dosflag && z->atx & ~0xffL)\", but what for?      */\n    if (((n = z->vem >> 8) != 3) && n != 2 && n != 13 && z->atx & ~0xffL)\n    {\n        sprintf(errbuf, \"unknown external attributes = 0x%08lx: \", z->atx);\n        zipwarn(errbuf, z->oname);\n    }\n# endif\n\n    /* This test is just annoying, as Zip itself does not write the same\n       extra fields to both the local and central headers.  It's much more\n       complicated than this test implies.  3/17/05 */\n#if 0\n    if (z->ext || z->cext)\n    {\n# if 0\n        if (z->ext && z->cext && z->extra != z->cextra)\n        {\n          sprintf(errbuf,\n                  \"local extra (%ld bytes) != central extra (%ld bytes): \",\n                  (ulg)z->ext, (ulg)z->cext);\n          if (noisy) fprintf(mesg, \"\\tzip info: %s%s\\n\", errbuf, z->oname);\n        }\n#   if (!defined(RISCOS) && !defined(CMS_MVS))\n        /* in noisy mode, extra field sizes are always reported */\n        else if (noisy)\n#   else /* RISCOS || CMS_MVS */\n/* avoid warnings for zipfiles created on the same type of OS system! */\n/* or, was this warning really intended (eg. OS/2)? */\n        /* Only give info if extra bytes were added by another system */\n        else if (noisy && ((z->vem >> 8) != (OS_CODE >> 8)))\n#   endif /* ?(RISCOS || CMS_MVS) */\n# endif /* 0 */\n        {\n            fprintf(mesg, \"zip info: %s has %ld bytes of %sextra data\\n\",\n                    z->oname, z->ext ? (ulg)z->ext : (ulg)z->cext,\n                    z->ext ? (z->cext ? \"\" : \"local \") : \"central \");\n        }\n    }\n#endif\n}\n\n\n#if 0 /* scanzipf_fix() no longer used */\n/*\n * scanzipf_fix is called with zip -F or zip -FF\n * read the file from front to back and pick up the pieces\n * NOTE: there are still checks missing to see if the header\n *       that was found is *VALID*\n *\n * Still much work to do so can handle more cases.  1/18/04 EG\n */\nlocal int scanzipf_fix(f)\n  FILE *f;                      /* zip file */\n/*\n   The name of the zip file is pointed to by the global \"zipfile\".  The globals\n   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.\n   Return an error code in the ZE_ class.\n*/\n{\n    ulg a = 0L;                 /* attributes returned by filetime() */\n    char b[CENHEAD];            /* buffer for central headers */\n    ush flg;                    /* general purpose bit flag */\n    int m;                      /* mismatch flag */\n    extent n;                   /* length of name */\n    uzoff_t p;                  /* current file offset */\n    uzoff_t s;                  /* size of data, start of central */\n    struct zlist far * far *x;  /* pointer last entry's link */\n    struct zlist far *z;        /* current zip entry structure */\n\n#ifndef ZIP64_SUPPORT\n\n/* 2004-12-06 SMS.\n * Check for too-big file before doing any serious work.\n */\n    if (ffile_size( f) == EOF)\n      return ZE_ZIP64;\n\n#endif /* ndef ZIP64_SUPPORT */\n\n\n    /* Get any file attribute valid for this OS, to set in the central\n     * directory when fixing the archive:\n     */\n# ifndef UTIL\n    filetime(zipfile, &a, (zoff_t*)&s, NULL);\n# endif\n    x = &zfiles;                        /* first link */\n    p = 0;                              /* starting file offset */\n# ifdef HANDLE_AMIGA_SFX\n    amiga_sfx_offset = 0L;\n# endif\n\n    /* Find start of zip structures */\n    for (;;) {\n      /* look for signature */\n      while ((m = getc(f)) != EOF && m != 0x50)    /* 0x50 == 'P' */\n      {\n# ifdef HANDLE_AMIGA_SFX\n        if (p == 0 && m == 0)\n          amiga_sfx_offset = 1L;\n        else if (amiga_sfx_offset) {\n          if ((p == 1 && m != 0) || (p == 2 && m != 3)\n                                 || (p == 3 && (uch) m != 0xF3))\n            amiga_sfx_offset = 0L;\n        }\n# endif /* HANDLE_AMIGA_SFX */\n        p++;\n      }\n      /* found a P */\n      b[0] = (char) m;\n      /* local - 11/2/03 EG */\n      if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG)\n        break;\n      /* why search for ENDSIG if doing only local - 11/2/03 EG\n      if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == ENDSIG)\n        break;\n      */\n      /* back up */\n      if (zfseeko(f, -3L, SEEK_CUR))\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      /* move 1 byte forward */\n      p++;\n    }\n    zipbeg = p;\n# ifdef HANDLE_AMIGA_SFX\n    if (amiga_sfx_offset && zipbeg >= 12 && (zipbeg & 3) == 0\n        && fseek(f, -12L, SEEK_CUR) == 0 && fread(b, 12, 1, f) == 1\n        && LG(b + 4) == 0xF1030000 /* 1009 in Motorola byte order */)\n      amiga_sfx_offset = zipbeg - 4;\n    else\n      amiga_sfx_offset = 0L;\n# endif /* HANDLE_AMIGA_SFX */\n\n    /* Read local headers */\n    while (LG(b) == LOCSIG)\n    {\n      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL ||\n          zcount + 1 < zcount)\n        return ZE_MEM;\n      if (fread(b, LOCHEAD, 1, f) != 1) {\n          farfree((zvoid far *)z);\n          break;\n      }\n\n      z->ver = SH(LOCVER + b);\n      z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);\n      z->dosflag = dosify;\n      flg = z->flg = z->lflg = SH(LOCFLG + b);\n      z->how = SH(LOCHOW + b);\n      z->tim = LG(LOCTIM + b);          /* time and date into one long */\n      z->crc = LG(LOCCRC + b);\n      z->siz = LG(LOCSIZ + b);\n      z->len = LG(LOCLEN + b);\n      n = z->nam = SH(LOCNAM + b);\n      z->cext = z->ext = SH(LOCEXT + b);\n\n      z->com = 0;\n      z->dsk = 0;\n      z->att = 0;\n      z->atx = dosify ? a & 0xff : a;     /* Attributes from filetime() */\n      z->mark = 0;\n      z->trash = 0;\n\n      /* attention: this one breaks the VC optimizer (Release Build) */\n      /* may be fixed - 11/1/03 EG */\n      s = fix > 1 ? 0L : z->siz; /* discard compressed size with -FF */\n\n      /* Initialize all fields pointing to malloced data to NULL */\n      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;\n      z->oname = NULL;\n#ifdef UNICODE_SUPPORT\n      z->uname = z->zuname = z->ouname = NULL;\n#endif\n\n      /* Link into list */\n      *x = z;\n      z->nxt = NULL;\n      x = &z->nxt;\n\n      /* Read file name and extra field and skip data */\n      if (n == 0)\n      {\n        sprintf(errbuf, \"%lu\", (ulg)zcount + 1);\n        zipwarn(\"zero-length name for entry #\", errbuf);\n# ifndef DEBUG\n        return ZE_FORM;\n# endif\n      }\n      if ((z->iname = malloc(n+1)) ==  NULL ||\n          (z->ext && (z->extra = malloc(z->ext)) == NULL))\n        return ZE_MEM;\n      if (fread(z->iname, n, 1, f) != 1 ||\n          (z->ext && fread(z->extra, z->ext, 1, f) != 1))\n        return ferror(f) ? ZE_READ : ZE_EOF;\n\n#  ifdef ZIP64_SUPPORT\n      /* adjust/update siz,len and off (to come: dsk) entries */\n      /* PKZIP does not care of the version set in a CDH: if  */\n      /* there is a zip64 extra field assigned to a CDH PKZIP */\n      /* uses it, we should do so, too.                       */\n      zip64_entry = adjust_zip_local_entry(z);\n      /* z->siz may be updated */\n      s = fix > 1 ? 0L : z->siz; /* discard compressed size with -FF */\n#  endif\n\n      if (s && zfseeko(f, (zoff_t)s, SEEK_CUR))\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      /* If there is an extended local header, s is either 0 or\n       * the correct compressed size.\n       */\n      z->iname[n] = '\\0';               /* terminate name */\n      z->zname = in2ex(z->iname);       /* convert to external name */\n      if (z->zname == NULL)\n        return ZE_MEM;\n      z->name = z->zname;\n      z->cextra = z->extra;\n      if (noisy) fprintf(mesg, \"zip: reading %s\\n\", z->zname);\n\n      /* Save offset, update for next header */\n      z->off = p;\n      p += 4 + LOCHEAD + n + z->ext + s;\n      zcount++;\n\n      /* Skip extended local header if there is one */\n      if ((flg & 8) != 0) {\n        /* Skip the compressed data if compressed size is unknown.\n         * For safety, we should use the central directory.\n         */\n        if (s == 0) {\n          for (;;) {\n            while ((m = getc(f)) != EOF && m != 0x50) ;  /* 0x50 == 'P' */\n            b[0] = (char) m;\n            if (fread(b+1, 15, 1, f) != 1 || LG(b) == EXTLOCSIG)\n              break;\n            if (zfseeko(f, -15L, SEEK_CUR))\n              return ferror(f) ? ZE_READ : ZE_EOF;\n          }\n# ifdef ZIP64_SUPPORT\n          if (zip64_entry) {        /* from extra field */\n            /* all are 8 bytes */\n            s = LG(4 + ZIP64_EXTSIZ + b);\n          } else {\n            s = LG(4 + EXTSIZ + b);\n          }\n# else\n          s = LG(4 + EXTSIZ + b);\n# endif\n          p += s;\n          if ((uzoff_t) zftello(f) != p+16L) {\n            zipwarn(\"bad extended local header for \", z->zname);\n            return ZE_FORM;\n          }\n        } else {\n          /* compressed size non-zero, assume that it is valid: */\n          Assert(p == zftello(f), \"bad compressed size with extended header\");\n\n          if (zfseeko(f, p, SEEK_SET) || fread(b, 16, 1, f) != 1)\n            return ferror(f) ? ZE_READ : ZE_EOF;\n          if (LG(b) != EXTLOCSIG) {\n            zipwarn(\"extended local header not found for \", z->zname);\n            return ZE_FORM;\n          }\n        }\n        /* overwrite the unknown values of the local header: */\n\n        /* already in host format */\n# ifdef ZIP64_SUPPORT\n        z->crc = LG(4 + ZIP64_EXTCRC + b);\n        z->siz = s;\n        z->len = LG(4 + ZIP64_EXTLEN + b);\n# else\n        z->crc = LG(4 + EXTCRC + b);\n        z->siz = s;\n        z->len = LG(4 + EXTLEN + b);\n# endif\n\n        p += 16L;\n      }\n      else if (fix > 1) {\n        /* Don't trust the compressed size */\n        for (;;) {\n          while ((m = getc(f)) != EOF && m != 0x50) p++; /* 0x50 == 'P' */\n          b[0] = (char) m;\n          if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == CENSIG)\n            break;\n          if (zfseeko(f, -3L, SEEK_CUR))\n            return ferror(f) ? ZE_READ : ZE_EOF;\n          p++;\n        }\n        s = p - (z->off + 4 + LOCHEAD + n + z->ext);\n        if (s != z->siz) {\n          fprintf(mesg, \" compressed size %s, actual size %s for %s\\n\",\n                  zip_fzofft(z->siz, NULL, \"u\"), zip_fzofft(s, NULL, \"u\"),\n                  z->zname);\n          z->siz = s;\n        }\n        /* next LOCSIG already read at this point, don't read it again: */\n        continue;\n      }\n\n      /* Read next signature */\n      if (fread(b, 4, 1, f) != 1)\n          break;\n    }\n\n    s = p;                              /* save start of central */\n\n    if (LG(b) != CENSIG && noisy) {\n      fprintf(mesg, \"zip warning: %s %s truncated.\\n\", zipfile,\n              fix > 1 ? \"has been\" : \"would be\");\n\n      if (fix == 1) {\n        fprintf(mesg,\n   \"Retry with option -qF to truncate, with -FF to attempt full recovery\\n\");\n        ZIPERR(ZE_FORM, NULL);\n      }\n    }\n\n    cenbeg = s;\n\n    if (zipbeg && noisy)\n      fprintf(mesg, \"%s: adjusting offsets for a preamble of %s bytes\\n\",\n              zipfile, zip_fzofft(zipbeg, NULL, \"u\"));\n    return ZE_OK;\n} /* end of function scanzipf_fix() */\n#endif /* never, scanzipf_fix() no longer used */\n\n#endif /* !UTIL */\n\n/*\n * read_local\n *\n * Read the local header assumed at in_file file pointer.\n * localz is the returned local header, z is the central directory entry.\n *\n * This is used by crypt.c.\n *\n * Return ZE code\n */\nint readlocal(localz, z)\n  struct zlist far **localz;\n  struct zlist far *z;\n{\n  char buf[LOCHEAD + 1];\n  struct zlist far *locz;\n\n#ifndef UTIL\n  ulg start_disk = 0;\n  uzoff_t start_offset = 0;\n  char *split_path;\n\n  start_disk = z->dsk;\n  start_offset = z->off;\n\n  /* don't assume reading the right disk */\n\n  if (start_disk != current_in_disk) {\n    if (in_file) {\n      fclose(in_file);\n      in_file = NULL;\n    }\n  }\n\n  current_in_disk = start_disk;\n\n  /* disks are archive.z01, archive.z02, ..., archive.zip */\n  split_path = get_in_split_path(in_path, current_in_disk);\n\n  if (in_file == NULL) {\n    while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n      /* could not open split */\n\n      /* Ask for directory with split.  Updates in_path */\n      if (ask_for_split_read_path(start_disk) != ZE_OK) {\n        return ZE_ABORT;\n      }\n      free(split_path);\n      split_path = get_in_split_path(in_path, start_disk);\n    }\n  }\n#endif\n\n  /* For utilities assume archive is on one disk for now */\n\n  if (zfseeko(in_file, z->off, SEEK_SET) != 0) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"reading archive fseek: \", strerror(errno));\n    return ZE_READ;\n  }\n  if (!at_signature(in_file, \"PK\\03\\04\")) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"Did not find entry for \", z->iname);\n    return ZE_FORM;\n  }\n\n  /* read local header */\n  if (fread(buf, LOCHEAD, 1, in_file) != 1) {\n    int f = ferror(in_file);\n    zipwarn(\"reading local entry: \", strerror(errno));\n    fclose(in_file);\n    return f ? ZE_READ : ZE_EOF;\n  }\n\n  /* Local Header\n       local file header signature     4 bytes  (0x04034b50)\n       version needed to extract       2 bytes\n       general purpose bit flag        2 bytes\n       compression method              2 bytes\n       last mod file time              2 bytes\n       last mod file date              2 bytes\n       crc-32                          4 bytes\n       compressed size                 4 bytes\n       uncompressed size               4 bytes\n       file name length                2 bytes\n       extra field length              2 bytes\n\n       file name (variable size)\n       extra field (variable size)\n   */\n\n  if ((locz = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n    zipwarn(\"reading entry\", \"\");\n    fclose(in_file);\n    return ZE_MEM;\n  }\n\n  locz->ver = SH(LOCVER + buf);\n  locz->lflg = SH(LOCFLG + buf);\n  locz->how = SH(LOCHOW + buf);\n  locz->tim = LG(LOCTIM + buf);          /* time and date into one long */\n  locz->crc = LG(LOCCRC + buf);\n  locz->nam = SH(LOCNAM + buf);\n  locz->ext = SH(LOCEXT + buf);\n\n  /* Initialize all fields pointing to malloced data to NULL */\n  locz->zname = locz->name = locz->iname = locz->extra = NULL;\n  locz->oname = NULL;\n#ifdef UNICODE_SUPPORT\n  locz->uname = NULL;\n  locz->zuname = NULL;\n  locz->ouname = NULL;\n#endif\n\n  /* Read file name, extra field and comment field */\n  if ((locz->iname = malloc(locz->nam+1)) ==  NULL ||\n      (locz->ext && (locz->extra = malloc(locz->ext)) == NULL))\n    return ZE_MEM;\n  if (fread(locz->iname, locz->nam, 1, in_file) != 1 ||\n      (locz->ext && fread(locz->extra, locz->ext, 1, in_file) != 1))\n    return ferror(in_file) ? ZE_READ : ZE_EOF;\n  locz->iname[z->nam] = '\\0';                  /* terminate name */\n#ifdef UNICODE_SUPPORT\n  if (unicode_mismatch != 3)\n    read_Unicode_Path_local_entry(locz);\n#endif\n#ifdef WIN32\n  {\n    /* translate archive name from OEM if came from OEM-charset environment */\n    unsigned hostver = (z->vem & 0xff);\n    Ext_ASCII_TO_Native(locz->iname, (z->vem >> 8), hostver,\n                        ((z->atx & 0xffff0000L) != 0), TRUE);\n  }\n#endif\n  if ((locz->name = malloc(locz->nam+1)) ==  NULL)\n    return ZE_MEM;\n  strcpy(locz->name, locz->iname);\n\n#ifdef ZIP64_SUPPORT\n  zip64_entry = adjust_zip_local_entry(locz);\n#endif\n\n  /* Compare localz to z */\n  if (locz->ver != z->ver) {\n    sprintf(errbuf, \"Local Version Needed (%d) does not match CD (%d): \", locz->ver, z->ver);\n    zipwarn(errbuf, z->iname);\n  }\n  if (locz->lflg != z->flg) {\n    zipwarn(\"Local Entry Flag does not match CD: \", z->iname);\n  }\n  if (locz->crc != z->crc) {\n    zipwarn(\"Local Entry CRC does not match CD: \", z->iname);\n  }\n\n  /* as copying get uncompressed and compressed sizes from central directory */\n  locz->len = z->len;\n  locz->siz = z->siz;\n\n  *localz = locz;\n\n  return ZE_OK;\n} /* end function readlocal() */\n\n#if 0 /* following functions are not (no longer) used. */\n/*\n * scanzipf_reg starts searching for the End Signature at the end of the file\n * The End Signature points to the Central Directory Signature which points\n * to the Local Directory Signature\n * XXX probably some more consistency checks are needed\n */\nlocal int scanzipf_reg(f)\n  FILE *f;                      /* zip file */\n/*\n   The name of the zip file is pointed to by the global \"zipfile\".  The globals\n   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.\n   Return an error code in the ZE_ class.\n*/\n{\n    char b[CENHEAD];            /* buffer for central headers */\n    extent n;                   /* length of name */\n    struct zlist far * far *x;  /* pointer last entry's link */\n    struct zlist far *z;        /* current zip entry structure */\n    char *t;                    /* temporary pointer */\n    char far *u;                /* temporary variable */\n    int found;\n    char *buf;                  /* temp buffer for reading zipfile */\n# ifdef ZIP64_SUPPORT\n    ulg u4;                     /* unsigned 4 byte variable */\n    char bf[8];\n    uzoff_t u8;                 /* unsigned 8 byte variable */\n    uzoff_t censiz;             /* size of central directory */\n    uzoff_t z64eocd;            /* Zip64 End Of Central Directory record byte offset */\n# else\n    ush flg;                    /* general purpose bit flag */\n    int m;                      /* mismatch flag */\n# endif\n    zoff_t deltaoff = 0;\n\n\n#ifndef ZIP64_SUPPORT\n\n    /* 2004-12-06 SMS.\n     * Check for too-big file before doing any serious work.\n     */\n    if (ffile_size( f) == EOF)\n      return ZE_ZIP64;\n\n#endif /* ndef ZIP64_SUPPORT */\n\n\n    buf = malloc(4096 + 4);\n    if (buf == NULL)\n      return ZE_MEM;\n\n#ifdef HANDLE_AMIGA_SFX\n    amiga_sfx_offset = (fread(buf, 1, 4, f) == 4 && LG(buf) == 0xF3030000);\n    /* == 1 if this file is an Amiga executable (presumably UnZipSFX) */\n#endif\n    /* detect spanning signature */\n    zfseeko(f, 0, SEEK_SET);\n    read_split_archive = (fread(buf, 1, 4, f) == 4 && LG(buf) == 0x08074b50L);\n    found = 0;\n    t = &buf[4096];\n    t[1] = '\\0';\n    t[2] = '\\0';\n    t[3] = '\\0';\n    /* back up as much as 4k from end */\n    /* zip64 support 08/31/2003 R.Nausedat */\n    if (zfseeko(f, -4096L, SEEK_END) == 0) {\n      zipbeg = (uzoff_t) (zftello(f) + 4096L);\n      /* back up 4k blocks and look for End Of CD signature */\n      while (!found && zipbeg >= 4096) {\n        zipbeg -= 4096L;\n        buf[4096] = t[1];\n        buf[4097] = t[2];\n        buf[4098] = t[3];\n/*\n * XXX error check ??\n */\n        fread(buf, 1, 4096, f);\n        zfseeko(f, -8192L, SEEK_CUR);\n        t = &buf[4095];\n/*\n * XXX far pointer arithmetic in DOS\n */\n        while (t >= buf) {\n          /* Check for ENDSIG (\"PK\\5\\6\" in ASCII) */\n          if (LG(t) == ENDSIG) {\n            found = 1;\n/*\n * XXX error check ??\n * XXX far pointer arithmetic in DOS\n */\n            zipbeg += (uzoff_t) (t - buf);\n            zfseeko(f, (zoff_t) zipbeg + 4L, SEEK_SET);\n            break;\n          }\n          --t;\n        }\n      }\n    }\n    else\n      /* file less than 4k bytes */\n      zipbeg = 4096L;\n/*\n * XXX warn: garbage at the end of the file ignored\n */\n    if (!found && zipbeg > 0) {\n      size_t s;\n\n      zfseeko(f, 0L, SEEK_SET);\n      clearerr(f);\n      s = fread(buf, 1, (size_t) zipbeg, f);\n      /* add 0 bytes at end */\n      buf[s] = t[1];\n      buf[s + 1] = t[2];\n      buf[s + 2] = t[3];\n      t = &buf[s - 1];\n/*\n * XXX far pointer comparison in DOS\n */\n      while (t >= buf) {\n        /* Check for ENDSIG (\"PK\\5\\6\" in ASCII) */\n        if (LG(t) == ENDSIG) {\n          found = 1;\n/*\n * XXX far pointer arithmetic in DOS\n */\n          zipbeg = (ulg) (t - buf);\n          zfseeko(f, (zoff_t) zipbeg + 4L, SEEK_SET);\n          break;\n        }\n        --t;\n      }\n    }\n    free(buf);\n    if (!found) {\n      zipwarn(\"missing end signature--probably not a zip file (did you\", \"\");\n      zipwarn(\"remember to use binary mode when you transferred it?)\", \"\");\n      return ZE_FORM;\n    }\n\n/*\n * Check for a Zip64 EOCD Locator signature - 12/10/04 EG\n */\n#ifndef ZIP64_SUPPORT\n    /* If Zip64 not enabled check if archive being read is Zip64 */\n    /* back up 24 bytes (size of Z64 EOCDL and ENDSIG) */\n    if (zfseeko(f, -24, SEEK_CUR) != 0) {\n        perror(\"fseek\");\n        return ZE_FORM; /* XXX */\n    }\n    /* read Z64 EOCDL if there */\n    if (fread(b, 20, 1, f) != 1) {\n      return ZE_READ;\n    }\n    /* first 4 bytes are the signature if there */\n    if (LG(b) == ZIP64_EOCDL_SIG) {\n      zipwarn(\"found Zip64 signature - this may be a Zip64 archive\", \"\");\n      zipwarn(\"PKZIP 4.5 or later needed - set ZIP64_SUPPORT in Zip 3\", \"\");\n      return ZE_ZIP64;\n    }\n\n    /* now should be back at the EOCD signature */\n    if (fread(b, 4, 1, f) != 1) {\n      zipwarn(\"unable to read after relative seek\", \"\");\n      return ZE_READ;\n    }\n    if (LG(b) != ENDSIG) {\n      zipwarn(\"unable to relative seek in archive\", \"\");\n      return ZE_FORM;\n    }\n#if 0\n    if (fseek(f, -4, SEEK_CUR) != 0) {\n        perror(\"fseek\");\n        return ZE_FORM; /* XXX */\n    }\n#endif\n#endif\n\n    /* Read end header */\n    if (fread(b, ENDHEAD, 1, f) != 1)\n      return ferror(f) ? ZE_READ : ZE_EOF;\n    if (SH(ENDDSK + b) || SH(ENDBEG + b) ||\n        SH(ENDSUB + b) != SH(ENDTOT + b))\n      zipwarn(\"multiple disk information ignored\", \"\");\n    zcomlen = SH(ENDCOM + b);\n    if (zcomlen)\n    {\n      if ((zcomment = malloc(zcomlen)) == NULL)\n        return ZE_MEM;\n      if (fread(zcomment, zcomlen, 1, f) != 1)\n      {\n        free((zvoid *)zcomment);\n        zcomment = NULL;\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      }\n#ifdef EBCDIC\n      if (zcomment)\n         memtoebc(zcomment, zcomment, zcomlen);\n#endif /* EBCDIC */\n    }\n#ifdef ZIP64_SUPPORT\n    /* account for Zip64 EOCD Record and Zip64 EOCD Locator */\n\n    /* Z64 EOCDL should be just before EOCD (unless this is an empty archive) */\n    cenbeg = zipbeg - ZIP64_EOCDL_OFS_SIZE;\n    /* check for empty archive */\n    /* changed cenbeg to uzoff_t so instead of cenbeg >= 0 use new check - 5/23/05 EG */\n    if (zipbeg >= ZIP64_EOCDL_OFS_SIZE) {\n      /* look for signature */\n      if (zfseeko(f, cenbeg, SEEK_SET)) {\n        zipwarn(\"end of file seeking Z64EOCDL\", \"\");\n        return ZE_FORM;\n      }\n      if (fread(bf, 4, 1, f) != 1) {\n        ziperr(ZE_FORM, \"read error\");\n      }\n      u4 = LG(bf);\n      if (u4 == ZIP64_EOCDL_SIG) {\n        /* found Zip64 EOCD Locator */\n        /* check for disk information */\n        zfseeko(f, cenbeg + ZIP64_EOCDL_OFS_TOTALDISKS, SEEK_SET);\n        if (fread(bf, 4, 1, f) != 1) {\n          ziperr(ZE_FORM, \"read error\");\n        }\n        u4 = LG(bf);\n        if (u4 != 1) {\n          ziperr(ZE_FORM, \"multiple disk archives not yet supported\");\n        }\n\n        /* look for Zip64 EOCD Record */\n        zfseeko(f, cenbeg + ZIP64_EOCDL_OFS_EOCD_START, SEEK_SET);\n        if (fread(bf, 8, 1, f) != 1) {\n         ziperr(ZE_FORM, \"read error\");\n        }\n        z64eocd = LLG(bf);\n        if (zfseeko(f, z64eocd, SEEK_SET)) {\n          ziperr(ZE_FORM, \"error searching for Z64 EOCD Record\");\n        }\n        if (fread(bf, 4, 1, f) != 1) {\n         ziperr(ZE_FORM, \"read error\");\n        }\n        u4 = LG(bf);\n        if (u4 != ZIP64_EOCD_SIG) {\n          ziperr(ZE_FORM, \"Z64 EOCD not found but Z64 EOCD Locator exists\");\n        }\n        /* get size of CD */\n        zfseeko(f, z64eocd + ZIP64_EOCD_OFS_SIZE, SEEK_SET);\n        if (fread(bf, 8, 1, f) != 1) {\n         ziperr(ZE_FORM, \"read error\");\n        }\n        censiz = LLG(bf);\n        /* get start of CD */\n        zfseeko(f, z64eocd + ZIP64_EOCD_OFS_CD_START, SEEK_SET);\n        if (fread(bf, 8, 1, f) == (size_t) -1) {\n         ziperr(ZE_FORM, \"read error\");\n        }\n        cenbeg = LLG(bf);\n        u8 = z64eocd - cenbeg;\n        deltaoff = adjust ? u8 - censiz : 0L;\n      } else {\n        /* assume no Locator and no Zip64 EOCD Record */\n        censiz = LG(ENDSIZ + b);\n        cenbeg = LG(b + ENDOFF);\n        u8 = zipbeg - censiz;\n        deltaoff = adjust ? u8 - censiz : 0L;\n      }\n    }\n#else /* !ZIP64_SUPPORT */\n/*\n * XXX assumes central header immediately precedes end header\n */\n    /* start of central directory */\n    cenbeg = zipbeg - LG(ENDSIZ + b);\n/*\nprintf(\"start of central directory cenbeg %ld\\n\", cenbeg);\n*/\n\n    /* offset to first entry of archive */\n    deltaoff = adjust ? cenbeg - LG(b + ENDOFF) : 0L;\n#endif /* ?ZIP64_SUPPORT */\n\n    if (zipbeg < ZIP64_EOCDL_OFS_SIZE) {\n      /* zip file seems empty */\n      return ZE_OK;\n    }\n\n    if (zfseeko(f, cenbeg, SEEK_SET) != 0) {\n        perror(\"fseek\");\n        return ZE_FORM; /* XXX */\n    }\n\n    x = &zfiles;                        /* first link */\n\n    if (fread(b, 4, 1, f) != 1)\n      return ferror(f) ? ZE_READ : ZE_EOF;\n\n    while (LG(b) == CENSIG) {\n      /* Read central header. The portion of the central header that should\n         be in common with local header is read raw, for later comparison.\n         (this requires that the offset of ext in the zlist structure\n         be greater than or equal to LOCHEAD) */\n      if (fread(b, CENHEAD, 1, f) != 1)\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)\n        return ZE_MEM;\n      z->vem = SH(CENVEM + b);\n      for (u = (char far *)(&(z->ver)), n = 0; n < (CENNAM-CENVER); n++)\n        u[n] = b[CENVER + n];\n      z->nam = SH(CENNAM + b);          /* used before comparing cen vs. loc */\n      z->cext = SH(CENEXT + b);         /* may be different from z->ext */\n      z->com = SH(CENCOM + b);\n      z->dsk = SH(CENDSK + b);\n      z->att = SH(CENATT + b);\n      z->atx = LG(CENATX + b);\n      z->off = LG(CENOFF + b) + deltaoff;\n      z->dosflag = (z->vem & 0xff00) == 0;\n\n      /* Initialize all fields pointing to malloced data to NULL */\n      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;\n      z->oname = NULL;\n#ifdef UNICODE_SUPPORT\n      z->uname = NULL;      /* UTF-8 path */\n      z->zuname = NULL;     /* Escaped local version of uname */\n      z->ouname = NULL;     /* Display version of zuname */\n#endif\n\n      /* Link into list */\n      *x = z;\n      z->nxt = NULL;\n      x = &z->nxt;\n\n      /* Read file name, extra field and comment field */\n      if (z->nam == 0)\n      {\n        sprintf(errbuf, \"%lu\", (ulg)zcount + 1);\n        zipwarn(\"zero-length name for entry #\", errbuf);\n#ifndef DEBUG\n        farfree((zvoid far *)z);\n        return ZE_FORM;\n#endif\n      }\n      if ((z->iname = malloc(z->nam+1)) ==  NULL ||\n          (z->cext && (z->cextra = malloc(z->cext)) == NULL) ||\n          (z->com && (z->comment = malloc(z->com)) == NULL))\n        return ZE_MEM;\n      if (fread(z->iname, z->nam, 1, f) != 1 ||\n          (z->cext && fread(z->cextra, z->cext, 1, f) != 1) ||\n          (z->com && fread(z->comment, z->com, 1, f) != 1))\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      z->iname[z->nam] = '\\0';                  /* terminate name */\n\n#ifdef EBCDIC\n      if (z->com)\n         memtoebc(z->comment, z->comment, z->com);\n#endif /* EBCDIC */\n\n#ifdef ZIP64_SUPPORT\n      /* zip64 support 08/31/2003 R.Nausedat                          */\n      /* here, we have to read the len, siz etc values from the CD    */\n      /* entry as we might have to adjust them regarding their        */\n      /* correspronding zip64 extra fields.                           */\n      /* also, we cannot compare the values from the CD entries with  */\n      /* the values from the LH as they might be different.           */\n      z->len = LG(CENLEN + b);\n      z->siz = LG(CENSIZ + b);\n      z->crc = LG(CENCRC + b);\n      z->tim = LG(CENTIM + b);   /* time and date into one long */\n      z->how = SH(CENHOW + b);\n      z->flg = SH(CENFLG + b);\n      z->ver = SH(CENVER + b);\n      /* adjust/update siz,len and off (to come: dsk) entries */\n      /* PKZIP does not care of the version set in a CDH: if  */\n      /* there is a zip64 extra field assigned to a CDH PKZIP */\n      /* uses it, we should do so, too.                       */\n      adjust_zip_central_entry(z);\n#endif /* ZIP64_SUPPORT */\n\n      /* Update zipbeg offset, prepare for next header */\n      if (z->off < zipbeg)\n         zipbeg = z->off;\n      zcount++;\n      /* Read next signature */\n      if (fread(b, 4, 1, f) != 1)\n          return ferror(f) ? ZE_READ : ZE_EOF;\n    }\n\n    /* Point to start of header list and read local headers */\n    z = zfiles;\n    while (z != NULL) {\n      /* Read next signature */\n      if (zfseeko(f, z->off, SEEK_SET) != 0 || fread(b, 4, 1, f) != 1)\n        return ferror(f) ? ZE_READ : ZE_EOF;\n      if (LG(b) == LOCSIG) {\n        if (fread(b, LOCHEAD, 1, f) != 1)\n            return ferror(f) ? ZE_READ : ZE_EOF;\n\n        z->lflg = SH(LOCFLG + b);\n        n = SH(LOCNAM + b);\n        z->ext = SH(LOCEXT + b);\n\n        /* Compare name and extra fields */\n        if (n != z->nam)\n        {\n#ifdef EBCDIC\n          strtoebc(z->iname, z->iname);\n#endif\n          zipwarn(\"name lengths in local and central differ for \", z->iname);\n          return ZE_FORM;\n        }\n        if ((t = malloc(z->nam)) == NULL)\n          return ZE_MEM;\n        if (fread(t, z->nam, 1, f) != 1)\n        {\n          free((zvoid *)t);\n          return ferror(f) ? ZE_READ : ZE_EOF;\n        }\n        if (memcmp(t, z->iname, z->nam))\n        {\n          free((zvoid *)t);\n#ifdef EBCDIC\n          strtoebc(z->iname, z->iname);\n#endif\n          zipwarn(\"names in local and central differ for \", z->iname);\n          return ZE_FORM;\n        }\n        free((zvoid *)t);\n        if (z->ext)\n        {\n          if ((z->extra = malloc(z->ext)) == NULL)\n            return ZE_MEM;\n          if (fread(z->extra, z->ext, 1, f) != 1)\n          {\n            free((zvoid *)(z->extra));\n            return ferror(f) ? ZE_READ : ZE_EOF;\n          }\n          if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)\n          {\n            free((zvoid *)(z->extra));\n            z->extra = z->cextra;\n          }\n        }\n\n#ifdef ZIP64_SUPPORT       /* zip64 support 09/02/2003 R.Nausedat */\n        /*\n        for now the below is left out if ZIP64_SUPPORT is defined as the fields\n        len, siz and off in struct zlist are type of int64 if ZIP64_SUPPORT\n        is defined. In either way, the values read from the central directory\n        should be valid. comments are welcome\n        */\n#else /* !ZIP64_SUPPORT */\n        /* Check extended local header if there is one */\n        /* bit 3 */\n        if ((z->lflg & 8) != 0)\n        {\n          char buf2[16];\n          ulg s;                        /* size of compressed data */\n\n          s = LG(LOCSIZ + b);\n          if (s == 0)\n            s = LG((CENSIZ-CENVER) + (char far *)(&(z->ver)));\n          if (zfseeko(f, (z->off + (4+LOCHEAD) + z->nam + z->ext + s), SEEK_SET)\n              || (fread(buf2, 16, 1, f) != 1))\n            return ferror(f) ? ZE_READ : ZE_EOF;\n          if (LG(buf2) != EXTLOCSIG)\n          {\n# ifdef EBCDIC\n            strtoebc(z->iname, z->iname);\n# endif\n            zipwarn(\"extended local header not found for \", z->iname);\n            return ZE_FORM;\n          }\n          /* overwrite the unknown values of the local header: */\n          for (n = 0; n < 12; n++)\n            b[LOCCRC+n] = buf2[4+n];\n        }\n\n        /* Compare local header with that part of central header (except\n           for the reserved bits in the general purpose flags and except\n           for the already checked entry name length */\n        /* If I have read this right we are stepping through the z struct\n           here as a byte array.  Need to fix this.  5/25/2005 EG */\n        u = (char far *)(&(z->ver));\n        flg = SH((CENFLG-CENVER) + u);          /* Save central flags word */\n        u[CENFLG-CENVER+1] &= 0x1f;             /* Mask reserved flag bits */\n        b[LOCFLG+1] &= 0x1f;\n        for (m = 0, n = 0; n < LOCNAM; n++) {\n          if (b[n] != u[n])\n          {\n            if (!m)\n            {\n              zipwarn(\"local and central headers differ for \", z->iname);\n              m = 1;\n            }\n            if (noisy)\n            {\n              sprintf(errbuf, \" offset %u--local = %02x, central = %02x\",\n                      (unsigned)n, (uch)b[n], (uch)u[n]);\n              zipwarn(errbuf, \"\");\n            }\n          }\n        }\n        if (m && !adjust)\n          return ZE_FORM;\n\n        /* Complete the setup of the zlist entry by translating the remaining\n         * central header fields in memory, starting with the fields with\n         * highest offset. This order of the conversion commands takes into\n         * account potential buffer overlaps caused by structure padding.\n         */\n        z->len = LG((CENLEN-CENVER) + u);\n        z->siz = LG((CENSIZ-CENVER) + u);\n        z->crc = LG((CENCRC-CENVER) + u);\n        z->tim = LG((CENTIM-CENVER) + u);   /* time and date into one long */\n        z->how = SH((CENHOW-CENVER) + u);\n        z->flg = flg;                       /* may be different from z->lflg */\n        z->ver = SH((CENVER-CENVER) + u);\n#endif /* ?ZIP64_SUPPORT */\n\n        /* Clear actions */\n        z->mark = 0;\n        z->trash = 0;\n#ifdef UNICODE_SUPPORT\n        if (unicode_mismatch != 3) {\n          read_Unicode_Path_entry(z);\n          if (z->uname) {\n            /* match based on converted Unicode name */\n            z->name = utf8_to_local_string(z->uname);\n# ifdef EBCDIC\n            /* z->zname is used for printing and must be coded in native charset */\n            strtoebc(z->zname, z->name);\n# else\n            if ((z->zname = malloc(strlen(z->name) + 1)) == NULL) {\n              ZIPERR(ZE_MEM, \"scanzipf_reg\");\n            }\n            strcpy(z->zname, z->name);\n# endif\n            z->oname = local_to_display_string(z->zname);\n          } else {\n            /* no UTF-8 path */\n            if ((z->name = malloc(strlen(z->iname) + 1)) == NULL) {\n              ZIPERR(ZE_MEM, \"scanzipf_reg\");\n            }\n            strcpy(z->name, z->iname);\n            if ((z->zname = malloc(strlen(z->iname) + 1)) == NULL) {\n              ZIPERR(ZE_MEM, \"scanzipf_reg\");\n            }\n            strcpy(z->zname, z->iname);\n            z->oname = local_to_display_string(z->iname);\n          }\n        }\n#else /* !UNICODE_SUPPORT */\n# ifdef UTIL\n/* We only need z->iname in the utils */\n        z->name = z->iname;\n#  ifdef EBCDIC\n/* z->zname is used for printing and must be coded in native charset */\n        if ((z->zname = malloc(z->nam+1)) ==  NULL)\n          return ZE_MEM;\n        strtoebc(z->zname, z->iname);\n#  else\n        z->zname = z->iname;\n#  endif\n# else /* !UTIL */\n        z->zname = in2ex(z->iname);       /* convert to external name */\n        if (z->zname == NULL)\n          return ZE_MEM;\n        z->name = z->zname;\n# endif /* ?UTIL */\n        if ((z->oname = malloc(strlen(z->zname) + 1)) == NULL) {\n          ZIPERR(ZE_MEM, \"scanzipf_reg\");\n        }\n        strcpy(z->oname, z->zname);\n#endif /* ?UNICODE_SUPPORT */\n      }\n      else {\n#ifdef EBCDIC\n        strtoebc(z->iname, z->iname);\n#endif\n        zipwarn(\"local header not found for \", z->iname);\n        return ZE_FORM;\n      }\n#ifndef UTIL\n      if (verbose && fix == 0)\n        zipoddities(z);\n#endif\n      z = z->nxt;\n    }\n\n    if (zipbeg && noisy)\n      fprintf(mesg, \"%s: %s a preamble of %s bytes\\n\",\n              zipfile, adjust ? \"adjusting offsets for\" : \"found\",\n              zip_fzofft(zipbeg, NULL, \"u\"));\n#ifdef HANDLE_AMIGA_SFX\n    if (zipbeg < 12 || (zipbeg & 3) != 0 /* must be longword aligned */)\n      amiga_sfx_offset = 0;\n    else if (amiga_sfx_offset) {\n      char buf2[16];\n      if (!fseek(f, zipbeg - 12, SEEK_SET) && fread(buf2, 12, 1, f) == 1) {\n        if (LG(buf2 + 4) == 0xF1030000 /* 1009 in Motorola byte order */)\n          /* could also check if LG(buf2) == 0xF2030000... no for now */\n          amiga_sfx_offset = zipbeg - 4;\n        else\n          amiga_sfx_offset = 0L;\n      }\n    }\n#endif /* HANDLE_AMIGA_SFX */\n    return ZE_OK;\n} /* end of function scanzipf_reg() */\n#endif /* never */\n\n\n\n\n/* find_next_signature\n *\n * Scan the file forward and look for the next PK signature.\n *\n * Return 1 if find one and leave file pointer pointing to next char\n * after signature and set sigbuf to signature.\n *\n * Return 0 if not.  Will be at EOF on return unless error.\n *\n */\n\nlocal char sigbuf[4];   /* signature found */\n\n#if 0 /* currently unused */\n/* copy signature */\nchar *copy_sig(copyto, copyfrom)\n  char *copyto;\n  char *copyfrom;\n{\n  int i;\n\n  for (i = 0; i < 4; i++) {\n    copyto[i] = copyfrom[i];\n  }\n  return copyto;\n}\n#endif /* currently unused */\n\n\nlocal int find_next_signature(f)\n  FILE *f;\n{\n  int m;\n  /*\n  zoff_t here;\n  */\n\n  /* look for P K ? ? signature */\n\n  m = getc(f);\n\n  /*\n  here = zftello(f);\n  */\n\n  while (m != EOF)\n  {\n    if (m == 0x50 /*'P' except EBCDIC*/) {\n      /* found a P */\n      sigbuf[0] = (char) m;\n\n      if ((m = getc(f)) == EOF)\n        break;\n      if (m != 0x4b /*'K' except EBCDIC*/) {\n        /* not a signature */\n        ungetc(m, f);\n      } else {\n        /* found P K */\n        sigbuf[1] = (char) m;\n\n        if ((m = getc(f)) == EOF)\n          break;\n        if (m == 0x50 /*'P' except EBCDIC*/) {\n          /* not a signature but maybe start of new one */\n          ungetc(m, f);\n          continue;\n        } else if (m >= 16) {\n          /* last 2 chars expect < 16 for signature */\n          continue;\n        }\n        sigbuf[2] = (char) m;\n\n        if ((m = getc(f)) == EOF)\n          break;\n        if (m == 0x50 /*'P' except EBCDIC*/) {\n          /* not a signature but maybe start of new one */\n          ungetc(m, f);\n          continue;\n        } else if (m >= 16) {\n          /* last 2 chars expect < 16 */\n          continue;\n        }\n        sigbuf[3] = (char) m;\n\n        /* found possible signature */\n        return 1;\n      }\n    }\n    m = getc(f);\n  }\n  if (ferror(f)) {\n    return 0;\n  }\n\n  /* found nothing */\n  return 0;\n}\n\n/* find_signature\n *\n * Find signature.\n *\n * Return 1 if found and leave file pointing to next character\n * after signature.  Set sigbuf with signature.\n *\n * Return 0 if not found.\n */\n\nlocal int find_signature(f, signature)\n  FILE *f;\n  ZCONST char *signature;\n{\n  int i;\n  char sig[4];\n  /*\n  zoff_t here = zftello(f);\n  */\n\n  for (i = 0; i < 4; i++)\n    sig[i] = signature[i];\n\n  /* for EBCDIC */\n  if (sig[0] == 'P')\n    sig[0] = 0x50;\n  if (sig[1] == 'K')\n    sig[1] = 0x4b;\n\n  while (!feof(f)) {\n    if (!find_next_signature(f)) {\n      return 0;\n    } else {\n      for (i = 0; i < 4; i++) {\n        if (sig[i] != sigbuf[i]) {\n          /* not a match */\n          break;\n        }\n      }\n      if (i == 4) {\n        /* found it */\n        return 1;\n      }\n    }\n  }\n  return 0;\n}\n\n\n/* is_signature\n *\n * Compare signatures\n *\n * Return 1 if the signatures match.\n */\n\nlocal int is_signature(sig1, sig2)\n  ZCONST char *sig1;\n  ZCONST char *sig2;\n{\n  int i;\n  char tsig1[4];\n  char tsig2[4];\n\n  for (i = 0; i < 4; i++) {\n    tsig1[i] = sig1[i];\n    tsig2[i] = sig2[i];\n  }\n\n  /* for EBCDIC */\n  if (tsig1[0] == 'P')\n    tsig1[0] = 0x50;\n  if (tsig1[1] == 'K')\n    tsig1[1] = 0x4b;\n\n  if (tsig2[0] == 'P')\n    tsig2[0] = 0x50;\n  if (tsig2[1] == 'K')\n    tsig2[1] = 0x4b;\n\n  for (i = 0; i < 4; i++) {\n    if (tsig1[i] != tsig2[i]) {\n      /* not a match */\n      break;\n    }\n  }\n  if (i == 4) {\n    /* found it */\n    return 1;\n  }\n  return 0;\n}\n\n\n/* at_signature\n *\n * Is at signature in file\n *\n * Return 1 if at the signature and leave file pointing to next character\n * after signature.\n *\n * Return 0 if not.\n */\n\nlocal int at_signature(f, signature)\n  FILE *f;\n  ZCONST char *signature;\n{\n  int i;\n  extent m;\n  char sig[4];\n  char b[4];\n\n  for (i = 0; i < 4; i++)\n    sig[i] = signature[i];\n\n  /* for EBCDIC */\n  if (sig[0] == 'P')\n    sig[0] = 0x50;\n  if (sig[1] == 'K')\n    sig[1] = 0x4b;\n\n  m = fread(b, 1, 4, f);\n  if (m != 4) {\n    return 0;\n  } else {\n    for (i = 0; i < 4; i++) {\n      if (sig[i] != b[i]) {\n        /* not a match */\n        break;\n      }\n    }\n    if (i == 4) {\n      /* found it */\n      return 1;\n    }\n  }\n  return 0;\n}\n\n\n#ifndef UTIL\n\nlocal int scanzipf_fixnew()\n/*\n   Scan an assumed broke archive from the beginning, salvaging what can.\n\n   Generally scanzipf_regnew() is used for reading archives normally and\n   for fixing archives with a readable central directory using -F.  This\n   scan is used by -FF and is for an archive that is unreadable by\n   scanzipf_regnew().\n\n   Start with the first file of the archive, either .z01 or .zip, and\n   look for local entries.  Read local entries found and create zlist\n   entries for them.  If we find central directory entries, read them\n   and update the zlist created while reading local entries.\n\n   The input path for the .zip file is in in_path.  If this is a multiple disk\n   archive get the paths for splits from in_path as we go.  If a split is not in\n   the same directory as the last split we ask the user where it is and update\n   in_path.\n */\n/*\n   This is old:\n\n   The name of the zip file is pointed to by the global \"zipfile\".  The globals\n   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.\n   Return an error code in the ZE_ class.\n*/\n{\n  /* This function only reads the standard End-of-CentralDir record and the\n     standard CentralDir-Entry records directly.  To conserve stack space,\n     only a buffer of minimal size is declared.\n   */\n# if CENHEAD > ENDHEAD\n#   define FIXSCAN_BUFSIZE  CENHEAD\n# else\n#   define FIXSCAN_BUFSIZE  ENDHEAD\n# endif\n\n  char    scbuf[FIXSCAN_BUFSIZE];  /* buffer big enough for headers */\n  char   *split_path;\n  ulg     eocdr_disk;\n  uzoff_t eocdr_offset;\n\n  uzoff_t current_offset = 0; /* offset before */\n  uzoff_t offset = 0;         /* location after return from seek */\n\n  int skip_disk = 0;          /* 1 if user asks to skip current disk */\n  int skipped_disk = 0;       /* 1 if skipped start disk and start offset is useless */\n\n  int r = 0;                  /* zipcopy return */\n  uzoff_t s;                  /* size of data, start of central */\n  struct zlist far * far *x;  /* pointer last entry's link */\n  struct zlist far *z;        /* current zip entry structure */\n  int plen;\n  char *in_path_ext;\n  int in_central_directory = 0; /* found a central directory record */\n  struct zlist far *cz;\n  uzoff_t cd_total_entries = 0; /* number of entries according to EOCDR */\n  ulg     in_cd_start_disk;     /* central directory start disk */\n  uzoff_t in_cd_start_offset;   /* offset of start of cd on cd start disk */\n\n\n  total_disks = 1000000;\n\n  /* open the zipfile */\n  /* This must be .zip file, even if it doesn't exist */\n\n  /* see if zipfile name ends in .zip */\n  plen = strlen(in_path);\n\n#ifdef VMS\n  /* On VMS, adjust plen (and in_path_ext) to avoid the file version. */\n  plen -= strlen(vms_file_version(in_path));\n#endif /* def VMS */\n  in_path_ext = zipfile + plen - 4;\n\n  if (plen >= 4 &&\n      in_path_ext[0] == '.' &&\n      toupper(in_path_ext[1]) == 'Z' &&\n      in_path_ext[2] >= '0' && in_path_ext[2] <= '9' &&\n      in_path_ext[3] >= '0' && in_path_ext[3] <= '9' &&\n      (plen == 4 || (in_path_ext[4] >= '0' && in_path_ext[4] <= '9'))) {\n    /* This may be a split but not the end split */\n    strcpy(errbuf, \"if archive to fix is split archive, need to provide\\n\");\n    strcat(errbuf, \"      path of the last split with .zip extension,\\n\");\n    strcat(errbuf, \"      even if it doesn't exist (zip will ask for splits)\");\n    zipwarn(errbuf, \"\");\n    return ZE_FORM;\n  }\n\n  if ((in_file = zfopen(in_path, FOPR)) == NULL) {\n    zipwarn(\"could not open input archive: \", in_path);\n  }\n  else\n  {\n\n#ifndef ZIP64_SUPPORT\n    /* 2004-12-06 SMS.\n     * Check for too-big file before doing any serious work.\n     */\n    if (ffile_size( in_file) == EOF) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"input file requires Zip64 support: \", in_path);\n      return ZE_ZIP64;\n    }\n#endif /* ndef ZIP64_SUPPORT */\n\n    /* look for End Of Central Directory Record */\n\n    /* back up 64k (the max size of the EOCDR) from end */\n    if (zfseeko(in_file, -0x40000L, SEEK_END) != 0) {\n      /* assume file is less than 64 KB so backup to beginning */\n      if (zfseeko(in_file, 0L, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        zipwarn(\"unable to seek in input file \", in_path);\n        return ZE_READ;\n      }\n    }\n\n\n    /* find EOCD Record signature */\n    if (!find_signature(in_file, \"PK\\05\\06\")) {\n      /* No End Of Central Directory Record */\n      strcpy(errbuf, \"Missing end (EOCDR) signature - either this archive\\n\");\n      strcat(errbuf, \"                     is not readable or the end is damaged\");\n      zipwarn(errbuf, \"\");\n    }\n    else\n    {\n      /* at start of data after EOCDR signature */\n      eocdr_offset = (uzoff_t) zftello(in_file);\n\n      /* OK, it is possible this is not the last EOCDR signature (might be\n         EOCDR signature from a stored archive in the last 64 KB) and so not\n         the one we want.\n\n         The below assumes the signature does not appear in the assumed\n         ASCII text .ZIP file comment.  Even if something like UTF-8\n         is stored in the comment, it's unlikely the binary \\05 and \\06\n         will be in the comment text.\n      */\n      while (find_signature(in_file, \"PK\\05\\06\")) {\n        eocdr_offset = (uzoff_t) zftello(in_file);\n      }\n\n      /* found EOCDR */\n      /* format is\n           end of central dir signature     4 bytes  (0x06054b50)\n           number of this disk              2 bytes\n           number of the disk with the\n            start of the central directory  2 bytes\n           total number of entries in the\n            central directory on this disk  2 bytes\n           total number of entries in\n            the central directory           2 bytes\n           size of the central directory    4 bytes\n           offset of start of central\n            directory with respect to\n            the starting disk number        4 bytes\n           .ZIP file comment length         2 bytes\n           .ZIP file comment        (variable size)\n       */\n\n      if (zfseeko(in_file, eocdr_offset, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        zipwarn(\"unable to seek in input file \", in_path);\n        return ZE_READ;\n      }\n\n      /* read the EOCDR */\n      s = fread(scbuf, 1, ENDHEAD, in_file);\n\n      /* make sure we read enough bytes */\n      if (s < ENDHEAD) {\n        sprintf(errbuf, \"End record (EOCDR) only %s bytes - assume truncated\",\n                  zip_fzofft(s, NULL, \"u\"));\n        zipwarn(errbuf, \"\");\n      }\n      else\n      {\n        /* the first field should be number of this (the last) disk */\n        eocdr_disk = (ulg)SH(scbuf);\n        total_disks = eocdr_disk + 1;\n\n        /* assume this is this disk - if Zip64 it may not be as the\n           disk number may be bigger than this field can hold\n        */\n        current_in_disk = total_disks - 1;\n\n        /* Central Directory disk, offset, and total entries */\n        in_cd_start_disk = (ulg)SH(scbuf + 2);\n        in_cd_start_offset = (uzoff_t)LG(scbuf + 12);\n        cd_total_entries = (uzoff_t)SH(scbuf + 6);\n\n        /* the in_cd_start_disk should always be less than the total_disks,\n           unless the -1 flags are being used */\n        if (total_disks < 0x10000 && in_cd_start_disk > total_disks) {\n          zipwarn(\"End record (EOCDR) has bad disk numbers - ignoring EOCDR\", \"\");\n          total_disks = 0;\n        }\n        else\n        {\n          /* length of zipfile comment */\n          zcomlen = SH(scbuf + ENDCOM);\n          if (zcomlen)\n          {\n            if ((zcomment = malloc(zcomlen + 1)) == NULL)\n              return ZE_MEM;\n            if (fread(zcomment, zcomlen, 1, in_file) != 1)\n            {\n              free((zvoid *)zcomment);\n              zcomment = NULL;\n              zipwarn(\"zipfile comment truncated - ignoring\", \"\");\n            } else {\n              zcomment[zcomlen] = '\\0';\n            }\n#ifdef EBCDIC\n            if (zcomment)\n               memtoebc(zcomment, zcomment, zcomlen);\n#endif /* EBCDIC */\n          }\n        }\n        if (total_disks != 1)\n          sprintf(errbuf, \" Found end record (EOCDR) - says expect %lu splits\", total_disks);\n        else\n          sprintf(errbuf, \" Found end record (EOCDR) - says expect single disk archive\");\n        zipmessage(errbuf, \"\");\n        if (zcomment)\n          zipmessage(\"  Found archive comment\", \"\");\n      } /* good EOCDR */\n\n    } /* found EOCDR */\n\n    /* if total disks is other than 1 then this is not start disk */\n    /* if the EOCDR is bad, total_disks is 0 */\n\n    /* if total_disks = 0, then guess if this is a single-disk archive\n       by seeing if starts with local header */\n\n    if (total_disks == 0) {\n      int issig;\n      /* seek to top */\n      if (zfseeko(in_file, 0, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        zipwarn(\"unable to seek in input file \", in_path);\n        return ZE_READ;\n      }\n      /* get next signature */\n      issig = find_next_signature(in_file);\n      if (issig) {\n        current_in_offset = zftello(in_file);\n        if (current_in_offset == 4 && is_signature(sigbuf, \"PK\\03\\03\")) {\n          /* could be multi-disk aborted signature at top */\n          /* skip */\n          issig = find_next_signature(in_file);\n        } else if (current_in_offset <= 4 && is_signature(sigbuf, \"PK\\03\\03\")) {\n          /* multi-disk spanning signature */\n          total_disks = 99999;\n        }\n      }\n      if (issig && total_disks == 0) {\n        current_in_offset = zftello(in_file);\n\n        if (current_in_offset == 8 && is_signature(sigbuf, \"PK\\03\\04\")) {\n\n          /* Local Header Record at top */\n\n          printf(\"Is this a single-disk archive?  (y/n): \");\n          fflush(stdout);\n\n          if (fgets(errbuf, 100, stdin) != NULL) {\n            if (errbuf[0] == 'y' || errbuf[0] == 'Y') {\n              total_disks = 1;\n              zipmessage(\"  Assuming single-disk archive\", \"\");\n            }\n          }\n        }\n      }\n    }\n    if (!noisy)\n      /* if quiet assume single-disk archive */\n      total_disks = 1;\n\n    if (total_disks == 1000000) {\n      /* still don't know, so ask */\n      printf(\"Is this a single-disk archive?  (y/n): \");\n      fflush(stdout);\n\n      if (fgets(errbuf, 100, stdin) != NULL) {\n        if (errbuf[0] == 'y' || errbuf[0] == 'Y') {\n          total_disks = 1;\n          zipmessage(\"  Assuming single-disk archive\", \"\");\n        }\n      }\n    }\n    if (total_disks == 1000000) {\n      /* assume max */\n      total_disks = 100000;\n    }\n\n  } /* .zip file exists */\n\n  /* Skip reading the Zip64 EOCDL, Zip64 EOCDR, or central directory */\n\n  /* Now read the archive starting with first disk.  Find local headers,\n     create entry in zlist, then copy entry to new archive */\n\n  /* Multi-volume file names end in .z01, .z02, ..., .z10, .zip for 11 disk archive */\n\n  /* Unless quiet, always close the in_path disk and ask user for first disk,\n     unless there is an End Of Central Directory record and that says there is\n     only one disk.\n     If quiet, assume the file pointed to is a single file archive to fix. */\n  if (noisy && in_file) {\n    fclose(in_file);\n    in_file = NULL;\n  }\n\n  /* Read the archive disks - no idea how many disks there are\n     since we can't trust the EOCDR and other end records\n   */\n  zipmessage(\"Scanning for entries...\", \"\");\n\n  for (current_in_disk = 0; current_in_disk < total_disks; current_in_disk++) {\n    /* get the path for this disk */\n    split_path = get_in_split_path(in_path, current_in_disk);\n\n    /* if in_file is not NULL then in_file is already open */\n    if (in_file == NULL) {\n      /* open the split */\n      while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n        int result;\n        /* could not open split */\n\n        /* Ask for directory with split.  Updates global variable in_path */\n        result = ask_for_split_read_path(current_in_disk);\n        if (result == ZE_ABORT) {\n          zipwarn(\"could not find split: \", split_path);\n          return ZE_ABORT;\n        } else if (result == ZE_EOF) {\n          zipmessage_nl(\"\", 1);\n          zipwarn(\"user ended reading - closing archive\", \"\");\n          return ZE_EOF;\n        } else if (result == ZE_FORM) {\n          /* user asked to skip this disk */\n          zipmessage_nl(\"\", 1);\n          sprintf(errbuf, \"skipping disk %lu ...\\n\", current_in_disk);\n          zipwarn(errbuf, \"\");\n          skip_disk = 1;\n          break;\n        }\n\n        split_path = get_in_split_path(in_path, current_in_disk);\n      }\n      if (skip_disk) {\n        /* skip this current disk - this works because central directory entries\n           can't be split across splits */\n        skip_disk = 0;\n        skipped_disk = 1;\n        continue;\n      }\n    }\n\n    if (skipped_disk) {\n      /* Not much to do here as between entries.  Entries are copied\n         in zipcopy() and that has to handle missing disks while\n         reading data for an entry.\n       */\n    }\n\n    /* Main loop */\n    /* Look for next signature and process it */\n    while (find_next_signature(in_file)) {\n      current_in_offset = zftello(in_file);\n\n      if (is_signature(sigbuf, \"PK\\05\\06\")) {\n\n        /* End Of Central Directory Record */\n\n        sprintf(errbuf, \"EOCDR found (%2lu %6s)...\",\n                current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n        zipmessage_nl(errbuf, 1);\n\n\n      } else if (is_signature(sigbuf, \"PK\\06\\06\")) {\n\n        /* Zip64 End Of Central Directory Record */\n\n        sprintf(errbuf, \"Zip64 EOCDR found (%2lu %6s)...\",\n                current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n        zipmessage_nl(errbuf, 1);\n\n\n      } else if (is_signature(sigbuf, \"PK\\06\\07\")) {\n\n        /* Zip64 End Of Central Directory Locator */\n\n        sprintf(errbuf, \"Zip64 EOCDL found (%2lu %6s)...\",\n                current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n        zipmessage_nl(errbuf, 1);\n\n\n      } else if (is_signature(sigbuf, \"PK\\03\\04\")) {\n\n        /* Local Header Record */\n\n\n        if (verbose) {\n          sprintf(errbuf, \" Local (%2lu %6s):\",\n                  current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n          zipmessage_nl(errbuf, 0);\n        }\n\n        /* Create zlist entry.  Most will be filled in by zipcopy(). */\n\n        if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n          zipwarn(\"reading central directory\", \"\");\n          return ZE_MEM;\n        }\n\n        z->vem = 0;\n        z->ver = 0;\n        z->flg = 0;\n        z->how = 0;\n        z->tim = 0;          /* time and date into one long */\n        z->crc = 0;\n        z->siz = 0;\n        z->len = 0;\n        z->nam = 0;          /* used before comparing cen vs. loc */\n        z->cext = 0;         /* may be different from z->ext */\n        z->com = 0;\n        z->dsk = 0;\n        z->att = 0;\n        z->atx = 0;\n        z->off = 0;\n        z->dosflag = 0;\n\n        /* Initialize all fields pointing to malloced data to NULL */\n        z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;\n        z->oname = NULL;\n#ifdef UNICODE_SUPPORT\n        z->uname = z->zuname = z->ouname = NULL;\n#endif\n\n        /* Attempt to copy entry */\n\n        r = zipcopy(z);\n\n        if (in_central_directory) {\n          sprintf(errbuf, \"Entry after central directory found (%2lu %6s)...\",\n                  current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n          zipmessage_nl(errbuf, 1);\n          in_central_directory = 0;\n        }\n\n        if (r == ZE_EOF)\n          /* user said no more splits */\n          break;\n        else if (r == ZE_OK) {\n          zcount++;\n          files_total++;\n          bytes_total += z->siz;\n\n          /* Link into list */\n          if (zfiles == NULL)\n            /* first link */\n            x = &zfiles;\n          /* Link into list */\n          *x = z;\n          z->nxt = NULL;\n          x = &z->nxt;\n        }\n\n      } else if (is_signature(sigbuf, \"PK\\01\\02\")) {\n\n        /* Central directory header */\n\n\n        /* sort the zlist */\n        if (in_central_directory == 0) {\n          zipmessage(\"Central Directory found...\", \"\");\n          /* If one or more files, sort by name */\n          if (zcount)\n          {\n            struct zlist far * far *x;    /* pointer into zsort array */\n            struct zlist far *z;          /* pointer into zfiles linked list */\n            int i = 0;\n            extent zl_size = zcount * sizeof(struct zlist far *);\n\n            if (zl_size / sizeof(struct zlist far *) != zcount ||\n                (x = zsort = (struct zlist far **)malloc(zl_size)) == NULL)\n              return ZE_MEM;\n            for (z = zfiles; z != NULL; z = z->nxt)\n              x[i++] = z;\n            qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);\n\n            /* Skip Unicode searching */\n          }\n        }\n\n        if (verbose) {\n          sprintf(errbuf, \" Cen   (%2lu %6s): \",\n                  current_in_disk + 1, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n          zipmessage_nl(errbuf, 0);\n        }\n\n        in_central_directory = 1;\n\n        /* Read central directory entry */\n\n        /* central directory signature */\n\n        /* The format of a central directory record\n          central file header signature   4 bytes  (0x02014b50)\n          version made by                 2 bytes\n          version needed to extract       2 bytes\n          general purpose bit flag        2 bytes\n          compression method              2 bytes\n          last mod file time              2 bytes\n          last mod file date              2 bytes\n          crc-32                          4 bytes\n          compressed size                 4 bytes\n          uncompressed size               4 bytes\n          file name length                2 bytes\n          extra field length              2 bytes\n          file comment length             2 bytes\n          disk number start               2 bytes\n          internal file attributes        2 bytes\n          external file attributes        4 bytes\n          relative offset of local header 4 bytes\n\n          file name (variable size)\n          extra field (variable size)\n          file comment (variable size)\n         */\n\n        if (fread(scbuf, CENHEAD, 1, in_file) != 1) {\n          zipwarn(\"reading central directory: \", strerror(errno));\n          zipwarn(\"bad archive - error reading central directory\", \"\");\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        }\n\n        if ((cz = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n          zipwarn(\"reading central directory\", \"\");\n          return ZE_MEM;\n        }\n\n        cz->vem = SH(CENVEM + scbuf);\n        cz->ver = SH(CENVER + scbuf);\n        cz->flg = SH(CENFLG + scbuf);\n        cz->how = SH(CENHOW + scbuf);\n        cz->tim = LG(CENTIM + scbuf);   /* time and date into one long */\n        cz->crc = LG(CENCRC + scbuf);\n        cz->siz = LG(CENSIZ + scbuf);\n        cz->len = LG(CENLEN + scbuf);\n        cz->nam = SH(CENNAM + scbuf);   /* used before comparing cen vs. loc */\n        cz->cext = SH(CENEXT + scbuf);  /* may be different from z->ext */\n        cz->com = SH(CENCOM + scbuf);\n        cz->dsk = SH(CENDSK + scbuf);\n        cz->att = SH(CENATT + scbuf);\n        cz->atx = LG(CENATX + scbuf);\n        cz->off = LG(CENOFF + scbuf);\n        cz->dosflag = (cz->vem & 0xff00) == 0;\n\n        /* Initialize all fields pointing to malloced data to NULL */\n        cz->zname = cz->name = cz->iname = cz->extra = cz->cextra = NULL;\n        cz->comment = cz->oname = NULL;\n#ifdef UNICODE_SUPPORT\n        cz->uname = cz->zuname = cz->ouname = NULL;\n#endif\n\n        /* Read file name, extra field and comment field */\n        if (cz->nam == 0)\n        {\n          sprintf(errbuf, \"%lu\", (ulg)zcount + 1);\n          zipwarn(\"zero-length name for entry #\", errbuf);\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        }\n        if ((cz->iname = malloc(cz->nam+1)) ==  NULL ||\n            (cz->cext && (cz->cextra = malloc(cz->cext + 1)) == NULL) ||\n            (cz->com && (cz->comment = malloc(cz->com + 1)) == NULL))\n          return ZE_MEM;\n        if (fread(cz->iname, cz->nam, 1, in_file) != 1 ||\n            (cz->cext && fread(cz->cextra, cz->cext, 1, in_file) != 1) ||\n            (cz->com && fread(cz->comment, cz->com, 1, in_file) != 1)) {\n          zipwarn(\"error reading entry:  \", strerror(errno));\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        }\n        cz->iname[cz->nam] = '\\0';                  /* terminate name */\n\n        /* Look up this name in zlist from local entries */\n        z = zsearch(cz->iname);\n\n\n        if (z && z->tim == cz->tim) {\n\n          /* Apparently as iname and date and time match this central\n             directory entry goes with this zlist entry */\n\n          if (verbose) {\n            /* cen dir name matches a local name */\n            sprintf(errbuf, \"updating: %s\", cz->iname);\n            zipmessage_nl(errbuf, 0);\n          }\n\n          if (z->crc != cz->crc) {\n            sprintf(errbuf, \"local (%lu) and cen (%lu) crc mismatch\", z->crc, cz->crc);\n            zipwarn(errbuf, \"\");\n          }\n\n          z->vem = cz->vem;\n         /* z->ver = cz->ver; */\n         /* z->flg = cz->flg; */\n         /* z->how = cz->how; */\n         /* z->tim = cz->tim; */          /* time and date into one long */\n         /* z->crc = cz->crc; */\n         /* z->siz = cz->siz; */\n         /* z->len = cz->len; */\n         /* z->nam = cz->nam; */          /* used before comparing cen vs. loc */\n          z->cext = cz->cext;             /* may be different from z->ext */\n          z->com = cz->com;\n          z->cextra = cz->cextra;\n          z->comment = cz->comment;\n         /* z->dsk = cz->dsk; */\n          z->att = cz->att;\n          z->atx = cz->atx;\n         /* z->off = cz->off; */\n          z->dosflag = cz->dosflag;\n\n#ifdef UNICODE_SUPPORT\n          if (unicode_mismatch != 3 && z->uname == NULL) {\n            if (z->flg & UTF8_BIT) {\n              /* path is UTF-8 */\n              if ((z->uname = malloc(strlen(z->iname) + 1)) == NULL) {\n                ZIPERR(ZE_MEM, \"reading archive\");\n              }\n              strcpy(z->uname, z->iname);\n            } else {\n              /* check for UTF-8 path extra field */\n              read_Unicode_Path_entry(z);\n            }\n          }\n#endif\n\n#ifdef WIN32\n          /* Input path may be OEM */\n          {\n            unsigned hostver = (z->vem & 0xff);\n            Ext_ASCII_TO_Native(z->iname, (z->vem >> 8), hostver,\n                                ((z->atx & 0xffff0000L) != 0), FALSE);\n          }\n#endif\n\n#ifdef EBCDIC\n          if (z->com)\n             memtoebc(z->comment, z->comment, z->com);\n#endif /* EBCDIC */\n#ifdef WIN32\n          /* Comment may be OEM */\n          {\n            unsigned hostver = (z->vem & 0xff);\n            Ext_ASCII_TO_Native(z->comment, (z->vem >> 8), hostver,\n                                ((z->atx & 0xffff0000L) != 0), FALSE);\n          }\n#endif\n\n#ifdef ZIP64_SUPPORT\n          /* zip64 support 08/31/2003 R.Nausedat                          */\n          /* here, we have to read the len, siz etc values from the CD    */\n          /* entry as we might have to adjust them regarding their        */\n          /* correspronding zip64 extra fields.                           */\n          /* also, we cannot compare the values from the CD entries with  */\n          /* the values from the LH as they might be different.           */\n\n          /* adjust/update siz,len and off (to come: dsk) entries */\n          /* PKZIP does not care of the version set in a CDH: if  */\n          /* there is a zip64 extra field assigned to a CDH PKZIP */\n          /* uses it, we should do so, too.                       */\n  /*\n          adjust_zip_central_entry(z);\n   */\n#endif\n\n        /* Update zipbeg beginning of archive offset, prepare for next header */\n/*\n          if (z->dsk == 0 && (!zipbegset || z->off < zipbeg)) {\n            zipbeg = z->off;\n            zipbegset = 1;\n          }\n          zcount++;\n */\n\n#ifndef UTIL\n          if (verbose)\n            zipoddities(z);\n#endif\n\n          current_offset = zftello(y);\n\n          if (zfseeko(y, z->off, SEEK_SET) != 0) {\n            fclose(in_file);\n            in_file = NULL;\n            zipwarn(\"writing archive seek: \", strerror(errno));\n            return ZE_WRITE;\n          }\n\n          if (putlocal(z, PUTLOCAL_REWRITE) != ZE_OK)\n            zipwarn(\"Error rewriting local header\", \"\");\n\n          if (zfseeko(y, current_offset, SEEK_SET) != 0) {\n            fclose(in_file);\n            in_file = NULL;\n            zipwarn(\"write archive seek: \", strerror(errno));\n            return ZE_WRITE;\n          }\n          offset = zftello(y);\n          if (current_offset != offset) {\n            fclose(in_file);\n            in_file = NULL;\n            zipwarn(\"seek after local: \", strerror(errno));\n            return ZE_WRITE;\n          }\n\n          if (verbose)\n            zipmessage_nl(\"\", 1);\n\n        } else {\n          /* cen dir name does not match local name */\n          sprintf(errbuf, \"no local entry: %s\", cz->iname);\n          zipmessage_nl(errbuf, 1);\n        }\n\n      } else if (zfiles == NULL && is_signature(sigbuf, \"PK\\07\\010\")) {\n\n        /* assume spanning signature at top of archive */\n        if (total_disks == 1) {\n          zipmessage(\"  Found spanning marker, but did not expect split (multi-disk) archive...\", \"\");\n\n        } else if (total_disks > 1) {\n          zipmessage(\"  Found spanning marker - expected as this is split (multi-disk) archive...\", \"\");\n\n        } else {\n          zipmessage(\"  Found spanning marker - could be split archive...\", \"\");\n\n        }\n\n      } else {\n\n        /* this signature shouldn't be here */\n        int c;\n        char errbuftemp[40];\n\n        strcpy(errbuf, \"unexpected signature \");\n        for (c = 0; c < 4; c++) {\n          sprintf(errbuftemp, \"%02x \", sigbuf[c]);\n          strcat(errbuf, errbuftemp);\n        }\n        sprintf(errbuftemp, \"on disk %lu at %s\\n\", current_in_disk,\n                                 zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n        strcat(errbuf, errbuftemp);\n        zipwarn(errbuf, \"\");\n        zipwarn(\"skipping this signature...\", \"\");\n      }\n\n\n    } /* while reading file */\n\n    /* close disk and do next disk */\n    if (in_file)\n      fclose(in_file);\n    in_file = NULL;\n    free(split_path);\n\n    if (r == ZE_EOF)\n      /* user says no more splits */\n      break;\n\n  } /* for each disk */\n\n  return ZE_OK;\n\n} /* end of function scanzipf_fixnew() */\n\n#endif /* !UTIL */\n\n\n\n\n\n\n/* ---------------------- */\n/* New regular scan       */\n\n/*\n * scanzipf_regnew is similar to the orignal scanzipf_reg in that it\n * reads the end of the archive and goes from there.  Unlike that\n * scan this one stops after reading the central directory and does\n * not read the local headers.  After the directory scan for new\n * files is done in zip.c the zlist created here is used to read\n * the old archive entries there.  The local headers are read using\n * readlocal() in zipcopy().\n *\n * This scan assumes the zip file is well structured.  If not it may\n * fail and the new scanzipf_fixnew should be used.\n *\n * 2006-2-4, 2007-12-10 EG\n */\n\nlocal int scanzipf_regnew()\n/*\n   The input path for the .zip file is in in_path.  If a split archive,\n   the path for each split is created from the current disk number\n   and in_path.  If a split is not in the same directory as the last\n   split we ask the user where it is and update in_path.\n */\n/*\n   This is old but more or less still applies:\n\n   The name of the zip file is pointed to by the global \"zipfile\".  The globals\n   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.\n   Return an error code in the ZE_ class.\n*/\n{\n  /* In this function, a local buffer is used to read in the following Zip\n     structures:\n      End-of-CentralDir record (EOCDR) (ENDHEAD)\n      Zip64-End-of-CentralDir-Record locator (Zip64 EOCDL) (EC64LOC)\n      Zip64-End-of-CentralDir record (Zip64 EOCDR) (EC64REC)\n      CentralDir-Entry record (CENHEAD)\n     To conserve valuable stack space, this buffer is sized to the largest\n     of these structures.\n   */\n# if CENHEAD > ENDHEAD\n#   define SCAN_BUFSIZE CENHEAD   /* CENHEAD should be the larger struct */\n# else\n#   define SCAN_BUFSIZE ENDHEAD\n# endif\n\n#ifdef ZIP64_SUPPORT\n# if EC64REC > SCAN_BUFSIZE\n#   undef SCAN_BUFSIZE\n#   define SCAN_BUFSIZE EC64REC   /* EC64 record should be largest struct */\n# endif\n# if EC64LOC > SCAN_BUFSIZE\n#   undef SCAN_BUFSIZE\n#   define SCAN_BUFSIZE EC64LOC\n# endif\n#endif\n\n  char    scbuf[SCAN_BUFSIZE];  /* buffer just enough for all header types */\n  char   *split_path;\n  ulg     eocdr_disk;\n  uzoff_t eocdr_offset;\n# ifdef ZIP64_SUPPORT\n  ulg     z64eocdr_disk;\n  uzoff_t z64eocdr_offset;\n  uzoff_t z64eocdr_size;\n  ush     version_made;\n  ush     version_needed = 0;\n  zoff_t zip64_eocdr_start;\n  zoff_t z64eocdl_offset;\n# endif /* def ZIP64_SUPPORT */\n  uzoff_t cd_total_entries;        /* num of entries as read from (Zip64) EOCDR */\n  ulg     in_cd_start_disk;        /* central directory start disk */\n  uzoff_t in_cd_start_offset;      /* offset of start of cd on cd start disk */\n  uzoff_t adjust_offset = 0;       /* bytes before first entry (size of sfx prefix) */\n  uzoff_t cd_total_size = 0;       /* total size of cd */\n\n\n  int first_CD = 1;           /* looking for first CD entry */\n  int zipbegset = 0;\n\n  int skip_disk = 0;          /* 1 if user asks to skip current disk */\n  int skipped_disk = 0;       /* 1 if skipped start disk and start offset is useless */\n\n  uzoff_t s;                  /* size of data, start of central */\n  struct zlist far * far *x;  /* pointer last entry's link */\n  struct zlist far *z;        /* current zip entry structure */\n\n\n  /* open the zipfile */\n  if ((in_file = zfopen(in_path, FOPR)) == NULL) {\n    zipwarn(\"could not open input archive\", in_path);\n    return ZE_OPEN;\n  }\n\n#ifndef ZIP64_SUPPORT\n  /* 2004-12-06 SMS.\n   * Check for too-big file before doing any serious work.\n   */\n  if (ffile_size( in_file) == EOF) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"input file requires Zip64 support: \", in_path);\n    return ZE_ZIP64;\n  }\n#endif /* ndef ZIP64_SUPPORT */\n\n  /* look for End Of Central Directory Record */\n\n  /* In a valid Zip archive, the EOCDR can be at most (64k-1 + ENDHEAD + 4)\n     bytes (=65557 bytes) from the end of the file.\n     We back up 128k, to allow some junk being appended to a Zip file.\n   */\n  if ((zfseeko(in_file, -0x20000L, SEEK_END) != 0) ||\n      /* Some fseek() implementations (e.g. MSC 8.0 16-bit) fail to signal\n         an error when seeking before the beginning of the file.\n         As work-around, we check the position returned by zftello()\n         for the error value -1.\n       */\n      (zftello(in_file) == (zoff_t)-1L)) {\n    /* file is less than 128 KB so back up to beginning */\n    if (zfseeko(in_file, 0L, SEEK_SET) != 0) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"unable to seek in input file \", in_path);\n      return ZE_READ;\n    }\n  }\n\n  /* find EOCD Record signature */\n  if (!find_signature(in_file, \"PK\\05\\06\")) {\n    /* No End Of Central Directory Record */\n    fclose(in_file);\n    in_file = NULL;\n    if (fix == 1) {\n      zipwarn(\"bad archive - missing end signature\", \"\");\n      zipwarn(\"(If downloaded, was binary mode used?  If not, the\", \"\");\n      zipwarn(\" archive may be scrambled and not recoverable)\", \"\");\n      zipwarn(\"Can't use -F to fix (try -FF)\", \"\");\n    } else{\n      zipwarn(\"missing end signature--probably not a zip file (did you\", \"\");\n      zipwarn(\"remember to use binary mode when you transferred it?)\", \"\");\n      zipwarn(\"(if you are trying to read a damaged archive try -F)\", \"\");\n    }\n    return ZE_FORM;\n  }\n\n  /* at start of data after EOCDR signature */\n  eocdr_offset = (uzoff_t) zftello(in_file);\n\n  /* OK, it is possible this is not the last EOCDR signature (might be\n     EOCDR signature from a stored archive in the last 128 KB) and so not\n     the one we want.\n\n     The below assumes the signature does not appear in the assumed ASCII text\n     .ZIP file comment.\n  */\n  while (find_signature(in_file, \"PK\\05\\06\")) {\n    /* previous one was not the one */\n    eocdr_offset = (uzoff_t) zftello(in_file);\n  }\n\n  /* found EOCDR */\n  /* format is\n       end of central dir signature     4 bytes  (0x06054b50)\n       number of this disk              2 bytes\n       number of the disk with the\n        start of the central directory  2 bytes\n       total number of entries in the\n        central directory on this disk  2 bytes\n       total number of entries in\n        the central directory           2 bytes\n       size of the central directory    4 bytes\n       offset of start of central\n        directory with respect to\n        the starting disk number        4 bytes\n       .ZIP file comment length         2 bytes\n       .ZIP file comment        (variable size)\n   */\n\n  if (zfseeko(in_file, eocdr_offset, SEEK_SET) != 0) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"unable to seek in input file \", in_path);\n    return ZE_READ;\n  }\n\n  /* read the EOCDR */\n  s = fread(scbuf, 1, ENDHEAD, in_file);\n\n  /* the first field should be number of this (the last) disk */\n  eocdr_disk = (ulg)SH(scbuf);\n  total_disks = eocdr_disk + 1;\n\n  /* Assume EOCDR disk is this disk.  If a lot of disks, the Zip64 field\n     may be needed and this EOCDR field could be set to the Zip64 flag\n     value as the disk number may be bigger than this field can hold.\n  */\n  current_in_disk = total_disks - 1;\n\n  /* Central Directory disk, offset, and total entries */\n  in_cd_start_disk = (ulg)SH(scbuf + ENDBEG);\n  in_cd_start_offset = (uzoff_t)LG(scbuf + ENDOFF);\n  cd_total_entries = (uzoff_t)SH(scbuf + ENDTOT);\n  cd_total_size = (uzoff_t)LG(scbuf + ENDSIZ);\n\n  /* length of zipfile comment */\n  zcomlen = SH(scbuf + ENDCOM);\n  if (zcomlen)\n  {\n    if ((zcomment = malloc(zcomlen + 1)) == NULL)\n      return ZE_MEM;\n    if (fread(zcomment, zcomlen, 1, in_file) != 1)\n    {\n      free((zvoid *)zcomment);\n      zcomment = NULL;\n      return ferror(in_file) ? ZE_READ : ZE_EOF;\n    }\n    zcomment[zcomlen] = '\\0';\n#ifdef EBCDIC\n    if (zcomment)\n       memtoebc(zcomment, zcomment, zcomlen);\n#endif /* EBCDIC */\n  }\n\n  if (cd_total_entries == 0) {\n    /* empty archive */\n\n    fclose(in_file);\n    in_file = NULL;\n    return ZE_OK;\n  }\n\n  /* if total disks is other than 1 then multi-disk archive */\n  if (total_disks != 1) {\n    /* zipfile name must end in .zip for split archives */\n    int plen = strlen(in_path);\n    char *in_path_ext;\n\n    if (adjust) {\n      zipwarn(\"Adjusting split archives not yet supported\", \"\");\n      return ZE_FORM;\n    }\n\n#ifdef VMS\n    /* On VMS, adjust plen (and in_path_ext) to avoid the file version. */\n    plen -= strlen(vms_file_version(in_path));\n#endif /* def VMS */\n    in_path_ext = zipfile + plen - 4;\n\n    if (plen < 4 ||\n        in_path_ext[0] != '.' ||\n        toupper(in_path_ext[1]) != 'Z' ||\n        toupper(in_path_ext[2]) != 'I' ||\n        toupper(in_path_ext[3]) != 'P') {\n      zipwarn(\"archive name must end in .zip for splits\", \"\");\n      fclose(in_file);\n      in_file = NULL;\n      return ZE_PARMS;\n    }\n  }\n\n  /* if input or output are split archives, must be different archives */\n  if ((total_disks != 1 || split_method) && !show_files &&\n      strcmp(in_path, out_path) == 0) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"cannot update a split archive (use --out option)\", \"\");\n    return ZE_PARMS;\n  }\n\n  /* if fixing archive, input and output must be different archives */\n  if (fix == 1 && strcmp(in_path, out_path) == 0) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"must use --out when fixing an archive\", \"\");\n    return ZE_PARMS;\n  }\n\n\n  /* Get sfx offset if adjusting. Above we made sure not split archive. */\n  /* Also check for an offset if fix and single disk archive. */\n  if ((fix == 1 && total_disks == 1) || adjust) {\n    zoff_t cd_start;\n# ifdef ZIP64_SUPPORT\n    zoff_t zip64_eocdr_start;\n# endif\n\n    /* First attempt.  If the CD start offset and size are valid in the EOCDR\n       (meaning they are not the Zip64 flag values that say the actual values\n       are in the Zip64 EOCDR), we can use them to get the offset */\n    if (in_cd_start_offset != 0xFFFFFFFF && cd_total_size != 0xFFFFFFFF) {\n      /* Search for start of central directory */\n      /* There still might be a Zip64 EOCDR.  This assumes if there is\n         a Zip64 EOCDR, it's version 1 and 52 bytes */\n      cd_start = eocdr_offset - cd_total_size - 24 - 56;\n      if (zfseeko(in_file, cd_start, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        if (fix == 1) {\n          zipwarn(\"could not seek back to start of central directory: \", strerror(errno));\n          zipwarn(\"(try -FF)\", \"\");\n        } else {\n          zipwarn(\"reading archive fseek: \", strerror(errno));\n        }\n        return ZE_FORM;\n      }\n      if (find_signature(in_file, \"PK\\01\\02\")) {\n        /* Should now be after first central directory header signature in archive */\n        adjust_offset = zftello(in_file) - 4 - in_cd_start_offset;\n      } else {\n        zipwarn(\"central dir not where expected - could not adjust offsets\", \"\");\n        zipwarn(\"(try -FF)\", \"\");\n        return ZE_FORM;\n      }\n    } else {\n\n      /* Second attempt.  We need the Zip64 EOCDL to get the offset */\n\n      /*\n       * Check for a Zip64 EOCD Locator signature\n       */\n\n      /* Format of Z64EOCD Locator is\n           zip64 end of central dir locator\n            signature                       4 bytes  (0x07064b50)\n           number of the disk with the\n            start of the zip64 end of\n            central directory               4 bytes\n           relative offset of the zip64\n            end of central directory record 8 bytes\n           total number of disks            4 bytes\n       */\n\n      /* back up 20 bytes from EOCDR to Z64 EOCDL */\n      if (zfseeko(in_file, eocdr_offset - 24, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        if (fix == 1) {\n          zipwarn(\"could not seek back to Zip64 EOCDL: \", strerror(errno));\n          zipwarn(\"(try -FF)\", \"\");\n        } else {\n          zipwarn(\"reading archive fseek: \", strerror(errno));\n        }\n        return ZE_FORM;\n      }\n      if (at_signature(in_file, \"PK\\06\\07\"))\n#ifndef ZIP64_SUPPORT\n      {\n        fclose(in_file);\n        in_file = NULL;\n        zipwarn(\"found Zip64 signature - this may be a Zip64 archive\", \"\");\n        zipwarn(\"Need PKZIP 4.5 or later compatible zip\", \"\");\n        zipwarn(\"Set ZIP64_SUPPORT in Zip 3\", \"\");\n        return ZE_ZIP64;\n      }\n#else /* ZIP64_SUPPORT */\n      {\n        z64eocdl_offset = zftello(in_file) - 4;\n\n        /* read Z64 EOCDL */\n        if (fread(scbuf, EC64LOC, 1, in_file) != 1) {\n          fclose(in_file);\n          in_file = NULL;\n          zipwarn(\"reading archive: \", strerror(errno));\n          return ZE_READ;\n        }\n        /* now should be back at the EOCD signature */\n        if (!at_signature(in_file, \"PK\\05\\06\")) {\n          fclose(in_file);\n          in_file = NULL;\n          zipwarn(\"unable to read EOCD after seek: \", in_path);\n          return ZE_READ;\n        }\n\n        /* read disk and offset to Zip64 EOCDR and total disks */\n        z64eocdr_disk = LG(scbuf);\n        z64eocdr_offset = LLG(scbuf + 4);\n        total_disks = LG(scbuf + 12);\n\n        /* For now no split archives */\n        if (total_disks != 1) {\n          zipwarn(\"Adjusting split archives not supported:  \", in_path);\n          zipwarn(\"(try -FF)\", \"\");\n          return ZE_FORM;\n        }\n\n        /* go to the Zip64 EOCDR */\n        if (zfseeko(in_file, z64eocdr_offset, SEEK_SET) != 0) {\n          fclose(in_file);\n          in_file = NULL;\n          zipwarn(\"reading archive fseek: \", strerror(errno));\n          return ZE_FORM;\n        }\n        /* Should be at Zip64 EOCDR signature */\n        if (at_signature(in_file, \"PK\\06\\06\")) {\n          /* apparently no offset */\n\n        } else {\n          /* Wasn't there, so calculate based on Zip64 EOCDL offset */\n\n          zip64_eocdr_start = z64eocdl_offset - 24 - 56;\n          if (zfseeko(in_file, zip64_eocdr_start, SEEK_SET) != 0) {\n            fclose(in_file);\n            in_file = NULL;\n            if (fix == 1) {\n              zipwarn(\"could not seek back to Zip64 EOCDR: \", strerror(errno));\n              zipwarn(\"(try -FF)\", \"\");\n            } else {\n              zipwarn(\"reading archive fseek: \", strerror(errno));\n            }\n            return ZE_FORM;\n          }\n          if (find_next_signature(in_file) && is_signature(sigbuf, \"PK\\06\\06\")) {\n            /* Should now be after Zip64 EOCDR signature in archive */\n            adjust_offset = zftello(in_file) - 4 - z64eocdr_offset;\n          } else {\n            zipwarn(\"Could not determine offset of entries\", \"\");\n            zipwarn(\"(try -FF)\", \"\");\n            return ZE_FORM;\n          }\n        }\n      }\n#endif\n    }\n    if (noisy) {\n      if (adjust_offset) {\n        sprintf(errbuf, \"Zip entry offsets appear off by %s bytes - correcting...\",\n                        zip_fzofft(adjust_offset, NULL, NULL));\n      } else {\n        sprintf(errbuf, \"Zip entry offsets do not need adjusting\");\n      }\n      zipmessage(errbuf, \"\");\n    }\n  }\n\n\n  /*\n   * Check for a Zip64 EOCD Locator signature\n   */\n\n  /* Format of Z64EOCD Locator is\n       zip64 end of central dir locator\n        signature                       4 bytes  (0x07064b50)\n       number of the disk with the\n        start of the zip64 end of\n        central directory               4 bytes\n       relative offset of the zip64\n        end of central directory record 8 bytes\n       total number of disks            4 bytes\n   */\n\n  /* back up 20 bytes from EOCDR to Z64 EOCDL */\n  if (zfseeko(in_file, eocdr_offset - 24, SEEK_SET) != 0) {\n    fclose(in_file);\n    in_file = NULL;\n    if (fix == 1) {\n      zipwarn(\"bad archive - could not seek back to Zip64 EOCDL: \", strerror(errno));\n      zipwarn(\"(try -FF)\", \"\");\n    } else {\n      zipwarn(\"reading archive fseek: \", strerror(errno));\n    }\n    return ZE_FORM;\n  }\n  if (at_signature(in_file, \"PK\\06\\07\"))\n#ifndef ZIP64_SUPPORT\n  {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"found Zip64 signature - this may be a Zip64 archive\", \"\");\n    zipwarn(\"Need PKZIP 4.5 or later compatible zip\", \"\");\n    zipwarn(\"Set ZIP64_SUPPORT in Zip 3\", \"\");\n    return ZE_ZIP64;\n  }\n#else /* ZIP64_SUPPORT */\n  {\n    z64eocdl_offset = zftello(in_file) - 4;\n    /* read Z64 EOCDL */\n    if (fread(scbuf, EC64LOC, 1, in_file) != 1) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"reading archive: \", strerror(errno));\n      return ZE_READ;\n    }\n    /* now should be back at the EOCD signature */\n    if (!at_signature(in_file, \"PK\\05\\06\")) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"unable to read EOCD after seek: \", in_path);\n      return ZE_READ;\n    }\n\n    /* read disk and offset to Zip64 EOCDR and total disks */\n    z64eocdr_disk = LG(scbuf);\n    z64eocdr_offset = LLG(scbuf + 4) + adjust_offset;\n    total_disks = LG(scbuf + 12);\n\n    /* set the current disk */\n    current_in_disk = total_disks - 1;\n\n    /* Now need to read the Zip64 EOCD Record to get version needed\n       to extract */\n\n    if (z64eocdr_disk != total_disks - 1) {\n      /* Zip64 EOCDR not on this disk */\n\n      /* done with this disk (since apparently there are no CD entries\n         on it) */\n      fclose(in_file);\n      in_file = NULL;\n\n      /* get the path for the disk with the Zip64 EOCDR */\n      split_path = get_in_split_path(in_path, z64eocdr_disk);\n\n      while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n        /* could not open split */\n\n        /* Ask where this split is.  This call also updates global in_path. */\n        if (ask_for_split_read_path(z64eocdr_disk) != ZE_OK) {\n          return ZE_ABORT;\n        }\n        free(split_path);\n        split_path = get_in_split_path(in_path, z64eocdr_disk);\n      }\n      free(split_path);\n    }\n\n    current_in_disk = z64eocdr_disk;\n\n    /* go to the Zip64 EOCDR */\n    if (zfseeko(in_file, z64eocdr_offset, SEEK_SET) != 0) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"reading archive fseek: \", strerror(errno));\n      return ZE_FORM;\n    }\n    /* Should be at Zip64 EOCDR signature */\n    if (!at_signature(in_file, \"PK\\06\\06\")) {\n      /* Wasn't there, so calculate based on Zip64 EOCDL offset */\n      zip64_eocdr_start = z64eocdl_offset - 24 - 56;\n      if (zfseeko(in_file, zip64_eocdr_start, SEEK_SET) != 0) {\n        fclose(in_file);\n        in_file = NULL;\n        if (fix == 1) {\n          zipwarn(\"bad archive - could not seek back to Zip64 EOCDR: \", strerror(errno));\n          zipwarn(\"(try -FF)\", \"\");\n        } else {\n          zipwarn(\"reading archive fseek: \", strerror(errno));\n        }\n        return ZE_FORM;\n      }\n      if (find_next_signature(in_file) && is_signature(sigbuf, \"PK\\06\\06\")) {\n        /* Should now be after Zip64 EOCDR signature in archive */\n        adjust_offset = zftello(in_file) - 4 - z64eocdr_offset;\n        zipwarn(\"Zip64 EOCDR not found where expected - compensating\", \"\");\n        zipwarn(\"(try -A to adjust offsets)\", \"\");\n      } else {\n        fclose(in_file);\n        in_file = NULL;\n        if (fix == 1) {\n          zipwarn(\"bad archive - Zip64 EOCDR not found in split:  \", in_path);\n          zipwarn(\"(try -FF)\", \"\");\n        } else {\n          zipwarn(\"Zip64 End Of Central Directory Record not found:  \", in_path);\n        }\n        return ZE_FORM;\n      }\n    }\n\n    /*\n     * Read the Z64 End Of Central Directory Record\n     */\n\n    /* The format of the Z64 EOCDR is\n        zip64 end of central dir\n         signature                       4 bytes  (0x06064b50)\n        size of zip64 end of central\n         directory record                8 bytes\n        version made by                  2 bytes\n        version needed to extract        2 bytes\n        number of this disk              4 bytes\n        number of the disk with the\n         start of the central directory  4 bytes\n        total number of entries in the\n         central directory on this disk  8 bytes\n        total number of entries in the\n         central directory               8 bytes\n        size of the central directory    8 bytes\n        offset of start of central\n         directory with respect to\n         the starting disk number        8 bytes\n        (version 2 of the Zip64 EOCDR has more after this)\n        zip64 extensible data sector    (variable size)\n     */\n\n    /* read the first 52 bytes of the Zip64 EOCDR (we don't support\n       version 2, which supports PKZip licensed features)\n    */\n    s = fread(scbuf, 1, EC64REC, in_file);\n    if (s < EC64REC) {\n      if (fix == 1) {\n        zipwarn(\"bad archive - Zip64 EOCDR bad or truncated\", \"\");\n        zipwarn(\"(try -FF)\", \"\");\n      } else {\n        zipwarn(\"Zip64 EOCD Record bad or truncated\", \"\");\n      }\n      fclose(in_file);\n      in_file = NULL;\n      return ZE_FORM;\n    }\n    z64eocdr_size = LLG(scbuf);\n    version_made = SH(scbuf + 8);\n    version_needed = SH(scbuf + 10);\n    in_cd_start_disk = LG(scbuf + 16);\n    cd_total_entries = LLG(scbuf + 28);\n    in_cd_start_offset = LLG(scbuf + 44) + adjust_offset;\n\n    if (version_needed > 46) {\n      int major = version_needed / 10;\n      int minor = version_needed - (major * 10);\n      sprintf(errbuf, \"This archive requires version %d.%d\", major, minor);\n      zipwarn(errbuf, \"\");\n      zipwarn(\"Zip currently only supports up to version 4.6 archives\", \"\");\n      zipwarn(\"(up to 4.5 if bzip2 is not compiled in)\", \"\");\n      if (fix == 1)\n        zipwarn(\"If -F fails try -FF to try to salvage something\", \"\");\n      else if (fix == 2)\n        zipwarn(\"Attempting to salvage what can\", \"\");\n      else {\n        zipwarn(\"Try -F to attempt to read anyway\", \"\");\n        fclose(in_file);\n        in_file = NULL;\n        return ZE_FORM;\n      }\n    }\n  }\n#endif /* ?ZIP64_SUPPORT */\n\n  /* Now read the central directory and create the zlist */\n\n  /* Multi-volume file names end in .z01, .z02, ..., .z10, .zip for 11 disk archive */\n\n  in_cd_start_offset += adjust_offset;\n  cenbeg = in_cd_start_offset;\n  zipbegset = 0;\n  zipbeg = 0;\n  first_CD = 1;\n\n  /* if the central directory starts on other than this disk, close this disk */\n  if (current_in_disk != in_cd_start_disk) {\n    /* close current disk */\n    fclose(in_file);\n    in_file = NULL;\n  }\n\n  /* Read the disks with the central directory in order - usually the\n     central directory fits on the last disk, but it doesn't have to.\n   */\n  for (current_in_disk = in_cd_start_disk;\n       current_in_disk < total_disks;\n       current_in_disk++) {\n    /* get the path for this disk */\n    if (current_in_disk == total_disks - 1) {\n      /* last disk is archive.zip */\n      if ((split_path = malloc(strlen(in_path) + 1)) == NULL) {\n        zipwarn(\"reading archive: \", in_path);\n        return ZE_MEM;\n      }\n      strcpy(split_path, in_path);\n    } else {\n      /* other disks are archive.z01, archive.z02, ... */\n      split_path = get_in_split_path(in_path, current_in_disk);\n    }\n\n    /* if in_file is not NULL then in_file is already open */\n    if (in_file == NULL) {\n      /* open the split */\n      while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n        int result;\n        /* could not open split */\n\n        /* Ask for directory with split.  Updates global variable in_path */\n        result = ask_for_split_read_path(current_in_disk);\n        if (result == ZE_ABORT) {\n          zipwarn(\"could not find split: \", split_path);\n          return ZE_ABORT;\n        } else if (result == ZE_FORM) {\n          /* user asked to skip this disk */\n          sprintf(errbuf, \"skipping disk %lu ...\\n\", current_in_disk);\n          zipwarn(errbuf, \"\");\n          skip_disk = 1;\n          break;\n        }\n\n        if (current_in_disk == total_disks - 1) {\n          /* last disk is archive.zip */\n          if ((split_path = malloc(strlen(in_path) + 1)) == NULL) {\n            zipwarn(\"reading archive: \", in_path);\n            return ZE_MEM;\n          }\n          strcpy(split_path, in_path);\n        } else {\n          /* other disks are archive.z01, archive.z02, ... */\n          split_path = get_in_split_path(zipfile, current_in_disk);\n        }\n      }\n      if (skip_disk) {\n        /* skip this current disk - this works because central directory entries\n           can't be split across splits */\n        skip_disk = 0;\n        skipped_disk = 1;\n        continue;\n      }\n    }\n\n    if (skipped_disk) {\n      /* skipped start CD disk so start searching for CD signature at start of disk */\n      first_CD = 0;\n    } else {\n      /* seek to the first CD entry */\n      if (first_CD) {\n        if (zfseeko(in_file, in_cd_start_offset, SEEK_SET) != 0) {\n          fclose(in_file);\n          in_file = NULL;\n          zipwarn(\"unable to seek in input file \", split_path);\n          return ZE_READ;\n        }\n        first_CD = 0;\n        x = &zfiles;                        /* first link */\n      }\n    }\n\n    /* Main loop */\n    /* Look for next signature and process it */\n    while (find_next_signature(in_file)) {\n      current_in_offset = zftello(in_file);\n\n      if (is_signature(sigbuf, \"PK\\05\\06\")) {\n        /* End Of Central Directory Record */\n        /*\n          fprintf(mesg, \"EOCDR signature at %d / %I64d\\n\",\n                  current_in_disk, current_in_offset - 4);\n        */\n        break;\n\n      } else if (is_signature(sigbuf, \"PK\\06\\06\")) {\n        /* Zip64 End Of Central Directory Record */\n        /*\n          fprintf(mesg, \"Zip64 EOCDR signature at %d / %I64d\\n\",\n                  current_in_disk, current_in_offset - 4);\n        */\n        break;\n\n      } else if (!is_signature(sigbuf, \"PK\\01\\02\")) {\n        /* Not Central Directory Record */\n\n        /* this signature shouldn't be here */\n        if (fix == 1) {\n          int c;\n          char errbuftemp[40];\n\n          strcpy(errbuf, \"bad archive - unexpected signature \");\n          for (c = 0; c < 4; c++) {\n            sprintf(errbuftemp, \"%02x \", sigbuf[c]);\n            strcat(errbuf, errbuftemp);\n          }\n          sprintf(errbuftemp, \"on disk %lu at %s\\n\", current_in_disk,\n                                   zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n          strcat(errbuf, errbuftemp);\n          zipwarn(errbuf, \"\");\n          zipwarn(\"skipping this signature...\", \"\");\n          continue;\n        } else {\n          sprintf(errbuf, \"unexpected signature on disk %lu at %s\\n\",\n                  current_in_disk, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n          zipwarn(errbuf, \"\");\n          zipwarn(\"archive not in correct format: \", split_path);\n          zipwarn(\"(try -F to attempt recovery)\", \"\");\n          fclose(in_file);\n          in_file = NULL;\n          return ZE_FORM;\n        }\n      }\n\n      /* central directory signature */\n      if (verbose && fix == 1) {\n        fprintf(mesg, \"central directory header signature on disk %lu at %s\\n\",\n                current_in_disk, zip_fzofft(current_in_offset - 4, NULL, \"u\"));\n      }\n\n      /* The format of a central directory record\n        central file header signature   4 bytes  (0x02014b50)\n        version made by                 2 bytes\n        version needed to extract       2 bytes\n        general purpose bit flag        2 bytes\n        compression method              2 bytes\n        last mod file time              2 bytes\n        last mod file date              2 bytes\n        crc-32                          4 bytes\n        compressed size                 4 bytes\n        uncompressed size               4 bytes\n        file name length                2 bytes\n        extra field length              2 bytes\n        file comment length             2 bytes\n        disk number start               2 bytes\n        internal file attributes        2 bytes\n        external file attributes        4 bytes\n        relative offset of local header 4 bytes\n\n        file name (variable size)\n        extra field (variable size)\n        file comment (variable size)\n       */\n\n      if (fread(scbuf, CENHEAD, 1, in_file) != 1) {\n        zipwarn(\"reading central directory: \", strerror(errno));\n        if (fix == 1) {\n          zipwarn(\"bad archive - error reading central directory\", \"\");\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        } else {\n          return ferror(in_file) ? ZE_READ : ZE_EOF;\n        }\n      }\n\n      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n        zipwarn(\"reading central directory\", \"\");\n        return ZE_MEM;\n      }\n\n      z->vem = SH(CENVEM + scbuf);\n      z->ver = SH(CENVER + scbuf);\n      z->flg = SH(CENFLG + scbuf);\n      z->how = SH(CENHOW + scbuf);\n      z->tim = LG(CENTIM + scbuf);      /* time and date into one long */\n      z->crc = LG(CENCRC + scbuf);\n      z->siz = LG(CENSIZ + scbuf);\n      z->len = LG(CENLEN + scbuf);\n      z->nam = SH(CENNAM + scbuf);      /* used before comparing cen vs. loc */\n      z->cext = SH(CENEXT + scbuf);     /* may be different from z->ext */\n      z->com = SH(CENCOM + scbuf);\n      z->dsk = SH(CENDSK + scbuf);\n      z->att = SH(CENATT + scbuf);\n      z->atx = LG(CENATX + scbuf);\n      z->off = LG(CENOFF + scbuf);      /* adjust_offset is added below */\n      z->dosflag = (z->vem & 0xff00) == 0;\n\n      /* Initialize all fields pointing to malloced data to NULL */\n      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;\n      z->oname = NULL;\n#ifdef UNICODE_SUPPORT\n      z->uname = z->zuname = z->ouname = NULL;\n#endif\n\n      /* Read file name, extra field and comment field */\n      if (z->nam == 0)\n      {\n        sprintf(errbuf, \"%lu\", (ulg)zcount + 1);\n        zipwarn(\"zero-length name for entry #\", errbuf);\n        if (fix == 1) {\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        }\n#ifndef DEBUG\n        return ZE_FORM;\n#endif\n      }\n      if ((z->iname = malloc(z->nam+1)) ==  NULL ||\n          (z->cext && (z->cextra = malloc(z->cext)) == NULL) ||\n          (z->com && (z->comment = malloc(z->com)) == NULL))\n        return ZE_MEM;\n      if (fread(z->iname, z->nam, 1, in_file) != 1 ||\n          (z->cext && fread(z->cextra, z->cext, 1, in_file) != 1) ||\n          (z->com && fread(z->comment, z->com, 1, in_file) != 1)) {\n        if (fix == 1) {\n          zipwarn(\"error reading entry:  \", strerror(errno));\n          zipwarn(\"skipping this entry...\", \"\");\n          continue;\n        }\n        return ferror(in_file) ? ZE_READ : ZE_EOF;\n      }\n      z->iname[z->nam] = '\\0';                  /* terminate name */\n#ifdef UNICODE_SUPPORT\n      if (unicode_mismatch != 3) {\n        if (z->flg & UTF8_BIT) {\n          char *iname;\n          /* path is UTF-8 */\n          if ((z->uname = malloc(strlen(z->iname) + 1)) == NULL) {\n            zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n            return ZE_MEM;\n          }\n          strcpy(z->uname, z->iname);\n          /* Create a local name.  If UTF-8 system this should also be UTF-8 */\n          iname = utf8_to_local_string(z->uname);\n          if (iname) {\n            free(z->iname);\n            z->iname = iname;\n          }\n          else\n            zipwarn(\"illegal UTF-8 name: \", z->uname);\n        } else {\n          /* check for UTF-8 path extra field */\n          read_Unicode_Path_entry(z);\n        }\n      }\n#endif\n\n#ifdef WIN32\n      /* Input path may be OEM */\n      {\n        unsigned hostver = (z->vem & 0xff);\n        Ext_ASCII_TO_Native(z->iname, (z->vem >> 8), hostver,\n                            ((z->atx & 0xffff0000L) != 0), FALSE);\n      }\n#endif\n\n#ifdef EBCDIC\n      if (z->com)\n         memtoebc(z->comment, z->comment, z->com);\n#endif /* EBCDIC */\n#ifdef WIN32\n      /* Comment may be OEM */\n      {\n        unsigned hostver = (z->vem & 0xff);\n        Ext_ASCII_TO_Native(z->comment, (z->vem >> 8), hostver,\n                            ((z->atx & 0xffff0000L) != 0), FALSE);\n      }\n#endif\n\n#ifdef ZIP64_SUPPORT\n      /* zip64 support 08/31/2003 R.Nausedat                          */\n      /* here, we have to read the len, siz etc values from the CD    */\n      /* entry as we might have to adjust them regarding their        */\n      /* correspronding zip64 extra fields.                           */\n      /* also, we cannot compare the values from the CD entries with  */\n      /* the values from the LH as they might be different.           */\n\n      /* adjust/update siz,len and off (to come: dsk) entries */\n      /* PKZIP does not care of the version set in a CDH: if  */\n      /* there is a zip64 extra field assigned to a CDH PKZIP */\n      /* uses it, we should do so, too.                       */\n      adjust_zip_central_entry(z);\n#endif\n      /* if adjusting for sfx prefix, add the offset */\n      if ((fix ==1 && total_disks == 1) || adjust) z->off += adjust_offset;\n\n      /* Update zipbeg beginning of archive offset, prepare for next header */\n      if (z->dsk == 0 && (!zipbegset || z->off < zipbeg)) {\n        zipbeg = z->off;\n        zipbegset = 1;\n      }\n      zcount++;\n\n      /* Clear actions */\n      z->mark = 0;\n      z->trash = 0;\n#if defined(UNICODE_SUPPORT) && !defined(UTIL)\n      z->zname = in2ex(z->iname);       /* convert to external name */\n      if (z->zname == NULL)\n        return ZE_MEM;\n      if ((z->name = malloc(strlen(z->zname) + 1)) == NULL) {\n        zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n        return ZE_MEM;\n      }\n      strcpy(z->name, z->zname);\n      z->oname = local_to_display_string(z->iname);\n\n# ifdef WIN32\n      z->namew = NULL;\n      z->inamew = NULL;\n      z->znamew = NULL;\n# endif\n\n      if (unicode_mismatch != 3) {\n        if (z->uname) {\n          /* create zuname which is alternate zname for matching based on\n             converted Unicode name */\n          char *name;\n\n          /* Convert UTF-8 to current local character set */\n          name = utf8_to_local_string(z->uname);\n\n          if (name == NULL) {\n            /*\n            zipwarn(\"illegal UTF-8 name: \", z->uname);\n            */\n            /* not able to convert name, so use iname */\n            if ((name = malloc(strlen(z->iname) + 1)) == NULL) {\n              zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n              return ZE_MEM;\n            }\n            strcpy(name, z->iname);\n          }\n\n# ifdef EBCDIC\n          /* z->zname is used for printing and must be coded in native charset */\n          strtoebc(z->zuname, name);\n# else /* !EBCDIC */\n          if ((z->zuname = malloc(strlen(name) + 1)) == NULL) {\n            zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n            return ZE_MEM;\n          }\n          strcpy(z->zuname, name);\n          /* For output to terminal */\n          if (unicode_escape_all) {\n            char *ouname;\n            /* Escape anything not 7-bit ASCII */\n            ouname = utf8_to_escape_string(z->uname);\n            if (ouname)\n              z->ouname = ouname;\n            else {\n              if ((z->ouname = malloc(strlen(name) + 1)) == NULL) {\n                zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n                return ZE_MEM;\n              }\n              strcpy(z->ouname, name);\n            }\n          } else {\n            if ((z->ouname = malloc(strlen(name) + 1)) == NULL) {\n              zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n              return ZE_MEM;\n            }\n            strcpy(z->ouname, name);\n          }\n#  ifdef WIN32\n\n          if (!no_win32_wide) {\n            z->inamew = utf8_to_wchar_string(z->uname);\n            z->znamew = in2exw(z->inamew); /* convert to external name */\n            if (z->znamew == NULL)\n              return ZE_MEM;\n          }\n\n          local_to_oem_string(z->ouname, z->ouname);\n          /* For matching.  There seems to be something lost\n             in the translation from displaying a name in a\n             console window using zip -su on Win32 and using\n             that name in a command line to match what's in\n             the archive.  This is klugy though.\n          */\n          if ((z->wuname = malloc(strlen(z->ouname) + 1)) == NULL) {\n            zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n            return ZE_MEM;\n          }\n          strcpy(z->wuname, z->ouname);\n          oem_to_local_string(z->wuname, z->wuname);\n#  endif /* WIN32 */\n# endif /* ?EBCDIC */\n        } else {\n          /* no uname */\n# ifdef WIN32\n          if (!no_win32_wide) {\n            z->inamew = local_to_wchar_string(z->iname);\n            z->znamew = in2exw(z->inamew); /* convert to external name */\n            if (z->znamew == NULL)\n              return ZE_MEM;\n          }\n# endif\n        }\n      }\n#else /* !(UNICODE_SUPPORT && !UTIL) */\n# ifdef UTIL\n/* We only need z->iname in the utils */\n      z->name = z->iname;\n#  ifdef EBCDIC\n/* z->zname is used for printing and must be coded in native charset */\n      if ((z->zname = malloc(z->nam+1)) ==  NULL) {\n        zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n        return ZE_MEM;\n      }\n      strtoebc(z->zname, z->iname);\n#  else\n      z->zname = z->iname;\n#  endif\n# else /* !UTIL */\n      z->zname = in2ex(z->iname);       /* convert to external name */\n      if (z->zname == NULL)\n        return ZE_MEM;\n      z->name = z->zname;\n# endif /* ?UTIL */\n      if ((z->oname = malloc(strlen(z->zname) + 1)) == NULL) {\n        zipwarn(\"could not allocate memory: scanzipf_reg\", \"\");\n        return ZE_MEM;\n      }\n      strcpy(z->oname, z->zname);\n#endif /* ?(UNICODE_SUPPORT && !UTIL) */\n\n#ifndef UTIL\n      if (verbose && fix == 0)\n        zipoddities(z);\n#endif\n\n      /* Link into list */\n      *x = z;\n      z->nxt = NULL;\n      x = &z->nxt;\n\n    } /* while reading file */\n\n    /* close disk and do next disk */\n    fclose(in_file);\n    in_file = NULL;\n    free(split_path);\n\n    if (!is_signature(sigbuf, \"PK\\01\\02\")) {\n      /* if the last signature is not a CD signature and we get here then\n         hit either the  Zip64 EOCDR or the EOCDR and done */\n      break;\n    }\n\n  } /* for each disk */\n\n  if (zcount != cd_total_entries) {\n    sprintf(errbuf, \"expected %s entries but found %s\",\n      zip_fzofft(cd_total_entries, NULL, \"u\"),\n      zip_fzofft(zcount, NULL, \"u\"));\n    zipwarn(errbuf, \"\");\n    return ZE_FORM;\n  }\n\n  return ZE_OK;\n\n} /* end of function scanzipf_regnew() */\n\n\n\n\n\n\n\n\n/* ---------------------- */\n\n\n\n\n/*\n * readzipfile initializes the global variables that hold the zipfile\n * directory info and opens the zipfile. For the actual zipfile scan,\n * the subroutine scanzipf_reg() or scanzipf_fix() is called,\n * depending on the mode of operation (regular processing, or zipfix mode).\n */\nint readzipfile()\n/*\n   The name of the zip file is pointed to by the global \"zipfile\".\n   The globals zipbeg, zfiles, zcount, and zcomlen are initialized.\n   Return an error code in the ZE_ class.\n*/\n{\n  FILE *f;              /* zip file */\n  int retval;           /* return code */\n  int readable;         /* 1 if zipfile exists and is readable */\n\n  /* Initialize zip file info */\n  zipbeg = 0;\n  zfiles = NULL;                        /* Points to first header */\n  zcount = 0;                           /* number of files */\n  zcomlen = 0;                          /* zip file comment length */\n  retval = ZE_OK;\n  f = NULL;                             /* shut up some compilers */\n  zipfile_exists = 0;\n\n  /* If zip file exists, read headers and check structure */\n#ifdef VMS\n  if (zipfile == NULL || !(*zipfile) || !strcmp(zipfile, \"-\"))\n    return ZE_OK;\n  {\n    int rtype;\n\n    if ((VMSmunch(zipfile, GET_RTYPE, (char *)&rtype) == RMS$_NORMAL) &&\n        (rtype == FAT$C_VARIABLE)) {\n      fprintf(mesg,\n     \"\\n     Error:  zipfile is in variable-length record format.  Please\\n\\\n     run \\\"bilf b %s\\\" to convert the zipfile to fixed-length\\n\\\n     record format.\\n\\n\", zipfile);\n      return ZE_FORM;\n    }\n  }\n  readable = ((f = zfopen(zipfile, FOPR)) != NULL);\n#else /* !VMS */\n  readable = (zipfile != NULL && *zipfile && strcmp(zipfile, \"-\"));\n  if (readable) {\n    readable = ((f = zfopen(zipfile, FOPR)) != NULL);\n  }\n#endif /* ?VMS */\n\n  /* skip check if streaming */\n  if (!readable) {\n    if (!zip_to_stdout && fix != 2 && strcmp(in_path, out_path)) {\n      /* If -O used then in_path must exist */\n      if (fix == 1)\n        zipwarn(\"No .zip file found\\n        \",\n                \"(If all you have are splits (.z01, .z02, ...) and no .zip, try -FF)\");\n      ZIPERR(ZE_OPEN, zipfile);\n    }\n  } else {\n    zipfile_exists = 1;\n  }\n\n#ifdef MVS\n  /* Very nasty special case for MVS.  Just because the zipfile has been\n   * opened for reading does not mean that we can actually read the data.\n   * Typical JCL to create a zipfile is\n   *\n   * //ZIPFILE  DD  DISP=(NEW,CATLG),DSN=prefix.ZIP,\n   * //             SPACE=(CYL,(10,10))\n   *\n   * That creates a VTOC entry with an end of file marker (DS1LSTAR) of zero.\n   * Alas the VTOC end of file marker is only used when the file is opened in\n   * append mode.  When a file is opened in read mode, the \"other\" end of file\n   * marker is used, a zero length data block signals end of file when reading.\n   * With a brand new file which has not been written to yet, it is undefined\n   * what you read off the disk.  In fact you read whatever data was in the same\n   * disk tracks before the zipfile was allocated.  You would be amazed at the\n   * number of application programmers who still do not understand this.  Makes\n   * for interesting and semi-random errors, GIGO.\n   *\n   * Newer versions of SMS will automatically write a zero length block when a\n   * file is allocated.  However not all sites run SMS or they run older levels\n   * so we cannot rely on that.  The only safe thing to do is close the file,\n   * open in append mode (we already know that the file exists), close it again,\n   * reopen in read mode and try to read a data block.  Opening and closing in\n   * append mode will write a zero length block where DS1LSTAR points, making\n   * sure that the VTOC and internal end of file markers are in sync.  Then it\n   * is safe to read data.  If we cannot read one byte of data after all that,\n   * it is a brand new zipfile and must not be read.\n   */\n  if (readable)\n  {\n    char c;\n    fclose(f);\n    /* append mode */\n    if ((f = zfopen(zipfile, \"ab\")) == NULL) {\n      ZIPERR(ZE_OPEN, zipfile);\n    }\n    fclose(f);\n    /* read mode again */\n    if ((f = zfopen(zipfile, FOPR)) == NULL) {\n      ZIPERR(ZE_OPEN, zipfile);\n    }\n    if (fread(&c, 1, 1, f) != 1) {\n      /* no actual data */\n      readable = 0;\n      fclose(f);\n    }\n    else{\n      fseek(f, 0, SEEK_SET);  /* at least one byte in zipfile, back to the start */\n    }\n  }\n#endif /* MVS */\n\n  /* ------------------------ */\n  /* new file read */\n\n\n\n#ifndef UTIL\n  if (fix == 2) {\n    scanzipf_fixnew();\n  }\n  else\n#endif\n  if (readable)\n  {\n    /* close file as the new scan opens the splits as needed */\n    fclose(f);\n# ifndef UTIL\n    retval = (fix == 2 && !adjust) ? scanzipf_fixnew() : scanzipf_regnew();\n# else\n    retval = scanzipf_regnew();\n# endif\n  }\n\n  if (fix != 2 && readable)\n  {\n    /* If one or more files, sort by name */\n    if (zcount)\n    {\n      struct zlist far * far *x;    /* pointer into zsort array */\n      struct zlist far *z;          /* pointer into zfiles linked list */\n      extent zl_size = zcount * sizeof(struct zlist far *);\n\n      if (zl_size / sizeof(struct zlist far *) != zcount ||\n          (x = zsort = (struct zlist far **)malloc(zl_size)) == NULL)\n        return ZE_MEM;\n      for (z = zfiles; z != NULL; z = z->nxt)\n        *x++ = z;\n      qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);\n\n#ifdef UNICODE_SUPPORT\n      /* sort by zuname (local conversion of UTF-8 name) */\n      if (zl_size / sizeof(struct zlist far *) != zcount ||\n          (x = zusort = (struct zlist far **)malloc(zl_size)) == NULL)\n        return ZE_MEM;\n      for (z = zfiles; z != NULL; z = z->nxt)\n        *x++ = z;\n      qsort((char *)zusort, zcount, sizeof(struct zlist far *), zuqcmp);\n#endif\n    }\n  }\n\n  /* ------------------------ */\n\n  return retval;\n} /* end of function readzipfile() */\n\n\nint putlocal(z, rewrite)\n  struct zlist far *z;    /* zip entry to write local header for */\n  int rewrite;            /* did seek to rewrite */\n/* Write a local header described by *z to file *f.  Return an error code\n   in the ZE_ class. */\n{\n  /* If any of compressed size (siz), uncompressed size (len), offset(off), or\n     disk number (dsk) is larger than can fit in the below standard fields then a\n     Zip64 flag value is stored and a Zip64 extra field is created.\n     Only siz and len are in the local header while all can be in the central\n     directory header.\n\n     For the local header if the extra field is created must store both\n     uncompressed and compressed sizes.\n\n     This assumes that for large entries the compressed size won't need a\n     Zip64 extra field if the uncompressed size did not.  This assumption should\n     only fail for a large file of nearly totally uncompressable data.\n\n     If streaming stdin in and use_descriptors is set then always create a Zip64\n     extra field flagging the data descriptor as being in Zip64 format.  This is\n     needed as don't know if need Zip64 or not when need to set Zip64 flag in\n     local header.\n\n     If rewrite is set then don't count bytes written for splits\n   */\n  char *block = NULL;   /* mem block to write to */\n  extent offset = 0;    /* offset into block */\n  extent blocksize = 0; /* size of block */\n#ifdef UNICODE_SUPPORT\n  ush nam = z->nam;     /* size of name to write to header */\n  int use_uname = 0;    /* write uname to header */\n#endif\n#ifdef ZIP64_SUPPORT\n  int streaming_in = 0; /* streaming stdin */\n  int was_zip64 = 0;\n\n  /* If input is stdin then streaming stdin.  No problem with that.\n\n     The problem is updating the local header data in the output once the sizes\n     and crc are known.  If the output is not seekable, then need data descriptors\n     and also need to assume Zip64 will be needed as don't know yet.  Even if the\n     output is seekable, if the input is streamed need to write the Zip64 extra field\n     before writing the data or there won't be room for it later if we need it.\n  */\n  streaming_in = (strcmp(z->name, \"-\") == 0);\n\n  if (!rewrite) {\n    zip64_entry = 0;\n    /* initial local header */\n    if (z->siz > ZIP_UWORD32_MAX || z->len > ZIP_UWORD32_MAX ||\n      force_zip64 == 1 || (force_zip64 != 0 && streaming_in))\n    {\n      /* assume Zip64 */\n      if (force_zip64 == 0) {\n        zipwarn(\"Entry too big:\", z->oname);\n        ZIPERR(ZE_BIG, \"Large entry support disabled with -fz- but needed\");\n      }\n      zip64_entry = 1;        /* header of this entry has a field needing Zip64 */\n      if (z->ver < ZIP64_MIN_VER)\n        z->ver = ZIP64_MIN_VER;\n      was_zip64 = 1;\n    }\n  } else {\n    /* rewrite */\n    was_zip64 = zip64_entry;\n    zip64_entry = 0;\n    if (z->siz > ZIP_UWORD32_MAX || z->len > ZIP_UWORD32_MAX ||\n      force_zip64 == 1 || (force_zip64 != 0 && streaming_in))\n    {\n      /* Zip64 entry */\n      zip64_entry = 1;\n    }\n    if (force_zip64 == 0 && zip64_entry) {\n      /* tried to force into standard entry but needed Zip64 entry */\n      zipwarn(\"Entry too big:\", z->oname);\n      ZIPERR(ZE_BIG, \"Large entry support disabled with -fz- but entry needs\");\n    }\n    /* Normally for a large archive if the input file is less than 4 GB then\n       the compressed or stored version should be less than 4 GB.  If this\n       assumption is wrong this catches it.  This is a problem even if not\n       streaming as the Zip64 extra field was not written and now there's no\n       room for it. */\n    if (was_zip64 == 0 && zip64_entry == 1) {\n      /* guessed wrong and need Zip64 */\n      zipwarn(\"Entry too big:\", z->oname);\n      if (force_zip64 == 0) {\n        ZIPERR(ZE_BIG, \"Compressed/stored entry unexpectedly large - do not use -fz-\");\n      } else {\n        ZIPERR(ZE_BIG, \"Poor compression resulted in unexpectedly large entry - try -fz\");\n      }\n    }\n    if (zip64_entry) {\n      /* Zip64 entry still */\n      /* this archive needs Zip64 (version 4.5 unzipper) */\n      zip64_archive = 1;\n      if (z->ver < ZIP64_MIN_VER)\n        z->ver = ZIP64_MIN_VER;\n    } else {\n      /* it turns out we do not need Zip64 */\n      zip64_entry = 0;\n    }\n    if (was_zip64 && zip64_entry != 1) {\n      z->ver = 20;\n    }\n  }\n\n\n#endif /* ZIP64_SUPPORT */\n\n  /* Instead of writing to the file as we go, to do splits we have to write it\n     to memory and see if it will fit before writing the entire local header.\n     If the local header doesn't fit we need to save it for the next disk.\n   */\n\n#ifdef ZIP64_SUPPORT\n  if (zip64_entry || was_zip64)\n    /* update extra field */\n    add_local_zip64_extra_field( z );\n#endif /* ZIP64_SUPPORT */\n\n#ifdef UNICODE_SUPPORT\n# if 0\n  /* if UTF-8 bit is set on an existing entry, assume it should be */\n  /* clear the UTF-8 flag */\n  z->flg &= ~UTF8_BIT;\n  z->lflg &= ~UTF8_BIT;\n# endif\n\n  if (z->uname) {\n    /* need UTF-8 name */\n    if (utf8_force || using_utf8) {\n      z->lflg |= UTF8_BIT;\n      z->flg |= UTF8_BIT;\n    }\n    if (z->flg & UTF8_BIT) {\n      /* If this flag is set, then restore UTF-8 as path name */\n      use_uname = 1;\n      nam = strlen(z->uname);\n    } else {\n      /* use extra field */\n      add_Unicode_Path_local_extra_field(z);\n    }\n  } else {\n    /* clear UTF-8 bit as not needed */\n    z->flg &= ~UTF8_BIT;\n    z->lflg &= ~UTF8_BIT;\n  }\n#endif\n\n  append_ulong_to_mem(LOCSIG, &block, &offset, &blocksize);     /* local file header signature */\n  append_ushort_to_mem(z->ver, &block, &offset, &blocksize);    /* version needed to extract */\n  append_ushort_to_mem(z->lflg, &block, &offset, &blocksize);   /* general purpose bit flag */\n  append_ushort_to_mem(z->how, &block, &offset, &blocksize);    /* compression method */\n  append_ulong_to_mem(z->tim, &block, &offset, &blocksize);     /* last mod file date time */\n  append_ulong_to_mem(z->crc, &block, &offset, &blocksize);     /* crc-32 */\n#ifdef ZIP64_SUPPORT        /* zip64 support 09/02/2003 R.Nausedat */\n                            /* changes 10/5/03 EG */\n  if (zip64_entry) {\n    append_ulong_to_mem(0xFFFFFFFF, &block, &offset, &blocksize);\t/* compressed size */\n    append_ulong_to_mem(0xFFFFFFFF, &block, &offset, &blocksize);\t/* uncompressed size */\n  } else {\n    append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize);/* compressed size */\n    append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize);/* uncompressed size */\n  }\n#else\n  append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize);    /* compressed size */\n  append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize);    /* uncompressed size */\n#endif\n#ifdef UNICODE_SUPPORT\n  append_ushort_to_mem(nam, &block, &offset, &blocksize);   /* file name length */\n#else\n  append_ushort_to_mem(z->nam, &block, &offset, &blocksize);   /* file name length */\n#endif\n\n  append_ushort_to_mem(z->ext, &block, &offset, &blocksize);    /* extra field length */\n\n#ifdef UNICODE_SUPPORT\n  if (use_uname) {\n    /* path is UTF-8 */\n    append_string_to_mem(z->uname, nam, &block, &offset, &blocksize);\n  } else\n#endif\n#ifdef WIN32_OEM\n  /* store name in OEM character set in archive */\n  if ((z->vem & 0xff00) == 0)\n  {\n    char *oem;\n\n    if ((oem = malloc(strlen(z->iname) + 1)) == NULL)\n      ZIPERR(ZE_MEM, \"putlocal oem\");\n    INTERN_TO_OEM(z->iname, oem);\n    append_string_to_mem(oem, z->nam, &block, &offset, &blocksize); /* file name */\n    free(oem);\n  } else {\n    append_string_to_mem(z->iname, z->nam, &block, &offset, &blocksize); /* file name */\n  }\n#else\n  append_string_to_mem(z->iname, z->nam, &block, &offset, &blocksize); /* file name */\n#endif\n  if (z->ext) {\n    append_string_to_mem(z->extra, z->ext, &block, &offset, &blocksize); /* extra field */\n  }\n\n  /* write the header */\n  if (rewrite == PUTLOCAL_REWRITE) {\n    /* use fwrite as seeked back and not extending the archive */\n    /* also if split_method 1 write to file with local header */\n    if (split_method == 1) {\n      if (fwrite(block, 1, offset, current_local_file) != offset) {\n        free(block);\n        return ZE_TEMP;\n      }\n      /* now can close the split if local header on previous split */\n      if (current_local_disk != current_disk) {\n        close_split(current_local_disk, current_local_file, current_local_tempname);\n        current_local_file = NULL;\n        free(current_local_tempname);\n      }\n    } else {\n      /* not doing splits */\n      if (fwrite(block, 1, offset, y) != offset) {\n        free(block);\n        return ZE_TEMP;\n      }\n    }\n  } else {\n    /* do same if archive not split or split_method 2 with descriptors */\n    /* use bfwrite which counts bytes for splits */\n    if (bfwrite(block, 1, offset, BFWRITE_LOCALHEADER) != offset) {\n      free(block);\n      return ZE_TEMP;\n    }\n  }\n  free(block);\n  return ZE_OK;\n}\n\nint putextended(z)\n  struct zlist far *z;    /* zip entry to write local header for */\n  /* This is the data descriptor.\n   * Write an extended local header described by *z to file *f.\n   * Return an error code in the ZE_ class. */\n{\n  /* write to mem block then write to file 3/10/2005 */\n  char *block = NULL;   /* mem block to write to */\n  extent offset = 0;    /* offset into block */\n  extent blocksize = 0; /* size of block */\n\n  append_ulong_to_mem(EXTLOCSIG, &block, &offset, &blocksize);  /* extended local signature */\n  append_ulong_to_mem(z->crc, &block, &offset, &blocksize);     /* crc-32 */\n#ifdef ZIP64_SUPPORT\n  if (zip64_entry) {\n    /* use Zip64 entries */\n    append_int64_to_mem(z->siz, &block, &offset, &blocksize);   /* compressed size */\n    append_int64_to_mem(z->len, &block, &offset, &blocksize);   /* uncompressed size */\n    /* This is rather klugy as the AppNote handles this poorly.  Typically\n       we don't know at this point if we are writing a Zip64 archive or not,\n       unless a file has needed Zip64.  This is particularly annoying here\n       when deciding the size of the data descriptor (extended local header)\n       fields as the appnote says the uncompressed and compressed sizes\n       should be 8 bytes if the archive is Zip64 and 4 bytes if not.\n\n       One interpretation is the version of the archive is determined from\n       the Version Needed To Extract field in the Zip64 End Of Central Directory\n       record and so either an archive should start as Zip64 and write all data\n       descriptors with 8-byte fields or store everything until all the files\n       are processed and then write everything to the archive as changing the\n       sizes of the data descriptors is messy and just not feasible when\n       streaming to standard output.  This is not easily workable and others\n       use the different interpretation below.\n\n       This was the old thought:\n       We always write a standard data descriptor.  If the file has a large\n       uncompressed or compressed size we set the field to the max field\n       value, which we are defining as flagging the field as having a Zip64\n       value that doesn't fit.  As the CRC happens before the variable size\n       fields the CRC is still valid and can be used to check the file.  We\n       always use deflate if streaming so signatures should not appear in\n       the data and all local header signatures should be valid, allowing a\n       streaming unzip to find entries by local header signatures, if max size\n       values in the data descriptor sizes ignore them, and extract the file and\n       check it using the CRC.  If not streaming the central directory is available\n       so just use those values which are correct.\n\n       After discussions with other groups this is the current thinking:\n\n       Apparent industry interpretation for data descriptors:\n       Data descriptor size is determined for each entry.  If the local header\n       version needed to extract is 45 or higher then the entry can use Zip64\n       data descriptors but more checking is needed.  If Zip64 extra field is\n       present then assume data descriptor is Zip64 and local version needed\n       to extract should be 45 or higher.  If standard data descriptor then\n       local size fields are set to 0 and correct sizes are in standard data descriptor.\n       If Zip64 data descriptor then local sizes are set to -1, Zip64 extra field\n       sizes are set to 0, and the correct sizes are in the Zip64 data descriptor.\n\n       So do this:\n       If an entry is standard and the archive is updatable then seek back and\n       update the local header.  No change.\n\n       If an entry is zip64 and the archive is updatable assume the Zip64 extra\n       field was created and update it.  No change.\n\n       If data descriptors are needed then assume the archive is Zip64.  This is\n       a change and means if ZIP64_SUPPORT is enabled that any non-updatable archive\n       will be in Zip64 format and use Zip64 data descriptors.  This should be\n       compatible with other zippers that depend on the current (though not perfect)\n       AppNote description.\n\n       If anyone has some ideas on this I'd like to hear them.\n\n       3/20/05 EG\n\n       Only assume need Zip64 if the input size is unknown.  If the input size is\n       known we can assume Zip64 if the input is larger than 4 GB and assume not\n       otherwise.  If the output is seekable we still need to create the Zip64\n       extra field if the input size is unknown so we can seek back and update it.\n       12/28/05 EG\n       Updated 5/21/06 EG\n    */\n  } else {\n    /* for encryption */\n    append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize);  /* compressed size */\n    append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize);  /* uncompressed size */\n  }\n#else\n  append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize);    /* compressed size */\n  append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize);    /* uncompressed size */\n#endif\n  /* write the header */\n  if (bfwrite(block, 1, offset, BFWRITE_HEADER) != offset) {\n    free(block);\n    return ZE_TEMP;\n  }\n  free(block);\n  return ZE_OK;\n}\n\nint putcentral(z)\n  struct zlist far *z;    /* zip entry to write central header for */\n/* Write a central header described by *z to file *f.  Return an error code\n   in the ZE_ class. */\n/* output now uses bfwrite which writes global y */\n{\n  /* If any of compressed size (siz), uncompressed size (len), offset(off), or\n     disk number (dsk) is larger than can fit in the below standard fields then a\n     Zip64 flag value is stored and a Zip64 extra field is created.\n     Only siz and len are in the local header while all are in the central directory\n     header.\n\n     For the central directory header just store the fields required.  All previous fields\n     must be stored though.  So can store none (no extra field), just uncompressed size\n     (len), len then siz, len then siz then off, or len then siz then off then dsk, in\n     those orders.  10/6/03 EG\n   */\n\n  /* write to mem block then write to file 3/10/2005 EG */\n  char *block = NULL;   /* mem block to write to */\n  extent offset = 0;    /* offset into block */\n  extent blocksize = 0; /* size of block */\n  uzoff_t off = 0;      /* offset to start of local header */\n  ush nam = z->nam;     /* size of name to write to header */\n#ifdef UNICODE_SUPPORT\n  int use_uname = 0;    /* write uname to header */\n#endif\n\n#ifdef ZIP64_SUPPORT        /* zip64 support 09/02/2003 R.Nausedat */\n  int iRes;\n#endif\n\n#ifdef UNICODE_SUPPORT\n  if (z->uname) {\n    if (utf8_force) {\n      z->flg |= UTF8_BIT;\n    }\n    if (z->flg & UTF8_BIT) {\n      /* If this flag is set, then restore UTF-8 as path name */\n      use_uname = 1;\n      nam = strlen(z->uname);\n    } else {\n      add_Unicode_Path_cen_extra_field(z);\n    }\n  } else {\n    /* clear UTF-8 bit as not needed */\n    z->flg &= ~UTF8_BIT;\n    z->lflg &= ~UTF8_BIT;\n  }\n#endif\n\n  off = z->off;\n\n#ifdef ZIP64_SUPPORT        /* zip64 support 09/02/2003 R.Nausedat */\n  if (z->siz > ZIP_UWORD32_MAX || z->len > ZIP_UWORD32_MAX ||\n      z->off > ZIP_UWORD32_MAX || z->dsk > ZIP_UWORD16_MAX || (force_zip64 == 1))\n  {\n    iRes = add_central_zip64_extra_field(z);\n    if( iRes != ZE_OK )\n      return iRes;\n  }\n\n  append_ulong_to_mem(CENSIG, &block, &offset, &blocksize);     /* central file header signature */\n  append_ushort_to_mem(z->vem, &block, &offset, &blocksize);    /* version made by */\n  append_ushort_to_mem(z->ver, &block, &offset, &blocksize);    /* version needed to extract */\n  append_ushort_to_mem(z->flg, &block, &offset, &blocksize);    /* general purpose bit flag */\n  append_ushort_to_mem(z->how, &block, &offset, &blocksize);    /* compression method */\n  append_ulong_to_mem(z->tim, &block, &offset, &blocksize);     /* last mod file date time */\n  append_ulong_to_mem(z->crc, &block, &offset, &blocksize);     /* crc-32 */\n  if (z->siz > ZIP_UWORD32_MAX)\n  {\n    /* instead of z->siz */\n    append_ulong_to_mem(ZIP_UWORD32_MAX, &block, &offset, &blocksize); /* compressed size */\n  }\n  else\n  {\n    append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize); /* compressed size */\n  }\n  /* if forcing Zip64 just force first ef field */\n  if (z->len > ZIP_UWORD32_MAX || (force_zip64 == 1))\n  {\n    /* instead of z->len */\n    append_ulong_to_mem(ZIP_UWORD32_MAX, &block, &offset, &blocksize); /* uncompressed size */\n  }\n  else\n  {\n    append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize); /* uncompressed size */\n  }\n  append_ushort_to_mem(nam, &block, &offset, &blocksize);       /* file name length */\n  append_ushort_to_mem(z->cext, &block, &offset, &blocksize);   /* extra field length */\n  append_ushort_to_mem(z->com, &block, &offset, &blocksize);    /* file comment length */\n\n  if (z->dsk > ZIP_UWORD16_MAX)\n  {\n    /* instead of z->dsk */\n    append_ushort_to_mem((ush)ZIP_UWORD16_MAX, &block, &offset, &blocksize); /* Zip64 flag */\n  }\n  else\n  {\n    append_ushort_to_mem((ush)z->dsk, &block, &offset, &blocksize);\t/* disk number start */\n  }\n  append_ushort_to_mem(z->att, &block, &offset, &blocksize);    /* internal file attributes */\n  append_ulong_to_mem(z->atx, &block, &offset, &blocksize);     /* external file attributes */\n  if (off > ZIP_UWORD32_MAX)\n  {\n    /* instead of z->off */\n    append_ulong_to_mem(ZIP_UWORD32_MAX, &block, &offset, &blocksize); /* Zip64 flag */\n  }\n  else\n  {\n    append_ulong_to_mem((ulg)off, &block, &offset, &blocksize); /* offset of local header */\n  }\n\n#else /* !ZIP64_SUPPORT */\n\n  append_ulong_to_mem(CENSIG, &block, &offset, &blocksize);     /* central file header signature */\n  append_ushort_to_mem(z->vem, &block, &offset, &blocksize);    /* version made by */\n  append_ushort_to_mem(z->ver, &block, &offset, &blocksize);    /* version needed to extract */\n  append_ushort_to_mem(z->flg, &block, &offset, &blocksize);    /* general purpose bit flag */\n  append_ushort_to_mem(z->how, &block, &offset, &blocksize);    /* compression method */\n  append_ulong_to_mem(z->tim, &block, &offset, &blocksize);     /* last mod file date time */\n  append_ulong_to_mem(z->crc, &block, &offset, &blocksize);     /* crc-32 */\n  append_ulong_to_mem((ulg)z->siz, &block, &offset, &blocksize);  /* compressed size */\n  append_ulong_to_mem((ulg)z->len, &block, &offset, &blocksize);  /* uncompressed size */\n  append_ushort_to_mem(nam, &block, &offset, &blocksize);       /* file name length */\n  append_ushort_to_mem(z->cext, &block, &offset, &blocksize);   /* extra field length */\n  append_ushort_to_mem(z->com, &block, &offset, &blocksize);    /* file comment length */\n  append_ushort_to_mem((ush)z->dsk, &block, &offset, &blocksize); /* disk number start */\n  append_ushort_to_mem(z->att, &block, &offset, &blocksize);    /* internal file attributes */\n  append_ulong_to_mem(z->atx, &block, &offset, &blocksize);     /* external file attributes */\n  append_ulong_to_mem((ulg)off, &block, &offset, &blocksize);   /* relative offset of local header */\n\n#endif /* ZIP64_SUPPORT */\n\n#ifdef EBCDIC\n  if (z->com)\n    memtoasc(z->comment, z->comment, z->com);\n#endif /* EBCDIC */\n\n#ifdef UNICODE_SUPPORT\n  if (use_uname) {\n    /* path is UTF-8 */\n    append_string_to_mem(z->uname, nam, &block, &offset, &blocksize);\n  } else\n#endif\n#ifdef WIN32_OEM\n  /* store name in OEM character set in archive */\n  if ((z->vem & 0xff00) == 0)\n  {\n    char *oem;\n\n    if ((oem = malloc(strlen(z->iname) + 1)) == NULL)\n      ZIPERR(ZE_MEM, \"putcentral oem\");\n    INTERN_TO_OEM(z->iname, oem);\n    append_string_to_mem(oem, z->nam, &block, &offset, &blocksize);\n    free(oem);\n  } else {\n    append_string_to_mem(z->iname, z->nam, &block, &offset, &blocksize);\n  }\n#else\n  append_string_to_mem(z->iname, z->nam, &block, &offset, &blocksize);\n#endif\n\n  if (z->cext) {\n    append_string_to_mem(z->cextra, z->cext, &block, &offset, &blocksize);\n  }\n  if (z->com) {\n#ifdef WIN32_OEM\n    /* store comment in OEM character set in archive */\n    if ((z->vem & 0xff00) == 0)\n    {\n      char *oem;\n\n      if ((oem = malloc(strlen(z->comment) + 1)) == NULL)\n        ZIPERR(ZE_MEM, \"putcentral oem comment\");\n      INTERN_TO_OEM(z->comment, oem);\n      append_string_to_mem(oem, z->com, &block, &offset, &blocksize);\n      free(oem);\n    } else {\n      append_string_to_mem(z->comment, z->com, &block, &offset, &blocksize);\n    }\n#else\n    append_string_to_mem(z->comment, z->com, &block, &offset, &blocksize);\n#endif\n  }\n\n  /* write the header */\n  if (bfwrite(block, 1, offset, BFWRITE_CENTRALHEADER) != offset) {\n    free(block);\n    return ZE_TEMP;\n  }\n  free(block);\n\n  return ZE_OK;\n}\n\n\n/* Write the end of central directory data to file y.  Return an error code\n   in the ZE_ class. */\n\nint putend( OFT( uzoff_t) n,\n            OFT( uzoff_t) s,\n            OFT( uzoff_t) c,\n            OFT( extent) m,\n            OFT( char *) z\n          )\n#ifdef NO_PROTO\n  uzoff_t n;                /* number of entries in central directory */\n  uzoff_t s;                /* size of central directory */\n  uzoff_t c;                /* offset of central directory */\n  extent m;                 /* length of zip file comment (0 if none) */\n  char *z;                  /* zip file comment if m != 0 */\n#endif /* def NO_PROTO */\n{\n#ifdef ZIP64_SUPPORT        /* zip64 support 09/05/2003 R.Nausedat */\n  ush vem;          /* version made by */\n  int iNeedZip64 = 0;\n\n  char *block = NULL;   /* mem block to write to */\n  extent offset = 0;    /* offset into block */\n  extent blocksize = 0; /* size of block */\n\n  /* we have to create a zip64 archive if we have more than 64k - 1 entries,      */\n  /* if the CD is > 4 GB or if the offset to the CD > 4 GB. even if the CD start  */\n  /* is < 4 GB and CD start + CD size > 4GB we do not need a zip64 archive since  */\n  /* the offset entry in the CD tail is still valid.  [note that there are other  */\n  /* reasons for needing a Zip64 archive though, such as an uncompressed          */\n  /* size > 4 GB for an entry but the entry compresses below 4 GB, so the archive */\n  /* is Zip64 but the CD does not need Zip64.]                                    */\n  /* order of the zip/zip64 records in a zip64 archive:                           */\n  /* central directory                                                            */\n  /* zip64 end of central directory record                                        */\n  /* zip64 end of central directory locator                                       */\n  /* end of central directory record                                              */\n\n  /* check zip64_archive instead of force_zip64 3/19/05 */\n\n  zip64_eocd_disk = current_disk;\n  zip64_eocd_offset = bytes_this_split;\n\n  if( n > ZIP_UWORD16_MAX || s > ZIP_UWORD32_MAX || c > ZIP_UWORD32_MAX ||\n      zip64_archive )\n  {\n    ++iNeedZip64;\n    /* write zip64 central dir tail:  */\n    /*                                    */\n    /* 4 bytes   zip64 end of central dir signature (0x06064b50) */\n    append_ulong_to_mem((ulg)ZIP64_CENTRAL_DIR_TAIL_SIG, &block, &offset, &blocksize);\n    /* 8 bytes   size of zip64 end of central directory record */\n    /* a fixed size unless the end zip64 extensible data sector is used. - 3/19/05 EG */\n    /* also note that AppNote 6.2 creates version 2 of this record for\n       central directory encryption - 3/19/05 EG */\n    append_int64_to_mem((zoff_t)ZIP64_CENTRAL_DIR_TAIL_SIZE, &block, &offset, &blocksize);\n\n    /* 2 bytes   version made by */\n    vem = OS_CODE + Z_MAJORVER * 10 + Z_MINORVER;\n    append_ushort_to_mem(vem, &block, &offset, &blocksize);\n\n    /* APPNOTE says that zip64 archives should have at least version 4.5\n       in the \"version needed to extract\" field */\n    /* 2 bytes   version needed to extract */\n    append_ushort_to_mem(ZIP64_MIN_VER, &block, &offset, &blocksize);\n\n    /* 4 bytes   number of this disk */\n    append_ulong_to_mem(current_disk, &block, &offset, &blocksize);\n    /* 4 bytes   number of the disk with the start of the central directory */\n    append_ulong_to_mem(cd_start_disk, &block, &offset, &blocksize);\n    /* 8 bytes   total number of entries in the central directory on this disk */\n    append_int64_to_mem(cd_entries_this_disk, &block, &offset, &blocksize);\n    /* 8 bytes   total number of entries in the central directory */\n    append_int64_to_mem(n, &block, &offset, &blocksize);\n    /* 8 bytes   size of the central directory */\n    append_int64_to_mem(s, &block, &offset, &blocksize);\n    /* 8 bytes   offset of start of central directory with respect to the starting disk number */\n    append_int64_to_mem(cd_start_offset, &block, &offset, &blocksize);\n    /* zip64 extensible data sector    (variable size), we don't use it... */\n\n    /* write zip64 end of central directory locator:  */\n    /*                                                    */\n    /* 4 bytes   zip64 end of central dir locator  signature (0x07064b50) */\n    append_ulong_to_mem(ZIP64_CENTRAL_DIR_TAIL_END_SIG, &block, &offset, &blocksize);\n    /* 4 bytes   number of the disk with the start of the zip64 end of central directory */\n    append_ulong_to_mem(zip64_eocd_disk, &block, &offset, &blocksize);\n    /* 8 bytes   relative offset of the zip64 end of central directory record, that is */\n    /* offset of CD + CD size */\n    append_int64_to_mem(zip64_eocd_offset, &block, &offset, &blocksize);\n    /* PUTLLG(l64Temp, f); */\n    /* 4 bytes   total number of disks */\n    append_ulong_to_mem(current_disk + 1, &block, &offset, &blocksize);\n  }\n\n  /* end of central dir signature */\n  append_ulong_to_mem(ENDSIG, &block, &offset, &blocksize);\n    /* mv archives to come :)         */\n    /* for now use n for all          */\n    /* 2 bytes    number of this disk */\n  if (current_disk < 0xFFFF)\n    append_ushort_to_mem((ush)current_disk, &block, &offset, &blocksize);\n  else\n    append_ushort_to_mem((ush)0xFFFF, &block, &offset, &blocksize);\n  /* 2 bytes    number of the disk with the start of the central directory */\n  if (cd_start_disk == (ulg)-1)\n    cd_start_disk = 0;\n  if (cd_start_disk < 0xFFFF)\n    append_ushort_to_mem((ush)cd_start_disk, &block, &offset, &blocksize);\n  else\n    append_ushort_to_mem((ush)0xFFFF, &block, &offset, &blocksize);\n  /* 2 bytes    total number of entries in the central directory on this disk */\n  if (cd_entries_this_disk < 0xFFFF)\n    append_ushort_to_mem((ush)cd_entries_this_disk, &block, &offset, &blocksize);\n  else\n    append_ushort_to_mem((ush)0xFFFF, &block, &offset, &blocksize);\n  /* 2 bytes    total number of entries in the central directory */\n  if (total_cd_entries < 0xFFFF)\n    append_ushort_to_mem((ush)total_cd_entries, &block, &offset, &blocksize);\n  else\n    append_ushort_to_mem((ush)0xFFFF, &block, &offset, &blocksize);\n  if( s > ZIP_UWORD32_MAX )\n    /* instead of s */\n    append_ulong_to_mem(ZIP_UWORD32_MAX, &block, &offset, &blocksize);\n  else\n    /* 4 bytes    size of the central directory */\n    append_ulong_to_mem((ulg)s, &block, &offset, &blocksize);\n  if(force_zip64 == 1 || cd_start_offset > ZIP_UWORD32_MAX)\n    /* instead of cd_start_offset */\n    append_ulong_to_mem(ZIP_UWORD32_MAX, &block, &offset, &blocksize);\n  else\n    /* 4 bytes    offset of start of central directory with respect to the starting disk number */\n    append_ulong_to_mem((ulg)cd_start_offset, &block, &offset, &blocksize);\n\n#else /* !ZIP64_SUPPORT */\n  char *block = NULL;   /* mem block to write to */\n  extent offset = 0;    /* offset into block */\n  extent blocksize = 0; /* size of block */\n\n  /* end of central dir signature */\n  append_ulong_to_mem(ENDSIG, &block, &offset, &blocksize);\n  /* 2 bytes    number of this disk */\n  append_ushort_to_mem((ush)current_disk, &block, &offset, &blocksize);\n  /* 2 bytes    number of the disk with the start of the central directory */\n  append_ushort_to_mem((ush)cd_start_disk, &block, &offset, &blocksize);\n  /* 2 bytes    total number of entries in the central directory on this disk */\n  append_ushort_to_mem((ush)cd_entries_this_disk, &block, &offset, &blocksize);\n  /* 2 bytes    total number of entries in the central directory */\n  append_ushort_to_mem((ush)n, &block, &offset, &blocksize);\n  /* 4 bytes    size of the central directory */\n  append_ulong_to_mem((ulg)s, &block, &offset, &blocksize);\n  /* 4 bytes    offset of start of central directory with respect to the starting disk number */\n  append_ulong_to_mem((ulg)cd_start_offset, &block, &offset, &blocksize);\n#endif /* ZIP64_SUPPORT */\n\n  /* size of comment */\n  append_ushort_to_mem((ush)m, &block, &offset, &blocksize);\n  /* Write the comment, if any */\n#ifdef EBCDIC\n  memtoasc(z, z, m);\n#endif\n  if (m) {\n    /* PKWare defines the archive comment to be ASCII only so no OEM conversion */\n    append_string_to_mem(z, m, &block, &offset, &blocksize);\n  }\n\n  /* write the block */\n  if (bfwrite(block, 1, offset, BFWRITE_HEADER) != offset) {\n    free(block);\n    return ZE_TEMP;\n  }\n  free(block);\n\n#ifdef HANDLE_AMIGA_SFX\n  if (amiga_sfx_offset && zipbeg /* -J zeroes this */) {\n    s = zftello(y);\n    while (s & 3) s++, putc(0, f);   /* final marker must be longword aligned */\n    PUTLG(0xF2030000 /* 1010 in Motorola byte order */, f);\n    c = (s - amiga_sfx_offset - 4) / 4;  /* size of archive part in longwords */\n    if (zfseeko(y, amiga_sfx_offset, SEEK_SET) != 0)\n      return ZE_TEMP;\n    c = ((c >> 24) & 0xFF) | ((c >> 8) & 0xFF00)\n         | ((c & 0xFF00) << 8) | ((c & 0xFF) << 24);     /* invert byte order */\n    PUTLG(c, y);\n    zfseeko(y, 0, SEEK_END);                                  /* just in case */\n  }\n#endif\n\n  return ZE_OK;\n} /* end function putend() */\n\n\n\n/* Note: a zip \"entry\" includes a local header (which includes the file\n   name), an encryption header if encrypting, the compressed data\n   and possibly an extended local header. */\n\nint zipcopy(z)\n  struct zlist far *z;    /* zip entry to copy */\n/* Copy the zip entry described by *z from in_file to y.  Return an\n   error code in the ZE_ class.  Also update tempzn by the number of bytes\n   copied. */\n/* Now copies to global output file y */\n/* Handle entries that span disks */\n/* If fix == 2, assume in_file is pointing to a local header and fill\n   in z from local header */\n{\n  uzoff_t n;            /* holds local header offset */\n  ulg e = 0;            /* extended local header size */\n  ulg start_disk = 0;\n  uzoff_t start_offset = 0;\n  char *split_path;\n  char buf[LOCHEAD + 1];\n  struct zlist far *localz;\n  int r;\n\n\n  Trace((stderr, \"zipcopy %s\\n\", z->zname));\n\n  /* if fix == 2 assume in_file open and pointing at local header */\n  if (fix != 2) {\n    start_disk = z->dsk;\n    start_offset = z->off;\n\n    /* don't assume reading the right disk */\n\n    /* if start not on current disk then close current disk */\n    if (start_disk != current_in_disk) {\n      if (in_file) {\n        fclose(in_file);\n        in_file = NULL;\n      }\n    }\n\n    current_in_disk = start_disk;\n\n    /* disks are archive.z01, archive.z02, ..., archive.zip */\n    split_path = get_in_split_path(in_path, current_in_disk);\n\n    if (in_file == NULL) {\n      while ((in_file = zfopen(split_path, FOPR)) == NULL) {\n        /* could not open split */\n\n        if (!noisy) {\n          ZIPERR(ZE_OPEN, split_path);\n        }\n\n        /* Ask for directory with split.  Updates global in_path */\n        r = ask_for_split_read_path(start_disk);\n        if (r == ZE_ABORT) {\n          /* user abort */\n          return ZE_ABORT;\n        } else if ((fix == 1 || fix == 2) && r == ZE_FORM) {\n          /* user asks to skip this disk */\n          return ZE_FORM;\n        }\n        free(split_path);\n        split_path = get_in_split_path(in_path, start_disk);\n      }\n    }\n\n    if (zfseeko(in_file, start_offset, SEEK_SET) != 0) {\n      fclose(in_file);\n      in_file = NULL;\n      zipwarn(\"reading archive fseek: \", strerror(errno));\n      return ZE_READ;\n    }\n  } /* fix != 2 */\n\n  if (fix != 2 && !at_signature(in_file, \"PK\\03\\04\")) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"Did not find entry for \", z->iname);\n    return ZE_FORM;\n  }\n\n  /* read local header */\n  if (fread(buf, LOCHEAD, 1, in_file) != 1) {\n    int f = ferror(in_file);\n    zipwarn(\"reading local entry: \", strerror(errno));\n    if (fix != 2)\n      fclose(in_file);\n    return f ? ZE_READ : ZE_EOF;\n  }\n\n  /* Local Header\n       local file header signature     4 bytes  (0x04034b50)\n       version needed to extract       2 bytes\n       general purpose bit flag        2 bytes\n       compression method              2 bytes\n       last mod file time              2 bytes\n       last mod file date              2 bytes\n       crc-32                          4 bytes\n       compressed size                 4 bytes\n       uncompressed size               4 bytes\n       file name length                2 bytes\n       extra field length              2 bytes\n\n       file name (variable size)\n       extra field (variable size)\n   */\n\n  if ((localz = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL) {\n    zipwarn(\"reading entry\", \"\");\n    if (fix != 2)\n      fclose(in_file);\n    return ZE_MEM;\n  }\n\n  localz->ver = SH(LOCVER + buf);\n  localz->lflg = SH(LOCFLG + buf);\n  localz->how = SH(LOCHOW + buf);\n  localz->tim = LG(LOCTIM + buf);          /* time and date into one long */\n  localz->crc = LG(LOCCRC + buf);\n  localz->nam = SH(LOCNAM + buf);\n  localz->ext = SH(LOCEXT + buf);\n  if (fix == 2) {\n    localz->siz = LG(LOCSIZ + buf);\n    localz->len = LG(LOCLEN + buf);\n  }\n\n  if (fix == 2) {\n    /* Do some sanity checks to make reasonably sure this is a local header */\n    ush os = localz->ver >> 8;\n    ush pkver = localz->ver - os;\n\n    /* OS - currently 0 - 18 (AppNote 6.3) and 30 (ATHEOS) */\n    if (os > 40) {\n      sprintf(errbuf, \"Illegal host system mapping in local header:  %d\", os);\n      zipwarn(errbuf, \"\");\n      zipwarn(\"Skipping:  \", z->iname);\n      return ZE_FORM;\n    }\n    /* PK Version - currently 10 - 62 (AppNote 6.2.2) */\n    /* If PKZip central directory encryption is used (62), the local header\n       values could be masked values.  Specifically, as of AppNote 6.2.2\n       the time, crc-32, and uncompressed file size are masked and the\n       file name is also replaced with a hex entry count.  Should\n       still be able to recover the entries, but they may be unreadable\n       without the 62 support fields. */\n    if (pkver > 100) {\n      sprintf(errbuf, \"Illegal PK version mapping in local header:  %d\", pkver);\n      zipwarn(errbuf, \"\");\n      zipwarn(\"Skipping:  \", z->iname);\n      return ZE_FORM;\n    }\n    /* Currently compression method is defined as 0 - 19 and 98 (AppNote 6.3) */\n    /* We can still copy an entry we can't read, but something over 200 is\n       probably illegal */\n    if (localz->how > 200) {\n      sprintf(errbuf, \"Unrecognized compression method in local header:  %d\", localz->how);\n      zipwarn(errbuf, \"\");\n      zipwarn(\"Skipping:  \", z->iname);\n      return ZE_FORM;\n    }\n\n    /* It's hard to make guesses on the other fields.  Suggestions welcome. */\n  }\n\n  /* Initialize all fields pointing to malloced data to NULL */\n  localz->zname = localz->name = localz->iname = localz->extra = NULL;\n  localz->oname = NULL;\n#ifdef UNICODE_SUPPORT\n  localz->uname = NULL;\n#endif\n\n  /* Read file name, extra field and comment field */\n  if ((localz->iname = malloc(localz->nam+1)) ==  NULL ||\n      (localz->ext && (localz->extra = malloc(localz->ext)) == NULL))\n    return ZE_MEM;\n  if (fread(localz->iname, localz->nam, 1, in_file) != 1 ||\n      (localz->ext && fread(localz->extra, localz->ext, 1, in_file) != 1))\n    return ferror(in_file) ? ZE_READ : ZE_EOF;\n  localz->iname[localz->nam] = '\\0';                  /* terminate name */\n  if ((localz->name = malloc(localz->nam+1)) ==  NULL)\n    return ZE_MEM;\n  strcpy(localz->name, localz->iname);\n\n#ifdef ZIP64_SUPPORT\n  zip64_entry = adjust_zip_local_entry(localz);\n#endif\n\n  localz->vem = 0;\n  if (fix != 2) {\n    /* Need vem to determine if iname is Win32 OEM name */\n    localz->vem = z->vem;\n\n#ifdef UNICODE_SUPPORT\n    if (unicode_mismatch != 3) {\n      if (z->flg & UTF8_BIT) {\n        char *iname;\n        /* path is UTF-8 */\n        localz->uname = localz->iname;\n        iname = utf8_to_local_string(localz->uname);\n        if (iname == NULL) {\n          /* a bad UTF-8 character in name likely - go with (probably messed up) uname */\n          if ((localz->iname = malloc(strlen(localz->uname) + 1)) == NULL) {\n            return ZE_MEM;\n          }\n          strcpy(localz->iname, localz->uname);\n        } else {\n          /* go with local character set iname */\n          localz->iname = iname;\n        }\n      } else {\n        /* check for UTF-8 path extra field */\n        read_Unicode_Path_local_entry(localz);\n      }\n    }\n#endif\n\n#ifdef WIN32_OEM\n      /* If fix == 2 and reading local headers first, vem is not in the local\n         header so we don't know when to do OEM translation, as the ver field\n         is set to MSDOS (0) by all unless something specific is needed.\n         However, if local header has a Unicode path extra field, we can get\n         the real file name from there. */\n    if ((z->vem & 0xff00) == 0)\n      /* assume archive name is OEM if from DOS */\n      oem_to_local_string(localz->iname, localz->iname);\n#endif\n  }\n\n  if (fix == 2) {\n# ifdef WIN32\n#  ifdef UNICODE_SUPPORT\n    localz->namew = NULL;\n    localz->inamew = NULL;\n    localz->znamew = NULL;\n    z->namew = NULL;\n    z->inamew = NULL;\n    z->znamew = NULL;\n#  endif\n# endif\n    /* set z from localz */\n    z->flg = localz->lflg;\n    z->len = localz->len;\n    z->siz = localz->siz;\n\n  } else {\n    /* Compare localz to z */\n    if (localz->ver != z->ver) {\n      zipwarn(\"Local Version Needed To Extract does not match CD: \", z->iname);\n    }\n    if (localz->lflg != z->flg) {\n      zipwarn(\"Local Entry Flag does not match CD: \", z->iname);\n    }\n    if (!(z->flg & 8)) {\n      if (localz->crc != z->crc) {\n        zipwarn(\"Local Entry CRC does not match CD: \", z->iname);\n      }\n    }\n    if (fix != 3 && strcmp(localz->iname, z->iname) != 0) {\n      zipwarn(\"Local Entry name does not match CD: \", z->iname);\n    }\n\n    /* as copying get uncompressed and compressed sizes from central directory */\n    localz->len = z->len;\n    localz->siz = z->siz;\n  }\n\n#if 0\n  if (fix > 1) {\n    if (zfseeko(in_file, z->off + n, SEEK_SET)) /* seek to compressed data */\n      return ferror(in_file) ? ZE_READ : ZE_EOF;\n\n    if (fix > 2) {\n      /* Update length of entry's name, it may have been changed.  This is\n         needed to support the ZipNote ability to rename archive entries. */\n      z->nam = strlen(z->iname);\n      n = (uzoff_t)((LOCHEAD) + (ulg)z->nam + (ulg)z->ext);\n    }\n\n    /* do not trust the old compressed size */\n    if (putlocal(z, PUTLOCAL_WRITE) != ZE_OK)\n      return ZE_TEMP;\n\n    z->off = tempzn;\n    tempzn += n;\n    n = z->siz;\n  } else {\n    if (zfseeko(in_file, z->off, SEEK_SET))     /* seek to local header */\n      return ferror(in_file) ? ZE_READ : ZE_EOF;\n\n    z->off = tempzn;\n    n += z->siz;\n  }\n#endif\n\n  /* from zipnote */\n  if (fix == 3) {\n    /* Update length of entry's name, as it may have been changed.  This is\n       needed to support the ZipNote ability to rename archive entries. */\n    localz->nam = z->nam = strlen(z->iname);\n    /* update local name */\n    free(localz->iname);\n    if ((localz->iname = malloc(strlen(z->iname) + 1)) == NULL) {\n      zipwarn(\"out of memory in zipcopy\", \"\");\n      return ZE_MEM;\n    }\n    strcpy(localz->iname, z->iname);\n  }\n\n  /* update disk and offset */\n  z->dsk = current_disk;\n  z->off = bytes_this_split;\n\n  /* copy the compressed data and the extended local header if there is one */\n\n  /* copy the compressed data.  We recreate the local header as the local\n     header can't be split and putlocal ensures it won't.  Also, since we\n     use siz and len from the central directory, we don't need the extended\n     local header if there is one, unless the file is encrypted as then the\n     extended header is used to indicate crypt head uses file time instead\n     of crc as the password check.\n\n     If fix = 2 then we don't have the central directory yet so keep\n     any data descriptors. */\n\n  if (fix != 2 && !(z->flg & 1)) {\n    /* Not encrypted */\n    localz->flg = z->flg &= ~8;\n    z->lflg = localz->lflg &= ~8;\n  }\n\n  e = 0;\n  if (z->lflg & 8) {\n#ifdef ZIP64_SUPPORT\n    if (zip64_entry)\n      e = 24;\n    else\n#endif\n      e = 16;\n  }\n  /* 4 is signature */\n  n = 4 + (uzoff_t)((LOCHEAD) + (ulg)(localz->nam) + (ulg)(localz->ext));\n\n  n += e + z->siz;\n  tempzn += n;\n\n  /* Output name */\n  if (fix == 2) {\n    if ((z->oname = malloc(strlen(localz->iname) + 1)) == NULL) {\n      return ZE_MEM;\n    }\n    strcpy(z->oname, localz->iname);\n#ifndef UTIL\n# ifdef WIN32\n    /* Win9x console always uses OEM character coding, and\n       WinNT console is set to OEM charset by default, too */\n    _INTERN_OEM(z->oname);\n# endif\n#endif\n    sprintf(errbuf, \" copying: %s \", z->oname);\n    zipmessage_nl(errbuf, 0);\n  }\n\n  if (fix == 2)\n    z->crc = localz->crc;\n  else\n    localz->crc = z->crc;\n\n  if (putlocal(localz, PUTLOCAL_WRITE) != ZE_OK)\n      return ZE_TEMP;\n\n  /*\n  if (zfseeko(in_file, start_offset, SEEK_SET) != 0) {\n    fclose(in_file);\n    in_file = NULL;\n    zipwarn(\"reading archive fseek: \", strerror(errno));\n    return ZE_READ;\n  }\n  */\n\n  /* copy the data */\n  if (fix == 2 && localz->lflg & 8)\n    /* read to data descriptor */\n    r = bfcopy((uzoff_t) -2);\n  else\n    r = bfcopy(localz->siz);\n\n  if (r == ZE_ABORT) {\n      if (localz->ext) free(localz->extra);\n      if (localz->nam) free(localz->iname);\n      if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n      if (localz->uname) free(localz->uname);\n#endif\n      free(localz);\n      ZIPERR(ZE_ABORT, \"Could not find split\");\n  }\n\n  if (r == ZE_EOF || skip_this_disk) {\n      /* missing disk */\n      zipwarn(\"aborting: \", z->oname);\n\n      if (r == ZE_OK)\n        r = ZE_FORM;\n\n      if (fix == 2) {\n#ifdef DEBUG\n        zoff_t here = zftello(y);\n#endif\n\n        /* fix == 2 skips right to next disk */\n        skip_this_disk = 0;\n\n        /* seek back in output to start of this entry so can overwrite */\n        if (zfseeko(y, current_local_offset, SEEK_SET) != 0) {\n          ZIPERR(ZE_WRITE, \"seek failed on output file\");\n        }\n        bytes_this_split = current_local_offset;\n        tempzn = current_local_offset;\n      }\n\n      /* tell scan to skip this entry */\n      if (localz->ext) free(localz->extra);\n      if (localz->nam) free(localz->iname);\n      if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n      if (localz->uname) free(localz->uname);\n#endif\n      free(localz);\n      return r;\n  }\n\n  if (fix == 2 && z->flg & 8) {\n    /* this entry should have a data descriptor */\n    /* only -FF needs to read the descriptor as other modes\n       rely on the central directory */\n    if (des_good) {\n      /* found an apparently good data descriptor */\n      localz->crc = des_crc;\n      localz->siz = des_csize;\n      localz->len = des_usize;\n    } else {\n      /* no end to this entry found */\n      zipwarn(\"no end of stream entry found: \", z->oname);\n      zipwarn(\"rewinding and scanning for later entries\", \"\");\n\n      /* seek back in output to start of this entry so can overwrite */\n      if (zfseeko(y, current_local_offset, SEEK_SET) != 0){\n\n      }\n\n      /* tell scan to skip this entry */\n      if (localz->ext) free(localz->extra);\n      if (localz->nam) free(localz->iname);\n      if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n      if (localz->uname) free(localz->uname);\n#endif\n      free(localz);\n      return ZE_FORM;\n    }\n  }\n\n  if (z->flg & 8) {\n    putextended(localz);\n  }\n\n  /* now can close the split if local header on previous split */\n  if (split_method == 1 && current_local_disk != current_disk) {\n    close_split(current_local_disk, current_local_file, current_local_tempname);\n    current_local_file = NULL;\n    free(current_local_tempname);\n  }\n\n  /* update local header and close start split */\n  /* to use this need to seek back, do this, then come back\n  if (putlocal(localz, PUTLOCAL_REWRITE) != ZE_OK)\n    r = ZE_TEMP;\n  */\n\n  if (fix == 2) {\n    z->ver = localz->ver;\n    z->how = localz->how;\n    z->tim = localz->tim;\n    z->crc = localz->crc;\n    z->lflg = localz->lflg;\n    z->flg = localz->lflg;\n    z->len = localz->len;\n    z->siz = localz->siz;\n    z->nam = localz->nam;\n    z->ext = localz->ext;\n    z->extra = localz->extra;\n    /* copy local extra fields to central directory for now */\n    z->cext = localz->ext;\n    z->cextra = NULL;\n    if (localz->ext) {\n      if ((z->cextra = malloc(localz->ext + 1)) == NULL) {\n      return ZE_MEM;\n      }\n      strcpy(z->cextra, localz->extra);\n    }\n    z->com = 0;\n    z->att = 0;\n    z->atx = 0;\n    z->name = localz->name;\n    z->iname = localz->iname;\n#ifdef UNICODE_SUPPORT\n    z->uname = localz->uname;\n#endif\n    if ((z->zname = malloc(localz->nam + 1)) == NULL) {\n      return ZE_MEM;\n    }\n    strcpy(z->zname, z->iname);\n  } else {\n    if (localz->ext) free(localz->extra);\n    if (localz->nam) free(localz->iname);\n    if (localz->nam) free(localz->name);\n#ifdef UNICODE_SUPPORT\n    if (localz->uname) free(localz->uname);\n#endif\n    free(localz);\n  }\n\n  if (fix == 2) {\n    sprintf(errbuf, \" (%s bytes)\", zip_fzofft(z->siz, NULL, \"u\"));\n    zipmessage_nl(errbuf, 1);\n\n    if (r == ZE_READ) {\n      zipwarn(\"entry truncated: \", z->oname);\n      sprintf(errbuf, \"expected compressed/stored size %s, actual %s\",\n              zip_fzofft(localz->siz, NULL, \"u\"), zip_fzofft(bytes_this_entry, NULL, \"u\"));\n      zipwarn(errbuf, \"\");\n    }\n  }\n\n  return r;\n}\n\n\n\n#ifndef UTIL\n\n#ifdef USE_EF_UT_TIME\n\nlocal int ef_scan_ut_time(ef_buf, ef_len, ef_is_cent, z_utim)\nchar *ef_buf;                   /* buffer containing extra field */\nextent ef_len;                  /* total length of extra field */\nint ef_is_cent;                 /* flag indicating \"is central extra field\" */\niztimes *z_utim;                /* return storage: atime, mtime, ctime */\n/* This function scans the extra field for EF_TIME or EF_IZUNIX blocks\n * containing Unix style time_t (GMT) values for the entry's access, creation\n * and modification time.\n * If a valid block is found, all time stamps are copied to the iztimes\n * structure.\n * The presence of an EF_TIME or EF_IZUNIX2 block results in ignoring\n * all data from probably present obsolete EF_IZUNIX blocks.\n * If multiple blocks of the same type are found, only the information from\n * the last block is used.\n * The return value is the EF_TIME Flags field (simulated in case of an\n * EF_IZUNIX block) or 0 in case of failure.\n */\n{\n  int flags = 0;\n  unsigned eb_id;\n  extent eb_len;\n  int have_new_type_eb = FALSE;\n\n  if (ef_len == 0 || ef_buf == NULL)\n    return 0;\n\n  Trace((stderr,\"\\nef_scan_ut_time: scanning extra field of length %u\\n\",\n         (unsigned)ef_len));\n  while (ef_len >= EB_HEADSIZE) {\n    eb_id = SH(EB_ID + ef_buf);\n    eb_len = SH(EB_LEN + ef_buf);\n\n    if (eb_len > (ef_len - EB_HEADSIZE)) {\n      /* Discovered some extra field inconsistency! */\n      Trace((stderr,\"ef_scan_ut_time: block length %u > rest ef_size %u\\n\",\n             (unsigned)eb_len, (unsigned)(ef_len - EB_HEADSIZE)));\n      break;\n    }\n\n    switch (eb_id) {\n      case EF_TIME:\n        flags &= ~0x00ff;       /* ignore previous IZUNIX or EF_TIME fields */\n        have_new_type_eb = TRUE;\n        if ( eb_len >= EB_UT_MINLEN && z_utim != NULL) {\n           unsigned eb_idx = EB_UT_TIME1;\n           Trace((stderr,\"ef_scan_ut_time: Found TIME extra field\\n\"));\n           flags |= (ef_buf[EB_HEADSIZE+EB_UT_FLAGS] & 0x00ff);\n           if ((flags & EB_UT_FL_MTIME)) {\n              if ((eb_idx+4) <= eb_len) {\n                 z_utim->mtime = LG((EB_HEADSIZE+eb_idx) + ef_buf);\n                 eb_idx += 4;\n                 Trace((stderr,\"  Unix EF modtime = %ld\\n\", z_utim->mtime));\n              } else {\n                 flags &= ~EB_UT_FL_MTIME;\n                 Trace((stderr,\"  Unix EF truncated, no modtime\\n\"));\n              }\n           }\n           if (ef_is_cent) {\n              break;            /* central version of TIME field ends here */\n           }\n           if (flags & EB_UT_FL_ATIME) {\n              if ((eb_idx+4) <= eb_len) {\n                 z_utim->atime = LG((EB_HEADSIZE+eb_idx) + ef_buf);\n                 eb_idx += 4;\n                 Trace((stderr,\"  Unix EF acctime = %ld\\n\", z_utim->atime));\n              } else {\n                 flags &= ~EB_UT_FL_ATIME;\n              }\n           }\n           if (flags & EB_UT_FL_CTIME) {\n              if ((eb_idx+4) <= eb_len) {\n                 z_utim->ctime = LG((EB_HEADSIZE+eb_idx) + ef_buf);\n                 /* eb_idx += 4; */  /* superfluous for now ... */\n                 Trace((stderr,\"  Unix EF cretime = %ld\\n\", z_utim->ctime));\n              } else {\n                 flags &= ~EB_UT_FL_CTIME;\n              }\n           }\n        }\n        break;\n\n      case EF_IZUNIX2:\n        if (!have_new_type_eb) {\n           flags &= ~0x00ff;    /* ignore any previous IZUNIX field */\n           have_new_type_eb = TRUE;\n        }\n        break;\n\n      case EF_IZUNIX:\n        if (eb_len >= EB_UX_MINLEN) {\n           Trace((stderr,\"ef_scan_ut_time: Found IZUNIX extra field\\n\"));\n           if (have_new_type_eb) {\n              break;            /* Ignore IZUNIX extra field block ! */\n           }\n           z_utim->atime = LG((EB_HEADSIZE+EB_UX_ATIME) + ef_buf);\n           z_utim->mtime = LG((EB_HEADSIZE+EB_UX_MTIME) + ef_buf);\n           Trace((stderr,\"  Unix EF access time = %ld\\n\",z_utim->atime));\n           Trace((stderr,\"  Unix EF modif. time = %ld\\n\",z_utim->mtime));\n           flags |= (EB_UT_FL_MTIME | EB_UT_FL_ATIME);  /* signal success */\n        }\n        break;\n\n      case EF_THEOS:\n/*      printf(\"Not implemented yet\\n\"); */\n        break;\n\n      default:\n        break;\n    }\n    /* Skip this extra field block */\n    ef_buf += (eb_len + EB_HEADSIZE);\n    ef_len -= (eb_len + EB_HEADSIZE);\n  }\n\n  return flags;\n}\n\nint get_ef_ut_ztime(z, z_utim)\nstruct zlist far *z;\niztimes *z_utim;\n{\n  int r;\n\n#ifdef IZ_CHECK_TZ\n  if (!zp_tz_is_valid) return 0;\n#endif\n\n  /* First, scan local extra field. */\n  r = ef_scan_ut_time(z->extra, z->ext, FALSE, z_utim);\n\n  /* If this was not successful, try central extra field, but only if\n     it is really different. */\n  if (!r && z->cext > 0 && z->cextra != z->extra)\n    r = ef_scan_ut_time(z->cextra, z->cext, TRUE, z_utim);\n\n  return r;\n}\n\n#endif /* USE_EF_UT_TIME */\n\n\nlocal void cutpath(p, delim)\nchar *p;                /* path string */\nint delim;              /* path component separator char */\n/* Cut the last path component off the name *p in place.\n * This should work on both internal and external names.\n */\n{\n  char *r;              /* pointer to last path delimiter */\n\n#ifdef VMS                      /* change [w.x.y]z to [w.x]y.DIR */\n  if ((r = MBSRCHR(p, ']')) != NULL)\n  {\n    *r = 0;\n    if ((r = MBSRCHR(p, '.')) != NULL)\n    {\n      *r = ']';\n      strcat(r, \".DIR;1\");     /* this assumes a little padding--see PAD */\n    } else {\n      *p = 0;\n    }\n  } else {\n    if ((r = MBSRCHR(p, delim)) != NULL)\n      *r = 0;\n    else\n      *p = 0;\n  }\n#else /* !VMS */\n  if ((r = MBSRCHR(p, delim)) != NULL)\n    *r = 0;\n  else\n    *p = 0;\n#endif /* ?VMS */\n}\n\nint trash()\n/* Delete the compressed files and the directories that contained the deleted\n   files, if empty.  Return an error code in the ZE_ class.  Failure of\n   destroy() or deletedir() is ignored. */\n{\n  extent i;             /* counter on deleted names */\n  extent n;             /* number of directories to delete */\n  struct zlist far **s; /* table of zip entries to handle, sorted */\n  struct zlist far *z;  /* current zip entry */\n\n  /* Delete marked names and count directories */\n  n = 0;\n  for (z = zfiles; z != NULL; z = z->nxt)\n    if (z->mark == 1 || z->trash)\n    {\n      z->mark = 1;\n      if (z->iname[z->nam - 1] != (char)0x2f) { /* don't unlink directory */\n        if (verbose)\n          fprintf(mesg, \"zip diagnostic: deleting file %s\\n\", z->name);\n        if (destroy(z->name)) {\n          zipwarn(\"error deleting \", z->name);\n        }\n        /* Try to delete all paths that lead up to marked names. This is\n         * necessary only with the -D option.\n         */\n        if (!dirnames) {\n          cutpath(z->name, '/');  /* XXX wrong ??? */\n          /* Below apparently does not work for Russian OEM but\n             '/' should be same as 0x2f for ascii and most ports so\n             changed it.  Did not trace through the mappings but\n             maybe 0x2F is mapped differently on OEM_RUSS - EG 2/28/2003 */\n          /* CS, 5/14/2005: iname is the byte array read from and written\n             to the zip archive; it MUST be ASCII (compatible)!!!\n             If something goes wrong with OEM_RUSS, there is a charcode\n             mapping error between external name (z->name) and iname somewhere\n             in the in2ex & ex2in code. The charcode translation should be\n             checked.\n             This code line is changed back to the original code. */\n          /* CS, 6/12/2005: What is handled here is the difference between\n             ASCII charsets and non-ASCII charsets like the family of EBCDIC\n             charsets.  On these systems, the slash character '/' is not coded\n             as 0x2f but as 0x61 (the ASCII 'a'). The iname struct member holds\n             the name as stored in the Zip file, which are ASCII or translated\n             into ASCII for new entries, whereas the \"name\" struct member hold\n             the external name, coded in the native charset of the system\n             (EBCDIC on EBCDIC systems) */\n          /* cutpath(z->iname, '/'); */ /* QQQ ??? */\n          cutpath(z->iname, 0x2f); /* 0x2f = ascii['/'] */\n          z->nam = strlen(z->iname);\n          if (z->nam > 0) {\n            z->iname[z->nam - 1] = (char)0x2f;\n            z->iname[z->nam++] = '\\0';\n          }\n          if (z->nam > 0) n++;\n        }\n      } else {\n        n++;\n      }\n    }\n\n  /* Construct the list of all marked directories. Some may be duplicated\n   * if -D was used.\n   */\n  if (n)\n  {\n    if ((s = (struct zlist far **)malloc(n*sizeof(struct zlist far *))) ==\n        NULL)\n      return ZE_MEM;\n    n = 0;\n    for (z = zfiles; z != NULL; z = z->nxt) {\n      if (z->mark && z->nam > 0 && z->iname[z->nam - 1] == (char)0x2f /* '/' */\n          && (n == 0 || strcmp(z->name, s[n-1]->name) != 0)) {\n        s[n++] = z;\n      }\n    }\n    /* Sort the files in reverse order to get subdirectories first.\n     * To avoid problems with strange naming conventions as in VMS,\n     * we sort on the internal names, so x/y/z will always be removed\n     * before x/y. On VMS, x/y/z > x/y but [x.y.z] < [x.y]\n     */\n    qsort((char *)s, n, sizeof(struct zlist far *), rqcmp);\n\n    for (i = 0; i < n; i++) {\n      char *p = s[i]->name;\n      if (*p == '\\0') continue;\n      if (p[strlen(p) - 1] == '/') { /* keep VMS [x.y]z.dir;1 intact */\n        p[strlen(p) - 1] = '\\0';\n      }\n      if (i == 0 || strcmp(s[i]->name, s[i-1]->name) != 0) {\n        if (verbose) {\n          fprintf(mesg, \"deleting directory %s (if empty)                \\n\",\n                  s[i]->name);\n        }\n        deletedir(s[i]->name);\n      }\n    }\n    free((zvoid *)s);\n  }\n  return ZE_OK;\n}\n\n#endif /* !UTIL */\n"
  },
  {
    "path": "deps/infozip/zip30/zipnote.c",
    "content": "/*\n  zipnote.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  zipnote.c by Mark Adler.\n */\n#define __ZIPNOTE_C\n\n#ifndef UTIL\n#define UTIL\n#endif\n#include \"zip.h\"\n#define DEFCPYRT        /* main module: enable copyright string defines! */\n#include \"revision.h\"\n#include <signal.h>\n\n/* Calculate size of static line buffer used in write (-w) mode. */\n#define WRBUFSIZ 2047\n/* The line buffer size should be at least as large as FNMAX. */\n#if FNMAX > WRBUFSIZ\n#  undef WRBUFSIZ\n#  define WRBUFSIZ FNMAX\n#endif\n\n/* Character to mark zip entry names in the comment file */\n#define MARK '@'\n#define MARKE \" (comment above this line)\"\n#define MARKZ \" (zip file comment below this line)\"\n\n/* Temporary zip file pointer */\nlocal FILE *tempzf;\n\n\n/* Local functions */\nlocal void handler OF((int));\nlocal void license OF((void));\nlocal void help OF((void));\nlocal void version_info OF((void));\nlocal void putclean OF((char *, extent));\n/* getline name conflicts with GNU getline() function */\nlocal char *zgetline OF((char *, extent));\nlocal int catalloc OF((char * far *, char *));\nint main OF((int, char **));\n\n/* keep compiler happy until implement long options - 11/4/2003 EG */\nstruct option_struct far options[] = {\n  /* short longopt        value_type        negatable        ID    name */\n    {\"h\",  \"help\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    /* the end of the list */\n    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */\n  };\n\n#ifdef MACOS\n#define ziperr(c, h)    zipnoteerr(c, h)\n#define zipwarn(a, b)   zipnotewarn(a, b)\n\nvoid zipnoteerr(int c, ZCONST char *h);\nvoid zipnotewarn(ZCONST char *a, ZCONST char *b);\n#endif\n\n#ifdef QDOS\n#define exit(p1) QDOSexit()\n#endif\n\nint set_filetype(out_path)\n  char *out_path;\n{\n#ifdef __BEOS__\n  /* Set the filetype of the zipfile to \"application/zip\" */\n  setfiletype( out_path, \"application/zip\" );\n#endif\n\n#ifdef __ATHEOS__\n  /* Set the filetype of the zipfile to \"application/x-zip\" */\n  setfiletype(out_path, \"application/x-zip\");\n#endif\n\n#ifdef MACOS\n  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */\n  setfiletype(out_path, 'IZip', 'ZIP ');\n#endif\n\n#ifdef RISCOS\n  /* Set the filetype of the zipfile to &DDC */\n  setfiletype(out_path, 0xDDC);\n#endif\n  return ZE_OK;\n}\n\n/* rename a split\n * A split has a tempfile name until it is closed, then\n * here rename it as out_path the final name for the split.\n */\nint rename_split(temp_name, out_path)\n  char *temp_name;\n  char *out_path;\n{\n  int r;\n  /* Replace old zip file with new zip file, leaving only the new one */\n  if ((r = replace(out_path, temp_name)) != ZE_OK)\n  {\n    zipwarn(\"new zip file left as: \", temp_name);\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    ZIPERR(r, \"was replacing split file\");\n  }\n  if (zip_attributes) {\n    setfileattr(out_path, zip_attributes);\n  }\n  return ZE_OK;\n}\n\nvoid zipmessage_nl(a, nl)\nZCONST char *a;     /* message string to output */\nint nl;             /* 1 = add nl to end */\n/* If nl false, print a message to mesg without new line.\n   If nl true, print and add new line.  If logfile is\n   open then also write message to log file. */\n{\n  if (noisy) {\n    fprintf(mesg, \"%s\", a);\n    if (nl) {\n      fprintf(mesg, \"\\n\");\n      mesg_line_started = 0;\n    } else {\n      mesg_line_started = 1;\n    }\n    fflush(mesg);\n  }\n}\n\nvoid zipmessage(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a message to mesg and flush.  Also write to log file if\n   open.  Write new line first if current line has output already. */\n{\n  if (noisy) {\n    if (mesg_line_started)\n      fprintf(mesg, \"\\n\");\n    fprintf(mesg, \"%s%s\\n\", a, b);\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n}\n\nvoid ziperr(c, h)\nint c;                  /* error code from the ZE_ class */\nZCONST char *h;         /* message about how it happened */\n/* Issue a message for the error, clean up files and memory, and exit. */\n{\n  if (PERR(c))\n    perror(\"zipnote error\");\n  fprintf(mesg, \"zipnote error: %s (%s)\\n\", ZIPERRORS(c), h);\n  if (tempzf != NULL)\n    fclose(tempzf);\n  if (tempzip != NULL)\n  {\n    destroy(tempzip);\n    free((zvoid *)tempzip);\n  }\n  if (zipfile != NULL)\n    free((zvoid *)zipfile);\n  EXIT(c);\n}\n\n\nlocal void handler(s)\nint s;                  /* signal number (ignored) */\n/* Upon getting a user interrupt, abort cleanly using ziperr(). */\n{\n#ifndef MSDOS\n  putc('\\n', mesg);\n#endif /* !MSDOS */\n  ziperr(ZE_ABORT, \"aborting\");\n  s++;                                  /* keep some compilers happy */\n}\n\n\nvoid zipwarn(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a warning message to mesg (usually stderr) and return. */\n{\n  fprintf(mesg, \"zipnote warning: %s%s\\n\", a, b);\n}\n\n\nlocal void license()\n/* Print license information to stdout. */\n{\n  extent i;             /* counter for copyright array */\n\n  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)\n    puts(swlicense[i]);\n}\n\n\nlocal void help()\n/* Print help (along with license info) to stdout. */\n{\n  extent i;             /* counter for help array */\n\n  /* help array */\n  static ZCONST char *text[] = {\n\"\",\n\"ZipNote %s (%s)\",\n#ifdef VM_CMS\n\"Usage:  zipnote [-w] [-q] [-b fm] zipfile\",\n#else\n\"Usage:  zipnote [-w] [-q] [-b path] zipfile\",\n#endif\n\"  the default action is to write the comments in zipfile to stdout\",\n\"  -w   write the zipfile comments from stdin\",\n#ifdef VM_CMS\n\"  -b   use \\\"fm\\\" as the filemode for the temporary zip file\",\n#else\n\"  -b   use \\\"path\\\" for the temporary zip file\",\n#endif\n\"  -q   quieter operation, suppress some informational messages\",\n\"  -h   show this help    -v   show version info    -L   show software license\",\n\"\",\n\"Example:\",\n#ifdef VMS\n\"     define/user sys$output foo.tmp\",\n\"     zipnote foo.zip\",\n\"     edit foo.tmp\",\n\"     ... then you edit the comments, save, and exit ...\",\n\"     define/user sys$input foo.tmp\",\n\"     zipnote -w foo.zip\",\n#else\n#ifdef RISCOS\n\"     zipnote foo/zip > foo/tmp\",\n\"     <!Edit> foo/tmp\",\n\"     ... then you edit the comments, save, and exit ...\",\n\"     zipnote -w foo/zip < foo/tmp\",\n#else\n#ifdef VM_CMS\n\"     zipnote foo.zip > foo.tmp\",\n\"     xedit foo tmp\",\n\"     ... then you edit the comments, save, and exit ...\",\n\"     zipnote -w foo.zip < foo.tmp\",\n#else\n\"     zipnote foo.zip > foo.tmp\",\n\"     ed foo.tmp\",\n\"     ... then you edit the comments, save, and exit ...\",\n\"     zipnote -w foo.zip < foo.tmp\",\n#endif /* VM_CMS */\n#endif /* RISCOS */\n#endif /* VMS */\n\"\",\n\"  \\\"@ name\\\" can be followed by an \\\"@=newname\\\" line to change the name\"\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {\n    printf(copyright[i], \"zipnote\");\n    putchar('\\n');\n  }\n  for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n  {\n    printf(text[i], VERSION, REVDATE);\n    putchar('\\n');\n  }\n}\n\n/*\n * XXX put this in version.c\n */\n\nlocal void version_info()\n/* Print verbose info about program version and compile time options\n   to stdout. */\n{\n  extent i;             /* counter in text arrays */\n\n  /* Options info array */\n  static ZCONST char *comp_opts[] = {\n#ifdef DEBUG\n    \"DEBUG\",\n#endif\n    NULL\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)\n  {\n    printf(copyright[i], \"zipnote\");\n    putchar('\\n');\n  }\n\n  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)\n  {\n    printf(versinfolines[i], \"ZipNote\", VERSION, REVDATE);\n    putchar('\\n');\n  }\n\n  version_local();\n\n  puts(\"ZipNote special compilation options:\");\n  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)\n  {\n    printf(\"\\t%s\\n\",comp_opts[i]);\n  }\n  if (i == 0)\n      puts(\"\\t[none]\");\n}\n\n\nlocal void putclean(s, n)\nchar *s;                /* string to write to stdout */\nextent n;               /* length of string */\n/* Write the string s to stdout, filtering out control characters that are\n   not tab or newline (mainly to remove carriage returns), and prefix MARK's\n   and backslashes with a backslash.  Also, terminate with a newline if\n   needed. */\n{\n  int c;                /* next character in string */\n  int e;                /* last character written */\n\n  e = '\\n';                     /* if empty, write nothing */\n  while (n--)\n  {\n    c = *(uch *)s++;\n    if (c == MARK || c == '\\\\')\n      putchar('\\\\');\n    if (c >= ' ' || c == '\\t' || c == '\\n')\n      { e=c; putchar(e); }\n  }\n  if (e != '\\n')\n    putchar('\\n');\n}\n\n\nlocal char *zgetline(buf, size)\nchar *buf;\nextent size;\n/* Read a line of text from stdin into string buffer 'buf' of size 'size'.\n   In case of buffer overflow or EOF, a NULL pointer is returned. */\n{\n    char *line;\n    unsigned len;\n\n    line = fgets(buf, size, stdin);\n    if (line != NULL && (len = strlen(line)) > 0) {\n        if (len == size-1 && line[len-1] != '\\n') {\n            /* buffer is full and record delimiter not seen -> overflow */\n            line = NULL;\n        } else {\n            /* delete trailing record delimiter */\n            if (line[len-1] == '\\n') line[len-1] = '\\0';\n        }\n    }\n    return line;\n}\n\n\nlocal int catalloc(a, s)\nchar * far *a;          /* pointer to a pointer to a malloc'ed string */\nchar *s;                /* string to concatenate on a */\n/* Concatentate the string s to the malloc'ed string pointed to by a.\n   Preprocess s by removing backslash escape characters. */\n{\n  char *p;              /* temporary pointer */\n  char *q;              /* temporary pointer */\n\n  for (p = q = s; *q; *p++ = *q++)\n    if (*q == '\\\\' && *(q+1))\n      q++;\n  *p = 0;\n  if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)\n    return ZE_MEM;\n  strcat(strcat(strcpy(p, *a), **a ? \"\\r\\n\" : \"\"), s);\n  free((zvoid *)*a);\n  *a = p;\n  return ZE_OK;\n}\n\n\n#ifndef USE_ZIPNOTEMAIN\nint main(argc, argv)\n#else\nint zipnotemain(argc, argv)\n#endif\nint argc;               /* number of tokens in command line */\nchar **argv;            /* command line tokens */\n/* Write the comments in the zipfile to stdout, or read them from stdin. */\n{\n  char abf[WRBUFSIZ+1]; /* input line buffer */\n  char *a;              /* pointer to line buffer or NULL */\n  zoff_t c;             /* start of central directory */\n  int k;                /* next argument type */\n  char *q;              /* steps through option arguments */\n  int r;                /* arg counter, temporary variable */\n  zoff_t s;             /* length of central directory */\n  int t;                /* attributes of zip file */\n  int w;                /* true if updating zip file from stdin */\n  FILE *x;              /* input file for testing if can write it */\n  struct zlist far *z;  /* steps through zfiles linked list */\n\n#ifdef THEOS\n  setlocale(LC_CTYPE, \"I\");\n#endif\n\n#ifdef UNICODE_SUPPORT\n# ifdef UNIX\n  /* For Unix, set the locale to UTF-8.  Any UTF-8 locale is\n     OK and they should all be the same.  This allows seeing,\n     writing, and displaying (if the fonts are loaded) all\n     characters in UTF-8. */\n  {\n    char *loc;\n\n    /*\n      loc = setlocale(LC_CTYPE, NULL);\n      printf(\"  Initial language locale = '%s'\\n\", loc);\n    */\n\n    loc = setlocale(LC_CTYPE, \"en_US.UTF-8\");\n\n    /*\n      printf(\"langinfo %s\\n\", nl_langinfo(CODESET));\n    */\n\n    if (loc != NULL) {\n      /* using UTF-8 character set so can set UTF-8 GPBF bit 11 */\n      using_utf8 = 1;\n      /*\n        printf(\"  Locale set to %s\\n\", loc);\n      */\n    } else {\n      /*\n        printf(\"  Could not set Unicode UTF-8 locale\\n\");\n      */\n    }\n  }\n# endif\n#endif\n\n  /* If no args, show help */\n  if (argc == 1)\n  {\n    help();\n    EXIT(ZE_OK);\n  }\n\n  /* Direct info messages to stderr; stdout is used for data output. */\n  mesg = stderr;\n\n  init_upper();           /* build case map table */\n\n  /* Go through args */\n  zipfile = tempzip = NULL;\n  tempzf = NULL;\n  signal(SIGINT, handler);\n#ifdef SIGTERM              /* AMIGA has no SIGTERM */\n  signal(SIGTERM, handler);\n#endif\n#ifdef SIGABRT\n  signal(SIGABRT, handler);\n#endif\n#ifdef SIGBREAK\n  signal(SIGBREAK, handler);\n#endif\n#ifdef SIGBUS\n  signal(SIGBUS, handler);\n#endif\n#ifdef SIGILL\n  signal(SIGILL, handler);\n#endif\n#ifdef SIGSEGV\n  signal(SIGSEGV, handler);\n#endif\n  k = w = 0;\n  for (r = 1; r < argc; r++)\n    if (*argv[r] == '-') {\n      if (argv[r][1])\n        for (q = argv[r]+1; *q; q++)\n          switch (*q)\n          {\n            case 'b':   /* Specify path for temporary file */\n              if (k)\n                ziperr(ZE_PARMS, \"use -b before zip file name\");\n              else\n                k = 1;          /* Next non-option is path */\n              break;\n            case 'h':   /* Show help */\n              help();  EXIT(ZE_OK);\n            case 'l':  case 'L':  /* Show copyright and disclaimer */\n              license();  EXIT(ZE_OK);\n            case 'q':   /* Quiet operation, suppress info messages */\n              noisy = 0;  break;\n            case 'v':   /* Show version info */\n              version_info();  EXIT(ZE_OK);\n            case 'w':\n              w = 1;  break;\n            default:\n              ziperr(ZE_PARMS, \"unknown option\");\n          }\n      else\n        ziperr(ZE_PARMS, \"zip file cannot be stdin\");\n    } else\n      if (k == 0)\n      {\n        if (zipfile == NULL)\n        {\n          if ((zipfile = ziptyp(argv[r])) == NULL)\n            ziperr(ZE_MEM, \"was processing arguments\");\n        }\n        else\n          ziperr(ZE_PARMS, \"can only specify one zip file\");\n      }\n      else\n      {\n        tempath = argv[r];\n        k = 0;\n      }\n  if (zipfile == NULL)\n    ziperr(ZE_PARMS, \"need to specify zip file\");\n\n  if ((in_path = malloc(strlen(zipfile) + 1)) == NULL) {\n    ziperr(ZE_MEM, \"input\");\n  }\n  strcpy(in_path, zipfile);\n\n  /* Read zip file */\n  if ((r = readzipfile()) != ZE_OK)\n    ziperr(r, zipfile);\n  if (zfiles == NULL)\n    ziperr(ZE_NAME, zipfile);\n\n  /* Put comments to stdout, if not -w */\n  if (!w)\n  {\n    for (z = zfiles; z != NULL; z = z->nxt)\n    {\n      printf(\"%c %s\\n\", MARK, z->zname);\n      putclean(z->comment, z->com);\n      printf(\"%c%s\\n\", MARK, MARKE);\n    }\n    printf(\"%c%s\\n\", MARK, MARKZ);\n    putclean(zcomment, zcomlen);\n    EXIT(ZE_OK);\n  }\n\n  /* If updating comments, make sure zip file is writeable */\n  if ((x = fopen(zipfile, \"a\")) == NULL)\n    ziperr(ZE_CREAT, zipfile);\n  fclose(x);\n  t = getfileattr(zipfile);\n\n  /* Process stdin, replacing comments */\n  z = zfiles;\n  while ((a = zgetline(abf, WRBUFSIZ+1)) != NULL &&\n         (a[0] != MARK || strcmp(a + 1, MARKZ)))\n  {                                     /* while input and not file comment */\n    if (a[0] != MARK || a[1] != ' ')    /* better be \"@ name\" */\n      ziperr(ZE_NOTE, \"unexpected input\");\n    while (z != NULL && strcmp(a + 2, z->zname))\n      z = z->nxt;                       /* allow missing entries in order */\n    if (z == NULL)\n      ziperr(ZE_NOTE, \"unknown entry name\");\n    if ((a = zgetline(abf, WRBUFSIZ+1)) != NULL && a[0] == MARK && a[1] == '=')\n    {\n      if (z->name != z->iname)\n        free((zvoid *)z->iname);\n      if ((z->iname = malloc(strlen(a+1))) == NULL)\n        ziperr(ZE_MEM, \"was changing name\");\n#ifdef EBCDIC\n      strtoasc(z->iname, a+2);\n#else\n      strcpy(z->iname, a+2);\n#endif\n\n/*\n * Don't update z->nam here, we need the old value a little later.....\n * The update is handled in zipcopy().\n */\n      a = zgetline(abf, WRBUFSIZ+1);\n    }\n    if (z->com)                         /* change zip entry comment */\n      free((zvoid *)z->comment);\n    z->comment = malloc(1);  *(z->comment) = 0;\n    while (a != NULL && *a != MARK)\n    {\n      if ((r = catalloc(&(z->comment), a)) != ZE_OK)\n        ziperr(r, \"was building new zipentry comments\");\n      a = zgetline(abf, WRBUFSIZ+1);\n    }\n    z->com = strlen(z->comment);\n    z = z->nxt;                         /* point to next entry */\n  }\n  if (a != NULL)                        /* change zip file comment */\n  {\n    zcomment = malloc(1);  *zcomment = 0;\n    while ((a = zgetline(abf, WRBUFSIZ+1)) != NULL)\n      if ((r = catalloc(&zcomment, a)) != ZE_OK)\n        ziperr(r, \"was building new zipfile comment\");\n    zcomlen = strlen(zcomment);\n  }\n\n  /* Open output zip file for writing */\n#if defined(UNIX) && !defined(NO_MKSTEMP)\n  {\n    int yd;\n    int i;\n\n    /* use mkstemp to avoid race condition and compiler warning */\n\n    if (tempath != NULL)\n    {\n      /* if -b used to set temp file dir use that for split temp */\n      if ((tempzip = malloc(strlen(tempath) + 12)) == NULL) {\n        ZIPERR(ZE_MEM, \"allocating temp filename\");\n      }\n      strcpy(tempzip, tempath);\n      if (lastchar(tempzip) != '/')\n        strcat(tempzip, \"/\");\n    }\n    else\n    {\n      /* create path by stripping name and appending template */\n      if ((tempzip = malloc(strlen(zipfile) + 12)) == NULL) {\n      ZIPERR(ZE_MEM, \"allocating temp filename\");\n      }\n      strcpy(tempzip, zipfile);\n      for(i = strlen(tempzip); i > 0; i--) {\n        if (tempzip[i - 1] == '/')\n          break;\n      }\n      tempzip[i] = '\\0';\n    }\n    strcat(tempzip, \"ziXXXXXX\");\n\n    if ((yd = mkstemp(tempzip)) == EOF) {\n      ZIPERR(ZE_TEMP, tempzip);\n    }\n    if ((tempzf = y = fdopen(yd, FOPW)) == NULL) {\n      ZIPERR(ZE_TEMP, tempzip);\n    }\n  }\n#else\n  if ((tempzf = y = fopen(tempzip = tempname(zipfile), FOPW)) == NULL)\n    ziperr(ZE_TEMP, tempzip);\n#endif\n\n  /* Open input zip file again, copy preamble if any */\n  if ((in_file = fopen(zipfile, FOPR)) == NULL)\n    ziperr(ZE_NAME, zipfile);\n\n  if (zipbeg && (r = bfcopy(zipbeg)) != ZE_OK)\n    ziperr(r, r == ZE_TEMP ? tempzip : zipfile);\n  tempzn = zipbeg;\n\n  /* Go through local entries, copying them over as is */\n  fix = 3; /* needed for zipcopy if name changed */\n  for (z = zfiles; z != NULL; z = z->nxt) {\n    if ((r = zipcopy(z)) != ZE_OK)\n      ziperr(r, \"was copying an entry\");\n  }\n  fclose(x);\n\n  /* Write central directory and end of central directory with new comments */\n  if ((c = zftello(y)) == (zoff_t)-1)    /* get start of central */\n    ziperr(ZE_TEMP, tempzip);\n  for (z = zfiles; z != NULL; z = z->nxt)\n    if ((r = putcentral(z)) != ZE_OK)\n      ziperr(r, tempzip);\n  if ((s = zftello(y)) == (zoff_t)-1)    /* get end of central */\n    ziperr(ZE_TEMP, tempzip);\n  s -= c;                       /* compute length of central */\n  if ((r = putend((zoff_t)zcount, s, c, zcomlen, zcomment)) != ZE_OK)\n    ziperr(r, tempzip);\n  tempzf = NULL;\n  if (fclose(y))\n    ziperr(ZE_TEMP, tempzip);\n  if ((r = replace(zipfile, tempzip)) != ZE_OK)\n  {\n    zipwarn(\"new zip file left as: \", tempzip);\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    ziperr(r, \"was replacing the original zip file\");\n  }\n  free((zvoid *)tempzip);\n  tempzip = NULL;\n  setfileattr(zipfile, t);\n#ifdef RISCOS\n  /* Set the filetype of the zipfile to &DDC */\n  setfiletype(zipfile,0xDDC);\n#endif\n  free((zvoid *)zipfile);\n  zipfile = NULL;\n\n  /* Done! */\n  RETURN(0);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/zipnote.txt",
    "content": "zipnote(1)                                                          zipnote(1)\n\nNAME\n       zipnote  -  write  the comments in zipfile to stdout, edit comments and\n       rename files in zipfile\n\nSYNOPSIS\n       zipnote [-w] [-b path] [-h] [-v] [-L] zipfile\n\nARGUMENTS\n       zipfile  Zipfile to read comments from or edit.\n\nOPTIONS\n       -w     Write comments to a zipfile from stdin (see below).\n\n       -b path\n              Use path for the temporary zip file.\n\n       -h     Show a short help.\n\n       -v     Show version information.\n\n       -L     Show software license.\n\nDESCRIPTION\n       zipnote writes the comments in  a  zipfile  to  stdout.   This  is  the\n       default  mode.  A second mode allows updating the comments in a zipfile\n       as well as allows changing the names  of  the  files  in  the  zipfile.\n       These modes are described below.\n\nEXAMPLES\n       To write all comments in a zipfile to stdout use for example\n\n            zipnote foo.zip > foo.tmp\n\n       This  writes all comments in the zipfile foo.zip to the file foo.tmp in\n       a specific format.\n\n       If desired, this file can then be edited to  change  the  comments  and\n       then used to update the zipfile.\n\n            zipnote -w foo.zip < foo.tmp\n\n       The  names of the files in the zipfile can also be changed in this way.\n       This is done by following lines like\n            \"@ name\"\n       in the created temporary file (called foo.tmp here) with lines like\n            \"@=newname\"\n       and then using the -w option as above.\n\nBUGS\n       The temporary file format is rather  specific  and  zipnote  is  rather\n       picky  about it.  It should be easier to change file names in a script.\n\n       Does not yet support large (> 2 GB) or split archives.\n\nSEE ALSO\n       zip(1), unzip(1)\n\nAUTHOR\n       Info-ZIP\n\n                              v3.0 of 8 May 2008                    zipnote(1)\n"
  },
  {
    "path": "deps/infozip/zip30/zipsplit.c",
    "content": "/*\n  zipsplit.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  zipsplit.c by Mark Adler.\n */\n#define __ZIPSPLIT_C\n\n#ifndef UTIL\n#define UTIL\n#endif\n#include \"zip.h\"\n#define DEFCPYRT        /* main module: enable copyright string defines! */\n#include \"revision.h\"\n#include <signal.h>\n\n#define DEFSIZ 36000L   /* Default split size (change in help() too) */\n#ifdef MSDOS\n#  define NL 2          /* Number of bytes written for a \\n */\n#else /* !MSDOS */\n#  define NL 1          /* Number of bytes written for a \\n */\n#endif /* ?MSDOS */\n#ifdef RISCOS\n#  define INDEX \"zipspl/idx\"      /* Name of index file */\n#  define TEMPL_FMT \"%%0%dld\"\n#  define TEMPL_SIZ 13\n#  define ZPATH_SEP '.'\n#else\n#ifdef QDOS\n#  define ZPATH_SEP '_'\n#  define INDEX \"zipsplit_idx\"    /* Name of index file */\n#  define TEMPL_FMT \"%%0%dld_zip\"\n#  define TEMPL_SIZ 17\n#  define exit(p1) QDOSexit()\n#else\n#ifdef VM_CMS\n#  define INDEX \"zipsplit.idx\"    /* Name of index file */\n#  define TEMPL_FMT \"%%0%dld.zip\"\n#  define TEMPL_SIZ 21\n#  define ZPATH_SEP '.'\n#else\n#  define INDEX \"zipsplit.idx\"    /* Name of index file */\n#  define TEMPL_FMT \"%%0%dld.zip\"\n#  define TEMPL_SIZ 17\n#  define ZPATH_SEP '.'\n#endif /* VM_CMS */\n#endif /* QDOS */\n#endif /* RISCOS */\n\n#ifdef MACOS\n#define ziperr(c, h)    zipspliterr(c, h)\n#define zipwarn(a, b)   zipsplitwarn(a, b)\nvoid zipsplitwarn(ZCONST char *a, ZCONST char *b);\nvoid zipspliterr(int c, ZCONST char *h);\n#endif /* MACOS */\n\n/* Local functions */\nlocal zvoid *talloc OF((extent));\nlocal void tfree OF((zvoid *));\nlocal void tfreeall OF((void));\nlocal void handler OF((int));\nlocal void license OF((void));\nlocal void help OF((void));\nlocal void version_info OF((void));\nlocal extent simple OF((uzoff_t *, extent, uzoff_t, uzoff_t));\nlocal int descmp OF((ZCONST zvoid *, ZCONST zvoid *));\nlocal extent greedy OF((uzoff_t *, extent, uzoff_t, uzoff_t));\nlocal int retry OF((void));\nint main OF((int, char **));\n\n\n/* Output zip files */\nlocal char template[TEMPL_SIZ]; /* name template for output files */\nlocal int zipsmade = 0;         /* number of zip files made */\nlocal int indexmade = 0;        /* true if index file made */\nlocal char *path = NULL;        /* space for full name */\nlocal char *name;               /* where name goes in path[] */\n\n\n/* The talloc() and tree() routines extend malloc() and free() to keep\n   track of all allocated memory.  Then the tfreeall() routine uses this\n   information to free all allocated memory before exiting. */\n\n#define TMAX 6          /* set intelligently by examining the code */\nzvoid *talls[TMAX];     /* malloc'ed pointers to track */\nint talln = 0;          /* number of entries in talls[] */\n\n\nint set_filetype(out_path)\n  char *out_path;\n{\n#ifdef __BEOS__\n  /* Set the filetype of the zipfile to \"application/zip\" */\n  setfiletype( out_path, \"application/zip\" );\n#endif\n\n#ifdef __ATHEOS__\n  /* Set the filetype of the zipfile to \"application/x-zip\" */\n  setfiletype(out_path, \"application/x-zip\");\n#endif\n\n#ifdef MACOS\n  /* Set the Creator/Type of the zipfile to 'IZip' and 'ZIP ' */\n  setfiletype(out_path, 'IZip', 'ZIP ');\n#endif\n\n#ifdef RISCOS\n  /* Set the filetype of the zipfile to &DDC */\n  setfiletype(out_path, 0xDDC);\n#endif\n  return ZE_OK;\n}\n\n/* rename a split\n * A split has a tempfile name until it is closed, then\n * here rename it as out_path the final name for the split.\n *\n * This is not used in zipsplit but is referenced by the generic split\n * writing code.  If zipsplit is made split aware (so can write splits of\n * splits, if that makes sense) then this would get used.  But if that\n * happens these utility versions should be dropped and the main ones\n * used.\n */\nint rename_split(temp_name, out_path)\n  char *temp_name;\n  char *out_path;\n{\n  int r;\n  /* Replace old zip file with new zip file, leaving only the new one */\n  if ((r = replace(out_path, temp_name)) != ZE_OK)\n  {\n    zipwarn(\"new zip file left as: \", temp_name);\n    free((zvoid *)tempzip);\n    tempzip = NULL;\n    ZIPERR(r, \"was replacing split file\");\n  }\n  if (zip_attributes) {\n    setfileattr(out_path, zip_attributes);\n  }\n  return ZE_OK;\n}\n\nvoid zipmessage_nl(a, nl)\nZCONST char *a;     /* message string to output */\nint nl;             /* 1 = add nl to end */\n/* If nl false, print a message to mesg without new line.\n   If nl true, print and add new line.  If logfile is\n   open then also write message to log file. */\n{\n  if (noisy) {\n    fprintf(mesg, \"%s\", a);\n    if (nl) {\n      fprintf(mesg, \"\\n\");\n      mesg_line_started = 0;\n    } else {\n      mesg_line_started = 1;\n    }\n    fflush(mesg);\n  }\n}\n\nvoid zipmessage(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a message to mesg and flush.  Also write to log file if\n   open.  Write new line first if current line has output already. */\n{\n  if (noisy) {\n    if (mesg_line_started)\n      fprintf(mesg, \"\\n\");\n    fprintf(mesg, \"%s%s\\n\", a, b);\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n}\n\nlocal zvoid *talloc(s)\nextent s;\n/* does a malloc() and saves the pointer to free later (does not check\n   for an overflow of the talls[] list) */\n{\n  zvoid *p;\n\n  if ((p = (zvoid *)malloc(s)) != NULL)\n    talls[talln++] = p;\n  return p;\n}\n\n\nlocal void tfree(p)\nzvoid *p;\n/* does a free() and also removes the pointer from the talloc() list */\n{\n  int i;\n\n  free(p);\n  i = talln;\n  while (i--)\n    if (talls[i] == p)\n      break;\n  if (i >= 0)\n  {\n    while (++i < talln)\n      talls[i - 1] = talls[i];\n    talln--;\n  }\n}\n\n\nlocal void tfreeall()\n/* free everything talloc'ed and not tfree'd */\n{\n  while (talln)\n    free(talls[--talln]);\n}\n\n\nvoid ziperr(c, h)\nint c;                  /* error code from the ZE_ class */\nZCONST char *h;         /* message about how it happened */\n/* Issue a message for the error, clean up files and memory, and exit. */\n{\n  if (PERR(c))\n    perror(\"zipsplit error\");\n  fprintf(mesg, \"zipsplit error: %s (%s)\\n\", ZIPERRORS(c), h);\n  if (indexmade)\n  {\n    strcpy(name, INDEX);\n    destroy(path);\n  }\n  for (; zipsmade; zipsmade--)\n  {\n    sprintf(name, template, zipsmade);\n    destroy(path);\n  }\n  tfreeall();\n  if (zipfile != NULL)\n    free((zvoid *)zipfile);\n  EXIT(c);\n}\n\n\nlocal void handler(s)\nint s;                  /* signal number (ignored) */\n/* Upon getting a user interrupt, abort cleanly using ziperr(). */\n{\n#ifndef MSDOS\n  putc('\\n', mesg);\n#endif /* !MSDOS */\n  ziperr(ZE_ABORT, \"aborting\");\n  s++;                                  /* keep some compilers happy */\n}\n\n\nvoid zipwarn(a, b)\nZCONST char *a, *b;     /* message strings juxtaposed in output */\n/* Print a warning message to mesg (usually stderr) and return. */\n{\n  fprintf(mesg, \"zipsplit warning: %s%s\\n\", a, b);\n}\n\n\nlocal void license()\n/* Print license information to stdout. */\n{\n  extent i;             /* counter for copyright array */\n\n  for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)\n    puts(swlicense[i]);\n}\n\n\nlocal void help()\n/* Print help (along with license info) to stdout. */\n{\n  extent i;             /* counter for help array */\n\n  /* help array */\n  static ZCONST char *text[] = {\n\"\",\n\"ZipSplit %s (%s)\",\n#ifdef VM_CMS\n\"Usage:  zipsplit [-tipqs] [-n size] [-r room] [-b fm] zipfile\",\n#else\n\"Usage:  zipsplit [-tipqs] [-n size] [-r room] [-b path] zipfile\",\n#endif\n\"  -t   report how many files it will take, but don't make them\",\n#ifdef RISCOS\n\"  -i   make index (\" INDEX \") and count its size against first zip file\",\n#else\n\"  -i   make index (zipsplit.idx) and count its size against first zip file\",\n#endif\n\"  -n   make zip files no larger than \\\"size\\\" (default = 36000)\",\n\"  -r   leave room for \\\"room\\\" bytes on the first disk (default = 0)\",\n#ifdef VM_CMS\n\"  -b   use \\\"fm\\\" as the filemode for the output zip files\",\n#else\n\"  -b   use \\\"path\\\" for the output zip files\",\n#endif\n\"  -q   quieter operation, suppress some informational messages\",\n\"  -p   pause between output zip files\",\n\"  -s   do a sequential split even if it takes more zip files\",\n\"  -h   show this help    -v   show version info    -L   show software license\"\n  };\n\n  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {\n    printf(copyright[i], \"zipsplit\");\n    putchar('\\n');\n  }\n  for (i = 0; i < sizeof(text)/sizeof(char *); i++)\n  {\n    printf(text[i], VERSION, REVDATE);\n    putchar('\\n');\n  }\n}\n\n\nlocal void version_info()\n/* Print verbose info about program version and compile time options\n   to stdout. */\n{\n  extent i;             /* counter in text arrays */\n\n  /* Options info array */\n  static ZCONST char *comp_opts[] = {\n#ifdef DEBUG\n    \"DEBUG\",\n#endif\n    NULL\n  };\n\n  for (i = 0; i < sizeof(versinfolines)/sizeof(char *); i++)\n  {\n    printf(versinfolines[i], \"ZipSplit\", VERSION, REVDATE);\n    putchar('\\n');\n  }\n\n  version_local();\n\n  puts(\"ZipSplit special compilation options:\");\n  for (i = 0; (int)i < (int)(sizeof(comp_opts)/sizeof(char *) - 1); i++)\n  {\n    printf(\"\\t%s\\n\",comp_opts[i]);\n  }\n  if (i == 0)\n      puts(\"\\t[none]\");\n}\n\n\nlocal extent simple(a, n, c, d)\nuzoff_t *a;     /* items to put in bins, return value: destination bins */\nextent n;       /* number of items */\nuzoff_t c;      /* capacity of each bin */\nuzoff_t d;      /* amount to deduct from first bin */\n/* Return the number of bins of capacity c that are needed to contain the\n   integers in a[0..n-1] placed sequentially into the bins.  The value d\n   is deducted initially from the first bin (space for index).  The entries\n   in a[] are replaced by the destination bins. */\n{\n  extent k;     /* current bin number */\n  uzoff_t t;    /* space used in current bin */\n\n  t = k = 0;\n  while (n--)\n  {\n    if (*a + t > c - (k == 0 ? d : 0))\n    {\n      k++;\n      t = 0;\n    }\n    t += *a;\n    *(ulg huge *)a++ = k;\n  }\n  return k + 1;\n}\n\n\nlocal int descmp(a, b)\nZCONST zvoid *a, *b;          /* pointers to pointers to ulg's to compare */\n/* Used by qsort() in greedy() to do a descending sort. */\n{\n  return **(uzoff_t **)a < **(uzoff_t **)b ? 1 :\n         (**(uzoff_t **)a > **(uzoff_t **)b ? -1 : 0);\n}\n\n\nlocal extent greedy(a, n, c, d)\nuzoff_t *a;         /* items to put in bins, return value: destination bins */\nextent n;       /* number of items */\nuzoff_t c;          /* capacity of each bin */\nuzoff_t d;          /* amount to deduct from first bin */\n/* Return the number of bins of capacity c that are needed to contain the\n   items with sizes a[0..n-1] placed non-sequentially into the bins.  The\n   value d is deducted initially from the first bin (space for index).\n   The entries in a[] are replaced by the destination bins. */\n{\n  uzoff_t *b;   /* space left in each bin (malloc'ed for each m) */\n  uzoff_t *e;   /* copy of argument a[] (malloc'ed) */\n  extent i;     /* steps through items */\n  extent j;     /* steps through bins */\n  extent k;     /* best bin to put current item in */\n  extent m;     /* current number of bins */\n  uzoff_t **s;  /* pointers to e[], sorted descending (malloc'ed) */\n  uzoff_t t;    /* space left in best bin (index k) */\n\n  /* Algorithm:\n     1. Copy a[] to e[] and sort pointers to e[0..n-1] (in s[]), in\n        descending order.\n     2. Compute total of s[] and set m to the smallest number of bins of\n        capacity c that can hold the total.\n     3. Allocate m bins.\n     4. For each item in s[], starting with the largest, put it in the\n        bin with the smallest current capacity greater than or equal to the\n        item's size.  If no bin has enough room, increment m and go to step 4.\n     5. Else, all items ended up in a bin--return m.\n  */\n\n  /* Copy a[] to e[], put pointers to e[] in s[], and sort s[].  Also compute\n     the initial number of bins (minus 1). */\n  if ((e = (uzoff_t *)malloc(n * sizeof(uzoff_t))) == NULL ||\n      (s = (uzoff_t **)malloc(n * sizeof(uzoff_t *))) == NULL)\n  {\n    if (e != NULL)\n      free((zvoid *)e);\n    ziperr(ZE_MEM, \"was trying a smart split\");\n    return 0;                           /* only to make compiler happy */\n  }\n  memcpy((char *)e, (char *)a, n * sizeof(uzoff_t));\n  for (t = i = 0; i < n; i++)\n    t += *(s[i] = e + i);\n  m = (extent)((t + c - 1) / c) - 1;    /* pre-decrement for loop */\n  qsort((char *)s, n, sizeof(ulg *), descmp);\n\n  /* Stuff bins until successful */\n  do {\n    /* Increment the number of bins, allocate and initialize bins */\n    if ((b = (uzoff_t *)malloc(++m * sizeof(uzoff_t))) == NULL)\n    {\n      free((zvoid *)s);\n      free((zvoid *)e);\n      ziperr(ZE_MEM, \"was trying a smart split\");\n    }\n    b[0] = c - d;                       /* leave space in first bin */\n    for (j = 1; j < m; j++)\n      b[j] = c;\n\n    /* Fill the bins greedily */\n    for (i = 0; i < n; i++)\n    {\n      /* Find smallest bin that will hold item i (size s[i]) */\n      t = c + 1;\n      for (k = j = 0; j < m; j++)\n        if (*s[i] <= b[j] && b[j] < t)\n          t = b[k = j];\n\n      /* If no bins big enough for *s[i], try next m */\n      if (t == c + 1)\n        break;\n\n      /* Diminish that bin and save where it goes */\n      b[k] -= *s[i];\n      a[(int)((uzoff_t huge *)(s[i]) - (uzoff_t huge *)e)] = k;\n    }\n\n    /* Clean up */\n    free((zvoid *)b);\n\n    /* Do until all items put in a bin */\n  } while (i < n);\n\n  /* Done--clean up and return the number of bins needed */\n  free((zvoid *)s);\n  free((zvoid *)e);\n  return m;\n}\n\n/* keep compiler happy until implement long options - 11/4/2003 EG */\nstruct option_struct far options[] = {\n  /* short longopt        value_type        negatable        ID    name */\n    {\"h\",  \"help\",        o_NO_VALUE,       o_NOT_NEGATABLE, 'h',  \"help\"},\n    /* the end of the list */\n    {NULL, NULL,          o_NO_VALUE,       o_NOT_NEGATABLE, 0,    NULL} /* end has option_ID = 0 */\n  };\n\n\nlocal int retry()\n{\n  char m[10];\n  fputs(\"Error writing to disk--redo entire disk? \", mesg);\n  fgets(m, 10, stdin);\n  return *m == 'y' || *m == 'Y';\n}\n\n\n#ifndef USE_ZIPSPLITMAIN\nint main(argc, argv)\n#else\nint zipsplitmain(argc, argv)\n#endif\n\nint argc;               /* number of tokens in command line */\nchar **argv;            /* command line tokens */\n/* Split a zip file into several zip files less than a specified size.  See\n   the command help in help() above. */\n{\n  uzoff_t *a;           /* malloc'ed list of sizes, dest bins */\n  extent *b;            /* heads of bin linked lists (malloc'ed) */\n  uzoff_t c;            /* bin capacity, start of central directory */\n  int d;                /* if true, just report the number of disks */\n  FILE *e;              /* input zip file */\n  FILE *f;              /* output index and zip files */\n  extent g;             /* number of bins from greedy(), entry to write */\n  int h;                /* how to split--true means simple split, counter */\n  zoff_t i = 0;            /* size of index file plus room to leave */\n  extent j;             /* steps through zip entries, bins */\n  int k;                /* next argument type */\n  extent *n = NULL;     /* next item in bin list (heads in b) */\n  uzoff_t *p;           /* malloc'ed list of sizes, dest bins for greedy() */\n  char *q;              /* steps through option characters */\n  int r;                /* temporary variable, counter */\n  extent s;             /* number of bins needed */\n  zoff_t t;             /* total of sizes, end of central directory */\n  int u;                /* flag to wait for user on output files */\n  struct zlist far **w; /* malloc'ed table for zfiles linked list */\n  int x;                /* if true, make an index file */\n  struct zlist far *z;  /* steps through zfiles linked list */\n#ifdef AMIGA\n  char tailchar;         /* temporary variable used in name generation below */\n#endif\n  char errbuf[5000];\n\n#ifdef THEOS\n  setlocale(LC_CTYPE, \"I\");\n#endif\n\n#ifdef UNICODE_SUPPORT\n# ifdef UNIX\n  /* For Unix, set the locale to UTF-8.  Any UTF-8 locale is\n     OK and they should all be the same.  This allows seeing,\n     writing, and displaying (if the fonts are loaded) all\n     characters in UTF-8. */\n  {\n    char *loc;\n\n    /*\n      loc = setlocale(LC_CTYPE, NULL);\n      printf(\"  Initial language locale = '%s'\\n\", loc);\n    */\n\n    loc = setlocale(LC_CTYPE, \"en_US.UTF-8\");\n\n    /*\n      printf(\"langinfo %s\\n\", nl_langinfo(CODESET));\n    */\n\n    if (loc != NULL) {\n      /* using UTF-8 character set so can set UTF-8 GPBF bit 11 */\n      using_utf8 = 1;\n      /*\n        printf(\"  Locale set to %s\\n\", loc);\n      */\n    } else {\n      /*\n        printf(\"  Could not set Unicode UTF-8 locale\\n\");\n      */\n    }\n  }\n# endif\n#endif\n\n  /* If no args, show help */\n  if (argc == 1)\n  {\n    help();\n    EXIT(ZE_OK);\n  }\n\n  /* Informational messages are written to stdout. */\n  mesg = stdout;\n\n  init_upper();           /* build case map table */\n\n  /* Go through args */\n  signal(SIGINT, handler);\n#ifdef SIGTERM                 /* Amiga has no SIGTERM */\n  signal(SIGTERM, handler);\n#endif\n#ifdef SIGABRT\n  signal(SIGABRT, handler);\n#endif\n#ifdef SIGBREAK\n  signal(SIGBREAK, handler);\n#endif\n#ifdef SIGBUS\n  signal(SIGBUS, handler);\n#endif\n#ifdef SIGILL\n  signal(SIGILL, handler);\n#endif\n#ifdef SIGSEGV\n  signal(SIGSEGV, handler);\n#endif\n  k = h = x = d = u = 0;\n  c = DEFSIZ;\n  for (r = 1; r < argc; r++)\n    if (*argv[r] == '-')\n    {\n      if (argv[r][1])\n        for (q = argv[r]+1; *q; q++)\n          switch (*q)\n          {\n            case 'b':   /* Specify path for output files */\n              if (k)\n                ziperr(ZE_PARMS, \"options are separate and precede zip file\");\n              else\n                k = 1;          /* Next non-option is path */\n              break;\n            case 'h':   /* Show help */\n              help();  EXIT(ZE_OK);\n            case 'i':   /* Make an index file */\n              x = 1;\n              break;\n            case 'l': case 'L':  /* Show copyright and disclaimer */\n              license();  EXIT(ZE_OK);\n            case 'n':   /* Specify maximum size of resulting zip files */\n              if (k)\n                ziperr(ZE_PARMS, \"options are separate and precede zip file\");\n              else\n                k = 2;          /* Next non-option is size */\n              break;\n            case 'p':\n              u = 1;\n              break;\n            case 'q':   /* Quiet operation, suppress info messages */\n              noisy = 0;\n              break;\n            case 'r':\n              if (k)\n                ziperr(ZE_PARMS, \"options are separate and precede zip file\");\n              else\n                k = 3;          /* Next non-option is room to leave */\n              break;\n            case 's':\n              h = 1;    /* Only try simple */\n              break;\n            case 't':   /* Just report number of disks */\n              d = 1;\n              break;\n            case 'v':   /* Show version info */\n              version_info();  EXIT(ZE_OK);\n            default:\n              ziperr(ZE_PARMS, \"Use option -h for help.\");\n          }\n      else\n        ziperr(ZE_PARMS, \"zip file cannot be stdin\");\n    }\n    else\n      switch (k)\n      {\n        case 0:\n          if (zipfile == NULL)\n          {\n            if ((zipfile = ziptyp(argv[r])) == NULL)\n              ziperr(ZE_MEM, \"was processing arguments\");\n          }\n          else\n            ziperr(ZE_PARMS, \"can only specify one zip file\");\n          break;\n        case 1:\n          tempath = argv[r];\n          k = 0;\n          break;\n        case 2:\n          if ((c = (ulg)atol(argv[r])) < 100)   /* 100 is smallest zip file */\n            ziperr(ZE_PARMS, \"invalid size given. Use option -h for help.\");\n          k = 0;\n          break;\n        default:        /* k must be 3 */\n          i = (ulg)atol(argv[r]);\n          k = 0;\n          break;\n      }\n  if (zipfile == NULL)\n    ziperr(ZE_PARMS, \"need to specify zip file\");\n\n  if ((in_path = malloc(strlen(zipfile) + 1)) == NULL) {\n    ziperr(ZE_MEM, \"input\");\n  }\n  strcpy(in_path, zipfile);\n\n  /* Read zip file */\n  if ((r = readzipfile()) != ZE_OK)\n    ziperr(r, zipfile);\n  if (zfiles == NULL)\n    ziperr(ZE_NAME, zipfile);\n\n  /* Make a list of sizes and check against capacity.  Also compute the\n     size of the index file. */\n  c -= ENDHEAD + 4;                     /* subtract overhead/zipfile */\n  if ((a = (uzoff_t *)talloc(zcount * sizeof(uzoff_t))) == NULL ||\n      (w = (struct zlist far **)talloc(zcount * sizeof(struct zlist far *))) ==\n       NULL)\n  {\n    ziperr(ZE_MEM, \"was computing split\");\n    return 1;\n  }\n  t = 0;\n  for (j = 0, z = zfiles; j < zcount; j++, z = z->nxt)\n  {\n    w[j] = z;\n    if (x)\n      i += z->nam + 6 + NL;\n    /* New scanzip_reg only reads central directory so use cext for ext */\n    t += a[j] = 8 + LOCHEAD + CENHEAD +\n           2 * (zoff_t)z->nam + 2 * (zoff_t)z->cext + z->com + z->siz;\n    if (a[j] > c) {\n      sprintf(errbuf, \"Entry is larger than max split size of: %s\",\n       zip_fzofft(c, NULL, \"u\"));\n      zipwarn(errbuf, \"\");\n      zipwarn(\"use -n to set split size\", \"\");\n      ziperr(ZE_BIG, z->zname);\n    }\n  }\n\n  /* Decide on split to use, report number of files */\n  if (h)\n    s = simple(a, zcount, c, i);\n  else\n  {\n    if ((p = (uzoff_t *)talloc(zcount * sizeof(uzoff_t))) == NULL)\n      ziperr(ZE_MEM, \"was computing split\");\n    memcpy((char *)p, (char *)a, zcount * sizeof(uzoff_t));\n    s = simple(a, zcount, c, i);\n    g = greedy(p, zcount, c, i);\n    if (s <= g)\n      tfree((zvoid *)p);\n    else\n    {\n      tfree((zvoid *)a);\n      a = p;\n      s = g;\n    }\n  }\n  printf(\"%ld zip files w%s be made (%s%% efficiency)\\n\",\n         (ulg)s, d ? \"ould\" : \"ill\",\n         zip_fzofft( ((200 * ((t + c - 1)/c)) / s + 1) / 2, NULL, \"d\"));\n  if (d)\n  {\n    tfreeall();\n    free((zvoid *)zipfile);\n    zipfile = NULL;\n    EXIT(ZE_OK);\n  }\n\n  /* Set up path for output files */\n  /* Point \"name\" past the path, where the filename should go */\n  if ((path = (char *)talloc(tempath == NULL ? 13 : strlen(tempath) + 14)) ==\n      NULL)\n    ziperr(ZE_MEM, \"was making output file names\");\n  if (tempath == NULL)\n     name = path;\n  else\n  {\n#ifndef VM_CMS\n    /* Copy the output path to the target */\n    strcpy(path, tempath);\n#endif\n#ifdef AMIGA\n    tailchar = path[strlen(path) - 1];  /* last character */\n    if (path[0] && (tailchar != '/') && (tailchar != ':'))\n      strcat(path, \"/\");\n#else\n#ifdef RISCOS\n    if (path[0] && path[strlen(path) - 1] != '.')\n      strcat(path, \".\");\n#else\n#ifdef QDOS\n    if (path[0] && path[strlen(path) - 1] != '_')\n      strcat(path, \"_\");\n#else\n#ifndef VMS\n    if (path[0] && path[strlen(path) - 1] != '/')\n      strcat(path, \"/\");\n#endif /* !VMS */\n#endif /* ?QDOS */\n#endif /* ?RISCOS */\n#endif /* ?AMIGA */\n    name = path + strlen(path);\n  }\n\n  /* Make linked lists of results */\n  if ((b = (extent *)talloc(s * sizeof(extent))) == NULL ||\n      (n = (extent *)talloc(zcount * sizeof(extent))) == NULL)\n    ziperr(ZE_MEM, \"was computing split\");\n  for (j = 0; j < s; j++)\n    b[j] = (extent)-1;\n  j = zcount;\n  while (j--)\n  {\n    g = (extent)a[j];\n    n[j] = b[g];\n    b[g] = j;\n  }\n\n  /* Make a name template for the zip files that is eight or less characters\n     before the .zip, and that will not overwrite the original zip file. */\n  for (k = 1, j = s; j >= 10; j /= 10)\n    k++;\n  if (k > 7)\n    ziperr(ZE_PARMS, \"way too many zip files must be made\");\n/*\n * XXX, ugly ....\n */\n/* Find the final \"path\" separator character */\n#ifdef QDOS\n  q = LastDir(zipfile);\n#else\n#ifdef VMS\n  if ((q = strrchr(zipfile, ']')) != NULL)\n#else\n#ifdef AMIGA\n  if (((q = strrchr(zipfile, '/')) != NULL)\n                       || ((q = strrchr(zipfile, ':'))) != NULL)\n#else\n#ifdef RISCOS\n  if ((q = strrchr(zipfile, '.')) != NULL)\n#else\n#ifdef MVS\n  if ((q = strrchr(zipfile, '.')) != NULL)\n#else\n  if ((q = strrchr(zipfile, '/')) != NULL)\n#endif /* MVS */\n#endif /* RISCOS */\n#endif /* AMIGA */\n#endif /* VMS */\n    q++;\n  else\n    q = zipfile;\n#endif /* QDOS */\n\n  r = 0;\n  while ((g = *q++) != '\\0' && g != ZPATH_SEP && r < 8 - k)\n    template[r++] = (char)g;\n  if (r == 0)\n    template[r++] = '_';\n  else if (g >= '0' && g <= '9')\n    template[r - 1] = (char)(template[r - 1] == '_' ? '-' : '_');\n  sprintf(template + r, TEMPL_FMT, k);\n#ifdef VM_CMS\n  /* For CMS, add the \"path\" as the filemode at the end */\n  if (tempath)\n  {\n     strcat(template,\".\");\n     strcat(template,tempath);\n  }\n#endif\n\n  /* Make the zip files from the linked lists of entry numbers */\n  if ((e = fopen(zipfile, FOPR)) == NULL)\n    ziperr(ZE_NAME, zipfile);\n  free((zvoid *)zipfile);\n  zipfile = NULL;\n  for (j = 0; j < s; j++)\n  {\n    /* jump here on a disk retry */\n  redobin:\n\n    current_disk = 0;\n    cd_start_disk = 0;\n    cd_entries_this_disk = 0;\n\n    /* prompt if requested */\n    if (u)\n    {\n      char m[10];\n      fprintf(mesg, \"Insert disk #%ld of %ld and hit return: \",\n              (ulg)j + 1, (ulg)s);\n      fgets(m, 10, stdin);\n    }\n\n    /* write index file on first disk if requested */\n    if (j == 0 && x)\n    {\n      strcpy(name, INDEX);\n      printf(\"creating: %s\\n\", path);\n      indexmade = 1;\n      if ((f = fopen(path, \"w\")) == NULL)\n      {\n        if (u && retry()) goto redobin;\n        ziperr(ZE_CREAT, path);\n      }\n      for (j = 0; j < zcount; j++)\n        fprintf(f, \"%5s %s\\n\",\n         zip_fzofft( (a[j] + 1), NULL, \"d\"), w[j]->zname);\n\n      if ((j = ferror(f)) != 0 || fclose(f))\n      {\n        if (j)\n          fclose(f);\n        if (u && retry()) goto redobin;\n        ziperr(ZE_WRITE, path);\n      }\n    }\n\n    /* create output zip file j */\n    sprintf(name, template, j + 1L);\n    printf(\"creating: %s\\n\", path);\n    zipsmade = j + 1;\n    if ((y = f = fopen(path, FOPW)) == NULL)\n    {\n      if (u && retry()) goto redobin;\n      ziperr(ZE_CREAT, path);\n    }\n    bytes_this_split = 0;\n    tempzn = 0;\n\n    /* write local headers and copy compressed data */\n    for (g = b[j]; g != (extent)-1; g = (extent)n[g])\n    {\n      if (zfseeko(e, w[g]->off, SEEK_SET))\n        ziperr(ferror(e) ? ZE_READ : ZE_EOF, zipfile);\n      in_file = e;\n      if ((r = zipcopy(w[g])) != ZE_OK)\n      {\n        if (r == ZE_TEMP)\n        {\n          if (u && retry()) goto redobin;\n          ziperr(ZE_WRITE, path);\n        }\n        else\n          ziperr(r, zipfile);\n      }\n    }\n\n    /* write central headers */\n    if ((c = zftello(f)) == (uzoff_t)-1)\n    {\n      if (u && retry()) goto redobin;\n      ziperr(ZE_WRITE, path);\n    }\n    for (g = b[j], k = 0; g != (extent)-1; g = n[g], k++)\n      if ((r = putcentral(w[g])) != ZE_OK)\n      {\n        if (u && retry()) goto redobin;\n        ziperr(ZE_WRITE, path);\n      }\n\n    /* write end-of-central header */\n    cd_start_offset = c;\n    total_cd_entries = k;\n    if ((t = zftello(f)) == (zoff_t)-1 ||\n        (r = putend((zoff_t)k, t - c, c, (extent)0, (char *)NULL)) !=\n        ZE_OK ||\n        ferror(f) || fclose(f))\n    {\n      if (u && retry()) goto redobin;\n      ziperr(ZE_WRITE, path);\n    }\n#ifdef RISCOS\n    /* Set the filetype to &DDC */\n    setfiletype(path,0xDDC);\n#endif\n  }\n  fclose(e);\n\n  /* Done! */\n  if (u)\n    fputs(\"Done.\\n\", mesg);\n  tfreeall();\n\n  RETURN(0);\n}\n"
  },
  {
    "path": "deps/infozip/zip30/zipsplit.txt",
    "content": "zipnote(1)                                                          zipnote(1)\n\nNAME\n       zipsplit - split a zipfile into smaller zipfiles\n\nSYNOPSIS\n       zipsplit  [-t]  [-i]  [-p] [-s] [-n size] [-r room] [-b path] [-h] [-v]\n       [-L] zipfile\n\nARGUMENTS\n       zipfile  Zipfile to split.\n\nOPTIONS\n       -t     Report how many files it will take, but don't make them.\n\n       -i     Make index (zipsplit.idx) and count its size against  first  zip\n              file.\n\n       -n size\n              Make zip files no larger than \"size\" (default = 36000).\n\n       -r room\n              Leave room for \"room\" bytes on the first disk (default = 0).\n\n       -b path\n              Use path for the output zip files.\n\n       -p     Pause between output zip files.\n\n       -s     Do a sequential split even if it takes more zip files.\n\n       -h     Show a short help.\n\n       -v     Show version information.\n\n       -L     Show software license.\n\nDESCRIPTION\n       zipsplit reads a zipfile and splits it into smaller zipfiles.\n\nEXAMPLES\n       To be filled in.\n\nBUGS\n       Does not yet support large (> 2 GB) or split archives.\n\nSEE ALSO\n       zip(1), unzip(1)\n\nAUTHOR\n       Info-ZIP\n\n                              v3.0 of 8 May 2008                    zipnote(1)\n"
  },
  {
    "path": "deps/infozip/zip30/zipup.c",
    "content": "/*\n  zipup.c - Zip 3\n\n  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2007-Mar-4 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n*/\n/*\n *  zipup.c by Mark Adler and Jean-loup Gailly.\n */\n#define __ZIPUP_C\n\n/* Found that for at least unix port zip.h has to be first or ctype.h will\n   define off_t and when using 64-bit file environment off_t in other files\n   is 8 bytes while off_t here is 4 bytes, and this makes the zlist struct\n   different sizes and needless to say leads to segmentation faults.  Putting\n   zip.h first seems to fix this.  8/14/04 EG */\n#include \"zip.h\"\n#include <ctype.h>\n#include <errno.h>\n\n#ifndef UTIL            /* This module contains no code for Zip Utilities */\n\n#include \"revision.h\"\n#include \"crc32.h\"\n#include \"crypt.h\"\n#ifdef USE_ZLIB\n#  include \"zlib.h\"\n#endif\n#ifdef BZIP2_SUPPORT\n#  ifdef BZIP2_USEBZIP2DIR\n#    include \"bzip2/bzlib.h\"\n#  else\n#    include \"bzlib.h\"\n#  endif\n#endif\n\n#ifdef OS2\n#  include \"os2/os2zip.h\"\n#endif\n\n#if defined(MMAP)\n#  include <sys/mman.h>\n#  ifndef PAGESIZE   /* used to be SYSV, what about pagesize on SVR3 ? */\n#    define PAGESIZE getpagesize()\n#  endif\n#  if defined(NO_VALLOC) && !defined(valloc)\n#    define valloc malloc\n#  endif\n#endif\n\n/* Use the raw functions for MSDOS and Unix to save on buffer space.\n   They're not used for VMS since it doesn't work (raw is weird on VMS).\n */\n\n#ifdef AMIGA\n#  include \"amiga/zipup.h\"\n#endif /* AMIGA */\n\n#ifdef AOSVS\n#  include \"aosvs/zipup.h\"\n#endif /* AOSVS */\n\n#ifdef ATARI\n#  include \"atari/zipup.h\"\n#endif\n\n#ifdef __BEOS__\n#  include \"beos/zipup.h\"\n#endif\n\n#ifdef __ATHEOS__\n#  include \"atheos/zipup.h\"\n#endif /* __ATHEOS__ */\n\n#ifdef __human68k__\n#  include \"human68k/zipup.h\"\n#endif /* __human68k__ */\n\n#ifdef MACOS\n#  include \"macos/zipup.h\"\n#endif\n\n#ifdef DOS\n#  include \"msdos/zipup.h\"\n#endif /* DOS */\n\n#ifdef NLM\n#  include \"novell/zipup.h\"\n#  include <nwfattr.h>\n#endif\n\n#ifdef OS2\n#  include \"os2/zipup.h\"\n#endif /* OS2 */\n\n#ifdef RISCOS\n#  include \"acorn/zipup.h\"\n#endif\n\n#ifdef TOPS20\n#  include \"tops20/zipup.h\"\n#endif\n\n#ifdef UNIX\n#  include \"unix/zipup.h\"\n#endif\n\n#ifdef CMS_MVS\n#  include \"zipup.h\"\n#endif /* CMS_MVS */\n\n#ifdef TANDEM\n#  include \"zipup.h\"\n#endif /* TANDEM */\n\n#ifdef VMS\n#  include \"vms/zipup.h\"\n#endif /* VMS */\n\n#ifdef QDOS\n#  include \"qdos/zipup.h\"\n#endif /* QDOS */\n\n#ifdef WIN32\n#  include \"win32/zipup.h\"\n#endif\n\n#ifdef THEOS\n#  include \"theos/zipup.h\"\n#endif\n\n/* Local functions */\n#ifndef RISCOS\n   local int suffixes OF((char *, char *));\n#else\n   local int filetypes OF((char *, char *));\n#endif\nlocal unsigned file_read OF((char *buf, unsigned size));\n#ifdef USE_ZLIB\n  local int zl_deflate_init OF((int pack_level));\n#else /* !USE_ZLIB */\n# ifdef ZP_NEED_MEMCOMPR\n    local unsigned mem_read OF((char *buf, unsigned size));\n# endif\n#endif /* ?USE_ZLIB */\n\n/* zip64 support 08/29/2003 R.Nausedat */\nlocal zoff_t filecompress OF((struct zlist far *z_entry, int *cmpr_method));\n\n#ifdef BZIP2_SUPPORT\nlocal zoff_t bzfilecompress OF((struct zlist far *z_entry, int *cmpr_method));\n#endif\n\n/* Deflate \"internal\" global data (currently not in zip.h) */\n#if defined(MMAP) || defined(BIG_MEM)\n# ifdef USE_ZLIB\n    local uch *window = NULL;   /* Used to read all input file at once */\n    local ulg window_size;      /* size of said window */\n# else /* !USE_ZLIB */\n    extern uch *window;         /* Used to read all input file at once */\n#endif /* ?USE_ZLIB */\n#endif /* MMAP || BIG_MEM */\n#ifndef USE_ZLIB\n  extern ulg window_size;       /* size of said window */\n\n  unsigned (*read_buf) OF((char *buf, unsigned size)) = file_read;\n  /* Current input function. Set to mem_read for in-memory compression */\n#endif /* !USE_ZLIB */\n\n\n/* Local data */\nlocal ulg crc;                  /* crc on uncompressed file data */\nlocal ftype ifile;              /* file to compress */\n#if defined(MMAP) || defined(BIG_MEM)\n  local ulg remain;\n  /* window bytes not yet processed.\n   *  special value \"(ulg)-1L\" reserved to signal normal reads.\n   */\n#endif /* MMAP || BIG_MEM */\n#ifdef USE_ZLIB\n  local int deflInit = FALSE;   /* flag: zlib deflate is initialized */\n  local z_stream zstrm;         /* zlib's data interface structure */\n  local char *f_ibuf = NULL;\n  local char *f_obuf = NULL;\n#else /* !USE_ZLIB */\n  local char file_outbuf[1024]; /* output buffer for compression to file */\n\n# ifdef ZP_NEED_MEMCOMPR\n    local char *in_buf;\n    /* Current input buffer, in_buf is used only for in-memory compression. */\n    local unsigned in_offset;\n    /* Current offset in input buffer. in_offset is used only for in-memory\n     * compression. On 16 bit machines, the buffer is limited to 64K.\n     */\n    local unsigned in_size;     /* size of current input buffer */\n# endif /* ZP_NEED_MEMCOMPR */\n#endif /* ?USE_ZLIB */\n\n#ifdef BZIP2_SUPPORT\n    local int bzipInit;         /* flag: bzip2lib is initialized */\n    local bz_stream bstrm;      /* zlib's data interface structure */\n# if !defined(USE_ZLIB)\n    local char *f_ibuf = NULL;\n    local char *f_obuf = NULL;\n# endif /* !USE_ZLIB */\n#endif /* BZIP2_SUPPORT */\n\n#ifdef DEBUG\n    zoff_t isize;               /* input file size. global only for debugging */\n#else /* !DEBUG */\n    local zoff_t isize;         /* input file size. global only for debugging */\n#endif /* ?DEBUG */\n  /* If file_read detects binary it sets this flag - 12/16/04 EG */\n  local int file_binary = 0;        /* first buf */\n  local int file_binary_final = 0;  /* for bzip2 for entire file.  assume text until find binary */\n\n\n/* moved check to function 3/14/05 EG */\nint is_seekable(y)\n  FILE *y;\n{\n  zoff_t pos;\n\n#ifdef BROKEN_FSEEK\n  if (!fseekable(y)) {\n    return 0;\n  }\n#endif\n\n  pos = zftello(y);\n  if (zfseeko(y, pos, SEEK_SET)) {\n    return 0;\n  }\n\n  return 1;\n}\n\n\nint percent(n, m)\n  uzoff_t n;\n  uzoff_t m;                    /* n is the original size, m is the new size */\n/* Return the percentage compression from n to m using only integer\n   operations */\n{\n  zoff_t p;\n\n#if 0\n  if (n > 0xffffffL)            /* If n >= 16M */\n  {                             /*  then divide n and m by 256 */\n    n += 0x80;  n >>= 8;\n    m += 0x80;  m >>= 8;\n  }\n  return n > m ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;\n#endif\n\n/* 2004-12-01 SMS.\n * Changed to do big-n test only for small zoff_t.\n * Changed big-n arithmetic to accomodate apparently negative values\n * when a small zoff_t value exceeds 2G.\n * Increased the reduction divisor from 256 to 512 to avoid the sign bit\n * in a reduced intermediate, allowing signed arithmetic for the final\n * result (which is no longer artificially limited to non-negative\n * values).\n * Note that right shifts must be on unsigned values to avoid undesired\n * sign extension.\n */\n\n/* Handle n = 0 case and account for int maybe being 16-bit.  12/28/2004 EG\n */\n\n#define PC_MAX_SAFE 0x007fffffL    /* 9 clear bits at high end. */\n#define PC_MAX_RND  0xffffff00L    /* 8 clear bits at low end. */\n\n  if (sizeof(uzoff_t) < 8)          /* Don't fiddle with big zoff_t. */\n  {\n    if ((ulg)n > PC_MAX_SAFE)       /* Reduce large values.  (n > m) */\n    {\n      if ((ulg)n < PC_MAX_RND)      /* Divide n by 512 with rounding, */\n        n = ((ulg)n + 0x100) >> 9;  /* if boost won't overflow. */\n      else                          /* Otherwise, use max value. */\n        n = PC_MAX_SAFE;\n\n      if ((ulg)m < PC_MAX_RND)      /* Divide m by 512 with rounding, */\n        m = ((ulg)m + 0x100) >> 9;  /* if boost won't overflow. */\n      else                          /* Otherwise, use max value. */\n        m = PC_MAX_SAFE;\n    }\n  }\n  if (n != 0)\n    p = ((200 * ((zoff_t)n - (zoff_t)m) / (zoff_t)n) + 1) / 2;\n  else\n    p = 0;\n  return (int)p;  /* Return (rounded) % reduction. */\n}\n\n\n#ifndef RISCOS\n\nlocal int suffixes(a, s)\n  char *a;                      /* name to check suffix of */\n  char *s;                      /* list of suffixes separated by : or ; */\n/* Return true if a ends in any of the suffixes in the list s. */\n{\n  int m;                        /* true if suffix matches so far */\n  char *p;                      /* pointer into special */\n  char *q;                      /* pointer into name a */\n\n#ifdef QDOS\n  short dlen = devlen(a);\n  a = a + dlen;\n#endif\n\n  m = 1;\n#ifdef VMS\n  if( (q = strrchr(a,';')) != NULL )    /* Cut out VMS file version */\n    --q;\n  else\n    q = a + strlen(a) - 1;\n#else /* !VMS */\n  q = a + strlen(a) - 1;\n#endif /* ?VMS */\n  for (p = s + strlen(s) - 1; p >= s; p--)\n    if (*p == ':' || *p == ';')\n    {\n      if (m)\n        return 1;\n      else\n      {\n        m = 1;\n#ifdef VMS\n        if( (q = strrchr(a,';')) != NULL )      /* Cut out VMS file version */\n          --q;\n        else\n          q = a + strlen(a) - 1;\n#else /* !VMS */\n        q = a + strlen(a) - 1;\n#endif /* ?VMS */\n      }\n    }\n    else\n    {\n      m = m && q >= a && case_map(*p) == case_map(*q);\n      q--;\n    }\n  return m;\n}\n\n#else /* RISCOS */\n\nlocal int filetypes(a, s)\nchar *a;                        /* extra field of file to check filetype of */\nchar *s;                        /* list of filetypes separated by : or ; */\n/* Return true if a is any of the filetypes in the list s. */\n{\n char *p;                       /* pointer into special */\n char typestr[4];               /* filetype hex string taken from a */\n\n if ((((unsigned*)a)[2] & 0xFFF00000) != 0xFFF00000) {\n /* The file is not filestamped, always try to compress it */\n   return 0;\n }\n\n sprintf(typestr,\"%.3X\",(((unsigned*)a)[2] & 0x000FFF00) >> 8);\n\n for (p=s;p<=s+strlen(s)-3;p+=3) { /* p+=3 to skip 3 hex type */\n   while (*p==':' || *p==';')\n     p++;\n\n   if (typestr[0] == toupper(p[0]) &&\n       typestr[1] == toupper(p[1]) &&\n       typestr[2] == toupper(p[2]))\n     return 1;\n }\n return 0;\n}\n#endif /* ?RISCOS */\n\n\n\n/* Note: a zip \"entry\" includes a local header (which includes the file\n   name), an encryption header if encrypting, the compressed data\n   and possibly an extended local header. */\n\nint zipup(z)\nstruct zlist far *z;    /* zip entry to compress */\n/* Compress the file z->name into the zip entry described by *z and write\n   it to the file *y. Encrypt if requested.  Return an error code in the\n   ZE_ class.  Also, update tempzn by the number of bytes written. */\n/* y is now global */\n{\n  iztimes f_utim;       /* UNIX GMT timestamps, filled by filetime() */\n  ulg tim;              /* time returned by filetime() */\n  ulg a = 0L;           /* attributes returned by filetime() */\n  char *b;              /* malloc'ed file buffer */\n  extent k = 0;         /* result of zread */\n  int l = 0;            /* true if this file is a symbolic link */\n  int m;                /* method for this entry */\n\n  zoff_t o = 0, p;      /* offsets in zip file */\n  zoff_t q = (zoff_t) -3; /* size returned by filetime */\n  uzoff_t uq;           /* unsigned q */\n  zoff_t s = 0;         /* size of compressed data */\n\n  int r;                /* temporary variable */\n  int isdir;            /* set for a directory name */\n  int set_type = 0;     /* set if file type (ascii/binary) unknown */\n  zoff_t last_o;        /* used to detect wrap around */\n\n  ush tempext = 0;      /* temp copies of extra fields */\n  ush tempcext = 0;\n  char *tempextra = NULL;\n  char *tempcextra = NULL;\n\n\n#ifdef WINDLL\n# ifdef ZIP64_SUPPORT\n  extern _int64 filesize64;\n  extern unsigned long low;\n  extern unsigned long high;\n#  endif\n#endif\n\n  z->nam = strlen(z->iname);\n  isdir = z->iname[z->nam-1] == (char)0x2f; /* ascii[(unsigned)('/')] */\n\n  file_binary = -1;      /* not set, set after first read */\n  file_binary_final = 0; /* not set, set after first read */\n\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n  if (!no_win32_wide)\n    tim = filetimew(z->namew, &a, &q, &f_utim);\n  else\n    tim = filetime(z->name, &a, &q, &f_utim);\n#else\n  tim = filetime(z->name, &a, &q, &f_utim);\n#endif\n  if (tim == 0 || q == (zoff_t) -3)\n    return ZE_OPEN;\n\n  /* q is set to -1 if the input file is a device, -2 for a volume label */\n  if (q == (zoff_t) -2) {\n     isdir = 1;\n     q = 0;\n  } else if (isdir != ((a & MSDOS_DIR_ATTR) != 0)) {\n     /* don't overwrite a directory with a file and vice-versa */\n     return ZE_MISS;\n  }\n  /* reset dot_count for each file */\n  if (!display_globaldots)\n    dot_count = -1;\n\n  /* display uncompressed size */\n  uq = ((uzoff_t) q > (uzoff_t) -3) ? 0 : (uzoff_t) q;\n  if (noisy && display_usize) {\n    fprintf(mesg, \" (\");\n    DisplayNumString( mesg, uq );\n    fprintf(mesg, \")\");\n    mesg_line_started = 1;\n    fflush(mesg);\n  }\n  if (logall && display_usize) {\n    fprintf(logfile, \" (\");\n    DisplayNumString( logfile, uq );\n    fprintf(logfile, \")\");\n    logfile_line_started = 1;\n    fflush(logfile);\n  }\n\n  /* initial z->len so if error later have something */\n  z->len = uq;\n\n  z->att = (ush)UNKNOWN; /* will be changed later */\n  z->atx = 0; /* may be changed by set_extra_field() */\n\n  /* Free the old extra fields which are probably obsolete */\n  /* Should probably read these and keep any we don't update.  12/30/04 EG */\n  if (extra_fields == 2) {\n    /* If keeping extra fields, make copy before clearing for set_extra_field()\n       A better approach is to modify the port code, but maybe later */\n    if (z->ext) {\n      if ((tempextra = malloc(z->ext)) == NULL) {\n        ZIPERR(ZE_MEM, \"extra fields copy\");\n      }\n      memcpy(tempextra, z->extra, z->ext);\n      tempext = z->ext;\n    }\n    if (z->cext) {\n      if ((tempcextra = malloc(z->cext)) == NULL) {\n        ZIPERR(ZE_MEM, \"extra fields copy\");\n      }\n      memcpy(tempcextra, z->cextra, z->cext);\n      tempcext = z->cext;\n    }\n  }\n  if (z->ext) {\n    free((zvoid *)(z->extra));\n  }\n  if (z->cext && z->extra != z->cextra) {\n    free((zvoid *)(z->cextra));\n  }\n  z->extra = z->cextra = NULL;\n  z->ext = z->cext = 0;\n\n#if defined(MMAP) || defined(BIG_MEM)\n  remain = (ulg)-1L; /* changed only for MMAP or BIG_MEM */\n#endif /* MMAP || BIG_MEM */\n#if (!defined(USE_ZLIB) || defined(MMAP) || defined(BIG_MEM))\n  window_size = 0L;\n#endif /* !USE_ZLIB || MMAP || BIG_MEM */\n\n  /* Select method based on the suffix and the global method */\n#ifndef RISCOS\n  m = special != NULL && suffixes(z->name, special) ? STORE : method;\n#else /* RISCOS  must set m after setting extra field */\n  m = method;\n#endif /* ?RISCOS */\n\n  /* For now force deflate if using descriptors.  Instead zip and unzip\n     could check bytes read against compressed size in each data descriptor\n     found and skip over any that don't match.  This is how at least one\n     other zipper does it.  To be added later.  Until then it\n     probably doesn't hurt to force deflation when streaming.  12/30/04 EG\n  */\n\n  /* Now is a good time.  For now allow storing for testing.  12/16/05 EG */\n  /* By release need to force deflation based on reports some inflate\n     streamed data to find the end of the data */\n  /* Need to handle bzip2 */\n#ifdef NO_STREAMING_STORE\n  if (use_descriptors && m == STORE)\n  {\n      m = DEFLATE;\n  }\n#endif\n\n  /* Open file to zip up unless it is stdin */\n  if (strcmp(z->name, \"-\") == 0)\n  {\n    ifile = (ftype)zstdin;\n#if defined(MSDOS) || defined(__human68k__)\n    if (isatty(zstdin) == 0)  /* keep default mode if stdin is a terminal */\n      setmode(zstdin, O_BINARY);\n#endif\n    z->tim = tim;\n  }\n  else\n  {\n#if !(defined(VMS) && defined(VMS_PK_EXTRA))\n    if (extra_fields) {\n      /* create extra field and change z->att and z->atx if desired */\n      set_extra_field(z, &f_utim);\n# ifdef QLZIP\n      if(qlflag)\n          a |= (S_IXUSR) << 16;   /* Cross compilers don't set this */\n# endif\n# ifdef RISCOS\n      m = special != NULL && filetypes(z->extra, special) ? STORE : method;\n# endif /* RISCOS */\n\n      /* For now allow store for testing */\n#ifdef NO_STREAMING_STORE\n      /* For now force deflation if using data descriptors. */\n      if (use_descriptors && m == STORE)\n      {\n        m = DEFLATE;\n      }\n#endif\n\n    }\n#endif /* !(VMS && VMS_PK_EXTRA) */\n    l = issymlnk(a);\n    if (l) {\n      ifile = fbad;\n      m = STORE;\n    }\n    else if (isdir) { /* directory */\n      ifile = fbad;\n      m = STORE;\n      q = 0;\n    }\n#ifdef THEOS\n    else if (((a >> 16) & S_IFMT) == S_IFLIB) {   /* library */\n      ifile = fbad;\n      m = STORE;\n      q = 0;\n    }\n#endif\n    else {\n#ifdef CMS_MVS\n      if (bflag) {\n        if ((ifile = zopen(z->name, fhowb)) == fbad)\n           return ZE_OPEN;\n      }\n      else\n#endif /* CMS_MVS */\n#if defined(UNICODE_SUPPORT) && defined(WIN32)\n      if (!no_win32_wide) {\n        if ((ifile = zwopen(z->namew, fhow)) == fbad)\n          return ZE_OPEN;\n      } else {\n        if ((ifile = zopen(z->name, fhow)) == fbad)\n          return ZE_OPEN;\n      }\n#else\n      if ((ifile = zopen(z->name, fhow)) == fbad)\n        return ZE_OPEN;\n#endif\n    }\n\n    z->tim = tim;\n\n#if defined(VMS) && defined(VMS_PK_EXTRA)\n    /* vms_get_attributes must be called after vms_open() */\n    if (extra_fields) {\n      /* create extra field and change z->att and z->atx if desired */\n      vms_get_attributes(ifile, z, &f_utim);\n    }\n#endif /* VMS && VMS_PK_EXTRA */\n\n#if defined(MMAP) || defined(BIG_MEM)\n    /* Map ordinary files but not devices. This code should go in fileio.c */\n    if (!translate_eol && m != STORE && q != -1L && (ulg)q > 0 &&\n        (ulg)q + MIN_LOOKAHEAD > (ulg)q) {\n# ifdef MMAP\n      /* Map the whole input file in memory */\n      if (window != NULL)\n        free(window);  /* window can't be a mapped file here */\n      window_size = (ulg)q + MIN_LOOKAHEAD;\n      remain = window_size & (PAGESIZE-1);\n      /* If we can't touch the page beyond the end of file, we must\n       * allocate an extra page.\n       */\n      if (remain > MIN_LOOKAHEAD) {\n        window = (uch*)mmap(0, window_size, PROT_READ, MAP_PRIVATE, ifile, 0);\n      } else {\n        window = (uch*)valloc(window_size - remain + PAGESIZE);\n        if (window != NULL) {\n          window = (uch*)mmap((char*)window, window_size - remain, PROT_READ,\n                        MAP_PRIVATE | MAP_FIXED, ifile, 0);\n        } else {\n          window = (uch*)(-1);\n        }\n      }\n      if (window == (uch*)(-1)) {\n        Trace((mesg, \" mmap failure on %s\\n\", z->name));\n        window = NULL;\n        window_size = 0L;\n        remain = (ulg)-1L;\n      } else {\n        remain = (ulg)q;\n      }\n# else /* !MMAP, must be BIG_MEM */\n      /* Read the whole input file at once */\n      window_size = (ulg)q + MIN_LOOKAHEAD;\n      window = window ? (uch*) realloc(window, (unsigned)window_size)\n                      : (uch*) malloc((unsigned)window_size);\n      /* Just use normal code if big malloc or realloc fails: */\n      if (window != NULL) {\n        remain = (ulg)zread(ifile, (char*)window, q+1);\n        if (remain != (ulg)q) {\n          fprintf(mesg, \" q=%lu, remain=%lu \", (ulg)q, remain);\n          error(\"can't read whole file at once\");\n        }\n      } else {\n        window_size = 0L;\n      }\n# endif /* ?MMAP */\n    }\n#endif /* MMAP || BIG_MEM */\n\n  } /* strcmp(z->name, \"-\") == 0 */\n\n  if (extra_fields == 2) {\n    unsigned len;\n    char *p;\n\n    /* step through old extra fields and copy over any not already\n       in new extra fields */\n    p = copy_nondup_extra_fields(tempextra, tempext, z->extra, z->ext, &len);\n    free(z->extra);\n    z->ext = len;\n    z->extra = p;\n    p = copy_nondup_extra_fields(tempcextra, tempcext, z->cextra, z->cext, &len);\n    free(z->cextra);\n    z->cext = len;\n    z->cextra = p;\n\n    if (tempext)\n      free(tempextra);\n    if (tempcext)\n      free(tempcextra);\n  }\n\n  if (q == 0)\n    m = STORE;\n  if (m == BEST)\n    m = DEFLATE;\n\n  /* Do not create STORED files with extended local headers if the\n   * input size is not known, because such files could not be extracted.\n   * So if the zip file is not seekable and the input file is not\n   * on disk, obey the -0 option by forcing deflation with stored block.\n   * Note however that using \"zip -0\" as filter is not very useful...\n   * ??? to be done.\n   */\n\n  /* An alternative used by others is to allow storing but on reading do\n   * a second check when a signature is found.  This is simply to check\n   * the compressed size to the bytes read since the start of the file data.\n   * If this is the right signature then the compressed size should match\n   * the size of the compressed data to that point.  If not look for the\n   * next signature.  We should do this.  12/31/04 EG\n   *\n   * For reading and testing we should do this, but should not write\n   * stored streamed data unless for testing as finding the end of\n   * streamed deflated data can be done by inflating.  6/26/06 EG\n   */\n\n  /* Fill in header information and write local header to zip file.\n   * This header will later be re-written since compressed length and\n   * crc are not yet known.\n   */\n\n  /* (Assume ext, cext, com, and zname already filled in.) */\n#if defined(OS2) || defined(WIN32)\n# ifdef WIN32_OEM\n  /* When creating OEM-coded names on Win32, the entries must always be marked\n     as \"created on MSDOS\" (OS_CODE = 0), because UnZip needs to handle archive\n     entry names just like those created by Zip's MSDOS port.\n   */\n  z->vem = (ush)(dosify ? 20 : 0 + Z_MAJORVER * 10 + Z_MINORVER);\n# else\n  z->vem = (ush)(z->dosflag ? (dosify ? 20 : /* Made under MSDOS by PKZIP 2.0 */\n                               (0 + Z_MAJORVER * 10 + Z_MINORVER))\n                 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);\n  /* For a plain old (8+3) FAT file system, we cheat and pretend that the file\n   * was not made on OS2/WIN32 but under DOS. unzip is confused otherwise.\n   */\n# endif\n#else /* !(OS2 || WIN32) */\n  z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);\n#endif /* ?(OS2 || WIN32) */\n\n  z->ver = (ush)(m == STORE ? 10 : 20); /* Need PKUNZIP 2.0 except for store */\n#ifdef BZIP2_SUPPORT\n  if (method == BZIP2)\n      z->ver = (ush)(m == STORE ? 10 : 46);\n#endif\n  z->crc = 0;  /* to be updated later */\n  /* Assume first that we will need an extended local header: */\n  if (isdir)\n    /* If dir then q = 0 and extended header not needed */\n    z->flg = 0;\n  else\n    z->flg = 8;  /* to be updated later */\n#if CRYPT\n  if (!isdir && key != NULL) {\n    z->flg |= 1;\n    /* Since we do not yet know the crc here, we pretend that the crc\n     * is the modification time:\n     */\n    z->crc = z->tim << 16;\n    /* More than pretend.  File is encrypted using crypt header with that. */\n  }\n#endif /* CRYPT */\n  z->lflg = z->flg;\n  z->how = (ush)m;                              /* may be changed later  */\n  z->siz = (zoff_t)(m == STORE && q >= 0 ? q : 0); /* will be changed later */\n  z->len = (zoff_t)(q != -1L ? q : 0);          /* may be changed later  */\n  if (z->att == (ush)UNKNOWN) {\n      z->att = BINARY;                    /* set sensible value in header */\n      set_type = 1;\n  }\n  /* Attributes from filetime(), flag bits from set_extra_field(): */\n#if defined(DOS) || defined(OS2) || defined(WIN32)\n  z->atx = z->dosflag ? a & 0xff : a | (z->atx & 0x0000ff00);\n#else\n  z->atx = dosify ? a & 0xff : a | (z->atx & 0x0000ff00);\n#endif /* DOS || OS2 || WIN32 */\n\n  if ((r = putlocal(z, PUTLOCAL_WRITE)) != ZE_OK) {\n    if (ifile != fbad)\n      zclose(ifile);\n    return r;\n  }\n\n  /* now get split information set by bfwrite() */\n  z->off = current_local_offset;\n\n  /* disk local header was written to */\n  z->dsk = current_local_disk;\n\n  tempzn += 4 + LOCHEAD + z->nam + z->ext;\n\n\n#if CRYPT\n  if (!isdir && key != NULL) {\n    crypthead(key, z->crc);\n    z->siz += RAND_HEAD_LEN;  /* to be updated later */\n    tempzn += RAND_HEAD_LEN;\n  }\n#endif /* CRYPT */\n  if (ferror(y)) {\n    if (ifile != fbad)\n      zclose(ifile);\n    ZIPERR(ZE_WRITE, \"unexpected error on zip file\");\n  }\n\n  last_o = o;\n  o = zftello(y); /* for debugging only, ftell can fail on pipes */\n  if (ferror(y))\n    clearerr(y);\n\n  if (o != -1 && last_o > o) {\n    fprintf(mesg, \"last %s o %s\\n\", zip_fzofft(last_o, NULL, NULL),\n                                    zip_fzofft(o, NULL, NULL));\n    ZIPERR(ZE_BIG, \"seek wrap - zip file too big to write\");\n  }\n\n  /* Write stored or deflated file to zip file */\n  isize = 0L;\n  crc = CRCVAL_INITIAL;\n\n  if (isdir) {\n    /* nothing to write */\n  }\n  else if (m != STORE) {\n    if (set_type) z->att = (ush)UNKNOWN;\n    /* ... is finally set in file compression routine */\n#ifdef BZIP2_SUPPORT\n    if (m == BZIP2) {\n      s = bzfilecompress(z, &m);\n    }\n    else\n#endif /* BZIP2_SUPPORT */\n    {\n      s = filecompress(z, &m);\n    }\n#ifndef PGP\n    if (z->att == (ush)BINARY && translate_eol && file_binary) {\n      if (translate_eol == 1)\n        zipwarn(\"has binary so -l ignored\", \"\");\n      else\n        zipwarn(\"has binary so -ll ignored\", \"\");\n    }\n    else if (z->att == (ush)BINARY && translate_eol) {\n      if (translate_eol == 1)\n        zipwarn(\"-l used on binary file - corrupted?\", \"\");\n      else\n        zipwarn(\"-ll used on binary file - corrupted?\", \"\");\n    }\n#endif\n  }\n  else\n  {\n    if ((b = malloc(SBSZ)) == NULL)\n       return ZE_MEM;\n\n    if (l) {\n      k = rdsymlnk(z->name, b, SBSZ);\n/*\n * compute crc first because zfwrite will alter the buffer b points to !!\n */\n      crc = crc32(crc, (uch *) b, k);\n      if (zfwrite(b, 1, k) != k)\n      {\n        free((zvoid *)b);\n        return ZE_TEMP;\n      }\n      isize = k;\n\n#ifdef MINIX\n      q = k;\n#endif /* MINIX */\n    }\n    else\n    {\n      while ((k = file_read(b, SBSZ)) > 0 && k != (extent) EOF)\n      {\n        if (zfwrite(b, 1, k) != k)\n        {\n          if (ifile != fbad)\n            zclose(ifile);\n          free((zvoid *)b);\n          return ZE_TEMP;\n        }\n        if (!display_globaldots) {\n          if (dot_size > 0) {\n            /* initial space */\n            if (noisy && dot_count == -1) {\n#ifndef WINDLL\n              putc(' ', mesg);\n              fflush(mesg);\n#else\n              fprintf(stdout,\"%c\",' ');\n#endif\n              dot_count++;\n            }\n            dot_count++;\n            if (dot_size <= (dot_count + 1) * SBSZ) dot_count = 0;\n          }\n          if ((verbose || noisy) && dot_size && !dot_count) {\n#ifndef WINDLL\n            putc('.', mesg);\n            fflush(mesg);\n#else\n            fprintf(stdout,\"%c\",'.');\n#endif\n            mesg_line_started = 1;\n          }\n        }\n      }\n    }\n    free((zvoid *)b);\n    s = isize;\n  }\n  if (ifile != fbad && zerr(ifile)) {\n    perror(\"\\nzip warning\");\n    if (logfile)\n      fprintf(logfile, \"\\nzip warning: %s\\n\", strerror(errno));\n    zipwarn(\"could not read input file: \", z->oname);\n  }\n  if (ifile != fbad)\n    zclose(ifile);\n#ifdef MMAP\n  if (remain != (ulg)-1L) {\n    munmap((caddr_t) window, window_size);\n    window = NULL;\n  }\n#endif /*MMAP */\n\n  tempzn += s;\n  p = tempzn; /* save for future fseek() */\n\n#if (!defined(MSDOS) || defined(OS2))\n#if !defined(VMS) && !defined(CMS_MVS) && !defined(__mpexl)\n  /* Check input size (but not in VMS -- variable record lengths mess it up)\n   * and not on MSDOS -- diet in TSR mode reports an incorrect file size)\n   */\n#ifndef TANDEM /* Tandem EOF does not match byte count unless Unstructured */\n  if (!translate_eol && q != -1L && isize != q)\n  {\n    Trace((mesg, \" i=%lu, q=%lu \", isize, q));\n    zipwarn(\" file size changed while zipping \", z->name);\n  }\n#endif /* !TANDEM */\n#endif /* !VMS && !CMS_MVS && !__mpexl */\n#endif /* (!MSDOS || OS2) */\n\n  if (isdir)\n  {\n    /* A directory */\n    z->siz = 0;\n    z->len = 0;\n    z->how = STORE;\n    z->ver = 10;\n    /* never encrypt directory so don't need extended local header */\n    z->flg &= ~8;\n    z->lflg &= ~8;\n  }\n  else\n  {\n    /* Try to rewrite the local header with correct information */\n    z->crc = crc;\n    z->siz = s;\n#if CRYPT\n    if (!isdir && key != NULL)\n      z->siz += RAND_HEAD_LEN;\n#endif /* CRYPT */\n    z->len = isize;\n    /* if can seek back to local header */\n#ifdef BROKEN_FSEEK\n    if (use_descriptors || !fseekable(y) || zfseeko(y, z->off, SEEK_SET))\n#else\n    if (use_descriptors || zfseeko(y, z->off, SEEK_SET))\n#endif\n    {\n      if (z->how != (ush) m)\n         error(\"can't rewrite method\");\n      if (m == STORE && q < 0)\n         ZIPERR(ZE_PARMS, \"zip -0 not supported for I/O on pipes or devices\");\n      if ((r = putextended(z)) != ZE_OK)\n        return r;\n      /* if Zip64 and not seekable then Zip64 data descriptor */\n#ifdef ZIP64_SUPPORT\n      tempzn += (zip64_entry ? 24L : 16L);\n#else\n      tempzn += 16L;\n#endif\n      z->flg = z->lflg; /* if z->flg modified by deflate */\n    } else {\n      /* ftell() not as useful across splits */\n      if (bytes_this_entry != (uzoff_t)(key ? s + 12 : s)) {\n        fprintf(mesg, \" s=%s, actual=%s \",\n                zip_fzofft(s, NULL, NULL), zip_fzofft(bytes_this_entry, NULL, NULL));\n        error(\"incorrect compressed size\");\n      }\n#if 0\n       /* seek ok, ftell() should work, check compressed size */\n# if !defined(VMS) && !defined(CMS_MVS)\n      if (p - o != s) {\n        fprintf(mesg, \" s=%s, actual=%s \",\n                zip_fzofft(s, NULL, NULL), zip_fzofft(p-o, NULL, NULL));\n        error(\"incorrect compressed size\");\n      }\n# endif /* !VMS && !CMS_MVS */\n#endif /* 0 */\n      z->how = (ush)m;\n      switch (m)\n      {\n      case STORE:\n        z->ver = 10; break;\n      /* Need PKUNZIP 2.0 for DEFLATE */\n      case DEFLATE:\n        z->ver = 20; break;\n#ifdef BZIP2_SUPPORT\n      case BZIP2:\n        z->ver = 46; break;\n#endif\n      }\n      /*\n       * The encryption header needs the crc, but we don't have it\n       * for a new file.  The file time is used instead and the encryption\n       * header then used to encrypt the data.  The AppNote standard only\n       * can be applied to a file that the crc is known, so that means\n       * either an existing entry in an archive or get the crc before\n       * creating the encryption header and then encrypt the data.\n       */\n      if ((z->flg & 1) == 0) {\n        /* not encrypting so don't need extended local header */\n        z->flg &= ~8;\n      }\n      /* deflate may have set compression level bit markers in z->flg,\n         and we can't think of any reason central and local flags should\n         be different. */\n      z->lflg = z->flg;\n\n      /* If not using descriptors, back up and rewrite local header. */\n      if (split_method == 1 && current_local_file != y) {\n        if (zfseeko(current_local_file, z->off, SEEK_SET))\n          return ZE_READ;\n      }\n\n      /* if local header in another split, putlocal will close it */\n      if ((r = putlocal(z, PUTLOCAL_REWRITE)) != ZE_OK)\n        return r;\n\n      if (zfseeko(y, bytes_this_split, SEEK_SET))\n        return ZE_READ;\n\n      if ((z->flg & 1) != 0) {\n        /* encrypted file, extended header still required */\n        if ((r = putextended(z)) != ZE_OK)\n          return r;\n#ifdef ZIP64_SUPPORT\n        if (zip64_entry)\n          tempzn += 24L;\n        else\n          tempzn += 16L;\n#else\n        tempzn += 16L;\n#endif\n      }\n    }\n  } /* isdir */\n  /* Free the local extra field which is no longer needed */\n  if (z->ext) {\n    if (z->extra != z->cextra) {\n      free((zvoid *)(z->extra));\n      z->extra = NULL;\n    }\n    z->ext = 0;\n  }\n\n  /* Display statistics */\n  if (noisy)\n  {\n    if (verbose) {\n      fprintf( mesg, \"\\t(in=%s) (out=%s)\",\n               zip_fzofft(isize, NULL, \"u\"), zip_fzofft(s, NULL, \"u\"));\n    }\n#ifdef BZIP2_SUPPORT\n    if (m == BZIP2)\n      fprintf(mesg, \" (bzipped %d%%)\\n\", percent(isize, s));\n    else\n#endif\n    if (m == DEFLATE)\n      fprintf(mesg, \" (deflated %d%%)\\n\", percent(isize, s));\n    else\n      fprintf(mesg, \" (stored 0%%)\\n\");\n    mesg_line_started = 0;\n    fflush(mesg);\n  }\n  if (logall)\n  {\n#ifdef BZIP2_SUPPORT\n    if (m == BZIP2)\n      fprintf(logfile, \" (bzipped %d%%)\\n\", percent(isize, s));\n    else\n#endif\n    if (m == DEFLATE)\n      fprintf(logfile, \" (deflated %d%%)\\n\", percent(isize, s));\n    else\n      fprintf(logfile, \" (stored 0%%)\\n\");\n    logfile_line_started = 0;\n    fflush(logfile);\n  }\n\n#ifdef WINDLL\n# ifdef ZIP64_SUPPORT\n   /* The DLL api has been updated and uses a different\n      interface.  7/24/04 EG */\n   if (lpZipUserFunctions->ServiceApplication64 != NULL)\n    {\n    if ((*lpZipUserFunctions->ServiceApplication64)(z->zname, isize))\n                ZIPERR(ZE_ABORT, \"User terminated operation\");\n    }\n  else\n   {\n   filesize64 = isize;\n   low = (unsigned long)(filesize64 & 0x00000000FFFFFFFF);\n   high = (unsigned long)((filesize64 >> 32) & 0x00000000FFFFFFFF);\n   if (lpZipUserFunctions->ServiceApplication64_No_Int64 != NULL) {\n    if ((*lpZipUserFunctions->ServiceApplication64_No_Int64)(z->zname, low, high))\n                ZIPERR(ZE_ABORT, \"User terminated operation\");\n    }\n   }\n# else\n  if (lpZipUserFunctions->ServiceApplication != NULL)\n  {\n    if ((*lpZipUserFunctions->ServiceApplication)(z->zname, isize))\n    {\n      ZIPERR(ZE_ABORT, \"User terminated operation\");\n    }\n  }\n# endif\n#endif\n\n  return ZE_OK;\n}\n\n\n\n\nlocal unsigned file_read(buf, size)\n  char *buf;\n  unsigned size;\n/* Read a new buffer from the current input file, perform end-of-line\n * translation, and update the crc and input file size.\n * IN assertion: size >= 2 (for end-of-line translation)\n */\n{\n  unsigned len;\n  char *b;\n  zoff_t isize_prev;    /* Previous isize.  Used for overflow check. */\n\n#if defined(MMAP) || defined(BIG_MEM)\n  if (remain == 0L) {\n    return 0;\n  } else if (remain != (ulg)-1L) {\n    /* The window data is already in place. We still compute the crc\n     * by 32K blocks instead of once on whole file to keep a certain\n     * locality of reference.\n     */\n    Assert(buf == (char*)window + isize, \"are you lost?\");\n    if ((ulg)size > remain) size = (unsigned)remain;\n    if (size > WSIZE) size = WSIZE; /* don't touch all pages at once */\n    remain -= (ulg)size;\n    len = size;\n  } else\n#endif /* MMAP || BIG_MEM */\n  if (translate_eol == 0) {\n    len = zread(ifile, buf, size);\n    if (len == (unsigned)EOF || len == 0) return len;\n#ifdef OS390\n    b = buf;\n    if (aflag == ASCII) {\n      while (*b != '\\0') {\n        *b = (char)ascii[(uch)*b];\n        b++;\n      }\n    }\n#endif\n  } else if (translate_eol == 1) {\n    /* translate_eol == 1 */\n    /* Transform LF to CR LF */\n    size >>= 1;\n    b = buf+size;\n    size = len = zread(ifile, b, size);\n    if (len == (unsigned)EOF || len == 0) return len;\n\n    /* check buf for binary - 12/16/04 */\n    if (file_binary == -1) {\n      /* first read */\n      file_binary = is_text_buf(b, size) ? 0 : 1;\n    }\n\n    if (file_binary != 1) {\n#ifdef EBCDIC\n      if (aflag == ASCII)\n      {\n         do {\n            char c;\n\n            if ((c = *b++) == '\\n') {\n               *buf++ = CR; *buf++ = LF; len++;\n            } else {\n              *buf++ = (char)ascii[(uch)c];\n            }\n         } while (--size != 0);\n      }\n      else\n#endif /* EBCDIC */\n      {\n         do {\n            if ((*buf++ = *b++) == '\\n') *(buf-1) = CR, *buf++ = LF, len++;\n         } while (--size != 0);\n      }\n      buf -= len;\n    } else { /* do not translate binary */\n      memcpy(buf, b, size);\n    }\n\n  } else {\n    /* translate_eol == 2 */\n    /* Transform CR LF to LF and suppress final ^Z */\n    b = buf;\n    size = len = zread(ifile, buf, size-1);\n    if (len == (unsigned)EOF || len == 0) return len;\n\n    /* check buf for binary - 12/16/04 */\n    if (file_binary == -1) {\n      /* first read */\n      file_binary = is_text_buf(b, size) ? 0 : 1;\n    }\n\n    if (file_binary != 1) {\n      buf[len] = '\\n'; /* I should check if next char is really a \\n */\n#ifdef EBCDIC\n      if (aflag == ASCII)\n      {\n         do {\n            char c;\n\n            if ((c = *b++) == '\\r' && *b == '\\n') {\n               len--;\n            } else {\n               *buf++ = (char)(c == '\\n' ? LF : ascii[(uch)c]);\n            }\n         } while (--size != 0);\n      }\n      else\n#endif /* EBCDIC */\n      {\n         do {\n            if (( *buf++ = *b++) == CR && *b == LF) buf--, len--;\n         } while (--size != 0);\n      }\n      if (len == 0) {\n         zread(ifile, buf, 1); len = 1; /* keep single \\r if EOF */\n#ifdef EBCDIC\n         if (aflag == ASCII) {\n            *buf = (char)(*buf == '\\n' ? LF : ascii[(uch)(*buf)]);\n         }\n#endif\n      } else {\n         buf -= len;\n         if (buf[len-1] == CTRLZ) len--; /* suppress final ^Z */\n      }\n    }\n  }\n  crc = crc32(crc, (uch *) buf, len);\n  /* 2005-05-23 SMS.\n     Increment file size.  A small-file program reading a large file may\n     cause isize to overflow, so complain (and abort) if it goes\n     negative or wraps around.  Awful things happen later otherwise.\n  */\n  isize_prev = isize;\n  isize += (ulg)len;\n  if (isize < isize_prev) {\n    ZIPERR(ZE_BIG, \"overflow in byte count\");\n  }\n  return len;\n}\n\n\n#ifdef USE_ZLIB\n\nlocal int zl_deflate_init(pack_level)\n    int pack_level;\n{\n    unsigned i;\n    int windowBits;\n    int err = Z_OK;\n    int zp_err = ZE_OK;\n\n    if (zlib_version[0] != ZLIB_VERSION[0]) {\n        sprintf(errbuf, \"incompatible zlib version (expected %s, found %s)\",\n              ZLIB_VERSION, zlib_version);\n        zp_err = ZE_LOGIC;\n    } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) {\n        fprintf(mesg,\n                \"\\twarning:  different zlib version (expected %s, using %s)\\n\",\n                ZLIB_VERSION, zlib_version);\n    }\n\n    /* windowBits = log2(WSIZE) */\n    for (i = ((unsigned)WSIZE), windowBits = 0; i != 1; i >>= 1, ++windowBits);\n\n    zstrm.zalloc = (alloc_func)Z_NULL;\n    zstrm.zfree = (free_func)Z_NULL;\n\n    Trace((stderr, \"initializing deflate()\\n\"));\n    err = deflateInit2(&zstrm, pack_level, Z_DEFLATED, -windowBits, 8, 0);\n\n    if (err == Z_MEM_ERROR) {\n        sprintf(errbuf, \"cannot initialize zlib deflate\");\n        zp_err = ZE_MEM;\n    } else if (err != Z_OK) {\n        sprintf(errbuf, \"zlib deflateInit failure (%d)\", err);\n        zp_err = ZE_LOGIC;\n    }\n\n    deflInit = TRUE;\n    return zp_err;\n}\n\n\nvoid zl_deflate_free()\n{\n    int err;\n\n    if (f_obuf != NULL) {\n        free(f_obuf);\n        f_obuf = NULL;\n    }\n    if (f_ibuf != NULL) {\n        free(f_ibuf);\n        f_ibuf = NULL;\n    }\n    if (deflInit) {\n        err = deflateEnd(&zstrm);\n        if (err != Z_OK && err !=Z_DATA_ERROR) {\n            ziperr(ZE_LOGIC, \"zlib deflateEnd failed\");\n        }\n        deflInit = FALSE;\n    }\n}\n\n#else /* !USE_ZLIB */\n\n# ifdef ZP_NEED_MEMCOMPR\n/* ===========================================================================\n * In-memory read function. As opposed to file_read(), this function\n * does not perform end-of-line translation, and does not update the\n * crc and input size.\n *    Note that the size of the entire input buffer is an unsigned long,\n * but the size used in mem_read() is only an unsigned int. This makes a\n * difference on 16 bit machines. mem_read() may be called several\n * times for an in-memory compression.\n */\nlocal unsigned mem_read(b, bsize)\n     char *b;\n     unsigned bsize;\n{\n    if (in_offset < in_size) {\n        ulg block_size = in_size - in_offset;\n        if (block_size > (ulg)bsize) block_size = (ulg)bsize;\n        memcpy(b, in_buf + in_offset, (unsigned)block_size);\n        in_offset += (unsigned)block_size;\n        return (unsigned)block_size;\n    } else {\n        return 0; /* end of input */\n    }\n}\n# endif /* ZP_NEED_MEMCOMPR */\n\n\n/* ===========================================================================\n * Flush the current output buffer.\n */\nvoid flush_outbuf(o_buf, o_idx)\n    char *o_buf;\n    unsigned *o_idx;\n{\n    if (y == NULL) {\n        error(\"output buffer too small for in-memory compression\");\n    }\n    /* Encrypt and write the output buffer: */\n    if (*o_idx != 0) {\n        zfwrite(o_buf, 1, (extent)*o_idx);\n        if (ferror(y)) ziperr(ZE_WRITE, \"write error on zip file\");\n    }\n    *o_idx = 0;\n}\n\n/* ===========================================================================\n * Return true if the zip file can be seeked. This is used to check if\n * the local header can be re-rewritten. This function always returns\n * true for in-memory compression.\n * IN assertion: the local header has already been written (ftell() > 0).\n */\nint seekable()\n{\n    return fseekable(y);\n}\n#endif /* ?USE_ZLIB */\n\n\n/* ===========================================================================\n * Compression to archive file.\n */\nlocal zoff_t filecompress(z_entry, cmpr_method)\n    struct zlist far *z_entry;\n    int *cmpr_method;\n{\n#ifdef USE_ZLIB\n    int err = Z_OK;\n    unsigned mrk_cnt = 1;\n    int maybe_stored = FALSE;\n    ulg cmpr_size;\n#if defined(MMAP) || defined(BIG_MEM)\n    unsigned ibuf_sz = (unsigned)SBSZ;\n#else\n#   define ibuf_sz ((unsigned)SBSZ)\n#endif\n#ifndef OBUF_SZ\n#  define OBUF_SZ ZBSZ\n#endif\n    unsigned u;\n\n#if defined(MMAP) || defined(BIG_MEM)\n    if (remain == (ulg)-1L && f_ibuf == NULL)\n#else /* !(MMAP || BIG_MEM */\n    if (f_ibuf == NULL)\n#endif /* MMAP || BIG_MEM */\n        f_ibuf = (char *)malloc(SBSZ);\n    if (f_obuf == NULL)\n        f_obuf = (char *)malloc(OBUF_SZ);\n#if defined(MMAP) || defined(BIG_MEM)\n    if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)\n#else /* !(MMAP || BIG_MEM */\n    if (f_ibuf == NULL || f_obuf == NULL)\n#endif /* MMAP || BIG_MEM */\n        ziperr(ZE_MEM, \"allocating zlib file-I/O buffers\");\n\n    if (!deflInit) {\n        err = zl_deflate_init(level);\n        if (err != ZE_OK)\n            ziperr(err, errbuf);\n    }\n\n    if (level <= 2) {\n        z_entry->flg |= 4;\n    } else if (level >= 8) {\n        z_entry->flg |= 2;\n    }\n#if defined(MMAP) || defined(BIG_MEM)\n    if (remain != (ulg)-1L) {\n        zstrm.next_in = (Bytef *)window;\n        ibuf_sz = (unsigned)WSIZE;\n    } else\n#endif /* MMAP || BIG_MEM */\n    {\n        zstrm.next_in = (Bytef *)f_ibuf;\n    }\n    zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);\n    if (zstrm.avail_in < ibuf_sz) {\n        unsigned more = file_read(zstrm.next_in + zstrm.avail_in,\n                                  (ibuf_sz - zstrm.avail_in));\n        if (more == EOF || more == 0) {\n            maybe_stored = TRUE;\n        } else {\n            zstrm.avail_in += more;\n        }\n    }\n    zstrm.next_out = (Bytef *)f_obuf;\n    zstrm.avail_out = OBUF_SZ;\n\n    if (!maybe_stored) while (zstrm.avail_in != 0 && zstrm.avail_in != EOF) {\n        err = deflate(&zstrm, Z_NO_FLUSH);\n        if (err != Z_OK && err != Z_STREAM_END) {\n            sprintf(errbuf, \"unexpected zlib deflate error %d\", err);\n            ziperr(ZE_LOGIC, errbuf);\n        }\n        if (zstrm.avail_out == 0) {\n            if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {\n                ziperr(ZE_TEMP, \"error writing to zipfile\");\n            }\n            zstrm.next_out = (Bytef *)f_obuf;\n            zstrm.avail_out = OBUF_SZ;\n        }\n        if (zstrm.avail_in == 0) {\n            if (verbose || noisy)\n                while((unsigned)(zstrm.total_in / (uLong)WSIZE) > mrk_cnt) {\n                    mrk_cnt++;\n                    if (!display_globaldots) {\n                      if (dot_size > 0) {\n                        /* initial space */\n                        if (noisy && dot_count == -1) {\n#ifndef WINDLL\n                          putc(' ', mesg);\n                          fflush(mesg);\n#else\n                          fprintf(stdout,\"%c\",' ');\n#endif\n                          dot_count++;\n                        }\n                        dot_count++;\n                        if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;\n                      }\n                      if (noisy && dot_size && !dot_count) {\n#ifndef WINDLL\n                        putc('.', mesg);\n                        fflush(mesg);\n#else\n                        fprintf(stdout,\"%c\",'.');\n#endif\n                        mesg_line_started = 1;\n                      }\n                    }\n                }\n#if defined(MMAP) || defined(BIG_MEM)\n            if (remain == (ulg)-1L)\n                zstrm.next_in = (Bytef *)f_ibuf;\n#else\n            zstrm.next_in = (Bytef *)f_ibuf;\n#endif\n            zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);\n        }\n    }\n\n    do {\n        err = deflate(&zstrm, Z_FINISH);\n        if (maybe_stored) {\n            if (err == Z_STREAM_END && zstrm.total_out >= zstrm.total_in &&\n                fseekable(zipfile)) {\n                /* deflation does not reduce size, switch to STORE method */\n                unsigned len_out = (unsigned)zstrm.total_in;\n                if (zfwrite(f_ibuf, 1, len_out) != len_out) {\n                    ziperr(ZE_TEMP, \"error writing to zipfile\");\n                }\n                zstrm.total_out = (uLong)len_out;\n                *cmpr_method = STORE;\n                break;\n            } else {\n                maybe_stored = FALSE;\n            }\n        }\n        if (zstrm.avail_out < OBUF_SZ) {\n            unsigned len_out = OBUF_SZ - zstrm.avail_out;\n            if (zfwrite(f_obuf, 1, len_out) != len_out) {\n                ziperr(ZE_TEMP, \"error writing to zipfile\");\n            }\n            zstrm.next_out = (Bytef *)f_obuf;\n            zstrm.avail_out = OBUF_SZ;\n        }\n    } while (err == Z_OK);\n\n    if (err != Z_STREAM_END) {\n        sprintf(errbuf, \"unexpected zlib deflate error %d\", err);\n        ziperr(ZE_LOGIC, errbuf);\n    }\n\n    if (z_entry->att == (ush)UNKNOWN)\n        z_entry->att = (ush)(zstrm.data_type == Z_ASCII ? ASCII : BINARY);\n    cmpr_size = (ulg)zstrm.total_out;\n\n    if ((err = deflateReset(&zstrm)) != Z_OK)\n        ziperr(ZE_LOGIC, \"zlib deflateReset failed\");\n    return cmpr_size;\n#else /* !USE_ZLIB */\n\n    /* Set the defaults for file compression. */\n    read_buf = file_read;\n\n    /* Initialize deflate's internals and execute file compression. */\n    bi_init(file_outbuf, sizeof(file_outbuf), TRUE);\n    ct_init(&z_entry->att, cmpr_method);\n    lm_init(level, &z_entry->flg);\n    return deflate();\n#endif /* ?USE_ZLIB */\n}\n\n#ifdef ZP_NEED_MEMCOMPR\n/* ===========================================================================\n * In-memory compression. This version can be used only if the entire input\n * fits in one memory buffer. The compression is then done in a single\n * call of memcompress(). (An extension to allow repeated calls would be\n * possible but is not needed here.)\n * The first two bytes of the compressed output are set to a short with the\n * method used (DEFLATE or STORE). The following four bytes contain the CRC.\n * The values are stored in little-endian order on all machines.\n * This function returns the byte size of the compressed output, including\n * the first six bytes (method and crc).\n */\n\nulg memcompress(tgt, tgtsize, src, srcsize)\n    char *tgt, *src;       /* target and source buffers */\n    ulg tgtsize, srcsize;  /* target and source sizes */\n{\n    ulg crc;\n    unsigned out_total;\n    int method   = DEFLATE;\n#ifdef USE_ZLIB\n    int err      = Z_OK;\n#else\n    ush att      = (ush)UNKNOWN;\n    ush flags    = 0;\n#endif\n\n    if (tgtsize <= (ulg)6L) error(\"target buffer too small\");\n    out_total = 2 + 4;\n\n#ifdef USE_ZLIB\n    if (!deflInit) {\n        err = zl_deflate_init(level);\n        if (err != ZE_OK)\n            ziperr(err, errbuf);\n    }\n\n    zstrm.next_in = (Bytef *)src;\n    zstrm.avail_in = (uInt)srcsize;\n    zstrm.next_out = (Bytef *)(tgt + out_total);\n    zstrm.avail_out = (uInt)tgtsize - (uInt)out_total;\n\n    err = deflate(&zstrm, Z_FINISH);\n    if (err != Z_STREAM_END)\n        error(\"output buffer too small for in-memory compression\");\n    out_total += (unsigned)zstrm.total_out;\n\n    if ((err = deflateReset(&zstrm)) != Z_OK)\n        error(\"zlib deflateReset failed\");\n#else /* !USE_ZLIB */\n    read_buf  = mem_read;\n    in_buf    = src;\n    in_size   = (unsigned)srcsize;\n    in_offset = 0;\n    window_size = 0L;\n\n    bi_init(tgt + (2 + 4), (unsigned)(tgtsize - (2 + 4)), FALSE);\n    ct_init(&att, &method);\n    lm_init((level != 0 ? level : 1), &flags);\n    out_total += (unsigned)deflate();\n    window_size = 0L; /* was updated by lm_init() */\n#endif /* ?USE_ZLIB */\n\n    crc = CRCVAL_INITIAL;\n    crc = crc32(crc, (uch *)src, (extent)srcsize);\n\n    /* For portability, force little-endian order on all machines: */\n    tgt[0] = (char)(method & 0xff);\n    tgt[1] = (char)((method >> 8) & 0xff);\n    tgt[2] = (char)(crc & 0xff);\n    tgt[3] = (char)((crc >> 8) & 0xff);\n    tgt[4] = (char)((crc >> 16) & 0xff);\n    tgt[5] = (char)((crc >> 24) & 0xff);\n\n    return (ulg)out_total;\n}\n#endif /* ZP_NEED_MEMCOMPR */\n\n#ifdef BZIP2_SUPPORT\n\nlocal int bz_compress_init(pack_level)\nint pack_level;\n{\n    int err = BZ_OK;\n    int zp_err = ZE_OK;\n    const char *bzlibVer;\n\n    bzlibVer = BZ2_bzlibVersion();\n\n    /* $TODO - Check BZIP2 LIB version? */\n\n    bstrm.bzalloc = NULL;\n    bstrm.bzfree = NULL;\n    bstrm.opaque = NULL;\n\n    Trace((stderr, \"initializing bzlib compress()\\n\"));\n    err = BZ2_bzCompressInit(&bstrm, pack_level, 0, 30);\n\n    if (err == BZ_MEM_ERROR) {\n        sprintf(errbuf, \"cannot initialize bzlib compress\");\n        zp_err = ZE_MEM;\n    } else if (err != BZ_OK) {\n        sprintf(errbuf, \"bzlib bzCompressInit failure (%d)\", err);\n        zp_err = ZE_LOGIC;\n    }\n\n    bzipInit = TRUE;\n    return zp_err;\n}\n\nvoid bz_compress_free()\n{\n    int err;\n\n    if (f_obuf != NULL) {\n        free(f_obuf);\n        f_obuf = NULL;\n    }\n    if (f_ibuf != NULL) {\n        free(f_ibuf);\n        f_ibuf = NULL;\n    }\n    if (bzipInit) {\n        err = BZ2_bzCompressEnd(&bstrm);\n        if (err != BZ_OK && err != BZ_DATA_ERROR) {\n            ziperr(ZE_LOGIC, \"bzlib bzCompressEnd failed\");\n        }\n        bzipInit = FALSE;\n    }\n}\n\n/* ===========================================================================\n * BZIP2 Compression to archive file.\n */\n\nlocal zoff_t bzfilecompress(z_entry, cmpr_method)\nstruct zlist far *z_entry;\nint *cmpr_method;\n{\n    FILE *zipfile = y;\n\n    int err = BZ_OK;\n    unsigned mrk_cnt = 1;\n    int maybe_stored = FALSE;\n    zoff_t cmpr_size;\n#if defined(MMAP) || defined(BIG_MEM)\n    unsigned ibuf_sz = (unsigned)SBSZ;\n#else\n#   define ibuf_sz ((unsigned)SBSZ)\n#endif\n#ifndef OBUF_SZ\n#  define OBUF_SZ ZBSZ\n#endif\n\n#if defined(MMAP) || defined(BIG_MEM)\n    if (remain == (ulg)-1L && f_ibuf == NULL)\n#else /* !(MMAP || BIG_MEM */\n    if (f_ibuf == NULL)\n#endif /* MMAP || BIG_MEM */\n        f_ibuf = (char *)malloc(SBSZ);\n    if (f_obuf == NULL)\n        f_obuf = (char *)malloc(OBUF_SZ);\n#if defined(MMAP) || defined(BIG_MEM)\n    if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)\n#else /* !(MMAP || BIG_MEM */\n    if (f_ibuf == NULL || f_obuf == NULL)\n#endif /* MMAP || BIG_MEM */\n        ziperr(ZE_MEM, \"allocating zlib/bzlib file-I/O buffers\");\n\n    if (!bzipInit) {\n        err = bz_compress_init(level);\n        if (err != ZE_OK)\n            ziperr(err, errbuf);\n    }\n\n#if defined(MMAP) || defined(BIG_MEM)\n    if (remain != (ulg)-1L) {\n        bstrm.next_in = (Bytef *)window;\n        ibuf_sz = (unsigned)WSIZE;\n    } else\n#endif /* MMAP || BIG_MEM */\n    {\n        bstrm.next_in = (char *)f_ibuf;\n    }\n    bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);\n    if (file_binary_final == 0) {\n      /* check for binary as library does not */\n      if (!is_text_buf(bstrm.next_in, ibuf_sz))\n        file_binary_final = 1;\n    }\n    if (bstrm.avail_in < ibuf_sz) {\n        unsigned more = file_read(bstrm.next_in + bstrm.avail_in,\n                                  (ibuf_sz - bstrm.avail_in));\n        if (more == (unsigned) EOF || more == 0) {\n            maybe_stored = TRUE;\n        } else {\n            bstrm.avail_in += more;\n        }\n    }\n    bstrm.next_out = (char *)f_obuf;\n    bstrm.avail_out = OBUF_SZ;\n\n    if (!maybe_stored) {\n      while (bstrm.avail_in != 0 && bstrm.avail_in != (unsigned) EOF) {\n        err = BZ2_bzCompress(&bstrm, BZ_RUN);\n        if (err != BZ_RUN_OK && err != BZ_STREAM_END) {\n            sprintf(errbuf, \"unexpected bzlib compress error %d\", err);\n            ziperr(ZE_LOGIC, errbuf);\n        }\n        if (bstrm.avail_out == 0) {\n            if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {\n                ziperr(ZE_TEMP, \"error writing to zipfile\");\n            }\n            bstrm.next_out = (char *)f_obuf;\n            bstrm.avail_out = OBUF_SZ;\n        }\n        /* $TODO what about high 32-bits of total-in??? */\n        if (bstrm.avail_in == 0) {\n            if (verbose || noisy)\n#ifdef LARGE_FILE_SUPPORT\n                while((unsigned)((bstrm.total_in_lo32\n                                  + (((zoff_t)bstrm.total_in_hi32) << 32))\n                                 / (zoff_t)(ulg)WSIZE) > mrk_cnt) {\n#else\n                while((unsigned)(bstrm.total_in_lo32 / (ulg)WSIZE) > mrk_cnt) {\n#endif\n                    mrk_cnt++;\n                    if (!display_globaldots) {\n                      if (dot_size > 0) {\n                        /* initial space */\n                        if (noisy && dot_count == -1) {\n#ifndef WINDLL\n                          putc(' ', mesg);\n                          fflush(mesg);\n#else\n                          fprintf(stdout,\"%c\",' ');\n#endif\n                          dot_count++;\n                        }\n                        dot_count++;\n                        if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;\n                      }\n                      if (noisy && dot_size && !dot_count) {\n#ifndef WINDLL\n                        putc('.', mesg);\n                        fflush(mesg);\n#else\n                        fprintf(stdout,\"%c\",'.');\n#endif\n                        mesg_line_started = 1;\n                      }\n                    }\n                }\n#if defined(MMAP) || defined(BIG_MEM)\n            if (remain == (ulg)-1L)\n                bstrm.next_in = (char *)f_ibuf;\n#else\n            bstrm.next_in = (char *)f_ibuf;\n#endif\n            bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);\n            if (file_binary_final == 0) {\n              /* check for binary as library does not */\n              if (!is_text_buf(bstrm.next_in, ibuf_sz))\n                file_binary_final = 1;\n            }\n        }\n      }\n    }\n\n    /* binary or text */\n    if (file_binary_final)\n      /* found binary in file */\n      z_entry->att = (ush)BINARY;\n    else\n      /* text file */\n      z_entry->att = (ush)ASCII;\n\n    do {\n        err = BZ2_bzCompress(&bstrm, BZ_FINISH);\n        if (maybe_stored) {\n            /* This code is only executed when the complete data stream fits\n               into the input buffer (see above where maybe_stored gets set).\n               So, it is safe to assume that total_in_hi32 (and total_out_hi32)\n               are 0, because the input buffer size is well below the 32-bit\n               limit.\n             */\n            if (err == BZ_STREAM_END\n                && bstrm.total_out_lo32 >= bstrm.total_in_lo32\n                && fseekable(zipfile)) {\n                /* BZIP2 compress does not reduce size,\n                   switch to STORE method */\n                unsigned len_out = (unsigned)bstrm.total_in_lo32;\n                if (zfwrite(f_ibuf, 1, len_out) != len_out) {\n                    ziperr(ZE_TEMP, \"error writing to zipfile\");\n                }\n                bstrm.total_out_lo32 = (ulg)len_out;\n                *cmpr_method = STORE;\n                break;\n            } else {\n                maybe_stored = FALSE;\n            }\n        }\n        if (bstrm.avail_out < OBUF_SZ) {\n            unsigned len_out = OBUF_SZ - bstrm.avail_out;\n            if (zfwrite(f_obuf, 1, len_out) != len_out) {\n                ziperr(ZE_TEMP, \"error writing to zipfile\");\n            }\n            bstrm.next_out = (char *)f_obuf;\n            bstrm.avail_out = OBUF_SZ;\n        }\n    } while (err == BZ_FINISH_OK);\n\n    if (err < BZ_OK) {\n        sprintf(errbuf, \"unexpected bzlib compress error %d\", err);\n        ziperr(ZE_LOGIC, errbuf);\n    }\n\n    if (z_entry->att == (ush)UNKNOWN)\n        z_entry->att = (ush)BINARY;\n#ifdef LARGE_FILE_SUPPORT\n    cmpr_size = (zoff_t)bstrm.total_out_lo32\n               + (((zoff_t)bstrm.total_out_hi32) << 32);\n#else\n    cmpr_size = (zoff_t)bstrm.total_out_lo32;\n#endif\n\n    if ((err = BZ2_bzCompressEnd(&bstrm)) != BZ_OK)\n        ziperr(ZE_LOGIC, \"zlib deflateReset failed\");\n    bzipInit = FALSE;\n    return cmpr_size;\n}\n\n#endif /* BZIP2_SUPPORT */\n#endif /* !UTIL */\n"
  },
  {
    "path": "deps/readme.txt",
    "content": "Google Test\ndir: googletest (submodule)\nurl: https://github.com/wwivbbs/googletest\nlicense: New BSD\n\nPD Curses\ndir: pdcurses\nfork: https://github.com/wwivbbs/PDCurses\nurl:  https://github.com/wmcbrine/PDCurses\nlicense: Public Domain\n\nInfoZIP\ndir: infozip\nurl: http://www.info-zip.org/\nlicense: New BSD\n\nCereal\ndir cereal\nurl: https://github.com/USCiLab/cereal/\nlicense: New BSD\n\nMy-Basic\ndir:  my_basic\nfork: https://github.com/wwivbbs/my_basic\nurl:  https://github.com/paladin-t/my_basic/commit/144d39285198222da8d55e612c51bf39be600a8f\nLicense: MIT\n\nFMT\ndir fmt\nfork: https://github.com/wwivbbs/fmt\nurl:  https://github.com/fmtlib/fmt\nLicense: BSD 2-Clause \"Simplified\" License\n"
  },
  {
    "path": "doors/qemu-freedos/fdos/FDAUTO.BAT",
    "content": "@ECHO OFF\r\n@REM Optimized fdauto.bat for running BBS DOORs.\r\nset DOSDIR=C:\\FDOS\r\nset LANG=EN\r\nset TZ=UTC\r\nset PATH=%dosdir%\\BIN\r\nset NLSPATH=%dosdir%\\NLS\r\nset HELPPATH=%dosdir%\\HELP\r\nset TEMP=%dosdir%\\TEMP\r\nset TMP=%TEMP%\r\nset OS_NAME=FreeDOS\r\nset OS_VERSION=1.3-RC4\r\nalias halt=fdapm pureoff\r\n\r\nLH FDAPM APMDOS\r\nLH SHARE\r\n\r\nif exist E:\\DOOR.BAT goto DOOR\r\ngoto END\r\n\r\n:DOOR\r\nE:\r\ncd\\\r\nCALL E:\\DOOR.BAT\r\nHALT\r\n\r\n:END\r\n\r\n"
  },
  {
    "path": "doors/qemu-freedos/fdos/FDCONFIG.SYS",
    "content": "SET DOSDIR=C:\\FDOS\r\n\r\n!COUNTRY=001,858,C:\\FDOS\\BIN\\COUNTRY.SYS\r\n!LASTDRIVE=Z\r\n!BUFFERS=20\r\n!FILES=40\r\n!MENUCOLOR=7,0\r\n\r\nDOS=HIGH\r\nDOS=UMB\r\nDOSDATA=UMB\r\nDEVICE=C:\\FDOS\\BIN\\JEMMEX.EXE NOEMS X=TEST I=TEST NOVME NOINVLPG\r\nSHELLHIGH=C:\\FDOS\\BIN\\COMMAND.COM C:\\FDOS\\BIN /E:1024 /P=FDAUTO.BAT\r\n"
  },
  {
    "path": "doors/qemu-freedos/gw.sh",
    "content": "#!/bin/sh\n#\n# Sample script to call global war.\n#\n# Usage: gw.sh INST_NUM INST_DIR SOCKET_PORT\n#\n# Configuration in WWIV:\n#\n#    A) Description  : GW\n#    B) Filename     : /wwiv/gw.sh %N %I %Z\n#    C) ACS          : user.sl >= 10\n#    D) ANSI         : Optional\n#    E) Exec Mode    : Listen Socket Port\n#    F) Launch From  : BBS Root Directory\n#    G) Local only   : No\n#    H) Multi user   : No\n#    I) Usage        : 11\n#    J) Registered by: AVAILABLE\n#    L) Pause after  : No\n#\n\nINST_NUM=$1\nINST_DIR=$2\nSOCKET_PORT=$3\n\nDOORFILE=$(realpath ${INST_DIR}/DOOR.BAT)\necho C:\\\\BNU\\\\BNU.COM >${DOORFILE}\necho D: >>${DOORFILE}\necho cd \\\\GW >>${DOORFILE}\necho \"WAR.EXE /W E:\\CHAIN.TXT\" >>${DOORFILE}\n\nunix2dos ${DOORFILE}\nunix2dos ${INST_DIR}/chain.txt\n\necho \"num: ${INST_NUM} doors: ${INST_DIR}; DOORFILE: ${DOORFILE}\"\n./wwivqemu.sh ${INST_NUM} /wwiv/doors ${SOCKET_PORT}\n\nrm ${DOORFILE}\n\n"
  },
  {
    "path": "doors/qemu-freedos/local.sh",
    "content": "\nBOOT_IMG=/wwiv/freedos.img\nDOORS=/wwiv/doors\nINST=/wwiv/e/1/temp\nexport TERM=linux \nqemu-system-i386 \\\n    -drive format=raw,file=${BOOT_IMG} \\\n    -drive format=raw,file=fat:rw:${DOORS} \\\n    -drive format=raw,file=fat:rw:${INST} \n"
  },
  {
    "path": "doors/qemu-freedos/readme.txt",
    "content": "Simple instructions for QEMU/FreeDOS Doors under WWIV.\n\n1) Install QEMU according to your Linux Distributions instructions.\n   On debian this is:\n   sudo apt-get install qemu-kvm qemu\n\n2) Make a Disk Image for FreeDos:\n   qemu-img create -f raw freedos.img 20M\n\n3) Download FreeDOS ISO.\n   I grabbed the latest 1.3RC4 Live CD ISO from:\n   https://www.freedos.org/download/\n\n4) Install FreeDOS.  Pick any configuration, but I didn't need\n   a big one, so choose the basic system without sources.\n   Here's the command I used.\n   qemu-system-x86_64 freedos.img -cdrom ./FD13LIVE.iso -boot d\n\n5) You will need to reboot after partitioning (DOS) and then should\n   have a basic functioning system.\n\n6) Download BNU FOSSIL driver and put it in a place where you can\n   get it to as drive D: (i.e. put it in wwiv/doors), run QEMU\n   and copy it to C:\\BNU.  Also replace FDAUTO.BAT and FDCONFIG.SYS\n   with the ones here under the FDOS directory.\n\nIf you want to look at the disk image read only from linux, you can\nuse the following command:\n\nsudo mount -o loop,offset=32256 /wwiv/freedos.img /mnt\n\nI prefer to boot into freedos and let drive D: or E: be the directory\nwhere I'll stage files to copy into FreeDOS from inside of FreeDOS\nunder QEMU.\n\ni.e from inside freeDOS run:\nUNZIP -D E:\\BNU170.ZIP -d C:\\BNU\n\nUse:\n\n  1) The way this works is D: should be mounted under QEMU where the doors\n     are installed.\n  2) E: should be the node's temp directory.\n  3) When running a door, write out the command to use into a batch file\n     located in the node's temp dir called DOOR.BAT, this will be invoked\n     by the end of FreeDOS's FDAUTO.BAT on bootup.\n  4) Also note that since the C: drive contents are not modified while using\n     a door, the gw.sh script copies it to the temp directory to use it, this\n     way multiple nodes can be in doors at the same time. Just make sure that\n     two nodes don't use the same door at the same time, since drive D is\n     shared across the two (but writes from one VM are not visible immediately\n     to the other).\n\nContents\n\t* gw.sh - sample script to use for Global WAR\n\t* wwivqemu.sh - wrapper to spawn QEMU seting most of the defaults\n\t  we want.\n\t* local.sh - local wrapper script to run QEMU locally to access\n\t  the FreeDOS contents.\n\nThis worked for me under Ubuntu and a Debian VM in the cloud.\n"
  },
  {
    "path": "doors/qemu-freedos/wwivqemu.sh",
    "content": "#!/bin/sh\n#\n# QEMU Launcher for WWIV Doors.\n#\n# This assumes the following drives for the FreeDOS session:\n# C: boot disk from freedos.img\n# D: Doors root directory (Linux dir containing all doors)\n# E: Temp/Instance directory for the BBS.\n#\n# Usage:\n#\n# - write out DOOR.BAT to the temp/instance dir with the command to run.\n# q.sh NODE_NUM DOORS_DIR\n#\n\n# customize this to match your install\nWWIV_TEMP=/wwiv/e\n\n\nINSTANCE_NUM=\"${1:-1}\"\nDOORS=\"${2:-/wwiv/doors}\"\nINST=${WWIV_TEMP}/${INSTANCE_NUM}/temp\nBASE_BOOT_IMG=/wwiv/freedos.img\nBOOT_IMG=${INST}/$(basename ${BASE_BOOT_IMG})\n\ncp ${BASE_BOOT_IMG} ${BOOT_IMG}\n\nexport TERM=linux \nqemu-system-x86_64 \\\n    -drive format=raw,file=${BOOT_IMG} \\\n    -drive format=raw,file=fat:rw:${DOORS} \\\n    -drive format=raw,file=fat:rw:${INST} \\\n    -chardev stdio,id=char0,signal=off \\\n    -serial chardev:char0 \\\n    -monitor none \n\n# If you have a headless setup, uncomment and add this line\n# before -monitor none, otherwise leave it out so you can\n# see the DOOR console window in QEMU.\n#    -display none \\\n\n\n"
  },
  {
    "path": "dos/wwivfoss/c.bat",
    "content": "set LIB=C:\\msvc\\lib\nnmake\ncv bin\\wwivfoss.exe /N1 fecho.com Hello\n"
  },
  {
    "path": "dos/wwivfoss/dostypes.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_DOSTYPES_H\n#define INCLUDED_DOSTYPES_H\n\ntypedef char int8_t;\ntypedef int  int16_t;\ntypedef long int32_t;\n\ntypedef unsigned char uint8_t;\ntypedef unsigned int  uint16_t;\ntypedef unsigned long uint32_t;\n\ntypedef int BOOL;\ntypedef int bool;\n\n#define TRUE  1\n#define true  1\n#define FALSE 0\n#define false 0\n\n\n#endif // INCLUDED_DOSTYPES_H\n"
  },
  {
    "path": "dos/wwivfoss/fossil.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"fossil.h\"\n\n#include \"dostypes.h\"\n#include \"pipe.h\"\n#include \"util.h\"\n\n#include <ctype.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <stdarg.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#pragma warning(disable : 4505)\n\n#define LOBYTE(w) ((w) & 0xff)\n#define HIBYTE(w) (((w) >> 8) & 0xff)\n\n#define STATUS_BASE           0x0008\n#define STATUS_CARRIER_DETECT 0x0080\n#define STATUS_INPUT_AVAIL    0x0100\n#define STATUS_INPUT_OVERRUN  0x0200\n#define STATUS_OUTPUT_AVAIL   0x2000\n#define STATUS_OUTPUT_EMPTY   0x4000\n\n#define FOSSIL_HIGHEST_FUNCTION 0x1B\n#define FOSSIL_SIGNATURE 0x1954\n\nvoid (__interrupt __far *old_int14)();\n\nstatic int fossil_enabled = 0;\nstatic int carrier = 1;\nstatic int pipe_handle = -1;\nstatic int log_count_ = 0;\nstatic int num_calls = 0;\nstatic int fos_calls[32];\nstatic int in_int14 = 0;\nstatic char m[20];\nstatic Pipe __far * pipe = NULL;\nstatic int char_avail = 0;\n\nchar  __near* fossil_info_ident = \"WWIV FOSSIL runner for Win32 and OS/2 Named Pipes\";\n\n#pragma pack(1)\nstruct fossil_info {\n   unsigned int size;\n   unsigned char majver;\n   unsigned char minver;\n   char __far *  ident;\n   unsigned int  in_buffer_size;\n   unsigned int  in_bytes_avail;\n   unsigned int  out_buffer_size;\n   unsigned int  out_buffer_avail;\n   unsigned char width;\n   unsigned char height;\n   unsigned char baudmask;\n};\n#pragma pack()\n\nstatic struct fossil_info info;\n\nFossilOptions::FossilOptions() : comport(0), node_number(0), open_timeout_seconds(10) {}\nFossilOptions::~FossilOptions() {}\n\nstatic unsigned status() {\n  unsigned r = STATUS_BASE;\n  if (!pipe->is_open() || !carrier) {\n    carrier = 0;\n    return r;\n  }\n\n  r |= STATUS_CARRIER_DETECT;\n  if (char_avail <= 0) {\n    char_avail = pipe->peek();\n  }\n  if (char_avail > 0) {\n    r |= STATUS_INPUT_AVAIL;\n  }\n  // HACK: Claim were were done writing\n  r |= STATUS_OUTPUT_AVAIL;\n  r |= STATUS_OUTPUT_EMPTY;\n  return r;\n}\n\n#pragma check_stack-\n#pragma warning(disable : 4100)\n\nvoid __interrupt __far int14_handler( unsigned _es, unsigned _ds,\n\t  unsigned _di, unsigned _si,\n\t  unsigned _bp, unsigned _sp,\n\t  unsigned _bx, unsigned _dx,\n\t  unsigned _cx, unsigned _ax,\n\t  unsigned _ip, unsigned _cs,\n\t  unsigned _flags ) { \n\n  if (in_int14) {\n    return;\n  }\n  in_int14 = 1;\n  \n  int func = (int) HIBYTE(_ax);\n  if (func < 32 && func >= 0) {\n    ++fos_calls[func];\n  }\n  num_calls++;\n  switch (func) {\n  case 0x0: {\n    // Set baud rate.  Nothing to set since we don't care about BPS\n    _ax = status();\n  } break;\n  case 0x01: {\n    /*\n      AH = 01h    Transmit character with wait\n\n            Parameters:\n                Entry:  AL = Character\n                        DX = Port number\n                Exit:   AX = Port status (see function 03h)\n\n     */\n    unsigned char ch = (unsigned char) LOBYTE(_ax);\n    //pipe->write(\"0x01: \", 6);\n    ++log_count_;\n    pipe->write(ch);\n    _ax = status();\n  } break;\n  case 0x02: {\n    //pipe->write(\"0x02: \", 6);\n    // Receive characer with wait\n    char_avail = 0;\n    _ax = pipe->blocking_read();\n  } break;\n  case 0x03: {\n    // pipe->write(\"0x03: \", 6);\n    // Request status. \n    // TODO should we mask it?\n    int cc = pipe->control_code();\n    if (cc == 'D') {\n      carrier = 0;\n    }\n    _ax = status();\n  } break;\n  case 0x04: {\n    // AH = 04h    Initialize driver\n    // TODO should we mask it?\n    _ax = FOSSIL_SIGNATURE;\n    _bx = 0x1000 | FOSSIL_HIGHEST_FUNCTION;\n    //pipe->write(\"0x04: \", 6);\n  } break;\n  case 0x0B: {\n    /*\n      AH = 0Bh    Transmit no wait\n\n            Parameters:\n                Entry:  DX = Port number\n                Exit:   AX = 0001h - Character was accepted\n                           = 0000h - Character was not accepted\n\n     */\n    // Transmit character with wait (or no wait for 0b)\n    unsigned char ch = (unsigned char) LOBYTE(_ax);\n    ++log_count_;\n    pipe->write(ch);\n    _ax = 1;\n    // See if this makes gwar work.\n    os_yield();\n  } break;\n  case 0x0C: {\n    // com peek\n    int ch = pipe->peek();\n    _ax = (ch == -1) ? 0xffff : ch;\n  } break;\n  case 0x0D: {\n    // read keyboard without wait\n  } break;\n  case 0x0E: {\n    // read keyboard with wait\n  } break;\n  case 0x19: {\n    // block write\n    /*\n           Parameters:\n               Entry:  CX = Maximum number of characters to transfer\n                       DX = Port number\n                       ES = Segment of user buffer\n                       DI = Offset into ES of user buffer\n               Exit:   AX = Number of characters actually transferred  */\n    char __far * buf = (char __far *) MK_FP(_es, _di);\n    _ax = pipe->write(buf, _cx);\n  } break;\n  case 0x1B: {\n    /*\n     AH = 1Bh    Return information about the driver\n\n           Parameters:\n               Entry:  CX = Size of user info buffer in bytes\n                       DX = Port number\n                       ES = Segment of user info buffer\n                       DI = Offset into ES of user info buffer\n               Exit:   AX = Number of bytes actually transferred\n     */\n    // Request status. \n    // TODO should we mask it?\n    unsigned int siz = sizeof(info);\n    if (siz < _cx) {\n      siz = _cx;\n    }\n    info.size = sizeof(info);\n    info.majver = 10;\n    info.minver = 1;\n    info.ident = fossil_info_ident;\n    info.in_buffer_size = 100;\n    info.in_bytes_avail = 100;\n    info.out_buffer_size = 100;\n    info.out_buffer_avail = 100;\n    info.width = 80;\n    info.height = 25;\n    info.baudmask = 0x23; // 38400 N81\n    void __far * p = MK_FP(_es, _di);\n    _fmemcpy(p, &info, siz);\n    _ax = siz;\n  } break;\n  }\n\n  in_int14 = 0;\n}\n\nvoid __interrupt __far int14_sig() { \n  char pad[10] = {0};\n}\n\nbool enable_fossil(const FossilOptions* options) {\n  if (!options) {\n    log(\"NULL options passed to enable_fossil.\");\n    abort();\n  }\n  char pipename[200];\n  sprintf(pipename, \"\\\\PIPE\\\\WWIV%d\", options->node_number);\n  log(\"Opening pipe: '%s'\", pipename);\n  pipe = new __far Pipe(pipename, options->open_timeout_seconds);\n  if (!pipe->is_open()) {\n    log(\"Failed to open pipe: '%s'\", pipename);\n    return false;\n  }\n  // This seems to make it work consistently with the test app.\n  os_yield();\n  // pipe_handle is used in the interrupt handler.\n  pipe_handle = pipe->handle();\n\n  old_int14 = _dos_getvect(0x14);\n\n  for (int i=0; i<32; i++) {\n    fos_calls[i]=0;\n  }\n\n  _disable();\n  unsigned char __far * p = (unsigned char __far *) ((void __far *) int14_sig);\n  void __far * sig_addr = int14_sig;\n  void __far * handler_addr = int14_handler;\n  // We offset by 3 since JMP is one, and then two for the address for a near JMP\n  int diff = FP_OFF(handler_addr) - FP_OFF(sig_addr) - 3;\n\n  *p = 0xE9;\n  *(p+1) = (unsigned char)(diff & 0xff);\n  *(p+2) = (unsigned char)(((diff & 0xff00) >> 8) & 0xff);\n  *(p+3) = 0x90;\n  *(p+4) = 0x90;\n  *(p+5) = 0x90;\n  // 0x1954 (signature)\n  *(p+6) = LOBYTE(FOSSIL_SIGNATURE);\n  *(p+7) = HIBYTE(FOSSIL_SIGNATURE);\n  // Highest supported FOSSIL function.\n  *(p+8) = FOSSIL_HIGHEST_FUNCTION;\n  _dos_setvect(0x14, (void (__interrupt __far *)()) int14_sig);\n  _enable();\n\n  log(\"signature:[%p:%p]; handler:[%p:%p] [offset: %d]\", FP_SEG(sig_addr), FP_OFF(sig_addr), \n      FP_SEG(handler_addr), FP_OFF(handler_addr), diff);\n  fossil_enabled = 1;\n  os_yield();\n\n  log(\"FOSSIL Enabled. Pipe Handle:[%d]\", pipe_handle);\n  return true;\n}\n\nbool disable_fossil() {\n  if (!fossil_enabled) {\n    log(\"ERROR: disable_fossil called when not enabled.\");\n    return false;\n  }\n\n  _disable();\n  _dos_setvect(0x14, old_int14);\n  _enable();\n\n  log(\"FOSSIL Disabled: [%d calls][handle: %d]\", num_calls, pipe->handle());\n\n  for (int i=0; i<32; i++) {\n    if (fos_calls[i]) {\n      log(\"Fossil Call: 0x%02X: %d times\", i, fos_calls[i]);\n    }\n  }\n  log(\"Pipe: [writes: %d][errors: %d][bytes: %ld]\", pipe->num_writes(),\n      pipe->num_errors(), pipe->bytes_written());\n\n  log(\"Closed pipe\");\n  delete pipe;\n  pipe = NULL;\n  return true;\n}\n\n"
  },
  {
    "path": "dos/wwivfoss/fossil.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_FOSSIL_H\n#define INCLUDED_FOSSIL_H\n\n#include \"dostypes.h\"\n\n#define ENABLE_LOG\n#define FOSSIL_BUFFER_SIZE 4000\n\nclass FossilOptions {\npublic:\n  FossilOptions();\n  ~FossilOptions();\n\n  int comport;\n  int node_number;\n  int open_timeout_seconds;\n};\n\nbool enable_fossil(const FossilOptions* options);\nbool disable_fossil();\n\n#endif // INCLUDED_FOSSIL_H\n"
  },
  {
    "path": "dos/wwivfoss/makefile",
    "content": "#######################################################################\n# WWIVFOSS Makefile \n# \n\nMSVC_HOME\t= C:\\MSVC\nINCLUDE \t= $(MSVC_HOME)\\INCLUDE\nLIB\t\t= $(MSVC_HOME)\\LIB\n# Note: /G3 for 386 compile caused this to crash.\nCPPFLAGS\t= /nologo -I $(INCLUDE) -L $(LIB) /W4 /G0\nLDFLAGS\t\t= \nBINDIR\t\t= bin\\\n\nall:\t$(BINDIR)\\WWIVFOSS.EXE \\\n\t\t$(BINDIR)\\UTILTEST.EXE\n\nclean:\n\t-@DEL /N $(BINDIR)\\*.*\n\t-@DEL /Q $(BINDIR)\\*.*\n\t-@DEL /N .\\*.COD\n\t-@DEL /Q .\\*.COD\n\n.cpp{$(BINDIR)}.obj:\n    $(MSVC_HOME)\\BIN\\CL.EXE $(CPPFLAGS) /Zi /Od /Fo$@ /c $<\n\nWWIVFOSS_OBJS\t= $(BINDIR)\\WWIVFOSS.OBJ \\\n\t\t  $(BINDIR)\\FOSSIL.OBJ \\\n\t\t  $(BINDIR)\\UTIL.OBJ \\\n\t\t  $(BINDIR)\\PIPE.OBJ\n\n$(BINDIR)\\WWIVFOSS.EXE::   $(WWIVFOSS_OBJS)\n\t-@MKDIR $(BINDIR)\n\tLINK /NOLOGO /CODEVIEW $(LDFLAGS) @<<$*.CRF\n$(WWIVFOSS_OBJS: =+^\n)\n$@\n$*.MAP\n\n\n<<\n\n\nUTILTEST_OBJS\t= $(BINDIR)\\UTILTEST.OBJ \\\n\t\t  $(BINDIR)\\UTIL.OBJ\n\n\n$(BINDIR)\\UTILTEST.EXE::   $(UTILTEST_OBJS)\n\t-@MKDIR $(BINDIR)\n\tLINK /NOLOGO $(LDFLAGS) @<<$*.CRF\n$(UTILTEST_OBJS: =+^\n)\n$@\n$*.MAP\n\n\n<<\n"
  },
  {
    "path": "dos/wwivfoss/pipe.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"pipe.h\"\n\n#include \"util.h\"\n#include <conio.h>\n#include <ctype.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <time.h>\n\n#pragma warning(disable : 4505)\n\n\n// See http://www.delorie.com/djgpp/doc/rbinter/ix/21/5F.html\n/*\nINT 21 - Named Pipes - LOCAL DosQNmPHandState\n\n\tAX = 5F33h\n\tBX = handle\nReturn: CF clear if successful\na\t    AH = pipe mode bit mask (see #01702)\n\t    AL = maximum number of instances\n\tCF set on error\n\t    AX = error code\nNote:\tthis function was introduced by LAN Manager but is also supported by\n\t  the Novell DOS Named Pipe Extender, Banyan VINES, OS/2 Virtual DOS\n\t  Machines, and others\nSeeAlso: AX=5F32h,AX=5F34h\n\nCategory: network\nFlags: partially documented function\n\nINT 21 - Named Pipes - LOCAL DosSetNmPHandState\n\n\tAX = 5F34h\n\tBX = handle\n\tCX = pipe mode bit mask\n\t    bit 15: set if nonblocking, clear if blocking\n\t    bit\t 8: set if read in message mode, clear if read in byte mode\nReturn: CF clear if successful\n\tCF set if error\n\t    AX = error code\nNote:\tthis function was introduced by LAN Manager but is also supported by\n\t  the Novell DOS Named Pipe Extender, Banyan VINES, OS/2 Virtual DOS\n\t  Machines, and others\nSeeAlso: AX=5F32h,AX=5F33h,AX=5F36h\n\n\nand\n\n\nINT 21 - Named Pipes - LOCAL DosPeekNmPipe\n\n\tAX = 5F35h\n\tBX = handle\n\tCX = buffer length\n\tDS:SI -> buffer\nReturn: CF set on error\n\t    AX = error code\n\tCF clear if successful (LAN Manager v1-v2)\n\tAX = 0000h if successful (LAN Manager 3.x)\n\t---if successful---\n\t    CX = bytes read\n\t    SI = bytes left in the pipe\n\t    DX = bytes left in the current message\n\t    AX = pipe status (v1-v2) (see #01703)\n\t    DI = pipe status (v3.x)\nNote:\tthis function was introduced by LAN Manager but is also supported by\n\t  the Novell DOS Named Pipe Extender, Banyan VINES, OS/2 Virtual DOS\n\t  Machines, and others\nSeeAlso: AX=5F38h,AX=5F39h,AX=5F51h\n\nValues for pipe status:\n 0001h\tdisconnected\n 0002h\tlistening\n 0003h\tconnected\n 0004h\tclosing\n */\n\n\nvoid SetPipeNonBlocking(int handle) {\n  union _REGS r;\n  r.x.ax = 0x5F33;\n  r.x.bx = handle;\n  _intdos(&r, &r);\n\n  r.h.al = 0;\n  r.x.bx = handle;\n  r.x.cx = r.x.ax | 0x8000;\n  r.x.ax = 0x5F34;\n\n  union _REGS or;\n  int result = _intdos(&r, &or);\n  if (or.x.cflag) {\n    log(\"Error Setting Pipe Nonnblocking: %d\", result);\n  }\n}\n\n\nint DosPeekNmPipe(int handle) {\n  char buffer[10];\n  union _REGS r;\n  union _REGS or;\n  struct _SREGS s;\n  unsigned int c_seg;\n  r.x.ax = 0x5F35;\n  r.x.bx = handle;\n  r.x.cx = 1;\n  __asm {\n    mov c_seg, ss\n      }\n  s.ds  = (__segment) &buffer;\n  r.x.si = (unsigned int) buffer;\n  _intdosx(&r, &or, &s);\n  if (or.x.ax == 0 || or.x.cflag == 0) {\n    if (or.x.ax == 1 || or.x.ax == 4) {\n      // disconnected\n      return -1;\n    }\n    if (or.x.ax != 0x03) {\n      //log(\"WARNING: DosPeekNmPipe: CF:%d/AX:%d/CX:%d\", or.x.cflag, or.x.ax, or.x.cx);\n    }\n    return or.x.cx;\n  }\n  //log(\"ERROR: DosPeekNmPipe: CF:%d/AX:%d/CX:%d\", or.x.cflag, or.x.ax, or.x.cx);\n  return 0;\n}\n\n\nPipe::Pipe(const char* fn, int timeout_secs) __far {\n  next_char_ = -1;\n  handle_ = -1;\n  control_handle_ = -1;\n\n  int h = -1;\n  clock_t start_time = clock();\n  log(\"Pipe::Pipe\");\n  while (handle_ == -1 && ((clock() - start_time) / CLOCKS_PER_SEC) < timeout_secs) {\n    if (_dos_open(fn, _O_RDWR, &h) != 0) {\n      log(\"ERROR: (Pipe) Unable to open pipe: '%s'\", fn);\n      handle_ = -1;\n      // Sleep for 1/10 of total time in ms (so time * 10 / 1000)\n      sleep(timeout_secs * 100);\n    } else {\n      handle_ = h;\n      num_writes_ = 0;\n      num_errors_ = 0;\n      bytes_written_ = 0;\n      os_yield();\n      SetPipeNonBlocking(handle_);\n      break;\n    }\n  }\n\n  if (handle_ == -1) {\n    log(\"Unable to open data handle\");\n    return;\n  }\n  os_yield();\n  log(\"Opened data pipe with handle: [%d]\", handle_);\n\n  char control_fn[81];\n  sprintf(control_fn, \"%sC\", fn);\n  start_time = clock();\n  h = -1;\n  while (control_handle_ == -1 && ((clock() - start_time) / CLOCKS_PER_SEC) < timeout_secs) {\n    if (_dos_open(control_fn, _O_RDWR, &h) == 0) {\n      control_handle_ = h;\n      os_yield();\n      SetPipeNonBlocking(control_handle_);\n      break;\n    } else {\n      log(\"ERROR: (Pipe) Unable to open pipe: '%s'\", control_fn);\n    }\n    // Sleep for 1/10 of total time in ms (so time * 10 / 1000)\n    sleep(timeout_secs * 100);\n  }\n  log(\"Opened control pipe with handle: [%d]\", control_handle_);\n}\n\n/** Send a control code to the remote side */\nint Pipe::send_control(char code) __far {\n  unsigned int num_written;\n  return _dos_write(control_handle_, &code, 1, &num_written) == 0;\n}\n\n/** Gets the current control code */\nchar Pipe::control_code() __far {\n  unsigned num_read;\n  char ch;\n  int ret = _dos_read(control_handle_, &ch, 1, &num_read);\n  if (ret == 0 && num_read > 0) {\n    return ch;\n  }\n  return -1;\n}\n\n\nvoid Pipe::close() __far {\n  log(\"Pipe::close()\");\n  if (handle_ != -1) {\n    _dos_close(handle_);\n    handle_ = -1;\n  }\n\n  if (control_handle_ != -1) {\n    _dos_close(control_handle_);\n    control_handle_ = -1;\n  }\n  os_yield();\n}\n\nPipe::~Pipe() __far {\n  close();\n}\n\nint Pipe::is_open() __far { \n  return handle_ != -1 && control_handle_ != -1;\n}\n\nint Pipe::peek() __far {\n  if (next_char_ < 0) {\n    next_char_ = read();\n  }\n  return next_char_;\n}\n\nint Pipe::read() __far {\n  int ch = 0;\n  if (next_char_ >= 0) {\n    ch = next_char_;\n    next_char_ = -1;\n    return ch;\n  }\n\n  unsigned num_read;\n  int ret = _dos_read(handle_, &ch, 1, &num_read);\n  if (ret == 0 && num_read > 0) {\n    ++bytes_read_;\n    return ch;\n  }\n  if (ret != 0 && ret != 5) {\n    // Not sure why we get permission denied but it fixes itself\n    ++num_errors_;\n    close();\n  }\n  return -1;\n}\n\nint Pipe::blocking_read() {\n  for (;;) {\n    int r = read();\n    if (r) {\n      return r;\n    }\n    os_yield();\n  }\n}\n\nint Pipe::write(int ch) __far {\n  unsigned int num_written;\n  ++num_writes_;\n  if (_dos_write(handle_, &ch, 1, &num_written) != 0) {\n    ++num_errors_;\n    close();\n    return 0;\n  }\n  ++bytes_written_;\n  return 1;\n}\n\nint Pipe::write(const char __far * buf, int maxlen) {\n  unsigned int num_written;\n  ++num_writes_;\n  if (_dos_write(handle_, buf, maxlen, &num_written) != 0) {\n    ++num_errors_;\n    close();\n    return 0;\n  }\n  bytes_written_ += maxlen;\n  return maxlen;\n}\n\n\n\n\n\n"
  },
  {
    "path": "dos/wwivfoss/pipe.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef PIPE_H\n#define PIPE_H\n\n#include \"util.h\"\n\n#define PIPE_BUFFER_SIZE 4000\n\n\nint DosPeekNmPipe(int handle);\n\nclass __far Pipe {\n public:\n  /** \n   * Constructs a set of pipes for FOSSIL communication. \n   * There will be 2 pipes, the one pointed by FN will be a bi-direcitonal\n   * pipe for data, and a second named fn + \"C\" will be created for control\n   * information.\n   *\n   * N.B: The pipe is expected to be created before installing a TSR\n   * or interrupt handler.\n   */\n  Pipe(const char* fn, int timeout_secs);\n  /** Destroys the pipe, closing if needed */\n  ~Pipe();\n\n  /** \n   * A non-blocking read of 1 char.  A value if 0 or -1 is returned\n   * if there is nothing to read.\n   */\n  int read();\n\n  /**\n   * A blocking version of read.\n   */\n  int blocking_read();\n\n  /**\n   * Writes a single char to the pipe.  Returning the number of characters\n   * written or -1 on error.\n   */\n  int write(int ch);\n\n  /**\n   * Writes a block of chars to the pipe.  Returning the number of characters\n   * written or -1 on error.\n   */\n  int write(const char __far * buf, int maxlen);\n\n  /** Send a control code to the remote side */\n  int send_control(char code);\n\n  /** Gets the current control code */\n  char control_code();\n\n  /** \n   * A non-blocking peek of 1 char.  A value if 0 or -1 is returned\n   * if there is nothing to read.\n   */\n  int peek();\n\n  /**\n   * returns true (1) if the pipe is open.\n   */\n  int is_open();\n\n  /**\n   * Closes this end of the pipe.\n   */\n  void close();\n\n  /**\n   * Returns the native DOS handle for the pipe.  \n   * May be needed to pass to interrupt or _dos_xxxx calls\n   */\n  int handle() { return handle_; }\n\n  /**\n   * Returns the total number of write calls.\n   */\n  int num_writes() { return num_writes_; }\n\n  /**\n   * Returns the total number of write calls that ended in an error.\n   */\n  int num_errors() { return num_errors_; }\n \n  /**\n   * Returns the bytes written.\n   */\n  long bytes_written() { return bytes_written_; }\n\n  /**\n   * Returns the bytes written.\n   */\n  long bytes_read() { return bytes_read_; }\n\n private:\n  int handle_;\n  int control_handle_;\n  int num_writes_;\n  int num_errors_;\n  long bytes_written_;\n  long bytes_read_;\n  int next_char_;\n};\n\n#endif // PIPE_H\n\n\n"
  },
  {
    "path": "dos/wwivfoss/util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"util.h\"\n\n#include <conio.h>\n#include <ctype.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#pragma warning(disable : 4505)\n\n\nArray::Array(int max_items) : max_items_(max_items), last_item_(0) {\n  items_ = new char*[max_items];\n  for (int i=0; i<max_items; i++) {\n    items_[i] = NULL;\n  }\n}\n\nArray::~Array() {\n  for (int i=0; i<last_item_; i++) {\n    free(items_[i]);\n  }\n  delete[] items_;\n}\n\nvoid Array::push_back(const char* item) {\n  items_[last_item_++] = strdup(item);\n}\n\nint Array::size() const { \n  return last_item_;\n}\n\nconst char* Array::at(int n) const {\n  if (n >= last_item_) {\n    fprintf(stderr, \"n[%d] > last_item_[%d]\", n, last_item_);\n    abort();\n  }\n  return items_[n];\n}\n\n\nvoid log(const char* msg, ...) {\n#ifndef DISABLE_LOG\n  va_list argptr;\n  va_start(argptr, msg);\n  vfprintf(stderr, msg, argptr);\n  va_end(argptr);\n  fprintf(stderr, \"\\r\\n\");\n  fflush(stderr);\n#endif\n}\n\nvoid os_yield() {\n  // log(\"os_yield\");\n  union _REGS r;\n  r.x.ax = 0x1680;\n  _int86(0x2f, &r, &r);\n}\n\nvoid outch(int ch) {\n  fprintf(stdout, \"%c\", ch);\n  if (ch == '\\r') {\n    fprintf(stdout, \"\\n\");\n  }\n  fflush(stdout);\n}\n\nvoid sleep(int ms) {\n  clock_t then = clock();\n  while ((clock() - then) * 1000 / CLOCKS_PER_SEC < ms) {\n    // Try to yield timeslices until we're done waiting.\n    os_yield();\n  }\n}\n\n\n"
  },
  {
    "path": "dos/wwivfoss/util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef UTIL_H\n#define UTIL_H\n\nclass Array {\npublic:\n  Array(int max_items);\n  ~Array();\n  void push_back(const char* item);\n  int size() const;\n  const char* at(int n) const;\n\n  char** items() { return items_; }\n\n  int max_items_;\n  int last_item_;\n  char** items_;\n};\n\n\n/** Writes a log entry to stderr */\nvoid log(const char* msg, ...);\n\n/** Yields a timeslice to the OS on OS/2 or Windows under DOS */\nvoid os_yield();\n\n/** Writes ch to stdout, processing \\r => \\r\\n */\nvoid outch(int ch);\n\n/** Sleeps for roughly ms milliseconds */\nvoid sleep(int ms);\n\n#endif // UTIL_H\n\n\n\n\n\n\n\n"
  },
  {
    "path": "dos/wwivfoss/utiltest.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"util.h\"\n\n#include <conio.h>\n#include <ctype.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#pragma warning(disable : 4505)\n#pragma warning(disable : 4127)\n\n#define ASSERT_EQ(x, y) do { \\\n  if ((x) != (y)) { \\\n    fprintf(stderr, \"FAILED EQ: %s:%d: %d != %d\\r\\n \", __FILE__, __LINE__, x, y); \\\n    fflush(stderr); \\\n    return 1; \\\n  }  \\\n} while(0)\n\n#define ASSERT_STR_EQ(x, y) do { \\\n  if (strcmp((x), (y)) != 0) { \\\n    fprintf(stderr, \"FAILED STR_EQ: %s:%d: %s != %s\\r\\n \", __FILE__, __LINE__, x, y); \\\n    fflush(stderr); \\\n    return 1; \\\n  }  \\\n} while(0)\n\n\nint main(int, char**) {\n  Array a(10);\n  ASSERT_EQ(0, a.size());\n\n  a.push_back(\"Hello\");\n  ASSERT_EQ(1, a.size());\n  \n  a.push_back(\"World\");\n  ASSERT_EQ(2, a.size());\n  \n  ASSERT_STR_EQ(\"Hello\", a.at(0));\n  ASSERT_STR_EQ(\"World\", a.at(1));\n  fprintf(stderr, \"Success!\\r\\n\");\n  return 0;\n}\n"
  },
  {
    "path": "dos/wwivfoss/wwivfoss.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n// WWIVFOSS- Runs a command under a FOSSIL emulation shell.\n#include \"fossil.h\"\n#include \"pipe.h\"\n#include \"util.h\"\n#include <conio.h>\n#include <ctype.h>\n#include <dos.h>\n#include <fcntl.h>\n#include <io.h>\n#include <malloc.h>\n#include <process.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#pragma warning(disable : 4505)\n\nclass App {\npublic:\n  App() : opts(), cmdline(20) {}\n  ~App() {}\n\n  FossilOptions opts;\n  Array cmdline;\n};\n\nstatic void show_help() {\n  fprintf(stderr,\n    \"Usage: \\r\\n\"\n    \"  WWIVFOSS [args] COMMANDLINE\\r\\n\\r\\n\"\n    \"Example: \\r\\n\"\n    \"  WWIVFOSS -N2 BRE.BAT 2 Z:\\\\CHAIN.TXT\\r\\n\\r\\n\"\n    \"Commands: \\r\\n\"\n    \"  -N#   Node Number for this instance (1-99) [REQUIRED]\\r\\n\"\n    \"  -P#   Port Number for this fossil instance (unset means any)\\r\\n\"\n    \"  -?    Help - displays this information\\r\\n\"\n    \"\\r\\n\");\n}\n\nextern char __near* fossil_info_ident;\n\nint main(int argc, char** argv) {\n  fprintf(stderr, \"WWIVFOSS: \");\n  fprintf(stderr, ((char __near*)fossil_info_ident));\n  fprintf(stderr, \"\\r\\n\"\n      \"          Copyright (c) 2021-2023, WWIV Software Services\\r\\n\"\n      \"          Built: \" __DATE__ \", \" __TIME__ \"\\r\\n\\r\\n\");\n\n  App app;\n  int had_positional = 0;\n  for (int i = 1; i < argc; i++) {\n    const char* arg = argv[i];\n    const int alen = strlen(arg);\n    if (!alen) {\n      log(\"WARNING: Empty arg at position: %d\", i);\n      continue;\n    }\n    if (!had_positional && (arg[0] == '-' || arg[0] == '/')) {\n      if (alen < 2) {\n\t      log(\"Invalid argument: '%s'\", arg);\n\t      continue;\n      }\n      // Process switch\n      char schar = (char)toupper(*(arg+1));\n      const char* sval = (arg+2);\n      // cerr << \"Switch: \" <<  schar << \"; value: '\" << sval << \"'\" << std::endl;\n      switch (schar) {\n      case 'N': {\n\t      // Node number\n\t      app.opts.node_number = atoi(sval);\n      } break;\n      case 'P': {\n\t      // Node number\n\t      app.opts.comport = atoi(sval);\n      } break;\n      case '?': {\n        // Help\n        show_help();\n        return 0;\n      } break;\n      }\n      continue;\n    }\n    had_positional = 1;\n    // Positional arg, must be part of the commandline.\n    app.cmdline.push_back(arg);\n  } \n\n  // Args parsed, do something.\n  if (app.opts.node_number < 1) {\n    fprintf(stderr, \"Node number not specified.  Exiting.\\r\\n\");\n    show_help();\n    return 1;\n  }\n\n  if (!enable_fossil(&app.opts)) {\n    log(\"Failed to initialize FOSSIL support.\");\n    return 2;\n  }\n  \n  // Don't call _heapmin, or things crash later.\n  int ret = _spawnvp(_P_WAIT, app.cmdline.at(0), \n                     (const char**) app.cmdline.items());\n  disable_fossil();\n  if (ret < 0) {\n    log(\"Error spawning process. \");\n    return 3;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "fsed/CMakeLists.txt",
    "content": "# CMake for WWIV\nInclude(FindWWIVCurses)\n\nset(SOURCES \n commands.cpp\n common.cpp\n fsed.cpp\n line.cpp\n model.cpp\n view.cpp\n)\n\nadd_library(\n  fsed \n  ${SOURCES} \n) \n\ntarget_link_libraries(\n  fsed \n  fmt::fmt-header-only\n  local_io \n  common\n  core \n  sdk \n)\n\n\nset_max_warnings(fsed)\ntarget_include_directories(fsed PRIVATE ${CMAKE_CURRENT_BINARY_DIR})\n\nif (WWIV_BUILD_TESTS)\n  add_executable(fsed_tests\n    \"fsed_test_main.cpp\"\n    \"model_test.cpp\"\n    \"fsed_model_test.cpp\"\n  )\n\n  include(GoogleTest)\n  target_link_libraries(fsed_tests fsed core_fixtures core common sdk GTest::gtest)\n  gtest_discover_tests(fsed_tests EXTRA_ARGS \"--wwiv_testdata=${CMAKE_CURRENT_SOURCE_DIR}/testdata\")\n  \nendif()"
  },
  {
    "path": "fsed/commands.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/commands.h\"\n\n\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"core/stl.h\"\n#include \"fsed/model.h\"\n#include \"fsed/view.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/filenames.h\"\n#include <map>\n#include <utility>\n\nnamespace wwiv::fsed {\n\nusing namespace wwiv::common;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\n\n\nstd::map<int, fsed_command_id> CreateDefaultEditModeKeyMap() {\n  std::map<int, fsed_command_id> map;\n  map.emplace(COMMAND_UP, fsed_command_id::cursor_up);\n  map.emplace(COMMAND_DOWN, fsed_command_id::cursor_down);\n  map.emplace(COMMAND_PAGEUP, fsed_command_id::cursor_pgup);\n  map.emplace(COMMAND_PAGEDN, fsed_command_id::cursor_pgdown);\n  map.emplace(COMMAND_LEFT, fsed_command_id::cursor_left);\n  map.emplace(COMMAND_RIGHT, fsed_command_id::cursor_right);\n  map.emplace(COMMAND_HOME, fsed_command_id::cursor_home);\n  map.emplace(CA, fsed_command_id::cursor_home);\n  map.emplace(CD, fsed_command_id::delete_line);\n  map.emplace(COMMAND_END, fsed_command_id::cursor_end);\n  map.emplace(CE, fsed_command_id::cursor_end);\n  map.emplace(CK, fsed_command_id::delete_to_eol);\n  map.emplace(CL, fsed_command_id::view_redraw);\n  map.emplace(COMMAND_DELETE, fsed_command_id::delete_right);\n  map.emplace(BACKSPACE, fsed_command_id::backspace);\n  map.emplace(ESC, fsed_command_id::menu);\n  map.emplace(CI, fsed_command_id::toggle_insovr);\n  map.emplace(RETURN, fsed_command_id::key_return);\n  map.emplace(SOFTRETURN, fsed_command_id::ignore);\n  map.emplace(CP, fsed_command_id::input_wwiv_color);\n  map.emplace(CW, fsed_command_id::delete_word_left);\n  map.emplace(CX, fsed_command_id::delete_line_left);\n\n  return map;\n}\n\nFsedCommand::FsedCommand(fsed_command_id id, std::string name, fsed_command_fn fn)\n    : id_(id), name_(std::move(name)), fn_(std::move(fn)) {}\n\nbool FsedCommand::Invoke(FsedModel& model, FsedView& view, FsedState& state) const {\n  return fn_(model, view, state);\n}\n\nFsedCommands::FsedCommands(Context& ctx, MessageEditorData& data) : ctx_(ctx), data_(data) {\n  AddAll();\n  edit_keymap_ = CreateDefaultEditModeKeyMap();\n}\n\nstd::optional<FsedCommand> FsedCommands::get(fsed_command_id id) {\n  if (contains(by_id_, id)) {\n    return by_id_.at(id);\n  }\n  return std::nullopt;\n}\n\nstd::optional<FsedCommand> FsedCommands::get(const std::string& id) {\n  if (contains(by_name_, id)) {\n    return by_name_.at(id);\n  }\n  return std::nullopt;\n}\n\nbool FsedCommands::add(const FsedCommand& cmd) {\n  by_id_.emplace(cmd.id(), cmd);\n  by_name_.emplace(cmd.name(), cmd);\n  return true;\n}\n\nstatic void show_fsed_menu(Context& ctx, FsedModel& ed, FsedView& view, MessageEditorData& data,\n                           bool& done, bool& save) {\n  view.fs().PutsCommandLine(\n      \"|#9(|#2ESC|#9=Return, |#2A|#9=Abort, |#2Q|#9=Quote, |#2S|#9=Save, |#2D|#9=Debug, \"\n      \"|#2T|#9=Title, |#2?|#9=Help): \");\n  const auto cmd = std::toupper(view.fs().bgetch() & 0xff);\n  view.ClearCommandLine();\n  switch (cmd) {\n  case 'S':\n    view.ClearCommandLine();\n    view.fs().PutsCommandLine(\"\");\n    done = save = true;\n    break;\n  case 'A':\n    done = true;\n    save = false;\n    break;\n  case 'D': {\n    view.debug = !view.debug;\n    view.draw_bottom_bar(ed);\n  } break;\n  case 'Q': {\n    // Hacky quote solution for now.\n    // TODO(rushfan): Do something less lame here.\n    view.cls();\n    auto quoted_lines = query_quote_lines(ctx.session_context());\n    if (!quoted_lines.empty()) {\n      ed.insert_lines(quoted_lines);\n    }\n    // Even if we don't insert quotes, we still need to\n    // redraw the frame\n    view.redraw(ed);\n    ed.invalidate_to_eof(0);\n  } break;\n  case 'T': {\n    view.ClearCommandLine();\n    view.fs().PutsCommandLine(\"Title: \");\n    data.title = view.fs().in().input_text(data.title, 72);\n    view.ClearCommandLine();\n    view.redraw(ed);\n  } break;\n  case '?': {\n    view.ClearCommandLine();\n    view.fs().ClearMessageArea();\n    if (!view.fs().out().print_help_file(FSED_NOEXT)) {\n      view.fs().PutsCommandLine(wwiv::strings::StrCat(\"|#6Unable to find file: \", FSED_NOEXT));\n    }\n    view.fs().out().pausescr();\n    view.fs().ClearMessageArea();\n    view.ClearCommandLine();\n    view.redraw(ed);\n    ed.invalidate_to_eof(0);\n  } break;\n  case ESC:\n    [[fallthrough]];\n  default: {\n  } break;\n  }\n  view.ClearCommandLine();\n}\n\nbool FsedCommands::AddAll() {\n  add(FsedCommand(fsed_command_id::cursor_up, \"cursor_up\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_up(); }));\n  add(FsedCommand(fsed_command_id::cursor_down, \"cursor_down\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_down(); }));\n  add(FsedCommand(fsed_command_id::cursor_pgup, \"cursor_pgup\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_pgup(); }));\n  add(FsedCommand(fsed_command_id::cursor_pgdown, \"cursor_pgdown\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_pgdown(); }));\n  add(FsedCommand(fsed_command_id::cursor_left, \"cursor_left\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_left(); }));\n  add(FsedCommand(fsed_command_id::cursor_right, \"cursor_right\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_right(); }));\n  add(FsedCommand(fsed_command_id::cursor_home, \"cursor_home\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_home(); }));\n  add(FsedCommand(fsed_command_id::delete_line, \"delete_line\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.delete_line(); }));\n  add(FsedCommand(fsed_command_id::cursor_end, \"cursor_end\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.cursor_end(); }));\n  add(FsedCommand(fsed_command_id::delete_to_eol, \"delete_to_eol\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.delete_to_eol(); }));\n  add(FsedCommand(fsed_command_id::view_redraw, \"view_redraw\",\n                  [](FsedModel& ed, FsedView& view, FsedState&) -> bool {\n                    view.redraw(ed);\n                    ed.invalidate_to_eof(0);\n                    return true;\n                  }));\n  add(FsedCommand(fsed_command_id::delete_right, \"delete_right\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.delete_right(); }));\n  add(FsedCommand(fsed_command_id::key_return, \"key_return\",\n                  [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.enter(); }));\n  add(FsedCommand(fsed_command_id::backspace, \"backspace\",\n                  [&](FsedModel& ed, FsedView& view, FsedState&) -> bool {\n                    ed.bs();\n                    view.outchr(ed.curline().wwiv_color(), ed.current_cell().ch);\n                    return true;\n                  }));\n  add(FsedCommand(fsed_command_id::toggle_insovr, \"toggle_insovr\",\n                  [](FsedModel& ed, FsedView& view, FsedState&) -> bool {\n                    ed.toggle_ins_ovr_mode();\n                    view.draw_bottom_bar(ed);\n                    return true;\n                  }));\n  add(FsedCommand(fsed_command_id::input_wwiv_color, \"input_wwiv_color\",\n                  [&](FsedModel& ed, FsedView& view, FsedState&) -> bool {\n                    const auto cc = view.bgetch(ed);\n                    if (cc >= '0' && cc <= '9') {\n                      ed.curline().set_wwiv_color(cc - '0');\n                    } else if (cc == CA || cc == CD || cc == CF) {\n                      view.macro(ctx_, cc);\n                    }\n                    ed.current_line_dirty(ed.curli);\n                    return true;\n                  }));\n  add(FsedCommand(\n      fsed_command_id::delete_word_left, \"delete_word_left\",\n      [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.delete_word_left(); }));\n  add(FsedCommand(\n      fsed_command_id::delete_line_left, \"delete_line_left\",\n      [](FsedModel& ed, FsedView&, FsedState&) -> bool { return ed.delete_line_left(); }));\n  add(FsedCommand(fsed_command_id::menu, \"menu\",\n                  [&](FsedModel& ed, FsedView& view, FsedState& state) -> bool {\n                    show_fsed_menu(ctx_, ed, view, data_, state.done, state.save);\n                    return true;\n                  }));\n\n  add(FsedCommand(\n      fsed_command_id::ignore, \"ignore\",\n      [](FsedModel&, FsedView&, FsedState&) -> bool { return true; }));\n  return false;\n}\n\nstd::optional<fsed_command_id> FsedCommands::get_command_id(int key) {\n  const auto key_it = edit_keymap_.find(key);\n  if (key_it == std::end(edit_keymap_)) {\n    // No key binding\n    return std::nullopt;\n  }\n  return {key_it->second};\n}\n\nbool FsedCommands::InvokeCommand(fsed_command_id cmd_id, FsedModel& model, FsedView& view,\n                                 FsedState& state) {\n\n  if (auto cmd = get(cmd_id)) {\n    return cmd.value().Invoke(model, view, state);\n  }\n\n  // No command bound for this cmd_id.\n  LOG(WARNING) << \"No command for command id: \" << static_cast<int>(cmd_id);\n  return false;\n}\n\nbool FsedCommands::TryInterpretChar(int key, FsedModel& model, FsedView& view, FsedState& state) {\n\n  if (auto cmd_id = get_command_id(key)) {\n    return InvokeCommand(cmd_id.value(), model, view, state);\n  }\n  return false;\n}\n\n} // namespace"
  },
  {
    "path": "fsed/commands.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_COMMANDS_H\n#define INCLUDED_FSED_COMMANDS_H\n\n#include \"common/context.h\"\n#include <functional>\n#include <map>\n#include <optional>\n#include <string>\n\nnamespace wwiv::common {\nclass MessageEditorData;\n}\n\nnamespace wwiv::fsed {\n\nclass FsedModel;\nclass FsedView;\nclass FsedState;\n\nenum class fsed_command_id {\n  cursor_up,\n  cursor_down,\n  cursor_pgup, \n  cursor_pgdown,\n  cursor_left,\n  cursor_right,\n  cursor_home,\n  cursor_end,\n  delete_to_eol,\n  delete_line,\n  delete_line_left,\n  delete_word_left,\n  delete_right,\n  backspace,\n  key_return,\n  menu,\n  toggle_insovr,\n  view_redraw,\n  input_wwiv_color,\n  ignore,\n  none,\n};\n\ntypedef std::function<bool(FsedModel&, FsedView& view, FsedState&)> fsed_command_fn;\n\nclass FsedCommand {\npublic:\n\n  // remain default constructable so that we can be used in a map.\n  FsedCommand() = default;\n  FsedCommand(fsed_command_id id, std::string name, fsed_command_fn fn);\n  [[nodiscard]] fsed_command_id id() const { return id_; }\n  [[nodiscard]] std::string name() const { return name_; }\n  bool Invoke(FsedModel& mode, FsedView& view, FsedState& state) const;\n\nprivate:\n  fsed_command_id id_{fsed_command_id::none};\n  std::string name_;\n  fsed_command_fn fn_;\n};\n\nclass FsedCommands {\npublic:\n  FsedCommands() = delete;\n  FsedCommands(common::Context& ctx, common::MessageEditorData& data);\n  std::optional<FsedCommand> get(fsed_command_id id);\n  std::optional<FsedCommand> get(const std::string& id);\n  bool add(const FsedCommand& cmd);\n\n  std::optional<fsed_command_id> get_command_id(int key);\n\n  /**\n   * Attempts to interpret a key by executing a command.  Returns\n   * true if executed as a command, false otherwise.\n   */\n  bool InvokeCommand(fsed_command_id cmdid, FsedModel& model, FsedView& view, FsedState& state);\n\n  /**\n   * Attempts to interpret a key by executing a command.  Returns\n   * true if executed as a command, false otherwise.\n   */\n  bool TryInterpretChar(int key, FsedModel& model, FsedView& view, FsedState& state);\n\nprivate:\n  bool AddAll();\n\n  common::Context& ctx_;\n  common::MessageEditorData& data_;\n  std::map<fsed_command_id, FsedCommand> by_id_;\n  std::map<std::string, FsedCommand> by_name_;\n  std::map<int, fsed_command_id> edit_keymap_;\n};\n\n\nstd::map<int, fsed_command_id> CreateDefaultEditModeKeyMap();\n\n}\n\n#endif"
  },
  {
    "path": "fsed/common.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/common.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n\nnamespace wwiv::fsed {\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n/////////////////////\n// LOCALS\n\nstd::vector<line_t> read_file(const std::filesystem::path& path, int line_length) {\n  TextFile f(path, \"rt\");\n  if (!f) {\n    return {};\n  }\n  auto lines = f.ReadFileIntoVector();\n\n  std::vector<line_t> out;\n  for (auto l : lines) {\n    do {\n      const auto size_wc = size_without_colors(l);\n      if (size_wc <= line_length) {\n        out.emplace_back(false, l);\n        break;\n      }\n      // We have a long line\n      auto pos = line_length;\n      while (pos > 0 && l[pos] > 32) {\n        pos--;\n      }\n      if (pos == 0) {\n        pos = line_length;\n      }\n      auto subset_of_l = l.substr(0, pos);\n      l = l.substr(pos + 1);\n      out.emplace_back(true, l);\n    } while (true);\n  }\n  return out;\n}\n\n\n\n} // namespace wwiv::fsed"
  },
  {
    "path": "fsed/common.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_COMMON_H\n#define INCLUDED_FSED_COMMON_H\n\n#include \"fsed/line.h\"\n#include <filesystem>\n#include <vector>\n\nnamespace wwiv::fsed {\n\nstd::vector<line_t> read_file(const std::filesystem::path& path, int line_length);\n\n}\n\n#endif"
  },
  {
    "path": "fsed/fsed.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/fsed.h\"\n\n#include \"common/full_screen.h\"\n#include \"common/input.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/output.h\"\n#include \"core/eventbus.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fsed/commands.h\"\n#include \"fsed/common.h\"\n#include \"fsed/line.h\"\n#include \"fsed/model.h\"\n#include \"fsed/view.h\"\n\n#include <memory>\n#include <string>\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::fsed {\n\nstatic std::shared_ptr<FsedView> create_frame(MessageEditorData& data, bool file, const wwiv::sdk::User* user) {\n  const auto screen_width = (user != nullptr) ? user->screen_width() : 80;\n  const auto screen_length = (user != nullptr) ? user->screen_lines() - 1 : 24;\n  const auto num_header_lines = 4;\n  auto fs = FullScreenView(bout, bin, num_header_lines, screen_width, screen_length);\n  auto view = std::make_shared<FsedView>(fs, data, file);\n  view->redraw();\n  return view;\n}\n\nbool fsed(Context& ctx, const std::filesystem::path& path) {\n  MessageEditorData data(\"<<NO USERNAME>>\"); // anonymous username\n  data.title = path.string();\n  FsedModel ed(1000);\n  auto file_lines = read_file(path, ed.maxli());\n  if (!file_lines.empty()) {\n    ed.set_lines(std::move(file_lines));\n  }\n\n  auto save = fsed(ctx, ed, data, true);\n  if (!save) {\n    return false;\n  }\n\n  TextFile f(path, \"wt\");\n  if (!f) {\n    return false;\n  }\n  for (const auto& l : ed.to_lines(true)) {\n    f.WriteLine(l);\n  }\n  return true;\n}\n\nbool fsed(Context& ctx, std::vector<std::string>& lin, int maxli, MessageEditorData& data,\n          bool file) {\n  const auto saved_mci_enabled = bout.mci_enabled();\n  const auto saved_okskey = bin.okskey();\n  auto at_exit = finally([=] {\n    bout.set_mci_enabled(saved_mci_enabled);\n    bin.okskey(saved_okskey);\n  });\n  bout.disable_mci();\n  bin.okskey(false);\n\n  FsedModel ed(maxli);\n  for (auto l : lin) {\n    const auto wrapped = !l.empty() && l.back() == '\\x1';\n    ed.emplace_back(line_t{ wrapped, l });\n  }\n  if (!fsed(ctx, ed, data, file)) {\n    return false;\n  }\n\n  lin = ed.to_lines(true);\n  return true;\n}\n\nbool fsed(Context& ctx, FsedModel& ed, MessageEditorData& data, bool file) {\n  const auto saved_mci_enabled = bout.mci_enabled();\n  const auto saved_okskey = bin.okskey();\n  auto at_exit = finally([=] {\n    bout.set_mci_enabled(saved_mci_enabled);\n    bin.okskey(saved_okskey);\n  });\n  bout.disable_mci();\n  bin.okskey(false);\n\n  auto view = create_frame(data, file, &ctx.u());\n  ed.set_view(view);\n  auto& fs = view->fs();\n  ed.set_max_line_len(view->max_view_columns());\n  ed.add_callback([&view](FsedModel& e, editor_range_t t) {\n    view->handle_editor_invalidate(e, t);\n    });\n  ed.add_callback([&view](FsedModel& e, int previous_line) { \n      view->draw_current_line(e, previous_line);\n    });\n\n  // Draw the initial contents of the file.\n  ed.invalidate_to_eof(0);\n  // Draw the bottom bar once to start with.\n  view->ansic(0);\n  view->draw_bottom_bar(ed);\n  fs.GotoContentAreaTop();\n  FsedState state{};\n\n  FsedCommands commands(ctx, data);\n  // Add the menu command since that needs the state variables\n  // from here.\n\n  // top editor line number in thw viewable area.\n  while (!state.done) {\n    view->gotoxy(ed);\n\n    const auto key = view->bgetch(ed);\n    if (key < 0xff && key >= 32) {\n      const auto c = static_cast<char>(key & 0xff);\n\n      // If we're in the 1st postition and get a '/', display the menu.\n      if (c == '/' && ed.cx == 0) {\n        if (commands.InvokeCommand(fsed_command_id::menu, ed, *view, state)) {\n          // We showed the menu\n          continue;\n        }\n      }\n      view->gotoxy(ed);\n      view->outchr(ed.curline().wwiv_color(), c);\n      ed.add(c);\n      continue;\n    }\n    if (!commands.TryInterpretChar(key, ed, *view, state)) {\n      LOG(ERROR) << \"Unable to handle key: \" << key;\n    }\n  }\n\n  fs.ClearCommandLine();\n  fs.PutsCommandLine(\"\");\n  return state.save;\n}\n\n} // namespace\n"
  },
  {
    "path": "fsed/fsed.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_FSED_H\n#define INCLUDED_FSED_FSED_H\n\n#include \"common/context.h\"\n#include \"common/message_editor_data.h\"\n#include \"fsed/model.h\"\n#include <filesystem>\n#include <vector>\n#include <string>\n\nnamespace wwiv::fsed {\n\nbool fsed(wwiv::common::Context&ctx, const std::filesystem::path& path);\nbool fsed(common::Context& ctx, FsedModel& ed, common::MessageEditorData& data, bool file);\nbool fsed(common::Context& ctx, std::vector<std::string>& lin, int maxli,\n          common::MessageEditorData& data, bool file);\n\n}\n\n#endif"
  },
  {
    "path": "fsed/fsed_model_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/bbs_helper.h\"\n#include \"core/stl.h\"\n#include \"fsed/model.h\"\n\n#include \"gtest/gtest.h\"\n#include <memory>\n#include <string>\n\nusing namespace wwiv::stl;\n\nclass FakeView : public wwiv::fsed::editor_viewport_t {\npublic:\n  // Inherited via editor_viewport_t\n  [[nodiscard]] int max_view_lines() const override { return 10; }\n  [[nodiscard]] int max_view_columns() const override { return 20; }\n  [[nodiscard]] int top_line() const override { return top_line_; }\n  void set_top_line(int l) override { top_line_ = l; }\n  void gotoxy(const wwiv::fsed::FsedModel& ed) override { \n    x_ = ed.cx;\n    y_ = ed.cy;\n  }\n\nprivate:\n  int top_line_{0};\n  int x_{0};\n  int y_{0};\n};\n\nclass FsedModelWithViewTest : public ::testing::Test {\nprotected:\n  FsedModelWithViewTest() { \n    view = std::make_shared<FakeView>();\n    ed.set_view(view);\n  }\n\n  void add(const std::string& s) {\n    for (const auto& c : s) {\n      if (c == '\\n') {\n        ed.enter();\n        continue;\n      } \n      ed.add(c);\n    }\n  }\n\n  void add_test_lines(int n) {\n    for (int i = 0; i < n; i++) {\n      add(fmt::format(\"Test-{}\\n\", i));\n    }\n  }\n\n  wwiv::fsed::FsedModel ed{255};\n  std::shared_ptr<FakeView> view;\n};\n\nTEST_F(FsedModelWithViewTest, AddSingle_Character) {\n  ed.add('H');\n  EXPECT_EQ(0, ed.cy);\n  EXPECT_EQ(1, ed.cx);\n  EXPECT_EQ(0, ed.curli);\n  EXPECT_EQ(1, wwiv::stl::ssize(ed));\n}\n\nTEST_F(FsedModelWithViewTest, AddSingleline) {\n  const std::string line = \"Hello World\";\n  add(line);\n  EXPECT_EQ(0, ed.cy);\n  EXPECT_EQ(ssize(line), ed.cx);\n  EXPECT_EQ(0, ed.curli);\n  EXPECT_EQ(1, wwiv::stl::ssize(ed));\n}\n\nTEST_F(FsedModelWithViewTest, AddTwolines) {\n  const std::string line = \"Hello\\nWorld\";\n  add(line);\n  EXPECT_EQ(ssize(std::string(\"World\")), ed.cx);\n  EXPECT_EQ(1, ed.curli);\n  EXPECT_EQ(2, wwiv::stl::ssize(ed));\n  EXPECT_EQ(1, ed.cy);\n}\n\nTEST_F(FsedModelWithViewTest, SixLines) {\n  const std::string line = \"Hello\\nWorld\\nThis\\nIs\\nA\\nTest\\n\";\n  add(line);\n  EXPECT_EQ(6, ed.curli);\n  EXPECT_EQ(7, wwiv::stl::ssize(ed));\n  EXPECT_EQ(6, ed.cy);\n}\n\nTEST_F(FsedModelWithViewTest, PageUp_NoScroll) {\n  const std::string line = \"Hello\\nWorld\\nThis\\nIs\\nA\\nTest\\n\";\n  add(line);\n  ed.cursor_pgup();\n  EXPECT_EQ(0, ed.curli);\n  EXPECT_EQ(7, wwiv::stl::ssize(ed));\n  EXPECT_EQ(0, ed.cy);\n}\n\nTEST_F(FsedModelWithViewTest, PageUp_Scroll) {\n  add_test_lines(100);\n  EXPECT_EQ(100, ed.curli);\n  EXPECT_EQ(10, ed.cy);\n\n  // Scroll up\n  ed.cursor_pgup();\n  EXPECT_EQ(0, ed.cy);\n  EXPECT_EQ(90, ed.curli);\n}\n\nTEST_F(FsedModelWithViewTest, BackSpace_Color) {\n  ed.curline().set_wwiv_color(2);\n  add(\"a\");\n  // Still 2\n  EXPECT_EQ(2, ed.curline().wwiv_color());\n  ed.bs();\n  // Still 2 after a backspace\n  EXPECT_EQ(2, ed.curline().wwiv_color());\n  ed.bs();\n  // Now 0 since we went to the end.\n  EXPECT_EQ(0, ed.curline().wwiv_color());\n}\n"
  },
  {
    "path": "fsed/fsed_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2022, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/test/wwivtest.h\"\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n} \n"
  },
  {
    "path": "fsed/line.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/line.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n\nnamespace wwiv::fsed {\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nenum class add_cell_state_t { text, heart_color };\n\nline_t::line_t(bool wrapped, std::string text) : wrapped_(wrapped) {\n  auto state = add_cell_state_t::text;\n  for (const auto c : text) {\n    if (state == add_cell_state_t::heart_color) {\n      state = add_cell_state_t::text;\n      const auto color = static_cast<int>(c - '0');\n      if (color >= 0 && color <= 9) {\n        wwiv_color_ = color;\n      }\n      continue;\n    }\n    if (c == 0x03) {\n      state = add_cell_state_t::heart_color;\n      continue;\n    }\n    cell_.emplace_back(wwiv_color_, c);\n    ++size_;\n  }\n}\n\nvoid line_t::push_back(char c) {\n  cell_.emplace_back(wwiv_color_, c);\n  ++size_;\n}\n\nline_add_result_t line_t::add(int x, char c, ins_ovr_mode_t mode) {\n  while (size_ < x) {\n    push_back(' ');\n  }\n  if (x == size_) {\n    push_back(c);\n    return line_add_result_t::no_redraw;\n  }\n  if (mode == ins_ovr_mode_t::ins) {\n    wwiv::stl::insert_at(cell_, x, cell_t{wwiv_color_, c});\n    ++size_;\n    return line_add_result_t::needs_redraw;\n  }\n  cell_[x] = cell_t{wwiv_color_, c};\n  return line_add_result_t::no_redraw;\n}\n\nline_add_result_t line_t::del(int x, ins_ovr_mode_t) {\n  if (x < 0) {\n    return line_add_result_t::error;\n  }\n  const auto result = x == size_ ? line_add_result_t::no_redraw : line_add_result_t::needs_redraw;\n  if (!erase_at(cell_, x)) {\n    return line_add_result_t ::error;\n  }\n  --size_;\n\n  const auto new_x = x - 1;\n  if (new_x >= 0 && new_x < size_) {\n    // adopt new color\n    wwiv_color_ = cell_.at(new_x).wwiv_color;\n  }\n  return result;\n}\n\nline_add_result_t line_t::bs(int x, ins_ovr_mode_t mode) { \n  if (x <= 0) {\n    return line_add_result_t::error;\n  }\n  return del(x - 1, mode);\n}\n\nstd::size_t line_t::size() const { return size_; }\n\nint line_t::last_space_before(int maxlen) { \n  if (size_ < maxlen) {\n    return size_;\n  }\n  if (cell_.empty()) {\n    return 0;\n  }\n  for (auto i = maxlen - 1; i > 0; i--) {\n    const auto c = cell_.at(i).ch;\n    if (c == '\\t' || c == ' ') {\n      return i;\n    }\n  }\n  return 0;\n}\n\nvoid line_t::set_wwiv_color(int c) { \n  wwiv_color_ = c;\n}\n\nint line_t::wwiv_color() const noexcept { \n  return wwiv_color_; \n}\n\nline_t& line_t::operator=(const line_t& o) {\n  wrapped_ = o.wrapped_;\n  cell_ = o.cell_;\n  size_ = o.size_;\n  wwiv_color_ = o.wwiv_color_;\n  return *this;\n}\n\nvoid line_t::assign(const std::vector<cell_t>& cells) {\n  if (cells.empty()) {\n    cell_.clear();\n    size_ = 0;\n    return;\n  }\n  cell_ = cells;\n  size_ = size_int(cells);\n  wwiv_color_ = cells.back().wwiv_color;\n}\n\nvoid line_t::append(const std::vector<cell_t>& cells) {\n  if (cells.empty()) {\n    return;\n  }\n  for (const auto& c : cells) {\n    cell_.emplace_back(c);\n  }\n  size_ += size_int(cells);\n  wwiv_color_ = cells.back().wwiv_color;\n}\n\nstd::vector<cell_t> line_t::substr(int start, int end) {\n  return std::vector<cell_t>(cell_.begin() + start, cell_.begin() + end);\n}\n\nstd::vector<cell_t> line_t::substr(int start) {\n  return std::vector<cell_t>(cell_.begin() + start, cell_.end());\n}\n\nstatic void append_wwiv_color(std::string& out, int wwiv_color, line_color_code_format_t format) {\n  if (format == line_color_code_format_t::heart) {\n    out.push_back('\\x3');\n    out.push_back(static_cast<char>(wwiv_color + '0'));\n  } else {\n    out.append(fmt::format(\"|#{}\", wwiv_color));\n  }\n}\n\nstd::string line_t::to_colored_text(int default_last_color) const {\n  // default the last color to 0 by default)\n  bool changed_color = false;\n  // This used to be 0, try -1 so we always set the color explicitly.\n  auto last_color = default_last_color;\n  std::string out;\n  for (const auto& c : cell_) {\n    if (c.wwiv_color != last_color) {\n      append_wwiv_color(out, c.wwiv_color, line_color_code_format_t::heart);\n      last_color = c.wwiv_color;\n      changed_color = true;\n    }\n    out.push_back(c.ch);\n  }\n  if (changed_color) {\n    append_wwiv_color(out, 0, line_color_code_format_t::heart);\n  }\n  return out;\n}\n\n\n} // namespace wwiv::fsed"
  },
  {
    "path": "fsed/line.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_LINE_H\n#define INCLUDED_FSED_LINE_H\n\n#include <vector>\n#include <string>\n\nnamespace wwiv::fsed {\n\nenum class line_add_result_t { needs_redraw, no_redraw, error };\nenum class ins_ovr_mode_t { ins, ovr };\n\nclass cell_t {\npublic:\n  cell_t(int co, char cc) : wwiv_color(co), ch(cc) {}\n  int wwiv_color{0};\n  char ch{0};\n};\n\nenum class line_color_code_format_t { heart, pipe };\n\nclass line_t {\npublic:\n  line_t() : line_t(false, \"\") {}\n  line_t(bool wrapped, std::string text);\n  explicit line_t(std::string text) : line_t(false, std::move(text)) {}\n\n  line_add_result_t add(int x, char c, ins_ovr_mode_t mode);\n  line_add_result_t del(int x, ins_ovr_mode_t mode);\n  line_add_result_t bs(int x, ins_ovr_mode_t mode);\n  void push_back(char c);\n\n  [[nodiscard]] bool wrapped() const noexcept { return wrapped_; }\n  void wrapped(bool b) { wrapped_ = b; }\n\n  [[nodiscard]] std::size_t size() const;\n\n  // Specialized stuff\n  int last_space_before(int maxlen);\n  void set_wwiv_color(int c);\n  [[nodiscard]] int wwiv_color() const noexcept;\n\n  // operators\n  line_t& operator=(const line_t& o);\n\n  void assign(const std::vector<cell_t>& cells);\n  void append(const std::vector<cell_t>& cells);\n  [[nodiscard]] const std::vector<cell_t>& cells() const { return cell_; }\n  std::vector<cell_t> substr(int start, int end);\n  std::vector<cell_t> substr(int start);\n  // Gets a line of text that can be displayed using bputs\n  [[nodiscard]] std::string to_colored_text(int default_last_color) const;\n\nprivate:\n  bool wrapped_{false};\n  std::vector<cell_t> cell_;\n  int size_{0};\n  int wwiv_color_{0};\n};\n\n}\n\n#endif"
  },
  {
    "path": "fsed/model.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/model.h\"\n\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n\nnamespace wwiv::fsed {\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n/////////////////////////////////////////////////////////////////////////////\n// LOCALS\n\nstatic void advance_cy(FsedModel& ed, editor_viewport_t& view, bool invalidate = true) {\n  // advance cy if we have room, scroll region otherwise\n  if (ed.cy < view.max_view_lines()) {\n    ++ed.cy;\n  } else {\n    // scroll\n    view.set_top_line(ed.curli - ed.cy);\n    if (invalidate) {\n      ed.invalidate_to_eof(view.top_line());\n    }\n  }\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// EDITOR\n\nvoid FsedModel::set_view(const std::shared_ptr<editor_viewport_t>& view) { view_ = view; }\n\nline_t& FsedModel::curline() const {\n  // TODO: insert return statement here\n  while (curli >= size_int(lines_)) {\n    lines_.emplace_back();\n  }\n  try {\n    return lines_.at(curli);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Exception trying to get line: \" << curli << \"; what: \" << e.what();\n    LOG(ERROR) << wwiv::os::stacktrace();\n    throw;\n  }\n}\n\nline_t& FsedModel::line(int n) const {\n  try {\n    return lines_.at(n);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Exception trying to get line: \" << n << \"; what: \" << e.what();\n    LOG(ERROR) << wwiv::os::stacktrace();\n    throw;\n  }\n}\n\nbool FsedModel::set_lines(std::vector<line_t>&& n) {\n  lines_ = n;\n  return true;\n}\n\nvoid FsedModel::emplace_back(line_t&& n) { lines_.emplace_back(n); }\n\nbool FsedModel::insert_line() {\n  if (size_int(lines_) >= maxli()) {\n    return false;\n  }\n  return wwiv::stl::insert_at(lines_, curli, line_t());\n}\n\nbool FsedModel::insert_lines(std::vector<std::string>& lines) {\n  for (const auto& ql : lines) {\n    // Insert all quote lines.\n    ++curli;\n    insert_line();\n    curline() = line_t(ql);\n    advance_cy(*this, *view_, false);\n  }\n  // Add blank line afterwards to use to start new text.\n  ++curli;\n  insert_line();\n  advance_cy(*this, *view_, false);\n  // Redraw everything, the whole enchilada!\n  invalidate_to_eof(0);\n  return true;\n}\n\nbool FsedModel::remove_line() {\n  if (lines_.empty()) {\n    return false;\n  }\n  return wwiv::stl::erase_at(lines_, curli);\n}\n\neditor_add_result_t FsedModel::add(char c) {\n  auto& line = curline();\n  const auto line_result = line.add(cx, c, mode_);\n  if (line_result == line_add_result_t::error) {\n    return editor_add_result_t::error;\n  }\n  const auto start_line = curli;\n  ++cx;\n  if (cx < max_line_len_) {\n    // no  wrapping is needed\n    if (line_result == line_add_result_t::needs_redraw) {\n      invalidate_range(start_line, curli);\n    }\n    return editor_add_result_t::added;\n  }\n  const auto last_space = line.last_space_before(size_int(line));\n  line.wrapped(true);\n  const auto wwiv_color = line.wwiv_color();\n  if (last_space != -1 && (max_line_len_ - last_space) < (max_line_len_ / 2)) {\n    // Word Wrap at the position after the last space. That way the space\n    // end up on the previous line\n    const auto wrap_position = last_space + 1;\n    const auto nline = line.substr(wrap_position);\n    line.assign(line.substr(0, wrap_position));\n    ++curli;\n    insert_line();\n    curline().assign(nline);\n    cx = size_int(curline());\n  } else {\n    // Character wrap.\n    ++curli;\n    cx %= max_line_len_;\n  }\n  // Create the new line and carry over line color since we wrapped (either\n  // line or character).\n  curline().set_wwiv_color(wwiv_color);\n\n  invalidate_range(start_line, curli);\n  advance_cy(*this, *view_);\n  return editor_add_result_t::wrapped;\n}\n\ncell_t FsedModel::current_cell() const {\n  const auto& line = curline();\n  if (cx >= size_int(line)) {\n    return cell_t(0, ' ');\n  }\n  try {\n    return line.cells().at(cx);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Exception trying to get cx: \" << cx << \"; what: \" << e.what();\n    LOG(ERROR) << wwiv::os::stacktrace();\n    throw;\n  }\n}\n\nbool FsedModel::cursor_up() {\n  const auto previous_line = curli;\n  if (cy > 0) {\n    --cy;\n    --curli;\n    const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n    cx = std::min<int>(cx, right_max);\n  } else if (curli > 0) {\n    // scroll\n    --curli;\n    const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n    cx = std::min<int>(cx, right_max);\n    view_->set_top_line(curli);\n    invalidate_to_eof(view_->top_line());\n  }\n  current_line_dirty(previous_line);\n  return true;\n}\n\nbool FsedModel::cursor_down() {\n  const auto previous_line = curli;\n  if (curli < size_int(lines_) - 1) {\n    ++curli;\n    const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n    cx = std::min<int>(cx, right_max);\n    advance_cy(*this, *view_);\n  }\n  current_line_dirty(previous_line);\n  return true;\n}\n\nbool FsedModel::cursor_left() {\n  if (cx > 0) {\n    --cx;\n  }\n  return true;\n}\n\nbool FsedModel::cursor_right() {\n  // TODO: add option to cursor right to end of view\n  const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n  if (cx < right_max) {\n    ++cx;\n  }\n  return true;\n}\n\nbool FsedModel::cursor_pgup() {\n  const auto previous_line = curli;\n  const auto up = std::min<int>(curli, view_->max_view_lines());\n  // nothing to do!\n  if (up == 0) {\n    return true;\n  }\n  cy = std::max<int>(cy - up, 0);\n  curli = std::max<int>(curli - up, 0);\n  view_->set_top_line(curli - cy);\n  const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n  cx = std::min<int>(cx, right_max);\n  invalidate_to_eof(view_->top_line());\n  current_line_dirty(previous_line);\n  return true;\n}\n\nbool FsedModel::cursor_pgdown() {\n  const auto previous_line = curli;\n  const auto dn =\n      std::min<int>(view_->max_view_lines(), std::max<int>(0, size_int(lines_) - curli - 1));\n  if (dn == 0) {\n    // nothing to do!\n    return true;\n  }\n  curli += dn;\n  cy += dn;\n  const auto right_max = std::min<int>(max_line_len(), size_int(curline()));\n  cx = std::min<int>(cx, right_max);\n  if (cy >= view_->max_view_lines()) {\n    // will need to scroll\n    cy = view_->max_view_lines();\n    view_->set_top_line(curli - cy);\n    invalidate_to_eof(view_->top_line());\n  }\n  current_line_dirty(previous_line);\n  return true;\n}\n\nbool FsedModel::cursor_home() {\n  cx = 0;\n  return true;\n}\n\nbool FsedModel::cursor_end() {\n  cx = size_int(curline());\n  return true;\n}\n\nbool FsedModel::delete_line() {\n  if (remove_line()) {\n    invalidate_to_eof(curli);\n  }\n  current_line_dirty(curli);\n  return true;\n}\n\nbool FsedModel::delete_to_eol() {\n  if (cx < size_int(curline())) {\n    auto& oline = curline();\n    oline.assign(oline.substr(0, cx));\n    oline.wrapped(false);\n    invalidate_to_eol();\n  } else if (size_int(curline()) == 0) {\n    // delete line\n    if (remove_line()) {\n      invalidate_to_eof(curli);\n      current_line_dirty(curli);\n    }\n  }\n  return true;\n}\n\nbool FsedModel::delete_line_left() {\n  auto& line = curline();\n  const auto remainder = line.substr(cx);\n  line.assign(remainder);\n  cx = 0;\n  line.wrapped(false);\n  invalidate_to_eol();\n  return true;\n}\n\nbool FsedModel::delete_word_left() {\n  if (cx <= 0) {\n    return true;\n  }\n  auto& line = curline();\n  const auto last_space = line.last_space_before(cx);\n  if (last_space == cx) {\n    return true;\n  }\n  const auto remainder = line.substr(cx);\n  cx = last_space;\n  if (last_space == 0) {\n    line.assign(remainder);\n  } else {\n    line.assign(line.substr(0, cx));\n    line.append(remainder);\n  }\n  // TODO(rushfan): Should reflow paragraph here.\n  line.wrapped(false);\n  invalidate_to_eol();\n  return true;\n}\n\nbool FsedModel::delete_right() {\n  // TODO keep mode state;\n  del();\n  invalidate_to_eol();\n  view_->gotoxy(*this);\n  return true;\n}\n\n// Toggles the internal state if the editor is in INSERT or OVERWRITE mode. This\n// matters on add, bs, and del\n\nvoid FsedModel::toggle_ins_ovr_mode() {\n  mode_ = mode_ == ins_ovr_mode_t::ins ? ins_ovr_mode_t::ovr : ins_ovr_mode_t::ins;\n}\n\n// Get the internal state if the editor is in INSERT or OVERWRITE mode.\n\nins_ovr_mode_t FsedModel::mode() const noexcept { return mode_; }\n\nbool FsedModel::del() {\n  const auto r = curline().del(cx, mode_);\n  if (r == line_add_result_t::error) {\n    return false;\n  }\n  if (r == line_add_result_t::needs_redraw) {\n    invalidate_to_eof(curli);\n  }\n  return true;\n}\n\nbool FsedModel::bs_nowrap() {\n  const auto r = curline().bs(cx, mode_);\n  if (r == line_add_result_t::error) {\n    return false;\n  }\n  if (r == line_add_result_t::needs_redraw) {\n    invalidate_to_eof(curli);\n  }\n  return true;\n}\n\nbool FsedModel::bs() {\n  const auto previous_line = curli;\n  // TODO keep mode state;\n  const auto previous_cx = std::max<int>(cx - 1, 0);\n  const auto previous_cx_color = size_int(curline().cells()) > previous_cx ? curline().cells().at(previous_cx).wwiv_color : 0;\n  bs_nowrap();\n  if (cx > 0) {\n    --cx;\n  } else if (curli > 0 && size_int(curline()) == 0) {\n    // If current line is empty then delete it and move up one line\n    if (remove_line()) {\n      --cy;\n      --curli;\n      cx = size_int(curline());\n      invalidate_to_eof(curli);\n    }\n  } else if (curli > 0) {\n    auto& prev = line(curli - 1);\n    auto& cur = curline();\n    const auto last_pos = std::max<int>(0, max_line_len() - size_int(prev) - 1);\n    const auto new_cx = size_int(prev);\n    if (ssize(cur) < last_pos) {\n      prev.append(cur.cells());\n      remove_line();\n    } else if (const int space = cur.last_space_before(last_pos) > 0) {\n      prev.append(cur.substr(0, space));\n      cur.assign(cur.substr(space));\n    }\n    --cy;\n    --curli;\n    cx = new_cx;\n    invalidate_to_eof(curli);\n  }\n  current_line_dirty(previous_line);\n  view_->gotoxy(*this);\n  curline().set_wwiv_color(previous_cx_color);\n  return true;\n}\n\nbool FsedModel::enter() {\n  const auto orig_start_line = curli;\n  curline().wrapped(false);\n  const auto previous_color = curline().wwiv_color();\n  // Insert inserts after the current line\n  if (cx >= size_int(curline())) {\n    ++curli;\n    insert_line();\n  } else {\n    // Wrap\n    auto& oline = curline();\n    const auto ntext = oline.substr(cx);\n    oline.assign(oline.substr(0, cx));\n    oline.wrapped(false);\n\n    ++curli;\n    insert_line();\n    curline().assign(ntext);\n  }\n  advance_cy(*this, *view_);\n  // Restore the wwiv color on the new line so we don't reset to 0.\n  curline().set_wwiv_color(previous_color);\n  cx = 0;\n  invalidate_to_eof(orig_start_line);\n  current_line_dirty(orig_start_line);\n  return true;\n}\n\nbool FsedModel::add_callback(const editor_range_invalidated_fn& fn) {\n  range_callbacks_.emplace_back(fn);\n  return true;\n}\n\nbool FsedModel::add_callback(const editor_current_line_redraw_fn& fn) {\n  line_callbacks_.emplace_back(fn);\n  return true;\n}\n\nvoid FsedModel::invalidate_to_eol() {\n  editor_range_t r;\n  r.start.line = r.end.line = curli;\n  r.start.x = cx;\n  r.end.x = size_int(curline());\n  for (auto& c : range_callbacks_) {\n    c(*this, r);\n  }\n}\n\nvoid FsedModel::invalidate_to_eof() { invalidate_to_eof(curli); }\n\nvoid FsedModel::invalidate_to_eof(int start_line) {\n  invalidate_range(start_line, size_int(lines_) - 1);\n}\n\nvoid FsedModel::invalidate_range(int start_line, int end_line) {\n  editor_range_t r{};\n  r.start.line = start_line;\n  r.start.x = cx;\n  r.end.line = end_line;\n  for (auto& c : range_callbacks_) {\n    c(*this, r);\n  }\n}\n\nvoid FsedModel::current_line_dirty(int previous_line) {\n  for (auto& c : line_callbacks_) {\n    c(*this, previous_line);\n  }\n}\n\nstd::vector<std::string> FsedModel::to_lines(bool wrap) {\n  std::vector<std::string> out;\n  std::string curline;\n  for (const auto& l : lines_) {\n    if (!curline.empty() && curline.back() != ' ') {\n      curline.push_back(' ');\n    }\n    auto x = l.to_colored_text(0);\n    StringTrimCRLF(&x);\n    curline.append(x);\n    if (l.wrapped()) {\n      if (wrap) {\n        // wwiv line wrapping character.\n        curline.push_back('\\x1');\n        out.emplace_back(curline);\n        curline.clear();\n        continue;\n      }\n      // else leave curline as the current line and the next iteration will append to it.\n    } else {\n      out.emplace_back(curline);\n      curline.clear();\n    }\n  }\n\n  if (!curline.empty()) {\n    // Add last line if we have been building one up.\n    out.emplace_back(curline);\n    curline.clear();\n  }\n  return out;\n}\n\n} // namespace wwiv::fsed\n"
  },
  {
    "path": "fsed/model.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_MODEL_H\n#define INCLUDED_FSED_MODEL_H\n\n#include \"fsed/line.h\"\n#include <functional>\n#include <vector>\n#include <string>\n#include <memory>\n\nnamespace wwiv::fsed {\n\n\nclass FsedState {\npublic:\n  // mods are \"edit\", \"menu\", \"command\"\n  std::string mode{\"edit\"};\n  bool save{false};\n  bool done{false};\n};\n\nenum class editor_add_result_t { added, wrapped, error };\n\nstruct editor_marker_t {\n  int line{0};\n  int x{0};\n};\n\nstruct editor_range_t {\n  editor_marker_t start;\n  editor_marker_t end;\n};\n\nclass FsedModel;\n\nclass editor_viewport_t {\npublic:\n  virtual ~editor_viewport_t() = default;\n  [[nodiscard]] virtual int max_view_lines() const = 0;\n  [[nodiscard]] virtual int max_view_columns() const = 0;\n  [[nodiscard]] virtual int top_line() const = 0;\n  virtual void set_top_line(int l) = 0;\n  virtual void gotoxy(const FsedModel& ed) = 0;\n};\n\nclass FsedModel {\n\npublic:\n  \n  // Constructor and Destructor\n\n  explicit FsedModel(int max_lines) : maxli_(max_lines) {}\n  FsedModel() : FsedModel(255) {}\n  ~FsedModel() = default;\n  void set_view(const std::shared_ptr<editor_viewport_t>& view);\n\n  //\n  // Line Operations  \n  //\n\n  // gets the current line\n  line_t& curline() const;\n  // Gets the line at a position n or throws.\n  [[nodiscard]] line_t& line(int n) const;\n  bool set_lines(std::vector<line_t>&& n);\n  // return the number of lines.\n  [[nodiscard]] std::size_t size() const { return lines_.size(); }\n  // Adds a new line to the end of the list of lines.\n  void emplace_back(line_t&& n);\n  // inserts a new line after curli.\n  bool insert_line();\n\n  // Inserts all of the lines into the editor at the current\n  // position.  These lines may contain heart codes, or pipe\n  // codes or both.\n  bool insert_lines(std::vector<std::string>& lines);\n\n  // deletes the current line.\n  bool remove_line();\n\n  /**\n   * Return the text as a vector of strings\n   * If wrap is true then the text is wrapped in WWIV format, this means the\n   * last character is a \\x1.\n   */\n  std::vector<std::string> to_lines(bool wrap);\n\n  //\n  // Character Operations\n  //\n\n  // Adds a char at the current position (cx, curli);\n  editor_add_result_t add(char c);\n  // deletes current character and shifts left rest\n  bool del();\n  // backspace over existing character.  Does not handle wrapping the\n  // line onto the previous line\n  bool bs_nowrap();\n  // backspace over existing character.  Wraps the current line onto\n  // the previous line.\n  bool bs();\n  // handles the enter key\n  bool enter();\n  // Gets the current character\n  cell_t current_cell() const;\n\n  //\n  // Cursor Operations\n  //\n  bool cursor_up();\n  bool cursor_down();\n  bool cursor_left();\n  bool cursor_right();\n  bool cursor_pgup();\n  bool cursor_pgdown();\n  bool cursor_home();\n  bool cursor_end();\n\n  bool delete_line();\n  bool delete_to_eol();\n  bool delete_line_left();\n  bool delete_word_left();\n  bool delete_right();\n\n  // Toggles the internal state if the editor is in INSERT or OVERWRITE mode. This\n  // matters on add, bs, and del\n  void toggle_ins_ovr_mode();\n  // Get the internal state if the editor is in INSERT or OVERWRITE mode.\n  ins_ovr_mode_t mode() const noexcept;\n\n  //\n  // Maximums\n  //\n  void set_max_line_len(int n) noexcept { max_line_len_ = n; }\n  int max_line_len() const noexcept { return max_line_len_;  }\n  // Max number of lines\n  int maxli() const noexcept { return maxli_; }\n\n  //\n  // Listeners, Callbacks and invalidation\n  //\n  typedef std::function<void(FsedModel&, editor_range_t)> editor_range_invalidated_fn;\n  typedef std::function<void(FsedModel&, int)> editor_current_line_redraw_fn;\n  bool add_callback(const editor_range_invalidated_fn& fn);\n  bool add_callback(const editor_current_line_redraw_fn& fn);\n  void invalidate_to_eol();\n  void invalidate_to_eof();\n  void invalidate_to_eof(int start_line);\n  void invalidate_range(int start_line, int end_line);\n  void current_line_dirty(int previous_line);\n\n  //\n  // Public values\n  //\n\n  // cursor X position\n  int cx{0};\n  // cursor Y position\n  int cy{0};\n  // Current line number\n  int curli{0};\n\nprivate:\n  // Max number of lines allowed\n  int maxli_{255};\n  // Lines of text.  mark mutable so we can add the current line\n  // into the array and stay logically const.\n  mutable std::vector<line_t> lines_;\n  // Insert or Overwrite mode\n  ins_ovr_mode_t mode_{ins_ovr_mode_t::ins};\n  // Max number of lines allowed.\n  int max_line_len_{79};\n\n  std::vector<editor_range_invalidated_fn> range_callbacks_;\n  std::vector<editor_current_line_redraw_fn> line_callbacks_;\n  // Viewport for display\n  std::shared_ptr<editor_viewport_t> view_;\n};\n\n}\n\n#endif"
  },
  {
    "path": "fsed/model_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n\n#include \"fsed/model.h\"\n\nusing namespace wwiv::fsed;\nusing namespace testing;\n\n\nTEST(Model, NoWrap) { \n FsedModel model(100);\n\n model.emplace_back({false, \"Hello\"});\n model.emplace_back({false, \"World\"});\n\n auto lines = model.to_lines(false);\n EXPECT_THAT(lines.size(), Eq(2));\n EXPECT_THAT(lines[0], Eq(\"Hello\"));\n EXPECT_THAT(lines[1], Eq(\"World\"));\n}\n\nTEST(Model, NoWrapNeeded) {\n FsedModel model(100);\n\n model.emplace_back({false, \"Hello\"});\n model.emplace_back({false, \"World\"});\n\n auto lines = model.to_lines(true);\n EXPECT_THAT(lines.size(), Eq(2));\n EXPECT_THAT(lines[0], Eq(\"Hello\"));\n EXPECT_THAT(lines[1], Eq(\"World\"));\n}\n\nTEST(Model, Wrap_NotWWIV) {\n FsedModel model(10);\n\n model.emplace_back({true, \"Hello\"});\n model.emplace_back({false, \"World\"});\n\n auto lines = model.to_lines(false);\n EXPECT_THAT(lines.size(), Eq(1));\n EXPECT_THAT(lines[0], Eq(\"Hello World\"));\n}\n\nTEST(Model, Wrap_NotWWIV_End) {\n FsedModel model(10);\n\n model.emplace_back({true, \"Hello\"});\n model.emplace_back({true, \"World\"});\n\n auto lines = model.to_lines(false);\n EXPECT_THAT(lines.size(), Eq(1));\n EXPECT_THAT(lines[0], Eq(\"Hello World\"));\n}\n\nTEST(Model, Wrap_WWIV) {\n FsedModel model(10);\n\n model.emplace_back({true, \"Hello\"});\n model.emplace_back({false, \"World\"});\n\n auto lines = model.to_lines(true);\n EXPECT_THAT(lines.size(), Eq(2));\n EXPECT_THAT(lines[0], Eq(\"Hello\\x1\"));\n EXPECT_THAT(lines[1], Eq(\"World\"));\n}\n\nTEST(Model, Wrap_WWIV_End) {\n FsedModel model(10);\n\n model.emplace_back({true, \"Hello\"});\n model.emplace_back({true, \"World\"});\n\n auto lines = model.to_lines(true);\n EXPECT_THAT(lines.size(), Eq(2));\n EXPECT_THAT(lines[0], Eq(\"Hello\\x1\"));\n EXPECT_THAT(lines[1], Eq(\"World\\x1\"));\n}\n"
  },
  {
    "path": "fsed/view.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"fsed/view.h\"\n\n#include \"common/full_screen.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/input.h\"\n#include \"common/output.h\"\n#include \"fsed/model.h\"\n#include \"fsed/line.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"local_io/keycodes.h\"\n\nusing namespace wwiv::common;\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::fsed {\n\nFsedView::FsedView(const FullScreenView& fs, MessageEditorData& data, bool file)\n    : fs_(fs), bout_(fs_.out()), bin_(fs_.in()), data_(data), file_(file) {\n  max_view_lines_ = fs.message_height() - 1;\n  max_view_columns_ = fs.screen_width();\n}\n\nFullScreenView& FsedView::fs() { return fs_; }\n\nvoid FsedView::gotoxy(const FsedModel& ed) {\n  bout_.goxy(ed.cx + 1, ed.cy + fs_.lines_start()); // - top_line() \n}\n\nvoid FsedView::ClearCommandLine() { \n    fs_.PutsCommandLine(\"|#9(|#2ESC|#9 or |#2/|#9=Menu/Help) \"); }\n\nvoid FsedView::macro(Context& ctx, int cc) {\n  if (!ctx.session_context().okmacro() || bin.charbufferpointer_) {\n    return;\n  }\n  std::map<int, int> macro_nums{{CD, 0}, {CF, 1}, {CA, 2}};\n  const auto macro_num = macro_nums.at(cc);\n  const auto m = ctx.u().macro(macro_num);\n  if (m.empty()) {\n    return;\n  }\n  strcpy(&bin.charbuffer[1], m.c_str());\n  bin.charbufferpointer_ = 1;\n\n}\n\nvoid FsedView::draw_current_line(FsedModel& ed, int previous_line) { \n  if (previous_line != ed.curli) {\n    const auto py = previous_line - top_line() + fs_.lines_start();\n    bout_.goxy(0, py);\n    if (previous_line < size_int(ed)) {\n      bout_.outstr(ed.line(previous_line).to_colored_text(-1));\n    }\n    bout_.clreol();\n  }\n\n  const auto y = ed.curli - top_line() + fs_.lines_start(); \n  bout_.goxy(0, y);\n  bout_.ansic(0);\n  for (const auto& c : ed.curline().cells()) {\n    // Draw char by char for the current line so we don't display\n    // color codes where we are editing.\n    bout_.ansic(c.wwiv_color);\n    bout_.outchr(c.ch);\n  }\n  bout_.clreol();\n  gotoxy(ed);\n}\n\nvoid FsedView::handle_editor_invalidate(FsedModel& e, editor_range_t t) {\n  // TODO: optimize for first line\n\n  // Never go below top line.\n  const auto start_line = std::max<int>(t.start.line, top_line());\n  auto last_color = -1;\n\n  for (auto i = start_line; i <= t.end.line; i++) {\n    auto y = i - top_line() + fs_.lines_start();\n    if (y >= fs_.lines_end()) {\n      break;\n    }\n    if (i >= size_int(e)) {\n      break;\n    }\n    bout_.goxy(0, y);\n    auto& rl = e.line(i);\n    if (i == e.curli) {\n      for (const auto& c : rl.cells()) {\n        // Draw char by char for the current line so we don't display\n        // color codes where we are editing.\n        if (c.wwiv_color != last_color) {\n          last_color = c.wwiv_color;\n          bout_.ansic(c.wwiv_color);\n        }\n        bout_.outchr(c.ch);\n      }\n    } else {\n      bout_.outstr(rl.to_colored_text(-1));\n    }\n    bout_.clreol();\n  }\n\n  // Clean up the bottom.\n  // clear the current and then remaining\n  if (size_int(e) == t.end.line + 1) {\n    for (auto z = size_int(e) - top_line() + fs_.lines_start(); z < fs_.lines_end(); z++) {\n      bout_.goxy(0, z);\n      bout_.clreol();\n    }\n  }\n\n  gotoxy(e);\n}\n\nvoid FsedView::draw_header() {\n  const auto oldcuratr = bout_.curatr();\n  bout_.cls();\n  const auto to = data_.to_name.empty() ? \"All\" : data_.to_name;\n  bout_.print(\"|#7From: |#2{}\\r\\n\", data_.from_name);\n  bout_.print(\"|#7To:   |#2{}\\r\\n\", to);\n  bout_.print(\"|#7Area: |#2{}\\r\\n\", data_.sub_name);\n  bout_.print(\"|#7{}|#2{}\\r\\n\", (file_ ? \"File: \" : \"Subj: \"), data_.title);\n\n  bout_.setc(oldcuratr);\n}\n\nvoid FsedView::redraw() { \n  draw_header(); \n  fs_.DrawTopBar();\n  fs_.DrawBottomBar(\"\");\n  ClearCommandLine();\n}\n\nvoid FsedView::redraw(const FsedModel& ed) {\n  draw_header();\n  fs_.DrawTopBar();\n  // reset the cache that is used by draw_bottom_bar so that\n  // the bottom bar will be drawn even if the cursor position\n  // has not changed.\n  sx = sy = sl = -1;\n  draw_bottom_bar(ed);\n  ClearCommandLine();\n}\n\nvoid FsedView::draw_bottom_bar(const FsedModel& ed) {\n  const auto sc = bout_.curatr();\n  static auto smode = ed.mode();\n  static auto sdebug = debug;\n  static auto sline_color = 0;\n  const auto line_color = ed.curline().wwiv_color();\n  if (sx != ed.cx || sy != ed.cy || sl != ed.curli || smode != ed.mode() || sdebug != debug ||\n      sline_color != line_color) {\n    const auto* mode = ed.mode() == ins_ovr_mode_t::ins ? \"INS\" : \"OVR\";\n    const auto cell = ed.current_cell();\n    const auto text = (debug) ? fmt::format(\"X:{} Y:{} L:{} T:{} C:{} WC:{} WL:{} [{}]\", ed.cx, ed.cy, ed.curli,\n                                      top_line(), static_cast<int>(cell.ch), cell.wwiv_color, line_color, mode)\n                        : fmt::format(\"[{}]\", mode);\n    fs_.DrawBottomBar(text);\n    sx = ed.cx;\n    sy = ed.cy;\n    sl = ed.curli;\n    smode = ed.mode();\n    sdebug = debug;\n    sline_color = line_color;\n  }\n  bout_.setc(sc);\n  gotoxy(ed);\n}\n\nint FsedView::bgetch(FsedModel& ed) {\n  // bgetch_event doesn't process macros by design, but\n  // we want them in the FSED\n  if (bin_.charbufferpointer_) {\n    if (!bin_.charbuffer[bin_.charbufferpointer_]) {\n      bin_.charbufferpointer_ = 0;\n      bin_.charbuffer[0] = 0;\n    } else {\n      if (bin_.charbuffer[bin_.charbufferpointer_] == CC) {\n        bin_.charbuffer[bin_.charbufferpointer_] = CP;\n      }\n      return bin_.charbuffer[bin_.charbufferpointer_++];\n    }\n  }\n\n  return bin.bgetch_event(Input::numlock_status_t::NUMBERS, std::chrono::seconds(1),\n                      [&](Input::bgetch_timeout_status_t status, int s) {\n                        if (status == Input::bgetch_timeout_status_t::WARNING) {\n      fs_.PrintTimeoutWarning(s);\n                        } else if (status == Input::bgetch_timeout_status_t::CLEAR) {\n      ClearCommandLine();\n                        } else if (status == Input::bgetch_timeout_status_t::IDLE) {\n      draw_bottom_bar(ed);\n    }\n  });\n}\n\nvoid FsedView::outchr(int color, char ch) {\n  bout_.ansic(color);\n  bout_.outchr(ch);\n}\n\nvoid FsedView::cls() { bout_.cls(); }\n\nvoid FsedView::ansic(int c) { bout_.ansic(c); }\n\n\n} // namespace wwiv::fsed\n"
  },
  {
    "path": "fsed/view.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_FSED_VIEW_H\n#define INCLUDED_FSED_VIEW_H\n\n#include \"common/full_screen.h\"\n#include \"common/message_editor_data.h\"\n#include \"fsed/model.h\"\n\nnamespace wwiv {\nnamespace common {\nclass Context;\n}\n}\n\nnamespace wwiv::fsed {\n\nclass FsedView final : public editor_viewport_t {\npublic:\n  FsedView(const common::FullScreenView& fs, common::MessageEditorData& data, bool file);\n  ~FsedView() override = default;\n\n  common::FullScreenView& fs();\n  [[nodiscard]] int max_view_lines() const override { return max_view_lines_; }\n  [[nodiscard]] int max_view_columns() const override { return max_view_columns_; }\n  // Draws the current line without colors, and redraws the previous\n  // line with colors.\n  void draw_current_line(FsedModel& e, int previous_line);\n  // Updates the editor line number based on the cy and fs view of the \n  // world.\n  void handle_editor_invalidate(FsedModel&, editor_range_t t);\n  void draw_header();\n  void redraw();\n  void redraw(const FsedModel& ed);\n  void draw_bottom_bar(const FsedModel& ed);\n  [[nodiscard]] int bgetch(FsedModel& ed);\n  void outchr(int color, char ch);\n  void cls();\n  void ansic(int c);\n  [[nodiscard]] int top_line() const override { return top_line_; }\n  void set_top_line(int l) override { top_line_ = l; }\n  void gotoxy(const FsedModel& ed) override;\n  void ClearCommandLine();\n  void macro(wwiv::common::Context& ctx, int cc);\n\n  // Top editor line number visible in the viewport.\n  int top_line_{0};\n  bool debug{false};\n\nprivate:\n  common::FullScreenView fs_;\n  common::Output& bout_;\n  common::Input& bin_;\n  int max_view_lines_;\n  int max_view_columns_;\n  common::MessageEditorData& data_;\n  bool file_{false};\n  //  Saved positions for the bottom bar caching.\n  int sx{-1};\n  int sy{-1};\n  int sl{-1};\n};\n\n}\n\n#endif"
  },
  {
    "path": "install/data/menu_commands.json",
    "content": "{\n    \"version\": 1,\n    \"commands\": [\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"AutoMessage\",\n            \"help\": \"Displays the legacy automessage menu\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"ReadAutoMessage\",\n            \"help\": \"Read the auto message\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:delete\",\n            \"help\": \"Deletes the auto message (cosysop required)\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:email\",\n            \"help\": \"E-mail the author of the automessage\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:lock\",\n            \"help\": \"Locks the automessage (cosysop required)\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:read\",\n            \"help\": \"Read the auto message \\n[use automessage:read instead]\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:unlock\",\n            \"help\": \"Unlocks the automessage (cosysop required)\"\n        },\n        {\n            \"cat\": \"AutoMessage\",\n            \"cmd\": \"amsg:write\",\n            \"help\": \"Writes a new auto message\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist\",\n            \"help\": \"Legacy BBSList Menu\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist:add\",\n            \"help\": \"Adds a new BBS to the BBSList\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist:bbslist\",\n            \"help\": \"Legacy BBSList Menu\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist:delete\",\n            \"help\": \"Deletes a new BBS from the BBSList\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist:net\",\n            \"help\": \"Read the network bbs lists\"\n        },\n        {\n            \"cat\": \"BBSList\",\n            \"cmd\": \"bbslist:read\",\n            \"help\": \"Read the bbslist\"\n        },\n        {\n            \"cat\": \"Chain\",\n            \"cmd\": \"Doors\",\n            \"help\": \"Enter the doors, or chains section.  Like '.'\"\n        },\n        {\n            \"cat\": \"Chain\",\n            \"cmd\": \"RunDoor\",\n            \"help\": \"<door name>\\n\\n  Runs a door (chain) with doorname matching, exactly, the description you have\\n  given the door in //CHEDIT\"\n        },\n        {\n            \"cat\": \"Chain\",\n            \"cmd\": \"RunDoorFree\",\n            \"help\": \"<door name>\\n\\n  Runs a door (chain) with doorname matching, exactly, the description you have\\n  given the door in //CHEDIT, but this function bypasses the check to see if\\n  the user is allowed to run the door.\"\n        },\n        {\n            \"cat\": \"Chain\",\n            \"cmd\": \"RunDoorNumber\",\n            \"help\": \"<door number>\\n\\n  Like RunDoor, but you must specify the #1 in //CHEDIT instead of the\\n  description.\"\n        },\n        {\n            \"cat\": \"Chain\",\n            \"cmd\": \"RunDoorNumberFree\",\n            \"help\": \"<door number>\\n\\n  Like RunDoorFree, but you must specify the #1 in //CHEDIT instead of the\\n  description.\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"DisableConf\",\n            \"help\": \"Turns conferencing off\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"DownDirConf\",\n            \"help\": \"Go to the prior directory conference '{'\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"DownSubConf\",\n            \"help\": \"Decrement ({) to the next sub conference\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"EnableConf\",\n            \"help\": \"Turns conferencing on\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"JumpDirConf\",\n            \"help\": \"Jump to another directory conference 'J'\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"JumpSubConf\",\n            \"help\": \"Jump to another sub conference.\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"NewMsgsAllConfs\",\n            \"help\": \"Do a new message scan for all subs in all conferences '/A'\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"UpDirConf\",\n            \"help\": \"Go to the next directory conference '}'\"\n        },\n        {\n            \"cat\": \"Conference\",\n            \"cmd\": \"UpSubConf\",\n            \"help\": \"Increment ()) to the previous conference number\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"AttachFile\",\n            \"help\": \"\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"KillEMail\",\n            \"help\": \"Kill email that you have sent 'K'\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"MultiEMail\",\n            \"help\": \"Send multi-email\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"ReadAllMail\",\n            \"help\": \"Sysop command to read all mail\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"ReadEMail\",\n            \"help\": \"Read your email\"\n        },\n        {\n            \"cat\": \"EMail\",\n            \"cmd\": \"SendEMail\",\n            \"help\": \"Enter and send email 'E' from the main menu\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"AllowEdit\",\n            \"help\": \"Sysop command to enter the 'ALLOW.DAT' editor.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"BatchMenu\",\n            \"help\": \"Enter the batch menu 'B'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ConfigFileList\",\n            \"help\": \"Enter the List+ configurator so the user can set it up to look like he wants\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"DLFile\",\n            \"help\": \"<dirfname> <filename>\\n\\n  This will download a file, with a check for ratios and will update the\\n  kb downloaded and number of files downloaded.\\n  You must specify the dirfilename, which is the name of the data file in\\n  the transfer editor.  filename is the name of the file being downloaded.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"DLFreeFile\",\n            \"help\": \"<dirfname> <filename>\\n\\n  This will download a file, but not check ratios or charge a download charge.\\n  You must specify the dir filename, which is the name of the data file in\\n  the transfer editor.  filename is the name of the file being downloaded.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"DirList\",\n            \"help\": \"List the directory names in the xfer section\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"DownDir\",\n            \"help\": \"Go to the prior directory number '-'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"Download\",\n            \"help\": \"Download a file 'D'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"FindDescription\",\n            \"help\": \"Search for a file by description\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"HopDir\",\n            \"help\": \"Hop to another directory number 'H'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ListFiles\",\n            \"help\": \"List the file in the current directory\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ListUsersDL\",\n            \"help\": \"List users with access to the current xfer sub\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"MoveFiles\",\n            \"help\": \"Sysop command to move files\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"NewFileScan\",\n            \"help\": \"List files that are new since your 'New Scan Date (usually last call)' 'N'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"NewFilesAllConfs\",\n            \"help\": \"New file scan in all directories in all conferences\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"PrintDSZLog\",\n            \"help\": \"View the DSZ log\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ReadIDZ\",\n            \"help\": \"Sysop command to read the file_id.diz and add it to the extended description\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"RemoveFiles\",\n            \"help\": \"Remove a file you uploaded\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"RemoveNotThere\",\n            \"help\": \"SYSOP command to remove files that do not exist.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"RenameFiles\",\n            \"help\": \"Sysop command to edit and rename files\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ReverseSortDirs\",\n            \"help\": \"Sort the directory by date or name, backwards.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SearchAllFiles\",\n            \"help\": \"Search all files???\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SelectDir\",\n            \"help\": \"Like SelectSub, but for the xfer section.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SetDirConf\",\n            \"help\": \"<key>\\n\\n  Sets the xfer section conference to key\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SetDirNumber\",\n            \"help\": \"<key>\\n\\n  Equivalent to typing in a number at the xfer menu, it sets the current dir\\n  number.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SetNewFileScanDate\",\n            \"help\": \"Set the 'New Scan Date' to a new date\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"SortDirs\",\n            \"help\": \"Sort the directory by date or name\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"UpDir\",\n            \"help\": \"Go to the next directory number '+'\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"Upload\",\n            \"help\": \"User upload a file\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"UploadAllDirs\",\n            \"help\": \"Syosp command to add any files sitting in the directories, but not in\\n  the file database to wwiv's file database\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"UploadCurDir\",\n            \"help\": \"Sysop command to scan the current directory for any files that are not in\\n  wwiv's file database and adds them to it.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"UploadFilesBBS\",\n            \"help\": \"Import a files.bbs (probably a CD) into the wwiv's file database\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"UploadToSysop\",\n            \"help\": \"Upload a file into dir#0, the sysop dir.\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"ViewArchive\",\n            \"help\": \"List an archive's contents\"\n        },\n        {\n            \"cat\": \"File\",\n            \"cmd\": \"XferDefaults\",\n            \"help\": \"Enter the xfer section defaults\"\n        },\n        {\n            \"cat\": \"GFiles\",\n            \"cmd\": \"BulletinEdit\",\n            \"help\": \"Sysop command to edit the bulletins 'gfiles'\"\n        },\n        {\n            \"cat\": \"GFiles\",\n            \"cmd\": \"Bulletins\",\n            \"help\": \"Enter the bulletins (or 'gfiles') section.  'G'\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"DisplayHelp\",\n            \"help\": \"An alias for DisplayMenu. \\n  This alias is deprecated, please use menu:display.\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"DisplayMenu\",\n            \"help\": \"Prints the 'novice menus' for the current menu set, or if one doesn't exist,\\n  it will generate one using command \\\"menu:generate_short\\\"\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"MENU\",\n            \"help\": \"<menu>\\n  Loads up and starts running a new menu set, where <menu> equals the name of\\n  the menu to load.\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"ReturnFromMenu\",\n            \"help\": \"\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"menu:display\",\n            \"help\": \"Prints the 'novice menus' for the current menu set, or if one doesn't exist,\\n  it will generate one using command \\\"menu:generate_short\\\"\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"menu:generate_long\",\n            \"help\": \"Generates the long form (one cmd per line) help text/menu for the current menu set.\\nThis command does not attempt to display a .msg/.ans file.\"\n        },\n        {\n            \"cat\": \"Menu\",\n            \"cmd\": \"menu:generate_short\",\n            \"help\": \"Generates the short form 'novice menus' for the current menu set.\\nThis command does not attempt to display a .msg/.ans file.\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"ClearQScan\",\n            \"help\": \"Marks messages unread.\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"DownSub\",\n            \"help\": \"Decrement the current sub number (-)\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"HopSub\",\n            \"help\": \"Hop to another sub.  'H'\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"ListUsers\",\n            \"help\": \"List users who have access to the current sub\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"NewMessageScan\",\n            \"help\": \"Do a new message scan\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"NewMsgScanCurSub\",\n            \"help\": \"Scan new messages in the current message sub\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"NewMsgScanFromHere\",\n            \"help\": \"Read new messages starting from the current sub\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"PostMessage\",\n            \"help\": \"Post a message in the current sub\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"RemovePost\",\n            \"help\": \"Remove a post\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"ResetQscan\",\n            \"help\": \"Set all messages to read (I think)\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"SelectSub\",\n            \"help\": \"This will prompt the user to enter a sub to change to.  However, it does not\\n  first show the subs (like Renegade).  However, you can stack a sublist and\\n  then this command to mimic the action.\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"SetMsgConf\",\n            \"help\": \"<key>\\n\\n  Sets the subboards conference to key\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"SetNewScanMsg\",\n            \"help\": \"Enter the menu so that a user can set which subs he want to scan when doing\\n  a new message scan\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"SetSubNumber\",\n            \"help\": \"<key>\\n\\n  Equivalent to typing in a number at the main menu, it sets the current sub\\n  number.\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"SubList\",\n            \"help\": \"List the subs available\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"TitleScan\",\n            \"help\": \"Scan the titles of the messages in the current sub\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"UnQScan\",\n            \"help\": \"Marks messages as unread\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"UpSub\",\n            \"help\": \"Increment the current sub# (+)\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"UploadPost\",\n            \"help\": \"Allow a user to upload a post that will be posted\"\n        },\n        {\n            \"cat\": \"Message\",\n            \"cmd\": \"ValidatePosts\",\n            \"help\": \"Sysop command to validate unvalidated posts\"\n        },\n        {\n            \"cat\": \"Net\",\n            \"cmd\": \"NetListing\",\n            \"help\": \"Show networks\"\n        },\n        {\n            \"cat\": \"Net\",\n            \"cmd\": \"NetLog\",\n            \"help\": \"Sysop command to view the network log\"\n        },\n        {\n            \"cat\": \"Net\",\n            \"cmd\": \"Pending\",\n            \"help\": \"Shows which net files are ready to be sent\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"Packers\",\n            \"help\": \"Executes the QWK menu. (Legacy, use qwk: commands now)\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"qwk:config_sysop\",\n            \"help\": \"Configures SysOp Settings for QWK\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"qwk:config_user\",\n            \"help\": \"Configures User Settings for QWK\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"qwk:download\",\n            \"help\": \"Download a QWK Message Packet\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"qwk:menu\",\n            \"help\": \"Executes the default QWK menu.\"\n        },\n        {\n            \"cat\": \"QWK\",\n            \"cmd\": \"qwk:upload\",\n            \"help\": \"Upload a QWK Reply Packet\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ChainEdit\",\n            \"help\": \"Sysop command to edit the doors or chains\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ChangeUser\",\n            \"help\": \"Sysop command equal to //CHUSER, to change into another users\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ConferenceEdit\",\n            \"help\": \"Sysop command ot edit the conferences\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"DirEdit\",\n            \"help\": \"Sysop command to edit the directory records\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"Edit\",\n            \"help\": \"Sysop command to edit a text file\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"MemStat\",\n            \"help\": \"\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"Status\",\n            \"help\": \"\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"SubEdit\",\n            \"help\": \"Sysop command to edit the subboards\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ToggleAvailable\",\n            \"help\": \"Toggle the sysop availability for chat\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ValidateUser\",\n            \"help\": \"Validate a new users.  I think this '!'\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"ViewNetDataLog\",\n            \"help\": \"View the net data logs\"\n        },\n        {\n            \"cat\": \"SYSOP\",\n            \"cmd\": \"VoteEdit\",\n            \"help\": \"Sysop command to edit the voting both\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"ChatRoom\",\n            \"help\": \"Go into the multiuser chat room\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"Defaults\",\n            \"help\": \"Enter the normal 'defaults' section\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"FastGoodBye\",\n            \"help\": \"Logoff fast '/O'\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"Feedback\",\n            \"help\": \"Leave feedback to the syosp.  'F'\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"Goodbye\",\n            \"help\": \"Normal logoff 'O'\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"GuestApply\",\n            \"help\": \"Allows a guest to apply for access\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"LastCallers\",\n            \"help\": \"View the last few callers\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"ListAllColors\",\n            \"help\": \"Display all colors available for use.\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"LoadText\",\n            \"help\": \"Sysop command to load a text file that will be edited in the text editor\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"LoadTextFile\",\n            \"help\": \"Looks like a duplicate to 'LoadText'\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"Log\",\n            \"help\": \"Syosp command to view the log file\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"Pause\",\n            \"help\": \"Pauses the screen, like 'pausescr()' in C code\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"PrintDevices\",\n            \"help\": \"Show the 'devices'.  I have no idea why.\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"PrintFile\",\n            \"help\": \"<filename>\\n\\n  Prints a file, first checking to see if you specified an absolute path,\\n  then the language dir, then the gfilesdir.  It will use the usual checks to\\n  determine .ANS, or .MSG if not specified.\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"PrintFileNA\",\n            \"help\": \"<filename>\\n\\n  Just like PrintFile, but the user can not abort it with the space bar.\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"RequestChat\",\n            \"help\": \"Request chat from the sysop\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"RunBasic\",\n            \"help\": \"<script name>\\n\\nRuns a WWIVbasic Script\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"SystemInfo\",\n            \"help\": \"View the system info\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"TextEdit\",\n            \"help\": \"Edit a text file\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"TimeBank\",\n            \"help\": \"Enter the time bank\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"ToggleExpert\",\n            \"help\": \"Turn 'X'pert mode on or off (toggle)\\n  Can optionally pass \\\"quiet=on\\\" as the command data to suppress displaying the expert mode state.\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"TurnMCIOff\",\n            \"help\": \"Disable MCI codes\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"TurnMCIOn\",\n            \"help\": \"Enable MCI codes\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"WHO\",\n            \"help\": \"Show who else is online\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"WWIVVer\",\n            \"help\": \"Get the wwiv version\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"YLog\",\n            \"help\": \"View yesterdays log\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"YourInfo\",\n            \"help\": \"Display the yourinfo screen\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"YourInfoDL\",\n            \"help\": \"Prints user info for downloads\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"ZLog\",\n            \"help\": \"View the ZLog\"\n        },\n        {\n            \"cat\": \"System\",\n            \"cmd\": \"cls\",\n            \"help\": \"Clear the screen\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"ConfigUserMenuSet\",\n            \"help\": \"Takes the user into the user menu config so they can select which menuset\\n  they want to use, etc...\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:24\",\n            \"help\": \"Toggles If the time should be displayed using a 24-hour clock vs. 12-hour\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:address\",\n            \"help\": \"Allows the user to change their address\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:ansistate\",\n            \"help\": \"Allows the user to change their ANSI state\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:autoquote\",\n            \"help\": \"Toggles If new messages in external editors should contain the entire reply text\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:callsign\",\n            \"help\": \"Allows the user to change their HAM callsign\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:city\",\n            \"help\": \"Allows the user to change their city\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:cls\",\n            \"help\": \"Toggles If the screen should be cleared between messages in the non-full screen message reader\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:colors\",\n            \"help\": \"Allows the user to change their colors\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:comptype\",\n            \"help\": \"Allows the user to change their computer type\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:conference\",\n            \"help\": \"Toggles if conferences are enables\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:country\",\n            \"help\": \"Allows the user to change their country\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:ctrlcodes\",\n            \"help\": \"Toggles if message lines with kludges or control codes are shown\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:dataphone\",\n            \"help\": \"Allows the user to change their data phone number\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:editor\",\n            \"help\": \"Allows the user to change their default editor\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:email\",\n            \"help\": \"Allows the user to change their email address\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:extra_color\",\n            \"help\": \"Toggles Extra Colors\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:fs_reader\",\n            \"help\": \"Toggles If the full screen message reader is used\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:gender\",\n            \"help\": \"Allows the user to change their gender\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:macros\",\n            \"help\": \"Allows the user to change their macros\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:mailbox\",\n            \"help\": \"Allows the user to change their email forward/mailbox settings\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:menus\",\n            \"help\": \"Takes the user into the user menu config so they can select which menuset\\n  they want to use, etc...\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:nomsgs\",\n            \"help\": \"Toggles If the user doesn't want inter instance messages\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:optional_lines\",\n            \"help\": \"Allows the user to change the number of optional lines displayed\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:password\",\n            \"help\": \"Allows the user to change their password\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:pause\",\n            \"help\": \"Toggles pause on page\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:phone\",\n            \"help\": \"Allows the user to change their voice phone number\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:qscan\",\n            \"help\": \"Allows the user to change their subs that are newscanned\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:realname\",\n            \"help\": \"Allows the user to change their real name\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:regnum\",\n            \"help\": \"Allows the user to change their WWIV 4.x registration number\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:screensize\",\n            \"help\": \"Allows the user to change their screen size\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:state\",\n            \"help\": \"Allows the user to change their state\"\n        },\n        {\n            \"cat\": \"User\",\n            \"cmd\": \"user:zipcode\",\n            \"help\": \"Allows the user to change their zipcode\"\n        },\n        {\n            \"cat\": \"Vote\",\n            \"cmd\": \"InitVotes\",\n            \"help\": \"\"\n        },\n        {\n            \"cat\": \"Vote\",\n            \"cmd\": \"Vote\",\n            \"help\": \"Enter the voting both\"\n        },\n        {\n            \"cat\": \"Vote\",\n            \"cmd\": \"VotePrint\",\n            \"help\": \"Show the voting statistics\"\n        }\n    ]\n}"
  },
  {
    "path": "install/docs/changelog-2000-2014.txt",
    "content": "==============================================================================\n                             WWIV 5.0 Source Code\n              Copyright 2002-2020 WWIV Software Services\n==============================================================================\n\nThis is the legacy changelog.  More recent changes can be found from the\nsubversion commit log.\n\n==============================================================================\n\nSee WHATSNEW.TXT or the Subversion ChangeLog for changes post February 2014.\n\nLABEL: WWIV-5_0_62\nDATE:  February 2014\n\nRushfan - Created start of a cmake makefile. It build bbs on mac and linux so far.\nWSS     - Fixed XY locations of line when editing system event in Event Editor.\nAtani   - Added periodic event support (recurring event every 1-240mins)\nAtani   - Fixed odd formatting in user list\nAtani   - Fixed failure due to lowercase drive letter\nAtani   - Added periodic event execution, freq range of 1-60min currently.\nAtani   - Upgraded projects to VS2013.\nAtani   - Fixed door.sys generation.\nAtani   - Fix for invalid drive probing for free space.\nAtani   - Misc fixes for fix to compile/work again.\nAtani   - Fixed crash WRT invalid instance data on startup.\nAtani   - Upgraded PDCurses to 3.4.\nAtani   - Fix issue identified in large filebases\nAtani   - Added flags for C++11 compiling on Linux\nAtani   - Added WUserManager::FindUser(string) to reduce duplicated code in networking\n          stack and bbs\nRushfan - Upgrade to vs2013 for telnet server.\nAtani   - Removed duplicated code in ~WIOSerial.\nRushfan - Fixes to automessage.\nAtani   - Fixes for GFiles.\nAtani   - Converted most high ascii instances to \\xXX (hex) in the source code.\nAtani   - Updated displayed copyrights to 2014.\nAtani   - Fixed case where no modem is configured startup would crash due to\n          null/empty modem response string.\nAtani   - Fixes for //EM crash on loading menu descriptions file.\nAtani   - moved memory.h include into wwiv.h and define _USE_32BIT_TIME_T.\nAtani   - Updated platform detection when on Win7 and compiling with Win7+ SDKs.\nAtani   - Revert of r210 updates that were incorrect.\n\n-- Older updated pre-2014:\nAtani   - Added VS 2005 project files\nAtani   - Copyright update to 2007\nAtani   - Started in earnest on an OS X port.\nRushfan - More STL'ification\nAtani   - more OS X tweaks\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_61\nDATE:  01/15/2006\n\nRushfan - Fixed up more time_t != sizeof(int) issues in the code, mainly with localtime\nRushfan - Some const correctness work, also using ISO C++ functionanmes in more places\nRushfan - Changed WStatusMgr::Get to return a bool instead of calling AbortBBS directly\nRushfan - Made WFile::Write take a const void * parameter to help fix const correctness\nRushfan - Implemented windows trashcan support in WFile::Delete\nRushfan - Changed ANSI file code over to WFile in several places througout the code.\nRushfan - Got rid of filelength (use WFile::GetLength()) now.\nRushfan - renamed islname to GetTemporaryInstanceLogFileName\nRushfan - renamed slname to GetSysopLogFileName\nRushfan - Split up each of the different dropfile creation code into separate functions\nRushfan - renamed sl1 to AddLineToSysopLogImpl\nRushfan - Started making WStatusMgr support transactions so status can stop being global\nAtani   - various linux compilation issues fixed\nRushfan - Added WFile::Exists(dir,filename), WFile::Remove(string)\nRushfan - Fixed issue with startup (not starting) and cleaned up some xinit code\nRushfan - Introduced WTextFile as a replacement for the CRT FILE* handle + our fsh_XXX code\nRushfan - Started making utility objects not depend on so much of the BBS so that\n          WFile, WTextFile, WUser, WUserManager can be used outside of the BBS, eventually\n          we will have classes for messagebase manipulation available from outside of WWIV.\nRushfan - Some more const-correctness in the transfer code to make life easier in other places\nRushfan - Removed almost all usages of status\nRushfan - fsh_open was moved into WTextFile (WTextFile::OpenImpl).\nRushfan - last usages of fsh_XXXX is migrated to WTextFile\nRushfan - Changed thisuser to GetCurrentUser\nRushfan - Moved WLocalIO::pr_Wait to WSession::DisplaySysopWorkingIndicator\nRushfan - nl => WOutStream::NewLine, ansic => WOutStream::Color, \n          setc => WOutStream::SystemColor, BackSpace & BackLine &\n          DisplayLiteBar => WOutStream, reset_colors => WOutStream::ResetColors\n          goxy => WOutStream::GotoXY, bputs => WOutStream::Write\n          bprintf => WOutStream::WriteFormatted\nRushfan - Started working on WIniFile Class\nRushfan - ** IMPORTANT CHANGE ** In chat.ini, CH_PROMPT's allowable values\n          for true and false are now Y and N (like the rest of WWIV), and\n          not 1 and 0.  Please change this in CHAT.INI when you upgrade to\n          this version.  I am standardizing the INI files as much as possible\n          and making 1 set of INI code for WWIV and all utilities to share.\nRushfan - Renamed WBbsApp to WApplication\nRushfan - moved attach dir into WApplication\nRushfan - Finished WIniFile implementation\nRushfan - Updates WIniFile and WFile to take string parameters instead of\n          char* parameters.\nRushfan - Started converting functions over from char* parameters to string\nRushfan - renamed describe_town to describe_area_code_prefix\nRushfan - moved WLocalIO and WComm to WSession, now available as\n          WSession::localIO and WSession::remoteIO.\nRushfan - Updated several of the StringUtils methods to use better STL code\nRushfan - Rewrote read_automessage to use WTextFile and simplified logic\nRushfan - Started trying to make WUser stand alone w/o pulling in the entire bbs\nRushfan - Fixed logic error in read user where it wasn't returning a value WUser's data\nRushfan - Added WUser::SetUserWritesAllowed to disable writing the user record (this\n          is used instead of the global guest_user)\nRushfan - Added WSession::ReadCurrentUser() and WSession::WriteCurrentUser()\nRushfan - Renamed Input1 case constantes to INPUT_MODE_XXXX so they don't clash with windows.h\nRushfan - Moved the password validation logic into it's own function so it can\n          be fixed (the string conversion broke it) and also augmented\nRushfan - Moved global structure screentype from vardec.h (shouldn't have been there)\n          into WLocalIO.h (now vardec.h doesn't need windows.h to compile on Win32)\nRushfan - Changed WLocalIO save/restorescreen to not need a parameter and the screen \n          buffer is now internal to WLocalIO\nRushfan - Moved SOCKET and COMM Handles into WIOTelnet and WIOSerial\nRushfan - Moved Internal Telnet Listener to it's own class\nRushfan - Removed incl3.h and wshare.h (both not used)\nRushfan - added InternalTelnetServer.cpp/.h\nRushfan - removed unused linux function chsize\nRushfan - Removed some unused data types from wtypes.h, also made sure we are\n          consistent with what type we declare a variable as and use it as.\nRushfan - moved windows.h out of incl1.h and trying to get rid of it except for\n          in the platform/win32 subdirectory (if possible)\nRushfan - Added filenames.h into the incldue list for WUser\nRushfan - moved cid_name and cid_number into WComm\nRushfan - moved WComm::SetHandle and WComm::startup into the constructor and shutdown \n          into the destructor.  Also removed WSession::ShutdownComm (never used)\nRushfan - Added factory method to WComm to create the WComm instance, and renamed\n          WSession::StartupComm to CreateComm.\nRushfan - renamed write_automessage1 to write_automessage\nRushfan - changed repeat_char to always add a NL (since all callers did), added\n          inli variant that works with strings.\nRushfan - Update Copyright statements to 2007\nAtani   - Linux compilation fixes\nAtani   - Fixed typo in chains.cpp for format specifier (line 97, arg 3)\nRushfan - Fixed error in Input1 where the input field would be at least 80 chars\nRushfan - Fixed up couple of hard coded colors that should be using wwiv colors\n\n==============================================================================\n\nLABEL: WWIV-5_0_60\nDATE:  11/28/2005\n\nRushfan - Fixed issue with message base corruption\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_59\nDATE:  11/20/2005\n\nAtani   - sf-bug 1215436 - door32.sys contained extra \"l\" after baud rate\nRushfan - Started working on Mac OS X Support\nRushfan - Changed global app to GetApplication(), sess to GetSession().  Added\n          GetComm(), GetUserManager(), GetLocalIO(), and GetStatusManager() \n          to WBbsApp and made the previously public member variables private \n          and updated all access through the accessors\nRushfan - Update size test code to handle Mac OS X as well as Linux/Win32 and\n          MSDOS.\nRushfan - Updated Copyright statement in header files to 2005\nRushfan - removed unused files extrn.cpp and extrn1.cpp from CVS finally.\nRushfan - Updated code to compile under VS.NET 2005 (using VC++ Express)\nRushfan - Got rid of WWIV_Copy_File and moved it to WFile.  Also added WFile::MoveFile\n          which needs to be implemented on UNIX still.\nRushfan - WFile no longer includes wwiv.h (and should now work outside of WWIV)\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_58\nDATE:  11/30/2004\n\nRushfan - Fixed a typo/bug in the sending the initial telnet sequences, look\n          for echo being broken or linemode being enabled on some lesser\n          telnet clients\nRushfan - More conversion of sprintf to snprintf and replacing hard coded sizes\n          with sizeof for non-pointer strings.\nAtani   - Fixed linux build, added MAX_PATH to WFile.h (if not defined)\nRushfan - Fixed bug [ 1059251 ] user can't login -- Issue with the phone number\n          verification support.  This should be fixed now.\n\n==============================================================================\n\nLABEL: WWIV-5_0_57\nDATE:  10/22/2004\n\nRushfan - Moved shutdown information and variables from WSession to WBbsApp.\nRushfan - Changed skey to take an int vs. unsigned char.\nRushfan - More ongoing work on removing unneeded unsigned data type usages.\nRushfan - Disabled remote.exe and remotes.dat support by default.\nRushfan - Fixed display bug in voting booth.\nRushfan - got rid of number_userrecs for WUserManager::GetNumberOfUserRecords\nRushfan - split out code from user.cpp to SmallRecord.cpp and FindUser.cpp\nRushfan - Moved function prototypes from fcns.h to WStringUtils.h for the\n          string functions contained in that file.\nRushfan - Started making WUser and WUserManager self-contained so it can be\n          used outside of the main bbs code more easily.\n\n==============================================================================\n\nLABEL: WWIV-5_0_56 (Beta-3)\nDATE:  9/8/2004\n\nRushfan - Removed registration code from lilo\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_55\nDATE:  9/8/2004\n\nRushfan - Moved WFC initialization out of xinit and into wfc_init\nRushfan - Moved WFC variables out of WSession into wfc.cpp module.\nRushfan - Removed global use_forcescan as it's not used (it's an ini flag)\nRushfan - Got rid of INT32, made it all int.\nRushfan - Changed dir_dates from ULONG32 to UINT32 since that's what they are\nRushfan - Moved dir_dates and sub_dates into WSession class.\nRushfan - Implemented more accessors in WSession\nRushfan - Changed the length of all c-style strings with length 161 to 255\nRushfan - Moved PPP email information into WSession and made ppp_realname bool\nRushfan - Removed global variable in_fsed since we don't need it anymore.\nRushfan - Replaced lecho variable with calls to AllowLocalSysop\nRushfan - Removed unused global \"ppp_domain_usernum\"\nRushfan - Fixed chainedit/boardedit where unsigned chars were displaying\n          as characters and not as numbers after the streams conversion.\nRushfan - Removed extra nl in message header display\nRushfan - More streams work.  Fixed bug in WOutStream with a null parameter.\nAtani   - Cleaned up warnings under linux\nAtani   - Linux build fixes\nRushfan - Fixed message read going 1 line too far.\nRushfan - Removed trailing whitespace in all files.\nRushfan - Started to use stringstream vs. sprintf calls\nRushfan - replaced printf calls with streams to cout\nRushfan - removed EOL() as it did the same as clearline(), also renamed \n          clearline() to ClearEOL().  Renamed spin to SpinPuts, left to\n          MoveLeft, and backprint to BackPrint, bempty to bkbhit,\n          get1c to bgetchraw, comhit to bkbhitraw\nRushfan - Still working on making WSession use encapsulation.\nRushfan - Updated Copyrights and License Statements to reflect Apache License\n          \n==============================================================================\n\nLABEL: WWIV-5_0_54\nDATE:  01/19/2004\n\nRushfan - Merged system_operation_rec with WSession\nRushfan - Added Set/Has/Clear/Toggle+ConfigFlag to WBbsApp and use it \n          instead of (former sysinfo.flags)\nRushfan - Fixed MSVC6 build i.r.t STL usages.\nRushfan - cleaned up a couple of the /W4 warnings.\nRushfan - Found more places where I wasn't using control-code #defines - fixed\nRushfan - Created WSession.cpp and started moving code to it from  WSession.h\nRushfan - Created and Fixed a GPD caused by a memset call to WSession()\nRushfan - Started using iostreams instead of bputs/bprintf in a couple\n          of places. Not ready for a full-scale conversion yet, but\n          investigations are underway.\nRushfan - Fixed \"(x years old)\" display in newuser logon\nRushfan - Fixed Full Screen Editors\n\n==============================================================================\n\nLABEL: WWIV-5_0_53\nDATE:  01/12/2004\n\nRushfan - Fixed litebar call in list files.\nRushfan - Fixed display of chains (missing part of the pipe color code)\nRushfan - Introduced WUser class for user record.\nRushfan - Fixed fast logon for users other than user #1\nRushfan - nam and nam1 now takes userrec as a const parameter.\nRushfan - Introduced WUser and WUserManager classes.  sess->thisuser is now\n          a WUser object instead of a userrec structure.\nRushfan - Added WSession::ReadCurrentUser and WSession::WriteCurrentUser\nAtani   - Fixes for linx build\nRushfan - Added broadcast( s, ... ) and switched to it.\nRushfan - More fleshing out of WUser C++ class.\nRushfan - Making more parameters in the message base, file areas, and \n          conferences code const so it can use the const char* return values \n          from WUser member functions.\nRushfan - Fixed bug in message base code that could assert in a debug build\n          when the message being quoted had control characters\nRushfan - More constness fixes and variable name sanitization.\nRushfan - Finished WUser class and use it virtually everywhere.\nRushfan - Added input function that take string vs. char*\nRushfan - renamed input_pw1 to change_password\nRushfan - Added StringTrimBegin, StringTrimEnd, and StringTrim that works on\n          STL string classes to WStringUtils.\nRushfan - Converted most hard-coded color codes back into WWIV color codes\n          instead of hard color attributes (still uses pipe syntax though)\nRushfan - Added #defines to be used when calling inmsg and external_edit to \n          the list of other #defines at WConstants.h\n          \n==============================================================================\n\nLABEL: WWIV-5_0_52 (Beta-2)\nDATE:  01/03/2004\n\nRushfan - Use masked field editline (used in F1 user editor)\nRushfan - Changed the message scan prompt to be 1 line instead of 2.\n          Does anyone like it?  dislike it?\nRushfan - Added litebar calls to voting booth and yourinfo\nRushfan - In UEdit, if you are editing user #1, you can increase that SL/DSL\n          even if your SL/DSL is lower.\nRushfan - Telnet should now respond with a \"IAC WILL SUPPRESS GA\" after \n          receiving a \"IAC DO SUPPRESS GA\".\nRushfan - Now sends a IAC DON'T ECHO along with the IAC WILL ECHO at startup.\n\t\t  (these last 2 things makes putty happy)      \nRushfan - Wrapped WIOTelnet::purgeIn in a Mutex for good measure.\t\nRushfan - Split up existing files into more files; bgetch.cpp, bputch.cpp, \n          pause.cpp, interpret.cpp, stuffin.cpp, execexternal.cpp, and \n          printfile.cpp\nRushfan - Moved editline to WLocalIO::LocalEditLine and editlinestrlen to \n          WLocalIO::EditLineStringLength\nRushfan - Replaced itoa with sprintf calls.\nRushfan - Replaced ltoa and ultoa with sprintf calls.\nRushfan - Renamed WLocalIO::LocalXYPrintf to WLocalIO::LocalXYAPrintf and\n          created a new LocalXYPrintf, LocalPrintf and a new LocalXYPuts\nRushfan - Replaced many LocalGotoXY and LocalFastPuts combos with LocalXYPuts\n          LocalXYPrintf, or LocalXYAPrintf calls\nRushfan - Fixed Pending Net Display.\nRushfan - WFC Cleanups (display issues and misc code cleanup)\nRushfan - print_net_listing now takes a bool argument instead of an int.\nRushfan - Added EFLAG_NONE to use instead of a 0\nRushfan - Added #defines to pass to usedit ( UEDIT_NONE, UEDIT_FULLINFO, and \n          UEDIT_CLEARSCREEN ) to use instead of hard coded numbers.\nRushfan - Updated Copyright Statements to 2004.\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_51\nDATE:  12/18/2003\n\nRushfan - Got rid of utoa macros, replaced with ultoa\nRushfan - Fixed %% parameter in stuff_in, this has never worked. (it added\n          %s instead of % to the commandline)\nRushfan - Updated L&F of timebank.\nRushfan - renamed ok_local() to AllowLocalSysop()\nRushfan - renamed checkpw() to ValidateSysopPassword()\nRushfan - Changed play_sdf's abortable param to a bool & used the macro \n          versions of filenames that are passed to it.\nRushfan - moved more of the string functions into WStringUtils.cpp, they are:\n          justify_string, trimstr1, strstr_nocase, single_space, and stptok\nRushfan - Improved the look of the online user editor (F1 Sysop Command)\nRushfan - strip_space and trimstr1 did the same thing, strip_space is now \n          gone, replaced with trimstr1 (which needs a more descriptive name!)\nRushfan - Renamed trimstr1 > StringTrim, trimstr > StringTrimEnd,\n          justify_string > StringJustify, strstr_nocase > stristr (removed\n          old stristr), stripspace > StringRemoveWhitespace, \n          strrepl > StringReplace, strip > StringRemoveChar,\n          stripfn1 > stripfn_inplace\nRushfan - Added #defines for the various spawnopts\nRushfan - Fixed some keys (home, end, etc) that were not working in \n          get_kb_event and therefore not from Input1.\nRushfan - Consolidated get_kb_event1 into get_kb_event.\nRushfan - Fixed cursor staying invisible at the WFC screen when invoking \n          sysop commands (boardedit, chainedit, etc).          \nRushfan - Lowercased more filename parts          \nRushfan - constrain editor name in defaults to keep display nice\nRushfan - Fixed check_for_files_zip and check_for_files_lzh (wwiv wouldn't\n          recognize a valid ZIP header)\nRushfan - COMIO support was broken though the Synchronet FOSSIL driver, this\n          should be fixed again.\nRushfan - Fixed temp directories not getting cleaned up in remove_from_temp          \nRushfan - Added call to create_chain_file in extern_prog and removed it from\n          most other places where it was being called and not used for getting\n          the path to chain.txt.\nRushfan - Removed the directory changing in create_drop_file, it's not needed\n          anymore now that wwiv uses full pathnames for datadir and gfilesdir\n          (plus it was just lame)\nRushfan - When running a true \"chain\", use the normal internal IO for writing\n          text locally/remotely (heart codes aren't processed locally, but \n          they are remotely)\nRushfan - Moved archiver structions into vardec.h so we don't need to have the \n          pack #pragma around it.  Also, missed the .ARC structure, so that \n          bit didn't work before. Moved fedit_data into vardec.h too.  It \n          didn't work before either (again a padding issue)\nRushfan - In the message read prompt, '$' will move to the last message.\nRushfan - renamed InternalOutputString back to bputs, since we need it in\n          several places outside of com.cpp\nRushfan - moved get_quote from extrn.cpp to quote.cpp\nRushfan - removed global variable list_option, added an optional parameter\n          oo mmkey (bool bListOption)\nRushfan - Changed more filenames to lowercase.  If a file can't be found on \n          UNIX, try making the real file name lowercase.\nRushfan - Changed nam1 and nam to return char* vs. unsigned char*\nRushfan - removed wfcprt, added WLocalIO::LocalXYPrintf\nRushfan - //VER didn't show expired versions. it does now.\nRushfan - Added ClearScreen calls before the WFC commands that were missing it\n          and still needed one.\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_50 (Beta-1)\nDATE:  12/16/2003\n\nRushfan - Build50 was branched to branch WWIV-5_0_BETA_1_BRANCH.  This was\n          build 50 which was never released.\n\n\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_49\nDATE:  12/04/2003\n\nRushfan - merged in missing 4.30 code to disable pause while displaying the\n          logoff ansi/ascii file.\nRushfan - We now disable the FSED during newuser logon.          \n\n==============================================================================\n\nLABEL: WWIV-5_0_48\nDATE:  12/02/2003\n\nRushfan - removed parameter from wfc_update since 1 wasn't used.\nRushfan - Fixed check_ul_event (had logic broken) and changed it to return a \n\t\t  bool\nRushfan - Removed paths in include statements (finally got around to it)\nRushfan - Added defaulted parameter (bAutoMpl) to input, inputl, and input1\n          which will invoke mpl automatically to reduce clutter in the rest\n          of the place.\nRushfan - added new method - input_password( password, length )\nRushfan - Added some pauses around the zmodem send code to see if that helps.\nRushfan - More cleaning up #include statements to not include any path info\n\t\t  since we should just make the compiler do that for us ;-)\nRushfan - Changed side_menu_colors members from unsigned to int.\nRushfan - Removed an odd if statement in msgbase.c which was always true in\n          function OpenMessageArea.\nRushfan - email wasn't passing the force_title parameter to inmsg.\nRushfan - changed cache_start and last_msgnum from unsigned shorts to ints.\nRushfan - Cleaned up many of the /W4 warnings, now down to a dozen or so, \n          mostly in the ZModem code.\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_47\nDATE:  07/02/2003\n\nRushfan - Fixed extra space in login information before \"Available\" in the\n          sysop chat status.\nRushfan - Changed all static variables into instance variables in WIOSerial\n          and WIOTelnet since they really are not static by instance specific.\nRushfan - Added a new argument to printfile (bForcePause) to force the pause on\n          screen even for ANSI files.\nRushfan - Commented some more functions.                    \nRushfan - renamed write_automessage to do_automessage.\nRushfan - A couple of fixed which were causing ValScan and scanning a message\n          area when THREADED_SUBS was enabled to crash WWIV.         \nRushfan - Removed WWIV_ASSERT in get_post when the parameter is 0 since it is\n          actually legal in some places.\nRushfan - Fixed extra space being added after getting quotes (/Q) in inmsg\nRushfan - Fixed bug reportd by Gremlin about userlist not working right when\n          sorting by user number and you have gaping holes in the user numbers\n          of the users on your bbs.\nRushfan - Updated header of email to match new messagebase headers\nRushfan - Fixed File list with full info and the extended description has\n          a high-ascii character.\n          \n==============================================================================\n\nLABEL: WWIV-5_0_46\nDATE:  06/14/2003\n\nRushfan - Dropped cbuf_t (circbuf.cpp/h) in WIOTelnet in favor of the STL\n          queue class (since cbuf_t has more issues than it should)\nRushfan - Dropped cbuf_t in WIOSerial (again replacing it with queue)\nRushfan - Removed IncommingSize and PeekBuffer from WComm          \nRushfan - Fixed bug in WIOTelnet where incomming would return false when the\n          next character in the input buffer was a NULL.\nRushfan - Added INI_INIT_TF (works off of YesNoString, i,e, Y/N)\nRushfan - Changed InternalZmodem to use Y/N vs. 1/0.\nRushfan - Changed ExecLogSyncFoss and ExecUseWaitForInputIdle to use Y/N\nRushfan - Added commandline option -k (pacK message areas) to wwiv50.  This \n          will pack all message areas unless you specify the number of the\n          areas to pack on the commandline. i.e. \"wwiv50 -k 1 5 10\" would\n          pack areas 1, 5 and 10.\nRushfan - If you add \"NEW_SCAN_AT_LOGIN=Y\" to WWIV.INI, then when a user logs \n          in they will be asked to scan all message areas for new messages.\nRushfan - stryn2tf now recognizes YesNoString(true)[0], 1, '1', and 'T'\n          as valid responses for \"YES\"\nRushfan - InternalZmodem is now enabled by default.\nRushfan - The display while packing message bases is now a bit nicer looking.\n\n==============================================================================\n\nLABEL: WWIV-5_0_45\nDATE:  06/09/2003\n\nRushfan - Fixed GPF when changing menu sets. (reportd by Eli)\nRushfan - Got rid of the extra space between NN: and PW: after a failed login\nRushfan - Removed some more unused function prototypes from fcns.h\nRushfan - made ssm take variable arguments\nRushfan - Fixed a couple of typos and missing nl()'s\nRushfan - Removed E_C, it's always on now.\nRushfan - Changed the format of the message headers\nRushfan - Fixed user.log only having 1 user listed (reported by Frank)\nRushfan - Using C++ style casts more and more now.\nRushfan - Added missing \\r\\n's in confedit\nRushfan - Added IsEquals(char*,char*) and IsEqualsIgnoreCase(char*,char*)\n          to WStringUtils.\nRushfan - Fixed problem making ini flags not work.          \nRushfan - npr is now bprintf ({both}printf).  Some other name changes will\n          be [{local}|{remote}]puts.\nRushfan - outchr is now bputch.  inkey is now bgetch.  outcomch is now rputch.\n          restorel is now RestoreCurrentLine (to more closely match\n          WLocalIO::SaveCurrentLine -- changed in build 20 in 3/2000)\nRushfan - moved some functions from com.cpp to WStringUtils.cpp          \nRushfan - Fixed assertion in trimstr on a string of all spaces.\nFCReid  - Fixed build on Visual Studio 6.0\nRushfan - Fixed reversed logic in subedit when a filename is already in use\n          and wwiv asks if you want to use it anyway.\nRushfan - Fixed an INI file glitch where the following commands were off by 1\n          BEGINDAYNODENUMBER, INTERNALZMODEM, EXEC_LOGSYNCFOSS  \n          EXEC_USECWAITFORIDLE, EXEC_CHILDWAITTIME, EXEC_WAITFORIDLETIME\nRushfan - Added a new Zmodem implementation.  Internal Zmodem now works for\n          1 file at a time downloads (nothing else has been tested yet)          \nRushfan - Fixed WIOS_TRACE when TRACE_DEBUGSTRING is enabled.  It was writing\n          to the sysop log not to the debugger.\nRushfan - Fixed color of horizontal bar in LastCallers (it wasn't always #7)\nRushfan - Removed some unnecessary sleeps in the zmodem code which made it \n          go from ~1k/second locally to about ~500k/second locally.                    \nRushfan - found some serious synchonization issues in the telnet code, fixed \n          them, but it's new code.  let me know if there's any performance\n          issues with the socket code vs. the last release.\nRushfan - Fixed issue with the socket buffer, we were stopping at a NULL and\n          adding garbage into the input buffer (which was giving Zmodem\n          quite a bit of gas)\nRushfan - Fixed header truncation in new mail prompt.\n\n          \n==============================================================================\n\nLABEL: WWIV-5_0_44\nDATE:  05/20/2003\n\nRushfan - More simple code cleanup.\nRushfan - Upgraded to Visual Studio.NET 2003\n\nRushfan - Added new files (split up existing files).  The new files are \n          xinitini.h which has the INI defines and such from xinit.cpp\n\t\t  and input.cpp which now has input* and Input1.\nRushfan - More new style casting and other misc changes.\nRushfan - Added new WWIV.INI parameters for customizing the launching of \n          chains/doors under Win32. (Notational note [ X | Y ] means X or \n          Y, for example \"[ 1 | 0 ]\" means that the value can be 1 or 0.\n    New WWIV.INI Parameters\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\tEXEC_LOGSYNCFOSS = [ 1 | 0 ] - If non-zero then wwivsync.log will \n\t\t\t\t\t   be generated.  The default setting is 1 and this\n\t\t\t\t\t   is currently ignored.\n\tEXEC_USECWAITFORIDLE = [ 1 | 0 ] - Under WindowsNT/2K/XP when launching\n\t\t\t\t\t\tthe child process WWIV uses WaitForInputIdle to wait\n\t\t\t\t\t\tfor the child process to process all normal input \n\t\t\t\t\t\tbefore starting the Fossil handling code.  Setting\n\t\t\t\t\t\tthis to 0 will disable that (behaving like Win9x where\n\t\t\t\t\t\twe just wait for a bit (See EXEC_CHILDWAITTIME).  The\n\t\t\t\t\t\tdefault value of this is 1.\n\tEXEC_CHILDWAITTIME = #### (time to wait in milliseconds, this parameter is \n\t\t\t\t\t\tonly used on Win9X unless EXEC_USEWAITFORIDLE is\n\t\t\t\t\t\tset to 0.  The default value for this is 500 \n\t\t\t\t\t\t(1/2 second)\n\tEXEC_WAITFORIDLETIME = #### (time to wait in milliseconds, only used on \n\t\t\t\t\t\tWindows NT/2K/XP unless EXEC_USEWAITFORIDLE=0).  The\n\t\t\t\t\t\tdefault value for this is 2000 (2 seconds)\nRushfan - Added new file quote.cpp and moved auto_quote, grab_quotes, and           \n          the associated helper functions into this module.\nRushfan - added a pile of #defines for dealing with time to make the math easy\n          to understand (also make WWIV use them everywhere I could find) \n          The new #defines are:          \n\t\t\tHOURS_PER_DAY, HOURS_PER_DAY_FLOAT, MINUTES_PER_HOUR, \n\t\t\tMINUTES_PER_HOUR_FLOAT, SECONDS_PER_MINUTE, SECONDS_PER_MINUTE_FLOAT, \n\t\t\tSECONDS_PER_HOUR_FLOAT, SECONDS_PER_DAY_FLOAT\nRushfan - Replaced numerous hard coded ascii values with #defines (CU, CX, \n          ESC, TAB, RETURN, CP, ...)\nAtani   - Reacting to latest win32->linux changes, fixing some warnings.\nRushfan - removed function \"pl\", everyone should use npr now.\nRushfan - in printfile if the filesize is 0, return false (since it's not \n          really anything in there to display)\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_43\nDATE:  04/28/2003\n\n\nRushfan - Split out 2 new files from batch.cpp -- trytoul.cpp and normupld.cpp\nRushfan - Split out new files from listplus.cpp - lpfunc.cpp\nRushfan - save_config() is now app->SaveConfig()\nRushfan - Changed hungarian notation in menu code to conform with wwiv50\nRushfan - Found more pulldown menu stuff to remove.\nRushfan - Move conversions from sh_XXXXX calls to using the WFile class\nRushfan - Changed WriteBuf to take a WFile& vs. int (file handle)\nRushfan - Changed WFile::GetFileTime to open the file with WFile::modeReadOnly\n          when it auto-opens the file to get the file date/time.\nRushfan - Removed WWIV_GetFileTime\nRushfan - Modified send_b to take a WFile& vs. file handle\nRushfan - Added WFile *OpenEmailFile( bool bAllowWrite ) to replace open_email\nRushfan - Removed old version of FileAreaSetRecord as it all uses WFile now\nRushfan - Removed open_email(int) and delmail(int, int)\nRushfan - Removed sh_open25\nRushfan - Changed filename global.txt to global-<node number>.txt\nRushfan - Removed sh_open, sh_open1, sh_open_internal, sh_lseek, sh_read, \n          sh_write, sh_close\nRushfan - Changed open_sub to return a bool (succes/fail) vs. file handle.\nRushfan - Using std::min/max vs. our defines now.\nRushfan - Upped the size of all the filename char[]'s I could find to MAX_PATH\nAtani   - Fixed compilation issues on linux, fixed \"slowness\" on linux\n          caused by funky permissions being set during WFile::Open.\nRushfan - Fixed last login date always being today (reported by Taz), which \n          was broken in 5.0 build 14.\nRushfan - Added code to wtypes.h to make min/max part of the std namespace\n          (like it is SUPPOSED TO BE) under MSVC6\nRushfan - Added function \"VerifyStatusDates\" into sysopf.cpp which is executed\n          during the beginday event which ensures the dates are only 8 chars\n          long (since I seem to get corrupted dates on fresh installs often\n          enough and that causes big problems for me)\nRushfan - Make onek call onek1 to get rid of duplicate logic.\nRushfan - Some tweaks to allow the serial code to at least init the modem\n          built into my dell laptop.\nRushfan - added TRACE_DEBUGSTRING to WIN32/Wios.cpp\nRushfan - More cleaning up of warnings when at warning level 4\nRushfan - introducing c++ strings a little bit here and there.\nRushfan - Added new wwiv::WStringUtils namespace to add some extra \n          functionality when using c++ strings\nRushfan - Added WFile constructor which takes a C++ string\nRushfan - renamed forwardm to ForwardMessage and changed the ret type to bool\nRushfan - renamed isr to InsertSmallRecord and dsr to DeleteSmallRecord\nRushfan - Fixes for MSVC6 compatability from Frank (thx!)\nRushfan - Making sure done, ok, (bool variables) really are bool\nRushfan - Added 2 parameter version of static WFile::remove which takes\n          a directory name and a filename\nRushfan - made setconf return a bool vs. int, also made most of the functions\n          in confutil.cpp local functions.\nRushfan - made some of the conf code use int vs. usigned long (since it really\n          just needs a 32bit value)\n\n==============================================================================\n\nLABEL: WWIV-5_0_42\nDATE:  03/01/2003\n\nRushfan - Fixed problem with WFile and not getting the read permission\nRushfan - Also fixed a couple of GPF's with a fresh install\nRushfan - Fixed write_user opening the user list in read only mode\nRushfan - Fixed issues with status.dat not getting updated properly\nRushfan - Fixed WFC display issue where the # of new sysop msgs was always 0,\n          also changed color to red w/o +128 since Win2k/etc doesn't blink.\nRushfan - Changed ClearScreen to CLS to make defaults look better and fit\nRushfan - Removed ansiec from xfer.cpp and replaced with ansic calls\nRushfan - Changed the SETREC macro to the FileAreaSetRecord function which\n          is contained in xfer.cpp (vs. the macro which is defined in each \n\t\t  file that it is used)\nRushfan - Cleaned up display in events editor. Also fixed problem with blue\n          hilight bar in sub/diredit/etc only being 73 chars wide vs. 79\nRushfan - Merged the menu commands LoadText and LoadTextFile since they both\n          did the same thing.  Currently both menu command work, however go\n\t\t  ahead and update your menus to use LoadTextFile\nRushfan - Started replacing prt usages with npr calls (more consolidation of\n          the output code used in WWIV)\nRushfan - Finished removing all usages of prt\nRushfan - Changed most usages of outstr to npr\nRushfan - Changed almost all \"typedef struct {...} X;\" declarations to just \n          \"struct X {...}\" since the typedef is no longer needed for simplified\n\t\t  notation in C++. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang98/html/_pluslang_use_of_typedef_with_class_types.asp\n          for more information (if you are curious)  Now things aren't listed\n          as \"unnamed_X3948328945234\" in the class browsers in MSVC 6/7\nRushfan - changed num_lines to g_num_lines\nRushfan - Changed side_menu param \"redraw\" from int to bool\nRushfan - in listplus.cpp -- Much parameter bool'izing and code cleanup\nRushfan - started to cleanup defaults.cpp\nRushfan - Fixed File NewScan\nRushfan - Attempt to fix a GPF in show_chains when you abort the listing\nRushfan - Added fix in DateTime.cpp to make sure we don't get a 9 \n          digit date\nRushfan - Now removed and restores topscreen when using Input1 so the line\n          offsets match.\nRushfan - Now guard against going past the screen size in function goxy(x,y)\n==============================================================================\n\nLABEL: WWIV-5_0_41\nDATE:  01/10/2003\n\nRushfan - Added BEGINDAYNODENUMBER to wwiv.ini, it defaults to 1.  This must \n          be set to the node number which will run the beginday events.\nRushfan - Also, the -E commandline parameter won't allow the beginday event\n          to run multiple times in one day anymore. If you try, you will see\n          a nasty message in the sysop log.\nRushfan - Removed the '-W' commandline parameter since it doesn't seem usefull\n          and just makes wwiv crash.\nRushfan - WLocalIO::LocalCls will save and restore the default attribute to 7\nRushfan - When exiting WWIV the cursor will be restored and the screen won't\n          be yellow\nRushfan - Replaced cursor constants with static const int's off WLocalIO\nRushfan - Cleaned up header files a bit\nRushfan - Removed defines for OK_LEVEL, NOK_LEVEL in bbs.h and moved them into\n          WBbsApp as static constants.\nRushfan - Added WFile::modeTruncate\nRushfan - Removed exist(char* filename), replaced all usages with WFile::Exists\nRushfan - Added WFile::ExistsWildcard( char* wildcard ), and removed exists\n          (replaced with WFile method)\nRushfan - Added Assertions to WFile::Exists looking for wildcards.\nRushfan - Many more conversions to use WFile for all file I/O\nRushfan - Code cleanup in gfiles and other places\nRushfan - Changed wwiv_version to not include \"WWIV\" since we all know this\n          is WWIV (plus it saves us room on the WFC and other places)\nRushfan - Added exit code to sysoplog and screen when WWIV is exiting.\nRushfan - Put debuglevel into sysinfo structure as nGlobalDebugLevel\nRushfan - Misc cleanup in Platform sections of the code and in the header files.\nRushfan - Changed MSDOS typedef of \"bool\" to unsigned char to match what MSVC\n          actually uses for it.\nRushfan - Reformatted code in netsup.cpp to make it easier to read\nRushfan - Removed usages of \"BOOL\" outside of the win32 platform code.\nRushfan - Replaces GOTO_XY with the real function \"goxy\"\nRushfan - Started some code cleanup/reformatting in listplus.cpp, also \n          removed TOBOOL and the BOOL variables there (replaced with \"bool\")\nAtani   - Fixed many compilation issues on linux with gcc 3.2\nRushfan - Globally replaces unlink calls with WFile::Remove\nRushfan - Added WFile::SetFilePermissions( int nPermissions ) and changed all\n          usages of _chmod to it. Also removed the UNIX #define for _chmod.\nRushfan - Replaced all calls to rename with WFile::Rename\nRushfan - Removed old version of extract_mod and made the changes in WWIV to\n          use the new one which was added in 4.31build2 (somehow this got\n          lost in the 4.31b2 merge many moons ago)\nRushfan - Split up some files into smaller logical units.  New source files\n          are: confutil.cpp, dirlist.cpp, extract.cpp, and sublist.cpp\nRushfan - Added \"time_t WFile::GetFileTime\"\nRushfan - More converting to WFile from sh_XXXX calls\nRushfan - Replaced topdata numbers (0-2) with WLocalIO::topdataNone,\n          WLocalIO::topdataSystem, and WLocalIO::topdataUser constants.\nRushfan - Fixed problem where tleft would write one too many topscreen lines\nRushfan - The title of the console now displays the username who is online.\nRushfan - Replaced the \"PRINTER\" option in wwiv.ini with \"TITLEBAR\", if this\n          is 'Y' then the username will be displayed in the console windows\n          titlebar (on Win32 only)\nRushfan - Cleaned up this readme so it fits in 80 columns.          \nRushfan - GuestCheck now returns bool (true = ok, false = not ok)\nRushfan - Merged some functions from menusupp.cpp with the real ones if all \n          the stub in menusupp did was to call the real one.\nRushfan - Added hop.cpp, valscan.cpp, inmsg.cpp, and msgscan.cpp\nAtani   - Fixed new platform/linux/WFile.cpp changes for GetFileTime method\nAtani   - Cleanup/reorder building of objects\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_40\nDATE:  01/02/2003\n\nRushfan - Created admin dir with some of the .MSG, ANS, .MNU, etc..., files \n          that are part of the stock wwiv50 install.\nRushfan - removed unused platform/$PLATFORM/datetime.cpp\nRushfan - Updates to the MSVC6 workspace + fixes in exec.cpp for MSVC6\nRushfan - Made most constants in version.cpp const.\nRushfan - Added const long lWWIVVersionNumbe to version.cpp\nRushfan - Updated Copyright Statement to include 2003\nRushfan - Added control-U for who's online hotkey.  Also changed \n          HandleControlKey to use the Control code macros vs. numbers\nRushfan - Fixed ivotes from not showing the 1st question at the WFC          \nRushfan - Fixed laston edge case where the header didn't match the data when\n          EXTENDED_USERINFO = N but SHOW_CITY_ST = Y.\nRushfan - Mods in exec.cpp to combine the 2 log files into one.\n\n==============================================================================\n\nLABEL: WWIV-5_0_39\nDATE:  12/15/2002\n\nAdded \"Intercept DOS Interrupts\" back to chainedit and enabled COMIO in the\nwwiv.ini SPAWNOPT's again.  We're using SyncFOSS for Dos interrupts (just like\nwe do for FOSSIL support) -- Thanks Rob from Synchronet!!! \nOne thing to note: WWIVEDIT doesn't do local ANSI support, so it looks bad \nlocally.\n\nNow we zero the ansiptr when makeansi is called with an invalid ansi sequence\nso that the ansistr can't be overrun causing memory corruption.  We also \ncheck the ansiptr on bputch to ensure no overruns are going to occur (as is\nthe case when you have a text file with an escape char (27) and then a lot\nof garbage after it (or a corrupt mail packet as in my case).  Anyway, be on \nthe lookout for local ANSI interpretation not working as well after this \nchange, it seems to work fine on my machine in all the tests I've tried.\n\n=======\nAtani - Cleanup of WZmodem, WProtocol to allow them to compile on linux.\nAlso removed more hard-coded names to filenames.h (lowercased as well)\n\nRushfan - Changed Win9x loop to not check exit code till 500 loops after no\ndata. This should improve the performance of doors under Win9x slightly.\n\nRemoved the function huge_xfer since it's really not needed in 32-bits\nRemoved W_Proper function (not used)\n\nRushfan - Fixed but in WFile asserting on Open.\nRushfan - 1st real use of WFile class in xinit.cpp\nRushfan - Added new spawnopt flag in WWIV.INI (NETWORK is the key name) so\n          that Eli can add \"FOSSIL\" to that ;-)\n          \nRushfan - Made WFile::IsOpen public\n          Added WFile::GetFullPathName\n          \nRushfan - Rewrote stripcolors to be about 1/3 of it's original size (and it\n          even works right now)         \n\nAtani - various cleanups and reactions to WFile changes.\n\nRushfan - Replaces hard coded numbers used to identify internal protocols \n          with #defines\n\n          Added WProtocol/WZmodem to the list of files built.\n          \n          WFile::GetLength will now open the file if its not already open.\n          \nFrank   - Fix in chains.cpp when CHAINS_REG is not set.\n\nRushfan - try to fix CR/LF bug in input1.\n        - Misc cleanup in com.cpp        \n\n==============================================================================\n\nLABEL: WWIV-5_0_38\nDATE:  11/02/2002\n\nwe now unalign filenames in the transfer area before checking their existance\nso that //UPLOAD works on filenames with the base < 8 characters.\n\nmade hack in listplus.cpp to unalign every name before checking if it exists\n( needs to be reworked with the rest of the xfer code... <sigh> )\n\nadded sysoplogf( bool indent, char*, ... ) and sysoplogf( char*, ... ) which\nare printf style versions of the sysoplog function so that there are\nfewer places in the source where temp variables are made just for a sprintf\nand then a sysoplog call.\n\nchanged extern_prot and maybe_upload to use a bool for a boolean vs. an int.\n\ncode cleanup in utility.cpp\n\ntweaked the inputting directory path in diredit to be nicer\n\nChanges from Atani to make it build under GCC 3.2 on Linux.\n\nreplaced cd_to and get_dir with the WWIV functions\n\nFixed nrecno which was starting at record 2 instead of 1 (bugger!)\n\nFixed not stripping spaces before a move file operation.\n\nremoved unused i1 variable in uploadall and also removed unneeded nl(2) call\nfrom there, also changed sig of upload to return a bool vs. int, and false \nmeans that it was aborted (which actually works now)\n\nChanged the who's online list to be a list, also removed the WFC hack there\nand made it a 3rd parameter to the function\n\nAtani - Various fixes to warnings on compiling under GCC 3.2 on Linux.\nAtani - initlite updates to allow further config.dat settings, #1 SL/DSL twiddle.\n\nRushfan - Tweaks to the SyncFoss support\n\nAtani - Moved more hard-coded filenames to filenames.h\nAtani - Added platform/linux/WFile.cpp\nAtani - Added nodemgr for linux, Makefile was modifed to have a \"PLATFORM_TARGETS\"\noption which is for targets that should only run on certain platforms.\n\nRushfan - Fixed voting booth.\n\nRushfan - More tweaks to the SyncFOSS support\n\n==============================================================================\n\nLABEL: WWIV-5_0_37\nDATE:  09/29/2002\n\nAdded new parameter to read_user (bForceRead) so that you don't have to jump\nthough hoops setting the WFCStatus and stuff.\n\nRemoved a pile of code not used anymore in extrn1.cpp (some of it wouldn't \neven work if it were used such as the strtok nonsense\n\nremoved in_extern variable.\n\nChanged last parameter of write_qscn and read_qscn from int to bool.\n\nFixed \"random_screen\" in lilo since it accidentally got .0 replaced with \\0030\n\nFixed the sublist from not displaying the horizontal high-bit ascii bars\n\nchanged most \\003's to |# to use the simpler form\n\nchanged Input1 to return an int vs. unsigned char (noone uses the retval \nanyway, and the cast there is just not needed)\n\nFixed //CHAT from GPF'ing. (it actually toggles the scroll lock on Win32 too)\n\nFixed /C from GPF'ing (no promises it works yet, but it does on my machine)\n\nFixed possible GPF in beginday since it's possible for it to execute an \nevent if beginday_c[1] is not NULL, which is true in debug builds, it's\nsome weird number.\n\nCode cleanup and reformatting in chat.cpp and ini.cpp, getting ready for C++\noverhaul of the ini code.\n\nAdded default parameters to param 2 and 3 from ini_get\n\nChanged %%TODO: comments to TODO so MSVC.NET sees them right.\n\nCode Cleanup in syschat.cpp\n\nChanged 3rd parameter of inli from \"int\" to \"bool\"\n\nCode cleanup in defaults.cpp and mulinst.cpp\n\nStarted code cleanup in transfer area code\n\nmade recno(s) just call nrecno(s, 1)\n\nremoved nete, added app->GetNetworkExtension()\n\nrenamed dlfn to g_szDownloadFileName, and edlfn to g_szExtDescrFileName\n\nstarted cleanup in sr.cpp and srrcv.cpp\n\nchanged osan, plan, pla, pla1, printtitle, printinfo, nscandir, print_extended,\nread_message, and read_message1 to use bool's for abort and next instead of\nints.\n\nchanged had (HangupAfterDownload) from int to bool in batch.cpp globally\n\ncode cleanup in attach.cpp and automsg.cpp\n\nremoved global force_title, added new optional parameter to inmsg and email.\n\nrefactored bbslist.cpp into smaller chunks.\n\nstarted code cleanup in uedit.cpp\n\nmoved statusfile in status.cpp into class\n\nstarted refactorign in newuser.cpp\n\nremoved ClearScreen function, and renamed CLS to ClearScreen\n\ncodecleanup in menu.cpp\n\nUpdated wwiv50 info in readme.txt, also added URL for Mingw\n\nremoved numerous calls to ansic... replaced with pipe codes.\n\nreplaced usages of strcmpi with stricmp ( so we only had 1 fn doing this )\n\ndefaulted parameter in \"nscan\" to 0\n\nchanged osan and plan to use buffered version of bputch.\n\nmodified read_message1 to put more data in each packet (like 1 line vs 1 word)\n\nNow use CreateProcess to execute a command vs. spawnvpe\n\nMoved GetLastErrorText() into WComm from Wios (since I needed it in Wiot)\n\nChanged thread signaling to use Events instead of being lame and using a bool.\n\nrenamed ansir_no_300 to ansir_emulate_fossil since 300 baud is so not an\nissue anymore.\n\nMoved function ExecExternalProgram into an platform package to get rid of most of\nthe platform defines in extrn1.cpp\n\nAdded new flag in ChainEdit (Emulate FOSSIL), enable this, and if you have\nthe DOSXTRN.EXE, SBBSEXEC.DLL, and SBBSEXEC.VXD in your wwiv home directory,\nthen DOS doors will work, just make sure your comport number is set to 1.\n(yes, Eli, this works on Win9x and WinNT/2k/XP, at least on my Win98 machine\nit seems to work as well as Win98 ever does)\n\nFOSSIL can now be specified in WWIV.INI as a valid flag for spawn options\n\nAdded new parameter to write in WComm to spefify NoTranslation (defaults to \nfalse) when broadcasting IAC chars over telnet.\n\nIn WIOTelnet::write, it now excapes IAC chars so that FDSZ will work with the\nemulated fossil. (Just add FOSSIL for SPAWNOPT[PROT_SINGLE] and \nSPAWNOPT[PROT_BATCH].\n\nStarted stuffing the envionment entries we need into the processes environ\nsince passing xenviron wasn't working with the emulated fossil.  Maybe\nxenviron should just go away.  Doing this, downloads now work as expected \nusign fdsz.\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_36\nDATE:  09/08/2002\n\nCHANGES:\n\nMoved non-class functions in wiot.cpp into the class as static member \nfunctions along with moving variables into class as statics as well.\n\nFixed bug with ctypes looping.\n\nFixed bug with displaying subs when you had exactly 17 of them.\n\nAdded quasi-buffered writing to the IO code, it should be a tad bit\nfaster, especially for telnet connections.\n\nFixed problem with XXX's appearing in newuser password prompt on non-ansi \nconnections\n\nfixed problem with some telnet clients hanging after the 1st CR/LF pair\nwas entered.\n\nSynced the version of the telnet server with the bbs's version number\n\nMoved the global variable instance into the WBbsApp class\n\nMoved init() into the WBbsApp class\n\nremoved two_color global variable, made it a defaulted parameter to inli\n\nmoved the global variabl elastcon into the WSession class\n\nAdded function const char* YesNoString(bool) to return the Yes or No String\n\nmade sure all malloc/free went through bbsmalloc/BbsFreeMemory to facilitate dropping\nin a debugging malloc\n\nmade a couple of functions return const char* vs char* where possible.\n\nReplaced nln function with overloaded version of nl which can optionally\ntake an argument\n\nCode cleanup in WLocalIO class.  \n\nmoved initport into modem.cpp and renamed it to InitializeComPort\n\nreplaced set_baud with the call to app->comm->setup\n\nremoved setfgc and setgbc, inlined the methods into execute_ansi\n\nAdded new pipe codes:\n~~~~~~~~~~~~~~~~~~~~~\n|#<wwiv color code 0-9> as an alternative to the \"heart\" codes\n\n|@<macro character> as an alternative to ^O^O<macro char>\n\nJust FYI: Existing pipe codes are |B<background char>, and |<2 digit code>\nfor foreground colors.\n\n\n==============================================================================\n\nLABEL: WWIV-5_0_35\nDATE:  08/18/2002\n\nCHANGES:\n\nAdded [R]estore default colors as an option in Defaults under the color\nconfiguration.\n\nChanged defaults to be 2 columns instead of one, also changed the colors\nof it so it looks nicer and added a header line.\n\nChanged colors used in Your Info, also added a header\n\nFixed problem where print_local_file wasnt' abortable even when it was told\nthat it should be.\n\nCosmetic improvements in the voting booth code.\n\nChanged the return type of more functions from int to bool when they were\nreally returning a boolean type value.\n\nThe included telnet server will now minimize to a system tray icon.\n\nRefactored the getuser function in lilo.cpp -- It now has numerous helper\nfunctions which do most of the work, and getuser is just left to control\nthe flow.  This makes the code ALOT easier to maintain and spot problems.\n\nStarted refactoring the rest of the code in lilo.cpp since before it was only\na couple of really long nasty looking functions.\n\nRemoved function \"pln\" since npr should really be used instead.\n\nMerged alot of code from multiple outstr calls into 1 call to npr\n\nMerged the two places which calculate how many lines a message can be into\none function \"void GetMaxMessageLinesAllowed()\"\n\nAdded parameter \"%E\" to stuff_in which can be used in doors as the path to the\ndoor32.sys file.\n\nSome work on the WIOTelnet class.  The read thread is now started/stopped \nwhereas before it was not.  There was a problem with it running during a\nDOOR32.SYS door.  Also, close doesn't close the socket when bIsTemporary\nis true (new parameter WComm::close takes).  In short, now PimpWars and\nother door32.sys doors should work under the native telnet handling.\n\nFixed the problem where WWIV would not handle an IAC telnet command and\ntreat the command as text to process.... We still don't handle the command\nproperly, but at least we know it is a command. (hey, it's a start)\n\nNow lists the replacable parameters when editing the command in ChainEdit. \nAlso, we use the Input1 routines so you don't have to always retype \neverything.\n\n==============================================================================\n\nLABEL: WWIV-5_0_34\nDATE:  08/04/2002\n\nCHANGES:\nTons since the last update, check CVS sources for full list. (I know,\nI should be better about writing these down... but I get sidetracked \neasily...)\n\nBetter OS detection (again).  Detects XP properly now.\nBuilding with Microsoft Visual C++.NET now, so this has allowed me to find\nnumerous stack corruptions and fix them.\n\nFound issue where the WFC status was not set to zero when a caller was\npassed in from the telnet server, therefore the load/save user code\nwas trashing the sysop's user record (yuck)\n\nSource code cleanup particularly in the message base areas.\n\nChanged several functions to use bool vs. int/BOOL for return codes.\n\nMore using of bool internally for control flags, instead of using\nint values ( as booleans )\n\nRemoved a few unused global variables ( I wish they would all get removed! ),\nalso added parameters to functions to get rid of globals.\n\n==============================================================================\n\nLABEL: WWIV-5_0_33\nDATE:  06/01/2002\n\nCHANGES:\nTons since the last update, check CVS sources for full list.\n\nImproved OS detection\n/A, /H, /? Added to internal message editor\nmany tweaks to prompts\nScreen size set on launch, and reset on exit.\nblah blah blah\n\n\nLABEL:  WWIV-5_0_25\nDATE:   04/21/2000\n\nCHANGES:\n\n* Many changes for Linux.  It now compiles on Linux with GCC\n\n* New FindFirst/FindNext class\n\nChanged all instances of findfirst()/findnext() to use WFindFile class\nChanged all instances of WIN32 specific _findfirst()/_findnext() to use \nWFindFile class removed functions findfirst/findnext\n\nWFileFile usage:\n~~~~~~~~~~~~~~~~\nWFindFile fnd;\nBOOL bFound = fnd.open(<filespec>, 0)\nwhile (bFound)\n{\n\tchar *name = fnd.GetFileName();\n\tlong size = fnd.GetFileSize();\n\tBOOL isFile = fnd.IsFile()\n\tBOOL isDir = fnd.IsDirectory();\n\tbFound = fnd.next();\n}\n\nOptionally you can call fnd.close() to free resources allocated by the object,\nhowever the resources are also freed in the destructor for the class.  (when \nit goes out of scope if it's on the stack, or when delete is called if it was\ncreated with new)\n\n\n* Moved Wios, Wiot, dosemu to platform/WIN32 since they are not generic source.\n\n* ADD int WLocalIO::LocalGetChar() - same as getch() or getchar()\n\n* Merged all the different functions to copy a file\n\n\t1) Changed copy_file(x, y) to copyfile(x, y, FALSE)\n\t2) Removed copyfile2\n\t3) Changed all calls to copyfile2 to use copyfile\n\t4) Modified copyfile to invoke WWIV_CopyFile to do the actual copying\n\n* Started working on file path issues for Linux compatability.\n\n\t1) define WWIV_FILE_SEPERATOR_CHAR and WWIV_FILE_SEPERATOR_STRING as \n\t   the proper file seperator for the platforms\n\n\t2) changed \\\\ to WWIV_FILE_SEPERATOR_CHAR\n\n\t3) Made WWIV_ChangeDirTo, and WWIV_GetDir just simply call into platform \n\t   routines to perform these functions.\n\n* Other general code cleanup for Linux and WIN32\n\t- Started removing those little annoying warnings because \n  \t  the variable and the formatting placeholder didn't match.\n\t- Moved some functions out of wfc.cpp because they really\n  \t  shouldn't be in there.\n\t- Changed a putenv() to a setenv() because putenv() doesn't \n  \t  work sometimes.\n\t- Changed setftime to char * instead of int because it works \n  \t  on Linux that way.\n\t- Moved function show_files from utility to platform/$PLATFORM/utility2.cpp\n\n\n* Moved more code into the WLocalIO class\n\n\t1) Changed WWIV_MakeLocalWindow(...) to WLocalIO::MakeLocalWindow(...)\n\t2) Changed _setcursortype(UINT) to WLocalIO::SetCursor(UINT)\n\n\n\n\n==============================================================================\n\nLABEL:  WWIV-5_0_24 \nDATE:   04/04/2000\n\nCHANGES:\n\n* Makefile is now the Linux makefile.  makefile-gcc.w32 is the Win32 GCC \n  makefile\n\n* More of the WWIV code compiles on Linux now\n\n* platform/incl1.h and platform/incl2.h have been moved from wwiv.h\n\n* all Linux files are now lower or proper case (not all upper case)\n\n* Many makefile changes for Linux\n\n* More code is making it's way into the platform directories\n\n\n\n==============================================================================\n\nLABEL:  WWIV_5.0_23 (Includes changes in 21 and 22)\nDATE:   03/19/2000\n\nCHANGES:\n\n* Changed WComm::setup()'s return type to BOOL\n\n* Added hCommHandle to system_operation_rec\n\n* Removed function call to ReadIniInfo from the Menu Commands\n\n* Changed initport() to return TRUE on success (not 0)\n\n* Got rough version of Serial IO working (Win95/Win98)\n\n* Made WWIV not open and close the comport on check_comport\n\n* Got rough version of Serial IO working (WinNT/Win2000)\n\n* Implemented function WIOSerial::carrer() finally\n\n* Removed functions from WComm classes [ set(), brk(), status() ] - unused\n\n* Removed fossil_set(), fossil_brk(), fossil_status() - unused\n\n* Moved function wfcprt() to sysopf.cpp  (with the rest of the WFC stuff)\n\n* Fixed Serial input thread not exiting under WinNT/Win2000\n\n* Fixed display of chains list.\n\n* put #ifdef _WIN32 code around telnet server code in bbs.cpp\n\n* Modified the header files to compile under GCC/EMX v0.9d on OS/2.\n\n\n\n\n==============================================================================\n\nLABEL:  WWIV_5.0_20\nDATE:   03/12/2000\n\nCHANGES:\n\n* Moved makewindow into platform/$PLATFORM & renamed it WWIV_MakeLocalWindow\n\n* Moved code to copy a file out of a function in attach.cpp into a new\n\tfile platform/$PLATFORM/filesupp.cpp as WWIV_CopyFile(char*, char*)\n\t(There are still 2 other functions that copy a file that need\n\tto be converted into calling this one)\n\n* Moved most (hopefully all) of the Local IO code into a C++ class\n\tWLocalIO.  The header file is platform/WLocalIO.h, and the source\n\tfile is platform/$PLATFORM/WLocalIO.h.  Currently only a WIN32\n\tand partial OS2 implementation exist.  The Linux implementation\n\tneeds to be written.\n\n* Removed \"Control-O\" processing in skey, since it was only falling through\n\tto the \"Control-T\" handler.\n\n* Changed savel() into WLocalIO::SaveCurrentLine()\n\n* Updated Borland C++ Builder 5.0 Project and Borland C++ 5.5/Builder \n\tmakefile to include the new files added.\n\n\n\n==============================================================================\n\nLABEL:  WWIV_5.0_19\nDATE:   03/10/2000\n\nCHANGES:\n\n* Moved OS testing / #define verification code into platform/testos.h\n\n* Moved the platform code from wwiv.h into platform/incl1.h and platform/incl2.h\n\tplatform/incl1.h - This is for platform code to be included before the\n\tcommon set of standard C runtime libraries.\n\tplatform/incl2.h - This is for platform code to be included before \n\tWWIV specific header files\n\n* Created new file - platform/platformfcns.h \n\tIf you add a new routine into the platform code area, please be sure\n\tthat you add the prototype into platform/platformfcns.h NOT fcns.h.  Also\n\tnotate the build note so that the other platform groups can make\n\ttheir own platform version of that function.\n\n\n\n\n\n==============================================================================\n\nLABEL:  WWIV_5.0_18\nDATE:   03/06/2000\n\nCHANGES:\n* New files added (split up larger files into smaller ones)\n    asv.cpp\n    attach.cpp\n    automsg.cpp\n    bbslist.cpp\n    chains.cpp\n    colors.cpp\n    datetime.cpp\n    dupphone.cpp\n    inetmsg.cpp\n    memory.cpp\n    shortmsg.cpp\n    status.cpp\n    sysoplog.cpp\n    user.cpp\n    vote.cpp\n    wqscn.cpp\n\n\n* Renamed clrscrb() to LocalCls()\n\n* Fixed F1 (UserEdit) from not looking right if the TopScreen is on\n\n* Sorted FCNS.H to list the files in alphabetical order\n\n* Removed function gotoxy() (it was a duplicate of movecsr)\n\n* Renamed movecsr() to LocalGotoXY()\n\n* Renamed kbhitb() to LocalKeyPressed()\n\n* Updated Borland C++ Builder Project file with new files\n\n* Removed MAKEFILE.BCC - Now you should use WWIV50b.mak (b = Borland)\n    To change the output path, edit the file and look for \"PROJECT\"\n    and change the location of the EXE that will be generated\n\n* Removed build.bat - Wasn't used\n\n* The makefile for GCC 2.95.2 - Mingw32 is in the root directory, and is\n    called makefile-win32.gcc.  It is no longer in the platform/WIN32 directory\n    (the whole make file thing needs to be reorganized quite a bit)\n\n\n\n\n==============================================================================\n\n        \nWWIV 5.0 Build 16\n\nNOTE: Build 15 was never distributed as the changes weren't significant\n\n\nMajor changes since Build 14\n============================\n\nRemoved pull down menu code (This was all of build 15)\n\nFixed warning in Release Build related to #pragma component(Browser, on)\n\nFixed remaining warnings under MSVC 6.0 (BC++ Builder 5.0 still reports a few\nwarnings, and most of them are flat-wrong)\n\nFixed auto network callouts from not happening while running WWIV50 -m\n\nrenamed out1chx -> LocalPutchRaw\nrenamed out1ch  -> LocalPutch\nrenamed lf -> LocalLf\nrenamed bs -> LocalBs\nrenamed cr -> LocalCr\nrenamed outfast -> LocalFastPuts\nrenamed outs -> LocalPuts\n\nChanged most code that called outs to use the fast version \n(minor speed increase)\n\nChanged function makewindow() to use the fast outs routine under __OS2__\n\nWrote WIN32 optimized version of makewindow() that write to a buffer then \nwrites the entire buffer to screen with 1 call (twice as fast under NT/2000, \n10 times faster under 95/98)\n\nModifed the wfc_screen() function to only load WFC.DAT one time from disk, \nand cache it from there on out.  (The was causing HD access every time the WFC\nscreen had to redraw itself)  And since we have the memory (whereas DOS apps \ndon't) , it's better to do this.\n\n\n\n==============================================================================\n\n\nWWIV 5.0 Build 14\n\nMajor changes since Build 13a\n==============================\n\n\nChanged \"thisuser\" to \"sess->thisuser\" (moved to WSession class)\nRemoved code for writing STAT.WWV and RESTORE.WWV\nRemoved extern_prog flag \"EFLAG_SHRINK\" and \"EFLAG_FILES\"\nRemoved defines for sysconfig_shrink_term and ansir_shrink\nRemoved global variables\n\txdate (moved to only function using it)\n\tcur_lang_idx (set but never used)\n\tcursor_move\n\tdaysmin\n\tdaysmax\n\tendday (always = to 0, even in 4.30)\n\tpend_num (always = to 0, even in 4.30)\n\ttempio\n\tcommport (used only in fossil.cpp)\n\tcurloc\n\tver_no2 (used for WWIV_FP environment which isn't with us anymore)\n\t\nMoved ooneuser & event_only to bbs.cpp\nMoved inst_num to sysopf.cpp\nMoved screenlen to only function in comio.cpp that used it\nMoved xtime to function \"holdphone\"\nMoved sp to uedit.cpp as file level static\n\nRemoved GetHostID() in bbs.cpp.  Now the internal telnet listener binds to any\nlocal address (otherwise, it wouldn't work right on non-networked machines)\n\nFixed the topscreen from scrolling away\nFixed topscreen display (now shows proper flags (comm disabled, etc.))\nmoved default_ctyles to bbsutl2.cpp\nmade translate_letters, valid_letters, and invalid_chars const.\nmoved valid_letters to com.cpp\nremoved unused function SetNet_Name()\n\noptimized WFC drawing code to write to a buffer then blit to to the screen \n(now it's about 5-10 times faster at drawing the WFC)\n\nremoved unused global variable \"abortext\"\nmoved variable \"search_pattern\" to uedit.cpp as file level static\nRemoved variable \"force_newuser\".. It was used but never set (even in 4.30)\nRemoved unused structure \"resultrec\"\nFixed problem with xenviron[] not being zeroed to NULL before use.\nDisabled part of the EFLAG_NETPROG processing in extern_prog since it was \nhosing any attempts at running the network software\n\nAdded \"BOOL bUsingPppProject = TRUE\" to bbs.cpp.  If this is set, you can do \na wwivnet callout even if ok_modem_stuf == FALSE. \n\nadded back in a #pragma (pack, 1) to net.h so WWIVnet packets are the correct \nsize again\n\nfixed remaining structures in net.h to be the right size under WIN32\nFixed network pending list under WIN32\nFixed arrow keys not working in function ansicallout() under WIN32\n\n(Now you can use the PPP project to do callouts from WWIV 5.0)\n\n\n\n\n\n==============================================================================\n\n\nWWIV 5.0 Build 13a Source.\n\n\nMajor changes since Build 12\n============================\n\n1)  If you do not specify an instance number, 1 is assumed instead of 0\n2)  List of command line parameters is now sorted\n3)  SystemInfo() now calls WWIVVersion() for version information \n    (removed redundant code)\n4)  At logon time, the real OS detection code is used, (vs, #ifdef's)\n5)  At logon time, \"Multitasker\" is now just \"OS\"\n6)  Removed some older code guarded with #ifdef OLD and #ifdef __NEVER__\n7)  It now builds with GCC/Mingw32 again\n8)  It now builds and runs with Borland C++ 5.5 Free Command Line Tools. \n    (see makefile.bcc)\n9)  Changed WApplication to WBbsApp (Main Application) \n10) Started adding C++ objects\n\tWSession\t- Current user session information\n\tWComm\t\t- Base class for serial/socket communications\n\tWIos\t\t- Win32 Serial IO (not implemented yet)\n\tWIot\t\t- Win32 Telnet/Socket IO\n\n\tTo access a low-level comm routine, instead of \"fossil_write()\", you \n\tshould call app->comm->write().\n\n11) Fixed ListPlus from not working (structures in listplus.h were wrong size)\n12) more source code reformatting/cleanup.\n\n\n\n\n\n\n==============================================================================\n\n\n\nWWIV 5.0 Build 12 \n\n\nMajor changes include:\n======================\n1) native Telnet support.  (however it won't build under GCC anymore since \nthey don't include Winsock2 headers, etc...).. Right now you need MSVC to \nbuild it.  (I'll get it working under Borland's Free C++ 5.5 compiler soon)\n\n2) Now includes it's own quasi-function telnet server (run WWIV50 -TELSRV)...\nAfter one connection, it exits to DOS.  (But it works)\n\n3) It now can run under EleBBS's telsrv.exe (Their telnet server process)...\nJust rename this to elebbs.exe, and copy over ELCONFIG.EXE and TELSRV.EXE \nfrom an EleBBS distribution.  Then modify it in ELCONFIG to start with Node #1.\n\n4) You no longer have to set WWIV_INSTANCE to do multi-node (just passing the\nnode number on the command line is enough).. WWIV will set the environment \nvariable by itself now (had to make this change to get it to work with telnet \nservers)\n\n5) WWIV Networking works (fixed a bug where it was generating corrupt \noutgoing packets)\n\n6) BBS.CPP now contains a C++ class (minor code changes, however I wanted to \nstart adding the C++ classes into the framework)\n\n7) Command line parameter changes (to match what we get from EleBBS's \ntelsrv).. -N is now -Q, -I is not -N (but -I still works), -TELSRV tells \nWWIV to use internal telnet server (not needed if running under EleBBS's \ntelnet server).. However with this option, you can only run single node, \nwhereas you can run multi-node under EleBBS's server\n\n8) All sorts of other random fixes/tweaks to make things work...\n\n\n\n\n==============================================================================\n\nWWIV 5.0 Build 6\n================\n\n* Fixed several ANSI errors (i.e. external foo, without the type, etc.)\n\n* Changed some functions parameters to \"const char*\" if they really are \n(warnings under GCC)\n\n* Added some GCC specific code in port.h to enable compiles under \nGCC 2.95 on WIN32\n\n==============================================================================\n\n\n01-06-2000 Build 3\n==================\n* Made compiles 10 times faster with VC's pre-compiled headers.  Also \n  reorganized header file setup so that the only header file to include per \n  .C/.CPP file is \"wwiv.h\".  Precompiled headers are set to work through wwiv.h\n\n* Sped up compile time by defining WIN32_LEAN_AND_MEAN\n\n* Added 1st OS/2 conditional code segment to port.c\n\n* removed #pragma hdrstop code (since MSVC doesn't use it)\n\n* changed all header file guards to \"__INCLUDED_XXXXX_H__\" and test define \n  before #include statement (this is many times faster than making the compiler \n  parse the entire header file looking for\n  the #endif at the end)\n\n* Removed #include statements from most of the header file since they are \n  only included from \"wwiv.h\"\n\n==============================================================================\n\n\n01-05-2000 Build 2\n==================\nFixed save and restore screen.  They use the right screen sizes now.\n\n\n\n==============================================================================\n\n01-04-2000 Build 2\n==================\n\n* Fixed INI files not working right, apparently, WIN32 wasn't working w/o \n  full pathnames to files, and the INI files were relative.\n\n* Fixed bug where \"char* ctypes(int num)\" was freeing the data before \n  returning it and not working.\n\n* Fixed WFC.  Added \"void DisplayWFCScreen(char *pszScreenBuffer)\" to sysopf.c\n\n* Fixed Null-Pointer Exceptions where 0 was being passed to inmsg from \n  newuser.c where a pointer is being used. (bad!!)\n\n\n\n==============================================================================\n\n\n01-04-2000 Build 1\n==================\n\nInitial Revision, Created initial port\n\n\n\n\n==============================================================================\n\n[End of revision history]\n\n"
  },
  {
    "path": "install/docs/install50-from-eli.txt",
    "content": "-----------------------------------------------------------------------------------------------\nWWIV 5.0 Install & Upgrade Documentation by Eli Sanford\n-----------------------------------------------------------------------------------------------\n\nInstallation:\n=============\nto install WWIV 5.0 \nyou need to download WWIV 4.30\n& setup 4.30 according to its documentation\nthen follow the upgrade info below\n\n\n\nUpgrading:\n===========\nupgrading is simple \nextract the new win32 exe file/s in to your WWIV root dir (ie: c:\\WWIV)\n& setup the gui telnet server\nWWIV 5.0 uses all existing files in your 4.3+ install\n\n\n\nWWIV.ini:\n=========\nnew features have been added to the WWIV.ini\nfile that you may need/want to add\n\nEXEC_LOGSYNCFOSS     = [ 1 | 0 ] - If non-zero then WWIVsync.log will \n                         be generated.  The default setting is 1 and this \n                         is currently ignored. \n\nEXEC_USECWAITFORIDLE = [ 1 | 0 ] - Under WindowsNT/2K/XP when launching \n                         the child process WWIV uses WaitForInputIdle to wait \n                         for the child process to process all normal input \n                         before starting the Fossil handling code.  Setting \n                         this to 0 will disable that (acting like Win9x where \n                         we just wait for a bit (See EXEC_CHILDWAITTIME). \n                         The default value of this is 1. \n\nEXEC_CHILDWAITTIME   = (time to wait in milliseconds, this parameter is \n                         only used on Win9X unless EXEC_USEWAITFORIDLE is \n                         set to 0. The default value is 500 (1/2 second) \n\nEXEC_WAITFORIDLETIME = (time to wait in milliseconds, only used on \n                         Windows NT/2K/XP unless EXEC_USEWAITFORIDLE=0). \n                         The default value for this is 2000 (2 seconds) \n\nINTERNALZMODEM       = [ 1 | 0 ] Turns internal zmodem on & off\n\nNEW_SCAN_AT_LOGIN    = [ Y | N ] If you add this then when a user logs in they\n                                 will be asked to scan all message areas for new messages. \n\n\n\nTelnet:\n=======\nCopy the WWIV telnet server into your WWIV home directory (for example: C:\\WWIV). \nThen run the program Before you first use the program, you must configure it. \nYou do this from the Preferences button. \n\nFor more help on the telnet server read its help file \n\n\nLinux systems:\n==============\ncreate a BBS user account\nsetup WWIV in the BBS user accounts home dir\nthen edit .bashrc (or alternative) to start nodemgr\n\n"
  },
  {
    "path": "install/docs/menu-header.txt",
    "content": "Menu commands are called by there name and a number of options parameters.\n\nThe following forms are valid syntax\n\ncommand without parameters  : menucmd\ncommand with one parameter  : menucmd \"xyz\"\ncommand with two parameters : menucmd 123, \"abc def\"\ncommand with two parameters : menucmd(456,\"abc\")\n\nMost menu commands run without any parameters at all, and most are taken\nstraight from the main and xfer menus.  Additional commands are added to\nmanage the menu system as well as a few commands which will help you to\nemulate other BBSes.\n\n =============================================================================\n"
  },
  {
    "path": "install/docs/menu.txt",
    "content": "Category: AutoMessage\n***\n\namsg:delete\n    Deletes the auto message (cosysop required)\n\n\namsg:email\n    E-mail the author of the automessage\n\n\namsg:lock\n    Locks the automessage (cosysop required)\n\n\namsg:read\n    Read the auto message\n    [use automessage:read instead]\n\n\namsg:unlock\n    Unlocks the automessage (cosysop required)\n\n\namsg:write\n    Writes a new auto message\n\n\nAutoMessage\n    Displays the legacy automessage menu\n\n\nReadAutoMessage\n    Read the auto message\n\n\nCategory: BBSList\n***\n\nbbslist\n    Legacy BBSList Menu\n\n\nbbslist:add\n    Adds a new BBS to the BBSList\n\n\nbbslist:bbslist\n    Legacy BBSList Menu\n\n\nbbslist:delete\n    Deletes a new BBS from the BBSList\n\n\nbbslist:net\n    Read the network bbs lists\n\n\nbbslist:read\n    Read the bbslist\n\n\nCategory: Chain\n***\n\nDoors\n    Enter the doors, or chains section.  Like '.'\n\n\nRunDoor\n    <door name>\n    Runs a door (chain) with doorname matching, exactly, the description you have\n    given the door in //CHEDIT\n\n\nRunDoorFree\n    <door name>\n    Runs a door (chain) with doorname matching, exactly, the description you have\n    given the door in //CHEDIT, but this function bypasses the check to see if\n    the user is allowed to run the door.\n\n\nRunDoorNumber\n    <door number>\n    Like RunDoor, but you must specify the #1 in //CHEDIT instead of the\n    description.\n\n\nRunDoorNumberFree\n    <door number>\n    Like RunDoorFree, but you must specify the #1 in //CHEDIT instead of the\n    description.\n\n\nCategory: Conference\n***\n\nDisableConf\n    Turns conferencing off\n\n\nDownDirConf\n    Go to the prior directory conference '{'\n\n\nDownSubConf\n    Decrement ({) to the next sub conference\n\n\nEnableConf\n    Turns conferencing on\n\n\nJumpDirConf\n    Jump to another directory conference 'J'\n\n\nJumpSubConf\n    Jump to another sub conference.\n\n\nNewMsgsAllConfs\n    Do a new message scan for all subs in all conferences '/A'\n\n\nUpDirConf\n    Go to the next directory conference '}'\n\n\nUpSubConf\n    Increment ()) to the previous conference number\n\n\nCategory: EMail\n***\n\nAttachFile\n\n\nKillEMail\n    Kill email that you have sent 'K'\n\n\nMultiEMail\n    Send multi-email\n\n\nReadAllMail\n    Sysop command to read all mail\n\n\nReadEMail\n    Read your email\n\n\nSendEMail\n    Enter and send email 'E' from the main menu\n\n\nCategory: File\n***\n\nAllowEdit\n    Sysop command to enter the 'ALLOW.DAT' editor.\n\n\nBatchMenu\n    Enter the batch menu 'B'\n\n\nConfigFileList\n    Enter the List+ configurator so the user can set it up to look like he wants\n\n\nDirList\n    List the directory names in the xfer section\n\n\nDLFile\n    <dirfname> <filename>\n    This will download a file, with a check for ratios and will update the\n    kb downloaded and number of files downloaded.\n    You must specify the dirfilename, which is the name of the data file in\n    the transfer editor.  filename is the name of the file being downloaded.\n\n\nDLFreeFile\n    <dirfname> <filename>\n    This will download a file, but not check ratios or charge a download charge.\n    You must specify the dir filename, which is the name of the data file in\n    the transfer editor.  filename is the name of the file being downloaded.\n\n\nDownDir\n    Go to the prior directory number '-'\n\n\nDownload\n    Download a file 'D'\n\n\nFindDescription\n    Search for a file by description\n\n\nHopDir\n    Hop to another directory number 'H'\n\n\nListFiles\n    List the file in the current directory\n\n\nListUsersDL\n    List users with access to the current xfer sub\n\n\nMoveFiles\n    Sysop command to move files\n\n\nNewFilesAllConfs\n    New file scan in all directories in all conferences\n\n\nNewFileScan\n    List files that are new since your 'New Scan Date (usually last call)' 'N'\n\n\nPrintDSZLog\n    View the DSZ log\n\n\nReadIDZ\n    Sysop command to read the file_id.diz and add it to the extended description\n\n\nRemoveFiles\n    Remove a file you uploaded\n\n\nRemoveNotThere\n    SYSOP command to remove files that do not exist.\n\n\nRenameFiles\n    Sysop command to edit and rename files\n\n\nReverseSortDirs\n    Sort the directory by date or name, backwards.\n\n\nSearchAllFiles\n    Search all files???\n\n\nSelectDir\n    Like SelectSub, but for the xfer section.\n\n\nSetDirConf\n    <key>\n    Sets the xfer section conference to key\n\n\nSetDirNumber\n    <key>\n    Equivalent to typing in a number at the xfer menu, it sets the current dir\n    number.\n\n\nSetNewFileScanDate\n    Set the 'New Scan Date' to a new date\n\n\nSortDirs\n    Sort the directory by date or name\n\n\nUpDir\n    Go to the next directory number '+'\n\n\nUpload\n    User upload a file\n\n\nUploadAllDirs\n    Syosp command to add any files sitting in the directories, but not in\n    the file database to wwiv's file database\n\n\nUploadCurDir\n    Sysop command to scan the current directory for any files that are not in\n    wwiv's file database and adds them to it.\n\n\nUploadFilesBBS\n    Import a files.bbs (probably a CD) into the wwiv's file database\n\n\nUploadToSysop\n    Upload a file into dir#0, the sysop dir.\n\n\nViewArchive\n    List an archive's contents\n\n\nXferDefaults\n    Enter the xfer section defaults\n\n\nCategory: GFiles\n***\n\nBulletinEdit\n    Sysop command to edit the bulletins 'gfiles'\n\n\nBulletins\n    Enter the bulletins (or 'gfiles') section.  'G'\n\n\nCategory: Menu\n***\n\nDisplayHelp\n    An alias for DisplayMenu.\n    This alias is deprecated, please use menu:display.\n\n\nDisplayMenu\n    Prints the 'novice menus' for the current menu set, or if one doesn't exist,\n    it will generate one using command \"menu:generate_short\"\n\n\nMENU\n    <menu>\n    Loads up and starts running a new menu set, where <menu> equals the name of\n    the menu to load.\n\n\nmenu:display\n    Prints the 'novice menus' for the current menu set, or if one doesn't exist,\n    it will generate one using command \"menu:generate_short\"\n\n\nmenu:generate_long\n    Generates the long form (one cmd per line) help text/menu for the current menu set.\n    This command does not attempt to display a .msg/.ans file.\n\n\nmenu:generate_short\n    Generates the short form 'novice menus' for the current menu set.\n    This command does not attempt to display a .msg/.ans file.\n\n\nReturnFromMenu\n\n\nCategory: Message\n***\n\nClearQScan\n    Marks messages unread.\n\n\nDownSub\n    Decrement the current sub number (-)\n\n\nHopSub\n    Hop to another sub.  'H'\n\n\nListUsers\n    List users who have access to the current sub\n\n\nNewMessageScan\n    Do a new message scan\n\n\nNewMsgScanCurSub\n    Scan new messages in the current message sub\n\n\nNewMsgScanFromHere\n    Read new messages starting from the current sub\n\n\nPostMessage\n    Post a message in the current sub\n\n\nRemovePost\n    Remove a post\n\n\nResetQscan\n    Set all messages to read (I think)\n\n\nSelectSub\n    This will prompt the user to enter a sub to change to.  However, it does not\n    first show the subs (like Renegade).  However, you can stack a sublist and\n    then this command to mimic the action.\n\n\nSetMsgConf\n    <key>\n    Sets the subboards conference to key\n\n\nSetNewScanMsg\n    Enter the menu so that a user can set which subs he want to scan when doing\n    a new message scan\n\n\nSetSubNumber\n    <key>\n    Equivalent to typing in a number at the main menu, it sets the current sub\n    number.\n\n\nSubList\n    List the subs available\n\n\nTitleScan\n    Scan the titles of the messages in the current sub\n\n\nUnQScan\n    Marks messages as unread\n\n\nUploadPost\n    Allow a user to upload a post that will be posted\n\n\nUpSub\n    Increment the current sub# (+)\n\n\nValidatePosts\n    Sysop command to validate unvalidated posts\n\n\nCategory: Net\n***\n\nNetListing\n    Show networks\n\n\nNetLog\n    Sysop command to view the network log\n\n\nPending\n    Shows which net files are ready to be sent\n\n\nCategory: QWK\n***\n\nPackers\n    Executes the QWK menu. (Legacy, use qwk: commands now)\n\n\nqwk:config_sysop\n    Configures SysOp Settings for QWK\n\n\nqwk:config_user\n    Configures User Settings for QWK\n\n\nqwk:download\n    Download a QWK Message Packet\n\n\nqwk:menu\n    Executes the default QWK menu.\n\n\nqwk:upload\n    Upload a QWK Reply Packet\n\n\nCategory: SYSOP\n***\n\nChainEdit\n    Sysop command to edit the doors or chains\n\n\nChangeUser\n    Sysop command equal to //CHUSER, to change into another users\n\n\nConferenceEdit\n    Sysop command ot edit the conferences\n\n\nDirEdit\n    Sysop command to edit the directory records\n\n\nEdit\n    Sysop command to edit a text file\n\n\nMemStat\n\n\nStatus\n\n\nSubEdit\n    Sysop command to edit the subboards\n\n\nToggleAvailable\n    Toggle the sysop availability for chat\n\n\nValidateUser\n    Validate a new users.  I think this '!'\n\n\nViewNetDataLog\n    View the net data logs\n\n\nVoteEdit\n    Sysop command to edit the voting both\n\n\nCategory: System\n***\n\nChatRoom\n    Go into the multiuser chat room\n\n\ncls\n    Clear the screen\n\n\nDefaults\n    Enter the normal 'defaults' section\n\n\nFastGoodBye\n    Logoff fast '/O'\n\n\nFeedback\n    Leave feedback to the syosp.  'F'\n\n\nGoodbye\n    Normal logoff 'O'\n\n\nGuestApply\n    Allows a guest to apply for access\n\n\nLastCallers\n    View the last few callers\n\n\nListAllColors\n    Display all colors available for use.\n\n\nLoadText\n    Sysop command to load a text file that will be edited in the text editor\n\n\nLoadTextFile\n    Looks like a duplicate to 'LoadText'\n\n\nLog\n    Syosp command to view the log file\n\n\nPause\n    Pauses the screen, like 'pausescr()' in C code\n\n\nPrintDevices\n    Show the 'devices'.  I have no idea why.\n\n\nPrintFile\n    <filename>\n    Prints a file, first checking to see if you specified an absolute path,\n    then the language dir, then the gfilesdir.  It will use the usual checks to\n    determine .ANS, or .MSG if not specified.\n\n\nPrintFileNA\n    <filename>\n    Just like PrintFile, but the user can not abort it with the space bar.\n\n\nRequestChat\n    Request chat from the sysop\n\n\nRunBasic\n    <script name>\n    Runs a WWIVbasic Script\n\n\nSystemInfo\n    View the system info\n\n\nTextEdit\n    Edit a text file\n\n\nTimeBank\n    Enter the time bank\n\n\nToggleExpert\n    Turn 'X'pert mode on or off (toggle)\n    Can optionally pass \"quiet=on\" as the command data to suppress displaying the expert mode state.\n\n\nTurnMCIOff\n    Disable MCI codes\n\n\nTurnMCIOn\n    Enable MCI codes\n\n\nWHO\n    Show who else is online\n\n\nWWIVVer\n    Get the wwiv version\n\n\nYLog\n    View yesterdays log\n\n\nYourInfo\n    Display the yourinfo screen\n\n\nYourInfoDL\n    Prints user info for downloads\n\n\nZLog\n    View the ZLog\n\n\nCategory: User\n***\n\nConfigUserMenuSet\n    Use user:menus instead.\n    Sets the user's menuset to the value specified by data\n    or takes the user into the user menu config so they can select which menuset to use.\n\n\nuser:24\n    Toggles If the time should be displayed using a 24-hour clock vs. 12-hour\n\n\nuser:address\n    Allows the user to change their address\n\n\nuser:ansistate\n    Allows the user to change their ANSI state\n\n\nuser:autoquote\n    Toggles If new messages in external editors should contain the entire reply text\n\n\nuser:callsign\n    Allows the user to change their HAM callsign\n\n\nuser:city\n    Allows the user to change their city\n\n\nuser:cls\n    Toggles If the screen should be cleared between messages in the non-full screen message reader\n\n\nuser:colors\n    Allows the user to change their colors\n\n\nuser:comptype\n    Allows the user to change their computer type\n\n\nuser:conference\n    Toggles if conferences are enables\n\n\nuser:country\n    Allows the user to change their country\n\n\nuser:ctrlcodes\n    Toggles if message lines with kludges or control codes are shown\n\n\nuser:dataphone\n    Allows the user to change their data phone number\n\n\nuser:editor\n    Allows the user to change their default editor\n\n\nuser:email\n    Allows the user to change their email address\n\n\nuser:extra_color\n    Toggles Extra Colors\n\n\nuser:fs_reader\n    Toggles If the full screen message reader is used\n\n\nuser:gender\n    Allows the user to change their gender\n\n\nuser:macros\n    Allows the user to change their macros\n\n\nuser:mailbox\n    Allows the user to change their email forward/mailbox settings\n\n\nuser:menus\n    Sets the user's menuset to the value specified by data\n    or takes the user into the user menu config so they can select which menuset to use.\n\n\nuser:nomsgs\n    Toggles If the user doesn't want inter instance messages\n\n\nuser:optional_lines\n    Allows the user to change the number of optional lines displayed\n\n\nuser:password\n    Allows the user to change their password\n\n\nuser:pause\n    Toggles pause on page\n\n\nuser:phone\n    Allows the user to change their voice phone number\n\n\nuser:qscan\n    Allows the user to change their subs that are newscanned\n\n\nuser:realname\n    Allows the user to change their real name\n\n\nuser:regnum\n    Allows the user to change their WWIV 4.x registration number\n\n\nuser:screensize\n    Allows the user to change their screen size\n\n\nuser:state\n    Allows the user to change their state\n\n\nuser:zipcode\n    Allows the user to change their zipcode\n\n\nCategory: Vote\n***\n\nInitVotes\n\n\nVote\n    Enter the voting both\n\n\nVotePrint\n    Show the voting statistics\n\n\n"
  },
  {
    "path": "install/docs/readme-wwiv.txt",
    "content": "readme-wwiv.txt\n\nWWIV 5.x Getting Started\n~~~~~~~~~~~~~~~~~~~~~~~~\nIf you already have WWIV 4.3 or 5.x installed, Please see the instructions at\nhttp://docs.wwivbbs.org for upgrading from a previous version, with the latest\ninstructions available here as upgrade.txt.\n\ninit.exe was renamed to WWIVconfig earlier in 5.x, so please delete the\nolder init.exe if you have it still.\n\nThe command line parameters have changed quite a bit, I suggest running\n\"bbs -? | more\" to see the list of changes.\n\nSo far, WWIV 5.x is still fully upgradable from your existing WWIV 4.30\nand 5.x installations (Just drop it in and run WWIVconfig to upgrade the \ndata files and go for the most part).\n\nRun wwivconfig.exe and then select the menu WWIVD and setup\nthe information for your configuration (paths, and the starting and ending\nnode numbers to use for inbound telnet). Then launch wwivd to have it\nlisten on a socket and ready to spawn instances of WWIV.  You do not\nneed to keep any copies of WWIV running, as wwivd will spawn them as\nrequired and can also run the beginday event if configured so in\nWWIVconfig.\n\nFull documentation is avalable online: http://docs.wwivbbs.org\n\n*** Be sure to read WHATSNEW.TXT for a list of all the new major features and\nother changes that have happened since 5.0. ***\n\nNOTE: Serial I/O Support has been removed. Use one of the serial -> telnet\nbridges for \"Dial Up\" support.\n\n===============================================================================\n\n                *** Attention Windows Users ***\n\n    You may need to download the Visual Studio 2019 redistributable\n    files. \n    \n    Here's the official link: \n    https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads\n        \n    If you see errors about missing DLL files, you may need to install this package\n    before using WWIV (wwivconfig.exe, bbs.exe, everything).\n\n*** Please see https://github.com/wwivbbs/wwiv for development information. ***\n\n===============================================================================\n\nThe following copyright statements and licenses apply to the various open\nsource softwares components included with WWIV.\n\nWWIV does not necessarily use all the open source software components\nreferred to below and may also only use portions of a given component.\n\n\nHere is a list of the third party open source components included with\nWWIV:\n\n===============================================================================\n** INFOZIP ZIP3.0/UNZIP6.0 (zip.exe/unzip.exe)\n\nThis is version 2007-Mar-4 of the Info-ZIP license.\nThe definitive version of this document should be available at\nftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and\na copy at http://www.info-zip.org/pub/infozip/license.html.\n\n\nCopyright (c) 1990-2007 Info-ZIP.  All rights reserved.\n\nFor the purposes of this copyright and license, \"Info-ZIP\" is defined as\nthe following set of individuals:\n\n   Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois,\n   Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth,\n   Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz,\n   David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko,\n   Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs,\n   Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda,\n   Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren,\n   Rich Wales, Mike White.\n\nThis software is provided \"as is,\" without warranty of any kind, express\nor implied.  In no event shall Info-ZIP or its contributors be held liable\nfor any direct, indirect, incidental, special or consequential damages\narising out of the use of or inability to use this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the above disclaimer and the following restrictions:\n\n    1. Redistributions of source code (in whole or in part) must retain\n       the above copyright notice, definition, disclaimer, and this list\n       of conditions.\n\n    2. Redistributions in binary form (compiled executables and libraries)\n       must reproduce the above copyright notice, definition, disclaimer,\n       and this list of conditions in documentation and/or other materials\n       provided with the distribution.  The sole exception to this condition\n       is redistribution of a standard UnZipSFX binary (including SFXWiz) as\n       part of a self-extracting archive; that is permitted without inclusion\n       of this license, as long as the normal SFX banner has not been removed\n       from the binary or disabled.\n\n    3. Altered versions--including, but not limited to, ports to new operating\n       systems, existing ports with new graphical interfaces, versions with\n       modified or added functionality, and dynamic, shared, or static library\n       versions not from Info-ZIP--must be plainly marked as such and must not\n       be misrepresented as being the original source or, if binaries,\n       compiled from the original source.  Such altered versions also must not\n       be misrepresented as being Info-ZIP releases--including, but not\n       limited to, labeling of the altered versions with the names \"Info-ZIP\"\n       (or any variation thereof, including, but not limited to, different\n       capitalizations), \"Pocket UnZip,\" \"WiZ\" or \"MacZip\" without the\n       explicit permission of Info-ZIP.  Such altered versions are further\n       prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP\n       e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP\n       will provide support for the altered versions.\n\n    4. Info-ZIP retains the right to use the names \"Info-ZIP,\" \"Zip,\" \"UnZip,\"\n       \"UnZipSFX,\" \"WiZ,\" \"Pocket UnZip,\" \"Pocket Zip,\" and \"MacZip\" for its\n       own source and binary releases.\n===============================================================================\n** RapidJSON\n\nCopyright (C) 2011 Milo Yip\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n===============================================================================\n** GoogleTest\n\nCopyright 2008, Google Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n    * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n    * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n===============================================================================\n** sanitizers-cmake (https://github.com/arsenm/sanitizers-cmake)\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Matt Arsenault\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n===============================================================================\n** cryptlib 3.4.2 (http://www.cryptlib.com/security-software/download-form/download-security-toolkit)\n\ncryptlib is distributed under a dual license that allows free, open-source use\nunder a GPL-compatible license and closed-source use under a standard\ncommercial license.  The GPL-compatible license (a.k.a. the Sleepycat license)\nis given below.  Further details on this license are available from the\ncryptlib home page.\n\n  Copyright 1992-2010 Peter Gutmann. All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n\n  1. Redistributions of source code must retain the above copyright notice, this\n     list of conditions and the following disclaimer.\n\n  2. Redistributions in binary form must reproduce the above copyright notice,\n     this list of conditions and the following disclaimer in the documentation\n     and/or other materials provided with the distribution.\n\n  3. Redistributions in any form must be accompanied by information on how to\n     obtain complete source code for the cryptlib software and any accompanying\n     software that uses the cryptlib software.  The source code must either be\n     included in the distribution or be available for no more than the cost of\n     distribution, and must be freely redistributable under reasonable\n     conditions.  For an executable file, complete source code means the source\n     code for all modules it contains or uses.  It does not include source code\n     for modules or files that typically accompany the major components of the\n     operating system on which the executable file runs.  Note that decoupling\n     the software from the user, for example by running in a SaaS configuration,\n     does not exempt you from these requirements.\n\n  THIS SOFTWARE IS PROVIDED \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED.  IN NO\n  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\n  OF SUCH DAMAGE.\n\nIf you're unable to comply with the above license then the following,\nalternate usage conditions apply:\n\n  Any large-scale commercial use of cryptlib requires a license.  \"Large-scale\n  commercial use\" means any revenue-generating purpose such as use for\n  company-internal purposes, or use of cryptlib in an application or product,\n  with a total gross revenue of over US$5,000.  This allows cryptlib to be\n  used in freeware and shareware applications, for evaluation and research\n  purposes, and for non-revenue-generating or personal use without charge.  In\n  addition the author reserves the right to grant free licenses for commercial\n  use in special cases (for example where there is a general benefit to the\n  public), contact the author for details if you think you qualify.\n\n\n===============================================================================\n* cereal https://github.com/USCiLab/cereal/ (BSD License)\n\n\nCopyright (c) 2014, Randolph Voorhies, Shane Grant\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of cereal nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n===============================================================================\n* My-Basic https://github.com/paladin-t/my_basic\n\nThe MIT License\n\nCopyright (C) 2011 - 2016 Wang Renxin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n===============================================================================\n* FMT https://github.com/fmtlib/fmt\n\nCopyright (c) 2012 - present, Victor Zverovich\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "install/docs/upgrade.txt",
    "content": "\nSpecific additions for upgrading to WWIV 5.7.0\n(from 5.6.0 or a pre-release 5.7.0)\n===============================================\n\n\nAfter upgrading to 5.6.0, please move your $WWIV_HOME/gfiles/menu tree \nto $WWIV_HOME/menus.  This is how the canonical structure is going forward,\nnow that menusets will have child directories under it for gfiles/ and \nscripts/.\n\nIf you haven't customized your menus, I'd suggest replacing and overwriting\nthem with the ones included in the release archive's menus.zip file\n\nFor the gfiles.zip, using \"unzip -n gfiles.zip -d gfiles\" is likely\nto get you most of the way there, just manually also copy sbmain.msg\nfrom the gfiles.zip archive.\n\nIn addition to the standard upgrade steps on http://docs.wwivbbs.org, \nplease note that here is a changelog of all of the files in menus, data,\nini files, and gfiles that has happened since 5.6.0. \n\nLegend:\n=======\nM - Modified\nR - Moved and modified\nA - Added\nD - Deleted\n\nPlease make sure that \n\nM\tinstall/data/menu_commands.json\nM\tinstall/docs/menu.txt\nM\tinstall/docs/whatsnew.txt\nA\tinstall/gfiles/bbs.str.ini\nA\tinstall/gfiles/fs_msgread.120.msg\nA\tinstall/gfiles/fs_msgread.msg\nA\tinstall/gfiles/fs_msgscan.msg\nD\tinstall/gfiles/menus/wwiv/automsg.pro\nD\tinstall/gfiles/menuwel.ans\nM\tinstall/gfiles/menuwel.msg\nM\tinstall/gfiles/smbmain.msg\nA\tinstall/gfiles/yourinfo.msg\nM\tinstall/inifiles/wwiv.ini\nR100\tinstall/gfiles/menus/descript.ion\tinstall/menus/descript.ion\nR073\tinstall/gfiles/menus/wwiv/automsg.mnu.json\tinstall/menus/wwiv/automsg.mnu.json\nA\tinstall/menus/wwiv/automsg.pro\nR100\tinstall/gfiles/menus/wwiv/bbslist.mnu.json\tinstall/menus/wwiv/bbslist.mnu.json\nR100\tinstall/gfiles/menus/wwiv/bbslist.pro\tinstall/menus/wwiv/bbslist.pro\nA\tinstall/menus/wwiv/defaults.mnu.json\nA\tinstall/menus/wwiv/defaults.msg\nA\tinstall/menus/wwiv/defaults.pro\nR095\tinstall/gfiles/menus/wwiv/main.mnu.json\tinstall/menus/wwiv/main.mnu.json\nR100\tinstall/gfiles/menus/wwiv/main.msg\tinstall/menus/wwiv/main.msg\nR100\tinstall/gfiles/menus/wwiv/main.pro\tinstall/menus/wwiv/main.pro\nA\tinstall/menus/wwiv/menuset.json\nR086\tinstall/gfiles/menus/wwiv/qwk.mnu.json\tinstall/menus/wwiv/qwk.mnu.json\nR100\tinstall/gfiles/menus/wwiv/qwk.msg\tinstall/menus/wwiv/qwk.msg\nR100\tinstall/gfiles/menus/wwiv/qwk.pro\tinstall/menus/wwiv/qwk.pro\nR088\tinstall/gfiles/menus/wwiv/sysop.mnu.json\tinstall/menus/wwiv/sysop.mn.0u.json\nR100\tinstall/gfiles/menus/wwiv/sysop.pro\tinstall/menus/wwiv/sysop.pro\nR077\tinstall/gfiles/menus/wwiv/vissys.mnu.json\tinstall/menus/wwiv/vissys.mnu.json\nR100\tinstall/gfiles/menus/wwiv/vissys.msg\tinstall/menus/wwiv/vissys.msg\nR100\tinstall/gfiles/menus/wwiv/vissys.pro\tinstall/menus/wwiv/vissys.pro\nR093\tinstall/gfiles/menus/wwiv/xfer.mnu.json\tinstall/menus/wwiv/xfer.mnu.json\nR100\tinstall/gfiles/menus/wwiv/xfer.msg\tinstall/menus/wwiv/xfer.msg\nR100\tinstall/gfiles/menus/wwiv/xfer.pro\tinstall/menus/wwiv/xfer.pro\ndiff --git a/install/data/menu_commands.json b/install/data/menu_commands.json\n\n\nHere's a full diff of all of the changes to the install files since 5.6.0 for reference\n=======================================================================================\n\nindex ded179fad..776668d1a 100644\n--- a/install/data/menu_commands.json\n+++ b/install/data/menu_commands.json\n@@ -4,16 +4,71 @@\n         {\n             \"cat\": \"AutoMessage\",\n             \"cmd\": \"AutoMessage\",\n-            \"help\": \"Read the auto message\"\n+            \"help\": \"Displays the legacy automessage menu\"\n         },\n         {\n             \"cat\": \"AutoMessage\",\n             \"cmd\": \"ReadAutoMessage\",\n             \"help\": \"Read the auto message\"\n         },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:delete\",\n+            \"help\": \"Deletes the auto message (cosysop required)\"\n+        },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:email\",\n+            \"help\": \"E-mail the author of the automessage\"\n+        },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:lock\",\n+            \"help\": \"Locks the automessage (cosysop required)\"\n+        },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:read\",\n+            \"help\": \"Read the auto message \\n[use automessage:read instead]\"\n+        },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:unlock\",\n+            \"help\": \"Unlocks the automessage (cosysop required)\"\n+        },\n+        {\n+            \"cat\": \"AutoMessage\",\n+            \"cmd\": \"amsg:write\",\n+            \"help\": \"Writes a new auto message\"\n+        },\n+        {\n+            \"cat\": \"BBSList\",\n+            \"cmd\": \"bbslist\",\n+            \"help\": \"Legacy BBSList Menu\"\n+        },\n+        {\n+            \"cat\": \"BBSList\",\n+            \"cmd\": \"bbslist:add\",\n+            \"help\": \"Adds a new BBS to the BBSList\"\n+        },\n+        {\n+            \"cat\": \"BBSList\",\n+            \"cmd\": \"bbslist:bbslist\",\n+            \"help\": \"Legacy BBSList Menu\"\n+        },\n         {\n             \"cat\": \"BBSList\",\n-            \"cmd\": \"BBSList\",\n+            \"cmd\": \"bbslist:delete\",\n+            \"help\": \"Deletes a new BBS from the BBSList\"\n+        },\n+        {\n+            \"cat\": \"BBSList\",\n+            \"cmd\": \"bbslist:net\",\n+            \"help\": \"Read the network bbs lists\"\n+        },\n+        {\n+            \"cat\": \"BBSList\",\n+            \"cmd\": \"bbslist:read\",\n             \"help\": \"Read the bbslist\"\n         },\n         {\n@@ -304,12 +359,12 @@\n         {\n             \"cat\": \"Menu\",\n             \"cmd\": \"DisplayHelp\",\n-            \"help\": \"<filename>\\n\\n  An alias for DisplayMenu. \\n  This alias is deprecated, please use DisplayMenu.\"\n+            \"help\": \"An alias for DisplayMenu. \\n  This alias is deprecated, please use menu:display.\"\n         },\n         {\n             \"cat\": \"Menu\",\n             \"cmd\": \"DisplayMenu\",\n-            \"help\": \"<filename>\\n\\n  Prints the 'novice menus' for the current menu set, or if one doesn't exist,\\n  it will generate one using the menu definitions.\"\n+            \"help\": \"Prints the 'novice menus' for the current menu set, or if one doesn't exist,\\n  it will generate one using command \\\"menu:generate_short\\\"\"\n         },\n         {\n             \"cat\": \"Menu\",\n@@ -321,6 +376,21 @@\n             \"cmd\": \"ReturnFromMenu\",\n             \"help\": \"\"\n         },\n+        {\n+            \"cat\": \"Menu\",\n+            \"cmd\": \"menu:display\",\n+            \"help\": \"Prints the 'novice menus' for the current menu set, or if one doesn't exist,\\n  it will generate one using command \\\"menu:generate_short\\\"\"\n+        },\n+        {\n+            \"cat\": \"Menu\",\n+            \"cmd\": \"menu:generate_long\",\n+            \"help\": \"Generates the long form (one cmd per line) help text/menu for the current menu set.\\nThis command does not attempt to display a .msg/.ans file.\"\n+        },\n+        {\n+            \"cat\": \"Menu\",\n+            \"cmd\": \"menu:generate_short\",\n+            \"help\": \"Generates the short form 'novice menus' for the current menu set.\\nThis command does not attempt to display a .msg/.ans file.\"\n+        },\n         {\n             \"cat\": \"Message\",\n             \"cmd\": \"ClearQScan\",\n@@ -496,11 +566,6 @@\n             \"cmd\": \"MemStat\",\n             \"help\": \"\"\n         },\n-        {\n-            \"cat\": \"SYSOP\",\n-            \"cmd\": \"ReloadMenus\",\n-            \"help\": \"This is probably obsolete.\"\n-        },\n         {\n             \"cat\": \"SYSOP\",\n             \"cmd\": \"Status\",\n@@ -634,7 +699,7 @@\n         {\n             \"cat\": \"System\",\n             \"cmd\": \"ToggleExpert\",\n-            \"help\": \"Turn 'X'pert mode on or off (toggle)\"\n+            \"help\": \"Turn 'X'pert mode on or off (toggle)\\n  Can optionally pass \\\"quiet=on\\\" as the command data to suppress displaying the expert mode state.\"\n         },\n         {\n             \"cat\": \"System\",\n@@ -686,6 +751,166 @@\n             \"cmd\": \"ConfigUserMenuSet\",\n             \"help\": \"Takes the user into the user menu config so they can select which menuset\\n  they want to use, etc...\"\n         },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:24\",\n+            \"help\": \"Toggles If the time should be displayed using a 24-hour clock vs. 12-hour\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:address\",\n+            \"help\": \"Allows the user to change their address\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:ansistate\",\n+            \"help\": \"Allows the user to change their ANSI state\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:autoquote\",\n+            \"help\": \"Toggles If new messages in external editors should contain the entire reply text\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:callsign\",\n+            \"help\": \"Allows the user to change their HAM callsign\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:city\",\n+            \"help\": \"Allows the user to change their city\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:cls\",\n+            \"help\": \"Toggles If the screen should be cleared between messages in the non-full screen message reader\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:colors\",\n+            \"help\": \"Allows the user to change their colors\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:comptype\",\n+            \"help\": \"Allows the user to change their computer type\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:conference\",\n+            \"help\": \"Toggles if conferences are enables\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:country\",\n+            \"help\": \"Allows the user to change their country\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:ctrlcodes\",\n+            \"help\": \"Toggles if message lines with kludges or control codes are shown\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:dataphone\",\n+            \"help\": \"Allows the user to change their data phone number\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:editor\",\n+            \"help\": \"Allows the user to change their default editor\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:email\",\n+            \"help\": \"Allows the user to change their email address\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:extra_color\",\n+            \"help\": \"Toggles Extra Colors\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:fs_reader\",\n+            \"help\": \"Toggles If the full screen message reader is used\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:gender\",\n+            \"help\": \"Allows the user to change their gender\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:macros\",\n+            \"help\": \"Allows the user to change their macros\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:mailbox\",\n+            \"help\": \"Allows the user to change their email forward/mailbox settings\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:menus\",\n+            \"help\": \"Takes the user into the user menu config so they can select which menuset\\n  they want to use, etc...\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:nomsgs\",\n+            \"help\": \"Toggles If the user doesn't want inter instance messages\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:optional_lines\",\n+            \"help\": \"Allows the user to change the number of optional lines displayed\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:password\",\n+            \"help\": \"Allows the user to change their password\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:pause\",\n+            \"help\": \"Toggles pause on page\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:phone\",\n+            \"help\": \"Allows the user to change their voice phone number\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:qscan\",\n+            \"help\": \"Allows the user to change their subs that are newscanned\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:realname\",\n+            \"help\": \"Allows the user to change their real name\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:regnum\",\n+            \"help\": \"Allows the user to change their WWIV 4.x registration number\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:screensize\",\n+            \"help\": \"Allows the user to change their screen size\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:state\",\n+            \"help\": \"Allows the user to change their state\"\n+        },\n+        {\n+            \"cat\": \"User\",\n+            \"cmd\": \"user:zipcode\",\n+            \"help\": \"Allows the user to change their zipcode\"\n+        },\n         {\n             \"cat\": \"Vote\",\n             \"cmd\": \"InitVotes\",\ndiff --git a/install/docs/menu.txt b/install/docs/menu.txt\nindex 9b5d93522..3197540aa 100644\n--- a/install/docs/menu.txt\n+++ b/install/docs/menu.txt\n@@ -327,10 +327,6 @@ ReadIDZ\n     Sysop command to read the file_id.diz and add it to the extended description\n \n \n-ReloadMenus\n-    This is probably obsolete.\n-\n-\n RemoveFiles\n     Remove a file you uploaded\n \ndiff --git a/install/docs/whatsnew.txt b/install/docs/whatsnew.txt\nindex 84e0252d6..47976fb18 100644\n--- a/install/docs/whatsnew.txt\n+++ b/install/docs/whatsnew.txt\n@@ -9,6 +9,166 @@ Legend (starting with 5.3)\n - Feature removed\n * Change or cleanup\n \n+*** Please make sure you get the new files out of the install archives\n+    like gfiles.zip, menus.zip, etc.  We're adding new files and each\n+    new wwiv update may contain new files.  I'd recommend using unzip -n\n+    so that you don't overwrite any files (or use winmerge or meld\n+    to compare new changes)\n+\n+What's New in WWIV 5.7.0 (2021)\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n++ Improve autoblocker in wwivd (#1359)\n+  WWIV's autoblocker now gives variable automatic blocking for fixed\n+  time periods 4 times before adding a permanent ban to badips.txt.\n+  The way you trigger the blocking is to have more than X connections within\n+  Y seconds, where X and Y are defined in wwivconfig's wwivd blocking page.\n+  ** You may want to delete badip.txt or rename it to something else, it likely\n+     has more systems in it than you intended to block **\n+* Removed the following from wwiv.ini:\n+  CHECK_DUP_PHONES       = N \n+  HANGUP_DUP_PHONES      = N \n+  The first never worked, therefore neither did the second and also isn't really\n+  need anymore.\n++ Added new setting in wwivconfig for fine grained newuser info.\n+! Add granular control over which profile information must be provided by new users (#845)\n+  By default wwivconfig should match what you had in wwiv.ini, but please take a look\n+  also please remove the following from wwiv.ini since they are confusing and \n+  these values are now controlled by wwivconfig:\n+  * EXTENDED_USERINFO\n+  * NEWUSER_MIN\n+  * TEMP_DIRECTORY\n+  * BATCH_DIRECTORY\n+  * NUM_INSTANCES  \n+  * WFC_SCREEN\n++ Add new page in wwivconfig for setting which fields are required, optional, and unused.\n++ Set newuser to internal fsed not first external editor\n++ Added chain pause functionality (#1379) - thanks to DMXrob\n+* Fix IsPhoneRequired for login. We don't have NEWUSER_MIN anymore.\n++ Added yourinfo.msg to the list of gfiles/ wwiv uses.\n+  This will replace the internal YourInfo hardcoded info that is displayed\n+   if this file exists, otherwise we'll fall back to the hardcoded one.\n++ Added @z macro to display the upload/download ratio for the user.\n++ When toggling expert mode, WWIV will now display the status of expert\n+  mode or not unless \"quiet=on\" is passed to the menu command as data.\n+* Still allow HandleControlKey to work with bgetch_event. (#1382)\n+* Added ACS user.guest, and cleaned up menu and newuser routines a bit.\n+* Let KEY_SSAVE behave like control-Z (#1360)\n++ Added user.validated to acs. (#1387)\n++ better asv from valuser command (#1388)\n+* Fix automessage menu: (A)uto reply not working in default menus (#1389)\n+* Don't add RE: line to email messages.\n++ Fix changing user settings for online user gets overwritten (#960)\n+* Improve display of 'I' information and FTN networks (#1392)\n+* Fix node instance messages should use new scratch dir not data dir (#1391)\n+* Don't check for dupes on FTN emails. (#1395)\n+* Full screen reader not displaying color right when previous line ends in ^A (#1399)\n+* System crash when setting Transfer QSCAN (#1394)\n+* Fix PAUSE prompt from loosing current attribute. (#1398)\n++ Add FTN network data in net.log for FTN using Fake Network node # (#1393)\n+* Fix control-a,d,f key handling in fsed.\n+* Run network3 automatically after editing a network\n+! --title must be specified for wwivutil email add\n+* Modem speed in last callers list (#1381)\n+* Having no networks to load is not an error anymore. (#1400)\n++ Added new wwivconfig page (under (G)) for configuring system toggles\n+    * Remove FAST_TAG_RELIST from wwiv.ini, it was not useful.\n+    * Removed CLOSE_XFER from wwiv.ini, it was no longer useful\n+    * Removed SETLDATE from wwiv.ini, it's always true.\n+    * Removed FORCE_NEWUSER from wwiv.ini. It was never used and the variable\n+      for it was removed in 5.0 build 14 (around 2001)\n+    * Removed CHAIN_REG, now that all of the data is in chains.json, there's\n+      no need to have this variable (which just kept chain.reg from being used)\n+    * Added system toggle for showing last network connections at logon.\n+    * Removed EXTENDED_USERINFO from wwiv.ini, it's always true.\n+    * Removed NEWUSER_MINfrom wwiv.ini, it's not used anymore.\n+    * Removed OFF_HOOK from wwiv.ini, it wasn't used anymore.\n+* Don't store intermediate reference to pass to WWIVMessageApi constructor. (#1402)\n++ new files fs_msgread.msg and fs_msgscan.msg control the headers for the full\n+  screen message reader and title list.  Lots of new pipe expression variables\n+  are available and documented under \"Displaying Text\" in WWIV's online \n+  documentation.\n+*  Last nework connections no longer displaying (#1403)\n+! Removed inetaddr.dat.  The data is already in user.lst\n+* Fix readmail when you have a message header template\n+* Removed MAIL_WHO_LEN from wwiv.ini, it didn't work well.\n+* Fixed qscan display error on expert mode (#1405)\n+* Fixed issue where setting a date < 1970 can crash the bbs\n+* Add new setting to allow outbound pipe codes for ftn messages. (#1407)\n+* Work around large filesystems failing the File::freespace_for_path call (#1408)\n+* HeartCodeFilter needs to handle pipe codes too (#1410)\n++ Let ini files support multi-line strings like TOML does (#1411)\n+    * Add support for a multi-line ini value. Example\n+    FOO=\"\"\"This\n+    is a multline\n+    value\n+    \"\"\"\n+    * If value is quoted using \", then strip the surrounding quote characters.\n+* Progress on merge language + menusets together #1414.  Languages and menus are\n+  now 1-1 vs. 1 language to N menus.  This simplifies many things in the BBS and \n+  better matches how folks expect to change these together.\n+! move menus to top level - Menus are now peers to gfiles/ in the bbs directory\n+  layout.  Please consider moving yours (mv gfiles/menus menus) and then updating\n+  the path using wwivconfig.\n++ Added strings for yes, no, quit, NN: and PW:\n++ Support system location and name display for FTN networks too when the\n+  nodelist is available and the nodelist base set for the network in wwivconfig.\n+* System name and location not showing up for your own system (#1419)\n+* logs dir isn't created automatically on new install (#1417)\n+* menus.zip is not unzipped during new install (#1416)\n+* provide a location/sysname on local posts to wwivnet subs\n+* use 5d address when presenting M_ADR in binkp\n++ Broke out State entry from city state to make it clearer and easier. (#1430)\n+* Use unique cram challenge (#1429)\n+* Add validation text for FTN address\n++ binkp can't answer with mutliple AKAs presented (#1426)\n+! |{pause} is now |{pausescr}\n+* Fix Last callers not displaying correct information (#1428)\n+* name_and_number() should be proper case not upper cas\n+* Move to next sub? The default is No and should be yes. (#1431)\n+* Unable to validate new users while they are online (#1432)\n+* increase default dir and sub size to 500/5000\n++ need \"bbs\" pipe expressions (#1413)\n++ Added new pipe expressions, sleep, backprint, and spin\n++ Added rainow pipe expression (#1427)\n+* Added many more {user.xxx} variables. Please see docs.\n+* Added help on how to save a message created in the internal editor (#1436)\n+* Errror on resize_file: 32; (#1438)\n+* Added ability to format pipe variables\n+* Fix handling of addresses mixed with and without domain names\n+* Problems emailng FTN networks from BBS (#1439)\n+* Log says user \"hung up\" when user logs off (#1440)\n++ Add FTN nodelist support into network bbs list viewer (i.e. (B)bsList then (N)etwork. (#1231)\n++ After using (B) to bypass a sub (from the reading prompt), don't ask if we want to post (#1437)\n++ |{if expr yes no fmt} can now take a format (like pipe variables now)\n+! Added new strings FIXED_YES and FIXED_NO.\n++ Added new pipe expression |{yesno \"expression\" \"fmt\"}\n+* WWIVNet BBS list not working (#1441)\n+* Fix crash in displaying a generated menu in wwivconfig\n+! Defaults is now a menu, not a built-in command by default, please make sure\n+  to update your wwiv menus with the new defaults menu and update main menu.\n++ You can now filter text in wwivconfig listboxes by pressing / and then \n+  entering the text to filter by.\n+* add ways to see and change personal info in defaults (#1390)\n+* Fix crash in listplus after ~130 files\n+* Support interestingly formed Tic line with addresses (#1445)\n+* reset the color to |#0 at the end of each kludge line (#1446)\n++ When sending FTN emails, try to match by zone and not ask which network to use.\n+* delete /Z and /S from default menus, they don't exist anymore\n++ Need global menu (#1415)\n+* Don't try to parse FTN addresses in 4.x\n++ Check ACS on menusets, and only show ones that are available\n++ Initial cut at support for getting the screen size from the remote terminal.\n+* FTN: just stop on short read error, don't keep retrying bad packets\n+* litebar width should be full screen not capped at 80 (#1450)\n++ user:menus should select the menuset for the caller if only one matches (#1451)\n+* throwing exception while scanning new messages (#1453)\n+* screen size detection broken at local console on linux (#1454)\n+* fullscreen view, bottom bar gets drawn on same line as command line (#1449)\n+* Fixed wwivconfig not showing 1st menu item.\n++ Filenames can now be of the form: basename.MIN_NUM_COLS_NEEDED.extension for dispay.\n+  example: logon.132.ans or fs_msgread.132.msg (#1456)\n+\n+\n What's New in WWIV 5.6.1 (2021)\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n + Added wwivutil users asv command.  This can increase user attributes to match\ndiff --git a/install/gfiles/bbs.str.ini b/install/gfiles/bbs.str.ini\nnew file mode 100644\nindex 000000000..46fd8744f\n--- /dev/null\n+++ b/install/gfiles/bbs.str.ini\n@@ -0,0 +1,32 @@\n+; WWIV BBS \"Strings\" file for custome language support.\n+; THis is the common language file for all menusets.  Ideally any customizations\n+; should be made by placing a copy of the strings into a bbs.str.ini file\n+; location in the menuset directory.\n+;\n+[lang]\n+\n+;\n+; Common words: Yes/No/Quit/Pause/etc\n+;\n+\n+; Keys to use for YNQ\n+KEY_NO    = N\n+KEY_QUIT  = Q\n+KEY_YES   = Y\n+\n+NO        = |{random \"No\", \"Nah\"}\n+PAUSE     = \"|#3More? [Y/n/c]\"\n+QUIT      = Quit\n+YES       = |{random \"Yes\", \"Yep\", \"Sure\"}\n+\n+; Fixed string values, do not use any random or colorized text.\n+FIXED_NO  = No\n+FIXED_YES = Yes\n+\n+;\n+; Logon Area. note that the three double quotes are a multi-line string\n+;\n+NN_PROMPT = \"\"\"\n+Enter number or name or 'NEW'\n+NN: \"\"\"\n+PW_PROMPT = \"PW: \"\n\\ No newline at end of file\ndiff --git a/install/gfiles/fs_msgread.120.msg b/install/gfiles/fs_msgread.120.msg\nnew file mode 100644\nindex 000000000..375f3cd7d\n--- /dev/null\n+++ b/install/gfiles/fs_msgread.120.msg\n@@ -0,0 +1,5 @@\n+|#9 Sub: |#2|{msg.message_area, \"<45\"} |#9Msg#: |[59;1H|#9[|#2|{msg.message_number, \">5\"}|#9 of |#2|{msg.total_messages, \">5\"}|#9]         Info: |#1|{if \"msg.flags.local == true\", \"|#9[|#5LOC|#9] \", \"\"}|{if \"msg.flags.wwivnet == true\", \"|#9[|#5WWIVNET|#9] \", \"\"}|{if \"msg.flags.ftn == true\", \"|#9[|#5FTN|#9] \", \"\"}\n+|#9From: |#1|{msg.from, \"<45\"} |#9Date: |#1|{msg.date}\n+|#9  To: |#1|{msg.to, \"<45\"} |#9Subj: |#2|{msg.title}\n+|#9 Sys: |#1|{msg.sys, \"<45\"} |#9Loc: |[59;4H|{msg.loc}\n+|#0|{set num_header_lines 4}\n\\ No newline at end of file\ndiff --git a/install/gfiles/fs_msgread.msg b/install/gfiles/fs_msgread.msg\nnew file mode 100644\nindex 000000000..1c3e187be\n--- /dev/null\n+++ b/install/gfiles/fs_msgread.msg\n@@ -0,0 +1,13 @@\n+|#9 Sub:                                     Msg#:\n+|#9From:                                     Date:\n+|#9  To:\n+|#9Subj:\n+|#9 Sys:                                      Loc:\n+|#9Info:\n+|[7;1H|#2|{msg.message_area}|[49;1H|#9[|#2|{msg.message_number}|#9 of |#2|{msg.total_messages}|#9]\n+|[7;2H|#1|{msg.from}|[49;2H|#1|{msg.date}\n+|[7;3H|#1|{msg.to}\n+|[7;4H|#2|{msg.title}\n+|[7;5H|#1|{msg.sys}|[49;5H|{msg.loc}\n+|[7;6H|#1|{if \"msg.flags.local == true\", \"|#9[|#5LOC|#9] \", \"\"}|{if \"msg.flags.wwivnet == true\", \"|#9[|#5WWIVNET|#9] \", \"\"}|{if \"msg.flags.ftn == true\", \"|#9[|#5FTN|#9] \", \"\"}\n+|#0|{set num_header_lines 6}\n\\ No newline at end of file\ndiff --git a/install/gfiles/fs_msgscan.msg b/install/gfiles/fs_msgscan.msg\nnew file mode 100644\nindex 000000000..0eee4f5b5\n--- /dev/null\n+++ b/install/gfiles/fs_msgscan.msg\n@@ -0,0 +1,2 @@\n+|[2J|#4Sub #|{cursub.subnum} - |{cursub.name}  (|{cursub.num_msgs} messages.)|[K|#0\n+|14      Num Title                                      From|#0|{set num_header_lines 2}\n\\ No newline at end of file\ndiff --git a/install/gfiles/menus/wwiv/automsg.pro b/install/gfiles/menus/wwiv/automsg.pro\ndeleted file mode 100644\nindex 05ab5c87b..000000000\n--- a/install/gfiles/menus/wwiv/automsg.pro\n+++ /dev/null\n@@ -1 +0,0 @@\n-|#7[|#1AutoMessage|#7]|#6:|#0 .end.\n\\ No newline at end of file\ndiff --git a/install/gfiles/menuwel.ans b/install/gfiles/menuwel.ans\ndeleted file mode 100644\nindex 9c9bd5b03..000000000\n--- a/install/gfiles/menuwel.ans\n+++ /dev/null\n@@ -1,11 +0,0 @@\n-\u001b[40m\u001b[2J\u001b[0;1;36mWWIV v5 uses a new menu system that allows you to select from a variety\n-of menu types, providing you with a new level of individual configuration.\n-Each menu set provides an option for both standard and pulldown styles, as\n-well as a \"hot-key\" support toggle.\n-\n-\u001b[0;1;35mAfter selecting your default menu set, you can change them by typing \u001b[0;1;31m//CM\n-\u001b[0;1;35m('Change Menus') from the main menu. Remember, if hotkey support is turned\n-off, you do not need the '//' before multi-letter commands.\n-\n-\u001b[0;1;32mPlease select a menu set from the menus listed below:\n-\u001b[0m\u001b[255D\ndiff --git a/install/gfiles/menuwel.msg b/install/gfiles/menuwel.msg\nindex bb31e3cc4..2e80c0942 100644\n--- a/install/gfiles/menuwel.msg\n+++ b/install/gfiles/menuwel.msg\n@@ -1,10 +1,5 @@\n-WWIV v5.00 uses a new menu system that allows you to select from a variety\n-of menu types, providing you with a new level of individual configuration.\n-Each menu set provides an option for both standard and pulldown styles, as\n-well as a \"hot-key\" support toggle.\n+|#9WWIV allows customizable menus. These menus can be changed in the stock \n+|#9WWIV menuset using either the (K) change menus command in (D)efaults, \n+|#9or from the \"//CM\" (Change Menu) command in the main menu.\n \n-After selecting your default menu set, you can change them by typing //CM\n-('Change Menus') from the main menu. Remember, if hotkey support is turned\n-off, you do not need the '//' before multi-letter commands.\n-\n-Please select a menu set from the menus listed below:\n+|#5Please select a menu set from the menus listed below:\ndiff --git a/install/gfiles/smbmain.msg b/install/gfiles/smbmain.msg\nindex a75025597..b4eeb25cb 100644\n--- a/install/gfiles/smbmain.msg\n+++ b/install/gfiles/smbmain.msg\n@@ -20,3 +20,4 @@\n |#2W      |#9Reply with \"Regards\" to Last Message\n |#2X      |#9Toggle Net Pending Status           \n |#2Y      |#9Download Last Message               \n+|#2@      |#9Reply to Different Address          \ndiff --git a/install/gfiles/yourinfo.msg b/install/gfiles/yourinfo.msg\nnew file mode 100644\nindex 000000000..d6b35ca79\n--- /dev/null\n+++ b/install/gfiles/yourinfo.msg\n@@ -0,0 +1,20 @@\n+|#4Your User Information|[K|#0\n+\n+\n+|#9Your name      : |#5|{user.name} |#9#|#2|@#\n+|#9Phone number   : |#2|@p\n+|#9Mail Waiting   : |#2|@M\n+|#9Security Level : |#2|@S\n+|#9Transfer SL    : |#2|@d\n+\n+|#9Date Last On   : |#2|@L\n+|#9Times on       : |#2|@l\n+|#9On today       : |#2|@O\n+|#9Messages posted: |#2|@m\n+|#9E-mail sent    : |#2|@E\n+|#9Time spent on  : |#2|@o |#9Minutes\n+|#9Uploads        : |#2|@K|#9k in |#2|@U |#9files\n+|#9Downloads      : |#2|@k|#9k in |#2|@D |#9files\n+|#9Transfer Ratio : |#2|@z\n+\n+|{pausescr}\ndiff --git a/install/inifiles/wwiv.ini b/install/inifiles/wwiv.ini\nindex 1aeb7898c..bc3989fbf 100644\n--- a/install/inifiles/wwiv.ini\n+++ b/install/inifiles/wwiv.ini\n@@ -149,32 +149,22 @@ BEGINDAYNODENUMBER     = 0            ;\n ; various settings to tailor your system to your needs.\n ;\n FORCE_FBACK            = N            ; force newusers to send fback\n-FORCE_NEWUSER          = N            ; force newusers to read NEWUSER.MSG\n FORCE_SCAN             = N            ; force user to scan sysop sub\n-FORCE_SCAN_SUBNUM      = 1            ; sub to force scan on\n-CHECK_DUP_PHONES       = N            ; check newuser dupe phones\n-HANGUP_DUP_PHONES      = N            ; hangup on newuser dupe phone\n+FORCE_SCAN_SUBNUM      = 1            ; sub to force scan on (as defined in boardedit)\n POSTTIME_COMPENS       = N            ; compensate for time posting\n IDZ_DESC               = Y            ; 1st line of file_id.diz as descrip\n-SETLDATE               = N            ; set file date on nscan\n READ_CD_IDZ            = N            ; read file_id.diz from cdroms\n FSED_EXT_DESC          = Y            ; allow fsed for extended descriptions\n-FAST_TAG_RELIST        = Y            ; don't show xfer dirs on tag relist\n MAIL_PROMPT            = Y            ; fancy mail prompt\n SHOW_CITY_ST           = Y            ; show city/state in laston info\n 2WAY_CHAT              = Y            ; 2-way local sysop chat\n-OFF_HOOK               = Y            ; phone offhook when sysop on\n LOG_DOWNLOADS          = N            ; send SSM to uploader on file DL\n-CLOSE_XFER             = N            ; disable transfer section\n ALL_UL_TO_SYSOP        = Y            ; all uploads go to sysop dir\n MSG_TAG                = Y            ; sysop post/email taglines\n-CHAIN_REG              = Y            ; user sponsoring of chains\n CAN_SAVE_SSM           = Y            ; allow saving of SSMs\n ALLOW_ALIASES          = Y            ; allow users to use aliases\n FREE_PHONE             = N            ; allow any format phone #\n LOGON_PHONE            = N            ; check phone # at logon?\n-EXTENDED_USERINFO      = N            ; enable addr, etc info in userrec\n-NEWUSER_MIN            = Y            ; ask minimal new user information\n ALLOW_CC_BCC           = Y            ; allow CC: and BCC: for email?\n TITLEBAR               = Y            ; show user in console titlebar\n ;\n@@ -182,9 +172,6 @@ TITLEBAR               = Y            ; show user in console titlebar\n ;                           SYSTEM TUNING PARAMETERS\n ;=============================================================================\n ;\n-MAIL_WHO_LEN           = 45           ; max length of user name when\n-;                                     ; reading mail\n-;\n ATTACH_DIR             = attach       ; dir for email attachments\n NETFOSS_DIR            = netfoss      ; directory for netfoss install (Win32)\n ;\n@@ -204,7 +191,6 @@ MAX_GFILESEC           = 32           ; max gfile sections allowed\n ;\n ; ANSI Callout and WFC Options\n ;\n-WFC_SCREEN             = Y            ; Use ANSI WFC screen?\n ;                                     ; List sequentialy i.e. CDXYZ\n SCREEN_SAVER_TIME      = 120          ; Screen saver invoke time (min.)\n INTERNALZMODEM         = Y            ; Set to N to disable internal Zmodem\n@@ -225,14 +211,6 @@ SYSTEM_BPS             = 0            ; BPS to emulate when displaying\n                                       ; would use \"SYSTEM_BPS = 9600\"\n ;\n ;=============================================================================\n-;                        TEMPORARY DIRECTORY SETTING\n-;=============================================================================\n-NUM_INSTANCES        = 4\n-TEMP_DIRECTORY       = e/%n/temp\n-BATCH_DIRECTORY      = e/%n/batch\n-;\n-;\n-;=============================================================================\n ;                           ASV OPTIONS\n ;=============================================================================\n ; Auto Sysop Validation (ASV) Settings allow you\n@@ -252,21 +230,6 @@ USE_SIMPLE_ASV                  = N         ; Use Simple ASV?\n ;SIMPLE_ASV[DAR]                =           ; DAR to assign\n ;SIMPLE_ASV[RESTRICT]           =           ; Restriction to assign\n ;\n-;\n-;=============================================================================\n-;                        INSTANCE SPECIFIC OPTIONS\n-;=============================================================================\n-; There are only a very few settings that would or should be used for\n-; individual instances.  You may have an instance that does all network\n-; callouts or one that does all processing of Fido or other network mail.\n-; To define these instance specific settings, use an ID block \n-: [WWIV-<instance>] as follows:\n-;\n-; Instance #2\n-;[WWIV-2]\n-;SCREEN_SAVER_TIME      = 120         ; Screen saver invoke time\n-;\n-;\n ;=============================================================================\n ;                         AVAILABLE COMPUTER TYPES\n ;=============================================================================\ndiff --git a/install/gfiles/menus/descript.ion b/install/menus/descript.ion\nsimilarity index 100%\nrename from install/gfiles/menus/descript.ion\nrename to install/menus/descript.ion\ndiff --git a/install/gfiles/menus/wwiv/automsg.mnu.json b/install/menus/wwiv/automsg.mnu.json\nsimilarity index 73%\nrename from install/gfiles/menus/wwiv/automsg.mnu.json\nrename to install/menus/wwiv/automsg.mnu.json\nindex 186857570..af6330af4 100644\n--- a/install/gfiles/menus/wwiv/automsg.mnu.json\n+++ b/install/menus/wwiv/automsg.mnu.json\n@@ -1,14 +1,20 @@\n {\n     \"version\": 1,\n     \"menu\": {\n+        \"cls\": false,\n         \"num_action\": \"none\",\n         \"logging_action\": \"key\",\n         \"help_type\": \"always\",\n-        \"color_title\": 5,\n-        \"color_item_key\": 2,\n-        \"color_item_text\": 1,\n-        \"color_item_braces\": 9,\n-        \"title\": \"AutoMessage Menu\",\n+        \"generated_menu\": {\n+            \"num_cols\": 6,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#7\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 0\n+        },\n+        \"title\": \"\",\n         \"acs\": \"\",\n         \"password\": \"\",\n         \"enter_actions\": [\n@@ -23,6 +29,7 @@\n             {\n                 \"item_key\": \"\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -33,6 +40,7 @@\n             {\n                 \"item_key\": \"A\",\n                 \"item_text\": \"Auto-reply\",\n+                \"visible\": false,\n                 \"help_text\": \"Replies via email to the AutoMessage author\",\n                 \"log_text\": \"AutoReply\",\n                 \"instance_message\": \"\",\n@@ -40,7 +48,24 @@\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n-                        \"cmd\": \"amsg:email_author\",\n+                        \"cmd\": \"amsg:email\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"D\",\n+                \"item_text\": \"Delete\",\n+                \"visible\": true,\n+                \"help_text\": \"Delete current automessage\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"user.sysop == true\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"amsg:delete\",\n                         \"data\": \"\",\n                         \"acs\": \"\"\n                     }\n@@ -48,7 +73,8 @@\n             },\n             {\n                 \"item_key\": \"R\",\n-                \"item_text\": \"Read AutoMessage\",\n+                \"item_text\": \"Read\",\n+                \"visible\": false,\n                 \"help_text\": \"Reads the current auto message\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -64,7 +90,8 @@\n             },\n             {\n                 \"item_key\": \"L\",\n-                \"item_text\": \"Lock AutoMessage\",\n+                \"item_text\": \"Lock\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -80,7 +107,8 @@\n             },\n             {\n                 \"item_key\": \"U\",\n-                \"item_text\": \"Unlock AutoMesssage\",\n+                \"item_text\": \"Unlock\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -96,7 +124,8 @@\n             },\n             {\n                 \"item_key\": \"W\",\n-                \"item_text\": \"Write AutoMessage\",\n+                \"item_text\": \"Write\",\n+                \"visible\": false,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -113,6 +142,7 @@\n             {\n                 \"item_key\": \"Q\",\n                 \"item_text\": \"Quit\",\n+                \"visible\": false,\n                 \"help_text\": \"Returns to the previous menu\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -128,7 +158,8 @@\n             },\n             {\n                 \"item_key\": \"?\",\n-                \"item_text\": \"Display help\",\n+                \"item_text\": \"Display Help\",\n+                \"visible\": false,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\ndiff --git a/install/menus/wwiv/automsg.pro b/install/menus/wwiv/automsg.pro\nnew file mode 100644\nindex 000000000..eba42264b\n--- /dev/null\n+++ b/install/menus/wwiv/automsg.pro\n@@ -0,0 +1 @@\n+|#7[|#1AutoMessage|#7]|#6: |#7(|#2Q|#7)|#0uit, |#7(|#2A|#7)|#0uto-Reply, |#7(|#2R|#7)|#0ead, |#7(|#2W|#7)|#0rite|#6:|#0 .end.\ndiff --git a/install/gfiles/menus/wwiv/bbslist.mnu.json b/install/menus/wwiv/bbslist.mnu.json\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/bbslist.mnu.json\nrename to install/menus/wwiv/bbslist.mnu.json\ndiff --git a/install/gfiles/menus/wwiv/bbslist.pro b/install/menus/wwiv/bbslist.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/bbslist.pro\nrename to install/menus/wwiv/bbslist.pro\ndiff --git a/install/menus/wwiv/defaults.mnu.json b/install/menus/wwiv/defaults.mnu.json\nnew file mode 100644\nindex 000000000..3ff3fee13\n--- /dev/null\n+++ b/install/menus/wwiv/defaults.mnu.json\n@@ -0,0 +1,427 @@\n+{\n+    \"version\": 1,\n+    \"menu\": {\n+        \"cls\": false,\n+        \"num_action\": \"none\",\n+        \"logging_action\": \"command\",\n+        \"help_type\": \"always\",\n+        \"generated_menu\": {\n+            \"num_cols\": 3,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#1\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 1\n+        },\n+        \"title\": \"|[2J|#4 Your Preferences|[K|#0\",\n+        \"acs\": \"\",\n+        \"password\": \"\",\n+        \"enter_actions\": [],\n+        \"exit_actions\": [],\n+        \"items\": [\n+            {\n+                \"item_key\": \"\",\n+                \"item_text\": \"\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": []\n+            },\n+            {\n+                \"item_key\": \"1\",\n+                \"item_text\": \"Screen Size\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:screensize\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"2\",\n+                \"item_text\": \"ANSI\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:ansistate\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"3\",\n+                \"item_text\": \"Pause on screen\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:pause\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"4\",\n+                \"item_text\": \"Mailbox\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:mailbox\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"5\",\n+                \"item_text\": \"Configured Q-scan\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:qscan\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"6\",\n+                \"item_text\": \"Change password\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:password\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"7\",\n+                \"item_text\": \"Update macros\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:macros\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"8\",\n+                \"item_text\": \"Change colors\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:colors\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"9\",\n+                \"item_text\": \"Message editor\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:editor\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"A\",\n+                \"item_text\": \"Extended colors\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:extra_color\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"B\",\n+                \"item_text\": \"Optional lines\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:optional_lines\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"C\",\n+                \"item_text\": \"Conferencing\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:conference\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"D\",\n+                \"item_text\": \"Show Hidden Lines\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:ctrlcodes\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"G\",\n+                \"item_text\": \"Message Reader\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:fs_reader\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"I\",\n+                \"item_text\": \"Internet Address\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:email\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"K\",\n+                \"item_text\": \"Configure Menus\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:menus\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"M\",\n+                \"item_text\": \"Allow user msgs\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:nomsgs\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"N\",\n+                \"item_text\": \"Configure QWK\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"qwk:config_user\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"S\",\n+                \"item_text\": \"Cls Between Msgs?\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:cls\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"T\",\n+                \"item_text\": \"12hr or 24hr clock\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:24\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"U\",\n+                \"item_text\": \"Use Msg AutoQuote\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:autoquote\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"W\",\n+                \"item_text\": \"WWIV reg num\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"user:regnum\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            },\n+            {\n+                \"item_key\": \"Q\",\n+                \"item_text\": \"Quit to main menu\",\n+                \"visible\": true,\n+                \"help_text\": \"\",\n+                \"log_text\": \"\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"ReturnFromMenu\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            }\n+        ]\n+    }\n+}\n\\ No newline at end of file\ndiff --git a/install/menus/wwiv/defaults.msg b/install/menus/wwiv/defaults.msg\nnew file mode 100644\nindex 000000000..361d07268\n--- /dev/null\n+++ b/install/menus/wwiv/defaults.msg\n@@ -0,0 +1,17 @@\n+|[2J|#4 Your Preferences|[K|#0\n+\n+|#11|#9) Screen size       : |#2|{user.screenwidth, \">3\"} |#9X |#2|{user.screenlines, \">3\"}        |#12|#9) ANSI              : |#2|{user.ansistr}\n+|#13|#9) Pause on screen   : |#2|{if \"user.pause == true\", \"On\", \"Off\"}\n+|#14|#9) Mailbox           : |#2|{user.mailbox_state}\n+|#15|#9) Configured Q-scan                    |#16|#9) Change password\n+|#17|#9) Update macros                        |#18|#9) Change colors\n+|#19|#9) Message editor    : |#2|{user.editorname, \"<16\"} |#1A|#9) Extended colors   : |#2|{yesno \"user.extcolors == true\"}\n+|#1B|#9) Optional lines    : |#2|{user.optional_lines}                |#1C|#9) Conferencing      : |#2|{yesno \"user.conferencing == true\"}\n+|#1D|#9) Show Hidden Lines : |#2|{yesno \"user.show_controlcodes == true\", \"<16\"} |#1G|#9) Message Reader    : |#2|{if \"user.fs_reader == true\", \"Full-Screen\", \"Traditional\"}\n+|#1I|#9) Internet Address  : |#2|{user.email}\n+|#1K|#9) Configure Menus\n+|#1M|#9) Allow user msgs   : |#2|{yesno \"user.ignore_msgs == false\", \"<16\"} |#1N|#9) Configure QWK\n+|#1S|#9) Cls Between Msgs? : |#2|{yesno \"user.clear_screen == true\", \"<16\"} |#1T|#9) 12hr or 24hr clock: |#2|{if \"user.twentyfour_clock == true\", \"24hr\", \"12hr\"}\n+|#1U|#9) Use Msg AutoQuote : |#2|{yesno \"user.auto_quote == true\", \"<16\"} |#W|#9) WWIV reg num      : |#2|{user.regnum}\n+|#1Q|#9) Quit to main menu\n+\ndiff --git a/install/menus/wwiv/defaults.pro b/install/menus/wwiv/defaults.pro\nnew file mode 100644\nindex 000000000..dd1551288\n--- /dev/null\n+++ b/install/menus/wwiv/defaults.pro\n@@ -0,0 +1,2 @@\n+\n+|#9Defaults: .end.\ndiff --git a/install/gfiles/menus/wwiv/main.mnu.json b/install/menus/wwiv/main.mnu.json\nsimilarity index 95%\nrename from install/gfiles/menus/wwiv/main.mnu.json\nrename to install/menus/wwiv/main.mnu.json\nindex e518654e8..647e5624d 100644\n--- a/install/gfiles/menus/wwiv/main.mnu.json\n+++ b/install/menus/wwiv/main.mnu.json\n@@ -20,23 +20,6 @@\n         \"enter_actions\": [],\n         \"exit_actions\": [],\n         \"items\": [\n-            {\n-                \"item_key\": \"RI\",\n-                \"item_text\": \"\",\n-                \"visible\": true,\n-                \"help_text\": \"Read current WWIV.INI values into memory\",\n-                \"log_text\": \"RI\",\n-                \"instance_message\": \"\",\n-                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"readini\",\n-                        \"data\": \"\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"IE\",\n                 \"item_text\": \"InstanceEdit\",\n@@ -224,23 +207,6 @@\n                     }\n                 ]\n             },\n-            {\n-                \"item_key\": \"RELOAD\",\n-                \"item_text\": \"ReloadMenus\",\n-                \"visible\": false,\n-                \"help_text\": \"Reload Current Menu Set\",\n-                \"log_text\": \"RELOAD\",\n-                \"instance_message\": \"\",\n-                \"acs\": \"user.sysop == true\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"reloadmenus\",\n-                        \"data\": \"\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"RESETQSCAN\",\n                 \"item_text\": \"\",\n@@ -401,7 +367,7 @@\n                 \"help_text\": \"Upload Text File to Post in next Email or Message\",\n                 \"log_text\": \"UPLOAD\",\n                 \"instance_message\": \"\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.validated == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -637,23 +603,6 @@\n                     }\n                 ]\n             },\n-            {\n-                \"item_key\": \"/Z\",\n-                \"item_text\": \"DownLoad Posts\",\n-                \"visible\": true,\n-                \"help_text\": \"DownLoad Posts in ASCII Format\",\n-                \"log_text\": \"/Z\",\n-                \"instance_message\": \"Downloading Posts\",\n-                \"acs\": \"\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"downloadposts\",\n-                        \"data\": \"\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"+\",\n                 \"item_text\": \"Up One Sub (+, ], >)\",\n@@ -831,7 +780,7 @@\n                 \"help_text\": \"Enter Time Bank\",\n                 \"log_text\": \"$\",\n                 \"instance_message\": \"Time Bank\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.validated == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -896,15 +845,15 @@\n                 \"item_key\": \"D\",\n                 \"item_text\": \"Defaults\",\n                 \"visible\": true,\n-                \"help_text\": \"Set User Defaults\",\n-                \"log_text\": \"D\",\n-                \"instance_message\": \"Defaults\",\n+                \"help_text\": \"Edit user settings\",\n+                \"log_text\": \"RAN Defaults\",\n+                \"instance_message\": \"\",\n                 \"acs\": \"\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n-                        \"cmd\": \"defaults\",\n-                        \"data\": \"\",\n+                        \"cmd\": \"MENU\",\n+                        \"data\": \"defaults\",\n                         \"acs\": \"\"\n                     }\n                 ]\n@@ -1341,7 +1290,7 @@\n                 \"help_text\": \"Allows GUEST to Apply for an Account\",\n                 \"log_text\": \"APPLY\",\n                 \"instance_message\": \"New User Logon\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.guest == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -1409,7 +1358,7 @@\n                 \"help_text\": \"Slash Menu\",\n                 \"log_text\": \"W\",\n                 \"instance_message\": \"\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.sysop == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -1431,7 +1380,7 @@\n                 \"help_text\": \"Display Sysop Menu\",\n                 \"log_text\": \"SYSOP\",\n                 \"instance_message\": \"\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.sysop == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -1465,7 +1414,7 @@\n                 \"help_text\": \"Configure Colors\",\n                 \"log_text\": \"COLORS\",\n                 \"instance_message\": \"\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.sysop == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n@@ -1482,7 +1431,7 @@\n                 \"help_text\": \"Edit Conferences\",\n                 \"log_text\": \"CONFEDIT\",\n                 \"instance_message\": \"\",\n-                \"acs\": \"\",\n+                \"acs\": \"user.sysop == true\",\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\ndiff --git a/install/gfiles/menus/wwiv/main.msg b/install/menus/wwiv/main.msg\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/main.msg\nrename to install/menus/wwiv/main.msg\ndiff --git a/install/gfiles/menus/wwiv/main.pro b/install/menus/wwiv/main.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/main.pro\nrename to install/menus/wwiv/main.pro\ndiff --git a/install/menus/wwiv/menuset.json b/install/menus/wwiv/menuset.json\nnew file mode 100644\nindex 000000000..dc188d2da\n--- /dev/null\n+++ b/install/menus/wwiv/menuset.json\n@@ -0,0 +1,27 @@\n+{\n+    \"version\": 1,\n+    \"menuset\": {\n+        \"name\": \"wwiv\",\n+        \"description\": \"wwiv v5.00 stock menus\",\n+        \"acs\": \"\",\n+        \"items\": [\n+            {\n+                \"item_key\": \"/O\",\n+                \"item_text\": \"Fast Logoff\",\n+                \"visible\": true,\n+                \"help_text\": \"Log off immediately\",\n+                \"log_text\": \"Logged off using '/O'\",\n+                \"instance_message\": \"\",\n+                \"acs\": \"\",\n+                \"password\": \"\",\n+                \"actions\": [\n+                    {\n+                        \"cmd\": \"FastGoodBye\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    }\n+                ]\n+            }\n+        ]\n+    }\n+}\n\\ No newline at end of file\ndiff --git a/install/gfiles/menus/wwiv/qwk.mnu.json b/install/menus/wwiv/qwk.mnu.json\nsimilarity index 86%\nrename from install/gfiles/menus/wwiv/qwk.mnu.json\nrename to install/menus/wwiv/qwk.mnu.json\nindex f5af2e1fa..e09487c5b 100644\n--- a/install/gfiles/menus/wwiv/qwk.mnu.json\n+++ b/install/menus/wwiv/qwk.mnu.json\n@@ -1,13 +1,19 @@\n {\n     \"version\": 1,\n     \"menu\": {\n+        \"cls\": false,\n         \"num_action\": \"none\",\n         \"logging_action\": \"none\",\n         \"help_type\": \"always\",\n-        \"color_title\": 5,\n-        \"color_item_key\": 2,\n-        \"color_item_text\": 1,\n-        \"color_item_braces\": 9,\n+        \"generated_menu\": {\n+            \"num_cols\": 3,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#1\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 1\n+        },\n         \"title\": \"QWK Menu\",\n         \"acs\": \"user.sl >= 10\",\n         \"password\": \"\",\n@@ -17,6 +23,7 @@\n             {\n                 \"item_key\": \"\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -27,6 +34,7 @@\n             {\n                 \"item_key\": \"D\",\n                 \"item_text\": \"Download\",\n+                \"visible\": true,\n                 \"help_text\": \"Download QWK Packet\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -43,6 +51,7 @@\n             {\n                 \"item_key\": \"U\",\n                 \"item_text\": \"Upload Reply\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -59,6 +68,7 @@\n             {\n                 \"item_key\": \"Q\",\n                 \"item_text\": \"Quit\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -75,6 +85,7 @@\n             {\n                 \"item_key\": \"C\",\n                 \"item_text\": \"Configure Settings\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -91,6 +102,7 @@\n             {\n                 \"item_key\": \"*\",\n                 \"item_text\": \"Sysop Menu\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\n@@ -107,6 +119,7 @@\n             {\n                 \"item_key\": \"?\",\n                 \"item_text\": \"Help\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"\",\n                 \"instance_message\": \"\",\ndiff --git a/install/gfiles/menus/wwiv/qwk.msg b/install/menus/wwiv/qwk.msg\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/qwk.msg\nrename to install/menus/wwiv/qwk.msg\ndiff --git a/install/gfiles/menus/wwiv/qwk.pro b/install/menus/wwiv/qwk.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/qwk.pro\nrename to install/menus/wwiv/qwk.pro\ndiff --git a/install/gfiles/menus/wwiv/sysop.mnu.json b/install/menus/wwiv/sysop.mnu.json\nsimilarity index 88%\nrename from install/gfiles/menus/wwiv/sysop.mnu.json\nrename to install/menus/wwiv/sysop.mnu.json\nindex b049e5d26..4d9907005 100644\n--- a/install/gfiles/menus/wwiv/sysop.mnu.json\n+++ b/install/menus/wwiv/sysop.mnu.json\n@@ -1,14 +1,20 @@\n {\n     \"version\": 1,\n     \"menu\": {\n+        \"cls\": true,\n         \"num_action\": \"none\",\n         \"logging_action\": \"command\",\n-        \"help_type\": \"always\",\n-        \"color_title\": 0,\n-        \"color_item_key\": 0,\n-        \"color_item_text\": 0,\n-        \"color_item_braces\": 0,\n-        \"title\": \"\",\n+        \"help_type\": \"user_choice\",\n+        \"generated_menu\": {\n+            \"num_cols\": 2,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#1\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 1\n+        },\n+        \"title\": \"|#5Sysop Menu\",\n         \"acs\": \"user.sysop == true\",\n         \"password\": \"\",\n         \"enter_actions\": [],\n@@ -17,6 +23,7 @@\n             {\n                 \"item_key\": \"A\",\n                 \"item_text\": \"Allow Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"AE\",\n                 \"instance_message\": \"\",\n@@ -33,6 +40,7 @@\n             {\n                 \"item_key\": \"B\",\n                 \"item_text\": \"Sub Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"BE\",\n                 \"instance_message\": \"\",\n@@ -49,6 +57,7 @@\n             {\n                 \"item_key\": \"C\",\n                 \"item_text\": \"Chain Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"CE\",\n                 \"instance_message\": \"\",\n@@ -65,6 +74,7 @@\n             {\n                 \"item_key\": \"D\",\n                 \"item_text\": \"Dir Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"DE\",\n                 \"instance_message\": \"\",\n@@ -81,6 +91,7 @@\n             {\n                 \"item_key\": \"G\",\n                 \"item_text\": \"Bulletin Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"GE\",\n                 \"instance_message\": \"\",\n@@ -97,6 +108,7 @@\n             {\n                 \"item_key\": \"I\",\n                 \"item_text\": \"Instance Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"IE\",\n                 \"instance_message\": \"\",\n@@ -113,6 +125,7 @@\n             {\n                 \"item_key\": \"J\",\n                 \"item_text\": \"Conference Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"JE\",\n                 \"instance_message\": \"\",\n@@ -129,6 +142,7 @@\n             {\n                 \"item_key\": \"T\",\n                 \"item_text\": \"Text Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"TE\",\n                 \"instance_message\": \"\",\n@@ -145,6 +159,7 @@\n             {\n                 \"item_key\": \"V\",\n                 \"item_text\": \"Voting Editor\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"VE\",\n                 \"instance_message\": \"\",\n@@ -161,6 +176,7 @@\n             {\n                 \"item_key\": \"K\",\n                 \"item_text\": \"Print Votes\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"VP\",\n                 \"instance_message\": \"\",\n@@ -177,6 +193,7 @@\n             {\n                 \"item_key\": \"Q\",\n                 \"item_text\": \"Quit\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"Q\",\n                 \"instance_message\": \"\",\n@@ -193,6 +210,7 @@\n             {\n                 \"item_key\": \"?\",\n                 \"item_text\": \"Display Help\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"?\",\n                 \"instance_message\": \"\",\ndiff --git a/install/gfiles/menus/wwiv/sysop.pro b/install/menus/wwiv/sysop.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/sysop.pro\nrename to install/menus/wwiv/sysop.pro\ndiff --git a/install/gfiles/menus/wwiv/vissys.mnu.json b/install/menus/wwiv/vissys.mnu.json\nsimilarity index 77%\nrename from install/gfiles/menus/wwiv/vissys.mnu.json\nrename to install/menus/wwiv/vissys.mnu.json\nindex 396e8f5a1..5aa3fac1f 100644\n--- a/install/gfiles/menus/wwiv/vissys.mnu.json\n+++ b/install/menus/wwiv/vissys.mnu.json\n@@ -1,13 +1,19 @@\n {\n     \"version\": 1,\n     \"menu\": {\n+        \"cls\": false,\n         \"num_action\": \"none\",\n         \"logging_action\": \"key\",\n         \"help_type\": \"on_entrance\",\n-        \"color_title\": 0,\n-        \"color_item_key\": 0,\n-        \"color_item_text\": 0,\n-        \"color_item_braces\": 0,\n+        \"generated_menu\": {\n+            \"num_cols\": 3,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#1\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 1\n+        },\n         \"title\": \"Visting Sysops\",\n         \"acs\": \"\",\n         \"password\": \"\",\n@@ -26,25 +32,10 @@\n             }\n         ],\n         \"items\": [\n-            {\n-                \"item_key\": \"R\",\n-                \"item_text\": \"Read Messages\",\n-                \"help_text\": \"\",\n-                \"log_text\": \"R\",\n-                \"instance_message\": \"\",\n-                \"acs\": \"\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"readmessages\",\n-                        \"data\": \"\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"Q\",\n                 \"item_text\": \"Quit back to Main\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"Q\",\n                 \"instance_message\": \"\",\n@@ -61,6 +52,7 @@\n             {\n                 \"item_key\": \"?\",\n                 \"item_text\": \"Help\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"?\",\n                 \"instance_message\": \"\",\n@@ -77,6 +69,7 @@\n             {\n                 \"item_key\": \"X\",\n                 \"item_text\": \"Toggle Expert\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"X\",\n                 \"instance_message\": \"\",\n@@ -93,6 +86,7 @@\n             {\n                 \"item_key\": \"L\",\n                 \"item_text\": \"List Files\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"L\",\n                 \"instance_message\": \"\",\n@@ -100,7 +94,17 @@\n                 \"password\": \"\",\n                 \"actions\": [\n                     {\n-                        \"cmd\": \"dirlist~selectdir~listfiles\",\n+                        \"cmd\": \"dirlist\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    },\n+                    {\n+                        \"cmd\": \"selectdir\",\n+                        \"data\": \"\",\n+                        \"acs\": \"\"\n+                    },\n+                    {\n+                        \"cmd\": \"listfiles\",\n                         \"data\": \"\",\n                         \"acs\": \"\"\n                     }\n@@ -109,6 +113,7 @@\n             {\n                 \"item_key\": \"N\",\n                 \"item_text\": \"List New Files\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"N\",\n                 \"instance_message\": \"\",\n@@ -122,25 +127,10 @@\n                     }\n                 ]\n             },\n-            {\n-                \"item_key\": \"1\",\n-                \"item_text\": \"Download Asylum.ZIP\",\n-                \"help_text\": \"Download ASYLUM.ZIP - Free download\",\n-                \"log_text\": \"\",\n-                \"instance_message\": \"\",\n-                \"acs\": \"\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"dlfreefile\",\n-                        \"data\": \"ASYLUMMO ASYLUM.ZIP\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"F\",\n                 \"item_text\": \"Feedback to the Sysop\",\n+                \"visible\": true,\n                 \"help_text\": \"Leave the sysop a note\",\n                 \"log_text\": \"F\",\n                 \"instance_message\": \"\",\ndiff --git a/install/gfiles/menus/wwiv/vissys.msg b/install/menus/wwiv/vissys.msg\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/vissys.msg\nrename to install/menus/wwiv/vissys.msg\ndiff --git a/install/gfiles/menus/wwiv/vissys.pro b/install/menus/wwiv/vissys.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/vissys.pro\nrename to install/menus/wwiv/vissys.pro\ndiff --git a/install/gfiles/menus/wwiv/xfer.mnu.json b/install/menus/wwiv/xfer.mnu.json\nsimilarity index 93%\nrename from install/gfiles/menus/wwiv/xfer.mnu.json\nrename to install/menus/wwiv/xfer.mnu.json\nindex b939b5734..84a54e60c 100644\n--- a/install/gfiles/menus/wwiv/xfer.mnu.json\n+++ b/install/menus/wwiv/xfer.mnu.json\n@@ -1,13 +1,19 @@\n {\n     \"version\": 1,\n     \"menu\": {\n+        \"cls\": false,\n         \"num_action\": \"dirs\",\n         \"logging_action\": \"key\",\n         \"help_type\": \"always\",\n-        \"color_title\": 0,\n-        \"color_item_key\": 0,\n-        \"color_item_text\": 0,\n-        \"color_item_braces\": 0,\n+        \"generated_menu\": {\n+            \"num_cols\": 3,\n+            \"color_title\": \"|#4\",\n+            \"color_item_key\": \"|#2\",\n+            \"color_item_text\": \"|#0\",\n+            \"color_item_braces\": \"|#1\",\n+            \"show_empty_text\": false,\n+            \"num_newlines_at_end\": 1\n+        },\n         \"title\": \"Transfer Menu\",\n         \"acs\": \"\",\n         \"password\": \"\",\n@@ -17,6 +23,7 @@\n             {\n                 \"item_key\": \">\",\n                 \"item_text\": \"Up One Dir (+, ], >)\",\n+                \"visible\": true,\n                 \"help_text\": \"Up One Directory\",\n                 \"log_text\": \">\",\n                 \"instance_message\": \"\",\n@@ -33,6 +40,7 @@\n             {\n                 \"item_key\": \"Q\",\n                 \"item_text\": \"Quit to Main Menu\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"Q\",\n                 \"instance_message\": \"\",\n@@ -49,6 +57,7 @@\n             {\n                 \"item_key\": \"<\",\n                 \"item_text\": \"Down One Dir (-, [, <)\",\n+                \"visible\": true,\n                 \"help_text\": \"Down One Directory\",\n                 \"log_text\": \"<\",\n                 \"instance_message\": \"\",\n@@ -65,6 +74,7 @@\n             {\n                 \"item_key\": \"-\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"-\",\n                 \"instance_message\": \"\",\n@@ -81,6 +91,7 @@\n             {\n                 \"item_key\": \"[\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"[\",\n                 \"instance_message\": \"\",\n@@ -97,6 +108,7 @@\n             {\n                 \"item_key\": \"+\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"+\",\n                 \"instance_message\": \"\",\n@@ -113,6 +125,7 @@\n             {\n                 \"item_key\": \"]\",\n                 \"item_text\": \"\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"]\",\n                 \"instance_message\": \"\",\n@@ -129,6 +142,7 @@\n             {\n                 \"item_key\": \"*\",\n                 \"item_text\": \"List Dirs\",\n+                \"visible\": true,\n                 \"help_text\": \"List Directories\",\n                 \"log_text\": \"*\",\n                 \"instance_message\": \"\",\n@@ -145,6 +159,7 @@\n             {\n                 \"item_key\": \"H\",\n                 \"item_text\": \"Hop to New Dir\",\n+                \"visible\": true,\n                 \"help_text\": \"Enter partial directory name to hop to\",\n                 \"log_text\": \"H\",\n                 \"instance_message\": \"\",\n@@ -161,6 +176,7 @@\n             {\n                 \"item_key\": \"}\",\n                 \"item_text\": \"Up One Conference\",\n+                \"visible\": true,\n                 \"help_text\": \"Up One Conference\",\n                 \"log_text\": \"}\",\n                 \"instance_message\": \"\",\n@@ -177,6 +193,7 @@\n             {\n                 \"item_key\": \"{\",\n                 \"item_text\": \"Down One Conference\",\n+                \"visible\": true,\n                 \"help_text\": \"Down One Conference\",\n                 \"log_text\": \"{\",\n                 \"instance_message\": \"\",\n@@ -193,6 +210,7 @@\n             {\n                 \"item_key\": \"J\",\n                 \"item_text\": \"Select Conference\",\n+                \"visible\": true,\n                 \"help_text\": \"Manually Select Conference\",\n                 \"log_text\": \"J\",\n                 \"instance_message\": \"\",\n@@ -209,6 +227,7 @@\n             {\n                 \"item_key\": \"CHANGEDIR\",\n                 \"item_text\": \"Change Dir\",\n+                \"visible\": true,\n                 \"help_text\": \"Change Directory Select\",\n                 \"log_text\": \"CHANGEDIR\",\n                 \"instance_message\": \"\",\n@@ -222,25 +241,10 @@\n                     }\n                 ]\n             },\n-            {\n-                \"item_key\": \"/S\",\n-                \"item_text\": \"Download File List\",\n-                \"help_text\": \"Download ASCII File Listing\",\n-                \"log_text\": \"/S\",\n-                \"instance_message\": \"Downloading File List\",\n-                \"acs\": \"\",\n-                \"password\": \"\",\n-                \"actions\": [\n-                    {\n-                        \"cmd\": \"downloadfilelist\",\n-                        \"data\": \"\",\n-                        \"acs\": \"\"\n-                    }\n-                ]\n-            },\n             {\n                 \"item_key\": \"F\",\n                 \"item_text\": \"Search Files by Description\",\n+                \"visible\": true,\n                 \"help_text\": \"Search Files by Description\",\n                 \"log_text\": \"F\",\n                 \"instance_message\": \"File Search\",\n@@ -257,6 +261,7 @@\n             {\n                 \"item_key\": \"L\",\n                 \"item_text\": \"List Files\",\n+                \"visible\": true,\n                 \"help_text\": \"Display Available Files in Current Dir\",\n                 \"log_text\": \"L\",\n                 \"instance_message\": \"\",\n@@ -273,6 +278,7 @@\n             {\n                 \"item_key\": \"N\",\n                 \"item_text\": \"New File Scan\",\n+                \"visible\": true,\n                 \"help_text\": \"Scan for New Files\",\n                 \"log_text\": \"N\",\n                 \"instance_message\": \"Scanning Files\",\n@@ -289,6 +295,7 @@\n             {\n                 \"item_key\": \"/A\",\n                 \"item_text\": \"New Files (All Confs)\",\n+                \"visible\": true,\n                 \"help_text\": \"List new files in all conferences\",\n                 \"log_text\": \"/A\",\n                 \"instance_message\": \"Scanning Files\",\n@@ -305,6 +312,7 @@\n             {\n                 \"item_key\": \"S\",\n                 \"item_text\": \"Search by FileName\",\n+                \"visible\": true,\n                 \"help_text\": \"Seach for files by wildcard filenames\",\n                 \"log_text\": \"S\",\n                 \"instance_message\": \"Scanning Files\",\n@@ -321,6 +329,7 @@\n             {\n                 \"item_key\": \"B\",\n                 \"item_text\": \"Batch Commands\",\n+                \"visible\": true,\n                 \"help_text\": \"Batch Menu\",\n                 \"log_text\": \"B\",\n                 \"instance_message\": \"\",\n@@ -337,6 +346,7 @@\n             {\n                 \"item_key\": \"D\",\n                 \"item_text\": \"Download Files\",\n+                \"visible\": true,\n                 \"help_text\": \"Download Files\",\n                 \"log_text\": \"D\",\n                 \"instance_message\": \"Downloading Files\",\n@@ -353,6 +363,7 @@\n             {\n                 \"item_key\": \"U\",\n                 \"item_text\": \"Upload Files\",\n+                \"visible\": true,\n                 \"help_text\": \"You send the BBS a file\",\n                 \"log_text\": \"U\",\n                 \"instance_message\": \"Uploading Files\",\n@@ -369,6 +380,7 @@\n             {\n                 \"item_key\": \"Z\",\n                 \"item_text\": \"Upload to Sysop\",\n+                \"visible\": true,\n                 \"help_text\": \"Upload a file that no one but the sysop can see\",\n                 \"log_text\": \"Z\",\n                 \"instance_message\": \"Uploading Files\",\n@@ -385,6 +397,7 @@\n             {\n                 \"item_key\": \"K\",\n                 \"item_text\": \"Configure File List\",\n+                \"visible\": true,\n                 \"help_text\": \"Config your listplus menus to show what you want\",\n                 \"log_text\": \"K\",\n                 \"instance_message\": \"Configuring File List\",\n@@ -401,6 +414,7 @@\n             {\n                 \"item_key\": \"~\",\n                 \"item_text\": \"List Users\",\n+                \"visible\": true,\n                 \"help_text\": \"Lists users with access to the dir you are currently in\",\n                 \"log_text\": \"~\",\n                 \"instance_message\": \"\",\n@@ -417,6 +431,7 @@\n             {\n                 \"item_key\": \"P\",\n                 \"item_text\": \"Set 'New Files' Date\",\n+                \"visible\": true,\n                 \"help_text\": \"Sets the date the computer will use to determin new files\",\n                 \"log_text\": \"P\",\n                 \"instance_message\": \"\",\n@@ -433,6 +448,7 @@\n             {\n                 \"item_key\": \"Y\",\n                 \"item_text\": \"Your DL Info\",\n+                \"visible\": true,\n                 \"help_text\": \"Display Your Download Info\",\n                 \"log_text\": \"Y\",\n                 \"instance_message\": \"\",\n@@ -449,6 +465,7 @@\n             {\n                 \"item_key\": \"A\",\n                 \"item_text\": \"Archive Commands\",\n+                \"visible\": true,\n                 \"help_text\": \"Enters the temporary archive menu\",\n                 \"log_text\": \"A\",\n                 \"instance_message\": \"\",\n@@ -465,6 +482,7 @@\n             {\n                 \"item_key\": \"E\",\n                 \"item_text\": \"Extract Commands\",\n+                \"visible\": true,\n                 \"help_text\": \"Extracts a file to the archive menu\",\n                 \"log_text\": \"E\",\n                 \"instance_message\": \"\",\n@@ -481,6 +499,7 @@\n             {\n                 \"item_key\": \"V\",\n                 \"item_text\": \"View Archive\",\n+                \"visible\": true,\n                 \"help_text\": \"View an archived file\",\n                 \"log_text\": \"V\",\n                 \"instance_message\": \"\",\n@@ -497,6 +516,7 @@\n             {\n                 \"item_key\": \"T\",\n                 \"item_text\": \"Xfer Defaults\",\n+                \"visible\": true,\n                 \"help_text\": \"Set the defaults for the XFER section\",\n                 \"log_text\": \"T\",\n                 \"instance_message\": \"Xfer Defaults\",\n@@ -513,6 +533,7 @@\n             {\n                 \"item_key\": \"M\",\n                 \"item_text\": \"Move Files\",\n+                \"visible\": true,\n                 \"help_text\": \"\",\n                 \"log_text\": \"M\",\n                 \"instance_message\": \"\",\n@@ -529,6 +550,7 @@\n             {\n                 \"item_key\": \".\",\n                 \"item_text\": \"Print DSZ.LOG\",\n+                \"visible\": true,\n                 \"help_text\": \"Displays Current DSZ.LOG File\",\n                 \"log_text\": \".\",\n                 \"instance_message\": \"\",\n@@ -545,6 +567,7 @@\n             {\n                 \"item_key\": \"R\",\n                 \"item_text\": \"Remove Files\",\n+                \"visible\": true,\n                 \"help_text\": \"Remove Files from Database\",\n                 \"log_text\": \"R\",\n                 \"instance_message\": \"\",\n@@ -561,6 +584,7 @@\n             {\n                 \"item_key\": \"X\",\n                 \"item_text\": \"Toggle Expert\",\n+                \"visible\": true,\n                 \"help_text\": \"Turn novice menus on and off\",\n                 \"log_text\": \"X\",\n                 \"instance_message\": \"\",\n@@ -577,6 +601,7 @@\n             {\n                 \"item_key\": \"?\",\n                 \"item_text\": \"Help\",\n+                \"visible\": true,\n                 \"help_text\": \"Display Menu\",\n                 \"log_text\": \"?\",\n                 \"instance_message\": \"\",\n@@ -593,6 +618,7 @@\n             {\n                 \"item_key\": \"/O\",\n                 \"item_text\": \"Fast LogOff\",\n+                \"visible\": true,\n                 \"help_text\": \"Logoff without showing logoff ansi or other good stuff\",\n                 \"log_text\": \"/O\",\n                 \"instance_message\": \"Logging Off\",\n@@ -609,6 +635,7 @@\n             {\n                 \"item_key\": \"O\",\n                 \"item_text\": \"Normal LogOff\",\n+                \"visible\": true,\n                 \"help_text\": \"Normal termination from the BBS\",\n                 \"log_text\": \"O\",\n                 \"instance_message\": \"Logging Off\",\n@@ -625,6 +652,7 @@\n             {\n                 \"item_key\": \"UPLOAD\",\n                 \"item_text\": \"UL Files Current Dir\",\n+                \"visible\": true,\n                 \"help_text\": \"Upload Local File in Current Dir\",\n                 \"log_text\": \"//UPLOAD\",\n                 \"instance_message\": \"Uploading \",\n@@ -641,6 +669,7 @@\n             {\n                 \"item_key\": \"UPLOADALL\",\n                 \"item_text\": \"UL All Dirs\",\n+                \"visible\": true,\n                 \"help_text\": \"Upload Local Files in ALL Dirs\",\n                 \"log_text\": \"//UPLOADALL\",\n                 \"instance_message\": \"Uploading\",\n@@ -657,6 +686,7 @@\n             {\n                 \"item_key\": \"/T\",\n                 \"item_text\": \"Test Archive\",\n+                \"visible\": true,\n                 \"help_text\": \"Tests integrity of any archive\",\n                 \"log_text\": \"/T\",\n                 \"instance_message\": \"Testing Archive\",\n@@ -673,6 +703,7 @@\n             {\n                 \"item_key\": \"/D\",\n                 \"item_text\": \"Delete BBS Ads\",\n+                \"visible\": true,\n                 \"help_text\": \"Deletes BBS Ads from archive\",\n                 \"log_text\": \"/D\",\n                 \"instance_message\": \"\",\n@@ -689,6 +720,7 @@\n             {\n                 \"item_key\": \"/K\",\n                 \"item_text\": \"Comment Archive\",\n+                \"visible\": true,\n                 \"help_text\": \"Adds COMMENT.TXT to archive\",\n                 \"log_text\": \"/K\",\n                 \"instance_message\": \"\",\n@@ -705,6 +737,7 @@\n             {\n                 \"item_key\": \"/?\",\n                 \"item_text\": \"Slash Commands\",\n+                \"visible\": true,\n                 \"help_text\": \"Display Extended Command Menu\",\n                 \"log_text\": \"/?\",\n                 \"instance_message\": \"\",\n@@ -721,6 +754,7 @@\n             {\n                 \"item_key\": \"W\",\n                 \"item_text\": \"Slash Menu\",\n+                \"visible\": true,\n                 \"help_text\": \"Slash Menu\",\n                 \"log_text\": \"W\",\n                 \"instance_message\": \"Display Extended Command Menu\",\n@@ -737,6 +771,7 @@\n             {\n                 \"item_key\": \"DE\",\n                 \"item_text\": \"DirEdit\",\n+                \"visible\": true,\n                 \"help_text\": \"Dir Editor\",\n                 \"log_text\": \"DE\",\n                 \"instance_message\": \"\",\n@@ -753,6 +788,7 @@\n             {\n                 \"item_key\": \"JE\",\n                 \"item_text\": \"Conf Edit\",\n+                \"visible\": true,\n                 \"help_text\": \"Edit SUBS/XFER Conferences\",\n                 \"log_text\": \"JE\",\n                 \"instance_message\": \"\",\n@@ -769,6 +805,7 @@\n             {\n                 \"item_key\": \"SYSOP\",\n                 \"item_text\": \"Sysop Menu\",\n+                \"visible\": true,\n                 \"help_text\": \"Sysop Functions\",\n                 \"log_text\": \"SYSOP\",\n                 \"instance_message\": \"\",\n@@ -785,6 +822,7 @@\n             {\n                 \"item_key\": \"CONFEDIT\",\n                 \"item_text\": \"Conf Edit\",\n+                \"visible\": true,\n                 \"help_text\": \"Edit SUBS/XFER Conferences\",\n                 \"log_text\": \"CONFEDIT\",\n                 \"instance_message\": \"\",\n@@ -801,6 +839,7 @@\n             {\n                 \"item_key\": \"SORT\",\n                 \"item_text\": \"Sort Dirs\",\n+                \"visible\": true,\n                 \"help_text\": \"Sort Xfer Dirs\",\n                 \"log_text\": \"SORT\",\n                 \"instance_message\": \"\",\n@@ -817,6 +856,7 @@\n             {\n                 \"item_key\": \"RSORT\",\n                 \"item_text\": \"RSort Dirs\",\n+                \"visible\": true,\n                 \"help_text\": \"Sort Xfer Dirs In Reverse Order\",\n                 \"log_text\": \"RSORT\",\n                 \"instance_message\": \"\",\n@@ -833,6 +873,7 @@\n             {\n                 \"item_key\": \"READIDZ\",\n                 \"item_text\": \"ReadIDZ\",\n+                \"visible\": true,\n                 \"help_text\": \"Read in File_id.diz as description\",\n                 \"log_text\": \"READIDZ\",\n                 \"instance_message\": \"\",\n@@ -849,6 +890,7 @@\n             {\n                 \"item_key\": \"MOVE\",\n                 \"item_text\": \"MoveFiles\",\n+                \"visible\": true,\n                 \"help_text\": \"Move File(s) to other areas\",\n                 \"log_text\": \"MOVE\",\n                 \"instance_message\": \"\",\n@@ -865,6 +907,7 @@\n             {\n                 \"item_key\": \"AE\",\n                 \"item_text\": \"AllowEdit\",\n+                \"visible\": true,\n                 \"help_text\": \"Run AllowEdit\",\n                 \"log_text\": \"AE\",\n                 \"instance_message\": \"\",\n@@ -881,6 +924,7 @@\n             {\n                 \"item_key\": \"UPLOADFILE\",\n                 \"item_text\": \"UploadFilesBBS\",\n+                \"visible\": true,\n                 \"help_text\": \"Upload from FILES.BBS\",\n                 \"log_text\": \"UPLOADFILE\",\n                 \"instance_message\": \"\",\n@@ -897,6 +941,7 @@\n             {\n                 \"item_key\": \"REN\",\n                 \"item_text\": \"RenameFiles\",\n+                \"visible\": true,\n                 \"help_text\": \"Change File Info\",\n                 \"log_text\": \"REN\",\n                 \"instance_message\": \"\",\n@@ -913,6 +958,7 @@\n             {\n                 \"item_key\": \"RN\",\n                 \"item_text\": \"RemoveNotThere\",\n+                \"visible\": true,\n                 \"help_text\": \"Remove N/A Files From List\",\n                 \"log_text\": \"RN\",\n                 \"instance_message\": \"\",\n@@ -929,6 +975,7 @@\n             {\n                 \"item_key\": \"C\",\n                 \"item_text\": \"RequestChat\",\n+                \"visible\": true,\n                 \"help_text\": \"Call SysOp to Chat\",\n                 \"log_text\": \"C\",\n                 \"instance_message\": \"Requesting Chat\",\ndiff --git a/install/gfiles/menus/wwiv/xfer.msg b/install/menus/wwiv/xfer.msg\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/xfer.msg\nrename to install/menus/wwiv/xfer.msg\ndiff --git a/install/gfiles/menus/wwiv/xfer.pro b/install/menus/wwiv/xfer.pro\nsimilarity index 100%\nrename from install/gfiles/menus/wwiv/xfer.pro\nrename to install/menus/wwiv/xfer.pro\n"
  },
  {
    "path": "install/docs/whatsnew.txt",
    "content": "==============================================================================\n                           WWIV BBS What's New List\n                 Copyright 1999-2023, WWIV Software Services\n==============================================================================\nLegend (starting with 5.3)\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n! Breaking change (you may need to do something)\n+ New feature\n- Feature removed\n* Change or cleanup\n\n*** Please make sure you get the new files out of the install archives\n    like gfiles.zip, menus.zip, etc.  We're adding new files and each\n    new wwiv update may contain new files.  I'd recommend using unzip -n\n    so that you don't overwrite any files (or use winmerge or meld\n    to compare new changes)\n\nWhat's New in WWIV 5.9.0 (2023)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* \n\n\nWhat's New in WWIV 5.8.0 (2023)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Removed duplicated code for LastCallers() from lilo.cpp. (#1501)\n* Fix cosmetic bug in Scan Message Titles in Traditional Reader mode (#1505)\n* Added InterBBS LastCallers to display laston.txt if it exists in network directory.\n* Fixed logoff matrix to squelch INFO error from appearing in logs.\n* Need comments on printfile and friends on how to use them. (#1502)\n+ Feature request: ANSI display speed (#1479)\n  You can now add a pipe expression like:\n  |{set bps 2400}\n* Birthday date not displayed correctly on newuser account (#1509)\n* Crash in PhoneNumbers::Load when phonenum.dat is empty (#1511)\n* Show preview of auto-message before confirming save (#1512) (#1510)\n+ Add max age option for importing FTN messages (#1423)\n+ basic debugger with stepping works (use github.com/wwiv/wwivdbg for client)\n* Fix Chains display of sponsor lists first sponsor twice (#1513)\n* Display of Chain sponsor no longer duplicates 1st entry (#1514)\n* Only rename pending files if the 2nd digit is not a letter. (#1518)\n* Create subscriber file as needed when it does not exist. (#1519)\n* Fix Win32 on 10, when in BE, modify Network, space to Quit does not. (#1521)\n* Fix do_wwiv_ugprades() function misspelled in wwivconfig (#1523)\n* Chains fixes displaying CHAINS_NOEXT and switchable Chain Usage display (#1528)\n* Make chain usage display configurable from wwivconfig (#1527)\n* Clean up non-ANSI displays for CHAINS (#1530)\n* String passed to System call to execute \"eprogs.net\" externals corrected. (#1533)\n+ Implement support for epreproc.net (#1531)\n* Added precision to formatting in chains display (#1535)\n* Limit loc string to avoid header overflowing and other minor fixes (#1537)\n* Display more of location string when there is room. (#1542)\n* Check that file areas exist in most xfer functions (#1551)\n* Use higher value for max_view_lines and max_view_columns instead of lower value (#1543)\n* Fix off-by-one error in message reporting network value range (#1545)\n* Delete curses_out in the places we don't on exit (#1539)\n* network2 moves \"deleted\" packets to dead.net because identifed as UNKNOWN type. (#1540)\n* wwivutil print fixes crash and also autodetect screen size (#1555) (#1556)\n* Fix file::set_length from failing when the file is open\n* network2 doesn't use the DISALLOW.NET file (#1541)\n* net: only skip 146 bytes for method 1\n* minor cosmetic fixes in WFC and message date header display (#1565)\n* Cleaned up output of file area tags and networks in diredit (#1568)\n* network2 handle_sub_add_drop_resp fix, and cosmetic networkf fix (#1571)\n! Don't call out to nerd.dk for country blocking, it's broke (#1576)\n* Make fsed/view.cpp use default screen settings for max values (#1579)\n* Cosmetic: add OS to FTN tearlines and fixes to msgscan prompt and legacy header display (#1585) \n* Restored '@' reply to a different address in HandleScanAutoReply in both Traditional Reader and Full Screen Reader (#1572)\n* Clear title before 'P'osting a new message in msgscan/titlescan (#1588)\n* Removed dangling RE: with title for new posts (#1590)\n* Replaced : with ; in wwiv.ini for uniformity and so ini file parsers don't gag. (#1586)\n* Make Xfer menu display toggleable with eXpert mode option on new installs. (#1578)\n\n\n\nWhat's New in WWIV 5.8.0 (2022)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* A couple of renames to make terms make more sense\n    * PacketFileReader -> NetMailFile (This is how the net tech docs calls it)\n    * Packet -> NetPacket (since each stored message is a wwivnet packet, not the container)\n* Start to use NetMailFile vs. read_packet\n* Fix issue of pause missing in chains.json. (#1475)\n* Fix Unable to change password in Defaults menu. (#1483)\n* Clear FSED Flag if the caller disables ANSI. (#1484)\n  - thanks to xenos for the fix\n* Make CL345 compile on GCC versions >10, at least 11\n* Update cl345 to us sched_yield vs. pthread_yield\n  Newer linux distributions with newer glibc may not have\n  pthread_yield anymore since it's been deprecated forever.\n* Fix WFC cosmetic issues (#1485)\n* Fix Network3 crashing repeatedly. (#1481)\n* default to ZIP if we can't determine the archiver to use for networkf\n+ Start of support for lnet. It's now part of the 5.8 build\n* Set the default value when inputting the email message to read properly. (#1478)\n* Only set a dir if there is one to set. (#1482)\n* Mark messages deleted in network2 when processing local.net (#1488)\n! Update docs to use pull --recurse\n  * Please be sure to pull new builds using --recurse\n* fix some vs2022 analysis warnings\n* Modernize how cmake sets warning levels (makes MSVC warnings cleaner)\n* ScopeExit should act like GSL final_act/finally (#1375)\n* WWIV source no longer using iosteams for displaying user text.  Additionally\n  adter almost 23 years, many function names on the Output class (bout) have been\n  renamed back to the 4.x naming.\n  * Color -> ansic\n  * SetColor -> setc\n  * GotoXY -> goxy\n  * bputch ->outchr\n  * puts -> outstr\n  * puts + \\r\\n -> pl\n  * make sysoplog(...) back into a function and not a class for iostreams\n  * format -> print (print is new, but matches std::print and is a better name\n    than format)\n* default wwiv main menu is missing //QWK (#1492)\n* //QWK menu for sysop doesn't list (*) config menu (#1493)\n* wwivutil subs import  - update nSUBNAME.net when using import (#1495)\n* move code to import subs into sdk so it can be used by developers\n+ LNet: Add ability to (W)rite packet to new file, and added PAUSE on page\n+ Initial cut at support to auto add missing fido echos\n* /s not working in fsed (#1378)\n+ Add a new option to wwivfsed \"--wrap\" to turn off WWIV style wrapping.\n* writing to dead net should clear the list_len and list (#1496)\n* wwivutil: Make --start and --end a bit more robust in inputs it accepts to wwivutil messages dump\n* Fix wrapped lines in fsed reader (#1498)\n* Fix pause sometimes needing 2 key presses (#1499)\n+ Need way to add newly created auto-imported subs to a conference (#1500)\n  Add support for a new \"conf = CONFERENCE LETTERS\" line into the inport.ini file\n  used by both auto importing of subs from FTN echos, as well as the\n  \"wwivutil subs import\" command.\n+ initial cut of functioning default colors for non-wwiv messages\n\n\n\nWhat's New in WWIV 5.8.0 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Use vcpkg for dependencies where possible vs. git submodules\n* Added SleepFor to the Clock class\n* Don't use u8string anywhere since it's a shipwreck (c++20 pre-work)\n* Remove EMPTY_FIDO_ADDRESS and use std::optional more.\n* Add Config into SdkHelper so it can be more easily used in SDK tests.\n* Use SOCKET and INVALID_SOCKET consistently everywhere.\n\n\n\nWhat's New in WWIV 5.7.2 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* Fixed: Garbled display while connected locally (probably encoding issue) (#1467)\n* Update to netfoss 1.25\n* default to 1 when ansi callout is off\n* Update dependencies to latest fmt::fmtlib, pdcurses, my_basic, and googletest.\n\nWhat's New in WWIV 5.7.1 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+ Telnet support from wwivd.  Use @telnet:HOST:PORT for the telnet command\n  in the wwivd matrix setting for that BBS entry.\n    ┌─────────────────────────────────────────────── Matrix Config: mystic ┐\n    │            Key: m                                                    │\n    │           Name: mystic                                               │\n    │    Description: Mystic BBS (MIS)                                     │\n    │    Working Dir:                                                      │\n    │ Telnet Command: @telnet:localhost:2300                               │\n    │    SSH Command:                                                      │\n    │   Require Ansi: No                                                   │\n    │     Start Node: 1                                                    │\n    │       End Node: 10                                                   │\n    │     Local Node: 0                                                    │\n    └──────────────────────────────────────────────────────────────────────┘\n+ Added scripts for using QEMU online.  Tested DOS doors under QEMU/FreeDos\n  on Linux.\n+ WWIV builds on OS/2 under GCC 9.2, but doors won't run.\n* Incorrect BY: line when posting to a Fido sub (#1460)\n* Don't let a sub go to position 0 (#1457)\n* regions and zip-city not unzipped with default install on linux (#1455)\n+ STDIO support now works on Win32. It works when WWIV is using either\n  sockets or pipes to talk to wwivd.\n+ OS/2 support is here if you build it yourself.  Also included is\n  WWIVFOSS which will convert FOSSIl into Named Pipe calls for telnet\n  ability from WWIVd.\n  * Use -XP for (PIPE) instead of -XS or -XT to use it.  -H is obsolete\n    when using PIPE since the pipe name is hard coded to be\n    \\\\.\\PIPE\\WWIV# and \\\\.\\PIPE\\WWIV#C where # is the node number.  \n+ WWIVFOSS is now bundled with the OS/2 cpack target.\n+ WWIV supports listening on either a TCP local socket port or an UNIX\n  socket for the door to connect back to instead of using socket passing\n  ala DOOR32 style.  This works on both Windows and UNIX.  Please note that\n  Windows 10 17063 or later is needed for AF_UNIX support on Windows.\n  This is handy for using QEMU from within BBS to run DOS based doors.  \n  The port number or socket path will be available as a new (%Z) replacable\n  parameter from chainedit when using the selected chain execution mode.\n\n\n\nWhat's New in WWIV 5.7.0 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+ Improve autoblocker in wwivd (#1359)\n  WWIV's autoblocker now gives variable automatic blocking for fixed\n  time periods 4 times before adding a permanent ban to badips.txt.\n  The way you trigger the blocking is to have more than X connections within\n  Y seconds, where X and Y are defined in wwivconfig's wwivd blocking page.\n  ** You may want to delete badip.txt or rename it to something else, it likely\n     has more systems in it than you intended to block **\n* Removed the following from wwiv.ini:\n  CHECK_DUP_PHONES       = N \n  HANGUP_DUP_PHONES      = N \n  The first never worked, therefore neither did the second and also isn't really\n  need anymore.\n+ Added new setting in wwivconfig for fine grained newuser info.\n! Add granular control over which profile information must be provided by new users (#845)\n  By default wwivconfig should match what you had in wwiv.ini, but please take a look\n  also please remove the following from wwiv.ini since they are confusing and \n  these values are now controlled by wwivconfig:\n  * EXTENDED_USERINFO\n  * NEWUSER_MIN\n  * TEMP_DIRECTORY\n  * BATCH_DIRECTORY\n  * NUM_INSTANCES  \n  * WFC_SCREEN\n+ Add new page in wwivconfig for setting which fields are required, optional, and unused.\n+ Set newuser to internal fsed not first external editor\n+ Added chain pause functionality (#1379) - thanks to DMXrob\n* Fix IsPhoneRequired for login. We don't have NEWUSER_MIN anymore.\n+ Added yourinfo.msg to the list of gfiles/ wwiv uses.\n  This will replace the internal YourInfo hardcoded info that is displayed\n   if this file exists, otherwise we'll fall back to the hardcoded one.\n+ Added @z macro to display the upload/download ratio for the user.\n+ When toggling expert mode, WWIV will now display the status of expert\n  mode or not unless \"quiet=on\" is passed to the menu command as data.\n* Still allow HandleControlKey to work with bgetch_event. (#1382)\n* Added ACS user.guest, and cleaned up menu and newuser routines a bit.\n* Let KEY_SSAVE behave like control-Z (#1360)\n+ Added user.validated to acs. (#1387)\n+ better asv from valuser command (#1388)\n* Fix automessage menu: (A)uto reply not working in default menus (#1389)\n* Don't add RE: line to email messages.\n+ Fix changing user settings for online user gets overwritten (#960)\n* Improve display of 'I' information and FTN networks (#1392)\n* Fix node instance messages should use new scratch dir not data dir (#1391)\n* Don't check for dupes on FTN emails. (#1395)\n* Full screen reader not displaying color right when previous line ends in ^A (#1399)\n* System crash when setting Transfer QSCAN (#1394)\n* Fix PAUSE prompt from loosing current attribute. (#1398)\n+ Add FTN network data in net.log for FTN using Fake Network node # (#1393)\n* Fix control-a,d,f key handling in fsed.\n* Run network3 automatically after editing a network\n! --title must be specified for wwivutil email add\n* Modem speed in last callers list (#1381)\n* Having no networks to load is not an error anymore. (#1400)\n+ Added new wwivconfig page (under (G)) for configuring system toggles\n    * Remove FAST_TAG_RELIST from wwiv.ini, it was not useful.\n    * Removed CLOSE_XFER from wwiv.ini, it was no longer useful\n    * Removed SETLDATE from wwiv.ini, it's always true.\n    * Removed FORCE_NEWUSER from wwiv.ini. It was never used and the variable\n      for it was removed in 5.0 build 14 (around 2001)\n    * Removed CHAIN_REG, now that all of the data is in chains.json, there's\n      no need to have this variable (which just kept chain.reg from being used)\n    * Added system toggle for showing last network connections at logon.\n    * Removed EXTENDED_USERINFO from wwiv.ini, it's always true.\n    * Removed NEWUSER_MINfrom wwiv.ini, it's not used anymore.\n    * Removed OFF_HOOK from wwiv.ini, it wasn't used anymore.\n* Don't store intermediate reference to pass to WWIVMessageApi constructor. (#1402)\n+ new files fs_msgread.msg and fs_msgscan.msg control the headers for the full\n  screen message reader and title list.  Lots of new pipe expression variables\n  are available and documented under \"Displaying Text\" in WWIV's online \n  documentation.\n*  Last nework connections no longer displaying (#1403)\n! Removed inetaddr.dat.  The data is already in user.lst\n* Fix readmail when you have a message header template\n* Removed MAIL_WHO_LEN from wwiv.ini, it didn't work well.\n* Fixed qscan display error on expert mode (#1405)\n* Fixed issue where setting a date < 1970 can crash the bbs\n* Add new setting to allow outbound pipe codes for ftn messages. (#1407)\n* Work around large filesystems failing the File::freespace_for_path call (#1408)\n* HeartCodeFilter needs to handle pipe codes too (#1410)\n+ Let ini files support multi-line strings like TOML does (#1411)\n    * Add support for a multi-line ini value. Example\n    FOO=\"\"\"This\n    is a multline\n    value\n    \"\"\"\n    * If value is quoted using \", then strip the surrounding quote characters.\n* Progress on merge language + menusets together #1414.  Languages and menus are\n  now 1-1 vs. 1 language to N menus.  This simplifies many things in the BBS and \n  better matches how folks expect to change these together.\n! move menus to top level - Menus are now peers to gfiles/ in the bbs directory\n  layout.  Please consider moving yours (mv gfiles/menus menus) and then updating\n  the path using wwivconfig.\n+ Added strings for yes, no, quit, NN: and PW:\n+ Support system location and name display for FTN networks too when the\n  nodelist is available and the nodelist base set for the network in wwivconfig.\n* System name and location not showing up for your own system (#1419)\n* logs dir isn't created automatically on new install (#1417)\n* menus.zip is not unzipped during new install (#1416)\n* provide a location/sysname on local posts to wwivnet subs\n* use 5d address when presenting M_ADR in binkp\n+ Broke out State entry from city state to make it clearer and easier. (#1430)\n* Use unique cram challenge (#1429)\n* Add validation text for FTN address\n+ binkp can't answer with mutliple AKAs presented (#1426)\n! |{pause} is now |{pausescr}\n* Fix Last callers not displaying correct information (#1428)\n* name_and_number() should be proper case not upper cas\n* Move to next sub? The default is No and should be yes. (#1431)\n* Unable to validate new users while they are online (#1432)\n* increase default dir and sub size to 500/5000\n+ need \"bbs\" pipe expressions (#1413)\n+ Added new pipe expressions, sleep, backprint, and spin\n+ Added rainow pipe expression (#1427)\n* Added many more {user.xxx} variables. Please see docs.\n* Added help on how to save a message created in the internal editor (#1436)\n* Errror on resize_file: 32; (#1438)\n* Added ability to format pipe variables\n* Fix handling of addresses mixed with and without domain names\n* Problems emailng FTN networks from BBS (#1439)\n* Log says user \"hung up\" when user logs off (#1440)\n+ Add FTN nodelist support into network bbs list viewer (i.e. (B)bsList then (N)etwork. (#1231)\n+ After using (B) to bypass a sub (from the reading prompt), don't ask if we want to post (#1437)\n+ |{if expr yes no fmt} can now take a format (like pipe variables now)\n! Added new strings FIXED_YES and FIXED_NO.\n+ Added new pipe expression |{yesno \"expression\" \"fmt\"}\n* WWIVNet BBS list not working (#1441)\n* Fix crash in displaying a generated menu in wwivconfig\n! Defaults is now a menu, not a built-in command by default, please make sure\n  to update your wwiv menus with the new defaults menu and update main menu.\n+ You can now filter text in wwivconfig listboxes by pressing / and then \n  entering the text to filter by.\n* add ways to see and change personal info in defaults (#1390)\n* Fix crash in listplus after ~130 files\n* Support interestingly formed Tic line with addresses (#1445)\n* reset the color to |#0 at the end of each kludge line (#1446)\n+ When sending FTN emails, try to match by zone and not ask which network to use.\n* delete /Z and /S from default menus, they don't exist anymore\n+ Need global menu (#1415)\n* Don't try to parse FTN addresses in 4.x\n+ Check ACS on menusets, and only show ones that are available\n+ Initial cut at support for getting the screen size from the remote terminal.\n* FTN: just stop on short read error, don't keep retrying bad packets\n* litebar width should be full screen not capped at 80 (#1450)\n+ user:menus should select the menuset for the caller if only one matches (#1451)\n* throwing exception while scanning new messages (#1453)\n* screen size detection broken at local console on linux (#1454)\n* fullscreen view, bottom bar gets drawn on same line as command line (#1449)\n* Fixed wwivconfig not showing 1st menu item.\n+ Filenames can now be of the form: basename.MIN_NUM_COLS_NEEDED.extension for dispay.\n  example: logon.132.ans or fs_msgread.132.msg (#1456)\n\n\nWhat's New in WWIV 5.6.1 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+ Added wwivutil users asv command.  This can increase user attributes to match\n  those specified in the Auto Validation list defined in wwivconfig.\n* Don't MPL on mmkey long text input. It makes the UI go wonky\n* Don't crash when doing a title scan when the subtype is not 2.\n* fix title display for curses windows with longer titles than contents\n* Add wwivutil users asv\n* fix display of autoval in wwivconfig\n* Add more error handling (#1354)\n* Check conf not area tags when checking for empty conf list. (#1358)\n* Write out BUSY reason when returning BUSY from WWIVd. (#1357)\n* Use - not / when calling network on UNIX (#1366)\n* Add AR/DAR to usereditor. (#1370)\n* Save statusrec after general page in wwivconfig (#1373)\n* Use size of dirs in conference, not all dirs to find last dirnum. (#1371)\n\nWhat's New in WWIV 5.6 (2021)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n! config.dat has been replaced with config.json.  wwivconfig will \n  automatically upgrade to this new file.  networking utils and wwivutil will\n  work with either.\n* Now binkp will log \"RECV\" messages too and not just send.\n* BinkP is quicker to notice the other side has disconnected and respond.  \n* Better handling of status.dat, making it less likely to get corrupt.\n+ Added help for ACS expressions in the places where WWIV prompts for the\n  sysop to enter one for access control. (#1333)\n+ Send SSM's to sysop when receiving files from wwivnet (like net37)\n+ Added new \"wwivutil instance\" command for displaying instance\n  metadata.\n* Finish instance SDK class and use it in the BBS (#1335)\n* Fix Color description messed up in defaults for color 4 #(1340)\n* In defaults move (4) to a new line of it's own (#1341)\n* More fixes and work on internal zmodem.  Fixed uploads with either one\n  or more IAC codes embedded in the file.\n\nWhat's New in WWIV 5.6 (2020)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+ Remove WSL stanzas, that makes MSVC 16.6 and newer unhappy (#1268)\n* Update instance.dat when a node exits. \n+ Implemented WWIVfsed. WWIV's internal FSED as an external.\n! Arguments on linux must start with '-'' and not '/', this is also\n  how standard arguments work on Linux.  Windows still accepts arguments\n  either like \"/N\" or \"-N\". (#1273)\n* Don't throw an exception when no dirs are visible. (#1276)\n+ Support for Ubuntu 20.04 LTS has been added. (#1264)\n+ dd email address to useredit in wwivconfig. (#1258)\n! Removed InternetEmail menu command, it didn't work without PPP project \n  for sending internet emails.  Also the rest of the BBS doesn't use \n  acct.ini anymore.\n* Fix crash with subs list and only 1 conference.\n+ Fix TO handling in the SDK. Setting the TO name will now either\n  add FidoAddr for FTN subs, or BY: lines into the message text.\n+ Added MessageOptions::add_re_and_by_line to add the RE: and BY: lines to \n  the message like WWIV does when you reply to a post since 4.22. (#1285)\n* BinkP: Wait to send password until we have the remote address. (#1289)\n* Updated to CryptLib v3.4.5 with SSH fixes (#1288)\n* Don't use default \"%z\" for tzutc klduge (Fixes TZUTC bug with positive TZ)\n! Move wwivutil messages list to wwivutil subs areas.\n* Fix crash when deleting a tagged file. (#1282)\n* fixed , not working from WFC\n+ Add wwivfsed to the wwiv archive. (#1275)\n+ Implement a max_backups setting in the bbs. (#1278)\n+ add netdat support to network stack\n+ Set Uploaded By: to WWIV TIC Processor (#1279)\n+ Add setting in wwivd for working directory for launch the bbs (#1269)\n* Don't check for hangup on the network programs, user isn't online\n* Improve pending list.\n* new WWIVbasic packages:\n** wwiv.io.file\n** wwiv.time\n! Fix netdat.log formatting and don't delete old ones, just move them\n  to the logs directory.\n+ Add new option for wwivd to launch network and bbs minimized\n* Don't allow filenames >8chars to save to 4.22 format.\n+ Initial rough cut of backbone.na importer.\n  Here's how it works:\n  * Create import.ini file with default values for the subs\n    that will be created from importing them from a\n    BACKBONE.NA file.\n  * Run \"wwivutil subs import\" to do the import.\n\n  Example Command Line:\n  wwivutil subs import --defaults=import.ini FSXNET.NA\n\n  Example import.ini\n  ```\n  [backbone]\n  post_acs = user.sl >= 20\n  read_acs = user.sl >= 10\n  maxmsgs = 5000\n  net_num = 2\n  uplink = 21:2/100\n  ```\n* Rebuild names.lst on useredit changes.\n* Reset the SIGCHLD signal handler on networkc and networkf.(#1297)\n+ Support USER data in addition to GLOBAL in wwivbasic. (#1296)\n* Fix Disconnect on linux while in STDIO door does not exit (#1293)\n* Always add MSGID, even on netmails (#1295)\n* Fix age display in newuser login.\n+ Update subs and dirs to use ACS\n* Fix crash with subs list and only 1 conference. (#1292)\n* Validate FTN Address against nodelist when sending emails (#1232)\n! Some WWIVbasic packages may be selectively enabled and disabled,\n  by default wwiv.io.file and wwiv.os will be disabled. Please use\n  wwivconfig (menu item R for Scripting Config) to enable these.\n+ For those writing unit tests for WWIVbasic, added macros \n  BASIC_ASSERT_EQUALS and BASIC_ASSERT_NE on the C++ side and\n  ASSERT.NE in WWIVbasic\n+ Added the WWIV.OS package (not enabled by default in WWIVconfig)\n+ Initial start of WWIV 5.6 style menus.  These are JSON vs. binary\n  on disk, and support multiple actions to be invoked per menu\n  command, also on entry and exit.\n+ ACS Improvements:\n  * Added user.sysop, user.cosysop meta values.\n  * Implemented previously documented user.regnum\n  * Added variables true, false with values as you expect.\n* Require cosysop for netdatlog (#1291)\n* Fix net.log date format. (#1307)\n* Introduce a SubDialog class to use for all SubDialogs in wwivconfig.\n  * This allows fixing the inconsistent key handling that exists\n      with pressing escape after exiting the dialog.\n  * This allows fixing the inconsistent experience where some dialogs\n    auto-open when cursoring over them (unexpectedly), while others\n    properly wait for an ENTER keypress.\n* Fixed A couple of quirks with netdat.log\n+ Implement \"(F)ind text\" in the full screen message reader\n+ update fs msg reader help text to include (F)ind\n+ Add SYSTEM_BPS to wwiv.ini to emulate a BPS for displaying files.\n+ Add --bps option to wwivutil print\n  This emulates a bps rate when displaying the file.\n* Fixed numerous issues in the conference system.\n  conference list is now stored in data/conference.json\n  conference bindings is stored with subs and dirs.\n* UI for editing conference binding has been improved and is now also \n  available from subedit and diredit.\n* Fix Ar checking when one side is empty. (#1310)\n+ More work on BPS and pause control\n    * Added pause=[on|off|start|end] to printfile menu command\n    * This works with printfile_random too.\n    * Added bps=<bps> to printfile menu command\n    * Changed system_bps to impact all of the BBS, and not just\n      the file printing.\n+ Experimental start of |{xxx} expression support.\n  So far here's what we have:\n  Expressions:\n    |{set pause=on}\n    |{set pause=off}\n    |{pause}\n    |{set lines=0}\n  Feedback welcome, the syntax is still in flux, trying to see what\n  works well and can grow in the future and still make sense.\n+ Convert wwiv heart and user color pipe code to standard pipe code when\n  sending the message as an FTN message (#1235)\n* fix crash with wwivconfig --initialize\n* Attempt to fix netmail issues with points. (#1312)\n  * Add TOPT and FMPT kludge lines into netmail.\n  * Don't include the point number in INTL kludge lines\n+ Ask if still wants to send ftn netmail when node doesn't exist. (#1232)\n+ Add ability to copy menu to a new name in wwivconfig menu editor\n+ Added integrated support for NetFoss. (#1257)\n  Here's how to use it:\n  * Download netfoss and unzip it to \\wwiv\\netfoss (assuming that \\wwiv is\n    where wwiv is installed).  if you want it in some other directory you can\n    use the wwiv.ini directive NETFOSS_DIR to pick a different location.\n  * Edit a chain, adn change the exec mode to \"Integrated NetFOSS\"\n    example:\n    F) Exec Mode:     Integrated NetFOSS\n\n    That's it, you do not need to edit the commandline to specify a path to\n    the NF.BAT file, nor edit it for your environment. WWIV will create a\n    nf.bat in the node's temp directory every time it invokes a chain or\n    editor using the integrated netfoss support. WWIV will execute:\n    \"nf.bat <commandline entered>\"\n* Don't let mouse movement freeze console.\n+ Use UTF-8 for local display (#881)\n  WWIV always outputs local text using UTF-8 now on all platforms, if you\n  had previously changed your codepage for your terminal app to IBM850\n  or IBM437 or Windows-1252 please change it back to UTF-8 which is the\n  default.  This doesn't affect what is sent over the socket to remote \n  users, just the local display.\n+ Added Option for Windows doors to use console codepage OEM437 (#1313)\n! QWK menu is now it's own menu.  You should update the main menu to\n  call cmd: \"MENU\" data: \"qwk\", and copy over the qwk menu and prompt\n  from the gfile.zip in the distribution.  also data/qwk.cfg can be\n  safely deleted once you see qwk.json has been created when you use\n  the sysop menu or qwk door.\n  There are several new menu commands for handling QWK, so you can \n  embed them into other menus:\n    qwk_upload, qwk_download, qwk_user_config, and qwk_sysop_config\n* Also refreshed the default menus and prompts to use pipe macro codes\n  and wwiv color pipe codes vs. standard color codes.\n* QWK: Fixed email conference numer from being wrong whenyou have other \n  messages.\n* QWK use wwiv file io everywhere vs POSIX IO calls.\n* preopen subs for mail packing and subslist.\n  (This gives us a 10-20x speedup on both)\n+ added qwk defaults as (N) to defaults\n* Update GFiles, Network packet configs, and qwk config. (#1315) (#1316)\n* Switch install location to /opt/wwiv in 5.6 for unix (#1263)\n* Fixed min_k setting for FTN network auto callout\n+ Added ability to preview menu in wwivconfig\n+ Moved bbslist into it's own menu (bbslist)  (#405)\n+ Validate ACS and display errors in wwivconfig.\n  Currently only the menu editor has ACS expressions that are\n  editable in wwivconfig, but the framework is in place should\n  others arise in the future\n* Fix mmkey for file areas. (#1323)\n* don't wait for key when checking if there is a key (#1324)\n* Fixed issue where logging in and there's less than 2 subs, wwiv will \n  crash. (#1325)\n+ Adds a wwivutil email command similar to wwivutil messages. (#1329)\n  It can dump, add and delete emails.\n\nWhat's New in WWIV 5.5.1 (2020)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Fix age display in newuser login.\n* Always add MSGID, even on netmails (#1295)\n* Fix crash with subs list and only 1 conference. (#1292)\n* Fix crash when deleting a tagged file (#1282)\n* Don't check for hangup on the network programs, user isn't online\n* Remove WSL stanzas, that makes MSVC 16.6 and newer unhappy (#1268)\n* Fix install.sh script for unix. (#1261, #1262)\n* Fix formatting for non-full screen reader (#1250)\n* Fix Disconnect on linux while in STDIO door does not exit (#1293)\n* Don't allow filenames >8chars to save to 4.22 format. (#1306)\n\nWhat's New in WWIV 5.5 (2020)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Change message of warning from inactivity. (#1197)\n* Less screen redrawing in full screen message viewer for both\n  viewing messages and selecting messages.\n* Fixed //QWK from crashing\n+ Merge pull request (#1204). You can now have a LOGOFF and CLEANUP command\n  in WWIV.INI to execute at logoff time, or post-logoff time to perform\n  any necessry post-user cleanup.\n* Fixed inputting WWIV registration number in (D)efaults (#1205)\n+ Initial cut of wwivutil net send command:\n    This command will send the last few posts to another system. The\n    command line arguments are modeled closely from those used by AUTOSEND.\n! Use _ and not - in flag names for consistency\n+ Added --start-date and --end-date to wwivutil messages dump\n* Fix crash saving email when you have no networks defined\n* Fixed a typo in wfndfile (#1200)\n* Update copyright to 2020\n* Fix output display problem for uint8_t in UserEditor. (#1199)\n! debug.sh has been renamed to cmake-config.sh since with the cmake \n  Ninja generator is multi-config so the config is only used when\n  invoking cmake --build, not during generation time.  Updated the build\n  scripts and documentation to reflect this.\n+ Documented install-prereqs.sh for debian installations. This makes it\n  easy to install the requirements to compile wwiv.\n+ File transfers now work on case sensitive file systems.  Please make sure\n  that all of the files in the file transfer section have filename in lower\n  case on disk.\n* default unzip commandlines now overwrite by default, fixing a pause on\n  processing file_id.diz.\n+ The WWIV SDK now includes support for file areas, file lists, and dsz\n  log file parsing (minimal).\n! Log files from the unit tests are now under ${TEMP}/wwiv_test_out by\n  default and not  ${TEMP}\n+ wwivutil files list will now also display extended file descriptions\n  in addition to short ones.\n+ wwivutil files delete will also delete extended descriptions.\n* Internal ZModem performance is 5-10x faster.\n* dirs.json is now the source of truth for directory data (before, dirs.dat\n  was the source of truth.  WWIV will automatically convert dirs.dat into\n  dirs.json the first time it encounters dirs.dat without dirs.json.\n* Fixed bug where callouts were not happening as expected from wwivd due to \n  the list of networks not loading sporatically.\n+ TIC support for receiving files from FTN networks is now available.  To\n  use this feature and set a default TIC directory to receive tic files into\n  and then enable TIC processing in wwivconfig for your FTN network\n  and then edit the directories to specify the correct \"FTN Area Tag\" for\n  the allfix file echo tag name.   After that networkc should automatically\n  move the files into the WWIV file areas specified.\n! Removed ArchiveMenu and TempExtract menu commands.  Please remove these\n  from your menus if you have them.\n+ \"bbs -o\" will not list the available menu commands for WWIV's menu editor.\n   menu.txt is now generated from the BBS output.\n   bbs -oc will group by category (once tagged), and bbs -om (or -ocm) will\n   output the text in markdown format.\n* Fixed archive types other than ZIP in QWK.  Now you can use any supported\n  archive type.\n* Simplified Quoting Code.  It's much simpler than before and now possible\n  to fix/change it.\n* Fized parsing of FTN address from FTN messages.\n* Convert QBBS editor text from Fido format to WWIV. This fixes a few issued\n  with QBBS style editors and control lines.\n+ wwivutil fix dirs actually works now.\n* Lots of fixes around handling botched conferences.\n+ Transfer area can now list file sizes by MB or GB in addition to KB\n* Fixed displaying WWIV color codes in File Extended descriptions\n! Removed FAST_SEARCH from wwiv.ini.  We always use it\n! Removed EXTRA_COLOR from wwiv.ini, it was not used.\n* Many fixes to FILE_ID.DIZ handling\n+ Support multiple tic areas per file area.\n! Don't call out from the BBS WFC automatically anymore. WWIVD handles callouts\n* 8x Speedup in networkf.\n* Fix format string in litebar header for listplus.\n+ Added script used to create links to built binaries. use-built-bin.sh\n* Improved wwivutil fido dump display.\n* Fix qwk uploads\n+ added \"wwivutil files tic validate\" comman\n+ Numerous FTN network usability improvements\n  * Stopped allowing network type changes in wwivconfig.\n  * When creating a new network in wwivconfig, ask for type before creating\n    the network.\n  * When creating new ftn area, set packet archiver to zip by default\n  * Pre-create directories for fido types\n  * run network3 once so that the directory is setup. Maybe also add it\n    to networkc to check\n  * When adding a network to a sub, ask for the host and then automatically\n    add it to the subscriber's file.\n  * Don't add msgid to emails\n  * Don't add failed crc32 entries to the dupe database\n  * Don't add emails to the dupe database\n+ Added SDK code to list archives for arc, zip, lzh, and arj.\n+ Added new command \"wwivutil files arc cmd\", that will display\n  the commandlines used for manipulating archives.\n+ Also added new command \"wwivutil files arc view\" to display\n  the contents of any supported archive format.\n+ Use internal arc viewer when arc view command is \"@internal\"\n* Added \"ARC\" archive type by default to WWIV.  Delete data/archiver.dat\n  then re-run wwivconfig and visit the archiver page to recreate your\n  default archiver.dat.\n* Fix full screen reader on unvalidated messages.\n* Remove File::creation_time, it doesn't work reliably on any platform\n* Lots of work on the installer:\n  * add some cmake install targets\n    cmake .. -DCMAKE_INSTALL_PREFIX=<location>\n    cmake --build . --target install\n  * You can use to generate archives (valid types ZIP, TGZ, STGZ, NSIS)\n    example: cpack -G ZIP\n* Added back the color countdown in bihangup.\n* Fix setting the nscandate (P) from the xfer menu.\n* Fix \"years old\" display in newuser (#1224)\n+ include networkt in builds\n+ The Internal FSED is now available for use.\n  To disable this, please set INTERNAL_FSED=N in WWIV.INI\n  The previous WWIV.INI setting of \"EXPERIMENTAL_FSED_USERS\"\n  is not longer used.\n  For a user to enable it, they should go to (D)efaults\n  and under \"(9) Message Editor\" select the option for:\n   \"A. Internal full-screen editor\"\n+ Added a help file (FSED.MSG) for the internal full screen \n  message editor. Please add it to your wwiv install under\n  the gfiles/ directory.\n+ Last IP Address for a user is now saved with the user record and displayed\n  at logon time in lilo.\n+ WWIV now supports an ACS language such as \"user.sl > 200\" that will be used\n  in expressions requiring access checks in the future.\n+ Added \"WWIVUTIL ACS\" command to validate ACS expressions and also execute\n  them against users to test the result.\n! Updated menu commands in extract post, please copy over MEXTRACT.MSG from\n  gfiles.zip to your GFILES directory.\n* fix crash renaming conference key in ConfEdit\n* Create wwivd.json if it's missing in wwivconfig. (#1248)\n* Only list chain exec modes (in chainedit) that work for the platform.\n* Fixed EXEC_LOG_SYNCFOSS string in wwiv.ini\n! default wwivd port to 23 on windows (#1251)\n+ Enable full screen reader for sysop and users with ansi by default. (#1252)\n+ Enable full screen editor for sysop and users with ansi by default. (#1252)\n+ Bundle netfoss with the install (#1253)\n* Removed unused spawnopts for NETWORK and TIMED as they were not used\n\nWhat's New in WWIV 5.5 (2019)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* WWIV now requires GCC 8.3 or later and MSVC 2019 v16.3 or later.\n* WWIV now builds on Debian10, Windows 10 and Centos7 (soon to add Centos8)\n* StringPrintf has been replaced by using fmt::fmtlib everywhere.\n* Added --start_date and --end_date to wwivutil messages dump, this\n  allows dumping of messages by date rather than by number.  The\n  format for the date is \"YYYY-MM-DD[ H:M:S]\"\"\n\nWhat's New in WWIV 5.4 (2019)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Conference files {subs,dirs}.cnf will be backed up before saving\n  them in case of corruption.  If you see these files getting corrupted\n  please log a bug and let us know what change was more recently made\n  to the conference data file.\n* Help text for command line arguments are a bit easier to understand.\n+ wwivconfig now has an option under paths for Logs directory. If set,\n  it'll be the default location for all binary *.log files.  If the\n  WWIV_LOG_DIR environment variable or --logdir command line argument\n  are specified, they will override this setting from wwivconfig.  Like\n  all other paths, if specified as a relative path, it is relative to \n  the bbsdir (aka WWIV_DIR or --bbsdir).\n* Added --log_startup to all binaries. This will enable the start/stop\n  default logging with command line arguments displayed.  This is now\n  not the default behavior anymore.  If you want it displayed, either\n  pass --log_startup or edit Logger::Init in core/log.cpp and set\n  log_startup_ to true.\n* WWIV now uses the C++17 standard std::filesystem for almost all file\n  and directory operations, this removed most of the OS specific code\n  from WWIV.\n* The wwiv_test from jenkins has been removed, the normal build target\n  also runs tests now, this saves a lot of time double-compiling\n  everything.\n* Created chains.json to replace chains.dat and chains.reg.\n\n\nWhat's New in WWIV 5.4 (2018)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n! windows-wwiv-update has been removed from the distribution.  Had lots\n  of complaints of it not working for people, and may reappear in the\n  future as a native C++ implementation.\n  It's source has been moved it it's own repo.\n! wwivserver.exe has been removed from the distribution.  wwivd is\n  the replacement. It's source has been moved it it's own repo.\n! WINS has been removed from the distribution. It hasn't changed in\n  several years and it's source has been moved it it's own repo.\n  If new changes are made, it'll get it's own downloadable build\n  for win32, or instructions for how to compile it yourself\n  will be created.\n* Lots of small changed related to logging, the user visible one is\n  that log files are not held open anymore, so you can rotate them\n  while a binary is running (like networkb or wwivd)\n! Removed the '#' modifer from callout.net. It didn't work and also\n  wasn't documented.\n* Fixed duplicate contact.net entries.\n+ Added options --save and --backup to wwivutil net contact\n* Fixed networkc missed things to do, by adding a loop in networkc \n  to catch everything to do.\n! remove INI variable RATIO. It was duplicated in wwivconfig and confusing.\n* Fixes the dialog to create sysop account\n* Fix error logged about failure to write 5.x header\n+ Added wwivutil net subscribers command.\n* Fixed a bunch of networking issues. (gating and hosting related)\n+ added wwivutil fido subscribers command\n* Improved FTN duplicate checking to check for either the \n  MSGID (if available) or a hash of the message header.\n  Either one will now trigger a dupe, vs needing both to\n  mark a message as a dupe.  This should improve the case\n  where the header is changed on a message and it is resent\n  to us.\n* Only use fake mailer mode on telnet connections (not SSH)\n  since that breaks SSH/\n* Fixed a problem where we couldn't mark a wwivnet call as\n  a failure (we threw an exception vs. recoring it in contact.net)\n* Fixed STDIO based editors not working in Linux, and added an\n  option to wwivconfig to enable it (the option is visible for\n  all platforms, but currently only works on Linux/Unix)\n* The Message SDK now honors pending_net_val flag on subboards.\n! Fixed hubbing and gating in the network stack this should now\n  mostly work as expected.\n* Remove existing msgid line before adding a new one (bug #1134)\n* Improvements on detecting a failed session in networkb.\n+ wwivconfig can now edit callout.net from the networks menu\n  just like it can edit fido_callouts.json with a GUI editor.\n! You can now send a FTN email using the form:\n  \"username (net/node)\" or \"username (zone:net/node)\".  Using\n  the fake ftn node number is no longer needed.\n! Added --skip_delete to most network commands, it'll backup vs\n  deleting packets that it's processed.\n* wwivutil messages dump now displays msgid for messages\n+ net.ini is now read for default values for most command\n  line flags for all network? commands.  I.e. you can add\n  skip_net = true under [networkb] and it'll be the same\n  as added --skip_net=true on the commandline\n+ wwivd now handles all of the callouts instead of bbs's\n  WFC screen.  Make sure you turn it on in wwivconfig\n  to allow it to happen, then the nodes that allow \n  auto-callouts will be called out to on schedule as\n  set in callout.net or fido_callout.json (both are\n  editable in wwivconfig in the network settings).\n* Don't silently crash the binary when a network connection\n  gets dropped.  Handle SIGPIPE on linux and log the result.\n* networkb (and bbs) now uses networkc to \"cleanup the net\"\n  instead of each tool having a different buggy implementation.\n* Fixed the log file timestamp (was using . not ,)\n* net54's network1 now updates the bytes waiting in contact.net\n  like net3x did (and it should have been doing all along)\n* wwivd will reload the network callout configuration when\n  receiving a HUP signal.\n+ wwivd can now execute wwiv's beginday event if specified\n  to do so in wwivconfig\n+ added --quiet flag to wwivconfig to make it not output\n  anything unless it's doing something (nice to keep the\n  wfc from displaying lots of useless info)\n* wwivd now exit's cleanly so systemd is happier.\n+ wwivd autoblocking now works (it was listed in wwivconfig\n  back in 5.3, but never enabled in wwivd, fixed that)\n+ networkc now has a --process_instance=XX flag that's used\n  when the bbs uses it to cleanup the net.\n- Removed the '-k' flag from bbs, please use wwivutil to\n  pack the message bases now\n+ added \"wwivutil print\" command to print ansi files using the same\n  ansi interpretation code in the bbs (also it's now been rewritten\n  into the SDK module so others can use it easily)\n+ If an environment variable WWIV_DIR exists, use that\n  to locate config.dat unless --bbsdir is specified on\n  the commandline.  This works in every wwiv binary.\n* For linux we now have builds for debian9 and centos7.\n+ code that inputs numbers is much nicer and validates\n  the number a bit more.\n* broke and fixed quoting, it's much simplier now and\n  understandable by humans.\n+ ANSIs display reasonably well now in the fullscreen message viewer.\n+ added wwivutil net list and wwivutil messages areas\n* Made and use new string functions for inputting numbers that only\n  allow numbers to be input, also can color the numbers red when out\n  of range.\n+ Implement WWIV_LOGS_DIR and WWIV_BIN_DIR env vars\n+ Setup the ability to specify an env var for any command\n  line parameter as the 4th argument to CommmandLineArgument, this\n  simplified the logic for checking the bbsdir value.\n* WWIV now uses the same commandline parsing code as the rest of the\n  binaries in the suite of tools (wwivutil, network, etc)\n* Add --configdir to all binaries\n* Add --bindir to all binaries\n* add --logdir to all binaries\n* Add --quiet to all network binaries\n* WWIV now needs CMake 3.9 and C++17 compatibility (this means \n  gcc >=6.3.0 or MSVC 2017 on Win32)\n  For stretch add this line:\n    deb http://ftp.debian.org/debian stretch-backports main\n  to your sources.list (or add a new file with the \".list\" extension to\n  /etc/apt/sources.list.d/)\n  You can also find a list of other mirrors at\n  https://www.debian.org/mirror/list\n\n  Then run the following to install cmake 3.9:\n    sudo apt update\n    sudo apt -t stretch-backports install cmake\n  On Centos: yum install cmake3\n  On Windows: It's already there with MSVC 2017\n+ STDIO mode on Linux now creates a PTY in addition to setting the\n  handles of 0 and 1 to pipe to the socket.  Also the pty seems to\n  be setup properly with a Window size of 80 x 25.\n* /C is fixed (it was broken a few weeks ago)\n* QBBS Editors should now mostly work as expected, we strip the colors\n  out of the messages, and the header lines that go into QUOTES.TXT \n  since only wwiv editors care about that metadata.\n+ TextFile now supports a 'd' parameter for filemode, it means DOS\n  text (i.e use \\r\\n on Linux vs. \\n on Linux).  All door drop files\n  and QBBS Editor Files (MSG{TMP,INF}) now use this mode.  This means\n  no more unix2dos needed on Linux.  Since these are only used by\n  DOSEMU based doors, it should be fine.\n\nWhat's New in WWIV 5.3 (2018)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Lots of fixes to the SDK messagebase code.\n+ Created SDK class for handling qscan pointers\n! networkf will exit with error level 1 when there is\n  no work to do.\n* Optimize the full screen message title list by not redrawing\n  the whole screen when there is no change.\n* Lots of improvements in getting rid of global variables throughout\n  the BBS and especially around the message base code in WWIV\n* Lots of improvements to the localUI classes used by INIT, also\n  can now optionally have help for edit items displayed in the\n  statusbar and UI pages are easier to create.\n* Added UI for WWIVD.\n* Implemented all of the wwiv-server features (auto blocking,\n  country blocking, goodlist, badlist, etc) into wwivd except\n  for \"fake mailer mode\"\n* Dont try to use the Full-Screen Reader for emails, since \n  it doesn't work yet.\n* For linux we now have builds for debian8, debian9 and centos7.\n+ wwivd now offers fakemailer mode and is now has (mostly) feature parity\n  with wwivserver.exe on windows.  wwivserver.exe is deprecated\n  with the 5.3 release and will be removed for 5.4\n! INIT has been renamed to WWIVCONFIG.  Please delete init.exe or\n  ./init when you upgrade to 5.3\n+ wwivutil dump will now display control characters (like [^A]\n  for control-A)\n* On FTN messages bank lines were being striped accidentally,\n  this is now fixed.\n+ wwivconfig has some new parameters for how it works with 4.x\n  WWIV installs.  --4xx will launch a menu with only the items\n  that work with 4.x (like wwivd editor and network.dat editor)\n  run \"wwivconfig --help\" for the latest list of command-line parameters.\n* Fixed internal editor word wrapping on linux.\n* fixed 8 char packet passwords truncating the last character.\n* Emails packed in PKT files will now import, previously only\n  ones in bundles (*.su?, *.mo?, etc) would import.\n! Fixed the oubound FTN gateway number (network3 thought it\n  was 32675 not 32765). This means you need to run network3\n  on all FTN node networks (i.e. if fsxnet is network .2 in init\n  then run \"network3 .2\" to rebuild the bbsdata.* files).\n! **!!*!*!*! You need to update the outbound sub by recreating the\n  network node it's under in subedit (J, then M, then the letter, usually\n  A, then retype the echo tag, or just edit data/subs.json and replace\n  32675 with 32765 everywhere prettymuch (it's under host section))\n\nWhat's New in WWIV 5.3 (2017)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+ WWIVbasic interpreter is available.  The menu command is\n  \"RUNBASIC\".  Also you can run a script from the logon event\n  by using @basic:[scriptname.bas] for the LOGON_CMD in wwiv.ini\n  (eventually many other commands will allow you to specify a\n  script to run instead of an external command).\n+ New install.sh on Linux to do the entire installation.\n* Init no longer prompts for system password.\n* subs.json is now the source of truth for subs data (before, subs.dat\n  and subs.xtr were both used as source of truth, although subs.json has\n  been written on save since 5.2)\n- background color pipe code (the format is '|Bn' where n in [0,9]), which\n  were deprecated in 5.2 has been removed.\n- extended ^P codes > 9 are removed.\n+ New experimental menu editor in INIT.\n* Most lists in INIT will now keep their selected index when returning\n  to the list.\n+ Added wwivutil status command. 1st operation is \n  \"wwivutil status qscan [set|get]\". You can set or get the qscan value\n  in status.dat.\n- Removed internal menueditor, use the one in init if needed.\n* Upgraded compilers to MSVC 2017 and GCC 6.2.\n+ handling type main_type_sub_list is implemented now, so receiving\n  SUBS.LST from netup for WWIVnet type networks should work in net53.\n* FTN KLUDGE lines are now hidden for FTN networks.\n* Heart codes are stripped on outbound FTN messages now.\n+ WWIV now compiles and runs on OpenIndiana (an Open Solaris fork)\n  Thanks to apam for the code!\n* Many FTN fixes. Also points may now work.\n+ WWIVD now runs on Windows.  It has an initial version of a shuttle\n  or matrix logon support.\n- Removed internal usereditor, use the one in init if needed.\n+ WWIVd now exports connection information to HTTP as a JSON object.\n  on the http port defined on init, URL: \"/status\"\n  Example output:\n    { \"status\": [ { \"num_instances\" : 3 }, { \"used_instances\": 0 } ] }\n+ New option to set the working directory to the temp directory vs. \n  bbs directory. It's available for both chains and editors.\n+ Added %I when running commands to point to the path to the temporary\n  directory.\n* Fix some color schemes displaying black-on-black for colors\n* Fix compilation on GCC 4.9, also fix many warnings from clang-tidy\n! Use git submodules for dependencies instead of copyingn in code \n  from another repository. This makes it easier to update to new\n  versions of our dependencies and also push fixes back.\n  You now need to update submodules when cloning unless you clone\n  it recursing submodules.\n* BinkP Fix (thanks apam) where all FTN addresses were not being presented\n  when answering.\n! CMake is now the source-of-truth build system on all platforms.\n  to build use \"cmake --build . -- -j8\" and not make or msbuild\n  anymore.\n! networkb will stay running now and doesn't need to be in a \n  batch file or shells script to loop after each connection.\n  Also even better, let wwivd spawn it as needed vs. running\n  it manually.\n\nWhat's New in WWIV 5.2 (2016)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Added \"WWIVUTIL FILES\" subcommand to list files, file areas and also\n  delete a file entry from the listing.\n* Fixed \"WWIVUTIL FIX\" with file entries. It actually works again.\n* Login prompt looks a little snazzier, uses the colorized input prompt.\n* config.dat now includes version info on what wrote to it for better\n  versioning of upgrades.  The only change is now if you go back to 4.3\n  you will need to run init to reset your newuser password (if you have\n  one, or to clear it on downgrade since the newuserpw field and version\n  info in config.dat live in the same first 21 characters in the file.)\n* CONFUG.USR is no longer needed, INIT in 5.2.2129+ will move the data into\n  user.lst and delete the file.\n* Removed command line option -O, since -X{T,S} implies -O\n* Removed Control-F1 to shutdown the BBS, it's not needed anymore on\n  non-single user operating systems.\n* Removed TAB {Instance Editor, didn't really edit, just allowed you to see\n  status or shutdown an instance} command from WFC. Not really needed anymore.\n* BBS now uses the network support code from the SDK module (like net51).\n* nodemgr is deleted.  wwivd is the new preferred *nix daemon for spawning\n  instances.\n* bbs -XU is no longer supported.  valid connection types are local, ssh and\n  telnet on all platforms.\n* bbs -I# is no longer supported. It's been a duplicate of -N forever, please\n  use -N## to specify the node number. (It also hasn't worked for quite some\n  time)\n* installation now includes sample scripts for systemd.\n* wwivserver (windows), can now run networkb on demand for receiving connections\n  automatically. Make sure that you configure it on the binkp page. This won't\n  callout but will receive network binkp requests.\n* / callout menu displays host:port if it's a binkp connection.\n* callout.net flag /## now means ## minutes not ## hours\n* wwivutil net dump_xxx commands are now just called wwivutil net xxx\n  for example dump_callout -> callout\n* networkb now supports CRC verification when sending files. To disable it\n  set crc=N in the newly created net.ini\n* net.ini can now handle defaults on a per-network basis or\n  per-network-node basis (when calling out) using tags of \n  [networkb-network_name] and [networkb-network_name-sendto_node].\n  The only settings are crc=[Y|N] and skip_net=[Y|N].\n* The short lived networkb.ini is renamed to net.ini (yes, this is the same\n  as the WINS one, but WINS will go away over time).\n* networkb will loop on receive, no need to run binkp.cmd, but\n  since wwivserver can answer binkp for you, no need to run networkb\n  manually to receive traffic.\n* wwivutil messages now has a pack comand to pack a message area.\n* Network names \"Filenet\" and \"internet\" no longer have special meaning,\n  within the BBS, please ensure those networks are of type \"internet\" for\n  WWIV to understand those are internet network types. (don't rename them\n  since WINS may care about the name).\n* networkf is now bundled with the binaries. It can import and export\n  message network types fido.\n* The fake FTN network address is now hard coded, and it is 32765.\n* Routing in FTN now works, uou need to define a route string for nodes\n  in the address list in INIT for the network.  The format is space\n  separated list of routes.  A route is a partial address ending in *\n  as a wildcard. Optionally starting with ! to be a negative match.\n  Example \"11:* !11:2/*\" would match everything in zone 11, except\n  for everything in net 11:2/*.\n* NETWORKC.EXE is added, it's like the Cerebrum software clnup.exe. It\n  will run network{1,2,3} as needed to process all mail. It'll also\n  run networkf to export packets to FTN bundles if any exist.\n* FTN NetMail now works (sometimes).\n* net.in has a new parameter for section [networkb].  cram_md5=[Y|N]. If set\n  to N, it'll disable cram-md5 and works on either end.  If either side\n  disables it, the session won't use it.\n* Fixed network1 from breaking DE1 packets\n* Fixed the cram-md5 implementation, it's not correct and can talk to \n  other binkp servers (tested against MIS) using cram-md5.  This happened\n  in build 2304.\n* The new user flow on Linux now works as expected (the screen\n  positioning is not off).\n* New experimental full screen reader. Enable it with\n  \"EXPERIMENTAL_READ_PROMPT = Y\" in wwiv.ini.  Once enabled it's\n  a per-user option in Defaults.\n* New file \"gfiles/mbfsed.msg\" is the help screen for user\n  commands for the full screen message reader.\n* New file \"gfiles/mbfsed-sysop.msg\" is the help screen for sysop\n  commands for the full screen message reader.\n* New file \"gfiles/title-fsed.msg\" is the help screen for title\n  scan in hte full screen message reader.\n* readme.510 is now readme-wwiv.txt.\n* wwivini.510 is now wwivini.txt\n* Keyboard timeouts are now configurable in WWIV.INI.  Also\n  you can configure a different timeout value for connections\n  still at the logon phase, before a user is logged in. That\n  defaults to 30 second (vs. 10 minutes before)\n  The keys with defaults are are:\n    USER_KEY_TIMEOUT  = 180 ; Timeout in seconds for non-sysops.\n    SYSOP_KEY_TIMEOUT = 600 ; Timeout in seconds for sysops.\n    LOGON_KEY_TIMEOUT = 130 ; Timeout in second for users logging in \n                            ; (i.e. They are at the NN: prompt.)\n* EXPERIMENTAL_READ_PROMPT is now FULL_SCREEN_READER and defaults\n  to being on.\n* New Subboard flag (P) to disable the full screen reader for a \n  specific subboard. This is needed for ansi art subs.\n* USE_NEW_BBSLIST is removed from WWIV.INI. All BBS List is the\n  new JSON format.\n* fcns.h is finally gone.\n\nWhat's New in WWIV 5.1 (2016)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* removed \"debug_level\" and Debug menu command. use VLOG(2) now.\n* \"extra color\" was only used in transfer section w/o listplus \n  (which means it's not ever used). removed the checks for it.  This\n  will come back in the future somewhere else to be useful.\n* Added IP blocklisting/safelisting and auto blocking. The settings\n  are on the blocklist page in wwivserver.exe. By default 3 connection\n  attempts in 120 seconds will get an IP blacklisted.\n* The wwiv server also pretends to be a FTN mailer for fun.\n* Removed F6 (toggle sysop alert), to page you after a session ends, since\n  this isn't needed post-DOS anymore.\n* Added wwiv-update.exe (contributed to WWIV by TRI0N from \n  https://github.com/TRI0N/Windows-WWIV-Update/) into nightly builds.  \n  wwiv-update.exe is the name of the new binary.\n* SSH support. Use -XS as the commandline argumetn vs. -XT for telnet.\n* networkb will use CRAM-MD5 for authentication by default if both\n  systems support it.\n* The wwiv.ini setting TERMINAL_CMD will be used to launch a terminal\n  program from the WFC using the 'T' command (again).\n* WWIV5TelnetServer has a log viewer built in you may use to see the\n  state of the various WWIV and network log files.\n* net.log is now written in normal order for log files with the newest\n  entry at the bottom and never truncated to behave like the rest of \n  the log files in WWIV.\n* The two laston lists in WWIV have been merged into one.  Now last few\n  callers will always display the last few callers regardless of the \n  day they called.\n* Added -XU command line type for UNIX communication type. On UNIX we\n  temporarily use that type by default for now.\n* UNIX Local IO is now curses based. Win32 can optionally use curses\n  for local IO by defining WWIV_WIN32_CURSES_IO.\n* Removed \"-w\" argument to BBS since there is now just 1 WFC (again).\n* Removed the --network=[net name] option from networkb.exe, now please\n  use --network_number=N (where N is like you would use with network1 .N)\n* Created alpha-quality network{1,2,3} replacements.  Please feel free to\n  try them out. They will eventually become net51 and replace the DOS based\n  net38.\n* Renamed WWIV5TelnetServer to WWIVServer, since it also does SSH too.\n* Numeric subtypes are no longer used.  Here's the diff of the change\n  in case you run an older WWIV and want to mod it to behave the same\n  way (using a string version for numeric types).  Otherwise just don't\n  use numeric named subs anymore.\n  https://github.com/wwivbbs/wwiv/pull/784/files\n*   \n\nWhat's New in WWIV 5.1 (2015)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Message titles are now limited to 72 characters (same as FidoNet message)\n  limits.  In reality they would get truncated around this length anyway and\n  in most places WWIV still forces a max of 60 characters.\n* Internal application-level caching for posts have been removed. It didn't help\n  access times anymore and added lots of unneeded complexity.\n* Started new utility WWIVUTIL which will eventually handle maintenance\n  tasks for the bbs.\n* Updated menus/textfiles to reflect 5.1 and also remove commands that have\n  been removed years ago.\n* LOCAL_SYSOP has been removed from wwiv.ini, it's always true now.\n* Callback support has been removed the rest of the way.\n* Threaded messages support has been removed (it didn't work anyway).\n* NETUTIL has been merged into WWIVUTIL.  Going forward, WWIVUTIL will be\n  the main external command line tool for WWIV on all platforms.\n* Removed menu commands DownloadPosts and DownloadFileList and the \n  Download Zipped Text menu item from //QWK (all did the same thing).\n* Removed ability to run WWIVMAIL.EXE from the //QWK menu. If anyone\n  wants this, then can add their own //QWK menu now that we have a\n  menu editor since 4.3. This removed USE_WWIVMAIL and USE_INTERNAL_QWK\n  from wwiv.ini.\n* removed SLASH_SZ from wwiv.ini. It wasn't enabled by default anyway.\n* Removed ReadMessages menu item. It wasn't classic WWIV\n\nWhat's New in 2015 (WWIV 5.0)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* networkb - BINKP transport for WWIV networking is now part of the WWIV builds.\n* netutil - Network packet and config file utility now included\n* network - shim to proxy between network0, networkp (PPP project) and networkb\n  is now part of the product.\n* A SSM will be sent to the sysop when a new user joins the bbs.\n* WWIV moved from wwiv.sf.net to wwivbbs.org\n* Source code moved from sourceforge.net to GitHub.\n* Upgraded compilers from MSVC 2013 to 2015 Community.\n* Upgraded .NET from 4.0 to 4.6\n* Fixed hangs with guest user accounts when they drop connection\n* Made all QWK filenames lowercase\n* zip/unzip now bundled with WWIV on Windows\n* linux builds now just include linux files, ditto for windows\n\nWhat's New in 2014 (WWIV 5.0)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Many more things work.\n* Init is open sourced\n* Full self-bootstrapping support. No longer need 4.30 installed first.\n* Added new parameter for chains/commands %H = Telnet Socket Handle\n* Added wwiv.ini setting NO_NEWUSER_FEEDBACK. If set to Y no newuser messages\n  will be sent at all.\n* Added wwiv.ini setings to control temp/batch directories. This is no longer\n  configured in init.  For TEMP_DIRECTORY/BATCH_DIRECTORY the %n is replaced\n  by the node number of the instance. Also paths are relative to the bbs home\n  directory (where config.dat lives).  NUM_INSTANCES defines how many intances\n  you want to spawn.  Also node that directories are created on demand by the\n  bbs on startup and config.ovr will be created by legacy tools when you run\n  init.  \n  Here are the default values:\n    TEMP_DIRECTORY = temp%n\n    BATCH_DIRECTORY = batch%n\n    NUM_INSTANCES = 4\n* INIT will create default archiver configuration for infozip's unzip/zip. If\n  you want to try it just delete archiver.dat (back it up first) and rerun\n  INIT to create the new defaults.\n* Internal QWK support has been added and only works with ZIP archives for now.\n  If you use this, please add the QWK.ANS and QWK.MSG files from the release\n  archive into your GFILES directory.\n* Added new wwiv.ini setting to enable/disable internal QWK and wwivmail from\n  the //QWK menu.  These currently both default to 'Y' (the wwivmail one will\n  shortly default to 'N', so if you use it please add this to your INI)\n  Here are the ini keys and default values:\n    USE_WWIVMAIL = Y\n    USE_INTERNAL_QWK = Y\n* New files will optionally be displayed at login (right after \"login\" file):\n  sl### : where ### is the current user SL.\n  dsl### : where ### is the current user DSL.\n  arX : Where X is one of the AR for the user.\n  darX : Where X is one of the DAR for the user.\n* Added support for QBBS style external editors. Just set the editor type to\n  QuickBBS instead of WWIV.\n* SPAWNOPT[FSED] is now unused and no longer supported.  Spawn options are now\n  set on a per-editor bases in INIT (similiar to how chains work).\n* Fix now defaults to only fixing critical files.  To enable other \"fixes\" \n  (which I recommend using at your own risk after you backed up DATA/\" use\n  the command line flags to enable each of these.  See fix -? for help.\n* EXEC_WAITFORIDLETIME and EXEC_USECWAITFORIDLE are no longer used, \n  EXEC_CHILDWAITTIME  should be used to set how long to wait for exec'ed\n  processes to become runnable. It defaults to 500ms.\n\nWhat's New in 5.0 Beta-2 (2004)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n* Archver commands now work.\n* F1 User Editor Improvements\n* PuTTY now works with auto-detect line mode\n* WFC now clears the screen in places it forgot to.\n* Fixed Pending Network display glitches\n* Changed Message Scan Prompt to 1 line from 2.\n* Added Litebar calls in Your Info and Voting Booth for \n  a more common look and feel.\n* Fixed missing mutex in telnet handling code.\n* 2004 Copyright\n* Misc internal code cleanups.\n\nWhat's New in 5.0 Beta-1\n~~~~~~~~~~~~~~~~~~~~~~~~\n* File compatable with 4.30/4.31\n* 32-bit Win32 version.\n* Compiles and Runs on Linux.\n* Included GUI Telnet Server.\n* Internal ZModem\n* DOOR32.SYS support.\n* Uses the SyncFoss code from Synchronet (thanks to Rob Swindell for helping\n  get this to work)  \"Emulate Win32 FOSSIL\" enables this.\n* Added commandline option -k (pacK message areas) to wwiv50.  This \n  will pack all message areas unless you specify the number of the\n  areas to pack on the commandline. i.e. \"wwiv50 -k 1 5 10\" would\n  pack areas 1, 5 and 10. (Build46)\n* If you add \"NEW_SCAN_AT_LOGIN=Y\" to WWIV.INI, then when a user logs \n  in they will be asked to scan all message areas for new messages. (Build46)\n* The display while packing message bases is now a bit nicer looking.\n* Changed filename global.txt to global-<node number>.txt (Build43)\n* Added control-U for who's online hotkey. (Build40)\n* Fixed laston edge case where the header didn't match the data when\n  EXTENDED_USERINFO = N but SHOW_CITY_ST = Y. (Build40)\n* FOSSIL can now be specified in WWIV.INI as a valid flag for spawn \n  options (Build37)\n* Added 2 new pipe codes:\n  * |#<wwiv color code 0-9> as an alternative to the \"heart\" codes\n  * |@<macro character> as an alternative to ^O^O<macro char>\n  * Existing pipe codes are: |B<background char>, and |<2 digit code>\n    for foreground colors. (Build36) \n* Added parameter \"%E\" to stuff_in which can be used in doors as the path \n  to the DOOR32.SYS file (You can put this in chainedit or init) (Build35)\n* Detects WinXP (Build34)\n* '/A', '/H', '/?' Added to internal message editor (Build33)\n* New WWIV.INI Parameters\n  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  EXEC_LOGSYNCFOSS     = [ 1 | 0 ] - If non-zero then wwivsync.log will \n                         be generated.  The default setting is 1 and this\n                         is currently ignored.\n  EXEC_USECWAITFORIDLE = [ 1 | 0 ] - Under WindowsNT/2K/XP when launching\n                         the child process WWIV uses WaitForInputIdle to wait\n                         for the child process to process all normal input \n                         before starting the Fossil handling code.  Setting\n                         this to 0 will disable that (acting like Win9x where\n                         we just wait for a bit (See EXEC_CHILDWAITTIME).  The\n                         default value of this is 1.\n  EXEC_CHILDWAITTIME   = (time to wait in milliseconds, this parameter is\n                         only used on Win9X unless EXEC_USEWAITFORIDLE is\n                         set to 0. The default value is 500 (1/2 second)\n  EXEC_WAITFORIDLETIME = (time to wait in milliseconds, only used on \n                         Windows NT/2K/XP unless EXEC_USEWAITFORIDLE=0).  The\n                         default value for this is 2000 (2 seconds)\n"
  },
  {
    "path": "install/gfiles/bbs.str.ini",
    "content": "; WWIV BBS \"Strings\" file for custome language support.\n; THis is the common language file for all menusets.  Ideally any customizations\n; should be made by placing a copy of the strings into a bbs.str.ini file\n; location in the menuset directory.\n;\n[lang]\n\n;\n; Common words: Yes/No/Quit/Pause/etc\n;\n\n; Keys to use for YNQ\nKEY_NO    = N\nKEY_QUIT  = Q\nKEY_YES   = Y\n\nNO        = |{random \"No\", \"Nah\"}\nPAUSE     = \"|#3More? [Y/n/c]\"\nQUIT      = Quit\nYES       = |{random \"Yes\", \"Yep\", \"Sure\"}\n\n; Fixed string values, do not use any random or colorized text.\nFIXED_NO  = No\nFIXED_YES = Yes\n\n;\n; Logon Area. note that the three double quotes are a multi-line string\n;\nNN_PROMPT = \"\"\"\nEnter number or name or 'NEW'\nNN: \"\"\"\nPW_PROMPT = \"PW: \""
  },
  {
    "path": "install/gfiles/chat.msg",
    "content": "|#9ķ\n|#9|#4                           WWIV Chatroom Help                                |#9\n|#9Ľ\n\n|#1                Command|#9                      What it does\n|#2                -------                      ------------\n|#1                ?                            |#9Displays this menu\n|#1                /q or x                      |#9Exits chat\n|#1                /c                           |#9Changes chat channels\n|#1                /s                           |#9Secures a chat channel\n|#1                /u                           |#9Unsecures a chat channel\n|#1                /p                           |#9Pages a user\n|#1                /w                           |#9Display who's online\n|#1                /a                           |#9Toggles action mode \n|#1                list                         |#9Displays a list of actions\n|#1                (action name) ?              |#9Displays help on an action\n|#1                GA                           |#9Executes a generic action\n|#1                >username msg                |#9Direct a message to a user \n|#1                /username msg                |#9Whispers a message to a user or\n|#9                                             sends a message to someone\n|#9                                             outside of chat.\n"
  },
  {
    "path": "install/gfiles/cmdparam.msg",
    "content": " Replacable parameters:\n\n  Param     Description                       Example\n  ---------------------------------------------------------------------\n   %%       A single '%'                      \"%\"\n   %1-%5    Specified passed-in parameters\n   %B       Com port base address, in hex     \"3f8\"\n   %I       Com port irq, in decimal          \"4\"\n   %M       Modem baud rate                   \"14400\"\n   %S       Com port baud rate                \"38400\"\n   %P       Com port number                   \"1\"\n   %N       Instance number                   \"1\"\n   %T       Time remaining (min)              \"30\"\n   %C       chain.txt full pathname           \"c:\\wwiv\\temp\\chain.txt\"\n   %D       doorinfo full pathname            \"c:\\wwiv\\temp\\dorinfo1.def\"\n   %O       pcboard full pathname             \"c:\\wwiv\\temp\\pcboard.sys\"\n   %A       callinfo full pathname            \"c:\\wwiv\\temp\\callinfo.bbs\"\n   %R       door full pathname                \"c:\\wwiv\\temp\\door.sys\"\n   %K       gfiles comment file for archives  \"c:\\wwiv\\gfiles\\comment.txt\"\n\n"
  },
  {
    "path": "install/gfiles/comment.txt",
    "content": "This is GFILES\\COMMENT.TXT.\r\r\n\u001a"
  },
  {
    "path": "install/gfiles/cs-email.msg",
    "content": "|#9(|#2Q|#9)uit to Main Menu\n|#9(|#2S|#9)ave Mail and Reply to Author\n|#9(|#2R|#9)e-Read Last Mail #\n|#9(|#2I|#9)gnore Last Mail Read\n|#9(|#2D|#9)elete Last Mail Read\n|#9(|#2A|#9)uto-Reply and Delete Last Mail Read\n|#9(|#2F|#9)orward Mail to Another User; does not permit comments\n|#9(|#2-|#9) Previous Mail #|#0\n|#9(|#2+|#9) Next Mail #|#0\n|#9(|#2G|#9)o to Specific Mail #\n|#9(|#2Z|#9)ap Current Mail; does not send \"So and So read your message.\"\n|#9(|#2P|#9)urge all mail from Author.\n|#9(|#2V|#9)alidate Author\n|#9(|#2O|#9) Send Form Letter to Author\n|#9(|#2U|#9)edit Author\n|#9(|#2C|#9) Concise Uedit Author\n|#9(|#2Y|#9) Download this Mail\n|#9(|#2@|#9) Reply to Different Address with quoting\n"
  },
  {
    "path": "install/gfiles/editor.msg",
    "content": "|#2                              WWIV Editor Commands\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    |#1/?            |#9 Display WWIV Editor help (this screen)\n    |#1/S            |#9 Save Message\n    |#1/Q            |#9 Quote text from original message.\n    |#1/ESY          |#9 Save Message Anonymously\n    |#1/ESN          |#9 Save Message NOT Anonymously\n    |#1/ABT          |#9 Abort Entire Message (Quit)\n    |#1/CLR          |#9 Clear Message and Start Over\n    |#1/RL           |#9 Replace Last Line\n    |#1/TI           |#9 Edit Message Title\n    |#1/LI           |#9 List Message So Far\n    |#1/C:           |#9 Center Text After \"/C:\"\n\n    |#1/SU/Old/New   |#9 Replace Old Text with New\n    |#1CTRL-P+ 0 - Z |#9 Change Color to Digit\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n"
  },
  {
    "path": "install/gfiles/email.msg",
    "content": "|#9(|#2Q|#9)uit to Main Menu\n|#9(|#2S|#9)ave Message and Reply to Author\n|#9(|#2R|#9)e-Read Last Message Number\n|#9(|#2I|#9)gnore Last Message Read\n|#9(|#2D|#9)elete Last Message Read\n|#9(|#2A|#9)uto-Reply and Delete Last Message Read\n|#9(|#2F|#9)orward Message to Another User (Does |#6not |#9permit comments)\n|#9(|#2-|#9) Previous Message #\n|#9(|#2+|#9) Next Message #\n|#9(|#2G|#9)o to Specific Message Number\n|#9(|#2Y|#9) Download Current Message\n|#9(|#2@|#9) Reply to Different Address with quoting\n"
  },
  {
    "path": "install/gfiles/feedback.msg",
    "content": "This is feedback.msg.\r\nEdit to suit your needs.\r\n"
  },
  {
    "path": "install/gfiles/formasv.msg",
    "content": "Entered as a visiting sysop using your BBS information.\n"
  },
  {
    "path": "install/gfiles/fs_msgread.120.msg",
    "content": "|#9 Sub: |#2|{msg.message_area, \"<45\"} |#9Msg#: |[59;1H|#9[|#2|{msg.message_number, \">5\"}|#9 of |#2|{msg.total_messages, \">5\"}|#9]         Info: |#1|{if \"msg.flags.local == true\", \"|#9[|#5LOC|#9] \", \"\"}|{if \"msg.flags.wwivnet == true\", \"|#9[|#5WWIVNET|#9] \", \"\"}|{if \"msg.flags.ftn == true\", \"|#9[|#5FTN|#9] \", \"\"}\n|#9From: |#1|{msg.from, \"<45\"} |#9Date: |#1|{msg.date}\n|#9  To: |#1|{msg.to, \"<45\"} |#9Subj: |#2|{msg.title}\n|#9 Sys: |#1|{msg.sys, \"<45\"} |#9Loc: |[59;4H|{msg.loc}\n|#0|{set num_header_lines 4}"
  },
  {
    "path": "install/gfiles/fs_msgread.msg",
    "content": "|#9 Sub:                                     Msg#:\n|#9From:                                     Date:\n|#9  To:\n|#9Subj:\n|#9 Sys:                                      Loc:\n|#9Info:\n|[7;1H|#2|{msg.message_area}|[49;1H|#9[|#2|{msg.message_number}|#9 of |#2|{msg.total_messages}|#9]\n|[7;2H|#1|{msg.from}|[49;2H|#1|{msg.date}\n|[7;3H|#1|{msg.to}\n|[7;4H|#2|{msg.title}\n|[7;5H|#1|{msg.sys}|[49;5H|{msg.loc}\n|[7;6H|#1|{if \"msg.flags.local == true\", \"|#9[|#5LOC|#9] \", \"\"}|{if \"msg.flags.wwivnet == true\", \"|#9[|#5WWIVNET|#9] \", \"\"}|{if \"msg.flags.ftn == true\", \"|#9[|#5FTN|#9] \", \"\"}\n|#0|{set num_header_lines 6}"
  },
  {
    "path": "install/gfiles/fs_msgscan.msg",
    "content": "|[2J|#4Sub #|{cursub.subnum} - |{cursub.name}  (|{cursub.num_msgs} messages.)|[K|#0\n|14      Num Title                                      From|#0|{set num_header_lines 2}"
  },
  {
    "path": "install/gfiles/fsed.msg",
    "content": " |#2                          Editor Menu Commands\n |#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n |#1ESCAPE     |#9 Edit Menu (This Menu)    |#1ESCAPE + S |#9 Save Message\n |#1ESCAPE + Q |#9 Quote text from message. |#1ESCAPE + A |#9 Abort Message (Quit)\n\n\n |#2                        Movement and Key Editing\n |#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n |#1ARROW KEYS |#9 Move around              |#1PGUP/PGDN    |#9 Page up, Page Down \n |#1HOME       |#9 Beginning of Line        |#1END          |#9 End of Line\n |#1CTRL-A     |#9 Beginning of Line        |#1CTRL-E       |#9 End of Line\n |#1CTRL-D     |#9 Delete Line              |#1CTRL-K       |#9 Delete to End of Line\n |#1CTRL-I     |#9 Toggle INS/OVR Mode      |#1CTRL-L       |#9 Redraw Screen     \n |#1CTRL-P+0-9 |#9 Change Color to Digit\n |#1CTRL-P+Control{A,D,F} |#9 Execute macro (control-A, control-D or control-F)\n"
  },
  {
    "path": "install/gfiles/listplus.hlp",
    "content": "Use your arrow keys to move left and right among the bottom menu.  These menu\r\ncommands affect the file that you have selected with the up and down keys.\r\n\r\nIf your arrow keys do not work, turn your num lock ON, and use your numerical\r\nkeypad as arrow keys.\r\n\r\n\r\nCommands are:\r\n\r\n<Space Bar> \r\n  Add or remove a file from the batch queue.  You will know if a file is in the\r\n  batch queue by the '' on the far left of the screen of the file you have\r\n  marked.\r\n\r\nNext\r\n  View the next n files in the download dir\r\n  \r\nPrev\r\n  View the previous n files in the download dir\r\n  \r\nMark\r\n  Add or remove a file from the batch queue.  You will know if a file is in the\r\n  batch queue by the  on the far left of the screen of the file you have\r\n  marked.\r\n  \r\nView\r\n  Do an archive view of the file\r\n  \r\nInfo\r\n  Get extended info on file\r\n  \r\nDownload\r\n  Download current file, or if you have files in your batch queue, will ask you\r\n  if you want to download them.\r\n  \r\nBatch Menu\r\n  Brings up your batch menu.\r\n  \r\n+Dir\r\n  Go up the one in the directory     \r\n  \r\n-Dir\r\n  Go back one in the directory\r\n  \r\nQuit\r\n  Quit listfiles plus\r\n  \r\n  \r\n  \r\nVarious commands affected by listfiles plus from the Transfer menu.\r\n\r\n'L'ist files\r\n'S'earch all dirs\r\n'F'ind text\r\n'N'ew scan all dirs\r\n\r\nList files and New scan are pretty staight forward...\r\n\r\nListfiles will ask you for a filespec and show you the files in the dir.\r\n\r\nNewscan will scan all dirs in your NSCAN for files newer than your limiting\r\ndate (date you last logged on, or set with the 'P' command)\r\n\r\nSearch all dirs and Find text have been combined into one area.  When you\r\nselect either of these commands you get an extended search menu, get more\r\nhelp in that area.\r\n\r\n"
  },
  {
    "path": "install/gfiles/logoff.mat",
    "content": "|09=======================================\n|10Leaving So Soon?\n\n|03Log |09(|14O|09)|03ff the BBS.\n|03Send |09(|14F|09)|03eedback to the Sysop\n|03|09(|14Q|09)|03uit back to the BBS.\n|03Visit the |09(|14T|09)|03ime Bank before you go.\n\n|09=======================================\n|03What would you like to do? \n"
  },
  {
    "path": "install/gfiles/logoff.msg",
    "content": "\n|#5Thank You for calling this new |#2WWIV |#5BBS|#1!\n\n"
  },
  {
    "path": "install/gfiles/logon.msg",
    "content": "This is logon.msg.\r\nEdit to suit your needs.\r\n"
  },
  {
    "path": "install/gfiles/lpconfig.ans",
    "content": "\u001b[?7h\u001b[40m\u001b[2J\u001b[7C\u001b[0;34m\n\u001b[7C\u001b[44m \u001b[1;36m\u001b[32m  \u001b[37mListPlus \u001b[0;36;44m- \u001b[1;33mWWIV User Configurable Transfer Area File Listing   \u001b[32m\u001b[36m \u001b[40m\n\u001b[7C\u001b[44m \u001b[34m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[33;40m1  \u001b[37mFile Name\u001b[12C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[1;36;40mInstructions:\u001b[16C\u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[33;40m2  \u001b[37mFile Extension\u001b[7C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[30C \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m3  \u001b[37mTimes Downloaded\u001b[5C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[36;40mSelect the \u001b[1mNUMBER \u001b[0;36mof the\u001b[5C\u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m4  \u001b[37mFile Size (K-bytes)  \u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[36;40mitem which you wish shown in \u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m5  \u001b[37mFile Description\u001b[5C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[36;40myour File Listing.\u001b[11C\u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m6  \u001b[37mDate Uploaded\u001b[8C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[30C \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m7  \u001b[37mFile Cost/Points\u001b[5C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[36;40mUse the <\u001b[1mSHIFT\u001b[0;36m> key plus the \u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m8  \u001b[37mFile Age (Days Old)  \u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[1;36;40mNUMBER \u001b[0;36mkey of the selected   \u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40m9  \u001b[37mUploaded By\u001b[10C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[1C\u001b[36;40mitem to change \u001b[1mCOLORS\u001b[0;36m.\u001b[7C\u001b[44m \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40mH  \u001b[37mFile List Header\u001b[5C\u001b[44m  \u001b[0;30;44m \u001b[34;40m\u001b[44m   \u001b[30C \u001b[40m\n\u001b[7C\u001b[44m \u001b[2C\u001b[1;33;40mQ  \u001b[37mQuit/Abort\u001b[11C\u001b[44m             \u001b[30C \u001b[40m\n\u001b[7C\u001b[0;34m\n\u001b[7C\u001b[1;36mUse the 'K' command to reconfigure your setting from the Transfer Menu.\n\u001b[7C\u001b[0;36mSelection (\u001b[1;33mQ\u001b[0;36m=Quit):\u001b[0m\n"
  },
  {
    "path": "install/gfiles/lpfreq.msg",
    "content": "|#3The file you attempted to download is offline.\n\n|#2If you request this file when prompted, a message is sent to the sysop\n|#2and the file will be restored.  Check again in the next few days.\n\n|#2If you choose not to request it, no one will ever know you tried to mark\n|#2this offline file. <G>\n\n|#1In any event, please do not request the same file OVER and OVER.  If I\n|#1haven't restored it, it must be missing....\n\n\n"
  },
  {
    "path": "install/gfiles/lpsearch.ans",
    "content": "\u001b[40m\u001b[2J\u001b[0;1;34mĿ \u001b[0;1;33mOption [A] searches \u001b[s\n\u001b[ufor a specific filename.  Wildcards (*,?) are okay, but  \u001b[0;1;34m \u001b[0;1;33mmust match, e.g. \"WILD\" will \u001b[0;1;31mNOT \u001b[s\n\u001b[u\u001b[0;1;33mfind \"WILDCAT.ZIP\" but \"WILD*\" will!\u001b[8C\u001b[0;1;34m\u001b[78C \u001b[0;1;35mOption [B] searches for text in filenames \u001b[s\n\u001b[u\u001b[0;1;31mAND \u001b[0;1;35mdescriptions.  You can use\u001b[5C\u001b[0;1;34m \u001b[0;1;35mmultiple search parameters using the logical expressi\u001b[s\n\u001b[uons described below.    \u001b[0;1;34m\u001b[78C \u001b[0;1;36mThe operators | (or), & (and), and ! (not) can be used to tailor your sear\u001b[s\n\u001b[uch \u001b[0;1;34m \u001b[0;1;36mvery specifically.  Some examples are:\u001b[39C\u001b[0;1;34m\u001b[78C \u001b[0;1;32mcat | dog\u001b[10C<- find \"cat\" OR \u001b[s\n\u001b[u\"dog\" in the filename or description.    \u001b[0;1;34m \u001b[0;1;32mcat & dog\u001b[10C<- show if \"cat\" AND \"dog\" are both found in descr\u001b[s\n\u001b[uiption. \u001b[0;1;34m \u001b[0;1;32mrip & !description <- show \"rip\" but skip if the full word is \"description\". \u001b[0;1;34m\u001b[s\n\u001b[u\u001b[16;1H\n\u001b[0m\u001b[255D\n"
  },
  {
    "path": "install/gfiles/lpsysop.msg",
    "content": "\u001b[2J|#1Side menu colors\n|#2A|#3] |#7Non-selected 'highlighted' color :       |#2B|#3] |#7Non-selected color          :\n|#2C|#3] |#7Selected 'highlighted' color     :       |#2D|#3] |#7Selected color              :\n\n|#1Other colors\n|#2E|#3] |#7Color of '' when file is tagged :       |#2F|#3] |#7Color of file number       :\n|#2G|#3] |#7'Found' text foreground color    :       |#2H|#3] |#7Found background color     :\n|#2I|#3] |#7The color of the 'current' file  :\n\n|#1Other junk\n|#2J|#3] |#7Max screen lines to show (0=all) :       |#2K|#3] |#7Min extended lines to show :\n\n|#1Toggles...\n|#2L|#3] |#7Allow user to edit .CFL:                 |#2M|#3] |#7Request file is        :\n|#2N|#3] |#7Colorize found text is :                 |#2O|#3] |#7Search extended is     :\n|#2P|#3] |#7Simple search is       :                 |#2R|#3] |#7Configurable lists are :\n|#2S|#3] |#7Check file existance   :\n"
  },
  {
    "path": "install/gfiles/mbfsed-sysop.msg",
    "content": "|#5SysOp Commands:\n|#9(|#2D|#9) Delete last message read\n|#9(|#2E|#9) Extract last message read to disk\n|#9(|#2L|#9) Load file into Workspace\n|#9(|#2M|#9) Move message to new subboard\n|#9(|#2N|#9) Not Auto-purgeable (toggle status)  \n|#9(|#2U|#9) Make Current Message NOT Anonymous  \n|#9(|#2X|#9) Toggle Net Pending Status           \n|#9(|#2Y|#9) Download Last Message               \n\n"
  },
  {
    "path": "install/gfiles/mbfsed.msg",
    "content": "|#5Arrow Keys:\n|#9(|#2Up|#9)     |#9Scroll Up                  |#9(|#2Down|#9)     |#9Scroll Down\n|#9(|#2Left|#9)   |#9Previous Message           |#9(|#2Right|#9)    |#9Next Message\n|#9(|#2ENTER|#9)  |#9Scroll Down / Read Next Message\n\n|#5Commands:\n|#9(|#2A|#9) E-Mail Author of Last Message        \n|#9(|#2B|#9) Bypass (Skip) Current Sub (For N-Scan) \n|#9(|#2F|#9) Find Text in headers and messages\n|#9(|#2K|#9) Toggle Displaying Hidden Control Lines\n|#9(|#2T|#9) List Message Titles\n|#9(|#2P|#9) Post a Public Message in Current Sub   \n|#9(|#2Q|#9) Quit to Main Menu                      \n|#9(|#2W|#9) Reply with \"Regards\" to Last Message \n|#9(|#2Y|#9) Download Last Message                \n\n"
  },
  {
    "path": "install/gfiles/mbmain.msg",
    "content": "|#2         WWIV Message Base Commands\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#2(ENTER)  Read Next Message             \n|#2#        Go to Message # Entered              \n|#2-        Back Up 1 Message #                  \n|#2A        E-Mail Author of Last Message        \n|#2B        Bypass (Skip) Current Sub (For N-Scan) \n|#2F        Find Text in headers and messages      \n|#2P        Post a Public Message in Current Sub   \n|#2Q        Quit to Main Menu                      \n|#2R        Re-Read Last Message #                 \n|#2T        See Titles of Next 15 Messages       \n|#2W        Reply with \"Regards\" to Last Message \n|#2Y        Download Last Message                \n\n"
  },
  {
    "path": "install/gfiles/mbslash.msg",
    "content": "|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#2                           WWIV Slash Command Menu\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#2Commands Preceeded by Two Slashes           Commands Preceeded by One Slash \n|#2Net      |#9Show Network Boards          |#2Z  |#9Zip New Messages for Download  \n|#2Who      |#9Who is on the Board          |#2O  |#9Log Off without Logoff Msg     \n|#2Upload   |#9Upload a Text or Ansi File   |#2E  |#9Multiple E-mail                \n|#2Qscan    |#9Mark messages as READ        |#2N  |#9Begin N-Scan at Current Sub    \n|#2CLS      |#9Clear Screen                 |#2C  |#9Enter Chat Room                \n|#2CM       |#9Change menu command set      |#2A  |#9New Scan Messages, All Confs   \n|#2UNQSCAN  |#9Mark messages as UNread\n|#2COLORS   |#9Edit Color Set\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  },
  {
    "path": "install/gfiles/menuwel.msg",
    "content": "|#9WWIV allows customizable menus. These menus can be changed in the stock \n|#9WWIV menuset using either the (K) change menus command in (D)efaults, \n|#9or from the \"//CM\" (Change Menu) command in the main menu.\n\n|#5Please select a menu set from the menus listed below:\n"
  },
  {
    "path": "install/gfiles/mextract.msg",
    "content": "|#5 Available directories|#0\n\n|#2 G|#7)|#1 Extract to GFILES or Path\\filename|#0\n|#2 D|#7)|#1 Extract to Data Directory|#0\n|#2 T|#7)|#1 Extract to TEMP Directory|#0\n\n"
  },
  {
    "path": "install/gfiles/mmail.msg",
    "content": "|#9(|#2A|#9)dd to List\n|#9(|#2M|#3)ailing-list add to List\n|#9(|#2D|#9)elete from List\n|#9(|#2E|#9) Write and Send Multi-Mail\n|#9(|#2L|#9)ist Users in Multi-Mail List\n|#9(|#2Q|#9)uit Multi-Mail\n"
  },
  {
    "path": "install/gfiles/newmail.msg",
    "content": "    Here is a general overview of how WWIV BBS software operates.\n\n    The BBS is divided into three main areas.  When you finish reading this\nmessage, you'll be at the |#2Main Menu|#0, which contains BBS utility functions,\nsystem bulletins, and local/networked public and private messages.  The BBS\nhas an wide assortment of message area topics.  You can view the available\nareas with the <*> key.  Message forums are separated into \"conferences\" to\nhelp you find them, and the <J>oin command allows you to change conferences.\nIf you don't see topic that interest you, drop me a note and I'll surely find\nnetworked areas with others sharing your interests.\n\n    The |#2Game Area|#0 is accessed by hitting <.> at the Main Menu.  There are\nmany games to play online, competing against the BBS and other users.  Some\nare played against users on other systems, too!  My favorites are Scrabble and\nTradewars, but have fun trying them all!\n\n    Uploads and downloads are done in the |#2Transfer Area|#0, accessed by\nhitting <T> at the Main Menu.  Like the message areas, the file areas are\norganized into conferences and directories.  Again, <J>oin and <*> command\nmove you around to the area you want.  Other common commands are <L>ist to\nlist the files in a directory, <D>ownload and <V>iew Archives.  There is no\nupload or download ratio to satisfy here, but I ask if you come across a\nprogram which you feel others would enjoy, please share it.\n\n    I hope you enjoy the BBS!  Your security level allows access to all\nfile, game, and message areas.  Let me know if there's something special\nyou're looking for but can't find.  I want the BBS to grow to meet your needs.\nMake yourself at home, and I hope you call often!\n\n"
  },
  {
    "path": "install/gfiles/newsysop.msg",
    "content": "    Glad you could drop by!  It's always a pleasure to have a Sysop visit!\nDouble-check your information in [D]efaults and, if something's not correct,\nplease correct it.  Remember, WWIV modifications are only accessible after\nyour registration number is provided.  As a Sysop, I'm sure you know your way\naround the BBS, so I won't bore you with overviews or rules!  Help yourself\nto whatever's here and enjoy!\n"
  },
  {
    "path": "install/gfiles/newuser.msg",
    "content": "This is newuser.msg.\r\nEdit to suit your needs.\r\n"
  },
  {
    "path": "install/gfiles/noansi.msg",
    "content": "\n\nYou must install a telnet client application that supports ANSI color and\ngraphics to use all the features of this system.  Here are some shareware\nand freeware clients I have used and can recommend:\n\n    NetRunner\n         http://mysticbbs.com/downloads.html   [win32, linux]\n\n    SyncTerm\n         http://syncterm.bbsdev.net/     [mac, win32, linux]\n\n    Zap-O-Comm\n         http://www.emtec.com/zoc/index.html   [win32, mac]\n\n"
  },
  {
    "path": "install/gfiles/oneliner.msg",
    "content": "|10     WWIVbasic Presents:\n|11                            _  _ \n|11                           | |(_)\n|11           ___  ____  _____| | _ ____  _____  ____ ___\n|11          / _ \\|  _ \\| ___ | || |  _ \\| ___ |/ ___)___)\n|11         | |_| | | | | ____| || | | | | ____| |  |___ |\n|11          \\___/|_| |_|_____)\\_)_|_| |_|_____)_|  (___/\n|11\n|03                                   Based on oddliners by Eli!\n\n"
  },
  {
    "path": "install/gfiles/qwk.msg",
    "content": "|#2WWIV QWK Off-Line Reader Menu\n|#7-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n|#1D|#9)|#9ownload Qwk Packet\n|#1U|#9)|#9pload Reply Packet\n|#1C|#9)|#9onfig Qwk settings\n|#1Q|#9)|#9uit to Main Menu\n\n"
  },
  {
    "path": "install/gfiles/rs-email.msg",
    "content": "|#1Q|#3>|#5uit to Main Menu\n|#1I|#3>|#5gnore Last Mail Read\n|#1-|#3>|#5 Previous Mail #|#0\n|#1+|#3>|#5 Next Mail #|#0\n|#1G|#3>|#5o to Specific Mail #\n"
  },
  {
    "path": "install/gfiles/sconfig.hlp",
    "content": "(N)ext:  \r\nGo on to next page.  If you have conferencing enabled, you have to press } to\r\ngo on to the next conference.  If there are more than one page of subs in the\r\ncurrent conference, choosing (N)ext will take you on to the next page, leaving\r\nyou in the current conference.  \r\n\r\n(P)revious:  \r\nTake you back one page.  Works like (N)ext but in reverse.  If you want to go\r\nback one conference, press {\r\n\r\n(T)oggle:  \r\nToggles the current status of the sub.  Spacebar will do this as well.\r\n\r\n(C)lear All:  \r\nClears all subs currently displayed on the screen.\r\n\r\n(S)et All:  \r\nToggles on all subs on trhe current page.\r\n\r\n(Q):  \r\nQuit to the main Defaults menu.\r\n\r\n\r\n\r\n\r\nPress your SPACE BAR to 'Tag' the subs/dirs that you want to include into your\r\n'New Scan' Scanning.\r\n\r\nUpon doing so, you will be presented with something that looks like this:\r\n\r\nConfigure QSCAN -- Local Discussion            -- Press <SPACE> to toggle a sub\r\n\r\n[] Sam Sez\r\n[] The Never-Ending Story (Written\r\n[ ] Local User Get Together Discussi\r\n[] Best Local Restraunts\r\n[ ] South East Texas Talk\r\n\r\n\r\nNext  Prev  Toggle  Clear ALL  Set ALL  Read New  { Conf  } Conf  Quit\r\n^^^^\r\n\r\nThe \"Next\" above the carets will be highlighted.  What this \"Next\" means is\r\nthe Next Page of the current conference.  In this particular conference\r\n(\"Local Discussion\", as indicated at the top of the page) there is no \"Next\r\npage\"...there are only the five subs shown on this page in this particular\r\nconference.  Using your up and down arrows, navigate up and down the list of\r\nsubs, using your spacebar to toggle off or on any you want to read.  (You may\r\nhave to use either the numbers on your numeric keypad, or the ones between the\r\nright Ctrl and Shift keys, or both sets may work.)  The [] indicates your\r\ndesire to read that particular sub. It will change to [ ] when that particular\r\nsub is turned off.\u0001\r\n\r\nAfter you finish this page, press } to go to the next conference, and repeat\r\nthe process.  The next conference should look something like this:\r\n\r\n\r\nConfigure QSCAN -- Of Interest to Sysops       -- Press <SPACE> to toggle a sub\r\n\r\n[] WWIV Support Board Sub             [] QWKMod and WWIV QWK Readers Dicu\r\n[] WWIV 4.24 Development Sub          [] Hackers Elite (How to Protect Yo\r\n[] WWIV Modifications Sub             [] JAFO's Support Sub\r\n[] Group Four Sysops                  [] WWIV Sysops Magazine\r\n[] Modnet                             [] Netlog Support Sub\r\n[] Mod Talk and Requests              [] Mod Companion Sub\r\n\r\nNext  Prev  Toggle  Clear ALL  Set ALL  Read New  { Conf  } Conf  Quit\r\n^^^^\r\n\r\nIn this particular case, most all of the subs are related to Sysops, and you\r\nmay not be interested in them at all, or a very few of them.  In this case, you\r\nwill benefit by selecting \"Clear ALL\", which will de-select them all, then\r\nturn on the ones you want to include (again by using your arrow keys and\r\nspacebar).  Also, in this conference, there is probably more than one page.\r\n\r\n\"Prev\" will take you back a page in the current conference.\r\n\"Toggle\" does the same thing as the spacebar.\r\n\"Set ALL\" will turn on all subs in the current conference.\r\n\"Read New\" will show you the messages in whatever sub you have highlighted at\r\n      the time.  This is good if you want to see a sample of the messages in a\r\n      sub where the title may be unclear of what the sub is about.\r\n\"{ and } Conf\" will go backwards or forwards one conference.\r\n\"Quit\" takes you back the the main QWK menu.\r\n\r\nOnce you select all the subs you wish to read, you will not need to do this\r\nagain unless I have mechanical problems with my computer.  So please don't\r\nthink this is something you'll have to do each time you log on.  Also, if/when\r\nI add more message bases, they are automatically added into your scan so that\r\nyou will know they are there.  If I add something new and you don't like it or\r\ndon't care to read it, you simply turn it off in the above manner.\r\n"
  },
  {
    "path": "install/gfiles/smain.msg",
    "content": "|#5|#4 CO-SYSOP COMMANDS |#5\n|#5                                   |#2//|#1STATUS    |#3=|#5 Current System Status \n|#5  |#1,       |#3=|#5 Verbose Net Logs       |#2//|#1PENDING   |#3=|#5 Network Mail Pending  \n|#5 |#2//|#1LOG    |#3=|#5 Today's Sysop Log      |#2/|#1V          |#3=|#5 Validate Msgs.        \n|#5 |#2//|#1NLOG   |#3=|#5 Network Connection Log |#2//|#1!         |#3=|#5 Validate a User       \n|#5 |#2//|#1YLOG   |#3=|#5 Yesterday's Sysop Log  |#2//|#1IVOTES    |#3=|#5 Initialize Voting Dat \n|#5 |#2//|#1ZLOG   |#3=|#5 System Activity Log    |#2//|#1VOTEPRINT |#3=|#5 Voting Data to File   \n|#5                                                                       \n|#5|#4 SYSOP COMMANDS |#5\n|#5                                                                       \n|#5 |#2//|#1AE    |#3=|#5 Allowed Files Editor    |#2//|#1CHAT       |#3=|#5 Toggle Chat Avail.   \n|#5 |#2//|#1BE    |#3=|#5 Message Board Editor    |#2//|#1EDIT       |#3=|#5 Edit Any Text File   \n|#5 |#2//|#1CE    |#3=|#5 Chain (Door) Editor     |#2//|#1LOAD       |#3=|#5 Load File in Editor  \n|#5 |#2//|#1DE    |#3=|#5 Directory Editor        |#2//|#1MAILR      |#3=|#5 Read All Mail Sent   \n|#5 |#2//|#1EE    |#3=|#5 Event Editor            |#2//|#1RELOAD     |#3=|#5 Reload All Menu File \n|#5 |#2//|#1GE    |#3=|#5 G-File Editor           |#2//|#1RESETF     |#3=|#5 Reset User Files      \n|#5 |#2//|#1IE    |#3=|#5 Instance Editor         |#2//|#1RESETQSCAN |#3=|#5 Reset Qscan pointers \n|#5 |#2//|#1JE    |#3=|#5 Conference Editor       |#2//|#1STAT       |#3=|#5 Stack/Heap in Memory \n|#5 |#2//|#1RI    |#3=|#5 Read WWIV.INI           |#2//|#1TEDIT      |#3=|#5 Edit GFILES\\<file>   \n|#5 |#2//|#1CU    |#3=|#5 Change User                                                 \n|#5 |#2//|#1UE    |#3=|#5 User Editor                                                 \n|#5\n"
  },
  {
    "path": "install/gfiles/smbmain.msg",
    "content": "|#2      WWIV Sysop Message Base Commands\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#2(ENTER)|#9Read Next Message            \n|#2#      |#9Go to Message # Entered       \n|#2-      |#9Back Up 1 Message #           \n|#2A      |#9E-Mail Author of Last Message \n|#2B      |#9Bypass (Skip) Current Sub (For N-Scan) \n|#2C      |#9Continuous Message Read                \n|#2D      |#9Delete Current Message #               \n|#2E      |#9Save Current Message to Disk        \n|#2F      |#9Find specific text in messages      \n|#2L      |#9Load a File as a Post               \n|#2M      |#9Move Message to Another Sub         \n|#2N      |#9Not Auto-purgeable (toggle status)  \n|#2P      |#9Post a Public Message in Current Sub\n|#2Q      |#9Quit to Main Menu                   \n|#2R      |#9Re-Read Last Message #              \n|#2T      |#9See Titles of Next 15 Messages      \n|#2U      |#9Make Current Message NOT Anonymous  \n|#2W      |#9Reply with \"Regards\" to Last Message\n|#2X      |#9Toggle Net Pending Status           \n|#2Y      |#9Download Last Message               \n|#2@      |#9Reply to Different Address          \n"
  },
  {
    "path": "install/gfiles/sonline.msg",
    "content": "|#5WWIV USER ON-LINE COMMAND:\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#2F1        |#9 Edit User Information       |#2CTRL+F5  |#9 Time-out; Drop Carrier   \n|#2F2        |#9 Toggle Top of Screen Data   |#2F6       |#9 Toggle User Alert        \n|#2F3        |#9 (Dis/En)able Remote Typing  |#2F7       |#9 Decrease User's Time by 5\n|#2F4        |#9 Turn Off Chat Call          |#2F8       |#9 Increase User's Time by 5\n|#2F5        |#9 Drop Modem Carrier          |#2F9       |#9 Temporary Sysop Access   \n|#2SHIFTF5   |#9 Line Noise; Drop Carrier    |#2F10      |#9 (Dis)Engage 2-Way Chat   \n|#2ALT+F-Keys|#9 Auto-Validation Keys        |#2CTRL+F10 |#9 (Dis)Engage Regular Chat \n|#2ScrollLck |#9 Toggle Sysop Availability\n|#7~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n|#9[|#2ESCAPE |#9Exit Help] [|#2RETURN |#9Next Screen] [|#2ScrLck |#9Toggle Available]\n|#0\n"
  },
  {
    "path": "install/gfiles/srestrct.msg",
    "content": "|#1L |#3- |#5Only 1 Log On per Day             |#1E |#3- |#5Can't Send E-Mail\n|#1C |#3- |#5Can't Page for Chat               |#1V |#3- |#5Restricted from Voting Section\n|#1M |#3- |#5Posts Require Sysop Validation    |#1K |#3- |#5Chat Room Restriction\n|#1A |#3- |#5Restricted from Auto-Message      |#1N |#3- |#5Restricted from Network Access\n|#1* |#3- |#5Restricted from Anonymous Posting |#1U |#3- |#5Restricted to Sysop Dir Uploads|#0\n|#1P |#3- |#5Can't Post Messages|#0\n"
  },
  {
    "path": "install/gfiles/strans.msg",
    "content": "\n|#5|#4 TRANSFER SECTION SYSOP COMMANDS |#5|#0\n|#5|#3\"|#1//MOVE|#3\"      = |#5Move a File to Another Directory                   |#0\n|#5|#3\"|#1//REN|#3\"       = |#5Rename a File And/Or Change its File Description   |#0\n|#5|#3\"|#1//RSORT|#3\"     = |#5Sort Files Oldest to Newest                        |#0\n|#5|#3\"|#1//SORT|#3\"      = |#5Sort Files Alphabetically, or by Date of Upload    |#0\n|#5|#3\"|#1//UPLOAD|#3\"    = |#5Add all Files in Current Directory Path to Database|#0\n|#5|#3\"|#1//UPLOADALL|#3\" = |#5Add all Files in All Directory Paths to Database   |#0\n|#5|#3\"|#1//UPLOADFILE|#3\"= |#5Import File Descriptions from Another BBS Software |#0\n|#5|#3\"|#1//|#2A|#1llow|#2E|#1dit|#3\" = |#5Edit ALLOW.DAT                                     |#0\n|#5|#3\"|#1//READIDZ|#3\"   = |#5Read in File as Extended Descriptions              |#0\n|#5|#3\"|#1//|#2R|#1EMOVE|#2N|#1T|#3\"  = |#5Remove some/all N/A files in transfer area         |#0\n|#5|#3\"|#1^|#3\"           = |#5List Devices                                       |#0\n|#5|#3\"|#1.|#3\"           = |#5View DSZ Log File                                  |#0\n|#5|#3\"|#1M|#3\"           = |#5Same as //MOVE Command                             |#0\n|#5|#3\"|#1U|#3\"           = |#5Upload file in Directory using File_idz            |#0\n|#5|#0\n"
  },
  {
    "path": "install/gfiles/swfc.msg",
    "content": "|#5WFC COMMANDS \n|#7===============================================================================\n|#2SPACE |#9Log On                |#2ESC   |#9Quit BBS              \n|#2` |#9Show Net Information      |#2/ |#9Force Net callout     |#2' |#9Print Net Logs      \n|#2B     |#9Message Sub Editor    |#2C |#9Chains/Doors Editor   |#2D |#9Download Dir Editor\n|#2E     |#9Email                 |#2G |#9G-File Section Editor |#2H |#9Event Editor          \n|#2J     |#9Conference Editor     |#2K |#9Load file for E-mail  |#2L |#9Today's Sysop Log\n|#2M     |#9Read Mail             |#2N |#9Network Log           |#2O |#9Edit Text File\n|#2P     |#9Pending Network data  |#2Q |#9Quit the BBS          |#2R |#9Read all email\n|#2S     |#9System Status         |#2T |#9Run Terminal Program\n|#2V     |#9Initialize Vote Data  |#2Y |#9Yesterday's Sysop Log |#2Z |#9System Activity Log\n|#7===============================================================================\n|#9[|#2ESCAPE |#9Exit Help] [|#2RETURN |#9Next Screen] [|#2ScrLck |#9Toggle Available]\n|#0\n"
  },
  {
    "path": "install/gfiles/sy-email.msg",
    "content": "|#9(|#2Q|#9)uit to Main Menu\n|#9(|#2S|#9)ave Mail and Reply to Author\n|#9(|#2R|#9)e-Read Last Mail #\n|#9(|#2I|#9)gnore Last Mail Read\n|#9(|#2D|#9)elete Last Mail Read\n|#9(|#2A|#9)uto-Reply and Delete Last Mail Read\n|#9(|#2F|#9)orward Mail to Another User; does not permit comments\n|#9(|#2-|#9) Previous Mail #|#0\n|#9(|#2+|#9) Next Mail #|#0\n|#9(|#2G|#9)o to Specific Mail #\n|#9(|#2E|#9)xtract this Mail\n|#9(|#2M|#9)ove this Mail to a Sub-board\n|#9(|#2Z|#9)ap Current Mail; does not send \"So and So read your message.\"\n|#9(|#2P|#9)urge all mail from Author.\n|#9(|#2V|#9)alidate Author\n|#9(|#2U|#9)edit Author\n|#9(|#2O|#9) Send Form Letter to Author\n|#9(|#2L|#9)oad File in Workspace (no quoting)\n|#9(|#2C|#9) Concise Uedit Author\n|#9(|#2N|#9) Add Author as Net-Subscriber\n|#9(|#2Y|#9) Download this Mail\n|#9(|#2@|#9) Reply to Different Address with quoting\n"
  },
  {
    "path": "install/gfiles/system.msg",
    "content": "This is system.msg.\nEdit to suit your needs.\n"
  },
  {
    "path": "install/gfiles/tarchive.msg",
    "content": "|#1A|#3>|#5dd to Temporary ARC File\n|#1D|#3>|#5ownload Temporary ARC File\n|#1L|#3>|#5ist Files in Temporary Directory\n|#1Q|#3>|#5uit to Transfer Menu\n|#1R|#3>|#5emove a File from Temporary Directory\n|#1V|#3>|#5iew Files in Temporary ARC File\n|#1T|#3>|#5ext Download Files|#0\n"
  },
  {
    "path": "install/gfiles/tbatch.msg",
    "content": "\n|#3ķ|#0\n|#3|#1     Download Commands                |#3|#0\n|#3Ķ|#0\n|#3|#5 L |#1>|#2  List files in Queue             |#3|#0\n|#3|#5 R |#1>|#2  Remove files from Queue         |#3|#0\n|#3|#5 Q |#1>|#2  Quit to Transfer Menu           |#3|#0\n|#3|#5 C |#1>|#2  Clear download Queue            |#3|#0\n|#3|#5 D |#1>|#2  Download Queue                  |#3|#0\n|#3|#5 U |#1>|#2  Upload Files                    |#3|#0\n|#3|#5 B |#1>|#2  Bi-directional transfer         |#3|#0\n|#3Ľ|#0\n\n"
  },
  {
    "path": "install/gfiles/title-fsed.msg",
    "content": "|#5Arrow Keys:\n|#9(|#2Up|#9)     |#9Scroll Up                  |#9(|#2Down|#9)     |#9Scroll Down\n|#9(|#2Left|#9)   |#9Previous Message           |#9(|#2Right|#9)    |#9Next Message\n|#9(|#2ENTER|#9)  |#9Scroll Down / Read Next Message\n\n|#5Commands:\n|#9(|#2J|#9) Jump to Specific Message\n|#9(|#2Q|#9) Quit to Main Menu                      \n\n"
  },
  {
    "path": "install/gfiles/trashcan.txt",
    "content": "admin\nadministrator\nadvent\nagsadmin\naltibase\namssys\nandroid\nankit\nankur\napp\napplmgr\narbab\nareafix\nbackup\nbilling\nbin\nbitrix\nboys\ncisco\nclfs\ncron\ndb2admin\ndebug\ndemo\ndesign\ndev\ndspace\ndvs\nftp\nftpguest\nftpuser\ngit\ngit2\nguest\nhscroot\ninfo\ninformix\nintel\nios\nlog\nlp\nlsfadmin\nmanager\nmfs\nmircte\nmysql\nmythtv\nnagiosuser\nnetapp\nnetwork\nnsroot\nopenfiler\nopenvpn\noperator\noracle\nosmc\novhuser\npi\nplcmspip\nportal\npostgres\npostmaster\nproject\nrdp\nroot\nsales\nsecurity\nsquid\nsshd\nstress\nstudent\nsupport\nsvn\nsysadm\nsysadmin\nsysop\ntech\ntecmint\ntelnet\ntemp\ntest\ntest1\ntmp\ntomcat\ntomcat4\nts\ntst\nubnt\nuploader\nuser\nusername\nuucp\nvacftp\nverwalter\nvnc\nwebadm\nwebadmin\nwebmaster\nwwiv\nwwivlink\nwwivnet\nxerox\nzabbix\n"
  },
  {
    "path": "install/gfiles/tslash.msg",
    "content": "\n|#3ķ|#0\n|#3|#1 Commands Preceeded by One Slash      |#3|#0\n|#3Ķ|#0\n|#3|#5 O |#1>|#2  Log Off without Logoff Message  |#3|#0\n|#3|#5 S |#1>|#2  Zip Up a Listing Of All Files   |#3|#0\n|#3|#5 A |#1>|#2  List All New Files              |#3|#0\n|#3|#5 T |#1>|#2  Test an Archive                 |#3|#0\n|#3|#5 V |#1>|#2  Scan an Archive for Viruses     |#3|#0\n|#3Ľ|#0\n\n|#3ķ|#0\n|#3|#1 Commands Preceded by Two Slashes|#3    |#0\n|#3Ķ|#0\n|#3|#5 Who |#1>|#2 Who is On-Line|#3                |#0\n|#3Ľ|#0\n\n|#3ķ|#0\n|#3|#1 Other Commands Available|#3            |#0\n|#3Ķ|#0\n|#3|#5 . |#1>|#2 Show WWIVdsz.LOG if it exists|#3   |#0\n|#3|#5 ~ |#1>|#2 List users            |#3          |#0\n|#3ͼ|#0\n"
  },
  {
    "path": "install/gfiles/ttagging.msg",
    "content": "\n|#9|#2Tag File Menu|#9|#0\n|#9                                                           |#0\n|#9   |#2C|#1>|#8 Continue|#9                                                             |#0\n|#9   |#2D|#1>|#8 Download Tagged Files|#9             |#2Q|#1>|#8 Quit|#9                            |#0\n|#9   |#2E|#1>|#8 Extended Information|#9              |#2R|#1>|#8 Relist Files|#9                    |#0\n|#9   |#2M|#1>|#8 Move File (Sysop Only)|#9            |#2T|#1>|#8 Tag Files|#9                       |#0\n|#9                                        |#2V|#1>|#8 View Tagged File|#9                |#0\n|#9                                                                           |#0\n|#9|#0\n"
  },
  {
    "path": "install/gfiles/welcome.ans",
    "content": "\u001b[?7h\u001b[255D\u001b[7C\u001b[0;1m\u001b[8C\u001b[18C\u001b[30C\u001b[47m\u001b[40m\n  \u001b[5C\u001b[47m\u001b[40m\u001b[10C\u001b[47m\u001b[40m\u001b[29C\u001b[47m۲\u001b[40m\u001b[47m\u001b[40m \u001b[47m۲\u001b[40m    \u001b[47m\u001b[40m\u001b[8C\u001b[18C\u001b[47m\u001b[40m\u001b[47m۲\u001b[40m\n\u001b[A\u001b[79C\u001b[47m\u001b[2C\u001b[40m\u001b[47m\u001b[1C\u001b[40m\u001b[47m۲\u001b[40m  \u001b[47m\u001b[40m\u001b[47m\u001b[40m\u001b[6C\u001b[47m۲\u001b[11C\u001b[40m  \u001b[47m۲\u001b[2C\u001b[40m\u001b[47m\u001b[40m\n\u001b[A\u001b[79C\u001b[47m\u001b[3C۲\u001b[3C\u001b[40m\u001b[47m\u001b[3C۲\u001b[40m    \u001b[47m۲\u001b[4C\u001b[30;40m  \u001b[37m\u001b[47m\u001b[40m   \u001b[47m\u001b[0m   \u001b[1;47m\u001b[4C\u001b[40m\u001b[47m\u001b[40m   \u001b[47m\u001b[40m\u001b[0m\u001b[1;47m\u001b[40m  \u001b[47m۲\u001b[3C\u001b[0m\u001b[1m\u001b[47m\u001b[40m\u001b[6C\u001b[47m\u001b[0m   \u001b[1m\u001b[47m\u001b[5C\u001b[4C\u001b[0m\u001b[1;47m\u001b[2C\u001b[40m   \u001b[47m\u001b[30;40m\u001b[0m\u001b[1m\u001b[0m\u001b[1;30m  \u001b[37m\u001b[47m\u001b[40m\u001b[5C\u001b[47m\u001b[40m\n   \u001b[47m\u001b[5C\u001b[0m   \u001b[1;47m \u001b[0m\u001b[47m \u001b[1m\u001b[40m \u001b[47m\u001b[40m  \u001b[47m\u001b[2C\u001b[0m\u001b[1m  \u001b[47m\u001b[5C\u001b[40m\u001b[47m  \u001b[40m\n    \u001b[47m\u001b[5C\u001b[0m\u001b[1;47m\u001b[0m   \u001b[1;47m\u001b[0m\u001b[1;30;47m \u001b[37m\u001b[40m\u001b[47m\u001b[3C\u001b[40m\u001b[47m\u001b[0m\u001b[1m\u001b[47m۲\u001b[1C\u001b[40m\u001b[47m\u001b[5C  \u001b[0m\n    \u001b[1;47m\u001b[0m    \u001b[1;47m \u001b[4C\u001b[0m\u001b[1;30;47m\u001b[0m\u001b[47m \u001b[1m\u001b[30m\u001b[4C\u001b[37m\u001b[3C\u001b[0m\u001b[1m\u001b[47m۲\u001b[40m \u001b[47m\u001b[0m    \u001b[1;47m   \u001b[30m\u001b[0m\n    \u001b[1m\u001b[47m\u001b[4C     \u001b[3C\u001b[0m\u001b[47m    \u001b[40m\u001b[1;30;47m \u001b[0m\u001b[1;30;47m\u001b[5C\u001b[0m\u001b[1;47m \u001b[0m   \u001b[1;47m  \u001b[2C\u001b[40m\u001b[47m\u001b[40m   \u001b[47m\u001b[0m   \u001b[47m   \u001b[1;30m\u001b[40m\n\u001b[5C\u001b[37;47m\u001b[0m   \u001b[47m \u001b[1;30m\u001b[3C  \u001b[1C\u001b[0m\u001b[1;30;47m\u001b[0m\u001b[5C\u001b[1;30;47m \u001b[37m \u001b[3C\u001b[0m\u001b[1;47m   \u001b[0m    \u001b[1m\u001b[47m\u001b[40m   \u001b[47m  \u001b[3C  \u001b[30m\u001b[40m\n\u001b[5C\u001b[37;47m \u001b[2C \u001b[30m\u001b[0m   \u001b[1;30;47m\u001b[1C\u001b[6C \u001b[37m \u001b[3C   \u001b[30m \u001b[1C\u001b[37;40m\u001b[47m\u001b[40m   \u001b[47m   \u001b[3C\u001b[30m\u001b[40m\n\u001b[5C\u001b[37;47m \u001b[30m\u001b[1C\u001b[3C\u001b[2C۲\u001b[6C\u001b[37m \u001b[30m\u001b[3C    \u001b[37;40m\u001b[47m۲\u001b[5C   \u001b[30m\u001b[2C\u001b[0m\u001b[1;30;47m\u001b[40m\n\u001b[5C\u001b[0m\u001b[1;47m   \u001b[1C\u001b[30m\u001b[3C\u001b[2C۲\u001b[5C\u001b[0m\u001b[1;30;47m  \u001b[2C\u001b[0m\u001b[1;30;47m\u001b[0m \u001b[1m\u001b[47m۲\u001b[40m\u001b[5C\u001b[0m\u001b[1;47m  \u001b[30m\u001b[0m \u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[37;47m  \u001b[30m\u001b[40m\u001b[47m\u001b[2C\u001b[40m޲\u001b[47m۲\u001b[40m    \u001b[0m\u001b[1;30;47m \u001b[1C\u001b[0m\u001b[1;30;47m\u001b[3C\u001b[37;40m\u001b[47m۲\u001b[7C  \u001b[30m\u001b[0m\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[37;47m \u001b[30m\u001b[2C\u001b[40m\u001b[47m۲\u001b[4C\u001b[0m\u001b[1;30;47m\u001b[40m   \u001b[37;47m\u001b[7C\u001b[0m\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[37;47m \u001b[30m\u001b[3C\u001b[40m\u001b[47m\u001b[40m   \u001b[47m\u001b[0m\u001b[1;30;47m\u001b[40m  \u001b[37m\u001b[47m\u001b[0m\u001b[7C\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[37;47m \u001b[30m\u001b[40m \u001b[47m\u001b[3C\u001b[40m\u001b[47m\u001b[40m\u001b[47m \u001b[3C\u001b[37m\u001b[7C\u001b[0m\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[47m  \u001b[7C\u001b[40m\u001b[47m\u001b[4C\u001b[40m\u001b[47m\u001b[40m\u001b[47m\u001b[2C\u001b[37m\u001b[0m\u001b[5C\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[47m\u001b[11C\u001b[40m    \u001b[47m\u001b[40m\u001b[47m\u001b[40m  \u001b[37m\u001b[47m\u001b[1C  \u001b[0m\u001b[7C\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[47m\u001b[12C\u001b[40m߲   \u001b[6C\u001b[37;47m\u001b[0m\u001b[11C\u001b[1;30;47m\u001b[40m\n\u001b[6C\u001b[47m\u001b[13C\u001b[40m   \u001b[13C\u001b[0m\u001b[8C\u001b[1;30m[\u001b[37m5.20\u001b[30m]  \n\n\u001b[11C\u001b[37mA\u001b[5CN  e  w    W  W  I  V\u001b[6CB   B   S  !\u001b[0m\u001b[255D"
  },
  {
    "path": "install/gfiles/welcome.msg",
    "content": "This is welcome.msg.\nEdit to suit your needs.\n"
  },
  {
    "path": "install/gfiles/yourinfo.msg",
    "content": "|#4Your User Information|[K|#0\n\n\n|#9Your name      : |#5|{user.name} |#9#|#2|@#\n|#9Phone number   : |#2|@p\n|#9Mail Waiting   : |#2|@M\n|#9Security Level : |#2|@S\n|#9Transfer SL    : |#2|@d\n\n|#9Date Last On   : |#2|@L\n|#9Times on       : |#2|@l\n|#9On today       : |#2|@O\n|#9Messages posted: |#2|@m\n|#9E-mail sent    : |#2|@E\n|#9Time spent on  : |#2|@o |#9Minutes\n|#9Uploads        : |#2|@K|#9k in |#2|@U |#9files\n|#9Downloads      : |#2|@k|#9k in |#2|@D |#9files\n|#9Transfer Ratio : |#2|@z\n\n|{pausescr}\n"
  },
  {
    "path": "install/inifiles/chat.ini",
    "content": ";-----------------------------------------------------------------------------\n;\n;                           WWIV Version 5.1.0\n;              Copyright (C) 1999-2016 by WWIV Software Services\n;\n;              Lines begining with a semi-colon are ignored\n;-----------------------------------------------------------------------------\n; ID Block for ChatRoom settings.  This ID *must* appear as the first\n; uncommented  line in the INI file.\n;\n[CHAT]\n;SL required to access sysop functions (entering secured channels, looking\n;up userinfo) inside chat.  Setting it to 256 disables sysop functions.\nCHATOP_SL = 255\n\n;Set this equal to 1 if you want Chat to ask which channel to enter upon\n;entering chat, 0 will throw people into channel 1 immediately.  I recommend\n;leaving it at 0, it's simpler for new users.\nCH_PROMPT = 0\n\n;For every node you have, you MUST have a corresponding C(node number) here.\n;These denote what color to put the text in.\nC1 = \u00036\nC2 = \u00033\nC3 = \u00037\nC4 = \u00032\n\n;CH1 through CH10 are requirements to enter chat channels.  A is the channel\n;name, B is the SL required to enter the channel, C is the AR required to\n;enter the channel (0 if none), D is the sex required to enter the channel -\n;M, F, or A(ll).  E is the minimum age to enter the channel, and F is the\n;maximum age to enter the channel.\nCH1A = The Main Public Channel \nCH1B = 0\nCH1C = 0\nCH1D = A\nCH1E = 0\nCH1F = 127\n\nCH2A = Channel 2                   \nCH2B = 10\nCH2C = 0\nCH2D = A\nCH2E = 0\nCH2F = 127\n\nCH3A = Channel 3                 \nCH3B = 10\nCH3C = 0\nCH3D = A\nCH3E = 0\nCH3F = 127\n\nCH4A = Channel 4                 \nCH4B = 10\nCH4C = 0\nCH4D = A\nCH4E = 0\nCH4F = 127\n\nCH5A = Channel 5                  \nCH5B = 10\nCH5C = 0\nCH5D = A\nCH5E = 0\nCH5F = 127\n\nCH6A = Channel 6                 \nCH6B = 10\nCH6C = 0\nCH6D = A\nCH6E = 0\nCH6F = 127\n\nCH7A = Channel 7                \nCH7B = 10\nCH7C = 0\nCH7D = A\nCH7E = 0\nCH7F = 127\n   \nCH8A = Channel 8              \nCH8B = 10\nCH8C = 0\nCH8D = A\nCH8E = 0\nCH8F = 127\n\nCH9A = Channel 9                  \nCH9B = 10\nCH9C = 0\nCH9D = A\nCH9E = 0\nCH9F = 127\n\nCH10A = The Sysop's Lounge          \nCH10B = 255\nCH10C = 0\nCH10D = A\nCH10E = 0\nCH10F = 127\n\n;The NUM_ACTIONS setting tells the chatroom how many actions to read from\n;WWIV.INI.  This can be smaller than the actual number of actions in the\n;data file, but if it is larger problems could occur.  Set this equal to 0\n;to disable actions.\nNUM_ACTIONS = 39\n\n;Following this are the action declarations.  The format is simple.  The\n;first line of each action is the number of the action, followed by an A.\n;Make this equal to 0 if no recipient is required for the action, or 1 if\n;a recipient is required.  The second line contains the name of the action\n;(no longer than 12 characters!), the third the text to be printed to the\n;person doing the action, the fourth the text to be printed to the recipient\n;of the action, and the fifth the text printed to everyone else.  If you're\n;short on RAM, keep this list brief.  The chatroom is able to support up to\n;100 actions, but it only uses RAM for as many actions as you provide it.\n;A full 100 actions would require about 25k of RAM.\n\n;These actions MUST be in alphabetical order or the chatroom will not find them!\n\n1A = 0\n1B = AFK\n1C = Hope you don't miss much!\n1D = %s is away from his keyboard.\n1E = %s ran away from his keyboard because of %s\n1F = %s has left the keyboard!!!!\n\n2A = 1\n2B = AGREE\n2C = You're so right.\n2D = %s is nodding in agreement with you.\n2E = %s is in agreement with %s\n\n3A = 0\n3B = BARF\n3C = GROSS!\n3D = %s is barfing in your lap, a sign of affection.\n3E = %s is barfing in %s's lap, \n3F = %s is barfing\n\n4A = 1\n4B = BAT  \n4C = How awful!\n4D = %s just pulled out a baseball bat and beat you to death.\n4E = %s just beat %s to death with a baseball bat.\n\n6A = 0\n6B = BELCH\n6C = NICE! We wanted to hear that!\n6D = %s is belching in your face\n6E = %s is belching at %s\n6F = %s is belching, yum!\n\n7A = 1\n7B = BLOWING\n7C = Away goes the kiss :)\n7D = %s is blowing a kiss to you.\n7E = %s is blowing a kiss to %s, how sweet!\n\n5A = 0\n5B = BOW\n5C = How humble of you.\n5D = %s is bowing to you.    \n5E = %s is bowing to %s.     \n5F = %s is bowing.     \n\n8A = 0\n8B = BRB\n8C = Hurry up!                 \n8D = %s will be right back with you.\n8E = %s will be right back with %s.\n8F = %s will be right back.\n\n9A = 1\n9B = BURN\n9C = Fire! Fire! Huhuhu... Yeah.\n9D = %s just burned you, and is laughing maniacally.\n9E = %s just burned %s, and is laughing maniacally.\n\n10A = 0\n10B = CHEER\n10C = Yeaaa!\n10D = %s is cheering for you!\n10E = %s is cheering for %s!\n10F = %s is cheering!\n\n11A = 0\n11B = CHUCKLE\n11C = Umm.. okay\n11D = %s is chuckling at what you said!\n11E = %s is chuckling at what %s said!\n11F = %s is chuckling.\n\n12A = 0\n12B = COUGH\n12C = Hahummm.\n12D = %s is coughing at you\n12E = %s is coughing at %s.\n12F = %s is coughing.\n\n13A = 0\n13B = CRY\n13C = It's ok, we love you!\n13D = %s is crying on your shoulder\n13E = %s is cring on %s shoulder.\n13F = %s is sobing uncontrollably! \n\n14A = 0\n14B = DANCE\n14C = Whee!\n14D = %s grabs you and begins dancing with you!\n14E = %s grabs %s and begins dancing with them!\n14F = %s is dancing around the room.\n\n15A = 1\n15B = DISAGREE\n15C = You're never wrong, are you?\n15D = %s is shaking their head at you in disagreement with you.\n15E = %s does not agree at all with what %s said.\n\n16A = 0\n16B = FROWN\n16C = Don't be disapointed.\n16D = %s is frowning at you.\n16E = %s is frowning at %s in disbelief.\n16F = %s is frowning.\n \n17A = 0\n17B = GIGGLE\n17C = What a girlish giggle!\n17D = %s is giggling at you!\n17E = %s is giggling at %s\n17F = %s is giggling like a Girl!\n\n18A = 1\n18B = GLARE\n18C = Give them the evil eye!\n18D = %s is glaring at you!   \n18E = %s is glaring at %s!\n\n19A = 0\n19B = GRIN\n19C = What a sly grin..\n19D = %s is grinning at you.\n19E = %s is grinning at %s.\n19F = %s is grinning.\n\n20A = 0\n20B = GROWL\n20C = gggggrrrrrrr\n20D = %s is growling at you.\n20E = %s is growling fiercly at %s\n20F = %s Is growling, gggggggrrrrrrr.\n\n21A = 1\n21B = HUG\n21C = How sweet!\n21D = %s is hugging you tightly.\n21E = %s is hugging %s tightly.\n  \n22A = 1\n22B = KARATE\n22C = HIYA!\n22D = %s is karate-chopping you in half!\n22E = %s is karate-chopping %s in half!  \n  \n23A = 1\n23B = KICK \n23C = Such violence!\n23D = %s is kicking the crap out of you!\n23E = %s is kicking the crap out of %s!\n\n24A = 1\n24B = KISS \n24C = Pucker up!    \n24D = %s is kissing you.                   \n24E = %s is kissing %s.\n  \n25A = 0\n25B = LAUGH\n25C = Hahahaha!\n25D = %s is laughing at you!\n25E = %s is laughing at %s!\n25F = %s is laughing.\n\n26A = 0\n26B = LOL\n26C = That's funny!\n26D = %s is laughing out loud at you!\n26E = %s is laughing out loud at %s!\n26F = %s is laughing out loud!\n\n27A = 0\n27B = LOOK\n27C = Is it interesting?\n27D = %s is looking at you with curiosity.\n27E = %s is looking at %s with curiosity.\n27F = %s is looking around the room with curiosity.\n\n28A = 1\n28B = PUNCH\n28C = Pow!\n28D = %s just punched you in the face!\n28E = %s is punching %s in the face!\n \n29A = 0\n29B = ROFL\n29C = Pretty funny, eh?\n29D = %s is rolling on the floor laughing at you!\n29E = %s is rolling on the floor laughing at %s!\n29F = %s is rolling on the floor laughing!\n\n30A = 1\n30B = SACK\n30C = Get a motel room!\n30D = %s wants you in the sack! \n30E = %s declares that he wants %s in the sack!\n \n31A = 0\n31B = SCREAM\n31C = AAAAAAAAAAAAAAAAAAAAAAAAAAAAH!\n31D = %s is screaming at the top of their lungs at you!\n31E = %s is screaming at the top of their lungs at %s!\n31F = %s is scream at the top of their lungs!\n\n32A = 0\n32B = SIGH\n32C = Sigh...\n32D = %s turns to you and lets out a big sigh.\n32E = %s turns to %s and lets out a big sigh.\n32F = %s lets out a big sigh.\n\n33A = 1\n33B = SLAP \n33C = Thwap!\n33D = %s is slapping you silly!\n33E = %s is slapping %s silly!\n\n34A = 1\n34B = SMACK\n34C = Thwap!\n34D = %s just smacked you upside the head!\n34E = %s just smacked %s upside the head!\n\n35A = 0\n35B = SMILE\n35C = Oh stop being so happy!\n35D = %s is smiling at you.\n35E = %s is smiling at %s, could it be love?\n35F = %s is smiling, what a happy person. :)\n\n36A = 1\n36B = SMOOCH\n36C = Lay it on THICK!\n36D = %s is giving you a big wet smooch! How sweet.\n36E = %s is smooching with %s, romance isn't dead yet.\n\n37A = 0\n37B = WAVE\n37C = You look like royalty.\n37D = %s is waving to you.\n37E = %s is waving to %s\n37F = %s is waving to all.\n\n38A = 1\n38B = WINK \n38C = Ooooh!                      \n38D = %s is winking at you!\n38E = %s is winking at %s!\n  \n39A = 1\n39B = ZAP\n39C = Youch!\n39D = %s is zapping you! [OW!]\n39E = %s is zapping %s! [ouch!]\n"
  },
  {
    "path": "install/inifiles/net.ini",
    "content": ";=============================================================================\n;\n;                Network Version 5.3.0 Initialization File\n;\n;              Lines begining with a semi-colon are ignored\n;=============================================================================\n;\n[networkb]\nskip_net = N\ncrc = Y\n"
  },
  {
    "path": "install/inifiles/wwiv.ini",
    "content": ";=============================================================================\n;\n;                 WWIV Version 5.x Initialization File\n;\n;              Lines begining with a semi-colon are ignored\n;=============================================================================\n;\n; WWIV ID Block for default / common BBS settings.  This ID *must* appear as\n; the first uncommented  line in the INI file.  See individual instance \n; settings at the end of this file\n;\n[WWIV]\n;\n;=============================================================================\n;                               SPAWN OPTIONS\n;=============================================================================\n;\n; The various spawn options that may be used are:\n;\n; NOHUP        Doesn't check for hangup\n; COMIO        Intercept DOS interrupts (Win32 Only)\n; FOSSIL       Emulate the FOSSIL for DOS applications (Win32 Only)\n; NETPROG      Tries to run program in network data dir first.\n;\n; Options can be combined like so:\n;\n; SPAWNOPTS[LOGON]=FOSSIL,NOHANGUP\n;\n; Valid locations that can have spawn options specified are:\n;\n; NEWUSER, BEGINDAY, LOGON, LOGOFF ULCHK, PROT_SINGLE,\n; PROT_BATCH, ARCH_E, ARCH_V, ARCH_A, ARCH_D, ARCH_K, ARCH_T\n;\n; Values listed for lines commented out are the default settings.  Under\n; normal conditions, you should not have to edit these settings.  If you\n; have problems getting the stock spawn options to work properly with\n; your supporting program, try adding COMIO.  These are\n; the most commonly used settings.\n;\n; ----------------------------------------------------------------------------\n;\n; Event spawn options\n;\n;SPAWNOPT[NEWUSER]      =                         ; for newuser event\n;SPAWNOPT[BEGINDAY]     =                         ; for beginday event\n;SPAWNOPT[LOGON]        =                         ; for logon event\n;SPAWNOPT[LOGOFF]       =                         ; for logoff event\n;SPAWNOPT[CLEANUP]      =                         ; for cleanup event\n;SPAWNOPT[ULCHK]        = NOHUP                   ; for upload event\n;\n; External program spawn options\n;\n;SPAWNOPT[PROT_SINGLE]  = NONE                    ; for single file xfers\n;SPAWNOPT[PROT_BATCH]   = NONE                    ; for batch xfers\n;\n; Archiver spawn settings\n;\n;SPAWNOPT[ARCH_E]       =                         ; for extracting archives\n;SPAWNOPT[ARCH_L]       =                         ; for viewing archives\n;SPAWNOPT[ARCH_A]       =                         ; for adding to archives\n;SPAWNOPT[ARCH_D]       =                         ; for deleting from archives\n;SPAWNOPT[ARCH_K]       =                         ; for commenting archives\n;SPAWNOPT[ARCH_T]       =                         ; for testing archives\n;\n;=============================================================================\n;                               COLOR OPTIONS\n;=============================================================================\n;\n; NOTE:  Although the BBS is capable of using over 90 color combinations,\n; only the first ten may be set here.  The remaining colors are set from\n; inside the BBS.\n;\n; Colors are selected numerically. To determine the value for a color, use the\n; following chart:\n;\n;    0 = Black             8  = Dark Gray\n;    1 = Blue              9  = Light Blue\n;    2 = Green             10 = Light Green\n;    3 = Cyan              11 = Light Cyan\n;    4 = Red               12 = Light Red\n;    5 = Magenta           13 = Light Magenta\n;    6 = Brown             14 = Yellow\n;    7 = Light Gray        15 = White\n;\n; Now, to calculate a color, you take the value for the background color and\n; multiply by 16, then add it to the foreground color you wish. This will\n; provide the value you should use for that color combination. Note that\n; color values greater than 127 will result in blinking. In other words,\n; you should probably restrict background colors to colors 0-7 above.\n;\n; An example: if you want to find the value for, say, bright yellow on \n; magenta, it would be (5*16) + 14. This equates to (magenta * 16) + white.\n;\n; ----------------------------------------------------------------------------\nNUCOLOR[0]     = 7\nNUCOLOR[1]     = 11\nNUCOLOR[2]     = 14\nNUCOLOR[3]     = 13\nNUCOLOR[4]     = 31\nNUCOLOR[5]     = 10\nNUCOLOR[6]     = 12\nNUCOLOR[7]     = 9\nNUCOLOR[8]     = 5\nNUCOLOR[9]     = 3\nNUCOLORBW[0]   = 7\nNUCOLORBW[1]   = 15\nNUCOLORBW[2]   = 15\nNUCOLORBW[3]   = 15\nNUCOLORBW[4]   = 112\nNUCOLORBW[5]   = 15\nNUCOLORBW[6]   = 15\nNUCOLORBW[7]   = 7\nNUCOLORBW[8]   = 7\nNUCOLORBW[9]   = 7\n;\n; System Colors\n;\nTOPCOLOR               = 27           ; for topscreen info\nF1COLOR                = 9            ; for F1 user editor\nEDITLINECOLOR          = 31           ; current field in F1\nCHATSELCOLOR           = 11           ; for selecting sysop\nMSG_COLOR              = 2            ; for color msgs\n;\n;=============================================================================\n;                          EXTERNAL PROGRAM OPTIONS\n;=============================================================================\n;\n;UPLOAD_CMD     =                     ; upload event\n;BEGINDAY_CMD   =                     ; beginday event\n; Node number to handle beginday event, this should be set if you\n; want to restrict executing the beginday event to your local\n; node number.  0 means that it may be executed on any node.\nBEGINDAYNODENUMBER     = 0            ; \n;NEWUSER_CMD    =                     ; newuser event\n;LOGON_CMD      =                     ; logon event or script to run. \n                                      ; use @basic:scriptname.bas for a script\n;LOGOFF_CMD     =                     ; logoff event or script to run. \n                                      ; use @basic:scriptname.bas for a script\n;CLEANUP_CMD    =                     ; terminate cleanup event or script to\n                                      ; run. (executes after use logs off)\n;TERMINAL_CMD   = term.exe            ; WFC terminal command\n;\n;\n;=============================================================================\n;                              SYSTEM FLAGS\n;=============================================================================\n; These settings enable or disable system features.  The most commonly\n; used settings are already set for you.  You may want to experiment with\n; various settings to tailor your system to your needs.\n;\nFORCE_FBACK            = N            ; force newusers to send fback\nFORCE_SCAN             = N            ; force user to scan sysop sub\nFORCE_SCAN_SUBNUM      = 1            ; sub to force scan on (as defined in boardedit)\nPOSTTIME_COMPENS       = N            ; compensate for time posting\nIDZ_DESC               = Y            ; 1st line of file_id.diz as descrip\nREAD_CD_IDZ            = N            ; read file_id.diz from cdroms\nFSED_EXT_DESC          = Y            ; allow fsed for extended descriptions\nMAIL_PROMPT            = Y            ; fancy mail prompt\nSHOW_CITY_ST           = Y            ; show city/state in laston info\n2WAY_CHAT              = Y            ; 2-way local sysop chat\nLOG_DOWNLOADS          = N            ; send SSM to uploader on file DL\nALL_UL_TO_SYSOP        = Y            ; all uploads go to sysop dir\nMSG_TAG                = Y            ; sysop post/email taglines\nCAN_SAVE_SSM           = Y            ; allow saving of SSMs\nALLOW_ALIASES          = Y            ; allow users to use aliases\nFREE_PHONE             = N            ; allow any format phone #\nLOGON_PHONE            = N            ; check phone # at logon?\nALLOW_CC_BCC           = Y            ; allow CC: and BCC: for email?\nTITLEBAR               = Y            ; show user in console titlebar\n;\n;=============================================================================\n;                           SYSTEM TUNING PARAMETERS\n;=============================================================================\n;\nATTACH_DIR             = attach       ; dir for email attachments\nNETFOSS_DIR            = netfoss      ; directory for netfoss install (Win32)\n;\n; AutoUserPurge purges the user base of all users who have not called in\n; x days.  (Min Setting: 60) Users possessing the ADEL (bitwise:16)\n; exemption are ignored.  USE CAUTION when setting this value as it\n; could delete many dormant accounts.\n;\n;AUTO_USER_PURGE        = 60          ; Purge user base of users who\n;                                     ; have not called within x days.\n;NO_PURGE_SL            = 75          ; This SL and higher are skipped\n;\nMAX_BATCH              = 50           ; max files in batch queue\nMAX_EXTEND_LINES       = 10           ; max extended description lines\nMAX_CHAINS             = 50           ; max chains allowed\nMAX_GFILESEC           = 32           ; max gfile sections allowed\n;\n; ANSI Callout and WFC Options\n;\n;                                     ; List sequentialy i.e. CDXYZ\nSCREEN_SAVER_TIME      = 120          ; Screen saver invoke time (min.)\nINTERNALZMODEM         = Y            ; Set to N to disable internal Zmodem\nEXEC_LOG_SYNCFOSS      = N            ; Verbose logging in wwivsync.log when \n                                      ; using emulated FOSSIL.\nEXEC_CHILDWAITTIME     = 500          ; Time to wait for the DOOR to load\n                                      ; (used under Win9X)\nNEW_SCAN_AT_LOGIN      = Y            ; Ask the user to scan for new \n                                      ; messages when they log in.\nFULL_SCREEN_READER     = Y            ; Enable the full screen message reader.\nUSER_KEY_TIMEOUT       = 180          ; Timeout in seconds for non-sysops.\nSYSOP_KEY_TIMEOUT      = 600          ; Timeout in seconds for sysops.\nLOGON_KEY_TIMEOUT      = 130          ; Timeout in second for users logging in \n                                      ; (i.e. They are at the NN: prompt.)\n\nSYSTEM_BPS             = 0            ; BPS to emulate when displaying\n                                      ; .MSG/.ANS files. To emulate 9600bps you\n                                      ; would use \"SYSTEM_BPS = 9600\"\n;\n;=============================================================================\n;                           ASV OPTIONS\n;=============================================================================\n; Auto Sysop Validation (ASV) Settings allow you\n; to tailor your system to automatically validate certain users and\n; upgrade access levels based on the settings below.  By default, all\n; options are OFF.  In most cases, only systems specializing in support\n; will activate thes options.\n;\nUSE_SIMPLE_ASV                  = N         ; Use Simple ASV?\n;\n; Simple ASV values\n;\n;SIMPLE_ASV[SL]                 = 75        ; SL to assign\n;SIMPLE_ASV[DSL]                = 75        ; DSL to assign\n;SIMPLE_ASV[EXEMPT]             = 16        ; Exemption to assign\n;SIMPLE_ASV[AR]                 =           ; AR to assign\n;SIMPLE_ASV[DAR]                =           ; DAR to assign\n;SIMPLE_ASV[RESTRICT]           =           ; Restriction to assign\n;\n;=============================================================================\n;                         AVAILABLE COMPUTER TYPES\n;=============================================================================\n; These are the computer types offered to new users to choose from.\n; You may add as many as you like or edit the existing entries.  They\n; must be enumerated as shown.  Keep in mind that if you include too\n; many types, they will scroll off the screen.\n;\n[CTYPES]\nCOMP_TYPE[1]  = IBM AT (80286/80386)\nCOMP_TYPE[2]  = IBM AT (80486/80586)\nCOMP_TYPE[3]  = AMD 80686 K6/K6-2\nCOMP_TYPE[4]  = Pentium\nCOMP_TYPE[5]  = Pentium MMX/Pro\nCOMP_TYPE[6]  = Pentium II\nCOMP_TYPE[7]  = Pentium III\nCOMP_TYPE[8]  = Alpha 500-550\nCOMP_TYPE[9]  = Sparc Workstation\nCOMP_TYPE[10] = Apple / MacIntosh\nCOMP_TYPE[11] = Commodore\nCOMP_TYPE[12] = Amiga\nCOMP_TYPE[13] = Atari\nCOMP_TYPE[14] = Others\n;\n;\n;=============================================================================\n;                         END OF BBS SPECIFIC SETTING\n;=============================================================================\n;  Many third party add-ons for WWIV use this file to maintain certain\n;  settings.  You are advised to keep those settings below this point in\n;  the file for readability and integrity.\n;\n"
  },
  {
    "path": "install/menus/descript.ion",
    "content": "WWIV WWIV v5.00 Stock Menus\n"
  },
  {
    "path": "install/menus/wwiv/automsg.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"none\",\n        \"logging_action\": \"key\",\n        \"help_type\": \"always\",\n        \"generated_menu\": {\n            \"num_cols\": 6,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#7\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 0\n        },\n        \"title\": \"\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [\n            {\n                \"cmd\": \"amsg:read\",\n                \"data\": \"\",\n                \"acs\": \"\"\n            }\n        ],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": []\n            },\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"Auto-reply\",\n                \"visible\": false,\n                \"help_text\": \"Replies via email to the AutoMessage author\",\n                \"log_text\": \"AutoReply\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"amsg:email\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Delete\",\n                \"visible\": true,\n                \"help_text\": \"Delete current automessage\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"amsg:delete\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"R\",\n                \"item_text\": \"Read\",\n                \"visible\": false,\n                \"help_text\": \"Reads the current auto message\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"amsg:read\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"L\",\n                \"item_text\": \"Lock\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"Amsg:Lock\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"U\",\n                \"item_text\": \"Unlock\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"Amsg:Unlock\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"W\",\n                \"item_text\": \"Write\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 20\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"Amsg:Write\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit\",\n                \"visible\": false,\n                \"help_text\": \"Returns to the previous menu\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"ReturnFromMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Display Help\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"DisplayMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/automsg.pro",
    "content": "|#7[|#1AutoMessage|#7]|#6: |#7(|#2Q|#7)|#0uit, |#7(|#2A|#7)|#0uto-Reply, |#7(|#2R|#7)|#0ead, |#7(|#2W|#7)|#0rite|#6:|#0 .end.\n"
  },
  {
    "path": "install/menus/wwiv/bbslist.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"none\",\n        \"logging_action\": \"key\",\n        \"help_type\": \"always\",\n        \"generated_menu\": {\n            \"num_cols\": 6,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#7\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 0\n        },\n        \"title\": \"\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": []\n            },\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"Add to BBS list\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bbslist:add\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Delete\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bbslist:delete\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"R\",\n                \"item_text\": \"Read\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bbslist:read\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"N\",\n                \"item_text\": \"Net\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bbslist:net\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit\",\n                \"visible\": false,\n                \"help_text\": \"Returns to the previous menu\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"ReturnFromMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Display Help\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"DisplayMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/bbslist.pro",
    "content": "|#7[|#BBS List|#7]|#6: |#7(|#2Q|#7)|#0uit, |#7(|#2R|#7)|#0ead, |#7(|#2A|#7)|#0dd, |#7(|#2N|#7)|#0et|#6:|#0 .end.\n"
  },
  {
    "path": "install/menus/wwiv/defaults.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"none\",\n        \"logging_action\": \"command\",\n        \"help_type\": \"always\",\n        \"generated_menu\": {\n            \"num_cols\": 3,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#1\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"|[2J|#4 Your Preferences|[K|#0\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": []\n            },\n            {\n                \"item_key\": \"1\",\n                \"item_text\": \"Screen Size\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:screensize\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"2\",\n                \"item_text\": \"ANSI\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:ansistate\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"3\",\n                \"item_text\": \"Pause on screen\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:pause\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"4\",\n                \"item_text\": \"Mailbox\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:mailbox\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"5\",\n                \"item_text\": \"Configured Q-scan\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:qscan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"6\",\n                \"item_text\": \"Change password\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:password\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"7\",\n                \"item_text\": \"Update macros\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:macros\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"8\",\n                \"item_text\": \"Change colors\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:colors\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"9\",\n                \"item_text\": \"Message editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:editor\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"Extended colors\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:extra_color\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"B\",\n                \"item_text\": \"Optional lines\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:optional_lines\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"C\",\n                \"item_text\": \"Conferencing\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:conference\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Show Hidden Lines\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:ctrlcodes\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"G\",\n                \"item_text\": \"Message Reader\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:fs_reader\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"I\",\n                \"item_text\": \"Internet Address\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:email\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"K\",\n                \"item_text\": \"Configure Menus\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:menus\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"M\",\n                \"item_text\": \"Allow user msgs\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:nomsgs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"N\",\n                \"item_text\": \"Configure QWK\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"qwk:config_user\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"S\",\n                \"item_text\": \"Cls Between Msgs?\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:cls\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"T\",\n                \"item_text\": \"12hr or 24hr clock\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:24\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"U\",\n                \"item_text\": \"Use Msg AutoQuote\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:autoquote\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"W\",\n                \"item_text\": \"WWIV reg num\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"user:regnum\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit to main menu\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"ReturnFromMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/defaults.msg",
    "content": "|[2J|#4 Your Preferences|[K|#0\n\n|#11|#9) Screen size       : |#2|{user.screenwidth, \">3\"} |#9X |#2|{user.screenlines, \">3\"}        |#12|#9) ANSI              : |#2|{user.ansistr}\n|#13|#9) Pause on screen   : |#2|{if \"user.pause == true\", \"On\", \"Off\"}\n|#14|#9) Mailbox           : |#2|{user.mailbox_state}\n|#15|#9) Configured Q-scan                    |#16|#9) Change password\n|#17|#9) Update macros                        |#18|#9) Change colors\n|#19|#9) Message editor    : |#2|{user.editorname, \"<16\"} |#1A|#9) Extended colors   : |#2|{yesno \"user.extcolors == true\"}\n|#1B|#9) Optional lines    : |#2|{user.optional_lines}                |#1C|#9) Conferencing      : |#2|{yesno \"user.conferencing == true\"}\n|#1D|#9) Show Hidden Lines : |#2|{yesno \"user.show_controlcodes == true\", \"<16\"} |#1G|#9) Message Reader    : |#2|{if \"user.fs_reader == true\", \"Full-Screen\", \"Traditional\"}\n|#1I|#9) Internet Address  : |#2|{user.email}\n|#1K|#9) Configure Menus\n|#1M|#9) Allow user msgs   : |#2|{yesno \"user.ignore_msgs == false\", \"<16\"} |#1N|#9) Configure QWK\n|#1S|#9) Cls Between Msgs? : |#2|{yesno \"user.clear_screen == true\", \"<16\"} |#1T|#9) 12hr or 24hr clock: |#2|{if \"user.twentyfour_clock == true\", \"24hr\", \"12hr\"}\n|#1U|#9) Use Msg AutoQuote : |#2|{yesno \"user.auto_quote == true\", \"<16\"} |#W|#9) WWIV reg num      : |#2|{user.regnum}\n|#1Q|#9) Quit to main menu\n\n"
  },
  {
    "path": "install/menus/wwiv/defaults.pro",
    "content": "\n|#9Defaults: .end.\n"
  },
  {
    "path": "install/menus/wwiv/main.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"subs\",\n        \"logging_action\": \"key\",\n        \"help_type\": \"user_choice\",\n        \"generated_menu\": {\n            \"num_cols\": 3,\n            \"color_title\": \"|#5\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#1\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"WWIV Main Menu\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"IE\",\n                \"item_text\": \"InstanceEdit\",\n                \"visible\": true,\n                \"help_text\": \"Enter the instance editor\",\n                \"log_text\": \"IE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"instanceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"JE\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Edit the XFER/MSG conferences\",\n                \"log_text\": \"JE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"conferenceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"BE\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Edit the sub boards\",\n                \"log_text\": \"BE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"subedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CE\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Edit the setups to run external programs\",\n                \"log_text\": \"CE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"chainedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CHAT\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Toggle the ability for users to call the sysop to chat\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"toggleavailable\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CU\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Change into a different user\",\n                \"log_text\": \"-* Changed Users\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"changeuser\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"DE\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Edit the transfers directories\",\n                \"log_text\": \"DE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"diredit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"TEDIT\",\n                \"item_text\": \"TextEdit\",\n                \"visible\": true,\n                \"help_text\": \"Edit a text file\",\n                \"log_text\": \"TEDIT\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"textedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"GE\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Edit the bulletin area\",\n                \"log_text\": \"GE\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bulletinedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"LOAD\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Load Text File Into Editor\",\n                \"log_text\": \"LOAD\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"loadtext\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"MAILR\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"-* Read All Mail\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"readallmail\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"RESETQSCAN\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"Set ALL Messages to UNread\",\n                \"log_text\": \"RESETQSCAN\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"resetqscan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"IVOTES\",\n                \"item_text\": \"VoteEdit\",\n                \"visible\": false,\n                \"help_text\": \"Initialize Votes\",\n                \"log_text\": \"IVOTES\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"voteedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"LOG\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"View Today's Log\",\n                \"log_text\": \"LOG\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"log\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"NLOG\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"View NetLog\",\n                \"log_text\": \"NLOG\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"netlog\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"PENDING\",\n                \"item_text\": \"Pending NetData\",\n                \"visible\": false,\n                \"help_text\": \"Display Pending Network Data\",\n                \"log_text\": \"PENDING\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"pending\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"STATUS\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"Display Current System Status\",\n                \"log_text\": \"STATUS\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"status\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"VOTEPRINT\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"View Voting Data\",\n                \"log_text\": \"VOTEPRINT\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"voteprint\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"YLOG\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"View Yesterday's Log\",\n                \"log_text\": \"YLOG\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"ylog\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"ZLOG\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"View Activity Log\",\n                \"log_text\": \"ZLOG\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"zlog\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"UPLOAD\",\n                \"item_text\": \"Upload Post\",\n                \"visible\": true,\n                \"help_text\": \"Upload Text File to Post in next Email or Message\",\n                \"log_text\": \"UPLOAD\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.validated == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"uploadpost\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"QWK\",\n                \"item_text\": \"QWK Mail\",\n                \"visible\": true,\n                \"help_text\": \"QWK\",\n                \"log_text\": \"QWK\",\n                \"instance_message\": \"QWK Mail Processing\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"MENU\",\n                        \"data\": \"qwk\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CLS\",\n                \"item_text\": \"Clear Screen\",\n                \"visible\": false,\n                \"help_text\": \"Clear Screen\",\n                \"log_text\": \"CLS\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"cls\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"NET\",\n                \"item_text\": \"Net Listings\",\n                \"visible\": false,\n                \"help_text\": \"View Network Listings\",\n                \"log_text\": \"NET\",\n                \"instance_message\": \"Net Listing\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"netlisting\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"WHO\",\n                \"item_text\": \"Who's On?\",\n                \"visible\": false,\n                \"help_text\": \"Display Users on other Instances\",\n                \"log_text\": \"WHO\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"who\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"QSCAN\",\n                \"item_text\": \"Clear Qscan\",\n                \"visible\": false,\n                \"help_text\": \"Set all Messages to READ\",\n                \"log_text\": \"QSCAN\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"clearqscan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"VER\",\n                \"item_text\": \"WWIV Version\",\n                \"visible\": true,\n                \"help_text\": \"Display WWIV Version Info\",\n                \"log_text\": \"//VER\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"wwivver\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/A\",\n                \"item_text\": \"All New Msgs\",\n                \"visible\": true,\n                \"help_text\": \"NewScan All Conferences\",\n                \"log_text\": \"/A\",\n                \"instance_message\": \"NewScan\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newmsgsallconfs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/E\",\n                \"item_text\": \"Multi Email\",\n                \"visible\": true,\n                \"help_text\": \"Multi-Mail Menu\",\n                \"log_text\": \"/E\",\n                \"instance_message\": \"MultiEmail\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"multiemail\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/N\",\n                \"item_text\": \"NewScan From Here\",\n                \"visible\": true,\n                \"help_text\": \"NewScan Messages from Current Sub\",\n                \"log_text\": \"/N\",\n                \"instance_message\": \"NewScan\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newmsgscanfromhere\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/O\",\n                \"item_text\": \"Fast LogOff\",\n                \"visible\": true,\n                \"help_text\": \"LogOff Fast\",\n                \"log_text\": \"/O\",\n                \"instance_message\": \"Logging Off\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"fastgoodbye\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/?\",\n                \"item_text\": \"Sysop Slash Menu\",\n                \"visible\": true,\n                \"help_text\": \"Display Sysop Slash Commands List\",\n                \"log_text\": \"/?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"printfile\",\n                        \"data\": \"smain\",\n                        \"acs\": \"\"\n                    },\n                    {\n                        \"cmd\": \"Pause\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/V\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Validate Pending Posts\",\n                \"log_text\": \"/V\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"validateposts\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/C\",\n                \"item_text\": \"Chat Room\",\n                \"visible\": true,\n                \"help_text\": \"Enter WWIV ChatRoom\",\n                \"log_text\": \"/C\",\n                \"instance_message\": \"ChatRoom\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"chatroom\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"+\",\n                \"item_text\": \"Up One Sub (+, ], >)\",\n                \"visible\": false,\n                \"help_text\": \"Up One Sub\",\n                \"log_text\": \"+\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"upsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \">\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \">\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"upsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"]\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"]\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"upsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"-\",\n                \"item_text\": \"Down One Sub (-, [, <)\",\n                \"visible\": false,\n                \"help_text\": \"Down One Sub\",\n                \"log_text\": \"-\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"<\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"<\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"[\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"[\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"}\",\n                \"item_text\": \"Up One Conference\",\n                \"visible\": true,\n                \"help_text\": \"Up One Conference\",\n                \"log_text\": \"}\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"upsubconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"{\",\n                \"item_text\": \"Down One Conference\",\n                \"visible\": true,\n                \"help_text\": \"Down One Conference\",\n                \"log_text\": \"{\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downsubconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"!\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"Validate User\",\n                \"log_text\": \"!\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"validateuser\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \".\",\n                \"item_text\": \"Doors\",\n                \"visible\": true,\n                \"help_text\": \"Chains Menu\",\n                \"log_text\": \".\",\n                \"instance_message\": \"Doors\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"doors\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"$\",\n                \"item_text\": \"Time Bank\",\n                \"visible\": true,\n                \"help_text\": \"Enter Time Bank\",\n                \"log_text\": \"$\",\n                \"instance_message\": \"Time Bank\",\n                \"acs\": \"user.validated == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"timebank\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"AutoMessage\",\n                \"visible\": true,\n                \"help_text\": \"Display AutoMessage\",\n                \"log_text\": \"A\",\n                \"instance_message\": \"AutoMessage\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"MENU\",\n                        \"data\": \"automsg\",\n                        \"acs\": \"user.sl >= 10\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"B\",\n                \"item_text\": \"BBS List\",\n                \"visible\": true,\n                \"help_text\": \"Display BBS List\",\n                \"log_text\": \"B\",\n                \"instance_message\": \"BBS List\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"MENU\",\n                        \"data\": \"bbslist\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"C\",\n                \"item_text\": \"Request Chat\",\n                \"visible\": true,\n                \"help_text\": \"Request CHat w/Sysop\",\n                \"log_text\": \"C\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"requestchat\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Defaults\",\n                \"visible\": true,\n                \"help_text\": \"Edit user settings\",\n                \"log_text\": \"RAN Defaults\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"MENU\",\n                        \"data\": \"defaults\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"E\",\n                \"item_text\": \"Email\",\n                \"visible\": true,\n                \"help_text\": \"Send Email\",\n                \"log_text\": \"E\",\n                \"instance_message\": \"Email\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"sendemail\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"F\",\n                \"item_text\": \"FeedBack\",\n                \"visible\": true,\n                \"help_text\": \"Send FeedBack to Sysop\",\n                \"log_text\": \"F\",\n                \"instance_message\": \"FeedBack\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"feedback\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"G\",\n                \"item_text\": \"Gfiles\",\n                \"visible\": true,\n                \"help_text\": \"Display Gfiles\",\n                \"log_text\": \"G\",\n                \"instance_message\": \"Gfiles\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bulletins\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"H\",\n                \"item_text\": \"Hop Subs\",\n                \"visible\": true,\n                \"help_text\": \"Hop to Sub\",\n                \"log_text\": \"H\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"hopsub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"I\",\n                \"item_text\": \"System Info\",\n                \"visible\": true,\n                \"help_text\": \"Display System Info\",\n                \"log_text\": \"I\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"systeminfo\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"J\",\n                \"item_text\": \"Jump Confs\",\n                \"visible\": true,\n                \"help_text\": \"Jump to another Confernce\",\n                \"log_text\": \"J\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"jumpsubconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"K\",\n                \"item_text\": \"Kill Email\",\n                \"visible\": true,\n                \"help_text\": \"Delete Email you Sent\",\n                \"log_text\": \"K\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"killemail\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"L\",\n                \"item_text\": \"Last Few Callers\",\n                \"visible\": true,\n                \"help_text\": \"Display Last Few Callers\",\n                \"log_text\": \"L\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"lastcallers\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"M\",\n                \"item_text\": \"Read Email\",\n                \"visible\": true,\n                \"help_text\": \"Read your Email\",\n                \"log_text\": \"M\",\n                \"instance_message\": \"Reading Email\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"reademail\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"N\",\n                \"item_text\": \"NewScan Messages\",\n                \"visible\": true,\n                \"help_text\": \"NewScan Messages in Current Conference\",\n                \"log_text\": \"N\",\n                \"instance_message\": \"NewScanning Messages\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newmessagescan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"O\",\n                \"item_text\": \"Normal LogOff\",\n                \"visible\": true,\n                \"help_text\": \"Normal LogOff\",\n                \"log_text\": \"O\",\n                \"instance_message\": \"Logging Off\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"goodbye\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"P\",\n                \"item_text\": \"Post Message\",\n                \"visible\": true,\n                \"help_text\": \"Post Message in Current Sub\",\n                \"log_text\": \"P\",\n                \"instance_message\": \"Posting Message\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"postmessage\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"QuickScan Current Sub\",\n                \"visible\": true,\n                \"help_text\": \"Quick NewScan of Current Sub\",\n                \"log_text\": \"Q\",\n                \"instance_message\": \"NewScanning Messages\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newmsgscancursub\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"R\",\n                \"item_text\": \"Remove Post\",\n                \"visible\": true,\n                \"help_text\": \"Remove Message you Posted\",\n                \"log_text\": \"R\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"removepost\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"S\",\n                \"item_text\": \"Scan Titles\",\n                \"visible\": true,\n                \"help_text\": \"Scan Titles in Current Sub\",\n                \"log_text\": \"S\",\n                \"instance_message\": \"Scanning Messages\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"titlescan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"T\",\n                \"item_text\": \"Transfer Section\",\n                \"visible\": true,\n                \"help_text\": \"Go To Transfer Section\",\n                \"log_text\": \"T\",\n                \"instance_message\": \"Transfer Section\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"menu\",\n                        \"data\": \"xfer\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"U\",\n                \"item_text\": \"List Users\",\n                \"visible\": true,\n                \"help_text\": \"List Users w/access to Current Sub\",\n                \"log_text\": \"U\",\n                \"instance_message\": \"User List\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"listusers\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"~\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"~\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"listusers\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"V\",\n                \"item_text\": \"Vote\",\n                \"visible\": true,\n                \"help_text\": \"Enter Voting Booth\",\n                \"log_text\": \"V\",\n                \"instance_message\": \"Voting\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"vote\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"X\",\n                \"item_text\": \"Toggle Expert\",\n                \"visible\": true,\n                \"help_text\": \"Toggle Expert Mode\",\n                \"log_text\": \"X\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"toggleexpert\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Y\",\n                \"item_text\": \"Your Info\",\n                \"visible\": true,\n                \"help_text\": \"Display Your Info\",\n                \"log_text\": \"Y\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"yourinfo\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Z\",\n                \"item_text\": \"Zippy NewScan\",\n                \"visible\": true,\n                \"help_text\": \"NewScan Message Base Only\",\n                \"log_text\": \"Z\",\n                \"instance_message\": \"NewScanning\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"expressscan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"*\",\n                \"item_text\": \"Sub List\",\n                \"visible\": true,\n                \"help_text\": \"List Available Subs\",\n                \"log_text\": \"*\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"sublist\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"RETURN\",\n                \"item_text\": \"\",\n                \"visible\": false,\n                \"help_text\": \"\",\n                \"log_text\": \"RETURN\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"returnfrommenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Display Help\",\n                \"visible\": true,\n                \"help_text\": \"Display Current Menu\",\n                \"log_text\": \"?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"menu:display\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"APPLY\",\n                \"item_text\": \"Guest Apply\",\n                \"visible\": true,\n                \"help_text\": \"Allows GUEST to Apply for an Account\",\n                \"log_text\": \"APPLY\",\n                \"instance_message\": \"New User Logon\",\n                \"acs\": \"user.guest == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"guestapply\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"UNQSCAN\",\n                \"item_text\": \"UnQScan\",\n                \"visible\": true,\n                \"help_text\": \"Mark all Messages as UNread\",\n                \"log_text\": \"UNQSCAN\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"unqscan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"ATTACH\",\n                \"item_text\": \"Attach File\",\n                \"visible\": true,\n                \"help_text\": \"Attach File to Email\",\n                \"log_text\": \"ATTACH\",\n                \"instance_message\": \"Email\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"attachfile\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"VISIT\",\n                \"item_text\": \"Visiting Sysops\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 60 && user.dsl >= 60\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"menu\",\n                        \"data\": \"vissys\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"W\",\n                \"item_text\": \"Slash Menu\",\n                \"visible\": true,\n                \"help_text\": \"Slash Menu\",\n                \"log_text\": \"W\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"printfile\",\n                        \"data\": \"mbslash.msg\",\n                        \"acs\": \"\"\n                    },\n                    {\n                        \"cmd\": \"Pause\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"SYSOP\",\n                \"item_text\": \"Sysop Menu\",\n                \"visible\": true,\n                \"help_text\": \"Display Sysop Menu\",\n                \"log_text\": \"SYSOP\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"menu\",\n                        \"data\": \"sysop\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \",\",\n                \"item_text\": \"ViewNetDataLog\",\n                \"visible\": true,\n                \"help_text\": \"View Net Data Log Files\",\n                \"log_text\": \",\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"viewnetdatalog\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"COLORS\",\n                \"item_text\": \"ColorConfig\",\n                \"visible\": false,\n                \"help_text\": \"Configure Colors\",\n                \"log_text\": \"COLORS\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"colorconfig\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CONFEDIT\",\n                \"item_text\": \"ConferenceEdit\",\n                \"visible\": false,\n                \"help_text\": \"Edit Conferences\",\n                \"log_text\": \"CONFEDIT\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"conferenceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"EDIT\",\n                \"item_text\": \"Edit\",\n                \"visible\": false,\n                \"help_text\": \"Edit ANY Text File\",\n                \"log_text\": \"EDIT\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.dsl >= 255\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"edit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/main.msg",
    "content": "                            |#4 WWIV Main Menu |#0\n|#7ͻ\n|#7|#4Message Center|#7|#4Miscellaneous|#7|#4E-Mail|#7Ķ\n|#7|#2N|#1>|#0 New Msgs, All Subs|#7     |#2A|#1>|#0 Auto-Message|#7       |#2E|#1>|#0 E-mail User|#7           \n|#7|#2P|#1>|#0 Post a Message|#7         |#2B|#1>|#0 BBS List|#7           |#2M|#1>|#0 Read E-mail|#7           \n|#7|#2R|#1>|#0 Remove a message|#7       |#2C|#1>|#0 Chat with Sysop|#7    |#2F|#1>|#0 Send Feedback|#7         \n|#7|#2S|#1>|#0 Scan Current Msg Base|#7  |#2I|#1>|#0 System Information|#7 |#2K|#1>|#0 Kill Sent E-mail|#7      \n|#7|#2Z|#1>|#0 Scan All Subs Non-Stop|#7 |#2L|#1>|#0 Last Caller List|#7                        |#7    \n|#7|#2#|#1>|#0 Enter Number of Sub|#7    |#2O|#1>|#0 Log Off|#7            |#4System Features|#7Ķ\n|#7|#2J|#1>|#0 Join Conference|#7        |#2U|#0 or |#2~ |#1>|#0 User List|#7    |#2D|#1>|#0 Change Your Defaults|#7  \n|#7|#2*|#1>|#0 List Subs Available|#7    |#2V|#1>|#0 Voting Booth|#7       |#2G|#1>|#0 Read General Files|#7    \n|#7|#2>|#0, |#2]|#0 or |#2+|#1>|#0 Advance 1 Sub|#7  |#2X|#1>|#0 Toggle Xpert Mode|#7  |#2T|#1>|#0 Transfer Section|#7      \n|#7|#2<|#0, |#2[|#2 or |#2-|#1>|#0 Retreat 1 Sub|#7  |#2Y|#1>|#0 Your Information|#7   |#2.|#1>|#0 On-Line Programs|#7      \n|#7|#2}|#1>|#0 Advance 1 Conference|#7   |#2CTRL Y|#1>|#0 Toggle Pause|#7  |#2$|#1>|#0 Use Time Bank|#7         \n|#7|#2{|#1>|#0 Retreat 1 Conference|#7   |#2QWK|#1> |#0QWK Offline Mail |#7                    |#7     \n|#7|#2H|#1>|#0 Hop to Another Sub|#7     |#2                  |#7    |#2              |#7           \n|#7Ķ\n|#7|#2W|#1>|#0 WWIV Slash Menu                              |#2Ctrl T|#1>|#0 Time left On-Line|#7  \n|#7ͼ\n"
  },
  {
    "path": "install/menus/wwiv/main.pro",
    "content": "|#7Time Left|#6: |#1|@% |#7minutes\n|#3Conference|#6: |#5|@J\n|#7[|#0|@:|#7] [|#1|@u|#7]|#6:|#0 .end."
  },
  {
    "path": "install/menus/wwiv/menuset.json",
    "content": "{\n    \"version\": 1,\n    \"menuset\": {\n        \"name\": \"wwiv\",\n        \"description\": \"wwiv v5.00 stock menus\",\n        \"acs\": \"\",\n        \"items\": [\n            {\n                \"item_key\": \"/O\",\n                \"item_text\": \"Fast Logoff\",\n                \"visible\": true,\n                \"help_text\": \"Log off immediately\",\n                \"log_text\": \"Logged off using '/O'\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"FastGoodBye\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/qwk.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": true,\n        \"num_action\": \"none\",\n        \"logging_action\": \"none\",\n        \"help_type\": \"always\",\n        \"generated_menu\": {\n            \"num_cols\": 1,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#9\",\n            \"color_item_braces\": \"|#9\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"|[2J|#4QWK Menu|[K|#0\",\n        \"acs\": \"user.sl >= 10\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": []\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Download\",\n                \"visible\": true,\n                \"help_text\": \"Download QWK Packet\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"qwk:download\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"U\",\n                \"item_text\": \"Upload Reply\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"qwk:upload\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"ReturnFromMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"C\",\n                \"item_text\": \"Configure Settings\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"qwk:config_user\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"*\",\n                \"item_text\": \"Sysop Menu\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"qwk:config_sysop\",\n                        \"data\": \"\",\n                        \"acs\": \"user.sysop\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Help\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"DisplayMenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/qwk.pro",
    "content": "|#7Time Left|#6: |#1|@% |#7minutes\n|#7[|#1QWK Menu|#7] |#6: |#0.end.\n"
  },
  {
    "path": "install/menus/wwiv/sysop.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": true,\n        \"num_action\": \"none\",\n        \"logging_action\": \"command\",\n        \"help_type\": \"user_choice\",\n        \"generated_menu\": {\n            \"num_cols\": 2,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#1\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"|#5Sysop Menu\",\n        \"acs\": \"user.sysop == true\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"Allow Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"AE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"allowedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"B\",\n                \"item_text\": \"Sub Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"BE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"subedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"C\",\n                \"item_text\": \"Chain Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"CE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"chainedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Dir Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"DE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"diredit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"G\",\n                \"item_text\": \"Bulletin Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"GE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"bulletinedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"I\",\n                \"item_text\": \"Instance Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"IE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"instanceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"J\",\n                \"item_text\": \"Conference Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"JE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"conferenceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"T\",\n                \"item_text\": \"Text Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"TE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"textedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"V\",\n                \"item_text\": \"Voting Editor\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"VE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"voteedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"K\",\n                \"item_text\": \"Print Votes\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"VP\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"voteprint\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"Q\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"returnfrommenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Display Help\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"displayhelp\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/sysop.pro",
    "content": "|#7Time Left|#6: |#1|@% |#7minutes\n|#7[|#1Sysop Menu|#7] |#6: |#0.end."
  },
  {
    "path": "install/menus/wwiv/vissys.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"none\",\n        \"logging_action\": \"key\",\n        \"help_type\": \"on_entrance\",\n        \"generated_menu\": {\n            \"num_cols\": 3,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#1\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"Visting Sysops\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [\n            {\n                \"cmd\": \"miniconf\",\n                \"data\": \"VISSYS\",\n                \"acs\": \"\"\n            }\n        ],\n        \"exit_actions\": [\n            {\n                \"cmd\": \"miniconf\",\n                \"data\": \"VISSYS\",\n                \"acs\": \"\"\n            }\n        ],\n        \"items\": [\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit back to Main\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"Q\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"returnfrommenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Help\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"displayhelp\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"X\",\n                \"item_text\": \"Toggle Expert\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"X\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"toggleexpert\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"L\",\n                \"item_text\": \"List Files\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"L\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"dirlist\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    },\n                    {\n                        \"cmd\": \"selectdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    },\n                    {\n                        \"cmd\": \"listfiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"N\",\n                \"item_text\": \"List New Files\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"N\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newfilescan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"F\",\n                \"item_text\": \"Feedback to the Sysop\",\n                \"visible\": true,\n                \"help_text\": \"Leave the sysop a note\",\n                \"log_text\": \"F\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"feedback\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}"
  },
  {
    "path": "install/menus/wwiv/vissys.msg",
    "content": "\n|#7    |#4 Welcome Visiting Sysops|#7 Ŀ\n|#7                                                                       \n|#7    |#2  R|#1>|#0 Read Messages  |#2  Q|#1>|#0 Quit back to Main  |#2  F|#1>|#0 Leave Feedback   |#7 \n|#7    |#2  L|#1>|#0 List files     |#2  X|#1>|#0 Toggle Expert Mod  |#0     to Sysop         |#7 \n|#7    |#2  N|#1>|#0 New files      |#2  ?|#1>|#0 Help                                     |#7 \n|#7                                                                       \n|#7    \n"
  },
  {
    "path": "install/menus/wwiv/vissys.pro",
    "content": "|#7Time Left|#6: |#1|@% |#7minutes\n|#7[|#2|@:|#7] [|#1|@u|#7]|#6:|#0\n|#7[|#1Visiting Sysop Menu|#7] |#6: |#0.end."
  },
  {
    "path": "install/menus/wwiv/xfer.mnu.json",
    "content": "{\n    \"version\": 1,\n    \"menu\": {\n        \"cls\": false,\n        \"num_action\": \"dirs\",\n        \"logging_action\": \"key\",\n        \"help_type\": \"user_choice\",\n        \"generated_menu\": {\n            \"num_cols\": 3,\n            \"color_title\": \"|#4\",\n            \"color_item_key\": \"|#2\",\n            \"color_item_text\": \"|#0\",\n            \"color_item_braces\": \"|#1\",\n            \"show_empty_text\": false,\n            \"num_newlines_at_end\": 1\n        },\n        \"title\": \"Transfer Menu\",\n        \"acs\": \"\",\n        \"password\": \"\",\n        \"enter_actions\": [],\n        \"exit_actions\": [],\n        \"items\": [\n            {\n                \"item_key\": \">\",\n                \"item_text\": \"Up One Dir (+, ], >)\",\n                \"visible\": true,\n                \"help_text\": \"Up One Directory\",\n                \"log_text\": \">\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"updir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Q\",\n                \"item_text\": \"Quit to Main Menu\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"Q\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"returnfrommenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"<\",\n                \"item_text\": \"Down One Dir (-, [, <)\",\n                \"visible\": true,\n                \"help_text\": \"Down One Directory\",\n                \"log_text\": \"<\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"-\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"-\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"[\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"[\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"+\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"+\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"updir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"]\",\n                \"item_text\": \"\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"]\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"updir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"*\",\n                \"item_text\": \"List Dirs\",\n                \"visible\": true,\n                \"help_text\": \"List Directories\",\n                \"log_text\": \"*\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"dirlist\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"H\",\n                \"item_text\": \"Hop to New Dir\",\n                \"visible\": true,\n                \"help_text\": \"Enter partial directory name to hop to\",\n                \"log_text\": \"H\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"hopdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"}\",\n                \"item_text\": \"Up One Conference\",\n                \"visible\": true,\n                \"help_text\": \"Up One Conference\",\n                \"log_text\": \"}\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"updirconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"{\",\n                \"item_text\": \"Down One Conference\",\n                \"visible\": true,\n                \"help_text\": \"Down One Conference\",\n                \"log_text\": \"{\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"downdirconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"J\",\n                \"item_text\": \"Select Conference\",\n                \"visible\": true,\n                \"help_text\": \"Manually Select Conference\",\n                \"log_text\": \"J\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"jumpdirconf\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CHANGEDIR\",\n                \"item_text\": \"Change Dir\",\n                \"visible\": true,\n                \"help_text\": \"Change Directory Select\",\n                \"log_text\": \"CHANGEDIR\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"dirlist\",\n                        \"data\": \"~ SelectDir\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"F\",\n                \"item_text\": \"Search Files by Description\",\n                \"visible\": true,\n                \"help_text\": \"Search Files by Description\",\n                \"log_text\": \"F\",\n                \"instance_message\": \"File Search\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"finddescription\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"L\",\n                \"item_text\": \"List Files\",\n                \"visible\": true,\n                \"help_text\": \"Display Available Files in Current Dir\",\n                \"log_text\": \"L\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"listfiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"N\",\n                \"item_text\": \"New File Scan\",\n                \"visible\": true,\n                \"help_text\": \"Scan for New Files\",\n                \"log_text\": \"N\",\n                \"instance_message\": \"Scanning Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newfilescan\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/A\",\n                \"item_text\": \"New Files (All Confs)\",\n                \"visible\": true,\n                \"help_text\": \"List new files in all conferences\",\n                \"log_text\": \"/A\",\n                \"instance_message\": \"Scanning Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"newfilesallconfs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"S\",\n                \"item_text\": \"Search by FileName\",\n                \"visible\": true,\n                \"help_text\": \"Seach for files by wildcard filenames\",\n                \"log_text\": \"S\",\n                \"instance_message\": \"Scanning Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"searchallfiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"B\",\n                \"item_text\": \"Batch Commands\",\n                \"visible\": true,\n                \"help_text\": \"Batch Menu\",\n                \"log_text\": \"B\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"batchmenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"D\",\n                \"item_text\": \"Download Files\",\n                \"visible\": true,\n                \"help_text\": \"Download Files\",\n                \"log_text\": \"D\",\n                \"instance_message\": \"Downloading Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"download\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"U\",\n                \"item_text\": \"Upload Files\",\n                \"visible\": true,\n                \"help_text\": \"You send the BBS a file\",\n                \"log_text\": \"U\",\n                \"instance_message\": \"Uploading Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"upload\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Z\",\n                \"item_text\": \"Upload to Sysop\",\n                \"visible\": true,\n                \"help_text\": \"Upload a file that no one but the sysop can see\",\n                \"log_text\": \"Z\",\n                \"instance_message\": \"Uploading Files\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"uploadtosysop\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"K\",\n                \"item_text\": \"Configure File List\",\n                \"visible\": true,\n                \"help_text\": \"Config your listplus menus to show what you want\",\n                \"log_text\": \"K\",\n                \"instance_message\": \"Configuring File List\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"configfilelist\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"~\",\n                \"item_text\": \"List Users\",\n                \"visible\": true,\n                \"help_text\": \"Lists users with access to the dir you are currently in\",\n                \"log_text\": \"~\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"listusersdl\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"P\",\n                \"item_text\": \"Set 'New Files' Date\",\n                \"visible\": true,\n                \"help_text\": \"Sets the date the computer will use to determin new files\",\n                \"log_text\": \"P\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"setnewfilescandate\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"Y\",\n                \"item_text\": \"Your DL Info\",\n                \"visible\": true,\n                \"help_text\": \"Display Your Download Info\",\n                \"log_text\": \"Y\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"yourinfodl\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"A\",\n                \"item_text\": \"Archive Commands\",\n                \"visible\": true,\n                \"help_text\": \"Enters the temporary archive menu\",\n                \"log_text\": \"A\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"archivemenu\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"E\",\n                \"item_text\": \"Extract Commands\",\n                \"visible\": true,\n                \"help_text\": \"Extracts a file to the archive menu\",\n                \"log_text\": \"E\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"tempextract\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"V\",\n                \"item_text\": \"View Archive\",\n                \"visible\": true,\n                \"help_text\": \"View an archived file\",\n                \"log_text\": \"V\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"viewarchive\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"T\",\n                \"item_text\": \"Xfer Defaults\",\n                \"visible\": true,\n                \"help_text\": \"Set the defaults for the XFER section\",\n                \"log_text\": \"T\",\n                \"instance_message\": \"Xfer Defaults\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"xferdefaults\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"M\",\n                \"item_text\": \"Move Files\",\n                \"visible\": true,\n                \"help_text\": \"\",\n                \"log_text\": \"M\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.dsl >= 100 && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"movefiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \".\",\n                \"item_text\": \"Print DSZ.LOG\",\n                \"visible\": true,\n                \"help_text\": \"Displays Current DSZ.LOG File\",\n                \"log_text\": \".\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.dsl >= 100 && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"printdszlog\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"R\",\n                \"item_text\": \"Remove Files\",\n                \"visible\": true,\n                \"help_text\": \"Remove Files from Database\",\n                \"log_text\": \"R\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.dsl >= 100 && user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"removefiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"X\",\n                \"item_text\": \"Toggle Expert\",\n                \"visible\": true,\n                \"help_text\": \"Turn novice menus on and off\",\n                \"log_text\": \"X\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"toggleexpert\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"?\",\n                \"item_text\": \"Help\",\n                \"visible\": true,\n                \"help_text\": \"Display Menu\",\n                \"log_text\": \"?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"displayhelp\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/O\",\n                \"item_text\": \"Fast LogOff\",\n                \"visible\": true,\n                \"help_text\": \"Logoff without showing logoff ansi or other good stuff\",\n                \"log_text\": \"/O\",\n                \"instance_message\": \"Logging Off\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"fastgoodbye\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"O\",\n                \"item_text\": \"Normal LogOff\",\n                \"visible\": true,\n                \"help_text\": \"Normal termination from the BBS\",\n                \"log_text\": \"O\",\n                \"instance_message\": \"Logging Off\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"goodbye\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"UPLOAD\",\n                \"item_text\": \"UL Files Current Dir\",\n                \"visible\": true,\n                \"help_text\": \"Upload Local File in Current Dir\",\n                \"log_text\": \"//UPLOAD\",\n                \"instance_message\": \"Uploading \",\n                \"acs\": \"user.sl >= 200 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"uploadcurdir\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"UPLOADALL\",\n                \"item_text\": \"UL All Dirs\",\n                \"visible\": true,\n                \"help_text\": \"Upload Local Files in ALL Dirs\",\n                \"log_text\": \"//UPLOADALL\",\n                \"instance_message\": \"Uploading\",\n                \"acs\": \"user.sl >= 255 && user.sysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"uploadalldirs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/T\",\n                \"item_text\": \"Test Archive\",\n                \"visible\": true,\n                \"help_text\": \"Tests integrity of any archive\",\n                \"log_text\": \"/T\",\n                \"instance_message\": \"Testing Archive\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"testarc\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/D\",\n                \"item_text\": \"Delete BBS Ads\",\n                \"visible\": true,\n                \"help_text\": \"Deletes BBS Ads from archive\",\n                \"log_text\": \"/D\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"deleteads\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/K\",\n                \"item_text\": \"Comment Archive\",\n                \"visible\": true,\n                \"help_text\": \"Adds COMMENT.TXT to archive\",\n                \"log_text\": \"/K\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.cosysop == true\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"addcomment\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"/?\",\n                \"item_text\": \"Slash Commands\",\n                \"visible\": true,\n                \"help_text\": \"Display Extended Command Menu\",\n                \"log_text\": \"/?\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"printfile\",\n                        \"data\": \"strans.msg\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"W\",\n                \"item_text\": \"Slash Menu\",\n                \"visible\": true,\n                \"help_text\": \"Slash Menu\",\n                \"log_text\": \"W\",\n                \"instance_message\": \"Display Extended Command Menu\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"printfile\",\n                        \"data\": \"tslash.msg\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"DE\",\n                \"item_text\": \"DirEdit\",\n                \"visible\": true,\n                \"help_text\": \"Dir Editor\",\n                \"log_text\": \"DE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"diredit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"JE\",\n                \"item_text\": \"Conf Edit\",\n                \"visible\": true,\n                \"help_text\": \"Edit SUBS/XFER Conferences\",\n                \"log_text\": \"JE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"conferenceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"SYSOP\",\n                \"item_text\": \"Sysop Menu\",\n                \"visible\": true,\n                \"help_text\": \"Sysop Functions\",\n                \"log_text\": \"SYSOP\",\n                \"instance_message\": \"\",\n                \"acs\": \"user.sl >= 255 && user.dsl >= 255\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"menu\",\n                        \"data\": \"sysop\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"CONFEDIT\",\n                \"item_text\": \"Conf Edit\",\n                \"visible\": true,\n                \"help_text\": \"Edit SUBS/XFER Conferences\",\n                \"log_text\": \"CONFEDIT\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"conferenceedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"SORT\",\n                \"item_text\": \"Sort Dirs\",\n                \"visible\": true,\n                \"help_text\": \"Sort Xfer Dirs\",\n                \"log_text\": \"SORT\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"sortdirs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"RSORT\",\n                \"item_text\": \"RSort Dirs\",\n                \"visible\": true,\n                \"help_text\": \"Sort Xfer Dirs In Reverse Order\",\n                \"log_text\": \"RSORT\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"reversesortdirs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"READIDZ\",\n                \"item_text\": \"ReadIDZ\",\n                \"visible\": true,\n                \"help_text\": \"Read in File_id.diz as description\",\n                \"log_text\": \"READIDZ\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"readidz\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"MOVE\",\n                \"item_text\": \"MoveFiles\",\n                \"visible\": true,\n                \"help_text\": \"Move File(s) to other areas\",\n                \"log_text\": \"MOVE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"movefiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"AE\",\n                \"item_text\": \"AllowEdit\",\n                \"visible\": true,\n                \"help_text\": \"Run AllowEdit\",\n                \"log_text\": \"AE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"allowedit\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"UPLOADFILE\",\n                \"item_text\": \"UploadFilesBBS\",\n                \"visible\": true,\n                \"help_text\": \"Upload from FILES.BBS\",\n                \"log_text\": \"UPLOADFILE\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"uploadfilesbbs\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"REN\",\n                \"item_text\": \"RenameFiles\",\n                \"visible\": true,\n                \"help_text\": \"Change File Info\",\n                \"log_text\": \"REN\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"renamefiles\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"RN\",\n                \"item_text\": \"RemoveNotThere\",\n                \"visible\": true,\n                \"help_text\": \"Remove N/A Files From List\",\n                \"log_text\": \"RN\",\n                \"instance_message\": \"\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"removenotthere\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            },\n            {\n                \"item_key\": \"C\",\n                \"item_text\": \"RequestChat\",\n                \"visible\": true,\n                \"help_text\": \"Call SysOp to Chat\",\n                \"log_text\": \"C\",\n                \"instance_message\": \"Requesting Chat\",\n                \"acs\": \"\",\n                \"password\": \"\",\n                \"actions\": [\n                    {\n                        \"cmd\": \"requestchat\",\n                        \"data\": \"\",\n                        \"acs\": \"\"\n                    }\n                ]\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "install/menus/wwiv/xfer.msg",
    "content": "                         |#4 WWIV Transfer Menu |#0\n\n|#5 |#4 File Transfers |#5|#4 Miscellaneous |#5ķ|#0\n|#5  |#7D |#1> |#2Download a File                 |#5 |#7C |#1> |#2Chat with Sysop              |#5|#0\n|#5  |#7U |#1> |#2Upload a File                   |#5 |#7H |#1> |#2Hop to Another Directory     |#5|#0\n|#5  |#7Z |#1> |#2Upload a File to Sysop          |#5 |#7J |#1> |#2Join File Conference         |#5|#0\n|#5  |#7R |#1> |#2Remove a File You Uploaded      |#5 |#7K |#1> |#2Configure File List          |#5|#0\n|#5  |#7B |#1> |#2Batch Download Bi-Directional   |#5 |#7O |#1> |#2Log Off                      |#5|#0\n|#5 |#4 File Searches |#5ĺ |#7Q |#1> |#2Quit to Main Menu            |#5|#0\n|#5  |#7F |#1> |#2Search by File Description      |#5 |#7T |#1> |#2Set Transfer Options         |#5|#0\n|#5  |#7S |#1> |#2Search by File Name             |#5 |#7W |#1> |#2Menu of Slash Commands       |#5|#0\n|#5  |#7L |#1> |#2List Files - Current Directory  |#5 |#7X |#1> |#2Toggle Expert mode (menus)   |#5|#0\n|#5  |#7N |#1> |#2List all New Files              |#5 |#7Y |#1> |#2Your Transfer Stats          |#5|#0\n|#5  |#7P |#1> |#2Set New Search Date             |#5|#4 Archive Commands |#5Ķ|#0\n|#5  |#7* |#1> |#2List all Directories            |#5 |#7E |#1> |#2Extract files from Archive   |#5|#0\n|#5  |#7>|#1,|#7]|#1,|#7+ |#1> |#2Move Forward One Directory  |#5 |#7G |#1> |#2Access Archive Command Menu  |#5|#0\n|#5  |#7<|#1,|#7[|#1,|#7- |#1> |#2Move Backward One Directory |#5 |#7A|#1,|#7V |#1> |#2List files in Archive      |#5|#0\n|#5  |#7{ |#1> |#2Move Backward One Conference    |#5Ķ|#0\n|#5  |#7} |#1> |#2Move Forward One Conference     |#5 |#1Ctrl T - Time on Line            |#5|#0\n|#5 Ľ|#0\n"
  },
  {
    "path": "install/menus/wwiv/xfer.pro",
    "content": "|#7Time Left|#6: |#1|@% |#7minutes\n|#3Conference|#6: |#5|@j\n|#7[|#0|@;|#7] [|#1|@@|#7]|#6:|#0 .end.\n\n"
  },
  {
    "path": "install/nsis/wwiv.nsi",
    "content": "; Script generated with the Venis Install Wizard\n\n; Define your application name\n!define PRODUCT_NAME \"WWIV\"\n!define PRODUCT_BUILD \"49\"\n!define PRODUCT_VERSION \"Beta1\"\n!define PRODUCT_WEB_SITE \"http://www.wwiv.com\"\n!define PRODUCT_PUBLISHER \"WWIV Software Services\"\n!define PRODUCT_UNINST_KEY \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${PRODUCT_NAME}\"\n!define PRODUCT_UNINST_ROOT_KEY \"HKLM\"\n\n; Modern interface settings\n!include \"MUI.nsh\"\n\n!define MUI_ABORTWARNING\n!define MUI_FINISHPAGE_RUN \"$INSTDIR\\WWIVTelnetServer.exe\"\n!define MUI_FINISHPAGE_RUN_TEXT \"Start WWIV Telnet Server\"\n\n!insertmacro MUI_PAGE_WELCOME\n!insertmacro MUI_PAGE_LICENSE \"..\\admin\\LICENSE.AGR\"\n!insertmacro MUI_PAGE_DIRECTORY\n!insertmacro MUI_PAGE_COMPONENTS\n!insertmacro MUI_PAGE_INSTFILES\n!insertmacro MUI_PAGE_FINISH\n\n!insertmacro MUI_UNPAGE_CONFIRM\n!insertmacro MUI_UNPAGE_INSTFILES\n\n!insertmacro MUI_LANGUAGE \"English\"\n\n; Main Install settings\nName \"${PRODUCT_NAME}\"\nInstallDir \"C:\\WWIV\"\nOutFile \"WWIV50_beta1_${PRODUCT_BUILD}.exe\"\nInstallDirRegKey HKLM \"Software\\${APPNAME}\" \"\"\n\nSection \"-WWIV 430 Core\" Section1\n\t; Set Section properties\n\tSetOverwrite on\n\tSetOutPath \"$INSTDIR\\\"\n\tFile \"..\\admin\\unzip.exe\"\n\tFile \"..\\admin\\*.ini\"\n\tFile \"..\\admin\\*.txt\"\n\tFile \"..\\admin\\docs\\*.doc\"\n        File /oname=\"wwiv.ini\" \"..\\admin\\wwivini.500\"\n\tFile \"..\\admin\\readme.500\"\n\tFile \"..\\admin\\license.agr\"\n\tFile \"..\\admin\\regions.zip\"\n\tFile \"..\\admin\\zip-city.zip\"\n\tFile \"..\\admin\\wfc.dat\"\n\t\n        File /oname=\"wwiv50.exe\" \"..\\bin\\wwiv50.exe\"\n; This next line assumes that \"FIX.EXE\", \"wwivconfig.EXE\", \"STREDIT.EXE\" have been placed in the vin folder\n        File \"..\\bin\\*.exe\"\n\n\tSetOutPath \"$INSTDIR\\data\"\n\tFile \"..\\admin\\modems.500\"\n\tFile \"..\\admin\\menucmds.dat\"\t\n\tFile \"..\\admin\\regions.dat\"\t\n\n\tSetOutPath \"$INSTDIR\\gfiles\"\n\tFile \"..\\admin\\menus\\en\\*\"\n\t\n\tSetOutPath \"$INSTDIR\\gfiles\\menus\"\n\tFile \"..\\admin\\menus\\en\\menus\\*\"\n\t\n\tSetOutPath \"$INSTDIR\\gfiles\\menus\\wwiv\"\n\tFile \"..\\admin\\menus\\en\\menus\\wwiv\\*\"\n\n\tCreateDirectory \"$INSTDIR\\data\"\t\n\tExecWait \"$INSTDIR\\unzip -qq -o $INSTDIR\\regions.zip -d $INSTDIR\\data\"\n\tExecWait \"$INSTDIR\\unzip -qq -o $INSTDIR\\zip-city.zip -d $INSTDIR\\data\"\n\n\tDelete $INSTDIR\\regions.zip\n\tDelete $INSTDIR\\zip-city.zip\t\nSectionEnd\n\nSection \"WWIV Telnet Server\" Section2\n\t; Set Section properties\n\tSetOverwrite on\n\t; Set Section Files and Shortcuts\n\tSetOutPath \"$INSTDIR\\\"\n\tFile \"..\\bin\\WWIVTelnetServer.exe\"\n\tFile \"..\\telsrv\\WWIVTelnetServer.exe.manifest\"\n\tFile \"..\\telsrv\\WWIVTelnetServer.cnt\"\n\tFile \"..\\telsrv\\WWIVTelnetServer.HLP\"\n\tFile /oname=\"TelnetServer_README.TXT\" \"..\\telsrv\\README.TXT\"\t\n\tCreateShortCut \"$DESKTOP\\WWIV Telnet Server.lnk\" \"$INSTDIR\\WWIVTelnetServer.exe\"\n\tCreateDirectory \"$SMPROGRAMS\\WWIV\"\n\tCreateShortCut \"$SMPROGRAMS\\WWIV\\WWIV Telnet Server.lnk\" \"$INSTDIR\\WWIVTelnetServer.exe\"\n\tCreateShortCut \"$SMPROGRAMS\\WWIV\\WWIV Telnet Server Help.lnk\" \"$INSTDIR\\WWIVTELNETSERVER.HLP\"\nSectionEnd\n\nSection \"Synchronet Fossil\" Section3\n\t; Set Section properties\n\tSetOverwrite on\n\t; Set Section Files and Shortcuts\n\tSetOutPath \"$INSTDIR\\\"\t\n\tFile \"..\\bin\\sync\\*\"\nSectionEnd\n\nSection -FinishSection\n  WriteUninstaller \"$INSTDIR\\uninstall.exe\"\n  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} \"${PRODUCT_UNINST_KEY}\" \"DisplayName\" \"$(^Name)\"\n  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} \"${PRODUCT_UNINST_KEY}\" \"UninstallString\" \"$INSTDIR\\uninstall.exe\"\n  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} \"${PRODUCT_UNINST_KEY}\" \"DisplayVersion\" \"${PRODUCT_VERSION}\"\n  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} \"${PRODUCT_UNINST_KEY}\" \"URLInfoAbout\" \"${PRODUCT_WEB_SITE}\"\n  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} \"${PRODUCT_UNINST_KEY}\" \"Publisher\" \"${PRODUCT_PUBLISHER}\"\n  ExecWait \"$INSTDIR\\wwivconfig.exe ,1\"\n  CreateDirectory \"$SMPROGRAMS\\WWIV\"\n  CreateShortCut \"$SMPROGRAMS\\WWIV\\Uninstall.lnk\" \"$INSTDIR\\uninstall.exe\"\n  CreateShortCut \"$SMPROGRAMS\\WWIV\\Sysop Node.lnk\" \"$INSTDIR\\wwiv50.exe\" \"-m -u0\"\nSectionEnd\n\n; Modern install component descriptions\n!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN\n\t!insertmacro MUI_DESCRIPTION_TEXT ${Section1} \"\"\n\t!insertmacro MUI_DESCRIPTION_TEXT ${Section2} \"\"\n\t!insertmacro MUI_DESCRIPTION_TEXT ${Section3} \"\"\n!insertmacro MUI_FUNCTION_DESCRIPTION_END\n\n;Uninstall section\nSection Uninstall\n\t;Remove from registry...\n\tDeleteRegKey HKLM \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${PRODUCT_NAME}\"\n\tDeleteRegKey HKLM \"SOFTWARE\\${PRODUCT_NAME}\"\n\n\t; Delete self\n\tDelete \"$INSTDIR\\uninstall.exe\"\n\n\t; Delete Shortcuts\n\tDelete \"$DESKTOP\\WWIV Telnet Server.lnk\"\n\tDelete \"$SMPROGRAMS\\WWIV\\WWIV Telnet Server.lnk\"\n\tDelete \"$SMPROGRAMS\\WWIV\\Uninstall.lnk\"\n\n\t; Delete all installed files\n\tDelete \"$INSTDIR\\*\"\n\tDelete \"$INSTDIR\\data\\*\"\n\tDelete \"$INSTDIR\\data\\regions\\*\"\n\tDelete \"$INSTDIR\\data\\zip-city\\*\"\n\tDelete \"$INSTDIR\\gfiles\\menus\\wwiv\\*\"\n\tDelete \"$INSTDIR\\gfiles\\menus\\*\"\n\tDelete \"$INSTDIR\\gfiles\\*\"\n\tDelete \"$INSTDIR\\attach\\*\"\n\tDelete \"$INSTDIR\\msgs\\*\"\n\tDelete \"$INSTDIR\\temp1\\*\"\n\tDelete \"$INSTDIR\\temp2\\*\"\n\tDelete \"$INSTDIR\\dloads\\misc\\*\"\n\tDelete \"$INSTDIR\\dloads\\sysop\\*\"\n\tDelete \"$INSTDIR\\dloads\\*\"\n\t; Remove remaining directories\n\tRMDir \"$INSTDIR\\data\\zip-city\"\n\tRMDir \"$INSTDIR\\data\\regions\"\n\tRMDir \"$INSTDIR\\data\"\n\tRMDir \"$INSTDIR\\gfiles\\menus\\wwiv\"\n\tRMDir \"$INSTDIR\\gfiles\\menus\"\n\tRMDir \"$INSTDIR\\gfiles\"\n\tRMDir \"$INSTDIR\\attach\"\n\tRMDir \"$INSTDIR\\msgs\"\n\tRMDir \"$INSTDIR\\temp1\"\n\tRMDir \"$INSTDIR\\temp2\"\n\tRMDir \"$INSTDIR\\dloads\\misc\"\n\tRMDir \"$INSTDIR\\dloads\\sysop\"\n\tRMDir \"$INSTDIR\\dloads\"\n\tRMDir \"$INSTDIR\\\"\n\tRMDir \"$SMPROGRAMS\\WWIV\"\nSectionEnd\n\n; eof\n"
  },
  {
    "path": "install/platform/unix/install.bash",
    "content": "# install.sh helper library\n\ndeclare -r PURPLE='\\033[1;35m'\ndeclare -r NC='\\033[0m'\ndeclare -r GREEN='\\033[1;32m'\ndeclare -r YELLOW='\\033[1;33m'\ndeclare -r RED='\\033[1;31m'\ndeclare -r CYAN='\\033[0;36m'\ndeclare -r BLUE='\\033[1;34m'\n  \nsay() {\n  echo -e \"${BLUE}* ${CYAN}$1${NC}\"\n  echo `date \"+%Y-%m-%d_%H-%M-%S\"`: $1 >> ${LOGFILE}\n}\n\nconfirm () {\n\tif [[ -n \"${YES}\" ]]; then\n\t\treturn\n\tfi\n  read -r -p \"$1 [y/N]: \" response\n  case $response in\n    [yY]) \n        true\n        ;;\n    *)\n        false\n        ;;\n  esac\n}\n\nprintok() {\n  echo -e \"${GREEN}OK: $1${NC}\"\n  echo `date \"+%Y-%m-%d_%H-%M-%S\"`: OK: $1 >> ${LOGFILE}\n}\n\nprintwarn() {\n  echo -e \"${YELLOW}WARNING: $1${NC}\"\n  echo `date \"+%Y-%m-%d_%H-%M-%S\"`: WARNING: $1 >> ${LOGFILE}\n}\n\nprinterr() {\n  echo -e \"${RED}ERROR: $1${NC}\"\n  echo `date \"+%Y-%m-%d_%H-%M-%S\"`: ERROR: $1 >> ${LOGFILE}\n}\n\npausescr() {\n\tif [[ -z \"${YES}\" ]]; then\n\t  echo -e \"${PURPLE}[PAUSE]${NC}\"\n\t  read -n1 -s\n\tfi\n}\n\nfilearch() {\n  file -be elf $1 | awk -F, '{print $2}' | sed 's/[- _]//g'\n}\n\n# Checks if a binary exists in the path\n# Params: [binary]\ncheck_binary_exists() {\n\tlocal binary=\"$1\"\n\tcommand -v $1 >/dev/null 2>&1\n}\n\ncheckcrit() {\n  if ! check_binary_exists \"$1\"; then\n    printerr \"$1 is not installed\"\n    MISSING_CRIT=true\n  fi\n}\n\ncheckopt() {\n  if ! check_binary_exists $1; then\n    printwarn \"$1 is not installed\"\n    MISSING_OPT=true\n  fi\n}\n\n# Checks if the binary is likely the right architecture for\n# this system.  \n# Note: The binary must exist or it's a fatal error\n# Params: [full path to binary]\ncheck_binary_arch_type() {\n\tlocal binary=\"$1\"\n\tif [[ ! -f \"${binary}\" ]]; then\n\t\tprinterr \"FATAL: check_binary_arch_type: Did not find ${binary}\"\n\t\tsay \"${binary} is missing. Please verify your BBS tarball is complete\"\n\t\tsay \"and run install.sh again.\"\n\t\tsay \"\"\n\t\tsay \"If you are running on a system that requires compiling the binaries\"\n\t\tsay \"manually, please do so and copy them all into ${WWIV_DIR}\"\n\t\tsay \"and run install.sh again.\"\n\t\texit 2;\n\tfi\n\n\tdeclare -r SYSTYPE=$(uname -m|sed 's/[- _]//g')\n\tdeclare -r INIT_TYPE=$(filearch ${binary})\n\t[[ $SYSTYPE =~ $INIT_TYPE ]]\n}\n\ncheck_binary() {\n\tlocal binary=${WWIV_BIN_DIR}/$1\n\tif ! check_binary_arch_type \"${binary}\"; then\n\t\tprintwarn \"Found ${binary}, continuing.  But...\"\n\t\tsay \"Your system type does not match the filetype of ${binary}.\"\n\t\tsay \"System type is ${SYSTYPE} and file reports ${INIT_TYPE}.\"\n\t\tsay \"If things are too different, it might not work\"\n\t\tsay \"Please refer to the documentation about compiling yourself\"\n\t\tsay \"if things don't look right or ${binary} doesn't run.\"\n\t\techo\n\t\tif ! confirm \"Should we continue the install?\"; then\n\t\t\techo\n\t\t\tsay \"Aborting the install.  Please verify your binaries and re-run the installer.\"\n\t\t\texit 2\n\t  fi\n\tfi\n}\n\ncheck_binaries() {\n  while [[ -n $1 ]]; do\n  \techo \"Checking $1\"\n    check_binary $1\n    shift\n  done\n}\n\ncreate_directory() {\n  local dir=$1\n  MKDIR=\"${RUN} mkdir\"\n  # Validate WWIV directory\n  if [[ ! -d ${dir} ]]; then\n  \tsay \"The directory ${dir} doesn't exist; creating it.\"\n  \tif ! ${MKDIR} -p ${dir}  &>> ${LOGFILE}\n  \tthen\n\t    say \"FATAL: There was an error creating the directory\"\n\t    say \"Please check $LOGFILE for details.\"\n\t    exit 10\n  \tfi\n  fi\n}\n\n# Does a user exist. \n# Params: [username]\nwwiv_user_exists() {\n\tlocal user=\"$1\"\n\tid \"${WWIV_USER}\" > /dev/null 2>&1\n}\n\n# Creates a locked WWIV service user.\n# Params: [username] [group] [home]\ncreate_wwiv_user() {\n\tlocal wwiv_user=\"$1\"\n\tlocal wwiv_group=\"$2\"\n\tlocal wwiv_home=\"$3\"\n\t${RUN} useradd  -g ${wwiv_group} \\\n\t\t\t\t\t\t\t\t\t-c \"WWIV BBS Service Account\" \\\n\t\t\t\t\t\t\t\t\t-d ${wwiv_home} \\\n\t\t\t\t\t  \t\t\t-s /sbin/nologin \\\n\t\t\t\t\t  \t\t\t-m ${wwiv_user} &>> ${LOGFILE}\n}\n\n# Locks an existing WWIV service user.\n# Params: [username]\nlock_wwiv_user() {\n\tlocal wwiv_user=\"$1\"\n\t# Lock the wwiv user.\n\t${RUN} usermod -L ${wwiv_user} &>> ${LOGFILE}\n}\n\n# Does the WWIV group exist.\n# params: [groupname]\nwwiv_group_exists() {\n\tlocal wwiv_group=\"$1\"\n\tgrep -q \"^${WWIV_GROUP}:\" /etc/group\n}\n\n# Creates a group for the locked WWIV service user.\n# Params: [groupname]\ncreate_wwiv_group() {\n\tlocal wwiv_group=\"$1\"\n\t${RUN} groupadd \"${wwiv_group}\" &>> ${LOGFILE}\n}\n\n# Checks to see if an existing WWIV installation exists at dir.\n# Params: [dir]\ncheck_existing_wwiv_install() {\n\tlocal dir=\"$1\"\n\t[[ -e \"${dir}/config.dat\" ]]\n}\n\n# Process all template files with environment variable substitution\n# Globals needed; WWIV_USER, WWIV_DIR\n# Params: [globspec]\nprocess_templates() {\n\tlocal globspec=\"$1\"\n\t# Don't quote globspec or it will not expand\n  for i in ${globspec}\n  do \n    out=${i%%.template}\n    say \"Processing: $i > ${out}\"\n    ${RUN} sed -e \"s|\\${WWIV_DIR}|${WWIV_DIR}|g\" -e \"s|\\${WWIV_USER}|${WWIV_USER}|g\" $i > ${out}\n  done\n}\n\n# Creates /etc/wwiv and copies the processed template\n# files to it.\n# Params: [dir: Where the installer is run from]\ncreate_etc_wwiv() {\n\tlocal dir=\"$1\"\n  say \"Copying the wwiv config file to /etc/wwiv\"\n  if [[ ! -d /etc/wwiv ]]; then\n    ${RUN} mkdir -p /etc/wwiv  &>> ${LOGFILE}\n  elif [[ -e /etc/wwiv/config ]]; then\n    say \"/etc/wwiv/config already exists, saving as /etc/wwiv/config.new\"\n    ${RUN} cp ${dir}/systemd/config /etc/wwiv/config.new  &>> ${LOGFILE}\n  fi\n  ${RUN} cp ${dir}/systemd/config /etc/wwiv/config  &>> ${LOGFILE}\n  say \"Installed: /etc/wwiv/config\"\n}\n\n# Configures systemd by copying the templated install\n# files to it.\n# Params: [dir: Where the installer is run from]\nconfigure_systemd() {\n\tlocal dir=\"$1\"\n\tif [[ ! -d /etc/systemd ]]; then\n\t  say \"You don't appear to be using systemd. You may need some more customization\"\n\t  say \"to run the wwivd service on a non-systemd setup.  Please check the docs\"\n\t  say \"or the IRC channel for additional help.\"\n\t  return 255;\n\tfi\n\n\tif [[ -e /etc/systemd/system/wwivd.service ]]; then\n    say \"/etc/systemd/system/wwivd.service already exists\"\n    say \"Installed /etc/systemd/system/wwivd.service.new\"\n    ${RUN} cp ${dir}/systemd/wwivd.service /etc/systemd/system/wwivd.service.new  &>> ${LOGFILE}\n  else\n    ${RUN} cp ${dir}/systemd/wwivd.service /etc/systemd/system/wwivd.service &>> ${LOGFILE}\n    say \"Installed: /etc/systemd/system/wwivd.service\"\n\t  ${RUN} systemctl daemon-reload &>> ${LOGFILE}\n  fi\n  ${RUN} systemctl enable wwivd.service &>> ${LOGFILE}\n  say \"systemd wwivd service enabled\"\n}\n\n# Configures Solaris svcadm by copying the templated install\n# files to it.\n# Params: [RUNDIR: Where the installer is run from]\nconfigure_svcadm() {\n\tlocal RUNDIR=\"$1\"\n  if [[ -e /var/svc/manifest/application/wwivd.xml ]]; then\n  \tsay \"/var/svc/manifest/application/wwivd.xml already exists, aborting svcadm install\"\n  \treturn 255\n\tfi\n  if [[ ! -e ${WWIV_DIR}/start_wwiv.sh ]]; then\n    say \"Installing ${RUNDIR}/svcadm/start_wwiv.sh\"\n    ${RUN} cp ${RUNDIR}/svcadm/start_wwiv.sh ${WWIV_DIR} &>> ${LOGFILE}\n    ${RUN} chmod +x ${WWIV_DIR}/start_wwiv.sh &>> ${LOGFILE}\n  fi\n  say \"Installing service manifest.\"\n  ${RUN} cp ${RUNDIR}/svcadm/wwivd.xml /var/svc/manifest/application/wwivd.xml &>> ${LOGFILE}\n  ${RUN} svcadm restart svc:/system/manifest-import &>> ${LOGFILE}\n  say \"service manifest installed, to enable run : \\\"svcadm enable wwivd\\\"\"\n}\n\n\ndisplay_banner() {\n\techo -e \"${BLUE}\"\n\t### Install header ###\n\tcat <<HEADER\n\n\n _       ___       __ __ _    __   ______\n| |     / / |     / /  _/ |  / /  / ____/\n| | /| / /| | /| / // / | | / /  /___ \\\\\n| |/ |/ / | |/ |/ // /  | |/ /  ____/ /\n|__/|__/  |__/|__/___/  |___/  /_____/\n\n    ____           __        ____      __  _           \n   /  _/___  _____/ /_____ _/ / /___ _/ /_(_)___  ____ \n   / // __ \\/ ___/ __/ __  / / / __  / __/ / __ \\/ __ \\\\\n _/ // / / (__  ) /_/ /_/ / / / /_/ / /_/ / /_/ / / / / \n/___/_/ /_/____/\\__/\\__,_/_/_/\\__,_/\\__/_/\\____/_/ /_/  \n \n\n\nHEADER\n\techo -e \"${NC}\"\n}\n\n"
  },
  {
    "path": "install/platform/unix/install.sh",
    "content": "#!/bin/bash\n#\n# install.sh\n#\n# Runs through the basic steps to install.  We do make certain assumptions\n# in order to facilitate the setup.  In particular, we assume we are running\n# from the install wwivbase location and we also assume we are running as \n# the root user.\n\nRUN=\"\"\ndeclare -r RUNDIR=$(pwd)\nwwiv_dir=\"${RUNDIR}\"\nwwiv_user=\"wwiv\"\nwwiv_group=\"wwiv\"\nFORCE=\"false\"\nYES=\"\"\n\nshow_help() {\n  \n  printf \"$0 - WWIV Bulletin Board System Installation Script.\\r\\n\\n\"\n\n  printf \"Usage:\\r\\n\\n\"\n  echo \"-d | --directory [directory]  : Directory to install WWIV \"\n  echo \"                                (default ${RUNDIR})\"\n  echo \"-g | --group [group]          : WWIV User's Group (default ${wwiv_group})\"\n  echo \"-f | --force                  : Force - ignore warnings on existing users,\"\n  echo \"                                groups, or software requirements\"\n  echo \"-n | --dry_run                : Dry run mode, do not execute commands\"\n  echo \"-u | --user [username]        : WWIV User (default ${wwiv_user})\"\n  echo \"-y | --yes                    : Don't prompt for confirmation or pause\"\n  printf \"\\r\\n\\n\"\n}\n\nwhile :; do\n  # echo \"param: $1\"\n  case $1 in\n      -h|-\\?|--help)\n        show_help    # Display a usage synopsis.\n        exit\n        ;;\n      -d|--dir)     # Set wwiv-user\n        if [ \"$2\" ]; then\n          wwiv_dir=\"$2\"\n          shift\n        fi\n        ;;\n      -f|--force)  # Force\n        FORCE=\"true\"\n        echo \"** FORCE\"\n        ;;\n      -g|--group)     # Set wwiv-user\n        if [ \"$2\" ]; then\n          wwiv_group=\"$2\"\n          shift\n        fi\n        ;;\n      -n|--dry_run)  # Set dry-run mode\n        RUN=\"echo DRY-RUN: \"\n        echo \"** Dry Run Mode\"\n        ;;\n      -u|--user)     # Set wwiv-user\n        if [ \"$2\" ]; then\n          wwiv_user=\"$2\"\n          shift\n        fi\n        ;;\n      -y|--yes)  # Force\n        YES=\"true\"\n        echo \"** YES\"\n        ;;\n      --) # Done\n        shift\n        break\n        ;;\n      -?*)\n        echo \"WARN: Unknown option (ignored): $1\"\n        ;;\n      *)\n        break;\n  esac\n  shift\ndone\n\n# Ensure we're root.\nID=$(id -u)\nif [[ $ID -ne 0 ]]; then\n  echo \"Looks like you are not root.  Please re-run as root.\"\n  echo \"${RED}There are tasks that require root to complete.\"\n  exit 20\nfi\n\ndeclare -r WWIV_DIR=${wwiv_dir:-\"${RUNDIR}\"}\ndeclare -r WWIV_BIN_DIR=${WWIV_BIN_DIR:-\"${WWIV_DIR}\"}\ndeclare -r WWIV_LOG_DIR=${WWIV_LOG_DIR:-\"${WWIV_DIR}/log\"}\ndeclare -r WWIV_OS=$(uname -s)\ndeclare -r DATE=`date \"+%Y-%m-%d_%H-%M-%S\"`\ndeclare -r LOGFILE=${RUNDIR}/install.${DATE}.log\ndeclare -r WWIV_USER=${wwiv_user:-\"wwiv\"}\ndeclare -r WWIV_GROUP=${wwiv_group:-\"wwiv\"}\n\n# now that variables are defined, these functions can be used.\nsource \"$(dirname $(realpath $0))/install.bash\"\n\n# setting path so running with sudo works\nexport PATH=/sbin:/usr/sbin:/usr/local/sbin:$PATH\n\ndisplay_banner\n\nif ! confirm \"Welcome to the WWIV installer. Continue?\"\nthen\n  say \"Sorry you don't want to continue.  Hope you come back soon.\"\n  exit 3\nfi\n\n# Show menu.\n\necho\nsay \"Starting the install process.\"\nsay \"\"\nsay \"The install details will be captured in: ${LOGFILE}\"\n\n\n### parse our CLI options ###\n# Future getopts for setting values will go here.\n# For right now, we just edit the variables at the top of the \n# script for our expected WWIV user, etc.\n\n\n### check for pre-reqs ###\nsay \"Checking for needed OS tools\"\n\n# Critical\nMISSING_CRIT=false\ncheckcrit sudo\ncheckcrit zip\ncheckcrit unzip\ncheckcrit awk\n\nif [[ ${MISSING_CRIT} == \"true\" ]]; then\n  say \"You are missing critical tools (listed as ERROR above)\"\n  if [[ ${FORCE} == \"false\" ]]; then\n    say \"Please install the missing tools and start the install again\"\n    exit 5\n  fi\nelse\n  echo\n  say \"All critical checks passed, continuing with the install.\"\nfi\n\n# Optional\nMISSING_OPT=false\ncheckopt dos2unix\ncheckopt unix2dos\ncheckopt dosemu\ncheckopt screen\n\nif [[ ${MISSING_OPT} == \"true\" ]]; then\n  echo\n  say \"You are missing some optional tools (listed as WARNING above)\"\n  say \"These are not necessary for a basic system, but you may want\"\n  say \"to install the missing tools later; continuing.\"\n  echo\nelse\n  echo\n  say \"All optional tools checks passed, continuing with the install.\"\n  echo\nfi\npausescr\n\n# ncurses\n\n\necho\nsay \"Doing some basic sanity checks\"\necho\n\nif [[ -e \"${WWIV_DIR}/config.dat\" ]]; then\n  printerr \"Looks like there's already a WWIV install in ${WWIV_DIR}.\"\n  say \"If you really meant to install, please check the target directory\"\n  say \"before trying again.  Aborting the install.\"\n  say \"\"\n  exit 2\nfi\n\nsay \"Checking if wwiv group (${WWIV_GROUP}) exists\"\nwwiv_group_exists \"${WWIV_GROUP}\"\ngroup_exist=$?\nif [[ \"${group_exist}\" -eq 0 && \"${FORCE}\" == \"false\" ]]; then\n  say \"User (${WWIV_GROUP}) already exists, too.  Please verify your user\"\n  say \"name choice and re-run the installer or add --force to the commandline.\"\n  exit 3\nfi\nsay \"Checking if wwiv user (${WWIV_USER}) exists\"\nwwiv_user_exists \"${WWIV_USER}\"\nuser_exist=$?\nif [[ ${user_exist} -eq 0 && \"${FORCE}\" == \"false\" ]]; then\n  say \"User (${WWIV_USER}) already exists, too.  Please verify your user\"\n  say \"name choice and re-run the installer or add --force to the commandline.\"\n  exit 3\nfi\n\ncheck_binaries bbs wwivconfig wwivd wwivutil\nsay \"\"\nsay \"Basic Checks completed\"\n\n# Making sure the values are what we want\nsay \"Creating the WWIV user, group and directory with the following values:\"\nsay \"\"\nsay \"WWIV_DIR:     ${YELLOW}${WWIV_DIR}\"\nsay \"WWIV_BIN_DIR: ${YELLOW}${WWIV_BIN_DIR}\"\nsay \"WWIV_LOG_DIR: ${YELLOW}${WWIV_LOG_DIR}\"\nsay \"WWIV_USER:    ${YELLOW}${WWIV_USER}\"\nsay \"WWIV_GROUP:   ${YELLOW}${WWIV_GROUP}\"\nsay \"\"\n\nif ! confirm \"Are these correct?\"\nthen\n  say \"\"\n  say \"Please set the values to what you want in the top of install.sh\"\n  say \"and re-run the script. Exiting.\"\n  exit 1\nfi\n\nif ! wwiv_group_exists \"${WWIV_USER}\"; then\n  create_wwiv_group \"${WWIV_GROUP}\"\nfi\n\nif ! wwiv_user_exists \"${WWIV_USER}\"; then\n  say \"Creating locked WWIV user account: ${WWIV_USER}\"\n  create_wwiv_user \"${WWIV_USER}\" \"${WWIV_GROUP}\" \"${WWIV_DIR}\"\n  lock_wwiv_user \"${WWIV_USER}\"\nfi\n\ncreate_directory ${WWIV_DIR}\n\n### configure scripts and helper binaries. ###\nsay \"\"\nsay \"Configuring scripts to use the following settings:\"\n\nsay \"WWIV_DIR:  ${WWIV_DIR}\"\nsay \"WWIV_USER: ${WWIV_USER}\"\nsay \"WWIV_GROUP: ${WWIV_GROUP}\"\nsay \"\"\n\n# Unzip the unix archive.\nunzip -n -q unix.zip\n\nWWIV_TEMPLATE_PATH=\"systemd/*.template\"\nif [[ ${WWIV_OS} == \"SunOS\" ]]; then\n  WWIV_TEMPLATE_PATH=\"svcadm/*.template\"\nfi\nprocess_templates \"${WWIV_TEMPLATE_PATH}\"\n\nif [[ ${WWIV_OS} == \"Linux\" ]]; then\n  create_etc_wwiv \"${RUNDIR}\"\n  configure_systemd \"${RUNDIR}\"\nelif [[ ${WWIV_OS} == \"SunOS\" ]]; then\n  configure_svcadm \"${RUNDIR}\"\nfi\n\n\n#Final permissions setting of the WWIV directory files before running wwivconfig\nsay \"Making sure ${WWIV_USER} owns all the files\"\n${RUN} chown -R ${WWIV_USER}:${WWIV_GROUP} ${WWIV_DIR} &>> ${LOGFILE}\nsay \"\"\nsay \"Your BBS basic systemd service configuration \"\nsay \"and helper scripts are complete.\"\n\n### Final wwivconfig steps ###\nsay \"About to initialize the WWIV BBS data files\"\npausescr\n\nsay \"Initializing data files\"\n${RUN} sudo -u${WWIV_USER} \"${WWIV_DIR}/wwivconfig\" --initialize\nsay \"Installation complete\"\n\necho\nsay \"Please log in as your new WWIV user (eg, sudo -u ${WWIV_USER} -s)\"\nsay \"and run the ./wwivconfig command to create the SysOp account and\"\nsay \"customize the BBS information.\"\nsay \"\"\nsay \"If you need any assistance, check out the docs or find us on IRC.\"\n"
  },
  {
    "path": "install/platform/unix/lib/door-lib-v0.sh",
    "content": "#!/bin/bash\n############################################\n# UNIX Door Shell Script Library\n# - A collection of helpers using DOSEMU\n#\n# Example Door Script:\n#\n#   !/bin/bash\n#   source /bbs/doors/door-lib-v0.sh\n#\n#   Expected usage is gw.sh %C %H\n#\n#   dd_set_door_dir /bbs/doors/gw\n#   dd_set_dropfile $1\n#   dd_set_sockethandle $2\n#   # Note that it's gw.bat and not GW.BAT, it also\n#   # doesn't include a drive letter nor path. This needs\n#   # to match the UNIX name, dosemu will find it and\n#   # execute it.\n#dd_dosemu gw.bat\n\n\n\necho \"Starting door...\"\n\nDROPFILE_PATH=\"\"\nDROPFILE_NAME=\"\"\nBBS_TEMPDIR=\"\"\nDOOR_DIR=\"\"\nSOCKET_HANDLE=-1\n\nif [[ -z \"${DOSEMU_RC}\" ]]; then\n    echo \"Setting DOSEMU_RC\"\n    DOSEMU_RC=${HOME}/.dosemurc\nfi\n\n##############################################\n#\n# die with message.\n#\ndie() { echo \"$*\" 1>&2 ; exit 1; }\n\n\n##############################################\n#\n# Test pre-requisites\n#\n\nfunction check_in_path() {\n    if ! [[ -x \"$(command -v $1)\" ]]; then\n\tdie \"$1 must be installed\"\n    fi\n}\n\ncheck_in_path dos2unix\ncheck_in_path dosemu\n\n##############################################\n#\n# Sets the full path to the dropfile.\n#\n# $1 is the full path to the dropdile\nfunction dd_set_dropfile() {\n    DROPFILE_PATH=$1\n    DROPFILE_NAME=$(basename ${DROPFILE_PATH})\n    if [[ -z \"${BBS_TEMPDIR}\" ]]; then\n\t# Set the BBS_TEMPDIR to the directory for the dropfile\n\t# If we haven't already set it.\n\tBBS_TEMPDIR=$(dirname ${DROPFILE_PATH})\n    fi\n}\n\n##############################################\n#\n# Sets the full path to the temp/node\n# directory\n#\n# $1 = tempdir\nfunction dd_set_temp_dir() {\n    BBS_TEMPDIR=$1\n}\n\n\nis_num() { [[ ${1} =~ ^[0-9]+$ ]]; }\n\n##############################################\n#\n# Set the socket handle.\n#\n# $1 = socket handle\n#\nfunction dd_set_sockethandle() {\n    if ! [[ ${1} =~ ^[0-9]+$ ]]; then\n\tdie \"dd_set_sockethandle expects a number, got $1\"\n    fi\n    SOCKET_HANDLE=$1\n}\n\n# $1 is door dir\nfunction dd_set_door_dir() {\n    DOOR_DIR=$1\n}\n\n##############################################\n#\n# Sets the environment variables needed for\n# the DOS directories baeds on the door_dir\n# and temp_dir set (either directly or as the\n# directory for the dropfile.\n#\nfunction dosemu_paths() {\n    # D: is door path\n    # T: is TEMP path\n    export DOSDRIVE_D=${DOOR_DIR}\n    export DOSDRIVE_T=${BBS_TEMPDIR}\n}\n\n##############################################\n#\n# Executes DOSEMU on command passed as $1\n# $1 is the name of the command to execute.\n#\n# Note that it's gw.bat and not GW.BAT, it also\n# doesn't include a drive letter nor path. This needs\n# to match the UNIX name, dosemu will find it and\n# execute it.\n#\nfunction dd_dosemu() {\n    if [[ -z \"$1\" ]]; then\n\tdie \"execute_dosemu needs the command specified as a param\"\n    fi\n\n    if [[ -z \"${DROPFILE_PATH}\" ]]; then\n\tdie \"The path to the drop file must be specified to dd_set_dropfile\"\n    fi\n\n    # Ensure that the dropfile is in DOS format.\n    unix2dos ${DROPFILE_PATH}\n    \n    if [[ -z \"${DOSDRIVE_D}\" || -z \"${DOSDRIVE_T}\" ]]; then\n\tdosemu_paths D T\n    fi\n    local bat=$1\n    cd ${DOOR_DIR}\n    socat -d -d \\\n\t  FD:${SOCKET_HANDLE} \\\n\t  EXEC:\"dosemu -f ${DOSEMU_RC} ${bat}\",pty\n}\n\n"
  },
  {
    "path": "install/platform/unix/lib/door.sh",
    "content": "#!/bin/bash\n# Expected usage is door.sh %C %H\n# Or some other drop file for %C\nset -x\nsource /etc/wwiv/config\nsource ${WWIV_DIR}/lib/door-lib-v0.sh\n\ndeclare -r DIR=$(dirname $(readlink -f $0))\n\ndd_set_door_dir ${DIR}\ndd_set_dropfile $1\ndd_set_sockethandle $2\n\necho \"Door DIR:       ${DOOR_DIR}\"\necho \"Dropfile Path:  ${DROPFILE_PATH}\"\necho \"Temporary Path: ${BBS_TEMPDIR}\"\n\n# Note that it's gw.bat and not GW.BAT, it also\n# doesn't include a drive letter nor path. This needs\n# to match the UNIX name, dosemu will find it and\n# execute it.\ndd_dosemu gw.bat\n"
  },
  {
    "path": "install/platform/unix/svcadm/start_wwiv.sh.template",
    "content": "#!/bin/sh\n\ncd ${WWIV_DIR}\n./wwivd --wwiv_user=${WWIV_USER} --bbsdir=${WWIV_DIR}\n"
  },
  {
    "path": "install/platform/unix/svcadm/wwivd.xml.template",
    "content": "<?xml version='1.0'?>\n\n<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>\n\n<service_bundle type=\"manifest\" name=\"wwivd\">\n    <service name=\"application/wwivd\" type=\"service\" version=\"1\">\n       <create_default_instance enabled=\"false\"/>\n       <single_instance/>\n\n       <method_context>\n           <method_credential user='${WWIV_USER}' group='${WWIV_GROUP}'/>\n\n           <method_environment>\n               <envvar name='PATH' value='/usr/bin:/usr/local/bin:${WWIV_DIR}'/>\n           </method_environment>\n       </method_context>\n\n       <exec_method type=\"method\" name=\"start\" exec=\"${WWIV_DIR}/start_wwiv.sh\" timeout_seconds=\"0\"/>\n\n       <exec_method type=\"method\" name=\"stop\" exec=\":kill -TERM\" timeout_seconds=\"30\"/>\n\n       <property_group name='startd' type='framework'>\n           <propval name='duration' type='astring' value='child'/>\n       </property_group>\n\n       <stability value=\"Evolving\"/>\n\n       <template>\n           <common_name>\n               <loctext xml:lang='C'>WWIV Bulletin Board System</loctext>\n           </common_name>\n\n           <documentation>\n               <doc_link name='www.wwivbbs.org' uri='http://www.wwivbbs.org/'/>\n           </documentation>\n       </template>\n    </service>\n</service_bundle>\n"
  },
  {
    "path": "install/platform/unix/systemd/config.template",
    "content": "#\n# WWIV Environment Settings\n#\n\nWWIV_DIR=${WWIV_DIR}\nWWIV_USER=${WWIV_USER}\n\n"
  },
  {
    "path": "install/platform/unix/systemd/wwivd.service.template",
    "content": "[Unit]\nDescription=wwivd: WWIV UNIX Daemon\n[Service]\nWorkingDirectory=${WWIV_DIR}\nExecStart=${WWIV_DIR}/wwivd\nEnvironmentFile=/etc/wwiv/config\n[Install]\nWantedBy=multi-user.target\n\n"
  },
  {
    "path": "install/platform/win32/install.ps1",
    "content": "cls\nWrite-Output \"\"\nWrite-Host  WWIV Installer -ForegroundColor Yellow\nWrite-Host  ****************************************************** -ForegroundColor Blue\nWrite-Output \"\"\nWrite-Host  IT IS HIGHLY RECOMMENDED THAT YOU MAKE A COMPLETE BACKUP OF YOUR -ForegroundColor Red\nWrite-Host  DATA PRIOR TO INSTALLING AND RUNNNING THIS SOFTWARE. -ForegroundColor Red\nWrite-Output \"\"\nWrite-Host  WWIV SOFTWARE SERVICES DISCLAIMS ANY AND ALL RESPONSIBILITY AND -ForegroundColor Red\nWrite-Host  LIABILITY FOR ANY HARDWARE OR SOFTWARE DAMAGE, CORRUPTION OR LOSS OF -ForegroundColor Re\nWrite-Host  DATA AS A RESULT OF YOUR USE OF THIS SOFTWARE. -ForegroundColor Red\nWrite-Output \"\"\nWrite-Host         ****************************************************** -ForegroundColor Blue\nWrite-Output \"\"\nWrite-Output \"\"\n\nif (Test-Path config.dat) {\n  Write-Host \"Looks like there's already a WWIV install.\"  -ForegroundColor Red\n  Write-Host \"If you really meant to install, please check the target directory\"  -ForegroundColor Red\n  Write-Host \"before trying again.  Aborting the install.\"  -ForegroundColor Red\n  Exit\n}\n\nfunction Say {\n  Write-host $args -ForegroundColor DarkCyan\n}\n\nfunction WWIV-Unzip {\n  Param($ZipFile, $Dir)\n  Say .\\unzip.exe -qq -o $ZipFile -d $Dir\n}\n\nfunction YesNo {\n  Param ($Prompt)\n    while(\"y\",\"n\" -notcontains $answer)\n    {\n\t    $answer = Read-Host $Prompt \"(y/n)\"\n    }  \n    return ($Answer -eq 'y')\n}\n\nfunction UnzipFiles {\n    WWIV-Unzip -ZipFile inifiles.zip -Dir .\n    WWIV-Unzip -ZipFile gfiles.zip -Dir gfiles\n    WWIV-Unzip -ZipFile scripts.zip -Dir scripts\n    WWIV-Unzip -ZipFile data.zip -Dir data\n    WWIV-Unzip -ZipFile regions.zip -Dir data\n    WWIV-Unzip -ZipFile zip-city.zip -Dir data\n}\n\n# ******************************* run INIT to convert data files to\n# ******************************* v5.00 format\nif (!(YesNo -Prompt \"Do you want to install WWIV 5?\")) {\n    Say \"That's ok, Thanks anyway\"\n    Exit\n}\n\nUnzipFiles\nSay wwivconfig.exe\n\nWrite-Host \"Installation Complete\" -ForegroundColor Green\nWrite-Host \"If you need any assistance, check out the docs or find us on IRC.\" -ForegroundColor DarkCyan\n\n"
  },
  {
    "path": "install/platform/win32/sbbsexec.ini",
    "content": "; exec/sbbsexec.ini\n; $Id: sbbsexec.ini,v 1.4 2006/06/20 21:56:21 rswindell Exp $\n\n; This file reflects the default operating parameters of the\n; Synchronet Windows NT Virtual Device Driver (sbbsexec.dll)\n; used for FOSSIL and UART (COM port) virtualization for DOS programs\n; (e.g. door games) on Windows NT-based operating systems (WinNT/2K/XP/etc.)\n\n; A copy of this file in the current working directory (e.g. xtrn/somedoor)\n; when a DOS program is executed, will *over-ride* these settings.\n\n; Additionally, if a section matching the program's name\n; (e.g. [DSZ] when executing DSZ.EXE) is found, any values in that section\n; will over-ride any global values and [UART.<program name>] (e.g. [UART.DSZ])\n; will over-ride any global UART virtualization values (see [UART] section\n; below for details).\n\n; Specify the Logging Level (e.g. \"error\", \"warning\", ..., \"info\", \"debug\"):\n; Log output goes to the Windows debug output (e.g. use DebugView or any\n; other Windows debug viewer to view log messages).\nLogLevel=warning\n; Over-ride the above log level (set to \"debug\" temporarily?)\nDebug=false\n; Allow program to disconnect the socket (i.e. hangup the user?)\nCanDisconnect=true\n\n; Interval of time-slice yield, in milliseconds (fractions supported):\n; Lower numbers result in *more* frequent yields, reducing CPU utilization\n; and possibly reducing performance/responsiveness while higher numbers\n; can result in fewer yeilds, increasing CPU utilization (possibly taxing\n; the system) and increasing performance/responsiveness.\n; This number may need to be \"tuned\" on a per-program/system basis.\n; Set to '0' to disable yielding.\nYieldInterval=1.0\n\n; Example of custom YieldInterval setting for DSZ and GSZ:\n[dsz|gsz]\nYieldInterval=3\n\n; The following section pertains to UART (COM port) virtualization only:\n[UART]\n; Set to false to disable UART virtualization:\nVirtualize=true\n; The DOS COM port number to be emulated/virtualized (default: \"COM1\"):\nComPort=1\n; The following values are optional, used for specifying the specific\n; hardware interrupt request line (IRQ) and I/O base address of the UART\n; to be emulated/virtualized:\n; Note: these values will *over-ride* the hardware attributes associated\n; with the \"ComPort\" value above.\n; IRQ=4\n; Address=0x3f8\n"
  },
  {
    "path": "install/platform/win32/upgrade.bat",
    "content": "@ECHO OFF\nREM  Commandline must include the MAIN BBS destination directory for the\nREM  upgrade with *NO* trailing slash i.e. C:\\WWIV\n\nCLS\nECHO.\nECHO.\nECHO                      WWIV v5.00 Upgrade Batch\nECHO.\n\nif %1a == a goto HELP\n\nECHO    IT IS HIGHLY RECOMMENDED THAT YOU MAKE A COMPLETE BACKUP OF YOUR\nECHO          DATA PRIOR TO INSTALLING AND RUNNNING THIS SOFTWARE.\nECHO.\nECHO  WWIV SOFTWARE SERVICES DISCLAIMS ANY AND ALL RESPONSIBILITY AND\nECHO  LIABILITY FOR ANY HARDWARE OR SOFTWARE DAMAGE, CORRUPTION OR LOSS OF\nECHO             DATA AS A RESULT OF YOUR USE OF THIS SOFTWARE.\nECHO.\nECHO.\nECHO Press Control-C to Cancel\npause\n\nrem ******************************* display license agreement\ncls\ntype license.agr | more\nECHO.\nECHO.\nECHO.\nrem ******************************* run wwivconfig to convert data files to\nrem ******************************* v5.00 format\nECHO Press Control-C to Cancel\npause\n\nCLS\nECHO.\nECHO.\nECHO                      WWIV v5.00 Upgrade Batch\nECHO.\nECHO  If your system does not use a standard WWIV directory tree, you\nECHO  must edit this file prior to upgrading to account for directories\nECHO  or files that are in non-standard locations.\nECHO.\nECHO  You must manually merge the changes from WWIVINI.500 with your\nECHO  WWIV.INI file.  Settings in your current file that are not in the\nECHO  new file should be removed.  They will be ignored in any case, but\nECHO  will increase read times if not removed.\nECHO.\nECHO                  ***WARNING***WARNING***WARNING***\nECHO.\nECHO  Running the BBS prior to running wwivconfig to convert the data files\nECHO  will corrupt the files making it impossible to convert them.  Make\nECHO  sure you have a current backup!  If you included a trailing\nECHO  backslash on your install directory, this upgrade will fail!!\nECHO.\nECHO Upgrade to WWIV v5.00 now?\nECHO.\nECHO Press Control-C to Cancel\npause\n\n:UPGRADE\nECHO Upgrading to WWIV v5.00...  Please wait....\nECHO.\nECHO.\nREM ******************************* Change the attributes if set\nECHO Changing file attributes if set...\nattrib -r %1\\wwivconfig.exe\nattrib -r %1\\bbs.exe\nattrib -r %1\\fix.exe\nattrib -r %1\\return.exe\n\nREM ******************************* copy EXE's\nECHO Copying EXE's...\ncopy wwivconfig.exe %1\ncopy bbs.exe %1\nattrib +r %1\\bbs.exe\ncopy fix.exe %1\ncopy return.exe %1\ncopy stredit.exe %1\n\nREM ******************************* copy STR files\nECHO Copying String files...\ncopy english.str %1\\gfiles\\bbs.str\ncopy sysoplog.str %1\\gfiles\\sysoplog.str\ncopy chat.str %1\\gfiles\\chat.str\ncopy ini.str %1\\gfiles\\ini.str\ncopy yes.str %1\\gfiles\\yes.str\ncopy no.str %1\\gfiles\\no.str\n\nREM ******************************* copy INI's and text files\nECHO Copying INI, data, and text files...\ncopy chat.ini %1\ncopy wwivini.500 %1\ncopy bbsads.txt %1\ncopy revision.txt %1\ncopy readme.500 %1\ncopy menu.doc %1\ncopy *.sam %1\ncopy modems.500 %1\\DATA\ncopy regions.dat %1\\DATA\ncopy wfc.dat %1\\DATA\n\nREM ******************************* unzip menus regions and zip code files\nECHO Decompressing archives. Please wait....\nif %TZ%a == a goto DOTZ\nunzip -qq -o en-menus.zip -d%1\\gfiles\nunzip -qq -o regions.zip -d%1\\data\nunzip -qq -o zip-city.zip -d%1\\data\ngoto TZEND\n:DOTZ\nSET TZ=EST5EDT\nunzip -qq -o en-menus.zip -d%1\\gfiles\nunzip -qq -o regions.zip -d%1\\data\nunzip -qq -o zip-city.zip -d%1\\data\nSET TZ=\n:TZEND\n\nREM ******************************* run wwivconfig to convert data files to\nREM ******************************* v5.00 format\nCLS\ncd %1\ntype license.agr | more\nECHO.\nECHO.\nECHO You must now run wwivconfig to convert your data files to v5.00 format.\nECHO.\nECHO.\nECHO.\nECHO Run wwivconfig ,1 now?\nECHO Press Control-C to Cancel\npause\ncd %1\nwwivconfig ,1\ngoto CLOSE\n\nREM Display Help\n:HELP\nECHO.\nECHO.\nECHO Commandline must include destination directory!\nECHO.\nECHO DO NOT include a trailing backslash!\nECHO.\nECHO.\nECHO  i.e.  UPGRADE.BAT C:\\WWIV\ngoto END\n\nREM Exit Batch file\n:CLOSE\nCLS\nECHO.\nECHO.\nECHO                      WWIV v5.00 Upgrade Batch\nECHO.\nECHO If wwivconfig.EXE faile to run, you will need to run it manually to complete\nECHO the upgrade process.  Be forewarened that if wwivconfig.EXE is not run once\nECHO prior to running the BBS, your data files will be permanently\nECHO corrupted.  It would be wise to run wwivconfig.EXE again now just to be\nECHO sure.\nECHO.\nECHO You will then need to manually merge WWIVINI.500 with your current\nECHO WWIV.INI file.  This is also imperative as some new settings must be\nECHO included for v5.00 to run.  Be sure to read the comments thoroughly.\nECHO They should be more than sufficient to get you up and running for the\nECHO first time.  Consult the documentation for advanced settings.\nECHO.\nECHO The new file, MODEMS.500, has been copied to your DATA directory.\nECHO If your current modem setup is working, you should continue to use it.\nECHO There are some new definitions in this file that are specialized for\nECHO telnet use with COM/IP or NetModem32.\nECHO.\n\n:END\nECHO.\n"
  },
  {
    "path": "install/regions/README.NOW",
    "content": "\n                                                                       2/21/94\n\nJust wanted to include this little file and thank a few people who helped me\nout with this ENORMOUS undertaking...  It's taken me so many months now that I\nprobably forgot a lot of people, but you know who you are!\n\nSandman, #1 @8135 - who continues to help find gaps and holes and plug them\n                    by contacting people whose boards come up as unknown\n\nBerryg, #1 @      - who provided the AT&T information, cryptic as it\n                    was, for this project.  Berryg also wrote the BSCM010A\n                    mod that uses these REGIONS.* files.\n\n...and many others who both provided information about their area, and re-did\nREGIONS files for their area code, most notably Spotnick in Canada, who helped\nout with the 514 area.\n\nAnd a VERY HARD thump on the head to those Sysops who, for some totally\nunforseen reason, have decided not to help us out by telling us where they are\nlocated, even though finding such information would be quite simple (e.g.\ndialing their BBS and waiting for the next LD bill to show up).  If you find a\nSysop who won't give his location, feel free to use the flamethrower at the\nmaximum setting.  These people give all the rest of us in WWIVnet a bad name.\n\nAs always, these files will be kept as up-to-date as possible via the\nREGIONS.* Update Sub, hosted by me.  Subtype is 10955, and I'm @19955.\nAuto-requestable.\n\nThanks for your interest in these files, and if you find errors, LET ME KNOW!!\n\n                             Scott Schnegelberger\n\n\nSpackle #1 @19955.WWIVnet                      spackle@allen.com\n        #1 @1000.FILEnet                       scott.schnegelberger@delta.com\n\n\n                  The Rubicon [ASV]  Raleigh, North Carolina\n          919-676-0738    24 hrs    14,400/v32bis/v42bis/MNP 2-5\n\n"
  },
  {
    "path": "install/regions/REGIONS.224",
    "content": "Algonquin, Illinois\n999\n"
  },
  {
    "path": "install/regions/REGIONS.225",
    "content": "Somewhere in La., Louisiana\n201\n205\n206\n212\n214\n215\n216\n219\n222\n226\n233\n234\n235\n237\n247\n251\n266\n274\n285\n287\n298\n310\n312\n315\n316\n317\n319\n322\n324\n325\n326\n327\n373\n376\n378\n390\n397\n404\n405\n408\n409\n413\n425\n426\n445\n473\n474\n490\n496\n498\n505\n545\n603\n607\n608\n612\n614\n615\n617\n618\n621\n638\n660\n677\n692\n701\n704\n706\n709\n713\n715\n716\n717\n718\n719\n721\n743\n744\n746\n754\n757\n760\n761\n772\n776\n777\n784\n791\n802\n806\n815\n819\n906\n907\n909\n910\n916\n930\n931\n932\n934\n936\n938\n939\n951\n952\n953\n954\n955\n964\n975\n977\n978\n979\n987\nAlbany, Louisiana\n567\nBaton Rouge, Louisiana\n231\n232\n261\n262\n267\n272\n273\n275\n291\n292\n293\n295\n296\n297\n332\n334\n335\n336\n337\n338\n339\n342\n343\n344\n346\n352\n353\n354\n355\n356\n357\n358\n359\n377\n379\n381\n382\n383\n387\n388\n389\n399\n499\n749\n751\n752\n753\n755\n756\n763\n765\n766\n767\n768\n769\n771\n774\n775\n778\n920\n921\n922\n923\n924\n925\n926\n927\n928\n929\n933\n935\n937\n963\nClinton, Louisiana\n683\nConvent, Louisiana\n562\nDenham Springs, Louisiana\n664\n665\n667\nDutch Town, Louisiana\n673\nFrench Stolmont, Louisiana\n698\nGalvez, Louisiana\n622\nGonzales, Louisiana\n644\n647\nInnis, Louisiana\n492\nJackson, Louisiana\n634\nLivingston, Louisiana\n686\nLivonia, Louisiana\n637\nLutcher, Louisiana\n869\nMaringouin, Louisiana\n625\nMaurepas, Louisiana\n695\nMorganza, Louisiana\n694\nNorth Cornor, Louisiana\n874\nNorco, Louisiana\n725\n764\nPlaquemine, Louisiana\n659\n685\n687\nRosedale, Louisiana\n648\nRougon, Louisiana\n627\nSorrento, Louisiana\n675\nSpringfield, Louisiana\n294\nSaint Gabriel, Louisiana\n642\nSaint Francisville, Louisiana\n635\nTunica, Louisiana\n655\nVacherie, Louisiana\n265\nWilson, Louisiana\n629\nZachary, Louisiana\n654\n658\n\u00035Unknown prefix code (225) - Louisiana\n"
  },
  {
    "path": "install/regions/REGIONS.234",
    "content": "Akron, Ohio\n716\nHutchinson, MN\n775\n"
  },
  {
    "path": "install/regions/REGIONS.240",
    "content": "Saint Cloud, MN\n907\n"
  },
  {
    "path": "install/regions/REGIONS.250",
    "content": "[--- BDE Regions File Marker - 05/05/96 ---]\nAbbotsford, BC\n850\n852\n853\n854\n855\n859\n864\nAgassiz, BC\n796\nAhousat, BC\n670\nAiyansh, BC\n633\nAldergrove, BC\n856\n857\nAlert Bay, BC\n974\nAlexis Creek, BC\n394\n395\nAlkali Lake, BC\n440\nArmstrong, BC\n546\nAshcroft, BC\n453\nAspen Park, BC\n578\nAtlin, BC\n651\nAttachie, BC\n262\nAvola, BC\n678\nBalfour, BC\n229\nBamfield, BC\n728\nBarriere, BC\n672\nBear Lake, BC\n972\nBearskin Lake, BC\n236\nBeaver Cove, BC\n928\nBeaver Dell, BC\n484\nBeaver Valley, BC\n243\nBella Bella, BC\n957\nBella Coola, BC\n799\n982\nBlack Point, BC\n487\nBlue River, BC\n673\nBob Quin Lake, BC\n237\nBoston Bar, BC\n867\nBoswell, BC\n223\nBouchie Lake, BC\n249\nBowen Island, BC\n947\nBowser, BC\n757\nBridge Lake, BC\n593\nBritannia Beach, BC\n896\nBurns Lake, BC\n692\n698\nCache Creek, BC\n457\nCampbell River, BC\n285\n286\n287\n830\nCanal Flats, BC\n349\nCassiar, NT\n778\nCastlegar, BC\n365\nCelista, BC\n955\nChase, BC\n577\n679\nChemainus, BC\n246\nChetwynd, BC\n788\nChief Lake, BC\n967\nChilako, BC\n560\nChilliwack, BC\n792\n793\n794\n795\n823\n824\n858\nChristina Lake, BC\n447\nClearwater, BC\n587\n674\nClinton, BC\n200\n459\nCloverdale, BC\n531\n535\n536\n538\n541\n574\n576\nCluculz Lake, BC\n441\nCobble Hill, BC\n743\nCortez Island, BC\n935\nCourtenay, BC\n334\n338\n339\n890\n897\nCranbrook, BC\n426\n489\nCrawford Bay, BC\n227\nCreston, BC\n428\nCumberland, BC\n336\nDarcy, BC\n452\nDawson Creek, BC\n759\n782\n784\nDease Lake, NT\n771\nDonald, BC\n340\nDouglas Lake, BC\n350\nDragon Lake, BC\n747\nDuncan Lake, BC\n366\nDuncan, BC\n746\n748\nDunster, BC\n968\nEast Pine, BC\n780\nElkford, BC\n865\nElko, BC\n529\nEnderby, BC\n838\nFairmont, BC\n345\nFalkland, BC\n379\nFauquier, BC\n269\nFernie, BC\n423\nField, BC\n343\nFlat Rock, BC\n781\nForest Grove, BC\n397\nFort Babine, BC\n975\nFort Fraser, BC\n690\nFort Langley, BC\n888\nFort Nelson, NT\n774\nFort Saint James, BC\n996\nFort Saint John, BC\n785\n787\n789\n827\nFort Ware, BC\n471\nFranois Lake, BC\n695\nFraser Lake, BC\n699\nFruitvale, BC\n367\nFulford Harbor, BC\n653\nGabriola Island, BC\n247\nGanges, BC\n537\nGenelle, BC\n693\nGibsons, BC\n886\nGiscome, BC\n568\nGold Bridge, BC\n238\nGold River, BC\n283\nGolden, BC\n344\nGood Hope Lake, BC\n239\nGrand Forks, BC\n442\nGranisle, BC\n697\nGrasmere, BC\n887\nGrassy Plains, BC\n694\nGreenville, BC\n621\nGreenwood, BC\n445\nGulf Islands, BC\n539\nHaney, BC\n460\n463\n466\n467\nHansard, BC\n966\nHartley Bay, BC\n841\nHartway, BC\n962\nHedley, BC\n292\nHemlock Valley, BC\n797\nHendrix Lake, BC\n393\nHighland Valley, BC\n575\nHixon, BC\n998\nHolberg, BC\n288\nHope, BC\n869\nHorsefly, BC\n620\nHouston, BC\n845\nHudsons Hope, BC\n783\nInvermere, BC\n342\nIskut, NT\n234\nJaffray, BC\n429\nJordan River, BC\n646\nKamloops, BC\n573\n579\nKaslo, BC\n353\nKelowna, BC\n470\n491\n762\n763\n860\n861\n862\n868\nKemano, BC\n634\nKeremeos, BC\n499\nKersley, BC\n993\nKimberley, BC\n427\nKincolith, BC\n326\nKitimat, BC\n632\n639\nKitkatla, BC\n848\nKitsault, BC\n831\nKitwanga, BC\n849\nKlemtu, BC\n839\nKyuquot, BC\n332\nLac La Hache, BC\n396\nLadner, BC\n940\n943\n946\n948\nLadysmith, BC\n245\nLake Cowichan, BC\n749\nLakelse, BC\n798\nLakeview Heights, BC\n769\nLangley, BC\n530\n532\n533\n534\n882\nLantzville, BC\n390\nLasqueti Island, BC\n333\nLikely, BC\n790\n791\nLillooet, BC\n256\nLittle Fort, BC\n677\nLogan Lake, BC\n523\nLoos, BC\n553\nLower Post, NT\n779\nLumby, BC\n547\nLytton, BC\n455\n456\nMackenzie, BC\n997\nManning Park, BC\n840\nMasset, BC\n626\nMcbride, BC\n569\nMcDame Lake, BC\n233\nMcLeese Lake, BC\n297\nMcLeod Lake, BC\n750\nMerritt, BC\n378\nMica Creek, BC\n834\nMidway, BC\n449\nMinaker River, BC\n773\nMission, BC\n820\n826\nMoyie, BC\n829\nMuncho Lake, NT\n776\nNakusp, BC\n265\nNanaimo, BC\n722\n741\n751\n753\n754\n755\nNanoose, BC\n468\nNelson, BC\n352\n354\nNew Denver, BC\n358\nNew Hazelton, BC\n842\nNewton, BC\n543\n572\n590\n591\n594\n596\n597\n599\nNimpo Lake, BC\n742\nNorth Kamloops, BC\n376\n554\nNorth Nelson, BC\n825\nOcean Falls, BC\n289\nOkanagan Falls, BC\n497\nOkanagan Mission, BC\n764\nOliver, BC\n498\nOsoyoos, BC\n495\nOyama, BC\n548\nOyster Bay, BC\n337\nParksville, BC\n248\n752\n954\nParson, BC\n348\nPeachland, BC\n767\nPemberton, BC\n894\nPender Harbour, BC\n883\nPender Island, BC\n629\nPenticton, BC\n490\n492\n493\n496\nPineview, BC\n963\nPitt Meadows, BC\n465\nPoint Roberts, BC\n945\nPort Alberni, BC\n720\n723\n724\nPort Alice, BC\n284\nPort Clements, BC\n557\nPort Coquitlam, BC\n464\n927\n941\n942\n944\nPort Edward, BC\n628\nPort Hardy, BC\n949\nPort McNeill, BC\n956\nPort Mellon, BC\n884\nPort Renfrew, BC\n647\nPort Simpson, BC\n625\nPouce Coupe, BC\n786\nPowell River, BC\n483\nPrespatou, BC\n630\nPrince George, BC\n561\n562\n563\n564\n565\n960\nPrince Rupert, BC\n624\n627\nPrinceton, BC\n295\nPuntzi, BC\n481\nQueen Charlotte, BC\n559\nQuesnel, BC\n991\n992\nRadium, BC\n347\nRed Rock, BC\n330\nRevelstoke, BC\n837\nRichmond, BC\n231\n241\n244\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n448\n522\n644\n671\n821\nRiondel, BC\n225\nRiske Creek, BC\n659\nRock Creek, BC\n446\nRossland, BC\n362\nRutland, BC\n765\nSaanich, BC\n544\n652\n655\n656\nSalmo, BC\n357\nSalmon Arm, BC\n832\n833\n835\nSalmon Valley, BC\n971\nSandspit, BC\n637\nSavona, BC\n373\nSayward, BC\n282\nSechelt, BC\n740\n885\nShalalth, BC\n259\nSicamous, BC\n836\nSkookumchk, BC\n422\nSlocan, BC\n355\nSmithers, BC\n847\nSointula, BC\n973\nSooke, BC\n642\nSorrento, BC\n675\nSouth Kamloops, BC\n371\n372\n374\n828\n851\nSouth Slocan, BC\n359\nSparwood, BC\n425\nSpences Bridge, BC\n458\nSpilmachen, BC\n346\nSquamish, BC\n892\n898\nStewart, BC\n636\nSummerland, BC\n494\nSummit Lake, BC\n965\nTachie, BC\n648\nTahsis, BC\n934\nTatla Lake, BC\n476\nTelegraph Creek, NT\n235\nTelkwa, BC\n846\nTerrace, BC\n635\n638\nThrums, BC\n399\nToad River, NT\n232\nTofino, BC\n725\nTopley, BC\n696\nTrail, BC\n364\n368\nTrout Lake, BC\n369\nTumbler Ridge, BC\n242\nUcluelet, BC\n726\nUnion Bay, BC\n335\nValemount, BC\n566\nVallican, BC\n226\nVananda, BC\n486\nVanderhoof, BC\n567\nVanway, BC\n964\nVavenby, BC\n676\nVernon, BC\n260\n542\n545\n549\n558\nVictoria, BC\n356\n360\n361\n363\n370\n380\n381\n382\n383\n384\n385\n386\n387\n388\n389\n391\n472\n474\n475\n477\n478\n479\n480\n592\n595\n598\n658\n721\n727\n744\n881\n952\n953\n995\nWellington, BC\n756\n758\nWells, BC\n994\nWestbank, BC\n768\nWestview, BC\n485\nWestwold, BC\n375\nWhalley, BC\n581\n582\n583\n584\n585\n586\n588\n589\n951\nWhistler, BC\n932\n938\nWhonnock, BC\n462\nWildwood, BC\n989\nWilliams Lake, BC\n296\n392\n398\nWillow Flats, BC\n920\nWillow Point, BC\n923\nWillowbrook, BC\n843\nWinfield, BC\n766\nWinter Harbor, BC\n969\nWonowon, NT\n772\nWoss Lake, BC\n281\nWynndel, BC\n866\nYahk, BC\n424\nYale, BC\n863\nYoubou, BC\n745\nZeballos, BC\n761\n"
  },
  {
    "path": "install/regions/REGIONS.267",
    "content": "Glendale, Arizona\r\n386\r\n\u00035Unknown prefix code (267) - Arizona\r\n"
  },
  {
    "path": "install/regions/REGIONS.321",
    "content": "Titusville, Florida\r\n833\r\n\u00035Unknown prefix code (321) - Florida\r\n"
  },
  {
    "path": "install/regions/REGIONS.435",
    "content": "Nephi, Utah\n314\nXfer from AC801, Utah\n207\n210\n234\n245\n247\n257\n258\n259\n260\n279\n283\n285\n286\n289\n326\n335\n336\n340\n353\n381\n384\n386\n387\n410\n418\n419\n421\n422\n425\n427\n428\n433\n436\n438\n439\n445\n448\n452\n454\n456\n457\n458\n459\n462\n469\n471\n472\n473\n477\n502\n527\n528\n529\n542\n545\n548\n559\n563\n564\n574\n577\n586\n587\n590\n592\n609\n610\n613\n615\n618\n619\n623\n624\n628\n630\n632\n634\n635\n636\n637\n638\n640\n642\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n663\n665\n668\n669\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n683\n684\n686\n687\n688\n689\n690\n691\n692\n693\n695\n697\n712\n713\n720\n722\n723\n727\n729\n730\n734\n735\n738\n739\n740\n743\n744\n746\n747\n748\n749\n750\n751\n752\n753\n755\n757\n758\n759\n760\n761\n769\n770\n772\n780\n781\n783\n784\n787\n788\n789\n790\n792\n793\n795\n797\n810\n813\n819\n820\n822\n823\n824\n826\n827\n828\n830\n831\n832\n833\n834\n835\n836\n837\n839\n840\n841\n842\n843\n846\n848\n849\n850\n851\n854\n855\n857\n863\n864\n865\n866\n867\n869\n870\n871\n872\n874\n877\n878\n879\n880\n881\n882\n884\n885\n888\n889\n893\n895\n896\n897\n899\n901\n946\n948\n979\n\u00035Unknown prefix code (435) - Utah\n"
  },
  {
    "path": "install/regions/REGIONS.441",
    "content": "[--- BDE Regions File Marker - 05/05/96 ---]\nBermuda\n231\n232\n233\n234\n235\n236\n237\n238\n239\n291\n292\n293\n294\n295\n296\n297\n298\n299\n"
  },
  {
    "path": "install/regions/REGIONS.480",
    "content": "FromAC602, Arizona\n218\n283\n288\n301\n303\n312\n314\n317\n342\n345\n348\n350\n354\n357\n367\n368\n373\n380\n391\n394\n396\n413\n419\n421\n423\n424\n425\n429\n441\n443\n446\n449\n451\n456\n457\n460\n461\n464\n471\n473\n475\n481\n483\n488\n491\n496\n497\n502\n503\n507\n515\n517\n539\n545\n552\n554\n557\n563\n575\n585\n592\n595\n596\n598\n607\n609\n610\n614\n632\n633\n638\n641\n642\n644\n649\n654\n655\n657\n659\n661\n668\n671\n675\n693\n699\n704\n705\n706\n715\n726\n727\n730\n731\n732\n733\n736\n752\n753\n755\n756\n759\n767\n774\n775\n777\n782\n783\n784\n785\n786\n802\n804\n807\n812\n813\n814\n816\n820\n821\n827\n829\n830\n831\n832\n833\n834\n835\n836\n837\n838\n839\n844\n854\n855\n857\n858\n860\n874\n883\n884\n888\n890\n891\n892\n893\n894\n895\n897\n898\n899\n902\n905\n917\n921\n922\n924\n926\n927\n929\n940\n941\n945\n946\n947\n948\n949\n951\n961\n962\n963\n964\n965\n966\n967\n968\n969\n970\n981\n982\n983\n984\n985\n986\n987\n988\n990\n991\n994\n998\n\u00035Unknown prefix code (480) - Arizona\n\n"
  },
  {
    "path": "install/regions/REGIONS.559",
    "content": "Fresno, California\r\n256\r\n\u00035Unknown prefix code (559) - California\r\n"
  },
  {
    "path": "install/regions/REGIONS.570",
    "content": "Shavertown, Pennsylvania\r\n696\r\n\u00035Unknown prefix code (570) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/REGIONS.623",
    "content": "Xfer from AC602, Arizona\n214\n245\n247\n322\n334\n362\n374\n386\n388\n393\n412\n434\n435\n465\n486\n487\n492\n516\n535\n536\n546\n561\n566\n572\n580\n581\n582\n583\n584\n587\n691\n742\n772\n773\n780\n815\n825\n842\n845\n846\n847\n848\n849\n853\n856\n869\n872\n873\n875\n876\n877\n878\n879\n907\n915\n925\n930\n931\n932\n933\n934\n935\n936\n937\n939\n972\n974\n975\n977\n979\n\u00035Unknown prefix code (623) - Arizona\n"
  },
  {
    "path": "install/regions/REGIONS.636",
    "content": "Lisle, Illinois\r\n219\r\n\u00035Unknown prefix code (636) - Illinois\r\n"
  },
  {
    "path": "install/regions/REGIONS.650",
    "content": "Pleasanton, California\r\n346\r\nFoster City, California\r\n627\r\n\u0003Unknown prefix code (650) - California\r\n"
  },
  {
    "path": "install/regions/REGIONS.720",
    "content": "Buffalo Creek, Colorado\r\n999\r\n\u00035Unknown prefix code (720) - Colorado\r\n"
  },
  {
    "path": "install/regions/REGIONS.721",
    "content": "Brunswick, ME\n962\n"
  },
  {
    "path": "install/regions/REGIONS.732",
    "content": "Tom's River, New Jersey\r\n797\r\n\u00035Unknown prefix code (732) - New Jersey\r\n"
  },
  {
    "path": "install/regions/REGIONS.765",
    "content": "Acton, Indiana\n862\nAlbany, Indiana\n789\nAlexandria, Indiana\n724\nAmboy Cnvr, Indiana\n395\nAmo, Indiana\n539\nAnderson, Indiana\n621\n622\n623\n640\n641    \n642\n643\n644\n646\n648\n649\nArlington, Indiana\n663\nAtlanta, Indiana\n292\nAttica, Indiana\n762\n764\nBainbridge, Indiana\n522\nBargersville, Indiana\n422\nBattleground, Indiana\n567\nBelle Union, Indiana\n526\nBloomingdale, Indiana\n498\nBloutsville, Indiana\n774\nBoswell, Indiana\n869\nBridgton, Indiana\n548\nBrookston, Indiana\n563\nBrookville, Indiana\n647\nBuck Creek, Indiana\n589\nBunkerhill, Indiana\n682\n688\n689\nBurlington, Indiana\n566\nCambridge City, Indiana\n478\nCarthage, Indiana\n565\nCayuga, Indiana\n492\nCenterville, Indiana\n855\nCharlottville, Indiana\n936\nChesterfield, Indiana\n378\nClarks Hill, Indiana\n523\nClinton, Indiana\n828\n665\n832\nCloverdale, Indiana\n795\nCoatesville, Indiana\n386\nColfax, Indiana\n324\nConnersville, Indiana\n825\n827\nCovington, Indiana\n793\nCrawfordsville, Indiana\n361\n362    \n363\n364\n366\nCumberland, Indiana\n891\n894\nCutler, Indiana\n268\nDarlington, Indiana\n794\nDelphi, Indiana\n564\nDenver, Indiana\n985\nDunkirk, Indiana\n768\nEaton, Indiana\n396\nElwood, Indiana\n552    \nEminence, Indiana\n528\nFairmount, Indiana\n948\nFarmland, Indiana\n468\nFillmore, Indiana\n246\nFountain City, Indiana\n847\nFowler, Indiana\n884\nFrankfort, Indiana\n652\n654\n659\nFrankton, Indiana\n754\nGaston, Indiana\n358\nGeetingsville, Indiana\n258\nGlenwood, Indiana\n679\nGreencastle, Indiana\n653\n657\n658\n721\nGreens Fork, Indiana\n886\nGreentown, Indiana\n628\nHagerstown, Indiana\n486\n489    \nHartford City, Indiana\n348\nHillsboro, Indiana\n798\nJamestown, Indiana\n676\nKempton, Indiana\n947\nKingman, Indiana\n397\nKirklin, Indiana\n279\nKnightston, Indiana\n345\nKokomo, Indiana\n434\n438\n451\n454\n456\n459\n863\n864\n868\n452\n453\n455\n457\n883\nLadoga, Indiana\n942\nLafayette, Indiana\n340\n360\n420\n421\n423    \n426\n427\n428\n429\n433\n447\n448\n449\n463\n474\n477\n493\n494\n495\n496\n497\n742\n743\n746\n992\nLafontaine, Indiana\n981    \nLapel, Indiana\n534\nLaurel, Indiana\n698\nLebanon, Indiana\n482\n483\nLiberty, Indiana\n458\nLinden, Indiana\n339\nLizton, Indiana\n994\nLynn, Indiana\n874\nManilla, Indiana\n544\nMarietta, Indiana\n729\nMarion, Indiana\n651\n661    \n662\n664\n668\n669\n674\n677\nMarkleville, Indiana\n531\n533\nMarshall, Indiana\n597\nMartinsville, Indiana\n342\n349\nMaxwell, Indiana\n323\n326\nMays, Indiana\n645\nMccordsville, Indiana\n335\n336    \nMechanicsburg, Indiana\n325\n779\nMellott, Indiana\n295\nMichigantown, Indiana\n249\nMiddletown, Indiana\n354\nMilroy, Indiana\n629\nModoc, Indiana\n853\nMontezuma, Indiana\n245\nMontpelier, Indiana\n728\nMooreland, Indiana\n766\nMorristown, Indiana\n763\nMorton, Indiana\n739\nMount Summit, Indiana\n836\nMulberry, Indiana\n296\nMuncie, Indiana\n281\n282\n284\n285\n286\n287\n288\n289\n741\n744\n747    \n748\n749\n751\nNew Castle, Indiana\n521\n524\n527\n529\n593\nNew Lisbon, Indiana\n332\nNew Market, Indiana\n866\nNew Ross, Indiana\n723\nNew Palstone, Indiana\n861\nOaklandon, Indiana\n823\nOtterbein, Indiana\n583\nOxford, Indiana\n385\nParagon, Indiana\n537\nPendleton, Indiana\n778\nPerkinsville, Indiana\n734\nPeru, Indiana\n472\n473\nPittsboro, Indiana\n892\nRedkey, Indiana\n369\nReelsville, Indiana\n672\nRichmond, Indiana\n935\n962\n966\n967\n969\n973\n983\nRidgeville, Indiana\n857\nRoann, Indiana\n833\nRockville, Indiana\n344\n569\nRomney, Indiana\n538\nRossville, Indiana\n379    \nRushville, Indiana\n932\n938\nSharpsville, Indiana\n963\nSheridan, Indiana\n758\nShirley, Indiana\n737\nSpiceland, Indiana\n987\nSpringport, Indiana\n755\nStewart, Indiana\n986\nSummitville, Indiana\n536\nSwayzee, Indiana\n922    \nSweetser, Indiana\n384\nThorntown, Indiana\n436\nTipton, Indiana\n675\nTrafalgar, Indiana\n878\nUnion City, Indiana\n964\nUpland, Indiana\n998\nVan Buren, Indiana\n934\nVeedersburg, Indiana\n294\nWest Lebanon, Indiana\n893\nWest Point, Indiana\n572\nWaldron, Indiana\n525    \nWaveland, Indiana\n435\nWaynetown, Indiana\n234\nWest College Corner, Indiana\n732\nWest Newton, Indiana\n856\nWest Wabash, Indiana\n944\nWhiteland, Indiana\n535\nWhitestown, Indiana\n769\nWilkinson, Indiana\n785\nWinchester, Indiana\n584    \nWindfall, Indiana\n945\nWingate, Indiana\n275\nYorktown, Indiana\n759\n\u00035Unknown prefix code (765) - Indiana\n"
  },
  {
    "path": "install/regions/REGIONS.794",
    "content": "Albemarle, NC\n982\nAlbemarle, NC\n983\nAlton, NC\n764\nAndrews, NC\n321\nAnsonville, NC\n826\nArden, NC\n684\nArden, NC\n687\nAsheville, NC\n240\nAsheville, NC\n251\nAsheville, NC\n252\nAsheville, NC\n253\nAsheville, NC\n254\nAsheville, NC\n255\nAsheville, NC\n257\nAsheville, NC\n258\nAsheville, NC\n259\nAsheville, NC\n274\nAsheville, NC\n298\nAsheville, NC\n299\nAsheville, NC\n777\nBadin, NC\n422\nBakersvl, NC\n688\nBanner Elk, NC\n898\nBarnardsvl, NC\n626\nBeech Mt, NC\n387\nBelmont, NC\n825\nBessemercy, NC\n629\nBethlehem, NC\n495\nBlack Mt, NC\n669\nBlowing Rk, NC\n295\nBlsm Grove, NC\n655\nBoone, NC\n262\nBoone, NC\n264\nBoone, NC\n265\nBrevard, NC\n862\nBrevard, NC\n877\nBrevard, NC\n883\nBrevard, NC\n884\nBrevard, NC\n885\nBrevard, NC\n966\nBrysoncity, NC\n488\nBurnsville, NC\n682\nCanton, NC\n235\nCanton, NC\n646\nCanton, NC\n648\nCaroleen, NC\n657\nCashiers, NC\n743\nCatawba, NC\n241\nCharlotte, NC\n331\nCharlotte, NC\n332\nCharlotte, NC\n333\nCharlotte, NC\n334\nCharlotte, NC\n335\nCharlotte, NC\n336\nCharlotte, NC\n337\nCharlotte, NC\n338\nCharlotte, NC\n339\nCharlotte, NC\n342\nCharlotte, NC\n343\nCharlotte, NC\n344\nCharlotte, NC\n346\nCharlotte, NC\n347\nCharlotte, NC\n355\nCharlotte, NC\n356\nCharlotte, NC\n357\nCharlotte, NC\n358\nCharlotte, NC\n359\nCharlotte, NC\n362\nCharlotte, NC\n364\nCharlotte, NC\n365\nCharlotte, NC\n366\nCharlotte, NC\n370\nCharlotte, NC\n371\nCharlotte, NC\n372\nCharlotte, NC\n373\nCharlotte, NC\n374\nCharlotte, NC\n375\nCharlotte, NC\n376\nCharlotte, NC\n377\nCharlotte, NC\n378\nCharlotte, NC\n379\nCharlotte, NC\n382\nCharlotte, NC\n383\nCharlotte, NC\n391\nCharlotte, NC\n392\nCharlotte, NC\n393\nCharlotte, NC\n394\nCharlotte, NC\n398\nCharlotte, NC\n399\nCharlotte, NC\n521\nCharlotte, NC\n522\nCharlotte, NC\n523\nCharlotte, NC\n525\nCharlotte, NC\n527\nCharlotte, NC\n529\nCharlotte, NC\n531\nCharlotte, NC\n532\nCharlotte, NC\n533\nCharlotte, NC\n534\nCharlotte, NC\n535\nCharlotte, NC\n536\nCharlotte, NC\n537\nCharlotte, NC\n541\nCharlotte, NC\n542\nCharlotte, NC\n543\nCharlotte, NC\n544\nCharlotte, NC\n545\nCharlotte, NC\n547\nCharlotte, NC\n548\nCharlotte, NC\n549\nCharlotte, NC\n551\nCharlotte, NC\n552\nCharlotte, NC\n553\nCharlotte, NC\n554\nCharlotte, NC\n556\nCharlotte, NC\n563\nCharlotte, NC\n564\nCharlotte, NC\n567\nCharlotte, NC\n568\nCharlotte, NC\n570\nCharlotte, NC\n587\nCharlotte, NC\n588\nCharlotte, NC\n594\nCharlotte, NC\n595\nCharlotte, NC\n596\nCharlotte, NC\n597\nCharlotte, NC\n598\nCharlotte, NC\n976\nCherokee, NC\n497\nCherryvl, NC\n435\nChngrvlnds, NC\n855\nChngrvlnds, NC\n857\nChurchland, NC\n762\nClaremont, NC\n459\nCleveland, NC\n278\nClyde, NC\n627\nColumbus, NC\n894\nConcord, NC\n782\nConcord, NC\n784\nConcord, NC\n786\nConcord, NC\n788\nCooleemee, NC\n284\nCullowhee, NC\n227\nCullowhee, NC\n293\nDavidson, NC\n892\nDavidson, NC\n896\nDenton, NC\n869\nDenver, NC\n483\nEllenboro, NC\n453\nEnkacandlr, NC\n665\nEnkacandlr, NC\n667\nFairview, NC\n628\nFontanavlg, NC\n498\nForestcity, NC\n245\nForestcity, NC\n248\nFranklin, NC\n369\nFranklin, NC\n524\nGardencity, NC\n724\nGastonia, NC\n853\nGastonia, NC\n861\nGastonia, NC\n864\nGastonia, NC\n865\nGastonia, NC\n866\nGastonia, NC\n867\nGastonia, NC\n868\nGastonia, NC\n922\nGastonia, NC\n962\nGlnwdprdnc, NC\n738\nGoosecreek, NC\n753\nGranitefls, NC\n396\nGreencreek, NC\n863\nGrntqyrkwl, NC\n279\nGrover, NC\n937\nGuntertown, NC\n656\nHarmony, NC\n546\nHarrisburg, NC\n455\nHayesville, NC\n389\nHemby Bdg, NC\n882\nHendersnvl, NC\n685\nHendersnvl, NC\n692\nHendersnvl, NC\n693\nHendersnvl, NC\n696\nHendersnvl, NC\n697\nHendersnvl, NC\n891\nHickory, NC\n244\nHickory, NC\n256\nHickory, NC\n322\nHickory, NC\n323\nHickory, NC\n324\nHickory, NC\n327\nHickory, NC\n328\nHickory, NC\n381\nHighlands, NC\n526\nHildebran, NC\n397\nHotsprings, NC\n622\nHuntersvl, NC\n875\nIjames, NC\n492\nIndian Trl, NC\n821\nKannapolis, NC\n932\nKannapolis, NC\n933\nKannapolis, NC\n938\nKannapolis, NC\n939\nKings Mt, NC\n734\nKings Mt, NC\n739\nLake Lure, NC\n625\nLattimore, NC\n434\nLawndale, NC\n538\nLeicester, NC\n683\nLenoir, NC\n726\nLenoir, NC\n728\nLenoir, NC\n754\nLenoir, NC\n757\nLenoir, NC\n758\nLexington, NC\n242\nLexington, NC\n243\nLexington, NC\n246\nLexington, NC\n249\nLexington, NC\n352\nLexington, NC\n744\nLexington, NC\n956\nLiberty, NC\n494\nLilesville, NC\n848\nLincolnton, NC\n276\nLincolnton, NC\n732\nLincolnton, NC\n735\nLocust, NC\n888\nLowell, NC\n824\nMaggie Vly, NC\n926\nMaiden, NC\n428\nMarion, NC\n652\nMarion, NC\n659\nMars Hill, NC\n689\nMarshall, NC\n649\nMarshville, NC\n624\nMatthews, NC\n841\nMatthews, NC\n845\nMatthews, NC\n846\nMatthews, NC\n847\nMicaville, NC\n675\nMocksville, NC\n634\nMonroe, NC\n282\nMonroe, NC\n283\nMonroe, NC\n289\nMooresvl, NC\n663\nMooresvl, NC\n664\nMorganton, NC\n433\nMorganton, NC\n437\nMorganton, NC\n438\nMorganton, NC\n584\nMorven, NC\n851\nMountholly, NC\n822\nMountholly, NC\n827\nMt View, NC\n294\nMtpleasant, NC\n436\nMurphy, NC\n837\nNew Hope, NC\n592\nNew London, NC\n463\nNew Salem, NC\n385\nNewland, NC\n733\nNewton, NC\n462\nNewton, NC\n464\nNewton, NC\n465\nNorwood, NC\n474\nOakboro, NC\n485\nOld Fort, NC\n668\nPeachldplk, NC\n272\nPineville, NC\n889\nReeds, NC\n787\nRobbinsvl, NC\n479\nRutherfdtn, NC\n286\nRutherfdtn, NC\n287\nSalisbury, NC\n633\nSalisbury, NC\n636\nSalisbury, NC\n637\nSalisbury, NC\n638\nSaluda, NC\n749\nSevier, NC\n756\nShelby, NC\n480\nShelby, NC\n481\nShelby, NC\n482\nShelby, NC\n484\nShelby, NC\n487\nSherils Fd, NC\n478\nSocrwdrcrk, NC\n228\nSouthmont, NC\n798\nSprucepine, NC\n765\nStanley, NC\n263\nStatesvl, NC\n872\nStatesvl, NC\n873\nStatesvl, NC\n876\nStatesvl, NC\n878\nStonypoint, NC\n585\nSugargrove, NC\n297\nSuit, NC\n644\nSwannanoa, NC\n686\nSylva, NC\n586\nTaylorsvl, NC\n632\nTroutman, NC\n528\nTryon, NC\n859\nUniongrove, NC\n539\nValdese, NC\n874\nValdese, NC\n879\nWadesboro, NC\n694\nWatauga, NC\n963\nWaterville, NC\n486\nWaxhaw, NC\n843\nWaynesvl, NC\n452\nWaynesvl, NC\n456\nWeavervl, NC\n645\nWeavervl, NC\n658\nWelcome, NC\n731\nWingate, NC\n233\n"
  },
  {
    "path": "install/regions/REGIONS.843",
    "content": "Abbeville, South Carolina\n459\nAndrews, South Carolina\n264\nAynor, South Carolina\n358\nBeaufort, South Carolina\n521\n522\n524\n525\nBennettsville, South Carolina\n454\n479\nBethune, South Carolina\n334\nBlackburg, South Carolina\n490\nBlacksburg, South Carolina\n839\nBlenheim, South Carolina\n528\nBluffton, South Carolina\n757\n837\nBonneau, South Carolina\n825\nCalhoun Falls, South Carolina\n447\nCharleston, South Carolina\n529\n552\n554\n556\n569\n570\n571\n572\n577\n693\n696\n720\n721\n722\n723\n724\n727\n728\n729\n740\n743\n744\n745\n747\n760\n762\n763\n764\n766\n767\n768\n769\n795\n797\n820\n824\n830\n852\n853\n860\n863\n937\n961\n973\n974\nCheraw, South Carolina\n537\n921\nChesterfield, South Carolina\n623\nClemson, South Carolina\n653\n654\n656\n858\n624\nClinton, South Carolina\n833\n923\n938\nClio, South Carolina\n586\nCollins Creek, South Carolina\n650\nConway, South Carolina\n248\nCottageville, South Carolina\n835\nCowpens, South Carolina\n463\nCross, South Carolina\n753\nDarlington, South Carolina\n393\n395\n398\nDillon, South Carolina\n774\n841\nEasley, South Carolina\n850\n855\nEast Conway, South Carolina\n340\n347\n349\nEcnwywmybc, South Carolina\n236\nEdisto Isle, South Carolina\n869\nFlorence, South Carolina\n621\n660\n661\n662\n664\n665\n667\n669\n673\n678\n679\n687\nFloyds, South Carolina\n392\nFolly Beach, South Carolina\n588\nGaffney, South Carolina\n487\n488\n489\nGeorgetown, South Carolina\n520\n527\n546\nGreeleyville, South Carolina\n426\nGreenville, South Carolina\n220\n230\n232\n233\n234\n235\n239\n240\n241\n242\n243\n244\n246\n250\n255\n268\n269\n270\n271\n277\n281\n282\n288\n290\n291\n292\n294\n295\n297\n298\n299\n322\n350\n370\n371\n380\n390\n420\n422\n430\n455\n458\n460\n467\n470\n627\n675\n676\n859\nGreenwood, South Carolina\n223\n227\n229\n941\n942\nHanahan, South Carolina\n544\n566\nHardeeville, South Carolina\n784\nHarleyville, South Carolina\n462\nHartsville, South Carolina\n332\n339\n383\nHemingway, South Carolina\n558\nHendersenville, South Carolina\n844\nHickory Tavern, South Carolina\n575\nHilton Head, South Carolina\n341\n342\n363\n384\n671\n681\n686\n689\n785\n842\nHonea Path, South Carolina\n369\nHuger, South Carolina\n336\nJamestown, South Carolina\n257\nJefferson, South Carolina\n658\nJoanna, South Carolina\n697\nJohn's Island, South Carolina\n559\nJohnsonville, South Carolina\n386\nKingstree, South Carolina\n354\nLadson, South Carolina\n553\nLake City, South Carolina\n394\nLake View, South Carolina\n759\nLake Woodwmy Beach, South Carolina\n293\nLamar, South Carolina\n326\nLandrum, South Carolina\n457\nLane, South Carolina\n387\nLatta, South Carolina\n752\nLaurel Bay, South Carolina\n846\nLaurens, South Carolina\n984\n682\nLebanon, South Carolina\n688\nLockhart, South Carolina\n545\nLodge, South Carolina\n866\nLoris, South Carolina\n357\n756\nLyman, South Carolina\n433\n439\n949\nMacedonia, South Carolina\n565\nMc Coll, South Carolina\n523\nMarion, South Carolina\n362\n423\n431\nMcbee, South Carolina\n335\nMcclellanville, South Carolina\n887\nMoncks Corner, South Carolina\n761\n899\nMount Carmel, South Carolina\n391\nMt. Pleasant, South Carolina\n849\n856\n881\n884\nMullins, South Carolina\n464\nMurrls Inlet, South Carolina\n651\nMyrtle Beach, South Carolina\n238\n444\n448\n449\n450\n477\n497\n626\n828\n946\nNewtonville, South Carolina\n265\nNichols, South Carolina\n526\nNinety Six, South Carolina\n543\nNokingstre, South Carolina\n382\nNorth Conway, South Carolina\n365\nNorth Myrtle Beach, South Carolina\n249\n272\n280\n361\nOlanta, South Carolina\n396\nPageland, South Carolina\n672\nPamplico, South Carolina\n493\nPatrick, South Carolina\n498\nPawleys Is, South Carolina\n237\nPineville, South Carolina\n351\nPlumbranch, South Carolina\n443\nRidgeland, South Carolina\n726\nRowland, South Carolina\n262\nRuby, South Carolina\n634\nSaint George, South Carolina\n563\nSaint Stephen, South Carolina\n567\nSaluda, South Carolina\n445\nScranton, South Carolina\n389\nSociety Hill, South Carolina\n378\nSouth Conway, South Carolina\n397\nSpartanburg, South Carolina\n542\n560\n573\n574\n576\n578\n579\n580\n582\n583\n585\n587\n590\n591\n592\n594\n595\n596\n597\n599\n620\n948\nTimmonsville, South Carolina\n346\nTravelers Rest, South Carolina\n834\n836\nTroy, South Carolina\n746\nTurbeville, South Carolina\n659\nWalhalla, South Carolina\n638\nWalterboro, South Carolina\n549\n538\n893\nWampee, South Carolina\n399\nWareshoals, South Carolina\n456\nWaterloo, South Carolina\n677\nWest End, South Carolina\n861\nWest Andrews, South Carolina\n221\nWest Abbeville, South Carolina\n446\nWilliams, South Carolina\n562\nYemassee, South Carolina\n589\n\u00035Unknown prefix code (843) - South Carolina\n"
  },
  {
    "path": "install/regions/REGIONS.850",
    "content": "\n\n"
  },
  {
    "path": "install/regions/REGIONS.860",
    "content": "Groton, Connecticut\n917\n\n"
  },
  {
    "path": "install/regions/REGIONS.864",
    "content": "Anderson, South Carolina\n224\n225\n226\n231\n260\n261\n287\n296\n375\n933\n934\nBlacksburg, South Carolina\n839\n\u00035Unknown prefix code (864) - South Carolina\n"
  },
  {
    "path": "install/regions/REGIONS.971",
    "content": "Xfer from AC503 July 11-99, Orgeon\n201\n202\n203\n204\n205\n207\n208\n209\n210\n212\n213\n214\n215\n216\n217\n218\n219\n220\n221\n222\n223\n224\n225\n226\n227\n228\n229\n230\n231\n232\n233\n234\n235\n236\n237\n238\n239\n240\n241\n242\n243\n244\n245\n246\n247\n248\n249\n250\n251\n252\n253\n254\n255\n256\n257\n259\n260\n261\n262\n263\n264\n265\n266\n267\n268\n269\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n280\n281\n282\n283\n284\n285\n286\n287\n288\n289\n290\n291\n292\n293\n294\n295\n296\n297\n298\n299\n301\n303\n304\n305\n306\n307\n308\n309\n310\n312\n313\n314\n315\n316\n317\n318\n319\n320\n321\n323\n324\n326\n327\n328\n329\n330\n331\n332\n333\n334\n335\n336\n337\n340\n341\n342\n343\n344\n345\n347\n348\n349\n350\n351\n352\n353\n354\n356\n357\n358\n359\n361\n362\n363\n364\n365\n366\n367\n369\n370\n371\n372\n373\n374\n375\n378\n379\n380\n381\n382\n383\n385\n386\n387\n389\n390\n391\n393\n394\n395\n396\n397\n399\n401\n402\n403\n404\n405\n406\n407\n408\n409\n410\n412\n413\n414\n415\n416\n417\n418\n419\n420\n421\n422\n423\n424\n425\n426\n427\n428\n429\n430\n431\n432\n433\n434\n435\n437\n438\n439\n441\n442\n443\n444\n445\n446\n447\n448\n449\n450\n451\n452\n453\n454\n455\n456\n460\n461\n462\n463\n464\n465\n466\n467\n468\n469\n471\n472\n473\n474\n475\n476\n477\n478\n479\n480\n481\n482\n484\n485\n486\n487\n488\n490\n491\n492\n493\n494\n495\n497\n498\n499\n502\n504\n505\n507\n508\n510\n512\n513\n514\n515\n516\n517\n518\n519\n520\n521\n522\n523\n524\n525\n526\n527\n528\n529\n530\n531\n532\n533\n534\n535\n536\n537\n538\n539\n540\n542\n543\n544\n548\n550\n551\n552\n553\n554\n556\n557\n558\n559\n560\n561\n566\n569\n570\n571\n572\n574\n575\n576\n577\n578\n579\n580\n581\n582\n585\n587\n588\n589\n590\n591\n592\n594\n596\n597\n598\n599\n601\n603\n604\n605\n606\n608\n610\n612\n613\n614\n615\n616\n617\n618\n619\n620\n621\n622\n623\n624\n625\n626\n627\n628\n629\n630\n631\n632\n633\n634\n635\n636\n637\n638\n639\n640\n641\n642\n643\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n662\n663\n664\n665\n666\n667\n668\n669\n670\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n684\n685\n689\n690\n691\n692\n693\n694\n695\n696\n697\n698\n699\n701\n702\n703\n704\n705\n706\n707\n708\n709\n710\n712\n713\n716\n720\n721\n722\n723\n725\n726\n727\n728\n730\n731\n732\n733\n734\n735\n736\n743\n746\n747\n748\n749\n751\n752\n753\n754\n756\n757\n760\n761\n762\n763\n767\n768\n769\n770\n771\n772\n773\n774\n775\n776\n777\n778\n780\n781\n783\n784\n786\n787\n788\n789\n790\n792\n793\n794\n795\n796\n797\n799\n802\n803\n804\n805\n806\n807\n808\n810\n813\n816\n817\n818\n819\n820\n821\n823\n824\n825\n826\n827\n828\n829\n830\n831\n832\n833\n834\n835\n838\n840\n843\n844\n845\n846\n848\n849\n850\n851\n852\n854\n855\n857\n858\n859\n860\n862\n864\n866\n868\n869\n870\n871\n872\n873\n874\n876\n877\n878\n879\n880\n881\n882\n883\n884\n885\n886\n887\n890\n891\n892\n893\n894\n897\n899\n902\n903\n904\n905\n906\n907\n909\n910\n916\n918\n919\n920\n921\n925\n930\n931\n932\n936\n937\n938\n939\n940\n941\n942\n943\n944\n945\n946\n947\n948\n949\n951\n952\n955\n957\n961\n962\n963\n964\n968\n969\n970\n972\n973\n975\n977\n978\n980\n981\n982\n983\n985\n986\n989\n991\n992\n\u00035Unknown prefix code (971) - Oregon\n"
  },
  {
    "path": "install/regions/REGIONS.991",
    "content": "Kadena Air Base, Okinawa, Japan\n633\n734\n745\nCamp Shields, Okinawa, Japan\n732\nCamp Kinser, Okinawa, Japan\n737\nCamp Lester, Okinawa, Japan\n731\nCamp Foster/Butler, Okinawa, Japan\n645\n735\nCamp Courtney, Okinawa, Japan\n723\nCamp Schwab, Okinawa, Japan\n736\nCamp McTureous, Okinawa, Japan\n722\nUnknown prefix code (611) - Okinawa, Japan\n\n"
  },
  {
    "path": "install/regions/REGIONS.999",
    "content": "Internet\n\n\u001a"
  },
  {
    "path": "install/regions/regions.000",
    "content": "Unknown Areacode!!!\r\n000\r\n"
  },
  {
    "path": "install/regions/regions.006",
    "content": "International\r\n006\r\n011\r\n047\r\n0711\r\n074\r\n092\r\n093\r\n098\r\n100\r\n439\r\n447\r\n\u00035Unknown prefix (006) - International"
  },
  {
    "path": "install/regions/regions.031",
    "content": "Scotland\r\n558\r\n\u00035Unknown prefix code (031) - Scotland"
  },
  {
    "path": "install/regions/regions.044",
    "content": "United Kingdom\r\n044029\r\n068\r\n\u00035Unknown prefix (044) - U.K."
  },
  {
    "path": "install/regions/regions.049",
    "content": "Germany\r\n049"
  },
  {
    "path": "install/regions/regions.057",
    "content": "Columbia\r\n057\r\n\u00035Unknown prefix code (057) - United Kingdom"
  },
  {
    "path": "install/regions/regions.061",
    "content": "North Toowoomba, Australia\r\n478\r\n\u00035Unknown prefix code (061) - Australia"
  },
  {
    "path": "install/regions/regions.071",
    "content": "London, United Kingdom\r\n071\r\n\u00035Unknown prefix (071) - London, U.K."
  },
  {
    "path": "install/regions/regions.081",
    "content": "London, United Kingdom\r\n081071\r\n\u00035Unknown prefix (081) - London, U.K."
  },
  {
    "path": "install/regions/regions.098",
    "content": "Kadena AFB, Okinawa, Japan\r\n897\r\n633\r\n\u00035Unknown prefix code (098) Okinawa, Japan\r\n"
  },
  {
    "path": "install/regions/regions.201",
    "content": "Andover, New Jersey\r\n786\r\nBayonne, New Jersey\r\n339\r\n436\r\n437\r\n823\r\n858\r\nBelleville, New Jersey\r\n450\r\n751\r\n759\r\nBernardsville, New Jersey\r\n425\r\nBloomfield, New Jersey\r\n281\r\n338\r\n429\r\n655\r\n680\r\n743\r\n744\r\n746\r\n748\r\n783\r\n893\r\nBoonton, New Jersey\r\n263\r\n299\r\n316\r\n331\r\n334\r\n335\r\n402\r\nBranchville, New Jersey\r\n948\r\nButler, New Jersey\r\n283\r\n492\r\n838\r\nCaldwell, New Jersey\r\n226\r\n227\r\n228\r\n244\r\n364\r\n403\r\n575\r\n808\r\n882\r\nChatham, New Jersey\r\n635\r\n701\r\nCliffside, New Jersey\r\n224\r\n313\r\n886\r\n941\r\n943\r\n945\r\nCloster, New Jersey\r\n767\r\n768\r\nCragmere, New Jersey\r\n512\r\n529\r\nDover, New Jersey\r\n328\r\n361\r\n366\r\n442\r\n724\r\n989\r\nDumont, New Jersey\r\n384\r\n385\r\n387\r\n439\r\n501\r\nEnglewood, New Jersey\r\n567\r\n568\r\n569\r\n816\r\n871\r\n894\r\nErskine Lakes, New Jersey\r\n962       \r\nFair Lawn, New Jersey\r\n280\r\n321\r\n410\r\n703\r\n791\r\n794\r\n796\r\n797\r\nFreehold, New Jersey\r\n411\r\nFranklinboro, New Jersey\r\n209\r\n827\r\nHackensack, New Jersey\r\n229\r\n294\r\n296\r\n314\r\n315\r\n329\r\n342\r\n343\r\n368\r\n394\r\n417\r\n440\r\n441\r\n487\r\n488\r\n489\r\n519\r\n525\r\n570\r\n587\r\n641\r\n646\r\n695\r\n712\r\n752\r\n803\r\n807\r\n814\r\n843\r\n909\r\n960\r\n970\r\n996\r\nHasbrouck Heights, New Jersey\r\n237\r\n288\r\n393\r\n462\r\nHawthorne, New Jersey\r\n238\r\n304\r\n423\r\n427\r\nHopatcong, New Jersey\r\n398\r\n663\r\n770\r\nJersey City, New Jersey\r\n216\r\n217\r\n222\r\n240\r\n309\r\n320\r\n324\r\n332\r\n333\r\n401\r\n413\r\n420\r\n432\r\n433\r\n434\r\n435\r\n451\r\n547\r\n557\r\n626\r\n653\r\n656\r\n659\r\n714\r\n792\r\n795\r\n798\r\n860\r\n915\r\n938\r\n963\r\nKearny, New Jersey\r\n955\r\n991\r\n997\r\n998\r\nLake Mohawk, New Jersey\r\n726\r\n729\r\nLeonia, New Jersey\r\n302\r\n346\r\n461\r\n585\r\n592\r\n706\r\n944\r\n947\r\nLittle Falls, New Jersey\r\n256\r\n785\r\n812\r\n890\r\nLivingston, New Jersey\r\n533\r\n535\r\n716\r\n740\r\n992\r\n994\r\nMadison, New Jersey\r\n301\r\n377\r\n408\r\n514\r\n593\r\n765\r\n822\r\n966\r\nMendham, New Jersey\r\n543\r\nMillburn, New Jersey\r\n376\r\n379\r\n467\r\n564\r\n912\r\nMontague, New Jersey\r\n293\r\nMontvale, New Jersey\r\n555\r\nMorristown, New Jersey\r\n203\r\n243\r\n267\r\n285\r\n292\r\n326\r\n397\r\n404\r\n455\r\n490\r\n538\r\n539\r\n540\r\n605\r\n606\r\n631\r\n644\r\n650\r\n682\r\n715\r\n829\r\n898\r\n924\r\n971\r\n984\r\n993\r\nMountain View, New Jersey\r\n305\r\n628\r\n633\r\n694\r\n696\r\n872\r\nMt Freedom, New Jersey\r\n895\r\nNetcong, New Jersey\r\n347\r\n426\r\n691\r\nNewark, New Jersey\r\n201\r\n207\r\n242\r\n259\r\n268\r\n282\r\n312\r\n318\r\n344\r\n371\r\n372\r\n373\r\n374\r\n375\r\n399\r\n409\r\n416\r\n421\r\n430\r\n456\r\n465\r\n466\r\n468\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n491\r\n504\r\n565\r\n578\r\n589\r\n596\r\n608\r\n621\r\n622\r\n623\r\n624\r\n639\r\n642\r\n643\r\n645\r\n648\r\n649\r\n690\r\n698\r\n705\r\n708\r\n733\r\n799\r\n802\r\n817\r\n824\r\n877\r\n905\r\n923\r\n926\r\n961\r\n976\r\n982\r\nNewfoundland, New Jersey\r\n208\r\n697\r\nNewton, New Jersey\r\n300\r\n380\r\n383\r\n579\r\nNorwood, New Jersey\r\n784\r\nNutley, New Jersey\r\n235\r\n284\r\n661\r\n667\r\nOakland, New Jersey\r\n337\r\n405\r\nOradell, New Jersey\r\n261\r\n262\r\n265\r\n599\r\n967\r\n986\r\nOrange, New Jersey\r\n266\r\n325\r\n414\r\n669\r\n672\r\n673\r\n674\r\n675\r\n676\r\n677\r\n678\r\n731\r\n736\r\nPark Ridge, New Jersey\r\n307\r\n391\r\n476\r\n573\r\n930\r\nParsippany, New Jersey\r\n884\r\nPassaic, New Jersey\r\n253\r\n340\r\n365\r\n458\r\n470\r\n471\r\n472\r\n473\r\n478\r\n546\r\n614\r\n772\r\n773\r\n777\r\n778\r\n779\r\n916\r\nPaterson, New Jersey\r\n225\r\n278\r\n279\r\n345\r\n357\r\n389\r\n516\r\n523\r\n595\r\n684\r\n742\r\n790\r\n881\r\n904\r\n942\r\n956\r\n977\r\nPompton Lakes, New Jersey\r\n616\r\n831\r\n835\r\n839\r\nRamsey, New Jersey\r\n236\r\n327\r\n818\r\n825\r\n934\r\nRidgewood, New Jersey\r\n251\r\n444\r\n445\r\n447\r\n612\r\n652\r\n670\r\nRochelle Park, New Jersey\r\n845\r\nRockaway, New Jersey\r\n586\r\n625\r\n627\r\n983\r\nRutherford, New Jersey\r\n438\r\n460\r\n507\r\n531\r\n804\r\n896\r\n933\r\n935\r\n939\r\nSouth Orange, New Jersey\r\n275\r\n378\r\n761\r\n762\r\n763\r\nSuccasunna, New Jersey\r\n252\r\n584\r\n927\r\nSussex, New Jersey\r\n702\r\n875\r\nTeaneck, New Jersey\r\n692\r\n801\r\n833\r\n836\r\n837\r\n907\r\n928\r\nUnion City, New Jersey\r\n223\r\n271\r\n295\r\n319\r\n330\r\n348\r\n392\r\n601\r\n617\r\n662\r\n854\r\n861\r\n863\r\n864\r\n865\r\n866\r\n867\r\n868\r\n869\r\n902\r\n974\r\nUpper Grnwdlk, New Jersey\r\n853\r\nUpper Montclair, New Jersey\r\n509\r\nVernon, New Jersey\r\n764\r\nVerona, New Jersey\r\n239\r\n857\r\nWest Milford, New Jersey\r\n728\r\nWestwood, New Jersey\r\n358\r\n664\r\n666\r\n722\r\nWhippany, New Jersey\r\n386\r\n428\r\n503\r\n515\r\n581\r\n887\r\n952\r\nWyckoff, New Jersey\r\n847\r\n848\r\n891\r\n\u00035Unknown prefix code (201) - New Jersey\r\n"
  },
  {
    "path": "install/regions/regions.202",
    "content": "Washington, D.C.\r\n205\r\n208\r\n213\r\n215\r\n219\r\n223\r\n224\r\n225\r\n226\r\n228\r\n232\r\n233\r\n234\r\n244\r\n245\r\n252\r\n253\r\n254\r\n259\r\n260\r\n264\r\n265\r\n267\r\n268\r\n269\r\n272\r\n273\r\n274\r\n275\r\n279\r\n282\r\n283\r\n287\r\n288\r\n289\r\n291\r\n293\r\n296\r\n298\r\n305\r\n307\r\n307\r\n307\r\n307\r\n307\r\n310\r\n316\r\n319\r\n324\r\n326\r\n328\r\n331\r\n332\r\n333\r\n334\r\n336\r\n337\r\n338\r\n342\r\n343\r\n346\r\n347\r\n348\r\n357\r\n358\r\n362\r\n363\r\n364\r\n365\r\n366\r\n371\r\n373\r\n374\r\n376\r\n377\r\n382\r\n383\r\n387\r\n388\r\n389\r\n392\r\n393\r\n395\r\n396\r\n397\r\n398\r\n399\r\n401\r\n404\r\n408\r\n416\r\n418\r\n424\r\n426\r\n429\r\n432\r\n433\r\n434\r\n435\r\n436\r\n445\r\n447\r\n452\r\n453\r\n456\r\n457\r\n458\r\n462\r\n463\r\n466\r\n467\r\n471\r\n472\r\n473\r\n475\r\n477\r\n479\r\n482\r\n483\r\n484\r\n485\r\n488\r\n490\r\n494\r\n501\r\n504\r\n508\r\n512\r\n514\r\n515\r\n516\r\n522\r\n523\r\n526\r\n529\r\n535\r\n537\r\n539\r\n541\r\n542\r\n543\r\n544\r\n546\r\n547\r\n554\r\n561\r\n562\r\n563\r\n566\r\n574\r\n575\r\n576\r\n581\r\n582\r\n583\r\n584\r\n586\r\n588\r\n592\r\n597\r\n605\r\n606\r\n610\r\n613\r\n616\r\n619\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n628\r\n632\r\n633\r\n634\r\n635\r\n636\r\n637\r\n638\r\n639\r\n646\r\n647\r\n651\r\n653\r\n659\r\n662\r\n663\r\n665\r\n666\r\n667\r\n668\r\n672\r\n673\r\n675\r\n676\r\n678\r\n679\r\n682\r\n685\r\n686\r\n687\r\n690\r\n707\r\n708\r\n714\r\n716\r\n720\r\n722\r\n723\r\n724\r\n726\r\n727\r\n728\r\n732\r\n736\r\n737\r\n745\r\n752\r\n755\r\n757\r\n767\r\n773\r\n775\r\n778\r\n783\r\n784\r\n785\r\n786\r\n788\r\n789\r\n796\r\n797\r\n799\r\n801\r\n806\r\n812\r\n822\r\n825\r\n828\r\n829\r\n832\r\n833\r\n835\r\n837\r\n842\r\n843\r\n844\r\n855\r\n857\r\n861\r\n862\r\n863\r\n865\r\n872\r\n874\r\n877\r\n879\r\n882\r\n884\r\n885\r\n887\r\n889\r\n895\r\n896\r\n898\r\n901\r\n906\r\n915\r\n917\r\n921\r\n927\r\n928\r\n936\r\n939\r\n942\r\n943\r\n944\r\n947\r\n954\r\n955\r\n956\r\n957\r\n962\r\n965\r\n966\r\n973\r\n976\r\n986\r\n991\r\n994\r\n996\r\n\u00035Unknown prefix code (202) - District Of Columbia\r\n"
  },
  {
    "path": "install/regions/regions.203",
    "content": "Ansoniader, Connecticut\r\n732\r\n734\r\n735\r\n736\r\nBaltic, Connecticut\r\n822\r\nBerlin, Connecticut\r\n828\r\n829\r\nBethany, Connecticut\r\n393\r\nBloomfield, Connecticut\r\n242\r\n243\r\n286\r\n726\r\n768\r\n769\r\nBranford, Connecticut\r\n481\r\n483\r\n488\r\nBridgeport, Connecticut\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n362\r\n365\r\n366\r\n367\r\n368\r\n371\r\n372\r\n373\r\n374\r\n382\r\n384\r\n556\r\n576\r\n579\r\n581\r\n942\r\nBristol, Connecticut\r\n582\r\n583\r\n584\r\n585\r\n589\r\nBrookfield, Connecticut\r\n740\r\n775\r\nByram, Connecticut\r\n531\r\n532\r\n552\r\nCanaan, Connecticut\r\n824\r\nCanterbury, Connecticut\r\n546\r\nCanton, Connecticut\r\n693\r\nCheshire, Connecticut\r\n250\r\n271\r\n272\r\nClinton, Connecticut\r\n664\r\n669\r\nColchester, Connecticut\r\n537\r\nColumbia, Connecticut\r\n228\r\nCornwall, Connecticut\r\n672\r\nCoventry, Connecticut\r\n742\r\nCromwell, Connecticut\r\n632\r\n635\r\nDanbury, Connecticut\r\n530\r\n570\r\n730\r\n731\r\n733\r\n743\r\n744\r\n748\r\n770\r\n778\r\n790\r\n791\r\n792\r\n794\r\n796\r\n797\r\n798\r\n825\r\n830\r\nDanielson, Connecticut\r\n774\r\n779\r\nDarien, Connecticut\r\n655\r\n656\r\n662\r\nDeep River, Connecticut\r\n526\r\nDurham, Connecticut\r\n349\r\nEast Hartford, Connecticut\r\n282\r\n289\r\n290\r\n291\r\n528\r\n557\r\n565\r\n568\r\n569\r\nEast Hampton, Connecticut\r\n267\r\nEnfield, Connecticut\r\n253\r\n741\r\n745\r\n749\r\n763\r\nEssex, Connecticut\r\n767\r\nFairfield, Connecticut\r\n254\r\n255\r\n256\r\n259\r\nFarmington, Connecticut\r\n673\r\n674\r\n675\r\n676\r\n677\r\n678\r\n679\r\nGeorgetown, Connecticut\r\n544\r\nGlastonby, Connecticut\r\n633\r\n652\r\n657\r\n659\r\nGoshen, Connecticut\r\n491\r\nGranby, Connecticut\r\n653\r\n844\r\nGreenwich, Connecticut\r\n622\r\n625\r\n629\r\n661\r\n861\r\n862\r\n863\r\n864\r\n869\r\nGroton, Connecticut\r\n433\r\n441\r\n445\r\n446\r\n448\r\n449\r\nGuilford, Connecticut\r\n453\r\n457\r\n458\r\nHaddam, Connecticut\r\n345\r\nHamden, Connecticut\r\n230\r\n248\r\n281\r\n287\r\n288\r\nHampton, Connecticut\r\n455\r\nHartford, Connecticut\r\n220\r\n240\r\n241\r\n244\r\n246\r\n247\r\n249\r\n251\r\n252\r\n260\r\n273\r\n275\r\n277\r\n278\r\n279\r\n280\r\n293\r\n296\r\n297\r\n299\r\n320\r\n340\r\n360\r\n369\r\n422\r\n424\r\n493\r\n520\r\n522\r\n524\r\n525\r\n527\r\n541\r\n543\r\n545\r\n547\r\n548\r\n549\r\n550\r\n558\r\n559\r\n560\r\n566\r\n588\r\n590\r\n594\r\n650\r\n660\r\n722\r\n724\r\n725\r\n727\r\n728\r\n750\r\n752\r\n820\r\n841\r\n842\r\n850\r\n880\r\n930\r\n936\r\n947\r\n951\r\n952\r\n953\r\n954\r\n956\r\n976\r\n987\r\nHarwinton, Connecticut\r\n485\r\nHuntington, Connecticut\r\n922\r\n924\r\n925\r\n926\r\n929\r\n944\r\nJewett City, Connecticut\r\n376\r\nKent, Connecticut\r\n927\r\nKillngworth, Connecticut\r\n663\r\nLakeville, Connecticut\r\n435\r\nLebanon, Connecticut\r\n642\r\nLitchfield, Connecticut\r\n567\r\nLyme, Connecticut\r\n434\r\nMadison, Connecticut\r\n245\r\n421\r\nManchester, Connecticut\r\n643\r\n645\r\n646\r\n647\r\n649\r\nMarlborough, Connecticut\r\n295\r\nMeriden, Connecticut\r\n235\r\n237\r\n238\r\n420\r\n630\r\n631\r\n634\r\n639\r\n686\r\nMiddlebury, Connecticut\r\n593\r\nMiddletown, Connecticut\r\n343\r\n344\r\n346\r\n347\r\n636\r\n638\r\nMilford, Connecticut\r\n783\r\n874\r\n876\r\n877\r\n878\r\n882\r\nMontville, Connecticut\r\n848\r\nMoodus, Connecticut\r\n873\r\nMystic, Connecticut\r\n535\r\n536\r\n572\r\nNorth Branford, Connecticut\r\n484\r\nNaugatuck, Connecticut\r\n720\r\n723\r\n729\r\nNew Canaan, Connecticut\r\n966\r\n972\r\nNew Haven, Connecticut\r\n370\r\n387\r\n389\r\n390\r\n392\r\n397\r\n430\r\n432\r\n436\r\n466\r\n467\r\n468\r\n469\r\n492\r\n494\r\n495\r\n497\r\n498\r\n499\r\n553\r\n562\r\n624\r\n640\r\n641\r\n737\r\n766\r\n771\r\n772\r\n773\r\n776\r\n777\r\n781\r\n782\r\n784\r\n785\r\n786\r\n787\r\n789\r\n821\r\n865\r\n867\r\nNew London, Connecticut\r\n437\r\n439\r\n440\r\n442\r\n443\r\n444\r\n447\r\n460\r\n490\r\nNew Britain, Connecticut\r\n223\r\n224\r\n225\r\n229\r\n826\r\n827\r\n832\r\nNewington, Connecticut\r\n665\r\n666\r\n667\r\nNew Milford, Connecticut\r\n350\r\n354\r\n355\r\nNewtown, Connecticut\r\n270\r\n426\r\nNorth Fairfield, Connecticut\r\n746\r\nNiantic, Connecticut\r\n691\r\n739\r\nNorfolk, Connecticut\r\n542\r\nNorth Haven, Connecticut\r\n234\r\n239\r\n985\r\nNorwalk, Connecticut\r\n398\r\n470\r\n760\r\n831\r\n838\r\n840\r\n845\r\n846\r\n847\r\n849\r\n851\r\n852\r\n853\r\n854\r\n855\r\n856\r\n857\r\n858\r\n866\r\nNorwich, Connecticut\r\n823\r\n884\r\n885\r\n886\r\n887\r\n889\r\nNorth Thompson, Connecticut\r\n935\r\nOld Greenwich, Connecticut\r\n637\r\n698\r\nOld Saybrk, Connecticut\r\n388\r\n391\r\n395\r\nOrange, Connecticut\r\n795\r\n799\r\nPawcatuck, Connecticut\r\n599\r\nPlainfield, Connecticut\r\n564\r\nPlainville, Connecticut\r\n747\r\n793\r\nPortland, Connecticut\r\n342\r\nPutnam, Connecticut\r\n923\r\n928\r\n963\r\n974\r\nRedding, Connecticut\r\n938\r\nRidgefield, Connecticut\r\n431\r\n438\r\nRockville, Connecticut\r\n870\r\n871\r\n872\r\n875\r\nS Windsor, Connecticut\r\n644\r\n648\r\nSalem, Connecticut\r\n859\r\nSeymour, Connecticut\r\n881\r\n888\r\nSharon, Connecticut\r\n364\r\nSimsbury, Connecticut\r\n651\r\n658\r\n843\r\nSouthingtn, Connecticut\r\n276\r\n620\r\n621\r\n628\r\nStafford Spring, Connecticut\r\n684\r\nStamford, Connecticut\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n348\r\n351\r\n352\r\n353\r\n356\r\n357\r\n358\r\n359\r\n363\r\n462\r\n961\r\n962\r\n964\r\n965\r\n967\r\n968\r\n969\r\n973\r\n975\r\n977\r\n978\r\n979\r\nStorrs, Connecticut\r\n427\r\n429\r\n486\r\n487\r\nStratford, Connecticut\r\n375\r\n377\r\n378\r\n380\r\n381\r\n383\r\n385\r\n386\r\nSuffield, Connecticut\r\n668\r\nThomaston, Connecticut\r\n283\r\nTorrington, Connecticut\r\n480\r\n482\r\n489\r\n496\r\n626\r\nTrumbull, Connecticut\r\n261\r\n268\r\n452\r\n459\r\nWest Hartford, Connecticut\r\n231\r\n232\r\n233\r\n236\r\n521\r\n523\r\n561\r\n586\r\nWallingford, Connecticut\r\n265\r\n269\r\n284\r\n294\r\n949\r\nWashington, Connecticut\r\n868\r\nWaterbury, Connecticut\r\n573\r\n574\r\n575\r\n577\r\n578\r\n580\r\n592\r\n596\r\n597\r\n598\r\n670\r\n680\r\n690\r\n753\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n780\r\n890\r\nWatertown, Connecticut\r\n274\r\n945\r\nWest Haven, Connecticut\r\n931\r\n932\r\n933\r\n934\r\n937\r\nWestbrook, Connecticut\r\n399\r\nWestport, Connecticut\r\n221\r\n222\r\n226\r\n227\r\n341\r\n451\r\n454\r\nWethersfield, Connecticut\r\n257\r\n258\r\n529\r\n563\r\n571\r\n721\r\nWillimantc, Connecticut\r\n423\r\n428\r\n450\r\n456\r\n465\r\n940\r\nWilton, Connecticut\r\n761\r\n762\r\n834\r\nWindsor, Connecticut\r\n285\r\n298\r\n683\r\n687\r\n688\r\nWindsor Lakes, Connecticut\r\n292\r\n623\r\n627\r\n654\r\nWinsted, Connecticut\r\n379\r\n738\r\nWolcott, Connecticut\r\n879\r\nWoodbury, Connecticut\r\n262\r\n263\r\n264\r\n266\r\n\u00035Unknown prefix code (203) - Connecticut\r\n"
  },
  {
    "path": "install/regions/regions.204",
    "content": "Alexander, Manitoba, Canada\r\n752\r\nAlonsa, Manitoba, Canada\r\n767\r\nAltona, Manitoba, Canada\r\n324\r\n327\r\nArborg, Manitoba, Canada\r\n364\r\n376\r\nAshern, Manitoba, Canada\r\n768\r\nAustin, Manitoba, Canada\r\n637\r\nBaldur, Manitoba, Canada\r\n535\r\nBasswood, Manitoba, Canada\r\n874\r\nBeausejour, Manitoba, Canada\r\n265\r\n268\r\nBelmont, Manitoba, Canada\r\n528\r\n537\r\nBenito, Manitoba, Canada\r\n539\r\nBerens River, Manitoba, Canada\r\n382\r\nBeulah, Manitoba, Canada\r\n568\r\nBinscarth, Manitoba, Canada\r\n532\r\nBirtle, Manitoba, Canada\r\n842\r\nBissett, Manitoba, Canada\r\n277\r\nBoissevain, Manitoba, Canada\r\n534\r\nBrandon, Manitoba, Canada\r\n332\r\n725\r\n726\r\n727\r\n728\r\n729\r\n763\r\nBrochet, Manitoba, Canada\r\n323\r\nBrookdale, Manitoba, Canada\r\n354\r\nCamperville, Manitoba, Canada\r\n524\r\nCarberry, Manitoba, Canada\r\n834\r\nCarman, Manitoba, Canada\r\n745\r\n828\r\nCartwright, Manitoba, Canada\r\n529\r\nChurchill, Manitoba, Canada\r\n675\r\nClear Lake, Manitoba, Canada\r\n848\r\nCormorant, Manitoba, Canada\r\n357\r\nCowan, Manitoba, Canada\r\n569\r\nCrandall, Manitoba, Canada\r\n562\r\nCranberry Portage, Manitoba, Canada\r\n468\r\n472\r\nCross Lake, Manitoba, Canada\r\n676\r\nCrystal City, Manitoba, Canada\r\n873\r\nCypress River, Manitoba, Canada\r\n743\r\nDarlingfield, Manitoba, Canada\r\n246\r\nDauphin, Manitoba, Canada\r\n622\r\n638\r\n655\r\nDeloraine, Manitoba, Canada\r\n747\r\nDominion City, Manitoba, Canada\r\n427\r\nDugald, Manitoba, Canada\r\n444\r\n755\r\n853\r\n866\r\n878\r\nEasterville, Manitoba, Canada\r\n329\r\nEddystone, Manitoba, Canada\r\n448\r\nElgin, Manitoba, Canada\r\n769\r\nElie, Manitoba, Canada\r\n353\r\nElkhorn, Manitoba, Canada\r\n845\r\nElm Creek, Manitoba, Canada\r\n436\r\nEmerson, Manitoba, Canada\r\n373\r\nErickson, Manitoba, Canada\r\n636\r\nEriksdale, Manitoba, Canada\r\n739\r\nEthelbert, Manitoba, Canada\r\n742\r\nFalconlake, Manitoba, Canada\r\n349\r\nFisher River, Manitoba, Canada\r\n394\r\n645\r\nFisherbrch, Manitoba, Canada\r\n372\r\nFlin Flon, Manitoba, Canada\r\n687\r\nFork River, Manitoba, Canada\r\n657\r\nFoxwarren, Manitoba, Canada\r\n683\r\n847\r\nGilbertpls, Manitoba, Canada\r\n548\r\nGillam, Manitoba, Canada\r\n486\r\n652\r\nGimli, Manitoba, Canada\r\n642\r\n643\r\nGladstone, Manitoba, Canada\r\n385\r\nGlenboro, Manitoba, Canada\r\n827\r\nGod Lake Nar, Manitoba, Canada\r\n335\r\n366\r\nGrand Rapids, Manitoba, Canada\r\n639\r\nGrand Beach, Manitoba, Canada\r\n754\r\n756\r\nGrandview, Manitoba, Canada\r\n546\r\nGull Lake, Manitoba, Canada\r\n635\r\nGypsumville, Manitoba, Canada\r\n659\r\nHadashville, Manitoba, Canada\r\n426\r\nHamiota, Manitoba, Canada\r\n764\r\nHartney, Manitoba, Canada\r\n858\r\nHecla, Manitoba, Canada\r\n279\r\nHolland, Manitoba, Canada\r\n526\r\nIlford, Manitoba, Canada\r\n288\r\nInwood, Manitoba, Canada\r\n278\r\nKelwood, Manitoba, Canada\r\n967\r\nKenton, Manitoba, Canada\r\n838\r\nKillarney, Manitoba, Canada\r\n523\r\nLabroqueri, Manitoba, Canada\r\n424\r\nLacbrochet, Manitoba, Canada\r\n337\r\nLacdubonnt, Manitoba, Canada\r\n345\r\nLangruth, Manitoba, Canada\r\n445\r\n843\r\nLeaf Rapids, Manitoba, Canada\r\n473\r\nLibau, Manitoba, Canada\r\n766\r\nLittle Grand Rapids, Manitoba, Canada\r\n397\r\nLundar, Manitoba, Canada\r\n762\r\nLynn Lake, Manitoba, Canada\r\n356\r\nMacgregor, Manitoba, Canada\r\n685\r\nMafeking, Manitoba, Canada\r\n545\r\nManigotagn, Manitoba, Canada\r\n363\r\nManitou, Manitoba, Canada\r\n242\r\nMcauley, Manitoba, Canada\r\n722\r\nMccreary, Manitoba, Canada\r\n835\r\nMelita, Manitoba, Canada\r\n522\r\n634\r\n649\r\n658\r\n665\r\n673\r\n686\r\nMiami, Manitoba, Canada\r\n435\r\nMiniota, Manitoba, Canada\r\n567\r\nMinnedosa, Manitoba, Canada\r\n865\r\n867\r\nMinto, Manitoba, Canada\r\n776\r\nMoose Lake, Manitoba, Canada\r\n678\r\nMorden, Manitoba, Canada\r\n822\r\nMorris, Manitoba, Canada\r\n737\r\n746\r\n758\r\nNeepawa, Manitoba, Canada\r\n368\r\n476\r\n966\r\nNelson House, Manitoba, Canada\r\n484\r\nNewdale, Manitoba, Canada\r\n585\r\n849\r\nNorway House, Manitoba, Canada\r\n359\r\nNtrdmdlrds, Manitoba, Canada\r\n248\r\nOak Lake, Manitoba, Canada\r\n855\r\nOak River, Manitoba, Canada\r\n566\r\nOakville, Manitoba, Canada\r\n267\r\nOchreriver, Manitoba, Canada\r\n733\r\nOxford House, Manitoba, Canada\r\n538\r\nPelicn Rapid, Manitoba, Canada\r\n587\r\nPikwitonei, Manitoba, Canada\r\n458\r\nPilotmound, Manitoba, Canada\r\n825\r\nPinawa, Manitoba, Canada\r\n753\r\nPine Falls, Manitoba, Canada\r\n367\r\nPine River, Manitoba, Canada\r\n263\r\nPinedock, Manitoba, Canada\r\n276\r\n395\r\nPiney, Manitoba, Canada\r\n423\r\nPleasant Valley, Manitoba, Canada\r\n543\r\nPlumas, Manitoba, Canada\r\n352\r\n386\r\nPlumcoulee, Manitoba, Canada\r\n829\r\nPoplar River, Manitoba, Canada\r\n244\r\nPoplarfield, Manitoba, Canada\r\n664\r\nPortage Lprar, Manitoba, Canada\r\n239\r\n243\r\n252\r\n274\r\n428\r\n856\r\n857\r\nPort Du Bois, Manitoba, Canada\r\n884\r\nPukatwagon, Manitoba, Canada\r\n553\r\nRapid City, Manitoba, Canada\r\n826\r\nRathwell, Manitoba, Canada\r\n749\r\nRed S Lake, Manitoba, Canada\r\n469\r\nRennie, Manitoba, Canada\r\n369\r\nReston, Manitoba, Canada\r\n662\r\n854\r\n877\r\nRivers, Manitoba, Canada\r\n328\r\nRiverton, Manitoba, Canada\r\n378\r\nRoblin, Manitoba, Canada\r\n935\r\n937\r\nRoland, Manitoba, Canada\r\n343\r\nRorketon, Manitoba, Canada\r\n732\r\nRossburn, Manitoba, Canada\r\n859\r\nRussell, Manitoba, Canada\r\n564\r\n773\r\nSanford, Manitoba, Canada\r\n736\r\nSelkirk, Manitoba, Canada\r\n482\r\n738\r\n757\r\n785\r\nShamattawa, Manitoba, Canada\r\n565\r\nShilo, Manitoba, Canada\r\n765\r\nShoal Lake, Manitoba, Canada\r\n234\r\n759\r\nSidney, Manitoba, Canada\r\n466\r\nSnow Lake, Manitoba, Canada\r\n358\r\nSnowflake, Manitoba, Canada\r\n876\r\nSouth Indian Lake, Manitoba, Canada\r\n374\r\nSomerset, Manitoba, Canada\r\n744\r\nSouris, Manitoba, Canada\r\n483\r\nSperling, Manitoba, Canada\r\n626\r\nSplit Lake, Manitoba, Canada\r\n341\r\n342\r\nSprague, Manitoba, Canada\r\n437\r\nSaint Agathe, Manitoba, Canada\r\n882\r\n883\r\nSaint Claude, Manitoba, Canada\r\n379\r\nSaint Frnc Xr, Manitoba, Canada\r\n864\r\nSaint Laurent, Manitoba, Canada\r\n646\r\nSaint Pierre, Manitoba, Canada\r\n347\r\n433\r\nStanndchns, Manitoba, Canada\r\n422\r\nStarbuck, Manitoba, Canada\r\n735\r\nSteep Rock, Manitoba, Canada\r\n449\r\nSteinbach, Manitoba, Canada\r\n321\r\n326\r\n346\r\n355\r\n377\r\n388\r\n434\r\nStonewall, Manitoba, Canada\r\n322\r\n344\r\n375\r\n383\r\n467\r\nStrathclar, Manitoba, Canada\r\n365\r\n625\r\nStrosedlac, Manitoba, Canada\r\n447\r\nSwan Lake, Manitoba, Canada\r\n836\r\nSwan River, Manitoba, Canada\r\n236\r\n238\r\n525\r\n734\r\nTadoule Lake, Manitoba, Canada\r\n684\r\nTeulon, Manitoba, Canada\r\n886\r\nThicket Portage, Manitoba, Canada\r\n286\r\nThe Pas, Manitoba, Canada\r\n623\r\n624\r\nThompson, Manitoba, Canada\r\n677\r\n778\r\nTreherne, Manitoba, Canada\r\n723\r\nVirden, Manitoba, Canada\r\n556\r\n748\r\nVita, Manitoba, Canada\r\n425\r\nWaasagamch, Manitoba, Canada\r\n456\r\n457\r\n462\r\nWabowden, Manitoba, Canada\r\n689\r\nWanless, Manitoba, Canada\r\n682\r\nWaterhen, Manitoba, Canada\r\n628\r\nWawanesa, Manitoba, Canada\r\n824\r\nWhitemouth, Manitoba, Canada\r\n348\r\nWinipegoss, Manitoba, Canada\r\n656\r\nWinkler, Manitoba, Canada\r\n325\r\nWinnipeg, Manitoba, Canada\r\n222\r\n224\r\n225\r\n228\r\n231\r\n233\r\n235\r\n237\r\n253\r\n254\r\n255\r\n256\r\n257\r\n261\r\n269\r\n275\r\n284\r\n287\r\n333\r\n334\r\n336\r\n338\r\n339\r\n452\r\n453\r\n474\r\n475\r\n477\r\n478\r\n488\r\n489\r\n582\r\n586\r\n589\r\n631\r\n632\r\n633\r\n654\r\n661\r\n663\r\n667\r\n668\r\n669\r\n694\r\n697\r\n770\r\n771\r\n772\r\n774\r\n775\r\n780\r\n783\r\n784\r\n786\r\n787\r\n788\r\n789\r\n831\r\n832\r\n833\r\n837\r\n885\r\n888\r\n889\r\n895\r\n896\r\n897\r\n923\r\n924\r\n925\r\n931\r\n932\r\n933\r\n934\r\n940\r\n941\r\n942\r\n943\r\n944\r\n945\r\n946\r\n947\r\n948\r\n949\r\n955\r\n956\r\n957\r\n958\r\n976\r\n981\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n989\r\n992\r\nWinnipeg Beach, Manitoba, Canada\r\n389\r\nWoodridge, Manitoba, Canada\r\n429\r\n\u00035Unknown prefix code (204) - Manitoba, Canada\r\n"
  },
  {
    "path": "install/regions/regions.205",
    "content": "Abbeville, Alabama\r\n585\r\nAlabaster, Alabama\r\n620\r\n663\r\n664\r\nAlberta, Alabama\r\n573\r\nAliceville, Alabama\r\n373\r\nAndalusia, Alabama\r\n222\r\nArab, Alabama\r\n586\r\nArdmore, Alabama\r\n420\r\n423\r\nAriton, Alabama\r\n762\r\nArlington, Alabama\r\n385\r\nAroney, Alabama\r\n561\r\nAshford, Alabama\r\n899\r\nAshland, Alabama\r\n354\r\nAshville, Alabama\r\n594\r\nAtmore, Alabama\r\n368\r\nAttalla, Alabama\r\n538\r\n570\r\nAuburn, Alabama\r\n821\r\n826\r\n844\r\n887\r\nBanks, Alabama\r\n243\r\nBayminette, Alabama\r\n580\r\n937\r\nBayoulbtre, Alabama\r\n824\r\nBeatrice, Alabama\r\n789\r\nBellefntne, Alabama\r\n973\r\nBerry, Alabama\r\n689\r\nBessemer, Alabama\r\n424\r\n425\r\n426\r\n428\r\n481\r\n436\r\n477\r\n491\r\n497\r\nBirmingham, Alabama\r\n226\r\n250\r\n251\r\n252\r\n254\r\n307\r\n320\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n458\r\n521\r\n531\r\n581\r\n583\r\n715\r\n731\r\n741\r\n801\r\n902\r\n913\r\n914\r\n915\r\n936\r\n960\r\n976\r\n999\r\n808\r\n841\r\n849\r\n822\r\n823\r\n978\r\n979\r\n833\r\n836\r\n838\r\n923\r\n925\r\n929\r\n951\r\n956\r\n967\r\n969\r\n970\r\n972\r\n977\r\n980\r\n991\r\n995\r\n744\r\n290\r\n805\r\n806\r\n818\r\n819\r\n869\r\n888\r\n916\r\n940\r\n941\r\n942\r\n945\r\n954\r\n444\r\n560\r\n733\r\n985\r\n987\r\n988\r\n520\r\n853\r\n854\r\n856\r\n558\r\n906\r\n918\r\n930\r\n933\r\n934\r\n939\r\n975\r\n591\r\n592\r\n595\r\n599\r\n780\r\n781\r\n783\r\n785\r\n786\r\n787\r\n788\r\n791\r\n798\r\n802\r\n868\r\n870\r\n871\r\n877\r\n879\r\n319\r\n403\r\n555\r\n716\r\nBlountsville, Alabama\r\n429\r\nBoaz, Alabama\r\n593\r\n840\r\nBon Secour, Alabama\r\n949\r\nBrantley, Alabama\r\n527\r\nBrewton, Alabama\r\n809\r\n867\r\nBridgeport, Alabama\r\n495\r\nBrilliant, Alabama\r\n465\r\nBrundidge, Alabama\r\n735\r\nBryant, Alabama\r\n597\r\nButler, Alabama\r\n459\r\nCalera, Alabama\r\n668\r\nCamden, Alabama\r\n682\r\nCamp Hill, Alabama\r\n896\r\nCarbonhill, Alabama\r\n924\r\nCarrollton, Alabama\r\n367\r\nCastlebury, Alabama\r\n966\r\nCatherine, Alabama\r\n225\r\nCedar Bluff, Alabama\r\n779\r\nCentre, Alabama\r\n927\r\nCentreville, Alabama\r\n926\r\nChatom, Alabama\r\n847\r\nChelsea, Alabama\r\n678\r\nCherokee, Alabama\r\n359\r\n360\r\n370\r\nChildersberg, Alabama\r\n378\r\nChulafinne, Alabama\r\n253\r\nCitronelle, Alabama\r\n866\r\nClanton, Alabama\r\n217\r\n280\r\n755\r\nClayton, Alabama\r\n775\r\nClear Spgs, Alabama\r\n931\r\nClio, Alabama\r\n397\r\nCoffeeville, Alabama\r\n276\r\nCollinsville, Alabama\r\n524\r\nColumbia, Alabama\r\n696\r\nColumbiana, Alabama\r\n669\r\nCordova, Alabama\r\n483\r\nCottonwood, Alabama\r\n691\r\nCourtland, Alabama\r\n637\r\nCrossville, Alabama\r\n528\r\nDadeville, Alabama\r\n825\r\nDaleville, Alabama\r\n255\r\n503\r\n598\r\nDauphin Island, Alabama\r\n861\r\nDecatur, Alabama\r\n306\r\n340\r\n350\r\n351\r\n353\r\n355\r\n552\r\nDeer Park, Alabama\r\n777\r\nDelta, Alabama\r\n488\r\nDemopolis, Alabama\r\n216\r\n289\r\nDetroit, Alabama\r\n273\r\nDixons Mills, Alabama\r\n992\r\nDora, Alabama\r\n648\r\nDothan, Alabama\r\n671\r\n677\r\n712\r\n713\r\n719\r\n790\r\n792\r\n793\r\n794\r\n797\r\nDouble Springs, Alabama\r\n489\r\nDozier, Alabama\r\n496\r\nEcho, Alabama\r\n795\r\nEclectic, Alabama\r\n541\r\nElba, Alabama\r\n897\r\nElberta, Alabama\r\n986\r\nElkmont, Alabama\r\n732\r\nEnterprise, Alabama\r\n308\r\n347\r\n393\r\nEthelsville, Alabama\r\n658\r\nEufaula, Alabama\r\n616\r\n687\r\nEutaw, Alabama\r\n336\r\n372\r\nEvergreen, Alabama\r\n513\r\n578\r\nExcel, Alabama\r\n765\r\nFairhope, Alabama\r\n928\r\n990\r\nFalkville, Alabama\r\n784\r\nFayette, Alabama\r\n932\r\nFinchburg, Alabama\r\n282\r\nFlat Rock, Alabama\r\n632\r\nFlatwood, Alabama\r\n998\r\nFlomaton, Alabama\r\n296\r\nFlorala, Alabama\r\n858\r\nFoley, Alabama\r\n943\r\n952\r\nForesthome, Alabama\r\n346\r\nFort Davis, Alabama\r\n485\r\nFort Morgan, Alabama\r\n540\r\nFowl River, Alabama\r\n873\r\nFrancisco, Alabama\r\n448\r\nFrankville, Alabama\r\n754\r\nFredonia, Alabama\r\n499\r\nFriscocity, Alabama\r\n267\r\nFruitdale, Alabama\r\n827\r\nFruithurst, Alabama\r\n579\r\nFt Deposit, Alabama\r\n227\r\nFyffe, Alabama\r\n623\r\nGantt, Alabama\r\n388\r\nGardendale, Alabama\r\n608\r\n631\r\nGaylesville, Alabama\r\n422\r\nGeneva, Alabama\r\n684\r\nGeorgiana, Alabama\r\n376\r\nGeraldine, Alabama\r\n659\r\nGilbertown, Alabama\r\n843\r\nGoodwater, Alabama\r\n839\r\nGordo, Alabama\r\n364\r\nGordon, Alabama\r\n522\r\nGordonsville, Alabama\r\n563\r\nGoshen, Alabama\r\n484\r\nGosport, Alabama\r\n258\r\nGrand Bay, Alabama\r\n865\r\nGrant, Alabama\r\n728\r\nGrayson, Alabama\r\n292\r\nGraysville, Alabama\r\n674\r\nGreensboro, Alabama\r\n624\r\nGreenville, Alabama\r\n382\r\nGrove Hill, Alabama\r\n275\r\nGuin, Alabama\r\n468\r\nGulfshores, Alabama\r\n948\r\n968\r\nGuntersvl, Alabama\r\n506\r\n571\r\n582\r\nGurley, Alabama\r\n776\r\nHackleburg, Alabama\r\n935\r\nHaleyville, Alabama\r\n486\r\nHamilton, Alabama\r\n921\r\nHanceville, Alabama\r\n287\r\n352\r\nHartford, Alabama\r\n588\r\nHartselle, Alabama\r\n751\r\n773\r\n778\r\nHayneville, Alabama\r\n548\r\nHazelgreen, Alabama\r\n828\r\nHeadland, Alabama\r\n693\r\nHeflin, Alabama\r\n463\r\nHenagar, Alabama\r\n657\r\nHoltville, Alabama\r\n569\r\nHuguley, Alabama\r\n576\r\nHurtsboro, Alabama\r\n667\r\nHuxford, Alabama\r\n294\r\nIrv St Elm, Alabama\r\n957\r\nJackson, Alabama\r\n246\r\nJacksonville, Alabama\r\n435\r\n782\r\nJasper, Alabama\r\n221\r\n302\r\n384\r\n387\r\nJemison, Alabama\r\n688\r\nKennedy, Alabama\r\n596\r\nKillen, Alabama\r\n757\r\nKinston, Alabama\r\n565\r\nKowaliga, Alabama\r\n857\r\nLafayette, Alabama\r\n864\r\nLangdale, Alabama\r\n756\r\nLapine, Alabama\r\n537\r\nLecta, Alabama\r\n748\r\nLeeds, Alabama\r\n640\r\n699\r\nLeesburg, Alabama\r\n526\r\nLeighton, Alabama\r\n446\r\nLexington, Alabama\r\n229\r\nLillian, Alabama\r\n962\r\nLincoln, Alabama\r\n763\r\nLinden, Alabama\r\n295\r\nLineville, Alabama\r\n396\r\nLisman, Alabama\r\n398\r\nLivingston, Alabama\r\n609\r\n652\r\nLouisville, Alabama\r\n266\r\nLowndesbo, Alabama\r\n278\r\nLoxley, Alabama\r\n964\r\nLuverne, Alabama\r\n335\r\nLynn, Alabama\r\n893\r\nMadison, Alabama\r\n461\r\n464\r\n730\r\n772\r\n961\r\nMagnolia Springs, Alabama\r\n965\r\nMaplesville, Alabama\r\n366\r\nMarion, Alabama\r\n683\r\nMassey, Alabama\r\n462\r\nMccullough, Alabama\r\n577\r\nMcintosh, Alabama\r\n944\r\nMckenzie, Alabama\r\n374\r\nMelvin, Alabama\r\n771\r\nMentone, Alabama\r\n634\r\nMidland Cy, Alabama\r\n983\r\nMidway, Alabama\r\n529\r\nMillport, Alabama\r\n662\r\nMillry, Alabama\r\n846\r\nMobile, Alabama\r\n330\r\n452\r\n456\r\n457\r\n675\r\n679\r\n633\r\n639\r\n341\r\n342\r\n343\r\n344\r\n380\r\n460\r\n408\r\n443\r\n402\r\n415\r\n417\r\n421\r\n431\r\n432\r\n433\r\n434\r\n438\r\n439\r\n441\r\n454\r\n604\r\n605\r\n690\r\n694\r\n770\r\n450\r\n470\r\n471\r\n473\r\n476\r\n478\r\n479\r\n602\r\n660\r\n661\r\n666\r\n621\r\n626\r\n645\r\n649\r\n653\r\n304\r\nMonroeville, Alabama\r\n575\r\n743\r\nMontevallo, Alabama\r\n665\r\nMontgomery, Alabama\r\n202\r\n213\r\n215\r\n224\r\n223\r\n240\r\n241\r\n242\r\n244\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n269\r\n270\r\n271\r\n272\r\n277\r\n279\r\n281\r\n284\r\n285\r\n286\r\n288\r\n293\r\n303\r\n317\r\n399\r\n416\r\n516\r\n519\r\n832\r\n834\r\n860\r\n953\r\n613\r\nMorgan City, Alabama\r\n498\r\nMorson Crossroad, Alabama\r\n363\r\nMoulton, Alabama\r\n905\r\n974\r\nMoundville, Alabama\r\n371\r\nMount Vernon, Alabama\r\n829\r\nMunford, Alabama\r\n358\r\nNanafalia, Alabama\r\n736\r\nNauvoo, Alabama\r\n697\r\nNectar, Alabama\r\n559\r\nNeedham, Alabama\r\n673\r\nNew Hope, Alabama\r\n723\r\nNew Market, Alabama\r\n379\r\nNew Brockton, Alabama\r\n894\r\nNewton, Alabama\r\n299\r\nNewville, Alabama\r\n889\r\nNorthport, Alabama\r\n333\r\nNotasulga, Alabama\r\n257\r\nOakland, Alabama\r\n982\r\nOakman, Alabama\r\n622\r\nOden Ridge, Alabama\r\n482\r\nOdenville, Alabama\r\n629\r\nOhatchee, Alabama\r\n892\r\nOneonta, Alabama\r\n274\r\n625\r\nOpelika, Alabama\r\n705\r\n742\r\n745\r\n749\r\n704\r\nOpp, Alabama\r\n493\r\nOrange Beach, Alabama\r\n981\r\nOrrville, Alabama\r\n996\r\nOwen Crossroads, Alabama\r\n725\r\nOzark, Alabama\r\n774\r\nPanola, Alabama\r\n455\r\nParrish, Alabama\r\n686\r\nPell City, Alabama\r\n338\r\n884\r\nPennington, Alabama\r\n654\r\nPerote, Alabama\r\n474\r\nPeterman, Alabama\r\n564\r\nPheonix City, Alabama\r\n291\r\n297\r\n298\r\n480\r\n855\r\nPhil Campbell, Alabama\r\n993\r\nPiedmont, Alabama\r\n447\r\nPine Apple, Alabama\r\n746\r\nPine Hill, Alabama\r\n963\r\nPine Level, Alabama\r\n584\r\nPinson, Alabama\r\n680\r\n681\r\nPisgah, Alabama\r\n451\r\nPrattville, Alabama\r\n361\r\n365\r\nRagland, Alabama\r\n472\r\nRainsville, Alabama\r\n638\r\n717\r\nRamer, Alabama\r\n562\r\nRanburne, Alabama\r\n568\r\nRed Bay, Alabama\r\n356\r\nRed Level, Alabama\r\n469\r\nReform, Alabama\r\n375\r\nRepton, Alabama\r\n248\r\nResearch Park West, Alabama\r\n922\r\n971\r\nRinehart, Alabama\r\n643\r\nRoanoke, Alabama\r\n863\r\nRobertsdale, Alabama\r\n947\r\nRock Mills, Alabama\r\n885\r\nRockford, Alabama\r\n377\r\nRogersvale, Alabama\r\n247\r\nRussellville, Alabama\r\n331\r\n332\r\nSamson, Alabama\r\n898\r\nSand Rock, Alabama\r\n523\r\nScottsboro, Alabama\r\n218\r\n259\r\n574\r\nSection, Alabama\r\n228\r\nSelma, Alabama\r\n412\r\n418\r\n419\r\n872\r\n874\r\n875\r\nSeminole, Alabama\r\n946\r\nShawmut, Alabama\r\n768\r\nSheffield, Alabama\r\n381\r\n383\r\n386\r\n389\r\nSilas, Alabama\r\n542\r\nSkyline, Alabama\r\n587\r\nSlocomb, Alabama\r\n886\r\nSnead, Alabama\r\n466\r\nSpringville, Alabama\r\n467\r\nStevenson, Alabama\r\n437\r\nSulligent, Alabama\r\n698\r\nSummerdale, Alabama\r\n989\r\nSurfside, Alabama\r\n525\r\nSweetwater, Alabama\r\n994\r\nTallassee, Alabama\r\n283\r\nThomaston, Alabama\r\n627\r\nThomasville, Alabama\r\n636\r\nThorsby, Alabama\r\n646\r\nTown Creek, Alabama\r\n685\r\nTroy, Alabama\r\n566\r\n670\r\nTrussville, Alabama\r\n655\r\nTuscaloosa, Alabama\r\n554\r\n339\r\n345\r\n348\r\n349\r\n391\r\n750\r\n752\r\n758\r\n759\r\n799\r\n394\r\n507\r\n550\r\n553\r\n556\r\nTuskegee, Alabama\r\n724\r\n727\r\nUnion Springs, Alabama\r\n738\r\nUnion Grove, Alabama\r\n753\r\nUniontown, Alabama\r\n628\r\nUriah, Alabama\r\n862\r\nValleyhead, Alabama\r\n635\r\nVernon, Alabama\r\n695\r\nVeto, Alabama\r\n769\r\nVincent, Alabama\r\n672\r\nVredenburg, Alabama\r\n337\r\nWest Blocton, Alabama\r\n938\r\nWadley, Alabama\r\n395\r\nWalnut Grove, Alabama\r\n589\r\nWarrior, Alabama\r\n590\r\n647\r\nWest Point, Alabama\r\n642\r\n644\r\nWetumpka, Alabama\r\n514\r\n567\r\nWhorton, Alabama\r\n475\r\nWicksburg, Alabama\r\n692\r\nWinfield, Alabama\r\n487\r\nWing, Alabama\r\n572\r\nWoodland, Alabama\r\n449\r\nYork, Alabama\r\n392\r\n\u00035Unknown prefix code (205) - Alabama\r\n"
  },
  {
    "path": "install/regions/regions.206",
    "content": "Aberdeen, Washington\r\n532\r\n533\r\n580\r\n590\r\nAcme, Washington\r\n595\r\nAlger, Washington\r\n724\r\nAmboy, Washington\r\n247\r\nAnacortes, Washington\r\n293\r\n299\r\nBainbridge Island, Washington\r\n780\r\n842\r\nBald Hills, Washington\r\n894\r\nBeaver, Washington\r\n327\r\nBelfair, Washington\r\n275\r\nBellevue, Washington\r\n450\r\n451\r\n453\r\n454\r\n455\r\n462\r\n562\r\n637\r\n641\r\n643\r\n644\r\n646\r\n649\r\n704\r\n746\r\n747\r\n865\r\n957\r\nBellingham, Washington\r\n647\r\n650\r\n671\r\n676\r\n715\r\n733\r\n734\r\n738\r\n739\r\n758\r\n961\r\nBig Lake, Washington\r\n422\r\nBlack Diamond, Washington\r\n886\r\nBlaine, Washington\r\n310\r\n319\r\n332\r\nBlakely Island, Washington\r\n375\r\nBothell, Washington\r\n481\r\n483\r\n485\r\n486\r\n487\r\n488\r\n489\r\nBremerton, Washington\r\n373\r\n377\r\n405\r\n478\r\n479\r\n674\r\n731\r\n830\r\n981\r\nBuckley, Washington\r\n829\r\nBurlington, Washington\r\n755\r\n757\r\nCamas, Washington\r\n834\r\n837\r\nCarnation, Washington\r\n333\r\nCathlamet, Washington\r\n795\r\nCentralia, Washington\r\n330\r\n736\r\nChehalis, Washington\r\n269\r\nChinook, Washington\r\n777\r\nClallam Bay, Washington\r\n963\r\nClearwater, Washington\r\n962\r\nCopalis, Washington\r\n289\r\nCrystal Mountain, Washington\r\n663\r\nCuster, Washington\r\n366\r\nDarrington, Washington\r\n436\r\nDes Moines, Washington\r\n824\r\n870\r\n878\r\n941\r\n946\r\nDewatto, Washington\r\n372\r\nDuvall, Washington\r\n788\r\nEastsound, Washington\r\n376\r\nEatonville, Washington\r\n832\r\nEdison, Washington\r\n766\r\nElma, Washington\r\n470\r\n482\r\nEnumclaw, Washington\r\n825\r\nFerndale, Washington\r\n384\r\nForks, Washington\r\n374\r\nFriday Harbor, Washington\r\n317\r\n378\r\nGlenoma, Washington\r\n498\r\nGranite Falls, Washington\r\n691\r\nHalls Lake, Washington\r\n640\r\n670\r\n672\r\n742\r\n743\r\n744\r\n745\r\n771\r\n774\r\n775\r\n776\r\n778\r\nHat Island, Washington\r\n444\r\nHoodsport, Washington\r\n877\r\nIssaquah, Washington\r\n557\r\n391\r\n392\r\nKalama, Washington\r\n673\r\nKapowsin, Washington\r\n879\r\nKelso, Washington\r\n749\r\nKeyport Torpedo Station, Washington\r\n396\r\nKingston, Washington\r\n297\r\nKirkland, Washington\r\n556\r\n558\r\n703\r\n803\r\n814\r\n899\r\n936\r\n820\r\n821\r\n822\r\n823\r\n827\r\n828\r\n867\r\n869\r\n880\r\n881\r\n882\r\n889\r\nLa Conner, Washington\r\n466\r\nLacey, Washington\r\n438\r\n459\r\nLake Stevens, Washington\r\n334\r\nLaurel, Washington\r\n398\r\nLebam, Washington\r\n934\r\nLong Beach, Washington\r\n642\r\nLongview, Washington\r\n423\r\n425\r\n577\r\n578\r\n636\r\nLopez Island, Washington\r\n468\r\nLynden, Washington\r\n354\r\nManor Way, Washington\r\n787\r\nMaple Falls, Washington\r\n599\r\nMaple Valley, Washington\r\n432\r\nMaple Valley, Washington\r\n413\r\nMarblemount, Washington\r\n873\r\nMarysville, Washington\r\n651\r\n652\r\n653\r\n658\r\n659\r\nMccleary, Washington\r\n495\r\nMineral, Washington\r\n492\r\nMonroe, Washington\r\n794\r\nMount Vernon, Washington\r\n336\r\n424\r\nNaselle, Washington\r\n484\r\nNeah Bay, Washington\r\n645\r\nNorth Bend, Washington\r\n831\r\n888\r\nOak Harbor, Washington\r\n675\r\n679\r\nOcean Park, Washington\r\n665\r\nOcosta, Washington\r\n648\r\nOlympia, Washington\r\n407\r\n493\r\n534\r\n664\r\n666\r\n705\r\n902\r\n352\r\n357\r\n456\r\n491\r\n586\r\n741\r\n753\r\n754\r\n786\r\n791\r\n866\r\n943\r\n951\r\nOnalaska, Washington\r\n978\r\nOrting, Washington\r\n893\r\nPacific Beach, Washington\r\n276\r\nPackwood, Washington\r\n494\r\nPort Angeles, Washington\r\n417\r\n452\r\n457\r\n928\r\nPort Ludlow, Washington\r\n437\r\nPort Orchard, Washington\r\n769\r\n871\r\n876\r\n895\r\nPort Townsend, Washington\r\n301\r\n379\r\n385\r\nPoulsbo, Washington\r\n315\r\n697\r\nPuget Island, Washington\r\n849\r\nQuilcene, Washington\r\n765\r\nRainier, Washington\r\n446\r\nRandle, Washington\r\n497\r\nRedmond, Washington\r\n861\r\n883\r\n885\r\nRichmond Beach, Washington\r\n542\r\n546\r\nRochester, Washington\r\n273\r\nSalkum, Washington\r\n985\r\nSammamish, Washington\r\n836\r\n868\r\nSeattle, Washington\r\n217\r\n220\r\n230\r\n223\r\n224\r\n232\r\n233\r\n236\r\n241\r\n242\r\n244\r\n246\r\n248\r\n270\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n292\r\n296\r\n298\r\n314\r\n320\r\n322\r\n323\r\n324\r\n325\r\n326\r\n328\r\n329\r\n340\r\n343\r\n344\r\n345\r\n346\r\n358\r\n361\r\n362\r\n363\r\n364\r\n365\r\n367\r\n368\r\n369\r\n382\r\n386\r\n389\r\n394\r\n399\r\n421\r\n430\r\n431\r\n433\r\n439\r\n440\r\n441\r\n442\r\n443\r\n447\r\n448\r\n449\r\n461\r\n464\r\n467\r\n469\r\n499\r\n504\r\n516\r\n517\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n543\r\n544\r\n545\r\n547\r\n548\r\n553\r\n554\r\n555\r\n559\r\n575\r\n583\r\n585\r\n587\r\n608\r\n609\r\n612\r\n615\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n628\r\n632\r\n633\r\n634\r\n635\r\n654\r\n655\r\n660\r\n662\r\n667\r\n669\r\n680\r\n682\r\n684\r\n685\r\n689\r\n720\r\n721\r\n722\r\n723\r\n725\r\n726\r\n727\r\n728\r\n760\r\n762\r\n763\r\n764\r\n767\r\n768\r\n772\r\n781\r\n782\r\n783\r\n784\r\n789\r\n799\r\n819\r\n860\r\n915\r\n918\r\n919\r\n923\r\n930\r\n932\r\n933\r\n935\r\n937\r\n938\r\n940\r\n947\r\n948\r\n949\r\n953\r\n954\r\n955\r\n956\r\n960\r\n969\r\n972\r\n976\r\n977\r\n979\r\n982\r\n986\r\n989\r\n991\r\n993\r\n994\r\n995\r\n996\r\n997\r\n998\r\n999\r\nSedro Woolley, Washington\r\n855\r\n429\r\nSequim, Washington\r\n681\r\nShelton, Washington\r\n401\r\n490\r\n426\r\n427\r\nSherwood, Washington\r\n688\r\nSilver Lake, Washington\r\n337\r\n338\r\nSilver Lake, Washington\r\n316\r\nSilverdale, Washington\r\n613\r\n698\r\nSnohomish, Washington\r\n563\r\n568\r\n668\r\nSnoqualmie Pass, Washington\r\n434\r\nSouth Whidbey, Washington\r\n331\r\n341\r\n579\r\n729\r\n730\r\nSouth Prairie, Washington\r\n897\r\nSouth Whidbey Island, Washington\r\n221\r\n321\r\nStandwood/Camano Island, Washington\r\n387\r\nSultan\u00031/\u00032Gold Bar\u00031/\u00032Index, Washington\r\n793\r\nSuquamish, Washington\r\n598\r\nTenino, Washington\r\n264\r\nToledo, Washington\r\n864\r\nTukwila, Washington\r\n243\r\nUnion, Washington\r\n898\r\nVader, Washington\r\n295\r\nVancouver, Washington\r\n253\r\n256\r\n574\r\n690\r\n694\r\n695\r\n696\r\n699\r\n750\r\n892\r\n901\r\n944\r\nVashon, Washington\r\n463\r\nVashon Island, Washington\r\n465\r\n567\r\nWestport, Washington\r\n268\r\nWhidbey Island Nas, Washington\r\n257\r\nWinlock, Washington\r\n785\r\nYelm, Washington\r\n458\r\n\u00035Unknown prefix code (206) - Washington\r\n"
  },
  {
    "path": "install/regions/regions.207",
    "content": "Acton, Maine\r\n477\r\nAlbion, Maine\r\n437\r\nAlton, Maine\r\n394\r\nAndover, Maine\r\n392\r\nAshland, Maine\r\n435\r\nAthens, Maine\r\n654\r\nAugusta, Maine\r\n242\r\n287\r\n289\r\n441\r\n557\r\n621\r\n622\r\n623\r\n624\r\n626\r\nAurora, Maine\r\n584\r\nBangor, Maine\r\n561\r\n745\r\n941\r\n942\r\n944\r\n945\r\n947\r\n989\r\n990\r\nBar Harbor, Maine\r\n288\r\nBar Mills, Maine\r\n727\r\n929\r\nBath, Maine\r\n371\r\n389\r\n442\r\n443\r\nBeddington, Maine\r\n638\r\nBelfast, Maine\r\n338\r\nBelgrade, Maine\r\n495\r\nBerwick, Maine\r\n698\r\nBethel, Maine\r\n824\r\nBiddeford, Maine\r\n281\r\n282\r\n283\r\n284\r\n286\r\n468\r\nBigelow, Maine\r\n237\r\nBingham, Maine\r\n672\r\nBlue Hill, Maine\r\n374\r\nBoothbay Harbour, Maine\r\n633\r\nBowdoinham, Maine\r\n666\r\nBradford, Maine\r\n327\r\nBremen, Maine\r\n529\r\nBridgton, Maine\r\n647\r\nBrooks, Maine\r\n722\r\nBrownville, Maine\r\n965\r\nBrunswick, Maine\r\n720\r\n721\r\n725\r\n729\r\n921\r\nBryant Pond, Maine\r\n665\r\nBuckfield, Maine\r\n336\r\nBucksport, Maine\r\n469\r\nCalais, Maine\r\n454\r\nCamden, Maine\r\n236\r\nCanton, Maine\r\n597\r\nCaribou, Maine\r\n492\r\n493\r\n496\r\n498\r\nCarrabaset, Maine\r\n235\r\nCasco, Maine\r\n627\r\nCastine, Maine\r\n326\r\nChina, Maine\r\n968\r\nClinton, Maine\r\n426\r\nCoburngore, Maine\r\n297\r\nColumbia, Maine\r\n483\r\nCorinna, Maine\r\n278\r\nCorinth, Maine\r\n285\r\nCornish, Maine\r\n625\r\nCumberland, Maine\r\n829\r\nDamariscta, Maine\r\n563\r\nDanforth, Maine\r\n448\r\nDark Harbor, Maine\r\n734\r\nDeer Isle, Maine\r\n348\r\n367\r\nDenmark, Maine\r\n452\r\nDexter, Maine\r\n924\r\nDixfield, Maine\r\n562\r\nDover Foxcraft, Maine\r\n564\r\nEast Vassalbo, Maine\r\n923\r\nEagle Lake, Maine\r\n444\r\nEaston, Maine\r\n488\r\nEastport, Maine\r\n853\r\nEddington, Maine\r\n843\r\nEliot, Maine\r\n748\r\nEllsworth, Maine\r\n266\r\n460\r\n667\r\nEmbdenlake, Maine\r\n566\r\nEmillinckt, Maine\r\n746\r\nEtna, Maine\r\n269\r\nExeter, Maine\r\n379\r\nFairfield, Maine\r\n453\r\nFarmington, Maine\r\n778\r\nFort Kent, Maine\r\n834\r\nFranklin, Maine\r\n565\r\nFreedom, Maine\r\n382\r\nFreeport, Maine\r\n865\r\nFrenchboro, Maine\r\n334\r\nFrenchville, Maine\r\n543\r\nFryeburg, Maine\r\n935\r\nFort Fairfield, Maine\r\n472\r\n473\r\n476\r\nGardiner, Maine\r\n582\r\n588\r\nGoodwinsmill, Maine\r\n499\r\nGorham, Maine\r\n839\r\nGrand Isle, Maine\r\n895\r\nGray, Maine\r\n657\r\nGreene, Maine\r\n946\r\nGreenville, Maine\r\n695\r\nGuilford, Maine\r\n876\r\nHampden, Maine\r\n862\r\nHarmony, Maine\r\n683\r\nHarpswell, Maine\r\n833\r\nHarrison, Maine\r\n583\r\nHartland, Maine\r\n938\r\nHebron, Maine\r\n966\r\nHermon, Maine\r\n848\r\nHoulton, Maine\r\n532\r\n538\r\nIsland Falls, Maine\r\n463\r\nIsleauhaut, Maine\r\n335\r\nJackman, Maine\r\n668\r\nJonesboro, Maine\r\n434\r\nJonesport, Maine\r\n497\r\nKennebunkport, Maine\r\n967\r\nKennebunk, Maine\r\n985\r\nKingfield, Maine\r\n265\r\nKingman, Maine\r\n765\r\nKittery, Maine\r\n438\r\n439\r\n475\r\nLebanon, Maine\r\n457\r\nLee, Maine\r\n738\r\nLeeds, Maine\r\n524\r\nLevant, Maine\r\n884\r\nLewiston, Maine\r\n753\r\n754\r\n777\r\n782\r\n783\r\n784\r\n786\r\n795\r\nLiberty, Maine\r\n589\r\nLimerick, Maine\r\n793\r\nLimestone, Maine\r\n325\r\n328\r\n999\r\nLimington, Maine\r\n637\r\nLincoln, Maine\r\n794\r\nLincolnville, Maine\r\n763\r\nLisbon Falls, Maine\r\n353\r\nLitchfield, Maine\r\n268\r\nLivermore Falls, Maine\r\n897\r\nLincolnville Beach, Maine\r\n789\r\nLockemills, Maine\r\n875\r\nLovell, Maine\r\n925\r\nLubec, Maine\r\n733\r\nMachias, Maine\r\n255\r\n259\r\nMadawaska, Maine\r\n728\r\nMadison, Maine\r\n696\r\nManchester, Maine\r\n555\r\nMars Hill, Maine\r\n425\r\n429\r\nMatinicus, Maine\r\n366\r\nMattawamkg, Maine\r\n736\r\nMechanicfl, Maine\r\n345\r\n346\r\nMercer, Maine\r\n587\r\nMilbridge, Maine\r\n546\r\nMillinockt, Maine\r\n723\r\nMilo, Maine\r\n943\r\nMonmouth, Maine\r\n933\r\nMonroe, Maine\r\n525\r\nMonson, Maine\r\n997\r\nMoosehorn, Maine\r\n243\r\nMorrill, Maine\r\n342\r\nMount Vernon, Maine\r\n293\r\nNaples, Maine\r\n693\r\nNew Harbor, Maine\r\n677\r\nNew Sweden, Maine\r\n896\r\nNewburgh, Maine\r\n234\r\nNewgloster, Maine\r\n926\r\nNewport, Maine\r\n368\r\nNew Vineyard, Maine\r\n652\r\nNorth Berwick, Maine\r\n676\r\nNorth Lovell, Maine\r\n928\r\nNorth New Portland, Maine\r\n628\r\nNorth Norway, Maine\r\n527\r\nNortheast Harbor, Maine\r\n276\r\nNorth Fryeburg, Maine\r\n697\r\nNorrdgewck, Maine\r\n634\r\nNorthanson, Maine\r\n635\r\nNorway, Maine\r\n461\r\n743\r\nNorth Whitefield, Maine\r\n549\r\nOakland, Maine\r\n465\r\nOld Town, Maine\r\n827\r\nOldorch Beach, Maine\r\n934\r\nOrono, Maine\r\n581\r\n866\r\nOrrington, Maine\r\n825\r\nOtis, Maine\r\n537\r\nOxford, Maine\r\n539\r\nPalermo, Maine\r\n993\r\nPatten, Maine\r\n528\r\nPembroke, Maine\r\n726\r\nPhillips, Maine\r\n639\r\nPittsfield, Maine\r\n487\r\nPlymouth, Maine\r\n257\r\nPoland, Maine\r\n998\r\nPortland, Maine\r\n232\r\n233\r\n758\r\n759\r\n761\r\n766\r\n767\r\n770\r\n772\r\n773\r\n774\r\n775\r\n776\r\n780\r\n781\r\n791\r\n792\r\n797\r\n799\r\n821\r\n822\r\n823\r\n828\r\n870\r\n871\r\n874\r\n878\r\n879\r\n955\r\n976\r\nPownal, Maine\r\n688\r\nPresque Is, Maine\r\n762\r\n764\r\n768\r\n769\r\nPrinceton, Maine\r\n796\r\nRangeley, Maine\r\n864\r\nRaymond, Maine\r\n655\r\nReadfield, Maine\r\n685\r\nRichmond, Maine\r\n737\r\nRockland, Maine\r\n594\r\n596\r\nRockwood, Maine\r\n534\r\nRome, Maine\r\n397\r\nRoxbury Pond, Maine\r\n545\r\nRumford, Maine\r\n364\r\n369\r\nSabattus, Maine\r\n375\r\nSalem, Maine\r\n678\r\nSanford, Maine\r\n324\r\n490\r\n636\r\nScarborough, Maine\r\n883\r\n885\r\nSearsport, Maine\r\n548\r\nSebago, Maine\r\n787\r\nSedgwick, Maine\r\n359\r\nSheepscot, Maine\r\n586\r\nSherman Mills, Maine\r\n365\r\nSidney, Maine\r\n547\r\nSkowhegan, Maine\r\n474\r\nSmithfield, Maine\r\n362\r\nSmyrna Mills, Maine\r\n757\r\nSouth Berwick, Maine\r\n384\r\nSouth Bristol, Maine\r\n644\r\nSouth Lebanon, Maine\r\n339\r\nSolon, Maine\r\n643\r\nSouth China, Maine\r\n445\r\nSouthwest Harbor, Maine\r\n244\r\nSaint Francis, Maine\r\n398\r\nStandish, Maine\r\n642\r\nSteepfalls, Maine\r\n675\r\nStetson, Maine\r\n296\r\nStockton Spring, Maine\r\n567\r\nStratton, Maine\r\n246\r\nStrong, Maine\r\n684\r\nSullivan, Maine\r\n422\r\nSumner, Maine\r\n388\r\nSwans Is, Maine\r\n526\r\nTenants Harbor, Maine\r\n372\r\nThe Forks, Maine\r\n663\r\nThomaston, Maine\r\n354\r\nThorndike, Maine\r\n568\r\nTurner, Maine\r\n224\r\n225\r\nUnion, Maine\r\n785\r\nUnity, Maine\r\n948\r\nUpton, Maine\r\n533\r\nVan Buren, Maine\r\n868\r\nVanceboro, Maine\r\n788\r\nVinalhaven, Maine\r\n863\r\n867\r\nWest Enfield, Maine\r\n732\r\nWest Gardiner, Maine\r\n724\r\nWest Lebanon, Maine\r\n658\r\nWaldoboro, Maine\r\n832\r\nWarren, Maine\r\n273\r\nWashburn, Maine\r\n455\r\nWashington, Maine\r\n845\r\nWaterboro, Maine\r\n247\r\nWaterville, Maine\r\n872\r\n873\r\n877\r\nWeld, Maine\r\n585\r\nWells, Maine\r\n646\r\nWest Gray, Maine\r\n428\r\nWest Paris, Maine\r\n674\r\nWest Bethel, Maine\r\n836\r\nWestbrook, Maine\r\n854\r\n856\r\nWest Ripley, Maine\r\n277\r\nWilson Mills, Maine\r\n486\r\nWilton, Maine\r\n645\r\nWindham, Maine\r\n892\r\n893\r\nWinter Harbor, Maine\r\n963\r\nWinterport, Maine\r\n223\r\nWinthrop, Maine\r\n377\r\n395\r\nWiscasset, Maine\r\n882\r\nWoodland, Maine\r\n427\r\nWytopitlck, Maine\r\n456\r\nYarmouth, Maine\r\n846\r\nYork, Maine\r\n361\r\n363\r\n\u00035Unknown prefix code (207) - Maine\r\n"
  },
  {
    "path": "install/regions/regions.208",
    "content": "Aberdeen, Idaho\r\n397\r\nAlbeni, Idaho\r\n437\r\nAlbion, Idaho\r\n673\r\nAlmo, Idaho\r\n824\r\nAlpine, Idaho\r\n564\r\nAmerican Falls, Idaho\r\n220\r\n226\r\n949\r\nArbon, Idaho\r\n335\r\nArco, Idaho\r\n527\r\n554\r\n767\r\nAshton, Idaho\r\n652\r\nAtlanta, Idaho\r\n864\r\nBancroft, Idaho\r\n648\r\nBayview, Idaho\r\n683\r\nBlackfoot, Idaho\r\n680\r\n684\r\n785\r\n980\r\nBliss, Idaho\r\n352\r\nBluebell, Idaho\r\n274\r\nBoise, Idaho\r\n322\r\n323\r\n327\r\n332\r\n333\r\n334\r\n336\r\n338\r\n340\r\n342\r\n343\r\n344\r\n345\r\n348\r\n362\r\n364\r\n368\r\n373\r\n375\r\n376\r\n377\r\n378\r\n383\r\n384\r\n385\r\n386\r\n387\r\n389\r\n393\r\n396\r\n853\r\n860\r\n866\r\n867\r\n939\r\nBoiseriver, Idaho\r\n653\r\nBonnersfry, Idaho\r\n267\r\nBovill, Idaho\r\n826\r\nBruneau, Idaho\r\n845\r\nBuhl, Idaho\r\n543\r\nBurley, Idaho\r\n654\r\n670\r\n677\r\n678\r\n940\r\nCaldwell, Idaho\r\n454\r\n455\r\n459\r\nCambridge, Idaho\r\n257\r\nCarey, Idaho\r\n823\r\nCascade, Idaho\r\n382\r\nCastleford, Idaho\r\n537\r\nChallis, Idaho\r\n879\r\nClark Fork, Idaho\r\n266\r\nClayton, Idaho\r\n838\r\nCoeurdalen, Idaho\r\n661\r\n664\r\n666\r\n667\r\n761\r\n765\r\n769\r\nCora, Idaho\r\n668\r\nCottonwood, Idaho\r\n962\r\nCouncil, Idaho\r\n253\r\nCraigmont, Idaho\r\n924\r\nCuprum, Idaho\r\n258\r\nDeary, Idaho\r\n877\r\nDietrich, Idaho\r\n544\r\nDonnelly, Idaho\r\n325\r\nDowney, Idaho\r\n897\r\nDriggs, Idaho\r\n354\r\n456\r\n787\r\nDubois, Idaho\r\n374\r\nEden, Idaho\r\n825\r\n829\r\nElba, Idaho\r\n638\r\nElk Bend, Idaho\r\n894\r\nElk City, Idaho\r\n842\r\nEmmett, Idaho\r\n365\r\n369\r\nEvergreen, Idaho\r\n268\r\nFairfield, Idaho\r\n764\r\nFiler, Idaho\r\n326\r\nFreedom, Idaho\r\n873\r\nFruitland, Idaho\r\n452\r\nGarden Valley, Idaho\r\n462\r\nGenesee, Idaho\r\n285\r\nGlenns Fry, Idaho\r\n366\r\nGooding, Idaho\r\n934\r\nGrace, Idaho\r\n425\r\n427\r\nGrand View, Idaho\r\n834\r\nGrangevl, Idaho\r\n983\r\nGrasmerrdl, Idaho\r\n759\r\nHagerman, Idaho\r\n837\r\nHailey, Idaho\r\n788\r\nHamer, Idaho\r\n662\r\nHarrison, Idaho\r\n689\r\nHaydenlake, Idaho\r\n762\r\n772\r\nHolbrook, Idaho\r\n698\r\nHollister, Idaho\r\n655\r\nHomedale, Idaho\r\n337\r\nHope, Idaho\r\n264\r\nHorseshbnd, Idaho\r\n793\r\nIdaho City, Idaho\r\n392\r\nIdaho Falls, Idaho\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n528\r\n529\r\n533\r\n534\r\n535\r\n979\r\nIndian Valley, Idaho\r\n256\r\nIrwin, Idaho\r\n483\r\nIsland Park, Idaho\r\n558\r\nJerome, Idaho\r\n324\r\nJuliaetta, Idaho\r\n276\r\nKamiah, Idaho\r\n935\r\nKellogg, Idaho\r\n682\r\n783\r\n784\r\n786\r\nKendrick, Idaho\r\n289\r\nKetchum, Idaho\r\n622\r\n726\r\n727\r\n981\r\nKilgore, Idaho\r\n778\r\nKimberly, Idaho\r\n420\r\n423\r\n930\r\nKooskia, Idaho\r\n926\r\nKuna, Idaho\r\n922\r\nLakeview, Idaho\r\n222\r\nLapwai, Idaho\r\n843\r\nLava Hot Springs, Idaho\r\n776\r\nLeadore, Idaho\r\n768\r\nLenore, Idaho\r\n836\r\nLeon, Idaho\r\n224\r\nLewiston, Idaho\r\n743\r\n746\r\n799\r\nLowman, Idaho\r\n259\r\nMackay, Idaho\r\n588\r\nMalad, Idaho\r\n766\r\nMalta, Idaho\r\n645\r\nMarsing, Idaho\r\n896\r\nMay, Idaho\r\n876\r\nMc Call, Idaho\r\n634\r\nMc Cammon, Idaho\r\n254\r\nMelba, Idaho\r\n495\r\nMeridian, Idaho\r\n887\r\n888\r\n890\r\nMiddleton, Idaho\r\n585\r\nMidvale, Idaho\r\n355\r\n555\r\nMinidoka, Idaho\r\n531\r\nMonteview, Idaho\r\n657\r\nMontpelier, Idaho\r\n847\r\nMoscow, Idaho\r\n883\r\n885\r\nMoscow, Idaho\r\n882\r\nMt Home, Idaho\r\n587\r\n590\r\n598\r\n599\r\n828\r\n832\r\nMullan, Idaho\r\n744\r\nMurtaugh, Idaho\r\n432\r\nNampa, Idaho\r\n249\r\n250\r\n463\r\n465\r\n466\r\n467\r\n880\r\n899\r\nNew Plymouth, Idaho\r\n278\r\nNewmeadows, Idaho\r\n347\r\nNezperce, Idaho\r\n937\r\nNorland, Idaho\r\n532\r\nNu Acres, Idaho\r\n674\r\nOakley, Idaho\r\n862\r\nOrofino, Idaho\r\n476\r\nParis, Idaho\r\n945\r\nParma, Idaho\r\n722\r\nPaul, Idaho\r\n438\r\nPayette, Idaho\r\n642\r\n739\r\n740\r\nPeck, Idaho\r\n486\r\nPierce, Idaho\r\n464\r\nPlmr Wrly, Idaho\r\n686\r\nPocatello, Idaho\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n241\r\n242\r\n775\r\n989\r\nPost Falls, Idaho\r\n773\r\n777\r\nPotlatch, Idaho\r\n875\r\nPowell, Idaho\r\n942\r\nPrairie, Idaho\r\n868\r\nPreston, Idaho\r\n646\r\n747\r\n852\r\nPriest Riv, Idaho\r\n448\r\nPriestlake, Idaho\r\n443\r\nRaft River, Idaho\r\n349\r\nRathdrum, Idaho\r\n687\r\nRexburg, Idaho\r\n351\r\n356\r\n359\r\n969\r\nRichfield, Idaho\r\n487\r\nRigby, Idaho\r\n745\r\n754\r\nRiggins, Idaho\r\n628\r\nRirie, Idaho\r\n538\r\nRoberts, Idaho\r\n228\r\nRock Creek, Idaho\r\n273\r\nRockland, Idaho\r\n548\r\nRupert, Idaho\r\n434\r\n436\r\nSalmon, Idaho\r\n756\r\n865\r\nSandpoint, Idaho\r\n263\r\n265\r\nSetters, Idaho\r\n231\r\nShelley, Idaho\r\n346\r\n357\r\nShoshone, Idaho\r\n886\r\nShoup, Idaho\r\n394\r\nSoda Springs, Idaho\r\n547\r\nSouth Mt, Idaho\r\n583\r\nSpiritlake, Idaho\r\n623\r\nSpringfld, Idaho\r\n328\r\nSt Anthony, Idaho\r\n458\r\n624\r\nSt Maries, Idaho\r\n245\r\nStanley, Idaho\r\n774\r\nStar, Idaho\r\n286\r\nSweet, Idaho\r\n584\r\nTerreton, Idaho\r\n663\r\nThreecreek, Idaho\r\n857\r\nTipanuk, Idaho\r\n796\r\nTroy, Idaho\r\n835\r\nTwin Falls, Idaho\r\n731\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\nTygee Valley, Idaho\r\n225\r\nWallace, Idaho\r\n556\r\n752\r\n753\r\nWayan, Idaho\r\n574\r\nWeippe, Idaho\r\n435\r\nWeiser, Idaho\r\n549\r\nWellesley, Idaho\r\n858\r\nWendell, Idaho\r\n536\r\nWhite Bird, Idaho\r\n839\r\nWilder, Idaho\r\n482\r\n\u00035Unknown prefix code (208) - Idaho\r\n"
  },
  {
    "path": "install/regions/regions.209",
    "content": "Alpaugh, California\r\n949\r\nAngel's Camp, California\r\n728\r\n736\r\n753\r\n795\r\nAtwater, California\r\n357\r\n358\r\nAuberry, California\r\n855\r\nAvenal, California\r\n386\r\nBadger, California\r\n337\r\nBig Creek, California\r\n893\r\nBurrel, California\r\n866\r\n884\r\nCaruthers, California\r\n864\r\nCathy's Valley, California\r\n374\r\nCeres, California\r\n531\r\n537\r\n538\r\nChowchilla, California\r\n665\r\nClements, California\r\n759\r\nClovis, California\r\n297\r\n298\r\n299\r\n322\r\n323\r\nCoalinga, California\r\n935\r\nCoarsegold, California\r\n642\r\n658\r\n683\r\nCopperoplis, California\r\n785\r\nCorcoran, California\r\n992\r\nCoulterville, California\r\n878\r\nCrow's Landing, California\r\n837\r\nDel Rey, California\r\n888\r\nDinuba, California\r\n528\r\n591\r\n595\r\nDos Palos, California\r\n364\r\n387\r\n392\r\nDucor, California\r\n534\r\nDunlap, California\r\n338\r\nEscalon, California\r\n838\r\nExeter, California\r\n592\r\n594\r\nFarmington, California\r\n886\r\nFirebaugh, California\r\n659\r\nFowler, California\r\n834\r\nFresno, California\r\n221\r\n222\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n233\r\n237\r\n241\r\n244\r\n246\r\n247\r\n248\r\n251\r\n252\r\n255\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n268\r\n269\r\n271\r\n275\r\n276\r\n277\r\n278\r\n279\r\n281\r\n283\r\n284\r\n285\r\n291\r\n292\r\n294\r\n348\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n438\r\n439\r\n441\r\n442\r\n443\r\n445\r\n447\r\n448\r\n449\r\n452\r\n453\r\n454\r\n456\r\n458\r\n485\r\n486\r\n487\r\n488\r\n495\r\n496\r\n497\r\n498\r\n630\r\n640\r\n764\r\n778\r\n779\r\n971\r\n974\r\n976\r\n977\r\n978\r\n979\r\n981\r\nFriant, California\r\n822\r\nGalt, California\r\n745\r\nGrant Grove, California\r\n335\r\nGroveland, California\r\n962\r\nGustine, California\r\n854\r\nHanford, California\r\n582\r\n583\r\n584\r\n585\r\nHerald, California\r\n748\r\nHornitos, California\r\n376\r\n378\r\nHughson, California\r\n883\r\nHuron, California\r\n945\r\nIone, California\r\n274\r\n469\r\nJackson, California\r\n223\r\nJamestown, California\r\n984\r\nJenny Lind, California\r\n786\r\nKerman, California\r\n843\r\n846\r\nKingsburg, California\r\n897\r\nKirkwood Meadows, California\r\n258\r\nKnight's Ferry, California\r\n881\r\nLaton, California\r\n923\r\nLe Grand, California\r\n389\r\nLemon Cove, California\r\n597\r\nLemoore, California\r\n924\r\n925\r\n997\r\n998\r\nLinden, California\r\n887\r\nLindsay, California\r\n562\r\n568\r\nLivingston, California\r\n394\r\nLockeford, California\r\n727\r\nLodi, California\r\n331\r\n333\r\n334\r\n339\r\n367\r\n368\r\n369\r\nLos Banos, California\r\n826\r\n827\r\nMadera, California\r\n645\r\n661\r\n673\r\n674\r\n675\r\nManteca, California\r\n239\r\n823\r\n824\r\n825\r\n857\r\n858\r\nMariposa, California\r\n742\r\n966\r\nMendota, California\r\n655\r\nMerced, California\r\n340\r\n383\r\n384\r\n385\r\n721\r\n722\r\n723\r\n725\r\n726\r\nMilton, California\r\n899\r\nMiramonte-Pinehurst, California\r\n336\r\nMoccasin, California\r\n989\r\nModesto, California\r\n491\r\n492\r\n520\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n529\r\n541\r\n543\r\n544\r\n549\r\n551\r\n552\r\n558\r\n571\r\n572\r\n573\r\n574\r\n575\r\n576\r\n577\r\n578\r\n579\r\n581\r\n766\r\nMokelumne Hill, California\r\n286\r\nMount Bullion, California\r\n377\r\nNewman, California\r\n862\r\nNorth Fork, California\r\n877\r\nO'Neals, California\r\n868\r\nOakdale, California\r\n569\r\n847\r\n848\r\nOrange Cove, California\r\n626\r\nParlier, California\r\n646\r\nPatterson, California\r\n892\r\n894\r\n895\r\nPinecrest, California\r\n965\r\nPioneer, California\r\n295\r\nPixley, California\r\n757\r\nPlanada, California\r\n382\r\nPlymouth, California\r\n245\r\nPorterville, California\r\n781\r\n782\r\n783\r\n784\r\nRaymond, California\r\n689\r\nReedley, California\r\n637\r\n638\r\nRipon, California\r\n599\r\nRiverbank, California\r\n869\r\nRiverdale, California\r\n867\r\nSalida, California\r\n545\r\nSan Andreas, California\r\n754\r\nSan Joaquin, California\r\n693\r\n698\r\n829\r\nSanger, California\r\n875\r\n876\r\nSelma, California\r\n891\r\n896\r\nSequoia, California\r\n565\r\nShaver, California\r\n841\r\nSnelling, California\r\n563\r\nSonora M, California\r\n536\r\n694\r\nSonora, California\r\n532\r\n533\r\n586\r\nSpringville, California\r\n539\r\n542\r\nSquaw Valley, California\r\n332\r\nStockton, California\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n468\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n478\r\n479\r\n481\r\n482\r\n483\r\n484\r\n540\r\n546\r\n547\r\n660\r\n761\r\n762\r\n765\r\n768\r\n769\r\n931\r\n937\r\n941\r\n942\r\n943\r\n944\r\n946\r\n948\r\n951\r\n952\r\n953\r\n955\r\n956\r\n957\r\n982\r\n983\r\n985\r\n987\r\n988\r\nStratford, California\r\n947\r\nSutter Creek, California\r\n267\r\nTerra Bella, California\r\n535\r\nThornton, California\r\n794\r\nThree Rivers, California\r\n561\r\nTipton, California\r\n752\r\nTivy Valley, California\r\n787\r\nTracy, California\r\n831\r\n832\r\n833\r\n835\r\n836\r\nTulare, California\r\n685\r\n686\r\n687\r\n688\r\nTuolumne, California\r\n928\r\nTurlock, California\r\n632\r\n634\r\n656\r\n664\r\n667\r\n668\r\n669\r\nValley Springs, California\r\n772\r\nVisalia, California\r\n621\r\n625\r\n627\r\n635\r\n636\r\n651\r\n730\r\n731\r\n732\r\n733\r\n734\r\n735\r\n737\r\n738\r\n739\r\n740\r\n747\r\n798\r\nVolcano, California\r\n296\r\nWallace, California\r\n763\r\nWaterford, California\r\n852\r\n853\r\n874\r\nWest Point, California\r\n293\r\nWishon, California\r\n865\r\nWoodlake, California\r\n564\r\nYosemite, California\r\n372\r\n375\r\n379\r\n\u00035Unknown prefix code (209) - California\r\n"
  },
  {
    "path": "install/regions/regions.210",
    "content": "Artesa Wells, Texas\r\n676\r\nAsherton, Texas\r\n468\r\nBabcock, Texas\r\n498\r\n558\r\n561\r\n641\r\n691\r\n694\r\n696\r\n697\r\n699\r\nBalcones, Texas\r\n755\r\n981\r\nBandera, Texas\r\n796\r\nBarksdale, Texas\r\n234\r\nBatesville, Texas\r\n376\r\nBig Wells, Texas\r\n457\r\nBlanco, Texas\r\n833\r\nBoerne, Texas\r\n249\r\n816\r\nBracken, Texas\r\n651\r\nBrackettville, Texas\r\n563\r\nBrownsville, Texas\r\n350\r\n405\r\n504\r\n507\r\n541\r\n542\r\n544\r\n546\r\n548\r\n549\r\n551\r\n570\r\n806\r\n831\r\n982\r\n986\r\nBuena Vista, Texas\r\n627\r\nBulverde, Texas\r\n980\r\n438\r\nCamp Wood, Texas\r\n597\r\nCampbelltn, Texas\r\n579\r\nCarrzo Springs, Texas\r\n876\r\nCastroville, Texas\r\n538\r\nCatarina, Texas\r\n999\r\nCenter Point, Texas\r\n634\r\nCharlotte, Texas\r\n277\r\nChristine, Texas\r\n784\r\nCibolo, Texas\r\n793\r\nComfort, Texas\r\n995\r\nConverse, Texas\r\n492\r\n945\r\nCost, Texas\r\n437\r\nCotulla, Texas\r\n879\r\nCranes Ml, Texas\r\n899\r\n905\r\nCrystal City, Texas\r\n374\r\nCulebra, Texas\r\n509\r\n520\r\n521\r\n522\r\n523\r\n647\r\n680\r\n681\r\n684\r\nDel Rio, Texas\r\n298\r\n313\r\n703\r\n774\r\n775\r\nDevine, Texas\r\n663\r\nDhanis, Texas\r\n363\r\nDilley, Texas\r\n965\r\nDolores, Texas\r\n417\r\n418\r\n419\r\n799\r\nDonna, Texas\r\n464\r\nDoss, Texas\r\n669\r\nEagle Pass, Texas\r\n757\r\n773\r\nEdinburg, Texas\r\n316\r\n318\r\n330\r\n380\r\n381\r\n382\r\n383\r\n605\r\n607\r\n801\r\n802\r\nEl Sauz, Texas\r\n486\r\nElm Creek, Texas\r\n497\r\nElmendorf, Texas\r\n635\r\nElsa\u00031/\u00032Edcouch, Texas\r\n262\r\nEncinal, Texas\r\n948\r\nFalcon Heights, Texas\r\n848\r\nFloresville, Texas\r\n393\r\nFoster, Texas\r\n648\r\nFowlerton, Texas\r\n373\r\nFratt, Texas\r\n590\r\n599\r\n619\r\n637\r\n646\r\n650\r\n654\r\n655\r\n656\r\n657\r\n871\r\n967\r\n653\r\nFredricksburg, Texas\r\n997\r\nFrio Canyon, Texas\r\n232\r\nGarvnstore, Texas\r\n640\r\nGeronimo Creek, Texas\r\n688\r\nGillett, Texas\r\n789\r\nGonzales, Texas\r\n672\r\nGrant Shales, Texas\r\n598\r\nHancock, Texas\r\n906\r\n935\r\nHargill, Texas\r\n845\r\nHarlingen, Texas\r\n202\r\n290\r\n291\r\n407\r\n412\r\n421\r\n423\r\n425\r\n427\r\n428\r\n430\r\n760\r\nHarper, Texas\r\n864\r\nHelotes, Texas\r\n695\r\nHidalgo, Texas\r\n843\r\nHollywood Park, Texas\r\n491\r\nHondo, Texas\r\n426\r\nHunt, Texas\r\n238\r\nIndian Creek, Texas\r\n623\r\nIngram, Texas\r\n367\r\nJarratt, Texas\r\n622\r\nJohnson City, Texas\r\n868\r\nJourdanton, Texas\r\n769\r\nKarnes City, Texas\r\n254\r\n780\r\nKenberg, Texas\r\n336\r\nKenedy, Texas\r\n583\r\nKerrville, Texas\r\n257\r\n739\r\n792\r\n895\r\n896\r\nKingsbury, Texas\r\n639\r\nKnippa, Texas\r\n934\r\nKosciusko, Texas\r\n745\r\nLa Feria, Texas\r\n797\r\nLa Pryor, Texas\r\n365\r\nLackland, Texas\r\n670\r\n671\r\n673\r\n674\r\n675\r\n678\r\nLacoste, Texas\r\n762\r\nLaredo, Texas\r\n717\r\n718\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n744\r\n763\r\n791\r\nLasara, Texas\r\n612\r\n642\r\nLavernia, Texas\r\n779\r\nLeesville, Texas\r\n424\r\nLeon Springs, Texas\r\n698\r\nLos Fresnos, Texas\r\n233\r\nLuling, Texas\r\n875\r\nLyford, Texas\r\n347\r\nLytle, Texas\r\n709\r\nLytle Em, Texas\r\n772\r\nMarble Falls, Texas\r\n693\r\nMarion, Texas\r\n420\r\nMarion Em, Texas\r\n914\r\nMartinez, Texas\r\n661\r\n662\r\n666\r\nMcAllen, Texas\r\n618\r\n630\r\n631\r\n632\r\n633\r\n638\r\n682\r\n686\r\n687\r\n917\r\n971\r\n972\r\nMcCook, Texas\r\n842\r\nMedical Center, Texas\r\n513\r\n567\r\n593\r\n613\r\n614\r\n615\r\n616\r\n617\r\n692\r\n989\r\nMedina, Texas\r\n589\r\nMedina Lake, Texas\r\n751\r\nMercedes, Texas\r\n514\r\n565\r\nMillett, Texas\r\n378\r\nMission, Texas\r\n519\r\n580\r\n581\r\n585\r\nMontgomery, Texas\r\n677\r\nMt Home, Texas\r\n866\r\nNewbrnfels, Texas\r\n608\r\n620\r\n625\r\n629\r\nNixon, Texas\r\n582\r\nOak Island, Texas\r\n624\r\nPalo Alto, Texas\r\n628\r\nPearsall, Texas\r\n317\r\n334\r\nPharr\u00031/\u00032San Juan\u00031/\u00032Alamo, Texas\r\n702\r\n781\r\n783\r\n787\r\nPipe Creek, Texas\r\n535\r\nPleasanton, Texas\r\n315\r\n569\r\nPort Isabel, Texas\r\n761\r\n943\r\nPoteet, Texas\r\n742\r\nPoth, Texas\r\n484\r\nPotranco, Texas\r\n679\r\nPort Mansfield, Texas\r\n944\r\nRaymondville, Texas\r\n689\r\nRio Hondo, Texas\r\n748\r\nRio Grand City, Texas\r\n487\r\n500\r\n716\r\nRock Spring, Texas\r\n683\r\nRocky Creek, Texas\r\n839\r\nRoma, Texas\r\n849\r\nRound Mt, Texas\r\n825\r\nRunge, Texas\r\n239\r\nSabina, Texas\r\n537\r\nSabinal, Texas\r\n988\r\nSan Benito, Texas\r\n361\r\n399\r\nSan Isidro, Texas\r\n481\r\nSan Miguel, Texas\r\n466\r\nSan Antonio, Texas\r\n203\r\n207\r\n208\r\n212\r\n213\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n235\r\n240\r\n246\r\n260\r\n270\r\n271\r\n283\r\n299\r\n304\r\n308\r\n333\r\n337\r\n340\r\n341\r\n342\r\n344\r\n349\r\n351\r\n359\r\n366\r\n377\r\n410\r\n414\r\n415\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n470\r\n506\r\n508\r\n518\r\n524\r\n525\r\n530\r\n531\r\n532\r\n533\r\n534\r\n536\r\n554\r\n603\r\n606\r\n659\r\n690\r\n704\r\n705\r\n714\r\n715\r\n720\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n803\r\n804\r\n805\r\n807\r\n820\r\n821\r\n822\r\n824\r\n826\r\n827\r\n828\r\n829\r\n841\r\n844\r\n861\r\n912\r\n916\r\n921\r\n922\r\n923\r\n924\r\n925\r\n927\r\n930\r\n933\r\n951\r\n954\r\n977\r\n978\r\n979\r\nSandy Hills, Texas\r\n621\r\nSan Perlita, Texas\r\n248\r\nSanta Rosa, Texas\r\n636\r\nSattler, Texas\r\n907\r\n964\r\nSaturn, Texas\r\n540\r\nSayers, Texas\r\n649\r\nSeguin, Texas\r\n372\r\n379\r\n401\r\n557\r\nShavano, Texas\r\n408\r\n493\r\nSisterdale, Texas\r\n324\r\nSmiley, Texas\r\n587\r\nSmithson Valley, Texas\r\n885\r\n904\r\nSomerset, Texas\r\n429\r\n701\r\n710\r\nSaint Hedwig, Texas\r\n667\r\nSaint Harold Springs, Texas\r\n947\r\nStillman, Texas\r\n743\r\nStockdale, Texas\r\n996\r\nStonewall, Texas\r\n644\r\nSullivan City, Texas\r\n485\r\nTarpley, Texas\r\n562\r\nThelma, Texas\r\n626\r\nUniversal City, Texas\r\n652\r\n658\r\nUtopia, Texas\r\n966\r\nUvalde, Texas\r\n278\r\n591\r\nVinegarron, Texas\r\n395\r\nWeslaco, Texas\r\n903\r\n961\r\n962\r\n963\r\n968\r\n969\r\n974\r\nWesthoff, Texas\r\n236\r\nWetmore, Texas\r\n402\r\n490\r\n494\r\n496\r\n545\r\nWillow City, Texas\r\n685\r\nZapata, Texas\r\n765\r\n936\r\n\u00035Unknown prefix code (210) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.212",
    "content": "Bronx\u00031/\u00032Manhattan, New York\r\n388\r\nNew York City, New York\r\n436\r\n609\r\n609\r\n950\r\n960\r\n205\r\n206\r\n207\r\n208\r\n210\r\n211\r\n213\r\n214\r\n216\r\n218\r\n219\r\n221\r\n223\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n232\r\n233\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n258\r\n259\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n282\r\n284\r\n285\r\n286\r\n287\r\n290\r\n291\r\n296\r\n297\r\n298\r\n301\r\n302\r\n303\r\n306\r\n307\r\n308\r\n309\r\n310\r\n311\r\n311\r\n311\r\n311\r\n312\r\n313\r\n314\r\n315\r\n317\r\n318\r\n319\r\n321\r\n322\r\n323\r\n326\r\n329\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n340\r\n341\r\n343\r\n344\r\n345\r\n346\r\n347\r\n349\r\n350\r\n351\r\n352\r\n353\r\n354\r\n355\r\n356\r\n357\r\n358\r\n359\r\n361\r\n363\r\n366\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n377\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n387\r\n389\r\n390\r\n391\r\n392\r\n393\r\n394\r\n395\r\n397\r\n398\r\n399\r\n401\r\n404\r\n406\r\n407\r\n408\r\n412\r\n413\r\n414\r\n415\r\n416\r\n417\r\n418\r\n419\r\n420\r\n421\r\n422\r\n424\r\n425\r\n426\r\n428\r\n429\r\n431\r\n432\r\n433\r\n435\r\n437\r\n440\r\n441\r\n442\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n457\r\n458\r\n459\r\n460\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n468\r\n469\r\n470\r\n471\r\n473\r\n474\r\n475\r\n476\r\n477\r\n478\r\n479\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n490\r\n492\r\n493\r\n494\r\n495\r\n502\r\n503\r\n504\r\n505\r\n506\r\n508\r\n509\r\n510\r\n511\r\n511\r\n511\r\n512\r\n513\r\n514\r\n516\r\n520\r\n521\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n529\r\n530\r\n532\r\n533\r\n536\r\n537\r\n541\r\n545\r\n546\r\n551\r\n552\r\n553\r\n554\r\n556\r\n557\r\n558\r\n559\r\n560\r\n561\r\n563\r\n564\r\n565\r\n566\r\n571\r\n572\r\n573\r\n574\r\n575\r\n576\r\n577\r\n578\r\n581\r\n582\r\n586\r\n587\r\n591\r\n592\r\n593\r\n594\r\n596\r\n598\r\n599\r\n602\r\n603\r\n605\r\n607\r\n608\r\n610\r\n612\r\n613\r\n614\r\n616\r\n618\r\n619\r\n620\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n629\r\n630\r\n631\r\n632\r\n633\r\n635\r\n636\r\n637\r\n638\r\n639\r\n640\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n648\r\n649\r\n651\r\n656\r\n657\r\n658\r\n659\r\n661\r\n664\r\n667\r\n668\r\n669\r\n672\r\n673\r\n674\r\n675\r\n676\r\n677\r\n679\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n691\r\n692\r\n693\r\n695\r\n696\r\n697\r\n698\r\n699\r\n701\r\n702\r\n703\r\n704\r\n705\r\n706\r\n707\r\n708\r\n709\r\n712\r\n713\r\n714\r\n715\r\n719\r\n720\r\n725\r\n727\r\n730\r\n732\r\n735\r\n736\r\n741\r\n742\r\n745\r\n746\r\n747\r\n748\r\n750\r\n751\r\n752\r\n753\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n760\r\n764\r\n765\r\n766\r\n767\r\n768\r\n770\r\n773\r\n775\r\n776\r\n777\r\n778\r\n779\r\n780\r\n782\r\n783\r\n785\r\n786\r\n788\r\n789\r\n790\r\n791\r\n793\r\n797\r\n804\r\n806\r\n807\r\n808\r\n809\r\n811\r\n812\r\n813\r\n815\r\n818\r\n819\r\n820\r\n821\r\n825\r\n826\r\n827\r\n830\r\n832\r\n833\r\n836\r\n837\r\n838\r\n839\r\n840\r\n841\r\n845\r\n846\r\n847\r\n848\r\n850\r\n851\r\n852\r\n855\r\n856\r\n858\r\n867\r\n868\r\n869\r\n871\r\n872\r\n878\r\n880\r\n883\r\n886\r\n887\r\n888\r\n889\r\n890\r\n891\r\n898\r\n899\r\n902\r\n903\r\n905\r\n906\r\n907\r\n908\r\n909\r\n912\r\n916\r\n921\r\n922\r\n924\r\n925\r\n929\r\n930\r\n935\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n936\r\n938\r\n940\r\n941\r\n943\r\n944\r\n945\r\n947\r\n949\r\n951\r\n952\r\n953\r\n954\r\n955\r\n956\r\n957\r\n959\r\n961\r\n962\r\n963\r\n964\r\n966\r\n967\r\n968\r\n969\r\n971\r\n972\r\n973\r\n974\r\n975\r\n976\r\n977\r\n978\r\n979\r\n980\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n989\r\n995\r\n997\r\n998\r\n222\r\n241\r\n249\r\n280\r\n288\r\n289\r\n316\r\n327\r\n348\r\n360\r\n362\r\n369\r\n396\r\n410\r\n423\r\n427\r\n439\r\n456\r\n472\r\n496\r\n517\r\n531\r\n534\r\n535\r\n570\r\n580\r\n595\r\n606\r\n628\r\n650\r\n662\r\n663\r\n666\r\n678\r\n717\r\n721\r\n722\r\n724\r\n734\r\n737\r\n744\r\n749\r\n769\r\n771\r\n772\r\n774\r\n787\r\n794\r\n799\r\n831\r\n853\r\n854\r\n860\r\n861\r\n864\r\n865\r\n866\r\n870\r\n873\r\n874\r\n875\r\n876\r\n877\r\n879\r\n932\r\n988\r\n996\r\n999\r\n220\r\n234\r\n281\r\n283\r\n292\r\n293\r\n294\r\n295\r\n299\r\n304\r\n305\r\n328\r\n342\r\n364\r\n365\r\n367\r\n368\r\n378\r\n402\r\n491\r\n518\r\n538\r\n542\r\n544\r\n562\r\n567\r\n568\r\n569\r\n579\r\n583\r\n584\r\n585\r\n588\r\n589\r\n590\r\n617\r\n665\r\n681\r\n690\r\n694\r\n716\r\n731\r\n733\r\n740\r\n781\r\n795\r\n817\r\n842\r\n862\r\n893\r\n901\r\n923\r\n926\r\n927\r\n928\r\n933\r\n939\r\n942\r\n991\r\n992\r\n993\r\n409\r\n430\r\n597\r\n792\r\n822\r\n823\r\n824\r\n828\r\n829\r\n863\r\n892\r\n904\r\n918\r\n931\r\n231\r\n320\r\n324\r\n325\r\n379\r\n405\r\n515\r\n519\r\n543\r\n547\r\n548\r\n549\r\n601\r\n652\r\n653\r\n654\r\n655\r\n671\r\n796\r\n798\r\n881\r\n882\r\n884\r\n885\r\n920\r\n994\r\n\u00035Unknown prefix code (212) - N.Y. City\r\n"
  },
  {
    "path": "install/regions/regions.213",
    "content": "Gardena, California\r\n200\r\n248\r\n400\r\n500\r\n502\r\n505\r\n700\r\n703\r\n706\r\n708\r\n709\r\n712\r\n718\r\n760\r\n806\r\n810\r\n819\r\n899\r\n918\r\n999\r\nHollywood, California\r\n469\r\nLos Angeles, California\r\n217\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n272\r\n276\r\n277\r\n283\r\n290\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n298\r\n299\r\n300\r\n302\r\n303\r\n304\r\n305\r\n306\r\n307\r\n308\r\n309\r\n312\r\n321\r\n339\r\n340\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n347\r\n349\r\n351\r\n353\r\n356\r\n357\r\n359\r\n360\r\n361\r\n362\r\n365\r\n367\r\n368\r\n369\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n389\r\n413\r\n415\r\n418\r\n436\r\n441\r\n460\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n468\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n503\r\n504\r\n506\r\n507\r\n508\r\n509\r\n520\r\n525\r\n526\r\n530\r\n549\r\n550\r\n554\r\n555\r\n560\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\n567\r\n569\r\n580\r\n581\r\n582\r\n583\r\n584\r\n585\r\n586\r\n587\r\n588\r\n589\r\n600\r\n610\r\n612\r\n613\r\n614\r\n617\r\n620\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n628\r\n629\r\n636\r\n644\r\n650\r\n651\r\n653\r\n654\r\n655\r\n656\r\n658\r\n660\r\n661\r\n662\r\n663\r\n664\r\n665\r\n666\r\n667\r\n668\r\n669\r\n678\r\n680\r\n681\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n701\r\n702\r\n704\r\n705\r\n707\r\n713\r\n714\r\n716\r\n717\r\n723\r\n729\r\n730\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n739\r\n740\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n750\r\n751\r\n752\r\n753\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n765\r\n766\r\n770\r\n771\r\n772\r\n773\r\n774\r\n775\r\n776\r\n777\r\n778\r\n779\r\n780\r\n782\r\n786\r\n787\r\n789\r\n812\r\n845\r\n846\r\n847\r\n848\r\n849\r\n850\r\n851\r\n852\r\n853\r\n856\r\n857\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n878\r\n879\r\n881\r\n882\r\n883\r\n891\r\n892\r\n893\r\n894\r\n895\r\n896\r\n897\r\n900\r\n910\r\n912\r\n913\r\n917\r\n919\r\n920\r\n930\r\n931\r\n932\r\n933\r\n934\r\n935\r\n936\r\n937\r\n938\r\n939\r\n951\r\n953\r\n954\r\n955\r\n956\r\n957\r\n960\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n968\r\n969\r\n971\r\n972\r\n974\r\n975\r\n976\r\n977\r\n979\r\n990\r\n991\r\n993\r\n994\r\nMontebello, California\r\n720\r\n721\r\n722\r\n724\r\n725\r\n726\r\n727\r\n728\r\n887\r\n888\r\n889\r\n890\r\n\u00035Unknown prefix code (213) - California\r\n"
  },
  {
    "path": "install/regions/regions.214",
    "content": "Addison, Texas\r\n383\r\n531\r\n725\r\n839\r\n233\r\n239\r\n308\r\n338\r\n385\r\n386\r\n387\r\n392\r\n404\r\n406\r\n419\r\n448\r\n450\r\n458\r\n490\r\n591\r\n661\r\n701\r\n702\r\n715\r\n716\r\n770\r\n788\r\n851\r\n934\r\n960\r\n980\r\n991\r\n996\r\nAllen, Texas\r\n390\r\n727\r\nAnna, Texas\r\n924\r\nAvalon, Texas\r\n627\r\nBardwell, Texas\r\n646\r\nBlue Ridge, Texas\r\n752\r\nBristol, Texas\r\n666\r\n846\r\nBurleson, Texas\r\n295\r\nCarrollton, Texas\r\n242\r\n245\r\n294\r\n306\r\n307\r\n323\r\n369\r\n389\r\n394\r\n416\r\n417\r\n418\r\n443\r\n446\r\n466\r\n492\r\nCedar Hill, Texas\r\n291\r\n293\r\n299\r\nCelina, Texas\r\n382\r\nCombine, Texas\r\n474\r\n476\r\nCrandall, Texas\r\n427\r\n472\r\nCrowley, Texas\r\n297\r\nDallas-Fort Worth Ar Em, Texas\r\n425\r\n615\r\nDallas, Texas\r\n213\r\n589\r\n648\r\n693\r\n697\r\n777\r\n787\r\n844\r\n928\r\n976\r\n981\r\n990\r\n998\r\n555\r\nDallas-Fort Worth International Airport, Texas\r\n426\r\n453\r\n456\r\n574\r\nDanieldale, Texas\r\n224\r\n228\r\nDavis, Texas\r\n319\r\n320\r\n321\r\n324\r\n327\r\n328\r\nDesoto, Texas\r\n217\r\n223\r\n230\r\nDiamond, Texas\r\n340\r\n341\r\n342\r\n343\r\n348\r\n349\r\n503\r\n553\r\nDowntown Dallas, Texas\r\n220\r\n268\r\n290\r\n325\r\n464\r\n508\r\n520\r\n521\r\n522\r\n523\r\n526\r\n528\r\n529\r\n559\r\n573\r\n651\r\n652\r\n653\r\n655\r\n658\r\n670\r\n698\r\n703\r\n704\r\n707\r\n712\r\n720\r\n740\r\n741\r\n742\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n754\r\n760\r\n761\r\n767\r\n812\r\n818\r\n820\r\n821\r\n823\r\n824\r\n826\r\n827\r\n828\r\n841\r\n855\r\n871\r\n880\r\n922\r\n939\r\n953\r\n954\r\n969\r\n977\r\n978\r\n979\r\n999\r\nDuncanville, Texas\r\n283\r\n296\r\n298\r\n708\r\n709\r\n780\r\nEmerson, Texas\r\n265\r\n345\r\n360\r\n361\r\n363\r\n368\r\n373\r\n691\r\n692\r\n696\r\n706\r\n739\r\n750\r\n768\r\n890\r\n891\r\n987\r\nEnnis, Texas\r\n875\r\n878\r\nEvergreen, Texas\r\n275\r\n381\r\n388\r\nExpress, Texas\r\n309\r\n391\r\n398\r\nFarmers Branch, Texas\r\n241\r\n243\r\n247\r\n277\r\n280\r\n484\r\n620\r\n888\r\n919\r\nFarmersville, Texas\r\n782\r\nFarmers Birch, Texas\r\n432\r\n444\r\n831\r\n784\r\nFederal, Texas\r\n312\r\n330\r\n331\r\n333\r\n337\r\n339\r\n467\r\nFerris, Texas\r\n544\r\nFerris Em, Texas\r\n842\r\nFleetwood, Texas\r\n350\r\n351\r\n352\r\n353\r\n357\r\n358\r\n902\r\n904\r\n956\r\nForney, Texas\r\n552\r\n564\r\nFranklin, Texas\r\n302\r\n371\r\n372\r\n374\r\n375\r\n376\r\nFrisco the Colony, Texas\r\n334\r\n335\r\n370\r\n377\r\n624\r\n625\r\n731\r\nGarland, Texas\r\n205\r\n240\r\n271\r\n272\r\n273\r\n276\r\n278\r\n303\r\n414\r\n485\r\n487\r\n494\r\n495\r\n496\r\n530\r\n840\r\n864\r\nGlendale, Texas\r\n429\r\n457\r\n654\r\n925\r\n930\r\nGrand Prairie, Texas\r\n202\r\n204\r\n212\r\n215\r\n229\r\n236\r\n237\r\n246\r\n249\r\n260\r\n262\r\n263\r\n264\r\n266\r\n269\r\n282\r\n305\r\n314\r\n332\r\n336\r\n384\r\n397\r\n399\r\n460\r\n502\r\n504\r\n533\r\n558\r\n601\r\n602\r\n603\r\n609\r\n623\r\n641\r\n642\r\n647\r\n660\r\n676\r\n755\r\n799\r\n804\r\n805\r\n807\r\n808\r\n906\r\n908\r\n909\r\n912\r\n913\r\n914\r\n933\r\n949\r\n957\r\n988\r\n992\r\n993\r\n344\r\n532\r\n534\r\n535\r\n614\r\n786\r\n901\r\n975\r\n232\r\n244\r\n408\r\n785\r\n813\r\n822\r\n834\r\n835\r\n836\r\n850\r\nGrapevine, Texas\r\n488\r\nHamilton, Texas\r\n421\r\n428\r\n565\r\nHurst\u00031/\u00032Euless\u00031/\u00032Bedford, Texas\r\n322\r\n354\r\n410\r\n451\r\n540\r\n622\r\n806\r\nHutchins, Texas\r\n225\r\nIrving, Texas\r\n281\r\n518\r\n594\r\n607\r\n659\r\n753\r\n915\r\n929\r\n986\r\n326\r\n621\r\n916\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\n261\r\n413\r\n438\r\n445\r\n513\r\n514\r\n515\r\n541\r\n550\r\n554\r\n570\r\n579\r\n580\r\n650\r\n714\r\n717\r\n718\r\n719\r\n721\r\n751\r\n790\r\n791\r\n815\r\nItaly, Texas\r\n483\r\nJefferson, Texas\r\n536\r\nJosephine, Texas\r\n694\r\nKaufman, Texas\r\n932\r\nKeller, Texas\r\n379\r\nKennedale, Texas\r\n478\r\n561\r\n572\r\nLancaster, Texas\r\n218\r\n227\r\nLewisville, Texas\r\n219\r\n221\r\n304\r\n313\r\n315\r\n316\r\n317\r\n318\r\n393\r\n420\r\n434\r\n436\r\n462\r\n471\r\n539\r\n724\r\nLittle Elm, Texas\r\n292\r\nMansfield, Texas\r\n473\r\n477\r\nMarket, Texas\r\n626\r\nMaypearl, Texas\r\n435\r\nMckinney, Texas\r\n542\r\n547\r\n548\r\n569\r\n562\r\n837\r\n838\r\nMelrose, Texas\r\n267\r\n590\r\n630\r\n631\r\n634\r\n637\r\n638\r\n640\r\n688\r\n689\r\n781\r\n819\r\n879\r\n905\r\n920\r\n951\r\nMesquite, Texas\r\n216\r\n222\r\n284\r\n285\r\n288\r\n289\r\n329\r\n882\r\nMidlothian, Texas\r\n723\r\n775\r\nMilford, Texas\r\n493\r\nNewark, Texas\r\n489\r\nNorth Mesquite, Texas\r\n682\r\nNorth Richland Hills, Texas\r\n498\r\n577\r\n581\r\n656\r\nNevada, Texas\r\n843\r\n853\r\nNorth Lake, Texas\r\n401\r\n402\r\n506\r\n556\r\n830\r\n869\r\nNorth Mesquite, Texas\r\n270\r\n279\r\n613\r\n681\r\n686\r\nPalmer, Texas\r\n449\r\n845\r\nPlano, Texas\r\n423\r\n431\r\n509\r\n527\r\n578\r\n608\r\n618\r\n867\r\n403\r\n422\r\n424\r\n491\r\n516\r\n517\r\n519\r\n575\r\n596\r\n604\r\n605\r\n606\r\n612\r\n616\r\n881\r\n964\r\n985\r\nPrinceton, Texas\r\n734\r\n736\r\nProsper, Texas\r\n346\r\n347\r\nRed Oak, Texas\r\n576\r\n617\r\nRenner, Texas\r\n447\r\n732\r\n248\r\n250\r\n380\r\n407\r\n713\r\n733\r\n931\r\nRichardson, Texas\r\n231\r\n234\r\n235\r\n238\r\n301\r\n437\r\n454\r\n470\r\n480\r\n497\r\n644\r\n669\r\n680\r\n684\r\n690\r\n699\r\n705\r\n773\r\n783\r\n801\r\n802\r\n803\r\n907\r\n917\r\n918\r\n952\r\n994\r\n995\r\n997\r\nRichland Hills, Texas\r\n595\r\nRockwall, Texas\r\n722\r\n771\r\nRowlan, Texas\r\n412\r\n475\r\nRoyse City, Texas\r\n635\r\n636\r\nRylie, Texas\r\n286\r\n557\r\nSaginaw, Texas\r\n847\r\nScurry, Texas\r\n452\r\n486\r\nSeagoville, Texas\r\n287\r\nSunnyvale, Texas\r\n203\r\n226\r\nTerrell, Texas\r\n524\r\n551\r\n563\r\nVenus, Texas\r\n366\r\nWalnut, Texas\r\n921\r\n926\r\n927\r\nWaxahachie, Texas\r\n923\r\n937\r\n938\r\nWeatherford, Texas\r\n598\r\n599\r\nWestland, Texas\r\n560\r\nWhitehall, Texas\r\n941\r\n942\r\n943\r\n944\r\n946\r\n948\r\nWhite Settlement, Texas\r\n367\r\n935\r\nWilmer, Texas\r\n441\r\nWilmer Em, Texas\r\n525\r\nWylie, Texas\r\n442\r\n\u00035Unknown prefix code (214) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.215",
    "content": "Adamstown, Pennsylvania\r\n484\r\nAllentown, Pennsylvania\r\n366\r\n390\r\n391\r\n392\r\n395\r\n398\r\n402\r\n432\r\n433\r\n434\r\n435\r\n437\r\n439\r\n481\r\n606\r\n720\r\n740\r\n770\r\n774\r\n776\r\n778\r\n791\r\n797\r\n798\r\n820\r\n821\r\nAtglen, Pennsylvania\r\n593\r\nAvondale, Pennsylvania\r\n268\r\nBally, Pennsylvania\r\n845\r\nBangor, Pennsylvania\r\n588\r\n599\r\nBath, Pennsylvania\r\n837\r\nBedminster, Pennsylvania\r\n795\r\nBelvidere, Pennsylvania\r\n498\r\nBernville, Pennsylvania\r\n488\r\nBethlehem, Pennsylvania\r\n216\r\n360\r\n691\r\n694\r\n730\r\n758\r\n814\r\n861\r\n865\r\n866\r\n867\r\n868\r\n954\r\n974\r\n882\r\nBirdsboro, Pennsylvania\r\n582\r\n858\r\nBowmanston, Pennsylvania\r\n852\r\nBoyertown, Pennsylvania\r\n367\r\n369\r\nBuckingham, Pennsylvania\r\n794\r\nCarversville, Pennsylvania\r\n297\r\nCatasauqua, Pennsylvania\r\n231\r\n264\r\n266\r\nCenter Point, Pennsylvania\r\n584\r\nCheltenham, Pennsylvania\r\n635\r\nChestersprings, Pennsylvania\r\n827\r\nCoatesville, Pennsylvania\r\n380\r\n383\r\n384\r\nCollegeville, Pennsylvania\r\n454\r\n489\r\nCoopersburg, Pennsylvania\r\n282\r\nDenver, Pennsylvania\r\n267\r\nDouglassville, Pennsylvania\r\n385\r\nDownington, Pennsylvania\r\n269\r\n873\r\nDoylestown, Pennsylvania\r\n230\r\n340\r\n345\r\n348\r\nDublin, Pennsylvania\r\n249\r\nEagle, Pennsylvania\r\n458\r\nEaston, Pennsylvania\r\n250\r\n252\r\n253\r\n258\r\n559\r\nEmmaus, Pennsylvania\r\n965\r\n966\r\n967\r\nExton, Pennsylvania\r\n363\r\n524\r\n594\r\nFerndale, Pennsylvania\r\n847\r\nFleetwood, Pennsylvania\r\n944\r\nGlenmoore, Pennsylvania\r\n942\r\nGreen Hills, Pennsylvania\r\n856\r\nGreen Lane, Pennsylvania\r\n234\r\nHamburg, Pennsylvania\r\n562\r\nHarleysville, Pennsylvania\r\n256\r\nHatboro, Pennsylvania\r\n443\r\nHellertown, Pennsylvania\r\n838\r\nHoneybrook, Pennsylvania\r\n273\r\nHuntingdon Valley, Pennsylvania\r\n938\r\n947\r\nIronton, Pennsylvania\r\n799\r\nKemblesville, Pennsylvania\r\n255\r\nKempton, Pennsylvania\r\n756\r\nKennett Square, Pennsylvania\r\n444\r\nKing Of Prussia, Pennsylvania\r\n265\r\nKresgeville, Pennsylvania\r\n681\r\nKunkletown, Pennsylvania\r\n381\r\nKutztown, Pennsylvania\r\n683\r\nLandenberg, Pennsylvania\r\n274\r\nLansdale, Pennsylvania\r\n361\r\n362\r\n368\r\n393\r\n855\r\nLeesport, Pennsylvania\r\n916\r\n926\r\nLehighton, Pennsylvania\r\n377\r\nLenape, Pennsylvania\r\n793\r\nLnlexingtn, Pennsylvania\r\n822\r\n997\r\nMendenhall, Pennsylvania\r\n388\r\nMorgantown, Pennsylvania\r\n286\r\nMorrisvale, Pennsylvania\r\n295\r\n428\r\n736\r\nMortonville, Pennsylvania\r\n486\r\nNazareth, Pennsylvania\r\n746\r\n759\r\nNew Hope, Pennsylvania\r\n862\r\nNewsmithvl, Pennsylvania\r\n285\r\nNewtown, Pennsylvania\r\n579\r\n860\r\n968\r\nNew Tripoli, Pennsylvania\r\n298\r\nNorthampton, Pennsylvania\r\n261\r\n262\r\nNorth Wales, Pennsylvania\r\n616\r\n652\r\n661\r\n699\r\nOley, Pennsylvania\r\n987\r\nOxford, Pennsylvania\r\n932\r\nPalmerton, Pennsylvania\r\n826\r\nParkesburg, Pennsylvania\r\n857\r\nPen Argyl, Pennsylvania\r\n863\r\nPennsburg, Pennsylvania\r\n541\r\n679\r\nPerkasie, Pennsylvania\r\n257\r\n453\r\nPhiladelphia, Pennsylvania\r\n555\r\n203\r\n204\r\n209\r\n213\r\n214\r\n217\r\n218\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n232\r\n235\r\n236\r\n238\r\n241\r\n242\r\n243\r\n246\r\n247\r\n248\r\n263\r\n271\r\n276\r\n280\r\n281\r\n288\r\n289\r\n291\r\n299\r\n304\r\n306\r\n308\r\n319\r\n324\r\n329\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n338\r\n339\r\n342\r\n343\r\n349\r\n351\r\n365\r\n382\r\n386\r\n387\r\n389\r\n403\r\n406\r\n413\r\n414\r\n418\r\n419\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n438\r\n440\r\n448\r\n451\r\n452\r\n455\r\n456\r\n457\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n468\r\n471\r\n472\r\n473\r\n474\r\n476\r\n477\r\n482\r\n483\r\n487\r\n492\r\n496\r\n502\r\n523\r\n533\r\n535\r\n537\r\n545\r\n546\r\n548\r\n549\r\n551\r\n552\r\n553\r\n557\r\n560\r\n561\r\n563\r\n564\r\n567\r\n568\r\n569\r\n571\r\n573\r\n574\r\n575\r\n577\r\n578\r\n580\r\n581\r\n585\r\n587\r\n590\r\n592\r\n596\r\n597\r\n602\r\n612\r\n618\r\n620\r\n621\r\n624\r\n625\r\n627\r\n629\r\n632\r\n634\r\n636\r\n637\r\n656\r\n662\r\n665\r\n671\r\n673\r\n676\r\n677\r\n680\r\n684\r\n685\r\n686\r\n697\r\n698\r\n722\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\n731\r\n732\r\n735\r\n737\r\n739\r\n742\r\n743\r\n744\r\n745\r\n747\r\n748\r\n764\r\n751\r\n753\r\n755\r\n761\r\n762\r\n763\r\n765\r\n769\r\n772\r\n786\r\n787\r\n790\r\n805\r\n806\r\n817\r\n812\r\n819\r\n823\r\n824\r\n829\r\n831\r\n839\r\n840\r\n841\r\n842\r\n843\r\n844\r\n846\r\n848\r\n849\r\n850\r\n851\r\n854\r\n864\r\n870\r\n871\r\n875\r\n877\r\n878\r\n879\r\n880\r\n883\r\n893\r\n894\r\n895\r\n897\r\n898\r\n899\r\n922\r\n923\r\n924\r\n925\r\n927\r\n928\r\n930\r\n931\r\n934\r\n936\r\n937\r\n951\r\n952\r\n955\r\n960\r\n961\r\n963\r\n969\r\n972\r\n973\r\n976\r\n977\r\n978\r\n979\r\n980\r\n981\r\n984\r\n985\r\n988\r\n990\r\n991\r\n994\r\n998\r\nPhoenixville, Pennsylvania\r\n933\r\n935\r\n983\r\nPhiladelphia, Pennsylvania\r\n358\r\n459\r\n558\r\n447\r\n485\r\n490\r\n494\r\n497\r\n499\r\n833\r\n859\r\n872\r\n874\r\n876\r\n565\r\n566\r\n891\r\n892\r\n328\r\n543\r\n544\r\n690\r\n237\r\n461\r\n521\r\n522\r\n532\r\n534\r\n583\r\n586\r\n591\r\n595\r\n259\r\n284\r\n352\r\n394\r\n528\r\n622\r\n623\r\n626\r\n734\r\n446\r\n449\r\n789\r\n853\r\n325\r\n353\r\n356\r\n359\r\nPhiladelphia, Pennsylvania\r\n660\r\n664\r\n667\r\n668\r\n835\r\n642\r\n645\r\n649\r\n658\r\n896\r\n519\r\n520\r\n525\r\n526\r\n527\r\n254\r\n293\r\n341\r\n687\r\n688\r\n964\r\n971\r\n975\r\n989\r\n995\r\n219\r\n251\r\n296\r\n640\r\n644\r\n647\r\n648\r\n651\r\n669\r\n695\r\n889\r\n993\r\n650\r\n666\r\n783\r\n220\r\n239\r\n270\r\n272\r\n275\r\n277\r\n278\r\n279\r\n292\r\n337\r\n354\r\n531\r\n539\r\n630\r\n631\r\n768\r\n808\r\n962\r\n992\r\n303\r\n305\r\n307\r\n397\r\n825\r\n828\r\n832\r\n834\r\n940\r\n941\r\n233\r\n836\r\n206\r\n260\r\n283\r\n290\r\n317\r\n350\r\n421\r\n450\r\n460\r\n470\r\n479\r\n480\r\n530\r\n540\r\n542\r\n570\r\n619\r\n628\r\n641\r\n643\r\n646\r\n653\r\n654\r\n771\r\n802\r\n803\r\n813\r\n815\r\n816\r\n919\r\n920\r\n986\r\nPhiladelphia, Pennsylvania\r\n379\r\n572\r\n576\r\n663\r\n782\r\n881\r\n884\r\n885\r\n886\r\n887\r\n657\r\n659\r\n784\r\n830\r\n441\r\n442\r\n672\r\n674\r\n675\r\n956\r\n957\r\n322\r\n355\r\n357\r\n364\r\n396\r\n953\r\n202\r\n244\r\n245\r\n633\r\n638\r\n639\r\n781\r\n785\r\n788\r\n741\r\n750\r\n752\r\n757\r\n547\r\n943\r\n945\r\n946\r\n949\r\n491\r\nPlumstedvl, Pennsylvania\r\n766\r\nPottstown, Pennsylvania\r\n323\r\n326\r\n327\r\n970\r\nPughtown, Pennsylvania\r\n469\r\nQuakertown, Pennsylvania\r\n529\r\n536\r\n538\r\nReading, Pennsylvania\r\n208\r\n320\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n378\r\n478\r\n655\r\n670\r\n678\r\n775\r\n777\r\n779\r\n780\r\n796\r\n921\r\n929\r\n939\r\nRiegelsvl, Pennsylvania\r\n749\r\n982\r\nRobesonia, Pennsylvania\r\n693\r\nRoyersford, Pennsylvania\r\n495\r\n792\r\nSassmansville, Pennsylvania\r\n754\r\nSchwenksville, Pennsylvania\r\n287\r\nSlatington, Pennsylvania\r\n760\r\n767\r\nSouderton, Pennsylvania\r\n721\r\n723\r\nSpring City, Pennsylvania\r\n948\r\nSpringtown, Pennsylvania\r\n346\r\nTerre Hill, Pennsylvania\r\n445\r\nTopton, Pennsylvania\r\n682\r\nUhlerstown, Pennsylvania\r\n294\r\nUnionville, Pennsylvania\r\n347\r\nWarminister, Pennsylvania\r\n773\r\nWest Chester, Pennsylvania\r\n344\r\n429\r\n430\r\n431\r\n436\r\n692\r\n696\r\nWest Grove, Pennsylvania\r\n869\r\nWesttown, Pennsylvania\r\n399\r\nWomelsdorf, Pennsylvania\r\n589\r\nWycombe, Pennsylvania\r\n598\r\nYardley, Pennsylvania\r\n321\r\n493\r\nYellow House, Pennsylvania\r\n689\r\n\u00035Unknown prefix code (215) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/regions.216",
    "content": "Akron, Ohio\r\n556\r\n250\r\n253\r\n258\r\n370\r\n374\r\n375\r\n376\r\n379\r\n384\r\n388\r\n434\r\n535\r\n560\r\n571\r\n592\r\n620\r\n630\r\n633\r\n643\r\n644\r\n645\r\n686\r\n688\r\n697\r\n724\r\n730\r\n733\r\n745\r\n753\r\n762\r\n773\r\n784\r\n785\r\n794\r\n796\r\n798\r\n825\r\n836\r\n848\r\n860\r\n864\r\n867\r\n869\r\n873\r\n920\r\n922\r\n923\r\n928\r\n929\r\n940\r\n945\r\n971\r\n972\r\n981\r\n996\r\nAlliance, Ohio\r\n821\r\n823\r\n829\r\nAmherst, Ohio\r\n984\r\n985\r\n986\r\n988\r\nAndover, Ohio\r\n293\r\nApple Creek, Ohio\r\n698\r\nAshtabula, Ohio\r\n964\r\n969\r\n992\r\n993\r\n994\r\n997\r\n998\r\nAtwater, Ohio\r\n947\r\nAurora, Ohio\r\n995\r\n562\r\nAustinburg, Ohio\r\n275\r\nAvon, Ohio\r\n934\r\n937\r\nAvon Lake, Ohio\r\n930\r\n933\r\nBainbridge, Ohio\r\n543\r\nBaltic, Ohio\r\n897\r\nBeach City, Ohio\r\n756\r\nBedford, Ohio\r\n232\r\n439\r\n786\r\nBerea, Ohio\r\n234\r\n243\r\n826\r\n891\r\nBerlin, Ohio\r\n893\r\nBig Prairie, Ohio\r\n496\r\nBirmingham, Ohio\r\n965\r\nBolivar, Ohio\r\n874\r\nBrecksville, Ohio\r\n526\r\n546\r\n838\r\nBrewster, Ohio\r\n767\r\nBristolville, Ohio\r\n889\r\nBrookfield\u00031/\u00032Sharon Center, Ohio\r\n448\r\nBrunswick, Ohio\r\n220\r\n225\r\n273\r\nBurbank, Ohio\r\n624\r\nBurton, Ohio\r\n834\r\nCanal Fulton, Ohio\r\n854\r\nCanton, Ohio\r\n430\r\n438\r\n450\r\n452\r\n453\r\n454\r\n455\r\n456\r\n471\r\n477\r\n478\r\n484\r\n488\r\n489\r\n492\r\n493\r\n495\r\n580\r\n588\r\nCarrollton, Ohio\r\n627\r\nChagrin Falls, Ohio\r\n247\r\n248\r\n349\r\n498\r\nChardon, Ohio\r\n285\r\n286\r\nChatham, Ohio\r\n667\r\nChesterld, Ohio\r\n729\r\nCleveland, Ohio\r\n221\r\n226\r\n228\r\n229\r\n231\r\n241\r\n249\r\n251\r\n252\r\n261\r\n265\r\n266\r\n267\r\n268\r\n271\r\n281\r\n283\r\n289\r\n291\r\n295\r\n299\r\n321\r\n331\r\n333\r\n341\r\n344\r\n346\r\n348\r\n351\r\n356\r\n361\r\n362\r\n363\r\n368\r\n371\r\n381\r\n382\r\n383\r\n387\r\n389\r\n390\r\n391\r\n397\r\n398\r\n421\r\n429\r\n431\r\n432\r\n433\r\n436\r\n440\r\n441\r\n443\r\n444\r\n445\r\n451\r\n459\r\n462\r\n469\r\n470\r\n476\r\n479\r\n481\r\n485\r\n486\r\n491\r\n521\r\n522\r\n523\r\n529\r\n531\r\n541\r\n555\r\n561\r\n566\r\n570\r\n574\r\n575\r\n578\r\n579\r\n586\r\n589\r\n598\r\n621\r\n622\r\n623\r\n631\r\n634\r\n641\r\n651\r\n661\r\n664\r\n670\r\n671\r\n676\r\n681\r\n687\r\n689\r\n691\r\n692\r\n694\r\n696\r\n721\r\n728\r\n731\r\n732\r\n736\r\n737\r\n741\r\n749\r\n751\r\n752\r\n754\r\n761\r\n771\r\n778\r\n780\r\n781\r\n787\r\n789\r\n790\r\n791\r\n795\r\n822\r\n844\r\n851\r\n861\r\n870\r\n881\r\n883\r\n921\r\n931\r\n932\r\n941\r\n952\r\n961\r\n973\r\n976\r\n977\r\n978\r\n983\r\n987\r\n991\r\n999\r\nColebrook, Ohio\r\n422\r\nColmbiasta, Ohio\r\n236\r\nConneaut, Ohio\r\n593\r\n594\r\n599\r\nCortland, Ohio\r\n637\r\n638\r\nCreston, Ohio\r\n435\r\nDalton, Ohio\r\n828\r\nDamascus, Ohio\r\n537\r\nDellroy, Ohio\r\n735\r\nDorset, Ohio\r\n858\r\nDoylestown, Ohio\r\n658\r\nEast Claridon, Ohio\r\n635\r\nEast Liverpool, Ohio\r\n385\r\n386\r\nElyria, Ohio\r\n284\r\n322\r\n323\r\n324\r\n327\r\n329\r\n353\r\n355\r\n365\r\n366\r\n458\r\nEast Palestine, Ohio\r\n426\r\nEast Rochester, Ohio\r\n894\r\nFredricksburg, Ohio\r\n695\r\nGarretsville, Ohio\r\n527\r\nGatesmills, Ohio\r\n423\r\nGeneva, Ohio\r\n466\r\nGlenmont, Ohio\r\n377\r\nGrafton, Ohio\r\n926\r\nGreene, Ohio\r\n583\r\nGreensburg, Ohio\r\n896\r\nHanoverton, Ohio\r\n223\r\nHarlem Springs, Ohio\r\n739\r\nHartford, Ohio\r\n772\r\nHartville, Ohio\r\n877\r\nHillcrest, Ohio\r\n442\r\n446\r\n449\r\n461\r\n473\r\n646\r\nHinckley, Ohio\r\n278\r\nHiram, Ohio\r\n569\r\nHolmesville, Ohio\r\n279\r\nHomerville, Ohio\r\n625\r\nHudson, Ohio\r\n342\r\n650\r\n655\r\n653\r\nHuntsburg, Ohio\r\n636\r\nIndependence, Ohio\r\n328\r\n447\r\n524\r\n573\r\n642\r\n680\r\n768\r\n982\r\nJefferson, Ohio\r\n576\r\nJohnston, Ohio\r\n924\r\nKent, Ohio\r\n672\r\n677\r\n673\r\n678\r\nKidron, Ohio\r\n857\r\nKillbuck, Ohio\r\n276\r\nKingsville, Ohio\r\n224\r\nKinsman, Ohio\r\n876\r\nKirtland, Ohio\r\n256\r\nLake Milton, Ohio\r\n654\r\nLeetonia, Ohio\r\n427\r\nLeroy, Ohio\r\n254\r\nLisbon, Ohio\r\n424\r\n853\r\nLodi, Ohio\r\n948\r\nLorain, Ohio\r\n233\r\n242\r\n277\r\n949\r\n244\r\n245\r\n246\r\n282\r\n288\r\n960\r\nLouisville, Ohio\r\n875\r\nMadison, Ohio\r\n428\r\nMagnlwynburg, Ohio\r\n866\r\nMalvern, Ohio\r\n863\r\nManchester, Ohio\r\n882\r\nMantua, Ohio\r\n274\r\nMarlboro, Ohio\r\n935\r\nMarshallville, Ohio\r\n855\r\nMassillon, Ohio\r\n830\r\n832\r\n833\r\n837\r\nMechanicston, Ohio\r\n738\r\nMedina, Ohio\r\n722\r\n723\r\n725\r\n764\r\nMentor, Ohio\r\n255\r\n257\r\n974\r\nMesopotama, Ohio\r\n693\r\nMiddlefield, Ohio\r\n632\r\nMillersbg, Ohio\r\n674\r\nMineral City, Ohio\r\n859\r\nMinerva, Ohio\r\n868\r\nMogadore, Ohio\r\n628\r\nMontrose City, Ohio\r\n475\r\n581\r\n587\r\n662\r\n663\r\n665\r\n666\r\n668\r\nMontville, Ohio\r\n968\r\nNashville, Ohio\r\n378\r\nNavarre, Ohio\r\n879\r\nNew Lyme, Ohio\r\n294\r\nNew Phila, Ohio\r\n339\r\n340\r\n343\r\n364\r\n827\r\nNewbury, Ohio\r\n564\r\nNewton Falls, Ohio\r\n872\r\nNewwaterford, Ohio\r\n457\r\nNiles, Ohio\r\n544\r\n652\r\nNorth Benton, Ohio\r\n584\r\nNorth Canton, Ohio\r\n490\r\n494\r\n497\r\n499\r\n966\r\nNorth Bloomfield, Ohio\r\n685\r\nNorth Georgetown, Ohio\r\n525\r\nNorth Royalton, Ohio\r\n230\r\n237\r\n582\r\nNorth Eaton, Ohio\r\n748\r\nNorthfield, Ohio\r\n463\r\n467\r\n468\r\n528\r\n656\r\nOberlin, Ohio\r\n774\r\n775\r\nOlmstedfalls, Ohio\r\n235\r\nOrrville, Ohio\r\n682\r\n683\r\n684\r\nOrwell, Ohio\r\n437\r\nPainesville, Ohio\r\n350\r\n352\r\n354\r\n357\r\n639\r\nParis, Ohio\r\n862\r\nParkman, Ohio\r\n548\r\nPatersonville, Ohio\r\n895\r\nPeninsula, Ohio\r\n657\r\nPerry, Ohio\r\n259\r\nPierpont, Ohio\r\n577\r\nRavenna, Ohio\r\n296\r\n297\r\nRichfield, Ohio\r\n659\r\nRittman, Ohio\r\n925\r\n927\r\nRock Creek, Ohio\r\n563\r\nRogers, Ohio\r\n227\r\nRoosevelt, Minnesota\r\n442\r\nRootstown, Ohio\r\n325\r\nRussell, Ohio\r\n338\r\nSalem, Ohio\r\n332\r\n337\r\nSalineville, Ohio\r\n679\r\nSebring, Ohio\r\n938\r\nSeville, Ohio\r\n769\r\nSharon, Ohio\r\n239\r\nShreve, Ohio\r\n567\r\nSmithville, Ohio\r\n669\r\nSpencer, Ohio\r\n648\r\nSterling, Ohio\r\n939\r\nStrasburg, Ohio\r\n878\r\nStreetsboro, Ohio\r\n626\r\nStrongsville, Ohio\r\n238\r\n572\r\n846\r\nSugar Creek, Ohio\r\n852\r\nTerrace, Ohio\r\n292\r\n360\r\n464\r\n590\r\n591\r\n595\r\n690\r\n765\r\n766\r\n831\r\n880\r\nThompson, Ohio\r\n298\r\nTrinity, Ohio\r\n734\r\n777\r\n779\r\n835\r\n871\r\n892\r\n899\r\n962\r\n979\r\nTrumbull, Ohio\r\n474\r\nTwinsburg, Ohio\r\n425\r\n487\r\n963\r\nUniontown, Ohio\r\n699\r\nValleycity, Ohio\r\n483\r\nVermilion, Ohio\r\n967\r\nVictory, Ohio\r\n842\r\n843\r\n845\r\n884\r\n885\r\n886\r\n888\r\nWest Field Center, Ohio\r\n887\r\nWadsworth, Ohio\r\n334\r\n335\r\n336\r\nWakeman, Ohio\r\n839\r\nWarren, Ohio\r\n367\r\n369\r\n372\r\n373\r\n392\r\n393\r\n394\r\n395\r\n399\r\n675\r\n824\r\n841\r\n847\r\n856\r\n898\r\nWayland, Ohio\r\n358\r\nWellington, Ohio\r\n647\r\nWellsville, Ohio\r\n532\r\nWickliffe, Ohio\r\n585\r\n943\r\n944\r\nWilloughby, Ohio\r\n269\r\n942\r\n946\r\n951\r\n953\r\n975\r\nWilmot, Ohio\r\n359\r\nWindham, Ohio\r\n326\r\nWindsor, Ohio\r\n272\r\nWinona, Ohio\r\n222\r\nWooster, Ohio\r\n262\r\n263\r\n264\r\n287\r\n345\r\n465\r\nYoungstown, Ohio\r\n482\r\n530\r\n533\r\n534\r\n536\r\n538\r\n539\r\n540\r\n542\r\n545\r\n547\r\n549\r\n565\r\n568\r\n629\r\n720\r\n726\r\n727\r\n740\r\n742\r\n743\r\n744\r\n746\r\n747\r\n750\r\n755\r\n757\r\n758\r\n759\r\n782\r\n783\r\n788\r\n792\r\n793\r\n797\r\n799\r\n820\r\n\u00035Unknown prefix code (216) - Ohio\r\n"
  },
  {
    "path": "install/regions/regions.217",
    "content": "Alexander, Illinois\r\n478\r\nAlvin, Illinois\r\n765\r\nArcola, Illinois\r\n268\r\nArenzville, Illinois\r\n997\r\nArgenta, Illinois\r\n795\r\nArmstrong, Illinois\r\n569\r\nArthur, Illinois\r\n543\r\nAshland, Illinois\r\n476\r\nAshmore, Illinois\r\n349\r\nAssumption, Illinois\r\n226\r\nAthens, Illinois\r\n636\r\nAtlanta, Illinois\r\n648\r\nAtwood, Illinois\r\n578\r\nAuburn, Illinois\r\n438\r\nAugusta, Illinois\r\n392\r\nBarry, Illinois\r\n335\r\nBasco, Illinois\r\n743\r\nBaylis, Illinois\r\n336\r\nBeardstown, Illinois\r\n323\r\nBeason, Illinois\r\n447\r\nBement, Illinois\r\n678\r\nBenld, Illinois\r\n835\r\nBethany, Illinois\r\n665\r\nBismarck, Illinois\r\n759\r\nBlue Mound, Illinois\r\n692\r\nBluffs, Illinois\r\n754\r\nBondville, Illinois\r\n863\r\nBowen, Illinois\r\n842\r\nBroadlands, Illinois\r\n834\r\nBrocton, Illinois\r\n385\r\nBuckley, Illinois\r\n394\r\nBuffalo, Illinois\r\n364\r\nBurton, Illinois\r\n885\r\nCamp Point, Illinois\r\n593\r\nCantrall, Illinois\r\n487\r\nCarlinville, Illinois\r\n854\r\nCarrollton, Illinois\r\n942\r\nCarthage, Illinois\r\n357\r\nCasey, Illinois\r\n932\r\nCatlin, Illinois\r\n427\r\nCerrogordo, Illinois\r\n763\r\nChambersburg, Illinois\r\n327\r\nChampaign, Illinois\r\n351\r\n352\r\n356\r\n359\r\n363\r\n365\r\n367\r\n369\r\n372\r\n373\r\n377\r\n378\r\n383\r\n384\r\n398\r\n591\r\nChandlerville, Illinois\r\n458\r\nChapin, Illinois\r\n472\r\nCharleston, Illinois\r\n345\r\n348\r\n581\r\nChatham, Illinois\r\n483\r\nCheneyville, Illinois\r\n339\r\nChestnut, Illinois\r\n796\r\nChmpurb Cm, Illinois\r\n366\r\n249\r\n255\r\nChrisman, Illinois\r\n269\r\nCisco, Illinois\r\n669\r\nClarksville, Illinois\r\n889\r\nClayton, Illinois\r\n894\r\nClinton, Illinois\r\n935\r\n937\r\nCoatsburg, Illinois\r\n455\r\nCoffeen, Illinois\r\n534\r\nCollison, Illinois\r\n776\r\nColumbus, Illinois\r\n334\r\nColusa, Illinois\r\n755\r\nConcord, Illinois\r\n457\r\nCowden, Illinois\r\n783\r\nDallas City, Illinois\r\n852\r\nDalton City, Illinois\r\n874\r\nDanville, Illinois\r\n431\r\n442\r\n443\r\n446\r\n474\r\n477\r\n497\r\nDe Land, Illinois\r\n664\r\nDecatur, Illinois\r\n433\r\n362\r\n421\r\n422\r\n423\r\n424\r\n425\r\n428\r\n429\r\n454\r\n462\r\n464\r\n475\r\n872\r\n875\r\n876\r\n877\r\nDieterich, Illinois\r\n925\r\nDivernon, Illinois\r\n628\r\nDonnellson, Illinois\r\n537\r\nEast Lynn, Illinois\r\n375\r\nEdinburg, Illinois\r\n623\r\nEffingham, Illinois\r\n342\r\n343\r\n347\r\nEldred, Illinois\r\n983\r\nElkhart, Illinois\r\n947\r\nElliotstown, Illinois\r\n739\r\nElliott, Illinois\r\n749\r\nElvaston, Illinois\r\n845\r\nElwin, Illinois\r\n767\r\n865\r\nEmden, Illinois\r\n376\r\nFairmount, Illinois\r\n733\r\nFarmersville, Illinois\r\n227\r\nFerris, Illinois\r\n746\r\nFillmore, Illinois\r\n538\r\nFindlay, Illinois\r\n756\r\nFisher, Illinois\r\n897\r\nFishhook, Illinois\r\n338\r\nFithian, Illinois\r\n548\r\nFlatville, Illinois\r\n694\r\nFoosland, Illinois\r\n846\r\nFountn Green, Illinois\r\n654\r\nFowler, Illinois\r\n434\r\nFranklin, Illinois\r\n675\r\nGays, Illinois\r\n752\r\nGeorgetown, Illinois\r\n662\r\nGibson City, Illinois\r\n784\r\nGifford, Illinois\r\n568\r\nGila, Illinois\r\n683\r\nGillespie, Illinois\r\n839\r\nGirard, Illinois\r\n627\r\nGolden, Illinois\r\n696\r\nGrandview, Illinois\r\n946\r\nGreenfield, Illinois\r\n368\r\nGreenup, Illinois\r\n923\r\nGreenview, Illinois\r\n968\r\nGriggsville, Illinois\r\n833\r\nHamilton, Illinois\r\n847\r\nHammond, Illinois\r\n262\r\nHarristown, Illinois\r\n963\r\nHartsburg, Illinois\r\n642\r\nHenning, Illinois\r\n286\r\nHersman, Illinois\r\n289\r\nHillsboro, Illinois\r\n532\r\nHillview, Illinois\r\n945\r\nHomer, Illinois\r\n896\r\nHoopeston, Illinois\r\n283\r\nHull, Illinois\r\n432\r\nHumboldt, Illinois\r\n856\r\nIlliopolis, Illinois\r\n486\r\nIndianola, Illinois\r\n284\r\nIrving, Illinois\r\n533\r\nIvesdale, Illinois\r\n564\r\nJacksonville, Illinois\r\n243\r\n245\r\n248\r\n473\r\n479\r\nKansas, Illinois\r\n948\r\nKenney, Illinois\r\n944\r\nKincaid, Illinois\r\n237\r\nKirksville, Illinois\r\n797\r\nLa Harpe, Illinois\r\n659\r\nLa Place, Illinois\r\n677\r\nLatham, Illinois\r\n674\r\nLiberty, Illinois\r\n645\r\nLima, Illinois\r\n985\r\nLincoln, Illinois\r\n732\r\n735\r\n737\r\nLitchfield, Illinois\r\n324\r\nLiterberry, Illinois\r\n886\r\nLoami, Illinois\r\n624\r\nLoda, Illinois\r\n386\r\nLomax, Illinois\r\n449\r\nLoraine, Illinois\r\n938\r\nLovington, Illinois\r\n873\r\nLudlow, Illinois\r\n396\r\nMacon, Illinois\r\n764\r\nMahomet, Illinois\r\n586\r\nManchester, Illinois\r\n587\r\nMansfield, Illinois\r\n489\r\nMaroa, Illinois\r\n794\r\nMarshall, Illinois\r\n822\r\n826\r\nMartinsville, Illinois\r\n382\r\nMason City, Illinois\r\n482\r\nMattoon, Illinois\r\n232\r\n234\r\n235\r\n254\r\n258\r\n259\r\nMidltonnhland, Illinois\r\n445\r\nMelvin, Illinois\r\n388\r\nMendon, Illinois\r\n936\r\nMeredosia, Illinois\r\n584\r\nMetcalf, Illinois\r\n887\r\nMeyer, Illinois\r\n647\r\nMilton, Illinois\r\n723\r\nMindale, Illinois\r\n667\r\nModesto, Illinois\r\n439\r\nMonticello, Illinois\r\n762\r\nMontrose, Illinois\r\n924\r\nMorrisonville, Illinois\r\n526\r\nMount Zion, Illinois\r\n864\r\nMountolive, Illinois\r\n999\r\nMoweaqua, Illinois\r\n768\r\nMount Auburn, Illinois\r\n676\r\nMount Pulaski, Illinois\r\n792\r\nMount Sterling, Illinois\r\n773\r\nMurrayville, Illinois\r\n882\r\nNauvoo, Illinois\r\n453\r\nNeoga, Illinois\r\n895\r\nNew Berlin, Illinois\r\n488\r\nNew Canton, Illinois\r\n426\r\nNewdouglas, Illinois\r\n456\r\nNewman, Illinois\r\n837\r\nNiantic, Illinois\r\n668\r\nNiota, Illinois\r\n448\r\nNokomis, Illinois\r\n563\r\nOakford, Illinois\r\n635\r\nOakland, Illinois\r\n346\r\nOakwood, Illinois\r\n354\r\nOconee, Illinois\r\n539\r\nOgden, Illinois\r\n582\r\nOreana, Illinois\r\n468\r\nOwaneco, Illinois\r\n879\r\nPalmyra, Illinois\r\n436\r\nPana, Illinois\r\n562\r\nParis, Illinois\r\n463\r\n465\r\n466\r\nPatterson, Illinois\r\n927\r\nPawnee, Illinois\r\n625\r\nPaxton, Illinois\r\n379\r\nPayson, Illinois\r\n656\r\nPearl, Illinois\r\n829\r\nPenfield, Illinois\r\n595\r\nPerry, Illinois\r\n236\r\nPesotum, Illinois\r\n867\r\nPetersburg, Illinois\r\n632\r\nPhilo, Illinois\r\n684\r\nPittsfield, Illinois\r\n285\r\nPleasant Hill, Illinois\r\n734\r\nPleasantpls, Illinois\r\n626\r\nPotomac, Illinois\r\n987\r\nQuincy, Illinois\r\n221\r\n222\r\n223\r\n224\r\n228\r\n242\r\n257\r\nRankin, Illinios\r\n397\r\nRantoul, Illinois\r\n495\r\n892\r\n893\r\nRaymond, Illinois\r\n229\r\nRedmon, Illinois\r\n884\r\nRidge Farm, Illinois\r\n247\r\nRiverton, Illinois\r\n629\r\nRoberts, Illinois\r\n395\r\nRochester, Illinois\r\n498\r\nRockport, Illinois\r\n437\r\nRoodhouse, Illinois\r\n589\r\nRossville, Illinois\r\n748\r\nRoyal, Illinois\r\n583\r\nRushville, Illinois\r\n322\r\nSadorus, Illinois\r\n598\r\nScottville, Illinois\r\n484\r\nSeymour, Illinois\r\n687\r\nShelbyville, Illinois\r\n774\r\nSherman, Illinois\r\n496\r\nShumway, Illinois\r\n868\r\nSibley, Illinois\r\n745\r\nSidell, Illinois\r\n288\r\nSidney, Illinois\r\n688\r\nSigel, Illinois\r\n844\r\nSorento, Illinois\r\n272\r\nSpringfield, Illinois\r\n529\r\n585\r\n786\r\n467\r\n492\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n535\r\n541\r\n544\r\n545\r\n744\r\n747\r\n753\r\n782\r\n785\r\n788\r\n789\r\n546\r\n547\r\n698\r\n787\r\n793\r\nSpringfieldcl, Illinois\r\n652\r\n725\r\nSaint Joseph, Illinois\r\n469\r\nStewardson, Illinois\r\n682\r\nStonington, Illinois\r\n325\r\nStrasburg, Illinois\r\n644\r\nSullivan, Illinois\r\n728\r\nSutter, Illinois\r\n658\r\nTallula, Illinois\r\n634\r\nTaylorville, Illinois\r\n287\r\n824\r\n825\r\nTeutopolis, Illinois\r\n857\r\nThawville, Illinois\r\n387\r\nThomasboro, Illinois\r\n643\r\nToledo, Illinois\r\n849\r\nTolono, Illinois\r\n485\r\nTower Hill, Illinois\r\n567\r\nTuscola, Illinois\r\n253\r\nUniversity Of Illinois, Illinois\r\n244\r\n332\r\n333\r\nUrbana, Illinois\r\n326\r\n328\r\n337\r\n344\r\n355\r\nUrsa, Illinois\r\n964\r\nVermilion, Illinois\r\n275\r\nVersailles, Illinois\r\n225\r\nVillagrove, Illinois\r\n832\r\nVirden, Illinois\r\n965\r\nVirginia, Illinois\r\n452\r\nWarrensburg, Illinois\r\n672\r\nWarsaw, Illinois\r\n256\r\nWatson, Illinois\r\n536\r\nWaverly, Illinois\r\n435\r\nWaynesville, Illinois\r\n949\r\nWeldon, Illinois\r\n736\r\nWest Dana, Illinois\r\n666\r\nWest Union, Illinois\r\n279\r\nWestervelt, Illinois\r\n738\r\nWestfield, Illinois\r\n967\r\nWestville, Illinois\r\n267\r\nWhite Hall, Illinois\r\n374\r\nWilliamsville, Illinois\r\n566\r\nWinchester, Illinois\r\n742\r\nWindsor, Illinois\r\n459\r\nWitt, Illinois\r\n594\r\nWoodson, Illinois\r\n673\r\n\u00035Unknown prefix code (217) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.218",
    "content": "Ada, Minnesota\r\n784\r\nAitkin, Minnesota\r\n927\r\nAlborn, Minnesota\r\n345\r\nAlvarado, Minnesota\r\n965\r\nAngleinlet, Minnesota\r\n223\r\nArgyle, Minnesota\r\n437\r\nAsh River, Minnesota\r\n374\r\nAshby, Minnesota\r\n747\r\nAudubon, Minnesota\r\n439\r\nAurora, Minnesota\r\n229\r\nBabbitt, Minnesota\r\n827\r\nBackus, Minnesota\r\n947\r\nBadger, Minnesota\r\n528\r\nBagley, Minnesota\r\n694\r\nBarnesvl, Minnesota\r\n354\r\n493\r\nBarnum, Minnesota\r\n380\r\n389\r\nBattlelake, Minnesota\r\n864\r\nBaudette, Minnesota\r\n634\r\nBear River, Minnesota\r\n376\r\nBecida, Minnesota\r\n854\r\nBeltrami, Minnesota\r\n926\r\nBemidji, Minnesota\r\n751\r\n755\r\n759\r\n760\r\n766\r\nBena, Minnesota\r\n665\r\nBennettville, Minnesota\r\n678\r\nBertha, Minnesota\r\n924\r\nBig Falls, Minnesota\r\n276\r\nBigfork, Minnesota\r\n743\r\nBiwabik, Minnesota\r\n865\r\nBlackduck, Minnesota\r\n835\r\nBorup, Minnesota\r\n582\r\nBoy River, Minnesota\r\n889\r\nBrainerd, Minnesota\r\n820\r\n828\r\n829\r\n839\r\nBreckenridge, Minnesota\r\n643\r\nBreezy Point, Minnesota\r\n562\r\nBrimson, Minnesota\r\n848\r\nBrooks, Minnesota\r\n698\r\nBrookston, Minnesota\r\n453\r\nBuhl, Minnesota\r\n258\r\nBygland, Minnesota\r\n893\r\nCallaway, Minnesota\r\n375\r\nCampbell, Minnesota\r\n630\r\nCarlton, Minnesota\r\n384\r\n390\r\nCass Lake, Minnesota\r\n335\r\nChisholm, Minnesota\r\n254\r\nClarissa, Minnesota\r\n756\r\nClearbrook, Minnesota\r\n776\r\nClimax, Minnesota\r\n857\r\nCloquet, Minnesota\r\n878\r\n879\r\nColeraine, Minnesota\r\n244\r\n245\r\n259\r\nComstock, Minnesota\r\n585\r\nCook, Minnesota\r\n666\r\nCormorant, Minnesota\r\n532\r\nCotton, Minnesota\r\n482\r\nCrane Lake, Minnesota\r\n993\r\nCromwell, Minnesota\r\n644\r\nCrookston, Minnesota\r\n280\r\n281\r\n289\r\nCrosby, Minnesota\r\n546\r\nCross Lake, Minnesota\r\n692\r\nDalton, Minnesota\r\n589\r\nDeer Creek, Minnesota\r\n462\r\nDeer River, Minnesota\r\n246\r\nDeerwood, Minnesota\r\n534\r\nDenham, Minnesota\r\n658\r\nDent, Minnesota\r\n758\r\nDetroit Lakes, Minnesota\r\n841\r\n846\r\n847\r\n849\r\nDonaldson, Minnesota\r\n466\r\nDuluth, Minnesota\r\n343\r\n348\r\n525\r\n624\r\n626\r\n628\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\n730\r\nEast Abercrombe, Minnesota\r\n557\r\nEast Drayton, Minnesota\r\n455\r\nEagle Bend, Minnesota\r\n738\r\nEast Fairmount, Minnesota\r\n479\r\nEast Grand Forks, Minnesota\r\n773\r\n779\r\nElbow Lake, Minnesota\r\n685\r\nEly, Minnesota\r\n364\r\n365\r\nEmbarrass, Minnesota\r\n984\r\nEmily, Minnesota\r\n763\r\nErhard, Minnesota\r\n842\r\nEricsburg, Minnesota\r\n377\r\nErskine, Minnesota\r\n687\r\nEvansville, Minnesota\r\n948\r\nFargo, North Dakota\r\n555\r\nFederal Dam, Minnesota\r\n654\r\nFelton, Minnesota\r\n494\r\nFergus Falls, Minnesota\r\n731\r\n736\r\n739\r\nFertile, Minnesota\r\n945\r\nFisher, Minnesota\r\n891\r\nFlom, Minnesota\r\n567\r\nFloodwood, Minnesota\r\n476\r\nFosston, Minnesota\r\n435\r\nFrazee, Minnesota\r\n334\r\nGary, Minnesota\r\n356\r\nGateway, Minnesota\r\n426\r\nGatzke, Minnesota\r\n459\r\nGlyndon, Minnesota\r\n498\r\nGonvick, Minnesota\r\n487\r\nGoodridge, Minnesota\r\n378\r\nGrand Mara, Minnesota\r\n387\r\n388\r\nGrand Rapids, Minnesota\r\n326\r\n327\r\n328\r\nGreaney, Minnesota\r\n787\r\nGreenbush, Minnesota\r\n781\r\n782\r\nGrygla, Minnesota\r\n294\r\nGully, Minnesota\r\n268\r\nHackensack, Minnesota\r\n675\r\n682\r\nHallock, Minnesota\r\n843\r\nHalstad, Minnesota\r\n456\r\nHawley, Minnesota\r\n483\r\nHenning, Minnesota\r\n583\r\nHibbing, Minnesota\r\n262\r\n263\r\n966\r\nHill City, Minnesota\r\n697\r\nHitterdal, Minnesota\r\n962\r\nHolt, Minnesota\r\n449\r\nHovland, Minnesota\r\n475\r\nHoyt Lakes, Minnesota\r\n225\r\nHumboldt, Minnesota\r\n379\r\nIdeal Cors, Minnesota\r\n543\r\nInger Wirt, Minnesota\r\n798\r\nIntntl Fls, Minnesota\r\n283\r\n285\r\nIsabella, Minnesota\r\n323\r\nJacobson, Minnesota\r\n752\r\nKabetogama, Minnesota\r\n875\r\nKarlstad, Minnesota\r\n265\r\n436\r\n597\r\nKeewatin, Minnesota\r\n778\r\nKelliher, Minnesota\r\n647\r\nKennedy, Minnesota\r\n674\r\nKettle River, Minnesota\r\n273\r\nKimberly, Minnesota\r\n549\r\nLake Park, Minnesota\r\n238\r\nLancaster, Minnesota\r\n762\r\nLaporte, Minnesota\r\n224\r\nLeader, Minnesota\r\n397\r\nLengby, Minnesota\r\n668\r\nLeonard, Minnesota\r\n968\r\nLincoln, Minnesota\r\n575\r\nLittle Fork, Minnesota\r\n278\r\nLake Bronson, Minnesota\r\n754\r\nLoman, Minnesota\r\n279\r\nLongville, Minnesota\r\n363\r\nMahnomen, Minnesota\r\n935\r\nMaine, Minnesota\r\n495\r\nMalngwansk, Minnesota\r\n425\r\nMaple Bay, Minnesota\r\n574\r\nMarble, Minnesota\r\n247\r\nMarcell, Minnesota\r\n832\r\nMcgregor, Minnesota\r\n768\r\nMcintosh, Minnesota\r\n563\r\nMeadowlands, Minnesota\r\n427\r\nMenahga, Minnesota\r\n564\r\nMentor, Minnesota\r\n637\r\nMiddle River, Minnesota\r\n222\r\nMiltona, Minnesota\r\n943\r\nMinerva, Minnesota\r\n657\r\nMission, Minnesota\r\n765\r\nMoorhead, Minnesota\r\n233\r\n236\r\n287\r\n299\r\n790\r\nMoorhead, North Dakota\r\n291\r\nMoose Lake, Minnesota\r\n485\r\nMotley, Minnesota\r\n352\r\nNashwauk, Minnesota\r\n885\r\nNevis, Minnesota\r\n652\r\nNewfolden, Minnesota\r\n874\r\nNew York Mills, Minnesota\r\n385\r\nNickerson, Minnesota\r\n496\r\nNielsville, Minnesota\r\n946\r\nNimrod, Minnesota\r\n472\r\nNisswa, Minnesota\r\n963\r\nNokay Lake, Minnesota\r\n764\r\nNorthome, Minnesota\r\n897\r\nOklee, Minnesota\r\n796\r\nOrr, Minnesota\r\n757\r\nOsage, Minnesota\r\n573\r\nOslo, Minnesota\r\n695\r\nOttertail, Minnesota\r\n367\r\nOuting, Minnesota\r\n792\r\nPalisade, Minnesota\r\n845\r\nPalo, Minnesota\r\n638\r\nParkr Prar, Minnesota\r\n338\r\nPark Rapids, Minnesota\r\n266\r\n732\r\nPelican Rapid, Minnesota\r\n863\r\nPequot Lakes, Minnesota\r\n568\r\nPerham, Minnesota\r\n346\r\n347\r\nPerley, Minnesota\r\n861\r\nPillager, Minnesota\r\n746\r\nPine River, Minnesota\r\n587\r\nPlummer, Minnesota\r\n465\r\nPonemah, Minnesota\r\n554\r\nPuposky, Minnesota\r\n243\r\nRanier, Minnesota\r\n286\r\nRed Lake, Minnesota\r\n679\r\nRed Lake Falls, Minnesota\r\n253\r\nRemer, Minnesota\r\n566\r\nRollag, Minnesota\r\n937\r\nRoosevelt, Minnesota\r\n442\r\nRoseau, Minnesota\r\n463\r\n469\r\nRothsay, Minnesota\r\n867\r\nSabin, Minnesota\r\n789\r\nSebeka, Minnesota\r\n837\r\nShelly, Minnesota\r\n886\r\nShevlin, Minnesota\r\n785\r\nSilver Bay, Minnesota\r\n226\r\n353\r\nSolway, Minnesota\r\n467\r\nSquaw Lake, Minnesota\r\n659\r\nSaint Hilaire, Minnesota\r\n964\r\nSaint Vincent, Minnesota\r\n823\r\nStaples, Minnesota\r\n894\r\nStephen, Minnesota\r\n478\r\nSturgen Lake, Minnesota\r\n372\r\nThf River Falls, Minnesota\r\n681\r\n686\r\n689\r\nTintah, Minnesota\r\n369\r\nTofte, Minnesota\r\n663\r\nTower, Minnesota\r\n753\r\nTurtle River, Minnesota\r\n586\r\nTwin Valley, Minnesota\r\n584\r\nTwo Harbors, Minnesota\r\n830\r\n834\r\nUlen, Minnesota\r\n596\r\nUnderwood, Minnesota\r\n826\r\nUrbank, Minnesota\r\n267\r\nVergas, Minnesota\r\n342\r\nVerndale, Minnesota\r\n445\r\n639\r\nViking, Minnesota\r\n523\r\nVining, Minnesota\r\n769\r\nVirginia, Minnesota\r\n735\r\n741\r\n744\r\n749\r\n750\r\nWadena, Minnesota\r\n631\r\nWalker, Minnesota\r\n547\r\nWarba, Minnesota\r\n492\r\nWarren, Minnesota\r\n745\r\nWarroad, Minnesota\r\n382\r\n386\r\nWaubun, Minnesota\r\n473\r\n734\r\nWawina, Minnesota\r\n488\r\nWendell, Minnesota\r\n458\r\nWhipholt, Minnesota\r\n836\r\nWhite Earth, Minnesota\r\n983\r\nWilliams, Minnesota\r\n783\r\nWinger, Minnesota\r\n938\r\nWolf Lake, Minnesota\r\n538\r\nWolverton, Minnesota\r\n995\r\nWright, Minnesota\r\n357\r\n\u00035Unknown prefix code (218) - Minnesota\r\n"
  },
  {
    "path": "install/regions/regions.219",
    "content": "Akron, Indiana\r\n893\r\nAlbion, Indiana\r\n636\r\nAndrews, Indiana\r\n786\r\nAngola, Indiana\r\n665\r\n668\r\nArcola, Indiana\r\n625\r\nArgos, Indiana\r\n892\r\nAshley, Indiana\r\n587\r\nAtwood, Indiana\r\n858\r\nAuburn, Indiana\r\n925\r\nAvilla, Indiana\r\n897\r\nBerne, Indiana\r\n589\r\nBippus, Indiana\r\n344\r\nBluffton, Indiana\r\n824\r\nBourbon, Indiana\r\n342\r\nBremen, Indiana\r\n546\r\nBristol, Indiana\r\n848\r\nBrook, Indiana\r\n275\r\nBryant, Indiana\r\n997\r\nBuffalo, Indiana\r\n278\r\nBurket, Indiana\r\n491\r\nBurnettsville, Indiana\r\n826\r\nBurrows, Indiana\r\n652\r\nButler, Indiana\r\n868\r\nCamden, Indiana\r\n686\r\nCedar Lake, Indiana\r\n374\r\nChesterton, Indiana\r\n926\r\n928\r\n929\r\nChurubusco, Indiana\r\n693\r\nClaypool, Indiana\r\n566\r\nColumbia City, Indiana\r\n244\r\n248\r\nCorunna, Indiana\r\n281\r\nCraigville, Indiana\r\n565\r\nCromwell, Indiana\r\n856\r\nCrownpoint, Indiana\r\n662\r\n663\r\n765\r\n776\r\nCulver, Indiana\r\n842\r\nDecatur, Indiana\r\n724\r\n728\r\nDeer Creek, Indiana\r\n859\r\nDemotte, Indiana\r\n987\r\nDunlap, Indiana\r\n875\r\nDyer, Indiana\r\n322\r\n864\r\n865\r\nEast Chicago, Indiana\r\n378\r\n391\r\n392\r\n397\r\n398\r\n399\r\nElkhart, Indiana\r\n262\r\n264\r\n265\r\n266\r\n293\r\n294\r\n295\r\n296\r\n522\r\n523\r\nEtna, Indiana\r\n799\r\nFlora, Indiana\r\n967\r\nFort Wayne, Indiana\r\n420\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n439\r\n441\r\n447\r\n451\r\n452\r\n455\r\n456\r\n458\r\n460\r\n461\r\n466\r\n467\r\n470\r\n471\r\n478\r\n479\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n489\r\n492\r\n497\r\n744\r\n745\r\n747\r\n750\r\nFrancesville, Indiana\r\n567\r\nFremont, Indiana\r\n495\r\nFulton, Indiana\r\n857\r\nGalveston, Indiana\r\n699\r\nGarrett, Indiana\r\n357\r\nGary, Indiana\r\n730\r\n741\r\n742\r\n743\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n938\r\n939\r\n944\r\n949\r\n977\r\n980\r\n981\r\n985\r\nGeneva, Indiana\r\n368\r\nGoodland, Indiana\r\n297\r\nGoshen, Indiana\r\n533\r\n534\r\n535\r\n536\r\n537\r\nHamilton, Indiana\r\n488\r\nHamlet, Indiana\r\n867\r\nHammond, Indiana\r\n844\r\n845\r\n852\r\n853\r\n931\r\n932\r\n933\r\n937\r\n989\r\nHanna, Indiana\r\n797\r\nHarlan, Indiana\r\n657\r\nHebron, Indiana\r\n996\r\nHighland, Indiana\r\n836\r\n838\r\n922\r\n923\r\n924\r\n972\r\nHobart, Indiana\r\n942\r\n947\r\nHowe, Indiana\r\n562\r\nHuntertown, Indiana\r\n637\r\nHuntington, Indiana\r\n356\r\n358\r\n359\r\nIdaville, Indiana\r\n943\r\nKendallville, Indiana\r\n347\r\nKentland, Indiana\r\n474\r\nKewanna, Indiana\r\n653\r\nKimmell, Indiana\r\n635\r\nKnox, Indiana\r\n772\r\nKouts, Indiana\r\n766\r\nLa Crosse, Indiana\r\n754\r\nLa Porte, Indiana\r\n324\r\n325\r\n326\r\n362\r\n363\r\n369\r\n393\r\nLagrange, Indiana\r\n463\r\nLagro, Indiana\r\n782\r\nLapaz, Indiana\r\n784\r\nLarwill, Indiana\r\n327\r\nLaud, Indiana\r\n396\r\nLeesburg, Indiana\r\n453\r\nLeo, Indiana\r\n627\r\nLiberty Center, Indiana\r\n694\r\nLigonier, Indiana\r\n894\r\nLinn Grove, Indiana\r\n334\r\nLake For Sns, Indiana\r\n988\r\nLake Station, Indiana\r\n962\r\n963\r\nLake Village, Indiana\r\n992\r\nLogansport, Indiana\r\n720\r\n721\r\n722\r\n725\r\n727\r\n729\r\n732\r\n735\r\n737\r\n739\r\n753\r\nLowell, Indiana\r\n552\r\n696\r\nLucerne, Indiana\r\n889\r\nMacy, Indiana\r\n382\r\nMarkle, Indiana\r\n758\r\nMedaryville, Indiana\r\n843\r\nMentone, Indiana\r\n353\r\nMerrillville, Indiana\r\n647\r\n736\r\n738\r\n751\r\n752\r\n755\r\n756\r\n757\r\n769\r\n791\r\n793\r\n794\r\nMichigan City, Indiana\r\n872\r\n873\r\n874\r\n878\r\n879\r\nMiddlebury, Indiana\r\n825\r\nMilford, Indiana\r\n658\r\nMillersburg, Indiana\r\n642\r\nMillwood, Indiana\r\n646\r\nMishawaka, Indiana\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\nMongo, Indiana\r\n367\r\nMonon, Indiana\r\n253\r\nMonroe, Indiana\r\n692\r\nMonroeville, Indiana\r\n623\r\nMonterey, Indiana\r\n542\r\nMonticello, Indiana\r\n583\r\nMorocco, Indiana\r\n285\r\nMount Ayr, Indiana\r\n394\r\nNappanee, Indiana\r\n773\r\nNew Haven, Indiana\r\n493\r\n748\r\n749\r\nNew Paris, Indiana\r\n831\r\nNewcarlisle, Indiana\r\n654\r\nNorth Judson, Indiana\r\n896\r\nNorth Liberty, Indiana\r\n656\r\nNorth Manchester, Indiana\r\n982\r\nNorth Webster, Indiana\r\n834\r\nOrland, Indiana\r\n829\r\nOsceola, Indiana\r\n674\r\n679\r\nOssian, Indiana\r\n622\r\nPennville, Indiana\r\n731\r\nPetroleum, Indiana\r\n346\r\nPierceton, Indiana\r\n594\r\nPleasant Lake, Indiana\r\n475\r\nPleasant Mills, Indiana\r\n592\r\nPlymouth, Indiana\r\n935\r\n936\r\nPoe Hoagld, Indiana\r\n639\r\nPokagon, Indiana\r\n833\r\nPortage, Indiana\r\n762\r\n763\r\n771\r\n787\r\nPortland, Indiana\r\n726\r\nPreble, Indiana\r\n547\r\nRemington, Indiana\r\n261\r\nRensselaer, Indiana\r\n863\r\n866\r\nReservoir, Indiana\r\n468\r\nReynolds, Indiana\r\n984\r\nRoanoke, Indiana\r\n672\r\n673\r\nRochester, Indiana\r\n223\r\n224\r\nRolling Prairie, Indiana\r\n778\r\nRoselawn, Indiana\r\n345\r\nRoyal Center, Indiana\r\n643\r\nSouth Bend, Indiana\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n239\r\n271\r\n272\r\n273\r\n277\r\n280\r\n282\r\n283\r\n284\r\n286\r\n287\r\n288\r\n289\r\n291\r\n292\r\n298\r\n299\r\n520\r\n555\r\n556\r\n631\r\n634\r\nSalamonia, Indiana\r\n335\r\nSan Pierre, Indiana\r\n828\r\nShipshewna, Indiana\r\n768\r\nSidney, Indiana\r\n839\r\nSilverlake, Indiana\r\n352\r\nSouth Milford, Indiana\r\n351\r\nSouth Whitley, Indiana\r\n723\r\nSouth Bendm Indiana\r\n556\r\nSpencerville, Indiana\r\n238\r\nSaint Joe, Indiana\r\n337\r\nSaint John, Indiana\r\n365\r\nStar City, Indiana\r\n595\r\nSyracuse, Indiana\r\n457\r\nTippecanoe, Indiana\r\n498\r\nTocsin, Indiana\r\n597\r\nTopeka, Indiana\r\n593\r\nTri Lakes, Indiana\r\n691\r\nTwelve Mile, Indiana\r\n664\r\nUniondale, Indiana\r\n543\r\nUnionmills, Indiana\r\n767\r\nUrbana, Indiana\r\n774\r\nValparaiso, Indiana\r\n230\r\n241\r\n462\r\n464\r\n465\r\n476\r\n477\r\n531\r\nWabash, Indiana\r\n563\r\n568\r\n569\r\nWakarusa, Indiana\r\n862\r\nWalkerton, Indiana\r\n586\r\nWalton, Indiana\r\n626\r\nWanatah, Indiana\r\n733\r\nWarren, Indiana\r\n375\r\nWarsaw, Indiana\r\n267\r\n268\r\n269\r\nWaterloo, Indiana\r\n837\r\nWawaka, Indiana\r\n761\r\n780\r\nWestville, Indiana\r\n785\r\nWheatfield, Indiana\r\n956\r\nWheeler, Indiana\r\n759\r\nWhiting, Indiana\r\n473\r\n659\r\nWinamac, Indiana\r\n946\r\nWinona Lake, Indiana\r\n372\r\nWolcott, Indiana\r\n279\r\nWolcottville, Indiana\r\n854\r\nWoodburn, Indiana\r\n632\r\nWyatt, Indiana\r\n633\r\nYeoman, Indiana\r\n965\r\nZanesville, Indiana\r\n638\r\n\u00035Unknown prefix code (219) - Indiana\r\n"
  },
  {
    "path": "install/regions/regions.228",
    "content": "Somewhere in Miss., Mississippi\r\n202\r\n209\r\n212\r\n214\r\n216\r\n217\r\n218\r\n219\r\n297\r\n312\r\n381\r\n386\r\n396\r\n463\r\n470\r\n493\r\n516\r\n518\r\n522\r\n523\r\n539\r\n555\r\n574\r\n575\r\n586\r\n594\r\n602\r\n604\r\n617\r\n669\r\n670\r\n691\r\n695\r\n696\r\n697\r\n701\r\n702\r\n712\r\n770\r\n808\r\n813\r\n818\r\n822\r\n860\r\n880\r\n883\r\n889\r\n931\r\n979\r\n990\r\nBay Saint Louis, Mississippi\r\n466\r\n467\r\n688\r\n689\r\nBiloxi, Mississippi\r\n374\r\n377\r\n385\r\n388\r\n392\r\n432\r\n435\r\n436\r\nGulfport, Mississippi\r\n380\r\n850\r\n870\r\n871\r\n831\r\n832\r\n861\r\n863\r\n864\r\n865\r\n867\r\n868\r\n896\r\n897\r\n993\r\nHurley, Mississippi\r\n588\r\nJackson, Mississippi\r\n760\r\nMoss Point, Mississippi\r\n474\r\n475\r\nOcean Springs, Mississippi\r\n872\r\n875\r\nPascagoula, Mississippi\r\n497\r\n761\r\n762\r\n769\r\n935\r\n938\r\n994\r\n934\r\nPaschristn, Mississippi\r\n255\r\n452\r\nPearlington, Mississippi\r\n533\r\nTanerwilms, Mississippi\r\n641\r\nVancleave, Mississippi\r\n826\r\n\u00035Unknown prefix code (228) - Mississippi\r\n"
  },
  {
    "path": "install/regions/regions.252",
    "content": "Aberdeen, North Carolina\r\n944\r\nAhoskie, North Carolina\r\n332\r\nAnderson, North Carolina\r\n421\r\nAtlantic, North Carolina\r\n225\r\nAulander, North Carolina\r\n345\r\nAurora, North Carolina\r\n322\r\nAyden, North Carolina\r\n746\r\nBailey, North Carolina\r\n235\r\nBath, North Carolina\r\n923\r\nBayboro, North Carolina\r\n745\r\nBeaufort, North Carolina\r\n728\r\nBelhaven, North Carolina\r\n943\r\nBenson, North Carolina\r\n207\r\n820\r\n894\r\nBethel, North Carolina\r\n825\r\nBoomer, North Carolina\r\n921\r\nBurlington, North Carolina\r\n538\r\nBuxton, North Carolina\r\n986\r\n995\r\nCandor, North Carolina\r\n974\r\nCarolina Beach, North Carolina\r\n458\r\nCarthage, North Carolina\r\n947\r\nChampion, North Carolina\r\n973\r\nClingman, North Carolina\r\n984\r\nCoinjock, North Carolina\r\n453\r\nColerain, North Carolina\r\n356\r\nColumbia, North Carolina\r\n796\r\nConway, North Carolina\r\n585\r\nCourtney, North Carolina\r\n463\r\nCreswell, North Carolina\r\n797\r\nEden, North Carolina\r\n635\r\nEdenton, North Carolina\r\n482\r\nElizabeth City, North Carolina\r\n331\r\n335\r\n338\r\nElkin, North Carolina\r\n526\r\nElm City, North Carolina\r\n236\r\nEnfield, North Carolina\r\n445\r\nEngelhard, North Carolina\r\n925\r\nFarmville, North Carolina\r\n753\r\nFayetteville, North Carolina\r\n323\r\n396\r\n423\r\n436\r\nFountain, North Carolina\r\n749\r\nGatesville, North Carolina\r\n357\r\nGibsonville, North Carolina\r\n449\r\nGreensboro, North Carolina\r\n230\r\n271\r\n272\r\n273\r\n274\r\n275\r\n279\r\n282\r\n288\r\n292\r\n294\r\n299\r\n333\r\n334\r\n337\r\n339\r\n370\r\n373\r\n375\r\n378\r\n379\r\n545\r\n547\r\n574\r\n621\r\n632\r\n665\r\n668\r\n674\r\n680\r\n691\r\n697\r\n698\r\n852\r\n854\r\n855\r\nGreenville, North Carolina\r\n355\r\n551\r\n752\r\n756\r\n757\r\n758\r\n830\r\n931\r\nGrifton, North Carolina\r\n524\r\nHalifax, North Carolina\r\n583\r\nHamilton, North Carolina\r\n798\r\nHarrells, North Carolina\r\n532\r\nHavelock, North Carolina\r\n444\r\n447\r\n466\r\nHenderson, North Carolina\r\n213\r\n430\r\n438\r\n492\r\nHerring, North Carolina\r\n564\r\nHertford, North Carolina\r\n426\r\nHigh Point, North Carolina\r\n431\r\n434\r\n454\r\nHighfalls, North Carolina\r\n464\r\nHollyridge, North Carolina\r\n329\r\nJackson Creek, North Carolina\r\n241\r\nJackson, North Carolina\r\n534\r\nJacksonville, North Carolina\r\n347\r\nKernersville, North Carolina\r\n996\r\nKill Devil Hills, North Carolina\r\n255\r\n261\r\n441\r\n480\r\nKinston, North Carolina\r\n522\r\n523\r\n527\r\n559\r\nKnotts Isle, North Carolina\r\n429\r\nLa Grange, North Carolina\r\n566\r\nLewiston, North Carolina\r\n348\r\nLittleton, North Carolina\r\n586\r\nLucama, North Carolina\r\n239\r\nLumberton, North Carolina\r\n671\r\nMamie, North Carolina\r\n491\r\nManteo, North Carolina\r\n473\r\nMarshallburg, North Carolina\r\n729\r\nMilton, North Carolina\r\n234\r\nMoorehead City, North Carolina\r\n240\r\n247\r\n726\r\nMoss Hill, North Carolina\r\n569\r\nMoyock, North Carolina\r\n232\r\n435\r\nMurfreesboro, North Carolina\r\n398\r\nNashville, North Carolina\r\n459\r\nNew Bern, North Carolina\r\n633\r\n636\r\n637\r\n638\r\nNewport, North Carolina\r\n223\r\n808\r\nNorlina, North Carolina\r\n456\r\nOcracoke, North Carolina\r\n928\r\nOldtown, North Carolina\r\n924\r\nOriental, North Carolina\r\n249\r\nPembroke, North Carolina\r\n521\r\nPike Road, North Carolina\r\n935\r\nPinetops, North Carolina\r\n827\r\nPinetown, North Carolina\r\n927\r\nPiney Woods, North Carolina\r\n297\r\nPink Hill, North Carolina\r\n568\r\nPisgah, North Carolina\r\n381\r\nPlymouth, North Carolina\r\n793\r\nPollocksville, North Carolina\r\n224\r\nRamseur, North Carolina\r\n824\r\nReidsville, North Carolina\r\n634\r\nRich Square, North Carolina\r\n539\r\nRoanoke Rapids, North Carolina\r\n535\r\n537\r\nRobbins, North Carolina\r\n948\r\nRobersonville, North Carolina\r\n795\r\nRocky Mount, North Carolina\r\n442\r\n443\r\n446\r\n450\r\n937\r\n972\r\n977\r\n985\r\nRoseboro, North Carolina\r\n525\r\nRowland, North Carolina\r\n422\r\nRoxobel, North Carolina\r\n344\r\nRuffin, North Carolina\r\n939\r\nSanford, North Carolina\r\n774\r\n775\r\n776\r\nScotland Neck, North Carolina\r\n826\r\nSeaboard, North Carolina\r\n589\r\nShallotte, North Carolina\r\n754\r\nShiloh, North Carolina\r\n336\r\nSidney, North Carolina\r\n964\r\nSix Run, North Carolina\r\n533\r\nSnow Hill, North Carolina\r\n747\r\nSouth Mills, North Carolina\r\n771\r\nSouthport, North Carolina\r\n457\r\nSpringhope, North Carolina\r\n478\r\nStantonsburg, North Carolina\r\n238\r\nSunbury, North Carolina\r\n465\r\nSwan Quarter, North Carolina\r\n926\r\nSwansboro, North Carolina\r\n354\r\n393\r\nTarboro, North Carolina\r\n641\r\n823\r\nThomasville, North Carolina\r\n475\r\nTimberlake, North Carolina\r\n364\r\nTopsail Island, North Carolina\r\n328\r\nTrenton, North Carolina\r\n448\r\nVanceboro, North Carolina\r\n244\r\nVass, North Carolina\r\n245\r\nWarrenton, North Carolina\r\n257\r\nWarsaw, North Carolina\r\n293\r\nWashington, North Carolina\r\n946\r\n975\r\nWaves, North Carolina\r\n987\r\nWeeksville, North Carolina\r\n330\r\nWelch, North Carolina\r\n221\r\nWeldon, North Carolina\r\n536\r\nWhitakers, North Carolina\r\n437\r\nWilliamston, North Carolina\r\n792\r\nWilmington, North Carolina\r\n395\r\n452\r\n520\r\n791\r\n799\r\nWilson, North Carolina\r\n237\r\n243\r\n291\r\n399\r\nWindsor, North Carolina\r\n794\r\nWinston Salem, North Carolina\r\n720\r\n723\r\n724\r\n725\r\n727\r\n741\r\n744\r\n766\r\nWinton, North Carolina\r\n358\r\nWest Jefferson, North Carolina\r\n246\r\nWoodland, North Carolina\r\n587\r\nWoodville, North Carolina\r\n264\r\nWrightville Beach, North Carolina\r\n256\r\n\u00035Unknown prefix code (252) - North Carolina\r\n"
  },
  {
    "path": "install/regions/regions.253",
    "content": "Aberdeen, Washington\r\n538\r\nArletta, Washington\r\n265\r\nArlington\u00031/\u00032Silvana, Washington\r\n435\r\nAuburn, Washington\r\n350\r\n351\r\n709\r\n735\r\n804\r\n833\r\n931\r\n939\r\nAshford, Washington\r\n569\r\nBattleground, Washington\r\n687\r\nBirch Bay, Washington\r\n371\r\nBremerton, Washington\r\n404\r\n476\r\n792\r\nBrinnon, Washington\r\n796\r\nBuccoda, Washington\r\n278\r\nBurley, Washington\r\n857\r\nCamas, Washington\r\n835\r\nCastlerock, Washington\r\n274\r\nCenter, Washington\r\n732\r\nChehalis, Washington\r\n262\r\n269\r\n520\r\n740\r\n748\r\nConcrete\u00031/\u00032Rockport, Washington\r\n853\r\nConway, Washington\r\n445\r\nCoupeville, Washington\r\n678\r\nDeming, Washington\r\n592\r\nDes Moines, Washington\r\n529\r\n661\r\n838\r\n839\r\n874\r\n941\r\n946\r\nEverson, Washington\r\n966\r\nFederal Way, Washington\r\n874\r\nFerndale, Washington\r\n380\r\nFox Island, Washington\r\n549\r\nGarniner, Washington\r\n797\r\nGig Harbor, Washington\r\n530\r\n851\r\n858\r\nGraham, Washington\r\n846\r\n847\r\nHansville, Washington\r\n638\r\nHumptulips, Washington\r\n987\r\nKent, Washington\r\n639\r\n813\r\n395\r\n630\r\n631\r\n657\r\n773\r\n850\r\n852\r\n854\r\n859\r\n872\r\nKirkland, Washington\r\n903\r\nLake Quinault, Washington\r\n288\r\nLakebay, Washington\r\n884\r\nLyman\u00031/\u00032Hamilton, Washington\r\n826\r\nMorton, Washington\r\n496\r\nMossyrock, Washington\r\n983\r\nMount Vernon, Washington\r\n428\r\nPe Ell, Washington\r\n291\r\nPoint Roberts, Washington\r\n945\r\nPort Angeles, Washington\r\n460\r\nPoulsbo, Washington\r\n779\r\nPuget Sound, Washington\r\n875\r\nPuyallup, Washington\r\n770\r\n840\r\n841\r\n845\r\n848\r\nRaymond, Washington\r\n942\r\nRidgefield, Washington\r\n887\r\nRoy, Washington\r\n843\r\nSedro Woolley, Washington\r\n856\r\nSequim, Washington\r\n683\r\nSilverdale, Washington\r\n692\r\nSkykomish, Washington\r\n677\r\nSouth Bend, Washington\r\n875\r\nStandwood, Washington\r\n629\r\nSteven's Pass, Washington\r\n973\r\nSumas, Washington\r\n988\r\nSumner, Washington\r\n862\r\n863\r\n891\r\nTacoma, Washington\r\n229\r\n280\r\n305\r\n370\r\n471\r\n539\r\n589\r\n761\r\n272\r\n279\r\n381\r\n383\r\n472\r\n473\r\n474\r\n475\r\n531\r\n535\r\n536\r\n537\r\n552\r\n564\r\n565\r\n566\r\n572\r\n581\r\n582\r\n584\r\n588\r\n591\r\n593\r\n594\r\n596\r\n597\r\n627\r\n751\r\n752\r\n756\r\n759\r\n922\r\n924\r\n925\r\n926\r\n927\r\n952\r\n964\r\n967\r\n968\r\n984\r\nVancouver, Washington\r\n573\r\n693\r\n798\r\n896\r\nWoodland, Washington\r\n225\r\nYacolt, Washington\r\n686\r\n\u00035Unknown prefix code (253) - Washington\r\n"
  },
  {
    "path": "install/regions/regions.256",
    "content": "Albertville, Alabama\r\n878\r\n891\r\nAlexander City, Alabama\r\n212\r\n234\r\n329\r\nAnniston, Alabama\r\n231\r\n235\r\n236\r\n237\r\n238\r\n239\r\n453\r\n820\r\n848\r\n831\r\n835\r\nAthens, Alabama\r\n230\r\n232\r\n233\r\n729\r\nCullman, Alabama\r\n708\r\n734\r\n737\r\n739\r\n747\r\n796\r\nFlorence, Alabama\r\n718\r\n740\r\n760\r\n764\r\n766\r\n767\r\nFort Payne, Alabama\r\n845\r\n997\r\nGadsden, Alabama\r\n390\r\n490\r\n543\r\n545\r\n546\r\n547\r\n549\r\n413\r\n442\r\n492\r\n494\r\nHuntsville, Alabama\r\n220\r\n430\r\n517\r\n518\r\n532\r\n533\r\n534\r\n535\r\n536\r\n539\r\n544\r\n551\r\n650\r\n651\r\n656\r\n720\r\n721\r\n722\r\n726\r\n830\r\n837\r\n842\r\n851\r\n852\r\n859\r\n876\r\n880\r\n881\r\n882\r\n883\r\n890\r\n895\r\n920\r\n955\r\n508\r\n603\r\n313\r\n707\r\nSylacauga, Alabama\r\n208\r\n245\r\n249\r\nTallaadega, Alabama\r\n268\r\n362\r\n761\r\nWedowee, Alabama\r\n357\r\n\u00035Unknown prefix code (256) - Alabama\r\n"
  },
  {
    "path": "install/regions/regions.270",
    "content": "Bonnieville, Kentucky\r\n531\r\nBowling Green, Kentucky\r\n495\r\n745\r\n777\r\n781\r\n782\r\n784\r\n792\r\n793\r\n796\r\n842\r\n843\r\nBuffalo, Kentucky\r\n325\r\nCampbellsville, Kentucky\r\n465\r\n789\r\nCanmer, Kentucky\r\n528\r\nCave City, Kentucky\r\n773\r\nCecilia, Kentucky\r\n862\r\nElizabethtown, Kentucky\r\n723\r\n734\r\n735\r\n737\r\n739\r\n763\r\n765\r\n766\r\n769\r\nGlasgow, Kentucky\r\n576\r\n651\r\n659\r\n678\r\nGlendale, Kentucky\r\n369\r\nGreensburg, Kentucky\r\n932\r\nHodgenville, Kentucky\r\n358\r\nMagnolia, Kentucky\r\n324\r\nMunfordville, Kentucky\r\n524\r\nOwensboro, Kentucky\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n925\r\n926\r\n929\r\nPaducah, Kentucky\r\n441\r\n442\r\n443\r\n444\r\n554\r\n559\r\n575\r\n744\r\n898\r\nSonora, Kentucky\r\n369\r\nUpton, Kentucky\r\n369\r\n\u00035Unknown prefix code (270) - Kentucky\r\n"
  },
  {
    "path": "install/regions/regions.281",
    "content": "Houston, Texas\r\n687\r\n\u00035Unknown prefix code (281) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.301",
    "content": "Ashton, Maryland\r\n421\r\n549\r\n570\r\n774\r\n940\r\n854\r\nBaltimore, Maryland\r\n555\r\n878\r\n954\r\nBeltsville, Maryland\r\n953\r\nBerwyn, Maryland\r\n206\r\n207\r\n220\r\n286\r\n303\r\n308\r\n344\r\n345\r\n369\r\n409\r\n419\r\n425\r\n441\r\n474\r\n489\r\n506\r\n507\r\n510\r\n513\r\n552\r\n595\r\n615\r\n688\r\n701\r\n709\r\n901\r\n902\r\n914\r\n923\r\n935\r\n937\r\n953\r\n982\r\nBethesda, Maryland\r\n214\r\n215\r\n221\r\n227\r\n229\r\n275\r\n295\r\n318\r\n320\r\n335\r\n365\r\n380\r\n402\r\n406\r\n412\r\n469\r\n480\r\n492\r\n493\r\n496\r\n503\r\n530\r\n564\r\n571\r\n594\r\n648\r\n652\r\n654\r\n656\r\n657\r\n661\r\n667\r\n718\r\n742\r\n803\r\n814\r\n897\r\n907\r\n913\r\n919\r\n941\r\n951\r\n964\r\n986\r\nBowie-Glenn Date, Maryland\r\n249\r\n261\r\n262\r\n352\r\n390\r\n464\r\n470\r\n621\r\n629\r\n677\r\n794\r\n805\r\n912\r\n970\r\n973\r\nBittinger, Maryland\r\n245\r\nBrandywine, Maryland\r\n579\r\n782\r\nBrunswick, Maryland\r\n834\r\nBuckeystown, Maryland\r\n874\r\nBurke, Maryland\r\n608\r\nCamp Springs, Maryland\r\n599\r\nCapitol Heights, Maryland\r\n336\r\n350\r\n420\r\n423\r\n449\r\n499\r\n568\r\n669\r\n702\r\n735\r\n736\r\n763\r\n808\r\n817\r\n883\r\n899\r\n925\r\n967\r\n981\r\nClear Springs, Maryland\r\n842\r\nClinton, Maryland\r\n238\r\n297\r\n856\r\n868\r\n888\r\nCumberland, Maryland\r\n697\r\n707\r\n722\r\n724\r\n729\r\n759\r\n777\r\nDamascus, Maryland\r\n253\r\n414\r\n607\r\n607\r\n607\r\n831\r\n831\r\n831\r\nEmmitsburg, Maryland\r\n447\r\nFlintstone, Maryland\r\n478\r\nFrederick, Maryland\r\n401\r\n473\r\n606\r\n619\r\n620\r\n662\r\n663\r\n694\r\n695\r\n696\r\n698\r\n815\r\n846\r\n898\r\nFriendsville, Maryland\r\n746\r\nFrostburg, Maryland\r\n689\r\nGaithersburg, Maryland\r\n208\r\n216\r\n330\r\n540\r\n869\r\n916\r\n926\r\n963\r\n972\r\n977\r\n990\r\nGrantsville, Maryland\r\n895\r\nHagerstown, Maryland\r\n331\r\n491\r\n582\r\n714\r\n733\r\n739\r\n790\r\n791\r\n797\r\nHancock, Maryland\r\n678\r\nHighfield, Maryland\r\n241\r\nHughesville, Maryland\r\n274\r\nHyattsville, Maryland\r\n209\r\n239\r\n277\r\n306\r\n314\r\n322\r\n341\r\n386\r\n403\r\n406\r\n422\r\n436\r\n454\r\n459\r\n532\r\n559\r\n577\r\n618\r\n699\r\n731\r\n772\r\n773\r\n779\r\n851\r\n853\r\n864\r\n927\r\n985\r\nIndianhead, Maryland\r\n375\r\n743\r\nKeedysville, Maryland\r\n432\r\nKensington, Maryland\r\n230\r\n231\r\n413\r\n431\r\n443\r\n460\r\n468\r\n649\r\n770\r\n816\r\n871\r\n881\r\n929\r\n933\r\n942\r\n946\r\n949\r\n984\r\nKitzmiller, Maryland\r\n453\r\nLa Plata, Maryland\r\n934\r\nLaurel, Maryland\r\n210\r\n317\r\n490\r\n497\r\n498\r\n604\r\n725\r\n776\r\n596\r\n596\r\nLayhill, Maryland\r\n236\r\n384\r\n438\r\n598\r\n847\r\n879\r\n890\r\n924\r\n989\r\nLeonardtown, Maryland\r\n373\r\n475\r\n769\r\n904\r\nLonaconing, Maryland\r\n463\r\nLexingpk Gtml, Maryland\r\n737\r\n826\r\n862\r\n863\r\n994\r\nMarlboro, Maryland\r\n627\r\n855\r\n952\r\nMc Coole, Maryland\r\n786\r\nMechanicsville, Maryland\r\n884\r\nMiddletown, Maryland\r\n371\r\nMount Airy, Maryland\r\n829\r\nMount Ranier, Maryland\r\n277\r\nMount Savage, Maryland\r\n264\r\nMyersville, Maryland\r\n293\r\n416\r\n487\r\nNanjemoy, Maryland\r\n246\r\nNew Market, Maryland\r\n865\r\nNorth Potomac, Maryland\r\n948\r\nOakland, Maryland\r\n334\r\n387\r\n501\r\n616\r\nOdenton, Maryland\r\n677\r\nOlney, Maryland\r\n570\r\nOxon Hill, Maryland\r\n203\r\n248\r\n283\r\n292\r\n505\r\n567\r\n630\r\n749\r\n753\r\n839\r\n843\r\n870\r\n894\r\nPoolesville, Maryland\r\n349\r\nRidge, Maryland\r\n872\r\nRising Sun, Maryland\r\n658\r\nRockville, Maryland\r\n212\r\n217\r\n240\r\n251\r\n258\r\n279\r\n294\r\n299\r\n309\r\n340\r\n353\r\n417\r\n424\r\n428\r\n517\r\n518\r\n548\r\n590\r\n601\r\n640\r\n670\r\n738\r\n762\r\n840\r\n903\r\n921\r\n948\r\n975\r\n983\r\nSilver Spring, Maryland\r\n270\r\n367\r\n394\r\n415\r\n427\r\n431\r\n434\r\n439\r\n445\r\n495\r\n502\r\n504\r\n509\r\n517\r\n518\r\n520\r\n565\r\n572\r\n580\r\n585\r\n587\r\n588\r\n589\r\n593\r\n608\r\n622\r\n641\r\n650\r\n651\r\n680\r\n681\r\n704\r\n713\r\n717\r\n754\r\n757\r\n758\r\n807\r\n873\r\n878\r\n891\r\n905\r\n908\r\n930\r\n980\r\nSmithsburg, Maryland\r\n824\r\nThurmont, Maryland\r\n271\r\nTompkinsville, Maryland\r\n259\r\nWaldorf, Maryland\r\n609\r\n645\r\n705\r\n809\r\n818\r\n932\r\n870\r\nWalkersville, Maryland\r\n845\r\nWestern Point, Maryland\r\n359\r\nWillamsport, Maryland\r\n223\r\n\u00035Unknown prefix code (301) - Maryland\r\n"
  },
  {
    "path": "install/regions/regions.302",
    "content": "Angola, Delaware\r\n945\r\n947\r\nBridgeville, Delaware\r\n337\r\nCamden, Delaware\r\n270\r\n697\r\n698\r\nDagsboro, Delaware\r\n732\r\nDelaware City, Delaware\r\n834\r\n836\r\nDelmar, Delaware\r\n846\r\nDover, Delaware\r\n666\r\n670\r\n672\r\n674\r\n677\r\n678\r\n734\r\n736\r\n739\r\n735\r\nFrederica, Delaware\r\n335\r\nGeorgetown, Delaware\r\n542\r\n822\r\n855\r\n856\r\nGreenwood, Delaware\r\n349\r\nGumboro, Delaware\r\n238\r\nHarrington, Delaware\r\n398\r\nHartly, Delaware\r\n492\r\nHockessin, Delaware\r\n234\r\n239\r\nHolly Oak, Delaware\r\n475\r\n529\r\n791\r\n792\r\n798\r\nLaurel, Delaware\r\n875\r\nLewes, Delaware\r\n644\r\n645\r\nMiddletown, Delaware\r\n378\r\nMilford, Delaware\r\n422\r\n424\r\n441\r\n745\r\nMillsboro, Delaware\r\n934\r\nMilton, Delaware\r\n684\r\nNew Castle, Delaware\r\n322\r\n323\r\n324\r\n325\r\n328\r\n740\r\n750\r\nNewark, Delaware\r\n292\r\n452\r\n457\r\n458\r\n623\r\n733\r\n831\r\n837\r\n366\r\n368\r\n451\r\n453\r\n454\r\n455\r\n456\r\n731\r\n737\r\n738\r\nNewport, Delaware\r\n633\r\n892\r\n992\r\n994\r\n995\r\n996\r\n998\r\n999\r\nOcean View, Delaware\r\n537\r\n539\r\nPhcz 1, Pa, Delaware\r\n555\r\nRehoboth, Delaware\r\n226\r\n227\r\nSeaford, Delaware\r\n628\r\n629\r\nSelbyville, Delaware\r\n436\r\nSmyrna, Delaware\r\n659\r\n653\r\nViola, Delaware\r\n284\r\nWilmington, Delaware\r\n320\r\n421\r\n425\r\n426\r\n427\r\n428\r\n429\r\n477\r\n478\r\n479\r\n530\r\n540\r\n571\r\n573\r\n575\r\n576\r\n577\r\n594\r\n634\r\n651\r\n652\r\n654\r\n655\r\n656\r\n657\r\n658\r\n695\r\n761\r\n762\r\n764\r\n772\r\n773\r\n774\r\n884\r\n886\r\n887\r\n888\r\n984\r\nWrangle Hill, Delaware\r\n832\r\n\u00035Unknown prefix code (302) - Delaware\r\n"
  },
  {
    "path": "install/regions/regions.303",
    "content": "Akron, Colorado\r\n345\r\n554\r\nAllens Park, Colorado\r\n747\r\nAllison, Colorado\r\n883\r\nAmherst, Colorado\r\n439\r\nAnton, Colorado\r\n383\r\nArvada, Colorado\r\n412\r\n431\r\n456\r\n467\r\n489\r\n550\r\n650\r\n657\r\n868\r\n940\r\n941\r\n947\r\n420\r\n421\r\n422\r\n423\r\n424\r\n425\r\nAspen, Colorado\r\n544\r\n920\r\n923\r\n925\r\nAult, Colorado\r\n454\r\nAurora, Colorado\r\n338\r\n360\r\n361\r\n363\r\n364\r\n367\r\n676\r\n739\r\n261\r\n342\r\n373\r\n375\r\n340\r\n341\r\n343\r\n344\r\n366\r\n680\r\nBailey, Colorado\r\n838\r\nBasalt, Colorado\r\n927\r\nBayfield, Colorado\r\n884\r\nBennet, Colorado\r\n644\r\nBerthoud, Colorado\r\n532\r\nBoulder, Colorado\r\n543\r\n545\r\n546\r\n440\r\n441\r\n442\r\n443\r\n444\r\n447\r\n449\r\n492\r\n494\r\n497\r\n499\r\n530\r\n541\r\n581\r\n589\r\n786\r\n924\r\n938\r\n939\r\n966\r\nBreckenridge, Colorado\r\n453\r\nBriggsdale, Colorado\r\n656\r\nBrighton, Colorado\r\n637\r\n654\r\n659\r\nBroomfield, Colorado\r\n252\r\n254\r\n255\r\n280\r\n438\r\n460\r\n465\r\n466\r\n469\r\n538\r\nBrush, Colorado\r\n842\r\nByers, Colorado\r\n822\r\nCarbondale, Colorado\r\n963\r\nCastle Rock, Colorado\r\n660\r\n688\r\n681\r\nCedar Edge, Colorado\r\n856\r\nCentral City, Colorado\r\n582\r\nCoal Creek Canyon, Colorado\r\n642\r\nCollbran, Colorado\r\n487\r\nCope, Colorado\r\n357\r\nCortez, Colorado\r\n549\r\n560\r\n564\r\n565\r\nCraig, Colorado\r\n272\r\n326\r\n824\r\nCrawford, Colorado\r\n921\r\nCrested Beaute, Colorado\r\n349\r\nCrook, Colorado\r\n886\r\nDe Beque, Colorado\r\n283\r\nDeckers, Colorado\r\n647\r\nDeer Trail, Colorado\r\n769\r\nDelta, Colorado\r\n874\r\nDenver, Colorado\r\n270\r\n281\r\n331\r\n333\r\n336\r\n337\r\n348\r\n355\r\n378\r\n391\r\n392\r\n455\r\n473\r\n478\r\n553\r\n561\r\n578\r\n584\r\n585\r\n595\r\n633\r\n634\r\n640\r\n672\r\n685\r\n687\r\n727\r\n742\r\n748\r\n764\r\n780\r\n782\r\n871\r\n896\r\n955\r\n965\r\n286\r\n287\r\n288\r\n289\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n320\r\n321\r\n322\r\n324\r\n329\r\n370\r\n372\r\n377\r\n388\r\n393\r\n394\r\n398\r\n399\r\n433\r\n436\r\n446\r\n458\r\n477\r\n480\r\n534\r\n556\r\n571\r\n572\r\n573\r\n575\r\n592\r\n620\r\n623\r\n624\r\n628\r\n629\r\n631\r\n639\r\n691\r\n692\r\n698\r\n722\r\n733\r\n744\r\n753\r\n756\r\n757\r\n758\r\n759\r\n763\r\n765\r\n777\r\n778\r\n787\r\n820\r\n821\r\n825\r\n830\r\n831\r\n832\r\n837\r\n839\r\n844\r\n852\r\n860\r\n861\r\n863\r\n866\r\n869\r\n888\r\n892\r\n893\r\n894\r\n898\r\n899\r\n922\r\n934\r\n935\r\n936\r\n937\r\n964\r\n969\r\n980\r\n985\r\n986\r\n987\r\n988\r\n989\r\nDillon, Colorado\r\n262\r\n389\r\n468\r\n485\r\n668\r\n968\r\nDolores, Colorado\r\n882\r\nDove Creek, Colorado\r\n677\r\nDry Creek, Colorado\r\n220\r\n266\r\n267\r\n290\r\n461\r\n488\r\n540\r\n689\r\n694\r\n721\r\n740\r\n741\r\n770\r\n771\r\n773\r\n779\r\n843\r\n850\r\n889\r\n930\r\nDurango, Colorado\r\n382\r\n946\r\n247\r\n259\r\n385\r\n749\r\nEagle, Colorado\r\n328\r\nEaton, Colorado\r\n834\r\nEckert, Colorado\r\n835\r\nEckley, Colorado\r\n359\r\nEdwards, Colorado\r\n926\r\nElbert, Colorado\r\n648\r\nElizabeth, Colorado\r\n646\r\nEnglewood, Colorado\r\n397\r\n548\r\n643\r\n649\r\n754\r\n760\r\n767\r\n784\r\n790\r\n792\r\n799\r\n826\r\n829\r\n851\r\n855\r\n877\r\n880\r\n890\r\n891\r\n761\r\n762\r\n781\r\n783\r\n788\r\n789\r\n836\r\nErie, Colorado\r\n828\r\nEstes Park, Colorado\r\n586\r\nEvergreen, Colorado\r\n670\r\n674\r\nFleming, Colorado\r\n265\r\nFort Collins, Colorado\r\n204\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n229\r\n282\r\n481\r\n482\r\n484\r\n490\r\n491\r\n493\r\n495\r\n498\r\nFort Morgan, Colorado\r\n380\r\n599\r\n768\r\n867\r\nFraser, Colorado\r\n726\r\nFrederick, Colorado\r\n833\r\nFruita, Colorado\r\n858\r\nFort Lupton, Colorado\r\n857\r\nGateway, Colorado\r\n931\r\nGeorgetown, Colorado\r\n569\r\nGilcrest, Colorado\r\n737\r\nGlenwood Springs, Colorado\r\n379\r\n928\r\n945\r\n948\r\nGolden, Colorado\r\n384\r\n271\r\n273\r\n277\r\n278\r\n279\r\nGranby, Colorado\r\n887\r\nGrand Junction, Colorado\r\n241\r\n242\r\n243\r\n244\r\n245\r\n248\r\n250\r\n260\r\n434\r\n523\r\n853\r\nGrand Lake, Colorado\r\n627\r\nGreeley, Colorado\r\n330\r\n339\r\n346\r\n350\r\n351\r\n352\r\n353\r\n356\r\n376\r\n381\r\n395\r\n396\r\nGrover, Colorado\r\n895\r\nGunnison, Colorado\r\n641\r\n943\r\nGypsum, Colorado\r\n524\r\nHaxtun, Colorado\r\n774\r\nHayden, Colorado\r\n276\r\nHereford, Colorado\r\n496\r\nHillrose, Colorado\r\n847\r\nHolyoke, Colorado\r\n854\r\nHotchkiss, Colorado\r\n872\r\nHoyt, Colorado\r\n432\r\nHot Sulpher Springs, Colorado\r\n725\r\nHudson, Colorado\r\n536\r\nIdaho Springs, Colorado\r\n567\r\n570\r\nIdalia, Colorado\r\n354\r\nIgnacio, Colorado\r\n563\r\nJoes, Colorado\r\n358\r\nJohnstown/Milliken, Colorado\r\n587\r\nJulesburg, Colorado\r\n463\r\n474\r\n547\r\nKeenesburg, Colorado\r\n732\r\nKiowa, Colorado\r\n621\r\nKirk, Colorado\r\n362\r\nKremmling, Colorado\r\n724\r\nLa Salle, Colorado\r\n284\r\nLafayette/louisville, Colorado\r\n661\r\n665\r\n666\r\n673\r\nLake City, Colorado\r\n944\r\nLakewood, Colorado\r\n274\r\n275\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n251\r\nLittleton, Colorado\r\n347\r\n470\r\n486\r\n738\r\n791\r\n793\r\n730\r\n794\r\n795\r\n796\r\n797\r\n798\r\n932\r\n933\r\n971\r\n972\r\n973\r\n977\r\n978\r\n979\r\nLodore, Colorado\r\n365\r\nLongmont, Colorado\r\n651\r\n678\r\n682\r\n683\r\n684\r\n772\r\n775\r\n776\r\nLookout Mountain, Colorado\r\n526\r\nLoveland, Colorado\r\n635\r\n663\r\n667\r\n669\r\n679\r\n962\r\nLyons, Colorado\r\n823\r\nMancos, Colorado\r\n528\r\n533\r\nMarvel, Colorado\r\n588\r\nMaybell, Colorado\r\n269\r\nMc Coy, Colorado\r\n653\r\nMead, Colorado\r\n535\r\nMeeker, Colorado\r\n878\r\nMesa, Colorado\r\n268\r\nMesa Verde, Colorado\r\n529\r\nMontbello, Colorado\r\n371\r\nMontrose, Colorado\r\n240\r\n249\r\nMorrison, Colorado\r\n697\r\nNaturita, Colorado\r\n865\r\nNederland, Colorado\r\n258\r\nNew Castle, Colorado\r\n984\r\nNew Raymer, Colorado\r\n437\r\nNiwot, Colorado\r\n652\r\nNorthglenn, Colorado\r\n450\r\n451\r\n452\r\n457\r\nNorwood, Colorado\r\n327\r\nNucla, Colorado\r\n862\r\n864\r\nNunn, Colorado\r\n897\r\nOak Creek, Colorado\r\n736\r\nOlathe, Colorado\r\n323\r\nOtis, Colorado\r\n246\r\nOuray, Colorado\r\n325\r\nPagosa Springs, Colorado\r\n264\r\nPagosa West, Colorado\r\n731\r\nPalisade, Colorado\r\n464\r\nPaonia, Colorado\r\n527\r\nParachute, Colorado\r\n285\r\nParadox, Colorado\r\n859\r\nParker, Colorado\r\n840\r\n841\r\nPeetz, Colorado\r\n334\r\nPlatteville, Colorado\r\n785\r\nPleasant View, Colorado\r\n562\r\nRangely, Colorado\r\n374\r\n574\r\n675\r\nRed Feather Lakes, Colorado\r\n881\r\nRico, Colorado\r\n967\r\nRidgway, Colorado\r\n626\r\nRifle, Colorado\r\n625\r\nRogen, Colorado\r\n849\r\nSouth Baggs, Colorado\r\n583\r\nSilt, Colorado\r\n876\r\nSilverton, Colorado\r\n387\r\nSmokey Hill, Colorado\r\n690\r\n693\r\n699\r\n766\r\nSouth Big Springs, Colorado\r\n885\r\nSouth Chappel, Colorado\r\n875\r\nSouth Laramie, Colorado\r\n435\r\nSouth Pinebluff, Colorado\r\n257\r\nSouth Sidney, Colorado\r\n253\r\nSouth Cheyenne, Colorado\r\n662\r\nSomerset, Colorado\r\n929\r\nStarsburg, Colorado\r\n622\r\nSteamboat Springs, Colorado\r\n590\r\n734\r\n846\r\n870\r\n879\r\nSterling, Colorado\r\n520\r\n521\r\n522\r\n579\r\n580\r\nStoneham, Colorado\r\n735\r\nSullivan, Colorado\r\n368\r\n369\r\n636\r\n671\r\n695\r\n696\r\n720\r\n743\r\n745\r\n750\r\n751\r\n752\r\n755\r\nTelluride, Colorado\r\n728\r\n729\r\nVail, Colorado\r\n390\r\n471\r\n476\r\n479\r\n827\r\n845\r\n949\r\nVonaseibrt, Colorado\r\n664\r\nWest Venango, Colorado\r\n448\r\nWalden, Colorado\r\n723\r\nWard, Colorado\r\n459\r\nWeldona, Colorado\r\n645\r\nWellington, Colorado\r\n568\r\nWestminster, Colorado\r\n426\r\n427\r\n428\r\n429\r\n430\r\nWiggens, Colorado\r\n483\r\nWillard, Colorado\r\n228\r\nWindsor, Colorado\r\n686\r\nWoodrow, Colorado\r\n386\r\nWray, Colorado\r\n332\r\nYampa, Colorado\r\n638\r\nYuma, Colorado\r\n630\r\n848\r\n\u00035Unknown prefix code (303) - Colorado\r\n"
  },
  {
    "path": "install/regions/regions.304",
    "content": "Alderson, West Virginia\r\n445\r\nAlloy, West Virginia\r\n779\r\nAnawalt, West Virginia\r\n383\r\nAnsted, West Virginia\r\n658\r\nApplegrove, West Virginia\r\n576\r\nArbovale, West Virginia\r\n456\r\nArnoldsbg, West Virginia\r\n655\r\nAthens, West Virginia\r\n384\r\nAugusta, West Virginia\r\n496\r\nBch Bottom, West Virginia\r\n394\r\nBeckley, West Virginia\r\n252\r\n253\r\n254\r\n255\r\n256\r\n673\r\n763\r\n770\r\nBelington, West Virginia\r\n823\r\nBelmont, West Virginia\r\n665\r\nBerkeley Springs, West Virginia\r\n258\r\nBethany, West Virginia\r\n829\r\nBirch River, West Virginia\r\n649\r\nBlacksville, West Virginia\r\n432\r\nBluefield, West Virginia\r\n320\r\n324\r\n325\r\n327\r\nBluewell, West Virginia\r\n589\r\nBradshaw, West Virginia\r\n967\r\nBramwell, West Virginia\r\n248\r\nBranchland, West Virginia\r\n778\r\nBrandywine, West Virginia\r\n249\r\nBridgeport, West Virginia\r\n842\r\nBruceton Mills, West Virginia\r\n379\r\nBrushton, West Virginia\r\n836\r\nBuckhannon, West Virginia\r\n472\r\n473\r\nBuffalo, West Virginia\r\n937\r\nBurlington, West Virginia\r\n289\r\nBurnsville, West Virginia\r\n853\r\nCairo, West Virginia\r\n628\r\nCameron, West Virginia\r\n686\r\nCanaan Valley, West Virginia\r\n866\r\nCapon Bdg, West Virginia\r\n856\r\nChapmanville, West Virginia\r\n855\r\nCharles Town, West Virginia\r\n725\r\n728\r\n340\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n347\r\n348\r\n351\r\n353\r\n357\r\n361\r\n542\r\n545\r\n558\r\n744\r\n746\r\n747\r\n766\r\n768\r\n840\r\n925\r\n926\r\n954\r\n984\r\n988\r\n965\r\n949\r\n722\r\n727\r\n755\r\n759\r\n776\r\n756\r\nCheat Lake, West Virginia\r\n594\r\nChester, West Virginia\r\n387\r\nClarksburg, West Virginia\r\n555\r\n622\r\n623\r\n624\r\n626\r\n627\r\n641\r\nClay, West Virginia\r\n587\r\nClendenin, West Virginia\r\n548\r\nCoalwood, West Virginia\r\n297\r\nCore, West Virginia\r\n879\r\nCowen, West Virginia\r\n226\r\nCraigsville, West Virginia\r\n742\r\nDailey, West Virginia\r\n338\r\nDavis, West Virginia\r\n259\r\nDavy, West Virginia\r\n656\r\nDaybrook, West Virginia\r\n798\r\nDelbarton, West Virginia\r\n475\r\nDunlow, West Virginia\r\n385\r\nDutchridge, West Virginia\r\n968\r\nEast Bank, West Virginia\r\n595\r\nEast Lynn, West Virginia\r\n849\r\nEglon, West Virginia\r\n735\r\nElizabeth, West Virginia\r\n275\r\nElk Garden, West Virginia\r\n446\r\nElkins, West Virginia\r\n636\r\n637\r\n642\r\nEllenboro, West Virginia\r\n869\r\nFairmont, West Virginia\r\n362\r\n363\r\n366\r\n367\r\n534\r\nFairview, West Virginia\r\n449\r\nFalling Waters, West Virginia\r\n274\r\nFarmington, West Virginia\r\n825\r\nFayettevl, West Virginia\r\n574\r\nFlat Top, West Virginia\r\n787\r\nFlemington, West Virginia\r\n739\r\nFollansbee, West Virginia\r\n527\r\nFort Ashby, West Virginia\r\n298\r\nFort Gay, West Virginia\r\n648\r\nFrankford, West Virginia\r\n497\r\nFranklin, West Virginia\r\n358\r\nGary, West Virginia\r\n448\r\nGassaway, West Virginia\r\n364\r\nGauley Bdg, West Virginia\r\n632\r\nGilbert, West Virginia\r\n664\r\nGlendaniel, West Virginia\r\n934\r\nGlenville, West Virginia\r\n462\r\nGormania, West Virginia\r\n693\r\nGrafton, West Virginia\r\n265\r\nGrantsville, West Virginia\r\n354\r\nGreenville, West Virginia\r\n832\r\nGriffithville, West Virginia\r\n524\r\nHacker Valley, West Virginia\r\n493\r\nHamlin, West Virginia\r\n824\r\nHarman, West Virginia\r\n227\r\nHarpersfry, West Virginia\r\n535\r\nHarrisville, West Virginia\r\n643\r\nHedgesville, West Virginia\r\n754\r\nHelen, West Virginia\r\n774\r\nHillsboro, West Virginia\r\n653\r\nHinton, West Virginia\r\n466\r\nHundred, West Virginia\r\n775\r\nHunsz, West Virginia\r\n429\r\n522\r\n523\r\n525\r\n526\r\n528\r\n529\r\n540\r\n544\r\n633\r\n691\r\n696\r\n697\r\n733\r\n736\r\n453\r\nHurricane, West Virginia\r\n562\r\nIaeger, West Virginia\r\n938\r\nInwood, West Virginia\r\n229\r\nIvydale, West Virginia\r\n286\r\nJane Lew, West Virginia\r\n884\r\nJoetown, West Virginia\r\n795\r\nKermit, West Virginia\r\n393\r\nKeyser, West Virginia\r\n788\r\nKimball, West Virginia\r\n585\r\nKincaid, West Virginia\r\n465\r\nKingwood, West Virginia\r\n329\r\nLaurel Point, West Virginia\r\n983\r\nLawford, West Virginia\r\n349\r\nLe Tart, West Virginia\r\n895\r\nLeon, West Virginia\r\n458\r\nLevels, West Virginia\r\n492\r\nLewisburg, West Virginia\r\n645\r\n647\r\nLogan, West Virginia\r\n239\r\n687\r\n752\r\n784\r\n792\r\n946\r\nLost River, West Virginia\r\n434\r\n897\r\nLumberport, West Virginia\r\n584\r\nMadison, West Virginia\r\n369\r\nMan, West Virginia\r\n583\r\nMannington, West Virginia\r\n986\r\nMarlinton, West Virginia\r\n799\r\nMartinsburg, West Virginia\r\n671\r\n263\r\n264\r\n267\r\nMason, West Virginia\r\n773\r\nMatewan, West Virginia\r\n426\r\nMatoaka, West Virginia\r\n467\r\nMaybeury, West Virginia\r\n827\r\nMaysville, West Virginia\r\n749\r\nMeadow Bridge, West Virginia\r\n484\r\nMiddleborne, West Virginia\r\n758\r\nMill Creek, West Virginia\r\n335\r\nMilton, West Virginia\r\n743\r\nMineral Well, West Virginia\r\n489\r\nMontgomery, West Virginia\r\n442\r\nMoorefield, West Virginia\r\n538\r\nMorgantown, West Virginia\r\n282\r\n284\r\n285\r\n288\r\n291\r\n292\r\n293\r\n296\r\n598\r\n599\r\nMount Hope, West Virginia\r\n877\r\nMount Morris, West Virginia\r\n328\r\nMullens, West Virginia\r\n294\r\nNew Cumberland, West Virginia\r\n564\r\nNew Haven, West Virginia\r\n882\r\nNewburg, West Virginia\r\n892\r\nNewton, West Virginia\r\n565\r\nNorth Martinsville, West Virginia\r\n455\r\nNorthfork, West Virginia\r\n862\r\nOak Hill, West Virginia\r\n469\r\n438\r\nOakvale, West Virginia\r\n898\r\nOceana, West Virginia\r\n682\r\nPaden City, West Virginia\r\n337\r\nParsons, West Virginia\r\n478\r\nPaw Paw, West Virginia\r\n947\r\nPennsboro, West Virginia\r\n659\r\nPetersburg, West Virginia\r\n257\r\nPeterstown, West Virginia\r\n753\r\nPhilippi, West Virginia\r\n457\r\nPiedmont, West Virginia\r\n355\r\nPine Grove, West Virginia\r\n889\r\nPineville, West Virginia\r\n732\r\nPrichard, West Virginia\r\n486\r\nPrinceton, West Virginia\r\n425\r\n487\r\n295\r\n420\r\n422\r\n424\r\n428\r\n480\r\n481\r\n482\r\n485\r\n490\r\n679\r\n863\r\nPoint Pleasant, West Virginia\r\n674\r\n675\r\nRavenswood, West Virginia\r\n273\r\nReader, West Virginia\r\n386\r\nReedsville, West Virginia\r\n864\r\nRichwood, West Virginia\r\n846\r\nRidgeley, West Virginia\r\n726\r\n738\r\nRipley, West Virginia\r\n372\r\n377\r\n532\r\nRiverton, West Virginia\r\n567\r\nRivesville, West Virginia\r\n278\r\nRock Cave, West Virginia\r\n924\r\nRockport, West Virginia\r\n474\r\nRomney, West Virginia\r\n822\r\nRowlesburg, West Virginia\r\n454\r\nRupert, West Virginia\r\n392\r\nSalem, West Virginia\r\n782\r\nSardis, West Virginia\r\n783\r\nScottdepot, West Virginia\r\n757\r\nSeth, West Virginia\r\n837\r\nShepherdston, West Virginia\r\n876\r\nShinnston, West Virginia\r\n592\r\nSistersville, West Virginia\r\n652\r\nSmithfield, West Virginia\r\n334\r\nSmithville, West Virginia\r\n477\r\nSnowshoe, West Virginia\r\n572\r\nSophia, West Virginia\r\n683\r\nSpencer, West Virginia\r\n927\r\nSaint Marys, West Virginia\r\n684\r\nSummersville, West Virginia\r\n651\r\n872\r\nSutton, West Virginia\r\n644\r\n678\r\n765\r\nTerra Alta, West Virginia\r\n789\r\nThomas, West Virginia\r\n463\r\nTunnelton, West Virginia\r\n568\r\nUnion, West Virginia\r\n772\r\nUnion Ridge, West Virginia\r\n762\r\nValley Mills, West Virginia\r\n464\r\nValleyhead, West Virginia\r\n339\r\nVan, West Virginia\r\n245\r\nW Milford, West Virginia\r\n745\r\nWadestown, West Virginia\r\n662\r\nWalkersville, West Virginia\r\n452\r\nWallace, West Virginia\r\n796\r\nWalton, West Virginia\r\n577\r\nWar, West Virginia\r\n875\r\nWardensville, West Virginia\r\n874\r\nWayne, West Virginia\r\n272\r\nWebsterspring, West Virginia\r\n847\r\nWeirton, West Virginia\r\n479\r\n670\r\n723\r\n748\r\n797\r\nWelch, West Virginia\r\n436\r\nWellsburg, West Virginia\r\n737\r\nWest Union, West Virginia\r\n873\r\nWeston, West Virginia\r\n266\r\n269\r\nWharton, West Virginia\r\n247\r\nWhitesville, West Virginia\r\n854\r\n232\r\n233\r\n234\r\n238\r\n242\r\n243\r\n277\r\n281\r\n639\r\n336\r\n547\r\n843\r\n845\r\nWhistlepher Spring, West Virginia\r\n536\r\nWiden, West Virginia\r\n332\r\nWilliamson, West Virginia\r\n235\r\nWilliamstown, West Virginia\r\n375\r\nWinfield, West Virginia\r\n586\r\nWorthingtown, West Virginia\r\n287\r\n\u00035Unknown prefix code (304) - West Virginia\r\n"
  },
  {
    "path": "install/regions/regions.305",
    "content": "Big Pine, Florida\r\n872\r\nCoral Springs, Florida\r\n340\r\n341\r\n344\r\n345\r\n346\r\n752\r\n753\r\n755\r\nDavie, Florida\r\n587\r\nDeerfield Beach, Florida\r\n675\r\n690\r\n360\r\n420\r\n421\r\n422\r\n426\r\n427\r\n428\r\n429\r\n480\r\n481\r\n570\r\n574\r\n695\r\n698\r\nFort Lauderdale, Florida\r\n898\r\n286\r\n423\r\n515\r\n748\r\n830\r\n231\r\n240\r\n244\r\n249\r\n321\r\n327\r\n328\r\n351\r\n355\r\n356\r\n357\r\n359\r\n370\r\n384\r\n389\r\n390\r\n396\r\n398\r\n424\r\n452\r\n462\r\n463\r\n467\r\n468\r\n469\r\n472\r\n473\r\n474\r\n475\r\n476\r\n484\r\n485\r\n486\r\n490\r\n491\r\n492\r\n493\r\n494\r\n497\r\n521\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n537\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\n568\r\n572\r\n581\r\n583\r\n584\r\n629\r\n631\r\n645\r\n646\r\n647\r\n648\r\n676\r\n679\r\n728\r\n730\r\n731\r\n733\r\n735\r\n739\r\n741\r\n742\r\n746\r\n747\r\n749\r\n760\r\n761\r\n763\r\n764\r\n765\r\n766\r\n767\r\n768\r\n771\r\n772\r\n774\r\n776\r\n777\r\n779\r\n791\r\n792\r\n797\r\n831\r\n832\r\n845\r\n846\r\n849\r\n850\r\n855\r\n875\r\n877\r\n878\r\n879\r\n896\r\n928\r\n938\r\n980\r\n992\r\nHollywood, Florida\r\n430\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n438\r\n454\r\n455\r\n456\r\n457\r\n458\r\n680\r\n920\r\n921\r\n922\r\n923\r\n925\r\n926\r\n927\r\n929\r\n961\r\n962\r\n963\r\n964\r\n966\r\n967\r\n981\r\n983\r\n985\r\n986\r\n987\r\n989\r\nHomestead, Florida\r\n224\r\n230\r\n242\r\n245\r\n246\r\n247\r\n248\r\n257\r\n258\r\nIslamorada, Florida\r\n664\r\nKey Largo, Florida\r\n451\r\n453\r\n852\r\n853\r\nKey West, Florida\r\n292\r\n293\r\n294\r\n296\r\nMarathon, Florida\r\n289\r\n743\r\nMiami, Florida\r\n220\r\n221\r\n222\r\n223\r\n225\r\n226\r\n227\r\n229\r\n237\r\n250\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n270\r\n271\r\n273\r\n274\r\n277\r\n279\r\n284\r\n285\r\n298\r\n322\r\n323\r\n324\r\n325\r\n326\r\n334\r\n337\r\n338\r\n339\r\n342\r\n347\r\n348\r\n350\r\n352\r\n353\r\n358\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n368\r\n369\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n379\r\n380\r\n381\r\n382\r\n383\r\n385\r\n386\r\n387\r\n388\r\n391\r\n397\r\n399\r\n439\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n460\r\n461\r\n464\r\n465\r\n470\r\n471\r\n477\r\n478\r\n520\r\n526\r\n529\r\n530\r\n531\r\n532\r\n534\r\n535\r\n536\r\n538\r\n539\r\n540\r\n542\r\n543\r\n544\r\n545\r\n546\r\n547\r\n548\r\n549\r\n550\r\n551\r\n552\r\n553\r\n554\r\n556\r\n557\r\n558\r\n559\r\n560\r\n567\r\n571\r\n573\r\n575\r\n576\r\n577\r\n578\r\n579\r\n580\r\n582\r\n585\r\n586\r\n588\r\n590\r\n591\r\n592\r\n593\r\n594\r\n595\r\n596\r\n597\r\n598\r\n599\r\n633\r\n634\r\n635\r\n636\r\n637\r\n638\r\n642\r\n643\r\n644\r\n649\r\n661\r\n662\r\n663\r\n665\r\n666\r\n667\r\n669\r\n670\r\n672\r\n673\r\n674\r\n681\r\n685\r\n687\r\n688\r\n691\r\n693\r\n694\r\n696\r\n729\r\n732\r\n734\r\n737\r\n751\r\n754\r\n756\r\n757\r\n758\r\n759\r\n762\r\n769\r\n773\r\n775\r\n789\r\n790\r\n793\r\n794\r\n795\r\n799\r\n820\r\n821\r\n822\r\n823\r\n824\r\n825\r\n826\r\n827\r\n828\r\n833\r\n834\r\n835\r\n836\r\n837\r\n838\r\n839\r\n840\r\n841\r\n842\r\n843\r\n844\r\n854\r\n856\r\n857\r\n858\r\n859\r\n860\r\n861\r\n862\r\n864\r\n865\r\n866\r\n867\r\n868\r\n869\r\n870\r\n871\r\n873\r\n874\r\n876\r\n880\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\n891\r\n892\r\n893\r\n895\r\n899\r\n939\r\n951\r\n953\r\n990\r\n993\r\n995\r\n996\r\n276\r\n297\r\n715\r\n736\r\n738\r\n819\r\n897\r\nNorth Key Largo, Florida\r\n367\r\nNorth Dade, Florida\r\n239\r\n319\r\n331\r\n332\r\n333\r\n335\r\n336\r\n343\r\n354\r\n541\r\n620\r\n621\r\n623\r\n624\r\n625\r\n626\r\n628\r\n651\r\n652\r\n653\r\n654\r\n655\r\n657\r\n658\r\n659\r\n660\r\n682\r\n770\r\n778\r\n787\r\n829\r\n931\r\n932\r\n933\r\n934\r\n935\r\n936\r\n937\r\n940\r\n944\r\n945\r\n947\r\n948\r\n949\r\n952\r\n956\r\n957\r\n965\r\nOrlando, Florida\r\n555\r\nPerrine, Florida\r\n232\r\n233\r\n234\r\n235\r\n238\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n281\r\n282\r\n283\r\n378\r\nPompano Beach, Florida\r\n425\r\n720\r\n722\r\n724\r\n726\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n941\r\n942\r\n943\r\n946\r\n960\r\n968\r\n969\r\n970\r\n971\r\n972\r\n973\r\n974\r\n975\r\n977\r\n978\r\n979\r\nSugarloaf Key, Florida\r\n744\r\n745\r\nTamarac, Florida\r\n721\r\n\u00035Unknown prefix code (305) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.306",
    "content": "Regina, Saskatchewan, Canada\r\n352\r\nAbbey, Saskatchewan, Canada\r\n689\r\nAberdeen, Saskatchewan, Canada\r\n253\r\nAbernethy, Saskatchewan, Canada\r\n333\r\nAlameda, Saskatchewan, Canada\r\n489\r\nAlida, Saskatchewan, Canada\r\n443\r\nAllan, Saskatchewan, Canada\r\n257\r\nAlsask, Saskatchewan, Canada\r\n968\r\nAlvena, Saskatchewan, Canada\r\n943\r\nAneroid, Saskatchewan, Canada\r\n588\r\nArborfield, Saskatchewan, Canada\r\n769\r\nArcherwill, Saskatchewan, Canada\r\n323\r\nArcola, Saskatchewan, Canada\r\n455\r\nAsquith, Saskatchewan, Canada\r\n329\r\nAssiniboia, Saskatchewan, Canada\r\n642\r\nAvonlea, Saskatchewan, Canada\r\n868\r\nBalcarres, Saskatchewan, Canada\r\n334\r\nBalgonie, Saskatchewan, Canada\r\n771\r\nBeauval, Saskatchewan, Canada\r\n288\r\nBeechy, Saskatchewan, Canada\r\n859\r\nBengough, Saskatchewan, Canada\r\n268\r\nBesnard Lake, Saskatchewan, Canada\r\n620\r\nBethune, Saskatchewan, Canada\r\n638\r\nBienfait, Saskatchewan, Canada\r\n388\r\nBig River, Saskatchewan, Canada\r\n469\r\nBiggar, Saskatchewan, Canada\r\n948\r\nBirchhills, Saskatchewan, Canada\r\n749\r\nBirsay, Saskatchewan, Canada\r\n573\r\nBlainelake, Saskatchewan, Canada\r\n497\r\nBorden, Saskatchewan, Canada\r\n997\r\nBredenbury, Saskatchewan, Canada\r\n898\r\nBriercrest, Saskatchewan, Canada\r\n799\r\nBroadview, Saskatchewan, Canada\r\n696\r\nBrock, Saskatchewan, Canada\r\n379\r\nBruno, Saskatchewan, Canada\r\n369\r\nBuchanan, Saskatchewan, Canada\r\n592\r\nBuflo Nrws, Saskatchewan, Canada\r\n235\r\nBurstall, Saskatchewan, Canada\r\n679\r\nCabri, Saskatchewan, Canada\r\n587\r\nCadillac, Saskatchewan, Canada\r\n785\r\nCalder, Saskatchewan, Canada\r\n742\r\nCanoe Nrws, Saskatchewan, Canada\r\n829\r\nCanora, Saskatchewan, Canada\r\n563\r\nCanwood, Saskatchewan, Canada\r\n468\r\nCarievale, Saskatchewan, Canada\r\n928\r\nCarlyle, Saskatchewan, Canada\r\n453\r\n577\r\nCarnduff, Saskatchewan, Canada\r\n482\r\nCaron, Saskatchewan, Canada\r\n756\r\nCarrot River, Saskatchewan, Canada\r\n768\r\nCentralbte, Saskatchewan, Canada\r\n796\r\nCeylon, Saskatchewan, Canada\r\n454\r\n969\r\nChaplin, Saskatchewan, Canada\r\n395\r\nChoiceland, Saskatchewan, Canada\r\n428\r\nChristopher Lake, Saskatchewan, Canada\r\n982\r\nChurchbdg, Saskatchewan, Canada\r\n896\r\nClimax, Saskatchewan, Canada\r\n293\r\nCluff Lake, Saskatchewan, Canada\r\n420\r\nCoderre, Saskatchewan, Canada\r\n394\r\nColeville, Saskatchewan, Canada\r\n965\r\nColonsay, Saskatchewan, Canada\r\n255\r\nConquest, Saskatchewan, Canada\r\n856\r\nConsul, Saskatchewan, Canada\r\n299\r\nCoronach, Saskatchewan, Canada\r\n267\r\nCraik, Saskatchewan, Canada\r\n734\r\nCreelman, Saskatchewan, Canada\r\n433\r\nCreighton, Saskatchewan, Canada\r\n362\r\n688\r\nCrswll River, Saskatchewan, Canada\r\n440\r\nCudworth, Saskatchewan, Canada\r\n256\r\nCumberld H, Saskatchewan, Canada\r\n888\r\nCupar, Saskatchewan, Canada\r\n723\r\nCut Knife, Saskatchewan, Canada\r\n398\r\nDalmeny, Saskatchewan, Canada\r\n254\r\nDavidson, Saskatchewan, Canada\r\n567\r\nDebden, Saskatchewan, Canada\r\n724\r\nDelisle, Saskatchewan, Canada\r\n493\r\nDenzil, Saskatchewan, Canada\r\n358\r\nDillon, Saskatchewan, Canada\r\n282\r\nDinsmore, Saskatchewan, Canada\r\n846\r\nDodsland, Saskatchewan, Canada\r\n356\r\nDomremy, Saskatchewan, Canada\r\n423\r\nDrake, Saskatchewan, Canada\r\n363\r\nDubuc, Saskatchewan, Canada\r\n877\r\nDuck Lake, Saskatchewan, Canada\r\n467\r\nDundurn, Saskatchewan, Canada\r\n492\r\nDysart, Saskatchewan, Canada\r\n432\r\nEarl Grey, Saskatchewan, Canada\r\n939\r\nEastend, Saskatchewan, Canada\r\n295\r\nEatonia, Saskatchewan, Canada\r\n967\r\nEdam, Saskatchewan, Canada\r\n397\r\nElbow, Saskatchewan, Canada\r\n854\r\nElfros, Saskatchewan, Canada\r\n328\r\nElrose, Saskatchewan, Canada\r\n378\r\nEsterhazy, Saskatchewan, Canada\r\n745\r\nEstevan, Saskatchewan, Canada\r\n421\r\n461\r\n634\r\n636\r\nEston, Saskatchewan, Canada\r\n962\r\nEyebrow, Saskatchewan, Canada\r\n759\r\nFillmore, Saskatchewan, Canada\r\n722\r\nFoam Lake, Saskatchewan, Canada\r\n272\r\nFond Dulac, Saskatchewan, Canada\r\n686\r\nFox Valley, Saskatchewan, Canada\r\n666\r\nFrancis, Saskatchewan, Canada\r\n245\r\nFrobisher, Saskatchewan, Canada\r\n486\r\nFrontier, Saskatchewan, Canada\r\n296\r\nFtquappell, Saskatchewan, Canada\r\n332\r\nGainsbrgh, Saskatchewan, Canada\r\n685\r\nGlaslyn, Saskatchewan, Canada\r\n342\r\nGlen Ewen, Saskatchewan, Canada\r\n925\r\nGlenavon, Saskatchewan, Canada\r\n429\r\nGoodeve, Saskatchewan, Canada\r\n876\r\nGoodsoil, Saskatchewan, Canada\r\n238\r\nGovan, Saskatchewan, Canada\r\n484\r\nGravelborg, Saskatchewan, Canada\r\n648\r\nGrayson, Saskatchewan, Canada\r\n794\r\nGreen Lake, Saskatchewan, Canada\r\n832\r\nGrenfell, Saskatchewan, Canada\r\n697\r\nGull Lake, Saskatchewan, Canada\r\n672\r\nHafford, Saskatchewan, Canada\r\n549\r\nHague, Saskatchewan, Canada\r\n225\r\nHanley, Saskatchewan, Canada\r\n544\r\nHarris, Saskatchewan, Canada\r\n656\r\nHatchet Lake, Saskatchewan, Canada\r\n390\r\nHawarden, Saskatchewan, Canada\r\n855\r\nHawkrock, Saskatchewan, Canada\r\n330\r\nHazlet, Saskatchewan, Canada\r\n678\r\nHepburn, Saskatchewan, Canada\r\n947\r\nHerbert, Saskatchewan, Canada\r\n784\r\nHerschel, Saskatchewan, Canada\r\n377\r\nHodgeville, Saskatchewan, Canada\r\n677\r\nHoldfast, Saskatchewan, Canada\r\n488\r\nHudson Bay, Saskatchewan, Canada\r\n865\r\nHumboldt, Saskatchewan, Canada\r\n231\r\n682\r\nIlealacros, Saskatchewan, Canada\r\n833\r\nImperial, Saskatchewan, Canada\r\n963\r\nIndianhead, Saskatchewan, Canada\r\n695\r\nInvermay, Saskatchewan, Canada\r\n593\r\nItuna, Saskatchewan, Canada\r\n795\r\nJansen, Saskatchewan, Canada\r\n364\r\nKamsack, Saskatchewan, Canada\r\n542\r\nKane Lake, Saskatchewan, Canada\r\n920\r\nKelliher, Saskatchewan, Canada\r\n675\r\nKelvington, Saskatchewan, Canada\r\n327\r\nKenaston, Saskatchewan, Canada\r\n252\r\nKennedy, Saskatchewan, Canada\r\n538\r\nKerrobert, Saskatchewan, Canada\r\n834\r\nKey Lake, Saskatchewan, Canada\r\n870\r\nKincaid, Saskatchewan, Canada\r\n264\r\nKindersley, Saskatchewan, Canada\r\n463\r\nKinistino, Saskatchewan, Canada\r\n864\r\n887\r\nKipling, Saskatchewan, Canada\r\n736\r\nKisbey, Saskatchewan, Canada\r\n462\r\nKyle, Saskatchewan, Canada\r\n375\r\nLa Loche, Saskatchewan, Canada\r\n822\r\nLa Ronge, Saskatchewan, Canada\r\n425\r\nLafleche, Saskatchewan, Canada\r\n472\r\nLaird, Saskatchewan, Canada\r\n223\r\nLake Alma, Saskatchewan, Canada\r\n447\r\nLakelenore, Saskatchewan, Canada\r\n368\r\n598\r\nLampman, Saskatchewan, Canada\r\n487\r\nLandis, Saskatchewan, Canada\r\n658\r\nLang, Saskatchewan, Canada\r\n464\r\nLangenburg, Saskatchewan, Canada\r\n743\r\nLangham, Saskatchewan, Canada\r\n283\r\nLanigan, Saskatchewan, Canada\r\n365\r\nLashburn, Saskatchewan, Canada\r\n285\r\nLeader, Saskatchewan, Canada\r\n628\r\nLeask, Saskatchewan, Canada\r\n466\r\nLemberg, Saskatchewan, Canada\r\n335\r\nLeoville, Saskatchewan, Canada\r\n984\r\nLeroy, Saskatchewan, Canada\r\n286\r\nLestock, Saskatchewan, Canada\r\n274\r\nLiberty, Saskatchewan, Canada\r\n847\r\nLimerick, Saskatchewan, Canada\r\n263\r\nLintlaw, Saskatchewan, Canada\r\n325\r\nLipton, Saskatchewan, Canada\r\n336\r\nLlydminstr, Saskatchewan, Canada\r\n821\r\n825\r\nLoon Lake, Saskatchewan, Canada\r\n837\r\nLoreburn, Saskatchewan, Canada\r\n644\r\nLucky Lake, Saskatchewan, Canada\r\n858\r\nLumsden, Saskatchewan, Canada\r\n731\r\nLuseland, Saskatchewan, Canada\r\n372\r\nMacklin, Saskatchewan, Canada\r\n753\r\nMacrorie, Saskatchewan, Canada\r\n243\r\nMaidstone, Saskatchewan, Canada\r\n893\r\nMankota, Saskatchewan, Canada\r\n478\r\nManor, Saskatchewan, Canada\r\n448\r\nMaplecreek, Saskatchewan, Canada\r\n662\r\nMarcelin, Saskatchewan, Canada\r\n226\r\nMargo, Saskatchewan, Canada\r\n324\r\nMarquis, Saskatchewan, Canada\r\n788\r\nMarsden, Saskatchewan, Canada\r\n826\r\nMarshall, Saskatchewan, Canada\r\n387\r\nMaryfield, Saskatchewan, Canada\r\n646\r\nMaymont, Saskatchewan, Canada\r\n389\r\nMckenziefl, Saskatchewan, Canada\r\n360\r\nMeacham, Saskatchewan, Canada\r\n376\r\nMeadowlake, Saskatchewan, Canada\r\n236\r\nMeath Park, Saskatchewan, Canada\r\n929\r\nMelfort, Saskatchewan, Canada\r\n752\r\n809\r\n921\r\nMelville, Saskatchewan, Canada\r\n728\r\nMeota, Saskatchewan, Canada\r\n892\r\nMidale, Saskatchewan, Canada\r\n458\r\nMiddlelake, Saskatchewan, Canada\r\n367\r\nMilden, Saskatchewan, Canada\r\n935\r\nMilestone, Saskatchewan, Canada\r\n436\r\nMistatim, Saskatchewan, Canada\r\n889\r\nMolanosa, Saskatchewan, Canada\r\n830\r\nMontmartre, Saskatchewan, Canada\r\n424\r\nMoose Jaw, Saskatchewan, Canada\r\n631\r\n681\r\n691\r\n692\r\n693\r\n694\r\nMoosomin, Saskatchewan, Canada\r\n435\r\nMorse, Saskatchewan, Canada\r\n629\r\nMortlach, Saskatchewan, Canada\r\n355\r\nMossbank, Saskatchewan, Canada\r\n354\r\nNaicam, Saskatchewan, Canada\r\n874\r\nNarrowlake, Saskatchewan, Canada\r\n972\r\nNeidpath, Saskatchewan, Canada\r\n553\r\nNeilburg, Saskatchewan, Canada\r\n823\r\nNeudorf, Saskatchewan, Canada\r\n748\r\nNeville, Saskatchewan, Canada\r\n627\r\nNipawin, Saskatchewan, Canada\r\n862\r\nNo Portal, Saskatchewan, Canada\r\n927\r\nNobattlefd, Saskatchewan, Canada\r\n386\r\n441\r\n445\r\n446\r\n481\r\n937\r\nNokomis, Saskatchewan, Canada\r\n528\r\nNorquay, Saskatchewan, Canada\r\n594\r\nOdessa, Saskatchewan, Canada\r\n957\r\nOgema, Saskatchewan, Canada\r\n459\r\nOrmiston, Saskatchewan, Canada\r\n475\r\nOsler, Saskatchewan, Canada\r\n239\r\nOutlook, Saskatchewan, Canada\r\n867\r\nOxbow, Saskatchewan, Canada\r\n483\r\nPaddockwd, Saskatchewan, Canada\r\n989\r\nPangman, Saskatchewan, Canada\r\n442\r\nParadisehl, Saskatchewan, Canada\r\n344\r\nPatuanak, Saskatchewan, Canada\r\n396\r\nPaynton, Saskatchewan, Canada\r\n895\r\nPelcn Nrws, Saskatchewan, Canada\r\n632\r\nPelly, Saskatchewan, Canada\r\n595\r\nPennant, Saskatchewan, Canada\r\n626\r\nPense, Saskatchewan, Canada\r\n345\r\nPerdue, Saskatchewan, Canada\r\n237\r\nPiapot, Saskatchewan, Canada\r\n558\r\nPierceland, Saskatchewan, Canada\r\n839\r\nPinehouse, Saskatchewan, Canada\r\n884\r\nPlato, Saskatchewan, Canada\r\n574\r\nPlenty, Saskatchewan, Canada\r\n932\r\nPonteix, Saskatchewan, Canada\r\n625\r\nPorcupinpl, Saskatchewan, Canada\r\n278\r\nPreecevl, Saskatchewan, Canada\r\n547\r\nPrelate, Saskatchewan, Canada\r\n673\r\nPrincealbt, Saskatchewan, Canada\r\n763\r\n764\r\n922\r\n953\r\n961\r\n981\r\nPrudhomme, Saskatchewan, Canada\r\n654\r\nPunnichy, Saskatchewan, Canada\r\n835\r\nQuappelle, Saskatchewan, Canada\r\n699\r\nQuill Lake, Saskatchewan, Canada\r\n383\r\nRabbitlake, Saskatchewan, Canada\r\n824\r\nRadisson, Saskatchewan, Canada\r\n827\r\nRadville, Saskatchewan, Canada\r\n869\r\nRaymore, Saskatchewan, Canada\r\n746\r\nRedvers, Saskatchewan, Canada\r\n452\r\nRegina, Saskatchewan, Canada\r\n337\r\n347\r\n359\r\n522\r\n525\r\n536\r\n543\r\n545\r\n546\r\n565\r\n566\r\n569\r\n584\r\n585\r\n586\r\n596\r\n721\r\n751\r\n757\r\n761\r\n775\r\n777\r\n779\r\n780\r\n781\r\n787\r\n789\r\n791\r\n797\r\n828\r\n924\r\n936\r\n949\r\n995\r\nRegina Bch, Saskatchewan, Canada\r\n729\r\nRhein, Saskatchewan, Canada\r\n273\r\nRiceton, Saskatchewan, Canada\r\n738\r\nRichmound, Saskatchewan, Canada\r\n669\r\nRidgedale, Saskatchewan, Canada\r\n277\r\nRiverhurst, Saskatchewan, Canada\r\n353\r\nRocanville, Saskatchewan, Canada\r\n645\r\nRockglen, Saskatchewan, Canada\r\n476\r\nRosetown, Saskatchewan, Canada\r\n831\r\n882\r\nRosevalley, Saskatchewan, Canada\r\n322\r\nRosthern, Saskatchewan, Canada\r\n232\r\nRouleau, Saskatchewan, Canada\r\n776\r\nSaltcoats, Saskatchewan, Canada\r\n744\r\nSandy Bay, Saskatchewan, Canada\r\n754\r\nSaskatoon, Saskatchewan, Canada\r\n221\r\n241\r\n242\r\n244\r\n249\r\n343\r\n373\r\n382\r\n384\r\n477\r\n652\r\n653\r\n661\r\n664\r\n668\r\n683\r\n931\r\n938\r\n955\r\n956\r\n966\r\n975\r\n978\r\n374\r\n665\r\n933\r\n934\r\nSceptre, Saskatchewan, Canada\r\n623\r\nScott, Saskatchewan, Canada\r\n247\r\nSedley, Saskatchewan, Canada\r\n885\r\nSemans, Saskatchewan, Canada\r\n524\r\nShaunavon, Saskatchewan, Canada\r\n297\r\nSheho, Saskatchewan, Canada\r\n849\r\nShell Lake, Saskatchewan, Canada\r\n427\r\nShellbrook, Saskatchewan, Canada\r\n747\r\nSimpson, Saskatchewan, Canada\r\n836\r\nSintaluta, Saskatchewan, Canada\r\n727\r\nSmeaton, Saskatchewan, Canada\r\n426\r\nSmiley, Saskatchewan, Canada\r\n838\r\nSouthend, Saskatchewan, Canada\r\n758\r\nSouthey, Saskatchewan, Canada\r\n726\r\nSpalding, Saskatchewan, Canada\r\n872\r\nSpeers, Saskatchewan, Canada\r\n246\r\nSpiritwood, Saskatchewan, Canada\r\n883\r\nSpringside, Saskatchewan, Canada\r\n792\r\nSpy Hill, Saskatchewan, Canada\r\n534\r\nSt Brieux, Saskatchewan, Canada\r\n275\r\nSt Gregor, Saskatchewan, Canada\r\n366\r\nSt Louis, Saskatchewan, Canada\r\n422\r\nSt Walburg, Saskatchewan, Canada\r\n248\r\nStanleymis, Saskatchewan, Canada\r\n635\r\nStar City, Saskatchewan, Canada\r\n863\r\nStbenedict, Saskatchewan, Canada\r\n289\r\nStockholm, Saskatchewan, Canada\r\n793\r\nStonyrapds, Saskatchewan, Canada\r\n284\r\n439\r\nStorthoaks, Saskatchewan, Canada\r\n449\r\nStoughton, Saskatchewan, Canada\r\n457\r\nStrasbourg, Saskatchewan, Canada\r\n725\r\nStrongfld, Saskatchewan, Canada\r\n857\r\nSturgis, Saskatchewan, Canada\r\n548\r\nSwift Crnt, Saskatchewan, Canada\r\n741\r\n773\r\n778\r\nTantallon, Saskatchewan, Canada\r\n643\r\nTheodore, Saskatchewan, Canada\r\n647\r\nTisdale, Saskatchewan, Canada\r\n873\r\n886\r\nTogo, Saskatchewan, Canada\r\n597\r\nTompkins, Saskatchewan, Canada\r\n622\r\nTorquay, Saskatchewan, Canada\r\n923\r\nTower Bch, Saskatchewan, Canada\r\n340\r\nTrampinglake, Saskatchewan, Canada\r\n755\r\nTribune, Saskatchewan, Canada\r\n456\r\nTurnorlake, Saskatchewan, Canada\r\n894\r\nTurtleford, Saskatchewan, Canada\r\n845\r\nTurtlelake, Saskatchewan, Canada\r\n530\r\nUnity, Saskatchewan, Canada\r\n228\r\nUraniumcty, Saskatchewan, Canada\r\n498\r\nVal Marie, Saskatchewan, Canada\r\n298\r\nVanguard, Saskatchewan, Canada\r\n582\r\nVibank, Saskatchewan, Canada\r\n762\r\nViscount, Saskatchewan, Canada\r\n944\r\nVonda, Saskatchewan, Canada\r\n258\r\nWadena, Saskatchewan, Canada\r\n338\r\nWakaw, Saskatchewan, Canada\r\n233\r\nWaldheim, Saskatchewan, Canada\r\n945\r\nWapella, Saskatchewan, Canada\r\n532\r\nWaskesiulake, Saskatchewan, Canada\r\n663\r\nWatrous, Saskatchewan, Canada\r\n946\r\nWatson, Saskatchewan, Canada\r\n287\r\nWawota, Saskatchewan, Canada\r\n739\r\nWebb, Saskatchewan, Canada\r\n674\r\nWelwyn, Saskatchewan, Canada\r\n733\r\nWeyburn, Saskatchewan, Canada\r\n842\r\n848\r\n861\r\n891\r\nWhite Fox, Saskatchewan, Canada\r\n276\r\nWhitewood, Saskatchewan, Canada\r\n735\r\nWilcox, Saskatchewan, Canada\r\n732\r\nWilkie, Saskatchewan, Canada\r\n843\r\nWillowbnch, Saskatchewan, Canada\r\n473\r\nWindthorst, Saskatchewan, Canada\r\n224\r\nWiseton, Saskatchewan, Canada\r\n357\r\nWishart, Saskatchewan, Canada\r\n576\r\nWollston Lake, Saskatchewan, Canada\r\n633\r\nWolseley, Saskatchewan, Canada\r\n698\r\nWood Mt, Saskatchewan, Canada\r\n266\r\nWynyard, Saskatchewan, Canada\r\n554\r\nYellow Creek, Saskatchewan, Canada\r\n279\r\nYellow Grs, Saskatchewan, Canada\r\n465\r\nYorkton, Saskatchewan, Canada\r\n621\r\n641\r\n782\r\n783\r\n786\r\nYoung, Saskatchewan, Canada\r\n259\r\nZenon Park, Saskatchewan, Canada\r\n767\r\n\u00035Unknown prefix code (306) - Saskatchewan, Canada\r\n"
  },
  {
    "path": "install/regions/regions.307",
    "content": "Afton, Wyoming\r\n886\r\nAlbin, Wyoming\r\n246\r\nAlpine, Wyoming\r\n654\r\nAlta, Wyoming\r\n353\r\nArvada, Wyoming\r\n736\r\nBaggs, Wyoming\r\n383\r\nBasin, Wyoming\r\n568\r\nBig Piney, Wyoming\r\n260\r\n276\r\nBorder, Wyoming\r\n849\r\nBoulder, Wyoming\r\n537\r\nBuffalo, Wyoming\r\n684\r\nBurlington, Wyoming\r\n762\r\nBurns, Wyoming\r\n547\r\nCarpenter, Wyoming\r\n649\r\nCasper, Wyoming\r\n234\r\n235\r\n237\r\n261\r\n262\r\n265\r\n266\r\n267\r\n268\r\n472\r\n473\r\n577\r\n995\r\nCheyenne, Wyoming\r\n630\r\n632\r\n633\r\n634\r\n635\r\n637\r\n638\r\n640\r\n662\r\n771\r\n772\r\n775\r\n777\r\n778\r\n996\r\nChugwater, Wyoming\r\n422\r\nClark, Wyoming\r\n645\r\nClearmont, Wyoming\r\n758\r\nCody, Wyoming\r\n272\r\n290\r\n527\r\n578\r\n587\r\n899\r\nCokeville, Wyoming\r\n279\r\nCrowheart, Wyoming\r\n486\r\nDaniel, Wyoming\r\n859\r\nDecker, Wyoming\r\n750\r\nDouglas, Wyoming\r\n358\r\n359\r\nDubois, Wyoming\r\n450\r\n455\r\nEncampment, Wyoming\r\n327\r\nEvanston, Wyoming\r\n783\r\n789\r\n799\r\nFarson, Wyoming\r\n273\r\n280\r\nFrannie, Wyoming\r\n664\r\nFreedom, Wyoming\r\n883\r\nGas Hills, Wyoming\r\n457\r\nGillette, Wyoming\r\n680\r\n687\r\n689\r\n682\r\n686\r\nGlendo, Wyoming\r\n735\r\nGlenrock, Wyoming\r\n436\r\nGreenriver, Wyoming\r\n870\r\n872\r\n875\r\nGreybull, Wyoming\r\n765\r\nGuernsey, Wyoming\r\n836\r\nHamiltondom, Wyoming\r\n867\r\nHanna, Wyoming\r\n325\r\n339\r\n348\r\nHulett, Wyoming\r\n467\r\nHyattville, Wyoming\r\n469\r\nJackson, Wyoming\r\n730\r\n733\r\n734\r\n739\r\n740\r\nJeffrey City, Wyoming\r\n544\r\nKaycee, Wyoming\r\n738\r\nKemmerer, Wyoming\r\n727\r\n828\r\n877\r\nLa Grange, Wyoming\r\n834\r\nLabarge, Wyoming\r\n386\r\n390\r\nLake, Wyoming\r\n242\r\nLander, Wyoming\r\n330\r\n332\r\nLaramie, Wyoming\r\n721\r\n742\r\n745\r\n755\r\n760\r\n761\r\n766\r\nLeigh Canyon, Wyoming\r\n576\r\nLingle, Wyoming\r\n837\r\nLovell, Wyoming\r\n548\r\nLusk, Wyoming\r\n334\r\nLyman, Wyoming\r\n787\r\nMammoth, Wyoming\r\n344\r\nManila, Wyoming\r\n874\r\nMedicine Bow, Wyoming\r\n379\r\n520\r\nMeeteetse, Wyoming\r\n868\r\nMidvale, Utah\r\n555\r\nMidwest, Wyoming\r\n437\r\nMoorcroft, Wyoming\r\n756\r\nMoran, Wyoming\r\n543\r\nMountainview, Wyoming\r\n780\r\n782\r\nNewcastle, Wyoming\r\n465\r\n746\r\nOldfaithful, Wyoming\r\n545\r\nPine Bluffs, Wyoming\r\n245\r\nPinedale, Wyoming\r\n367\r\nPowell, Wyoming\r\n754\r\nRawlins, Wyoming\r\n320\r\n324\r\n328\r\nRiverton, Wyoming\r\n850\r\n856\r\n857\r\nRock River, Wyoming\r\n378\r\nRock Springs, Wyoming\r\n350\r\n352\r\n362\r\n389\r\n382\r\nSaratoga, Wyoming\r\n326\r\n329\r\nSesheridan, Wyoming\r\n737\r\nSheridan, Wyoming\r\n655\r\n672\r\n683\r\n751\r\n752\r\n829\r\n674\r\nShirleybasin, Wyoming\r\n356\r\nShoshoni, Wyoming\r\n728\r\n876\r\nSouth Alzada, Wyoming\r\n878\r\nSouth Wyola, Wyoming\r\n341\r\nSundance, Wyoming\r\n283\r\nTen Sleep, Wyoming\r\n366\r\nThermopols, Wyoming\r\n864\r\nTorrington, Wyoming\r\n532\r\nUpton, Wyoming\r\n468\r\nUrie, Wyoming\r\n786\r\nWest Bel Frch, Wyoming\r\n896\r\nWest Edgemont, Wyoming\r\n663\r\nWest Lyman, Wyoming\r\n788\r\nWheatland, Wyoming\r\n322\r\nWorland, Wyoming\r\n347\r\n375\r\nWright, Wyoming\r\n464\r\n939\r\nWest Spearfish, Wyoming\r\n643\r\n\u00035Unknown prefix code (307) - Wyoming\r\n"
  },
  {
    "path": "install/regions/regions.308",
    "content": "Alliance, Nebraska\r\n760\r\n762\r\n763\r\nAlma, Nebraska\r\n928\r\nAmherst, Nebraska\r\n826\r\nAnselmo, Nebraska\r\n749\r\nAnsley, Nebraska\r\n935\r\nArapahoe, Nebraska\r\n962\r\nArcadia, Nebraska\r\n789\r\nArcher, Nebraska\r\n795\r\nArnold, Nebraska\r\n848\r\nArthur, Nebraska\r\n764\r\nAshby, Nebraska\r\n577\r\nAshton, Nebraska\r\n738\r\nAtlanta, Nebraska\r\n337\r\nAxtell, Nebraska\r\n743\r\nBartlett, Nebraska\r\n654\r\nBartley, Nebraska\r\n692\r\nBayard, Nebraska\r\n586\r\nBeaver City, Nebraska\r\n268\r\nBelgrade, Nebraska\r\n357\r\nBenkelman, Nebraska\r\n423\r\nBertrand, Nebraska\r\n472\r\nBig Springs, Nebraska\r\n889\r\nBingham, Nebraska\r\n588\r\nBloomingtn, Nebraska\r\n775\r\nBoelus, Nebraska\r\n996\r\nBrady, Nebraska\r\n584\r\nBrewster, Nebraska\r\n547\r\nBridgeport, Nebraska\r\n260\r\n262\r\nBroadwater, Nebraska\r\n489\r\nBroken Bow, Nebraska\r\n870\r\n872\r\nBrownlee, Nebraska\r\n748\r\nBrule, Nebraska\r\n287\r\nBurwell, Nebraska\r\n346\r\nBushnell, Nebraska\r\n673\r\nCairo, Nebraska\r\n485\r\nCallaway, Nebraska\r\n836\r\nCambridge, Nebraska\r\n697\r\nCedar Rapids, Nebraska\r\n358\r\nCentral City, Nebraska\r\n946\r\nChadron, Nebraska\r\n432\r\nChapman, Nebraska\r\n986\r\nChappell, Nebraska\r\n874\r\nClarks, Nebraska\r\n548\r\nComstock, Nebraska\r\n628\r\nCotesfield, Nebraska\r\n968\r\nCozad, Nebraska\r\n784\r\nCrawford, Nebraska\r\n665\r\n667\r\nCulbertson, Nebraska\r\n278\r\nCurtis, Nebraska\r\n367\r\nDalton, Nebraska\r\n377\r\nDanbury, Nebraska\r\n895\r\nDannebrog, Nebraska\r\n226\r\nDix, Nebraska\r\n682\r\nDunning, Nebraska\r\n538\r\nEast La Grang, Nebraska\r\n838\r\nEast Albin, Nebraska\r\n846\r\nEdison, Nebraska\r\n927\r\nElba, Nebraska\r\n863\r\nElm Creek, Nebraska\r\n856\r\nElsie, Nebraska\r\n228\r\nElwood, Nebraska\r\n785\r\nEricson, Nebraska\r\n653\r\nEustis, Nebraska\r\n486\r\nFarnam, Nebraska\r\n569\r\nFarwell, Nebraska\r\n336\r\nFranklin, Nebraska\r\n425\r\nFullerton, Nebraska\r\n536\r\nFunk, Nebraska\r\n263\r\nGering, Nebraska\r\n436\r\nGibbon, Nebraska\r\n468\r\nGordon, Nebraska\r\n282\r\nGothenburg, Nebraska\r\n529\r\n537\r\nGrand Isle, Nebraska\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n389\r\nGrant, Nebraska\r\n352\r\nGreeley, Nebraska\r\n428\r\nGurley, Nebraska\r\n884\r\nHaigler, Nebraska\r\n297\r\nHalsey, Nebraska\r\n533\r\nHarrison, Nebraska\r\n668\r\nHayes Center, Nebraska\r\n286\r\nHay Springs, Nebraska\r\n638\r\nHeartwell, Nebraska\r\n563\r\nHemingford, Nebraska\r\n487\r\nHendley, Nebraska\r\n265\r\nHershey, Nebraska\r\n368\r\nHildreth, Nebraska\r\n938\r\nHntlyragan, Nebraska\r\n567\r\nHolbrook, Nebraska\r\n493\r\nHoldrege, Nebraska\r\n991\r\n995\r\nHyannis, Nebraska\r\n458\r\nImperial, Nebraska\r\n882\r\nIndianola, Nebraska\r\n364\r\nKearney, Nebraska\r\n230\r\n233\r\n234\r\n236\r\n237\r\nKeystone, Nebraska\r\n726\r\nKimball, Nebraska\r\n235\r\nKimball City, Nebraska\r\n244\r\nLebanon, Nebraska\r\n375\r\nLemoyne, Nebraska\r\n355\r\nLewellen, Nebraska\r\n778\r\nLexington, Nebraska\r\n320\r\n324\r\n325\r\nLitchfield, Nebraska\r\n446\r\nLodgepole, Nebraska\r\n483\r\nLoomis, Nebraska\r\n876\r\nLoup City, Nebraska\r\n745\r\nLyman, Nebraska\r\n787\r\nMadrid, Nebraska\r\n326\r\nMason City, Nebraska\r\n732\r\nMaxwell, Nebraska\r\n582\r\nMaywood, Nebraska\r\n362\r\nMccook, Nebraska\r\n340\r\n345\r\n997\r\nMerna, Nebraska\r\n643\r\nMerriman, Nebraska\r\n684\r\nMiller, Nebraska\r\n457\r\nMinatare, Nebraska\r\n783\r\nMinden, Nebraska\r\n832\r\nMirageflat, Nebraska\r\n232\r\nMitchell, Nebraska\r\n623\r\nMorrill, Nebraska\r\n247\r\nMullen, Nebraska\r\n546\r\nNaponee, Nebraska\r\n269\r\nNorth Burwell, Nebraska\r\n348\r\nNorth Herndon, Nebraska\r\n328\r\nNorth Julesberg, Nebraska\r\n445\r\nNorth Long Isle, Nebraska\r\n859\r\nNorth Platte, Nebraska\r\n530\r\n532\r\n534\r\n535\r\n539\r\nNorth Loup, Nebraska\r\n496\r\nNorthpeetz, Nebraska\r\n335\r\nNowoodruff, Nebraska\r\n652\r\nOconto, Nebraska\r\n858\r\nOgallala, Nebraska\r\n280\r\n284\r\n289\r\nOmaha, Nebraska\r\n555\r\nOrd, Nebraska\r\n728\r\nOrleans, Nebraska\r\n473\r\nOshkosh, Nebraska\r\n772\r\nOverton, Nebraska\r\n987\r\nOxford, Nebraska\r\n824\r\nPalisade, Nebraska\r\n285\r\nPalmer, Nebraska\r\n894\r\nPaxton, Nebraska\r\n239\r\nPleasanton, Nebraska\r\n388\r\nPotter, Nebraska\r\n879\r\nPrimrose, Nebraska\r\n396\r\nPurdum, Nebraska\r\n834\r\nRavenna, Nebraska\r\n452\r\nRepublican City, Nebraska\r\n799\r\nRiverdale, Nebraska\r\n893\r\nRockville, Nebraska\r\n372\r\nRushville, Nebraska\r\n327\r\nSargent, Nebraska\r\n527\r\nScotia, Nebraska\r\n245\r\nScotts Bluff, Nebraska\r\n630\r\n631\r\n632\r\n635\r\n637\r\nSeneca, Nebraska\r\n639\r\nShelton, Nebraska\r\n647\r\nSidney, Nebraska\r\n249\r\n254\r\nSilver Creek, Nebraska\r\n773\r\nSouth Ardmore, Nebraska\r\n453\r\nSouth Oelrchs, Nebraska\r\n525\r\nSodtown, Nebraska\r\n467\r\nSpalding, Nebraska\r\n497\r\nSaint Libory, Nebraska\r\n687\r\nSaint Paul, Nebraska\r\n750\r\n754\r\nStamford, Nebraska\r\n868\r\nStapleton, Nebraska\r\n636\r\nStratton, Nebraska\r\n276\r\nSumner, Nebraska\r\n752\r\nSutherland, Nebraska\r\n386\r\nTaylor, Nebraska\r\n942\r\nThedford, Nebraska\r\n645\r\nTrenton, Nebraska\r\n334\r\nTryon, Nebraska\r\n587\r\nVenango, Nebraska\r\n447\r\nWallace, Nebraska\r\n387\r\nWauneta, Nebraska\r\n394\r\nWellfleet, Nebraska\r\n963\r\nWhiteclay, Nebraska\r\n862\r\nWhitman, Nebraska\r\n544\r\nWilcox, Nebraska\r\n478\r\nWilsonville, Nebraska\r\n349\r\nWolbach, Nebraska\r\n246\r\nWood River, Nebraska\r\n583\r\n\u00035Unknown prefix code (308) - Nebraska\r\n"
  },
  {
    "path": "install/regions/regions.309",
    "content": "Abingdon, Illinois\r\n462\r\nAdair, Illinois\r\n653\r\nAlbany, Illinois\r\n887\r\nAledo, Illinois\r\n582\r\nAlexis, Illinois\r\n482\r\nAlpha, Illinois\r\n529\r\nAltona, Illinois\r\n484\r\nAndover, Illinois\r\n476\r\nAnnawan, Illinois\r\n935\r\nArmington\u00031/\u00032Minier, Illinios\r\n392\r\nArrowsmith, Illinios\r\n727\r\nAstoria, Illinois\r\n329\r\nAtkinson, Illinois\r\n936\r\nAvon, Illinois\r\n465\r\nBardolph, Illinois\r\n769\r\nBath, Illinois\r\n546\r\nBellflower, Illinios\r\n722\r\nBenson, Illinois\r\n394\r\nBiggsville, Illinois\r\n627\r\nBishophill, Illinois\r\n927\r\nBlandinsville, Illinois\r\n652\r\nBloomington, Illinois\r\n436\r\n556\r\n824\r\n825\r\n557\r\n662\r\n663\r\n664\r\n763\r\n766\r\n823\r\n827\r\n828\r\n829\r\nBloomington\u00031/\u00032Normal, Illinios\r\n888\r\nBradford, Illinois\r\n897\r\nBrimfield, Illinois\r\n446\r\nBuda, Illinois\r\n895\r\nBushnell, Illinois\r\n772\r\nCambridge, Illinois\r\n937\r\nCameron, Illinois\r\n563\r\nCampgrove, Illinois\r\n493\r\nCanton Can, Illinois\r\n647\r\n649\r\n668\r\nCarlock, Illinios\r\n376\r\nCastleton, Illinois\r\n479\r\nCazenovia, Illinios\r\n443\r\nChillicoth, Illinois\r\n274\r\nColchester, Illinois\r\n776\r\nColfax-Anchor, Illinios\r\n723\r\nCongervl, Illinois\r\n448\r\nCooksville, Illinios\r\n725\r\nCordova, Illinois\r\n654\r\nCropsey, Illinios\r\n377\r\nCuba, Illinois\r\n785\r\nDanvers, Illinios\r\n963\r\nDeer Creek, Illinois\r\n447\r\nDelavan, Illinois\r\n244\r\nDowns, Illinios\r\n378\r\nDunlap, Illinois\r\n243\r\nEast Molne, Illinois\r\n751\r\n752\r\n755\r\n765\r\n765\r\n792\r\n796\r\nEaston, Illinois\r\n562\r\nEdelstein, Illinois\r\n249\r\nEdgington, Illinois\r\n795\r\nEl Paso, Illinois\r\n527\r\nEliza, Illinois\r\n537\r\nEllisville, Illinois\r\n293\r\nEllsworth, Illinios\r\n724\r\nElmira, Illinois\r\n896\r\nElmwood, Illinois\r\n742\r\nErie, Illinois\r\n659\r\nEureka, Illinois\r\n467\r\nFairview, Illinois\r\n778\r\nFarmer City, Illinois\r\n928\r\nFarmington, Illinois\r\n245\r\nFiatt, Illinois\r\n789\r\nForest City, Illinois\r\n597\r\nGalesburg, Illinois\r\n337\r\n341\r\n342\r\n343\r\n344\r\n345\r\n368\r\nGalva, Illinois\r\n932\r\nGeneseo, Illinois\r\n944\r\nGermanton Hill, Illinois\r\n383\r\nGilson, Illinois\r\n876\r\nGlasford, Illinois\r\n389\r\nGood Hope, Illinois\r\n456\r\nGoodfield, Illinois\r\n965\r\nGreen Valley, Illinois\r\n352\r\nGreen River, Illinois\r\n441\r\n949\r\nGridley, Illinois\r\n747\r\nGroveland, Illinois\r\n387\r\nGulfport, Illinois\r\n873\r\nHampton, Illinois\r\n496\r\nHanna City, Illinois\r\n565\r\nHavana, Illinois\r\n543\r\nHenry, Illinois\r\n364\r\nHeyworth, Illinios\r\n473\r\nHillsdale, Illinois\r\n658\r\nHopedale, Illinios\r\n449\r\nHudson, Illinios\r\n726\r\nIllinois City Edge, Illinois\r\n791\r\nIllinois State Univ, Illinios\r\n438\r\nIndustry, Illinois\r\n254\r\nIpava, Illinois\r\n753\r\nJoy, Illinois\r\n584\r\nKeithsburg, Illinois\r\n374\r\nKewanee, Illinois\r\n525\r\n852\r\n853\r\n854\r\n856\r\nKilbourne, Illinois\r\n538\r\nKirkwood, Illinois\r\n768\r\nKnoxville, Illinois\r\n289\r\nLa Fayette, Illinois\r\n995\r\nLa Rose, Illinois\r\n399\r\nLacon, Illinois\r\n246\r\nLeroy, Illinios\r\n962\r\nLewistown, Illinois\r\n547\r\nLexington, Illinios\r\n365\r\nLittleton, Illinois\r\n257\r\nLittle York, Illinois\r\n729\r\nLondon Mls, Illinois\r\n486\r\nMackinaw, Illinios\r\n359\r\nMacomb, Illinois\r\n255\r\n295\r\n298\r\n336\r\n833\r\n836\r\n837\r\nManito, Illinois\r\n968\r\nMaquon, Illinois\r\n875\r\nMarietta, Illinois\r\n926\r\nMatherville, Illinois\r\n754\r\nMclean, Illinios\r\n874\r\nMetamora, Illinois\r\n367\r\nMineral, Illinois\r\n288\r\nMinonk, Illinois\r\n432\r\nMoline, Illinois\r\n799\r\n757\r\n762\r\n764\r\n797\r\nMonmouth, Illinois\r\n457\r\n734\r\nMorton, Illinois\r\n263\r\n266\r\nMossville, Illinois\r\n578\r\n579\r\nNeponset, Illinois\r\n594\r\nNew Boston, Illinois\r\n587\r\nNew Windsor, Illinois\r\n667\r\nNorth Henderson, Illinois\r\n464\r\nNormal, Illinios\r\n452\r\n454\r\n862\r\nNorth Pekin, Illinois\r\n382\r\nOneida, Illinois\r\n483\r\nOquawka, Illinois\r\n867\r\nOrion, Illinois\r\n234\r\n526\r\nOsco, Illinois\r\n522\r\nPekin, Illinois\r\n346\r\n347\r\n353\r\n477\r\nPeoria Bar, Illinois\r\n633\r\n697\r\nPeoria Bluff, Illinois\r\n679\r\n681\r\n682\r\n685\r\n686\r\n688\r\n494\r\n497\r\n635\r\n637\r\n655\r\n657\r\n671\r\n672\r\n673\r\n674\r\n675\r\n676\r\n677\r\n696\r\n999\r\nPeoria North, Illinois\r\n678\r\n689\r\n691\r\n692\r\n693\r\nPeoria East, Illinois\r\n694\r\n698\r\n699\r\nPlymouth, Illinois\r\n458\r\nPort Byron, Illinois\r\n523\r\nPrairie City, Illinois\r\n775\r\nPreemption, Illinois\r\n534\r\nPrinceville, Illinois\r\n385\r\nRaritan, Illinois\r\n746\r\nReynolds, Illinois\r\n372\r\nRio, Illinois\r\n872\r\nRoanoke, Illinois\r\n923\r\nRock Island, Illinois\r\n798\r\n756\r\n787\r\n737\r\n781\r\n782\r\n786\r\n788\r\n793\r\n794\r\nRoseville, Illinois\r\n426\r\nSan Jose, Illinois\r\n247\r\nSaybrook, Illinios\r\n475\r\nSeaton, Illinois\r\n586\r\nSecor, Illinois\r\n744\r\nSherrard, Illinois\r\n593\r\nSmithfield, Illinois\r\n783\r\nSmithshire, Illinois\r\n325\r\nSouth Pekin, Illinois\r\n348\r\nSparland, Illinois\r\n469\r\nSpring Bay, Illinois\r\n822\r\nStanford, Illinios\r\n379\r\nStronghurst, Illinois\r\n924\r\nSummum, Illinois\r\n759\r\nSunnyland, Illinois\r\n745\r\nSwan Creek, Illinois\r\n774\r\nTablegrove, Illinois\r\n758\r\nTalbott, Illinois\r\n545\r\nTopeka, Illinois\r\n535\r\nToulon, Illinois\r\n286\r\nTowanda, Illinios\r\n728\r\nTremont, Illinois\r\n925\r\nTrivoli, Illinois\r\n362\r\nVarna, Illinois\r\n463\r\nVermont, Illinois\r\n784\r\nVictoria, Illinois\r\n879\r\nViola, Illinois\r\n596\r\nWashburn, Illinois\r\n248\r\nWashington, Illinios\r\n444\r\nWataga, Illinois\r\n375\r\nWilliamfield, Illinois\r\n639\r\nWoodhull, Illinois\r\n334\r\nWyoming, Illinois\r\n695\r\nYates City, Illinois\r\n358\r\n\u00035Unknown prefix code (309) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.310",
    "content": "Alamitos, California\r\n930\r\n936\r\nAvalon, California\r\n510\r\nBeverly Hills, California\r\n201\r\n203\r\n205\r\n246\r\n247\r\n270\r\n271\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n281\r\n282\r\n284\r\n285\r\n286\r\n288\r\n289\r\n550\r\n551\r\n552\r\n553\r\n556\r\n557\r\n652\r\n657\r\n659\r\n785\r\n788\r\n843\r\n854\r\n855\r\n858\r\n859\r\n967\r\n358\r\n772\r\n777\r\n888\r\nCompton, California\r\n272\r\n509\r\n668\r\n669\r\n884\r\n885\r\n220\r\n408\r\n529\r\n531\r\n537\r\n601\r\n602\r\n603\r\n604\r\n605\r\n608\r\n609\r\n630\r\n631\r\n632\r\n633\r\n634\r\n635\r\n637\r\n638\r\n639\r\n761\r\n762\r\n763\r\n764\r\n790\r\n886\r\n898\r\nCulver City, California\r\n202\r\n204\r\n280\r\n287\r\n558\r\n559\r\n815\r\n836\r\n837\r\n838\r\n839\r\n840\r\n841\r\n842\r\nDowney, California\r\n401\r\n803\r\n806\r\n861\r\n862\r\n869\r\n904\r\n922\r\n923\r\n927\r\n928\r\n940\r\nEl Segundo, California\r\n322\r\n333\r\n334\r\n335\r\n336\r\n364\r\n414\r\n416\r\n524\r\n606\r\n607\r\n615\r\n616\r\n640\r\n647\r\n648\r\n726\r\nGardena, California\r\n213\r\n353\r\n366\r\n380\r\n503\r\n504\r\n505\r\n508\r\n561\r\n600\r\n612\r\n613\r\n614\r\n617\r\n701\r\n710\r\n713\r\n716\r\n717\r\n718\r\n880\r\n990\r\n992\r\n993\r\n994\r\n995\r\n217\r\n323\r\n324\r\n327\r\n329\r\n352\r\n354\r\n501\r\n502\r\n512\r\n515\r\n516\r\n523\r\n527\r\n532\r\n538\r\n715\r\n719\r\n767\r\n768\r\n769\r\nHawthorne, California\r\n263\r\n725\r\n219\r\n297\r\n331\r\n332\r\n355\r\n363\r\n535\r\n536\r\n643\r\n644\r\n675\r\n676\r\n679\r\n812\r\n813\r\n814\r\n970\r\n978\r\nInglewood, California\r\n419\r\n215\r\n216\r\n330\r\n337\r\n338\r\n348\r\n410\r\n412\r\n417\r\n418\r\n568\r\n641\r\n642\r\n645\r\n646\r\n649\r\n670\r\n671\r\n672\r\n673\r\n674\r\n677\r\nLa Habra, California\r\n690\r\n691\r\n694\r\n697\r\n902\r\n905\r\n943\r\n947\r\nLos Angeles, California\r\n853\r\n520\r\nLakewood, California\r\n405\r\n629\r\n931\r\n932\r\n934\r\n935\r\n938\r\n210\r\n420\r\n421\r\n425\r\n429\r\n496\r\n497\r\n593\r\n982\r\nLawndale, California\r\n973\r\nLomita, California\r\n325\r\n326\r\n517\r\n530\r\n534\r\n784\r\nLong Beach, California\r\n218\r\n422\r\n423\r\n424\r\n426\r\n427\r\n428\r\n432\r\n435\r\n436\r\n437\r\n490\r\n491\r\n492\r\n495\r\n499\r\n570\r\n590\r\n591\r\n595\r\n599\r\n901\r\n933\r\n980\r\n981\r\n983\r\n984\r\n988\r\n989\r\n997\r\nLos Alamitos, California\r\n430\r\n431\r\n433\r\n434\r\n438\r\n439\r\n493\r\n494\r\n498\r\n592\r\n594\r\n596\r\n597\r\n598\r\n795\r\n797\r\n799\r\n985\r\n986\r\n987\r\nMalibu, California\r\n589\r\n317\r\n456\r\n457\r\nMar Vista, California\r\n577\r\n915\r\n301\r\n302\r\n305\r\n306\r\n313\r\n390\r\n391\r\n397\r\n398\r\n448\r\n572\r\n574\r\n576\r\n578\r\n821\r\n822\r\n823\r\n827\r\nNorwalk, California\r\n460\r\n461\r\n462\r\n465\r\n467\r\n916\r\n402\r\n403\r\n404\r\n406\r\n407\r\n409\r\n802\r\n804\r\n807\r\n809\r\n860\r\n863\r\n864\r\n865\r\n866\r\n867\r\n868\r\n920\r\n921\r\n924\r\n925\r\n926\r\n929\r\nPico Rivera, California\r\n949\r\n692\r\n695\r\n699\r\n801\r\n908\r\n942\r\n948\r\nRedondo, California\r\n937\r\n939\r\nRedondo Beach, California\r\n214\r\n316\r\n318\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n540\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n791\r\n792\r\n793\r\n796\r\n798\r\nSan Monica, California\r\n260\r\n261\r\n262\r\n580\r\n581\r\n582\r\n583\r\n584\r\n585\r\n587\r\n588\r\nSan Pedro, California\r\n732\r\n952\r\n513\r\n514\r\n518\r\n519\r\n521\r\n522\r\n547\r\n548\r\n549\r\n816\r\n830\r\n831\r\n832\r\n833\r\n834\r\n835\r\nSanta Monica, California\r\n314\r\n315\r\n319\r\n350\r\n392\r\n393\r\n394\r\n395\r\n396\r\n399\r\n449\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n458\r\n459\r\n573\r\n828\r\n829\r\n917\r\nTorrance, California\r\n222\r\n212\r\n320\r\n328\r\n533\r\n539\r\n618\r\n781\r\n782\r\n783\r\n787\r\nWest Los Angeles, California\r\n264\r\n914\r\n996\r\n998\r\n206\r\n207\r\n208\r\n209\r\n312\r\n440\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n470\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n478\r\n479\r\n571\r\n575\r\n794\r\n820\r\n824\r\n825\r\n826\r\nWhittier, California\r\n693\r\n696\r\n698\r\n903\r\n906\r\n907\r\n941\r\n944\r\n945\r\n946\r\n\u00035Unknown prefix code (310) - California\r\n"
  },
  {
    "path": "install/regions/regions.311",
    "content": "Misawa Air Base, Japan\r\n762\r\n\u00035Unknown prefix code (311) Mainland Japan\r\n"
  },
  {
    "path": "install/regions/regions.312",
    "content": "Chicago, Illinois\r\n201\r\n202\r\n203\r\n204\r\n206\r\n207\r\n214\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n229\r\n230\r\n233\r\n235\r\n236\r\n237\r\n238\r\n239\r\n241\r\n242\r\n243\r\n245\r\n247\r\n248\r\n249\r\n250\r\n252\r\n254\r\n257\r\n258\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n271\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n290\r\n291\r\n292\r\n293\r\n294\r\n296\r\n298\r\n300\r\n302\r\n306\r\n308\r\n315\r\n316\r\n320\r\n321\r\n322\r\n324\r\n326\r\n327\r\n329\r\n332\r\n334\r\n335\r\n337\r\n338\r\n339\r\n341\r\n342\r\n345\r\n346\r\n347\r\n348\r\n349\r\n353\r\n357\r\n360\r\n362\r\n363\r\n365\r\n368\r\n372\r\n373\r\n374\r\n375\r\n376\r\n378\r\n379\r\n380\r\n382\r\n384\r\n387\r\n392\r\n394\r\n396\r\n399\r\n400\r\n401\r\n404\r\n407\r\n408\r\n410\r\n415\r\n417\r\n419\r\n421\r\n427\r\n431\r\n433\r\n434\r\n435\r\n436\r\n440\r\n441\r\n443\r\n444\r\n445\r\n451\r\n454\r\n455\r\n456\r\n458\r\n460\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n468\r\n471\r\n472\r\n473\r\n474\r\n476\r\n477\r\n478\r\n479\r\n481\r\n482\r\n483\r\n484\r\n486\r\n487\r\n488\r\n489\r\n490\r\n493\r\n495\r\n497\r\n499\r\n500\r\n502\r\n503\r\n504\r\n507\r\n508\r\n509\r\n514\r\n521\r\n522\r\n523\r\n525\r\n527\r\n528\r\n533\r\n534\r\n535\r\n536\r\n538\r\n539\r\n540\r\n541\r\n542\r\n545\r\n546\r\n548\r\n549\r\n550\r\n551\r\n552\r\n553\r\n554\r\n556\r\n557\r\n558\r\n559\r\n560\r\n561\r\n562\r\n563\r\n565\r\n567\r\n568\r\n569\r\n570\r\n571\r\n572\r\n573\r\n574\r\n575\r\n578\r\n579\r\n580\r\n581\r\n582\r\n583\r\n585\r\n586\r\n587\r\n588\r\n589\r\n590\r\n592\r\n594\r\n600\r\n601\r\n602\r\n604\r\n606\r\n607\r\n608\r\n609\r\n613\r\n616\r\n618\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n629\r\n630\r\n631\r\n633\r\n634\r\n637\r\n638\r\n639\r\n640\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n648\r\n649\r\n650\r\n651\r\n654\r\n655\r\n657\r\n658\r\n659\r\n660\r\n661\r\n663\r\n664\r\n665\r\n666\r\n667\r\n669\r\n670\r\n672\r\n682\r\n683\r\n684\r\n685\r\n686\r\n688\r\n689\r\n693\r\n694\r\n697\r\n701\r\n702\r\n703\r\n704\r\n705\r\n707\r\n712\r\n714\r\n715\r\n716\r\n718\r\n720\r\n721\r\n722\r\n723\r\n725\r\n726\r\n727\r\n728\r\n730\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n739\r\n740\r\n741\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n750\r\n751\r\n752\r\n753\r\n755\r\n758\r\n759\r\n760\r\n761\r\n762\r\n763\r\n764\r\n765\r\n767\r\n768\r\n769\r\n770\r\n771\r\n772\r\n774\r\n775\r\n776\r\n777\r\n778\r\n779\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n787\r\n789\r\n790\r\n791\r\n792\r\n793\r\n794\r\n796\r\n797\r\n802\r\n804\r\n805\r\n807\r\n808\r\n812\r\n813\r\n814\r\n819\r\n820\r\n821\r\n822\r\n825\r\n826\r\n828\r\n829\r\n831\r\n835\r\n836\r\n837\r\n838\r\n839\r\n840\r\n842\r\n845\r\n846\r\n847\r\n849\r\n850\r\n851\r\n853\r\n854\r\n855\r\n856\r\n857\r\n859\r\n861\r\n862\r\n864\r\n868\r\n871\r\n873\r\n874\r\n875\r\n876\r\n877\r\n878\r\n879\r\n880\r\n881\r\n883\r\n884\r\n886\r\n887\r\n889\r\n890\r\n891\r\n892\r\n894\r\n899\r\n901\r\n902\r\n903\r\n904\r\n906\r\n907\r\n908\r\n909\r\n914\r\n915\r\n917\r\n918\r\n919\r\n920\r\n921\r\n922\r\n923\r\n924\r\n925\r\n927\r\n928\r\n929\r\n930\r\n931\r\n932\r\n933\r\n934\r\n935\r\n936\r\n938\r\n939\r\n941\r\n942\r\n943\r\n944\r\n945\r\n946\r\n947\r\n949\r\n951\r\n954\r\n955\r\n961\r\n962\r\n972\r\n973\r\n974\r\n975\r\n977\r\n978\r\n979\r\n982\r\n983\r\n984\r\n986\r\n987\r\n988\r\n989\r\n992\r\n993\r\n994\r\n995\r\n996\r\n997\r\nUniversity Of Illinois, Chicago, Illinios\r\n413\r\n\u00035Unknown prefix code (312) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.313",
    "content": "Algonac, Michigan\r\n748\r\n794\r\nAlmont, Michigan\r\n798\r\nAnn Arbor, Michigan\r\n509\r\n662\r\n663\r\n665\r\n668\r\n677\r\n741\r\n747\r\n761\r\n763\r\n764\r\n769\r\n930\r\n936\r\n971\r\n973\r\n994\r\n995\r\n996\r\n998\r\nApplegate, Michigan\r\n633\r\nArmada, Michigan\r\n784\r\nAuburn Heights, Michigan\r\n299\r\n852\r\n853\r\nAvoca, Michigan\r\n324\r\nBelleville, Michigan\r\n697\r\n699\r\n957\r\nBirmingham, Michigan\r\n258\r\n265\r\n300\r\n400\r\n402\r\n410\r\n418\r\n433\r\n540\r\n550\r\n618\r\n637\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n649\r\n696\r\n701\r\n815\r\n816\r\n820\r\n901\r\n919\r\n952\r\nBrighton, Michigan\r\n220\r\n227\r\n229\r\n231\r\nBrown City, Michigan\r\n346\r\nBurton, Michigan\r\n234\r\n744\r\nByron, Michigan\r\n266\r\nCapac, Michigan\r\n395\r\nCarleton, Michigan\r\n654\r\nCarsonvl, Michigan\r\n404\r\n657\r\n710\r\nCenterline, Michigan\r\n492\r\n497\r\n558\r\n573\r\n574\r\n575\r\n578\r\n751\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n947\r\n986\r\nChelsea, Michigan\r\n475\r\nClarkston, Michigan\r\n394\r\n620\r\n625\r\nCliomtmors, Michigan\r\n640\r\n686\r\n687\r\nColumbiavl, Michigan\r\n793\r\nCommerce, Michigan\r\n360\r\n363\r\n698\r\nCroswell, Michigan\r\n679\r\nDavison, Michigan\r\n653\r\n658\r\nDeckervl, Michigan\r\n376\r\nDetroit-Free, Michigan\r\n260\r\n601\r\n606\r\n609\r\n660\r\n705\r\n709\r\nDetroit, Michigan\r\n222\r\n223\r\n224\r\n225\r\n226\r\n237\r\n256\r\n259\r\n298\r\n310\r\n318\r\n330\r\n361\r\n393\r\n396\r\n430\r\n431\r\n441\r\n446\r\n472\r\n494\r\n496\r\n505\r\n515\r\n520\r\n536\r\n556\r\n567\r\n568\r\n577\r\n596\r\n608\r\n613\r\n706\r\n719\r\n745\r\n770\r\n801\r\n808\r\n819\r\n830\r\n831\r\n832\r\n833\r\n840\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n894\r\n895\r\n896\r\n897\r\n898\r\n899\r\n917\r\n961\r\n962\r\n963\r\n964\r\n965\r\n972\r\n974\r\n976\r\n983\r\n993\r\n245\r\n267\r\n331\r\n343\r\n371\r\n372\r\n499\r\n521\r\n526\r\n527\r\n571\r\n579\r\n605\r\n821\r\n822\r\n823\r\n824\r\n839\r\n881\r\n882\r\n884\r\n885\r\n886\r\n921\r\n922\r\n923\r\n924\r\n925\r\n926\r\n252\r\n365\r\n366\r\n368\r\n369\r\n564\r\n865\r\n866\r\n867\r\n868\r\n869\r\n883\r\n891\r\n892\r\n893\r\n956\r\n270\r\n272\r\n273\r\n341\r\n342\r\n345\r\n491\r\n493\r\n507\r\n508\r\n834\r\n835\r\n836\r\n837\r\n838\r\n861\r\n862\r\n863\r\n864\r\n927\r\n929\r\n931\r\n933\r\n934\r\n935\r\n966\r\n249\r\n255\r\n275\r\n276\r\n306\r\n320\r\n321\r\n328\r\n440\r\n444\r\n460\r\n514\r\n531\r\n532\r\n533\r\n534\r\n535\r\n537\r\n538\r\n560\r\n592\r\n599\r\n690\r\n780\r\n818\r\n829\r\n937\r\n940\r\n980\r\n240\r\n248\r\n271\r\n274\r\n277\r\n278\r\n291\r\n292\r\n295\r\n297\r\n317\r\n322\r\n323\r\n336\r\n337\r\n381\r\n382\r\n383\r\n386\r\n388\r\n389\r\n390\r\n436\r\n554\r\n561\r\n562\r\n563\r\n565\r\n581\r\n582\r\n584\r\n593\r\n594\r\n730\r\n841\r\n842\r\n843\r\n845\r\n846\r\n849\r\n928\r\n943\r\n945\r\nDexter, Michigan\r\n426\r\nDraytonpls, Michigan\r\n623\r\n666\r\n673\r\n674\r\nDryden, Michigan\r\n796\r\nDundee, Michigan\r\n529\r\nEmmett, Michigan\r\n384\r\nErie, Michigan\r\n848\r\nFarmington, Michigan\r\n308\r\n309\r\n406\r\n442\r\n450\r\n471\r\n473\r\n474\r\n476\r\n477\r\n478\r\n488\r\n489\r\n553\r\n615\r\n704\r\n870\r\nFenton, Michigan\r\n629\r\n750\r\nFlat Rock, Michigan\r\n782\r\n783\r\nFlint, Michigan\r\n230\r\n232\r\n233\r\n234\r\n235\r\n236\r\n238\r\n239\r\n250\r\n251\r\n257\r\n301\r\n502\r\n732\r\n733\r\n736\r\n742\r\n743\r\n744\r\n760\r\n762\r\n766\r\n767\r\n768\r\n785\r\n787\r\n789\r\nFlint-Free, Michigan\r\n714\r\n990\r\nFlushing, Michigan\r\n659\r\nGoodells, Michigan\r\n325\r\nGoodrich, Michigan\r\n636\r\nGrand Blanc, Michigan\r\n694\r\n695\r\nGregory, Michigan\r\n498\r\nHadley, Michigan\r\n797\r\nHartland, Michigan\r\n632\r\nHolly, Michigan\r\n634\r\nIda, Michigan\r\n269\r\nImlay City, Michigan\r\n724\r\nJeddo, Michigan\r\n327\r\nLake Orion, Michigan\r\n693\r\nLambertvl, Michigan\r\n854\r\n856\r\nLapeer, Michigan\r\n664\r\n667\r\nLennon, Michigan\r\n621\r\nLexington, Michigan\r\n359\r\nLinden, Michigan\r\n735\r\nLivonia, Michigan\r\n261\r\n421\r\n422\r\n425\r\n427\r\n458\r\n462\r\n464\r\n513\r\n522\r\n523\r\n525\r\n591\r\n953\r\nLost Peninsula, Michigan\r\n723\r\nManchester, Michigan\r\n428\r\nMarine City, Michigan\r\n765\r\nMaybee, Michigan\r\n587\r\nMayfair, Michigan\r\n539\r\n626\r\n661\r\n737\r\n788\r\n851\r\n855\r\n932\r\nMemphis, Michigan\r\n392\r\nMetamora, Michigan\r\n678\r\nMilan, Michigan\r\n439\r\nMlfd Wh Lake, Michigan\r\n684\r\n685\r\n887\r\n889\r\nMonroe, Michigan\r\n241\r\n242\r\n243\r\n289\r\n457\r\nMontrose, Michigan\r\n639\r\nMt Clemens, Michigan\r\n228\r\n263\r\n286\r\n307\r\n463\r\n465\r\n466\r\n468\r\n469\r\n598\r\n790\r\n791\r\n792\r\n949\r\n954\r\nMundy Township, Michigan\r\n655\r\nNew Baltimore, Michigan\r\n716\r\n725\r\nNew Boston, Michigan\r\n753\r\nB02\r\nNew Haven, Michigan\r\n749\r\nB03\r\nNewlothrop, Michigan\r\n638\r\nNewport, Michigan\r\n586\r\nNorth Branch, Michigan\r\n688\r\nNorthville, Michigan\r\n305\r\n344\r\n347\r\n348\r\n349\r\n380\r\nB04\r\nB05\r\nNosylvania, Michigan\r\n888\r\nOrtonville, Michigan\r\n627\r\nOtisville, Michigan\r\n631\r\nOxford, Michigan\r\n628\r\n969\r\nB06\r\nPeck, Michigan\r\n378\r\nPetersburg, Michigan\r\n279\r\nPinckney, Michigan\r\n878\r\nB07\r\nPlymouth, Michigan\r\n416\r\n420\r\n451\r\n453\r\n454\r\n455\r\n459\r\n981\r\nB08\r\nB09\r\nPontiac, Michigan\r\n253\r\n332\r\n333\r\n334\r\n335\r\n338\r\n339\r\n340\r\n370\r\n373\r\n377\r\n391\r\n452\r\n456\r\n555\r\n576\r\n681\r\n682\r\n683\r\n738\r\n857\r\n858\r\nB10\r\nB11\r\nB12\r\nB13\r\nB54\r\nPort Huron, Michigan\r\n364\r\n385\r\n982\r\n984\r\n985\r\n987\r\n989\r\nB14\r\nB15\r\nPort Sanilac, Michigan\r\nB16\r\n622\r\nRankin, Michigan\r\n655\r\nRichmond, Michigan\r\n727\r\nRochester, Michigan\r\n375\r\n650\r\n651\r\n652\r\n656\r\nB17\r\nRockwood, Michigan\r\n379\r\nB18\r\nRomeo, Michigan\r\n752\r\nB19\r\nB20\r\nRomolus, Michigan\r\n955\r\n941\r\n942\r\n946\r\nB21\r\nB22\r\nRoseville, Michigan\r\n293\r\n294\r\n296\r\n415\r\n445\r\n447\r\n771\r\n772\r\n773\r\n774\r\n775\r\n776\r\n777\r\n778\r\n779\r\nB23\r\nB24\r\nRoyal Oak, Michigan\r\n280\r\n288\r\n398\r\n399\r\n414\r\n435\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n547\r\n548\r\n549\r\n551\r\n583\r\n585\r\n588\r\n589\r\n597\r\n691\r\n967\r\n968\r\nB25\r\nSaint Clair, Michigan\r\n329\r\nB26\r\nSaline, Michigan\r\n429\r\n944\r\nSandusky, Michigan\r\n648\r\nB27\r\nSmiths Creek, Michigan\r\n367\r\nSnover, Michigan\r\n672\r\nSouth Lyon, Michigan\r\n437\r\n486\r\nB28\r\nSouthfield, Michigan\r\n262\r\n290\r\n302\r\n304\r\n319\r\n350\r\n351\r\n352\r\n353\r\n354\r\n355\r\n356\r\n357\r\n358\r\n401\r\n403\r\n405\r\n407\r\n409\r\n423\r\n424\r\n443\r\n470\r\n500\r\n501\r\n510\r\n518\r\n530\r\n552\r\n557\r\n559\r\n569\r\n570\r\n580\r\n590\r\n600\r\n604\r\n610\r\n630\r\n670\r\n720\r\n746\r\n799\r\n807\r\n827\r\n902\r\n903\r\n908\r\n909\r\n910\r\n920\r\n938\r\n948\r\nB29\r\nB30\r\nSwartz Creek, Michigan\r\n635\r\nTaylor-Wic, Michigan\r\nB31\r\nTemperance, Michigan\r\n847\r\nTrenton, Michigan\r\n671\r\n675\r\n676\r\n692\r\nB32\r\nB33\r\nTroy, Michigan\r\n244\r\n362\r\n524\r\n528\r\n680\r\n689\r\n740\r\n828\r\n879\r\nB34\r\nB35\r\nB36\r\nB37\r\nUtica, Michigan\r\n247\r\n254\r\n566\r\n726\r\n731\r\n739\r\nB38\r\nB39\r\nWalled Lake, Michigan\r\nB40\r\n624\r\n669\r\n960\r\nWarren, Michigan\r\n264\r\n268\r\n795\r\n825\r\n826\r\n939\r\n977\r\n978\r\n979\r\nB41\r\nB42\r\nB43\r\nB44\r\nWashington, Michigan\r\n781\r\n786\r\nB45\r\nWayne, Michigan\r\n326\r\n397\r\n467\r\n595\r\n721\r\n722\r\n728\r\n729\r\nB46\r\nB47\r\nB55\r\nWest Bloom, Michigan\r\nB48\r\nWhitmore Lake, Michigan\r\nB49\r\n449\r\nWillis, Michigan\r\n461\r\nB50\r\nWyandotte, Michigan\r\n246\r\n281\r\n282\r\n283\r\n284\r\n285\r\n287\r\n374\r\n479\r\nB51\r\nYale, Michigan\r\n387\r\nYpsilanti, Michigan\r\n434\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n487\r\n495\r\n572\r\nB52\r\nB53\r\n\u00035Unknown prefix code (313) - Michigan\r\n"
  },
  {
    "path": "install/regions/regions.314",
    "content": "Advance, Missouri\r\n722\r\nAltonburg Fro, Missouri\r\n824\r\nAnnapolis, Missouri\r\n598\r\nAntonia, Missouri\r\n948\r\nArgyle, Missouri\r\n728\r\nArnold, Missouri\r\n296\r\nAshland, Missouri\r\n657\r\nAugusta, Missouri\r\n228\r\nAuxvasse, Missouri\r\n386\r\nBeaufort, Missouri\r\n484\r\nBelgrade, Missouri\r\n766\r\nBell City, Missouri\r\n733\r\nBelle, Missouri\r\n859\r\nBelleview, Missouri\r\n697\r\nBellflower, Missouri\r\n929\r\nBenton, Missouri\r\n545\r\nBerger, Missouri\r\n834\r\nBernie, Missouri\r\n293\r\nBig Spring, Missouri\r\n252\r\nBirch Tree, Missouri\r\n292\r\nBismarck, Missouri\r\n734\r\nBland, Missouri\r\n646\r\nBloomfield, Missouri\r\n568\r\nBloomsdale, Missouri\r\n483\r\nBlytheville, Missouri\r\n720\r\nBonneterre, Missouri\r\n358\r\nBoss, Missouri\r\n626\r\nBourbon, Missouri\r\n732\r\nBowling Green, Missouri\r\n324\r\n470\r\nBrazito, Missouri\r\n496\r\nBridgeton, Missouri\r\n895\r\n232\r\n233\r\n234\r\n291\r\n298\r\n344\r\n551\r\n731\r\n739\r\n770\r\n777\r\nBuckhorn, Missouri\r\n774\r\nBunker, Missouri\r\n689\r\nCaledonia, Missouri\r\n779\r\nCalifornia, Missouri\r\n796\r\nCamdenton, Missouri\r\n346\r\n873\r\nCampbell, Missouri\r\n246\r\nCanton, Missouri\r\n288\r\nCape Grardu, Missouri\r\n290\r\n334\r\n335\r\n339\r\n651\r\nCardwell, Missouri\r\n654\r\nCaruthrsville, Missouri\r\n333\r\nCedar Hill, Missouri\r\n285\r\nCenter, Missouri\r\n267\r\nCentertown, Missouri\r\n584\r\nCenterville, Missouri\r\n648\r\nCentralia, Missouri\r\n682\r\nChaffee, Missouri\r\n887\r\nChamois, Missouri\r\n763\r\nCharleston, Missouri\r\n683\r\nCherryville, Missouri\r\n743\r\nChesterfield, Missouri\r\n489\r\n529\r\n530\r\n532\r\n536\r\n537\r\nClark, Missouri\r\n641\r\nClarksburg, Missouri\r\n787\r\nClarksville, Missouri\r\n242\r\nClearwater Lake, Missouri\r\n461\r\nClimax Springs, Missouri\r\n345\r\n347\r\nClubb, Missouri\r\n495\r\nColumbia, Missouri\r\n442\r\n443\r\n445\r\n446\r\n449\r\n474\r\n499\r\n864\r\n874\r\n875\r\n876\r\n881\r\n882\r\n884\r\n886\r\nCreve Coeur, Missouri\r\n275\r\n434\r\n453\r\n469\r\n523\r\n542\r\n576\r\n851\r\n878\r\n579\r\nCrocker, Missouri\r\n736\r\nCuba, Missouri\r\n885\r\nDardenne, Missouri\r\n625\r\nDe Soto, Missouri\r\n586\r\nDeering, Missouri\r\n757\r\nDefiance, Missouri\r\n987\r\nDelta, Missouri\r\n794\r\nDexter, Missouri\r\n624\r\nDixon, Missouri\r\n759\r\nDoniphan, Missouri\r\n996\r\nEast Prairie, Missouri\r\n649\r\nEdgar Springs, Missouri\r\n435\r\nEldon, Missouri\r\n392\r\nEllington, Missouri\r\n663\r\nEllsinore, Missouri\r\n322\r\nElsberry, Missouri\r\n898\r\nEminence, Missouri\r\n226\r\nEolia, Missouri\r\n485\r\nEssex, Missouri\r\n283\r\nEugene, Missouri\r\n498\r\nEureka, Missouri\r\n587\r\n938\r\nEwing, Missouri\r\n494\r\nFair Dealing, Missouri\r\n857\r\nFarber, Missouri\r\n249\r\nFarmington, Missouri\r\n756\r\nFenton, Missouri\r\n326\r\n343\r\n349\r\n861\r\nFerguson, Missouri\r\n680\r\n263\r\n521\r\n522\r\n524\r\n595\r\nFestus\u00031/\u00032Crystal City, Missouri\r\n909\r\n931\r\n933\r\n937\r\nFisk, Missouri\r\n967\r\nFlat River, Missouri\r\n431\r\nFlorissant, Missouri\r\n831\r\n837\r\n838\r\n839\r\n921\r\n830\r\nFoley, Missouri\r\n662\r\nForistell, Missouri\r\n673\r\nFrankford, Missouri\r\n784\r\nFredrickton, Missouri\r\n783\r\nFreeburg, Missouri\r\n744\r\nFremont, Missouri\r\n251\r\nFort Leonardwood, Missouri\r\n329\r\n563\r\n596\r\nFulton, Missouri\r\n220\r\n592\r\n642\r\nGarwood, Missouri\r\n945\r\nGerald, Missouri\r\n764\r\nGideon, Missouri\r\n448\r\nGrandin, Missouri\r\n593\r\nGravois Mills, Missouri\r\n372\r\n374\r\nGreenville, Missouri\r\n224\r\nGrey Summit, Missouri\r\n742\r\nHallsville, Missouri\r\n696\r\nHannibal, Missouri\r\n221\r\n248\r\nHarvester, Missouri\r\n320\r\n441\r\n447\r\n476\r\n922\r\n926\r\n928\r\n936\r\nHatton, Missouri\r\n387\r\nHawk Point, Missouri\r\n338\r\nHayti, Missouri\r\n359\r\nHerculaneum, Missouri\r\n478\r\nHermann, Missouri\r\n486\r\nHigh Hill, Missouri\r\n585\r\nHigh Ridge, Missouri\r\n375\r\n376\r\n671\r\n677\r\nHillsboro, Missouri\r\n789\r\nHolcomb, Missouri\r\n792\r\nHolstein, Missouri\r\n932\r\nHornersville, Missouri\r\n737\r\nHunnewell, Missouri\r\n983\r\nHuzzah, Missouri\r\n786\r\nIberia, Missouri\r\n793\r\nImperial, Missouri\r\n464\r\n467\r\nImperial\u00031/\u00032Otto, MIssouri\r\n942\r\nIrondale, Missouri\r\n749\r\nIronton, Missouri\r\n546\r\nJackson, Missouri\r\n243\r\nJapan, Missouri\r\n627\r\nJefferson City, Missouri\r\n526\r\n634\r\n635\r\n636\r\n659\r\n681\r\n751\r\n761\r\n893\r\n896\r\nJonesburg, Missouri\r\n488\r\nKirkwood, Missouri\r\n821\r\n822\r\n957\r\n965\r\n966\r\n984\r\nLa Grange, Missouri\r\n655\r\nLaddonia, Missouri\r\n373\r\nLadue, Missouri\r\n981\r\n432\r\n567\r\n569\r\n694\r\n872\r\n991\r\n993\r\n994\r\n995\r\n997\r\nLake Ozark, Missouri\r\n365\r\nLeadwood, Missouri\r\n562\r\nLeasburg, Missouri\r\n245\r\nLesterville, Missouri\r\n637\r\nLewistown, Missouri\r\n497\r\nLicking, Missouri\r\n674\r\nLilbourn, Missouri\r\n688\r\nLinn, Missouri\r\n897\r\nLkozkosbch, Missouri\r\n348\r\nLouisiana, Missouri\r\n754\r\nLyon, Missouri\r\n459\r\nMackscreek, Missouri\r\n363\r\nMalden, Missouri\r\n276\r\nManchester, Missouri\r\n227\r\n230\r\n256\r\n391\r\n394\r\n527\r\n891\r\nMarble Hill, Missouri\r\n238\r\nMarston, Missouri\r\n643\r\nMarthasville, Missouri\r\n433\r\nMartinsberg, Missouri\r\n492\r\nMaxville, Missouri\r\n287\r\n282\r\nMehlville, Missouri\r\n487\r\n892\r\n894\r\nMeta, Missouri\r\n229\r\nMexico, Missouri\r\n473\r\n581\r\nMiddletown, Missouri\r\n549\r\nMokane, Missouri\r\n676\r\nMonroe City, Missouri\r\n735\r\nMontauk, Missouri\r\n548\r\nMontgomery City, Missouri\r\n564\r\nMonticello, Missouri\r\n767\r\nMorehouse, Missouri\r\n667\r\nMorrison, Missouri\r\n294\r\nMoscow Mills, Missouri\r\n356\r\nMount Sterling, Missouri\r\n943\r\nNaylor, Missouri\r\n399\r\nNeelyville, Missouri\r\n989\r\nNew Bloomfield, Missouri\r\n491\r\nNew Hartford, Missouri\r\n669\r\nNew Haven, Missouri\r\n237\r\nNew London, Missouri\r\n985\r\nNew Madrid, Missouri\r\n748\r\nNew Melle, Missouri\r\n828\r\nNewburg, Missouri\r\n762\r\nNew Florence, Missouri\r\n835\r\nO'Fallon, Missouri\r\n272\r\n281\r\nOak Ridge, Missouri\r\n266\r\nOakville, Missouri\r\n846\r\nOates, Missouri\r\n269\r\nOld Monroe, Missouri\r\n665\r\nOld Appleton, Missouri\r\n788\r\nOlney, Missouri\r\n656\r\nOran, Missouri\r\n262\r\nOrchard Farm, Missouri\r\n258\r\nOverland, Missouri\r\n490\r\n870\r\n253\r\n423\r\n424\r\n426\r\n427\r\n428\r\n429\r\n538\r\nOwensville, Missouri\r\n437\r\nOxly, Missouri\r\n354\r\nPacific, Missouri\r\n257\r\nPalmyra, Missouri\r\n769\r\nParma, Missouri\r\n357\r\nPatterson, Missouri\r\n856\r\nPatton, Missouri\r\n866\r\nPaynesville, Missouri\r\n847\r\nPerry, Missouri\r\n565\r\nPerryville, Missouri\r\n547\r\nPevely, Missouri\r\n475\r\n479\r\nPhiladelphia, Missouri\r\n439\r\nPiedmont, Missouri\r\n223\r\nPocahontas, Missouri\r\n833\r\nPond, Missouri\r\n273\r\n458\r\nPonder, Missouri\r\n255\r\nPoplar Bluff, Missouri\r\n686\r\n778\r\n785\r\n840\r\nPortage Des Sioux, Missouri\r\n753\r\n899\r\nPortageville, Missouri\r\n379\r\nPotosi, Missouri\r\n438\r\nPuxico, Missouri\r\n222\r\nQulin, Missouri\r\n328\r\nRedford, Missouri\r\n558\r\nRhineland, Missouri\r\n236\r\nRichland, Missouri\r\n765\r\nRichwoods, Missouri\r\n678\r\nRisco, Missouri\r\n396\r\nRiverview, Missouri\r\n388\r\n867\r\n868\r\n869\r\nRocheport, Missouri\r\n698\r\nRolla, Missouri\r\n368\r\n465\r\n341\r\n364\r\nRussellville, Missouri\r\n782\r\nSafe, Missouri\r\n699\r\nSalem, Missouri\r\n729\r\nSanta Fe, Missouri\r\n685\r\nSappington, Missouri\r\n525\r\n755\r\n842\r\n849\r\n853\r\n843\r\nScott City, Missouri\r\n264\r\nSenath, Missouri\r\n738\r\nShelbina, Missouri\r\n588\r\nShelbyville, Missouri\r\n633\r\nSikeston, Missouri\r\n471\r\n472\r\nSilex, Missouri\r\n384\r\nSpanish Lake, Missouri\r\n355\r\n653\r\n741\r\nSpring Bluff, Missouri\r\n457\r\nSaint Clair, Missouri\r\n629\r\nSaint James, Missouri\r\n265\r\nSaint Louis, Missouri\r\n231\r\n235\r\n241\r\n247\r\n259\r\n261\r\n268\r\n270\r\n277\r\n289\r\n321\r\n330\r\n331\r\n340\r\n342\r\n351\r\n352\r\n353\r\n361\r\n362\r\n367\r\n371\r\n381\r\n382\r\n383\r\n385\r\n389\r\n416\r\n420\r\n421\r\n425\r\n436\r\n440\r\n444\r\n454\r\n466\r\n481\r\n520\r\n531\r\n533\r\n534\r\n535\r\n539\r\n541\r\n544\r\n553\r\n554\r\n570\r\n571\r\n572\r\n577\r\n578\r\n621\r\n622\r\n623\r\n631\r\n638\r\n644\r\n645\r\n647\r\n652\r\n658\r\n664\r\n679\r\n721\r\n725\r\n726\r\n727\r\n740\r\n746\r\n747\r\n750\r\n752\r\n758\r\n768\r\n771\r\n772\r\n773\r\n776\r\n781\r\n791\r\n795\r\n799\r\n823\r\n826\r\n829\r\n836\r\n841\r\n845\r\n848\r\n854\r\n855\r\n862\r\n863\r\n865\r\n871\r\n879\r\n889\r\n890\r\n935\r\n941\r\n969\r\n973\r\n982\r\n992\r\n280\r\n284\r\n286\r\n380\r\n450\r\n480\r\n540\r\n550\r\n560\r\n580\r\n590\r\n620\r\n630\r\n670\r\n780\r\n832\r\n920\r\n923\r\n964\r\nSaint Marys, Missouri\r\n543\r\nSaint Robert, Missouri\r\n336\r\nSaint Thomas, Missouri\r\n477\r\nSaint Charles, Missouri\r\n723\r\n724\r\n916\r\n925\r\n939\r\n940\r\n946\r\n947\r\n949\r\nSaint Peters, Missouri\r\n278\r\n279\r\n397\r\n970\r\nStanton, Missouri\r\n927\r\nSteele, Missouri\r\n695\r\nSteelville, Missouri\r\n775\r\nSaint Elizabeth, Missouri\r\n493\r\nSaint Geneveve, Missouri\r\n883\r\nStoutsville, Missouri\r\n672\r\nStover, Missouri\r\n377\r\nSturgeon, Missouri\r\n687\r\nSullivan, Missouri\r\n468\r\n860\r\nSweetwater, Missouri\r\n924\r\nTaos, Missouri\r\n395\r\nTebbetts, Missouri\r\n295\r\nTimber, Missouri\r\n858\r\nTroy, Missouri\r\n528\r\nTruxton, Missouri\r\n597\r\nTuscumbia, Missouri\r\n369\r\nUnion, Missouri\r\n583\r\nValley Park, Missouri\r\n225\r\n825\r\n827\r\nVan Buren, Missouri\r\n323\r\nVandalia, Missouri\r\n594\r\nVersailles, Missouri\r\n378\r\nViburnum, Missouri\r\n244\r\nVichy, Missouri\r\n299\r\nVienna, Missouri\r\n422\r\nWapapelo Park, Missouri\r\n297\r\nWardell, Missouri\r\n628\r\nWare, Missouri\r\n944\r\nWarrenton, Missouri\r\n456\r\nWashington, Missouri\r\n239\r\n390\r\nWebster Groves, Missouri\r\n888\r\n961\r\n962\r\n963\r\n968\r\nWellsville, Missouri\r\n684\r\nWentzville, Missouri\r\n327\r\n639\r\nWestphalia, Missouri\r\n455\r\nWest Quincy, Missouri\r\n393\r\nWilliamsburg, Missouri\r\n254\r\nWilliamsville, Missouri\r\n998\r\nWinfield, Missouri\r\n668\r\nWinona, Missouri\r\n325\r\nWright City, Missouri\r\n745\r\nWyatt, Missouri\r\n675\r\n\u00035Unknown prefix code (314) - Missouri\r\n"
  },
  {
    "path": "install/regions/regions.315",
    "content": "Adams, New York\r\n232\r\nAdams Center, New York\r\n583\r\nAlexanderaby, New York\r\n482\r\nAmber, New York\r\n636\r\nAntwerp, New York\r\n659\r\nAuburn, New York\r\n246\r\n252\r\n253\r\n255\r\n258\r\nBaldwinsvale, New York\r\n635\r\n638\r\nBarneveld, New York\r\n896\r\nBelleville, New York\r\n846\r\nBoonville, New York\r\n942\r\nBranchport, New York\r\n595\r\nBridgeport, New York\r\n633\r\nBrookfield, New York\r\n899\r\nCamden, New York\r\n245\r\nCamillus, New York\r\n672\r\nCanastota, New York\r\n697\r\nCanton, New York\r\n379\r\n386\r\nCape Vincent, New York\r\n654\r\nCarthage, New York\r\n493\r\nCato, New York\r\n626\r\nCazenovia, New York\r\n655\r\nCentral Square, New York\r\n668\r\n676\r\nChaumont, New York\r\n649\r\nChittenngo, New York\r\n687\r\nCicero, New York\r\n699\r\nClayton, New York\r\n686\r\nClayville, New York\r\n839\r\nCleveland, New York\r\n675\r\nClifton Springs, New York\r\n462\r\nClinton, New York\r\n853\r\n859\r\nClyde, New York\r\n923\r\nConstableville, New York\r\n397\r\nConstantia, New York\r\n623\r\nCopenhagen, New York\r\n688\r\nCroghan, New York\r\n346\r\nDe Ruyter, New York\r\n852\r\nDexter, New York\r\n639\r\nDolgeville, New York\r\n429\r\nEagle Bay, New York\r\n357\r\nEarlville, New York\r\n691\r\nEdwards, New York\r\n562\r\nEvansmills, New York\r\n629\r\nFabius, New York\r\n683\r\nFair Haven, New York\r\n947\r\nFayette, New York\r\n549\r\nFayetteville, New York\r\n637\r\nForestport, New York\r\n392\r\nFulton, New York\r\n591\r\n592\r\n593\r\n598\r\nGeneva, New York\r\n781\r\n787\r\n789\r\nGeorgetown, New York\r\n837\r\nGouverneur, New York\r\n287\r\nHamilton, New York\r\n824\r\nHammond, New York\r\n324\r\nHannibal, New York\r\n564\r\nHarrisville, New York\r\n543\r\nHenderson, New York\r\n938\r\nHerkimer, New York\r\n866\r\n867\r\nHermon, New York\r\n347\r\nHeuvelton, New York\r\n344\r\nHolland Point, New York\r\n865\r\nIlion, New York\r\n894\r\n895\r\nJordan, New York\r\n689\r\nKnoxboro, New York\r\n843\r\nLa Fargeville, New York\r\n658\r\nLafayette, New York\r\n677\r\nLeonardsville, New York\r\n855\r\nLittle Falls, New York\r\n823\r\nLiverpool, New York\r\n622\r\n652\r\nLowville, New York\r\n376\r\nLyons, New York\r\n946\r\nLyonsfalls, New York\r\n348\r\nLysander, New York\r\n678\r\nMacdougall, New York\r\n585\r\nMacedon, New York\r\n986\r\nMacomb, New York\r\n578\r\nMadison, New York\r\n893\r\nMadrid, New York\r\n322\r\nManlius, New York\r\n682\r\nMannsville, New York\r\n465\r\nMarcellus, New York\r\n673\r\nMarion, New York\r\n926\r\nMassena, New York\r\n764\r\n769\r\nMexico, New York\r\n963\r\nMiddleville, New York\r\n891\r\nMinoa, New York\r\n656\r\nMoravia, New York\r\n497\r\nMorristown, New York\r\n375\r\nMorrisvlle, New York\r\n684\r\nMunnsville, New York\r\n495\r\nNatural Bridge, New York\r\n644\r\nNewark, New York\r\n331\r\n332\r\nNewport, New York\r\n845\r\nNew Woodstock, New York\r\n662\r\nNicholville, New York\r\n328\r\nNorth Brookfield, New York\r\n861\r\nNorfolk, New York\r\n384\r\nNorth Rose, New York\r\n587\r\nNorwood, New York\r\n353\r\nOgdensburg, New York\r\n393\r\nOld Forge, New York\r\n369\r\nOneida, New York\r\n361\r\n363\r\n366\r\nOntario, New York\r\n524\r\nOriskny Falls, New York\r\n821\r\nOsceola, New York\r\n599\r\nOswego, New York\r\n341\r\n342\r\n343\r\n349\r\n529\r\nOwasco, New York\r\n784\r\nPalmyra, New York\r\n597\r\nParish, New York\r\n625\r\nPenn Yan, New York\r\n531\r\n536\r\nPhelps, New York\r\n548\r\nPhila, New York\r\n642\r\nPhoenix, New York\r\n695\r\nPoland, New York\r\n826\r\nPoplar Ridge, New York\r\n364\r\nPort Byron, New York\r\n776\r\nPotsdam, New York\r\n262\r\n265\r\n267\r\n268\r\nPulaski, New York\r\n298\r\nRaquette Lake, New York\r\n354\r\nRichfield Springs, New York\r\n858\r\nRed Creek, New York\r\n754\r\nRemsen, New York\r\n831\r\nRome, New York\r\n330\r\n335\r\n336\r\n337\r\n338\r\n339\r\nSacketshbr, New York\r\n646\r\nSandycreek, New York\r\n387\r\nSavannah, New York\r\n365\r\nSempronius, New York\r\n496\r\nSeneca Falls, New York\r\n568\r\nSkaneatels, New York\r\n685\r\nSouth Otselic, New York\r\n653\r\nSodus, New York\r\n483\r\nStar Lake, New York\r\n848\r\nSylvan Beach, New York\r\n762\r\nSyracuse, New York\r\n976\r\n977\r\n345\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n438\r\n439\r\n441\r\n442\r\n443\r\n445\r\n446\r\n447\r\n448\r\n449\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n460\r\n463\r\n464\r\n466\r\n467\r\n468\r\n469\r\n470\r\n471\r\n472\r\n473\r\n474\r\n476\r\n477\r\n478\r\n479\r\n484\r\n487\r\n488\r\n490\r\n492\r\n498\r\n540\r\n640\r\n796\r\n920\r\n890\r\n475\r\nTheresa, New York\r\n628\r\nTully, New York\r\n696\r\nUnion Springs, New York\r\n889\r\nUtica, New York\r\n721\r\n724\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n765\r\n767\r\n768\r\n792\r\n793\r\n794\r\n797\r\n798\r\nVernon, New York\r\n829\r\nWest Winfield, New York\r\n822\r\nWaddington, New York\r\n382\r\n388\r\nWaterloo, New York\r\n539\r\nWatertown, New York\r\n771\r\n772\r\n773\r\n774\r\n779\r\n782\r\n783\r\n785\r\n786\r\n788\r\nWaterville, New York\r\n841\r\nWeedsport, New York\r\n834\r\nWesternville, New York\r\n827\r\nWilliamson, New York\r\n589\r\nWilliamston, New York\r\n964\r\nWinthrop, New York\r\n389\r\nWolcott, New York\r\n594\r\n\u00035Unknown prefix code (315) - New York\r\n"
  },
  {
    "path": "install/regions/regions.316",
    "content": "Abbeyvale Plvn, Kansas\r\n259\r\n286\r\nAlbert, Kansas\r\n923\r\nAlden, Kansas\r\n534\r\nAllen, Kansas\r\n528\r\nAltamont, Kansas\r\n784\r\nAltoona, Kansas\r\n568\r\nAmericus, Kansas\r\n443\r\nAndale, Kansas\r\n444\r\n445\r\nAndover, Kansas\r\n733\r\nAnthony, Kansas\r\n842\r\nArcadia, Kansas\r\n638\r\nArgonia, Kansas\r\n435\r\nArkansas City, Kansas\r\n441\r\n442\r\n446\r\nArlington, Kansas\r\n538\r\nArma, Kansas\r\n347\r\nAshland, Kansas\r\n635\r\nAtlanta, Kansas\r\n394\r\nAttica, Kansas\r\n254\r\nAugusta, Kansas\r\n775\r\nBartlett, Kansas\r\n226\r\nBaxter Springs, Kansas\r\n856\r\nBeaumont, Kansas\r\n843\r\nBelleplain, Kansas\r\n488\r\nBelpre, Kansas\r\n995\r\nBenedict, Kansas\r\n698\r\nBenton, Kansas\r\n778\r\nBig Bow, Kansas\r\n495\r\nBluff City, Kansas\r\n967\r\nBrazilton, Kansas\r\n395\r\nBronson, Kansas\r\n939\r\nBucklin, Kansas\r\n826\r\nBuffalo, Kansas\r\n537\r\nBuhler, Kansas\r\n543\r\nBurden, Kansas\r\n438\r\nBurdett, Kansas\r\n525\r\nBurlington, Kansas\r\n364\r\nBurns, Kansas\r\n726\r\nBurrton, Kansas\r\n463\r\nBushton, Kansas\r\n562\r\nCaldwell, Kansas\r\n845\r\nCambridge, Kansas\r\n467\r\nCaney, Kansas\r\n879\r\nCanton, Kansas\r\n628\r\nCassoday, Kansas\r\n735\r\nCedar Vale, Kansas\r\n758\r\nCedarpoint, Kansas\r\n274\r\nChanute, Kansas\r\n431\r\nChase, Kansas\r\n938\r\nCheney, Kansas\r\n542\r\nCherokee, Kansas\r\n457\r\nCherryvale, Kansas\r\n336\r\nChetopa, Kansas\r\n236\r\nCimarron, Kansas\r\n855\r\nClaflin, Kansas\r\n587\r\nClearwater, Kansas\r\n545\r\n584\r\nClwh Bently, Kansas\r\n796\r\nCoats, Kansas\r\n893\r\nCoffeyvale, Kansas\r\n251\r\n252\r\n948\r\nColdwater, Kansas\r\n582\r\nColony, Kansas\r\n852\r\nColumbus, Kansas\r\n429\r\n674\r\nConway, Kansas\r\n834\r\nConway Springs, Kansas\r\n456\r\nCoolidge, Kansas\r\n372\r\nCopeland, Kansas\r\n668\r\nCorbin, Kansas\r\n863\r\nCottonwood Falls, Kansas\r\n273\r\nCouncil Grove, Kansas\r\n767\r\nCoyville, Kansas\r\n692\r\nCrestline, Kansas\r\n389\r\nCullison, Kansas\r\n895\r\nCunningham, Kansas\r\n298\r\nDeerfield, Kansas\r\n426\r\nDerby, Kansas\r\n788\r\nDevon, Kansas\r\n829\r\nDexter, Kansas\r\n876\r\nDighton, Kansas\r\n397\r\nDodge City, Kansas\r\n225\r\n227\r\n338\r\n339\r\nDouglass, Kansas\r\n746\r\n747\r\nDunlap, Kansas\r\n787\r\nDurham, Kansas\r\n732\r\nEdna, Kansas\r\n922\r\nEl Dorado, Kansas\r\n321\r\n322\r\n323\r\nElgin, Kansas\r\n346\r\nElk City, Kansas\r\n627\r\nElk Falls, Kansas\r\n329\r\nElkhart, Kansas\r\n697\r\nEllinwood, Kansas\r\n564\r\nEmporia, Kansas\r\n341\r\n342\r\n343\r\n344\r\nEnglewood, Kansas\r\n539\r\nEnsign, Kansas\r\n865\r\nErie, Kansas\r\n244\r\nEureka, Kansas\r\n583\r\nFall River, Kansas\r\n658\r\nFarlington, Kansas\r\n362\r\nFlorence, Kansas\r\n878\r\nFord, Kansas\r\n369\r\nFort Scott, Kansas\r\n223\r\nFowler, Kansas\r\n646\r\nFredonia, Kansas\r\n378\r\nFreeport, Kansas\r\n962\r\nFulton, Kansas\r\n857\r\nGalatia, Kansas\r\n935\r\nGalena, Kansas\r\n783\r\nGalesburg, Kansas\r\n763\r\nGalva, Kansas\r\n654\r\nGarden Place, Kansas\r\n531\r\n535\r\nGarden City, Kansas\r\n272\r\n275\r\n276\r\n277\r\n287\r\nGarfield, Kansas\r\n569\r\nGeneseo, Kansas\r\n824\r\nGeuda Springs, Kansas\r\n447\r\nGirard, Kansas\r\n724\r\nGoddard, Kansas\r\n794\r\nGoessel, Kansas\r\n367\r\nGreat Bend, Kansas\r\n792\r\n793\r\n797\r\nGreensburg, Kansas\r\n723\r\nGrenola, Kansas\r\n358\r\nGridley, Kansas\r\n836\r\nHallowell, Kansas\r\n597\r\nHalstead, Kansas\r\n835\r\nHamilton, Kansas\r\n678\r\nHanston, Kansas\r\n623\r\nHardtner, Kansas\r\n296\r\nHarper, Kansas\r\n896\r\nHartford, Kansas\r\n392\r\nHavana, Kansas\r\n673\r\nHaven, Kansas\r\n465\r\nHaviland, Kansas\r\n862\r\nHazelton, Kansas\r\n239\r\nHealy, Kansas\r\n398\r\nHepler, Kansas\r\n368\r\nHesston, Kansas\r\n327\r\nHewins, Kansas\r\n565\r\nHiattville, Kansas\r\n547\r\nHillsboro, Kansas\r\n947\r\nHoisington, Kansas\r\n653\r\nHoward, Kansas\r\n374\r\nHudson, Kansas\r\n458\r\nHugoton, Kansas\r\n544\r\nHumboldt, Kansas\r\n473\r\nHutchinson, Kansas\r\n662\r\n663\r\n664\r\n665\r\n669\r\n694\r\n727\r\nIndependence, Kansas\r\n331\r\n332\r\nIngalls, Kansas\r\n335\r\nInman, Kansas\r\n585\r\nIola, Kansas\r\n363\r\n365\r\nIsabel, Kansas\r\n739\r\nIuka, Kansas\r\n546\r\nJetmore, Kansas\r\n357\r\nJohnson, Kansas\r\n492\r\nKendall, Kansas\r\n373\r\nKincaid, Kansas\r\n439\r\nKingman, Kansas\r\n532\r\n553\r\nKinsley, Kansas\r\n659\r\nKiowa, Kansas\r\n825\r\nLa Harpe, Kansas\r\n496\r\nLafontaine, Kansas\r\n633\r\nLake City, Kansas\r\n247\r\nLakin, Kansas\r\n355\r\nLangdon, Kansas\r\n596\r\nLarned, Kansas\r\n285\r\nLatham, Kansas\r\n965\r\nLawton, Kansas\r\n643\r\nLe Roy, Kansas\r\n964\r\nLebo, Kansas\r\n256\r\nLehigh, Kansas\r\n483\r\nLeon, Kansas\r\n742\r\n745\r\nLeoti, Kansas\r\n375\r\nLewis, Kansas\r\n324\r\nLiberal, Kansas\r\n621\r\n624\r\n626\r\n629\r\nLiberty, Kansas\r\n485\r\nLincolnville, Kansas\r\n924\r\nLittle River, Kansas\r\n897\r\nLongton, Kansas\r\n642\r\nLyons, Kansas\r\n257\r\nMacksville, Kansas\r\n348\r\nMadison, Kansas\r\n427\r\n437\r\nManter, Kansas\r\n493\r\nMapleton, Kansas\r\n743\r\nMarienthal, Kansas\r\n379\r\nMarion, Kansas\r\n382\r\nMatfieldgren, Kansas\r\n753\r\nMayfield, Kansas\r\n434\r\nMcCune, Kansas\r\n632\r\nMcpherson, Kansas\r\n241\r\n242\r\nMeade, Kansas\r\n873\r\n877\r\nMedicine Ledge, Kansas\r\n886\r\nMinneola, Kansas\r\n885\r\nMoline, Kansas\r\n647\r\nMontezuma, Kansas\r\n846\r\nMoran, Kansas\r\n237\r\nMoscow, Kansas\r\n598\r\nMound Valley, Kansas\r\n328\r\nMoundridge, Kansas\r\n345\r\nMount Hope, Kansas\r\n661\r\n667\r\nMulberry, Kansas\r\n764\r\nMullinville, Kansas\r\n548\r\nMulvane, Kansas\r\n777\r\nMurdock, Kansas\r\n297\r\nNashville, Kansas\r\n246\r\nNeodesha, Kansas\r\n325\r\nNeosho Falls, Kansas\r\n963\r\nNewton, Kansas\r\n283\r\n284\r\nNickerson, Kansas\r\n422\r\nNomanchester, Kansas\r\n693\r\nNorwich, Kansas\r\n478\r\nOlmitz, Kansas\r\n586\r\nOlpe, Kansas\r\n475\r\nOswego, Kansas\r\n795\r\nOxford, Kansas\r\n455\r\nParsons, Kansas\r\n421\r\n423\r\nPartridge, Kansas\r\n567\r\nPawnee Rock, Kansas\r\n982\r\nPeabody, Kansas\r\n983\r\nPenalosa, Kansas\r\n644\r\nPiedmont, Kansas\r\n864\r\nPiqua, Kansas\r\n468\r\nPittsburg, Kansas\r\n231\r\n232\r\n235\r\n249\r\nPlains, Kansas\r\n563\r\nPotwin, Kansas\r\n752\r\nPratt, Kansas\r\n672\r\nPreston, Kansas\r\n656\r\nPretty Prairie, Kansas\r\n459\r\nProtection, Kansas\r\n622\r\nQuincy, Kansas\r\n645\r\nReading, Kansas\r\n699\r\nReece, Kansas\r\n853\r\nRichfield, Kansas\r\n592\r\nRiverdale, Kansas\r\n867\r\nRiverton, Kansas\r\n848\r\nRock, Kansas\r\n986\r\nRolla, Kansas\r\n593\r\nRosalia, Kansas\r\n476\r\nRose Hill, Kansas\r\n776\r\nRozel, Kansas\r\n527\r\nRyus, Kansas\r\n657\r\nSaffordville, Kansas\r\n279\r\nSatanta, Kansas\r\n649\r\nSavonburg, Kansas\r\n754\r\nSawyer, Kansas\r\n594\r\nScammon, Kansas\r\n479\r\nScott City, Kansas\r\n872\r\nSedan, Kansas\r\n725\r\nSedgwick, Kansas\r\n772\r\nSevery, Kansas\r\n736\r\nSharon, Kansas\r\n294\r\nSouthhaven, Kansas\r\n892\r\nSpearville, Kansas\r\n385\r\nSpivey, Kansas\r\n785\r\nSaintt John, Kansas\r\n549\r\nSaintt Paul, Kansas\r\n449\r\nStafford, Kansas\r\n234\r\nSterling, Kansas\r\n278\r\nSublette, Kansas\r\n675\r\nSun City, Kansas\r\n248\r\nSylvia, Kansas\r\n486\r\nSyracuse, Kansas\r\n384\r\nThayer, Kansas\r\n839\r\nToronto, Kansas\r\n637\r\nTowanda, Kansas\r\n536\r\n541\r\nTreece, Kansas\r\n679\r\nTribune, Kansas\r\n376\r\nTuron, Kansas\r\n497\r\nTyro, Kansas\r\n289\r\nUdall, Kansas\r\n782\r\nUlysses, Kansas\r\n353\r\n356\r\nUniontown, Kansas\r\n756\r\nValley Center, Kansas\r\n755\r\nWest Mineral, Kansas\r\n827\r\nWaldron, Kansas\r\n984\r\nWalnut, Kansas\r\n354\r\nWalton, Kansas\r\n837\r\nWeir City, Kansas\r\n396\r\nWellington, Kansas\r\n326\r\n968\r\nWhitewater, Kansas\r\n799\r\nWichita Parkview, Kansas\r\n722\r\n729\r\nWichita\u00031/\u00032Jackson, Kansas\r\n522\r\n523\r\n524\r\n526\r\n529\r\n554\r\nWichita, Kansas\r\n555\r\n261\r\n262\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n291\r\n292\r\n337\r\n352\r\n359\r\n383\r\n436\r\n570\r\n579\r\n634\r\n636\r\n641\r\n648\r\n651\r\n652\r\n655\r\n676\r\n681\r\n682\r\n684\r\n686\r\n687\r\n688\r\n689\r\n734\r\n828\r\n832\r\n833\r\n838\r\n941\r\n943\r\n945\r\n946\r\n976\r\n571\r\n574\r\n263\r\n683\r\n685\r\n721\r\n744\r\n942\r\nWilmore, Kansas\r\n738\r\nWindom, Kansas\r\n489\r\nWinfield, Kansas\r\n221\r\n222\r\nYates Center, Kansas\r\n625\r\nZenda, Kansas\r\n243\r\n\u00035Unknown prefix code (316) - Kansas\r\n"
  },
  {
    "path": "install/regions/regions.317",
    "content": "Acton, Indiana\r\n862\r\nAlbany, Indiana\r\n789\r\nAlexandria, Indiana\r\n724\r\nAmboy Cnvr, Indiana\r\n395\r\nAmo, Indiana\r\n539\r\nAnderson, Indiana\r\n621\r\n622\r\n623\r\n640\r\n641\r\n642\r\n643\r\n644\r\n646\r\n648\r\n649\r\nArlington, Indiana\r\n663\r\nAtlanta, Indiana\r\n292\r\nAttica, Indiana\r\n762\r\n764\r\nBainbridge, Indiana\r\n522\r\nBargersville, Indiana\r\n422\r\nBattleground, Indiana\r\n567\r\nBelle Union, Indiana\r\n526\r\nBloomingdale, Indiana\r\n498\r\nBloutsville, Indiana\r\n774\r\nBoswell, Indiana\r\n869\r\nBridgton, Indiana\r\n548\r\nBrookston, Indiana\r\n563\r\nBrookville, Indiana\r\n647\r\nBrownsburg, Indiana\r\n852\r\nBuck Creek, Indiana\r\n589\r\nBunkerhill, Indiana\r\n682\r\n688\r\n689\r\nBurlington, Indiana\r\n566\r\nCambridge City, Indiana\r\n478\r\nCarmel, Indiana\r\n571\r\n573\r\n574\r\n580\r\n581\r\n582\r\n843\r\n844\r\n846\r\n848\r\nCarthage, Indiana\r\n565\r\nCayuga, Indiana\r\n492\r\nCenterville, Indiana\r\n855\r\nCharlottville, Indiana\r\n936\r\nChesterfield, Indiana\r\n378\r\nCicero, Indiana\r\n984\r\nClarks Hill, Indiana\r\n523\r\nClinton, Indiana\r\n828\r\n665\r\n832\r\nCloverdale, Indiana\r\n795\r\nCoatesville, Indiana\r\n386\r\nColfax, Indiana\r\n324\r\nConnersville, Indiana\r\n825\r\n827\r\nCovington, Indiana\r\n793\r\nCrawfordsville, Indiana\r\n361\r\n362\r\n363\r\n364\r\n366\r\nCumberland, Indiana\r\n891\r\n894\r\nCutler, Indiana\r\n268\r\nDanville, Indiana\r\n745\r\nDarlington, Indiana\r\n794\r\nDelphi, Indiana\r\n564\r\nDenver, Indiana\r\n985\r\nDunkirk, Indiana\r\n768\r\nEaton, Indiana\r\n396\r\nElwood, Indiana\r\n552\r\nEminence, Indiana\r\n528\r\nFairland, Indiana\r\n835\r\nFairmount, Indiana\r\n948\r\nFarmland, Indiana\r\n468\r\nFillmore, Indiana\r\n246\r\nFishers, Indiana\r\n576\r\n577\r\n578\r\n579\r\n588\r\n594\r\n595\r\n841\r\n842\r\n845\r\n849\r\nFortville, Indiana\r\n485\r\nFountain City, Indiana\r\n847\r\nFowler, Indiana\r\n884\r\nFrankfort, Indiana\r\n652\r\n654\r\n659\r\nFranklin, Indiana\r\n736\r\n738\r\nFrankton, Indiana\r\n754\r\nGaston, Indiana\r\n358\r\nGeetingsville, Indiana\r\n258\r\nGlenwood, Indiana\r\n679\r\nGreencastle, Indiana\r\n653\r\n657\r\n658\r\n721\r\nGreenfield, Indiana\r\n462\r\n467\r\nGreens Fork, Indiana\r\n886\r\nGreentown, Indiana\r\n628\r\nGreenwood, Indiana\r\n865\r\n885\r\n887\r\n889\r\n881\r\n882\r\n888\r\nHagerstown, Indiana\r\n486\r\n489\r\nHartford City, Indiana\r\n348\r\nHillsboro, Indiana\r\n798\r\nIndianapolis, Indiana\r\n228\r\n327\r\n334\r\n337\r\n338\r\n367\r\n381\r\n382\r\n388\r\n440\r\n446\r\n479\r\n484\r\n487\r\n568\r\n695\r\n696\r\n726\r\n756\r\n767\r\n897\r\n929\r\n222\r\n226\r\n230\r\n231\r\n232\r\n233\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n247\r\n248\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n259\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n269\r\n271\r\n273\r\n274\r\n276\r\n277\r\n278\r\n283\r\n290\r\n291\r\n293\r\n297\r\n298\r\n299\r\n321\r\n322\r\n328\r\n329\r\n351\r\n352\r\n353\r\n355\r\n356\r\n357\r\n359\r\n375\r\n424\r\n425\r\n431\r\n432\r\n439\r\n441\r\n442\r\n443\r\n445\r\n461\r\n464\r\n465\r\n466\r\n469\r\n470\r\n471\r\n475\r\n481\r\n488\r\n541\r\n542\r\n543\r\n545\r\n546\r\n547\r\n549\r\n556\r\n562\r\n575\r\n624\r\n625\r\n626\r\n627\r\n630\r\n631\r\n632\r\n633\r\n634\r\n635\r\n636\r\n637\r\n638\r\n639\r\n681\r\n684\r\n685\r\n686\r\n687\r\n691\r\n692\r\n693\r\n694\r\n780\r\n781\r\n782\r\n783\r\n784\r\n786\r\n787\r\n788\r\n824\r\n870\r\n871\r\n872\r\n875\r\n876\r\n879\r\n895\r\n898\r\n899\r\n920\r\n921\r\n923\r\n924\r\n925\r\n926\r\n927\r\n928\r\n931\r\nJamestown, Indiana\r\n676\r\nKempton, Indiana\r\n947\r\nKingman, Indiana\r\n397\r\nKirklin, Indiana\r\n279\r\nKnightston, Indiana\r\n345\r\nKokomo, Indiana\r\n434\r\n438\r\n451\r\n454\r\n456\r\n459\r\n863\r\n864\r\n868\r\n452\r\n453\r\n455\r\n457\r\n883\r\nLadoga, Indiana\r\n942\r\nLafayette, Indiana\r\n340\r\n360\r\n420\r\n421\r\n423\r\n426\r\n427\r\n428\r\n429\r\n433\r\n447\r\n448\r\n449\r\n463\r\n474\r\n477\r\n493\r\n494\r\n495\r\n496\r\n497\r\n742\r\n743\r\n746\r\n992\r\nLafontaine, Indiana\r\n981\r\nLapel, Indiana\r\n534\r\nLaurel, Indiana\r\n698\r\nLebanon, Indiana\r\n482\r\n483\r\nLiberty, Indiana\r\n458\r\nLinden, Indiana\r\n339\r\nLizton, Indiana\r\n994\r\nLynn, Indiana\r\n874\r\nManilla, Indiana\r\n544\r\nMarietta, Indiana\r\n729\r\nMarion, Indiana\r\n651\r\n661\r\n662\r\n664\r\n668\r\n669\r\n674\r\n677\r\nMarkleville, Indiana\r\n531\r\n533\r\nMarshall, Indiana\r\n597\r\nMartinsville, Indiana\r\n342\r\n349\r\nMaxwell, Indiana\r\n323\r\n326\r\nMays, Indiana\r\n645\r\nMccordsville, Indiana\r\n335\r\n336\r\nMechanicsburg, Indiana\r\n325\r\n779\r\nMellott, Indiana\r\n295\r\nMichigantown, Indiana\r\n249\r\nMiddletown, Indiana\r\n354\r\nMilroy, Indiana\r\n629\r\nModoc, Indiana\r\n853\r\nMonrovia, Indiana\r\n996\r\nMontezuma, Indiana\r\n245\r\nMontpelier, Indiana\r\n728\r\nMooreland, Indiana\r\n766\r\nMooresville, Indiana\r\n831\r\n834\r\nMorristown, Indiana\r\n763\r\nMorton, Indiana\r\n739\r\nMount Summit, Indiana\r\n836\r\nMulberry, Indiana\r\n296\r\nMuncie, Indiana\r\n281\r\n282\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n741\r\n744\r\n747\r\n748\r\n749\r\n751\r\nNew Castle, Indiana\r\n521\r\n524\r\n527\r\n529\r\n593\r\nNew Lisbon, Indiana\r\n332\r\nNew Market, Indiana\r\n866\r\nNew Ross, Indiana\r\n723\r\nNew Palstone, Indiana\r\n861\r\nNineveh, Indiana\r\n933\r\nNoblesville, Indiana\r\n773\r\n776\r\nOaklandon, Indiana\r\n823\r\nOtterbein, Indiana\r\n583\r\nOxford, Indiana\r\n385\r\nParagon, Indiana\r\n537\r\nPendleton, Indiana\r\n778\r\nPerkinsville, Indiana\r\n734\r\nPeru, Indiana\r\n472\r\n473\r\nPittsboro, Indiana\r\n892\r\nPlainfield, Indiana\r\n272\r\n838\r\n839\r\nRedkey, Indiana\r\n369\r\nReelsville, Indiana\r\n672\r\nRichmond, Indiana\r\n935\r\n962\r\n966\r\n967\r\n969\r\n973\r\n983\r\nRidgeville, Indiana\r\n857\r\nRoann, Indiana\r\n833\r\nRockville, Indiana\r\n344\r\n569\r\nRomney, Indiana\r\n538\r\nRossville, Indiana\r\n379\r\nRushville, Indiana\r\n932\r\n938\r\nSharpsville, Indiana\r\n963\r\nShelbyville, Indiana\r\n392\r\n398\r\nSheridan, Indiana\r\n758\r\nShirley, Indiana\r\n737\r\nSpiceland, Indiana\r\n987\r\nSpringport, Indiana\r\n755\r\nStewart, Indiana\r\n986\r\nSummitville, Indiana\r\n536\r\nSwayzee, Indiana\r\n922\r\nSweetser, Indiana\r\n384\r\nThorntown, Indiana\r\n436\r\nTipton, Indiana\r\n675\r\nTrafalgar, Indiana\r\n878\r\nUnion City, Indiana\r\n964\r\nUpland, Indiana\r\n998\r\nVan Buren, Indiana\r\n934\r\nVeedersburg, Indiana\r\n294\r\nWest Lebanon, Indiana\r\n893\r\nWest Point, Indiana\r\n572\r\nWaldron, Indiana\r\n525\r\nWaveland, Indiana\r\n435\r\nWaynetown, Indiana\r\n234\r\nWest College Corner, Indiana\r\n732\r\nWest Newton, Indiana\r\n856\r\nWest Wabash, Indiana\r\n944\r\nWestfield, Indiana\r\n867\r\n877\r\n896\r\nWhiteland, Indiana\r\n535\r\nWhitestown, Indiana\r\n769\r\nWilkinson, Indiana\r\n785\r\nWinchester, Indiana\r\n584\r\nWindfall, Indiana\r\n945\r\nWingate, Indiana\r\n275\r\nYorktown, Indiana\r\n759\r\nZionsville, Indiana\r\n873\r\n\u00035Unknown prefix code (317) - Indiana\r\n"
  },
  {
    "path": "install/regions/regions.318",
    "content": "Abbeville, Louisiana\r\n893\r\n898\r\nAlexandria, Louisiana\r\n441\r\n444\r\n420\r\n442\r\n443\r\n445\r\n446\r\n447\r\n448\r\n449\r\n473\r\n484\r\n487\r\n466\r\n641\r\nArcadia, Louisiana\r\n263\r\n385\r\nArnaudville, Louisiana\r\n754\r\nAthens, Louisiana\r\n258\r\nBaldwin, Louisiana\r\n923\r\nBasile, Louisiana\r\n432\r\nBastrop, Louisiana\r\n281\r\n283\r\nBelcher, Louisiana\r\n378\r\nBenton, Louisiana\r\n965\r\nBernice, Louisiana\r\n285\r\n778\r\nBig Cane, Louisiana\r\n939\r\nBlanchard, Louisiana\r\n929\r\nBonita, Louisiana\r\n823\r\nBordelonville, Louisiana\r\n997\r\nBoyce, Louisiana\r\n793\r\nBreaux Bridge, Louisiana\r\n332\r\nBroussard, Louisiana\r\n837\r\nBunkie, Louisiana\r\n346\r\nCalcasieu, Louisiana\r\n659\r\nCalhoun, Louisiana\r\n644\r\nCameron, Louisiana\r\n775\r\nCampti, Louisiana\r\n476\r\nCankton, Louisiana\r\n668\r\nCarencro, Louisiana\r\n896\r\nCarlyss, Louisiana\r\n583\r\nCastor, Louisiana\r\n544\r\nCecelia, Louisiana\r\n667\r\nCentervale, Louisiana\r\n836\r\nChataigner, Louisiana\r\n885\r\nChatham, Louisiana\r\n249\r\nCheneyville, Louisiana\r\n279\r\nChoudrant, Louisiana\r\n768\r\nChurch Point, Louisiana\r\n684\r\nColfax, Louisiana\r\n627\r\nCollinston, Louisiana\r\n874\r\nColumbia, Louisiana\r\n649\r\nConverse, Louisiana\r\n567\r\nCotton Valley, Louisiana\r\n832\r\nCottonport, Louisiana\r\n876\r\nCoushatta, Louisiana\r\n932\r\nCreole, Louisiana\r\n542\r\nCreston, Louisiana\r\n875\r\nCrowley, Louisiana\r\n783\r\n788\r\nCrowville, Louisiana\r\n722\r\nDe Quincy, Louisiana\r\n786\r\nDe Ridder, Louisiana\r\n462\r\n463\r\nDelcambre, Louisiana\r\n685\r\nDelhi, Louisiana\r\n878\r\nDelta, Louisiana\r\n633\r\nDoyline, Louisiana\r\n745\r\nDry Prong, Louisiana\r\n899\r\nDubach, Louisiana\r\n777\r\nDuson, Louisiana\r\n873\r\nEagle Lake, Louisiana\r\n275\r\nElizabeth, Louisiana\r\n634\r\nElton, Louisiana\r\n584\r\nEpps, Louisiana\r\n926\r\nErath, Louisiana\r\n937\r\nEunice, Louisiana\r\n457\r\n546\r\nFarmervale, Louisiana\r\n368\r\n982\r\nFenton, Louisiana\r\n756\r\nFerriday, Louisiana\r\n757\r\nFlorien, Louisiana\r\n586\r\nForked Island, Louisiana\r\n642\r\nFranklin, Louisiana\r\n828\r\nFort Necesity, Louisiana\r\n723\r\nFort Polk, Louisiana\r\n535\r\nGeorgetown, Louisiana\r\n827\r\nGibsland, Louisiana\r\n843\r\nGilliam, Louisiana\r\n296\r\nGlenmora, Louisiana\r\n748\r\nGrambling, Louisiana\r\n247\r\n274\r\nGrand Cane, Louisiana\r\n858\r\nGrandchner, Louisiana\r\n538\r\nGreenwood, Louisiana\r\n938\r\nGueydan, Louisiana\r\n536\r\nHackberry, Louisiana\r\n762\r\nHarrisonburg, Louisiana\r\n744\r\nHaughton, Louisiana\r\n949\r\n987\r\nHayes, Louisiana\r\n622\r\nHaynesville, Louisiana\r\n624\r\nHebron, Louisiana\r\n246\r\nHenderson, Louisiana\r\n228\r\nHomer, Louisiana\r\n927\r\nHornbeck, Louisiana\r\n565\r\nHosston, Louisiana\r\n287\r\nIda, Louisiana\r\n284\r\nIota, Louisiana\r\n779\r\nIowa, Louisiana\r\n582\r\nJeanerette, Louisiana\r\n276\r\nJena, Louisiana\r\n992\r\nJennings, Louisiana\r\n821\r\n824\r\nJohson Bayou, Louisiana\r\n569\r\nJonesboro, Louisiana\r\n259\r\nJonesville, Louisiana\r\n339\r\nKaplan, Louisiana\r\n643\r\nKeatchie, Louisiana\r\n933\r\nKeithville, Louisiana\r\n925\r\nKinder, Louisiana\r\n738\r\nKrotz Springs, Louisiana\r\n566\r\nLacassine, Louisiana\r\n588\r\nLafayette, Louisiana\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n261\r\n262\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n278\r\n288\r\n920\r\n273\r\n277\r\n981\r\n984\r\n988\r\n989\r\nLake Arthur, Louisiana\r\n774\r\nLawtell, Louisiana\r\n543\r\nLecompte, Louisiana\r\n776\r\nLeesvale, Louisiana\r\n238\r\n239\r\n286\r\n383\r\n531\r\n537\r\nLeonville, Louisiana\r\n879\r\nLisbon, Louisiana\r\n353\r\nLake Chas, Louisiana\r\n433\r\n436\r\n437\r\n438\r\n439\r\n491\r\n493\r\n494\r\n496\r\n497\r\n474\r\n475\r\n477\r\n478\r\n479\r\n855\r\n882\r\nLake Prov, Louisiana\r\n552\r\n559\r\nLogansport, Louisiana\r\n697\r\nLoreauvale, Louisiana\r\n229\r\nMamou, Louisiana\r\n468\r\nMangham, Louisiana\r\n248\r\nMansfield, Louisiana\r\n872\r\nMansura, Louisiana\r\n964\r\nMany, Louisiana\r\n256\r\nMarion, Louisiana\r\n292\r\nMarksville, Louisiana\r\n253\r\n563\r\nMelville, Louisiana\r\n623\r\nMer Rouge, Louisiana\r\n647\r\nMerryville, Louisiana\r\n825\r\nMinden, Louisiana\r\n371\r\n377\r\nMonroe, Louisiana\r\n322\r\n323\r\n324\r\n325\r\n329\r\n348\r\n361\r\n362\r\n366\r\n372\r\n387\r\n388\r\n342\r\n343\r\n345\r\n396\r\n397\r\n327\r\nMonterey, Louisiana\r\n386\r\nMontgomery, Louisiana\r\n646\r\nMooringsport, Louisiana\r\n996\r\nMoreauville, Louisiana\r\n985\r\nNatchtch, Louisiana\r\n352\r\n357\r\n379\r\nNew Iberia, Louisiana\r\n364\r\n365\r\n367\r\n369\r\n373\r\n374\r\nNewellton, Louisiana\r\n467\r\nOak Grove, Louisiana\r\n428\r\nOak Ridge, Louisiana\r\n244\r\nOakdale, Louisiana\r\n335\r\nOberlin, Louisiana\r\n639\r\nOil City, Louisiana\r\n995\r\nOlla, Louisiana\r\n495\r\nOpelousas, Louisiana\r\n942\r\n948\r\n943\r\nParks, Louisiana\r\n845\r\nPecan Island, Louisiana\r\n737\r\nPelican, Louisiana\r\n755\r\nPine Prar, Louisiana\r\n599\r\nPinesville, Louisiana\r\n640\r\nPitkin, Louisiana\r\n358\r\nPl Dealing, Louisiana\r\n326\r\nPlaucheville, Louisiana\r\n922\r\nPleasanthill, Louisiana\r\n796\r\nPollock, Louisiana\r\n765\r\nPort Barre, Louisiana\r\n585\r\nRagley, Louisiana\r\n725\r\nRayne, Louisiana\r\n334\r\nRayville, Louisiana\r\n728\r\n729\r\nReeves, Louisiana\r\n666\r\nRinggold, Louisiana\r\n894\r\nRoanoke, Louisiana\r\n753\r\nRobeline, Louisiana\r\n471\r\n472\r\n481\r\nRodessa, Louisiana\r\n223\r\nRuston, Louisiana\r\n251\r\n254\r\n255\r\n257\r\nSaline, Louisiana\r\n576\r\nSarepta, Louisiana\r\n847\r\nShongaloo, Louisiana\r\n846\r\nShreveport, Louisiana\r\n555\r\n675\r\n221\r\n222\r\n226\r\n227\r\n320\r\n424\r\n425\r\n429\r\n455\r\n458\r\n459\r\n465\r\n469\r\n670\r\n673\r\n674\r\n676\r\n677\r\n976\r\n456\r\n741\r\n742\r\n746\r\n747\r\n621\r\n631\r\n632\r\n635\r\n636\r\n683\r\n686\r\n687\r\n688\r\n795\r\n797\r\n798\r\n861\r\n862\r\n865\r\n868\r\n869\r\nSicily Island, Louisiana\r\n389\r\nSimmesport, Louisiana\r\n941\r\nSouth Dodge City, Louisiana\r\n571\r\nSouth Junction City, Louisiana\r\n986\r\nSpencer, Louisiana\r\n726\r\nSpringhill, Louisiana\r\n539\r\n994\r\nSaint Joseph, Louisiana\r\n766\r\nSaint Landry, Louisiana\r\n838\r\nSaint Martnville, Louisiana\r\n394\r\nStarks, Louisiana\r\n743\r\nSterlington, Louisiana\r\n665\r\nSugartown, Louisiana\r\n328\r\nSulphur, Louisiana\r\n527\r\n528\r\n625\r\nSunset, Louisiana\r\n662\r\nSweet Lake, Louisiana\r\n598\r\nTallulah, Louisiana\r\n574\r\nThornwell, Louisiana\r\n587\r\nTullos, Louisiana\r\n534\r\nTurkey Creek, Louisiana\r\n461\r\nVidalia, Louisiana\r\n336\r\nVilleplatt, Louisiana\r\n363\r\nVinton, Louisiana\r\n589\r\nVivian, Louisiana\r\n375\r\nWashington, Louisiana\r\n826\r\nWaterproof, Louisiana\r\n749\r\nWeeks Island, Louisiana\r\n867\r\nWelsh, Louisiana\r\n734\r\nWinnfield, Louisiana\r\n628\r\n727\r\nWinnsboro, Louisiana\r\n435\r\nWisner, Louisiana\r\n724\r\nYoungsville, Louisiana\r\n856\r\nZwolle, Louisiana\r\n645\r\n\u00035Unknown prefix code (318) - Louisiana\r\n"
  },
  {
    "path": "install/regions/regions.319",
    "content": "Ainsworth, Iowa\r\n657\r\nAlburnett, Iowa\r\n842\r\nAllison, Iowa\r\n267\r\nAlpha, Iowa\r\n429\r\nAmana, Iowa\r\n622\r\nAnamosa, Iowa\r\n480\r\n481\r\n462\r\nAndrew, Iowa\r\n672\r\nAplington, Iowa\r\n347\r\nArgyle, Iowa\r\n838\r\nArlington, Iowa\r\n633\r\nAtalissa, Iowa\r\n649\r\nAtkins, Iowa\r\n446\r\nAurora, Iowa\r\n634\r\nBaldwin, Iowa\r\n673\r\nBelle Plaine, Iowa\r\n444\r\nBellevue, Iowa\r\n872\r\nBennett, Iowa\r\n893\r\nBernard, Iowa\r\n879\r\nBirmingham, Iowa\r\n498\r\nBlairstown, Iowa\r\n454\r\nBonaparte, Iowa\r\n592\r\nBrandon, Iowa\r\n474\r\nBrighton, Iowa\r\n694\r\nBurlington, Iowa\r\n750\r\n752\r\n753\r\n754\r\n759\r\nBurr Oak, Iowa\r\n735\r\nCalamus, Iowa\r\n246\r\nCalmar, Iowa\r\n562\r\nCantril, Iowa\r\n397\r\nCascade, Iowa\r\n852\r\nCastalia, Iowa\r\n567\r\nCedar Falls, Iowa\r\n266\r\n268\r\n273\r\n277\r\nCedar Rapids, Iowa\r\n362\r\n363\r\n364\r\n365\r\n366\r\n368\r\n369\r\n375\r\n378\r\n390\r\n393\r\n395\r\n396\r\n398\r\n399\r\n350\r\n360\r\n361\r\nCentel Cellular Phone, Iowa\r\n230\r\n231\r\n240\r\nCenter Junction, Iowa\r\n487\r\nCenter Point, Iowa\r\n849\r\nCentral City, Iowa\r\n438\r\nCharlotte, Iowa\r\n677\r\nChester, Iowa\r\n565\r\nClarence, Iowa\r\n452\r\nClarksville, Iowa\r\n278\r\nClermont, Iowa\r\n423\r\nClinton, Iowa\r\n242\r\n243\r\n244\r\n249\r\n259\r\n357\r\nClutier, Iowa\r\n479\r\nCoggon, Iowa\r\n435\r\nColesburg, Iowa\r\n856\r\nColumbus Junction, Iowa\r\n728\r\nConesville, Iowa\r\n725\r\nConroy, Iowa\r\n662\r\nCrawfordsville, Iowa\r\n658\r\nCresco, Iowa\r\n547\r\nDanville, Iowa\r\n392\r\nDavenport, Iowa\r\n320\r\n322\r\n323\r\n324\r\n326\r\n327\r\n328\r\n332\r\n340\r\n344\r\n349\r\n359\r\n370\r\n381\r\n383\r\n386\r\n388\r\n391\r\nDe Witt, Iowa\r\n659\r\nDecorah, Iowa\r\n379\r\n380\r\n382\r\n387\r\nDelhi, Iowa\r\n922\r\nDelmar, Iowa\r\n674\r\nDenmark, Iowa\r\n528\r\nDenver, Iowa\r\n984\r\nDike, Iowa\r\n989\r\nDixon, Iowa\r\n843\r\nDodgeville, Iowa\r\n985\r\nDonahue, Iowa\r\n282\r\nDonnellson, Iowa\r\n835\r\nDorchester, Iowa\r\n497\r\nDubuque, Iowa\r\n552\r\n556\r\n557\r\n580\r\n582\r\n583\r\n588\r\n589\r\n590\r\n599\r\nDunkerton, Iowa\r\n822\r\nDurant, Iowa\r\n785\r\nDyersville, Iowa\r\n875\r\nDysart, Iowa\r\n476\r\nEarlville, Iowa\r\n923\r\nEdgewood, Iowa\r\n928\r\nElberon, Iowa\r\n439\r\nEldridge, Iowa\r\n285\r\nElgin, Iowa\r\n426\r\nElkader, Iowa\r\n245\r\nEly, Iowa\r\n848\r\nEpworth, Iowa\r\n876\r\nFairbank, Iowa\r\n635\r\nFairfax, Iowa\r\n846\r\nFarley, Iowa\r\n744\r\nFarmersburg, Iowa\r\n536\r\nFarmington, Iowa\r\n878\r\nFayette, Iowa\r\n425\r\nFredericksburg, Iowa\r\n237\r\nFrederika, Iowa\r\n275\r\nFort Madison, Iowa\r\n372\r\n376\r\nFort Atkinson, Iowa\r\n534\r\nGarber, Iowa\r\n255\r\nGarrison, Iowa\r\n477\r\nGoose Lake, Iowa\r\n577\r\nGranavillo, Iowa\r\n964\r\nGrandmound, Iowa\r\n847\r\nGrandview, Iowa\r\n729\r\nGreeley, Iowa\r\n925\r\nGrundy Center, Iowa\r\n824\r\nGuernsey, Iowa\r\n685\r\nGuttenberg, Iowa\r\n252\r\nHarpers Ferry, Iowa\r\n586\r\nHartwick, Iowa\r\n525\r\nHawkeye, Iowa\r\n427\r\nHazelton, Iowa\r\n636\r\nHesper, Iowa\r\n496\r\nHighlandville, Iowa\r\n546\r\nHills, Iowa\r\n679\r\nHillsboro, Iowa\r\n253\r\nHoly Cross, Iowa\r\n870\r\nHopkinton, Iowa\r\n926\r\nHoughton, Iowa\r\n469\r\nHudson, Iowa\r\n988\r\nIndependence, Iowa\r\n334\r\nIowa City, Iowa\r\n330\r\n331\r\n356\r\n358\r\n335\r\n337\r\n338\r\n339\r\n351\r\n353\r\n354\r\n355\r\nJanesville, Iowa\r\n987\r\nJesup, Iowa\r\n827\r\nKalona, Iowa\r\n656\r\nKeokuk, Iowa\r\n524\r\nKeosauqua, Iowa\r\n293\r\nKeswick, Iowa\r\n738\r\nKeystone, Iowa\r\n442\r\nKingston, Iowa\r\n937\r\nKinross, Iowa\r\n639\r\nLa Motte, Iowa\r\n773\r\nLa Porte City, Iowa\r\n342\r\nLadora, Iowa\r\n623\r\nLamont, Iowa\r\n924\r\nLansing, Iowa\r\n538\r\nLawler, Iowa\r\n238\r\nLe Claire, Iowa\r\n289\r\nLetts, Iowa\r\n726\r\nLime Springs, Iowa\r\n566\r\nLisbon, Iowa\r\n455\r\nLockridge, Iowa\r\n696\r\nLone Tree, Iowa\r\n629\r\nLost Nation, Iowa\r\n678\r\nLow Moor, Iowa\r\n522\r\nLowden, Iowa\r\n944\r\nLuxemburg, Iowa\r\n853\r\nManchester, Iowa\r\n920\r\n927\r\nMaquoketa, Iowa\r\n652\r\nMarengo, Iowa\r\n642\r\nMarion, Iowa\r\n373\r\n377\r\nMartelle, Iowa\r\n482\r\nMaynard, Iowa\r\n637\r\nMccausland, Iowa\r\n225\r\nMcgregor, Iowa\r\n873\r\nMechanicsville, Iowa\r\n432\r\nMediapolis, Iowa\r\n394\r\nMiles, Iowa\r\n682\r\nMillersburg, Iowa\r\n655\r\nMonona, Iowa\r\n539\r\nMonticello, Iowa\r\n465\r\nMontrose, Iowa\r\n463\r\nMorley, Iowa\r\n489\r\nMorningsun, Iowa\r\n868\r\nMoscow, Iowa\r\n724\r\nMountunion, Iowa\r\n865\r\nMount Auburn, Iowa\r\n475\r\nMount Vernon, Iowa\r\n895\r\nMount Pleasant, Iowa\r\n385\r\n986\r\nMount Sterling, Iowa\r\n494\r\nMuscatine, Iowa\r\n260\r\n262\r\n263\r\n264\r\nNew Albin, Iowa\r\n544\r\nNew Hartford, Iowa\r\n983\r\nNew London, Iowa\r\n367\r\nNew Vienna, Iowa\r\n921\r\nNewhall, Iowa\r\n223\r\nNichols, Iowa\r\n723\r\nNorth English, Iowa\r\n664\r\nNorth Liberty, Iowa\r\n626\r\nNorway, Iowa\r\n227\r\nOakville, Iowa\r\n766\r\nOelwein, Iowa\r\n283\r\nOlds, Iowa\r\n254\r\nOlin, Iowa\r\n484\r\nOnslow, Iowa\r\n485\r\nOran, Iowa\r\n638\r\nOssian, Iowa\r\n532\r\nOttercreek, Iowa\r\n686\r\nOxford Junction, Iowa\r\n486\r\nOxford, Iowa\r\n628\r\nPackwood, Iowa\r\n695\r\nPalo, Iowa\r\n851\r\nParkersburg, Iowa\r\n346\r\nPlainfield, Iowa\r\n276\r\nPostville, Iowa\r\n864\r\nPrairieburg, Iowa\r\n437\r\nPreston, Iowa\r\n689\r\nPrimrose, Iowa\r\n836\r\nProtivin, Iowa\r\n569\r\nQuasqueton, Iowa\r\n934\r\nRandalia, Iowa\r\n428\r\nReadlyn, Iowa\r\n279\r\nReinbeck, Iowa\r\n345\r\nRichland, Iowa\r\n456\r\nRidgeway, Iowa\r\n737\r\nRiverside, Iowa\r\n648\r\nRochester, Iowa\r\n946\r\nRowley, Iowa\r\n938\r\nRyan, Iowa\r\n932\r\nSabula, Iowa\r\n687\r\nSalem, Iowa\r\n258\r\nSharon Center, Iowa\r\n683\r\nShell Rock, Iowa\r\n885\r\nShellsburg, Iowa\r\n436\r\nSouth Canton, Iowa\r\n745\r\nSouth Harmony, Iowa\r\n883\r\nSouth Spring Grove, Iowa\r\n492\r\nSolon, Iowa\r\n644\r\nSouth English, Iowa\r\n667\r\nSpringville, Iowa\r\n854\r\nSaint Lucas, Iowa\r\n778\r\nSaint Olaf, Iowa\r\n783\r\nStanwood, Iowa\r\n945\r\nStockport, Iowa\r\n796\r\nStrawberry Point, Iowa\r\n933\r\nSumner, Iowa\r\n578\r\nSwisher, Iowa\r\n857\r\nTiffin, Iowa\r\n645\r\nTipton, Iowa\r\n886\r\nTraer, Iowa\r\n478\r\nTripoli, Iowa\r\n882\r\nTroy Mills, Iowa\r\n224\r\nUrbana, Iowa\r\n443\r\nVan Horne, Iowa\r\n228\r\nVictor, Iowa\r\n647\r\nVinton, Iowa\r\n472\r\nVolga, Iowa\r\n767\r\nWadena, Iowa\r\n774\r\nWalcott, Iowa\r\n284\r\nWalker, Iowa\r\n448\r\nWapello, Iowa\r\n523\r\nWashburn, Iowa\r\n009\r\nWashington, Iowa\r\n458\r\n653\r\nWaterloo, Iowa\r\n239\r\n232\r\n233\r\n234\r\n235\r\n236\r\n291\r\n292\r\n296\r\nWaterville, Iowa\r\n535\r\nWaucoma, Iowa\r\n776\r\nWaukon, Iowa\r\n568\r\nWaverly, Iowa\r\n352\r\nWayland, Iowa\r\n256\r\nWellman, Iowa\r\n646\r\nWest Branch, Iowa\r\n643\r\nWest Chester, Iowa\r\n698\r\nWest Liberty, Iowa\r\n627\r\nWest Point, Iowa\r\n837\r\nWest Union, Iowa\r\n422\r\nWheatland, Iowa\r\n374\r\nWilliamsbg, Iowa\r\n660\r\nWilliamsburg, Iowa\r\n668\r\nWilton, Iowa\r\n732\r\nWinfield, Iowa\r\n257\r\nWinthrop, Iowa\r\n935\r\nWorthington, Iowa\r\n855\r\nWyoming, Iowa\r\n488\r\n\u00035Unknown prefix code (319) - Iowa\r\n"
  },
  {
    "path": "install/regions/regions.320",
    "content": "Milaca, Minnesota\r\n983\r\n\u00035Unknown prefix code (320) - Minnesota\r\n"
  },
  {
    "path": "install/regions/regions.326",
    "content": "\u00032Belgium\u00030\r\n326\r\n\u00035Unknown prefix code (326) - Belgium\r\n"
  },
  {
    "path": "install/regions/regions.334",
    "content": "Daleville, Alabama\r\n598\r\n\u00035Unknown prefix code (334) - Alabama\r\n"
  },
  {
    "path": "install/regions/regions.336",
    "content": "Abbotsburg, North Carolina\r\n648\r\nAberdeen, North Carolina\r\n944\r\nAdvance, North Caroina\r\n998\r\nAnderson, North Carolina\r\n421\r\nAsheboro, North Carolina\r\n318\r\n365\r\n626\r\n629\r\n636\r\n672\r\n953\r\nBadin Lake, North Carolina\r\n461\r\nBaldwin, North Carolina\r\n877\r\nBennett, North Carolina\r\n581\r\nBenson, North Carolina\r\n894\r\nBeulah, North Carolina\r\n352\r\nBeulaville, North Carolina\r\n298\r\nBiscoe, North Carolina\r\n428\r\nBladenboro, North Carolina\r\n863\r\nBonlee, North Carolina\r\n837\r\nBoomer, North Carolina\r\n921\r\nBoonville, North Carolina\r\n367\r\nBrooks, North Carolina\r\n468\r\nBurlington, North Carolina\r\n222\r\n226\r\n227\r\n228\r\n229\r\n260\r\n263\r\n513\r\n538\r\n570\r\n578\r\n584\r\nCandor, North Carolina\r\n974\r\nCarthage, North Carolina\r\n947\r\nChadboum, North Carolina\r\n654\r\nChampion, North Carolina\r\n973\r\nClarkton, North Carolina\r\n647\r\nClemmons, North Carolina\r\n766\r\nClingman, North Carolina\r\n984\r\nClinton, North Carolina\r\n590\r\n592\r\nCoharie, North Carolina\r\n567\r\nColeridge, North Carolina\r\n879\r\nCourtney, North Carolina\r\n463\r\nCreston, North Carolina\r\n385\r\nCypress Creek, North Carolina\r\n588\r\nDanbury, North Carolina\r\n593\r\nDobson, North Carolina\r\n386\r\nDunn-Erwin, North Carolina\r\n891\r\n892\r\n897\r\n980\r\nEast Bend, North Carolina\r\n699\r\nEden, North Carolina\r\n623\r\n627\r\n635\r\nElizabethtown, North Carolina\r\n862\r\nElkin, North Carolina\r\n526\r\n835\r\nFair Bluff, North Carolina\r\n649\r\nFalson, North Carolina\r\n267\r\nFarmer, North Carolina\r\n857\r\nFayetteville, North Carolina\r\n214\r\n215\r\n219\r\n234\r\n245\r\n251\r\n253\r\n256\r\n259\r\n262\r\n265\r\n267\r\n268\r\n270\r\n276\r\n277\r\n278\r\n281\r\n283\r\n285\r\n287\r\n289\r\n293\r\n295\r\n296\r\n298\r\n313\r\n324\r\n326\r\n327\r\n328\r\n329\r\n340\r\n341\r\n343\r\n346\r\n347\r\n350\r\n353\r\n369\r\n371\r\n388\r\n389\r\n392\r\n394\r\n395\r\n417\r\n422\r\n451\r\n452\r\n455\r\n457\r\n458\r\n462\r\n464\r\n520\r\n521\r\n525\r\n529\r\n531\r\n532\r\n533\r\n540\r\n564\r\n565\r\n567\r\n577\r\n579\r\n581\r\n582\r\n588\r\n590\r\n591\r\n592\r\n594\r\n602\r\n608\r\n618\r\n622\r\n625\r\n628\r\n640\r\n642\r\n645\r\n646\r\n647\r\n648\r\n652\r\n653\r\n654\r\n655\r\n669\r\n671\r\n675\r\n686\r\n692\r\n695\r\n738\r\n739\r\n743\r\n754\r\n762\r\n763\r\n791\r\n799\r\n814\r\n815\r\n817\r\n818\r\n819\r\n820\r\n842\r\n843\r\n844\r\n858\r\n860\r\n862\r\n863\r\n865\r\n866\r\n875\r\n879\r\n891\r\n892\r\n893\r\n895\r\n896\r\n897\r\n938\r\n944\r\n945\r\n947\r\n948\r\n949\r\n951\r\n961\r\n980\r\n988\r\n997\r\nFayetteville\u00031/\u00032Ft. Bragg, North Carolina\r\n396\r\n868\r\n488\r\n484\r\n483\r\n822\r\n864\r\n486\r\n867\r\n436\r\n306\r\n307\r\n308\r\n322\r\n323\r\n424\r\n425\r\n485\r\n432\r\n433\r\n391\r\n630\r\n678\r\n960\r\n624\r\n487\r\n907\r\nForbush, North Carolina\r\n861\r\nFort Bragg, North Carolina\r\n396\r\nFour Oaks, North Carolina\r\n963\r\nGarland, North Carolina\r\n529\r\nGibsonville, North Carolina\r\n449\r\nGlade Creek, North Carolina\r\n657\r\nGoldston, North Carolina\r\n898\r\nGreensboro, North Carolina\r\n218\r\n230\r\n271\r\n272\r\n273\r\n274\r\n275\r\n279\r\n282\r\n288\r\n292\r\n294\r\n299\r\n312\r\n314\r\n316\r\n333\r\n334\r\n337\r\n339\r\n370\r\n373\r\n375\r\n378\r\n379\r\n393\r\n412\r\n507\r\n513\r\n545\r\n547\r\n574\r\n601\r\n605\r\n621\r\n632\r\n665\r\n668\r\n674\r\n680\r\n691\r\n697\r\n698\r\n852\r\n854\r\n855\r\n908\r\n913\r\nHarrells, North Carolina\r\n532\r\nHays, North Carolina\r\n696\r\nHerring, North Carolina\r\n564\r\nHigh Falls, North Carolina\r\n464\r\nHigh Point, North Carolina\r\n431\r\n434\r\n454\r\n812\r\n841\r\n861\r\n869\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\nHillsdale, North Carolina\r\n940\r\nHolly Ridge, North Carolina\r\n329\r\nHope Mills, North Carolina\r\n423\r\nJackson Creek, North Carolina\r\n241\r\nJacksonville, North Carolina\r\n353\r\n577\r\n455\r\n346\r\n451\r\n347\r\n340\r\n389\r\n938\r\n219\r\nJulian, North Carolina\r\n685\r\nKenansville, North Carolina\r\n296\r\nKelly, North Carolina\r\n669\r\nKernersville, North Carolina\r\n993\r\n996\r\nKimesville, North Carolina\r\n545\r\nKing, North Carolina\r\n983\r\nLake Waccamaw, North Carolina\r\n646\r\nLansing, North Carolina\r\n384\r\nLevel Cross, North Carolina\r\n374\r\nLewisville, North Carolina\r\n845\r\nLexington, North Carolina\r\n764\r\nLiberty, North Carolina\r\n662\r\nLillington, North Carolina\r\n893\r\nLisbon, North Carolina\r\n645\r\nLomax, North Carolina\r\n957\r\nMadison, North Carolina\r\n427\r\n548\r\nMaxton, North Carolina\r\n844\r\nMaysville, North Carolina\r\n743\r\nMonticello, North Carolina\r\n656\r\nMount Airy, North Carolina\r\n719\r\n786\r\n789\r\nMount Gilead, North Carolina\r\n439\r\nMulberry, North Carolina\r\n670\r\nNathans Creek, North Carolina\r\n982\r\nNewton Grove, North Carolina\r\n594\r\nNorth Wilkesboro, North Carolina\r\n651\r\n667\r\n838\r\n902\r\nOldtown, North Carolina\r\n922\r\n924\r\nParkton, North Carolina\r\n858\r\nPilot Mountain, North Carolina\r\n368\r\nPinebluff, North Carolina\r\n281\r\nPinehurst, North Carolina\r\n215\r\n295\r\nPisgah, North Carolina\r\n381\r\nPittsboro, North Carolina\r\n542\r\nPope A.F.B., North Carolina\r\n394\r\nPrinceton, North Carolina\r\n936\r\nProspect Hill, North Carolina\r\n562\r\nQuaker Gap, North Carolina\r\n994\r\nRaeford, North Carolina\r\n875\r\nRamseur, North Carolina\r\n824\r\nRandleman, North Carolina\r\n495\r\n498\r\nRed Brush, North Carolina\r\n320\r\nRed Springs, North Carolina\r\n843\r\nReidsville, North Carolina\r\n342\r\n349\r\n616\r\n634\r\nRichlands, North Carolina\r\n324\r\nRoaring Gap, North Carolina\r\n363\r\nRobbins, North Carolina\r\n948\r\nRoseboro, North Carolina\r\n525\r\nRose Hill, North Carolina\r\n289\r\nRoxboro, North Carolina\r\n503\r\n597\r\n599\r\nRuffin, North Carolina\r\n939\r\nRural Hall, North Carolina\r\n969\r\nSaint Pauls, North Carolina\r\n865\r\nSandy Ridge, North Carolina\r\n871\r\nSaxapahaw, North Carolina\r\n376\r\nScottville, North Carolina\r\n359\r\nSeagrove, North Carolina\r\n873\r\nShoals, North Carolina\r\n325\r\nSiler City, North Carolina\r\n663\r\n742\r\nSix Run, North Carolina\r\n533\r\nSmithfield, North Carolina\r\n915\r\n989\r\n934\r\nSneads Ferry, North Carolina\r\n327\r\nSouth River, North Carolina\r\n531\r\nSouthern Pines, North Carolina\r\n692\r\n695\r\nSparta, NOrth Carolina\r\n372\r\nSpring Lake, North Carolina\r\n497\r\nStanleyville, North Carolina\r\n377\r\nState Road, North Carolina\r\n874\r\nStoneville, North Carolina\r\n573\r\nSummerfield, North Carolina\r\n643\r\nSwansboro, North Carolina\r\n326\r\n354\r\nTabor City, North Carolina\r\n653\r\nThomasville, North Carolina\r\n472\r\n474\r\n475\r\n476\r\nTimberlake, North Carolina\r\n364\r\nTopsail Island, North Carolina\r\n328\r\nTroy, North Carolina\r\n572\r\n576\r\nVass, North Carolina\r\n245\r\nWallace, North Carolina\r\n285\r\nWalkertown, North Carolina\r\n595\r\nWalnut Cove, North Carolina\r\n481\r\nWarsaw, North Carolina\r\n293\r\nWest End, North Carolina\r\n673\r\nWest Jefferson, North Carolina\r\n246\r\nWestfield, North Carolina\r\n351\r\nWhispering Pines, North Carolina\r\n949\r\nWhite Oak, North Carolina\r\n866\r\nWhiteville, North Carolina\r\n642\r\n640\r\nWinston-Salem, North Carolina\r\n208\r\n418\r\n519\r\n607\r\n631\r\n650\r\n659\r\n661\r\n712\r\n716\r\n717\r\n718\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n727\r\n730\r\n741\r\n744\r\n748\r\n750\r\n759\r\n760\r\n761\r\n764\r\n765\r\n766\r\n767\r\n768\r\n769\r\n770\r\n773\r\n777\r\n780\r\n784\r\n785\r\n788\r\n\u00035Unknown prefix code (336) - North Carolina (not c/w yet)\r\n"
  },
  {
    "path": "install/regions/regions.341",
    "content": "Madrid, Spain\r\n341\r\n663\r\n632\r\n413\r\n547\r\n886\r\n240\r\n\u00035Unknown prefix code (341) - Spain\r\n"
  },
  {
    "path": "install/regions/regions.343",
    "content": "Barcelona, Spain\r\n343\r\n\u00035Unknown prefix code (343) - Spain\r\n"
  },
  {
    "path": "install/regions/regions.345",
    "content": "Moron de la Fontera, Spain\r\n345\r\n584\r\n\u00035Unknown prefix code (345) - Spain\r\n"
  },
  {
    "path": "install/regions/regions.346",
    "content": "Valencia, Spain\r\n346\r\n\u00035Unknown prefix code (346) - Spain\r\n"
  },
  {
    "path": "install/regions/regions.352",
    "content": "Lady Lake, Florida\r\n259\r\nGainesville, Florida\r\n375\r\nLake County, Florida\r\n357\r\n\u00035Unknown prefix code (352) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.353",
    "content": "Dublin, Ireland\r\n547\r\n\u00035Unknown prefix code (353) - Ireland\r\n"
  },
  {
    "path": "install/regions/regions.360",
    "content": "Coupeville, Washington\r\n678\r\nOak Harbor\u00031/\u00032Whidbey Island, Washington\r\n240\r\n675\r\n679\r\nMonroe, Washington\r\n793\r\n794\r\n805\r\nSnohomish, Washington\r\n691\r\nVancouver, Washington\r\n896\r\n\u00035Unknown prefix code (360) - Washington\r\n"
  },
  {
    "path": "install/regions/regions.401",
    "content": "Block Is, Rhode Island\r\n466\r\nBristol, Rhode Island\r\n253\r\n254\r\nCarolina, Rhode Island\r\n364\r\nCentredale, Rhode Island\r\n231\r\n232\r\n233\r\n933\r\n938\r\n949\r\nCumberland Hill, Rhode Island\r\n658\r\nCoventry, Rhode Island\r\n392\r\n397\r\nGreenwich, Rhode Island\r\n884\r\n885\r\n886\r\nHopevalley, Rhode Island\r\n539\r\nJamestown, Rhode Island\r\n423\r\nLtlcompton, Rhode Island\r\n635\r\nNarragnstt, Rhode Island\r\n782\r\n783\r\n788\r\n789\r\n792\r\nNewport, Rhode Island\r\n841\r\n842\r\n846\r\n847\r\n848\r\n849\r\nNorth Kingston, Rhode Island\r\n267\r\n268\r\n294\r\n295\r\nPascoag, Rhode Island\r\n567\r\n568\r\nPawtucket, Rhode Island\r\n333\r\n334\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\nPortsmouth, Rhode Island\r\n683\r\nProvidence, Rhode Island\r\n224\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n331\r\n351\r\n353\r\n354\r\n421\r\n431\r\n433\r\n434\r\n435\r\n437\r\n438\r\n444\r\n448\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n461\r\n463\r\n464\r\n467\r\n521\r\n523\r\n524\r\n525\r\n527\r\n528\r\n529\r\n544\r\n555\r\n572\r\n574\r\n575\r\n621\r\n751\r\n776\r\n781\r\n784\r\n785\r\n786\r\n831\r\n861\r\n863\r\n865\r\n941\r\n942\r\n943\r\n944\r\n946\r\n955\r\n976\r\nScituate, Rhode Island\r\n647\r\n934\r\nTiverton, Rhode Island\r\n624\r\n625\r\nWest Warwick, Rhode Island\r\n821\r\n822\r\n823\r\n825\r\n826\r\n827\r\n828\r\nWarren, Rhode Island\r\n245\r\n246\r\n247\r\nWarwick, Rhode Island\r\n732\r\n736\r\n737\r\n738\r\n739\r\nWesterly, Rhode Island\r\n322\r\n348\r\n377\r\n596\r\nWest Glocester, Rhode Island\r\n968\r\nWoonsocket, Rhode Island\r\n581\r\n762\r\n763\r\n765\r\n766\r\n767\r\n769\r\n\u00035Unknown prefix code (401) - Rhode Island\r\n"
  },
  {
    "path": "install/regions/regions.402",
    "content": "Adams, Nebraska\r\n988\r\nAinsworth, Nebraska\r\n387\r\nAlbion, Nebraska\r\n395\r\nAlexandria, Nebraska\r\n749\r\nAllen, Nebraska\r\n635\r\nArlington, Nebraska\r\n478\r\n931\r\nAshland, Nebraska\r\n944\r\nAtkinson, Nebraska\r\n925\r\nAuburn, Nebraska\r\n274\r\nAurora, Nebraska\r\n694\r\nAvoca, Nebraska\r\n275\r\nBancroft, Nebraska\r\n648\r\nBarneston, Nebraska\r\n674\r\nBassett, Nebraska\r\n684\r\nBattle Creek, Nebraska\r\n675\r\nBeatrice, Nebraska\r\n223\r\n228\r\nBeaver Crossing, Nebraska\r\n532\r\nBeemer, Nebraska\r\n528\r\nBelden, Nebraska\r\n985\r\nBellevue, Nebraska\r\n292\r\nBellwood, Nebraska\r\n538\r\nBenedict, Nebraska\r\n732\r\nBennet, Nebraska\r\n782\r\nBennington, Nebraska\r\n238\r\nBlair, Nebraska\r\n426\r\n533\r\nBloomfield, Nebraska\r\n373\r\nBlue Hill, Nebraska\r\n756\r\nBradshaw, Nebraska\r\n736\r\nBrainard, Nebraska\r\n545\r\nBristow, Nebraska\r\n583\r\nBrock, Nebraska\r\n856\r\nBrownville, Nebraska\r\n825\r\nBruning, Nebraska\r\n353\r\nBruno, Nebraska\r\n543\r\nBrunswick, Nebraska\r\n842\r\nBurchard, Nebraska\r\n865\r\nBurr, Nebraska\r\n848\r\nButte, Nebraska\r\n775\r\nByron, Nebraska\r\n236\r\nCarleton, Nebraska\r\n356\r\nCarroll, Nebraska\r\n585\r\nCedar Bluffs, Nebraska\r\n628\r\nCenter, Nebraska\r\n288\r\nCeresco, Nebraska\r\n665\r\nChambers, Nebraska\r\n482\r\nChester, Nebraska\r\n324\r\nClarkson, Nebraska\r\n892\r\nClatonia, Nebraska\r\n989\r\nClaycenter, Nebraska\r\n762\r\nClearwater, Nebraska\r\n485\r\nCody, Nebraska\r\n823\r\nColeridge, Nebraska\r\n283\r\nColon, Nebraska\r\n647\r\nColumbus, Nebraska\r\n562\r\n563\r\n564\r\n570\r\nCook, Nebraska\r\n864\r\nCordova, Nebraska\r\n576\r\nCortland, Nebraska\r\n798\r\nCrab Orch, Nebraska\r\n876\r\nCraig, Nebraska\r\n377\r\nCreighton, Nebraska\r\n358\r\nCreston, Nebraska\r\n285\r\nCrete, Nebraska\r\n826\r\nCrofton, Nebraska\r\n388\r\nCrookston, Nebraska\r\n425\r\nDakota City, Nebraska\r\n987\r\nDavenport, Nebraska\r\n364\r\nDavey, Nebraska\r\n785\r\nDavid City, Nebraska\r\n367\r\nDawson, Nebraska\r\n855\r\nDaykin, Nebraska\r\n446\r\nDe Witt, Nebraska\r\n683\r\nDecatur, Nebraska\r\n349\r\nDenton, Nebraska\r\n797\r\nDeshler, Nebraska\r\n365\r\nDesoto Bend, Nebraska\r\n672\r\nDeweese, Nebraska\r\n262\r\nDiller, Nebraska\r\n793\r\nDixon, Nebraska\r\n584\r\nDodge, Nebraska\r\n693\r\nDoniphan, Nebraska\r\n845\r\nDorchester, Nebraska\r\n946\r\nDouglas, Nebraska\r\n799\r\nDubois, Nebraska\r\n859\r\nDunbar, Nebraska\r\n259\r\nDuncan, Nebraska\r\n897\r\nDwight, Nebraska\r\n566\r\nEagle, Nebraska\r\n781\r\nEdgar, Nebraska\r\n224\r\nElgin, Nebraska\r\n843\r\nElk Creek, Nebraska\r\n877\r\nElkhorn, Nebraska\r\n289\r\n779\r\nElmwood, Nebraska\r\n994\r\nEmerson, Nebraska\r\n695\r\nEwing, Nebraska\r\n626\r\nExeter, Nebraska\r\n266\r\nFairbury, Nebraska\r\n729\r\nFairfield, Nebraska\r\n726\r\nFairmont, Nebraska\r\n268\r\nFalls City, Nebraska\r\n245\r\nFilley, Nebraska\r\n662\r\nFirth, Nebraska\r\n791\r\nFremont, Nebraska\r\n720\r\n721\r\n727\r\nFriend, Nebraska\r\n947\r\nFort Calhoun, Nebraska\r\n468\r\nGarland, Nebraska\r\n588\r\nGeneva, Nebraska\r\n759\r\nGenoa, Nebraska\r\n993\r\nGiltner, Nebraska\r\n849\r\nGlenvil, Nebraska\r\n771\r\nGrafton, Nebraska\r\n282\r\nGreenwood, Nebraska\r\n789\r\nGresham, Nebraska\r\n735\r\nGretna, Nebraska\r\n332\r\nGuide Rock, Nebraska\r\n257\r\nHallam, Nebraska\r\n787\r\nHampton, Nebraska\r\n725\r\nHansen, Nebraska\r\n744\r\nHarbine, Nebraska\r\n754\r\nHardy, Nebraska\r\n279\r\nHartington, Nebraska\r\n254\r\nHarvard, Nebraska\r\n772\r\nHastings, Nebraska\r\n461\r\n462\r\n463\r\nHebron, Nebraska\r\n768\r\nHenderson, Nebraska\r\n723\r\nHerman, Nebraska\r\n456\r\nHickman, Nebraska\r\n792\r\nHomer, Nebraska\r\n698\r\nHooper, Nebraska\r\n654\r\nHordville, Nebraska\r\n757\r\nHoskins, Nebraska\r\n565\r\nHowells, Nebraska\r\n986\r\nHumboldt, Nebraska\r\n862\r\nHumphrey, Nebraska\r\n923\r\nInman, Nebraska\r\n394\r\nIthaca, Nebraska\r\n623\r\nJackson, Nebraska\r\n632\r\nJansen, Nebraska\r\n424\r\nJohnson, Nebraska\r\n868\r\nJohnstown, Nebraska\r\n722\r\nJulian, Nebraska\r\n242\r\nJuniata, Nebraska\r\n751\r\nKenesaw, Nebraska\r\n752\r\nKennard, Nebraska\r\n427\r\nKilgore, Nebraska\r\n966\r\nLaurel, Nebraska\r\n256\r\nLeigh, Nebraska\r\n487\r\nLiberty, Nebraska\r\n696\r\nLincoln, Nebraska\r\n420\r\n421\r\n423\r\n432\r\n434\r\n435\r\n436\r\n437\r\n438\r\n441\r\n464\r\n465\r\n466\r\n467\r\n470\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n479\r\n483\r\n484\r\n486\r\n488\r\n489\r\n560\r\n742\r\n790\r\nLindsay, Nebraska\r\n428\r\nLnwdmrsbluff, Nebraska\r\n666\r\nLong Pine, Nebraska\r\n273\r\nLouisville, Nebraska\r\n234\r\nLynch, Nebraska\r\n569\r\nLyons, Nebraska\r\n687\r\nMacy, Nebraska\r\n837\r\nMadison, Nebraska\r\n454\r\nMalcolm, Nebraska\r\n796\r\nMarquette, Nebraska\r\n854\r\nMartell, Nebraska\r\n794\r\nMccool Junction, Nebraska\r\n724\r\nMead, Nebraska\r\n624\r\nMeadow Grove, Nebraska\r\n634\r\nMilford, Nebraska\r\n761\r\nMilligan, Nebraska\r\n629\r\nMonroe, Nebraska\r\n495\r\nMurdock, Nebraska\r\n867\r\nMurray, Nebraska\r\n235\r\nNaper, Nebraska\r\n832\r\nNebraska City, Nebraska\r\n873\r\nNehawka, Nebraska\r\n227\r\nNeligh, Nebraska\r\n887\r\nNelson, Nebraska\r\n225\r\nNemaha, Nebraska\r\n824\r\nNewcastle, Nebraska\r\n355\r\n692\r\n945\r\nNewman Grove, Nebraska\r\n447\r\nNewport, Nebraska\r\n244\r\nNiobrara, Nebraska\r\n857\r\nNorth Mahaska, Nebraska\r\n247\r\nNorfolk, Nebraska\r\n370\r\n371\r\n379\r\n640\r\n644\r\n649\r\nNorth Bend, Nebraska\r\n652\r\nNorth Summerfield, Nebraska\r\n248\r\nOakdale, Nebraska\r\n776\r\nOakland, Nebraska\r\n685\r\nOctavia, Nebraska\r\n539\r\nOdell, Nebraska\r\n766\r\nOhiowa, Nebraska\r\n295\r\nOmaha, Nebraska\r\n221\r\n222\r\n255\r\n271\r\n280\r\n291\r\n293\r\n294\r\n330\r\n331\r\n333\r\n334\r\n339\r\n341\r\n342\r\n344\r\n345\r\n346\r\n348\r\n351\r\n384\r\n390\r\n391\r\n392\r\n393\r\n397\r\n398\r\n399\r\n422\r\n444\r\n449\r\n451\r\n452\r\n453\r\n455\r\n457\r\n491\r\n492\r\n493\r\n496\r\n536\r\n551\r\n552\r\n553\r\n554\r\n555\r\n556\r\n557\r\n558\r\n559\r\n571\r\n572\r\n573\r\n575\r\n592\r\n593\r\n594\r\n595\r\n597\r\n633\r\n636\r\n670\r\n677\r\n680\r\n681\r\n689\r\n690\r\n691\r\n697\r\n731\r\n733\r\n734\r\n738\r\n895\r\n896\r\n962\r\n977\r\n978\r\n498\r\nOneill, Nebraska\r\n336\r\n340\r\nOng, Nebraska\r\n284\r\nOrchard, Nebraska\r\n893\r\nOsceola, Nebraska\r\n747\r\nOsmond, Nebraska\r\n748\r\nOtoe, Nebraska\r\n265\r\nPage, Nebraska\r\n338\r\nPalmyra, Nebraska\r\n780\r\nPanama, Nebraska\r\n788\r\nPawneecity, Nebraska\r\n852\r\nPender, Nebraska\r\n385\r\nPeru, Nebraska\r\n872\r\nPetersburg, Nebraska\r\n386\r\nPhillips, Nebraska\r\n886\r\nPickrell, Nebraska\r\n673\r\nPierce, Nebraska\r\n329\r\nPilger, Nebraska\r\n396\r\nPlainview , Nebraska\r\n582\r\nPlatte Center, Nebraska\r\n246\r\nPlattsmth, Nebraska\r\n296\r\n298\r\nPleasantdale, Nebraska\r\n795\r\nPlymouth, Nebraska\r\n656\r\nPolk, Nebraska\r\n765\r\nPonca, Nebraska\r\n755\r\nPrague, Nebraska\r\n663\r\nRandolph, Nebraska\r\n337\r\n360\r\nRaymond, Nebraska\r\n783\r\nRed Cloud, Nebraska\r\n746\r\nRising City, Nebraska\r\n542\r\nRosalie, Nebraska\r\n863\r\nRuskin, Nebraska\r\n226\r\nSchuyler, Nebraska\r\n352\r\nScribner, Nebraska\r\n664\r\nSeward, Nebraska\r\n643\r\nShelby, Nebraska\r\n527\r\nShickley, Nebraska\r\n627\r\nSnyder, Nebraska\r\n568\r\nSouth Gregory, Nebraska\r\n974\r\nSouth Yankton, Nebraska\r\n667\r\nSobonsteel, Nebraska\r\n653\r\nSouth Sioux City, Nebraska\r\n241\r\n494\r\nSouthburke, Nebraska\r\n774\r\nSpencer, Nebraska\r\n589\r\nSpringfield, Nebraska\r\n253\r\nSpringview, Nebraska\r\n497\r\nSaint Edward, Nebraska\r\n678\r\nStanton, Nebraska\r\n439\r\nStaplehurst, Nebraska\r\n535\r\nSteele City, Nebraska\r\n442\r\nSteinauer, Nebraska\r\n869\r\nSterling, Nebraska\r\n866\r\nStockham, Nebraska\r\n737\r\nStromsburg, Nebraska\r\n764\r\nStuart, Nebraska\r\n924\r\nSuperior, Nebraska\r\n879\r\nSurprise, Nebraska\r\n526\r\nSutton, Nebraska\r\n773\r\nSwanton, Nebraska\r\n448\r\nSyracuse, Nebraska\r\n269\r\nTable Rock, Nebraska\r\n839\r\nTalmage, Nebraska\r\n264\r\nTamora, Nebraska\r\n523\r\nTecumseh, Nebraska\r\n335\r\nTekamah, Nebraska\r\n374\r\nTilden, Nebraska\r\n368\r\nTobias, Nebraska\r\n243\r\nTri City, Nebraska\r\n883\r\nTrumbull, Nebraska\r\n743\r\nUehling, Nebraska\r\n567\r\nUlysses, Nebraska\r\n549\r\nUnadilla, Nebraska\r\n828\r\nUnion, Nebraska\r\n263\r\nUtica, Nebraska\r\n534\r\nValentine, Nebraska\r\n376\r\n378\r\nValley, Nebraska\r\n359\r\nValparaiso, Nebraska\r\n784\r\nVerdel, Nebraska\r\n229\r\nVerdigre, Nebraska\r\n668\r\nVirginia, Nebraska\r\n688\r\nWest Hamburg, Nebraska\r\n383\r\nWaco, Nebraska\r\n728\r\nWahoo, Nebraska\r\n443\r\nWakefield , Nebraska\r\n287\r\nWalnut, Nebraska\r\n655\r\nWalthill, Nebraska\r\n846\r\nWaterbury , Nebraska\r\n638\r\nWausa, Nebraska\r\n586\r\nWaverly, Nebraska\r\n786\r\nWayne, Nebraska\r\n375\r\nWeeping Water, Nebraska\r\n267\r\nWest Point, Nebraska\r\n372\r\n380\r\nWestern, Nebraska\r\n433\r\nWeston, Nebraska\r\n642\r\nWilber, Nebraska\r\n821\r\nWinnebago , Nebraska\r\n878\r\nWinnetoon, Nebraska\r\n847\r\nWinside, Nebraska\r\n286\r\nWisner, Nebraska\r\n529\r\nWood Lake, Nebraska\r\n967\r\nWy For Sth, Nebraska\r\n357\r\nWymore, Nebraska\r\n645\r\nYork, Nebraska\r\n362\r\n363\r\nYutan, Nebraska\r\n625\r\n\u00035Unknown prefix code (402) - Nebraska\r\n"
  },
  {
    "path": "install/regions/regions.403",
    "content": "Acadia Vly, Alberta, Canada\r\n972\r\nAcme, Alberta, Canada\r\n546\r\nAirdrie, Alberta, Canada\r\n948\r\nAklavik, Alberta, Canada\r\n978\r\nAlberta Beach, Alberta, Canada\r\n924\r\nAlderflats, Alberta, Canada\r\n388\r\nAlix, Alberta, Canada\r\n747\r\nAlliance, Alberta, Canada\r\n879\r\nAltario, Alberta, Canada\r\n552\r\nAndrew, Alberta, Canada\r\n365\r\nAnzac, Alberta, Canada\r\n334\r\nArdrossan, Alberta, Canada\r\n922\r\nArrowwood, Alberta, Canada\r\n534\r\nArtcredriver, Alberta, Canada\r\n953\r\nAshmont, Alberta, Canada\r\n726\r\nAssumption, Alberta, Canada\r\n321\r\nAthabasca, Alberta, Canada\r\n675\r\nBanff, Alberta, Canada\r\n760\r\n762\r\nBarons, Alberta, Canada\r\n757\r\nBarrhead, Alberta, Canada\r\n674\r\nBashaw, Alberta, Canada\r\n372\r\nBassano, Alberta, Canada\r\n641\r\nBawlf, Alberta, Canada\r\n373\r\nBear Canyn, Alberta, Canada\r\n595\r\nBeaumont, Alberta, Canada\r\n929\r\nBeaver Creek, Alberta, Canada\r\n862\r\nBeaverlodge, Alberta, Canada\r\n354\r\nBeiseker, Alberta, Canada\r\n947\r\nBentley, Alberta, Canada\r\n748\r\nBerwyn, Alberta, Canada\r\n338\r\nBig Valley, Alberta, Canada\r\n876\r\nBindloss, Alberta, Canada\r\n379\r\nBlackfalds, Alberta, Canada\r\n885\r\nBlackie, Alberta, Canada\r\n684\r\nBlue Ridge, Alberta, Canada\r\n648\r\nBon Accord, Alberta, Canada\r\n921\r\nBonanza, Alberta, Canada\r\n353\r\nBonnyville, Alberta, Canada\r\n826\r\nBow Island, Alberta, Canada\r\n545\r\nBowden, Alberta, Canada\r\n224\r\nBoyle, Alberta, Canada\r\n689\r\nBraggcreek, Alberta, Canada\r\n949\r\nBreton, Alberta, Canada\r\n696\r\nBrocket, Alberta, Canada\r\n965\r\nBrooks, Alberta, Canada\r\n362\r\n793\r\nBrownvale, Alberta, Canada\r\n597\r\nBruderheim, Alberta, Canada\r\n796\r\nBurdett, Alberta, Canada\r\n833\r\nByemoor, Alberta, Canada\r\n579\r\nCadomin, Alberta, Canada\r\n692\r\nCalgary, Alberta, Canada\r\n220\r\n221\r\n225\r\n226\r\n228\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n290\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n520\r\n521\r\n530\r\n531\r\n540\r\n541\r\n543\r\n547\r\n560\r\n569\r\n590\r\n630\r\n640\r\n650\r\n651\r\n661\r\n670\r\n680\r\n686\r\n691\r\n720\r\n730\r\n850\r\n931\r\n974\r\nCalling Lk, Alberta, Canada\r\n331\r\nCalmar, Alberta, Canada\r\n985\r\nCambrdgbay, Alberta, Canada\r\n983\r\nCamrose, Alberta, Canada\r\n672\r\n679\r\nCanmore, Alberta, Canada\r\n678\r\nCarbon, Alberta, Canada\r\n572\r\nCarcross, Alberta, Canada\r\n821\r\nCardston, Alberta, Canada\r\n653\r\nCarmacks, Alberta, Canada\r\n863\r\nCarmangay, Alberta, Canada\r\n643\r\nCaroline, Alberta, Canada\r\n722\r\nCarstairs, Alberta, Canada\r\n337\r\nCastor, Alberta, Canada\r\n882\r\nCayley, Alberta, Canada\r\n395\r\nCereal, Alberta, Canada\r\n326\r\nCessford, Alberta, Canada\r\n566\r\nChampion, Alberta, Canada\r\n897\r\nChauvin, Alberta, Canada\r\n858\r\nChipewyn L, Alberta, Canada\r\n899\r\nChipman, Alberta, Canada\r\n363\r\nClairmont, Alberta, Canada\r\n567\r\nClaresholm, Alberta, Canada\r\n625\r\nClive, Alberta, Canada\r\n784\r\nClyde, Alberta, Canada\r\n348\r\nCoaldale, Alberta, Canada\r\n345\r\nCochrane, Alberta, Canada\r\n932\r\nCold Lake, Alberta, Canada\r\n639\r\nConklin, Alberta, Canada\r\n559\r\nConsort, Alberta, Canada\r\n577\r\nCoppermine, Alberta, Canada\r\n982\r\nCoronation, Alberta, Canada\r\n578\r\nCoutts, Alberta, Canada\r\n344\r\nCowley, Alberta, Canada\r\n628\r\nCraigmyle, Alberta, Canada\r\n665\r\nCremona, Alberta, Canada\r\n637\r\nCrossfield, Alberta, Canada\r\n946\r\nCrwsnst Ps, Alberta, Canada\r\n562\r\n563\r\n564\r\nCzar, Alberta, Canada\r\n857\r\nDawson, Alberta, Canada\r\n993\r\nDaysland, Alberta, Canada\r\n374\r\nDebolt, Alberta, Canada\r\n957\r\nDelburne, Alberta, Canada\r\n749\r\nDelia, Alberta, Canada\r\n364\r\nDerwent, Alberta, Canada\r\n741\r\nDestrcnbay, Alberta, Canada\r\n841\r\nDevon, Alberta, Canada\r\n987\r\nDidsbury, Alberta, Canada\r\n335\r\nDixonville, Alberta, Canada\r\n971\r\nDonalda, Alberta, Canada\r\n883\r\nDonnelly, Alberta, Canada\r\n925\r\nDrayton Valley, Alberta, Canada\r\n542\r\nDrumheller, Alberta, Canada\r\n823\r\nDuchess, Alberta, Canada\r\n378\r\nEaglesham, Alberta, Canada\r\n359\r\nEastcoulee, Alberta, Canada\r\n822\r\nEckville, Alberta, Canada\r\n746\r\nEdgerton, Alberta, Canada\r\n755\r\nEdmntn Arp, Alberta, Canada\r\n890\r\nEdmonton, Alberta, Canada\r\n420\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n430\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n438\r\n439\r\n440\r\n441\r\n444\r\n445\r\n446\r\n447\r\n448\r\n450\r\n451\r\n453\r\n454\r\n455\r\n456\r\n457\r\n461\r\n462\r\n463\r\n465\r\n466\r\n468\r\n469\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n478\r\n479\r\n480\r\n481\r\n482\r\n483\r\n484\r\n486\r\n487\r\n488\r\n489\r\n490\r\n491\r\n492\r\n493\r\n495\r\n496\r\n497\r\n498\r\n499\r\n550\r\n551\r\n554\r\n557\r\n930\r\n940\r\n944\r\n945\r\n970\r\n988\r\n990\r\n991\r\n437\r\n452\r\nEdson, Alberta, Canada\r\n723\r\nEdzo, Alberta, Canada\r\n371\r\nElk Point, Alberta, Canada\r\n724\r\nElkwater, Alberta, Canada\r\n893\r\nElnora, Alberta, Canada\r\n773\r\nElsa, Alberta, Canada\r\n995\r\nEmpress, Alberta, Canada\r\n565\r\nEnchant, Alberta, Canada\r\n739\r\nEnterprise, Alberta, Canada\r\n984\r\nEtzikom, Alberta, Canada\r\n666\r\nEvansburg, Alberta, Canada\r\n727\r\nExshaw, Alberta, Canada\r\n673\r\nFairview, Alberta, Canada\r\n835\r\nFalher, Alberta, Canada\r\n837\r\nFaro, Alberta, Canada\r\n994\r\nFaust, Alberta, Canada\r\n355\r\nFerintosh, Alberta, Canada\r\n877\r\nFlatbush, Alberta, Canada\r\n681\r\nForemost, Alberta, Canada\r\n867\r\nForestburg, Alberta, Canada\r\n582\r\nFort Liard, Alberta, Canada\r\n770\r\nFort McMurray, Alberta, Canada\r\n743\r\nFort Smith, Alberta, Canada\r\n872\r\nFort Norman, Alberta, Canada\r\n588\r\nFox Creek, Alberta, Canada\r\n622\r\nFt Chipwyn, Alberta, Canada\r\n697\r\nFt Mackay, Alberta, Canada\r\n828\r\nFt Macleod, Alberta, Canada\r\n553\r\nFt McPhereson, Alberta, Canada\r\n952\r\nFt Providence, Alberta, Canada\r\n699\r\nFt Resolution, Alberta, Canada\r\n394\r\nFt Simpson, Alberta, Canada\r\n695\r\nFt Assinibn, Alberta, Canada\r\n584\r\nFt Franklin, Alberta, Canada\r\n589\r\nFt Goodhope, Alberta, Canada\r\n598\r\nFt Mcmurray, Alberta, Canada\r\n790\r\n791\r\n799\r\nFt Saskatch, Alberta, Canada\r\n992\r\n998\r\nFt Vermilin, Alberta, Canada\r\n927\r\nGadsby, Alberta, Canada\r\n574\r\nGalahad, Alberta, Canada\r\n583\r\nGarden River, Alberta, Canada\r\n659\r\nGibbons, Alberta, Canada\r\n923\r\nGift Lake, Alberta, Canada\r\n767\r\nGirouxvl, Alberta, Canada\r\n323\r\nGjoa Haven, Alberta, Canada\r\n360\r\nGleichen, Alberta, Canada\r\n734\r\nGlendon, Alberta, Canada\r\n635\r\nGlenwood, Alberta, Canada\r\n626\r\nGrand Cach, Alberta, Canada\r\n827\r\nGrand Ctr, Alberta, Canada\r\n594\r\n840\r\nGrandeprar, Alberta, Canada\r\n532\r\n538\r\n539\r\n831\r\nGranum, Alberta, Canada\r\n687\r\nGrassland, Alberta, Canada\r\n525\r\nGrassylake, Alberta, Canada\r\n655\r\nGrimshaw, Alberta, Canada\r\n332\r\nGrouard, Alberta, Canada\r\n751\r\nHaines Jct, Alberta, Canada\r\n634\r\nHairy Hill, Alberta, Canada\r\n768\r\nHalkirk, Alberta, Canada\r\n884\r\nHanna, Alberta, Canada\r\n854\r\nHardisty, Alberta, Canada\r\n888\r\nHay Lakes, Alberta, Canada\r\n878\r\nHay River, Alberta, Canada\r\n874\r\nHays, Alberta, Canada\r\n725\r\nHeinsburg, Alberta, Canada\r\n943\r\nHeisler, Alberta, Canada\r\n889\r\nHigh Level, Alberta, Canada\r\n926\r\nHigh Prar, Alberta, Canada\r\n523\r\nHigh River, Alberta, Canada\r\n652\r\nHilda, Alberta, Canada\r\n838\r\nHinescreek, Alberta, Canada\r\n494\r\nHinton, Alberta, Canada\r\n865\r\nHobbema, Alberta, Canada\r\n585\r\nHolden, Alberta, Canada\r\n688\r\nHolman, Alberta, Canada\r\n396\r\nHughenden, Alberta, Canada\r\n856\r\nHussar, Alberta, Canada\r\n787\r\nHythe, Alberta, Canada\r\n356\r\nInnisfail, Alberta, Canada\r\n227\r\nInnisfree, Alberta, Canada\r\n592\r\nInuvik, Alberta, Canada\r\n979\r\nIrma, Alberta, Canada\r\n754\r\nIron Spgs, Alberta, Canada\r\n738\r\nIrricana, Alberta, Canada\r\n935\r\nIrvine, Alberta, Canada\r\n834\r\nIslay, Alberta, Canada\r\n744\r\nJarvie, Alberta, Canada\r\n954\r\nJasper, Alberta, Canada\r\n852\r\nJaspereast, Alberta, Canada\r\n866\r\nJean D Pra, Alberta, Canada\r\n759\r\nJenner, Alberta, Canada\r\n898\r\nJoussard, Alberta, Canada\r\n776\r\nKananas Lk, Alberta, Canada\r\n591\r\nKeephills, Alberta, Canada\r\n731\r\nKeg River, Alberta, Canada\r\n981\r\nKillam, Alberta, Canada\r\n385\r\nKinuso, Alberta, Canada\r\n775\r\nKitscoty, Alberta, Canada\r\n846\r\nLa Crete, Alberta, Canada\r\n928\r\nLaclabiche, Alberta, Canada\r\n623\r\nLaclamartr, Alberta, Canada\r\n573\r\nLacombe, Alberta, Canada\r\n782\r\nLakelouise, Alberta, Canada\r\n522\r\nLamont, Alberta, Canada\r\n895\r\nLangdon, Alberta, Canada\r\n936\r\nLavoy, Alberta, Canada\r\n658\r\nLeduc, Alberta, Canada\r\n980\r\n986\r\nLegal, Alberta, Canada\r\n961\r\nLeslievl, Alberta, Canada\r\n729\r\nLethbridge, Alberta, Canada\r\n320\r\n327\r\n328\r\n329\r\n380\r\n381\r\n382\r\nLit Buf Lake, Alberta, Canada\r\n629\r\nLloydminister, Alberta, Canada\r\n871\r\n875\r\nLodgepole, Alberta, Canada\r\n894\r\nLomond, Alberta, Canada\r\n792\r\nLongview, Alberta, Canada\r\n558\r\nLougheed, Alberta, Canada\r\n386\r\nMagrath, Alberta, Canada\r\n758\r\nMameobeach, Alberta, Canada\r\n586\r\nManning, Alberta, Canada\r\n836\r\nMannville, Alberta, Canada\r\n763\r\nManyberris, Alberta, Canada\r\n868\r\nMarlboro, Alberta, Canada\r\n397\r\nMarwayne, Alberta, Canada\r\n847\r\nMayerthorp, Alberta, Canada\r\n786\r\nMayo, Alberta, Canada\r\n996\r\nMclennan, Alberta, Canada\r\n324\r\nMeander River, Alberta, Canada\r\n535\r\nMedicine Hat, Alberta, Canada\r\n526\r\n527\r\n528\r\n529\r\n548\r\nMilk River, Alberta, Canada\r\n647\r\nMillet, Alberta, Canada\r\n387\r\nMilo, Alberta, Canada\r\n599\r\nMinburn, Alberta, Canada\r\n593\r\nMirror, Alberta, Canada\r\n788\r\nMorinville, Alberta, Canada\r\n939\r\nMorley, Alberta, Canada\r\n881\r\nMorrin, Alberta, Canada\r\n772\r\nMulhurst, Alberta, Canada\r\n389\r\nMundare, Alberta, Canada\r\n764\r\nMyrnam, Alberta, Canada\r\n366\r\nNamao, Alberta, Canada\r\n973\r\nNampa, Alberta, Canada\r\n322\r\nNanton, Alberta, Canada\r\n646\r\nNew Dayton, Alberta, Canada\r\n733\r\nNew Norway, Alberta, Canada\r\n855\r\nNewbrook, Alberta, Canada\r\n576\r\nNewsarepta, Alberta, Canada\r\n941\r\nNisku, Alberta, Canada\r\n880\r\n955\r\nNiton Jct, Alberta, Canada\r\n795\r\nNobleford, Alberta, Canada\r\n824\r\nNordegg, Alberta, Canada\r\n721\r\nNorman Wls, Alberta, Canada\r\n587\r\nOkotoks, Alberta, Canada\r\n938\r\nOld Crow, Alberta, Canada\r\n966\r\nOlds, Alberta, Canada\r\n556\r\nOnoway, Alberta, Canada\r\n967\r\nOyen, Alberta, Canada\r\n664\r\nParadise Valley, Alberta, Canada\r\n745\r\nPaulatuk, Alberta, Canada\r\n580\r\nPeaceriver, Alberta, Canada\r\n624\r\nPeerless L, Alberta, Canada\r\n869\r\nPeers, Alberta, Canada\r\n693\r\nPelly Bay, Alberta, Canada\r\n769\r\nPellycrsng, Alberta, Canada\r\n537\r\nPenhold, Alberta, Canada\r\n886\r\nPicturebte, Alberta, Canada\r\n732\r\nPinchercrk, Alberta, Canada\r\n627\r\nPine Point, Alberta, Canada\r\n393\r\nPlamondon, Alberta, Canada\r\n798\r\nPonoka, Alberta, Canada\r\n783\r\n346\r\nProvost, Alberta, Canada\r\n753\r\nRadway, Alberta, Canada\r\n736\r\nRae, Alberta, Canada\r\n392\r\nRae Lakes, Alberta, Canada\r\n997\r\nRainbow Lake, Alberta, Canada\r\n956\r\nRalston, Alberta, Canada\r\n544\r\nRaymond, Alberta, Canada\r\n752\r\nRed Deer, Alberta, Canada\r\n340\r\n341\r\n342\r\n343\r\n347\r\n350\r\nRed Earth, Alberta, Canada\r\n649\r\nRedwater, Alberta, Canada\r\n942\r\nRimbey, Alberta, Canada\r\n843\r\nRky Mt Hse, Alberta, Canada\r\n845\r\nRobb, Alberta, Canada\r\n794\r\nRochester, Alberta, Canada\r\n698\r\nRockyford, Alberta, Canada\r\n533\r\nRollinghls, Alberta, Canada\r\n964\r\nRosalind, Alberta, Canada\r\n375\r\nRosebud, Alberta, Canada\r\n677\r\nRoss River, Alberta, Canada\r\n969\r\nRumsey, Alberta, Canada\r\n368\r\nRycroft, Alberta, Canada\r\n765\r\nRyley, Alberta, Canada\r\n663\r\nSachs Hrbr, Alberta, Canada\r\n690\r\nSangudo, Alberta, Canada\r\n785\r\nSask Rv Cr, Alberta, Canada\r\n761\r\nSchuler, Alberta, Canada\r\n839\r\nSeba Beach, Alberta, Canada\r\n797\r\nSedgewick, Alberta, Canada\r\n384\r\nSevn Prsns, Alberta, Canada\r\n832\r\nSexsmith, Alberta, Canada\r\n568\r\nSherwoodpark, Alberta, Canada\r\n449\r\n464\r\n467\r\nSibbald, Alberta, Canada\r\n676\r\nSilver Vly, Alberta, Canada\r\n351\r\nSlave Lake, Alberta, Canada\r\n849\r\nSmith, Alberta, Canada\r\n829\r\nSmoky Lake, Alberta, Canada\r\n656\r\nSnchldochs, Alberta, Canada\r\n989\r\nSnowdrift, Alberta, Canada\r\n370\r\nSpence Bay, Alberta, Canada\r\n561\r\nSpirit Riv, Alberta, Canada\r\n864\r\nSpruce Grv, Alberta, Canada\r\n962\r\nSpruceview, Alberta, Canada\r\n728\r\nSt Albert, Alberta, Canada\r\n458\r\n459\r\n460\r\n470\r\n671\r\nSt Michael, Alberta, Canada\r\n896\r\nSt Paul, Alberta, Canada\r\n645\r\nStand Off, Alberta, Canada\r\n737\r\nStandard, Alberta, Canada\r\n644\r\nStavely, Alberta, Canada\r\n549\r\nStettler, Alberta, Canada\r\n740\r\n742\r\nStirling, Alberta, Canada\r\n756\r\nStonyplain, Alberta, Canada\r\n963\r\nStrathmore, Alberta, Canada\r\n934\r\nStrome, Alberta, Canada\r\n376\r\nSundre, Alberta, Canada\r\n638\r\nSwan Hills, Alberta, Canada\r\n333\r\nSwiftriver, Alberta, Canada\r\n851\r\nSylvanlake, Alberta, Canada\r\n887\r\nTaber, Alberta, Canada\r\n223\r\nTagish, Alberta, Canada\r\n399\r\nTeslin, Alberta, Canada\r\n390\r\nThorhild, Alberta, Canada\r\n398\r\nThorsby, Alberta, Canada\r\n789\r\nThreehills, Alberta, Canada\r\n443\r\nTilley, Alberta, Canada\r\n377\r\nTofield, Alberta, Canada\r\n662\r\nTomahawk, Alberta, Canada\r\n339\r\nTorrington, Alberta, Canada\r\n631\r\nTrochu, Alberta, Canada\r\n442\r\nTuktyaktuk, Alberta, Canada\r\n977\r\nTungsten, Alberta, Canada\r\n777\r\nTurner Vly, Alberta, Canada\r\n933\r\nTwo Hills, Alberta, Canada\r\n657\r\nValleyview, Alberta, Canada\r\n524\r\nVauxhall, Alberta, Canada\r\n654\r\nVegreville, Alberta, Canada\r\n632\r\nVermilion, Alberta, Canada\r\n853\r\nVeteran, Alberta, Canada\r\n575\r\nViking, Alberta, Canada\r\n336\r\nVilna, Alberta, Canada\r\n636\r\nVulcan, Alberta, Canada\r\n485\r\nWabamun, Alberta, Canada\r\n892\r\nWabasca, Alberta, Canada\r\n891\r\nWainwright, Alberta, Canada\r\n842\r\nWalsh, Alberta, Canada\r\n937\r\nWanham, Alberta, Canada\r\n694\r\nWarburg, Alberta, Canada\r\n848\r\nWarner, Alberta, Canada\r\n642\r\nWarspite, Alberta, Canada\r\n383\r\nWaskatenau, Alberta, Canada\r\n358\r\nWatertonpk, Alberta, Canada\r\n859\r\nWatsonlake, Alberta, Canada\r\n536\r\nWembley, Alberta, Canada\r\n766\r\nWestlock, Alberta, Canada\r\n349\r\nWetaskiwin, Alberta, Canada\r\n352\r\n361\r\nWhitecourt, Alberta, Canada\r\n778\r\nWhitehorse, Alberta, Canada\r\n633\r\n667\r\n668\r\nWhitelaw, Alberta, Canada\r\n596\r\nWidewater, Alberta, Canada\r\n369\r\nWildwood, Alberta, Canada\r\n325\r\nWillingdon, Alberta, Canada\r\n367\r\nWinfield, Alberta, Canada\r\n682\r\nWandering Riv, Alberta, Canada\r\n771\r\nWoking, Alberta, Canada\r\n774\r\nWorsley, Alberta, Canada\r\n685\r\nWrentham, Alberta, Canada\r\n222\r\nWrigley, Alberta, Canada\r\n581\r\nYellowknife, Alberta, Canada\r\n669\r\n873\r\n920\r\nYoungstown, Alberta, Canada\r\n779\r\nZama, Alberta, Canada\r\n683\r\n\u00035Unknown prefix code (403) - Alberta\r\n"
  },
  {
    "path": "install/regions/regions.404",
    "content": "Atlanta, Georgia\r\n201\r\n202\r\n206\r\n209\r\n210\r\n212\r\n215\r\n218\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n230\r\n233\r\n235\r\n237\r\n238\r\n239\r\n240\r\n241\r\n243\r\n244\r\n248\r\n249\r\n250\r\n252\r\n255\r\n256\r\n257\r\n261\r\n262\r\n264\r\n266\r\n280\r\n281\r\n284\r\n286\r\n288\r\n289\r\n290\r\n291\r\n292\r\n294\r\n296\r\n297\r\n298\r\n299\r\n302\r\n303\r\n305\r\n308\r\n309\r\n310\r\n312\r\n313\r\n314\r\n315\r\n316\r\n317\r\n320\r\n321\r\n325\r\n329\r\n330\r\n331\r\n332\r\n341\r\n344\r\n346\r\n347\r\n349\r\n350\r\n351\r\n352\r\n355\r\n360\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n370\r\n371\r\n372\r\n373\r\n377\r\n378\r\n380\r\n383\r\n398\r\n401\r\n402\r\n403\r\n405\r\n406\r\n408\r\n415\r\n420\r\n444\r\n501\r\n505\r\n515\r\n520\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n529\r\n530\r\n550\r\n555\r\n556\r\n558\r\n559\r\n561\r\n566\r\n570\r\n572\r\n573\r\n577\r\n580\r\n581\r\n584\r\n586\r\n588\r\n589\r\n605\r\n607\r\n608\r\n609\r\n614\r\n616\r\n617\r\n619\r\n622\r\n624\r\n626\r\n633\r\n634\r\n636\r\n639\r\n651\r\n653\r\n656\r\n657\r\n658\r\n659\r\n669\r\n676\r\n679\r\n680\r\n681\r\n683\r\n686\r\n688\r\n690\r\n691\r\n696\r\n697\r\n699\r\n703\r\n705\r\n712\r\n714\r\n715\r\n716\r\n726\r\n727\r\n728\r\n730\r\n731\r\n741\r\n744\r\n752\r\n753\r\n755\r\n756\r\n758\r\n761\r\n762\r\n763\r\n765\r\n766\r\n767\r\n768\r\n771\r\n792\r\n794\r\n799\r\n805\r\n810\r\n814\r\n815\r\n817\r\n818\r\n827\r\n833\r\n837\r\n841\r\n842\r\n843\r\n847\r\n848\r\n851\r\n853\r\n863\r\n865\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n880\r\n881\r\n885\r\n888\r\n892\r\n894\r\n897\r\n898\r\n899\r\n906\r\n910\r\n976\r\n982\r\n999\r\n548\r\n629\r\n687\r\n724\r\n733\r\nBuckhead\u00031/\u00032Toco Hills, Georgia\r\n231\r\n816\r\nChamblee, Georgia\r\n551\r\n708\r\n628\r\n722\r\nDecatur, Georgia\r\n508\r\nFayetteville, Georgia\r\n631\r\nLa Grange, Georgia\r\n845\r\nManchester, Georgia\r\n846\r\nNorcross, Georgia\r\n713\r\n905\r\n689\r\n738\r\nRossville, Georgia\r\n891\r\nRoswell, Georgia\r\n552\r\nSmyrna, Georgia\r\n432\r\nWest Point, Georgia\r\n585\r\n\u00035Unknown prefix code (404) - Georgia\r\n"
  },
  {
    "path": "install/regions/regions.405",
    "content": "Achille, Oklahoma\r\n283\r\nAda, Oklahoma\r\n332\r\n421\r\n436\r\nAdams, Oklahoma\r\n253\r\nAlex, Oklahoma\r\n785\r\nAlfalfa, Oklahoma\r\n637\r\nAline, Oklahoma\r\n463\r\nAllen, Oklahoma\r\n857\r\nAltus, Oklahoma\r\n471\r\n477\r\n481\r\n482\r\nAlva, Oklahoma\r\n327\r\nAmes, Oklahoma\r\n753\r\nAnadarko, Oklahoma\r\n247\r\nAntlers, Oklahoma\r\n298\r\nApache, Oklahoma\r\n588\r\nArcadia, Oklahoma\r\n396\r\nArdmore, Oklahoma\r\n221\r\n223\r\n226\r\n264\r\n465\r\nArdmrair Park, Oklahoma\r\n389\r\nArnett, Oklahoma\r\n885\r\nAsher, Oklahoma\r\n784\r\nAtoka, Oklahoma\r\n889\r\nAtwood, Oklahoma\r\n986\r\nBalko, Oklahoma\r\n646\r\nBattiest, Oklahoma\r\n241\r\nBeaver, Oklahoma\r\n625\r\nBennington, Oklahoma\r\n847\r\nBessie, Oklahoma\r\n337\r\nBethany, Oklahoma\r\n491\r\n495\r\n720\r\n721\r\n722\r\n787\r\n789\r\n791\r\n792\r\n798\r\nBillings, Oklahoma\r\n725\r\nBinger, Oklahoma\r\n656\r\nBlackwell, Oklahoma\r\n363\r\nBlair, Oklahoma\r\n563\r\nBlanchard, Oklahoma\r\n485\r\nBoise City, Oklahoma\r\n544\r\nBokchito, Oklahoma\r\n295\r\nBooker, Oklahoma\r\n768\r\nBoswell, Oklahoma\r\n566\r\nBowlegs, Oklahoma\r\n398\r\nBradley, Oklahoma\r\n462\r\nBraman, Oklahoma\r\n385\r\nBreckinridge, Oklahoma\r\n446\r\nBritton, Oklahoma\r\n475\r\n478\r\n748\r\n749\r\n751\r\n752\r\n755\r\n775\r\n841\r\n842\r\n843\r\n848\r\n858\r\n879\r\nBroken Bow, Oklahoma\r\n584\r\nBromide, Oklahoma\r\n638\r\nBryans Cor, Oklahoma\r\n361\r\nBuffalo, Oklahoma\r\n735\r\nBurlington, Oklahoma\r\n431\r\nBurns Flat, Oklahoma\r\n562\r\nButler, Oklahoma\r\n664\r\nByars, Oklahoma\r\n783\r\nByron, Oklahoma\r\n474\r\nCache, Oklahoma\r\n429\r\nCaddo, Oklahoma\r\n367\r\nCalera, Oklahoma\r\n434\r\nCalumet, Oklahoma\r\n893\r\nCalvin, Oklahoma\r\n645\r\nCamargo, Oklahoma\r\n926\r\nCanton, Oklahoma\r\n886\r\nCanute, Oklahoma\r\n472\r\nCapron, Oklahoma\r\n829\r\nCarmen, Oklahoma\r\n987\r\nCarnegie, Oklahoma\r\n654\r\nCarney, Oklahoma\r\n865\r\nCarrier, Oklahoma\r\n855\r\nCarter, Oklahoma\r\n486\r\nCartwright, Oklahoma\r\n965\r\nCashion, Oklahoma\r\n433\r\nCedar Lake, Oklahoma\r\n284\r\nCement, Oklahoma\r\n489\r\nChandler, Oklahoma\r\n258\r\nChattanoga, Oklahoma\r\n597\r\nCherokee, Oklahoma\r\n596\r\nChester, Oklahoma\r\n764\r\nCheyenne, Oklahoma\r\n497\r\nChickasha, Oklahoma\r\n222\r\n224\r\n779\r\nChoctaw, Oklahoma\r\n390\r\nClarita, Oklahoma\r\n428\r\nCleo Springs, Oklahoma\r\n438\r\nClinton, Oklahoma\r\n323\r\n331\r\n445\r\nCoalgate, Oklahoma\r\n927\r\nColbert, Oklahoma\r\n296\r\nColony, Oklahoma\r\n929\r\nComanche, Oklahoma\r\n439\r\nConnervl, Oklahoma\r\n836\r\nCordell, Oklahoma\r\n832\r\nCorn, Oklahoma\r\n343\r\nCovington, Oklahoma\r\n864\r\nCoyle, Oklahoma\r\n466\r\nCrescent, Oklahoma\r\n969\r\nCromwell, Oklahoma\r\n944\r\nCustercity, Oklahoma\r\n593\r\nCyril, Oklahoma\r\n464\r\nDacoma, Oklahoma\r\n871\r\nDarrouzett, Oklahoma\r\n984\r\nDavidson, Oklahoma\r\n568\r\nDavis, Oklahoma\r\n369\r\nDeer Creek, Oklahoma\r\n267\r\nDel City, Oklahoma\r\n672\r\n677\r\nDevol, Oklahoma\r\n299\r\nDibble, Oklahoma\r\n344\r\nDill City, Oklahoma\r\n674\r\nDougherty, Oklahoma\r\n993\r\nDouglas, Oklahoma\r\n862\r\nDover, Oklahoma\r\n828\r\nDrummond, Oklahoma\r\n493\r\nDuke, Oklahoma\r\n679\r\nDuncan, Oklahoma\r\n251\r\n252\r\n255\r\n467\r\nDurant, Oklahoma\r\n920\r\n924\r\nEagletown, Oklahoma\r\n835\r\nEakly, Oklahoma\r\n797\r\nEarlsboro, Oklahoma\r\n997\r\nEdmond, Oklahoma\r\n330\r\n340\r\n341\r\n348\r\n359\r\nEl Reno, Oklahoma\r\n262\r\n422\r\nEldorado, Oklahoma\r\n633\r\nElgin, Oklahoma\r\n492\r\nElk City, Oklahoma\r\n225\r\n243\r\n821\r\nElmer, Oklahoma\r\n687\r\nElmore City, Oklahoma\r\n788\r\nElmore West, Oklahoma\r\n432\r\nEnid, Oklahoma\r\n233\r\n234\r\n237\r\n242\r\n249\r\n540\r\n541\r\n548\r\nErick, Oklahoma\r\n526\r\nEva, Oklahoma\r\n545\r\nFairmont, Oklahoma\r\n358\r\nFairview, Oklahoma\r\n227\r\nFargo, Oklahoma\r\n698\r\nFay, Oklahoma\r\n887\r\nFeltwheles, Oklahoma\r\n426\r\nFittstown, Oklahoma\r\n777\r\nFletcher, Oklahoma\r\n549\r\nFloris, Oklahoma\r\n259\r\nForgan, Oklahoma\r\n487\r\nFort Cobb, Oklahoma\r\n643\r\nFort Supply, Oklahoma\r\n766\r\nFort Towson, Oklahoma\r\n873\r\nFoss, Oklahoma\r\n592\r\nFrederick, Oklahoma\r\n335\r\nFreedom, Oklahoma\r\n621\r\nGage, Oklahoma\r\n923\r\nGarber, Oklahoma\r\n863\r\nGate, Oklahoma\r\n934\r\nGeary, Oklahoma\r\n884\r\nGene Autry, Oklahoma\r\n294\r\nGerty, Oklahoma\r\n892\r\nGlencoe, Oklahoma\r\n669\r\nGoltry, Oklahoma\r\n496\r\nGoodwell, Oklahoma\r\n349\r\nGotebo, Oklahoma\r\n538\r\nGould, Oklahoma\r\n676\r\nGracemont, Oklahoma\r\n966\r\nGrandfield, Oklahoma\r\n479\r\nGranite, Oklahoma\r\n535\r\nGriggs, Oklahoma\r\n543\r\nGuthrie, Oklahoma\r\n282\r\nGuymon, Oklahoma\r\n338\r\n651\r\nHammon, Oklahoma\r\n473\r\nHardesty, Oklahoma\r\n888\r\nHarmon, Oklahoma\r\n939\r\nHarrah, Oklahoma\r\n454\r\nHastings, Oklahoma\r\n963\r\nHeadrick, Oklahoma\r\n738\r\nHealdton, Oklahoma\r\n229\r\nHelena, Oklahoma\r\n852\r\nHennepin, Oklahoma\r\n868\r\nHennessey, Oklahoma\r\n853\r\nHiggins, Oklahoma\r\n982\r\nHillsdale, Oklahoma\r\n635\r\nHinton, Oklahoma\r\n542\r\nHitchcock, Oklahoma\r\n825\r\nHobart, Oklahoma\r\n726\r\nHochatown, Oklahoma\r\n494\r\nHoldenville, Oklahoma\r\n379\r\nHollis, Oklahoma\r\n688\r\nHooker, Oklahoma\r\n652\r\nHopeton, Oklahoma\r\n435\r\nHugo, Oklahoma\r\n326\r\nHunter, Oklahoma\r\n684\r\nHydro, Oklahoma\r\n663\r\nIdabel, Oklahoma\r\n245\r\n286\r\nIndiahoma, Oklahoma\r\n246\r\nJet, Oklahoma\r\n626\r\nJones, Oklahoma\r\n399\r\nKaw City, Oklahoma\r\n269\r\nKemp, Oklahoma\r\n838\r\nKenton, Oklahoma\r\n261\r\nKeyes, Oklahoma\r\n546\r\nKingfisher, Oklahoma\r\n368\r\n375\r\n699\r\nKingston, Oklahoma\r\n564\r\nKonawa, Oklahoma\r\n925\r\nKremlin, Oklahoma\r\n874\r\nLahoma, Oklahoma\r\n796\r\nLamont, Oklahoma\r\n388\r\nLaverne, Oklahoma\r\n921\r\nLawton, Oklahoma\r\n248\r\n250\r\n351\r\n353\r\n355\r\n357\r\n442\r\n458\r\n531\r\n536\r\n581\r\n585\r\n591\r\n595\r\nLeedey, Oklahoma\r\n488\r\nLindsay, Oklahoma\r\n756\r\nLoco, Oklahoma\r\n537\r\nLogan, Oklahoma\r\n837\r\nLone Grove, Oklahoma\r\n657\r\nLone Wolf, Oklahoma\r\n846\r\nLongdale, Oklahoma\r\n274\r\nLookeba, Oklahoma\r\n457\r\nLoyal, Oklahoma\r\n729\r\nLuther, Oklahoma\r\n277\r\nMadill, Oklahoma\r\n795\r\nManchester, Oklahoma\r\n694\r\nMangum, Oklahoma\r\n782\r\nManitou, Oklahoma\r\n397\r\nMarietta, Oklahoma\r\n276\r\nMarland, Oklahoma\r\n268\r\nMarlow, Oklahoma\r\n658\r\nMarshall, Oklahoma\r\n935\r\nMartha, Oklahoma\r\n266\r\nMaud, Oklahoma\r\n374\r\nMay, Oklahoma\r\n689\r\nMaysville, Oklahoma\r\n867\r\nMcloud, Oklahoma\r\n964\r\nMedford, Oklahoma\r\n395\r\nMedicine Park, Oklahoma\r\n529\r\nMeeker, Oklahoma\r\n279\r\nMeno, Oklahoma\r\n776\r\nMeridian, Oklahoma\r\n586\r\nMidwest City\u00031/\u00032Tinker AFB, Oklahoma\r\n732\r\n733\r\n734\r\n737\r\nMidwest City, Oklahoma\r\n731\r\n736\r\n739\r\n741\r\nMilburn, Oklahoma\r\n443\r\nMill Creek, Oklahoma\r\n384\r\nMillerton, Oklahoma\r\n746\r\nMinco, Oklahoma\r\n352\r\nMoore, Oklahoma\r\n691\r\n692\r\n793\r\n799\r\n794\r\nMooreland, Oklahoma\r\n994\r\nMorrison, Oklahoma\r\n724\r\nMountainview, Oklahoma\r\n347\r\nMulhall, Oklahoma\r\n649\r\nMustang, Oklahoma\r\n376\r\nMutual, Oklahoma\r\n989\r\nNash, Oklahoma\r\n839\r\nNewalla, Oklahoma\r\n391\r\nNewcastle, Oklahoma\r\n387\r\n392\r\nNewkirk, Oklahoma\r\n362\r\nNicomapark, Oklahoma\r\n769\r\nNoble, Oklahoma\r\n872\r\nNorman, Oklahoma\r\n321\r\n322\r\n325\r\n360\r\n364\r\n366\r\n447\r\n573\r\n329\r\nOak Hill, Oklahoma\r\n420\r\nOakwood, Oklahoma\r\n891\r\nOkarche, Oklahoma\r\n263\r\nOkeene, Oklahoma\r\n822\r\nOklahoma City, Oklahoma\r\n230\r\n231\r\n232\r\n235\r\n236\r\n239\r\n270\r\n271\r\n272\r\n278\r\n291\r\n297\r\n424\r\n425\r\n427\r\n460\r\n521\r\n522\r\n523\r\n524\r\n525\r\n528\r\n530\r\n539\r\n551\r\n552\r\n556\r\n557\r\n558\r\n583\r\n599\r\n620\r\n627\r\n629\r\n630\r\n631\r\n632\r\n634\r\n636\r\n640\r\n641\r\n642\r\n644\r\n647\r\n650\r\n659\r\n671\r\n678\r\n680\r\n681\r\n682\r\n685\r\n686\r\n823\r\n826\r\n942\r\n943\r\n945\r\n946\r\n947\r\n948\r\n949\r\n951\r\n954\r\n976\r\n555\r\n670\r\n728\r\n840\r\nOklahoma State University, Oklahoma\r\n744\r\nOlustee, Oklahoma\r\n648\r\nOrlando, Oklahoma\r\n455\r\nPaden, Oklahoma\r\n932\r\nPaoli, Oklahoma\r\n484\r\nPauls Valley, Oklahoma\r\n238\r\nPearson, Oklahoma\r\n333\r\nPerkins, Oklahoma\r\n547\r\nPerry, Oklahoma\r\n336\r\nPerryton, Oklahoma\r\n992\r\nPiedmont, Oklahoma\r\n373\r\nPike City, Oklahoma\r\n673\r\nPocasset, Oklahoma\r\n459\r\nPonca City, Oklahoma\r\n761\r\n762\r\n763\r\n765\r\n767\r\nPond Creek, Oklahoma\r\n532\r\nPrague, Oklahoma\r\n567\r\nPurcell, Oklahoma\r\n527\r\nPutnam, Oklahoma\r\n582\r\nQuinlan, Oklahoma\r\n697\r\nRandlett, Oklahoma\r\n281\r\nRatliff City, Oklahoma\r\n856\r\nRattan, Oklahoma\r\n587\r\nRed Rock, Oklahoma\r\n723\r\nReed, Oklahoma\r\n683\r\nReydon, Oklahoma\r\n655\r\nRingling, Oklahoma\r\n662\r\nRingwood, Oklahoma\r\n883\r\nRocky, Oklahoma\r\n666\r\nRoff, Oklahoma\r\n456\r\nRogermills, Oklahoma\r\n983\r\nRoosevelt, Oklahoma\r\n639\r\nRosedale, Oklahoma\r\n469\r\nRufe, Oklahoma\r\n876\r\nRush Springs, Oklahoma\r\n476\r\nRyan, Oklahoma\r\n757\r\nSasakwa, Oklahoma\r\n941\r\nSayre, Oklahoma\r\n928\r\nSeiling, Oklahoma\r\n922\r\nSelman, Oklahoma\r\n727\r\nSeminole, Oklahoma\r\n382\r\nSentinel, Oklahoma\r\n393\r\nSharon, Oklahoma\r\n866\r\nShattuck, Oklahoma\r\n938\r\nShawnee, Oklahoma\r\n273\r\n275\r\n878\r\nSmithville, Oklahoma\r\n244\r\nSnyder, Oklahoma\r\n569\r\nSouth Arkansas City, Oklahoma\r\n448\r\nSouth Bluff City, Oklahoma\r\n968\r\nSouth Coldwater, Oklahoma\r\n589\r\nSouth Elkhart, Oklahoma\r\n696\r\nSouth Englewood, Oklahoma\r\n533\r\nSouth Waldron, Oklahoma\r\n985\r\nSouth Caldwell, Oklahoma\r\n849\r\nSouth Hardtner, Oklahoma\r\n293\r\nSoper, Oklahoma\r\n345\r\nSouthhaven, Oklahoma\r\n894\r\nSouthmeade, Oklahoma\r\n877\r\nSpencer, Oklahoma\r\n771\r\nSpringer, Oklahoma\r\n653\r\nSaint Louis, Oklahoma\r\n289\r\nStella, Oklahoma\r\n386\r\nSterling, Oklahoma\r\n365\r\nStillwater, Oklahoma\r\n372\r\n377\r\n378\r\n624\r\n742\r\n743\r\n747\r\nStonewall, Oklahoma\r\n265\r\nStratford, Oklahoma\r\n759\r\nStringtown, Oklahoma\r\n346\r\nSulphur, Oklahoma\r\n622\r\nSweetwater, Oklahoma\r\n534\r\nTaloga, Oklahoma\r\n328\r\nTecumseh, Oklahoma\r\n598\r\nTemple, Oklahoma\r\n342\r\nTerral, Oklahoma\r\n437\r\nTexhoma, Oklahoma\r\n423\r\nThomas, Oklahoma\r\n661\r\nTipton, Oklahoma\r\n667\r\nTishomingo, Oklahoma\r\n371\r\nTonkawa, Oklahoma\r\n628\r\nTribbey, Oklahoma\r\n899\r\nTupelo, Oklahoma\r\n845\r\nTurpin, Oklahoma\r\n778\r\nTuttle, Oklahoma\r\n381\r\nTyrone, Oklahoma\r\n854\r\nUnion City, Oklahoma\r\n483\r\nValliant, Oklahoma\r\n933\r\nVelma, Oklahoma\r\n444\r\nVerden, Oklahoma\r\n453\r\nVici, Oklahoma\r\n995\r\nVinson, Oklahoma\r\n675\r\nWakita, Oklahoma\r\n594\r\nWalters, Oklahoma\r\n875\r\nWanette, Oklahoma\r\n383\r\nWapanucka, Oklahoma\r\n937\r\nWashington, Oklahoma\r\n288\r\nWatonga, Oklahoma\r\n623\r\nWaukomis, Oklahoma\r\n758\r\nWaurika, Oklahoma\r\n228\r\nWayne, Oklahoma\r\n449\r\nWaynoka, Oklahoma\r\n824\r\nWeatherford, Oklahoma\r\n772\r\n774\r\nWeleetka, Oklahoma\r\n786\r\nWellston, Oklahoma\r\n356\r\nWetumka, Oklahoma\r\n452\r\nWewoka, Oklahoma\r\n257\r\nWheatland, Oklahoma\r\n745\r\nWillow, Oklahoma\r\n287\r\nWilson, Oklahoma\r\n668\r\nWoodford, Oklahoma\r\n561\r\nWoodward, Oklahoma\r\n254\r\n256\r\n334\r\nWright City, Oklahoma\r\n981\r\nWynnewood, Oklahoma\r\n665\r\nYuba, Oklahoma\r\n285\r\nYukon, Oklahoma\r\n324\r\n350\r\n354\r\n577\r\n\u00035Unknown prefix code (405) - Oklahoma\r\n"
  },
  {
    "path": "install/regions/regions.406",
    "content": "Absarokee, Montana\r\n328\r\nAlberton, Montana\r\n722\r\nAlta, Montana\r\n349\r\nAlzada, Montana\r\n828\r\nAmsterdam, Montana\r\n282\r\nAnaconda, Montana\r\n560\r\n563\r\n691\r\n797\r\nArlee, Montana\r\n726\r\nAshland, Montana\r\n784\r\nAugusta, Montana\r\n562\r\nAvon, Montana\r\n492\r\nBainville, Montana\r\n769\r\nBaker, Montana\r\n778\r\nBelfry, Montana\r\n664\r\nBelgrade, Montana\r\n388\r\nBelt, Montana\r\n277\r\nBig Sandy, Montana\r\n378\r\nBig Sky, Montana\r\n993\r\n995\r\nBig Timber, Montana\r\n932\r\nBig Fork, Montana\r\n837\r\nBillings, Montana\r\n238\r\n245\r\n248\r\n252\r\n254\r\n255\r\n256\r\n259\r\n551\r\n652\r\n655\r\n656\r\n657\r\n680\r\n698\r\n855\r\n999\r\nBirney, Montana\r\n984\r\nBloomfield, Montana\r\n583\r\nBoulder, Montana\r\n225\r\nBox Elder, Montana\r\n352\r\nBozeman, Montana\r\n580\r\n581\r\n585\r\n586\r\n587\r\n590\r\n994\r\nBrady, Montana\r\n753\r\nBridger, Montana\r\n662\r\nBroadus, Montana\r\n436\r\nBroadview, Montana\r\n667\r\nBrockton, Montana\r\n786\r\nBrowning, Montana\r\n338\r\nBusby, Montana\r\n592\r\nButte, Montana\r\n490\r\n491\r\n494\r\n496\r\n723\r\n781\r\n782\r\nCanyon Creek, Montana\r\n368\r\nCanyon Ferry, Montana\r\n475\r\nCarlyle, Montana\r\n588\r\nCarter, Montana\r\n734\r\nCascade, Montana\r\n468\r\nCharlo, Montana\r\n644\r\nChester, Montana\r\n759\r\nChinook, Montana\r\n357\r\nChoteau, Montana\r\n466\r\nCircle, Montana\r\n485\r\nClancy, Montana\r\n933\r\nClinton, Montana\r\n825\r\nClyde Park, Montana\r\n686\r\nColstrip, Montana\r\n748\r\nColumbia Falls, Montana\r\n892\r\nColumbus, Montana\r\n322\r\nCondon, Montana\r\n754\r\nConrad, Montana\r\n278\r\nCooke City, Montana\r\n838\r\nCrooked Creek, Montana\r\n484\r\nCrow Agency, Montana\r\n638\r\nCorvallis, Montana\r\n961\r\nCulbertson, Montana\r\n787\r\nNorth Custer, Montana\r\n856\r\nCut Bank, Montana\r\n873\r\nDagmar, Montana\r\n483\r\nDarby, Montana\r\n821\r\nDecker, Montana\r\n757\r\nDeer Lodge, Montana\r\n846\r\nDenton, Montana\r\n567\r\nDevon, Montana\r\n432\r\nDillon, Montana\r\n683\r\nDivide, Montana\r\n267\r\nDixon, Montana\r\n246\r\nDodson, Montana\r\n383\r\nDrummond, Montana\r\n288\r\nDupuyer, Montana\r\n472\r\nDutton, Montana\r\n476\r\nEast Conrad, Montana\r\n627\r\nEast Glacier Park, Montana\r\n226\r\nEkalaka, Montana\r\n775\r\nElmo, Montana\r\n849\r\nEnnis, Montana\r\n682\r\nEthridge, Montana\r\n339\r\nEureka, Montana\r\n296\r\nEureka Rular, Montana\r\n889\r\nFairfield, Montana\r\n467\r\nFairview, Montana\r\n747\r\nFallon, Montana\r\n486\r\nFinley Point, Montana\r\n887\r\nFlaxville, Montana\r\n779\r\n474\r\nForsyth, Montana\r\n340\r\n356\r\nFort Peck, Montana\r\n526\r\nFort Shaw, Montana\r\n264\r\nFort Smith, Montana\r\n666\r\nFort Benton, Montana\r\n622\r\nFortine, Montana\r\n882\r\nFrazer, Montana\r\n695\r\nFrenchtown, Montana\r\n626\r\nFroid, Montana\r\n766\r\nFroid Rural, Montana\r\n963\r\nFromberg, Montana\r\n668\r\nGallatin Gateway, Montana\r\n763\r\nGardiner, Montana\r\n848\r\nGeraldine, Montana\r\n737\r\nGeyser, Montana\r\n735\r\nGildford, Montana\r\n376\r\nGlasgow, Montana\r\n228\r\n263\r\n298\r\n488\r\nGlendive, Montana\r\n359\r\n365\r\n940\r\nGlentana, Montana\r\n724\r\nGrant, Montana\r\n681\r\nGrass Range, Montana\r\n428\r\nGreat Falls, Montana\r\n452\r\n453\r\n454\r\n455\r\n727\r\n761\r\n771\r\n788\r\n790\r\n791\r\n799\r\nHamilton, Montana\r\n360\r\n363\r\nHardin, Montana\r\n665\r\n679\r\n690\r\nHarlem, Montana\r\n353\r\nHarlowton, Montana\r\n632\r\nHarrison, Montana\r\n685\r\nHaugan, Montana\r\n678\r\nHavre, Montana\r\n265\r\nHays, Montana\r\n673\r\nHelena, Montana\r\n227\r\n431\r\n439\r\n441\r\n442\r\n443\r\n444\r\n447\r\n449\r\n458\r\n499\r\nHighwood, Montana\r\n733\r\nHingham, Montana\r\n397\r\nHinsdale, Montana\r\n364\r\nHobson, Montana\r\n423\r\nHoppilliad, Montana\r\n386\r\nHot Springs, Montana\r\n741\r\nHungry Horse, Montana\r\n387\r\nHuntley, Montana\r\n348\r\nHysham, Montana\r\n342\r\nJackson, Montana\r\n834\r\nJoliet, Montana\r\n962\r\nJoplin, Montana\r\n292\r\nJordan, Montana\r\n557\r\nJudith Gap, Montana\r\n473\r\nKalispell, Montana\r\n257\r\n752\r\n755\r\n756\r\nKalispell (Cellular), Montana\r\n253\r\n758\r\nKeven, Montana\r\n337\r\nKremlin, Montana\r\n372\r\nLakeside, Montana\r\n844\r\nLambert, Montana\r\n774\r\nLame Deer, Montana\r\n477\r\nLarsian, Montana\r\n725\r\nLaurel, Montana\r\n628\r\nLavina, Montana\r\n636\r\nLewistown, Montana\r\n366\r\n369\r\n538\r\nLibby, Montana\r\n293\r\nLima, Montana\r\n276\r\nLincoln, Montana\r\n362\r\nLindsey, Montana\r\n584\r\nLivingston, Montana\r\n222\r\nLodge Grass, Montana\r\n639\r\nLolo, Montana\r\n273\r\nLoma, Montana\r\n739\r\nMalstrom AFB, Montana\r\n731\r\nMalta, Montana\r\n654\r\nManhattan, Montana\r\n284\r\nMarion, Montana\r\n854\r\nMartinsdale, Montana\r\n572\r\nMcGregor Lake, Montana\r\n858\r\nMedicine Lake, Montana\r\n789\r\nMelrose, Montana\r\n835\r\nMelstone, Montana\r\n358\r\nMelville, Montana\r\n537\r\nMidvale, Montana\r\n555\r\nMiles City, Montana\r\n232\r\n853\r\n890\r\n951\r\nMilltown, Montana\r\n258\r\nMissoula, Montana\r\n240\r\n243\r\n251\r\n329\r\n523\r\n541\r\n542\r\n543\r\n544\r\n549\r\n599\r\n721\r\n728\r\nMolt, Montana\r\n669\r\nMoore, Montana\r\n374\r\nMusselshell, Montana\r\n947\r\nNashua, Montana\r\n746\r\nNeihart, Montana\r\n236\r\nNorth Broadus, Montana\r\n554\r\nNorth Cut Bank, Montana\r\n336\r\nNorth Frannie, Montana\r\n764\r\nNorth Glasgow, Montana\r\n367\r\nNorth Nashua, Montana\r\n785\r\nNorth Parkman, Montana\r\n659\r\nNorth Poplar, Montana\r\n448\r\nNorth Ryegate, Montana\r\n575\r\nNorth Wolf Point, Montana\r\n392\r\nNorth Hinsdale, Montana\r\n648\r\nNorth Havre, Montana\r\n394\r\n398\r\nNoxon, Montana\r\n847\r\nOlney, Montana\r\n881\r\nOpheim, Montana\r\n762\r\nOutlook, Montana\r\n895\r\nOvando, Montana\r\n793\r\nPablo, Montana\r\n675\r\nPark City, Montana\r\n633\r\nPeerless, Montana\r\n893\r\nPendroy, Montana\r\n469\r\nPhillipsburg, Montana\r\n859\r\nPlains, Montana\r\n826\r\nPlentywood, Montana\r\n765\r\nPlevna, Montana\r\n772\r\nPompeys Pillar, Montana\r\n875\r\nPolson, Montana\r\n883\r\nPoplar, Montana\r\n768\r\nPotomac, Montana\r\n244\r\nPower, Montana\r\n463\r\nPray, Montana\r\n333\r\nRapelje, Montana\r\n663\r\nRaynesford, Montana\r\n738\r\nRed Lodge, Montana\r\n420\r\n425\r\n446\r\nReedpoint, Montana\r\n326\r\nReserve, Montana\r\n286\r\nRichey, Montana\r\n773\r\nRidge, Montana\r\n767\r\nRoberts, Montana\r\n445\r\nRock Springs, Montana\r\n354\r\nRonan, Montana\r\n676\r\nRosebud, Montana\r\n347\r\nRoundup, Montana\r\n323\r\nRoy, Montana\r\n464\r\nRudyard, Montana\r\n355\r\nRyegate, Montana\r\n568\r\nShepherd, Montana\r\n373\r\nSouth Alberton, Montana\r\n864\r\nSouth Miles City, Montana\r\n421\r\nSaco, Montana\r\n527\r\nSavage, Montana\r\n776\r\nScobey, Montana\r\n487\r\n783\r\nSeeley Lake, Montana\r\n677\r\nShelby, Montana\r\n434\r\nSheridan, Montana\r\n842\r\nSidney, Montana\r\n482\r\nSilvertip, Montana\r\n574\r\nSouth Broadus, Montana\r\n427\r\nSouth Chester, Montana\r\n456\r\nSouth Wolf Point, Montana\r\n525\r\nSomers, Montana\r\n857\r\nSouth Havre, Montana\r\n390\r\n395\r\nSouth Malta, Montana\r\n658\r\nSaint Mary, Montana\r\n732\r\nSaint Regis, Montana\r\n649\r\nStanford, Montana\r\n566\r\nStevensville, Montana\r\n777\r\nSt Ignatius, Montana\r\n745\r\nStockett, Montana\r\n736\r\nSunburst, Montana\r\n937\r\nSuperior, Montana\r\n822\r\nSwan Lake, Montana\r\n886\r\nSweet Grass, Montana\r\n335\r\nTerry, Montana\r\n637\r\nThompson Falls, Montana\r\n827\r\nThree Forks, Montana\r\n285\r\nTownsend, Montana\r\n266\r\n949\r\n980\r\nTroy, Montana\r\n295\r\nTurner, Montana\r\n379\r\nTwin Bridges, Montana\r\n684\r\nUlm, Montana\r\n866\r\nValier, Montana\r\n279\r\nVaughin, Montana\r\n965\r\nVictor, Montana\r\n642\r\nVirginia City, Montana\r\n843\r\nValley Indian Park, Montana\r\n524\r\nWest Glacier, Montana\r\n888\r\nWest Glendive, Montana\r\n687\r\n939\r\n970\r\n989\r\nWest Squaw Gap, Montana\r\n569\r\nWarm Springs, Montana\r\n693\r\nWest Camp Crook, Montana\r\n972\r\nWest Beach, Montana\r\n877\r\nWestby, Montana\r\n385\r\nWest Sidney, Montana\r\n798\r\nWhitefish, Montana\r\n862\r\nWhitehall, Montana\r\n287\r\nWhitewater, Montana\r\n674\r\nWhite Sulphur Springs, Montana\r\n547\r\nWibaux, Montana\r\n795\r\nWilsall, Montana\r\n578\r\nWinifred, Montana\r\n462\r\nWinnett, Montana\r\n429\r\nWisdom, Montana\r\n689\r\nWise River, Montana\r\n832\r\nWolf Creek, Montana\r\n235\r\nWolf Point, Montana\r\n653\r\nWorden, Montana\r\n967\r\nWest Yellowstone, Montana\r\n646\r\nWyola, Montana\r\n343\r\nYellow Bay, Montana\r\n982\r\n\u00035Unknown prefix code (406) - Montana\r\n"
  },
  {
    "path": "install/regions/regions.407",
    "content": "Apopka, Florida\r\n880\r\n884\r\n886\r\n889\r\nBelleglade, Florida\r\n992\r\n996\r\nBoca Raton, Florida\r\n241\r\n289\r\n338\r\n347\r\n361\r\n362\r\n367\r\n368\r\n378\r\n391\r\n392\r\n393\r\n394\r\n395\r\n443\r\n451\r\n457\r\n477\r\n479\r\n482\r\n483\r\n487\r\n488\r\n750\r\n852\r\n955\r\n982\r\n994\r\n995\r\n997\r\n998\r\nBoyinton Beach, Florida\r\n731\r\n364\r\n369\r\n375\r\n732\r\n734\r\n735\r\n736\r\n737\r\n738\r\nCocoa Beach, Florida\r\n494\r\n783\r\n784\r\n799\r\n853\r\n868\r\nCocoa, Florida\r\n258\r\n452\r\n453\r\n454\r\n455\r\n459\r\n480\r\n537\r\n543\r\n631\r\n632\r\n633\r\n635\r\n636\r\n639\r\n690\r\n730\r\n861\r\n867\r\n986\r\nDebary, Florida\r\n668\r\nDebary-Deltona, Florida\r\n574\r\n860\r\nDelray Beach, Florida\r\n243\r\n251\r\n265\r\n271\r\n272\r\n274\r\n276\r\n278\r\n279\r\n280\r\n495\r\n496\r\n498\r\n499\r\n637\r\nEast Orange, Florida\r\n568\r\nEau Gallie, Florida\r\n242\r\n253\r\n254\r\n255\r\n259\r\nFort Pierce, Florida\r\n462\r\n460\r\n461\r\n464\r\n465\r\n466\r\n467\r\n468\r\n489\r\n595\r\nGeneva, Florida\r\n349\r\nGreen Acres, Florida\r\n965\r\nHobe Sound, Florida\r\n545\r\n546\r\nIndian Harbor, Florida\r\n773\r\n777\r\n779\r\nIndiantown, Florida\r\n597\r\nJensen Beach, Florida\r\n225\r\n334\r\n692\r\nJupiter, Florida\r\n575\r\n743\r\n744\r\n745\r\n746\r\n747\r\nKenansville, Florida\r\n436\r\nKissimmee, Florida\r\n931\r\n935\r\n344\r\n348\r\n396\r\n397\r\n846\r\n847\r\n870\r\n873\r\n932\r\n933\r\nLake Buena Vista, Florida\r\n560\r\n824\r\n827\r\n828\r\n934\r\n939\r\nLake Mary, Florida\r\n333\r\n444\r\n942\r\nMelbourne, Florida\r\n726\r\n676\r\n722\r\n723\r\n724\r\n725\r\n727\r\n728\r\n729\r\n768\r\n951\r\n952\r\n984\r\nMontverde, Florida\r\n469\r\nOrange City, Florida\r\n774\r\n775\r\nOrlando, Florida\r\n325\r\n353\r\n441\r\n521\r\n527\r\n555\r\n763\r\n849\r\n858\r\n222\r\n228\r\n236\r\n237\r\n240\r\n244\r\n246\r\n247\r\n249\r\n256\r\n257\r\n273\r\n275\r\n277\r\n281\r\n282\r\n290\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n341\r\n342\r\n345\r\n351\r\n352\r\n354\r\n356\r\n363\r\n372\r\n376\r\n380\r\n381\r\n382\r\n384\r\n420\r\n422\r\n423\r\n424\r\n425\r\n426\r\n438\r\n578\r\n579\r\n648\r\n649\r\n651\r\n658\r\n675\r\n823\r\n825\r\n826\r\n836\r\n839\r\n841\r\n843\r\n850\r\n851\r\n855\r\n856\r\n857\r\n859\r\n872\r\n894\r\n895\r\n896\r\n897\r\n898\r\n899\r\nOviedo, Florida\r\n359\r\n365\r\n366\r\nPahokee, Florida\r\n924\r\nPoint Saint Luce, Florida\r\n229\r\n335\r\n336\r\n337\r\n340\r\n377\r\n398\r\n871\r\n878\r\n879\r\nReedy Creek, Florida\r\n238\r\n239\r\nSanford, Florida\r\n321\r\n322\r\n323\r\n324\r\n328\r\n330\r\nSebastian, Florida\r\n388\r\n571\r\n589\r\n663\r\n664\r\nSaint Cloud, Florida\r\n892\r\n957\r\nStuart, Florida\r\n220\r\n221\r\n223\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\nTitusville, Florida\r\n264\r\n267\r\n268\r\n269\r\n383\r\nVero Beach, Florida\r\n231\r\n234\r\n235\r\n538\r\n562\r\n563\r\n567\r\n569\r\n770\r\n778\r\nWest Palm Beach, Florida\r\n233\r\n329\r\n346\r\n355\r\n358\r\n371\r\n373\r\n379\r\n385\r\n386\r\n387\r\n433\r\n434\r\n439\r\n471\r\n478\r\n533\r\n540\r\n547\r\n550\r\n553\r\n554\r\n580\r\n582\r\n585\r\n586\r\n588\r\n622\r\n624\r\n625\r\n626\r\n627\r\n640\r\n641\r\n642\r\n650\r\n653\r\n655\r\n659\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n691\r\n694\r\n697\r\n751\r\n753\r\n754\r\n762\r\n790\r\n791\r\n793\r\n795\r\n796\r\n798\r\n820\r\n832\r\n833\r\n835\r\n837\r\n838\r\n840\r\n842\r\n844\r\n845\r\n848\r\n854\r\n863\r\n881\r\n936\r\n966\r\n967\r\n968\r\n969\r\n319\r\n882\r\n947\r\n964\r\nWindermere, Florida\r\n876\r\nWinter Garden, Florida\r\n656\r\n877\r\nWinter Park, Florida\r\n260\r\n262\r\n263\r\n331\r\n332\r\n339\r\n539\r\n623\r\n628\r\n629\r\n643\r\n644\r\n645\r\n646\r\n647\r\n657\r\n660\r\n661\r\n671\r\n672\r\n677\r\n678\r\n679\r\n682\r\n695\r\n696\r\n699\r\n740\r\n767\r\n788\r\n830\r\n831\r\n834\r\n862\r\n865\r\n869\r\n875\r\nWinter Springs, Florida\r\n327\r\nWinter Garden, Florida\r\n654\r\nWinter Park, Florida\r\n261\r\n621\r\n662\r\n741\r\n920\r\n941\r\n980\r\n981\r\n\u00035Unknown prefix code (407) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.408",
    "content": "Aptos, California\r\n662\r\n684\r\n685\r\n688\r\nBen Lomond, California\r\n336\r\nBig Sur, California\r\n667\r\nBoulder Creek, California\r\n338\r\nCambell, California\r\n364\r\n369\r\n370\r\n371\r\n374\r\n376\r\n377\r\n378\r\n379\r\n559\r\n866\r\n879\r\nCarmel, California\r\n622\r\n624\r\n625\r\n626\r\nCarmel Valley, California\r\n659\r\nCastroville, California\r\n633\r\nChualar, California\r\n679\r\nCupertino, California\r\n257\r\n258\r\nFelton, California\r\n335\r\nGilroy, California\r\n842\r\n847\r\n848\r\nGonzales, California\r\n675\r\nGreenfield, California\r\n674\r\nHollister, California\r\n636\r\n637\r\n638\r\nIdria, California\r\n693\r\nKing City, California\r\n385\r\n386\r\nLos Gatos, California\r\n353\r\n354\r\n356\r\n358\r\n395\r\n399\r\nMonterey, California\r\n242\r\n372\r\n373\r\n375\r\n384\r\n393\r\n394\r\n644\r\n645\r\n646\r\n647\r\n648\r\n649\r\n655\r\n656\r\n883\r\n899\r\nMorgan Hill, California\r\n776\r\n778\r\n779\r\nPinnacles, California\r\n389\r\nSalinas, California\r\n422\r\n424\r\n442\r\n443\r\n449\r\n455\r\n484\r\n594\r\n595\r\n598\r\n663\r\n671\r\n672\r\n673\r\n751\r\n753\r\n754\r\n755\r\n757\r\n758\r\n759\r\n766\r\n769\r\nSan Ardo, California\r\n627\r\nSan Jose\u00031/\u00032Sunnyvale, California\r\n245\r\n481\r\n522\r\n524\r\n541\r\n720\r\n721\r\n730\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n739\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n749\r\n752\r\n756\r\n773\r\n820\r\n973\r\n991\r\n992\r\nSan Jose, California\r\n221\r\n231\r\n234\r\n235\r\n236\r\n243\r\n244\r\n246\r\n247\r\n248\r\n249\r\n252\r\n253\r\n255\r\n261\r\n271\r\n275\r\n277\r\n279\r\n280\r\n282\r\n283\r\n285\r\n286\r\n287\r\n288\r\n289\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n332\r\n339\r\n345\r\n366\r\n381\r\n383\r\n388\r\n391\r\n397\r\n398\r\n436\r\n437\r\n441\r\n446\r\n447\r\n450\r\n451\r\n452\r\n453\r\n472\r\n482\r\n483\r\n485\r\n488\r\n491\r\n492\r\n494\r\n496\r\n497\r\n499\r\n521\r\n534\r\n552\r\n553\r\n554\r\n562\r\n575\r\n631\r\n697\r\n698\r\n699\r\n725\r\n727\r\n748\r\n764\r\n765\r\n777\r\n789\r\n798\r\n862\r\n864\r\n865\r\n888\r\n894\r\n920\r\n924\r\n925\r\n932\r\n934\r\n947\r\n951\r\n970\r\n971\r\n974\r\n975\r\n976\r\n977\r\n980\r\n981\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n989\r\n993\r\n994\r\n995\r\n996\r\n998\r\n999\r\n251\r\n254\r\n259\r\n262\r\n263\r\n272\r\n276\r\n321\r\n322\r\n428\r\n432\r\n433\r\n434\r\n435\r\n456\r\n473\r\n493\r\n729\r\n922\r\n923\r\n926\r\n928\r\n929\r\n942\r\n943\r\n944\r\n945\r\n946\r\n954\r\n955\r\n956\r\n957\r\n223\r\n224\r\n225\r\n226\r\n227\r\n229\r\n233\r\n237\r\n238\r\n239\r\n256\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n270\r\n274\r\n281\r\n284\r\n363\r\n365\r\n445\r\n448\r\n463\r\n578\r\n629\r\n723\r\n927\r\n972\r\n978\r\n979\r\n997\r\nSan Juan, California\r\n623\r\nSan Lucas, California\r\n382\r\nSan Martin, California\r\n683\r\n686\r\nSan Antonio, California\r\n897\r\nSanta Clara, California\r\n241\r\n555\r\nSanta Cruz, California\r\n423\r\n425\r\n426\r\n427\r\n429\r\n431\r\n438\r\n439\r\n454\r\n457\r\n458\r\n459\r\n461\r\n462\r\n464\r\n475\r\n476\r\n479\r\nSaratoga, California\r\n741\r\n867\r\nSoledad, California\r\n678\r\nSunnyvale, California\r\n774\r\nTres Pinos, California\r\n628\r\nWatsonville, California\r\n722\r\n724\r\n726\r\n728\r\n761\r\n763\r\n\u00035Unknown prefix code (408) - California\r\n"
  },
  {
    "path": "install/regions/regions.409",
    "content": "Alto, Texas\r\n858\r\nAnahuac, Texas\r\n267\r\nAnderson, Texas\r\n873\r\nAngleton, Texas\r\n848\r\n849\r\n922\r\nApple Springs, Texas\r\n831\r\nAustonio, Texas\r\n624\r\nBatson, Texas\r\n262\r\nBay City, Texas\r\n241\r\n244\r\n245\r\nBeasley, Texas\r\n387\r\nBeaumont, Texas\r\n654\r\n656\r\n757\r\n781\r\n832\r\n833\r\n835\r\n838\r\n839\r\n840\r\n841\r\n842\r\n866\r\n880\r\n881\r\n887\r\n892\r\n893\r\n898\r\n899\r\n860\r\nBedias, Texas\r\n395\r\nBellville, Texas\r\n865\r\nBlanchard, Texas\r\n967\r\nBlowing Nwglf, Texas\r\n657\r\nBon Wier, Texas\r\n397\r\nBorden, Texas\r\n263\r\nBrazra Chl, Texas\r\n798\r\n964\r\nBrenham, Texas\r\n277\r\n830\r\n836\r\nBridge City, Texas\r\n734\r\n735\r\nBroaddus, Texas\r\n872\r\nBronson, Texas\r\n586\r\nBryan, Texas\r\n222\r\n260\r\n268\r\n361\r\n690\r\n693\r\n696\r\n754\r\n759\r\n764\r\n774\r\n775\r\n776\r\n777\r\n778\r\n779\r\n820\r\n821\r\n822\r\n823\r\n845\r\n846\r\n847\r\n862\r\nBuna, Texas\r\n994\r\nBurkeville, Texas\r\n565\r\nBurton, Texas\r\n289\r\nCaldwell, Texas\r\n567\r\nCalvert, Texas\r\n364\r\nCarmine, Texas\r\n278\r\nCenter, Texas\r\n598\r\nCentral, Texas\r\n853\r\nChester, Texas\r\n969\r\nChina, Texas\r\n752\r\nChireno, Texas\r\n362\r\nClutlkjksn, Texas\r\n265\r\n266\r\n292\r\n297\r\n299\r\nColdspring, Texas\r\n653\r\nColmesneil, Texas\r\n837\r\nColumbus, Texas\r\n732\r\nConroe, Texas\r\n231\r\n264\r\n273\r\n525\r\n537\r\n538\r\n539\r\n588\r\n756\r\n760\r\n788\r\n321\r\nCorrigan, Texas\r\n398\r\nCrockett, Texas\r\n544\r\n546\r\nCushing, Texas\r\n326\r\nDamon, Texas\r\n553\r\n742\r\nDayton, Texas\r\n258\r\nDeanville, Texas\r\n535\r\nDevers, Texas\r\n549\r\nDeweyville, Texas\r\n746\r\nDiboll, Texas\r\n829\r\nDime Box, Texas\r\n884\r\nDoublebayu, Texas\r\n252\r\nEast Bernard, Texas\r\n335\r\nEagle Lake, Texas\r\n234\r\nEl Campo, Texas\r\n541\r\n543\r\nEtoile, Texas\r\n854\r\nEvadale, Texas\r\n276\r\nEvergreen, Texas\r\n767\r\nFairmount, Texas\r\n579\r\nFannett, Texas\r\n794\r\nFayetteville Texas\r\n378\r\nFranklin, Texas\r\n828\r\nFreeport, Texas\r\n233\r\n235\r\n238\r\n239\r\nFuller Springs, Texas\r\n824\r\nGalveston, Texas\r\n737\r\n739\r\n740\r\n744\r\n747\r\n761\r\n762\r\n763\r\n765\r\n766\r\n770\r\n771\r\n772\r\nGarrison, Texas\r\n347\r\nGarwood, Texas\r\n758\r\nGiddings, Texas\r\n542\r\nGlen Flora, Texas\r\n677\r\nGoodrich, Texas\r\n365\r\nGrapeland, Texas\r\n687\r\nGroveton, Texas\r\n642\r\nHamshire, Texas\r\n243\r\nHankamer, Texas\r\n374\r\nHardin, Texas\r\n298\r\nHearne, Texas\r\n279\r\nHemphill, Texas\r\n787\r\nHempstead, Texas\r\n826\r\nHigh Hill, Texas\r\n561\r\nHigh Island, Texas\r\n286\r\nHilltop Lake, Texas\r\n855\r\nHostyn, Texas\r\n247\r\nHouston, Texas\r\n555\r\nHtchk Sntf, Texas\r\n925\r\n986\r\nHudson, Texas\r\n875\r\nHull, Texas\r\n536\r\nHuntington, Texas\r\n422\r\n876\r\nHuntsville, Texas\r\n291\r\n293\r\n294\r\n295\r\n661\r\nHuxley, Texas\r\n368\r\nIndustry, Texas\r\n357\r\nIola, Texas\r\n394\r\nJasper, Texas\r\n383\r\n384\r\n698\r\nJoaquin, Texas\r\n269\r\nKennard, Texas\r\n655\r\nKirbyville, Texas\r\n423\r\nKountze, Texas\r\n246\r\nKurten, Texas\r\n589\r\nLa Belle, Texas\r\n796\r\nLa Grange, Texas\r\n968\r\nLexington, Texas\r\n773\r\nLiberty, Texas\r\n336\r\nLivingston, Texas\r\n327\r\nLouise, Texas\r\n648\r\nLovelady, Texas\r\n636\r\nLufkin, Texas\r\n632\r\n633\r\n634\r\n635\r\n637\r\n639\r\nLumberton, Texas\r\n755\r\nMadisonville, Texas\r\n348\r\nMarkham, Texas\r\n843\r\nMatagorda, Texas\r\n863\r\nMauriceville, Texas\r\n745\r\nMemorial Point, Texas\r\n566\r\nMilam, Texas\r\n625\r\nMontgomery, Texas\r\n582\r\n597\r\nMoravia, Texas\r\n562\r\nNacogoches, Texas\r\n552\r\n554\r\n560\r\n564\r\n568\r\n569\r\nNavasota, Texas\r\n825\r\nNeedville, Texas\r\n793\r\nNew Ulm, Texas\r\n992\r\nNewton, Texas\r\n379\r\nNew Waverly, Texas\r\n344\r\nNome, Texas\r\n253\r\nNormangee, Texas\r\n396\r\nNorthrup, Texas\r\n366\r\nNorth Zulch, Texas\r\n399\r\nOakhurst, Texas\r\n377\r\nOld Ocean, Texas\r\n491\r\n647\r\nOnalaska, Texas\r\n646\r\nOrange, Texas\r\n882\r\n883\r\n886\r\nPennington, Texas\r\n638\r\nPineland, Texas\r\n584\r\nPlantersville, Texas\r\n894\r\nPlum, Texas\r\n242\r\nPort Neches, Texas\r\n721\r\n722\r\n723\r\n724\r\n726\r\n727\r\n728\r\n729\r\nPrairie View, Texas\r\n857\r\nPort Arthur, Texas\r\n736\r\n962\r\n963\r\n982\r\n983\r\n985\r\n989\r\nPort Bolivar, Texas\r\n684\r\nRaywood, Texas\r\n587\r\nReklaw, Texas\r\n369\r\nRichards, Texas\r\n851\r\nRuby, Texas\r\n563\r\nSabine Pass, Texas\r\n971\r\nSan Augustine, Texas\r\n275\r\nSaratoga, Texas\r\n274\r\nSchulenburg, Texas\r\n743\r\nSealy, Texas\r\n885\r\nSegno, Texas\r\n685\r\nShepherd, Texas\r\n628\r\nShiro, Texas\r\n874\r\nSilsbee, Texas\r\n385\r\nSmithpoint, Texas\r\n355\r\nSnooktunis, Texas\r\n272\r\nSomerville, Texas\r\n596\r\nSour Lake, Texas\r\n287\r\nSouth Vidor, Texas\r\n768\r\nSpurger, Texas\r\n429\r\nSweeny, Texas\r\n490\r\n548\r\nTenaha, Texas\r\n248\r\nTexcylmarq, Texas\r\n643\r\n644\r\n935\r\n938\r\n942\r\n943\r\n945\r\n948\r\nTimpson, Texas\r\n254\r\nTrinity, Texas\r\n594\r\nVidor, Texas\r\n769\r\n786\r\nWest Columbia, Texas\r\n345\r\nWaller, Texas\r\n372\r\n931\r\nWallis, Texas\r\n478\r\nWallisville, Texas\r\n389\r\nWarren, Texas\r\n547\r\nWarrenton, Texas\r\n249\r\nWashington, Texas\r\n878\r\nWaterwood, Texas\r\n891\r\nWeimar, Texas\r\n725\r\nWells, Texas\r\n867\r\nWestbury, Texas\r\n753\r\nWharton, Texas\r\n282\r\n532\r\n533\r\nWildwood, Texas\r\n834\r\nWillis, Texas\r\n856\r\nWinnie, Texas\r\n296\r\nWoodville, Texas\r\n283\r\nZavalla, Texas\r\n897\r\n\u00035Unknown prefix code (409) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.410",
    "content": "Aberdeen, Maryland\r\n272\r\n273\r\n278\r\nAnnapolis, Maryland\r\n224\r\n263\r\n266\r\n267\r\n268\r\n280\r\n533\r\n562\r\n573\r\n626\r\n693\r\n703\r\n757\r\n956\r\n991\r\nArbutus, Maryland\r\n204\r\n242\r\n247\r\n536\r\nArmiger-Gibson Island, Maryland\r\n255\r\n360\r\n437\r\nArundal-North Beach, Maryland\r\n257\r\nBaltimore, Maryland\r\n201\r\n218\r\n545\r\n878\r\nBaltimore City, Maryland\r\n205\r\n225\r\n232\r\n233\r\n234\r\n235\r\n237\r\n243\r\n244\r\n254\r\n276\r\n291\r\n305\r\n319\r\n323\r\n325\r\n327\r\n328\r\n332\r\n333\r\n338\r\n342\r\n347\r\n351\r\n354\r\n355\r\n358\r\n361\r\n362\r\n366\r\n367\r\n368\r\n382\r\n383\r\n385\r\n389\r\n393\r\n396\r\n404\r\n426\r\n433\r\n435\r\n444\r\n448\r\n450\r\n456\r\n458\r\n462\r\n466\r\n467\r\n481\r\n483\r\n485\r\n488\r\n516\r\n522\r\n523\r\n525\r\n528\r\n532\r\n534\r\n537\r\n539\r\n542\r\n547\r\n550\r\n554\r\n558\r\n563\r\n566\r\n576\r\n578\r\n591\r\n605\r\n613\r\n614\r\n617\r\n624\r\n625\r\n631\r\n633\r\n637\r\n644\r\n646\r\n659\r\n664\r\n669\r\n675\r\n685\r\n706\r\n727\r\n728\r\n732\r\n752\r\n764\r\n783\r\n801\r\n804\r\n837\r\n889\r\n906\r\n915\r\n945\r\n947\r\n955\r\n960\r\n962\r\n999\r\nBaltimore County, Maryland\r\n844\r\n936\r\nBel Air, Maryland\r\n399\r\n638\r\n836\r\n838\r\nBerlin-Ocean Pines, Maryland\r\n208\r\n641\r\nBishopville, Maryland\r\n352\r\nBrooklyn Park-Linthicum, Maryland\r\n636\r\n789\r\nCalvert County-Prince Frederick\u00031/\u00032Prince George's County, Maryland\r\n535\r\nCambridge, Maryland\r\n221\r\n228\r\nCardiff, Maryland\r\n452\r\nCatonsville, Maryland\r\n370\r\n440\r\n446\r\n455\r\n719\r\n744\r\n747\r\n788\r\n802\r\n917\r\n971\r\n978\r\n979\r\n302\r\nCecilton, Maryland\r\n275\r\nCentreville, Maryland\r\n758\r\nChase, Maryland\r\n335\r\nCheasapeake City, Maryland\r\n885\r\nChesterton, Maryland\r\n708\r\nChestertown, Maryland\r\n778\r\nChrisfield, Maryland\r\n968\r\nChurchhill, Maryland\r\n556\r\nChurchville, Maryland\r\n734\r\nCockeysville, Maryland\r\n316\r\n329\r\n527\r\n584\r\n628\r\n666\r\n667\r\n683\r\n771\r\n785\r\nColumbia, Maryland\r\n290\r\n312\r\n381\r\n531\r\n715\r\n730\r\n740\r\n964\r\n992\r\n997\r\nCrofton, Maryland\r\n451\r\n721\r\nDarlington, Maryland\r\n457\r\nDeal Island, Maryland\r\n784\r\nDelmar, Maryland\r\n896\r\nDenton, Maryland\r\n479\r\nDundalk, Maryland\r\n282\r\n284\r\n285\r\n288\r\nEaston, Maryland\r\n310\r\n819\r\n820\r\n822\r\nEdgewood, Maryland\r\n569\r\n612\r\n671\r\n676\r\n679\r\nElkridge, Maryland\r\n379\r\n407\r\n471\r\n712\r\n796\r\n909\r\nElkton, Maryland\r\n392\r\n398\r\n996\r\nEllicott City, Maryland\r\n313\r\n418\r\n442\r\n465\r\n720\r\n748\r\n750\r\n781\r\n988\r\n995\r\nEssex, Maryland\r\n391\r\n574\r\n682\r\n686\r\n687\r\n780\r\n866\r\nFallston, Maryland\r\n877\r\nFederalsburg, Maryland\r\n754\r\nFork, Maryland\r\n515\r\n538\r\n557\r\n575\r\n592\r\n879\r\n893\r\nGalmena, Maryland\r\n648\r\nGlen Burnie, Maryland\r\n582\r\n508\r\n553\r\n684\r\n691\r\n760\r\n761\r\n765\r\n766\r\n768\r\n787\r\n850\r\n859\r\n892\r\n993\r\nGlenwood, Maryland\r\n489\r\nGreensburrow, Maryland\r\n482\r\nHampstead, Maryland\r\n374\r\nHarve De Grace, Maryland\r\n939\r\nHillsburrow, Maryland\r\n364\r\nHoward County, Maryland\r\n461\r\nHurlock, Maryland\r\n943\r\nJarrettsville, Maryland\r\n692\r\n941\r\nMarion, Maryland\r\n623\r\nMillersville, Maryland\r\n923\r\nMillington, Maryland\r\n928\r\nNanticoke, Maryland\r\n873\r\nNew Windsor, Maryland\r\n635\r\nNorth East, Maryland\r\n287\r\n920\r\nOcean City, Maryland\r\n213\r\n250\r\n289\r\n524\r\n723\r\nOdenton, Maryland\r\n672\r\n674\r\nOxford, Maryland\r\n226\r\nParkton, Maryland\r\n357\r\nParkville, Maryland\r\n529\r\n661\r\n665\r\n668\r\n931\r\nPerry Hall, Maryland\r\n256\r\n882\r\nPerryville, Maryland\r\n642\r\nPikesville, Maryland\r\n356\r\n363\r\n484\r\n486\r\n581\r\n602\r\n653\r\n998\r\nPocomoke City, Maryland\r\n957\r\nPort Deposit, Maryland\r\n378\r\nPreston, Maryland\r\n673\r\nPrince Anne's, Maryland\r\n651\r\nPrince Frederick, Maryland\r\n586\r\n610\r\nQueenstown, Maryland\r\n827\r\nRandallstown, Maryland\r\n521\r\n655\r\n922\r\nReisterstown, Maryland\r\n239\r\n526\r\n833\r\n876\r\nRidgely, Maryland\r\n634\r\nRising Sun, Maryland\r\n658\r\nRock Hall, Maryland\r\n639\r\nSalisbury, Maryland\r\n219\r\n430\r\n543\r\n546\r\n548\r\n603\r\n726\r\n742\r\n749\r\n860\r\nSevern, Maryland\r\n222\r\n514\r\n519\r\n551\r\n677\r\n969\r\n987\r\nSeverna Park, Maryland\r\n260\r\n269\r\n315\r\n541\r\n544\r\n647\r\n793\r\n841\r\n974\r\nSharptown, Maryland\r\n883\r\nSherwood Forest, Maryland\r\n849\r\nSilver Run, Maryland\r\n346\r\nSmithsland, Maryland\r\n425\r\nSnow Hill, Maryland\r\n632\r\nSolomons-Saint Mary, Maryland\r\n326\r\nSparks-Glencoe, Maryland\r\n343\r\n472\r\nSparrows Point, Maryland\r\n388\r\n477\r\nSaint Michael's, Maryland\r\n745\r\nStevesville, Maryland\r\n643\r\nStill Pond, Maryland\r\n348\r\nSudlerville, Maryland\r\n438\r\nSykesville, Maryland\r\n549\r\n795\r\n875\r\nTaneytown, Maryland\r\n756\r\nTilghman, Maryland\r\n886\r\nTowson, Maryland\r\n324\r\n408\r\n512\r\n812\r\n252\r\n296\r\n307\r\n321\r\n337\r\n339\r\n377\r\n494\r\n560\r\n561\r\n583\r\n716\r\n806\r\n821\r\n823\r\n825\r\n828\r\n830\r\n832\r\n887\r\n938\r\nTrappe, Maryland\r\n476\r\nUnion Bridge, Maryland\r\n775\r\nVienna, Maryland\r\n376\r\nWarwick, Maryland\r\n755\r\nWaterloo, Maryland\r\n792\r\n797\r\n799\r\n813\r\n880\r\nWest River, Maryland\r\n741\r\n798\r\n867\r\nWestminister, Maryland\r\n751\r\n848\r\n857\r\n861\r\nWillards, Maryland\r\n835\r\nWingate, Maryland\r\n397\r\nWoodlawn, Maryland\r\n265\r\n281\r\n298\r\n594\r\n597\r\n944\r\n965\r\n966\r\nWorthington, Maryland\r\n429\r\n\u00035Unknown prefix code (410) - Maryland\r\n"
  },
  {
    "path": "install/regions/regions.412",
    "content": "Aleppo, Pennsylvania\r\n685\r\nAliquippa, Pennsylvania\r\n375\r\n378\r\n857\r\nAmbridge, Pennsylvania\r\n251\r\n266\r\nApollo, Pennsylvania\r\n478\r\nAvella, Pennsylvania\r\n587\r\nAvonmore, Pennsylvania\r\n697\r\nBaden, Pennsylvania\r\n869\r\nBealsville, Pennsylvania\r\n769\r\nBeaver Falls, Pennsylvania\r\n843\r\n846\r\n847\r\n944\r\nBelle Vernon, Pennsylvania\r\n929\r\nBessemer, Pennsylvania\r\n667\r\nBethal Park, Pennsylvania\r\n831\r\n833\r\n835\r\n854\r\nBlack Lick, Pennsylvania\r\n248\r\nBlacktown, Pennsylvania\r\n748\r\nBlairsville, Pennsylvania\r\n459\r\nBobtown, Pennsylvania\r\n839\r\nBolivar, Pennsylvania\r\n676\r\nBrave, Pennsylvania\r\n451\r\nBridgeville, Pennsylvania\r\n221\r\n257\r\nBrownsville, Pennsylvania\r\n785\r\nBruin, Pennsylvania\r\n753\r\nBuffalo, Pennsylvania\r\n345\r\nBurgettstown, Pennsylvania\r\n947\r\nButler, Pennsylvania\r\n477\r\n282\r\n283\r\n284\r\n285\r\n287\r\n629\r\n679\r\nCalifornia, Pennsylvania\r\n938\r\nCanonsburg, Pennsylvania\r\n745\r\n746\r\n873\r\nCarmichael, Pennsylvania\r\n966\r\nCarnegie, Pennsylvania\r\n276\r\n279\r\n429\r\n494\r\n747\r\n787\r\n788\r\nCenterville, Pennsylvania\r\n757\r\nCharleroi, Pennsylvania\r\n483\r\n489\r\nChicora, Pennsylvania\r\n445\r\nClairton, Pennsylvania\r\n233\r\nClaysvilles, Pennsylvania\r\n663\r\nClymer, Pennsylvania\r\n254\r\nConnellsvilles, Pennsylvania\r\n626\r\n628\r\nConnoquenessing, Pennsylvania\r\n789\r\nCooperstown, Pennsylvania\r\n898\r\nCoraopolis, Pennsylvania\r\n262\r\n264\r\n269\r\n299\r\n472\r\n859\r\nCore, Pennsylvania\r\n878\r\nCriders Corner, Pennsylvania\r\n772\r\n776\r\n779\r\nCurtisville, Pennsylvania\r\n265\r\nDarlington, Pennsylvania\r\n827\r\nDawson, Pennsylvania\r\n529\r\nDelmont, Pennsylvania\r\n468\r\nDerry, Pennsylvania\r\n694\r\nDonora, Pennsylvania\r\n379\r\nDunbar, Pennsylvania\r\n277\r\nEast Palestine, Pennsylvania\r\n436\r\nEast Brady, Pennsylvania\r\n526\r\nEau Claire, Pennsylvania\r\n791\r\nElderton, Pennsylvania\r\n354\r\nElizabeth, Pennsylvania\r\n382\r\n384\r\nEllwood City, Pennsylvania\r\n752\r\n758\r\nEmlenton, Pennsylvania\r\n867\r\nEnon Valley, Pennsylvania\r\n336\r\nEvans City, Pennsylvania\r\n538\r\nExport, Pennsylvania\r\n325\r\n327\r\n733\r\nFairchance, Pennsylvania\r\n564\r\nFarmington, Pennsylvania\r\n239\r\n329\r\nFayette City, Pennsylvania\r\n326\r\nFinelyville, Pennsylvania\r\n348\r\n699\r\n981\r\n983\r\nFord City, Pennsylvania\r\n763\r\nFox Chapel, Pennsylvania\r\n767\r\n963\r\n967\r\nFoxburg, Pennsylvania\r\n659\r\nFredericktown, Pennsylvania\r\n377\r\nFredonia, Pennsylvania\r\n475\r\nFreeport, Pennsylvania\r\n295\r\nGibsonia, Pennsylvania\r\n443\r\n444\r\nGlenshaw, Pennsylvania\r\n486\r\n487\r\n492\r\nGlenwillard, Pennsylvania\r\n457\r\nGraysville, Pennsylvania\r\n428\r\nGreensboro, Pennsylvania\r\n943\r\nGreensburg, Pennsylvania\r\n830\r\n832\r\n834\r\n836\r\n837\r\n838\r\n950\r\nGreenville, Pennsylvania\r\n588\r\n589\r\nGrove City, Pennsylvania\r\n458\r\nHarrison City, Pennsylvania\r\n744\r\nHarrisville, Pennsylvania\r\n735\r\nHerminie, Pennsylvania\r\n446\r\nHickory, Pennsylvania\r\n356\r\nHomer City, Pennsylvania\r\n479\r\nHookstown, Pennnsylvania\r\n573\r\nImperial, Pennsylvania\r\n695\r\nIndiana, Pennsylvania\r\n349\r\n357\r\n463\r\n465\r\n541\r\nIndianhead, Pennsylvania\r\n455\r\nIrwin, Pennsylvania\r\n863\r\n864\r\nJamestown, Pennsylvania\r\n932\r\nJeanette, Pennsylvania\r\n523\r\n527\r\nJefferson, Pennsylvania\r\n883\r\nKecksburg, Pennsylvania\r\n423\r\nKittanning, Pennsylvania\r\n525\r\n543\r\n545\r\n548\r\nLatrobe, Pennsylvania\r\n532\r\n537\r\n539\r\nLeechburg, Pennsylvania\r\n842\r\n845\r\nLigonier, Pennsylvania\r\n238\r\nLowellville, Pennsylvania\r\n546\r\nMarchand, Pennsylvania\r\n286\r\nMarianna, Pennsylvania\r\n267\r\nMaridian, Pennsylvania\r\n482\r\nMarion Center, Pennsylvania\r\n397\r\nMars, Pennsylvania\r\n625\r\nMasontown, Pennsylvania\r\n583\r\nMcClellandtown, Pennsylvania\r\n737\r\nMcDonald, Pennsylvania\r\n926\r\nMcKeesport, Pennsylvania\r\n466\r\n469\r\n664\r\n672\r\n673\r\n675\r\n678\r\n751\r\n754\r\nMcMurray, Pennsylvania\r\n941\r\n942\r\nMercer, Pennsylvania\r\n662\r\nMidland, Pennsylvania\r\n643\r\nMidway, Pennsylvania\r\n796\r\nMonessen, Pennsylvania\r\n684\r\nMonongahela, Pennsylvania\r\n258\r\nMonroeville, Pennsylvania\r\n372\r\n373\r\n374\r\n856\r\n858\r\nMount Morris, Pennsylvania\r\n324\r\nMount Pleasant, Pennsylvania\r\n547\r\n696\r\nMurdocksville, Pennsylvania\r\n899\r\nNorth Washington, Pennsylvania\r\n894\r\nNew Alexandria, Pennylvania\r\n668\r\nNew Bedford, Pennsylvania\r\n964\r\nNew Castle, Pennsylvania\r\n651\r\n652\r\n654\r\n656\r\n658\r\nNew Florence, Pennsylvania\r\n235\r\nNew Freeport, Pennsylvania\r\n447\r\nNew Kensington, Pennsylvania\r\n335\r\n337\r\n339\r\nNew Salem, Pennsylvania\r\n245\r\nNew Wilmington, Pennsylvania\r\n946\r\nNixon, Pennsylvania\r\n586\r\nOakdale, Pennsylvania\r\n693\r\nOakmont, Pensylvania\r\n826\r\n828\r\nParis, Pennsylvania\r\n729\r\nParker, Pennsylvania\r\n399\r\nParkwood, Pennsylvania\r\n726\r\nPenn Hills, Pennsylvania\r\n793\r\n795\r\n798\r\nPerryopolis, Pennsylvania\r\n736\r\nPerrysville, Pennsylvania\r\n364\r\n366\r\n367\r\n369\r\nPetrolia, Pennsylvania\r\n756\r\nPittsburgh, Pennsylvania\r\n920\r\n231\r\n396\r\n574\r\n577\r\n579\r\n890\r\n973\r\n649\r\n328\r\n634\r\n635\r\n820\r\n227\r\n232\r\n234\r\n236\r\n237\r\n241\r\n242\r\n243\r\n244\r\n247\r\n255\r\n256\r\n261\r\n263\r\n268\r\n271\r\n273\r\n281\r\n288\r\n289\r\n298\r\n321\r\n322\r\n323\r\n331\r\n333\r\n338\r\n341\r\n343\r\n344\r\n351\r\n355\r\n359\r\n361\r\n362\r\n363\r\n365\r\n371\r\n381\r\n383\r\n389\r\n391\r\n392\r\n393\r\n394\r\n421\r\n422\r\n427\r\n431\r\n433\r\n434\r\n441\r\n442\r\n456\r\n461\r\n462\r\n464\r\n471\r\n476\r\n481\r\n488\r\n491\r\n496\r\n497\r\n521\r\n531\r\n551\r\n553\r\n561\r\n562\r\n563\r\n565\r\n566\r\n571\r\n572\r\n575\r\n578\r\n594\r\n621\r\n622\r\n623\r\n624\r\n633\r\n636\r\n638\r\n641\r\n642\r\n644\r\n645\r\n647\r\n648\r\n661\r\n665\r\n681\r\n682\r\n683\r\n687\r\n688\r\n692\r\n721\r\n731\r\n734\r\n761\r\n762\r\n765\r\n766\r\n771\r\n777\r\n778\r\n781\r\n782\r\n784\r\n821\r\n822\r\n841\r\n848\r\n855\r\n881\r\n882\r\n884\r\n885\r\n889\r\n892\r\n921\r\n922\r\n923\r\n928\r\n931\r\n936\r\n937\r\n939\r\n961\r\nPlain Grove, Pennsylvania\r\n530\r\nPleasant Hills, Pennsylvania\r\n653\r\n655\r\nPoint Marion, Pennsylvania\r\n725\r\nPortersville, Pennsylvania\r\n368\r\nPrinceton, Pennsylvania\r\n924\r\nProspect, Pennsylvania\r\n865\r\nRepublic, Pennsylvania\r\n246\r\nRices Landing, Pennsylvania\r\n592\r\nRochester, Pennsylvania\r\n495\r\n728\r\n773\r\n774\r\n775\r\nRogersville, Pennsylvania\r\n499\r\nRural Valley, Pennsylvania\r\n783\r\nSaltsburg, Pennsylvania\r\n639\r\nSandy Lake, Pennsylvania\r\n376\r\nSarver, Pennsylvania\r\n353\r\nSaxonburgh, Pennsylvania\r\n352\r\nScenery Hill, Pennsylvania\r\n945\r\nScottdale, Pennsylvania\r\n887\r\nSewickley, Pennsylvania\r\n741\r\n749\r\nSharon, Pennsylvania\r\n342\r\n346\r\n347\r\nSharpsville, Pennsylvania\r\n866\r\n962\r\nSheackleyville, Pennsylvania\r\n253\r\nSlippery Rock, Pennsylvania\r\n738\r\n794\r\nSmithfield, Pennsylvania\r\n569\r\nSmiths Ferry, Pennsylvania\r\n764\r\nSmock, Pennsylvania\r\n677\r\nSpraggs, Pennsylvania\r\n435\r\nSpringdale, Pennsylvania\r\n274\r\nStahlstown, Pennslvania\r\n593\r\nTarentum, Pennsylvania\r\n224\r\n226\r\nTaylorstown, Pennsylvania\r\n948\r\nTempleton, Pennsylvania\r\n868\r\nTransfer, Pennsylvania\r\n646\r\nTurtle Creek, Pennsylvania\r\n823\r\n824\r\n825\r\n829\r\nUniontown , Pennsylvania\r\n440\r\n581\r\n430\r\n437\r\n438\r\n439\r\n557\r\n582\r\nVandergrift, Pennsylvania\r\n567\r\n568\r\n727\r\nVolant, Pennsylvania\r\n533\r\nWest Alexander, Pennsylvania\r\n484\r\nWest Middlesex, Pennsylvania\r\n528\r\nWampum, Pennsylvania\r\n535\r\nWashington, Pennsylvania\r\n222\r\n223\r\n225\r\n228\r\n229\r\nWaynesburg, Pennsylvania\r\n627\r\n852\r\nWest Newton, Pennsylvania\r\n872\r\nWest Sunbury, Pennsylvania\r\n637\r\nWestford, Pennsylvania\r\n927\r\nWexford, Pennsylvania\r\n934\r\n935\r\nWorthington, Pennsylvania\r\n297\r\nYoungwood, Pennsylvania\r\n925\r\nYukon, Pennsylvania\r\n722\r\nZelienople, Pennsylvania\r\n452\r\n\u00035Unknown prefix code (412) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/regions.413",
    "content": "Adams, Massachusetts\r\n743\r\nAgawam, Massachusetts\r\n786\r\n789\r\nAmherst, Massachusetts\r\n253\r\n256\r\n259\r\n542\r\n545\r\n546\r\n548\r\n549\r\nAshfield, Massachusetts\r\n628\r\nBecket, Massachusetts\r\n623\r\nBelchertown, Massachusetts\r\n323\r\nBernardston, Massachusetts\r\n648\r\nBlandford, Massachusetts\r\n848\r\nBrimfield, Massachusetts\r\n245\r\nCharlemont, Massachusetts\r\n339\r\nChester, Massachusetts\r\n354\r\nChesterfield, Massachusetts\r\n296\r\nChicopee, Massachusetts\r\n557\r\n592\r\n593\r\n594\r\n598\r\nColrain, Massachusetts\r\n624\r\nConway, Massachusetts\r\n369\r\nCummington, Massachusetts\r\n634\r\nDalton, Massachusetts\r\n684\r\nEasthampton, Massachusetts\r\n527\r\n529\r\nEast Longmeadow, Massachusetts\r\n525\r\nGilbertville, Massachusetts\r\n477\r\nGranby, Massachusetts\r\n467\r\nGranville, Massachusetts\r\n357\r\nGreat Barrington, Massachusetts\r\n528\r\nGreenfield, Massachusetts\r\n772\r\n773\r\n774\r\nHatfield, Massachusetts\r\n247\r\nHancock Center, Massachusetts\r\n738\r\nHampden, Massachusetts\r\n566\r\nHeath, Massachusetts\r\n337\r\nHindsdale, Massachusetts\r\n655\r\nHolyoke, Massachusetts\r\n530\r\n531\r\n532\r\n533\r\n534\r\n535\r\n536\r\n538\r\n539\r\nHousationic, Massachusetts\r\n274\r\nHuntington, Massachusetts\r\n667\r\nIndian Orchard, Massachusetts\r\n543\r\nLee, Massachusetts\r\n243\r\nLenox, Massachusetts\r\n637\r\nLongmeadow, Massachusetts\r\n567\r\nLudlow, Massachusetts\r\n547\r\n583\r\n589\r\nMillers Falls, Massachusetts\r\n659\r\nMonson, Massachusetts\r\n267\r\nMonroe Bridge, Massachusetts\r\n424\r\nMontague, Massachusetts\r\n367\r\nNorthfield, Massachusetts\r\n498\r\nNorthhampton, Massachusetts\r\n582\r\n584\r\n585\r\n586\r\nNorth Adams, Massachusetts\r\n662\r\n663\r\n664\r\nOtis, Massachusetts\r\n269\r\nPalmer, Massachusetts\r\n283\r\n284\r\n289\r\nPittsfield, Massachusetts\r\n442\r\n443\r\n445\r\n446\r\n447\r\n448\r\n494\r\n499\r\nRichmond, Massachusetts\r\n698\r\nRussell, Massachusetts\r\n862\r\nSandisfield, Massachusetts\r\n258\r\nSheffield, Massachusetts\r\n229\r\nShelburne Falls, Massachusetts\r\n625\r\nSouthwick, Massachusetts\r\n569\r\nSouth Deerfield, Massachusetts\r\n665\r\nSpringfield, Massachusetts\r\n263\r\n292\r\n293\r\n295\r\n730\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n739\r\n744\r\n746\r\n747\r\n748\r\n781\r\n782\r\n783\r\n784\r\n785\r\n787\r\n788\r\n796\r\n955\r\nStockbridge, Massachusetts\r\n298\r\nTurners Falls, Massachusetts\r\n863\r\nWare, Massachusetts\r\n967\r\nWarren, Massachusetts\r\n436\r\nWestfield, Massachusetts\r\n562\r\n568\r\n572\r\nWest Stockbridge, Massachusetts\r\n232\r\nWilbraham, Massachusetts\r\n596\r\n599\r\nWilliamsburg, Massachusetts\r\n268\r\nWilliamstown, Massachusetts\r\n458\r\n597\r\nWorthington, Massachusetts\r\n238\r\n\u00035Unknown prefix code (413) - Massachusetts\r\n"
  },
  {
    "path": "install/regions/regions.414",
    "content": "Abrams, Wisconsin\r\n826\r\nAlgoma, Wisconsin\r\n487\r\nAllenton, Wisconsin\r\n629\r\nAppleton, Wisconsin\r\n234\r\n428\r\n572\r\n585\r\n586\r\n730\r\n731\r\n733\r\n734\r\n735\r\n738\r\n739\r\n749\r\n757\r\n830\r\n831\r\n832\r\n841\r\n858\r\n954\r\nBaileys Harbor, Wisconsin\r\n839\r\nBeaver Dam, Wisconsin\r\n885\r\n887\r\nBelgium, Wisconsin\r\n285\r\nBergen, Wisconsin\r\n296\r\nBerlin, Wisconsin\r\n361\r\nBig Bend, Wisconsin\r\n662\r\nBlack Creek, Wisconsin\r\n984\r\nBohners Lake, Wisconsin\r\n539\r\nBrandon, Wisconsin\r\n346\r\nBrillion, Wisconsin\r\n756\r\nBristol, Wisconsin\r\n857\r\nBrussels, Wisconsin\r\n825\r\nBurlington, Wisconsin\r\n763\r\n767\r\nBurnett, Wisconsin\r\n689\r\nCaledonia, Wisconsin\r\n835\r\nCambria, Wisconsin\r\n348\r\nCampbels' Point, Wisconsin\r\n533\r\nCascade, Wisconsin\r\n528\r\nCasco, Wisconsin\r\n837\r\nCedarburg, Wisconsin\r\n375\r\n377\r\nCedargrove, Wisconsin\r\n668\r\nChilton, Wisconsin\r\n849\r\nCleveland, Wisconsin\r\n693\r\nClyman, Wisconsin\r\n696\r\nColeman, Wisconsin\r\n897\r\nCollins, Wisconsin\r\n772\r\nColumbus, Wisconsin\r\n623\r\nDarien, Wisconsin\r\n724\r\nDe Pere, Wisconsin\r\n336\r\n337\r\n339\r\nDelafield, Wisconsin\r\n646\r\nDelavan, Wisconsin\r\n728\r\nDenmark, Wisconsin\r\n863\r\nDousman, Wisconsin\r\n965\r\nEagle, Wisconsin\r\n594\r\nEast Troy, Wisconsin\r\n642\r\nEden, Wisconsin\r\n477\r\nEgg Harbor, Wisconsin\r\n868\r\nElkhart Lake, Wisconsin\r\n876\r\nElkhorn, Wisconsin\r\n723\r\n741\r\n742\r\nFall River, Wisconsin\r\n484\r\nFond Dulac, Wisconsin\r\n921\r\n922\r\n923\r\n924\r\n929\r\nForestville, Wisconsin\r\n856\r\nFox Lake, Wisconsin\r\n928\r\nFremont, Wisconsin\r\n446\r\nFort Atkinson, Wisconsin\r\n563\r\n568\r\nGenesee, Wisconsin\r\n968\r\nGenoa City, Wisconsin\r\n279\r\nGillett, Wisconsin\r\n855\r\nGreen Bay, Wisconsin\r\n366\r\n373\r\n391\r\n399\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n448\r\n455\r\n465\r\n468\r\n469\r\n492\r\n493\r\n494\r\n496\r\n497\r\n498\r\n499\r\n556\r\n559\r\n592\r\n621\r\n655\r\n664\r\n665\r\n952\r\n988\r\n995\r\nGreen Lake, Wisconsin\r\n294\r\nGreenbush, Wisconsin\r\n526\r\nGreenfield, Wisconsin\r\n281\r\nHartford, Wisconsin\r\n670\r\n673\r\nHartland, Wisconsin\r\n369\r\n367\r\nHilbert, Wisconsin\r\n853\r\nHoricon, Wisconsin\r\n485\r\nHortonvl, Wisconsin\r\n779\r\nHowardsgrove, Wisconsin\r\n565\r\nHubertus, Wisconsin\r\n628\r\nHustisford, Wisconsin\r\n349\r\nJackson, Wisconsin\r\n677\r\nJackson Point, Wisconsin\r\n823\r\nJefferson, Wisconsin\r\n674\r\nJohnsburg, Wisconsin\r\n795\r\nJohnson Creek, Wisconsin\r\n699\r\nJuneau, Wisconsin\r\n386\r\nKaukauna, Wisconsin\r\n759\r\n766\r\nKenosha, Wisconsin\r\n551\r\n597\r\n652\r\n653\r\n654\r\n656\r\n657\r\n658\r\n694\r\n697\r\n942\r\n947\r\nKewaskum, Wisconsin\r\n626\r\nKewaunee, Wisconsin\r\n388\r\nKiel, Wisconsin\r\n894\r\nKingston, Wisconsin\r\n394\r\nKrakow, Wisconsin\r\n899\r\nLake Mills, Wisconsin\r\n648\r\nLake Geneva, Wisconsin\r\n248\r\n249\r\nLarsen, Wisconsin\r\n836\r\nLebanon, Wisconsin\r\n925\r\nLena, Wisconsin\r\n829\r\nLomira, Wisconsin\r\n269\r\nLittle Chute, Wisconsin\r\n687\r\n788\r\nLittle Strgn, Wisconsin\r\n824\r\nLuxemburg, Wisconsin\r\n845\r\nManawa, Wisconsin\r\n596\r\nManitowoc, Wisconsin\r\n682\r\n683\r\n684\r\nMapleton, Wisconsin\r\n474\r\nMarkesan, Wisconsin\r\n398\r\nMayville, Wisconsin\r\n387\r\nMenomne Falls, Wisconsin\r\n250\r\n251\r\n252\r\n253\r\n255\r\nMerton, Wisconsin\r\n538\r\nMillcenter, Wisconsin\r\n865\r\nMishicot, Wisconsin\r\n755\r\nMt Calvary, Wisconsin\r\n753\r\nMukwonago, Wisconsin\r\n363\r\nMuskego, Wisconsin\r\n679\r\nMilwaukee, Wisconsin\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n237\r\n254\r\n256\r\n257\r\n258\r\n259\r\n263\r\n264\r\n265\r\n266\r\n271\r\n272\r\n273\r\n274\r\n276\r\n277\r\n278\r\n282\r\n283\r\n286\r\n287\r\n288\r\n289\r\n291\r\n297\r\n298\r\n299\r\n321\r\n323\r\n325\r\n327\r\n328\r\n332\r\n333\r\n341\r\n342\r\n343\r\n344\r\n345\r\n347\r\n372\r\n374\r\n379\r\n382\r\n383\r\n384\r\n385\r\n389\r\n393\r\n411\r\n438\r\n442\r\n444\r\n445\r\n447\r\n449\r\n453\r\n454\r\n461\r\n462\r\n463\r\n464\r\n466\r\n471\r\n475\r\n476\r\n481\r\n482\r\n483\r\n486\r\n491\r\n527\r\n535\r\n536\r\n541\r\n543\r\n545\r\n546\r\n555\r\n557\r\n558\r\n562\r\n575\r\n579\r\n581\r\n584\r\n588\r\n640\r\n643\r\n645\r\n647\r\n649\r\n663\r\n669\r\n671\r\n672\r\n678\r\n744\r\n747\r\n765\r\n769\r\n771\r\n774\r\n777\r\n778\r\n791\r\n798\r\n799\r\n838\r\n844\r\n848\r\n861\r\n871\r\n873\r\n874\r\n881\r\n931\r\n933\r\n935\r\n936\r\n937\r\n939\r\n941\r\n945\r\n946\r\n948\r\n949\r\n955\r\n961\r\n962\r\n963\r\n964\r\n985\r\n989\r\n322\r\n378\r\n573\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n789\r\n792\r\n796\r\n797\r\n821\r\n827\r\n879\r\n421\r\n422\r\n423\r\n425\r\n427\r\n529\r\n247\r\n351\r\n352\r\n353\r\n354\r\n355\r\n357\r\n358\r\n359\r\n362\r\n365\r\n577\r\n571\r\n762\r\n764\r\n768\r\nNeenah, Wisconsin\r\n721\r\n722\r\n725\r\n727\r\n729\r\n751\r\nNeosho, Wisconsin\r\n625\r\nNeshkoro, Wisconsin\r\n293\r\nNew London, Wisconsin\r\n982\r\nNewburg, Wisconsin\r\n675\r\nNewfranken, Wisconsin\r\n866\r\nNewholsten, Wisconsin\r\n898\r\nNewton, Wisconsin\r\n726\r\nNewtonburg, Wisconsin\r\n758\r\nNichols, Wisconsin\r\n525\r\nNorth Antioch, Wisconsin\r\n396\r\nNorth Prairie, Wisconsin\r\n392\r\nNorth Lake, Wisconsin\r\n966\r\nOak Creek, Wisconsin\r\n761\r\nOakfield, Wisconsin\r\n583\r\nOconomowoc, Wisconsin\r\n567\r\n569\r\nOconto, Wisconsin\r\n834\r\nOconto Falls, Wisconsin\r\n846\r\nOgdensburg, Wisconsin\r\n244\r\nOmro, Wisconsin\r\n685\r\nOneida, Wisconsin\r\n869\r\nOostburg, Wisconsin\r\n564\r\nOshkosh, Wisconsin\r\n231\r\n232\r\n233\r\n235\r\n236\r\n424\r\n426\r\nPalmyra, Wisconsin\r\n495\r\nParkside, Wisconsin\r\n552\r\n553\r\n595\r\nPewaukee, Wisconsin\r\n691\r\n695\r\nPickett, Wisconsin\r\n589\r\nPlymouth, Wisconsin\r\n892\r\n893\r\nPoy Sippi, Wisconsin\r\n987\r\nPrinceton, Wisconsin\r\n295\r\nPoint Washington, Wisconsin\r\n268\r\n284\r\nPulaski, Wisconsin\r\n822\r\nRacine, Wisconsin\r\n554\r\n598\r\n631\r\n632\r\n633\r\n634\r\n635\r\n636\r\n637\r\n638\r\n639\r\n681\r\n884\r\n886\r\nRandolph, Wisconsin\r\n326\r\nRandomlake, Wisconsin\r\n994\r\nReadfield, Wisconsin\r\n667\r\nRedgranite, Wisconsin\r\n566\r\nReedsville, Wisconsin\r\n754\r\nReeseville, Wisconsin\r\n927\r\nRio, Wisconsin\r\n992\r\nRipon, Wisconsin\r\n745\r\n748\r\nRosendale, Wisconsin\r\n872\r\nSalem, Wisconsin\r\n843\r\nSeymour, Wisconsin\r\n833\r\nSharon, Wisconsin\r\n736\r\nSheboygan, Wisconsin\r\n576\r\n451\r\n452\r\n457\r\n458\r\n459\r\nSheboygan Fall, Wisconsin\r\n467\r\nShiocton, Wisconsin\r\n986\r\nSilverlake, Wisconsin\r\n889\r\nSister Bay, Wisconsin\r\n854\r\nSlinger, Wisconsin\r\n644\r\nSomers, Wisconsin\r\n859\r\nSt Cloud, Wisconsin\r\n999\r\nSt Nazianz, Wisconsin\r\n773\r\nStockbdg, Wisconsin\r\n439\r\nSturgen Bay, Wisconsin\r\n743\r\n746\r\nSullivan, Wisconsin\r\n593\r\nSuring, Wisconsin\r\n842\r\nSussex, Wisconsin\r\n246\r\nTheresa, Wisconsin\r\n488\r\nThiensvl, Wisconsin\r\n238\r\n241\r\n242\r\n243\r\nTischmills, Wisconsin\r\n776\r\nTrevor, Wisconsin\r\n862\r\nTwin Lakes, Wisconsin\r\n877\r\nTwo Rivers, Wisconsin\r\n793\r\n794\r\nUniongrove, Wisconsin\r\n878\r\nValders, Wisconsin\r\n775\r\nVan Dyne, Wisconsin\r\n688\r\nWalworth, Wisconsin\r\n275\r\nWashington Island, Wisconsin\r\n847\r\nWaterford, Wisconsin\r\n534\r\nWaterloo, Wisconsin\r\n478\r\nWatertown, Wisconsin\r\n261\r\n262\r\nWaubeka, Wisconsin\r\n692\r\nWaukesha, Wisconsin\r\n521\r\n523\r\n524\r\n542\r\n544\r\n547\r\n548\r\n549\r\n574\r\n896\r\nWaupun, Wisconsin\r\n324\r\nWautoma, Wisconsin\r\n787\r\nWayside, Wisconsin\r\n864\r\nWest Bend, Wisconsin\r\n334\r\n335\r\n338\r\nWeyauwega, Wisconsin\r\n867\r\nWheatland, Wisconsin\r\n537\r\nWhitelaw, Wisconsin\r\n732\r\nWhitewater, Wisconsin\r\n472\r\n473\r\nWild Rose, Wisconsin\r\n622\r\nWilliamsby, Wisconsin\r\n245\r\nWind Lake, Wisconsin\r\n895\r\nWinneconne, Wisconsin\r\n582\r\nWrightston, Wisconsin\r\n532\r\n\u00035Unknown prefix code (414) - Wisconsin\r\n"
  },
  {
    "path": "install/regions/regions.415",
    "content": "Berkeley\u00031/\u00032San Fran.\u00031/\u00032Mt. View, California\r\n415\r\n510\r\n335\r\n336\r\n390\r\n404\r\n604\r\n691\r\n694\r\n903\r\n940\r\n960\r\n961\r\n962\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\n988\r\nBelvedere, Cailfornia\r\n435\r\n789\r\nCorte Madera, California\r\n924\r\n927\r\nFoster City, California\r\n349\r\nLos Altos, California\r\n917\r\n941\r\n948\r\n949\r\nMillbrae, California\r\n259\r\n692\r\n697\r\nMill Valley, California\r\n381\r\n383\r\n388\r\n389\r\nMoss Beach, California\r\n728\r\nPacifica, California\r\n355\r\n359\r\n738\r\nSan Francisco, California\r\n201\r\n202\r\n206\r\n207\r\n219\r\n221\r\n227\r\n239\r\n241\r\n243\r\n252\r\n255\r\n267\r\n270\r\n274\r\n280\r\n281\r\n282\r\n285\r\n288\r\n291\r\n292\r\n296\r\n301\r\n303\r\n330\r\n333\r\n334\r\n337\r\n338\r\n346\r\n353\r\n362\r\n379\r\n386\r\n387\r\n391\r\n393\r\n394\r\n395\r\n396\r\n397\r\n398\r\n399\r\n403\r\n406\r\n421\r\n431\r\n433\r\n434\r\n441\r\n442\r\n445\r\n467\r\n468\r\n469\r\n474\r\n476\r\n477\r\n478\r\n495\r\n502\r\n512\r\n520\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n550\r\n552\r\n553\r\n554\r\n556\r\n557\r\n558\r\n560\r\n561\r\n563\r\n564\r\n565\r\n566\r\n567\r\n575\r\n576\r\n584\r\n585\r\n586\r\n587\r\n597\r\n607\r\n616\r\n621\r\n622\r\n624\r\n626\r\n640\r\n641\r\n647\r\n648\r\n660\r\n661\r\n664\r\n665\r\n666\r\n668\r\n673\r\n677\r\n679\r\n681\r\n693\r\n695\r\n698\r\n701\r\n703\r\n705\r\n708\r\n715\r\n719\r\n731\r\n739\r\n744\r\n749\r\n750\r\n751\r\n752\r\n753\r\n755\r\n756\r\n759\r\n761\r\n764\r\n765\r\n768\r\n771\r\n772\r\n773\r\n774\r\n775\r\n776\r\n777\r\n781\r\n788\r\n804\r\n807\r\n809\r\n821\r\n822\r\n824\r\n826\r\n861\r\n863\r\n864\r\n882\r\n885\r\n894\r\n896\r\n904\r\n905\r\n907\r\n912\r\n915\r\n921\r\n922\r\n923\r\n928\r\n929\r\n931\r\n951\r\n953\r\n954\r\n955\r\n956\r\n957\r\n972\r\n973\r\n974\r\n978\r\n979\r\n981\r\n982\r\n983\r\n984\r\n985\r\n986\r\n989\r\n991\r\n992\r\n993\r\n994\r\n995\r\n997\r\n998\r\nSan Mateo, California\r\n312\r\n340\r\n341\r\n342\r\n343\r\n344\r\n345\r\n347\r\n348\r\n371\r\n375\r\n377\r\n378\r\n513\r\n570\r\n571\r\n572\r\n573\r\n574\r\n578\r\n579\r\n696\r\nSan Rafael, California\r\n257\r\n258\r\n453\r\n454\r\n456\r\n457\r\n459\r\n461\r\n472\r\n479\r\n485\r\n488\r\n491\r\n492\r\n499\r\n507\r\n721\r\n925\r\nSausalito, California\r\n289\r\n331\r\n332\r\n754\r\nSouth San Francisco\u00031/\u00032San Bruno, California\r\n225\r\n244\r\n266\r\n583\r\n588\r\n589\r\n615\r\n737\r\n742\r\n871\r\n872\r\n873\r\n875\r\n876\r\n877\r\n878\r\n952\r\n\u00035Unknown prefix code (415) - California\r\n"
  },
  {
    "path": "install/regions/regions.416",
    "content": "Ajax, Ontario, Canada\r\n702\r\nAjax Pickering, Ontario, Canada\r\n427\r\n428\r\n619\r\n683\r\n686\r\n706\r\nAncaster, Ontario, Canada\r\n304\r\n648\r\nAurora, Ontario, Canada\r\n713\r\n727\r\n841\r\nBeamsville, Ontario, Canada\r\n563\r\nBeeton, Ontario, Canada\r\n729\r\nBethesda, Ontario, Canada\r\n888\r\nBinbrook, Ontario, Canada\r\n692\r\nBl 976 Svc, Ontario, Canada\r\n976\r\nBlackstock, Ontario, Canada\r\n986\r\nBolton, Ontario, Canada\r\n857\r\n951\r\nBowmanville, Ontario, Canada\r\n623\r\n697\r\nBradford, Ontario, Canada\r\n775\r\nBrampton, Ontario, Canada\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n790\r\n791\r\n792\r\n793\r\n796\r\n799\r\n840\r\n846\r\n874\r\nBrooklin, Ontario, Canada\r\n655\r\nBurlington, Ontario, Canada\r\n319\r\n332\r\n333\r\n335\r\n336\r\n632\r\n634\r\n637\r\n639\r\n681\r\nCaledonia, Ontario, Canada\r\n584\r\n765\r\nCampbellville, Ontario, Canada\r\n854\r\nCastlemore, Ontario, Canada\r\n794\r\nCastleton, Ontario, Canada\r\n344\r\nCayuga, Ontario, Canada\r\n772\r\nCentennial College, Toronto\r\n439\r\nClaremont, Ontario, Canada\r\n649\r\nClarkson, Ontario, Canada\r\n403\r\n822\r\n823\r\n855\r\nCobourg, Ontario, Canada\r\n372\r\n373\r\nColborne, Ontario, Canada\r\n355\r\nCold Springs, Ontario, Canada\r\n342\r\nCooksville, Ontario, Canada\r\n206\r\n238\r\n270\r\n272\r\n273\r\n275\r\n276\r\n277\r\n279\r\n507\r\n566\r\n568\r\n602\r\n615\r\n624\r\n625\r\n629\r\n803\r\n848\r\n890\r\n896\r\n897\r\n949\r\nDundas, Ontario, Canada\r\n627\r\n628\r\nDunnville, Ontario, Canada\r\n774\r\nFisherville, Ontario, Canada\r\n779\r\nFort Erie, Ontario, Canada\r\n871\r\n994\r\nFreelton, Ontario, Canada\r\n659\r\nGardenhill, Ontario, Canada\r\n797\r\nGeorgetown, Ontario, Canada\r\n873\r\n877\r\nGormley, Ontario, Canada\r\n887\r\nGrafton, Ontario, Canada\r\n349\r\nGrimsby, Ontario, Canada\r\n945\r\nHagersville, Ontario, Canada\r\n768\r\nHamilton, Ontario, Canada\r\n308\r\n312\r\n317\r\n318\r\n383\r\n385\r\n387\r\n388\r\n389\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n529\r\n541\r\n544\r\n545\r\n546\r\n547\r\n548\r\n549\r\n560\r\n561\r\n570\r\n572\r\n573\r\n574\r\n575\r\n577\r\n578\r\n645\r\nHampton, Ontario, Canada\r\n263\r\nKeswick, Ontario, Canada\r\n476\r\n989\r\nKing City, Ontario, Canada\r\n833\r\nKleinburg, Ontario, Canada\r\n893\r\nMalton, Ontario, Canada\r\n405\r\n564\r\n612\r\n670\r\n671\r\n672\r\n673\r\n676\r\n677\r\n678\r\n795\r\nMaple, Ontario, Canada\r\n832\r\nMarkham, Ontario, Canada\r\n294\r\n471\r\n472\r\nMilton, Ontario, Canada\r\n875\r\n876\r\n878\r\nMississauga, Ontario, Canada\r\n820\r\nMount Hope, Ontario, Canada\r\n679\r\nMount Albert, Ontario, Canada\r\n473\r\nNewcastle, Ontario, Canada\r\n987\r\nNewmarket, Ontario, Canada\r\n830\r\n836\r\n853\r\n895\r\n898\r\nNewtonville, Ontario, Canada\r\n786\r\nNiagara Falls, Ontario, Canada\r\n356\r\n262\r\n295\r\n354\r\n357\r\n358\r\n371\r\n374\r\nNiagara Lake, Ontario, Canada\r\n468\r\nNobleton, Ontario, Canada\r\n859\r\nOak Ridges, Ontario, Canada\r\n773\r\nOakville, Ontario, Canada\r\n257\r\n338\r\n815\r\n825\r\n827\r\n829\r\n842\r\n844\r\n845\r\n847\r\n849\r\nOrono, Ontario, Canada\r\n983\r\nOshawa, Ontario, Canada\r\n404\r\n432\r\n433\r\n434\r\n435\r\n436\r\n571\r\n576\r\n579\r\n644\r\n721\r\n723\r\n725\r\n728\r\nPalgrave, Ontario, Canada\r\n880\r\nPelham, Ontario, Canada\r\n892\r\nPort Hope, Ontario, Canada\r\n885\r\nPort Perry, Ontario, Canada\r\n985\r\nPort Credit, Ontario, Canada\r\n271\r\n274\r\n278\r\n891\r\nPort Robinson, Ontario, Canada\r\n384\r\nPort Colborne, Ontario, Canada\r\n834\r\n835\r\nQueensvale, Ontario, Canada\r\n478\r\nRichmond Hill, Ontario, Canada\r\n508\r\n737\r\n770\r\n883\r\n884\r\nRidgeway, Ontario, Canada\r\n894\r\nRoseneath, Ontario, Canada\r\n352\r\nScarborough, Toronto, Canada\r\n208\r\n267\r\n285\r\nSchomberg, Ontario, Canada\r\n939\r\nSelkirk, Ontario, Canada\r\n776\r\nSnelgrove, Ontario, Canada\r\n843\r\nSouthpick, Ontario, Canada\r\n420\r\n831\r\n837\r\n839\r\nSaint Catherins, Ontario, Canada\r\n227\r\n641\r\n646\r\n680\r\n682\r\n684\r\n685\r\n687\r\n688\r\n934\r\n935\r\n937\r\n938\r\n984\r\n988\r\nStevensville, Ontario, Canada\r\n382\r\nStoney Creek, Ontario, Canada\r\n662\r\n664\r\nStouffville, Ontario, Canada\r\n640\r\n642\r\nStreetsvale, Ontario, Canada\r\n542\r\n567\r\n569\r\n607\r\n819\r\n821\r\n824\r\n826\r\n828\r\n858\r\nSutton, Ontario, Canada\r\n722\r\nThornhill, Ontario, Canada\r\n660\r\n669\r\n731\r\n738\r\n764\r\n771\r\n879\r\n881\r\n882\r\n886\r\n889\r\nToronto, Ontario, Canada\r\n200\r\n203\r\n204\r\n205\r\n207\r\n210\r\n213\r\n214\r\n215\r\n217\r\n218\r\n219\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n258\r\n259\r\n260\r\n261\r\n264\r\n265\r\n266\r\n269\r\n281\r\n282\r\n283\r\n284\r\n286\r\n287\r\n288\r\n289\r\n290\r\n291\r\n292\r\n293\r\n296\r\n297\r\n298\r\n299\r\n307\r\n314\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n330\r\n331\r\n334\r\n337\r\n339\r\n340\r\n341\r\n343\r\n345\r\n346\r\n347\r\n348\r\n350\r\n351\r\n353\r\n359\r\n360\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n367\r\n368\r\n369\r\n370\r\n375\r\n376\r\n377\r\n378\r\n379\r\n381\r\n390\r\n391\r\n392\r\n393\r\n394\r\n395\r\n396\r\n397\r\n399\r\n401\r\n402\r\n406\r\n407\r\n408\r\n409\r\n410\r\n412\r\n413\r\n417\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n429\r\n431\r\n438\r\n440\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n460\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n467\r\n469\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n490\r\n491\r\n492\r\n493\r\n494\r\n495\r\n496\r\n497\r\n498\r\n499\r\n501\r\n502\r\n503\r\n504\r\n505\r\n506\r\n509\r\n512\r\n515\r\n516\r\n517\r\n518\r\n520\r\n530\r\n531\r\n532\r\n533\r\n534\r\n535\r\n536\r\n539\r\n540\r\n543\r\n565\r\n580\r\n581\r\n582\r\n583\r\n585\r\n586\r\n587\r\n588\r\n589\r\n590\r\n591\r\n592\r\n593\r\n594\r\n595\r\n596\r\n597\r\n598\r\n599\r\n600\r\n601\r\n603\r\n604\r\n605\r\n606\r\n608\r\n609\r\n614\r\n616\r\n617\r\n618\r\n620\r\n621\r\n622\r\n626\r\n630\r\n631\r\n633\r\n635\r\n636\r\n638\r\n650\r\n651\r\n652\r\n653\r\n654\r\n656\r\n657\r\n658\r\n661\r\n663\r\n665\r\n667\r\n674\r\n675\r\n690\r\n691\r\n693\r\n694\r\n695\r\n696\r\n699\r\n720\r\n724\r\n726\r\n730\r\n733\r\n736\r\n739\r\n740\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n750\r\n751\r\n752\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n760\r\n761\r\n762\r\n763\r\n766\r\n767\r\n769\r\n777\r\n778\r\n781\r\n782\r\n783\r\n784\r\n785\r\n787\r\n789\r\n798\r\n801\r\n812\r\n813\r\n860\r\n861\r\n862\r\n863\r\n864\r\n865\r\n866\r\n867\r\n868\r\n869\r\n870\r\n872\r\n920\r\n921\r\n922\r\n923\r\n924\r\n925\r\n926\r\n927\r\n928\r\n929\r\n930\r\n931\r\n932\r\n933\r\n941\r\n943\r\n944\r\n947\r\n948\r\n954\r\n956\r\n960\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\n971\r\n972\r\n973\r\n974\r\n975\r\n977\r\n978\r\n979\r\n980\r\n981\r\n982\r\n398\r\n416\r\n510\r\n537\r\n538\r\n698\r\nTottenham, Ontario, Canada\r\n936\r\nUnionville, Ontario, Canada\r\n415\r\n470\r\n474\r\n475\r\n477\r\n479\r\n513\r\n647\r\n940\r\n946\r\nUxbridge, Ontario, Canada\r\n852\r\nVictoria, Ontario, Canada\r\n838\r\nVineland, Ontario, Canada\r\n562\r\nWainfleet, Ontario, Canada\r\n899\r\nWaterdown, Ontario, Canada\r\n689\r\nWelcome, Ontario, Canada\r\n753\r\nWelland, Ontario, Canada\r\n714\r\n732\r\n734\r\n735\r\n788\r\nWelland Point, Ontario, Canada\r\n386\r\nWest Lincoln, Ontario, Canada\r\n957\r\nWhitby, Ontario, Canada\r\n430\r\n666\r\n668\r\nWinona, Ontario, Canada\r\n643\r\nWoodbridge, Ontario, Canada\r\n850\r\n851\r\n856\r\n\u00035Unknown prefix code (416) - Ontario, Canada\r\n"
  },
  {
    "path": "install/regions/regions.417",
    "content": "Aldrich, Missouri\r\n694\r\nAlton, Missouri\r\n778\r\nAnderson, Missouri\r\n845\r\nArcola, Missouri\r\n424\r\nAsbury, Missouri\r\n642\r\nAsh Grove, Missouri\r\n672\r\nAurora, Missouri\r\n678\r\nAva, Missouri\r\n683\r\nAvilla, Missouri\r\n246\r\nBillings, Missouri\r\n695\r\nBillingsem, Missouri\r\n744\r\nBlue Eye, Missouri\r\n779\r\nBolivar, Missouri\r\n326\r\n777\r\nBradleyville, Missouri\r\n796\r\nBranson, Missouri\r\n331\r\n334\r\n335\r\n336\r\n337\r\n338\r\nBronaugh, Missouri\r\n922\r\nBuffalo, Missouri\r\n345\r\nCabool, Missouri\r\n962\r\nCape Fair, Missouri\r\n538\r\nCarl Junction, Missouri\r\n649\r\nCarthage, Missouri\r\n358\r\n359\r\nCassville, Missouri\r\n847\r\nCaulfield, Missouri\r\n284\r\nCedar Creek, Missouri\r\n794\r\nClever, Missouri\r\n583\r\n743\r\nCollins, Missouri\r\n275\r\nConway, Missouri\r\n589\r\nCrane, Missouri\r\n723\r\nCross Timbers, Missouri\r\n998\r\nDadeville, Missouri\r\n995\r\nDeerfield, Missouri\r\n966\r\nDiamond, Missouri\r\n325\r\nDora, Missouri\r\n261\r\nEast Arcadia, Missouri\r\n639\r\nEast Fort Scott, Missouri\r\n228\r\nEast Mulberry, Missouri\r\n769\r\nEldord Springs, Missouri\r\n876\r\nEldridge, Missouri\r\n426\r\nElkland, Missouri\r\n329\r\nEast Pittsburg, Missouri\r\n238\r\nEverton, Missouri\r\n535\r\nExeter, Missouri\r\n835\r\nFair Grove, Missouri\r\n759\r\nFair Play, Missouri\r\n654\r\nFairview, Missouri\r\n632\r\nFordland, Missouri\r\n738\r\nForsyth, Missouri\r\n546\r\nGainesville, Missouri\r\n679\r\nGalena, Missouri\r\n357\r\nGolden City, Missouri\r\n537\r\nGoodman, Missouri\r\n364\r\nGranby, Missouri\r\n472\r\nGreenfield, Missouri\r\n637\r\nGrove Spring, Missouri\r\n462\r\nHalf Way, Missouri\r\n445\r\nHalltown, Missouri\r\n749\r\nHartville, Missouri\r\n741\r\nHermitage, Missouri\r\n745\r\nHighlandville, Missouri\r\n587\r\nHouston, Missouri\r\n967\r\nHumansville, Missouri\r\n754\r\nHurley, Missouri\r\n748\r\nJacket, Missouri\r\n341\r\nJane, Missouri\r\n226\r\nJasper, Missouri\r\n394\r\nJenkins, Missouri\r\n574\r\nJerico Springs, Missouri\r\n398\r\nJoplin, Missouri\r\n437\r\n438\r\n571\r\n572\r\n578\r\n623\r\n624\r\n625\r\n629\r\n659\r\n781\r\n782\r\nKimberling City, Missouri\r\n739\r\nKoshkonong, Missouri\r\n867\r\nLamar, Missouri\r\n682\r\nLanagan, Missouri\r\n436\r\nLebanon, Missouri\r\n531\r\n532\r\n588\r\nLiberal, Missouri\r\n843\r\nLockwood, Missouri\r\n232\r\nLouisburg, Missouri\r\n752\r\nLowry City, Missouri\r\n644\r\nManes, Missouri\r\n668\r\nMano, Missouri\r\n271\r\nMansfield, Missouri\r\n924\r\nMarionville, Missouri\r\n463\r\nMarshfield, Missouri\r\n464\r\n468\r\nMetz, Missouri\r\n484\r\nMiller, Missouri\r\n452\r\nMilo, Missouri\r\n944\r\nMindenmins, Missouri\r\n842\r\nMonett, Missouri\r\n235\r\nMorrisvale, Missouri\r\n756\r\nMountain View, Missouri\r\n934\r\nMount Grove, Missouri\r\n926\r\nMount Vernon, Missouri\r\n466\r\nMyrtle, Missouri\r\n938\r\nNebo, Missouri\r\n453\r\nNeosho, Missouri\r\n451\r\nNevada, Missouri\r\n321\r\n448\r\n667\r\nNiangua, Missouri\r\n473\r\nNixa, Missouri\r\n725\r\nNoel, Missouri\r\n475\r\nNorwood, Missouri\r\n746\r\nOsceola, Missouri\r\n646\r\nOzark, Missouri\r\n485\r\nPeace Valley , Missouri\r\n277\r\nPierce City, Missouri\r\n476\r\nPineville, Missouri\r\n223\r\nPittsburg, Missouri\r\n852\r\nPleasant Hope, Missouri\r\n467\r\nPolk, Missouri\r\n253\r\nPowell, Missouri\r\n435\r\nPreston, Missouri\r\n722\r\nProtem, Missouri\r\n785\r\nPurcell, Missouri\r\n525\r\nPurdy, Missouri\r\n442\r\nRaymondville, Missouri\r\n457\r\nReeds Spring, Missouri\r\n272\r\nRepublic, Missouri\r\n732\r\nRich Hill, Missouri\r\n395\r\nRichards, Missouri\r\n927\r\nRoby, Missouri\r\n458\r\nRockway Beach, Missouri\r\n561\r\nRogersvl, Missouri\r\n753\r\nSarcoxie, Missouri\r\n548\r\nSchell City, Missouri\r\n432\r\nSeligman, Missouri\r\n662\r\nSeneca, Missouri\r\n776\r\nSeymour, Missouri\r\n935\r\nSheldon, Missouri\r\n884\r\nShell Knob, Missouri\r\n858\r\nSouth West City, Missouri\r\n762\r\nSparta, Missouri\r\n278\r\nSpringfield, Missouri\r\n555\r\n227\r\n577\r\n820\r\n831\r\n833\r\n836\r\n837\r\n839\r\n861\r\n862\r\n863\r\n864\r\n865\r\n866\r\n868\r\n869\r\n873\r\n881\r\n882\r\n883\r\n885\r\n886\r\n887\r\n888\r\n889\r\n895\r\n940\r\nStark City, Missouri\r\n638\r\nStella, Missouri\r\n628\r\nStockton, Missouri\r\n276\r\nStotts City, Missouri\r\n285\r\nStoutland, Missouri\r\n286\r\nStrafford, Missouri\r\n736\r\nSummersville, Missouri\r\n932\r\nThayer, Missouri\r\n264\r\nTheodosia, Missouri\r\n273\r\nThomasville, Missouri\r\n764\r\nTiff City, Missouri\r\n775\r\nUrbana, Missouri\r\n993\r\nVanzant, Missouri\r\n948\r\nVerona, Missouri\r\n498\r\nWalker, Missouri\r\n465\r\nWalnut Grove, Missouri\r\n994\r\nWashburn, Missouri\r\n826\r\nWasola, Missouri\r\n265\r\nWeaubleau, Missouri\r\n428\r\nWebb City, Missouri\r\n673\r\nWest Plains, Missouri\r\n256\r\n257\r\nWheatland, Missouri\r\n282\r\nWheaton, Missouri\r\n652\r\nWillard, Missouri\r\n742\r\nWillow Springs, Missouri\r\n469\r\n\u00035Unknown prefix code (417) - Missouri\r\n"
  },
  {
    "path": "install/regions/regions.418",
    "content": "A Bagotville, Quebec, Canada\r\n677\r\nAguanish, Quebec, Canada\r\n533\r\nAlbanel, Quebec, Canada\r\n279\r\nAlma, Quebec, Canada\r\n481\r\n662\r\n668\r\n669\r\nAmqui, Quebec, Canada\r\n629\r\nAnse Saint John, Quebec, Canada\r\n272\r\nArmagh, Quebec, Canada\r\n466\r\nB Johanbee, Quebec, Canada\r\n539\r\nB St Cath, Quebec, Canada\r\n237\r\nB St Paul, Quebec, Canada\r\n435\r\nB Trinite, Quebec, Canada\r\n920\r\n939\r\nBaiecomeau, Quebec, Canada\r\n294\r\n296\r\nBaiesables, Quebec, Canada\r\n772\r\nBarachois, Quebec, Canada\r\n645\r\nBatiscan, Quebec, Canada\r\n362\r\nBeauceville, Quebec, Canada\r\n774\r\nBergerones, Quebec, Canada\r\n232\r\nBic, Quebec, Canada\r\n736\r\nBiencourt, Quebec, Canada\r\n499\r\nBl 976 Svc, Quebec, Canada\r\n976\r\nBlack Lake, Quebec, Canada\r\n423\r\nBoischatel, Quebec, Canada\r\n822\r\nBonaventur, Quebec, Canada\r\n530\r\n534\r\nCabano, Quebec, Canada\r\n854\r\nCap Chat, Quebec, Canada\r\n786\r\nCap Desros, Quebec, Canada\r\n892\r\nCap Saint Ign, Quebec, Canada\r\n246\r\nCapauxmeul, Quebec, Canada\r\n986\r\nCaplan, Quebec, Canada\r\n388\r\nCarleton, Quebec, Canada\r\n364\r\nCausapscal, Quebec, Canada\r\n756\r\nChambord, Quebec, Canada\r\n342\r\nChandler, Quebec, Canada\r\n689\r\nChapais, Quebec, Canada\r\n745\r\nCharny, Quebec, Canada\r\n832\r\nChat Rchr, Quebec, Canada\r\n824\r\nChevery, Quebec, Canada\r\n787\r\nChibgmau, Quebec, Canada\r\n748\r\nChicoutimi, Quebec, Canada\r\n543\r\n545\r\n549\r\n690\r\n693\r\n696\r\n698\r\nChts Aux O, Quebec, Canada\r\n567\r\nChts Des P, Quebec, Canada\r\n377\r\nClarke City, Quebec, Canada\r\n583\r\nClermont, Quebec, Canada\r\n439\r\nCloridorme, Quebec, Canada\r\n395\r\nColombier, Quebec, Canada\r\n565\r\nCourcelles, Quebec, Canada\r\n483\r\nDaaquam, Quebec, Canada\r\n244\r\nDelisle, Quebec, Canada\r\n347\r\nDesbiens, Quebec, Canada\r\n346\r\nDisraeli, Quebec, Canada\r\n449\r\nDolbeau, Quebec, Canada\r\n276\r\nDonnacona, Quebec, Canada\r\n285\r\nEast Broughton, Quebec, Canada\r\n427\r\nEscoumins, Quebec, Canada\r\n233\r\nEsprit Saint, Quebec, Canada\r\n779\r\nFerland, Quebec, Canada\r\n676\r\nFermont, Quebec, Canada\r\n287\r\nForestville, Quebec, Canada\r\n587\r\nFrampton, Quebec, Canada\r\n479\r\nGarthby, Quebec, Canada\r\n458\r\nGaspe, Quebec, Canada\r\n360\r\n368\r\nGirardville, Quebec, Canada\r\n258\r\nGodbout, Quebec, Canada\r\n568\r\nGr Entree, Quebec, Canada\r\n985\r\nGrande River, Quebec, Canada\r\n385\r\nGrandvalle, Quebec, Canada\r\n393\r\nHarngtn Harbor, Quebec, Canada\r\n795\r\nHauterive, Quebec, Canada\r\n295\r\n589\r\nHavaubert, Quebec, Canada\r\n937\r\nHavauxmais, Quebec, Canada\r\n969\r\nHavre Saint P, Quebec, Canada\r\n538\r\nHebertvill, Quebec, Canada\r\n344\r\n343\r\nIle Au Cou, Quebec, Canada\r\n438\r\nInverness, Quebec, Canada\r\n453\r\nJonquiere, Quebec, Canada\r\n542\r\n547\r\n548\r\n695\r\n699\r\nLa Baie, Quebec, Canada\r\n544\r\n697\r\nLa Dore, Quebec, Canada\r\n256\r\nLa Guadlpe, Quebec, Canada\r\n459\r\nLa Malbaie, Quebec, Canada\r\n665\r\nLa Martre, Quebec, Canada\r\n288\r\nLac Au Sau, Quebec, Canada\r\n778\r\nLac Bouch, Quebec, Canada\r\n348\r\nLac Etchmn, Quebec, Canada\r\n625\r\nLac Frontier, Quebec, Canada\r\n245\r\nLambton, Quebec, Canada\r\n486\r\nLapocatier, Quebec, Canada\r\n856\r\nLaromaine, Quebec, Canada\r\n229\r\nLaterriere, Quebec, Canada\r\n678\r\nLac Aux Sbl, Quebec, Canada\r\n336\r\nLeeds, Quebec, Canada\r\n424\r\nLes Boules, Quebec, Canada\r\n936\r\nLes Eblmts, Quebec, Canada\r\n635\r\nLes Mechns, Quebec, Canada\r\n729\r\nLevis, Quebec, Canada\r\n833\r\n834\r\n835\r\n837\r\n838\r\n839\r\nLislet, Quebec, Canada\r\n247\r\nLisleverte, Quebec, Canada\r\n898\r\nLoretteville, Quebec, Canada\r\n842\r\n843\r\n845\r\n847\r\nLour Bln S, Quebec, Canada\r\n461\r\nLuceville, Quebec, Canada\r\n739\r\nManicouagn, Quebec, Canada\r\n584\r\nMaria, Quebec, Canada\r\n759\r\nMatane, Quebec, Canada\r\n562\r\n566\r\nMatapedia, Quebec, Canada\r\n865\r\nMetabchn, Quebec, Canada\r\n349\r\nMilot, Quebec, Canada\r\n373\r\nMittasn Lake, Quebec, Canada\r\n923\r\nMoisie, Quebec, Canada\r\n927\r\nMont Apica, Quebec, Canada\r\n467\r\nMont Bleu, Quebec, Canada\r\n637\r\nMont Joli, Quebec, Canada\r\n775\r\nMont Louis, Quebec, Canada\r\n797\r\nMont Magny, Quebec, Canada\r\n241\r\n248\r\nMurdochville, Quebec, Canada\r\n784\r\nMutton Bay, Quebec, Canada\r\n773\r\nNatashquan, Quebec, Canada\r\n726\r\nNd Des Lrt, Quebec, Canada\r\n841\r\n849\r\nNd Du Lac, Quebec, Canada\r\n899\r\nNeuville, Quebec, Canada\r\n876\r\nNew Carlisle, Quebec, Canada\r\n752\r\nNewport, Quebec, Canada\r\n777\r\nNewrichmnd, Quebec, Canada\r\n392\r\nNormandin, Quebec, Canada\r\n274\r\nNouvelle, Quebec, Canada\r\n794\r\nP Des Laur, Quebec, Canada\r\n846\r\nP La Croix, Quebec, Canada\r\n788\r\nP Riv Saint F, Quebec, Canada\r\n632\r\nPentecote, Quebec, Canada\r\n799\r\nPerce, Quebec, Canada\r\n782\r\nPeribonka, Quebec, Canada\r\n374\r\nPont Rouge, Quebec, Canada\r\n873\r\nPort Daniel, Quebec, Canada\r\n396\r\nPort Neuf, Quebec, Canada\r\n286\r\nPort Cartier, Quebec, Canada\r\n766\r\n768\r\nPort Menier, Quebec, Canada\r\n535\r\nQuebec, Quebec, Canada\r\n521\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n529\r\n563\r\n564\r\n569\r\n621\r\n622\r\n623\r\n624\r\n626\r\n627\r\n628\r\n640\r\n641\r\n643\r\n644\r\n646\r\n647\r\n648\r\n649\r\n650\r\n651\r\n652\r\n653\r\n654\r\n655\r\n656\r\n657\r\n658\r\n659\r\n660\r\n661\r\n663\r\n664\r\n666\r\n667\r\n670\r\n681\r\n682\r\n683\r\n684\r\n686\r\n687\r\n688\r\n691\r\n692\r\n694\r\n871\r\n872\r\n874\r\n877\r\n890\r\n943\r\n991\r\nRimouski, Quebec, Canada\r\n722\r\n723\r\n724\r\n725\r\n750\r\nRiv A Pre, Quebec, Canada\r\n323\r\nRiv Au Ren, Quebec, Canada\r\n269\r\nRiv Bleue, Quebec, Canada\r\n893\r\nRiv Duloup, Quebec, Canada\r\n862\r\n867\r\n868\r\nRiv Stain John, Quebec, Canada\r\n949\r\nRiv Ton, Quebec, Canada\r\n465\r\nRoberval, Quebec, Canada\r\n275\r\nS Au Moutn, Quebec, Canada\r\n231\r\nSacrecoeur, Quebec, Canada\r\n236\r\nSayabec, Quebec, Canada\r\n536\r\nScheffervl, Quebec, Canada\r\n585\r\nSept Iles, Quebec, Canada\r\n962\r\n964\r\n968\r\nSquatec, Quebec, Canada\r\n855\r\nSaint A Des M, Quebec, Canada\r\n763\r\nSaint Adelphe, Quebec, Canada\r\n322\r\nSaint Ag Lotb, Quebec, Canada\r\n599\r\nSaint Agapit, Quebec, Canada\r\n888\r\nSaint Alexander, Quebec, Canada\r\n495\r\nSaint Alx Mat, Quebec, Canada\r\n299\r\nSaint Amb Chi, Quebec, Canada\r\n672\r\nSaint Andre, Quebec, Canada\r\n493\r\nSaint Ann Bpr, Quebec, Canada\r\n827\r\nSaint Ann Per, Quebec, Canada\r\n325\r\nSaint Ann Ptn, Quebec, Canada\r\n238\r\nSaint Anselme, Quebec, Canada\r\n885\r\nSaint Ant Tly, Quebec, Canada\r\n886\r\nSaint Bas Pnf, Quebec, Canada\r\n329\r\nSaint Bern Do, Quebec, Canada\r\n475\r\nSaint Blandin, Quebec, Canada\r\n735\r\nSaint Camille, Quebec, Canada\r\n595\r\nSaint Casimir, Quebec, Canada\r\n339\r\nSaint Cathrne, Quebec, Canada\r\n875\r\nSaint Chs Bel, Quebec, Canada\r\n887\r\nSaint Clr Dor, Quebec, Canada\r\n883\r\nSaint Come Ke, Quebec, Canada\r\n685\r\nSaint Croix, Quebec, Canada\r\n926\r\nSaint Dam Buc, Quebec, Canada\r\n789\r\nSaint Ed Lotb, Quebec, Canada\r\n796\r\nSaint Eleuthr, Quebec, Canada\r\n859\r\nSaint Eph Bce, Quebec, Canada\r\n484\r\nSaint Fab Rim, Quebec, Canada\r\n869\r\nSaint Fb De P, Quebec, Canada\r\n249\r\nSaint Felicit, Quebec, Canada\r\n733\r\nSaint Felicn, Quebec, Canada\r\n679\r\nSaint Fer Dha, Quebec, Canada\r\n428\r\nSaint Fereol, Quebec, Canada\r\n826\r\nSaint Fidele, Quebec, Canada\r\n434\r\nSaint Flavien, Quebec, Canada\r\n728\r\nSaint Francois, Quebec, Canada\r\n259\r\nSaint Fulgnce, Quebec, Canada\r\n674\r\nSaint Gab Rim, Quebec, Canada\r\n798\r\nSaint Ged Bce, Quebec, Canada\r\n582\r\nSaint Gedeon, Quebec, Canada\r\n345\r\nSaint Geo Bce, Quebec, Canada\r\n226\r\n227\r\n228\r\nSaint Hen Lev, Quebec, Canada\r\n882\r\nSaint Henedin, Quebec, Canada\r\n935\r\nSaint Hlarion, Quebec, Canada\r\n457\r\nSaint Irenee, Quebec, Canada\r\n452\r\nSaint J Dieu, Quebec, Canada\r\n963\r\nSaint Jn Dorl, Quebec, Canada\r\n829\r\nSaint Jn Point J, Quebec, Canada\r\n598\r\nSaint Jos Bce, Quebec, Canada\r\n397\r\nSaint Justine, Quebec, Canada\r\n383\r\nSaint Lam Lzn, Quebec, Canada\r\n889\r\nSaint Leon Gr, Quebec, Canada\r\n743\r\nSaint Luc, Quebec, Canada\r\n636\r\nSaint Luc Bea, Quebec, Canada\r\n223\r\nSaint Magloir, Quebec, Canada\r\n257\r\nSaint Malachi, Quebec, Canada\r\n642\r\nSaint Marc Ca, Quebec, Canada\r\n268\r\nSaint Mart Bc, Quebec, Canada\r\n382\r\nSaint Meth Fr, Quebec, Canada\r\n422\r\nSaint Mich Be, Quebec, Canada\r\n884\r\nSaint Moise, Quebec, Canada\r\n776\r\nSaint Mrie Bc, Quebec, Canada\r\n386\r\n387\r\nSaint Nicolas, Quebec, Canada\r\n831\r\n836\r\nSaint Od Cran, Quebec, Canada\r\n464\r\nSaint Pacome, Quebec, Canada\r\n852\r\nSaint Pamphil, Quebec, Canada\r\n356\r\nSaint Pascal, Quebec, Canada\r\n492\r\nSaint Pat Bge, Quebec, Canada\r\n596\r\nSaint Perpetu, Quebec, Canada\r\n359\r\nSaint Petrnil, Quebec, Canada\r\n828\r\nSaint Phl Nri, Quebec, Canada\r\n498\r\nSaint Pl Mont, Quebec, Canada\r\n469\r\nSaint Pl Riv, Quebec, Canada\r\n379\r\nSaint Prime, Quebec, Canada\r\n251\r\nSaint Prs Dor, Quebec, Canada\r\n594\r\nSaint Raymond, Quebec, Canada\r\n337\r\nSaint Rch Aul, Quebec, Canada\r\n354\r\nSaint Rene Ma, Quebec, Canada\r\n224\r\nSaint Rose N, Quebec, Canada\r\n675\r\nSaint Rose Wa, Quebec, Canada\r\n267\r\nSaint Rphl Be, Quebec, Canada\r\n243\r\nSaint Sim Rim, Quebec, Canada\r\n738\r\nSaint Simeon, Quebec, Canada\r\n638\r\nSaint Stan Ch, Quebec, Canada\r\n328\r\nSaint Thecle, Quebec, Canada\r\n289\r\nSaint Theophl, Quebec, Canada\r\n597\r\nSaint Tite, Quebec, Canada\r\n365\r\nSaint Tite Cp, Quebec, Canada\r\n823\r\nSaint Ubalde, Quebec, Canada\r\n277\r\nSaint Ulric, Quebec, Canada\r\n737\r\nSaint Urbain, Quebec, Canada\r\n639\r\nSaint Vic Bce, Quebec, Canada\r\n588\r\nSaint Zachari, Quebec, Canada\r\n593\r\nSaint Appollin, Quebec, Canada\r\n881\r\nSaint Augustine, Quebec, Canada\r\n947\r\n878\r\nSaint Brig Del, Quebec, Canada\r\n825\r\nSaint Honore, Quebec, Canada\r\n485\r\n673\r\n497\r\nStoneham, Quebec, Canada\r\n848\r\nStratford, Quebec, Canada\r\n443\r\nTadoussac, Quebec, Canada\r\n235\r\nTete Baln, Quebec, Canada\r\n242\r\nThetford Mns, Quebec, Canada\r\n334\r\n335\r\n338\r\nTring Junction, Quebec, Canada\r\n426\r\nTrois Pist, Quebec, Canada\r\n851\r\nVal Alain, Quebec, Canada\r\n744\r\nVal Brilan, Quebec, Canada\r\n742\r\nValcartier, Quebec, Canada\r\n844\r\nVallee Junction, Quebec, Canada\r\n253\r\nVl Degelis, Quebec, Canada\r\n853\r\n\u00035Unknown prefix code (418) - Quebec, Canada\r\n"
  },
  {
    "path": "install/regions/regions.419",
    "content": "Ada, Ohio\r\n634\r\n772\r\nAdario, Ohio\r\n895\r\nAlger, Ohio\r\n757\r\nAntwerp, Ohio\r\n258\r\nArcadia, Ohio\r\n894\r\nArchbold, Ohio\r\n445\r\n446\r\nArlington, Ohio\r\n365\r\nArthur, Ohio\r\n393\r\nAshland, Ohio\r\n281\r\n282\r\n289\r\n322\r\n323\r\n324\r\n325\r\nAyersville, Ohio\r\n395\r\nBascom, Ohio\r\n937\r\nBeaverdam, Ohio\r\n643\r\nBellevue, Ohio\r\n483\r\nBelmore, Ohio\r\n275\r\nBenton Ridge, Ohio\r\n859\r\nBerlin Heights, Ohio\r\n588\r\nBettsville, Ohio\r\n986\r\nBloomdale, Ohio\r\n454\r\nBloomingville, Ohio\r\n359\r\nBloomville, Ohio\r\n983\r\nBluffton, Ohio\r\n358\r\nBowling Green, Ohio\r\n352\r\n353\r\n354\r\n372\r\n373\r\nBryan, Ohio\r\n631\r\n633\r\n636\r\nBuckland, Ohio\r\n657\r\nBucyrus, Ohio\r\n562\r\n563\r\nButler, Ohio\r\n883\r\nCairo, Ohio\r\n641\r\nCaledonia, Ohio\r\n845\r\nCardington, Ohio\r\n864\r\nCarey, Ohio\r\n396\r\nCastalia, Ohio\r\n684\r\nCelina, Ohio\r\n268\r\n586\r\nChatfield, Ohio\r\n988\r\nChesterfld, Ohio\r\n452\r\nChestervl, Ohio\r\n768\r\nCloverdale, Ohio\r\n488\r\nClyde, Ohio\r\n547\r\nColdwater, Ohio\r\n678\r\nColumbus Grove, Ohio\r\n659\r\nCongress, Ohio\r\n846\r\nContinental, Ohio\r\n596\r\nConvoy, Ohio\r\n749\r\nCooney, Ohio\r\n459\r\nCrestline, Ohio\r\n683\r\nCridersville, Ohio\r\n645\r\nCurtc Orgn, Ohio\r\n836\r\nCygnet, Ohio\r\n655\r\nDefiance, Ohio\r\n769\r\n782\r\n783\r\n784\r\nDelphos, Ohio\r\n692\r\n695\r\nDelta, Ohio\r\n822\r\nDeshler, Ohio\r\n278\r\nDunkirk, Ohio\r\n759\r\nEast Monroeville, Ohio\r\n623\r\nEast Woodburn, Ohio\r\n632\r\nEdgerton, Ohio\r\n298\r\nEdon, Ohio\r\n272\r\nElida, Ohio\r\n339\r\nElmore, Ohio\r\n862\r\nEvansport, Ohio\r\n428\r\nFayette, Ohio\r\n237\r\nFindlay, Ohio\r\n348\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\nFlorida, Ohio\r\n762\r\nForest, Ohio\r\n273\r\nFostoria, Ohio\r\n435\r\n436\r\nFremont, Ohio\r\n332\r\n334\r\n355\r\nFort Jennings, Ohio\r\n286\r\nFort Recovery, Ohio\r\n375\r\nGalion, Ohio\r\n462\r\n468\r\nGenoa, Ohio\r\n855\r\nGerald, Ohio\r\n598\r\nGibsonburg, Ohio\r\n637\r\nGilboa, Ohio\r\n456\r\nGlandorf, Ohio\r\n538\r\nGomer, Ohio\r\n642\r\nGrand Rapids, Ohio\r\n832\r\nGreen Springs, Ohio\r\n639\r\nGreenwich, Ohio\r\n752\r\nGretn Mlnt, Ohio\r\n256\r\nGroverhill, Ohio\r\n587\r\nHamler, Ohio\r\n274\r\nHaskntntgy, Ohio\r\n823\r\nHayesville, Ohio\r\n368\r\nHelena, Ohio\r\n638\r\nHicksville, Ohio\r\n542\r\nHolgate, Ohio\r\n264\r\nHolland, Ohio\r\n865\r\n866\r\n867\r\n868\r\nHuron, Ohio\r\n433\r\nJenera, Ohio\r\n326\r\nJewell, Ohio\r\n497\r\nJohnsville, Ohio\r\n362\r\nKalida, Ohio\r\n532\r\nKellys Isle, Ohio\r\n746\r\nKenton, Ohio\r\n673\r\n674\r\n675\r\nLafayette, Ohio\r\n649\r\nLakeville, Ohio\r\n827\r\nLeipsic, Ohio\r\n943\r\nLexington, Ohio\r\n884\r\nLiberty Center, Ohio\r\n533\r\nLima, Ohio\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n234\r\n235\r\n331\r\n991\r\n998\r\n999\r\nLindsey, Ohio\r\n665\r\nLoudonvl, Ohio\r\n994\r\nLucas, Ohio\r\n892\r\nLuckey, Ohio\r\n833\r\nLykens, Ohio\r\n284\r\nLyons, Ohio\r\n923\r\nMansfield, Ohio\r\n529\r\n543\r\n564\r\n747\r\n774\r\nMansfield, Ohio\r\n521\r\n522\r\n524\r\n525\r\n526\r\n589\r\n755\r\n756\r\n886\r\nMarblehead, Ohio\r\n798\r\nMarengo, Ohio\r\n253\r\nMariastein, Ohio\r\n925\r\nMaumee-Cel, Ohio\r\n891\r\n893\r\n897\r\nMcclure, Ohio\r\n748\r\nMccomb, Ohio\r\n293\r\nMcCutchinville, Ohio\r\n981\r\nMelmore, Ohio\r\n397\r\nMendon, Ohio\r\n795\r\nMetamora, Ohio\r\n644\r\nMiddle Point, Ohio\r\n968\r\nMilan, Ohio\r\n499\r\nMiller City, Ohio\r\n876\r\nMinster, Ohio\r\n628\r\nMoline, Ohio\r\n838\r\nMonroeville, Ohio\r\n465\r\nMontpelier, Ohio\r\n485\r\nMount Blanchard, Ohio\r\n694\r\nMount Cory, Ohio\r\n447\r\n477\r\nMount Gilead, Ohio\r\n946\r\n947\r\nNapoleon, Ohio\r\n592\r\n599\r\nNeapolis, Ohio\r\n875\r\nNew Bremen, Ohio\r\n629\r\nNew Knoxville, Ohio\r\n753\r\nNew London, Ohio\r\n929\r\nNew Riegel, Ohio\r\n595\r\nNew Winchester, Ohio\r\n985\r\nNew Bavaria, Ohio\r\n653\r\nNew Washington, Ohio\r\n492\r\nNey, Ohio\r\n658\r\nNorth Baltimore, Ohio\r\n257\r\nNorth Star, Ohio\r\n336\r\nNorthcreek, Ohio\r\n398\r\nNorwalk, Ohio\r\n651\r\n663\r\n668\r\n744\r\nNova, Ohio\r\n652\r\nOak Harbor, Ohio\r\n898\r\nOakwood, Ohio\r\n594\r\nOhio City, Ohio\r\n965\r\nOkolona, Ohio\r\n758\r\nOld Fort, Ohio\r\n992\r\nOttawa, Ohio\r\n523\r\nOttoville, Ohio\r\n453\r\nPandora, Ohio\r\n384\r\nPaulding, Ohio\r\n399\r\nPayne, Ohio\r\n263\r\nPemberville, Ohio\r\n287\r\nPerrysburg, Ohio\r\n872\r\n874\r\nPerrysville, Ohio\r\n938\r\nPioneer, Ohio\r\n737\r\nPlymouth, Ohio\r\n687\r\nPolk, Ohio\r\n945\r\nPortage, Ohio\r\n686\r\nPoint Clinton, Ohio\r\n635\r\n732\r\n734\r\n797\r\nPut In Bay, Ohio\r\n285\r\nRawson, Ohio\r\n963\r\nRichford Centerby, Ohio\r\n829\r\nRdgvl Cors, Ohio\r\n267\r\nRedhaw, Ohio\r\n869\r\nRepublic, Ohio\r\n585\r\nRising Sun, Ohio\r\n457\r\nRockford, Ohio\r\n363\r\nSandusky, Ohio\r\n621\r\n624\r\n625\r\n626\r\n627\r\nSavannah, Ohio\r\n962\r\nScott, Ohio\r\n622\r\nShelby, Ohio\r\n342\r\n347\r\nSherwood, Ohio\r\n899\r\nShiloh, Ohio\r\n896\r\nSpencerville, Ohio\r\n647\r\nSt Marys, Ohio\r\n394\r\nStonyridge, Ohio\r\n837\r\nStryker, Ohio\r\n682\r\nSullivan, Ohio\r\n736\r\nSwanton, Ohio\r\n825\r\n826\r\nSycamore, Ohio\r\n927\r\nSylvania, Ohio\r\n824\r\n841\r\n843\r\n882\r\n885\r\nTiffin, Ohio\r\n443\r\n448\r\nToledo, Ohio\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n249\r\n252\r\n255\r\n259\r\n261\r\n262\r\n265\r\n269\r\n292\r\n321\r\n327\r\n349\r\n351\r\n356\r\n361\r\n381\r\n382\r\n385\r\n389\r\n470\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n478\r\n479\r\n531\r\n534\r\n535\r\n536\r\n537\r\n539\r\n555\r\n661\r\n666\r\n691\r\n693\r\n697\r\n698\r\n726\r\n727\r\n729\r\n936\r\nUpper Sandusky, Ohio\r\n294\r\n357\r\nVan Buren, Ohio\r\n299\r\nVan Wert, Ohio\r\n238\r\nVanlue, Ohio\r\n387\r\nVaughnsville, Ohio\r\n646\r\nVenedocia, Ohio\r\n667\r\nWabash, Ohio\r\n942\r\nWapakoneta, Ohio\r\n738\r\n739\r\nWaterville, Ohio\r\n878\r\nWauseon, Ohio\r\n335\r\n337\r\nWaynebrdnr, Ohio\r\n288\r\nWaynesfield, Ohio\r\n568\r\nWest Salem, Ohio\r\n853\r\nWest Unity, Ohio\r\n924\r\nWestminister, Ohio\r\n648\r\nWeston, Ohio\r\n669\r\nWharton, Ohio\r\n458\r\nWhitehouse, Ohio\r\n877\r\nWillard, Ohio\r\n933\r\n935\r\nWillshrewrn, Ohio\r\n495\r\nWoodland, Ohio\r\n231\r\nWoodville, Ohio\r\n849\r\nYorkshire, Ohio\r\n582\r\n\u00035Unknown prefix code (419) - Ohio\r\n"
  },
  {
    "path": "install/regions/regions.423",
    "content": "Bean Station, Tennessee\r\n993\r\nBluff City, Tennessee\r\n538\r\nBulls Gap\u00031/\u00032Whitesburg, Tennessee\r\n235\r\nClaxton, Tennessee\r\n945\r\nClinton, Tennessee\r\n457\r\n463\r\nConcord, Tennessee\r\n216\r\n640\r\n671\r\n675\r\n679\r\n680\r\n966\r\nDandridge, Tennessee\r\n397\r\nFarragut, Tennessee\r\n675\r\nFountain City\u00031/\u00032Knoxville, Tennessee\r\n281\r\nFriendsville, Tennessee\r\n995\r\nGatlinburg, Tennessee\r\n430\r\n436\r\n453\r\nGray, Tennessee\r\n477\r\nGreenback, Tennessee\r\n856\r\nHalls Cross Roads, Tennessee\r\n922\r\n925\r\nHarriman, Tennessee\r\n590\r\n882\r\nHartford, Tennessee\r\n217\r\nJefferson City, Tennessee\r\n471\r\n475\r\nJohnson City, Tennessee\r\n929\r\nKarns, Tennessee\r\n531\r\nKnoxville, Tennessee\r\n215\r\n250\r\n301\r\n310\r\n414\r\n417\r\n450\r\n470\r\n521\r\n522\r\n523\r\n524\r\n525\r\n531\r\n539\r\n541\r\n545\r\n546\r\n549\r\n558\r\n564\r\n567\r\n573\r\n577\r\n579\r\n584\r\n588\r\n594\r\n595\r\n599\r\n602\r\n631\r\n632\r\n637\r\n656\r\n673\r\n687\r\n688\r\n689\r\n690\r\n691\r\n693\r\n694\r\n777\r\n850\r\n873\r\n966\r\n971\r\n974\r\n977\r\n996\r\nKingston, Tennessee\r\n376\r\nKodak\u00031/\u00032Blaine, Tennessee\r\n397\r\n933\r\nLake City, Tennessee\r\n426\r\nLenoir City, Tennessee\r\n986\r\n987\r\nLouden, Tennessee\r\n458\r\nMaryville, Tennessee\r\n681\r\n970\r\n977\r\n981\r\n982\r\n983\r\n984\r\n985\r\nMaynardville, Tennessee\r\n992\r\nMorristown, Tennessee\r\n318\r\n581\r\n585\r\n586\r\n587\r\nNewport, Tennessee\r\n509\r\nNewport\u00031/\u00032Cosby, Tennessee\r\n623\r\n625\r\nNorris, Tennessee\r\n494\r\nOak Ridge, Tennessee\r\n220\r\n241\r\n481\r\n482\r\n483\r\n574\r\n576\r\n927\r\nOliver Springs\u00031/\u00032Clinton, Tennessee\r\n435\r\nPowell, Tennessee\r\n938\r\n947\r\nRockwood, Tennessee\r\n354\r\nRogersville\u00031/\u00032Mooresburg, Tennessee\r\n272\r\nRutledge, Tennessee\r\n828\r\nSeymour, Tennessee\r\n577\r\nSevierville\u00031/\u00032Pigeon Forge, Tennessee\r\n428\r\n429\r\nSharps Chapel, Tennessee\r\n278\r\nStrawberry Plains\u00031/\u00032Mascot, Tennessee\r\n932\r\n933\r\nSweetwater, Tennessee\r\n213\r\nTate Springs, Tennessee\r\n767\r\nTownsend, Tennessee\r\n448\r\nWashburn, Tennessee\r\n497\r\nWhite Pine, Tennessee\r\n674\r\n\u00035Unknown prefix code (423) - Tennessee\r\n"
  },
  {
    "path": "install/regions/regions.425",
    "content": "Cougar, Washington\r\n238\r\nCurtis, Washington\r\n245\r\nEverett, Washington\r\n304\r\n513\r\n514\r\n717\r\n239\r\n252\r\n258\r\n259\r\n261\r\n266\r\n290\r\n294\r\n335\r\n339\r\n342\r\n347\r\n348\r\n349\r\n353\r\n355\r\n356\r\n359\r\n388\r\n929\r\n513\r\n742\r\nFall City, Washington\r\n222\r\nGrayland, Washington\r\n267\r\nLa Center, Washington\r\n263\r\nMontesano, Washington\r\n249\r\nRenton, Washington\r\n227\r\n393\r\n477\r\n226\r\n228\r\n234\r\n235\r\n237\r\n251\r\n255\r\n271\r\n277\r\n656\r\n965\r\nVancouver, Washington\r\n254\r\n260\r\n418\r\n576\r\n737\r\n921\r\nYale, Washington\r\n231\r\n\u00035Unknown prefix code (425) - Washington\r\n"
  },
  {
    "path": "install/regions/regions.429",
    "content": "Aylesbury, Buckinghamshire, Great Britain.\r\n429\r\n639\r\n\u00035Unknown prefix code (429) - Great Britian\r\n"
  },
  {
    "path": "install/regions/regions.497",
    "content": "Somewhere in Germany (Unk prefix)\r\n457\r\n\u00035Unknown prefix (497) - Germany\r\n"
  },
  {
    "path": "install/regions/regions.499",
    "content": "Germany\r\n499\r\n\u00035Unknown prefix code (499) - Germany\r\n"
  },
  {
    "path": "install/regions/regions.501",
    "content": "Allison, Arkansas\r\n585\r\nAlma, Arkansas\r\n632\r\nAlmyra, Arkansas\r\n992\r\nAlpena, Arkansas\r\n437\r\nAltheimer, Arkansas\r\n766\r\nAltus, Arkansas\r\n468\r\nAmity, Arkansas\r\n342\r\nArkadlphia, Arkansas\r\n245\r\n246\r\nArkansas City, Arkansas\r\n877\r\nAsh Flat, Arkansas\r\n994\r\nAshdown, Arkansas\r\n898\r\nAtkins, Arkansas\r\n641\r\nAugusta, Arkansas\r\n347\r\nAurora, Arkansas\r\n232\r\nBald Knob, Arkansas\r\n724\r\nBanks, Arkansas\r\n465\r\nBatesville, Arkansas\r\n251\r\n698\r\n793\r\nBauxite, Arkansas\r\n557\r\nBay, Arkansas\r\n781\r\nBearden, Arkansas\r\n687\r\nBeebe, Arkansas\r\n882\r\nBelleville, Arkansas\r\n493\r\nBenton, Arkansas\r\n776\r\n778\r\n794\r\n860\r\nBentonville, Arkansas\r\n271\r\n273\r\n277\r\n855\r\n876\r\nBerryville, Arkansas\r\n423\r\nBigelow, Arkansas\r\n759\r\nBiggers, Arkansas\r\n769\r\nBismarck, Arkansas\r\n865\r\nBlack Rock, Arkansas\r\n878\r\nBlevins, Arkansas\r\n874\r\nBlackFish Lake, Arkansas\r\n657\r\nBlooming Grove, Arkansas\r\n566\r\nBlue Mount, Arkansas\r\n947\r\nBluffton, Arkansas\r\n299\r\nBlytheville, Arkansas\r\n532\r\n720\r\n740\r\n762\r\n763\r\nBodcaw, Arkansas\r\n899\r\nBoles, Arkansas\r\n577\r\nBooneville, Arkansas\r\n675\r\nBradford, Arkansas\r\n344\r\nBradley, Arkansas\r\n894\r\nBrinkley, Arkansas\r\n734\r\nBryntclgville, Arkansas\r\n847\r\nBullshoals, Arkansas\r\n445\r\nCabot, Arkansas\r\n843\r\n941\r\nCalico Rock, Arkansas\r\n297\r\nCalion, Arkansas\r\n748\r\nCamden, Arkansas\r\n231\r\n574\r\n836\r\n837\r\nCaraway, Arkansas\r\n482\r\nCarlisle, Arkansas\r\n552\r\nCarryville, Arkansas\r\n529\r\nCarthage, Arkansas\r\n254\r\nCasa, Arkansas\r\n233\r\nCash, Arkansas\r\n477\r\nCave City, Arkansas\r\n283\r\nCenter Ridge, Arkansas\r\n893\r\nCenterton, Arkansas\r\n795\r\nCenterville, Arkansas\r\n576\r\nCharleston, Arkansas\r\n965\r\nCherke Village, Arkansas\r\n257\r\nCherry Vally, Arkansas\r\n588\r\nChidester, Arkansas\r\n685\r\nClarendon, Arkansas\r\n747\r\nClarksville, Arkansas\r\n754\r\nCleveland, Arkansas\r\n669\r\nClinton, Arkansas\r\n745\r\nCompton, Arkansas\r\n420\r\nConcord, Arkansas\r\n668\r\nConway, Arkansas\r\n327\r\n329\r\n336\r\n450\r\n470\r\n730\r\nCorning, Arkansas\r\n857\r\nCotton Plt, Arkansas\r\n459\r\nCove, Arkansas\r\n387\r\nCoy, Arkansas\r\n275\r\nCrawfrdsville, Arkansas\r\n823\r\nCrossett, Arkansas\r\n364\r\n567\r\nCrystal Springs, Arkansas\r\n991\r\nDaisy, Arkansas\r\n398\r\nDalark, Arkansas\r\n366\r\nDamascus, Arkansas\r\n335\r\nDanville, Arkansas\r\n495\r\nDardanelle, Arkansas\r\n229\r\nDe Queen, Arkansas\r\n584\r\n642\r\nDe Witt, Arkansas\r\n946\r\nDecatur, Arkansas\r\n752\r\nDeer, Arkansas\r\n428\r\nDelaplaine, Arkansas\r\n249\r\nDelight, Arkansas\r\n379\r\nDell, Arkansas\r\n564\r\nDermott, Arkansas\r\n538\r\nDes Arc, Arkansas\r\n256\r\nDevall Bluff, Arkansas\r\n998\r\nDiamond City, Arkansas\r\n422\r\nDierks, Arkansas\r\n286\r\nDodd Ridge, Arkansas\r\n691\r\nDodge City, Arkansas\r\n599\r\nDonaldson, Arkansas\r\n384\r\nDover, Arkansas\r\n331\r\nDrakes Creek, Arkansas\r\n456\r\nDumas, Arkansas\r\n382\r\nDyess, Arkansas\r\n764\r\nEarle, Arkansas\r\n792\r\nEl Dorado, Arkansas\r\n862\r\n863\r\n864\r\n866\r\nElaine, Arkansas\r\n827\r\nElkins, Arkansas\r\n643\r\nElm Springs, Arkansas\r\n248\r\nEmerson, Arkansas\r\n547\r\nEngland, Arkansas\r\n842\r\nEnola, Arkansas\r\n849\r\nEudora, Arkansas\r\n355\r\nEureka Springs, Arkansas\r\n253\r\nEvengshade, Arkansas\r\n266\r\nFairfield Bay, Arkansas\r\n884\r\nFarmington, Arkansas\r\n267\r\nFayetteville, Arkansas\r\n442\r\n443\r\n444\r\n521\r\n530\r\n575\r\n841\r\n582\r\n587\r\nFerndale, Arkansas\r\n821\r\nFiftysix, Arkansas\r\n757\r\nFisher, Arkansas\r\n328\r\nFlippin, Arkansas\r\n453\r\nFordyce, Arkansas\r\n352\r\nForeman, Arkansas\r\n542\r\nForrest City, Arkansas\r\n261\r\n270\r\n581\r\n630\r\n633\r\nFort Smith, Arkansas\r\n288\r\n441\r\n452\r\n478\r\n484\r\n646\r\n648\r\n649\r\n650\r\n651\r\n782\r\n783\r\n784\r\n785\r\n788\r\nForum, Arkansas\r\n559\r\nFouke, Arkansas\r\n653\r\nFox, Arkansas\r\n363\r\nFranklin, Arkansas\r\n322\r\nFulton, Arkansas\r\n896\r\nGamaliel, Arkansas\r\n467\r\nGarden Point, Arkansas\r\n531\r\nGarfield, Arkansas\r\n359\r\nGarland, Arkansas\r\n683\r\nGassville, Arkansas\r\n435\r\nGateway, Arkansas\r\n656\r\nGentry, Arkansas\r\n736\r\nGillett, Arkansas\r\n548\r\nGillham, Arkansas\r\n386\r\nGlenwood, Arkansas\r\n356\r\nGould, Arkansas\r\n263\r\nGrady, Arkansas\r\n479\r\nGravette, Arkansas\r\n787\r\nGreen For, Arkansas\r\n438\r\nGreenbrier, Arkansas\r\n679\r\nGreenwood, Arkansas\r\n996\r\nGreers Fry, Arkansas\r\n825\r\nGriffithville, Arkansas\r\n323\r\nGrubbs, Arkansas\r\n252\r\nGurdon, Arkansas\r\n353\r\nHackett, Arkansas\r\n638\r\nHamburg, Arkansas\r\n853\r\nHampton, Arkansas\r\n798\r\nHardy, Arkansas\r\n856\r\nHarrisburg, Arkansas\r\n578\r\nHarrison, Arkansas\r\n365\r\n741\r\n743\r\nHartman, Arkansas\r\n497\r\nHatfield, Arkansas\r\n389\r\nHavana, Arkansas\r\n476\r\nHazen, Arkansas\r\n255\r\nHeber Springs, Arkansas\r\n250\r\n362\r\nHector, Arkansas\r\n284\r\nHelena, Arkansas\r\n338\r\n572\r\nHenderson, Arkansas\r\n488\r\nHermitage, Arkansas\r\n463\r\nHickory Place, Arkansas\r\n854\r\nHickory Ridge, Arkansas\r\n697\r\nHindsville, Arkansas\r\n789\r\nHollygrove, Arkansas\r\n462\r\nHope, Arkansas\r\n722\r\n777\r\nHoratio, Arkansas\r\n832\r\nHorseshoe Bend, Arkansas\r\n670\r\nHot Springs, Arkansas\r\n262\r\n321\r\n520\r\n525\r\n620\r\n622\r\n623\r\n624\r\n760\r\n767\r\nHughes, Arkansas\r\n339\r\nHumphrey, Arkansas\r\n873\r\nHuntsville, Arkansas\r\n738\r\nHuttig, Arkansas\r\n943\r\nIda, Arkansas\r\n454\r\nImboden, Arkansas\r\n869\r\nJacksonville, Arkansas\r\n982\r\n985\r\n988\r\nJasper, Arkansas\r\n446\r\nJessieville, Arkansas\r\n922\r\n984\r\nJesup, Arkansas\r\n528\r\nJoiner, Arkansas\r\n537\r\nJonesboro, Arkansas\r\n926\r\n930\r\n931\r\n932\r\n933\r\n935\r\n972\r\nJones Mills, Arkansas\r\n844\r\nJudsonia, Arkansas\r\n729\r\nJunction City, Arkansas\r\n924\r\n986\r\nKeiser, Arkansas\r\n526\r\nKensett, Arkansas\r\n742\r\nKingsland, Arkansas\r\n348\r\nKingston, Arkansas\r\n665\r\nKnobel, Arkansas\r\n259\r\nLake City, Arkansas\r\n237\r\nLake Hinkle, Arkansas\r\n923\r\nLake Village, Arkansas\r\n265\r\nLakeview, Arkansas\r\n431\r\nLamar, Arkansas\r\n885\r\nLavaca, Arkansas\r\n674\r\nLeachville, Arkansas\r\n539\r\nLead Hill, Arkansas\r\n436\r\nLeola, Arkansas\r\n765\r\nLeonard, Arkansas\r\n522\r\nLepanto, Arkansas\r\n475\r\nLeslie, Arkansas\r\n447\r\nLewisville, Arkansas\r\n921\r\nLincoln, Arkansas\r\n824\r\nLittle Rock, Arkansas\r\n220\r\n221\r\n223\r\n224\r\n225\r\n227\r\n228\r\n280\r\n320\r\n324\r\n340\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n399\r\n433\r\n455\r\n490\r\n555\r\n562\r\n565\r\n568\r\n569\r\n570\r\n580\r\n590\r\n660\r\n661\r\n663\r\n664\r\n666\r\n671\r\n680\r\n681\r\n682\r\n686\r\n688\r\n690\r\n753\r\n758\r\n771\r\n791\r\n945\r\n954\r\n980\r\n990\r\nLockesburg, Arkansas\r\n289\r\nLondon, Arkansas\r\n293\r\nLonoke, Arkansas\r\n676\r\nLonsdale, Arkansas\r\n939\r\nLouann, Arkansas\r\n689\r\nLurton, Arkansas\r\n294\r\nLuxora, Arkansas\r\n658\r\nMacedonia, Arkansas\r\n696\r\nMagazine, Arkansas\r\n969\r\nMagnolia, Arkansas\r\n234\r\n235\r\nMallard Point, Arkansas\r\n492\r\nMalvern, Arkansas\r\n332\r\n337\r\nMammoth Spring, Arkansas\r\n625\r\nManila, Arkansas\r\n561\r\nMansfield, Arkansas\r\n928\r\nMarianna, Arkansas\r\n295\r\nMarion, Arkansas\r\n739\r\nMarked Tree, Arkansas\r\n358\r\nMarmaduke, Arkansas\r\n597\r\nMarshall, Arkansas\r\n448\r\nMarvell, Arkansas\r\n829\r\nMaumelle, Arkansas\r\n333\r\nMaynard, Arkansas\r\n647\r\nMaysville, Arkansas\r\n291\r\nMc Gehee, Arkansas\r\n222\r\nMccrory, Arkansas\r\n731\r\nMcneil, Arkansas\r\n695\r\nMcrae, Arkansas\r\n726\r\nMelbourne, Arkansas\r\n368\r\nMena, Arkansas\r\n394\r\nMidland, Arkansas\r\n639\r\nMidway, Arkansas\r\n481\r\nMineral Springs, Arkansas\r\n287\r\nMonette, Arkansas\r\n486\r\nMonticello, Arkansas\r\n367\r\n460\r\nMorganton, Arkansas\r\n654\r\nMoro, Arkansas\r\n768\r\nMorrilton, Arkansas\r\n354\r\n727\r\n940\r\nMorrow, Arkansas\r\n848\r\nMount Ida, Arkansas\r\n867\r\nMountainbg, Arkansas\r\n369\r\nMount Holly, Arkansas\r\n554\r\nMount Judea, Arkansas\r\n434\r\nMount Home, Arkansas\r\n424\r\n425\r\nMount View, Arkansas\r\n269\r\nMount Pleasant, Arkansas\r\n346\r\nMulberry, Arkansas\r\n997\r\nMurfreesbo, Arkansas\r\n285\r\nNashville, Arkansas\r\n845\r\nNaturaldam, Arkansas\r\n929\r\nNewark, Arkansas\r\n799\r\nNewport, Arkansas\r\n523\r\nNimrod, Arkansas\r\n432\r\nNorfork, Arkansas\r\n499\r\nNorman, Arkansas\r\n334\r\nNorphlet, Arkansas\r\n546\r\nNorth Spring Hill, Arkansas\r\n859\r\nOak Acres, Arkansas\r\n852\r\nOak Grove, Arkansas\r\n749\r\nOden, Arkansas\r\n326\r\nOil Trough, Arkansas\r\n264\r\nOkolona, Arkansas\r\n274\r\nOla, Arkansas\r\n489\r\nOmaha, Arkansas\r\n426\r\nOsage, Arkansas\r\n553\r\nOsceola, Arkansas\r\n563\r\nOxford, Arkansas\r\n258\r\nOzark, Arkansas\r\n667\r\nOzark Acres, Arkansas\r\n966\r\nPalarm, Arkansas\r\n851\r\nPangburn, Arkansas\r\n728\r\nParagould, Arkansas\r\n236\r\n239\r\n573\r\n586\r\nParis, Arkansas\r\n963\r\nParkin, Arkansas\r\n755\r\nParon, Arkansas\r\n594\r\nPayneway, Arkansas\r\n593\r\nPea Ridge, Arkansas\r\n451\r\nPerry, Arkansas\r\n662\r\nPerryville, Arkansas\r\n889\r\nPiggott, Arkansas\r\n598\r\nPine Bluff, Arkansas\r\n247\r\n534\r\n535\r\n536\r\n540\r\n541\r\n543\r\n550\r\n551\r\n879\r\nPinnacle, Arkansas\r\n868\r\nPlainview, Arkansas\r\n272\r\nPleasant Grove, Arkansas\r\n652\r\nPleasnt Pls, Arkansas\r\n345\r\nPocahontas, Arkansas\r\n892\r\nPollard, Arkansas\r\n544\r\nPonca, Arkansas\r\n861\r\nPortland, Arkansas\r\n737\r\nPrairie Grove, Arkansas\r\n846\r\nPrattsville, Arkansas\r\n699\r\nPrescott, Arkansas\r\n887\r\nPrim, Arkansas\r\n948\r\nPyatt, Arkansas\r\n427\r\nQuitman, Arkansas\r\n589\r\nRatcliff, Arkansas\r\n635\r\nRector, Arkansas\r\n595\r\nRedfield, Arkansas\r\n397\r\nRison, Arkansas\r\n325\r\nRoe, Arkansas\r\n241\r\nRogers, Arkansas\r\n621\r\n631\r\n640\r\n636\r\n659\r\n925\r\nRose Bud, Arkansas\r\n556\r\nRosston, Arkansas\r\n871\r\nRowell, Arkansas\r\n357\r\nRudd, Arkansas\r\n545\r\nRussellville, Arkansas\r\n890\r\n964\r\n967\r\n968\r\n970\r\nSalem, Arkansas\r\n895\r\nSalus, Arkansas\r\n292\r\nSaratoga, Arkansas\r\n388\r\nScotland, Arkansas\r\n592\r\nScott, Arkansas\r\n961\r\nScranton, Arkansas\r\n938\r\nSearcy, Arkansas\r\n268\r\n278\r\n279\r\nSheridan, Arkansas\r\n942\r\nShirley, Arkansas\r\n723\r\nSiloam Springs, Arkansas\r\n524\r\nSmackover, Arkansas\r\n725\r\nSouth Fourche, Arkansas\r\n440\r\nSouth Myrtle, Arkansas\r\n937\r\nSouth W, Arkansas\r\n822\r\nSparkman, Arkansas\r\n678\r\nSpringdale, Arkansas\r\n290\r\n361\r\n750\r\n751\r\n756\r\n770\r\n820\r\n872\r\nSpringlake, Arkansas\r\n888\r\nSaint Charles, Arkansas\r\n282\r\nSaint Joe, Arkansas\r\n439\r\nSaint Paul, Arkansas\r\n677\r\nStamps, Arkansas\r\n533\r\nStar City, Arkansas\r\n628\r\nStephens, Arkansas\r\n786\r\nStrickler, Arkansas\r\n761\r\nStrong, Arkansas\r\n797\r\nStuttgart, Arkansas\r\n672\r\n673\r\n830\r\nSubiaco, Arkansas\r\n934\r\nSuccess, Arkansas\r\n276\r\nSulphur Spring, Arkansas\r\n298\r\nSunnyland, Arkansas\r\n591\r\nSwifton, Arkansas\r\n485\r\nSylvianshrwd, Arkansas\r\n834\r\n835\r\nTaylor, Arkansas\r\n694\r\nTexarkana, Arkansas\r\n772\r\n773\r\n774\r\n779\r\nTillar, Arkansas\r\n392\r\nTimbo, Arkansas\r\n746\r\nTracy Fry, Arkansas\r\n491\r\nTrailback, Arkansas\r\n549\r\nTrigg, Arkansas\r\n645\r\nTrumann, Arkansas\r\n483\r\nTuckerman, Arkansas\r\n349\r\nTupelo, Arkansas\r\n744\r\nTurrell, Arkansas\r\n343\r\nTyronza, Arkansas\r\n487\r\nUmpire, Arkansas\r\n583\r\nUrbana, Arkansas\r\n962\r\nVan Buren, Arkansas\r\n471\r\n474\r\nVillage, Arkansas\r\n596\r\nVilonia, Arkansas\r\n796\r\nViola, Arkansas\r\n458\r\nWest Memphis, Arkansas\r\n732\r\n733\r\n735\r\nWaldenburg, Arkansas\r\n579\r\nWaldo, Arkansas\r\n693\r\nWaldron, Arkansas\r\n637\r\nWalnut Ridge, Arkansas\r\n886\r\nWarren, Arkansas\r\n226\r\nWashington, Arkansas\r\n983\r\nWatson, Arkansas\r\n644\r\nWeiner, Arkansas\r\n684\r\nWest Fork, Arkansas\r\n839\r\nWestern Grove, Arkansas\r\n429\r\nWheatley, Arkansas\r\n457\r\nWhiteville, Arkansas\r\n430\r\nWickes, Arkansas\r\n385\r\nWilmar, Arkansas\r\n469\r\nWilmot, Arkansas\r\n473\r\nWilson, Arkansas\r\n655\r\nWinslow, Arkansas\r\n634\r\nWinthrop, Arkansas\r\n381\r\nWitts Springs, Arkansas\r\n496\r\nWrightsville, Arkansas\r\n897\r\nWye, Arkansas\r\n330\r\nWynne, Arkansas\r\n238\r\nYellville, Arkansas\r\n449\r\n\u00035Unknown prefix code (501) - Arkansas\r\n"
  },
  {
    "path": "install/regions/regions.502",
    "content": "Adairville, Kentucky\r\n539\r\nArlington, Kentucky\r\n655\r\nAuburn, Kentucky\r\n542\r\nAurora, Kentucky\r\n474\r\nBagdad, Kentucky\r\n747\r\nBandana, Kentucky\r\n224\r\nBardstown, Kentucky\r\n348\r\n349\r\nBardwell, Kentucky\r\n628\r\nBarlow, Kentucky\r\n334\r\nBattletown, Kentucky\r\n497\r\nBeaver Dam, Kentucky\r\n274\r\nBedford, Kentucky\r\n255\r\nBee Spring, Kentucky\r\n286\r\nBenton, Kentucky\r\n527\r\nBessiebend, Kentucky\r\n238\r\nBloomfield, Kentucky\r\n252\r\nBluff Springs, Kentucky\r\n269\r\nBradfordsville, Kentucky\r\n337\r\nBrandenburg, Kentucky\r\n422\r\nBremen, Kentucky\r\n525\r\nBrownsville, Kentucky\r\n597\r\nBurkesville, Kentucky\r\n433\r\n864\r\nCadiz, Kentucky\r\n522\r\nCalhoun, Kentucky\r\n273\r\nCalvert City, Kentucky\r\n395\r\nCampbellsburg, Kentucky\r\n532\r\nCaneyville, Kentucky\r\n879\r\nCanton, Kentucky\r\n924\r\nCarrollton, Kentucky\r\n732\r\nCayce, Kentucky\r\n838\r\nCenter, Kentucky\r\n565\r\nCentertown, Kentucky\r\n232\r\nCentral City, Kentucky\r\n754\r\nChaplin, Kentucky\r\n673\r\nClarkson, Kentucky\r\n242\r\nClay, Kentucky\r\n664\r\nClinton, Kentucky\r\n653\r\nCloverport, Kentucky\r\n788\r\nColumbia, Kentucky\r\n384\r\nColumbus, Kentucky\r\n677\r\nCorydon, Kentucky\r\n533\r\nCrofton, Kentucky\r\n424\r\nCropper, Kentucky\r\n461\r\nCunningham, Kentucky\r\n642\r\nCuster, Kentucky\r\n536\r\nDawson Springs, Kentucky\r\n797\r\nDixon, Kentucky\r\n639\r\nDrakesboro, Kentucky\r\n476\r\nDunmor, Kentucky\r\n657\r\nEarlington, Kentucky\r\n383\r\nEddyville, Kentucky\r\n388\r\nEdmonton, Kentucky\r\n432\r\nElkton, Kentucky\r\n265\r\nEminence, Kentucky\r\n845\r\n878\r\nEnsor, Kentucky\r\n281\r\nFairdealing, Kentucky\r\n354\r\nFairplay, Kentucky\r\n378\r\nFancy Farm, Kentucky\r\n623\r\nFarmington, Kentucky\r\n345\r\nFinchville, Kentucky\r\n834\r\nFolsomdale, Kentucky\r\n856\r\nFordsville, Kentucky\r\n276\r\nFountain Run, Kentucky\r\n434\r\nFrankfort, Kentucky\r\n223\r\n226\r\n227\r\n564\r\n695\r\n875\r\nFranklin, Kentucky\r\n586\r\nFredonia, Kentucky\r\n545\r\nFulton, Kentucky\r\n468\r\n472\r\nGage, Kentucky\r\n876\r\nGamaliel, Kentucky\r\n457\r\nGeorgetown, Kentucky\r\n863\r\n867\r\n868\r\nGhent, Kentucky\r\n347\r\nGilbertsville, Kentucky\r\n362\r\nGracey, Kentucky\r\n235\r\nGreenville, Kentucky\r\n338\r\nGuthrie, Kentucky\r\n483\r\nHabit, Kentucky\r\n729\r\nHanson, Kentucky\r\n322\r\nHardin, Kentucky\r\n437\r\nHardinsburg, Kentucky\r\n756\r\nHartford, Kentucky\r\n298\r\nHawesville, Kentucky\r\n927\r\nHazel, Kentucky\r\n492\r\nHeath, Kentucky\r\n488\r\nHebbardsville, Kentucky\r\n546\r\nHenderson, Kentucky\r\n823\r\n826\r\n827\r\n831\r\n832\r\nHickman, Kentucky\r\n236\r\nHiseville, Kentucky\r\n453\r\nHopkinsville, Kentucky\r\n885\r\n886\r\n887\r\n889\r\nHorse Cave, Kentucky\r\n786\r\nIrvington, Kentucky\r\n547\r\nIsland, Kentucky\r\n486\r\nJamestown, Kentucky\r\n343\r\nJordan, Kentucky\r\n883\r\nKevil, Kentucky\r\n462\r\nKirksey, Kentucky\r\n489\r\nLa Center, Kentucky\r\n665\r\nLa Fayette, Kentucky\r\n271\r\nLa Grange, Kentucky\r\n222\r\nLawrenceburg, Kentucky\r\n839\r\nLebanon, Kentucky\r\n692\r\nLebanonjct, Kentucky\r\n833\r\nLeitchfld, Kentucky\r\n259\r\nLewisburg, Kentucky\r\n755\r\nLewisport, Kentucky\r\n295\r\nLivermore, Kentucky\r\n278\r\nLogansport, Kentucky\r\n728\r\nLoretto, Kentucky\r\n865\r\nLouisville, Kentucky\r\n228\r\n231\r\n239\r\n241\r\n244\r\n245\r\n254\r\n263\r\n266\r\n267\r\n327\r\n329\r\n332\r\n336\r\n339\r\n361\r\n363\r\n364\r\n366\r\n367\r\n368\r\n375\r\n421\r\n423\r\n425\r\n426\r\n429\r\n447\r\n448\r\n449\r\n451\r\n452\r\n454\r\n455\r\n456\r\n458\r\n459\r\n464\r\n473\r\n478\r\n491\r\n495\r\n499\r\n540\r\n551\r\n552\r\n553\r\n558\r\n560\r\n561\r\n562\r\n566\r\n568\r\n569\r\n571\r\n572\r\n574\r\n580\r\n581\r\n582\r\n583\r\n584\r\n585\r\n587\r\n588\r\n589\r\n592\r\n593\r\n595\r\n596\r\n625\r\n627\r\n629\r\n634\r\n635\r\n636\r\n637\r\n648\r\n649\r\n679\r\n681\r\n682\r\n772\r\n774\r\n775\r\n776\r\n778\r\n852\r\n899\r\n893\r\n894\r\n895\r\n896\r\n897\r\n933\r\n935\r\n937\r\n962\r\n964\r\n966\r\n968\r\n969\r\n976\r\nLowes, Kentucky\r\n674\r\nLucas, Kentucky\r\n646\r\nLynn Grove, Kentucky\r\n435\r\nLynnville, Kentucky\r\n382\r\nMaceo, Kentucky\r\n264\r\nMadisonville, Kentucky\r\n821\r\n824\r\n825\r\nMamoth Cove, Kentucky\r\n758\r\nMarion, Kentucky\r\n965\r\nMayfield, Kentucky\r\n247\r\n251\r\nMcdaniels, Kentucky\r\n257\r\nMilburn, Kentucky\r\n694\r\nMilton, Kentucky\r\n268\r\nMorganfield, Kentucky\r\n389\r\nMorgantown, Kentucky\r\n526\r\nMortons Gap, Kentucky\r\n258\r\nMount Eden, Kentucky\r\n738\r\nMount Washington, Kentucky\r\n538\r\nMurray, Kentucky\r\n753\r\n759\r\n762\r\n767\r\nNebo, Kentucky\r\n249\r\nNew Haven, Kentucky\r\n549\r\nNew Concord, Kentucky\r\n436\r\nNew Liberty, Kentucky\r\n463\r\nNorth Garrett, Kentucky\r\n828\r\nNortonville, Kentucky\r\n676\r\nOak Grove, Kentucky\r\n439\r\n798\r\nOwenton, Kentucky\r\n484\r\nPanther, Kentucky\r\n785\r\nPark City, Kentucky\r\n749\r\nPayneville, Kentucky\r\n496\r\nPembroke, Kentucky\r\n475\r\nPleasant Ridge, Kentucky\r\n275\r\nPort Royal, Kentucky\r\n947\r\nPrinceton, Kentucky\r\n365\r\nProvidence, Kentucky\r\n667\r\nRadcliff, Kentucky\r\n351\r\n352\r\nRobards, Kentucky\r\n521\r\nRochester, Kentucky\r\n934\r\nRose Terrace, Kentucky\r\n624\r\n942\r\n943\r\nRussellville, Kentucky\r\n726\r\nRussel Springs, Kentucky\r\n866\r\nSacramento, Kentucky\r\n736\r\nSadieville, Kentucky\r\n857\r\nSalem, Kentucky\r\n988\r\nScottsville, Kentucky\r\n237\r\n622\r\nSebree, Kentucky\r\n835\r\nSedalia, Kentucky\r\n328\r\nSharon Grove, Kentucky\r\n277\r\nShelbyville, Kentucky\r\n633\r\n647\r\nShepherdville, Kentucky\r\n543\r\nSimpsonville, Kentucky\r\n722\r\nSlaughters, Kentucky\r\n884\r\nSmithland, Kentucky\r\n928\r\nSmiths Grove, Kentucky\r\n563\r\nSorgho, Kentucky\r\n771\r\nSaint Charles, Kentucky\r\n669\r\nStamping Ground, Kentucky\r\n535\r\nStanley, Kentucky\r\n764\r\nSturgis, Kentucky\r\n333\r\nSulphur, Kentucky\r\n743\r\nSumershade, Kentucky\r\n428\r\nSymsonia, Kentucky\r\n851\r\nTaylorsville, Kentucky\r\n477\r\nTemplehill, Kentucky\r\n427\r\nTompkinsville, Kentucky\r\n487\r\nTrenton, Kentucky\r\n466\r\nUniontown, Kentucky\r\n822\r\nUtica, Kentucky\r\n733\r\nVine Grove, Kentucky\r\n877\r\nWest Louisville, Kentucky\r\n229\r\nWaddy, Kentucky\r\n829\r\nWater Valley, Kentucky\r\n355\r\nWest Point, Kentucky\r\n922\r\nWestplains, Kentucky\r\n658\r\nWhitesville, Kentucky\r\n233\r\nWickliffe, Kentucky\r\n335\r\nWingo, Kentucky\r\n376\r\nWoodburn, Kentucky\r\n529\r\nZoneton, Kentucky\r\n955\r\n957\r\n\u00035Unknown prefix code (502) - Kentucky\r\n"
  },
  {
    "path": "install/regions/regions.503",
    "content": "Adrian, Oregon\r\n724\r\nAlbany, Oregon\r\n924\r\n926\r\n928\r\n967\r\n979\r\n990\r\nAloha, Orgeon\r\n649\r\nAlsea, Oregon\r\n487\r\nAmity, Oregon\r\n835\r\nAntelope, Oregon\r\n489\r\nArlington, Oregon\r\n454\r\nAsh Valley, Oregon\r\n599\r\nAshland, Oregon\r\n482\r\n488\r\n552\r\nAstoria, Oregon\r\n325\r\n338\r\n791\r\nAthena, Oregon\r\n566\r\nAurora, Oregon\r\n678\r\nAvmsviltrn, Oregon\r\n743\r\n749\r\nAzalea, Oregon\r\n837\r\nBaker, Oregon\r\n523\r\nBandon, Oregon\r\n347\r\nBates, Oregon\r\n448\r\nBay City, Oregon\r\n377\r\nBeaver Creek, Oregon\r\n632\r\nBeaver, Oregon\r\n398\r\nBeaverton, Oregon\r\n520\r\n524\r\n526\r\n531\r\n550\r\n578\r\n579\r\n591\r\n626\r\n627\r\n629\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n671\r\n677\r\n690\r\nBell Fountain, Oregon\r\n424\r\nBend, Oregon\r\n382\r\n383\r\n385\r\n388\r\n389\r\n420\r\n480\r\n540\r\n593\r\nBlodgett, Oregon\r\n453\r\nBlue River, Oregon\r\n822\r\nBly, Oregon\r\n353\r\nBoardman, Oregon\r\n481\r\nBonanza, Oregon\r\n545\r\nBrookings, Oregon\r\n469\r\nBrownsville, Oregon\r\n466\r\nBurlington, Oregon\r\n621\r\nBurns, Oregon\r\n573\r\nButte Falls, Oregon\r\n865\r\nCamas Valley, Oregon\r\n445\r\nCanby, Oregon\r\n263\r\n266\r\n651\r\nCannon Beach, Oregon\r\n436\r\nCanyonville, Oregon\r\n839\r\nCarlton, Oregon\r\n852\r\nCascade Lake, Oregon\r\n374\r\nCave Junction, Oregon\r\n592\r\nCentral Point, Oregon\r\n664\r\nCharboneau, Oregon\r\n694\r\nChemult, Oregon\r\n365\r\nChiloquin, Oregon\r\n783\r\nChitwood, Oregon\r\n875\r\nClackamas, Oregon\r\n786\r\nClatskanie, Oregon\r\n728\r\nCloverdale, Oregon\r\n392\r\nCmp Shermn, Oregon\r\n595\r\nColton, Oregon\r\n824\r\nCondon, Oregon\r\n384\r\nConnor Creek, Oregon\r\n675\r\nCoos Bay, Oregon\r\n264\r\n267\r\n269\r\n751\r\n756\r\n888\r\nCoquille, Oregon\r\n396\r\nCorbett, Oregon\r\n695\r\nCorvallis, Oregon\r\n737\r\n740\r\n745\r\n750\r\n752\r\n753\r\n754\r\n757\r\n758\r\nCottage Grove, Oregon\r\n942\r\n946\r\nCove, Oregon\r\n568\r\nCraterlake, Oregon\r\n594\r\nCreswell, Oregon\r\n895\r\nCulver, Oregon\r\n546\r\nDallas, Oregon\r\n623\r\nDays Creek, Oregon\r\n825\r\nDayton, Oregon\r\n864\r\nDayville, Oregon\r\n987\r\nDeadwood, Oregon\r\n964\r\nDepoe Bay, Oregon\r\n589\r\n764\r\n765\r\nDetroit, Oregon\r\n854\r\nDiamond Lake, Oregon\r\n793\r\nDrain, Oregon\r\n836\r\nDufur, Oregon\r\n467\r\nDurkee, Oregon\r\n877\r\nEcho, Oregon\r\n376\r\nElgin, Oregon\r\n437\r\nElkton, Oregon\r\n584\r\nEnterprise, Oregon\r\n426\r\nEstacada, Oregon\r\n630\r\n637\r\nEugene, Oregon\r\n334\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n461\r\n465\r\n484\r\n485\r\n683\r\n686\r\n687\r\n688\r\n689\r\n726\r\n729\r\n741\r\n744\r\n746\r\n747\r\n953\r\n954\r\nFalls City, Oregon\r\n787\r\nFish Lake, Oregon\r\n949\r\nFlora Troy, Oregon\r\n828\r\nFlorence, Oregon\r\n991\r\n997\r\n999\r\nForest Grove, Oregon\r\n324\r\n357\r\n359\r\n985\r\nFossil, Oregon\r\n763\r\nFort Klamath, Oregon\r\n381\r\nGaribaldi, Oregon\r\n322\r\nGervais, Oregon\r\n792\r\nGilchrist, Oregon\r\n433\r\nGlendale, Oregon\r\n832\r\nGlide, Oregon\r\n496\r\nGold Beach, Oregon\r\n247\r\nGold Hill, Oregon\r\n855\r\nGovernment Camp, Oregon\r\n272\r\nGrand Island, Oregon\r\n868\r\nGrandronde, Oregon\r\n879\r\nGrants Pass, Oregon\r\n450\r\n471\r\n474\r\n476\r\n479\r\n660\r\n851\r\n955\r\nGrass Valley, Oregon\r\n333\r\nGresham, Oregon\r\n492\r\n661\r\n663\r\n665\r\n666\r\n667\r\n669\r\nHaines, Oregon\r\n856\r\nHalfway, Oregon\r\n742\r\nHalsey, Oregon\r\n369\r\nHarlan, Oregon\r\n438\r\nHarper, Oregon\r\n358\r\nHarrisburg, Oregon\r\n995\r\nHelix, Oregon\r\n457\r\nHeppner, Oregon\r\n676\r\nHerefdunty, Oregon\r\n446\r\nHermiston, Oregon\r\n561\r\n564\r\n567\r\nHillsboro, Oregon\r\n640\r\n648\r\n681\r\n693\r\n696\r\nHood Land, Oregon\r\n622\r\nHood River, Oregon\r\n349\r\n386\r\n387\r\n490\r\nHorton, Oregon\r\n925\r\nHuntington, Oregon\r\n869\r\nImbler, Oregon\r\n534\r\nIndependence, Oregon\r\n838\r\nIone, Oregon\r\n422\r\nJacksonville, Oregon\r\n899\r\nJefferson, Oregon\r\n327\r\nJewell, Oregon\r\n755\r\nJohn Day, Oregon\r\n575\r\nJordan Valley, Oregon\r\n586\r\nJoseph, Oregon\r\n432\r\n577\r\nJunction City, Oregon\r\n998\r\nJuntura, Oregon\r\n277\r\nKlamath Falls, Oregon\r\n850\r\n882\r\n883\r\n884\r\n885\r\n891\r\n892\r\nKnappa, Oregon\r\n458\r\nLa Grande, Oregon\r\n962\r\n963\r\nLake Oswego, Oregon\r\n635\r\n636\r\n697\r\n699\r\nLakeside, Oregon\r\n759\r\nLakeview, Oregon\r\n947\r\nLanglois, Oregon\r\n348\r\nLapine, Oregon\r\n536\r\nLeaburg, Oregon\r\n896\r\nLebanon, Oregon\r\n258\r\n259\r\n451\r\nLexington, Oregon\r\n989\r\nLincoln City, Oregon\r\n921\r\n992\r\n994\r\n996\r\nLobster Valley, Oregon\r\n486\r\nLong Creek, Oregon\r\n421\r\nLostine, Oregon\r\n569\r\nLowell, Oregon\r\n937\r\nLyons, Oregon\r\n859\r\nMadras, Oregon\r\n475\r\n553\r\nMalin, Oregon\r\n723\r\nMapleton, Oregon\r\n268\r\nMarcola, Oregon\r\n933\r\nMaupin, Oregon\r\n395\r\nMcMinnville, Oregon\r\n434\r\n472\r\nMeacham, Oregon\r\n983\r\nMedford, Oregon\r\n734\r\n770\r\n772\r\n773\r\n776\r\n779\r\n821\r\n840\r\n857\r\n890\r\n944\r\nMedical Spring, Oregon\r\n853\r\nMerrill, Oregon\r\n798\r\nMill City, Oregon\r\n897\r\nMitchell, Oregon\r\n462\r\nMltn Freewater, Oregon\r\n938\r\nMolalla, Oregon\r\n829\r\nMonitor, Oregon\r\n634\r\nMonroe, Oregon\r\n847\r\nMonument, Oregon\r\n934\r\nMoro, Oregon\r\n565\r\nMosier, Oregon\r\n478\r\nMount Angel, Oregon\r\n845\r\nMount Hood, Oregon\r\n337\r\nMount Vernon, Oregon\r\n932\r\nMyrtle Creek, Oregon\r\n863\r\nMyrtle Point, Oregon\r\n572\r\nNehalem, Oregon\r\n368\r\nNewberg, Oregon\r\n537\r\n538\r\nNewport, Oregon\r\n265\r\n270\r\n574\r\n961\r\nNorth Harney, Oregon\r\n493\r\nNorth Plains, Oregon\r\n647\r\nNorth Powder, Oregon\r\n898\r\nNorth Umpqua, Oregon\r\n498\r\nNyssa, Oregon\r\n372\r\nO Brien, Oregon\r\n596\r\nOakgrove Mill, Oregon\r\n652\r\n653\r\n654\r\n659\r\n794\r\nOakland, Oregon\r\n459\r\nOakridge, Oregon\r\n782\r\nOdell, Oregon\r\n354\r\nOntario, Oregon\r\n881\r\n889\r\nOregon City, Oregon\r\n557\r\n650\r\n655\r\n656\r\n657\r\nOregonslope, Oregon\r\n262\r\nOxbow, Oregon\r\n785\r\nPacific Cy, Oregon\r\n965\r\nPaisley, Oregon\r\n943\r\nParkdale, Oregon\r\n352\r\nPaulina, Oregon\r\n477\r\nPendleton, Oregon\r\n276\r\n278\r\n379\r\n380\r\n966\r\n969\r\nPhilomath, Oregon\r\n929\r\nPhoenix, Oregon\r\n535\r\nPilot Rock, Oregon\r\n428\r\n443\r\nPine Grove, Oregon\r\n328\r\nPortland, Oregon\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n260\r\n261\r\n273\r\n274\r\n275\r\n279\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n291\r\n292\r\n293\r\n294\r\n295\r\n297\r\n299\r\n307\r\n320\r\n321\r\n323\r\n326\r\n329\r\n331\r\n335\r\n340\r\n423\r\n425\r\n441\r\n452\r\n464\r\n494\r\n497\r\n499\r\n539\r\n555\r\n720\r\n721\r\n725\r\n727\r\n731\r\n733\r\n735\r\n760\r\n761\r\n762\r\n768\r\n771\r\n774\r\n775\r\n777\r\n778\r\n780\r\n781\r\n784\r\n788\r\n789\r\n790\r\n795\r\n796\r\n797\r\n799\r\n823\r\n827\r\n833\r\n860\r\n870\r\n880\r\n887\r\n936\r\n939\r\n940\r\n960\r\n970\r\n976\r\n977\r\n978\r\nPortorford, Oregon\r\n332\r\nPowers, Oregon\r\n439\r\nPrairie City, Oregon\r\n820\r\nPrineville, Oregon\r\n447\r\nProspect, Oregon\r\n560\r\nPrvltmrphy, Oregon\r\n846\r\n862\r\nQuinn, Oregon\r\n522\r\nRainier, Oregon\r\n556\r\nRedland, Oregon\r\n631\r\nRedmond, Oregon\r\n548\r\n923\r\nReedsport, Oregon\r\n271\r\nRichland, Oregon\r\n893\r\nRiddle, Oregon\r\n874\r\nRidgeview, Oregon\r\n339\r\nRipplebreak, Oregon\r\n834\r\nRockaway, Oregon\r\n355\r\nRockypoint, Oregon\r\n356\r\nRogue River, Oregon\r\n582\r\nRoseburg, Oregon\r\n430\r\n440\r\n670\r\n672\r\n673\r\n679\r\n844\r\n957\r\nRufus, Oregon\r\n739\r\nSalem, Oregon\r\n361\r\n362\r\n363\r\n364\r\n370\r\n371\r\n373\r\n375\r\n378\r\n390\r\n391\r\n393\r\n399\r\n463\r\n559\r\n580\r\n581\r\n585\r\n588\r\n871\r\n930\r\n931\r\n945\r\n986\r\nSandy, Oregon\r\n668\r\nScappoose, Oregon\r\n543\r\nScholls, Oregon\r\n628\r\nScio, Oregon\r\n394\r\nScottsburg, Oregon\r\n587\r\nSeaside, Oregon\r\n738\r\nSelma, Oregon\r\n597\r\nSeneca, Oregon\r\n542\r\nShady Cove, Oregon\r\n878\r\nShedd, Oregon\r\n491\r\nSheridan, Oregon\r\n843\r\nSherwood, Oregon\r\n625\r\nSiletz, Oregon\r\n444\r\nSilverlake, Oregon\r\n576\r\nSilverton, Oregon\r\n873\r\nSisters, Oregon\r\n549\r\nSouth Harney, Oregon\r\n495\r\nSouthbeach, Oregon\r\n867\r\nSprague River, Oregon\r\n533\r\nSpray, Oregon\r\n468\r\nSaint Helens, Oregon\r\n366\r\n397\r\nSaint Paul, Oregon\r\n633\r\nStafford, Oregon\r\n638\r\n682\r\n685\r\nStanfield, Oregon\r\n449\r\nStateline, Oregon\r\n558\r\nStayton, Oregon\r\n769\r\nSummit, Oregon\r\n456\r\nSumpter, Oregon\r\n894\r\nSunnyside, Oregon\r\n658\r\n698\r\nSweet Home, Oregon\r\n367\r\nThe Dalles, Oregon\r\n296\r\n298\r\n980\r\n993\r\nTidewater, Oregon\r\n528\r\nTigard, Oregon\r\n590\r\n598\r\n620\r\n624\r\n639\r\n684\r\n691\r\n692\r\nTillamook, Oregon\r\n842\r\nToledo, Oregon\r\n336\r\nTriangle Lake, Oregon\r\n927\r\nTygh Valley, Oregon\r\n483\r\nUkiah, Oregon\r\n427\r\nUmatilla, Oregon\r\n922\r\nUnion, Oregon\r\n562\r\nVale, Oregon\r\n473\r\nVeneta, Oregon\r\n935\r\nVernonia, Oregon\r\n429\r\nWaldport, Oregon\r\n563\r\nWallowa, Oregon\r\n886\r\nWamic, Oregon\r\n544\r\nWarrenton, Oregon\r\n861\r\nWasco, Oregon\r\n442\r\nWestport, Oregon\r\n455\r\nWhite City, Oregon\r\n826\r\n830\r\nWillamina, Oregon\r\n876\r\nWolf Creek, Oregon\r\n866\r\nWoodburn, Oregon\r\n981\r\n982\r\nYachats, Oregon\r\n547\r\nYamhill, Oregon\r\n662\r\nYoncalla, Oregon\r\n849\r\n\u00035Unknown prefix code (503) - Oregon\r\n"
  },
  {
    "path": "install/regions/regions.504",
    "content": "Amite City, Louisiana\r\n748\r\nAngie, Louisiana\r\n986\r\nBogalusa, Louisiana\r\n732\r\n735\r\nBuras, Louisiana\r\n657\r\nBush, Louisiana\r\n886\r\nChackbay, Louisiana\r\n633\r\nCovington, Louisiana\r\n867\r\n892\r\n893\r\n898\r\nDelacroix, Louisiana\r\n684\r\nDonaldsonville, Louisiana\r\n473\r\n474\r\nDulac, Louisiana\r\n563\r\nEdgard, Louisiana\r\n497\r\nFolsom, Louisiana\r\n796\r\nFranklinton, Louisiana\r\n839\r\nGalliano, Louisiana\r\n632\r\nGaryville, Louisiana\r\n535\r\nGibson, Louisiana\r\n575\r\nGolden Meadow, Louisiana\r\n475\r\nGrand Isle, Louisiana\r\n787\r\nGreensburg, Louisiana\r\n222\r\nHammond, Louisiana\r\n345\r\n542\r\n543\r\n545\r\n549\r\nHouma, Louisiana\r\n850\r\n851\r\n854\r\n857\r\n868\r\n872\r\n873\r\n876\r\n879\r\nIndependence, Louisiana\r\n878\r\nJesuitbend, Louisiana\r\n656\r\nKenner, Louisiana\r\n431\r\n441\r\n443\r\n461\r\n462\r\n464\r\n465\r\n466\r\n467\r\n469\r\n471\r\n737\r\n738\r\n739\r\nKentwood, Louisiana\r\n229\r\nLabadieville, Louisiana\r\n526\r\nLacombe, Louisiana\r\n882\r\nLaf Louisville, Louisiana\r\n689\r\nLaplace, Louisiana\r\n651\r\n652\r\nLarose, Louisiana\r\n691\r\n693\r\n798\r\nLeeville, Louisiana\r\n396\r\nLake Catherine, Louisiana\r\n662\r\nLockport, Louisiana\r\n532\r\nLuling, Louisiana\r\n783\r\n785\r\nMadisonville, Louisiana\r\n845\r\nMandeville, Louisiana\r\n624\r\n626\r\nMetaire, Louisiana\r\n468\r\n773\r\nMontegut, Louisiana\r\n594\r\nMontpelier, Louisiana\r\n777\r\nMorgancity, Louisiana\r\n380\r\n384\r\n385\r\n631\r\nMount Hermon, Louisiana\r\n877\r\nNapoleonville, Louisiana\r\n369\r\nNew Orleans, Louisiana\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n253\r\n254\r\n255\r\n257\r\n260\r\n271\r\n277\r\n278\r\n279\r\n282\r\n283\r\n286\r\n288\r\n340\r\n341\r\n347\r\n348\r\n349\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n367\r\n368\r\n371\r\n391\r\n392\r\n393\r\n394\r\n398\r\n436\r\n437\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n482\r\n483\r\n484\r\n486\r\n488\r\n521\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n529\r\n544\r\n546\r\n547\r\n552\r\n553\r\n554\r\n556\r\n558\r\n561\r\n565\r\n566\r\n568\r\n569\r\n581\r\n582\r\n583\r\n584\r\n585\r\n586\r\n587\r\n588\r\n589\r\n592\r\n593\r\n595\r\n596\r\n597\r\n671\r\n731\r\n733\r\n734\r\n736\r\n762\r\n821\r\n822\r\n824\r\n826\r\n827\r\n830\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n838\r\n840\r\n841\r\n842\r\n861\r\n862\r\n864\r\n865\r\n866\r\n881\r\n883\r\n884\r\n885\r\n887\r\n888\r\n889\r\n891\r\n894\r\n895\r\n896\r\n897\r\n899\r\n941\r\n942\r\n943\r\n944\r\n945\r\n947\r\n948\r\n949\r\n976\r\nNew Roads, Louisiana\r\n638\r\nOffshore, Louisiana\r\n444\r\nParadis, Louisiana\r\n758\r\nPatterson, Louisiana\r\n395\r\nPearlington, Louisiana\r\n531\r\nPearl River, Louisiana\r\n863\r\nPierrepart, Louisiana\r\n252\r\nPine, Louisiana\r\n848\r\nPonchatola, Louisiana\r\n386\r\nPoint L, Louisiana\r\n333\r\nPoint Sulphur, Louisiana\r\n564\r\nRaceland, Louisiana\r\n537\r\nReserve, Louisiana\r\n479\r\n536\r\nSlidell, Louisiana\r\n641\r\n643\r\n645\r\n646\r\n649\r\n847\r\nSouthosyka, Louisiana\r\n548\r\nSaint Bernard, Louisiana\r\n682\r\nThibodaux, Louisiana\r\n446\r\n447\r\n448\r\n449\r\nVenice, Louisiana\r\n534\r\nWh Castle, Louisiana\r\n545\r\nYscloskey, Louisiana\r\n676\r\n\u00035Unknown prefix code (504) - Louisiana\r\n"
  },
  {
    "path": "install/regions/regions.505",
    "content": "Abiquiu, New Mexico\r\n685\r\nAlamogordo, New Mexico\r\n430\r\n431\r\n434\r\n437\r\n439\r\n475\r\n479\r\nAlbuquerque, New Mexico\r\n555\r\n222\r\n224\r\n237\r\n242\r\n243\r\n245\r\n246\r\n247\r\n248\r\n249\r\n250\r\n251\r\n252\r\n254\r\n255\r\n256\r\n260\r\n262\r\n263\r\n264\r\n265\r\n266\r\n268\r\n269\r\n271\r\n272\r\n275\r\n277\r\n291\r\n292\r\n293\r\n294\r\n296\r\n298\r\n299\r\n343\r\n344\r\n345\r\n761\r\n764\r\n765\r\n766\r\n768\r\n821\r\n822\r\n823\r\n828\r\n831\r\n833\r\n836\r\n837\r\n839\r\n841\r\n842\r\n843\r\n844\r\n845\r\n846\r\n848\r\n851\r\n853\r\n856\r\n857\r\n873\r\n877\r\n880\r\n881\r\n883\r\n884\r\n888\r\n889\r\n891\r\n892\r\n893\r\n896\r\n897\r\n898\r\n899\r\n923\r\n960\r\n976\r\nAlto, New Mexico\r\n336\r\nAngel Fire, New Mexico\r\n377\r\nAnimas, New Mexico\r\n548\r\nAntelope Ridge, New Mexico\r\n225\r\nAnthony, New Mexico\r\n882\r\nAntonchico, New Mexico\r\n427\r\nArch, New Mexico\r\n276\r\nArtesia, New Mexico\r\n746\r\n748\r\nAztec, New Mexico\r\n334\r\n632\r\nBayard, New Mexico\r\n537\r\nBelen, New Mexico\r\n861\r\n864\r\nBellview, New Mexico\r\n456\r\nBernalillo, New Mexico\r\n867\r\nBingham, New Mexico\r\n423\r\nCanjilon, New Mexico\r\n684\r\nCapitan, New Mexico\r\n354\r\nCarlsbad, New Mexico\r\n234\r\n236\r\n885\r\n887\r\nCarlsbad Cavern, New Mexico\r\n785\r\nCarrizozo, New Mexico\r\n648\r\nCausey, New Mexico\r\n273\r\nChama, New Mexico\r\n756\r\nChaparral, New Mexico\r\n824\r\nChimayo, New Mexico\r\n351\r\nCimarron, New Mexico\r\n376\r\nClayton, New Mexico\r\n374\r\nCliff, New Mexico\r\n535\r\nCloudcroft, New Mexico\r\n682\r\nClovis, New Mexico\r\n791\r\n762\r\n763\r\n769\r\n784\r\nColumbus, New Mexico\r\n531\r\n549\r\nConchas Dam, New Mexico\r\n868\r\nCorona, New Mexico\r\n849\r\nCottonwood, New Mexico\r\n365\r\nCrown Point, New Mexico\r\n786\r\nCuba, New Mexico\r\n289\r\nDatil, New Mexico\r\n772\r\nDell City, New Mexico\r\n963\r\nDeming, New Mexico\r\n544\r\n546\r\nDes Moines, New Mexico\r\n278\r\nDexter, New Mexico\r\n734\r\nDixon, New Mexico\r\n579\r\nDora, New Mexico\r\n477\r\nDulce, New Mexico\r\n759\r\nEl Rito, New Mexico\r\n581\r\nEl Valle, New Mexico\r\n421\r\nElida, New Mexico\r\n274\r\nEspanola, New Mexico\r\n747\r\n753\r\nEstancia, New Mexico\r\n384\r\nEunice, New Mexico\r\n394\r\nFarmington, New Mexico\r\n320\r\n324\r\n325\r\n326\r\n327\r\n598\r\n599\r\n860\r\nFence Lake, New Mexico\r\n788\r\nFloyd, New Mexico\r\n478\r\nFort Sumner, New Mexico\r\n355\r\nGallina, New Mexico\r\n638\r\nGallup, New Mexico\r\n979\r\n488\r\n722\r\n862\r\n863\r\nGlenwood, New Mexico\r\n539\r\nGrady, New Mexico\r\n357\r\nGrants, New Mexico\r\n285\r\n287\r\n876\r\nGuadalupe Park, New Mexico\r\n826\r\nHagerman, New Mexico\r\n752\r\nHatch, New Mexico\r\n267\r\nHillsboro, New Mexico\r\n895\r\nHobbs, New Mexico\r\n369\r\n390\r\n391\r\n392\r\n393\r\n397\r\nHondo, New Mexico\r\n653\r\nHope, New Mexico\r\n484\r\nHouse, New Mexico\r\n279\r\nJal, New Mexico\r\n395\r\nJemez Springs, New Mexico\r\n829\r\nKenton, New Mexico\r\n451\r\nLa Mesa, New Mexico\r\n233\r\nLagunacoma, New Mexico\r\n552\r\nLakewood, New Mexico\r\n457\r\nLas Cruces, New Mexico\r\n382\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n642\r\n644\r\n645\r\n646\r\n678\r\n679\r\nLas Vegas, New Mexico\r\n425\r\n454\r\nLindrith, New Mexico\r\n774\r\nLoco Hills, New Mexico\r\n677\r\nLogan, New Mexico\r\n487\r\nLordsburg, New Mexico\r\n542\r\nLos Alamos, New Mexico\r\n660\r\n661\r\n662\r\n665\r\n667\r\n669\r\nLos Lunas, New Mexico\r\n865\r\n866\r\n869\r\nLoving, New Mexico\r\n745\r\nLovington, New Mexico\r\n396\r\nLuna, New Mexico\r\n547\r\nLybrook, New Mexico\r\n568\r\nMagdalena, New Mexico\r\n854\r\nMaljamar, New Mexico\r\n676\r\nMaxwell, New Mexico\r\n375\r\nMayhill, New Mexico\r\n687\r\nMelrose, New Mexico\r\n253\r\nMescalero, New Mexico\r\n671\r\nMilnesand, New Mexico\r\n675\r\nMimbres, New Mexico\r\n536\r\nMora, New Mexico\r\n387\r\nMoriarty, New Mexico\r\n832\r\nMosquero, New Mexico\r\n673\r\nMountainair, New Mexico\r\n847\r\nNara Visa, New Mexico\r\n633\r\nNaschitti, New Mexico\r\n732\r\nNavajo, New Mexico\r\n777\r\nNewcomb, New Mexico\r\n696\r\nOjocliente, New Mexico\r\n583\r\nPecos, New Mexico\r\n757\r\nPenablanca, New Mexico\r\n465\r\nPenasco, New Mexico\r\n587\r\nPine Hill, New Mexico\r\n775\r\nPlayas, New Mexico\r\n436\r\nPleasant Hill, New Mexico\r\n389\r\n760\r\nPortales, New Mexico\r\n356\r\n359\r\n562\r\nPueblo Pntd, New Mexico\r\n655\r\nQueen, New Mexico\r\n981\r\nQuemado, New Mexico\r\n773\r\nQuesta, New Mexico\r\n586\r\nRagland, New Mexico\r\n458\r\nRamah, New Mexico\r\n783\r\nRanchvale, New Mexico\r\n985\r\nRaton, New Mexico\r\n447\r\n445\r\nRed River, New Mexico\r\n754\r\nReserve, New Mexico\r\n533\r\nRodeo, New Mexico\r\n557\r\nRoswell, New Mexico\r\n420\r\n626\r\n627\r\n347\r\n622\r\n623\r\n624\r\n625\r\nRoy, New Mexico\r\n485\r\nRuidoso, New Mexico\r\n257\r\n258\r\nRuidosodwn, New Mexico\r\n378\r\nSan Jon, New Mexico\r\n576\r\nSan Ysidro, New Mexico\r\n834\r\nSanostee, New Mexico\r\n723\r\nSanta Fe, New Mexico\r\n470\r\n474\r\n690\r\n699\r\n820\r\n438\r\n455\r\n471\r\n473\r\n827\r\n982\r\n983\r\n984\r\n986\r\n988\r\n989\r\nSanta Rosa, New Mexico\r\n472\r\nShiprock, New Mexico\r\n368\r\nSilver City, New Mexico\r\n388\r\n538\r\nSanta Teresa, New Mexico\r\n589\r\n874\r\nSouth Clovis, New Mexico\r\n683\r\nSocorro, New Mexico\r\n835\r\nSpringer, New Mexico\r\n483\r\nTaos, New Mexico\r\n751\r\n758\r\n776\r\nTatum, New Mexico\r\n398\r\nTexico, New Mexico\r\n482\r\nTierraamar, New Mexico\r\n588\r\nTijeras, New Mexico\r\n281\r\nTimberon, New Mexico\r\n987\r\nToadlena, New Mexico\r\n789\r\nTohatchi, New Mexico\r\n733\r\nTorreon, New Mexico\r\n731\r\nTrementina, New Mexico\r\n641\r\nTrthcnsqnc, New Mexico\r\n740\r\n743\r\n744\r\n894\r\nTruchas, New Mexico\r\n689\r\nTse Bonito, New Mexico\r\n371\r\nTucumcari, New Mexico\r\n461\r\nTularosa, New Mexico\r\n585\r\nTwin Lakes, New Mexico\r\n735\r\nVallecitos, New Mexico\r\n582\r\nVanderwag, New Mexico\r\n778\r\nVaughn, New Mexico\r\n584\r\nVelarde, New Mexico\r\n852\r\nVirden, New Mexico\r\n358\r\nWagonmound, New Mexico\r\n666\r\nWeber City, New Mexico\r\n372\r\nWhite Rock, New Mexico\r\n672\r\nWhite Lakes, New Mexico\r\n422\r\nZuni, New Mexico\r\n782\r\n\u00035Unknown prefix code (505) - New Mexico\r\n"
  },
  {
    "path": "install/regions/regions.506",
    "content": "Albert, Nebraska\r\n882\r\nAllardville, Nebraska\r\n725\r\nAlma, Nebraska\r\n887\r\nBaiestanne, Nebraska\r\n228\r\nBakerbrook, Nebraska\r\n258\r\nBalmoral, Nebraska\r\n826\r\nBath, Nebraska\r\n278\r\nBathurst, Nebraska\r\n546\r\n547\r\n548\r\nBelledune, Nebraska\r\n522\r\n718\r\nBlacks Harbor, Nebraska\r\n456\r\nBlackville, Nebraska\r\n843\r\nBoiestown, Nebraska\r\n369\r\nBouctouche, Nebraska\r\n743\r\n955\r\nBrowns Flat, Nebraska\r\n468\r\nCampbellton, Nebraska\r\n753\r\n759\r\n789\r\n818\r\nCampobello, Nebraska\r\n752\r\nCanterbury, Nebraska\r\n279\r\nCap Pele, Nebraska\r\n577\r\nCaraquet, Nebraska\r\n726\r\n727\r\nCentreville, Nebraska\r\n276\r\nChatham, Nebraska\r\n773\r\n778\r\nChipman, Nebraska\r\n339\r\nClair, Nebraska\r\n992\r\nClarkscors, Nebraska\r\n385\r\nCocagne, Nebraska\r\n576\r\nDalhousie, Nebraska\r\n684\r\nDebec, Nebraska\r\n277\r\nDeerisland, Nebraska\r\n747\r\nDoaktown, Nebraska\r\n365\r\nDorchester, Nebraska\r\n379\r\nEdmundston, Nebraska\r\n735\r\n737\r\n739\r\n919\r\nFlorenceville, Nebraska\r\n392\r\nFordsmills, Nebraska\r\n785\r\nFosterville, Nebraska\r\n894\r\nFredericton Junction, Nebraska\r\n368\r\n443\r\n444\r\n447\r\n451\r\n450\r\n452\r\n453\r\n454\r\n455\r\n457\r\n458\r\n459\r\n472\r\n474\r\n515\r\n985\r\nGagetown, Nebraska\r\n488\r\nGlassville, Nebraska\r\n246\r\nGrand Anse, Nebraska\r\n732\r\nGrand Bay, Nebraska\r\n738\r\n757\r\nGrand Falls, Nebraska\r\n473\r\nGrand Manan, Nebraska\r\n662\r\nHampstead, Nebraska\r\n425\r\nHampton, Nebraska\r\n832\r\nHartland, Nebraska\r\n375\r\nHarvey Sta, Nebraska\r\n366\r\nHavelock, Nebraska\r\n534\r\nHillsbrgh, Nebraska\r\n734\r\nHoyt, Nebraska\r\n687\r\nJacquetriv, Nebraska\r\n237\r\nKedgwick, Nebraska\r\n284\r\nKeswick, Nebraska\r\n363\r\nLameque, Nebraska\r\n344\r\nMaces Bay, Nebraska\r\n659\r\nMcadam, Nebraska\r\n784\r\nMeductic, Nebraska\r\n272\r\nMemramcook, Nebraska\r\n758\r\nMillville, Nebraska\r\n463\r\nMinto, Nebraska\r\n327\r\nMoncton, Nebraska\r\n383\r\n851\r\n861\r\n862\r\n382\r\n384\r\n386\r\n387\r\n388\r\n389\r\n616\r\n852\r\n853\r\n854\r\n855\r\n856\r\n857\r\n858\r\n859\r\n982\r\nNackawic, Nebraska\r\n575\r\nNeguac, Nebraska\r\n776\r\nNewcastle, Nebraska\r\n622\r\n627\r\nNew Denmark, Nebraska\r\n553\r\nNorton, Nebraska\r\n839\r\nOromocto, Nebraska\r\n357\r\n422\r\n446\r\nPaquetville, Nebraska\r\n764\r\nPetitcodic, Nebraska\r\n756\r\nPetitrochr, Nebraska\r\n542\r\n783\r\nPlaster Rk, Nebraska\r\n356\r\nPort Elgin, Nebraska\r\n538\r\nPerth Andover, Nebraska\r\n273\r\nRed Bank, Nebraska\r\n836\r\nRichibucto, Nebraska\r\n523\r\nRogersville, Nebraska\r\n775\r\nRothesay, Nebraska\r\n847\r\n849\r\nSackville, Nebraska\r\n364\r\n536\r\nSaint John, Nebraska\r\n551\r\n557\r\n558\r\n634\r\n643\r\n644\r\n645\r\n653\r\n313\r\n632\r\n633\r\n635\r\n636\r\n642\r\n648\r\n652\r\n657\r\n658\r\n672\r\n674\r\n693\r\n694\r\n696\r\n983\r\nSalisbury, Nebraska\r\n372\r\nShediac, Nebraska\r\n532\r\n533\r\nShippegan, Nebraska\r\n336\r\nSpringfield, Nebraska\r\n485\r\nSaint Andrews, Nebraska\r\n529\r\nSaint Anne, Nebraska\r\n445\r\nSaint Antoine, Nebraska\r\n525\r\nSaint Basile, Nebraska\r\n263\r\nSaint George, Nebraska\r\n755\r\nSaint Isidore, Nebraska\r\n358\r\nSaint Leonard, Nebraska\r\n423\r\nSaint Martins, Nebraska\r\n833\r\nSaint Quentin, Nebraska\r\n235\r\nSaint Stephen, Nebraska\r\n465\r\n466\r\nStanley, Nebraska\r\n367\r\nSaint Louisknt, Nebraska\r\n876\r\nSummerville, Nebraska\r\n763\r\nSussex, Nebraska\r\n432\r\n433\r\nTabusintac, Nebraska\r\n779\r\nTracadie, Nebraska\r\n393\r\n395\r\nWelsford, Nebraska\r\n486\r\nWoodstock, Nebraska\r\n325\r\n328\r\nYoungscvrd, Nebraska\r\n362\r\n\u00035Unknown prefix code (506) - Nebraska\r\n"
  },
  {
    "path": "install/regions/regions.507",
    "content": "Adams, Minnesota\r\n582\r\nAdrian, Minnesota\r\n483\r\nAlbert Lea, Minnesota\r\n373\r\n377\r\nAlden, Minnesota\r\n874\r\nAltura, Minnesota\r\n796\r\nAmboy, Minnesota\r\n674\r\nArco, Minnesota\r\n487\r\nAustin, Minnesota\r\n434\r\n433\r\n437\r\nAvoca, Minnesota\r\n335\r\nBalaton, Minnesota\r\n734\r\nBelview, Minnesota\r\n938\r\nBigelow, Minnesota\r\n683\r\nBlooming Prairie, Minnesota\r\n583\r\nBlue Earth, Minnesota\r\n526\r\nBrewster, Minnesota\r\n842\r\nBricelyn, Minnesota\r\n653\r\nBrownsdale, Minnesota\r\n567\r\nBrownsville, Minnesota\r\n482\r\nButterfield, Minnesota\r\n956\r\nByron, Minnesota\r\n775\r\nCaledonia, Minnesota\r\n724\r\nCambria, Minnesota\r\n947\r\nCanby, Minnesota\r\n223\r\nCannon Falls, Minnesota\r\n263\r\nCanton, Minnesota\r\n743\r\nCeylon, Minnesota\r\n632\r\nChandler, Minnesota\r\n677\r\nChatfield, Minnesota\r\n867\r\nCherry Grove, Minnesota\r\n937\r\nClaremont, Minnesota\r\n528\r\nClarks Grove, Minnesota\r\n256\r\nClements, Minnesota\r\n692\r\nComfrey, Minnesota\r\n877\r\nConger, Minnesota\r\n265\r\nCottonwood, Minnesota\r\n423\r\nCurrie, Minnesota\r\n763\r\nDakota, Minnesota\r\n643\r\nDelavan, Minnesota\r\n854\r\nDelft, Minnesota\r\n678\r\nDexter, Minnesota\r\n584\r\nDodge Center, Minnesota\r\n374\r\nDundee, Minnesota\r\n468\r\nDunnell, Minnesota\r\n695\r\nEast Garretsn, Minnesota\r\n597\r\nEast Valley, Minnesota\r\n755\r\nEagle Lake, Minnesota\r\n257\r\nEast Chain, Minnesota\r\n773\r\nEast Gary, Minnesota\r\n277\r\nEastelkton, Minnesota\r\n548\r\nEaston, Minnesota\r\n787\r\nEcho, Minnesota\r\n925\r\nEdgerton, Minnesota\r\n442\r\nEitzen, Minnesota\r\n495\r\nElgin, Minnesota\r\n876\r\nEllendale, Minnesota\r\n684\r\nEllsworth, Minnesota\r\n967\r\nElmore, Minnesota\r\n943\r\nElysian, Minnesota\r\n267\r\nEmmons, Minnesota\r\n297\r\nEyota, Minnesota\r\n545\r\nFairfax, Minnesota\r\n426\r\nFairmont, Minnesota\r\n230\r\n235\r\n238\r\nFaribault, Minnesota\r\n330\r\n339\r\n332\r\n334\r\nFountain, Minnesota\r\n268\r\nFranklin, Minnesota\r\n557\r\nFreeborn, Minnesota\r\n863\r\nFrost, Minnesota\r\n878\r\nFulda, Minnesota\r\n425\r\nGarden City, Minnesota\r\n546\r\nGarvin, Minnesota\r\n746\r\nGhent, Minnesota\r\n428\r\nGibbon, Minnesota\r\n834\r\nGlenville, Minnesota\r\n448\r\nGoodthunder, Minnesota\r\n278\r\nGranada, Minnesota\r\n447\r\nGrand Mdw, Minnesota\r\n754\r\nGranger, Minnesota\r\n772\r\nGuckeen, Minnesota\r\n464\r\nHanley Falls, Minnesota\r\n768\r\nHanska, Minnesota\r\n439\r\nHardwick, Minnesota\r\n669\r\nHarmony, Minnesota\r\n886\r\nHartland, Minnesota\r\n845\r\nHayfield, Minnesota\r\n477\r\nHendricks, Minnesota\r\n275\r\nHeron Lake, Minnesota\r\n793\r\nHills, Minnesota\r\n962\r\nHokah, Minnesota\r\n894\r\nHolland, Minnesota\r\n347\r\nHollandale, Minnesota\r\n889\r\nHouston, Minnesota\r\n896\r\nHuntley, Minnesota\r\n866\r\nIona, Minnesota\r\n264\r\nIvanhoe, Minnesota\r\n694\r\nJackson, Minnesota\r\n847\r\nJanesville, Minnesota\r\n234\r\nJasper, Minnesota\r\n348\r\nJeffers, Minnesota\r\n628\r\nKasson, Minnesota\r\n634\r\nKellogg, Minnesota\r\n767\r\nKenyon, Minnesota\r\n789\r\nKiester, Minnesota\r\n294\r\nKilkenny, Minnesota\r\n595\r\nLaCrescent, Minnesota\r\n895\r\nLaf Louisville, Minnesota\r\n228\r\nLake Benton, Minnesota\r\n368\r\nLakefield, Minnesota\r\n662\r\nLake Wilson, Minnesota\r\n879\r\nLamberton, Minnesota\r\n752\r\nLanesboro, Minnesota\r\n467\r\nLeota, Minnesota\r\n443\r\nLeroy, Minnesota\r\n324\r\nLewiston, Minnesota\r\n523\r\nLewisville, Minnesota\r\n435\r\nLismore, Minnesota\r\n472\r\nLake Crystal, Minnesota\r\n726\r\nLonsdale, Minnesota\r\n744\r\nLucan, Minnesota\r\n747\r\nLuverne, Minnesota\r\n227\r\n283\r\n673\r\nLyle, Minnesota\r\n325\r\nLynd, Minnesota\r\n865\r\nMabel, Minnesota\r\n493\r\nMadelia, Minnesota\r\n642\r\nMadison Lake, Minnesota\r\n243\r\nManchester, Minnesota\r\n826\r\nMankato, Minnesota\r\n340\r\n380\r\n386\r\n345\r\n387\r\n388\r\n389\r\n625\r\nMantorville, Minnesota\r\n635\r\nMapleton, Minnesota\r\n524\r\nMarshall, Minnesota\r\n530\r\n532\r\n537\r\nMazeppa, Minnesota\r\n843\r\nMillville, Minnesota\r\n798\r\nMilroy, Minnesota\r\n336\r\nMinneota, Minnesota\r\n828\r\n872\r\nMinnestalk, Minnesota\r\n462\r\nMorgan, Minnesota\r\n249\r\nMorristown, Minnesota\r\n685\r\nMorton, Minnesota\r\n697\r\nMount Lake, Minnesota\r\n427\r\nNorth Lester, Minnesota\r\n471\r\nNew Sweden, Minnesota\r\n246\r\nNew Ulm, Minnesota\r\n233\r\n276\r\n354\r\n359\r\nNew Richlnd, Minnesota\r\n465\r\nNicollet, Minnesota\r\n225\r\nNorth Bur, Minnesota\r\n733\r\nNorth Chester, Minnesota\r\n561\r\nNorth Esthrville, Minnesota\r\n862\r\nNorth Lake, Minnesota\r\n839\r\nNorth Swea, Minnesota\r\n273\r\nNorth Little Rock, Minnesota\r\n394\r\nNonewalbin, Minnesota\r\n542\r\nNorth Rock Rapids, Minnesota\r\n392\r\nNorth Rake, Minnesota\r\n569\r\nNorthfield, Minnesota\r\n645\r\n646\r\n663\r\nNorthrop, Minnesota\r\n436\r\nNorth Spirit Lake, Minnesota\r\n856\r\nOdin, Minnesota\r\n736\r\nOkabena, Minnesota\r\n853\r\nOronoco, Minnesota\r\n367\r\nOstrander, Minnesota\r\n657\r\nOwatonna, Minnesota\r\n451\r\n455\r\nPemberton, Minnesota\r\n869\r\nPeterson, Minnesota\r\n875\r\nPine Island, Minnesota\r\n356\r\nPipestone, Minnesota\r\n825\r\nPlainview, Minnesota\r\n534\r\nPorter, Minnesota\r\n296\r\nPreston, Minnesota\r\n765\r\nRacine, Minnesota\r\n378\r\nRed Del, Minnesota\r\n641\r\n644\r\nRedwood Falls, Minnesota\r\n637\r\nRochester, Minnesota\r\n250\r\n252\r\n255\r\n259\r\n266\r\n251\r\n253\r\n254\r\n280\r\n281\r\n282\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\nRock Dell, Minnesota\r\n365\r\nRollingston, Minnesota\r\n689\r\nRound Lake, Minnesota\r\n945\r\nRushford, Minnesota\r\n864\r\nRushmore, Minnesota\r\n370\r\n478\r\nRussell, Minnesota\r\n823\r\nRuthton, Minnesota\r\n658\r\nSanborn, Minnesota\r\n648\r\nSeaforth, Minnesota\r\n984\r\nSherburn, Minnesota\r\n764\r\nSlayton, Minnesota\r\n836\r\nSleepy Eye, Minnesota\r\n794\r\nSpring Grove, Minnesota\r\n498\r\nSpring Valley, Minnesota\r\n346\r\nSpringfield, Minnesota\r\n723\r\nSaint Charles, Minnesota\r\n932\r\nSaint Clair, Minnesota\r\n245\r\nSaint James, Minnesota\r\n630\r\n375\r\nSaint Leo, Minnesota\r\n224\r\nSaint Peter, Minnesota\r\n931\r\n933\r\nSteen, Minnesota\r\n855\r\nStewartville, Minnesota\r\n533\r\nStorden, Minnesota\r\n445\r\nTracy, Minnesota\r\n629\r\nTrimont, Minnesota\r\n639\r\nTruman, Minnesota\r\n776\r\nTwin Lakes, Minnesota\r\n852\r\nTyler, Minnesota\r\n247\r\nVernon Center, Minnesota\r\n549\r\nVesta, Minnesota\r\n762\r\nWest Concord, Minnesota\r\n527\r\nWabasso, Minnesota\r\n342\r\nWaldorf, Minnesota\r\n239\r\nWalnut Grove, Minnesota\r\n859\r\nWanamingo, Minnesota\r\n824\r\nWaseca, Minnesota\r\n837\r\n835\r\nWaterville, Minnesota\r\n362\r\nWelcome, Minnesota\r\n728\r\nWells, Minnesota\r\n553\r\nWestbrook, Minnesota\r\n274\r\nWilmont, Minnesota\r\n926\r\nWindom, Minnesota\r\n831\r\nWinnebago, Minnesota\r\n893\r\nWinona, Minnesota\r\n450\r\n453\r\n452\r\n454\r\n457\r\nWinthrop, Minnesota\r\n647\r\nWood Lake, Minnesota\r\n485\r\nWoodstock, Minnesota\r\n777\r\nWorthington, Minnesota\r\n372\r\n376\r\nWykoff, Minnesota\r\n352\r\nZumbro Falls, Minnesota\r\n753\r\nZumbrota, Minnesota\r\n732\r\n\u00035Unknown prefix code (507) - Minnesota\r\n"
  },
  {
    "path": "install/regions/regions.508",
    "content": "Acton, Massachusetts\r\n263\r\n264\r\n266\r\n635\r\nAmesbury, Massachusetts\r\n388\r\n834\r\nAndover, Massachusettes\r\n623\r\n470\r\n474\r\n475\r\n749\r\nAshburnham, Massachusetts\r\n827\r\nAshby, Massachusetts\r\n386\r\nAshland, Massachusetts\r\n881\r\nAssonet, Massachusetts\r\n644\r\nAthol, Massachusetts\r\n249\r\n575\r\nAttleboro, Massachusetts\r\n222\r\n223\r\n226\r\nAuburn, Massachusettes\r\n327\r\n426\r\n721\r\n729\r\n832\r\nAyer, Massachusetts\r\n772\r\nBarnstable, Massachusetts\r\n362\r\n364\r\nBarre, Massachusetts\r\n355\r\nBellingham, Massachusettes\r\n966\r\n960\r\nBerlin, Massachusetts\r\n838\r\nBeverly, Massachusetts\r\n524\r\n921\r\n922\r\n927\r\nBillerica, Massachusettes\r\n262\r\n488\r\n545\r\n547\r\n574\r\n622\r\n629\r\n294\r\n436\r\n663\r\n667\r\n670\r\n671\r\nBlackstone, Massachusetts\r\n883\r\nBolton, Massachusetts\r\n779\r\nBoylston, Massachusetts\r\n869\r\nBrewster, Massachusetts\r\n896\r\nBridgewater, Massachusetts\r\n279\r\n697\r\nBrockton, Massachusettes\r\n631\r\n427\r\n559\r\n580\r\n583\r\n584\r\n586\r\n587\r\n588\r\n846\r\n941\r\n942\r\nBuzzards Bay, Massachusetts\r\n759\r\nCarver, Massachusetts\r\n866\r\nCataumet, Massachusetts\r\n563\r\n564\r\n968\r\nCharlton, Massachusetts\r\n248\r\nChatham, Massachusetts\r\n945\r\nChelmsford, Massachusetts\r\n250\r\n256\r\nChilmark, Massachusetts\r\n645\r\nClinton, Massachusetts\r\n365\r\n368\r\nConcord, Massachusettes\r\n472\r\n963\r\n287\r\n369\r\n371\r\nDanvers, Massachusetts\r\n750\r\n762\r\n774\r\n777\r\nDennis, Massachusetts\r\n385\r\n394\r\n398\r\n760\r\nDighton, Massachusetts\r\n669\r\nDover, Massachusetts\r\n785\r\nDracut, Massachusetts\r\n957\r\nEast Bridgewater, Massachusetts\r\n378\r\n690\r\nEast Douglas, Massachusetts\r\n476\r\nEaston, Massachusetts\r\n230\r\n238\r\nEdgartown, Massachusetts\r\n627\r\nEssex, Massachusetts\r\n768\r\nFall River, Massachusettes\r\n491\r\n324\r\n672\r\n673\r\n674\r\n675\r\n676\r\n677\r\n678\r\n679\r\nFalmouth, Massachusetts\r\n457\r\n540\r\n548\r\nFitchburg, Massachusetts\r\n340\r\n342\r\n343\r\n345\r\n348\r\n665\r\nFort Devens, Massachusetts\r\n796\r\nFoxborough, Massachusetts\r\n543\r\n549\r\n698\r\nFramingham, Massachusettes\r\n268\r\n361\r\n387\r\n391\r\n396\r\n483\r\n484\r\n489\r\n522\r\n628\r\n370\r\n380\r\n383\r\n390\r\n395\r\n620\r\n626\r\n820\r\n872\r\n875\r\n877\r\n879\r\n935\r\nFranklin, Massachusettes\r\n541\r\n520\r\n528\r\nGardner, Massachusetts\r\n630\r\n632\r\nGeorgetown, Massachusetts\r\n352\r\nGloucester, Massachusetts\r\n281\r\n282\r\n283\r\nGrafton, Massachusetts\r\n839\r\nGroton, Massachusetts\r\n448\r\nHamilton, Massachusetts\r\n468\r\nHarvard, Massachusetts\r\n456\r\nHarwich, Massachusetts\r\n430\r\n432\r\nHaverhill, Massachusetts\r\n372\r\n373\r\n374\r\n469\r\n521\r\nHolden, Massachusetts\r\n829\r\nHolliston, Massachusetts\r\n429\r\nHopkinton, Massachusettes\r\n497\r\nHopkinton, Massachusetts\r\n435\r\nHubbardston, Massachusetts\r\n928\r\nHudson, Massachusetts\r\n562\r\n568\r\nHyannis, Massachusetts\r\n771\r\n775\r\n776\r\n778\r\n790\r\nIpswich, Massachusetts\r\n356\r\nLawrence, Massachusettes\r\n659\r\n662\r\n641\r\n681\r\n682\r\n683\r\n685\r\n686\r\n687\r\n688\r\n689\r\n691\r\n783\r\n794\r\n837\r\n975\r\n989\r\nLeicester, Massachusetts\r\n892\r\nLeominster, Massachusetts\r\n534\r\n537\r\n840\r\nLittleton, Massachusetts\r\n486\r\n952\r\nLowell, Massachusettes\r\n441\r\n442\r\n446\r\n452\r\n453\r\n454\r\n458\r\n459\r\n656\r\n934\r\n937\r\n967\r\n970\r\nLunenburg, Massachusetts\r\n582\r\nManchester, Massachusetts\r\n525\r\n526\r\nManomet, Massachusetts\r\n224\r\nMansfield, Massachusetts\r\n261\r\n337\r\n339\r\nManyard, Massachusetts\r\n461\r\n493\r\n496\r\n897\r\nMarion, Massachusetts\r\n748\r\nMarlboro, Massachusettes\r\n229\r\n460\r\n467\r\n480\r\n481\r\n485\r\n490\r\n624\r\nMashpee, Massachusetts\r\n477\r\n539\r\nMattapoisett, Massachusetts\r\n758\r\nMedfield, Massachusetts\r\n359\r\nMedway, Massachusetts\r\n533\r\nMerrimac, Massachusetts\r\n346\r\nMiddleboro, Massachusetts\r\n946\r\n947\r\nMilford, Massachusetts\r\n473\r\n478\r\n634\r\nMillbury/Sutton, Massachusetts\r\n865\r\nMillis, Massachusetts\r\n376\r\nNantucket, Massachusetts\r\n228\r\n325\r\nNatick, Massachusetts\r\n650\r\n651\r\n653\r\n655\r\nNaushon Island, Massachusetts\r\n299\r\nNew Bedford, Massachusetts\r\n965\r\n971\r\n979\r\n990\r\n991\r\n992\r\n993\r\n994\r\n995\r\n996\r\n997\r\n998\r\n999\r\nNewburyport, Massachusetts\r\n462\r\n463\r\n465\r\nNorth Attleborough, Massachusetts\r\n643\r\n695\r\n699\r\nNorth Brookfield, Massachusetts\r\n867\r\nNorth Chelmsford, Massachusetts\r\n251\r\n254\r\nNorth Framingham, Massachusetts\r\n788\r\nNorth Reading, Massachusetts\r\n664\r\nNorth Swansea, Massachusetts\r\n379\r\nNorthboro, Massachusettes\r\n393\r\nNorthborough, Massachusetts\r\n351\r\nNorthbridge/Whitinsville, Massachusetts\r\n234\r\nNorton, Massachusetts\r\n285\r\nOakham, Massachusetts\r\n882\r\nOrange, Massachusetts\r\n544\r\nOrleans, Massachusetts\r\n240\r\n255\r\nOsterville, Massachusettes\r\n420\r\n428\r\nOxford, Massachusetts\r\n987\r\nPeabody, Massachusettes\r\n536\r\n538\r\n530\r\n531\r\n532\r\n535\r\n977\r\nPepperell, Massachusetts\r\n433\r\nPetersham, Massachusetts\r\n724\r\nPlymouth, Massachusetts\r\n746\r\n747\r\n830\r\nPrinceton, Massachusetts\r\n464\r\nProvincetown, Massachusetts\r\n487\r\nRehoboth, Massachusetts\r\n252\r\nRochester, Massachusetts\r\n763\r\nRockport, Massachusetts\r\n546\r\nRowley, Massachusetts\r\n948\r\nRutland, Massachusetts\r\n886\r\nSagamore, Massachusetts\r\n833\r\n888\r\nSalem, Massachusetts\r\n740\r\n741\r\n744\r\n745\r\nSeekonk, Massachusetts\r\n336\r\nShirley, Massachusettes\r\n425\r\nShrewsbury, Massachusetts\r\n841\r\n842\r\n845\r\nSiasconset, Massachusetts\r\n257\r\nSouth Attleborough, Massachusetts\r\n399\r\n761\r\nSouthbridge, Massachusetts\r\n764\r\n765\r\nSpencer, Massachusetts\r\n885\r\nSterling, Massachusettes\r\n422\r\nSturbridge, Massachusetts\r\n347\r\nSudbury, Massachusetts\r\n440\r\n443\r\nTaunton, Massachusetts\r\n821\r\n822\r\n823\r\n824\r\n880\r\nTempleton, Massachusetts\r\n939\r\nTewksbury, Massachusetts\r\n640\r\n851\r\n858\r\nTopsfield, Massachusetts\r\n887\r\nTownsend, Massachusetts\r\n597\r\nTyngsboro, Massachusetts\r\n649\r\nUpton, Massachusetts\r\n529\r\nUxbridge, Massachusetts\r\n278\r\nVineyard Haven, Massachusetts\r\n693\r\n696\r\nWalpole, Massachusetts\r\n660\r\n668\r\nWareham, Massachusetts\r\n291\r\n295\r\nWayland, Massachusetts\r\n358\r\nWebster, Massachusetts\r\n943\r\n949\r\nWellfleet, Massachusetts\r\n349\r\nWest Boylston, Massachusetts\r\n835\r\nWest Newbury, Massachusetts\r\n363\r\nWestboro, Massachusettes\r\n389\r\nWestborough, Massachusetts\r\n366\r\n836\r\n870\r\n898\r\nWestford, Massachusetts\r\n392\r\n692\r\nWestminster, Massachusetts\r\n874\r\nWestport, Massachusetts\r\n636\r\nWilmington, Massachusetts\r\n657\r\n658\r\n694\r\n988\r\nWinchendon, Massachusetts\r\n297\r\nWorcester, Massachusettes\r\n335\r\n723\r\n849\r\n751\r\n752\r\n753\r\n754\r\n755\r\n756\r\n757\r\n767\r\n791\r\n792\r\n793\r\n795\r\n797\r\n798\r\n799\r\n826\r\n831\r\n852\r\n853\r\n854\r\n855\r\n856\r\n860\r\nWrentham, Massachusetts\r\n384\r\n\u00035Unknown prefix code (508) - Massachusetts\r\n"
  },
  {
    "path": "install/regions/regions.509",
    "content": "Almira, Washington\r\n639\r\nAnatone, Washington\r\n256\r\nAsotin, Washington\r\n243\r\nBasin City, Washington\r\n269\r\nBenge, Washington\r\n887\r\nBenton City, Washington\r\n588\r\nBickleton, Washington\r\n896\r\nBrewster, Washington\r\n689\r\nBridgeport, Washington\r\n686\r\nCashmere, Washington\r\n782\r\nChelan, Washington\r\n682\r\n687\r\nCheney, Washington\r\n235\r\n359\r\nChewelah, Washington\r\n936\r\n935\r\n937\r\nClarkston, Washington\r\n751\r\n758\r\nCle Elum, Washington\r\n674\r\nColfax, Washington\r\n397\r\nColumbia, Washington\r\n377\r\nColville, Washington\r\n684\r\nConnell, Washington\r\n234\r\nCoulee City, Washington\r\n632\r\nCoulee Dam, Washington\r\n633\r\nCowiche, Washington\r\n678\r\nCreston, Washington\r\n636\r\nCurlew, Washington\r\n779\r\nCusick, Washington\r\n445\r\nDallesport, Washington\r\n767\r\nDavenport, Washington\r\n725\r\nDayton, Washington\r\n382\r\nDeer Park, Washington\r\n276\r\nEaston, Washington\r\n656\r\nEdwall Taylor, Washington\r\n236\r\n239\r\nElk, Washington\r\n292\r\nEllensburg, Washington\r\n925\r\n929\r\n962\r\n963\r\nEltopia, Washington\r\n297\r\nEndicott, Washington\r\n657\r\nEntiat, Washington\r\n784\r\nEphrata, Washington\r\n754\r\nEureka, Washington\r\n749\r\nFairfield, Washington\r\n283\r\nFarmington, Washington\r\n287\r\nGarfield, Washington\r\n635\r\nGarrison, Washington\r\n872\r\nGeorge, Washington\r\n785\r\nGlenwood, Washington\r\n364\r\nGoldendale, Washington\r\n773\r\nGrandview, Washington\r\n882\r\nGranger, Washington\r\n854\r\nGreenbluff, Washington\r\n238\r\nHarrah, Washington\r\n848\r\nHarrington, Washington\r\n253\r\nHunters, Washington\r\n722\r\nIone, Washington\r\n442\r\nKahlotus, Washington\r\n282\r\nKennewick, Washington\r\n222\r\n582\r\n585\r\n586\r\n628\r\n734\r\n735\r\n736\r\n783\r\n948\r\nKettle Faals, Washington\r\n738\r\nKittitas, Washington\r\n968\r\nKlickitat, Washington\r\n369\r\nLacrosse, Washington\r\n549\r\nLatah, Washington\r\n286\r\nLauderdale, Washington\r\n857\r\nLeavenworth, Washington\r\n548\r\n763\r\nLiberty Lake, Washington\r\n255\r\nLind, Washington\r\n677\r\nLoomis, Washington\r\n223\r\n486\r\nLoon Lake, Washington\r\n233\r\nLyle, Washington\r\n365\r\nMabton, Washington\r\n894\r\nMansfield, Washington\r\n683\r\nMatthews Corner, Washington\r\n266\r\nMattawa, Washington\r\n932\r\nMedical Lake, Washington\r\n299\r\nMesa, Washington\r\n265\r\nMetalin Falls, Washington\r\n446\r\nMolson, Washington\r\n485\r\nMoses Lake, Washington\r\n750\r\n760\r\n762\r\n765\r\n766\r\n770\r\nNaches, Washington\r\n653\r\nNespelem, Washington\r\n634\r\nNewman Lake, Washington\r\n226\r\nNewport, Washington\r\n447\r\nNile, Washington\r\n658\r\nNorthport, Washington\r\n732\r\nOakesdale, Washington\r\n285\r\nOdessa, Washington\r\n982\r\nOmak, Washington\r\n422\r\n826\r\nOroville, Washington\r\n476\r\nOthello, Washington\r\n989\r\n346\r\n488\r\nPalouse, Washington\r\n878\r\nPasco, Washington\r\n539\r\n543\r\n544\r\n545\r\n546\r\n547\r\nPateros, Washington\r\n875\r\n923\r\nPomeroy, Washington\r\n843\r\nPrescott, Washington\r\n849\r\nProsser, Washington\r\n786\r\nPullman, Washington\r\n336\r\n332\r\n334\r\n335\r\nQuincy, Washington\r\n787\r\nReardan, Washington\r\n796\r\nRepublic, Washington\r\n775\r\nRichland, Washington\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n942\r\n943\r\n946\r\nRichland\u00031/\u00032Kennewick, Washington\r\n627\r\nRimrock, Washington\r\n672\r\nRitzville, Washington\r\n650\r\n660\r\n659\r\nRockford, Washington\r\n291\r\nRoosevelt, Washington\r\n374\r\nRosalia, Washington\r\n478\r\n523\r\n569\r\nRoslyn, Washington\r\n649\r\nSelah, Washington\r\n698\r\n697\r\nSoap Lake, Washington\r\n246\r\nSpangle, Washington\r\n245\r\nSpokane, Washington\r\n244\r\n247\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n353\r\n354\r\n358\r\n441\r\n448\r\n455\r\n456\r\n458\r\n459\r\n466\r\n467\r\n468\r\n482\r\n483\r\n484\r\n487\r\n489\r\n533\r\n534\r\n535\r\n536\r\n623\r\n624\r\n625\r\n626\r\n747\r\n838\r\n891\r\n921\r\n922\r\n924\r\n926\r\n927\r\n928\r\n960\r\n990\r\n993\r\n994\r\nSprague, Washington\r\n257\r\nSpringdale, Washington\r\n258\r\nSaint John, Washington\r\n648\r\nStarbuck, Washington\r\n399\r\nStevenson, Washington\r\n427\r\nSunnyside, Washington\r\n837\r\n839\r\nTekoa, Washington\r\n284\r\nThorp, Washington\r\n964\r\nTieton, Washington\r\n673\r\nToppenish, Washington\r\n865\r\nTouchet, Washington\r\n394\r\nTrout Lake, Washington\r\n395\r\nTwisp, Washington\r\n997\r\nUniontown, Washington\r\n229\r\nVantage, Washington\r\n856\r\nWaitsburg, Washington\r\n337\r\nWallawalla, Washington\r\n520\r\n522\r\n525\r\n527\r\n529\r\n629\r\nWapato, Washington\r\n877\r\nWarden, Washington\r\n349\r\nWashtucna, Washington\r\n646\r\nWaterville, Washington\r\n745\r\nWenatchee, Washington\r\n669\r\n662\r\n663\r\n664\r\n884\r\n886\r\nWest Richland, Washington\r\n967\r\nWhite Salmon, Washington\r\n493\r\nWhite Swan, Washington\r\n874\r\nWhitstran, Washington\r\n973\r\nWilbur, Washington\r\n647\r\nWillard, Washington\r\n538\r\nWilson Creek, Washington\r\n345\r\nWinthrop, Washington\r\n996\r\nWishram, Washington\r\n748\r\nYakima, Washington\r\n248\r\n452\r\n453\r\n454\r\n457\r\n572\r\n575\r\n576\r\n577\r\n945\r\n949\r\n952\r\n965\r\n966\r\n969\r\nZillah, Washington\r\n829\r\nTri-Cities, Washington\r\nNET\r\n\u00035Unknown prefix code (509) - Washington\r\n"
  },
  {
    "path": "install/regions/regions.510",
    "content": "Alameda, California\r\n521\r\n522\r\nAntioch, California\r\n706\r\n753\r\n754\r\n757\r\n777\r\n778\r\n779\r\nBerkeley, California\r\n486\r\n845\r\nBishop Ranch, California\r\n244\r\n275\r\n277\r\n355\r\n735\r\n806\r\n815\r\n823\r\n830\r\n842\r\n866\r\n867\r\n901\r\nBrentwood, California\r\n634\r\nClayton, California\r\n673\r\n672\r\nConcord, California\r\n246\r\n356\r\n602\r\n603\r\n609\r\n646\r\n675\r\n676\r\n680\r\n682\r\n685\r\n686\r\n687\r\n798\r\n825\r\n671\r\n674\r\n689\r\n827\r\nCrockett, California\r\n787\r\nDanville, California\r\n736\r\n743\r\n820\r\n831\r\n837\r\n838\r\nDub-Sn Rmn, California\r\n248\r\n551\r\n803\r\n828\r\n829\r\n833\r\nEast Central Coast, California\r\n516\r\n679\r\n684\r\nEl Sbr-Pin, California\r\n222\r\n223\r\n262\r\n669\r\n724\r\n741\r\n758\r\nSan Francisco, California\r\n494\r\n505\r\n713\r\n745\r\n790\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n429\r\n441\r\n471\r\n475\r\n487\r\n489\r\n226\r\n249\r\n252\r\n438\r\n440\r\n490\r\n498\r\n623\r\n651\r\n656\r\n657\r\n659\r\n683\r\n770\r\nHayward, California\r\n247\r\n276\r\n278\r\n293\r\n317\r\n481\r\n537\r\n538\r\n581\r\n582\r\n670\r\n727\r\n732\r\n733\r\n782\r\n783\r\n784\r\n785\r\n786\r\n881\r\n884\r\n886\r\n887\r\n888\r\n889\r\nHercul-Rod, California\r\n245\r\n799\r\nLa Fayette, California\r\n283\r\n284\r\n299\r\nLivermore, California\r\n294\r\n373\r\n422\r\n423\r\n424\r\n443\r\n447\r\n449\r\n455\r\n606\r\nMartinez, California\r\n313\r\n228\r\n229\r\n370\r\n372\r\nMoraga, California\r\n631\r\n376\r\nOakland, California\r\n263\r\n523\r\n748\r\n769\r\n814\r\n865\r\n261\r\n339\r\n436\r\n437\r\n482\r\n530\r\n531\r\n532\r\n533\r\n534\r\n535\r\n536\r\n208\r\n220\r\n238\r\n251\r\n268\r\n271\r\n272\r\n273\r\n286\r\n287\r\n302\r\n308\r\n310\r\n321\r\n380\r\n381\r\n409\r\n410\r\n414\r\n419\r\n420\r\n428\r\n442\r\n444\r\n446\r\n448\r\n450\r\n451\r\n452\r\n464\r\n465\r\n466\r\n504\r\n514\r\n539\r\n547\r\n596\r\n601\r\n612\r\n630\r\n637\r\n645\r\n652\r\n653\r\n654\r\n655\r\n658\r\n697\r\n702\r\n716\r\n717\r\n718\r\n720\r\n726\r\n762\r\n763\r\n801\r\n805\r\n810\r\n816\r\n819\r\n832\r\n834\r\n835\r\n836\r\n839\r\n840\r\n868\r\n869\r\n874\r\n891\r\n893\r\n902\r\n910\r\n913\r\n914\r\n918\r\n936\r\n980\r\n987\r\n204\r\n524\r\n525\r\n526\r\n527\r\n528\r\n529\r\n540\r\n548\r\n549\r\n559\r\n642\r\n643\r\n644\r\n649\r\n693\r\n704\r\n841\r\n843\r\n848\r\n849\r\n883\r\n297\r\n351\r\n352\r\n357\r\n382\r\n425\r\n430\r\n483\r\n562\r\n568\r\n569\r\n577\r\n613\r\n614\r\n618\r\n632\r\n633\r\n635\r\n636\r\n638\r\n639\r\n667\r\n678\r\n729\r\n895\r\n555\r\n320\r\nOakley, California\r\n625\r\nOrinda, California\r\n253\r\n254\r\nPittsburg, California\r\n709\r\n427\r\n439\r\n473\r\n432\r\nPleasanton, California\r\n224\r\n416\r\n417\r\n426\r\n460\r\n462\r\n463\r\n484\r\n734\r\n846\r\n847\r\nRichmond, California\r\n215\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n242\r\n307\r\n374\r\n412\r\n620\r\n970\r\nSunol, California\r\n862\r\nWalnut Creek, California\r\n256\r\n930\r\n939\r\n945\r\n210\r\n295\r\n746\r\n906\r\n932\r\n933\r\n934\r\n935\r\n937\r\n938\r\n942\r\n943\r\n944\r\n946\r\n947\r\n975\r\n977\r\n988\r\nWest Pittsburg, California\r\n458\r\n\u00035Unknown prefix code (510) - California\r\n"
  },
  {
    "path": "install/regions/regions.512",
    "content": "Adamsville, Texas\r\n768\r\nAgua Dulce, Texas\r\n998\r\nAlice, Texas\r\n660\r\n664\r\n668\r\nAmarillo, Texas\r\n781\r\n787\r\nAnnarose, Texas\r\n566\r\nAransaspas, Texas\r\n758\r\nArmstrong, Texas\r\n216\r\nArtesan Wells, Texas\r\n676\r\nAsherton, Texas\r\n468\r\nAustin, Texas\r\n205\r\n206\r\n209\r\n217\r\n314\r\n403\r\n413\r\n502\r\n505\r\n517\r\n602\r\n604\r\n606\r\n706\r\n707\r\n719\r\n728\r\n750\r\n919\r\n931\r\n941\r\n970\r\n282\r\n356\r\n369\r\n386\r\n390\r\n465\r\n823\r\n838\r\n860\r\n891\r\n940\r\n973\r\n984\r\nBabcock, Texas\r\n498\r\n558\r\n561\r\n567\r\n641\r\n690\r\n691\r\n692\r\n694\r\n696\r\n697\r\n699\r\n975\r\nBalcones, Texas\r\n755\r\n981\r\nBandera, Texas\r\n796\r\nBarksdale, Texas\r\n234\r\nBastrop, Texas\r\n321\r\n332\r\nBatesville, Texas\r\n376\r\nBayside, Texas\r\n529\r\nBee Caves, Texas\r\n261\r\n263\r\nBee Creek, Texas\r\n264\r\nBeeville, Texas\r\n319\r\n354\r\n358\r\n362\r\nBenavides, Texas\r\n256\r\nBerclair, Texas\r\n439\r\nBertram, Texas\r\n355\r\nBig Wells, Texas\r\n457\r\nBishop, Texas\r\n584\r\nBlanco, Texas\r\n833\r\nBlessing, Texas\r\n588\r\nBloomington, Texas\r\n897\r\nBoerne, Texas\r\n816\r\n249\r\nBracken, Texas\r\n651\r\nBrackettville, Texas\r\n563\r\nBriggs, Texas\r\n489\r\nBrownsville, Texas\r\n405\r\n504\r\n507\r\n570\r\n986\r\n350\r\n541\r\n542\r\n544\r\n546\r\n548\r\n549\r\n551\r\n831\r\n982\r\nBruni, Texas\r\n747\r\nBuchanan Dam, Texas\r\n793\r\nBuda, Texas\r\n312\r\n295\r\nBuena Vista, Texas\r\n627\r\nBulverde, Texas\r\n980\r\n438\r\nBurnet, Texas\r\n756\r\nCalallen, Texas\r\n241\r\n242\r\nCamp Wood, Texas\r\n597\r\nCampbellton, Texas\r\n579\r\nCarrzo Springs, Texas\r\n876\r\nCastroville, Texas\r\n538\r\nCatarina, Texas\r\n999\r\nCedar Valley, Texas\r\n288\r\nCenter Point, Texas\r\n634\r\nCharco, Texas\r\n269\r\nCharlotte, Texas\r\n277\r\nChristine, Texas\r\n784\r\nClarkwood, Texas\r\n265\r\nComfort, Texas\r\n995\r\nConcepcion, Texas\r\n539\r\nCorpus Christi, Texas\r\n215\r\n808\r\n812\r\n813\r\n814\r\n815\r\n854\r\n902\r\n960\r\n985\r\n289\r\n560\r\n850\r\n851\r\n852\r\n853\r\n855\r\n857\r\n877\r\n878\r\n880\r\n881\r\n882\r\n883\r\n884\r\n886\r\n887\r\n888\r\n889\r\n946\r\n949\r\n991\r\n992\r\n993\r\n994\r\nCost, Texas\r\n437\r\nCotulla, Texas\r\n879\r\nCoupland, Texas\r\n856\r\nCranes Mill, Texas\r\n899\r\nCreedmoor, Texas\r\n243\r\nCrystal City, Texas\r\n374\r\nCuero, Texas\r\n275\r\nCulebra, Texas\r\n509\r\n520\r\n521\r\n522\r\n523\r\n647\r\n680\r\n681\r\n684\r\nDale, Texas\r\n764\r\nDel Rio, Texas\r\n298\r\n313\r\n703\r\n774\r\n775\r\n252\r\nDevine, Texas\r\n663\r\nDhanis, Texas\r\n363\r\nDilley, Texas\r\n965\r\nDolores, Texas\r\n417\r\n799\r\nDonna, Texas\r\n464\r\nDoss, Texas\r\n669\r\nDripping Springs, Texas\r\n858\r\n894\r\nEagle Pass, Texas\r\n757\r\n773\r\nEdcouch, Texas\r\n262\r\nEdinburg, Texas\r\n316\r\n318\r\n330\r\n381\r\n382\r\n605\r\n607\r\n380\r\n383\r\nEdna, Texas\r\n782\r\nEl Sauz, Texas\r\n486\r\nElgin, Texas\r\n285\r\nElm Creek, Texas\r\n497\r\nElmendorf, Texas\r\n635\r\nEncinal, Texas\r\n948\r\nEncino, Texas\r\n568\r\nEvergreen, Texas\r\n385\r\n389\r\nFairfax, Texas\r\n327\r\n328\r\n329\r\nFalcon Heights, Texas\r\n848\r\nFalfurrias, Texas\r\n325\r\nFentress, Texas\r\n488\r\nFireside, Texas\r\n338\r\n343\r\n345\r\n346\r\n794\r\n795\r\nFlatonia, Texas\r\n865\r\nFloresville, Texas\r\n393\r\nFlourbluff, Texas\r\n937\r\n939\r\nFoster, Texas\r\n648\r\nFowlerton, Texas\r\n373\r\nFratt, Texas\r\n590\r\n599\r\n619\r\n637\r\n646\r\n650\r\n654\r\n655\r\n656\r\n657\r\n871\r\n653\r\nFredricksburg, Texas\r\n997\r\nFreer, Texas\r\n394\r\nFriocanyon, Texas\r\n232\r\nGanado, Texas\r\n771\r\nGarfield\u00031/\u00032Evergreen, Texas\r\n247\r\nGarvin Store, Texas\r\n640\r\nGeorgetown, Texas\r\n818\r\n819\r\n863\r\n869\r\n930\r\nGeorge West, Texas\r\n449\r\nGeronimo Creek, Texas\r\n688\r\nGillett, Texas\r\n789\r\nGoliad, Texas\r\n645\r\nGonzales, Texas\r\n672\r\nGranger, Texas\r\n859\r\nGrant Shoals, Texas\r\n598\r\nGreenwood, Texas\r\n320\r\n322\r\n370\r\n397\r\n404\r\n461\r\n463\r\n469\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n478\r\n479\r\n480\r\n482\r\n495\r\n499\r\n867\r\n870\r\nGreenwood\u00031/\u00032Homestead, Texas\r\n422\r\nHallettsville, Texas\r\n798\r\nHancock, Texas\r\n935\r\nHargill, Texas\r\n845\r\nHarlingen, Texas\r\n202\r\n290\r\n291\r\n407\r\n412\r\n421\r\n423\r\n425\r\n427\r\n430\r\n760\r\n428\r\nHarper, Texas\r\n864\r\nHebbronville, Texas\r\n527\r\nHelotes, Texas\r\n695\r\nHickory, Texas\r\n326\r\n416\r\n440\r\n441\r\n442\r\n443\r\n444\r\n445\r\n447\r\n448\r\n462\r\nHomestead, Texas\r\n323\r\n371\r\n406\r\n450\r\n451\r\n452\r\n453\r\n454\r\n458\r\n459\r\n467\r\n483\r\nHondo, Texas\r\n426\r\nHunt, Texas\r\n238\r\nHutto, Texas\r\n846\r\nHutto, Texas\r\n759\r\nIndian Creek, Texas\r\n623\r\nIngleside, Texas\r\n776\r\nIngram, Texas\r\n367\r\nJarratt, Texas\r\n622\r\nJarrell, Texas\r\n746\r\nJohnson City, Texas\r\n868\r\nJollyville, Texas\r\n219\r\n250\r\n258\r\n331\r\n335\r\n918\r\nJourdanton, Texas\r\n769\r\nKarnes City, Texas\r\n254\r\n780\r\nKempner, Texas\r\n932\r\nKenberg, Texas\r\n336\r\nKenedy, Texas\r\n583\r\nKerrville, Texas\r\n257\r\n739\r\n792\r\n895\r\n896\r\nKingsbury, Texas\r\n639\r\nKingsville, Texas\r\n516\r\n592\r\n595\r\nKnippa, Texas\r\n934\r\nKosciusko, Texas\r\n745\r\nKyle, Texas\r\n268\r\nLa Feria, Texas\r\n797\r\nLa Pryor, Texas\r\n365\r\nLa Ward, Texas\r\n872\r\nLackland, Texas\r\n670\r\n671\r\n673\r\n675\r\n678\r\n674\r\nLacoste, Texas\r\n762\r\nLake Travis, Texas\r\n267\r\nLampasas, Texas\r\n556\r\nLaredo, Texas\r\n717\r\n718\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n744\r\n763\r\n791\r\nLasara, Texas\r\n642\r\nLavernia, Texas\r\n779\r\nLeander, Texas\r\n259\r\nLeesville, Texas\r\n424\r\nLeon Springs, Texas\r\n698\r\nLiberty Hill, Texas\r\n515\r\n778\r\nLockhart, Texas\r\n398\r\nLolita, Texas\r\n874\r\nLometa, Texas\r\n752\r\nLos Fresnos, Texas\r\n233\r\nLoyola Beach, Texas\r\n297\r\nLuling, Texas\r\n875\r\nLyford, Texas\r\n347\r\nLytle, Texas\r\n772\r\nLytton Springs, Texas\r\n601\r\n559\r\nManchaca, Texas\r\n292\r\n280\r\nManor, Texaexas\r\n272\r\nMarble Falls, Texas\r\n693\r\nMarion, Texas\r\n420\r\nMarshall Ford, Texas\r\n266\r\nMartindale, Texas\r\n357\r\nMartinez, Texas\r\n662\r\n666\r\n661\r\nMathis, Texas\r\n547\r\nMc Dade, Texas\r\n273\r\nMcAllen, Texas\r\n618\r\n630\r\n632\r\n638\r\n686\r\n687\r\n843\r\n631\r\n682\r\nMcCook, Texas\r\n842\r\nMedical Center, Texas\r\n513\r\n593\r\n593\r\n613\r\n614\r\n615\r\n616\r\n617\r\n989\r\nMedina, Texas\r\n589\r\nMedina Lake, Texas\r\n751\r\nMercedes, Texas\r\n514\r\n565\r\nMilano, Texas\r\n455\r\nMillett, Texas\r\n378\r\nMirando City, Texas\r\n586\r\nMission, Texas\r\n519\r\n580\r\n581\r\n585\r\nMontgomery, Texas\r\n677\r\nMoulton, Texas\r\n596\r\nMount Home, Texas\r\n866\r\nNew Bornfels, Texas\r\n608\r\n620\r\n625\r\n629\r\nNixon, Texas\r\n582\r\nNordheim, Texas\r\n938\r\nOak Island, Texas\r\n624\r\nOdem, Texas\r\n368\r\nOrange Grove, Texas\r\n384\r\nPaige, Texas\r\n253\r\nPalacios, Texas\r\n972\r\nPalo Alto, Texas\r\n628\r\nPawnee, Texas\r\n456\r\nPearsall, Texas\r\n317\r\n334\r\nPettus, Texas\r\n375\r\nPflugerville, Texas\r\n251\r\n990\r\nPharr, Texas\r\n702\r\n783\r\nPipe Creek, Texas\r\n535\r\nPleasanton, Texas\r\n315\r\n569\r\nPort Alto, Texas\r\n893\r\nPort Isabella, Texas\r\n761\r\n943\r\nPort Lavaca, Texas\r\n501\r\n552\r\n553\r\n920\r\nPoteet, Texas\r\n742\r\nPoth, Texas\r\n484\r\nPotranco, Texas\r\n679\r\nPremont, Texas\r\n348\r\nPoint Aransas, Texas\r\n749\r\nPoint Comfort, Texas\r\n987\r\nPoint Mansfield, Texas\r\n944\r\nPoint Oconner, Texas\r\n983\r\nPortland Gregory, Texas\r\n643\r\n777\r\nRachel, Texas\r\n391\r\nRaymondville, Texas\r\n689\r\nRefugio, Texas\r\n526\r\nRio Grande, Texas\r\n716\r\nRio Hondo, Texas\r\n748\r\nRiogrand City, Texas\r\n487\r\n500\r\nRiviera, Texas\r\n296\r\nRobstown, Texas\r\n387\r\n767\r\nRockdale, Texas\r\n446\r\nRockport, Texas\r\n729\r\n790\r\nRockspring, Texas\r\n683\r\nRocky Creek, Texas\r\n839\r\nRoma, Texas\r\n849\r\nRound Mount, Texas\r\n825\r\nRound Rock, Texas\r\n218\r\n244\r\n255\r\n388\r\nRunge, Texas\r\n239\r\nSabina, Texas\r\n537\r\nSabinal, Texas\r\n988\r\nSan Antonio, Texas\r\n555\r\nSan Benito, Texas\r\n361\r\n399\r\nSan Diego, Texas\r\n279\r\nSan Isidro, Texas\r\n481\r\nSan Marcos, Texas\r\n245\r\n353\r\n392\r\n396\r\n753\r\n754\r\nSan Miguel, Texas\r\n466\r\nSan Antonio, Texas\r\n203\r\n208\r\n212\r\n213\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n235\r\n240\r\n246\r\n260\r\n270\r\n271\r\n283\r\n299\r\n304\r\n308\r\n333\r\n337\r\n340\r\n341\r\n342\r\n344\r\n349\r\n351\r\n359\r\n366\r\n377\r\n410\r\n414\r\n415\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n470\r\n508\r\n518\r\n524\r\n525\r\n530\r\n531\r\n532\r\n533\r\n534\r\n536\r\n554\r\n603\r\n720\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n803\r\n804\r\n805\r\n807\r\n820\r\n821\r\n822\r\n824\r\n826\r\n827\r\n828\r\n829\r\n841\r\n861\r\n921\r\n922\r\n923\r\n924\r\n925\r\n927\r\n951\r\n954\r\n976\r\n977\r\n978\r\n979\r\nSandy Hills, Texas\r\n621\r\nSan Gabriel, Texas\r\n862\r\nSan Perlita, Texas\r\n248\r\nSanta Rosa, Texas\r\n636\r\nSarita, Texas\r\n294\r\nSattler, Texas\r\n964\r\nSaturn, Texas\r\n540\r\nSayers, Texas\r\n649\r\nSeadrift, Texas\r\n785\r\nSeguin, Texas\r\n372\r\n379\r\n401\r\n557\r\nShavano, Texas\r\n408\r\n492\r\n493\r\nShiner, Texas\r\n594\r\nSinton, Texas\r\n364\r\nSisterdale, Texas\r\n324\r\nSkidmore, Texas\r\n287\r\nSmiley, Texas\r\n587\r\nSmithson Valley, Texas\r\n885\r\nSmithville, Texas\r\n237\r\nSomerset, Texas\r\n429\r\n701\r\nSouthton, Texas\r\n633\r\nSaint Hedwig, Texas\r\n667\r\nSaint Herald Springs, Texas\r\n947\r\nStillman, Texas\r\n743\r\nStockdale, Texas\r\n996\r\nStonewall, Texas\r\n644\r\nSullivan City, Texas\r\n485\r\nTaft, Texas\r\n528\r\nTarpley, Texas\r\n562\r\nTaylor, Texas\r\n352\r\nTennyson, Texas\r\n339\r\n832\r\n834\r\n835\r\n836\r\n837\r\n873\r\n908\r\nThelma, Texas\r\n626\r\nThree Rivers, Texas\r\n786\r\nThrndlthrl, Texas\r\n898\r\nTilden, Texas\r\n274\r\nTivoli, Texas\r\n286\r\nTwinbrook, Texas\r\n892\r\nUniversal City, Texas\r\n652\r\n658\r\n659\r\n945\r\nUtopia, Texas\r\n966\r\nUvalde, Texas\r\n278\r\n591\r\nVanderbilt, Texas\r\n284\r\nVictoria, Texas\r\n503\r\n550\r\n571\r\n572\r\n573\r\n574\r\n575\r\n576\r\n578\r\n788\r\nVinegarron, Texas\r\n395\r\nWaelder, Texas\r\n665\r\nWalnut, Texas\r\n926\r\n928\r\n929\r\nWebberville\u00031/\u00032Walnut, Texas\r\n276\r\nWeslaco, Texas\r\n961\r\n962\r\n963\r\n968\r\n969\r\n974\r\nWesthoff, Texas\r\n236\r\nWetmore, Texas\r\n402\r\n490\r\n494\r\n496\r\n545\r\n491\r\nWillow City, Texas\r\n685\r\nWimberley, Texas\r\n847\r\nWoodsboro, Texas\r\n543\r\nYoakum, Texas\r\n293\r\n741\r\nYorktown, Texas\r\n564\r\nZapata, Texas\r\n765\r\n\u00035Unknown prefix code (512) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.513",
    "content": "Aberdeen, Ohio\r\n795\r\nAnna, Ohio\r\n394\r\nAnsonia, Ohio\r\n337\r\nArcanum, Ohio\r\n692\r\nBeavercreek, Ohio\r\n320\r\n426\r\n427\r\n429\r\nBelfast, Ohio\r\n764\r\nBellbrook, Ohio\r\n848\r\nBelle Center, Ohio\r\n464\r\nBellefontaine, Ohio\r\n592\r\n593\r\n597\r\n599\r\n935\r\nBethany, Ohio\r\n777\r\n779\r\nBethel, Ohio\r\n734\r\nBlanchestr, Ohio\r\n783\r\nBotkins, Ohio\r\n693\r\nBowersville, Ohio\r\n453\r\nBradford, Ohio\r\n448\r\nBrookville, Ohio\r\n833\r\nButlerville, Ohio\r\n877\r\nByhalia, Ohio\r\n982\r\nCamden, Ohio\r\n452\r\nCatawba, Ohio\r\n828\r\nCedarville, Ohio\r\n766\r\nCenterville, Ohio\r\n885\r\nChristensburg, Ohio\r\n857\r\nCincinnati, Ohio\r\n221\r\n231\r\n232\r\n234\r\n241\r\n242\r\n243\r\n244\r\n245\r\n247\r\n249\r\n251\r\n266\r\n269\r\n271\r\n272\r\n281\r\n284\r\n287\r\n301\r\n306\r\n321\r\n326\r\n343\r\n345\r\n346\r\n347\r\n350\r\n351\r\n352\r\n353\r\n357\r\n366\r\n369\r\n381\r\n385\r\n388\r\n389\r\n395\r\n396\r\n397\r\n421\r\n451\r\n458\r\n467\r\n469\r\n471\r\n474\r\n475\r\n479\r\n481\r\n482\r\n483\r\n489\r\n521\r\n522\r\n527\r\n530\r\n531\r\n532\r\n533\r\n535\r\n541\r\n542\r\n543\r\n551\r\n552\r\n554\r\n556\r\n557\r\n558\r\n559\r\n561\r\n562\r\n563\r\n565\r\n566\r\n569\r\n574\r\n579\r\n582\r\n589\r\n591\r\n595\r\n598\r\n621\r\n624\r\n626\r\n627\r\n629\r\n631\r\n632\r\n634\r\n641\r\n646\r\n648\r\n649\r\n651\r\n658\r\n659\r\n661\r\n662\r\n671\r\n672\r\n673\r\n679\r\n681\r\n684\r\n721\r\n723\r\n728\r\n729\r\n731\r\n733\r\n736\r\n739\r\n741\r\n742\r\n744\r\n745\r\n749\r\n751\r\n758\r\n761\r\n762\r\n763\r\n765\r\n768\r\n769\r\n771\r\n772\r\n782\r\n784\r\n786\r\n791\r\n792\r\n793\r\n801\r\n806\r\n821\r\n825\r\n827\r\n841\r\n851\r\n852\r\n853\r\n861\r\n871\r\n872\r\n891\r\n906\r\n921\r\n922\r\n923\r\n931\r\n941\r\n945\r\n948\r\n961\r\n972\r\n977\r\n983\r\n984\r\n985\r\nClarksville, Ohio\r\n289\r\nClermont, Ohio\r\n402\r\n528\r\n553\r\n732\r\n737\r\n752\r\n753\r\n755\r\n797\r\n943\r\nCovington, Ohio\r\n473\r\nDanville, Ohio\r\n288\r\nDayton, Ohio\r\n235\r\n238\r\n261\r\n279\r\n291\r\n330\r\n331\r\n334\r\n341\r\n356\r\n391\r\n463\r\n545\r\n546\r\n643\r\n220\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n233\r\n236\r\n237\r\n239\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\n262\r\n263\r\n267\r\n268\r\n274\r\n275\r\n276\r\n277\r\n278\r\n285\r\n286\r\n290\r\n293\r\n294\r\n296\r\n297\r\n298\r\n299\r\n433\r\n434\r\n435\r\n436\r\n438\r\n439\r\n443\r\n445\r\n449\r\n455\r\n457\r\n461\r\n476\r\n477\r\n478\r\n495\r\n496\r\n499\r\nDe Graff, Ohio\r\n585\r\nDecatur, Ohio\r\n373\r\nDonnelsville, Ohio\r\n882\r\nEast Liberty, Ohio\r\n666\r\nEast Richmond, Ohio\r\n966\r\nEaton, Ohio\r\n456\r\nEldorado, Ohio\r\n273\r\nEnglewood, Ohio\r\n832\r\n836\r\nEnon, Ohio\r\n864\r\nFairborn, Ohio\r\n754\r\n873\r\n878\r\n879\r\nFarmersville, Ohio\r\n696\r\nFayetteville, Ohio\r\n875\r\nFelicity, Ohio\r\n876\r\nFletcher Lane, Ohio\r\n368\r\nFranklin, Ohio\r\n743\r\n746\r\n748\r\nFort Loramie, Ohio\r\n295\r\nGeorgetown, Ohio\r\n378\r\nGermantown, Ohio\r\n855\r\nGettysburg, Ohio\r\n447\r\nGratis, Ohio\r\n787\r\nGreenfield, Ohio\r\n981\r\nGreenville, Ohio\r\n547\r\n548\r\nHamersville, Ohio\r\n379\r\nHamilton, Ohio\r\n706\r\n820\r\n822\r\n829\r\n844\r\n856\r\n858\r\n860\r\n863\r\n867\r\n868\r\n869\r\n870\r\n874\r\n881\r\n887\r\n892\r\n893\r\n894\r\n895\r\n896\r\nHarrison, Ohio\r\n340\r\n367\r\nHigginsport, Ohio\r\n375\r\nHillsboro, Ohio\r\n393\r\nHollansburg, Ohio\r\n997\r\nHuntsville, Ohio\r\n686\r\nJacksoncenter, Ohio\r\n596\r\nJamestown, Ohio\r\n675\r\nLaura, Ohio\r\n947\r\nLebanon, Ohio\r\n932\r\n933\r\nLeesburg, Ohio\r\n780\r\nLewisburg, Ohio\r\n962\r\nLiberty, Ohio\r\n835\r\nLittle Miami, Ohio\r\n248\r\n333\r\n575\r\n576\r\n583\r\n677\r\n683\r\n774\r\n831\r\nLynchburg, Ohio\r\n364\r\nMagnetic Springs, Ohio\r\n348\r\nManchester, Ohio\r\n549\r\nMarshall, Ohio\r\n466\r\nMartinsville, Ohio\r\n685\r\nMarysville, Ohio\r\n642\r\n644\r\n645\r\nMason, Ohio\r\n459\r\n398\r\n573\r\nMechanicsburg, Ohio\r\n847\r\n859\r\n865\r\n866\r\n834\r\nMedway, Ohio\r\n849\r\nMiddletown, Ohio\r\n420\r\n422\r\n423\r\n424\r\n425\r\n727\r\nMilford Center, Ohio\r\n349\r\nMonroe, Ohio\r\n539\r\nMorningsun, Ohio\r\n796\r\nMorrow, Ohio\r\n899\r\nMount Orab, Ohio\r\n444\r\nMount Victory, Ohio\r\n354\r\nMowrystown, Ohio\r\n442\r\nNew Lebanon, Ohio\r\n687\r\nNew Madison, Ohio\r\n996\r\nNew Paris, Ohio\r\n437\r\nNew Vienna, Ohio\r\n987\r\nNew Burlington, Ohio\r\n488\r\nNew Carlisle, Ohio\r\n845\r\n846\r\nNewtonsville, Ohio\r\n625\r\n722\r\nNorth Hampton, Ohio\r\n964\r\nNorth Lewisburg, Ohio\r\n747\r\nOxford, Ohio\r\n523\r\n529\r\n798\r\nPeebles, Ohio\r\n587\r\nPhillipsburg, Ohio\r\n884\r\nPiqua, Ohio\r\n773\r\n778\r\nPitchin, Ohio\r\n265\r\nPleasant Hill, Ohio\r\n676\r\nPort William, Ohio\r\n486\r\nRainsboro, Ohio\r\n365\r\nRaymond, Ohio\r\n246\r\nReily, Ohio\r\n756\r\n757\r\nRidgeway, Ohio\r\n363\r\nRipley, Ohio\r\n392\r\nRosewood, Ohio\r\n362\r\nRossburg, Ohio\r\n338\r\nRushsylvna, Ohio\r\n468\r\nRussells Point, Ohio\r\n842\r\n843\r\nRussellville, Ohio\r\n377\r\nSabina, Ohio\r\n584\r\nSardinia, Ohio\r\n446\r\nSeaman, Ohio\r\n386\r\nSeven Mile, Ohio\r\n726\r\nShandon, Ohio\r\n361\r\n738\r\nSidney, Ohio\r\n492\r\n497\r\n498\r\nSinking Spring, Ohio\r\n588\r\nSouth Charleston, Ohio\r\n462\r\nSouth Lebanon, Ohio\r\n494\r\nSouth Vienna, Ohio\r\n568\r\nSouthsolon, Ohio\r\n883\r\nSpring Valley, Ohio\r\n862\r\nSpringfield, Ohio\r\n322\r\n323\r\n324\r\n325\r\n327\r\n328\r\n390\r\n399\r\n342\r\nSaint Paris, Ohio\r\n663\r\nSugar Tower, Ohio\r\n927\r\nTerre Haute, Ohio\r\n788\r\nTipp City, Ohio\r\n667\r\nTremont City, Ohio\r\n969\r\nTrenton, Ohio\r\n988\r\nTrotwood, Ohio\r\n837\r\n854\r\nTroy, Ohio\r\n332\r\n335\r\n339\r\nUnion City, Ohio\r\n968\r\nUrbana, Ohio\r\n484\r\n652\r\n653\r\nVandalia, Ohio\r\n264\r\n454\r\n890\r\n898\r\nVersailles, Ohio\r\n526\r\nWest Alexandria, Ohio\r\n839\r\nWaynesville, Ohio\r\n897\r\nWest Liberty, Ohio\r\n465\r\nWest Manchester, Ohio\r\n678\r\nWest Mansfield, Ohio\r\n355\r\nWest Union, Ohio\r\n544\r\nWest Milton, Ohio\r\n698\r\nWilliamsburg, Ohio\r\n536\r\n724\r\nWilmington, Ohio\r\n382\r\n383\r\n725\r\nWinchester, Ohio\r\n695\r\nWoodstock, Ohio\r\n826\r\nXenia, Ohio\r\n372\r\n374\r\n376\r\nYellow Spring Cfton, Ohio\r\n767\r\nYork Center, Ohio\r\n358\r\n\u00035Unknown prefix code (513) - Ohio\r\n"
  },
  {
    "path": "install/regions/regions.514",
    "content": "Montral, Qubec, Canada\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n259\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n305\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n340\r\n341\r\n342\r\n343\r\n344\r\n345\r\n350\r\n351\r\n352\r\n353\r\n354\r\n355\r\n356\r\n362\r\n363\r\n364\r\n365\r\n366\r\n367\r\n368\r\n369\r\n374\r\n376\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n389\r\n390\r\n391\r\n393\r\n394\r\n395\r\n397\r\n398\r\n399\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n493\r\n495\r\n496\r\n497\r\n499\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n529\r\n556\r\n557\r\n558\r\n591\r\n592\r\n593\r\n594\r\n595\r\n597\r\n598\r\n599\r\n721\r\n722\r\n725\r\n727\r\n728\r\n729\r\n731\r\n733\r\n735\r\n736\r\n737\r\n738\r\n739\r\n741\r\n744\r\n745\r\n747\r\n748\r\n749\r\n761\r\n762\r\n765\r\n766\r\n767\r\n768\r\n769\r\n790\r\n840\r\n842\r\n843\r\n844\r\n845\r\n846\r\n848\r\n849\r\n861\r\n866\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n878\r\n879\r\n931\r\n932\r\n933\r\n934\r\n935\r\n936\r\n937\r\n939\r\n948\r\n951\r\n952\r\n953\r\n954\r\n956\r\n957\r\n981\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n989\r\n982\r\n986\r\n997\r\n998\r\nSaint Calixte De Kilkenny, Qubec, Canada\r\n222\r\nSaint-Sauveur, Qubec, Canada\r\n227\r\nKnowlton, Qubec, Canada\r\n242\r\n243\r\nHemmingford, Qubec, Canada\r\n247\r\nHuntingdon, Qubec, Canada\r\n264\r\nSainte-Blaise, Qubec, Canada\r\n291\r\nDunham, Qubec, Canada\r\n295\r\nHenryville, Qubec, Canada\r\n299\r\nSaint-Jean, Qubec, Canada\r\n348\r\n349\r\n346\r\n347\r\n358\r\n359\r\n886\r\nValleyfield, Qubec, Canada\r\n371\r\n373\r\n377\r\nGramby, Qubec, Canada\r\n372\r\n375\r\n378\r\n777\r\nSaint-Paul D'asbestos, Qubec, Canada\r\n379\r\n388\r\n392\r\n396\r\nRoxboro, Qubec, Canada\r\n421\r\n683\r\n684\r\n685\r\nSainte-Martine, Qubec, Canada\r\n427\r\nSaint-Jrme, Qubec, Canada\r\n438\r\n431\r\n432\r\n436\r\n565\r\nSaint-Bruno, Qubec, Canada\r\n441\r\n461\r\n653\r\nSaint-Lambert, Qubec, Canada\r\n443\r\n445\r\n462\r\n465\r\n466\r\n656\r\n671\r\n672\r\n676\r\n678\r\n923\r\n926\r\nBoucherville, Qubec, Canada\r\n449\r\n641\r\n655\r\nSaint-Rmi, Qubec, Canada\r\n454\r\nHudson, Qubec, Canada\r\n458\r\nTerrebonne, Qubec, Canada\r\n471\r\n492\r\n964\r\nMirabelle\u00031/\u00032St-Augustin, Qubec, Canada\r\n475\r\nOka, Qubec, Canada\r\n479\r\nBrownsburg, Qubec, Canada\r\n533\r\nSutton, Qubec, Canada\r\n538\r\nUpton, Qubec, Canada\r\n549\r\nVerchres, Qubec, Canada\r\n583\r\nContrecoeur, Qubec, Canada\r\n587\r\nSainte-Thrse, Qubec, Canada\r\n430\r\n433\r\n434\r\n435\r\n437\r\n621\r\n965\r\n979\r\nSainte-Rose, Laval, Qubec, Canada\r\n622\r\n625\r\n628\r\n963\r\nPont-Viau, Laval, Qubec, Canada\r\n629\r\n662\r\n663\r\n667\r\n668\r\n669\r\n967\r\n975\r\nLachine, Qubec, Canada\r\n422\r\n631\r\n633\r\n634\r\n636\r\n637\r\n639\r\nPointe-Aux-Trembles, Qubec, Canada\r\n494\r\n498\r\n552\r\n642\r\n643\r\n640\r\n644\r\n648\r\n645\r\nSainte-Julie De Verchres, Qubec, Canada\r\n649\r\n922\r\nLe Gardeur, Qubec, Canada\r\n581\r\n582\r\n585\r\n654\r\n657\r\nLa Prairie, Qubec, Canada\r\n444\r\n659\r\nDuvernay\u00031/\u00032Saint-Vicent-De-Paul, Laval, Qubec, Canada\r\n664\r\nChomedey, Laval, Qubec, Canada\r\n681\r\n682\r\n686\r\n687\r\n688\r\nChteaugay, Qubec, Canada\r\n691\r\n692\r\n698\r\n699\r\nPointe Claire, Qubec, Canada\r\n426\r\n428\r\n457\r\n630\r\n694\r\n695\r\n697\r\nJoliette, Qubec, Canada\r\n753\r\n759\r\n755\r\n756\r\nCte Du Lac, Qubec, Canada\r\n763\r\nSainte-Pie, Qubec, Canada\r\n772\r\nSaint-Pie, Qubec, Canada\r\n784\r\nYamaska, Qubec, Canada\r\n789\r\nSaint-Liboire, Qubec, Canada\r\n793\r\nSaint-Damase, Qubec, Canada\r\n797\r\nSainte-Christine, Qubec, Canada\r\n826\r\nSaint-Michel-Des-Saints, Qubec, Canada\r\n833\r\nSaint-Jacques, Qubec, Canada\r\n839\r\nSaint-Barthlmi, Qubec, Canada\r\n885\r\nSaint-Julie, Qubec, Canada\r\n922\r\nLaval Ouest, Qubec, Canada\r\n627\r\n689\r\n969\r\n962\r\nMascouche, Qubec, Canada\r\n474\r\n477\r\n966\r\n968\r\nBlainville, Qubec, Canada\r\n976\r\nShawbridge, Qubec, Canada\r\n224\r\nSainte-Marguerite, Qubec, Canada\r\n228\r\nVenenque, Qubec, Canada\r\n244\r\nBedford, Qubec, Canada\r\n248\r\nMirabelle\u00031/\u00032Sainte-Scholastique, Qubec, Canada\r\n258\r\nSaint-Polyc, Qubec, Canada\r\n265\r\nMansonville, Qubec, Canada\r\n292\r\nND Saint-Anbr, Qubec, Canada\r\n296\r\nVaudreuil, Qubec, Canada\r\n424\r\n455\r\nBeauharnois, Qubec, Canada\r\n429\r\n225\r\nLongueuil, Qubec, Canada\r\n442\r\n448\r\n468\r\n463\r\n646\r\n647\r\n651\r\n670\r\n674\r\n677\r\n679\r\n928\r\nBeloeil, Qubec, Canada\r\n467\r\n446\r\n464\r\nRiguad, Qubec, Canada\r\n451\r\nSainte-Marthe, Qubec, Canada\r\n459\r\nSaint-Eustache, Qubec, Canada\r\n472\r\n473\r\n491\r\n623\r\n974\r\nMirabel Aroport, Qubec, Canada\r\n476\r\nBromont, Qubec, Canada\r\n534\r\n776\r\nWaterloo, Qubec, Canada\r\n539\r\nLachute, Qubec, Canada\r\n562\r\nPierreville, Qubec, Canada\r\n568\r\nSaint-Marc, Qubec, Canada\r\n584\r\nL'piphanie-L'assomption, Qubec, Canada\r\n588\r\n589\r\nSainte-Genevive, Qubec, Canada\r\n620\r\n624\r\n696\r\n626\r\nSaint-Constant, Qubec, Canada\r\n632\r\n635\r\n638\r\nSaint-Vincent-De-Paul, Laval, Qubec, Canada\r\n661\r\n664\r\n665\r\nSorel, Qubec, Canada\r\n743\r\n742\r\n746\r\nSaint-Justin, Qubec, Canada\r\n764\r\nSaint-Hyacinte, Qubec, Canada\r\n773\r\n778\r\n774\r\nSaint-Hyacinthe, Qubec, Canada\r\n771\r\nSaint-Ours, Qubec, Canada\r\n785\r\nSaint-Hughes, Qubec, Canada\r\n794\r\nSaint-Simon, Qubec, Canada\r\n798\r\nFranklnct, Qubec, Canada\r\n827\r\nRawdon, Qubec, Canada\r\n834\r\n882\r\nSainte-Adle, Qubec, Canada\r\n229\r\nNapierville, Qubec, Canada\r\n245\r\nCteau LDG, Qubec, Canada\r\n267\r\nFarnham, Qubec, Canada\r\n293\r\nEast-Man, Qubec, Canada\r\n297\r\nIle Perrot, Qubec, Canada\r\n425\r\n453\r\nChambly, Qubec, Canada\r\n658\r\n447\r\nLes Cdres, Qubec, Canada\r\n452\r\nSaint-Clet, Qubec, Canada\r\n456\r\nMarieville, Qubec, Canada\r\n460\r\nLawrenceville, Qubec, Canada\r\n535\r\nActon Vale, Qubec, Canada\r\n546\r\nSaint-Hipolyte, Qubec, Canada\r\n563\r\nVarennes, Qubec, Canada\r\n652\r\nLaval Est, Qubec, Canada\r\n666\r\nPointe-Claire, Qubec, Canada\r\n695\r\nCrabtree, Qubec, Canada\r\n754\r\nSainte-Victoire, Qubec, Canada\r\n782\r\nSaint-Denis, Qubec, Canada\r\n787\r\nSaint-Hlne De Bagotteville, Qubec, Canada\r\n791\r\nSainte-Madeleine, Qubec, Canada\r\n795\r\nSainte-Rosalie, Qubec, Canada\r\n799\r\nOrmstown, Qubec, Canada\r\n829\r\nSaint-Gabriel-De-Brandon, Qubec, Canada\r\n835\r\nSaint-Adolphe, Qubec, Canada\r\n883\r\nLanoraie, Qubec, Canada\r\n887\r\nMorin Heights, Qubec, Canada\r\n226\r\nLacolle, Qubec, Canada\r\n246\r\nCowansville, Qubec, Canada\r\n263\r\nRiv Beaud, Qubec, Canada\r\n269\r\nClarenceville, Qubec, Canada\r\n294\r\nFrelighsburg, Qubec, Canada\r\n298\r\nSaint-Lin, Qubec, Canada\r\n439\r\nSaint-Csaire, Qubec, Canada\r\n469\r\nSainte-Anne-Des-Plaines, Qubec, Canada\r\n478\r\n838\r\nValcourt, Qubec, Canada\r\n532\r\nSaint-Andr Est, Qubec, Canada\r\n537\r\nRoxton Falls, Qubec, Canada\r\n548\r\nSaint-Zphirin, Qubec, Canada\r\n564\r\nLavaltrie, Qubec, Canada\r\n586\r\nPierrefonds, Qubec, Canada\r\n624\r\nBaiefbvre, Qubec, Canada\r\n783\r\nSaint-Aim, Qubec, Canada\r\n788\r\nSaint-Jude, Qubec, Canada\r\n792\r\nSaint-Thomas, Qubec, Canada\r\n796\r\nHowick, Qubec, Canada\r\n825\r\nSainte-Julienne, Qubec, Canada\r\n831\r\nBerthierville, Qubec, Canada\r\n836\r\nSaint-Zenon, Qubec, Canada\r\n884\r\nSaint-Flix, Qubec, Canada\r\n889\r\n\u00035Unknown prefix code (514) - Qubec, Canada\r\n"
  },
  {
    "path": "install/regions/regions.515",
    "content": "Ackley, Iowa\r\n847\r\nAdair, Iowa\r\n742\r\nAdel, Iowa\r\n993\r\nAfton, Iowa\r\n347\r\nAgency, Iowa\r\n937\r\nAlbia, Iowa\r\n932\r\nAlbion, Iowa\r\n488\r\nAlden, Iowa\r\n859\r\nAlexander, Iowa\r\n692\r\nAlgona, Iowa\r\n320\r\n295\r\nAllerton, Iowa\r\n873\r\nAlta Vista, Iowa\r\n364\r\nAltoona, Iowa\r\n967\r\nAmes, Iowa\r\n231\r\n290\r\n291\r\n232\r\n233\r\n239\r\n292\r\n294\r\n296\r\nAmund, Iowa\r\n298\r\nAnkeny, Iowa\r\n964\r\n965\r\nAredale, Iowa\r\n894\r\nArispe, Iowa\r\n346\r\nAttica, Iowa\r\n943\r\nBadger, Iowa\r\n545\r\nBagley, Iowa\r\n427\r\nBailey, Iowa\r\n329\r\nBancroft, Iowa\r\n885\r\nBarnes City, Iowa\r\n644\r\nBarnum, Iowa\r\n542\r\nBatavia, Iowa\r\n662\r\nBaxter, Iowa\r\n227\r\nBelmond, Iowa\r\n444\r\nBenton, Iowa\r\n785\r\nBladensburg, Iowa\r\n934\r\nBlairsburg, Iowa\r\n325\r\nBlakesburg, Iowa\r\n938\r\nBlockton, Iowa\r\n788\r\nBloomfield, Iowa\r\n664\r\nBoone, Iowa\r\n230\r\n330\r\n432\r\n433\r\nBouton, Iowa\r\n676\r\nBoxholm, Iowa\r\n846\r\nBradgate, Iowa\r\n375\r\nBridgewater, Iowa\r\n369\r\nBristow, Iowa\r\n775\r\nBritt, Iowa\r\n843\r\nBrooklyn, Iowa\r\n522\r\nBuckeye, Iowa\r\n855\r\nBuffalo Center, Iowa\r\n561\r\n562\r\nBurt, Iowa\r\n924\r\nBussey, Iowa\r\n944\r\nCallender, Iowa\r\n548\r\nCambridge, Iowa\r\n383\r\nCarlisle, Iowa\r\n989\r\nCasey, Iowa\r\n740\r\n746\r\nCenterville, Iowa\r\n437\r\n856\r\nChariton, Iowa\r\n774\r\nCharles City, Iowa\r\n220\r\n228\r\n257\r\nChelsea, Iowa\r\n489\r\nChillicoth, Iowa\r\n935\r\nChurdan, Iowa\r\n389\r\nCincinnati, Iowa\r\n658\r\nClare, Iowa\r\n546\r\nClarion, Iowa\r\n532\r\nClear Lake, Iowa\r\n355\r\n357\r\nClearfield, Iowa\r\n336\r\nClemons, Iowa\r\n477\r\nColfax, Iowa\r\n674\r\nCollins, Iowa\r\n385\r\nColo, Iowa\r\n377\r\nConrad, Iowa\r\n366\r\nCorning, Iowa\r\n322\r\nCorwith, Iowa\r\n583\r\nCorydon, Iowa\r\n872\r\nCoulter, Iowa\r\n866\r\nCreston, Iowa\r\n782\r\nCrystal Lake, Iowa\r\n565\r\nDallas Center, Iowa\r\n992\r\nDavis City, Iowa\r\n442\r\nDawson, Iowa\r\n428\r\nDayton, Iowa\r\n547\r\nDe Soto, Iowa\r\n834\r\nDeep River, Iowa\r\n595\r\nDelta, Iowa\r\n624\r\nDerby, Iowa\r\n533\r\nDes Moines, Iowa\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n229\r\n237\r\n238\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n262\r\n263\r\n265\r\n266\r\n270\r\n271\r\n274\r\n276\r\n277\r\n278\r\n279\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n830\r\nDexter, Iowa\r\n789\r\nDiagonal, Iowa\r\n734\r\nDouds, Iowa\r\n936\r\nDougherty, Iowa\r\n794\r\nDows, Iowa\r\n852\r\nDrakesville, Iowa\r\n722\r\nDumont, Iowa\r\n857\r\nDuncombe, Iowa\r\n543\r\nEagle Grove, Iowa\r\n448\r\nEarlham, Iowa\r\n758\r\nEddyville, Iowa\r\n969\r\nEldon, Iowa\r\n652\r\nEldora, Iowa\r\n858\r\nElkhart, Iowa\r\n367\r\nEllsworth, Iowa\r\n836\r\nElma, Iowa\r\n393\r\nFairfield, Iowa\r\n469\r\n472\r\nFarnhamville, Iowa\r\n544\r\nFarson, Iowa\r\n655\r\nFenton, Iowa\r\n889\r\nFerguson, Iowa\r\n478\r\nFertile, Iowa\r\n797\r\nFloris, Iowa\r\n459\r\nFloyd, Iowa\r\n398\r\nFontanelle, Iowa\r\n745\r\nForest City, Iowa\r\n581\r\n582\r\nFort Dodge, Iowa\r\n570\r\n571\r\n573\r\n576\r\n955\r\nFremont, Iowa\r\n933\r\nGarden Grove, Iowa\r\n443\r\nGarden City, Iowa\r\n893\r\nGarner, Iowa\r\n923\r\nGarwin, Iowa\r\n499\r\nGeneva, Iowa\r\n458\r\nGilman, Iowa\r\n498\r\nGilmore City, Iowa\r\n373\r\nGladbrook, Iowa\r\n473\r\nGoldfield, Iowa\r\n825\r\nGoodell, Iowa\r\n495\r\nGowrie, Iowa\r\n352\r\nGrafton, Iowa\r\n748\r\nGrand Junction, Iowa\r\n738\r\nGrand River, Iowa\r\n773\r\nGranger, Iowa\r\n999\r\nGreen Mountain, Iowa\r\n474\r\nGreene, Iowa\r\n823\r\nGreenfield, Iowa\r\n343\r\n743\r\nGrimes, Iowa\r\n986\r\nGrinnell, Iowa\r\n260\r\n236\r\n269\r\nGuthrie Center, Iowa\r\n747\r\nHampton, Iowa\r\n456\r\nHanlontown, Iowa\r\n896\r\nHarcourt, Iowa\r\n354\r\nHarper, Iowa\r\n635\r\nHaverhill, Iowa\r\n475\r\nHedrick, Iowa\r\n653\r\nHubbard, Iowa\r\n864\r\nHumboldt, Iowa\r\n332\r\nHumeston, Iowa\r\n877\r\nHuxley, Iowa\r\n597\r\nIndianola, Iowa\r\n961\r\nIowa Falls, Iowa\r\n640\r\n648\r\nJamaica, Iowa\r\n429\r\nJefferson, Iowa\r\n370\r\n945\r\n386\r\nJewell, Iowa\r\n827\r\nJoice, Iowa\r\n590\r\n588\r\nKamrar, Iowa\r\n539\r\nKanawha, Iowa\r\n762\r\nKellerton, Iowa\r\n783\r\nKelley, Iowa\r\n769\r\nKellogg, Iowa\r\n526\r\nKensett, Iowa\r\n845\r\nKent, Iowa\r\n348\r\nKeota, Iowa\r\n636\r\nKillduff, Iowa\r\n798\r\nKlemme, Iowa\r\n587\r\nKnierim, Iowa\r\n463\r\nKnoxville, Iowa\r\n820\r\n828\r\n842\r\nLacona, Iowa\r\n534\r\nLake Mills, Iowa\r\n592\r\nLakota, Iowa\r\n886\r\nLamoni, Iowa\r\n784\r\nLanyon, Iowa\r\n879\r\nLatimer, Iowa\r\n580\r\n589\r\n579\r\nLaurel, Iowa\r\n476\r\nLe Grand, Iowa\r\n479\r\nLedyard, Iowa\r\n646\r\n888\r\nLehigh, Iowa\r\n359\r\nLeighton, Iowa\r\n626\r\nLeland, Iowa\r\n567\r\nLenox, Iowa\r\n333\r\nLeon, Iowa\r\n446\r\nLiberty Center, Iowa\r\n466\r\nLibertyville, Iowa\r\n693\r\nLinden, Iowa\r\n744\r\nLineville, Iowa\r\n876\r\nLiscomb, Iowa\r\n496\r\nLivermore, Iowa\r\n379\r\nLone Rock, Iowa\r\n925\r\nLorimor, Iowa\r\n763\r\nLovilia, Iowa\r\n946\r\nLittle Cedar, Iowa\r\n983\r\nLucas, Iowa\r\n766\r\nLuverne, Iowa\r\n882\r\nLynnville, Iowa\r\n527\r\nMacksburg, Iowa\r\n768\r\nMadrid, Iowa\r\n795\r\nMalcom, Iowa\r\n528\r\nManly, Iowa\r\n454\r\nMarble Rock, Iowa\r\n397\r\nMark, Iowa\r\n929\r\nMarshallton, Iowa\r\n750\r\n751\r\n752\r\n753\r\n754\r\nMartensdale, Iowa\r\n764\r\nMartinsburg, Iowa\r\n661\r\nMason City, Iowa\r\n420\r\n421\r\n423\r\n424\r\n425\r\n430\r\n450\r\nMaxwell, Iowa\r\n387\r\nMcCallsburg, Iowa\r\n434\r\nMelbourne, Iowa\r\n482\r\nMelcher, Iowa\r\n947\r\nMelrose, Iowa\r\n726\r\nMenlo, Iowa\r\n524\r\nMeservey, Iowa\r\n358\r\nMiller, Iowa\r\n927\r\nMillerton, Iowa\r\n897\r\nMilo, Iowa\r\n942\r\nMilton, Iowa\r\n656\r\nMinburn, Iowa\r\n677\r\nMingo, Iowa\r\n363\r\nMona, Iowa\r\n326\r\nMonroe, Iowa\r\n259\r\nMontezuma, Iowa\r\n623\r\nMontour, Iowa\r\n492\r\nMoorland, Iowa\r\n549\r\nMoravia, Iowa\r\n724\r\nMoulton, Iowa\r\n642\r\nMount Ayr, Iowa\r\n464\r\nMurray, Iowa\r\n447\r\nMystic, Iowa\r\n647\r\nNashua, Iowa\r\n435\r\nNevada, Iowa\r\n382\r\nNevinville, Iowa\r\n345\r\nNew Haven, Iowa\r\n982\r\nNew Provid, Iowa\r\n497\r\nNew Sharon, Iowa\r\n637\r\nNew Virgna, Iowa\r\n449\r\nNew Hampton, Iowa\r\n394\r\nNewton, Iowa\r\n840\r\n849\r\n791\r\n792\r\nNora Springs, Iowa\r\n749\r\nNorthwood, Iowa\r\n324\r\nNorwalk, Iowa\r\n981\r\nOgden, Iowa\r\n275\r\nOllie, Iowa\r\n667\r\nOrient, Iowa\r\n337\r\nOsage, Iowa\r\n732\r\nOsceola, Iowa\r\n340\r\n342\r\nOskaloosa, Iowa\r\n660\r\n669\r\n670\r\n672\r\n673\r\nOtho, Iowa\r\n972\r\nOtley, Iowa\r\n627\r\nOttumwa, Iowa\r\n680\r\n777\r\n779\r\n799\r\n682\r\n683\r\n684\r\nPanora, Iowa\r\n755\r\nPaton, Iowa\r\n968\r\nPella, Iowa\r\n628\r\nPeoria, Iowa\r\n625\r\nPerry, Iowa\r\n465\r\nPeru, Iowa\r\n728\r\nPilotmound, Iowa\r\n353\r\nPlano, Iowa\r\n649\r\nPleasantville, Iowa\r\n848\r\nPlymouth, Iowa\r\n696\r\nPolk City, Iowa\r\n984\r\nPrairie City, Iowa\r\n994\r\nPrescott, Iowa\r\n335\r\nPromise City, Iowa\r\n874\r\nPulaski, Iowa\r\n675\r\nRadcliffe, Iowa\r\n899\r\nRake, Iowa\r\n566\r\nRandall, Iowa\r\n328\r\nReasnor, Iowa\r\n793\r\nRedding, Iowa\r\n767\r\nRedfield, Iowa\r\n833\r\nRenwick, Iowa\r\n824\r\nRhodes, Iowa\r\n493\r\nRiceville, Iowa\r\n985\r\nRippey, Iowa\r\n436\r\nRockford, Iowa\r\n756\r\nRockwell, Iowa\r\n822\r\nRoland, Iowa\r\n388\r\nRose Hill, Iowa\r\n632\r\nRowan, Iowa\r\n853\r\nRudd, Iowa\r\n395\r\nRunnells, Iowa\r\n966\r\nRussell, Iowa\r\n535\r\nScarville, Iowa\r\n568\r\nSearsboro, Iowa\r\n593\r\nSeymour, Iowa\r\n898\r\nShannon City, Iowa\r\n339\r\nSharpsburg, Iowa\r\n349\r\nSheffield, Iowa\r\n892\r\nSigourney, Iowa\r\n622\r\nSlater, Iowa\r\n685\r\nSouth Emmons, Iowa\r\n293\r\nSomers, Iowa\r\n467\r\nSouthadams, Iowa\r\n586\r\nSaint Ansgar, Iowa\r\n736\r\nSaint Charles, Iowa\r\n396\r\nSaint Marys, Iowa\r\n297\r\nStacyville, Iowa\r\n737\r\nStanhope, Iowa\r\n826\r\nState Center, Iowa\r\n483\r\nSteamboat Rock, Iowa\r\n868\r\nStevens, Iowa\r\n948\r\nStory City, Iowa\r\n733\r\nStratford, Iowa\r\n838\r\nStuart, Iowa\r\n523\r\nSully, Iowa\r\n594\r\nSwaledale, Iowa\r\n995\r\nSwea City, Iowa\r\n272\r\nThayer, Iowa\r\n338\r\nThompson, Iowa\r\n584\r\nThor, Iowa\r\n378\r\nThornton, Iowa\r\n998\r\nTingley, Iowa\r\n772\r\nTitonka, Iowa\r\n928\r\nToledo, Iowa\r\n484\r\nTracy, Iowa\r\n949\r\nTruro, Iowa\r\n765\r\nUnion, Iowa\r\n486\r\nUnionville, Iowa\r\n452\r\nVan Meter, Iowa\r\n996\r\nVentura, Iowa\r\n829\r\nVincent, Iowa\r\n356\r\nWaukee, Iowa\r\n987\r\nWebster City, Iowa\r\n832\r\n835\r\nWeldon, Iowa\r\n445\r\nWellsburg, Iowa\r\n869\r\nWesley, Iowa\r\n679\r\nWest Bend, Iowa\r\n887\r\nWhat Cheer, Iowa\r\n634\r\nWhittemore, Iowa\r\n884\r\nWilliams, Iowa\r\n854\r\nWilliamson, Iowa\r\n862\r\nWinterset, Iowa\r\n468\r\n462\r\nWoden, Iowa\r\n926\r\nWoodward, Iowa\r\n438\r\nWoolstock, Iowa\r\n839\r\nYale, Iowa\r\n439\r\nZearing, Iowa\r\n487\r\n\u00035Unknown prefix code (515) - Iowa\r\n"
  },
  {
    "path": "install/regions/regions.516",
    "content": "Albany, New York\r\n518\r\nAmagansett, New York\r\n267\r\n329\r\nAmityville, New York\r\n264\r\n598\r\n691\r\n789\r\n842\r\nAtlantic, New York\r\n281\r\n395\r\n399\r\nBabylon, New York\r\n321\r\n422\r\n587\r\n661\r\n669\r\n893\r\nBay Shore, New York\r\n665\r\n666\r\n968\r\nBayport, New York\r\n363\r\n472\r\nBellport, New York\r\n286\r\nBrentwood, New York\r\n230\r\n268\r\n272\r\n275\r\n276\r\n278\r\n279\r\n339\r\n342\r\n429\r\n441\r\n442\r\n853\r\n854\r\n951\r\n952\r\n231\r\n233\r\n273\r\n434\r\n435\r\n436\r\nBridgehampton, New York\r\n537\r\nCentral Islip, New York\r\n232\r\n234\r\n348\r\n438\r\n582\r\n851\r\n859\r\nCold Spring Harbor, New York\r\n367\r\n692\r\nCommack, New York\r\n543\r\n864\r\nCtrmorichs, New York\r\n874\r\n878\r\nDeer Park, New York\r\n241\r\n274\r\n242\r\n243\r\n254\r\n492\r\n586\r\n595\r\n667\r\n955\r\nEast Fire Island, New York\r\n597\r\nEast Hampton, New York\r\n324\r\nEastport, New York\r\n325\r\nFarmingdale, New York\r\n249\r\n293\r\n391\r\n420\r\n454\r\n531\r\n577\r\n694\r\n752\r\n753\r\n755\r\n756\r\n844\r\n845\r\n847\r\n777\r\n843\r\nFire Island, New York\r\n583\r\nFishers Island, New York\r\n788\r\nGreenport, New York\r\n477\r\nHampton Bays, New York\r\n723\r\n728\r\nHuntington, New York\r\n271\r\n351\r\n385\r\n421\r\n423\r\n424\r\n425\r\n427\r\n547\r\n549\r\n673\r\nIslip, New York\r\n224\r\n277\r\n581\r\nJamesport, New York\r\n722\r\nKings Park, New York\r\n269\r\n544\r\nLindenhurst, New York\r\n225\r\n226\r\n884\r\n888\r\n841\r\n956\r\n957\r\nMattituck, New York\r\n298\r\nMidland, New York\r\n221\r\n253\r\n491\r\n639\r\n643\r\nMineola, New York\r\n222\r\n223\r\n227\r\n228\r\n229\r\n235\r\n236\r\n237\r\n238\r\n239\r\n248\r\n252\r\n255\r\n270\r\n285\r\n292\r\n294\r\n295\r\n296\r\n299\r\n326\r\n328\r\n333\r\n334\r\n336\r\n338\r\n346\r\n349\r\n352\r\n354\r\n357\r\n358\r\n364\r\n365\r\n371\r\n374\r\n378\r\n379\r\n394\r\n431\r\n432\r\n433\r\n437\r\n463\r\n466\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n496\r\n520\r\n521\r\n526\r\n535\r\n536\r\n538\r\n541\r\n542\r\n546\r\n559\r\n560\r\n561\r\n562\r\n564\r\n565\r\n566\r\n568\r\n569\r\n574\r\n575\r\n576\r\n579\r\n593\r\n596\r\n599\r\n621\r\n623\r\n624\r\n625\r\n626\r\n627\r\n628\r\n629\r\n644\r\n647\r\n656\r\n658\r\n663\r\n671\r\n674\r\n676\r\n677\r\n678\r\n679\r\n681\r\n682\r\n683\r\n684\r\n686\r\n731\r\n733\r\n735\r\n739\r\n741\r\n742\r\n745\r\n746\r\n747\r\n759\r\n763\r\n764\r\n766\r\n767\r\n773\r\n775\r\n781\r\n783\r\n785\r\n791\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\n822\r\n823\r\n824\r\n825\r\n826\r\n829\r\n832\r\n833\r\n867\r\n868\r\n869\r\n872\r\n873\r\n876\r\n877\r\n883\r\n887\r\n889\r\n890\r\n897\r\n921\r\n922\r\n926\r\n931\r\n932\r\n933\r\n934\r\n935\r\n937\r\n938\r\n939\r\n942\r\n943\r\n944\r\n949\r\n950\r\n997\r\nMontauk Point, New York\r\n668\r\nLong Island, New York\r\n974\r\n327\r\n355\r\n594\r\n256\r\n792\r\n245\r\n251\r\n291\r\n297\r\n332\r\n337\r\n356\r\n384\r\n392\r\n428\r\n456\r\n522\r\n528\r\n571\r\n572\r\n573\r\n657\r\n659\r\n793\r\n891\r\n892\r\n925\r\n954\r\n972\r\n975\r\n539\r\n335\r\n377\r\nNorthport, New York\r\n261\r\n262\r\n754\r\n757\r\nOrient, New York\r\n323\r\nPatchogue, New York\r\n550\r\n687\r\n289\r\n447\r\n475\r\n654\r\n758\r\nPeconic, New York\r\n734\r\nPoint Jefferson, New York\r\n331\r\n473\r\n474\r\n476\r\n928\r\nQuogue, New York\r\n653\r\nRiverhead, New York\r\n852\r\n284\r\n369\r\n548\r\n727\r\n729\r\n953\r\nRonkonkoma, New York\r\n467\r\n468\r\n471\r\n585\r\n588\r\n737\r\n981\r\nSag Harbor, New York\r\n725\r\nSayville, New York\r\n244\r\n563\r\n567\r\n589\r\nSelden, New York\r\n383\r\n443\r\n527\r\n451\r\n696\r\n698\r\n732\r\n736\r\nShelter Island, New York\r\n749\r\nShoreham, New York\r\n265\r\n360\r\n361\r\n366\r\n382\r\n388\r\n724\r\n744\r\n821\r\n979\r\nSmithtown, New York\r\n263\r\nSouthampton, New York\r\n283\r\n287\r\nSouthold, New York\r\n765\r\nSaint James, New York\r\n584\r\n862\r\nStonybrook, New York\r\n246\r\n444\r\n632\r\n689\r\n751\r\n941\r\nWading River, New York\r\n929\r\nWater Mill, New York\r\n726\r\nWest Commack, New York\r\n266\r\n368\r\n462\r\n493\r\n499\r\nWesthampton, New York\r\n288\r\nYaphank, New York\r\n344\r\n282\r\n341\r\n345\r\n924\r\n\u00035Unknown prefix code (516) - New York\r\n"
  },
  {
    "path": "install/regions/regions.517",
    "content": "Addison, Michigan\r\n547\r\nAdrian, Michigan\r\n260\r\n263\r\n264\r\n265\r\nAkron, Michigan\r\n691\r\nAlbion, Michigan\r\n629\r\nAlger, Michigan\r\n836\r\nAllen, Michigan\r\n869\r\nAlma, Michigan\r\n463\r\n466\r\nAlpena, Michigan\r\n370\r\n354\r\n356\r\nAshley, Michigan\r\n847\r\nAtlanta, Michigan\r\n785\r\nAu Gres, Michigan\r\n876\r\nAuburn, Michigan\r\n662\r\nBad Axe, Michigan\r\n269\r\nBancroft, Michigan\r\n634\r\nBarryton, Michigan\r\n382\r\nBath, Michigan\r\n641\r\nBay City, Michigan\r\n220\r\n329\r\n330\r\n667\r\n684\r\n686\r\n751\r\n892\r\n893\r\n894\r\n895\r\nBay Port, Michigan\r\n656\r\nBeaverton, Michigan\r\n435\r\nBell Oak, Michigan\r\n468\r\nBirch Run, Michigan\r\n624\r\nBlanchard, Michigan\r\n561\r\nBlissfield, Michigan\r\n486\r\nBrant, Michigan\r\n585\r\nBreckenridge, Michigan\r\n842\r\nBritton, Michigan\r\n451\r\nBronson, Michigan\r\n369\r\nBrooklyn, Michigan\r\n592\r\nBundy Hill, Michigan\r\n688\r\nBurlington, Michigan\r\n765\r\nCambria, Michigan\r\n357\r\nCamden, Michigan\r\n368\r\nCaro, Michigan\r\n670\r\n672\r\n673\r\nCarson City, Michigan\r\n584\r\nCaseville, Michigan\r\n856\r\nCass City, Michigan\r\n872\r\nChapin, Michigan\r\n661\r\nCharlotte, Michigan\r\n543\r\nChesaning, Michigan\r\n845\r\nChester, Michigan\r\n939\r\nClare, Michigan\r\n240\r\n386\r\nClark Lake, Michigan\r\n529\r\nClayton, Michigan\r\n445\r\nClifford, Michigan\r\n761\r\nClinton, Michigan\r\n456\r\nColdwater Lake, Michigan\r\n238\r\nColdwater, Michigan\r\n278\r\n279\r\nColeman, Michigan\r\n465\r\nConcord, Michigan\r\n524\r\nCrystal, Michigan\r\n235\r\nDansville, Michigan\r\n623\r\nDe Witt, Michigan\r\n669\r\nDeerfield, Michigan\r\n447\r\nDimondale, Michigan\r\n646\r\nDurand, Michigan\r\n288\r\nEast Tawas, Michigan\r\n362\r\nEaton Rapids, Michigan\r\n663\r\nEdmore, Michigan\r\n427\r\nElkton, Michigan\r\n375\r\nElsie, Michigan\r\n862\r\nFairgrove, Michigan\r\n693\r\nFairview, Michigan\r\n848\r\nFarwell, Michigan\r\n544\r\n588\r\nFenwick, Michigan\r\n248\r\nFitchburg, Michigan\r\n565\r\nFostoria, Michigan\r\n795\r\nFowlerville, Michigan\r\n223\r\nFowler Pwam, Michigan\r\n593\r\nFranknmuth, Michigan\r\n652\r\nFreeland, Michigan\r\n696\r\n695\r\nFrontier, Michigan\r\n254\r\nGagetown, Michigan\r\n665\r\nGaines, Michigan\r\n271\r\nGaylord, Michigan\r\n350\r\n731\r\n732\r\nGladwin, Michigan\r\n426\r\nGlennie, Michigan\r\n735\r\nGrace Harbor, Michigan\r\n938\r\nGrand Ledge, Michigan\r\n626\r\n627\r\nGrass Lake, Michigan\r\n522\r\nGrayling, Michigan\r\n348\r\nHale, Michigan\r\n728\r\nHanover, Michigan\r\n563\r\nHarbor Beach, Michigan\r\n479\r\nHarrison, Michigan\r\n539\r\nHarrisville, Michigan\r\n724\r\nHemlock, Michigan\r\n642\r\nHiggins Lake, Michigan\r\n821\r\nHillman, Michigan\r\n742\r\nHillsdale, Michigan\r\n437\r\n439\r\nHolt, Michigan\r\n694\r\n699\r\nHomer, Michigan\r\n568\r\nHope, Michigan\r\n689\r\nHoughtonlk, Michigan\r\n366\r\n422\r\nHowell, Michigan\r\n545\r\n546\r\n548\r\nHubbard Lake, Michigan\r\n727\r\nHubbardston, Michigan\r\n981\r\nHudson, Michigan\r\n448\r\nIthaca, Michigan\r\n875\r\nJackson, Michigan\r\n250\r\n499\r\n780\r\n840\r\n850\r\n740\r\n750\r\n764\r\n769\r\n782\r\n783\r\n784\r\n787\r\n788\r\n789\r\nJonesville, Michigan\r\n849\r\nKinde, Michigan\r\n874\r\nKingston, Michigan\r\n683\r\nLachine, Michigan\r\n379\r\nLaingsburg, Michigan\r\n651\r\nLakeview, Michigan\r\n352\r\nLansing, Michigan\r\n290\r\n333\r\n340\r\n341\r\n481\r\n570\r\n580\r\n930\r\n321\r\n322\r\n323\r\n331\r\n332\r\n334\r\n335\r\n336\r\n337\r\n339\r\n342\r\n347\r\n349\r\n351\r\n353\r\n355\r\n360\r\n363\r\n371\r\n372\r\n373\r\n374\r\n377\r\n393\r\n394\r\n482\r\n483\r\n484\r\n485\r\n487\r\n881\r\n882\r\n885\r\n886\r\n887\r\nLeslie, Michigan\r\n589\r\nLewiston, Michigan\r\n786\r\nLincoln, Michigan\r\n736\r\nLinwood, Michigan\r\n697\r\nLitchfield, Michigan\r\n542\r\nLong Lake, Michigan\r\n595\r\nLupton, Michigan\r\n473\r\nManisteerv, Michigan\r\n925\r\nMaple Rapids, Michigan\r\n682\r\nMarlette, Michigan\r\n635\r\nMason, Michigan\r\n251\r\n676\r\nMayville, Michigan\r\n843\r\nMcbrides, Michigan\r\n762\r\nMerrill, Michigan\r\n643\r\nMiddleton, Michigan\r\n236\r\nMidland, Michigan\r\n496\r\n631\r\n636\r\n638\r\n832\r\n835\r\n837\r\n839\r\nMillington, Michigan\r\n871\r\nMinden City, Michigan\r\n864\r\nMio, Michigan\r\n826\r\nMontgomery, Michigan\r\n296\r\nMorenci, Michigan\r\n458\r\nMosherville, Michigan\r\n549\r\nMount Pleasant, Michigan\r\n560\r\n772\r\n773\r\n774\r\nMuir, Michigan\r\n855\r\nMulliken, Michigan\r\n649\r\nMunger, Michigan\r\n659\r\nMunith, Michigan\r\n596\r\nNapoleon, Michigan\r\n536\r\nNashville, Michigan\r\n852\r\nNorthadams, Michigan\r\n287\r\nOgden Center, Michigan\r\n443\r\nOmer, Michigan\r\n653\r\nOnaway, Michigan\r\n733\r\nOnondaga, Michigan\r\n628\r\nOnsted, Michigan\r\n467\r\nOscoda, Michigan\r\n739\r\n747\r\nOsseo, Michigan\r\n523\r\nOssineke, Michigan\r\n471\r\nOvid, Michigan\r\n834\r\nOwendale, Michigan\r\n678\r\nOwosso, Michigan\r\n723\r\n725\r\n743\r\nPalo, Michigan\r\n637\r\nParma, Michigan\r\n531\r\nPerry, Michigan\r\n625\r\nPigeon, Michigan\r\n550\r\n453\r\nPinconning, Michigan\r\n879\r\nPompeii, Michigan\r\n838\r\nPort Hope, Michigan\r\n428\r\nPort Austin, Michigan\r\n738\r\nPortland, Michigan\r\n647\r\nPosen, Michigan\r\n766\r\nPotterville, Michigan\r\n645\r\nPrattville, Michigan\r\n383\r\nPrescott, Michigan\r\n873\r\nQuincy, Michigan\r\n639\r\nRansom, Michigan\r\n567\r\nReading, Michigan\r\n283\r\nReese, Michigan\r\n868\r\nRemus, Michigan\r\n967\r\nRiverdale, Michigan\r\n833\r\nRives Junction, Michigan\r\n569\r\nRogers City, Michigan\r\n734\r\nRoscommon, Michigan\r\n275\r\nRose City, Michigan\r\n685\r\nRosebush, Michigan\r\n433\r\nSaginaw, Michigan\r\n298\r\n797\r\n830\r\n870\r\n890\r\n920\r\n730\r\n752\r\n753\r\n754\r\n755\r\n757\r\n758\r\n759\r\n770\r\n771\r\n776\r\n777\r\n781\r\n790\r\n791\r\n792\r\n793\r\n798\r\n799\r\nSand Creek, Michigan\r\n436\r\nSandlk Heights, Michigan\r\n469\r\nSanford, Michigan\r\n687\r\nSebewaing, Michigan\r\n883\r\nShaftsburg, Michigan\r\n675\r\nShepherd, Michigan\r\n828\r\nSheridan, Michigan\r\n291\r\nSidney, Michigan\r\n328\r\nSix Lakes, Michigan\r\n365\r\nSixty Lakes, Michigan\r\n257\r\nSpringport, Michigan\r\n857\r\nSaint Charles, Michigan\r\n865\r\nSaint Helen, Michigan\r\n389\r\nSaint Johns, Michigan\r\n224\r\nSaint Louis, Michigan\r\n681\r\nStandish, Michigan\r\n846\r\nStanton, Michigan\r\n831\r\nSterling, Michigan\r\n654\r\nStockbridge, Michigan\r\n851\r\nSunfield, Michigan\r\n566\r\nTecumseh, Michigan\r\n423\r\nTekonsha, Michigan\r\n767\r\nTipton, Michigan\r\n431\r\nTwining, Michigan\r\n867\r\nUbly, Michigan\r\n658\r\nUnion City, Michigan\r\n741\r\nUnionville, Michigan\r\n674\r\nVanderbilt, Michigan\r\n983\r\nVassar, Michigan\r\n823\r\nVermontville, Michigan\r\n726\r\nVestaburg, Michigan\r\n268\r\nVickeryville, Michigan\r\n261\r\nWaldron, Michigan\r\n286\r\nWebberville, Michigan\r\n521\r\nWeidman, Michigan\r\n644\r\nWestbranch, Michigan\r\n345\r\nWestphalia, Michigan\r\n587\r\nWhittemore, Michigan\r\n756\r\nWilliamstn, Michigan\r\n655\r\nWinn, Michigan\r\n866\r\n\u00035Unknown prefix code (517) - Michigan\r\n"
  },
  {
    "path": "install/regions/regions.518",
    "content": "Albany, New York\r\n435\r\n977\r\n262\r\n367\r\n396\r\n421\r\n427\r\n431\r\n433\r\n446\r\n448\r\n469\r\n478\r\n484\r\n488\r\n495\r\n496\r\n540\r\n920\r\n422\r\n423\r\n424\r\n426\r\n428\r\n432\r\n434\r\n436\r\n437\r\n438\r\n439\r\n442\r\n443\r\n445\r\n447\r\n449\r\n451\r\n453\r\n454\r\n455\r\n457\r\n458\r\n459\r\n462\r\n463\r\n465\r\n467\r\n470\r\n471\r\n472\r\n473\r\n474\r\n475\r\n476\r\n477\r\n479\r\n482\r\n485\r\n486\r\n487\r\n489\r\n890\r\nAltamont, New York\r\n861\r\nAmsterdam, New York\r\n841\r\n842\r\n843\r\nArgyle, New York\r\n638\r\nAthens, New York\r\n945\r\nAusable Fork, New York\r\n647\r\nAverill Park, New York\r\n674\r\nBallstnspa, New York\r\n884\r\n885\r\nBerlin, New York\r\n658\r\nBerne, New York\r\n872\r\nBlue Mt, New York\r\n352\r\nBolton Lodge, New York\r\n644\r\nBrainrdsville, New York\r\n425\r\nBramanville, New York\r\n296\r\nBroadalbin, New York\r\n883\r\nCairo, New York\r\n622\r\nCambridge, New York\r\n677\r\nCanaan, New York\r\n781\r\nCanajharie, New York\r\n673\r\nCarogalake, New York\r\n835\r\nCastleton, New York\r\n732\r\nCatskill, New York\r\n943\r\nCentral Bridge, New York\r\n231\r\n868\r\nChamplain, New York\r\n298\r\nChateaugay, New York\r\n497\r\nChatham, New York\r\n392\r\nChazy, New York\r\n846\r\nChestertn, New York\r\n494\r\nClarksville, New York\r\n768\r\nClaverack, New York\r\n851\r\nCobleskill, New York\r\n234\r\nColonie, New York\r\n464\r\n498\r\n782\r\n452\r\n456\r\n783\r\n785\r\n786\r\n869\r\nCopake, New York\r\n329\r\nCorinth, New York\r\n654\r\nCoxsackie, New York\r\n731\r\nCrownpoint, New York\r\n597\r\nDannemora, New York\r\n492\r\nDelanson, New York\r\n895\r\nElenburg Dpt, New York\r\n594\r\nElizabethton, New York\r\n873\r\nEsperance, New York\r\n875\r\nFonda, New York\r\n853\r\nFort Ann, New York\r\n639\r\nFort Covington, New York\r\n358\r\nFort Plain, New York\r\n993\r\nFreehold, New York\r\n634\r\nGalway, New York\r\n882\r\nGermantown, New York\r\n537\r\nGlen, New York\r\n922\r\nGlens Falls, New York\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n761\r\n792\r\n793\r\n796\r\n798\r\nGloversville, New York\r\n224\r\n774\r\n725\r\n773\r\nGranville, New York\r\n642\r\nGreenville, New York\r\n966\r\nGreenwich, New York\r\n692\r\nGreenfield Center, New York\r\n893\r\nHague, New York\r\n543\r\nHampton, New York\r\n282\r\nHartford, New York\r\n632\r\nHillsdale, New York\r\n325\r\nHoosick Falls, New York\r\n686\r\nHudson, New York\r\n821\r\n822\r\n828\r\nHunter, New York\r\n263\r\nIndian Lake, New York\r\n648\r\nJohnstown, New York\r\n736\r\n762\r\nJonesville, New York\r\n877\r\nKattskill Bay, New York\r\n656\r\nKeene, New York\r\n576\r\nKeeseville, New York\r\n834\r\nKinderhook, New York\r\n755\r\n758\r\n784\r\n799\r\nLake Luzern, New York\r\n696\r\nLake Placid, New York\r\n523\r\nLake Pleasant, New York\r\n548\r\nLake George, New York\r\n668\r\nLexington, New York\r\n989\r\nLong Lake, New York\r\n624\r\nLyon Mt, New York\r\n735\r\nMalone, New York\r\n481\r\n483\r\nMariaville, New York\r\n864\r\nMayfield, New York\r\n661\r\nMechanicville, New York\r\n664\r\nMiddleburg, New York\r\n295\r\n827\r\nMillerton, New York\r\n789\r\nMineville, New York\r\n942\r\nMoira, New York\r\n529\r\nMooers, New York\r\n236\r\nNassau, New York\r\n766\r\nNewcomb, New York\r\n582\r\nNorth Creek, New York\r\n251\r\nNorthville, New York\r\n863\r\nOak Hill, New York\r\n239\r\nPalenville, New York\r\n678\r\nPaulsmiths, New York\r\n327\r\nPeru, New York\r\n643\r\nPhilmont, New York\r\n672\r\nPineplains, New York\r\n398\r\nPittstown, New York\r\n663\r\nPlattsburg, New York\r\n569\r\n572\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\nPort Henry, New York\r\n546\r\nPrattsville, New York\r\n299\r\nPutnam, New York\r\n547\r\nRavena, New York\r\n756\r\nRichmondville, New York\r\n294\r\nRotterdam Junction, New York\r\n887\r\nRound Lake, New York\r\n899\r\nRouses Point, New York\r\n297\r\nSalem, New York\r\n854\r\nSaranac Lake, New York\r\n891\r\n897\r\nSaranac, New York\r\n293\r\nSaratoga Springs, New York\r\n581\r\n583\r\n584\r\n587\r\nSchenectady, New York\r\n346\r\n355\r\n356\r\n370\r\n371\r\n372\r\n374\r\n377\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n393\r\n395\r\n399\r\n341\r\n342\r\n344\r\n347\r\n357\r\n373\r\nSchroon Lake, New York\r\n532\r\nSchuylerville, New York\r\n695\r\nSharon Springs, New York\r\n284\r\nSouth Bethlehem, New York\r\n767\r\nSaint Johnsville, New York\r\n568\r\nStephenton, New York\r\n733\r\nSaint Regis Falls, New York\r\n856\r\nSummit, New York\r\n287\r\nTannersville, New York\r\n589\r\nTiconderoga, New York\r\n585\r\nTribes Hill, New York\r\n829\r\nTroy, New York\r\n238\r\n233\r\n235\r\n237\r\n266\r\n270\r\n271\r\n272\r\n273\r\n274\r\n276\r\n279\r\n283\r\n285\r\n286\r\nTupperlake, New York\r\n359\r\nValley Falls, New York\r\n753\r\nVoorheesville, New York\r\n765\r\nWarrensburg, New York\r\n623\r\nWells, New York\r\n924\r\nWest Chazy, New York\r\n493\r\nWest Lebanon, New York\r\n794\r\nWesterlo, New York\r\n797\r\nWestport, New York\r\n962\r\nWhitehall, New York\r\n499\r\nWillsboro, New York\r\n963\r\nWilmington, New York\r\n946\r\nWindham, New York\r\n734\r\n\u00035Unknown prefix code (518) - New York\r\n"
  },
  {
    "path": "install/regions/regions.519",
    "content": "Aberarder, Ontario, Canada\r\n899\r\nActon, Ontario, Canada\r\n853\r\nAilsacraig, Ontario, Canada\r\n293\r\nAlvinston, Ontario, Canada\r\n898\r\n847\r\nAmherstburg, Ontario, Canada\r\n736\r\nArkona, Ontario, Canada\r\n828\r\nArthur, Ontario, Canada\r\n848\r\nAtwood, Ontario, Canada\r\n356\r\nAuburn, Ontario, Canada\r\n526\r\nAylmer, Ontario, Canada\r\n765\r\n773\r\nAyr, Ontario, Canada\r\n632\r\nAyton, Ontario, Canada\r\n665\r\nBaden, Ontario, Canada\r\n634\r\nBayfield, Ontario, Canada\r\n565\r\nBeachville, Ontario, Canada\r\n423\r\nBelle River, Ontario, Canada\r\n728\r\nBelmont, Ontario, Canada\r\n644\r\nBlenheim, Ontario, Canada\r\n676\r\nBlyth, Ontario, Canada\r\n523\r\nBothwell, Ontario, Canada\r\n695\r\nBrantford, Ontario, Canada\r\n751\r\n752\r\n753\r\n754\r\n756\r\n758\r\n759\r\nBreslau, Ontario, Canada\r\n648\r\nBrigden, Ontario, Canada\r\n864\r\nBright, Ontario, Canada\r\n454\r\nBrights Grove, Ontario, Canada\r\n869\r\nBrownsville, Ontario, Canada\r\n877\r\nBrussels, Ontario, Canada\r\n887\r\nBurford, Ontario, Canada\r\n449\r\nBurgessville, Ontario, Canada\r\n424\r\nCaledon, Ontario, Canada\r\n927\r\nCargill, Ontario, Canada\r\n366\r\nCentralia, Ontario, Canada\r\n228\r\nChatham, Ontario, Canada\r\n351\r\n352\r\n354\r\n358\r\n436\r\nChatsworth, Ontario, Canada\r\n794\r\nChesley, Ontario, Canada\r\n363\r\nClifford, Ontario, Canada\r\n327\r\nClinton, Ontario, Canada\r\n233\r\n482\r\nComber, Ontario, Canada\r\n687\r\nCorunna, Ontario, Canada\r\n481\r\n862\r\nCottam, Ontario, Canada\r\n839\r\nCourtright, Ontario, Canada\r\n431\r\n867\r\nCrediton, Ontario, Canada\r\n234\r\nDashwood, Ontario, Canada\r\n237\r\nDelhi, Ontario, Canada\r\n582\r\nDorchester, Ontario, Canada\r\n268\r\nDrayton, Ontario, Canada\r\n638\r\nDresden, Ontario, Canada\r\n683\r\nDrumbo, Ontario, Canada\r\n463\r\nDublin, Ontario, Canada\r\n345\r\nDundalk, Ontario, Canada\r\n923\r\nDungannon, Ontario, Canada\r\n529\r\nDurham, Ontario, Canada\r\n369\r\nDutton, Ontario, Canada\r\n762\r\nDyer Bay, Ontario, Canada\r\n795\r\nEastwood, Ontario, Canada\r\n467\r\nElmira, Ontario, Canada\r\n669\r\nElora, Ontario, Canada\r\n846\r\nEmbro, Ontario, Canada\r\n475\r\nEmeryville, Ontario, Canada\r\n727\r\nErin, Ontario, Canada\r\n833\r\nEssex, Ontario, Canada\r\n776\r\nExeter, Ontario, Canada\r\n235\r\nFergus, Ontario\r\n787\r\nFergus, Ontario, Canada\r\n843\r\nFeversham, Ontario, Canada\r\n922\r\nFingal, Ontario, Canada\r\n769\r\nFlesherton, Ontario, Canada\r\n924\r\nForest, Ontario, Canada\r\n786\r\nGalt, Ontario, Canada\r\n621\r\n622\r\n623\r\n624\r\n740\r\nGlencoe, Ontario, Canada\r\n287\r\nGoderich, Ontario, Canada\r\n524\r\nGorrie, Ontario, Canada\r\n335\r\nGrand Bend, Ontario, Canada\r\n238\r\nGrand Valley, Ontario, Canada\r\n928\r\nGranton, Ontario, Canada\r\n225\r\nGuelph, Ontario, Canada\r\n763\r\n766\r\n767\r\n821\r\n822\r\n823\r\n824\r\n836\r\n837\r\nHanover, Ontario, Canada\r\n364\r\nHarrietsville, Ontario, Canada\r\n269\r\nHarriston, Ontario, Canada\r\n338\r\nHarrow, Ontario, Canada\r\n738\r\nHensall Inlet, Ontario, Canada\r\n263\r\nHensall, Ontario, Canada\r\n262\r\nHepworth, Ontario, Canada\r\n935\r\nHespeler, Ontario, Canada\r\n240\r\n241\r\n651\r\n654\r\n658\r\nHickson, Ontario, Canada\r\n462\r\nHighgate, Ontario, Canada\r\n678\r\nHillsburgh, Ontario, Canada\r\n855\r\nHolstein, Ontario, Canada\r\n334\r\nIlderton, Ontario, Canada\r\n666\r\nIngersoll, Ontario, Canada\r\n425\r\n485\r\nInnerkip, Ontario, Canada\r\n469\r\nInwood, Ontario, Canada\r\n844\r\nJarvis, Ontario, Canada\r\n587\r\nKerwood, Ontario, Canada\r\n247\r\nKincardine, Ontario, Canada\r\n396\r\nKingsville, Ontario, Canada\r\n733\r\nKintore, Ontario, Canada\r\n283\r\nKirkton, Ontario, Canada\r\n229\r\nKitchener-Wtl, Ontario, Canada\r\n570\r\n576\r\n578\r\n579\r\n725\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n884\r\n885\r\n886\r\n888\r\n893\r\n894\r\n895\r\n896\r\n571\r\n572\r\n575\r\n883\r\nLa Salle, Ontario, Canada\r\n734\r\n978\r\nLambeth, Ontario, Canada\r\n652\r\nLangton, Ontario, Canada\r\n875\r\nLeamington, Ontario, Canada\r\n322\r\n326\r\nLinwood, Ontario, Canada\r\n698\r\nLions Head, Ontario, Canada\r\n793\r\nListowel, Ontario, Canada\r\n291\r\nLondon, Ontario, Canada\r\n430\r\n457\r\n474\r\n640\r\n680\r\n850\r\n858\r\n878\r\n432\r\n433\r\n434\r\n438\r\n439\r\n451\r\n452\r\n453\r\n455\r\n471\r\n472\r\n473\r\n641\r\n642\r\n643\r\n645\r\n646\r\n649\r\n657\r\n659\r\n660\r\n661\r\n663\r\n667\r\n668\r\n670\r\n671\r\n672\r\n673\r\n675\r\n679\r\n681\r\n685\r\n686\r\n771\r\nLucan, Ontario, Canada\r\n227\r\nLucknow, Ontario, Canada\r\n528\r\nLynden, Ontario, Canada\r\n647\r\nMaidstone, Ontario, Canada\r\n737\r\nMarkdale, Ontario, Canada\r\n986\r\nMcgregor, Ontario, Canada\r\n726\r\nMeaford, Ontario, Canada\r\n538\r\nMelbourne, Ontario, Canada\r\n289\r\nMerlin, Ontario, Canada\r\n689\r\nMildmay, Ontario, Canada\r\n367\r\nMilverton, Ontario, Canada\r\n595\r\nMitchell, Ontario, Canada\r\n348\r\nMonkton, Ontario, Canada\r\n347\r\nMount Brydges, Ontario, Canada\r\n264\r\nMount Forest, Ontario, Canada\r\n323\r\nMount Pleasant, Ontario, Canada\r\n484\r\nNairn, Ontario, Canada\r\n232\r\nNeustadt, Ontario, Canada\r\n799\r\nNew Dundee, Ontario, Canada\r\n696\r\nNew Hamburg, Ontario, Canada\r\n662\r\nNorwich Inlet, Ontario, Canada\r\n468\r\nNorwich, Ontario, Canada\r\n863\r\nOhsweken, Ontario, Canada\r\n445\r\nOil Springs, Ontario, Canada\r\n834\r\nOrangeville, Ontario, Canada\r\n940\r\n941\r\n942\r\nOtterville, Ontario, Canada\r\n879\r\nOwen Sound, Ontario, Canada\r\n372\r\n371\r\n376\r\nPaisley, Ontario, Canada\r\n353\r\nPalmerston, Ontario, Canada\r\n343\r\nParis, Ontario, Canada\r\n442\r\nParkhill, Ontario, Canada\r\n294\r\nPelee Isle, Ontario, Canada\r\n724\r\nPetrolia, Ontario, Canada\r\n882\r\nPlattsville, Ontario, Canada\r\n684\r\nPleasant Park, Ontario, Canada\r\n723\r\nPort Dover, Ontario, Canada\r\n583\r\nPort Elgin, Ontario, Canada\r\n389\r\n832\r\nPort Rowan, Ontario, Canada\r\n586\r\nPort Franks, Ontario, Canada\r\n243\r\nPreston, Ontario, Canada\r\n650\r\n653\r\nPrinceton, Ontario, Canada\r\n458\r\nPort Burwell, Ontario, Canada\r\n874\r\nPort Lambton, Ontario, Canada\r\n677\r\nPort Stanley, Ontario, Canada\r\n782\r\nRidgetown, Ontario, Canada\r\n674\r\nRipley, Ontario, Canada\r\n395\r\nRockwood, Ontario, Canada\r\n856\r\nRodney, Ontario, Canada\r\n785\r\nSarina, Ontario, Canada\r\n332\r\n336\r\n337\r\n339\r\n344\r\n383\r\n542\r\n464\r\n541\r\nSauble Beach, Ontario, Canada\r\n422\r\nScotland, Ontario, Canada\r\n446\r\nSeaforth, Ontario, Canada\r\n527\r\nSebringville, Ontario, Canada\r\n393\r\nSefthindpt, Ontario, Canada\r\n522\r\nShakespear, Ontario, Canada\r\n625\r\nShedden, Ontario, Canada\r\n764\r\nShelburne, Ontario, Canada\r\n925\r\nSimcoe, Ontario, Canada\r\n426\r\n428\r\nSombra, Ontario, Canada\r\n892\r\nSouthmpton, Ontario, Canada\r\n797\r\nSparta, Ontario, Canada\r\n775\r\nSaint Clemnts, Ontario, Canada\r\n699\r\nSaint George, Ontario, Canada\r\n448\r\nSaint Jacobs, Ontario, Canada\r\n664\r\nSaint Marys, Ontario, Canada\r\n284\r\nSaint Thomas, Ontario, Canada\r\n637\r\n631\r\n633\r\nStokes Bay, Ontario, Canada\r\n592\r\nStoney Point, Ontario, Canada\r\n798\r\nStrafordville, Ontario, Canada\r\n866\r\nStratford, Ontario, Canada\r\n271\r\n272\r\n273\r\nStrathroy, Ontario, Canada\r\n245\r\n246\r\nStreetsville, Ontario, Canada\r\n567\r\nTara, Ontario, Canada\r\n934\r\nTavistock, Ontario, Canada\r\n655\r\nTecumseh, Ontario, Canada\r\n735\r\n979\r\nTeeswater, Ontario, Canada\r\n392\r\nThamesford, Ontario, Canada\r\n285\r\nThamesville, Ontario, Canada\r\n692\r\nThedford, Ontario, Canada\r\n296\r\nThornbury, Ontario, Canada\r\n599\r\nThorndale, Ontario, Canada\r\n461\r\nTilbury, Ontario, Canada\r\n682\r\nTillsonburg, Ontario, Canada\r\n688\r\n842\r\nTiverton, Ontario, Canada\r\n361\r\n368\r\nTobermory, Ontario, Canada\r\n596\r\nUniondale, Ontario, Canada\r\n349\r\nWalkerton, Ontario, Canada\r\n881\r\nWallaceburg, Ontario, Canada\r\n627\r\nWardsville, Ontario, Canada\r\n693\r\nWaterford, Ontario, Canada\r\n443\r\nWatford In, Ontario, Canada\r\n849\r\nWatford, Ontario, Canada\r\n876\r\nWellesley, Ontario, Canada\r\n656\r\nWest Lorne, Ontario, Canada\r\n768\r\nWheatley, Ontario, Canada\r\n825\r\nWiarton, Ontario, Canada\r\n534\r\nWindsor, Ontario, Canada\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n792\r\n944\r\n945\r\n948\r\n966\r\n969\r\n971\r\n972\r\n973\r\n974\r\n977\r\nWingham, Ontario, Canada\r\n357\r\nWoodslee, Ontario, Canada\r\n975\r\nWoodstock In, Ontario, Canada\r\n456\r\nWoodstock, Ontario, Canada\r\n421\r\n537\r\n539\r\nWyoming, Ontario, Canada\r\n845\r\nZurich, Ontario, Canada\r\n236\r\n\u00035Unknown prefix code (519) - Ontario, Canada\r\n"
  },
  {
    "path": "install/regions/regions.520",
    "content": "Prescott, Arizona\r\n775\r\n776\r\nYuma, Arizona\r\n305\r\n317\r\n539\r\n580\r\n920\r\n328\r\n329\r\n341\r\n342\r\n343\r\n344\r\n726\r\n782\r\n783\r\n\u00035Unknown prefix code (602) - Arizona\r\n"
  },
  {
    "path": "install/regions/regions.523",
    "content": "Guadalajara, Mexico\r\n523\r\n\u00035Unknown prefix code (523) - Mexico\r\n"
  },
  {
    "path": "install/regions/regions.524",
    "content": "\u00032Mexico City, Mexico\u00030\r\n524\r\n525\r\n\u00035Unknown prefix code (524) - Mexico\r\n"
  },
  {
    "path": "install/regions/regions.525",
    "content": "Mexico City, Mexico\r\n524\r\n525\r\n577\r\nMexico City, Polanco, Mexico\r\n282\r\nMexico City, Doctores, Mexico\r\n519\r\n\u00035Unknown prefix code (525) - Mexico\r\n"
  },
  {
    "path": "install/regions/regions.526",
    "content": "\u00032Mexico City, Mexico\u00030\r\n526\r\nTijuana, Mexico\r\n686\r\n\u00035Unknown prefix code (526) - Mexico\r\n"
  },
  {
    "path": "install/regions/regions.528",
    "content": "Monterrey, Mexico\r\n528\r\n\u00035Unknown prefix code (528) - Mexico\r\n"
  },
  {
    "path": "install/regions/regions.540",
    "content": "Abingdon, Virginia\r\n623\r\n628\r\n676\r\nAlum Ridge, Virginia\r\n763\r\nAppalachia, Virginia\r\n565\r\nArarat, Virginia\r\n251\r\nAustinville, Virginia\r\n699\r\nAxton, Virginia\r\n650\r\nBallard, Virginia\r\n593\r\nBassett, Virginia\r\n627\r\n629\r\nBasye, Virginia\r\n856\r\nBedford, Virginia\r\n871\r\n586\r\n587\r\nBent Mountain, Virginia\r\n929\r\nBergton, Virginia\r\n852\r\nBerryville, Virginia\r\n955\r\nBig Prater, Virginia\r\n597\r\nBig Rock, Virginia\r\n530\r\nBig Stonegap, Virginia\r\n523\r\nBig Meadows, Virginia\r\n423\r\nBlacksburg, Virginia\r\n231\r\n232\r\n552\r\n770\r\n951\r\n953\r\n961\r\nBland, Virginia\r\n688\r\nBlue Grass, Virginia\r\n474\r\nBluefield, Virginia\r\n322\r\n326\r\nBluemont, Virginia\r\n554\r\nBoones Mill, Virginia\r\n334\r\nBoyce, Virginia\r\n837\r\nBridgewater, Virginia\r\n828\r\nBristol, Virginia\r\n466\r\n645\r\n669\r\nBroadway, Virginia\r\n896\r\nBrokenburg, Virginia\r\n895\r\nBrownsburg, Virginia\r\n348\r\nBurnt Chimney, Virginia\r\n721\r\nBuchanan, Virginia\r\n254\r\nBuenavista, Virginia\r\n261\r\n570\r\nBurks Garden, Virginia\r\n472\r\nCalverton, Virginia\r\n788\r\nCana, Virginia\r\n755\r\nCatoctin, Virginia\r\n668\r\n822\r\n882\r\nCeres, Virginia\r\n682\r\nChancellor, Virginia\r\n786\r\n972\r\nChilhowie, Virginia\r\n646\r\nChristnsburg, Virginia\r\n381\r\n382\r\nClifton Forge, Virginia\r\n862\r\n863\r\nClinchco, Virginia\r\n835\r\nClinchport, Virginia\r\n940\r\nClintwood, Virginia\r\n926\r\nCmrsrk Elc, Virginia\r\n655\r\nCoeburn, Virginia\r\n395\r\nCollinsville, Virginia\r\n647\r\n340\r\nCovington, Virginia\r\n962\r\n965\r\n969\r\nCraigsville, Virginia\r\n997\r\nCriglersville, Virginia\r\n923\r\nCripple Creek, Virginia\r\n621\r\nCrows Hemt, Virginia\r\n559\r\nCulpeper, Virginia\r\n262\r\n399\r\n547\r\n825\r\n829\r\n937\r\nCumberland Gap, Virginia\r\n861\r\nDahlgren, Virginia\r\n653\r\n663\r\nDamascus, Virginia\r\n475\r\nDante, Virginia\r\n495\r\nDavenport, Virginia\r\n859\r\nDayton, Virginia\r\n879\r\nDeerfield, Virginia\r\n939\r\nDublin, Virginia\r\n674\r\nDuffield, Virginia\r\n431\r\nDungannon, Virginia\r\n467\r\nDwight, Virginia\r\n259\r\nEagle Rock, Virginia\r\n884\r\nEdinburg, Virginia\r\n333\r\n984\r\nEdom, Virginia\r\n833\r\nElkton, Virginia\r\n298\r\nElk Wallow, Virginia\r\n420\r\nFalmouth, Virginia\r\n899\r\nFerrum, Virginia\r\n365\r\nFieldale, Virginia\r\n673\r\nFincastle, Virginia\r\n473\r\nFloyd, Virginia\r\n745\r\nFort Valley, Virginia\r\n933\r\nFredericksburg, Virginia\r\n371\r\n372\r\n373\r\n785\r\n891\r\n898\r\n220\r\n374\r\n840\r\nFries, Virginia\r\n744\r\nFront Royal, Virginia\r\n622\r\n635\r\n636\r\nFort Blackmoor, Virginia\r\n995\r\nGainesboro, Virginia\r\n888\r\nGainesville, Virginia\r\n341\r\nGalax, Virginia\r\n236\r\n238\r\nGate City, Virginia\r\n386\r\nGlade Spring, Virginia\r\n429\r\nGlasgow, Virginia\r\n258\r\nGordonsville, Virginia\r\n832\r\nGore, Virginia\r\n858\r\nGreenwood, Virginia\r\n456\r\nGrottoes, Virginia\r\n249\r\nGrundy, Virginia\r\n935\r\nHarrisonburg, Virginia\r\n564\r\n574\r\n432\r\n433\r\n434\r\n568\r\nHartwood, Virginia\r\n752\r\nHaysi, Virginia\r\n865\r\n728\r\nHinton, Virginia\r\n867\r\nHonaker, Virginia\r\n873\r\n991\r\nHot Springs, Virginia\r\n839\r\nHurley, Virginia\r\n566\r\nIndependence, Virginia\r\n773\r\nJewell Ridge, Virginia\r\n881\r\nJonesville, Virginia\r\n346\r\nKeezletown, Virginia\r\n269\r\nKing George, Virginia\r\n775\r\nKonnarock, Virginia\r\n388\r\nLaurel Fork, Virginia\r\n398\r\nLebanon, Virginia\r\n794\r\n880\r\n889\r\nLee, Virginia\r\n445\r\n464\r\nLexington, Virginia\r\n460\r\n462\r\n463\r\nLocust Grove, Virginia\r\n651\r\nLouisa, Virginia\r\n967\r\nLuray, Virginia\r\n743\r\nMadison, Virginia\r\n543\r\n948\r\nMarion, Virginia\r\n782\r\n783\r\nMarshall, Virginia\r\n364\r\nMartinsville, Virginia\r\n656\r\n632\r\n638\r\n666\r\n634\r\nMaxie, Virginia\r\n531\r\nMax Meadows, Virginia\r\n637\r\nMcClung, Virginia\r\n996\r\nMcDowell, Virginia\r\n396\r\nMcGaheysville, Virginia\r\n289\r\nMeadows of Dan, Virginia\r\n952\r\nMeadowview, Virginia\r\n944\r\nMiddleburg, Virginia\r\n687\r\nMill Gap, Virginia\r\n499\r\nMineral, Virginia\r\n872\r\n894\r\nMonterey, Virginia\r\n468\r\nMontvale, Virginia\r\n947\r\nMorrison City, Virginia\r\n225\r\nMount Solon, Virginia\r\n350\r\nMount Gilead, Virginia\r\n338\r\nMount Grove, Virginia\r\n279\r\nMount Jackson, Virginia\r\n477\r\nMth Wilson, Virginia\r\n579\r\nNarrows, Virginia\r\n726\r\nNatural Bridge, Virginia\r\n291\r\nNew Castle, Virginia\r\n864\r\nNew Hope, Virginia\r\n363\r\nNew Market, Virginia\r\n740\r\nNewport, Virginia\r\n544\r\nNickelsville, Virginia\r\n479\r\nNorton, Virginia\r\n870\r\n973\r\n679\r\nOakwood, Virginia\r\n498\r\nOrange, Virginia\r\n672\r\nOriskany, Virginia\r\n567\r\nPaint Bank, Virginia\r\n897\r\nPearisburg, Virginia\r\n599\r\n921\r\nPembroke, Virginia\r\n626\r\nPennington Gap, Virginia\r\n546\r\nPocahontas, Virginia\r\n945\r\nPottscreek, Virginia\r\n747\r\nPound, Virginia\r\n796\r\nPulaski, Virginia\r\n980\r\n994\r\nRadford, Virginia\r\n230\r\n320\r\n633\r\n639\r\n731\r\n831\r\nRaphine, Virginvirginia\r\n377\r\nRemington, Virginia\r\n439\r\nRichlands, Virginia\r\n963\r\n964\r\nRich Valley, Virginia\r\n624\r\nRidgeway, Virginia\r\n956\r\nRoanoke, Virginia\r\n390\r\n427\r\n853\r\n954\r\n224\r\n265\r\n342\r\n343\r\n344\r\n345\r\n362\r\n366\r\n520\r\n561\r\n562\r\n563\r\n580\r\n772\r\n774\r\n776\r\n857\r\n890\r\n977\r\n981\r\n982\r\n983\r\n985\r\n986\r\n989\r\nRocky Gap, Virginia\r\n928\r\nRocky Mount, Virginia\r\n483\r\n489\r\nRural Retreat, Virginia\r\n686\r\nSalem, Virginia\r\n375\r\n380\r\n384\r\n387\r\n389\r\nSaltville, Virginia\r\n496\r\nShawsville, Virginia\r\n268\r\nShenandoah Park, Virginia\r\n999\r\nShenandoah, Virginia\r\n652\r\nSpencer, Virginia\r\n957\r\nSperryville, Virginia\r\n987\r\nSpotsylvania, Virginia\r\n582\r\nSaint Charles, Virginia\r\n383\r\nSaint Paul, Virginia\r\n738\r\n762\r\nStafford, Virginia\r\n657\r\n659\r\n720\r\nStanley, Virginia\r\n778\r\nStaunton, Virginia\r\n245\r\n480\r\n248\r\n332\r\n337\r\n885\r\n886\r\n887\r\nStephens City, Virginia\r\n869\r\nStone Mountain, Virginia\r\n297\r\nStrasburg, Virginia\r\n465\r\nStuart, Virginia\r\n694\r\nSugar Grove, Virginia\r\n677\r\nSylvatus, Virginia\r\n766\r\nTazewell, Virginia\r\n988\r\nThe Plains, Virginia\r\n253\r\nToms Brook, Virginia\r\n436\r\nTroutville, Virginia\r\n966\r\n992\r\nUnion Hall, Virginia\r\n576\r\nUnionville, Virginia\r\n854\r\nUpperville, Virginia\r\n592\r\nWarrenton, Virginia\r\n270\r\n347\r\n349\r\nWaynesboro, Virginia\r\n470\r\n932\r\n942\r\n943\r\n946\r\n949\r\nWeyers Cave, Virginia\r\n234\r\nWilliams Mill, Virginia\r\n452\r\n925\r\nWillis, Virginia\r\n789\r\nWinchester, Virginia\r\n336\r\n542\r\n662\r\n665\r\n667\r\n678\r\n722\r\n877\r\nWise, Virginia\r\n376\r\n328\r\nWoodstock, Virginia\r\n459\r\nWoolwine, Virginia\r\n930\r\nWytheville, Virginia\r\n223\r\n535\r\n228\r\n\u00035Unknown & in-use prefix, Va (540)\r\n226\r\n229\r\n292\r\n337\r\n393\r\n485\r\n539\r\n555\r\n596\r\n608\r\n625\r\n654\r\n675\r\n723\r\n725\r\n727\r\n732\r\n748\r\n797\r\n798\r\n842\r\n843\r\n851\r\n868\r\n950\r\n970\r\n\u00035Unknown prefix code (540) - Virginia\r\n"
  },
  {
    "path": "install/regions/regions.541",
    "content": "Eugene, Oregon\r\n334\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n461\r\n465\r\n484\r\n485\r\n683\r\n686\r\n687\r\n688\r\n689\r\n726\r\n729\r\n744\r\n746\r\n747\r\n953\r\n954\r\nSpringfield, Oregon\r\n741\r\nAdrian, Oregon\r\n724\r\nAlbany, Oregon\r\n924\r\n926\r\n928\r\n967\r\n979\r\n990\r\nAlsea, Oregon\r\n487\r\nAmity, Oregon\r\n835\r\nAntelope, Oregon\r\n489\r\nArlington, Oregon\r\n454\r\nAsh Valley, Oregon\r\n599\r\nAshland, Oregon\r\n201\r\n482\r\n488\r\n552\r\nAstoria, Oregon\r\n325\r\n338\r\n791\r\nAthena, Oregon\r\n566\r\nAurora, Oregon\r\n678\r\nAvmsviltrn, Oregon\r\n743\r\n749\r\nAzalea, Oregon\r\n837\r\nBaker, Oregon\r\n523\r\nBandon, Oregon\r\n347\r\nBates, Oregon\r\n448\r\nBay City, Oregon\r\n377\r\nBeaver Creek, Oregon\r\n632\r\nBeaver, Oregon\r\n398\r\nBeaverton, Oregon\r\n520\r\n524\r\n526\r\n531\r\n550\r\n578\r\n579\r\n591\r\n626\r\n627\r\n629\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n649\r\n671\r\n677\r\n690\r\nBell Fountain, Oregon\r\n424\r\nBend, Oregon\r\n382\r\n383\r\n385\r\n388\r\n389\r\n420\r\n480\r\n540\r\n593\r\nBlodgett, Oregon\r\n453\r\nBlue River, Oregon\r\n822\r\nBly, Oregon\r\n353\r\nBoardman, Oregon\r\n481\r\nBonanza, Oregon\r\n545\r\nBrookings, Oregon\r\n469\r\nBrownsville, Oregon\r\n466\r\nBurlington, Oregon\r\n621\r\nBurns, Oregon\r\n573\r\nButte Falls, Oregon\r\n865\r\nCamas Valley, Oregon\r\n445\r\nCanby, Oregon\r\n263\r\n266\r\n651\r\nCannon Beach, Oregon\r\n436\r\nCanyonville, Oregon\r\n839\r\nCarlton, Oregon\r\n852\r\nCascade Lake, Oregon\r\n374\r\nCave Junction, Oregon\r\n592\r\nCentral Point, Oregon\r\n664\r\nCharboneau, Oregon\r\n694\r\nChemult, Oregon\r\n365\r\nChiloquin, Oregon\r\n783\r\nChitwood, Oregon\r\n875\r\nClackamas, Oregon\r\n786\r\nClatskanie, Oregon\r\n728\r\nCloverdale, Oregon\r\n392\r\nCmp Shermn, Oregon\r\n595\r\nColton, Oregon\r\n824\r\nCondon, Oregon\r\n384\r\nConnor Creek, Oregon\r\n675\r\nCoos Bay, Oregon\r\n264\r\n267\r\n269\r\n751\r\n756\r\n888\r\nCoquille, Oregon\r\n396\r\nCorbett, Oregon\r\n695\r\nCorvallis, Oregon\r\n737\r\n740\r\n745\r\n750\r\n752\r\n753\r\n754\r\n757\r\n758\r\nCottage Grove, Oregon\r\n942\r\n946\r\nCove, Oregon\r\n568\r\nCraterlake, Oregon\r\n594\r\nCreswell, Oregon\r\n895\r\nCulver, Oregon\r\n546\r\nDallas, Oregon\r\n623\r\nDays Creek, Oregon\r\n825\r\nDayville, Oregon\r\n987\r\nDeadwood, Oregon\r\n964\r\nDepoe Bay, Oregon\r\n589\r\n764\r\n765\r\nDetroit, Oregon\r\n854\r\nDiamond Lake, Oregon\r\n793\r\nDrain, Oregon\r\n836\r\nDufur, Oregon\r\n467\r\nDurkee, Oregon\r\n877\r\nEcho, Oregon\r\n376\r\nElgin, Oregon\r\n437\r\nElkton, Oregon\r\n584\r\nEnterprise, Oregon\r\n426\r\nEstacada, Oregon\r\n630\r\n637\r\nFalls City, Oregon\r\n787\r\nFish Lake, Oregon\r\n949\r\nFlora Troy, Oregon\r\n828\r\nFlorence, Oregon\r\n991\r\n997\r\n999\r\nForest Grove, Oregon\r\n324\r\n357\r\n359\r\n985\r\nFossil, Oregon\r\n763\r\nFort Klamath, Oregon\r\n381\r\nGaribaldi, Oregon\r\n322\r\nGervais, Oregon\r\n792\r\nGilchrist, Oregon\r\n433\r\nGlendale, Oregon\r\n832\r\nGlide, Oregon\r\n496\r\nGold Beach, Oregon\r\n247\r\nGold Hill, Oregon\r\n855\r\nGovernment Camp, Oregon\r\n272\r\nGrand Island, Oregon\r\n868\r\nGrandronde, Oregon\r\n879\r\nGrants Pass, Oregon\r\n450\r\n471\r\n474\r\n476\r\n479\r\n660\r\n851\r\n955\r\nGrass Valley, Oregon\r\n333\r\nGresham, Oregon\r\n492\r\n661\r\n663\r\n665\r\n666\r\n667\r\n669\r\nHaines, Oregon\r\n856\r\nHalfway, Oregon\r\n742\r\nHalsey, Oregon\r\n369\r\nHarlan, Oregon\r\n438\r\nHarper, Oregon\r\n358\r\nHarrisburg, Oregon\r\n995\r\nHelix, Oregon\r\n457\r\nHeppner, Oregon\r\n676\r\nHerefdunty, Oregon\r\n446\r\nHermiston, Oregon\r\n561\r\n564\r\n567\r\nHillsboro, Oregon\r\n640\r\n648\r\n681\r\n693\r\n696\r\nHood Land, Oregon\r\n622\r\nHood River, Oregon\r\n349\r\n386\r\n387\r\n490\r\nHorton, Oregon\r\n925\r\nHuntington, Oregon\r\n869\r\nImbler, Oregon\r\n534\r\nIndependence, Oregon\r\n838\r\nIone, Oregon\r\n422\r\nJacksonville, Oregon\r\n889\r\n899\r\nJefferson, Oregon\r\n327\r\nJewell, Oregon\r\n755\r\nJohn Day, Oregon\r\n575\r\nJordan Valley, Oregon\r\n586\r\nJoseph, Oregon\r\n432\r\n577\r\nJunction City, Oregon\r\n998\r\nJuntura, Oregon\r\n277\r\nKlamath Falls, Oregon\r\n850\r\n882\r\n883\r\n884\r\n885\r\n891\r\n892\r\nKnappa, Oregon\r\n458\r\nLa Grande, Oregon\r\n962\r\n963\r\nLake Oswego, Oregon\r\n635\r\n636\r\n697\r\n699\r\nLakeside, Oregon\r\n759\r\nLakeview, Oregon\r\n947\r\nLanglois, Oregon\r\n348\r\nLapine, Oregon\r\n536\r\nLeaburg, Oregon\r\n896\r\nLebanon, Oregon\r\n258\r\n259\r\n451\r\nLexington, Oregon\r\n989\r\nLincoln City, Oregon\r\n921\r\n992\r\n994\r\n996\r\nLobster Valley, Oregon\r\n486\r\nLong Creek, Oregon\r\n421\r\nLostine, Oregon\r\n569\r\nLowell, Oregon\r\n937\r\nLyons, Oregon\r\n859\r\nMadras, Oregon\r\n475\r\n553\r\nMalin, Oregon\r\n723\r\nMapleton, Oregon\r\n268\r\nMarcola, Oregon\r\n933\r\nMaupin, Oregon\r\n395\r\nMcMinnville, Oregon\r\n434\r\n472\r\nMeacham, Oregon\r\n983\r\nMedford, Oregon\r\n245\r\n608\r\n732\r\n734\r\n770\r\n772\r\n773\r\n774\r\n776\r\n779\r\n821\r\n840\r\n857\r\n858\r\n864\r\n890\r\n944\r\nMedical Spring, Oregon\r\n853\r\nMerrill, Oregon\r\n798\r\nMill City, Oregon\r\n897\r\nMitchell, Oregon\r\n462\r\nMltn Freewater, Oregon\r\n938\r\nMolalla, Oregon\r\n829\r\nMonitor, Oregon\r\n634\r\nMonroe, Oregon\r\n847\r\nMonument, Oregon\r\n934\r\nMoro, Oregon\r\n565\r\nMosier, Oregon\r\n478\r\nMount Angel, Oregon\r\n845\r\nMount Hood, Oregon\r\n337\r\nMount Vernon, Oregon\r\n932\r\nMyrtle Creek, Oregon\r\n863\r\nMyrtle Point, Oregon\r\n572\r\nNehalem, Oregon\r\n368\r\nNewberg, Oregon\r\n537\r\n538\r\nNewport, Oregon\r\n265\r\n270\r\n574\r\n961\r\nNorth Harney, Oregon\r\n493\r\nNorth Plains, Oregon\r\n647\r\nNorth Powder, Oregon\r\n898\r\nNorth Umpqua, Oregon\r\n498\r\nNyssa, Oregon\r\n372\r\nO Brien, Oregon\r\n596\r\nOakgrove Mill, Oregon\r\n652\r\n653\r\n654\r\n659\r\n794\r\nOakland, Oregon\r\n459\r\nOakridge, Oregon\r\n782\r\nOdell, Oregon\r\n354\r\nOntario, Oregon\r\n881\r\nOregon City, Oregon\r\n557\r\n650\r\n655\r\n656\r\n657\r\nOregonslope, Oregon\r\n262\r\nOxbow, Oregon\r\n785\r\nPacific Cy, Oregon\r\n965\r\nPaisley, Oregon\r\n943\r\nParkdale, Oregon\r\n352\r\nPaulina, Oregon\r\n477\r\nPendleton, Oregon\r\n276\r\n278\r\n379\r\n380\r\n966\r\n969\r\nPhilomath, Oregon\r\n929\r\nPhoenix, Oregon\r\n535\r\nPilot Rock, Oregon\r\n428\r\n443\r\nPine Grove, Oregon\r\n328\r\nPortland, Oregon\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n246\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n260\r\n261\r\n273\r\n274\r\n275\r\n279\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n291\r\n292\r\n293\r\n294\r\n295\r\n297\r\n299\r\n320\r\n321\r\n323\r\n326\r\n329\r\n331\r\n335\r\n340\r\n423\r\n425\r\n441\r\n452\r\n464\r\n494\r\n497\r\n499\r\n539\r\n555\r\n720\r\n721\r\n725\r\n727\r\n731\r\n733\r\n735\r\n760\r\n761\r\n762\r\n768\r\n771\r\n775\r\n777\r\n778\r\n780\r\n781\r\n784\r\n788\r\n789\r\n790\r\n795\r\n796\r\n797\r\n799\r\n823\r\n827\r\n833\r\n860\r\n870\r\n880\r\n887\r\n936\r\n939\r\n940\r\n960\r\n970\r\n976\r\n977\r\n978\r\nPortorford, Oregon\r\n332\r\nPowers, Oregon\r\n439\r\nPrairie City, Oregon\r\n820\r\nPrineville, Oregon\r\n447\r\nProspect, Oregon\r\n560\r\nPrvltmrphy, Oregon\r\n846\r\n862\r\nQuinn, Oregon\r\n522\r\nRainier, Oregon\r\n556\r\nRedland, Oregon\r\n631\r\nRedmond, Oregon\r\n548\r\n923\r\nReedsport, Oregon\r\n271\r\nRichland, Oregon\r\n893\r\nRiddle, Oregon\r\n874\r\nRidgeview, Oregon\r\n339\r\nRipplebreak, Oregon\r\n834\r\nRockaway, Oregon\r\n355\r\nRockypoint, Oregon\r\n356\r\nRogue River, Oregon\r\n582\r\nRoseburg, Oregon\r\n430\r\n440\r\n670\r\n672\r\n673\r\n679\r\n844\r\n957\r\nRufus, Oregon\r\n739\r\nSalem, Oregon\r\n361\r\n362\r\n363\r\n364\r\n370\r\n371\r\n373\r\n375\r\n378\r\n390\r\n391\r\n393\r\n399\r\n463\r\n559\r\n580\r\n581\r\n585\r\n588\r\n871\r\n930\r\n931\r\n945\r\n986\r\nSandy, Oregon\r\n668\r\nScappoose, Oregon\r\n543\r\nScholls, Oregon\r\n628\r\nScio, Oregon\r\n394\r\nScottsburg, Oregon\r\n587\r\nSeaside, Oregon\r\n738\r\nSelma, Oregon\r\n597\r\nSeneca, Oregon\r\n542\r\nShady Cove, Oregon\r\n878\r\nShedd, Oregon\r\n491\r\nSheridan, Oregon\r\n843\r\nSherwood, Oregon\r\n625\r\nSiletz, Oregon\r\n444\r\nSilverlake, Oregon\r\n576\r\nSilverton, Oregon\r\n873\r\nSisters, Oregon\r\n549\r\nSouth Harney, Oregon\r\n495\r\nSouthbeach, Oregon\r\n867\r\nSprague River, Oregon\r\n533\r\nSpray, Oregon\r\n468\r\nSaint Helens, Oregon\r\n366\r\n397\r\nSaint Paul, Oregon\r\n633\r\nStafford, Oregon\r\n638\r\n682\r\n685\r\nStanfield, Oregon\r\n449\r\nStateline, Oregon\r\n558\r\nStayton, Oregon\r\n769\r\nSummit, Oregon\r\n456\r\nSumpter, Oregon\r\n894\r\nSunnyside, Oregon\r\n658\r\n698\r\nSweet Home, Oregon\r\n367\r\nTalent\u00031/\u00032Phoenix, Oregon\r\n512\r\n535\r\nThe Dalles, Oregon\r\n296\r\n298\r\n980\r\n993\r\nTidewater, Oregon\r\n528\r\nTigard, Oregon\r\n590\r\n598\r\n620\r\n624\r\n639\r\n684\r\n691\r\n692\r\nTillamook, Oregon\r\n842\r\nToledo, Oregon\r\n336\r\nTriangle Lake, Oregon\r\n927\r\nTygh Valley, Oregon\r\n483\r\nUkiah, Oregon\r\n427\r\nUmatilla, Oregon\r\n922\r\nUnion, Oregon\r\n562\r\nVale, Oregon\r\n473\r\nVeneta, Oregon\r\n935\r\nVernonia, Oregon\r\n429\r\nWaldport, Oregon\r\n563\r\nWallowa, Oregon\r\n886\r\nWamic, Oregon\r\n544\r\nWarrenton, Oregon\r\n861\r\nWasco, Oregon\r\n442\r\nWestport, Oregon\r\n455\r\nWhite City, Oregon\r\n826\r\n830\r\nWillamina, Oregon\r\n876\r\nWolf Creek, Oregon\r\n866\r\nWoodburn, Oregon\r\n981\r\n982\r\nYachats, Oregon\r\n547\r\nYamhill, Oregon\r\n662\r\nYoncalla, Oregon\r\n849\r\n\u00035Unknown prefix code (541) - Oregon\r\n"
  },
  {
    "path": "install/regions/regions.562",
    "content": "(City name needed please, California)\r\n227\r\n622\r\n653\r\n709\r\n776\r\nArtesia, California\r\n467\r\n916\r\nArtesia\u00031/\u00032Cerritos\u00031/\u00032La Palma, California\r\n865\r\n924\r\nBellflower, California\r\n461\r\n804\r\n866\r\n867\r\n920\r\n925\r\nCerritos, California\r\n402\r\nCompton, California\r\n259\r\n272\r\n601\r\n602\r\n663\r\n790\r\nDowney, California\r\n401\r\n469\r\n803\r\n806\r\n861\r\n862\r\n869\r\n904\r\n922\r\n923\r\n927\r\n928\r\n940\r\nHawaiian Gardens, California\r\n496\r\nLa Habra, California\r\n690\r\n691\r\n694\r\n697\r\n902\r\n905\r\nLa Mirada, California\r\n903\r\n943\r\n947\r\nLakewood, California\r\n210\r\n308\r\n405\r\n420\r\n425\r\n429\r\n497\r\n593\r\n620\r\n623\r\n627\r\n629\r\n678\r\n681\r\n770\r\n870\r\n931\r\n932\r\n934\r\n935\r\n938\r\n982\r\nLong Beach\u00031/\u00032Bixby Knolls, California\r\n426\r\n427\r\n428\r\n490\r\n492\r\n595\r\n933\r\n984\r\n989\r\n997\r\nLong Beach [Downtown], CA\r\n570\r\n901\r\n980\r\n981\r\n988\r\nLong Beach [East], California\r\n432\r\n590\r\n985\r\nLong Beach [North Of Downtown], California\r\n435\r\n436\r\n437\r\n491\r\n495\r\n591\r\n983\r\nLong Beach [North], California\r\n421\r\n422\r\n423\r\n424\r\nLong Beach [Signal Hill], California\r\n218\r\n599\r\nLong Beach, California\r\n499\r\n624\r\n628\r\n951\r\nLos Alamitos, California\r\n433\r\n434\r\n438\r\n439\r\n494\r\n498\r\n520\r\n597\r\n621\r\n961\r\n987\r\nNorwalk, California\r\n403\r\n404\r\n407\r\n409\r\n460\r\n462\r\n465\r\n466\r\n651\r\n802\r\n807\r\n809\r\n860\r\n926\r\nParamount, California\r\n220\r\n408\r\n529\r\n531\r\n630\r\n633\r\n634\r\nPico Rivera [Los Nietos], California\r\n695\r\n699\r\n942\r\n948\r\n949\r\nPico Rivera, California\r\n463\r\n654\r\n692\r\n801\r\n908\r\nSanta Fe Springs, California\r\n406\r\n468\r\n483\r\n863\r\n864\r\n868\r\n921\r\n929\r\nSeal Beach, California\r\n430\r\n431\r\n493\r\n594\r\n596\r\n598\r\n626\r\n795\r\n797\r\n799\r\n930\r\n936\r\n986\r\nSunset Beach, California\r\n592\r\nWhittier, California\r\n321\r\n464\r\n693\r\n696\r\n698\r\n906\r\n907\r\n941\r\n944\r\n945\r\n946\r\n\u00035Unknown prefix code (562) - California\r\n"
  },
  {
    "path": "install/regions/regions.567",
    "content": "Van Buren, Ohio\r\n525\r\n\u00035Unknown prefix code (567) - Ohio\r\n"
  },
  {
    "path": "install/regions/regions.573",
    "content": "Advance, Missouri\r\n722\r\nAltonburg Fro, Missouri\r\n824\r\nAnnapolis, Missouri\r\n598\r\nAntonia, Missouri\r\n942\r\n948\r\nArgyle, Missouri\r\n728\r\nAshland, Missouri\r\n657\r\nAuxvasse, Missouri\r\n386\r\nBeaufort, Missouri\r\n484\r\nBelgrade, Missouri\r\n766\r\nBell City, Missouri\r\n733\r\nBelle, Missouri\r\n859\r\nBelleview, Missouri\r\n697\r\nBellflower, Missouri\r\n929\r\nBenton, Missouri\r\n545\r\nBerger, Missouri\r\n834\r\nBernie, Missouri\r\n293\r\nBig Spring, Missouri\r\n252\r\nBirch Tree, Missouri\r\n292\r\nBismarck, Missouri\r\n734\r\nBland, Missouri\r\n646\r\nBloomfield, Missouri\r\n568\r\nBloomsdale, Missouri\r\n483\r\nBlytheville, Missouri\r\n720\r\nBonneterre, Missouri\r\n358\r\nBoss, Missouri\r\n626\r\nBourbon, Missouri\r\n732\r\nBowling Green, Missouri\r\n324\r\n470\r\nBrazito, Missouri\r\n496\r\nBuckhorn, Missouri\r\n774\r\nBunker, Missouri\r\n689\r\nCaledonia, Missouri\r\n779\r\nCalifornia, Missouri\r\n796\r\nCamdenton, Missouri\r\n346\r\n873\r\nCampbell, Missouri\r\n246\r\nCanton, Missouri\r\n288\r\nCape Grardu, Missouri\r\n290\r\n334\r\n335\r\n339\r\n651\r\nCardwell, Missouri\r\n654\r\nCaruthrsville, Missouri\r\n333\r\nCenter, Missouri\r\n267\r\nCentertown, Missouri\r\n584\r\nCenterville, Missouri\r\n648\r\nCentralia, Missouri\r\n682\r\nChaffee, Missouri\r\n887\r\nChamois, Missouri\r\n763\r\nCharleston, Missouri\r\n683\r\nCherryville, Missouri\r\n743\r\nClark, Missouri\r\n641\r\nClarksburg, Missouri\r\n787\r\nClarksville, Missouri\r\n242\r\nClearwater Lake, Missouri\r\n461\r\nClimax Springs, Missouri\r\n345\r\n347\r\nClubb, Missouri\r\n495\r\nColumbia, Missouri\r\n442\r\n443\r\n445\r\n446\r\n449\r\n474\r\n499\r\n864\r\n874\r\n875\r\n876\r\n881\r\n882\r\n884\r\n886\r\nCrocker, Missouri\r\n736\r\nCuba, Missouri\r\n885\r\nDeering, Missouri\r\n757\r\nDelta, Missouri\r\n794\r\nDexter, Missouri\r\n624\r\nDixon, Missouri\r\n759\r\nDoniphan, Missouri\r\n996\r\nEast Prairie, Missouri\r\n649\r\nEdgar Springs, Missouri\r\n435\r\nEldon, Missouri\r\n392\r\nEllington, Missouri\r\n663\r\nEllsinore, Missouri\r\n322\r\nEminence, Missouri\r\n226\r\nEolia, Missouri\r\n485\r\nEssex, Missouri\r\n283\r\nEugene, Missouri\r\n498\r\nEwing, Missouri\r\n494\r\nFair Dealing, Missouri\r\n857\r\nFarber, Missouri\r\n249\r\nFarmington, Missouri\r\n756\r\nFisk, Missouri\r\n967\r\nFlat River, Missouri\r\n431\r\nFrankford, Missouri\r\n784\r\nFredrickton, Missouri\r\n783\r\nFreeburg, Missouri\r\n744\r\nFremont, Missouri\r\n251\r\nFort Leonardwood, Missouri\r\n329\r\n563\r\n596\r\n\r\nFulton, Missouri\r\n220\r\n592\r\nGarwood, Missouri\r\n945\r\nGideon, Missouri\r\n448\r\nGrandin, Missouri\r\n593\r\nGravois Mills, Missouri\r\n372\r\n374\r\nGreenville, Missouri\r\n224\r\nGrey Summit, Missouri\r\n742\r\nHallsville, Missouri\r\n696\r\nHannibal, Missouri\r\n221\r\n248\r\nHatton, Missouri\r\n387\r\nHawk Point, Missouri\r\n338\r\nHayti, Missouri\r\n359\r\nHermann, Missouri\r\n486\r\nHigh Hill, Missouri\r\n585\r\nHolcomb, Missouri\r\n792\r\nHolstein, Missouri\r\n932\r\nHornersville, Missouri\r\n737\r\nHunnewell, Missouri\r\n983\r\nHuzzah, Missouri\r\n786\r\nIberia, Missouri\r\n793\r\nIrondale, Missouri\r\n749\r\nIronton, Missouri\r\n546\r\nJackson, Missouri\r\n243\r\nJapan, Missouri\r\n627\r\nJefferson City\u00031/\u00032Columbia, Missouri\r\n573\r\n642\r\nJefferson City, Missouri\r\n526\r\n634\r\n635\r\n636\r\n659\r\n681\r\n751\r\n761\r\n893\r\n896\r\nJonesburg, Missouri\r\n488\r\nLa Grange, Missouri\r\n655\r\nLaddonia, Missouri\r\n373\r\nLake Ozark, Missouri\r\n365\r\nLeadwood, Missouri\r\n562\r\nLeasburg, Missouri\r\n245\r\nLesterville, Missouri\r\n637\r\nLewistown, Missouri\r\n497\r\nLicking, Missouri\r\n674\r\nLilbourn, Missouri\r\n688\r\nLinn, Missouri\r\n897\r\nLkozkosbch, Missouri\r\n348\r\nLouisiana, Missouri\r\n754\r\nLyon, Missouri\r\n459\r\nMackscreek, Missouri\r\n363\r\nMalden, Missouri\r\n276\r\nMarble Hill, Missouri\r\n238\r\nMarston, Missouri\r\n643\r\nMartinsberg, Missouri\r\n492\r\nMeta, Missouri\r\n229\r\nMexico, Missouri\r\n473\r\n581\r\nMiddletown, Missouri\r\n549\r\nMokane, Missouri\r\n676\r\nMonroe City, Missouri\r\n735\r\nMontauk, Missouri\r\n548\r\nMontgomery City, Missouri\r\n564\r\nMonticello, Missouri\r\n767\r\nMorehouse, Missouri\r\n667\r\nMorrison, Missouri\r\n294\r\nMount Sterling, Missouri\r\n943\r\nNaylor, Missouri\r\n399\r\nNeelyville, Missouri\r\n989\r\nNew Bloomfield, Missouri\r\n491\r\nNew Hartford, Missouri\r\n669\r\nNew Haven, Missouri\r\n237\r\nNew London, Missouri\r\n985\r\nNew Madrid, Missouri\r\n748\r\nNewburg, Missouri\r\n762\r\nNew Florence, Missouri\r\n835\r\nOates, Missouri\r\n269\r\nOld Appleton, Missouri\r\n788\r\nOlney, Missouri\r\n656\r\nOran, Missouri\r\n262\r\nOwensville, Missouri\r\n437\r\nOxly, Missouri\r\n354\r\nPalmyra, Missouri\r\n769\r\nParma, Missouri\r\n357\r\nPatterson, Missouri\r\n856\r\nPatton, Missouri\r\n866\r\nPaynesville, Missouri\r\n847\r\nPerry, Missouri\r\n565\r\nPerryville, Missouri\r\n547\r\nPhiladelphia, Missouri\r\n439\r\nPiedmont, Missouri\r\n223\r\nPocahontas, Missouri\r\n833\r\nPond, Missouri\r\n273\r\n458\r\nPonder, Missouri\r\n255\r\nPoplar Bluff, Missouri\r\n686\r\n778\r\n785\r\n840\r\nPortageville, Missouri\r\n379\r\nPotosi, Missouri\r\n438\r\nPuxico, Missouri\r\n222\r\nQulin, Missouri\r\n328\r\nRedford, Missouri\r\n558\r\nRhineland, Missouri\r\n236\r\nRichland, Missouri\r\n765\r\nRichwoods, Missouri\r\n678\r\nRisco, Missouri\r\n396\r\nRocheport, Missouri\r\n698\r\nRolla, Missouri\r\n368\r\n465\r\n341\r\n364\r\nRussellville, Missouri\r\n782\r\nSafe, Missouri\r\n699\r\nSalem, Missouri\r\n729\r\nSanta Fe, Missouri\r\n685\r\nScott City, Missouri\r\n264\r\nSenath, Missouri\r\n738\r\nShelbina, Missouri\r\n588\r\nShelbyville, Missouri\r\n633\r\nSikeston, Missouri\r\n471\r\n472\r\nSpring Bluff, Missouri\r\n457\r\nSaint James, Missouri\r\n265\r\nSaint Marys, Missouri\r\n543\r\nSaint Peters, Missouri\r\n489\r\nSaint Robert, Missouri\r\n336\r\nSaint Thomas, Missouri\r\n477\r\nStanton, Missouri\r\n927\r\nSteele, Missouri\r\n695\r\nSteelville, Missouri\r\n775\r\nSaint Elizabeth, Missouri\r\n493\r\nSaint Geneveve, Missouri\r\n883\r\nStoutsville, Missouri\r\n672\r\nStover, Missouri\r\n377\r\nSturgeon, Missouri\r\n687\r\nSullivan, Missouri\r\n468\r\n860\r\nSweetwater, Missouri\r\n924\r\nTaos, Missouri\r\n395\r\nTebbetts, Missouri\r\n295\r\nTimber, Missouri\r\n858\r\nTruxton, Missouri\r\n597\r\nTuscumbia, Missouri\r\n369\r\nVan Buren, Missouri\r\n323\r\nVandalia, Missouri\r\n594\r\nVersailles, Missouri\r\n378\r\nViburnum, Missouri\r\n244\r\nVichy, Missouri\r\n299\r\nVienna, Missouri\r\n422\r\nWapapelo Park, Missouri\r\n297\r\nWardell, Missouri\r\n628\r\nWare, Missouri\r\n944\r\nWarrenton, Missouri\r\n456\r\nWashington, Missouri\r\n239\r\n390\r\nWellsville, Missouri\r\n684\r\nWestphalia, Missouri\r\n455\r\nWest Quincy, Missouri\r\n393\r\nWilliamsburg, Missouri\r\n254\r\nWilliamsville, Missouri\r\n998\r\nWinona, Missouri\r\n325\r\nWright City, Missouri\r\n745\r\nWyatt, Missouri\r\n675\r\nSaint Louis, Missouri\r\n314\r\nCape Girardeau, Missouri\r\n200\r\n\u00035Unknown prefix code (573) - Missouri\r\n"
  },
  {
    "path": "install/regions/regions.601",
    "content": "Aberdeen, Mississippi\r\n343\r\n369\r\nAckerman, Mississippi\r\n285\r\nAmory, Mississippi\r\n256\r\nArtsa Crfd, Mississippi\r\n272\r\nAshland, Mississippi\r\n224\r\nBaldwyn, Mississippi\r\n365\r\nBarlow, Mississippi\r\n277\r\nBassfield, Mississippi\r\n943\r\nBatesville, Mississippi\r\n561\r\n563\r\nBay Springs, Mississippi\r\n764\r\nBeaumont, Mississippi\r\n784\r\nBelmont, Mississippi\r\n454\r\nBelzoni, Mississippi\r\n247\r\nBenndale, Mississippi\r\n945\r\nBenoit, Mississippi\r\n742\r\nBig Creek, Mississippi\r\n763\r\nBlue Mt, Mississippi\r\n685\r\nBolton, Mississippi\r\n866\r\nBooneville, Mississippi\r\n728\r\nBrandon, Mississippi\r\n824\r\n825\r\n829\r\nBriarwood, Mississippi\r\n681\r\nBrookhaven, Mississippi\r\n734\r\n833\r\n835\r\nBruce, Mississippi\r\n983\r\nBuckatunna, Mississippi\r\n648\r\nBurnsville, Mississippi\r\n427\r\nByhalia, Mississippi\r\n838\r\nCaledonia, Mississippi\r\n356\r\nCalhoun City, Mississippi\r\n628\r\nCanton, Mississippi\r\n855\r\n859\r\nCarrollton, Mississippi\r\n237\r\nCarthage, Mississippi\r\n253\r\n267\r\n654\r\nCentreville, Mississippi\r\n645\r\nCharleston, Mississippi\r\n647\r\nChester, Mississippi\r\n387\r\nChulahoma, Mississippi\r\n564\r\nClarksdale, Mississippi\r\n624\r\n627\r\nCleveland, Mississippi\r\n721\r\n843\r\n846\r\nClinton, Mississippi\r\n924\r\n925\r\nCoffeeville, Mississippi\r\n675\r\nColdwater, Mississippi\r\n233\r\n622\r\nCollins, Mississippi\r\n765\r\nColmbus Air Force Base, Mississippi\r\n434\r\nColumbia, Mississippi\r\n740\r\n243\r\n731\r\n736\r\n242\r\n245\r\n327\r\n328\r\n329\r\nComo, Mississippi\r\n526\r\nCorinth, Mississippi\r\n286\r\n287\r\nCrenshaw, Mississippi\r\n382\r\nCrosby, Mississippi\r\n639\r\nCrossroads, Mississippi\r\n772\r\nCrystal Springs, Mississippi\r\n892\r\nDe Kalb, Mississippi\r\n743\r\nDecatur, Mississippi\r\n635\r\nDrew, Mississippi\r\n745\r\nDuck Hill, Mississippi\r\n565\r\nDuffee, Mississippi\r\n986\r\nDuncan, Mississippi\r\n395\r\nDurant, Mississippi\r\n653\r\nEagle Lake, Mississippi\r\n279\r\nEddiceton, Mississippi\r\n532\r\nEdwards, Mississippi\r\n852\r\nEllisville, Mississippi\r\n433\r\n477\r\nEnterprise, Mississippi\r\n659\r\nEthel, Mississippi\r\n674\r\nEupora, Mississippi\r\n258\r\nFairview, Mississippi\r\n585\r\nFayette, Mississippi\r\n786\r\nFlora, Mississippi\r\n879\r\nFlorence, Mississippi\r\n845\r\nForest, Mississippi\r\n469\r\n625\r\nFriars Point, Mississippi\r\n383\r\nFulton, Mississippi\r\n862\r\nGeorgetown, Mississippi\r\n858\r\nGlen Allan, Mississippi\r\n839\r\nGloster, Mississippi\r\n225\r\nGoodman, Mississippi\r\n472\r\nGreenville, Mississippi\r\n332\r\n334\r\n335\r\n378\r\n379\r\nGreenwood, Mississippi\r\n453\r\n455\r\n459\r\n658\r\nGrenada, Mississippi\r\n226\r\n227\r\nGunnison, Mississippi\r\n747\r\nGuntown, Mississippi\r\n348\r\nHattiesburg, Mississippi\r\n261\r\n264\r\n266\r\n268\r\n288\r\n544\r\n545\r\n582\r\n583\r\n584\r\n549\r\n270\r\n543\r\nHazlehurst, Mississippi\r\n894\r\nHeidelberg, Mississippi\r\n787\r\nHermanville, Mississippi\r\n535\r\nHernando, Mississippi\r\n429\r\nHollandale, Mississippi\r\n827\r\nHolly Springs, Mississippi\r\n252\r\n333\r\nHolly Bluff, Mississippi\r\n828\r\nHomewood, Mississippi\r\n536\r\nHoulka, Mississippi\r\n568\r\nHouston, Mississippi\r\n456\r\nIndianola, Mississippi\r\n884\r\n887\r\nInverness, Mississippi\r\n265\r\nIsola, Mississippi\r\n962\r\nItta Bena, Mississippi\r\n254\r\nIuka, Mississippi\r\n423\r\n424\r\nJackson, Mississippi\r\n360\r\n471\r\n881\r\n942\r\n955\r\n973\r\n974\r\n930\r\n978\r\n331\r\n352\r\n353\r\n354\r\n355\r\n359\r\n362\r\n364\r\n366\r\n371\r\n372\r\n373\r\n376\r\n922\r\n923\r\n932\r\n933\r\n936\r\n939\r\n941\r\n944\r\n946\r\n948\r\n949\r\n956\r\n957\r\n960\r\n961\r\n965\r\n966\r\n968\r\n969\r\n977\r\n981\r\n982\r\n984\r\n987\r\n992\r\n995\r\nJanice, Mississippi\r\n598\r\nJonestown, Mississippi\r\n358\r\nKilmichael, Mississippi\r\n262\r\nKosciusko, Mississippi\r\n289\r\nLake, Mississippi\r\n775\r\nLaurel, Mississippi\r\n422\r\n439\r\n344\r\n425\r\n426\r\n428\r\n649\r\nLeakesville, Mississippi\r\n394\r\nLeland, Mississippi\r\n686\r\nLexington, Mississippi\r\n834\r\nLiberty, Mississippi\r\n657\r\nLouin, Mississippi\r\n739\r\nLouise, Mississippi\r\n836\r\nLouisville, Mississippi\r\n773\r\nLucedale, Mississippi\r\n947\r\nLula, Mississippi\r\n337\r\nLumberton, Mississippi\r\n796\r\nLynville, Mississippi\r\n677\r\nMaben, Mississippi\r\n263\r\nMacon, Mississippi\r\n726\r\n738\r\nMadison, Mississippi\r\n853\r\n856\r\nMagee, Mississippi\r\n849\r\nMagnolia, Mississippi\r\n783\r\nMantachie, Mississippi\r\n282\r\nMarks, Mississippi\r\n326\r\nMcComb, Mississippi\r\n249\r\n276\r\n567\r\n684\r\nMcCool, Mississippi\r\n547\r\nMcLain, Mississippi\r\n753\r\nMeadville, Mississippi\r\n384\r\nMemphis, Mississippi\r\n342\r\n349\r\n393\r\n781\r\nMendenhall, Mississippi\r\n847\r\nMeridian, Mississippi\r\n482\r\n483\r\n484\r\n485\r\n626\r\n644\r\n655\r\n693\r\n748\r\nMichigan City, Mississippi\r\n768\r\nMize, Mississippi\r\n733\r\nMonticello, Mississippi\r\n587\r\nMoorhead, Mississippi\r\n246\r\nMorton, Mississippi\r\n732\r\nMound Bayou, Mississippi\r\n741\r\nMount Olive, Mississippi\r\n797\r\nMount Pleasant, Mississippi\r\n851\r\nMyrtle, Mississippi\r\n988\r\nNatchez, Mississippi\r\n431\r\n442\r\n443\r\n445\r\n446\r\nNavalarsta, Mississippi\r\n679\r\nNeely, Mississippi\r\n525\r\nNettleton, Mississippi\r\n963\r\nNew Albany, Mississippi\r\n534\r\n538\r\nNew Hebron, Mississippi\r\n694\r\nNew Augusta, Mississippi\r\n964\r\nNewton Hkry, Mississippi\r\n646\r\n683\r\nNoxapater, Mississippi\r\n724\r\nOakland, Mississippi\r\n623\r\nObadiah, Mississippi\r\n737\r\nOkolona, Mississippi\r\n447\r\nOld Taylorville, Mississippi\r\n725\r\nOlive Branch, Mississippi\r\n893\r\n895\r\nOsyka, Mississippi\r\n542\r\nOxford, Mississippi\r\n232\r\n234\r\n236\r\nPace, Mississippi\r\n723\r\nPelahatche, Mississippi\r\n854\r\nPhila, Mississippi\r\n650\r\n656\r\nPicayune, Mississippi\r\n798\r\n799\r\nPickens, Mississippi\r\n468\r\nPittman, Mississippi\r\n752\r\nPolkville, Mississippi\r\n537\r\nPontotoc, Mississippi\r\n489\r\nPoplarville, Mississippi\r\n795\r\nPort Gibson, Mississippi\r\n437\r\n877\r\nPrentiss, Mississippi\r\n792\r\nPurvis, Mississippi\r\n794\r\nQuitman, Mississippi\r\n776\r\nRaleigh, Mississippi\r\n782\r\nRaymond, Mississippi\r\n857\r\nRed Bay, Mississippi\r\n676\r\nRichton, Mississippi\r\n788\r\nRienzi, Mississippi\r\n462\r\nRipley, Mississippi\r\n837\r\nRolling Fork, Mississippi\r\n873\r\nRose Hill, Mississippi\r\n727\r\nRosedale, Mississippi\r\n759\r\nRoxie, Mississippi\r\n322\r\nRuleville, Mississippi\r\n756\r\nSand Hill, Mississippi\r\n989\r\nSardis, Mississippi\r\n487\r\nScooba, Mississippi\r\n476\r\nSeminary, Mississippi\r\n722\r\nSenatobia, Mississippi\r\n562\r\nShannon, Mississippi\r\n767\r\nShaw, Mississippi\r\n754\r\nShelby, Mississippi\r\n398\r\nShubuta, Mississippi\r\n687\r\nShuqualak, Mississippi\r\n793\r\nSilver Creek, Mississippi\r\n886\r\nSlate Springs, Mississippi\r\n637\r\nSmithville, Mississippi\r\n651\r\nSouth Moscow, Mississippi\r\n778\r\nSoso, Mississippi\r\n729\r\nStarkville, Mississippi\r\n323\r\n324\r\n325\r\n465\r\n338\r\nState Line, Mississippi\r\n848\r\nSumner, Mississippi\r\n375\r\nSumrall, Mississippi\r\n758\r\nSunflower, Mississippi\r\n569\r\nSylvarena, Mississippi\r\n789\r\nTaylorsville, Mississippi\r\n785\r\nTchula, Mississippi\r\n235\r\nTerry, Mississippi\r\n878\r\nTishomingo, Mississippi\r\n438\r\nToomsuba, Mississippi\r\n632\r\nTremont, Mississippi\r\n652\r\nTunica, Mississippi\r\n363\r\nTupelo, Mississippi\r\n678\r\n791\r\n680\r\n840\r\n841\r\n842\r\n844\r\n869\r\nTutwiler, Mississippi\r\n345\r\nTylertown, Mississippi\r\n876\r\nUnion, Mississippi\r\n774\r\nUtica, Mississippi\r\n885\r\nVaiden, Mississippi\r\n464\r\nVardaman, Mississippi\r\n682\r\nVerona, Mississippi\r\n566\r\nVicksburg, Mississippi\r\n630\r\n631\r\n634\r\n636\r\n638\r\nWalnut, Mississippi\r\n223\r\nWalters, Mississippi\r\n546\r\nWater Valley, Mississippi\r\n473\r\nWaynesboro, Mississippi\r\n735\r\nWesson, Mississippi\r\n643\r\nWest Point, Mississippi\r\n494\r\n495\r\nWest, Mississippi\r\n967\r\nWhite Oak, Mississippi\r\n269\r\nWiggins, Mississippi\r\n928\r\nWinona, Mississippi\r\n283\r\nWoodville, Mississippi\r\n888\r\nYazoo City, Mississippi\r\n673\r\n746\r\n755\r\n751\r\nYellow Creek, Mississippi\r\n667\r\n\u00035Unknown prefix code (601) - Mississippi\r\n"
  },
  {
    "path": "install/regions/regions.602",
    "content": "Agua Fria, Arizona\r\n214\r\nAguila, Arizona\r\n685\r\nAjo, Arizona\r\n387\r\nAlpine, Arizona\r\n339\r\nArizona Village, Arizona\r\n346\r\nAsh Fork, Arizona\r\n637\r\nBagdad, Arizona\r\n633\r\nBenson, Arizona\r\n609\r\n586\r\nBethany, Arizona\r\n872\r\n877\r\nBisbee, Arizona\r\n366\r\n432\r\nBlack Mesa, Arizona\r\n677\r\nBlackwater, Arizona\r\n215\r\nBlue Ridge, Arizona\r\n477\r\nBonita, Arizona\r\n828\r\nBouse, Arizona\r\n851\r\nBowie, Arizona\r\n847\r\nBuckeye, Arizona\r\n386\r\nBullhead City, Arizona\r\n754\r\nCamp Verde, Arizona\r\n567\r\nCasa Grande, Arizona\r\n421\r\n426\r\n836\r\n518\r\n560\r\n705\r\n709\r\nCasablanca, Arizona\r\n315\r\nCascabel, Arizona\r\n212\r\nCastle Rock, Arizona\r\n764\r\nCave Creek, Arizona\r\n488\r\nChandler, Arizona\r\n706\r\n802\r\n814\r\n917\r\n554\r\n598\r\n732\r\n786\r\n821\r\n893\r\n895\r\n899\r\n940\r\n961\r\n963\r\nChinle, Arizona\r\n674\r\nChino Valley, Arizona\r\n636\r\nCibola, Arizona\r\n857\r\nCircle City, Arizona\r\n388\r\nClifton, Arizona\r\n865\r\nColorado City, Arizona\r\n875\r\nCoolidge, Arizona\r\n723\r\nCoronado, Arizona\r\n825\r\nCottonwood, Arizona\r\n634\r\n639\r\n646\r\n725\r\nCraycroft, Arizona\r\n570\r\n571\r\n745\r\n747\r\n748\r\n750\r\n790\r\nDeer Valley, Arizona\r\n516\r\nDennehotso, Arizona\r\n658\r\nDilcon, Arizona\r\n657\r\nDolan Springs, Arizona\r\n767\r\nDouglas, Arizona\r\n364\r\nDudleyville, Arizona\r\n357\r\nDuncan, Arizona\r\n359\r\nEhrenberg, Arizona\r\n923\r\nElfrida, Arizona\r\n642\r\nElgin, Arizona\r\n455\r\nEloy, Arizona\r\n466\r\nFlagstaff, Arizona\r\n556\r\n699\r\n523\r\n525\r\n526\r\n527\r\n679\r\n773\r\n774\r\n779\r\nFlorence, Arizona\r\n868\r\nFort Defiance, Arizona\r\n729\r\nFredonia, Arizona\r\n643\r\nFort McDowel, Arizona\r\n471\r\n837\r\nGanado, Arizona\r\n755\r\nGila Bend, Arizona\r\n683\r\nGilbert, Arizona\r\n497\r\n545\r\n892\r\n926\r\nGlendale, Arizona\r\n815\r\n842\r\n930\r\n931\r\n934\r\n937\r\n939\r\n975\r\nGlobe, Arizona\r\n425\r\nGolden Valley, Arizona\r\n565\r\nGrand Canyon, Arizona\r\n638\r\nGreasewood, Arizona\r\n654\r\nGreen Valley, Arizona\r\n625\r\n648\r\nGreenway, Arizona\r\n547\r\n548\r\nGreer, Arizona\r\n735\r\nHarquahala Valley, Arizona\r\n372\r\nHawley Lake, Arizona\r\n335\r\nHayden, Arizona\r\n356\r\nHeber, Arizona\r\n535\r\nHigley, Arizona\r\n987\r\n988\r\nHolbrook, Arizona\r\n521\r\n524\r\nHyder, Arizona\r\n454\r\nJoseph City, Arizona\r\n288\r\nKaibito, Arizona\r\n673\r\nKayenta, Arizona\r\n697\r\nKeams Canyon, Arizona\r\n738\r\nKearny, Arizona\r\n363\r\nKingman, Arizona\r\n716\r\n718\r\n692\r\n753\r\n757\r\nKomatke, Arizona\r\n550\r\nKyktsmovi Village, Arizona\r\n734\r\nLake Havasu, Arizona\r\n453\r\n680\r\n855\r\nLe Chee, Arizona\r\n698\r\nLeupp, Arizona\r\n686\r\nLitchfield Park, Arizona\r\n907\r\nLittlefield, Arizona\r\n347\r\nLone Butte, Arizona\r\n796\r\nLukachukai, Arizona\r\n787\r\nMammoth, Arizona\r\n487\r\nMany Farms, Arizona\r\n781\r\nMarana, Arizona\r\n682\r\nMarble Canyon, Arizona\r\n353\r\n355\r\nMaricopa, Arizona\r\n430\r\n568\r\nMaryvale, Arizona\r\n873\r\nMcClintock, Arizona\r\n730\r\n752\r\n756\r\n820\r\n831\r\n838\r\n839\r\n897\r\nMcNary, Arizona\r\n334\r\nMeadview, Arizona\r\n564\r\nMesa, Arizona\r\n309\r\n370\r\n531\r\n541\r\n807\r\n813\r\n819\r\n827\r\n345\r\n350\r\n396\r\n431\r\n461\r\n464\r\n491\r\n496\r\n644\r\n649\r\n833\r\n834\r\n835\r\n844\r\n890\r\n898\r\n921\r\n962\r\n964\r\n969\r\nMiami, Arizona\r\n473\r\nMohave Valley, Arizona\r\n768\r\nMormon Lake, Arizona\r\n354\r\nMunds Park, Arizona\r\n286\r\nNorth Phoenix, Arizona\r\n395\r\n404\r\n504\r\n904\r\nNogales, Arizona\r\n216\r\n281\r\n287\r\n761\r\nOracle, Arizona\r\n896\r\nPage, Arizona\r\n645\r\nParadise Valley, Arizona\r\n585\r\n502\r\nParker, Arizona\r\n669\r\nParker Dam, Arizona\r\n667\r\nPatagonia, Arizona\r\n394\r\nPayson, Arizona\r\n472\r\n474\r\n478\r\nPeach Springs, Arizona\r\n769\r\nPearce, Arizona\r\n826\r\nPeoria, Arizona\r\n878\r\n979\r\nPhoenix, Arizona\r\n201\r\n202\r\n205\r\n207\r\n210\r\n217\r\n219\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n243\r\n244\r\n245\r\n246\r\n247\r\n248\r\n249\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n258\r\n259\r\n260\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n280\r\n285\r\n336\r\n340\r\n351\r\n352\r\n365\r\n371\r\n374\r\n375\r\n379\r\n381\r\n392\r\n393\r\n412\r\n420\r\n433\r\n434\r\n435\r\n436\r\n437\r\n438\r\n439\r\n440\r\n450\r\n460\r\n465\r\n468\r\n470\r\n482\r\n484\r\n486\r\n492\r\n493\r\n495\r\n498\r\n528\r\n530\r\n534\r\n542\r\n543\r\n546\r\n553\r\n561\r\n566\r\n581\r\n582\r\n583\r\n584\r\n588\r\n589\r\n597\r\n630\r\n631\r\n640\r\n650\r\n678\r\n681\r\n759\r\n780\r\n788\r\n789\r\n841\r\n843\r\n846\r\n848\r\n849\r\n853\r\n856\r\n862\r\n863\r\n864\r\n866\r\n867\r\n869\r\n876\r\n879\r\n912\r\n919\r\n925\r\n932\r\n933\r\n935\r\n936\r\n938\r\n942\r\n953\r\n954\r\n955\r\n956\r\n957\r\n971\r\n972\r\n973\r\n974\r\n977\r\n978\r\n980\r\n992\r\n993\r\n995\r\n996\r\n306\r\n319\r\n320\r\n360\r\n376\r\n377\r\n382\r\n389\r\n390\r\n397\r\n401\r\n407\r\n409\r\n490\r\n501\r\n506\r\n514\r\n540\r\n549\r\n594\r\n808\r\n809\r\nPima, Arizona\r\n485\r\nPine, Arizona\r\n476\r\nPinedale, Arizona\r\n739\r\nPinetop, Arizona\r\n367\r\n368\r\n369\r\nPolacca, Arizona\r\n737\r\nPortal, Arizona\r\n558\r\nPoston, Arizona\r\n662\r\nPrescott, Arizona\r\n717\r\n442\r\n445\r\n632\r\n771\r\n772\r\n775\r\n776\r\n778\r\nQuartzsite, Arizona\r\n927\r\nRed Valley, Arizona\r\n653\r\nRio Mojava, Arizona\r\n330\r\nRiviera, Arizona\r\n758\r\n763\r\nRock Point, Arizona\r\n659\r\nRoosevelt Lake, Arizona\r\n467\r\nRough Rock, Arizona\r\n728\r\nSacaton, Arizona\r\n562\r\nSafford, Arizona\r\n348\r\n552\r\n428\r\nSalome, Arizona\r\n859\r\nSan Carlos, Arizona\r\n475\r\nSan Manuel, Arizona\r\n385\r\nSan Simon, Arizona\r\n845\r\nSanders, Arizona\r\n688\r\nSanta Rosa, Arizona\r\n361\r\nSasabe, Arizona\r\n823\r\nScottsdale, Arizona\r\n301\r\n391\r\n423\r\n441\r\n443\r\n451\r\n481\r\n483\r\n494\r\n563\r\n569\r\n596\r\n661\r\n840\r\n852\r\n860\r\n941\r\n945\r\n946\r\n947\r\n948\r\n949\r\n951\r\n952\r\n959\r\n970\r\n990\r\n991\r\n994\r\n998\r\nSedona, Arizona\r\n204\r\n282\r\n284\r\nSeligman, Arizona\r\n422\r\nSells, Arizona\r\n383\r\nShonto, Arizona\r\n672\r\nShow Low, Arizona\r\n532\r\n537\r\nSierra Vista, Arizona\r\n378\r\n452\r\n456\r\n458\r\n459\r\n533\r\n538\r\n559\r\nSnowflake, Arizona\r\n536\r\nSomerton, Arizona\r\n627\r\nSpringerville, Arizona\r\n333\r\nSaint John's, Arizona\r\n337\r\nStanfield, Arizona\r\n424\r\nStotonic, Arizona\r\n418\r\nSunizona, Arizona\r\n824\r\nSunnyslope, Arizona\r\n331\r\n861\r\n870\r\n943\r\n944\r\n997\r\nSupai, Arizona\r\n448\r\nSuperior, Arizona\r\n689\r\nSuperstition, Arizona\r\n373\r\n380\r\n641\r\n671\r\n830\r\n832\r\n891\r\n924\r\n981\r\n982\r\n983\r\n984\r\n985\r\n986\r\nTanque Verde, Arizona\r\n749\r\n760\r\nTeecnospos, Arizona\r\n656\r\nTempe, Arizona\r\n413\r\n414\r\n592\r\n858\r\n902\r\n914\r\n693\r\n731\r\n784\r\n829\r\n894\r\n929\r\n965\r\n966\r\n967\r\n968\r\nTombstone, Arizona\r\n457\r\nTonto Basin, Arizona\r\n479\r\nToyci, Arizona\r\n736\r\nTsaile, Arizona\r\n724\r\nTuba City, Arizona\r\n283\r\nTubac, Arizona\r\n398\r\nTucson, Arizona\r\n318\r\n349\r\n403\r\n410\r\n429\r\n444\r\n449\r\n508\r\n513\r\n529\r\n573\r\n617\r\n676\r\n690\r\n770\r\n880\r\n290\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n446\r\n447\r\n469\r\n544\r\n574\r\n575\r\n576\r\n577\r\n578\r\n579\r\n620\r\n621\r\n622\r\n623\r\n624\r\n626\r\n628\r\n629\r\n670\r\n694\r\n695\r\n720\r\n721\r\n722\r\n740\r\n741\r\n742\r\n743\r\n744\r\n746\r\n751\r\n791\r\n792\r\n793\r\n794\r\n795\r\n797\r\n798\r\n799\r\n822\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\nVail, Arizona\r\n647\r\n762\r\nWellton, Arizona\r\n785\r\nWest San Simon, Arizona\r\n362\r\nWhite River, Arizona\r\n332\r\n338\r\nWhitlow, Arizona\r\n463\r\nWickenburg, Arizona\r\n684\r\nWide Ruin, Arizona\r\n652\r\nWikieup, Arizona\r\n765\r\nWillcox, Arizona\r\n905\r\n384\r\nWilliams, Arizona\r\n635\r\nWindow Rock, Arizona\r\n871\r\nWinslow, Arizona\r\n587\r\n613\r\n999\r\n289\r\nYarnell, Arizona\r\n427\r\nYork, Arizona\r\n687\r\nYoung, Arizona\r\n462\r\nYucca, Arizona\r\n766\r\nYuma, Arizona\r\n305\r\n317\r\n539\r\n580\r\n920\r\n328\r\n329\r\n341\r\n342\r\n343\r\n344\r\n726\r\n782\r\n783\r\n\u00035Unknown prefix code (602) - Arizona\r\n"
  },
  {
    "path": "install/regions/regions.603",
    "content": "Alstead, New Hampshire\r\n835\r\nAlton, New Hampshire\r\n875\r\nAndover, New Hampshire\r\n735\r\nAntrim, New Hampshire\r\n588\r\nAshland, New Hampshire\r\n968\r\nBarnstead, New Hampshire\r\n776\r\nBarrington, New Hampshire\r\n664\r\nBartlett, New Hampshire\r\n374\r\nBedford, New Hampshire\r\n471\r\n472\r\nBelmont, New Hampshire\r\n267\r\nBerlin, New Hampshire\r\n342\r\n752\r\nBethlehem, New Hampshire\r\n869\r\nBoscawen, New Hampshire\r\n796\r\nBradford, New Hampshire\r\n938\r\nBretton Woods, New Hampshire\r\n278\r\nBristol, New Hampshire\r\n744\r\nCampton, New Hampshire\r\n236\r\n726\r\nCanaan, New Hampshire\r\n523\r\nCandia, New Hampshire\r\n483\r\nCanterbury, New Hampshire\r\n783\r\nCenter Harbor, New Hampshire\r\n253\r\nCharleston, New Hampshire\r\n826\r\nChatham, New Hampshire\r\n694\r\nChester, New Hampshire\r\n887\r\nChicago, New Hampshire\r\n798\r\nClaremont, New Hampshire\r\n542\r\n543\r\nColebrook, New Hampshire\r\n237\r\nConcord, New Hampshire\r\n496\r\n224\r\n225\r\n226\r\n228\r\n229\r\n271\r\nContoocook, New Hampshire\r\n746\r\nConway, New Hampshire\r\n447\r\nCenter Barnstead, New Hampshire\r\n269\r\nCtrossipee, New Hampshire\r\n539\r\nCenter Sandwich, New Hampshire\r\n284\r\n476\r\nDanbury, New Hampshire\r\n768\r\nDeerfield, New Hampshire\r\n463\r\nDerry, New Hampshire\r\n421\r\n425\r\n426\r\n432\r\n434\r\n437\r\nDixvlnotch, New Hampshire\r\n255\r\nDover, New Hampshire\r\n248\r\n740\r\n767\r\n534\r\n742\r\n743\r\n749\r\nDublin, New Hampshire\r\n563\r\nDunbarton, New Hampshire\r\n774\r\nDurham, New Hampshire\r\n862\r\n868\r\nEast Conway, New Hampshire\r\n939\r\nEnfield, New Hampshire\r\n632\r\nEpping, New Hampshire\r\n679\r\nEpsom, New Hampshire\r\n736\r\nErrol, New Hampshire\r\n482\r\nExeter, New Hampshire\r\n772\r\n778\r\nFarmington, New Hampshire\r\n755\r\nFitzwillam, New Hampshire\r\n585\r\nFranconia, New Hampshire\r\n823\r\nFranklin, New Hampshire\r\n934\r\nGlmtnirnwk, New Hampshire\r\n364\r\nGoffstown, New Hampshire\r\n497\r\nGorham, New Hampshire\r\n466\r\nGreenfield, New Hampshire\r\n547\r\nGreenville, New Hampshire\r\n878\r\nGroveton, New Hampshire\r\n636\r\nHampstead, New Hampshire\r\n329\r\n362\r\nHampton, New Hampshire\r\n926\r\n929\r\nHancock, New Hampshire\r\n525\r\nHanover, New Hampshire\r\n650\r\n640\r\n643\r\n646\r\nHarrisville, New Hampshire\r\n827\r\nHenniker, New Hampshire\r\n428\r\nHillsboro, New Hampshire\r\n464\r\nHinsdale, New Hampshire\r\n336\r\nHlsboup Village, New Hampshire\r\n478\r\nHollis, New Hampshire\r\n465\r\nJackson, New Hampshire\r\n383\r\nJaffrey, New Hampshire\r\n532\r\nJefferson, New Hampshire\r\n586\r\nKeene, New Hampshire\r\n355\r\n352\r\n357\r\n358\r\nKingston, New Hampshire\r\n642\r\nLaconia, New Hampshire\r\n387\r\n293\r\n366\r\n524\r\n527\r\n528\r\nLancaster, New Hampshire\r\n788\r\nLebanon, New Hampshire\r\n252\r\n443\r\n448\r\nLisbon, New Hampshire\r\n838\r\nLittleton, New Hampshire\r\n444\r\nLyme, New Hampshire\r\n795\r\nMadison, New Hampshire\r\n367\r\nManchester, New Hampshire\r\n481\r\n492\r\n564\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n628\r\n634\r\n639\r\n641\r\n644\r\n645\r\n647\r\n666\r\n668\r\n669\r\n695\r\n955\r\nMarlborugh, New Hampshire\r\n876\r\nMarlow, New Hampshire\r\n446\r\nMelvin Village, New Hampshire\r\n544\r\nMeredith, New Hampshire\r\n279\r\nMeriden, New Hampshire\r\n469\r\nMerrimack, New Hampshire\r\n423\r\n494\r\n345\r\n424\r\n429\r\n493\r\nMilan, New Hampshire\r\n449\r\nMilford, New Hampshire\r\n672\r\n673\r\nMilton Mills, New Hampshire\r\n473\r\nMilton, New Hampshire\r\n652\r\nMonroe, New Hampshire\r\n638\r\nNashua, New Hampshire\r\n598\r\n599\r\n791\r\n594\r\n595\r\n596\r\n880\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n888\r\n889\r\n891\r\nNew Boston, New Hampshire\r\n487\r\nNew Durham, New Hampshire\r\n859\r\nNew London, New Hampshire\r\n526\r\nNewmarket, New Hampshire\r\n659\r\nNewport, New Hampshire\r\n863\r\nNorth Conway, New Hampshire\r\n356\r\nNorth Stratfd, New Hampshire\r\n922\r\nNorth Walpole, New Hampshire\r\n445\r\nNorthwood, New Hampshire\r\n942\r\nNorth Woodstock, New Hampshire\r\n745\r\nOrford, New Hampshire\r\n353\r\nPelham, New Hampshire\r\n635\r\nPenacook, New Hampshire\r\n753\r\nPeterborgh, New Hampshire\r\n924\r\nPiermont, New Hampshire\r\n272\r\nPike, New Hampshire\r\n989\r\nPittsburg, New Hampshire\r\n538\r\nPittsfield, New Hampshire\r\n435\r\nPlainfield, New Hampshire\r\n675\r\nPlaistow, New Hampshire\r\n382\r\nPlymouth, New Hampshire\r\n535\r\n536\r\nPortsmouth, New Hampshire\r\n334\r\n422\r\n427\r\n430\r\n431\r\n433\r\n436\r\nRaymond, New Hampshire\r\n895\r\nRindge, New Hampshire\r\n899\r\nRochester, New Hampshire\r\n337\r\n332\r\n335\r\nRumney, New Hampshire\r\n786\r\nRye Beach, New Hampshire\r\n964\r\nSalem, New Hampshire\r\n890\r\n893\r\n894\r\n898\r\nSalisbury, New Hampshire\r\n648\r\nSanbornville, New Hampshire\r\n522\r\nSeabrook, New Hampshire\r\n474\r\nSouth Hampton, New Hampshire\r\n394\r\nSomersworth, New Hampshire\r\n692\r\nSpofford, New Hampshire\r\n363\r\nSullivan, New Hampshire\r\n847\r\nSunapee, New Hampshire\r\n763\r\nSuncook, New Hampshire\r\n268\r\n485\r\nSutton, New Hampshire\r\n927\r\nTamworth, New Hampshire\r\n323\r\nTilton, New Hampshire\r\n286\r\nTroy, New Hampshire\r\n242\r\nTwin Mount, New Hampshire\r\n846\r\nWalpole, New Hampshire\r\n756\r\nWarner, New Hampshire\r\n456\r\nWarren, New Hampshire\r\n764\r\nWashington, New Hampshire\r\n495\r\nWest Chesterfield, New Hampshire\r\n256\r\nWeare, New Hampshire\r\n529\r\nWest Lebanon, New Hampshire\r\n298\r\nWest Stewtston, New Hampshire\r\n246\r\nWhitefield, New Hampshire\r\n837\r\nWilton, New Hampshire\r\n654\r\nWinchester, New Hampshire\r\n239\r\nWestmoreland, New Hampshire\r\n399\r\nWolfeboro, New Hampshire\r\n569\r\nWoodsville, New Hampshire\r\n747\r\n787\r\n\u00035Unknown prefix code (603) - New Hampshire\r\n"
  },
  {
    "path": "install/regions/regions.604",
    "content": "Abbotsford, British Columbia, Canada\r\n855\r\n864\r\n850\r\n852\r\n853\r\n854\r\n859\r\nAgassiz, British Columbia, Canada\r\n796\r\nAhousat, British Columbia, Canada\r\n670\r\nAiyansh, British Columbia, Canada\r\n633\r\nAldergrove, British Columbia, Canada\r\n856\r\n857\r\nAlert Bay, British Columbia, Canada\r\n974\r\nAlexis Creek, British Columbia, Canada\r\n394\r\n395\r\nAlkali Lake, British Columbia, Canada\r\n440\r\nArmstrong, British Columbia, Canada\r\n546\r\nAshcroft, British Columbia, Canada\r\n453\r\nAtlin, British Columbia, Canada\r\n651\r\nAttachie, British Columbia, Canada\r\n262\r\nAvola, British Columbia, Canada\r\n678\r\nB Quin Lake, British Columbia, Canada\r\n237\r\nBalfour, British Columbia, Canada\r\n229\r\nBamfield, British Columbia, Canada\r\n728\r\nBarriere, British Columbia, Canada\r\n672\r\nBear Lake, British Columbia, Canada\r\n972\r\nBearskin Lake, British Columbia, Canada\r\n236\r\nBeaver Valley, British Columbia, Canada\r\n243\r\nBeavercove, British Columbia, Canada\r\n928\r\nBeaverdell, British Columbia, Canada\r\n484\r\nBellabella, British Columbia, Canada\r\n957\r\nBellacoola, British Columbia, Canada\r\n799\r\n982\r\nBlue River, British Columbia, Canada\r\n673\r\nBoston Bar, British Columbia, Canada\r\n867\r\nBoswell, British Columbia, Canada\r\n223\r\nBowen Isle, British Columbia, Canada\r\n947\r\nBowser, British Columbia, Canada\r\n757\r\nBridge Lake, British Columbia, Canada\r\n593\r\nBritana Beach, British Columbia, Canada\r\n896\r\nBurns Lake, British Columbia, Canada\r\n692\r\n695\r\n698\r\nCache Creek, British Columbia, Canada\r\n457\r\nCampbel River, British Columbia, Canada\r\n285\r\n286\r\n287\r\n923\r\nCanal Flats, British Columbia, Canada\r\n349\r\nCassiar, British Columbia, Canada\r\n778\r\nCastlegar, British Columbia, Canada\r\n365\r\nCelista, British Columbia, Canada\r\n955\r\nChase, British Columbia, Canada\r\n577\r\n679\r\nChemainus, British Columbia, Canada\r\n246\r\nChetwynd, British Columbia, Canada\r\n788\r\nChief Lake, British Columbia, Canada\r\n967\r\nChilako, British Columbia, Canada\r\n560\r\nChilliwack, British Columbia, Canada\r\n793\r\n824\r\n792\r\n794\r\n795\r\n823\r\n858\r\nChristina Lake, British Columbia, Canada\r\n447\r\nClearwater, British Columbia, Canada\r\n587\r\n674\r\nClinton, British Columbia, Canada\r\n459\r\nCloverdale, British Columbia, Canada\r\n531\r\n535\r\n536\r\n538\r\n574\r\n576\r\nCluculz Lake, British Columbia, Canada\r\n441\r\nCobblehill, British Columbia, Canada\r\n743\r\nComox Valley, British Columbia, Canada\r\n338\r\nCortez Isle, British Columbia, Canada\r\n935\r\nCourtenay, British Columbia, Canada\r\n334\r\n339\r\nCranbrook, British Columbia, Canada\r\n426\r\n489\r\nCrawford Bay, British Columbia, Canada\r\n227\r\nCreston, British Columbia, Canada\r\n428\r\n866\r\nCumberland, British Columbia, Canada\r\n336\r\nDarcy, British Columbia, Canada\r\n452\r\nDawson Creek, British Columbia, Canada\r\n759\r\n782\r\n784\r\n843\r\nDease Lake, British Columbia, Canada\r\n771\r\nDonald, British Columbia, Canada\r\n340\r\nDouglas Lake, British Columbia, Canada\r\n350\r\nDuncan Lake, British Columbia, Canada\r\n366\r\nDuncan, British Columbia, Canada\r\n746\r\n748\r\nDunster, British Columbia, Canada\r\n968\r\nEast Pine, British Columbia, Canada\r\n780\r\nElkford, British Columbia, Canada\r\n865\r\nElko, British Columbia, Canada\r\n529\r\nEnderby, British Columbia, Canada\r\n838\r\nFalkland, British Columbia, Canada\r\n379\r\nFauquier, British Columbia, Canada\r\n269\r\nFernie, British Columbia, Canada\r\n423\r\nField, British Columbia, Canada\r\n343\r\nFlatrock, British Columbia, Canada\r\n781\r\nForest Grove, British Columbia, Canada\r\n397\r\nFort Ware, British Columbia, Canada\r\n471\r\nFort Fraser, British Columbia, Canada\r\n690\r\nFort Nelson, British Columbia, Canada\r\n774\r\nFort Saint John, British Columbia, Canada\r\n785\r\n787\r\n789\r\n827\r\nFraser Lake, British Columbia, Canada\r\n699\r\nFruitvale, British Columbia, Canada\r\n367\r\nFort Saint James, British Columbia, Canada\r\n996\r\nGabriolais, British Columbia, Canada\r\n247\r\nGanges, British Columbia, Canada\r\n537\r\n653\r\nGood Hope Lake, British Columbia, Canada\r\n239\r\nGibsons, British Columbia, Canada\r\n886\r\nGiscome, British Columbia, Canada\r\n568\r\nGold River, British Columbia, Canada\r\n283\r\nGoldbridge, British Columbia, Canada\r\n238\r\nGolden, British Columbia, Canada\r\n344\r\nGrand Forks, British Columbia, Canada\r\n442\r\nGranisle, British Columbia, Canada\r\n697\r\nGrasmere, British Columbia, Canada\r\n887\r\nGrassy Pls, British Columbia, Canada\r\n694\r\nGreenville, British Columbia, Canada\r\n621\r\nGreenwood, British Columbia, Canada\r\n445\r\nGulf Is, British Columbia, Canada\r\n539\r\n629\r\nHaney, British Columbia, Canada\r\n460\r\n466\r\n462\r\n463\r\n465\r\n467\r\nHansard, British Columbia, Canada\r\n966\r\nHartley Bay, British Columbia, Canada\r\n841\r\nHazelton, British Columbia, Canada\r\n842\r\nHedley, British Columbia, Canada\r\n292\r\nHemlock Valley, British Columbia, Canada\r\n797\r\nHendrix Lake, British Columbia, Canada\r\n393\r\nHighland Valley, British Columbia, Canada\r\n575\r\nHixon, British Columbia, Canada\r\n998\r\nHolberg, British Columbia, Canada\r\n288\r\nHope, British Columbia, Canada\r\n869\r\nHorsefly, British Columbia, Canada\r\n620\r\nHouston, British Columbia, Canada\r\n845\r\nHudsonhope, British Columbia, Canada\r\n783\r\nInvermere, British Columbia, Canada\r\n342\r\n345\r\nIskut, British Columbia, Canada\r\n234\r\nJaffray, British Columbia, Canada\r\n429\r\nKamloops, British Columbia, Canada\r\n371\r\n372\r\n374\r\n376\r\n554\r\n573\r\n578\r\n579\r\n828\r\n851\r\nKaslo, British Columbia, Canada\r\n353\r\nKelowna, British Columbia, Canada\r\n470\r\n491\r\n868\r\n762\r\n763\r\n764\r\n765\r\n769\r\n860\r\n861\r\n862\r\nKemano, British Columbia, Canada\r\n634\r\nKeremeos, British Columbia, Canada\r\n499\r\nKersley, British Columbia, Canada\r\n993\r\nKimberley, British Columbia, Canada\r\n427\r\nKincolith, British Columbia, Canada\r\n326\r\nKitimat, British Columbia, Canada\r\n632\r\n639\r\nKitkatla, British Columbia, Canada\r\n848\r\nKitsault, British Columbia, Canada\r\n831\r\nKitwanga, British Columbia, Canada\r\n849\r\nKlemtu, British Columbia, Canada\r\n839\r\nKyuquot, British Columbia, Canada\r\n332\r\nLaclahache, British Columbia, Canada\r\n396\r\nLadner, British Columbia, Canada\r\n940\r\n943\r\n946\r\n948\r\nLadysmith, British Columbia, Canada\r\n245\r\nLakelse, British Columbia, Canada\r\n798\r\nLangley, British Columbia, Canada\r\n530\r\n532\r\n533\r\n534\r\n882\r\n888\r\nLasquet Is, British Columbia, Canada\r\n333\r\nLikely, British Columbia, Canada\r\n790\r\n791\r\nLillooet, British Columbia, Canada\r\n256\r\nLittle Fort, British Columbia, Canada\r\n677\r\nLake Cowichan, British Columbia, Canada\r\n749\r\nLogan Lake, British Columbia, Canada\r\n523\r\nLower Post, British Columbia, Canada\r\n779\r\nLumby, British Columbia, Canada\r\n547\r\nLytton, British Columbia, Canada\r\n455\r\n456\r\nMackenzie, British Columbia, Canada\r\n997\r\nManning Park, British Columbia, Canada\r\n840\r\nMasset, British Columbia, Canada\r\n626\r\nMcBride, British Columbia, Canada\r\n569\r\nMcDame Lake, British Columbia, Canada\r\n233\r\nMcLeese Lake, British Columbia, Canada\r\n297\r\nMcLeod Lake, British Columbia, Canada\r\n750\r\nMerritt, British Columbia, Canada\r\n378\r\nMica Creek, British Columbia, Canada\r\n834\r\nMidway, British Columbia, Canada\r\n449\r\nMinaker River, British Columbia, Canada\r\n773\r\nMission, British Columbia, Canada\r\n820\r\n826\r\nMoyie, British Columbia, Canada\r\n829\r\nMuncho Lake, British Columbia, Canada\r\n776\r\nNakusp, British Columbia, Canada\r\n265\r\nNanaimo, British Columbia, Canada\r\n390\r\n722\r\n741\r\n753\r\n754\r\n755\r\n756\r\n758\r\n751\r\nNelson, British Columbia, Canada\r\n352\r\n354\r\n825\r\nNew Denver, British Columbia, Canada\r\n358\r\nNewton, British Columbia, Canada\r\n543\r\n572\r\n590\r\n591\r\n594\r\n596\r\n597\r\n599\r\nNimpo Lake, British Columbia, Canada\r\n742\r\nNorth Vancouver, British Columbia, Canada\r\n929\r\n980\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n924\r\n981\r\nNorth Westminister, British Columbia, Canada\r\n520\r\n521\r\n522\r\n524\r\n525\r\n526\r\n527\r\n580\r\n581\r\n583\r\n584\r\n585\r\n588\r\n589\r\n351\r\n377\r\n528\r\n540\r\n582\r\n586\r\n878\r\n889\r\n951\r\nOcean Falls, British Columbia, Canada\r\n289\r\nOkanagan Falls, British Columbia, Canada\r\n497\r\nOliver, British Columbia, Canada\r\n498\r\nOsoyoos, British Columbia, Canada\r\n495\r\nOyama, British Columbia, Canada\r\n548\r\nOyster Bay, British Columbia, Canada\r\n337\r\nParksville, British Columbia, Canada\r\n248\r\n468\r\n752\r\n954\r\nParson, British Columbia, Canada\r\n348\r\nPeachland, British Columbia, Canada\r\n767\r\nPemberton, British Columbia, Canada\r\n894\r\nPender Harbor, British Columbia, Canada\r\n883\r\nPenticton, British Columbia, Canada\r\n490\r\n492\r\n493\r\n496\r\nPoint Roberts, British Columbia, Canada\r\n945\r\nPort Alice, British Columbia, Canada\r\n284\r\nPort Hardy, British Columbia, Canada\r\n949\r\nPort Moody, British Columbia, Canada\r\n461\r\n469\r\n931\r\n936\r\n937\r\n939\r\nPort Edward, British Columbia, Canada\r\n628\r\nPort Mellon, British Columbia, Canada\r\n884\r\nPoucecoupe, British Columbia, Canada\r\n786\r\nPowell River, British Columbia, Canada\r\n483\r\n485\r\n487\r\nPrespatou, British Columbia, Canada\r\n630\r\nPrince George, British Columbia, Canada\r\n561\r\n562\r\n563\r\n564\r\n565\r\n962\r\n963\r\n964\r\nPrince Rupert, British Columbia, Canada\r\n624\r\n627\r\nPrinceton, British Columbia, Canada\r\n295\r\nPort Alberni, British Columbia, Canada\r\n720\r\n723\r\n724\r\nPort McNeil, British Columbia, Canada\r\n956\r\nPort Renfrew, British Columbia, Canada\r\n647\r\nPort Simpson, British Columbia, Canada\r\n625\r\nPort Clements, British Columbia, Canada\r\n557\r\nPort Coquitlm, British Columbia, Canada\r\n464\r\n941\r\n942\r\n944\r\nPuntzi, British Columbia, Canada\r\n481\r\nQn Charlot, British Columbia, Canada\r\n559\r\nQuesnel, British Columbia, Canada\r\n249\r\n747\r\n992\r\nRadium, British Columbia, Canada\r\n347\r\nRed Rock, British Columbia, Canada\r\n330\r\nRevelstoke, British Columbia, Canada\r\n837\r\nRichmond, British Columbia, Canada\r\n231\r\n241\r\n244\r\n448\r\n671\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\nRiondel, British Columbia, Canada\r\n225\r\nRiske Creek, British Columbia, Canada\r\n659\r\nRock Creek, British Columbia, Canada\r\n446\r\nRossland, British Columbia, Canada\r\n362\r\nSaanich, British Columbia, Canada\r\n652\r\n655\r\n656\r\nSalmo, British Columbia, Canada\r\n357\r\nSalmon Arm, British Columbia, Canada\r\n832\r\n833\r\n835\r\nSalmon Valley, British Columbia, Canada\r\n971\r\nSandspit, British Columbia, Canada\r\n637\r\nSavona, British Columbia, Canada\r\n373\r\nSayward, British Columbia, Canada\r\n282\r\nSechelt, British Columbia, Canada\r\n885\r\nShalalth, British Columbia, Canada\r\n259\r\nSicamous, British Columbia, Canada\r\n836\r\nSkookumchk, British Columbia, Canada\r\n422\r\nSlocan, British Columbia, Canada\r\n355\r\nSmithers, British Columbia, Canada\r\n847\r\nSouth Slocan, British Columbia, Canada\r\n359\r\nSointula, British Columbia, Canada\r\n973\r\nSooke, British Columbia, Canada\r\n642\r\n646\r\nSorrento, British Columbia, Canada\r\n675\r\nSparwood, British Columbia, Canada\r\n425\r\nSpencesbridge, British Columbia, Canada\r\n458\r\nSpilmachen, British Columbia, Canada\r\n346\r\nSquamish, British Columbia, Canada\r\n892\r\n898\r\nStewart, British Columbia, Canada\r\n636\r\nSummerland, British Columbia, Canada\r\n494\r\nSummit Lake, British Columbia, Canada\r\n965\r\nTachie, British Columbia, Canada\r\n648\r\nTahsis, British Columbia, Canada\r\n934\r\nTatla Lake, British Columbia, Canada\r\n476\r\nTelegraph Creek, British Columbia, Canada\r\n235\r\nTelkwa, British Columbia, Canada\r\n846\r\nTerrace, British Columbia, Canada\r\n635\r\n638\r\nThrums, British Columbia, Canada\r\n399\r\nToad River, British Columbia, Canada\r\n232\r\nTofino, British Columbia, Canada\r\n725\r\nTopley, British Columbia, Canada\r\n696\r\nTrail, British Columbia, Canada\r\n364\r\n368\r\n693\r\nTrout Lake, British Columbia, Canada\r\n369\r\nTumblerdge, British Columbia, Canada\r\n242\r\nUcluelet, British Columbia, Canada\r\n726\r\nUnion Bay, British Columbia, Canada\r\n335\r\nValemount, British Columbia, Canada\r\n566\r\nVallican, British Columbia, Canada\r\n226\r\nVananda, British Columbia, Canada\r\n486\r\nVancouver, British Columbia, Canada\r\n220\r\n221\r\n230\r\n252\r\n257\r\n268\r\n280\r\n320\r\n323\r\n328\r\n443\r\n451\r\n482\r\n571\r\n623\r\n667\r\n680\r\n691\r\n735\r\n739\r\n775\r\n811\r\n822\r\n830\r\n844\r\n871\r\n880\r\n891\r\n893\r\n895\r\n899\r\n930\r\n970\r\n977\r\n978\r\n979\r\n222\r\n224\r\n228\r\n240\r\n250\r\n251\r\n253\r\n254\r\n255\r\n261\r\n263\r\n264\r\n266\r\n290\r\n291\r\n293\r\n294\r\n298\r\n299\r\n321\r\n322\r\n324\r\n325\r\n327\r\n420\r\n421\r\n430\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n437\r\n438\r\n439\r\n444\r\n631\r\n640\r\n641\r\n643\r\n644\r\n645\r\n649\r\n650\r\n654\r\n657\r\n660\r\n661\r\n662\r\n663\r\n664\r\n665\r\n666\r\n668\r\n669\r\n681\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n731\r\n732\r\n733\r\n734\r\n736\r\n737\r\n738\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n879\r\nVanderhoof, British Columbia, Canada\r\n567\r\nVavenby, British Columbia, Canada\r\n676\r\nVernon, British Columbia, Canada\r\n542\r\n545\r\n549\r\n558\r\nVernon Lake, British Columbia, Canada\r\n363\r\nVictoria, British Columbia, Canada\r\n360\r\n472\r\n475\r\n480\r\n744\r\n952\r\n953\r\n995\r\n356\r\n361\r\n370\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n389\r\n474\r\n477\r\n478\r\n479\r\n592\r\n595\r\n598\r\n658\r\n721\r\n727\r\nWells, British Columbia, Canada\r\n994\r\nWest Vancouver, British Columbia, Canada\r\n921\r\n922\r\n925\r\n926\r\nWestbank, British Columbia, Canada\r\n768\r\nWestwold, British Columbia, Canada\r\n375\r\nWhistler, British Columbia, Canada\r\n932\r\n938\r\nWilliams Lake, British Columbia, Canada\r\n296\r\n392\r\n398\r\n989\r\nWillow Flats, British Columbia, Canada\r\n920\r\nWinfield, British Columbia, Canada\r\n766\r\nWinter Harbor, British Columbia, Canada\r\n969\r\nWonowon, British Columbia, Canada\r\n772\r\nWoss Lake, British Columbia, Canada\r\n281\r\nYahk, British Columbia, Canada\r\n424\r\nYale, British Columbia, Canada\r\n863\r\nYoubou, British Columbia, Canada\r\n745\r\nZeballos, British Columbia, Canada\r\n761\r\n\u00035Unknown prefix code (604) - British Columbia, Canada\r\n"
  },
  {
    "path": "install/regions/regions.605",
    "content": "Aberdeen, South Dakota\r\n228\r\n240\r\n380\r\n225\r\n226\r\n229\r\n377\r\n622\r\nAcademy, South Dakota\r\n726\r\nAlcester, South Dakota\r\n934\r\nAlexandria, South Dakota\r\n239\r\nAlpena, South Dakota\r\n849\r\nAlsen, South Dakota\r\n253\r\nAndover, South Dakota\r\n298\r\nArdmore, South Dakota\r\n459\r\nArlington, South Dakota\r\n983\r\nArmour, South Dakota\r\n724\r\nArtesian, South Dakota\r\n527\r\nAstoria, South Dakota\r\n832\r\nAvon, South Dakota\r\n286\r\nBaltic, South Dakota\r\n529\r\nBelle French, South Dakota\r\n892\r\nBelvidere, South Dakota\r\n344\r\nBeresford, South Dakota\r\n763\r\n957\r\nBig Stone City, South Dakota\r\n862\r\nBison, South Dakota\r\n244\r\nBlunt, South Dakota\r\n962\r\nBonesteel, South Dakota\r\n654\r\nBowdle, South Dakota\r\n285\r\nBradley, South Dakota\r\n784\r\nBrandon, South Dakota\r\n582\r\nBrandt, South Dakota\r\n876\r\nBridgewater, South Dakota\r\n729\r\nBristol, South Dakota\r\n492\r\nBritton, South Dakota\r\n448\r\nBrkngs City, South Dakota\r\n688\r\n689\r\n690\r\n692\r\n693\r\n695\r\n696\r\n697\r\nBrntwilo Lake, South Dakota\r\n625\r\n628\r\nBuffalo, South Dakota\r\n375\r\nBuffalo Gap, South Dakota\r\n833\r\nBurke, South Dakota\r\n775\r\nCamp Crook, South Dakota\r\n797\r\nCanistota, South Dakota\r\n296\r\nCanova, South Dakota\r\n523\r\nCanton, South Dakota\r\n987\r\nCastlewood, South Dakota\r\n793\r\nCavour, South Dakota\r\n599\r\nCenter, South Dakota\r\n247\r\nCenterville, South Dakota\r\n563\r\nChamberlan, South Dakota\r\n734\r\nChester, South Dakota\r\n489\r\nClaire City, South Dakota\r\n652\r\nClaremont, South Dakota\r\n294\r\nClark, South Dakota\r\n532\r\nClayton, South Dakota\r\n825\r\nClear Lake, South Dakota\r\n874\r\nClearfield, South Dakota\r\n557\r\nColman, South Dakota\r\n530\r\n534\r\nColton, South Dakota\r\n446\r\nColumbia, South Dakota\r\n396\r\nConde, South Dakota\r\n382\r\nCorsica, South Dakota\r\n946\r\nCreighton, South Dakota\r\n457\r\nCresbard, South Dakota\r\n324\r\nCrooks, South Dakota\r\n543\r\nCuster, South Dakota\r\n673\r\nDe Smet, South Dakota\r\n854\r\nDeadwood, South Dakota\r\n578\r\nDell Rapids, South Dakota\r\n428\r\nDelmont, South Dakota\r\n779\r\nDoland, South Dakota\r\n635\r\nDupree, South Dakota\r\n365\r\n538\r\nEagle Butte, South Dakota\r\n964\r\nEdgemont, South Dakota\r\n662\r\nElk Point, South Dakota\r\n356\r\nElkton, South Dakota\r\n542\r\nEmery, South Dakota\r\n449\r\nEast Newcastle, South Dakota\r\n749\r\nEnning, South Dakota\r\n985\r\nEstelline, South Dakota\r\n873\r\nEthan, South Dakota\r\n227\r\nEureka, South Dakota\r\n284\r\nFaith, South Dakota\r\n739\r\n967\r\nFaulkton, South Dakota\r\n598\r\nFerney, South Dakota\r\n395\r\nFlandreau, South Dakota\r\n997\r\nFlorence, South Dakota\r\n758\r\nFlyger, South Dakota\r\n327\r\nForestburg, South Dakota\r\n495\r\nFrederick, South Dakota\r\n329\r\nFreeman, South Dakota\r\n925\r\nFort Thompson, South Dakota\r\n245\r\nGann Valley, South Dakota\r\n293\r\nGarretson, South Dakota\r\n594\r\nGary, South Dakota\r\n272\r\nGettysburg, South Dakota\r\n765\r\nGlenham, South Dakota\r\n848\r\n850\r\n762\r\nGoodwin, South Dakota\r\n795\r\nGregory, South Dakota\r\n835\r\nGroton, South Dakota\r\n397\r\nHarrisburg T, South Dakota\r\n368\r\n743\r\nHarrold, South Dakota\r\n875\r\nHartford, South Dakota\r\n528\r\nHayes, South Dakota\r\n567\r\nHayti, South Dakota\r\n783\r\nHecla, South Dakota\r\n994\r\nHermosa, South Dakota\r\n255\r\nHerreid, South Dakota\r\n437\r\nHighmore, South Dakota\r\n852\r\nHill City, South Dakota\r\n574\r\nHitchcock, South Dakota\r\n266\r\nHosmer, South Dakota\r\n283\r\nHot Springs, South Dakota\r\n745\r\n890\r\n899\r\nHoughton, South Dakota\r\n885\r\nHoven, South Dakota\r\n948\r\nHoward, South Dakota\r\n772\r\nHudson, South Dakota\r\n984\r\nHumboldt, South Dakota\r\n363\r\nHurley, South Dakota\r\n238\r\nHuron, South Dakota\r\n290\r\n350\r\n354\r\n352\r\n353\r\nInterior, South Dakota\r\n433\r\nIpswich, South Dakota\r\n426\r\nIrene, South Dakota\r\n263\r\nIroquois, South Dakota\r\n546\r\nIsabel, South Dakota\r\n466\r\nJefferson, South Dakota\r\n966\r\nKadoka, South Dakota\r\n837\r\nKennebec, South Dakota\r\n869\r\nKeystone, South Dakota\r\n666\r\nKimball, South Dakota\r\n778\r\nKyle, South Dakota\r\n455\r\nLa Plant, South Dakota\r\n733\r\nLake Andes, South Dakota\r\n487\r\nLake Norden, South Dakota\r\n785\r\nLangford, South Dakota\r\n493\r\nLead, South Dakota\r\n584\r\nLebanon, South Dakota\r\n768\r\nLemmon, South Dakota\r\n374\r\nLennox, South Dakota\r\n647\r\nLeola, South Dakota\r\n439\r\nLesterville, South Dakota\r\n364\r\nLetcher, South Dakota\r\n248\r\nLake Preston, South Dakota\r\n847\r\nLong Lake, South Dakota\r\n577\r\nLong Valley, South Dakota\r\n462\r\nMadison, South Dakota\r\n480\r\n256\r\nMarion, South Dakota\r\n648\r\nMartin, South Dakota\r\n685\r\nMaurine, South Dakota\r\n748\r\nMcIntosh, South Dakota\r\n273\r\nMcLaughlin, South Dakota\r\n823\r\nMeadow, South Dakota\r\n788\r\nMellette, South Dakota\r\n887\r\nMenno, South Dakota\r\n387\r\nMidland, South Dakota\r\n843\r\nMilbank, South Dakota\r\n432\r\nMilesville, South Dakota\r\n544\r\nMiller, South Dakota\r\n853\r\nMission, South Dakota\r\n856\r\nMitchell, South Dakota\r\n770\r\n979\r\n999\r\n995\r\n996\r\nMobridge, South Dakota\r\n845\r\nMorristown, South Dakota\r\n524\r\nMound City, South Dakota\r\n955\r\nMount Vernon, South Dakota\r\n236\r\nMurdo, South Dakota\r\n669\r\nNew Effington, South Dakota\r\n637\r\nNewell, South Dakota\r\n456\r\nNew Holland, South Dakota\r\n243\r\nNew Underweed, South Dakota\r\n754\r\nNisland, South Dakota\r\n257\r\nNorth Larchwood, South Dakota\r\n474\r\nNorth Bristow, South Dakota\r\n587\r\nNorth Gordon, South Dakota\r\n288\r\nNorth Kilgore, South Dakota\r\n969\r\nNorth Sioux City, South Dakota\r\n232\r\nNorth Crookston, South Dakota\r\n429\r\nNorth Cody, South Dakota\r\n822\r\nNorth Naper, South Dakota\r\n834\r\nNorth Valentine, South Dakota\r\n378\r\nNunda, South Dakota\r\n586\r\nOelrichs, South Dakota\r\n535\r\nOld Hamramn, South Dakota\r\n482\r\nOnaka, South Dakota\r\n447\r\nOnida, South Dakota\r\n258\r\n264\r\n973\r\nOral, South Dakota\r\n424\r\nOrient, South Dakota\r\n392\r\nParker, South Dakota\r\n297\r\nParkston, South Dakota\r\n928\r\nPeever, South Dakota\r\n932\r\nPhilip, South Dakota\r\n859\r\nPierpont, South Dakota\r\n325\r\nPierre, South Dakota\r\n222\r\n260\r\n945\r\n223\r\n224\r\n773\r\nPine Ridge, South Dakota\r\n867\r\nPlankinton, South Dakota\r\n942\r\nPlatte, South Dakota\r\n337\r\nPollock, South Dakota\r\n889\r\nPresho, South Dakota\r\n895\r\nPukwana, South Dakota\r\n894\r\nQuinn, South Dakota\r\n386\r\nRapid City, South Dakota\r\n341\r\n342\r\n343\r\n348\r\n381\r\n385\r\n388\r\n390\r\n393\r\n394\r\n399\r\n787\r\n877\r\n923\r\nRedfield, South Dakota\r\n460\r\n472\r\nRee Heights, South Dakota\r\n943\r\nReliance, South Dakota\r\n473\r\nRevillo, South Dakota\r\n623\r\nRoscoe, South Dakota\r\n287\r\nRosebud, South Dakota\r\n747\r\nRosholt, South Dakota\r\n537\r\nRoslyn, South Dakota\r\n486\r\nSalem, South Dakota\r\n425\r\nScotland, South Dakota\r\n583\r\nSelby, South Dakota\r\n649\r\nSeneca, South Dakota\r\n436\r\nSinai, South Dakota\r\n826\r\nSioux Falls, South Dakota\r\n357\r\n362\r\n444\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n338\r\n339\r\n360\r\n361\r\n366\r\n367\r\n371\r\n477\r\nSisseton, South Dakota\r\n698\r\nSouth Ashley, South Dakota\r\n289\r\nSouth Ellendl, South Dakota\r\n346\r\nSouth Forbes, South Dakota\r\n358\r\nSouth Forman, South Dakota\r\n735\r\nSouth Guelph, South Dakota\r\n383\r\nSouth Nelvik, South Dakota\r\n379\r\nSouth Reeder, South Dakota\r\n855\r\nSouth Hettinger, South Dakota\r\n564\r\nSolidgerwood, South Dakota\r\n533\r\nSorum, South Dakota\r\n866\r\nSouth Scranton, South Dakota\r\n278\r\nSouth Ladd, South Dakota\r\n576\r\nSouthshore, South Dakota\r\n756\r\nSouth Venturia, South Dakota\r\n687\r\nSpearfish, South Dakota\r\n640\r\n645\r\n642\r\nSpencer, South Dakota\r\n246\r\nSpringfield, South Dakota\r\n369\r\nStickney, South Dakota\r\n732\r\nStockholm, South Dakota\r\n676\r\nSturgis, South Dakota\r\n347\r\nSummit, South Dakota\r\n398\r\nTabor, South Dakota\r\n463\r\nTimberlake, South Dakota\r\n865\r\nTolstoy, South Dakota\r\n442\r\nToronto, South Dakota\r\n794\r\nTripp, South Dakota\r\n935\r\nTulare, South Dakota\r\n596\r\nTurton, South Dakota\r\n897\r\nTyndall, South Dakota\r\n589\r\nValley Springs, South Dakota\r\n757\r\nVeblen, South Dakota\r\n738\r\nVermillion, South Dakota\r\n624\r\n670\r\n677\r\n679\r\nViborg, South Dakota\r\n326\r\nVivian, South Dakota\r\n683\r\nVolga, South Dakota\r\n627\r\nWest Hawarden, South Dakota\r\n547\r\nWest Marietta, South Dakota\r\n678\r\nWagner, South Dakota\r\n384\r\nWakonda, South Dakota\r\n267\r\nWall Lake, South Dakota\r\n526\r\nWall, South Dakota\r\n279\r\nWasta, South Dakota\r\n993\r\nWatertown, South Dakota\r\n880\r\n881\r\n882\r\n886\r\nWaubay, South Dakota\r\n947\r\nWest Browns Valley, South Dakota\r\n694\r\nWebster, South Dakota\r\n345\r\nWentworth, South Dakota\r\n483\r\nWessington Spring, South Dakota\r\n539\r\nWessington, South Dakota\r\n458\r\nWest Akron, South Dakota\r\n565\r\nWest Jasper, South Dakota\r\n349\r\nWest Hendricks, South Dakota\r\n479\r\nWhite Lake, South Dakota\r\n249\r\nWhite, South Dakota\r\n629\r\nWhite River, South Dakota\r\n259\r\nWhitewood, South Dakota\r\n269\r\nWicksville, South Dakota\r\n798\r\nWilmot, South Dakota\r\n938\r\nWinfred, South Dakota\r\n485\r\nWinner, South Dakota\r\n842\r\nWitten, South Dakota\r\n879\r\nWolsey, South Dakota\r\n883\r\nWood, South Dakota\r\n452\r\nWoonsocket, South Dakota\r\n796\r\nWorthing, South Dakota\r\n372\r\nYankton, South Dakota\r\n660\r\n661\r\n665\r\n668\r\n\u00035Unknown prefix code (605) - South Dakota\r\n"
  },
  {
    "path": "install/regions/regions.606",
    "content": "Albany, Kentucky\r\n387\r\nAlexandria, Kentucky\r\n635\r\n694\r\nAllen, Kentucky\r\n874\r\nAnnville, Kentucky\r\n364\r\nAshland, Kentucky\r\n920\r\n324\r\n325\r\n327\r\n329\r\nAugusta, Kentucky\r\n756\r\nBarbourville, Kentucky\r\n546\r\nBeattyville, Kentucky\r\n464\r\nBenhmlynch, Kentucky\r\n848\r\nBerea, Kentucky\r\n986\r\nBlaine, Kentucky\r\n652\r\nBledsoe, Kentucky\r\n558\r\nBoone, Kentucky\r\n209\r\n647\r\n282\r\n283\r\n334\r\n371\r\n384\r\n525\r\n534\r\n586\r\n594\r\n657\r\n689\r\nBooneville, Kentucky\r\n593\r\nBrodhead, Kentucky\r\n758\r\nBrooksville, Kentucky\r\n735\r\nBryantsville, Kentucky\r\n548\r\nBuckhorn, Kentucky\r\n398\r\nBurgin, Kentucky\r\n748\r\nBurlington, Kentucky\r\n430\r\nBurnside, Kentucky\r\n561\r\nButler, Kentucky\r\n472\r\nCampton, Kentucky\r\n668\r\nCanoe, Kentucky\r\n295\r\nCarlisle, Kentucky\r\n289\r\nCatlettsburg, Kentucky\r\n739\r\nChapman, Kentucky\r\n673\r\nCody, Kentucky\r\n642\r\nCorbin, Kentucky\r\n524\r\n523\r\n528\r\nCornishville, Kentucky\r\n366\r\nCovington, Kentucky\r\n261\r\n291\r\n292\r\n331\r\n341\r\n342\r\n344\r\n431\r\n441\r\n491\r\n572\r\n581\r\n628\r\n727\r\n781\r\n240\r\n250\r\n391\r\n492\r\n655\r\n578\r\n386\r\nCrab Orchard, Kentucky\r\n355\r\nCumberland, Kentucky\r\n589\r\nCynthiana, Kentucky\r\n234\r\nDanville, Kentucky\r\n236\r\n238\r\nDover, Kentucky\r\n882\r\nDwarf, Kentucky\r\n378\r\nEbernstadt, Kentucky\r\n843\r\nElkhorn City, Kentucky\r\n754\r\nEubank, Kentucky\r\n379\r\nEvarts, Kentucky\r\n837\r\nEwing, Kentucky\r\n267\r\nEzel, Kentucky\r\n725\r\nFallsburg, Kentucky\r\n686\r\nFalmouth, Kentucky\r\n654\r\nFaubush, Kentucky\r\n871\r\nFedscreek, Kentucky\r\n835\r\nFernleaf, Kentucky\r\n883\r\nFisty, Kentucky\r\n251\r\nFlat Gap, Kentucky\r\n265\r\nFlat Lick, Kentucky\r\n542\r\nFlemingsburg, Kentucky\r\n845\r\n849\r\nFord, Kentucky\r\n527\r\nFreeburn, Kentucky\r\n456\r\nFrenchburg, Kentucky\r\n768\r\nGarrison, Kentucky\r\n757\r\nGermantown, Kentucky\r\n728\r\nGlencoe, Kentucky\r\n643\r\nGrayson, Kentucky\r\n474\r\nGreenup, Kentucky\r\n473\r\nGrethel, Kentucky\r\n587\r\nHarlan, Kentucky\r\n573\r\nHarold, Kentucky\r\n477\r\n478\r\nHarrodsburg, Kentucky\r\n734\r\nHazard, Kentucky\r\n436\r\n439\r\nHazelgreen, Kentucky\r\n662\r\nHillsboro, Kentucky\r\n876\r\nHindman, Kentucky\r\n438\r\n785\r\nHustonville, Kentucky\r\n346\r\nHyden, Kentucky\r\n672\r\nIndependence, Kentucky\r\n356\r\n359\r\nInez, Kentucky\r\n298\r\nIrvine, Kentucky\r\n723\r\nJackson, Kentucky\r\n666\r\nJellico, Kentucky\r\n786\r\nJenkins, Kentucky\r\n832\r\nJeptha, Kentucky\r\n522\r\nJohnsville, Kentucky\r\n747\r\nJunction City, Kentucky\r\n854\r\nKirksville, Kentucky\r\n328\r\nLancaster, Kentucky\r\n792\r\nLeatherwd, Kentucky\r\n675\r\nLewisburg, Kentucky\r\n742\r\nLexington, Kentucky\r\n221\r\n223\r\n224\r\n229\r\n231\r\n232\r\n233\r\n243\r\n252\r\n253\r\n254\r\n255\r\n257\r\n258\r\n259\r\n263\r\n264\r\n266\r\n268\r\n269\r\n271\r\n272\r\n273\r\n275\r\n276\r\n277\r\n278\r\n280\r\n281\r\n288\r\n293\r\n299\r\n225\r\n226\r\n227\r\n244\r\n321\r\n245\r\n294\r\nLiberty, Kentucky\r\n787\r\nLittle Rock, Kentucky\r\n383\r\nLivingston, Kentucky\r\n453\r\nLondon, Kentucky\r\n875\r\n877\r\n864\r\n878\r\nLouisa, Kentucky\r\n638\r\nMackville, Kentucky\r\n262\r\nManchester, Kentucky\r\n598\r\nMartin, Kentucky\r\n285\r\nMays Lick, Kentucky\r\n763\r\nMaysville, Kentucky\r\n564\r\nMcCarr, Kentucky\r\n427\r\nMcDowell, Kentucky\r\n377\r\nMcKee, Kentucky\r\n287\r\nMeads, Kentucky\r\n922\r\n928\r\nMiddlesbo, Kentucky\r\n242\r\n248\r\nMidway, Kentucky\r\n846\r\nMillerburg, Kentucky\r\n484\r\nMonticello, Kentucky\r\n348\r\nMorehead, Kentucky\r\n782\r\n783\r\n784\r\nMorresville, Kentucky\r\n284\r\nMousie, Kentucky\r\n946\r\nMount Olivet, Kentucky\r\n724\r\nMount Sterlng, Kentucky\r\n497\r\n498\r\nMount Vernon, Kentucky\r\n256\r\nNancy, Kentucky\r\n636\r\nNeon, Kentucky\r\n855\r\nNicholasville, Kentucky\r\n885\r\n887\r\nNorth Middleton, Kentucky\r\n362\r\nOlive Hill, Kentucky\r\n286\r\nOneida, Kentucky\r\n847\r\nOwingsville, Kentucky\r\n674\r\nPaint Lick, Kentucky\r\n925\r\nPaintsville, Kentucky\r\n788\r\n789\r\n793\r\nParis, Kentucky\r\n987\r\nPerryville, Kentucky\r\n332\r\nPikeville, Kentucky\r\n432\r\n433\r\n437\r\n631\r\n434\r\nPine Knot, Kentucky\r\n354\r\nPineville, Kentucky\r\n337\r\nPippa Pass, Kentucky\r\n368\r\nPrestonsburg, Kentucky\r\n886\r\nRichmond, Kentucky\r\n544\r\n625\r\n622\r\n623\r\n624\r\nRoyalton, Kentucky\r\n884\r\nRussell, Kentucky\r\n831\r\n833\r\n836\r\nSalt Lick, Kentucky\r\n683\r\nSalvisa, Kentucky\r\n865\r\nSalyersville, Kentucky\r\n349\r\nSandgap, Kentucky\r\n965\r\nSandy Hook, Kentucky\r\n738\r\nScience Hill, Kentucky\r\n423\r\nSharpsburg, Kentucky\r\n247\r\nShopville, Kentucky\r\n274\r\nSomerset, Kentucky\r\n677\r\n678\r\n679\r\nSouthshore, Kentucky\r\n932\r\nSouth Wiliamson, Kentucky\r\n237\r\nSpringfield, Kentucky\r\n336\r\nStaffordsville, Kentucky\r\n228\r\n297\r\nStanford, Kentucky\r\n365\r\nStanton, Kentucky\r\n663\r\nStinnett, Kentucky\r\n374\r\nStone, Kentucky\r\n353\r\nStrnwhly City, Kentucky\r\n376\r\nTollesboro, Kentucky\r\n798\r\nTopmost, Kentucky\r\n447\r\nVanceburg, Kentucky\r\n796\r\nVersailles, Kentucky\r\n873\r\n879\r\nVicco, Kentucky\r\n476\r\nVirgie, Kentucky\r\n639\r\nWest Liberty, Kentucky\r\n743\r\nWaco, Kentucky\r\n369\r\nWallins Creek, Kentucky\r\n664\r\nWalton, Kentucky\r\n485\r\n493\r\nWarfield, Kentucky\r\n395\r\nWarsaw, Kentucky\r\n567\r\nWashington, Kentucky\r\n759\r\nWayland, Kentucky\r\n358\r\nWheelwrght, Kentucky\r\n452\r\nWhite Lily, Kentucky\r\n382\r\nWhitesburg, Kentucky\r\n633\r\nWilliamsburg, Kentucky\r\n549\r\nWilliamston, Kentucky\r\n428\r\n823\r\n824\r\nWillisburg, Kentucky\r\n375\r\nWilmore, Kentucky\r\n858\r\nWinchester, Kentucky\r\n744\r\n745\r\n842\r\nWooton, Kentucky\r\n279\r\n\u00035Unknown prefix code (606) - Kentucky\r\n"
  },
  {
    "path": "install/regions/regions.607",
    "content": "Addison, New York\r\n359\r\nAfton, New York\r\n639\r\nAlfred, New York\r\n587\r\n871\r\nAlmond, New York\r\n276\r\nAndover, New York\r\n478\r\nApalachin, New York\r\n625\r\nArkport, New York\r\n295\r\nAvoca, New York\r\n566\r\nBainbridge, New York\r\n967\r\nBath, New York\r\n776\r\nBerkshire, New York\r\n657\r\nBig Flats, New York\r\n562\r\nBinghamton, New York\r\n540\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n727\r\n729\r\n762\r\n763\r\n770\r\n771\r\n772\r\n773\r\n774\r\n775\r\n777\r\n778\r\n779\r\n780\r\n797\r\n798\r\n890\r\n920\r\n977\r\nBurdett, New York\r\n546\r\nCameron, New York\r\n695\r\nCampbell, New York\r\n527\r\nCanaseraga, New York\r\n545\r\nCandor, New York\r\n659\r\nCanisteo, New York\r\n698\r\nCaton, New York\r\n524\r\nChemung, New York\r\n529\r\nChenangbdg, New York\r\n648\r\nCherry Vallley, New York\r\n264\r\nCincinnats, New York\r\n863\r\nCooperstown, New York\r\n547\r\nCorning, New York\r\n936\r\n937\r\n962\r\n974\r\nCortland, New York\r\n745\r\n758\r\n749\r\n753\r\n756\r\nDavenport, New York\r\n278\r\nDelhi, New York\r\n746\r\n832\r\nDeposit, New York\r\n467\r\nDownsville, New York\r\n363\r\nDryden, New York\r\n844\r\nDundee, New York\r\n243\r\nEdmeston, New York\r\n965\r\nElmira, New York\r\n735\r\n795\r\n731\r\n732\r\n733\r\n734\r\n737\r\n738\r\n739\r\n796\r\nEndicott, New York\r\n741\r\n748\r\n752\r\n754\r\n755\r\n757\r\n785\r\n786\r\nEtna, New York\r\n347\r\nFranklin, New York\r\n829\r\nGilbertsville, New York\r\n783\r\nGrand Gorge, New York\r\n588\r\nGreene, New York\r\n656\r\nGreenwood, New York\r\n225\r\nGroton, New York\r\n898\r\nGuilford, New York\r\n895\r\nHammonds Point, New York\r\n569\r\nHancock, New York\r\n637\r\nHarpursville, New York\r\n693\r\nHartwick, New York\r\n293\r\nHawleyton, New York\r\n669\r\nHobart, New York\r\n538\r\nHornell, New York\r\n324\r\nInterlaken, New York\r\n532\r\nIthaca, New York\r\n266\r\n275\r\n279\r\n253\r\n254\r\n255\r\n256\r\n257\r\n272\r\n273\r\n274\r\n277\r\nJasper, New York\r\n792\r\nLansing, New York\r\n533\r\nLindley, New York\r\n523\r\nLockwood, New York\r\n598\r\nLodi, New York\r\n582\r\nMaine, New York\r\n862\r\nMarathon, New York\r\n849\r\nMasonville, New York\r\n265\r\nMcDonough, New York\r\n647\r\nMcGraw, New York\r\n836\r\nMcLean, New York\r\n838\r\nMilford, New York\r\n286\r\nMorris, New York\r\n263\r\nMount Upton, New York\r\n764\r\nNew Berlin, New York\r\n847\r\nNewark Valley, New York\r\n642\r\nNewfield, New York\r\n564\r\nNichols, New York\r\n699\r\nNorwich, New York\r\n337\r\n334\r\n335\r\n336\r\nOdessa, New York\r\n594\r\nOneonta, New York\r\n434\r\n435\r\n436\r\n431\r\n432\r\n433\r\nOtego, New York\r\n988\r\nOvid, New York\r\n869\r\nOwego, New York\r\n687\r\n751\r\nOxford, New York\r\n843\r\nPrattsburg, New York\r\n522\r\nPulteney, New York\r\n868\r\nRoscoe, New York\r\n498\r\nRoxbury, New York\r\n326\r\nSavona, New York\r\n583\r\nSchenevus, New York\r\n638\r\nSherburne, New York\r\n674\r\nSidney, New York\r\n561\r\n563\r\nSltrville Springs, New York\r\n539\r\nSmyrna, New York\r\n627\r\nSouth New Berlin, New York\r\n859\r\nSpencer, New York\r\n589\r\nStamford, New York\r\n652\r\nTroupsburg, New York\r\n525\r\nTrumansburg, New York\r\n387\r\nTruxton, New York\r\n842\r\nUnadilla, New York\r\n369\r\nVirgil, New York\r\n835\r\nWalton, New York\r\n865\r\nWatkinsgln, New York\r\n535\r\nWaverly, New York\r\n565\r\nWayne, New York\r\n292\r\nWhitesville, New York\r\n356\r\nWhitney Point, New York\r\n692\r\nWindsor, New York\r\n655\r\nWoodhull, New York\r\n458\r\nWorcester, New York\r\n397\r\n\u00035Unknown prefix code (607) - New York\r\n"
  },
  {
    "path": "install/regions/regions.608",
    "content": "Adams, Wisconsin\r\n339\r\nAlbany, Wisconsin\r\n862\r\nAlma, Wisconsin\r\n685\r\nArcadia, Wisconsin\r\n323\r\nArena, Wisconsin\r\n753\r\nArgyle, Wisconsin\r\n543\r\nAvoca, Wisconsin\r\n532\r\nBagley, Wisconsin\r\n996\r\nBangor, Wisconsin\r\n486\r\nBaraboo, Wisconsin\r\n355\r\n356\r\nBeetown, Wisconsin\r\n794\r\nBelleville, Wisconsin\r\n424\r\nBelmont, Wisconsin\r\n762\r\nBeloit, Wisconsin\r\n363\r\n362\r\n364\r\n365\r\nBenton, Wisconsin\r\n759\r\nBlackearth, Wisconsin\r\n767\r\nBlair, Wisconsin\r\n989\r\nBlanchardville, Wisconsin\r\n523\r\nBloom City, Wisconsin\r\n549\r\nBloomington, Wisconsin\r\n994\r\nBlue River, Wisconsin\r\n537\r\nBoaz, Wisconsin\r\n536\r\nBoscobel, Wisconsin\r\n375\r\nBriggsville, Wisconsin\r\n981\r\nBrodhead, Wisconsin\r\n897\r\nBrooklyn, Wisconsin\r\n455\r\nBrooks, Wisconsin\r\n584\r\nBrowntown, Wisconsin\r\n966\r\nCambridge, Wisconsin\r\n423\r\nCamp Douglas, Wisconsin\r\n427\r\nCashton, Wisconsin\r\n654\r\nCassville, Wisconsin\r\n725\r\nCataract, Wisconsin\r\n272\r\nCazenovia, Wisconsin\r\n983\r\nCenterville, Wisconsin\r\n539\r\nChaseburg, Wisconsin\r\n483\r\nClinton, Wisconsin\r\n676\r\nCobb, Wisconsin\r\n623\r\nCochrane, Wisconsin\r\n248\r\nCoon Valley, Wisconsin\r\n452\r\nCottage Grove, Wisconsin\r\n839\r\nCross Pls, Wisconsin\r\n798\r\nCuba City, Wisconsin\r\n744\r\nDarlington, Wisconsin\r\n776\r\nDe Forest, Wisconsin\r\n846\r\nDe Soto, Wisconsin\r\n648\r\nDeerfield, Wisconsin\r\n764\r\nDickeyville, Wisconsin\r\n568\r\nDodgeville, Wisconsin\r\n553\r\n574\r\n935\r\nEastman, Wisconsin\r\n874\r\nEdgerton, Wisconsin\r\n884\r\nElroy, Wisconsin\r\n462\r\nEndeavor, Wisconsin\r\n587\r\nEttrick, Wisconsin\r\n525\r\nEvansville, Wisconsin\r\n882\r\nFairplay, Wisconsin\r\n748\r\nFennimore, Wisconsin\r\n822\r\nFootville, Wisconsin\r\n876\r\nFort McCoy, Wisconsin\r\n388\r\nFountain City, Wisconsin\r\n687\r\nGalesville, Wisconsin\r\n582\r\nGays Mills, Wisconsin\r\n735\r\nGenoa, Wisconsin\r\n689\r\nGratiot, Wisconsin\r\n922\r\nHazel Green, Wisconsin\r\n854\r\nHighland, Wisconsin\r\n929\r\nHillsboro, Wisconsin\r\n489\r\nHollandale, Wisconsin\r\n967\r\nHolmen, Wisconsin\r\n526\r\nIthaca, Wisconsin\r\n585\r\nJanesville, Wisconsin\r\n751\r\n752\r\n754\r\n755\r\n756\r\n757\r\n758\r\n774\r\nJuda, Wisconsin\r\n934\r\nKendall, Wisconsin\r\n463\r\nLa Crosse, Wisconsin\r\n793\r\n796\r\n797\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n787\r\n788\r\n789\r\n791\r\n792\r\nLa Farge, Wisconsin\r\n625\r\nLa Valle, Wisconsin\r\n985\r\nLancaster, Wisconsin\r\n723\r\nLiberty Pole, Wisconsin\r\n675\r\nLime Ridge, Wisconsin\r\n986\r\nLodi, Wisconsin\r\n592\r\nLoganville, Wisconsin\r\n727\r\nLone Rock, Wisconsin\r\n583\r\nLyndon Station, Wisconsin\r\n666\r\nMadison, Wisconsin\r\n232\r\n243\r\n261\r\n265\r\n284\r\n376\r\n393\r\n398\r\n444\r\n559\r\n578\r\n657\r\n692\r\n893\r\n963\r\n221\r\n222\r\n223\r\n231\r\n233\r\n238\r\n241\r\n242\r\n244\r\n246\r\n249\r\n251\r\n252\r\n255\r\n256\r\n257\r\n258\r\n259\r\n262\r\n263\r\n264\r\n266\r\n267\r\n271\r\n273\r\n274\r\n275\r\n276\r\n277\r\n281\r\n282\r\n283\r\n556\r\n575\r\n695\r\n936\r\n957\r\nMarshall, Wisconsin\r\n655\r\nMauston, Wisconsin\r\n547\r\n572\r\n847\r\nMazomanie, Wisconsin\r\n795\r\nMcFarland, Wisconsin\r\n838\r\nMelrose, Wisconsin\r\n488\r\nMerrimac, Wisconsin\r\n493\r\nMiddleton, Wisconsin\r\n828\r\n829\r\n831\r\n833\r\n836\r\nMilton, Wisconsin\r\n868\r\nMindoro, Wisconsin\r\n857\r\nMineral Point, Wisconsin\r\n987\r\nMonroe Center, Wisconsin\r\n564\r\nMonroe, Wisconsin\r\n293\r\n558\r\n324\r\n325\r\n328\r\n329\r\nMontello, Wisconsin\r\n297\r\nMontfort, Wisconsin\r\n943\r\nMonticello, Wisconsin\r\n938\r\nMount Hope, Wisconsin\r\n988\r\nMount Vernon, Wisconsin\r\n832\r\nMount Zion, Wisconsin\r\n872\r\nMount Horeb, Wisconsin\r\n437\r\nMuscoda, Wisconsin\r\n739\r\nNecedah, Wisconsin\r\n565\r\nNew Glarus, Wisconsin\r\n527\r\nNew Lisbon, Wisconsin\r\n562\r\nNorth Apple River, Wisconsin\r\n596\r\nNorth Freedom, Wisconsin\r\n381\r\n522\r\nNorth Warren, Wisconsin\r\n677\r\nNorth Winslow, Wisconsin\r\n867\r\nNorwalk, Wisconsin\r\n823\r\nOntario, Wisconsin\r\n337\r\nOregon, Wisconsin\r\n835\r\nOrfordville, Wisconsin\r\n879\r\nOxford, Wisconsin\r\n586\r\nPackwaukee, Wisconsin\r\n589\r\nPardeeville, Wisconsin\r\n429\r\nPlain, Wisconsin\r\n546\r\nPlatteville, Wisconsin\r\n342\r\n348\r\n349\r\n642\r\n778\r\nPortage, Wisconsin\r\n697\r\n742\r\nPotosi, Wisconsin\r\n763\r\nPoynette, Wisconsin\r\n635\r\nPrarduchen, Wisconsin\r\n326\r\nReadstown, Wisconsin\r\n629\r\nReedsburg, Wisconsin\r\n524\r\nRichld Center, Wisconsin\r\n647\r\nRichmond, Wisconsin\r\n883\r\nRidgeway, Wisconsin\r\n924\r\nSabin, Wisconsin\r\n538\r\nSauk City, Wisconsin\r\n643\r\nSeneca, Wisconsin\r\n734\r\nShullsburg, Wisconsin\r\n965\r\nSoldier Grove, Wisconsin\r\n624\r\nSouthwayne, Wisconsin\r\n439\r\nSparta, Wisconsin\r\n269\r\nSpring Green, Wisconsin\r\n588\r\nSteuben, Wisconsin\r\n476\r\nStoddard, Wisconsin\r\n457\r\nStoughton, Wisconsin\r\n877\r\n873\r\nSunprairie, Wisconsin\r\n825\r\n837\r\nTomah, Wisconsin\r\n343\r\n374\r\n372\r\nTrempealau, Wisconsin\r\n534\r\nVerona, Wisconsin\r\n845\r\nViola, Wisconsin\r\n627\r\nViroqua, Wisconsin\r\n637\r\nWarrens, Wisconsin\r\n378\r\nWaumandee, Wisconsin\r\n626\r\nWaunakee, Wisconsin\r\n849\r\nWauzeka, Wisconsin\r\n875\r\nWestby, Wisconsin\r\n634\r\nWestfield, Wisconsin\r\n296\r\nWestsalem, Wisconsin\r\n786\r\nWilton, Wisconsin\r\n435\r\nWiota, Wisconsin\r\n968\r\nWisconsin dls, Wisconsin\r\n253\r\n254\r\nWitwen, Wisconsin\r\n544\r\nWonewoc, Wisconsin\r\n464\r\nWoodford, Wisconsin\r\n465\r\nWoodman, Wisconsin\r\n533\r\nYuba, Wisconsin\r\n528\r\n\u00035Unknown prefix code (608) - Wisconsin\r\n"
  },
  {
    "path": "install/regions/regions.609",
    "content": "Allentown, New Jersey\r\n259\r\n529\r\nAtlantic City, New Jersey\r\n226\r\n340\r\n343\r\n344\r\n345\r\n347\r\n348\r\n441\r\n442\r\n449\r\n487\r\n822\r\n823\r\n236\r\n300\r\n335\r\n400\r\n572\r\n576\r\nAvalon, New Jersey\r\n368\r\n967\r\nBarnegat, New Jersey\r\n660\r\n597\r\n693\r\n698\r\n971\r\n978\r\nBeachhaven, New Jersey\r\n361\r\n492\r\n494\r\nBeaver Brook, New Jersey\r\n931\r\n933\r\n939\r\nBerlin, New Jersey\r\n753\r\n767\r\n768\r\nBlackwood, New Jersey\r\n374\r\n227\r\n228\r\n232\r\nBordentown, New Jersey\r\n291\r\n298\r\nBridgeton, New Jersey\r\n451\r\n453\r\n455\r\n774\r\nBrigantine, New Jersey\r\n264\r\n266\r\nBurlington, New Jersey\r\n239\r\n386\r\n387\r\n835\r\n871\r\n877\r\nCamden, New Jersey\r\n225\r\n233\r\n337\r\n564\r\n580\r\n725\r\n738\r\n790\r\n968\r\n969\r\n338\r\n342\r\n365\r\n541\r\n590\r\n756\r\n757\r\n962\r\n963\r\n964\r\n966\r\nCape May Court House, New Jersey\r\n463\r\n465\r\nCedarville, New Jersey\r\n447\r\nCollingswood, Nj\r\n854\r\n858\r\n869\r\nCranbury, New Jersey\r\n860\r\n395\r\n655\r\nDennisville, New Jersey\r\n861\r\nEast Windsor, New Jersey\r\n443\r\nEgg Harbor, New Jersey\r\n965\r\nElmer, New Jersey\r\n358\r\nEwing, New Jersey\r\n538\r\n771\r\n882\r\n883\r\nFlorence, New Jersey\r\n499\r\nFort Dix, New Jersey\r\n562\r\n723\r\n724\r\nFranklinville, New Jersey\r\n694\r\nGlassboro, New Jersey\r\n863\r\n881\r\nGloucester, New Jersey\r\n456\r\n742\r\nHaddon Heights, New Jersey\r\n471\r\n546\r\n547\r\n573\r\n922\r\n472\r\nHaddonfield, New Jersey\r\n330\r\n354\r\n424\r\n427\r\n428\r\n429\r\n751\r\n770\r\n772\r\n795\r\n870\r\n220\r\n230\r\n440\r\n489\r\n560\r\n843\r\nHammonton, New Jersey\r\n561\r\n567\r\nHightstown, New Jersey\r\n426\r\n448\r\n490\r\nHopewell, New Jersey\r\n466\r\n639\r\nLambertville, New Jersey\r\n397\r\n885\r\nLaurel Springs, New Jersey\r\n566\r\n346\r\n435\r\n627\r\n782\r\n783\r\n784\r\nLawrenceville, New Jersey\r\n530\r\n895\r\n896\r\n647\r\n844\r\nMarlton, New Jersey\r\n988\r\n596\r\n983\r\n985\r\nMays Lodge, New Jersey\r\n625\r\nMedford, New Jersey\r\n654\r\n953\r\nMercerville, New Jersey\r\n581\r\n584\r\n585\r\n586\r\n587\r\n588\r\n890\r\n229\r\n631\r\nMerchantville, New Jersey\r\n482\r\n486\r\n488\r\n662\r\n663\r\n665\r\n667\r\n779\r\n321\r\n661\r\nMillville, New Jersey\r\n247\r\n293\r\n327\r\n825\r\nMilmay, New Jersey\r\n476\r\nMoorestown, New Jersey\r\n231\r\n234\r\n235\r\n273\r\n439\r\n687\r\n722\r\n727\r\n755\r\n778\r\n866\r\n923\r\nMorrestown, New Jersey\r\n840\r\nMount Holly, New Jersey\r\n261\r\n265\r\n267\r\nMullica Hill, New Jersey\r\n223\r\n478\r\nNew Egypt, New Jersey\r\n758\r\nOcean City, New Jersey\r\n390\r\n391\r\n398\r\n399\r\nPaulsboro, New Jersey\r\n224\r\n423\r\nPemberton, New Jersey\r\n735\r\n726\r\n893\r\n894\r\nPennington, New Jersey\r\n730\r\n737\r\nPennsgrove, New Jersey\r\n299\r\n351\r\n540\r\n678\r\nPitman, New Jersey\r\n256\r\n582\r\n589\r\nPlainsboro, New Jersey\r\n275\r\n799\r\n897\r\n936\r\nPleasantville, New Jersey\r\n272\r\n370\r\n383\r\n484\r\n641\r\n645\r\n646\r\n652\r\n748\r\n485\r\n679\r\nPort Norris, New Jersey\r\n785\r\nPrinceton, New Jersey\r\n252\r\n279\r\n951\r\n243\r\n258\r\n282\r\n452\r\n497\r\n520\r\n683\r\n734\r\n921\r\n924\r\n987\r\nRiverside, New Jersey\r\n461\r\n764\r\nRiverton, New Jersey\r\n786\r\n829\r\nSalem, New Jersey\r\n339\r\n420\r\n935\r\nSea Isle, New Jersey\r\n263\r\n624\r\nSomers Point, New Jersey\r\n653\r\n926\r\n927\r\nSwedesboro, New Jersey\r\n467\r\nTrenton, New Jersey\r\n278\r\n731\r\n826\r\n292\r\n392\r\n393\r\n394\r\n396\r\n421\r\n575\r\n599\r\n633\r\n658\r\n695\r\n777\r\n888\r\n984\r\n989\r\nTuckahoe, New Jersey\r\n628\r\nTuckerton, New Jersey\r\n290\r\n294\r\n296\r\nVincentown, New Jersey\r\n268\r\n859\r\nVineland, New Jersey\r\n563\r\n691\r\n692\r\n696\r\n697\r\n794\r\nWenonah, New Jersey\r\n464\r\n468\r\nWildwood, New Jersey\r\n425\r\n522\r\n523\r\n729\r\n884\r\n886\r\n889\r\n898\r\nWilliamston, New Jersey\r\n629\r\n728\r\n875\r\nWoodbury, New Jersey\r\n384\r\n845\r\n848\r\n853\r\nWoodstown, New Jersey\r\n769\r\n\u00035Unknown prefix code (609) - New Jersey\r\n"
  },
  {
    "path": "install/regions/regions.610",
    "content": "Allentown, Pennsylvania\r\n366\r\n390\r\n391\r\n392\r\n395\r\n398\r\n402\r\n432\r\n433\r\n434\r\n435\r\n437\r\n439\r\n481\r\n606\r\n703\r\n712\r\n720\r\n740\r\n770\r\n774\r\n776\r\n778\r\n791\r\n797\r\n798\r\n820\r\n821\r\nArdmore, Pennsylvania\r\n642\r\n645\r\n649\r\n658\r\n896\r\nAtglen, Pennsylvania\r\n593\r\nAvondale, Pennsylvania\r\n268\r\nBala-Cynwyd, Pennsylvania\r\n617\r\n660\r\n664\r\n667\r\n668\r\nBally, Pennsylvania\r\n845\r\nBangor, Pennsylvania\r\n588\r\n599\r\nBath, Pennsylvania\r\n837\r\nBelvidere, Pennsylvania\r\n498\r\nBernville, Pennsylvania\r\n488\r\nBethlehem, Pennsylvania\r\n216\r\n360\r\n691\r\n694\r\n730\r\n758\r\n814\r\n861\r\n865\r\n866\r\n867\r\n868\r\n882\r\n954\r\n974\r\nBirdsboro, Pennsylvania\r\n404\r\n582\r\n858\r\nBowmanstown, Pennsylvania\r\n852\r\nBoyertown, Pennsylvania\r\n367\r\n369\r\nBryn Mawr, Pennsylvania\r\n519\r\n520\r\n525\r\n526\r\n527\r\nCatasauaqa, Pennsylvania\r\n231\r\n264\r\n266\r\nCenter Point, Pennsylvania\r\n584\r\nCheltenham Township, Pennsylvania\r\n635\r\nChester, Pennsylvania\r\n447\r\n490\r\n494\r\n497\r\n499\r\n872\r\n874\r\n876\r\nChester Heights, Pennsylvania\r\n358\r\n459\r\n558\r\nChester Springs, Pennsylvania\r\n827\r\nCoatesville, Pennsylvania\r\n380\r\n383\r\n384\r\nCollegeville, Pennsylvania\r\n454\r\n489\r\nConshohocken, Pennsylvania\r\n303\r\n305\r\n307\r\n309\r\n315\r\n397\r\n825\r\n828\r\n832\r\n834\r\n907\r\n940\r\n941\r\nCoopersburg, Pennsylvania\r\n282\r\nDouglassville, Pennsylvania\r\n385\r\nDowningtown, Pennsylvania\r\n269\r\n873\r\nDrexel Hill, Pennsylvania\r\n259\r\nEagle, Pennsylvania\r\n458\r\n250\r\n252\r\n253\r\n258\r\n515\r\n559\r\nEmmaus, Pennsylvania\r\n965\r\n967\r\nExton, Pennsylvania\r\n363\r\n524\r\n594\r\nFerndale, Pennsylvvania\r\n847\r\nFleetwood, Pennsylvania\r\n944\r\nGlenmoore, Pennsylvania\r\n942\r\nGlenolden, Pennsylvania\r\n237\r\n461\r\n522\r\nGreen Hills, Pennsylvania\r\n856\r\nHamburg, Pennsylvania\r\n562\r\nHavertown, Pennsylvania\r\n446\r\n449\r\n789\r\n853\r\nHellertown, Pennsylvania\r\n838\r\nHoney Brook, Pennsylvania\r\n273\r\nIronton, Pennsylvania\r\n799\r\nKemblesville, Pennsylvania\r\n255\r\nKempton, Pennsylvania\r\n756\r\nKennett Square, Pennsylvania\r\n444\r\nKing of Prussia, Pennsylvania\r\n220\r\n265\r\n337\r\n354\r\n531\r\n715\r\n768\r\n962\r\n992\r\nKresgeville, Pennsylvania\r\n681\r\nKuhnsville, Pennsylvania\r\n706\r\nKunkletown, Pennsylvania\r\n381\r\nKutztown, Pennsylvania\r\n683\r\nLandenberg, Pennsylvania\r\n274\r\nLansdowne, Pennsylvania\r\n284\r\n394\r\n622\r\n623\r\n626\r\nLeesport, Pennsylvania\r\n916\r\n926\r\nLehighton, Pennsylvania\r\n377\r\nLenape, Pennsylvania\r\n793\r\nLinfield, Pennsylvania\r\n495\r\nMarcus Hook, Pennsylvania\r\n485\r\n859\r\nMedia, Pennsylvania\r\n565\r\n566\r\n891\r\n892\r\nMendenhall, Pennsylvania\r\n388\r\nMorgantown, Pennsylvania\r\n286\r\nMortonville, Pennsylvania\r\n486\r\nMacungie, Pennsylvania\r\n966\r\nNazareth, Pennsylvania\r\n746\r\n759\r\nNew Smithville, Pennsylvania\r\n285\r\nNew Tripoli, Pennsylvania\r\n298\r\nNewtown Square, Pennsylvania\r\n325\r\n353\r\n356\r\n359\r\nNorristown, Pennsylvania\r\n239\r\n270\r\n272\r\n275\r\n277\r\n278\r\n279\r\n292\r\n539\r\n630\r\n631\r\nNorthampton, Pennsylvania\r\n261\r\n262\r\nOley, Pennsylvania\r\n987\r\nOxford, Pennsylvania\r\n932\r\nPalmerton, Pennsylvania\r\n826\r\nPaoli, Pennsylvania\r\n219\r\n251\r\n296\r\n408\r\n640\r\n644\r\n647\r\n648\r\n651\r\n669\r\n695\r\n889\r\n993\r\nParkesburg, Pennsylvania\r\n857\r\nPenn Argyle, Pennsylvania\r\n863\r\nPhiladelphia, Pennsylvania\r\n556\r\n846\r\n936\r\n976\r\nPhoenixville, Pennsylvania\r\n917\r\n933\r\n935\r\n983\r\nPottstown, Pennsylvania\r\n323\r\n326\r\n327\r\n718\r\n970\r\nPughtown, Pennsylvania\r\n469\r\nReading, Pennsylvania\r\n207\r\n208\r\n320\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n378\r\n478\r\n655\r\n670\r\n678\r\n779\r\n780\r\n796\r\n921\r\n929\r\n939\r\nRidley Park, Pennsylvania\r\n521\r\n532\r\n534\r\n591\r\n595\r\nRiegelsville, Pennsylvania\r\n749\r\nRobesonia, Pennsylvania\r\n693\r\nRoyersford, Pennsylvania\r\n792\r\n948\r\nSassamansville, Pennsylvania\r\n754\r\nSchwenksville, Pennsylvania\r\n287\r\nSharon Hill, Pennsylvania\r\n583\r\n586\r\nShillington, Pennsylvania\r\n775\r\n777\r\n796\r\nSlatington, Pennsylvania\r\n760\r\n767\r\nSpringtown, Pennsylvania\r\n346\r\nSwarthmore, Pennsylvania\r\n328\r\n543\r\n544\r\n690\r\nTopton, Pennsylvania\r\n682\r\nTrooper, Pennsylvania\r\n316\r\n405\r\n733\r\n883\r\n996\r\nUhlerstown, Pennsylvania\r\n294\r\nUnionville, Pennsylvania\r\n347\r\nUpper Black Eddy, Pennsylvania\r\n982\r\nUpper Darby, Pennsylvania\r\n352\r\n734\r\nValley Forge, Pennsylvania\r\n650\r\n666\r\n783\r\nWayne, Pennsylvania\r\n254\r\n293\r\n341\r\n687\r\n688\r\n902\r\n964\r\n971\r\n975\r\n989\r\n995\r\nWest Chester, Pennsylvania\r\n344\r\n429\r\n430\r\n431\r\n436\r\n692\r\n696\r\n701\r\nWest Grove, Pennsylvania\r\n869\r\nWesttown, Pennsylvania\r\n399\r\nWomelsdorf, Pennsylvania\r\n589\r\nWoodlyn, Pennsylvania\r\n833\r\nYellow House\u00031/\u00032Earlville, Pennsylvania\r\n689\r\n\u00035Unknown prefix code (610) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/regions.611",
    "content": "Kadena Air Base, Okinawa, Japan\r\n633\r\n733\r\n734\r\n745\r\n976\r\nCamp Shields, Okinawa, Japan\r\n732\r\nCamp Kinser, Okinawa, Japan\r\n637\r\n737\r\nCamp Lester, Okinawa, Japan\r\n731\r\nCamp Foster\u00031/\u00032Butler, Okinawa, Japan\r\n645\r\n735\r\nCamp Courtney, Okinawa, Japan\r\n723\r\nCamp Schwab, Okinawa, Japan\r\n736\r\nCamp McTureous, Okinawa, Japan\r\n722\r\nCamp Hansen, Okinawa, Japan\r\n623\r\n723\r\nMisawa AB, Mainland Japan\r\n762\r\n\u00035Unknown prefix code (611) - Okinawa, Japan\r\n"
  },
  {
    "path": "install/regions/regions.612",
    "content": "Brooklyn Park, Minnesota\r\n504\r\nMinneapolis, Minnesota\r\n362\r\n397\r\n399\r\n530\r\n580\r\n581\r\n590\r\n661\r\n671\r\n672\r\n751\r\n759\r\n790\r\n794\r\n798\r\n821\r\n889\r\n899\r\n928\r\n951\r\n973\r\n767\r\n783\r\n957\r\n670\r\n680\r\n820\r\n840\r\n844\r\n882\r\n883\r\n940\r\n948\r\n956\r\n930\r\n945\r\n946\r\n947\r\n230\r\n525\r\n531\r\n549\r\n550\r\n551\r\n585\r\n586\r\n595\r\n799\r\n954\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n340\r\n341\r\n342\r\n343\r\n344\r\n347\r\n348\r\n349\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n499\r\n520\r\n521\r\n522\r\n526\r\n527\r\n529\r\n533\r\n534\r\n535\r\n536\r\n537\r\n538\r\n540\r\n541\r\n542\r\n544\r\n545\r\n546\r\n553\r\n557\r\n559\r\n560\r\n561\r\n566\r\n569\r\n571\r\n572\r\n574\r\n588\r\n591\r\n593\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n639\r\n663\r\n667\r\n673\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\n741\r\n750\r\n754\r\n755\r\n757\r\n780\r\n781\r\n782\r\n784\r\n785\r\n786\r\n788\r\n789\r\n822\r\n823\r\n824\r\n825\r\n827\r\n828\r\n829\r\n830\r\n831\r\n832\r\n835\r\n851\r\n853\r\n854\r\n858\r\n860\r\n861\r\n863\r\n865\r\n866\r\n867\r\n868\r\n869\r\n870\r\n871\r\n872\r\n874\r\n879\r\n881\r\n884\r\n885\r\n887\r\n888\r\n890\r\n893\r\n894\r\n895\r\n896\r\n897\r\n920\r\n921\r\n922\r\n924\r\n925\r\n926\r\n927\r\n929\r\n931\r\n932\r\n933\r\n934\r\n936\r\n937\r\n938\r\n939\r\n941\r\n942\r\n943\r\n944\r\n949\r\n977\r\nSaint Paul, Minnesota\r\n220\r\n221\r\n222\r\n223\r\n224\r\n227\r\n228\r\n229\r\n290\r\n291\r\n292\r\n293\r\n296\r\n297\r\n298\r\n450\r\n451\r\n452\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n481\r\n482\r\n483\r\n484\r\n487\r\n488\r\n489\r\n490\r\n552\r\n620\r\n631\r\n633\r\n635\r\n636\r\n638\r\n640\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n648\r\n649\r\n681\r\n683\r\n687\r\n688\r\n690\r\n696\r\n698\r\n699\r\n730\r\n731\r\n733\r\n735\r\n736\r\n737\r\n738\r\n739\r\n770\r\n771\r\n772\r\n774\r\n776\r\n777\r\n778\r\n779\r\n989\r\nAlbany, Minnesota\r\n845\r\nAlexandria, Minnesota\r\n760\r\n762\r\n763\r\n766\r\n846\r\nAlmelund, Minnesota\r\n583\r\nAnnandale, Minnesota\r\n274\r\nAnoka, Minnesota\r\n323\r\n421\r\n422\r\n427\r\n753\r\nApple Valley, Minnesota\r\n431\r\n432\r\n891\r\n953\r\nAppleton, Minnesota\r\n289\r\nArlington, Minnesota\r\n964\r\nAskov, Minnesota\r\n838\r\nAtwater, Minnesota\r\n979\r\n974\r\nAvon, Minnesota\r\n356\r\nBarrett, Minnesota\r\n528\r\nBeardsley, Minnesota\r\n265\r\nBecker, Minnesota\r\n261\r\nBelgrade, Minnesota\r\n254\r\nBelleplain, Minnesota\r\n873\r\nBellingham, Minnesota\r\n568\r\nBenson, Minnesota\r\n842\r\n843\r\nBig Bend, Minnesota\r\n793\r\nBig Lake, Minnesota\r\n262\r\n263\r\nBird Island, Minnesota\r\n365\r\nBock, Minnesota\r\n556\r\nBoyd, Minnesota\r\n855\r\nBraham, Minnesota\r\n396\r\nBrandon, Minnesota\r\n524\r\nBrooten, Minnesota\r\n346\r\nBrowerville, Minnesota\r\n594\r\nBrowns Valley, Minnesota\r\n695\r\nBrownton, Minnesota\r\n328\r\nBuffalo Lake, Minnesota\r\n833\r\nBuffalo, Minnesota\r\n682\r\nBurnsville, Minnesota\r\n898\r\nCambridge, Minnesota\r\n689\r\nCarlos, Minnesota\r\n852\r\nCerrogordo, Minnesota\r\n752\r\nChaska, Minnesota\r\n368\r\n448\r\nChokio, Minnesota\r\n324\r\nClara City, Minnesota\r\n847\r\nClarkfield, Minnesota\r\n669\r\nClear Lake, Minnesota\r\n743\r\nClearwater, Minnesota\r\n558\r\nClinton, Minnesota\r\n325\r\nCloverton, Minnesota\r\n242\r\nCokato, Minnesota\r\n286\r\nColdspring, Minnesota\r\n685\r\nCologne, Minnesota\r\n466\r\nCorrell, Minnesota\r\n596\r\nCosmos, Minnesota\r\n877\r\nCyrus, Minnesota\r\n795\r\nDanube, Minnesota\r\n826\r\nDanvers, Minnesota\r\n567\r\nDassel, Minnesota\r\n275\r\nDawson, Minnesota\r\n769\r\nDelano, Minnesota\r\n972\r\nDonnelly, Minnesota\r\n246\r\nEden Valley, Minnesota\r\n453\r\nEdina\u00031/\u00032Minnetonka\u00031/\u00032Hopkins, Minnesota\r\n988\r\nElk River, Minnesota\r\n241\r\n441\r\nElrosa, Minnesota\r\n697\r\nEnfield, Minnesota\r\n878\r\nFarmington, Minnesota\r\n460\r\n463\r\nFinlayson, Minnesota\r\n233\r\nFoley, Minnesota\r\n968\r\nForest Lake, Minnesota\r\n464\r\nForeston, Minnesota\r\n294\r\nFreedhem, Minnesota\r\n745\r\nFreeport, Minnesota\r\n836\r\nGarfield, Minnesota\r\n834\r\nGarrison, Minnesota\r\n692\r\nGaylord, Minnesota\r\n237\r\nGilman, Minnesota\r\n387\r\nGlencoe, Minnesota\r\n864\r\nGlendorado, Minnesota\r\n662\r\nGlenwood, Minnesota\r\n634\r\nGoodhue, Minnesota\r\n923\r\nGraceville, Minnesota\r\n748\r\nGranite Falls, Minnesota\r\n564\r\nGreen Isle, Minnesota\r\n326\r\nGreenwald, Minnesota\r\n987\r\nGrey Eagle, Minnesota\r\n285\r\nGrove City, Minnesota\r\n857\r\nHamel, Minnesota\r\n478\r\nHancock, Minnesota\r\n392\r\nHanover, Minnesota\r\n498\r\nHastings, Minnesota\r\n480\r\n437\r\n438\r\nHazel Run, Minnesota\r\n383\r\nHector, Minnesota\r\n848\r\nHenderson, Minnesota\r\n248\r\nHerman, Minnesota\r\n677\r\nHinckley, Minnesota\r\n279\r\n390\r\n384\r\nHoffman, Minnesota\r\n986\r\nHoldingfield, Minnesota\r\n746\r\nHolloway, Minnesota\r\n394\r\nHolmes City, Minnesota\r\n886\r\nHopkins, Minnesota\r\n935\r\nHoward Lake, Minnesota\r\n543\r\nHutchinson, Minnesota\r\n234\r\n587\r\nIrving, Minnesota\r\n276\r\nIsanti, Minnesota\r\n444\r\nIsle, Minnesota\r\n676\r\nJordan, Minnesota\r\n492\r\nKandiyohi, Minnesota\r\n382\r\nKensington, Minnesota\r\n965\r\nKerkhoven, Minnesota\r\n264\r\nKimball, Minnesota\r\n398\r\nLake City, Minnesota\r\n345\r\nLake Lillian, Minnesota\r\n664\r\nLakeville, Minnesota\r\n469\r\nLe Center, Minnesota\r\n357\r\nLe Sueur, Minnesota\r\n756\r\n665\r\nLesterprar, Minnesota\r\n395\r\nLindstrom, Minnesota\r\n257\r\nLitchfield, Minnesota\r\n693\r\nLittle Falls, Minnesota\r\n632\r\n360\r\n630\r\nLong Prairie, Minnesota\r\n732\r\nLowry, Minnesota\r\n283\r\nMadison, Minnesota\r\n598\r\nMalmo, Minnesota\r\n684\r\nMaple Lake, Minnesota\r\n963\r\nMaple Plain, Minnesota\r\n479\r\nMarietta, Minnesota\r\n668\r\nMayer, Minnesota\r\n657\r\nMaynard, Minnesota\r\n367\r\nMcgrath, Minnesota\r\n592\r\nMelrose, Minnesota\r\n256\r\nMilaca, Minnesota\r\n983\r\nMilan, Minnesota\r\n734\r\nMillerville, Minnesota\r\n876\r\nMontevideo, Minnesota\r\n269\r\nMontgomery, Minnesota\r\n364\r\nMonticello, Minnesota\r\n271\r\n295\r\nMontrose, Minnesota\r\n675\r\nMora, Minnesota\r\n679\r\nMorris, Minnesota\r\n589\r\nMound, Minnesota\r\n472\r\n491\r\nMurdock, Minnesota\r\n875\r\nNew Germany, Minnesota\r\n353\r\nNew London, Minnesota\r\n354\r\nNew Market, Minnesota\r\n461\r\nNew Munich, Minnesota\r\n837\r\nNew Prague, Minnesota\r\n758\r\nNorcross, Minnesota\r\n284\r\nNorth Branch, Minnesota\r\n674\r\nNorwood, Minnesota\r\n467\r\nOdessa, Minnesota\r\n273\r\nOgilvie, Minnesota\r\n272\r\nOlivia, Minnesota\r\n523\r\nOnamia, Minnesota\r\n532\r\nOrtonville, Minnesota\r\n839\r\nOsakis, Minnesota\r\n859\r\nOsseo, Minnesota\r\n420\r\n424\r\n425\r\n493\r\n494\r\nPaynesville, Minnesota\r\n243\r\nPease, Minnesota\r\n369\r\nPennock, Minnesota\r\n599\r\nPierz, Minnesota\r\n468\r\nPine City, Minnesota\r\n629\r\nPlato, Minnesota\r\n238\r\nPrinceton, Minnesota\r\n389\r\nPrinsburg, Minnesota\r\n978\r\nPrior Lake, Minnesota\r\n440\r\n447\r\nRamey, Minnesota\r\n355\r\nRandall, Minnesota\r\n749\r\nRaymond, Minnesota\r\n967\r\nRed Wing, Minnesota\r\n380\r\n385\r\n388\r\nRenville, Minnesota\r\n329\r\nRice, Minnesota\r\n393\r\nRichmond, Minnesota\r\n597\r\nRockford, Minnesota\r\n477\r\nRogers, Minnesota\r\n428\r\nRosemount, Minnesota\r\n322\r\n423\r\nRoyalton, Minnesota\r\n584\r\nRush City, Minnesota\r\n358\r\nSacredhart, Minnesota\r\n765\r\nSandstone, Minnesota\r\n245\r\nSaukcentre, Minnesota\r\n352\r\nScand Marn, Minnesota\r\n433\r\nSedan, Minnesota\r\n268\r\nShakopee, Minnesota\r\n445\r\n496\r\nSilver Lake, Minnesota\r\n327\r\nSoderville, Minnesota\r\n434\r\nSouth Burnsville, Minnesota\r\n435\r\n892\r\nSouthhaven, Minnesota\r\n236\r\nSpicer, Minnesota\r\n796\r\nSaint Cloud, Minnesota\r\n240\r\n249\r\n267\r\n656\r\n761\r\n250\r\n251\r\n252\r\n253\r\n255\r\n259\r\n654\r\nSaint Joseph, Minnesota\r\n363\r\nSaint Martin, Minnesota\r\n548\r\nSaint Michael, Minnesota\r\n497\r\nStarbuck, Minnesota\r\n239\r\nSaint Bonfacus, Minnesota\r\n446\r\nSaint Croix Beach, Minnesota\r\n436\r\nStewart, Minnesota\r\n562\r\nStillwater, Minnesota\r\n351\r\n430\r\n439\r\n225\r\n232\r\n244\r\n266\r\n282\r\n650\r\n659\r\n660\r\n962\r\n969\r\n582\r\n628\r\n486\r\n787\r\n773\r\n686\r\nSullivan Lake, Minnesota\r\n277\r\nSunburg, Minnesota\r\n366\r\nSvea, Minnesota\r\n995\r\nSwanville, Minnesota\r\n547\r\nTaylors Falls, Minnesota\r\n465\r\nTerrace, Minnesota\r\n278\r\nUpsala, Minnesota\r\n573\r\nVictoria, Minnesota\r\n443\r\nVillard, Minnesota\r\n554\r\nWabasha, Minnesota\r\n565\r\nWaconia, Minnesota\r\n442\r\nWahkon, Minnesota\r\n495\r\nWatertown, Minnesota\r\n955\r\nWatkins, Minnesota\r\n764\r\nWaverly, Minnesota\r\n658\r\nWayzata, Minnesota\r\n742\r\n449\r\n470\r\n471\r\n473\r\n474\r\n475\r\n476\r\nWebster, Minnesota\r\n652\r\nWest Danbury, Minnesota\r\n655\r\nWheaton, Minnesota\r\n563\r\nWhite Bear Lake, Minnesota\r\n426\r\n429\r\n653\r\nWhite Rock, Minnesota\r\n258\r\nWillmar, Minnesota\r\n231\r\n235\r\nWinsted, Minnesota\r\n485\r\nWyoming, Minnesota\r\n462\r\nZimmerman, Minnesota\r\n856\r\n\u00035Unknown prefix code (612) - Minnesota\r\n"
  },
  {
    "path": "install/regions/regions.613",
    "content": "Adolphuston, Ontario, Canada\r\n373\r\nAlexandria, Ontario, Canada\r\n525\r\nAlfred, Ontario, Canada\r\n679\r\nAlmonte, Ontario, Canada\r\n256\r\nArden, Ontario, Canada\r\n335\r\nArnprior, Ontario, Canada\r\n623\r\nAthens, Ontario, Canada\r\n924\r\nAvonmore, Ontario, Canada\r\n346\r\nBancroft, Ontario, Canada\r\n332\r\nBarrys Bay, Ontario, Canada\r\n756\r\nBath, Ontario, Canada\r\n352\r\nBeachburg, Ontario, Canada\r\n582\r\nBelleville, Ontario, Canada\r\n962\r\n966\r\n967\r\n968\r\n969\r\nBl 976, Ontario, Canada\r\n976\r\nBloomfield, Ontario, Canada\r\n393\r\nBourget, Ontario, Canada\r\n487\r\nBrighton, Ontario, Canada\r\n475\r\nBrockville, Ontario, Canada\r\n342\r\n345\r\nCalabogie, Ontario, Canada\r\n752\r\nCardiff, Ontario, Canada\r\n339\r\nCardinal, Ontario, Canada\r\n657\r\nCarletonpl, Ontario, Canada\r\n253\r\n257\r\nCarp, Ontario, Canada\r\n839\r\nCasselman, Ontario, Canada\r\n764\r\nChalkriver, Ontario, Canada\r\n589\r\nChestervl, Ontario, Canada\r\n448\r\nClarncecrk, Ontario, Canada\r\n488\r\nCobden, Ontario, Canada\r\n646\r\nCoe Hill, Ontario, Canada\r\n337\r\nConstnceb, Ontario, Canada\r\n832\r\nCornwall, Ontario, Canada\r\n931\r\n932\r\n933\r\n936\r\n937\r\n938\r\nCrysler, Ontario, Canada\r\n987\r\nCumberland, Ontario, Canada\r\n833\r\nDeep River, Ontario, Canada\r\n584\r\nDelta, Ontario, Canada\r\n928\r\nDenbigh, Ontario, Canada\r\n333\r\nDeseronto, Ontario, Canada\r\n396\r\nDouglas, Ontario, Canada\r\n649\r\nEganville, Ontario, Canada\r\n628\r\nElgin, Ontario, Canada\r\n359\r\nEmbrun, Ontario, Canada\r\n443\r\nEnterprise, Ontario, Canada\r\n358\r\nFinch, Ontario, Canada\r\n984\r\nFoymount, Ontario, Canada\r\n754\r\nFrankford, Ontario, Canada\r\n398\r\nGananoque, Ontario, Canada\r\n382\r\nGilmour, Ontario, Canada\r\n474\r\nGlen Robtn, Ontario, Canada\r\n874\r\nGloucester, Ontario, Canada\r\n822\r\nGolden Lk, Ontario, Canada\r\n625\r\nHarrwsmith, Ontario, Canada\r\n372\r\nHawkesbury, Ontario, Canada\r\n242\r\n632\r\nIngleside, Ontario, Canada\r\n537\r\nInverary, Ontario, Canada\r\n353\r\nIroquois, Ontario, Canada\r\n652\r\nJockvale, Ontario, Canada\r\n825\r\nKanat Stit, Ontario, Canada\r\n591\r\n592\r\n831\r\n836\r\nKemptville, Ontario, Canada\r\n258\r\nKillaloe, Ontario, Canada\r\n757\r\nKingston, Ontario, Canada\r\n384\r\n389\r\n531\r\n541\r\n542\r\n544\r\n545\r\n546\r\n547\r\n548\r\n549\r\n650\r\nLanark, Ontario, Canada\r\n259\r\nLancaster, Ontario, Canada\r\n347\r\nLansdowne, Ontario, Canada\r\n659\r\nLong Sault, Ontario, Canada\r\n534\r\nLorignal, Ontario, Canada\r\n675\r\nMaberly, Ontario, Canada\r\n268\r\nMadoc, Ontario, Canada\r\n473\r\nMaitland, Ontario, Canada\r\n348\r\nMallorytn, Ontario, Canada\r\n923\r\nManotick, Ontario, Canada\r\n692\r\nMarmora, Ontario, Canada\r\n472\r\nMartintown, Ontario, Canada\r\n528\r\nMaxville, Ontario, Canada\r\n527\r\nMaynooth, Ontario, Canada\r\n338\r\nMcdnldcors, Ontario, Canada\r\n278\r\nMerrickvl, Ontario, Canada\r\n269\r\nMetcalfe, Ontario, Canada\r\n821\r\nMoosecreek, Ontario, Canada\r\n538\r\nMorrisburg, Ontario, Canada\r\n543\r\nNapanee, Ontario, Canada\r\n354\r\nNavan, Ontario, Canada\r\n835\r\nNewburgh, Ontario, Canada\r\n378\r\nNo Augusta, Ontario, Canada\r\n926\r\nNorthbrook, Ontario, Canada\r\n336\r\nNorthgower, Ontario, Canada\r\n489\r\nOdessa, Ontario, Canada\r\n386\r\nOrleans, Ontario, Canada\r\n824\r\n830\r\n834\r\n837\r\nOsgoode, Ontario, Canada\r\n826\r\nOttawa Hul, Ontario, Canada\r\n224\r\n225\r\n226\r\n228\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n243\r\n521\r\n523\r\n526\r\n560\r\n561\r\n563\r\n564\r\n566\r\n567\r\n568\r\n593\r\n594\r\n595\r\n596\r\n598\r\n672\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\n731\r\n733\r\n734\r\n737\r\n738\r\n739\r\n741\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n750\r\n755\r\n761\r\n762\r\n763\r\n765\r\n769\r\n770\r\n771\r\n776\r\n777\r\n778\r\n781\r\n782\r\n783\r\n785\r\n787\r\n788\r\n790\r\n820\r\n828\r\n829\r\n943\r\n945\r\n946\r\n951\r\n952\r\n953\r\n954\r\n956\r\n957\r\n990\r\n991\r\n992\r\n993\r\n994\r\n995\r\n996\r\n997\r\n998\r\nPakenham, Ontario, Canada\r\n624\r\nPalmerrpds, Ontario, Canada\r\n758\r\nParham, Ontario, Canada\r\n375\r\nPembroke, Ontario, Canada\r\n638\r\n732\r\n735\r\nPerth, Ontario, Canada\r\n264\r\n267\r\nPetawawa, Ontario, Canada\r\n588\r\n687\r\nPicton, Ontario, Canada\r\n476\r\nPlantagent, Ontario, Canada\r\n673\r\nPlevna, Ontario, Canada\r\n479\r\nPortland, Ontario, Canada\r\n272\r\nPrescott, Ontario, Canada\r\n925\r\nRenfrew, Ontario, Canada\r\n432\r\nRichmond, Ontario, Canada\r\n838\r\nRockland, Ontario, Canada\r\n446\r\nRolphton, Ontario, Canada\r\n586\r\nRussell, Ontario, Canada\r\n445\r\nSeeleysbay, Ontario, Canada\r\n387\r\nSelby, Ontario, Canada\r\n388\r\nSharbot Lk, Ontario, Canada\r\n279\r\nSmiths Fls, Ontario, Canada\r\n283\r\n284\r\nSouth Mt, Ontario, Canada\r\n989\r\nSpencervl, Ontario, Canada\r\n658\r\nSt Eugene, Ontario, Canada\r\n674\r\nSt Isdr, Ontario, Canada\r\n524\r\nStirling, Ontario, Canada\r\n395\r\nSydenham, Ontario, Canada\r\n376\r\nTamworth, Ontario, Canada\r\n379\r\nThurlow, Ontario, Canada\r\n477\r\nToledo, Ontario, Canada\r\n275\r\nTrenton, Ontario, Canada\r\n392\r\n394\r\n965\r\nTweed, Ontario, Canada\r\n478\r\nVankleekhl, Ontario, Canada\r\n678\r\nVerona, Ontario, Canada\r\n374\r\nWellington, Ontario, Canada\r\n399\r\nWestmeath, Ontario, Canada\r\n587\r\nWestport, Ontario, Canada\r\n273\r\nWhitney, Ontario, Canada\r\n637\r\nWilliamsbg, Ontario, Canada\r\n535\r\nWinchester, Ontario, Canada\r\n774\r\nWolfe Is, Ontario, Canada\r\n385\r\nWooler, Ontario, Canada\r\n397\r\nYarker, Ontario, Canada\r\n377\r\n\u00035Unknown prefix code (613) - Ontario, Canada\r\n"
  },
  {
    "path": "install/regions/regions.614",
    "content": "Adamsville, Ohio\r\n796\r\nAdena, Ohio\r\n546\r\nAlbany, Ohio\r\n698\r\nAlexandria, Ohio\r\n924\r\nAlton, Ohio\r\n853\r\n851\r\n870\r\n878\r\nAmanda, Ohio\r\n969\r\nAmesville, Ohio\r\n448\r\nAmsterdam, Ohio\r\n543\r\nArabia, Ohio\r\n643\r\nAshley, Ohio\r\n747\r\nAshville, Ohio\r\n983\r\nAthens, Ohio\r\n541\r\n589\r\n591\r\n592\r\n593\r\n594\r\n597\r\nBainbridge, Ohio\r\n634\r\nBaltimore, Ohio\r\n862\r\nBarlow, Ohio\r\n678\r\nBarnesville, Ohio\r\n425\r\nBartlett, Ohio\r\n551\r\nBeallsville, Ohio\r\n926\r\nBeaver, Ohio\r\n226\r\nBelpre, Ohio\r\n423\r\nBergholz, Ohio\r\n768\r\nBethesda, Ohio\r\n484\r\nBeverly, Ohio\r\n984\r\nBloomingburg, Ohio\r\n437\r\nBloomingdale, Ohio\r\n944\r\nBourneville, Ohio\r\n626\r\nBowerston, Ohio\r\n269\r\nBremen, Ohio\r\n569\r\nBrilliant, Ohio\r\n598\r\nByesville, Ohio\r\n685\r\nCadiz, Ohio\r\n942\r\nCaldwell, Ohio\r\n732\r\nCambridge, Ohio\r\n584\r\n432\r\n439\r\nCarroll, Ohio\r\n756\r\nCenterburg, Ohio\r\n625\r\nCenterville, Ohio\r\n686\r\nChesapeake, Ohio\r\n867\r\n886\r\n894\r\nCheshire, Ohio\r\n367\r\nCheshire Center, Ohio\r\n548\r\nChester, Ohio\r\n985\r\nChesterhill, Ohio\r\n554\r\nChillicoth, Ohio\r\n649\r\n772\r\n773\r\n774\r\n775\r\nCircleville, Ohio\r\n474\r\n477\r\nClarington, Ohio\r\n458\r\nClarksburg, Ohio\r\n993\r\nColonel Winchester, Ohio\r\n833\r\n837\r\nColumbus, Ohio\r\n240\r\n241\r\n242\r\n244\r\n257\r\n298\r\n325\r\n326\r\n361\r\n422\r\n429\r\n449\r\n480\r\n531\r\n538\r\n566\r\n582\r\n624\r\n648\r\n692\r\n693\r\n731\r\n736\r\n784\r\n221\r\n222\r\n223\r\n224\r\n225\r\n227\r\n228\r\n229\r\n231\r\n235\r\n236\r\n237\r\n238\r\n239\r\n243\r\n248\r\n249\r\n251\r\n252\r\n253\r\n258\r\n261\r\n262\r\n263\r\n265\r\n267\r\n268\r\n271\r\n272\r\n274\r\n275\r\n276\r\n278\r\n279\r\n281\r\n291\r\n292\r\n293\r\n294\r\n296\r\n297\r\n299\r\n329\r\n338\r\n341\r\n351\r\n365\r\n371\r\n395\r\n421\r\n424\r\n442\r\n443\r\n444\r\n445\r\n447\r\n451\r\n457\r\n459\r\n460\r\n461\r\n462\r\n463\r\n464\r\n466\r\n469\r\n481\r\n486\r\n487\r\n488\r\n621\r\n644\r\n645\r\n752\r\n821\r\nConesville, Ohio\r\n829\r\nCoolville, Ohio\r\n378\r\n667\r\nCooperdale, Ohio\r\n327\r\nCorning, Ohio\r\n347\r\nCoshocton, Ohio\r\n622\r\n623\r\nCrooksville, Ohio\r\n982\r\nCroton, Ohio\r\n893\r\nCumberland, Ohio\r\n638\r\nDanville, Ohio\r\n599\r\nDelaware, Ohio\r\n360\r\n362\r\n363\r\n368\r\n369\r\nDexter City, Ohio\r\n783\r\nDlnvlmtplt, Ohio\r\n769\r\nDresden, Ohio\r\n754\r\nDublin, Ohio\r\n791\r\n798\r\n761\r\n764\r\n766\r\n792\r\n793\r\n889\r\nDuffy, Ohio\r\n483\r\nFairview, Ohio\r\n758\r\nFlushing, Ohio\r\n968\r\nFrankfort, Ohio\r\n998\r\nFrazeysburg, Ohio\r\n828\r\nFrederickton, Ohio\r\n694\r\nFreeport, Ohio\r\n658\r\nFultonham, Ohio\r\n849\r\nGahanna, Ohio\r\n337\r\n471\r\n475\r\n476\r\n478\r\n479\r\nGallipolis, Ohio\r\n441\r\n446\r\nGambier, Ohio\r\n427\r\nGlenford, Ohio\r\n659\r\nGlouster, Ohio\r\n767\r\nGnadenhutn, Ohio\r\n254\r\nGranville, Ohio\r\n321\r\n587\r\nGratiot, Ohio\r\n787\r\nGraysville, Ohio\r\n934\r\nGreen Camp, Ohio\r\n528\r\nGrove City, Ohio\r\n539\r\n871\r\n875\r\nGroveport, Ohio\r\n836\r\nGuyan, Ohio\r\n256\r\nGuysville, Ohio\r\n662\r\nHallsville, Ohio\r\n655\r\nHanover, Ohio\r\n575\r\nHarpster, Ohio\r\n496\r\nHarrisburg, Ohio\r\n877\r\nHebron, Ohio\r\n928\r\n929\r\nHilliard, Ohio\r\n529\r\n771\r\n777\r\n876\r\nHopedale, Ohio\r\n937\r\nIdaho, Ohio\r\n493\r\nIronton, Ohio\r\n377\r\n532\r\n533\r\nJackson, Ohio\r\n286\r\n988\r\nJeffersonville, Ohio\r\n426\r\nJewett, Ohio\r\n946\r\nJohnstown, Ohio\r\n967\r\nJunction City, Ohio\r\n987\r\nKilbourne, Ohio\r\n524\r\nKingston, Ohio\r\n642\r\nKnoxville, Ohio\r\n544\r\nLa Rue, Ohio\r\n499\r\nLancaster, Ohio\r\n681\r\n744\r\n653\r\n654\r\n687\r\nLaurelville, Ohio\r\n332\r\nLetart Falls, Ohio\r\n247\r\nLewisville, Ohio\r\n567\r\nLockbourne, Ohio\r\n288\r\n491\r\n492\r\n497\r\nLogan, Ohio\r\n385\r\nLondon, Ohio\r\n852\r\nLondondery, Ohio\r\n887\r\nLowell, Ohio\r\n896\r\nLower Salem, Ohio\r\n585\r\nLittle Hocking, Ohio\r\n989\r\nMarietta, Ohio\r\n376\r\n525\r\n373\r\n374\r\nMarion, Ohio\r\n382\r\n383\r\n387\r\n389\r\nMartinsburg, Ohio\r\n668\r\nMassieville, Ohio\r\n663\r\nMcArthur, Ohio\r\n596\r\nMcConelsville, Ohio\r\n962\r\nMilledgeville, Ohio\r\n948\r\nMillers Point, Ohio\r\n467\r\nMingo Junction, Ohio\r\n535\r\nMnfd Stockdale, Ohio\r\n820\r\nMorral, Ohio\r\n465\r\nMorristown, Ohio\r\n782\r\nMount Sterlng, Ohio\r\n869\r\nMount Vernon, Ohio\r\n398\r\n392\r\n393\r\n397\r\nMurray City, Ohio\r\n762\r\nNelsonville, Ohio\r\n753\r\nNevada, Ohio\r\n482\r\nNew Albany, Ohio\r\n855\r\n939\r\nNewark, Ohio\r\n328\r\n348\r\n788\r\n323\r\n344\r\n345\r\n349\r\n366\r\n522\r\n763\r\nNew Comerton, Ohio\r\n498\r\nNew Concord, Ohio\r\n826\r\nNew Holland, Ohio\r\n495\r\nNew Lexington, Ohio\r\n342\r\nNew Matamars, Ohio\r\n865\r\nNew Marshfield, Ohio\r\n664\r\nNewport, Ohio\r\n473\r\nNorwich, Ohio\r\n872\r\nOak Hill, Ohio\r\n682\r\nOld Washington, Ohio\r\n489\r\nOstrander, Ohio\r\n666\r\nPataskala, Ohio\r\n927\r\n964\r\nPennsville, Ohio\r\n557\r\nPhilo, Ohio\r\n674\r\nPiketon, Ohio\r\n289\r\n897\r\nPlain City, Ohio\r\n873\r\nPleasantville, Ohio\r\n468\r\nPomeroy, Ohio\r\n742\r\n949\r\n992\r\nPortland, Ohio\r\n843\r\nPortsmouth, Ohio\r\n259\r\n285\r\n352\r\n353\r\n354\r\n355\r\n372\r\n456\r\n574\r\n776\r\n778\r\n858\r\nPowhatan Point, Ohio\r\n795\r\nProspect, Ohio\r\n494\r\nQuaker City, Ohio\r\n679\r\nRadnor, Ohio\r\n595\r\nRathbone, Ohio\r\n881\r\nResaca, Ohio\r\n857\r\nReynoldsburg, Ohio\r\n577\r\n755\r\n759\r\n860\r\n861\r\n863\r\n864\r\n866\r\n868\r\nRichmond, Ohio\r\n765\r\nRichmondale, Ohio\r\n884\r\nRichwood, Ohio\r\n943\r\nRinrvlhkny, Ohio\r\n558\r\nRio Grande, Ohio\r\n245\r\nRoseville, Ohio\r\n697\r\nRushville, Ohio\r\n536\r\nScio, Ohio\r\n945\r\nSedalia, Ohio\r\n874\r\nShade, Ohio\r\n696\r\nShawnee, Ohio\r\n394\r\nSmithfield, Ohio\r\n733\r\nSomerset, Ohio\r\n743\r\nSomerton, Ohio\r\n757\r\nSaint Louisville, Ohio\r\n745\r\nSteubenville, Ohio\r\n264\r\n266\r\n282\r\n283\r\n284\r\n381\r\nStockport, Ohio\r\n559\r\nSugargrove, Ohio\r\n746\r\nSummerfield, Ohio\r\n838\r\nSunbury, Ohio\r\n965\r\nThe Plains, Ohio\r\n797\r\nThornville, Ohio\r\n246\r\nTiltonsville, Ohio\r\n859\r\nToronto, Ohio\r\n537\r\nUhrichsville, Ohio\r\n922\r\nUticahomer, Ohio\r\n892\r\nVinton, Ohio\r\n388\r\nWaldo, Ohio\r\n726\r\nWalnut, Ohio\r\n379\r\nWarsaw, Ohio\r\n824\r\nWash Ct Hills, Ohio\r\n636\r\nWash Ct, Ohio\r\n333\r\n335\r\nWatertown, Ohio\r\n749\r\nWaverly, Ohio\r\n947\r\nWellston, Ohio\r\n384\r\nWesterville, Ohio\r\n523\r\n823\r\n794\r\n882\r\n890\r\n891\r\n895\r\n898\r\n899\r\nWheeling, Ohio\r\n633\r\n635\r\n671\r\n676\r\n695\r\n391\r\nWilkesville, Ohio\r\n669\r\nWilliams Point, Ohio\r\n986\r\nWest Jefferson, Ohio\r\n879\r\nWest Lafayette, Ohio\r\n545\r\nWoodsfield, Ohio\r\n472\r\nWorthington, Ohio\r\n431\r\n433\r\n436\r\n438\r\n637\r\n646\r\n647\r\n785\r\n786\r\n825\r\n841\r\n842\r\n844\r\n846\r\n847\r\n848\r\n885\r\n888\r\nZanesville, Ohio\r\n450\r\n452\r\n453\r\n454\r\n455\r\n586\r\n\u00035Unknown prefix code (614) - Ohio\r\n"
  },
  {
    "path": "install/regions/regions.615",
    "content": "Adamscdrhill, Tennessee\r\n696\r\nAlexandria, Tennessee\r\n529\r\nApison, Tennessee\r\n236\r\nAshland City, Tennessee\r\n792\r\nAthens, Tennessee\r\n744\r\n745\r\nAuburntown, Tennessee\r\n464\r\nBaileyton, Tennessee\r\n234\r\nBall Play, Tennessee\r\n295\r\nBean Station, Tennessee\r\n993\r\nBenton, Tennessee\r\n338\r\nBethpage, Tennessee\r\n841\r\nBlountville, Tennessee\r\n279\r\n323\r\nBluff City, Tennessee\r\n538\r\nBristol, Tennessee\r\n534\r\n989\r\n652\r\n878\r\n968\r\nBulls Gap, Tennessee\r\n235\r\nButler, Tennessee\r\n768\r\nCarthage, Tennessee\r\n735\r\nCharleston, Tennessee\r\n336\r\nCharlotte, Tennessee\r\n789\r\nChatanooga, Tennessee\r\n240\r\n785\r\n954\r\n991\r\n490\r\n265\r\n266\r\n267\r\n344\r\n488\r\n493\r\n495\r\n499\r\n622\r\n624\r\n629\r\n634\r\n642\r\n667\r\n697\r\n698\r\n751\r\n755\r\n756\r\n757\r\n778\r\n821\r\n825\r\n842\r\n843\r\n846\r\n855\r\n867\r\n870\r\n874\r\n875\r\n877\r\n886\r\n891\r\n892\r\n894\r\n899\r\nChestnutmnd, Tennessee\r\n897\r\nChurch Hill, Tennessee\r\n357\r\nClaxton, Tennessee\r\n945\r\nCleveland, Tennessee\r\n559\r\n339\r\n472\r\n476\r\n478\r\n479\r\nClinchport, Tennessee\r\n944\r\nClinton, Tennessee\r\n457\r\n463\r\nCoker Creek, Tennessee\r\n261\r\nCollege Station, Tennessee\r\n554\r\nCollegedale, Tennessee\r\n396\r\nCollege Grove, Tennessee\r\n368\r\nConcord, Tennessee\r\n640\r\n671\r\n567\r\n675\r\n679\r\n966\r\nCopperbasin, Tennessee\r\n496\r\nCrsplsorln, Tennessee\r\n654\r\nCumberland Gap, Tennessee\r\n869\r\nDayton, Tennessee\r\n775\r\nDeer Lodge, Tennessee\r\n965\r\nDefeated, Tennessee\r\n774\r\nDickson, Tennessee\r\n441\r\n446\r\nDunlap, Tennessee\r\n949\r\nEagleville, Tennessee\r\n274\r\nElizabethton, Tennessee\r\n542\r\n543\r\n547\r\nEnglewood, Tennessee\r\n887\r\nErwin, Tennessee\r\n743\r\nEtowah, Tennessee\r\n263\r\nFairview, Tennessee\r\n799\r\nFallbranch, Tennessee\r\n348\r\nFall Creek, Tennessee\r\n881\r\nFork Ridge, Tennessee\r\n233\r\n249\r\nFranklin, Tennessee\r\n771\r\n790\r\n791\r\n794\r\nGallatin, Tennessee\r\n230\r\n451\r\n452\r\nGatlinburg, Tennessee\r\n430\r\n436\r\nGeorgetown, Tennessee\r\n961\r\nGoodletsville, Tennessee\r\n851\r\n859\r\nGordonsville, Tennessee\r\n683\r\nGreenback, Tennessee\r\n856\r\nGreenbrier, Tennessee\r\n643\r\nGreeneville, Tennessee\r\n636\r\n638\r\n639\r\nGreen Grove, Tennessee\r\n655\r\nHalls Crossroad, Tennessee\r\n922\r\n925\r\nHampton, Tennessee\r\n725\r\nHarriman, Tennessee\r\n882\r\nHartsville, Tennessee\r\n374\r\nHendersonville, Tennessee\r\n264\r\n822\r\n824\r\n826\r\nHillsdale, Tennessee\r\n633\r\nHuntsville, Tennessee\r\n663\r\nJasper, Tennessee\r\n942\r\nJefferson City, Tennessee\r\n471\r\n475\r\nJellico, Tennessee\r\n784\r\nJohnson City, Tennessee\r\n282\r\n283\r\n461\r\n926\r\n928\r\n929\r\n795\r\n854\r\n434\r\nJonesboro, Tennessee\r\n753\r\nKingsport, Tennessee\r\n229\r\n245\r\n246\r\n247\r\n288\r\n378\r\n224\r\n392\r\nKingston, Tennessee\r\n376\r\nKingston Spring, Tennessee\r\n952\r\nKnoxville, Tennessee\r\n470\r\n521\r\n522\r\n523\r\n524\r\n525\r\n531\r\n541\r\n544\r\n546\r\n549\r\n558\r\n564\r\n573\r\n577\r\n579\r\n584\r\n588\r\n594\r\n595\r\n631\r\n632\r\n637\r\n656\r\n673\r\n687\r\n688\r\n689\r\n690\r\n691\r\n693\r\n694\r\n971\r\n974\r\n250\r\n545\r\n599\r\n850\r\n996\r\n281\r\n539\r\n873\r\nLaf Louisville, Tennessee\r\n562\r\n566\r\n666\r\nLake City, Tennessee\r\n426\r\nLavergne, Tennessee\r\n641\r\n287\r\n793\r\nLebanon, Tennessee\r\n443\r\n444\r\n449\r\nLenoir City, Tennessee\r\n986\r\n988\r\nLiberty, Tennessee\r\n536\r\nLimestone, Tennessee\r\n257\r\nLoudon, Tennessee\r\n458\r\nMadisonville, Tennessee\r\n442\r\nMaryville, Tennessee\r\n448\r\n681\r\n970\r\n977\r\n981\r\n982\r\n983\r\n984\r\n995\r\n985\r\nMascot, Tennessee\r\n932\r\n933\r\nMaynardville, Tennessee\r\n992\r\nMidway, Tennessee\r\n571\r\n239\r\n335\r\n341\r\n477\r\nMilton, Tennessee\r\n273\r\nMorristown, Tennessee\r\n581\r\n585\r\n586\r\n587\r\nMosheim, Tennessee\r\n422\r\nMountain City, Tennessee\r\n727\r\nMount Juliet, Tennessee\r\n754\r\n758\r\n773\r\nMurfreesboro, Tennessee\r\n848\r\n849\r\n890\r\n893\r\n895\r\n896\r\n898\r\nNashville, Tennessee\r\n222\r\n226\r\n227\r\n228\r\n242\r\n244\r\n248\r\n251\r\n252\r\n254\r\n255\r\n256\r\n259\r\n262\r\n269\r\n271\r\n275\r\n292\r\n297\r\n298\r\n320\r\n321\r\n322\r\n327\r\n329\r\n331\r\n333\r\n340\r\n343\r\n350\r\n351\r\n352\r\n353\r\n356\r\n360\r\n361\r\n366\r\n367\r\n370\r\n371\r\n373\r\n377\r\n383\r\n385\r\n386\r\n391\r\n399\r\n421\r\n646\r\n662\r\n664\r\n665\r\n726\r\n734\r\n736\r\n737\r\n741\r\n742\r\n747\r\n748\r\n749\r\n780\r\n781\r\n782\r\n831\r\n832\r\n833\r\n834\r\n860\r\n862\r\n865\r\n868\r\n871\r\n872\r\n876\r\n883\r\n885\r\n889\r\n923\r\n943\r\n835\r\n221\r\n660\r\n661\r\n731\r\n291\r\n330\r\n532\r\n838\r\n948\r\n972\r\n973\r\n299\r\n783\r\n936\r\n231\r\n284\r\n342\r\n347\r\n390\r\nNewport, Tennessee\r\n623\r\n625\r\nNew Tazewell, Tennessee\r\n626\r\nNine Mile, Tennessee\r\n533\r\nNiota, Tennessee\r\n568\r\nNolensville, Tennessee\r\n941\r\n776\r\nNorene, Tennessee\r\n286\r\nNorris, Tennessee\r\n494\r\nOak Grove, Tennessee\r\n888\r\nOak Ridge, Tennessee\r\n220\r\n241\r\n481\r\n482\r\n483\r\n574\r\n576\r\nOakdale, Tennessee\r\n369\r\nOld Hickory, Tennessee\r\n847\r\nOliver Springs, Tennessee\r\n435\r\nOneida, Tennessee\r\n569\r\nOoltewah, Tennessee\r\n238\r\nPetros, Tennessee\r\n324\r\nPikeville, Tennessee\r\n447\r\nPleasantview, Tennessee\r\n746\r\nPleasantshed, Tennessee\r\n677\r\nPortland, Tennessee\r\n325\r\nPowell, Tennessee\r\n938\r\n947\r\nRed Boiling Spring, Tennessee\r\n699\r\nRiceville, Tennessee\r\n462\r\nRoan Mount, Tennessee\r\n772\r\nRobbins, Tennessee\r\n627\r\nRockwood, Tennessee\r\n354\r\nRogersville, Tennessee\r\n272\r\n921\r\nRutledge, Tennessee\r\n828\r\nSevierville, Tennessee\r\n429\r\n428\r\n453\r\nShady Valley, Tennessee\r\n739\r\nSharps Chapel, Tennessee\r\n278\r\nSmithville, Tennessee\r\n597\r\nSmyrna, Tennessee\r\n223\r\n355\r\n459\r\nSneedville, Tennessee\r\n733\r\nSouth Pittsburg, Tennessee\r\n837\r\nSoddydaisy, Tennessee\r\n332\r\nSolway, Tennessee\r\n927\r\nSpring City, Tennessee\r\n365\r\nSpringfield, Tennessee\r\n382\r\n384\r\nStoney Creek, Tennessee\r\n474\r\nSullivan Garden, Tennessee\r\n349\r\nSunbright, Tennessee\r\n628\r\nSurgoinsville, Tennessee\r\n345\r\nSweetwater, Tennessee\r\n337\r\nTate Springs, Tennessee\r\n767\r\nTellicopls, Tennessee\r\n253\r\nTemperance Hill, Tennessee\r\n548\r\nTruine, Tennessee\r\n395\r\nVanleer, Tennessee\r\n763\r\nVonore, Tennessee\r\n884\r\nWartburg, Tennessee\r\n346\r\nWashburn, Tennessee\r\n497\r\nWatertown, Tennessee\r\n237\r\nWestmoreld, Tennessee\r\n644\r\nWhite Pine, Tennessee\r\n674\r\nWhitebluff, Tennessee\r\n797\r\nWhitehouse, Tennessee\r\n672\r\nWhitwell, Tennessee\r\n658\r\nWoodbury, Tennessee\r\n563\r\nWoodland, Tennessee\r\n765\r\n\u00035Unknown prefix code (615) - Tennessee\r\n"
  },
  {
    "path": "install/regions/regions.616",
    "content": "Ada, Michigan\r\n676\r\nAlanson, Michigan\r\n548\r\nAlba, Michigan\r\n584\r\nAlden, Michigan\r\n331\r\nAllegan, Michigan\r\n673\r\nAllendale, Michigan\r\n892\r\n895\r\nAlto, Michigan\r\n868\r\nAmble, Michigan\r\n762\r\nAthens, Michigan\r\n729\r\nAugusta, Michigan\r\n731\r\nBaldwin, Michigan\r\n745\r\nBanfield, Michigan\r\n721\r\nBangor, Michigan\r\n427\r\nBaroda, Michigan\r\n422\r\nBattle Creek, Michigan\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\n979\r\nBear Lake, Michigan\r\n864\r\nBelding, Michigan\r\n794\r\nBellaire, Michigan\r\n533\r\nBellevue, Michigan\r\n763\r\nBenton Hbr, Michigan\r\n849\r\n921\r\n925\r\n926\r\n927\r\n944\r\nBerrienspg, Michigan\r\n471\r\n473\r\nBeulah, Michigan\r\n882\r\nBig Rapids, Michigan\r\n592\r\n796\r\nBloomingdl, Michigan\r\n521\r\nBois Blanc, Michigan\r\n634\r\nBorculo, Michigan\r\n875\r\nBoyne City, Michigan\r\n582\r\nBoynefalls, Michigan\r\n549\r\nBrethren, Michigan\r\n477\r\nBridgman, Michigan\r\n465\r\n466\r\nBrutus, Michigan\r\n529\r\nBuchanan, Michigan\r\n695\r\n697\r\nBuckley, Michigan\r\n269\r\nBurr Oak, Michigan\r\n489\r\nByron Ctr, Michigan\r\n878\r\nCadillac, Michigan\r\n775\r\n779\r\nCaledonia, Michigan\r\n891\r\nCarr, Michigan\r\n898\r\nCasnovia, Michigan\r\n675\r\nCassopolis, Michigan\r\n445\r\nCedar Spgs, Michigan\r\n696\r\nCentral Lk, Michigan\r\n544\r\nCentrevl, Michigan\r\n467\r\nCharlevoix, Michigan\r\n547\r\nCheboygan, Michigan\r\n625\r\n627\r\nChippowa Lake, Michigan\r\n867\r\nClam River, Michigan\r\n377\r\nClarksvl, Michigan\r\n693\r\nClimax, Michigan\r\n746\r\nColoma, Michigan\r\n468\r\nColon, Michigan\r\n432\r\nConklin, Michigan\r\n899\r\nConstntine, Michigan\r\n435\r\nCoopersvl, Michigan\r\n837\r\nCopemish T, Michigan\r\n378\r\nCoral, Michigan\r\n354\r\nCovert, Michigan\r\n764\r\nDecatur, Michigan\r\n423\r\nDelton, Michigan\r\n623\r\nDorr, Michigan\r\n681\r\nDowagiac, Michigan\r\n782\r\nDrenthe, Michigan\r\n688\r\nDutton, Michigan\r\n698\r\nEastjordan, Michigan\r\n536\r\nEastport, Michigan\r\n599\r\nEau Claire, Michigan\r\n461\r\nEdwardsbg, Michigan\r\n663\r\n699\r\nElk Rapids, Michigan\r\n264\r\nEllsworth, Michigan\r\n588\r\nElmira, Michigan\r\n546\r\nEvart, Michigan\r\n734\r\nFalmouth, Michigan\r\n826\r\nFennville, Michigan\r\n561\r\nFife Lake, Michigan\r\n879\r\nFountain, Michigan\r\n462\r\nFrankfort, Michigan\r\n352\r\nFreeport, Michigan\r\n765\r\nFreesoil, Michigan\r\n464\r\nFremont, Michigan\r\n924\r\n928\r\nFruitport, Michigan\r\n865\r\nFulton, Michigan\r\n778\r\nGalesburg, Michigan\r\n665\r\nGalien, Michigan\r\n545\r\nGanges, Michigan\r\n543\r\nGlen Lake, Michigan\r\n228\r\n326\r\n334\r\nGlenn, Michigan\r\n227\r\nGobles, Michigan\r\n628\r\nGrand Jct, Michigan\r\n434\r\nGrand Rapids, Michigan\r\n224\r\n235\r\n240\r\n241\r\n242\r\n243\r\n245\r\n246\r\n247\r\n249\r\n281\r\n361\r\n363\r\n364\r\n380\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n530\r\n531\r\n532\r\n534\r\n538\r\n560\r\n732\r\n770\r\n771\r\n774\r\n776\r\n784\r\n785\r\n790\r\n791\r\n940\r\n942\r\n949\r\n956\r\n957\r\n976\r\nGrandhaven, Michigan\r\n842\r\n846\r\n847\r\nGrant, Michigan\r\n834\r\nGrattan, Michigan\r\n691\r\nGreenville, Michigan\r\n754\r\nHamilton, Michigan\r\n751\r\nHarborspgs, Michigan\r\n526\r\nHarrietta, Michigan\r\n389\r\nHart, Michigan\r\n873\r\nHartford, Michigan\r\n621\r\nHastings, Michigan\r\n945\r\n948\r\nHesperia, Michigan\r\n854\r\nHickorycor, Michigan\r\n671\r\nHolland, Michigan\r\n335\r\n392\r\n393\r\n394\r\n396\r\n399\r\n786\r\nHolton, Michigan\r\n821\r\nHonor, Michigan\r\n325\r\nHopkins, Michigan\r\n793\r\nHowardcity, Michigan\r\n937\r\nHoxeyville, Michigan\r\n862\r\nHudsonville, Michigan\r\n669\r\nIndian River, Michigan\r\n23\r\nInterlochn, Michigan\r\n276\r\nIonia, Michigan\r\n527\r\nIrons, Michigan\r\n266\r\nJamestown, Michigan\r\n896\r\nKalamazoo, Michigan\r\n323\r\n324\r\n327\r\n329\r\n333\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n349\r\n370\r\n372\r\n375\r\n381\r\n382\r\n383\r\n384\r\n385\r\n387\r\n388\r\nKaleva, Michigan\r\n362\r\nKalkaska, Michigan\r\n258\r\nKent City, Michigan\r\n678\r\nKingsley, Michigan\r\n263\r\nLacey, Michigan\r\n758\r\nLacota, Michigan\r\n253\r\nLake Ann, Michigan\r\n275\r\nLake City, Michigan\r\n839\r\nLake Of, Michigan\r\n585\r\nLakeodessa, Michigan\r\n374\r\nLawrence, Michigan\r\n674\r\nLawton, Michigan\r\n624\r\nLe Roy, Michigan\r\n768\r\nLevering, Michigan\r\n537\r\nLkleelanau, Michigan\r\n256\r\nLowell, Michigan\r\n897\r\nLudington, Michigan\r\n843\r\n845\r\nLuther, Michigan\r\n797\r\nMackinaw City, Michigan\r\n436\r\nMancelona, Michigan\r\n587\r\nManistee, Michigan\r\n723\r\nManton, Michigan\r\n824\r\nMarcellus, Michigan\r\n646\r\nMarion, Michigan\r\n743\r\nMarne, Michigan\r\n677\r\nMarshall, Michigan\r\n781\r\n789\r\nMartin, Michigan\r\n672\r\nMattawan, Michigan\r\n668\r\nMcbain, Michigan\r\n825\r\nMecosta, Michigan\r\n972\r\nMendon, Michigan\r\n496\r\nMerritt, Michigan\r\n328\r\nMesick, Michigan\r\n885\r\nMiddleville, Michigan\r\n795\r\nMoline, Michigan\r\n877\r\nMoorestown, Michigan\r\n229\r\nMorley, Michigan\r\n856\r\nMuskegon, Michigan\r\n722\r\n724\r\n725\r\n726\r\n727\r\n728\r\n733\r\n737\r\n739\r\n740\r\n744\r\n750\r\n755\r\n759\r\n766\r\n773\r\n777\r\n780\r\n788\r\n798\r\nNew Troy, Michigan\r\n426\r\nNewaygo, Michigan\r\n652\r\nNewbuffalo, Michigan\r\n469\r\nNiles, Michigan\r\n683\r\n684\r\nNorthport, Michigan\r\n386\r\nOldmission, Michigan\r\n223\r\nOlivet, Michigan\r\n749\r\nOnekama, Michigan\r\n889\r\nOrleans, Michigan\r\n761\r\nOtsego, Michigan\r\n692\r\n694\r\nPaw Paw, Michigan\r\n657\r\nPellston, Michigan\r\n539\r\nPentwater, Michigan\r\n869\r\nPetoskey, Michigan\r\n347\r\n348\r\nPine Lake, Michigan\r\n664\r\nPlainwell, Michigan\r\n685\r\nPullman, Michigan\r\n236\r\nRavenna, Michigan\r\n853\r\nReed City, Michigan\r\n832\r\nRichland, Michigan\r\n629\r\nRockford, Michigan\r\n866\r\n874\r\nSand Lake, Michigan\r\n636\r\nSaranac, Michigan\r\n642\r\nSaugatuck, Michigan\r\n857\r\nSchoolcft, Michigan\r\n679\r\nScotts, Michigan\r\n626\r\nScottville, Michigan\r\n757\r\nShelby, Michigan\r\n861\r\nSister Lakes, Michigan\r\n424\r\nSoboardman, Michigan\r\n369\r\nSouth Haven, Michigan\r\n637\r\n639\r\nSparta, Michigan\r\n887\r\nSaint James, Michigan\r\n448\r\nSaint Joseph, Michigan\r\n428\r\n429\r\n982\r\n983\r\nStanwood, Michigan\r\n823\r\nSturgis, Michigan\r\n651\r\n659\r\nSuttonsbay, Michigan\r\n271\r\nThree Oaks, Michigan\r\n756\r\nThree Rivers, Michigan\r\n244\r\n273\r\n278\r\n279\r\nTraverse City, Michigan\r\n922\r\n929\r\n938\r\n941\r\n943\r\n946\r\n947\r\nTrchriverbridge, Michigan\r\n322\r\nTrufant, Michigan\r\n984\r\nTustin, Michigan\r\n829\r\nTwin Lake, Michigan\r\n828\r\nUnion, Michigan\r\n641\r\nVandalia, Michigan\r\n476\r\nVicksburg, Michigan\r\n649\r\nWalloon Lake, Michigan\r\n535\r\nWatervliet, Michigan\r\n463\r\nWayland, Michigan\r\n792\r\nWellston, Michigan\r\n848\r\nWh Pigeon, Michigan\r\n483\r\nWhitecloud, Michigan\r\n689\r\nWhitehall, Michigan\r\n893\r\n894\r\nWilliamsburg, Michigan\r\n267\r\nWolverine, Michigan\r\n525\r\nWoodland, Michigan\r\n367\r\nZeeland, Michigan\r\n772\r\n\u00035Unknown prefix code (616) - Michigan\r\n"
  },
  {
    "path": "install/regions/regions.617",
    "content": "Arlington, Massachusetts\r\n483\r\n488\r\n641\r\n643\r\n646\r\n648\r\nBelmont, Massachusetts\r\n484\r\n489\r\n855\r\nBoston, Massachusetts\r\n223\r\n227\r\n228\r\n236\r\n247\r\n248\r\n261\r\n262\r\n263\r\n266\r\n267\r\n292\r\n330\r\n338\r\n342\r\n343\r\n345\r\n346\r\n348\r\n350\r\n351\r\n352\r\n353\r\n357\r\n367\r\n372\r\n373\r\n375\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n428\r\n429\r\n434\r\n437\r\n439\r\n443\r\n450\r\n451\r\n457\r\n476\r\n482\r\n490\r\n523\r\n526\r\n534\r\n536\r\n542\r\n556\r\n557\r\n563\r\n565\r\n570\r\n571\r\n572\r\n573\r\n574\r\n578\r\n579\r\n589\r\n635\r\n637\r\n638\r\n654\r\n680\r\n694\r\n695\r\n720\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n733\r\n737\r\n742\r\n743\r\n772\r\n780\r\n781\r\n859\r\n931\r\n936\r\n951\r\n954\r\n955\r\n956\r\n973\r\nBraintree, Massachusetts\r\n356\r\n380\r\n843\r\n848\r\n849\r\nBrighton, Massachusetts\r\n254\r\n560\r\n562\r\n782\r\n783\r\n787\r\n789\r\nBrookline, Massachusetts\r\n232\r\n264\r\n277\r\n278\r\n432\r\n566\r\n632\r\n730\r\n731\r\n732\r\n734\r\n735\r\n738\r\n739\r\nBryantvl, Massachusetts\r\n293\r\n294\r\nBurlington, Massachusetts\r\n221\r\n229\r\n238\r\n270\r\n272\r\n273\r\n564\r\nCambridge, Massachusetts\r\n225\r\n234\r\n252\r\n253\r\n258\r\n339\r\n349\r\n354\r\n374\r\n384\r\n430\r\n441\r\n465\r\n468\r\n491\r\n492\r\n493\r\n494\r\n495\r\n496\r\n497\r\n498\r\n499\r\n520\r\n547\r\n576\r\n577\r\n621\r\n661\r\n693\r\n864\r\n868\r\n873\r\n876\r\nCanton, Massachusetts\r\n575\r\n821\r\n828\r\nCharlestn, Massachusetts\r\n241\r\n242\r\nChelsea, Massachusetts\r\n884\r\n887\r\n889\r\nCohasset, Massachusetts\r\n383\r\nDedham, Massachusetts\r\n320\r\n326\r\n329\r\n461\r\n462\r\n467\r\nDorchester, Massachusetts\r\n265\r\n282\r\n287\r\n288\r\n436\r\n474\r\n825\r\n929\r\nDuxbury, Massachusetts\r\n934\r\nEastboston, Massachusetts\r\n561\r\n567\r\n568\r\n569\r\nEverett, Massachusetts\r\n381\r\n387\r\n389\r\nHanover, Massachusetts\r\n826\r\n829\r\nHingham, Massachusetts\r\n740\r\n741\r\n749\r\nHull, Massachusetts\r\n925\r\nHyde Park, Massachusetts\r\n333\r\n361\r\n362\r\n364\r\nJamaica Plain, Massachusetts\r\n323\r\n327\r\n469\r\n522\r\n524\r\n983\r\nKingston, Massachusetts\r\n582\r\n585\r\nLexington, Massachusetts\r\n226\r\n230\r\n271\r\n274\r\n275\r\n276\r\n280\r\n377\r\n456\r\n532\r\n553\r\n597\r\n669\r\n674\r\n748\r\n841\r\n845\r\n860\r\n861\r\n862\r\n863\r\n945\r\n958\r\n981\r\nLincoln, Massachusetts\r\n259\r\nLynn, Massachusetts\r\n477\r\n581\r\n586\r\n592\r\n593\r\n594\r\n595\r\n596\r\n598\r\n599\r\nLynnfield, Massachusetts\r\n334\r\nMalden, Massachusetts\r\n321\r\n322\r\n324\r\n382\r\n388\r\n394\r\n397\r\nMarblehead, Massachusetts\r\n631\r\n639\r\nMarshfield, Massachusetts\r\n834\r\n837\r\nMedford, Massachusetts\r\n391\r\n393\r\n395\r\n396\r\nMelrose, Massachusetts\r\n662\r\n665\r\n979\r\nMilton, Massachusetts\r\n296\r\n298\r\n696\r\n698\r\nNeedham, Massachusetts\r\n433\r\n444\r\n449\r\n455\r\nNew Bedford, Massachusetts\r\n370\r\n990\r\n992\r\n994\r\n996\r\n998\r\nNewton, Massachusetts\r\n243\r\n244\r\n332\r\n473\r\n527\r\n546\r\n552\r\n558\r\n630\r\n881\r\n964\r\n965\r\n969\r\nNorwell, Massachusetts\r\n659\r\nNorwood, Massachusetts\r\n255\r\n551\r\n762\r\n769\r\nQuincy, Massachusetts\r\n328\r\n347\r\n376\r\n471\r\n472\r\n479\r\n537\r\n770\r\n773\r\n774\r\n786\r\n842\r\n847\r\n984\r\n985\r\nRandolph, Massachusetts\r\n767\r\n961\r\n963\r\n986\r\nReading, Massachusetts\r\n673\r\n677\r\n764\r\n765\r\n942\r\n944\r\nRevere, Massachusetts\r\n284\r\n286\r\n289\r\nRockland, Massachusetts\r\n857\r\n871\r\n878\r\n982\r\nRoxbury, Massachusetts\r\n325\r\n427\r\n442\r\n445\r\n541\r\nSaugus, Massachusetts\r\n231\r\n233\r\n240\r\n257\r\n285\r\nScituate, Massachusetts\r\n544\r\n545\r\nSharon, Massachusetts\r\n784\r\nSouth Boston, Massachusetts\r\n268\r\n269\r\n463\r\n464\r\nSomerville, Massachusetts\r\n623\r\n625\r\n627\r\n628\r\n629\r\n666\r\n776\r\nStoneham, Massachusetts\r\n279\r\n438\r\nStoughton, Massachusetts\r\n297\r\n341\r\n344\r\nWakefield, Massachusetts\r\n224\r\n245\r\n246\r\nWaltham, Massachusetts\r\n281\r\n290\r\n386\r\n398\r\n466\r\n487\r\n538\r\n622\r\n633\r\n642\r\n647\r\n684\r\n736\r\n788\r\n890\r\n891\r\n893\r\n894\r\n895\r\n899\r\n930\r\n962\r\n966\r\n968\r\n974\r\nWatertown, Massachusetts\r\n923\r\n924\r\n926\r\n972\r\nWellesley, Massachusetts\r\n235\r\n237\r\n239\r\n283\r\n431\r\n446\r\nWeymouth, Massachusetts\r\n331\r\n335\r\n337\r\n340\r\nWhitman, Massachusetts\r\n447\r\n970\r\nWinchester, Massachusetts\r\n721\r\n729\r\n756\r\nWinthrop, Massachusetts\r\n539\r\n846\r\nWoburn, Massachusetts\r\n932\r\n933\r\n935\r\n937\r\n938\r\nWorcester, Massachusetts\r\n854\r\n\u00035Unknown prefix code (617) - Massachusetts\r\n"
  },
  {
    "path": "install/regions/regions.618",
    "content": "Addieville, Illinois\r\n424\r\nAlbers, Illinois\r\n248\r\nAlbion, Illinois\r\n445\r\nAlhambra, Illinois\r\n488\r\nAllendale, Illinois\r\n299\r\nAltamont, Illinois\r\n483\r\nAlton Alt, Illinois\r\n463\r\n465\r\n474\r\nAlton Els, Illinois\r\n374\r\nAlton Gfy, Illinois\r\n467\r\nAlton, Illinois\r\n462\r\nAnna, Illinois\r\n833\r\nAnnapolis, Illinois\r\n562\r\n569\r\nAshley, Illinois\r\n485\r\nAva, Illinois\r\n426\r\nAviston, Illinois\r\n228\r\nBaldwin, Illinois\r\n785\r\nBartelso, Illinois\r\n765\r\nBatchtown, Illinois\r\n396\r\nBeckemeyer, Illinois\r\n227\r\nBeecher City, Illinois\r\n487\r\nBelle Rive, Illinois\r\n756\r\nBelleville, Illinois\r\n233\r\n234\r\n235\r\n236\r\nBellmont, Illinois\r\n298\r\nBellvl Ad, Illinois\r\n222\r\n256\r\n257\r\nBellvl Pi, Illinois\r\n744\r\nBenton, Illinois\r\n435\r\n438\r\n439\r\nBethalto, Illinois\r\n377\r\nBiblegrove, Illinois\r\n686\r\nBirds, Illinois\r\n928\r\nBlair, Illinois\r\n774\r\nBlairsville, Illinois\r\n757\r\nBluford, Illinois\r\n732\r\nBreese, Illinois\r\n526\r\nBridgeport, Illinois\r\n945\r\nBrighton, Illinois\r\n372\r\nBrookport, Illinois\r\n564\r\nBroughton, Illinois\r\n647\r\nBrowns, Illinois\r\n446\r\nBrownstown, Illinois\r\n427\r\nBrussels, Illinois\r\n883\r\nBunkerhill, Illinois\r\n585\r\nBurnt Prar, Illinois\r\n896\r\nCairo, Illinois\r\n734\r\nCalhoun, Illinois\r\n863\r\nCarbondale, Illinois\r\n457\r\n525\r\n529\r\n534\r\n549\r\nCarlyle, Illinois\r\n594\r\nCarmi, Illinois\r\n382\r\n384\r\nCarriers Mill, Illinois\r\n994\r\nCarterville, Illinois\r\n985\r\nCavein Rock, Illinois\r\n289\r\nCentralia, Illinois\r\n237\r\n267\r\n532\r\n533\r\n545\r\nChauncey, Illinois\r\n947\r\nChester, Illinois\r\n826\r\nChristophr, Illinois\r\n724\r\nChestfield Rkb, Illinois\r\n753\r\nCisne, Illinois\r\n673\r\nClaremont, Illinois\r\n869\r\nClay City, Illinois\r\n676\r\nCobden, Illinois\r\n893\r\nCollinsville, Illinois\r\n345\r\n320\r\n325\r\n334\r\n338\r\n344\r\n346\r\n420\r\n520\r\n535\r\n540\r\n541\r\n550\r\n560\r\n570\r\n578\r\n623\r\n626\r\n630\r\n782\r\n791\r\n795\r\n799\r\n920\r\nColumbia, Illinois\r\n281\r\nCoultervale, Illinois\r\n758\r\nCereal Springs, Illinois\r\n996\r\nCrisp, Illinois\r\n898\r\nCrossville, Illinois\r\n966\r\nCypress, Illinois\r\n657\r\nDahlgren, Illinois\r\n736\r\nDale, Illinois\r\n773\r\nDe Soto, Illinois\r\n867\r\nDix Kell, Illinois\r\n266\r\nDongola, Illinois\r\n827\r\nDorchester, Illinois\r\n362\r\nDow, Illinois\r\n885\r\nDu Quoin, Illinois\r\n542\r\nDubois, Illinois\r\n787\r\nDundas, Illinois\r\n754\r\nDupo, Illinois\r\n286\r\nEast St Ls C, Illinois\r\n332\r\nEast St Ls E, Illinois\r\n583\r\n874\r\n875\r\nEddyville, Illinois\r\n672\r\nEdgemont, Illinois\r\n293\r\n394\r\n397\r\n398\r\n399\r\nEdgewood, Illinois\r\n238\r\nEdwardsville, Illinois\r\n656\r\n692\r\n659\r\nEldorado, Illinois\r\n273\r\nElizabethtown, Illinois\r\n287\r\nElkville, Illinois\r\n568\r\nEllisgrove, Illinois\r\n859\r\nEnfield, Illinois\r\n963\r\nEquality, Illinois\r\n276\r\nEstls Em C, Illinois\r\n337\r\nEstls Em E, Illinois\r\n271\r\n274\r\n482\r\nEvansville, Illinois\r\n853\r\nEwing, Illinois\r\n629\r\nFairfield, Illinois\r\n842\r\n847\r\nFarina, Illinois\r\n245\r\nFayetteville, Illinois\r\n677\r\nFieldon, Illinois\r\n376\r\nFlat Rock, Illinois\r\n584\r\nFlora, Illinois\r\n662\r\nFreeburg, Illinois\r\n539\r\nGeff, Illinois\r\n897\r\nGermantown, Illinois\r\n523\r\nGlen Carbon, Illinois\r\n288\r\nGlenn, Illinois\r\n763\r\nGodfrey, Illinios\r\n466\r\nGolconda, Illinois\r\n683\r\nGoreville, Illinois\r\n995\r\nGrafton, Illinois\r\n786\r\nGran City Gc, Illinois\r\n225\r\n798\r\n876\r\n877\r\nGran City Pb, Illinois\r\n931\r\nGrandtower, Illinois\r\n565\r\nGrantfork, Illinois\r\n675\r\nGrayville, Illinois\r\n375\r\nGrcy Em Gc, Illinois\r\n451\r\n452\r\nGrcy Em Pb, Illinois\r\n797\r\nGreenville, Illinois\r\n664\r\nHamburg, Illinois\r\n232\r\nHamel, Illinois\r\n633\r\nHardin, Illinois\r\n576\r\nHardinvale, Illinois\r\n557\r\nHarmony, Illinois\r\n755\r\nHarrisburg, Illinois\r\n252\r\n253\r\nHecker, Illinois\r\n473\r\nHerrick, Illinois\r\n428\r\nHerrin, Illinois\r\n942\r\n988\r\nHettick, Illinois\r\n778\r\nHicks, Illinois\r\n264\r\nHighland, Illinois\r\n654\r\nHoffman, Illinois\r\n495\r\nHoyleton, Illinois\r\n493\r\nHurst, Illinois\r\n987\r\nHutsonvl, Illinois\r\n563\r\nIna       , Illinois\r\n437\r\nIrvington, Illinois\r\n249\r\nIuka, Illinois\r\n323\r\nJerseyvale, Illinois\r\n498\r\nJohnston City, Illinois\r\n983\r\nJoppa, Illinois\r\n543\r\nKampsville, Illinois\r\n653\r\nKarnak, Illinois\r\n634\r\nKaskaskia, Illinois\r\n366\r\nKell, Illinois\r\n822\r\nKeyesport, Illinois\r\n749\r\nKinmundy, Illinois\r\n547\r\nLawrenceville, Illinois\r\n943\r\nLeamington, Illinois\r\n275\r\nLebanon, Illinois\r\n537\r\nLivingston, Illinois\r\n637\r\nLouisville, Illinois\r\n665\r\nMacedonia, Illinois\r\n728\r\nMarine, Illinois\r\n887\r\nMarion, Illinois\r\n964\r\n967\r\n993\r\n997\r\nMarissa, Illinois\r\n295\r\nMascoutah, Illinois\r\n566\r\nMaunie, Illinois\r\n968\r\nMcclure, Illinois\r\n661\r\nMcleansbo, Illinois\r\n643\r\nMedora, Illinois\r\n729\r\nMetropolis, Illinois\r\n524\r\nMillstadt, Illinois\r\n476\r\nMound City, Illinois\r\n742\r\n748\r\nMounds, Illinois\r\n745\r\nMount Erie, Illinois\r\n854\r\nMt Carmel, Illinois\r\n262\r\n263\r\nMt Vernon, Illinois\r\n242\r\n244\r\n246\r\nMulberry Grove, Illinois\r\n326\r\nMurphysboro, Illinois\r\n648\r\n684\r\n687\r\nNashville, Illinois\r\n327\r\nNew Athens, Illinois\r\n475\r\nNew Baden, Illinois\r\n588\r\nNew Haven, Illinois\r\n265\r\nNew Minden, Illinois\r\n478\r\nNewton, Illinois\r\n783\r\nNoble, Illinois\r\n723\r\nNorriscity, Illinois\r\n378\r\nO'Fallon, Illinois\r\n628\r\n624\r\n632\r\nOakdale, Illinois\r\n329\r\nOblong, Illinois\r\n592\r\nOdin, Illinois\r\n775\r\nOkawville, Illinois\r\n243\r\nOlive Branch, Illinois\r\n776\r\nOlney, Illinois\r\n392\r\n393\r\n395\r\nOmaha, Illinois\r\n962\r\nOrchardvale, Illinois\r\n835\r\nPalestine, Illinois\r\n586\r\nParkersbg, Illinois\r\n442\r\nPatoka, Illinois\r\n432\r\nPaulton, Illinois\r\n982\r\nPeoria, Illinois\r\n555\r\nPercy, Illinois\r\n497\r\nPinckneyvale, Illinois\r\n357\r\nPittsburg, Illinois\r\n425\r\nPocahontas, Illinois\r\n669\r\nPrairietown, Illinois\r\n888\r\nPrardurchr, Illinois\r\n284\r\nRalghgalta, Illinois\r\n268\r\nRamsey, Illinois\r\n423\r\nRed Bud, Illinois\r\n282\r\nRenault, Illinois\r\n458\r\nRenshaw, Illinois\r\n949\r\nRice, Illinois\r\n336\r\nRidgway, Illinois\r\n272\r\nRobinson, Illinois\r\n544\r\n546\r\nRose Hill, Illinois\r\n793\r\nRosiclare, Illinois\r\n285\r\nRoyalton, Illinois\r\n984\r\nSailorsprings, Illinois\r\n689\r\nSalem, Illinois\r\n292\r\n548\r\nSandoval, Illinois\r\n247\r\nScott AFB, Illinois\r\n746\r\nSefton, Illinois\r\n347\r\nSesser, Illinois\r\n625\r\nShattuc, Illinois\r\n226\r\nShawneetown, Illinois\r\n269\r\nShipman, Illinois\r\n836\r\nShobonier, Illinois\r\n846\r\nSimpson, Illinois\r\n695\r\nSiu-C, Carbondale, Illinois\r\n453\r\n536\r\nSparta, Illinois\r\n443\r\nSt Elmo, Illinois\r\n829\r\nSt Francvale, Illinois\r\n948\r\nSt Jacob, Illinois\r\n644\r\n973\r\nSt Libory, Illinois\r\n768\r\nSt Peter, Illinois\r\n349\r\nStaunton, Illinois\r\n635\r\nSteeleville, Illinois\r\n965\r\nStonefort, Illinois\r\n777\r\nSummerfield, Illinois\r\n934\r\nSumner, Illinois\r\n936\r\nSwansea, Illinois\r\n277\r\nTamaroa, Illinois\r\n496\r\nTamms, Illinois\r\n747\r\nThebes, Illinois\r\n764\r\nThompsonvale, Illinois\r\n627\r\nTilden, Illinois\r\n587\r\nTrenton, Illinois\r\n224\r\nTroy, Illinois\r\n667\r\nUllin, Illinois\r\n845\r\nValmeyer, Illinois\r\n935\r\nVandalia, Illinois\r\n283\r\nVenedy, Illinois\r\n824\r\nVienna, Illinois\r\n658\r\nVillaridge, Illinois\r\n342\r\nWaltonvl, Illinois\r\n279\r\nWaterloo, Illinois\r\n939\r\nWayne City, Illinois\r\n895\r\nWendelin, Illinois\r\n752\r\nWest Frankfort, Illinois\r\n937\r\nWest Salem, Illinois\r\n456\r\nWestport, Illinois\r\n884\r\nWestview, Illinois\r\n538\r\nWfrankfort, Illinois\r\n932\r\nWillowhill, Illinois\r\n455\r\nWood River, Illinois\r\n254\r\nWoodburn, Illinois\r\n278\r\nWoodlawn, Illinois\r\n735\r\nWoodriv Rh, Illinois\r\n258\r\n259\r\n373\r\nWoodriv Wr, Illinois\r\n251\r\n255\r\nWorden, Illinois\r\n459\r\nXenia, Illinois\r\n678\r\nZeigler, Illinois\r\n596\r\n\u00035Unknown prefix code (618) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.619",
    "content": "Apple Valley, California\r\n240\r\n241\r\n242\r\n247\r\n946\r\nBaker, California\r\n733\r\nBarstow, California\r\n252\r\n577\r\n254\r\n255\r\n256\r\nBenton, California\r\n933\r\nBig Pine, California\r\n938\r\nBishop, California\r\n872\r\n873\r\n937\r\nBlythe, California\r\n921\r\n922\r\nBoron, California\r\n762\r\n769\r\nBorrego, California\r\n767\r\nBrawley, California\r\n344\r\n351\r\nBridgeport, California\r\n932\r\nCalexico, California\r\n357\r\n768\r\nCalifornia City, California\r\n373\r\nCalipatria, California\r\n348\r\n354\r\n359\r\nCamp Pendelton, California\r\n430\r\n725\r\nCampo, California\r\n478\r\nCarlsbad, California\r\n603\r\n431\r\n438\r\n929\r\n931\r\nChula Vista, California\r\n420\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n476\r\n482\r\n575\r\n585\r\n656\r\n661\r\n662\r\n690\r\n691\r\n413\r\n498\r\nCima, California\r\n928\r\nCoronado, California\r\n408\r\n435\r\n437\r\n522\r\n545\r\nCrowley Lake, California\r\n935\r\nDeath Valley, California\r\n786\r\nDel Mar, California\r\n500\r\n794\r\n259\r\n481\r\n755\r\n792\r\n793\r\nDesert Center, California\r\n227\r\nDesert Hot Springs, California\r\n251\r\n329\r\nDulzura, California\r\n468\r\nEagle Mountain, California\r\n392\r\nEarp, California\r\n665\r\nEl Cajon, California\r\n401\r\n590\r\n258\r\n390\r\n440\r\n441\r\n442\r\n443\r\n444\r\n447\r\n448\r\n449\r\n561\r\n562\r\n579\r\n588\r\n593\r\n596\r\nEl Centro, California\r\n370\r\n337\r\n339\r\n352\r\n353\r\nEl Mirage, California\r\n388\r\nEncinitas, California\r\n436\r\n510\r\n632\r\n633\r\n634\r\n753\r\n942\r\n943\r\n944\r\nEscondido, California\r\n432\r\n480\r\n489\r\n504\r\n737\r\n738\r\n739\r\n740\r\n741\r\n743\r\n745\r\n746\r\n747\r\nFallbrook, California\r\n516\r\n723\r\n728\r\n731\r\nFort Irwin, California\r\n386\r\nGeorge Air Force Base, California\r\n246\r\n269\r\nHarbison/Alpine, California\r\n445\r\n659\r\nHavasu Lake, California\r\n858\r\nHoltville, California\r\n356\r\nHomestead Valley, California\r\n364\r\nImperial, California\r\n355\r\nIndependence, California\r\n878\r\nIndio, California\r\n342\r\n347\r\n391\r\n393\r\n396\r\n397\r\n398\r\n399\r\n564\r\n771\r\n775\r\n777\r\n863\r\nInyokern, California\r\n377\r\nJacumba, California\r\n766\r\nJoshua Tree, California\r\n366\r\nJulian, California\r\n765\r\nJune Lake, California\r\n648\r\nKernville, California\r\n376\r\nLa Jolla, California\r\n404\r\n506\r\n508\r\n518\r\n550\r\n657\r\n658\r\n270\r\n272\r\n273\r\n274\r\n450\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n483\r\n488\r\n490\r\n534\r\n535\r\n539\r\n546\r\n551\r\n552\r\n554\r\n558\r\n581\r\n587\r\n597\r\n622\r\n625\r\nLa Mesa, California\r\n460\r\n461\r\n462\r\n463\r\n464\r\n465\r\n466\r\n469\r\n589\r\n660\r\n667\r\n668\r\n669\r\n670\r\n697\r\n698\r\nLee Vining, California\r\n647\r\nLenwood, California\r\n253\r\nLinda Vista, California\r\n268\r\n277\r\n278\r\n279\r\n292\r\n467\r\n492\r\n493\r\n494\r\n495\r\n496\r\n541\r\n560\r\n565\r\n569\r\n571\r\n573\r\n576\r\n627\r\n694\r\n972\r\n974\r\n502\r\n637\r\n654\r\nLake Isabella, California\r\n379\r\nLone Pine, California\r\n876\r\nLost Lake, California\r\n664\r\nLucerne Valley, California\r\n248\r\nMammoth Lakes, California\r\n924\r\n934\r\nMira Mesa, California\r\n684\r\n271\r\n530\r\n536\r\n537\r\n547\r\n549\r\n566\r\n578\r\n586\r\n621\r\n689\r\n693\r\n695\r\nMorongo Valley, California\r\n363\r\nMount Pass, California\r\n856\r\nNational City, California\r\n267\r\n336\r\n470\r\n472\r\n474\r\n475\r\n477\r\n479\r\n412\r\n416\r\nNeedles, California\r\n326\r\nNewberry, California\r\n257\r\nOceanside, California\r\n414\r\n433\r\n434\r\n439\r\n512\r\n709\r\n720\r\n721\r\n722\r\n729\r\n754\r\n757\r\n763\r\n945\r\n966\r\n967\r\nOcotillo, California\r\n358\r\nOlancha, California\r\n764\r\nPalm Springs, California\r\n250\r\n320\r\n321\r\n322\r\n323\r\n324\r\n325\r\n327\r\n328\r\n567\r\n770\r\n774\r\n778\r\n861\r\n864\r\n866\r\nPalm Desert, California\r\n340\r\n341\r\n343\r\n345\r\n346\r\n360\r\n568\r\n772\r\n773\r\n776\r\n779\r\n862\r\nPalo Verde, California\r\n854\r\nParker Dam, California\r\n663\r\nPauma Valley, California\r\n742\r\nPendleton, California\r\n385\r\nPine Creek, California\r\n387\r\nPine Valley, California\r\n473\r\nPinyon, California\r\n349\r\nPoway, California\r\n486\r\n679\r\n748\r\nRamona, California\r\n788\r\n789\r\nRancho Bernardo, California\r\n451\r\n485\r\n487\r\n592\r\n604\r\n673\r\n674\r\n675\r\nRancho Penasquitos, California\r\n484\r\n538\r\n672\r\nRancho Santa Fe, California\r\n513\r\n756\r\n759\r\nRandsburg, California\r\n374\r\nRidgecrest, California\r\n371\r\n375\r\n382\r\n384\r\n446\r\n499\r\n927\r\n939\r\nSalton, California\r\n394\r\n395\r\nSan Diego, California\r\n220\r\n276\r\n289\r\n406\r\n407\r\n417\r\n419\r\n505\r\n507\r\n514\r\n525\r\n532\r\n540\r\n548\r\n559\r\n624\r\n645\r\n701\r\n702\r\n717\r\n844\r\n853\r\n887\r\n888\r\n897\r\n898\r\n899\r\n925\r\n970\r\n971\r\n977\r\n980\r\n981\r\n985\r\n987\r\n988\r\n990\r\n991\r\n992\r\n993\r\n994\r\n995\r\n996\r\n997\r\n998\r\n999\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n229\r\n230\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n239\r\n260\r\n262\r\n263\r\n264\r\n265\r\n266\r\n275\r\n280\r\n281\r\n282\r\n283\r\n284\r\n285\r\n286\r\n287\r\n288\r\n290\r\n291\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n338\r\n491\r\n497\r\n521\r\n523\r\n524\r\n526\r\n527\r\n528\r\n529\r\n531\r\n533\r\n542\r\n543\r\n544\r\n553\r\n556\r\n557\r\n563\r\n570\r\n574\r\n580\r\n582\r\n583\r\n584\r\n594\r\n595\r\n685\r\n686\r\n687\r\n688\r\n692\r\n696\r\n699\r\n923\r\n926\r\n965\r\n968\r\n969\r\n973\r\n975\r\n978\r\n979\r\n982\r\n983\r\n984\r\n986\r\n989\r\nSan Marcos, California\r\n471\r\n591\r\n736\r\n744\r\n752\r\nSantee, California\r\n855\r\n895\r\nShoshone, California\r\n852\r\nSummit Valley, California\r\n389\r\nTrona, California\r\n372\r\nTwentynnplm, California\r\n361\r\n362\r\n367\r\n368\r\n865\r\nValley Center, California\r\n749\r\n751\r\nVictorville, California\r\n243\r\n244\r\n245\r\n947\r\n949\r\n261\r\n381\r\n951\r\n952\r\n953\r\n954\r\n955\r\n957\r\n961\r\n948\r\n956\r\nVista, California\r\n519\r\n732\r\n598\r\n599\r\n630\r\n631\r\n724\r\n726\r\n727\r\n758\r\n940\r\n941\r\nWarner Springs, California\r\n782\r\nWeldon, California\r\n378\r\nWinter Haven, California\r\n572\r\nWrightwdph, California\r\n868\r\nWrightwood, California\r\n249\r\n867\r\nYucca Valley, California\r\n228\r\n365\r\n369\r\n\u00035Unknown prefix code (619) - California\r\n"
  },
  {
    "path": "install/regions/regions.626",
    "content": "Temple City, California\r\n451\r\n\u00035Unknown prefix code (626) - California\r\n"
  },
  {
    "path": "install/regions/regions.651",
    "content": "East St. Paul, Minnesota\r\n731\r\nUnknown(xfer from 612), Minnesota\r\n205\r\n207\r\n213\r\n215\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n227\r\n228\r\n229\r\n232\r\n233\r\n234\r\n236\r\n239\r\n244\r\n251\r\n254\r\n255\r\n256\r\n257\r\n258\r\n265\r\n266\r\n267\r\n268\r\n274\r\n276\r\n281\r\n282\r\n286\r\n290\r\n291\r\n292\r\n293\r\n296\r\n297\r\n298\r\n303\r\n306\r\n310\r\n312\r\n345\r\n351\r\n380\r\n385\r\n387\r\n388\r\n393\r\n398\r\n402\r\n407\r\n408\r\n415\r\n426\r\n429\r\n430\r\n433\r\n436\r\n437\r\n438\r\n439\r\n450\r\n451\r\n453\r\n455\r\n457\r\n458\r\n459\r\n462\r\n464\r\n465\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n489\r\n490\r\n501\r\n503\r\n505\r\n523\r\n528\r\n552\r\n558\r\n565\r\n575\r\n578\r\n582\r\n583\r\n587\r\n592\r\n602\r\n603\r\n604\r\n605\r\n610\r\n628\r\n629\r\n631\r\n632\r\n633\r\n634\r\n635\r\n636\r\n637\r\n638\r\n639\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n649\r\n653\r\n659\r\n665\r\n674\r\n690\r\n691\r\n693\r\n695\r\n696\r\n697\r\n698\r\n699\r\n702\r\n704\r\n705\r\n714\r\n730\r\n733\r\n735\r\n736\r\n737\r\n738\r\n739\r\n748\r\n762\r\n764\r\n765\r\n766\r\n768\r\n769\r\n770\r\n771\r\n772\r\n773\r\n774\r\n776\r\n777\r\n778\r\n779\r\n787\r\n793\r\n796\r\n815\r\n842\r\n847\r\n848\r\n855\r\n908\r\n917\r\n918\r\n923\r\n962\r\n966\r\n967\r\n969\r\n982\r\n983\r\n989\r\n994\r\n\u00035Unknown prefix code (651) - Minnesota\r\n"
  },
  {
    "path": "install/regions/regions.671",
    "content": "Anderson AFB, Guam\r\n734\r\n477\r\n649\r\n\u00035Unknown prefix code (671) - Guam\r\n"
  },
  {
    "path": "install/regions/regions.678",
    "content": "New Numbers, Georgia\r\n000\r\n911\r\n\u00035Unknown prefix code (678) - Georgia\r\n"
  },
  {
    "path": "install/regions/regions.701",
    "content": "Abercrombe, North Dakota\r\n553\r\nAbsaraka, North Dakota\r\n896\r\nAdams, North Dakota\r\n944\r\nAlamo, North Dakota\r\n528\r\nAlexander, North Dakota\r\n828\r\nAlice, North Dakota\r\n689\r\nAmbrose, North Dakota\r\n982\r\nAmidon, North Dakota\r\n879\r\nAneta, North Dakota\r\n326\r\nAntler, North Dakota\r\n267\r\nArnegard, North Dakota\r\n586\r\nArthur, North Dakota\r\n967\r\nAshley, North Dakota\r\n288\r\nBalta, North Dakota\r\n542\r\nBeach, North Dakota\r\n872\r\nBelfield, North Dakota\r\n575\r\nBerthold, North Dakota\r\n453\r\nBeulah, North Dakota\r\n873\r\nBinford, North Dakota\r\n676\r\nBisbee, North Dakota\r\n656\r\nBismarck, North Dakota\r\n220\r\n221\r\n222\r\n223\r\n224\r\n226\r\n250\r\n255\r\n258\r\n663\r\n667\r\nBottineau, North Dakota\r\n228\r\nBowbells, North Dakota\r\n377\r\nBowdon, North Dakota\r\n962\r\nBowman, North Dakota\r\n523\r\nBrocket, North Dakota\r\n655\r\nBuffalo, North Dakota\r\n633\r\nButte, North Dakota\r\n626\r\nCando, North Dakota\r\n968\r\nCarpio, North Dakota\r\n468\r\nCarrington, North Dakota\r\n652\r\nCarson, North Dakota\r\n622\r\nCasselton, North Dakota\r\n347\r\nCavalier, North Dakota\r\n265\r\nCenter, North Dakota\r\n794\r\nChristine, North Dakota\r\n998\r\nColfax, North Dakota\r\n372\r\nColumbus, North Dakota\r\n939\r\nCooperston, North Dakota\r\n797\r\nCourtenay, North Dakota\r\n435\r\nCrary, North Dakota\r\n398\r\nCrete, North Dakota\r\n753\r\nCrosby, North Dakota\r\n965\r\nCrystal, North Dakota\r\n657\r\nDahlen, North Dakota\r\n384\r\nDazey, North Dakota\r\n733\r\nDeering, North Dakota\r\n728\r\nDes Lacs, North Dakota\r\n725\r\nDevils Lake, North Dakota\r\n662\r\nDickey, North Dakota\r\n778\r\nDickinson, North Dakota\r\n260\r\n261\r\n290\r\n330\r\n225\r\n227\r\n264\r\nDodge, North Dakota\r\n846\r\nDonnybrook, North Dakota\r\n482\r\nDouglas, North Dakota\r\n529\r\nDrake, North Dakota\r\n465\r\nDrayton, North Dakota\r\n454\r\nDunncenter, North Dakota\r\n548\r\nDunseith, North Dakota\r\n244\r\nEast Carlyle, North Dakota\r\n688\r\nEast Fairview, North Dakota\r\n744\r\nEast Sidney, North Dakota\r\n481\r\nEast Westby, North Dakota\r\n985\r\nEdgeley, North Dakota\r\n493\r\nEdinburg, North Dakota\r\n993\r\nEdmore, North Dakota\r\n644\r\nEdmunds, North Dakota\r\n285\r\nElgin, North Dakota\r\n584\r\nEllendale, North Dakota\r\n349\r\nEmerado, North Dakota\r\n739\r\n594\r\n747\r\nEmmet, North Dakota\r\n337\r\nEnderlin, North Dakota\r\n437\r\nEpping, North Dakota\r\n859\r\nEsmond, North Dakota\r\n249\r\nFairdale, North Dakota\r\n966\r\nFairmount, North Dakota\r\n474\r\nFargo, North Dakota\r\n271\r\n298\r\n232\r\n234\r\n235\r\n237\r\n238\r\n239\r\n241\r\n277\r\n280\r\n281\r\n282\r\n293\r\nFessenden, North Dakota\r\n547\r\nFinley, North Dakota\r\n524\r\nFlasher, North Dakota\r\n597\r\nFlaxton, North Dakota\r\n596\r\nForbes, North Dakota\r\n357\r\nFordville, North Dakota\r\n229\r\nForman, North Dakota\r\n724\r\nFort Yates, North Dakota\r\n854\r\nFort Ransom, North Dakota\r\n973\r\nFortuna, North Dakota\r\n834\r\nFredonia, North Dakota\r\n698\r\nFort Totten, North Dakota\r\n766\r\nFullerton, North Dakota\r\n375\r\nGackle, North Dakota\r\n485\r\nGalesburg, North Dakota\r\n488\r\nGardner, North Dakota\r\n484\r\nGarrison, North Dakota\r\n463\r\nGilby, North Dakota\r\n869\r\nGlen Ullin, North Dakota\r\n348\r\nGlenburn, North Dakota\r\n362\r\nGolden Valley, North Dakota\r\n983\r\nGoodrich, North Dakota\r\n884\r\nGrace City, North Dakota\r\n674\r\nGrafton, North Dakota\r\n360\r\n352\r\nGrand Forks, North Dakota\r\n732\r\n746\r\n772\r\n775\r\n777\r\n780\r\n781\r\n795\r\nGrassy Butte, North Dakota\r\n863\r\nGreat Bend, North Dakota\r\n545\r\nGrenora, North Dakota\r\n694\r\nGuelph, North Dakota\r\n783\r\nGwinner, North Dakota\r\n678\r\nHalliday, North Dakota\r\n938\r\nHampden, North Dakota\r\n868\r\nHankinson, North Dakota\r\n242\r\nHannaford, North Dakota\r\n769\r\nHarvey, North Dakota\r\n324\r\nHatton, North Dakota\r\n543\r\nHazelton, North Dakota\r\n782\r\nHazen, North Dakota\r\n748\r\nHebron, North Dakota\r\n878\r\nHettinger, North Dakota\r\n567\r\nHickson, North Dakota\r\n588\r\nHillsboro, North Dakota\r\n430\r\n436\r\nHoople, North Dakota\r\n894\r\nHope, North Dakota\r\n945\r\nHunter, North Dakota\r\n874\r\nInkster, North Dakota\r\n865\r\nJamestown, North Dakota\r\n269\r\n320\r\n339\r\n251\r\n252\r\n253\r\nJud, North Dakota\r\n685\r\nKarlsruhe, North Dakota\r\n525\r\nKathryn, North Dakota\r\n796\r\nKeene, North Dakota\r\n675\r\nKenmare, North Dakota\r\n385\r\nKilldeer, North Dakota\r\n764\r\nKindred, North Dakota\r\n428\r\nKintyre, North Dakota\r\n332\r\nKnox, North Dakota\r\n583\r\nKramer, North Dakota\r\n359\r\nKulm, North Dakota\r\n647\r\nLa Moure, North Dakota\r\n883\r\nLadd, North Dakota\r\n574\r\nLakota, North Dakota\r\n247\r\nLanda, North Dakota\r\n295\r\nLangdon, North Dakota\r\n256\r\nLankin, North Dakota\r\n593\r\nLansford, North Dakota\r\n784\r\nLarimore, North Dakota\r\n343\r\nLeeds, North Dakota\r\n466\r\nLehr, North Dakota\r\n378\r\nLeonard, North Dakota\r\n645\r\nLidgerwood, North Dakota\r\n538\r\nLignite, North Dakota\r\n933\r\nLinton, North Dakota\r\n254\r\nLisbon, North Dakota\r\n683\r\nLitchville, North Dakota\r\n762\r\nMaddock, North Dakota\r\n438\r\nMakoti, North Dakota\r\n726\r\nMandaree, North Dakota\r\n759\r\nManning, North Dakota\r\n573\r\nManvel, North Dakota\r\n696\r\nMarion, North Dakota\r\n669\r\nMarmon, North Dakota\r\n826\r\nMartin, North Dakota\r\n693\r\nMax, North Dakota\r\n679\r\nMaxbass, North Dakota\r\n268\r\nMayville, North Dakota\r\n786\r\nMcClusky, North Dakota\r\n363\r\nMcGregor, North Dakota\r\n546\r\nMcHenry, North Dakota\r\n785\r\nMcKenzie, North Dakota\r\n673\r\nMcVille, North Dakota\r\n322\r\nMedina, North Dakota\r\n486\r\nMedora, North Dakota\r\n623\r\nMercer, North Dakota\r\n447\r\nMerricourt, North Dakota\r\n396\r\nMetigoshe, North Dakota\r\n263\r\nMichigan, North Dakota\r\n259\r\nMilnor, North Dakota\r\n427\r\nMilton, North Dakota\r\n496\r\nMinnewakan, North Dakota\r\n473\r\nMinot, North Dakota\r\n240\r\n329\r\n720\r\n248\r\n838\r\n839\r\n852\r\n857\r\n858\r\nMinot Air Force Base, North Dakota\r\n723\r\n727\r\nMohall, North Dakota\r\n756\r\nMooreton, North Dakota\r\n274\r\nMott, North Dakota\r\n824\r\nMunich, North Dakota\r\n682\r\nNapoleon, North Dakota\r\n754\r\nNeche, North Dakota\r\n886\r\nNekoma, North Dakota\r\n949\r\nNelvik, North Dakota\r\n374\r\nNew Rockford, North Dakota\r\n947\r\nNew Salem, North Dakota\r\n843\r\nNew Town, North Dakota\r\n627\r\nNewburg, North Dakota\r\n272\r\nNew England, North Dakota\r\n579\r\nNiagara, North Dakota\r\n397\r\nNorth McLaughlin, North Dakota\r\n827\r\nNorth Britton, North Dakota\r\n443\r\nNorth Lemmon, North Dakota\r\n376\r\nNorth Veblen, North Dakota\r\n736\r\nNorth McIntosh, North Dakota\r\n276\r\nNome, North Dakota\r\n924\r\nNorth Morristown, North Dakota\r\n522\r\nNorth Wefington, North Dakota\r\n634\r\nNoonan, North Dakota\r\n925\r\nNorma, North Dakota\r\n467\r\nNorthhecla, North Dakota\r\n992\r\nNorthwood, North Dakota\r\n587\r\nOakes, North Dakota\r\n742\r\nOberon, North Dakota\r\n798\r\nPage, North Dakota\r\n668\r\nPark River, North Dakota\r\n284\r\nParshall, North Dakota\r\n862\r\nPekin, North Dakota\r\n296\r\nPembina, North Dakota\r\n825\r\nPenn, North Dakota\r\n393\r\nPetersburg, North Dakota\r\n345\r\nPettibone, North Dakota\r\n273\r\nPick City, North Dakota\r\n487\r\nPlaza, North Dakota\r\n497\r\nPortal, North Dakota\r\n926\r\nPowers Lake, North Dakota\r\n464\r\nRay, North Dakota\r\n568\r\nReeder, North Dakota\r\n853\r\nRegan, North Dakota\r\n286\r\nRegent, North Dakota\r\n563\r\nReynolds, North Dakota\r\n760\r\n847\r\nRhame, North Dakota\r\n279\r\nRichardton, North Dakota\r\n974\r\nRiverdale, North Dakota\r\n654\r\nRobinson, North Dakota\r\n392\r\nRock Lake, North Dakota\r\n266\r\nRolette, North Dakota\r\n246\r\nRolla, North Dakota\r\n477\r\nRoseglen, North Dakota\r\n743\r\nRoss, North Dakota\r\n755\r\nRound Prairie, North Dakota\r\n875\r\nRugby, North Dakota\r\n776\r\nRyder, North Dakota\r\n758\r\nSanborn, North Dakota\r\n646\r\nSarles, North Dakota\r\n697\r\nSawyer, North Dakota\r\n624\r\nScranton, North Dakota\r\n275\r\nSelfridge, North Dakota\r\n422\r\nSheldon, North Dakota\r\n882\r\nSherwood, North Dakota\r\n459\r\nSheyenne, North Dakota\r\n996\r\nSouth Prairie, North Dakota\r\n722\r\nSolen, North Dakota\r\n544\r\nSouris, North Dakota\r\n243\r\nSouthheart, North Dakota\r\n677\r\nSpencer, North Dakota\r\n848\r\nSquaw Gap, North Dakota\r\n565\r\nSaint Anthony, North Dakota\r\n445\r\nSaint Thomas, North Dakota\r\n520\r\n257\r\nStanley, North Dakota\r\n628\r\nStanton, North Dakota\r\n745\r\nStarkweather, North Dakota\r\n292\r\nSteele, North Dakota\r\n475\r\nSterling, North Dakota\r\n387\r\nStrasburg, North Dakota\r\n336\r\nStreeter, North Dakota\r\n424\r\nSykeston, North Dakota\r\n984\r\nTappen, North Dakota\r\n327\r\nThompson, North Dakota\r\n599\r\nTioga, North Dakota\r\n664\r\nTolley, North Dakota\r\n386\r\nTolna, North Dakota\r\n262\r\nTower City, North Dakota\r\n749\r\nTowner, North Dakota\r\n537\r\nTurtlelake, North Dakota\r\n448\r\nTuttle, North Dakota\r\n867\r\nUnderwood, North Dakota\r\n442\r\nUpham, North Dakota\r\n768\r\nValley City, North Dakota\r\n840\r\n845\r\nVelva, North Dakota\r\n338\r\nVenturia, North Dakota\r\n684\r\nVerona, North Dakota\r\n432\r\nWest Halstad, North Dakota\r\n457\r\nWest Nielsville, North Dakota\r\n942\r\nWahpeton, North Dakota\r\n640\r\n642\r\n671\r\nWalcott, North Dakota\r\n469\r\nWales, North Dakota\r\n283\r\nWalhalla, North Dakota\r\n549\r\nWarwick, North Dakota\r\n294\r\nWashburn, North Dakota\r\n462\r\nWatford City, North Dakota\r\n842\r\nWebster, North Dakota\r\n395\r\nWest Oslo, North Dakota\r\n699\r\nWest Climax, North Dakota\r\n856\r\nWesthope, North Dakota\r\n245\r\nWest Perley, North Dakota\r\n860\r\nWest Shelly, North Dakota\r\n887\r\nWildrose, North Dakota\r\n539\r\nWilliston, North Dakota\r\n570\r\n580\r\n572\r\n774\r\nWillow City, North Dakota\r\n366\r\nWilton, North Dakota\r\n734\r\nWindsor, North Dakota\r\n763\r\nWing, North Dakota\r\n943\r\nWishek, North Dakota\r\n452\r\nWoodworth, North Dakota\r\n752\r\nWyndmere, North Dakota\r\n439\r\nYork, North Dakota\r\n592\r\nYpsilanti, North Dakota\r\n489\r\nZap, North Dakota\r\n948\r\nZeeland, North Dakota\r\n423\r\n\u00035Unknown prefix code (701) - North Dakota\r\n"
  },
  {
    "path": "install/regions/regions.702",
    "content": "Alamo, Nevada\r\n725\r\nAustin, Nevada\r\n964\r\nBaker, Nevada\r\n234\r\nBattle Mount, Nevada\r\n635\r\nBeatty, Nevada\r\n553\r\nBlack Diamond, Nevada\r\n875\r\nBoulder City, Nevada\r\n293\r\n294\r\n502\r\nCaliente, Nevada\r\n726\r\nCarlin, Nevada\r\n754\r\nCarson City, Nevada\r\n246\r\n687\r\n882\r\n883\r\n884\r\n885\r\n887\r\nCarson Plains, Nevada\r\n241\r\nChurchill, Nevada\r\n629\r\nCortez Mountain, Nevada\r\n473\r\nCottonwood Creek, Nevada\r\n475\r\nCrescent Valley, Nevada\r\n468\r\nCrystal Bay, Nevada\r\n831\r\n832\r\n833\r\nDenio Trail, Nevada\r\n941\r\nDesert Valley, Nevada\r\n859\r\nDiamond Valley, Nevada\r\n769\r\nDuckwater Ct, Nevada\r\n863\r\nElko, Nevada\r\n778\r\n738\r\n753\r\nEly, Nevada\r\n289\r\nEmpire, Nevada\r\n557\r\nEureka, Nevada\r\n237\r\nFallon, Nevada\r\n423\r\n426\r\n427\r\n867\r\nFernley, Nevada\r\n575\r\nFishlake Valley, Nevada\r\n572\r\nGabbs, Nevada\r\n285\r\nGardnerville, Nevada\r\n265\r\n267\r\n782\r\n781\r\nGlenbrook, Nevada\r\n749\r\nGlendale, Nevada\r\n864\r\nGoldfield, Nevada\r\n485\r\nHawthorne, Nevada\r\n945\r\nHenderson, Nevada\r\n501\r\n558\r\n701\r\n564\r\n565\r\n566\r\nImlay, Nevada\r\n538\r\nIndian Springs, Nevada\r\n879\r\nJackpot, Nevada\r\n755\r\nJarbridge, Nevada\r\n488\r\nJean, Nevada\r\n503\r\n603\r\n874\r\nLake Mead, Nevada\r\n394\r\nLake Valley, Nevada\r\n724\r\nLas Vegas, Nevada\r\n221\r\n222\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n242\r\n244\r\n247\r\n255\r\n256\r\n259\r\n261\r\n262\r\n264\r\n371\r\n373\r\n375\r\n376\r\n431\r\n432\r\n433\r\n434\r\n436\r\n471\r\n474\r\n496\r\n497\r\n500\r\n592\r\n593\r\n596\r\n600\r\n631\r\n651\r\n655\r\n656\r\n657\r\n698\r\n699\r\n700\r\n891\r\n892\r\n893\r\n894\r\n895\r\n251\r\n252\r\n253\r\n254\r\n258\r\n295\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n367\r\n368\r\n369\r\n378\r\n379\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n389\r\n399\r\n424\r\n435\r\n437\r\n438\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n477\r\n486\r\n492\r\n594\r\n595\r\n597\r\n598\r\n599\r\n634\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n648\r\n649\r\n652\r\n653\r\n654\r\n658\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n739\r\n791\r\n792\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\n870\r\n871\r\n873\r\n876\r\n877\r\n878\r\n896\r\n897\r\n898\r\n923\r\n928\r\n929\r\nLathropwls, Nevada\r\n372\r\nLaughlin, Nevada\r\n299\r\n504\r\n704\r\n298\r\nLees Jiggs, Nevada\r\n744\r\nLovelock, Nevada\r\n273\r\nLund, Nevada\r\n238\r\nManhattan, Nevada\r\n487\r\nMarys River, Nevada\r\n472\r\nMcDermit, Nevada\r\n532\r\nMcGill, Nevada\r\n235\r\nMesquite, Nevada\r\n346\r\nMina, Nevada\r\n573\r\nMontello, Nevada\r\n776\r\nMountain City, Nevada\r\n763\r\nMount Charleston, Nevada\r\n872\r\nNelson, Nevada\r\n291\r\nNixon, Nevada\r\n574\r\nNorth Fork, Nevada\r\n758\r\nOrovada, Nevada\r\n272\r\nOsgood Trail, Nevada\r\n529\r\nOverton, Nevada\r\n397\r\n398\r\n484\r\nOwyhee, Nevada\r\n757\r\nPahrump, Nevada\r\n727\r\nPanaca, Nevada\r\n728\r\nParadise Valley, Nevada\r\n578\r\nPilot Valley, Nevada\r\n489\r\nPioche, Nevada\r\n962\r\nRed Rock, Nevada\r\n969\r\nReno, Nevada\r\n334\r\n686\r\n771\r\n856\r\n858\r\n828\r\n351\r\n353\r\n685\r\n857\r\n321\r\n322\r\n323\r\n324\r\n328\r\n329\r\n331\r\n333\r\n342\r\n343\r\n345\r\n348\r\n352\r\n354\r\n355\r\n356\r\n357\r\n358\r\n359\r\n626\r\n673\r\n674\r\n677\r\n688\r\n689\r\n741\r\n742\r\n746\r\n747\r\n784\r\n785\r\n786\r\n788\r\n789\r\n793\r\n825\r\n826\r\n827\r\n829\r\n844\r\n849\r\n851\r\n852\r\n853\r\n971\r\n972\r\nRound Mountain, Nevada\r\n377\r\nRuby Valley, Nevada\r\n779\r\nSand Springs, Nevada\r\n729\r\nSandy Valley, Nevada\r\n723\r\nSchurz, Nevada\r\n773\r\nSearchlight, Nevada\r\n297\r\nSilverpeak, Nevada\r\n937\r\nSilver Springs, Nevada\r\n577\r\nSmith Valley, Nevada\r\n465\r\nSpring Valley, Nevada\r\n591\r\nStateline, Nevada\r\n586\r\n588\r\n589\r\nSun Valley, Nevada\r\n425\r\nSutcliffe, Nevada\r\n476\r\nTonopah, Nevada\r\n374\r\n482\r\nTopaz Lake, Nevada\r\n266\r\nTuscarora, Nevada\r\n756\r\nUpper Muddy, Nevada\r\n865\r\nVirginia City, Nevada\r\n847\r\nWells, Nevada\r\n752\r\nWendover, Nevada\r\n664\r\n668\r\nWest Wendover, Nevada\r\n478\r\nWhite River, Nevada\r\n287\r\nWinnemucca, Nevada\r\n623\r\n625\r\nYerington, Nevada\r\n463\r\n\u00035Unknown prefix code (702) - Nevada\r\n"
  },
  {
    "path": "install/regions/regions.703",
    "content": "Alexandria, Virginia\r\n671\r\n765\r\n768\r\n780\r\nArcola, Virginia\r\n327\r\nArlington, Virginia\r\n522\r\n528\r\n578\r\n931\r\nBraddock, Virginia\r\n239\r\n250\r\n266\r\n278\r\n815\r\n830\r\nCentreville, Virginia\r\n631\r\nChantilly, Virginia\r\n803\r\nDale City, Virginia\r\n730\r\n590\r\n670\r\n680\r\n878\r\nDulles, Virginia\r\n661\r\nEngleside, Virginia\r\n339\r\n440\r\n455\r\n781\r\nFairfax, Virginia\r\n978\r\nFalls Church, Virginia\r\n532\r\n533\r\nHarrisonburg, Virginia\r\n535\r\nHaymarket, Virginia\r\n753\r\n754\r\nHerndon, Virginia\r\n488\r\n263\r\n378\r\n391\r\n430\r\n435\r\n437\r\n444\r\n476\r\n481\r\n689\r\n787\r\n817\r\n826\r\n860\r\n581\r\n707\r\n793\r\n814\r\nHillsville, Virginia\r\n728\r\nIndependent Hill, Virginia\r\n791\r\nLeesburg, Virginia\r\n443\r\n779\r\n729\r\n771\r\n777\r\nLorton, Virginia\r\n446\r\n551\r\n649\r\n690\r\nManassas, Virginia\r\n331\r\n792\r\n257\r\n330\r\n335\r\n361\r\n367\r\n368\r\n369\r\nNokesville, Virginia\r\n594\r\nOccoquan, Virginia\r\n492\r\n490\r\n491\r\n494\r\n497\r\nRoanoke(703), Virginia\r\n427\r\nSpringfield, Virginia\r\n971\r\nStaunton, Virginia\r\n844\r\nTriangle, Virginia\r\n441\r\n630\r\n221\r\n640\r\nWashington, DC, Virginia\r\n207\r\n218\r\n222\r\n235\r\n237\r\n241\r\n242\r\n243\r\n246\r\n247\r\n255\r\n256\r\n260\r\n264\r\n271\r\n273\r\n274\r\n276\r\n280\r\n281\r\n284\r\n285\r\n321\r\n325\r\n329\r\n351\r\n352\r\n354\r\n355\r\n356\r\n358\r\n359\r\n360\r\n370\r\n379\r\n385\r\n406\r\n415\r\n418\r\n425\r\n438\r\n442\r\n448\r\n450\r\n451\r\n461\r\n471\r\n478\r\n482\r\n486\r\n487\r\n503\r\n516\r\n517\r\n519\r\n521\r\n524\r\n525\r\n527\r\n534\r\n536\r\n538\r\n548\r\n549\r\n550\r\n553\r\n556\r\n557\r\n558\r\n560\r\n569\r\n573\r\n591\r\n602\r\n603\r\n620\r\n641\r\n642\r\n643\r\n644\r\n648\r\n658\r\n660\r\n664\r\n683\r\n684\r\n685\r\n691\r\n693\r\n695\r\n696\r\n697\r\n698\r\n706\r\n709\r\n712\r\n715\r\n719\r\n733\r\n734\r\n739\r\n742\r\n746\r\n749\r\n750\r\n751\r\n756\r\n758\r\n759\r\n760\r\n761\r\n764\r\n769\r\n790\r\n795\r\n799\r\n802\r\n818\r\n820\r\n821\r\n823\r\n824\r\n827\r\n834\r\n836\r\n838\r\n841\r\n845\r\n846\r\n847\r\n848\r\n849\r\n850\r\n866\r\n874\r\n875\r\n876\r\n883\r\n892\r\n893\r\n904\r\n912\r\n914\r\n920\r\n922\r\n934\r\n938\r\n941\r\n960\r\n968\r\n974\r\n979\r\n998\r\n675\r\n414\r\n545\r\n607\r\n614\r\n692\r\n204\r\n205\r\n315\r\n506\r\n813\r\n902\r\n903\r\n905\r\n936\r\n209\r\n212\r\n213\r\n214\r\n305\r\n306\r\n308\r\n309\r\n312\r\n313\r\n404\r\n405\r\n407\r\n408\r\n409\r\n412\r\n413\r\n419\r\n509\r\n514\r\n515\r\n518\r\n609\r\n617\r\n701\r\n702\r\n704\r\n705\r\n717\r\n801\r\n805\r\n806\r\n812\r\n816\r\n819\r\n907\r\n908\r\n909\r\n267\r\n318\r\n323\r\n324\r\n589\r\n708\r\n713\r\n757\r\n993\r\n\u00035Unknown prefix code (703) - Virginia\r\n"
  },
  {
    "path": "install/regions/regions.704",
    "content": "Albemarle, North Carolina\r\n982\r\n983\r\n985\r\nAltan, North Carolina\r\n764\r\nAnsonville, North Carolina\r\n826\r\nBadin, North Carolina\r\n422\r\nBelmont, North Carolina\r\n825\r\n829\r\nBessemer City, North Carolina\r\n629\r\nCharlotte, North Carolina\r\n329\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n341\r\n342\r\n343\r\n344\r\n346\r\n347\r\n348\r\n351\r\n353\r\n354\r\n355\r\n356\r\n357\r\n358\r\n359\r\n362\r\n364\r\n365\r\n366\r\n367\r\n368\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n382\r\n383\r\n384\r\n386\r\n388\r\n391\r\n392\r\n393\r\n394\r\n398\r\n399\r\n412\r\n423\r\n442\r\n512\r\n513\r\n514\r\n515\r\n516\r\n517\r\n518\r\n519\r\n521\r\n522\r\n523\r\n525\r\n527\r\n529\r\n531\r\n532\r\n533\r\n534\r\n535\r\n536\r\n537\r\n541\r\n542\r\n543\r\n544\r\n545\r\n547\r\n548\r\n549\r\n551\r\n552\r\n553\r\n554\r\n556\r\n558\r\n559\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\n567\r\n568\r\n570\r\n571\r\n572\r\n573\r\n574\r\n575\r\n576\r\n577\r\n578\r\n579\r\n581\r\n582\r\n583\r\n587\r\n588\r\n589\r\n590\r\n591\r\n593\r\n594\r\n595\r\n596\r\n597\r\n598\r\n599\r\n613\r\n614\r\n617\r\n623\r\n643\r\n651\r\n661\r\n671\r\n672\r\nCherryville, North Carolina\r\n435\r\n445\r\n447\r\nChina Grove\u00031/\u00032Landis, North Carolina\u00030\r\n855\r\n857\r\nChurchland, North Carolina\r\n762\r\nCleveland, North Carolina\r\n278\r\nConcord, North Carolina\r\n782\r\n783\r\n784\r\n785\r\n786\r\n788\r\n792\r\n793\r\n795\r\nCooleemee, North Carolina\r\n284\r\nDallas, North Carolina\r\n922\r\nCornelius\u00031/\u00032Davidson, North Carolina\r\n892\r\n896\r\nDenton, North Carolina\r\n869\r\nDenver, North Carolina\r\n483\r\nGastonia, North Carolina\r\n214\r\n215\r\n460\r\n616\r\n673\r\n808\r\n810\r\n813\r\n830\r\n833\r\n834\r\n836\r\n842\r\n852\r\n853\r\n854\r\n860\r\n861\r\n864\r\n865\r\n866\r\n867\r\n868\r\n913\r\n914\r\n915\r\n922\r\n923\r\nGoose Creek, North Carolina\r\n753\r\nGranite Quarry\u00031/\u00032Rockwell, North Carolina\u00030\r\n279\r\nGrover, North Carolina\r\n937\r\nHarmony, North Carolina\r\n546\r\nHarrisburg, North Carolina\r\n455\r\nHemby Bridge, North Carolina\r\n882\r\nHuntersville, North Carolina\r\n875\r\n948\r\nIjames, North Carolina\r\n492\r\nIndian Trail, North Carolina\r\n821\r\nKannapolis, North Carolina\r\n932\r\n933\r\n938\r\n939\r\nKings Mountain, North Carolina\r\n710\r\n730\r\n734\r\n739\r\nLattimore, North Carolina\r\n434\r\nLawndale, North Carolina\r\n312\r\nLawndale\u00031/\u00032Casar, North Carolina\u00030\r\n538\r\nLexington, North Carolina\r\n237\r\n239\r\n242\r\n243\r\n246\r\n249\r\n250\r\n352\r\n744\r\n858\r\n956\r\nLilesville, North Carolina\r\n848\r\nLincolnton, North Carolina\r\n276\r\n732\r\n735\r\n736\r\n740\r\n742\r\n745\r\n748\r\nLocust, North Carolina\r\n888\r\nLowell, North Carolina\r\n819\r\n823\r\n824\r\nMatthews, North Carolina\r\n841\r\n845\r\n846\r\n847\r\n849\r\nMocksville, North Carolina\r\n634\r\nMonroe, North Carolina\r\n221\r\n282\r\n283\r\n289\r\n291\r\n292\r\n296\r\nMooresville, North Carolina\r\n662\r\n663\r\n664\r\nMorven, North Carolina\r\n851\r\nMount Holly, North Carolina\r\n822\r\n827\r\nMount Pleasant, North Carolina\r\n436\r\nNew Hope, North Carolina\r\n592\r\nNew London, North Carolina\r\n463\r\nNew Salem, North Carolina\r\n385\r\nNewton, North Carolina\r\n462\r\n464\r\n465\r\n466\r\nNortheastern Charlotte, North Carolina\r\n510\r\nNorwood, North Carolina\r\n474\r\nOakboro, North Carolina\r\n485\r\nPeachland\u00031/\u00032Polkton, North Carolina\u00030\r\n272\r\nPineville, North Carolina\r\n889\r\nReeds, North Carolina\r\n787\r\nSalisbury, North Carolina\r\n633\r\n636\r\n637\r\n638\r\n639\r\n642\r\n647\r\nCleveland County\u00031/\u00032Shelby, North Carolina\r\n407\r\n414\r\n415\r\n418\r\n419\r\n470\r\n471\r\n472\r\n473\r\n476\r\n480\r\n481\r\n482\r\n484\r\n487\r\nSouth Crowders Creek, North Carolina\r\n228\r\nSouthmont, North Carolina\r\n798\r\nStanley, North Carolina\r\n263\r\nStatesville, North Carolina\r\n838\r\n871\r\n872\r\n873\r\n876\r\n878\r\n881\r\nStony Point, North Carolina\r\n585\r\nTroutman, North Carolina\r\n528\r\nUnion Grove, North Carolina\r\n539\r\nWadesboro, North Carolina\r\n694\r\n695\r\nWaxhaw, North Carolina\r\n843\r\nWelcome, North Carolina\r\n731\r\nWingate, North Carolina\r\n233\r\n\u00035Unknown prefix code (704) - North Carolina\u00030\r\n"
  },
  {
    "path": "install/regions/regions.705",
    "content": "Abitibi Cn, Ontario, Canada\r\n334\r\nAlban, Ontario, Canada\r\n857\r\nAlgoma Mills, Ontario, Canada\r\n849\r\nAlgonqn Park, Ontario, Canada\r\n633\r\nAlliston, Ontario, Canada\r\n435\r\nApsley, Ontario, Canada\r\n656\r\nAttawapskt, Ontario, Canada\r\n997\r\nAzilda, Ontario, Canada\r\n983\r\nBailieboro, Ontario, Canada\r\n939\r\nBala, Ontario, Canada\r\n762\r\nBarrie, Ontario, Canada\r\n725\r\n733\r\n739\r\n721\r\n722\r\n726\r\n728\r\n734\r\n737\r\nBatchwan Bay, Ontario, Canada\r\n882\r\nBaysville, Ontario, Canada\r\n767\r\nBeaverton, Ontario, Canada\r\n426\r\nBethany, Ontario, Canada\r\n277\r\nBiscotasng, Ontario, Canada\r\n239\r\nBlezard Valley, Ontario, Canada\r\n897\r\nBlind River, Ontario, Canada\r\n356\r\nBluewater, Ontario, Canada\r\n361\r\nBobcaygeon, Ontario, Canada\r\n738\r\nBonfield, Ontario, Canada\r\n776\r\nBorden Ang, Ontario, Canada\r\n423\r\n424\r\nBracebridge, Ontario, Canada\r\n646\r\n645\r\nBrechin, Ontario, Canada\r\n484\r\nBridgeno, Ontario, Canada\r\n292\r\nBritt, Ontario, Canada\r\n383\r\nBruce Mns, Ontario, Canada\r\n785\r\nBuckhorn, Ontario, Canada\r\n657\r\nBurksfalls, Ontario, Canada\r\n382\r\nBurleigh Falls, Ontario, Canada\r\n654\r\nCallander, Ontario, Canada\r\n752\r\nCalstock, Ontario, Canada\r\n463\r\nCambray, Ontario, Canada\r\n374\r\nCameron, Ontario, Canada\r\n359\r\nCampbellfield, Ontario, Canada\r\n653\r\nCannington, Ontario, Canada\r\n432\r\nCapreol, Ontario, Canada\r\n858\r\nCarnarvon, Ontario, Canada\r\n489\r\nCartier, Ontario, Canada\r\n965\r\nCavan, Ontario, Canada\r\n944\r\nChapleau, Ontario, Canada\r\n864\r\nChelmsford, Ontario, Canada\r\n855\r\nChristn I, Ontario, Canada\r\n247\r\nChub Lake, Ontario, Canada\r\n841\r\nCobalt, Ontario, Canada\r\n679\r\nCoboconk, Ontario, Canada\r\n454\r\nCochrane, Ontario, Canada\r\n272\r\nColdwater, Ontario, Canada\r\n686\r\nCollingwd, Ontario, Canada\r\n446\r\n444\r\n445\r\nConiston, Ontario, Canada\r\n694\r\nConnaught, Ontario, Canada\r\n363\r\nCookstown, Ontario, Canada\r\n458\r\nCreemore, Ontario, Canada\r\n466\r\nDesbarats, Ontario, Canada\r\n782\r\nDetour Lake, Ontario, Canada\r\n245\r\nDeux River, Ontario, Canada\r\n747\r\nDokis, Ontario, Canada\r\n763\r\nDorset, Ontario, Canada\r\n766\r\nDubreuilville, Ontario, Canada\r\n884\r\nDunsford, Ontario, Canada\r\n793\r\nDwight, Ontario, Canada\r\n635\r\nEarlton, Ontario, Canada\r\n563\r\nEcho Bay, Ontario, Canada\r\n248\r\nElk Lake, Ontario, Canada\r\n678\r\nElliot Lake, Ontario, Canada\r\n461\r\n848\r\nElmvale, Ontario, Canada\r\n322\r\nEmsdale, Ontario, Canada\r\n636\r\nEnglehart, Ontario, Canada\r\n544\r\nEspanola, Ontario, Canada\r\n869\r\nEstaire, Ontario, Canada\r\n695\r\nFauquier, Ontario, Canada\r\n339\r\nFenlon Falls, Ontario, Canada\r\n887\r\nField, Ontario, Canada\r\n758\r\nFoleyet, Ontario, Canada\r\n899\r\nFort Albany, Ontario, Canada\r\n278\r\nGarson, Ontario, Canada\r\n699\r\n693\r\nGogama, Ontario, Canada\r\n894\r\nGooderham, Ontario, Canada\r\n447\r\nGore Bay, Ontario, Canada\r\n282\r\nGoulais, Ontario, Canada\r\n649\r\nGowganda, Ontario, Canada\r\n624\r\nGravenhurst, Ontario, Canada\r\n687\r\nHaileybury, Ontario, Canada\r\n672\r\nHaliburton, Ontario, Canada\r\n457\r\nHanmer, Ontario, Canada\r\n969\r\nHastings, Ontario, Canada\r\n696\r\nHavelock, Ontario, Canada\r\n778\r\nHawk Junction, Ontario, Canada\r\n889\r\nHearst, Ontario, Canada\r\n362\r\n372\r\nHoney Hbr, Ontario, Canada\r\n756\r\nHuntsville, Ontario, Canada\r\n788\r\n789\r\nIron Bridge, Ontario, Canada\r\n843\r\nIroq Falls, Ontario, Canada\r\n232\r\n258\r\nIsland Lake, Ontario, Canada\r\n860\r\nKamiskotia, Ontario, Canada\r\n365\r\nKapuskasng, Ontario, Canada\r\n335\r\n337\r\nKashechwn, Ontario, Canada\r\n275\r\nKeene, Ontario, Canada\r\n295\r\nKillarney, Ontario, Canada\r\n287\r\nKinmount, Ontario, Canada\r\n488\r\nKirkfield, Ontario, Canada\r\n438\r\nKirklnd Lake, Ontario, Canada\r\n567\r\n568\r\nLaf Louisville, Ontario, Canada\r\n533\r\nLakefield, Ontario, Canada\r\n652\r\nLarder Lake, Ontario, Canada\r\n643\r\nLatchford, Ontario, Canada\r\n676\r\nLefroy, Ontario, Canada\r\n456\r\nLevack, Ontario, Canada\r\n966\r\nLindsay, Ontario, Canada\r\n878\r\n324\r\n328\r\nLively, Ontario, Canada\r\n692\r\nLt Britain, Ontario, Canada\r\n786\r\nLt Current, Ontario, Canada\r\n368\r\nMactier, Ontario, Canada\r\n375\r\nMagnetawan, Ontario, Canada\r\n387\r\nManitownng, Ontario, Canada\r\n859\r\nMarkstay, Ontario, Canada\r\n853\r\nMarten River, Ontario, Canada\r\n892\r\nMassey, Ontario, Canada\r\n865\r\nMatachewan, Ontario, Canada\r\n565\r\nMatheson, Ontario, Canada\r\n273\r\nMattawa, Ontario, Canada\r\n744\r\nMattice, Ontario, Canada\r\n364\r\nMcKellar, Ontario, Canada\r\n389\r\nMidland, Ontario, Canada\r\n526\r\n527\r\nMilford Bay, Ontario, Canada\r\n764\r\nMillbrook, Ontario, Canada\r\n932\r\nMindemoya, Ontario, Canada\r\n377\r\nMinden, Ontario, Canada\r\n286\r\nMissanable, Ontario, Canada\r\n234\r\nMoonbeam, Ontario, Canada\r\n367\r\nMoonstone, Ontario, Canada\r\n835\r\nMoosefacty, Ontario, Canada\r\n658\r\nMoosonee, Ontario, Canada\r\n336\r\nNephton, Ontario, Canada\r\n877\r\nNew Liskard, Ontario, Canada\r\n647\r\nNobel, Ontario, Canada\r\n342\r\nNoelville, Ontario, Canada\r\n898\r\nNorth Bay, Ontario, Canada\r\n494\r\n840\r\n472\r\n474\r\n476\r\n495\r\n497\r\nNorwood, Ontario, Canada\r\n639\r\nOakwood, Ontario, Canada\r\n953\r\nOba, Ontario, Canada\r\n883\r\nOmemee, Ontario, Canada\r\n799\r\nOpasatika, Ontario, Canada\r\n369\r\nOphir, Ontario, Canada\r\n736\r\nOpishng Lake, Ontario, Canada\r\n399\r\nOrillia, Ontario, Canada\r\n329\r\n323\r\n325\r\n326\r\n327\r\nOro, Ontario, Canada\r\n487\r\nOtter Lake, Ontario, Canada\r\n378\r\nParrysound, Ontario, Canada\r\n746\r\nPeawanuck, Ontario, Canada\r\n473\r\nPefferlaw, Ontario, Canada\r\n437\r\nPentangshn, Ontario, Canada\r\n549\r\nPeterborough, Ontario, Canada\r\n740\r\n741\r\n742\r\n743\r\n745\r\n748\r\n749\r\n876\r\nPineal Lake, Ontario, Canada\r\n861\r\nPowassan, Ontario, Canada\r\n724\r\nPort Au, Ontario, Canada\r\n366\r\nPort Carling, Ontario, Canada\r\n765\r\nPort Loring, Ontario, Canada\r\n757\r\nPort Sydney, Ontario, Canada\r\n385\r\nPort McNicoll, Ontario, Canada\r\n534\r\nRamore, Ontario, Canada\r\n236\r\nRamsay, Ontario, Canada\r\n299\r\nRedbridge, Ontario, Canada\r\n663\r\nRestoule, Ontario, Canada\r\n729\r\nRosseau, Ontario, Canada\r\n732\r\nSouth Porcpine, Ontario, Canada\r\n235\r\nS Marie, Ontario, Canada\r\n541\r\n941\r\nSault Ste. Marie, Ontario, Canada\r\n253\r\n254\r\n256\r\n759\r\n777\r\n779\r\n942\r\n945\r\n946\r\n949\r\nSearchmont, Ontario, Canada\r\n781\r\nSebright, Ontario, Canada\r\n833\r\nSevern Bdg, Ontario, Canada\r\n689\r\nSilverwater, Ontario, Canada\r\n283\r\nSmall Rock, Ontario, Canada\r\n338\r\nSouthriver, Ontario, Canada\r\n386\r\nSpanish, Ontario, Canada\r\n844\r\nSprucedale, Ontario, Canada\r\n685\r\nSaint Charles, Ontario, Canada\r\n867\r\nSaint Jos, Ontario, Canada\r\n246\r\nStayner, Ontario, Canada\r\n428\r\nStroud, Ontario, Canada\r\n431\r\n436\r\nSturgn Falls, Ontario, Canada\r\n753\r\nSudbury, Ontario, Canada\r\n525\r\n670\r\n677\r\n522\r\n523\r\n524\r\n560\r\n566\r\n671\r\n673\r\n674\r\n675\r\n682\r\n688\r\nSultan, Ontario, Canada\r\n233\r\nSunderland, Ontario, Canada\r\n357\r\nSundridge, Ontario, Canada\r\n384\r\nSwastika, Ontario, Canada\r\n642\r\nTemagami, Ontario, Canada\r\n237\r\n569\r\nThessalon, Ontario, Canada\r\n842\r\nThorne, Ontario, Canada\r\n981\r\nTimmins, Ontario, Canada\r\n360\r\n264\r\n267\r\n268\r\nTrout Creek, Ontario, Canada\r\n723\r\nUdora, Ontario, Canada\r\n228\r\nVerner, Ontario, Canada\r\n594\r\nVirginiaton, Ontario, Canada\r\n634\r\nWest Guilford, Ontario, Canada\r\n754\r\nWarkworth, Ontario, Canada\r\n924\r\nWarren, Ontario, Canada\r\n967\r\nWasaga Beach, Ontario, Canada\r\n429\r\nWaubaushen, Ontario, Canada\r\n538\r\nWawa, Ontario, Canada\r\n856\r\nWestree, Ontario, Canada\r\n263\r\nWhitefish Falls, Ontario, Canada\r\n285\r\nWhitefish, Ontario, Canada\r\n866\r\nWilberfrce, Ontario, Canada\r\n448\r\nWindermere, Ontario, Canada\r\n769\r\nWoodville, Ontario, Canada\r\n439\r\n\u00035Unknown prefix code (705) - Ontario, Canada\r\n"
  },
  {
    "path": "install/regions/regions.706",
    "content": "Appling, Georgia\r\n541\r\nAthens, Georgia\r\n201\r\n208\r\n338\r\n353\r\n354\r\n357\r\n369\r\n476\r\n540\r\n542\r\n543\r\n546\r\n548\r\n549\r\n613\r\nAtlanta, Georgia\r\n221\r\n555\r\nAugusta, Georgia\r\n481\r\n560\r\n650\r\n667\r\n721\r\n722\r\n724\r\n731\r\n732\r\n733\r\n736\r\n737\r\n738\r\n771\r\n790\r\n791\r\n792\r\n793\r\n796\r\n798\r\n821\r\n823\r\n825\r\n826\r\n828\r\n829\r\n831\r\n849\r\n855\r\n860\r\n863\r\n868\r\n564\r\nBatesville, Georgia\r\n947\r\nBig Canoe, Georgia\r\n268\r\n579\r\nBlairsville, Georgia\r\n745\r\nBlue Ridge, Georgia\r\n632\r\nBraselton, Georgia\r\n654\r\nBuchanan, Georgia\r\n646\r\nCalhoun, Georgia\r\n602\r\n625\r\n629\r\nCanton, Georgia\r\n345\r\n479\r\n720\r\nCarlton, Georgia\r\n797\r\nCarnesville, Georgia\r\n384\r\nCartecay, Georgia\r\n273\r\nCave Spring, Georgia\r\n777\r\nChatsworth, Georgia\r\n517\r\n695\r\nChickamuga, Georgia\r\n375\r\nClarkesville, Georgia\r\n754\r\nClayton, Georgia\r\n782\r\nCleveland, Georgia\r\n219\r\n865\r\nCohutta, Georgia\r\n694\r\nColbert, Georgia\r\n788\r\nColumbus, Georgia\r\n322\r\n323\r\n324\r\n326\r\n327\r\n366\r\n544\r\n545\r\n561\r\n563\r\n568\r\n569\r\n571\r\n575\r\n576\r\n577\r\n596\r\n641\r\n649\r\n660\r\n682\r\n685\r\n687\r\n689\r\n966\r\n640\r\nComer, Georgia\r\n783\r\nCommerce, Georgia\r\n335\r\nConcord, Georgia\r\n495\r\nCornelia, Georgia\r\n776\r\n778\r\nCrawfordville, Georgia\r\n456\r\nCusseta, Georgia\r\n989\r\nDahlonega, Georgia\r\n864\r\nDalton, Georgia\r\n217\r\n226\r\n259\r\n260\r\n272\r\n275\r\n277\r\n278\r\nDanielsville, Georgia\r\n795\r\nDawsonville, Georgia\r\n216\r\n265\r\nDial, Georgia\r\n838\r\nDilardmtcy, Georgia\r\n746\r\nEastanolle, Georgia\r\n779\r\nEatonton, Georgia\r\n484\r\n485\r\nElberton, Georgia\r\n213\r\n283\r\nEllijay, Georgia\r\n276\r\n635\r\n636\r\nFairmount, Georgia\r\n337\r\nFranklin, Georgia\r\n675\r\nGay, Georgia\r\n538\r\nGeneva, Georgia\r\n269\r\nGibson, Georgia\r\n598\r\nGreensboro, Georgia\r\n453\r\nGreenville, Georgia\r\n672\r\nHamilton, Georgia\r\n628\r\nHarlem, Georgia\r\n556\r\nHartwell, Georgia\r\n376\r\n856\r\nHelen, Georgia\r\n878\r\nHephzibah, Georgia\r\n592\r\nHiawassee, Georgia\r\n896\r\nHigh Point, Georgia\r\n931\r\nHogansville, Georgia\r\n637\r\nHomer, Georgia\r\n677\r\nIla, Georgia\r\n789\r\nJasper, Georgia\r\n407\r\n691\r\n692\r\nJefferson, Georgia\r\n367\r\nKensington, Georgia\r\n539\r\nLa Fayette, Georgia\r\n638\r\nLa Grange, Georgia\r\n812\r\n845\r\n882\r\n883\r\n884\r\n302\r\n880\r\nLakewood, Georgia\r\n374\r\nLavonia, Georgia\r\n356\r\nLexington, Georgia\r\n743\r\nLincolnton, Georgia\r\n359\r\nLyerly, Georgia\r\n895\r\nMadison, Georgia\r\n342\r\nManchester, Georgia\r\n846\r\nMaxeys, Georgia\r\n759\r\nMaysville, Georgia\r\n652\r\nMcCaysville, Georgia\r\n492\r\nMenlo, Georgia\r\n862\r\nMetasville, Georgia\r\n293\r\nMonroe, Georgia\r\n207\r\n267\r\nMonticello, Georgia\r\n468\r\nNicholson, Georgia\r\n757\r\nNoble, Georgia\r\n764\r\nPendergrass, Georgia\r\n693\r\nPine Mountain, Georgia\r\n663\r\nRanger, Georgia\r\n334\r\nRayle, Georgia\r\n274\r\nRing Gold, Georgia\r\n935\r\n937\r\n965\r\nRising Fawn, Georgia\r\n462\r\nRome, Georgia\r\n232\r\n234\r\n235\r\n236\r\n290\r\n291\r\n295\r\n506\r\n802\r\n237\r\nRossville, Georgia\r\n630\r\n820\r\n858\r\n861\r\n866\r\n891\r\nRoyston, Georgia\r\n245\r\nRutledge, Georgia\r\n318\r\n557\r\nSparta, Georgia\r\n444\r\nSuches, Georgia\r\n747\r\nSummerville, Georgia\r\n857\r\nTalbotton, Georgia\r\n665\r\nTennga, Georgia\r\n328\r\nThomaston, Georgia\r\n647\r\n648\r\nThomson, Georgia\r\n595\r\n597\r\nTignall, Georgia\r\n285\r\nToccoa, Georgia\r\n282\r\n886\r\nTrenton, Georgia\r\n657\r\nTrion, Georgia\r\n734\r\nTunnel Hill, Georgia\r\n673\r\nUnion Point, Georgia\r\n486\r\nVillanow, Georgia\r\n397\r\nWarm Springs, Georgia\r\n655\r\nWarrenton, Georgia\r\n465\r\nWashington, Georgia\r\n678\r\nWatkinsville, Georgia\r\n769\r\nWaverly H, Georgia\r\n582\r\nWaynesboro, Georgia\r\n437\r\n554\r\nWest Brow, Georgia\r\n398\r\nWest Point, Georgia\r\n585\r\n643\r\n645\r\nWhite Plains, Georgia\r\n467\r\nWinder, Georgia\r\n307\r\n867\r\nWinterville, Georgia\r\n742\r\nWoodbury, Georgia\r\n553\r\nWoodland, Georgia\r\n674\r\nWrens, Georgia\r\n547\r\nYatesville, Georgia\r\n472\r\nYoungharis, Georgia\r\n379\r\nZebulon, Georgia\r\n567\r\n\u00035Unknown prefix code (706) - Georgia\r\n"
  },
  {
    "path": "install/regions/regions.707",
    "content": "Alderpoint, California\r\n926\r\nAnnapolis, California\r\n886\r\nArcata, California\r\n822\r\n826\r\n839\r\nBenicia, California\r\n745\r\n746\r\n747\r\nBlue Lake, California\r\n668\r\nBodega Bay, California\r\n875\r\nBoonville, California\r\n895\r\nBridgeville, California\r\n777\r\nCalistoga, California\r\n942\r\nCazadero, California\r\n632\r\nClearlkoak, California\r\n998\r\nCloverdale, California\r\n894\r\nCobb Mountain, California\r\n928\r\nCovelo, California\r\n983\r\nCrescent City, California\r\n457\r\n458\r\n464\r\n465\r\n951\r\nElk, California\r\n877\r\nEureka, California\r\n441\r\n498\r\n499\r\n269\r\n442\r\n443\r\n444\r\n445\r\nFairfield Sun, California\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n437\r\n438\r\n864\r\n434\r\n435\r\n863\r\nFerndale, California\r\n786\r\nForestville, California\r\n887\r\nFort Bragg, California\r\n961\r\n964\r\nFortuna, California\r\n725\r\nGarberville, California\r\n923\r\nGeyserville, California\r\n857\r\nGualala, California\r\n884\r\nGuerneville, California\r\n869\r\nHealdsburg, California\r\n431\r\n433\r\nHopland, California\r\n744\r\nHydesville, California\r\n768\r\nKelseyville, California\r\n277\r\n279\r\nKenwood, California\r\n833\r\nKlamath, California\r\n482\r\nLakeport, California\r\n262\r\n263\r\nLaytonville, California\r\n984\r\nLeggett, California\r\n925\r\nLake Berryesa, California\r\n966\r\nLoleta, California\r\n733\r\nLower Lake, California\r\n994\r\n995\r\nMad River, California\r\n574\r\nMendocino, California\r\n937\r\nMiddletown, California\r\n987\r\nMiranda, California\r\n943\r\nMonte Rio, California\r\n865\r\nNapa, California\r\n254\r\n259\r\n224\r\n226\r\n252\r\n253\r\n255\r\n257\r\n258\r\nNice, California\r\n274\r\nOccidental, California\r\n874\r\nOrick, California\r\n488\r\nPepperwood, California\r\n722\r\nPetaluma, California\r\n762\r\n763\r\n765\r\n769\r\n778\r\n664\r\n792\r\n794\r\n795\r\nPetrolia, California\r\n629\r\nPiercy, California\r\n247\r\nPointarena, California\r\n882\r\nPotter Valley, California\r\n743\r\nRio Dell, California\r\n764\r\nRio Vista, California\r\n374\r\nSanta Rosa, California\r\n270\r\n321\r\n322\r\n323\r\n324\r\n480\r\n483\r\n484\r\n486\r\n489\r\n491\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n537\r\n538\r\n539\r\n542\r\n543\r\n544\r\n545\r\n546\r\n571\r\n573\r\n575\r\n576\r\n577\r\n578\r\n579\r\n584\r\n585\r\n586\r\n793\r\n952\r\n953\r\n972\r\n973\r\nSebastopol, California\r\n823\r\n824\r\n829\r\nSmith River, California\r\n487\r\nSonoma, California\r\n935\r\n938\r\n939\r\n996\r\nSaint Helena, California\r\n963\r\n965\r\n967\r\nTimber Cove, California\r\n785\r\n847\r\nTomales, California\r\n878\r\nTrinidad, California\r\n677\r\nUkiah, California\r\n462\r\n463\r\n468\r\n485\r\nUpper Lake, California\r\n275\r\nVacaville, California\r\n452\r\n453\r\n650\r\n446\r\n447\r\n448\r\n449\r\n451\r\nVallejo, California\r\n556\r\n558\r\n641\r\n647\r\n552\r\n553\r\n554\r\n557\r\n642\r\n643\r\n644\r\n645\r\n646\r\n648\r\n649\r\nValleyford, California\r\n876\r\nWeott, California\r\n946\r\nWhitethorn, California\r\n986\r\nWillits, California\r\n459\r\nWindsor, California\r\n836\r\n837\r\n838\r\nYountville, California\r\n944\r\n\u00035Unknown prefix code (707) - California\r\n"
  },
  {
    "path": "install/regions/regions.708",
    "content": "Algonquin, Illinois\r\n854\r\n658\r\nAntioch, Illinois\r\n838\r\n395\r\nArlington Heights, Illinios\r\n253\r\n506\r\n577\r\n818\r\n870\r\n255\r\n259\r\n342\r\n392\r\n394\r\n398\r\n435\r\n590\r\n632\r\n670\r\nAurora, Illinois\r\n585\r\n820\r\n851\r\n907\r\n978\r\n264\r\n844\r\n859\r\n897\r\n906\r\n801\r\n892\r\n896\r\n898\r\nBarrington, Illinios\r\n304\r\n382\r\n277\r\n381\r\n842\r\n248\r\n765\r\nBartlett, Illinois\r\n213\r\n289\r\n372\r\n483\r\n830\r\n837\r\nBatavia Gn, Illinios\r\n406\r\n840\r\n879\r\nBeecher, Illinois\r\n946\r\nBellwood Hill, Illinois\r\n236\r\n493\r\n649\r\n449\r\nBellwood, Illinios\r\n544\r\n547\r\nBensenville, Illinios\r\n350\r\n595\r\n766\r\n860\r\n238\r\n616\r\nBerwyn, Illinois\r\n484\r\n795\r\n749\r\n788\r\nBig Rock, Illinios\r\n556\r\nBlue Island, Illinios\r\n385\r\n389\r\n597\r\nBlue Island, Illinois\r\n535\r\n687\r\n239\r\n371\r\n388\r\n396\r\n489\r\nBolingbrook, Illinios\r\n739\r\n972\r\nBrookfield, Illinios\r\n387\r\n485\r\nCalumet City, Illinios\r\n730\r\n868\r\n862\r\n891\r\nCary, Illinois\r\n516\r\n639\r\nChicago, Illinois\r\n796\r\n667\r\n867\r\n758\r\n720\r\n754\r\n756\r\n481\r\n503\r\n748\r\n709\r\n747\r\n755\r\n757\r\nCicero, Illinois\r\n222\r\n780\r\n652\r\n656\r\n863\r\nCrete, Illinois\r\n672\r\nDeerfield, Illinois\r\n374\r\n405\r\n317\r\n940\r\n945\r\n948\r\nDes Plaines, Illinios\r\n296\r\n298\r\n391\r\n294\r\n297\r\n299\r\n390\r\n635\r\n699\r\n768\r\n803\r\n824\r\n827\r\nDowners Grove, Illinois\r\n910\r\n512\r\n515\r\n719\r\n852\r\n964\r\n968\r\n971\r\n241\r\n275\r\n322\r\n434\r\n663\r\n769\r\n810\r\n829\r\n960\r\n963\r\n969\r\nDundee, Illinois\r\n428\r\n580\r\n836\r\n286\r\n645\r\n426\r\n551\r\nElburn, Illinois\r\n365\r\nElgin, Illinois\r\n468\r\n622\r\n695\r\n697\r\n741\r\n742\r\n888\r\n931\r\nElk Grove, Illinois\r\n427\r\n734\r\n956\r\n981\r\n996\r\n228\r\n290\r\n364\r\n437\r\n439\r\n593\r\n640\r\n806\r\n952\r\nElmhurst, Illinois\r\n543\r\n628\r\n530\r\n782\r\n833\r\n941\r\n993\r\n279\r\n617\r\n832\r\n834\r\nEvanston, Illinois\r\n328\r\n332\r\n467\r\n492\r\n570\r\n733\r\n864\r\n866\r\n869\r\n475\r\n491\r\nForest O, Illinois\r\n209\r\n488\r\n771\r\n366\r\nFox Lake, Illinois\r\n973\r\n587\r\nFranklin Park, Illinios\r\n451\r\n671\r\n288\r\n455\r\n678\r\n928\r\nGeneva, Illinois\r\n845\r\n208\r\n232\r\nGlen Ellyn, Illinios\r\n469\r\n790\r\n858\r\n545\r\nGlencoe Wn, Illinois\r\n835\r\nGlenview, Illinois\r\n486\r\n646\r\n657\r\n729\r\n724\r\n998\r\nGrays Lake, Illinois\r\n223\r\n548\r\nHalfday Wh, Illinios\r\n634\r\n913\r\n793\r\n883\r\nHampshire, Illinios\r\n683\r\nHarvey, Illinois\r\n225\r\n331\r\n339\r\n596\r\n335\r\n210\r\n333\r\nHighland Park, Illinios\r\n432\r\n266\r\n433\r\n831\r\n926\r\nHinsdale, Illinois\r\n230\r\n280\r\n323\r\n528\r\n642\r\n655\r\n703\r\n789\r\n794\r\n822\r\n828\r\n856\r\n887\r\n986\r\n218\r\n325\r\n571\r\n573\r\n575\r\n654\r\n850\r\n920\r\n954\r\n990\r\n408\r\n368\r\n572\r\n574\r\n684\r\n722\r\nHomewood, Illinois\r\n206\r\n799\r\n922\r\n798\r\n957\r\nHuntley, Illinois\r\n669\r\nItasca Bend, Illinois\r\n285\r\n775\r\n250\r\n773\r\nKaneville, Illinois\r\n557\r\nLa Grange, Illinois\r\n242\r\n276\r\n334\r\n341\r\n354\r\n379\r\n440\r\n476\r\n567\r\n610\r\n626\r\n638\r\n643\r\n661\r\n710\r\n738\r\n750\r\n846\r\n861\r\n886\r\n927\r\n936\r\n962\r\n984\r\n988\r\n994\r\n319\r\n352\r\n482\r\n579\r\nLake Villa, Illinois\r\n265\r\n356\r\nLake Forest, Illinois\r\n234\r\n295\r\n615\r\n735\r\nLake Zurich, Illinois\r\n320\r\n438\r\n540\r\n550\r\n726\r\nLansing, Illinios\r\n418\r\n474\r\n895\r\nLemont, Illinois\r\n378\r\n257\r\n252\r\n783\r\n759\r\nLibertyville, Illinios\r\n816\r\n362\r\n367\r\n522\r\n549\r\n680\r\n791\r\n918\r\nLombard, Illinois\r\n261\r\n268\r\n691\r\n932\r\n953\r\n495\r\n620\r\n627\r\n629\r\n916\r\nMaywood Bl, Illinios\r\n343\r\n345\r\n412\r\n531\r\n681\r\n865\r\n216\r\n344\r\n450\r\n786\r\n327\r\n338\r\n409\r\n562\r\n947\r\nMokena, Illinois\r\n479\r\nMonee Grove Park, Illinios\r\n534\r\n235\r\nMundelein, Illinios\r\n566\r\n949\r\n970\r\nNaperville, Illinios\r\n713\r\n355\r\n357\r\n369\r\n961\r\n985\r\n305\r\n416\r\n420\r\n527\r\n717\r\n778\r\n904\r\n983\r\n224\r\n245\r\n505\r\n955\r\n979\r\nNorthbrook, Illinois\r\n326\r\n402\r\n205\r\n480\r\n272\r\n281\r\n291\r\n309\r\n370\r\n376\r\n421\r\n454\r\n461\r\n498\r\n533\r\n559\r\n561\r\n564\r\n592\r\n621\r\n650\r\n651\r\n686\r\n721\r\n732\r\n753\r\n772\r\n817\r\n881\r\n890\r\n939\r\n944\r\n951\r\n975\r\n989\r\nOak F, Illinios\r\n560\r\nOak Lawn, Illinois\r\n346\r\n423\r\n425\r\n857\r\n422\r\n424\r\n499\r\n636\r\n599\r\n233\r\n430\r\n598\r\nOak Park, Illinois\r\n383\r\n386\r\n445\r\n660\r\n524\r\n848\r\nOrland, Illinois\r\n349\r\n873\r\n301\r\n403\r\n460\r\nOswego, Illinois\r\n554\r\nPalatine, Illinois\r\n523\r\n538\r\n576\r\n202\r\n358\r\n776\r\n991\r\n359\r\n705\r\n934\r\n397\r\n303\r\n925\r\nPalos Park, Illinios\r\n361\r\n974\r\n448\r\n923\r\nPark Ridge, Illinios\r\n692\r\n696\r\n698\r\n823\r\n825\r\n292\r\n318\r\n384\r\n518\r\n723\r\nPeotone, Illinios\r\n258\r\nPistakee Highlands, Illinios\r\n497\r\nPlano, Illinois\r\n552\r\n464\r\nRiverdale, Illinois\r\n321\r\n841\r\n849\r\n201\r\nRivergrove, Illinios\r\n453\r\n456\r\n324\r\n452\r\n583\r\n999\r\nRiverside, Illinios\r\n442\r\n447\r\nRoselle, Illinois\r\n220\r\n314\r\n347\r\n351\r\n436\r\n471\r\n565\r\n582\r\n603\r\n767\r\n804\r\n893\r\n917\r\n924\r\n977\r\n240\r\n307\r\n330\r\n517\r\n519\r\n529\r\n605\r\n612\r\n843\r\n882\r\n885\r\n894\r\n905\r\n980\r\n217\r\n254\r\n278\r\n284\r\n287\r\n337\r\n363\r\n373\r\n380\r\n413\r\n431\r\n494\r\n525\r\n542\r\n558\r\n602\r\n619\r\n624\r\n641\r\n644\r\n648\r\n706\r\n744\r\n751\r\n762\r\n826\r\n899\r\n987\r\n995\r\n997\r\n764\r\n807\r\n310\r\n490\r\n536\r\n880\r\n884\r\nRound Lake, Illinios\r\n740\r\n270\r\n546\r\nRiver Grove New, Illinois\r\n457\r\n521\r\nSkokie, Illinois\r\n329\r\n674\r\n676\r\n933\r\n470\r\n581\r\n965\r\n967\r\n673\r\n675\r\n677\r\n679\r\n966\r\n982\r\n647\r\nSaint Charles Glen, Illinois\r\n444\r\n513\r\n584\r\nSaint Charles, Illinios\r\n377\r\nSugar Grove, Illinois\r\n466\r\nSummit, Illinois\r\n269\r\n496\r\n594\r\n728\r\n921\r\n458\r\n563\r\nThorton, Illinios\r\n877\r\nTinleypark, Illinios\r\n429\r\n614\r\n532\r\n633\r\nWest Chicago, Illinois\r\n231\r\n876\r\nWarrenville, Illinios\r\n393\r\nWauconda, Illinois\r\n487\r\n526\r\nWaukegan, Illinois\r\n244\r\n249\r\n360\r\n623\r\n785\r\n855\r\n263\r\n336\r\n473\r\n662\r\n688\r\n578\r\n689\r\n935\r\n937\r\n938\r\nWest Chicago, Illinios\r\n293\r\nWheaton, Illinois\r\n221\r\n407\r\n462\r\n510\r\n653\r\n665\r\n682\r\n752\r\n260\r\n668\r\n690\r\nWheeling, Illinois\r\n459\r\n465\r\n520\r\n808\r\n215\r\n537\r\n541\r\nWilmette, Illinois\r\n251\r\n853\r\n256\r\nWinnetka, Illinois\r\n441\r\n446\r\n501\r\nWillow Spring, Illinois\r\n839\r\nWesternsp Lg, Illinios\r\n246\r\nWesternsp Lg, Illinois\r\n784\r\nYorkville, Illinios\r\n553\r\nZion, Illinois\r\n731\r\n746\r\n872\r\n\u00035Unknown prefix code (708) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.709",
    "content": "Arnolds Cove, Newfoundland, Canada\r\n463\r\nBadger, Newfoundland, Canada\r\n539\r\nBaie Verte, Newfoundland, Canada\r\n532\r\nBatteau, Newfoundland, Canada\r\n943\r\nBattle Harbor, Newfoundland, Canada\r\n972\r\nBay Largnt, Newfoundland, Canada\r\n461\r\nBay Roberts, Newfoundland, Canada\r\n786\r\nBeaumont, Newfoundland, Canada\r\n264\r\nBelleoram, Newfoundland, Canada\r\n881\r\nBellevue, Newfoundland, Canada\r\n442\r\nBell Island, Newfoundland, Canada\r\n488\r\nBenoits Cove, Newfoundland, Canada\r\n789\r\nBirchy Bay, Newfoundland, Canada\r\n659\r\nBishops Falls, Newfoundland, Canada\r\n258\r\nBlack Tickl, Newfoundland, Canada\r\n471\r\nBlack Duck Cove, Newfoundland, Canada\r\n877\r\nBona Vista, Newfoundland, Canada\r\n468\r\nBotwood, Newfoundland, Canada\r\n257\r\nBoyds Cove, Newfoundland, Canada\r\n656\r\nBranch, Newfoundland, Canada\r\n338\r\nBrentscove, Newfoundland, Canada\r\n661\r\nBrig Bay, Newfoundland, Canada\r\n247\r\nBrigus, Newfoundland, Canada\r\n528\r\nBrowns Arm, Newfoundland, Canada\r\n654\r\nBuchans, Newfoundland, Canada\r\n672\r\nBurgeo, Newfoundland, Canada\r\n886\r\nBurin, Newfoundland, Canada\r\n891\r\nBurlington, Newfoundland, Canada\r\n252\r\nCampbellton, Newfoundland, Canada\r\n261\r\nCape Broyle, Newfoundland, Canada\r\n432\r\nCarbonear, Newfoundland, Canada\r\n596\r\n945\r\nCarmanville, Newfoundland, Canada\r\n534\r\nCartwright, Newfoundland, Canada\r\n938\r\nCatalina, Newfoundland, Canada\r\n469\r\nCentreville, Newfoundland, Canada\r\n678\r\nChance Cove, Newfoundland, Canada\r\n460\r\nChange Island, Newfoundland, Canada\r\n621\r\nChapel Arm, Newfoundland, Canada\r\n592\r\nCharlotteton Bay, Newfoundland, Canada\r\n664\r\n949\r\nChurch Falls, Newfoundland, Canada\r\n925\r\nClarenville, Newfoundland, Canada\r\n427\r\n466\r\nClrks Head, Newfoundland, Canada\r\n676\r\nComfort Cove New, Newfoundland, Canada\r\n244\r\nCodroy, Newfoundland, Canada\r\n955\r\nCome By Chance, Newfoundland, Canada\r\n472\r\n542\r\nConche, Newfoundland, Canada\r\n622\r\nCooks Harbor, Newfoundland, Canada\r\n249\r\nCoombs Cove, Newfoundland, Canada\r\n887\r\nCorner Break, Newfoundland, Canada\r\n632\r\n634\r\n637\r\n639\r\n785\r\nCotrels Cove, Newfoundland, Canada\r\n485\r\nCow Head, Newfoundland, Canada\r\n243\r\nDanels Harbor, Newfoundland, Canada\r\n898\r\nDavis Inlet, Newfoundland, Canada\r\n478\r\nDeer Lake, Newfoundland, Canada\r\n635\r\nDegras, Newfoundland, Canada\r\n644\r\nEastport, Newfoundland, Canada\r\n677\r\nEnglee, Newfoundland, Canada\r\n866\r\nEnglshhbre, Newfoundland, Canada\r\n245\r\n888\r\nFairhaven, Newfoundland, Canada\r\n878\r\nFermeuse, Newfoundland, Canada\r\n363\r\nFleur Lys, Newfoundland, Canada\r\n253\r\nFlowers Cove, Newfoundland, Canada\r\n456\r\nFogo, Newfoundland, Canada\r\n266\r\nForteau, Newfoundland, Canada\r\n931\r\nFrancois, Newfoundland, Canada\r\n842\r\nFreshwater, Newfoundland, Canada\r\n227\r\nFrnchmn Is, Newfoundland, Canada\r\n934\r\nGambo, Newfoundland, Canada\r\n674\r\nGander, Newfoundland, Canada\r\n234\r\n256\r\n651\r\nGardencove, Newfoundland, Canada\r\n549\r\nGarnish, Newfoundland, Canada\r\n826\r\nGaultois, Newfoundland, Canada\r\n841\r\nGlenwood, Newfoundland, Canada\r\n679\r\nGlovertown, Newfoundland, Canada\r\n533\r\nGrand Bank, Newfoundland, Canada\r\n832\r\nGrandbruit, Newfoundland, Canada\r\n492\r\nGrand Falls, Newfoundland, Canada\r\n292\r\n489\r\nGrd Croque, Newfoundland, Canada\r\n423\r\nGreen Island, Newfoundland, Canada\r\n475\r\nGreenspond, Newfoundland, Canada\r\n269\r\nGrey River, Newfoundland, Canada\r\n296\r\nGriquet, Newfoundland, Canada\r\n623\r\nGreat Harbor, Newfoundland, Canada\r\n843\r\nHampden, Newfoundland, Canada\r\n455\r\nHarborbrtn, Newfoundland, Canada\r\n885\r\nHarbour Mn, Newfoundland, Canada\r\n229\r\nHare Bay, Newfoundland, Canada\r\n537\r\nHarrys Harbor, Newfoundland, Canada\r\n624\r\nHartsdlght, Newfoundland, Canada\r\n588\r\nHawkes Bay, Newfoundland, Canada\r\n248\r\nHermitage, Newfoundland, Canada\r\n883\r\nHickmans Harbor, Newfoundland, Canada\r\n547\r\nHillgrade, Newfoundland, Canada\r\n628\r\nHillview, Newfoundland, Canada\r\n546\r\nHopedale, Newfoundland, Canada\r\n933\r\nHorwood, Newfoundland, Canada\r\n671\r\nHappy Valley, Newfoundland, Canada\r\n896\r\nHrts Cntnt, Newfoundland, Canada\r\n583\r\nInd Tickle, Newfoundland, Canada\r\n942\r\nIsauxmorts, Newfoundland, Canada\r\n698\r\nIsland Harbor, Newfoundland, Canada\r\n863\r\nJackson Arm, Newfoundland, Canada\r\n459\r\nJamestown, Newfoundland, Canada\r\n473\r\nJeffreys, Newfoundland, Canada\r\n645\r\nJoe Btsarm, Newfoundland, Canada\r\n658\r\nKingpoint, Newfoundland, Canada\r\n268\r\nKings Cove, Newfoundland, Canada\r\n447\r\nLa Scie, Newfoundland, Canada\r\n675\r\nLadle Cove, Newfoundland, Canada\r\n670\r\nLamaline, Newfoundland, Canada\r\n857\r\nLanse Loup, Newfoundland, Canada\r\n927\r\nLapoile, Newfoundland, Canada\r\n496\r\nLark Harbor, Newfoundland, Canada\r\n681\r\nLbr City, Newfoundland, Canada\r\n282\r\n285\r\n944\r\nLedg Tckls, Newfoundland, Canada\r\n483\r\nLewisporte, Newfoundland, Canada\r\n535\r\nLittle Bay, Newfoundland, Canada\r\n626\r\n267\r\nLong Harbor, Newfoundland, Canada\r\n228\r\nLong Pond, Newfoundland, Canada\r\n781\r\n834\r\nLourdes, Newfoundland, Canada\r\n642\r\nLow Is, Newfoundland, Canada\r\n584\r\nLittle Harbor, Newfoundland, Canada\r\n465\r\nLittle Hrt, Newfoundland, Canada\r\n548\r\nLumsden, Newfoundland, Canada\r\n530\r\nMain Brook, Newfoundland, Canada\r\n865\r\nMakkovik, Newfoundland, Canada\r\n923\r\nMarys Harbor, Newfoundland, Canada\r\n921\r\nMarystown, Newfoundland, Canada\r\n894\r\n279\r\nMc Callum, Newfoundland, Canada\r\n846\r\nMcIvers, Newfoundland, Canada\r\n688\r\nMillertown, Newfoundland, Canada\r\n852\r\nMilltown, Newfoundland, Canada\r\n882\r\nMingsbight, Newfoundland, Canada\r\n254\r\nMonkstown, Newfoundland, Canada\r\n356\r\nMonroe, Newfoundland, Canada\r\n663\r\nMoretons Harbor, Newfoundland, Canada\r\n684\r\nMorris Arm, Newfoundland, Canada\r\n653\r\nMount Carmel, Newfoundland, Canada\r\n521\r\nMount Pearl, Newfoundland, Canada\r\n747\r\nMusgraveton, Newfoundland, Canada\r\n467\r\nMusgrave Harbor, Newfoundland, Canada\r\n655\r\nNain, Newfoundland, Canada\r\n922\r\nNew Chelsea, Newfoundland, Canada\r\n586\r\nNew Harbour, Newfoundland, Canada\r\n582\r\nNewmans Cove, Newfoundland, Canada\r\n445\r\nNippers Harbor, Newfoundland, Canada\r\n255\r\nNorth W, Newfoundland, Canada\r\n497\r\nNorman Bay, Newfoundland, Canada\r\n988\r\nOld Perlican, Newfoundland, Canada\r\n587\r\nPacks Har, Newfoundland, Canada\r\n963\r\nPacquet, Newfoundland, Canada\r\n251\r\nParadise River, Newfoundland, Canada\r\n845\r\nPasadena, Newfoundland, Canada\r\n686\r\nPensonsarm, Newfoundland, Canada\r\n951\r\nPetite Ft, Newfoundland, Canada\r\n428\r\nPlate Cove, Newfoundland, Canada\r\n545\r\nPools Cove, Newfoundland, Canada\r\n665\r\nPort Albert, Newfoundland, Canada\r\n241\r\nPort Au Port, Newfoundland, Canada\r\n648\r\nPort Rexton, Newfoundland, Canada\r\n464\r\nPortugal Cove, Newfoundland, Canada\r\n773\r\n895\r\nPostville, Newfoundland, Canada\r\n479\r\nPouch Cove, Newfoundland, Canada\r\n335\r\nPrinceton, Newfoundland, Canada\r\n462\r\nPort Blandfd, Newfoundland, Canada\r\n543\r\nPort H, Newfoundland, Canada\r\n960\r\nPort Axbasqus, Newfoundland, Canada\r\n695\r\nPort Leamington, Newfoundland, Canada\r\n484\r\nPort Saunders, Newfoundland, Canada\r\n861\r\nRaleigh, Newfoundland, Canada\r\n452\r\nRamea, Newfoundland, Canada\r\n625\r\nRed Bay, Newfoundland, Canada\r\n920\r\nReefs Harbor, Newfoundland, Canada\r\n847\r\nRencontr E, Newfoundland, Canada\r\n848\r\nRigolet, Newfoundland, Canada\r\n947\r\nRiver Ponds, Newfoundland, Canada\r\n225\r\nRoberts Arm, Newfoundland, Canada\r\n652\r\nRocky Harbor, Newfoundland, Canada\r\n458\r\nRoddickton, Newfoundland, Canada\r\n457\r\nRoseblanch, Newfoundland, Canada\r\n956\r\nRushoon, Newfoundland, Canada\r\n443\r\nSealcove, Newfoundland, Canada\r\n744\r\n851\r\n531\r\nSeldom, Newfoundland, Canada\r\n627\r\nSmokey, Newfoundland, Canada\r\n961\r\nSops Arm, Newfoundland, Canada\r\n482\r\nSouthbrook, Newfoundland, Canada\r\n657\r\nSpotted Island, Newfoundland, Canada\r\n965\r\nSpringdale, Newfoundland, Canada\r\n673\r\nSaint Albans, Newfoundland, Canada\r\n538\r\nSaint Anthony, Newfoundland, Canada\r\n454\r\nSaint Brendns, Newfoundland, Canada\r\n669\r\nSaint Brides, Newfoundland, Canada\r\n337\r\nSaint Georges, Newfoundland, Canada\r\n647\r\nSaint Johns, Newfoundland, Canada\r\n682\r\n729\r\n748\r\n749\r\n758\r\n273\r\n364\r\n368\r\n551\r\n552\r\n553\r\n570\r\n576\r\n579\r\n722\r\n726\r\n733\r\n737\r\n738\r\n739\r\n745\r\n753\r\n754\r\n772\r\n778\r\n782\r\nSiant Lewis, Newfoundland, Canada\r\n939\r\nSaint Marys, Newfoundland, Canada\r\n525\r\nStephenville, Newfoundland, Canada\r\n643\r\nSaint Lawrence, Newfoundland, Canada\r\n873\r\nStephenville Crossing, Newfoundland, Canada\r\n646\r\nSummerford, Newfoundland, Canada\r\n629\r\nSummerside, Newfoundland, Canada\r\n783\r\nTerra Nova, Newfoundland, Canada\r\n265\r\nTerrenceville, Newfoundland, Canada\r\n662\r\nTorbay, Newfoundland, Canada\r\n437\r\nTrepassey, Newfoundland, Canada\r\n438\r\nTriton, Newfoundland, Canada\r\n263\r\nTrout River, Newfoundland, Canada\r\n451\r\nTwillingat, Newfoundland, Canada\r\n884\r\nUper Island, Newfoundland, Canada\r\n589\r\nWesleyville, Newfoundland, Canada\r\n536\r\nWestern Bay, Newfoundland, Canada\r\n598\r\nWestport, Newfoundland, Canada\r\n224\r\nWhitbourne, Newfoundland, Canada\r\n759\r\nWild Cove, Newfoundland, Canada\r\n329\r\nWill Harbor, Newfoundland, Canada\r\n924\r\nWitlessbay, Newfoundland, Canada\r\n334\r\nWoody Port, Newfoundland, Canada\r\n453\r\n\u00035Unknown prefix code (709) - Newfoundland, Canada\r\n"
  },
  {
    "path": "install/regions/regions.712",
    "content": "Akron, Iowa\r\n568\r\nAlbert City, Iowa\r\n843\r\nAlta, Iowa\r\n284\r\nAlton, Iowa\r\n756\r\nAlvord, Iowa\r\n473\r\nAnita, Iowa\r\n762\r\nAnthon, Iowa\r\n373\r\nArcadia, Iowa\r\n689\r\nArcher, Iowa\r\n723\r\nArmstrong, Iowa\r\n864\r\nArnolds Park, Iowa\r\n332\r\n337\r\nArthur, Iowa\r\n367\r\nAshton, Iowa\r\n724\r\nAtlantic, Iowa\r\n249\r\n250\r\n254\r\n243\r\nAuburn, Iowa\r\n688\r\nAudubon, Iowa\r\n563\r\nAurelia, Iowa\r\n434\r\nAvoca, Iowa\r\n343\r\nAyrshire, Iowa\r\n426\r\nBattle Creek, Iowa\r\n365\r\nBayard, Iowa\r\n651\r\nBedford, Iowa\r\n523\r\nBeloit, Iowa\r\n986\r\nBethesda, Iowa\r\n586\r\nBlencoe, Iowa\r\n452\r\nBoyden, Iowa\r\n725\r\nBraddyville, Iowa\r\n589\r\nBrayton, Iowa\r\n549\r\nBreda, Iowa\r\n673\r\nBronson, Iowa\r\n948\r\nBrunsville, Iowa\r\n533\r\nCarroll, Iowa\r\n792\r\nCarson, Iowa\r\n484\r\nCarter Lake, Iowa\r\n347\r\nCastana, Iowa\r\n353\r\nCharter Oak, Iowa\r\n678\r\nCherokee, Iowa\r\n225\r\nClarinda, Iowa\r\n542\r\nCleghorn, Iowa\r\n436\r\nClimbing Hill, Iowa\r\n876\r\nCoin, Iowa\r\n583\r\nCollege Spring, Iowa\r\n582\r\nCoon Rapids, Iowa\r\n684\r\nCorrectionville, Iowa\r\n372\r\nCouncil Bluff, Iowa\r\n326\r\n322\r\n323\r\n325\r\n328\r\n366\r\nCrescent, Iowa\r\n545\r\nCumberland, Iowa\r\n774\r\nCurlew, Iowa\r\n855\r\nCushing, Iowa\r\n384\r\nCylinder, Iowa\r\n424\r\nDanbury, Iowa\r\n883\r\nDedham, Iowa\r\n683\r\nDefiance, Iowa\r\n748\r\nDenison, Iowa\r\n269\r\n280\r\n263\r\nDickens, Iowa\r\n836\r\nDolliver, Iowa\r\n865\r\nDoon, Iowa\r\n726\r\nDow City, Iowa\r\n674\r\nDunlap, Iowa\r\n643\r\nEarling, Iowa\r\n747\r\nEarly, Iowa\r\n273\r\nEast Harrisburg, Iowa\r\n746\r\nEast Neb, Iowa\r\n973\r\nEast Hudson, Iowa\r\n982\r\nElk Horn, Iowa\r\n764\r\nElliott, Iowa\r\n767\r\nEmerson, Iowa\r\n824\r\nEmmetsburg, Iowa\r\n852\r\nEssex, Iowa\r\n370\r\n379\r\nEstherville, Iowa\r\n362\r\n360\r\nEverly, Iowa\r\n834\r\nExira, Iowa\r\n268\r\nFarragut, Iowa\r\n385\r\nFonda, Iowa\r\n288\r\nGalva, Iowa\r\n282\r\nGeorge, Iowa\r\n475\r\nGillett Grove, Iowa\r\n835\r\nGlenwood, Iowa\r\n520\r\n539\r\n527\r\nGlidden, Iowa\r\n659\r\nGraettinger, Iowa\r\n859\r\nGrant, Iowa\r\n763\r\nGranville, Iowa\r\n727\r\nGravity, Iowa\r\n537\r\nGriswold, Iowa\r\n778\r\nHalbur, Iowa\r\n658\r\nHamburg, Iowa\r\n350\r\n850\r\n382\r\nHancock, Iowa\r\n741\r\nHarlan, Iowa\r\n744\r\n755\r\nHarris, Iowa\r\n349\r\nHartley, Iowa\r\n728\r\nHavelock, Iowa\r\n776\r\nHawarden, Iowa\r\n552\r\nHenderson, Iowa\r\n825\r\nHinton, Iowa\r\n947\r\nHolstein, Iowa\r\n368\r\nHornick, Iowa\r\n874\r\nHospers, Iowa\r\n752\r\nHull, Iowa\r\n439\r\nIda Grove, Iowa\r\n364\r\nImogene, Iowa\r\n386\r\nInwood, Iowa\r\n753\r\nIreton, Iowa\r\n278\r\nIrwin, Iowa\r\n782\r\nJacksonville, Iowa\r\n799\r\nKimballton, Iowa\r\n773\r\nKingsley, Iowa\r\n378\r\nKirkman, Iowa\r\n766\r\nKiron, Iowa\r\n675\r\nLake City, Iowa\r\n464\r\nLake Park, Iowa\r\n832\r\nLake View, Iowa\r\n657\r\nLanesboro, Iowa\r\n656\r\nLarchwood, Iowa\r\n477\r\nLarrabee, Iowa\r\n437\r\nLaurens, Iowa\r\n845\r\nLawton, Iowa\r\n944\r\nLe Mars, Iowa\r\n499\r\n540\r\n548\r\n546\r\nLester, Iowa\r\n478\r\nLewis, Iowa\r\n769\r\nLidderdale, Iowa\r\n822\r\n830\r\nLinn Grove, Iowa\r\n296\r\nLittle Sioux, Iowa\r\n649\r\nLittle Rock, Iowa\r\n479\r\nLogan, Iowa\r\n644\r\nLohrville, Iowa\r\n465\r\nLytton, Iowa\r\n466\r\nMacedonia, Iowa\r\n486\r\nMagnolia, Iowa\r\n648\r\nMallard, Iowa\r\n425\r\nMalvern, Iowa\r\n624\r\nManilla, Iowa\r\n654\r\nManning, Iowa\r\n653\r\nManson, Iowa\r\n469\r\nMapleton, Iowa\r\n882\r\nMarathon, Iowa\r\n289\r\nMarcus, Iowa\r\n376\r\nMarne, Iowa\r\n781\r\nMassena, Iowa\r\n779\r\nMatlock, Iowa\r\n348\r\n738\r\nMaurice, Iowa\r\n567\r\nMay City, Iowa\r\n735\r\nMelvin, Iowa\r\n736\r\nMeriden, Iowa\r\n443\r\nMerrill, Iowa\r\n938\r\nMidland, Iowa\r\n963\r\nMilford, Iowa\r\n338\r\nMinden, Iowa\r\n483\r\nMineola, Iowa\r\n526\r\nMissouri Valley, Iowa\r\n642\r\nModale, Iowa\r\n645\r\nMondamin, Iowa\r\n646\r\nMoorhead, Iowa\r\n886\r\nMoville, Iowa\r\n873\r\nNemaha, Iowa\r\n636\r\nNeola, Iowa\r\n485\r\nNew Market, Iowa\r\n585\r\nNewell, Iowa\r\n272\r\nNorth Hopkins, Iowa\r\n287\r\nNodaway, Iowa\r\n785\r\nNorthboro, Iowa\r\n534\r\nOakland, Iowa\r\n482\r\nOcheyedan, Iowa\r\n758\r\nOdebolt, Iowa\r\n668\r\nOnawa, Iowa\r\n420\r\n429\r\n423\r\nOrange City, Iowa\r\n737\r\nOto, Iowa\r\n827\r\nPacific Junction, Iowa\r\n622\r\nPalmer, Iowa\r\n359\r\nPanama, Iowa\r\n489\r\nPaullina, Iowa\r\n448\r\nPercival, Iowa\r\n529\r\nPersia, Iowa\r\n488\r\nPeterson, Iowa\r\n295\r\nPierson, Iowa\r\n375\r\nPisgah, Iowa\r\n456\r\nPlover, Iowa\r\n857\r\nPocahontas, Iowa\r\n335\r\nPomeroy, Iowa\r\n468\r\nPortsmouth, Iowa\r\n743\r\nPrimghar, Iowa\r\n757\r\nQuimby, Iowa\r\n445\r\nRalston, Iowa\r\n667\r\nRandolph, Iowa\r\n625\r\nRed Oak, Iowa\r\n623\r\nRembrandt, Iowa\r\n286\r\nRemsen, Iowa\r\n670\r\n786\r\nRicketts, Iowa\r\n679\r\nRingsted, Iowa\r\n866\r\nRiverton, Iowa\r\n387\r\nRock Rapids, Iowa\r\n472\r\nRock Valley, Iowa\r\n476\r\nRockwell City, Iowa\r\n297\r\nRolfe, Iowa\r\n848\r\nRoyal, Iowa\r\n933\r\nRuthven, Iowa\r\n837\r\nSac City, Iowa\r\n662\r\nSalix, Iowa\r\n946\r\nSanborn, Iowa\r\n729\r\nSchaller, Iowa\r\n275\r\nSchleswig, Iowa\r\n676\r\nScranton, Iowa\r\n652\r\nSeargent Bluff, Iowa\r\n943\r\nShelby, Iowa\r\n544\r\nSheldon, Iowa\r\n324\r\nShenandoah, Iowa\r\n246\r\nSibley, Iowa\r\n754\r\nSidney, Iowa\r\n374\r\nSilver City, Iowa\r\n525\r\nSioux Center, Iowa\r\n722\r\nSioux City, Iowa\r\n233\r\n239\r\n251\r\n252\r\n255\r\n258\r\n259\r\n274\r\n276\r\n277\r\n279\r\n290\r\n958\r\nSioux Rapids, Iowa\r\n283\r\nSloan, Iowa\r\n428\r\nSmithland, Iowa\r\n889\r\nSoldier, Iowa\r\n884\r\nSouth Bigelow, Iowa\r\n682\r\nSouth Hills, Iowa\r\n964\r\nSouth Steen, Iowa\r\n851\r\nSouth Valley Springs, Iowa\r\n777\r\nSpencer, Iowa\r\n230\r\n260\r\n270\r\n262\r\n264\r\nSpirit Lake, Iowa\r\n336\r\nStanton, Iowa\r\n829\r\nStorm Lake, Iowa\r\n299\r\n732\r\n749\r\nStruble, Iowa\r\n562\r\nSuperior, Iowa\r\n858\r\nSutherland, Iowa\r\n446\r\nTabor, Iowa\r\n629\r\nTempleton, Iowa\r\n669\r\nTerril, Iowa\r\n853\r\nThurman, Iowa\r\n628\r\nTreynor, Iowa\r\n487\r\nUnderwood, Iowa\r\n566\r\nUte, Iowa\r\n885\r\nVail, Iowa\r\n677\r\nVillisca, Iowa\r\n826\r\nWall Lake, Iowa\r\n664\r\nWallingford, Iowa\r\n867\r\nWalnut, Iowa\r\n784\r\nWashta, Iowa\r\n447\r\nWebb, Iowa\r\n838\r\nWestphalia, Iowa\r\n627\r\nWestside, Iowa\r\n663\r\nWhiting, Iowa\r\n458\r\nWiota, Iowa\r\n783\r\nWoodbine, Iowa\r\n647\r\n\u00035Unknown prefix code (712) - Iowa\r\n"
  },
  {
    "path": "install/regions/regions.713",
    "content": "Airline, Texas\r\n405\r\n418\r\n445\r\n447\r\n448\r\n591\r\n820\r\n847\r\n878\r\n931\r\n999\r\nAldine, Texas\r\n442\r\n449\r\n590\r\n985\r\n986\r\n987\r\nAlief, Texas\r\n564\r\n495\r\n498\r\n530\r\n561\r\n568\r\n575\r\n879\r\n933\r\n983\r\nAlvin, Texas\r\n331\r\n388\r\n585\r\nApollo, Texas\r\n212\r\n218\r\n244\r\n286\r\n280\r\n282\r\n283\r\n480\r\n483\r\n486\r\nArcola, Texas\r\n431\r\nAtascocita, Texas\r\n812\r\n852\r\nBacliff, Texas\r\n339\r\n559\r\nBammel, Texas\r\n397\r\n587\r\n440\r\n444\r\n537\r\n580\r\n583\r\n586\r\n893\r\nBarker, Texas\r\n647\r\n492\r\n578\r\n579\r\nBaytown, Texas\r\n837\r\n838\r\n839\r\n420\r\n421\r\n422\r\n424\r\n425\r\n427\r\n428\r\nBeach City, Texas\r\n383\r\n573\r\nBlue Ridge, Texas\r\n436\r\n437\r\n438\r\n835\r\nBrookshire, Texas\r\n934\r\nBuffalo, Texas\r\n368\r\n407\r\n544\r\n560\r\n597\r\n293\r\n493\r\n496\r\n497\r\n531\r\n556\r\n558\r\n584\r\n588\r\n589\r\n596\r\n870\r\nChannelview, Texas\r\n860\r\n452\r\n457\r\nCleveland, Texas\r\n592\r\n593\r\nCrosby, Texas\r\n328\r\nCypress, Texas\r\n373\r\n256\r\nDeer Park, Texas\r\n246\r\n476\r\n478\r\n479\r\n884\r\n930\r\nDickinson, Texas\r\n337\r\n382\r\n534\r\nEast Houston, Texas\r\n458\r\n459\r\nEllington, Texas\r\n481\r\n484\r\n487\r\n922\r\n929\r\n998\r\nFriendswood, Texas\r\n482\r\n992\r\n996\r\nGreens Point, Texas\r\n423\r\n775\r\n872\r\n873\r\n874\r\n875\r\n876\r\nHighlands, Texas\r\n426\r\n843\r\nHmbl Sohml, Texas\r\n319\r\n441\r\n446\r\n540\r\n548\r\nHouston, Texas\r\n704\r\n740\r\n945\r\n413\r\n743\r\n746\r\n905\r\n216\r\n217\r\n245\r\n248\r\n249\r\n250\r\n252\r\n253\r\n254\r\n296\r\n297\r\n299\r\n327\r\n408\r\n410\r\n412\r\n414\r\n415\r\n416\r\n417\r\n419\r\n515\r\n542\r\n543\r\n547\r\n553\r\n557\r\n562\r\n567\r\n569\r\n582\r\n594\r\n598\r\n615\r\n616\r\n617\r\n624\r\n625\r\n628\r\n638\r\n646\r\n677\r\n693\r\n698\r\n703\r\n707\r\n708\r\n709\r\n710\r\n712\r\n716\r\n717\r\n724\r\n725\r\n735\r\n736\r\n737\r\n745\r\n752\r\n753\r\n755\r\n756\r\n758\r\n770\r\n773\r\n802\r\n803\r\n808\r\n815\r\n818\r\n828\r\n846\r\n851\r\n854\r\n858\r\n881\r\n887\r\n899\r\n901\r\n904\r\n906\r\n907\r\n917\r\n919\r\n942\r\n962\r\n982\r\n989\r\n260\r\n267\r\n365\r\n536\r\n606\r\n607\r\n612\r\n613\r\n619\r\n648\r\n687\r\n722\r\n727\r\n760\r\n764\r\n765\r\n819\r\n902\r\n903\r\n914\r\n916\r\n918\r\n938\r\n949\r\n990\r\n994\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n235\r\n236\r\n237\r\n238\r\n241\r\n247\r\n266\r\n268\r\n270\r\n271\r\n272\r\n284\r\n285\r\n295\r\n390\r\n432\r\n433\r\n434\r\n435\r\n439\r\n450\r\n451\r\n453\r\n455\r\n460\r\n461\r\n462\r\n464\r\n465\r\n467\r\n468\r\n472\r\n473\r\n475\r\n477\r\n488\r\n520\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n529\r\n535\r\n541\r\n546\r\n549\r\n551\r\n552\r\n599\r\n620\r\n621\r\n622\r\n623\r\n626\r\n627\r\n629\r\n630\r\n631\r\n633\r\n635\r\n636\r\n639\r\n640\r\n641\r\n643\r\n644\r\n645\r\n649\r\n650\r\n651\r\n652\r\n653\r\n654\r\n655\r\n656\r\n657\r\n658\r\n659\r\n660\r\n661\r\n662\r\n663\r\n664\r\n665\r\n666\r\n667\r\n668\r\n669\r\n670\r\n671\r\n672\r\n673\r\n674\r\n675\r\n676\r\n678\r\n679\r\n680\r\n681\r\n682\r\n683\r\n684\r\n685\r\n686\r\n688\r\n690\r\n691\r\n692\r\n694\r\n695\r\n696\r\n697\r\n699\r\n720\r\n721\r\n723\r\n726\r\n728\r\n729\r\n730\r\n731\r\n732\r\n733\r\n734\r\n738\r\n739\r\n741\r\n744\r\n747\r\n748\r\n749\r\n750\r\n751\r\n754\r\n757\r\n759\r\n761\r\n762\r\n763\r\n768\r\n769\r\n771\r\n772\r\n774\r\n776\r\n777\r\n778\r\n779\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n787\r\n788\r\n789\r\n790\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\n822\r\n823\r\n824\r\n825\r\n826\r\n827\r\n829\r\n831\r\n833\r\n834\r\n836\r\n840\r\n841\r\n842\r\n844\r\n845\r\n850\r\n853\r\n857\r\n861\r\n862\r\n863\r\n864\r\n865\r\n866\r\n867\r\n868\r\n869\r\n871\r\n877\r\n880\r\n882\r\n883\r\n886\r\n888\r\n891\r\n892\r\n895\r\n898\r\n920\r\n921\r\n923\r\n924\r\n926\r\n928\r\n932\r\n935\r\n939\r\n940\r\n941\r\n943\r\n944\r\n946\r\n947\r\n948\r\n951\r\n952\r\n953\r\n954\r\n956\r\n957\r\n960\r\n961\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\n971\r\n972\r\n973\r\n974\r\n975\r\n977\r\n978\r\n981\r\n984\r\n988\r\n991\r\n993\r\n995\r\nHuffman, Texas\r\n324\r\nJersey Village, Texas\r\n466\r\n849\r\n896\r\n937\r\nKaty, Texas\r\n396\r\n347\r\n371\r\n391\r\n392\r\n394\r\n395\r\n574\r\nKemah, Texas\r\n326\r\n334\r\n532\r\n538\r\nKingwood, Texas\r\n348\r\n361\r\n358\r\n359\r\n360\r\nLa Porte, Texas\r\n470\r\n471\r\nLangham Creek, Texas\r\n463\r\n550\r\n855\r\n856\r\n859\r\nLeague City, Texas\r\n554\r\n332\r\n338\r\n386\r\nLiverpool, Texas\r\n393\r\n581\r\nLake Houston, Texas\r\n454\r\nManvel, Texas\r\n489\r\nMount Belvieu, Texas\r\n576\r\n385\r\nNess Bay, Texas\r\n333\r\n335\r\nPearland, Texas\r\n485\r\n997\r\nPinehurst, Texas\r\n259\r\n356\r\nPorter, Texas\r\n354\r\n577\r\nPorter Height, Texas\r\n572\r\n429\r\nRichmondrsburg, Texas\r\n232\r\n239\r\n341\r\n342\r\n344\r\nRosharn, Texas\r\n369\r\n595\r\nSatsuma, Texas\r\n807\r\n469\r\n890\r\n894\r\n897\r\n955\r\nSeabrook, Texas\r\n291\r\n474\r\nSheldon, Texas\r\n456\r\nSmithers Lake, Texas\r\n545\r\n343\r\nSplendora, Texas\r\n689\r\nSplender, Texas\r\n399\r\nSpring, Texas\r\n377\r\n350\r\n353\r\n355\r\n363\r\n364\r\n367\r\n288\r\n292\r\n298\r\nStafford, Texas\r\n261\r\n499\r\nSugar Land, Texas\r\n240\r\n242\r\n262\r\n263\r\n264\r\n265\r\n269\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n287\r\n289\r\n294\r\n490\r\n491\r\n494\r\n563\r\n565\r\n566\r\n980\r\nTomball, Texas\r\n257\r\n320\r\n351\r\n357\r\n370\r\n374\r\n375\r\n376\r\n378\r\n379\r\n251\r\n255\r\nValley Ledge, Texas\r\n346\r\n533\r\nWestfield, Texas\r\n230\r\n233\r\n443\r\n821\r\n\u00035Unknown prefix code (713) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.714",
    "content": "Anaheim, California\r\n201\r\n202\r\n203\r\n204\r\n215\r\n216\r\n217\r\n218\r\n219\r\n237\r\n238\r\n254\r\n264\r\n266\r\n267\r\n268\r\n269\r\n271\r\n284\r\n286\r\n287\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\n312\r\n313\r\n314\r\n315\r\n344\r\n345\r\n346\r\n412\r\n501\r\n504\r\n561\r\n563\r\n570\r\n575\r\n576\r\n801\r\n802\r\n803\r\n807\r\n812\r\n813\r\n239\r\n321\r\n323\r\n324\r\n327\r\n328\r\n329\r\n349\r\n414\r\n490\r\n491\r\n502\r\n517\r\n520\r\n533\r\n535\r\n630\r\n632\r\n635\r\n742\r\n743\r\n745\r\n758\r\n762\r\n764\r\n772\r\n774\r\n776\r\n778\r\n956\r\n991\r\n999\r\nArlington, California\r\n343\r\n710\r\nArrowhead, California\r\n336\r\n337\r\nBanning, California\r\n769\r\n845\r\n849\r\n922\r\nBig Bear Lake, California\r\n866\r\n878\r\nBig Bear City, California\r\n584\r\n585\r\nBrea, California\r\n257\r\n255\r\n256\r\n529\r\n671\r\n990\r\nBuena Park, California\r\n228\r\n521\r\n522\r\n523\r\n562\r\n670\r\n739\r\n994\r\nCapster Valley, California\r\n240\r\n248\r\n249\r\n361\r\n363\r\n364\r\n365\r\n368\r\n468\r\n492\r\n493\r\n495\r\n496\r\n498\r\n661\r\n347\r\n366\r\n443\r\n489\r\nChino, California\r\n464\r\n606\r\n613\r\n393\r\n465\r\n590\r\n591\r\n597\r\n627\r\n628\r\nClmt Sndms, California\r\n305\r\n392\r\n394\r\n398\r\n399\r\n445\r\n482\r\n592\r\n593\r\n596\r\n599\r\n603\r\n607\r\n621\r\n624\r\n625\r\n626\r\nColton, California\r\n420\r\n423\r\n424\r\n426\r\n439\r\n512\r\n616\r\n370\r\n422\r\n431\r\n824\r\n825\r\n872\r\n876\r\n877\r\nCorona, California\r\n270\r\n273\r\n272\r\n277\r\n278\r\n279\r\n371\r\n734\r\n735\r\n736\r\n737\r\nCrestline, California\r\n220\r\n229\r\n338\r\nCypress, California\r\n236\r\n503\r\n527\r\n761\r\n821\r\n826\r\n827\r\n828\r\n952\r\n995\r\nDiamond Break, California\r\n396\r\n594\r\n595\r\n598\r\n612\r\n860\r\n861\r\n869\r\nElsinore, California\r\n471\r\n609\r\n245\r\n674\r\n678\r\nEtiwanda, California\r\n463\r\n899\r\nFontana, California\r\n427\r\n428\r\n350\r\n355\r\n356\r\n357\r\n822\r\n823\r\n829\r\nFullerton, California\r\n441\r\n447\r\n449\r\n519\r\n525\r\n526\r\n578\r\n680\r\n732\r\n738\r\n773\r\n870\r\n871\r\n879\r\n992\r\nGarden Grove, California\r\n530\r\n534\r\n537\r\n539\r\n636\r\n638\r\n663\r\n740\r\n741\r\n748\r\n750\r\n971\r\nHemet, California\r\n306\r\n765\r\n652\r\n654\r\n658\r\n763\r\n766\r\n925\r\n926\r\n927\r\n929\r\nHighland, California\r\n425\r\n862\r\n864\r\nHuntington Beach, California\r\n375\r\n377\r\n378\r\n374\r\n536\r\n840\r\n841\r\n842\r\n843\r\n846\r\n847\r\n848\r\n960\r\n962\r\n963\r\n964\r\n965\r\n968\r\n969\r\nIdyllwild, California\r\n659\r\nIrvine, California\r\n222\r\n263\r\n440\r\n442\r\n451\r\n453\r\n753\r\n932\r\n250\r\n251\r\n252\r\n253\r\n261\r\n262\r\n474\r\n476\r\n551\r\n552\r\n553\r\n559\r\n651\r\n660\r\n724\r\n725\r\n726\r\n727\r\n733\r\n752\r\n756\r\n757\r\n786\r\n833\r\n851\r\n852\r\n854\r\n856\r\n857\r\n863\r\n955\r\n975\r\nLaguna Beach, California\r\n376\r\n494\r\n497\r\n499\r\nLakeview Nuevo, California\r\n928\r\nMarshall, California\r\n473\r\nMentone, California\r\n389\r\nMoreno, California\r\n485\r\n486\r\n488\r\n601\r\n697\r\n242\r\n243\r\n247\r\n653\r\n655\r\n656\r\n924\r\nMurrieta, California\r\n304\r\n696\r\n677\r\n698\r\nNewport Beach, California\r\n574\r\n509\r\n515\r\n548\r\n631\r\n640\r\n642\r\n644\r\n645\r\n646\r\n650\r\n673\r\n675\r\n720\r\n721\r\n722\r\n723\r\n729\r\n759\r\n760\r\nOntario, California\r\n309\r\n390\r\n401\r\n402\r\n403\r\n405\r\n406\r\n407\r\n460\r\n467\r\n604\r\n605\r\n930\r\n933\r\n391\r\n395\r\n461\r\n462\r\n923\r\n947\r\n949\r\n983\r\n984\r\n986\r\n988\r\nOrange, California\r\n280\r\n281\r\n288\r\n456\r\n704\r\n935\r\n282\r\n283\r\n289\r\n322\r\n325\r\n326\r\n342\r\n385\r\n516\r\n532\r\n538\r\n633\r\n634\r\n637\r\n639\r\n712\r\n744\r\n746\r\n747\r\n771\r\n921\r\n937\r\n938\r\n939\r\n974\r\n978\r\n997\r\n998\r\nPerris, California\r\n657\r\n940\r\n943\r\nPlacentia, California\r\n577\r\n524\r\n528\r\n572\r\n579\r\n961\r\n993\r\n996\r\nPomona, California\r\n469\r\n397\r\n620\r\n622\r\n623\r\n629\r\n865\r\n868\r\nRanch Viejo, California\r\n728\r\nRedlands, California\r\n307\r\n478\r\n335\r\n790\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\nRialto, California\r\n421\r\n820\r\n873\r\n874\r\n875\r\nRiverside, California\r\n274\r\n341\r\n615\r\n715\r\n275\r\n276\r\n351\r\n352\r\n353\r\n354\r\n358\r\n359\r\n360\r\n369\r\n602\r\n681\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n749\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n787\r\n788\r\n789\r\nRunning Spring, California\r\n867\r\nSaddleback Valley, California\r\n348\r\n448\r\n454\r\n457\r\n580\r\n362\r\n367\r\n380\r\n455\r\n458\r\n472\r\n581\r\n582\r\n583\r\n586\r\n587\r\n588\r\n643\r\n707\r\n768\r\n770\r\n830\r\n831\r\n837\r\n855\r\n859\r\n951\r\nSage, California\r\n767\r\nSan Bernadino, California\r\n381\r\n382\r\n383\r\n384\r\n386\r\n387\r\n388\r\n880\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\nSan Jacinto, California\r\n487\r\nSanta Ana, California\r\n435\r\n436\r\n437\r\n438\r\n479\r\n480\r\n505\r\n560\r\n564\r\n571\r\n573\r\n967\r\n241\r\n258\r\n259\r\n265\r\n285\r\n339\r\n418\r\n432\r\n433\r\n434\r\n475\r\n513\r\n531\r\n540\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n547\r\n549\r\n550\r\n554\r\n556\r\n557\r\n558\r\n565\r\n566\r\n567\r\n568\r\n569\r\n641\r\n647\r\n648\r\n662\r\n664\r\n665\r\n666\r\n667\r\n668\r\n669\r\n691\r\n708\r\n730\r\n731\r\n751\r\n754\r\n755\r\n775\r\n832\r\n834\r\n835\r\n836\r\n838\r\n839\r\n850\r\n853\r\n953\r\n954\r\n957\r\n966\r\n972\r\n973\r\n977\r\n979\r\nSilverado, California\r\n649\r\nSun City, California\r\n301\r\n244\r\n246\r\n672\r\n679\r\nTemecula, California\r\n302\r\n303\r\n308\r\n695\r\n676\r\n694\r\n699\r\nTrabuco, California\r\n459\r\n589\r\n858\r\nUpland, California\r\n466\r\n477\r\n481\r\n483\r\n484\r\n608\r\n614\r\n931\r\n948\r\n920\r\n941\r\n942\r\n944\r\n945\r\n946\r\n980\r\n981\r\n982\r\n985\r\n987\r\n989\r\nWestminister, California\r\n372\r\n373\r\n890\r\n891\r\n892\r\n893\r\n894\r\n895\r\n896\r\n897\r\n898\r\n903\r\n379\r\n934\r\nYorbalinda, California\r\n415\r\n692\r\n693\r\n701\r\n777\r\n779\r\n970\r\n\u00035Unknown prefix code (714) - California\r\n"
  },
  {
    "path": "install/regions/regions.715",
    "content": "Alma Center, Wisconsin\r\n964\r\nAlmena, Wisconsin\r\n357\r\nAlmond, Wisconsin\r\n366\r\nAmberg, Wisconsin\r\n759\r\nAmery, Wisconsin\r\n268\r\nAmherst, Wisconsin\r\n824\r\nAntigo, Wisconsin\r\n623\r\n627\r\nArgonne, Wisconsin\r\n649\r\nArkansaw, Wisconsin\r\n285\r\nAshland, Wisconsin\r\n682\r\nAthens, Wisconsin\r\n257\r\nAuburndale, Wisconsin\r\n652\r\nAugusta, Wisconsin\r\n286\r\nAurora, Wisconsin\r\n589\r\nBaldwin, Wisconsin\r\n684\r\nBalsam Lake, Wisconsin\r\n485\r\nBarnes, Wisconsin\r\n795\r\nBarron, Wisconsin\r\n537\r\nBay City, Wisconsin\r\n594\r\nBayfield, Wisconsin\r\n779\r\nBear Creek, Wisconsin\r\n752\r\nBennett, Wisconsin\r\n375\r\nBenoit, Wisconsin\r\n746\r\nBirchwood, Wisconsin\r\n354\r\nBirnamwood, Wisconsin\r\n449\r\nBlackriverfalls, Wisconsin\r\n284\r\n299\r\nBloomer, Wisconsin\r\n568\r\nBonduel, Wisconsin\r\n758\r\nBoulder Junction, Wisconsin\r\n385\r\nBowler, Wisconsin\r\n793\r\nBoyceville, Wisconsin\r\n643\r\nBoyd, Wisconsin\r\n667\r\nBrantwood, Wisconsin\r\n564\r\nBruce, Wisconsin\r\n868\r\nButternut, Wisconsin\r\n769\r\nCable, Wisconsin\r\n798\r\nCadott, Wisconsin\r\n289\r\nCameron, Wisconsin\r\n458\r\nCanton, Wisconsin\r\n859\r\nCecil, Wisconsin\r\n745\r\nCenturia, Wisconsin\r\n646\r\nChetek, Wisconsin\r\n924\r\nChili, Wisconsin\r\n683\r\nChippawa Falls, Wisconsin\r\n723\r\n726\r\n720\r\nCity Point, Wisconsin\r\n593\r\nClayton, Wisconsin\r\n948\r\nClear Lake, Wisconsin\r\n263\r\nCleghorn, Wisconsin\r\n878\r\nClintonville, Wisconsin\r\n823\r\n584\r\n587\r\n853\r\n923\r\nColby, Wisconsin\r\n223\r\nColfax, Wisconsin\r\n962\r\nColoma, Wisconsin\r\n228\r\nCornell, Wisconsin\r\n239\r\nCornucopia, Wisconsin\r\n742\r\nCrandon, Wisconsin\r\n478\r\nCrescent Lake, Wisconsin\r\n282\r\nCrivitz, Wisconsin\r\n854\r\nCumberland, Wisconsin\r\n822\r\nCushing, Wisconsin\r\n648\r\nDairyland, Wisconsin\r\n244\r\nDallas, Wisconsin\r\n837\r\nDanbury, Wisconsin\r\n656\r\nDeer Park, Wisconsin\r\n269\r\nDorchester, Wisconsin\r\n654\r\nDownsville, Wisconsin\r\n664\r\nDresser, Wisconsin\r\n755\r\nDrummond, Wisconsin\r\n739\r\nDurand, Wisconsin\r\n672\r\nEaglepoint, Wisconsin\r\n288\r\nEagle River, Wisconsin\r\n479\r\nEau Claire, Wisconsin\r\n283\r\n393\r\n491\r\n492\r\n495\r\n556\r\n577\r\n797\r\n828\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n839\r\nEdgar, Wisconsin\r\n352\r\nElcho, Wisconsin\r\n275\r\nElderon, Wisconsin\r\n454\r\nEleva, Wisconsin\r\n287\r\nElk Lake, Wisconsin\r\n874\r\n876\r\nElk Mound, Wisconsin\r\n879\r\nEllsworth, Wisconsin\r\n273\r\nElmwood, Wisconsin\r\n639\r\nExeland, Wisconsin\r\n943\r\nFairchild, Wisconsin\r\n334\r\nFall Creek, Wisconsin\r\n877\r\nFalun, Wisconsin\r\n689\r\nFlorence, Wisconsin\r\n528\r\nFox Creek, Wisconsin\r\n857\r\nFrederic, Wisconsin\r\n327\r\nGilman, Wisconsin\r\n447\r\nGilmanton, Wisconsin\r\n946\r\nGleason, Wisconsin\r\n873\r\nGlen Flora, Wisconsin\r\n322\r\nGlenwood City, Wisconsin\r\n265\r\nGlidden, Wisconsin\r\n264\r\nGoodman, Wisconsin\r\n336\r\nGordon, Wisconsin\r\n376\r\nGrandview, Wisconsin\r\n763\r\nGranton, Wisconsin\r\n238\r\nGrantsburg, Wisconsin\r\n463\r\nGreenwood, Wisconsin\r\n267\r\nGresham, Wisconsin\r\n787\r\nHager City, Wisconsin\r\n792\r\nHammond, Wisconsin\r\n796\r\nHancock, Wisconsin\r\n249\r\nHarmony, Wisconsin\r\n789\r\nHatley, Wisconsin\r\n446\r\nHawkins, Wisconsin\r\n585\r\nHayward, Wisconsin\r\n634\r\nHixton, Wisconsin\r\n963\r\nHolcombe, Wisconsin\r\n595\r\nHoulton, Wisconsin\r\n549\r\nHudson, Wisconsin\r\n381\r\n386\r\nHurley, Wisconsin\r\n561\r\n893\r\nIndependence, Wisconsin\r\n985\r\nIola, Wisconsin\r\n445\r\nIron River, Wisconsin\r\n372\r\nJim Falls, Wisconsin\r\n382\r\nJump River, Wisconsin\r\n668\r\nJunction City, Wisconsin\r\n457\r\nKennan, Wisconsin\r\n474\r\nKeshena, Wisconsin\r\n799\r\nKnapp, Wisconsin\r\n665\r\nLa Pointe, Wisconsin\r\n747\r\nLacdflambu, Wisconsin\r\n588\r\nLadysmith, Wisconsin\r\n532\r\nLake Nebagmn, Wisconsin\r\n374\r\nLake Tomahawk, Wisconsin\r\n277\r\nLakewood, Wisconsin\r\n276\r\nLand o'lakes, Wisconsin\r\n547\r\nLaona, Wisconsin\r\n674\r\nLewis, Wisconsin\r\n653\r\nLindsey, Wisconsin\r\n676\r\nLong Lake, Wisconsin\r\n967\r\nLoyal, Wisconsin\r\n255\r\nLuck, Wisconsin\r\n472\r\nMaidenrock, Wisconsin\r\n448\r\nMantwashwater, Wisconsin\r\n543\r\nMaple, Wisconsin\r\n363\r\nMarathon, Wisconsin\r\n443\r\nMarengo, Wisconsin\r\n278\r\nMarinette, Wisconsin\r\n732\r\n735\r\nMarion, Wisconsin\r\n754\r\nMarshfield, Wisconsin\r\n384\r\n387\r\n389\r\nMason, Wisconsin\r\n765\r\nMattoon, Wisconsin\r\n489\r\nMedford, Wisconsin\r\n748\r\nMellen, Wisconsin\r\n274\r\nMenomonie, Wisconsin\r\n232\r\n235\r\nMercer, Wisconsin\r\n476\r\nMerrill, Wisconsin\r\n536\r\n539\r\nMerrillan, Wisconsin\r\n333\r\nMilltown, Wisconsin\r\n825\r\nMinocqua, Wisconsin\r\n358\r\n356\r\nMinong, Wisconsin\r\n466\r\nMondovi, Wisconsin\r\n926\r\nMont Dulac, Wisconsin\r\n636\r\nMosinee, Wisconsin\r\n693\r\nNamekgn Lake, Wisconsin\r\n794\r\nNeillsville, Wisconsin\r\n743\r\nNekoosa, Wisconsin\r\n886\r\nNelson, Wisconsin\r\n673\r\nNeopit, Wisconsin\r\n756\r\nNew Auburn, Wisconsin\r\n237\r\nNew Richmond, Wisconsin\r\n243\r\n246\r\nNiagara, Wisconsin\r\n251\r\nNorthfield, Wisconsin\r\n984\r\nOgema, Wisconsin\r\n767\r\nOsceola, Wisconsin\r\n294\r\nOsseo, Wisconsin\r\n597\r\nOwen, Wisconsin\r\n229\r\nPark Falls, Wisconsin\r\n762\r\nPelican Lake, Wisconsin\r\n487\r\nPembine, Wisconsin\r\n324\r\nPepin, Wisconsin\r\n442\r\nPerkinstown, Wisconsin\r\n785\r\nPeshtigo, Wisconsin\r\n582\r\nPhelps, Wisconsin\r\n545\r\nPhillips, Wisconsin\r\n339\r\nPickerel, Wisconsin\r\n484\r\nPigeon Falls, Wisconsin\r\n983\r\nPittsville, Wisconsin\r\n884\r\nPlainfield, Wisconsin\r\n335\r\nPleasantville, Wisconsin\r\n694\r\nPlum City, Wisconsin\r\n647\r\nPolonia, Wisconsin\r\n592\r\nPoplar, Wisconsin\r\n364\r\nPort Edwards, Wisconsin\r\n885\r\n887\r\nPort Wing, Wisconsin\r\n774\r\nPrar Farm, Wisconsin\r\n455\r\nPrentice, Wisconsin\r\n428\r\nPrescott, Wisconsin\r\n262\r\nPresque Is, Wisconsin\r\n686\r\nRadisson, Wisconsin\r\n945\r\nRhinelander, Wisconsin\r\n362\r\n369\r\n365\r\n367\r\n493\r\nRib Lake, Wisconsin\r\n427\r\nRice Lake, Wisconsin\r\n236\r\n296\r\n234\r\nRidgeland, Wisconsin\r\n949\r\nRiver Falls, Wisconsin\r\n425\r\n426\r\nRoberts, Wisconsin\r\n749\r\nRock Falls, Wisconsin\r\n875\r\nRosholt, Wisconsin\r\n677\r\nRudolph, Wisconsin\r\n435\r\nSand Creek, Wisconsin\r\n658\r\nSarona, Wisconsin\r\n469\r\nSayner, Wisconsin\r\n542\r\nScandinavia, Wisconsin\r\n467\r\nShawano, Wisconsin\r\n524\r\n526\r\nSheldon, Wisconsin\r\n452\r\nShell Lake, Wisconsin\r\n468\r\nSiren, Wisconsin\r\n349\r\nSolon Springs, Wisconsin\r\n378\r\nSomerset, Wisconsin\r\n247\r\nSoo Lake, Wisconsin\r\n332\r\nSpencer, Wisconsin\r\n659\r\nSpider Lake, Wisconsin\r\n462\r\nSpooner, Wisconsin\r\n635\r\nSpreadeagle, Wisconsin\r\n696\r\nSpring Valley, Wisconsin\r\n778\r\nSpringbreak, Wisconsin\r\n766\r\nSpring Lake, Wisconsin\r\n772\r\nSpringsted, Wisconsin\r\n583\r\nSaint Croix Falls, Wisconsin\r\n483\r\nStanley, Wisconsin\r\n644\r\nStar Prar, Wisconsin\r\n248\r\nStetsonville, Wisconsin\r\n678\r\nStevens Point, Wisconsin\r\n341\r\n342\r\n344\r\n345\r\n346\r\n498\r\nStone Lake, Wisconsin\r\n865\r\nStratford, Wisconsin\r\n687\r\nStrum, Wisconsin\r\n695\r\nSugar Camp, Wisconsin\r\n272\r\nSuperior, Wisconsin\r\n392\r\n394\r\n398\r\n399\r\nTaylor, Wisconsin\r\n662\r\nThorp, Wisconsin\r\n669\r\nThree Lakes, Wisconsin\r\n546\r\nTigerton, Wisconsin\r\n535\r\nTomahawk, Wisconsin\r\n453\r\nTrade Lake, Wisconsin\r\n488\r\nTurtle Lake, Wisconsin\r\n986\r\nTwin Bridge, Wisconsin\r\n757\r\nVesper, Wisconsin\r\n591\r\n569\r\nWabeno, Wisconsin\r\n473\r\nWashburn, Wisconsin\r\n373\r\nWaupaca, Wisconsin\r\n256\r\n258\r\nWausau, Wisconsin\r\n843\r\n355\r\n359\r\n571\r\n573\r\n576\r\n675\r\n842\r\n845\r\n847\r\n848\r\n994\r\nWausaukee, Wisconsin\r\n856\r\nWebb Lake, Wisconsin\r\n259\r\nWebster, Wisconsin\r\n866\r\nWeyerhauser, Wisconsin\r\n353\r\nWheeler, Wisconsin\r\n632\r\nWhite Lake, Wisconsin\r\n882\r\nWhitehall, Wisconsin\r\n538\r\nWinter, Wisconsin\r\n266\r\nWisconsinerpond, Wisconsin\r\n325\r\n421\r\n422\r\n423\r\n424\r\n572\r\nWittenberg, Wisconsin\r\n253\r\nWoodville, Wisconsin\r\n698\r\n\u00035Unknown prefix code (715) - Wisconsin\r\n"
  },
  {
    "path": "install/regions/regions.716",
    "content": "Akron, New York\r\n542\r\nAlbion, New York\r\n589\r\nAlden, New York\r\n937\r\nAmherst, New York\r\n636\r\n688\r\n689\r\nAngelica, New York\r\n466\r\nAngola, New York\r\n549\r\nArcade, New York\r\n492\r\nAtlanta, New York\r\n534\r\nAttica, New York\r\n591\r\n997\r\nAvon, New York\r\n226\r\nBarker, New York\r\n795\r\nBatavia, New York\r\n343\r\n344\r\nBelfast, New York\r\n365\r\nBelmont, New York\r\n268\r\nBemus Point, New York\r\n386\r\nBergen, New York\r\n494\r\nBliss, New York\r\n322\r\nBolivar, New York\r\n928\r\nBoston, New York\r\n941\r\nBrockport, New York\r\n395\r\n637\r\nBrocton, New York\r\n792\r\nBuffalo\u00031/\u00032Bailey, New York\r\n891\r\n892\r\n893\r\n894\r\n895\r\n896\r\n897\r\n898\r\nBuffalo\u00031/\u00032Elmwood, New York\r\n644\r\n878\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\nBuffalo\u00031/\u00032Franklin, New York\r\n842\r\n843\r\n844\r\n845\r\n846\r\n847\r\n849\r\n851\r\n852\r\n853\r\n854\r\n855\r\n856\r\n857\r\n858\r\nBuffalo\u00031/\u00032Hertel, New York\r\n862\r\n873\r\n874\r\n875\r\n876\r\n877\r\n879\r\nBuffalo\u00031/\u00032South Park, New York\r\n821\r\n822\r\n823\r\n824\r\n825\r\n826\r\n827\r\n828\r\nBuffalo, New York\r\n472\r\n474\r\n498\r\n540\r\n550\r\n642\r\n643\r\n829\r\n840\r\n848\r\n859\r\n861\r\n863\r\n864\r\n866\r\n867\r\n868\r\n871\r\n890\r\n920\r\n977\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n838\r\n839\r\n841\r\nByron, New York\r\n548\r\nCaledonia, New York\r\n538\r\nCanandagua, New York\r\n394\r\n396\r\nCassadaga, New York\r\n595\r\nCastile, New York\r\n493\r\nCattaraugs, New York\r\n257\r\nCayuga\u00031/\u00032Williamsville, New York\r\n626\r\n631\r\n632\r\n633\r\n634\r\n635\r\nChaffee, New York\r\n496\r\nChautauqua, New York\r\n357\r\nCherry Creek, New York\r\n296\r\nChurchville, New York\r\n293\r\nClarence Centre, New York\r\n741\r\n759\r\nClymer, New York\r\n355\r\nCohocton, New York\r\n384\r\nCorfu, New York\r\n599\r\nCuba, New York\r\n968\r\nDalton, New York\r\n476\r\nDansville, New York\r\n335\r\nDarien, New York\r\n547\r\nDerby, New York\r\n947\r\nDunkirk, New York\r\n366\r\n441\r\nEast Pembroke, New York\r\n762\r\nEast Amherst, New York\r\n639\r\nEast Aurora, New York\r\n652\r\n655\r\n687\r\nEden, New York\r\n992\r\nElba, New York\r\n757\r\nEllicottville, New York\r\n699\r\nEllington, New York\r\n287\r\nErochester, New York\r\n248\r\n264\r\n381\r\n383\r\n385\r\n387\r\n586\r\nFairport, New York\r\n223\r\n377\r\n388\r\n421\r\n425\r\nFillmore, New York\r\n567\r\nFindley Lake, New York\r\n769\r\nForestville, New York\r\n965\r\nFranklinville, New York\r\n676\r\nFredonia, New York\r\n672\r\n673\r\n679\r\nFrench\u00031/\u00032Cheekowaga, New York\r\n668\r\nFrewsburg, New York\r\n569\r\nFriendship, New York\r\n973\r\nGasport, New York\r\n772\r\nGeneseo, New York\r\n243\r\n245\r\nGerry, New York\r\n985\r\nGowanda, New York\r\n532\r\nGrand Island\u00031/\u00032Tonawanda, New York\r\n623\r\n690\r\n691\r\n692\r\n693\r\n694\r\n695\r\n696\r\n743\r\n773\r\n774\r\n775\r\nHamburg, New York\r\n646\r\n648\r\n649\r\nHamlin, New York\r\n964\r\nHemlock, New York\r\n367\r\nHenrietta, New York\r\n321\r\n334\r\n359\r\nHilton, New York\r\n392\r\nHinsdale, New York\r\n557\r\nHolcomb, New York\r\n657\r\nHolland, New York\r\n537\r\nHolley, New York\r\n638\r\nHoneoye, New York\r\n229\r\nHoneoye Falls, New York\r\n582\r\n624\r\nJamestown, New York\r\n483\r\n485\r\n487\r\n488\r\n489\r\n499\r\n661\r\n664\r\n665\r\n484\r\nJava, New York\r\n457\r\nKendall, New York\r\n659\r\nKennedy, New York\r\n267\r\nLakewood, New York\r\n456\r\n763\r\nLancaster, New York\r\n651\r\n681\r\n683\r\n684\r\n685\r\n686\r\nLe Roy, New York\r\n768\r\nLeicester, New York\r\n382\r\nLewiston, New York\r\n754\r\nLimestone, New York\r\n925\r\nLittle Valley, New York\r\n938\r\nLivonia, New York\r\n346\r\nLockport, New York\r\n438\r\n433\r\n434\r\n439\r\nLyndonville, New York\r\n765\r\nMachias, New York\r\n353\r\nMayville, New York\r\n753\r\nMedina, New York\r\n798\r\nMiddleport, New York\r\n735\r\nMount Morris, New York\r\n658\r\nNaples, New York\r\n374\r\nNewfane, New York\r\n778\r\nNiagara Falls, New York\r\n236\r\n278\r\n282\r\n283\r\n284\r\n285\r\n286\r\n297\r\n298\r\nNorth Collins, New York\r\n337\r\nNunda, New York\r\n468\r\nOakfield, New York\r\n948\r\nOlean, New York\r\n372\r\n373\r\n375\r\n376\r\n378\r\n933\r\nOrchard Park, New York\r\n662\r\n667\r\nPanama, New York\r\n782\r\nPavilion, New York\r\n584\r\nPendleton, New York\r\n625\r\nPerry, New York\r\n237\r\nRandolph, New York\r\n358\r\nRansomville, New York\r\n791\r\nRipley, New York\r\n252\r\n736\r\nRochester, New York\r\n224\r\n234\r\n242\r\n251\r\n255\r\n262\r\n273\r\n277\r\n292\r\n327\r\n336\r\n339\r\n527\r\n528\r\n581\r\n732\r\n733\r\n734\r\n737\r\n738\r\n739\r\n747\r\n748\r\n771\r\n776\r\n779\r\n960\r\n971\r\n975\r\n221\r\n222\r\n225\r\n227\r\n232\r\n235\r\n238\r\n244\r\n247\r\n253\r\n254\r\n256\r\n258\r\n263\r\n266\r\n271\r\n272\r\n274\r\n275\r\n288\r\n323\r\n325\r\n328\r\n338\r\n342\r\n423\r\n424\r\n426\r\n427\r\n428\r\n429\r\n436\r\n442\r\n454\r\n458\r\n461\r\n464\r\n467\r\n473\r\n475\r\n477\r\n482\r\n544\r\n546\r\n588\r\n621\r\n647\r\n654\r\n663\r\n721\r\n722\r\n723\r\n724\r\n726\r\n729\r\n777\r\n781\r\n783\r\n865\r\n921\r\n950\r\n955\r\n974\r\n987\r\nRush, New York\r\n533\r\nRushford, New York\r\n437\r\nRushville, New York\r\n554\r\nSalamanca, New York\r\n945\r\nSanborn, New York\r\n731\r\nScottsville, New York\r\n889\r\nSherman, New York\r\n761\r\nShortsville, New York\r\n289\r\nSilver Creek, New York\r\n934\r\nSinclairville, New York\r\n962\r\nSouth Dayton, New York\r\n988\r\nSpencerpoint, New York\r\n352\r\n594\r\nSpringville, New York\r\n592\r\nSpringwater, New York\r\n669\r\nStanley, New York\r\n526\r\nSteamburg, New York\r\n351\r\n354\r\nStedman, New York\r\n789\r\nTonawanda, New York\r\n622\r\n628\r\n629\r\n744\r\nVarysburg, New York\r\n535\r\nVictor, New York\r\n398\r\n742\r\n924\r\nWest Webster, New York\r\n671\r\n787\r\nWanakah, New York\r\n627\r\nWarsaw, New York\r\n786\r\nWaterport, New York\r\n682\r\nWayland, New York\r\n728\r\nWebster, New York\r\n265\r\n422\r\n872\r\nWellsville, New York\r\n593\r\n596\r\nWest Seneca, New York\r\n656\r\n674\r\n675\r\n677\r\nWestfield, New York\r\n326\r\nWest Valley, New York\r\n942\r\nWilliamsville, New York\r\n645\r\nWilson, New York\r\n751\r\nWyoming, New York\r\n495\r\nYoungstown, New York\r\n745\r\n\u00035Unknown prefix code (716) - New York\r\n"
  },
  {
    "path": "install/regions/regions.717",
    "content": "Airville, Pennsylvania\r\n862\r\nAdamstown, Pennsylvania\r\n484\r\nAkron, Pennsylvania\r\n859\r\nAllensville, Pennsylvania\r\n483\r\nAnnville, Pennsylvania\r\n867\r\nAshland, Pennsylvania\r\n875\r\nAuburn, Pennsylvania\r\n754\r\nAvis, Pennsylvania\r\n753\r\n847\r\nBeach Lake, Pennsylvania\r\n729\r\nBeaver Springs, Pennsylvania\r\n658\r\nBeechcreek, Pennsylvania\r\n962\r\nBelleville, Pennsylvania\r\n935\r\nBentley Creek, Pennsylvania\r\n596\r\nBenton, Pennsylvania\r\n925\r\nBerwick, Pennsylvania\r\n752\r\n759\r\nBiglerville, Pennsylvania\r\n677\r\nBlain, Pennsylvania\r\n536\r\nBloomsburg, Pennsylvania\r\n380\r\n387\r\n389\r\n638\r\n784\r\nBlue Ridge Summit, Pennsylvania\r\n794\r\n878\r\nBrogue, Pennsylvania\r\n927\r\nBrooklyn, Pennsylvania\r\n289\r\nBrookside, Pennsylvania\r\n634\r\nBushkill, Pennsylvania\r\n588\r\nCanton, Pennsylvania\r\n673\r\nCarbondale, Pennsylvania\r\n281\r\n282\r\nCarlisle, Pennsylvania\r\n240\r\n243\r\n245\r\n249\r\n258\r\nCatawissa, Pennsylvania\r\n356\r\nCenter Moreld, Pennsylvania\r\n333\r\nChambersburg, Pennsylvania\r\n860\r\n261\r\n263\r\n264\r\n267\r\nChapman Lake, Pennsylvania\r\n254\r\nClarks Summit, Pennsylvania\r\n585\r\n586\r\n587\r\nClifford, Pennsylvania\r\n222\r\nCnynghmdrm, Pennsylvania\r\n788\r\nColumbia, Pennsylvania\r\n684\r\nCovington, Pennsylvania\r\n659\r\nCresco, Pennsylvania\r\n595\r\nDallas, Pennsylvania\r\n674\r\n675\r\nDalton, Pennsylvania\r\n563\r\nDanville, Pennsylvania\r\n850\r\n271\r\n275\r\nDauphin, Pennsylvania\r\n921\r\nDelta, Pennsylvania\r\n456\r\nDenver, Pennsylvania\r\n336\r\nDillsburg, Pennsylvania\r\n432\r\nDingmnsfry, Pennsylvania\r\n828\r\nDover, Pennsylvania\r\n292\r\nDry Run, Pennsylvania\r\n349\r\nDuncannon, Pennsylvania\r\n834\r\nDushore, Pennsylvania\r\n928\r\nEaglesmere, Pennsylvania\r\n525\r\nEast Berlin, Pennsylvania\r\n259\r\nElizabethtown, Pennsylvania\r\n361\r\n367\r\nElizabethville, Pennsylvania\r\n362\r\nElysburg, Pennsylvania\r\n672\r\nEphrata, Pennsylvania\r\n721\r\n733\r\n738\r\nEstella, Pennsylvania\r\n924\r\nEast Waterford, Pennsylvania\r\n734\r\nFactoryville, Pennsylvania\r\n945\r\nFairfield, Pennsylvania\r\n642\r\nFawn Grove, Pennsylvania\r\n382\r\nFayetteville, Pennsylvania\r\n352\r\nForest City, Pennsylvania\r\n785\r\nFrackville, Pennsylvania\r\n874\r\nFreeland, Pennsylvania\r\n636\r\nFriedensburg, Pennsylvania\r\n739\r\nFrystown, Pennsylvania\r\n933\r\nGalilee, Pennsylvania\r\n224\r\nGap, Pennsylvania\r\n442\r\nGettsburg, Pennsylvania\r\n338\r\n334\r\n337\r\nGirardville, Pennsylvania\r\n276\r\nGlen Rock, Pennsylvania\r\n227\r\n235\r\nGratz, Pennsylvania\r\n365\r\nGreencastle, Pennsylvania\r\n597\r\nHalifax, Pennsylvania\r\n896\r\nHallstead, Pennsylvania\r\n879\r\nHamlin, Pennsylvania\r\n689\r\nHanover, Pennsylvania\r\n630\r\n632\r\n633\r\n637\r\nHarding, Pennsylvania\r\n388\r\nHarford, Pennsylvania\r\n434\r\nHarrisburg, Pennsylvania\r\n231\r\n232\r\n233\r\n234\r\n236\r\n237\r\n238\r\n255\r\n257\r\n540\r\n541\r\n545\r\n558\r\n561\r\n564\r\n574\r\n579\r\n599\r\n652\r\n657\r\n731\r\n732\r\n737\r\n761\r\n763\r\n770\r\n772\r\n774\r\n780\r\n782\r\n783\r\n787\r\n939\r\n975\r\n986\r\n230\r\n571\r\n576\r\n671\r\n720\r\n728\r\n730\r\n760\r\n777\r\n979\r\n985\r\nHarveys Lake, Pennsylvania\r\n639\r\nHawley, Pennsylvania\r\n226\r\nHazleton, Pennsylvania\r\n450\r\n454\r\n455\r\n459\r\n970\r\nHensel, Pennsylvania\r\n548\r\nHershey, Pennsylvania\r\n520\r\n531\r\n533\r\n534\r\nHonesdale, Pennsylvania\r\n470\r\n253\r\nHughesville, Pennsylvania\r\n584\r\nHummelston, Pennsylvania\r\n566\r\nHuntington Mill, Pennsylvania\r\n864\r\nIckesburg, Pennsylvania\r\n438\r\nIntercourse, Pennsylvania\r\n768\r\nJackson, Pennsylvania\r\n756\r\nJefferson, Pennsylvania\r\n229\r\nJermyn, Pennsylvania\r\n876\r\nJersey Shore, Pennsylvania\r\n398\r\nJim Thorpe, Pennsylvania\r\n325\r\nJonestown, Pennsylvania\r\n861\r\n865\r\nKingston, Pennsylvania\r\n283\r\n287\r\n288\r\nKirkwood, Pennsylvania\r\n529\r\nKulpmont, Pennsylvania\r\n373\r\nLaceyville, Pennsylvania\r\n869\r\nLake Ariel, Pennsylvania\r\n698\r\nLake Como, Pennsylvania\r\n798\r\nLake Winola, Pennsylvania\r\n378\r\nLakewood, Pennsylvania\r\n467\r\nLancaster, Pennsylvania\r\n390\r\n572\r\n581\r\n951\r\n291\r\n293\r\n295\r\n299\r\n392\r\n393\r\n394\r\n396\r\n397\r\n399\r\n464\r\n560\r\n569\r\n575\r\n940\r\nLandisville, Pennsylvania\r\n898\r\nLansford, Pennsylvania\r\n645\r\nLaporte, Pennsylvania\r\n946\r\nLawrenceville, Pennsylvania\r\n827\r\nLawsville, Pennsylvania\r\n967\r\nLe Raysville, Pennsylvania\r\n744\r\nLebanon, Pennsylvania\r\n228\r\n270\r\n272\r\n273\r\n274\r\nLeola, Pennsylvania\r\n661\r\n656\r\nLeroy, Pennsylvania\r\n364\r\nLewisberry, Pennsylvania\r\n932\r\n938\r\nLewisburg, Pennsylvania\r\n522\r\n577\r\n523\r\n524\r\n568\r\nLewistown, Pennsylvania\r\n250\r\n242\r\n248\r\n543\r\nLiberty, Pennsylvania\r\n324\r\nLititz, Pennsylvania\r\n626\r\n627\r\nLittle Meadows, Pennsylvania\r\n623\r\nLittlestown, Pennsylvania\r\n359\r\nLiverpool, Pennsylvania\r\n444\r\nLock Haven, Pennsylvania\r\n748\r\n893\r\nLoganton, Pennsylvania\r\n725\r\nLoganville, Pennsylvania\r\n428\r\nLords Valley, Pennsylvania\r\n775\r\nLoyalsock, Pennsylvania\r\n433\r\n435\r\n478\r\nLoysville, Pennsylvania\r\n789\r\nLykens, Pennsylvania\r\n453\r\nMahanoy City, Pennsylvania\r\n773\r\nManchester, Pennsylvania\r\n266\r\nMandata, Pennsylvania\r\n425\r\n758\r\nManheim, Pennsylvania\r\n664\r\n665\r\nMansfield, Pennsylvania\r\n662\r\nMantzville, Pennsylvania\r\n386\r\nMarietta, Pennsylvania\r\n426\r\nMarion, Pennsylvania\r\n375\r\nMarysville, Pennsylvania\r\n957\r\nMatamoras, Pennsylvania\r\n491\r\nMc Adoo, Pennsylvania\r\n929\r\nMcAlisterville, Pennsylvania\r\n463\r\nMcConnelsburg, Pennsylvania\r\n485\r\n987\r\nMcKeansburg, Pennsylvania\r\n943\r\nMcVeytown, Pennsylvania\r\n899\r\nMechanicburg, Pennsylvania\r\n750\r\n796\r\n691\r\n697\r\n766\r\n790\r\n795\r\nMehoopany, Pennsylvania\r\n833\r\nMercersburg, Pennsylvania\r\n328\r\nMiddleburg, Pennsylvania\r\n837\r\nMiddletown, Pennsylvania\r\n944\r\n948\r\nMiddleby Center, Pennsylvania\r\n376\r\nMifflinburg, Pennsylvania\r\n922\r\n966\r\nMifflinton, Pennsylvania\r\n436\r\nMilford, Pennsylvania\r\n296\r\n686\r\nMill Hall, Pennsylvania\r\n726\r\nMillersburg, Pennsylvania\r\n692\r\nMillerston, Pennsylvania\r\n589\r\nMillersville, Pennsylvania\r\n871\r\n872\r\nMillerton, Pennsylvania\r\n537\r\nMillville, Pennsylvania\r\n458\r\nMilton, Pennsylvania\r\n742\r\nMinersville, Pennsylvania\r\n544\r\nMontgomery, Pennsylvania\r\n547\r\nMontrose, Pennsylvania\r\n278\r\nMoosic, Pennsylvania\r\n480\r\n451\r\n457\r\nMorris, Pennsylvania\r\n353\r\nMoscow, Pennsylvania\r\n842\r\nMount Carmel, Pennsylvania\r\n339\r\nMount Gretna, Pennsylvania\r\n964\r\nMount Hollyspring, Pennsylvania\r\n486\r\nMount Joy, Pennsylvania\r\n492\r\n653\r\nMount Pocono, Pennsylvania\r\n839\r\n894\r\nMountaintop, Pennsylvania\r\n474\r\nMountville, Pennsylvania\r\n285\r\nMount Pleasant Mills, Pennsylvania\r\n539\r\nMuhlenburg, Pennsylvania\r\n256\r\nMuncy Valley, Pennsylvania\r\n482\r\nMuncy, Pennsylvania\r\n546\r\nMyerstown, Pennsylvania\r\n866\r\nNanticoke, Pennsylvania\r\n735\r\n736\r\nNeedmore, Pennsylvania\r\n573\r\nNesquehnng, Pennsylvania\r\n669\r\nNew Albany, Pennsylvania\r\n363\r\nNew Oxford, Pennsylvania\r\n624\r\nNew Philadelphia, Pennsylvania\r\n277\r\nNew Bloomfield, Pennsylvania\r\n582\r\nNewburg, Pennsylvania\r\n423\r\nNewfoundland, Pennsylvania\r\n676\r\nNew Holland, Pennsylvania\r\n354\r\n355\r\nNew Milford, Pennsylvania\r\n465\r\nNewport, Pennsylvania\r\n567\r\nNewville, Pennsylvania\r\n776\r\nNicholson, Pennsylvania\r\n942\r\nNorth Umberland, Pennsylvania\r\n473\r\n490\r\nNoxen, Pennsylvania\r\n298\r\nNuangola, Pennsylvania\r\n678\r\n868\r\nNumidia, Pennsylvania\r\n799\r\nNuremberg, Pennsylvania\r\n384\r\nOlyphant, Pennsylvania\r\n383\r\n489\r\nOrangeville, Pennsylvania\r\n683\r\nOrwigsburg, Pennsylvania\r\n366\r\nOval, Pennsylvania\r\n745\r\nPalmyra, Pennsylvania\r\n838\r\nPine Grove, Pennsylvania\r\n345\r\nPittston, Pennsylvania\r\n430\r\n885\r\n650\r\n654\r\n655\r\n881\r\n883\r\nPleasantmount, Pennsylvania\r\n448\r\nPlymouth, Pennsylvania\r\n779\r\nPocono Lake, Pennsylvania\r\n643\r\n646\r\nPort Royal, Pennsylvania\r\n527\r\nPortland, Pennsylvania\r\n897\r\nPottsville, Pennsylvania\r\n449\r\n621\r\n622\r\n628\r\n640\r\n641\r\nQuaker Lake, Pennsylvania\r\n663\r\nQuarryville, Pennsylvania\r\n786\r\nRawlinsville, Pennsylvania\r\n284\r\nRed Lion, Pennsylvania\r\n244\r\n246\r\nReedsville, Pennsylvania\r\n667\r\nRenovo, Pennsylvania\r\n923\r\nRichfield, Pennsylvania\r\n694\r\nRingtown, Pennsylvania\r\n889\r\nRome, Pennsylvania\r\n247\r\nRoseville, Pennsylvania\r\n549\r\nRowland, Pennsylvania\r\n685\r\nRush, Pennsylvania\r\n934\r\nSaylorsburg, Pennsylvania\r\n992\r\nSayre, Pennsylvania\r\n882\r\n888\r\nSchaeferston, Pennsylvania\r\n949\r\nSchylkl Haven, Pennsylvania\r\n385\r\nScranton, Pennsylvania\r\n941\r\n341\r\n342\r\n343\r\n344\r\n346\r\n347\r\n348\r\n961\r\n963\r\n969\r\nSelins Grove, Pennsylvania\r\n372\r\n374\r\n743\r\n884\r\nShamokin, Pennsylvania\r\n644\r\n648\r\nShellsville, Pennsylvania\r\n469\r\nShenandoah, Pennsylvania\r\n462\r\nSherman, Pennsylvania\r\n461\r\nShickshenny, Pennsylvania\r\n542\r\nShippensburg, Pennsylvania\r\n530\r\n532\r\nShohola, Pennsylvania\r\n559\r\nSouth Canaan, Pennsylvania\r\n937\r\nSpring Grove, Pennsylvania\r\n225\r\nSpringville, Pennsylvania\r\n965\r\nSaint Clair, Pennsylvania\r\n429\r\nSaint Joseph, Pennsylvania\r\n553\r\nSaint Thomas, Pennsylvania\r\n369\r\nStewartston, Pennsylvania\r\n993\r\nStrasburg, Pennsylvania\r\n687\r\nStroudsburg, Pennsylvania\r\n223\r\n420\r\n421\r\n424\r\n460\r\n476\r\n620\r\n629\r\n841\r\nSunbury, Pennsylvania\r\n286\r\n988\r\nSusquehnna, Pennsylvania\r\n853\r\nSweet Valley, Pennsylvania\r\n477\r\nTamaqua, Pennsylvania\r\n668\r\nTaylor, Pennsylvania\r\n562\r\nThompson, Pennsylvania\r\n727\r\nThompsonton, Pennsylvania\r\n535\r\nTioga, Pennsylvania\r\n835\r\nTowanda, Pennsylvania\r\n268\r\n265\r\nTower City, Pennsylvania\r\n647\r\nTremont, Pennsylvania\r\n695\r\nTrevorton, Pennsylvania\r\n797\r\nTrout Run, Pennsylvania\r\n995\r\n998\r\nTroy, Pennsylvania\r\n297\r\nTrucksville, Pennsylvania\r\n690\r\n696\r\nTunkhnnock, Pennsylvania\r\n836\r\nTurbotville, Pennsylvania\r\n649\r\nUlster, Pennsylvania\r\n358\r\nUnion Dale, Pennsylvania\r\n679\r\nValleyview, Pennsylvania\r\n682\r\nWalenpapck, Pennsylvania\r\n857\r\nWapwallopn, Pennsylvania\r\n379\r\nWarfordsburg, Pennsylvania\r\n294\r\nWarren Center, Pennsylvania\r\n395\r\nWashingtonville, Pennsylvania\r\n437\r\nWatsontown, Pennsylvania\r\n538\r\nWaymart, Pennsylvania\r\n488\r\nWaynesboro, Pennsylvania\r\n749\r\n762\r\n765\r\nWeatherly, Pennsylvania\r\n427\r\nWellsboro, Pennsylvania\r\n723\r\n724\r\nWhitehaven, Pennsylvania\r\n443\r\n722\r\nWilksbarre, Pennsylvania\r\n472\r\n820\r\n821\r\n822\r\n823\r\n824\r\n825\r\n826\r\n829\r\n831\r\nWilliamsport, Pennsylvania\r\n321\r\n322\r\n323\r\n326\r\n327\r\n368\r\n494\r\n220\r\n320\r\n971\r\nWinterdale, Pennsylvania\r\n635\r\nWoolrich, Pennsylvania\r\n769\r\nWrightsville, Pennsylvania\r\n252\r\nWyalusing, Pennsylvania\r\n746\r\nWyoming, Pennsylvania\r\n693\r\nYork, Pennsylvania\r\n851\r\n870\r\n891\r\n741\r\n751\r\n755\r\n757\r\n764\r\n767\r\n771\r\n792\r\n840\r\n843\r\n845\r\n846\r\n848\r\n849\r\n852\r\n854\r\n873\r\n880\r\nYork Springs, Pennsylvania\r\n528\r\n\u00035Unknown prefix code (717) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/regions.718",
    "content": "New York City, New York\r\n204\r\n209\r\n217\r\n221\r\n224\r\n225\r\n226\r\n229\r\n230\r\n232\r\n233\r\n234\r\n235\r\n236\r\n237\r\n238\r\n240\r\n241\r\n244\r\n247\r\n248\r\n251\r\n252\r\n253\r\n256\r\n257\r\n258\r\n259\r\n260\r\n261\r\n262\r\n263\r\n265\r\n266\r\n267\r\n268\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n282\r\n284\r\n287\r\n291\r\n296\r\n297\r\n317\r\n318\r\n321\r\n322\r\n326\r\n327\r\n330\r\n331\r\n332\r\n335\r\n336\r\n337\r\n338\r\n339\r\n341\r\n342\r\n343\r\n345\r\n346\r\n347\r\n349\r\n351\r\n352\r\n353\r\n354\r\n356\r\n357\r\n358\r\n359\r\n361\r\n363\r\n366\r\n370\r\n372\r\n373\r\n375\r\n376\r\n377\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n389\r\n390\r\n392\r\n395\r\n397\r\n398\r\n403\r\n417\r\n421\r\n423\r\n424\r\n426\r\n428\r\n429\r\n434\r\n435\r\n436\r\n438\r\n439\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n461\r\n462\r\n463\r\n464\r\n465\r\n467\r\n468\r\n469\r\n470\r\n471\r\n472\r\n474\r\n476\r\n478\r\n479\r\n480\r\n481\r\n482\r\n485\r\n486\r\n489\r\n492\r\n493\r\n494\r\n495\r\n497\r\n498\r\n499\r\n507\r\n520\r\n522\r\n523\r\n525\r\n526\r\n527\r\n528\r\n529\r\n531\r\n533\r\n539\r\n541\r\n544\r\n545\r\n552\r\n557\r\n565\r\n571\r\n574\r\n575\r\n591\r\n592\r\n596\r\n599\r\n604\r\n615\r\n622\r\n624\r\n625\r\n626\r\n627\r\n628\r\n629\r\n630\r\n631\r\n632\r\n633\r\n634\r\n636\r\n638\r\n639\r\n641\r\n642\r\n643\r\n644\r\n645\r\n646\r\n647\r\n648\r\n649\r\n651\r\n656\r\n657\r\n658\r\n659\r\n667\r\n670\r\n672\r\n680\r\n692\r\n693\r\n694\r\n698\r\n699\r\n706\r\n712\r\n720\r\n721\r\n723\r\n726\r\n727\r\n728\r\n729\r\n735\r\n738\r\n739\r\n740\r\n743\r\n745\r\n746\r\n748\r\n754\r\n755\r\n756\r\n760\r\n761\r\n762\r\n763\r\n764\r\n767\r\n768\r\n769\r\n771\r\n773\r\n774\r\n776\r\n778\r\n779\r\n780\r\n782\r\n783\r\n784\r\n786\r\n788\r\n789\r\n793\r\n797\r\n802\r\n803\r\n805\r\n816\r\n821\r\n826\r\n827\r\n830\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n840\r\n843\r\n845\r\n846\r\n847\r\n848\r\n849\r\n851\r\n852\r\n853\r\n854\r\n855\r\n856\r\n857\r\n858\r\n859\r\n868\r\n871\r\n875\r\n876\r\n883\r\n886\r\n891\r\n894\r\n895\r\n896\r\n897\r\n898\r\n899\r\n917\r\n919\r\n921\r\n922\r\n927\r\n932\r\n934\r\n935\r\n937\r\n938\r\n939\r\n941\r\n942\r\n945\r\n946\r\n948\r\n949\r\n951\r\n953\r\n955\r\n956\r\n961\r\n962\r\n963\r\n965\r\n966\r\n967\r\n968\r\n969\r\n972\r\n974\r\n977\r\n978\r\n979\r\n981\r\n983\r\n984\r\n987\r\n990\r\n995\r\n996\r\n997\r\n998\r\n999\r\n844\r\n985\r\n286\r\n289\r\n290\r\n298\r\n553\r\n926\r\n952\r\n223\r\n281\r\n264\r\n350\r\n668\r\n688\r\n980\r\n982\r\n220\r\n292\r\n293\r\n294\r\n295\r\n299\r\n328\r\n329\r\n364\r\n365\r\n367\r\n378\r\n402\r\n518\r\n538\r\n542\r\n562\r\n563\r\n579\r\n583\r\n584\r\n585\r\n588\r\n589\r\n590\r\n617\r\n665\r\n681\r\n716\r\n731\r\n733\r\n817\r\n842\r\n893\r\n901\r\n933\r\n960\r\n991\r\n992\r\n993\r\n409\r\n430\r\n597\r\n792\r\n822\r\n823\r\n824\r\n828\r\n829\r\n863\r\n892\r\n904\r\n918\r\n931\r\n231\r\n320\r\n324\r\n325\r\n379\r\n405\r\n515\r\n519\r\n536\r\n543\r\n547\r\n548\r\n549\r\n601\r\n652\r\n653\r\n654\r\n655\r\n671\r\n796\r\n798\r\n881\r\n882\r\n884\r\n885\r\n920\r\n994\r\n201\r\n219\r\n242\r\n243\r\n245\r\n246\r\n249\r\n250\r\n255\r\n269\r\n283\r\n288\r\n344\r\n348\r\n369\r\n394\r\n399\r\n404\r\n422\r\n425\r\n427\r\n473\r\n487\r\n488\r\n490\r\n491\r\n567\r\n598\r\n722\r\n752\r\n753\r\n757\r\n890\r\n940\r\n368\r\n714\r\n334\r\n396\r\n416\r\n433\r\n546\r\n595\r\n766\r\n777\r\n460\r\n\u00035Unknown prefix code (718) - New York City, New York\r\n"
  },
  {
    "path": "install/regions/regions.719",
    "content": "Agate, Colorado\r\n764\r\nAguilar, Colorado\r\n941\r\nAlamosa, Colorado\r\n580\r\n588\r\n949\r\n589\r\nAntonito, Colorado\r\n376\r\nArriba, Colorado\r\n768\r\nBeulah, Colorado\r\n485\r\nBlanca, Colorado\r\n379\r\nBranson, Colorado\r\n946\r\nBristol Granada, Colorado\r\n734\r\nBuena Vista, Colorado\r\n395\r\nBurlington, Colorado\r\n346\r\nCalhan, Colorado\r\n347\r\nCampo, Colorado\r\n787\r\nCanon City, Colorado\r\n269\r\n275\r\n429\r\n969\r\nCenter, Colorado\r\n754\r\nCheraw, Colorado\r\n853\r\nCheyenne Wl, Colorado\r\n767\r\nColorado Springs, Colorado\r\n536\r\n556\r\n572\r\n573\r\n386\r\n440\r\n442\r\n443\r\n444\r\n575\r\n660\r\n522\r\n535\r\n526\r\n260\r\n282\r\n338\r\n380\r\n382\r\n389\r\n390\r\n391\r\n392\r\n471\r\n472\r\n473\r\n475\r\n481\r\n488\r\n495\r\n520\r\n527\r\n528\r\n531\r\n540\r\n548\r\n550\r\n554\r\n570\r\n574\r\n576\r\n577\r\n578\r\n579\r\n590\r\n591\r\n592\r\n593\r\n594\r\n596\r\n597\r\n598\r\n599\r\n630\r\n632\r\n633\r\n634\r\n635\r\n636\r\n637\r\n661\r\n684\r\n685\r\n687\r\n777\r\n898\r\nColorado City, Colorado\r\n676\r\nCreede, Colorado\r\n658\r\nCrestone, Colorado\r\n256\r\nCripple Creek, Colorado\r\n689\r\nDel Norte, Colorado\r\n657\r\n873\r\nEads, Colorado\r\n438\r\nEl Paso, Colorado\r\n683\r\nFairplay, Colorado\r\n836\r\nFlagler, Colorado\r\n765\r\nFlorence, Colorado\r\n372\r\n784\r\nFowler, Colorado\r\n263\r\nGardner, Colorado\r\n746\r\nGenoa, Colorado\r\n740\r\n763\r\nHartman, Colorado\r\n739\r\nHaswell, Colorado\r\n436\r\nHolly, Colorado\r\n537\r\nHoward, Colorado\r\n479\r\n942\r\nHugo, Colorado\r\n743\r\nKarval, Colorado\r\n446\r\nKenton, Colorado\r\n461\r\nKim, Colorado\r\n643\r\nKit Carson, Colorado\r\n962\r\nLa Jara, Colorado\r\n274\r\nLa Junta, Colorado\r\n469\r\n929\r\n980\r\n384\r\nLa Veta, Colorado\r\n742\r\nLake George, Colorado\r\n748\r\nLamar, Colorado\r\n688\r\n939\r\n336\r\n829\r\nLas Animas, Colorado\r\n456\r\nLeadville, Colorado\r\n486\r\nLimon, Colorado\r\n773\r\n775\r\nManassa, Colorado\r\n843\r\nManzanola, Colorado\r\n462\r\nMonte Vista, Colorado\r\n850\r\n852\r\nMosca, Colorado\r\n378\r\nOrdway, Colorado\r\n267\r\nPeyton, Colorado\r\n749\r\nPueblo, Colorado\r\n250\r\n542\r\n543\r\n544\r\n545\r\n546\r\n547\r\n549\r\n560\r\n561\r\n564\r\n566\r\n568\r\n584\r\n585\r\n947\r\n948\r\n582\r\n583\r\nRocky Ford, Colorado\r\n254\r\nRush, Colorado\r\n478\r\nRye, Colorado\r\n489\r\nSaguache, Colorado\r\n655\r\nSalida, Colorado\r\n539\r\nSan Luis, Colorado\r\n672\r\nSheridan Lake, Colorado\r\n729\r\nSimla, Colorado\r\n541\r\nSpringfield, Colorado\r\n523\r\nStratton, Colorado\r\n349\r\n348\r\nTowner, Colorado\r\n727\r\nTrinidad, Colorado\r\n680\r\n859\r\n979\r\n846\r\nTwo Buttes, Colorado\r\n326\r\nWalsenburg, Colorado\r\n738\r\n989\r\nWalsh, Colorado\r\n324\r\nWest Kanorado, Colorado\r\n397\r\nWestcliffe, Colorado\r\n783\r\nWestmanter, Colorado\r\n498\r\nWeston, Colorado\r\n868\r\n\u00035Unknown prefix code (719) - Colorado\r\n"
  },
  {
    "path": "install/regions/regions.740",
    "content": "Lancaster, Ohio\r\n681\r\nSteubenville, Ohio\r\n266\r\n\u00035Unknown prefix code (740) - Ohio\u00030\r\n"
  },
  {
    "path": "install/regions/regions.757",
    "content": "Newport News, Virginia\r\n874\r\n877\r\n833\r\nVirginia Beach, Virginia\r\n473\r\n523\r\n\u00035Unknown prefix code (757) - Virginia\r\n"
  },
  {
    "path": "install/regions/regions.760",
    "content": "Carlsbad, California\r\n729\r\nHesperia, California\r\n244\r\n947\r\n\u00035Unknown prefix code (760) - California\r\n"
  },
  {
    "path": "install/regions/regions.770",
    "content": "Acworth, Georgia\r\n499\r\n917\r\n974\r\n975\r\nAdairsville, Georgia\r\n773\r\nAlpharetta, Georgia\r\n343\r\n410\r\n442\r\n475\r\n664\r\n665\r\n667\r\n740\r\n750\r\n751\r\n772\r\nAtlanta, Georgia\r\n247\r\n533\r\n627\r\nAustell, Georgia\r\n732\r\n739\r\n819\r\n941\r\n948\r\nBarnesville, Georgia\r\n358\r\nBogart Stahm, Georgia\r\n725\r\nBremen, Georgia\r\n537\r\n824\r\nBuchanan, Georgia\r\n646\r\nBowdon, Georgia\r\n258\r\nBuford, Georgia\r\n271\r\n932\r\n945\r\nCedartown, Georgia\r\n748\r\n749\r\nCanton, Georgia\r\n345\r\n479\r\n704\r\n720\r\nCarrollton, Georgia\r\n214\r\n830\r\n832\r\n834\r\n836\r\nCartersville, Georgia\r\n382\r\n386\r\n387\r\n606\r\nChamblee, Georgia\r\n260\r\n348\r\n353\r\n390\r\n391\r\n392\r\n393\r\n394\r\n395\r\n396\r\n399\r\n451\r\n452\r\n454\r\n455\r\n457\r\n458\r\n488\r\n512\r\n604\r\n661\r\n668\r\n671\r\n698\r\n804\r\n839\r\n890\r\n901\r\n913\r\n915\r\n936\r\n986\r\nClermont, Georgia\r\n983\r\nConyers, Georgia\r\n388\r\n483\r\n760\r\n785\r\n860\r\n918\r\n922\r\n929\r\nCovington, Georgia\r\n385\r\n784\r\n786\r\n787\r\nCumming, Georgia\r\n781\r\n844\r\n887\r\n889\r\nDallas, Georgia\r\n443\r\n445\r\nDouglasville, Georgia\r\n489\r\n920\r\n942\r\n949\r\nDuluth, Georgia\r\n418\r\n476\r\n497\r\n623\r\n813\r\nDunwoody, Georgia\r\n393\r\nFairburn, Georgia\r\n306\r\n774\r\n964\r\n969\r\nFayetteville, Georgia\r\n460\r\n461\r\n487\r\n719\r\nFlowery Birch, Georgia\r\n967\r\nGainesville, Georgia\r\n287\r\n503\r\n519\r\n531\r\n532\r\n534\r\n535\r\n536\r\n718\r\nGrantville, Georgia\r\n583\r\nGriffin, Georgia\r\n227\r\n228\r\n229\r\n412\r\n467\r\nHampton, Georgia\r\n327\r\n707\r\n946\r\nJackson, Georgia\r\n775\r\n504\r\nJonesboro, Georgia\r\n471\r\n473\r\n477\r\n478\r\n603\r\n907\r\n960\r\n961\r\n968\r\n991\r\n994\r\n996\r\n997\r\nKingston, Georgia\r\n336\r\nLawrenceville, Georgia\r\n339\r\n682\r\n736\r\n806\r\n513\r\n822\r\n962\r\n963\r\n972\r\n978\r\n979\r\n985\r\n995\r\nLithia Springs, Georgia\r\n944\r\nLithonia, Georgia\r\n482\r\n484\r\nLoganville, Georgia\r\n466\r\nLula, Georgia\r\n869\r\nLuthersville, Georgia\r\n927\r\nMarblehill, Georgia\r\n893\r\nMarietta, Georgia\r\n419\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n494\r\n499\r\n509\r\n514\r\n528\r\n565\r\n578\r\n579\r\n590\r\n919\r\n971\r\n973\r\n977\r\n793\r\nMcdonough, Georgia\r\n914\r\n954\r\n957\r\n\r\nMonroe, Georgia\r\n207\r\n267\r\nMonticello, Georgia\r\n468\r\nNelson, Georgia\r\n735\r\nNewnan, Georgia\r\n251\r\n253\r\n254\r\n301\r\n304\r\n502\r\nNorcross, Georgia\r\n242\r\n245\r\n246\r\n263\r\n368\r\n409\r\n416\r\n417\r\n441\r\n446\r\n447\r\n448\r\n449\r\n610\r\n662\r\n729\r\n798\r\n840\r\n902\r\n903\r\n931\r\nPalmetto, Georgia\r\n463\r\nPanola, Georgia\r\n322\r\n593\r\n808\r\n981\r\n987\r\nPowder Springs, Georgia\r\n439\r\n943\r\nRockmart, Georgia\r\n684\r\nRoopville, Georgia\r\n854\r\nRoswell, Georgia\r\n518\r\n587\r\n594\r\n640\r\n641\r\n642\r\n992\r\n993\r\n998\r\nSenoia, Georgia\r\n599\r\nSocial Circle, Georgia\r\n464\r\nSmyrna, Georgia\r\n319\r\n333\r\n431\r\n432\r\n433\r\n434\r\n435\r\n436\r\n438\r\n612\r\n618\r\n644\r\n801\r\n835\r\n850\r\n852\r\n859\r\n916\r\n933\r\n951\r\n952\r\n953\r\n955\r\n956\r\n980\r\n984\r\n988\r\n563\r\nStockbridge, Georgia\r\n389\r\n474\r\n507\r\nStone Mountain, Georgia\r\n413\r\n469\r\n498\r\n879\r\nSnellville, Georgia\r\n736\r\nTallapoosa, Georgia\r\n574\r\nTemple, Georgia\r\n562\r\nTucker, Georgia\r\n270\r\n279\r\n381\r\n414\r\n491\r\n493\r\n496\r\n564\r\n621\r\n717\r\n723\r\n908\r\n921\r\n923\r\n925\r\n934\r\n938\r\n939\r\nVilla Rica, Georgia\r\n459\r\nWest Point, Georgia\r\n643\r\n645\r\nWinder, Georgia\r\n307\r\n601\r\n867\r\nWoodstock, Georgia\r\n516\r\n591\r\n924\r\n926\r\n928\r\n\u00035Unknown prefix code (770) - Georgia\r\n"
  },
  {
    "path": "install/regions/regions.786",
    "content": "Miami-Dade County, Florida\r\n000\r\n911\r\n\u00035Unknown prefix code (786) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.800",
    "content": "\u00032 Anywhere - a FREE call!\u00030\r\n800\r\n"
  },
  {
    "path": "install/regions/regions.801",
    "content": "Private/Unknown number\r\n000\r\nAlta\u00031/\u00032Snowbird, Utah\r\n742\r\nAltamont, Utah\r\n454\r\nAmerican Fork, Utah\r\n756\r\n763\r\nAntimony, Utah\r\n624\r\nApple Valley, Utah\r\n877\r\nBear River City, Utah\r\n279\r\nBeaver, Utah\r\n438\r\nBeryl, Utah\r\n439\r\nBicknell, Utah\r\n425\r\nBlanding, Utah\r\n678\r\nBluff, Utah\r\n672\r\nBoulder, Utah\r\n335\r\nBountiful, Utah\r\n292\r\n295\r\n268\r\n295\r\n298\r\n299\r\nBrian Head, Utah\r\n677\r\nBrigham City, Utah\r\n720\r\n723\r\n729\r\n730\r\n734\r\n740\r\n744\r\nBryce Canyon, Utah\r\n834\r\nCainville, Utah\r\n456\r\nCannonville, Utah\r\n679\r\nCastledale, Utah\r\n381\r\n748\r\nCedar City, Utah\r\n559\r\n590\r\n865\r\n990\r\nChristmas Meadows, Utah\r\n642\r\nCircleville, Utah\r\n577\r\nClearfield\u00031/\u00032Sunset\u00031/\u00032Roy, Utah\r\n771\r\n773\r\n774\r\n775\r\n776\r\n779\r\n825\r\nCleveland, Utah\r\n653\r\nCoalville, Utah\r\n336\r\nCottonwood, Utah\r\n942\r\n943\r\n944\r\n947\r\nDangling Rope, Utah\r\n661\r\nDelta, Utah\r\n864\r\nDove Creek, Utah\r\n746\r\nDuchesne, Utah\r\n738\r\n822\r\nDuck Creek, Utah\r\n682\r\nDugway, Utah\r\n831\r\nDutch John, Utah\r\n880\r\n885\r\nEast Carbon, Utah\r\n888\r\nEmery, Utah\r\n286\r\nEnterprise, Utah\r\n878\r\nEphraim, Utah\r\n283\r\nEscalante, Utah\r\n826\r\nEureka, Utah\r\n433\r\nFairview, Utah\r\n427\r\nFarmington, Utah\r\n451\r\nFerron, Utah\r\n384\r\nFielding, Utah\r\n458\r\nFillmore, Utah\r\n743\r\nFlattop, Utah\r\n646\r\nFountain Green, Utah\r\n445\r\nFruitland, Utah\r\n548\r\nGarden City, Utah\r\n946\r\nGarrison, Utah\r\n855\r\nGlenn Canyon City, Utah\r\n675\r\nGoshen, Utah\r\n667\r\nGreendale, Utah\r\n889\r\nGreen River, Utah\r\n564\r\nGrouse Creek, Utah\r\n747\r\nGunnison, Utah\r\n528\r\nHalchita, Utah\r\n739\r\nHanksville, Utah\r\n542\r\nHeber City, Utah\r\n654\r\nHelper, Utah\r\n472\r\nHiawatha, Utah\r\n343\r\nHildale, Utah\r\n874\r\nHill AFB, Utah\r\n777\r\nHolden, Utah\r\n795\r\nHolladay, Utah\r\n272\r\n273\r\n277\r\n278\r\nHowell, Utah\r\n471\r\n863\r\nHuntington, Utah\r\n687\r\nHuntsville, Utah\r\n745\r\nHurricane, Utah\r\n635\r\nHyrum, Utah\r\n245\r\nIbapah, Utah\r\n234\r\nKamas, Utah\r\n783\r\nKanab, Utah\r\n644\r\nKanosh, Utah\r\n759\r\nKaysville\u00031/\u00032Layton, Utah\r\n540\r\n543\r\n544\r\n546\r\n547\r\n549\r\n552\r\nKearns, Utah\r\n962\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\nKoosharem, Utah\r\n638\r\nLa Sal, Utah\r\n686\r\nLapoint, Utah\r\n247\r\nLehi, Utah\r\n768\r\nLake Powell, Utah\r\n684\r\nLoa, Utah\r\n836\r\nLogan, Utah\r\n750\r\n751\r\n752\r\n753\r\n755\r\n757\r\n769\r\n770\r\nLynndyl, Utah\r\n857\r\nMagna, Utah\r\n250\r\n251\r\nManila, Utah\r\n780\r\n784\r\nManti, Utah\r\n835\r\nMarysvale, Utah\r\n326\r\nMeadow, Utah\r\n842\r\nMexican Hat, Utah\r\n683\r\nMidvale\u00031/\u00032Sandy, Utah\r\n252\r\n254\r\n255\r\n256\r\n561\r\n562\r\n565\r\n566\r\n569\r\n571\r\n572\r\nMidvale, Utah\r\n253\r\n567\r\n568\r\nMilford, Utah\r\n387\r\nMinersville, Utah\r\n386\r\nMoab, Utah\r\n259\r\nMonroe, Utah\r\n527\r\nMonticello, Utah\r\n587\r\nMonument Valley, Utah\r\n727\r\nMorgan, Utah\r\n829\r\n876\r\nMoroni, Utah\r\n436\r\nMount Pleasant, Utah\r\n462\r\nMount Zmcrkath, Utah\r\n651\r\nMurray, Utah\r\n261\r\n262\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n287\r\n288\r\nNeola, Utah\r\n353\r\nNephi, Utah\r\n623\r\nOak City, Utah\r\n846\r\nOgden, Utah\r\n391\r\n392\r\n393\r\n394\r\n399\r\n476\r\n479\r\n620\r\n621\r\n625\r\n626\r\n627\r\n629\r\n670\r\n728\r\n731\r\n732\r\n778\r\n782\r\n786\r\nOrderville, Utah\r\n648\r\nOrem, Utah\r\n224\r\nPanguitch, Utah\r\n676\r\n735\r\nPark City, Utah\r\n640\r\n645\r\n647\r\n649\r\n659\r\nPark Valley, Utah\r\n871\r\nParowan, Utah\r\n477\r\nPartoun, Utah\r\n693\r\nPayson, Utah\r\n465\r\n754\r\nPleasant Grove, Utah\r\n785\r\n796\r\nPortage, Utah\r\n866\r\nPrice, Utah\r\n637\r\n650\r\n669\r\nProvo, Utah\r\n221\r\n222\r\n223\r\n225\r\n226\r\n227\r\n228\r\n319\r\n342\r\n344\r\n345\r\n369\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n380\r\n429\r\n470\r\nRandlett, Utah\r\n545\r\nRandolph, Utah\r\n793\r\nRichfield, Utah\r\n896\r\n897\r\n970\r\nRichmond, Utah\r\n258\r\nRoosevelt, Utah\r\n722\r\n820\r\n823\r\nRush Valley, Utah\r\n837\r\nSalina, Utah\r\n529\r\nSalt Lake City, Utah\r\n220\r\n230\r\n237\r\n240\r\n246\r\n249\r\n297\r\n320\r\n321\r\n322\r\n325\r\n328\r\n350\r\n355\r\n359\r\n363\r\n364\r\n366\r\n442\r\n460\r\n461\r\n464\r\n466\r\n467\r\n468\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n521\r\n522\r\n524\r\n526\r\n530\r\n531\r\n532\r\n533\r\n534\r\n535\r\n536\r\n537\r\n538\r\n539\r\n550\r\n560\r\n570\r\n573\r\n575\r\n576\r\n578\r\n579\r\n580\r\n581\r\n582\r\n583\r\n584\r\n585\r\n586\r\n588\r\n594\r\n595\r\n596\r\n597\r\n598\r\n599\r\n633\r\n799\r\n933\r\n960\r\n972\r\n973\r\n974\r\n975\r\n976\r\n977\r\nScipio, Utah\r\n758\r\nScofield, Utah\r\n448\r\nSmithfield, Utah\r\n563\r\nSnowville, Utah\r\n872\r\nSoldier Summit, Utah\r\n870\r\nSpanish Fork, Utah\r\n423\r\n798\r\n873\r\nSpringdale, Utah\r\n772\r\nSpringville, Utah\r\n489\r\nSaint George, Utah\r\n574\r\n628\r\n632\r\n634\r\n673\r\n674\r\n879\r\n920\r\n680\r\nTabiona, Utah\r\n848\r\nThatcher, Utah\r\n854\r\nThompson, Utah\r\n285\r\nTicaboo, Utah\r\n788\r\nTooele, Utah\r\n830\r\n833\r\n840\r\n849\r\n882\r\n884\r\nTremonton, Utah\r\n257\r\nVernal, Utah\r\n781\r\n789\r\n790\r\n828\r\nVernon, Utah\r\n839\r\nWasatch, Utah\r\n289\r\nWendover, Utah\r\n665\r\nYost, Utah\r\n827\r\n\u00035Unknown prefix code (801) - Utah\r\n"
  },
  {
    "path": "install/regions/regions.802",
    "content": "Addison, Vermont\r\n759\r\nAlbany, Vermont\r\n755\r\nAlburg, Vermont\r\n796\r\nArlington, Vermont\r\n375\r\nBarnet, Vermont\r\n633\r\nBarre, Vermont\r\n249\r\n476\r\n479\r\nBarton, Vermont\r\n525\r\nBellows Falls, Vermont\r\n463\r\nBennington, Vermont\r\n442\r\n447\r\nBenson, Vermont\r\n537\r\nBethel, Vermont\r\n234\r\nBloomfield, Vermont\r\n962\r\nBradford, Vermont\r\n222\r\nBrandon, Vermont\r\n247\r\nBrattlebo, Vermont\r\n258\r\n254\r\n257\r\nBridgeport, Vermont\r\n758\r\nBridgewater, Vermont\r\n672\r\nBristol, Vermont\r\n453\r\nBrookfield, Vermont\r\n276\r\nBurlington, Vermont\r\n343\r\n654\r\n655\r\n656\r\n657\r\n658\r\n660\r\n860\r\n862\r\n863\r\n864\r\n865\r\n951\r\n985\r\nCabot, Vermont\r\n563\r\nCanaan, Vermont\r\n266\r\nCastleton, Vermont\r\n468\r\nCharlotte, Vermont\r\n425\r\nChelsea, Vermont\r\n685\r\nChester, Vermont\r\n875\r\nConcord, Vermont\r\n695\r\nCornwall, Vermont\r\n462\r\nCraftsbury, Vermont\r\n586\r\nCuttingsville, Vermont\r\n492\r\nDanby, Vermont\r\n293\r\nDanville, Vermont\r\n684\r\nDerby Line, Vermont\r\n873\r\nDerby, Vermont\r\n766\r\nDorset, Vermont\r\n867\r\nEast Corinth, Vermont\r\n439\r\nEast Fairfield, Vermont\r\n827\r\nEastcalais, Vermont\r\n456\r\nEnosburg Falls, Vermont\r\n933\r\nEssex Junction, Vermont\r\n769\r\n871\r\n872\r\n878\r\n879\r\nFair Haven, Vermont\r\n265\r\nFairfax, Vermont\r\n849\r\nFairlee, Vermont\r\n333\r\nFranklin, Vermont\r\n285\r\nGrafton, Vermont\r\n843\r\nGrand Isle, Vermont\r\n372\r\nGreensboro, Vermont\r\n533\r\nGroton, Vermont\r\n584\r\nGuildhall, Vermont\r\n328\r\nHardwick, Vermont\r\n472\r\nHartland, Vermont\r\n436\r\nHinesburg, Vermont\r\n482\r\nHubbardton, Vermont\r\n273\r\nIs L, Vermont\r\n928\r\nIslandpond, Vermont\r\n723\r\nJacksonville, Vermont\r\n368\r\nJamaica, Vermont\r\n874\r\nJeffersonville, Vermont\r\n644\r\nJohnson, Vermont\r\n635\r\nLemington, Vermont\r\n277\r\nLudlow, Vermont\r\n228\r\nLunenburg, Vermont\r\n892\r\nLyndonville, Vermont\r\n626\r\nMaidstone, Vermont\r\n676\r\nManchester, Vermont\r\n362\r\nMarshfield, Vermont\r\n426\r\nMiddlebury, Vermont\r\n388\r\nMiddleton Springs, Vermont\r\n235\r\nMilton, Vermont\r\n893\r\nMontgomery, Vermont\r\n326\r\nMontpelier, Vermont\r\n223\r\n229\r\n371\r\n828\r\nMorgan, Vermont\r\n895\r\nMorrisville, Vermont\r\n888\r\nMount Holly, Vermont\r\n259\r\nNewbury, Vermont\r\n866\r\nNewfane, Vermont\r\n365\r\nNewport, Vermont\r\n334\r\nNorth Troy, Vermont\r\n988\r\nNorthfield, Vermont\r\n485\r\nNorton, Vermont\r\n822\r\nNorwich, Vermont\r\n649\r\nOrleans, Vermont\r\n754\r\nOrwell, Vermont\r\n948\r\nPanton, Vermont\r\n475\r\nPawlet, Vermont\r\n325\r\nPeacham, Vermont\r\n592\r\nPerkinsville, Vermont\r\n263\r\nPittsfield, Vermont\r\n746\r\nPittsford, Vermont\r\n483\r\nPlainfield, Vermont\r\n454\r\nPoultney, Vermont\r\n287\r\nPownal, Vermont\r\n823\r\nProctor, Vermont\r\n459\r\nProctorsville, Vermont\r\n226\r\nPutney, Vermont\r\n387\r\nRandolph, Vermont\r\n728\r\nReading, Vermont\r\n484\r\nReadsboro, Vermont\r\n423\r\nRichford, Vermont\r\n848\r\nRichmond, Vermont\r\n434\r\nRochester, Vermont\r\n767\r\nRupert, Vermont\r\n394\r\nRutland, Vermont\r\n236\r\n770\r\n772\r\n747\r\n773\r\n775\r\nSalisbury, Vermont\r\n352\r\nSaxtons River, Vermont\r\n869\r\nSherburne, Vermont\r\n422\r\nShoreham, Vermont\r\n897\r\nSouth Londondry, Vermont\r\n297\r\n824\r\nSouth Royalton, Vermont\r\n763\r\nSouth Strafford, Vermont\r\n765\r\nSpringfield, Vermont\r\n885\r\n886\r\nSaint Albans, Vermont\r\n524\r\n527\r\nSaint Johnsby, Vermont\r\n748\r\nStamford, Vermont\r\n694\r\nStowe, Vermont\r\n253\r\nSwanton, Vermont\r\n868\r\nThetford, Vermont\r\n785\r\nTroy, Vermont\r\n744\r\nTunbridge, Vermont\r\n889\r\nUnderhill, Vermont\r\n899\r\nVergennes, Vermont\r\n877\r\nWaitsfield, Vermont\r\n496\r\n583\r\nWallingford, Vermont\r\n446\r\nWardsboro, Vermont\r\n896\r\nWashington, Vermont\r\n883\r\nWaterbury, Vermont\r\n241\r\n244\r\nWeatherfield, Vermont\r\n546\r\nWells, Vermont\r\n645\r\nWells River, Vermont\r\n757\r\nWest Burke, Vermont\r\n467\r\nWest Newbury, Vermont\r\n429\r\nWest Rutland, Vermont\r\n438\r\nWestminister, Vermont\r\n722\r\nWeybridge, Vermont\r\n545\r\nWhite River, Vermont\r\n238\r\n295\r\n296\r\n741\r\n955\r\nWhiting, Vermont\r\n623\r\nWilliamston, Vermont\r\n433\r\nWilliamsville, Vermont\r\n348\r\nWilmington, Vermont\r\n464\r\nWindsor, Vermont\r\n674\r\nWoodstock, Vermont\r\n457\r\n\u00035Unknown prefix code (802) - Vermont\r\n"
  },
  {
    "path": "install/regions/regions.803",
    "content": "Aiken, South Carolina\r\n640\r\n641\r\n642\r\n643\r\n644\r\n645\r\n648\r\n649\r\nAllendale, South Carolina\r\n584\r\nAntioch, South Carolina\r\n936\r\nAwendaw, South Carolina\r\n928\r\nBambert, South Carolina\r\n245\r\nBarnwell, South Carolina\r\n541\r\n259\r\nBath, South Carolina\r\n593\r\nBeech Island, South Carolina\r\n557\r\n725\r\n827\r\n952\r\n867\r\nBelton, South Carolina\r\n338\r\nBishopville, South Carolina\r\n428\r\n484\r\nBlackville, South Carolina\r\n284\r\nBlue Ridge, South Carolina\r\n895\r\nBowman, South Carolina\r\n829\r\nBranchville, South Carolina\r\n274\r\nCamden, South Carolina\r\n432\r\n424\r\n425\r\n438\r\n532\r\nCameron, South Carolina\r\n823\r\nCampobello, South Carolina\r\n468\r\nCentral, South Carolina\r\n639\r\nChapin, South Carolina\r\n345\r\nChapeltmtnn, South Carolina\r\n945\r\n932\r\nChappells, South Carolina\r\n995\r\nCharlotte, South Carolina\r\n555\r\nChesnee, South Carolina\r\n461\r\nChester, South Carolina\r\n581\r\n377\r\n385\r\nClarkshill, South Carolina\r\n333\r\nClover, South Carolina\r\n222\r\nCollege Of Charleston, South Carolina\r\n792\r\n953\r\nColumbia, South Carolina\r\n251\r\n252\r\n253\r\n254\r\n256\r\n319\r\n331\r\n343\r\n344\r\n360\r\n373\r\n376\r\n434\r\n530\r\n540\r\n551\r\n561\r\n690\r\n691\r\n695\r\n698\r\n699\r\n730\r\n731\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n739\r\n741\r\n742\r\n748\r\n749\r\n750\r\n751\r\n754\r\n755\r\n758\r\n765\r\n771\r\n772\r\n776\r\n777\r\n779\r\n782\r\n783\r\n786\r\n787\r\n788\r\n790\r\n791\r\n794\r\n796\r\n798\r\n799\r\n822\r\n865\r\n896\r\n920\r\n926\r\n929\r\n931\r\n935\r\n939\r\n955\r\n960\r\n975\r\n976\r\nCreston, South Carolina\r\n826\r\nCross Hill, South Carolina\r\n998\r\nDenmark, South Carolina\r\n793\r\nDue West, South Carolina\r\n379\r\nEastover, South Carolina\r\n353\r\nEdgefield, South Carolina\r\n637\r\nEhrhardt, South Carolina\r\n267\r\nElloree, South Carolina\r\n897\r\nEnoree, South Carolina\r\n969\r\nEstill, South Carolina\r\n625\r\nEutawville, South Carolina\r\n492\r\nFairfax, South Carolina\r\n632\r\nFort Lawn, South Carolina\r\n872\r\nFort Mill, South Carolina\r\n547\r\n548\r\nFountain Inn, South Carolina\r\n862\r\nGastonia, South Carolina\r\n962\r\nGilbert, South Carolina\r\n892\r\nGraniteville, South Carolina\r\n663\r\nGray Court, South Carolina\r\n876\r\nGreat Falls, South Carolina\r\n482\r\nGreer, South Carolina\r\n848\r\n877\r\n879\r\n968\r\nHampton, South Carolina\r\n943\r\nHeath Springs, South Carolina\r\n273\r\nHickory Grove, South Carolina\r\n925\r\nHodges, South Carolina\r\n374\r\nHolly Hill, South Carolina\r\n496\r\nHollywood, South Carolina\r\n889\r\nInman, South Carolina\r\n472\r\nIrmo, South Carolina\r\n732\r\n781\r\nIsle Palms, South Carolina\r\n886\r\nJackson, South Carolina\r\n471\r\nJohnston, South Carolina\r\n275\r\n480\r\nJonesville, South Carolina\r\n674\r\nKershaw, South Carolina\r\n475\r\nLake Wylie, South Carolina\r\n631\r\n831\r\nLancaster, South Carolina\r\n289\r\n283\r\n285\r\n286\r\nLewisville, South Carolina\r\n789\r\nLexington, South Carolina\r\n951\r\n356\r\n359\r\n957\r\nLiberty, South Carolina\r\n843\r\nLynchburg, South Carolina\r\n437\r\nManning, South Carolina\r\n435\r\n473\r\nMayesville, South Carolina\r\n453\r\nMccormick, South Carolina\r\n465\r\nMountville, South Carolina\r\n994\r\nNewberry, South Carolina\r\n924\r\n276\r\n321\r\nNewellenton, South Carolina\r\n652\r\nNorth Augusta, South Carolina\r\n278\r\n279\r\n441\r\n442\r\nNorth Sumter, South Carolina\r\n491\r\nNorth, South Carolina\r\n247\r\nNorway, South Carolina\r\n263\r\nOakland, South Carolina\r\n499\r\nOlar, South Carolina\r\n368\r\nOrangeburg, South Carolina\r\n531\r\n533\r\n534\r\n535\r\n536\r\nPacolet, South Carolina\r\n474\r\nPelion, South Carolina\r\n894\r\nPelzer, South Carolina\r\n947\r\nPendleton, South Carolina\r\n646\r\nPickens, South Carolina\r\n878\r\n898\r\nPiedmont, South Carolina\r\n845\r\nPinewood, South Carolina\r\n452\r\nPocalla, South Carolina\r\n481\r\nPond Branch, South Carolina\r\n657\r\nProsperity, South Carolina\r\n364\r\nRidge Springs, South Carolina\r\n685\r\nRidgeway, South Carolina\r\n337\r\nRock Hill, South Carolina\r\n325\r\n367\r\nRock Hill, South Carolina\r\n323\r\n324\r\n327\r\n328\r\n329\r\n366\r\nSalem, South Carolina\r\n944\r\nSantee, South Carolina\r\n854\r\nSeneca, South Carolina\r\n880\r\n882\r\n885\r\n972\r\n888\r\nSharon, South Carolina\r\n927\r\nShaw AFB Heights, South Carolina\r\n668\r\nShawville Heights, South Carolina\r\n666\r\nSimpsonville, South Carolina\r\n228\r\n963\r\n967\r\nSix Mile, South Carolina\r\n868\r\nSpringfield-Salley, South Carolina\r\n258\r\nSaint Heln Island, South Carolina\r\n838\r\nSaint Matthews, South Carolina\r\n655\r\n874\r\nStarr Iva, South Carolina\r\n348\r\n352\r\nStatesburg, South Carolina\r\n494\r\nSullivnsis, South Carolina\r\n883\r\nSummerton, South Carolina\r\n478\r\n485\r\nSummerville, South Carolina\r\n821\r\n851\r\n871\r\n873\r\n875\r\nSumter, South Carolina\r\n436\r\n840\r\n469\r\n495\r\n773\r\n775\r\n778\r\nSwansea, South Carolina\r\n568\r\nUnion, South Carolina\r\n427\r\n429\r\nWagener, South Carolina\r\n564\r\nWestminister, South Carolina\r\n647\r\nWhitmire, South Carolina\r\n694\r\nWilliamston, South Carolina\r\n847\r\nWilliston, South Carolina\r\n266\r\nWinnsboro, South Carolina\r\n635\r\nWoodruff, South Carolina\r\n476\r\nYork, South Carolina\r\n628\r\n684\r\n\u00035Unknown prefix code (803) - South Carolina\r\n"
  },
  {
    "path": "install/regions/regions.804",
    "content": "Alberta, Virginia\r\n949\r\nAllwood, Virginia\r\n922\r\nAltavista, Virginia\r\n369\r\nAmeliacths, Virginia\r\n561\r\nAmherst, Virginia\r\n946\r\nAppomattox, Virginia\r\n352\r\nArvonia, Virginia\r\n581\r\nAshland, Virginia\r\n550\r\n752\r\n798\r\nBachelorhill, Virginia\r\n685\r\nBarnesville, Virginia\r\n735\r\nBeaverdam, Virginia\r\n449\r\nBeechwood, Virginia\r\n689\r\nBelle Haven, Virginia\r\n442\r\nBethia, Virginia\r\n739\r\n763\r\nBig Island, Virginia\r\n299\r\nBlackridge, Virginia\r\n636\r\nBlackstone, Virginia\r\n292\r\nBowling Green, Virginia\r\n633\r\nBoydton, Virginia\r\n738\r\nBoykins, Virginia\r\n654\r\nBrodnax, Virginia\r\n729\r\nBrookneal, Virginia\r\n376\r\nBuckingham, Virginia\r\n969\r\nBurkeville, Virginia\r\n767\r\nCallao, Virginia\r\n529\r\nCape Charles, Virginia\r\n331\r\nCapron, Virginia\r\n658\r\nCartersville, Virginia\r\n375\r\nCharles City, Virginia\r\n829\r\nCharlottesville, Virginia\r\n243\r\n960\r\n961\r\n987\r\n293\r\n295\r\n296\r\n924\r\n971\r\n972\r\n973\r\n974\r\n977\r\n978\r\n979\r\n980\r\n981\r\n982\r\nChase City, Virginia\r\n372\r\nChatham, Virginia\r\n432\r\nChesapeake, Virginia\r\n421\r\n424\r\n548\r\nChester, Virginia\r\n748\r\n751\r\n768\r\n778\r\n790\r\n796\r\n920\r\nChincoteague, Virginia\r\n336\r\n830\r\nChlt Ct, Virginia\r\n542\r\nChuckatuck, Virginia\r\n255\r\nClaremont, Virginia\r\n866\r\nClarksville, Virginia\r\n374\r\nClover, Virginia\r\n454\r\nColonial Beach, Virginia\r\n224\r\nConcord, Virginia\r\n993\r\nCourtland, Virginia\r\n653\r\nCrewe, Virginia\r\n645\r\nCrittenden, Virginia\r\n238\r\nCrozet, Virginia\r\n823\r\nCumberland, Virginia\r\n492\r\nDanville, Virginia\r\n250\r\n770\r\n791\r\n792\r\n793\r\n797\r\n799\r\n822\r\n836\r\nDawn, Virginia\r\n994\r\nDeltaville, Virginia\r\n776\r\nDenbigh\u00031/\u00032Ft. Eustis\u00031/\u00032Lee Hall\u00031/\u00032Seaford\u00031/\u00032Yorktown, Virginia\r\n249\r\n508\r\n509\r\n532\r\n570\r\n820\r\n833\r\n869\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n877\r\n878\r\n879\r\n880\r\n881\r\n882\r\n884\r\n885\r\n886\r\n887\r\n888\r\n890\r\n898\r\n931\r\n988\r\n989\r\nDendron, Virginia\r\n267\r\nDillwyn, Virginia\r\n983\r\nDinwiddie, Virginia\r\n265\r\n469\r\nDisputanta, Virginia\r\n991\r\nDoswell, Virginia\r\n876\r\nDrakes Branch, Virginia\r\n568\r\nEastville, Virginia\r\n678\r\nEmporia, Virginia\r\n348\r\n634\r\nEnon, Virginia\r\n530\r\nLata\u00031/\u00032Eppes Fork, Virginia\r\n252\r\nFarmville, Virginia\r\n390\r\n392\r\n395\r\nFarnham, Virginia\r\n394\r\nFife, Virginia\r\n457\r\nFork Union, Virginia\r\n842\r\nFranklin, Virginia\r\n562\r\n569\r\nGatewood, North Carolina\r\n388\r\nGladstone, Virginia\r\n933\r\nGladys, Virginia\r\n283\r\nGloucester, Virginia\r\n693\r\n694\r\nGoochland, Virginia\r\n556\r\nGretna, Virginia\r\n656\r\nGum Tree, Virginia\r\n227\r\nHague, Virginia\r\n472\r\nHalifax, Virginia\r\n476\r\nHampdonsdny, Virginia\r\n223\r\nHampton, Virginia\r\n722\r\n723\r\n726\r\n727\r\n728\r\n764\r\n766\r\n825\r\n826\r\n827\r\n838\r\n850\r\n851\r\n864\r\n865\r\n867\r\n896\r\nHanover, Virginia\r\n537\r\nHayes, Virginia\r\n642\r\nHeathsville, Virginia\r\n580\r\nHighland Springs\u00031/\u00032Sandston, Virginia\r\n328\r\n737\r\nHolland, Virginia\r\n657\r\nHopewell, Virginia\r\n452\r\n458\r\n541\r\nHurt, Virginia\r\n324\r\nIrvington, Virginia\r\n438\r\nIvor, Virginia\r\n859\r\nJarratt, Virginia\r\n535\r\nKenbridge, Virginia\r\n676\r\nKeysville, Virginia\r\n736\r\nKilmarnock, Virginia\r\n435\r\nKing Queen, Virginia\r\n785\r\nKing William, Virginia\r\n769\r\nLa Crosse, Virginia\r\n757\r\nLadysmith, Virginia\r\n448\r\nLawrenceville, Virginia\r\n848\r\nLively, Virginia\r\n462\r\nLovingston, Virginia\r\n263\r\n325\r\n361\r\nLynchburg, Virginia\r\n534\r\n660\r\n237\r\n239\r\n384\r\n385\r\n386\r\n522\r\n525\r\n528\r\n582\r\n821\r\n832\r\n841\r\n845\r\n846\r\n847\r\n929\r\n947\r\n948\r\nManakin, Virginia\r\n784\r\nMathews, Virginia\r\n725\r\nMcKenney, Virginia\r\n478\r\nMechanicsville, Virginia\r\n559\r\n730\r\n746\r\n781\r\nMidlothian, Virginia\r\n378\r\n379\r\n794\r\nMilton, North Carolina\r\n234\r\nMontpelier, Virginia\r\n883\r\nMontrose, Virginia\r\n222\r\nMontross, Virginia\r\n493\r\nNewport News, Virginia\r\n244\r\n245\r\n247\r\n380\r\n591\r\n594\r\n595\r\n596\r\n599\r\n688\r\n867\r\n928\r\n930\r\nNorfolk, Virginia\r\n322\r\n326\r\n362\r\n366\r\n382\r\n420\r\n521\r\n549\r\n554\r\n557\r\n578\r\n630\r\n631\r\n650\r\n651\r\n667\r\n668\r\n670\r\n677\r\n680\r\n860\r\n889\r\n970\r\n368\r\n563\r\n480\r\nOld Church, Virginia\r\n779\r\nOnancock, Virginia\r\n787\r\nPalmyra, Virginia\r\n589\r\nPamplin, Virginia\r\n248\r\nParksley, Virginia\r\n665\r\nPetersburg\u00031/\u00032Colonial Heights, Virginia\r\n520\r\n524\r\n526\r\n590\r\n720\r\n731\r\n732\r\n733\r\n734\r\n765\r\n861\r\n862\r\nPiney River, Virginia\r\n277\r\nPoquoson, Virginia\r\n868\r\nPort Royal, Virginia\r\n742\r\nPortsmouth, Virginia\r\n334\r\n439\r\n477\r\n558\r\n391\r\n393\r\n396\r\n397\r\n398\r\n399\r\n408\r\n409\r\n434\r\n465\r\n483\r\n484\r\n485\r\n487\r\n488\r\n536\r\n567\r\n681\r\n686\r\nPowhatan, Virginia\r\n598\r\nProspect, Virginia\r\n574\r\nProvidence Gorge, Virginia\r\n932\r\n966\r\nReedville, Virginia\r\n453\r\nRenan, Virginia\r\n335\r\nRichmond, Virginia\r\n240\r\n279\r\n280\r\n573\r\n576\r\n690\r\n692\r\n759\r\n760\r\n762\r\n828\r\n840\r\n225\r\n226\r\n228\r\n230\r\n231\r\n232\r\n233\r\n235\r\n236\r\n254\r\n256\r\n257\r\n261\r\n262\r\n264\r\n266\r\n268\r\n270\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n278\r\n281\r\n282\r\n284\r\n285\r\n287\r\n288\r\n289\r\n320\r\n321\r\n323\r\n329\r\n330\r\n337\r\n342\r\n343\r\n344\r\n345\r\n346\r\n347\r\n350\r\n351\r\n353\r\n354\r\n355\r\n356\r\n358\r\n359\r\n360\r\n367\r\n370\r\n371\r\n383\r\n451\r\n527\r\n553\r\n560\r\n643\r\n644\r\n648\r\n649\r\n662\r\n672\r\n673\r\n674\r\n675\r\n697\r\n740\r\n741\r\n743\r\n744\r\n745\r\n747\r\n750\r\n755\r\n756\r\n771\r\n772\r\n775\r\n780\r\n782\r\n783\r\n786\r\n788\r\n844\r\n954\r\n965\r\nRockville, Virginia\r\n749\r\nRustburg, Virginia\r\n332\r\nSaluda, Virginia\r\n758\r\nSandy Level, Virginia\r\n927\r\nSchuyler, Virginia\r\n831\r\nScottsville, Virginia\r\n286\r\nSmithfield, Virginia\r\n357\r\n365\r\nSouth Boston, Virginia\r\n470\r\n572\r\n575\r\nSouth Brunswick, Virginia\r\n577\r\nSouth Hill, Virginia\r\n447\r\n774\r\nStanardsville, Virginia\r\n985\r\nStony Creek, Virginia\r\n246\r\nSuffolk, Virginia\r\n538\r\n539\r\n925\r\n934\r\nSurry, Virginia\r\n294\r\nSweetbriar, Virginia\r\n381\r\nTangler Island, Virginia\r\n891\r\nTapahanock, Virginia\r\n443\r\nTemperenceville, Virginia\r\n824\r\nToano\u00031/\u00032Williamsburg, Virginia\r\n220\r\n221\r\n229\r\n253\r\n258\r\n259\r\n564\r\n565\r\n566\r\nTurbeville, Virginia\r\n753\r\nVarina, Virginia\r\n795\r\nVictoria, Virginia\r\n696\r\nVirgilina, Virginia\r\n585\r\nVirginia Beach, Virginia\r\n241\r\n340\r\n363\r\n422\r\n423\r\n425\r\n426\r\n427\r\n428\r\n430\r\n431\r\n433\r\n434\r\n436\r\n437\r\n440\r\n441\r\n444\r\n445\r\n446\r\n455\r\n456\r\n459\r\n460\r\n461\r\n463\r\n464\r\n466\r\n467\r\n468\r\n471\r\n473\r\n474\r\n475\r\n479\r\n481\r\n482\r\n486\r\n489\r\n490\r\n491\r\n494\r\n495\r\n496\r\n497\r\n498\r\n499\r\n523\r\n531\r\n533\r\n543\r\n545\r\n547\r\n552\r\n583\r\n587\r\n588\r\n620\r\n621\r\n622\r\n623\r\n624\r\n625\r\n626\r\n627\r\n628\r\n629\r\n640\r\n666\r\n671\r\n683\r\n721\r\n853\r\n855\r\n857\r\n858\r\n999\r\nVolens, Virginia\r\n349\r\nWakefield, Virginia\r\n899\r\nWarsaw, Virginia\r\n450\r\n333\r\nWaverly, Virginia\r\n834\r\nWest Point, Virginia\r\n843\r\nWhaleyville, Virginia\r\n986\r\nWhitmell, Virginia\r\n724\r\nWilliamsburg, Virginia\r\n259\r\nWindsor, Virginia\r\n242\r\n\u00035Unknown prefix code (804) - Virginia\r\n"
  },
  {
    "path": "install/regions/regions.805",
    "content": "Arroyo Grand, California\r\n473\r\n481\r\n489\r\nArvin, California\r\n854\r\nAtascadero, California\r\n461\r\n466\r\nBakersfield, California\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n332\r\n334\r\n366\r\n392\r\n393\r\n395\r\n397\r\n398\r\n399\r\n589\r\n631\r\n664\r\n665\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n838\r\n842\r\n845\r\n858\r\n861\r\n871\r\n872\r\n331\r\n333\r\n335\r\n363\r\n391\r\n588\r\n632\r\n633\r\n634\r\n635\r\n839\r\n873\r\n396\r\n663\r\nBerend Mes, California\r\n465\r\nBig Butte, California\r\n261\r\nBradley, California\r\n472\r\nButton Willow, California\r\n764\r\nCalifornia Hot Spring, California\r\n548\r\nCamarillo, California\r\n383\r\n445\r\n388\r\n389\r\n482\r\n484\r\nCambria, California\r\n927\r\nCarpintera, California\r\n566\r\n684\r\nCarrisapls, California\r\n475\r\nCayucos, California\r\n995\r\nConejo, California\r\n491\r\n492\r\n493\r\nCuyama, California\r\n766\r\nDelano, California\r\n721\r\n725\r\nEarlimart, California\r\n849\r\nEdwards, California\r\n258\r\n275\r\n277\r\nEl Rio, California\r\n981\r\nFillmore, California\r\n524\r\nGaviota, California\r\n567\r\nGlennville, California\r\n536\r\nGuadalupe, California\r\n343\r\nHi Vista, California\r\n727\r\nLake Hughes, California\r\n724\r\nLancaster, California\r\n722\r\n723\r\n726\r\n728\r\n729\r\n940\r\n942\r\n943\r\n945\r\n946\r\n948\r\n949\r\nLebec, California\r\n242\r\n245\r\n248\r\nLompoc, California\r\n733\r\n734\r\n735\r\n736\r\n737\r\n865\r\n866\r\nLos Alamos, California\r\n344\r\nLost Hills, California\r\n797\r\nMcFarland, California\r\n792\r\nMckittrick, California\r\n762\r\nMojave, California\r\n824\r\nMoorpark, California\r\n532\r\n378\r\n523\r\n529\r\n531\r\nMorro Bay, California\r\n772\r\nNewbury Park, California\r\n376\r\n447\r\nNewhall, California\r\n257\r\n286\r\n251\r\n252\r\n253\r\n254\r\n255\r\n259\r\n295\r\n296\r\n297\r\n298\r\nNipomo, California\r\n929\r\nOjai, California\r\n640\r\n646\r\nOxnard, California\r\n382\r\n385\r\n483\r\n485\r\n486\r\n487\r\n488\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n989\r\nPalmdale, California\r\n267\r\n285\r\n538\r\n540\r\n572\r\n264\r\n265\r\n266\r\n269\r\n272\r\n273\r\n274\r\n944\r\n947\r\n268\r\n270\r\nParkfield, California\r\n463\r\nPasorobles, California\r\n227\r\n237\r\n238\r\n239\r\n434\r\nPiru, California\r\n521\r\nPismo Beach, California\r\n773\r\nRosamond, California\r\n256\r\nSan Luis Obispo, California\r\n462\r\n235\r\n441\r\n534\r\n547\r\n781\r\n782\r\nSan Luis, California\r\n528\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n549\r\n595\r\n756\r\nSan Miguel, California\r\n467\r\nSanclar, California\r\n287\r\n288\r\n294\r\n250\r\nSanta Barbara, California\r\n893\r\n896\r\n898\r\n899\r\n562\r\n563\r\n564\r\n565\r\n568\r\n569\r\n680\r\n681\r\n682\r\n683\r\n685\r\n687\r\n689\r\n706\r\n891\r\n897\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\nSanta Ynez, California\r\n686\r\n688\r\nSanta Maria, California\r\n346\r\n347\r\n349\r\n922\r\n925\r\n928\r\n934\r\n937\r\nSanta Margaret, California\r\n438\r\nSanta Paula, California\r\n525\r\n933\r\nSaticoy, California\r\n675\r\n645\r\n647\r\n655\r\n656\r\n659\r\nShafter, California\r\n746\r\nSimi Valley, California\r\n520\r\n522\r\n526\r\n527\r\n579\r\n581\r\n582\r\n583\r\n584\r\n629\r\n213\r\nSomis, California\r\n386\r\nTaft, California\r\n763\r\n765\r\n768\r\n769\r\nTehachapi, California\r\n823\r\n821\r\n822\r\nThousand Oak, California\r\n371\r\n372\r\n373\r\n375\r\n377\r\n379\r\n494\r\n495\r\n496\r\n497\r\n498\r\n499\r\n374\r\n444\r\n446\r\n731\r\n732\r\n923\r\nVan Nuys, California\r\n260\r\n320\r\n338\r\n341\r\n342\r\n390\r\n561\r\n660\r\nVentura, California\r\n339\r\n639\r\n340\r\n641\r\n642\r\n643\r\n644\r\n648\r\n649\r\n650\r\n651\r\n652\r\n653\r\n654\r\n657\r\n658\r\nWalker Basin, California\r\n867\r\nWasco, California\r\n758\r\n\u00035Unknown prefix code (805) - California\r\n"
  },
  {
    "path": "install/regions/regions.806",
    "content": "Abernathy, Texas\r\n298\r\nAcuff, Texas\r\n842\r\nAdrian, Texas\r\n538\r\nAfton, Texas\r\n689\r\nAllison, Texas\r\n375\r\nAmarillo, Texas\r\n220\r\n346\r\n356\r\n320\r\n335\r\n345\r\n352\r\n353\r\n354\r\n355\r\n358\r\n359\r\n371\r\n372\r\n373\r\n374\r\n376\r\n378\r\n379\r\n381\r\n383\r\n477\r\n622\r\n677\r\n678\r\n679\r\nAmherst, Texas\r\n246\r\nAnton, Texas\r\n997\r\nArnett, Texas\r\n297\r\nAten, Texas\r\n439\r\nAusborne, Texas\r\n585\r\nBean, Texas\r\n847\r\nBooker, Texas\r\n658\r\nBorger, Texas\r\n275\r\n898\r\n273\r\n274\r\nBovina, Texas\r\n238\r\nBoys Ranch, Texas\r\n534\r\nBrownfield, Texas\r\n637\r\n638\r\nBula, Texas\r\n933\r\nBunker Hill, Texas\r\n377\r\nCactus, Texas\r\n966\r\nCanadian, Texas\r\n323\r\nCanyon, Texas\r\n655\r\n656\r\nCaprock, Texas\r\n649\r\nChanning, Texas\r\n235\r\nClarendon, Texas\r\n874\r\nClaude, Texas\r\n226\r\nCleta, Texas\r\n488\r\nColdwater, Texas\r\n333\r\n384\r\nCone, Texas\r\n657\r\nCotton Center, Texas\r\n879\r\nCountyline, Texas\r\n757\r\nCrosbyton, Texas\r\n675\r\nDalhart, Texas\r\n249\r\nDarrouzett, Texas\r\n624\r\nDawn, Texas\r\n258\r\nDenver, Texas\r\n592\r\nDickens, Texas\r\n623\r\nDimmitt, Texas\r\n647\r\nDodson, Texas\r\n493\r\nDry Lake, Texas\r\n294\r\nDumas, Texas\r\n922\r\n930\r\n935\r\nEast Glenrio, Texas\r\n575\r\nEarth, Texas\r\n257\r\nEdmondson, Texas\r\n864\r\nElkins, Texas\r\n668\r\nEstelline, Texas\r\n888\r\nFarwell, Texas\r\n481\r\nFieldton, Texas\r\n262\r\nFletchcrtr, Texas\r\n327\r\nFlomot, Texas\r\n469\r\nFloydada, Texas\r\n983\r\nFollett, Texas\r\n653\r\nFrio, Texas\r\n276\r\nFriona, Texas\r\n247\r\nFritch, Texas\r\n857\r\nGail, Texas\r\n756\r\nGirard, Texas\r\n284\r\nGoodnight, Texas\r\n944\r\nGroom, Texas\r\n248\r\nGruver, Texas\r\n733\r\nGurley, Texas\r\n764\r\nGuymon, Texas\r\n339\r\nHackmont, Texas\r\n596\r\nHalecenter, Texas\r\n839\r\nHalfway, Texas\r\n889\r\nHappy, Texas\r\n558\r\nHappy Union, Texas\r\n895\r\nHart, Texas\r\n938\r\nHartley, Texas\r\n365\r\nHatch, Texas\r\n497\r\nHedley, Texas\r\n856\r\nHereford, Texas\r\n344\r\n363\r\n364\r\nHiggins, Texas\r\n852\r\nHigginbotthom, Texas\r\n732\r\nHollandville, Texas\r\n328\r\nHub, Texas\r\n265\r\nHurlwood, Texas\r\n885\r\nIdalou, Texas\r\n892\r\nJayton, Texas\r\n237\r\nKerrick, Texas\r\n727\r\nKress, Texas\r\n684\r\nLakeview, Texas\r\n867\r\nLamesa, Texas\r\n872\r\nLariat, Texas\r\n925\r\nLautz, Texas\r\n769\r\nLazbuddie, Texas\r\n965\r\nLefors, Texas\r\n835\r\nLehman, Texas\r\n525\r\nLevelland, Texas\r\n893\r\n897\r\n894\r\nLipscomb, Texas\r\n862\r\nLittlefield, Texas\r\n385\r\nLockney, Texas\r\n652\r\nLoop, Texas\r\n487\r\nLorenzo, Texas\r\n634\r\nLubbock, Texas\r\n788\r\n790\r\n951\r\n954\r\n567\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n761\r\n762\r\n763\r\n765\r\n766\r\n767\r\n770\r\n775\r\n777\r\n784\r\n789\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\nMaple, Texas\r\n927\r\nMatador, Texas\r\n347\r\nMcAdoo, Texas\r\n697\r\nMcLean, Texas\r\n779\r\nMeadow, Texas\r\n539\r\nMemphis, Texas\r\n259\r\nMerrell, Texas\r\n873\r\nMiami, Texas\r\n868\r\nMiddlewater, Texas\r\n343\r\nMilocenter, Texas\r\n578\r\nMobeetie, Texas\r\n845\r\nMorton, Texas\r\n266\r\nMuleshoe, Texas\r\n272\r\nNazareth, Texas\r\n945\r\nNeedmore, Texas\r\n946\r\nNelms, Texas\r\n645\r\nNew Home, Texas\r\n759\r\n924\r\nO'Donnell, Texas\r\n428\r\nOkla Lane, Texas\r\n825\r\nOlton, Texas\r\n285\r\nPaducah, Texas\r\n492\r\nPampa, Texas\r\n663\r\n665\r\n669\r\nPanhandle, Texas\r\n537\r\nParmer, Texas\r\n295\r\nPatricia, Texas\r\n462\r\nPeacock, Texas\r\n254\r\nPerryton, Texas\r\n435\r\n992\r\nPetersburg, Texas\r\n667\r\nPettit, Texas\r\n245\r\nPlains, Texas\r\n456\r\nPlainview, Texas\r\n221\r\n292\r\n774\r\n293\r\n296\r\nPleasanthill, Texas\r\n389\r\nPost, Texas\r\n495\r\nPunkin Center, Texas\r\n489\r\nQuitaque, Texas\r\n455\r\nRalls, Texas\r\n253\r\nRansom Canyon, Texas\r\n829\r\nRedmon, Texas\r\n627\r\nRoaring Springs, Texas\r\n348\r\nRopesville, Texas\r\n562\r\nSanford, Texas\r\n865\r\nSeagraves, Texas\r\n546\r\nShallowater, Texas\r\n832\r\nShamrock, Texas\r\n256\r\nSilverton, Texas\r\n823\r\nSkellytown, Texas\r\n664\r\n848\r\nSlaton, Texas\r\n828\r\nSmyer, Texas\r\n234\r\nSouth Texhoma, Texas\r\n827\r\nSouth Hardesty, Texas\r\n882\r\nSouthland, Texas\r\n996\r\nSpade, Texas\r\n233\r\nSpearman, Texas\r\n659\r\nSpring Lake, Texas\r\n986\r\nSpur, Texas\r\n271\r\nStevens, Texas\r\n753\r\nStinnett, Texas\r\n878\r\nStratford, Texas\r\n396\r\nSudan, Texas\r\n227\r\nSummerfield, Texas\r\n357\r\nSundown, Texas\r\n229\r\nSunray, Texas\r\n948\r\nSweetwater West, Texas\r\n754\r\nTahoka, Texas\r\n998\r\nTexline, Texas\r\n362\r\nTharp, Texas\r\n225\r\nTulia, Texas\r\n995\r\nTurkey, Texas\r\n423\r\nUmbarger, Texas\r\n499\r\nUnion, Texas\r\n755\r\nVega, Texas\r\n267\r\nVerbena, Texas\r\n629\r\nVigo Park, Texas\r\n633\r\nWest Roger, Texas\r\n988\r\nWellington, Texas\r\n447\r\nWest Lakes, Texas\r\n465\r\nWestreydon, Texas\r\n565\r\nWestway, Texas\r\n289\r\nWheatley, Texas\r\n522\r\nWheeler, Texas\r\n826\r\nWhite Deer, Texas\r\n883\r\nWhite River, Texas\r\n263\r\nWhiteface, Texas\r\n287\r\nWhitharral, Texas\r\n299\r\nWildorado, Texas\r\n426\r\nWilson, Texas\r\n628\r\nWolfforth, Texas\r\n866\r\nWoodrow, Texas\r\n863\r\n\u00035Unknown prefix code (806) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.807",
    "content": "Armstrong, Ontario, Canada\r\n583\r\nAtikokan, Ontario, Canada\r\n597\r\nBalmertown, Ontario, Canada\r\n735\r\nBarwick, Ontario, Canada\r\n487\r\nBeardmore, Ontario, Canada\r\n875\r\nBears Pass, Ontario, Canada\r\n481\r\nBearskn Lk, Ontario, Canada\r\n363\r\nBig Trt, Ontario, Canada\r\n537\r\nBl 976, Ontario, Canada\r\n976\r\nCaramat, Ontario, Canada\r\n872\r\nCat Lake, Ontario, Canada\r\n347\r\nClearwtr B, Ontario, Canada\r\n733\r\nCloud Bay, Ontario, Canada\r\n964\r\nCmp Robnsn, Ontario, Canada\r\n529\r\nCochenour, Ontario, Canada\r\n662\r\nDeer Lake, Ontario, Canada\r\n775\r\nDevlin, Ontario, Canada\r\n486\r\nDorion, Ontario, Canada\r\n857\r\nDryden, Ontario, Canada\r\n223\r\nEagleriver, Ontario, Canada\r\n755\r\nEar Falls, Ontario, Canada\r\n222\r\nEmo, Ontario, Canada\r\n482\r\nFlanders, Ontario, Canada\r\n947\r\nFort Hope, Ontario, Canada\r\n242\r\nFt Frances, Ontario, Canada\r\n274\r\nFt Severn, Ontario, Canada\r\n478\r\nGeraldton, Ontario, Canada\r\n854\r\nGrsy Naros, Ontario, Canada\r\n925\r\nGull Bay, Ontario, Canada\r\n982\r\nHemlo, Ontario, Canada\r\n238\r\nHornepayne, Ontario, Canada\r\n868\r\nHudson, Ontario, Canada\r\n582\r\nIgnace, Ontario, Canada\r\n934\r\nJafry Melk, Ontario, Canada\r\n548\r\nJellicoe, Ontario, Canada\r\n879\r\nKaministqa, Ontario, Canada\r\n933\r\nKasabonika, Ontario, Canada\r\n535\r\nKashabowie, Ontario, Canada\r\n984\r\nKeewatin, Ontario, Canada\r\n547\r\nKenora, Ontario, Canada\r\n468\r\nKngfshr Lk, Ontario, Canada\r\n532\r\nLaclacroix, Ontario, Canada\r\n485\r\nLansdwn Ho, Ontario, Canada\r\n479\r\nLonglac, Ontario, Canada\r\n876\r\nMacdiarmid, Ontario, Canada\r\n885\r\nMackenzie, Ontario, Canada\r\n983\r\nMadsen, Ontario, Canada\r\n749\r\nMantouwdge, Ontario, Canada\r\n826\r\nMarathon, Ontario, Canada\r\n229\r\nMcken Port, Ontario, Canada\r\n543\r\nMinaki, Ontario, Canada\r\n224\r\nMine Ctr, Ontario, Canada\r\n599\r\nMorson, Ontario, Canada\r\n488\r\nMurillo, Ontario, Canada\r\n935\r\nMuskratdam, Ontario, Canada\r\n471\r\nNakina, Ontario, Canada\r\n329\r\nNestor Fls, Ontario, Canada\r\n484\r\nNipigon, Ontario, Canada\r\n887\r\nOgoki, Ontario, Canada\r\n349\r\nOxdrift, Ontario, Canada\r\n937\r\nPass Lake, Ontario, Canada\r\n977\r\nPickle Lk, Ontario, Canada\r\n928\r\nPikangikum, Ontario, Canada\r\n773\r\nPoplar Hil, Ontario, Canada\r\n772\r\nRainy Riv, Ontario, Canada\r\n852\r\nRaith, Ontario, Canada\r\n448\r\nRed Lake, Ontario, Canada\r\n727\r\nRed Rock, Ontario, Canada\r\n886\r\nRedditt, Ontario, Canada\r\n225\r\nRosslyn, Ontario, Canada\r\n939\r\nSachigo Lk, Ontario, Canada\r\n595\r\nSandy Lake, Ontario, Canada\r\n774\r\nSapawe, Ontario, Canada\r\n929\r\nSavantlake, Ontario, Canada\r\n584\r\nSchreiber, Ontario, Canada\r\n824\r\nShebandown, Ontario, Canada\r\n926\r\nSioux Lkt, Ontario, Canada\r\n737\r\nSioux Naro, Ontario, Canada\r\n226\r\nStratton, Ontario, Canada\r\n483\r\nSum Beaver, Ontario, Canada\r\n593\r\nTerrace By, Ontario, Canada\r\n825\r\nThunderbay, Ontario, Canada\r\n343\r\n344\r\n345\r\n346\r\n473\r\n475\r\n577\r\n622\r\n623\r\n625\r\n683\r\n767\r\n768\r\n957\r\nUpsala, Ontario, Canada\r\n986\r\nVermiln By, Ontario, Canada\r\n227\r\nWabigoon, Ontario, Canada\r\n938\r\nWeagamow, Ontario, Canada\r\n469\r\nWebequie, Ontario, Canada\r\n353\r\nWhite Riv, Ontario, Canada\r\n822\r\nWhitedog, Ontario, Canada\r\n927\r\nWunumin Lk, Ontario, Canada\r\n442\r\n\u00035Unknown prefix code (807) - Ontario, Canada\r\n"
  },
  {
    "path": "install/regions/regions.808",
    "content": "Hawaii, Hawaii\r\n334\r\n350\r\n880\r\n884\r\n886\r\n887\r\n936\r\n982\r\n985\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n775\r\n776\r\n881\r\n882\r\n883\r\n885\r\n889\r\n925\r\n928\r\n929\r\n933\r\n934\r\n935\r\n959\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n967\r\n968\r\n969\r\n987\r\nKauai, Hawaii\r\n370\r\n639\r\n241\r\n245\r\n246\r\n332\r\n335\r\n337\r\n338\r\n651\r\n654\r\n739\r\n742\r\n822\r\n823\r\n826\r\n828\r\nLanai, Hawaii\r\n390\r\n565\r\nMaui, Hawaii\r\n249\r\n283\r\n297\r\n360\r\n665\r\n875\r\n876\r\n229\r\n242\r\n243\r\n244\r\n248\r\n281\r\n572\r\n573\r\n575\r\n579\r\n661\r\n662\r\n667\r\n669\r\n871\r\n872\r\n873\r\n874\r\n877\r\n878\r\n879\r\nMolokai, Hawaii\r\n380\r\n552\r\n553\r\n558\r\n567\r\nOahu, Hawaii\r\n220\r\n221\r\n223\r\n224\r\n228\r\n275\r\n282\r\n284\r\n285\r\n286\r\n289\r\n291\r\n299\r\n340\r\n497\r\n549\r\n574\r\n577\r\n578\r\n586\r\n587\r\n596\r\n597\r\n626\r\n627\r\n657\r\n674\r\n675\r\n679\r\n683\r\n721\r\n753\r\n754\r\n838\r\n844\r\n851\r\n225\r\n226\r\n233\r\n234\r\n235\r\n236\r\n237\r\n239\r\n247\r\n254\r\n257\r\n259\r\n261\r\n262\r\n263\r\n266\r\n287\r\n288\r\n293\r\n296\r\n373\r\n377\r\n394\r\n395\r\n396\r\n397\r\n422\r\n423\r\n424\r\n433\r\n438\r\n448\r\n449\r\n453\r\n454\r\n455\r\n456\r\n467\r\n471\r\n472\r\n474\r\n477\r\n483\r\n484\r\n486\r\n487\r\n488\r\n499\r\n520\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n529\r\n530\r\n531\r\n532\r\n533\r\n536\r\n537\r\n538\r\n539\r\n541\r\n543\r\n544\r\n545\r\n546\r\n547\r\n548\r\n576\r\n591\r\n592\r\n593\r\n594\r\n595\r\n599\r\n621\r\n622\r\n623\r\n624\r\n625\r\n628\r\n637\r\n638\r\n643\r\n653\r\n655\r\n656\r\n668\r\n671\r\n672\r\n673\r\n676\r\n677\r\n678\r\n681\r\n682\r\n684\r\n687\r\n689\r\n695\r\n696\r\n732\r\n733\r\n734\r\n735\r\n737\r\n738\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n839\r\n841\r\n842\r\n845\r\n846\r\n847\r\n848\r\n849\r\n921\r\n922\r\n923\r\n924\r\n926\r\n927\r\n931\r\n941\r\n942\r\n943\r\n944\r\n945\r\n946\r\n947\r\n948\r\n949\r\n951\r\n955\r\n956\r\n957\r\n971\r\n973\r\n979\r\n988\r\n\u00035Unknown prefix code (808) - Hawaii\r\n"
  },
  {
    "path": "install/regions/regions.809",
    "content": "Anguilla, Virgin Islands\r\n497\r\nAntigua, Virgin Islands\r\n460\r\n461\r\n462\r\n463\r\n464\r\nArroyo, Puerto Rico\r\n271\r\nBahamas, Bahama Islands\r\n321\r\n331\r\n341\r\n342\r\n344\r\n349\r\n351\r\n356\r\n357\r\n358\r\n361\r\n364\r\n368\r\n369\r\n377\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n338\r\n339\r\n345\r\n346\r\n347\r\n348\r\n352\r\n353\r\n354\r\n355\r\n359\r\n362\r\n363\r\n365\r\n366\r\n367\r\n373\r\n392\r\n393\r\nBarbados, Bahama Islands\r\n228\r\n229\r\n230\r\n420\r\n421\r\n430\r\n431\r\n434\r\n435\r\n438\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n432\r\n433\r\n436\r\n437\r\n439\r\nBayamon, Puerto Rico\r\n269\r\nBermuda, Bahama Islands\r\n231\r\n232\r\n233\r\n235\r\n237\r\n239\r\n234\r\n236\r\n238\r\n291\r\n292\r\n293\r\n294\r\n295\r\n296\r\n297\r\n298\r\n299\r\nBritish Vi, British Isles\r\n494\r\n495\r\n496\r\nCaguas, Puerto Rico\r\n258\r\nCamuy Htlo, Puerto Rico\r\n262\r\nCaparra, Puerto Rico\r\n273\r\nCarolina, Puerto Rico\r\n276\r\nCatano, Puerto Rico\r\n275\r\nCayey, Puerto Rico\r\n263\r\nCayman Island, Bahamas\r\n945\r\n947\r\n948\r\n949\r\nCharlt Aml, Virgin Islands\r\n772\r\n773\r\n774\r\n775\r\n776\r\n777\r\n778\r\n690\r\n692\r\n693\r\n770\r\n771\r\n779\r\nDominican Republic, Bahama Islands\r\n220\r\n221\r\n222\r\n223\r\n224\r\n226\r\n227\r\n240\r\n241\r\n243\r\n244\r\n246\r\n248\r\n320\r\n350\r\n470\r\n480\r\n526\r\n530\r\n531\r\n534\r\n536\r\n537\r\n540\r\n546\r\n550\r\n561\r\n563\r\n564\r\n569\r\n570\r\n576\r\n590\r\n591\r\n592\r\n593\r\n681\r\n683\r\n684\r\n691\r\n699\r\n970\r\n971\r\n521\r\n522\r\n523\r\n524\r\n525\r\n527\r\n528\r\n529\r\n532\r\n533\r\n535\r\n538\r\n539\r\n541\r\n542\r\n543\r\n544\r\n545\r\n547\r\n549\r\n551\r\n552\r\n553\r\n554\r\n556\r\n557\r\n558\r\n559\r\n560\r\n562\r\n565\r\n566\r\n567\r\n568\r\n571\r\n572\r\n573\r\n574\r\n575\r\n577\r\n578\r\n579\r\n580\r\n581\r\n582\r\n583\r\n584\r\n585\r\n586\r\n587\r\n588\r\n589\r\n594\r\n595\r\n596\r\n682\r\n685\r\n686\r\n687\r\n688\r\n689\r\n446\r\n447\r\n449\r\n445\r\n448\r\nGrenada, Bahama Islands\r\n441\r\n442\r\n440\r\n443\r\n444\r\nGuaynabo, Puerto Rico\r\n272\r\nJamaica, Bahama Islands\r\n931\r\n932\r\n933\r\n935\r\n936\r\n938\r\n951\r\n967\r\n968\r\n969\r\n977\r\n978\r\n979\r\n990\r\n995\r\n997\r\n998\r\n921\r\n922\r\n923\r\n924\r\n925\r\n926\r\n927\r\n928\r\n929\r\n942\r\n943\r\n944\r\n952\r\n953\r\n954\r\n955\r\n956\r\n957\r\n958\r\n962\r\n963\r\n964\r\n965\r\n966\r\n972\r\n973\r\n974\r\n975\r\n982\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n992\r\n993\r\n994\r\n996\r\nJuana Diaz, Puerto Rico\r\n260\r\nLevittown, Puerto Rico\r\n261\r\nMontseratt, MR\r\n491\r\nNevis, NI\r\n469\r\nPonce, Puerto Rico\r\n284\r\nRio Piedrs, Puerto Rico\r\n274\r\nSan Juan, Puerto Rico\r\n371\r\n250\r\n251\r\n252\r\n253\r\n254\r\n255\r\n256\r\n257\r\n259\r\n264\r\n265\r\n268\r\n380\r\n381\r\n382\r\n383\r\n384\r\n385\r\n386\r\n387\r\n388\r\n389\r\n390\r\n391\r\n394\r\n395\r\n396\r\n397\r\n398\r\n399\r\n597\r\n598\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n726\r\n727\r\n728\r\n729\r\n730\r\n731\r\n732\r\n733\r\n734\r\n735\r\n736\r\n737\r\n738\r\n739\r\n740\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n750\r\n751\r\n752\r\n753\r\n754\r\n755\r\n756\r\n757\r\n758\r\n759\r\n760\r\n761\r\n762\r\n763\r\n764\r\n765\r\n766\r\n767\r\n768\r\n769\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n787\r\n788\r\n789\r\n790\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\n820\r\n821\r\n822\r\n823\r\n824\r\n825\r\n826\r\n827\r\n828\r\n829\r\n830\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n837\r\n838\r\n839\r\n840\r\n841\r\n842\r\n843\r\n844\r\n845\r\n846\r\n847\r\n848\r\n849\r\n850\r\n851\r\n852\r\n853\r\n854\r\n855\r\n856\r\n857\r\n858\r\n859\r\n860\r\n861\r\n862\r\n863\r\n864\r\n865\r\n866\r\n867\r\n868\r\n869\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n878\r\n879\r\n880\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\n890\r\n891\r\n892\r\n893\r\n894\r\n895\r\n896\r\n897\r\n898\r\n899\r\nSanturce, Puerto Rico\r\n277\r\n278\r\n279\r\n280\r\n375\r\nSaint Kitts, Virgin Islands\r\n467\r\n465\r\nSaint Lucia, Virgin Islands\r\n450\r\n451\r\n455\r\n459\r\n484\r\n452\r\n453\r\n454\r\nSaint Vincent, Virgin Islands\r\n493\r\n456\r\n457\r\n458\r\nTrinidad, Caribbean Islands\r\n634\r\n645\r\n647\r\n650\r\n654\r\n656\r\n670\r\n673\r\n677\r\n678\r\n679\r\n680\r\n622\r\n623\r\n624\r\n625\r\n627\r\n628\r\n629\r\n630\r\n632\r\n633\r\n636\r\n637\r\n638\r\n639\r\n642\r\n643\r\n644\r\n646\r\n648\r\n649\r\n652\r\n653\r\n655\r\n657\r\n658\r\n659\r\n660\r\n662\r\n663\r\n664\r\n665\r\n667\r\n668\r\n669\r\n671\r\n672\r\n674\r\n675\r\n676\r\nTrjlo Alto, Puerto Rico\r\n283\r\nTrk Caicos, Bahama Islands\r\n941\r\n946\r\nVega Alta, Puerto Rico\r\n270\r\nYabucoa, Puerto Rico\r\n266\r\nYauco, Puerto Rico\r\n267\r\n\u00035Unknown prefix code (809) - Caribbean/Bahama/Virgin Islands/Puerto Rico\r\n"
  },
  {
    "path": "install/regions/regions.81-",
    "content": "Oyamacho Shibuy-ku, Tokyo, Japan\r\n468\r\n\u00035Unknown Prefix code (84-) Tokyo, Japan\r\n"
  },
  {
    "path": "install/regions/regions.810",
    "content": "Bloomfield Hills, Michigan\r\n626\r\nBrighton, Michigan\r\n206\r\nBurton, Michigan\r\n234\r\n742\r\n743\r\n744\r\nClio\u00031/\u00032Mount Morris, Michigan\r\n640\r\n686\r\n687\r\nDavison, Michigan\r\n653\r\n658\r\nFenton, Michigan\r\n629\r\n750\r\nFlint, Michigan\r\n230\r\n232\r\n233\r\n234\r\n235\r\n236\r\n238\r\n239\r\n250\r\n251\r\n257\r\n301\r\n342\r\n715\r\n732\r\n733\r\n736\r\n742\r\n743\r\n744\r\n760\r\n762\r\n767\r\n768\r\n785\r\n787\r\n789\r\nFlushing, Michigan\r\n487\r\n659\r\nGoodrich, Michigan\r\n636\r\nGrand Blanc, Michigan\r\n603\r\n694\r\n695\r\nHolly, Michigan\r\n634\r\nLennon, Michigan\r\n621\r\nLinden, Michigan\r\n735\r\nLivonia, Michigan\r\n474\r\nMontrose, Michigan\r\n639\r\nNovi, Michigan\r\n624\r\nOtisville, Michigan\r\n631\r\nRankin, Michigan\r\n655\r\nSwartz Creek, Michigan\r\n635\r\n\u00035Unknown prefix code (810) - Michigan\r\n"
  },
  {
    "path": "install/regions/regions.812",
    "content": "Alfordsville Glen, Indiana\r\n644\r\nAurora, Indiana\r\n926\r\nAustin, Indiana\r\n794\r\nBandon, Indiana\r\n843\r\nBatesville, Indiana\r\n933\r\n934\r\nBedford, Indiana\r\n275\r\n277\r\n278\r\n279\r\nBicknell, Indiana\r\n735\r\nBirdseye, Indiana\r\n389\r\nBloomfield, Indiana\r\n384\r\nBloomington, Indiana\r\n272\r\n322\r\n323\r\n327\r\n330\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n337\r\n339\r\n556\r\n855\r\n856\r\n857\r\nBoonville, Indiana\r\n897\r\nBrazil, Indiana\r\n442\r\n443\r\n446\r\n448\r\nBrownstown, Indiana\r\n358\r\nBruceville, Indiana\r\n324\r\nButlerville, Indiana\r\n458\r\nCampbellsburg, Indiana\r\n755\r\nCanaan, Indiana\r\n839\r\nCarlisle, Indiana\r\n398\r\nCenter Point, Indiana\r\n835\r\nCentral, Indiana\r\n732\r\nChandler, Indiana\r\n925\r\nCharleston, Indiana\r\n256\r\nChrisney, Indiana\r\n362\r\nClarksville, Indiana\r\n527\r\nClay City, Indiana\r\n939\r\nClearspring, Indiana\r\n995\r\nColumbus, Indiana\r\n342\r\n343\r\n371\r\n372\r\n375\r\n376\r\n377\r\n378\r\n379\r\nCory, Indiana\r\n864\r\nCorydon, Indiana\r\n738\r\nCrandall, Indiana\r\n366\r\nCrane, Indiana\r\n854\r\nCross Plains, Indiana\r\n667\r\nCrothersville, Indiana\r\n793\r\nCynthiana, Indiana\r\n845\r\nDale, Indiana\r\n937\r\nDecker, Indiana\r\n769\r\nDillsboro, Indiana\r\n432\r\nDubois, Indiana\r\n678\r\nDirectory Assistance, Southern Indiana\r\n555\r\nDugger, Indiana\r\n648\r\nEast Enterprise, Indiana\r\n534\r\nEdinburgh, Indiana\r\n526\r\nElberfeld, Indiana\r\n983\r\nElizabeth, Indiana\r\n969\r\nElizabethtown, Indiana\r\n579\r\nEllettsville, Indiana\r\n876\r\nElnora, Indiana\r\n692\r\nEnglish, Indiana\r\n338\r\nEvansville, Indiana\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n428\r\n429\r\n451\r\n453\r\n455\r\n464\r\n465\r\n473\r\n474\r\n476\r\n477\r\n479\r\nFairbanks, Indiana\r\n394\r\nFarmersburg, Indiana\r\n696\r\nFerdinand, Indiana\r\n367\r\nFlat Rock, Indiana\r\n587\r\nFort Branch, Indiana\r\n753\r\n759\r\n768\r\nFrancisco, Indiana\r\n782\r\nFredricksburg, Indiana\r\n472\r\nFreelandville, Indiana\r\n328\r\nFreetown, Indiana\r\n497\r\nFrenchlick, Indiana\r\n003\r\n935\r\n936\r\nFritchton, Indiana\r\n726\r\nGalena, Indiana\r\n923\r\nGeorgetown, Indiana\r\n951\r\nGosport, Indiana\r\n879\r\nGraysville, Indiana\r\n382\r\nGreensburg, Indiana\r\n662\r\n663\r\nGriffin, Indiana\r\n851\r\nGuilford, Indiana\r\n487\r\nHanover, Indiana\r\n866\r\nHaysville, Indiana\r\n695\r\nHazleton, Indiana\r\n784\r\nHeltonville, Indiana\r\n834\r\nHenryville, Indiana\r\n294\r\nHolland, Indiana\r\n536\r\nHope, Indiana\r\n546\r\nHuntingburg, Indiana\r\n683\r\nHymera, Indiana\r\n383\r\nJasonville, Indiana\r\n665\r\nJasper, Indiana\r\n482\r\n634\r\nJeffersonville, Indiana\r\n282\r\n283\r\n284\r\n285\r\n288\r\n872\r\nLaconia, Indiana\r\n737\r\nLake Monroe, Indiana\r\n837\r\nLamar, Indiana\r\n529\r\nLanesville, Indiana\r\n952\r\nLawrenceburg, Indiana\r\n537\r\nLeavenworth, Indiana\r\n739\r\nLewis, Indiana\r\n495\r\nLexington, Indiana\r\n889\r\nLinton, Indiana\r\n847\r\nLoogootee, Indiana\r\n295\r\nLynnville, Indiana\r\n922\r\nLyons, Indiana\r\n659\r\nMackey, Indiana\r\n795\r\nMadison, Indiana\r\n265\r\n273\r\nMarengo, Indiana\r\n365\r\nMccutchnvl, Indiana\r\n867\r\nMedora, Indiana\r\n966\r\nMerom, Indiana\r\n356\r\nMilan, Indiana\r\n654\r\nMilltown, Indiana\r\n633\r\nMitchell, Indiana\r\n849\r\nMonroe City, Indiana\r\n743\r\nMontgomery, Indiana\r\n486\r\nMoores Hill, Indiana\r\n744\r\nMorgantown, Indiana\r\n597\r\nMount Vernon, Indiana\r\n833\r\n838\r\nNapoleon, Indiana\r\n852\r\nNashville, Indiana\r\n988\r\nNew Albany, Indiana\r\n892\r\n944\r\n945\r\n948\r\n949\r\nNewburgh, Indiana\r\n853\r\n858\r\nNew Harmony, Indiana\r\n682\r\nNew Middleton, Indiana\r\n968\r\nNew Washington, Indiana\r\n289\r\n293\r\nNorth Vernon, Indiana\r\n346\r\nOakland City, Indiana\r\n749\r\nOaktown, Indiana\r\n745\r\nOdon, Indiana\r\n636\r\nOrleans, Indiana\r\n865\r\nOwensburg, Indiana\r\n863\r\nOwensville, Indiana\r\n724\r\n729\r\nPalmyra, Indiana\r\n364\r\nPaoli, Indiana\r\n723\r\nPatoka, Indiana\r\n779\r\nPatricksburg, Indiana\r\n859\r\nPatriot, Indiana\r\n594\r\nPekin, Indiana\r\n967\r\nPeoria, Indiana\r\n775\r\n776\r\nPetersburg, Indiana\r\n354\r\nPlainville, Indiana\r\n687\r\nPoland, Indiana\r\n986\r\nPoseyville, Indiana\r\n874\r\nPrairie Creek, Indiana\r\n898\r\nPrinceton, Indiana\r\n385\r\n386\r\nRamsey, Indiana\r\n347\r\nReddington, Indiana\r\n445\r\nRiley, Indiana\r\n894\r\nRising Sun, Indiana\r\n438\r\nRockport, Indiana\r\n649\r\nRosedale, Indiana\r\n848\r\nSalem, Indiana\r\n883\r\nSandborn, Indiana\r\n694\r\nSandridge, Indiana\r\n359\r\nSan Jacinto, Indiana\r\n871\r\n873\r\nSanta Claus, Indiana\r\n544\r\nScipio, Indiana\r\n392\r\nScottsburg, Indiana\r\n525\r\n752\r\n754\r\nSellersburg, Indiana\r\n246\r\nSeelyville, Indiana\r\n877\r\nSeymour, Indiana\r\n522\r\n523\r\n977\r\nShelbourne, Indiana\r\n397\r\nShoals, Indiana\r\n247\r\nSmithville, Indiana\r\n824\r\nSolitude, Indiana\r\n783\r\nSpencer, Indiana\r\n829\r\nSpurgeon, Indiana\r\n721\r\nSaint Anthony, Indiana\r\n326\r\nSaint Joseph, Indiana\r\n963\r\nSaint Leon, Indiana\r\n576\r\nSaint Marks, Indiana\r\n836\r\nSaint Meinrad, Indiana\r\n357\r\nSaint Philip, Indiana\r\n985\r\nStanford, Indiana\r\n825\r\nSullivan, Indiana\r\n268\r\nSunman, Indiana\r\n623\r\nTell City, Indiana\r\n547\r\nTennyson, Indiana\r\n567\r\nTerre Haute, Indiana\r\n231\r\n232\r\n234\r\n235\r\n237\r\n238\r\n239\r\n244\r\n249\r\n299\r\n462\r\n466\r\n478\r\n533\r\n535\r\n538\r\nTrinity Williams, Indiana\r\n388\r\nVersailles, Indiana\r\n689\r\nVevay, Indiana\r\n427\r\nVincennes, Indiana\r\n881\r\n882\r\n885\r\n886\r\n887\r\nWest Harrison, Indiana\r\n565\r\n566\r\n637\r\n656\r\nWadesville, Indiana\r\n673\r\nWashington, Indiana\r\n254\r\n258\r\nWestpoint, Indiana\r\n591\r\nWheatland, Indiana\r\n321\r\nWickliffe, Indiana\r\n685\r\nWinslow, Indiana\r\n789\r\nWorthington, Indiana\r\n875\r\n\u00035Uknown prefix code (812) - Indiana\r\n"
  },
  {
    "path": "install/regions/regions.813",
    "content": "Arcadia, Florida\r\n494\r\n993\r\nAvon Park, Florida\r\n452\r\n453\r\nBartow, Florida\r\n533\r\n534\r\n537\r\nBoca Grande, Florida\r\n964\r\nBonita Springs, Florida\r\n495\r\n947\r\n992\r\nBowling Green, Florida\r\n375\r\nBradenton, Florida\r\n720\r\n727\r\n730\r\n742\r\n750\r\n761\r\n779\r\n739\r\n741\r\n745\r\n746\r\n747\r\n748\r\n749\r\n751\r\n753\r\n755\r\n756\r\n758\r\n778\r\n792\r\n794\r\n795\r\n798\r\nBrandon, Florida\r\n651\r\n653\r\n654\r\n662\r\n681\r\n684\r\n685\r\n689\r\nCape Coral, Florida\r\n540\r\n542\r\n549\r\n945\r\nCape Haze, Florida\r\n697\r\n698\r\nClearwater, Florida\r\n298\r\n420\r\n430\r\n438\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n460\r\n461\r\n462\r\n464\r\n468\r\n469\r\n480\r\n520\r\n523\r\n529\r\n530\r\n531\r\n532\r\n535\r\n536\r\n538\r\n539\r\n559\r\n560\r\n562\r\n580\r\n581\r\n582\r\n584\r\n585\r\n586\r\n587\r\n588\r\n593\r\n595\r\n596\r\n669\r\n724\r\n725\r\n726\r\n733\r\n734\r\n736\r\n738\r\n781\r\n784\r\n785\r\n786\r\n787\r\n789\r\n790\r\n791\r\n796\r\n797\r\n799\r\nClewiston, Florida\r\n599\r\n983\r\nEnglewood, Florida\r\n473\r\n474\r\n475\r\nEverglades, Florida\r\n695\r\nFort Meade, Florida\r\n284\r\n285\r\nFort Meyers Beach, Florida\r\n463\r\n765\r\nFort Meyers, Florida\r\n267\r\n275\r\n277\r\n278\r\n332\r\n334\r\n335\r\n336\r\n337\r\n338\r\n432\r\n433\r\n454\r\n466\r\n470\r\n481\r\n482\r\n489\r\n561\r\n693\r\n694\r\n728\r\n768\r\n850\r\n851\r\n936\r\n939\r\n982\r\n994\r\n998\r\n999\r\n339\r\n490\r\n890\r\n940\r\nFrostproof, Florida\r\n635\r\nHaines County, Florida\r\n421\r\n422\r\n424\r\n427\r\n439\r\nHudson, Florida\r\n857\r\n861\r\n856\r\n862\r\n863\r\n868\r\n869\r\nImmokalee, Florida\r\n658\r\n657\r\nIndian Lake, Florida\r\n692\r\nKeystone, Florida\r\n920\r\nLa Belle, Florida\r\n674\r\n675\r\nLake Wales, Florida\r\n638\r\n676\r\n678\r\n679\r\n696\r\nLakeland, Florida\r\n568\r\n670\r\n499\r\n640\r\n644\r\n646\r\n647\r\n648\r\n660\r\n665\r\n666\r\n667\r\n668\r\n680\r\n682\r\n683\r\n686\r\n687\r\n688\r\n853\r\n858\r\n859\r\nLake Placid, Florida\r\n465\r\n699\r\nLand O'Lakes, Florida\r\n929\r\n996\r\nLehigh Acres, Florida\r\n368\r\n369\r\nLutz, Florida\r\n948\r\n949\r\nMarco Island, Florida\r\n394\r\n642\r\nMoorehaven, Florida\r\n946\r\nMulberry, Florida\r\n425\r\n428\r\nMyakka, Florida\r\n322\r\nNaples, Florida\r\n436\r\n261\r\n262\r\n263\r\n352\r\n353\r\n434\r\n455\r\n643\r\n649\r\n732\r\n774\r\n775\r\n793\r\nNew Port Richey, Florida\r\n372\r\n376\r\n836\r\n841\r\n842\r\n843\r\n844\r\n845\r\n846\r\n847\r\n848\r\n849\r\n834\r\n838\r\nNorth Cape, Florida\r\n458\r\n574\r\n772\r\nNorth Fort Myers, Florida\r\n543\r\n656\r\n731\r\n995\r\n997\r\nNorth Naples, Florida\r\n250\r\n566\r\n591\r\n592\r\n597\r\n598\r\n860\r\n290\r\n450\r\n594\r\nNorth Port, Florida\r\n423\r\n426\r\nOkeechobee, Florida\r\n357\r\n467\r\n763\r\nOldsmar, Florida\r\n852\r\n854\r\n855\r\nPalmetto-Parrish, Florida\r\n722\r\n723\r\n729\r\n776\r\nPine Island, Florida\r\n283\r\nPlant City, Florida\r\n650\r\n659\r\n737\r\n752\r\n754\r\n757\r\n759\r\nPolk City, Florida\r\n984\r\nPort Charlotte, Florida\r\n624\r\n625\r\n627\r\n629\r\n743\r\n255\r\n380\r\n764\r\n769\r\nPunta Gorda, Florida\r\n575\r\n637\r\n639\r\nSarasota, Florida\r\n320\r\n331\r\n358\r\n361\r\n362\r\n374\r\n569\r\n346\r\n349\r\n350\r\n351\r\n355\r\n356\r\n359\r\n364\r\n365\r\n366\r\n371\r\n377\r\n378\r\n379\r\n383\r\n387\r\n388\r\n921\r\n922\r\n923\r\n924\r\n925\r\n951\r\n952\r\n953\r\n954\r\n955\r\n957\r\nSebring, Florida\r\n386\r\n382\r\n385\r\n471\r\nSnblcptvis, Florida\r\n395\r\n472\r\nSpring Lake, Florida\r\n655\r\nSaint Petersburg, Florida\r\n321\r\n323\r\n327\r\n328\r\n341\r\n343\r\n344\r\n345\r\n347\r\n360\r\n363\r\n367\r\n381\r\n384\r\n391\r\n392\r\n393\r\n397\r\n398\r\n399\r\n521\r\n522\r\n525\r\n526\r\n527\r\n528\r\n541\r\n544\r\n545\r\n546\r\n547\r\n556\r\n570\r\n571\r\n572\r\n573\r\n576\r\n577\r\n578\r\n579\r\n821\r\n822\r\n823\r\n824\r\n825\r\n826\r\n864\r\n866\r\n867\r\n892\r\n893\r\n894\r\n895\r\n896\r\n898\r\n252\r\nTampa, Florida\r\n246\r\n249\r\n260\r\n271\r\n274\r\n288\r\n292\r\n330\r\n333\r\n340\r\n390\r\n396\r\n429\r\n567\r\n632\r\n673\r\n744\r\n891\r\n899\r\n220\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n230\r\n231\r\n232\r\n234\r\n236\r\n237\r\n238\r\n239\r\n240\r\n241\r\n242\r\n244\r\n245\r\n247\r\n248\r\n251\r\n253\r\n254\r\n258\r\n259\r\n264\r\n265\r\n266\r\n270\r\n272\r\n273\r\n276\r\n281\r\n282\r\n286\r\n287\r\n289\r\n348\r\n554\r\n558\r\n620\r\n621\r\n622\r\n623\r\n626\r\n628\r\n664\r\n671\r\n677\r\n690\r\n830\r\n831\r\n832\r\n835\r\n837\r\n839\r\n840\r\n870\r\n871\r\n872\r\n873\r\n874\r\n875\r\n876\r\n877\r\n878\r\n879\r\n880\r\n881\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\n926\r\n930\r\n931\r\n932\r\n933\r\n935\r\n960\r\n961\r\n962\r\n963\r\n968\r\n969\r\n971\r\n972\r\n974\r\n975\r\n977\r\n978\r\n979\r\n980\r\n985\r\n986\r\n987\r\n988\r\n989\r\n990\r\n991\r\nTarpon Springs, Florida\r\n934\r\n937\r\n938\r\n942\r\n943\r\nTemple Terrace, Florida\r\n914\r\nValrico, Florida\r\n661\r\nVenice, Florida\r\n486\r\n496\r\n483\r\n484\r\n485\r\n488\r\n492\r\n493\r\n497\r\n966\r\nWauchula, Florida\r\n767\r\n773\r\nWesley Chapel, Florida\r\n973\r\nWimauma-Ruskin, Florida\r\n633\r\n634\r\n641\r\n645\r\nWinter Haven, Florida\r\n293\r\n294\r\n297\r\n299\r\n324\r\n325\r\n956\r\n965\r\n967\r\n291\r\n326\r\n551\r\nYbor City, Florida\r\n301\r\n524\r\nZephyr Hills, Florida\r\n780\r\n782\r\n783\r\n788\r\nZolfo Springs, Florida\r\n735\r\n\u00035Unknown prefix code (813) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.814",
    "content": "Albion, Pennsylvania\r\n756\r\nAlexandria, Pennsylvania\r\n667\r\n669\r\nAltoona, Pennsylvania\r\n567\r\n940\r\n931\r\n935\r\n941\r\n942\r\n943\r\n944\r\n946\r\n947\r\n949\r\nAustin, Pennsylvania\r\n647\r\nBarnesboro, Pennsylvania\r\n948\r\nBeaverdale, Pennsylvania\r\n487\r\nBedford, Pennsylvania\r\n585\r\n977\r\n623\r\nBedford Valley, Pennsylvania\r\n356\r\nBellefonte, Pennsylvania\r\n353\r\n355\r\n359\r\n571\r\nBellwood, Pennsylvania\r\n742\r\nBerlin, Pennsylvania\r\n267\r\nBig Run, Pennsylvania\r\n427\r\nBoalsburg, Pennsylvania\r\n466\r\n808\r\n880\r\nBoswell, Pennsylvania\r\n629\r\nBradford, Pennsylvania\r\n598\r\n362\r\n368\r\nBreezewood, Pennsylvania\r\n735\r\nBrockway, Pennsylvania\r\n261\r\n265\r\n268\r\nBrookville, Pennsylvania\r\n849\r\nCallensburg, Pennsylvania\r\n358\r\nCambridge Springs, Pennsylvania\r\n398\r\nCarrollton, Pennsylvania\r\n344\r\nCentral City, Pennsylvania\r\n754\r\nCentrehall, Pennsylvania\r\n364\r\nCharlesville, Pennsylvania\r\n847\r\nCherrytree, Pennsylvania\r\n743\r\nClarion, Pennsylvania\r\n229\r\n226\r\n227\r\nClaysburg, Pennsylvania\r\n239\r\nClearfield, Pennsylvania\r\n590\r\n765\r\n768\r\n857\r\nClearville, Pennsylvania\r\n784\r\nClintonville, Pennsylvania\r\n385\r\nCoalport, Pennsylvania\r\n672\r\nCochranton, Pennsylvania\r\n425\r\nColver, Pennsylvania\r\n748\r\nConfluence, Pennsylvania\r\n395\r\nConneaut Lake, Pennsylvania\r\n382\r\nConneautville, Pennsylvania\r\n587\r\nCooperstown, Pennsylvania\r\n374\r\nCorry, Pennsylvania\r\n663\r\n664\r\n665\r\nCorsica, Pennsylvania\r\n379\r\nCouders Point, Pennsylvania\r\n274\r\nCresson, Pennsylvania\r\n886\r\nCurwensville, Pennsylvania\r\n236\r\nDavidsville, Pennsylvania\r\n479\r\nDayton, Pennsylvania\r\n257\r\nDriftwood, Pennsylvania\r\n546\r\nDu Bois, Pennsylvania\r\n371\r\n375\r\nDuke Center, Pennsylvania\r\n966\r\nEbensburg, Pennsylvania\r\n472\r\nEdinboro, Pennsylvania\r\n732\r\n734\r\nEldred, Pennsylvania\r\n225\r\nElkland, Pennsylvania\r\n258\r\n932\r\nEmporium, Pennsylvania\r\n483\r\n486\r\nEndeavor, Pennsylvania\r\n463\r\nErie, Pennsylvania\r\n877\r\n878\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n459\r\n824\r\n825\r\n833\r\n835\r\n838\r\n864\r\n866\r\n868\r\n870\r\n871\r\n875\r\n881\r\n898\r\n899\r\nEverett, Pennsylvania\r\n652\r\nFairview, Pennsylvania\r\n474\r\nFishertown, Pennsylvania\r\n839\r\nFranklin, Pennsylvania\r\n432\r\n437\r\nFrenchville, Pennsylvania\r\n263\r\nGaleton, Pennsylvania\r\n435\r\nGenesee, Pennsylvania\r\n228\r\nGirard, Pennsylvania\r\n774\r\nGlasgow, Pennsylvania\r\n687\r\nGlen Campbell, Pennsylvania\r\n845\r\nGrand Valley, Pennsylvania\r\n436\r\nGuys Mills, Pennsylvania\r\n789\r\nHarrison Valley, Pennsylvania\r\n334\r\nHastings, Pennsylvania\r\n247\r\nHawthorn, Pennsylvania\r\n365\r\nHazen, Pennsylvania\r\n328\r\nHewitt, Pennsylvania\r\n458\r\nHolidaysburg, Pennsylvania\r\n695\r\n696\r\nHooversville, Pennsylvania\r\n798\r\nHopewell, Pennsylvania\r\n928\r\nHoutzdale, Pennsylvania\r\n378\r\nHoward, Pennsylvania\r\n625\r\nHuntingdon, Pennsylvania\r\n599\r\n641\r\n643\r\nHyndman, Pennsylvania\r\n842\r\nJohnsonburg, Pennsylvania\r\n965\r\nJohnstown, Pennsylvania\r\n241\r\n242\r\n255\r\n266\r\n269\r\n288\r\n322\r\n532\r\n533\r\n535\r\n536\r\n539\r\nKane, Pennsylvania\r\n837\r\nKersey, Pennsylvania\r\n885\r\nKnox, Pennsylvania\r\n797\r\nKnoxville, Pennsylvania\r\n326\r\nLeeper, Pennsylvania\r\n744\r\nLincolnville, Pennsylvania\r\n694\r\nLinesville, Pennsylvania\r\n683\r\nLoysburg, Pennsylvania\r\n766\r\nLudlow, Pennsylvania\r\n945\r\nLuthersburg, Pennsylvania\r\n583\r\nMahaffey, Pennsylvania\r\n277\r\nMarienville, Pennsylvania\r\n927\r\nMarklesburg, Pennsylvania\r\n658\r\nMartinsburg, Pennsylvania\r\n793\r\nMcKean, Pennsylvania\r\n476\r\nMcConneltown, Pennsylvania\r\n627\r\nMeadville, Pennsylvania\r\n332\r\n333\r\n336\r\n337\r\n724\r\nMeyersdale, Pennsylvania\r\n634\r\nMillheim, Pennsylvania\r\n349\r\nMillport, Pennsylvania\r\n698\r\nMount Union, Pennsylvania\r\n542\r\nMount Jewett, Pennsylvania\r\n778\r\nNanty Glo, Pennsylvania\r\n749\r\nNew Bethlehem, Pennsylvania\r\n275\r\nNew Grenada, Pennsylvania\r\n685\r\nNorth East, Pennsylvania\r\n725\r\nOil City, Pennsylvania\r\n644\r\n645\r\n646\r\n648\r\n649\r\n676\r\n677\r\n678\r\nOrbisonia, Pennsylvania\r\n447\r\nOsceola Mills, Pennsylvania\r\n339\r\nOsterburg, Pennsylvania\r\n276\r\nPatton, Pennsylvania\r\n674\r\nPenfield, Pennsylvania\r\n637\r\nPhilipsburg, Pennsylvania\r\n342\r\nPleasantville, Pennsylvania\r\n589\r\nPortage, Pennsylvania\r\n736\r\nPort Allegny, Pennsylvania\r\n642\r\nPort Matilda, Pennsylvania\r\n692\r\nPunxsutawny, Pennsylvania\r\n938\r\nRew, Pennsylvania\r\n465\r\nReynoldsville, Pennsylvania\r\n541\r\n653\r\nRidgway, Pennsylvania\r\n772\r\n773\r\n776\r\nRimersburg, Pennsylvania\r\n473\r\nRoaring Spring, Pennsylvania\r\n224\r\nRockland, Pennsylvania\r\n498\r\nRockwood, Pennsylvania\r\n352\r\n926\r\nRoulette, Pennsylvania\r\n544\r\nRussell, Pennsylvania\r\n757\r\nSabinsville, Pennsylvania\r\n628\r\nSaegertown, Pennsylvania\r\n763\r\nSalisbury, Pennsylvania\r\n662\r\nSaxton, Pennsylvania\r\n635\r\nSchellsburg, Pennsylvania\r\n733\r\nSeward, Pennsylvania\r\n446\r\nShade Gap, Pennsylvania\r\n259\r\nSheffield, Pennsylvania\r\n968\r\nShinglehouse, Pennsylvania\r\n697\r\nShippenville, Pennsylvania\r\n782\r\nSigel, Pennsylvania\r\n752\r\nSligo, Pennsylvania\r\n745\r\nSmethport, Pennsylvania\r\n887\r\nSnow Shoe, Pennsylvania\r\n387\r\nSomerset, Pennsylvania\r\n443\r\n445\r\nSouth Fork, Pennsylvania\r\n495\r\nSpartansburg, Pennsylvania\r\n654\r\nSpring Mills, Pennsylvania\r\n422\r\nSaint Marys, Pennsylvania\r\n781\r\n834\r\nState College, Pennsylvania\r\n231\r\n234\r\n237\r\n238\r\n861\r\n862\r\n863\r\n865\r\n867\r\nState Line, Pennsylvania\r\n767\r\nStoystown, Pennsylvania\r\n893\r\nStrattanville, Pennsylvania\r\n764\r\nSugargrove, Pennsylvania\r\n489\r\nSummerville, Pennsylvania\r\n856\r\nSykesville, Pennsylvania\r\n894\r\nThree Springs, Pennsylvania\r\n448\r\nTidioute, Pennsylvania\r\n484\r\nTimblin, Pennsylvania\r\n256\r\nTionesta, Pennsylvania\r\n755\r\nTitusville, Pennsylvania\r\n827\r\nTownville, Pennsylvania\r\n967\r\nTyrone, Pennsylvania\r\n684\r\nUlysses, Pennsylvania\r\n848\r\nUnion City, Pennsylvania\r\n438\r\nVenus, Pennsylvania\r\n354\r\nWarren, Pennsylvania\r\n723\r\n726\r\nWarriors Mark, Pennsylvania\r\n632\r\nWaterford, Pennsylvania\r\n796\r\nWattsburg, Pennsylvania\r\n739\r\nWeedville, Pennsylvania\r\n787\r\nWellersburg, Pennsylvania\r\n324\r\nWesley, Pennsylvania\r\n786\r\nWestfield, Pennsylvania\r\n367\r\nWilcox, Pennsylvania\r\n929\r\nWilliamsburg, Pennsylvania\r\n832\r\nWinburne, Pennsylvania\r\n345\r\nWindber, Pennsylvania\r\n467\r\nWest Springfield, Pennsylvania\r\n922\r\nYoungsville, Pennsylvania\r\n563\r\nZion, Pennsylvania\r\n383\r\n\u00035Unknown prefix code (814) - Pennsylvania\r\n"
  },
  {
    "path": "install/regions/regions.815",
    "content": "Amboy, Illinois\r\n857\r\nApple River, Illinois\r\n492\r\n594\r\nAshkum, Illinois\r\n698\r\nAshton, Illinois\r\n453\r\nBeaverville, Illinois\r\n435\r\nBelvidere, Illinois\r\n544\r\n547\r\nBraidwood, Illinois\r\n458\r\nBureau, Illinois\r\n659\r\nByron, Illinois\r\n234\r\nCabery, Illinois\r\n949\r\nCampus, Illinois\r\n567\r\nCapron, Illinois\r\n569\r\nCedar Point, Illinois\r\n446\r\nCedarville, Illinois\r\n563\r\nChadwick, Illinois\r\n684\r\nChatsworth, Illinois\r\n635\r\nChebanse, Illinois\r\n697\r\nChenoa, Illinois\r\n945\r\nCherry Valley, Illinois\r\n332\r\nCissna Park, Illinois\r\n457\r\nClifton, Illinois\r\n694\r\nCoal City, Illinois\r\n634\r\nColeta, Illinois\r\n336\r\nCompton, Illinois\r\n497\r\nCornell, Illinois\r\n358\r\nCrescent City, Illinois\r\n683\r\nCreston, Illinois\r\n384\r\nCrystal Lake, Illinois\r\n455\r\n459\r\n477\r\n356\r\nCullom, Illinois\r\n689\r\nDakota, Illinois\r\n449\r\nDanforth, Illinois\r\n269\r\nDavis, Illinois\r\n865\r\nDeKalb, Illinois\r\n275\r\n746\r\n751\r\n754\r\n755\r\n757\r\n748\r\n752\r\n753\r\n756\r\n758\r\n977\r\nDepue, Illinois\r\n447\r\nDixon, Illinois\r\n285\r\n284\r\n288\r\nDonovan, Illinois\r\n486\r\nDover, Illinois\r\n643\r\nDurand, Illinois\r\n248\r\nDwight, Illinois\r\n584\r\nEast Dubuque, Illinois\r\n747\r\nEarlville, Illinois\r\n246\r\nElizabeth, Illinois\r\n858\r\nElwood, Illinois\r\n423\r\n424\r\nEmington, Illinois\r\n934\r\nFairbury, Illinois\r\n692\r\nFlanagan, Illinois\r\n796\r\nForrest, Illinois\r\n657\r\nForreston, Illinois\r\n938\r\nFrankfort, Illinois\r\n464\r\n469\r\nFrankln Grove, Illinois\r\n456\r\nFreeport, Illinois\r\n238\r\n232\r\n233\r\n235\r\nFulton, Illinois\r\n589\r\nGalena, Illinois\r\n777\r\nGarden Prairie, Illinois\r\n597\r\nGardner, Illinois\r\n237\r\nGenoa, Illinois\r\n784\r\nGerman Valley, Illinois\r\n362\r\nGilman, Illinois\r\n265\r\nGrand Detour, Illinois\r\n652\r\nGrandridge, Illinois\r\n249\r\nGrant Park, Illinois\r\n465\r\nGranville, Illinois\r\n339\r\nGraymont, Illinois\r\n743\r\nHanover, Illinois\r\n591\r\nHarding, Illinois\r\n792\r\nHarmon, Illinois\r\n359\r\nHarvard, Illinois\r\n943\r\nHebron, Illinois\r\n648\r\nHennepin, Illinois\r\n925\r\nHerscher, Illinois\r\n426\r\nHinckley, Illinois\r\n286\r\nHooppole, Illinois\r\n948\r\nJoliet, Illinois\r\n735\r\n474\r\n767\r\n722\r\n723\r\n726\r\n727\r\n740\r\n774\r\n725\r\n729\r\n741\r\n744\r\n773\r\nKankakee, Illinois\r\n922\r\n928\r\n936\r\n953\r\n592\r\n932\r\n933\r\n935\r\n937\r\n939\r\nKempton, Illinois\r\n253\r\nKinsman, Illinois\r\n392\r\nKirkland, Illinois\r\n522\r\nLa Grange, Illinois\r\n294\r\nLa Moille, Illinois\r\n638\r\nLa Salle, Illinois\r\n228\r\n223\r\n224\r\nLadd, Illinois\r\n894\r\nLanark, Illinois\r\n493\r\nLeaf River, Illinois\r\n738\r\nLeland, Illinois\r\n495\r\nLena, Illinois\r\n369\r\nLeonore, Illinois\r\n856\r\nLisbon, Illinois\r\n736\r\nLockport, Illinois\r\n254\r\n372\r\n886\r\n348\r\n532\r\n836\r\n834\r\n838\r\nLong Point, Illinois\r\n854\r\nLostant, Illinois\r\n368\r\nLyndon, Illinois\r\n778\r\nMagnolia, Illinois\r\n869\r\nMalta, Illinois\r\n825\r\nManhattan, Illinois\r\n478\r\nManlius, Illinois\r\n445\r\nManteno, Illinois\r\n468\r\nMaple Park, Illinois\r\n827\r\nMarengo, Illinois\r\n568\r\nMarseilles, Illinois\r\n795\r\nMartinton, Illinois\r\n428\r\nMassbach, Illinois\r\n598\r\nMazon, Illinois\r\n448\r\nMcConnell, Illinois\r\n868\r\nMcHenry, Illinois\r\n759\r\n344\r\n363\r\n385\r\nMcNabb, Illinois\r\n882\r\nMendota, Illinois\r\n538\r\n539\r\nMilford, Illinois\r\n889\r\nMilledgeville, Illinois\r\n225\r\nMinooka, Illinois\r\n647\r\n467\r\nMomence Hop, Illinois\r\n944\r\nMomence, Illinois\r\n472\r\nMonroe Center, Illinois\r\n393\r\nMorris, Illinois\r\n941\r\n942\r\nMorrison, Illinois\r\n772\r\nMount Carroll, Illinois\r\n244\r\nMount Morris, Illinois\r\n734\r\nNelson, Illinois\r\n251\r\nNew Lenox, Illinois\r\n462\r\n485\r\nNewark, Illinois\r\n695\r\nNew Milford, Illinois\r\n874\r\nOdell, Illinois\r\n998\r\nOglesby, Illinois\r\n883\r\nOhio, Illinois\r\n376\r\nOnarga, Illinois\r\n268\r\nOrangeville, Illinois\r\n789\r\nOregon, Illinois\r\n732\r\nOttawa, Illinois\r\n488\r\n433\r\n434\r\nPaw Paw, Illinois\r\n627\r\nPearl City, Illinois\r\n443\r\nPecatonica, Illinois\r\n239\r\nPiper City, Illinois\r\n686\r\nPlainfield, Illinois\r\n436\r\n439\r\n556\r\nPlatteville, Illinois\r\n475\r\nPolo, Illinois\r\n946\r\nPontiac, Illinois\r\n848\r\n842\r\n844\r\nPoplar Grove, Illinois\r\n765\r\nPrinceton, Illinois\r\n866\r\n878\r\n872\r\n875\r\n879\r\nProphetston, Illinois\r\n537\r\nPutnam, Illinois\r\n437\r\nRansom, Illinois\r\n586\r\nReddick, Illinois\r\n365\r\nRichmond, Illinois\r\n678\r\nRochelle, Illinois\r\n562\r\nRock Cut, Illinois\r\n885\r\nRockford, Illinois\r\n226\r\n229\r\n262\r\n282\r\n394\r\n395\r\n397\r\n398\r\n399\r\n489\r\n494\r\n624\r\n633\r\n654\r\n877\r\n961\r\n962\r\n963\r\n964\r\n965\r\n966\r\n968\r\n987\r\n983\r\n227\r\n636\r\n637\r\n967\r\n969\r\n985\r\n988\r\nRoscoe, Illinois\r\n623\r\nRutland, Illinois\r\n863\r\nSandwich, Illinois\r\n786\r\nSaunemin, Illinois\r\n832\r\nSavanna, Illinois\r\n273\r\nScales Mound, Illinois\r\n845\r\nSeneca, Illinois\r\n357\r\nSeward, Illinois\r\n247\r\nShabbona, Illinois\r\n824\r\nShannon, Illinois\r\n864\r\nSheffield, Illinois\r\n454\r\nSheldon, Illinois\r\n429\r\nSheridan, Illinois\r\n496\r\nShirland, Illinois\r\n629\r\nSouth Beloit, Illinois\r\n389\r\nSouth Bergen, Illinois\r\n292\r\nSouth Sharon, Illinois\r\n737\r\nSouth Monauk, Illinois\r\n498\r\nSpring Grove, Illinois\r\n675\r\nSpring Valley, Illinois\r\n663\r\n664\r\nSaint Anne, Illinois\r\n427\r\nStelle, Illinois\r\n256\r\nSterling, Illinois\r\n622\r\n625\r\n626\r\nSteward, Illinois\r\n396\r\nStilman Valley, Illinois\r\n645\r\nStockland, Illinois\r\n682\r\nStockton, Illinois\r\n947\r\nStrawn, Illinois\r\n688\r\nStreator, Illinois\r\n257\r\n674\r\n672\r\n673\r\nSublette, Illinois\r\n849\r\nSycamore, Illinois\r\n899\r\n895\r\nTampico, Illinois\r\n438\r\nThomas, Illinois\r\n542\r\nThomson, Illinois\r\n259\r\nTiskilwa, Illinois\r\n646\r\nToluca, Illinois\r\n452\r\nTonica, Illinois\r\n442\r\nUnion, Illinois\r\n923\r\nUtica, Illinois\r\n582\r\n667\r\nVerona, Illinois\r\n287\r\nWest Brooklyn, Illinois\r\n628\r\nWalnut, Illinois\r\n379\r\nWarren, Illinois\r\n745\r\nWaterman, Illinois\r\n264\r\nWatseka, Illinois\r\n432\r\nWellington, Illinois\r\n984\r\nWenona, Illinois\r\n853\r\nWilmington, Illinois\r\n476\r\nWinnebago, Illinois\r\n335\r\nWinslow, Illinois\r\n367\r\nWonder Lake, Illinois\r\n653\r\n728\r\nWoodland, Illinois\r\n473\r\nWoodstock, Illinois\r\n347\r\n353\r\n334\r\n382\r\n236\r\n337\r\n338\r\nWyanet, Illinois\r\n699\r\n\u00035Unknown prefix code (815) - Illinois\r\n"
  },
  {
    "path": "install/regions/regions.816",
    "content": "Adrian, Missouri\r\n297\r\nAgency, Missouri\r\n253\r\nAlbany, Missouri\r\n726\r\nAllendale, Missouri\r\n786\r\nAlma, Missouri\r\n674\r\nAmazonia, Missouri\r\n475\r\nAmoret, Missouri\r\n925\r\nAmsterdam, Missouri\r\n267\r\nAndover, Missouri\r\n878\r\nAppleton City, Missouri\r\n476\r\nArbela, Missouri\r\n945\r\nArchie, Missouri\r\n293\r\nArmstrong, Missouri\r\n273\r\nArrow Rock, Missouri\r\n837\r\nAthens, Missouri\r\n877\r\nAtlanta, Missouri\r\n239\r\nAvalon, Missouri\r\n636\r\nAvenue City, Missouri\r\n662\r\nBaring, Missouri\r\n892\r\nBarnard, Missouri\r\n652\r\nBelton, Missouri\r\n322\r\n331\r\n348\r\nBethany, Missouri\r\n425\r\nBethel, Missouri\r\n284\r\nBevier, Missouri\r\n773\r\nBlackburn, Missouri\r\n538\r\nBlackwater, Missouri\r\n846\r\nBlairstown, Missouri\r\n498\r\nBloomington, Missouri\r\n384\r\nBlue Lick, Missouri\r\n631\r\nBlue Springs, Missouri\r\n224\r\n228\r\n229\r\nBogard, Missouri\r\n731\r\nBolckow, Missouri\r\n428\r\nBoonville, Missouri\r\n888\r\n882\r\nBosworth, Missouri\r\n534\r\nBrashear, Missouri\r\n323\r\nBraymer, Missouri\r\n645\r\nBreckenridge, Missouri\r\n644\r\nBrimson, Missouri\r\n789\r\nBristleridge, Missouri\r\n624\r\nBurlington Junction, Missouri\r\n725\r\nBrock, Missouri\r\n328\r\nBrookfield, Missouri\r\n258\r\nBrowning, Missouri\r\n946\r\nBrunswick, Missouri\r\n548\r\nBucklin, Missouri\r\n695\r\nBuckner, Missouri\r\n249\r\nBunceton, Missouri\r\n427\r\nButler, Missouri\r\n679\r\nBynumville, Missouri\r\n222\r\nCainesville, Missouri\r\n893\r\nCalhoun, Missouri\r\n694\r\nCallao, Missouri\r\n768\r\nCamden Point, Missouri\r\n445\r\nCameron, Missouri\r\n632\r\nCarrollton, Missouri\r\n542\r\nCenterview, Missouri\r\n656\r\nChilhowee, Missouri\r\n678\r\nChillicoth, Missouri\r\n646\r\nChula, Missouri\r\n639\r\nClarence, Missouri\r\n699\r\nClarksdale, Missouri\r\n393\r\nClearmont, Missouri\r\n729\r\nCleveland, Missouri\r\n658\r\nClifton Hl, Missouri\r\n261\r\nClinton, Missouri\r\n492\r\n885\r\nCoal, Missouri\r\n477\r\nCoffey, Missouri\r\n533\r\nCole Camp, Missouri\r\n668\r\nConcordia, Missouri\r\n463\r\nConception Junction, Missouri\r\n944\r\nCorder, Missouri\r\n394\r\nCosby, Missouri\r\n378\r\nCowgill, Missouri\r\n255\r\nCraig, Missouri\r\n683\r\nCreighton, Missouri\r\n499\r\nDalton, Missouri\r\n544\r\nDarlington, Missouri\r\n666\r\nDawn, Missouri\r\n745\r\nDe Kalb, Missouri\r\n685\r\nDe Witt, Missouri\r\n549\r\nDearborn, Missouri\r\n992\r\nDeepwater, Missouri\r\n696\r\nDenver, Missouri\r\n326\r\nDowning, Missouri\r\n379\r\nDrexel, Missouri\r\n657\r\nEast Atchison, Missouri\r\n579\r\nEagleville, Missouri\r\n867\r\nEast Lynne, Missouri\r\n869\r\nEaston, Missouri\r\n473\r\nEdgerton, Missouri\r\n227\r\nEdina, Missouri\r\n397\r\nEast Independence, Missouri\r\n795\r\n796\r\nElk Grove, Missouri\r\n641\r\nElmer, Missouri\r\n825\r\nElmo, Missouri\r\n742\r\nEast Pleasanton, Missouri\r\n447\r\nEthel, Missouri\r\n486\r\nExcello, Missouri\r\n775\r\nExcelsior Springs, Missouri\r\n637\r\nFairfax, Missouri\r\n686\r\nFarley, Missouri\r\n546\r\nFayette, Missouri\r\n248\r\nFerrelview, Missouri\r\n243\r\n464\r\n466\r\nFillmore, Missouri\r\n487\r\nFlorence, Missouri\r\n368\r\nForest Green, Missouri\r\n481\r\nFortuna, Missouri\r\n337\r\nFoster, Missouri\r\n832\r\nFreeman, Missouri\r\n899\r\nGallatin, Missouri\r\n663\r\nGalt, Missouri\r\n673\r\nGarden City, Missouri\r\n862\r\nGentry, Missouri\r\n448\r\nGilliam, Missouri\r\n784\r\nGilman City, Missouri\r\n876\r\nGladstone, Missouri\r\n436\r\n452\r\n453\r\n454\r\n455\r\n459\r\n468\r\nGlasgow, Missouri\r\n338\r\nGorin, Missouri\r\n282\r\nGower, Missouri\r\n424\r\nGraham, Missouri\r\n939\r\nGrain Valley, Missouri\r\n443\r\nGrant City, Missouri\r\n564\r\nGreen City, Missouri\r\n874\r\nGreenridge, Missouri\r\n527\r\nGreentop, Missouri\r\n949\r\nGreenwood, Missouri\r\n537\r\n623\r\nHale, Missouri\r\n565\r\nHamilton, Missouri\r\n583\r\nHardin, Missouri\r\n398\r\nHarrisonville, Missouri\r\n884\r\n887\r\nHelena, Missouri\r\n369\r\nHenrietta, Missouri\r\n494\r\nHigbee, Missouri\r\n456\r\nHigginsville, Missouri\r\n584\r\nHigh Point, Missouri\r\n489\r\nHolden, Missouri\r\n732\r\nHolliday, Missouri\r\n266\r\nHolt, Missouri\r\n264\r\nHopkins, Missouri\r\n778\r\nHouston, Missouri\r\n568\r\nHume, Missouri\r\n643\r\nHuntsville, Missouri\r\n277\r\nHurdland, Missouri\r\n423\r\nIndependence, Missouri\r\n252\r\n254\r\n257\r\n325\r\n373\r\n461\r\n478\r\n521\r\n833\r\n836\r\nIonia, Missouri\r\n285\r\nJacksonville, Missouri\r\n295\r\nJameson, Missouri\r\n828\r\nJamesport, Missouri\r\n684\r\nJamestown, Missouri\r\n849\r\nKahoka, Missouri\r\n727\r\nKansas City, Missouri\r\n221\r\n223\r\n225\r\n231\r\n234\r\n241\r\n242\r\n245\r\n247\r\n274\r\n275\r\n276\r\n283\r\n292\r\n333\r\n346\r\n361\r\n363\r\n374\r\n391\r\n395\r\n421\r\n426\r\n435\r\n444\r\n471\r\n472\r\n474\r\n483\r\n497\r\n523\r\n531\r\n545\r\n556\r\n561\r\n571\r\n572\r\n576\r\n589\r\n591\r\n654\r\n691\r\n698\r\n751\r\n753\r\n756\r\n757\r\n821\r\n822\r\n842\r\n844\r\n854\r\n861\r\n871\r\n881\r\n921\r\n922\r\n923\r\n924\r\n926\r\n931\r\n932\r\n968\r\n995\r\n997\r\n235\r\n289\r\n329\r\n340\r\n349\r\n360\r\n392\r\n440\r\n482\r\n520\r\n536\r\n560\r\n590\r\n759\r\n769\r\n823\r\n830\r\n835\r\n840\r\n860\r\n870\r\n889\r\n898\r\n920\r\n929\r\n940\r\nKearney, Missouri\r\n635\r\nKeytesville, Missouri\r\n288\r\nKidder, Missouri\r\n575\r\nKimberly, Missouri\r\n670\r\nKing City, Missouri\r\n535\r\nKingston, Missouri\r\n586\r\nKingsville, Missouri\r\n597\r\nKirksville, Missouri\r\n341\r\n626\r\n627\r\n665\r\n785\r\nKnobnoster, Missouri\r\n563\r\n687\r\nKnox City, Missouri\r\n434\r\nKnoxville, Missouri\r\n352\r\nLa Belle, Missouri\r\n462\r\nLa Monte, Missouri\r\n347\r\nLa Plata, Missouri\r\n332\r\nLaclede, Missouri\r\n963\r\nLancaster, Missouri\r\n457\r\nLaredo, Missouri\r\n286\r\nLatham, Missouri\r\n458\r\nLathrop, Missouri\r\n528\r\nLawson, Missouri\r\n296\r\nLees Summit, Missouri\r\n246\r\n251\r\n524\r\n525\r\nLeeton, Missouri\r\n653\r\nLemons, Missouri\r\n344\r\nLeonard, Missouri\r\n762\r\nLexington, Missouri\r\n259\r\nLiberty, Missouri\r\n781\r\n792\r\nLincoln, Missouri\r\n547\r\nLinneus, Missouri\r\n895\r\nLake Lotawana, Missouri\r\n578\r\n774\r\nLock Springs, Missouri\r\n772\r\nLonejack, Missouri\r\n566\r\nLucerne, Missouri\r\n793\r\nLudlow, Missouri\r\n738\r\nLuray, Missouri\r\n866\r\nLvnwr Lnsg, Missouri\r\n996\r\nMacon, Missouri\r\n385\r\nMadison, Missouri\r\n291\r\nMaitland, Missouri\r\n935\r\nMalta Bend, Missouri\r\n595\r\nMarceline, Missouri\r\n376\r\nMarshall, Missouri\r\n886\r\nMarshall Junction, Missouri\r\n879\r\nMartinston, Missouri\r\n355\r\nMaryville, Missouri\r\n541\r\n449\r\n562\r\n582\r\nMayview, Missouri\r\n237\r\nMeadville, Missouri\r\n938\r\nMemphis, Missouri\r\n465\r\nMendon, Missouri\r\n272\r\nMercer, Missouri\r\n382\r\nMiami, Missouri\r\n852\r\nMilan, Missouri\r\n265\r\nMissouri City, Missouri\r\n336\r\nMoberly, Missouri\r\n651\r\n263\r\n269\r\nMontrose, Missouri\r\n693\r\nMooresville, Missouri\r\n755\r\nMound City, Missouri\r\n442\r\nMount Moriah, Missouri\r\n824\r\nNashua, Missouri\r\n420\r\n437\r\n734\r\nNelson, Missouri\r\n859\r\nNew Boston, Missouri\r\n689\r\nNewark, Missouri\r\n733\r\nNew Cambria, Missouri\r\n226\r\nNew Frankln, Missouri\r\n848\r\nNewhampton, Missouri\r\n439\r\nNewtown, Missouri\r\n794\r\nNorborne, Missouri\r\n594\r\nNovelty, Missouri\r\n739\r\nNovinger, Missouri\r\n488\r\nOak Grove, Missouri\r\n625\r\nOdessa, Missouri\r\n633\r\nOmaha, Missouri\r\n933\r\nOregon, Missouri\r\n446\r\nOrrick, Missouri\r\n496\r\nOsborn, Missouri\r\n675\r\nOtterville, Missouri\r\n366\r\nParis, Missouri\r\n327\r\nParkville, Missouri\r\n587\r\n741\r\n746\r\nParnell, Missouri\r\n986\r\nPattonsburg, Missouri\r\n367\r\nPeculiar, Missouri\r\n758\r\nPickering, Missouri\r\n927\r\nPilot Grove, Missouri\r\n834\r\nPlatte City, Missouri\r\n431\r\n858\r\nPlattsburg, Missouri\r\n539\r\nPleasant Hill, Missouri\r\n987\r\nPollock, Missouri\r\n692\r\nPolo, Missouri\r\n354\r\nPowersville, Missouri\r\n592\r\nPrairie Hill, Missouri\r\n777\r\nPrairie Lick, Missouri\r\n621\r\nPrar Home, Missouri\r\n841\r\nPrinceton, Missouri\r\n748\r\nPurdin, Missouri\r\n244\r\nQueen City, Missouri\r\n766\r\nRavenwood, Missouri\r\n937\r\nRaytown, Missouri\r\n353\r\n356\r\n358\r\n737\r\n743\r\nRevere, Missouri\r\n948\r\nRichmond, Missouri\r\n776\r\nRidgeway, Missouri\r\n872\r\nRock Port, Missouri\r\n787\r\n744\r\nRockville, Missouri\r\n598\r\nRosendale, Missouri\r\n567\r\nRothville, Missouri\r\n256\r\nRushville, Missouri\r\n688\r\nSalisbury, Missouri\r\n388\r\nSan Antonio, Missouri\r\n667\r\nSavannah, Missouri\r\n324\r\nSedalia, Missouri\r\n281\r\n530\r\n826\r\n827\r\nShannondale, Missouri\r\n788\r\nSheridan, Missouri\r\n799\r\nSkidmore, Missouri\r\n928\r\nSlater, Missouri\r\n529\r\nSmithton, Missouri\r\n343\r\nSmithville, Missouri\r\n873\r\n532\r\nSouth Davis City, Missouri\r\n735\r\nSouth Hamburg, Missouri\r\n389\r\nSouth Kansas City, Missouri\r\n672\r\n761\r\n763\r\n765\r\n767\r\n941\r\n942\r\n943\r\n966\r\nSouth Lineville, Missouri\r\n875\r\nSouth Redding, Missouri\r\n372\r\nSouth Seymour, Missouri\r\n399\r\nSouth Braddyville, Missouri\r\n581\r\nSpeed, Missouri\r\n838\r\nSpeedway, Missouri\r\n661\r\nSpickard, Missouri\r\n485\r\nSaint Joseph, Missouri\r\n390\r\n396\r\n671\r\n232\r\n233\r\n238\r\n271\r\n279\r\n351\r\n364\r\n387\r\nStanberry, Missouri\r\n783\r\nSteffenville, Missouri\r\n278\r\nStet, Missouri\r\n484\r\n655\r\nStewartsville, Missouri\r\n669\r\nStrasburg, Missouri\r\n865\r\nSumner, Missouri\r\n856\r\nSweet Springs, Missouri\r\n335\r\nSyracuse, Missouri\r\n298\r\nTarkio, Missouri\r\n736\r\nTiffany Springs, Missouri\r\n880\r\n891\r\nTina, Missouri\r\n622\r\nTipton, Missouri\r\n433\r\nTobin Creek, Missouri\r\n883\r\nTrenton, Missouri\r\n359\r\nTrimble, Missouri\r\n357\r\nTriplett, Missouri\r\n634\r\nTurney, Missouri\r\n664\r\nUnion Star, Missouri\r\n593\r\nUnionville, Missouri\r\n947\r\nUrich, Missouri\r\n638\r\nWalnut Hill, Missouri\r\n620\r\nWarrensburg, Missouri\r\n543\r\n429\r\n747\r\nWarsaw, Missouri\r\n438\r\nWatson, Missouri\r\n993\r\nWaverly, Missouri\r\n493\r\nWayland, Missouri\r\n754\r\nWellington, Missouri\r\n934\r\nWestboro, Missouri\r\n984\r\nWeston, Missouri\r\n386\r\nWestville, Missouri\r\n375\r\nWheeling, Missouri\r\n659\r\nWhitesville, Missouri\r\n526\r\nWindsor, Missouri\r\n647\r\nWinigan, Missouri\r\n857\r\nWinston, Missouri\r\n749\r\nWooldridge, Missouri\r\n839\r\nWashington Center, Missouri\r\n845\r\nWyaconda, Missouri\r\n479\r\n\u00035Unknown prefix code (816) - Missouri\r\n"
  },
  {
    "path": "install/regions/regions.817",
    "content": "Acton, Texas\r\n326\r\nAledo, Texas\r\n441\r\nAlexander, Texas\r\n764\r\nAlvarado, Texas\r\n783\r\n790\r\nAlvord, Texas\r\n427\r\nArcher City, Texas\r\n574\r\nArgyle, Texas\r\n240\r\n464\r\nArlington, Texas\r\n233\r\n276\r\n368\r\n462\r\n521\r\n557\r\n261\r\n265\r\n273\r\n356\r\n366\r\n425\r\n432\r\n449\r\n452\r\n461\r\n467\r\n469\r\n493\r\n499\r\n543\r\n588\r\n640\r\n652\r\n667\r\n671\r\n679\r\n695\r\n792\r\n794\r\n856\r\n274\r\n275\r\n277\r\n459\r\n460\r\n465\r\n468\r\n472\r\n548\r\n633\r\n649\r\n784\r\n795\r\n860\r\n861\r\n998\r\n226\r\n239\r\n331\r\n376\r\n434\r\n436\r\n450\r\n530\r\n620\r\n621\r\n630\r\n821\r\n824\r\n827\r\n828\r\n832\r\n843\r\n946\r\nAspermont, Texas\r\n989\r\nAubrey, Texas\r\n365\r\n440\r\nAxtell, Texas\r\n863\r\nAzle, Texas\r\n444\r\nBartlett, Texas\r\n527\r\nBartonville, Texas\r\n241\r\n455\r\nBellevue, Texas\r\n928\r\nBelton, Texas\r\n933\r\n939\r\nBen Hur, Texas\r\n789\r\nBenbrook, Texas\r\n249\r\nBenjamin, Texas\r\n454\r\nBlue Grove, Texas\r\n895\r\nBluffdale, Texas\r\n728\r\nBlum, Texas\r\n874\r\nBonita, Texas\r\n987\r\nBoonsville, Texas\r\n748\r\nBowie, Texas\r\n872\r\nBoyd, Texas\r\n433\r\nBrandon, Texas\r\n632\r\nBreckenridge, Texas\r\n559\r\nBremond, Texas\r\n746\r\nBridgeport, Texas\r\n683\r\nBryson, Texas\r\n392\r\nBuckholts, Texas\r\n593\r\nBurkburnet, Texas\r\n569\r\nBurleson, Texas\r\n295\r\n447\r\nBurlington, Texas\r\n869\r\nBynum, Texas\r\n623\r\nCameron, Texas\r\n697\r\nCarbon, Texas\r\n639\r\nCarlton, Texas\r\n785\r\nCee Vee, Texas\r\n585\r\nCharlie, Texas\r\n544\r\nChicago, Texas\r\n644\r\nChildress, Texas\r\n937\r\nChillicoth, Texas\r\n852\r\nChilton, Texas\r\n546\r\nChina Spring, Texas\r\n836\r\nCisco, Texas\r\n442\r\nCleburne, Texas\r\n556\r\n641\r\n645\r\n558\r\nClifton, Texas\r\n675\r\nCoolidge, Texas\r\n786\r\nCopperascv, Texas\r\n542\r\n547\r\nCovington, Texas\r\n854\r\nCranfils Gap, Texas\r\n597\r\nCrawford, Texas\r\n486\r\nCresson, Texas\r\n396\r\nCross Pls, Texas\r\n725\r\nCrowell, Texas\r\n684\r\nCrowley, Texas\r\n297\r\nDawson, Texas\r\n578\r\nDe Leon, Texas\r\n893\r\nDecatur, Texas\r\n627\r\nDenton, Texas\r\n243\r\n349\r\n369\r\n380\r\n391\r\n484\r\n591\r\n891\r\n381\r\n382\r\n383\r\n387\r\n565\r\n566\r\n788\r\n898\r\nDesdemona, Texas\r\n758\r\nDonie, Texas\r\n359\r\nDublin, Texas\r\n445\r\nEastland, Texas\r\n629\r\nEddy, Texas\r\n859\r\nEdgecliff, Texas\r\n293\r\n551\r\n568\r\nElbert, Texas\r\n862\r\nElectra, Texas\r\n495\r\nEliasville, Texas\r\n362\r\nEuless, Texas\r\n948\r\n285\r\n931\r\n952\r\n956\r\n267\r\n268\r\n280\r\n282\r\n283\r\n354\r\n355\r\n540\r\n545\r\n571\r\n685\r\n858\r\n868\r\n963\r\n967\r\nEvant, Texas\r\n471\r\nFlat, Texas\r\n487\r\nFlorence, Texas\r\n793\r\nForestburg, Texas\r\n964\r\nFort Hood, Texas\r\n287\r\n288\r\n532\r\nFort Worth, Texas\r\n284\r\n332\r\n333\r\n334\r\n335\r\n336\r\n338\r\n339\r\n347\r\n370\r\n377\r\n390\r\n429\r\n451\r\n457\r\n496\r\n531\r\n534\r\n535\r\n536\r\n590\r\n595\r\n624\r\n625\r\n626\r\n654\r\n731\r\n732\r\n735\r\n737\r\n738\r\n740\r\n762\r\n763\r\n777\r\n782\r\n787\r\n831\r\n834\r\n838\r\n844\r\n870\r\n871\r\n877\r\n878\r\n882\r\n884\r\n885\r\n892\r\n921\r\n922\r\n923\r\n924\r\n925\r\n926\r\n927\r\n930\r\n981\r\n991\r\n992\r\n994\r\n996\r\n446\r\n475\r\n929\r\n999\r\n292\r\n294\r\n346\r\nGainesville, Texas\r\n665\r\n668\r\nGatesville, Texas\r\n865\r\nGholson, Texas\r\n829\r\nGlen Rose, Texas\r\n897\r\nGodley, Texas\r\n389\r\nGoodlett, Texas\r\n674\r\nGordon, Texas\r\n693\r\nGorman, Texas\r\n734\r\nGraford, Texas\r\n664\r\nGraham, Texas\r\n550\r\n549\r\nGranbury, Texas\r\n573\r\n579\r\nGrandview, Texas\r\n866\r\nGrapevine, Texas\r\n421\r\n488\r\n329\r\n424\r\n481\r\nGroesbeck, Texas\r\n729\r\nHallsburg, Texas\r\n875\r\nHamilton, Texas\r\n386\r\nHaskell, Texas\r\n864\r\nHaslet, Texas\r\n439\r\nHeidenhimr, Texas\r\n983\r\nHenrietta, Texas\r\n538\r\nHico, Texas\r\n796\r\nHillsboro, Texas\r\n580\r\n582\r\nHolland, Texas\r\n657\r\nHolliday, Texas\r\n586\r\nHubbard, Texas\r\n576\r\nHurst, Texas\r\n589\r\nIowa Park, Texas\r\n592\r\nIredell, Texas\r\n364\r\nIrene, Texas\r\n678\r\nItasca, Texas\r\n687\r\nJacksboro, Texas\r\n567\r\nJermyn, Texas\r\n342\r\nJonesboro, Texas\r\n463\r\nJoplin, Texas\r\n374\r\nJoy, Texas\r\n476\r\nJustin, Texas\r\n242\r\n648\r\nKamay, Texas\r\n438\r\nKeller, Texas\r\n379\r\n431\r\n581\r\nKennedale, Texas\r\n478\r\n483\r\n561\r\n572\r\nKilleen, Texas\r\n289\r\n290\r\n520\r\n680\r\n286\r\n526\r\n539\r\n554\r\n628\r\n634\r\n690\r\n699\r\nKirkland, Texas\r\n537\r\nKnox City, Texas\r\n658\r\nKopperl, Texas\r\n889\r\nKosse, Texas\r\n375\r\nKrum, Texas\r\n482\r\nLake Kemp, Texas\r\n357\r\nLake Worth, Texas\r\n236\r\n237\r\n238\r\n489\r\nLakeside Village, Texas\r\n775\r\nLeroy, Texas\r\n822\r\nLipan, Texas\r\n646\r\nLittle River, Texas\r\n982\r\nLake Arrowhead, Texas\r\n528\r\nLake Kickapo, Texas\r\n525\r\nLake Whitney, Texas\r\n622\r\nLake Dallas, Texas\r\n321\r\n497\r\nLorena, Texas\r\n857\r\nLott, Texas\r\n584\r\nLoving, Texas\r\n378\r\nMalone, Texas\r\n533\r\nMansfield, Texas\r\n955\r\n473\r\n477\r\nMarlin, Texas\r\n883\r\nMart, Texas\r\n876\r\nMay, Texas\r\n259\r\nMcGregor, Texas\r\n840\r\nMedcine Mound, Texas\r\n839\r\nMegargel, Texas\r\n563\r\nMeridian, Texas\r\n435\r\nMexia, Texas\r\n747\r\n562\r\nMillsap, Texas\r\n682\r\nMineral Wells, Texas\r\n325\r\n328\r\nMoffat, Texas\r\n986\r\nMontague, Texas\r\n894\r\nMoody, Texas\r\n853\r\nMorgan, Texas\r\n635\r\nMosheim, Texas\r\n945\r\nMount Calm, Texas\r\n993\r\nMuenster, Texas\r\n759\r\nMunday, Texas\r\n422\r\nMyra, Texas\r\n727\r\n736\r\nNorth Richills, Texas\r\n498\r\n577\r\nNewcastle, Texas\r\n846\r\nNocona, Texas\r\n825\r\nNolanville, Texas\r\n698\r\nNorichldhale, Texas\r\n281\r\n428\r\n485\r\n656\r\nOenaville, Texas\r\n984\r\nOglesby, Texas\r\n456\r\nOklaunion, Texas\r\n886\r\nOlden, Texas\r\n653\r\nOlney, Texas\r\n564\r\nOrth, Texas\r\n873\r\nPalo Pinto, Texas\r\n659\r\nPaluxy, Texas\r\n823\r\nParadise, Texas\r\n969\r\nPerrin, Texas\r\n798\r\nPetrolia, Texas\r\n524\r\n529\r\nPilot Point, Texas\r\n686\r\nPonder, Texas\r\n479\r\nPosmkgdmlk, Texas\r\n779\r\nPottsville, Texas\r\n372\r\nPrairie Hill, Texas\r\n344\r\nProctor, Texas\r\n879\r\nQuanah, Texas\r\n663\r\nRanger, Texas\r\n647\r\nReagan, Texas\r\n587\r\nReno, Texas\r\n221\r\n677\r\nRhome, Texas\r\n638\r\n636\r\nRiesel, Texas\r\n896\r\nRinggold, Texas\r\n934\r\nRio Vista, Texas\r\n373\r\nRising Star, Texas\r\n643\r\nRoanoke, Texas\r\n837\r\n224\r\n430\r\n890\r\n961\r\n962\r\n491\r\nRochester, Texas\r\n743\r\nRogers, Texas\r\n642\r\nRosebud, Texas\r\n583\r\nRosenthal, Texas\r\n881\r\nRosston, Texas\r\n768\r\nRule, Texas\r\n997\r\nRunaway Bay, Texas\r\n575\r\nSaginaw, Texas\r\n234\r\n232\r\n847\r\nSalado, Texas\r\n947\r\nSandy, Texas\r\n353\r\nSanger, Texas\r\n458\r\nSanto, Texas\r\n769\r\nScotland, Texas\r\n541\r\nSeymour, Texas\r\n888\r\nSidney, Texas\r\n842\r\nSilver Creek, Texas\r\n448\r\nSlidell, Texas\r\n466\r\nSouth Bosque, Texas\r\n848\r\nSpanish Fort, Texas\r\n966\r\nSpringtown, Texas\r\n220\r\n523\r\nSaint Jo, Texas\r\n995\r\nStephenville, Texas\r\n977\r\n965\r\n968\r\nStrawn, Texas\r\n672\r\nSunset, Texas\r\n845\r\nTeague, Texas\r\n739\r\nTehuacana, Texas\r\n395\r\nTemple, Texas\r\n724\r\n742\r\n760\r\n770\r\n771\r\n773\r\n774\r\n778\r\n780\r\n899\r\nThalia, Texas\r\n655\r\nThornton, Texas\r\n385\r\nThrockmrtn, Texas\r\n849\r\nTioga, Texas\r\n437\r\nTolar, Texas\r\n835\r\nTroy, Texas\r\n938\r\nTruscott, Texas\r\n474\r\nTurnersville, Texas\r\n494\r\nValley Mills, Texas\r\n932\r\nValley View, Texas\r\n637\r\n726\r\nVernon, Texas\r\n552\r\n553\r\nWaco, Texas\r\n741\r\n745\r\n954\r\n990\r\n388\r\n662\r\n666\r\n744\r\n749\r\n750\r\n751\r\n752\r\n753\r\n754\r\n755\r\n756\r\n757\r\n772\r\n776\r\n799\r\n867\r\nWalnut Springs, Texas\r\n797\r\nWeatherford, Texas\r\n594\r\n598\r\n599\r\n596\r\nWedgewood, Texas\r\n263\r\nWeinert, Texas\r\n673\r\nWest, Texas\r\n826\r\nWestland, Texas\r\n244\r\n560\r\nWheatland, Texas\r\n443\r\nWhitecyodl, Texas\r\n887\r\nWhitney, Texas\r\n694\r\nWhite Settlement, Texas\r\n246\r\n367\r\n935\r\nWichita Falls, Texas\r\n320\r\n322\r\n330\r\n676\r\n689\r\n691\r\n692\r\n696\r\n720\r\n722\r\n723\r\n733\r\n761\r\n766\r\n767\r\n781\r\n851\r\n855\r\n880\r\nWindthorst, Texas\r\n423\r\nWoodson, Texas\r\n345\r\nWortham, Texas\r\n765\r\nZabcikville, Texas\r\n985\r\n\u00035Unknown prefix code (817) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.818",
    "content": "Agoura, California\r\n865\r\n879\r\n597\r\n706\r\n707\r\n889\r\n991\r\nAlhambra, California\r\n212\r\n291\r\n292\r\n293\r\n312\r\n805\r\n280\r\n281\r\n282\r\n284\r\n285\r\n286\r\n287\r\n288\r\n289\r\n300\r\n302\r\n307\r\n308\r\n309\r\n457\r\n458\r\n529\r\n570\r\n571\r\n572\r\n573\r\n576\r\nArcadia, California\r\n445\r\n446\r\n447\r\n574\r\n821\r\nAzusa-Glendale, California\r\n334\r\n335\r\n812\r\n815\r\n852\r\n857\r\n914\r\n963\r\n969\r\nBurbank, California\r\n556\r\n557\r\n558\r\n559\r\n562\r\n771\r\n973\r\n560\r\n563\r\n565\r\n566\r\n567\r\n569\r\n840\r\n841\r\n842\r\n843\r\n845\r\n846\r\n847\r\n848\r\n953\r\n954\r\n955\r\n972\r\nCanoga Park, California\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n313\r\n340\r\n341\r\n346\r\n347\r\n348\r\n407\r\n586\r\n587\r\n591\r\n592\r\n593\r\n594\r\n595\r\n596\r\n610\r\n700\r\n702\r\n703\r\n704\r\n709\r\n710\r\n712\r\n713\r\n715\r\n716\r\n718\r\n719\r\n773\r\n876\r\n878\r\n880\r\n882\r\n883\r\n884\r\n887\r\n888\r\n992\r\n998\r\n999\r\nCovina-Baldwin Park, California\r\n850\r\n851\r\n859\r\n931\r\n934\r\nCovina Baldwin, California\r\n331\r\n332\r\n337\r\n338\r\n339\r\n813\r\n814\r\n856\r\n858\r\n915\r\n916\r\n917\r\n918\r\n919\r\n960\r\n962\r\n966\r\n967\r\nEl Monte, California\r\n279\r\n453\r\n350\r\n401\r\n402\r\n442\r\n443\r\n444\r\n448\r\n450\r\n452\r\n459\r\n575\r\n579\r\n580\r\nGlendale, California\r\n543\r\n544\r\n549\r\n551\r\n552\r\n240\r\n241\r\n242\r\n243\r\n244\r\n246\r\n247\r\n409\r\n500\r\n502\r\n507\r\n545\r\n546\r\n547\r\n548\r\n956\r\nGlendora, California\r\n454\r\nGranada Hills, California\r\n832\r\nHollywood, California\r\n503\r\n505\r\n506\r\n508\r\n509\r\n753\r\n754\r\n760\r\n761\r\n762\r\n763\r\n764\r\n765\r\n766\r\n769\r\n777\r\n980\r\n982\r\n985\r\nLa Crescenta, California\r\n248\r\n249\r\n542\r\n957\r\n541\r\nLa Puente, California\r\n933\r\n935\r\n937\r\n330\r\n333\r\n336\r\n369\r\n810\r\n854\r\n855\r\n912\r\n913\r\n961\r\n964\r\n965\r\n968\r\nLos Angeles, California\r\n218\r\n421\r\n423\r\n424\r\n510\r\n512\r\n804\r\n853\r\n383\r\n520\r\nMonrovia, California\r\n305\r\n932\r\n301\r\n303\r\n357\r\n358\r\n359\r\nNorth Hollywood, California\r\n392\r\n622\r\n733\r\n752\r\n755\r\n759\r\nNorthridge, California\r\n725\r\n727\r\nPacoima, California\r\n834\r\nPasadena, California\r\n304\r\n354\r\n356\r\n393\r\n397\r\n398\r\n400\r\n403\r\n405\r\n406\r\n440\r\n441\r\n449\r\n564\r\n568\r\n577\r\n578\r\n584\r\n790\r\n791\r\n792\r\n793\r\n794\r\n795\r\n796\r\n797\r\n798\r\n799\r\n844\r\n952\r\n395\r\n396\r\n585\r\n666\r\n683\r\n949\r\nReseda, California\r\n757\r\n758\r\n776\r\n342\r\n343\r\n344\r\n345\r\n349\r\n609\r\n701\r\n705\r\n708\r\n717\r\n772\r\n774\r\n775\r\n881\r\n885\r\n886\r\n993\r\n996\r\nSan Fernando, California\r\n837\r\n360\r\n361\r\n362\r\n363\r\n364\r\n365\r\n366\r\n367\r\n368\r\n830\r\n831\r\n890\r\n891\r\n892\r\n893\r\n894\r\n895\r\n896\r\n897\r\n898\r\n899\r\nSan Gabrielle, California\r\n910\r\nSierra Madre, California\r\n306\r\n351\r\n355\r\n836\r\nSun Valley, California\r\n394\r\n504\r\n767\r\n768\r\nSunldtujunga, California\r\n352\r\n353\r\n951\r\nTemple City, California\r\n451\r\nVan Nuys, California\r\n219\r\n370\r\n380\r\n384\r\n385\r\n386\r\n410\r\n412\r\n413\r\n414\r\n416\r\n417\r\n418\r\n419\r\n420\r\n422\r\n425\r\n426\r\n513\r\n514\r\n561\r\n602\r\n603\r\n604\r\n605\r\n606\r\n607\r\n608\r\n612\r\n778\r\n779\r\n801\r\n802\r\n803\r\n807\r\n816\r\n818\r\n819\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n381\r\n382\r\n399\r\n404\r\n501\r\n528\r\n601\r\n780\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n787\r\n788\r\n789\r\n901\r\n902\r\n903\r\n904\r\n905\r\n906\r\n907\r\n908\r\n909\r\n981\r\n983\r\n984\r\n986\r\n987\r\n988\r\n989\r\n990\r\n994\r\n995\r\n997\r\n\u00035Unknown prefix code (818) - California\r\n"
  },
  {
    "path": "install/regions/regions.819",
    "content": "Akulivik, Quebec, Canada\r\n496\r\nAmos, Quebec, Canada\r\n727\r\n732\r\nAngliers, Quebec, Canada\r\n949\r\nArthabaska, Quebec, Canada\r\n357\r\nArtic Bay, Quebec, Canada\r\n439\r\nArundel, Quebec, Canada\r\n687\r\nAsbestos, Quebec, Canada\r\n879\r\nAston Junction, Quebec, Canada\r\n226\r\nAupaluk, Quebec, Canada\r\n491\r\nAyer's Cliff, Quebec, Canada\r\n838\r\nAylmer, Quebec, Canada\r\n682\r\n684\r\n685\r\nBaker Lake, Quebec, Canada\r\n793\r\nBarraute, Quebec, Canada\r\n734\r\nBearn, Quebec, Canada\r\n726\r\nBeaucanton, Quebec, Canada\r\n941\r\nBecancour, Quebec, Canada\r\n294\r\nBelleterre, Quebec, Canada\r\n722\r\nBishopton, Quebec, Canada\r\n884\r\nBouchette, Quebec, Canada\r\n465\r\nBromptonville, Quebec, Canada\r\n846\r\nBroug Island, Quebec, Canada\r\n927\r\nBuckingham, Quebec, Canada\r\n281\r\n986\r\nBury, Quebec, Canada\r\n872\r\nCadillac, Quebec, Canada\r\n759\r\nCampbells Bay, Quebec, Canada\r\n648\r\nCapdorst, Quebec, Canada\r\n897\r\nChamplain, Quebec, Canada\r\n295\r\nChapeau, Quebec, Canada\r\n689\r\nCharette, Quebec, Canada\r\n221\r\nChartierville, Quebec, Canada\r\n656\r\nChelsea, Quebec, Canada\r\n827\r\nCheneville, Quebec, Canada\r\n428\r\nChest Inlet, Quebec, Canada\r\n898\r\nChesterville, Quebec, Canada\r\n382\r\nChisasibi, Quebec, Canada\r\n855\r\nClericy, Quebec, Canada\r\n637\r\nClova, Quebec, Canada\r\n662\r\nClyde River, Quebec, Canada\r\n924\r\nCoaticook, Quebec, Canada\r\n849\r\nCompton, Quebec, Canada\r\n835\r\nCookshire, Quebec, Canada\r\n875\r\nCoral H, Quebec, Canada\r\n925\r\nDanville, Quebec, Canada\r\n839\r\nDaveluyville, Quebec, Canada\r\n367\r\nDeauville, Quebec, Canada\r\n864\r\nDeception B, Quebec, Canada\r\n982\r\nDeschailon, Quebec, Canada\r\n292\r\nDrummondville, Quebec, Canada\r\n472\r\n474\r\n475\r\n477\r\n478\r\nDubuisson, Quebec, Canada\r\n738\r\nDuparquet, Quebec, Canada\r\n948\r\nDupuy, Quebec, Canada\r\n783\r\nEast Hereford, Quebec, Canada\r\n844\r\nEast Angus, Quebec, Canada\r\n832\r\nEast Main, Quebec, Canada\r\n865\r\nEastmanville, Quebec, Canada\r\n977\r\nEskimo Point, Quebec, Canada\r\n857\r\nEvain, Quebec, Canada\r\n279\r\n768\r\nFabre, Quebec, Canada\r\n634\r\nFermeneuve, Quebec, Canada\r\n587\r\nFortierville, Quebec, Canada\r\n287\r\nFort Coulonge, Quebec, Canada\r\n683\r\nFugerville, Quebec, Canada\r\n748\r\nGatineau, Quebec, Canada\r\n643\r\n663\r\n669\r\nGentilly, Quebec, Canada\r\n298\r\nGracefield, Quebec, Canada\r\n463\r\nGrand Rem, Quebec, Canada\r\n438\r\nGrandmere, Quebec, Canada\r\n533\r\n538\r\nGrenville, Quebec, Canada\r\n242\r\nGrisefiord, Quebec, Canada\r\n980\r\nGuigues, Quebec, Canada\r\n728\r\nGuyenne, Quebec, Canada\r\n746\r\nHall Beach, Quebec, Canada\r\n928\r\nHam Nord, Quebec, Canada\r\n344\r\nHullottawa, Quebec, Canada\r\n246\r\n772\r\n773\r\n775\r\n779\r\n955\r\n995\r\n243\r\n561\r\n568\r\n595\r\n770\r\n771\r\n776\r\n777\r\n778\r\n790\r\n953\r\n956\r\n994\r\n997\r\nIgloolik, Quebec, Canada\r\n934\r\nInukjuak, Quebec, Canada\r\n254\r\nIqaluit, Quebec, Canada\r\n979\r\nIvujivik, Quebec, Canada\r\n922\r\nJoutel, Quebec, Canada\r\n756\r\nKangiqsual, Quebec, Canada\r\n337\r\n937\r\nKangiqsuju, Quebec, Canada\r\n338\r\n938\r\nKangirsuk, Quebec, Canada\r\n935\r\nKazabazua, Quebec, Canada\r\n467\r\nKingsey Falls, Quebec, Canada\r\n363\r\nKuujjuaq, Quebec, Canada\r\n964\r\nLa Corne, Quebec, Canada\r\n799\r\nLa Forge, Quebec, Canada\r\n853\r\nLa Minerve, Quebec, Canada\r\n274\r\nLa Prairie, Quebec, Canada\r\n888\r\nLa Reine, Quebec, Canada\r\n947\r\nLa Sarre, Quebec, Canada\r\n333\r\n339\r\nLa Tuque, Quebec, Canada\r\n523\r\n676\r\nLabelle, Quebec, Canada\r\n686\r\nLac-Drolet, Quebec, Canada\r\n549\r\n585\r\nLac Ducerf, Quebec, Canada\r\n597\r\nLac Edouar, Quebec, Canada\r\n653\r\nLac-Mgantic/Frontenac, Quebec, Canada\r\n583\r\nLa Grande, Quebec, Canada\r\n638\r\n672\r\n854\r\nLannoncatn, Quebec, Canada\r\n275\r\nLatulipe, Quebec, Canada\r\n747\r\nLaurierville, Quebec, Canada\r\n365\r\nLavenir, Quebec, Canada\r\n394\r\nLavlochre, Quebec, Canada\r\n765\r\nLeb Quevln, Quebec, Canada\r\n755\r\nLake Harbour, Quebec, Canada\r\n939\r\nLorrainville, Quebec, Canada\r\n625\r\nLouiseville, Quebec, Canada\r\n228\r\nLouvicourt, Quebec, Canada\r\n736\r\nLow, Quebec, Canada\r\n422\r\nLt Cnwls, Quebec, Canada\r\n253\r\nLuskville, Quebec, Canada\r\n455\r\nLyster, Quebec, Canada\r\n389\r\nMacamic, Quebec, Canada\r\n782\r\nMagog, Quebec, Canada\r\n843\r\n847\r\n868\r\nMalartic, Quebec, Canada\r\n757\r\nManiwaki, Quebec, Canada\r\n449\r\nManouane, Quebec, Canada\r\n971\r\nManseau, Quebec, Canada\r\n356\r\nMaskinonge, Quebec, Canada\r\n227\r\nMatagami, Quebec, Canada\r\n739\r\nMontebello, Quebec, Canada\r\n423\r\nMount Laurier, Quebec, Canada\r\n440\r\n623\r\nNanisivik, Quebec, Canada\r\n436\r\nNantes, Quebec, Canada\r\n547\r\nNd Bon, Quebec, Canada\r\n336\r\nNd Du, Quebec, Canada\r\n767\r\nNd La, Quebec, Canada\r\n522\r\nNd Lourdes, Quebec, Canada\r\n385\r\nNd Nord, Quebec, Canada\r\n723\r\nNd Salete, Quebec, Canada\r\n766\r\nNedelec, Quebec, Canada\r\n784\r\nNemaska, Quebec, Canada\r\n673\r\nNicolet, Quebec, Canada\r\n293\r\nNorth Hatley, Quebec, Canada\r\n842\r\nNominingue, Quebec, Canada\r\n278\r\nNoranda, Quebec, Canada\r\n762\r\n764\r\n797\r\nNorbertvil, Quebec, Canada\r\n369\r\nNormetal, Quebec, Canada\r\n788\r\nObedjiwan, Quebec, Canada\r\n974\r\nOtter Lake, Quebec, Canada\r\n453\r\nPalmarolle, Quebec, Canada\r\n787\r\nPangnirtng, Quebec, Canada\r\n473\r\nPapineauville, Quebec, Canada\r\n427\r\nParc Veren, Quebec, Canada\r\n435\r\nParent, Quebec, Canada\r\n667\r\nPerkins, Quebec, Canada\r\n671\r\nPlessisville, Quebec, Canada\r\n362\r\nPond Inlet, Quebec, Canada\r\n899\r\nPostebalin, Quebec, Canada\r\n929\r\nPovungntk, Quebec, Canada\r\n988\r\nPrinceville, Quebec, Canada\r\n364\r\nPurtuniq, Quebec, Canada\r\n984\r\nQuaqtaq, Quebec, Canada\r\n492\r\n932\r\nQuyon, Quebec, Canada\r\n458\r\nRadisson, Quebec, Canada\r\n866\r\nRankn Inlet, Quebec, Canada\r\n645\r\nRemigny, Quebec, Canada\r\n761\r\nRepulse Bay, Quebec, Canada\r\n462\r\nResolute, Quebec, Canada\r\n252\r\nRichmond, Quebec, Canada\r\n826\r\nRiv Heva, Quebec, Canada\r\n735\r\nRochebauct, Quebec, Canada\r\n754\r\nRock Island, Quebec, Canada\r\n876\r\nRollet, Quebec, Canada\r\n493\r\nSouth Durham, Quebec, Canada\r\n858\r\nSalluit, Quebec, Canada\r\n255\r\nSanikiluaq, Quebec, Canada\r\n266\r\nSanmaur, Quebec, Canada\r\n666\r\nSawyerville, Quebec, Canada\r\n889\r\nScotstown, Quebec, Canada\r\n657\r\nSenneterre, Quebec, Canada\r\n737\r\nShawinigan, Quebec, Canada\r\n536\r\n537\r\n539\r\nShawville, Quebec, Canada\r\n647\r\nSherbrooke, Quebec, Canada\r\n346\r\n620\r\n820\r\n829\r\n562\r\n563\r\n564\r\n565\r\n566\r\n567\r\n569\r\n821\r\n822\r\n823\r\nSaint Adolphe-de-Dudswell, Quebec, Canada\r\n327\r\n887\r\nSaint Agathe, Quebec, Canada\r\n324\r\n325\r\n326\r\nSaint Albert, Quebec, Canada\r\n353\r\nSaint Alex, Quebec, Canada\r\n265\r\nSaint Andre, Quebec, Canada\r\n983\r\nSaint Ang, Quebec, Canada\r\n222\r\nSaint Ann, Quebec, Canada\r\n586\r\nSaint Barnabe, Quebec, Canada\r\n264\r\nSaint Bonifice, Quebec, Canada\r\n535\r\nSaint Celestn, Quebec, Canada\r\n229\r\nSaint Cyr, Quebec, Canada\r\n397\r\nSaint Don, Quebec, Canada\r\n424\r\nSaint Emil, Quebec, Canada\r\n426\r\nSaint Eulalie, Quebec, Canada\r\n225\r\nSaint Faustin, Quebec, Canada\r\n688\r\nSaint Flix-de-Kingsey, Quebec, Canada\r\n848\r\nSaint Ger, Quebec, Canada\r\n395\r\nSaint Gertrude, Quebec, Canada\r\n297\r\nSaint Greg, Quebec, Canada\r\n233\r\nSaint Guillam, Quebec, Canada\r\n396\r\nSaint Jovite, Quebec, Canada\r\n425\r\nSaint Len, Quebec, Canada\r\n399\r\nSaint Ludger-de-Frontenac, Quebec, Canada\r\n548\r\nSaint Malo, Quebec, Canada\r\n658\r\nSaint Mathieu, Quebec, Canada\r\n532\r\nSaint Mon, Quebec, Canada\r\n289\r\nSaint Marie, Quebec, Canada\r\n283\r\nSaint Naza, Quebec, Canada\r\n392\r\nSaint Paulin, Quebec, Canada\r\n268\r\nSaint Pre, Quebec, Canada\r\n263\r\n457\r\nSaint Roch, Quebec, Canada\r\n646\r\nSaint Sebastien, Quebec, Canada\r\n652\r\nSaint Soph, Quebec, Canada\r\n288\r\nSaint Sylvere, Quebec, Canada\r\n285\r\nSaint Wenceslas, Quebec, Canada\r\n224\r\nSteug Guig, Quebec, Canada\r\n785\r\nStoke, Quebec, Canada\r\n878\r\nTaschereau, Quebec, Canada\r\n796\r\nTasiujaq, Quebec, Canada\r\n633\r\n933\r\nTemiscamng, Quebec, Canada\r\n627\r\nThurso, Quebec, Canada\r\n985\r\nTingwick, Quebec, Canada\r\n359\r\nTrois River, Quebec, Canada\r\n691\r\n693\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n379\r\n380\r\n991\r\nUmiujaq, Quebec, Canada\r\n331\r\nVal David, Quebec, Canada\r\n280\r\n824\r\n825\r\n874\r\n322\r\nValdesbois, Quebec, Canada\r\n454\r\nVictoriaville, Quebec, Canada\r\n751\r\n752\r\n758\r\nVillemarie, Quebec, Canada\r\n622\r\n629\r\nWakefield, Quebec, Canada\r\n456\r\n459\r\nWarwick, Quebec, Canada\r\n358\r\nWaskganish, Quebec, Canada\r\n895\r\nWaswanipi, Quebec, Canada\r\n753\r\nWaterville, Quebec, Canada\r\n837\r\nWeedon, Quebec, Canada\r\n877\r\nWemindji, Quebec, Canada\r\n978\r\nWhale Cove, Quebec, Canada\r\n896\r\nWickham, Quebec, Canada\r\n398\r\nWindsor, Quebec, Canada\r\n845\r\nWoburn, Quebec, Canada\r\n544\r\nWotton, Quebec, Canada\r\n828\r\nYamachiche, Quebec, Canada\r\n296\r\n\u00035Unknown prefix code (819) - Quebec, Canada\r\n"
  },
  {
    "path": "install/regions/regions.828",
    "content": "Andrews, North Carolina\r\n321\r\nArden, North Carolina\r\n674\r\n684\r\n687\r\nAsheville, North Carolina\r\n230\r\n231\r\n277\r\n240\r\n251\r\n252\r\n253\r\n254\r\n255\r\n257\r\n258\r\n259\r\n271\r\n274\r\n298\r\n299\r\n777\r\nBakersville, North Carolina\r\n688\r\nBalsam Grove, North Carolina\r\n655\r\nBanner Elk, North Carolina\r\n898\r\nBarnardsville, North Carolina\r\n626\r\nBeech Mountain, North Carolina\r\n387\r\nBethlehem, North Carolina\r\n495\r\nBlack Mountain, North Carolina\r\n669\r\nBlowing Rock, North Carolina\r\n295\r\nBoone, North Carolina\r\n262\r\n264\r\n265\r\n266\r\nBrevard, North Carolina\r\n862\r\n877\r\n883\r\n884\r\n885\r\n966\r\nBryson City, North Carolina\r\n488\r\nBurnsville, North Carolina\r\n682\r\nCanton, North Carolina\r\n235\r\n646\r\n648\r\nCaroleen, North Carolina\r\n657\r\nCashiers, North Carolina\r\n743\r\nCatawba, North Carolina\r\n241\r\nCherokee, North Carolina\r\n497\r\nClaremont, North Carolina\r\n459\r\nClyde, North Carolina\r\n627\r\nColumbus, North Carolina\r\n894\r\nCullowhee, North Carolina\r\n227\r\n293\r\nEllenboro, North Carolina\r\n410\r\n453\r\nEnkacandlr, North Carolina\r\n665\r\n667\r\nFairview, North Carolina\r\n628\r\nFontana Village, North Carolina\r\n498\r\nForest City, North Carolina\r\n223\r\n224\r\n245\r\n247\r\n248\r\nFranklin, North Carolina\r\n369\r\n524\r\nGarden City, North Carolina\r\n724\r\nGlenwood Prudence, North Carolina\r\n738\r\nGranite Falls, North Carolina\r\n313\r\n396\r\n493\r\n496\r\n499\r\nGreencreek, North Carolina\r\n863\r\nGuntertown, North Carolina\r\n656\r\nHayesville, North Carolina\r\n389\r\nHendersonville, North Carolina\r\n685\r\n692\r\n693\r\n696\r\n697\r\n891\r\nHickory, North Carolina\r\n234\r\n244\r\n256\r\n261\r\n267\r\n304\r\n310\r\n312\r\n314\r\n320\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n345\r\n381\r\n431\r\n441\r\n449\r\n612\r\n850\r\nHighlands, North Carolina\r\n526\r\nHildebran, North Carolina\r\n307\r\n397\r\nHot Springs, North Carolina\r\n622\r\nLake Lure, North Carolina\r\n625\r\nLeicester, North Carolina\r\n683\r\nLenoir, North Carolina\r\n726\r\n728\r\n754\r\n757\r\n758\r\nLiberty, North Carolina\r\n494\r\nMaggie Valley, North Carolina\r\n926\r\nMaiden, North Carolina\r\n428\r\nMarion, North Carolina\r\n652\r\n659\r\nMars Hill, North Carolina\r\n689\r\nMarshall, North Carolina\r\n649\r\nMicaville, North Carolina\r\n675\r\nMorganton, North Carolina\r\n432\r\n433\r\n437\r\n438\r\n439\r\n584\r\nMountain View, North Carolina\r\n294\r\nMurphy, North Carolina\r\n837\r\nNewland, North Carolina\r\n733\r\nOld Fort, North Carolina\r\n668\r\nRobbinsville, North Carolina\r\n479\r\nRutherfordton, North Carolina\r\n286\r\n287\r\nSaluda, North Carolina\r\n749\r\nSevier, North Carolina\r\n756\r\nSherrills Ford, North Carolina\r\n478\r\nSpruce Pine, North Carolina\r\n765\r\nSugar Grove, North Carolina\r\n297\r\nSuit, North Carolina\r\n644\r\nSwannanoa, North Carolina\r\n686\r\nSylvia, North Carolina\r\n586\r\nTaylorsville, North Carolina\r\n632\r\n635\r\nTryon, North Carolina\r\n859\r\nValdese, North Carolina\r\n874\r\n879\r\n893\r\nWatauga, North Carolina\r\n963\r\nWaterville, North Carolina\r\n486\r\nWaynesville, North Carolina\r\n452\r\n456\r\nWeaverville, North Carolina\r\n645\r\n658\r\n\u00035Unknown prefix code (828) - North Carolina\u00030\r\n"
  },
  {
    "path": "install/regions/regions.858",
    "content": "Del Mar, California\n259\n481\n500\n755\n792\n793\n794\nLa Jolla, California\n270\n272\n273\n274\n404\n450\n452\n453\n454\n455\n456\n457\n458\n459\n483\n488\n490\n506\n508\n518\n534\n535\n539\n546\n550\n551\n552\n554\n558\n581\n587\n597\n622\n625\n657\n658\nLinda Vista, California\n268\n277\n278\n279\n292\n467\n492\n493\n494\n495\n496\n502\n541\n560\n565\n569\n571\n573\n576\n627\n637\n654\n694\n972\n974\nMira Mesa, California\n271\n530\n536\n537\n547\n549\n566\n578\n586\n621\n684\n689\n693\n695\nPoway, California\n486\n679\n748\nRancho Bernardo, California\n451\n485\n487\n592\n604\n673\n674\n675\nRancho Penasquitos, California\n484\n538\n672\nRancho Santa Fe, California\n513\n756\n759\n\u00035Unknown prefix code (858) - California\n"
  },
  {
    "path": "install/regions/regions.886",
    "content": "Taipei\r\n127\r\n\u00035Unknown prefix code (886) - Taipei\r\n"
  },
  {
    "path": "install/regions/regions.900",
    "content": "\u00032Anywhere--Pay Per Call\u00030\r\n900\r\n"
  },
  {
    "path": "install/regions/regions.901",
    "content": "Adamsville, Tennessee\r\n632\r\nAlamo, Tennessee\r\n696\r\nArlington, Tennessee\r\n867\r\nAtwood, Tennessee\r\n662\r\nBells, Tennessee\r\n663\r\nBethel Springs, Tennessee\r\n934\r\nBig Sandy, Tennessee\r\n593\r\nBolivar, Tennessee\r\n658\r\nBradford, Tennessee\r\n742\r\nBrazil, Tennessee\r\n559\r\nBrownsville, Tennessee\r\n772\r\nBruceton, Tennessee\r\n586\r\nCamden, Tennessee\r\n220\r\n584\r\nCedar Grove, Tennessee\r\n987\r\nCentnal Is, Tennessee\r\n567\r\nCollierville, Tennessee\r\n853\r\n854\r\nCottage Grove, Tennessee\r\n782\r\nCovington, Tennessee\r\n475\r\n476\r\nDecaturville, Tennessee\r\n852\r\nDresden, Tennessee\r\n364\r\nDrummonds, Tennessee\r\n835\r\nDyer, Tennessee\r\n692\r\nDyersburg, Tennessee\r\n285\r\n286\r\n287\r\nFriendship, Tennessee\r\n677\r\nGibson, Tennessee\r\n787\r\nGleason, Tennessee\r\n648\r\nGrand Junction, Tennessee\r\n764\r\nGreenfield, Tennessee\r\n235\r\nHalls, Tennessee\r\n836\r\nHenderson, Tennessee\r\n989\r\nHenning, Tennessee\r\n738\r\nHenry, Tennessee\r\n243\r\nHornbeak, Tennessee\r\n538\r\nHumboldt, Tennessee\r\n784\r\nHuntingdon, Tennessee\r\n986\r\nJackson, Tennessee\r\n225\r\n661\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n664\r\n668\r\n935\r\n988\r\nKenton, Tennessee\r\n749\r\nLa Grange, Tennessee\r\n878\r\nLatham, Tennessee\r\n799\r\nLexington, Tennessee\r\n967\r\n968\r\nMartin, Tennessee\r\n588\r\n587\r\nMason F, Tennessee\r\n594\r\nMason Hall, Tennessee\r\n673\r\nMason T, Tennessee\r\n294\r\nMaury City, Tennessee\r\n656\r\nMcKenzie, Tennessee\r\n352\r\nMiddleton, Tennessee\r\n222\r\n376\r\nMedina, Tennessee\r\n783\r\nMemphis, Tennessee\r\n227\r\n448\r\n481\r\n482\r\n484\r\n486\r\n487\r\n488\r\n489\r\n533\r\n544\r\n572\r\n759\r\n344\r\n654\r\n375\r\n541\r\n597\r\n371\r\n383\r\n387\r\n223\r\n226\r\n680\r\n224\r\n272\r\n274\r\n276\r\n278\r\n320\r\n323\r\n324\r\n325\r\n327\r\n332\r\n345\r\n346\r\n348\r\n353\r\n357\r\n358\r\n360\r\n362\r\n363\r\n365\r\n366\r\n367\r\n368\r\n369\r\n372\r\n373\r\n377\r\n382\r\n385\r\n386\r\n388\r\n395\r\n396\r\n397\r\n398\r\n452\r\n454\r\n458\r\n483\r\n485\r\n521\r\n522\r\n523\r\n524\r\n525\r\n526\r\n527\r\n528\r\n529\r\n531\r\n532\r\n535\r\n543\r\n575\r\n576\r\n577\r\n578\r\n579\r\n678\r\n681\r\n682\r\n683\r\n684\r\n685\r\n721\r\n722\r\n725\r\n726\r\n728\r\n729\r\n743\r\n744\r\n745\r\n747\r\n748\r\n753\r\n754\r\n755\r\n756\r\n757\r\n758\r\n761\r\n762\r\n763\r\n765\r\n766\r\n767\r\n774\r\n775\r\n785\r\n789\r\n794\r\n795\r\n797\r\n922\r\n942\r\n946\r\n947\r\n948\r\nMichie, Tennessee\r\n239\r\nMilan, Tennessee\r\n686\r\nMilledgeville, Tennessee\r\n687\r\n688\r\nMillington, Tennessee\r\n872\r\n873\r\nMoscow, Tennessee\r\n877\r\nMunford, Tennessee\r\n837\r\nNewbern, Tennessee\r\n627\r\nPalmersville, Tennessee\r\n822\r\nParis, Tennessee\r\n642\r\n644\r\nParsons, Tennessee\r\n845\r\n847\r\nPuryear, Tennessee\r\n232\r\n247\r\nRidgely, Tennessee\r\n264\r\nRipley, Tennessee\r\n221\r\n635\r\nRosemark, Tennessee\r\n829\r\nRutherford, Tennessee\r\n665\r\nSardis, Tennessee\r\n858\r\nSavannah, Tennessee\r\n925\r\nScottshill, Tennessee\r\n549\r\nSelmer, Tennessee\r\n645\r\nSharon, Tennessee\r\n456\r\nShelby Fork, Tennessee\r\n876\r\nShiloh, Tennessee\r\n689\r\nSidonia, Tennessee\r\n973\r\nSouth Fulton, Tennessee\r\n469\r\n479\r\nSomerville, Tennessee\r\n465\r\nSouth Hazel, Tennessee\r\n498\r\nStanton, Tennessee\r\n548\r\nTiptonville, Tennessee\r\n253\r\nTrenton, Tennessee\r\n855\r\nTrezevant, Tennessee\r\n669\r\nTrimble, Tennessee\r\n297\r\nTroy, Tennessee\r\n536\r\nUnion City, Tennessee\r\n884\r\n885\r\nWhiteville, Tennessee\r\n254\r\nYorkville, Tennessee\r\n643\r\n\u00035Unknown prefix code (901) - Tennessee\r\n"
  },
  {
    "path": "install/regions/regions.902",
    "content": "Advocate, Nova Scotia\r\n392\r\nAlberton, Nova Scotia\r\n853\r\nAmherst, Nova Scotia\r\n661\r\n664\r\n667\r\nAnnaplsryl, Nova Scotia\r\n532\r\nAntigonish, Nova Scotia\r\n863\r\n867\r\nArgyle, Nova Scotia\r\n643\r\nArichat, Nova Scotia\r\n226\r\nAylesford, Nova Scotia\r\n847\r\nBaddeck, Nova Scotia\r\n295\r\nBarrington, Nova Scotia\r\n637\r\nBass River, Nova Scotia\r\n647\r\nBear River, Nova Scotia\r\n467\r\n638\r\nBedeque, Nova Scotia\r\n887\r\nBerwick, Nova Scotia\r\n538\r\nBlandford, Nova Scotia\r\n228\r\nBoisdale, Nova Scotia\r\n871\r\nBorden, Nova Scotia\r\n855\r\nBoulardere, Nova Scotia\r\n674\r\nBridgetown, Nova Scotia\r\n665\r\nBridgewater, Nova Scotia\r\n527\r\n327\r\n543\r\nBrookfield, Nova Scotia\r\n673\r\nBrooklyn, Nova Scotia\r\n757\r\nCaledonia, Nova Scotia\r\n242\r\n682\r\nCanning, Nova Scotia\r\n582\r\nCanso, Nova Scotia\r\n366\r\nCardigan, Nova Scotia\r\n583\r\nCarleton, Nova Scotia\r\n761\r\nCharlottetown, Nova Scotia\r\n239\r\n368\r\n552\r\n556\r\n557\r\n566\r\n569\r\n628\r\n629\r\n892\r\n894\r\nChelsea, Nova Scotia\r\n685\r\nChester, Nova Scotia\r\n275\r\nCheticamp, Nova Scotia\r\n224\r\nCheverie, Nova Scotia\r\n633\r\nChezzetcok, Nova Scotia\r\n827\r\nClarkes Harbor, Nova Scotia\r\n745\r\nClarksville, Nova Scotia\r\n632\r\nCollingwd, Nova Scotia\r\n686\r\nCountry Harbor, Nova Scotia\r\n328\r\nCovehead, Nova Scotia\r\n672\r\nCrapaud, Nova Scotia\r\n658\r\nDebert, Nova Scotia\r\n662\r\nDigby, Nova Scotia\r\n245\r\nDingwall, Nova Scotia\r\n383\r\nEast Bay, Nova Scotia\r\n822\r\n828\r\nEcum Secum, Nova Scotia\r\n347\r\nEldon, Nova Scotia\r\n659\r\nElmsdale, Nova Scotia\r\n883\r\nEskasoni, Nova Scotia\r\n379\r\nFreeport, Nova Scotia\r\n839\r\nFrench Village, Nova Scotia\r\n823\r\nGabarus, Nova Scotia\r\n884\r\nGeorgetown, Nova Scotia\r\n652\r\nGlace Bay, Nova Scotia\r\n842\r\n849\r\nGoldboro, Nova Scotia\r\n387\r\nGoshen, Nova Scotia\r\n783\r\nGreat Village, Nova Scotia\r\n668\r\nGrand Narrows, Nova Scotia\r\n622\r\nGuysboroug, Nova Scotia\r\n533\r\nHalifax, Nova Scotia\r\n460\r\n461\r\n481\r\n496\r\n497\r\n498\r\n832\r\n981\r\n238\r\n267\r\n420\r\n421\r\n422\r\n423\r\n424\r\n425\r\n426\r\n427\r\n428\r\n429\r\n434\r\n435\r\n443\r\n445\r\n450\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n458\r\n459\r\n462\r\n463\r\n464\r\n465\r\n466\r\n468\r\n469\r\n475\r\n477\r\n479\r\n492\r\n493\r\n494\r\n551\r\n558\r\n559\r\n829\r\n835\r\n876\r\nHantsport, Nova Scotia\r\n684\r\nHeatherton, Nova Scotia\r\n386\r\nHopewell, Nova Scotia\r\n923\r\nHubbards, Nova Scotia\r\n857\r\nHunter River, Nova Scotia\r\n621\r\n964\r\nIngonish, Nova Scotia\r\n285\r\nInverness, Nova Scotia\r\n258\r\nIona      \r\n725\r\nKennetcook, Nova Scotia\r\n362\r\nKensington, Nova Scotia\r\n836\r\nKentville, Nova Scotia\r\n681\r\n678\r\n679\r\nKenzieville, Nova Scotia\r\n924\r\nKetch Harbor, Nova Scotia\r\n868\r\nKingston, Nova Scotia\r\n765\r\nLa Have, Nova Scotia\r\n688\r\nLardoise, Nova Scotia\r\n587\r\nLarrys River, Nova Scotia\r\n525\r\nLawrenceton, Nova Scotia\r\n584\r\nLiscombe, Nova Scotia\r\n779\r\nLiverpool, Nova Scotia\r\n646\r\n354\r\nLake Charlotte, Nova Scotia\r\n845\r\nLockeport, Nova Scotia\r\n656\r\nLouisbourg, Nova Scotia\r\n733\r\nLouisdale, Nova Scotia\r\n345\r\nLunenburg, Nova Scotia\r\n634\r\nMabou, Nova Scotia\r\n945\r\nMaccan, Nova Scotia\r\n545\r\nMahone Bay, Nova Scotia\r\n624\r\n627\r\nMaitland, Nova Scotia\r\n261\r\nMargare Harbor, Nova Scotia\r\n235\r\nMargrefrks, Nova Scotia\r\n248\r\nMarion Bdg, Nova Scotia\r\n727\r\nMelrose, Nova Scotia\r\n833\r\nMerigomish, Nova Scotia\r\n926\r\nMeteghan, Nova Scotia\r\n645\r\nMiddleton, Nova Scotia\r\n825\r\nMill Village, Nova Scotia\r\n677\r\nMonastery, Nova Scotia\r\n232\r\n234\r\nMontague, Nova Scotia\r\n838\r\n969\r\nMrl St, Nova Scotia\r\n961\r\nMount Stewart, Nova Scotia\r\n676\r\nMount Uniacke, Nova Scotia\r\n866\r\nMulgrave, Nova Scotia\r\n747\r\nMurray River, Nova Scotia\r\n962\r\nMusquodobt Harbor, Nova Scotia\r\n889\r\nMusquodobt, Nova Scotia\r\n384\r\nNorth Sydney, Nova Scotia\r\n544\r\n736\r\n794\r\nNeils Harbor, Nova Scotia\r\n336\r\nNew Haven, Nova Scotia\r\n675\r\nNew London, Nova Scotia\r\n886\r\nNew Ross, Nova Scotia\r\n689\r\nNew Germany, Nova Scotia\r\n644\r\nNew Glascow, Nova Scotia\r\n928\r\n396\r\n752\r\n755\r\nNew Waterfield, Nova Scotia\r\n592\r\n862\r\nNoel, Nova Scotia\r\n369\r\nOleary, Nova Scotia\r\n859\r\nOxford, Nova Scotia\r\n447\r\nParrsboro, Nova Scotia\r\n254\r\nPictou, Nova Scotia\r\n485\r\nPort Hood, Nova Scotia\r\n787\r\nPort Latour, Nova Scotia\r\n768\r\nPort Morien, Nova Scotia\r\n737\r\nPort Mouton, Nova Scotia\r\n683\r\nProspectrd, Nova Scotia\r\n852\r\nPort Bickerton, Nova Scotia\r\n364\r\nPort Dufferin, Nova Scotia\r\n654\r\nPort Greville, Nova Scotia\r\n348\r\nPort Hawkesby, Nova Scotia\r\n227\r\n625\r\nPort Maitland, Nova Scotia\r\n649\r\nPubnico, Nova Scotia\r\n762\r\nPugwash, Nova Scotia\r\n243\r\nQueensport, Nova Scotia\r\n358\r\nRiver Hebert, Nova Scotia\r\n251\r\nRiver John, Nova Scotia\r\n351\r\nRiverport, Nova Scotia\r\n766\r\nRusticoville, Nova Scotia\r\n963\r\nSouth Lake, Nova Scotia\r\n357\r\nSackville, Nova Scotia\r\n864\r\n865\r\nSalt Springs, Nova Scotia\r\n925\r\nSandy Cove, Nova Scotia\r\n834\r\nSaulnierville, Nova Scotia\r\n769\r\nSheet Harbor, Nova Scotia\r\n885\r\nShelburne, Nova Scotia\r\n875\r\nSherbrooke, Nova Scotia\r\n522\r\nShubenacde, Nova Scotia\r\n758\r\nSouris, Nova Scotia\r\n687\r\nSouthampton, Nova Scotia\r\n546\r\nSpringfield, Nova Scotia\r\n547\r\nSpringhill, Nova Scotia\r\n597\r\nSaint Anns, Nova Scotia\r\n929\r\nSaint Margarets, Nova Scotia\r\n826\r\nSaint Peters, Nova Scotia\r\n535\r\nStewiacke, Nova Scotia\r\n639\r\nSummerside, Nova Scotia\r\n436\r\n888\r\nSydney, Nova Scotia\r\n565\r\n567\r\n539\r\n562\r\n563\r\n564\r\n595\r\nTangier, Nova Scotia\r\n772\r\nTatmagoche, Nova Scotia\r\n657\r\nThorburn, Nova Scotia\r\n922\r\nTignish, Nova Scotia\r\n882\r\nTruro, Nova Scotia\r\n897\r\n893\r\n895\r\nTusket, Nova Scotia\r\n648\r\nTynevalley, Nova Scotia\r\n831\r\nUpper Stewick, Nova Scotia\r\n671\r\nUpper Musquodobt, Nova Scotia\r\n568\r\nVernon River, Nova Scotia\r\n651\r\nWallace, Nova Scotia\r\n257\r\nWalton, Nova Scotia\r\n528\r\nWaverley, Nova Scotia\r\n860\r\n861\r\n873\r\nWedgeport, Nova Scotia\r\n663\r\nWellington, Nova Scotia\r\n854\r\nWentworth, Nova Scotia\r\n548\r\nWeymouth, Nova Scotia\r\n837\r\nWhycocomgh, Nova Scotia\r\n756\r\nWindsor, Nova Scotia\r\n798\r\nWolfville, Nova Scotia\r\n542\r\nWoods Harbor, Nova Scotia\r\n723\r\nYarmouth, Nova Scotia\r\n749\r\n742\r\n\u00035Unknown prefix code (902) - Nova Scotia\r\n"
  },
  {
    "path": "install/regions/regions.903",
    "content": "Alba, Texas\r\n765\r\nAnnona, Texas\r\n697\r\nArp, Texas\r\n859\r\nAthens, Texas\r\n675\r\n676\r\n677\r\nAtlanta, Texas\r\n796\r\nAvery, Texas\r\n684\r\nAvinger, Texas\r\n562\r\nBagwell, Texas\r\n925\r\nBeckville, Texas\r\n678\r\nBellsavoy, Texas\r\n965\r\nBen Franklin, Texas\r\n325\r\nBenwheeler, Texas\r\n833\r\nBettie, Texas\r\n762\r\nBig Sandy, Texas\r\n636\r\nBirthright, Texas\r\n945\r\nBloomburg, Texas\r\n728\r\nBlooming Grove, Texas\r\n695\r\nBlossom, Texas\r\n982\r\nBogata, Texas\r\n632\r\nBonham, Texas\r\n583\r\nBrashear, Texas\r\n582\r\nBrownsboro, Texas\r\n852\r\nBuffalo, Texas\r\n322\r\nBullard, Texas\r\n894\r\nCaddomills, Texas\r\n527\r\nCampbell, Texas\r\n862\r\nCanton, Texas\r\n567\r\nCarthage, Texas\r\n692\r\n693\r\n694\r\nCash, Texas\r\n883\r\nCayuga, Texas\r\n499\r\nCeleste, Texas\r\n568\r\nCenterville, Texas\r\n536\r\nChandler, Texas\r\n849\r\nClarksville, Texas\r\n427\r\nCollinsville, Texas\r\n429\r\nCommerce, Texas\r\n468\r\n886\r\nComo, Texas\r\n488\r\nCooper, Texas\r\n395\r\nCorsicana, Texas\r\n654\r\n872\r\n874\r\nCumby, Texas\r\n994\r\nCypres Springs, Texas\r\n860\r\nDaingerfield, Texas\r\n645\r\nDe Berry, Texas\r\n766\r\nDeadwood, Texas\r\n622\r\nDekalb, Texas\r\n667\r\nDenison, Texas\r\n415\r\n463\r\n465\r\nDeport, Texas\r\n652\r\nDetroit, Texas\r\n674\r\nDorchester, Texas\r\n476\r\nDouglassville, Texas\r\n846\r\nDry Creek, Texas\r\n850\r\n878\r\nEctor, Texas\r\n961\r\nEdgewood, Texas\r\n896\r\nElkhart, Texas\r\n764\r\nElysan Fields, Texas\r\n633\r\nEmhouse, Texas\r\n354\r\nEmory, Texas\r\n473\r\nEustace, Texas\r\n425\r\nFairfield, Texas\r\n388\r\n389\r\nFrankston, Texas\r\n876\r\nFrost, Texas\r\n682\r\nGary, Texas\r\n685\r\nGilmer, Texas\r\n843\r\nGladebrch, Texas\r\n588\r\nGladewater, Texas\r\n845\r\nGolden, Texas\r\n768\r\nGood Springs, Texas\r\n854\r\nGordonville, Texas\r\n523\r\nGrandsalne, Texas\r\n962\r\nGreenville, Texas\r\n408\r\n454\r\n455\r\n456\r\n457\r\n458\r\nGunter, Texas\r\n433\r\nHallsville, Texas\r\n660\r\n668\r\nHarleton, Texas\r\n777\r\nHawkins, Texas\r\n769\r\nHenderson, Texas\r\n649\r\n655\r\n657\r\n658\r\nHoney Grove, Texas\r\n378\r\nHooks, Texas\r\n547\r\nHowe, Texas\r\n532\r\nHudson, Texas\r\n743\r\nHughes Springs, Texas\r\n639\r\nJackson, Texas\r\n848\r\nJacksonville, Texas\r\n586\r\n589\r\nJefferson, Texas\r\n665\r\nJewett, Texas\r\n626\r\nJim Hogg, Texas\r\n967\r\nKarnack, Texas\r\n679\r\nKemp, Texas\r\n498\r\nKerens, Texas\r\n396\r\nKilgore, Texas\r\n983\r\n984\r\n985\r\n986\r\nKoon Kreek, Texas\r\n338\r\nLadonia, Texas\r\n367\r\nLaneville, Texas\r\n863\r\nLeona, Texas\r\n344\r\nLeonard, Texas\r\n587\r\nLinden, Texas\r\n756\r\nLindleswan, Texas\r\n881\r\n882\r\nLake Plstn, Texas\r\n825\r\nLone Oak, Texas\r\n662\r\nLone Star, Texas\r\n656\r\nLongview, Texas\r\n230\r\n232\r\n236\r\n237\r\n295\r\n297\r\n643\r\n663\r\n738\r\n753\r\n757\r\n758\r\n759\r\n844\r\n901\r\n921\r\n981\r\n990\r\n998\r\nMabank, Texas\r\n887\r\nMalakoff, Texas\r\n489\r\nMarquez, Texas\r\n529\r\nMarrietta, Texas\r\n835\r\nMarshall, Texas\r\n926\r\n927\r\n930\r\n935\r\n938\r\nMartins Mills, Texas\r\n479\r\nMaud, Texas\r\n585\r\nMaydelle, Texas\r\n795\r\nMerit, Texas\r\n776\r\nMiller Grove, Texas\r\n459\r\nMims, Texas\r\n755\r\nMinden, Texas\r\n898\r\nMineola, Texas\r\n569\r\nMontalba, Texas\r\n549\r\nMount Vernon, Texas\r\n537\r\nMount Enterprise, Texas\r\n822\r\nMount Pleasant, Texas\r\n572\r\n573\r\n577\r\nMurchison, Texas\r\n469\r\nMyrtle Springs, Texas\r\n865\r\nNaples, Texas\r\n897\r\nNeches, Texas\r\n584\r\nNegley, Texas\r\n966\r\nNew Boston, Texas\r\n628\r\nNew London, Texas\r\n895\r\nNew Summerfield, Texas\r\n726\r\nOak Hill, Texas\r\n836\r\nOakland, Texas\r\n829\r\nOakwood, Texas\r\n545\r\nOmaha, Texas\r\n884\r\nOre City, Texas\r\n968\r\nOverton, Texas\r\n834\r\nOwentown, Texas\r\n877\r\nPalestine, Texas\r\n729\r\n731\r\n723\r\nParis, Texas\r\n732\r\n737\r\n739\r\n784\r\n785\r\nPayne Springs, Texas\r\n451\r\nPecan Gap, Texas\r\n359\r\nPickton, Texas\r\n866\r\nPine Acres, Texas\r\n797\r\nPine Hill, Texas\r\n889\r\nPine Mills, Texas\r\n857\r\nPittsburg, Texas\r\n856\r\nPoint, Texas\r\n598\r\nPottsboro, Texas\r\n786\r\nPrice, Texas\r\n861\r\nPritchett, Texas\r\n734\r\nPurdon, Texas\r\n673\r\nQuinlan, Texas\r\n356\r\nQuitman, Texas\r\n763\r\nRed Springs, Texas\r\n858\r\nRedwater, Texas\r\n671\r\nRice, Texas\r\n326\r\nRichland, Texas\r\n362\r\nRoane, Texas\r\n345\r\nRosewood, Texas\r\n725\r\nRoxton, Texas\r\n346\r\nRusk, Texas\r\n683\r\nSandy Creek, Texas\r\n629\r\nSherley, Texas\r\n485\r\nSherman, Texas\r\n813\r\n814\r\n815\r\n867\r\n868\r\n870\r\n892\r\n893\r\nSimms, Texas\r\n543\r\nSlocum, Texas\r\n478\r\nStreetman, Texas\r\n599\r\nSulphur Springs, Texas\r\n439\r\n885\r\nTalco, Texas\r\n379\r\nTatum, Texas\r\n947\r\nTawakoni, Texas\r\n447\r\nTelephone, Texas\r\n664\r\nTenn Colny, Texas\r\n928\r\nTexarkana, Texas\r\n277\r\n334\r\n735\r\n792\r\n793\r\n794\r\n798\r\n826\r\n831\r\n832\r\n838\r\nTolsevn Point, Texas\r\n432\r\nTom Bean, Texas\r\n546\r\nTrenton, Texas\r\n989\r\nTrinidad, Texas\r\n778\r\nTroup, Texas\r\n842\r\nTucker, Texas\r\n538\r\nTurnertown, Texas\r\n847\r\nTyler, Texas\r\n505\r\n507\r\n509\r\n510\r\n530\r\n531\r\n533\r\n535\r\n561\r\n566\r\n571\r\n581\r\n592\r\n593\r\n595\r\n597\r\n534\r\nUncertain, Texas\r\n789\r\nVan, Texas\r\n963\r\nVanalstyne, Texas\r\n482\r\nVivian, Texas\r\n672\r\nWaskom, Texas\r\n687\r\nWeaver, Texas\r\n648\r\nWhitehouse, Texas\r\n839\r\nWhitesboro, Texas\r\n564\r\nWhitewright, Texas\r\n364\r\nWillspoint, Texas\r\n560\r\n873\r\nWindom, Texas\r\n623\r\nWinfield, Texas\r\n524\r\nWinnsboro, Texas\r\n342\r\nWolfe City, Texas\r\n496\r\nWynne, Texas\r\n365\r\nYantis, Texas\r\n383\r\n\u00035Unknown prefix code (903) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.904",
    "content": "Alachua, Florida\r\n462\r\nAlford, Florida\r\n579\r\nAligator Port, Florida\r\n349\r\nAltha, Florida\r\n762\r\nApalchicla, Florida\r\n653\r\nArcher, Florida\r\n495\r\nAstor, Florida\r\n759\r\nBaker, Florida\r\n537\r\nBaldwin, Florida\r\n266\r\nBelleview, Florida\r\n245\r\n347\r\nBeverly Hills, Florida\r\n527\r\n746\r\nBlountston, Florida\r\n674\r\nBonifay, Florida\r\n547\r\nBranford, Florida\r\n935\r\nBristol, Florida\r\n643\r\nBronson, Florida\r\n486\r\nBrooker, Florida\r\n485\r\nBrooksville, Florida\r\n754\r\n796\r\n799\r\n544\r\nBunnell, Florida\r\n586\r\n437\r\n568\r\n793\r\nCallahan, Florida\r\n879\r\nCantonment, Florida\r\n937\r\n968\r\nCarrabelle, Florida\r\n697\r\nCedar Keys, Florida\r\n543\r\nCentury, Florida\r\n256\r\nChatahoche, Florida\r\n662\r\n663\r\nCherry Lake, Florida\r\n929\r\nChiefland, Florida\r\n493\r\nChipley, Florida\r\n849\r\n638\r\nCitra, Florida\r\n595\r\nClermont, Florida\r\n242\r\n394\r\nCottondale, Florida\r\n352\r\nCrawfordville, Florida\r\n926\r\nCrescent City, Florida\r\n698\r\nCrestview, Florida\r\n682\r\n689\r\nCross City, Florida\r\n498\r\nCrystal River, Florida\r\n564\r\n563\r\n795\r\nDade City, Florida\r\n523\r\n524\r\n521\r\n567\r\nDavisville, Florida\r\n369\r\nDaytona Beach, Florida\r\n238\r\n239\r\n250\r\n252\r\n253\r\n254\r\n255\r\n257\r\n258\r\n274\r\n295\r\n299\r\n322\r\n441\r\n451\r\n672\r\n673\r\n676\r\n677\r\n691\r\n756\r\n760\r\n761\r\n767\r\n788\r\n869\r\n226\r\n248\r\n679\r\n831\r\n947\r\nDe Land, Florida\r\n734\r\n736\r\n738\r\n822\r\n943\r\nDefunak Spring, Florida\r\n951\r\n892\r\nDeleon Spring, Florida\r\n985\r\nDestin, Florida\r\n654\r\n837\r\nDunnellon, Florida\r\n465\r\n489\r\nEast Point, Florida\r\n670\r\n927\r\nEglin Air Force Base, Florida\r\n881\r\n882\r\n883\r\n884\r\n885\r\nEustis, Florida\r\n357\r\n483\r\n589\r\nFernandon Beach, Florida\r\n261\r\n277\r\n321\r\nFl Shf, Florida\r\n842\r\nFlagler Beach, Florida\r\n439\r\nFlorahome, Florida\r\n659\r\n661\r\nForest, Florida\r\n625\r\nFort White, Florida\r\n497\r\nFort George, Florida\r\n251\r\nFreeport, Florida\r\n835\r\nFort Walton Beach, Florida\r\n243\r\n244\r\n581\r\n582\r\n585\r\n664\r\n833\r\n862\r\n863\r\n864\r\n865\r\nGainesville, Florida\r\n846\r\n331\r\n332\r\n333\r\n334\r\n335\r\n336\r\n338\r\n339\r\n370\r\n371\r\n372\r\n373\r\n374\r\n375\r\n376\r\n377\r\n378\r\n392\r\n395\r\n491\r\n538\r\n665\r\nGlendale, Florida\r\n859\r\nGraceville, Florida\r\n263\r\nGrandridge, Florida\r\n592\r\nGreen Cove Spring, Florida\r\n284\r\nGreensboro, Florida\r\n442\r\nGreenville, Florida\r\n948\r\nGreenwood, Florida\r\n594\r\nGretna, Florida\r\n856\r\nGroveland, Florida\r\n429\r\nGulf Breeze, Florida\r\n932\r\n934\r\nHastings, Florida\r\n692\r\nHavana, Florida\r\n539\r\nHawthorne, Florida\r\n481\r\nHigh Springs, Florida\r\n454\r\nHilliard, Florida\r\n845\r\nHolleynvrr, Florida\r\n939\r\nHomos Spring, Florida\r\n382\r\n621\r\n628\r\nHosford, Florida\r\n379\r\nHoweyinhls, Florida\r\n324\r\nInterlachn, Florida\r\n684\r\nInverness, Florida\r\n860\r\n344\r\n637\r\n726\r\nJacksonville, Florida\r\n221\r\n223\r\n247\r\n260\r\n262\r\n268\r\n281\r\n292\r\n340\r\n346\r\n348\r\n350\r\n353\r\n354\r\n355\r\n356\r\n358\r\n359\r\n361\r\n363\r\n366\r\n367\r\n381\r\n384\r\n387\r\n388\r\n389\r\n390\r\n391\r\n393\r\n396\r\n398\r\n399\r\n443\r\n448\r\n459\r\n464\r\n565\r\n630\r\n631\r\n632\r\n633\r\n634\r\n635\r\n636\r\n641\r\n642\r\n645\r\n646\r\n655\r\n693\r\n695\r\n696\r\n720\r\n721\r\n723\r\n724\r\n725\r\n727\r\n730\r\n731\r\n733\r\n737\r\n739\r\n741\r\n743\r\n744\r\n745\r\n751\r\n757\r\n764\r\n765\r\n766\r\n768\r\n771\r\n772\r\n777\r\n778\r\n779\r\n781\r\n783\r\n786\r\n790\r\n791\r\n798\r\n828\r\n889\r\n967\r\n232\r\n279\r\n296\r\n499\r\n541\r\n549\r\n571\r\n573\r\n699\r\n858\r\n868\r\n876\r\n923\r\n924\r\n928\r\n945\r\n946\r\n952\r\n981\r\nJacksville Beach, Florida\r\n241\r\n246\r\n249\r\n270\r\nJasper, Florida\r\n792\r\nJay, Florida\r\n675\r\nJennings, Florida\r\n938\r\nJulington, Florida\r\n287\r\nKeaton Beach, Florida\r\n578\r\nKeyston Heights, Florida\r\n473\r\nKingsley Lake, Florida\r\n533\r\nLady Lake, Florida\r\n753\r\n821\r\n750\r\nLake City, Florida\r\n752\r\n755\r\n758\r\nLake Butler, Florida\r\n496\r\nLaurel Hill, Florida\r\n652\r\nLawtey, Florida\r\n782\r\nLee, Florida\r\n971\r\nLeesburg, Florida\r\n323\r\n360\r\n326\r\n365\r\n728\r\n787\r\nLive Oak, Florida\r\n362\r\n364\r\n658\r\nLuraville, Florida\r\n776\r\nLynn Haven, Florida\r\n265\r\n271\r\nMacClenny, Florida\r\n259\r\nMadison, Florida\r\n342\r\n973\r\nMalone, Florida\r\n569\r\nMandarin, Florida\r\n987\r\nMarianna, Florida\r\n577\r\n482\r\n526\r\nMaxville, Florida\r\n289\r\nMayo, Florida\r\n294\r\nMcIntosh, Florida\r\n591\r\nMelrose, Florida\r\n475\r\nMicanopy, Florida\r\n466\r\nMiddleburg, Florida\r\n282\r\n291\r\nMilton, Florida\r\n623\r\n626\r\nMolino, Florida\r\n587\r\nMonticello, Florida\r\n997\r\nMount Dora, Florida\r\n383\r\n735\r\nMunson, Florida\r\n957\r\nNewberry, Florida\r\n472\r\nNewsmrn Beach, Florida\r\n423\r\n424\r\n426\r\n427\r\n428\r\nOak Hill, Florida\r\n345\r\nOcala, Florida\r\n307\r\n620\r\n840\r\n895\r\n898\r\n236\r\n237\r\n351\r\n368\r\n622\r\n624\r\n629\r\n694\r\n732\r\n843\r\n854\r\n867\r\n873\r\nOklawaha, Florida\r\n288\r\nOld Town, Florida\r\n542\r\nOrange Spring, Florida\r\n546\r\nOrange City, Florida\r\n228\r\n532\r\n774\r\n775\r\n789\r\n851\r\nOrange Park, Florida\r\n213\r\n215\r\n264\r\n269\r\n272\r\n276\r\n278\r\nPace, Florida\r\n995\r\n994\r\nPalatka, Florida\r\n325\r\n328\r\n329\r\nPalm Coast, Florida\r\n445\r\n446\r\nPanacea, Florida\r\n984\r\nPanama City, Florida\r\n522\r\n747\r\n763\r\n769\r\n770\r\n784\r\n785\r\n832\r\n866\r\n871\r\n872\r\n874\r\nPanama City Beach, Florida\r\n230\r\n233\r\n234\r\n235\r\nPaxton, Florida\r\n834\r\nPenny Farms, Florida\r\n529\r\nPensacola, Florida\r\n293\r\n458\r\n839\r\n857\r\n887\r\n430\r\n432\r\n433\r\n434\r\n435\r\n436\r\n438\r\n444\r\n449\r\n452\r\n453\r\n455\r\n456\r\n457\r\n469\r\n474\r\n476\r\n477\r\n478\r\n479\r\n484\r\n492\r\n494\r\n572\r\n944\r\n982\r\nPerry, Florida\r\n838\r\n584\r\nPierson, Florida\r\n749\r\nPomona Park, Florida\r\n649\r\nPonce Deleon, Florida\r\n836\r\nPontvdr Beach, Florida\r\n273\r\n285\r\nPort Saint Joe, Florida\r\n227\r\n229\r\n827\r\nQuincy, Florida\r\n627\r\n875\r\nRaiford, Florida\r\n431\r\nReynolds Hill, Florida\r\n956\r\nSalt Springs, Florida\r\n685\r\nSan Antonio, Florida\r\n588\r\nSaint Anderson, Florida\r\n275\r\nSan Rosa Beach, Florida\r\n267\r\nSeagrove Beach, Florida\r\n231\r\nShalimar, Florida\r\n651\r\nSilver Springs Harbor, Florida\r\n680\r\n687\r\nSneads, Florida\r\n593\r\nSopchoppy, Florida\r\n962\r\nSaint Marks, Florida\r\n925\r\nSaint Augustine, Florida\r\n461\r\n471\r\n794\r\n797\r\n823\r\n824\r\n825\r\n826\r\n829\r\nStarke, Florida\r\n964\r\nSunny Hills, Florida\r\n773\r\nTallahasse, Florida\r\n222\r\n224\r\n298\r\n385\r\n386\r\n421\r\n422\r\n425\r\n487\r\n488\r\n531\r\n545\r\n561\r\n562\r\n566\r\n574\r\n575\r\n576\r\n599\r\n644\r\n656\r\n657\r\n668\r\n671\r\n681\r\n841\r\n847\r\n853\r\n877\r\n878\r\n891\r\n893\r\n894\r\n921\r\n922\r\n933\r\n942\r\nTavares, Florida\r\n343\r\n742\r\nThe Beaches, Florida\r\n647\r\n648\r\nTrenton, Florida\r\n463\r\nTrilacoche, Florida\r\n583\r\nTyndall Air Force Base, Florida\r\n283\r\n286\r\nUmatilla, Florida\r\n669\r\nValparaiso, Florida\r\n678\r\n729\r\n897\r\nVernon, Florida\r\n535\r\nWaldo, Florida\r\n468\r\nWalnut Hill, Florida\r\n327\r\nWelaka, Florida\r\n467\r\nWellborn, Florida\r\n963\r\nWestville, Florida\r\n548\r\nWewahtchka, Florida\r\n639\r\nWhite Springs, Florida\r\n397\r\nWildwood, Florida\r\n748\r\nWilliston, Florida\r\n528\r\nWkiwich Springs, Florida\r\n596\r\n597\r\n666\r\n683\r\n686\r\n688\r\nYankeetown, Florida\r\n447\r\nYoungstown Fountain, Florida\r\n722\r\nYulee, Florida\r\n225\r\n\u00035Unknown prefix code (904) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.905",
    "content": "Somewhere in Canada\r\n905\r\nBramalea, Ontario, Canada\r\n790\r\n793\r\n458\r\nBrampton, Ontario, Canada\r\n450\r\n451\r\n452\r\n454\r\n457\r\nNiagara Falls, Ontario, Canada\r\n702\r\nHeart Lake, Ontario, Canada\r\n840\r\nMississauga, Ontario, Canada\r\n272\r\n567\r\n820\r\n\u00035Unknown prefix code (905)\r\n"
  },
  {
    "path": "install/regions/regions.906",
    "content": "Alston, Michigan\r\n338\r\nAmasa, Michigan\r\n822\r\nAu Train, Michigan\r\n892\r\nBaraga, Michigan\r\n353\r\nBark River, Michigan\r\n466\r\nBay Mills, Michigan\r\n437\r\nBergland, Michigan\r\n575\r\nBessemer, Michigan\r\n663\r\n667\r\nBig Bay, Michigan\r\n345\r\nBrevort, Michigan\r\n292\r\nBrimley, Michigan\r\n248\r\nBrucecrsng, Michigan\r\n827\r\nCalumet, Michigan\r\n337\r\nCarney, Michigan\r\n639\r\nCedarville, Michigan\r\n484\r\nChampion, Michigan\r\n339\r\nChanning, Michigan\r\n542\r\nChatham, Michigan\r\n439\r\nCornell, Michigan\r\n384\r\nCrystal Falls, Michigan\r\n875\r\nCurtis, Michigan\r\n586\r\nDe Tour, Michigan\r\n297\r\nDeer Park, Michigan\r\n658\r\nDonken, Michigan\r\n288\r\nDrummondis, Michigan\r\n493\r\nEckerman, Michigan\r\n274\r\nEngadine, Michigan\r\n477\r\nEscanaba, Michigan\r\n786\r\n789\r\nEwen, Michigan\r\n988\r\nFaithorn, Michigan\r\n438\r\nFelch, Michigan\r\n246\r\nFence River, Michigan\r\n272\r\nGarden, Michigan\r\n644\r\nGladstone, Michigan\r\n420\r\n428\r\nGolden Lake, Michigan\r\n472\r\nGrand Maras, Michigan\r\n494\r\nGulliver, Michigan\r\n283\r\nGwinn, Michigan\r\n372\r\n346\r\nHermansville, Michigan\r\n498\r\nHiawth For, Michigan\r\n573\r\nHoughton, Michigan\r\n482\r\n487\r\n523\r\nHulbert, Michigan\r\n876\r\nIron Mountain, Michigan\r\n774\r\n779\r\nIron River, Michigan\r\n265\r\nIronwood, Michigan\r\n932\r\nIshpeming, Michigan\r\n485\r\n486\r\nKeweenaw, Michigan\r\n289\r\nKinross, Michigan\r\n495\r\nLake Linden, Michigan\r\n296\r\nLanse, Michigan\r\n524\r\nLake Gogebic, Michigan\r\n842\r\nMackinac Island, Michigan\r\n847\r\nManistique, Michigan\r\n341\r\nMarenisco, Michigan\r\n787\r\nMarquette, Michigan\r\n250\r\n360\r\n850\r\n222\r\n225\r\n226\r\n227\r\n228\r\n249\r\nMass, Michigan\r\n883\r\nMenominee, Michigan\r\n863\r\n864\r\nMichgm For, Michigan\r\n255\r\nMichigamme, Michigan\r\n323\r\nMunising, Michigan\r\n387\r\nNegaunee, Michigan\r\n475\r\nNewberry, Michigan\r\n293\r\nNorth Ld, Michigan\r\n544\r\nNorway, Michigan\r\n563\r\nOntonagon, Michigan\r\n884\r\nParadise, Michigan\r\n492\r\nPerkins, Michigan\r\n359\r\nPickford, Michigan\r\n647\r\nPowers, Michigan\r\n906\r\n497\r\nRapid River, Michigan\r\n474\r\nRepublic, Michigan\r\n376\r\nRexton, Michigan\r\n595\r\nRock, Michigan\r\n356\r\nRockland, Michigan\r\n886\r\nRudyard, Michigan\r\n478\r\nSand River, Michigan\r\n343\r\nScott Point, Michigan\r\n654\r\nSeney, Michigan\r\n499\r\nShingleton, Michigan\r\n452\r\nSkandia, Michigan\r\n942\r\nSltstmarie, Michigan\r\n440\r\n630\r\n632\r\n635\r\nSmokey Lake, Michigan\r\n548\r\nSaint Ignace, Michigan\r\n430\r\n643\r\nStephenson, Michigan\r\n753\r\nTapiola, Michigan\r\n334\r\nTrenary, Michigan\r\n446\r\nTrout Lake, Michigan\r\n569\r\nTrout Creek, Michigan\r\n852\r\nWakefield, Michigan\r\n224\r\n229\r\nWallace, Michigan\r\n788\r\nWatersmeet, Michigan\r\n358\r\nWatson, Michigan\r\n238\r\nWatton, Michigan\r\n355\r\nWhite Pine, Michigan\r\n885\r\n\u00035Unknown prefix code (906) - Michigan\r\n"
  },
  {
    "path": "install/regions/regions.907",
    "content": "Adak, Alaska\r\n855\r\n592\r\nAkhiok, Alaska\r\n836\r\nAkiachak, Alaska\r\n825\r\nAkiak, Alaska\r\n765\r\nAkutan, Alsaka\r\n698\r\nAlakanuk, Alaska\r\n238\r\nAlitak, Alaska\r\n371\r\nAllakaket, Alaska\r\n968\r\nAmbler, Alaska\r\n445\r\nAmchitka, Alaska\r\n751\r\nAnchorage, Alaska\r\n222\r\n229\r\n243\r\n244\r\n245\r\n248\r\n249\r\n257\r\n258\r\n261\r\n263\r\n264\r\n265\r\n266\r\n267\r\n268\r\n269\r\n271\r\n272\r\n273\r\n274\r\n275\r\n276\r\n277\r\n278\r\n279\r\n331\r\n333\r\n337\r\n338\r\n341\r\n342\r\n343\r\n344\r\n345\r\n346\r\n348\r\n349\r\n522\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\n754\r\n762\r\n786\r\n787\r\n887\r\n936\r\nAngoon, Alaska\r\n788\r\nAniak, Alaska\r\n675\r\nAnktuvk Ps, Alaska\r\n661\r\nAnnette, Alaska\r\n886\r\nAnvik, Alaska\r\n663\r\nArctic Village, Alaska\r\n587\r\nAtiguncamp, Alaska\r\n922\r\nAtka, Alaska\r\n839\r\nAtmautluak, Alaska\r\n553\r\nAtqasuk, Alaska\r\n633\r\nBarrow, Alaska\r\n852\r\nBeaver, Alaska\r\n628\r\nBethel, Alaska\r\n543\r\nBettles, Alaska\r\n692\r\nBig Lake, Alaska\r\n892\r\nBirch Creek, Alaska\r\n221\r\nBird Creek, Alaska\r\n653\r\nBlack Rapid Tr, Alaska\r\n871\r\nBorder City, Alaska\r\n774\r\nBuckland, Alaska\r\n494\r\nCabot, Alaska\r\n654\r\nCantwell, Alaska\r\n768\r\nCape Pole, Alaska\r\n879\r\nCentral, Alaska\r\n520\r\nChalkytsik, Alaska\r\n848\r\nChandalar, Alaska\r\n831\r\n838\r\nChefornak, Alaska\r\n867\r\nChenga Bay, Alaska\r\n573\r\nChevak, Alaska\r\n858\r\nChignik, Alaska\r\n749\r\nChignik Lake, Alaska\r\n845\r\nChignk Lag, Alaska\r\n840\r\nChitina, Alaska\r\n823\r\nChn Ht Spring, Alaska\r\n369\r\nChugiak, Alaska\r\n688\r\nChuthbaluk, Alaska\r\n467\r\nCircle, Alaska\r\n773\r\nClear Afs , Alaska\r\n582\r\n585\r\nClear Sumt, Alaska\r\n389\r\nCoffmancov, Alaska\r\n329\r\nCold Bay, Alaska\r\n532\r\n634\r\nColdbaymar, Alaska\r\n327\r\nColdfoot Camp, Alaska\r\n678\r\nCooper Lodge, Alaska\r\n595\r\nCordova, Alaska\r\n424\r\n635\r\nCouncil, Alaska\r\n665\r\nCp Spencer, Alaska\r\n326\r\nCplsbrnafs, Alaska\r\n725\r\nCraig, Alaska\r\n826\r\nCraig Mar , Alaska\r\n385\r\nCrdvamr 77, Alaska\r\n328\r\nCrok Creek, Alaska\r\n432\r\nCube Cove, Alaska\r\n799\r\nDeadhorse, Alaska\r\n659\r\nDeering, Alaska\r\n363\r\nDelta Jct, Alaska\r\n895\r\nDiamondridge, Alaska\r\n386\r\nDillingham, Alaska\r\n842\r\nDlngham Mar, Alaska\r\n387\r\nDot Lake, Alaska\r\n882\r\nDry Creek, Alaska\r\n323\r\nEagle, Alaska\r\n547\r\nEagle River, Alaska\r\n689\r\n694\r\n696\r\nEdna Bay, Alaska\r\n594\r\nEek, Alaska\r\n536\r\nEgegik, Alaska\r\n233\r\nEgegikmrnr, Alaska\r\n396\r\nEielson AFB, Alaska\r\n372\r\n377\r\nEkuk, Alaska\r\n236\r\nEkvik, Alaska\r\n769\r\nEkwok, Alaska\r\n464\r\nElfin Cove, Alaska\r\n239\r\nElim, Alaska\r\n890\r\nElmendorf AFB, Alaska\r\n552\r\n753\r\nEmer Rstl, Alaska\r\n521\r\nEmmonak, Alaska\r\n949\r\nEnglish Bay, Alaska\r\n281\r\nExcursion Inlet, Alaska\r\n866\r\nFairbanks, Alaska\r\n356\r\n388\r\n451\r\n452\r\n455\r\n456\r\n457\r\n458\r\n459\r\n474\r\n479\r\n888\r\nFt. Richardson, Alaska\r\n384\r\n428\r\nFalse Pass, Alaska\r\n548\r\nFort Yukon, Alaska\r\n662\r\nFort Greely, Alaska\r\n869\r\n873\r\nFreshwater Bay, Alaska\r\n924\r\nFt. Wainwright, Alaska\r\n353\r\nGalena AFS, Alaska\r\n446\r\n656\r\nGambell, Alaska\r\n985\r\nGirdwood, Alaska\r\n783\r\nGlennallen, Alaska\r\n822\r\nGolovin, Alaska\r\n779\r\nGoodnews B, Alaska\r\n967\r\nGrayling, Alaska\r\n453\r\nGustavus, Alaska\r\n697\r\nHaines, Alaska\r\n766\r\nHalbut Cove , Alaska\r\n296\r\nHealy, Alaska\r\n683\r\nHigh Mtn, Alaska\r\n395\r\nHobart Bay, Alaska\r\n673\r\nHollis, Alaska\r\n530\r\nHoly Cross, Alaska\r\n476\r\nHomer, Alaska\r\n235\r\nHoonah, Alaska\r\n945\r\nHooper Bay, Alaska\r\n758\r\nHope, Alaska\r\n782\r\nHughes, Alaska\r\n889\r\nHuslia, Alaska\r\n829\r\nHydaburg, Alaska\r\n285\r\nIgiugig, Alaska\r\n533\r\nIliamna, Alaska\r\n571\r\nInd Mt AFS, Alaska\r\n722\r\nIvanoff Bay, Alaska\r\n669\r\nJm River Camp, Alaska\r\n541\r\nJuneaumr 976, Alaska\r\n422\r\nJohnston Point, Alaska\r\n726\r\nJuneau, Alaska\r\n321\r\n364\r\n463\r\n465\r\n586\r\n667\r\n780\r\n789\r\n790\r\n793\r\nKake, Alaska\r\n785\r\nKakhonak, Alaska\r\n282\r\nKaktovik, Alaska\r\n640\r\nKalskag, Alaska\r\n471\r\nKaltag, Alaska\r\n534\r\nKarluk, Alaska\r\n241\r\nKasaan, Alaska\r\n542\r\nKasigluk, Alaska\r\n477\r\nKazakfbyville, Alaska\r\n381\r\nKazakofbay, Alaska\r\n379\r\nKenai, Alaska\r\n283\r\nKetchikan, Alaska\r\n225\r\n228\r\n247\r\n668\r\n856\r\nKetchikan Mr, Alaska\r\n423\r\nKg Slm AFS, Alaska\r\n721\r\nKiana, Alaska\r\n475\r\nKing Cove , Alaska\r\n497\r\nKing Salmon, Alaska\r\n246\r\n439\r\nKipnuk, Alaska\r\n896\r\nKivalina, Alaska\r\n645\r\nKlawock, Alaska\r\n755\r\nKlukwan, Alaska\r\n767\r\nKobuk, Alaska\r\n948\r\nKod Mar 78, Alaska\r\n433\r\nKodiak, Alaska\r\n486\r\n676\r\n857\r\nKodiakuscg, Alaska\r\n487\r\nKoliganek , Alaska\r\n596\r\nKongiganak, Alaska\r\n557\r\nKotlik, Alaska\r\n899\r\nKotzebue, Alaska\r\n442\r\nKoyuk, Alaska\r\n963\r\nKoyukuk, Alaska\r\n927\r\nKwethluk, Alaska\r\n757\r\nKwigilngok, Alaska\r\n588\r\nLarsen Bay, Alaska\r\n847\r\nLena Pt Mr, Alaska\r\n434\r\nLevelock, Alaska\r\n287\r\nLime Village, Alaska\r\n526\r\nLit Diomed, Alaska\r\n686\r\nLongisland, Alaska\r\n575\r\nMan Hot Springs, Alaska\r\n672\r\nManley Mar, Alaska\r\n435\r\nManokotak, Alaska\r\n289\r\nMarshall, Alaska\r\n679\r\nMcgrath, Alaska\r\n524\r\nMekoryuk , Alaska\r\n827\r\nMentasta, Alaska\r\n291\r\nMeshik, Alaska\r\n837\r\nMeyers Chk, Alaska\r\n569\r\n946\r\nMinchumina, Alaska\r\n674\r\n939\r\nMinto, Alaska\r\n798\r\nMontagueis, Alaska\r\n523\r\nMoosepass, Alaska\r\n288\r\nMurphydm AFS, Alaska\r\n744\r\nMtnvillage, Alaska\r\n591\r\nNorth Stuyahok, Alaska\r\n693\r\nNapakiak, Alaska\r\n589\r\nNapaskiak, Alaska\r\n737\r\nNaukiti, Alaska\r\n629\r\nNelson Lag, Alaska\r\n989\r\nNenana, Alaska\r\n832\r\nNewenhm AFS, Alaska\r\n794\r\nNewtok, Alaska\r\n237\r\nNightmute, Alaska\r\n647\r\nNikolai, Alaska\r\n293\r\nNikolski, Alaska\r\n576\r\nNikshk Mar, Alaska\r\n436\r\nNinilchik, Alaska\r\n567\r\nNoatak, Alaska\r\n485\r\nNome, Alaska\r\n443\r\n677\r\nNome Mr 73, Alaska\r\n461\r\nNondalton, Alaska\r\n294\r\nNoorvik, Alaska\r\n636\r\nNorth Kenai, Alaska\r\n776\r\nNorth Pole, Alaska\r\n322\r\n488\r\nNorthway, Alaska\r\n778\r\nNuiqsut, Alaska\r\n480\r\nNulato, Alaska\r\n898\r\nNunapitchk, Alaska\r\n527\r\nOld Harbor, Alaska\r\n286\r\nOliktok, Alaska\r\n791\r\nOuzinkie, Alaska\r\n680\r\nPalmer, Alaska\r\n745\r\n746\r\nPedro Bay, Alaska\r\n850\r\nPelican, Alaska\r\n735\r\nPerryville, Alaska\r\n853\r\nPetersburg, Alaska\r\n772\r\nPilot Sta, Alaska\r\n549\r\nPilotpoint, Alaska\r\n797\r\nPlatinum, Alaska\r\n979\r\nPump Station 10, Alaska\r\n641\r\nPoint Hope, Alaska\r\n368\r\nPoint Lay, Alaska\r\n833\r\nPointbaker, Alaska\r\n559\r\nPort Baily, Alaska\r\n370\r\nPort Lions, Alaska\r\n454\r\nPt Alexander, Alaska\r\n568\r\nPt Alsworth, Alaska\r\n781\r\nPt Graham, Alaska\r\n284\r\nPt Moller, Alaska\r\n987\r\nPt Protection, Alaska\r\n489\r\nPetersburg Mar, Alaska\r\n462\r\nPump Station 2, Alaska\r\n621\r\nPump Station 3, Alaska\r\n671\r\nPump Station 4, Alaska\r\n681\r\nPump Station 5, Alaska\r\n691\r\nPump Station 6, Alaska\r\n921\r\nPump Station 7, Alaska\r\n251\r\nQuinhagak, Alaska\r\n556\r\nRampart, Alaska\r\n358\r\nRatz Mtrmr, Alaska\r\n483\r\nRed Devil, Alaska\r\n447\r\nReddogmine, Alaska\r\n426\r\nRomanz AFS, Alaska\r\n795\r\nRowan Bay, Alaska\r\n630\r\nRuby, Alaska\r\n468\r\nRussian M, Alaska\r\n584\r\nSag River, Alaska\r\n824\r\nSand Point, Alaska\r\n383\r\nSavoonga, Alaska\r\n984\r\nScammon Bay, Alaska\r\n558\r\nSelawik, Alaska\r\n484\r\nSeldovia, Alaska\r\n234\r\nSeward, Alaska\r\n224\r\nSeward Mar, Alaska\r\n577\r\nShageluk, Alaska\r\n473\r\nShaktoolik, Alaska\r\n955\r\nSheldon Pt, Alaska\r\n498\r\nShemya, Alaska\r\n393\r\nShemya AFS, Alaska\r\n392\r\nShishmaref, Alaska\r\n649\r\nShungnak, Alaska\r\n437\r\nSitka, Alaska\r\n747\r\n792\r\n966\r\nSkagway, Alaska\r\n983\r\nSleetmute, Alaska\r\n449\r\nSoldotna, Alaska\r\n252\r\n262\r\nSprrvhn AFS, Alaska\r\n731\r\nSt Marys, Alaska\r\n438\r\nSt Michael, Alaska\r\n923\r\nSt Paul, Alaska\r\n546\r\n579\r\nSt. George, Alaska\r\n859\r\nSteebins, Alaska\r\n934\r\nStevens Vl, Alaska\r\n478\r\nStka Mr 43, Alaska\r\n572\r\nStnsn Well, Alaska\r\n657\r\nStony River, Alaska\r\n537\r\nSummitlake, Alaska\r\n482\r\nTakotna, Alaska\r\n298\r\nTalkeetna , Alaska\r\n733\r\nTanana, Alaska\r\n366\r\nTanunak, Alaska\r\n652\r\nTataln AFS , Alaska\r\n728\r\nTatitlek, Alaska\r\n325\r\nTelida, Alaska\r\n843\r\nTeller, Alaska\r\n642\r\nTenakeespring, Alaska\r\n736\r\nTetlin, Alaska\r\n324\r\nThorne Bay, Alaska\r\n828\r\nTincity AFS, Alaska\r\n724\r\nTogiak, Alaska\r\n493\r\nTogiak Mar, Alaska\r\n545\r\nTok, Alaska\r\n883\r\nToksookbay, Alaska\r\n427\r\nTuluksak, Alaska\r\n695\r\nTuntutulak, Alaska\r\n256\r\nTwin Hills, Alaska\r\n525\r\nTyonek, Alaska\r\n583\r\nUnalakleet, Alaska\r\n624\r\nUnalaska, Alaska\r\n581\r\nUnalsk Mar, Alaska\r\n574\r\nValdez, Alaska\r\n255\r\n835\r\nValdez Mr, Alaska\r\n626\r\nValdezckmn, Alaska\r\n597\r\nVenetie, Alaska\r\n849\r\nWainwright, Alaska\r\n763\r\nWales, Alaska\r\n664\r\nWasilla, Alaska\r\n352\r\n355\r\n373\r\n376\r\nWhale Pass, Alaska\r\n846\r\nWhite Mt, Alaska\r\n638\r\nWhittier, Alaska\r\n472\r\nWhittier Mar, Alaska\r\n397\r\nWillow, Alaska\r\n495\r\nWiseman, Alaska\r\n796\r\nWrangell, Alaska\r\n874\r\nYakutat, Alaska\r\n784\r\nYakutat Mr, Alaska\r\n627\r\nYukon Ven Camp, Alaska\r\n655\r\n\u00035Unknown prefix code (907) - Alaska\r\n"
  },
  {
    "path": "install/regions/regions.908",
    "content": "Asbury Park, New Jersey\r\n502\r\n774\r\n775\r\n776\r\n918\r\n922\r\n988\r\nAtlantic Highlands, New Jersey\r\n291\r\n872\r\nBelle Mead, New Jersey\r\n281\r\n359\r\n874\r\nBelmar, New Jersey\r\n280\r\n681\r\nBelvidere, New Jersey\r\n475\r\nBernardsville, New Jersey\r\n204\r\n221\r\n766\r\n953\r\nBlairstown, New Jersey\r\n362\r\nBloomsbury, New Jersey\r\n479\r\nBound Brook, New Jersey\r\n271\r\n302\r\n356\r\n457\r\n469\r\n560\r\n563\r\n627\r\n805\r\n844\r\n885\r\n980\r\nCalifon, New Jersey\r\n832\r\nCarteret, New Jersey\r\n541\r\n969\r\nChester, New Jersey\r\n879\r\nClinton, New Jersey\r\n500\r\n713\r\n730\r\n735\r\nColumbia, New Jersey\r\n496\r\nCranford, New Jersey\r\n272\r\n276\r\n709\r\n931\r\nDeal, New Jersey\r\n493\r\n517\r\n531\r\n663\r\nDunellen, New Jersey\r\n385\r\n424\r\n562\r\n752\r\n968\r\n981\r\nEast Millstone, New Jersey\r\n873\r\nEatontown, New Jersey\r\n389\r\n532\r\n542\r\n544\r\n935\r\nElizabeth, New Jersey\r\n230\r\n289\r\n351\r\n352\r\n353\r\n354\r\n355\r\n400\r\n411\r\n419\r\n527\r\n555\r\n558\r\n629\r\n803\r\n820\r\n965\r\nEnglishtown, New Jersey\r\n446\r\n536\r\n792\r\n972\r\nFanwood, New Jersey\r\n322\r\n889\r\nFarmingdale, New Jersey\r\n919\r\n938\r\nFlemington, New Jersey\r\n284\r\n782\r\n788\r\n806\r\nFranklin Park, New Jersey\r\n297\r\n386\r\n422\r\n821\r\n940\r\n954\r\nFreehold, New Jersey\r\n216\r\n294\r\n303\r\n308\r\n409\r\n415\r\n431\r\n462\r\n513\r\n577\r\n610\r\n618\r\n670\r\n780\r\n866\r\nFrenchtown, New Jersey\r\n996\r\nGreat Meadows, New Jersey\r\n637\r\nHackettstown, New Jersey\r\n813\r\n850\r\n852\r\nHampton, New Jersey\r\n310\r\n537\r\nHigh Bridge, New Jersey\r\n638\r\nHolmdel, New Jersey\r\n834\r\n946\r\n949\r\n975\r\nHope, New Jersey\r\n459\r\nJamesburg, New Jersey\r\n521\r\n656\r\nKeansburg, New Jersey\r\n495\r\n787\r\nKeyport, New Jersey\r\n264\r\n739\r\n888\r\nLakehurst, New Jersey\r\n323\r\n350\r\n657\r\n849\r\nLakewood, New Jersey\r\n363\r\n364\r\n367\r\n370\r\n901\r\n905\r\n928\r\nLebanon, New Jersey\r\n236\r\nLinden, New Jersey\r\n474\r\n486\r\n523\r\n717\r\n862\r\n925\r\nLong Branch, New Jersey\r\n222\r\n229\r\n571\r\n870\r\nLong Valley, New Jersey\r\n876\r\nManasquan, New Jersey\r\n223\r\n528\r\nMatawan, New Jersey\r\n290\r\n566\r\n583\r\n591\r\n702\r\nMetuchen, New Jersey\r\n205\r\n217\r\n225\r\n248\r\n283\r\n287\r\n321\r\n417\r\n494\r\n510\r\n548\r\n549\r\n603\r\n632\r\n906\r\n930\r\nMiddletown, New Jersey\r\n615\r\n671\r\n706\r\n957\r\nMilford, New Jersey\r\n995\r\nMillington, New Jersey\r\n580\r\n604\r\n647\r\nMonmouth Junction, New Jersey\r\n274\r\n329\r\nNeshanic, New Jersey\r\n369\r\nNew Brunswick, New Jersey\r\n202\r\n214\r\n220\r\n235\r\n246\r\n247\r\n249\r\n336\r\n418\r\n445\r\n463\r\n480\r\n519\r\n524\r\n545\r\n572\r\n588\r\n699\r\n745\r\n777\r\n819\r\n828\r\n843\r\n846\r\n878\r\n880\r\n883\r\n932\r\n937\r\n985\r\nOldwick, New Jersey\r\n439\r\nOxford, New Jersey\r\n453\r\nPeapack, New Jersey\r\n234\r\n719\r\n781\r\nPerth Amboy, New Jersey\r\n293\r\n324\r\n406\r\n407\r\n442\r\n715\r\n738\r\n826\r\nPhillipsburg, New Jersey\r\n213\r\n454\r\n859\r\nPlainfield, New Jersey\r\n412\r\n561\r\n668\r\n753\r\n754\r\n755\r\n756\r\n757\r\n769\r\nPoint Pleasant, New Jersey\r\n206\r\n262\r\n295\r\n458\r\n477\r\n840\r\n864\r\n892\r\n899\r\n920\r\nRahway, New Jersey\r\n381\r\n382\r\n388\r\n396\r\n499\r\n574\r\n594\r\n737\r\n760\r\n815\r\n827\r\n913\r\nRed Bank, New Jersey\r\n219\r\n224\r\n530\r\n576\r\n741\r\n747\r\n758\r\n842\r\nRoselle, New Jersey\r\n241\r\n245\r\n298\r\nSeaside Park, New Jersey\r\n793\r\n830\r\nSomerville, New Jersey\r\n218\r\n231\r\n253\r\n306\r\n526\r\n658\r\n685\r\n704\r\n707\r\n722\r\n725\r\nSouth Amboy, New Jersey\r\n525\r\n607\r\n679\r\n721\r\n727\r\nSouth River, New Jersey\r\n238\r\n251\r\n254\r\n257\r\n360\r\n390\r\n432\r\n613\r\n651\r\n723\r\n807\r\nSpring Lake, New Jersey\r\n449\r\n974\r\nStroudsburg, New Jersey\r\n841\r\nSummit, New Jersey\r\n273\r\n277\r\n464\r\n522\r\n582\r\n598\r\n665\r\n771\r\nToms River, New Jersey\r\n237\r\n240\r\n244\r\n255\r\n269\r\n270\r\n286\r\n288\r\n341\r\n349\r\n505\r\n506\r\n600\r\n910\r\n914\r\n929\r\nUnionville, New Jersey\r\n498\r\n569\r\n633\r\n686\r\n687\r\n688\r\n724\r\n729\r\n810\r\n851\r\n891\r\n964\r\nWashington, New Jersey\r\n619\r\n689\r\nWestfield, New Jersey\r\n232\r\n233\r\n317\r\n654\r\n789\r\nWhitehouse, New Jersey\r\n423\r\n534\r\n979\r\nWoodbridge, New Jersey\r\n602\r\n634\r\n636\r\n750\r\n855\r\n\u00035Unknown prefix code (908) - New Jersey\r\n"
  },
  {
    "path": "install/regions/regions.909",
    "content": "Anaheim, California\r\n201\r\n202\r\n203\r\n204\r\n312\r\n313\r\n314\r\n315\r\n561\r\nAnza, California\r\n763\r\nArlington, California\r\n343\r\n351\r\n353\r\n354\r\n358\r\n359\r\n602\r\n687\r\n688\r\n689\r\n710\r\n785\r\n909\r\nArrowhead, California\r\n336\r\n337\r\nBanning/Beaumont, California\r\n769\r\n845\r\n849\r\n922\r\nBig Bear City, California\r\n584\r\n585\r\nBig Bear Lake, California\r\n866\r\n878\r\nCalimesa, California\r\n446\r\n790\r\n797\r\nChino, California\r\n393\r\n464\r\n465\r\n590\r\n591\r\n597\r\n606\r\n613\r\n627\r\n628\r\nClaremont, California\r\n392\r\n394\r\n398\r\n399\r\n482\r\n592\r\n593\r\n596\r\n599\r\n607\r\n621\r\n624\r\n625\r\n626\r\nClmt Sndms, California\r\n305\r\n603\r\nColton, California\r\n370\r\n420\r\n422\r\n423\r\n424\r\n426\r\n431\r\n439\r\n445\r\n512\r\n616\r\n783\r\n824\r\n825\r\n872\r\n876\r\nCorona, California\r\n270\r\n272\r\n273\r\n278\r\n279\r\n371\r\n734\r\n735\r\n736\r\n737\r\nCrestline, California\r\n338\r\nDiamond Bar, California\r\n396\r\n468\r\n594\r\n595\r\n598\r\n860\r\n861\r\n869\r\nDyson's Sphere, California\r\n931\r\nElsinore, California\r\n245\r\n471\r\n609\r\n674\r\n678\r\nEtiwanda, California\r\n463\r\n899\r\nFontana, California\r\n350\r\n355\r\n356\r\n357\r\n427\r\n428\r\n822\r\n823\r\n829\r\nGardena, California\r\n555\r\nHemet, California\r\n306\r\n652\r\n658\r\n765\r\n766\r\n791\r\n925\r\n927\r\n929\r\nHighland, California\r\n425\r\n862\r\n864\r\nHomeland, California\r\n926\r\nIdyllwild, California\r\n659\r\nLakeview\u00031/\u00032Nuevo, California\r\n928\r\nMarshall, California\r\n473\r\n475\r\n880\r\n881\r\n883\r\n886\r\n887\r\nMentone, California\r\n389\r\n794\r\nMira Loma, California\r\n360\r\n681\r\n685\r\nMoreno, California\r\n601\r\nMoreno Valley, California\r\n242\r\n243\r\n247\r\n485\r\n486\r\n488\r\n653\r\n655\r\n656\r\n697\r\n924\r\nMurrieta, California\r\n304\r\n677\r\n696\r\n698\r\nOntario, California\r\n208\r\n309\r\n390\r\n391\r\n395\r\n401\r\n402\r\n403\r\n405\r\n406\r\n407\r\n460\r\n461\r\n462\r\n467\r\n604\r\n605\r\n923\r\n930\r\n933\r\n947\r\n983\r\n984\r\n986\r\n988\r\nPerris, California\r\n657\r\n940\r\n943\r\nPomona, California\r\n397\r\n469\r\n620\r\n622\r\n623\r\n629\r\n865\r\n868\r\nRedlands, California\r\n307\r\n335\r\n478\r\n792\r\n793\r\n796\r\n798\r\n799\r\nRialto, California\r\n320\r\n421\r\n820\r\n873\r\n874\r\n875\r\n877\r\nRiverside, California\r\n274\r\n275\r\n276\r\n341\r\n352\r\n369\r\n615\r\n682\r\n683\r\n684\r\n686\r\n715\r\n781\r\n782\r\n784\r\n787\r\n788\r\nRunning Springs, California\r\n867\r\nSage, California\r\n767\r\nSan Bernardino, California\r\n381\r\n382\r\n383\r\n384\r\n386\r\n387\r\n388\r\n882\r\n884\r\n885\r\n888\r\n889\r\nSan Jacinto, California\r\n487\r\n654\r\nSun City, California\r\n244\r\n246\r\n301\r\n672\r\n679\r\nTemecula, California\r\n302\r\n303\r\n308\r\n676\r\n694\r\n695\r\n699\r\nTemescal Canyon, California\r\n277\r\nUpland, California\r\n466\r\n477\r\n481\r\n483\r\n484\r\n608\r\n614\r\n920\r\n941\r\n942\r\n944\r\n945\r\n946\r\n948\r\n949\r\n980\r\n981\r\n982\r\n985\r\n987\r\n989\r\nWoodcrest, California\r\n780\r\n789\r\nYucaipa, California\r\n795\r\n\u00035Unknown prefix code (909) - California\r\n"
  },
  {
    "path": "install/regions/regions.910",
    "content": "Abbotsburg, North Carolina\r\n648\r\nAberdeen, North Carolina\r\n944\r\nAdvance, North Caroina\r\n998\r\nAnderson, North Carolina\r\n421\r\nAsheboro, North Carolina\r\n318\r\n365\r\n626\r\n629\r\n636\r\n672\r\n953\r\nBadin Lake, North Carolina\r\n461\r\nBaldwin, North Carolina\r\n877\r\nBennett, North Carolina\r\n581\r\nBenson, North Carolina\r\n894\r\nBeulah, North Carolina\r\n352\r\nBeulaville, North Carolina\r\n298\r\nBiscoe, North Carolina\r\n428\r\nBladenboro, North Carolina\r\n863\r\nBonlee, North Carolina\r\n837\r\nBoomer, North Carolina\r\n921\r\nBoonville, North Carolina\r\n367\r\nBrooks, North Carolina\r\n468\r\nBurlington, North Carolina\r\n222\r\n226\r\n227\r\n228\r\n229\r\n260\r\n263\r\n513\r\n538\r\n570\r\n578\r\n584\r\nCandor, North Carolina\r\n974\r\nCarthage, North Carolina\r\n947\r\nChadboum, North Carolina\r\n654\r\nChampion, North Carolina\r\n973\r\nClarkton, North Carolina\r\n647\r\nClemmons, North Carolina\r\n766\r\nClingman, North Carolina\r\n984\r\nClinton, North Carolina\r\n590\r\n592\r\nCoharie, North Carolina\r\n567\r\nColeridge, North Carolina\r\n879\r\nCourtney, North Carolina\r\n463\r\nCreston, North Carolina\r\n385\r\nCypress Creek, North Carolina\r\n588\r\nDanbury, North Carolina\r\n593\r\nDobson, North Carolina\r\n386\r\nDunn-Erwin, North Carolina\r\n891\r\n892\r\n897\r\n980\r\nEast Bend, North Carolina\r\n699\r\nEden, North Carolina\r\n623\r\n627\r\n635\r\nElizabethtown, North Carolina\r\n862\r\nElkin, North Carolina\r\n526\r\n835\r\nFair Bluff, North Carolina\r\n649\r\nFalson, North Carolina\r\n267\r\nFarmer, North Carolina\r\n857\r\nFayetteville, North Carolina\r\n214\r\n215\r\n219\r\n234\r\n245\r\n251\r\n253\r\n256\r\n259\r\n262\r\n265\r\n267\r\n268\r\n270\r\n276\r\n277\r\n278\r\n281\r\n283\r\n285\r\n287\r\n289\r\n293\r\n295\r\n296\r\n298\r\n313\r\n324\r\n326\r\n327\r\n328\r\n329\r\n340\r\n341\r\n343\r\n346\r\n347\r\n350\r\n353\r\n369\r\n371\r\n388\r\n389\r\n392\r\n394\r\n395\r\n417\r\n422\r\n451\r\n452\r\n455\r\n457\r\n458\r\n462\r\n464\r\n520\r\n521\r\n525\r\n529\r\n531\r\n532\r\n533\r\n540\r\n564\r\n565\r\n567\r\n577\r\n579\r\n581\r\n582\r\n588\r\n590\r\n591\r\n592\r\n594\r\n602\r\n608\r\n618\r\n622\r\n625\r\n628\r\n640\r\n642\r\n645\r\n646\r\n647\r\n648\r\n652\r\n653\r\n654\r\n655\r\n669\r\n671\r\n675\r\n686\r\n692\r\n695\r\n738\r\n739\r\n743\r\n754\r\n762\r\n763\r\n791\r\n799\r\n814\r\n815\r\n817\r\n818\r\n819\r\n820\r\n842\r\n843\r\n844\r\n858\r\n860\r\n862\r\n863\r\n865\r\n866\r\n875\r\n879\r\n891\r\n892\r\n893\r\n895\r\n896\r\n897\r\n938\r\n944\r\n945\r\n947\r\n948\r\n949\r\n951\r\n961\r\n980\r\n988\r\n997\r\nFayetteville\u00031/\u00032Ft. Bragg, North Carolina\r\n396\r\n868\r\n488\r\n484\r\n483\r\n822\r\n864\r\n486\r\n867\r\n436\r\n306\r\n307\r\n308\r\n322\r\n323\r\n424\r\n425\r\n485\r\n432\r\n433\r\n391\r\n630\r\n678\r\n960\r\n624\r\n487\r\n907\r\nForbush, North Carolina\r\n861\r\nFort Bragg, North Carolina\r\n396\r\nFour Oaks, North Carolina\r\n963\r\nGarland, North Carolina\r\n529\r\nGibsonville, North Carolina\r\n449\r\nGlade Creek, North Carolina\r\n657\r\nGoldston, North Carolina\r\n898\r\nGreensboro, North Carolina\r\n218\r\n230\r\n271\r\n272\r\n273\r\n274\r\n275\r\n279\r\n282\r\n288\r\n292\r\n294\r\n299\r\n312\r\n314\r\n316\r\n333\r\n334\r\n337\r\n339\r\n370\r\n373\r\n375\r\n378\r\n379\r\n393\r\n412\r\n507\r\n513\r\n545\r\n547\r\n574\r\n601\r\n605\r\n621\r\n632\r\n665\r\n668\r\n674\r\n680\r\n691\r\n697\r\n698\r\n852\r\n854\r\n855\r\n908\r\n913\r\nHarrells, North Carolina\r\n532\r\nHays, North Carolina\r\n696\r\nHerring, North Carolina\r\n564\r\nHigh Falls, North Carolina\r\n464\r\nHigh Point, North Carolina\r\n431\r\n434\r\n454\r\n812\r\n841\r\n861\r\n869\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\nHillsdale, North Carolina\r\n940\r\nHolly Ridge, North Carolina\r\n329\r\nHope Mills, North Carolina\r\n423\r\nJackson Creek, North Carolina\r\n241\r\nJacksonville, North Carolina\r\n353\r\n577\r\n455\r\n346\r\n451\r\n347\r\n340\r\n389\r\n938\r\n219\r\nJulian, North Carolina\r\n685\r\nKenansville, North Carolina\r\n296\r\nKelly, North Carolina\r\n669\r\nKernersville, North Carolina\r\n993\r\n996\r\nKimesville, North Carolina\r\n545\r\nKing, North Carolina\r\n983\r\nLake Waccamaw, North Carolina\r\n646\r\nLansing, North Carolina\r\n384\r\nLevel Cross, North Carolina\r\n374\r\nLewisville, North Carolina\r\n845\r\nLexington, North Carolina\r\n764\r\nLiberty, North Carolina\r\n662\r\nLillington, North Carolina\r\n893\r\nLisbon, North Carolina\r\n645\r\nLomax, North Carolina\r\n957\r\nMadison, North Carolina\r\n427\r\n548\r\nMaxton, North Carolina\r\n844\r\nMaysville, North Carolina\r\n743\r\nMonticello, North Carolina\r\n656\r\nMount Airy, North Carolina\r\n719\r\n786\r\n789\r\nMount Gilead, North Carolina\r\n439\r\nMulberry, North Carolina\r\n670\r\nNathans Creek, North Carolina\r\n982\r\nNewton Grove, North Carolina\r\n594\r\nNorth Wilkesboro, North Carolina\r\n651\r\n667\r\n838\r\n902\r\nOldtown, North Carolina\r\n922\r\n924\r\nParkton, North Carolina\r\n858\r\nPilot Mountain, North Carolina\r\n368\r\nPinebluff, North Carolina\r\n281\r\nPinehurst, North Carolina\r\n215\r\n295\r\nPisgah, North Carolina\r\n381\r\nPittsboro, North Carolina\r\n542\r\nPope A.F.B., North Carolina\r\n394\r\nPrinceton, North Carolina\r\n936\r\nProspect Hill, North Carolina\r\n562\r\nQuaker Gap, North Carolina\r\n994\r\nRaeford, North Carolina\r\n875\r\nRamseur, North Carolina\r\n824\r\nRandleman, North Carolina\r\n495\r\n498\r\nRed Brush, North Carolina\r\n320\r\nRed Springs, North Carolina\r\n843\r\nReidsville, North Carolina\r\n342\r\n349\r\n616\r\n634\r\nRichlands, North Carolina\r\n324\r\nRoaring Gap, North Carolina\r\n363\r\nRobbins, North Carolina\r\n948\r\nRoseboro, North Carolina\r\n525\r\nRose Hill, North Carolina\r\n289\r\nRoxboro, North Carolina\r\n503\r\n597\r\n599\r\nRuffin, North Carolina\r\n939\r\nRural Hall, North Carolina\r\n969\r\nSaint Pauls, North Carolina\r\n865\r\nSandy Ridge, North Carolina\r\n871\r\nSaxapahaw, North Carolina\r\n376\r\nScottville, North Carolina\r\n359\r\nSeagrove, North Carolina\r\n873\r\nShoals, North Carolina\r\n325\r\nSiler City, North Carolina\r\n663\r\n742\r\nSix Run, North Carolina\r\n533\r\nSmithfield, North Carolina\r\n915\r\n989\r\n934\r\nSneads Ferry, North Carolina\r\n327\r\nSouth River, North Carolina\r\n531\r\nSouthern Pines, North Carolina\r\n692\r\n695\r\nSparta, NOrth Carolina\r\n372\r\nSpring Lake, North Carolina\r\n497\r\nStanleyville, North Carolina\r\n377\r\nState Road, North Carolina\r\n874\r\nStoneville, North Carolina\r\n573\r\nSummerfield, North Carolina\r\n643\r\nSwansboro, North Carolina\r\n326\r\n354\r\nTabor City, North Carolina\r\n653\r\nThomasville, North Carolina\r\n472\r\n474\r\n475\r\n476\r\nTimberlake, North Carolina\r\n364\r\nTopsail Island, North Carolina\r\n328\r\nTroy, North Carolina\r\n572\r\n576\r\nVass, North Carolina\r\n245\r\nWallace, North Carolina\r\n285\r\nWalkertown, North Carolina\r\n595\r\nWalnut Cove, North Carolina\r\n481\r\nWarsaw, North Carolina\r\n293\r\nWest End, North Carolina\r\n673\r\nWest Jefferson, North Carolina\r\n246\r\nWestfield, North Carolina\r\n351\r\nWhispering Pines, North Carolina\r\n949\r\nWhite Oak, North Carolina\r\n866\r\nWhiteville, North Carolina\r\n642\r\n640\r\nWinston-Salem, North Carolina\r\n208\r\n418\r\n519\r\n607\r\n631\r\n650\r\n659\r\n661\r\n712\r\n716\r\n717\r\n718\r\n720\r\n721\r\n722\r\n723\r\n724\r\n725\r\n727\r\n730\r\n741\r\n744\r\n748\r\n750\r\n759\r\n760\r\n761\r\n764\r\n765\r\n766\r\n767\r\n768\r\n769\r\n770\r\n773\r\n777\r\n780\r\n784\r\n785\r\n788\r\nPhilippines\r\n473\r\n\u00035Unknown prefix code (910)\r\n"
  },
  {
    "path": "install/regions/regions.912",
    "content": "Abbeville, Georgia\r\n467\r\nAdel, Georgia\r\n896\r\nAdrian, Georgia\r\n668\r\nAlamo, Georgia\r\n568\r\nAlapaha, Georgia\r\n532\r\nAlbany, Georgia\r\n347\r\n430\r\n431\r\n432\r\n434\r\n435\r\n436\r\n438\r\n439\r\n879\r\n881\r\n883\r\n886\r\n888\r\n889\r\nAlma, Georgia\r\n632\r\nAmericus, Georgia\r\n924\r\n928\r\nAnderson, Georgia\r\n852\r\nArlington, Georgia\r\n725\r\nAshburn, Georgia\r\n567\r\nAtlanta, Georgia\r\n555\r\nAttapulgus, Georgia\r\n465\r\nBaconton, Georgia\r\n787\r\nBainbridge, Georgia\r\n221\r\n243\r\n246\r\n248\r\nBartow, Georgia\r\n364\r\nBarwick, Georgia\r\n735\r\nBaxley, Georgia\r\n367\r\nBerlin, Georgia\r\n324\r\nBlackshear, Georgia\r\n449\r\nBlakely, Georgia\r\n723\r\nBluffton, Georgia\r\n641\r\nBoston, Georgia\r\n498\r\nBrooklet, Georgia\r\n842\r\nBroxton, Georgia\r\n359\r\nBrunswick, Georgia\r\n222\r\n261\r\n262\r\n264\r\n265\r\n267\r\n269\r\nBuena Vista, Georgia\r\n649\r\nButler, Georgia\r\n862\r\nByromville, Georgia\r\n433\r\nByron, Georgia\r\n956\r\nCadwell, Georgia\r\n689\r\nCairo, Georgia\r\n377\r\nCalvryreno, Georgia\r\n872\r\nCamilla, Georgia\r\n336\r\nCedar Springs, Georgia\r\n372\r\nCedar Grove, Georgia\r\n463\r\nCenterville, Georgia\r\n953\r\nChattahoochie, Georgia\r\n662\r\nChester, Georgia\r\n358\r\nClaxton, Georgia\r\n739\r\nClito, Georgia\r\n587\r\nCobbtown, Georgia\r\n684\r\nCochran, Georgia\r\n934\r\nCollins, Georgia\r\n693\r\nColquitt, Georgia\r\n758\r\nCoolidge, Georgia\r\n346\r\nCordele, Georgia\r\n273\r\n276\r\nCulloden, Georgia\r\n885\r\nCuthbert, Georgia\r\n732\r\nDanville, Georgia\r\n962\r\nDarien, Georgia\r\n437\r\nDavisboro, Georgia\r\n348\r\nDawson, Georgia\r\n995\r\nDexter, Georgia\r\n875\r\nDoerun, Georgia\r\n782\r\nDonalsonville, Georgia\r\n524\r\nDouglas, Georgia\r\n383\r\n384\r\n389\r\nDover, Georgia\r\n863\r\nDublin, Georgia\r\n272\r\n274\r\n275\r\n277\r\n278\r\nDudley, Georgia\r\n676\r\nEastman, Georgia\r\n374\r\nEdison, Georgia\r\n835\r\nEllabelle, Georgia\r\n858\r\nEllaville, Georgia\r\n937\r\nEnigma, Georgia\r\n533\r\nEulonia, Georgia\r\n832\r\nFargo, Georgia\r\n637\r\nFitzgerald, Georgia\r\n423\r\n424\r\nFolkston, Georgia\r\n496\r\nForsyth, Georgia\r\n993\r\n994\r\nFort Gaines, Georgia\r\n768\r\nFort Valley, Georgia\r\n822\r\n825\r\nFunston, Georgia\r\n941\r\nGeorgetown, Georgia\r\n334\r\nGlennville, Georgia\r\n654\r\nGlenwood, Georgia\r\n523\r\nGordon, Georgia\r\n628\r\nGray, Georgia\r\n986\r\nGuyton, Georgia\r\n772\r\nHaddock, Georgia\r\n932\r\nHahira, Georgia\r\n794\r\nHawkinsville, Georgia\r\n783\r\n892\r\n893\r\nHazlehurst, Georgia\r\n375\r\nHilltonia, Georgia\r\n829\r\nHinesville, Georgia\r\n368\r\n369\r\n767\r\n876\r\n877\r\nHoboken, Georgia\r\n458\r\nHomerville, Georgia\r\n487\r\nHortense, Georgia\r\n473\r\nIdeal, Georgia\r\n949\r\nIron City, Georgia\r\n774\r\nIrwinton, Georgia\r\n946\r\nIrwinville, Georgia\r\n831\r\nJacksonville, Georgia\r\n833\r\nJakin, Georgia\r\n793\r\nJeffersonvale, Georgia\r\n945\r\nJekyll Island, Georgia\r\n635\r\nJesup, Georgia\r\n427\r\n530\r\n588\r\nJohnson Corner, Georgia\r\n565\r\nKeller, Georgia\r\n727\r\nKingsland, Georgia\r\n729\r\nKite, Georgia\r\n469\r\nLake Park, Georgia\r\n559\r\nLakeland, Georgia\r\n482\r\nLeary, Georgia\r\n792\r\nLeesburg, Georgia\r\n759\r\nLenox, Georgia\r\n546\r\nLeslie, Georgia\r\n874\r\nLexsy, Georgia\r\n562\r\nLizella, Georgia\r\n935\r\nLake Blackshear, Georgia\r\n853\r\nLake Sinclair, Georgia\r\n968\r\nLouisville, Georgia\r\n625\r\nLudowici, Georgia\r\n545\r\nLumber City, Georgia\r\n363\r\nLumpkin, Georgia\r\n838\r\nLyons, Georgia\r\n526\r\nMacon, Georgia\r\n471\r\n474\r\n477\r\n633\r\n646\r\n737\r\n738\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n749\r\n750\r\n751\r\n752\r\n753\r\n755\r\n757\r\n761\r\n781\r\n784\r\n788\r\n952\r\nMarshallville, Georgia\r\n967\r\nMc Rae, Georgia\r\n868\r\nMeigs, Georgia\r\n683\r\nMetter, Georgia\r\n685\r\nMidville, Georgia\r\n589\r\nMidway, Georgia\r\n884\r\nMilan, Georgia\r\n362\r\nMilledgeville, Georgia\r\n451\r\n452\r\n453\r\n454\r\n456\r\nMillen, Georgia\r\n982\r\nMontezuma, Georgia\r\n472\r\nMontrose, Georgia\r\n376\r\nMorgan, Georgia\r\n849\r\nMorven, Georgia\r\n775\r\nMoultrie, Georgia\r\n890\r\n891\r\n985\r\nMount Vernon, Georgia\r\n583\r\nNahunta, Georgia\r\n462\r\nNashville, Georgia\r\n686\r\nNevils, Georgia\r\n839\r\nNewington, Georgia\r\n857\r\nNewton, Georgia\r\n734\r\nNicholls, Georgia\r\n345\r\nNormanpark, Georgia\r\n769\r\nOak Park, Georgia\r\n578\r\nOchlocknee, Georgia\r\n574\r\nOcilla, Georgia\r\n468\r\nOdum, Georgia\r\n586\r\nOmega, Georgia\r\n528\r\nParrott, Georgia\r\n623\r\nPatterson, Georgia\r\n647\r\nPavo, Georgia\r\n859\r\nPearson, Georgia\r\n422\r\nPelham, Georgia\r\n294\r\nPembroke, Georgia\r\n653\r\nPerry, Georgia\r\n987\r\n988\r\nPinehurst, Georgia\r\n645\r\nPineview, Georgia\r\n624\r\nPitts, Georgia\r\n648\r\nPlains, Georgia\r\n824\r\nPooler, Georgia\r\n748\r\nPortal, Georgia\r\n865\r\nPreston, Georgia\r\n828\r\nQuitman, Georgia\r\n263\r\nRay City, Georgia\r\n455\r\nRebecca, Georgia\r\n643\r\nRegister, Georgia\r\n488\r\nReidsville, Georgia\r\n557\r\nRentz, Georgia\r\n984\r\nReynolds, Georgia\r\n847\r\nReynoldsville, Georgia\r\n861\r\nRhine, Georgia\r\n385\r\nRichland, Georgia\r\n887\r\nRichmond Hill, Georgia\r\n756\r\nRincon, Georgia\r\n826\r\nRoberta, Georgia\r\n836\r\nRochelle, Georgia\r\n365\r\nSandersville, Georgia\r\n552\r\n553\r\nSapelo Island, Georgia\r\n485\r\nSardis, Georgia\r\n569\r\nSasser, Georgia\r\n698\r\nSavannah, Georgia\r\n231\r\n232\r\n233\r\n234\r\n235\r\n236\r\n238\r\n350\r\n351\r\n352\r\n353\r\n354\r\n355\r\n356\r\n357\r\n598\r\n651\r\n652\r\n655\r\n656\r\n657\r\n658\r\n897\r\n898\r\n920\r\n921\r\n925\r\n927\r\n944\r\n947\r\n964\r\n965\r\n966\r\n976\r\nScreven, Georgia\r\n579\r\nShellman, Georgia\r\n679\r\nSmithville, Georgia\r\n846\r\nSouth Guyton, Georgia\r\n728\r\nSoperton, Georgia\r\n529\r\nSparks, Georgia\r\n549\r\nSpringfield, Georgia\r\n754\r\nSaint George, Georgia\r\n843\r\nSaint Marys, Georgia\r\n673\r\n882\r\nStatesboro, Georgia\r\n489\r\n536\r\n681\r\n682\r\n764\r\n871\r\nStilson, Georgia\r\n823\r\nSaint Simonsis, Georgia\r\n634\r\n638\r\nSwainsboro, Georgia\r\n237\r\nSylvania, Georgia\r\n564\r\nSylvester, Georgia\r\n776\r\nThomasville, Georgia\r\n225\r\n226\r\n227\r\n228\r\nTifton, Georgia\r\n382\r\n386\r\n387\r\n388\r\nToomsboro, Georgia\r\n933\r\nTwin City, Georgia\r\n763\r\nTybee Island, Georgia\r\n786\r\nUnadilla, Georgia\r\n627\r\nUvalda, Georgia\r\n594\r\nValdosta, Georgia\r\n241\r\n242\r\n244\r\n245\r\n247\r\n249\r\n251\r\n333\r\n560\r\nVidalia, Georgia\r\n537\r\n538\r\nVienna, Georgia\r\n268\r\nWadley, Georgia\r\n252\r\n253\r\nWarwick, Georgia\r\n535\r\nWaycross, Georgia\r\n282\r\n283\r\n284\r\n285\r\n287\r\nWaynesville, Georgia\r\n778\r\nWhigham, Georgia\r\n762\r\nWillacooch, Georgia\r\n534\r\nWoodbine, Georgia\r\n576\r\nWrightsville, Georgia\r\n864\r\nWarner Robbins, Georgia\r\n327\r\n328\r\n542\r\n922\r\n923\r\n926\r\n929\r\n951\r\n\u00035Unknown prefix code (912) - Georgia\r\n"
  },
  {
    "path": "install/regions/regions.913",
    "content": "Abilene, Kansas\r\n263\r\nAgenda, Kansas\r\n732\r\nAgra, Kansas\r\n638\r\nAlexander, Kansas\r\n343\r\nAlma, Kansas\r\n765\r\nAlmena, Kansas\r\n669\r\nAlta Vista, Kansas\r\n499\r\nAlton, Kansas\r\n984\r\nAssaria, Kansas\r\n667\r\nAtchison, Kansas\r\n367\r\nAthol, Kansas\r\n695\r\nAtwood, Kansas\r\n626\r\nAuburn, Kansas\r\n671\r\nAurora, Kansas\r\n464\r\nAxtell, Kansas\r\n736\r\nBaileyville, Kansas\r\n895\r\nBaldwin, Kansas\r\n594\r\nBarnard, Kansas\r\n792\r\nBarnes, Kansas\r\n763\r\nBasehor Em, Kansas\r\n724\r\nBasehor, Kansas\r\n728\r\nBazine, Kansas\r\n398\r\nBeattie, Kansas\r\n353\r\nBeeler, Kansas\r\n848\r\nBelleville, Kansas\r\n527\r\nBeloit, Kansas\r\n738\r\nBendena, Kansas\r\n988\r\nBennington, Kansas\r\n488\r\nBethel, Kansas\r\n299\r\n334\r\n788\r\nBeverly, Kansas\r\n436\r\nBird City, Kansas\r\n734\r\nBison, Kansas\r\n356\r\nBlue Mound, Kansas\r\n756\r\nBluerapids, Kansas\r\n226\r\nBonner Spg, Kansas\r\n422\r\n441\r\n721\r\nBrewster, Kansas\r\n694\r\nBrookville, Kansas\r\n225\r\nBrownell, Kansas\r\n481\r\nBuckeye, Kansas\r\n598\r\nBucyrus, Kansas\r\n879\r\nBurlingame, Kansas\r\n654\r\nBurr Oak, Kansas\r\n647\r\nCarlton, Kansas\r\n949\r\nCawkercity, Kansas\r\n781\r\nCentralia, Kansas\r\n857\r\nCentropols, Kansas\r\n255\r\nChapman, Kansas\r\n922\r\nCircleville, Kansas\r\n924\r\nClaycenter, Kansas\r\n632\r\nClifton, Kansas\r\n455\r\nClinton, Kansas\r\n748\r\nClyde, Kansas\r\n446\r\nColby, Kansas\r\n443\r\n462\r\nCollyer, Kansas\r\n769\r\nConcordia, Kansas\r\n243\r\nCorning, Kansas\r\n868\r\nCourtland, Kansas\r\n374\r\nCrbndlwkrs, Kansas\r\n564\r\n761\r\n836\r\nCuba, Kansas\r\n729\r\nDamar, Kansas\r\n839\r\nDe Soto, Kansas\r\n583\r\n585\r\nDelavan, Kansas\r\n466\r\nDelia, Kansas\r\n771\r\nDelphos, Kansas\r\n523\r\nDenison, Kansas\r\n935\r\nDenmark, Kansas\r\n277\r\nDenton, Kansas\r\n359\r\nDorrance, Kansas\r\n666\r\nDover, Kansas\r\n775\r\nDowns, Kansas\r\n454\r\nDwight, Kansas\r\n482\r\nEaston, Kansas\r\n773\r\nEdgerton, Kansas\r\n882\r\nEdmond, Kansas\r\n622\r\nEffingham, Kansas\r\n833\r\nEllis, Kansas\r\n726\r\nEllsworth, Kansas\r\n472\r\nElmont, Kansas\r\n288\r\nElwood, Kansas\r\n365\r\nEmmett, Kansas\r\n535\r\nEnterprise, Kansas\r\n934\r\nEsbon, Kansas\r\n725\r\nEskridge, Kansas\r\n449\r\nEudora, Kansas\r\n542\r\nEverest, Kansas\r\n548\r\nFairview, Kansas\r\n467\r\nFontana, Kansas\r\n849\r\nFormoso, Kansas\r\n794\r\nFrankfort, Kansas\r\n292\r\nGardner, Kansas\r\n856\r\n884\r\nGarnett, Kansas\r\n448\r\nGaylord, Kansas\r\n697\r\nGlasco, Kansas\r\n568\r\nGlen Elder, Kansas\r\n545\r\nGoff, Kansas\r\n939\r\nGoodland, Kansas\r\n821\r\n899\r\nGorham, Kansas\r\n637\r\nGove, Kansas\r\n938\r\nGrainfield, Kansas\r\n673\r\nGrantville, Kansas\r\n289\r\nGreeley, Kansas\r\n867\r\nGreen, Kansas\r\n944\r\nGreenleaf, Kansas\r\n747\r\nGrinnell, Kansas\r\n824\r\nGypsum, Kansas\r\n536\r\nHaddam, Kansas\r\n778\r\nHarveyville, Kansas\r\n589\r\nHavensville, Kansas\r\n948\r\nHays, Kansas\r\n623\r\n625\r\n628\r\n635\r\nHerington, Kansas\r\n258\r\nHerndon, Kansas\r\n322\r\nHiawatha, Kansas\r\n741\r\n742\r\nHighland, Kansas\r\n442\r\nHill City, Kansas\r\n674\r\nHillsdale, Kansas\r\n783\r\nHnvr Hlbg, Kansas\r\n337\r\nHolton, Kansas\r\n364\r\nHolyrood, Kansas\r\n252\r\nHome, Kansas\r\n799\r\nHope, Kansas\r\n366\r\nHorton, Kansas\r\n486\r\nHoxie, Kansas\r\n675\r\nHoyt, Kansas\r\n986\r\nHunter, Kansas\r\n529\r\nHuron, Kansas\r\n847\r\nIonia, Kansas\r\n786\r\nJamestown, Kansas\r\n439\r\nJennings, Kansas\r\n678\r\nJewell, Kansas\r\n428\r\nJunctioncy, Kansas\r\n238\r\n239\r\n240\r\n762\r\n784\r\nKanorado, Kansas\r\n399\r\nKansas City, Kansas\r\n236\r\n262\r\n281\r\n287\r\n321\r\n342\r\n362\r\n371\r\n375\r\n384\r\n424\r\n432\r\n522\r\n541\r\n551\r\n570\r\n573\r\n576\r\n588\r\n596\r\n624\r\n633\r\n634\r\n639\r\n645\r\n661\r\n676\r\n677\r\n787\r\n789\r\n831\r\n574\r\nKensington, Kansas\r\n476\r\nLa Crosse, Kansas\r\n222\r\nLa Cygne, Kansas\r\n757\r\nLancaster, Kansas\r\n874\r\nLane, Kansas\r\n869\r\nLawrence, Kansas\r\n691\r\n749\r\n766\r\n832\r\n841\r\n842\r\n843\r\n864\r\n865\r\nLeavenworth, Kansas\r\n651\r\n682\r\n684\r\n727\r\n758\r\n996\r\nXXX\r\nLebanon, Kansas\r\n389\r\nLecompton, Kansas\r\n887\r\nLenexa, Kansas\r\n495\r\n621\r\n722\r\n859\r\n888\r\nLenora, Kansas\r\n567\r\nLeonardville, Kansas\r\n293\r\nLevant, Kansas\r\n586\r\nLincoln, Kansas\r\n524\r\nLindsborg, Kansas\r\n227\r\nLinn, Kansas\r\n348\r\nLinwood, Kansas\r\n723\r\nLogan, Kansas\r\n689\r\nLongford, Kansas\r\n388\r\nLongisland, Kansas\r\n854\r\nLost Spgs, Kansas\r\n983\r\nLouisburg, Kansas\r\n837\r\nLucas, Kansas\r\n525\r\nLuray, Kansas\r\n698\r\nLyndon, Kansas\r\n828\r\nMahaska, Kansas\r\n245\r\nManhattan, Kansas\r\n532\r\n537\r\n539\r\n587\r\n776\r\nMankato, Kansas\r\n378\r\nMaple Hill, Kansas\r\n663\r\nMarquette, Kansas\r\n546\r\nMarysville, Kansas\r\n562\r\nMayetta, Kansas\r\n966\r\nMelrose, Kansas\r\n344\r\n458\r\n493\r\nMccracken, Kansas\r\n394\r\nMcdonald, Kansas\r\n538\r\nMclouth, Kansas\r\n796\r\nMelrose, Kansas\r\n268\r\n338\r\n339\r\n341\r\n345\r\n381\r\n383\r\n451\r\n469\r\n491\r\n492\r\n599\r\n631\r\n642\r\n648\r\n649\r\n752\r\n894\r\n962\r\n967\r\nMelvern, Kansas\r\n549\r\nMenlo, Kansas\r\n855\r\nMeriden, Kansas\r\n484\r\nMichgn Vly, Kansas\r\n453\r\nMilford, Kansas\r\n463\r\nMiltonvale, Kansas\r\n427\r\nMinneapols, Kansas\r\n392\r\nMorganvl, Kansas\r\n926\r\nMorland, Kansas\r\n627\r\nMorrill, Kansas\r\n459\r\nMorrowvl, Kansas\r\n265\r\nMound City, Kansas\r\n795\r\nMunden, Kansas\r\n987\r\nMuscotah, Kansas\r\n872\r\nNarka, Kansas\r\n358\r\nNatoma, Kansas\r\n885\r\nNavarre, Kansas\r\n479\r\nNekoma, Kansas\r\n329\r\nNess City, Kansas\r\n798\r\nNetawaka, Kansas\r\n933\r\nNorcatur, Kansas\r\n693\r\nNorth Topeka, Kansas\r\n246\r\nNorton, Kansas\r\n877\r\nNortonvl, Kansas\r\n886\r\nOakley, Kansas\r\n672\r\nOberlin, Kansas\r\n475\r\nOketo, Kansas\r\n744\r\nOlathe, Kansas\r\n764\r\n768\r\n780\r\n782\r\n791\r\n829\r\nOlsburg, Kansas\r\n468\r\nOnaga, Kansas\r\n889\r\nOsage City, Kansas\r\n528\r\nOsawatomie, Kansas\r\n755\r\nOsborne, Kansas\r\n346\r\nOskaloosa, Kansas\r\n863\r\nOtis, Kansas\r\n387\r\nOttawa, Kansas\r\n229\r\n242\r\nOverbrook, Kansas\r\n665\r\nOzawkie, Kansas\r\n876\r\nPalco, Kansas\r\n737\r\nPalmer, Kansas\r\n692\r\nPaola, Kansas\r\n285\r\n294\r\nParadise, Kansas\r\n998\r\nParker, Kansas\r\n898\r\nPauline, Kansas\r\n861\r\n862\r\nPaxico, Kansas\r\n636\r\nPerry, Kansas\r\n597\r\nPhillipsbg, Kansas\r\n543\r\nPlainville, Kansas\r\n434\r\nPleasanton, Kansas\r\n352\r\nPomona, Kansas\r\n566\r\nPowhattan, Kansas\r\n474\r\nPrairie View, Kansas\r\n973\r\nPrescott, Kansas\r\n471\r\nPrinceton, Kansas\r\n937\r\nQuenemo, Kansas\r\n759\r\nQuinter, Kansas\r\n754\r\nRamona, Kansas\r\n965\r\nRandall, Kansas\r\n739\r\nRansom, Kansas\r\n731\r\nRantoul, Kansas\r\n878\r\nRepublic, Kansas\r\n361\r\nRexford, Kansas\r\n687\r\nRichland, Kansas\r\n685\r\nRichmond, Kansas\r\n835\r\nRiley, Kansas\r\n485\r\nRobinson, Kansas\r\n544\r\nRossville, Kansas\r\n584\r\nRoxbury, Kansas\r\n254\r\nRushcenter, Kansas\r\n372\r\nRussell, Kansas\r\n483\r\nRusselsprings, Kansas\r\n751\r\nSabetha, Kansas\r\n284\r\nSalemsburg, Kansas\r\n668\r\nSalina, Kansas\r\n822\r\n823\r\n825\r\n826\r\n827\r\nScandia, Kansas\r\n335\r\nScranton, Kansas\r\n793\r\nSelden, Kansas\r\n386\r\nSeneca, Kansas\r\n336\r\nSharon Spring, Kansas\r\n852\r\nSilverlake, Kansas\r\n582\r\nSimpson, Kansas\r\n593\r\nSmith Ctr, Kansas\r\n282\r\nSouth Barnston, Kansas\r\n679\r\nSouth Benklman, Kansas\r\n426\r\nSouth Bloomington, Kansas\r\n779\r\nSouth Chester, Kansas\r\n326\r\nSouth Danbury, Kansas\r\n896\r\nSouth Du, Kansas\r\n858\r\nSouth Haigler, Kansas\r\n298\r\nSouth Liberty, Kansas\r\n699\r\nSouth Naponee, Kansas\r\n264\r\nSouth Pawn, Kansas\r\n853\r\nSouth Rpbn, Kansas\r\n797\r\nSouth Superor, Kansas\r\n875\r\nSouth Franklin, Kansas\r\n429\r\nSoldier, Kansas\r\n834\r\nSolomon, Kansas\r\n655\r\nSoredcloud, Kansas\r\n745\r\nSouth Alma, Kansas\r\n923\r\nSouthbyron, Kansas\r\n237\r\nSouthhardy, Kansas\r\n278\r\nSouthodell, Kansas\r\n767\r\nSowilsonville, Kansas\r\n347\r\nSpringhill, Kansas\r\n686\r\nSt Francis, Kansas\r\n332\r\nSt George, Kansas\r\n494\r\nSt Marys, Kansas\r\n437\r\nStanley, Kansas\r\n681\r\n897\r\nStockton, Kansas\r\n425\r\nSummerfield, Kansas\r\n244\r\nSylvan Grove, Kansas\r\n526\r\nTecumseh, Kansas\r\n379\r\nTescott, Kansas\r\n283\r\nTimken, Kansas\r\n355\r\nTipton, Kansas\r\n373\r\nTonganoxie, Kansas\r\n845\r\nTopeka Green, Kansas\r\n478\r\nTopeka, Kansas\r\n221\r\n224\r\n231\r\n232\r\n233\r\n234\r\n235\r\n266\r\n267\r\n271\r\n272\r\n273\r\n274\r\n276\r\n286\r\n291\r\n295\r\n296\r\n297\r\n354\r\n357\r\n435\r\n571\r\n575\r\n670\r\n976\r\nTroy, Kansas\r\n985\r\nUtica, Kansas\r\n391\r\nValley Falls, Kansas\r\n945\r\nVermillion, Kansas\r\n382\r\nVictoria, Kansas\r\n735\r\nWakeeney, Kansas\r\n743\r\nWakefield, Kansas\r\n461\r\nWaldo, Kansas\r\n942\r\nWallace, Kansas\r\n891\r\nWamego, Kansas\r\n456\r\nWashington, Kansas\r\n325\r\nWaterville, Kansas\r\n785\r\nWathena, Kansas\r\n989\r\nWaverly, Kansas\r\n733\r\nWcleveland, Kansas\r\n964\r\nWebber, Kansas\r\n753\r\nWellsville, Kansas\r\n883\r\nWeskan, Kansas\r\n943\r\nWest Hume, Kansas\r\n569\r\nWestdrexel, Kansas\r\n377\r\nWestmoreland, Kansas\r\n457\r\nWestphalia, Kansas\r\n489\r\nWest Topeka, Kansas\r\n256\r\nWetmore, Kansas\r\n866\r\nWheaton, Kansas\r\n396\r\nWhite City, Kansas\r\n349\r\nWhitecloud, Kansas\r\n595\r\nWhiting, Kansas\r\n873\r\nWilliamsburg, Kansas\r\n746\r\nWillis, Kansas\r\n547\r\nWilsey, Kansas\r\n497\r\nWilson, Kansas\r\n658\r\nWinchester, Kansas\r\n774\r\nWinona, Kansas\r\n846\r\nWoodbine, Kansas\r\n257\r\nWoodruff, Kansas\r\n653\r\nWoodston, Kansas\r\n994\r\nZurich, Kansas\r\n662\r\n\u00035Unknown prefix code (913) - Kansas\r\n"
  },
  {
    "path": "install/regions/regions.914",
    "content": "Amenia, New York\r\n373\r\nAndes, New York\r\n676\r\nArmonk Village, New York\r\n273\r\n765\r\nBarryville, New York\r\n557\r\nBeacon, New York\r\n831\r\n838\r\n892\r\n894\r\n896\r\n897\r\nBedford Village, New York\r\n234\r\nBirchwood, New York\r\n248\r\nBloomingbridge, New York\r\n733\r\nBrewster, New York\r\n278\r\n279\r\nCallicoon, New York\r\n887\r\nCarmel, New York\r\n225\r\n228\r\nChappaqua, New York\r\n238\r\nChester, New York\r\n469\r\nClintncors, New York\r\n266\r\nClintondale, New York\r\n883\r\nColdspring, New York\r\n265\r\nCongers, New York\r\n261\r\n267\r\n268\r\nCornwall, New York\r\n534\r\nCroton Hudson, New York\r\n271\r\nCrotonfall, New York\r\n276\r\n277\r\nDover Pls, New York\r\n877\r\nEllenville, New York\r\n647\r\nEsopus, New York\r\n384\r\nFallsburg, New York\r\n434\r\n436\r\nFleischmans, New York\r\n254\r\nFlorida, New York\r\n651\r\nGarrison, New York\r\n424\r\nGoshen, New York\r\n294\r\nGrahamsville, New York\r\n985\r\nGreenwood Lake, New York\r\n477\r\nHaverstraw, New York\r\n429\r\n786\r\n942\r\n947\r\nHigh Falls, New York\r\n687\r\nHighland, New York\r\n691\r\nHighland Falls, New York\r\n446\r\n938\r\nHighland Mills, New York\r\n928\r\nHopewell Junction, New York\r\n221\r\n223\r\n226\r\n227\r\nHyde Park, New York\r\n229\r\nJeffersnville, New York\r\n482\r\nKatonah, New York\r\n232\r\n233\r\n766\r\n767\r\nKerhonkson, New York\r\n626\r\nKingston, New York\r\n331\r\n334\r\n336\r\n338\r\n339\r\n382\r\n383\r\n385\r\n388\r\n389\r\nLakeland, New York\r\n526\r\n528\r\nLewisboro, New York\r\n533\r\nLiberty, New York\r\n292\r\n295\r\nLivington Manor, New York\r\n439\r\nLake Huntington, New York\r\n932\r\nMahopac, New York\r\n621\r\n628\r\nMargaretville, New York\r\n586\r\nMarlboro, New York\r\n236\r\nMaybrook, New York\r\n427\r\nMiddleton 1, New York\r\n283\r\n341\r\n342\r\n343\r\n344\r\n346\r\n355\r\n374\r\n386\r\n692\r\n695\r\nMillbrook, New York\r\n677\r\nMilton, New York\r\n795\r\nMonroe, New York\r\n774\r\n782\r\n783\r\nMontgomery, New York\r\n457\r\nMonticello, New York\r\n791\r\n794\r\n796\r\n799\r\nMount Kisco, New York\r\n241\r\n242\r\n244\r\n666\r\nNanuet, New York\r\n623\r\n624\r\n627\r\nNarrowsburg, New York\r\n252\r\nNew City, New York\r\n634\r\n638\r\n639\r\nNew Paltz, New York\r\n255\r\n256\r\n257\r\nNewburgh, New York\r\n542\r\n543\r\n561\r\n562\r\n563\r\n564\r\n565\r\n566\r\n567\r\n569\r\n879\r\nNorthclove, New York\r\n442\r\n724\r\nNorth Salem, New York\r\n669\r\nNyack, New York\r\n348\r\n353\r\n358\r\nOssining, New York\r\n762\r\n923\r\n941\r\n944\r\n945\r\nPatterson, New York\r\n878\r\nPawling, New York\r\n855\r\nPearl River, New York\r\n620\r\n732\r\n735\r\nPeekskill, New York\r\n734\r\n736\r\n737\r\n739\r\nPhoenicia, New York\r\n688\r\nPiermont, New York\r\n359\r\n365\r\n398\r\nPine Island, New York\r\n258\r\nPinebush, New York\r\n744\r\nPleasantville, New York\r\n741\r\n742\r\n745\r\n747\r\n769\r\n772\r\n773\r\nPleasant Valley, New York\r\n635\r\nPort Chester, New York\r\n235\r\n237\r\n251\r\n253\r\n282\r\n285\r\n286\r\n287\r\n288\r\n289\r\n321\r\n328\r\n332\r\n333\r\n335\r\n337\r\n345\r\n347\r\n375\r\n376\r\n378\r\n381\r\n390\r\n394\r\n395\r\n397\r\n422\r\n423\r\n428\r\n472\r\n476\r\n478\r\n523\r\n524\r\n576\r\n591\r\n592\r\n631\r\n632\r\n633\r\n636\r\n641\r\n642\r\n643\r\n644\r\n654\r\n662\r\n664\r\n665\r\n667\r\n668\r\n674\r\n681\r\n682\r\n683\r\n684\r\n686\r\n693\r\n694\r\n696\r\n697\r\n698\r\n699\r\n721\r\n723\r\n725\r\n738\r\n749\r\n761\r\n768\r\n771\r\n776\r\n779\r\n784\r\n789\r\n792\r\n793\r\n833\r\n834\r\n835\r\n899\r\n921\r\n925\r\n933\r\n934\r\n935\r\n937\r\n939\r\n946\r\n948\r\n949\r\n961\r\n963\r\n964\r\n965\r\n967\r\n968\r\n969\r\n976\r\n993\r\n997\r\nPort Jervis, New York\r\n754\r\n856\r\n858\r\nPoughkeepsie, New York\r\n920\r\n950\r\n977\r\n431\r\n432\r\n433\r\n435\r\n437\r\n449\r\n451\r\n452\r\n453\r\n454\r\n455\r\n462\r\n463\r\n471\r\n473\r\n474\r\n485\r\n486\r\n540\r\n575\r\n797\r\n844\r\n890\r\nPoundridge, New York\r\n764\r\nRed Hook, New York\r\n752\r\n756\r\n757\r\n758\r\nRhinebeck, New York\r\n871\r\n876\r\nRosendale, New York\r\n658\r\nSaugerties, New York\r\n246\r\n247\r\nShokan, New York\r\n657\r\nSloatsburg, New York\r\n753\r\n759\r\nSouth Salem, New York\r\n763\r\nSpring Valley, New York\r\n352\r\n354\r\n356\r\n362\r\n364\r\n425\r\n426\r\n573\r\n574\r\n577\r\n578\r\n579\r\nStaatsburg, New York\r\n889\r\nStanfordville, New York\r\n868\r\nSuffern, New York\r\n357\r\n368\r\n369\r\nThompson Ridge, New York\r\n361\r\nTuxedo, New York\r\n351\r\nUnionville, New York\r\n726\r\nWalden, New York\r\n778\r\nWallkill, New York\r\n895\r\nWappng Falls, New York\r\n296\r\n297\r\n298\r\nWarwick, New York\r\n986\r\n987\r\nWashingtonville, New York\r\n496\r\nWestchester, New York\r\n281\r\n322\r\n366\r\n377\r\n379\r\n391\r\n393\r\n421\r\n448\r\n479\r\n546\r\n547\r\n558\r\n593\r\n637\r\n645\r\n646\r\n649\r\n663\r\n671\r\n672\r\n722\r\n775\r\n777\r\n785\r\n787\r\n951\r\n952\r\n966\r\n971\r\n972\r\n973\r\nWhite Lake, New York\r\n583\r\nWingdale, New York\r\n832\r\nWoodstock, New York\r\n679\r\nWurtsboro, New York\r\n888\r\nYorktown Heights, New York\r\n243\r\n245\r\n962\r\n\u00035Unknown prefix code (914) - New York\r\n"
  },
  {
    "path": "install/regions/regions.915",
    "content": "Abilene, Texas\r\n222\r\n668\r\n670\r\n671\r\n672\r\n673\r\n674\r\n675\r\n676\r\n677\r\n690\r\n691\r\n692\r\n695\r\n696\r\n698\r\n738\r\nAckerly, Texas\r\n353\r\nAlamito, Texas\r\n358\r\nAlbany, Texas\r\n762\r\nAlpine, Texas\r\n837\r\nAndrews, Texas\r\n523\r\n524\r\n823\r\nAnthony, Texas\r\n886\r\nBaird, Texas\r\n854\r\nBallinger, Texas\r\n365\r\nBalmorhea, Texas\r\n375\r\nBangs, Texas\r\n752\r\nBarnhart, Texas\r\n876\r\nBend, Texas\r\n628\r\nBig Canyon, Texas\r\n753\r\nBig Lake, Texas\r\n884\r\nBig Spring, Texas\r\n263\r\n264\r\n267\r\n270\r\nBig Valley, Texas\r\n938\r\nBigbdnatpark, Texas\r\n477\r\nBlackwell, Texas\r\n282\r\nBlanket, Texas\r\n748\r\nBradshaw, Texas\r\n767\r\nBrady, Texas\r\n597\r\nBronte, Texas\r\n473\r\nBrownwood, Texas\r\n642\r\n643\r\n647\r\n649\r\nBuffalo Gap, Texas\r\n572\r\nBurkett, Texas\r\n624\r\nCalamity Creek, Texas\r\n364\r\nCanutillo, Texas\r\n874\r\n877\r\nCarlsbad, Texas\r\n465\r\nCherokee, Texas\r\n622\r\nChristoval, Texas\r\n896\r\nClint, Texas\r\n851\r\nClyde, Texas\r\n893\r\nCoahoma, Texas\r\n394\r\nColeman, Texas\r\n625\r\nColorado City, Texas\r\n728\r\nComanche, Texas\r\n356\r\nComstock, Texas\r\n292\r\nCoyanosa, Texas\r\n343\r\nCrane, Texas\r\n558\r\nCrews, Texas\r\n723\r\nDell City, Texas\r\n964\r\nDesert Haven, Texas\r\n988\r\nDoole, Texas\r\n483\r\nEarly, Texas\r\n646\r\nEast Hobbs, Texas\r\n297\r\nEden, Texas\r\n869\r\nEl Paso, Texas\r\n220\r\n521\r\n525\r\n526\r\n531\r\n532\r\n533\r\n534\r\n538\r\n539\r\n540\r\n541\r\n542\r\n543\r\n544\r\n545\r\n546\r\n549\r\n562\r\n564\r\n565\r\n566\r\n568\r\n569\r\n577\r\n578\r\n581\r\n584\r\n585\r\n590\r\n591\r\n592\r\n593\r\n594\r\n595\r\n598\r\n599\r\n678\r\n680\r\n747\r\n751\r\n755\r\n757\r\n771\r\n772\r\n774\r\n775\r\n778\r\n779\r\n821\r\n822\r\n833\r\n852\r\n855\r\n857\r\n858\r\n859\r\n860\r\n880\r\nEl Dorado, Texas\r\n853\r\nEola, Texas\r\n469\r\nFabens, Texas\r\n764\r\nForsan, Texas\r\n457\r\nFort Davis, Texas\r\n426\r\nFrankel City, Texas\r\n596\r\nFredonia, Texas\r\n429\r\nFort Hancock, Texas\r\n769\r\nFort Stockton, Texas\r\n336\r\nGail, Texas\r\n856\r\nGarden City, Texas\r\n354\r\nGoldsmith, Texas\r\n827\r\nGoldthwait, Texas\r\n648\r\nGrand Falls, Texas\r\n547\r\nGuadalupe Park, Texas\r\n828\r\nGustine, Texas\r\n667\r\nHamby, Texas\r\n548\r\nHamlin, Texas\r\n576\r\nHawley, Texas\r\n537\r\nHeath Canyon, Texas\r\n376\r\nHermleigh, Texas\r\n863\r\nImperial, Texas\r\n536\r\nIraan, Texas\r\n639\r\nJal, Texas\r\n295\r\nJunction, Texas\r\n446\r\nKatemcy, Texas\r\n258\r\nKermit, Texas\r\n586\r\nKingsland, Texas\r\n388\r\nLajitas, Texas\r\n424\r\nLake Brownwood, Texas\r\n784\r\nLake Coleman, Texas\r\n382\r\nLangtry, Texas\r\n291\r\nLawn, Texas\r\n583\r\nLenorah, Texas\r\n459\r\nLlano, Texas\r\n247\r\nLocker, Texas\r\n623\r\nLohn, Texas\r\n344\r\nLomax, Texas\r\n398\r\nLondon, Texas\r\n475\r\nLoraine, Texas\r\n737\r\nLueders, Texas\r\n228\r\nLuther, Texas\r\n399\r\nMarathon, Texas\r\n386\r\nMarfa, Texas\r\n729\r\nMaryneal, Texas\r\n288\r\nMason, Texas\r\n347\r\nMcCamey, Texas\r\n652\r\nMcCaulley, Texas\r\n962\r\nMelvin, Texas\r\n286\r\nMenard, Texas\r\n396\r\nMentone, Texas\r\n377\r\nMercury, Texas\r\n463\r\nMerkel, Texas\r\n928\r\nMertzon, Texas\r\n835\r\nMidkiff, Texas\r\n535\r\nMidland, Texas\r\n221\r\n520\r\n522\r\n559\r\n560\r\n570\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n694\r\n697\r\n699\r\n951\r\n954\r\nMile High, Texas\r\n986\r\nMiles, Texas\r\n468\r\nMonahans, Texas\r\n230\r\n556\r\n940\r\n943\r\nMoran, Texas\r\n945\r\nMozelle, Texas\r\n357\r\nMullen, Texas\r\n985\r\nNewburg, Texas\r\n885\r\nNolan, Texas\r\n798\r\nNoodle, Texas\r\n736\r\nNorton, Texas\r\n786\r\nNubia, Texas\r\n846\r\nOdessa, Texas\r\n332\r\n333\r\n334\r\n335\r\n337\r\n362\r\n363\r\n366\r\n367\r\n368\r\n381\r\n385\r\n530\r\n550\r\n552\r\n580\r\n582\r\n777\r\nOrla, Texas\r\n273\r\nOzona, Texas\r\n392\r\nPaint Rock, Texas\r\n732\r\nPecos, Texas\r\n445\r\n447\r\n844\r\nPontotoc, Texas\r\n251\r\nPotosi, Texas\r\n529\r\nPresidio, Texas\r\n229\r\nPriddy, Texas\r\n966\r\nPutnam, Texas\r\n662\r\nPyote, Texas\r\n389\r\nRankin, Texas\r\n693\r\nRedford, Texas\r\n384\r\nRichland Springs, Texas\r\n452\r\nRobert Lee, Texas\r\n453\r\nRoby, Texas\r\n776\r\nRochelle, Texas\r\n243\r\nRockwood, Texas\r\n785\r\nRoscoe, Texas\r\n766\r\nRotan, Texas\r\n735\r\nRowena, Texas\r\n442\r\nSan Angelo, Texas\r\n650\r\n651\r\n653\r\n654\r\n655\r\n656\r\n657\r\n658\r\n942\r\n944\r\n947\r\n949\r\nSan Saba, Texas\r\n372\r\nSand Springs, Texas\r\n393\r\nSanderson, Texas\r\n345\r\nSanta Anna, Texas\r\n348\r\nSeminole, Texas\r\n758\r\nSheffield, Texas\r\n836\r\nSierra Blanc, Texas\r\n369\r\nSix Shooter, Texas\r\n395\r\nSnyder, Texas\r\n573\r\n574\r\n575\r\nSonora, Texas\r\n387\r\nStamford, Texas\r\n773\r\nStanton, Texas\r\n756\r\nStar, Texas\r\n948\r\nSterling City, Texas\r\n378\r\nSaint Lawrence, Texas\r\n397\r\nStreeter, Texas\r\n265\r\nSweetwater, Texas\r\n235\r\n236\r\nSylvester, Texas\r\n993\r\nTerlingua, Texas\r\n371\r\nTerminal, Texas\r\n553\r\n557\r\n561\r\n563\r\n567\r\nTow, Texas\r\n379\r\nToyah, Texas\r\n259\r\nTrent, Texas\r\n862\r\nTuscola, Texas\r\n554\r\nValentine, Texas\r\n467\r\nValera, Texas\r\n636\r\nVan Horn, Texas\r\n283\r\n284\r\nVincent, Texas\r\n965\r\nVoca, Texas\r\n239\r\nWest Stanton, Texas\r\n458\r\nWater Valley, Texas\r\n484\r\nWestbrook, Texas\r\n644\r\nWingate, Texas\r\n743\r\nWink, Texas\r\n527\r\nWinters, Texas\r\n754\r\nZephyr, Texas\r\n739\r\n\u00035Unknown prefix code (915) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.916",
    "content": "Adin, California\r\n299\r\nAlleghany, California\r\n287\r\nAlpine, California\r\n694\r\nAlta, California\r\n389\r\nAlturas, California\r\n233\r\nAnderson, California\r\n365\r\n378\r\nArbuckle, California\r\n476\r\nAuburn, California\r\n269\r\n823\r\n878\r\n885\r\n887\r\n888\r\n889\r\nBangor, California\r\n679\r\nBerry Creek, California\r\n589\r\nBieber, California\r\n294\r\nBiggs, California\r\n868\r\nBlairsden, California\r\n836\r\nBrockway, California\r\n546\r\nBurney, California\r\n335\r\nButte City, California\r\n982\r\nCamino, California\r\n647\r\nCamptonville, California\r\n288\r\nCarmichael, California\r\n489\r\nCedarville, California\r\n279\r\nChallenge, California\r\n675\r\nChester, California\r\n258\r\n259\r\nChicago, California\r\n520\r\n521\r\n894\r\nChico, California\r\n342\r\n343\r\n345\r\n826\r\n891\r\n892\r\n893\r\n895\r\n896\r\n898\r\n899\r\nColeville, California\r\n495\r\nColfax, California\r\n346\r\nColusa, California\r\n458\r\nCorning, California\r\n824\r\nCottonwood, California\r\n347\r\nCourtland, California\r\n744\r\n775\r\nDavis, California\r\n752\r\n753\r\n754\r\n756\r\n757\r\n758\r\n759\r\nDixon, California\r\n678\r\nDorris, California\r\n397\r\nDownieville, California\r\n289\r\n862\r\nDunnigan, California\r\n724\r\nDunsmuir, California\r\n235\r\nEagle Lake, California\r\n825\r\nElk Creek, California\r\n682\r\n684\r\n685\r\n686\r\n687\r\n688\r\n689\r\n968\r\nElk Grove, California\r\n681\r\n683\r\nEsparto, California\r\n787\r\nEtna, California\r\n467\r\nFair Oaks, California\r\n531\r\n535\r\n537\r\n539\r\n765\r\n768\r\n847\r\n863\r\n867\r\n961\r\n962\r\n965\r\n966\r\n967\r\n969\r\nFall River Mills, California\r\n336\r\nFolsom, California\r\n351\r\n353\r\n355\r\n356\r\n933\r\n939\r\n983\r\n984\r\n985\r\n986\r\n987\r\n988\r\n989\r\nForest Hill, California\r\n367\r\nFort Jones, California\r\n468\r\nFrench Gulch, California\r\n359\r\nGazelle, California\r\n435\r\nGeorgetown, California\r\n333\r\nGerber, California\r\n385\r\nGrass Valley, California\r\n268\r\n272\r\n273\r\n274\r\n432\r\n477\r\nGreenville, California\r\n284\r\nGrenada, California\r\n436\r\nGridley, California\r\n846\r\nGrimes, California\r\n437\r\nGuinda, California\r\n796\r\nHamburg, California\r\n496\r\nHappy Camp, California\r\n493\r\nHayfork, California\r\n628\r\nHerlong, California\r\n827\r\nHomewood, California\r\n525\r\nHoopa, California\r\n625\r\nHornbrook, California\r\n475\r\nIsleton, California\r\n777\r\nJanesville, California\r\n253\r\n254\r\nKeddie, California\r\n281\r\nKnightslog, California\r\n735\r\nLake Almanor, California\r\n596\r\nLewiston, California\r\n778\r\nLincoln, California\r\n645\r\nLive Oak, California\r\n695\r\nLos Molinos, California\r\n384\r\nLoyalton, California\r\n993\r\nMacDoel, California\r\n398\r\nMarysville, California\r\n634\r\n671\r\n673\r\n674\r\n741\r\n742\r\n743\r\n747\r\n755\r\n788\r\nMaxwell, California\r\n438\r\nMc Cloud, California\r\n964\r\nMeadowview, California\r\n665\r\nMeridian, California\r\n696\r\nMichiganbr, California\r\n354\r\nMillville, California\r\n547\r\n549\r\nMineral, California\r\n595\r\nMinersville, California\r\n286\r\nMontague, California\r\n459\r\nMontgomery Creek, California\r\n337\r\nMount Shasta, California\r\n926\r\nNevada City, California\r\n265\r\n478\r\nNewell, California\r\n664\r\nNew Pine Creek, California\r\n946\r\nNicolaus, California\r\n656\r\nNorth San Juan, California\r\n292\r\nNorth Yuba, California\r\n692\r\nOak Knoll, California\r\n465\r\nOak Run, California\r\n472\r\nOlinda, California\r\n357\r\n396\r\nOrland, California\r\n865\r\nOrleans, California\r\n627\r\nOroville, California\r\n532\r\n533\r\n534\r\n538\r\nParadise, California\r\n872\r\n873\r\n876\r\n877\r\nPaskenta, California\r\n833\r\nPaynes Creek, California\r\n597\r\nPlacerville West, California\r\n621\r\n622\r\n626\r\n642\r\n644\r\nPlacerville, California\r\n293\r\nPlatina, California\r\n352\r\nPleasant Grove, California\r\n655\r\nPortola, California\r\n832\r\nPrinceton, California\r\n439\r\nQuincy, California\r\n283\r\nRancho T, California\r\n585\r\nRed Bluff, California\r\n527\r\n529\r\n840\r\nRedding, California\r\n221\r\n222\r\n223\r\n224\r\n225\r\n241\r\n243\r\n244\r\n245\r\n246\r\n275\r\n524\r\n598\r\n949\r\n953\r\nRichvale, California\r\n882\r\nRio Linda, California\r\n991\r\n992\r\nRobbins, California\r\n738\r\nRoseville, California\r\n721\r\n722\r\n723\r\n725\r\n726\r\n727\r\n728\r\n729\r\n745\r\n746\r\n771\r\n773\r\n774\r\n781\r\n782\r\n783\r\n784\r\n785\r\n786\r\n789\r\n791\r\n797\r\nSacramento, California\r\n227\r\n228\r\n255\r\n262\r\n263\r\n264\r\n277\r\n278\r\n296\r\n321\r\n322\r\n323\r\n324\r\n325\r\n326\r\n327\r\n328\r\n329\r\n361\r\n362\r\n363\r\n364\r\n366\r\n369\r\n371\r\n372\r\n373\r\n374\r\n375\r\n381\r\n383\r\n386\r\n388\r\n391\r\n392\r\n393\r\n394\r\n395\r\n399\r\n421\r\n422\r\n423\r\n424\r\n425\r\n427\r\n428\r\n429\r\n440\r\n441\r\n442\r\n443\r\n444\r\n445\r\n446\r\n447\r\n448\r\n449\r\n451\r\n452\r\n453\r\n454\r\n455\r\n456\r\n457\r\n464\r\n498\r\n522\r\n523\r\n551\r\n552\r\n553\r\n556\r\n557\r\n558\r\n568\r\n591\r\n592\r\n593\r\n631\r\n635\r\n636\r\n638\r\n653\r\n654\r\n657\r\n731\r\n732\r\n733\r\n734\r\n736\r\n739\r\n761\r\n762\r\n763\r\n764\r\n766\r\n769\r\n848\r\n849\r\n851\r\n852\r\n853\r\n854\r\n855\r\n858\r\n948\r\n951\r\n952\r\n954\r\n955\r\n956\r\n957\r\n976\r\n331\r\n332\r\n334\r\n338\r\n339\r\n344\r\n348\r\n349\r\n368\r\n382\r\n387\r\n433\r\n480\r\n481\r\n482\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n499\r\n564\r\n565\r\n566\r\n567\r\n574\r\n575\r\n599\r\n641\r\n643\r\n646\r\n648\r\n649\r\n737\r\n856\r\n920\r\n921\r\n922\r\n923\r\n924\r\n925\r\n927\r\n928\r\n929\r\n942\r\n944\r\n971\r\n972\r\n973\r\n974\r\n978\r\n979\r\n228\r\nSawyers Bar, California\r\n462\r\nShasta Lake, California\r\n238\r\nShingleton, California\r\n474\r\nShingle Springs, California\r\n672\r\n676\r\n677\r\nSierraville, California\r\n994\r\nSmartsville, California\r\n639\r\nSouth Placer, California\r\n624\r\n632\r\n652\r\n663\r\nSoda Springs, California\r\n426\r\nSomes Bar, California\r\n469\r\nSouth Tahoe, California\r\n541\r\n542\r\n544\r\n573\r\n577\r\n659\r\nStonyford, California\r\n963\r\nSusanville, California\r\n251\r\n257\r\nTahoe City, California\r\n581\r\n583\r\nTrinity Center, California\r\n266\r\nTruckee, California\r\n562\r\n582\r\n587\r\nTulelake, California\r\n667\r\nVerdi, California\r\n479\r\nVina, California\r\n839\r\nWalnut Grove, California\r\n776\r\nWeaverville, California\r\n623\r\nWeed, California\r\n938\r\nWeimar, California\r\n637\r\nWestwood, California\r\n256\r\nWheatland, California\r\n633\r\nWilliams, California\r\n473\r\nWillow Creek, California\r\n629\r\nWillows, California\r\n934\r\nWinters, California\r\n795\r\nWoodland, California\r\n661\r\n662\r\n666\r\n668\r\nYreka, California\r\n841\r\n842\r\n\u00035Unknown prefix code (916) - California\r\n"
  },
  {
    "path": "install/regions/regions.917",
    "content": "Sierraville, California\r\n205\r\n233\r\n240\r\n245\r\n246\r\n249\r\n253\r\n269\r\n270\r\n271\r\n278\r\n282\r\n284\r\n287\r\n288\r\n290\r\n298\r\n313\r\n321\r\n323\r\n331\r\n333\r\n336\r\n350\r\n354\r\n356\r\n360\r\n372\r\n375\r\n377\r\n384\r\n390\r\n404\r\n424\r\n426\r\n429\r\n433\r\n451\r\n458\r\n462\r\n467\r\n469\r\n471\r\n473\r\n483\r\n486\r\n487\r\n489\r\n491\r\n520\r\n539\r\n552\r\n556\r\n610\r\n616\r\n643\r\n694\r\n706\r\n712\r\n713\r\n726\r\n728\r\n729\r\n738\r\n739\r\n753\r\n754\r\n755\r\n758\r\n759\r\n763\r\n766\r\n784\r\n785\r\n786\r\n787\r\n788\r\n795\r\n812\r\n813\r\n844\r\n845\r\n846\r\n847\r\n851\r\n855\r\n856\r\n857\r\n858\r\n859\r\n865\r\n866\r\n867\r\n869\r\n871\r\n872\r\n873\r\n874\r\n879\r\n882\r\n896\r\n897\r\n899\r\n912\r\n919\r\n924\r\n925\r\n928\r\n934\r\n937\r\n943\r\n952\r\n953\r\n965\r\n974\r\n980\r\n981\r\n984\r\n986\r\n987\r\n988\r\n989\r\n993\r\n994\r\n996\r\n997\r\n998\r\n999\r\n\u00035Unknown prefix code (917) - California\r\n"
  },
  {
    "path": "install/regions/regions.918",
    "content": "Adair, Oklahoma\r\n785\r\nAfton, Oklahoma\r\n257\r\nAgra, Oklahoma\r\n375\r\nAlbion, Oklahoma\r\n563\r\nAlluwe, Oklahoma\r\n475\r\nArpelar, Oklahoma\r\n389\r\nAshland, Oklahoma\r\n867\r\nAvant, Oklahoma\r\n263\r\nBarnsdall, Oklahoma\r\n847\r\nBaron, Oklahoma\r\n778\r\nBartlesville, Oklahoma\r\n333\r\n335\r\n336\r\n337\r\n338\r\n641\r\n661\r\n662\r\nBeggs, Oklahoma\r\n267\r\nBig Cabin, Oklahoma\r\n783\r\nBixby, Oklahoma\r\n366\r\nBixby North, Oklahoma\r\n369\r\nBlackburn, Oklahoma\r\n538\r\nBlue Jacket, Oklahoma\r\n784\r\nBokoshe, Oklahoma\r\n969\r\nBoley, Oklahoma\r\n667\r\nBoynton, Oklahoma\r\n472\r\nBraggs, Oklahoma\r\n487\r\nBristow, Oklahoma\r\n367\r\nBroken Arrow, Oklahoma\r\n250\r\n251\r\n252\r\n254\r\n258\r\n259\r\n355\r\n357\r\n451\r\n455\r\n459\r\nBuffalo Valley, Oklahoma\r\n522\r\nBurbank, Oklahoma\r\n648\r\nCameron, Oklahoma\r\n654\r\nCanadian, Oklahoma\r\n339\r\nCastle, Oklahoma\r\n668\r\nCatoosa, Oklahoma\r\n266\r\nCedar Crest, Oklahoma\r\n386\r\nCedars, Oklahoma\r\n626\r\nChecotah, Oklahoma\r\n473\r\nChelsea, Oklahoma\r\n789\r\nChouteau, Oklahoma\r\n476\r\nClaremore, Oklahoma\r\n341\r\n342\r\n343\r\nClayton, Oklahoma\r\n569\r\nCleveland, Oklahoma\r\n358\r\nColcord, Oklahoma\r\n326\r\nCollinsville, Oklahoma\r\n371\r\nCommerce, Oklahoma\r\n675\r\nCopan, Oklahoma\r\n532\r\nCouncil Hill, Oklahoma\r\n474\r\nCoweta, Oklahoma\r\n486\r\nCrowder, Oklahoma\r\n334\r\nCushing, Oklahoma\r\n225\r\nDavenport, Oklahoma\r\n377\r\nDelaware, Oklahoma\r\n467\r\nDepew, Oklahoma\r\n324\r\nDewey, Oklahoma\r\n534\r\nDisney, Oklahoma\r\n435\r\nDrumright, Oklahoma\r\n352\r\nDustin, Oklahoma\r\n656\r\nEnterprise, Oklahoma\r\n799\r\nEufaula, Oklahoma\r\n689\r\nFairfax, Oklahoma\r\n642\r\nFairland, Oklahoma\r\n676\r\nFanshawe, Oklahoma\r\n659\r\nFlint, Oklahoma\r\n597\r\nForaker, Oklahoma\r\n722\r\nFort Gibson, Oklahoma\r\n478\r\nGore, Oklahoma\r\n489\r\nGrainola, Oklahoma\r\n433\r\nGrove, Oklahoma\r\n786\r\nHallett, Oklahoma\r\n356\r\nHanna, Oklahoma\r\n657\r\nHartshorne, Oklahoma\r\n297\r\nHaskell, Oklahoma\r\n482\r\nHeavener, Oklahoma\r\n653\r\nHenryetta, Oklahoma\r\n652\r\nHitchita, Oklahoma\r\n466\r\nHominy, Oklahoma\r\n885\r\nIndianola, Oklahoma\r\n823\r\nInola, Oklahoma\r\n543\r\nJay, Oklahoma\r\n253\r\nJenks, Oklahoma\r\n291\r\n298\r\n299\r\nJennings, Oklahoma\r\n757\r\nKansas, Oklahoma\r\n868\r\nKeefeton, Oklahoma\r\n989\r\nKellyville, Oklahoma\r\n247\r\nKendrick, Oklahoma\r\n368\r\nKeota, Oklahoma\r\n966\r\nKetchum, Oklahoma\r\n782\r\nKeystone, Oklahoma\r\n243\r\nKiefer, Oklahoma\r\n321\r\n322\r\nKinta, Oklahoma\r\n768\r\nKiowa, Oklahoma\r\n432\r\nLeflore, Oklahoma\r\n753\r\nLenapah, Oklahoma\r\n468\r\nLocust Grove, Oklahoma\r\n479\r\nLongtown, Oklahoma\r\n452\r\nMannford, Oklahoma\r\n363\r\n865\r\nMaramec, Oklahoma\r\n454\r\nMcalester, Oklahoma\r\n421\r\n423\r\n424\r\n426\r\nMcCortain, Oklahoma\r\n945\r\nMiami, Oklahoma\r\n540\r\n542\r\nMoffett, Oklahoma\r\n875\r\nMonroehowe, Oklahoma\r\n658\r\nMorris, Oklahoma\r\n733\r\nMounds, Oklahoma\r\n827\r\nMuldrow, Oklahoma\r\n427\r\nMuse, Oklahoma\r\n651\r\nMuskogee, Oklahoma\r\n681\r\n682\r\n683\r\n684\r\n685\r\n686\r\n687\r\nNashoba, Oklahoma\r\n755\r\nNew Home, Oklahoma\r\n383\r\nNowata, Oklahoma\r\n273\r\nOchelata, Oklahoma\r\n535\r\nOglesby, Oklahoma\r\n545\r\nOilton, Oklahoma\r\n862\r\nOkemah, Oklahoma\r\n623\r\nOkmulgee, Oklahoma\r\n756\r\n758\r\nOologah, Oklahoma\r\n443\r\nOsage, Oklahoma\r\n354\r\nOwasso, Oklahoma\r\n272\r\n274\r\nPanama, Oklahoma\r\n963\r\nPawhuska, Oklahoma\r\n287\r\nPawnee, Oklahoma\r\n762\r\nPeggs, Oklahoma\r\n598\r\nPicher, Oklahoma\r\n673\r\nPocola, Oklahoma\r\n436\r\nPorter, Oklahoma\r\n483\r\nPorum, Oklahoma\r\n484\r\nPoteau, Oklahoma\r\n647\r\nPrue, Oklahoma\r\n242\r\nPryor, Oklahoma\r\n825\r\nQuapaw, Oklahoma\r\n674\r\nQuinton, Oklahoma\r\n469\r\nRalston, Oklahoma\r\n738\r\nRamona, Oklahoma\r\n536\r\nRed Oak, Oklahoma\r\n754\r\nRipley, Oklahoma\r\n372\r\nSalina, Oklahoma\r\n434\r\nSallisaw, Oklahoma\r\n775\r\n776\r\nSand Springs, Oklahoma\r\n241\r\n245\r\nSapulpa, Oklahoma\r\n224\r\n227\r\nSavanna, Oklahoma\r\n548\r\nScipio, Oklahoma\r\n826\r\nShidler, Oklahoma\r\n793\r\nSkedee, Oklahoma\r\n767\r\nSkiatook, Oklahoma\r\n396\r\nSnugharbor, Oklahoma\r\n462\r\nSouth Chetopa, Oklahoma\r\n233\r\nSouth Hewins, Oklahoma\r\n566\r\nSouth West, Oklahoma\r\n854\r\nSouth Bartlett, Oklahoma\r\n996\r\nSouth Coffeyville, Oklahoma\r\n255\r\n944\r\nSouth Edna, Oklahoma\r\n929\r\nSouth Caney, Oklahoma\r\n889\r\nSouth Elgin, Oklahoma\r\n349\r\nSparks, Oklahoma\r\n866\r\nSpavinaw, Oklahoma\r\n589\r\nSperry, Oklahoma\r\n288\r\nSpiro, Oklahoma\r\n962\r\nStigler, Oklahoma\r\n967\r\nStilwell, Oklahoma\r\n696\r\nStrang, Oklahoma\r\n593\r\nStroud, Oklahoma\r\n968\r\nStuart, Oklahoma\r\n546\r\nSummerfld, Oklahoma\r\n677\r\nTahlequah, Oklahoma\r\n456\r\n457\r\n458\r\n772\r\nTalala, Oklahoma\r\n275\r\nTalihina, Oklahoma\r\n567\r\nTiff City, Oklahoma\r\n985\r\nTryon, Oklahoma\r\n374\r\nTulsa, Oklahoma\r\n234\r\n262\r\n277\r\n292\r\n425\r\n428\r\n437\r\n438\r\n445\r\n446\r\n460\r\n477\r\n481\r\n488\r\n491\r\n492\r\n493\r\n494\r\n495\r\n496\r\n497\r\n551\r\n555\r\n560\r\n561\r\n579\r\n581\r\n582\r\n583\r\n584\r\n585\r\n586\r\n587\r\n588\r\n591\r\n592\r\n596\r\n599\r\n621\r\n622\r\n624\r\n625\r\n627\r\n628\r\n629\r\n631\r\n632\r\n633\r\n634\r\n636\r\n637\r\n638\r\n639\r\n645\r\n646\r\n660\r\n663\r\n664\r\n665\r\n669\r\n741\r\n742\r\n743\r\n744\r\n745\r\n746\r\n747\r\n748\r\n749\r\n831\r\n832\r\n833\r\n834\r\n835\r\n836\r\n838\r\n932\r\n936\r\n939\r\n976\r\nVian, Oklahoma\r\n773\r\nVinita, Oklahoma\r\n256\r\nWagoner, Oklahoma\r\n485\r\nWann, Oklahoma\r\n531\r\nWardville, Oklahoma\r\n874\r\nWarner, Oklahoma\r\n463\r\nWatts, Oklahoma\r\n422\r\nWebb City, Oklahoma\r\n765\r\nWebbers Falls, Oklahoma\r\n464\r\nWelch, Oklahoma\r\n788\r\nWest Seneca, Oklahoma\r\n666\r\nWestville, Oklahoma\r\n723\r\nWilburton, Oklahoma\r\n465\r\nWister, Oklahoma\r\n655\r\nWest Maysville, Oklahoma\r\n529\r\nWest Union Town, Oklahoma\r\n498\r\nWyandotte, Oklahoma\r\n678\r\nWynona, Oklahoma\r\n846\r\nYale, Oklahoma\r\n387\r\n\u00035Unknown prefix code (918) - Oklahoma\r\n"
  },
  {
    "path": "install/regions/regions.919",
    "content": "Abbottsburg, North Carolina\r\n648\r\nAcme, North Carolina\r\n655\r\nAdvance, North Carolina\r\n998\r\nAngier, North Carolina\r\n639\r\nApex, North Carolina\r\n303\r\n362\r\n387\r\nAsheboro, North Carolina\r\n625\r\n626\r\n629\r\nAtkinson, North Carolina\r\n283\r\nBadin Lake, North Carolina\r\n461\r\nBaldwin, North Carolina\r\n877\r\nBennett, North Carolina\r\n581\r\nBenson, North Carolina\r\n207\r\n820\r\n894\r\nBeulah, North Carolina\r\n352\r\nBeulaville, North Carolina\r\n298\r\nBiscoe, North Carolina\r\n428\r\nBladenboro, North Carolina\r\n863\r\nBlowing Spring, North Carolina\r\n845\r\nBolivia, North Carolina\r\n253\r\nBonlee, North Carolina\r\n837\r\nBoonville, North Carolina\r\n367\r\nBroadway, North Carolina\r\n258\r\nBrooks, North Carolina\r\n468\r\nBurgaw, North Carolina\r\n259\r\nBurlington, North Carolina\r\n222\r\n226\r\n227\r\n228\r\n229\r\n260\r\n263\r\n513\r\n570\r\n578\r\n584\r\nCary\u00031/\u00032Morrisville, North Carolina\r\n319\r\n380\r\n460\r\n467\r\n469\r\n481\r\n677\r\n851\r\nCastle Hyn, North Carolina\r\n675\r\nCenterville, North Carolina\r\n853\r\nChadbourn, North Carolina\r\n654\r\nChapel Hill, North Carolina\r\n216\r\n408\r\n914\r\n918\r\n929\r\n932\r\n933\r\n942\r\n962\r\n966\r\n967\r\n968\r\nClarkton, North Carolina\r\n647\r\nClayton, North Carolina\r\n550\r\n553\r\nClinton, North Carolina\r\n590\r\n592\r\nCoharie, North Carolina\r\n567\r\nColeridge, North Carolina\r\n879\r\nCreedmoor\u00031/\u00032Butner, North Carolina\r\n528\r\n575\r\nCreston, North Carolina\r\n385\r\nCypress Creek, North Carolina\r\n588\r\nDanbury, North Carolina\r\n593\r\nDillon, North Carolina\r\n896\r\nDobson, North Carolina\r\n386\r\nDunn, North Carolina\r\n891\r\n892\r\n897\r\n980\r\nDurham, North Carolina\r\n220\r\n286\r\n309\r\n361\r\n382\r\n383\r\n405\r\n408\r\n409\r\n416\r\n419\r\n470\r\n471\r\n477\r\n479\r\n489\r\n490\r\n493\r\n530\r\n544\r\n596\r\n598\r\n613\r\n620\r\n660\r\n681\r\n682\r\n683\r\n684\r\n687\r\n688\r\n970\r\nEast Bend, North Carolina\r\n699\r\nEden, North Carolina\r\n623\r\n627\r\nElizabeth City, North Carolina\r\n862\r\nElkin, North Carolina\r\n835\r\nEllerbe, North Carolina\r\n652\r\nFair Bluff, North Carolina\r\n649\r\nFairmont, North Carolina\r\n628\r\nFaison, North Carolina\r\n267\r\nFarmer, North Carolina\r\n857\r\nFayetteville, North Carolina\r\n391\r\n394\r\n424\r\n425\r\n436\r\n483\r\n484\r\n485\r\n486\r\n487\r\n488\r\n624\r\n630\r\n678\r\n822\r\n864\r\n867\r\n868\r\nForbush, North Carolina\r\n961\r\nFour Oaks, North Carolina\r\n963\r\nFranklinton, North Carolina\r\n494\r\nFremont, North Carolina\r\n242\r\nFuquay-Varina, North Carolina\r\n552\r\n557\r\nGarland, North Carolina\r\n529\r\nGatewood, North Carolina\r\n388\r\nGibson, North Carolina\r\n268\r\nGlade Creek, North Carolina\r\n657\r\nGoldsboro, North Carolina\r\n580\r\n705\r\n731\r\n734\r\n735\r\n736\r\n751\r\n778\r\nGoldston, North Carolina\r\n898\r\nGrantham, North Carolina\r\n689\r\nGreensboro, North Carolina\r\n218\r\n271\r\n272\r\n273\r\n274\r\n275\r\n279\r\n282\r\n288\r\n299\r\n337\r\n370\r\n373\r\n375\r\n378\r\n379\r\n545\r\n547\r\n574\r\n621\r\n632\r\n665\r\n668\r\n674\r\n680\r\n691\r\n697\r\n698\r\n852\r\n854\r\n855\r\nHamlet, North Carolina\r\n582\r\nHays, North Carolina\r\n696\r\nHerring, North Carolina\r\n564\r\nHigh Point, North Carolina\r\n841\r\n861\r\n869\r\n882\r\n883\r\n884\r\n885\r\n886\r\n887\r\n888\r\n889\r\nHillsborough, North Carolina\r\n644\r\n732\r\nHolden Beach, North Carolina\r\n842\r\nJacksonville, North Carolina\r\n219\r\n340\r\n347\r\n389\r\n577\r\n938\r\nJulian, North Carolina\r\n685\r\nKelly, North Carolina\r\n669\r\nKenansville, North Carolina\r\n296\r\nKenly, North Carolina\r\n284\r\nKernersville, North Carolina\r\n993\r\nKimesville, North Carolina\r\n565\r\nKing, North Carolina\r\n983\r\nKnightdale, North Carolina\r\n217\r\n266\r\nLansing, North Carolina\r\n384\r\nLaurel Hill, North Carolina\r\n462\r\nLaurinburg, North Carolina\r\n276\r\n277\r\nLevelcross, North Carolina\r\n374\r\nLewisville, North Carolina\r\n945\r\nLiberty, North Carolina\r\n622\r\nLillington, North Carolina\r\n893\r\nLisbon, North Carolina\r\n645\r\nLake Waccamaw, North Carolina\r\n646\r\nLomax, North Carolina\r\n957\r\nLong Beach, North Carolina\r\n278\r\nLongwood, North Carolina\r\n287\r\nLouisburg, North Carolina\r\n496\r\nLumberton, North Carolina\r\n738\r\n739\r\nMadison, North Carolina\r\n427\r\n548\r\nMaxton, North Carolina\r\n844\r\nMaysville, North Carolina\r\n743\r\nMebane, North Carolina\r\n563\r\nMonticello, North Carolina\r\n656\r\nMount Airy, North Carolina\r\n786\r\n789\r\nMount Olive, North Carolina\r\n658\r\nMount Gilead, North Carolina\r\n439\r\nMulberry, North Carolina\r\n670\r\nNathan Creek, North Carolina\r\n982\r\nNewton Grove, North Carolina\r\n594\r\nNorth Wilkeboro, North Carolina\r\n651\r\n667\r\n838\r\nOldtown, North Carolina\r\n922\r\nOlivia, North Carolina\r\n499\r\nOxford, North Carolina\r\n690\r\n693\r\nParkton, North Carolina\r\n858\r\nPilot Mount, North Carolina\r\n368\r\nPine Bluff, North Carolina\r\n281\r\nPinehurst, North Carolina\r\n215\r\n295\r\nPisgah, North Carolina\r\n381\r\nPittsboro, North Carolina\r\n542\r\nPrinceton, North Carolina\r\n936\r\nProspect Hill, North Carolina\r\n562\r\nQuaker Gap, North Carolina\r\n994\r\nRaeford, North Carolina\r\n875\r\nRaleigh, North Carolina\r\n210\r\n212\r\n231\r\n233\r\n250\r\n280\r\n301\r\n302\r\n306\r\n414\r\n420\r\n501\r\n505\r\n508\r\n510\r\n512\r\n515\r\n516\r\n518\r\n546\r\n565\r\n571\r\n602\r\n604\r\n606\r\n608\r\n612\r\n614\r\n662\r\n664\r\n676\r\n713\r\n715\r\n733\r\n737\r\n740\r\n743\r\n755\r\n772\r\n779\r\n781\r\n782\r\n783\r\n787\r\n790\r\n801\r\n821\r\n828\r\n829\r\n831\r\n832\r\n833\r\n834\r\n836\r\n839\r\n846\r\n847\r\n848\r\n850\r\n851\r\n856\r\n859\r\n860\r\n870\r\n872\r\n876\r\n878\r\n880\r\n881\r\n890\r\n899\r\n906\r\n954\r\n971\r\n976\r\n981\r\nRaleigh\u00031/\u00032Durham Airport, North Carolina\r\n840\r\nRandleman, North Carolina\r\n495\r\n498\r\nResearch Triangle Park, North Carolina\r\n248\r\n254\r\n315\r\n406\r\n506\r\n517\r\n541\r\n543\r\n549\r\n558\r\n560\r\n905\r\n941\r\n956\r\n990\r\n991\r\n992\r\nRed Brush, North Carolina\r\n320\r\nRedsprings, North Carolina\r\n843\r\nReidsville, North Carolina\r\n342\r\n349\r\n951\r\nRichlands, North Carolina\r\n324\r\nRoaring Gap, North Carolina\r\n363\r\nRockingham, North Carolina\r\n895\r\n997\r\nRose Hill, North Carolina\r\n289\r\nRowland, North Carolina\r\n422\r\nRoxboro, North Carolina\r\n597\r\n599\r\nRural Hall, North Carolina\r\n969\r\nSandy Ridge, North Carolina\r\n871\r\nSaxapahaw, North Carolina\r\n376\r\nScotts Hill, North Carolina\r\n270\r\n686\r\nScottville, North Carolina\r\n359\r\nSeagrove, North Carolina\r\n873\r\nSeaside, North Carolina\r\n579\r\nSelma, North Carolina\r\n202\r\n965\r\nShoals, North Carolina\r\n325\r\nSiler City, North Carolina\r\n663\r\n742\r\nSmithfield, North Carolina\r\n915\r\n934\r\n989\r\nSnead Ferry, North Carolina\r\n327\r\nSouth River, North Carolina\r\n531\r\nSouthern Pines, North Carolina\r\n692\r\n695\r\nSparta, North Carolina\r\n372\r\nSaint Pauls, North Carolina\r\n865\r\nStanleyville, North Carolina\r\n377\r\nState Road, North Carolina\r\n874\r\nStoneville, North Carolina\r\n573\r\nSummerfield, North Carolina\r\n643\r\nSwansboro, North Carolina\r\n326\r\nTabor City, North Carolina\r\n653\r\nThomasville, North Carolina\r\n472\r\n476\r\nTroy, North Carolina\r\n572\r\n576\r\nVirgilina, North Carolina\r\n849\r\nWagram, North Carolina\r\n369\r\nWake Forest, North Carolina\r\n554\r\n556\r\nWalkertown, North Carolina\r\n595\r\nWallace, North Carolina\r\n285\r\nWalnut Cove, North Carolina\r\n591\r\nWendell, North Carolina\r\n365\r\nWest End, North Carolina\r\n673\r\nWestfield, North Carolina\r\n351\r\nWhispering Pine, North Carolina\r\n949\r\nWhite Oak, North Carolina\r\n866\r\nWhiteville, North Carolina\r\n640\r\n642\r\nWilmington, North Carolina\r\n251\r\n313\r\n341\r\n343\r\n350\r\n371\r\n392\r\n540\r\n762\r\n763\r\n815\r\n820\r\nWinston Salem, North Carolina\r\n208\r\n631\r\n650\r\n659\r\n661\r\n712\r\n721\r\n722\r\n730\r\n748\r\n750\r\n759\r\n760\r\n761\r\n764\r\n765\r\n767\r\n768\r\n769\r\n770\r\n773\r\n777\r\n784\r\n785\r\n788\r\nWinton, North Carolina\r\n817\r\nYadkinville, North Carolina\r\n679\r\nYanceyville, North Carolina\r\n694\r\nZebulon, North Carolina\r\n269\r\nZephyr, North Carolina\r\n366\r\nSpring Lake, North Carolina\r\n497\r\n\u00035Unknown prefix code (919) - North Carolina\r\n"
  },
  {
    "path": "install/regions/regions.925",
    "content": "Concord, California\r\n768\r\nAntioch, California\r\n753\r\nOakley, California\r\n625\r\n\u00035Unknown prefix code (925) - California\r\n"
  },
  {
    "path": "install/regions/regions.931",
    "content": "Somewhere in Tenn., Tennessee\r\n206\r\n212\r\n260\r\nArdmore, Tennessee\r\n427\r\nBaxter, Tennessee\r\n858\r\nBeech Grove, Tennessee\r\n394\r\nBeersheba, Tennessee\r\n692\r\nBelfast, Tennessee\r\n276\r\nBlanche, Tennessee\r\n425\r\nBondecroft, Tennessee\r\n935\r\nBristol, Tennessee\r\n764\r\nByrdstown, Tennessee\r\n864\r\nCelina, Tennessee\r\n243\r\nCentertown, Tennessee\r\n939\r\nChapel Hill, Tennessee\r\n364\r\nChatanooga, Tennessee\r\n752\r\nCenterville, Tennessee\r\n729\r\nClarksville, Tennessee\r\n572\r\n551\r\n552\r\n553\r\n645\r\n647\r\n648\r\nClark Range, Tennessee\r\n863\r\nClifton, Tennessee\r\n676\r\nCollinwood, Tennessee\r\n724\r\nColumbia, Tennessee\r\n560\r\n380\r\n381\r\n388\r\nConcord, Tennessee\r\n680\r\nCookeville, Tennessee\r\n372\r\n526\r\n528\r\n537\r\n260\r\n520\r\n979\r\n432\r\nCornersville, Tennessee\r\n293\r\nCrawford, Tennessee\r\n445\r\nCrossville, Tennessee\r\n456\r\n484\r\nCulleoka, Tennessee\r\n987\r\nCumberland City, Tennessee\r\n827\r\nCunningham, Tennessee\r\n387\r\nDandridge, Tennessee\r\n397\r\nDecatur, Tennessee\r\n334\r\nDibrell, Tennessee\r\n934\r\nDoyle, Tennessee\r\n657\r\nDover, Tennessee\r\n232\r\nElkton, Tennessee\r\n468\r\nErin, Tennessee\r\n289\r\nEstill Springs, Tennessee\r\n649\r\nEthridge, Tennessee\r\n829\r\nFayetteville, Tennessee\r\n433\r\n438\r\nFive Points, Tennessee\r\n556\r\nFlat Creek, Tennessee\r\n695\r\nFlintville, Tennessee\r\n937\r\nFranklin, Tennessee\r\n437\r\nFredonia, Tennessee\r\n362\r\nGainesboro, Tennessee\r\n268\r\nGranville, Tennessee\r\n653\r\nHampshire, Tennessee\r\n285\r\nHighland, Tennessee\r\n678\r\nHillsboro, Tennessee\r\n596\r\nHohenwald, Tennessee\r\n796\r\nHuntland, Tennessee\r\n469\r\nJamestown, Tennessee\r\n879\r\nLaager, Tennessee\r\n779\r\nLawrenceburg, Tennessee\r\n762\r\n766\r\nLeoma, Tennessee\r\n852\r\nLinden, Tennessee\r\n589\r\nLivingston, Tennessee\r\n823\r\nLobelville, Tennessee\r\n593\r\nLoretto, Tennessee\r\n853\r\nLewisburg, Tennessee\r\n270\r\n359\r\nLyles, Tennessee\r\n670\r\nLynchburg, Tennessee\r\n759\r\nLynnville, Tennessee\r\n527\r\nManchester, Tennessee\r\n723\r\n728\r\nMcMinnville, Tennessee\r\n473\r\n668\r\nMc Ewen, Tennessee\r\n582\r\nMcBurg, Tennessee\r\n732\r\nMinor Hill, Tennessee\r\n565\r\nMonteagle, Tennessee\r\n924\r\nMonterey, Tennessee\r\n839\r\nMoss, Tennessee\r\n258\r\nMount Pleasant, Tennessee\r\n379\r\nNew Johnsonville, Tennessee\r\n535\r\nNewport, Tennessee\r\n487\r\nNorth Springs, Tennessee\r\n621\r\nNormandy, Tennessee\r\n857\r\nOld Zion, Tennessee\r\n761\r\nPalmyra, Tennessee\r\n326\r\nPelham, Tennessee\r\n467\r\nPetersburg, Tennessee\r\n659\r\nPleasant Hill, Tennessee\r\n277\r\nPulaski, Tennessee\r\n424\r\n363\r\nRickman, Tennessee\r\n498\r\nRock Island, Tennessee\r\n686\r\nSango, Tennessee\r\n358\r\nSanta Fe, Tennessee\r\n682\r\nSewanee, Tennessee\r\n598\r\nShelbyville, Tennessee\r\n580\r\n561\r\n684\r\n685\r\nSouth Guthrie, Tennessee\r\n485\r\nSouth Oakgrove, Tennessee\r\n431\r\nSparta, Tennessee\r\n738\r\n836\r\nSpencer, Tennessee\r\n946\r\nSpringhill, Tennessee\r\n486\r\n489\r\nSaint Joseph, Tennessee\r\n845\r\nSummertown, Tennessee\r\n964\r\nTansi, Tennessee\r\n788\r\nTennessee Ridge, Tennessee\r\n721\r\nTracy City, Tennessee\r\n592\r\nTullahoma, Tennessee\r\n393\r\n454\r\n455\r\nUnionville, Tennessee\r\n294\r\nViola, Tennessee\r\n635\r\nWartrace, Tennessee\r\n389\r\nWaverly, Tennessee\r\n296\r\nWaynesboro, Tennessee\r\n722\r\nWilliamspoint, Tennessee\r\n583\r\nWinchester, Tennessee\r\n962\r\n967\r\n\u00035Unknown prefix code (931) - Tennessee\r\n"
  },
  {
    "path": "install/regions/regions.940",
    "content": "Wichita Falls, Texas\r\n691\r\n851\r\n\u00035Unknown prefix code (940) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.941",
    "content": "Bradenton, Florida\r\n751\r\nLakeland, Florida\r\n682\r\nNaples, Florida\r\n455\r\n\u00035Unknown area code (941) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.951",
    "content": "Anza, California\n763\nArlington, California\n343\n351\n353\n354\n358\n359\n602\n687\n688\n689\n710\n785\n909\nBanning/Beaumont, California\n769\n845\n849\n922\nCorona, California\n270\n272\n273\n278\n279\n371\n734\n735\n736\n737\nHemet, California\n306\n652\n658\n765\n766\n791\n925\n927\n929\nHomeland, California\n926\nIdyllwild, California\n659\nLakeview\u00031/\u00032Nuevo, California\n928\nLake Elsinore, California\n245\n471\n609\n674\n678\nMira Loma, California\n360\n681\n685\nMoreno Valley, California\n242\n243\n247\n485\n486\n488\n653\n655\n656\n697\n924\nMurrieta, California\n304\n677\n696\n698\nPerris, California\n657\n940\n943\nRiverside, California\n274\n275\n276\n341\n352\n369\n615\n682\n683\n684\n686\n715\n781\n782\n784\n787\n788\nSage, California\n767\nSan Jacinto, California\n487\n654\nSun City, California\n244\n246\n301\n672\n679\nTemecula, California\n302\n303\n308\n676\n694\n695\n699\nTemescal Canyon, California\n277\nWoodcrest, California\n780\n789\n\u00035Unknown prefix code (951) - California\n"
  },
  {
    "path": "install/regions/regions.954",
    "content": "Hollywood, Florida\r\n981\r\nTamarac, Florida\r\n721\r\n\u00035Unknown prefix code (954) - Florida\r\n"
  },
  {
    "path": "install/regions/regions.965",
    "content": "Kuwait\r\n252\r\nUnknown prefix code - (965) Kuwait\r\n"
  },
  {
    "path": "install/regions/regions.970",
    "content": "Allenspark, Colorado\r\n747\r\nAllison, Colorado\r\n883\r\nAult, Colorado\r\n454\r\nBailey, Colorado\r\n838\r\nBayfield, Colorado\r\n884\r\nBerthoud, Colorado\r\n532\r\nBriggsdale, Colorado\r\n656\r\nCortez, Colorado\r\n565\r\nDolores, Colorado\r\n882\r\nDurango, Colorado\r\n247\r\n259\r\n385\r\n749\r\nEaton, Colorado\r\n834\r\nElbert, Colorado\r\n648\r\nElizabeth, Colorado\r\n646\r\nEstes Park, Colorado\r\n586\r\nFort Collins, Colorado\r\n202\r\n204\r\n206\r\n214\r\n215\r\n217\r\n218\r\n221\r\n222\r\n223\r\n224\r\n225\r\n226\r\n227\r\n228\r\n229\r\n231\r\n282\r\n407\r\n408\r\n416\r\n472\r\n481\r\n482\r\n484\r\n490\r\n491\r\n493\r\n495\r\n498\r\n566\r\n568\r\n621\r\nFort Lupton, Colorado\r\n857\r\nFrederick, Colorado\r\n833\r\nGeorgetown, Colorado\r\n569\r\nGilcrest, Colorado\r\n737\r\nGreeley, Colorado\r\n302\r\n304\r\n330\r\n339\r\n346\r\n350\r\n351\r\n352\r\n353\r\n356\r\n376\r\n381\r\n392\r\n395\r\n396\r\n410\r\n506\r\n539\r\n590\r\n681\r\nGrover, Colorado\r\n895\r\nGunnison, Colorado\r\n641\r\nHillrose, Colorado\r\n847\r\nHoyt, Colorado\r\n432\r\nHudson, Colorado\r\n536\r\nIgnacio, Colorado\r\n563\r\nJohnstown/Milliken, Colorado\r\n587\r\nKeenesburg, Colorado\r\n732\r\nKiowa, Colorado\r\n621\r\nLa Salle, Colorado\r\n284\r\nLoveland, Colorado\r\n203\r\n290\r\n593\r\n622\r\n635\r\n663\r\n667\r\n669\r\n679\r\n962\r\nMancos, Colorado\r\n533\r\nMarvel, Colorado\r\n588\r\nMead, Colorado\r\n535\r\nMesa Verde, Colorado\r\n529\r\nOuray, Colorado\r\n325\r\nPagosa Springs, Colorado\r\n264\r\nPagosa West, Colorado\r\n731\r\nPlatteville, Colorado\r\n785\r\nPleasant View, Colorado\r\n562\r\nRico, Colorado\r\n967\r\nRogen, Colorado\r\n849\r\nSilverton, Colorado\r\n387\r\nWellington, Colorado\r\n568\r\nWiggens, Colorado\r\n483\r\n\u00035Unknown prefix code (970) - Colorado\r\n"
  },
  {
    "path": "install/regions/regions.972",
    "content": "Suburban Dallas, Texas\r\n387\r\nLewisville, Texas\r\n219\r\nMesquite, Texas\r\n285\r\n\u00035Unknown prefix code (972) - Texas\r\n"
  },
  {
    "path": "install/regions/regions.974",
    "content": "Qatar\r\n974\r\n\u00035Unknown prefix code (974) - Qatar\r\n"
  },
  {
    "path": "install/regions/regions.unk",
    "content": "Unknown Area Code!\r\nUnk\r\n"
  },
  {
    "path": "install/scripts/hello.bas",
    "content": "' IMPORT \"@wwiv.io\"\n' IMPORT \"@wwiv\"\n\ndef PrintList(l)\n\tprint \"PrintList: \" \n  \tprint l\n\tcount = 0;\n\ti = iterator(l)\n\twhile move_next(i)\n\t  count = count + 1\n\t  print get(i)\n\twend\nenddef\n\nPRINT \"|11Hello |10World\"\nwwiv.module_name()\nwwiv.io.module_name()\nPRINT \"You are running version: \" + wwiv.version()\n\n'wwiv.io.outstr(\"What is your name? \")\n'name = wwiv.io.gets(41)\n'PRINT \"Hello: \" + name\n\n' WWIV.RUNMENU(\"BBSList\")\n\nl = list(\"a\", \"b\", \"c\", \"d\")\nprint \"len: \", len(l)\nwwiv.data.save(\"USER\", l)\nprint \"l=\", l, \"[end]\"\n\n'd = dict(1, \"one\", 2, \"two\")\n'print \"dlen: \", len(d)\n'wwiv.data.save(\"USER\", d)\n\nnl = list()\nwwiv.data.load(\"USER\", nl)\nPrintList(nl)\nPrintList(l)"
  },
  {
    "path": "install/scripts/oneliners.bas",
    "content": "'\n' Reinterpretation of the classic OneLiners originally\n' written by Σ└¡ (Eli).\n'\n' This version is written in WWIVbasic v5.3 as a sample\n' application.\n'\nimport \"@wwiv.io\"\n\n'\n' Prints the list to the screen, one row at a time.\n'\ndef PrintList(l)\n  i = iterator(l)\n  While move_next(i)\n    Print get(i)\n  Wend\nenddef\n\n' Returns the WWIV Pipe Color Code for\n' the color name displayed in onliners\ndef PipeColor(c)\n  If c = 1 then\n    return \"|15\"\n  ElseIf c = 2 then\n    return \"|01\"\n  ElseIf c = 3 then\n    return \"|10\"\n  ElseIf c = 4 then\n    return \"|12\"\n  ElseIf c = 5 then\n    return \"|13\"\n  ElseIf c = 6 then\n    return \"|07\"\n  ElseIf c = 7 then\n    return \"|11\"\n  ElseIf c = 8 then\n    return \"|14\"\n  ElseIf c = 9 then\n    return \"|09\"\n  endif\n  ' Default color.\n  return \"|07\"\nenddef\n\ndef EnterOneLiner()\n  outstr(\"|15 1:White|01 2:DkBlue|10 3:Green|12 4:Red|13 5:Purple|07 6:Gray|11 7:Cyan|14 8:Yellow|09 9:Blue\")\n  nl()\n  outstr(\"What Color? \")\n\n  color = getkey()\n  nl()\n  colorcode = ASC(LEFT(color, 1)) - ASC(\"0\")\n  pipecode = PipeColor(colorcode)\n  outstr(\"|10Enter Your One Liner:\")\n  nl()\n  outstr(\"|#9: \")\n  s = gets(72)\n\n  wwiv.io.outstr(\"|10Anonymous? \")\n  an = wwiv.io.ny()\n  If an Then\n    name = \"Anonymous\"\n  Else\n    namepart = wwiv.interpret(\"N\")\n    number = wwiv.interpret(\"#\")\n    name = namepart + \" #\" + number\n  EndIf\n  Return pipecode + name + \" - \" + s\nEnddef\n\ndef Main()\n  l = list()\n  wwiv.data.load(\"GLOBAL\", l)\n  done = False\n  cls()\n  While True\n    wwiv.io.printfile(\"oneliner\");\n    PrintList(l)\n    nl()\n    outstr(\"|#9Would you like to add an oneliner? \")\n\n    If Not yn() Then\n      Return\n    EndIf\n    s = EnterOneLiner()\n    If len(l) > 10 Then\n      Remove(l, 0)\n    EndIf\n    Push(l, s)\n    wwiv.data.save(\"GLOBAL\", l) \n  wend\nenddef\n\nMain()\n"
  },
  {
    "path": "lnet/CMakeLists.txt",
    "content": "# LNet for WWIV5\n\nadd_executable(lnet lnet.cpp lnet_main.cpp)\nset_max_warnings(lnet)\ntarget_link_libraries(lnet net_core core sdk local_io localui)\n\n"
  },
  {
    "path": "lnet/lnet.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2022, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 LNet\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"lnet/lnet.h\"\n#include \"local_io/local_io.h\"\n#include \"local_io/local_io_curses.h\"\n#include \"local_io/local_io_win32.h\"\n#include \"localui/curses_io.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/status.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\n\n\nstatic LocalIO* CreateLocalIO() {\n#if defined(_WIN32) && !defined(WWIV_WIN32_CURSES_IO)\n  return new Win32ConsoleIO();\n#else\n  wwiv::local::ui::CursesIO::Init(fmt::sprintf(\"WWIV BBS %s\", full_version()));\n  return new CursesLocalIO(wwiv::local::ui::curses_out->GetMaxY(),\n                                            wwiv::local::ui::curses_out->GetMaxX());\n#endif\n}\n\nLNet::LNet(const wwiv::net::NetworkCommandLine& cmdline)\n    : net_cmdline_(cmdline), io(CreateLocalIO()) {}\n\nLNet::~LNet() {\n  delete io;\n  io = nullptr;\n\n  // Cleanup CursesIO.\n  using namespace wwiv::local::ui;\n  if (curses_out != nullptr) {\n    delete curses_out;\n    curses_out = nullptr;\n  }\n}\n\nvoid LNet::dump_char(char ch) {\n\n  switch (ch) {\n  case 0:\n    io->Putch(' ');\n    break;\n  case 1:\n  case 2:\n  case 3:\n  case 4:\n  case 5:\n  case 6:\n  case 7:\n  case 8:\n  case 9:\n  case 11:\n  case 12:\n  case 14:\n  case 15:\n  case 16:\n  case 17:\n  case 18:\n  case 19:\n  case 20:\n  case 21:\n  case 22:\n  case 23:\n  case 24:\n  case 25:\n  case 26:\n    io->Format(\"[^{:c}]\", static_cast<char>('@' + ch));\n    break;\n  case 27:\n    io->Puts(\"[ESC]\");\n    break;\n  case 28:\n  case 29:\n  case 30:\n  case 31:\n    io->Format(\"[#{:d}]\", ch);\n    break;\n  case 10:\n    ++curli_;\n    io->Putch(ch);\n    if (curli_ > 24) {\n      pausescr();\n    }\n    break;\n  default:\n    io->Putch(ch);\n    break;\n  }\n}\n\nstatic std::string minor_type_to_string(uint16_t main_type, uint16_t minor_type) {\n  if (main_type == main_type_net_info) {\n    return net_info_minor_type_name(minor_type);\n  } else if (main_type > 0) {\n    return std::to_string(minor_type);\n  }\n  return \"0\";\n}\n\nvoid LNet::show_help() {\n  const auto help_text = R\"(\n\nR - Read message.\nD - Delete message.\nN - Next message.\nT - Re-Read message.\nW - Write message to new file.\n] - 10 messages forward.\n} - 50 messages forward.\n' - 500 messages forward\nX - Truncate file (used for bad messages)\nQ - Quit.\n\n\n)\";\n  io->Puts(help_text);\n}\n\nvoid LNet::show_header(const net_header_rec& nh, int current, double percent) {\n  io->Format(\"Entry {:3} ({:03}%): \", current, percent);\n\n  if (nh.main_type == 65535) {\n    io->Puts(\">DELETED<\\n\\n\");\n  } else {\n    io->Format(\"{} ({})\", main_type_name(nh.main_type),\n               minor_type_to_string(nh.main_type, nh.minor_type));\n    if (nh.fromuser) {\n      io->Format(\", From #{} @{}\", nh.fromuser, nh.fromsys);\n    } else {\n      io->Format(\", From @{}\", nh.fromsys);\n    }\n    io->Format(\", {} bytes\", nh.length);\n    const auto now = wwiv::core::daten_t_now();\n    const auto days_old = (int)((now - nh.daten) / 24 / 3600);\n    io->Format(\", {} day{} old\", days_old, days_old > 1 ? \"s\" : \"\");\n\n    if (nh.touser) {\n      io->Format(\"\\n                  To #{} @{}\\r\\n\\n\", nh.touser, nh.tosys);\n    } else {\n      io->Format(\"\\n                  To @{}\\r\\n\\n\", nh.tosys);\n    }\n  }\n}\n\nstatic int skip_messages(NetMailFile& file, int num_to_skip) {\n  int skipped = 0;\n  while (--num_to_skip >= 0) {\n    auto [packet, resp] = file.Read();\n    if (resp != ReadNetPacketResponse::OK) {\n      return skipped;\n    }\n    ++skipped;\n  }\n  return skipped;\n}\n\nvoid LNet::pausescr() { \n  auto saved = io->curatr(); \n  io->curatr(13);\n  io->Puts(\"[PAUSE]\");\n  io->GetChar();\n  io->Cr();\n  io->Lf();\n  io->curatr(saved);\n  curli_ = 0;\n}\n\nint LNet::Run() {\n  const std::filesystem::path filename = net_cmdline_.cmdline().remaining().front();\n  NetMailFile file(filename, true, true);\n  if (!file) {\n    LOG(ERROR) << \"Unable to open file: \" << filename << \"; error: \" << file.file().last_error();\n    return 1;\n  }\n\n  auto current{0};\n  bool packet_modified{false};\n  const auto file_length = file.file().length();\n  for (;;) {\n    io->Cls();\n    auto [packet, response] = file.Read();\n    if (response == ReadNetPacketResponse::END_OF_FILE) {\n      return 0;\n    } else if (response != ReadNetPacketResponse::OK) {\n      return 1;\n    }\n    ++current;\n    const auto percent = static_cast<double>(packet.offset() / file_length);\n    show_header(packet.nh, current, std::floor(percent * 100));\n\n    auto prompt_done = false;\n    while (!prompt_done) {\n      io->Format(\"Action (R,D,N,T,Q,?) ? \");\n\n      char key = upcase(io->GetChar());\n\n      switch (key) {\n      case '?': {\n        show_help();\n      } break;\n      case ']':\n        current += skip_messages(file, 9);\n        prompt_done = true;\n        break;\n      case '}':\n        current += skip_messages(file, 49);\n        prompt_done = true;\n        break;\n      case '\\'':\n        current += skip_messages(file, 499);\n        prompt_done = true;\n        break;\n      case 'D': {\n        // TODO: Mark message 65536\n        auto saved_position = packet.offset();\n        file.file().Seek(saved_position, wwiv::core::File::Whence::begin);\n        packet.nh.main_type = 65535; // Mark this packet deleted.\n        const auto num = file.file().Write(&packet.nh, sizeof(net_header_rec));\n        if (num != sizeof(net_header_rec)) {\n          // Let's fail now since we didn't write this right.\n          LOG(ERROR) << \"Error deleting packet; num written (\" << num\n                     << \") != net_header_rec size.\";\n          io->GetChar();\n          prompt_done = true;\n          break;\n        }\n        file.file().Seek(saved_position, wwiv::core::File::Whence::begin);\n        --current;\n        prompt_done = true;\n        packet_modified = true;\n      } break;\n      case 'N':\n        prompt_done = true;\n        break;\n      case 'Q': {\n        if (packet_modified) {\n          file.Close();\n          // Move the pending file into the same directory as P1-L-###.NET\n          const auto dir = filename.parent_path();\n          rename_pend(dir, filename.filename().string(), 'L');\n        }\n        return 0;\n      } break;\n      case 'R': {\n        if (packet.nh.length) {\n          io->Cr();\n          io->Lf();\n          ++curli_;\n          for (const auto ch : packet.text()) {\n            dump_char(ch);\n          }\n          io->Cr();\n          io->Lf();\n        }\n      } break;\n      case 'T': {\n        // Reread message\n        file.file().Seek(packet.offset(), wwiv::core::File::Whence::begin);\n        --current;\n        prompt_done = true;\n      } break;\n      case 'W': {\n        // Write message to new file.\n\n        // Back up.\n        file.file().Seek(packet.offset(), wwiv::core::File::Whence::begin);\n        --current;\n        prompt_done = true;\n        std::string fn;\n        io->Puts(\"Enter Filename: \");\n        const auto r = io->EditLine(fn, 12, AllowedKeys::ALL);\n        io->Cr();\n        io->Lf();\n        if (r == EditlineResult::ABORTED) {\n          io->Puts(\"Aborted\");\n          break;\n        }\n        const auto dir = filename.parent_path();\n        write_wwivnet_packet(FilePath(dir, fn), packet);\n \n      } break;\n      }\n    } // !prompt_done\n  }\n}\n"
  },
  {
    "path": "lnet/lnet.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*          Copyright (C)2022, WWIV Software Services                     */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NET_LNET_H\n#define INCLUDED_NET_LNET_H\n\n#include \"local_io/local_io.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/net/legacy_net.h\"\n\nclass LNet final {\npublic:\n  LNet(const wwiv::net::NetworkCommandLine& cmdline);\n  ~LNet();\n\n  int Run();\n\nprivate:\n  void pausescr();\n  void dump_char(char ch);\n  void show_help();\n  void show_header(const net_header_rec& nh, int current, double percent);\n\n\n  const wwiv::net::NetworkCommandLine& net_cmdline_;\n  wwiv::local::io::LocalIO* io{nullptr};\n  int curli_{0};\n};\n\n#endif // INCLUDED_NET_LNET_H"
  },
  {
    "path": "lnet/lnet_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2022, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 LNet\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/version.h\"\n#include \"lnet/lnet.h\"\n#include \"net_core/net_cmdline.h\"\n\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::sdk;\n\nvoid ShowCommandLineHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n\n  const NetworkCommandLine net_cmdline(cmdline, 'l');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested() ||\n      net_cmdline.cmdline().remaining().empty()) {\n    ShowCommandLineHelp(net_cmdline);\n    return 1;\n  }\n  try {\n    auto semaphore =\n        SemaphoreFile::try_acquire(net_cmdline.semaphore_path(), net_cmdline.semaphore_timeout());\n    LNet lnet(net_cmdline);\n    return lnet.Run();\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [lnet]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n  return 1;\n}"
  },
  {
    "path": "local_io/CMakeLists.txt",
    "content": "# CMake for WWIV\nInclude(FindWWIVCurses)\n\nset(COMMON_SOURCES\n  local_io.cpp\n  local_io_curses.cpp\n  null_local_io.cpp\n  stdio_local_io.cpp\n  )\n\nif(WIN32)\n  set(PLATFORM_SOURCES\n\t\tlocal_io_win32.cpp\n\t)\nendif()\n\nadd_library(local_io ${COMMON_SOURCES} ${PLATFORM_SOURCES})\ntarget_link_libraries(local_io PUBLIC ${CURSES_LIBRARIES} localui core fmt::fmt-header-only)\nset_max_warnings(local_io)\n"
  },
  {
    "path": "local_io/curatr_provider.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_CURATR_PROVIDER_H\n#define INCLUDED_LOCAL_IO_CURATR_PROVIDER_H\n\n#include <cstdint>\n\nnamespace wwiv::local::io {\n\nclass curatr_provider {\npublic:\n  virtual ~curatr_provider() = default;\n  [[nodiscard]] virtual uint8_t curatr() const noexcept = 0;\n  virtual void curatr(int n) = 0;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "local_io/keycodes.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_KEYCODES_H\n#define INCLUDED_LOCAL_IO_KEYCODES_H\n\nnamespace wwiv::local::io {\n\nconstexpr int SPACE = 32;\nconstexpr int RETURN = 13;\nconstexpr int SOFTRETURN = 10;\nconstexpr int ENTER = RETURN;\n\nconstexpr int BACKSPACE = 8;\nconstexpr int CBACKSPACE = 127;\n\nconstexpr int ESC = 27;\nconstexpr int TAB = 9;\n\n/* Stab is an extended 15 (0 ascii, 15 ext) */\nconstexpr int STAB = 15;\n\nconstexpr int PAGEUP = 73;\nconstexpr int PAGEDN = 81;\nconstexpr int PGUP = PAGEUP;\nconstexpr int PGDN = PAGEDN;\nconstexpr int PAGEDOWN = PAGEDN;\nconstexpr int CPAGEUP = 132;\nconstexpr int CPAGEDN = 118;\nconstexpr int CPGUP = CPAGEUP;\nconstexpr int CPGDN = CPAGEDN;\nconstexpr int CPGDOWN = CPAGEDN;\n\nconstexpr int APAGEUP = 153;\nconstexpr int APAGEDN = 161;\nconstexpr int APGDN = APAGEDN;\nconstexpr int APGUP = APAGEUP;\n\nconstexpr int LARROW = 75;\nconstexpr int RARROW = 77;\nconstexpr int UPARROW = 72;\nconstexpr int UARROW = 72;\nconstexpr int DNARROW = 80;\nconstexpr int DARROW = 80;\n\nconstexpr int CRARROW = 116;\nconstexpr int CLARROW = 115;\nconstexpr int CUARROW = 141;\nconstexpr int CDARROW = 145;\n\nconstexpr int ALARROW = 155;\nconstexpr int ARARROW = 157;\nconstexpr int AUARROW = 152;\nconstexpr int ADARROW = 160;\n\nconstexpr int HOME = 71;\nconstexpr int CHOME = 119;\nconstexpr int END = 79;\nconstexpr int CEND = 117;\nconstexpr int KEY_INSERT = 82;\nconstexpr int KEY_DELETE = 83;\n\nconstexpr int F1 = 59;\nconstexpr int F2 = 60;\nconstexpr int F3 = 61;\nconstexpr int F4 = 62;\nconstexpr int F5 = 63;\nconstexpr int F6 = 64;\nconstexpr int F7 = 65;\nconstexpr int F8 = 66;\nconstexpr int F9 = 67;\nconstexpr int F10 = 68;\n\nconstexpr int AF1 = 104;\nconstexpr int AF2 = 105;\nconstexpr int AF3 = 106;\nconstexpr int AF4 = 107;\nconstexpr int AF5 = 108;\nconstexpr int AF6 = 109;\nconstexpr int AF7 = 110;\nconstexpr int AF8 = 111;\nconstexpr int AF9 = 112;\nconstexpr int AF10 = 113;\n\nconstexpr int SF1 = 84;\nconstexpr int SF2 = 85;\nconstexpr int SF3 = 86;\nconstexpr int SF4 = 87;\nconstexpr int SF5 = 88;\nconstexpr int SF6 = 89;\nconstexpr int SF7 = 90;\nconstexpr int SF8 = 91;\nconstexpr int SF9 = 92;\nconstexpr int SF10 = 93;\n\nconstexpr int CF1 = 94;\nconstexpr int CF2 = 95;\nconstexpr int CF3 = 96;\nconstexpr int CF4 = 97;\nconstexpr int CF5 = 98;\nconstexpr int CF6 = 99;\nconstexpr int CF7 = 100;\nconstexpr int CF8 = 101;\nconstexpr int CF9 = 102;\nconstexpr int CF10 = 103;\n\nstatic constexpr int COMMAND_F1 = (F1 + 256);\nconstexpr int COMMAND_SF1 = (SF1 + 256);\nconstexpr int COMMAND_CF1 = (CF1 + 256);\n\nconstexpr int COMMAND_F2 = (F2 + 256);\nconstexpr int COMMAND_SF2 = (SF2 + 256);\nconstexpr int COMMAND_CF2 = (CF2 + 256);\n\nconstexpr int COMMAND_F3 = (F3 + 256);\nconstexpr int COMMAND_SF3 = (SF3 + 256);\nconstexpr int COMMAND_CF3 = (CF3 + 256);\n\nconstexpr int COMMAND_F4 = (F4 + 256);\nconstexpr int COMMAND_SF4 = (SF4 + 256);\nconstexpr int COMMAND_CF4 = (CF4 + 256);\n\nconstexpr int COMMAND_F5 = (F5 + 256);\nconstexpr int COMMAND_SF5 = (SF5 + 256);\nconstexpr int COMMAND_CF5 = (CF5 + 256);\n\nconstexpr int COMMAND_F6 = (F6 + 256);\nconstexpr int COMMAND_SF6 = (SF6 + 256);\nconstexpr int COMMAND_CF6 = (CF6 + 256);\n\nconstexpr int COMMAND_F7 = (F7 + 256);\nconstexpr int COMMAND_SF7 = (SF7 + 256);\nconstexpr int COMMAND_CF7 = (CF7 + 256);\n\nconstexpr int COMMAND_F8 = (F8 + 256);\nconstexpr int COMMAND_SF8 = (SF8 + 256);\nconstexpr int COMMAND_CF8 = (CF8 + 256);\n\nconstexpr int COMMAND_F9 = (F9 + 256);\nconstexpr int COMMAND_SF9 = (SF9 + 256);\nconstexpr int COMMAND_CF9 = (CF9 + 256);\n\nconstexpr int COMMAND_F10 = (F10 + 256);\nconstexpr int COMMAND_SF10 = (SF10 + 256);\nconstexpr int COMMAND_CF10 = (CF10 + 256);\n\nconstexpr int CA = 1;\nconstexpr int CB = 2;\nconstexpr int CC = 3;\nconstexpr int CD = 4;\nconstexpr int CE = 5;\nconstexpr int CF = 6;\nconstexpr int CG = 7;\nconstexpr int CH = 8;\nconstexpr int CI = 9;\nconstexpr int CJ = 10;\nconstexpr int CK = 11;\nconstexpr int CL = 12;\nconstexpr int CM = 13;\nconstexpr int CN = 14;\nconstexpr int CO = 15;\nconstexpr int CP = 16;\nconstexpr int CQ = 17;\nconstexpr int CR = 18;\nconstexpr int CS = 19;\nconstexpr int CT = 20;\nconstexpr int CU = 21;\nconstexpr int CV = 22;\nconstexpr int CW = 23;\nconstexpr int CX = 24;\nconstexpr int CY = 25;\nconstexpr int CZ = 26;\n\nconstexpr int AA = 30;\nconstexpr int AB = 48;\nconstexpr int AC = 46;\nconstexpr int AD = 32;\nconstexpr int AE = 18;\nconstexpr int AF = 33;\nconstexpr int AG = 34;\nconstexpr int AH = 35;\nconstexpr int AI = 23;\nconstexpr int AJ = 36;\nconstexpr int AK = 37;\nconstexpr int AL = 38;\nconstexpr int AM = 50;\nconstexpr int AN = 49;\nconstexpr int AO = 24;\nconstexpr int AP = 25;\nconstexpr int AQ = 16;\nconstexpr int AR = 19;\nconstexpr int AS = 31;\nconstexpr int AT = 20;\nconstexpr int AU = 22;\nconstexpr int AV = 47;\nconstexpr int AW = 17;\nconstexpr int AX = 45;\nconstexpr int AY = 21;\nconstexpr int AZ = 44;\n\nconstexpr int GET_OUT = (ESC);\nconstexpr int EXECUTE = (RETURN);\n\nconstexpr int COMMAND_LEFT = (LARROW + 256);\nconstexpr int COMMAND_RIGHT = (RARROW + 256);\nconstexpr int COMMAND_UP = (UPARROW + 256);\nconstexpr int COMMAND_DOWN = (DARROW + 256);\nconstexpr int COMMAND_INSERT = (KEY_INSERT + 256);\nconstexpr int COMMAND_PAGEUP = (PAGEUP + 256);\nconstexpr int COMMAND_PAGEDN = (PAGEDN + 256);\nconstexpr int COMMAND_HOME = (HOME + 256);\nconstexpr int COMMAND_END = (END + 256);\nconstexpr int COMMAND_STAB = (STAB + 256);\nconstexpr int COMMAND_DELETE = (KEY_DELETE + 256);\n\nconstexpr int COMMAND_AA = (AA + 256);\nconstexpr int COMMAND_AB = (AB + 256);\nconstexpr int COMMAND_AC = (AC + 256);\nconstexpr int COMMAND_AD = (AD + 256);\nconstexpr int COMMAND_AE = (AE + 256);\nconstexpr int COMMAND_AF = (AF + 256);\nconstexpr int COMMAND_AG = (AG + 256);\nconstexpr int COMMAND_AH = (AH + 256);\nconstexpr int COMMAND_AI = (AI + 256);\nconstexpr int COMMAND_AJ = (AJ + 256);\nconstexpr int COMMAND_AK = (AK + 256);\nconstexpr int COMMAND_AL = (AL + 256);\nconstexpr int COMMAND_AM = (AM + 256);\nconstexpr int COMMAND_AN = (AN + 256);\nconstexpr int COMMAND_AO = (AO + 256);\nconstexpr int COMMAND_AP = (AP + 256);\nconstexpr int COMMAND_AQ = (AQ + 256);\nconstexpr int COMMAND_AR = (AR + 256);\nconstexpr int COMMAND_AS = (AS + 256);\nconstexpr int COMMAND_AT = (AT + 256);\nconstexpr int COMMAND_AU = (AU + 256);\nconstexpr int COMMAND_AV = (AV + 256);\nconstexpr int COMMAND_AW = (AW + 256);\nconstexpr int COMMAND_AX = (AX + 256);\nconstexpr int COMMAND_AY = (AY + 256);\nconstexpr int COMMAND_AZ = (AZ + 256);\n\n}\n\n#endif\n"
  },
  {
    "path": "local_io/local_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"local_io/local_io.h\"\n\n#include \"core/strings.h\"\n\nnamespace wwiv::local::io {\n\nusing namespace wwiv::strings;\n\nclass DefaultCurAttrProvider final : public wwiv::local::io::curatr_provider {\npublic:\n  DefaultCurAttrProvider() = default;\n  [[nodiscard]] uint8_t curatr() const noexcept override { return a_; }\n  void curatr(int n) override { a_ = static_cast<uint8_t>(n); }\n\nprivate:\n  uint8_t a_{7};\n};\n\nstatic std::unique_ptr<DefaultCurAttrProvider> default_curatr_provider_ =\n    std::make_unique<DefaultCurAttrProvider>();\n\nLocalIO::LocalIO() : curatr_(default_curatr_provider_.get()) {}\nLocalIO::~LocalIO() = default;\n\nvoid LocalIO::set_curatr_provider(wwiv::local::io::curatr_provider* p) { curatr_ = p; }\nwwiv::local::io::curatr_provider* LocalIO::curatr_provider() { return curatr_; }\n\nuint8_t LocalIO::curatr() const { return curatr_->curatr(); }\nvoid LocalIO::curatr(int c) { curatr_->curatr(c); }\n\nEditlineResult LocalIO::EditLine(std::string& s, int len, AllowedKeys allowed_keys,\n                    const std::string& allowed_set_chars) {\n  char p[1024];\n  to_char_array(p, s);\n  auto rc{EditlineResult::PREV};\n  EditLine(p, len, allowed_keys, &rc, allowed_set_chars.c_str());\n  s = p;\n  return rc;\n}\n\nEditlineResult LocalIO::EditLine(std::string& s, int len, AllowedKeys allowed_keys) {\n  return EditLine(s, len, allowed_keys, {});\n}\n\nvoid LocalIO::increment_topdata() {\n  switch (topdata_) {\n  case topdata_t::none:\n    topdata_ = topdata_t::system;\n    break;\n  case topdata_t::system:\n    topdata_ = topdata_t::user;\n    break;\n  case topdata_t::user:\n    topdata_ = topdata_t::none;\n    break;\n  }\n}\n\n}\n"
  },
  {
    "path": "local_io/local_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_LOCALIO_H\n#define INCLUDED_LOCAL_IO_LOCALIO_H\n\n#include \"fmt/printf.h\"\n#include \"local_io/curatr_provider.h\"\n\n#include <string>\n\nnamespace wwiv::local::io {\n\nenum class AllowedKeys { NUM_ONLY, UPPER_ONLY, ALL, SET };\n\nstruct LocalIOData {\n  int instance_number{0};\n  std::string system_name;\n};\n\nenum class EditlineResult { PREV, NEXT, DONE, ABORTED };\n\n\n/**\n * Encompasses all Local Input/Output from The BBS.\n * You should use a routine in here instead of using printf, puts, etc.\n */\nclass LocalIO {\npublic:\n  // Constructor/Destructor\n  LocalIO();\n  LocalIO(const LocalIO& copy) = delete;\n  virtual ~LocalIO();\n\n  static constexpr int cursorNone = 0;\n  static constexpr int cursorNormal = 1;\n  static constexpr int cursorSolid = 2;\n\n  enum class topdata_t { none, system, user };\n\n  [[nodiscard]] int GetTopLine() const noexcept { return topline_; }\n  void SetTopLine(int nTopLine) { topline_ = nTopLine; }\n\n  [[nodiscard]] int GetScreenBottom() const noexcept { return screen_bottom_; }\n  void SetScreenBottom(int nScreenBottom) { screen_bottom_ = nScreenBottom; }\n\n  virtual void GotoXY(int x, int y) = 0;\n  [[nodiscard]] virtual int WhereX() const noexcept = 0;\n  [[nodiscard]] virtual int WhereY() const noexcept = 0;\n  virtual void Lf() = 0;\n  virtual void Cr() = 0;\n  virtual void Cls() = 0;\n  virtual void ClrEol() = 0;\n  virtual void Backspace() = 0;\n  virtual void PutchRaw(unsigned char ch) = 0;\n  // Overridden by TestLocalIO in tests.\n  /** Writes a single character 'ch' at the current position */\n  virtual void Putch(unsigned char ch) = 0;\n  /** Writes text at the current position */\n  virtual void Puts(const std::string& text) = 0;\n\n  template <class... Args> void Printf(const char* format_str, Args&&... args) {\n    // Process arguments\n    return Puts(fmt::sprintf(format_str, std::forward<Args>(args)...));\n  }\n\n  template <class... Args> void Format(const char* format_str, Args&&... args) {\n    // Process arguments\n    return Puts(fmt::format(format_str, std::forward<Args>(args)...));\n  }\n\n  /**\n   * Writes text at position (x, y) using the current color.\n   *\n   * Note that x and y are zero based and (0, 0) is the top left corner of the screen.\n   */\n  virtual void PutsXY(int x, int y, const std::string& text) = 0;\n  /**\n   * Writes text at position (x, y) using the color 'attr'.\n   *\n   * Note that x and y are zero based and (0, 0) is the top left corner of the screen.\n   */\n  virtual void PutsXYA(int x, int y, int attr, const std::string& text) = 0;\n  virtual void set_protect(int l) = 0;\n  virtual void savescreen() = 0;\n  virtual void restorescreen() = 0;\n  virtual bool KeyPressed() = 0;\n  virtual unsigned char GetChar() = 0;\n  /*\n   * MakeLocalWindow makes a \"shadowed\" window with the upper-left hand corner at\n   * (x,y), and the lower-right corner at (x+xlen,y+ylen).\n   */\n  virtual void MakeLocalWindow(int x, int y, int xlen, int ylen) = 0;\n  virtual void SetCursor(int cursorStyle) = 0;\n  virtual void WriteScreenBuffer(const char* buffer) = 0;\n  [[nodiscard]] virtual int GetDefaultScreenBottom() const noexcept = 0;\n  virtual void EditLine(char* s, int len, AllowedKeys allowed_keys, EditlineResult* returncode,\n                        const char* allowed_set_chars) = 0;\n  virtual EditlineResult EditLine(std::string& s, int len, AllowedKeys allowed_keys,\n                       const std::string& allowed_set_chars);\n  virtual EditlineResult EditLine(std::string& s, int len, AllowedKeys allowed_keys);\n  virtual void UpdateNativeTitleBar(const std::string& system_name, int instance_number) = 0;\n\n  [[nodiscard]] uint8_t GetTopScreenColor() const noexcept { return top_screen_color_; }\n  void SetTopScreenColor(uint8_t n) { top_screen_color_ = n; }\n\n  [[nodiscard]] uint8_t GetUserEditorColor() const noexcept { return user_editor_color_; }\n  void SetUserEditorColor(uint8_t n) { user_editor_color_ = n; }\n\n  [[nodiscard]] uint8_t GetEditLineColor() const noexcept { return edit_line_color_; }\n  void SetEditLineColor(uint8_t n) { edit_line_color_ = n; }\n\n  virtual void DisableLocalIO() {}\n  virtual void ReenableLocalIO() {}\n\n  [[nodiscard]] topdata_t topdata() const noexcept { return topdata_; }\n  void topdata(topdata_t t) { topdata_ = t; }\n  void increment_topdata();\n\n  // curatr_provider interface\n  virtual void set_curatr_provider(wwiv::local::io::curatr_provider* p);\n  virtual wwiv::local::io::curatr_provider* curatr_provider();\n  [[nodiscard]] virtual uint8_t curatr() const;\n  virtual void curatr(int c);\n\nprivate:\n  virtual void FastPuts(const std::string& text) = 0;\n\n  int topline_{0};\n  int screen_bottom_{25}; // Just a default.\n  uint8_t top_screen_color_{27};\n  uint8_t user_editor_color_{9};\n  uint8_t edit_line_color_{31};\n  wwiv::local::io::curatr_provider* curatr_;\n  topdata_t topdata_{topdata_t::none};\n};\n\n}\n\n#endif"
  },
  {
    "path": "local_io/local_io_curses.cpp",
    "content": "//**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"local_io/local_io_curses.h\"\n#include \"core/cp437.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"localui/curses_io.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/wwiv_curses.h\"\n#include \"local_io/keycodes.h\"\n#include <algorithm>\n#include <cstdio>\n#include <string>\n\n#ifdef __unix__\n#include <unistd.h>\n#endif\n\nnamespace wwiv::local::io {\n\nusing namespace wwiv::strings;\n\nstatic const int default_screen_bottom = 20;\n\nstatic void InitPairs() {\n  std::vector<short> lowbit_colors = {COLOR_BLACK, COLOR_BLUE,    COLOR_GREEN,  COLOR_CYAN,\n                                      COLOR_RED,   COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE};\n  short num = 0;\n  for (auto bg = 0; bg < 8; bg++) {\n    for (auto fg = 0; fg < 8; fg++) {\n      init_pair(num++, lowbit_colors[fg], lowbit_colors[bg]);\n    }\n  }\n}\n\nCursesLocalIO::CursesLocalIO() : CursesLocalIO(default_screen_bottom + 1, 80) {}\n\nCursesLocalIO::CursesLocalIO(int num_lines, int num_cols) {\n  InitPairs();\n  window_.reset(new wwiv::local::ui::CursesWindow(nullptr, wwiv::local::ui::curses_out->color_scheme(), num_lines, num_cols, 0, 0));\n  auto* w = std::any_cast<WINDOW*>(window_->window());\n  scrollok(w, true);\n  window_->Clear();\n}\n\nCursesLocalIO::~CursesLocalIO() {\n  CursesLocalIO::SetCursor(LocalIO::cursorNormal);\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nvoid CursesLocalIO::SetColor(int original_color) {\n  const auto bold = (original_color & 8) != 0;\n  auto color = original_color;\n  const auto bg = (color >> 4) & 0x07;\n  const auto fg = color & 0x07;\n  color = (bg << 3) | fg;\n  auto attr = COLOR_PAIR(color);\n  if (bold) {\n    attr |= A_BOLD;\n  }\n  window_->AttrSet(attr);\n}\n\nvoid CursesLocalIO::GotoXY(int x, int y) { window_->GotoXY(x, y); }\n\nint CursesLocalIO::WhereX() const noexcept { return window_->GetcurX(); }\n\nint CursesLocalIO::WhereY() const noexcept { return window_->GetcurY(); }\n\nvoid CursesLocalIO::Lf() {\n  Cr();\n  y_ = WhereY();\n  x_ = WhereX();\n  y_++;\n\n  if (y_ > GetScreenBottom()) {\n    auto* w = std::any_cast<WINDOW*>(window_->window());\n    scroll(w);\n    y_ = GetScreenBottom();\n  }\n  window_->GotoXY(x_, y_);\n}\n\nvoid CursesLocalIO::Cr() {\n  const auto y = WhereY();\n  window_->GotoXY(0, y);\n}\n\nvoid CursesLocalIO::Cls() {\n  SetColor(curatr());\n  window_->Clear();\n}\n\nvoid CursesLocalIO::Backspace() {\n  PutchRaw('\\b');\n}\n\nvoid CursesLocalIO::PutchRaw(unsigned char ch) {\n  SetColor(curatr());\n#ifndef __OS2__\n  const auto wch = wwiv::core::cp437_to_utf8(static_cast<uint8_t>(ch));\n  window_->PutchW(wch);\n#else\n  window_->Putch(ch);\n#endif\n}\n\nvoid CursesLocalIO::Putch(unsigned char ch) {\n  if (ch > 31) {\n    PutchRaw(ch);\n  } else if (ch == CM) {\n    Cr();\n  } else if (ch == CJ) {\n    Lf();\n  } else if (ch == CL) {\n    Cls();\n  } else if (ch == BACKSPACE) {\n    Backspace();\n  } else if (ch == CG) {\n    // No bell please.\n  }\n}\n\nvoid CursesLocalIO::Puts(const std::string& s) {\n  for (auto ch : s) {\n    Putch(ch);\n  }\n}\n\nvoid CursesLocalIO::PutsXY(int x, int y, const std::string& text) {\n  GotoXY(x, y);\n  FastPuts(text);\n}\n\nvoid CursesLocalIO::PutsXYA(int x, int y, int a, const std::string& text) {\n  const auto old_color = curatr();\n  curatr(a);\n\n  GotoXY(x, y);\n  FastPuts(text);\n\n  curatr(old_color);\n}\n\nvoid CursesLocalIO::FastPuts(const std::string& text) {\n  SetColor(curatr());\n#ifndef __OS2__\n  const auto w = wwiv::core::cp437_to_utf8w(text);\n  window_->PutsW(w);\n#else\n  window_->Puts(text);\n#endif\n}\n\nvoid CursesLocalIO::set_protect(int l) { SetTopLine(l); }\n\nstatic std::vector<chtype*> saved_screen;\nvoid CursesLocalIO::savescreen() {\n  saved_screen.clear();\n  window_->Refresh();\n\n  const auto width = window_->GetMaxX();\n  const auto height = window_->GetMaxY();\n\n  for (auto line = 0; line < height; line++) {\n    auto* buf = new chtype[width];\n    auto* w = std::any_cast<WINDOW*>(window_->window());\n    mvwinchnstr(w, line, 0, buf, width);\n    saved_screen.push_back(buf);\n  }\n}\n\nvoid CursesLocalIO::restorescreen() {\n  const auto width = window_->GetMaxX();\n  auto y = 0;\n  auto* w = std::any_cast<WINDOW*>(window_->window());\n  for (auto* line : saved_screen) {\n    mvwaddchnstr(w, y++, 0, line, width);\n  }\n  window_->Refresh();\n}\n\nstatic int last_key_pressed = ERR;\n\nbool CursesLocalIO::KeyPressed() {\n  if (last_key_pressed != ERR) {\n    return true;\n  }\n  auto* w = std::any_cast<WINDOW*>(window_->window());\n  nodelay(w, TRUE);\n  last_key_pressed = window_->GetChar(std::chrono::milliseconds(0));\n  return last_key_pressed != ERR;\n}\n\nstatic int CursesToWin32KeyCodes(int curses_code) {\n  switch (curses_code) {\n  case KEY_F(1):\n    return F1;\n  case KEY_F(2):\n    return F2;\n  case KEY_F(3):\n    return F3;\n  case KEY_F(4):\n    return F4;\n  case KEY_F(5):\n    return F5;\n  case KEY_F(6):\n    return F6;\n  case KEY_F(7):\n    return F7;\n  case KEY_F(8):\n    return F8;\n  case KEY_F(9):\n    return F9;\n  case KEY_F(10):\n    return F10;\n\n#ifdef __PDCURSES__\n  case KEY_A1:\n    return HOME;\n  case KEY_A2: // upper middle on Virt. keypad. Win10 Terminal started using this\n    return UPARROW;\n  case KEY_A3:\n    return PGUP;\n  case KEY_B1: // middle left on Virt. keypad. Win10 Terminal started using this.\n    return LARROW;\n  case KEY_B3: // middle right on Vir. keypad. Win10 Terminal started using this.\n    return RARROW;\n  case KEY_C1:\n    return END;\n  case KEY_C2: // lower middle on Virt. keypad. Win10 Terminal started using this.\n    return DNARROW;\n  case KEY_C3:\n    return PGDN;\n#endif\n\n  case KEY_UP:\n    return UPARROW;\n  case KEY_DOWN:\n    return DNARROW;\n  case KEY_HOME:\n    return HOME;\n  case KEY_END:\n    return END;\n  case KEY_LEFT:\n    return LARROW;\n  case KEY_RIGHT:\n    return RARROW;\n  case KEY_DELETE:\n  case KEY_BACKSPACE:\n    return BACKSPACE;\n  case KEY_PPAGE:\n    return PAGEUP;\n  case KEY_NPAGE:\n    return PAGEDOWN;\n  // TODO: implement the rest.\n  default: {\n    LOG(INFO) << \"unknown key:\" << curses_code;\n    return 0;\n  }\n  }\n}\n\nunsigned char CursesLocalIO::GetChar() {\n  if (last_key_pressed != ERR) {\n    const auto ch = last_key_pressed;\n    if (ch > 255) {\n      // special key\n      switch (ch) {\n      case KEY_DELETE:\n      case KEY_BACKSPACE:\n        last_key_pressed = ERR;\n        return static_cast<unsigned char>(BACKSPACE);\n\n      default:\n        last_key_pressed = CursesToWin32KeyCodes(ch);\n        return 0;\n      }\n    }\n    last_key_pressed = ERR;\n    return static_cast<unsigned char>(ch);\n  }\n  auto* w = std::any_cast<WINDOW*>(window_->window());\n  nodelay(w, FALSE);\n  last_key_pressed = ERR;\n  return static_cast<unsigned char>(window_->GetChar());\n}\n\nvoid CursesLocalIO::SetCursor(int cursorStyle) { curs_set(cursorStyle); }\n\nvoid CursesLocalIO::ClrEol() {\n  SetColor(curatr());\n  window_->ClrtoEol();\n}\n\nvoid CursesLocalIO::WriteScreenBuffer(const char* buffer) {\n  // TODO(rushfan): Optimize me.\n  auto* p = buffer;\n  auto* w = std::any_cast<WINDOW*>(window_->window());\n  scrollok(w, false);\n\n  for (auto y = 0; y < 25; y++) {\n    for (auto x = 0; x < 80; x++) {\n      const auto c = *p++;\n      GotoXY(x, y);\n      curatr(*p++);\n      PutchRaw(c);\n    }\n  }\n  scrollok(w, true);\n}\n\nint CursesLocalIO::GetDefaultScreenBottom() const noexcept { return window_->GetMaxY() - 1; }\n\nstatic int GetEditLineStringLength(const char* text) {\n  auto i = size_int(text);\n  while (i >= 0 && (static_cast<unsigned char>(text[i - 1]) == 176)) {\n    --i;\n  }\n  return i;\n}\n\nvoid CursesLocalIO::EditLine(char* s, int len, AllowedKeys allowed_keys, EditlineResult* returncode,\n                             const char* allowed_set) {\n  const auto oldatr = curatr();\n  const auto cx = WhereX();\n  const auto cy = WhereY();\n  for (auto i = ssize(s); i < len; i++) {\n    s[i] = '\\xb0';\n  }\n  s[len] = '\\0';\n  curatr(GetEditLineColor());\n  FastPuts(s);\n  GotoXY(cx, cy);\n  auto done = false;\n  auto pos = 0;\n  auto insert = false;\n  do {\n    auto ch = GetChar();\n    if (ch == 0 || ch == 224) {\n      ch = GetChar();\n      switch (ch) {\n      case F1:\n        done = true;\n        *returncode = EditlineResult::DONE;\n        break;\n      case HOME:\n        pos = 0;\n        GotoXY(cx, cy);\n        break;\n      case END:\n        pos = GetEditLineStringLength(s);\n        GotoXY(cx + pos, cy);\n        break;\n      case RARROW:\n        if (pos < GetEditLineStringLength(s)) {\n          pos++;\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      case LARROW:\n        if (pos > 0) {\n          pos--;\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      case UARROW:\n      case CO:\n        done = true;\n        *returncode = EditlineResult::PREV;\n        break;\n      case DARROW:\n        done = true;\n        *returncode = EditlineResult::NEXT;\n        break;\n      case KEY_INSERT:\n        if (allowed_keys != AllowedKeys::SET) {\n          insert = !insert;\n        }\n        break;\n      case KEY_DELETE:\n        if (allowed_keys != AllowedKeys::SET) {\n          for (int i = pos; i < len; i++) {\n            s[i] = s[i + 1];\n          }\n          s[len - 1] = '\\xb0';\n          PutsXY(cx, cy, s);\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      }\n    } else {\n      if (ch > 31) {\n        if (allowed_keys == AllowedKeys::UPPER_ONLY) {\n          ch = to_upper_case<unsigned char>(ch);\n        }\n        if (allowed_keys == AllowedKeys::SET) {\n          ch = to_upper_case<unsigned char>(ch);\n          if (ch != SPACE) {\n            auto bLookingForSpace = true;\n            for (auto i = 0; i < len; i++) {\n              if (ch == allowed_set[i] && bLookingForSpace) {\n                bLookingForSpace = false;\n                pos = i;\n                GotoXY(cx + pos, cy);\n                if (s[pos] == SPACE) {\n                  ch = allowed_set[pos];\n                } else {\n                  ch = SPACE;\n                }\n              }\n            }\n            if (bLookingForSpace) {\n              ch = allowed_set[pos];\n            }\n          }\n        }\n        if ((pos < len) &&\n            ((allowed_keys == AllowedKeys::ALL) || (allowed_keys == AllowedKeys::UPPER_ONLY) ||\n             (allowed_keys == AllowedKeys::SET) ||\n             ((allowed_keys == AllowedKeys::NUM_ONLY) &&\n              (((ch >= '0') && (ch <= '9')) || (ch == SPACE))))) {\n          if (insert) {\n            for (int i = len - 1; i > pos; i--) {\n              s[i] = s[i - 1];\n            }\n            s[pos++] = static_cast<char>(ch);\n            PutsXY(cx, cy, s);\n            GotoXY(cx + pos, cy);\n          } else {\n            s[pos++] = static_cast<char>(ch);\n            Putch(ch);\n          }\n        }\n      } else {\n        // ch is > 32\n        switch (ch) {\n        case RETURN:\n        case TAB:\n          done = true;\n          *returncode = EditlineResult::NEXT;\n          break;\n        case ESC:\n          done = true;\n          *returncode = EditlineResult::ABORTED;\n          break;\n        case CA:\n          pos = 0;\n          GotoXY(cx, cy);\n          break;\n        case CE:\n          pos = GetEditLineStringLength(s); // len;\n          GotoXY(cx + pos, cy);\n          break;\n        case BACKSPACE:\n          if (pos > 0) {\n            if (insert) {\n              for (int i = pos - 1; i < len; i++) {\n                s[i] = s[i + 1];\n              }\n              s[len - 1] = '\\xb0';\n              pos--;\n              PutsXY(cx, cy, s);\n              GotoXY(cx + pos, cy);\n            } else {\n              const auto string_len = GetEditLineStringLength(s);\n              pos--;\n              if (pos == (string_len - 1)) {\n                s[pos] = '\\xb0';\n              } else {\n                s[pos] = SPACE;\n              }\n              PutsXY(cx, cy, s);\n              GotoXY(cx + pos, cy);\n            }\n          }\n          break;\n        }\n      }\n    }\n  } while (!done);\n\n  auto z = ssize(s);\n  while (z >= 0 && static_cast<unsigned char>(s[z - 1]) == 176) {\n    --z;\n  }\n  s[z] = '\\0';\n\n  char szFinishedString[260];\n  snprintf(szFinishedString, sizeof(szFinishedString), \"%-255s\", s);\n  szFinishedString[len] = '\\0';\n  GotoXY(cx, cy);\n  curatr(oldatr);\n  FastPuts(szFinishedString);\n  GotoXY(cx, cy);\n}\n\nvoid CursesLocalIO::MakeLocalWindow(int x, int y, int xlen, int ylen) {\n  // Make sure that we are within the range of {(0,0), (80,GetScreenBottom())}\n  curatr(GetUserEditorColor());\n  xlen = std::min(xlen, 80);\n  if (ylen > (GetScreenBottom() + 1 - GetTopLine())) {\n    ylen = (GetScreenBottom() + 1 - GetTopLine());\n  }\n  if ((x + xlen) > 80) {\n    x = 80 - xlen;\n  }\n  if ((y + ylen) > GetScreenBottom() + 1) {\n    y = GetScreenBottom() + 1 - ylen;\n  }\n\n  const auto xx = WhereX();\n  const auto yy = WhereY();\n\n  // we expect to be offset by GetTopLine()\n  y += GetTopLine();\n\n  // Loop through Y, each time looping through X adding the right character\n  for (int yloop = 0; yloop < ylen; yloop++) {\n    for (int xloop = 0; xloop < xlen; xloop++) {\n      curatr(static_cast<int16_t>(GetUserEditorColor()));\n      if ((yloop == 0) || (yloop == ylen - 1)) {\n        PutsXY(x + xloop, y + yloop, \"\\xC4\"); // top and bottom\n      } else {\n        if ((xloop == 0) || (xloop == xlen - 1)) {\n          PutsXY(x + xloop, y + yloop, \"\\xB3\"); // right and left sides\n        } else {\n          PutsXY(x + xloop, y + yloop, \"\\x20\"); // nothing... Just filler (space)\n        }\n      }\n    }\n  }\n\n  // sum of the lengths of the previous lines (+0) is the start of next line\n\n  /*\n  ci[0].Char.AsciiChar = '\\xDA';      // upper left\n  ci[xlen - 1].Char.AsciiChar = '\\xBF';    // upper right\n\n  ci[xlen * (ylen - 1)].Char.AsciiChar = '\\xC0';  // lower left\n  ci[xlen * (ylen - 1) + xlen - 1].Char.AsciiChar = '\\xD9'; // lower right\n  */\n  GotoXY(xx, yy);\n}\n\nvoid CursesLocalIO::UpdateNativeTitleBar([[maybe_unused]] const std::string& system_name, \n                                         [[maybe_unused]] int instance_number) {\n#ifdef _WIN32\n  // Set console title\n  const auto s = StrCat(\"WWIV Node \", instance_number, \" (\", system_name, \")\");\n  SetConsoleTitle(s.c_str());\n#else\n  \n#endif // _WIN32\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nvoid CursesLocalIO::ResetColors() { InitPairs(); }\n\nvoid CursesLocalIO::DisableLocalIO() { endwin(); }\n\nvoid CursesLocalIO::ReenableLocalIO() {\n  refresh();\n  window_->Refresh();\n}\n\n}\n"
  },
  {
    "path": "local_io/local_io_curses.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_CURSES_H\n#define INCLUDED_LOCAL_IO_CURSES_H\n\n#include \"localui/curses_win.h\"\n#include \"local_io/local_io.h\"\n#include <string>\n\nnamespace wwiv::local::io {\n\nclass CursesLocalIO final : public LocalIO {\npublic:\n  // Constructor/Destructor\n  CursesLocalIO();\n  explicit CursesLocalIO(int num_lines, int num_cols);\n  explicit CursesLocalIO(const CursesLocalIO& copy) = delete;\n  explicit CursesLocalIO(CursesLocalIO&&) = delete;\n  CursesLocalIO& operator=(const CursesLocalIO&) = delete;\n  CursesLocalIO& operator=(CursesLocalIO&&) = delete;\n  ~CursesLocalIO() override;\n\n  void GotoXY(int x, int y) override;\n  [[nodiscard]] int WhereX() const noexcept override;\n  [[nodiscard]] int WhereY() const noexcept override;\n  void Lf() override;\n  void Cr() override;\n  void Cls() override;\n  void ClrEol() override;\n  void Backspace() override;\n  void PutchRaw(unsigned char ch) override;\n  // Overridden by TestLocalIO in tests\n  void Putch(unsigned char ch) override;\n  void Puts(const std::string&) override;\n  void PutsXY(int x, int y, const std::string& text) override;\n  void PutsXYA(int x, int y, int a, const std::string& text) override;\n  void set_protect(int l) override;\n  void savescreen() override;\n  void restorescreen() override;\n  bool KeyPressed() override;\n  [[nodiscard]] unsigned char GetChar() override;\n  void MakeLocalWindow(int x, int y, int xlen, int ylen) override;\n  void SetCursor(int cursorStyle) override;\n  void WriteScreenBuffer(const char* buffer) override;\n  [[nodiscard]] int GetDefaultScreenBottom() const noexcept override;\n\n  void EditLine(char* s, int len, AllowedKeys allowed_keys, EditlineResult* returncode,\n                const char* allowed_set) override;\n  void UpdateNativeTitleBar(const std::string& system_name, int instance_number) override;\n  void ResetColors();\n\n  void DisableLocalIO() override;\n  void ReenableLocalIO() override;\n\nprivate:\n  void FastPuts(const std::string& text) override;\n  void SetColor(int color);\n  int x_{0};\n  int y_{0};\n\n  std::unique_ptr<wwiv::local::ui::CursesWindow> window_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "local_io/local_io_win32.cpp",
    "content": "/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"local_io/local_io_win32.h\"\n#include \"core/wwiv_windows.h\"\n\n#include \"core/cp437.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include <algorithm>\n#include <chrono>\n#include <conio.h>\n#include <memory>\n#include <string>\n\nnamespace wwiv::local::io {\n\n// local functions\nbool HasKeyBeenPressed(HANDLE in);\nunsigned char GetKeyboardChar();\n\nusing std::chrono::milliseconds;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing wwiv::os::sound;\n\nstruct screentype {\n  short x1, y1, topline1, curatr1;\n  CHAR_INFO* scrn1;\n};\n\nstatic screentype saved_screen;\n/*\n * Sets screen attribute at screen pos x,y to attribute contained in a.\n */\nvoid Win32ConsoleIO::set_attr_xy(int x, int y, int a) {\n  COORD loc;\n  DWORD cb = {0};\n\n  loc.X = static_cast<SHORT>(x);\n  loc.Y = static_cast<SHORT>(y);\n\n  WriteConsoleOutputAttribute(out_, reinterpret_cast<LPWORD>(&a), 1, loc, &cb);\n}\n\nWin32ConsoleIO::Win32ConsoleIO() {\n  out_ = GetStdHandle(STD_OUTPUT_HANDLE);\n  in_ = GetStdHandle(STD_INPUT_HANDLE);\n  if (out_ == INVALID_HANDLE_VALUE) {\n    std::cout << \"\\n\\nCan't get console handle!.\\n\\n\";\n    abort();\n  }\n  CONSOLE_SCREEN_BUFFER_INFO csbi{};\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  original_size_.X = csbi.dwSize.X;\n  original_size_.Y = csbi.dwSize.Y;\n  auto rect = csbi.srWindow;\n  COORD bufSize;\n  bufSize.X = static_cast<SHORT>(rect.Right - rect.Left + 1);\n  bufSize.Y = static_cast<SHORT>(rect.Bottom - rect.Top + 1);\n  // Let's not constrain it to 80x25.\n  SetConsoleWindowInfo(out_, TRUE, &rect);\n  SetConsoleScreenBufferSize(out_, bufSize);\n\n  cursor_pos_.X = csbi.dwCursorPosition.X;\n  cursor_pos_.Y = csbi.dwCursorPosition.Y;\n\n  // Have to reset this info, otherwise bad things happen.\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  GetConsoleMode(in_, &saved_input_mode_);\n  SetConsoleMode(in_, 0 | ENABLE_EXTENDED_FLAGS);\n}\n\nWin32ConsoleIO::~Win32ConsoleIO() {\n  COORD x{original_size_.X, original_size_.Y};\n  SetConsoleScreenBufferSize(out_, x);\n  SetConsoleTextAttribute(out_, 0x07);\n  SetConsoleMode(in_, saved_input_mode_);\n}\n\n// This, obviously, moves the cursor to the location specified, offset from\n// the protected display at the top of the screen.  Note: this function\n// is 0 based, so (0,0) is the upper left hand corner.\nvoid Win32ConsoleIO::GotoXY(int x, int y) {\n  CONSOLE_SCREEN_BUFFER_INFO csbi{};\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  // maybe just use original_size_.X ?\n\n  x = std::max<int>(x, 0);\n  x = std::min<int>(x, csbi.dwSize.X - 1);\n  y = std::max<int>(y, 0);\n  y += GetTopLine();\n  y = std::min<int>(y, GetScreenBottom());\n\n  cursor_pos_.X = static_cast<int16_t>(x);\n  cursor_pos_.Y = static_cast<int16_t>(y);\n  COORD c{cursor_pos_.X, cursor_pos_.Y};\n  SetConsoleCursorPosition(out_, c);\n}\n\n/* This function returns the current X cursor position, as the number of\n * characters from the left hand side of the screen.  An X position of zero\n * means the cursor is at the left-most position\n */\nint Win32ConsoleIO::WhereX() const noexcept {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n\n  cursor_pos_.X = csbi.dwCursorPosition.X;\n  cursor_pos_.Y = csbi.dwCursorPosition.Y;\n\n  return cursor_pos_.X;\n}\n\n/* This function returns the Y cursor position, as the line number from\n * the top of the logical window.  The offset due to the protected top\n * of the screen display is taken into account.  A WhereY() of zero means\n * the cursor is at the top-most position it can be at.\n */\nint Win32ConsoleIO::WhereY() const noexcept {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  cursor_pos_.X = csbi.dwCursorPosition.X;\n  cursor_pos_.Y = csbi.dwCursorPosition.Y;\n  return cursor_pos_.Y - GetTopLine();\n}\n\nvoid Win32ConsoleIO::Lf() {\n  /* This function performs a linefeed to the screen (but not remotely) by\n   * either moving the cursor down one line, or scrolling the logical screen\n   * up one line.\n   */\n  CONSOLE_SCREEN_BUFFER_INFO csbi{};\n  GetConsoleScreenBufferInfo(out_, &csbi);\n\n  SMALL_RECT scrollRect;\n  COORD dest;\n  CHAR_INFO fill;\n\n  if (cursor_pos_.Y >= GetScreenBottom()) {\n    dest.X = 0;\n    dest.Y = static_cast<int16_t>(GetTopLine());\n    scrollRect.Top = static_cast<int16_t>(GetTopLine() + 1);\n    scrollRect.Bottom = static_cast<int16_t>(GetScreenBottom());\n    scrollRect.Left = 0;\n    scrollRect.Right = csbi.dwSize.X - 1;\n    fill.Attributes = static_cast<int16_t>(curatr());\n    fill.Char.UnicodeChar = cp437_to_utf8(' ');\n\n    ScrollConsoleScreenBuffer(out_, &scrollRect, nullptr, dest, &fill);\n  } else {\n    cursor_pos_.Y++;\n    COORD c{cursor_pos_.X, cursor_pos_.Y};\n    SetConsoleCursorPosition(out_, c);\n  }\n}\n\n/**\n * Returns the local cursor to the left-most position on the screen.\n */\nvoid Win32ConsoleIO::Cr() {\n  cursor_pos_.X = 0;\n  const COORD c{cursor_pos_.X, cursor_pos_.Y};\n  SetConsoleCursorPosition(out_, c);\n}\n\n/**\n * Clears the local logical screen\n */\nvoid Win32ConsoleIO::Cls() {\n  const COORD coordScreen = {0, 0};\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  const DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y;\n  DWORD charsWriten = 0;\n\n  FillConsoleOutputCharacter(out_, ' ', dwConSize, coordScreen, &charsWriten);\n  FillConsoleOutputAttribute(out_, 7, dwConSize, coordScreen, &charsWriten);\n  GotoXY(0, 0);\n}\n\nvoid Win32ConsoleIO::Backspace() {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  /* This function moves the cursor one position to the left, or if the cursor\n   * is currently at its left-most position, the cursor is moved to the end of\n   * the previous line, except if it is on the top line, in which case nothing\n   * happens.\n   */\n  if (cursor_pos_.X >= 0) {\n    cursor_pos_.X--;\n  } else if (cursor_pos_.Y != GetTopLine()) {\n    cursor_pos_.Y--;\n    cursor_pos_.X = csbi.dwSize.X - 1;\n  }\n  COORD c{cursor_pos_.X, cursor_pos_.Y};\n  SetConsoleCursorPosition(out_, c);\n}\n\nvoid Win32ConsoleIO::PutchRaw(unsigned char ch) {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  /* This function outputs one character to the screen, then updates the\n   * cursor position accordingly, scrolling the screen if necessary.  Not that\n   * this function performs no commands such as a C/R or L/F.  If a value of\n   * 8, 7, 13, 10, 12 (BACKSPACE, BEEP, C/R, L/F, TOF), or any other command-\n   * type characters are passed, the appropriate corresponding \"graphics\"\n   * symbol will be output to the screen as a normal character.\n   */\n  DWORD cb;\n\n  SetConsoleTextAttribute(out_, static_cast<int16_t>(curatr()));\n  auto wch = cp437_to_utf8(ch);\n  WriteConsoleW(out_, &wch, 1, &cb, nullptr);\n\n  if (cursor_pos_.X < csbi.dwSize.X) {\n    cursor_pos_.X++;\n    return;\n  }\n\n  // Need to scroll the screen up one.\n  cursor_pos_.X = 0;\n  if (cursor_pos_.Y == GetScreenBottom()) {\n    COORD dest;\n    SMALL_RECT MoveRect;\n    CHAR_INFO fill;\n\n    // rushfan scrolling fix (was no +1)\n    MoveRect.Top = static_cast<int16_t>(GetTopLine() + 1);\n    MoveRect.Bottom = static_cast<int16_t>(GetScreenBottom());\n    MoveRect.Left = 0;\n    MoveRect.Right = csbi.dwSize.X - 1;\n\n    fill.Attributes = static_cast<int16_t>(curatr());\n    fill.Char.UnicodeChar = cp437_to_utf8(' ');\n\n    dest.X = 0;\n    // rushfan scrolling fix (was -1)\n    dest.Y = static_cast<int16_t>(GetTopLine());\n\n    ScrollConsoleScreenBufferW(out_, &MoveRect, &MoveRect, dest, &fill);\n  } else {\n    cursor_pos_.Y++;\n  }\n}\n\n/**\n * This function outputs one character to the local screen.  C/R, L/F, TOF,\n * BS, and BELL are interpreted as commands instead of characters.\n */\nvoid Win32ConsoleIO::Putch(unsigned char ch) {\n  if (ch > 31) {\n    PutchRaw(ch);\n  } else if (ch == CM) {\n    Cr();\n  } else if (ch == CJ) {\n    // Let's try CR-LF for local\n    Cr();\n    Lf();\n  } else if (ch == CL) {\n    Cls();\n  } else if (ch == BACKSPACE) {\n    Backspace();\n  } else if (ch == CG) {\n    // No bell.\n  }\n}\n\n// Outputs a string to the local screen.\nvoid Win32ConsoleIO::Puts(const std::string& text) {\n  for (auto ch : text) {\n    Putch(ch);\n  }\n}\n\nvoid Win32ConsoleIO::PutsXY(int x, int y, const std::string& text) {\n  GotoXY(x, y);\n  FastPuts(text);\n}\n\nvoid Win32ConsoleIO::PutsXYA(int x, int y, int a, const std::string& text) {\n  GotoXY(x, y);\n\n  const auto old_color = curatr();\n  curatr(a);\n  FastPuts(text);\n\n  curatr(old_color);\n}\n\nvoid Win32ConsoleIO::FastPuts(const std::string& text) {\n  // This RAPIDLY outputs ONE LINE to the screen only and is not exactly stable.\n  DWORD cb = 0;\n\n  SetConsoleTextAttribute(out_, static_cast<int16_t>(curatr()));\n  const auto s = cp437_to_utf8w(text);\n  WriteConsoleW(out_, s.c_str(), wwiv::stl::size_int(s), &cb, nullptr);\n  cursor_pos_.X = cursor_pos_.X + static_cast<int16_t>(cb);\n}\n\nvoid Win32ConsoleIO::set_protect(int l) {\n  // set_protect sets the number of lines protected at the top of the screen.\n  if (l != GetTopLine()) {\n    COORD coord;\n    coord.X = 0;\n    coord.Y = static_cast<int16_t>(l);\n\n    CONSOLE_SCREEN_BUFFER_INFO csbi;\n    GetConsoleScreenBufferInfo(out_, &csbi);\n\n    if (l > GetTopLine()) {\n      if ((WhereY() + GetTopLine() - l) < 0) {\n        CHAR_INFO lpFill;\n        SMALL_RECT scrnl;\n\n        scrnl.Top = static_cast<int16_t>(GetTopLine());\n        scrnl.Left = 0;\n        scrnl.Bottom = static_cast<int16_t>(GetScreenBottom());\n        scrnl.Right = csbi.dwSize.X;\n\n        lpFill.Char.UnicodeChar = cp437_to_utf8(' ');\n        lpFill.Attributes = 0;\n\n        coord.X = 0;\n        coord.Y = static_cast<int16_t>(l);\n        ScrollConsoleScreenBufferW(out_, &scrnl, nullptr, coord, &lpFill);\n        GotoXY(WhereX(), WhereY() + l - GetTopLine());\n      }\n    } else {\n      DWORD written;\n      FillConsoleOutputAttribute(out_, 0, (GetTopLine() - l) * csbi.dwSize.X, coord, &written);\n    }\n  }\n  SetTopLine(l);\n}\n\nvoid Win32ConsoleIO::savescreen() {\n  COORD topleft;\n  CONSOLE_SCREEN_BUFFER_INFO bufinfo;\n  SMALL_RECT region;\n\n  GetConsoleScreenBufferInfo(out_, &bufinfo);\n  topleft.Y = topleft.X = region.Top = region.Left = 0;\n  region.Bottom = static_cast<int16_t>(bufinfo.dwSize.Y - 1);\n  region.Right = static_cast<int16_t>(bufinfo.dwSize.X - 1);\n\n  if (!saved_screen.scrn1) {\n    saved_screen.scrn1 =\n        static_cast<CHAR_INFO*>(malloc((bufinfo.dwSize.X * bufinfo.dwSize.Y) * sizeof(CHAR_INFO)));\n  }\n\n  ReadConsoleOutput(out_, (CHAR_INFO*)saved_screen.scrn1, bufinfo.dwSize, topleft, &region);\n  saved_screen.x1 = static_cast<int16_t>(WhereX());\n  saved_screen.y1 = static_cast<int16_t>(WhereY());\n  saved_screen.topline1 = static_cast<int16_t>(GetTopLine());\n  saved_screen.curatr1 = static_cast<int16_t>(curatr());\n}\n\n/*\n * restorescreen restores a screen previously saved with savescreen\n */\nvoid Win32ConsoleIO::restorescreen() {\n  if (saved_screen.scrn1) {\n    // COORD size;\n    COORD topleft;\n    CONSOLE_SCREEN_BUFFER_INFO bufinfo;\n    SMALL_RECT region;\n\n    GetConsoleScreenBufferInfo(out_, &bufinfo);\n    topleft.Y = topleft.X = region.Top = region.Left = 0;\n    region.Bottom = static_cast<int16_t>(bufinfo.dwSize.Y - 1);\n    region.Right = static_cast<int16_t>(bufinfo.dwSize.X - 1);\n\n    WriteConsoleOutputW(out_, saved_screen.scrn1, bufinfo.dwSize, topleft, &region);\n    free(saved_screen.scrn1);\n    saved_screen.scrn1 = nullptr;\n  }\n  SetTopLine(saved_screen.topline1);\n  curatr(saved_screen.curatr1);\n  GotoXY(saved_screen.x1, saved_screen.y1);\n}\n\n/**\n * IsLocalKeyPressed - returns whether or not a key been pressed at the local console.\n *\n * @return true if a key has been pressed at the local console, false otherwise\n */\nbool Win32ConsoleIO::KeyPressed() {\n  if (extended_key_waiting_) {\n    return true;\n  }\n\n  return HasKeyBeenPressed(in_);\n}\n\n/*\n * returns the ASCII code of the next character waiting in the\n * keyboard buffer.  If there are no characters waiting in the\n * keyboard buffer, then it waits for one.\n *\n * A value of 0 is returned for all extended keys (such as F1,\n * Alt-X, etc.).  The function must be called again upon receiving\n * a value of 0 to obtain the value of the extended key pressed.\n */\nunsigned char Win32ConsoleIO::GetChar() {\n  if (extended_key_waiting_) {\n    extended_key_waiting_ = false;\n    return GetKeyboardChar();\n  }\n  const auto rc = GetKeyboardChar();\n  if (rc == 0 || rc == 0xe0) {\n    extended_key_waiting_ = true;\n  }\n  return rc;\n}\n\nvoid Win32ConsoleIO::MakeLocalWindow(int x, int y, int xlen, int ylen) {\n  // Make sure that we are within the range of {(0,0), (80,GetScreenBottom())}\n  curatr(GetUserEditorColor());\n  xlen = std::min(xlen, 80);\n  if (ylen > (GetScreenBottom() + 1 - GetTopLine())) {\n    ylen = (GetScreenBottom() + 1 - GetTopLine());\n  }\n  if ((x + xlen) > 80) {\n    x = 80 - xlen;\n  }\n  if ((y + ylen) > GetScreenBottom() + 1) {\n    y = GetScreenBottom() + 1 - ylen;\n  }\n\n  const auto xx = WhereX();\n  const auto yy = WhereY();\n\n  // we expect to be offset by GetTopLine()\n  y += GetTopLine();\n\n  // large enough to hold 80x50\n  CHAR_INFO ci[4000];\n\n  // pos is the position within the buffer\n  COORD pos = {0, 0};\n  COORD size;\n  SMALL_RECT rect;\n\n  // rect is the area on screen the buffer is to be drawn\n  rect.Top = static_cast<int16_t>(y);\n  rect.Left = static_cast<int16_t>(x);\n  rect.Right = static_cast<int16_t>(xlen + x - 1);\n  rect.Bottom = static_cast<int16_t>(ylen + y - 1);\n\n  // size of the buffer to use (lower right hand coordinate)\n  size.X = static_cast<int16_t>(xlen);\n  size.Y = static_cast<int16_t>(ylen);\n\n  // our current position within the CHAR_INFO buffer\n  auto nCiPtr = 0;\n\n  // Loop through Y, each time looping through X adding the right character\n  for (auto yloop = 0; yloop < size.Y; yloop++) {\n    for (auto xloop = 0; xloop < size.X; xloop++) {\n      ci[nCiPtr].Attributes = static_cast<int16_t>(GetUserEditorColor());\n      if ((yloop == 0) || (yloop == size.Y - 1)) {\n        ci[nCiPtr].Char.UnicodeChar = cp437_to_utf8('\\xC4'); // top and bottom\n      } else {\n        if ((xloop == 0) || (xloop == size.X - 1)) {\n          ci[nCiPtr].Char.UnicodeChar = cp437_to_utf8('\\xB3'); // right and left sides\n        } else {\n          ci[nCiPtr].Char.UnicodeChar = cp437_to_utf8('\\x20'); // nothing... Just filler (space)\n        }\n      }\n      nCiPtr++;\n    }\n  }\n\n  // sum of the lengths of the previous lines (+0) is the start of next line\n\n  ci[0].Char.UnicodeChar = cp437_to_utf8('\\xDA');        // upper left\n  ci[xlen - 1].Char.UnicodeChar = cp437_to_utf8('\\xBF'); // upper right\n\n  ci[xlen * (ylen - 1)].Char.UnicodeChar = cp437_to_utf8('\\xC0');            // lower left\n  ci[xlen * (ylen - 1) + xlen - 1].Char.UnicodeChar = cp437_to_utf8('\\xD9'); // lower right\n\n  // Send it all to the screen with 1 WIN32 API call (Windows 95's console mode API support\n  // is MUCH slower than NT/Win2k, therefore it is MUCH faster to render the buffer off\n  // screen and then write it with one fell swoop.\n\n  WriteConsoleOutputW(out_, ci, size, pos, &rect);\n\n  // Draw shadow around boxed window\n  for (auto i = 0; i < xlen; i++) {\n    set_attr_xy(x + 1 + i, y + ylen, 0x08);\n  }\n\n  for (auto i1 = 0; i1 < ylen; i1++) {\n    set_attr_xy(x + xlen, y + 1 + i1, 0x08);\n  }\n\n  GotoXY(xx, yy);\n}\n\nvoid Win32ConsoleIO::SetCursor(int cursorStyle) {\n  CONSOLE_CURSOR_INFO cursInfo;\n\n  switch (cursorStyle) {\n  case cursorNone: {\n    cursInfo.dwSize = 20;\n    cursInfo.bVisible = false;\n    SetConsoleCursorInfo(out_, &cursInfo);\n  } break;\n  case cursorSolid: {\n    cursInfo.dwSize = 100;\n    cursInfo.bVisible = true;\n    SetConsoleCursorInfo(out_, &cursInfo);\n  } break;\n  case cursorNormal:\n  default: {\n    cursInfo.dwSize = 20;\n    cursInfo.bVisible = true;\n    SetConsoleCursorInfo(out_, &cursInfo);\n  }\n  }\n}\n\nvoid Win32ConsoleIO::ClrEol() {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  DWORD cb;\n\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  const auto len = csbi.dwSize.X - WhereX();\n\n  FillConsoleOutputCharacter(out_, ' ', len, csbi.dwCursorPosition, &cb);\n  FillConsoleOutputAttribute(out_, static_cast<WORD>(curatr()), len, csbi.dwCursorPosition, &cb);\n}\n\n// NOTE: This only works for 80x25 WFC\nvoid Win32ConsoleIO::WriteScreenBuffer(const char* buffer) {\n  CHAR_INFO ci[2000] {};\n  const auto* p = buffer;\n\n  for (auto& i : ci) {\n    i.Char.UnicodeChar = cp437_to_utf8(*p++);\n    i.Attributes = static_cast<WORD>(*p++);\n  }\n\n  const COORD pos = {0, 0};\n  const COORD size = {80, 25};\n  SMALL_RECT rect = {0, 0, 79, 24};\n\n  WriteConsoleOutputW(out_, ci, size, pos, &rect);\n}\n\nint Win32ConsoleIO::GetDefaultScreenBottom() const noexcept {\n  CONSOLE_SCREEN_BUFFER_INFO csbi;\n  GetConsoleScreenBufferInfo(out_, &csbi);\n  return csbi.srWindow.Bottom - csbi.srWindow.Top;\n}\n\nbool HasKeyBeenPressed(HANDLE in) {\n  DWORD num_events; // NumPending\n  GetNumberOfConsoleInputEvents(in, &num_events);\n  if (num_events == 0) {\n    return false;\n  }\n\n  const auto input = std::make_unique<INPUT_RECORD[]>(num_events);\n  ZeroMemory(input.get(), sizeof(INPUT_RECORD) * num_events);\n\n  DWORD actually_read;\n  if (PeekConsoleInput(in, input.get(), num_events, &actually_read)) {\n    for (DWORD i = 0; i < actually_read; i++) {\n      if (input[i].EventType != KEY_EVENT) {\n        continue;\n      }\n      if (!input[i].Event.KeyEvent.bKeyDown) {\n        continue;\n      }\n      if (input[i].Event.KeyEvent.wVirtualKeyCode == VK_SHIFT ||\n          input[i].Event.KeyEvent.wVirtualKeyCode == VK_CONTROL ||\n          input[i].Event.KeyEvent.wVirtualKeyCode == VK_MENU) {\n        continue;\n      }\n      if (input[i].Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED ||\n          input[i].Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED) {\n        // VLOG(3) << \"ALT KEY uchar=\" << input[i].Event.KeyEvent.uChar.AsciiChar << \"} \";\n      }\n      // VLOG(3) << \"{KeyCode=\" << input[i].Event.KeyEvent.wVirtualKeyCode << \"; ScanCode=\"\n      //          << input[i].Event.KeyEvent.wVirtualScanCode << \", char=\"\n      //          << input[i].Event.KeyEvent.uChar.AsciiChar << \"} \";\n      return true;\n    }\n  }\n  return false;\n}\n\n// Use _getwch to work around https://github.com/wwivbbs/wwiv/issues/1113\nunsigned char GetKeyboardChar() { return static_cast<unsigned char>(_getwch()); }\n\nstatic int GetEditLineStringLength(const char* text) {\n  auto i = ssize(text);\n  while (i >= 0 && (/*text[i-1] == 32 ||*/ static_cast<unsigned char>(text[i - 1]) == 176)) {\n    --i;\n  }\n  return i;\n}\n\nvoid Win32ConsoleIO::EditLine(char* in, int len, AllowedKeys allowed_keys,\n                              EditlineResult* returncode, const char* allowed) {\n\n  const auto oldatr = curatr();\n  const auto cx = WhereX();\n  const auto cy = WhereY();\n  for (auto i = wwiv::strings::ssize(in); i < len; i++) {\n    in[i] = '\\xb0'; // 176\n  }\n  in[len] = '\\0';\n  curatr(GetEditLineColor());\n  FastPuts(in);\n  GotoXY(cx, cy);\n  auto done = false;\n  auto pos = 0;\n  auto insert = false;\n  do {\n    if (auto ch = GetChar(); ch == 0 || ch == 224) {\n      ch = GetChar();\n      switch (ch) {\n      case F1:\n        done = true;\n        *returncode = EditlineResult::DONE;\n        break;\n      case HOME:\n        pos = 0;\n        GotoXY(cx, cy);\n        break;\n      case END:\n        pos = GetEditLineStringLength(in);\n        GotoXY(cx + pos, cy);\n        break;\n      case RARROW:\n        if (pos < GetEditLineStringLength(in)) {\n          pos++;\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      case LARROW:\n        if (pos > 0) {\n          pos--;\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      case UARROW:\n      case CO:\n        done = true;\n        *returncode = EditlineResult::PREV;\n        break;\n      case DARROW:\n        done = true;\n        *returncode = EditlineResult::NEXT;\n        break;\n      case KEY_INSERT:\n        if (allowed_keys != AllowedKeys::SET) {\n          insert = !insert;\n        }\n        break;\n      case KEY_DELETE:\n        if (allowed_keys != AllowedKeys::SET) {\n          for (int i = pos; i < len; i++) {\n            in[i] = in[i + 1];\n          }\n          in[len - 1] = '\\xb0'; // 176\n          PutsXY(cx, cy, in);\n          GotoXY(cx + pos, cy);\n        }\n        break;\n      }\n    } else {\n      if (ch > 31) {\n        if (allowed_keys == AllowedKeys::UPPER_ONLY) {\n          ch = to_upper_case<unsigned char>(ch);\n        }\n        if (allowed_keys == AllowedKeys::SET) {\n          ch = to_upper_case<unsigned char>(ch);\n          if (ch != SPACE) {\n            auto looking_for_space = true;\n            for (int i = 0; i < len; i++) {\n              if (ch == allowed[i] && looking_for_space) {\n                looking_for_space = false;\n                pos = i;\n                GotoXY(cx + pos, cy);\n                if (in[pos] == SPACE) {\n                  ch = allowed[pos];\n                } else {\n                  ch = SPACE;\n                }\n              }\n            }\n            if (looking_for_space) {\n              ch = allowed[pos];\n            }\n          }\n        }\n        if (pos < len &&\n            (allowed_keys == AllowedKeys::ALL || allowed_keys == AllowedKeys::UPPER_ONLY ||\n             allowed_keys == AllowedKeys::SET ||\n             allowed_keys == AllowedKeys::NUM_ONLY &&\n             (ch >= '0' && ch <= '9' || ch == SPACE))) {\n          if (insert) {\n            for (auto i = len - 1; i > pos; i--) {\n              in[i] = in[i - 1];\n            }\n            in[pos++] = ch;\n            PutsXY(cx, cy, in);\n            GotoXY(cx + pos, cy);\n          } else {\n            in[pos++] = ch;\n            Putch(ch);\n          }\n        }\n      } else {\n        // ch is > 32\n        switch (ch) {\n        case RETURN:\n        case TAB:\n          done = true;\n          *returncode = EditlineResult::NEXT;\n          break;\n        case ESC:\n          done = true;\n          *returncode = EditlineResult::ABORTED;\n          break;\n        case CA:\n          pos = 0;\n          GotoXY(cx, cy);\n          break;\n        case CE:\n          pos = GetEditLineStringLength(in); // len;\n          GotoXY(cx + pos, cy);\n          break;\n        case BACKSPACE:\n          if (pos > 0) {\n            if (insert) {\n              for (int i = pos - 1; i < len; i++) {\n                in[i] = in[i + 1];\n              }\n              in[len - 1] = '\\xb0'; // 176\n              pos--;\n              PutsXY(cx, cy, in);\n              GotoXY(cx + pos, cy);\n            } else {\n              const auto ell = GetEditLineStringLength(in);\n              pos--;\n              if (pos == (ell - 1)) {\n                in[pos] = '\\xb0'; // 176\n              } else {\n                in[pos] = SPACE;\n              }\n              PutsXY(cx, cy, in);\n              GotoXY(cx + pos, cy);\n            }\n          }\n          break;\n        }\n      }\n    }\n  } while (!done);\n\n  auto z = ssize(in);\n  while (z >= 0 && static_cast<unsigned char>(in[z - 1]) == 176) {\n    --z;\n  }\n  in[z] = '\\0';\n\n  char szFinishedString[260];\n  snprintf(szFinishedString, sizeof(szFinishedString), \"%-255s\", in);\n  szFinishedString[len] = '\\0';\n  GotoXY(cx, cy);\n  curatr(oldatr);\n  FastPuts(szFinishedString);\n  GotoXY(cx, cy);\n}\n\nvoid Win32ConsoleIO::UpdateNativeTitleBar(const std::string& system_name, int instance_number) {\n  // Set console title\n  const auto s = StrCat(\"WWIV Node \", instance_number, \" (\", system_name, \")\");\n  SetConsoleTitle(s.c_str());\n}\n\n}\n"
  },
  {
    "path": "local_io/local_io_win32.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_LOCAL_IO_WIN32_H\n#define INCLUDED_LOCAL_IO_LOCAL_IO_WIN32_H\n\n#include \"core/file.h\"\n#include \"local_io/local_io.h\"\n#include <string>\n\nnamespace wwiv::local::io {\n\n// This C++ class should encompass all Local Input/Output from The BBS.\n// You should use a routine in here instead of using printf, puts, etc.\n\nstruct coord_t {\n  int16_t X;\n  int16_t Y;\n};\n\ntypedef void* HANDLE;\n\nclass Win32ConsoleIO final : public LocalIO {\npublic:\n  // Constructor/Destructor\n  Win32ConsoleIO();\n  explicit Win32ConsoleIO(const LocalIO& copy) = delete;\n  virtual ~Win32ConsoleIO();\n\n  void GotoXY(int x, int y) override;\n  int WhereX() const noexcept override;\n  int WhereY() const noexcept override;\n  void Lf() override;\n  void Cr() override;\n  void Cls() override;\n  void ClrEol() override;\n  void Backspace() override;\n  void PutchRaw(unsigned char ch) override;\n  // Overridden by TestLocalIO in tests\n  void Putch(unsigned char ch) override;\n  void Puts(const std::string& text) override;\n  void PutsXY(int x, int y, const std::string& text) override;\n  void PutsXYA(int x, int y, int a, const std::string& text) override;\n  void set_protect(int l) override;\n  void savescreen() override;\n  void restorescreen() override;\n  bool KeyPressed() override;\n  unsigned char GetChar() override;\n  void MakeLocalWindow(int x, int y, int xlen, int ylen) override;\n  void SetCursor(int cursorStyle) override;\n  void WriteScreenBuffer(const char* buffer) override;\n  int GetDefaultScreenBottom() const noexcept override;\n\n  void EditLine(char* in, int len, AllowedKeys allowed_keys, EditlineResult* returncode,\n                const char* allowed) override;\n  void UpdateNativeTitleBar(const std::string& system_name, int instance_number) override;\n\nprivate:\n  void FastPuts(const std::string& text) override;\n\nprivate:\n  void set_attr_xy(int x, int y, int a);\n\n  bool extended_key_waiting_{false};\n  // We set this when calling wherex, but logically WhereX should\n  // be const correct, so we'll handle this nasty stuff here.\n  mutable coord_t cursor_pos_{};\n  HANDLE out_ = (void*)-1;\n  HANDLE in_ = (void*)-1;\n  unsigned long /* DWORD */ saved_input_mode_{0};\n  coord_t original_size_{};\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "local_io/null_local_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                                WWIV Version 5                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"local_io/null_local_io.h\"\n\nnamespace wwiv::local::io {\n\nNullLocalIO::NullLocalIO() = default;\nNullLocalIO::~NullLocalIO() = default;\n\n}"
  },
  {
    "path": "local_io/null_local_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_NULL_LOCAL_IO_H\n#define INCLUDED_LOCAL_IO_NULL_LOCAL_IO_H\n#include \"local_io/local_io.h\"\n\n#include <string>\n\nnamespace wwiv::local::io {\n\nclass NullLocalIO final : public LocalIO {\npublic:\n  NullLocalIO();\n  ~NullLocalIO() override;\n  void Putch(unsigned char) override {}\n  void GotoXY(int, int) override {}\n  [[nodiscard]] int WhereX() const noexcept override { return 0; }\n  [[nodiscard]] int WhereY() const noexcept override { return 0; }\n  void Lf() override {}\n  void Cr() override {}\n  void Cls() override {}\n  void Backspace() override {}\n  void PutchRaw(unsigned char) override {}\n  void Puts(const std::string&) override {}\n  void PutsXY(int, int, const std::string&) override {}\n  void PutsXYA(int, int, int, const std::string&) override {}\n  void set_protect(int) override {}\n  void savescreen() override {}\n  void restorescreen() override {}\n  [[nodiscard]] bool KeyPressed() override { return false; }\n  [[nodiscard]] unsigned char GetChar() override { return static_cast<unsigned char>(getchar()); }\n  void MakeLocalWindow(int, int, int, int) override {}\n  void SetCursor(int) override {}\n  void ClrEol() override {}\n  void WriteScreenBuffer(const char*) override {}\n  [[nodiscard]] int GetDefaultScreenBottom() const noexcept override { return 24; }\n  void EditLine(char*, int, AllowedKeys, EditlineResult*,\n                const char*) override {}\n  void UpdateNativeTitleBar(const std::string&, int) override {}\n\nprivate:\n  void FastPuts(const std::string&) override {}\n};\n}\n\n#endif"
  },
  {
    "path": "local_io/stdio_local_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                                WWIV Version 5                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"local_io/stdio_local_io.h\"\n\n#include <cstdio>\n\nnamespace wwiv::local::io {\n\nStdioLocalIO::StdioLocalIO() = default;\nStdioLocalIO::~StdioLocalIO() = default;\n\nvoid StdioLocalIO::Putch(unsigned char ch) { putchar(ch); };\n\nvoid StdioLocalIO::Lf() { putchar(10); }\n\nvoid StdioLocalIO::Cr() { putchar(13); }\n\nvoid StdioLocalIO::Cls() {}\n\nvoid StdioLocalIO::Backspace() { putchar(8); }\n\nvoid StdioLocalIO::PutchRaw(unsigned char ch) { putchar(ch); }\n\nvoid StdioLocalIO::Puts(const std::string& s) { puts(s.c_str()); }\n\nvoid StdioLocalIO::PutsXY(int, int, const std::string& text) { Puts(text); }\n\nvoid StdioLocalIO::PutsXYA(int, int, int, const std::string& text) { Puts(text); }\n\nvoid StdioLocalIO::FastPuts(const std::string& text) { Puts(text); }\n\n}\n"
  },
  {
    "path": "local_io/stdio_local_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_STDIO_LOCAL_IO_H\n#define INCLUDED_LOCAL_IO_STDIO_LOCAL_IO_H\n\n#include \"local_io/local_io.h\"\n\n#include <string>\n\nnamespace wwiv::local::io {\n\nclass StdioLocalIO final : public LocalIO {\npublic:\n  StdioLocalIO();\n  ~StdioLocalIO() override;\n  void Putch(unsigned char ch) override;\n  void GotoXY(int, int) override {}\n  [[nodiscard]] int WhereX() const noexcept override { return 0; }\n  [[nodiscard]]int WhereY() const noexcept override { return 0; }\n\n  void Lf() override;\n  void Cr() override;\n  void Cls() override;\n  void Backspace() override;\n  void PutchRaw(unsigned char ch) override;\n  void Puts(const std::string& s) override;\n  void PutsXY(int x, int y, const std::string& text) override;\n  void PutsXYA(int x, int y, int a, const std::string& text) override;\n\n  void set_protect(int) override {}\n  void savescreen() override {}\n  void restorescreen() override {}\n  bool KeyPressed() override { return false; }\n  unsigned char GetChar() override { return static_cast<unsigned char>(getchar()); }\n  void MakeLocalWindow(int, int, int, int) override {}\n  void SetCursor(int) override {}\n  void ClrEol() override {}\n  void WriteScreenBuffer(const char*) override {}\n  [[nodiscard]] int GetDefaultScreenBottom() const noexcept override { return 24; }\n  void EditLine(char*, int, AllowedKeys, EditlineResult*,\n                const char*) override {}\n  void UpdateNativeTitleBar(const std::string&, int) override {}\n\nprivate:\n  void FastPuts(const std::string& text) override;\n};\n\n}\n\n\n#endif\n"
  },
  {
    "path": "local_io/wconstants.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCAL_IO_WCONSTANTS_H\n#define INCLUDED_LOCAL_IO_WCONSTANTS_H\n\n// Defines for Q/Nscan Plus\nconstexpr int QSCAN = 0;\nconstexpr int NSCAN = 1;\n\nconstexpr int INST_FORMAT_OLD = 0;\nconstexpr int INST_FORMAT_WFC = 1;\nconstexpr int INST_FORMAT_LIST = 2;\n\nconstexpr int NUM_DOTS = 5;\nconstexpr int FRAME_COLOR = 7;\n\n//\n// Protocols\n//\nconstexpr int WWIV_INTERNAL_PROT_ASCII = 1;\nconstexpr int WWIV_INTERNAL_PROT_XMODEM = 2;\nconstexpr int WWIV_INTERNAL_PROT_XMODEMCRC = 3;\nconstexpr int WWIV_INTERNAL_PROT_YMODEM = 4;\nconstexpr int WWIV_INTERNAL_PROT_BATCH = 5;\nconstexpr int WWIV_INTERNAL_PROT_ZMODEM = 6;\nconstexpr int WWIV_NUM_INTERNAL_PROTOCOLS = 7; // last protocol +1\n\nconstexpr int MAX_ARCS = 15;\nconstexpr int MAXMAIL = 255;\n\nconstexpr int LIST_USERS_MESSAGE_AREA = 0;\nconstexpr int LIST_USERS_FILE_AREA = 1;\n\n// Time\nconstexpr long MINUTES_PER_HOUR = 60L;\nconstexpr long SECONDS_PER_MINUTE = 60L;\nconstexpr long SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE;\nconstexpr long HOURS_PER_DAY = 24L;\nconstexpr long SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;\n\n#endif"
  },
  {
    "path": "localui/CMakeLists.txt",
    "content": "# CMake for WWIV 5\nInclude(FindWWIVCurses)\n\nset(COMMON_SOURCES\n  \"colors.cpp\"\n  \"curses_io.cpp\"\n  \"curses_win.cpp\"\n  \"edit_items.cpp\"\n  \"input.cpp\"\n  \"listbox.cpp\"\n  \"stdio_win.cpp\"\n  )\n\nadd_library(localui ${COMMON_SOURCES} ${PLATFORM_SOURCES})\ntarget_link_libraries(localui ${CURSES_LIBRARIES} fmt::fmt-header-only)\nset_max_warnings(localui)\n"
  },
  {
    "path": "localui/colors.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"colors.h\"\n\n#include \"core/strings.h\"\n#include \"localui/wwiv_curses.h\"\n\nnamespace wwiv::local::ui {\n\nSchemeDescription::SchemeDescription(SchemeId scheme, int f, int b, bool bold)\n  : scheme_(scheme), f_(f), b_(b), bold_(bold) {}\n\nSchemeDescription::SchemeDescription() \n  : scheme_(SchemeId::UNKNOWN), f_(COLOR_MAGENTA), b_(COLOR_RED), bold_(true) {\n}\n\nColorScheme::ColorScheme() : scheme_(LoadColorSchemes()) {\n  ColorScheme::InitPairs();\n}\n\nuint32_t ColorScheme::GetAttributesForScheme(SchemeId id) const {\n  const auto& s = scheme_.at(id);\n  auto attr = COLOR_PAIR(s.color_pair());\n  if (s.bold()) {\n    attr |= A_BOLD;\n  }\n  return attr;\n}\n\n\nvoid ColorScheme::InitPairs() {\n  // Create the color pairs for each of the colors defined in the color scheme.\n  for (const auto& kv : scheme_) {\n    init_pair(static_cast<short>(kv.second.color_pair()),\n              static_cast<short>(kv.second.f()),\n              static_cast<short>(kv.second.b()));\n  }\n\n}\n\n\n// static \nstd::map<SchemeId, SchemeDescription> ColorScheme::LoadColorSchemes() {\n  std::map<SchemeId, SchemeDescription> scheme;\n\n  // Create a default color scheme, ideally this would be loaded from an INI file or some other\n  // configuration file, but this is a sufficient start.\n  scheme[SchemeId::NORMAL] = SchemeDescription(SchemeId::NORMAL, COLOR_CYAN, COLOR_BLACK, false);\n  scheme[SchemeId::ERROR_TEXT] = SchemeDescription(SchemeId::ERROR_TEXT, COLOR_RED, COLOR_BLACK, false);\n  scheme[SchemeId::WARNING] = SchemeDescription(SchemeId::WARNING, COLOR_MAGENTA, COLOR_BLACK, true);\n  scheme[SchemeId::HIGHLIGHT] = SchemeDescription(SchemeId::HIGHLIGHT, COLOR_CYAN, COLOR_BLACK, true);\n  scheme[SchemeId::HEADER] = SchemeDescription(SchemeId::HEADER, COLOR_YELLOW, COLOR_BLUE, true);\n  scheme[SchemeId::HEADER_COPYRIGHT] = SchemeDescription(SchemeId::HEADER_COPYRIGHT, COLOR_WHITE, COLOR_BLUE, true);\n  scheme[SchemeId::FOOTER_KEY] = SchemeDescription(SchemeId::FOOTER_KEY, COLOR_YELLOW, COLOR_BLUE, true);\n  scheme[SchemeId::FOOTER_TEXT] = SchemeDescription(SchemeId::FOOTER_TEXT, COLOR_CYAN, COLOR_BLUE, false);\n  scheme[SchemeId::PROMPT] = SchemeDescription(SchemeId::PROMPT, COLOR_YELLOW, COLOR_BLACK, true);\n  scheme[SchemeId::EDITLINE] = SchemeDescription(SchemeId::EDITLINE, COLOR_WHITE, COLOR_BLUE, true);\n  scheme[SchemeId::INFO] = SchemeDescription(SchemeId::INFO, COLOR_CYAN, COLOR_BLACK, false);\n  scheme[SchemeId::DIALOG_PROMPT] = SchemeDescription(SchemeId::DIALOG_PROMPT, COLOR_YELLOW, COLOR_BLUE, true);\n  scheme[SchemeId::DIALOG_BOX] = SchemeDescription(SchemeId::DIALOG_BOX, COLOR_GREEN, COLOR_BLUE, true);\n  scheme[SchemeId::DIALOG_TEXT] = SchemeDescription(SchemeId::DIALOG_TEXT, COLOR_CYAN, COLOR_BLUE, true);\n  scheme[SchemeId::DIALOG_SELECTION] = SchemeDescription(SchemeId::DIALOG_SELECTION, COLOR_CYAN, COLOR_BLUE, true);\n  scheme[SchemeId::WINDOW_BOX] = SchemeDescription(SchemeId::WINDOW_BOX, COLOR_CYAN, COLOR_BLACK, true);\n  scheme[SchemeId::WINDOW_TEXT] = SchemeDescription(SchemeId::WINDOW_TEXT, COLOR_CYAN, COLOR_BLACK, false);\n  scheme[SchemeId::WINDOW_SELECTED] = SchemeDescription(SchemeId::WINDOW_SELECTED, COLOR_CYAN , COLOR_BLACK, true);\n  scheme[SchemeId::WINDOW_PROMPT] = SchemeDescription(SchemeId::WINDOW_PROMPT, COLOR_YELLOW, COLOR_BLACK, true);\n  scheme[SchemeId::DESKTOP] = SchemeDescription(SchemeId::DESKTOP, COLOR_CYAN, COLOR_BLACK, false);\n  scheme[SchemeId::WINDOW_DATA] = SchemeDescription(SchemeId::WINDOW_SELECTED, COLOR_YELLOW, COLOR_BLACK, true);\n  scheme[SchemeId::WINDOW_TITLE] = SchemeDescription(SchemeId::WINDOW_TITLE, COLOR_YELLOW, COLOR_BLUE, true);\n  return scheme;\n}\n\n}"
  },
  {
    "path": "localui/colors.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_COLORS_H\n#define INCLUDED_LOCALUI_COLORS_H\n\n#include <map>\n#include <memory>\n\nnamespace wwiv::local::ui {\n\n\n// Color Scheme\nenum class SchemeId { \n  NORMAL=1, ERROR_TEXT, WARNING, HIGHLIGHT, HEADER, HEADER_COPYRIGHT, \n  FOOTER_KEY, FOOTER_TEXT, \n  PROMPT, EDITLINE, INFO, \n  DIALOG_PROMPT, DIALOG_BOX, DIALOG_TEXT, DIALOG_SELECTION,\n  WINDOW_BOX, WINDOW_TEXT, WINDOW_SELECTED, WINDOW_PROMPT,\n  WINDOW_DATA, WINDOW_TITLE,\n  DESKTOP,\n  UNKNOWN\n};\n\n// Describes a color scheme.\nclass SchemeDescription {\npublic:\n  SchemeDescription(SchemeId scheme, int f, int b, bool bold);\n\n  // Make the unknown scheme magenta on a red background to make it easy to spot.\n  SchemeDescription();\n\n  // Don't provide a user defined destructor since that will block move semantics\n\n  [[nodiscard]] int color_pair() const { return static_cast<int>(scheme_); }\n  [[nodiscard]] int f() const { return f_; }\n  [[nodiscard]] int b() const { return b_; }\n  [[nodiscard]] bool bold() const { return bold_; }\n\nprivate:\n  SchemeId scheme_;\n  int f_;\n  int b_;\n  bool bold_;\n};\n\n\n// Curses implementation of a list box.\nclass ColorScheme {\n public:\n  ColorScheme();\n  virtual ~ColorScheme() = default;\n  [[nodiscard]] virtual uint32_t GetAttributesForScheme(SchemeId id) const;\n  ColorScheme& operator=(const ColorScheme&) = delete;\n  virtual void InitPairs();\nprivate:\n  static std::map<SchemeId, SchemeDescription> LoadColorSchemes();\n  const std::map<SchemeId, SchemeDescription> scheme_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/curses_io.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n// Always declare wwiv_windows.h first to avoid collisions on defines.\n#include \"core/wwiv_windows.h\"\n\n#include \"localui/curses_io.h\"\n#include \"core/strings.h\"\n#include \"localui/wwiv_curses.h\"\n#include <algorithm>\n#include <iostream>\n#include <memory>\n#include <stdexcept>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::local::ui {\n\nstatic const char* copyrightString = \"Copyright (c) 1998-2023, WWIV Software Services\";\n\n#if defined ( _WIN32 )\nstatic HANDLE hConOut;\nstatic COORD originalConsoleSize;\n#endif\n\nCursesIO* curses_out = nullptr;\n\nvoid CursesFooter::ShowHelpItems(int line, const std::vector<HelpItem>& help_items) const {\n  if (line < 0 || line > 1) {\n    line = 0;\n  }\n  window_->Move(line, 0);\n  window_->ClrtoEol();\n  for (const auto& h : help_items) {\n    window_->SetColor(SchemeId::FOOTER_KEY);\n    window_->Puts(h.key);\n    window_->SetColor(SchemeId::FOOTER_TEXT);\n    window_->Puts(\"-\");\n    window_->Puts(h.description);\n    window_->Puts(\" \");\n  }\n  window_->Refresh();\n}\n\nvoid CursesFooter::ShowContextHelp(const std::string& help_text) const {\n  window_->Move(1, 0);\n  window_->ClrtoEol();\n  window_->Puts(help_text);\n}\n\nvoid CursesFooter::SetDefaultFooter() const {\n  window_->Erase();\n  window_->Move(0, 0);\n  window_->SetColor(SchemeId::FOOTER_KEY);\n  window_->PutsXY(0, 0, \"Esc\");\n  window_->SetColor(SchemeId::FOOTER_TEXT);\n  window_->Puts(\"-Exit \");\n  window_->Refresh();\n}\n\nCursesIO::CursesIO(const std::string& title) \n    : max_x_(0), max_y_(0), window_(nullptr), footer_(nullptr), \n      header_(nullptr), indicator_mode_(IndicatorMode::none) {\n\n#ifdef _WIN32\n  // Save the original window size and also resize the window buffer size\n  // to match the visible window size so we do not have scroll bars.  The\n  // scroll bars don't work with text based UIs well so we will remove them\n  // like we do in bbs.exe\n  hConOut = GetStdHandle(STD_OUTPUT_HANDLE);\n  if (hConOut != INVALID_HANDLE_VALUE) {\n    CONSOLE_SCREEN_BUFFER_INFO consoleBufferInfo;\n    GetConsoleScreenBufferInfo(hConOut, &consoleBufferInfo);\n    originalConsoleSize = consoleBufferInfo.dwSize;\n    auto rect = consoleBufferInfo.srWindow;\n    COORD bufSize;\n    bufSize.X = static_cast<SHORT>(rect.Right - rect.Left + 1);\n    bufSize.Y = static_cast<SHORT>(rect.Bottom - rect.Top + 1);\n    bufSize.X = static_cast<SHORT>(std::min<SHORT>(bufSize.X, 80));\n    bufSize.Y = static_cast<SHORT>(std::min<SHORT>(bufSize.Y, 25));\n    SetConsoleWindowInfo(hConOut, TRUE, &rect);\n    SetConsoleScreenBufferSize(hConOut, bufSize);\n\n    // Have to reset this info, otherwise bad things happen.\n    GetConsoleScreenBufferInfo(hConOut, &consoleBufferInfo);\n  }\n#endif  // _WIN32\n\n  initscr();\n  raw();\n  keypad(stdscr, TRUE);\n  noecho();\n  nonl();\n  start_color();\n  color_scheme_.reset(new ColorScheme());\n  InitDosColorPairs(100);\n\n  const auto stdscr_maxx = getmaxx(stdscr);\n  const auto stdscr_maxy = getmaxy(stdscr);\n\n  if (stdscr_maxx < 80) {\n    endwin();\n    throw std::runtime_error(StrCat(\"Screen width must be at least 80, was: \", stdscr_maxx));\n  }\n  if (stdscr_maxy < 20) {\n    endwin();\n    throw std::runtime_error(StrCat(\"Screen height must be at least 20, was: \", stdscr_maxy));\n  }\n\n  header_.reset(new CursesWindow(nullptr, color_scheme_.get(), 2, 0));\n  footer_.reset(new CursesFooter(new CursesWindow(nullptr, color_scheme_.get(), 2, 0, stdscr_maxy-2, 0), \n    color_scheme_.get()));\n  header_->Bkgd(color_scheme_->GetAttributesForScheme(SchemeId::HEADER));\n  header_->SetColor(SchemeId::HEADER);\n  header_->PutsXY(0, 0, title);\n  header_->SetColor(SchemeId::HEADER_COPYRIGHT);\n  header_->PutsXY(0, 1, copyrightString);\n  footer_->window()->Bkgd(color_scheme_->GetAttributesForScheme(SchemeId::HEADER));\n  header_->Refresh();\n  footer_->window()->Refresh();\n  header_->RedrawWin();\n\n  window_.reset(new CursesWindow(nullptr, color_scheme_.get(), stdscr_maxy-4, stdscr_maxx, 2, 0));\n  window_->Keypad(true);\n\n  touchwin(stdscr);\n  max_x_ = window_->GetMaxX();\n  max_y_ = window_->GetMaxY();\n  window_->TouchWin();\n  window_->Refresh();\n}\n\nCursesIO::~CursesIO() {\n  endwin();\n\n#ifdef _WIN32\n  // restore the original window size.\n  SetConsoleScreenBufferSize(hConOut, originalConsoleSize);\n#endif  // _WIN32\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nvoid CursesIO::InitDosColorPairs(short start) {\n  std::vector<short> lowbit_colors = {COLOR_BLACK, COLOR_BLUE,    COLOR_GREEN,  COLOR_CYAN,\n                                      COLOR_RED,   COLOR_MAGENTA, COLOR_YELLOW, COLOR_WHITE};\n  auto num = start;\n  for (auto bg = 0; bg < 8; bg++) {\n    for (auto fg = 0; fg < 8; fg++) {\n      init_pair(num++, lowbit_colors[fg], lowbit_colors[bg]);\n    }\n  }\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nvoid CursesIO::DisableLocalIO() { endwin(); }\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nvoid CursesIO::ReenableLocalIO() {\n  refresh();\n  footer()->window()->RedrawWin();\n  footer()->window()->Refresh();\n  header()->RedrawWin();\n  header()->Refresh();\n  window()->RedrawWin();\n  window()->Refresh();\n}\n\n/**\n * Clears the local logical screen\n */\n// ReSharper disable once CppMemberFunctionMayBeConst\nvoid CursesIO::Cls(uint32_t background_char) {\n  window_->SetColor(SchemeId::NORMAL);\n  window_->Bkgd(background_char);\n  window_->Clear();\n  window_->Refresh();\n  window_->GotoXY(0, 0);\n}\n\nvoid CursesIO::SetIndicatorMode(IndicatorMode mode) {\n  if (mode == indicator_mode_) {\n    return;\n  }\n  std::string s = \"   \";\n  if (mode == IndicatorMode::insert) {\n    s = \"INS\";\n  } else if (mode == IndicatorMode::overwrite) {\n    s = \"OVR\";\n  }\n  header_->PutsXY(max_x_ - 5, 1, s);\n  header_->Refresh();\n  indicator_mode_ = mode;\n}\n\nCursesWindow* CursesIO::CreateBoxedWindow(const std::string& title, int nlines, int ncols) const {\n  ncols = std::max<int>(ncols, title.size() + 6);\n  std::unique_ptr<CursesWindow> window(new CursesWindow(window_.get(), color_scheme_.get(), nlines, ncols));\n  window->SetColor(SchemeId::WINDOW_BOX);\n  window->Box(0, 0);\n  window->SetTitle(title);\n  window->SetColor(SchemeId::WINDOW_TEXT);\n  return window.release();\n}\n\n// static\nvoid CursesIO::Init(const std::string& title) {\n  const auto once_init = [=]() { curses_out = new CursesIO(title); return true; };\n  [[maybe_unused]] static auto initialized_once = once_init();\n}\n\n// static \nCursesIO* CursesIO::Get() {\n  return curses_out;\n}\n\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nint CursesIO::GetMaxX() const {\n  return getmaxx(stdscr);\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nint CursesIO::GetMaxY() const {\n  return getmaxy(stdscr);\n}\n\n}"
  },
  {
    "path": "localui/curses_io.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_CURSES_IO_H\n#define INCLUDED_LOCALUI_CURSES_IO_H\n\n#include \"localui/curses_win.h\"\n#include \"localui/colors.h\"\n#include <memory>\n#include <vector>\n\nnamespace wwiv::local::ui {\n\n\n// Indicator mode for the header bar while editing text.\nenum class IndicatorMode { insert, overwrite, none };\n\nstruct HelpItem {\n  std::string key;\n  std::string description;\n};\n\nclass CursesFooter final {\npublic:\n  CursesFooter(CursesWindow* window, ColorScheme* color_scheme) \n    : window_(window), color_scheme_(color_scheme) {}\n  ~CursesFooter() = default;\n  void ShowHelpItems(int line, const std::vector<HelpItem>& help_items) const;\n  void ShowContextHelp(const std::string& help_text) const;\n  void SetDefaultFooter() const;\n  [[nodiscard]] CursesWindow* window() const { return window_.get(); }\n\n private:\n   std::unique_ptr<CursesWindow> window_;\n   ColorScheme* color_scheme_;\n};\n\n// Curses implementation of screen display routines for wwivconfig.\nclass CursesIO final {\n public:\n  // Constructor/Destructor\n  explicit CursesIO(const std::string& title);\n  CursesIO(const CursesIO& copy) = delete;\n  ~CursesIO();\n  // Initializes the DOS colors starting at 'start'.\n  void InitDosColorPairs(short start = 100);\n  void DisableLocalIO();\n\n  void ReenableLocalIO();\n  void Cls(uint32_t background_char = ' ');\n  [[nodiscard]] CursesWindow* window() const { return window_.get(); }\n  [[nodiscard]] CursesFooter* footer() const { return footer_.get(); }\n  [[nodiscard]] CursesWindow* header() const { return header_.get(); }\n  void SetIndicatorMode(IndicatorMode mode);\n\n  [[nodiscard]] CursesWindow* CreateBoxedWindow(const std::string& title, int nlines, int ncols) const;\n\n  [[nodiscard]] ColorScheme* color_scheme() const { return color_scheme_.get(); }\n  static void Init(const std::string& title);\n  [[nodiscard]] static CursesIO* Get();\n  [[nodiscard]] int GetMaxX() const;\n  [[nodiscard]] int GetMaxY() const;\n\n private:\n  int max_x_;\n  int max_y_;\n  std::unique_ptr<CursesWindow> window_;\n  std::unique_ptr<CursesFooter> footer_;\n  std::unique_ptr<CursesWindow> header_;\n  IndicatorMode indicator_mode_;\n  std::unique_ptr<ColorScheme> color_scheme_;\n};\n\nextern CursesIO* curses_out;\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/curses_win.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"localui/curses_win.h\"\n\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"localui/wwiv_curses.h\"\n\n#include <algorithm>\n#include <chrono>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::local::ui {\n\nCursesWindow::CursesWindow(CursesWindow* parent, ColorScheme* color_scheme, int nlines, int ncols,\n                           int begin_y, int begin_x)\n    : UIWindow(parent, color_scheme), parent_(parent), color_scheme_(color_scheme) {\n  WINDOW* window;\n  if (parent != nullptr) {\n    if (ncols > parent->GetMaxX()) {\n      ncols = parent->GetMaxX();\n    }\n    if (nlines > parent->GetMaxY()) {\n      nlines = parent->GetMaxY();\n    }\n    if (begin_x == -1) {\n      begin_x = (parent->GetMaxX() - ncols) / 2;\n    }\n    if (begin_y == -1) {\n      begin_y = (parent->GetMaxY() - nlines) / 2;\n    }\n    auto* pw = std::any_cast<WINDOW*>(parent->window());\n    window = newwin(nlines, ncols, begin_y + getbegy(pw), begin_x + getbegx(pw));\n  } else {\n    if (begin_x == -1) {\n      begin_x = 0;\n    }\n    if (begin_y == -1) {\n      begin_y = 0;\n    }\n    window = newwin(nlines, ncols, begin_y, begin_x);\n  }\n  window_ = window;\n\n  keypad(window, true);\n  werase(window);\n  touchwin(window);\n  Refresh();\n}\n\nCursesWindow::~CursesWindow() {\n  try {\n    auto* w = std::any_cast<WINDOW*>(window_);\n    delwin(w);\n    if (parent_) {\n      parent_->RedrawWin();\n      parent_->Refresh();\n      doupdate();\n    }\n  } catch (...) {\n    // NOP\n  }\n}\n\nstd::any CursesWindow::window() const { return window_; }\n\nCursesWindow* CursesWindow::parent() const { return parent_; }\n\nbool CursesWindow::IsGUI() const { return true; }\n\nvoid CursesWindow::SetTitle(const std::string& title) {\n  const auto saved_scheme(this->current_scheme_id());\n  SetColor(SchemeId::WINDOW_TITLE);\n  const auto max_title_size = GetMaxX() - 6;\n  auto working_title = fmt::format(\" {} \", title);\n  if (ssize(title) > max_title_size) {\n    working_title = fmt::format(\" {} \", title.substr(0, max_title_size));\n  }\n\n  const auto x = GetMaxX() - 1 - size_int(working_title);\n  PutsXY(x, 0, working_title);\n  SetColor(saved_scheme);\n}\n\nvoid CursesWindow::Bkgd(uint32_t ch) { wbkgd(std::any_cast<WINDOW*>(window_), ch); }\nint CursesWindow::RedrawWin() { return redrawwin(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::TouchWin() { return touchwin(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::Refresh() { return wrefresh(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::Move(int y, int x) { return wmove(std::any_cast<WINDOW*>(window_), y, x); }\nint CursesWindow::GetcurX() const { return getcurx(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::GetcurY() const { return getcury(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::Clear() { return wclear(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::Erase() { return werase(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::AttrSet(uint32_t attrs) {\n  return wattrset(std::any_cast<WINDOW*>(window_), attrs);\n}\nint CursesWindow::Keypad(bool b) { return keypad(std::any_cast<WINDOW*>(window_), b); }\nint CursesWindow::GetMaxX() const { return getmaxx(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::GetMaxY() const { return getmaxy(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::ClrtoEol() { return wclrtoeol(std::any_cast<WINDOW*>(window_)); }\nint CursesWindow::AttrGet(uint32_t* a, short* c) const {\n  return wattr_get(std::any_cast<WINDOW*>(window_), reinterpret_cast<attr_t*>(a), c, nullptr);\n}\nint CursesWindow::Box(uint32_t vert_ch, uint32_t horiz_ch) {\n  return box(std::any_cast<WINDOW*>(window_), vert_ch, horiz_ch);\n}\n\nint CursesWindow::GetChar(duration<double> timeout) const {\n  auto* window = std::any_cast<WINDOW*>(window_);\n  const auto timeout_ms =  duration_cast<milliseconds>(timeout);\n  const auto start = system_clock::now();\n  const auto end = start + timeout_ms;\n\n  for (;;) {\n    wtimeout(window, static_cast<int>(timeout_ms.count()));\n    const auto ch = wgetch(window);\n    if (ch == KEY_RESIZE) {\n      // Since we don't support online window resizing just ignore this\n      // but don't return it as a key for the application to (badly) handle.\n      continue;\n    }\n    if (ch == ERR && system_clock::now() >= end) {\n      return ERR;\n    }\n    if (ch == ERR) {\n      continue;\n    }\n    if (ch == 27) {\n      wtimeout(window, 0);\n      nodelay(window, true);\n      auto at_exit = finally([=] { nodelay(window, false); });\n      // Check for alt.\n      const auto ch2 = wgetch(window);\n      if (ch2 == ERR) {\n        return 27;\n      }\n      switch (ch2) {\n        case 'I': \n        case 'i':\n        return KEY_IC;\n      }\n      \n      continue;\n    }\n    switch (ch) {\n#ifdef __PDCURSES__\n    // Win10 Terminal started using these\n    case KEY_A1:\n      return KEY_HOME;\n    case KEY_A2: // upper middle on Virt. keypad.\n      return KEY_UP;\n    case KEY_A3:\n      return KEY_PPAGE;\n    case KEY_B1: // middle left on Virt. keypad. Win10 Terminal started using this.\n      return KEY_LEFT;\n    case KEY_B3: // middle right on Vir. keypad. Win10 Terminal started using this.\n      return KEY_RIGHT;\n    case KEY_C1:\n      return KEY_END;\n    case KEY_C2: // lower middle on Virt. keypad. Win10 Terminal started using this.\n      return KEY_DOWN;\n    case KEY_C3:\n#endif\n\n#ifdef PADENTER\n    case PADENTER:\n      return KEY_ENTER;\n#endif\n\n#ifdef KEY_SSAVE\n    // https://github.com/wwivbbs/wwiv/issues/1360\n    // control-Z not working through default terminal on RPI.\n    case KEY_SSAVE:\n      return 26; // Control-Z\n#endif // KEY_SSAVE\n\n    default:\n      return ch;\n    }\n  }\n}\n\nint CursesWindow::GetChar() const {\n  return GetChar(hours(24));\n}\n\nvoid CursesWindow::GotoXY(int x, int y) {\n  x = std::max<int>(x, 0);\n  x = std::min<int>(x, GetMaxX() - 1);\n  y = std::max<int>(y, 0);\n  y = std::min<int>(y, GetMaxY() - 1);\n\n  Move(y, x);\n  Refresh();\n}\n\nvoid CursesWindow::Putch(uint32_t ch) {\n  waddch(std::any_cast<WINDOW*>(window_), ch);\n  Refresh();\n}\n\nvoid CursesWindow::Puts(const std::string& text) {\n  waddstr(std::any_cast<WINDOW*>(window_), text.c_str());\n  Refresh();\n}\n\nvoid CursesWindow::PutsXY(int x, int y, const std::string& text) {\n  mvwaddstr(std::any_cast<WINDOW*>(window_), y, x, text.c_str());\n  Refresh();\n}\n\nvoid CursesWindow::PutchW(wchar_t ch) {\n  // Curses seriously has no way to display a single wchar_t!!\n  wchar_t c[2] = {ch, 0};\n  waddwstr(std::any_cast<WINDOW*>(window_), c);\n\n  Refresh();\n}\n\nvoid CursesWindow::PutsW(const std::wstring& text) {\n  waddwstr(std::any_cast<WINDOW*>(window_), text.c_str());\n  Refresh();\n}\n\nvoid CursesWindow::PutsXYW(int x, int y, const std::wstring& text) {\n  mvwaddwstr(std::any_cast<WINDOW*>(window_), y, x, text.c_str());\n  Refresh();\n}\n\nvoid CursesWindow::SetColor(SchemeId id) {\n  AttrSet(color_scheme_->GetAttributesForScheme(id));\n  set_current_scheme_id(id);\n}\n\nvoid CursesWindow::SetDosColor(int original_color) {\n  const auto bold = (original_color & 8) != 0;\n  auto color = original_color;\n  const auto bg = (color >> 4) & 0x07;\n  const auto fg = color & 0x07;\n  color = (bg << 3) | fg;\n  // DOS colors start at color pair 100.\n  auto attr = COLOR_PAIR(color + 100);\n  if (bold) {\n    attr |= A_BOLD;\n  }\n  AttrSet(attr);\n}\n\nstd::vector<int> colors = {7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n\nenum class pipe_state_t { text, pipe };\n\nvoid CursesWindow::PutsWithPipeColors(const std::string& s) {\n  auto state = pipe_state_t::text;\n  std::string curpipe;\n  auto curatr = 0x07;\n  for (auto it = std::begin(s); it != std::end(s); ++it) {\n    const auto c = *it;\n    switch (state) {\n    case pipe_state_t::text: {\n      if (c == '|') {\n        state = pipe_state_t::pipe;\n        curpipe.push_back(c);\n      } else {\n        Putch(c);\n      }\n    } break;\n    // grab first\n    case pipe_state_t::pipe: {\n      const auto pipe_size = ssize(curpipe);\n      if (std::isdigit(c) && pipe_size == 2) {\n        curpipe.push_back(c);\n        if (curpipe[1] == '#') {\n          curatr = at(colors, curpipe[2] - '0');\n        } else {\n          curatr = to_number<int>(curpipe.substr(1));\n        }\n        curpipe.clear();\n        SetDosColor(curatr);\n        state = pipe_state_t::text;\n      } else if ((std::isdigit(c) || c == '#') && pipe_size == 1) {\n        curpipe.push_back(c);\n      } else {\n        state = pipe_state_t::text;\n        Puts(curpipe);\n        curpipe.clear();\n      }\n    } break;\n    }\n  }\n}\n\nvoid CursesWindow::PutsWithPipeColors(int x, int y, const std::string& text) {\n  GotoXY(x, y);\n  PutsWithPipeColors(text);\n}\n\n}\n"
  },
  {
    "path": "localui/curses_win.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_CURSES_WIN_H\n#define INCLUDED_LOCALUI_CURSES_WIN_H\n\n#include \"localui/colors.h\"\n#include \"localui/ui_win.h\"\n#include <any>\n#include <chrono>\n#include <string>\n\nnamespace wwiv::local::ui {\n\n// Curses implementation of screen display routines for wwivconfig.\nclass CursesWindow final : public UIWindow {\npublic:\n  // Constructor/Destructor\n  CursesWindow(CursesWindow* parent, ColorScheme* color_scheme, int nlines, int ncols,\n               int begin_y = -1, int begin_x = -1);\n  CursesWindow(const CursesWindow& copy) = delete;\n  ~CursesWindow() override;\n\n  void SetTitle(const std::string& title) override;\n\n  void Bkgd(uint32_t ch) override;\n  int RedrawWin() override;\n  int TouchWin() override;\n  int Refresh() override;\n  int Move(int y, int x) override;\n  [[nodiscard]] int GetcurX() const override;\n  [[nodiscard]] int GetcurY() const override;\n  int Clear() override;\n  int Erase() override;\n  int AttrSet(uint32_t attrs) override;\n  int Keypad(bool b) override;\n  [[nodiscard]] int GetMaxX() const override;\n  [[nodiscard]] int GetMaxY() const override;\n  int ClrtoEol() override;\n  int AttrGet(uint32_t* a, short* c) const override;\n  int Box(uint32_t vert_ch, uint32_t horiz_ch) override;\n\n  [[nodiscard]] int GetChar(std::chrono::duration<double> timeout) const;\n  [[nodiscard]] int GetChar() const override;\n  void GotoXY(int x, int y) override;\n  void Putch(uint32_t ch) override;\n  void Puts(const std::string& text) override;\n  void PutsXY(int x, int y, const std::string& text) override;\n  // Wide character versions\n  void PutchW(wchar_t ch) override;\n  void PutsW(const std::wstring& text) override;\n  void PutsXYW(int x, int y, const std::wstring& text) override;\n\n  void SetColor(SchemeId id) override;\n  void SetDosColor(int attr);\n  void PutsWithPipeColors(const std::string& text);\n  void PutsWithPipeColors(int x, int y, const std::string& text);\n\n  [[nodiscard]] std::any window() const;\n  [[nodiscard]] CursesWindow* parent() const override;\n\n  [[nodiscard]] bool IsGUI() const override;\n\nprivate:\n  std::any window_;\n  CursesWindow* parent_;\n  ColorScheme* color_scheme_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/edit_items.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"localui/edit_items.h\"\n\n#include \"core/stl.h\"\n#include \"localui/curses_io.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/stdio_win.h\"\n#include \"localui/wwiv_curses.h\"\n#include <algorithm>\n#include <cstdlib>\n#include <memory>\n#include <set>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::stl;\n\nnamespace wwiv::local::ui {\n\n\nvoid EditItems::Run(const std::string& title) {\n  if (!window_) {\n    curses_out->Cls(ACS_CKBOARD);\n    create_window(title);\n  }\n  edit_mode_ = true;\n  auto cp = 0;\n  const auto size = static_cast<int>(items_.size());\n  Display();\n  for (;;) {\n    auto* item = items_[cp];\n    curses_out->footer()->ShowContextHelp(item->help_text());\n    const auto i1 = item->Run(window_.get());\n    item->Display(window_.get());\n    curses_out->footer()->SetDefaultFooter();\n    if (i1 == EditlineResult::PREV) {\n      if (--cp < 0) {\n        cp = size - 1;\n      }\n    } else if (i1 == EditlineResult::NEXT) {\n      if (++cp >= size) {\n        cp = 0;\n      }\n    } else if (i1 == EditlineResult::DONE) {\n      curses_out->SetIndicatorMode(IndicatorMode::none);\n      edit_mode_ = false;\n      return;\n    }\n  }\n}\n\nvoid EditItems::Display() const {\n  // Show help bar.\n  if (edit_mode_) {\n    curses_out->footer()->window()->Move(1, 0);\n    curses_out->footer()->window()->ClrtoEol();\n    curses_out->footer()->ShowHelpItems(0, editor_help_items_);\n  } else {\n    curses_out->footer()->ShowHelpItems(0, navigation_help_items_);\n    curses_out->footer()->ShowHelpItems(1, navigation_extra_help_items_);\n  }\n\n  window_->SetColor(SchemeId::NORMAL);\n  for (auto* l : labels_) {\n    l->Display(window_.get());\n  }\n  window_->SetColor(SchemeId::WINDOW_DATA);\n  for (auto* item : items_) {\n    item->Display(window_.get());\n  }\n  window_->Refresh();\n}\n\nBaseEditItem* EditItems::add(BaseEditItem* item, int column, int row) {\n  DCHECK(item);\n  item->set_column(column);\n  if (row >= 0) {\n    item->set_y(row);\n    auto& cell = cells_[row][column];\n    cell.item = item;\n    cell.set_column(column);\n  }\n  items_.push_back(item);\n  return item;\n}\n\nLabel* EditItems::add(Label* label, int column, int row) {\n  DCHECK(label);\n  label->set_column(column);\n  if (row >= 0) {\n    label->set_y(row);\n    auto& cell = cells_[row][column];\n    cell.item = label;\n    cell.set_column(column);\n    cell.cell_type_ = cell_type_t::label;\n  }\n  labels_.push_back(label);\n  return label;\n}\n\nBaseEditItem* EditItems::add(Label* label, BaseEditItem* item, int column, int row) {\n  add(label, column, row);\n  return add(item, column+1, row);\n}\n\nBaseEditItem* EditItems::add(Label* label, BaseEditItem* item, const std::string& help, int column, int row) {\n  item->set_help_text(help);\n  return add(label, item, column, row);\n}\n\nvoid EditItems::create_window(const std::string& title) {\n  window_ = std::unique_ptr<CursesWindow>(\n      curses_out->CreateBoxedWindow(title, max_display_height(), max_display_width()));\n}\n\nchar EditItems::GetKeyWithNavigation(const NavigationKeyConfig& config) const {\n  auto keys = config.keys_;\n  keys.push_back(config.dn);\n  keys.push_back(config.down10);\n  keys.push_back(config.up);\n  keys.push_back(config.up10);\n  if (config.quit) {\n    keys.push_back(config.quit);\n    keys.push_back('\\x1b');\n  }\n  for (;;) {\n    const auto key = window()->GetChar();\n    if (has_key(key)) {\n      switch (key) {\n      case KEY_PPAGE:\n        return config.up10;\n      case KEY_NPAGE:\n        return config.down10;\n      case KEY_LEFT:\n      case KEY_UP:\n        return config.up;\n      case KEY_RIGHT:\n      case KEY_DOWN:\n        return config.dn;\n      default:\n        continue;\n      }\n    }\n    const auto ch = static_cast<char>(std::toupper(key));\n    if (keys.find(ch) != std::string::npos) {\n      if (ch == '\\x1b') {\n        return config.quit;\n      }\n      return ch;\n    }\n  }\n}\n\nint EditItems::max_display_width() const {\n  auto result = 0;\n  for (const auto* i : items_) {\n    if ((i->x() + i->width()) > result) {\n      result = i->x() + i->width();\n    }\n  }\n  return std::min<int>(curses_out->window()->GetMaxX(), result + 2); // 2 is padding\n}\n\nint EditItems::max_display_height() {\n  int result = 1;\n  for (const auto* l : labels_) {\n    if (l->y() > result) {\n      result = l->y() + l->height() - 1;\n    }\n  }\n  for (const auto* i : items_) {\n    if (i->y() > result) {\n      result = i->y();\n    }\n  }\n  return std::min<int>(curses_out->window()->GetMaxY(), result + 2);\n}\n\n/**\n *  \n * Layout columns and look at max widths for only a subset of rows\n * so you can have things like:\n *\n * LLLLL: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n * LLLLL: FFFFFFFF    LLLLL: FFFFFFFFFFFFFFFFFFFFF\n *\n * Notice they have different max widths depending on the row.\n */\nvoid EditItems::relayout_items_and_labels() {\n  if (cells_.empty()) {\n    return;\n  }\n\n  //\n  // Ensure that we have blank columns before any later columsn.\n  // This allows things like this UI to work:\n  // XXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYY\n  //                     YYYYYYYYYYYYY\n  //\n  for (const auto& [row_num, row] : cells_) {\n    const auto& [first, _] = *row.begin();\n    for (int i = 1; i < first; i++) {\n      // Add mising empty spacer labels\n      add(new Label(\"\"), i, row_num);\n    }\n  }\n\n\n  // Make map of Widths -> row numbers\n  std::map<int, std::set<int>> widths_and_rows;\n  for (const auto& [row_num, row] : cells_) {\n    widths_and_rows[size_int(row)].insert(row_num);\n  }\n\n  std::map<int, std::map<int, Column>> widths_and_columns;\n  for (const auto& [num_cols_for_this_row, row_nums] : widths_and_rows) {\n    // Compute Max Width per cell\n    for (const auto& row_num : row_nums) {\n      for (auto& [col_num, cell] : cells_[row_num]) {\n        // c.first is column, c.second is Cell\n        auto& columns = widths_and_columns[num_cols_for_this_row];\n        if (cell.colspan_ == 1 && cell.width() > columns[col_num].width) {\n          // Ignore cells with colspan > 1\n          columns[col_num].width = cell.width();\n        }\n      }\n    }\n    // Set Max Width per cell\n    for (const auto& row_num : row_nums) {\n      auto& columns = widths_and_columns[size_int(cells_[row_num])];\n      for (auto& [col_num, cell] : cells_[row_num]) {\n        if (const auto width = columns[col_num].width; width > 0) {\n          cell.set_width(width);\n        }\n      }\n    }\n  }\n\n  // Calculate max width first\n  if (!align_label_cols_.empty()) {\n    std::map<int, int> aligned_col_max_width;\n    for (const auto aligned_col : align_label_cols_) {\n      auto& max_width = aligned_col_max_width[aligned_col];\n      for (auto& [rownum, row] : cells_) {\n        if (!contains(row, aligned_col)) {\n          continue;\n        }\n        auto& c = at(row, aligned_col);\n        const auto width = c.width();\n        if (c.cell_type_ == cell_type_t::label && width > max_width) {\n          max_width = width;\n        }\n      }\n    }\n\n    // Assign widths.\n    for (const auto aligned_col : align_label_cols_) {\n      auto& width = aligned_col_max_width[aligned_col];\n      // Update width for the individual item.\n      for (auto& [rownum, row] : cells_) {\n        if (!contains(row, aligned_col)) {\n          continue;\n        }\n        auto& cell = at(row, aligned_col);\n        if (cell.colspan_ == 1) {\n          cell.set_width(width);\n        }\n      }\n      // Update column width in Columns, used for spacing\n      for (auto& [wcwidth, cols] : widths_and_columns) {\n        if (!contains(cols, aligned_col)) {\n          continue;\n        }\n        at(cols, aligned_col).width = width;\n      }\n    }\n\n  }\n\n  // Figure out column x;\n  for (const auto& r : widths_and_rows) {\n    auto& columns = widths_and_columns[r.first];\n    for (auto& [col_num, col] : columns) {\n      if (col_num <= 0) {\n        // should be in order, so skip column 0, which is width 0;\n        continue;\n      }\n      auto& prev = columns[col_num - 1];\n      col.x = prev.x + prev.width + 1;\n    }\n  }\n\n  // Now need to set X values for everything.\n  for (auto& [_, row] : cells_) {\n    auto& columns = widths_and_columns[size_int(row)];\n    for (auto& [col_num, cell] : row) {\n      auto& col = columns[col_num];\n      cell.set_x(col.x);\n    }\n  }\n}\n\nCell& EditItems::cell(int row, int col) {\n  return cells_[row][col];\n}\n\nstd::vector<HelpItem> EditItems::StandardNavigationHelpItems() {\n  return {\n      {\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"[\", \"Previous\"},\n      {\"]\", \"Next\"}, {\"{\", \"Previous 10\"}, {\"}\", \"Next 10\"},\n  };\n}\n\nint Cell::width() const {\n  return item ? item->width() + 1 : 0;\n}\n\nvoid Cell::set_width(int w) {\n  width_ = w;\n  if (item) {\n    item->set_width(w);\n  }\n}\n\nvoid Cell::set_x(int new_x) {\n  x_ = new_x;\n  if (item) {\n    item->set_x(new_x);\n  }\n}\n\nint Cell::column() const { return column_; }\n\nEditItems::EditItems()\n  : navigation_help_items_(StandardNavigationHelpItems()),\n    editor_help_items_(StandardEditorHelpItems()), edit_mode_(false) { }\n\nEditItems::~EditItems() {\n  // Since we added raw pointers we must cleanup.  Since AFAIK there is\n  // no easy way to convert from std::initializer_list<T> to\n  // std::initializer_list<unique_ptr<T>>\n  for (auto* item : items_) {\n    delete item;\n  }\n  items_.clear();\n  for (auto* l : labels_) {\n    delete l;\n  }\n  labels_.clear();\n\n  // Clear the help bar on exit.\n  curses_out->footer()->window()->Erase();\n  curses_out->footer()->window()->Refresh();\n  curses_out->SetIndicatorMode(IndicatorMode::none);\n}\n\n}\n"
  },
  {
    "path": "localui/edit_items.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_EDIT_ITEMS_H\n#define INCLUDED_LOCALUI_EDIT_ITEMS_H\n\n#include \"localui/curses_io.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/input.h\"\n#include \"sdk/config.h\"\n#include <functional>\n#include <set>\n#include <string>\n#include <vector>\n\nnamespace wwiv::local::ui {\n\nenum class cell_type_t { label, edit_item };\n/**\n * Represent a cell in the UI.\n *\n * The column number is a number 1-N\n * x is the start position relative to the window\n * Width span both label, padding between label and item, and item widths.\n */\nclass Cell final {\npublic:\n  Cell() = default;\n  [[nodiscard]] int width() const;\n  void set_width(int);\n  [[nodiscard]] int x() const { return x_; }\n  void set_x(int);\n  [[nodiscard]] int column() const;\n  void set_column(int c) { column_ = c; }\n\n  Item* item{nullptr};\n  int x_{1};\n  int width_{0};\n  int column_{0};\n  cell_type_t cell_type_{cell_type_t::edit_item};\n  int colspan_ = 1;\n};\n\n\nclass Column final {\npublic:\n  Column() = default;\n  int width{0};\n  int x{0};\n};\n\n//TODO(rushfan): Maybe this should be renamed to Form, since that's really\n//what this has evolved into from a simple structure of EditItem instances.\n/**\n * Creates a window containing a form of items that may be filled out\n * or \"edited\".\n *\n * Typically the items are instances of \"EditItem\" classes\n */\nclass EditItems final {\npublic:\n  typedef std::function<void()> additional_helpfn;\n  EditItems();\n  EditItems(EditItems const&) = delete;\n  EditItems(EditItems&&) = delete;\n  EditItems& operator=(EditItems const&) = delete;\n  EditItems& operator=(EditItems&&) = delete;\n  ~EditItems();\n\n  void Run(const std::string& title = \"\");\n  void Display() const;\n\n  void set_navigation_help_items(const std::vector<HelpItem>& items) {\n    navigation_help_items_ = items;\n  }\n\n  void set_editmode_help_items(const std::vector<HelpItem>& items) { editor_help_items_ = items; }\n  void set_navigation_extra_help_items(const std::vector<HelpItem>& items) {\n    navigation_extra_help_items_ = items;\n  }\n\n  std::vector<BaseEditItem*>& items() { return items_; }\n\n  /**\n   * Adds an item to the list of EditItems.\n   *\n   * This uses both a column number and optionally a value to override for Y.\n   * If y is not set, the items preferred Y value will be used.\n   */\n  BaseEditItem* add(BaseEditItem* item, int column = 1, int row = -1);\n\n  /**\n   * Adds a label to the list of EditItems.\n   *\n   * This uses both a column number and optionally a value to override for Y.\n   * If y is not set, the items preferred Y value will be used.\n   */\n  Label* add(Label* label, int column = 1, int row = -1);\n\n  /**\n   * Adds a label and item\n   *\n   * This uses both a column number and optionally a value to override for Y.\n   * If y is not set, the items preferred Y value will be used.\n   */\n  BaseEditItem* add(Label* label, BaseEditItem* item, int column = 1, int row = -1);\n\n  /**\n   * Adds a label and item and help text\n   *\n   * This uses both a column number and optionally a value to override for Y.\n   * If y is not set, the items preferred Y value will be used.\n   */\n  BaseEditItem* add(Label* label, BaseEditItem* item, const std::string& help, int column = 1,\n                    int row = -1);\n\n  void create_window(const std::string& title);\n\n  /**\n   * Gets a key and automatically includes all navigation related keys\n   * from config.\n   */\n  [[nodiscard]] char GetKeyWithNavigation(const NavigationKeyConfig& config) const;\n\n  [[nodiscard]] CursesWindow* window() const { return window_.get(); }\n  [[nodiscard]] int size() const noexcept { return static_cast<int>(items_.size()); }\n\n  [[nodiscard]] int max_display_width() const;\n\n  [[nodiscard]] int max_display_height();\n\n  /**\n   * Moves the labels to the x position just after the labels.\n   * This only works for single column layouts of: {label:} {item}\n   */\n  void relayout_items_and_labels();\n\n  Cell& cell(int row, int col);\n\n  /**\n   * Add a column number to align label sizes for.\n   */\n  void add_aligned_width_column(int n) { align_label_cols_.insert(n); }\n\n  static std::vector<HelpItem> StandardNavigationHelpItems();\n\n  static std::vector<HelpItem> StandardEditorHelpItems() { return {{\"Esc\", \"Exit\"}}; }\n\n  static std::vector<HelpItem> ExitOnlyHelpItems() { return {{\"Esc\", \"Exit\"}}; }\n\nprivate:\n  std::vector<BaseEditItem*> items_;\n  std::vector<Label*> labels_;\n  std::vector<HelpItem> navigation_help_items_;\n  std::vector<HelpItem> navigation_extra_help_items_;\n  std::vector<HelpItem> editor_help_items_;\n  std::unique_ptr<CursesWindow> window_;\n  bool edit_mode_;\n  // row, then columns\n  std::map<int, std::map<int, Cell>> cells_;\n  std::set<int> align_label_cols_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/input.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"localui/input.h\"\r\n\r\n// has to go before cureses\r\n\r\n#include \"core/file.h\"\r\n#include \"core/stl.h\"\r\n#include \"core/strings.h\"\r\n#include \"localui/curses_io.h\"\r\n#include \"localui/curses_win.h\"\r\n#include \"localui/stdio_win.h\"\r\n#include \"localui/ui_win.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"local_io/keycodes.h\"\r\n#include \"sdk/acs/acs.h\"\r\n#include <algorithm>\r\n#include <cctype>\r\n#include <cmath>\r\n#include <cstdint>\r\n#include <cstdlib>\r\n#include <cstring>\r\n#include <functional>\r\n#include <memory>\r\n#include <stdexcept>\r\n#include <string>\r\n#include <vector>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::stl;\r\nusing namespace wwiv::strings;\r\n\r\nnamespace wwiv::local::ui {\r\n\r\n\r\nvoid Label::Display(CursesWindow* window) const {\r\n  window->GotoXY(x_, y_);\r\n  if (right_justify_) {\r\n    const auto pad = std::max<int>(0, width_ - size_int(text_));\r\n    window->Puts(std::string(pad, ' '));\r\n  }\r\n  window->Puts(text_);\r\n}\r\n\r\nMultilineLabel::MultilineLabel(const std::string& text)\r\n    : Label(0, text) {\r\n  lines_ = SplitString(text, \"\\r\\n\", false);\r\n  auto w = 0;\r\n  for (const auto& l : lines_) {\r\n    w = std::max<int>(w, size_int(l));\r\n  }\r\n  width_ = w;\r\n}\r\n\r\nvoid MultilineLabel::Display(CursesWindow* window) const {\r\n  for (auto i = 0; i < size_int(lines_); i++) {\r\n    window->GotoXY(x_, y_ + i);\r\n    window->Puts(at(lines_, i));\r\n  }\r\n}\r\n\r\nint MultilineLabel::height() const {\r\n  return size_int(lines_);\r\n}\r\n\r\nEditlineResult ACSEditItem::Run(CursesWindow* window) {\r\n  window->GotoXY(this->x_, this->y_);\r\n  DefaultDisplay(window);\r\n  window->GotoXY(this->x_, this->y_);\r\n  std::string last_expr;\r\n  const edline_validation_fn fn = [&](const std::string& acs)->void\r\n  {\r\n    if (acs == last_expr) {\r\n      // Don't keep re-evaluating the same thing.\r\n      return;\r\n    }\r\n    last_expr = acs;\r\n\r\n    auto [result, ex, info] = sdk::acs::validate_acs(acs, providers_);\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    if (result) {\r\n      curses_out->footer()->ShowContextHelp(\"The expression is valid.\");\r\n    } else {\r\n      curses_out->footer()->ShowContextHelp(StrCat(\"ACS Error: \", ex));\r\n    }\r\n  };\r\n  return editline(window, &this->data_, this->width_, edit_line_mode_, \"\", fn);\r\n}\r\n\r\nvoid ACSEditItem::DefaultDisplay(CursesWindow* window) const {\r\n  window->GotoXY(this->x_, this->y_);\r\n  this->DefaultDisplayString(window, data_);\r\n}\r\n\r\nEditlineResult FidoAddressStringEditItem::Run(CursesWindow* window) {\r\n  window->GotoXY(this->x_, this->y_);\r\n  DefaultDisplay(window);\r\n  window->GotoXY(this->x_, this->y_);\r\n  std::string last_addr;\r\n  const edline_validation_fn fn = [&](const std::string& raw) -> void {\r\n    const auto addr = StringTrim(raw);\r\n    if (addr == last_addr) {\r\n      // Don't keep re-evaluating the same thing.\r\n      return;\r\n    }\r\n    last_addr = addr;\r\n\r\n    if (const auto o = wwiv::sdk::fido::try_parse_fidoaddr(last_addr)) {\r\n      if (o->has_domain()) {\r\n        curses_out->footer()->ShowContextHelp(this->help_text());\r\n      } else {\r\n        curses_out->footer()->ShowContextHelp(\"Domain is missing. Address should be of the form:'Z:N/O@D'\");\r\n      }\r\n      return;\r\n    }\r\n    curses_out->footer()->ShowContextHelp(\"Address is NOT valid. Address should be of the form:'Z:N/O@D'\");\r\n  };\r\n  // Run the validation once on entry\r\n  if (!this->data_.empty()) {\r\n    fn(this->data_);\r\n  }\r\n  return editline(window, &this->data_, this->width_, edit_line_mode_, \"\", fn);\r\n}\r\n\r\nvoid FidoAddressStringEditItem::DefaultDisplay(CursesWindow* window) const {\r\n  window->GotoXY(this->x_, this->y_);\r\n  this->DefaultDisplayString(window, data_);\r\n}\r\n\r\n\r\nEditlineResult CustomEditItem::Run(CursesWindow* window) {\r\n  window->GotoXY(x_, y_);\r\n  auto s = to_field_();\r\n\r\n  // The width_ may be wider than the field width, so we need use field_width_.\r\n  const auto return_code = editline(window, &s, field_width_, EditLineMode::ALL, \"\");\r\n  from_field_(s);\r\n  return return_code;\r\n}\r\n\r\nvoid CustomEditItem::Display(CursesWindow* window) const {\r\n  window->GotoXY(x_, y_);\r\n  // The width_ may be wider than the field width, so we need use field_width_.\r\n  const std::string blanks(field_width_, ' ');\r\n  window->Puts(blanks);\r\n\r\n  const auto s = to_field_();\r\n  if (display_) {\r\n    display_(s);\r\n  } else {\r\n    window->PutsXY(x_, y_, s);\r\n  }\r\n}\r\n\r\nEditExternalFileItem::EditExternalFileItem(std::filesystem::path path)\r\n  : BaseEditItem(25), path_(std::move(path)) {\r\n}\r\n\r\nstatic UIWindow* CreateDialogWindow(UIWindow* parent, int height, int width) {\r\n  const auto maxx = parent->GetMaxX();\r\n  const auto maxy = parent->GetMaxY();\r\n  const auto startx = (maxx - width - 4) / 2;\r\n  const auto starty = (maxy - height - 2) / 2;\r\n  UIWindow* dialog;\r\n  if (parent->IsGUI()) {\r\n    dialog = new CursesWindow(dynamic_cast<CursesWindow*>(parent), parent->color_scheme(),\r\n                              height + 2, width + 4, starty, startx);\r\n  } else {\r\n    dialog = new StdioWindow(parent, parent->color_scheme());\r\n  }\r\n  dialog->Bkgd(parent->color_scheme()->GetAttributesForScheme(SchemeId::DIALOG_BOX));\r\n  dialog->SetColor(SchemeId::DIALOG_BOX);\r\n  dialog->Box(0, 0);\r\n  return dialog;\r\n}\r\n\r\nbool dialog_yn(CursesWindow* window, const std::vector<std::string>& text) {\r\n  auto maxlen = 4;\r\n  for (const auto& s : text) {\r\n    maxlen = std::max<int>(maxlen, size_int(s));\r\n  }\r\n  std::unique_ptr<UIWindow> dialog(CreateDialogWindow(window, size_int(text), maxlen));\r\n  dialog->SetColor(SchemeId::DIALOG_TEXT);\r\n  auto curline = 1;\r\n  for (const auto& s : text) {\r\n    dialog->PutsXY(2, curline++, s);\r\n  }\r\n  dialog->SetColor(SchemeId::DIALOG_PROMPT);\r\n  dialog->Refresh();\r\n  return toupper(dialog->GetChar()) == 'Y';\r\n}\r\n\r\nbool dialog_yn(CursesWindow* window, const std::string& text) {\r\n  const std::vector<std::string> text_vector = {text};\r\n  return dialog_yn(window, text_vector);\r\n}\r\n\r\nstatic void winput_password(CursesWindow* dialog, std::string* output, int max_length) {\r\n  dialog->SetColor(SchemeId::DIALOG_PROMPT);\r\n\r\n  auto curpos = 0;\r\n  std::string s;\r\n  s.resize(max_length);\r\n  output->clear();\r\n  for (;;) {\r\n    const auto ch = dialog->GetChar();\r\n    switch (ch) {\r\n    case 14:\r\n    case 13: // 13 on Win32\r\n    case 10: // 10 on unix\r\n    case KEY_ENTER:\r\n#ifdef PADENTER\r\n    case PADENTER:\r\n#endif\r\n      s.resize(curpos);\r\n      output->assign(s);\r\n      return;\r\n    case 23: // Ctrl-W\r\n      if (curpos) {\r\n        do {\r\n          curpos--;\r\n          dialog->Puts(\"\\b \\b\");\r\n          if (s[curpos] == 26) {\r\n            dialog->Puts(\"\\b \\b\");\r\n          }\r\n        } while (curpos && (s[curpos - 1] != 32));\r\n      }\r\n      break;\r\n    case 26: // control Z\r\n      break;\r\n    case 27: { // escape\r\n      output->clear();\r\n      return;\r\n    }\r\n    case 8:\r\n    case 0x7f: // some other backspace\r\n    case KEY_BACKSPACE:\r\n      if (curpos) {\r\n        curpos--;\r\n        dialog->Puts(\"\\b \\b\");\r\n        if (s[curpos] == 26) {\r\n          dialog->Puts(\"\\b \\b\");\r\n        }\r\n      }\r\n      break;\r\n    case 21: // control U\r\n    case 24: // control X\r\n      while (curpos) {\r\n        curpos--;\r\n        dialog->Puts(\"\\b \\b\");\r\n        if (s[curpos] == 26) {\r\n          dialog->Puts(\"\\b \\b\");\r\n        }\r\n      }\r\n      break;\r\n    default:\r\n      if (ch > 31 && curpos < max_length) {\r\n        s[curpos++] = to_upper_case<char>(static_cast<char>(ch));\r\n        dialog->Putch(ACS_DIAMOND);\r\n      }\r\n      break;\r\n    }\r\n  }\r\n}\r\n\r\nvoid input_password(CursesWindow* window, const std::string& prompt, const std::vector<std::string>& text,\r\n                    std::string* output, int max_length) {\r\n  auto maxlen = size_int(prompt) + max_length;\r\n  for (const auto& s : text) {\r\n    maxlen = std::max<int>(maxlen, size_int(s));\r\n  }\r\n  CHECK(window->IsGUI()) << \"input_password needs a GUI.\";\r\n  std::unique_ptr<CursesWindow> dialog(\r\n      dynamic_cast<CursesWindow*>(CreateDialogWindow(window, size_int(text) + 2, maxlen)));\r\n  dialog->SetColor(SchemeId::DIALOG_TEXT);\r\n\r\n  auto curline = 1;\r\n  for (const auto& s : text) {\r\n    dialog->PutsXY(2, curline++, s);\r\n  }\r\n  dialog->SetColor(SchemeId::DIALOG_PROMPT);\r\n  dialog->PutsXY(2, size_int(text) + 2, prompt);\r\n  dialog->Refresh();\r\n  winput_password(dialog.get(), output, max_length);\r\n}\r\n\r\nint messagebox(UIWindow* window, const std::string& text) {\r\n  const std::vector<std::string> vector = {text};\r\n  return messagebox(window, vector);\r\n}\r\n\r\nint messagebox(UIWindow* window, const std::vector<std::string>& text) {\r\n  const std::string prompt = \"Press Any Key\";\r\n  auto maxlen = size_int(prompt) + 2;\r\n  for (const auto& s : text) {\r\n    maxlen = std::max<int>(maxlen, size_int(s));\r\n  }\r\n  std::unique_ptr<UIWindow> dialog(CreateDialogWindow(window, size_int(text) + 2, maxlen));\r\n  dialog->SetColor(SchemeId::DIALOG_TEXT);\r\n  auto curline = 1;\r\n  for (const auto& s : text) {\r\n    dialog->PutsXY(2, curline++, s);\r\n  }\r\n  dialog->SetColor(SchemeId::DIALOG_PROMPT);\r\n  const auto x = (maxlen - ssize(prompt)) / 2;\r\n  dialog->PutsXY(x + 2, size_int(text) + 2, prompt);\r\n  dialog->Refresh();\r\n  return dialog->GetChar();\r\n}\r\n\r\nint input_select_item(UIWindow* window, const std::string& prompt, const std::vector<std::string>& items) {\r\n  auto maxlen = size_int(prompt) + 2;\r\n  for (const auto& s : items) {\r\n    maxlen = std::max<int>(maxlen, size_int(s));\r\n  }\r\n  std::unique_ptr<UIWindow> dialog(CreateDialogWindow(window, size_int(items) + 2, maxlen));\r\n  dialog->SetColor(SchemeId::DIALOG_TEXT);\r\n  auto curline = 1;\r\n  int index = 0;\r\n  std::string allowed(\"Q\");\r\n  for (const auto& s : items) {\r\n    dialog->PutsXY(2, curline++, fmt::format(\"{}) {}\", index, s));\r\n    allowed.push_back(static_cast<char>('0' + index));\r\n    ++index;\r\n  }\r\n  dialog->SetColor(SchemeId::DIALOG_PROMPT);\r\n  const auto x = (maxlen - size_int(prompt)) / 2;\r\n  dialog->PutsXY(x + 2, size_int(items) + 2, prompt);\r\n  dialog->Refresh();\r\n  return onek(window, allowed, false);\r\n}\r\n\r\nstd::string dialog_input_string(CursesWindow* window, const std::string& prompt,\r\n                                int max_length) {\r\n  std::unique_ptr<UIWindow> dialog(CreateDialogWindow(window, 3, size_int(prompt) + 4 + max_length));\r\n  dialog->PutsXY(2, 2, prompt);\r\n  dialog->Refresh();\r\n\r\n  CHECK(window->IsGUI()) << \"dialog_input_string needs a GUI.\";\r\n  std::string s;\r\n  editline(dynamic_cast<CursesWindow*>(dialog.get()), &s, max_length, EditLineMode::ALL, \"\");\r\n  return s;\r\n}\r\n\r\nstatic int max_length_for_number(int64_t n) {\r\n  return (n == 0) ? 1 : static_cast<int>(std::floor(std::log10(std::abs(n)))) + 1;\r\n}\r\n\r\nint dialog_input_number(CursesWindow* window, const std::string& prompt, int min_value, int max_value) {\r\n  const auto num_digits = max_length_for_number(max_value);\r\n  CHECK(window->IsGUI()) << \"dialog_input_number needs a GUI.\";\r\n  std::unique_ptr<CursesWindow> dialog(\r\n      dynamic_cast<CursesWindow*>(CreateDialogWindow(window, 3, size_int(prompt) + 4 + num_digits)));\r\n  dialog->PutsXY(2, 2, prompt);\r\n  dialog->Refresh();\r\n\r\n  std::string s;\r\n  editline(dialog.get(), &s, num_digits, EditLineMode::NUM_ONLY, \"\");\r\n  if (s.empty()) {\r\n    return min_value;\r\n  }\r\n  try {\r\n    const auto v = std::stoi(s);\r\n    if (v < min_value) {\r\n      return min_value;\r\n    }\r\n    return v;\r\n  } catch (std::logic_error&) {\r\n    // No conversion possible.\r\n    return min_value;\r\n  }\r\n}\r\n\r\nint onek(UIWindow* window, const std::string& allowed, bool allow_keycodes) {\r\n  for (;;) {\r\n    const auto key = window->GetChar();\r\n    if (has_key(key)) {\r\n      if (allow_keycodes) {\r\n        return key;\r\n      }\r\n      continue;\r\n    }\r\n    const auto ch = static_cast<char>(std::toupper(key));\r\n    if (allowed.find(ch) != std::string::npos) {\r\n      return ch;\r\n    }\r\n  }\r\n}\r\n\r\n\r\nstatic const int background_character = 32;\r\n;\r\n\r\nstatic int editlinestrlen(char* text) {\r\n  auto i = ssize(text);\r\n  while (i >= 0 && (static_cast<unsigned char>(text[i - 1]) == background_character)) {\r\n    --i;\r\n  }\r\n  return i;\r\n}\r\n\r\n\r\nEditlineResult editline(CursesWindow* window, std::string* s, int len, EditLineMode status,\r\n                         const char* ss) {\r\n  return editline(window, s, len, status, ss, {});\r\n}\r\n\r\nEditlineResult editline(CursesWindow* window, std::string* s, int len, EditLineMode status,\r\n                         const char* ss, edline_validation_fn fn) {\r\n  char buffer[255];\r\n  to_char_array(buffer, *s);\r\n  const auto rc = editline(window, buffer, len, status, ss, fn);\r\n  s->assign(buffer);\r\n  return rc;\r\n}\r\n\r\nEditlineResult editline(CursesWindow* window, char* s, int len, EditLineMode status,\r\n                         const char* ss) {\r\n  return editline(window, s, len, status, ss, {});\r\n}\r\n\r\n/* Edits a string, doing I/O to the screen only. */\r\nEditlineResult editline(CursesWindow* window, char* s, int len, EditLineMode status,\r\n                         const char* ss, const edline_validation_fn& fn) {\r\n  uint32_t old_attr;\r\n  short old_pair;\r\n  window->AttrGet(&old_attr, &old_pair);\r\n  const auto cx = window->GetcurX();\r\n  const auto cy = window->GetcurY();\r\n  auto rc = EditlineResult::NEXT;\r\n  for (auto i = ssize(s); i < len; i++) {\r\n    s[i] = static_cast<char>(background_character);\r\n  }\r\n  s[len] = '\\0';\r\n  window->SetColor(SchemeId::EDITLINE);\r\n  window->Puts(s);\r\n  curses_out->SetIndicatorMode(IndicatorMode::overwrite);\r\n  window->GotoXY(cx, cy);\r\n  auto done = false;\r\n  auto pos = 0;\r\n  auto bInsert = false;\r\n  const auto timeout = std::chrono::seconds((fn) ? 1 : 60*60*24);\r\n  do {\r\n    const auto raw_ch = window->GetChar(timeout);\r\n    if (fn && raw_ch == ERR) {\r\n      // We have a timeout, invoke the validation function if we have one.\r\n      fn(s);\r\n      // reset the color since the validator may have changed it.\r\n      window->SetColor(SchemeId::EDITLINE);\r\n      continue;\r\n    }\r\n    switch (raw_ch) {\r\n    case KEY_F(1): // curses\r\n      done = true;\r\n      rc = EditlineResult::DONE;\r\n      break;\r\n    case KEY_HOME: // curses\r\n      pos = 0;\r\n      window->GotoXY(cx, cy);\r\n      break;\r\n    case KEY_END: // curses\r\n      pos = editlinestrlen(s);\r\n      window->GotoXY(cx + pos, cy);\r\n      break;\r\n    case KEY_RIGHT:    // curses\r\n      if (pos < len) { // right\r\n        const auto mp = editlinestrlen(s);\r\n        if (pos < mp) {\r\n          pos++;\r\n          window->GotoXY(cx + pos, cy);\r\n        }\r\n      }\r\n      break;\r\n    case KEY_LEFT:   // curses\r\n      if (pos > 0) { // left\r\n        pos--;\r\n        window->GotoXY(cx + pos, cy);\r\n      }\r\n      break;\r\n    case io::CO:     // return\r\n    case KEY_UP: // curses\r\n      done = true;\r\n      rc = EditlineResult::PREV;\r\n      break;\r\n    case KEY_DOWN: // curses\r\n      done = true;\r\n      rc = EditlineResult::NEXT;\r\n      break;\r\n#ifdef __PDCURSES__\r\n    // This is a PD-CURSES only key, ncurses doesn't support alt keys\r\n    // directly.\r\n    case ALT_I:\r\n#endif\r\n    case KEY_IC: // curses\r\n      if (status != EditLineMode::SET) {\r\n        if (bInsert) {\r\n          bInsert = false;\r\n          curses_out->SetIndicatorMode(IndicatorMode::overwrite);\r\n          window->GotoXY(cx + pos, cy);\r\n        } else {\r\n          bInsert = true;\r\n          curses_out->SetIndicatorMode(IndicatorMode::insert);\r\n          window->GotoXY(cx + pos, cy);\r\n        }\r\n      }\r\n      break;\r\n    case KEY_DC: // curses\r\n    case io::CD: // control-d\r\n      if (status != EditLineMode::SET) {\r\n        for (int i = pos; i < len; i++) {\r\n          s[i] = s[i + 1];\r\n        }\r\n        s[len - 1] = static_cast<char>(background_character);\r\n        window->PutsXY(cx, cy, s);\r\n        window->GotoXY(cx + pos, cy);\r\n      }\r\n      break;\r\n    case KEY_PPAGE:\r\n    case KEY_NPAGE:\r\n      // Ignore page up and page down when editing a line.\r\n      break;\r\n    default: {\r\n      if (raw_ch > 31) {\r\n        auto ch = static_cast<char>(raw_ch & 0xff);\r\n        if (status == EditLineMode::UPPER_ONLY) {\r\n          ch = to_upper_case_char(ch);\r\n        } else if (status == EditLineMode::LOWER) {\r\n          ch = to_lower_case_char(ch);\r\n        }\r\n        if (status == EditLineMode::SET) {\r\n          ch = to_upper_case<char>(ch);\r\n          if (ch != ' ') {\r\n            bool bLookingForSpace = true;\r\n            for (int i = 0; i < len; i++) {\r\n              if (ch == ss[i] && bLookingForSpace) {\r\n                bLookingForSpace = false;\r\n                pos = i;\r\n                window->GotoXY(cx + pos, cy);\r\n                if (s[pos] == ' ') {\r\n                  ch = ss[pos];\r\n                } else {\r\n                  ch = ' ';\r\n                }\r\n              }\r\n            }\r\n            if (bLookingForSpace) {\r\n              ch = ss[pos];\r\n            }\r\n          }\r\n        }\r\n        // ReSharper disable CppRedundantParentheses\r\n        if (pos < len &&\r\n            (status == EditLineMode::ALL || status == EditLineMode::UPPER_ONLY ||\r\n             status == EditLineMode::SET || status == EditLineMode::LOWER ||\r\n             (status == EditLineMode::NUM_ONLY &&\r\n             ((ch >= '0' && ch <= '9') || ch == ' ' || (pos == 0 && ch == '-'))))) {\r\n          if (bInsert) {\r\n            for (auto i = len - 1; i > pos; i--) {\r\n              s[i] = s[i - 1];\r\n            }\r\n            s[pos++] = ch;\r\n            window->PutsXY(cx, cy, s);\r\n            window->GotoXY(cx + pos, cy);\r\n          } else {\r\n            s[pos++] = ch;\r\n            window->Putch(ch);\r\n          }\r\n        }\r\n      }\r\n    } break;\r\n    case KEY_ENTER:\r\n#ifdef PADENTER\r\n    case PADENTER:\r\n#endif\r\n    case io::ENTER: // return\r\n    case io::TAB:\r\n      done = true;\r\n      rc = EditlineResult::NEXT;\r\n      break;\r\n    case io::ESC: // esc\r\n      done = true;\r\n      rc = EditlineResult::DONE;\r\n      break;\r\n    case 0x7f:          // yet some other delete key\r\n    case KEY_BACKSPACE: // curses\r\n    case io::BACKSPACE: // backspace\r\n      if (status != EditLineMode::SET) {\r\n        if (pos > 0) {\r\n          for (int i = pos - 1; i < len; i++) {\r\n            s[i] = s[i + 1];\r\n          }\r\n          s[len - 1] = static_cast<char>(background_character);\r\n          pos--;\r\n          window->PutsXY(cx, cy, s);\r\n          window->GotoXY(cx + pos, cy);\r\n        }\r\n      }\r\n      break;\r\n    case io::CA: // control-a\r\n      pos = 0;\r\n      window->GotoXY(cx, cy);\r\n      break;\r\n    case io::CE: // control-e\r\n      pos = editlinestrlen(s);\r\n      window->GotoXY(cx + pos, cy);\r\n      break;\r\n    }\r\n  } while (!done);\r\n\r\n  int z = ssize(s);\r\n  while (z >= 0 && static_cast<unsigned char>(s[z - 1]) == background_character) {\r\n    --z;\r\n  }\r\n  s[z] = '\\0';\r\n\r\n  char szFinishedString[260];\r\n  sprintf(szFinishedString, \"%-255s\", s);\r\n  szFinishedString[len] = '\\0';\r\n  window->AttrSet(COLOR_PAIR(old_pair) | old_attr);\r\n  window->PutsXY(cx, cy, szFinishedString);\r\n  window->GotoXY(cx, cy);\r\n\r\n  return rc;\r\n}\r\n\r\nstd::vector<std::string>::size_type toggleitem(CursesWindow* window,\r\n                                               std::vector<std::string>::size_type value,\r\n                                               const std::vector<std::string>& strings,\r\n                                               EditlineResult* rc) {\r\n  if (value >= strings.size()) {\r\n    value = 0;\r\n  }\r\n\r\n  size_t max_size = 0;\r\n  for (const auto& item : strings) {\r\n    max_size = std::max<std::size_t>(max_size, item.size());\r\n  }\r\n\r\n  uint32_t old_attr;\r\n  short old_pair;\r\n  window->AttrGet(&old_attr, &old_pair);\r\n  window->SetColor(SchemeId::EDITLINE);\r\n  const auto cx = window->GetcurX();\r\n  const auto cy = window->GetcurY();\r\n  window->PutsXY(cx, cy, strings.at(value));\r\n  window->GotoXY(cx, cy);\r\n  auto done = false;\r\n  do {\r\n    const auto ch = window->GetChar();\r\n    switch (ch) {\r\n    case KEY_ENTER:\r\n    case io::ENTER:\r\n    case io::TAB:\r\n      done = true;\r\n      *rc = EditlineResult::NEXT;\r\n      break;\r\n    case io::ESC:\r\n    case KEY_F(1): // F1\r\n      done = true;\r\n      *rc = EditlineResult::DONE;\r\n      break;\r\n    case KEY_UP:   // UP\r\n    case KEY_BTAB: // SHIFT-TAB\r\n      done = true;\r\n      *rc = EditlineResult::PREV;\r\n      break;\r\n    case KEY_DOWN: // DOWN\r\n      done = true;\r\n      *rc = EditlineResult::NEXT;\r\n      break;\r\n    default:\r\n      if (ch == 32) {\r\n        value = (value + 1) % strings.size();\r\n        auto s = strings.at(value);\r\n        if (s.size() < max_size) {\r\n          s += std::string(max_size - s.size(), ' ');\r\n        }\r\n        window->PutsXY(cx, cy, s);\r\n        window->GotoXY(cx, cy);\r\n      }\r\n      break;\r\n    }\r\n  } while (!done);\r\n  window->AttrSet(COLOR_PAIR(old_pair) | old_attr);\r\n  window->PutsXY(cx, cy, strings.at(value));\r\n  window->GotoXY(cx, cy);\r\n  return value;\r\n}\r\n\r\n}\r\n"
  },
  {
    "path": "localui/input.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n// ReSharper disable CppClangTidyBugproneMacroParentheses\r\n#ifndef INCLUDED_LOCALUI_INPUT_H\r\n#define INCLUDED_LOCALUI_INPUT_H\r\n\r\n#include \"core/file.h\"\r\n#include \"core/scope_exit.h\"\r\n#include \"core/stl.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/curses_io.h\"\r\n#include \"localui/curses_win.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"local_io/keycodes.h\"\r\n#include \"sdk/config.h\"\r\n#include \"sdk/value/valueprovider.h\"\r\n\r\n#include <functional>\r\n#include <limits>\r\n#include <stdexcept>\r\n#include <string>\r\n#include <type_traits>\r\n#include <utility>\r\n#include <vector>\r\n\r\nnamespace wwiv::local::ui {\r\n\r\nenum class EditLineMode { NUM_ONLY, UPPER_ONLY, LOWER, ALL, SET };\r\n\r\n#ifdef __unix__\r\nstatic constexpr auto EDITLINE_FILENAME_CASE = EditLineMode::ALL;\r\n#else\r\nstatic constexpr auto EDITLINE_FILENAME_CASE = EditLineMode::ALL;\r\n#endif // __unix__\r\n\r\nenum class EditlineResult { PREV, NEXT, DONE, ABORTED };\r\n\r\nclass NavigationKeyConfig final {\r\npublic:\r\n  NavigationKeyConfig() = delete;\r\n  NavigationKeyConfig(const NavigationKeyConfig&) = delete;\r\n  NavigationKeyConfig(NavigationKeyConfig&&) = delete;\r\n  NavigationKeyConfig& operator=(const NavigationKeyConfig&) = delete;\r\n  NavigationKeyConfig& operator=(NavigationKeyConfig&&) = delete;\r\n  explicit NavigationKeyConfig(std::string keys) : keys_(std::move(keys)) {}\r\n  ~NavigationKeyConfig() = default;\r\n\r\n  char up{'['};\r\n  char dn{']'};\r\n  char up10{'{'};\r\n  char down10{'}'};\r\n  char quit{'Q'};\r\n  const std::string keys_;\r\n};\r\n\r\nbool dialog_yn(CursesWindow* window, const std::vector<std::string>& text);\r\nbool dialog_yn(CursesWindow* window, const std::string& text);\r\nstd::string dialog_input_string(CursesWindow* window, const std::string& prompt, int max_length);\r\nint dialog_input_number(CursesWindow* window, const std::string& prompt, int min_value,\r\n                        int max_value);\r\nint onek(UIWindow* window, const std::string& allowed, bool allow_keycodes = false);\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Line editing support\r\n\r\ntypedef std::function<void(std::string)> edline_validation_fn;\r\n\r\nEditlineResult editline(CursesWindow* window, std::string* s, int len, EditLineMode status,\r\n                        const char* ss, edline_validation_fn);\r\nEditlineResult editline(CursesWindow* window, char* s, int len, EditLineMode status,\r\n                        const char* ss, const edline_validation_fn&);\r\n\r\nEditlineResult editline(CursesWindow* window, std::string* s, int len, EditLineMode status,\r\n                        const char* ss);\r\nEditlineResult editline(CursesWindow* window, char* s, int len, EditLineMode status,\r\n                        const char* ss);\r\n\r\n/////////////////////////////////////////////////////////////////////////////\r\n// Line editing support\r\n\r\nstd::vector<std::string>::size_type toggleitem(CursesWindow* window,\r\n                                               std::vector<std::string>::size_type value,\r\n                                               const std::vector<std::string>& strings,\r\n                                               EditlineResult* rc);\r\n\r\nvoid input_password(CursesWindow* window, const std::string& prompt,\r\n                    const std::vector<std::string>& text, std::string* output, int max_length);\r\nint messagebox(UIWindow* window, const std::string& text);\r\nint messagebox(UIWindow* window, const std::vector<std::string>& text);\r\nint input_select_item(UIWindow* window, const std::string& prompt,\r\n                      const std::vector<std::string>& items);\r\n\r\ntemplate <typename T>\r\nstatic std::string to_restriction_string(T data, int size, const std::string& res) {\r\n  std::string s;\r\n  for (auto i = 0; i < size; i++) {\r\n    if (data & (1 << i)) {\r\n      s.push_back(res[i]);\r\n    } else {\r\n      s.push_back(' ');\r\n    }\r\n  }\r\n  return s;\r\n}\r\n\r\n// Base class of all items that can appear in a LocalUI based environment.\r\n\r\nclass Item {\r\npublic:\r\n  Item() = delete;\r\n  Item(const Item&) = delete;\r\n  Item(Item&&) = delete;\r\n  Item& operator=(const Item&) = delete;\r\n  Item& operator=(Item&&) = delete;\r\n  explicit Item(int width) : x_(0), y_(0), width_(width) {}\r\n  virtual ~Item() = default;\r\n  typedef ssize_t size_type;\r\n\r\n  [[nodiscard]] virtual int x() const noexcept { return x_; }\r\n  [[nodiscard]] virtual int y() const noexcept { return y_; }\r\n  virtual void set_x(int x) noexcept { x_ = x; }\r\n  virtual void set_y(int y) noexcept { y_ = y; }\r\n  [[nodiscard]] virtual int width() const noexcept { return width_; }\r\n  virtual void set_width(int width) noexcept { width_ = width; }\r\n  [[nodiscard]] std::size_t size() const noexcept { return width_; }\r\n\r\n  [[nodiscard]] virtual int column() const noexcept { return column_; }\r\n  void set_column(int column) noexcept { column_ = column; }\r\n\r\n  virtual void Display(CursesWindow* window) const = 0;\r\n\r\n protected:\r\n  int x_;\r\n  int y_;\r\n  int width_;\r\n  int column_{1};\r\n};\r\n\r\n// Base item of an editable value, this class does not use templates.\r\nclass BaseEditItem : public Item {\r\npublic:\r\n  BaseEditItem(int maxsize) : Item(maxsize) {}\r\n  ~BaseEditItem() override = default;\r\n\r\n  BaseEditItem() = delete;\r\n  BaseEditItem(BaseEditItem const&) = delete;\r\n  BaseEditItem(BaseEditItem&&) = delete;\r\n  BaseEditItem& operator=(BaseEditItem const&) = delete;\r\n  BaseEditItem& operator=(BaseEditItem&&) = delete;\r\n\r\n  void Display(CursesWindow* window) const override = 0;\r\n  virtual EditlineResult Run(CursesWindow* window) = 0;\r\n  BaseEditItem* set_help_text(const std::string& help_text) {\r\n    help_text_ = help_text;\r\n    return this;\r\n  }\r\n\r\n  [[nodiscard]] std::string help_text() const { return help_text_; }\r\n\r\nprotected:\r\n  std::string help_text_;\r\n};\r\n\r\n// Label class that's used to display a label for an EditItem\r\nclass Label : public Item {\r\npublic:\r\n  explicit Label(const std::string& text) : Label(wwiv::stl::size_int(text), text) {}\r\n\r\n  void Display(CursesWindow* window) const override;\r\n  void set_right_justified(bool r) noexcept { right_justify_ = r; }\r\n  [[nodiscard]] const std::string& text() const noexcept { return text_; }\r\n  [[nodiscard]] virtual int height() const { return 1; }\r\n\r\nprotected:\r\n  Label(int width, std::string text) : Item(width), text_(std::move(text)) {}\r\n  bool right_justify_{true};\r\n  const std::string text_;\r\n};\r\n\r\n// Label class that's used to display a label for an EditItem\r\nclass MultilineLabel final : public Label {\r\npublic:\r\n  MultilineLabel(const std::string& text);\r\n\r\n  void Display(CursesWindow* window) const override;\r\n  [[nodiscard]] int height() const override;\r\n\r\nprivate:\r\n  std::vector<std::string> lines_;\r\n};\r\n\r\n// Base item of an editable value that uses templates to hold the\r\n// value under edit.\r\ntemplate <typename T> class EditItem : public BaseEditItem {\r\npublic:\r\n  typedef std::function<std::string()> displayfn;\r\n  EditItem() = delete;\r\n  EditItem(EditItem const&) = delete;\r\n  EditItem(EditItem&&) = delete;\r\n  EditItem& operator=(EditItem const&) = delete;\r\n  EditItem& operator=(EditItem&&) = delete;\r\n\r\n  EditItem(int maxsize, T data) : BaseEditItem(maxsize), data_(data) {}\r\n  ~EditItem() override = default;\r\n\r\n  void set_displayfn(displayfn f) { display_ = f; }\r\n  void set_width(int width) noexcept override {\r\n    if (width < width_) {\r\n      // NOP.  We don't allow setting the width over the original width.\r\n      width_ = width;\r\n    }\r\n  }\r\n\r\n  void Display(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    if (display_) {\r\n      const std::string blanks(width(), ' ');\r\n      const auto custom = display_();\r\n      window->PutsXY(x_, y_, blanks);\r\n      window->PutsXY(x_, y_, custom);\r\n    } else {\r\n      DefaultDisplay(window);\r\n    }\r\n  }\r\n\r\nprotected:\r\n  virtual void DefaultDisplay(CursesWindow* window) const = 0;\r\n  virtual void DefaultDisplayString(CursesWindow* window, const std::string& text) const {\r\n    auto s = text;\r\n    if (wwiv::stl::ssize(s) > width()) {\r\n      s = text.substr(0, width());\r\n    } else if (wwiv::stl::ssize(s) < width()) {\r\n      s = text + std::string(static_cast<std::string::size_type>(width()) - text.size(), ' ');\r\n    }\r\n\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    window->PutsXY(this->x_, this->y_, s);\r\n  }\r\n\r\n  [[nodiscard]] T data() const noexcept { return data_; }\r\n  void set_data(T data) noexcept { data_ = data; }\r\n\r\n  T data_;\r\n  displayfn display_;\r\n};\r\n\r\ntemplate <typename T> class StringEditItem : public EditItem<T> {\r\npublic:\r\n  StringEditItem(int maxsize, T data, EditLineMode edit_line_mode = EditLineMode::ALL)\r\n    : EditItem<T>(maxsize, data), edit_line_mode_(edit_line_mode) {}\r\n\r\n  ~StringEditItem() override = default;\r\n\r\n  StringEditItem() = delete;\r\n  StringEditItem(StringEditItem const&) = delete;\r\n  StringEditItem(StringEditItem&&) = delete;\r\n  StringEditItem& operator=(StringEditItem const&) = delete;\r\n  StringEditItem& operator=(StringEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    // GCC wants this-> on data and width_.\r\n    return editline(window, reinterpret_cast<char*>(this->data_), this->width_, edit_line_mode_,\r\n                    \"\");\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    this->DefaultDisplayString(\r\n        window, std::string(reinterpret_cast<char*>(const_cast<const T>(this->data_))));\r\n  }\r\n\r\nprivate:\r\n  EditLineMode edit_line_mode_;\r\n};\r\n\r\ntemplate <> class StringEditItem<std::string&> final : public EditItem<std::string&> {\r\npublic:\r\n  StringEditItem(int maxsize, std::string& data, EditLineMode mode)\r\n      : EditItem<std::string&>(maxsize, data), edit_line_mode_(mode) {}\r\n  ~StringEditItem() override = default;\r\n  StringEditItem() = delete;\r\n  StringEditItem(StringEditItem const&) = delete;\r\n  StringEditItem(StringEditItem&&) = delete;\r\n  StringEditItem& operator=(StringEditItem const&) = delete;\r\n  StringEditItem& operator=(StringEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    return editline(window, &this->data_, this->width_, edit_line_mode_, \"\");\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    this->DefaultDisplayString(window, data_);\r\n  }\r\n\r\nprivate:\r\n  EditLineMode edit_line_mode_;\r\n};\r\n\r\n// String Editor for Strings with Pipe codes.  The UI will attempt to display\r\n// These with color in the UI when not editing.\r\nclass StringEditItemWithPipeCodes final : public EditItem<std::string&> {\r\npublic:\r\n  StringEditItemWithPipeCodes(int maxsize, std::string& data, EditLineMode mode)\r\n      : EditItem<std::string&>(maxsize, data), edit_line_mode_(mode) {}\r\n  ~StringEditItemWithPipeCodes() override = default;\r\n  StringEditItemWithPipeCodes() = delete;\r\n  StringEditItemWithPipeCodes(StringEditItemWithPipeCodes const&) = delete;\r\n  StringEditItemWithPipeCodes(StringEditItemWithPipeCodes&&) = delete;\r\n  StringEditItemWithPipeCodes& operator=(StringEditItemWithPipeCodes const&) = delete;\r\n  StringEditItemWithPipeCodes& operator=(StringEditItemWithPipeCodes&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    curses_out->footer()->ShowHelpItems(\r\n        0, {{\"Esc\", \"Exit\"}, {\"NOTE\", \"Pipe codes allowed.\"}});\r\n    window->GotoXY(this->x_, this->y_);\r\n    return editline(window, &this->data_, this->width_, edit_line_mode_, \"\");\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    auto s = data_;\r\n    if (const auto siz = wwiv::strings::size_without_colors(s); siz > width()) {\r\n      s = strings::trim_to_size_ignore_colors(s, width());\r\n    } else if (siz < width()) {\r\n      const auto num_padding = width() - siz;\r\n      s = s + std::string(num_padding, ' ');\r\n    }\r\n\r\n    window->PutsWithPipeColors(x_, y_, s);\r\n  }\r\n\r\nprivate:\r\n  EditLineMode edit_line_mode_;\r\n};\r\n\r\nclass ACSEditItem final : public EditItem<std::string&> {\r\npublic:\r\n  ACSEditItem(const sdk::Config&, std::vector<const sdk::value::ValueProvider*> p,\r\n              int maxsize, std::string& data)\r\n      : EditItem<std::string&>(maxsize, data), providers_(std::move(p)),\r\n        edit_line_mode_(EditLineMode::ALL) {}\r\n  ~ACSEditItem() override = default;\r\n  ACSEditItem() = delete;\r\n  ACSEditItem(ACSEditItem const&) = delete;\r\n  ACSEditItem(ACSEditItem&&) = delete;\r\n  ACSEditItem& operator=(ACSEditItem const&) = delete;\r\n  ACSEditItem& operator=(ACSEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override;\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override;\r\n\r\nprivate:\r\n  std::vector<const sdk::value::ValueProvider*> providers_;\r\n  EditLineMode edit_line_mode_;\r\n};\r\n\r\n\r\nclass FidoAddressStringEditItem : public EditItem<std::string&> {\r\npublic:\r\n  FidoAddressStringEditItem(int maxsize, std::string& data)\r\n      : EditItem<std::string&>(maxsize, data), edit_line_mode_(EditLineMode::LOWER) {}\r\n  ~FidoAddressStringEditItem() override = default;\r\n  FidoAddressStringEditItem() = delete;\r\n  FidoAddressStringEditItem(FidoAddressStringEditItem const&) = delete;\r\n  FidoAddressStringEditItem(FidoAddressStringEditItem&&) = delete;\r\n  FidoAddressStringEditItem& operator=(FidoAddressStringEditItem const&) = delete;\r\n  FidoAddressStringEditItem& operator=(FidoAddressStringEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override;\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override;\r\n\r\nprivate:\r\n  EditLineMode edit_line_mode_;\r\n};\r\n\r\n\r\ntemplate <typename T, int MAXLEN = std::numeric_limits<T>::digits10>\r\nclass NumberEditItem final : public EditItem<T*> {\r\npublic:\r\n  explicit NumberEditItem(T* data) : EditItem<T*>(MAXLEN + 2, data) {}\r\n  ~NumberEditItem() override = default;\r\n  NumberEditItem() = delete;\r\n  NumberEditItem(NumberEditItem const&) = delete;\r\n  NumberEditItem(NumberEditItem&&) = delete;\r\n  NumberEditItem& operator=(NumberEditItem const&) = delete;\r\n  NumberEditItem& operator=(NumberEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    auto s = std::to_string(*this->data_);\r\n    auto return_code = editline(window, &s, MAXLEN + 1, EditLineMode::NUM_ONLY, \"\");\r\n    *this->data_ = wwiv::strings::to_number<T>(s);\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    const auto d = std::to_string(*this->data_);\r\n    window->PutsXY(this->x_, this->y_, fmt::format(\"{:<{}}\", d, this->width()));\r\n  }\r\n};\r\n\r\ntemplate <typename T> constexpr typename std::underlying_type<T>::type enum_to_int(T value) {\r\n  return static_cast<typename std::underlying_type<T>::type>(value);\r\n}\r\n\r\ntemplate <typename T>\r\nstd::vector<std::string> item_list(const std::vector<std::pair<T, std::string>>& orig) {\r\n  std::vector<std::string> items;\r\n  for (const auto& e : orig) {\r\n    items.push_back(e.second);\r\n  }\r\n  return items;\r\n}\r\n\r\ntemplate <typename T>\r\nint index_of(T& haystack, const std::vector<std::pair<T, std::string>>& needle) {\r\n  for (auto i = 0; i < wwiv::stl::ssize(needle); i++) {\r\n    if (haystack == needle.at(i).first) {\r\n      return i;\r\n    }\r\n  }\r\n  return 0;\r\n}\r\n\r\ntemplate <typename T> class ToggleEditItem final : public EditItem<T*> {\r\npublic:\r\n  ToggleEditItem(const std::vector<std::pair<T, std::string>>& items, T* data)\r\n      : EditItem<T*>(0, data), items_(items) {\r\n    for (const auto& item : items) {\r\n      this->width_ = std::max<int>(this->width_, wwiv::strings::ssize(item.second));\r\n    }\r\n  }\r\n\r\n  ~ToggleEditItem() override = default;\r\n  ToggleEditItem() = delete;\r\n  ToggleEditItem(ToggleEditItem const&) = delete;\r\n  ToggleEditItem(ToggleEditItem&&) = delete;\r\n  ToggleEditItem& operator=(ToggleEditItem const&) = delete;\r\n  ToggleEditItem& operator=(ToggleEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    curses_out->footer()->ShowHelpItems(0, {{\"Esc\", \"Exit\"}, {\"SPACE\", \"Toggle Item\"}});\r\n\r\n    window->GotoXY(this->x_, this->y_);\r\n    auto return_code = EditlineResult::NEXT;\r\n    auto index = index_of(*this->data_, items_);\r\n    const auto items = item_list(items_);\r\n    index = static_cast<int>(toggleitem(window, index, items, &return_code));\r\n    *this->data_ = static_cast<T>(items_.at(index).first);\r\n    DefaultDisplay(window);\r\n    curses_out->footer()->SetDefaultFooter();\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    try {\r\n      auto index = index_of(*this->data_, items_);\r\n      const auto& s = items_.at(index).second;\r\n      this->DefaultDisplayString(window, s);\r\n    } catch (const std::out_of_range&) {\r\n      this->DefaultDisplayString(window, \"\");\r\n    }\r\n  }\r\n\r\nprivate:\r\n  const std::vector<std::pair<T, std::string>> items_;\r\n};\r\n\r\nstatic int maxlen_from_list(const std::vector<std::string>& items) {\r\n  std::string::size_type m = 0;\r\n  for (const auto& item : items) {\r\n    m = std::max<std::string::size_type>(m, item.size());\r\n  }\r\n  return static_cast<int>(m);\r\n}\r\n\r\nclass StringListItem final : public EditItem<std::string&> {\r\npublic:\r\n  StringListItem(const std::vector<std::string>& items, std::string& data)\r\n      : EditItem<std::string&>(maxlen_from_list(items), data), items_(items) {}\r\n  ~StringListItem() override = default;\r\n  StringListItem() = delete;\r\n  StringListItem(StringListItem const&) = delete;\r\n  StringListItem(StringListItem&&) = delete;\r\n  StringListItem& operator=(StringListItem const&) = delete;\r\n  StringListItem& operator=(StringListItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    curses_out->footer()->ShowHelpItems(0, {{\"Esc\", \"Exit\"}, {\"SPACE\", \"Toggle Item\"}});\r\n    window->GotoXY(this->x_, this->y_);\r\n    auto return_code = EditlineResult::NEXT;\r\n    const auto it = std::find(items_.begin(), items_.end(), data_);\r\n    std::vector<std::string>::size_type selection = 0;\r\n    if (it != items_.end()) {\r\n      selection = std::distance(items_.begin(), it);\r\n    }\r\n    selection = toggleitem(window, static_cast<std::vector<std::string>::size_type>(selection),\r\n                           items_, &return_code);\r\n    data_ = items_.at(selection);\r\n    curses_out->footer()->SetDefaultFooter();\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override { DefaultDisplayString(window, data_); }\r\n\r\nprivate:\r\n  const std::vector<std::string> items_;\r\n};\r\n\r\ntemplate <typename T> class FlagEditItem final : public EditItem<T*> {\r\npublic:\r\n  FlagEditItem(int flag, const std::string& on, const std::string& off, T* data)\r\n      : EditItem<T*>(0, data), flag_(flag) {\r\n    this->width_ = std::max<int>(wwiv::stl::size_int(on), wwiv::stl::size_int(off));\r\n    this->items_.push_back(off);\r\n    this->items_.push_back(on);\r\n  }\r\n\r\n  ~FlagEditItem() override = default;\r\n  FlagEditItem() = delete;\r\n  FlagEditItem(FlagEditItem const&) = delete;\r\n  FlagEditItem(FlagEditItem&&) = delete;\r\n  FlagEditItem& operator=(FlagEditItem const&) = delete;\r\n  FlagEditItem& operator=(FlagEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    curses_out->footer()->ShowHelpItems(0, {{\"Esc\", \"Exit\"}, {\"SPACE\", \"Toggle Item\"}});\r\n    auto return_code = EditlineResult::NEXT;\r\n    std::vector<std::string>::size_type state = (*this->data_ & this->flag_) ? 1 : 0;\r\n    state = toggleitem(window, state, this->items_, &return_code);\r\n    if (state == 0) {\r\n      *this->data_ &= ~this->flag_;\r\n    } else {\r\n      *this->data_ |= this->flag_;\r\n    }\r\n    curses_out->footer()->SetDefaultFooter();\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    const int state = (*this->data_ & this->flag_) ? 1 : 0;\r\n    this->DefaultDisplayString(window, items_.at(state));\r\n  }\r\n\r\nprivate:\r\n  std::vector<std::string> items_;\r\n  int flag_;\r\n};\r\n\r\nclass BaseRestrictionsEditItem : public EditItem<uint16_t*> {\r\npublic:\r\n  BaseRestrictionsEditItem(const char* rs, int rs_size, uint16_t* data)\r\n      : EditItem<uint16_t*>(rs_size, data), rs_(rs), rs_size_(rs_size) {}\r\n\r\n  ~BaseRestrictionsEditItem() override = default;\r\n  BaseRestrictionsEditItem() = delete;\r\n  BaseRestrictionsEditItem(BaseRestrictionsEditItem const&) = delete;\r\n  BaseRestrictionsEditItem(BaseRestrictionsEditItem&&) = delete;\r\n  BaseRestrictionsEditItem& operator=(BaseRestrictionsEditItem const&) = delete;\r\n  BaseRestrictionsEditItem& operator=(BaseRestrictionsEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n\r\n    window->GotoXY(this->x_, this->y_);\r\n    char s[21];\r\n    char rs[21];\r\n    char ch1 = '0';\r\n\r\n    wwiv::strings::to_char_array(rs, rs_);\r\n    for (int i = 0; i < rs_size_; i++) {\r\n      if (rs[i] == ' ') {\r\n        rs[i] = ch1++;\r\n      }\r\n      if (*this->data_ & (1 << i)) {\r\n        s[i] = rs[i];\r\n      } else {\r\n        s[i] = 32;\r\n      }\r\n    }\r\n    s[rs_size_] = 0;\r\n\r\n    const auto return_code = editline(window, s, 16, EditLineMode::SET, rs);\r\n\r\n    *this->data_ = 0;\r\n    for (auto i = 0; i < rs_size_; i++) {\r\n      if (s[i] != 32 && s[i] != 0) {\r\n        *this->data_ |= (1 << i);\r\n      }\r\n    }\r\n\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    const auto s = to_restriction_string(*data_, rs_size_, rs_);\r\n    DefaultDisplayString(window, s);\r\n  }\r\n  std::string rs_;\r\n  int rs_size_{0};\r\n};\r\n\r\nstatic const char* ar_string = \"ABCDEFGHIJKLMNOP\";\r\nstatic constexpr int ar_string_size = 16;\r\nstatic const char* xrestrictstring = \"LCMA*PEVKNU     \";\r\nstatic constexpr int xrestrictstring_size = 16;\r\n\r\nclass RestrictionsEditItem final : public BaseRestrictionsEditItem {\r\npublic:\r\n  explicit RestrictionsEditItem(uint16_t* data)\r\n      : BaseRestrictionsEditItem(xrestrictstring, xrestrictstring_size, data) {}\r\n  ~RestrictionsEditItem() override = default;\r\n  RestrictionsEditItem() = delete;\r\n  RestrictionsEditItem(RestrictionsEditItem const&) = delete;\r\n  RestrictionsEditItem(RestrictionsEditItem&&) = delete;\r\n  RestrictionsEditItem& operator=(RestrictionsEditItem const&) = delete;\r\n  RestrictionsEditItem& operator=(RestrictionsEditItem&&) = delete;\r\n};\r\n\r\nclass ArEditItem final : public BaseRestrictionsEditItem {\r\npublic:\r\n  explicit ArEditItem(uint16_t* data)\r\n      : BaseRestrictionsEditItem(ar_string, ar_string_size, data) {}\r\n  ~ArEditItem() override = default;\r\n  ArEditItem() = delete;\r\n  ArEditItem(ArEditItem const&) = delete;\r\n  ArEditItem(ArEditItem&&) = delete;\r\n  ArEditItem& operator=(ArEditItem const&) = delete;\r\n  ArEditItem& operator=(ArEditItem&&) = delete;\r\n};\r\n\r\nclass BooleanEditItem final : public EditItem<bool*> {\r\npublic:\r\n  explicit BooleanEditItem(bool* data) : EditItem<bool*>(6, data) {}\r\n  ~BooleanEditItem() override = default;\r\n  BooleanEditItem() = delete;\r\n  BooleanEditItem(BooleanEditItem const&) = delete;\r\n  BooleanEditItem(BooleanEditItem&&) = delete;\r\n  BooleanEditItem& operator=(BooleanEditItem const&) = delete;\r\n  BooleanEditItem& operator=(BooleanEditItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    curses_out->footer()->ShowHelpItems(0, {{\"Esc\", \"Exit\"}, {\"SPACE\", \"Toggle Item\"}});\r\n    static const std::vector<std::string> boolean_strings{\"No \", \"Yes\"};\r\n\r\n    window->GotoXY(this->x_, this->y_);\r\n    std::vector<std::string>::size_type data = *this->data_ ? 1 : 0;\r\n    auto return_code = EditlineResult::NEXT;\r\n    data = toggleitem(window, data, boolean_strings, &return_code);\r\n\r\n    *this->data_ = (data > 0) ? true : false;\r\n    curses_out->footer()->SetDefaultFooter();\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    static const std::vector<std::string> boolean_strings = {\"No \", \"Yes\"};\r\n    const auto& s = boolean_strings.at(*data_ ? 1 : 0);\r\n    DefaultDisplayString(window, s);\r\n  }\r\n};\r\n\r\nclass CustomEditItem final : public BaseEditItem {\r\npublic:\r\n  typedef std::function<void(const std::string&)> displayfn;\r\n  typedef std::function<std::string()> prefn;\r\n  typedef std::function<void(const std::string&)> postfn;\r\n  CustomEditItem(int maxsize, prefn to_field, postfn from_field)\r\n      : BaseEditItem(maxsize), to_field_(std::move(to_field)),\r\n        from_field_(std::move(from_field)), field_width_(maxsize) {}\r\n  CustomEditItem() = delete;\r\n  CustomEditItem(CustomEditItem const&) = delete;\r\n  CustomEditItem(CustomEditItem&&) = delete;\r\n  CustomEditItem& operator=(CustomEditItem const&) = delete;\r\n  CustomEditItem& operator=(CustomEditItem&&) = delete;\r\n  ~CustomEditItem() override = default;\r\n\r\n  EditlineResult Run(CursesWindow* window) override;\r\n  void Display(CursesWindow* window) const override;\r\n  void set_displayfn(displayfn f) { display_ = f; }\r\n\r\nprivate:\r\n  prefn to_field_;\r\n  postfn from_field_;\r\n  displayfn display_;\r\n  int field_width_{1};\r\n};\r\n\r\n\r\nclass FileSystemFilePathItem final : public EditItem<std::filesystem::path&> {\r\npublic:\r\n  FileSystemFilePathItem(int maxsize, std::filesystem::path base,\r\n                         std::filesystem::path& data)\r\n      : EditItem<std::filesystem::path&>(maxsize, data), base_(std::move(base)) {\r\n    help_text_ =\r\n        strings::StrCat(\"Enter an absolute path or path relative to: '\", base_.string(), \"'\");\r\n  }\r\n  ~FileSystemFilePathItem() override = default;\r\n  FileSystemFilePathItem() = delete;\r\n  FileSystemFilePathItem(FileSystemFilePathItem const&) = delete;\r\n  FileSystemFilePathItem(FileSystemFilePathItem&&) = delete;\r\n  FileSystemFilePathItem& operator=(FileSystemFilePathItem const&) = delete;\r\n  FileSystemFilePathItem& operator=(FileSystemFilePathItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    auto data = this->data_.string();\r\n    const auto return_code = editline(window, &data, this->width_, EDITLINE_FILENAME_CASE, \"\");\r\n    strings::StringTrimEnd(&data);\r\n    if (!data.empty()) {\r\n      data = core::File::EnsureTrailingSlash(data);\r\n    }\r\n    // Update what we display in case it changed.\r\n    DefaultDisplay(window);\r\n\r\n    const auto dir = wwiv::core::File::absolute(this->base_, data);\r\n    if (!core::File::Exists(dir)) {\r\n      const auto s1 = wwiv::strings::StrCat(\"The path '\", dir, \"' does not exist.\");\r\n      if (dialog_yn(window, {s1, \"Would you like to create it?\"})) {\r\n        if (!core::File::mkdirs(dir)) {\r\n          messagebox(window, {\"Unable to create directory: \", dir.string()});\r\n        }\r\n      }\r\n    }\r\n    // Set the path in the base class\r\n    data_ = data;\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    DefaultDisplayString(window, data_.string());\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path base_;\r\n};\r\n\r\nclass StringFilePathItem final : public EditItem<std::string&> {\r\npublic:\r\n  StringFilePathItem(int maxsize, const std::filesystem::path& base,\r\n                     std::string& data)\r\n      : EditItem<std::string&>(maxsize, data), base_(base) {\r\n    help_text_ = strings::StrCat(\"Enter an absolute path or path relative to: '\", base, \"'\");\r\n  }\r\n  ~StringFilePathItem() override = default;\r\n\r\n  StringFilePathItem() = delete;\r\n  StringFilePathItem(StringFilePathItem const&) = delete;\r\n  StringFilePathItem(StringFilePathItem&&) = delete;\r\n  StringFilePathItem& operator=(StringFilePathItem const&) = delete;\r\n  StringFilePathItem& operator=(StringFilePathItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    const auto return_code =\r\n        editline(window, &this->data_, this->width_, EDITLINE_FILENAME_CASE, \"\");\r\n    strings::StringTrimEnd(&this->data_);\r\n    if (!data_.empty()) {\r\n      data_ = core::File::EnsureTrailingSlash(data_);\r\n    }\r\n    // Update what we display in case it changed.\r\n    DefaultDisplay(window);\r\n\r\n    const auto dir = wwiv::core::File::absolute(this->base_, this->data_);\r\n    if (!wwiv::core::File::Exists(dir)) {\r\n      const auto s1 = wwiv::strings::StrCat(\"The path '\", dir, \"' does not exist.\");\r\n      if (dialog_yn(window, {s1, \"Would you like to create it?\"})) {\r\n        if (!wwiv::core::File::mkdirs(dir)) {\r\n          messagebox(window, {\"Unable to create directory: \", dir.string()});\r\n        }\r\n      }\r\n    }\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    DefaultDisplayString(window, data_);\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path base_;\r\n};\r\n\r\n\r\n/**\r\n * EditItem for a filename. \r\n * \r\n * Will check and warn if the file at base/filename doesn't exist.\r\n */\r\nclass StringFileNameItem final : public EditItem<std::string&> {\r\npublic:\r\n  StringFileNameItem(int maxsize, const std::filesystem::path& base, std::string& data)\r\n      : EditItem<std::string&>(maxsize, data), base_(base) {\r\n    help_text_ = strings::StrCat(\"Enter an absolute path or path relative to: '\", base, \"'\");\r\n  }\r\n  ~StringFileNameItem() override = default;\r\n\r\n  StringFileNameItem() = delete;\r\n  StringFileNameItem(StringFileNameItem const&) = delete;\r\n  StringFileNameItem(StringFileNameItem&&) = delete;\r\n  StringFileNameItem& operator=(StringFileNameItem const&) = delete;\r\n  StringFileNameItem& operator=(StringFileNameItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    const auto return_code =\r\n        editline(window, &this->data_, this->width_, EDITLINE_FILENAME_CASE, \"\");\r\n    strings::StringTrimEnd(&this->data_);\r\n    // Update what we display in case it changed.\r\n    DefaultDisplay(window);\r\n\r\n    const auto file = wwiv::core::File::absolute(this->base_, this->data_);\r\n    if (!wwiv::core::File::Exists(file)) {\r\n      messagebox(window, {\"The filename does not exist: \", file.string()});\r\n    }\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    DefaultDisplayString(window, data_);\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path base_;\r\n};\r\n\r\n\r\nclass CommandLineItem final : public EditItem<char*> {\r\npublic:\r\n  CommandLineItem(int maxsize, char* data) : EditItem<char*>(maxsize, data) {}\r\n  ~CommandLineItem() override = default;\r\n  CommandLineItem() = delete;\r\n  CommandLineItem(CommandLineItem const&) = delete;\r\n  CommandLineItem(CommandLineItem&&) = delete;\r\n  CommandLineItem& operator=(CommandLineItem const&) = delete;\r\n  CommandLineItem& operator=(CommandLineItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    window->GotoXY(this->x_, this->y_);\r\n    const auto return_code =\r\n        editline(window, this->data_, this->width_, EDITLINE_FILENAME_CASE, \"\");\r\n    std::string s(this->data_);\r\n    wwiv::strings::StringTrimEnd(&s);\r\n    strcpy(this->data_, s.c_str());\r\n    return return_code;\r\n  }\r\n\r\nprotected:\r\n  void DefaultDisplay(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    DefaultDisplayString(window, data_);\r\n  }\r\n};\r\n\r\n\r\n/**\r\n * EditItem that executes a std::function<T, CursesWindow*> to\r\n * edit the items. It is intended that this function will invoke\r\n * a new EditItem dialog or ListBox for editing.\r\n */\r\ntemplate <class T> class SubDialog : public BaseEditItem {\r\npublic:\r\n  SubDialog(const wwiv::sdk::Config& c, T& t)\r\n      : BaseEditItem(25), c_(c), t_(t) {}\r\n  ~SubDialog() override = default;\r\n  SubDialog() = delete;\r\n  SubDialog(const SubDialog&) = delete;\r\n  SubDialog(SubDialog&&) = delete;\r\n  SubDialog& operator=(const SubDialog&) = delete;\r\n  SubDialog& operator=(SubDialog&&) = delete;\r\n\r\n  virtual void RunSubDialog(CursesWindow* window) = 0;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    auto at_exit = core::finally([] { curses_out->footer()->SetDefaultFooter(); });\r\n    curses_out->footer()->ShowHelpItems(\r\n        0, {{\"Esc\", \"Exit\"}, {\"ENTER\", \"Edit Items (opens new dialog).\"}});\r\n    window->GotoXY(x_, y_);\r\n    uint32_t old_attr;\r\n    short old_pair;\r\n    window->AttrGet(&old_attr, &old_pair);\r\n    window->SetColor(SchemeId::EDITLINE);\r\n    // Don't use Display since we use that when we don't have focus here.\r\n    window->PutsXY(x_, y_, menu_label());\r\n    window->GotoXY(x_, y_);\r\n    const auto ch = window->GetChar();\r\n    window->AttrSet(COLOR_PAIR(old_pair) | old_attr);\r\n    if (ch == KEY_ENTER || ch == io::TAB || ch == io::ENTER) {\r\n      RunSubDialog(window);\r\n      window->RedrawWin();\r\n    } else if (ch == KEY_UP || ch == KEY_BTAB) {\r\n      return EditlineResult::PREV;\r\n    } else if (ch == io::ESC) {\r\n      return EditlineResult::DONE;\r\n    }\r\n    return EditlineResult::NEXT;\r\n  }\r\n\r\n  void Display(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    window->PutsXY(x_, y_, menu_label());\r\n  }\r\n\r\nprotected:\r\n  [[nodiscard]] const wwiv::sdk::Config& config() const noexcept { return c_; }\r\n  [[nodiscard]] virtual std::string menu_label() const { return \"[Edit]\"; }\r\n\r\n  const sdk::Config& c_;\r\n  T& t_;\r\n};\r\n\r\n/**\r\n * EditItem that executes a std::function<T, CursesWindow*> to\r\n * edit the items. It is intended that this function will invoke\r\n * a new EditItem dialog or ListBox for editing.\r\n */\r\ntemplate <class T> class SubDialogFunction final : public SubDialog<T> {\r\npublic:\r\n  SubDialogFunction() = delete;\r\n  SubDialogFunction(const SubDialogFunction&) = delete;\r\n  SubDialogFunction(SubDialogFunction&&) = delete;\r\n  SubDialogFunction& operator=(const SubDialogFunction&) = delete;\r\n  SubDialogFunction& operator=(SubDialogFunction&&) = delete;\r\n  SubDialogFunction(const sdk::Config& c, T& t,\r\n                    std::function<void(const sdk::Config&, T&, CursesWindow*)> fn)\r\n      : SubDialog<T>(c, t), c_(c), typ_(t), fn_(std::move(fn)) {}\r\n  ~SubDialogFunction() override = default;\r\n\r\n  void RunSubDialog(CursesWindow* window) override { fn_(c_, typ_, window); }\r\n\r\nprivate:\r\n  // For some reason GCC couldn't find config() or t_ from SubDialog.\r\n  const sdk::Config& c_;\r\n  T& typ_;\r\n  std::function<void(const wwiv::sdk::Config&, T&, CursesWindow*)> fn_;\r\n};\r\n\r\n/**\r\n * EditItem that executes a std::function<T, CursesWindow*> to\r\n * edit the items. It is intended that this function will invoke\r\n * a new EditItem dialog or ListBox for editing.\r\n */\r\nclass EditExternalFileItem final : public BaseEditItem {\r\npublic:\r\n  explicit EditExternalFileItem(std::filesystem::path path);\r\n  ~EditExternalFileItem() override = default;\r\n  EditExternalFileItem() = delete;\r\n  EditExternalFileItem(EditExternalFileItem const&) = delete;\r\n  EditExternalFileItem(EditExternalFileItem&&) = delete;\r\n  EditExternalFileItem& operator=(EditExternalFileItem const&) = delete;\r\n  EditExternalFileItem& operator=(EditExternalFileItem&&) = delete;\r\n\r\n  EditlineResult Run(CursesWindow* window) override {\r\n    auto at_exit = core::finally([] { curses_out->footer()->SetDefaultFooter(); });\r\n    curses_out->footer()->ShowHelpItems(\r\n        0, {{\"Esc\", \"Exit\"}, {\"ENTER\", \"Edit File (opens editor)\"}});\r\n    window->GotoXY(x_, y_);\r\n    uint32_t old_attr;\r\n    short old_pair;\r\n    window->AttrGet(&old_attr, &old_pair);\r\n    window->SetColor(SchemeId::EDITLINE);\r\n    window->PutsXY(x_, y_, menu_label());\r\n    window->GotoXY(x_, y_);\r\n    const auto ch = window->GetChar();\r\n    window->AttrSet(COLOR_PAIR(old_pair) | old_attr);\r\n    if (ch == KEY_ENTER || ch == io::TAB || ch == io::ENTER) {\r\n      curses_out->DisableLocalIO();\r\n      std::string exe;\r\n#ifdef _WIN32\r\n      exe = \".exe\";\r\n#endif\r\n      const auto cmd = fmt::format(\".{}wwivfsed{} -F {}\", wwiv::core::File::pathSeparatorChar, exe, path_.string());\r\n      system(cmd.c_str());\r\n      curses_out->ReenableLocalIO();\r\n      window->RedrawWin();\r\n    } else if (ch == KEY_UP || ch == KEY_BTAB) {\r\n      return EditlineResult::PREV;\r\n    } else if (ch == io::ESC) {\r\n      return EditlineResult::DONE;\r\n    }\r\n    return EditlineResult::NEXT;\r\n  }\r\n\r\n  void Display(CursesWindow* window) const override {\r\n    window->SetColor(SchemeId::WINDOW_DATA);\r\n    window->PutsXY(x_, y_, menu_label());\r\n  }\r\n\r\nprotected:\r\n  [[nodiscard]] std::string menu_label() const noexcept { return \"[Edit]\"; }\r\n\r\n  const std::filesystem::path path_;\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "localui/listbox.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"listbox.h\"\n\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"localui/colors.h\"\n#include \"localui/input.h\"\n#include \"localui/wwiv_curses.h\"\n#include <algorithm>\n#include <cmath>\n#include <iostream>\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic constexpr int MINIMUM_LISTBOX_HEIGHT = 10;\nstatic constexpr double RATIO_LISTBOX_HEIGHT = 0.8;\nstatic constexpr double RATIO_LISTBOX_WIDTH = 0.9;\n\nnamespace wwiv::local::ui {\n\n\nstatic std::vector<HelpItem> StandardHelpItems() { return {{\"Esc\", \"Exit\"}}; }\n\nListBox::ListBox(UIWindow* parent, const std::string& title, int max_x, int max_y,\n                 std::vector<ListBoxItem>& items, ColorScheme* scheme)\n    : title_(title), items_(items), color_scheme_(scheme), window_top_min_(1), parent_(parent) {\n  height_ = std::min<int>(size_int(items), max_y);\n  const auto window_height = 2 + height_ + window_top_min_ - 1;\n  auto longest_line = std::max<int>(2, size_int(title) + 4);\n  int num{0};\n  for (auto& item : items_) {\n    item.index(num++);\n    longest_line = std::max<int>(longest_line, size_int(item.text()));\n    if (item.hotkey() > 0) {\n      hotkeys_.push_back(static_cast<char>(item.hotkey()));\n    }\n  }\n  width_ = std::min<int>(max_x, longest_line);\n  const auto window_width = 4 + width_;\n  const auto maxx = curses_out->window()->GetMaxX();\n  const auto maxy = curses_out->window()->GetMaxY();\n  const auto begin_x = (maxx - window_width) / 2;\n  const auto begin_y = (maxy - window_height) / 2;\n\n  CHECK(curses_out->window()->IsGUI()) << \"ListBox needs a GUI.\";\n\n  window_.reset(new CursesWindow(curses_out->window(), parent->color_scheme(),\n                                 window_height, window_width, begin_y, begin_x));\n  window_->SetColor(SchemeId::WINDOW_BOX);\n  window_->Box(0, 0);\n  window_->Bkgd(color_scheme_->GetAttributesForScheme(SchemeId::WINDOW_TEXT));\n  if (!title.empty()) {\n    window_->SetTitle(title);\n  }\n  help_items_ = StandardHelpItems();\n}\n\nListBox::ListBox(UIWindow* parent, const std::string& title,\n                 std::vector<ListBoxItem>& items)\n    : ListBox(parent, title,\n              static_cast<int>(floor(curses_out->window()->GetMaxX() * RATIO_LISTBOX_WIDTH)),\n              std::min<int>(\n                  std::max<int>(size_int(items), MINIMUM_LISTBOX_HEIGHT),\n                  static_cast<int>(floor(curses_out->window()->GetMaxY() * RATIO_LISTBOX_HEIGHT))),\n              items, parent->color_scheme()) {}\n\nvoid ListBox::DrawAllItems(std::vector<ListBoxItem>& items) {\n  for (auto y = 0; y < height_; y++) {\n    const auto current_item = window_top_ + y - window_top_min_;\n    auto line = current_item < size_int(items) ? items[current_item].text() : \"\";\n    if (size_int(line) > width_) {\n      line = line.substr(0, width_);\n    } else {\n      for (auto i = size_int(line); i < width_; i++) {\n        line.push_back(' ');\n      }\n    }\n    if (selected_ == current_item) {\n      window_->SetColor(SchemeId::DIALOG_SELECTION);\n    } else {\n      window_->SetColor(SchemeId::WINDOW_TEXT);\n    }\n    line.insert(line.begin(), 1, ' ');\n    line.push_back(' ');\n    window_->PutsXY(1, y + window_top_min_, line);\n  }\n}\n\nListBoxResult ListBox::RunDialog() {\n  if (selected_ < 0) {\n    selected_ = 0;\n  } else if (selected_ >= size_int(items_)) {\n    selected_ = size_int(items_);\n  }\n  // Move window top to furthest possible spot.\n  const auto temp_top = std::max<int>(window_top_min_, selected_);\n  // Pull it back to the top of the window.\n  window_top_ = std::min<int>(temp_top, size_int(items_) - height_ + window_top_min_);\n  selected_ = std::min<int>(selected_, size_int(items_) - 1);\n\n  return RunDialogInner();\n}\n\nListBoxResult ListBox::RunDialogInner() {\n  auto items{items_};\n  bool need_redraw{true};\n  std::string mask;\n  while (true) {\n    if (need_redraw) {\n      DrawAllItems(items);\n      window_->Move(selected_ - (window_top_ - window_top_min_) + window_top_min_, 1);\n      window_->Refresh();\n    }\n    need_redraw = true;\n    switch (auto ch = window_->GetChar(); ch) {\n    case KEY_HOME:\n      selected_ = 0;\n      window_top_ = window_top_min_;\n      break;\n    case KEY_END:\n      window_top_ = size_int(items) - height_ + window_top_min_;\n      selected_ = window_top_ - window_top_min_;\n      break;\n    case KEY_PREVIOUS: // What is this key?\n    case KEY_UP:\n      if (selected_ + window_top_min_ == window_top_) {\n        // At the top of the window, move the window up one.\n        if (window_top_ > window_top_min_) {\n          window_top_--;\n          selected_--;\n        } else {\n          // nothing happened.\n          need_redraw = false;\n        }\n      } else {\n        selected_--;\n      }\n      break;\n    case KEY_PPAGE: {\n      const auto old_window_top = window_top_;\n      const auto old_selected = selected_;\n      window_top_ -= height_;\n      selected_ -= height_;\n      window_top_ = std::max<int>(window_top_, window_top_min_);\n      selected_ = std::max<int>(selected_, 0);\n\n      if (old_window_top == window_top_ && old_selected == selected_) {\n        need_redraw = false;\n      }\n    } break;\n    case KEY_NEXT: // What is this key?\n    case KEY_DOWN: {\n      if (items.empty()) {\n        selected_ = 0;\n        break;\n      }\n      if (const auto window_bottom = window_top_ + height_ - window_top_min_ - 1;\n          selected_ < window_bottom && selected_ + 1 < size_int(items)) {\n        selected_++;\n      } else if (selected_ < window_bottom && selected_ + 1 >= size_int(items)) {\n        // Do nothing, we're at the bottom of what we can scroll to.\n        //selected_++;\n      } else if (window_top_ < size_int(items) - height_ + window_top_min_) {\n        selected_++;\n        window_top_++;\n      } else {\n        need_redraw = false;\n      }\n    } break;\n    case KEY_NPAGE: {\n      const auto old_window_top = window_top_;\n      const auto old_selected = selected_;\n\n      window_top_ += height_;\n      selected_ += height_;\n      window_top_ = std::min<int>(window_top_, size_int(items) - height_ + window_top_min_);\n      selected_ = std::min<int>(selected_, size_int(items) - 1);\n      window_top_ = std::max<int>(1, window_top_);\n\n      if (old_window_top == window_top_ && old_selected == selected_) {\n        need_redraw = false;\n      }\n    } break;\n    case KEY_ENTER:\n    case 13: {\n      if (items.empty()) {\n        // Can not select an item when the list is empty.\n        break;\n      }\n      auto& item = items.at(selected_);\n      const auto hotkey = item.hotkey();\n      const auto data = item.data();\n      const auto index = item.index();\n      if (selection_returns_hotkey_ && hotkey > 0) {\n        return ListBoxResult{ListBoxResultType::HOTKEY, index, hotkey, data};\n      }\n      return ListBoxResult{ListBoxResultType::SELECTION, index, hotkey, data};\n    }\n    case 27: // ESCAPE_KEY\n      return ListBoxResult{ListBoxResultType::NO_SELECTION, 0, 0, 0};\n    case '/': {  // Filter\n      selected_ = 0;\n      window_top_ = window_top_min_;\n      window_->PutsXY(1, window_top_, \"Enter Mask: \");\n      window_->GotoXY(13, window_top_);\n      editline(window_.get(), &mask, 20, EditLineMode::ALL, \"\");\n      StringTrim(&mask);\n      if (mask.empty()) {\n        items = items_;\n      } else {\n        StringUpperCase(&mask);\n        items.clear();\n        items.reserve(items_.size());\n        for (auto& item : items_) {\n          if (ToStringUpperCase(item.text()).find(mask) != std::string::npos) {\n            items.emplace_back(item);\n          }          \n        }\n        items.shrink_to_fit();\n      }\n    } break;\n    default:\n      ch = toupper(ch);\n      if (hotkeys_.find(static_cast<char>(ch & 0xff)) != std::string::npos) {\n        // Since a hotkey was pressed, update selected_ to match the index\n        // of the item containing the hotkey.\n        auto data = 0;\n        for (auto i = 0; i < stl::ssize(items); i++) {\n          auto& item = items.at(i);\n          if (item.hotkey() == ch) {\n            selected_ = item.index();\n            data = item.data();\n            break;\n          }\n        }\n        return ListBoxResult{ListBoxResultType::HOTKEY, selected_, ch, data};\n      }\n    }\n  }\n}\n\nvoid ListBox::DisplayFooter() {\n  // Show help bar.\n  curses_out->footer()->window()->Move(1, 0);\n  curses_out->footer()->window()->ClrtoEol(); \n  curses_out->footer()->ShowHelpItems(0, help_items_);\n}\n\n}\n"
  },
  {
    "path": "localui/listbox.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_LISTBOX_H\n#define INCLUDED_LOCALUI_LISTBOX_H\n\n#include \"localui/curses_io.h\"\n#include \"localui/curses_win.h\"\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::local::ui {\n\nclass ColorScheme;\n\nclass ListBoxItem {\npublic:\n  // Need non-explicit constructor to use in initialize_lists\n  ListBoxItem(std::string text, int hotkey = 0, int data = 0)\n      : text_(std::move(text)), hotkey_(hotkey), data_(data) {}\n  ~ListBoxItem() = default;\n\n  [[nodiscard]] const std::string& text() const noexcept { return text_; }\n  [[nodiscard]] int hotkey() const noexcept { return hotkey_; }\n  [[nodiscard]] int data() const noexcept { return data_; }\n  [[nodiscard]] int index() const noexcept { return index_; }\n  void index(int i) { index_ = i; }\n\n private:\n  std::string text_;\n  int hotkey_;\n  int data_;\n  int index_{-1};\n};\n\nenum class ListBoxResultType { NO_SELECTION, SELECTION, HOTKEY };\nstruct ListBoxResult {\n  ListBoxResultType type;\n  int selected;\n  int hotkey;\n  int data{0};\n};\n\n// Curses implementation of a list box.\nclass ListBox final {\npublic:\n  // Constructor/Destructor\n  ListBox(UIWindow* parent, const std::string& title, std::vector<ListBoxItem>& items);\n  ListBox(const ListBox& copy) = delete;\n  ~ListBox() = default;\n\n  // Execute the listbox returning the index of the selected item.\n  ListBoxResult Run() {\n    this->DisplayFooter();\n    const auto result = RunDialog();\n    curses_out->footer()->SetDefaultFooter();\n    parent_->RedrawWin();\n    return result;\n  }\n\n  // Returns the index of the selected item.\n  [[nodiscard]] int selected() const noexcept { return selected_; }\n  void set_selected(int s) noexcept { selected_ = s; }\n\n  // List of additionally allowed hotkeys.\n  void set_additional_hotkeys(const std::string& hotkeys) { hotkeys_.append(hotkeys); }\n  // If true, a selection will return as a hotkey if a hotkey is set on the item.\n  void selection_returns_hotkey(bool selection_returns_hotkey) noexcept {\n    selection_returns_hotkey_ = selection_returns_hotkey;\n  }\n  // Sets the extra help items.\n  void set_help_items(const std::vector<HelpItem>& items) { help_items_ = items; }\n\nprivate:\n  ListBox(UIWindow* parent, const std::string& title, int max_x, int max_y,\n          std::vector<ListBoxItem>& items, ColorScheme* scheme);\n  ListBoxResult RunDialogInner();\n  ListBoxResult RunDialog();\n  void DrawAllItems(std::vector<ListBoxItem>& items);\n  void DisplayFooter();\n\n  int selected_ = -1;\n  const std::string title_;\n  std::vector<ListBoxItem> items_;\n  std::vector<HelpItem> help_items_;\n  int window_top_ = 0;\n  int width_ = 4;\n  int height_ = 2;\n  std::unique_ptr<CursesWindow> window_;\n  ColorScheme* color_scheme_;\n  const int window_top_min_;\n  std::string hotkeys_;\n  bool selection_returns_hotkey_{false};\n  UIWindow* parent_{nullptr};\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/stdio_win.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"localui/stdio_win.h\"\n#include \"core/strings.h\"\n#include <iostream>\n#include <string>\n\nnamespace wwiv::local::ui {\n\n\nint StdioWindow::GetChar() const { return std::cin.get(); }\n\nvoid StdioWindow::Putch(uint32_t ch) { std::cout << ch; }\n\nvoid StdioWindow::Puts(const std::string& text) { std::cout << text; }\n\nvoid StdioWindow::PutsXY(int, int, const std::string& text) { Puts(text); }\n\nvoid StdioWindow::PutchW(wchar_t ch) {\n  std::wcout << ch;\n}\n\nvoid StdioWindow::PutsW(const std::wstring& text) {\n  std::wcout << text;\n}\n\nvoid StdioWindow::PutsXYW(int, int, const std::wstring& text) {\n  PutsW(text);\n}\n\n}\n"
  },
  {
    "path": "localui/stdio_win.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_STDIO_WIN_H\n#define INCLUDED_LOCALUI_STDIO_WIN_H\n\n#include \"localui/colors.h\"\n#include \"localui/ui_win.h\"\n#include <string>\n\nnamespace wwiv::local::ui {\n\n// Generic implementation of screen display routines for wwivconfig.\nclass StdioWindow : public UIWindow {\npublic:\n  // Constructor/Destructor\n  StdioWindow(UIWindow* parent, ColorScheme* color_scheme) : UIWindow(parent, color_scheme) {}\n  StdioWindow(const UIWindow&) = delete;\n  StdioWindow() = delete;\n  StdioWindow(UIWindow&&) = delete;\n\n  ~StdioWindow() override = default;\n\n  void GotoXY(int, int) override {}\n\n  // Still used by some curses code\n\n  [[nodiscard]] int GetChar() const override;\n  void Putch(uint32_t ch) override;\n  void Puts(const std::string& text) override;\n  void PutsXY(int x, int y, const std::string& text) override;\n\n  void PutchW(wchar_t ch) override;\n  void PutsW(const std::wstring& text) override;\n  void PutsXYW(int x, int y, const std::wstring& text) override;\n\n  /**\n   * Returns true if this is a GUI mode UI vs. stdio based UI.\n   */\n  [[nodiscard]] bool IsGUI() const override { return false; }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "localui/ui_win.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_UI_WIN_H\n#define INCLUDED_LOCALUI_UI_WIN_H\n\n#include \"localui/colors.h\"\n#include <string>\n\nnamespace wwiv::local::ui {\n\n// Generic implementation of screen display routines for wwivconfig.\nclass UIWindow {\npublic:\n  // Constructor/Destructor\n  UIWindow(UIWindow* parent, ColorScheme* color_scheme)\n      : parent_(parent), color_scheme_(color_scheme) {}\n  UIWindow(const UIWindow& copy) = delete;\n  virtual ~UIWindow() = default;\n\n  virtual void SetColor(SchemeId) {}\n  virtual void SetTitle(const std::string&) {}\n  virtual void Bkgd(uint32_t) {}\n  virtual int RedrawWin() { return 0; }\n  virtual int TouchWin() { return 0; }\n  virtual int Refresh() { return 0; }\n  virtual int Move(int, int) { return 0; }\n  [[nodiscard]] virtual int GetcurX() const { return 0; }\n  [[nodiscard]] virtual int GetcurY() const { return 0; }\n  virtual int Clear() { return 0; }\n  virtual int Erase() { return 0; }\n  virtual int AttrSet(uint32_t) { return 0; }\n  virtual int Keypad(bool) { return 0; }\n  [[nodiscard]] virtual int GetMaxX() const { return 0; }\n  [[nodiscard]] virtual int GetMaxY() const { return 0; }\n  virtual int ClrtoEol() { return 0; }\n  virtual int AttrGet(uint32_t*, short*) const { return 0; }\n  virtual int Box(uint32_t, uint32_t) { return 0; }\n\n  [[nodiscard]] virtual int GetChar() const = 0;\n  virtual void GotoXY(int x, int y) = 0;\n  virtual void Putch(uint32_t ch) = 0;\n  virtual void Puts(const std::string& text) = 0;\n  virtual void PutsXY(int x, int y, const std::string& text) = 0;\n\n  // Wide character versions\n  virtual void PutchW(wchar_t ch) = 0;\n  virtual void PutsW(const std::wstring& text) = 0;\n  virtual void PutsXYW(int x, int y, const std::wstring& text) = 0;\n\n  /**\n   * Returns true if this is a GUI mode UI vs. stdio based UI.\n   */\n  [[nodiscard]] virtual bool IsGUI() const { return false; }\n\n  [[nodiscard]] virtual UIWindow* parent() const { return parent_; }\n  [[nodiscard]] SchemeId current_scheme_id() const { return current_scheme_id_; }\n  [[nodiscard]] ColorScheme* color_scheme() const { return color_scheme_; }\n\nprotected:\n  void set_current_scheme_id(SchemeId id) { current_scheme_id_ = id; }\n\nprivate:\n  UIWindow* parent_;\n  ColorScheme* color_scheme_;\n  SchemeId current_scheme_id_{SchemeId::UNKNOWN};\n};\n\n}\n\n#endif"
  },
  {
    "path": "localui/wwiv_curses.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_LOCALUI_WWIV_CURSES_H\n#define INCLUDED_LOCALUI_WWIV_CURSES_H\n\n#ifdef MOUSE_MOVED\n#undef MOUSE_MOVED\n#endif  // MOUSE_MOVED\n\n#if defined(__sun)\n#include <ncurses/curses.h>\n#else\n#include <curses.h>\n#endif\n\n#endif\n"
  },
  {
    "path": "misc/astyle.options",
    "content": "--style=google \r\n-U \r\n-s2 \r\n-H \r\n--pad-oper \r\n--add-brackets \r\n--convert-tabs  \r\n--max-code-length=120 \r\n\r\n"
  },
  {
    "path": "misc/gen_zipcodes.py",
    "content": "#!/usr/bin/env python\n# vim: ts=4 sw=4 sts=4 et\n#\n# gen_zipfiles.py\n#\n# read csv input from unitedstateszipcodes.org and output data\n# files in a format useful by WWIV\n\n# row[0] = zip\n# row[2] = City\n# row[5] = State\n\nimport csv\nimport string\nimport ConfigParser\nfrom optparse import OptionParser\n\n\ndef parse_zip_data(infile):\n    if debug:\n        print 'parsing %s' % (infile)\n    zipcodes = {}\n    cities = {}\n    with open(infile, 'rb') as csvfile:\n        zipdb_reader = csv.reader(csvfile, delimiter=',', quotechar='\"')\n        for row in zipdb_reader:\n            for zcgroup in range(10):\n                zipgroup = str(zcgroup)\n                if row[0].startswith(zipgroup):\n                    zipcodes.setdefault(zipgroup,{})\n                    zipcodes[zipgroup][row[0]] = {'state':row[5],'city':row[2]}\n\n                    citygroup = row[2][0].lower()\n                    cities.setdefault(citygroup,{})\n                    citykey = '%s--%s' % (row[2].lower(),row[5].lower())\n                    cities[citygroup].setdefault(citykey,{ 'city':row[2],\n                                                            'state':row[5],\n                                                            'zipcodes':[]})\n                    cities[citygroup][citykey]['zipcodes'].append(row[0])\n                    break\n    return zipcodes,cities\n\n\ndef write_zip_data(zc):\n    if debug:\n        print 'zip code groups: ', sorted(zc)\n    for group in sorted(zc):\n        with open('zip%s.dat' % (group), 'w') as zip_output:\n            for zipcode in sorted(zc[group]):\n                zip_output.write( '%s\\t%s\\t%s\\r\\n' % (zipcode, \n                                      zc[group][zipcode]['state'], \n                                      zc[group][zipcode]['city']))\n\n\ndef write_city_data(cities):\n    if debug:\n        print 'city groups: ', sorted(cities)\n    for group in sorted(cities):\n        with open('city-%s.dat' % (group), 'w') as city_output:\n            for ckey in sorted(cities[group]):\n                for zipcode in sorted(cities[group][ckey]['zipcodes']):\n                    city_output.write('%s %s %s\\r\\n' % (cities[group][ckey]['city'], \n                                                   cities[group][ckey]['state'], \n                                                   zipcode))\n            \n\n\nif __name__ == '__main__':\n    parser = OptionParser()\n    parser.add_option(\"-d\", \"--debug\", action=\"store_true\", dest=\"debug\", help=\"Turn on Debug mode\")\n    parser.set_defaults(debug=False)\n    (options, args) = parser.parse_args()\n\n    debug = options.debug\n\n    if args:\n        if debug:\n            print 'args list: ', args\n        zipcodes,cities = parse_zip_data(args[0])\n        write_zip_data(zipcodes)\n        write_city_data(cities)\n    else:\n        parser.print_help()\n        parser.error(\"you need to define an input file to parse\")\n\n"
  },
  {
    "path": "misc/scripts/crc32.py",
    "content": "#!/usr/bin/env python\n\nimport sys\nimport binascii\n\ndef c(filename):\n\tprint(filename)\n\tbuf = open(filename,'rb').read()\n\tbuf = (binascii.crc32(buf) & 0xFFFFFFFF)\n\tprint(\"CRC: %08X\" % buf)\n\nc(sys.argv[1])"
  },
  {
    "path": "misc/scripts/dump_names.py",
    "content": "import struct\n\nwith open('names.lst', 'rb') as f:\n\twhile True:\n\t\tb = f.read(31 + 2)\n\t\tif not b:\n\t\t\tbreak\n\t\ts = struct.unpack('<31sh', b)\n\t\tname = s[0].decode('cp437').split('\\0')[0]\n\t\tprint(str(s[1]) + ':' + name);"
  },
  {
    "path": "misc/scripts/test_blocklist.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport socket\nimport threading\nimport sys\nimport time\n\n\nclass ConnectionStats:\n    \"\"\"Thread-safe statistics tracking\"\"\"\n    def __init__(self):\n        self.lock = threading.Lock()\n        self.successful = 0\n        self.failed = 0\n        self.connections = []\n    \n    def add_success(self, sock):\n        with self.lock:\n            self.successful += 1\n            self.connections.append(sock)\n    \n    def add_failure(self):\n        with self.lock:\n            self.failed += 1\n    \n    def get_stats(self):\n        with self.lock:\n            return {\n                'successful': self.successful,\n                'failed': self.failed,\n                'total_attempted': self.successful + self.failed,\n                'open_connections': len(self.connections)\n            }\n\n\ndef create_connection(host, port, mode, stats):\n    \"\"\"Create a single connection and leave it abandoned\"\"\"\n    try:\n        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        sock.settimeout(10)  # 10 second timeout for connection\n        \n        # Connect to the host\n        sock.connect((host, port))\n        \n        # For telnet/ssh, we just leave the connection open\n        # Don't close it - this simulates a bad/abandoned connection\n        stats.add_success(sock)\n        return sock\n    except Exception:\n        stats.add_failure()\n        return None\n\n\ndef worker_thread(thread_id, host, port, mode, count, stats):\n    \"\"\"Worker thread that creates 'count' connections\"\"\"\n    thread_connections = []\n    \n    for i in range(count):\n        sock = create_connection(host, port, mode, stats)\n        if sock:\n            thread_connections.append(sock)\n        \n        # Print progress every 10 connections\n        if (i + 1) % 10 == 0:\n            current_stats = stats.get_stats()\n            print(f\"Thread {thread_id}: Created {i + 1}/{count} connections \"\n                  f\"(Total: {current_stats['successful']} successful, \"\n                  f\"{current_stats['failed']} failed)\")\n    \n    # Keep connections alive by storing them\n    # The connections will remain open until the program exits\n    return thread_connections\n\n\ndef main():\n    parser = argparse.ArgumentParser(\n        description='Test blocklist by creating abandoned connections',\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n        epilog=\"\"\"\nExamples:\n  %(prog)s --mode telnet --host localhost --port 23 --count 100 --threads 5\n  %(prog)s -m ssh -H 192.168.1.1 -p 22 -c 50 -t 10\n        \"\"\"\n    )\n    \n    parser.add_argument(\n        '--mode', '-m',\n        required=True,\n        choices=['telnet', 'ssh'],\n        help='Connection mode: telnet or ssh'\n    )\n    \n    parser.add_argument(\n        '--host', '-H',\n        required=True,\n        help='Target hostname or IP address'\n    )\n    \n    parser.add_argument(\n        '--port', '-p',\n        type=int,\n        required=True,\n        help='Target port number'\n    )\n    \n    parser.add_argument(\n        '--count', '-c',\n        type=int,\n        required=True,\n        help='Number of connections per thread'\n    )\n    \n    parser.add_argument(\n        '--threads', '-t',\n        type=int,\n        required=True,\n        help='Number of concurrent threads'\n    )\n    \n    args = parser.parse_args()\n    \n    # Validate arguments\n    if args.count <= 0:\n        print(\"Error: count must be greater than 0\", file=sys.stderr)\n        sys.exit(1)\n    \n    if args.threads <= 0:\n        print(\"Error: threads must be greater than 0\", file=sys.stderr)\n        sys.exit(1)\n    \n    if args.port < 1 or args.port > 65535:\n        print(\"Error: port must be between 1 and 65535\", file=sys.stderr)\n        sys.exit(1)\n    \n    total_connections = args.count * args.threads\n    \n    print(\"Starting connection test:\")\n    print(f\"  Mode: {args.mode}\")\n    print(f\"  Host: {args.host}\")\n    print(f\"  Port: {args.port}\")\n    print(f\"  Connections per thread: {args.count}\")\n    print(f\"  Threads: {args.threads}\")\n    print(f\"  Total connections: {total_connections}\")\n    print()\n    \n    stats = ConnectionStats()\n    threads = []\n    start_time = time.time()\n    \n    # Create and start worker threads\n    for i in range(args.threads):\n        thread = threading.Thread(\n            target=worker_thread,\n            args=(i + 1, args.host, args.port, args.mode, args.count, stats)\n        )\n        thread.daemon = True\n        threads.append(thread)\n        thread.start()\n    \n    # Wait for all threads to complete\n    for thread in threads:\n        thread.join()\n    \n    elapsed_time = time.time() - start_time\n    \n    # Print final statistics\n    final_stats = stats.get_stats()\n    print()\n    print(\"=\" * 60)\n    print(\"Connection Test Summary\")\n    print(\"=\" * 60)\n    print(f\"Total connections attempted: {final_stats['total_attempted']}\")\n    print(f\"Successful connections: {final_stats['successful']}\")\n    print(f\"Failed connections: {final_stats['failed']}\")\n    print(f\"Connections left open: {final_stats['open_connections']}\")\n    print(f\"Time elapsed: {elapsed_time:.2f} seconds\")\n    print()\n    print(f\"All {final_stats['open_connections']} successful connections are\")\n    print(\"left open (abandoned) to simulate bad connections.\")\n    print(\"Press Ctrl+C to exit and close all connections.\")\n    \n    # Keep the program running to maintain connections\n    try:\n        while True:\n            time.sleep(1)\n    except KeyboardInterrupt:\n        print(\"\\nExiting... Closing all connections.\")\n        # Close all connections\n        for sock in stats.connections:\n            try:\n                sock.close()\n            except Exception:\n                pass\n        sys.exit(0)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "misc/testkeys.cpp",
    "content": "// To compile: g++ -lcurses -otestkeys testkeys.cpp\n#include <curses.h>\n#include <cstdio>\n#include <iostream>\n\nusing namespace std;\n\nint main(int argc, char* argv[]) {\n  initscr();\n  raw();\n  nonl();\n  keypad(stdscr, TRUE);\n  noecho();\n  mvprintw(1, 0, \"Type keys to see the keycode, control-c to exit.\");\n  while (true) {\n    int ch = getch();\n    if (ch == 3) {\n      break;\n    }\n    char s[81];\n    sprintf(s, \"[ch: %c] [value: %d]\\n\", ch, ch);\n    mvprintw(3, 0, \"You Entered: %s\", s);\n  }\n  endwin();\n  return 0;\n}\n\n"
  },
  {
    "path": "net_core/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(SOURCES \n net_cmdline.cpp\n netdat.cpp\n)\n\nadd_library(net_core ${SOURCES})\nset_max_warnings(net_core)\ntarget_link_libraries(net_core fmt::fmt-header-only)\n\n## Tests\nif (WWIV_BUILD_TESTS)\n\n  set(test_sources\n    netdat_test.cpp\n    net_cmdline_test.cpp\n    net_core_test_main.cpp\n  )\n\n  add_executable(net_core_tests ${test_sources})\n  set_max_warnings(net_core_tests)\n  target_link_libraries(net_core_tests net_core core_fixtures GTest::gtest sdk)\n\n  gtest_discover_tests(net_core_tests)\n\nendif()\n"
  },
  {
    "path": "net_core/net_cmdline.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"net_core/net_cmdline.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/net/packets.h\"\n#include <filesystem>\n#include <iomanip>\n#include <ostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net {\n\nvoid AddStandardNetworkArgs(wwiv::core::CommandLine& cmdline) {\n  cmdline.add_argument({\"net\", \"Network number to use (i.e. 0).\", \"0\"});\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"skip_net\", \"Skip invoking network1/network2/network3\"));\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"skip_delete\", \"Don't delete packets, move to save area\"));\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"quiet\", \"Be more quiet and don't log entry/exit\"));\n  cmdline.add_argument(\n      {\"semaphore_timeout\",\n      \"Timeout (in seconds) to wait for the network semaphore to become available.\",\n      \"30\"});\n  cmdline.add_argument(BooleanCommandLineArgument(\"help\", 'h', \"Displays Help\", false));\n}\n\nNetworkCommandLine::NetworkCommandLine(wwiv::core::CommandLine& cmdline, char net_cmd)\n    : cmdline_(cmdline), net_cmd_(net_cmd) {\n  cmdline.set_no_args_allowed(true);\n  cmdline.AddStandardArgs();\n  AddStandardNetworkArgs(cmdline);\n\n  if (!cmdline.Parse()) {\n    initialized_ = false;\n  }\n\n  if (!LoadNetIni(net_cmd, cmdline.bbsdir())) {\n    LOG(ERROR) << \"Error loading INI file for defaults\";\n  }\n\n  network_number_ = cmdline.arg(\"net\").as_int();\n  // TODO(rushfan): Need to look to see if WWIV_CONFIG_FILE is set 1st.\n  config_ = sdk::load_any_config(cmdline.bbsdir());\n  if (!config_) {\n    LOG(ERROR) << \"Unable to load config.json or config.dat\";\n    initialized_ = false;\n    return;\n  }\n  networks_.reset(new sdk::Networks(*config_));\n\n  if (!config_->IsInitialized()) {\n    LOG(ERROR) << \"Unable to load config.json.\";\n    initialized_ = false;\n  }\n  if (!networks_->IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    initialized_ = false;\n  }\n  const auto& nws = networks_->networks();\n\n  if (nws.size()==0) {\n    LOG(ERROR) << \"Networks need to be set up first.\";\n    initialized_ = false;\n    return;\n  }\n\n  if (network_number_ < 0 || network_number_ >= size_int(nws)) {\n    LOG(ERROR) << \"network number must be between 0 and \" << nws.size()-1 << \".\";\n    initialized_ = false;\n    return;\n  }\n  network_ = nws[network_number_];\n  network_name_ = ToStringLowerCase(network_.name);\n  LOG(STARTUP) << cmdline.program_name() << \" [\" << full_version() << \"]\"\n               << \" for network: \" << network_name_;\n  if (!quiet()) {\n    std::cerr << cmdline.program_name() << \" [\" << full_version() << \"]\"\n              << \" for network: \" << network_name_ << std::endl;\n  }\n}\n\n// Returns the name of the network command for the command character\n// e.g. returns \"network1\" for '1', etc.  If 0 or '\\0' then it returns\n// \"network\".\nstatic std::string network_cmd_name(char net_cmd) {\n  return (net_cmd == '\\0') ? \"network\" : StrCat(\"network\", net_cmd);\n}\n\nstd::filesystem::path NetworkCommandLine::semaphore_path() const noexcept {\n  return FilePath(network_.dir, StrCat(network_cmd_name(net_cmd_), \".bsy\"));\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool NetworkCommandLine::LoadNetIni(char net_cmd, const std::string& bbsdir) {\n  const auto net_tag = network_cmd_name(net_cmd);\n  const auto net_tag_net = StrCat(net_tag, \"-\", network_name());\n\n  const auto ini = std::make_unique<IniFile>(\n      FilePath(bbsdir, \"net.ini\"), net_tag_net, net_tag);\n  if (!ini || !ini->IsOpen()) {\n    // This is fine and can happen.\n    return true;\n  }\n\n  SetNewBooleanDefault(cmdline_, *ini, \"skip_net\");\n  SetNewBooleanDefault(cmdline_, *ini, \"crc\");\n  SetNewBooleanDefault(cmdline_, *ini, \"cram_md5\");\n  SetNewBooleanDefault(cmdline_, *ini, \"quiet\");\n  SetNewIntDefault(cmdline_, *ini, \"semaphore_timeout\");\n  SetNewIntDefault(cmdline_, *ini, \"v\", [](int v) { Logger::set_cmdline_verbosity(v); });\n  SetNewBooleanDefault(cmdline_, *ini, \"skip_delete\");\n  SetNewStringDefault(cmdline_, *ini, \"configdir\");\n  SetNewStringDefault(cmdline_, *ini, \"bindir\");\n  SetNewStringDefault(cmdline_, *ini, \"logdir\");\n\n  // Reparse the commandline args to update the variables.\n  cmdline_.Parse();\n  return true;\n}\n\nbool NetworkCommandLine::skip_delete() const noexcept { return cmdline_.barg(\"skip_delete\"); }\n\nbool NetworkCommandLine::skip_net() const noexcept { return cmdline_.barg(\"skip_net\"); }\n\nbool NetworkCommandLine::quiet() const noexcept { return cmdline_.barg(\"quiet\"); }\n\nstd::string NetworkCommandLine::GetHelp() const {\n  std::ostringstream ss;\n  ss << cmdline_.GetHelp() << std::endl\n     << \"   .#### \" << std::setw(22) << \" \"\n     << \"Network number (as defined in WWIVconfig)\" << std::endl;\n  return ss.str();\n}\n\nstd::chrono::duration<double> NetworkCommandLine::semaphore_timeout() const noexcept {\n  const auto semaphore_timeout = cmdline_.iarg(\"semaphore_timeout\");\n  return std::chrono::seconds(semaphore_timeout);\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "net_core/net_cmdline.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NET_CORE_NET_CMDLINE_H\n#define INCLUDED_NET_CORE_NET_CMDLINE_H\n\n#include \"core/command_line.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/networks.h\"\n#include <chrono>\n#include <filesystem>\n#include <memory>\n#include <string>\n\nnamespace wwiv::net {\n\nvoid AddStandardNetworkArgs(core::CommandLine& cmdline);\n\n/**\n * Wrapper class that augments CommandLine to specialize it for the network commands.\n */\nclass NetworkCommandLine {\npublic:\n  NetworkCommandLine(core::CommandLine& cmdline, char net_cmd);\n\n  [[nodiscard]] bool IsInitialized() const noexcept { return initialized_; }\n  [[nodiscard]] const sdk::Config& config() const noexcept { return *config_; }\n  [[nodiscard]] const sdk::Networks& networks() const noexcept { return *networks_; }\n  [[nodiscard]] std::string network_name() const noexcept { return network_name_; }\n  [[nodiscard]] int network_number() const noexcept { return network_number_; }\n  [[nodiscard]] const sdk::net::Network& network() const noexcept { return network_; }\n  [[nodiscard]] const core::CommandLine& cmdline() const noexcept { return cmdline_; }\n  [[nodiscard]] char net_cmd() const noexcept { return net_cmd_; }\n  [[nodiscard]] std::filesystem::path semaphore_path() const noexcept;\n  [[nodiscard]] std::string GetHelp() const;\n\n  /** Process net.ini and reparse command line applying new defaults */\n  [[nodiscard]] bool LoadNetIni(char net_cmd, const std::string& bbsdir);\n  [[nodiscard]] bool skip_delete() const noexcept;\n  [[nodiscard]] bool skip_net() const noexcept;\n  [[nodiscard]] bool quiet() const noexcept;\n\n  [[nodiscard]] std::chrono::duration<double> semaphore_timeout() const noexcept;\n\nprivate:\n  std::unique_ptr<sdk::Config> config_;\n  std::unique_ptr<sdk::Networks> networks_;\n  std::string network_name_;\n  int network_number_{0};\n  bool initialized_{true};\n  sdk::net::Network network_;\n  core::CommandLine& cmdline_;\n  char net_cmd_;\n};\n\n}\n\n#endif\n\n"
  },
  {
    "path": "net_core/net_cmdline_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n\nusing namespace wwiv::strings;\n\n\nclass NetworkCommandlineTest: public testing::Test {\npublic:\n  NetworkCommandlineTest() {}\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n};\n\nTEST_F(NetworkCommandlineTest, NOP) {\n}\n"
  },
  {
    "path": "net_core/net_core_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n}\n"
  },
  {
    "path": "net_core/netdat.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include <utility>\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"net_core/netdat.h\"\n#include \"core/numbers.h\"\n#include \"sdk/net/net.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::net {\n\n// static\nchar NetDat::NetDatMsgType(netdat_msgtype_t t) {\n  switch (t) {\n  case netdat_msgtype_t::banner:\n    return '\\xFE';\n  case netdat_msgtype_t::post:\n    return '+';\n  case netdat_msgtype_t::normal:\n    return '-';\n  case netdat_msgtype_t::error:\n    return '!';\n  }\n  LOG(FATAL) << \"Missing case for \" << static_cast<int>(t);\n  return 0;\n}\n\nNetDat::NetDat(std::filesystem::path gfiles, std::filesystem::path logs,\n               const Network& net, char net_cmd, Clock& clock)\n    : gfiles_(std::move(gfiles)), logs_(std::move(logs)), net_(net), net_cmd_(net_cmd),\n      clock_(clock) {\n  rollover();\n  file_ = open(\"ad\", 0);\n  if (file_->position() == 0) {\n    // Write Header.\n    const auto ndate = clock_.Now().to_string(\"%m/%d/%y\");\n    file_->WriteLine(\"\");\n    const auto header = fmt::format(\"={}\", ndate);\n    file_->WriteLine(header);\n  }\n}\n\nNetDat::~NetDat() {\n  try {\n    WriteStats();\n    WriteLines();\n    file_->Close();\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught Exception \" << e.what();\n  } catch (...) {\n    LOG(ERROR) << \"Caught Unknown Exception \";\n  }\n}\n\nvoid NetDat::WriteHeader() {\n  const auto now_hms = clock_.Now().to_string(\"%H:%M:%S\");\n  const auto header = fmt::format(\"\\xFE {} - net{} network{} [{}] ({}) [{}]\",\n    now_hms,\n    wwiv_network_compatible_version(),\n    net_cmd_,\n    full_version(),\n    wwiv_compile_datetime(), net_.name);\n  file_->WriteLine(\"\");\n  WriteLine(header);\n  VLOG(2) << header;\n}\n\nvoid NetDat::WriteLine(const std::string& s) {\n  const auto now_hms = clock_.Now().to_string(\"%H:%M:%S\");\n  const auto prefix = fmt::format(\"\\xFE {} - \", now_hms);\n\n  file_->WriteLine(strings::StrCat(prefix, s));\n}\n\nbool NetDat::WriteStats() {\n  const auto now_hms = clock_.Now().to_string(\"%H:%M:%S\");\n  if (stats_.empty()) {\n    return false;\n  }\n\n  WriteHeader();\n\n  auto total_files = 0;\n  auto total_bytes = 0;\n  for (const auto& [_, s] : stats_) {\n    total_files += s.files;\n    total_bytes += s.bytes;\n  }\n\n  const auto total = fmt::format(\" Total :  {} msgs, {}k\", total_files, bytes_to_k(total_bytes));\n  LOG(INFO) << total;\n  add_message(netdat_msgtype_t::normal, total);\n\n  if (stl::contains(stats_, 65535)) {\n    const auto& s = wwiv::stl::at(stats_, 65535);\n    const auto line = fmt::format(\"  Dead :  {} msgs, {}k\", s.files, bytes_to_k(s.bytes));\n    LOG(INFO) << line;\n    add_message(netdat_msgtype_t::normal, line);\n  }\n\n  for (const auto& [n, s] : stats_) {\n    if (n == 65535) {\n      // Skip dead.net\n      continue;\n    }\n    const auto line = fmt::format(\"{:<6} :  {} msgs, {}k\", strings::StrCat(\"@\", n), s.files,\n                                  bytes_to_k(s.bytes));\n    VLOG(2) << line;\n    add_message(netdat_msgtype_t::normal, line);\n  }\n  stats_.clear();\n  return true;\n}\n\nbool NetDat::WriteLines() {\n  if (lines_.empty()) {\n    return false;\n  }\n\n  WriteHeader();\n  for (const auto& l : lines_) {\n    VLOG(2) << l;\n    file_->WriteLine(l);\n  }\n  lines_.clear();\n\n  return true;\n}\n\nvoid NetDat::add_file_bytes(int node, int bytes) {\n  ++stats_[node].files;\n  stats_[node].bytes += bytes;\n}\n\nvoid NetDat::add_message(netdat_msgtype_t t, const std::string& msg) {\n  const auto start =\n      t == netdat_msgtype_t::banner ? \"\\xFE \" : strings::StrCat(\" \", NetDatMsgType(t), \" \");\n  lines_.emplace_back(strings::StrCat(start, msg));\n}\n\nbool NetDat::empty() const {\n  return stats_.empty();\n}\n\nstd::string NetDat::ToDebugString() const {\n  std::ostringstream ss;\n\n  if (!stats_.empty()) {\n    ss << \"Stats: \" << std::endl;\n    for (const auto& [k, v] : stats_) {\n      ss << \"k: \" << k << \":  files: \" << v.files << \"; bytes: \" << v.bytes << std::endl;\n    }\n  }\n\n  if (!lines_.empty()) {\n    ss << \"Lines: \" << std::endl;\n    for (const auto& l : lines_) {\n      ss << l << std::endl;\n    }\n  }\n\n  return ss.str();\n}\n\nstd::optional<std::string> NetDat::netdat_date_mmddyy(int num) const {\n  auto r = open(\"rd\", num);\n  if (!r || !r->IsOpen()) {\n    return std::nullopt;\n  }\n  auto lines = r->ReadFileIntoVector(2);\n  if (lines.size() != 2 || stl::at(lines, 1).size() < 9) {\n    return std::nullopt;\n  }\n  const auto& l = stl::at(lines, 1);\n  // We have a proper line.\n  return l.substr(1);\n}\n\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool NetDat::rollover() {\n  if (const auto ddate = netdat_date_mmddyy(0)) {\n    const auto ndate = clock_.Now().to_string(\"%m/%d/%y\");\n    if (ddate.value() == ndate) {\n      return false;\n    }\n  }\n\n  const auto n0 = FilePath(gfiles_, \"netdat0.log\");\n  const auto n1 = FilePath(gfiles_, \"netdat1.log\");\n  const auto n2 = FilePath(gfiles_, \"netdat2.log\");\n\n  if (const auto ropt = netdat_date_mmddyy(2)) {\n    const auto& r = ropt.value();\n    if (r.size() == 8) {\n      const auto m = r.substr(0, 2);\n      const auto d = r.substr(3, 2);\n      const auto y = r.substr(6, 2);\n      // This will work through 2100\n      auto log = fmt::format(\"netdat-20{}{}{}.log\", y, m, d);\n      const auto nz = FilePath(logs_, log);\n      File::Move(n2, nz);\n    }\n  }\n  File::Remove(n2);\n  File::Move(n1, n2);\n  File::Move(n0, n1);\n\n  return true;\n}\n\nstd::unique_ptr<TextFile> NetDat::open(const std::string& mode, int num) const {\n  return std::make_unique<TextFile>(FilePath(gfiles_, \n    fmt::format(\"netdat{}.log\", num)), mode);\n\n}\n}\n\n"
  },
  {
    "path": "net_core/netdat.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NET_CORE_NETDAT_H\n#define INCLUDED_NET_CORE_NETDAT_H\n\n#include \"core/clock.h\"\n#include \"core/textfile.h\"\n#include <memory>\n#include <map>\n#include <filesystem>\n#include <optional>\n#include <vector>\n\n\nnamespace  wwiv::sdk::net {\nclass Network;\n}\n\nnamespace wwiv::net {\n\n\nclass NetworkStat final {\npublic:\n  NetworkStat() = default;\n  ~NetworkStat() = default;\n  [[nodiscard]] int k() const;\n\n  int files{0};\n  int bytes{0};\n\n};\n\n/**\n * Implements writing to and rolling over the netdat?.log files for\n * WWIVnet message reporting.\n */\nclass NetDat final {\npublic:\n  enum class netdat_msgtype_t { banner, post, normal, error };\n  \n  static char NetDatMsgType(netdat_msgtype_t t);\n\n  NetDat(std::filesystem::path gfiles, std::filesystem::path logs,\n         const sdk::net::Network& net, char net_cmd, core::Clock& clock);\n\n  ~NetDat();\n\n  bool WriteStats();\n  bool WriteLines();\n  void add_file_bytes(int node, int bytes);\n  void add_message(netdat_msgtype_t t, const std::string& msg);\n  [[nodiscard]] bool empty() const;\n  [[nodiscard]] std::string ToDebugString() const;\n  // Gets the filedate as \"MM/DD/YY\" from netdat{num}\n  [[nodiscard]] std::optional<std::string> netdat_date_mmddyy(int num) const;\n\nprivate:\n  bool rollover();\n  void WriteHeader();\n  void WriteLine(const std::string& s);\n  [[nodiscard]] std::unique_ptr<TextFile> open(const std::string& mode, int num) const;\n\n  std::filesystem::path gfiles_;\n  std::filesystem::path logs_;\n  const sdk::net::Network& net_;\n  const char net_cmd_;\n  core::Clock& clock_;\n  std::unique_ptr<TextFile> file_;\n  std::map<int, NetworkStat> stats_;\n  std::vector<std::string> lines_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "net_core/netdat_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/fake_clock.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"net_core/netdat.h\"\n#include \"sdk/net/net.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\n\nclass NetDatTest: public testing::Test {\npublic:\n  NetDatTest() {\n    CHECK(helper_.Mkdir(\"gfiles\"));\n    CHECK(helper_.Mkdir(\"logs\"));\n    gfiles_ = helper_.Dir(\"gfiles\");\n    logs_ = helper_.Dir(\"logs\");\n\n    // default date\n    t_.tm_mon = 9; // 10\n    t_.tm_mday = 25;\n    t_.tm_year = 120;\n\n    // default network.\n    net.sysnum = 1;\n    net.type = network_type_t::wwivnet;\n    net.name = \"testnet\";\n  }\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n  std::filesystem::path gfiles_;\n  std::filesystem::path logs_;\n  tm t_{};\n  Network net{};\n};\n\nTEST_F(NetDatTest, Smoke) {\n  EXPECT_FALSE(File::Exists(FilePath(gfiles_, \"netdat0.log\")));\n\n  FakeClock clock(DateTime::from_tm(&t_));\n  wwiv::net::NetDat n(gfiles_, logs_, net, 'z', clock);\n\n  EXPECT_TRUE(File::Exists(FilePath(gfiles_, \"netdat0.log\")));\n}\n\nTEST_F(NetDatTest, Rollover) {\n  EXPECT_FALSE(File::Exists(FilePath(gfiles_, \"netdat0.log\")));\n\n  FakeClock clock(DateTime::from_tm(&t_));\n  {\n    wwiv::net::NetDat n(gfiles_, logs_, net, 'z', clock);\n  }\n\n  EXPECT_TRUE(File::Exists(FilePath(gfiles_, \"netdat0.log\")));\n  EXPECT_FALSE(File::Exists(FilePath(gfiles_, \"netdat1.log\")));\n\n  clock.tick(std::chrono::hours(24));\n  {\n    wwiv::net::NetDat n(gfiles_, logs_, net, 'z', clock);\n  }\n  EXPECT_TRUE(File::Exists(FilePath(gfiles_, \"netdat0.log\")));\n  EXPECT_TRUE(File::Exists(FilePath(gfiles_, \"netdat1.log\")));\n}\n"
  },
  {
    "path": "network/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN network.cpp)\n\nadd_executable(network ${NETWORK_MAIN})\ntarget_link_libraries(network binkp_lib net_core core sdk)\nset_max_warnings(network)\n\n"
  },
  {
    "path": "network/network.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n#include \"binkp/binkp_config.h\"\n#include \"binkp/ppp_config.h\"\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/config.h\"\n#include <cstdlib>\n#include <iomanip>\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\n\nstatic void ShowHelp(NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << \"   /N####\" << std::setw(22) << \" \"\n            << \"Network node number to dial.\" << std::endl\n            << std::endl;\n  exit(1);\n}\n\nstatic int LaunchOldNetworkingStack(const NetworkCommandLine& net_cmdline, const std::string& exe, int argc, char** argv) {\n  std::ostringstream os;\n  os << FilePath(net_cmdline.cmdline().bindir(), exe).string();\n  for (auto i = 1; i < argc; i++) {\n    const std::string s(argv[1]);\n    if (starts_with(s, \"/\")) {\n      os << \" \" << argv[i];\n    }\n  }\n  const auto command_line = os.str();\n  LOG(INFO) << \"Executing Command: '\" << command_line << \"'\";\n  return system(command_line.c_str());\n}\n\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n  try {\n    auto at_exit = finally(Logger::ExitLogger);\n    CommandLine cmdline(argc, argv, \"net\");\n    cmdline.AddStandardArgs();\n    AddStandardNetworkArgs(cmdline);\n    cmdline.add_argument({\"node\", 'n', \"Network node number to dial.\", \"0\"});\n    cmdline.add_argument(BooleanCommandLineArgument(\"allow_sendback\", 'A', \"Allow sendback (only used by legacy network0)\", true));\n    cmdline.add_argument({\"phone_number\", 'P', \"Network number to use (only used by legacy network0)\", \"\"});\n    cmdline.add_argument({\"speed\", 'S', \"Modem Speedto use (only used by legacy network0)\", \"\"});\n    cmdline.add_argument({\"callout_time\", 'T', \"Start time of the callout (only used by legacy network0)\", \"\"});\n\n    NetworkCommandLine net_cmdline(cmdline, '0');\n    if (!net_cmdline.IsInitialized() || cmdline.help_requested()) {\n      ShowHelp(net_cmdline);\n      return 1;\n    }\n\n    auto network_name = net_cmdline.network_name();\n\n    auto node = cmdline.sarg(\"node\");\n    if (!contains(node, ':')) {\n      int nodeint = to_number<int>(node);\n      if (nodeint == 0 || nodeint > 32767) {\n        LOG(ERROR) << \"Invalid node number: '\" << node << \"' specified.\";\n        ShowHelp(net_cmdline);\n        return 1;\n      }\n      if (nodeint == INTERNET_EMAIL_FAKE_OUTBOUND_NODE) {\n        // 32767 is the PPP project address for \"send everything\". Some people use this\n        // \"magic\" node number.\n        LOG(INFO) << \"USE PPP Project to send to: Internet Email (@32767)\";\n        return LaunchOldNetworkingStack(net_cmdline, \"networkp\", argc, argv);\n      }\n    }\n\n    BinkConfig bink_config(network_name, net_cmdline.config(), net_cmdline.networks());\n    const binkp_session_config_t* node_config = bink_config.binkp_session_config_for(node);\n    if (node_config != nullptr) {\n      // We have a node configuration for this one, or it is a FTN\n      // network, so we will use networkb.\n      LOG(INFO) << \"USE networkb: \" << node_config->host << \":\" << node_config->port;\n      std::ostringstream ss;\n      ss << FilePath(net_cmdline.cmdline().bindir(), \"networkb\").string();\n      ss << \" --send --net=\" << net_cmdline.network_number() << \" --node=\" << node;\n      if (cmdline.barg(\"skip_net\")) {\n        ss << \" --skip_net\";\n      }\n      int verbose = cmdline.verbose();\n      if (verbose > 0) {\n        ss << \" --v=\" << verbose;\n      }\n      const auto command_line = ss.str();\n      LOG(INFO) << \"Executing Command: '\" << command_line << \"'\";\n      return system(command_line.c_str());\n    }\n\n    auto nodeint = to_number<int>(node);\n    if (nodeint == 0) {\n      LOG(ERROR) << \"Not sure how to call out to: \" << node;\n      return 1;\n    }\n    PPPConfig ppp_config(network_name, net_cmdline.config(), net_cmdline.networks());\n    const PPPNodeConfig* ppp_node_config = ppp_config.ppp_node_config_for(nodeint);\n    if (ppp_node_config != nullptr) {\n      LOG(INFO) << \"USE PPP Project to send to: \" << ppp_node_config->email_address;\n      return LaunchOldNetworkingStack(net_cmdline, \"networkp\", argc, argv);\n    }\n\n    // Use legacy networking.\n    return LaunchOldNetworkingStack(net_cmdline, \"network0\", argc, argv);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network]: \" << e.what();\n  }\n  return 1;\n}\n"
  },
  {
    "path": "network1/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN network1.cpp)\n\nadd_executable(network1 ${NETWORK_MAIN})\nset_max_warnings(network1)\ntarget_link_libraries(network1 binkp_lib net_core core sdk)\n\n"
  },
  {
    "path": "network1/network1.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 Network1\n#include \"network1.h\"\n\n#include \"core/clock.h\"\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/packets.h\"\n\n#include <cstdlib>\n#include <iostream>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nint NetworkStat::k() const {\n  return bytes == 0 ? 0 : (bytes + 1023) / 1024;\n}\n\nNetwork1::Network1(const NetworkCommandLine& cmdline, const BbsListNet& bbslist,\n                   wwiv::core::Clock& clock)\n    : net_cmdline_(cmdline), bbslist_(bbslist), clock_(clock), net_(net_cmdline_.network()),\n      netdat_(net_cmdline_.config().gfilesdir(),\n        net_cmdline_.config().logdir(), \n        net_, net_cmdline_.net_cmd(), clock_) {}\n\n\n/**\n * Determines the filename for each of the nodes in list to forward to\n * and writes packets (calling write_wwivnet_packet) to each of them.\n */\nbool Network1::write_multiple_wwivnet_packets(const net_header_rec& orig_header,\n                                              const std::vector<uint16_t>& list,\n                                              const std::string& text) {\n  std::map<uint16_t, std::set<uint16_t>> forsys_to_all;\n  for (const auto& node : list) {\n    auto forsys = get_forsys(bbslist_, node);\n    forsys_to_all[forsys].insert(node);\n  }\n\n  if (orig_header.tosys != 0) {\n    // TODO(rushfan): Does this happen, and if so should we also forward \n    // this packet to nh.tosys?  Maybe?\n    LOG(ERROR) << \"write_multiple_wwivnet_packets called to a tosys != 0; got; \" << orig_header.tosys;\n  }\n\n  auto result = true;\n  for (const auto& fa : forsys_to_all) {\n    net_header_rec nh{ orig_header };\n    std::vector<uint16_t> nplist(fa.second.begin(), fa.second.end());\n    nh.list_len = static_cast<uint16_t>(nplist.size());\n    NetPacket np(nh, nplist , text);\n    if (np.list.size() == 1) {\n      // If we only have 1, move it out of list into tosys.\n      np.nh.tosys = *std::begin(np.list);\n      np.nh.list_len = 0;\n      np.list.clear();\n    }\n    const auto forsys = fa.first;\n    netdat_.add_file_bytes(forsys, np.length());\n    if (!write_wwivnet_packet(NetPacket::wwivnet_packet_path(net_, forsys), np)) {\n      result = false;\n    }\n  }\n  return result;\n}\n\n// returns true on success, false on error.\nbool Network1::handle_packet(NetPacket& p) {\n\n  if (p.nh.main_type == 65535) {\n    // Deleted message. return true since ignoring it *is* handling it appropriately.\n    LOG(INFO) << \"Skipping deleted message of type: \" << main_type_name(p.nh.main_type);\n    return true;\n  }\n\n  // Update the routing information on this packet since\n  // we're unpacking it.\n  p.UpdateRouting(net_);\n\n  if (p.nh.tosys == net_.sysnum) {\n    // Local Packet.\n    netdat_.add_file_bytes(net_.sysnum, p.length());\n    return write_wwivnet_packet(FilePath(net_.dir, LOCAL_NET), p);\n  }\n  if (p.list.empty()) {\n    // Network packet, single destination\n    const auto forsys = get_forsys(bbslist_, p.nh.tosys);\n    netdat_.add_file_bytes(forsys, p.length());\n    return write_wwivnet_packet(NetPacket::wwivnet_packet_path(net_, forsys), p);\n  }\n  // Network packet, multiple destinations.\n  return write_multiple_wwivnet_packets(p.nh, p.list, p.text());\n}\n\nbool Network1::handle_file(const std::string& name) {\n  File f(FilePath(net_.dir, name));\n  if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n    LOG(ERROR) << \"Unable to open file: \" << net_.dir << name;\n    return false;\n  }\n\n  for (;;) {\n    auto [packet, response] = read_packet(f, false);\n    if (response == ReadNetPacketResponse::END_OF_FILE) {\n      return true;\n    }\n    if (response == ReadNetPacketResponse::ERROR) {\n      return false;\n    }\n    if (!handle_packet(packet)) {\n      LOG(ERROR) << \"error handing packet: type: \" << packet.nh.main_type;\n    }\n  }\n}\n\nbool Network1::Run() {\n  try {\n    LOG(INFO) << \" * Analyzing \" << net_.name << \" pending files...\";\n    FindFiles ff(FilePath(net_.dir, \"p*.net\"), FindFiles::FindFilesType::files);\n    for (const auto& f : ff) {\n      VLOG(1) << \"Processing: \" << net_.dir.string() << f.name;\n      if (handle_file(f.name)) {\n        VLOG(1) << \"Deleting: \" << net_.dir.string() << f.name;\n        if (net_cmdline_.skip_delete()) {\n          backup_file(FilePath(net_.dir, f.name));\n        }\n        File::Remove(FilePath(net_.dir, f.name));\n      }\n    }\n\n    // Update contact record.\n    LOG(INFO) << \" * Updating \" << net_.name << \" contact.net...\";\n    Contact contact(net_, true);\n    auto& m = contact.mutable_contacts();\n    for (auto it = std::begin(m); it != std::end(m); ) {\n      const auto sn = it->second.systemnumber();\n      if (!bbslist_.node_config_for(sn)) {\n        // Try to remove a entry that does not exist..\n        LOG(INFO) << \"Removing contact.net entry for node that does not exist: \" << sn;\n        it = m.erase(it);\n        continue;\n      }\n      auto* c = contact.contact_rec_for(sn);\n      // Should *never* happen since we checked above.\n      DCHECK(c);\n      VLOG(1) << \"Updating contact entry for node: @\" << sn;\n      const auto outbound_fn = FilePath(net_.dir, StrCat(\"s\", it->second.systemnumber(), \".net\"));\n      if (File::Exists(outbound_fn)) {\n        File of(outbound_fn);\n        c->set_bytes_waiting(static_cast<int32_t>(of.length()));\n      } else {\n        c->set_bytes_waiting(0);\n      }\n      ++it;\n    }\n\n    if (netdat_.empty()) {\n      // No need to log stats, just exit here.\n      return true;\n    }\n\n    LOG(INFO) << netdat_.ToDebugString();\n    netdat_.WriteStats();\n    return true;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network1]: \" << e.what();\n  }\n  return false;\n}\n\nint main(int argc, char** argv) { \n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  const NetworkCommandLine net_cmdline(cmdline, '1');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n\n\n  VLOG(3) << \"Reading bbsdata.net..\";\n  const auto& net = net_cmdline.network();\n  const auto b = BbsListNet::ReadBbsDataNet(net.dir);\n  if (b.empty()) {\n    LOG(ERROR) << \"ERROR: Unable to read bbsdata.net.\";\n    LOG(ERROR) << \"       You likely need to run network3?\";\n    return 1;\n  }\n\n  try {\n    auto semaphore = SemaphoreFile::try_acquire(net_cmdline.semaphore_path(),\n                                                net_cmdline.semaphore_timeout());\n    SystemClock clock;\n    Network1 n1(net_cmdline, b, clock);\n    return n1.Run() ? 0 : 2;\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n}"
  },
  {
    "path": "network1/network1.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NET_NETWORK1_H\n#define INCLUDED_NET_NETWORK1_H\n\n#include \"core/clock.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"net_core/netdat.h\"\n#include \"sdk/net/packets.h\"\n#include <string>\n\n\nnamespace wwiv::sdk {\nclass BbsListNet;\n}\n\n\nclass Network1 final {\npublic:\n  Network1(const wwiv::net::NetworkCommandLine& cmdline, \n           const wwiv::sdk::BbsListNet& bbslist,\n           wwiv::core::Clock& clock);\n  ~Network1() = default;\n\n  bool Run();\n\nprivate:\n  bool write_multiple_wwivnet_packets(const net_header_rec& nh, const std::vector<uint16_t>& list,\n                                      const std::string& text);\n  bool handle_packet(wwiv::sdk::net::NetPacket& p);\n  bool handle_file(const std::string& name);\n  const wwiv::net::NetworkCommandLine& net_cmdline_;\n  const wwiv::sdk::BbsListNet& bbslist_;\n  wwiv::core::Clock& clock_;\n  const wwiv::sdk::net::Network& net_;\n  wwiv::net::NetDat netdat_;\n};\n\n#endif // INCLUDED_NET_NETWORK1_H"
  },
  {
    "path": "network2/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN \n\tnetwork2.cpp\n\tcontext.cpp\n\temail.cpp\n\tpost.cpp\n\tsubs.cpp\n\t)\n\nadd_executable(network2 ${NETWORK_MAIN})\nset_max_warnings(network2)\ntarget_link_libraries(network2 binkp_lib net_core core sdk)\n\n"
  },
  {
    "path": "network2/context.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"network2/context.h\"\n\n\nnamespace wwiv::net::network2 {\n\nusing namespace wwiv::sdk::net;\n\nContext::Context(const sdk::Config& c, const Network& n, sdk::UserManager& u,\n                 const std::vector<Network>& ns, NetDat& netdat)\n  : config(c), net(n), user_manager(u), subs(c.datadir(), ns), networks_(ns), netdat_(netdat), ssm(c, u) {\n  subs_initialized = subs.Load();\n}\n\nvoid Context::set_api(int type, std::unique_ptr<sdk::msgapi::MessageApi>&& a) {\n  msgapis_[type] = std::move(a);\n}\n\nvoid Context::set_email_api(std::unique_ptr<sdk::msgapi::WWIVMessageApi>&& a) {\n  email_api_ = std::move(a);\n}\n\nsdk::msgapi::MessageApi& Context::api(int type) {\n  if (type == 0) { type = 2; }\n  return *stl::at(msgapis_, type);\n}\n\nsdk::msgapi::WWIVMessageApi& Context::email_api() const { return *email_api_; }\n\n\n}\n"
  },
  {
    "path": "network2/context.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORK2_CONTEXT_H\n#define INCLUDED_NETWORK2_CONTEXT_H\n\n#include \"net_core/netdat.h\"\n#include \"sdk/config.h\"\n#include \"sdk/ssm.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/usermanager.h\"\n#include <map>\n#include <vector>\n\nnamespace wwiv::net::network2 {\n \n/** \n * List of exes to use to invoke external programs when \n * main_type_new_external is encountered.\n */\nstruct external_programs_t {\n  std::string exe;\n  int low{-1};\n  int high{-1};\n};\n\n/** \n * Context for data needed by network processing.\n */\nclass Context {\n\npublic:\n  Context(const sdk::Config& c, const sdk::net::Network& n, sdk::UserManager& u,\n          const std::vector<sdk::net::Network>& ns, NetDat& netdat);\n\n  void set_api(int type, std::unique_ptr<sdk::msgapi::MessageApi>&& a);\n\n  void set_email_api(std::unique_ptr<sdk::msgapi::WWIVMessageApi>&& a);\n\n  [[nodiscard]] sdk::msgapi::MessageApi& api(int type);\n  [[nodiscard]] sdk::msgapi::WWIVMessageApi& email_api() const;\n\n  [[nodiscard]] const std::vector<sdk::net::Network>& networks() const noexcept { return networks_; }\n  [[nodiscard]] NetDat& netdat() const { return netdat_; }\n\n  const sdk::Config& config;\n  const sdk::net::Network& net;\n  sdk::UserManager& user_manager;\n  std::map<int, std::unique_ptr<sdk::msgapi::MessageApi>> msgapis_;\n  // This is the type-2 entry in msgapis_. It's owned there.\n  std::unique_ptr<sdk::msgapi::WWIVMessageApi> email_api_;\n  // network number like network 0 (.0) is the 1st network in WWIVconfig.\n  int network_number{0};\n  sdk::Subs subs;\n  const std::vector<sdk::net::Network> networks_;\n  NetDat& netdat_;\n  bool verbose{false};\n  bool subs_initialized{false};\n  sdk::SSM ssm;\n  std::unique_ptr<std::vector<external_programs_t>> external_programs;\n  std::set<int> external_programs_saved;\n};\n\n} // namespace wwiv::net::network2\n\n#endif // INCLUDED_NETWORK2_CONTEXT_H\n"
  },
  {
    "path": "network2/email.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"network2/email.h\"\n\n// WWIV5 Network2\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"network2/context.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/msgapi/email_wwiv.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/packets.h\"\n\n#include <memory>\n#include <set>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net::network2 {\n\n// Gets the user number or 0 if it is not found.\nstatic int GetUserNumber(const std::string& name, UserManager& um) {\n  const auto max = um.num_user_records();\n  auto realname_pos = 0;\n  for (auto i = 0; i <= max; i++) {\n    auto u = um.readuser(i);\n    if (!u) {\n      continue;\n    }\n    if (iequals(name, u->name())) {\n      return i;\n    }\n    if (const auto matches_realname = iequals(name, u->real_name());\n        matches_realname && realname_pos == 0) {\n      realname_pos = i;\n    } else if (matches_realname && realname_pos != 0) {\n      LOG(WARNING) << \"Duplicate real names\";\n    }\n  }\n  // If we didn't find a handle, use the first known position\n  // of the real name.  These are not guaranteed to be unique\n  // like the handles are.\n  return realname_pos;\n}\n\nbool handle_email_byname(Context& context, NetPacket& p) {\n  auto iter = std::begin(p.text());\n  const auto to_name = get_message_field(p.text(), iter, {'\\0'}, 80);\n  VLOG(1) << \"Processing email by name to: '\" << to_name << \"'\";\n\n  // Rest of the message is the text.\n  const auto text = std::string(iter, std::end(p.text()));\n\n  const auto user_number = GetUserNumber(to_name, context.user_manager);\n  if (user_number == 0) {\n    // Not found.\n    LOG(ERROR) << \"    ! ERROR Received email to user: '\" << to_name << \"' who is not found on this system; writing to dead.net\";\n    // Write it to DEAD_NET\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  \n  p.set_text(text);\n  return handle_email(context, static_cast<uint16_t>(user_number), p);\n}\n\n\nbool handle_email(Context& context,\n  uint16_t to_user, NetPacket& p) {\n  LOG(INFO) << \"==============================================================\";\n  auto at_exit = finally(\n      [] {\n    LOG(INFO) << \"==============================================================\";\n  });\n  LOG(INFO) << \"Processing email to user #\" << to_user;\n\n  {\n    User user;\n    if (!context.user_manager.readuser(&user, to_user)) {\n      // Unable to read user.\n      LOG(INFO) << \"ERROR: Unable to read user #\" << to_user << \". Discarding message.\";\n      return false;\n    }\n\n    if (user.deleted()) {\n      LOG(INFO) << \"User #\" << to_user << \" is deleted. Discarding message.\";\n      return false;\n    }\n  }\n\n  EmailData d{};\n  d.daten = p.nh.daten;\n  d.from_network_number = context.network_number;\n  d.from_system = p.nh.fromsys;\n  d.from_user = p.nh.fromuser;\n  // All local email should have the system number set to 0.\n  d.system_number = 0;\n  d.user_number = to_user;\n\n  auto iter = std::begin(p.text());\n  d.title = get_message_field(p.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n  // Rest of the message is the text of the form:\n  // SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n  d.text = std::string(iter, std::end(p.text()));\n  LOG(INFO) << \"  Title: '\" << d.title << \"'\";\n\n  auto email = context.email_api().OpenEmail();\n  if (!email) {\n    LOG(ERROR) << \"    ! ERROR creating email class; writing to dead.net\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  if (const auto added = email->AddMessage(d); !added) {\n    LOG(ERROR) << \"    ! ERROR adding email message; writing to dead.net\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  User user;\n  context.user_manager.readuser(&user, d.user_number);\n  auto num_waiting = user.email_waiting();\n  num_waiting++;\n  user.email_waiting(num_waiting);\n  context.user_manager.writeuser(&user, d.user_number);\n  LOG(INFO) << \"    + Received Email  '\" << d.title << \"'\";\n  return true;\n}\n\n}\n"
  },
  {
    "path": "network2/email.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORK2_EMAIL_H__\n#define __INCLUDED_NETWORK2_EMAIL_H__\n\n#include \"sdk/net/packets.h\"\n#include \"network2/context.h\"\n\nnamespace wwiv {\nnamespace net {\nnamespace network2 {\n\n // Expects the text in packet is of the form:\n // TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\nbool handle_email(Context& context, uint16_t to_user, wwiv::sdk::net::NetPacket& packet);\n\n// Expects the text in packet is of the form:\n// TO<nul>TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\nbool handle_email_byname(Context& context, wwiv::sdk::net::NetPacket& packet);\n\n}  // namespace network2\n}  // namespace net\n}  // namespace wwiv\n\n#endif  // __INCLUDED_NETWORK2_EMAIL_H__\n"
  },
  {
    "path": "network2/network2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 Network2\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"network2/context.h\"\n#include \"network2/email.h\"\n#include \"network2/post.h\"\n#include \"network2/subs.h\"\n#include \"net_core/netdat.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/ssm.h\"\n#include \"sdk/status.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/msgapi/msgapi.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/packets.h\"\n\n#include <cstdlib>\n#include <iostream>\n#include <memory>\n#include <set>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::net::network2;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nstatic bool email_changed = false;\nstatic bool posts_changed = false;\n\nstatic void update_filechange_status_dat(const std::filesystem::path& datadir, bool email, bool posts) {\n  StatusMgr sm(datadir);\n  sm.Run([=](Status& s)\n  {\n    if (email) {\n      s.increment_filechanged(Status::file_change_email);\n    }\n    if (posts) {\n      s.increment_filechanged(Status::file_change_posts);\n    }\n  });\n}\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nstatic bool handle_ssm(Context& context, NetPacket& p) {\n  auto at_exit =\n      finally(\n      [] { VLOG(1) << \"==============================================================\"; });\n  VLOG(1) << \"==============================================================\";\n  if (!context.ssm.send_local(p.nh.touser, p.text())) {\n    LOG(ERROR) << \"    ! ERROR writing SSM: '\" << p.nh.touser << \"; text: '\" << p.text()\n               << \"'; writing to dead.net\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n\n  LOG(INFO) << \"    + SSM  to: \" << p.nh.touser << \"; text: '\" << p.text() << \"'\";\n  return true;\n}\n\nstatic bool write_net_received_file(Context& context, const Network& net, NetPacket& p, NetInfoFileInfo info) {\n  if (!info.valid) {\n    LOG(ERROR) << \"    ! ERROR write_net_received_file: NetInfoFileInfo is not valid; writing to dead.net\";\n    return write_deadnet_packet(net.dir, p);\n  }\n\n  if (info.filename.empty()) {\n    LOG(ERROR) << \"    ! ERROR write_net_received_file: info.filename.empty(); writing to dead.net\";\n    return write_deadnet_packet(net.dir, p);\n  }\n  // we know the name.\n  const auto fn = net.dir / info.filename;\n  if (!info.overwrite && File::Exists(fn)) {\n    const auto err = fmt::format(\"Received file '{}' already exists, and packet not set to overwrite.\", fn.string());\n    LOG(ERROR) << \"    ! ERROR \" << err << \"; writing to dead.net\";\n    context.ssm.send_local(1, err);\n    return write_deadnet_packet(net.dir, p);\n  }\n  context.ssm.send_local(1, StrCat(\"Received \", info.filename));\n  File file(fn);\n  if (!file.Open(File::modeWriteOnly | File::modeBinary | File::modeCreateFile | File::modeTruncate,\n                 File::shareDenyReadWrite)) {\n    // We couldn't create or open the file.\n    LOG(ERROR) << \"    ! ERROR Unable to create or open file: '\" << info.filename\n               << \"'; writing to dead.net\";\n    return write_deadnet_packet(net.dir, p);\n  }\n  file.Write(info.data);\n  LOG(INFO) << \"  + Got \" << info.filename;\n  return true;\n}\n\nstatic bool handle_net_info_file(Context& context, const Network& net, NetPacket& p) {\n  const auto info = GetNetInfoFileInfo(p);\n  return write_net_received_file(context, net, p, info);\n}\n\nstatic bool load_external_programs(Context& context, const std::filesystem::path& path) {\n  // go ahead and create the vector so we don't try this again\n  context.external_programs = std::make_unique<std::vector<external_programs_t>>();\n\n  TextFile f(path, \"rt\");\n  if (!f.IsOpen()) {\n    return false;\n  }\n\n  auto lines = f.ReadFileIntoVector();\n  if (lines.empty()) {\n    return false;\n  }\n  \n  // Create the external program list.\n  for (const auto& l : lines) {\n    auto parts = SplitString(l, \" \\t\");\n    if (parts.size() != 3) {\n      VLOG(1) << \"Skipping malformed line in eprogs.net: '\" << l << \"'\";\n      continue;\n    }\n\n    external_programs_t e{};\n    e.exe = wwiv::stl::at(parts, 0);\n    e.low = to_number<int>(wwiv::stl::at(parts, 1));\n    e.high = to_number<int>(wwiv::stl::at(parts, 2));\n    context.external_programs->emplace_back(e);\n  }\n  return true;\n}\n\n// cribbed from networkc\nstatic int System(const std::string& cmd) {\n  VLOG(1) << \"Command: \" << cmd;\n  return system(cmd.c_str());\n}\n\nstatic bool handle_new_external(Context& context, NetPacket& p) {\n  if (!context.external_programs) {\n    load_external_programs(context, FilePath(context.net.dir, EPROGS_NET));\n  }\n  if (!context.external_programs) {\n    LOG(ERROR) << \"    ! ERROR Unable to load eprogs.net; writing to dead.net\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  \n  for (const auto& e : *context.external_programs) {\n    if (e.low <= p.nh.minor_type && p.nh.minor_type <= e.high) {\n      p.nh.list_len = 0;\n      p.list.clear();\n      const auto tempfn = fmt::format(\"temp{}.net\", p.nh.minor_type);\n      if (write_wwivnet_packet(FilePath(context.net.dir, tempfn), p)) {\n\tconst auto exe = fmt::format(\"{} {}{} .{}\", e.exe, context.net.dir.string(),  tempfn, context.net.network_number());\n        System(exe);\n      }\n    }\n  }\n  return true;\n}\n\nstatic bool handle_sub_list(Context& context, NetPacket& p) {\n  // Handle legacy type 9 main_type_sub_list (SUBS.LST)\n  NetInfoFileInfo info{};\n  info.filename = SUBS_LST;\n  info.data = p.text();\n  info.valid = true;\n  info.overwrite = true;\n  return write_net_received_file(context, context.net, p, info);\n}\n\nstatic bool handle_packet(Context& context, NetPacket& p) {\n  LOG(INFO) << \"Processing message with type: \" << main_type_name(p.nh.main_type) << \"/\"\n            << p.nh.minor_type;\n\n  switch (p.nh.main_type) {\n    /*\n    These messages contain various network information\n    files, encoded with method 1 (requiring DE1.EXE).\n    Once DE1.EXE has verified the source and returned to\n    the analyzer, the file is created in the network's\n    DATA directory with the filename determined by the\n    minor_type (except minor_type 1).\n    */\n  case main_type_net_info: {\n    if (p.nh.minor_type == 0) {\n      // Feedback to sysop from the NC.\n      // This is sent to the #1 account as source verified email.\n      email_changed = true;\n      return handle_email(context, 1, p);\n    }\n    return handle_net_info_file(context, context.net, p);\n  }\n  case main_type_email:\n    // This is regular email sent to a user number at this system.\n    // Email has no minor type, so minor_type will always be zero.\n    email_changed = true;\n    return handle_email(context, p.nh.touser, p);\n  case main_type_email_name:\n    // The other email type.  The \"touser\" field is zero, and the name is found at\n    // the beginning of the message text, followed by a NUL character.\n    // Minor_type will always be zero.\n    email_changed = true;\n    return handle_email_byname(context, p);\n  case main_type_new_post: {\n    posts_changed = true;\n    if (!handle_inbound_post(context, p)) {\n      LOG(ERROR) << \"Error on handle_inbound_post\";\n      return false;\n    }\n    return send_post_to_subscribers(context, p, {p.nh.fromsys});\n  }\n  case main_type_ssm: {\n    return handle_ssm(context, p);\n  }\n  // Subs add/drop support.\n  case main_type_sub_add_req:\n    return handle_sub_add_req(context, p);\n  case main_type_sub_drop_req:\n    return handle_sub_drop_req(context, p);\n  case main_type_sub_add_resp:\n    return handle_sub_add_drop_resp(context, p, \"add\");\n  case main_type_sub_drop_resp:\n    return handle_sub_add_drop_resp(context, p, \"drop\");\n\n  // Sub ping.\n  // In many WWIV networks, the subs list coordinator (SLC) occasionally sends\n  // out \"pings\" to all network members.\n  case main_type_sub_list_info: {\n    if (p.nh.minor_type == 0) {\n      return handle_sub_list_info_request(context, p);\n    }\n    return handle_sub_list_info_response(context, p);\n  }\n\n  case main_type_sub_list:\n    return handle_sub_list(context, p);\n\n  // EPROGS.NET support\n  case main_type_new_external:\n    return handle_new_external(context, p);\n\n  // Skip deleted messages.\n  case 0xFFFF:\n    // Ack processing it since there is nothing to do.\n    return true;\n\n  // Legacy numeric only post types.\n  case main_type_post:\n  case main_type_pre_post:\n\n  case main_type_external:\n\n  // NetEdit.\n  case main_type_net_edit:\n\n  // *.### support\n  case main_type_group_bbslist:\n  case main_type_group_connect:\n  case main_type_group_info:\n    // Anything undefined or anything we missed.\n  default:\n    LOG(ERROR) << \"    ! ERROR Writing message to dead.net for unhandled type: '\"\n               << main_type_name(p.nh.main_type) << \"'; writing to dead.net\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n}\n\nstatic void handle_epreproc_net(const Context& context) {\n  static constexpr char EPREPROC_NET[] = \"epreproc.net\";\n  const auto epreproc_net_file = FilePath(context.net.dir, EPREPROC_NET);\n  if (!File::Exists(epreproc_net_file)) {\n    return;\n  }\n\n  TextFile f(epreproc_net_file, \"rt\");\n  if (!f.IsOpen()) {\n    return;\n  }\n  const auto lines = f.ReadFileIntoVector();\n  for (const auto& l : lines) {\n    const auto cmd = fmt::format(\"{} .{}\", l, context.net.network_number());\n    System(cmd);\n  }\n}\n\n\nstatic bool handle_local_net(Context& context) {\n  // Handle epreproc.net 1st before we open and process the local.net packet\n  handle_epreproc_net(context);\n\n  NetMailFile packets(context.net.dir / LOCAL_NET, true, true);\n  if (!packets) {\n    return false;\n  }\n  for (auto packet : packets) {\n    if (!handle_packet(context, packet)) {\n      LOG(ERROR) << \"Error handing packet: type: \" << packet.nh.main_type;\n    } else if (packet.source() == NetPacketSource::DISK) {\n      // Seek to start of packet and mark it deleted.\n      delete_packet(packets.file(), packet);\n    }\n  }\n  return true;\n}\n\nint network2_main(const NetworkCommandLine& net_cmdline) {\n  try {\n    const auto& net = net_cmdline.network();\n    if (!File::Exists(net.dir / LOCAL_NET)) {\n      LOG(INFO) << \"No local.net exists. exiting.\";\n      return 0;\n    }\n\n    const auto& config = net_cmdline.config();\n    const auto& networks = net_cmdline.networks();\n    // TODO(rushfan): Load sub data here;\n    // TODO(rushfan): Create the right API type for the right message area.\n    MessageApiOptions options{};\n    // By default, delete excess messages like net37 did.\n    options.overflow_strategy = OverflowStrategy::delete_all;\n\n    const auto user_manager = std::make_unique<UserManager>(config);\n    SystemClock clock{};\n    NetDat netdat(config.gfilesdir(), config.logdir(), net, net_cmdline.net_cmd(), clock);\n\n    Context context(config, net, *user_manager, networks.networks(), netdat);\n    context.network_number = net_cmdline.network_number();\n    context.set_email_api(\n        std::make_unique<WWIVMessageApi>(options, config, networks.networks(), new NullLastReadImpl()));\n    context.set_api(2, std::make_unique<WWIVMessageApi>(options, config, networks.networks(),\n                                                        new NullLastReadImpl()));\n\n    VLOG(1) << \"Processing: \" << net.dir.string() << LOCAL_NET;\n    if (handle_local_net(context)) {\n      if (net_cmdline.skip_delete()) {\n        backup_file(net.dir / LOCAL_NET);\n      }\n      VLOG(1) << \"Deleting: \" << net.dir.string() << LOCAL_NET;\n      if (!File::Remove(net.dir / LOCAL_NET)) {\n        LOG(ERROR) << \"ERROR: Unable to delete \" << net.dir << LOCAL_NET;\n      }\n      update_filechange_status_dat(context.config.datadir(), email_changed, posts_changed);\n      return 0;\n    }\n    LOG(ERROR) << \"ERROR: handle_local_net returned false\";\n    return 1;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network]: \" << e.what();\n  }\n\n  return 255;\n}\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  const NetworkCommandLine net_cmdline(cmdline, '2');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n\n  try {\n    const auto semaphore =\n        SemaphoreFile::try_acquire(net_cmdline.semaphore_path(), net_cmdline.semaphore_timeout());\n    return network2_main(net_cmdline);\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n}\n"
  },
  {
    "path": "network2/post.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"network2/post.h\"\n\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"network2/context.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/msgapi/msgapi.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/fido/backbone.h\"\n#include <iostream>\n#include <memory>\n#include <set>\n#include <sstream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net::network2 {\n\nstatic bool find_sub(const Subs& subs, int network_number, const std::string& netname, subboard_t& sub) {\n  auto current = 0;\n  for (const auto& x : subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (n.net_num == network_number) {\n        if (iequals(netname, n.stype)) {\n          // Since the subtype matches, we need to find the subboard base filename.\n          // and return that.\n          sub = subs.sub(current);\n          return true;\n        }\n      }\n    }\n    ++current;\n  }\n  return false;\n}\n\n// Creates a single element vector of the echotag's info from the backbone list\nstatic std::vector<backbone_t> single_echo_backbone_list(std::vector<backbone_t> backbone,\n                                                         std::string echotag) {\n  for (const auto& b : backbone) {\n    if (b.tag == echotag) {\n      return std::vector<backbone_t>{b};\n    }\n  }\n  backbone_t b{echotag, echotag};\n  LOG(WARNING) << \"Could not find echotag: '\" << echotag << \"' in backbone file.\";\n  return std::vector<backbone_t>{b};\n}\n\nstatic bool attempt_auto_add(Context& context, const ParsedNetPacketText& ppt) {\n  // Only auto-add to FTN for now\n  IniFile ini(context.net.dir / context.net.settings.auto_add_ini, \"backbone\");\n  if (!ini.IsOpen()) {\n    LOG(ERROR) << \"Unable to auto add subtype, INI file missing: \"\n               << context.net.settings.auto_add_ini;\n    return false;\n  }\n\n  const auto backbone_filename = FilePath(context.net.dir, context.net.fido.backbone_filename);\n  const auto backbone_echos = ParseBackboneFile(backbone_filename);\n  const auto echo = single_echo_backbone_list(backbone_echos, ppt.subtype());\n  const auto r = ImportSubsFromBackbone(context.subs, context.net,\n                                        static_cast<int16_t>(context.network_number), ini, echo);\n  if (r.subs_dirty && r.success) {\n    return context.subs.Save();\n  } \n  if (!r.success) {\n    LOG(ERROR) << \"    ! ERROR: Failed to auto add sub to subs.json; subtype: \" << ppt.subtype();\n  }\n  return r.success;\n}\n\n// Alpha subtypes are seven characters -- the first must be a letter, but the rest can be any\n// character allowed in a DOS filename.This main_type covers both subscriber - to - host and\n// host - to - subscriber messages. Minor type is always zero(since it's ignored), and the\n// subtype appears as the first part of the message text, followed by a NUL.Thus, the message\n// header info at the beginning of the message text is in the format\n// SUBTYPE<nul>TITLE<nul>SENDER_NAME<cr / lf>DATE_STRING<cr / lf>MESSAGE_TEXT.\nbool handle_inbound_post(Context& context, NetPacket& p) {\n\n  ScopeExit at_exit;\n\n  auto ppt = ParsedNetPacketText::FromNetPacket(p);\n  if (VLOG_IS_ON(1)) {\n    at_exit.swap(\n        [] { LOG(INFO) << \"==============================================================\"; });\n    VLOG(1) << \"==============================================================\";\n    VLOG(1) << \"  Processing New Post on subtype: \" << ppt.subtype();\n    VLOG(1) << \"  Title:   \" << ppt.title();\n    VLOG(1) << \"  Sender:  \" << ppt.sender();\n    VLOG(1) << \"  Date:    \" << ppt.date();\n  }\n\n  subboard_t sub;\n  const auto can_auto_add =\n      context.net.settings.auto_add && context.net.type == network_type_t::ftn;\n  auto found = find_sub(context.subs, context.network_number, ppt.subtype(), sub);\n  if (!found && can_auto_add) {\n    LOG(INFO) << \"      Attempting to auto add area: \" << ppt.subtype();\n    found = attempt_auto_add(context, ppt);\n    if (found) {\n      // Log that we added this both in log file and netdat.\n      const auto msg = fmt::format(\"Auto added sub for type: '{}'\", ppt.subtype());\n      LOG(INFO) << \"      \" << msg;\n      context.netdat().add_message(NetDat::netdat_msgtype_t::normal, msg);\n    }\n  }\n\n  if (!found) {\n    LOG(INFO) << \"    ! ERROR: Unable to find message of subtype: \" << ppt.subtype();\n    LOG(INFO) << \"      title: \" << ppt.title() << \"; writing to dead.net.\";\n    const auto msg = fmt::format(\"Unable to find message of subtype: '{}'; writing to dead.net\", ppt.subtype());\n    context.netdat().add_message(NetDat::netdat_msgtype_t::error, msg);\n    return write_deadnet_packet(context.net.dir, p);\n  }\n\n  if (!context.api(sub.storage_type).Exist(sub)) {\n    // Since the area does not exist, let's create it automatically like WWIV always does.\n    const auto created = context.api(sub.storage_type).Create(sub, -1);\n    if (!created) {\n      const auto msg = fmt::format(\"Failed to create message area: '{}'; writing to dead.net\", sub.filename);\n      context.netdat().add_message(NetDat::netdat_msgtype_t::error, msg);\n      LOG(INFO) << \"    ! ERROR: Failed to create subboard files for sub: '\" << sub.filename\n                << \"'; writing to dead.net.\";\n      return write_deadnet_packet(context.net.dir, p);\n    }\n  }\n\n  std::unique_ptr<MessageArea> area(context.api(sub.storage_type).Open(sub, -1));\n  if (!area) {\n    const auto msg = fmt::format(\"Failed to open message area: '{}'; writing to dead.net\", sub.filename);\n    context.netdat().add_message(NetDat::netdat_msgtype_t::error, msg);\n    LOG(INFO) << \"    ! ERROR Unable to open message area: '\" << sub.filename\n              << \"'; writing to dead.net.\";\n    return write_deadnet_packet(context.net.dir, p);\n  }\n\n  if (area->Exists(p.nh.daten, ppt.title(), p.nh.fromsys, p.nh.fromuser)) {\n    const auto msg = fmt::format(\"Discarding Duplicate Message on sub: {}; daten: {}; title: {}\", ppt.subtype(),  p.nh.daten, ppt.title());\n    context.netdat().add_message(NetDat::netdat_msgtype_t::normal, msg);\n    LOG(INFO) << msg;\n    // Returning true since we properly handled this by discarding it.\n    return true;\n  }\n\n  // TODO(rushfan): Should we let CreateMessage accept the packet directly\n  // then we could also check the main_type to ensure it's fine.\n  Message msg(&context.api(sub.storage_type));\n  msg.header().set_from_system(p.nh.fromsys);\n  msg.header().set_from_usernum(p.nh.fromuser);\n  msg.header().set_title(ppt.title());\n  msg.header().set_from(ppt.sender());\n  msg.header().set_daten(p.nh.daten);\n\n  // Set the network number this came in on.\n  msg.header().set_net_number(context.network_number);\n  msg.set_text(ppt.text());\n\n  MessageAreaOptions options{};\n  options.send_post_to_network = false;\n  // these should already exist if they are needed.\n  options.add_re_and_by_line = false;\n  if (!area->AddMessage(msg, options)) {\n    const auto errmsg = fmt::format(\"Failed to add message: '{}'; writing to dead.net\", ppt.title());\n    context.netdat().add_message(NetDat::netdat_msgtype_t::error, errmsg);\n    LOG(ERROR) << \"    ! ERROR \" << errmsg;\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  LOG(INFO) << \"    + Posted  '\" << ppt.title() << \"' on sub: '\" << ppt.subtype() << \"'.\";\n    context.netdat().add_message(NetDat::netdat_msgtype_t::post, fmt::format(\"Posted  '{}' on sub: '{}'\",\n    ppt.title(), ppt.subtype()));\n\n  return true;\n}\n\nstatic std::string set_to_string(const std::set<uint16_t>& lines) {\n  std::ostringstream ss;\n  for (const auto& line : lines) {\n    ss << line << std::endl;\n  }\n  return ss.str();\n}\n\nbool send_post_to_subscribers(Context& context, NetPacket& template_packet,\n                              const std::set<uint16_t>& subscribers_to_skip) {\n  VLOG(1) << \"DEBUG: send_post_to_subscribers; skipping: \" << set_to_string(subscribers_to_skip);\n\n  if (template_packet.nh.main_type != main_type_new_post) {\n    LOG(ERROR) << \"Called send_post_to_subscribers on packet of wrong type.\";\n    LOG(ERROR) << \"expected send_post_to_subscribers, got: \"\n               << main_type_name(template_packet.nh.main_type);\n    return false;\n  }\n  const auto original_subtype = get_subtype_from_packet_text(template_packet.text());\n  VLOG(1) << \"DEBUG: send_post_to_subscribers; original subtype: \" << original_subtype;\n\n  if (original_subtype.empty()) {\n    LOG(ERROR) << \"No subtype found for packet text.\";\n    return false;\n  }\n\n  subboard_t sub;\n  if (!find_sub(context.subs, context.network_number, original_subtype, sub)) {\n    const auto msg = fmt::format(\"Unable to find message of subtype: '{}'; writing to dead.net\", original_subtype);\n    context.netdat().add_message(NetDat::netdat_msgtype_t::error, msg);\n    LOG(INFO) << msg;\n    NetPacket p(template_packet.nh, {}, template_packet.text());\n    return write_deadnet_packet(context.net.dir, p);\n  }\n  VLOG(1) << \"DEBUG: Found sub: \" << sub.name;\n\n  return send_post_to_subscribers(context.networks(), context.network_number, original_subtype, sub,\n                                  template_packet, subscribers_to_skip,\n                                  subscribers_send_to_t::hosted_and_gated_only);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "network2/post.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORK2_POST_H__\n#define __INCLUDED_NETWORK2_POST_H__\n\n#include \"network2/context.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/packets.h\"\n#include <set>\n\nnamespace wwiv {\nnamespace net {\nnamespace network2 {\n\n/**\n * Handles receiving a NetPacket with a post and writing it to the\n * local database.\n */\nbool handle_inbound_post(Context& context, wwiv::sdk::net::NetPacket& packet);\n/**\n * Send a network post out to the other subscribers when you are the host off\n * a sub or gating a sub.\n */\nbool send_post_to_subscribers(Context& context, wwiv::sdk::net::NetPacket& packet,\n                              const std::set<uint16_t>& subscribers_to_skip);\n\n} // namespace network2\n} // namespace net\n} // namespace wwiv\n\n#endif // __INCLUDED_NETWORK2_POST_H__\n"
  },
  {
    "path": "network2/subs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"network2/subs.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"network2/context.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/ssm.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/net/subscribers.h\"\n\n#include <iterator>\n#include <map>\n#include <set>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net::network2 {\n\nstruct sub_info_t {\n  std::string stype;\n  std::string flags;\n  std::string description;\n  uint16_t category = 0;\n};\n\nstatic std::string to_string(sub_info_t& s, uint16_t system_number) {\n  return fmt::sprintf(\"%-7s %5u %-5s %s~%u\", s.stype, system_number, s.flags, s.description, s.category);\n}\n\nstatic std::vector<std::string> create_sub_info(Context& context) {\n  auto current = 0;\n  std::vector <std::string> result;\n  for (const auto& x : context.subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (n.net_num != context.network_number) {\n        continue;\n      }\n      if (n.host != 0) {\n        continue;\n      }\n      if (!(n.flags & XTRA_NET_AUTO_INFO)) {\n        // Not allowed to subs.lst info for sub\n        continue;\n      }\n      sub_info_t s;\n      const auto& b = context.subs.sub(current);\n      s.stype = n.stype;\n      s.category = n.category;\n      s.description = stripcolors(x.desc);\n      if (s.description.empty()) {\n        s.description = stripcolors(context.subs.sub(current).name);\n      }\n      if (s.description.size() > 60) {\n        s.description.resize(60);\n      }\n      if (b.anony & anony_ansi_only) {\n        s.flags += 'A';\n      }\n      if (x.nets.size() > 1) {\n        s.flags += 'G';\n      }\n      if (b.anony & anony_val_net) {\n        s.flags += 'N';\n      }\n      if (n.flags & XTRA_NET_AUTO_ADDDROP) {\n        s.flags += 'R';\n      }\n      if (b.anony & anony_no_tag) {\n        s.flags += 'T';\n      }\n      result.emplace_back(to_string(s, context.net.sysnum));\n    }\n    ++current;\n  }\n  return result;\n}\n\nstatic std::string SubTypeFromText(const std::string& text) {\n  auto subtype = StringTrim(text);\n  if (subtype.back() == '\\0') subtype.pop_back();\n  if (subtype.size() > 7) {\n    return \"\";\n  }\n  return subtype;\n}\n\nstatic bool send_sub_add_drop_resp(Context& context, \n                                   net_header_rec orig,\n                                   uint8_t main_type, uint8_t code,\n                                   const std::string& subtype,\n                                   const std::string& response_file_text) {\n  net_header_rec nh = {};\n  nh.daten = daten_t_now();\n  nh.fromsys = orig.tosys;\n  nh.fromuser = orig.touser;\n  nh.main_type = main_type;\n  nh.tosys = orig.fromsys;\n  nh.touser = orig.fromuser;\n  std::string title; // empty\n\n  auto text = subtype;\n  text.push_back(0); // null after subtype.\n  text.push_back(code);\n\n  // Add \"Sub type 'subtype' ('subname') + #0\n  text.append(StrCat(\"Sub Type \", subtype));\n  text.push_back(0); // null after title.\n\n  // Add from Name + \\r\\n + date + \\r\\n + \\r\\n\n  text.append(StrCat(context.config.sysop_name(), \" #1\\r\\n\"));\n  text.append(StrCat(daten_to_wwivnet_time(daten_t_now()), \"\\r\\n\\r\\n\"));\n\n  // Add the text that probably came from a SA or SR  + subtype + .net file.\n  text.append(response_file_text);\n\n  nh.length = size_int(text); // should be subtype.size() + 2\n  const auto pendfile = create_pend(context.net.dir, false, '2');\n  const NetPacket packet(nh, {}, text);\n  return write_wwivnet_packet(FilePath(context.net.dir, pendfile), packet);\n}\n\nstatic bool IsHostedHere(Context& context, const std::string& subtype) {\n  for (const auto& x : context.subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (iequals(subtype, n.stype) \n          && n.host == 0\n          && n.net_num == context.network_number) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool handle_sub_add_req(Context& context, NetPacket& p) {\n  const auto subtype = SubTypeFromText(p.text());\n  const auto resp = [&](uint8_t code) -> bool {\n    const std::string base = (code == sub_adddrop_ok) ? \"sa\" : \"sr\";\n    const auto response_file = StrCat(base, subtype, \".net\");\n    std::string text;\n    LOG(INFO) << \"Candidate sa file: \" << FilePath(context.net.dir, response_file).string();\n    if (File::Exists(FilePath(context.net.dir, response_file))) {\n      TextFile tf(FilePath(context.net.dir, response_file), \"r\");\n      LOG(INFO) << \"Sending SA file: \" << tf;\n      text = tf.ReadFileIntoString();\n    }\n    return send_sub_add_drop_resp(context, p.nh, main_type_sub_add_resp, code, subtype, text);\n  };\n  if (subtype.empty()) {\n    return resp(sub_adddrop_error);\n  }\n  if (!IsHostedHere(context, subtype)) {\n    const auto msg = fmt::format(\"Can't add system @{} to subtype: {}, it's not hosted here\",p.nh.fromsys, subtype);\n    context.ssm.send_local(1, msg);\n    LOG(ERROR) << msg;\n    return resp(sub_adddrop_not_host);\n  }\n  const auto disallow_dat_fn = FilePath(context.net.dir, DISALLOW_NET);\n  auto disallowed = ReadSubcriberFile(disallow_dat_fn);\n  if (contains(disallowed, p.nh.fromsys)) {\n    context.ssm.send_local(1, fmt::format(\"Req Add: @{}Tried to subscribe '{}' - not allowed.\", p.nh.fromsys, subtype));\n    return resp(sub_adddrop_not_allowed);\n  }\n  const auto filename = StrCat(\"n\", subtype, \".net\");\n  const auto subscriber_fn = FilePath(context.net.dir, filename);\n  auto subscribers = ReadSubcriberFile(subscriber_fn);\n  if (const auto result = subscribers.insert(p.nh.fromsys); result.second == false) {\n    context.ssm.send_local(1, fmt::format(\"Can't add system @{} to subtype: {}, it's already there.\",p.nh.fromsys, subtype));\n    return resp(sub_adddrop_already_there);\n  }\n  if (!WriteSubcriberFile(FilePath(context.net.dir, filename), subscribers)) {\n    LOG(INFO) << \"Unable to write subscribers file.\";\n    context.ssm.send_local(1, fmt::format(\"Can't add system @{} to subtype: {}, failed to write subscriber file.\",p.nh.fromsys, subtype));\n    return resp(sub_adddrop_error);\n  }\n\n  // success!\n  const auto msg = fmt::format(\"Added System @{} to subtype: {}\",p.nh.fromsys, subtype);\n  LOG(INFO) << msg;\n  context.ssm.send_local(1, msg);\n  return resp(sub_adddrop_ok);\n}\n\nbool handle_sub_drop_req(Context& context, NetPacket& p) {\n  const auto subtype = SubTypeFromText(p.text());\n  const auto resp = [&](uint8_t code) -> bool { \n    return send_sub_add_drop_resp(context, p.nh, main_type_sub_drop_resp, code, subtype, \"\"); \n  };\n  if (subtype.empty()) {\n    return resp(sub_adddrop_error);\n  }\n  if (!IsHostedHere(context, subtype)) {\n    return resp(sub_adddrop_not_host);\n  }\n  const auto filename = StrCat(\"n\", subtype, \".net\");\n  const auto subscriber_fn = FilePath(context.net.dir, filename);\n  auto subscribers = ReadSubcriberFile(subscriber_fn);\n  if (const auto num_removed = subscribers.erase(p.nh.fromsys); num_removed == 0) {\n    return resp(sub_adddrop_not_there);\n  }\n  if (!WriteSubcriberFile(FilePath(context.net.dir, filename), subscribers)) {\n    LOG(INFO) << \"Unable to write subscribers file.\";\n    return resp(sub_adddrop_error);\n  }\n\n  // success!\n  LOG(INFO) << \"Dropped system @\" << p.nh.fromsys << \" to subtype: \" << subtype;\n  return resp(sub_adddrop_ok);\n}\n\nstatic std::string SubAddDropResponseMessage(uint8_t code) {\n  switch (code) {\n  case sub_adddrop_already_there: return \"You are already in the sub.\";\n  case sub_adddrop_error: return \"Error Adding or Droppign Sub\";\n  case sub_adddrop_not_allowed: return \"The sub is not under automatic control.  Send email instead.\";\n  case sub_adddrop_not_host: return \"That sub is not hosted here.\";\n  case sub_adddrop_not_there: return \"You were not listed for the sub.\";\n  case sub_adddrop_ok: return \"Success! You have been added to or removed from the sub.\";\n  default:\n    return fmt::format(\"Unknown response code {}\", code);\n  }\n}\n\nbool handle_sub_add_drop_resp(Context& context, NetPacket& p, const std::string& add_or_drop) {\n  // We want to stop at the 1st \\0\n  auto b = std::begin(p.text());\n  const auto subname = StringTrimEnd(get_message_field(p.text(),b, {'\\0'}, 80));\n  if (b == std::end(p.text())) {\n    LOG(INFO) << \"Unable to determine code from add_drop response.\";\n    return false;\n  }\n\n  LOG(INFO) << \"Processed \" << add_or_drop << \" response from system @\" << p.nh.fromsys << \" to subtype: \" << subname;\n\n  const auto code = *b++;\n  const auto code_string = SubAddDropResponseMessage(static_cast<uint8_t>(code));\n\n  const auto orig_title = get_message_field(p.text(), b, {'\\0', '\\r', '\\n'}, 80);\n  const auto sender_name = get_message_field(p.text(), b, {'\\0', '\\r', '\\n'}, 80);\n  const auto orig_date = get_message_field(p.text(), b, {'\\0', '\\r', '\\n'}, 80);\n  const auto message_text = std::string(b, std::end(p.text()));\n  net_header_rec nh = {};\n\n  const auto title = StrCat(\"WWIV AreaFix (\", context.net.name, \") Response for subtype '\", subname, \"'\");\n  const auto byname = StrCat(\"WWIV AreaFix (\", context.net.name, \") @\", p.nh.fromsys);\n  auto body =\n      StrCat(\"SubType '\", subname, \"', (\", add_or_drop, \") Response: '\", code_string, \"'\\r\\n\");\n  body.append(message_text);\n\n  nh.touser = 1;\n  nh.fromuser = std::numeric_limits<uint16_t>::max();\n  nh.fromsys = p.nh.fromsys;\n  nh.main_type = main_type_email;\n  nh.daten = daten_t_now();\n\n  const auto filename = create_pend(context.net.dir, true, '2');\n  return send_network_email(filename, context.net, nh, {}, body, byname, title);\n}\n\nbool handle_sub_list_info_response(Context& context, NetPacket& p) {\n  TextFile subs_inf(FilePath(context.net.dir, \"subs.inf\"), \"at\");\n  LOG(INFO) << \"Received subs line for subs.inf:\";\n  LOG(INFO) << p.text();\n  return subs_inf.Write(p.text()) > 0;\n}\n\nbool handle_sub_list_info_request(Context& context, NetPacket& p) {\n\n  net_header_rec nh{};\n  nh.fromsys = p.nh.tosys;\n  nh.fromuser = p.nh.touser;\n  nh.tosys = p.nh.fromsys;\n  nh.touser = p.nh.fromuser;\n  nh.main_type = main_type_sub_list_info;\n  nh.minor_type = 1;\n  nh.daten = daten_t_now();\n\n  const auto lines = create_sub_info(context);\n  const auto text = JoinStrings(lines, \"\\r\\n\");\n  nh.length = size_int(text);\n\n  LOG(INFO) << \"Sending subs line for subs.inf:\";\n  LOG(INFO) << text;\n\n  const auto pendfile = create_pend(context.net.dir, false, '2');\n  const NetPacket np(nh, {}, text);\n  return write_wwivnet_packet(FilePath(context.net.dir, pendfile), np);\n}\n\n\n}\n"
  },
  {
    "path": "network2/subs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_NETWORK2_SUBS_H__\n#define __INCLUDED_NETWORK2_SUBS_H__\n\n#include \"network2/context.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/packets.h\"\n\nnamespace wwiv {\nnamespace net {\nnamespace network2 {\n\nbool handle_sub_add_req(Context& context, wwiv::sdk::net::NetPacket& p);\nbool handle_sub_drop_req(Context& context, wwiv::sdk::net::NetPacket& p);\nbool handle_sub_add_drop_resp(Context& context, wwiv::sdk::net::NetPacket& p,\n                              const std::string& add_or_drop);\nbool handle_sub_list_info_request(Context& context, wwiv::sdk::net::NetPacket& p);\nbool handle_sub_list_info_response(Context& context, wwiv::sdk::net::NetPacket& p);\n\n}  // namespace network2\n}  // namespace net\n}  // namespace wwiv\n\n#endif  // __INCLUDED_NETWORK2_SUBS_H__\n"
  },
  {
    "path": "network3/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN network3.cpp)\n\nadd_executable(network3 ${NETWORK_MAIN})\nset_max_warnings(network3)\ntarget_link_libraries(network3 binkp_lib net_core core sdk)\n\n"
  },
  {
    "path": "network3/network3.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp_config.h\"\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"net_core/netdat.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/fido/nodelist.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/connect.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/net/subscribers.h\"\n\n#include <cctype>\n#include <cstdlib>\n#include <filesystem>\n#include <iostream>\n#include <map>\n#include <sstream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nstatic bool check_wwivnet_host_networks(\n  const wwiv::sdk::Config& config, \n  const wwiv::sdk::Networks& network,\n  const BbsListNet& b,\n  int network_number,\n  std::ostringstream& text) {\n  \n  wwiv::sdk::Subs subs(config.datadir(), network.networks());\n  if (!subs.Load()) {\n    LOG(ERROR) << \"Unable to load subs (.dat and .xtr)\";\n    return false;\n  }\n\n const auto& net = network.networks()[network_number];\n\n  for (const auto& x : subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (n.net_num == network_number) {\n        if (n.host == 0) {\n          // Sub hosted here.\n          const auto filename = StrCat(\"n\", n.stype, \".net\");\n          const auto subscriber_fn = FilePath(net.dir, filename);\n          const auto subscribers = ReadSubcriberFile(subscriber_fn);\n          for (auto subscriber : subscribers) {\n            if (const auto c = b.node_config_for(subscriber); !c) {\n              text << \"Unknown system @\" << subscriber << \" subscribed to sub '\" << n.stype << \"'\\r\\n\";\n            }\n          }\n        } else {\n          // Sub hosted elsewhere.\n          const auto c = b.node_config_for(n.host);\n          if (!c) {\n            text << \"Unknown system @\" << n.host << \" hosting subtype '\" << n.stype << \"'\\r\\n\";\n          }\n        }\n      }\n    }\n  }\n  return true;\n}\n\nstatic bool check_fido_host_networks(\n  const Config& config,\n  const Networks& network,\n  const Network& net,\n  int network_number,\n  std::ostringstream& text) {\n\n  Subs subs(config.datadir(), network.networks());\n  if (!subs.Load()) {\n    LOG(ERROR) << \"Unable to load subs (.dat and .xtr)\";\n    text << \"Unable to load subs (.dat and .xtr)\\r\\n\";\n    return false;\n  }\n\n  for (const auto& x : subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (n.net_num != network_number) {\n        continue;\n      }\n      if (n.host != 0) {\n        continue;\n      }\n      const auto filename = StrCat(\"n\", n.stype, \".net\");\n      if (!File::Exists(FilePath(net.dir, filename))) {\n        text << \"subscriber file '\" << filename << \"' for echotag: '\" << n.stype << \"' is missing.\\r\\n\";\n        text << \" ** Please fix it.\\r\\n\\n\";\n      }\n      LOG(INFO) << \"Checking FTN Subscribers in file \" << FilePath(net.dir, filename).string();\n      auto subscribers = ReadFidoSubcriberFile(FilePath(net.dir, filename));\n      if (subscribers.empty()) {\n        text << \"Unable to find any uplinks in subscriber file for echotag: \" << n.stype << \"\\r\\n\";\n        text << \" ** Please fix it.\\r\\n\\n\";\n      }\n    }\n  }\n\n  return true;\n}\n\nstatic bool check_connect_net(const BbsListNet& b,\n                              const Network& net,\n                              std::ostringstream& text) {\n\n  const Connect connect(net.dir);\n  for (const auto& entry : b.node_config()) {\n    const auto* n = connect.node_config_for(entry.first);\n    if (!n) {\n      text << \"connect.net entry missing for node @\" << entry.first << \"\\r\\n\";\n    }\n  }\n  return true;\n}\n\nstatic bool check_binkp_net(const BbsListNet& b,\n                            const BinkConfig& bink_config,\n                            std::ostringstream& text) {\n  for (const auto& entry : b.node_config()) {\n    const auto* binkp_entry = bink_config.binkp_session_config_for(entry.first);\n    if (binkp_entry == nullptr) {\n      text << \"binkp.net entry missing for node @\" << entry.first << \"\\r\\n\";\n    }\n  }\n  return true;\n}\n\nstatic bool send_feedback_email(const Network& net, const std::string& text) {\n  net_header_rec nh = {};\n\n  const auto now_mmddyy = DateTime::now().to_string(\"%m/%d/%y\");\n  const auto title = fmt::format(\"{} analysis on {}\", net.name, now_mmddyy);\n  const auto byname = fmt::format(\"{} @{}\", net.name, net.sysnum);\n\n  nh.touser = 1;\n  nh.fromuser = std::numeric_limits<uint16_t>::max();\n  nh.main_type = main_type_email;\n  nh.daten = daten_t_now();\n\n  return send_local_email(net, nh, text, byname, title);\n}\n\nstatic bool add_feedback_header(const std::filesystem::path& net_dir, std::ostringstream& text) {\n  TextFile feedback_hdr(FilePath(net_dir, \"fbackhdr.net\"), \"rt\");\n  if (!feedback_hdr.IsOpen()) {\n    return true;\n  }\n  text << \"\\r\\n\";\n  auto lines = feedback_hdr.ReadFileIntoVector();\n  for (const auto& line : lines) {\n    text << line << \"\\r\\n\";\n  }\n  return true;\n}\n\nstatic uint16_t get_network_cordinator(const BbsListNet& b) {\n  for (const auto& entry : b.node_config()) {\n    if (entry.second.other & other_net_coord) {\n      return entry.second.sysnum;\n    }\n  }\n  return WWIVNET_NO_NODE;\n}\n\nstatic bool add_feedback_general_info(\n    const Callout& callout, \n    const Network& net,\n    const std::vector<net_system_list_rec>& bbsdata_data,\n    std::ostringstream& text) {\n\n  uint16_t nc = 0;\n  uint16_t gc = 0;\n  uint16_t ac = 0;\n  std::map<int, int> hops_to_count;\n  std::map<int, int> system_to_route_count;\n  int total_hops = 0;\n  for (const auto& d : bbsdata_data) {\n    if (d.other & other_net_coord) {\n      nc = d.sysnum;\n    } else if (d.other & other_group_coord) {\n      gc = d.sysnum;\n    } else if (d.other & other_area_coord) {\n      ac = d.sysnum;\n    }\n\n    // Make num hops map.\n    const auto hops = hops_to_count[d.numhops];\n    hops_to_count[d.numhops] = hops + 1;\n\n    total_hops += d.numhops;\n    if (d.forsys != WWIVNET_NO_NODE) {\n      const auto num_route = system_to_route_count[d.forsys];\n      system_to_route_count[d.forsys] = num_route + 1;\n    }\n  }\n\n  text << fmt::format(\"Network Coordinator is @{}\\r\\n\", nc);\n  text << fmt::format(\"Group Coordinator is @{}\\r\\n\", (gc != 0) ? gc : nc);\n  text << fmt::format(\"Area Coordinator is @{}\\r\\n\", (ac != 0) ? ac : nc);\n  text << \"\\r\\n\";\n  text << \"Using bias of 0.00100 $ / k / hop.\\r\\n\";\n  text << \"\\r\\n\";\n  text << \"\\r\\n\";\n  for (const auto& e : hops_to_count) {\n    if (e.first > 0 && e.first < 10000) {\n      text << fmt::format(\"{} systems are {} hops away.\\r\\n\", e.second, e.first);\n    }\n  }\n  text << \"\\r\\n\";\n  for (const auto& e : system_to_route_count) {\n    if (e.first != net.sysnum) {\n      text << fmt::format(\"{} systems route through @{}.\\r\\n\", e.second, e.first);\n    }\n  }\n  text << \"\\r\\n\";\n\n  const Connect connect(net.dir);\n  const auto* c = connect.node_config_for(net.sysnum);\n  if (c == nullptr) {\n    text << \" ** Missing connect.net entries.\";\n  } else {\n    for (const auto& callout_node : c->connect) {\n      const auto* cnc = callout.net_call_out_for(callout_node);\n      if (cnc == nullptr) {\n        text << \"Can call \" << callout_node << \" but isn't in callout.net.\\r\\n\"\n          << \"  ** Add to callout.net\\r\\n\\r\\n\";\n      }\n    }\n  }\n\n  return true;\n}\n\nvoid update_timestamps(const std::filesystem::path& dir) {\n  // Update timestamps on {bbslist,connect,callout}.net\n  const auto t = File::last_write_time(FilePath(dir, BBSDATA_NET));\n  File(FilePath(dir, BBSLIST_NET)).set_last_write_time(t);\n  File(FilePath(dir, CONNECT_NET)).set_last_write_time(t);\n  File(FilePath(dir, CALLOUT_NET)).set_last_write_time(t);\n}\n\nstatic void write_bbsdata_reg_file(const BbsListNet& b, const std::filesystem::path& dir) {\n  LOG(INFO) << \"Writing BBSDATA.REG...\";\n  std::vector<int32_t> bbsdata_reg_data;\n  const auto& reg = b.reg_number();\n  for (const auto& [node, _] : b.node_config()) {\n    bbsdata_reg_data.push_back(at(reg, node));\n  }\n  DataFile<int32_t> bbsdata_reg_file(FilePath(dir, BBSDATA_REG),\n                                     File::modeBinary | File::modeReadWrite | File::modeCreateFile);\n  bbsdata_reg_file.WriteVector(bbsdata_reg_data);\n}\n\nstatic int write_bbsdata_files(const std::vector<net_system_list_rec>& bbsdata_data, \n  const std::filesystem::path& dir) {\n  {\n    LOG(INFO) << \"Writing bbsdata.net...\";\n    DataFile<net_system_list_rec> bbsdata_net_file(FilePath(dir, BBSDATA_NET),\n                                                   File::modeBinary | File::modeReadWrite |\n                                                       File::modeCreateFile);\n    bbsdata_net_file.WriteVector(bbsdata_data);\n   }\n  update_timestamps(dir);\n  auto num_reachable = 0;\n  {\n    LOG(INFO) << \"Writing bbsdata.ind...\";\n    std::vector<uint16_t> bbsdata_ind_data;\n    for (const auto& n : bbsdata_data) {\n      const auto is_reachable = n.forsys != WWIVNET_NO_NODE;\n      if (is_reachable) {\n        ++num_reachable;\n      }\n      bbsdata_ind_data.push_back(is_reachable ? n.sysnum : 0);\n    }\n    DataFile<uint16_t> bbsdata_ind_file(FilePath(dir, BBSDATA_IND), File::modeBinary |\n                                        File::modeReadWrite | File::modeCreateFile);\n    bbsdata_ind_file.WriteVector(bbsdata_ind_data);\n  }\n  {\n    LOG(INFO) << \"Writing bbsdata.rou...\";\n    std::vector<uint16_t> bbsdata_rou_data;\n    for (const auto& n : bbsdata_data) {\n      bbsdata_rou_data.push_back(n.forsys);\n    }\n    DataFile<uint16_t> bbsdata_rou_file(FilePath(dir, BBSDATA_ROU), File::modeBinary |\n                                                                            File::modeReadWrite |\n                                                                            File::modeCreateFile);\n    bbsdata_rou_file.WriteVector(bbsdata_rou_data);\n  }\n  return num_reachable;\n}\n\nstatic void update_net_ver_status_dat(const std::filesystem::path& datadir) {\n  statusrec_t statusrec{};\n  DataFile<statusrec_t> file(FilePath(datadir, STATUS_DAT),\n                             File::modeBinary | File::modeReadWrite);\n  if (!file) {\n    return;\n  }\n  if (!file.Read(0, &statusrec)) {\n    return;\n  }\n  if (statusrec.net_version == wwiv_network_compatible_version()) {\n    return;\n  }\n  statusrec.net_bias = 0;\n  statusrec.net_req_free = 0;\n  statusrec.net_version = static_cast<uint16_t>(wwiv_network_compatible_version());\n  file.Write(0, &statusrec);\n}\n\nstatic void update_filechange_status_dat(const std::filesystem::path& datadir) {\n  StatusMgr sm(datadir);\n  sm.Run([=](Status& s)\n  {\n    s.increment_filechanged(Status::file_change_net);\n  });\n\n  if (auto file = DataFile<statusrec_t>(FilePath(datadir, STATUS_DAT),\n                             File::modeBinary | File::modeReadWrite)) {\n    statusrec_t statusrec{};\n    if (file.Read(0, &statusrec)) {\n      statusrec.filechange[filechange_net]++;\n      file.Write(0, &statusrec);\n    }\n  }\n}\n\nstatic void rename_pending_files(const std::filesystem::path& dir) {\n  const auto dead_net_file(FilePath(dir, DEAD_NET));\n  if (File::Exists(dead_net_file)) {\n    rename_pend(dir, DEAD_NET, '3');\n  }\n\n  FindFiles ff(FilePath(dir, \"s*.net\"), FindFiles::FindFilesType::files);\n  for (const auto& f : ff) {\n    if (std::isdigit(f.name.at(1))) {\n      // Only process files of the form s######.net\n      rename_pend(dir, f.name, '3');\n    }\n  }\n}\n\nstatic void ensure_contact_net_entries(const Callout& callout, const Network& net) {\n  Contact contact(net, true);\n  for (const auto& [node, _] : callout.callout_config()) {\n    // Ensure we have a contact entry for each node in callout.net\n    contact.ensure_rec_for(node);\n  }\n}\n\nstatic bool need_to_send_feedback(const CommandLine& cmdline) {\n  if (cmdline.barg(\"feedback\")) {\n    return true;\n  }\n  for (const auto& s : cmdline.remaining()) {\n    if (s == \"Y\" || s == \"y\") {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic int network3_fido(const NetworkCommandLine& net_cmdline) {\n  VLOG(2) << \"network3_fido\";\n  const auto& net = net_cmdline.network();\n  std::ostringstream text;\n  add_feedback_header(net.dir, text);\n  LOG(INFO) << \"Sending Feedback.\";\n\n  std::vector<net_system_list_rec> bbsdata_data;\n  auto phone = net_cmdline.config().system_phone();\n  {\n    net_system_list_rec n1{};\n    to_char_array(n1.name, net_cmdline.config().system_name());\n    to_char_array(n1.phone, phone);\n    n1.forsys = FTN_FAKE_OUTBOUND_NODE;\n    n1.group = 0;\n    n1.speed = 33600;\n    n1.sysnum = 1;\n    n1.numhops = 0;\n    n1.forsys = 1;\n    bbsdata_data.emplace_back(n1);\n  }\n  {\n    auto fake_phone = phone;\n    if (fake_phone.size() > 3) {\n      fake_phone = fake_phone.substr(0, 3);\n    } else {\n      fake_phone = \"415\";\n    }\n    fake_phone += \"-000-FIDO\";\n\n    net_system_list_rec n2{};\n    to_char_array(n2.name, StrCat(net.name, \" Gateway\"));\n    to_char_array(n2.phone, fake_phone);\n    n2.sysnum = FTN_FAKE_OUTBOUND_NODE;\n    n2.group = 0;\n    n2.speed = 33600;\n    n2.numhops = 1;\n    n2.forsys = FTN_FAKE_OUTBOUND_NODE;\n    bbsdata_data.emplace_back(n2);\n  }\n\n  write_bbsdata_files(bbsdata_data, net.dir);\n\n  // create bbsdata.reg\n  {\n    std::vector<int32_t> bbsdata_reg_data;\n    bbsdata_reg_data.push_back(net_cmdline.config().wwiv_reg_number());\n    bbsdata_reg_data.push_back(0);\n    DataFile<int32_t> bbsdata_reg_file(FilePath(net.dir, BBSDATA_REG),\n                                       File::modeBinary |\n                                                                           File::modeReadWrite |\n                                                                           File::modeCreateFile);\n    bbsdata_reg_file.WriteVector(bbsdata_reg_data);\n  }\n\n  FidoAddress address;\n  try {\n    FidoAddress a(net.fido.fido_address);\n    address = a;\n  } catch (const std::exception&) {\n    text << \"Unable to parse your address of: \" << net.fido.fido_address << \"\\r\\n\";\n    text << \" ** Please fix it.\\r\\n\\n\";\n  }\n  FtnDirectories dirs(net_cmdline.cmdline().bindir(), net);\n  text << \"Inbound dir:             \" << dirs.inbound_dir() << \"\\r\\n\";\n  text << \"Outbound dir:            \" << dirs.outbound_dir() << \"\\r\\n\";\n  text << \"Temporary Inbound dir:   \" << dirs.temp_inbound_dir() << \"\\r\\n\";\n  text << \"Temporary Outbound dir:  \" << dirs.temp_outbound_dir() << \"\\r\\n\";\n  text << \"Bad Packets dir:         \" << dirs.bad_packets_dir() << \"\\r\\n\";\n  text << \"\\r\\n\";\n\n  if (!File::Exists(FilePath(dirs.net_dir(), FIDO_CALLOUT_JSON))) {\n    text << \" ** fido_callout.json file DOES NOT EXIST.\\r\\n\\n\";\n  }\n  FidoCallout callout(net_cmdline.config().root_directory(), net_cmdline.config().max_backups(),\n                      net);\n  if (!callout.IsInitialized()) {\n    text << \" ** Unable to read fido_callout.json\\r\\n\\n\";\n  } else {\n    check_fido_host_networks(net_cmdline.config(), net_cmdline.networks(), net,\n                             net_cmdline.network_number(), text);\n  }\n\n  text << \"Using nodelist base:     \" << net.fido.nodelist_base << \"\\r\\n\";\n  text << \"Using nodelist base dir: \" << dirs.net_dir() << \"\\r\\n\";\n  auto nodelist = Nodelist::FindLatestNodelist(dirs.net_dir(), net.fido.nodelist_base);\n  text << \"Latest FTN is:           \" << nodelist;\n  const auto nl_file = FilePath(dirs.net_dir(), nodelist);\n  if (!File::Exists(nl_file)) {\n    text << \" (DOES NOT EXIST)\\r\\n\";\n    text << \" ** Please fix it.\\r\\n\\n\";\n  } else {\n    text << \" [\" << time_t_to_wwivnet_time(File::last_write_time(nl_file)) << \"]\\r\\n\";\n    auto nl_path = File::absolute(dirs.net_dir(), nodelist);\n    Nodelist nl(nl_path, domain_from_address(net.fido.fido_address));\n    if (!nl.initialized()) {\n      text << \" ** Unable to parse nodelist.\\r\\n\";\n      text << \" ** Please fix it.\\r\\n\\n\";\n    } else {\n      if (!nl.contains(address)) {\n        text << \" ** Your address: '\" << address << \"' does not exist in the nodelist: '\" << nodelist << \".\\r\\n\";\n      }\n      for (const auto& ncs : callout.node_configs_map()) {\n        if (!nl.contains(ncs.first)) {\n          text << \" ** Callout address: '\" << ncs.first.as_string() << \"' does not exist in the nodelist.\\r\\n\";\n        }\n      }\n    }\n  }\n\n  text << \"\\r\\n\";\n\n  if (net.fido.origin_line.empty()) {\n    text << \"You may want to define an origin line for your network.\\r\\n\";\n  }\n\n  text << \"\\r\\nBest,\\r\\n\\r\\n\" << net.name << \"@\" << net.sysnum << \"\\r\\n\\r\\n\";\n\n  if (need_to_send_feedback(net_cmdline.cmdline())) {\n    send_feedback_email(net, text.str());\n  }\n\n  return 0;\n}\n\nstatic int network3_wwivnet(const NetworkCommandLine& net_cmdline) {\n  VLOG(2) << \"Reading bbslist.net..\";\n  const auto& net = net_cmdline.network();\n  const auto b = BbsListNet::ParseBbsListNet(net.sysnum, net.dir);\n  SystemClock clock;\n  NetDat netdat(net_cmdline.config().gfilesdir(), net_cmdline.config().logdir(),\n                net_cmdline.network(), net_cmdline.net_cmd(), clock);\n  if (b.empty()) {\n    LOG(ERROR) << \"ERROR: bbslist.net didn't parse.\";\n    return 1;\n  }\n\n  const auto nc = get_network_cordinator(b);\n  const auto is_nc = (net.sysnum == nc);\n  LOG(INFO) << \"I am the nc, my node # is @\" << net.sysnum;\n\n  std::vector<net_system_list_rec> bbsdata_data;\n  for (const auto& [_, n] : b.node_config()) {\n    bbsdata_data.push_back(n);\n  }\n\n  int num_systems = write_bbsdata_files(bbsdata_data, net.dir);\n  write_bbsdata_reg_file(b, net.dir);\n\n  VLOG(2) << \"Reading callout.net...\";\n  const Callout callout(net, net_cmdline.config().max_backups());\n  ensure_contact_net_entries(callout, net);\n  update_filechange_status_dat(net_cmdline.config().datadir());\n  rename_pending_files(net.dir);\n\n  if (need_to_send_feedback(net_cmdline.cmdline()) || is_nc) {\n    std::ostringstream text;\n    add_feedback_header(net.dir, text);\n    LOG(INFO) << \"Sending Feedback.\";\n    add_feedback_general_info(callout, net, bbsdata_data, text);\n    check_wwivnet_host_networks(net_cmdline.config(), net_cmdline.networks(), b, net_cmdline.network_number(), text);\n\n    if (is_nc) {\n      // We should always send feedback to the NCs.\n      const BinkConfig bink_config(net_cmdline.network_name(), net_cmdline.config(), net_cmdline.networks());\n      check_binkp_net(b, bink_config, text);\n      check_connect_net(b, net, text);\n    }\n    text << \"\\r\\nBest,\\r\\n\\r\\n\" << net.name << \"@\" << net.sysnum << \"\\r\\n\\r\\n\";\n    send_feedback_email(net, text.str());\n    const auto netdatmsg = fmt::format(\"{} Analysis for @{}: {} systems.\", \n      net.name, net.sysnum , num_systems);\n    netdat.add_message(NetDat::netdat_msgtype_t::normal, netdatmsg);\n  }\n  return 0;\n}\n\nint network3_main(const NetworkCommandLine& net_cmdline) {\n  try {\n    const auto& net = net_cmdline.network();\n    update_net_ver_status_dat(net_cmdline.config().datadir());\n\n    if (!File::Exists(net.dir)) {\n      LOG(ERROR) << \"Network directory '\" << net.dir << \"' does not exist.\";\n      LOG(ERROR) << \"Please create it.\";\n      return 1;\n    }\n\n    // Only run the net fido type network3 for 5.x\n    if (net_cmdline.config().is_5xx_or_later() && net.type == network_type_t::ftn) {\n      return network3_fido(net_cmdline);\n    }\n    return network3_wwivnet(net_cmdline);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network]: \" << e.what();\n  }\n  return 2;\n}\n\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.add_argument(BooleanCommandLineArgument(\"feedback\", 'y', \"Sends feedback.\", false));\n  const NetworkCommandLine net_cmdline(cmdline, '3');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n\n  try {\n    auto semaphore = SemaphoreFile::try_acquire(net_cmdline.semaphore_path(),\n                                                net_cmdline.semaphore_timeout());\n    return network3_main(net_cmdline);\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n}\n"
  },
  {
    "path": "networkb/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORKB_MAIN networkb.cpp)\n\nadd_executable(networkb ${NETWORKB_MAIN})\ntarget_link_libraries(networkb binkp_lib net_core core sdk)\nif(UNIX)\n  if(CMAKE_SYSTEM_NAME MATCHES \"SunOS.*\")\n    set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl -lkstat -lssp\")\n  endif()\nendif()\n"
  },
  {
    "path": "networkb/networkb.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"binkp/binkp.h\"\n#include \"binkp/binkp_config.h\"\n#include \"binkp/config_exceptions.h\"\n#include \"binkp/wfile_transfer_file.h\"\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/socket_connection.h\"\n#include \"core/socket_exceptions.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/status.h\"\n#include <chrono>\n#include <csignal>\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nstatic void RegisterNetworkBCommands(CommandLine& cmdline) {\n  cmdline.add_argument(BooleanCommandLineArgument(\"send\", \"Send network traffic to --node\"));\n  cmdline.add_argument(BooleanCommandLineArgument(\"receive\", \"Receive from any node\"));\n  cmdline.add_argument({\"node\", \"Node number (only used when sending)\", \"0\"});\n  cmdline.add_argument({\"handle\", \"Existing socket handle (only used when receiving)\", \"0\"});\n  cmdline.add_argument({\"port\", \"Port number to use (receiving only)\", \"24554\"});\n  cmdline.add_argument(BooleanCommandLineArgument(\n      \"daemon\", \"Run continually as a daemon until stopped  (only used when receiving)\", true));\n}\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nstatic bool Receive(const CommandLine& cmdline, BinkConfig& bink_config, int port) {\n  auto side = BinkSide::ANSWERING;\n  auto loop = false;\n  auto sock = INVALID_SOCKET;\n  auto socket_connected = false;\n  if (cmdline.iarg(\"handle\")) {\n    sock = static_cast<SOCKET>(cmdline.iarg(\"handle\"));\n    LOG(INFO) << \"BinkP receive; existing socket; handle: \" << sock;\n    socket_connected = true;\n  } else {\n    sock = CreateListenSocket(port);\n    loop = cmdline.barg(\"daemon\");\n  }\n\n  do {  // NOLINT(bugprone-infinite-loop)\n    try {\n      if (const auto ip = GetRemotePeerAddress(sock)) {\n        LOG(INFO) << \"Received connection from: \" << ip.value();\n      }\n      std::unique_ptr<SocketConnection> c;\n      if (socket_connected) {\n        c = std::make_unique<SocketConnection>(sock);\n      } else {\n        LOG(INFO) << \"BinkP receive; listening on port: \" << port;\n        sockaddr_in saddr{};\n        socklen_t addr_length = sizeof(saddr);\n        auto s = accept(sock, reinterpret_cast<struct sockaddr*>(&saddr), &addr_length);\n        c = std::make_unique<SocketConnection>(s);\n      }\n      BinkP::received_transfer_file_factory_t factory = [&](const std::string& network_name,\n                                                            const std::string& filename) {\n        const auto dir = bink_config.receive_dir(network_name);\n        return new WFileTransferFile(filename, std::make_unique<File>(FilePath(dir, filename)));\n      };\n      BinkP binkp(c.get(), &bink_config, side, \"0\", factory);\n      binkp.Run(cmdline);\n    } catch (const connection_error& e) {\n      LOG(ERROR) << \"CONNECTION ERROR: [networkb]: \" << e.what();\n    } catch (const socket_error& e) {\n      LOG(ERROR) << \"SOCKET ERROR: [networkb]: \" << e.what();\n    } catch (const std::exception& e) {\n      LOG(ERROR) << \"ERROR: [networkb]: \" << e.what();\n    }\n  } while (loop);\n  return true;\n}\n\nstatic bool Send(const CommandLine& cmdline, BinkConfig& bink_config, const std::string& sendto_node,\n                 const std::string& network_name) {\n  LOG(INFO) << \"BinkP send to: \" << sendto_node;\n  const auto start_time = system_clock::now();\n\n  auto* node_config = bink_config.binkp_session_config_for(sendto_node);\n  if (node_config == nullptr) {\n    LOG(ERROR) << \"Unable to find node config for node: \" << sendto_node;\n    return false;\n  }\n  std::unique_ptr<SocketConnection> c;\n  try {\n    c = Connect(node_config->host, node_config->port);\n  } catch (const connection_error& e) {\n    LOG(ERROR) << \"Recording failure: '\" << e.what() << \"'\";\n    const auto& net = bink_config.networks()[network_name];\n    Contact contact(net, true);\n\n    auto dt = DateTime::from_time_t(system_clock::to_time_t(start_time));\n    if (net.type == network_type_t::wwivnet) {\n      auto wwivnet_node = to_number<int>(sendto_node);\n      contact.add_failure(wwivnet_node, dt);\n    } else {\n      contact.add_failure(sendto_node, dt);\n    }\n\n    throw;\n  }\n\n  const auto& net = bink_config.networks()[network_name];\n  BinkP::received_transfer_file_factory_t factory = [&](const std::string&, const std::string& filename) {\n    const auto dir = bink_config.receive_dir(network_name);\n    return new WFileTransferFile(filename, std::make_unique<File>(FilePath(dir, filename)));\n  };\n\n  std::string sendto_ftn_node;\n  if (net.type == network_type_t::wwivnet) {\n    sendto_ftn_node = StrCat(\"20000:20000/\", sendto_node, \"@\", network_name);\n  } else if (net.type == network_type_t::ftn) {\n    sendto_ftn_node = sendto_node;\n  } else {\n    throw config_error(\"BinkP only supports wwivnet or ftn networks.\");\n  }\n  BinkP binkp(c.get(), &bink_config, BinkSide::ORIGINATING, sendto_ftn_node, factory);\n  binkp.Run(cmdline);\n  return true;\n}\n\nstatic int Main(const NetworkCommandLine& net_cmdline) {\n  try {\n    [[maybe_unused]] static bool initialized = wwiv::core::InitializeSockets();\n\n    const auto port = net_cmdline.cmdline().iarg(\"port\");\n    const auto skip_net = net_cmdline.skip_net();\n\n    StatusMgr sm(net_cmdline.config().datadir(), [](int) {});\n    const auto status = sm.get_status();\n\n    const auto& network_name = net_cmdline.network_name();\n\n    const auto sendto_node = net_cmdline.cmdline().sarg(\"node\");\n    BinkConfig bink_config(network_name, net_cmdline.config(), net_cmdline.networks());\n\n    bink_config.set_skip_net(skip_net);\n    bink_config.set_verbose(net_cmdline.cmdline().verbose());\n    bink_config.set_network_version(status->status_net_version());\n\n    for (const auto& n : bink_config.networks().networks()) {\n      auto domain = ToStringLowerCase(n.name);\n      if (n.type == network_type_t::wwivnet) {\n        auto c = std::make_unique<Callout>(n, bink_config.config().max_backups());\n        for (const auto& kv : c->callout_config()) {\n          if (const auto o = try_parse_fidoaddr(fmt::format(\"20000:20000/{}@{}\", kv.first, domain))) {\n            bink_config.address_pw_map.try_emplace(o.value(), kv.second.session_password);\n          }\n        }\n        bink_config.callouts()[domain] = std::move(c);\n      } else if (n.type == network_type_t::ftn && net_cmdline.config().is_5xx_or_later()) {\n        if (auto o = try_parse_fidoaddr(n.fido.fido_address)) {\n          if (o->has_domain()) {\n            domain = o->domain();\n          } else {\n            LOG(ERROR) << \"Domain is empty for FTN address. Please set it for: \"\n                       << n.fido.fido_address;\n          }\n          auto c = std::make_unique<FidoCallout>(net_cmdline.config().root_directory(),\n                                                 net_cmdline.config().max_backups(), n);\n          for (const auto& kv : c->node_configs_map()) {\n            bink_config.address_pw_map.try_emplace(kv.first, kv.second.binkp_config.password);\n          }\n          VLOG(1) << \"Adding FidoCallout for network domain: \" << domain;\n          bink_config.callouts()[domain] = std::move(c);\n        } else {\n          LOG(WARNING) << \"Unable to parse FTN Address for network: \" << n.name;\n          LOG(WARNING) << \"Address: \" << n.fido.fido_address;\n        }\n      }\n    }\n\n    if (net_cmdline.cmdline().barg(\"receive\")) {\n      Receive(net_cmdline.cmdline(), bink_config, port);\n    } else if (net_cmdline.cmdline().barg(\"send\")) {\n      if (Send(net_cmdline.cmdline(), bink_config, sendto_node, network_name)) {\n        VLOG(1) << \"Normal Exit\";\n        return 0;\n      }\n      return 1;\n    } else {\n      ShowHelp(net_cmdline);\n      return 1;\n    }\n  } catch (const connection_error& e) {\n    LOG(ERROR) << \"CONNECTION ERROR: [networkb]: \" << e.what();\n  } catch (const socket_error& e) {\n    LOG(ERROR) << \"SOCKET ERROR: [networkb]: \" << e.what();\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [networkb]: \" << e.what();\n  } catch (...) {\n    LOG(ERROR) << \"ERROR: [networkb]: (Unknown)\";\n  }\n  return 0;\n}\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n\n#ifdef __unix__\n  // Let the socket library handle EPIPE\n  signal(SIGPIPE, SIG_IGN);\n#endif // __unix__\n\n  CommandLine cmdline(argc, argv, \"net\");\n  RegisterNetworkBCommands(cmdline);\n  const NetworkCommandLine net_cmdline(cmdline, 'b');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n  try {\n    auto semaphore = SemaphoreFile::try_acquire(net_cmdline.semaphore_path(),\n                                                net_cmdline.semaphore_timeout());\n    return Main(net_cmdline);\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n    return 3;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught uncaught exception: \" << e.what();\n    return 2;\n  } catch (...) {\n    LOG(ERROR) << \"Caught uncaught throwable that doesn't extend std::exception: \";\n    return 1;\n  }\n}\n"
  },
  {
    "path": "networkc/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN networkc.cpp)\n\nadd_executable(networkc ${NETWORK_MAIN})\nset_max_warnings(networkc)\ntarget_link_libraries(networkc binkp_lib net_core core sdk)\n\n"
  },
  {
    "path": "networkc/networkc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 NetworkC\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/status.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/packets.h\"\n\n#include <cstdlib>\n#include <ctime>\n#include <iostream>\n#include <memory>\n#include <sstream>\n#include <string>\n\n#ifndef _WIN32\n#include <signal.h>\n#endif // _WIN32\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk::fido;\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\n\nstatic void rename_bbs_instance_files(const std::filesystem::path& dir, int instance_number, bool quiet) {\n  const auto pattern = fmt::sprintf(\"p*.%03d\", instance_number);\n  LOG_IF(!quiet, INFO) << \"Processing pending bbs instance files: '\" << pattern << \"'\";\n  FindFiles ff(FilePath(dir, pattern), FindFiles::FindFilesType::files);\n  for (const auto& f : ff) {\n    rename_pend(dir, f.name, 'c');\n  }\n}\n\nstd::string create_network_cmdline(const NetworkCommandLine& net_cmdline, char num, const std::string& cmd) {\n  const auto path = FilePath(net_cmdline.cmdline().bindir(), StrCat(\"network\", num));\n\n  std::ostringstream ss;\n  ss << path;\n#ifdef _WIN32\n  ss << \".exe\";\n#endif\n  ss << \" --v=\" << net_cmdline.cmdline().verbose();\n  if (net_cmdline.quiet()) {\n    ss << \" --quiet\";\n  }\n  ss << \" --bbsdir=\" << net_cmdline.cmdline().bbsdir();\n  ss << \" --bindir=\" << net_cmdline.cmdline().bindir();\n  ss << \" --configdir=\" << net_cmdline.cmdline().configdir();\n  ss << \" .\" << net_cmdline.network_number();\n  if (num == '3') {\n    ss << \" Y\";\n  }\n  if (!cmd.empty()) {\n    ss << \" \" << cmd;\n  }\n  return ss.str();\n}\n\nstatic int System(const std::string& cmd) {\n  VLOG(1) << \"Command: \" << cmd;\n  return system(cmd.c_str());\n}\n\nstatic bool checkup2(const time_t tFileTime, const std::filesystem::path& dir, const std::string& filename) {\n  const auto fn = FilePath(dir, filename);\n  File file(fn);\n\n  if (file.Open(File::modeReadOnly)) {\n    const auto tNewFileTime = File::last_write_time(fn);\n    return tNewFileTime > tFileTime + 2;\n  }\n  return true;\n}\n\nstatic bool need_network3(const Network& net, int network_version) {\n  const auto dir = net.dir;\n\n  if (!File::Exists(FilePath(dir, BBSDATA_NET))) {\n    return true;\n  }\n\n  if (net.type == network_type_t::ftn) {\n    // Since network3 writes out these files from memory for FTN networks, if\n    // they don't exist then we need to run it.\n    if (!File::Exists(FilePath(dir, BBSDATA_IND))) {\n      return true;\n    }\n    if (!File::Exists(FilePath(dir, BBSDATA_REG))) {\n      return true;\n    }\n    if (!File::Exists(FilePath(dir, BBSDATA_ROU))) {\n      return true;\n    }\n  }\n  if (!File::Exists(FilePath(dir, BBSLIST_NET))) {\n    return false;\n  }\n  if (!File::Exists(FilePath(dir, CONNECT_NET))) {\n    return false;\n  }\n  if (!File::Exists(FilePath(dir, CALLOUT_NET))) {\n    return false;\n  }\n\n  if (network_version != wwiv_network_compatible_version()) {\n    // always need network3 if the versions do not match.\n    LOG(INFO) << \"Need to run network3 since current network_version: \" << network_version\n              << \" != our network_version: \" << wwiv_network_compatible_version();\n    return true;\n  }\n  File bbsdataNet(FilePath(dir, BBSDATA_NET));\n  if (!bbsdataNet.Open(File::modeReadOnly)) {\n    return false;\n  }\n\n  const auto bbsdata_time = bbsdataNet.last_write_time();\n  bbsdataNet.Close();\n\n  return checkup2(bbsdata_time, dir, BBSLIST_NET) || checkup2(bbsdata_time, dir, CONNECT_NET) ||\n         checkup2(bbsdata_time, dir, CALLOUT_NET);\n}\n\nint networkc_main(const NetworkCommandLine& net_cmdline) {\n#ifndef _WIN32\n  // Set this to the default handling, since when wwivd invokes\n  // this (and wwivd ignores SIGCHLD).\n  signal(SIGCHLD, SIG_DFL);\n#endif // !_WIN32\n\n  try {\n    const auto process_instance = net_cmdline.cmdline().iarg(\"process_instance\");\n    const auto& net = net_cmdline.network();\n\n    StatusMgr sm(net_cmdline.config().datadir(), [](int) {});\n    const auto status = sm.get_status();\n\n    auto num_tries = 0;\n    bool found;\n    do {\n      found = false;\n      if (process_instance > 0) {\n        VLOG(1) << \"Processing instance for #\" << process_instance << \"; net: \" << net.dir;\n        // We need to process pending bbs instance file, these are\n        // of the form p1.###.  These will get renamed into p*.net\n        rename_bbs_instance_files(net.dir, process_instance, net_cmdline.quiet());\n      }\n\n      // Pending files, call network1 to put them into s* or local.net.\n      if (File::ExistsWildcard(FilePath(net.dir, \"p*.net\"))) {\n        VLOG(2) << \"Found p*.net\";\n        System(create_network_cmdline(net_cmdline, '1', \"\"));\n        found = true;\n      }\n\n      // If the network type is a FTN network.\n      if (net.type == network_type_t::ftn) {\n        FtnDirectories dirs(net_cmdline.config().root_directory(), net);\n        // Import everything into local.net\n        if (File::ExistsWildcard(FilePath(dirs.inbound_dir(), \"*.*\"))) {\n          VLOG(2) << \"Trying to FTN import\";\n          System(create_network_cmdline(net_cmdline, 'f', \"import\"));\n        }\n\n        // Check to see if TIC files exist.\n        const auto process_tic = net.fido.process_tic;\n        const auto tic_file_exist = File::ExistsWildcard(FilePath(dirs.tic_dir(), \"*.tic\"));\n        if (process_tic && tic_file_exist) {\n          VLOG(2) << \"Trying to process TIC files\";\n          System(create_network_cmdline(net_cmdline, 't', \"\"));\n        }\n\n        if (exists_bundle(net_cmdline.config(), net)) {\n          VLOG(2) << \"Trying to FTN export\";\n          System(create_network_cmdline(net_cmdline, 'f', \"export\"));\n        }\n\n        // Export everything to FTN bundles\n        const auto fido_out = StrCat(\"s\", FTN_FAKE_OUTBOUND_NODE, \".net\");\n        if (File::Exists(FilePath(net.dir, fido_out))) {\n          VLOG(2) << \"Found s\" << FTN_FAKE_OUTBOUND_NODE << \".net; trying to export\";\n          System(create_network_cmdline(net_cmdline, 'f', \"export\"));\n        }\n      }\n\n      // Process local mail with network2.\n      if (File::Exists(FilePath(net.dir, LOCAL_NET))) {\n        VLOG(2) << \"Found: \" << LOCAL_NET;\n        System(create_network_cmdline(net_cmdline, '2', \"\"));\n        found = true;\n      }\n\n      // If our network files have changed, run network3 and send feedback.\n      if (need_network3(net, status->status_net_version())) {\n        VLOG(2) << \"Need to run network3\";\n        System(create_network_cmdline(net_cmdline, '3', \"\"));\n        found = true;\n      }\n    } while (found && ++num_tries < 3);\n\n    return 0;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd() << \"]: \" << e.what();\n  }\n  return 2;\n}\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.add_argument({\"process_instance\", \"Also process pending files for BBS instance #\", \"0\"});\n\n  const NetworkCommandLine net_cmdline(cmdline, 'c');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n  try {\n    auto semaphore = SemaphoreFile::try_acquire(net_cmdline.semaphore_path(),\n                                                net_cmdline.semaphore_timeout());\n    return networkc_main(net_cmdline);\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n}"
  },
  {
    "path": "networkf/CMakeLists.txt",
    "content": "# CMake for WWIV NetworkF\n\n\nadd_library(networkf_lib networkf.cpp)\nset_max_warnings(networkf_lib)\ntarget_link_libraries(networkf_lib binkp_lib net_core core sdk fmt::fmt-header-only)\n\nadd_executable(networkf networkf_main.cpp)\ntarget_link_libraries(networkf networkf_lib)\n\n## Tests\nif (WWIV_BUILD_TESTS)\n\n  set(networkf_test_sources\n    networkf_test.cpp\n    networkf_test_main.cpp\n  )\n\n  add_executable(networkf_tests ${networkf_test_sources})\n  set_max_warnings(networkf_tests)\n  target_link_libraries(networkf_tests net_core core_fixtures GTest::gtest sdk sdk_fixtures networkf_lib)\n\n  gtest_discover_tests(networkf_tests)\n\nendif()\n"
  },
  {
    "path": "networkf/networkf.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"networkf/networkf.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/arc.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/net/subscribers.h\"\n#include <cstdlib>\n#include <ctime>\n#include <iostream>\n#include <memory>\n#include <set>\n#include <sstream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::net::networkf {\n\n\nstatic std::string arc_stuff_in(const std::string& command_line, const std::string& a1,\n                                const std::string& a2) {\n  std::ostringstream os;\n  for (auto it = command_line.begin(); it != command_line.end(); ++it) {\n    if (*it == '%') {\n      ++it;\n      switch (*it) {\n      case '%':\n        os << \"%\";\n        break;\n      case '1':\n        os << a1;\n        break;\n      case '2':\n        os << a2;\n        break;\n      }\n    } else {\n      os << *it;\n    }\n  }\n  return os.str();\n}\n\nvoid ShowNetworkfHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl\n       << \"commands: \" << std::endl\n       << std::endl\n       << \" import    Import messages from FTN Packet to WWIV (P*.net_)\" << std::endl\n       << \" export    Export messages from WWIV (p*.net_) to FTN packet\" << std::endl\n       << std::endl;\n\n  exit(1);\n}\n\nstatic std::string get_echomail_areaname(const std::string& text) {\n  auto lines = split_message(text);\n  for (const auto& line : lines) {\n    if (starts_with(line, \"AREA:\")) {\n      return line.substr(5);\n    }\n  }\n  return \"\";\n}\n\nNetworkF::NetworkF(const sdk::BbsDirectories& bbsdirs, const networkf_options_t& opts,\n                   const sdk::net::Network net, const sdk::BbsListNet& bbslist, core::Clock& clock)\n    : bbslist_(bbslist), clock_(clock), net_(net),\n      fido_callout_(bbsdirs.root_directory(), opts.max_backups, net_),\n      netdat_(bbsdirs.gfilesdir(), bbsdirs.logdir(), net_, opts.net_cmd, clock_),\n      dirs_(bbsdirs.root_directory(), net_), opts_(opts), datadir_(bbsdirs.datadir()) {\n  const IniFile ini(FilePath(bbsdirs.root_directory(), WWIV_INI), \"WWIV\");\n  if (ini.IsOpen()) {\n    // pull out new user colors\n    for (auto i = 0; i < 10; i++) {\n      const auto num = ini.value<int>(fmt::format(\"NUCOLOR[{}]\", i));\n      if (num != 0) {\n        colors_[i] = num;\n      }\n    }\n  }\n}\n\nNetworkF::~NetworkF() = default;\n\nint ftn_date_days_old(const Clock& clock, const std::string& ftn_date) {\n  const auto daten = fido_to_daten(ftn_date);\n  const auto pkt_dt = DateTime::from_daten(daten).to_system_clock();\n  const auto now = clock.Now().to_system_clock();\n  // TODO(rushfan): C++20 is needed for std::chrono::days\n  const auto diff_hours = std::chrono::duration_cast<std::chrono::hours>(now - pkt_dt).count();\n  const auto days = diff_hours / 24;\n  return days;\n}\n\nbool NetworkF::import_packet_file(const std::filesystem::path& path) {\n  LOG(INFO) << \"Importing Packet: \" << path.string();\n  auto o = FidoPacket::Open(path);\n  if (!o) {\n    LOG(INFO) << \"Unable to open file: \" << path.string();\n    return false;\n  }\n  auto& packet = o.value();\n\n  FidoAddress address(packet.header().orig_zone, packet.header().orig_net,\n                      packet.header().orig_node, packet.header().orig_point, \"\");\n  const auto expected = ToStringUpperCase(fido_callout_.packet_config_for(address).packet_password);\n  const auto actual = packet.password();\n  if (!iequals(expected, actual)) {\n    LOG(ERROR) << \"Unexpected packet password from node: \" << address << \"; actual: '\" << actual\n               << \"'; expected: '\" << expected << \"'\";\n    // Move to BADMSGS\n    packet.Close();\n    const auto bad_messages_paath = FilePath(dirs_.bad_packets_dir(), path.filename().string());\n\n    if (!File::Move(path, bad_messages_paath)) {\n      LOG(ERROR) << \"Error moving file to BADMSGS; file: \" << path.string();\n    }\n    return false;\n  }\n\n  while (true) {\n    auto [response, msg] = packet.Read();\n    if (response != ReadNetPacketResponse::OK) {\n      return true;\n    }\n\n    const auto is_email = (msg.nh.attribute & MSGPRIVATE) != 0;\n    if (!is_email) {\n\n      // Only check age for echomail, not email\n      const auto max_days = net().fido.max_echomail_age_days;\n      if (!is_email && max_days > 0) {\n        // Only check if max_days > 0, otherwise 0 means unlimited.\n        const auto days_old = ftn_date_days_old(clock_, msg.vh.date_time);\n        if (days_old > max_days) {\n          // Packet is too old, skip it.\n          const auto msgid = FtnMessageDupe::GetMessageIDFromText(msg.vh.text);\n          const auto logmsg = fmt::format(\"Too old FTN message ({} days): msgid:{}; '{}'\", days_old,\n            msgid, msg.vh.subject);\n          LOG(ERROR) << logmsg;\n          LOG(ERROR) << \"Text: \" << msg.vh.text;\n          // TODO(rushfan): move this or write out saved copy?\n          continue;\n        }\n      }\n\n\n      // Don't check for dupes in emails since we certainly won't have a MSGID and also\n      // likely the header may match for automated responses split over multiple messages (#1395)\n      if (dupe().is_dupe(msg)) {\n        const auto msgid = FtnMessageDupe::GetMessageIDFromText(msg.vh.text);\n        LOG(ERROR) << \"Skipping duplicate FTN message: '\" << msg.vh.subject << \"' msgid: (\" << msgid\n                   << \")\";\n        LOG(ERROR) << \"Text: \" << msg.vh.text;\n        // TODO(rushfan): move this or write out saved copy?\n        continue;\n      }\n      dupe().add(msg);\n    }\n\n    const auto ftn_packet_daten = fido_to_daten(msg.vh.date_time);\n    net_header_rec nh{};\n    nh.daten = static_cast<uint32_t>(ftn_packet_daten);\n    nh.fromsys = FTN_FAKE_OUTBOUND_NODE;\n    nh.fromuser = 0;\n    nh.list_len = 0;\n    if (is_email) {\n      nh.main_type = main_type_email_name;\n    } else {\n      nh.main_type = main_type_new_post;\n    }\n\n    nh.method = 0;\n    nh.minor_type = 0;\n    nh.tosys = 1; // always 1 in new fido\n    nh.touser = 0;\n\n    auto from_address = get_address_from_packet(msg, packet.header());\n\n    std::string s1;\n    // Email Format: TO_USER<nul>TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n    // Non-Email Sub Format: SUBTYPE<nul>TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n    std::string text = (is_email) ? msg.vh.to_user_name : get_echomail_areaname(msg.vh.text);\n    // Adding a 0 is adding a NULL character to the string\n    text.push_back(0);\n    text.append(msg.vh.subject);\n    text.push_back(0);\n    text.append(StrCat(msg.vh.from_user_name, \" (\", from_address, \")\\r\\n\"));\n    text.append(daten_to_wwivnet_time(ftn_packet_daten));\n    text.append(\"\\r\\n\");\n\n    if (!is_email) {\n      // Add ^D0FidoAddr for the \"To:\" name of the post.\n      static const char kFidoAddr[] = \"\\x04\"\n                                      \"0FidoAddr: \";\n      const auto to_name = msg.vh.to_user_name.empty() ? \"All\" : msg.vh.to_user_name;\n      // If for some screwy reason we don't have a to name, address it to 'All'.\n      text.append(kFidoAddr).append(to_name).append(\"\\r\\n\");\n    }\n    text.append(FidoToWWIVText(msg.vh.text));\n\n    nh.length = size_uint32(text);\n    // Create file, write to local.net_ for network2 to import.\n    NetPacket wwiv_packet(nh, {}, text);\n    if (!write_wwivnet_packet(FilePath(net_.dir, LOCAL_NET), wwiv_packet)) {\n      LOG(ERROR) << \"ERROR Writing WWIV packet for message: \" << wwiv_packet.nh.main_type << \"/\"\n                 << wwiv_packet.nh.minor_type;\n    } else {\n      std::string itype = is_email ? \"Email\" : \"Post\";\n      LOG(INFO) << fmt::format(\"Imported FTN {} '{}' to '{}'\", itype, msg.vh.subject, s1);\n    }\n  }\n\n  return true;\n}\n\nbool NetworkF::import_packets(const std::filesystem::path& dir, const std::string& mask) {\n  VLOG(1) << \"Importing packets from: \" << dir << \"' mask: '\" << mask << \"'\";\n  FindFiles files(FilePath(dir, mask), FindFiles::FindFilesType::files);\n  if (files.empty()) {\n    LOG(INFO) << \"No packets to import in: '\" << dir << \"' mask: '\" << mask << \"'\";\n  }\n  for (const auto& f : files) {\n    if (import_packet_file(FilePath(dir, f.name))) {\n      LOG(INFO) << \"Successfully imported packet: \" << FilePath(dir, f.name);\n      if (opts_.skip_delete) {\n        backup_file(FilePath(net_.dir, f.name));\n      }\n      File::Remove(FilePath(dir, f.name));\n    }\n  }\n  return true;\n}\n\nbool NetworkF::import_bundle_file(const std::filesystem::path& path) {\n  VLOG(1) << \"import_bundle_file: path: \" << path.string();\n\n  {\n    // Check to make sure the file is readable.\n    File f(path);\n    if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n      LOG(INFO) << \"Unable to open file: \" << path.string();\n      return false;\n    }\n  }\n\n  const auto saved_dir = File::current_directory();\n  auto at_exit = finally([=] { File::set_current_directory(saved_dir); });\n  File::set_current_directory(dirs_.temp_inbound_dir());\n\n  // were in the temp dir now.\n  const auto arcs = files::read_arcs(datadir_);\n  if (arcs.empty()) {\n    LOG(ERROR) << \"No archivers defined!\";\n    return false;\n  }\n\n  const auto arc = files::find_arcrec(arcs, path, \"ZIP\");\n  if (!arc) {\n    LOG(ERROR) << \"Unable to find archiver for file: \" << path;\n    return false;\n  }\n  // We have no parameter 2 since we're extracting everything.\n  const auto unzip_cmd = arc_stuff_in(arc.value().arce, path.string(), \"\");\n  // Execute the command\n  LOG(INFO) << \"Command: \" << unzip_cmd;\n  if (system(unzip_cmd.c_str()) != 0) {\n    LOG(ERROR) << \"Failed executing: \" << unzip_cmd;\n    return false;\n  }\n  // Need to be back home.\n  File::set_current_directory(saved_dir);\n\n  import_packets(dirs_.temp_inbound_dir(), \"*.pkt\");\n  return true;\n}\n\n/**\n * Imports FTN Bundles (files like XXXXXXXXX.SU0)\n *\n * Returns the # of bundles processed.\n */\nint NetworkF::import_bundles(const std::filesystem::path& dir, const std::string& mask) {\n  auto num_bundles_processed = 0;\n\n  VLOG(3) << \"import_bundles: mask: \" << mask;\n  FindFiles files(FilePath(dir, mask), FindFiles::FindFilesType::files);\n  for (const auto& f : files) {\n    if (f.size == 0) {\n      // skip zero byte files.\n      LOG(INFO) << \"Skipping zero byte bundle or packet: \" << f.name;\n      continue;\n    }\n    const auto lname = ToStringLowerCase(f.name);\n    const auto path = FilePath(dir, f.name);\n    LOG(INFO) << \"Attempting to import packet: \" << path;\n    if (ends_with(lname, \".pkt\")) {\n      if (import_packet_file(path)) {\n        LOG(INFO) << \"Successfully imported packet: \" << path;\n        ++num_bundles_processed;\n        if (opts_.skip_delete) {\n          backup_file(path);\n        }\n        File::Remove(path);\n      }\n    } else if (import_bundle_file(path)) {\n      LOG(INFO) << \"Successfully imported bundle: \" << path;\n      ++num_bundles_processed;\n      if (opts_.skip_delete) {\n        backup_file(path);\n      }\n      File::Remove(path);\n    }\n  }\n  return num_bundles_processed;\n}\n\nstatic std::string rename_fido_packet(const std::filesystem::path& dir, const std::string& origname) {\n  if (!ends_with(origname, \".pkt\") || origname.size() != 12) {\n    LOG(ERROR) << \"rename_fido_packet: not allowed on name: '\" << origname << \"'\";\n    return origname;\n  }\n  auto base = origname.substr(0, 8);\n  for (auto i = 0; i < 26; i++) {\n    base.pop_back();\n    base.push_back(static_cast<char>('a' + i));\n    auto newname = base + \".pkt\";\n    if (!File::Exists(FilePath(dir, newname))) {\n      return newname;\n    }\n  }\n  return origname;\n}\n\nstd::optional<std::string> NetworkF::create_ftn_bundle(const FidoAddress& route_to,\n                                                       const std::string& fido_packet_name) {\n  // were in the temp dir now.\n  auto arcs = files::read_arcs(datadir_);\n  if (arcs.empty()) {\n    LOG(ERROR) << \"No archivers defined!\";\n    return std::nullopt;\n  }\n  const auto now = clock_.Now();\n  const auto dow = now.dow();\n\n  const auto saved_dir = File::current_directory();\n  auto at_exit = finally([=] { File::set_current_directory(saved_dir); });\n\n  const auto ctype = fido_callout_.packet_config_for(route_to).compression_type;\n\n  if (ctype == \"PKT\") {\n    // No bundles, only packet files.\n    const auto in = FilePath(dirs_.temp_outbound_dir(), fido_packet_name);\n    auto out = FilePath(dirs_.outbound_dir(), fido_packet_name);\n    if (File::Exists(out)) {\n      LOG(INFO) << \"Outbound dir already has a packet named: \" << fido_packet_name;\n      const auto newname = rename_fido_packet(dirs_.outbound_dir(), fido_packet_name);\n      LOG(INFO) << \"Renamed to: \" << newname;\n      out = FilePath(dirs_.outbound_dir(), newname);\n    }\n    if (!File::Move(in, out)) {\n      LOG(ERROR) << \"Unable to move packet file into outbound dir. file: \" << fido_packet_name;\n      return std::nullopt;\n    }\n    LOG(INFO) << \"Created bundle(packet): \" << FilePath(dirs_.outbound_dir(), fido_packet_name);\n    return fido_packet_name;\n  }\n\n  FidoAddress orig(net_.fido.fido_address);\n  for (auto i = 0; i < 35; i++) {\n    const auto bname = bundle_name(orig, route_to, dow, i);\n    const auto full_bundle_path = FilePath(dirs_.outbound_dir(), bname);\n    if (File::Exists(full_bundle_path)) {\n      // Already exists.\n      VLOG(1) << \"Skipping candidate bundle: \" << full_bundle_path.string();\n      continue;\n    }\n    // We should actually change to the temp outbound dir so that we won't add paths.\n    File::set_current_directory(dirs_.temp_outbound_dir());\n    LOG(INFO) << \"Changed directory to: \" << dirs_.temp_outbound_dir();\n    // Use ZIP by default if we can't find anything that matches, then we'll hope for the best.\n    const auto arc = files::find_arcrec(arcs, ctype, \"ZIP\"); \n    if (!arc) {\n      LOG(WARNING) << \"Skipping candidate bundle. Unable to find archiver for type: '\" << ctype\n                   << \"'\";\n      continue;\n    }\n    const auto zip_cmd = arc_stuff_in(arc->arca, full_bundle_path.string(), fido_packet_name);\n    LOG(INFO) << \"Command: \" << zip_cmd;\n    if (0 != system(zip_cmd.c_str())) {\n      LOG(ERROR) << \"Failed executing: \" << zip_cmd;\n      return std::nullopt;\n    }\n    // Need to be back home.\n    LOG(INFO) << \"Changed directory back to: \" << saved_dir;\n    File::set_current_directory(saved_dir);\n\n    LOG(INFO) << \"Created bundle: \" << full_bundle_path.string();\n    if (!File::Remove(FilePath(dirs_.temp_outbound_dir(), fido_packet_name))) {\n      LOG(ERROR) << \"Error removing packet: \"\n                 << FilePath(dirs_.temp_outbound_dir(), fido_packet_name);\n    }\n    return bname;\n  }\n  return std::nullopt;\n}\n\nstatic bool CleanupWWIVName(std::string& sender_name) {\n  // #NN, @NODE or (FIDO_ADDR)\n  const auto idx = sender_name.find_first_of(\"#@(\");\n  if (idx != std::string::npos) {\n    sender_name = sender_name.substr(0, idx);\n  }\n  StringTrim(&sender_name);\n  return true;\n}\n\ntemplate <typename C, typename I>\nstatic std::string get_control_line(const C& c, I& iter, std::set<char> stop, std::size_t max) {\n  // No need to continue if we're already at the end.\n  if (iter == c.end()) {\n    return \"\";\n  }\n  if (*iter != '\\004') {\n    // #4 is control-D and a WWIV control line.\n    return \"\";\n  }\n  return get_message_field(c, iter, stop, max);\n}\n\ntemplate <typename C, typename I>\nstatic std::string get_fido_addr(const C& c, I& iter, std::set<char> stop, std::size_t max) {\n  static const std::string kFidoAddr = \"\\x04\"\n                                       \"0FidoAddr: \";\n  std::string address;\n  do {\n    address = get_control_line(c, iter, stop, max);\n    if (address.empty()) {\n      return \"\";\n    }\n    if (address.front() != '\\004') {\n      // Bail if we have a non-control line.\n      return \"\";\n    }\n    // HACK until the double \\004 in wwiv has been out in 5.2\n    // for a while (fixed 2016-11-22).  Let's leave this here until\n    // 5.2 is GA since some may use net52 with wwiv51.\n    if (address.size() > 2 && address[1] == '\\004') {\n      address.erase(address.begin());\n    }\n    if (starts_with(address, kFidoAddr)) {\n      // This is the address line.\n      return address.substr(kFidoAddr.size());\n    }\n  } while (!address.empty());\n  return \"\";\n}\n\ntemplate <typename C, typename I>\nstatic bool iter_starts_with(const C& c, I& iter, const std::string& expected) {\n  for (const auto& ch : expected) {\n    if (iter == c.end()) {\n      return false;\n    }\n    if (*iter != ch) {\n      return false;\n    }\n    ++iter;\n  }\n  return true;\n}\n\n\nstatic std::string remove_fido_addr(std::string to_user) {\n  std::string to_user_new;\n\n  for (auto i = 0; i < ssize(to_user); i++) {\n    if (to_user[i] == '(' || (to_user[i] == ' ' && to_user[i + 1] == '#')) {\n      break;\n    }\n    to_user_new += to_user[i];\n  }\n  return to_user_new;\n}\n\nstd::optional<std::string> NetworkF::create_ftn_packet(const FidoAddress& dest,\n                                                       const FidoAddress& route_to,\n                                                       const NetPacket& wwivnet_packet) {\n\n  VLOG(1) << \"create_ftn_packet: dest: \" << dest << \"; route: \" << route_to;\n\n  FidoAddress from_address(net_.fido.fido_address);\n  std::string pw = fido_callout_.packet_config_for(route_to).packet_password;\n  for (auto tries = 0; tries < 10; tries++) {\n    auto now = clock_.Now().now();\n    File file(FilePath(dirs_.temp_outbound_dir(), packet_name(now)));\n    if (!file.Open(File::modeCreateFile | File::modeExclusive | File::modeReadWrite |\n                       File::modeBinary,\n                   File::shareDenyReadWrite)) {\n      LOG(INFO) << \"Will try again: Unable to create packet file: \" << file;\n      clock_.SleepFor(std::chrono::seconds(1));\n      continue;\n    }\n\n    auto header = CreateType2PlusPacketHeader(from_address, route_to, now, pw);\n\n    if (!write_fido_packet_header(file, header)) {\n      LOG(ERROR) << \"Error writing packet header.\";\n      return std::nullopt;\n    }\n\n    auto is_email = wwivnet_packet.nh.main_type == main_type_email ||\n                    wwivnet_packet.nh.main_type == main_type_email_name;\n    const auto raw_text = wwivnet_packet.text();\n    auto iter = raw_text.cbegin();\n\n    std::string subtype;\n    std::string to_user_name;\n    // or we can put code in for email here??\n\n    if (is_email) {\n      to_user_name = get_message_field(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n      CleanupWWIVName(to_user_name);\n    } else {\n      subtype = get_message_field(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n    }\n    auto title = get_message_field(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n    auto sender_name = get_message_field(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n    auto date_string = get_message_field(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n\n    // TODO(rushfan: These next 2 here should be done differently. We should\n    // split the message here and look for these in all lines.  For the By:\n    // line we just want to remove it since it's useless.\n    if (!is_email) {\n      to_user_name = get_fido_addr(raw_text, iter, {'\\0', '\\r', '\\n'}, 80);\n    }\n\n    if (!is_email && iter_starts_with(raw_text, iter, \"BY: \")) {\n      // Skip BY line.\n      get_message_field(raw_text, iter, {'\\r', '\\n'}, 80);\n    }\n\n    fido_variable_length_header_t vh{};\n    vh.date_time = daten_to_fido(wwivnet_packet.nh.daten);\n    // Clean up sender name.\n    CleanupWWIVName(sender_name);\n    vh.from_user_name = sender_name;\n    vh.subject = title;\n    if (!to_user_name.empty()) {\n      const auto username_only = remove_fido_addr(to_user_name);\n      vh.to_user_name = properize(username_only);\n    } else {\n      vh.to_user_name = \"All\";\n    }\n\n    FtnMessageDupe dupe(datadir_, true);\n    auto msgid = FtnMessageDupe::GetMessageIDFromWWIVText(raw_text);\n    auto needs_msgid = false;\n    if (msgid.empty()) {\n      // Create a new MSGID if the BBS didn't put one in there already.\n      // We'll do this for emails too since Mystic needs this for a proper\n      // reply to address. Otherwise we'd just do it for conference mail.\n      msgid = dupe.CreateMessageID(from_address);\n      needs_msgid = true;\n    }\n\n    // TODO(rushfan): need to add in INTL for netmails, and all that nonsense.\n    // We probably have other stuff we need to add for echomail too.\n    std::ostringstream text;\n    if (is_email) {\n      text << \"\\001\"\n           << \"INTL \" << dest.as_string(false, false) << \" \"\n           << from_address.as_string(false, false) << \"\\r\";\n      if (from_address.point()) {\n        // FMPT (FROM POINT) just has the point address\n        text << \"\\001\" << \"FMPT \" << from_address.point() << \"\\r\";\n      }\n      if (dest.point()) {\n        // TOPT (TO POINT) just has the point address\n        text << \"\\001\" << \"TOPT \" << dest.point() << \"\\r\";\n      }\n    } else {\n      text << \"AREA:\" << subtype << \"\\r\";\n    }\n    // As of 5.3, the PID is added by the BBS software.\n    // text << \"\\001PID: WWIV \" << full_version() << \"\\r\";\n    text << \"\\001TID: WWIV NET\" << full_version() << \"\\r\";\n    if (needs_msgid && !is_email) {\n      text << \"\\001MSGID: \" << msgid << \"\\r\";\n    }\n    // Implement FTS-5003. [http://ftsc.org/docs/fts-5003.001]\n    // All outbound WWIV messages are always CP437.\n    text << \"\\001CHRS: CP437 2\\r\";\n\n    // Implement FRL-1004. [http://ftsc.org/docs/frl-1004.002]\n    text << \"\\001TZUTC: \" << tz_offset_from_utc(clock_.Now()) << \"\\r\";\n\n    // TODO(rushfan): We should rip through the bbs_text here.\n    // and add in any special kludges like ^AREPLY here.\n    // Add the text from the message (as entered from the BBS).\n    wwiv_to_fido_options opts{};\n    opts.colors = colors_;\n    opts.wwiv_heart_color_codes = net_.fido.wwiv_heart_color_codes;\n    opts.wwiv_pipe_color_codes = net_.fido.wwiv_pipe_color_codes;\n    opts.allow_any_pipe_codes = net_.fido.allow_any_pipe_codes;\n    auto bbs_text = WWIVToFidoText(std::string(iter, raw_text.end()), opts);\n    text << bbs_text;\n\n    // Now we need tear + origin lines\n    auto origin_line = net_.fido.origin_line;\n    if (origin_line.empty()) {\n      // default origin line to system name if it doesn't exist.\n      origin_line = opts_.system_name;\n    }\n\n    if (from_address.point() == 0) {\n      text << \"\\r\"\n           << \"--- WWIV \" << full_version() << \"[\" << os_version_string() << \"]\\r\"\n           << \" * Origin: \" << origin_line << \" (\" << to_zone_net_node(from_address) << \")\\r\";\n    } else {\n      text << \"\\r\"\n           << \"--- WWIV \" << full_version() << \"\\r\"\n           << \" * Origin: \" << origin_line << \" (\" << to_zone_net_node_point(from_address) << \")\\r\";\n    }\n    // Finally we need SEEN-BY and PATH lines for routing.\n    if (!is_email) {\n      // TODO(rushfan): Add the nodes we are exporting this to.\n      text << \"SEEN-BY: \" << to_net_node(from_address) << \"\\r\\r\";\n      // Also we need to add a ^APATH: line here, starting with us.\n    }\n\n    vh.text = text.str();\n\n    fido_packed_message_t nh{};\n    nh.message_type = 2;\n    nh.attribute = 0;\n    nh.cost = 0;\n    nh.orig_net = from_address.net();\n    nh.orig_node = from_address.node();\n    nh.dest_net = dest.net();\n    nh.dest_node = dest.node();\n    nh.attribute = MSGLOCAL;\n\n    if (wwivnet_packet.nh.main_type == main_type_email_name) {\n      nh.attribute |= MSGPRIVATE;\n    }\n\n    FidoPackedMessage p(nh, vh);\n    if (!write_packed_message(file, p)) {\n      LOG(ERROR) << \"Error writing packed message.\";\n      return std::nullopt;\n    }\n\n    // Since we wrote the packed message, let's add it to the\n    // duplicate message database if it's a post.\n    if (!is_email) {\n      dupe.add(p);\n    }\n    return file.path().filename().string();\n  }\n  return std::nullopt;\n}\n\nstd::optional<std::string> NetworkF::create_ftn_packet_and_bundle(const FidoAddress& dest,\n                                                                  const FidoAddress& route_to,\n                                                                  NetPacket& p) {\n  LOG(INFO) << \"Creating packet for subscriber: \" << dest << \"; route_to: \" << route_to;\n  // TODO(rushfan): Really this shouldn't go to dead.net since the wwivnet side exported it\n  // already, not really sure what to do here.\n  auto fido_packet_name = create_ftn_packet(dest, route_to, p);\n  if (!fido_packet_name) {\n    LOG(ERROR) << \"    ! ERROR Failed to create FTN packet; writing to dead.net\";\n    write_deadnet_packet(net_.dir, p);\n    return std::nullopt;\n  }\n  LOG(INFO) << \"Created packet: \" << FilePath(dirs_.temp_outbound_dir(), fido_packet_name.value());\n\n  const auto bundlename = create_ftn_bundle(route_to, fido_packet_name.value());\n  if (!bundlename) {\n    LOG(ERROR) << \"    ! ERROR Failed to create FTN bundle; writing to dead.net\";\n    write_deadnet_packet(net_.dir, p);\n    return std::nullopt;\n  }\n  return bundlename;\n}\n\nstatic std::string NextNetmailFilePath(const std::filesystem::path& path) {\n  for (int i = 2; i < 10000; i++) {\n    auto candidate = FilePath(path, StrCat(i, \".msg\"));\n    if (!File::Exists(candidate)) {\n      return candidate.string();\n    }\n  }\n  return \"\";\n}\n\nstatic bool CreateFidoNetAttachNetMail(const FidoAddress& orig, const FidoAddress& dest,\n                                       const std::string& netmail_filename,\n                                       const std::string& bundle_path,\n                                       const fido_packet_config_t& packet_config) {\n  File netmail(netmail_filename);\n  if (!netmail.Open(File::modeBinary | File::modeCreateFile | File::modeExclusive |\n                        File::modeReadWrite,\n                    File::shareDenyReadWrite)) {\n    LOG(ERROR) << \"Unable to open netmail filen: '\" << netmail << \"'\";\n    return false;\n  }\n\n  // FTC-0053 flags\n  std::string flags = \"FLAGS FIL TFS PVT\";\n  fido_stored_message_t h{};\n  h.attribute = (MSGFILE | MSGKILL | MSGLOCAL);\n  const auto& st = packet_config.netmail_status;\n  switch (st) {\n  case fido_bundle_status_t::hold:\n    h.attribute |= MSGHOLD;\n    flags += \" HLD\";\n    break;\n  case fido_bundle_status_t::immediate:\n    h.attribute |= MSGHOLD;\n    flags += \" IMM\";\n    break;\n  case fido_bundle_status_t::direct:\n    h.attribute |= MSGCRASH;\n    flags += \" CRA\";\n    break;\n  case fido_bundle_status_t::crash:\n    h.attribute |= MSGCRASH;\n    flags += \" IMM\";\n    break;\n  case fido_bundle_status_t::unknown:\n  case fido_bundle_status_t::normal: // NOP\n    break;\n  }\n\n  std::string from = StrCat(\"WWIV NET \", full_version());\n  std::string to = \"SYSOP\";\n\n  h.cost = 0;\n  to_char_array(h.date_time, daten_to_fido(time(nullptr)));\n  h.dest_net = dest.net();\n  h.dest_node = dest.node();\n  h.dest_point = dest.point();\n  h.dest_zone = dest.zone();\n  to_char_array(h.from, from);\n  h.next_reply = 0;\n  h.orig_net = orig.net();\n  h.orig_node = orig.node();\n  h.orig_point = orig.point();\n  h.orig_zone = orig.zone();\n  to_char_array(h.subject, bundle_path);\n  to_char_array(h.to, to);\n\n  std::string msgid;\n  std::ostringstream text;\n\n  // FTC-0053 flags\n  text << \"\\001\" << flags << \"\\r\";\n  // FTS-4001 INTL line\n  text << \"\\001\"\n       << \"INTL \" << dest << \" \" << orig << \"\\r\";\n  text << \"\\001PID: WWIV \" << full_version() << \"\\r\"\n       << \"\\001TID: WWIV NET\" << full_version() << \"\\r\";\n  if (!msgid.empty()) {\n    text << \"\\001MSGID: \" << msgid << \"\\r\";\n  }\n\n  FidoStoredMessage m(h, text.str());\n  write_stored_message(netmail, m);\n\n  return true;\n}\n\nstd::optional<std::string> NetworkF::CreateFloFile(const wwiv::sdk::fido::FidoAddress& dest,\n                                                   const std::string& bundlename,\n                                                   const fido_packet_config_t& packet_config) {\n  FidoAddress orig(net_.fido.fido_address);\n  const auto floname = flo_name(dest, packet_config.netmail_status);\n  const auto bsyname = net_node_name(dest, \"bsy\");\n\n  try {\n    auto sem_file = SemaphoreFile::try_acquire(bsyname, std::chrono::seconds(15));\n\n    TextFile flo_file(FilePath(dirs_.outbound_dir(), floname), \"a+\");\n    if (!flo_file.IsOpen()) {\n      LOG(ERROR) << \"Unable to open FLO file: \" << flo_file;\n      return std::nullopt;\n    }\n    const auto num_written =\n        flo_file.WriteLine(StrCat(\"^\", FilePath(dirs_.outbound_dir(), bundlename).string()));\n    return num_written == 0 ? std::nullopt : std::make_optional(flo_file.full_pathname());\n\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"Unable to create BSY file semaphore trying to create FLO file.\";\n    LOG(ERROR) << e.what();\n  }\n  return std::nullopt;\n}\n\nstd::optional<std::filesystem::path>\nNetworkF::CreateNetmailAttach(const FidoAddress& dest, const std::string& bundlename,\n                              const fido_packet_config_t& packet_config) {\n  const auto netmail_filepath = NextNetmailFilePath(dirs_.netmail_dir());\n\n  if (netmail_filepath.empty()) {\n    LOG(ERROR) << \"Unable to figure out netmail filename in dir: '\" << dirs_.netmail_dir() << \"'\";\n    return std::nullopt;\n  }\n  const auto bundlepath = FilePath(dirs_.outbound_dir(), bundlename);\n  if (!CreateFidoNetAttachNetMail(FidoAddress(net_.fido.fido_address), dest, netmail_filepath,\n                                  bundlepath.string(), packet_config)) {\n    LOG(ERROR) << \"Unable to create netmail: \" << netmail_filepath;\n    return std::nullopt;\n  }\n  LOG(INFO) << \"Wrote attach netmail: \" << netmail_filepath;\n  return netmail_filepath;\n}\n\nstd::optional<std::filesystem::path>\nNetworkF::CreateNetmailAttachOrFloFile(const FidoAddress& dest, const std::string& bundlename,\n                                       const fido_packet_config_t& packet_config) {\n  if (net_.fido.mailer_type == fido_mailer_t::attach) {\n    return CreateNetmailAttach(dest, bundlename, packet_config);\n  }\n  if (net_.fido.mailer_type == fido_mailer_t::flo) {\n    return CreateFloFile(dest, bundlename, packet_config);\n  }\n  LOG(ERROR) << \"Unknown mailer type: \" << static_cast<int>(net_.fido.mailer_type);\n  return std::nullopt;\n}\n\nstatic FidoAddress find_route_to(const FidoAddress& dest, const FidoCallout& callout,\n                                 const fido_packet_config_t& packet_config) {\n  if (packet_config.netmail_status == fido_bundle_status_t::direct) {\n    return dest;\n  }\n\n  if (const auto a = FindRouteToAddress(dest, callout)) {\n    return a.value();\n  }\n  // is this right? returning direct if we have no route?\n  return dest;\n}\n\nbool NetworkF::export_main_type_new_post(std::set<std::string>& bundles, NetPacket& p) {\n  // Lame implementation that creates 1 file per message.\n  auto subtype = get_subtype_from_packet_text(p.text());\n  LOG(INFO) << \"Creating packet for subtype: \" << subtype;\n\n  auto subscribers = ReadFidoSubcriberFile(FilePath(net_.dir, StrCat(\"n\", subtype, \".net\")));\n  if (subscribers.empty()) {\n    LOG(INFO) << \"There are no subscribers on echo: '\" << subtype << \"'. Nothing to do!\";\n  }\n  for (const auto& sub : subscribers) {\n    const auto packet_config = fido_callout_.packet_config_for(sub);\n    const auto route_to = find_route_to(sub, fido_callout_, packet_config);\n    if (auto bundlename = create_ftn_packet_and_bundle(sub, route_to, p)) {\n      if (!contains(bundles, bundlename.value())) {\n        // We only want to attach the bundle (or add it to the flo file)\n        // one time, so skip ones that have already been done.\n        bundles.insert(bundlename.value());\n        auto route_packet_config = fido_callout_.packet_config_for(route_to);\n        CreateNetmailAttachOrFloFile(route_to, bundlename.value(), route_packet_config);\n      }\n    }\n  }\n  return true;\n}\n\nbool NetworkF::export_main_type_email_name(std::set<std::string>& bundles, NetPacket& p) {\n  // Lame implementation that creates 1 file per message.\n  LOG(INFO) << \"Creating packet for netmail.\";\n\n  auto it = std::begin(p.text());\n  const auto to = get_message_field(p.text(), it, {0}, 80);\n  const auto odest = get_address_from_single_line(to);\n  if (!odest.has_value()) {\n    LOG(ERROR) << \"Unable to get address from to line: \" << to;\n    return false;\n  }\n  const auto& dest = odest.value();\n\n  // todo - actually we need a new way of making the ftn packet that works\n  // right with net mail\n  const auto packet_config = fido_callout_.packet_config_for(dest);\n  const FidoAddress route_to = find_route_to(dest, fido_callout_, packet_config);\n  if (auto bundlename = create_ftn_packet_and_bundle(dest, route_to, p)) {\n    if (!contains(bundles, bundlename.value())) {\n      // We only want to attach the bundle (or add it to the flo file)\n      // one time, so skip ones that have already been done.\n      bundles.insert(bundlename.value());\n      CreateNetmailAttachOrFloFile(route_to, bundlename.value(), packet_config);\n    }\n  }\n  return true;\n}\n\nsdk::FtnMessageDupe& NetworkF::dupe() {\n  if (!dupe_) {\n    dupe_ = std::make_unique<wwiv::sdk::FtnMessageDupe>(datadir_, true);\n  }\n  return *dupe_;\n}\n\nbool NetworkF::DoImport() {\n  auto num_packets_processed = 0;\n  std::unique_ptr<FtnMessageDupe> dupe;\n  const std::vector<std::string> extensions{\"su?\", \"mo?\", \"tu?\", \"we?\", \"th?\", \"fr?\", \"sa?\", \"pkt\"};\n  for (const auto& ext : extensions) {\n    num_packets_processed += import_bundles(dirs_.inbound_dir(), StrCat(\"*.\", ext));\n#ifndef _WIN32\n    num_packets_processed +=\n        import_bundles(dirs_.inbound_dir(), StrCat(\"*.\", ToStringUpperCase(ext)));\n#endif\n  }\n  return num_packets_processed > 0;\n}\n\nbool NetworkF::DoExport() {\n  const auto sfile_name = StrCat(\"s\", FTN_FAKE_OUTBOUND_NODE, \".net\");\n  const auto path = FilePath(net_.dir, sfile_name);\n  if (!File::Exists(path)) {\n    LOG(INFO) << \"No file '\" << path.string() << \"' exists to be exported to a FTN packet.\";\n    return false;\n  }\n\n  NetMailFile file(path, true);\n  if (!file) {\n    LOG(ERROR) << \"Unable to open file: \" << path.string();\n    return false;\n  }\n\n  std::set<std::string> bundles;\n  auto num_packets_processed = 0;\n  for (auto p : file) {\n    // If we got here, we had a packet to process.\n    ++num_packets_processed;\n\n    if (p.nh.main_type == main_type_new_post) {\n      if (!export_main_type_new_post(bundles, p)) {\n        LOG(ERROR) << \"Error exporting post.\";\n      }\n    } else if (p.nh.main_type == main_type_email_name) {\n      if (!export_main_type_email_name(bundles, p)) {\n        LOG(ERROR) << \"Error exporting email.\";\n      }\n    } else {\n      LOG(ERROR) << \"    ! ERROR Unhandled type: '\" << main_type_name(p.nh.main_type)\n                 << \"'; writing to dead.net\";\n      // Let's write it to dead.net_\n      if (!write_deadnet_packet(net_.dir, p)) {\n        LOG(ERROR) << \"Error writing to dead.net\";\n      }\n    }\n  }\n\n  // Delete the packet.\n  file.Close();\n  if (opts_.skip_delete) {\n    backup_file(path);\n  }\n  File::Remove(path);\n\n  return file.last_read_response() != ReadNetPacketResponse::ERROR && num_packets_processed > 0;\n}\n\nbool NetworkF::Run(std::vector<std::string> cmds) {\n  if (!fido_callout_.IsInitialized()) {\n    LOG(ERROR) << \"Unable to initialize fido_callout.\";\n    return false;\n  }\n\n  if (cmds.empty()) {\n    LOG(ERROR) << \"No command specified. Exiting.\";\n    return false;\n  }\n\n  const auto cmd = cmds.front();\n\n  if (cmd == \"import\") {\n    return DoImport();\n\n  } else if (cmd == \"export\") {\n    return DoExport();\n\n  } else {\n    LOG(ERROR) << \"Unknown command: \" << cmd;\n    return false;\n  }\n}\n\n} // namespace wwiv::net::networkf\n"
  },
  {
    "path": "networkf/networkf.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*          Copyright (C)2020-2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_NETWORKF_NETWORKF_H\n#define INCLUDED_NETWORKF_NETWORKF_H\n\n#include \"core/clock.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"net_core/netdat.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/net/packets.h\"\n#include <optional>\n#include <string>\n\nnamespace wwiv::net::networkf {\n\nstruct networkf_options_t {\n  int max_backups{0};\n  bool skip_delete{false};\n  char net_cmd{'f'};\n  std::string system_name;\n};\n\nclass NetworkF final {\npublic:\n  NetworkF(const sdk::BbsDirectories& bbsdirs,\n           const networkf_options_t& opts, const sdk::net::Network, const sdk::BbsListNet& bbslist,\n           core::Clock& clock);\n  ~NetworkF();\n\n  /** Runs networkf import */\n  bool DoImport();\n\n  /** Runs networkf export */\n  bool DoExport();\n\n  /** Runs networkf using cmds for the subcommands passed from the commandline */\n  bool Run(std::vector<std::string> cmds);\n\n  // [[VisibleForTesting]]\n  const sdk::net::Network& net() const { return net_; }\n\nprivate:\n  bool import_packet_file(const std::filesystem::path& path);\n\n  bool import_packets(const std::filesystem::path& dir, const std::string& mask);\n\n  bool import_bundle_file(const std::filesystem::path& path);\n\n  /** imports FTN bundles, returning the number of packets processed */\n  int import_bundles(const std::filesystem::path& dir, const std::string& mask);\n\n  /**\n   * Creates a FTN bundle using the appropriate archiver for the route_to system,\n   * if PKT is and adds the FTN packet named 'fido_packet_name'.\n   *\n   * Returns the name of the fido bundle on success.\n   */\n  std::optional<std::string> create_ftn_bundle(const sdk::fido::FidoAddress& route_to,\n                                               const std::string& fido_packet_name);\n\n  /**\n   * Creates a FTN packet from the contents of the WWIVnet style packet.\n   *\n   * Returns the name of the fido packet on success.\n   */\n  std::optional<std::string> create_ftn_packet(const sdk::fido::FidoAddress& dest,\n                                               const sdk::fido::FidoAddress& route_to,\n                                               const sdk::net::NetPacket& wwivnet_packet);\n\n  /**\n   * Creates a FTN packet and bundle from the contents of the WWIVnet style packet.\n   *\n   * Returns the name of the fido packet on success.\n   */\n  std::optional<std::string> create_ftn_packet_and_bundle(const sdk::fido::FidoAddress& dest,\n                                                          const sdk::fido::FidoAddress& route_to,\n                                                          sdk::net::NetPacket& p);\n\n  /** Create a FLO file, returning the name generated or nullopt */\n  std::optional<std::string> CreateFloFile(const wwiv::sdk::fido::FidoAddress& dest,\n                                           const std::string& bundlename,\n                                           const sdk::net::fido_packet_config_t& packet_config);\n\n  /** Create a FLO file, returning the name netmail attach file or nullopt */\n  std::optional<std::filesystem::path>\n  CreateNetmailAttach(const sdk::fido::FidoAddress& dest, const std::string& bundlename,\n                      const sdk::net::fido_packet_config_t& packet_config);\n\n  /** Create a FLO file, returning the FLO file or generated or nullopt */\n  std::optional<std::filesystem::path>\n  CreateNetmailAttachOrFloFile(const sdk::fido::FidoAddress& dest, const std::string& bundlename,\n                               const sdk::net::fido_packet_config_t& packet_config);\n\n  bool export_main_type_new_post(std::set<std::string>& bundles, sdk::net::NetPacket& p);\n\n  bool export_main_type_email_name(std::set<std::string>& bundles, sdk::net::NetPacket& p);\n\n  sdk::FtnMessageDupe& dupe();\n\n  const sdk::BbsListNet& bbslist_;\n  core::Clock& clock_;\n  const sdk::net::Network net_;\n  sdk::fido::FidoCallout fido_callout_;\n  NetDat netdat_;\n  sdk::fido::FtnDirectories dirs_;\n  const networkf_options_t opts_;\n  const std::filesystem::path datadir_;\n\n\n  std::unique_ptr<sdk::FtnMessageDupe> dupe_;\n  std::vector<int> colors_{7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n};\n\nvoid ShowNetworkfHelp(const NetworkCommandLine& cmdline);\n\n// Returns the difference in days between now (according to clock) and the date\n// specified in ftn format by ftn_date.\nint ftn_date_days_old(const core::Clock& clock, const std::string& ftn_date);\n\n} // namespace wwiv::net::networkf\n\n#endif\n"
  },
  {
    "path": "networkf/networkf_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"networkf/networkf.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/arc.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/net/subscribers.h\"\n#include <cstdlib>\n#include <ctime>\n#include <iostream>\n#include <memory>\n#include <set>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#ifndef _WIN32\n#include <signal.h>\n#endif // _WIN32\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nusing namespace wwiv::net::networkf;\n\nint main(int argc, char** argv) {\n\n#ifndef _WIN32\n  // Set this to the default handling, since when wwivd invokes\n  // this (and wwivd ignores SIGCHLD).\n  signal(SIGCHLD, SIG_DFL);\n#endif // !_WIN32\n\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  CommandLine cmdline(argc, argv, \"net\");\n  const NetworkCommandLine net_cmdline(cmdline, 'f');\n  try {\n    auto at_exit = finally(Logger::ExitLogger);\n    if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n      ShowNetworkfHelp(net_cmdline);\n      return 1;\n    }\n    const auto& net = net_cmdline.network();\n    if (net.type != network_type_t::ftn) {\n      LOG(ERROR) << \"NETWORKF is only for use on FTN type networks.\";\n      ShowNetworkfHelp(net_cmdline);\n      return 1;\n    }\n\n    VLOG(3) << \"Reading bbsdata.net_..\";\n    auto bbslist = BbsListNet::ReadBbsDataNet(net.dir);\n    if (bbslist.empty()) {\n      LOG(ERROR) << \"ERROR: Unable to read bbsdata.net_.\";\n      LOG(ERROR) << \"       Do you need to run network3?\";\n      return 3;\n    }\n\n    const auto fake_ftn_node = bbslist.node_config_for(FTN_FAKE_OUTBOUND_NODE);\n    if (!fake_ftn_node) {\n      LOG(ERROR) << \"Can not find node for outbound FTN address.\";\n      LOG(ERROR) << \"       Do you need to run network3?\";\n      return 2;\n    }\n\n    auto semaphore =\n        SemaphoreFile::try_acquire(net_cmdline.semaphore_path(), net_cmdline.semaphore_timeout());\n    SystemClock clock{};\n\n    networkf_options_t opts{net_cmdline.config().max_backups(), net_cmdline.skip_delete()};\n    opts.system_name = net_cmdline.config().system_name();\n    NetworkF nf(net_cmdline.config(), opts, net, bbslist, clock);\n    return nf.Run(net_cmdline.cmdline().remaining()) ? 0 : 2;\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [networkf]: \" << e.what();\n  }\n  return 2;\n}\n"
  },
  {
    "path": "networkf/networkf_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"core/datetime.h\"\n#include \"core/fake_clock.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"networkf/networkf.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/sdk_helper.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/fido/test/ftn_directories_test_helper.h\"\n#include <gmock/gmock-matchers.h>\n\n#include <chrono>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace testing;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::fido;\n\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido::test;\nusing namespace wwiv::net::networkf;\n\nclass NetworkFTest : public testing::Test {\npublic:\n  NetworkFTest() {}\n\nprotected:\n  wwiv::core::test::FileHelper file_helper_;\n  SdkHelper helper;\n};\n\nTEST_F(NetworkFTest, Smoke) { \n  constexpr int max_backups = 2;\n  constexpr bool skip_delete = false;\n  networkf_options_t opts{max_backups, skip_delete, 'f', \"\"};\n  opts.system_name = \"test bbsname\";\n\n  net_system_list_rec netsys;\n  netsys.sysnum = FTN_FAKE_OUTBOUND_NODE;\n  wwiv::sdk::BbsListNet bbslist({netsys});\n\n  FakeClock clock(DateTime::now());\n\n  auto net = helper.CreateTestNetwork(wwiv::sdk::net::network_type_t::ftn);\n  NetworkF f(helper, opts, net, bbslist, clock);\n\n  EXPECT_EQ(net.dir.string(), f.net().dir.string());\n}\n\n\nTEST_F(NetworkFTest, DaysOld_New) {\n  // daten_to_fido\n  FakeClock clock(DateTime::now());\n  auto fd = daten_to_fido(clock.Now().to_time_t());\n\n  EXPECT_THAT(ftn_date_days_old(clock, fd), Eq(0));\n}\n\nTEST_F(NetworkFTest, DaysOld_30) {\n  // daten_to_fido\n  FakeClock clock(DateTime::now());\n  auto fd = daten_to_fido(clock.Now().to_time_t());\n  clock.tick(hours(30 * 24));\n\n  EXPECT_THAT(ftn_date_days_old(clock, fd), Eq(30));\n}\n\nTEST_F(NetworkFTest, DaysOld_Newer) {\n  // daten_to_fido\n  FakeClock packet_clock(DateTime::now());\n  const auto now_clock = packet_clock;\n  packet_clock.tick(hours(25));\n  const auto fd = daten_to_fido(packet_clock.Now().to_time_t());\n\n  EXPECT_THAT(ftn_date_days_old(now_clock, fd), Le(0));\n}\n"
  },
  {
    "path": "networkf/networkf_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n}\n"
  },
  {
    "path": "networkt/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(NETWORK_MAIN networkt.cpp)\n\n\nadd_executable(networkt ${NETWORK_MAIN})\nset_max_warnings(networkt)\ntarget_link_libraries(networkt binkp_lib net_core core sdk)\n\n"
  },
  {
    "path": "networkt/networkt.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*         Copyright (C)2020-2022, WWIV Software Services                 */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n// WWIV5 NetworkC\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"net_core/net_cmdline.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/files/tic.h\"\n#include \"sdk/net/packets.h\"\n#include <cstdlib>\n#include <iostream>\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::stl;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk::fido;\n\nstatic void ShowHelp(const NetworkCommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nbool process_ftn_tic(const Config& config, const Network& net, bool save_tic_files, bool skip_delete) {\n  if (!net.fido.process_tic) {\n    LOG(WARNING) << \"TIC processing disabled for network: \" << net.name;\n    return false;\n  }\n  const FtnDirectories ftn_directories(config.root_directory(), net);\n  files::Dirs dirs(config.datadir(), 0);\n  if (!dirs.Load()) {\n    LOG(ERROR) << \"Unable to load directories.\";\n    return false;\n  }\n  files::FileApi api(config.datadir());\n\n  FindFiles ff(FilePath(ftn_directories.tic_dir(), \"*.tic\"), FindFiles::FindFilesType::files);\n  auto first = true;\n  const files::TicParser parser(ftn_directories.tic_dir());\n  for (const auto& f : ff) {\n    auto ot = parser.parse(f.name);\n    if (!ot) {\n      continue;\n    }\n    auto t = ot.value();\n    if (!t.IsValid()) {\n      continue;\n    }\n    auto od = FindFileAreaForTic(dirs, t, net);\n    if (!od) {\n      LOG(ERROR) << \"Unable to find AREA_TAG for tic file: TAG: \" << t.area << \"; file; \" << f.name;\n      continue;\n    }\n    auto d = od.value();\n    auto fa = api.CreateOrOpen(d);\n    if (!fa) {\n      LOG(ERROR) << \"Unable to open file area: \" << d.filename;\n      continue;\n    }\n    if (first) {\n      LOG(INFO) << \"------------------------------------------------------------------------------\";\n      first = false;\n    }\n    files::FileName fn(t.file);\n    auto op = fa->FindFile(fn);\n    files::FileRecord r;\n    r.set_filename(fn);\n    r.set_description(t.desc);\n    r.set_extended_description(!t.ldesc.empty());\n    r.set_numbytes(t.size());\n    r.set_date(t.date());\n    r.set_uploaded_by(\"WWIV Tic Processor\");\n    const auto actual_t = File::last_write_time(FilePath(ftn_directories.tic_dir(), r));\n    r.set_actual_date(DateTime::from_time_t(actual_t));\n    const auto ext_desc = JoinStrings(t.ldesc, \"\\r\\n\");\n\n    if (!net.fido.process_tic) {\n      LOG(INFO) << \"Skipping processing file. process_tic is not enabled. file: \" << t.file;\n      continue;\n    }\n\n    if (op.has_value()) {\n      LOG(INFO) << \"File already exists in file area\";\n      LOG(INFO) << \"** Updating: \"  << r;\n      if (!fa->UpdateFile(r, op.value(), ext_desc)) {\n        LOG(ERROR) << \"Failed to update File: \" << fn;\n        continue;\n      }\n    } else {\n      LOG(INFO) << \"** Adding  :\" << r;\n      if (!fa->AddFile(r, ext_desc)) {\n        LOG(ERROR) << \"Error adding file: \" << r;\n        continue;\n      }\n      if (!fa->Save()) {\n        LOG(ERROR) << \"Error saving file area: \" << d.filename;\n        continue;\n      }\n    }\n    // Display information about the file;\n    LOG(INFO) << \"Area Name  : \" << t.area;\n    LOG(INFO) << \"Area Desc  : \" << t.area_description;\n    LOG(INFO) << \"File Name  : \" << r;\n    LOG(INFO) << \"Description: \" << t.desc;\n    LOG(INFO) << \"Ext Desc   : \";\n    const auto v = SplitString(ext_desc, \"\\r\\n\", true);\n    for (const auto& l : v) {\n      LOG(INFO) << \"    \" << l;\n    }\n    LOG(INFO) << \"------------------------------------------------------------------------------\";\n    // Use t.file not r here since r will be the unaligned and lower-case filename,\n    // and we have to match the exact case specified. So use t.file.\n    const auto src = FilePath(ftn_directories.tic_dir(), t.file);\n    // f.name is the name of the TIC file\n    const auto tic = FilePath(ftn_directories.tic_dir(), f.name);\n    const auto dest = FilePath(d.path, r);\n    if (save_tic_files) {\n      LOG(INFO) << \"Not moving file, just copy, --save_tic_files == true\";\n      File::Copy(src, dest);\n    } else {\n      LOG(INFO) << \"Moving file to: \" << dest.string();\n      File::Move(src, dest);\n      if (!skip_delete) {\n        File::Remove(tic);\n      }\n    }\n  }\n  return true;\n}\n\nint networkt_main(const NetworkCommandLine& net_cmdline) {\n  try {\n    const auto& net = net_cmdline.network();\n\n    StatusMgr sm(net_cmdline.config().datadir(), [](int) {});\n    const auto status = sm.get_status();\n\n    switch (net.type) {\n    case network_type_t::ftn: {\n      const auto save_tic_files = net_cmdline.cmdline().barg(\"save_tic_files\");\n      const auto skip_delete = net_cmdline.skip_delete();\n      if (!process_ftn_tic(net_cmdline.config(), net, save_tic_files, skip_delete)) {\n        return 1;\n      }\n    } break;\n    case network_type_t::wwivnet:\n      LOG(ERROR) << \"TIC support not implemented for WWIVnet\";\n      return 1;\n    case network_type_t::internet:\n      LOG(ERROR) << \"TIC support not implemented for Internet\";\n      return 1;\n    case network_type_t::news:\n      LOG(ERROR) << \"TIC support not implemented for NNTP\";\n      return 1;\n    default:\n      LOG(ERROR) << \"Unknown network type: \" << static_cast<int>(net.type);\n      return 1;\n    }\n\n    return 0;\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd() << \"]: \" << e.what();\n  }\n  return 2;\n}\n\nint main(int argc, char** argv) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.add_argument({\"process_instance\", \"Also process pending files for BBS instance #\", \"0\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\n      \"save_tic_files\", 'S', \"Save TIC files, do not delete TIC and archives\", false});\n\n  const NetworkCommandLine net_cmdline(cmdline, 't');\n  if (!net_cmdline.IsInitialized() || net_cmdline.cmdline().help_requested()) {\n    ShowHelp(net_cmdline);\n    return 1;\n  }\n  try {\n    auto semaphore = SemaphoreFile::try_acquire(net_cmdline.semaphore_path(),\n                                                net_cmdline.semaphore_timeout());\n    return networkt_main(net_cmdline);\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << \"ERROR: [network\" << net_cmdline.net_cmd()\n               << \"]: Unable to Acquire Network Semaphore: \" << e.what();\n  }\n}"
  },
  {
    "path": "notice.txt",
    "content": " =========================================================================\n ==      Example file for use with the Apache License, Version 2.0      ==\n =========================================================================\n\n   This product includes software developed by\n   WWIV Software Services (http://wss.wwiv.com).\n"
  },
  {
    "path": "sdk/CMakeLists.txt",
    "content": "\nset(COMMON_SOURCES\n  \"arword.cpp\"\n  \"bbslist.cpp\"\n  \"chains.cpp\"\n  \"config.cpp\"\n  \"config430.cpp\"\n  \"gfiles.cpp\"\n  \"instance.cpp\"\n  \"instance_message.cpp\"\n  \"names.cpp\"\n  \"phone_numbers.cpp\"\n  \"qscan.cpp\"\n  \"ssm.cpp\"\n  \"status.cpp\"\n  \"subxtr.cpp\"\n  \"qwk_config.cpp\"\n  \"user.cpp\"\n  \"usermanager.cpp\"\n  \"wwivd_config.cpp\"\n  \"acs/acs.cpp\"\n  \"acs/eval.cpp\"\n  \"acs/expr.cpp\"\n  \"ansi/ansi.cpp\"\n  \"ansi/framebuffer.cpp\"\n  \"ansi/makeansi.cpp\"\n  \"ansi/localio_screen.cpp\"\n  \"ansi/vscreen.cpp\"\n  \"conf/conf.cpp\"\n  \"fido/backbone.cpp\"\n  \"fido/fido_address.cpp\"\n  \"fido/fido_callout.cpp\"\n  \"fido/fido_directories.cpp\"\n  \"fido/fido_packets.cpp\"\n  \"fido/fido_util.cpp\"\n  \"fido/flo_file.cpp\"\n  \"fido/nodelist.cpp\"\n  \"files/allow.cpp\"\n  \"files/arc.cpp\"\n  \"files/dirs.cpp\"\n  \"files/diz.cpp\"\n  \"files/file_record.cpp\"\n  \"files/files.cpp\"\n  \"files/files_ext.cpp\"\n  \"files/tic.cpp\"\n  \"menus/menu.cpp\"\n  \"menus/menu_set.cpp\"\n  \"msgapi/email_wwiv.cpp\"\n  \"msgapi/message.cpp\"\n  \"msgapi/message_api.cpp\"\n  \"msgapi/message_api_wwiv.cpp\"\n  \"msgapi/message_area.cpp\"\n  \"msgapi/message_area_wwiv.cpp\"\n  \"msgapi/parsed_message.cpp\"\n  \"msgapi/type2_text.cpp\"\n  \"net/binkp.cpp\"\n  \"net/callout.cpp\"\n  \"net/connect.cpp\"\n  \"net/contact.cpp\"\n  \"net/ftn_msgdupe.cpp\"\n  \"net/callouts.cpp\"\n  \"net/net.cpp\"\n  \"net/packets.cpp\"\n  \"net/networks.cpp\"\n  \"net/subscribers.cpp\"\n  \"value/value.cpp\"\n  \"value/valueprovider.cpp\"\n   )\n\nadd_library(sdk ${COMMON_SOURCES})\nset_max_warnings(sdk)\ntarget_link_libraries(sdk PRIVATE local_io)\ntarget_link_libraries(sdk PUBLIC core fmt::fmt-header-only)\n\n## Tests\nif (WWIV_BUILD_TESTS)\n\nadd_library(sdk_fixtures \n  \"sdk_helper.cpp\"\n)\ntarget_link_libraries(sdk_fixtures PUBLIC core fmt::fmt-header-only)\n\nset(test_sources\n  \"bbslist_test.cpp\"\n  \"chains_test.cpp\"\n  \"config_test.cpp\"\n  \"datetime_test.cpp\"\n  \"instance_message_test.cpp\"\n  \"names_test.cpp\"\n  \"phone_numbers_test.cpp\"\n  \"qscan_test.cpp\"\n  \"subxtr_test.cpp\"\n  \"user_test.cpp\"\n\n  \"acs/ar_test.cpp\"\n  \"acs/expr_test.cpp\"\n  \"acs/value_test.cpp\"\n  \"ansi/ansi_test.cpp\"\n  \"ansi/framebuffer_test.cpp\"\n  \"ansi/makeansi_test.cpp\"\n  \"conf/conf_test.cpp\"\n  \"fido/backbone_test.cpp\"\n  \"fido/fido_address_test.cpp\"\n  \"fido/fido_packets_test.cpp\"\n  \"fido/fido_util_test.cpp\"\n  \"fido/flo_test.cpp\"\n  \"fido/nodelist_test.cpp\"\n  \"fido/test/ftn_directories_test_helper_test.cpp\"\n  \"files/allow_test.cpp\"\n  \"files/dirs_test.cpp\"\n  \"files/diz_test.cpp\"\n  \"files/files_ext_test.cpp\"\n  \"files/files_test.cpp\"\n  \"files/tic_test.cpp\"\n  \"msgapi/email_test.cpp\"\n  \"msgapi/msgapi_test.cpp\"\n  \"msgapi/parsed_message_test.cpp\"\n  \"msgapi/type2_text_test.cpp\"\n  \"net/callout_test.cpp\"\n  \"net/callouts_test.cpp\"\n  \"net/contact_test.cpp\"\n  \"net/ftn_msgdupe_test.cpp\"\n  \"net/network_test.cpp\"\n  \"net/packets_test.cpp\"\n)\nlist(APPEND test_sources sdk_test_main.cpp)\n\n\nadd_executable(sdk_tests ${test_sources})\nset_max_warnings(sdk_tests)\ntarget_link_libraries(sdk_tests core core_fixtures GTest::gtest sdk sdk_fixtures)\n\ngtest_discover_tests(sdk_tests)\n\n\nendif()"
  },
  {
    "path": "sdk/acs/acs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/acs/acs.h\"\n\n#include \"core/stl.h\"\n#include \"sdk/acs/eval.h\"\n#include \"sdk/acs/eval_error.h\"\n#include \"common/value/uservalueprovider.h\"\n\n#include <string>\n#include <tuple>\n#include <vector>\n\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::acs {\n\nstd::tuple<bool, std::vector<std::string>>\ncheck_acs(const Config&, const std::string& expression,\n  const std::vector<const ValueProvider*>& providers) {\n  if (StringTrim(expression).empty()) {\n    // Empty expression is always allowed.\n    std::vector<std::string> debug_lines;\n    return std::make_tuple(true, debug_lines);\n  }\n\n  Eval eval(expression);\n  for (const auto* p : providers) {\n    eval.add(p);\n  }\n  const auto result = eval.eval();\n  return std::make_tuple(result, eval.debug_info());  \n}\n\nstd::tuple<bool, std::string, std::vector<std::string>>\nvalidate_acs(const std::string& expression, const std::vector<const ValueProvider*>& providers) {\n  Eval eval(expression);\n  for (const auto* p : providers) {\n    eval.add(p);\n  }\n\n  try {\n    eval.eval_throws();\n    std::vector<std::string> debug_lines;\n    return std::make_tuple(true, \"\", debug_lines);\n  } catch (const eval_error& e) {\n    return std::make_tuple(false, e.what(), eval.debug_info());\n  }\n}\n\n} // namespace wwiv::sdk::acs\n"
  },
  {
    "path": "sdk/acs/acs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ACS_ACS_H\n#define INCLUDED_SDK_ACS_ACS_H\n\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include \"sdk/value/valueprovider.h\"\n\n#include <string>\n#include <tuple>\n#include <vector>\n\nnamespace wwiv::sdk::acs {\n\nenum class acs_debug_t { local, remote, none };\n\ntemplate <typename... Args>\nstd::vector<const value::ValueProvider*> make_vector(Args&&... args) {\n    return {std::forward<Args>(args)...};\n}\n\n// Result: (true|false), debug lines\nstd::tuple<bool, std::vector<std::string>>\ncheck_acs(const Config& config, const std::string& expression,\n          const std::vector<const value::ValueProvider*>& providers);\n\ntemplate <typename... Args>\nstd::tuple<bool, std::vector<std::string>>\ncheck_acs(const Config& config, const std::string& expression, Args... args) {\n  auto v = make_vector(args...);\n  return check_acs(config, expression, v);\n}\n\n// Result: (true|false), exception message (if any), debug lines\nstd::tuple<bool, std::string, std::vector<std::string>>\nvalidate_acs(const std::string& expression,\n             const std::vector<const value::ValueProvider*>& providers);\n\n// Result: (true|false), exception message (if any), debug lines\ntemplate <typename... Args>\nstd::tuple<bool, std::string, std::vector<std::string>>\nvalidate_acs(const std::string& expression, Args... args) {\n  auto v = make_vector(args...);\n  return validate_acs(expression, v);\n}\n\n} // namespace wwiv::sdk::acs\n\n#endif\n"
  },
  {
    "path": "sdk/acs/ar_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/parser/ast.h\"\n#include \"sdk/user.h\"\n#include \"common/value/uservalueprovider.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\nusing namespace wwiv::sdk::value;\n\nclass ArTest : public ::testing::Test {\npublic:\n  ArTest() = default;\n\n};\n\nTEST_F(ArTest, Eq) {\n  const Ar a('A');\n  const Ar user_abcd(\"ABCD\", true);\n  EXPECT_EQ(user_abcd, a);\n  EXPECT_EQ(a, user_abcd);\n}\n\nTEST_F(ArTest, Ne) {\n  const Ar a('A');\n  const Ar user_cde(\"CDE\", true);\n  EXPECT_NE(user_cde, a);\n  EXPECT_NE(a, user_cde);\n}\n\nTEST_F(ArTest, Eq_Conversion) {\n  const Ar user_abcd(\"ABCD\", true);\n\n  EXPECT_EQ(user_abcd, 'A');\n  EXPECT_EQ(user_abcd, \"A\");\n  EXPECT_EQ(\"A\", user_abcd);\n  EXPECT_EQ(\"A\", user_abcd);\n}\n\nTEST_F(ArTest, Ne_Conversion) {\n  const Ar user_cde(\"CDE\", true);\n  EXPECT_NE(user_cde, 'A');\n  EXPECT_NE(user_cde, \"A\");\n  EXPECT_NE('A', user_cde);\n  EXPECT_NE(\"A\", user_cde);\n}\n\nTEST_F(ArTest, Eq_Userside_Empty) {\n  const Ar e(0, true);\n  EXPECT_NE(e, \"A\");\n  EXPECT_NE(\"A\", e);\n}\n\nTEST_F(ArTest, Eq_OtherSide_Empty) {\n  const Ar user(\"ABC\", true);\n  EXPECT_EQ(user, Ar(0, false));\n  EXPECT_EQ(Ar(0, false), user);\n}\n\n"
  },
  {
    "path": "sdk/acs/eval.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/acs/eval.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/parser/ast.h\"\n#include \"core/parser/lexer.h\"\n#include \"fmt/ostream.h\"\n#include \"fmt/printf.h\"\n#include \"fmt/ostream.h\"\n#include \"sdk/acs/eval_error.h\"\n#include <optional>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::value;\n\nnamespace wwiv::sdk::acs {\n\nstatic std::tuple<std::string, std::string> split_obj_name(const std::string& name) {\n  if (const auto idx = name.find('.'); idx == std::string::npos) {\n    // If we only have a name with no dot, return it as the attribute and not prefix.\n    return std::make_tuple(\"\", name);\n  }\n  return SplitOnceLast(name, \".\");\n}\n\nstd::optional<Value> Eval::to_value(Factor* n) {\n  switch (n->factor_type()) {\n  case FactorType::int_value:\n    return Value(n->int_value());\n  case FactorType::string_val:\n    return Value(n->value());\n  case FactorType::variable: {\n    const auto sval = n->value();\n    auto [prefix, member] = split_obj_name(sval);\n    if (auto vpi = providers_.find(prefix); vpi != std::end(providers_)) {\n      if (auto o = vpi->second->value(member)) {\n        return {o.value()};\n      }\n    }\n    throw eval_error(fmt::format(\"No object named '{}' exists.\", n->value()));\n  }\n  }\n  throw eval_error(fmt::format(\"Error finding factor for object: '{}'.\", to_string(*n)));\n}\n\n\nEval::Eval(std::string expression) : expression_(std::move(expression)) {\n  add(&default_provider_);  \n}\n\n\nvoid Eval::visit(Expression* n) { \n  //VLOG(2) << \"Evaluating: \" << n->ToString(false);  \n  std::optional<Value> left;\n  if (auto* factor = dynamic_cast<Factor*>(n->left())) {\n    left = to_value(factor);\n  } else {\n    // left must be expression, grab it from the cache.\n    left = values_[n->left()->id()];\n  }\n  std::optional<Value> right;\n  if (auto* factor = dynamic_cast<Factor*>(n->right())) {\n    right = to_value(factor);\n  } else {\n    // left must be expression, grab it from the cache.\n    right = values_[n->right()->id()];\n  }\n\n  auto eval_expr = fmt::format(\"{}(id:{}) {} {}(id:{})\", left.value(), n->left()->id(),\n                               to_symbol(n->op()), right.value(), n->right()->id());\n  //VLOG(1) << \"EVAL: \" << eval_expr;\n\n  // cache value\n  auto result = Value::eval(left.value(), n->op(), right.value());\n  if (result.is_boolean()) {\n    debug_info_.emplace_back(fmt::format(\"Expression '{}' evaluated to {}. Stored as id: '{}'\",\n                                         eval_expr, result.as_boolean() ? \"true\" : \"false\",\n                                         n->id()));\n  }\n  values_[n->id()] = result;\n}\n\nvoid Eval::visit(Factor* n) { \n  if (n->factor_type() == FactorType::variable) {\n    const auto sval = n->value();\n    auto [prefix, member] = split_obj_name(sval);\n    if (auto vpi = providers_.find(prefix); vpi != std::end(providers_)) {\n      if (auto o = vpi->second->value(member)) {\n        values_.emplace(n->id(), o.value());\n      }\n    }\n  }\n}\n\nbool Eval::eval_throws() {\n  //VLOG(1) << \"Eval::eval_throws: \" << expression_;\n\n  Lexer l(expression_);\n  if (!l.ok()) {\n    std::string error_token;\n    for (const auto& t : l.tokens()) {\n      if (t.type == TokenType::error) {\n        error_token += to_string(t);\n      }\n    }\n    throw eval_error(fmt::format(\"Failed to lex expression: '{}'; \\r\\nError {}: \", expression_, error_token));\n  }\n\n  Ast ast{};\n  if (!ast.parse(l)) {\n      return false;\n  }\n  auto* root = ast.root();\n  if (!root) {\n    throw eval_error(fmt::format(\"Failed to parse expression: '{}'.\", expression_));\n  }\n  //VLOG(1) << \"Root: \" << root->ToString();\n  if (root->ast_type() == AstType::AST_ERROR) {\n    const auto* error_node = dynamic_cast<ErrorNode*>(root);\n    throw eval_error(error_node->message);\n  }\n\n  root->accept(this);\n\n  if (auto* expr = dynamic_cast<Expression*>(root)) {\n    auto it = values_.find(expr->id());\n    if (it == std::end(values_)) {\n      throw eval_error(fmt::format(\"Unable to find expression id: '{}'.\", expr->id()));\n    }\n    return it->second.as_boolean();\n  }\n  throw eval_error(fmt::format(\"Failed to parse expression: '{}'.\", expression_));\n}\n\nbool Eval::eval() {\n\n  try {\n    return eval_throws();\n  } catch (const eval_error& error) {\n    error_text_ = error.what();\n    //VLOG(1) << \"Eval Error: \" << error_text_;\n    debug_info_.emplace_back(error_text_);\n  }\n  return false;\n}\n\nbool Eval::add(const value::ValueProvider* p) { \n  providers_[p->prefix()] = p;\n  return true; \n}\n\nbool Eval::add(std::unique_ptr<value::ValueProvider>&& p) {\n  add(p.get());\n  providers_storage_[p->prefix()] = std::move(p);\n  return true; \n}\n\n\n} // namespace wwiv::sdk::acs\n"
  },
  {
    "path": "sdk/acs/eval.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ACS_EVAL_H\n#define INCLUDED_SDK_ACS_EVAL_H\n\n#include \"core/parser/ast.h\"\n#include \"sdk/value/value.h\"\n#include \"sdk/value/valueprovider.h\"\n#include <memory>\n#include <optional>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\nnamespace wwiv::sdk::acs {\n\nenum class debug_message_t { trace, parse };\n\n/** Shorthand to create an optional Value */\ntemplate <typename T> static std::optional<value::Value> val(T&& v) {\n  return std::make_optional<value::Value>(std::forward<T>(v));\n}\n\nclass DefaultValueProvider : public value::ValueProvider {\npublic:\n  DefaultValueProvider() : ValueProvider(\"\") {}\n  [[nodiscard]] std::optional<value::Value> value(const std::string& name) const override {\n    if (name == \"true\") {\n      return val(true);\n    }\n    if (name == \"false\") {\n      return val(false);\n    }\n    return std::nullopt;\n  }  \n};\n\n/** \n * Evaluation engine for evaluating expressions provides.\n */\nclass Eval final : public core::parser::AstVisitor {\npublic:\n  explicit Eval(std::string expression);\n  ~Eval() override = default;\n\n  bool eval_throws();\n  bool eval();\n  bool add(std::unique_ptr<value::ValueProvider>&& p);\n  bool add(const value::ValueProvider* p);\n  std::optional<value::Value> to_value(core::parser::Factor* n);\n\n  /** \n   * Gets the error text that occurred when failing to evaluate the expression, \n   * or empty string if none exists.\n   */\n  [[nodiscard]] std::string error_text() const noexcept { return error_text_; }\n  [[nodiscard]] bool error() const noexcept { return !error_text_.empty(); }\n  \n  ///////////////////////////////////////////////////////////////////////////\n  // Debug support:  This writes out debug_info lines as the statement is \n  // evaluated. Used to explain how the statement was evaluated.\n  [[nodiscard]] const std::vector<std::string>& debug_info() const { return debug_info_; }\n\n  ///////////////////////////////////////////////////////////////////////////\n  // Visitor implementation\n  //\n\n  void visit(core::parser::AstNode*) override {}\n  void visit(core::parser::Expression* n) override;\n  void visit(core::parser::Factor* n) override;\n\nprivate:\n  std::string expression_;\n  std::unordered_map<std::string, const value::ValueProvider*> providers_;\n  std::unordered_map<int, value::Value> values_;\n  std::string error_text_;\n  std::vector<std::string> debug_info_;\n  std::unordered_map<std::string, std::unique_ptr<value::ValueProvider>> providers_storage_;\n  DefaultValueProvider default_provider_;\n};  // class\n\n} \n\n#endif\n"
  },
  {
    "path": "sdk/acs/eval_error.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ACS_EVAL_ERROR_H\n#define INCLUDED_SDK_ACS_EVAL_ERROR_H\n\n#include <stdexcept>\n#include <string>\n\nnamespace wwiv::sdk::acs {\n\n/** An error evaluating the expression */\nstruct eval_error : public std::runtime_error {\n  eval_error(const std::string& m) : runtime_error(m) {}\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/acs/expr.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/acs/expr.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::acs {\n\nstd::string AcsExpr::get() { \n  std::vector<std::string> expr;\n  if (min_age_ > 0 && min_age_ != 255) {\n    expr.emplace_back(fmt::format(\"user.age >= {}\", min_age_));\n  }\n  if (max_age_ < 255 && max_age_ != 0) {\n    expr.emplace_back(fmt::format(\"user.age <= {}\", max_age_));\n  }\n\n  if (ar_ >= 'A' && ar_ <= 'P') {\n    expr.emplace_back(fmt::format(\"user.ar == '{}'\", ar_));\n  }\n  if (min_sl_ > 0) {\n    expr.emplace_back(fmt::format(\"user.sl >= {}\", min_sl_));\n  }\n  if (max_sl_ > 0 && max_sl_ != 255) {\n    expr.emplace_back(fmt::format(\"user.sl <= {}\", max_sl_));\n  }\n\n  if (dar_ >= 'A' && dar_ <= 'P') {\n    expr.emplace_back(fmt::format(\"user.dar == '{}'\", dar_));\n  }\n  if (min_dsl_ > 0) {\n    expr.emplace_back(fmt::format(\"user.dsl >= {}\", min_dsl_));\n  }\n  if (max_dsl_ > 0 && max_dsl_ != 255) {\n    expr.emplace_back(fmt::format(\"user.dsl <= {}\", max_dsl_));\n  }\n\n  if (regnum_) {\n    expr.emplace_back(\"user.regnum == true\");\n  }\n\n  if (sysop_) {\n    expr.emplace_back(\"user.sysop == true\");\n  }\n\n  if (cosysop_) {\n    expr.emplace_back(\"user.cosysop == true\");\n  }\n\n  bool first{true};\n  std::ostringstream ss;\n  for (const auto& e : expr) {\n    if (!first) {\n      ss << \" && \";\n    }\n    ss << e;\n    first = false;\n  }\n  return ss.str();\n}\n\n}"
  },
  {
    "path": "sdk/acs/expr.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ACS_EXPR_H\n#define INCLUDED_SDK_ACS_EXPR_H\n\n#include <string>\n\nnamespace wwiv::sdk::acs {\n\n/** Provides a value for an identifier of the form \"object.attribute\" */\nclass AcsExpr final {\npublic:\n  AcsExpr() = default;\n  ~AcsExpr() = default;\n\n  AcsExpr& min_age(int min_age) {\n    min_age_ = min_age;\n    return *this;\n  }\n  AcsExpr& max_age(int max_age) {\n    max_age_ = max_age;\n    return *this;\n  }\n  AcsExpr& min_sl(int min_sl) {\n    min_sl_ = min_sl;\n    return *this;\n  }\n  AcsExpr& max_sl(int max_sl) {\n    max_sl_ = max_sl;\n    return *this;\n  }\n  AcsExpr& ar(char ar) {\n    ar_ = ar;\n    return *this;\n  }\n\n  AcsExpr& ar_int(int ar) {\n    if (ar != 0) {\n      for (auto i = 0; i < 16; i++) {\n        if ((1 << i) & ar) {\n          ar_ = static_cast<char>('A' + i);\n        }\n      }\n    }\n    return *this;\n  }\n\n  AcsExpr& min_dsl(int min_dsl) {\n    min_dsl_ = min_dsl;\n    return *this;\n  }\n  AcsExpr& max_dsl(int max_dsl) {\n    max_dsl_ = max_dsl;\n    return *this;\n  }\n  AcsExpr& dar(char dar) {\n    dar_ = dar;\n    return *this;\n  }\n  AcsExpr& dar_int(int ar) {\n    if (ar != 0) {\n      for (auto i = 0; i < 16; i++) {\n        if ((1 << i) & ar) {\n         dar_ = static_cast<char>('A' + i);\n        }\n      }\n    }\n    return *this;\n  }\n\n  AcsExpr& regnum(bool b) {\n    regnum_ = b;\n    return *this;\n  }\n\n  AcsExpr& sysop(bool b) {\n    sysop_ = b;\n    return *this;\n  }\n\n  AcsExpr& cosysop(bool b) {\n    cosysop_ = b;\n    return *this;\n  }\n\n  /** \n   * Gets the ACS expression for the given constraints.\n   */\n  [[nodiscard]] std::string get();\n\nprivate:\n  int min_age_{0};\n  int max_age_{255};\n  char ar_{0};\n  int min_sl_{0};\n  int max_sl_{255};\n  char dar_{0};\n  int min_dsl_{0};\n  int max_dsl_{255};\n  bool regnum_{false};\n  bool sysop_{false};\n  bool cosysop_{false};\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/acs/expr_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/parser/ast.h\"\n#include \"core/strings.h\"\n#include \"sdk/acs/expr.h\"\n\nusing namespace wwiv::core;\nusing namespace parser;\nusing namespace wwiv::sdk::acs;\n\nclass AcsExprTest : public testing::Test {\npublic:\n  AcsExpr ae;\n};\n\nTEST_F(AcsExprTest, MultipleLines) {\n  ae.max_age(18);\n  EXPECT_EQ(ae.get(), \"user.age <= 18\");\n}\n\nTEST_F(AcsExprTest, Age_Min) { EXPECT_EQ(ae.min_age(18).get(), \"user.age >= 18\"); }\nTEST_F(AcsExprTest, Age_Max) { EXPECT_EQ(ae.max_age(21).get(), \"user.age <= 21\"); }\nTEST_F(AcsExprTest, Age_Min_Max) {\n  EXPECT_EQ(ae.min_age(18).max_age(21).get(), \"user.age >= 18 && user.age <= 21\");\n}\n\nTEST_F(AcsExprTest, Ar) { EXPECT_EQ(ae.ar('C').get(), \"user.ar == 'C'\"); }\nTEST_F(AcsExprTest, Ar_Bad) { EXPECT_EQ(ae.ar('Z').get(), \"\"); }\nTEST_F(AcsExprTest, SL_Min) { EXPECT_EQ(ae.min_sl(18).get(), \"user.sl >= 18\"); }\nTEST_F(AcsExprTest, SL_Min_255) { EXPECT_EQ(ae.min_sl(255).get(), \"user.sl >= 255\"); }\nTEST_F(AcsExprTest, SL_Max) { EXPECT_EQ(ae.max_sl(21).get(), \"user.sl <= 21\"); }\nTEST_F(AcsExprTest, SL_Min_Max) {\n  EXPECT_EQ(ae.min_sl(18).max_sl(21).get(), \"user.sl >= 18 && user.sl <= 21\");\n}\n\nTEST_F(AcsExprTest, Ar_Int) { EXPECT_EQ(ae.ar_int(1).get(), \"user.ar == 'A'\"); }\n\nTEST_F(AcsExprTest, Dar) { EXPECT_EQ(ae.dar('C').get(), \"user.dar == 'C'\"); }\nTEST_F(AcsExprTest, Dar_Bad) { EXPECT_EQ(ae.dar('Z').get(), \"\"); }\nTEST_F(AcsExprTest, Dar_Int) { EXPECT_EQ(ae.dar_int(4).get(), \"user.dar == 'C'\"); }\n\n\nTEST_F(AcsExprTest, DSL_Min) { EXPECT_EQ(ae.min_dsl(18).get(), \"user.dsl >= 18\"); }\nTEST_F(AcsExprTest, DSL_Max) { EXPECT_EQ(ae.max_dsl(21).get(), \"user.dsl <= 21\"); }\nTEST_F(AcsExprTest, DSL_Min_Max) {\n  EXPECT_EQ(ae.min_dsl(18).max_dsl(21).get(), \"user.dsl >= 18 && user.dsl <= 21\");\n}\n\nTEST_F(AcsExprTest, DSL_Min_255) { EXPECT_EQ(ae.min_dsl(255).get(), \"user.dsl >= 255\"); }\n\nTEST_F(AcsExprTest, RegNum) { EXPECT_EQ(ae.regnum(true).get(), \"user.regnum == true\"); }\n\nTEST_F(AcsExprTest, MultipleConditions) {\n  EXPECT_EQ(ae.min_dsl(18).max_dsl(21).dar('A').regnum(true).get(),\n            \"user.dar == 'A' && user.dsl >= 18 && user.dsl <= 21 && user.regnum == true\");\n}\n"
  },
  {
    "path": "sdk/acs/value_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2020-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/parser/ast.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/eval.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::sdk::value;\n\nclass ValueTest : public ::testing::Test {\npublic:\n  ValueTest() = default;\n};\n\n#define EXPECT_VALUE_TRUE(l, op, r) EXPECT_TRUE(Value::eval(l, op, r).as_boolean())\n#define EXPECT_VALUE_FALSE(l, op, r) EXPECT_FALSE(Value::eval(l, op, r).as_boolean())\n\nTEST_F(ValueTest, Smoke) {\n  const Value l(\"hello\");\n  const Value r(\"hello\");\n  const Value r2(\"foo\");\n  EXPECT_VALUE_TRUE(l, Operator::eq, r);\n  EXPECT_VALUE_FALSE(l, Operator::eq, r2);\n}\n"
  },
  {
    "path": "sdk/ansi/ansi.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ansi/ansi.h\"\n\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/ansi/vscreen.h\"\n#include <algorithm>\n#include <cctype>\n#include <sstream>\n#include <utility>\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::ansi {\n\nstatic const char clrlst[] = \"04261537\";\n\nAnsi::Ansi(VScreen* b, AnsiCallbacks callbacks, uint8_t default_attr)\n    : b_(b), callbacks_(std::move(callbacks)), default_attr_(default_attr) {}\n\nbool Ansi::write(char c) {\n  if (state_ == AnsiMode::not_in_sequence && c == 27) {\n    state_ = AnsiMode::in_sequence;\n    return write_in_sequence(c);\n  }\n  if (state_ == AnsiMode::in_sequence) {\n    return write_in_sequence(c);\n  }\n  return write_not_in_sequence(c);\n}\n\nstd::vector<int> to_ansi_numbers(const std::string& as, int max_args, std::vector<int> defaults) {\n  // TODO(rushfan) assert that this starts_with(as, \"\\x1b[\"))?\n  auto list = SplitString(as.substr(2), \";\", false);\n  std::vector<int> out;\n  const auto list_size = std::min<int>(max_args, wwiv::stl::size_int(list));\n  for (auto i = 0; i < wwiv::stl::ssize(defaults); i++) {\n    if (i < list_size) {\n      const auto& c = wwiv::stl::at(list, i);\n      if (!c.empty()) {\n        out.push_back(to_number<int>(c));\n        continue;\n      }\n    }\n    out.push_back(wwiv::stl::at(defaults, i));\n  }\n\n  if (list_size > 0 && list_size > wwiv::stl::ssize(defaults)) {\n    const auto start = defaults.size();\n    const auto end = list_size - defaults.size();\n    for (auto i = start; i < end; i++) {\n      const auto& c = wwiv::stl::at(list, i);\n      if (!c.empty()) {\n        out.push_back(to_number<int>(c));\n      }\n    }\n  }\n\n  return out;\n}\n\nbool Ansi::write_in_sequence(char c) {\n  switch (c) {\n  case 27: {\n    if (!ansi_sequence_.empty()) {\n      return ansi_sequence_error(c);\n    }\n    ansi_sequence_.push_back(c);\n    return true;\n  }\n  case '[': {\n    if (ansi_sequence_.size() != 1) {\n      return ansi_sequence_error(c);\n    }\n    ansi_sequence_.push_back(c);\n    return true;\n  }\n  case 'A': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 1, {1});\n    const auto x = b_->x();\n    const auto y = std::max(0, b_->y() - ns[0]);\n    b_->gotoxy(x, y);\n    if (callbacks_.move_) {\n      callbacks_.move_(x, y);\n    }\n    return ansi_sequence_done();\n  }\n  case 'B': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 1, {1});\n    const auto x = b_->x();\n    const auto y = std::max(0, b_->y() + ns[0]);\n    b_->gotoxy(x, y);\n    if (callbacks_.move_) {\n      callbacks_.move_(x, y);\n    }\n    return ansi_sequence_done();\n  }\n  case 'C': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 1, {1});\n    const auto x = std::min(b_->cols() - 1, b_->x() + ns[0]);\n    const auto y = b_->y();\n    b_->gotoxy(x, y);\n    if (callbacks_.move_) {\n      callbacks_.move_(x, y);\n    }\n    return ansi_sequence_done();\n  }\n  case 'D': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 1, {1});\n    const auto x = std::min(b_->cols() - 1, b_->x() - ns[0]);\n    const auto y = b_->y();\n    b_->gotoxy(x, y);\n    if (callbacks_.move_) {\n      callbacks_.move_(x, y);\n    }\n    return ansi_sequence_done();\n  }\n  case 'H':\n  case 'f': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 2, {1, 1});\n    if (ns.size() < 2) {\n      return ansi_sequence_error(c);\n    }\n    const auto x = ns[1] - 1;\n    const auto y = ns[0] - 1;\n    if (callbacks_.move_) {\n      callbacks_.move_(x, y);\n    }\n    b_->gotoxy(x, y);\n    return ansi_sequence_done();\n  }\n  case 'h':\n  case 'l': { // save or restore wrap at last column.\n    // Were' ignoring this.\n    return ansi_sequence_done();\n  }\n  case 'J': {\n    auto ns = to_ansi_numbers(ansi_sequence_, 1, {1});\n    if (ns.size() != 1 || ns.front() != 2) {\n      return ansi_sequence_error(c);\n    }\n    b_->clear();\n    if (callbacks_.move_) {\n      callbacks_.move_(0, 0);\n    }\n    return ansi_sequence_done();\n  }\n  case 'K':\n  case 'k': {\n    b_->clear_eol();\n    return ansi_sequence_done();\n  }\n  case 'm': {\n    auto ansi_numbers_ = to_ansi_numbers(ansi_sequence_, 10, {});\n    // https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters\n    for (const auto n : ansi_numbers_) {\n      const auto a = b_->curatr();\n      switch (n) {\n      case 0: // Normal/Reset\n        b_->curatr(default_attr_);\n        break;\n      case 1: // Bold\n        b_->curatr(a | 0x08);\n        break;\n      case 5: // Slow blink?\n        b_->curatr(a | 0x80);\n        break;\n      case 7: { // Reverse Video\n        const auto ptr = static_cast<uint8_t>(a & 0x77);\n        b_->curatr((a & 0x88) | (ptr << 4) | (ptr >> 4));\n      } break;\n      default: {\n        if (n >= 30 && n <= 37) {\n          b_->curatr((a & 0xf8) | (clrlst[n - 30] - '0'));\n        } else if (n >= 40 && n <= 47) {\n          const uint8_t bg = (clrlst[n - 40] - '0') << 4;\n          const uint8_t ct = (a & 0x8f) | bg;\n          b_->curatr(ct);\n        }\n      }\n      }\n    }\n    return ansi_sequence_done();\n  }\n  case 's': { // Save\n    saved_x_ = b_->x();\n    saved_y_ = b_->y();\n    return ansi_sequence_done();\n  }\n  case 'u': {\n    b_->gotoxy(saved_x_, saved_y_);\n    if (callbacks_.move_) {\n      callbacks_.move_(saved_x_, saved_y_);\n    }\n    return ansi_sequence_done();\n  }\n  default: {\n    if (ansi_sequence_.size() < 2) {\n      return ansi_sequence_error(c);\n    }\n    // TODO(rushfan): Really should allow for any of these parameter or\n    // intermediate then final bytes:\n    // From Wikipedia: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences\n    // The ESC [ is followed by any number (including none) of \"parameter bytes\" in the\n    // range 0x300x3F (ASCII 09:;<=>?), then by any number of \"intermediate bytes\"\n    // in the range 0x200x2F (ASCII space and !\"#$%&'()*+,-./), then finally by a\n    // single \"final byte\" in the range 0x400x7E (ASCII @AZ[\\]^_`az{|}~)\n    if (std::isdigit(static_cast<unsigned char>(c)) || c == ';' || c == '?') {\n      ansi_sequence_.push_back(c);\n      return true;\n    }\n  } break;\n  }\n  VLOG(2) << \"Unknown ansi character: '\" << c << \"'; full sequence: \" << ansi_sequence_;\n  return true;\n}\n\nbool Ansi::ansi_sequence_done() {\n  state_ = AnsiMode::not_in_sequence;\n  ansi_sequence_.clear();\n  return true;\n}\n\nbool Ansi::ansi_sequence_error(char c) {\n  std::ostringstream ss;\n  ss << \"Previous Sequence: \";\n  for (const auto sc : ansi_sequence_) {\n    ss << \"['\" << sc << \"':\" << static_cast<int>(sc) << \"]\";\n  }\n  VLOG(2) << \"Invalid ansi char: ['\" << c << \"':\" << static_cast<int>(c) << \"] ; \" << ss.str();\n  write_not_in_sequence(ansi_sequence_);\n  write_not_in_sequence(c);\n  return ansi_sequence_done();\n}\n\nbool Ansi::write_not_in_sequence(char c) {\n  b_->write(c);\n  return true;\n}\n\nbool Ansi::attr(uint8_t a) {\n  b_->curatr(a);\n  return true;\n}\n\nbool Ansi::reset() {\n  state_ = AnsiMode::not_in_sequence;\n  ansi_sequence_.clear();\n  return true;\n}\n\nHeartAndPipeCodeFilter::HeartAndPipeCodeFilter(AnsiFilter* chain, std::vector<uint8_t> colors)\n    : chain_(chain), colors_(std::move(colors)) {}\n\nbool HeartAndPipeCodeFilter::write(char c) {\n\n  if (has_heart_) {\n    const uint8_t color = c - '0';\n    has_heart_ = false;\n    return attr(color);\n  }\n  if (c == 3) {\n    has_heart_ = true;\n    return true;\n  }\n  if (c == 10) {\n    // clear pipe and heart state and pass through\n    has_heart_ = false;\n    pipe_state_ = pipe_state::none;\n    pipe_text_.clear();\n    return chain_->write(c);\n  }\n  switch (pipe_state_) {\n  case pipe_state::none:\n    if (c == '|') {\n      pipe_state_ = pipe_state::pipe;\n      return true;\n    }\n    return chain_->write(c);\n  case pipe_state::pipe:\n    if (c == '#') {\n      pipe_state_ = pipe_state::wwiv_color;\n      pipe_text_.clear();\n      return true;\n    } if (std::isdigit(c)) {\n      pipe_text_.push_back(c);\n      pipe_state_ = pipe_state::dos_color;\n      return true;\n    }\n    // Not a valid color code.\n    pipe_text_.push_back(c);\n    return bad_pipe();\n  case pipe_state::wwiv_color:\n    // This one should be the color:\n    if (std::isdigit(c)) {\n      pipe_state_ = pipe_state::none;\n      const bool result = attr(c - '0');\n      pipe_text_.clear();\n      return result;\n    }\n    pipe_text_.push_back(c);\n    return bad_pipe();\n  case pipe_state::dos_color:\n    pipe_text_.push_back(c);\n    if (std::isdigit(c)) {\n      // Write through chain since it's ansi and not wwiv colors.\n      pipe_state_ = pipe_state::none;\n      const bool result = chain_->attr(wwiv::strings::to_number<uint8_t>(pipe_text_));\n      pipe_text_.clear();\n      return result;\n    }\n    return bad_pipe();\n  }\n  return chain_->write(c);\n}\n\nbool HeartAndPipeCodeFilter::attr(uint8_t a) {\n  if (a < colors_.size()) {\n    return chain_->attr(wwiv::stl::at(colors_, a));\n  }\n  return false;\n}\n\nbool HeartAndPipeCodeFilter::bad_pipe() {\n  chain_->write('|');\n  for (const auto& pc : pipe_text_) {\n    chain_->write(pc);\n  }\n  pipe_text_.clear();\n  pipe_state_ = pipe_state::none;\n  return true;\n}\n\nvoid HeartAndPipeCodeFilter::close() { \n  switch (pipe_state_) {\n  case  pipe_state::none: \n    break;\n  case  pipe_state::dos_color:\n  case  pipe_state::pipe:\n    chain_->write('|');\n    break;\n  case  pipe_state::wwiv_color:\n    chain_->write('|');\n    chain_->write('#');\n    break;\n  default: \n    break;\n  }\n  for (const auto& pc : pipe_text_) {\n    chain_->write(pc);\n  }\n  pipe_text_.clear();\n  pipe_state_ = pipe_state::none;\n\n  if (chain_) {\n    chain_->close();\n  }\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/ansi/ansi.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ANSI_H\n#define INCLUDED_SDK_ANSI_H\n\n#include \"sdk/ansi/vscreen.h\"\n#include <cstdint>\n#include <functional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::ansi {\n\nenum class AnsiMode { in_sequence, not_in_sequence };\n\ntypedef std::function<void(int, int)> move_cb;\n\nstruct AnsiCallbacks {\n  move_cb move_;\n};\n\nclass AnsiFilter {\npublic:\n  virtual ~AnsiFilter() = default;\n  // writes c to the filter/buffer.\n  virtual bool write(char c) = 0;\n  // Sets the attr to a for the next write\n  virtual bool attr(uint8_t a) = 0;\n  // Closes this filter and any chained filters/screen buffers.\n  virtual void close() = 0;\n};\n\nclass Ansi final : public AnsiFilter {\npublic:\n  Ansi(VScreen* b, AnsiCallbacks callbacks, uint8_t default_attr);\n  ~Ansi() override = default;\n\n  bool write(char c) override;\n\n  bool write(const std::string& s) {\n    auto result = true;\n    for (const auto c : s) {\n      if (!write(c)) {\n        result = false;\n      }\n    }\n    return result;\n  }\n\n  bool attr(uint8_t a) override;\n\n  bool reset();\n\n  [[nodiscard]] AnsiMode state() const noexcept { return state_; }\n\n  void close() override {\n    if (b_) { b_->close(); }\n  }\n\n\nprivate:\n  bool write_in_sequence(char c);\n  bool write_not_in_sequence(char c);\n  bool write_not_in_sequence(std::string& s) {\n    for (const auto c : s) {\n      write_not_in_sequence(c);\n    }\n    return true;\n  }\n  bool ansi_sequence_error(char c);\n  bool ansi_sequence_done();\n\n  VScreen* b_;\n  AnsiCallbacks callbacks_;\n  uint8_t default_attr_;\n  AnsiMode state_{AnsiMode::not_in_sequence};\n  std::string ansi_sequence_;\n\n  int saved_x_{0};\n  int saved_y_{0};\n};\n\nclass HeartAndPipeCodeFilter final : public AnsiFilter {\npublic:\n  HeartAndPipeCodeFilter(AnsiFilter* chain, std::vector<uint8_t> colors);\n  bool write(char c) override;\n  bool attr(uint8_t a) override;\n  bool bad_pipe();\n  void close() override;\n\nprivate:\n  enum class pipe_state { none, pipe, wwiv_color, dos_color };\n  AnsiFilter* chain_;\n  bool has_heart_{false};\n  const std::vector<uint8_t> colors_;\n  pipe_state pipe_state_{pipe_state::none};\n  std::string pipe_text_;\n};\n\n\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/ansi/ansi_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*            Copyright (C)2018-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/ansi/ansi.h\"\n#include \"sdk/ansi/framebuffer.h\"\n#include \"sdk/sdk_helper.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n#include <sdk/msgapi/parsed_message.h>\nusing namespace wwiv::sdk::msgapi;\n\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::ansi;\n\nclass AnsiTest : public testing::Test {\npublic:\n  AnsiTest()\n      : b(10), ansi(&b, {}, 0x07), heart_and_pipe(&ansi, {7, 11, 14, 13, 31, 10, 12, 9, 5, 3}) {}\n\n  void write(const std::string& s) {\n    ansi.write(s);\n    ansi.close();\n  }\n\n  bool write_hp(const std::string& s) {\n    auto result = true;\n    for (const auto c : s) {\n      if (!heart_and_pipe.write(c)) {\n        result = false;\n      }\n    }\n    heart_and_pipe.close();\n    return result;\n  }\n\n  void check(const std::vector<std::string>& lines) const {\n    EXPECT_EQ(wwiv::stl::ssize(lines), b.rows());\n    for (std::vector<std::string>::size_type i = 0; i < lines.size(); i++) {\n      EXPECT_EQ(lines[i], b.row_as_text(i)) << \"Line #\" << i;\n    }\n  }\n\n  FrameBuffer b;\n  Ansi ansi;\n  HeartAndPipeCodeFilter heart_and_pipe;\n};\n\nTEST_F(AnsiTest, ColorBlue) {\n  write(\"\\x1b[34;1mHello\");\n  EXPECT_EQ(9, b.curatr());\n  EXPECT_EQ(5, b.pos());\n  check({\"Hello\"});\n}\n\nTEST_F(AnsiTest, CSI_2J) {\n  write(\"\\x1b[34;1mHello\\x1b[2JH\");\n  EXPECT_EQ(9, b.curatr());\n  EXPECT_EQ(1, b.pos());\n  check({\"H\"});\n}\n\nTEST_F(AnsiTest, CSI_A_MoveUp) {\n  write(\"Hello\\n\\x1b[1AWorld\");\n  check({\"World\"});\n}\n\nTEST_F(AnsiTest, CSI_A_MoveUpTooFar) {\n  write(\"Hello\\n\\x1b[20AWorld\");\n  check({\"World\"});\n}\n\nTEST_F(AnsiTest, CSI_B_MoveDown) {\n  write(\"Hello\\n\\x1b[2BWorld\");\n  check({\"Hello\", \"\", \"\", \"World\"});\n}\n\nTEST_F(AnsiTest, CSI_C_Right) {\n  write(\"H\\x1b[4CW\");\n  check({\"H    W\"});\n}\n\nTEST_F(AnsiTest, CSI_D_Left) {\n  write(\"Hello\\x1b[4Da\");\n  check({\"Hallo\"});\n}\n\nTEST_F(AnsiTest, CSI_D_Left_TooFar) {\n  write(\"Hello\\x1b[40DY\");\n  check({\"Yello\"});\n}\n\nTEST_F(AnsiTest, CSI_K_ClearEOL) {\n  write(\"Hello\\nWorld\\n\\x1b[2A\\x1b[4C\\x1b[K\");\n  check({\"Hell      \", \"World\"});\n}\n\nTEST_F(AnsiTest, HeartAndPipe_HeartSmoke) {\n  write_hp(\"\\x03\"\"1Hello\");\n  check({\"Hello\"});\n  EXPECT_EQ(11, b.curatr());\n}\n\nTEST_F(AnsiTest, HeartAndPipe_StdPipe) {\n  write_hp(\"|12Hello\");\n  check({\"Hello\"});\n  EXPECT_EQ(12, b.curatr());\n}\n\nTEST_F(AnsiTest, HeartAndPipe_WWIVPipe) {\n  write_hp(\"|#5Hello\");\n  check({\"Hello\"});\n  EXPECT_EQ(10, b.curatr());\n}\n\nTEST_F(AnsiTest, HeartAndPipe_WWIVPipeMacro) {\n  write_hp(\"Hello |@N\");\n  check({\"Hello |@N\"});\n}\n\nTEST_F(AnsiTest, HeartAndPipe_WWIVPipeExpression) {\n  write_hp(\"|{a.b}\");\n  check({\"|{a.b}\"});\n}\n\n\nTEST_F(AnsiTest, XenosTagLine) {\n  std::string text =\n      R\"([^D]1\n[^D]2[^C]6  A  [^C]2.-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-.[^C]0\n[^D]3[^C]6 /[^C]5*[^C]6\\ [^C]2|[^C]4 /\\liens' /\\lcove! WWIV on Linux, Taguig, Metro Manila, Philippines [^C]2|\n[^D]4[^C]6/ v \\[^C]2`-=-=-=-=-=-=-=-=-=-=-=-[[^C]4 WWIV Development[^C]2]-=-=--=-=-=-=-=-=-=-=-=-=-'\n[^D]5\n[^D]6\n[^D]7)\";\n\n  StringReplace(&text, \"[^A]\", \"\\x01\");\n  StringReplace(&text, \"[^C]\", \"\\x03\");\n  StringReplace(&text, \"[^D]\", \"\\x04\");\n\n  const auto lines = SplitString(text, \"\\n\");\n\n  // Finally render it to the frame buffer to interpret heart codes, ansi, etc.\n  FrameBuffer b80(80);\n  Ansi ansib80(&b80, {}, 0x07);\n  HeartAndPipeCodeFilter heart(&ansib80, {7, 11, 14, 13, 31, 10, 12, 9, 5, 3});\n  for (auto& l : lines) {\n    for (const auto c : l) {\n      heart.write(c);\n    }\n    // This is the same as in split_wwiv_message\n    if (l.front() == 0x04) { // CD\n      ansib80.attr(7);\n      ansib80.reset();\n    }\n    heart.write('\\n');\n  }\n  heart.close();\n  b80.close();\n  auto screen_lines = b80.to_screen_as_lines();\n\n  const auto expected = fmt::format(\"{:c}4{:c}[0;31;40;1m/ v \\\\{:c}[33m`\", 0x04, 0x1b, 0x1b);\n  EXPECT_TRUE(starts_with(screen_lines[3], expected)) << JoinStrings(screen_lines, \"\\n\");\n}\n\n\nTEST_F(AnsiTest, HeartAndPipe_TrailingPipeCRLF) {\n  write_hp(\"| world |\\r\\n\");\n  check({ \"| world |\" });\n}\n\n\nTEST_F(AnsiTest, HeartAndPipe_TrailingPipe) {\n  write_hp(\"| world |\");\n  check({ \"| world |\" });\n}\n"
  },
  {
    "path": "sdk/ansi/framebuffer.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ansi/framebuffer.h\"\n\n#include \"core/stl.h\"\n#include <algorithm>\n#include \"sdk/ansi/makeansi.h\"\n\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::ansi {\n\nFrameBufferCell::FrameBufferCell() : FrameBufferCell(0, FRAMEBUFFER_DEFAULT_ATTRIBUTE) {}\n\nFrameBufferCell::FrameBufferCell(char c, uint8_t a) : a_(a), c_(c) {}\n\nFrameBuffer::FrameBuffer(int cols) : VScreen(), cols_(cols) { b_.reserve(cols_ * 100); }\n\nbool FrameBuffer::gotoxy(int x, int y) {\n  const auto xx = std::max(x, 0);\n  const auto yy = std::max(y, 0);\n  pos_ = (yy * cols_) + xx;\n  if (pos_ >= size_int(b_)) {\n    return grow(pos_);\n  }\n  return true;\n}\n\nbool FrameBuffer::clear() {\n  b_.clear();\n  pos_ = 0;\n  return true;\n}\n\nbool FrameBuffer::clear_eol() {\n  const auto start = pos_;\n  const auto end = (y() + 1) * cols_;\n  const auto a = curatr();\n  for (auto i = start; i < end; i++) {\n    put(i, ' ', a);\n  }\n  pos_ = end;\n  return true;\n}\n\nbool FrameBuffer::put(int pos, char c, uint8_t a) {\n  if (pos >= size_int(b_)) {\n    if (!grow(pos)) {\n      return false;\n    }\n  }\n  auto& b = b_[pos];\n  b.c(c);\n  b.a(a);\n  return true;\n}\n\nbool FrameBuffer::write(char c, uint8_t a) {\n  switch (c) {\n  case 0: // NOP\n    break;\n  case '\\r': {\n    const auto line = y();\n    return gotoxy(0, line);\n  }\n  case '\\n': {\n    const auto line = y() + 1;\n    return gotoxy(0, line);\n  }\n  default: {\n    return put(pos_++, c, a);\n  }\n  }\n\n  return true;\n}\n\nvoid FrameBuffer::close() {\n  if (!open_) {\n    return;\n  }\n  open_ = false;\n  if (b_.empty()) {\n    return;\n  }\n  for (auto i = size_int(b_) - 1; i >= 0;i--) {\n    if (b_[i].c() != 0) {\n      // Were at the end.\n      b_.resize(i + 1);\n      break;\n    }\n  }\n\n  auto f = false;\n  for (auto i = size_int(b_) - 1; i >= 0; i--) {\n    if (f && b_[i].c() == 0) {\n      b_[i].c(' ');\n    } else if (!f && b_[i].c() != 0) {\n      f = true;\n    }\n    if ((i % cols_) == 0) {\n      f = false;\n    }\n  }\n\n}\n\nbool FrameBuffer::grow(int pos) {\n  const auto e = std::max(pos + 1000, (y() + 1) * cols_);\n  b_.resize(e);\n  return true;\n}\n\nint FrameBuffer::rows() const {\n  return b_.empty() ? 0 : 1 + size_int(b_) / cols_;\n}\n\nstd::string FrameBuffer::row_as_text(int row) const {\n  const auto start = row * cols_;\n  const auto end = std::min<int>(size_int(b_), ((row + 1) * cols_));\n\n  std::string s;\n  s.reserve(end - start);\n  for (auto i = start; i < end; i++) {\n    s.push_back(b_[i].c());\n  }\n  const auto last = s.find_last_not_of('\\0');\n  if (last == std::string::npos) {\n    s.clear();\n  } else if (last + 1 != s.size()) {\n    s.resize(last + 1);\n  }\n\n  return s;\n}\n\nstd::vector<uint16_t> FrameBuffer::row_char_and_attr(int row) const {\n  const auto start = row * cols_;\n  const auto end = std::min<int>(size_int(b_), (row + 1) * cols_);\n\n  std::vector<uint16_t> s;\n  s.reserve(end - start);\n  for (auto i = start; i < end; i++) {\n    s.push_back(b_[i].w());\n  }\n  return s;\n}\n\nstd::vector<std::string> FrameBuffer::to_screen_as_lines() const { \n  std::vector<std::string> lines;\n  lines.reserve(rows());\n  int attr = 7;\n  for (auto i = 0; i < rows(); i++) {\n    auto row = row_char_and_attr(i);\n    std::ostringstream ss;\n    for (auto cc : row) {\n      const uint8_t a = cc >> 8;\n      const uint8_t c = cc & 0xff;\n      if (a != attr) {\n        ss << makeansi(a, attr);\n        attr = a;\n      }\n      ss << static_cast<char>(c);\n    }\n    lines.push_back(ss.str());\n  }\n  return lines;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/ansi/framebuffer.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_FRAMEBUFFER_H__\n#define __INCLUDED_SDK_FRAMEBUFFER_H__\n\n#include \"sdk/ansi/vscreen.h\"\n#include <cstdint>\n#include <string>\n#include <vector>\n\nnamespace wwiv {\nnamespace sdk {\nnamespace ansi {\n\nstatic constexpr int FRAMEBUFFER_DEFAULT_ATTRIBUTE = 0x07;\n\nclass FrameBufferCell {\npublic:\n  FrameBufferCell();\n  FrameBufferCell(char c, uint8_t a);\n  [[nodiscard]] char c() const noexcept { return c_; }\n  void c(char ch) { c_ = ch; }\n  [[nodiscard]] uint8_t a() const noexcept { return a_; }\n  void a(uint8_t aa) { a_ = aa; }\n\n  // As a composite word (high 8 bits are attribute, low are char)\n  [[nodiscard]] uint16_t w() const noexcept { return (a_ << 8) | (c_ & 0xff); }\n\nprivate:\n  uint8_t a_;\n  char c_;\n};\n\nclass FrameBuffer : public VScreen {\npublic:\n  explicit FrameBuffer(int cols);\n  /** Writes c using a, handles \\r and \\n */\n  bool write(char c, uint8_t a) override;\n  /** Moves the cursor to x,y */\n  bool gotoxy(int x, int y) override;\n  // Like CLS, clears everything viewable.\n  bool clear() override;\n  // clears from current position to the end of line.\n  bool clear_eol() override;\n  // Finalizes this frambuffer and shrinks the size to fit, etc.\n  void close() override;\n\n  /**\n   * Puts c using a at cursor position pos.\n   * Does not handle movement chars like \\r or \\n\n   */\n  bool put(int pos, char c, uint8_t a) override;\n\n  bool write(char c) override { return write(c, a_); }\n  void curatr(uint8_t a) override { a_ = a; }\n\n  [[nodiscard]] int cols() const noexcept override { return cols_; }\n  [[nodiscard]] int pos() const noexcept override { return pos_; }\n  [[nodiscard]] uint8_t curatr() const noexcept override { return a_; }\n  [[nodiscard]] int x() const noexcept override { return pos_ % cols_; }\n  [[nodiscard]] int y() const noexcept override { return pos_ / cols_; }\n\n  // Mostly used for debugging and tests.\n\n  // Number of total rows after the framebuffer has been closed.\n  [[nodiscard]] int rows() const;\n  // The raw text (without attributes) for row # 'row'\n  [[nodiscard]] std::string row_as_text(int row) const;\n  [[nodiscard]] std::vector<uint16_t> row_char_and_attr(int row) const;\n  [[nodiscard]] std::vector<std::string> to_screen_as_lines() const;\n\nprivate:\n  bool grow(int pos);\n  const int cols_;\n  std::vector<FrameBufferCell> b_;\n  uint8_t a_{7};\n  int pos_{0};\n  bool open_{true};\n};\n\n} // namespace ansi\n} // namespace sdk\n} // namespace wwiv\n\n#endif // __INCLUDED_SDK_FRAMEBUFFER_H__\n"
  },
  {
    "path": "sdk/ansi/framebuffer_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*            Copyright (C)2018-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include \"core/strings.h\"\n#include \"sdk/ansi/framebuffer.h\"\n#include \"sdk/sdk_helper.h\"\n\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::ansi;\n\nclass FrameBufferTest : public testing::Test {};\n\nTEST_F(FrameBufferTest, Cols) {\n  FrameBuffer b{10};\n  EXPECT_EQ(10, b.cols());\n}\n\nstatic void write(FrameBuffer& b, const std::string s) {\n  for (const auto c : s) {\n    b.write(c);\n  }\n}\n\nTEST_F(FrameBufferTest, SingleLine) {\n  FrameBuffer b{10};\n  b.curatr(3);\n  write(b, \"Hello\");\n  b.close();\n  EXPECT_EQ(5, b.pos());\n  EXPECT_EQ(1, b.rows());\n  EXPECT_EQ(\"Hello\", b.row_as_text(0));\n}\n\nTEST_F(FrameBufferTest, MultiLine) {\n  FrameBuffer b{10};\n  b.curatr(3);\n  write(b, \"Hello\\nWorld\");\n  b.close();\n  EXPECT_EQ(b.cols() + 5, b.pos());\n  EXPECT_EQ(2, b.rows());\n  EXPECT_EQ(\"Hello\", b.row_as_text(0));\n  EXPECT_EQ(\"World\", b.row_as_text(1));\n}\n\nTEST_F(FrameBufferTest, Goto) {\n  FrameBuffer b{10};\n  b.curatr(8);\n  b.gotoxy(0, 10);\n  write(b, \"\\xb0\"\"ello\");\n  b.close();\n  EXPECT_EQ(105, b.pos());\n  EXPECT_EQ(11, b.rows());\n  EXPECT_EQ(\"\\xb0\"\"ello\", b.row_as_text(10));\n  auto ca = b.row_char_and_attr(10);\n  EXPECT_EQ(5u, ca.size());\n  const auto f = static_cast<uint8_t>('\\xb0');\n  EXPECT_EQ((8 << 8) | f, ca[0]);\n  EXPECT_EQ((8 << 8) | 'e', ca[1]);\n  EXPECT_EQ((8 << 8) | 'l', ca[2]);\n  EXPECT_EQ((8 << 8) | 'l', ca[3]);\n  EXPECT_EQ((8 << 8) | 'o', ca[4]);\n}\n"
  },
  {
    "path": "sdk/ansi/localio_screen.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ansi/localio_screen.h\"\n\n#include \"core/stl.h\"\n#include \"local_io/curatr_provider.h\"\n\nusing namespace wwiv::local::io;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::ansi {\n\nclass LocalIOScreenCurAttrProvider : public wwiv::local::io::curatr_provider {\npublic:\n  LocalIOScreenCurAttrProvider(LocalIO* lio) : lio_(lio) {}\n  [[nodiscard]] uint8_t curatr() const noexcept override { return lio_->curatr(); }\n  void curatr(int n) override { lio_->curatr(n); }\n\nprivate:\n  LocalIO* lio_;\n};\n\n\nLocalIOScreen::LocalIOScreen(LocalIO* io, int cols)\n    : VScreen(), io_(io), cols_(cols),\n      curatr_provider_(std::make_unique<LocalIOScreenCurAttrProvider>(io)) {}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/ansi/localio_screen.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_LOCALIO_SCREEN_H__\n#define __INCLUDED_SDK_LOCALIO_SCREEN_H__\n\n#include \"local_io/curatr_provider.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/ansi/vscreen.h\"\n#include <cstdint>\n#include <memory>\n\nnamespace wwiv {\nnamespace sdk {\nnamespace ansi {\n\nclass LocalIOScreen : public VScreen {\npublic:\n  explicit LocalIOScreen(local::io::LocalIO* io, int cols);\n  virtual ~LocalIOScreen() = default;\n\n  /** Writes c using a, handles \\r and \\n */\n  bool write(char c, uint8_t) override {\n    return write(c);\n  }\n  /** Moves the cursor to x,y */\n  bool gotoxy(int x, int y) override {\n    io_->GotoXY(x, y);\n    return true;\n  }\n  // Like CLS, clears everything viewable.\n  bool clear() override {\n    io_->Cls();\n    return true;\n  }\n  // clears from current position to the end of line.\n  bool clear_eol() override {\n    io_->ClrEol();\n    return true;\n  }\n  // Finalizes this frambuffer and shrinks the size to fit, etc.\n  void close() override {}\n\n  /**\n   * Puts c using a at cursor position pos.\n   * Does not handle movement chars like \\r or \\n\n   */\n  bool put(int pos, char c, uint8_t a) override {\n    const auto x = pos % cols_;\n    const auto y = pos / cols_;\n    io_->PutsXYA(x, y, a, std::string(1, c));\n    return true;\n  }\n\n  bool write(char c) override {\n    io_->Putch(c);\n    return true;\n  }\n\n  void curatr(uint8_t a) override { curatr_provider_->curatr(a); }\n\n  [[nodiscard]] int cols() const noexcept override { return cols_; }\n  [[nodiscard]] int pos() const noexcept override { return (y() * cols()) + x(); }\n  [[nodiscard]] uint8_t curatr() const noexcept override { return curatr_provider_->curatr(); }\n  [[nodiscard]] int x() const noexcept override { return io_->WhereX(); }\n  [[nodiscard]] int y() const noexcept override { return io_->WhereY(); }\n\nprivate:\n  local::io::LocalIO* io_;\n  int cols_;\n  std::unique_ptr<wwiv::local::io::curatr_provider> curatr_provider_;\n};\n\n} // namespace ansi\n} // namespace sdk\n} // namespace wwiv\n\n#endif // __INCLUDED_SDK_LOCALIO_SCREEN_H__\n"
  },
  {
    "path": "sdk/ansi/makeansi.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ansi/makeansi.h\"\n\n#include <cstdint>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::ansi {\n\n\nstatic void addto(std::string* ansi_str, int num) {\n  if (ansi_str->empty()) {\n    ansi_str->append(\"\\x1b[\");\n  } else {\n    ansi_str->append(\";\");\n  }\n  ansi_str->append(std::to_string(num));\n}\n\nstd::string makeansi(int attr, int current_attr) {\n  static const uint8_t ansi_color_map[] = {'0', '4', '2', '6', '1', '5', '3', '7'};\n\n  if (current_attr == attr) {\n    return \"\";\n  }\n\n  auto catr = current_attr;\n  std::string out;\n  if ((catr & 0x88) ^ (attr & 0x88)) {\n    addto(&out, 0);\n    addto(&out, 30 + ansi_color_map[attr & 0x07] - '0');\n    addto(&out, 40 + ansi_color_map[(attr & 0x70) >> 4] - '0');\n    catr = (attr & 0x77);\n  }\n  if ((catr & 0x07) != (attr & 0x07)) {\n    addto(&out, 30 + ansi_color_map[attr & 0x07] - '0');\n  }\n  if ((catr & 0x70) != (attr & 0x70)) {\n    addto(&out, 40 + ansi_color_map[(attr & 0x70) >> 4] - '0');\n  }\n  if ((catr & 0x08) != (attr & 0x08)) {\n    addto(&out, 1);\n  }\n  if ((catr & 0x80) != (attr & 0x80)) {\n    // Italics will be generated\n    addto(&out, 3);\n  }\n  if (!out.empty()) {\n    out += \"m\";\n  }\n  return out;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/ansi/makeansi.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MAKEANSI_H\n#define INCLUDED_SDK_MAKEANSI_H\n\n#include <string>\n\nnamespace wwiv::sdk::ansi {\n\n/** \n * Passed to this function is a one-byte attribute as defined for IBM type\n * screens.  Returned is a string which, when printed, will change the\n * display to the color desired, from the current function.\n */\nstd::string makeansi(int attr, int current_attr);\n\n} // namespace wwiv::sdk::ansi\n\n#endif // INCLUDED_SDK_MAKEANSI_H\n"
  },
  {
    "path": "sdk/ansi/makeansi_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/strings.h\"\n#include \"sdk/ansi/makeansi.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::sdk::ansi;\n\nclass MakeAnsiTest : public ::testing::Test {};\n\nTEST_F(MakeAnsiTest, NOOP) {\n  EXPECT_EQ(\"\", makeansi(7, 7));\n}\n\nTEST_F(MakeAnsiTest, Foreground) {\n  EXPECT_EQ(\"\\x1B[30m\", makeansi(0, 7));\n  EXPECT_EQ(\"\\x1B[34m\", makeansi(1, 7));\n  EXPECT_EQ(\"\\x1B[32m\", makeansi(2, 7));\n  EXPECT_EQ(\"\\x1B[36m\", makeansi(3, 7));\n  EXPECT_EQ(\"\\x1B[31m\", makeansi(4, 7));\n  EXPECT_EQ(\"\\x1B[35m\", makeansi(5, 7));\n  EXPECT_EQ(\"\\x1B[33m\", makeansi(6, 7));\n  EXPECT_EQ(\"\\x1B[37m\", makeansi(7, 0));\n  EXPECT_EQ(\"\\x1B[0;30;40;1m\", makeansi(8, 7));\n  EXPECT_EQ(\"\\x1B[34m\", makeansi(9, 8));\n  EXPECT_EQ(\"\\x1B[32m\", makeansi(10, 8));\n  EXPECT_EQ(\"\\x1B[36m\", makeansi(11, 8));\n  EXPECT_EQ(\"\\x1B[31m\", makeansi(12, 8));\n  EXPECT_EQ(\"\\x1B[35m\", makeansi(13, 8));\n  EXPECT_EQ(\"\\x1B[33m\", makeansi(14, 8));\n  EXPECT_EQ(\"\\x1B[37m\", makeansi(15, 8));\n}\n\nTEST_F(MakeAnsiTest, Foreground_BrightToDim) {\n  EXPECT_EQ(\"\\x1B[0;37;40m\", makeansi(7, 9));\n}\n\nTEST_F(MakeAnsiTest, Foreground_DimToBright) {\n  EXPECT_EQ(\"\\x1B[0;34;40;1m\", makeansi(9, 7));\n}\n\nTEST_F(MakeAnsiTest, Background) {\n  EXPECT_EQ(\"\\x1B[0;37;44m\", makeansi(23, 9));\n  EXPECT_EQ(\"\\x1B[0;33;44;1m\", makeansi(30, 23));\n}\n"
  },
  {
    "path": "sdk/ansi/vscreen.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ansi/vscreen.h\"\n\nnamespace wwiv::sdk::ansi {\n\nVScreen::VScreen() = default;\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/ansi/vscreen.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_VSCREEN_H__\n#define __INCLUDED_SDK_VSCREEN_H__\n\n#include <cstdint>\n#include <vector>\n\nnamespace wwiv {\nnamespace sdk {\nnamespace ansi {\n\nstatic constexpr int VSCREEN_DEFAULT_ATTRIBUTE = 0x07;\n\nclass VScreen {\npublic:\n  explicit VScreen();\n  virtual ~VScreen() = default;\n\n  /** Writes c using a, handles \\r and \\n */\n  virtual bool write(char c, uint8_t a) = 0;\n  /** Moves the cursor to x,y */\n  virtual bool gotoxy(int x, int y) = 0;\n  // Like CLS, clears everything viewable.\n  virtual bool clear() = 0;\n  // clears from current position to the end of line.\n  virtual bool clear_eol() = 0;\n  // Finalizes this frambuffer and shrinks the size to fit, etc.\n  virtual void close() = 0;\n\n  /**\n   * Puts c using a at cursor position pos.\n   * Does not handle movement chars like \\r or \\n\n   */\n  virtual bool put(int pos, char c, uint8_t a) = 0;\n\n  virtual bool write(char c) = 0;\n  virtual void curatr(uint8_t a) = 0;\n\n  [[nodiscard]] virtual int cols() const noexcept = 0;\n  [[nodiscard]] virtual int pos() const noexcept = 0;\n  [[nodiscard]] virtual uint8_t curatr() const noexcept = 0;\n  [[nodiscard]] virtual int x() const noexcept = 0;\n  [[nodiscard]] virtual int y() const noexcept = 0;\n\n};\n\n} // namespace ansi\n} // namespace sdk\n} // namespace wwiv\n\n#endif // __INCLUDED_SDK_VSCREEN_H__\n"
  },
  {
    "path": "sdk/arword.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/arword.h\"\n\n#include <string>\n#include \"core/strings.h\"\n\nusing namespace wwiv::strings;\n\n/*\n * Returns bitmapped word representing an AR or DAR string.\n */\nuint16_t str_to_arword(const std::string& arstr) {\n  uint16_t rar = 0;\n  const auto s = ToStringUpperCase(arstr);\n\n  for (int i = 0; i < 16; i++) {\n    if (s.find(static_cast<char>(i + 'A')) != std::string::npos) {\n      rar |= (1 << i);\n    }\n  }\n  return rar;\n}\n\n/*\n * Converts an int to a string representing those ARs (DARs).\n * or '-' on an empty string.\n */\nstd::string word_to_arstr(int ar, const std::string& empty_ar_str) {\n\n  if (!ar) {\n    return empty_ar_str;\n  }\n\n  std::string arstr;\n  for (auto i = 0; i < 16; i++) {\n    if ((1 << i) & ar) {\n      arstr.push_back(static_cast<char>('A' + i));\n    } else {\n      arstr.push_back(' ');\n    }\n  }\n  return arstr.empty() ? empty_ar_str : arstr;\n}\n\n/*\n * Converts an int to a string representing those ARs (DARs).\n * or '-' on an empty string.\n */\nstd::string word_to_arstr_nopadding(int ar, const std::string& empty_ar_str) {\n\n  if (!ar) {\n    return empty_ar_str;\n  }\n\n  std::string arstr;\n  for (auto i = 0; i < 16; i++) {\n    if ((1 << i) & ar) {\n      arstr.push_back(static_cast<char>('A' + i));\n    }\n  }\n  return arstr.empty() ? empty_ar_str : arstr;\n}\n\n"
  },
  {
    "path": "sdk/arword.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_BBS_ARWORD_H\n#define INCLUDED_BBS_ARWORD_H\n\n#include <cstdint>\n#include <string>\n\n/**\n * Returns a proper AR string \"AB             P\", into the integer form.\n */\nuint16_t str_to_arword(const std::string& arstr);\n\n/**\n * Returns the int form of ar as proper AR string, Example: \"AB             P\"\n */\nstd::string word_to_arstr(int ar, const std::string& empty_ar_str);\n\n/**\n * Returns the int form of ar as a string, no padding. Example: \"ABP\"\n */\nstd::string word_to_arstr_nopadding(int ar, const std::string& empty_ar_str);\n\n#endif  // INCLUDED_BBS_ARWORD_H"
  },
  {
    "path": "sdk/bbs_directories.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_BBS_DIRECTORIES_H\n#define INCLUDED_SDK_BBS_DIRECTORIES_H\n\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk {\n\n\nclass BbsDirectories {\npublic:\n  [[nodiscard]] virtual std::filesystem::path root_directory() const = 0;\n  [[nodiscard]] virtual std::filesystem::path datadir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path msgsdir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path gfilesdir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path menudir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path dloadsdir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path scriptdir() const = 0;\n  [[nodiscard]] virtual std::filesystem::path logdir() const = 0;\n\n  /**\n   * Returns the scrarch directory for a given node.\n   */\n  [[nodiscard]] virtual std::filesystem::path scratch_dir(int node) const = 0;\n};\n\n} // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/bbslist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/bbslist.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/graphs.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/connect.h\"\n#include <algorithm>\n#include <cctype>\n#include <cmath>\n#include <iterator>\n#include <map>\n#include <optional>\n#include <sstream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::sdk {\n\n// [[ VisibleForTesting ]]\nbool ParseBbsListNetLine(const std::string& ss, net_system_list_rec* con, int32_t* reg_no) {\n  if (ss.empty() || ss[0] != '@') {\n    // skip empty lines and those not starting with @.\n    return false;\n  }\n  memset(con, 0, sizeof(net_system_list_rec));\n  *reg_no = 0;\n  VLOG(2) << ss;\n\n  for (auto iter = ss.begin(); iter != ss.end(); ++iter) {\n      switch (*iter) {\n      case '@': {\n        con->sysnum = to_number<uint16_t>(std::string(++iter, ss.end()));\n      } break;\n      case '&':\n        con->other |= other_net_coord;\n        break;\n      case '%':\n        con->other |= other_group_coord;\n        break;\n      case '^':\n        con->other |= other_area_coord;\n        break;\n      case '~':\n        con->other |= other_subs_coord;\n        break;\n      case '$':\n        con->other |= other_inet;\n        break;\n      case '\\\\':\n        con->other |= other_fido;\n        break;\n      case '|':\n        con->other |= other_telnet;\n        break;\n      case '<':\n        con->other |= other_no_links;\n        break;\n      case '>':\n        con->other |= other_fts_blt;\n        break;\n      case '!':\n        con->other |= other_direct;\n        break;\n      case '/':\n        con->other |= other_unregistered;\n        break;\n      case '?':\n        con->other |= other_fax;\n        break;\n      case '_':\n        con->other |= other_end_system;\n        break;\n      case '+':\n        con->other |= other_net_server;\n        break;\n      case '=':\n        con->other |= other_unused;\n        break;\n      // Phone number\n      case '*': {\n        ++iter;  // skip past *\n        std::string phone_number;\n        while (iter != ss.end() && !isspace(*iter)) {\n          phone_number.push_back(*iter++);\n        }\n        to_char_array_trim(con->phone, phone_number);\n      }\n      break;\n      case '#': {\n        con->speed = to_number<uint16_t>(std::string(++iter, ss.end()));\n      } break;\n      // Reg Number.\n      case '[': {\n        ++iter;  // skip past [\n        std::string reg_number;\n        while (iter != ss.end() && *iter != ']') {\n          reg_number.push_back(*iter++);\n        }\n        *reg_no = to_number<int>(reg_number);\n      } break;\n      case '\\\"': {\n        ++iter;  // skip past first \"\n        std::string name;\n        while (iter != ss.end() && *iter != '\\\"') {\n          name.push_back(*iter++);\n        }\n        to_char_array_trim(con->name, name);\n      }\n      break;\n      default:\n        break;\n      }\n    }\n    return true;\n}\n\nstatic bool ParseBbsListNetFile(\n  std::map<uint16_t, net_system_list_rec>* node_config_map,\n  std::map<uint16_t, int32_t>* reg_number_map,\n  const std::filesystem::path& network_dir,\n  wwiv::graphs::Graph& graph,\n  uint16_t net_node_number) {\n  TextFile bbs_list_file(FilePath(network_dir, BBSLIST_NET), \"rt\");\n  if (!bbs_list_file.IsOpen()) {\n    return false;\n  }\n\n  // A line will be of the format @node *phone options [reg] \"name\"\n  std::string line;\n  while (bbs_list_file.ReadLine(&line)) {\n    StringTrim(&line);\n    net_system_list_rec node_config{};\n    int32_t reg_number;\n    if (ParseBbsListNetLine(line, &node_config, &reg_number)) {\n      // Parsed a line correctly.\n      auto path = graph.shortest_path_to(node_config.sysnum);\n      auto cost = graph.cost_to(node_config.sysnum);\n      if (!std::isfinite(cost)) {\n        if(VLOG_IS_ON(2)) {\n          std::ostringstream ss; \n          VLOG(2) << \"high cost \" << cost << \" to \" << node_config.sysnum;\n          ss << \"Path to \" << node_config.sysnum << \": \";\n          std::copy(path.begin(), path.end(), std::ostream_iterator<uint16_t>(ss, \" \"));\n          VLOG(2) << ss.str();\n          VLOG(2) << graph.DumpCosts();\n        }\n      }\n      if (graph.has_node(node_config.sysnum) && path.front() == net_node_number) {\n        path.pop_front();\n        // We have a path...\n        //std::copy(path.begin(), path.end(), std::ostream_iterator<uint16_t>(std::cout, \" \"));\n        node_config.numhops = static_cast<int16_t>(path.size());\n        node_config.xx.cost = cost;\n        if (!path.empty()) {\n          node_config.forsys = path.front();\n        } else {\n          node_config.forsys = node_config.sysnum;\n        }\n      } else {\n        VLOG(2) << \"no path to \" << node_config.sysnum;\n        node_config.numhops = 10000;\n        node_config.xx.cost = 10000;\n        node_config.forsys = std::numeric_limits<uint16_t>::max();\n      }\n      node_config_map->emplace(node_config.sysnum, node_config);\n      reg_number_map->emplace(node_config.sysnum, reg_number);\n    }\n  }\n  return true;\n}\n\n// static \nBbsListNet BbsListNet::ParseBbsListNet(uint16_t net_node_number,\n                                       const std::filesystem::path& network_dir) {\n  BbsListNet b;\n\n  VLOG(3) << \"Processing \" << network_dir;\n  // We now need to add in cost and routing information.\n  const Connect connect(network_dir);\n\n  // Build the network graph\n  graphs::Graph graph(net_node_number, std::numeric_limits<uint16_t>::max());\n  for (const auto& e : connect.node_config()) {\n    const auto& c = e.second;\n    const auto source = c.sysnum;\n    \n    auto cost_iter = c.cost.begin();\n    for (auto dest_iter = c.connect.begin(); dest_iter != std::end(c.connect); ++dest_iter, ++cost_iter) {\n      graph.add_edge(source, *dest_iter, *cost_iter);\n    }\n  }\n\n  ParseBbsListNetFile(&b.node_config_, &b.reg_number_, network_dir, graph, net_node_number);\n  return b;\n}\n\n// static \nBbsListNet BbsListNet::ReadBbsDataNet(const std::filesystem::path& network_dir) {\n  BbsListNet b;\n\n  if (auto file = DataFile<net_system_list_rec>(FilePath(network_dir, BBSDATA_NET))) {\n    std::vector<net_system_list_rec> system_list;\n    file.ReadVector(system_list);\n    for (const auto& s : system_list) {\n      b.node_config_.emplace(s.sysnum, s);\n    }\n  }\n  return b;\n}\n\nBbsListNet::BbsListNet() = default;\n\nBbsListNet::BbsListNet(std::initializer_list<net_system_list_rec> l) {\n  for (const auto& r : l) {\n    node_config_.emplace(r.sysnum, r);\n  }\n}\n\nBbsListNet::~BbsListNet() = default;\n\nstd::optional<net_system_list_rec> BbsListNet::node_config_for(int node) const {\n  if (const auto iter = node_config_.find(static_cast<uint16_t>(node)); iter != end(node_config_)) {\n    return {iter->second};\n  }\n  return std::nullopt;\n}\n\nstatic std::string DumpBbsListNet(const net_system_list_rec& n) {\n  std::ostringstream ss;\n  ss << \"sysnum:        \" << n.sysnum << std::endl;\n  ss << \"name:          \" << n.name << std::endl;\n  ss << \"forsys:        \" << n.forsys << std::endl;\n  ss << \"numhops:       \" << n.numhops << std::endl;\n  ss << \"other:         \" << n.other << std::endl;\n  ss << \"phone:         \" << n.phone << std::endl;\n  ss << \"speed:         \" << n.speed << std::endl;\n  ss << \"cost:          \" << n.xx.cost << std::endl;\n  ss << \"rout_fact:     \" << n.xx.rout_fact << std::endl;\n  return ss.str();\n}\n\nstd::string BbsListNet::ToString() const {\n  std::ostringstream ss;\n  for (const auto& kv : node_config_) {\n    ss << DumpBbsListNet(kv.second) << std::endl;\n  }\n  return ss.str();\n}\n\n} // namespace wwiv\n\n"
  },
  {
    "path": "sdk/bbslist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_BBSLIST_H\n#define INCLUDED_SDK_BBSLIST_H\n\n#include <filesystem>\n#include <initializer_list>\n#include <map>\n#include <optional>\n#include <string>\n\nstruct net_system_list_rec;\n\nnamespace wwiv::sdk {\n  \nclass BbsListNet {\n public:\n   static BbsListNet ParseBbsListNet(uint16_t net_node_number, const std::filesystem::path& network_dir);\n   static BbsListNet ReadBbsDataNet(const std::filesystem::path& network_dir);\n  // VisibleForTesting\n  BbsListNet(std::initializer_list<net_system_list_rec> l);\n  BbsListNet(const wwiv::sdk::BbsListNet&) = default;\n  virtual ~BbsListNet();\n  [[nodiscard]] std::optional<net_system_list_rec> node_config_for(int node) const;\n  BbsListNet& operator=(const BbsListNet& rhs) { node_config_ = rhs.node_config_; return *this; }\n  [[nodiscard]] std::string ToString() const;\n\n  [[nodiscard]] bool empty() const { return node_config_.empty(); }\n  [[nodiscard]] const std::map<uint16_t, net_system_list_rec>& node_config() const { return node_config_; }\n  [[nodiscard]] const std::map<uint16_t, int32_t>& reg_number() const { return reg_number_; }\n\n private:\n   BbsListNet();\n   std::map<uint16_t, net_system_list_rec> node_config_;\n   std::map<uint16_t, int32_t> reg_number_;\n};\n\nbool ParseBbsListNetLine(const std::string& line, net_system_list_rec* config, int32_t* reg_number);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/bbslist_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2022-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"sdk/bbslist.h\"\n#include \"sdk/net/legacy_net.h\"\n#include <string>\n\nusing namespace wwiv::sdk;\n\nTEST(SdkBbsListTest, Smoke) {\n  net_system_list_rec node_config{};\n  int32_t reg_number;\n  std::string line = \"@513        *415-754-LNET #33600        !      [11259]  \\\"Mystic Rhythms\\\"\";\n  ASSERT_TRUE(ParseBbsListNetLine(line, &node_config, &reg_number));\n\n  EXPECT_EQ(11259, reg_number);\n  EXPECT_EQ(513, node_config.sysnum);\n  EXPECT_STREQ(\"Mystic Rhythms\", node_config.name); // truncated to 40 chars\n  EXPECT_STREQ(\"415-754-LNET\", node_config.phone);\n  EXPECT_TRUE(node_config.other & other_direct);\n}\n\nTEST(SdkBbsListTest, TruncatedName) {\n  net_system_list_rec node_config{};\n  int32_t reg_number;\n  std::string line =\n      \"@137 *999-999-INET #33600 ! [ ] \\\"Public Electronic Networked Information System\\\"\";\n  ASSERT_TRUE(ParseBbsListNetLine(line, &node_config, &reg_number));\n\n  EXPECT_STREQ(\"Public Electronic Networked Information\",\n               node_config.name); // truncated to 40 chars\n}\n"
  },
  {
    "path": "sdk/chains.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/chains.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/acs/expr.h\"\n#include \"sdk/chains_cereal.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include <type_traits>\n#include <vector>\n\nusing cereal::make_nvp;\nusing cereal::specialization;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nnamespace wwiv::sdk {\n\nchain_exec_mode_t& operator++(chain_exec_mode_t& t) {\n  using T = std::underlying_type<chain_exec_mode_t>::type;\n  t = (t == chain_exec_mode_t::sock_unix ? chain_exec_mode_t::none\n                                     : static_cast<chain_exec_mode_t>(static_cast<T>(t) + 1));\n  return t;\n}\n\nchain_exec_mode_t operator++(chain_exec_mode_t& t, int) {\n  using T = std::underlying_type<chain_exec_mode_t>::type;\n  const auto old = t;\n  t = (t == chain_exec_mode_t::sock_unix ? chain_exec_mode_t::none\n                                     : static_cast<chain_exec_mode_t>(static_cast<T>(t) + 1));\n  return old;\n}\n\nchain_exec_dir_t& operator++(chain_exec_dir_t& t) {\n  t = (t == chain_exec_dir_t::bbs ? chain_exec_dir_t::temp : chain_exec_dir_t::bbs);\n  return t;\n}\n\nchain_exec_dir_t operator++(chain_exec_dir_t& t, int) {\n  const auto old = t;\n  t = (t == chain_exec_dir_t::bbs ? chain_exec_dir_t::temp : chain_exec_dir_t::bbs);\n  return old;\n}\n\nconst Chains::size_type Chains::npos; // reserve space.\n\nChains::Chains(const std::filesystem::path& datadir) : datadir_(datadir) {\n  if (!File::Exists(FilePath(datadir_, CHAINS_JSON)) &&\n    !File::Exists(FilePath(datadir_, CHAINS_DAT))) {\n    return;\n  }\n\n  initialized_ = Load();\n  if (!initialized_) {\n    LOG(ERROR) << \"Failed to read \" << CHAINS_JSON << \" or \" << CHAINS_DAT;\n  }\n}\n\nChains::Chains(const Config& config) : Chains(config.datadir()) {}\n\nChains::~Chains() = default;\n\nbool Chains::insert(size_type n, chain_t r) { return insert_at(chains_, n, r); }\n\nbool Chains::erase(size_type n) { return erase_at(chains_, n); }\n\nbool Chains::Load() {\n  if (LoadFromJSON()) {\n    return true;\n  }\n  return LoadFromDat();\n}\n\nbool Chains::LoadFromJSON() {\n  chains_.clear();\n  JsonFile json(FilePath(datadir_, CHAINS_JSON), \"chains\", chains_, 1);\n  return json.Load();\n}\n\nbool Chains::LoadFromDat() {\n  DataFile<chainfilerec_422> old_chains(FilePath(datadir_, CHAINS_DAT),\n                                    File::modeBinary | File::modeReadOnly, File::shareDenyNone);\n  if (!old_chains) {\n    return false;\n  }\n\n  std::vector<chainfilerec_422> old;\n  std::vector<chainregrec_422> reg;\n\n  if (!old_chains.ReadVector(old)) {\n    return false;\n  }\n  DataFile<chainregrec_422> regfile(FilePath(datadir_, CHAINS_REG),\n                                File::modeBinary | File::modeReadOnly, File::shareDenyNone);\n  regfile.ReadVector(reg);\n\n  for (auto i = 0; i < wwiv::stl::ssize(old); i++) {\n    const auto& o = old.at(i);\n    chain_t c{};\n    c.filename = o.filename;\n    c.description = o.description;\n    if (o.ansir & ansir_emulate_fossil) {\n      c.exec_mode = chain_exec_mode_t::fossil;\n    } else if (o.ansir & ansir_stdio) {\n      c.exec_mode = chain_exec_mode_t::stdio;\n    } else if (!(o.ansir & ansir_no_DOS)) {\n      c.exec_mode = chain_exec_mode_t::dos;\n    } else {\n      c.exec_mode = chain_exec_mode_t::none;\n    }\n    c.dir = (o.ansir & ansir_temp_dir) ? chain_exec_dir_t::temp : chain_exec_dir_t::bbs;\n    c.ansi = (o.ansir & ansir_ansi);\n    c.local_only = (o.ansir & ansir_local_only);\n    c.multi_user = (o.ansir & ansir_multi_user);\n\n    if (i < wwiv::stl::ssize(reg)) {\n      // We have a chain.reg entry\n      const auto& r = reg.at(i);\n      for (auto rbc : r.regby) {\n        if (rbc > 0) {\n          c.regby.insert(rbc);\n        }\n      }\n      acs::AcsExpr ae;\n      c.acs = ae.min_sl(o.sl).ar_int(o.ar).min_age(r.minage).max_age(r.maxage).get();\n      c.usage = r.usage;\n    } else {\n      acs::AcsExpr ae;\n      c.acs = ae.min_sl(o.sl).ar_int(o.ar).get();\n    }\n\n    chains_.emplace_back(c);\n  }\n  return true;\n}\n\nbool Chains::Save() {\n  const auto dat = SaveToDat();\n  const auto json = SaveToJSON();\n\n  return dat && json;\n}\n\nbool Chains::SaveToJSON() {\n  JsonFile json(FilePath(datadir_, CHAINS_JSON), \"chains\", chains_, 1);\n  return json.Save();\n}\n\nbool Chains::SaveToDat() {\n  std::vector<chainfilerec_422> cdisk;\n  std::vector<chainregrec_422> rdisk;\n  for (const auto& from : chains_) {\n    chainfilerec_422 c{};\n    chainregrec_422 r{};\n    to_char_array(c.filename, from.filename);\n    to_char_array(c.description, from.description);\n    c.ansir = static_cast<uint8_t>(to_ansir(from) & 0xff);\n    //c.sl = from.sl;\n    //c.ar = from.ar;\n    //r.minage = from.minage;\n    //r.maxage = from.maxage;\n    r.usage = from.usage;\n    int regbycount = 0;\n    for (const auto& rbc : from.regby) {\n      if (regbycount > 4) {\n        break;\n      }\n      r.regby[regbycount] = rbc;\n      regbycount++;\n    }\n    cdisk.emplace_back(c);\n    rdisk.emplace_back(r);\n  }\n  bool cwritten;\n  auto rwritten{false};\n  {\n    DataFile<chainfilerec_422> cfile(FilePath(datadir_, CHAINS_DAT),\n                                 File::modeBinary | File::modeReadWrite | File::modeCreateFile |\n                                     File::modeTruncate,\n                                 File::shareDenyReadWrite);\n    if (!cfile) {\n      return false;\n    }\n    cwritten = cfile.WriteVector(cdisk);\n  }\n  {\n    if (DataFile<chainregrec_422> rfile(FilePath(datadir_, CHAINS_REG),\n                                        File::modeBinary | File::modeReadWrite | File::modeCreateFile |\n                                        File::modeTruncate,\n                                        File::shareDenyReadWrite); rfile) {\n      rwritten = rfile.WriteVector(rdisk);\n    }\n  }\n  return cwritten && rwritten;\n}\n\nbool Chains::HasRegisteredChains() const {\n  for (const auto& c : chains_) {\n    if (!c.regby.empty()) {\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid Chains::increment_chain_usage(int num) { wwiv::stl::at(chains_, num).usage++;\n}\n\n// static\nuint16_t Chains::to_ansir(const chain_t& c) {\n  uint16_t r{ansir_no_DOS};\n\n  if (c.ansi) {\n    r |= ansir_ansi;\n  }\n  if (c.exec_mode == chain_exec_mode_t::dos) {\n    r &= ~ansir_no_DOS;\n  } else if (c.exec_mode == chain_exec_mode_t::fossil) {\n    r |= ansir_emulate_fossil;\n  } else if (c.exec_mode == chain_exec_mode_t::netfoss) {\n    r |= ansir_netfoss;\n  } else if (c.exec_mode == chain_exec_mode_t::stdio) {\n    r |= ansir_stdio;\n  } else if (c.exec_mode == chain_exec_mode_t::none) {\n    // Do nothing\n  }\n  if (c.dir == chain_exec_dir_t::temp) {\n    r |= ansir_temp_dir;\n  }\n  if (c.local_only) {\n    r |= ansir_local_only;\n  }\n  if (c.multi_user) {\n    r |= ansir_multi_user;\n  }\n  return r;\n}\n\nuint32_t Chains::to_exec_flags(const chain_t& c) { \n  auto r = to_exec_flags(c.exec_mode); \n  if (c.dir == chain_exec_dir_t::temp) {\n    r |= EFLAG_TEMP_DIR;\n  }\n  return r;\n}\n\n// static\nuint32_t Chains::to_exec_flags(chain_exec_mode_t m) { \n  switch (m) {\n  case chain_exec_mode_t::fossil:\n    return EFLAG_SYNC_FOSSIL;\n  case chain_exec_mode_t::stdio:\n    return EFLAG_STDIO;\n  case chain_exec_mode_t::netfoss:\n    // NetFoss implies temp dir too.\n    return EFLAG_NETFOSS | EFLAG_TEMP_DIR;\n  case chain_exec_mode_t::sock_port:\n    return EFLAG_LISTEN_SOCK;\n  case chain_exec_mode_t::sock_unix:\n    return EFLAG_UNIX_SOCK;\n  case chain_exec_mode_t::dos:\n    return EFLAG_COMIO;\n  case chain_exec_mode_t::none:\n  default:\n    return 0;\n  }\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/chains.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*                Copyright (C)2019, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CHAINS_H\n#define INCLUDED_SDK_CHAINS_H\n\n#include \"core/stl.h\"\n#include \"core/wwivport.h\"\n#include \"sdk/config.h\"\n#include <initializer_list>\n#include <filesystem>\n#include <set>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\nenum class chain_exec_mode_t : uint8_t { none = 0, dos, fossil, stdio, netfoss, sock_port, sock_unix };\nenum class chain_exec_dir_t : uint8_t { bbs = 0, temp };\n\nchain_exec_mode_t& operator++(chain_exec_mode_t&);\nchain_exec_mode_t operator++(chain_exec_mode_t&, int);\nchain_exec_dir_t& operator++(chain_exec_dir_t&);\nchain_exec_dir_t operator++(chain_exec_dir_t&, int);\n\n// DATA FOR OTHER PROGRAMS AVAILABLE (5.5 format)\nstruct chain_55_t {\n  std::string filename;\n  std::string description;\n  chain_exec_mode_t exec_mode{chain_exec_mode_t::none};\n  chain_exec_dir_t dir{chain_exec_dir_t::bbs};\n  bool ansi{false};\n  bool local_only{false};\n  bool multi_user{false};\n\n  uint8_t sl{0};\n  // AR restriction\n  uint16_t ar{0};\n  // who registered\n  std::set<int16_t> regby;\n  // number of runs\n  uint16_t usage{0};\n  // minimum age necessary\n  uint8_t minage{0};\n  // maximum age allowed\n  uint8_t maxage{0};\n};\n\n// 5.6 format chain record.\nstruct chain_t {\n  // command to execute\n  std::string filename;\n  // description of the chain\n  std::string description;\n  // ACS expression for accessing chain.\n  std::string acs;\n  chain_exec_mode_t exec_mode{chain_exec_mode_t::none};\n  chain_exec_dir_t dir{chain_exec_dir_t::bbs};\n  bool ansi{false};\n  bool local_only{false};\n  bool multi_user{false};\n  bool local_console_cp437{false};\n  \n\n  // who registered\n  std::set<int16_t> regby;\n  // number of runs\n  uint16_t usage{0};\n  // pause flag\n  bool pause{false};\n};\n\nclass Chains final {\npublic:\n  typedef ssize_t size_type;\n  typedef chain_t& reference;\n  typedef const chain_t& const_reference;\n  static const size_type npos = -1;\n  explicit Chains(const Config& config);\n  explicit Chains(const std::filesystem::path& datadir);\n  // [[ VisibleForTesting ]]\n  explicit Chains(std::initializer_list<chain_t> l) : chains_(l) {}\n  Chains() = default;\n  ~Chains();\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  [[nodiscard]] const std::vector<chain_t>& chains() const { return chains_; }\n  [[nodiscard]] const chain_t& at(size_type num) const { return wwiv::stl::at(chains_, num); }\n  [[nodiscard]] chain_t& at(size_type num) { return wwiv::stl::at(chains_, num); }\n  [[nodiscard]] size_type size() const { return stl::size_int(chains_); }\n\n  bool insert(size_type n, chain_t r);\n  bool erase(size_type n);\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] static uint16_t to_ansir(const chain_t& c);\n    [[nodiscard]] static uint32_t to_exec_flags(const chain_t& c);\n    [[nodiscard]] static uint32_t to_exec_flags(chain_exec_mode_t m);\n\n\n  /**\n   * Is at least one chain registered or sponsored by someone?  If so return\n   * true, false otherwise.\n   */\n  [[nodiscard]] bool HasRegisteredChains() const;\n\n  /** \n   * Increments usage of chain number \"num\" by one.\n   */\n  void increment_chain_usage(int num);\n\nprivate:\n  bool LoadFromJSON();\n  bool LoadFromDat();\n  bool SaveToJSON();\n  bool SaveToDat();\n\n  bool initialized_{false};\n  std::filesystem::path datadir_;\n  std::vector<chain_t> chains_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/chains_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_CHAINS_CEREAL_H\n#define INCLUDED_SDK_CHAINS_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n#include <cereal/specialize.hpp>\n#include \"sdk/chains.h\"\n\nusing namespace wwiv::sdk;\n\n// We want to override how we store some enums as a string, not int.\n// This has to be in the global namespace.\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(chain_exec_mode_t, specialization::non_member_load_save_minimal);\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(chain_exec_dir_t, specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const chain_exec_mode_t& t) {\n  return to_enum_string<chain_exec_mode_t>(\n      t, {\"none\", \"DOS\", \"FOSSIL\", \"STDIO\", \"NETFOSS\", \"SOCK_PORT\", \"SOCK_UNIX\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, chain_exec_mode_t& t, const std::string& s) {\n  t = from_enum_string<chain_exec_mode_t>(\n      s, {\"none\", \"DOS\", \"FOSSIL\", \"STDIO\", \"NETFOSS\", \"SOCK_PORT\", \"SOCK_UNIX\"});\n}\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const chain_exec_dir_t& t) {\n  return to_enum_string<const chain_exec_dir_t>(t, {\"bbs\", \"temp\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, chain_exec_dir_t& t, const std::string& v) {\n  t = from_enum_string<const chain_exec_dir_t>(v, {\"bbs\", \"temp\"});\n}\n\ntemplate <class Archive> void serialize(Archive& ar, chain_55_t& n) {\n  SERIALIZE(n, filename);\n  SERIALIZE(n, description);\n  SERIALIZE(n, exec_mode);\n  SERIALIZE(n, dir);\n  SERIALIZE(n, ansi);\n  SERIALIZE(n, local_only);\n  SERIALIZE(n, multi_user);\n  SERIALIZE(n, sl);\n  SERIALIZE(n, ar);\n  SERIALIZE(n, regby);\n  SERIALIZE(n, usage);\n  SERIALIZE(n, minage);\n  SERIALIZE(n, maxage);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, chain_t& n) {\n  SERIALIZE(n, filename);\n  SERIALIZE(n, description);\n  SERIALIZE(n, exec_mode);\n  SERIALIZE(n, dir);\n  SERIALIZE(n, ansi);\n  SERIALIZE(n, local_only);\n  SERIALIZE(n, multi_user);\n  SERIALIZE(n, acs);\n  SERIALIZE(n, regby);\n  SERIALIZE(n, usage);\n  SERIALIZE(n, local_console_cp437);\n  SERIALIZE(n, pause);\n}\n\n} // namespace cereal\n\n\n#endif\n"
  },
  {
    "path": "sdk/chains_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2019-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"sdk/chains.h\"\n\nusing namespace wwiv::sdk;\n\nTEST(ChainsTest, ExecMode_Operator) {\n  auto t = chain_exec_mode_t::none; \n  ASSERT_EQ(chain_exec_mode_t::none, t++);\n  ASSERT_EQ(chain_exec_mode_t::dos, t++);\n  ASSERT_EQ(chain_exec_mode_t::fossil, t++);\n  ASSERT_EQ(chain_exec_mode_t::stdio, t++);\n  ASSERT_EQ(chain_exec_mode_t::netfoss, t++);\n  ASSERT_EQ(chain_exec_mode_t::sock_port, t++);\n  ASSERT_EQ(chain_exec_mode_t::sock_unix, t++);\n}\n\nTEST(ChainsTest, ExecDir_Operator) {\n  auto t = chain_exec_dir_t::bbs;\n  ASSERT_EQ(chain_exec_dir_t::bbs, t++);\n  ASSERT_EQ(chain_exec_dir_t::temp, t++);\n  ASSERT_EQ(chain_exec_dir_t::bbs, t);\n}\n"
  },
  {
    "path": "sdk/conf/conf.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"bbs/conf.h\"\n\n#include \"sdk/acs/expr.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/arword.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/conf/conf_cereal.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n\n#include <filesystem>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nstatic std::filesystem::path get_conf_430_path(const std::filesystem::path& datadir,\n                                               ConferenceType conftype) {\n  if (conftype == ConferenceType::CONF_DIRS) {\n    return FilePath(datadir, DIRS_CNF);\n  }\n  return FilePath(datadir, SUBS_CNF);\n}\n\n/*\n * Saves conferences of a specified conference-type.\n */\nbool save_confs_430(const Config& config, std::vector<confrec_430_t> confs,\n                    ConferenceType conftype) {\n  const auto path = get_conf_430_path(config.datadir(), conftype);\n  // No longer need to back this up since it is not source of truth anymore.\n\n  TextFile f(path, \"wt\");\n  if (!f.IsOpen()) {\n    LOG(ERROR) << \"Couldn't write to conference file: \" << path.filename().string() << std::endl;\n    return false;\n  }\n\n  f.Write(fmt::sprintf(\"%s\\n\\n\",\n                       \"/* !!!-!!! key not edit this file - use WWIV's conf editor! !!!-!!! */\"));\n  for (const auto& cp : confs) {\n    const auto s =\n        fmt::sprintf(\"~%c %s\\n!%d %d %d %d %d %d %d %u %d %s %s\\n@\", cp.key, cp.conf_name,\n                     cp.status, cp.minsl, cp.maxsl, cp.mindsl, cp.maxdsl, cp.minage, cp.maxage,\n                     cp.minbps, cp.sex, word_to_arstr(cp.ar, \"-\"), word_to_arstr(cp.dar, \"-\"));\n    f.Write(s);\n    for (const auto sub : cp.subs) {\n      f.Write(StrCat(sub, \" \"));\n    }\n    f.Write(fmt::sprintf(\"\\n\\n\"));\n  }\n  f.Close();\n  return true;\n}\n\nConference::Conference(ConferenceType type, const std::set<conference_t>& confs) : type_(type) {\n  for (const auto& c : confs) {\n    confs_.try_emplace(c.key.key(), c);\n  }\n}\n\nconst conference_t& Conference::conf(char key) const {\n  return at(confs_, key);\n}\n\nstd::optional<conference_t> Conference::try_conf(char key) const {\n  if (!contains(confs_, key)) {\n    return std::nullopt;\n  }\n  return {at(confs_, key)};\n}\n\nconference_t& Conference::conf(char key) {\n  return at(confs_, key);\n}\n\nconference_t& Conference::front() {\n  if (confs_.empty()) {\n    DLOG(FATAL) << \"Conference::front() called on empty conference\";\n  }\n  auto it = std::begin(confs_);\n  return it->second;\n}\n\nbool Conference::exists(char key) const {\n  return contains(confs_, key);\n}\n\nstd::set<conference_t> Conference::confs() const {\n  std::set<conference_t> r{};\n  for (const auto& [k, v] : confs_) {\n    r.insert(v);\n  }\n  return r;\n}\n\nstd::string Conference::keys_string() const {\n  std::string out;\n  for (const auto& [k, _] : confs_) {\n    out.push_back(k);\n  }\n  return out;\n}\n\nbool Conference::add(conference_t r) {\n  auto [_, happened] = confs_.try_emplace(r.key.key(), r);\n  return happened;\n}\n\nbool Conference::erase(char key) {\n  return confs_.erase(key) > 0;\n}\n\nConferences::Conferences(const std::filesystem::path& datadir, Subs& subs, files::Dirs& dirs, int max_backups)\n  : datadir_(datadir), subs_(subs), dirs_(dirs), max_backups_(max_backups) {\n  if (auto o = Load()) {\n    LoadFromFile(o.value());\n  } else {\n    std::set<conference_t> empty_set;\n    subs_conf_ = std::make_unique<Conference>(ConferenceType::CONF_SUBS, empty_set);\n    dirs_conf_ = std::make_unique<Conference>(ConferenceType::CONF_DIRS, empty_set);\n  }\n}\n\nstd::optional<conference_file_t> Conferences::Load() const {\n  conference_file_t c{};\n  const auto path = FilePath(datadir_, \"conference.json\");\n  JsonFile f(path, \"conf\", c, 1);\n  if (!f.Load()) {\n    return std::nullopt;\n  }\n  return { c};\n}\n\nbool Conferences::LoadFromFile(const conference_file_t& f) {\n  subs_conf_ = std::make_unique<Conference>(ConferenceType::CONF_SUBS, f.subs);\n  dirs_conf_ = std::make_unique<Conference>(ConferenceType::CONF_DIRS, f.dirs);\n  return true;\n}\n\nbool Conferences::Save() {\n  conference_file_t t{};\n  t.subs = subs_conf().confs();\n  t.dirs = dirs_conf().confs();\n  const auto path = FilePath(datadir_, \"conference.json\");\n  JsonFile f(path, \"conf\", t, 1);\n  return f.Save();\n\n}\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// 4.30 support and upgrading code\n//\nstd::vector<confrec_430_t> read_conferences_430(const std::filesystem::path& path) {\n  if (!File::Exists(path)) {\n    return {};\n  }\n\n  TextFile f(path, \"rt\");\n  if (!f.IsOpen()) {\n    return {};\n  }\n\n  std::vector<confrec_430_t> result;\n  std::string ls;\n  confrec_430_t c{};\n  while (f.ReadLine(&ls) && result.size() < MAX_CONFERENCES) {\n    StringTrim(&ls);\n    if (ls.empty()) {\n      continue;\n    }\n    const auto id = ls.front();\n    ls = ls.substr(1);\n    switch (id) {\n    case '~': {\n      if (ls.size() > 2 && ls[1] == ' ') {\n        c.key = ls.front();\n        auto name = ls.substr(2);\n        StringTrim(&name);\n        c.conf_name = name;\n      }\n    } break;\n    case '!': {\n      // data about the conference\n      auto words = SplitString(ls, DELIMS_WHITE);\n      if (!c.key || words.size() < 10) {\n        LOG(ERROR) << \"Invalid conf line: '\" << ls << \"'\";\n        c.maxsl = 255;\n        c.maxdsl = 255;\n        c.maxage = 255;\n        c.sex = 2;\n        break;\n      }\n      auto it = words.begin();\n      auto status = *it++;\n      c.status = to_number<uint16_t>(status.substr(1));\n      c.minsl = to_number<uint8_t>(*it++);\n      c.maxsl = to_number<uint8_t>(*it++);\n      c.mindsl = to_number<uint8_t>(*it++);\n      c.maxdsl = to_number<uint8_t>(*it++);\n      c.minage = to_number<uint8_t>(*it++);\n      c.maxage = to_number<uint8_t>(*it++);\n      c.minbps = to_number<uint16_t>(*it++);\n      c.sex = to_number<uint8_t>(*it++);\n      c.ar = static_cast<uint16_t>(str_to_arword(*it++));\n      c.dar = static_cast<uint16_t>(str_to_arword(*it++));\n    } break;\n    case '@':\n      // Sub numbers.\n      if (!c.key) {\n        break;\n      }\n      auto words = SplitString(ls, DELIMS_WHITE);\n      for (auto& word : words) {\n        StringTrim(&word);\n        if (word.empty())\n          continue;\n        c.subs.insert(to_number<uint16_t>(word));\n      }\n      c.num = static_cast<subconf_t>(c.subs.size());\n      c.maxnum = c.num;\n      result.push_back(c);\n      c = {};\n      break;\n    }\n  }\n  f.Close();\n  return result;\n}\n\nconference_t to_conference_t(const confrec_430_t& c4) {\n  conference_t c56{};\n  c56.key.key(c4.key);\n  c56.conf_name = c4.conf_name;\n  // N.B. There is no longer any offline, bps, nor ansi status check.\n  acs::AcsExpr ae;\n  ae.min_sl(c4.minsl).max_sl(c4.maxsl).min_dsl(c4.mindsl).max_dsl(c4.maxdsl);\n  ae.min_age(c4.minage).max_age(c4.maxage).ar_int(c4.ar).dar_int(c4.dar);\n  ae.regnum(c4.status & conf_status_wwivreg);\n  c56.acs = ae.get();\n  return c56;\n}\n\nconference_file_t UpgradeConferences(const Config& config, Subs& subs, files::Dirs& dirs) {\n  auto subconf =\n      read_conferences_430(get_conf_430_path(config.datadir(), ConferenceType::CONF_SUBS));\n  auto dirconf =\n      read_conferences_430(get_conf_430_path(config.datadir(), ConferenceType::CONF_DIRS));\n\n  conference_file_t confs56{};\n\n  for (const auto& c4 : subconf) {\n    auto c56 = to_conference_t(c4);\n    // Now to emplace this into the subs.\n    for (const auto subnum : c4.subs) {\n      try {\n        auto& sub = subs.sub(subnum);\n        LOG(INFO) << \"Inserting conf: '\" << c56.key << \"' into sub : \" << sub.name;\n        sub.conf.insert(c56.key.key());\n      } catch (const std::exception& e) {\n        LOG(ERROR) << \"Exception adding sub number: \" << subnum << \" in conf: '\" << c56.key\n                   << \"': \" << e.what();\n      }\n    }\n    confs56.subs.insert(c56);\n  }\n\n  for (const auto& c4 : dirconf) {\n    auto c56 = to_conference_t(c4);\n    // Now to emplace this into the subs.\n    for (const auto subnum : c4.subs) {\n      if (subnum >= dirs.size()) {\n        // Don't try to dereference a bad sub\n        continue;\n      }\n      try {\n        auto& dir = dirs.dir(subnum);\n        LOG(INFO) << \"Inserting conf: '\" << c56.key << \"' into dir : \" << dir.name;\n        dir.conf.insert(c56.key.key());\n      } catch (const std::exception& e) {\n        LOG(ERROR) << \"Exception adding sub number: \" << subnum << \" in conf: '\" << c56.key\n                   << \"': \" << e.what();\n      }\n    }\n    confs56.dirs.insert(c56);\n  }\n  return confs56;\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/conf/conf.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONF_H\n#define INCLUDED_SDK_CONF_H\n\n#include \"sdk/key.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/files/dirs.h\"\n#include <filesystem>\n#include <map>\n#include <memory>\n#include <optional>\n#include <set>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\nclass Config;\n\ntypedef uint16_t subconf_t;\n\nstatic constexpr int CONF_UPDATE_INSERT = 1;\nstatic constexpr int CONF_UPDATE_DELETE = 2;\nstatic constexpr int CONF_UPDATE_SWAP = 3;\n\nenum class ConferenceType { CONF_SUBS, CONF_DIRS };\n\n/** \n * Note: This isn't used on disk \n */\nstruct confrec_430_t {\n  // A to Z?\n  uint8_t key;\n  // Name of conference                                          \n  std::string conf_name;\n  // Minimum SL needed for access\n  uint8_t minsl;\n  // Maximum SL allowed for access\n  uint8_t maxsl;\n  // Minimum DSL needed for access\n  uint8_t mindsl;\n  // Maximum DSL allowed for access\n  uint8_t maxdsl;\n  // Minimum age needed for access\n  uint8_t minage;\n  // Maximum age allowed for access\n  uint8_t maxage;\n  // Gender: 0=male, 1=female 2=all\n  uint8_t sex;\n  // Bit-mapped stuff\n  uint16_t status;\n  // Minimum bps rate for access\n  uint16_t minbps;\n  // ARs necessary for access\n  uint16_t ar;\n  // DARs necessary for access\n  uint16_t dar;\n  // Num \"subs\" in this conference\n  uint16_t num;\n  // max num subs allocated in 'subs'\n  uint16_t maxnum;\n  // \"Sub\" numbers in the conference\n  std::set<subconf_t> subs;\n};\n\n\nstruct conference_t {\n  // A to Z?\n  key_t key;\n  // Name of conference                                          \n  std::string conf_name;\n  // ACS needed for access\n  std::string acs;\n};\ninline bool operator< (const conference_t &c, const conference_t & c2) { return c.key < c2.key; }\ninline bool operator< (const conference_t &c, const char& key) { return c.key < key; }\ninline bool operator< (const char& key, const conference_t &c) { return key < c.key; }\n\n\nstruct conference_file_t {\n  std::set<conference_t> subs;\n  std::set<conference_t> dirs;\n};\n\nclass Conference final {\npublic:\n  Conference(ConferenceType type, const std::set<conference_t>& confs);\n  ~Conference() = default;\n\n  [[nodiscard]] const conference_t& conf(char key) const;\n  [[nodiscard]] std::optional<conference_t> try_conf(char key) const;\n  conference_t& conf(char key);\n  conference_t& front();\n  [[nodiscard]] bool exists(char key) const;\n\n  [[nodiscard]] std::set<conference_t> confs() const;\n  [[nodiscard]] std::string keys_string() const;\n  bool add(conference_t r);\n  bool erase(char key);\n  [[nodiscard]] int size() const { return stl::size_int(confs_); }\n  [[nodiscard]] bool empty() const { return stl::size_int(confs_) == 0; }\n\n  [[nodiscard]] ConferenceType type() const noexcept { return type_; }\n\nprivate:\n  const ConferenceType type_;\n  std::map<char, conference_t> confs_;\n};\n\nclass Conferences final {\npublic:\n  Conferences(const std::filesystem::path& datadir, Subs& subs, files::Dirs& dirs, int max_backups = 0);\n  ~Conferences() = default;\n\n  [[nodiscard]] std::optional<conference_file_t> Load() const;\n  bool LoadFromFile(const conference_file_t&);\n  bool Save();\n\n  [[nodiscard]] Conference& subs_conf() const { return *subs_conf_; }\n  [[nodiscard]] Conference& dirs_conf() const { return *dirs_conf_; }\n\nprivate:\n  const std::filesystem::path datadir_;\n  Subs& subs_;\n  files::Dirs& dirs_;\n  const int max_backups_;\n  std::unique_ptr<Conference> subs_conf_;\n  std::unique_ptr<Conference> dirs_conf_;\n};\n\nconference_file_t UpgradeConferences(const Config& config, Subs& subs, files::Dirs& dirs);\n\nstd::vector<confrec_430_t> read_conferences_430(const std::filesystem::path& path);\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/conf/conf_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONF_CEREAL_H\n#define INCLUDED_SDK_CONF_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n#include \"sdk/key_cereal.h\"\n#include \"sdk/conf/conf.h\"\n\nnamespace wwiv::sdk {\n\ntemplate <class Archive> void serialize(Archive& ar, conference_t& s) { \n  SERIALIZE(s, key);\n  SERIALIZE(s, conf_name);\n  SERIALIZE(s, acs);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, conference_file_t& s) { \n  SERIALIZE(s, subs);\n  SERIALIZE(s, dirs);\n}\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/conf/conf_set.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONF_CONF_SET_H\n#define INCLUDED_SDK_CONF_CONF_SET_H\n\n#include \"core/stl.h\"\n#include <set>\n\nnamespace wwiv::sdk {\n\nclass conf_set_t final {\npublic:\n  conf_set_t() = default;\n  ~conf_set_t() = default;\n\n  void insert(char k) { data_.insert(k); }\n  void erase(char k) { data_.erase(k); }\n  void toggle(char k) {\n    if (data_.find(k) != std::end(data_)) {\n      erase(k);\n    } else {\n      insert(k);\n    }\n  }\n  [[nodiscard]] bool contains(char k) const  { return stl::contains(data_, k); }\n  [[nodiscard]] std::string to_string() const {\n    std::string out;\n    out.reserve(data_.size());\n    for (const auto c : data_) {\n      out.push_back(c);\n    }\n    return out;\n  }\n\n  void from_string(const std::string& s) {\n    data_.clear();\n    for (const auto c : s) {\n      data_.insert(wwiv::strings::to_upper_case_char(c));\n    }\n  }\n\n  /**\n   * Returns if the set of conferences is empty.\n   */\n  [[nodiscard]] bool empty() const noexcept {\n    return data_.empty();\n  }\n\n  std::set<char> data_;\n};\n}\n\n#endif\n"
  },
  {
    "path": "sdk/conf/conf_set_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONF_CEREAL_H\n#define INCLUDED_SDK_CONF_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n#include \"sdk/conf/conf_set.h\"\n#include <cereal/specialize.hpp>\n\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::conf_set_t, specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const wwiv::sdk::conf_set_t& t) {\n  return t.to_string();\n}\n\ntemplate <class Archive>\nvoid load_minimal(Archive const&, wwiv::sdk::conf_set_t& t, const std::string& s) {\n  t.from_string(s);\n}\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/conf/conf_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n#include \"core/fake_clock.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"networkf/networkf.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/sdk_helper.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/conf/conf.h\"\n#include \"gmock/gmock-matchers.h\"\n\nusing namespace testing;\nusing namespace wwiv::core;\nusing namespace wwiv::core::test;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::strings;\n\nclass ConfTest : public testing::Test {\npublic:\n  ConfTest() {}\n\nprotected:\n  wwiv::core::test::FileHelper file_helper_;\n  SdkHelper helper;\n};\n\n\nTEST_F(ConfTest, Smoke) {\n  if (!wwiv::core::test::FileHelper::HasTestData()) {\n    GTEST_SKIP() << \"Skipping all tests that use real files since FileHelper::TestData() is empty.\";\n  }\n\n  auto testdata = FilePath(FileHelper::TestData(), \"conf\");\n  helper.config().datadir(testdata.string());\n  helper.config().raw_config().datadir = testdata.string();\n  helper.config().update_paths();\n  std::vector<net::Network> net_networks;\n  Subs subs(testdata.string(), net_networks);\n  files::Dirs dirs(testdata.string(), 0);\n  ASSERT_TRUE(dirs.LoadLegacy());\n\n  auto result = UpgradeConferences(helper.config(), subs, dirs);\n} "
  },
  {
    "path": "sdk/config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/config.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/config430.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n\n#include <memory>\n#include <string>\n#include <utility>\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/config_cereal.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nConfig::Config(std::filesystem::path root_directory, config_t config)\n    : initialized_(true), root_directory_(std::move(root_directory)),\n      config_(std::move(config)) {\n  update_paths();\n}\n\nConfig::Config(const Config& c) : Config(c.root_directory(), c.config_) {\n  // Chained constructor sets initialized to true, but we want to\n  // match it from the copy.\n  initialized_ = c.IsInitialized();\n}\n\nConfig::~Config() = default;\n\nConfig::Config(std::filesystem::path root_directory) : root_directory_(std::move(root_directory)) {\n  initialized_ = Load();\n  if (!initialized_) {\n    // LOG(ERROR) << config_filename() << \" NOT FOUND.\";\n  }\n}\n\nConfig::Config(Config&& c) : Config(c.root_directory(), c.config_) {\n  // Chained constructor sets initialized to true, but we want to\n  // match it from the copy.\n  initialized_ = c.IsInitialized();\n}\n\n\nConfig& Config::operator=(const Config& o) {\n  initialized_ = true;\n  root_directory_ = o.root_directory_;\n  config_ = o.config_;\n  update_paths();\n  return *this;\n}\n\nConfig& Config::operator=(Config&& o) {\n  // Our move is really just a copy\n  initialized_ = true;\n  root_directory_ = o.root_directory_;\n  config_ = o.config_;\n  update_paths();\n  return *this;\n}\n\nbool Config::Load() {\n  {\n    JsonFile f(FilePath(root_directory_, \"config.json\"), \"config\", config_, 1);\n    if (!f.Load()) {\n      return false;\n    }\n    // We've initialized something. Update absolute paths.\n    update_paths();\n    versioned_config_dat_ = true;\n    readonly_ = false;\n  }\n\n  {\n    JsonFile f(FilePath(datadir_, \"sl.json\"), \"sl\", config_.sl, 1);\n    if (!f.Load()) {\n      return false;\n    }\n  }\n  {\n    JsonFile f(FilePath(datadir_, \"autoval.json\"), \"autoval\", config_.autoval, 1);\n    if (!f.Load()) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nbool Config::Save() {\n  // Update version/date on writes of config.json.\n  config_.header.last_written_date = DateTime::now().to_string();\n  config_.header.written_by_wwiv_version = full_version();\n  config_.header.written_by_wwiv_num_version = wwiv_config_version();\n\n  JsonFile f(FilePath(root_directory_, \"config.json\"), \"config\", config_, 1);\n  if (readonly_) {\n    LOG(ERROR) << \"Tried to save a readonly config.json!\";\n    return false;\n  }\n  if (!f.Save()) {\n    return false;\n  }\n\n  JsonFile sl_file(FilePath(datadir_, \"sl.json\"), \"sl\", config_.sl, 1);\n  sl_file.Save();\n  JsonFile av_file(FilePath(datadir_, \"autoval.json\"), \"autoval\", config_.autoval, 1);\n  av_file.Save();\n  return true;\n}\n\nvoid Config::set_config(const config_t& config, bool need_to_update_paths) {\n  config_ = config;\n\n  // Update absolute paths.\n  if (need_to_update_paths) {\n    update_paths();\n  }\n}\n\nstd::filesystem::path Config::scratch_dir(int node) const {\n  auto scratch_directory = scratch_format();\n  StringReplace(&scratch_directory, \"%n\", std::to_string(node));\n  scratch_directory = File::FixPathSeparators(scratch_directory);\n  return FilePath(root_directory(), scratch_directory);\n}\n\nvoid Config::system_name(const std::string& d) { config_.systemname = d; }\n\nvoid Config::sysop_name(const std::string& d) { config_.sysopname = d; }\n\nvoid Config::system_phone(const std::string& d) { config_.systemphone = d; }\n\nvoid Config::system_password(const std::string& d) { config_.systempw = d; }\n\nstd::filesystem::path Config::config_filename() const {\n  return FilePath(root_directory(), CONFIG_JSON).string();\n}\n\nvoid Config::update_paths() {\n  datadir_ = to_abs_path(config_.datadir);\n  msgsdir_ = to_abs_path(config_.msgsdir);\n  gfilesdir_ = to_abs_path(config_.gfilesdir);\n  menudir_ = to_abs_path(config_.menudir);\n  dloadsdir_ = to_abs_path(config_.dloadsdir);\n  if (config_.scriptdir.empty()) {\n    config_.scriptdir = config_.datadir;\n  }\n  script_dir_ = to_abs_path(config_.scriptdir);\n  if (config_.logdir[0]) {\n    // If the logdir is empty, leave log_dir_ empty.\n    log_dir_ = to_abs_path(config_.logdir);\n  }\n}\n\nconst config_t& Config::to_config_t() const {\n  return config_;\n}\n\nvoid Config::set_paths_for_test(const std::filesystem::path& datadir, const std::filesystem::path& msgsdir,\n                                const std::filesystem::path& gfilesdir, const std::filesystem::path& menudir,\n                                const std::filesystem::path& dloadsdir, const std::filesystem::path& scriptdir) {\n  datadir_ = datadir;\n  config_.datadir = datadir.string();\n  msgsdir_ = msgsdir;\n  config_.msgsdir = msgsdir.string();\n  gfilesdir_ = gfilesdir;\n  config_.gfilesdir = gfilesdir.string();\n  menudir_ = menudir;\n  config_.menudir = menudir.string();\n  dloadsdir_ = dloadsdir;\n  config_.dloadsdir = dloadsdir.string();\n  script_dir_ = scriptdir;\n  config_.scriptdir = scriptdir.string();\n}\n\nstatic void set_script_flag(uint16_t& data, uint16_t flg, bool on) {\n  if (on) {\n    data |= flg;\n  } else {\n    data &= ~flg;\n  }\n}\n\nvoid Config::newuser_password(const std::string& s) { config_.newuserpw = s; }\n\nvoid Config::newuser_restrict(uint16_t d) { config_.newuser_restrict = d; }\n\nvalidation_config_t Config::auto_val(int n) const {\n  if (!stl::contains(config_.autoval, n)) {\n    return {};\n  }\n  return stl::at(config_.autoval, n);\n}\n\nstatic const slrec empty_sl{};\n\nconst slrec& Config::sl(int n) const {\n  if (!stl::contains(config_.sl, n)) {\n    return empty_sl;\n  }\n  return stl::at(config_.sl, n);\n}\n\nvoid Config::sl(int n, slrec& s) { config_.sl[n] = s; }\n\nbool Config::scripting_enabled() const noexcept {\n  return !(config_.script_flags & script_flag_disable_script);\n}\n\nvoid Config::scripting_enabled(bool b) noexcept {\n  set_script_flag(config_.script_flags, script_flag_disable_script, !b);\n}\n\nbool Config::script_package_file_enabled() const noexcept {\n  return config_.script_flags & script_flag_enable_file;\n}\n\nvoid Config::script_package_file_enabled(bool b) noexcept {\n  set_script_flag(config_.script_flags, script_flag_enable_file, b);\n}\n\nbool Config::script_package_os_enabled() const noexcept {\n  return config_.script_flags & script_flag_enable_os;\n}\n\nvoid Config::script_package_os_enabled(bool b) noexcept {\n  set_script_flag(config_.script_flags, script_flag_enable_os, b);\n}\n\nstd::filesystem::path Config::to_abs_path(const std::string& dir) const {\n  return File::absolute(root_directory_, dir).string();\n}\n\nstd::filesystem::path LogDirFromConfig(const std::filesystem::path& bbsdir) {\n  const Config config{bbsdir};\n  if (!config.IsInitialized()) {\n    return {};\n  }\n  return config.logdir();\n}\n\nstd::unique_ptr<Config> load_any_config(const std::filesystem::path& bbsdir) {\n  auto config = std::make_unique<Config>(bbsdir);\n  if (config->IsInitialized()) {\n    return config;\n  }\n  // We didn't load config.json, let's try to load config.dat.\n  const Config430 c430(bbsdir);\n  if (!c430.IsInitialized()) {\n    // We couldn't load either.\n    LOG(ERROR) << \"Unable to load config.json or config.dat\";\n    return {};\n  }\n  // We have a good 430.\n  LOG(INFO) << \"No config.json found, using WWIV 4.x config.dat.\";\n  return std::make_unique<Config>(bbsdir, c430.to_json_config());\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONFIG_H\n#define INCLUDED_SDK_CONFIG_H\n\n#include \"sdk/bbs_directories.h\"\n#include \"sdk/vardec.h\"\n#include <filesystem>\n#include <map>\n#include <string>\n\nnamespace wwiv::sdk {\n\n/** Configuration header at the start of config.dat and also in config.json */\nstruct config_header_t {\n  int written_by_wwiv_num_version;\n  std::string written_by_wwiv_version;\n  std::string last_written_date;\n  int config_revision_number;\n};\n\nenum class newuser_item_type_t { unused, optional, required };\n\nstruct newuser_config_t {\n  newuser_item_type_t use_real_name{newuser_item_type_t::required};\n  newuser_item_type_t use_voice_phone{newuser_item_type_t::required};\n  newuser_item_type_t use_data_phone{newuser_item_type_t::optional};\n  newuser_item_type_t use_address_street{newuser_item_type_t::optional};\n  newuser_item_type_t use_address_city_state{newuser_item_type_t::required};\n  newuser_item_type_t use_address_zipcode{newuser_item_type_t::required};\n  newuser_item_type_t use_address_country{newuser_item_type_t::required};\n  newuser_item_type_t use_callsign{newuser_item_type_t::optional};\n  newuser_item_type_t use_gender{newuser_item_type_t::required};\n  newuser_item_type_t use_birthday{newuser_item_type_t::required};\n  newuser_item_type_t use_computer_type{newuser_item_type_t::required};\n  newuser_item_type_t use_email_address{newuser_item_type_t::required};\n  newuser_item_type_t first_last_name_required{newuser_item_type_t::required};\n};\n\nstruct system_toggles_t {\n  bool lastnet_at_logon{false};\n  bool show_chain_usage{false};\n};\n\n/** Configuration for various color codes to use in the message bases in WWIV. */\nstruct message_color_config_t {\n  std::string text_color{\"|#0\"};\n  std::string quote_color{\"|#5\"};\n  std::string kludge_color{\"|08\"};\n  std::string origin_color{\"|#8\"};\n  std::string tear_color{\"|#8\"};\n};\n\n/** Configuration for various color codes to use in WWIV. */\nstruct color_config_t {\n  message_color_config_t msg;\n};\n\nstruct validation_config_t {\n  // Friendly name of the validation type.\n  std::string name;\n  // SL\n  uint8_t sl{0}; \n  // DSL\n  uint8_t dsl{0};\n\n  // AR\n  uint16_t ar{0};\n  // DAR\n  uint16_t dar{0};\n  // restrictions\n  uint16_t restrict{0};\n};\n\nstruct config_t {\n  config_header_t header;\n\n  // system password\n  std::string systempw;\n  // path for msgs directory\n  std::string msgsdir;\n  // path for gfiles dir\n  std::string gfilesdir;\n  // path for data directory\n  std::string datadir;\n  // path for dloads dir\n  std::string dloadsdir;\n  // script directory.\n  std::string scriptdir;\n  // New in 5.4: Default Log Directory to use.\n  std::string logdir;\n\n  // New in 5.7 (moved from wwiv.ini): User temp directory\n  std::string tempdir_format;\n  // New in 5.7 (moved from wwiv.ini): User batch file transfer directory\n  std::string batchdir_format;\n  // New in 5.7: System scratch directory\n  std::string scratchdir_format;\n  // Number of instances (moved from wwiv.ini in 5.7)\n  int num_instances{4};\n\n  // BBS system name\n  std::string systemname;\n  // BBS system phone number\n  std::string systemphone;\n  // sysop's name\n  std::string sysopname;\n\n  // new user SL\n  uint8_t newusersl{0};\n  // new user DSL\n  uint8_t newuserdsl{0};\n  // Lowest SL given to a validated user.  If you want the BBS to\n  // not require validation, set this to the same value as newusersl.\n  uint8_t validated_sl{0};\n  // max mail waiting\n  uint8_t maxwaiting{0};\n  // file dir new uploads go\n  int newuploads{0};\n  // if system is closed\n  bool closedsystem{false};\n\n  // max users on system\n  uint16_t maxusers{0};\n  // new user restrictions\n  uint16_t newuser_restrict{0};\n  // System configuration\n  uint16_t sysconfig{0};\n  // Chat time on\n  uint16_t sysoplowtime{0};\n  // Chat time off\n  uint16_t sysophightime{0};\n  // Formerly required up/down ratio. This has been moved to wwiv.ini\n  float req_ratio{0.0f};\n  // new user gold\n  float newusergold{0.0f};\n  // security level data\n  std::map<int, slrec> sl;\n  // sysop quick validation data\n  std::map<int, validation_config_t> autoval;\n  // user record length\n  uint16_t userreclen{0};\n  // mail waiting offset\n  uint16_t waitingoffset{0};\n  // inactive offset\n  uint16_t inactoffset{0};\n  // SysOp's WWIV 4.x Registration Number\n  uint32_t wwiv_reg_number{0};\n  // New User Password\n  std::string newuserpw;\n  // New user config\n  newuser_config_t newuser_config;\n  // Post/Call Ratio required to access transfers\n  float post_call_ratio{0.0f};\n  // system status offset\n  uint16_t sysstatusoffset{0};\n  // offset values into user record, used by net3x.\n  uint16_t fuoffset{0};\n  uint16_t fsoffset{0};\n  uint16_t fnoffset{0};\n\n  // max subboards\n  uint16_t max_subs{0};\n  // max directories\n  uint16_t max_dirs{0};\n  // qscan pointer length in bytes\n  uint16_t qscn_len{0};\n  /** Max number of backup files to make of datafiles. 0 = unlimited */\n  uint8_t max_backups{0};\n  /** Flags that control the execution of scripts */\n  uint16_t script_flags{0};\n  // path for menu dir\n  std::string menudir;\n\n  // System toggles (on/off)\n  system_toggles_t toggles;\n\n  // Color configuration\n  color_config_t colors;\n};\n\nclass Config final  : public BbsDirectories {\npublic:\n  Config(std::filesystem::path root_directory, config_t config);\n  explicit Config(const Config& c);\n  explicit Config(std::filesystem::path root_directory);\n  ~Config();\n\n  Config& operator=(const Config&);\n  explicit Config(Config&& config);\n  Config& operator=(Config&&);\n\n  // remove unneeded operators/constructors\n  Config() = delete;\n\n  // members\n\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  void set_initialized_for_test(bool initialized) { initialized_ = initialized; }\n  void set_config(const config_t& config, bool update_paths);\n  [[nodiscard]] const config_t& to_config_t() const;\n  void set_paths_for_test(const std::filesystem::path& datadir, const std::filesystem::path& msgsdir,\n                          const std::filesystem::path& gfilesdir, const std::filesystem::path& menudir,\n                          const std::filesystem::path& dloadsdir, const std::filesystem::path& scriptdir);\n\n  [[nodiscard]] bool versioned_config_dat() const { return versioned_config_dat_; }\n  // ReSharper disable once CppMemberFunctionMayBeStatic\n  [[nodiscard]] bool is_5xx_or_later() const { return true; }\n  [[nodiscard]] int written_by_wwiv_num_version() const {\n    return config_.header.written_by_wwiv_num_version;\n  }\n  [[nodiscard]] int config_revision_number() const { return config_.header.config_revision_number; }\n  void config_revision_number(int v) { config_.header.config_revision_number = v; }\n\n  [[nodiscard]] std::filesystem::path root_directory() const override { return root_directory_; }\n  [[nodiscard]] std::filesystem::path datadir() const override { return datadir_; }\n  void datadir(const std::string& d) { config_.datadir = d; }\n  [[nodiscard]] std::filesystem::path msgsdir() const override { return msgsdir_; }\n  void msgsdir(const std::string& d) { config_.msgsdir = d; }\n  [[nodiscard]] std::filesystem::path gfilesdir() const override { return gfilesdir_; }\n  void gfilesdir(const std::string& d) { config_.gfilesdir = d; }\n  [[nodiscard]] std::filesystem::path menudir() const override { return menudir_; }\n  void menudir(const std::string& d) { config_.menudir = d; }\n  [[nodiscard]] std::filesystem::path dloadsdir() const override { return dloadsdir_; }\n  void dloadsdir(const std::string& d) { config_.dloadsdir = d; }\n  [[nodiscard]] std::filesystem::path scriptdir() const override { return script_dir_; }\n  void scriptdir(const std::string& d) { config_.scriptdir = d; }\n  [[nodiscard]] std::filesystem::path logdir() const override { return log_dir_; }\n  void logdir(const std::string& d) { config_.logdir = d; }\n\n  // moved from wwiv.ini\n  [[nodiscard]] std::string temp_format() const { return config_.tempdir_format; }\n  void temp_format(const std::string& d) { config_.tempdir_format = d; }\n  [[nodiscard]] std::string batch_format() const { return config_.batchdir_format; }\n  void batch_format(const std::string& d) { config_.batchdir_format = d; }\n  [[nodiscard]] std::string scratch_format() const { return config_.scratchdir_format; }\n  void scratch_format(const std::string& d) { config_.scratchdir_format = d; }\n\n  /**\n   * Returns the scrarch directory for a given node.\n   */\n  [[nodiscard]] std::filesystem::path scratch_dir(int node) const override;\n  \n  [[nodiscard]] int num_instances() const { return config_.num_instances; }\n  void num_instances(int n) { config_.num_instances = n; }\n\n  [[nodiscard]] std::string system_name() const { return config_.systemname; }\n  void system_name(const std::string& d);\n  [[nodiscard]] std::string sysop_name() const { return config_.sysopname; }\n  void sysop_name(const std::string& d);\n  [[nodiscard]] std::string system_phone() const { return config_.systemphone; }\n  void system_phone(const std::string& d);\n  [[nodiscard]] std::string system_password() const { return config_.systempw; }\n  void system_password(const std::string& d);\n\n  [[nodiscard]] std::filesystem::path config_filename() const;\n\n  // Sets the value for required upload/download ratio.\n  // This has been moved to the ini file.\n  void set_req_ratio(float req_ratio) { config_.req_ratio = req_ratio; }\n\n  // Upload/Download ratio\n  [[nodiscard]] float req_ratio() const { return config_.req_ratio; }\n  void req_ratio(float f) { config_.req_ratio = f; }\n  // Post to Call Ratio\n  [[nodiscard]] float post_to_call_ratio() const { return config_.post_call_ratio; }\n  void post_to_call_ratio(float f) { config_.post_call_ratio = f; }\n  // Max number of emails waiting allowed\n  [[nodiscard]] int max_waiting() const { return config_.maxwaiting; }\n  void max_waiting(int d) { config_.maxwaiting = static_cast<uint8_t>(d); }\n  // Directory number where uploads go by default.\n  [[nodiscard]] int new_uploads_dir() const { return config_.newuploads; }\n\n  // Sets the value for the sysconfig flags.\n  // These have been moved to the ini file.\n  void set_sysconfig(uint16_t sysconfig) { config_.sysconfig = sysconfig; }\n  [[nodiscard]] uint16_t sysconfig_flags() const { return config_.sysconfig; }\n  // QScan record length.\n  [[nodiscard]] int qscn_len() const { return config_.qscn_len; }\n  void qscn_len(uint16_t n) { config_.qscn_len = n; }\n  // Size in bytes of the userrec structure.\n  [[nodiscard]] int userrec_length() const { return config_.userreclen; }\n\n  [[nodiscard]] uint16_t waitingoffset() const { return config_.waitingoffset; }\n  [[nodiscard]] uint16_t inactoffset() const { return config_.inactoffset; }\n  [[nodiscard]] uint16_t fuoffset() const { return config_.fuoffset; }\n  [[nodiscard]] uint16_t fsoffset() const { return config_.fsoffset; }\n  [[nodiscard]] uint16_t fnoffset() const { return config_.fnoffset; }\n  [[nodiscard]] uint16_t sysstatusoffset() const { return config_.sysstatusoffset; }\n\n  // Max directories.\n  [[nodiscard]] uint16_t max_dirs() const { return config_.max_dirs; }\n  void max_dirs(uint16_t n) { config_.max_dirs = n; }\n  // Max Subs.\n  [[nodiscard]] uint16_t max_subs() const { return config_.max_subs; }\n  void max_subs(uint16_t n) { config_.max_subs = n; }\n  // Max Users.\n  [[nodiscard]] uint16_t max_users() const { return config_.maxusers; }\n  void max_users(int n) { config_.maxusers = static_cast<uint16_t>(n); }\n  // Sysop Low Time.\n  [[nodiscard]] uint16_t sysop_high_time() const { return config_.sysophightime; }\n  void sysop_high_time(int n) { config_.sysophightime = static_cast<uint16_t>(n); }\n  // Sysop Low Time.\n  [[nodiscard]] uint16_t sysop_low_time() const { return config_.sysoplowtime; }\n  void sysop_low_time(int n) { config_.sysoplowtime = static_cast<uint16_t>(n); }\n  // New User SL.\n  [[nodiscard]] uint8_t newuser_sl() const { return config_.newusersl; }\n  void newuser_sl(int n) { config_.newusersl = static_cast<uint8_t>(n); }\n  // New User DSL\n  [[nodiscard]] uint8_t newuser_dsl() const { return config_.newuserdsl; }\n  void newuser_dsl(int n) { config_.newuserdsl = static_cast<uint8_t>(n); }\n  /**\n   * Lowest SL given to a validated user.  If you want the BBS to\n   * not require validation, set this to the same value as newusersl.\n   */\n  [[nodiscard]] uint8_t validated_sl() const { return config_.validated_sl; }\n  void validated_sl(int n) { config_.validated_sl = static_cast<uint8_t>(n); }\n  // New User Gold given when they sign up.\n  [[nodiscard]] float newuser_gold() const { return config_.newusergold; }\n  void newuser_gold(float f) { config_.newusergold = f; }\n  // New User password (password needed to create a new user account)\n  [[nodiscard]] std::string newuser_password() const { return config_.newuserpw; }\n\n  // New user configuration\n  [[nodiscard]] newuser_config_t& newuser_config() { return config_.newuser_config; }\n\n  // System Toggles (mostly toggle settings moved from wwiv.ini)\n  [[nodiscard]] system_toggles_t& toggles() { return config_.toggles; }\n\n  // System Colors.\n  [[nodiscard]] color_config_t& colors() { return config_.colors; }\n\n  void newuser_password(const std::string&);\n  // New User restrictions given by default when they sign up.\n  [[nodiscard]] uint16_t newuser_restrict() const { return config_.newuser_restrict; }\n  void newuser_restrict(uint16_t);\n  // Is this a closed system?\n  [[nodiscard]] bool closed_system() const { return config_.closedsystem; }\n  void closed_system(bool b) { config_.closedsystem = b; }\n  // Auto validation record\n  [[nodiscard]] validation_config_t auto_val(int n) const;\n  void auto_val(int n, const validation_config_t& v) { config_.autoval[n] = v; }\n  // Security Level information\n  [[nodiscard]] const slrec& sl(int n) const;\n  void sl(int n, slrec& s);\n  // Registration Number\n  [[nodiscard]] uint32_t wwiv_reg_number() const { return config_.wwiv_reg_number; }\n  void wwiv_reg_number(int d) { config_.wwiv_reg_number = d; }\n  // max number of backups of datafiles to keep.\n  [[nodiscard]] int max_backups() const noexcept { return config_.max_backups; }\n  void max_backups(int n) { config_.max_backups = static_cast<uint8_t>(n); }\n\n  /** Is WWIVBasic scripting enabled */\n  [[nodiscard]] bool scripting_enabled() const noexcept;\n  void scripting_enabled(bool) noexcept;\n  /** Is WWIVBasic package wwiv.io.file enabled */\n  [[nodiscard]] bool script_package_file_enabled() const noexcept;\n  void script_package_file_enabled(bool) noexcept;\n  /** Is WWIVBasic package wwiv.os enabled */\n  [[nodiscard]] bool script_package_os_enabled() const noexcept;\n  void script_package_os_enabled(bool) noexcept;\n\n  /** Modern header */\n  [[nodiscard]] config_header_t& header() { return config_.header; }\n\n  /** Raw config_t. This should not be used outside of wwivconfig */\n  [[nodiscard]] config_t& raw_config() { return config_; }\n\n  // Is this config read only.\n  [[nodiscard]] bool readonly() const noexcept { return readonly_; }\n  // You probably shouldn't do this unless you are upgrading a dat to JSON.\n  void set_readonly(bool r) { readonly_ = r; }\n\n  void update_paths();\n\nprivate:\n  [[nodiscard]] std::filesystem::path to_abs_path(const std::string& dir) const;\n\n  bool initialized_{false};\n  std::filesystem::path root_directory_;\n  bool versioned_config_dat_{false};\n  // Is this config read only (meaning it was loaded from a dat file).\n  bool readonly_{true};\n\n  std::filesystem::path datadir_;\n  std::filesystem::path msgsdir_;\n  std::filesystem::path gfilesdir_;\n  std::filesystem::path menudir_;\n  std::filesystem::path dloadsdir_;\n  std::filesystem::path script_dir_;\n  std::filesystem::path log_dir_;\n\n  config_t config_{};\n};\n\n/**\n * Helper to load the config and get the logdir from it.\n * Used by the Logger code.\n */\nstd::filesystem::path LogDirFromConfig(const std::filesystem::path& bbsdir);\n\n/**\n * Loads a config from either JSON or DAT.\n */\nstd::unique_ptr<Config> load_any_config(const std::filesystem::path& bbsdir);\n\n} // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/config430.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/config430.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nstatic const int CONFIG_DAT_SIZE_424 = 5660;\n\nConfig430::Config430(const Config430& config) : Config430(config.root_directory_) {}\n\nConfig430::Config430(const configrec& config) { set_config(&config, true); }\n\n// Generate a WWIV 4.30 config from a 5.6+ JSON config.\nConfig430::Config430(const config_t& c5) {\n  memset(&config_, 0, sizeof(configrec));\n  auto& h = config_.header.header;\n  to_char_array(h.signature, \"WWIV\");\n  h.written_by_wwiv_num_version = static_cast<uint16_t>(c5.header.written_by_wwiv_num_version);\n  h.config_revision_number = c5.header.config_revision_number;\n  h.config_size = sizeof(configrec);\n  // update_paths() takes care of the header\n\n  auto& c = config_;\n  to_char_array_trim(c.systempw, c5.systempw);\n  to_char_array_trim(c.msgsdir, c5.msgsdir);\n  to_char_array_trim(c.gfilesdir, c5.gfilesdir);\n  to_char_array_trim(c.datadir, c5.datadir);\n  to_char_array_trim(c.dloadsdir, c5.dloadsdir);\n  to_char_array_trim(c.tempdir, \"\");\n  to_char_array_trim(c.scriptdir, c5.scriptdir);\n  to_char_array_trim(c.logdir, c5.logdir);\n  to_char_array_trim(c.systemname, c5.systemname);\n  to_char_array_trim(c.systemphone, c5.systemphone);\n  to_char_array_trim(c.sysopname, c5.sysopname);\n  to_char_array_trim(c.systemphone, c5.systemphone);\n\n  c.newusersl = c5.newusersl;\n  c.newuserdsl = c5.newuserdsl;\n  c.maxwaiting = c5.maxwaiting;\n  c.primaryport = 1;\n  c.newuploads = static_cast<uint8_t>(c5.newuploads);\n  c.closedsystem = c5.closedsystem ? 1 : 0;\n\n  // max users on system\n  c.maxusers = c5.maxusers;\n  c.newuser_restrict = c5.newuser_restrict;\n  c.sysconfig = c5.sysconfig;\n  c.sysoplowtime = c5.sysoplowtime;\n  c.sysophightime = c5.sysophightime;\n\n  c.req_ratio = c5.req_ratio;\n  c.newusergold = c5.newusergold;\n\n  for (const auto& [pos, sl] : c5.sl) {\n    c.sl[pos] = sl;\n  }\n  for (const auto& [pos, v] : c5.autoval) {\n    valrec v4{};\n    v4.sl = v.sl;\n    v4.dsl = v.dsl;\n    v4.ar = v.ar;\n    v4.dar = v.dar;\n    v4.restrict = v.restrict;\n    c.autoval[pos + 1] = v4;\n  }\n\n  // We're skipping arcs\n  // TODO(rushfan): Is this ok?\n  c.userreclen = c5.userreclen;\n  c.waitingoffset = c5.waitingoffset;\n  c.inactoffset = c5.inactoffset;\n  c.wwiv_reg_number = c5.wwiv_reg_number;\n  to_char_array_trim(c.newuserpw, c5.newuserpw);\n  // Post/Call Ratio required to access transfers\n  c.post_call_ratio = c5.post_call_ratio;\n  c.sysstatusoffset = c5.sysstatusoffset;\n  c.fuoffset = c5.fuoffset;\n  c.fsoffset = c5.fsoffset;\n  c.fnoffset = c5.fnoffset;\n  c.max_subs = c5.max_subs;\n  c.max_dirs = c5.max_dirs;\n  c.qscn_len = c5.qscn_len;\n  c.max_backups = c5.max_backups;\n  c.script_flags = c5.script_flags;\n  to_char_array_trim(c.menudir, c5.menudir);\n  update_paths();\n}\n\nConfig430::Config430(const std::filesystem::path& root_directory)\n    : root_directory_(root_directory) {\n  DataFile<configrec> configFile(FilePath(root_directory, CONFIG_DAT),\n                                 File::modeReadOnly | File::modeBinary);\n  if (!configFile) {\n    return;\n  }\n  initialized_ = configFile.Read(&config_);\n  // Handle 4.24 datafile\n  if (!initialized_) {\n    configFile.Seek(0);\n    auto size_read = configFile.file().Read(&config_, CONFIG_DAT_SIZE_424);\n    initialized_ = size_read == CONFIG_DAT_SIZE_424;\n    written_by_wwiv_num_version_ = 424;\n    config_revision_number_ = 0;\n    VLOG(1) << \"WWIV 4.24 CONFIG.DAT FOUND with size \" << size_read << \".\";\n  } else {\n    // We've initialized something.\n    // Update absolute paths.\n    update_paths();\n  }\n}\n\nConfig430::Config430(const std::filesystem::path& root_directory, const config_t& c5)\n    : Config430(c5) {\n  root_directory_ = root_directory;\n}\n\nConfig430::~Config430() = default;\n\nstd::string Config430::config_filename() const {\n  return FilePath(root_directory(), CONFIG_DAT).string();\n}\n\nvoid Config430::update_paths() {\n  if (!config_.scriptdir[0]) {\n    strcpy(config_.scriptdir, config_.datadir);\n  }\n\n  if (IsEquals(\"WWIV\", config_.header.header.signature)) {\n    // WWIV 5.2 style header.\n    const auto& h = config_.header.header;\n    versioned_config_dat_ = true;\n    config_revision_number_ = h.config_revision_number;\n    written_by_wwiv_num_version_ = h.written_by_wwiv_num_version;\n  }\n}\n\nvoid Config430::set_config(const configrec* config, bool need_to_update_paths) {\n  config_ = *config;\n\n  // Update absolute paths.\n  if (need_to_update_paths) {\n    update_paths();\n  }\n}\n\nconfig_t Config430::to_json_config(std::vector<arcrec> arcs) const {\n  config_t c{};\n\n  auto& h = c.header;\n  h.config_revision_number = config_.header.header.config_revision_number;\n  h.written_by_wwiv_num_version = config_.header.header.written_by_wwiv_num_version;\n  h.last_written_date = DateTime::now().to_string();\n  h.written_by_wwiv_version = full_version();\n\n  c.systempw = config_.systempw;\n  c.msgsdir = config_.msgsdir;\n\n  c.gfilesdir = config_.gfilesdir;\n  c.datadir = config_.datadir;\n  c.dloadsdir = config_.dloadsdir;\n  c.scriptdir = config_.scriptdir;\n  c.logdir = config_.logdir;\n  c.systemname = config_.systemname;\n  c.systemphone = config_.systemphone;\n  c.sysopname = config_.sysopname;\n\n  c.newusersl = config_.newusersl;\n  c.newuserdsl = config_.newuserdsl;\n  c.maxwaiting = config_.maxwaiting;\n  c.newuploads = config_.newuploads;\n  c.closedsystem = config_.closedsystem;\n\n  c.maxusers = config_.maxusers;\n  c.newuser_restrict = config_.newuser_restrict;\n  c.sysconfig = config_.sysconfig;\n  c.sysoplowtime = config_.sysoplowtime;\n  c.sysophightime = config_.sysophightime;\n  c.req_ratio = config_.req_ratio;\n  c.newusergold = config_.newusergold;\n  for (auto i = 0; i <= 255; i++) {\n    c.sl.emplace(i, config_.sl[i]);\n  }\n  for (auto i = 0; i < 10; i++) {\n    const auto& v4 = config_.autoval[i];\n    validation_config_t v5{};\n    v5.name = fmt::format(\"AutoVal: {}\", i);\n    v5.sl = v4.sl;\n    v5.dsl = v4.dsl;\n    v5.ar = v4.ar;\n    v5.dar = v4.dar;\n    v5.restrict = v4.restrict;\n    c.autoval.emplace(i + 1, v5);\n  }\n  c.userreclen = config_.userreclen;\n  c.waitingoffset = config_.waitingoffset;\n  c.inactoffset = config_.inactoffset;\n  c.wwiv_reg_number = config_.wwiv_reg_number;\n  c.newuserpw = config_.newuserpw;\n  c.post_call_ratio = config_.post_call_ratio;\n  c.sysstatusoffset = config_.sysstatusoffset;\n  c.fuoffset = config_.fuoffset;\n  c.fsoffset = config_.fsoffset;\n  c.fnoffset = config_.fnoffset;\n  c.max_subs = config_.max_subs;\n  c.max_dirs = config_.max_dirs;\n  c.qscn_len = config_.qscn_len;\n  c.max_backups = config_.max_backups;\n  c.script_flags = config_.script_flags;\n  c.menudir = config_.menudir;\n\n  // Copy first four new format archiver to arcrec_424_t\n  // This was the 4.24 and lower place for them.  4.31 introduced the new archive record.\n  for (auto j = 0; j < 4 && j < stl::size_int(arcs); j++) {\n    arcrec_424_t a{};\n    auto& oa = stl::at(arcs, j);\n    to_char_array(a.extension, oa.extension);\n    to_char_array(a.arca, oa.arca);\n    to_char_array(a.arce, oa.arce);\n    to_char_array(a.arcl, oa.arcl);\n  }\n  return c;\n}\n\nconfig_t Config430::to_json_config() const {\n  const std::vector<arcrec> empty_arcs;\n  return to_json_config(empty_arcs);\n}\n\nconst configrec* Config430::config() const { return &config_; }\n\nbool Config430::Load() {\n  DataFile<configrec> configFile(FilePath(root_directory_, CONFIG_DAT),\n                                 File::modeReadOnly | File::modeBinary);\n  if (!configFile) {\n    return false;\n  }\n  if (!configFile.Read(&config_)) {\n    return false;\n  }\n  update_paths();\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool Config430::Save() {\n  File file(FilePath(root_directory_, CONFIG_DAT));\n  if (!file.Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile)) {\n    // We may have to create this now since config.json is source of truth\n    return false;\n  }\n  return file.Write(&config_, sizeof(configrec)) == sizeof(configrec);\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/config430.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONFIG430_H\n#define INCLUDED_SDK_CONFIG430_H\n\n#include \"sdk/config.h\"\n#include \"sdk/vardec.h\"\n\n#include <cstdint>\n#include <filesystem>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\nclass Config430 final {\npublic:\n  explicit Config430(const Config430& config);\n  explicit Config430(const configrec& config);\n  explicit Config430(const config_t& c5);\n  explicit Config430(const std::filesystem::path& root_directory);\n  Config430(const std::filesystem::path& root_directory, const config_t& c5);\n  ~Config430();\n\n  // remove unneeded operators/constructors\n\n  Config430() = delete;\n  explicit Config430(Config430&& config) = delete;\n  Config430& operator=(const Config430&) = delete;\n  Config430& operator=(Config430&&) = delete;\n\n  // members\n\n  [[nodiscard]] std::string config_filename() const;\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  void set_initialized_for_test(bool initialized) { initialized_ = initialized; }\n  void set_config(const configrec* config, bool update_paths);\n\n  /** Provides a modern JSON version of the config from here. */\n  [[nodiscard]] config_t to_json_config(std::vector<arcrec>) const;\n  /** Provides a modern JSON version of the config from here without arcs. */\n  [[nodiscard]] config_t to_json_config() const;\n  [[nodiscard]] const configrec* config() const;\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] bool versioned_config_dat() const { return versioned_config_dat_; }\n  [[nodiscard]] bool is_5xx_or_later() const { return written_by_wwiv_num_version_ >= 500; }\n  [[nodiscard]] uint16_t written_by_wwiv_num_version() const { return written_by_wwiv_num_version_; }\n  [[nodiscard]] uint32_t config_revision_number() const { return config_revision_number_; }\n\n  [[nodiscard]] std::string root_directory() const { return root_directory_.string(); }\n\nprivate:\n  void update_paths();\n\n  bool initialized_{false};\n  configrec config_{};\n  std::filesystem::path root_directory_;\n  bool versioned_config_dat_{false};\n  uint32_t config_revision_number_{0};\n  uint16_t written_by_wwiv_num_version_{0};\n}; // namespace sdk\n\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/config_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_CONFIG_CEREAL_H\n#define INCLUDED_SDK_CONFIG_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n#include \"sdk/config.h\"\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/specialize.hpp>\n\n// We want to override how we store network_type_t to store it as a string, not int.\n// This has to be in the global namespace. \nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::newuser_item_type_t, cereal::specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\nusing namespace wwiv::sdk;\n\ntemplate <class Archive> void serialize(Archive& ar, config_header_t& n) {\n  SERIALIZE(n, config_revision_number);\n  SERIALIZE(n, last_written_date);\n  SERIALIZE(n, written_by_wwiv_num_version);\n  SERIALIZE(n, written_by_wwiv_version);\n}\ntemplate <class Archive> void serialize(Archive& ar, slrec& n) {\n  SERIALIZE(n, time_per_day);\n  SERIALIZE(n, time_per_logon);\n  SERIALIZE(n, messages_read);\n  SERIALIZE(n, emails);\n  SERIALIZE(n, posts);\n  SERIALIZE(n, ability); // todo: change to booleans?\n}\n\ntemplate <class Archive> void serialize(Archive& ar, validation_config_t& n) {\n  SERIALIZE(n, name);\n  SERIALIZE(n, sl);\n  SERIALIZE(n, dsl);\n  SERIALIZE(n, ar);\n  SERIALIZE(n, dar);\n  SERIALIZE(n, restrict);\n}\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const &, const newuser_item_type_t& t) {\n  return to_enum_string<newuser_item_type_t>(t, {\"unused\", \"optional\", \"required\"});\n}\ntemplate <class Archive> inline\nvoid load_minimal(Archive const &, newuser_item_type_t& t, const std::string& v) {\n  t = from_enum_string<newuser_item_type_t>(v, {\"unused\", \"optional\", \"required\"});\n}\n\ntemplate <class Archive> void serialize(Archive& ar, newuser_config_t& n) {\n  SERIALIZE(n, use_real_name);\n  SERIALIZE(n, use_voice_phone);\n  SERIALIZE(n, use_data_phone);\n  SERIALIZE(n, use_address_street);\n  SERIALIZE(n, use_address_city_state);\n  SERIALIZE(n, use_address_zipcode);\n  SERIALIZE(n, use_address_country);\n  SERIALIZE(n, use_callsign);\n  SERIALIZE(n, use_gender);\n  SERIALIZE(n, use_birthday);\n  SERIALIZE(n, use_computer_type);\n  SERIALIZE(n, use_email_address);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, system_toggles_t& n) {\n  SERIALIZE(n, lastnet_at_logon);\n  SERIALIZE(n, show_chain_usage);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, message_color_config_t& n) { \n  SERIALIZE(n, text_color);\n  SERIALIZE(n, quote_color);\n  SERIALIZE(n, kludge_color);\n  SERIALIZE(n, origin_color);\n  SERIALIZE(n, tear_color);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, color_config_t& n) {\n  SERIALIZE(n, msg);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, config_t& n) {\n  SERIALIZE(n, header);\n  SERIALIZE(n, systempw);\n  SERIALIZE(n, msgsdir);\n  SERIALIZE(n, gfilesdir);\n  SERIALIZE(n, datadir);\n  SERIALIZE(n, dloadsdir);\n  SERIALIZE(n, scriptdir);\n  SERIALIZE(n, logdir);\n  SERIALIZE(n, num_instances);\n  SERIALIZE(n, tempdir_format);\n  SERIALIZE(n, batchdir_format);\n  SERIALIZE(n, scratchdir_format);\n  SERIALIZE(n, systemname);\n  SERIALIZE(n, systemphone);\n  SERIALIZE(n, sysopname);\n  SERIALIZE(n, menudir);\n\n  SERIALIZE(n, closedsystem);\n\n  SERIALIZE(n, newuserpw);\n  SERIALIZE(n, newusersl);\n  SERIALIZE(n, newuserdsl);\n  SERIALIZE(n, newusergold);\n  SERIALIZE(n, newuser_restrict);\n  SERIALIZE(n, newuser_config);\n\n  SERIALIZE(n, newuploads);\n  SERIALIZE(n, sysconfig);\n  SERIALIZE(n, sysoplowtime);\n  SERIALIZE(n, sysophightime);\n  SERIALIZE(n, wwiv_reg_number);\n  SERIALIZE(n, post_call_ratio);\n  SERIALIZE(n, req_ratio);\n\n  // We don't want to serialize this here, this goes into data/sl.json\n  // SERIALIZE(n, sl);\n  // We don't want to serialize this here, this goes into data/autoval.json\n  // SERIALIZE(n, autoval);\n\n  SERIALIZE(n, userreclen);\n  SERIALIZE(n, waitingoffset);\n  SERIALIZE(n, inactoffset);\n  SERIALIZE(n, sysstatusoffset);\n  SERIALIZE(n, fsoffset);\n  SERIALIZE(n, fuoffset);\n  SERIALIZE(n, fnoffset);\n  SERIALIZE(n, qscn_len);\n\n  SERIALIZE(n, maxwaiting);\n  SERIALIZE(n, maxusers);\n  SERIALIZE(n, max_subs);\n  SERIALIZE(n, max_dirs);\n  SERIALIZE(n, max_backups);\n  SERIALIZE(n, script_flags);\n\n  SERIALIZE(n, toggles);\n  SERIALIZE(n, colors);\n}\n\n\n} // namespace cereal\n\n\n#endif\n"
  },
  {
    "path": "sdk/config_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/config.h\"\n#include \"sdk/sdk_helper.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/vardec.h\"\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass ConfigTest : public testing::Test {\npublic:\n  SdkHelper helper;\n};\n\nTEST_F(ConfigTest, Helper_CreatedBBSRoot) {\n  ASSERT_TRUE(ends_with(helper.root_directory().string(), \"bbs\")) << helper.root_directory();\n}\n\nTEST_F(ConfigTest, Helper_ConfigWorks) { ASSERT_EQ(helper.config().datadir(), helper.datadir()); }\n\nTEST_F(ConfigTest, Config_CurrentDirectory) {\n  ASSERT_EQ(0, chdir(helper.root_directory().string().c_str()));\n\n  const Config config(File::current_directory());\n  ASSERT_TRUE(config.IsInitialized());\n  EXPECT_EQ(helper.data_, config.datadir());\n}\n\nTEST_F(ConfigTest, Config_DifferentDirectory) {\n  const Config config(helper.root_directory());\n  ASSERT_TRUE(config.IsInitialized());\n  EXPECT_EQ(helper.data_, config.datadir());\n}\n\nTEST_F(ConfigTest, Config_WrongDirectory) {\n  const Config config(StrCat(helper.root_directory(), \"x\"));\n  ASSERT_FALSE(config.IsInitialized());\n}\n\nTEST_F(ConfigTest, SetConfig) {\n  Config config(helper.root_directory());\n  ASSERT_TRUE(config.IsInitialized());\n\n  config_t c{};\n  c.systemname = \"mysys\";\n  config.set_config(c, true);\n  ASSERT_EQ(\"mysys\", config.system_name());\n}\n\nTEST_F(ConfigTest, WrittenByNumVersion) {\n  const Config config(helper.root_directory());\n\n  ASSERT_EQ(wwiv_config_version(), config.written_by_wwiv_num_version());\n}\n\nTEST_F(ConfigTest, Is5XXOrLater) {\n  const Config config(helper.root_directory());\n\n  ASSERT_TRUE(config.is_5xx_or_later());\n}\n\nTEST_F(ConfigTest, LogDirFromConfig_Found) {\n  const Config config(helper.root_directory());\n  ASSERT_EQ(config.logdir(), LogDirFromConfig(helper.root_directory()));\n}\n\nTEST_F(ConfigTest, LogDirFromConfig_NotFound) {\n  Config config(helper.root_directory());\n  ASSERT_EQ(\"\", LogDirFromConfig(StrCat(helper.root_directory(), \"x\")));\n}\n"
  },
  {
    "path": "sdk/datetime_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2014-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include <chrono>\n#include <ctime>\n\n#include \"core/datetime.h\"\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\n\nstatic const daten_t t20140704 = 1404460800; // 1404457200;\n\nTEST(DateTime, ToString) {\n  EXPECT_EQ(\"1ms\", to_string(milliseconds(1)));\n  EXPECT_EQ(\"2ms\", to_string(milliseconds(2)));\n\n  EXPECT_EQ(\"1s 498ms\", to_string(milliseconds(1498)));\n    \n  EXPECT_EQ(\"2m 1s 498ms\", to_string(milliseconds(121498)));\n\n  EXPECT_EQ(\"3h 2m 1s 498ms\", to_string(milliseconds(10921498)));\n}\n\n// TODO(rushfan): Fix this now that the VM runs in PDT\n#if 0\nTEST(DateTime, date_to_daten) {\n  ASSERT_EQ(t20140704, date_to_daten(\"07/04/14\"));\n}\n#endif  // 0\n\n"
  },
  {
    "path": "sdk/fido/backbone.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2022, WWIV Software Services                   */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/backbone.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/subscribers.h\"\n#include <set>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::fido {\n\nstd::vector<backbone_t> ParseBackboneFile(const std::filesystem::path& file) {\n  TextFile f(file, \"rt\");\n  if (!f) {\n    return {};\n  }\n  const auto lines = f.ReadFileIntoVector();\n  std::vector<backbone_t> out;\n\n  for (const auto& line : lines) {\n    if (line.empty() || line.front() == ';') {\n      continue;\n    }\n    const auto idx = line.find_first_of(\" \\t\");\n    if (idx == std::string::npos) {\n      continue;\n    }\n    backbone_t b{};\n    b.tag = StringTrim(line.substr(0, idx));\n    b.desc = StringTrim(line.substr(idx + 1));\n    out.emplace_back(b);\n  }\n\n  return out;\n}\n\nimport_result_t ImportSubsFromBackbone(Subs& subs, const Network& net, int16_t net_num, wwiv::core::IniFile& ini,\n                                       const std::vector<backbone_t> backbone_echos) {\n\n  sdk::subboard_t prototype{};\n  prototype.post_acs = ini.value<std::string>(\"post_acs\", \"user.sl >= 20\");\n  prototype.read_acs = ini.value<std::string>(\"read_acs\", \"user.sl >= 10\");\n  prototype.maxmsgs = ini.value<uint16_t>(\"maxmsgs\", 5000);\n  prototype.storage_type = ini.value<uint8_t>(\"storage_type\", 2);\n  if (const auto conf = ini.value<std::string>(\"conf\", \"\"); !conf.empty()) {\n    // Set the conferences if the string is not empty.\n    prototype.conf.from_string(conf);\n  }\n\n  sdk::subboard_network_data_t netdata{};\n  const sdk::fido::FidoAddress uplink(ini.value<std::string>(\"uplink\"));\n  netdata.net_num = net_num;\n\n  netdata.host = FTN_FAKE_OUTBOUND_NODE;\n  netdata.ftn_uplinks.emplace(sdk::fido::FidoAddress(ini.value<std::string>(\"uplink\")));\n  prototype.nets.emplace_back(netdata);\n\n  // Build list of existing echos for this network.\n  std::unordered_set<std::string> existing_echos;\n  for (const auto& sub : subs.subs()) {\n    for (const auto& n : sub.nets) {\n      if (n.net_num == net_num) {\n        existing_echos.insert(n.stype);\n      }\n    }\n  }\n\n  auto subs_dirty = false;\n  for (const auto& b : backbone_echos) {\n    if (!stl::contains(existing_echos, b.tag)) {\n      // Add it.\n      LOG(INFO) << \"Echo tag: \" << b.tag << \" does not already exist.\";\n      subs_dirty = true;\n      auto new_sub{prototype};\n      new_sub.nets.front().stype = b.tag;\n      new_sub.filename = ToStringLowerCase(b.tag);\n      new_sub.name = b.desc;\n      subs.add(new_sub);\n\n      // Create nECHOTAG_NAME.net file.\n      auto subscriberfile = FilePath(net.dir, fmt::format(\"n{}.net\", b.tag));\n      wwiv::sdk::WriteFidoSubcriberFile(subscriberfile, {uplink});\n    }\n  }\n\n  return {true, subs_dirty};\n}\n\n}  // namespace\n\n"
  },
  {
    "path": "sdk/fido/backbone.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2022, WWIV Software Services                    */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_BACKBONE_H\n#define INCLUDED_SDK_FIDO_BACKBONE_H\n\n#include \"core/inifile.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/subxtr.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\n/**\n * Classes to represent a FTN BACKBONE file.\n *\n * The format is:\n *\n * ECHO_TAG      DESCRIPTION\n *\n */\n\nnamespace wwiv::sdk::fido {\n\nstruct backbone_t {\n  std::string tag;\n  std::string desc;\n};\n\nstd::vector<backbone_t> ParseBackboneFile(const std::filesystem::path& file);\n\nstruct import_result_t {\n  bool success{false};\n  bool subs_dirty{false};\n};\n\nimport_result_t ImportSubsFromBackbone(wwiv::sdk::Subs& subs, const wwiv::sdk::net::Network& net,\n                                       int16_t net_num, wwiv::core::IniFile& ini,\n                                       const std::vector<backbone_t> backbone_echos);\n\n} // namespace wwiv::sdk::fido\n\n#endif\n"
  },
  {
    "path": "sdk/fido/backbone_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2022, WWIV Software Services                  */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n\n#include \"core/inifile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/fido/backbone.h\"\n#include <type_traits>\n#include <string>\n\nusing namespace testing;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\n\n\nclass BackboneTest : public testing::Test {\npublic:\n  BackboneTest() {\n    networks.emplace_back(network_type_t::wwivnet, \"WWIVnet\"); // 0\n\n    net.dir = helper_.TempDir().string();\n    net.type = network_type_t::ftn;\n    net.fido.fido_address = \"11:1/211\";\n    networks.push_back(net); // 1\n\n    backbone_file = helper_.CreateTempFile(\"backbone.na\", R\"(\nFOO           This is the foo echo\nBAR           This is the bar echo\n\n)\");\n\n    ini_file = helper_.CreateTempFile(\"import.ini\", R\"(\n[backbone]\npost_acs = user.sl >= 21\nread_acs = user.sl >= 12\nmaxmsgs = 512\nnet_num = 1\nuplink = 11:1/1\n)\");\n\n    subs = std::make_unique<Subs>(helper_.Dir(\"data\"), networks);\n\n    inif = std::make_unique<IniFile>(ini_file, \"backbone\");\n  }\n\nprotected:\n\n  void DumpSubs() {\n    for (const auto& sub : subs->subs()) {\n      LOG(INFO) << \"Sub fn: \" << sub.filename << \"; name: \" << sub.name\n                << \"; net.stype: \" << sub.nets.front().stype;\n    }\n  }\n  wwiv::core::test::FileHelper helper_;\n  Network net{};\n  std::vector<Network> networks;\n  std::unique_ptr<Subs> subs;\n\n  std::filesystem::path ini_file{};\n  std::filesystem::path backbone_file{};\n  std::unique_ptr<IniFile> inif;\n};\n\nTEST_F(BackboneTest, ParseBackboneFile) {\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n  ASSERT_THAT(backbone_entries.size(), Eq(2));\n\n  EXPECT_THAT(backbone_entries.front().tag, Eq(\"FOO\"));\n  EXPECT_THAT(backbone_entries.front().desc, Eq(\"This is the foo echo\"));\n}\n\nTEST_F(BackboneTest, TwoNew) {\n  ASSERT_THAT(subs->size(), Eq(0));\n  ASSERT_TRUE(inif->IsOpen());\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n\n  // Ensure the import operation claims to have completed successfully.\n  auto r = ImportSubsFromBackbone(*subs, net, 1, *inif, backbone_entries);\n  ASSERT_TRUE(r.success);\n  ASSERT_TRUE(r.subs_dirty);\n  EXPECT_THAT(subs->size(), Eq(2));\n  DumpSubs();\n\n  // Ensure that Subs now contains the newly added subs.\n  auto sit = subs->subs().cbegin();\n  auto bit = backbone_entries.cbegin();\n  auto send = std::end(subs->subs());\n  auto bend = std::end(backbone_entries);\n  while (sit != send) { \n    const auto& sub = *sit++;\n    const auto& bbe = *bit++;\n    EXPECT_THAT(sub.filename, StrCaseEq(bbe.tag));\n    EXPECT_THAT(sub.read_acs, StrEq(\"user.sl >= 12\"));\n    EXPECT_THAT(sub.post_acs, StrEq(\"user.sl >= 21\"));\n    EXPECT_THAT(sub.maxmsgs, Eq(512));\n    EXPECT_THAT(sub.name, StrCaseEq(bbe.desc));\n    EXPECT_THAT(sub.nets.front().stype, StrCaseEq(bbe.tag));\n  }\n  EXPECT_EQ(bit, bend);\n  EXPECT_EQ(sit, send);\n\n}\n\n/** By default the INI file for the test class contained no conferences */\nTEST_F(BackboneTest, NoConf) {\n  ASSERT_THAT(subs->size(), Eq(0));\n  ASSERT_TRUE(inif->IsOpen());\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n\n  // Ensure the import operation claims to have completed successfully.\n  auto r = ImportSubsFromBackbone(*subs, net, 1, *inif, backbone_entries);\n  ASSERT_TRUE(r.success);\n  ASSERT_TRUE(r.subs_dirty);\n  EXPECT_THAT(subs->size(), Eq(2));\n\n  // Ensure that Subs now contains the newly added subs.\n  auto sit = subs->subs().front();\n  EXPECT_TRUE(sit.conf.empty());\n}\n\nTEST_F(BackboneTest, WithConf) {\n  ASSERT_THAT(subs->size(), Eq(0));\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n  // Create new inifile with conferences.\n  ini_file = helper_.CreateTempFile(\"import.ini\", R\"(\n[backbone]\npost_acs = user.sl >= 21\nread_acs = user.sl >= 12\nmaxmsgs = 512\nnet_num = 1\nuplink = 11:1/1\nconf = AwF\n)\");\n  // Use new inif that has conferences in it.\n  inif = std::make_unique<IniFile>(ini_file, \"backbone\");\n  ASSERT_TRUE(inif->IsOpen());\n\n  // Ensure the import operation claims to have completed successfully.\n  auto r = ImportSubsFromBackbone(*subs, net, 1, *inif, backbone_entries);\n  ASSERT_TRUE(r.success);\n  ASSERT_TRUE(r.subs_dirty);\n  EXPECT_THAT(subs->size(), Eq(2));\n\n  // Ensure that Subs now contains the newly added subs.\n  auto sit = subs->subs().front();\n  EXPECT_FALSE(sit.conf.empty());\n  // Note the conf list is sorted and has the correct case.\n  EXPECT_THAT(sit.conf.to_string(), Eq(\"AFW\"));\n}\n\nTEST_F(BackboneTest, OneAlreadyExists) {\n  ASSERT_THAT(subs->size(), Eq(0));\n  subboard_t newsub{};\n  newsub.filename = \"BAR\";\n  newsub.name = \"BAR\";\n  newsub.nets.emplace_back(subboard_network_data_t{\"BAR\", 0, 1, 0, 0, {}});\n  subs->insert(0, newsub);\n  ASSERT_TRUE(inif->IsOpen());\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n\n  // Ensure the import operation claims to have completed successfully.\n  auto r = ImportSubsFromBackbone(*subs, net, 1, *inif, backbone_entries);\n  ASSERT_TRUE(r.success);\n  ASSERT_TRUE(r.subs_dirty);\n  EXPECT_THAT(subs->size(), Eq(2));\n  DumpSubs();\n\n  // Ensure that Subs now contains the newly added subs.\n  auto sit = subs->subs().cbegin();\n  auto send = std::end(subs->subs());\n  EXPECT_THAT((*sit++).filename, StrCaseEq(\"BAR\"));\n  EXPECT_THAT((*sit++).filename, StrCaseEq(\"FOO\"));\n  EXPECT_THAT(sit, Eq(send));\n}\n\n\n\nTEST_F(BackboneTest, TwoAlreadyExists) {\n  ASSERT_THAT(subs->size(), Eq(0));\n  {\n    subboard_t newsub{};\n    newsub.filename = \"FOO\";\n    newsub.name = \"FOO\";\n    newsub.nets.emplace_back(subboard_network_data_t{\"FOO\", 0, 1, 0, 0, {}});\n    subs->insert(0, newsub);\n  }\n  {\n    subboard_t newsub{};\n    newsub.filename = \"BAR\";\n    newsub.name = \"BAR\";\n    newsub.nets.emplace_back(subboard_network_data_t{\"BAR\", 0, 1, 0, 0, {}});\n    subs->insert(0, newsub);\n  }\n  ASSERT_TRUE(inif->IsOpen());\n  auto backbone_entries = ParseBackboneFile(backbone_file);\n\n  // Ensure the import operation claims to have completed successfully.\n  auto r = ImportSubsFromBackbone(*subs, net, 1, *inif, backbone_entries);\n  ASSERT_TRUE(r.success);\n  // Nothing added, therefore dirty == false\n  ASSERT_FALSE(r.subs_dirty);\n  EXPECT_THAT(subs->size(), Eq(2));\n  DumpSubs();\n\n  // Ensure that Subs now contains the no newly added subs and has the short\n  // name specified in the test code.\n  auto sit = subs->subs().cbegin();\n  auto send = std::end(subs->subs());\n  EXPECT_THAT((*sit).filename, StrCaseEq(\"BAR\"));\n  EXPECT_THAT((*sit++).name, StrCaseEq(\"BAR\"));\n  EXPECT_THAT((*sit).filename, StrCaseEq(\"FOO\"));\n  EXPECT_THAT((*sit++).name, StrCaseEq(\"FOO\"));\n  EXPECT_THAT(sit, Eq(send));\n}\n"
  },
  {
    "path": "sdk/fido/fido_address.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/fido_address.h\"\n\n#include \"core/cereal_utils.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include <cctype>\n#include <set>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::fido {\n\ntemplate <typename T, typename C, typename I> static T next_int(C& c, I& it, std::set<char> stop) {\n  std::string s;\n  while (it != std::end(c) && !contains(stop, *it)) {\n    if (!std::isdigit(*it)) {\n      throw bad_fidonet_address(StrCat(\"Missing Unexpected nondigit. address: \", c));\n    }\n    s.push_back(*it++);\n  }\n  if (it != std::end(c) && contains(stop, *it)) {\n    // skip over last\n    ++it;\n  }\n  return static_cast<T>(to_number<int>(s));\n}\n\nFidoAddress::FidoAddress(const std::string& address) {\n  const auto has_zone = contains(address, ':');\n  const auto has_net = contains(address, '/');\n  const auto has_point = contains(address, '.');\n  const auto has_domain = contains(address, '@');\n\n  if (!has_net) {\n    throw bad_fidonet_address(\n        StrCat(\"Missing Net or Node. Unable to parse address: '\", address, \"'\"));\n  }\n  auto it = std::begin(address);\n  if (has_zone) {\n    zone_ = next_int<int16_t>(address, it, {':'});\n  } else {\n    // Per FSL-1002: \"If 'ZZ:' is missing then assume 1 as the zone.\"\n    zone_ = 1;\n  }\n  net_ = next_int<int16_t>(address, it, {'/'});\n  node_ = next_int<int16_t>(address, it, {'@', '.'});\n  if (has_point) {\n    point_ = next_int<int16_t>(address, it, {'@'});\n  }\n  if (has_domain) {\n    domain_ = std::string(it, std::end(address));\n  }\n}\n\nstd::string FidoAddress::as_string() const {\n  return as_string(false, true);\n}\n\nstd::string FidoAddress::as_string(bool include_domain) const {\n  return as_string(include_domain, true);\n}\n\nstd::string FidoAddress::as_string(bool include_domain, bool include_point) const {\n  // start off with the minimal things we know.\n  auto s = StrCat(zone_, \":\", net_, \"/\", node_);\n\n  if (include_point && point_ > 0) {\n    s += StrCat(\".\", point_);\n  }\n\n  if (include_domain && !domain_.empty()) {\n    s += StrCat(\"@\", domain_);\n  }\n\n  return s;\n}\n\nbool FidoAddress::operator<(const FidoAddress& r) const {\n  if (zone_ < r.zone_)\n    return true;\n  if (zone_ > r.zone_)\n    return false;\n\n  if (net_ < r.net_)\n    return true;\n  if (net_ > r.net_)\n    return false;\n\n  if (node_ < r.node_)\n    return true;\n  if (node_ > r.node_)\n    return false;\n\n  if (point_ < r.point_)\n    return true;\n  if (point_ > r.point_)\n    return false;\n  if (domain_ < r.domain_)\n    return true;\n\n  return false;\n}\n\nbool FidoAddress::operator==(const FidoAddress& o) const {\n  if (zone_ != o.zone_)\n    return false;\n  if (net_ != o.net_)\n    return false;\n  if (node_ != o.node_)\n    return false;\n  if (point_ != o.point_)\n    return false;\n  if (domain_ != o.domain_)\n    return false;\n  return true;\n}\n\nbool FidoAddress::approx_equals(const FidoAddress& o) const {\n  if (zone_ != o.zone_)\n    return false;\n  if (net_ != o.net_)\n    return false;\n  if (node_ != o.node_)\n    return false;\n  if (point_ != o.point_)\n    return false;\n  if (!domain_.empty() && !o.domain_.empty() && domain_ != o.domain_)\n    return false;\n  return true;\n}\n\nFidoAddress FidoAddress::without_domain() const {\n  return FidoAddress(zone_, net_, node_, point_, \"\");\n}\n\nFidoAddress FidoAddress::with_domain(const std::string& domain) const {\n  return FidoAddress(zone_, net_, node_, point_, domain);\n}\n\nFidoAddress FidoAddress::with_default_domain(const std::string& default_domain) const {\n  const auto d = domain_.empty() ? default_domain : domain_;\n  return FidoAddress(zone_, net_, node_, point_, d);\n}\n\nstd::optional<FidoAddress> try_parse_fidoaddr(const std::string& addr, fidoaddr_parse_t p) {\n  if (addr.empty()) {\n    return std::nullopt;\n  }\n  try {\n    FidoAddress a(addr);\n    return {a};\n  } catch (const bad_fidonet_address&) {\n    if (p == fidoaddr_parse_t::strict) {\n      return std::nullopt;\n    }\n  }\n\n  // Try more lax route.\n  auto s = addr;\n  auto it = std::begin(s);\n  while (it != std::end(s) && !isdigit(*it)) {\n    ++it;\n  }\n  // This removes any non digits from the front\n  std::string a2(it, std::end(s));\n  StringTrim(&a2);\n\n  if (const auto idx = a2.find(' '); idx != std::string::npos) {\n    a2 = a2.substr(0, idx);\n    StringTrim(&a2);\n  }\n  if (a2.empty()) {\n    return std::nullopt;\n  }\n  try {\n    FidoAddress a(a2);\n    return {a};\n  } catch (const bad_fidonet_address&) {\n  }\n  return std::nullopt;\n}\n\nstd::string domain_from_address(const std::string& addr) {\n  if (auto o = try_parse_fidoaddr(addr)) {\n    return o->domain();\n  }\n  return {};\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/fido/fido_address.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_FIDO_ADDRESS_H\n#define INCLUDED_SDK_FIDO_FIDO_ADDRESS_H\n\n#include \"fmt/format.h\"\n#include <cstdint>\n#include <optional>\n#include <stdexcept>\n#include <string>\n#include <utility>\n\n\nnamespace wwiv::sdk::fido {\n\n/**\n Represents a FidoNet Address [FRL-1002] as a class.\n \n \\verbatim\n (from http://ftsc.org/docs/frl-1002.001)\n\n Fidonet addressing uses the following format:\n\n ZZ:NN/FF.PP@DO\n\n where the fields refer to...\n\n ZZ - Zone Number:  The zone the node is part of.\n Min: 1 Max: 32767\n If 'ZZ:' is missing then assume 1 as the zone.\n\n NN - Net Number:   The network the node is a member of.\n Min: 1 Max: 32767\n Must be present.\n\n FF - Node Number:  The actual node number.\n Min: -1 Max: 32767\n Must be present.\n\n PP - Point Number: If the system is a point rather than a node then\n this is their point number off the node.\n Min: 0 Max: 32767\n If '.PP' is missing then assume 0 (ie not a\n point) as the point number.\n\n DO - Domain:       The name of the 'Fidonet Technology Network'.\n Maximum length of 8 characters. The domain\n should not include periods, thus 'fidonet.org'\n is invalid (should be fidonet).\n If '@DO' is missing then fidonet can be assumed.\n\n The following are all valid examples:\n 1:234/5.6@fidonet  (a '5D' address)   => 1:234/5.6@fidonet\n 2:34/6.78          (a '4D' address)   => 2:34/6.78@fidonet\n 4:610/34           (a '3D' address)   => 4:610/34.0@fidonet\n 123/45             (a '2D' address)   => 1:123/45.0@fidonet\n 955:95/2@othernet  (another FTN)      => 955:95/2.0@othernet\n 2:259/-1           (node application) => 2:259/-1.0@fidonet\n\n The limits on each various part of the address are a result of\n fts-0005 (zone, net, node, point), fsc-0045 (domain) and Policy 4\n (-1 node address for node application).\n \\endverbatim\n */\nclass FidoAddress {\npublic:\n  /**\n   * Parses address.  If it fails, throws bad_fidonet_address.\n   */\n  explicit FidoAddress(const ::std::string& address);\n  FidoAddress() noexcept : FidoAddress(-1, -1, -1, -1, \"\") {}\n  FidoAddress(int16_t zone, int16_t net, int16_t node, int16_t point, ::std::string domain)\n    : zone_(zone), net_(net), node_(node), point_(point), domain_(std::move(domain)) {}\n  ~FidoAddress() = default;\n\n  /**\n   * returns the address as a string with a point address and without domain.\n   */\n  [[nodiscard]] std::string as_string() const;\n\n  /**\n   * returns the address as a string with a point address and\n   * domain if include_domain is set.\n   */\n  [[nodiscard]] std::string as_string(bool include_domain) const;\n\n  /**\n   * returns the address as a string with a point address if include_point\n   * is set and domain if include_domain is set.\n   */\n  [[nodiscard]] std::string as_string(bool include_domain, bool include_point) const;\n\n  /**\n   * returns the address as a string with a point address and without domain\n   * N.B. calls as_string() under the covers/\n   */\n  friend std::ostream& operator<< (std::ostream &os, const FidoAddress &f) {\n    os << f.as_string(true, true);\n    return os; \n  }\n  [[nodiscard]] int16_t zone() const { return zone_; }\n  [[nodiscard]] int16_t net() const { return net_; }\n  [[nodiscard]] int16_t node() const { return node_; }\n  [[nodiscard]] int16_t point() const { return point_; }\n  [[nodiscard]] ::std::string domain() const { return domain_; }\n\n  // Needed to put FidoAddress into a set.\n  bool operator< (const FidoAddress& r) const;\n  bool operator== (const FidoAddress& o) const;\n  /** Approximately equals, equals ignoring domain */\n  [[nodiscard]] bool approx_equals(const FidoAddress& o) const;\n\n  /** Creates an address like this one without the domain. */\n  [[nodiscard]] FidoAddress without_domain() const;\n\n  /** Creates an address like this one replacing the domain. */\n  [[nodiscard]] FidoAddress with_domain(const std::string& domain) const;\n\n  /**\n   * Creates an address like this, but if the current address\n   * has no domain, use the specified default domain.\n   */\n  [[nodiscard]] FidoAddress with_default_domain(const std::string& default_domain) const;\n\n  /** Does this address have a domain? */\n  [[nodiscard]] bool has_domain() const { return !domain_.empty(); }\n\nprivate:\n  int16_t zone_ = 0;\n  int16_t net_ = 0;\n  int16_t node_ = 0;\n  int16_t point_ = 0;\n  std::string domain_;\n};\n\nclass bad_fidonet_address final : public std::runtime_error {\npublic:\n  explicit bad_fidonet_address(const std::string& message): runtime_error(message) {}\n};\n\nenum class fidoaddr_parse_t { strict, lax };\n\n/**\n * Try to parse a fidonet address, returning it if successful.\n *\n * if p is lax, try to parse an address and ignore as much other info\n * as possible.\n */\nstd::optional<FidoAddress> try_parse_fidoaddr(const std::string& addr, fidoaddr_parse_t p = fidoaddr_parse_t::strict);\n\n/**\n * Try to parse a fidonet address, returning it if successful.\n */\n\nstd::string domain_from_address(const std::string& addr);\n\n}  // namespace\n\nnamespace std {\ntemplate <>\nstruct hash<wwiv::sdk::fido::FidoAddress> {\n  size_t operator()(const wwiv::sdk::fido::FidoAddress& a) const noexcept {\n    // See http://stackoverflow.com/a/1646913/126995\n    size_t res = 17 * a.zone();\n    res = res * 31 + a.net();\n    res = res * 31 + a.node();\n    res = res * 31 + a.point();\n    if (a.has_domain()) {\n      res = res * 31 + hash<std::string>()(a.domain());\n    }\n    return res;\n  }\n};\n\n}  // namespace std\n\n// Custom formatter for FidoAddress\ntemplate <> struct fmt::formatter<wwiv::sdk::fido::FidoAddress> : fmt::formatter<string_view> {\n  // parse is inherited from formatter<string_view>.\n  template <typename FormatContext>\n  auto format(wwiv::sdk::fido::FidoAddress a, FormatContext& ctx) {\n    return formatter<string_view>::format(a.as_string(true, true), ctx);\n  }\n};\n\n#endif"
  },
  {
    "path": "sdk/fido/fido_address_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/stl.h\"\n#include \"sdk/fido/fido_address.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk::fido;\n\nTEST(FidoAddressTest, Basic) {\n  const FidoAddress f(\"11:10/211.123@wwiv-ftn\");\n  EXPECT_EQ(11, f.zone());\n  EXPECT_EQ(10, f.net());\n  EXPECT_EQ(211, f.node());\n  EXPECT_EQ(123, f.point());\n  EXPECT_EQ(\"wwiv-ftn\", f.domain());\n\n  EXPECT_EQ(\"11:10/211.123@wwiv-ftn\", f.as_string(true));\n}\n\nTEST(FidoAddressTest, Basic_TryParse) {\n  const auto o = try_parse_fidoaddr(\"11:10/211.123@wwiv-ftn\");\n  ASSERT_TRUE(o);\n  const auto& f = o.value();\n  EXPECT_EQ(11, f.zone());\n  EXPECT_EQ(10, f.net());\n  EXPECT_EQ(211, f.node());\n  EXPECT_EQ(123, f.point());\n  EXPECT_EQ(\"wwiv-ftn\", f.domain());\n\n  EXPECT_EQ(\"11:10/211.123@wwiv-ftn\", f.as_string(true));\n}\n\nTEST(FidoAddressTest, ZoneNetNode) {\n  const FidoAddress f(\"11:10/211\");\n  EXPECT_EQ(11, f.zone());\n  EXPECT_EQ(10, f.net());\n  EXPECT_EQ(211, f.node());\n  EXPECT_EQ(0, f.point());\n  EXPECT_FALSE(f.has_domain());\n\n  EXPECT_EQ(\"11:10/211\", f.as_string(true));\n}\n\nTEST(FidoAddressTest, DefaultZone) {\n  const FidoAddress f(\"10/211\");\n  EXPECT_EQ(1, f.zone());  // 1 is the default\n  EXPECT_EQ(10, f.net());\n  EXPECT_EQ(211, f.node());\n  EXPECT_EQ(0, f.point());\n  EXPECT_FALSE(f.has_domain());\n\n  EXPECT_EQ(\"1:10/211\", f.as_string(true));\n}\n\nTEST(FidoAddressTest, WithDomain) {\n  const FidoAddress f(\"1:10/211\");\n  EXPECT_EQ(f.with_domain(\"foo\").as_string(true, true), \"1:10/211@foo\");\n}\n\nTEST(FidoAddressTest, WithDefaultDomain_None) {\n  const FidoAddress f(\"1:10/211\");\n  EXPECT_EQ(f.with_default_domain(\"foo\").as_string(true, true), \"1:10/211@foo\");\n}\n\nTEST(FidoAddressTest, WithDefaultDomain_Existing) {\n  const FidoAddress f(\"1:10/211@bar\");\n  EXPECT_EQ(f.with_default_domain(\"foo\").as_string(true, true), \"1:10/211@bar\");\n}\n\nTEST(FidoAddressTest, WithoutDomain) {\n  const FidoAddress f(\"1:10/211@foo\");\n  EXPECT_EQ(f.without_domain().as_string(true, true), \"1:10/211\");\n}\n\n\nTEST(FidoAddressTest, MissingNetOrNode) {\n  try {\n    FidoAddress f(\"1\");\n    FAIL() << \"Exception expected\";\n  } catch (const wwiv::sdk::fido::bad_fidonet_address&) {\n  }\n}\n\nTEST(FidoAddressTest, MissingNetOrNode_TryParse) {\n  auto o = try_parse_fidoaddr(\"1\");\n  EXPECT_FALSE(o);\n}\n\nTEST(FidoAddressTest, LT) {\n  const FidoAddress f1(\"11:10/211\");\n  const FidoAddress f2(\"11:10/212\");\n\n  EXPECT_LT(f1, f2);\n}\n\nTEST(FidoAddressTest, Set) {\n  const FidoAddress f1(\"11:10/211\");\n  const FidoAddress f2(\"11:10/212\");\n  const FidoAddress f3(\"11:10/213\");\n\n  const std::set<FidoAddress> addrs{f1, f2};\n  EXPECT_TRUE(contains(addrs, f1));\n  EXPECT_TRUE(contains(addrs, f2));\n  EXPECT_FALSE(contains(addrs, f3));\n}\n\nTEST(FidoAddressTest, Streams) {\n  const std::string kAddr = \"11:10/211\";\n  const FidoAddress f1(kAddr);\n\n  std::ostringstream ss;\n  ss << f1;\n  EXPECT_EQ(kAddr, ss.str());\n}\n\n// 1:0/120<1:103/17\nTEST(FidoAddressTest, LTGT) {\n  const FidoAddress f1(\"1:0/120\");\n  const FidoAddress f2(\"1:103/17\");\n\n  EXPECT_LT(f1, f2);\n  EXPECT_FALSE(f2 < f1);\n}\n\nTEST(FidoAddressTest, TryParseFlex_Smoke) {\n  auto o = try_parse_fidoaddr(\"1:103/17\", fidoaddr_parse_t::lax);\n  ASSERT_TRUE(o);\n  ASSERT_EQ(FidoAddress(\"1:103/17\"), o.value());\n}\n\nTEST(FidoAddressTest, TryParseFlex_LeadingName) {\n  const FidoAddress expected(\"1:103/17\");\n  auto o = try_parse_fidoaddr(\"SysopName, 1:103/17\", fidoaddr_parse_t::lax);\n  ASSERT_TRUE(o);\n  ASSERT_EQ(expected, o.value());\n}\n\nTEST(FidoAddressTest, TryParseFlex_LeadingNameStrict) {\n  const FidoAddress expected(\"1:103/17\");\n  const auto o = try_parse_fidoaddr(\"SysopName, 1:103/17\", fidoaddr_parse_t::strict);\n  ASSERT_FALSE(o);\n}\n\nTEST(FidoAddressTest, TryParseFlex_LeadingNameAndTrailingSpace) {\n  const FidoAddress expected(\"1:103/17\");\n  auto o = try_parse_fidoaddr(\"SysopName, 1:103/17    \", fidoaddr_parse_t::lax);\n  ASSERT_TRUE(o);\n  ASSERT_EQ(expected, o.value());\n}\n\nTEST(FidoAddressTest, TryParseFlex_LeadingNameAndTrailingChars) {\n  const FidoAddress expected(\"1:103/17\");\n  auto o = try_parse_fidoaddr(\"SysopName, 1:103/17  Cool\", fidoaddr_parse_t::lax);\n  ASSERT_TRUE(o);\n  ASSERT_EQ(expected, o.value());\n}\n"
  },
  {
    "path": "sdk/fido/fido_callout.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/fido_callout.h\"\n\n#include <cereal/access.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/cereal.hpp>\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include <exception>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::fido::FidoAddress,\n                                   cereal::specialization::non_member_load_save_minimal);\n#include \"sdk/net/networks_cereal.h\"\n\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const wwiv::sdk::fido::FidoAddress& a) {\n  return a.as_string();\n}\n\ntemplate <class Archive>\nvoid load_minimal(Archive const&, wwiv::sdk::fido::FidoAddress& a, const std::string& s) {\n  a = wwiv::sdk::fido::FidoAddress(s);\n}\n\n} // namespace cereal\n\nnamespace wwiv::sdk::fido {\n\nFidoCallout::FidoCallout(const std::filesystem::path& root_directory, int max_backups, const Network& net)\n    : Callout(net, max_backups), root_dir_(root_directory), net_(net) {\n\n  initialized_ = Load();\n  if (!initialized_) {\n    LOG(ERROR) << \"Failed to read \" << FIDO_CALLOUT_JSON << \" or \" << FIDO_CALLOUT_JSON;\n  }\n  initialized_ = true;\n}\n\nFidoCallout::FidoCallout(const Config& config, const Network& net)\n    : FidoCallout(config.root_directory(), config.max_backups(), net) {}\n\n    FidoCallout::~FidoCallout() = default;\n\nconst net_call_out_rec* FidoCallout::net_call_out_for(int node) const {\n  VLOG(2) << \"       FidoCallout::net_call_out_for(\" << node << \")\";\n  return net_call_out_for(fmt::format(\"20000:20000/{}@{}\", node, net_.name));\n}\n\nconst net_call_out_rec* FidoCallout::net_call_out_for(const FidoAddress& node) const {\n  return net_call_out_for(node.as_string());\n}\n\nconst net_call_out_rec* FidoCallout::net_call_out_for(const std::string& node) const {\n  static net_call_out_rec nc{};\n  VLOG(2) << \"       FidoCallout::net_call_out_for(\" << node << \")\";\n\n  try {\n    const auto node_config = fido_node_config_for(FidoAddress(node));\n    nc.session_password = node_config.binkp_config.password;\n    return &nc;\n  } catch (const std::exception&) {\n  }\n  return nullptr;\n}\n\nfido_node_config_t FidoCallout::fido_node_config_for(const FidoAddress& address) const {\n  FidoAddress a = address;\n  if (!contains(node_configs_, a)) {\n    // Try 4D addressing if we don't have 5D.\n    VLOG(2) << \"FidoCallout::fido_node_config_for: Trying address without domain: \" << address;\n    a = FidoAddress(address.zone(), address.net(), address.node(), address.point(), \"\");\n  }\n\n  if (contains(node_configs_, a)) {\n    return at(node_configs_, a);\n  }\n  return {};\n}\n\n\nstatic fido_packet_config_t default_packet_config() {\n  fido_packet_config_t c{};\n  c.compression_type = \"ZIP\";\n  c.packet_type = fido_packet_t::type2_plus;\n  c.max_archive_size = 1024*1024;\n  c.max_packet_size = 1024*1024;\n\n  return c;\n}\n\nstatic const fido_packet_config_t s_default_packet_config = default_packet_config();\n\nfido_packet_config_t FidoCallout::packet_config_for(const FidoAddress& address) const {\n  return packet_config_for(address, s_default_packet_config);\n}\n\nfido_packet_config_t\nFidoCallout::packet_config_for(const FidoAddress& address,\n                               const fido_packet_config_t& default_config) const {\n  if (!contains(node_configs_, address)) {\n    // Try 4D addressing if we don't have 5D.\n    VLOG(2) << \"FidoCallout::packet_config_for: Trying address without domain: \" << address;\n    const auto a = FidoAddress(address.zone(), address.net(), address.node(), address.point(), \"\");\n    if (contains(node_configs_, a)) {\n      return at(node_configs_, a).packet_config;\n    }\n    VLOG(2) << \"FidoCallout::packet_config_for: Didn't have without zone, returning default\";\n    return default_config;\n  }\n  return at(node_configs_, address).packet_config;\n}\n\nfido_packet_config_t FidoCallout::merged_packet_config_for(const FidoAddress& address,\n    const fido_packet_config_t& base_config) const {\n  auto a = address;\n  if (!contains(node_configs_, a)) {\n    // Try 4D addressing if we don't have 5D.\n    VLOG(2) << \"FidoCallout::packet_config_for: Trying address without domain: \" << address;\n    a = FidoAddress(address.zone(), address.net(), address.node(), address.point(), \"\");\n  }\n\n  auto config = base_config;\n  // base config\n  if (contains(node_configs_, a)) {\n    // handle overrides\n    auto n = at(node_configs_, a).packet_config;\n    if (base_config.packet_type == fido_packet_t::unset) {\n      // Our base config is empty, just use the node one.\n      return n;\n    }\n    if (!n.areafix_password.empty())\n      config.areafix_password = n.areafix_password;\n    if (!n.compression_type.empty())\n      config.compression_type = n.compression_type;\n    if (n.max_archive_size > 0)\n      config.max_archive_size = n.max_archive_size;\n    if (n.max_packet_size > 0)\n      config.max_packet_size = n.max_packet_size;\n    if (!n.packet_password.empty())\n      config.packet_password = n.packet_password;\n    if (n.packet_type != fido_packet_t::unset)\n      config.packet_type = n.packet_type;\n    if (n.netmail_status != fido_bundle_status_t::unknown) {\n      config.netmail_status = n.netmail_status;\n    }\n  }\n  return config;\n}\n\nbool FidoCallout::insert(const FidoAddress& a, const fido_node_config_t& c) {\n  // emplace only inserts, doesn't update.\n  node_configs_.erase(a);\n  node_configs_.emplace(a, c);\n  return true;\n}\n\nbool FidoCallout::erase(const FidoAddress& a) {\n  node_configs_.erase(a);\n  return true;\n}\n\nbool FidoCallout::Load() {\n  node_configs_.clear();\n  if (!File::Exists(FilePath(net_.dir, FIDO_CALLOUT_JSON))) {\n    return true;\n  }\n  JsonFile json(FilePath(net_.dir, FIDO_CALLOUT_JSON), \"callout\", node_configs_);\n  return json.Load();\n}\n\nbool FidoCallout::Save() {\n  const auto dir = File::absolute(root_dir_, net_.dir);\n  JsonFile json(FilePath(dir, FIDO_CALLOUT_JSON), \"callout\", node_configs_);\n  return json.Save();\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/fido/fido_callout.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*               Copyright (C)2016-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_FIDO_CALLOUT_H\n#define INCLUDED_SDK_FIDO_FIDO_CALLOUT_H\n\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <map>\n#include <string>\n\nnamespace wwiv::sdk::fido {\n\nclass FidoCallout final : public Callout {\npublic:\n  typedef int size_type;\n  static const size_type npos = -1;\n  \n  FidoCallout(const std::filesystem::path& root_directory, int max_backups,\n              const wwiv::sdk::net::Network& net);\n\n  // [[ VisibleForTesting ]]\n  ~FidoCallout() override;\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n\n  [[nodiscard]] net::fido_node_config_t fido_node_config_for(const FidoAddress& a) const;\n  // Returns the packet config for the node, or a default empty config\n  // if none exist.\n  [[nodiscard]] net::fido_packet_config_t packet_config_for(const FidoAddress& a) const;\n  [[nodiscard]] net::fido_packet_config_t\n  packet_config_for(const FidoAddress& a, const net::fido_packet_config_t& default_config) const;\n  // Creates a merged config, starting with the base_config then adds in values that exist\n  // in the node specific config.\n  [[nodiscard]] net::fido_packet_config_t\n  merged_packet_config_for(const FidoAddress& a, const net::fido_packet_config_t& base_config) const;\n\n  // wwiv::sdk::Callout implementation\n  [[nodiscard]] const net::net_call_out_rec* net_call_out_for(int node) const override;\n  [[nodiscard]] const net::net_call_out_rec* net_call_out_for(const FidoAddress& node) const;\n  [[nodiscard]] const net::net_call_out_rec* net_call_out_for(const std::string& node) const override;\n\n  bool insert(const FidoAddress& a, const net::fido_node_config_t& c);\n  bool erase(const FidoAddress& a);\n  bool Load();\n  bool Save() override;\n  [[nodiscard]] const std::map<FidoAddress, net::fido_node_config_t>& node_configs_map() const{\n    return node_configs_;\n  }\n  [[nodiscard]] std::map<FidoAddress, net::fido_node_config_t>& node_configs_map() {\n    return node_configs_;\n  }\n\nprivate:\n  // TODO(rushfan): Remove this eventually\n  FidoCallout(const wwiv::sdk::Config& config, const net::Network& net);\n  bool initialized_{false};\n  const std::filesystem::path root_dir_;\n  net::Network net_;\n  std::map<FidoAddress, net::fido_node_config_t> node_configs_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/fido/fido_directories.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/fido_directories.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::fido {\n\n  \nFtnDirectories::FtnDirectories(const std::filesystem::path& bbsdir, const Network& net)\n  : FtnDirectories(bbsdir, net, net.dir) {}\n\nstatic void md(const std::vector<std::filesystem::path>& paths) {\n  for (const auto& p : paths) {\n    if (!File::Exists(p)) {\n      File::mkdirs(p);\n    }\n  }\n}\n// Receive dirs is relative to BBS home.\nFtnDirectories::FtnDirectories(std::filesystem::path bbsdir, const Network& net,\n                               std::filesystem::path receive_dir)\n    : bbsdir_(std::move(bbsdir)), net_(net), net_dir_(net.dir),\n      inbound_dir_(File::absolute(net_dir_, net_.fido.inbound_dir)),\n      temp_inbound_dir_(File::absolute(net_dir_, net_.fido.temp_inbound_dir)),\n      temp_outbound_dir_(File::absolute(net_dir_, net_.fido.temp_outbound_dir)),\n      outbound_dir_(File::absolute(net_dir_, net_.fido.outbound_dir)),\n      netmail_dir_(File::absolute(net_dir_, net_.fido.netmail_dir)),\n      bad_packets_dir_(File::absolute(net_dir_, net_.fido.bad_packets_dir)),\n      receive_dir_(std::move(receive_dir)),\n      tic_dir_(File::absolute(net_dir_, net_.fido.tic_dir)),\n      unknown_dir_(File::absolute(net_dir_, net_.fido.unknown_dir)) {\n  VLOG(1) << \"FtnDirectories: receive_dir: \" << receive_dir_;\n  md({inbound_dir_, temp_inbound_dir_, temp_outbound_dir(), outbound_dir_, netmail_dir_, bad_packets_dir_,\n     receive_dir_, tic_dir_, unknown_dir_});\n}\n\nFtnDirectories::~FtnDirectories() = default;\n\nstd::filesystem::path FtnDirectories::net_dir() const { return net_dir_; }\nstd::filesystem::path FtnDirectories::inbound_dir() const { return inbound_dir_; }\nstd::filesystem::path FtnDirectories::temp_inbound_dir() const { return temp_inbound_dir_; }\nstd::filesystem::path FtnDirectories::temp_outbound_dir() const { return temp_outbound_dir_; }\nstd::filesystem::path FtnDirectories::outbound_dir() const { return outbound_dir_; }\nstd::filesystem::path FtnDirectories::netmail_dir() const { return netmail_dir_; }\nstd::filesystem::path FtnDirectories::bad_packets_dir() const { return bad_packets_dir_; }\nstd::filesystem::path FtnDirectories::receive_dir() const { return receive_dir_; }\n\nstd::filesystem::path FtnDirectories::tic_dir() const { return tic_dir_; }\nstd::filesystem::path FtnDirectories::unknown_dir() const { return unknown_dir_; }\n\n}\n"
  },
  {
    "path": "sdk/fido/fido_directories.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_FIDO_DIRECTORIES_H\n#define INCLUDED_SDK_FIDO_FIDO_DIRECTORIES_H\n\n#include \"sdk/fido/fido_callout.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk::fido {\n\nusing namespace wwiv::sdk::net;\n\nclass FtnDirectories {\npublic:\n  FtnDirectories(std::filesystem::path bbsdir, const Network& net,\n                 std::filesystem::path receive_dir);\n  FtnDirectories(const std::filesystem::path& bbsdir, const Network& net);\n  virtual ~FtnDirectories();\n\n  [[nodiscard]] std::filesystem::path net_dir() const;\n  [[nodiscard]] std::filesystem::path inbound_dir() const;\n  [[nodiscard]] std::filesystem::path temp_inbound_dir() const;\n  [[nodiscard]] std::filesystem::path temp_outbound_dir() const;\n  [[nodiscard]] std::filesystem::path outbound_dir() const;\n  [[nodiscard]] std::filesystem::path netmail_dir() const;\n  [[nodiscard]] std::filesystem::path bad_packets_dir() const;\n  [[nodiscard]] std::filesystem::path receive_dir() const;\n  [[nodiscard]] std::filesystem::path tic_dir() const;\n  [[nodiscard]] std::filesystem::path unknown_dir() const;\n\nprivate:\n  const std::filesystem::path bbsdir_;\n  const Network net_;\n  const std::filesystem::path net_dir_;\n  const std::filesystem::path inbound_dir_;\n  const std::filesystem::path temp_inbound_dir_;\n  const std::filesystem::path temp_outbound_dir_;\n  const std::filesystem::path outbound_dir_;\n  const std::filesystem::path netmail_dir_;\n  const std::filesystem::path bad_packets_dir_;\n  const std::filesystem::path receive_dir_;\n  const std::filesystem::path tic_dir_;\n  const std::filesystem::path unknown_dir_;\n};\n\n}\n\n#endif"
  },
  {
    "path": "sdk/fido/fido_packets.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/fido_packets.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/packets.h\"\n#include <algorithm>\n#include <optional>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk::fido {\n\nstatic char ReadCharFromFile(File& f) {\n  char buf[1];\n  if (const auto num_read = f.Read(buf, 1); num_read == 0) {\n    return 0;\n  }\n  return buf[0];\n}\n\nstatic std::string ReadRestOfFile(File& f, int max_size) {\n  auto current = f.current_position();\n  const auto size = f.length();\n  std::string s;\n\n  const auto to_read = std::min<decltype(current)>(max_size, size - current);\n  s.resize(to_read + 1);\n  const auto num_read = f.Read(&s[0], to_read);\n  s.resize(num_read);\n  return s;\n}\n\n/**\n * Reads a field of length {len}.  Will trim the field to  remove\n * any trailing nulls.\n */\nstatic std::string ReadFixedLengthField(File& f, int len) {\n  std::string s;\n  s.resize(len + 1);\n  const auto num_read = f.Read(&s[0], len);\n  s.resize(num_read);\n  while (!s.empty() && s.back() == '\\0') {\n    // Remove trailing null characters.\n    s.pop_back();\n  }\n  return s;\n}\n\n/**\n * Reads a null-terminated field of up to length {len} or the first null\n * character.\n */\nstatic std::string ReadVariableLengthField(File& f, int max_len) {\n  std::string s;\n  for (auto i = 0; i < max_len; i++) {\n    const auto ch = ReadCharFromFile(f);\n    if (ch == 0) {\n      return s;\n    }\n    s.push_back(ch);\n  }\n  return s;\n}\n\nFidoStoredMessage::~FidoStoredMessage()  = default;\n\nbool write_fido_packet_header(File& f, const packet_header_2p_t& header) {\n  if (const auto num_written = f.Write(&header, sizeof(packet_header_2p_t));\n      num_written != sizeof(packet_header_2p_t)) {\n    LOG(ERROR) << \"short write to packet, wrote \" << num_written\n               << \"; expected: \" << sizeof(packet_header_2p_t);\n    return false;\n  }\n  return true;\n}\n\nbool write_packed_message(File& f, const FidoPackedMessage& packet) {\n  if (const auto num_written = f.Write(&packet.nh, sizeof(fido_packed_message_t));\n      num_written != sizeof(fido_packed_message_t)) {\n    LOG(ERROR) << \"short write to packet, wrote \" << num_written\n               << \"; expected: \" << sizeof(fido_packed_message_t);\n    return false;\n  }\n  f.Write(packet.vh.date_time.c_str(), 19);\n  f.Write(\"\\0\", 1);\n  f.Write(packet.vh.to_user_name);\n  f.Write(\"\\0\", 1);\n  f.Write(packet.vh.from_user_name);\n  f.Write(\"\\0\", 1);\n  f.Write(packet.vh.subject);\n  f.Write(\"\\0\", 1);\n  f.Write(packet.vh.text);\n  f.Write(\"\\0\", 1);\n  // End of packet.\n  f.Write(\"\\0\\0\", 2);\n  return true;\n}\n\nbool write_stored_message(File& f, FidoStoredMessage& packet) {\n  if (const auto num = f.Write(&packet.nh, sizeof(fido_stored_message_t));\n      num != sizeof(fido_stored_message_t)) {\n    LOG(ERROR) << \"Short write on write_stored_message. Wrote: \" << num\n               << \"; expected: \" << sizeof(fido_stored_message_t);\n    return false;\n  }\n  return f.Write(packet.text) == ssize(packet.text);\n}\n\n/**\n * Reads a packed message.\n * See http://ftsc.org/docs/fts-0001.016\n */\nReadNetPacketResponse read_packed_message(File& f, FidoPackedMessage& packet) {\n  const auto num_read = f.Read(&packet.nh, sizeof(fido_packed_message_t));\n  if (num_read == 0) {\n    // at the end of the packet.\n    return ReadNetPacketResponse::END_OF_FILE;\n  }\n  if (num_read == 2) {\n    // FIDO packets have 2 bytes of NULL at the end;\n    if (packet.nh.message_type == 0) {\n      return ReadNetPacketResponse::END_OF_FILE;\n    }\n  }\n\n  if (num_read != sizeof(fido_packed_message_t)) {\n    LOG(INFO) << \"error reading header, got short read of size: \" << num_read\n              << \"; expected: \" << sizeof(fido_packed_message_t);\n    return ReadNetPacketResponse::ERROR;\n  }\n\n  if (packet.nh.message_type != 2) {\n    LOG(INFO) << \"invalid message_type: \" << packet.nh.message_type << \"; expected: 2\";\n  }\n  packet.vh.date_time = ReadFixedLengthField(f, 20);\n  packet.vh.to_user_name = ReadVariableLengthField(f, 36);\n  packet.vh.from_user_name = ReadVariableLengthField(f, 36);\n  packet.vh.subject = ReadVariableLengthField(f, 72);\n  packet.vh.text = ReadVariableLengthField(f, 256 * 1024);\n  return ReadNetPacketResponse::OK;\n}\n\nReadNetPacketResponse read_stored_message(File& f, FidoStoredMessage& packet) {\n  if (const auto num_read = f.Read(&packet.nh, sizeof(fido_stored_message_t)); num_read == 0) {\n    // at the end of the packet.\n    return ReadNetPacketResponse::END_OF_FILE;\n  }\n\n  packet.text = ReadRestOfFile(f, 32 * 1024);\n  return ReadNetPacketResponse::OK;\n}\n\n// FidoPacket\n\npacket_header_2p_t CreateType2PlusPacketHeader(const FidoAddress& from_address,\n                                               const FidoAddress& dest, const DateTime& now,\n                                               const std::string& packet_password) {\n\n  packet_header_2p_t header = {};\n  header.orig_zone = from_address.zone();\n  header.orig_net = from_address.net();\n  header.orig_node = from_address.node();\n  header.orig_point = from_address.point();\n  header.dest_zone = dest.zone();\n  header.dest_net = dest.net();\n  header.dest_node = dest.node();\n  header.dest_point = dest.point();\n\n  const auto tm = now.to_tm();\n  header.year = static_cast<uint16_t>(tm.tm_year);\n  header.month = static_cast<uint16_t>(tm.tm_mon);\n  header.day = static_cast<uint16_t>(tm.tm_mday);\n  header.hour = static_cast<uint16_t>(tm.tm_hour);\n  header.minute = static_cast<uint16_t>(tm.tm_min);\n  header.second = static_cast<uint16_t>(tm.tm_sec);\n  header.baud = 33600;\n  header.packet_ver = 2;\n  header.product_code_high = 0x1d;\n  header.product_code_low = 0xff;\n  header.qm_dest_zone = dest.zone();\n  header.qm_orig_zone = from_address.zone();\n  header.capabilities = 0x0001;\n  // Ideally we'd just use bswap_16 if it was available everywhere.\n  header.capabilities_valid =\n      (header.capabilities & 0xff) << 8 | (header.capabilities & 0xff00) >> 8;\n  header.product_rev_major = 0;\n  header.product_rev_minor = static_cast<uint8_t>(wwiv_network_compatible_version() & 0xff);\n  // Add in packet password.  We don't want to ensure we have\n  // a trailing null since we may want all 8 bytes to be usable\n  // by the password.\n  to_char_array_no_null(header.password, packet_password);\n  return header;\n}\n\n\n// static\nstd::optional<FidoPacket> FidoPacket::Open(const std::filesystem::path& path) {\n  File f(path);\n  if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n    VLOG(2) << \"Unable to open file: \" << path.string();\n    return std::nullopt;\n  }\n\n  FidoPacket packet(std::move(f), true);\n  auto num_header_read = packet.file_.Read(&packet.header_, sizeof(packet_header_2p_t));\n  if (num_header_read < static_cast<int>(sizeof(packet_header_2p_t))) {\n    LOG(ERROR) << \"Read less than packet header\";\n    return std::nullopt;\n  }\n\n  return packet;\n}\n\n// static\nstd::optional<FidoPacket> FidoPacket::Create(const std::filesystem::path& outbound_path,\n                                             const packet_header_2p_t& header,\n                                             wwiv::core::Clock& clock) {\n  for (auto tries = 0; tries < 10; tries++) {\n    auto now = clock.Now().now();\n    File file(FilePath(outbound_path, packet_name(now)));\n    if (!file.Open(File::modeCreateFile | File::modeExclusive | File::modeReadWrite |\n                       File::modeBinary,\n                   File::shareDenyReadWrite)) {\n      LOG(INFO) << \"Will try again: Unable to create packet file: \" << file;\n      clock.SleepFor(std::chrono::seconds(1));\n      continue;\n    }\n\n    // Create packet with file and original header\n    FidoPacket packet(std::move(file), true, header);\n\n    // Then update packet header time to match when we actually created the packet on disk.\n    const auto tm = now.to_tm();\n    packet.header_.year = static_cast<uint16_t>(tm.tm_year);\n    packet.header_.month = static_cast<uint16_t>(tm.tm_mon);\n    packet.header_.day = static_cast<uint16_t>(tm.tm_mday);\n    packet.header_.hour = static_cast<uint16_t>(tm.tm_hour);\n    packet.header_.minute = static_cast<uint16_t>(tm.tm_min);\n    packet.header_.second = static_cast<uint16_t>(tm.tm_sec);\n\n    if (!packet.write_fido_packet_header()) {\n      return std::nullopt;\n    }\n    return packet;\n  }\n  return std::nullopt;\n}\n\nbool FidoPacket::write_fido_packet_header() {\n  if (const auto num_written = file_.Write(&header_, sizeof(packet_header_2p_t));\n      num_written != sizeof(packet_header_2p_t)) {\n    LOG(ERROR) << \"short write to packet, wrote \" << num_written\n               << \"; expected: \" << sizeof(packet_header_2p_t);\n    return false;\n  }\n  return true;\n}\n\nbool FidoPacket::Write(const FidoPackedMessage& packet) {\n  return write_packed_message(file_, packet);\n}\n\nstd::tuple<wwiv::sdk::net::ReadNetPacketResponse, FidoPackedMessage> FidoPacket::Read() {\n  FidoPackedMessage msg;\n  auto response = read_packed_message(file_, msg);\n  return std::make_tuple(response, msg);\n}\n\nstd::string FidoPacket::password() const {\n  // Do this dance to ensure that if there's no trailing null on header.password, we add one.\n  char temp[9];\n  memset(temp, 0, sizeof(temp));\n  strncpy(temp, header_.password, 8);\n  temp[8] = '\\0';\n  std::string actual = temp;\n  return ToStringUpperCase(actual);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/fido/fido_packets.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_FIDO_PACKETS_H\n#define INCLUDED_SDK_FIDO_FIDO_PACKETS_H\n\n#include \"core/clock.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/packets.h\"\n#include <cstdint>\n#include <optional>\n#include <string>\n#include <tuple>\n#include <utility>\n\nnamespace wwiv::sdk::fido {\n\n#ifndef __MSDOS__\n#pragma pack(push, 1)\n#endif // __MSDOS__\n\n#ifdef ERROR\n#undef ERROR\n#endif\n\n/**\n * Reference: http://ftsc.org/docs/fsc-0039.004\n *\n  Type-2 Packet Format (proposed, but currently in use)\n  -----------------------------------------------------\n  Field    Ofs Siz Type  Description                Expected value(s)\n  -------  --- --- ----  -------------------------- -----------------\n  OrgNode  0x0   2 Word  Origination node address   0-65535\n  DstNode    2   2 Word  Destination node address   1-65535\n  Year       4   2  Int  Year packet generated      19??-2???\n  Month      6   2  Int  Month  \"        \"          0-11 (0=Jan)\n  Day        8   2  Int  Day    \"        \"          1-31\n  Hour       A   2  Int  Hour   \"        \"          0-23\n  Min        C   2  Int  Minute \"        \"          0-59\n  Sec        E   2  Int  Second \"        \"          0-59\n  Baud      10   2  Int  Baud Rate (not in use)     ????\n  PktVer    12   2  Int  Packet Version             Always 2\n  OrgNet    14   2 Word  Origination net address    1-65535\n  DstNet    16   2 Word  Destination net address    1-65535\n  PrdCodL   18   1 Byte  FTSC Product Code     (lo) 1-255\n* PVMajor   19   1 Byte  FTSC Product Rev   (major) 1-255\n  Password  1A   8 Char  Packet password            A-Z,0-9\n* QOrgZone  22   2  Int  Orig Zone (ZMailQ,QMail)   1-65535\n* QDstZone  24   2  Int  Dest Zone (ZMailQ,QMail)   1-65535\n  Filler    26   2 Byte  Spare Change               ?\n* CapValid  28   2 Word  CW Byte-Swapped Valid Copy BitField\n* PrdCodH   2A   1 Byte  FTSC Product Code     (hi) 1-255\n* PVMinor   2B   1 Byte  FTSC Product Rev   (minor) 1-255\n* CapWord   2C   2 Word  Capability Word            BitField\n* OrigZone  2E   2  Int  Origination Zone           1-65535\n* DestZone  30   2  Int  Destination Zone           1-65535\n* OrigPoint 32   2  Int  Origination Point          1-65535\n* DestPoint 34   2  Int  Destination Point          1-65535\n* ProdData  36   4 Long  Product-specific data      Whatever\n  PktTerm   3A   2 Word  Packet terminator          0000\n*/\nstruct packet_header_2p_t { /* FSC-0039 Type 2.+ */\n  uint16_t orig_node, dest_node, year, month, day, hour, minute, second, baud, packet_ver, orig_net,\n      dest_net;\n\n  uint8_t product_code_low;\n  uint8_t product_rev_major;\n  char password[8];\n\n  uint16_t qm_orig_zone, qm_dest_zone;\n\n  uint8_t filler[2];\n\n  uint16_t capabilities_valid;\n\n  uint8_t product_code_high, product_rev_minor;\n\n  uint16_t capabilities, orig_zone, dest_zone, orig_point, dest_point;\n\n  uint32_t product_data;\n};\n\n/*\nStored Message (*.MSG format)\nFrom http://ftsc.org/docs/fts-0001.016\n-----------------------------------------------------\n\nMessage    =\nfromUserName(36)  (* Null terminated *)\ntoUserName(36)    (* Null terminated *)\nsubject(72)       (* see FileList below *)\nDateTime          (* message body was last edited *)\ntimesRead         (* number of times msg has been read *)\ndestNode          (* of message *)\norigNode          (* of message *)\ncost              (* in lowest unit of originator's\ncurrency *)\norigNet           (* of message *)\ndestNet           (* of message *)\ndestZone          (* of message *)\norigZone          (* of message *)\ndestPoint         (* of message *)\norigPoint         (* of message *)\nreplyTo           (* msg to which this replies *)\nAttributeWord\nnextReply         (* msg which replies to this *)\ntext(unbounded)   (* Null terminated *)\n*/\nstruct fido_stored_message_t {\n  char from[36];\n  char to[36];\n  char subject[72];\n  char date_time[20];\n  int16_t times_read, dest_node, orig_node, cost, orig_net, dest_net, dest_zone, orig_zone,\n      dest_point, orig_point, reply_to, attribute, next_reply;\n};\n\nstatic_assert(sizeof(packet_header_2p_t) == 58, \"packet_header_2p_t != 58 bytes\");\nstatic_assert(sizeof(fido_stored_message_t) == 190, \"fido_stored_message_t != 190 bytes\");\n/*\n,-------------------------------------------------------------------.\n| Name      | Offset | Bytes | Type  | Description                  |\n+-----------+--------+-------+-------+------------------------------+\n| msgType   | 0      | 2     | Int16 | MUST have a value of 2       |\n| origNode  | 2      | 2     | Int16 | Node number packet is from   |\n| destNode  | 4      | 2     | Int16 | Node number packet is to     |\n| origNet   | 6      | 2     | Int16 | Network number packet is from|\n| destNet   | 8      | 2     | Int16 | Network number packet is to  |\n| attribute | 10     | 2     | Int16 | See Notes                    |\n| cost      | 12     | 2     | Int16 | See Notes                    |\n`-----------+--------+-------+-------+------------------------------'\n */\n\nstruct fido_packed_message_t {\n  uint16_t message_type, orig_node, dest_node, orig_net, dest_net, attribute, cost;\n};\n\n#ifndef __MSDOS__\n#pragma pack(pop)\n#endif // __MSDOS__\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Non DOS packed structs and classes.\n//\n//\n\n// Private message\nstatic constexpr uint16_t MSGPRIVATE = 0x0001;\n// High priority\nstatic constexpr uint16_t MSGCRASH = 0x0002;\n// Read by addressee\nstatic constexpr uint16_t MSGREAD = 0x0004;\n// Has been sent\nstatic constexpr uint16_t MSGSENT = 0x0008;\n// File attached to msg\nstatic constexpr uint16_t MSGFILE = 0x0010;\n// In transit\nstatic constexpr uint16_t MSGTRANSIT = 0x0020;\n// Unknown node\nstatic constexpr uint16_t MSGORPHAN = 0x0040;\n// Kill after mailing\nstatic constexpr uint16_t MSGKILL = 0x0080;\n// Message was entered here\nstatic constexpr uint16_t MSGLOCAL = 0x0100;\n// Hold for pickup\nstatic constexpr uint16_t MSGHOLD = 0x0200;\n// Unused\nstatic constexpr uint16_t MSGUNUSED = 0x0400;\n// File req uest\nstatic constexpr uint16_t MSGFREQ = 0x0800;\n// Return receipt request\nstatic constexpr uint16_t MSGRRREQ = 0x1000;\n// Is return receipt\nstatic constexpr uint16_t MSGISRR = 0x2000;\n// Audit request\nstatic constexpr uint16_t MSGAREQ = 0x4000;\n// File update request\nstatic constexpr uint16_t MSGFUPDREQ = 0x8000;\n\nstruct fido_variable_length_header_t {\n  std::string date_time;\n  std::string to_user_name;\n  std::string from_user_name;\n  std::string subject;\n  std::string text;\n};\n\n/**\n * Represents a message in a .PKT file in FidoNET.\n */\nclass FidoPackedMessage {\npublic:\n  FidoPackedMessage(const fido_packed_message_t& h, fido_variable_length_header_t v)\n      : nh(h), vh(std::move(v)) {}\n\n  FidoPackedMessage() = default;\n  virtual ~FidoPackedMessage() = default;\n\n  fido_packed_message_t nh{};\n  fido_variable_length_header_t vh;\n};\n\n/**\n * Represents a .MSG file in FidoNET.\n */\nclass FidoStoredMessage {\npublic:\n  FidoStoredMessage(const fido_stored_message_t& h, std::string t) : nh(h), text(std::move(t)) {}\n  FidoStoredMessage() = default;\n  virtual ~FidoStoredMessage();\n\n  fido_stored_message_t nh{};\n  std::string text;\n};\n\n/**\n * Represents a .PKT file in FidoNET.\n */\nclass FidoPacket {\npublic:\n  FidoPacket(wwiv::core::File&& f, bool writable) : file_(std::move(f)), writable_(writable) {}\n  FidoPacket(wwiv::core::File&& f, bool writable, const packet_header_2p_t& header)\n      : file_(std::move(f)), writable_(writable), header_(header) {}\n\n  static std::optional<FidoPacket> Create(const std::filesystem::path& outbound_path,\n                                          const packet_header_2p_t& header,\n                                          wwiv::core::Clock& clock);\n  static std::optional<FidoPacket> Open(const std::filesystem::path& path);\n\n  FidoPacket(FidoPacket&& o) noexcept\n      : file_(std::move(o.file_)), writable_(o.writable_), header_(o.header_) {}\n\n  bool Write(const FidoPackedMessage& packet);\n  [[nodiscard]] std::tuple<wwiv::sdk::net::ReadNetPacketResponse, FidoPackedMessage> Read();\n  [[nodiscard]] packet_header_2p_t& header() { return header_; }\n\n  // Gets the packet password as a UPPER case string.\n  [[nodiscard]] std::string password() const;\n\n  // Close the packet\n  void Close() { file_.Close(); }\n\nprivate:\n  bool write_fido_packet_header();\n  wwiv::core::File file_;\n  bool writable_{false};\n  packet_header_2p_t header_{};\n};\n  \nbool write_fido_packet_header(wwiv::core::File& f, const packet_header_2p_t& header);\nbool write_packed_message(wwiv::core::File& f, const FidoPackedMessage& packet);\nbool write_stored_message(wwiv::core::File& f, FidoStoredMessage& packet);\n\nwwiv::sdk::net::ReadNetPacketResponse read_packed_message(wwiv::core::File& file,\n                                                       FidoPackedMessage& packet);\nwwiv::sdk::net::ReadNetPacketResponse read_stored_message(wwiv::core::File& file,\n                                                       FidoStoredMessage& packet);\npacket_header_2p_t CreateType2PlusPacketHeader(const FidoAddress& from_address,\n                                               const FidoAddress& dest, const wwiv::core::DateTime& now,\n                                               const std::string& packet_password);\n\n} // namespace wwiv::sdk::fido\n\n#endif  // INCLUDED_SDK_FIDO_FIDO_PACKETS_H\n"
  },
  {
    "path": "sdk/fido/fido_packets_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n#include \"core/file.h\"\n#include \"core/test/file_helper.h\"\n#include \"core/test/wwivtest.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"gtest/gtest.h\"\n\nclass FidoPacketsTestDataTest : public wwiv::core::test::TestDataTest {};\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::test;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\n\nTEST_F(FidoPacketsTestDataTest, OneMessage) {\n  const auto path = FilePath(FileHelper::TestData(), \"fido/0d73f767.pkt\");\n  auto f = File(path);\n  ASSERT_TRUE(f.Exists()) << f;\n\n  auto o = FidoPacket::Open(path);\n  ASSERT_TRUE(o.has_value());\n  auto& packet = o.value();\n  EXPECT_EQ(packet.header().orig_zone, 21);\n  EXPECT_EQ(packet.header().orig_net, 1);\n  EXPECT_EQ(packet.header().orig_node, 2);\n\n  EXPECT_EQ(packet.header().dest_zone, 21);\n  EXPECT_EQ(packet.header().dest_net, 1);\n  EXPECT_EQ(packet.header().dest_node, 1);\n\n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::OK, result);\n    EXPECT_EQ(\"All\", msg.vh.to_user_name);\n    EXPECT_EQ(\"test 4\", msg.vh.subject);\n  }\n  \n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::END_OF_FILE, result);\n  }\n\n}\n\nTEST_F(FidoPacketsTestDataTest, ThreeMessages) {\n  const auto path = FilePath(FileHelper::TestData(), \"fido/0e7c5b69.pkt\");\n  auto f = File(path);\n  ASSERT_TRUE(f.Exists()) << f;\n\n  auto o = FidoPacket::Open(path);\n  ASSERT_TRUE(o.has_value());\n  auto& packet = o.value();\n  EXPECT_EQ(packet.header().orig_zone, 21);\n  EXPECT_EQ(packet.header().orig_net, 1);\n  EXPECT_EQ(packet.header().orig_node, 2);\n\n  EXPECT_EQ(packet.header().dest_zone, 21);\n  EXPECT_EQ(packet.header().dest_net, 1);\n  EXPECT_EQ(packet.header().dest_node, 1);\n\n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::OK, result);\n    EXPECT_EQ(\"All\", msg.vh.to_user_name);\n    EXPECT_EQ(\"test5\", msg.vh.subject);\n  }\n\n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::OK, result);\n    EXPECT_EQ(\"All\", msg.vh.to_user_name);\n    EXPECT_EQ(\"test 6\", msg.vh.subject);\n  }\n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::OK, result);\n    EXPECT_EQ(\"All\", msg.vh.to_user_name);\n    EXPECT_EQ(\"test 7\", msg.vh.subject);\n  }\n  {\n    auto [result, msg] = packet.Read();\n    ASSERT_EQ(ReadNetPacketResponse::END_OF_FILE, result);\n  }\n}"
  },
  {
    "path": "sdk/fido/fido_util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/fido_util.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"sdk/fido/flo_file.h\"\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::fido {\n\nconstexpr char CZ = 26;\n\n// We use DDHHMMSS like SBBSECHO v2 does.\nstd::string packet_name(const DateTime& dt) {\n  const auto buf = dt.to_string(\"%d%H%M%S\");\n  return StrCat(buf, \".pkt\");\n}\n\nstd::string bundle_name(const wwiv::sdk::fido::FidoAddress& source,\n                        const wwiv::sdk::fido::FidoAddress& dest, const std::string& extension) {\n  const int16_t net = source.net() - dest.net();\n  const uint16_t node = source.node() - dest.node();\n\n  return fmt::sprintf(\"%04.4x%04.4x.%s\", net, node, extension);\n}\n\nstd::string net_node_name(const FidoAddress& dest, const std::string& extension) {\n  return fmt::sprintf(\"%04.4x%04.4x.%s\", dest.net(), dest.node(), extension);\n}\n\nstd::string flo_name(const FidoAddress& dest, fido_bundle_status_t status) {\n  std::string extension = \"flo\";\n  if (status != fido_bundle_status_t::unknown) {\n    extension[0] = static_cast<char>(status);\n  }\n  return net_node_name(dest, extension);\n}\n\nstd::string bundle_name(const FidoAddress& source, const FidoAddress& dest, int dow,\n                        int bundle_number) {\n  return bundle_name(source, dest, dow_extension(dow, bundle_number));\n}\n\nstd::vector<std::string> dow_prefixes() {\n  return std::vector<std::string> {\"su\", \"mo\", \"tu\", \"we\", \"th\", \"fr\", \"sa\", \"su\"};\n}\n\nstd::string dow_extension(int dow_num, int bundle_number) {\n  // TODO(rushfan): Should we assert of bundle_number > 25 (0-9=10, + a-z=26 = 0-35)\n\n  const auto dow = dow_prefixes();\n  auto ext = at(dow, dow_num);\n  auto c = static_cast<char>('0' + bundle_number);\n  if (bundle_number > 9) {\n    c = static_cast<char>('a' + bundle_number - 10);\n  }\n  ext.push_back(c);\n  return ext;\n}\n\nbool is_bundle_file(const std::string& name) {\n  const auto dot = name.find_last_of('.');\n  if (dot == std::string::npos) {\n    return false;\n  }\n  auto ext = name.substr(dot + 1);\n  if (ext.length() != 3) {\n    return false;\n  }\n  ext.pop_back();\n  const auto dow = dow_prefixes();\n  return contains(dow, ToStringLowerCase(ext));\n}\n\nbool is_packet_file(const std::string& name) {\n  const auto dot = name.find_last_of('.');\n  if (dot == std::string::npos) {\n    return false;\n  }\n  auto ext = name.substr(dot + 1);\n  if (ext.length() != 3) {\n    return false;\n  }\n  StringLowerCase(&ext);\n  return ext == \"pkt\";\n}\n\nstatic std::string control_file_extension(fido_bundle_status_t status) {\n  std::string s = \"flo\";\n  s[0] = static_cast<char>(status);\n  return s;\n}\n\nstd::string control_file_name(const wwiv::sdk::fido::FidoAddress& dest,\n                              fido_bundle_status_t status) {\n  const auto net = dest.net();\n  const auto node = dest.node();\n\n  const auto ext = control_file_extension(status);\n  return fmt::sprintf(\"%04.4x%04.4x.%s\", net, node, ext);\n}\n\n// 10 Nov 16  21:15:45\nstd::string daten_to_fido(time_t t) {\n  const auto dt = DateTime::from_time_t(t);\n  return dt.to_string(\"%d %b %y  %H:%M:%S\");\n}\n\n// Format: 10 Nov 16  21:15:45\ndaten_t fido_to_daten(std::string d) {\n  try {\n    std::vector<std::string> months = {\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\",\n                             \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"};\n    std::stringstream stream(d);\n    auto now = time_t_now();\n    auto* t = localtime(&now);\n    stream >> t->tm_mday;\n    std::string mon_str;\n    stream >> mon_str;\n    if (!contains(months, mon_str)) {\n      // Unparsable date. return now.\n      return daten_t_now();\n    }\n    t->tm_mon = static_cast<int>(\n        std::distance(months.begin(), std::find(months.begin(), months.end(), mon_str)));\n    int year;\n    stream >> year;\n    year %= 100;\n    // This will work until 2099.\n    t->tm_year = 100 + year;\n\n    std::string hms;\n    stream >> hms;\n    auto parts = SplitString(hms, \":\");\n    t->tm_hour = to_number<int>(at(parts, 0)) - 1;\n    t->tm_min = to_number<int>(at(parts, 1));\n    t->tm_sec = to_number<int>(at(parts, 2));\n\n    auto result = mktime(t);\n    if (result < 0) {\n      // Error.. return now so we don't blow stuff up.\n      result = time_t_now();\n    }\n    return DateTime::from_time_t(result).to_daten_t();  \n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"exception in fido_to_daten('\" << d << \"'): \" << e.what();\n    return daten_t_now();\n  }\n}\n\nstd::string to_net_node(const wwiv::sdk::fido::FidoAddress& a) {\n  return StrCat(a.net(), \"/\", a.node());\n}\n\nstd::string to_zone_net_node(const wwiv::sdk::fido::FidoAddress& a) {\n  return StrCat(a.zone(), \":\", to_net_node(a));\n}\n\nstd::string to_zone_net_node_point(const wwiv::sdk::fido::FidoAddress& a) {\n  return StrCat(to_zone_net_node(a), \".\", a.point());\n}\n\nstd::vector<std::string> split_message(const std::string& s) {\n  std::string temp(s);\n  temp.erase(std::remove(temp.begin(), temp.end(), 10), temp.end());\n  temp.erase(std::remove(temp.begin(), temp.end(), '\\x8d'), temp.end());\n  return SplitString(temp, \"\\r\");\n}\n\n/**\n * \\brief Type of control line. Control-A Kludge or non-control-a like AREA, or none.\n */\nenum class FtnControlLineType { control_a, plain_control_line, none };\n\nstatic FtnControlLineType determine_kludge_line_type(const std::string& line) {\n  if (line.empty()) {\n    return FtnControlLineType::none;\n  }\n  if (line.front() == 0x01) {\n    return line.size() > 1 ? FtnControlLineType::control_a : FtnControlLineType::none;\n  }\n  if (starts_with(line, \"AREA:\") || starts_with(line, \"SEEN-BY: \")) {\n    return FtnControlLineType::plain_control_line;\n  }\n  return FtnControlLineType::none;\n}\n\nstd::string FidoToWWIVText(const std::string& ft, bool convert_control_codes) {\n  // Some editors just use \\n for line endings, we need \\r\\n for\n  // FidoToWWIVText to work.  Replace the sole \\n with \\r\\n\n  const auto lf_only = ft.find('\\r') == std::string::npos;\n\n  // Split text into lines and process one at a time\n  // this is easier to handle control lines, etc.\n  std::string wt;\n  for (const auto& sc : ft) {\n    if (const auto c = static_cast<unsigned char>(sc); c == 0x8d) {\n      // FIDOnet style Soft CR. Convert to CR\n      wt.push_back(13);\n    } else if (c == 10) {\n      // NOP. We're skipping LF's so we can split on CR unless we only\n      // have LF.\n      if (lf_only) {\n        wt.push_back(13);\n      }\n    } else {\n      wt.push_back(c);\n    }\n  }\n\n  auto lines = SplitString(wt, \"\\r\", false);\n  wt.clear();\n\n  if (!convert_control_codes) {\n    for (const auto& line : lines) {\n      wt.append(line).append(\"\\r\\n\");\n    }\n    return wt;\n  }\n\n  for (auto line : lines) {\n    if (line.empty()) {\n      wt.append(\"\\r\\n\");\n      continue;\n    }\n\n    // According to FSC-0068. Kludge lines are not normally displayed\n    // when reading messages.\n    switch (determine_kludge_line_type(line)) {\n    case FtnControlLineType::control_a: {\n      line = line.substr(1);\n      wt.push_back(4);\n      wt.push_back('0');\n    } break;\n    case FtnControlLineType::plain_control_line: {\n      wt.push_back(4);\n      wt.push_back('0');\n    } break;\n    case FtnControlLineType::none:\n    default:\n      break;\n    }\n    wt.append(line).append(\"\\r\\n\");\n  }\n  return wt;\n}\n\nstd::string WWIVToFidoText(const std::string& wt, const wwiv_to_fido_options& opts) {\n  auto temp = wt;\n  // Fido Text is CR, not CRLF, so remove the LFs\n  temp.erase(std::remove(temp.begin(), temp.end(), 10), temp.end());\n  // Also remove the soft CRs since WWIV has no concept.\n  // TODO(rushfan): Is this really needed.\n  temp.erase(std::remove(temp.begin(), temp.end(), '\\x8d'), temp.end());\n  // Remove the trailing control-Z or trailing null characters (if one exists).\n  while (!temp.empty() && (temp.back() == CZ || temp.back() == 0)) {\n    temp.pop_back();\n  }\n\n  // Split this into lines, then we'll handle converting of\n  // WWIV style control codes to FTN style kludges as needed.\n  const auto lines = SplitString(temp, \"\\r\", false);\n  std::ostringstream out;\n  for (auto line : lines) {\n    if (line.empty()) {\n      // Handle the empty line case first. Everything else can assume non-empty now.\n      out << \"\\r\";\n      continue;\n    }\n    if (line.front() == 0x04 && line.size() > 2) {\n      // WWIV style control code.\n      const auto code = at(line, 1);\n      if (code < '0' || code > '9') {\n        // Bogus control-D line, let's skip.\n        VLOG(1) << \"Invalid control-D line: '\" << line << \"'\";\n        continue;\n      }\n      // Strip WWIV control off.\n      line = line.substr(2);\n      const int8_t code_num = code - '0';\n      if (code == '0') {\n        if (starts_with(line, \"MSGID:\") || starts_with(line, \"REPLY:\") ||\n            starts_with(line, \"PID:\")) {\n          // Handle ^A Control Lines\n          out << \"\\001\" << line << \"\\r\";\n        } else if (starts_with(line, \"AREA:\") || starts_with(line, \"SEEN-BY: \")) {\n          // Handle kludge lines that do not start with ^A\n          out << line << \"\\r\";\n        }\n        // Skip all ^D0 lines other than ones we know.\n        continue;\n      }\n      if (code_num > opts.max_optional_val_to_include) {\n        // Skip values higher than we want.\n        continue;\n      }\n    } else if (line.front() == 0x04) {\n      // skip ^D line that's not well formed (i.e. more than 2 characters lone)\n      // TODO(rushfan): Open question should we emit a blank line for a ^DN line that\n      //                is exactly 2 chars long?\n      continue;\n    }\n    if (line.back() == 0x01 /* CA */) {\n      // A line ending in ^A means it soft-wrapped.\n      line.pop_back();\n    }\n    if (line.front() == 0x02 /* CB */) {\n      // Starting with CB is centered. Let's just strip it.\n      line = line.substr(1);\n    }\n\n    // Strip out WWIV color codes.\n    const auto line_size = size_int(line);\n    for (auto i = 0; i < line_size; i++) {\n      const auto c = line[i];\n      if (c == 0x03) {\n        if (++i >= line_size) {\n          // We're at the end.\n          continue;\n        }\n        if (opts.wwiv_heart_color_codes && opts.allow_any_pipe_codes) {\n          const auto color = at(opts.colors,line[i] - '0');\n          out << fmt::format(\"|{:02}\", color);\n        }\n        continue;\n      }\n      if (c == '|' && opts.allow_any_pipe_codes && opts.wwiv_pipe_color_codes && (line_size - i) > 2 && line[i+1] == '#') {\n        const auto color = at(opts.colors, line[i + 2] - '0');\n        out << fmt::format(\"|{:02}\", color);\n        if (i < line_size) {\n          ++i;\n        }\n        if (i < line_size) {\n          ++i;\n        }\n        continue;\n      }\n      if (c == '|' && !opts.allow_any_pipe_codes) {\n        ++i;\n        if (i < line_size) {\n          ++i;\n        }\n        continue;\n      }\n      out << c;\n    }\n    out << \"\\r\";\n  }\n  return out.str();\n}\n\nstd::optional<FidoAddress> get_address_from_single_line(const std::string& line) {\n  const auto start = line.find_last_of('(');\n  const auto end = line.find_last_of(')');\n  if (start == std::string::npos || end == std::string::npos) {\n    return std::nullopt;\n  }\n\n  const auto astr = line.substr(start + 1, end - start - 1);\n  try {\n    return FidoAddress(astr);\n  } catch (std::exception&) {\n    return std::nullopt;\n  }\n}\n\nstd::optional<FidoAddress> get_address_from_origin(const std::string& text) {\n  auto lines = split_message(text);\n  for (const auto& line : lines) {\n    if (starts_with(line, \" * Origin:\")) {\n      return get_address_from_single_line(line);\n    }\n  }\n  return std::nullopt;\n}\n\nFidoAddress get_address_from_packet(const FidoPackedMessage& msg, const packet_header_2p_t& header) {\n  if (auto a = get_address_from_origin(msg.vh.text)) {\n    return a.value();\n  }\n  auto zone = header.orig_zone;\n  if (zone <= 0) {\n    zone = header.qm_orig_zone;\n  }\n  const auto net = msg.nh.orig_net;\n  const auto node = msg.nh.orig_node;\n  const auto point = header.orig_point;\n  return FidoAddress(zone, net, node, point, \"\");\n}\n\nFidoAddress get_address_from_stored_message(const FidoStoredMessage& msg) {\n  if (auto a = get_address_from_origin(msg.text)) {\n    return a.value();\n  }\n  const auto zone = msg.nh.orig_zone;\n  const auto net = msg.nh.orig_net;\n  const auto node = msg.nh.orig_node;\n  const auto point = msg.nh.orig_point;\n  return FidoAddress(zone, net, node, point, \"\");\n}\n\n// Returns a vector of valid routes.\n// A valid route is Zone:*, Zone:Net/*\nstatic std::vector<std::string> parse_routes(const std::string& routes) {\n  std::vector<std::string> result;\n  auto raw = SplitString(routes, \" \");\n  for (const auto& rr : raw) {\n    result.push_back(StringTrim(rr));\n  }\n  return result;\n}\n\nenum class RouteMatch { yes, no, exclude };\n\n// route can be a mask of: {Zone:*, Zone:Net/*, or Zone:Net/node}\n// also a route can be negated with ! in front of it.\nstatic RouteMatch matches_route(const wwiv::sdk::fido::FidoAddress& a, const std::string& route) {\n  auto r = StringTrim(route);\n\n  auto positive = RouteMatch::yes;\n\n  // Negated route.\n  if (starts_with(r, \"!\")) {\n    r = r.substr(1);\n    positive = RouteMatch::exclude;\n  }\n\n  // Just a \"*: for the route.\n  if (r == \"*\") {\n    return positive;\n  }\n\n  // No wild card, so see if it's a complete route.\n  if (!ends_with(r, \"*\")) {\n    try {\n      // Let's see if it's an address.\n      FidoAddress route_address(r);\n      return route_address == a ? positive : RouteMatch::no;\n    } catch (const std::exception&) {\n      // Not a valid address.\n      VLOG(2) << \"Malformed route (not a complete address): \" << route;\n      return RouteMatch::no;\n    }\n  }\n  // Remove the trailing *\n  r.pop_back();\n\n  if (contains(r, ':') && ends_with(r, \"/\")) {\n    // We have a ZONE:NET/*\n    r.pop_back();\n    auto parts = SplitString(r, \":\");\n    if (parts.size() != 2) {\n      VLOG(2) << \"Malformed route: \" << route;\n      return RouteMatch::no;\n    }\n    const auto zone = to_number<uint16_t>(at(parts, 0));\n    const auto net = to_number<uint16_t>(at(parts, 1));\n    if (a.zone() == zone && a.net() == net) {\n      return positive;\n    }\n  } else if (ends_with(r, \":\")) {\n    // We have a ZONE:*\n    r.pop_back();\n    const auto zone = to_number<uint16_t>(r);\n    if (a.zone() == zone) {\n      return positive;\n    }\n  }\n\n  return RouteMatch::no;\n}\n\nbool RoutesThroughAddress(const FidoAddress& a, const std::string& routes) {\n  if (routes.empty()) {\n    return false;\n  }\n  const auto rs = parse_routes(routes);\n  auto ok = false;\n  for (const auto& rr : rs) {\n    auto m = matches_route(a, rr);\n    if (m != RouteMatch::no) {\n      // Ignore any no matches, return otherwise;\n      if (m != RouteMatch::no) {\n        ok = (m == RouteMatch::yes);\n      }\n    }\n  }\n  return ok;\n}\n\nstd::optional<FidoAddress>\nFindRouteToAddress(const FidoAddress& a,\n                   const std::map<FidoAddress, fido_node_config_t>& node_configs_map) {\n\n  for (const auto& nc : node_configs_map) {\n    if (nc.first == a) {\n      return a;\n    }\n    if (RoutesThroughAddress(a, nc.second.routes)) {\n      return nc.first;\n    }\n  }\n  return std::nullopt;\n}\n\nstd::optional<FidoAddress> FindRouteToAddress(const FidoAddress& a, const FidoCallout& callout) {\n  return FindRouteToAddress(a, callout.node_configs_map());\n}\n\nbool exists_bundle(const wwiv::sdk::Config& config, const Network& net) {\n  const FtnDirectories dirs(config.root_directory(), net);\n  return exists_bundle(dirs.inbound_dir());\n}\n\nbool exists_bundle(const std::filesystem::path& dir) {\n  const std::vector<std::string> extensions{\"su?\", \"mo?\", \"tu?\", \"we?\", \"th?\", \"fr?\", \"sa?\", \"pkt\"};\n  for (const auto& e : extensions) {\n    {\n      FindFiles ff(FilePath(dir, StrCat(\"*.\", e)), FindFiles::FindFilesType::files);\n      for (const auto& f : ff) {\n        if (f.size > 0)\n          return true;\n      }\n    }\n    {\n      FindFiles ff(FilePath(dir, StrCat(\"*.\", ToStringUpperCase(e))), FindFiles::FindFilesType::files);\n      for (const auto& f : ff) {\n        if (f.size > 0)\n          return true;\n      }\n    }\n  }\n  return false;\n}\n\n/**\n * Display ISO 8601 offset from UTC in timezone\n * (1 minute=1, 1 hour=100)\n * If timezone cannot be determined, no characters.\n */\nstd::string tz_offset_from_utc(const core::DateTime& dt) {\n  auto z = dt.to_string(\"%z\");\n  if (z.empty()) {\n    // who knows!\n    return \"0000\";\n  }\n  if (z.front() == '+') {\n    return z.substr(1);\n  }\n  return z;\n}\n\n// From file_manager.cpp\nstd::vector<fido_bundle_status_t> statuses{\n    fido_bundle_status_t::crash, fido_bundle_status_t::normal, fido_bundle_status_t::direct,\n    fido_bundle_status_t::immediate};\n\nint ftn_bytes_waiting(const Network& net, const FidoAddress& dest) {\n  const auto outbound_dir = FilePath(net.dir, net.fido.outbound_dir);\n  auto size = 0;\n  for (const auto& st : statuses) {\n    const auto name = flo_name(dest, st);\n    if (!File::Exists(FilePath(outbound_dir, name))) {\n      continue;\n    }\n    LOG(INFO) << \"Found file file: \" << outbound_dir << \"; name: \" << name;\n    const auto flo_path = FilePath(outbound_dir, name);\n    FloFile flo(net, flo_path);\n    if (!flo.Load()) {\n      continue;\n    }\n    for (const auto& [flow_entry_name, _] : flo.flo_entries()) {\n      File f(flow_entry_name);\n      size += f.length();\n    }\n  }\n  VLOG(2) << \"ftn_bytes_waiting: size: \" << size;\n  return size;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/fido/fido_util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_FIDO_UTIL_H\n#define INCLUDED_SDK_FIDO_FIDO_UTIL_H\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include <ctime>\n#include <filesystem>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::fido {\n\nclass FidoStoredMessage;\nstruct packet_header_2p_t;\nclass FidoPackedMessage;\n\n// FTN Naming\nstd::string packet_name(const wwiv::core::DateTime& dt);\nstd::string bundle_name(const FidoAddress& source, const FidoAddress& dest, int dow, int bundle_number);\nstd::string bundle_name(const FidoAddress& source, const FidoAddress& dest, const std::string& extension);\nstd::string net_node_name(const FidoAddress& dest, const std::string& extension);\nstd::string flo_name(const FidoAddress& dest, net::fido_bundle_status_t status);\nstd::vector<std::string> dow_prefixes();\nstd::string dow_extension(int dow, int bundle_number);\nbool is_bundle_file(const std::string& name);\nbool is_packet_file(const std::string& name);\nstd::string control_file_name(const FidoAddress& dest, net::fido_bundle_status_t status);\nbool exists_bundle(const wwiv::sdk::Config& config, const net::Network& net);\nbool exists_bundle(const std::filesystem::path& dir);\n\n// FTN DateTime\nstd::string daten_to_fido(time_t t);\ndaten_t fido_to_daten(std::string d);\nstd::string tz_offset_from_utc(const core::DateTime& dt);\n\n// FTN Addressing\nstd::string to_net_node(const FidoAddress& a);\nstd::string to_zone_net_node(const FidoAddress& a);\nstd::string to_zone_net_node_point(const FidoAddress& a);\n\nbool RoutesThroughAddress(const FidoAddress& a, const std::string& routes);\n\n// [[VisibleForTesting]]\nstd::optional<FidoAddress> FindRouteToAddress(\n    const FidoAddress& a,\n    const std::map<FidoAddress, wwiv::sdk::net::fido_node_config_t>& node_configs_map);\nstd::optional<FidoAddress> FindRouteToAddress(const FidoAddress& a, const FidoCallout& callout);\n\n// FTN Text Handling\n/** Splits a message to find a specific line. This will strip blank lines. */\nstd::vector<std::string> split_message(const std::string& string);\n\n/** Converts Ftn style text to WWIV style */\nstd::string FidoToWWIVText(const std::string& ft, bool convert_control_codes = true);\n\nstruct wwiv_to_fido_options {\n  // Num of optional val lines to included (0-9)\n  int max_optional_val_to_include{9};\n  // Should heart codes be converted\n  bool wwiv_heart_color_codes{false};\n  // Should wwiv color pipe codes be made standard.\n  bool wwiv_pipe_color_codes{false};\n  // user colors to use.\n  std::vector<int> colors{7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n  // Allow any pipe codes, WWIV and standard.\n  bool allow_any_pipe_codes{true};\n};\n\n/**\n * Converts WWIV style text to FTN style, line endings, control lines, etc\n */\nstd::string WWIVToFidoText(const std::string& wt, const wwiv_to_fido_options& opts);\n\n/**\n * Gets the FidoAddress from a single line of text of the form:\n * \"Name (zone:node/net) or '* Origin: Foo BBS (zone:node/net)'\"\n */\nstd::optional<FidoAddress> get_address_from_single_line(const std::string& line);\n\n/**\n * Gets the FidoAddress from an entire message by looking for the \"* Origin: \"\n * line in the message text.  The Origin line is expected to be of the form:\n * \"* Origin: Some Origin Line Text (zone:node/net)\"\n */\nstd::optional<FidoAddress> get_address_from_origin(const std::string& text);\n\n/**\n * Gets the FidoAddress from an packet.\n *\n * Prefer the address from the Origin line of possible, otherwise use the zone\n * from the packet header, and net/node from the packed message that should be part of the\n * packet containing the header.\n */\nFidoAddress get_address_from_packet(const FidoPackedMessage& msg, const packet_header_2p_t& header);\n\n/**\n * Gets the FidoAddress from a stored message (*.MSG file).\n *\n * Prefer the address from the Origin line of possible, otherwise use the zone\n * from the packet header, and net/node from the packed message.\n */\nFidoAddress get_address_from_stored_message(const FidoStoredMessage& msg);\n\n/**\n *  Gets the number of bytes waiting across all packets listed in flo files for\n *  the 'dest' address on 'net' network.\n */\nint ftn_bytes_waiting(const net::Network& net, const fido::FidoAddress& dest);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/fido/fido_util_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/test/file_helper.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"gtest/gtest.h\"\n#include <ctime>\n#include <memory>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\n\nclass FidoUtilTest : public testing::Test {\npublic:\n  FidoUtilTest() = default;\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n  wwiv_to_fido_options opts;\n\n};\n\nTEST_F(FidoUtilTest, PacketName) {\n  auto dt = DateTime::now();\n  const auto tm = dt.to_tm();\n  const auto actual = packet_name(dt);\n\n  const auto expected =\n      fmt::sprintf(\"%2.2d%2.2d%2.2d%2.2d.pkt\", tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(FidoUtilTest, BundleName_Extension) {\n  const FidoAddress source(\"1:105/6\");\n  const FidoAddress dest(\"1:105/42\");\n  const auto actual = bundle_name(source, dest, \"su0\");\n\n  EXPECT_EQ(\"0000ffdc.su0\", actual);\n}\n\nTEST_F(FidoUtilTest, BundleName_NoExtension) {\n  const FidoAddress source(\"1:105/6\");\n  const FidoAddress dest(\"1:105/42\");\n  const auto actual = bundle_name(source, dest, 1, 3);\n\n  EXPECT_EQ(\"0000ffdc.mo3\", actual);\n}\n\nTEST_F(FidoUtilTest, DowExtension) {\n  EXPECT_EQ(\"mo0\", dow_extension(1, 0));\n  EXPECT_EQ(\"sa9\", dow_extension(6, 9));\n  EXPECT_EQ(\"sua\", dow_extension(0, 10));\n  EXPECT_EQ(\"suz\", dow_extension(0, 35));\n}\n\nTEST_F(FidoUtilTest, IsBundleFile) {\n  EXPECT_TRUE(is_bundle_file(\"00000000.su0\"));\n  EXPECT_FALSE(is_bundle_file(\"00000000.foo\"));\n}\n\nTEST_F(FidoUtilTest, ControlFileName) {\n  const FidoAddress dest(\"1:105/42\");\n  EXPECT_EQ(\"0069002a.flo\", control_file_name(dest, fido_bundle_status_t::normal));\n  EXPECT_EQ(\"0069002a.clo\", control_file_name(dest, fido_bundle_status_t::crash));\n  EXPECT_EQ(\"0069002a.dlo\", control_file_name(dest, fido_bundle_status_t::direct));\n  EXPECT_EQ(\"0069002a.hlo\", control_file_name(dest, fido_bundle_status_t::hold));\n}\n\nTEST_F(FidoUtilTest, ToNetNode) {\n  EXPECT_EQ(\"105/42\", to_net_node(FidoAddress(\"1:105/42\")));\n  EXPECT_EQ(\"105/42\", to_net_node(FidoAddress(\"105/42\")));\n}\n\nTEST_F(FidoUtilTest, ToNetNodeZone) {\n  EXPECT_EQ(\"2:105/42\", to_zone_net_node(FidoAddress(\"2:105/42\")));\n  EXPECT_EQ(\"1:105/42\", to_zone_net_node(FidoAddress(\"105/42\")));\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_Basic) {\n  const std::string fido = \"Hello\\rWorld\\r\";\n  const std::string wwiv = FidoToWWIVText(fido);\n  EXPECT_EQ(\"Hello\\r\\nWorld\\r\\n\", wwiv);\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_BlankLines) {\n  const std::string fido = \"Hello\\r\\r\\rWorld\\r\";\n  const auto wwiv = FidoToWWIVText(fido);\n  EXPECT_EQ(\"Hello\\r\\n\\r\\n\\r\\nWorld\\r\\n\", wwiv);\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_SoftCr) {\n  const std::string fido = \"a\\x8d\"\n                \"b\\r\";\n  const auto wwiv = FidoToWWIVText(fido);\n  EXPECT_EQ(\"a\\r\\nb\\r\\n\", wwiv);\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_ControlLine) {\n  const std::string fido = \"\\001\"\n                \"PID\\rWorld\\r\";\n  const auto wwiv = FidoToWWIVText(fido);\n  EXPECT_EQ(\"\\004\"\n            \"0PID\\r\\nWorld\\r\\n\",\n            wwiv);\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_SeenBy) {\n  const std::string fido = \"Hello\\rSEEN-BY: 1/1\\rWorld\\r\";\n  const auto  wwiv = FidoToWWIVText(fido);\n  EXPECT_EQ(\"Hello\\r\\n\\004\"\n            \"0SEEN-BY: 1/1\\r\\nWorld\\r\\n\",\n            wwiv);\n}\n\nTEST_F(FidoUtilTest, FidoToWWIVText_ControlLine_DoNotConvert) {\n  const std::string fido = \"\\001\"\n                \"PID\\rWorld\\r\";\n  const auto  wwiv = FidoToWWIVText(fido, false);\n  EXPECT_EQ(\"\\001\"\n            \"PID\\r\\nWorld\\r\\n\",\n            wwiv);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_Basic) {\n  const std::string wwiv = \"a\\r\\nb\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_BlankLines) {\n  const std::string wwiv = \"a\\r\\n\\r\\n\\r\\nb\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r\\r\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_MalformedControlLine) {\n  const std::string wwiv = \"a\\r\\nb\\r\\n\\004\"\n                \"0Foo:\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_MsgId) {\n  const std::string wwiv = \"a\\r\\nb\\r\\n\\004\"\n                \"0MSGID: 1234 5678\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\\001MSGID: 1234 5678\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_SeenBy) {\n  const std::string wwiv = \"a\\r\\nb\\r\\n\\004\"\n                \"0SEEN-BY: 1/1\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\rSEEN-BY: 1/1\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_Reply) {\n  const std::string wwiv = \"a\\r\\nb\\r\\n\\004\"\n                \"0REPLY: 1234 5678\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\\001REPLY: 1234 5678\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesControlZ) {\n  const std::string wwiv = \"a\\r\\n\\x1a\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesControlZs) {\n  const std::string wwiv = \"a\\r\\n\\x1a\\x1a\\x1a\\x1a\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesControlA) {\n  const std::string wwiv = \"a\\r\\nb\\001\\r\\n\";\n  const auto  fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesControlB) {\n  const std::string wwiv = \"a\\r\\n\\002b\\r\\n\";\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesHeart) {\n  const std::string wwiv = \"a\\r\\n\\003\"\"1b\\r\\n\";\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rb\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_RemovesHeartAndPipes) {\n  const std::string wwiv = \"a\\r\\n\\003\"\"1b|#1c|#0\\r\\n\";\n  opts.wwiv_heart_color_codes = false;\n  opts.wwiv_pipe_color_codes = false;\n  opts.allow_any_pipe_codes = false;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\rbc\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_HeartAtEnd) {\n  const std::string wwiv = \"a\\r\\n\\003\";\n  opts.wwiv_heart_color_codes = true;\n  opts.wwiv_pipe_color_codes = true;\n  opts.allow_any_pipe_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_PipeAtEnd) {\n  const std::string wwiv = \"a\\r\\n|\";\n  opts.wwiv_heart_color_codes = true;\n  opts.wwiv_pipe_color_codes = true;\n  opts.allow_any_pipe_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r|\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_ConvertsHeart) {\n  const std::string wwiv = \"a\\r\\n\\003\"\"1b\\r\\n\";\n  opts.wwiv_heart_color_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r|11b\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_ConvertsHeartOnly) {\n  const std::string wwiv = \"\\003\"\"1\";\n  opts.wwiv_heart_color_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"|11\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_ConvertsUserColorPipe) {\n  const std::string wwiv = \"a\\r\\n|#1b\\r\\n\";\n  opts.wwiv_pipe_color_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r|11b\\r\", fido);\n}\n\nTEST_F(FidoUtilTest, WWIVToFido_DoesntWhenNotSelected_ConvertsUserColorPipe) {\n  const std::string wwiv = \"a\\r\\n|#1b\\r\\n\";\n  opts.wwiv_pipe_color_codes = false;\n  opts.wwiv_heart_color_codes = true;\n  const auto fido = WWIVToFidoText(wwiv, opts);\n  EXPECT_EQ(\"a\\r|#1b\\r\", fido);\n}\n\n\nTEST_F(FidoUtilTest, MkTime) {\n  auto now = time(nullptr);\n  auto* tm = localtime(&now);\n  const auto rt = mktime(tm);\n\n  EXPECT_EQ(now, rt);\n}\n\nTEST_F(FidoUtilTest, RouteThrough) {\n  const FidoAddress a(\"11:1/100\");\n\n  EXPECT_TRUE(RoutesThroughAddress(a, \"*\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:*\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:1/*\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:1/100\"));\n\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:* 1:* 2:* 3:* 4:*\"));\n\n  EXPECT_FALSE(RoutesThroughAddress(a, \"!*\"));\n  EXPECT_FALSE(RoutesThroughAddress(a, \"12:*\"));\n  EXPECT_FALSE(RoutesThroughAddress(a, \"11:2/*\"));\n  EXPECT_FALSE(RoutesThroughAddress(a, \"11:1/101\"));\n\n  EXPECT_FALSE(RoutesThroughAddress(a, \"11:* !11:1/100\"));\n  EXPECT_FALSE(RoutesThroughAddress(a, \"11:* 11:1/* !11:1/100\"));\n\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:* !11:1/* 11:1/100\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"!11:* 11:1/100\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"* !11:* 11:1/100\"));\n  EXPECT_TRUE(RoutesThroughAddress(a, \"11:* !11:1/* 11:1/100\"));\n}\n\n\nTEST_F(FidoUtilTest, FindRouteAddress) {\n  const FidoAddress a(\"11:1/100\");\n  const FidoAddress b(\"12:112/100\");\n  const FidoAddress a1(\"1:1/1\");\n  const FidoAddress a2(\"2:1/1\");\n  const FidoAddress a11(\"11:1/1\");\n  const FidoAddress a11_other(\"11:1/1\");\n  const FidoAddress a12(\"12:1/1\");\n\n  fido_node_config_t c11{\"11:*\"};\n  fido_node_config_t c12{\"12:*\"};\n  const std::map<FidoAddress, fido_node_config_t> m = {{a11, c11}, {a12, c12}};\n  EXPECT_EQ(a11, FindRouteToAddress(a, m).value());\n  EXPECT_EQ(a12, FindRouteToAddress(b, m).value());\n  EXPECT_FALSE(FindRouteToAddress(a1, m).has_value());\n}\n\nclass FidoUtilConfigTest : public testing::Test {\npublic:\n  FidoUtilConfigTest() {\n    CHECK(files_.Mkdir(\"bbs\"));\n    CHECK(files_.Mkdir(\"bbs/net\"));\n    const auto root = files_.Dir(\"bbs\");\n    config_.reset(new wwiv::sdk::Config(root));\n  }\n\n  wwiv::core::test::FileHelper files_;\n  std::unique_ptr<wwiv::sdk::Config> config_;\n};\n\nTEST_F(FidoUtilConfigTest, ExistsBundle) {\n  Network net;\n  net.name = \"testnet\";\n  ASSERT_TRUE(files_.Mkdir(\"bbs/net\"));\n  net.dir = files_.DirName(\"bbs/net\");\n\n  EXPECT_FALSE(exists_bundle(*config_, net));\n  EXPECT_FALSE(exists_bundle(net.dir));\n\n  files_.CreateTempFile(\"bbs/net/00124567.su0\", \"x\");\n  EXPECT_TRUE(exists_bundle(*config_, net));\n  EXPECT_TRUE(exists_bundle(net.dir)) << net.dir;\n}\n\nTEST_F(FidoUtilTest, GetAddressFromSingleLine) {\n  {\n    const auto a = get_address_from_single_line(\"\");\n    EXPECT_FALSE(a.has_value());\n  }\n\n  {\n    const auto a = get_address_from_single_line(\"Not an origin line\");\n    EXPECT_FALSE(a.has_value());\n  }\n\n  {\n    const auto a = get_address_from_single_line(\" * Origin: Kewl BBS (1:2/3)\");\n    ASSERT_TRUE(a.has_value());\n    EXPECT_EQ(1, a->zone());\n    EXPECT_EQ(2, a->net());\n    EXPECT_EQ(3, a->node());\n  }\n}\n\nTEST_F(FidoUtilTest, FidoToDaten) {\n  const auto t = fido_to_daten(\"23 Dec 16  20:53:38\");\n  EXPECT_GT(t, 0u);\n}\n\nTEST_F(FidoUtilTest, TzOffsetFromUTC) {\n  char s[100];\n  auto t = time(nullptr);\n  auto* tm = localtime(&t);\n  memset(s, 0, sizeof s);\n  ASSERT_NE(0UL, strftime(s, sizeof s, \"%z\", tm));\n  \n  std::string ss{s};\n  if (ss.front() == '+') {\n    ss = ss.substr(1);\n  }\n\n  EXPECT_EQ(ss, tz_offset_from_utc(DateTime::from_tm(tm)));\n}\n\nTEST_F(FidoUtilTest, IsPacketFile) {\n  EXPECT_TRUE(is_packet_file(\"0c386971.pkt\"));  \n  EXPECT_TRUE(is_packet_file(\"0000000.pkt\"));  \n  EXPECT_FALSE(is_packet_file(\"0c386971.pkts\"));  \n  EXPECT_FALSE(is_packet_file(\"\"));  \n}\n\nTEST_F(FidoUtilTest, FtnBytesWaiting) {\n  Network net{};\n\n  net.dir = helper_.TempDir().string();\n  net.fido.fido_address = \"11:1/211\";\n  const FidoAddress dest(\"11:1/100\");\n  const auto actual = helper_.CreateTempFile(\"0000006f.su0\", std::string(2000, 'X'));\n  const auto line = fmt::format(\"^{}\", actual.string());\n  auto p = helper_.CreateTempFile(\"00010064.flo\", line);\n  const auto bytes_waiting = ftn_bytes_waiting(net, dest);\n  EXPECT_EQ(2000, bytes_waiting);\n}\n\nTEST_F(FidoUtilTest, FtnBytesWaiting_NonExistant) {\n  Network net{};\n\n  net.dir = helper_.TempDir().string();\n  net.fido.fido_address = \"11:1/211\";\n  const FidoAddress dest(\"11:1/100\");\n  const auto actual = helper_.CreateTempFile(\"0000006f.su0\", std::string(2000, 'X'));\n  const auto line = fmt::format(\"^{}\", actual.string());\n  auto p = helper_.CreateTempFilePath(\"00010064.flo\");\n  const auto bytes_waiting = ftn_bytes_waiting(net, dest);\n  EXPECT_EQ(0, bytes_waiting);\n}\n\nTEST_F(FidoUtilTest, GetAddressFromOrigin) {\n  std::string msg = R\"(\nthis is test #4.\n\nRushfan\n\n--- Mystic BBS v1.12 A45 2020/02/18 (Windows/64)\n * Origin: My Origin (21:1/2)\nSEEN-BY: 1/1 2\n)\";\n  std::replace(msg.begin(), msg.end(), '\\n', '\\r');\n\n  const auto a = get_address_from_origin(msg);\n  EXPECT_EQ(21, a->zone());\n  EXPECT_EQ(1, a->net());\n  EXPECT_EQ(2, a->node());\n}\n\n"
  },
  {
    "path": "sdk/fido/flo_file.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/flo_file.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::fido {\n\n  \nstatic std::vector<std::pair<std::string, flo_directive>>\nParseFloFile(const std::filesystem::path& path) {\n  TextFile file(path, \"r\");\n  if (!file.IsOpen()) {\n    return {};\n  }\n\n  std::vector<std::pair<std::string, flo_directive>> result;\n  std::string line;\n  while (file.ReadLine(&line)) {\n    StringTrim(&line);\n    if (line.empty()) {\n      continue;\n    }\n    if (auto st = line.front(); st == '^' || st == '#' || st == '~') {\n      const auto fn = line.substr(1);\n      result.emplace_back(fn, static_cast<flo_directive>(st));\n    }\n  }\n  return result;\n}\n\nFloFile::FloFile(const Network& net, std::filesystem::path p)\n    : net_(net), path_(std::move(p)) {\n  std::filesystem::path fn;\n  if (!path_.has_filename()) {\n    // This is a malformed flo file\n    LOG(ERROR) << \"Malformed FLO file found, bad filename: \" << path_;\n    return;\n  }\n  if (!path_.has_extension()) {\n    // This is a malformed flo file\n    LOG(ERROR) << \"Malformed FLO file found, no extension: \" << path_;\n    return;\n  }\n\n  auto basename = ToStringLowerCase(path_.stem().string());\n  auto ext = ToStringLowerCase(path_.extension().string());\n\n  // Check for 4 so that it's dot + 3 letter extension\n  if (ext.length() != 4) {\n    // malformed flo file\n    LOG(ERROR) << \"Malformed FLO file found, bad extension: \" << path_;\n    return;\n  }\n  // extract the dot\n  ext = ext.substr(1);\n\n  if (basename.length() != 8) {\n    // malformed flo file\n    LOG(ERROR) << \"Malformed FLO file found, bad stem: \" << path_;\n    return;\n  }\n  if (!ends_with(ext, \"lo\")) {\n    // malformed flo file\n    LOG(ERROR) << \"Malformed FLO file found, bad extension: \" << path_;\n    return;\n  }\n  status_ = static_cast<fido_bundle_status_t>(ext.front());\n\n  auto netstr = basename.substr(0, 4);\n  auto net_num = to_number<int16_t>(netstr, 16);\n  auto nodestr = basename.substr(4);\n  auto node_num = to_number<int16_t>(nodestr, 16);\n\n  FidoAddress source(net_.fido.fido_address);\n  dest_.reset(new FidoAddress(source.zone(), net_num, node_num, 0, source.domain()));\n\n  Load();\n}\n\nFloFile::~FloFile() = default;\n\nbool FloFile::insert(const std::string& file, flo_directive directive) {\n  entries_.emplace_back(file, directive);\n  return true;\n}\n\nbool FloFile::clear() noexcept {\n  entries_.clear();\n  poll_ = false;\n  return true;\n}\n\nbool FloFile::erase(const std::string& file) {\n  for (auto it = entries_.begin(); it != entries_.end(); ++it) {\n    if ((*it).first == file) {\n      entries_.erase(it);\n      return true;\n    }\n  }\n  return false;\n}\n\nbool FloFile::Load() {\n  exists_ = File::Exists(path_);\n  if (!exists_) {\n    return false;\n  }\n\n  const File f(path_);\n  poll_ = f.length() == 0;\n  entries_ = ParseFloFile(path_);\n  return true;\n}\n\nbool FloFile::Save() {\n  if (poll_ || !entries_.empty()) {\n    File f(path_);\n    if (!f.Open(File::modeCreateFile | File::modeReadWrite | File::modeText | File::modeTruncate,\n                File::shareDenyReadWrite)) {\n      return false;\n    }\n    for (const auto& e : entries_) {\n      auto dr = static_cast<char>(e.second);\n      const auto& name = e.first;\n      f.Writeln(StrCat(dr, name));\n    }\n    return true;\n  }\n  if (File::Exists(path_)) {\n    return File::Remove(path_);\n  }\n  return true;\n}\n\nFidoAddress FloFile::destination_address() const { return *dest_; }\n\nvoid FloFile::set_poll(bool p) { poll_ = p; }\n\nconst std::vector<std::pair<std::string, flo_directive>>& FloFile::flo_entries() const {\n  return entries_;\n}\n\n\n}\n"
  },
  {
    "path": "sdk/fido/flo_file.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_FIDO_FLO_FILE_H__\n#define __INCLUDED_SDK_FIDO_FLO_FILE_H__\n\n#include \"sdk/fido/fido_callout.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk::fido {\n  \nenum class flo_directive : char {\n  truncate_file = '#',\n  delete_file = '^',\n  skip_file = '~',\n  unknown = ' '\n};\n\n/**\n * Represents a FLO file on disk.  The file is locked open the entire time that\n * this class exists.\n */\nclass FloFile {\npublic:\n  FloFile(const net::Network& net, std::filesystem::path p);\n  virtual ~FloFile();\n\n  [[nodiscard]] FidoAddress destination_address() const;\n  [[nodiscard]] bool poll() const { return poll_; }\n  void set_poll(bool p);\n  [[nodiscard]] net::fido_bundle_status_t status() const { return status_; }\n  [[nodiscard]] const std::vector<std::pair<std::string, flo_directive>>& flo_entries() const;\n\n  [[nodiscard]] bool exists() const noexcept { return exists_; }\n  [[nodiscard]] bool empty() const noexcept { return entries_.empty(); }\n  [[nodiscard]] bool insert(const std::string& file, flo_directive directive);\n  bool clear() noexcept;\n  bool erase(const std::string& file);\n  bool Load();\n  bool Save();\n\nprivate:\n  const net::Network& net_;\n  const std::filesystem::path path_;\n  net::fido_bundle_status_t status_{net::fido_bundle_status_t::unknown};\n  std::unique_ptr<wwiv::sdk::fido::FidoAddress> dest_;\n  bool exists_{false};\n  bool poll_{false};\n\n  std::vector<std::pair<std::string, flo_directive>> entries_;\n};\n\n}\n\n#endif"
  },
  {
    "path": "sdk/fido/flo_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/fido/flo_file.h\"\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\n\nclass FloTest : public testing::Test {\npublic:\n  FloTest() {\n    net.dir = helper_.TempDir().string();\n    net.fido.fido_address = \"11:1/211\";\n    p = helper_.CreateTempFile(\"00010064.flo\", \"^C:\\\\db\\\\outbound\\\\0000006f.su0\");\n  }\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n  Network net{};\n\n  std::filesystem::path p{};\n};\n\nTEST_F(FloTest, FloFile_Exists) {\n  {\n    const FloFile flo(net, p);\n    ASSERT_TRUE(flo.exists());\n  }\n  { \n    p.replace_filename(\"00010063.flo\");\n    const FloFile flo(net, p);\n    ASSERT_FALSE(flo.exists());\n  }\n}\n\nTEST_F(FloTest, FloFile_Smoke) {\n  FloFile flo(net, p);\n  EXPECT_FALSE(flo.poll());\n  ASSERT_EQ(1, wwiv::stl::ssize(flo.flo_entries()));\n\n  {\n    auto e = flo.flo_entries().front();\n    EXPECT_EQ(\"C:\\\\db\\\\outbound\\\\0000006f.su0\", e.first);\n    EXPECT_EQ(flo_directive::delete_file, e.second);\n    EXPECT_TRUE(flo.clear());\n    EXPECT_TRUE(flo.empty());\n    EXPECT_TRUE(flo.Save());\n    EXPECT_FALSE(File::Exists(p)) << p;\n  }\n\n  EXPECT_TRUE(flo.insert(\"C:\\\\db\\\\outbound\\\\0000006f.mo0\", flo_directive::truncate_file));\n  {\n    auto e = flo.flo_entries().front();\n    EXPECT_EQ(\"C:\\\\db\\\\outbound\\\\0000006f.mo0\", e.first);\n    EXPECT_EQ(flo_directive::truncate_file, e.second);\n    flo.Save();\n    EXPECT_TRUE(File::Exists(p));\n    EXPECT_TRUE(flo.clear());\n    File::Remove(p);\n  }\n\n  {\n    flo.set_poll(true);\n    flo.Save();\n    EXPECT_TRUE(File::Exists(p));\n\n    TextFile tf(p, \"r\");\n    const auto contents = tf.ReadFileIntoString();\n    EXPECT_EQ(\"\", contents);\n  }\n}\n\nTEST_F(FloTest, Poll) {\n  FloFile flo(net, p);\n  ASSERT_FALSE(flo.poll());\n  flo.set_poll(true);\n  ASSERT_TRUE(flo.poll());\n  flo.set_poll(false);\n  ASSERT_FALSE(flo.poll());\n}\n"
  },
  {
    "path": "sdk/fido/nodelist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/fido/nodelist.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include <set>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::fido {\n\nstatic NodelistKeyword to_keyword(const std::string& k) {\n  if (k.empty()) {\n    return NodelistKeyword::node;\n  }\n\n  if (k == \"Down\") return NodelistKeyword::down;\n  if (k == \"Host\") return NodelistKeyword::host;\n  if (k == \"Hub\") return NodelistKeyword::hub;\n  if (k == \"Pvt\") return NodelistKeyword::pvt;\n  if (k == \"Region\") return NodelistKeyword::region;\n  if (k == \"Zone\") return NodelistKeyword::zone;\n\n  return NodelistKeyword::node;\n}\n\nstatic inline bool bool_flag(const std::string& value, const std::string& flag_name, bool& f) {\n  if (value == flag_name) {\n    f = true;\n    return true;\n  }\n  return false;\n}\n\nstatic bool internet_flag(const std::string& value, const std::string& flag_name, bool& f, std::string& host, uint16_t& port) {\n  if (!contains(value, ':')) return false;\n  auto parts = SplitString(value, \":\");\n  if (parts.size() > 3) return false;\n\n  if (parts.front() == flag_name) {\n    f = true;\n    if (parts.size() > 1) {\n      port = to_number<uint16_t>(parts.back());\n    }\n    if (parts.size() == 3) {\n      // flag:host:port\n      host = at(parts, 1);\n    }\n    return true;\n  }\n  return false;\n}\n\nstatic bool bool_flag(const std::string& value, const std::string& flag_name, bool& f, std::string& fs) {\n  if (!contains(value, ':')) return false;\n  std::vector<std::string> parts = SplitString(value, \":\");\n  if (parts.size() > 2) return false;\n\n  if (parts.front() == flag_name) {\n    f = true;\n    if (parts.size() > 1) {\n      fs = parts.back();\n//      StringTrim(&fs);\n    }\n    return true;\n  }\n  return false;\n}\n\nstatic std::string ToSpaces(const std::string& orig) {\n  std::string s(orig);\n  std::replace(std::begin(s), std::end(s), '_', ' ');\n  return s;\n}\n\n//static \nstd::optional<NodelistEntry> NodelistEntry::ParseDataLine(const std::string& data_line) {\n  if (data_line.front() == ';') {\n    return std::nullopt;\n  }\n\n  auto parts = SplitString(data_line, \",\");\n  if (parts.size() < 6) {\n    return std::nullopt;\n  }\n\n  NodelistEntry e{};\n  auto it = parts.cbegin();\n  if (data_line.front() == ',') {\n    // We have no 1st field, default the keyword and skip the iterator.\n    e.keyword_ = NodelistKeyword::node;\n  } else {\n    e.keyword_ = to_keyword(*it++);\n  }\n  e.number_ = to_number<uint16_t>(*it++);\n  e.name_ = ToSpaces(*it++);\n  e.location_ = ToSpaces(*it++);\n  e.sysop_name_ = ToSpaces(*it++);\n  e.phone_number_ = *it++;\n  if (it != parts.end()) {\n    e.baud_rate_ = to_number<unsigned int>(*it++);\n  }\n\n  while (it != parts.end()) {\n    const auto& f = *it++;\n    if (bool_flag(f, \"CM\", e.cm_)) continue;\n    if (bool_flag(f, \"ICM\", e.icm_)) continue;\n    if (bool_flag(f, \"MO\", e.mo_)) continue;\n    if (bool_flag(f, \"LO\", e.lo_)) continue;\n    if (bool_flag(f, \"MN\", e.mn_)) continue;\n\n    if (bool ignore; bool_flag(f, \"INA\", ignore, e.hostname_)) continue;\n    if (internet_flag(f, \"IBN\", e.binkp_, e.binkp_hostname_, e.binkp_port_)) continue;\n    if (internet_flag(f, \"ITN\", e.telnet_, e.telnet_hostname_, e.telnet_port_)) continue;\n    if (internet_flag(f, \"IVN\", e.vmodem_, e.vmodem_hostname_, e.vmodem_port_)) continue;\n\n    // TODO(rushfan): Handle X? flags.\n  }\n  if (e.binkp_) {\n    if (e.binkp_port_ == 0) e.binkp_port_ = 24554;\n    if (e.binkp_hostname_.empty()) e.binkp_hostname_ = e.hostname();\n  }\n  if (e.telnet_) {\n    if (e.telnet_port_ == 0) e.telnet_port_ = 24554;\n    if (e.telnet_hostname_.empty()) e.telnet_hostname_ = e.hostname();\n  }\n  if (e.vmodem_) {\n    if (e.vmodem_port_ == 0) e.vmodem_port_ = 24554;\n    if (e.vmodem_hostname_.empty()) e.vmodem_hostname_ = e.hostname();\n  }\n\n  return {e};\n}\n\nNodelist::Nodelist(const std::filesystem::path& path, std::string domain) \n  : domain_(std::move(domain)), initialized_(Load(path)) {}\n\nNodelist::Nodelist(const std::vector<std::string>& lines, std::string domain) \n  : domain_(std::move(domain)), initialized_(Load(lines)) {}\n\nbool Nodelist::AddEntry(uint16_t zone, uint16_t net, NodelistEntry& e) {\n  if (zone == 0 || net == 0) {\n    // skip malformed entries.\n    return false;\n  }\n  FidoAddress address(zone, net, e.number(), 0, domain_);\n  e.address(address);\n  entries_.emplace(address, e);\n  return true;\n}\n\nbool Nodelist::HandleLine(const std::string& line, uint16_t& zone, uint16_t& region, uint16_t& net, uint16_t& hub) {\n  if (line.empty()) return true;\n  if (line.front() == ';') {\n    // TODO(rushfan): Do we care to do anything with this?\n    return true;\n  }\n  if (auto e = NodelistEntry::ParseDataLine(line)) {\n    switch (e->keyword()) {\n    case NodelistKeyword::down:\n      // let's skip these for now\n    break;\n    case NodelistKeyword::host:\n    {\n      net = e->number();\n    } break;\n    case NodelistKeyword::hub:\n    {\n      hub = e->number();\n      // Hub's should have entries in the database\n      // Hub FTN NODELIST file variable not recognized #1616\n      AddEntry(zone, net, e.value());\n    } break;\n    // Let's include pvt nodes since you can still route\n    // to them.\n    case NodelistKeyword::pvt:\n    case NodelistKeyword::node:\n    {\n      AddEntry(zone, net, e.value());\n    } break;\n    case NodelistKeyword::region:\n    {\n      region = e->number();\n      // also use region for the net since we're addressable\n      // as zone:region/node\n      net = e->number();\n      hub = 0;\n    } break;\n    case NodelistKeyword::zone:\n    {\n      zone = e->number();\n      region = hub = net = 0;\n    } break;\n    }\n    return true;\n  }\n  return false;\n}\n\nbool Nodelist::Load(const std::filesystem::path& path) {\n  TextFile f(path, \"rt\");\n  if (!f) {\n    return false;\n  }\n  const auto lines = f.ReadFileIntoVector();\n  return Load(lines);\n}\n\nbool Nodelist::Load(const std::vector<std::string>& lines) {\n  if (lines.empty()) return false;\n  // ReSharper disable CppTooWideScope\n  uint16_t zone = 0, region = 0, net = 0, hub = 0;\n  // ReSharper restore CppTooWideScope\n  for (const auto& raw_line : lines) {\n    auto line = StringTrim(raw_line);\n    HandleLine(line, zone, region, net, hub);\n  }\n  return true;\n}\n\nconst NodelistEntry& Nodelist::entry(const FidoAddress& a) const {\n  if (stl::contains(entries_, a)) {\n    return at(entries_, a);\n  }\n  if (a.has_domain()) {\n    if (stl::contains(entries_, a.without_domain())) {\n      return at(entries_, a.without_domain());\n    }\n  } else {\n    if (stl::contains(entries_, a.with_domain(domain_))) {\n      return at(entries_, a.with_domain(domain_));\n    }\n  }\n  const auto s = fmt::format(\"Nodelist::entry: key missing: {} \", a.as_string(true, true));\n  DLOG(FATAL) << s << \": at: \\r\\n\" << os::stacktrace();\n  throw std::out_of_range(s);\n}\n\nbool Nodelist::contains(const FidoAddress& a) const {\n  if (stl::contains(entries_, a)) {\n    return true;\n  }\n  if (a.has_domain()) {\n    if (stl::contains(entries_, a.without_domain())) {\n      return true;\n    }\n  } else {\n    if (stl::contains(entries_, a.with_domain(domain_))) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstd::vector<NodelistEntry> Nodelist::entries(uint16_t zone, uint16_t net) const {\n  std::vector<NodelistEntry> entries;\n  for (const auto& e : entries_) {\n    if (e.first.zone() == zone && e.first.net() == net) {\n      entries.push_back(e.second);\n    }\n  }\n  return entries;\n}\n\nstd::vector<NodelistEntry> Nodelist::entries(uint16_t zone) const {\n  std::vector<NodelistEntry> entries;\n  for (const auto& e : entries_) {\n    if (e.first.zone() == zone) {\n      entries.push_back(e.second);\n    }\n  }\n  return entries;\n}\n\nstd::vector<uint16_t> Nodelist::zones() const {\n  std::set<uint16_t> s;\n  for (const auto& e : entries_) {\n    s.emplace(e.first.zone());\n  }\n  std::vector<uint16_t> zones;\n  for (const auto& n : s) {\n    zones.emplace_back(n);\n  }\n  return zones;\n}\n\nstd::vector<uint16_t> Nodelist::nets(uint16_t zone) const {\n  std::set<uint16_t> s;\n  for (const auto& e : entries_) {\n    if (e.first.zone() == zone) {\n      s.emplace(e.first.net());\n    }\n  }\n  std::vector<uint16_t> nets;\n  for (const auto& n : s) {\n    nets.emplace_back(n);\n  }\n  return nets;\n}\n\nstd::vector<uint16_t> Nodelist::nodes(uint16_t zone, uint16_t net) const {\n  std::vector<uint16_t> nodes;\n  for (const auto& e : entries_) {\n    if (e.first.zone() == zone && e.first.net() == net) {\n      nodes.emplace_back(e.first.node());\n    }\n  }\n  return nodes;\n}\n\nconst NodelistEntry* Nodelist::entry(uint16_t zone, uint16_t net, uint16_t node) {\n  const FidoAddress a(zone, net, node, 0, \"\");\n  if (!stl::contains(entries_, a)) {\n    return nullptr;\n  }\n  return &wwiv::stl::at(entries_, a);\n}\n\nbool Nodelist::has_zone(int zone) const noexcept {\n  return std::any_of(std::begin(entries_), std::end(entries_), \n    [zone](const auto& p) { return p.first.zone() == zone; });\n}\n\nstatic int year_of(time_t t) {\n  const auto dt = DateTime::from_time_t(t);\n  return dt.year();\n}\n\nint extension_number(const std::string& fn) {\n  if (!contains(fn, '.')) {\n    return 0;\n  }\n\n  const auto num = fn.substr(fn.find_last_of('.') + 1);\n  return to_number<int>(num);\n}\n\nstatic std::string latest_extension(const std::map<int, int>& ey) {\n  auto highest_year = 0;\n  for (const auto& y : ey) {\n    if (y.second > highest_year) {\n      highest_year = y.second;\n    }\n  }\n\n  for (auto r = ey.rbegin(); r != ey.rend(); ++r) {\n    if ((*r).second == highest_year) {\n      return fmt::sprintf(\"%03d\", (*r).first);\n    }\n  }\n  return \"000\";\n}\n\n// static\nstd::string Nodelist::FindLatestNodelist(const std::filesystem::path& dir, const std::string& base) {\n  const auto filespec = FilePath(dir, StrCat(base, \".*\"));\n  std::map<int, int> extension_year;\n  FindFiles fnd(filespec, FindFiles::FindFilesType::files);\n  for (const auto& ff : fnd) {\n    const auto fn = FilePath(dir, ff.name);\n    extension_year.emplace(extension_number(fn.filename().string()),\n                           year_of(File::last_write_time(fn)));\n  }\n\n  const auto ext = latest_extension(extension_year);\n  return StrCat(base, \".\", ext);\n}\n\n\n}  // namespace\n\n"
  },
  {
    "path": "sdk/fido/nodelist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_NODELIST_H\n#define INCLUDED_SDK_FIDO_NODELIST_H\n\n#include \"sdk/fido/fido_address.h\"\n#include <cstdint>\n#include <filesystem>\n#include <map>\n#include <string>\n#include <vector>\n\n/**\n * Classes to represent a FidoNet NodeList.\n *\n * FRL-1003 defines the format of the nodelist.\n * FTS-5001.004 defines the flags supported.\n */\n\nnamespace wwiv::sdk::fido {\n\n// The 1st entry of the 8 mandatory ones is the keyword.\nenum class NodelistKeyword {\n  zone, region, host, hub, pvt, down, node\n};\n\n/**\n * Represents one data line in the nodelist.\n */\nclass NodelistEntry final {\npublic:\n  NodelistEntry() = default;\n  ~NodelistEntry() = default;\n\n  static std::optional<NodelistEntry> ParseDataLine(const std::string& data_line);\n\n  [[nodiscard]] FidoAddress address() const { return address_; }\n  void address(const FidoAddress& a) { address_ = a; }\n  [[nodiscard]] NodelistKeyword keyword() const { return keyword_; }\n  [[nodiscard]] uint16_t number() const { return number_; }\n  [[nodiscard]] std::string name() const { return name_; }\n  [[nodiscard]] std::string location() const { return location_; }\n  [[nodiscard]] std::string sysop_name() const { return sysop_name_; }\n  [[nodiscard]] std::string phone_number() const { return phone_number_; }\n  [[nodiscard]] uint32_t baud_rate() const { return baud_rate_; }\n  [[nodiscard]] bool  cm() const { return cm_; }\n  [[nodiscard]] bool  icm() const { return icm_; }\n  [[nodiscard]] bool  mo() const { return mo_; }\n  [[nodiscard]] bool  lo() const { return lo_; }\n  [[nodiscard]] bool  mn() const { return mn_; }\n  [[nodiscard]] bool  bark_file() const { return bark_file_; }\n  [[nodiscard]] bool  bark_update() const { return bark_update_; }\n  [[nodiscard]] bool  wazoo_file() const { return wazoo_file_; }\n  [[nodiscard]] bool  wazoo_update() const { return wazoo_update_; }\n  [[nodiscard]] std::string hostname() const { return hostname_; }\n\n  [[nodiscard]] bool  binkp() const { return binkp_; }\n  [[nodiscard]] uint32_t binkp_port() const { return binkp_port_; }\n  [[nodiscard]] std::string binkp_hostname() const { return binkp_hostname_; }\n\n  [[nodiscard]] bool  telnet() const { return telnet_; }\n  [[nodiscard]] uint32_t telnet_port() const { return telnet_port_; }\n  [[nodiscard]] std::string telnet_hostname() const { return telnet_hostname_; }\n\n  [[nodiscard]] bool  vmodem() const { return vmodem_; }\n  [[nodiscard]] uint32_t vmodem_port() const { return vmodem_port_; }\n  [[nodiscard]] std::string vmodem_hostname() const { return vmodem_hostname_; }\n\nprivate:\n  FidoAddress address_;\n  NodelistKeyword keyword_ = NodelistKeyword::node;\n  uint16_t number_ = 0;\n  // If the bbs supports internet access, the hostname\n  // should be used here instead of the name.\n  std::string name_;\n  std::string location_;\n  std::string sysop_name_;\n  std::string phone_number_;\n  uint32_t baud_rate_ = 0;\n  // flags.\n  bool cm_ = false;\n  bool icm_ = false;\n  bool mo_ = false;\n  bool lo_ = false;\n  bool mn_ = false;\n\n  /*\n   * Capabilities defined by the X{A,B,C,P,R,W,X} flags.\n   */\n  bool bark_file_ = false;\n  bool bark_update_ = false;\n  bool wazoo_file_ = false;\n  bool wazoo_update_ = false;\n\n  //\n  // Internet flags.\n  //\n\n  // INA: Hostname to use (without port) for all services.\n  std::string hostname_;\n  // IBN: BinkP over internet\n  bool binkp_ = false;\n  uint16_t binkp_port_ = 0;\n  std::string binkp_hostname_;\n  // ITN: FTS-0001 or later over telnet.\n  bool telnet_ = false;\n  uint16_t telnet_port_ = 0;\n  std::string telnet_hostname_;\n  // IVM: FTS-0001 or later over telnet.\n  bool vmodem_ = false;\n  uint16_t vmodem_port_ = 0;\n  std::string vmodem_hostname_;\n  // The rest are ignored\n  // IP, IFC, IFT, IVM, IN04\n};\n\n/**\n * Represents a FidoNet NodeList as defined in FRL-1003.\n */\nclass Nodelist final {\npublic:\n  /** Parses address.  If it fails, throws bad_fidonet_address. */\n  Nodelist(const std::filesystem::path& path, std::string domain);\n  Nodelist(const std::vector<std::string>& lines, std::string domain);\n  ~Nodelist() = default;\n\n  [[nodiscard]] bool initialized() const { return initialized_; }\n  explicit operator bool() const { return initialized_; }\n\n  [[nodiscard]] const NodelistEntry& entry(const FidoAddress& a) const;\n  [[nodiscard]] bool contains(const FidoAddress& a) const;\n  [[nodiscard]] const std::map<FidoAddress, NodelistEntry>& entries() const { return entries_; }\n  [[nodiscard]] std::vector<NodelistEntry> entries(uint16_t zone, uint16_t net) const;\n  [[nodiscard]] std::vector<NodelistEntry> entries(uint16_t zone) const;\n  [[nodiscard]] std::vector<uint16_t> zones() const;\n  [[nodiscard]] std::vector<uint16_t> nets(uint16_t zone) const;\n  [[nodiscard]] std::vector<uint16_t> nodes(uint16_t zone, uint16_t net) const;\n  [[nodiscard]] const NodelistEntry* entry(uint16_t zone, uint16_t net, uint16_t node);\n  [[nodiscard]] bool has_zone(int zone) const noexcept;\n\n  static std::string FindLatestNodelist(const std::filesystem::path& dir, const std::string& base);\n\nprivate:\n  bool Load(const std::filesystem::path& path);\n  bool Load(const std::vector<std::string>& lines);\n\n  bool AddEntry(uint16_t zone, uint16_t net, NodelistEntry& e);\n  bool HandleLine(const std::string& line, uint16_t& zone, uint16_t& region, uint16_t& net, uint16_t& hub );\n  \n  std::map<FidoAddress, NodelistEntry> entries_;\n  std::string domain_;\n  bool initialized_{false};\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "sdk/fido/nodelist_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/fido/nodelist.h\"\n#include <type_traits>\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\n\nstatic const char raw[] = R\"(\n;\nZone,1,North_America,Slaterville_Springs_NY,Sysop_Name1,1-607-555-1212,9600,CM,XX,H16,V32b,V42b,V34,V32T,X2C,INA:filegate.net,IBN,IBN:24555,IFT,ITN\n,20,The_North_American_Backbone,Zone_1,Sysop_Name1_20,-Unpublished-,300,CM,MO,XX,INA:the-estar.com,IBN\n;\nRegion,10,Calif-Nevada,Aptos_CA,Sysop_Name10,-Unpublished-,300,CM,XX,INA:realitycheckbbs.org,IBN,IFC\n,1,Region_10_Echomail_Coordinator_Calif_Nevada,Aptos_CA,Sysop_Name10_1,-Unpublished-,300,CM,XX,INA:realitycheckbbs.org,IBN,IFC\n;\n;\nHost,109,National_Capital_Area_Net_109,Washington_DC,Frank_Reid,1-757-481-6611,9600,CM,XA,V32b,V42b,V34,IBN:bbsdoors.com\n,41,Internet_Email_Gateway,Wheaton_MD,Andrew_Miller,1-301-949-5764,9600,CM,XR,V32b,V42\n,42,Usenet_News_Gateway,Wheaton_MD,Andrew_Miller,1-301-949-5764,9600,CM,XR,V32b,V42\n,201,bbs.cyberchatnet.com,Vienna_VA,Phillip_Taylor,-Unpublished-,9600,CM,INA:bbs.cyberchatnet.com,IBN,IFC\n,202,bbs.cyberchatnet.com,Vienna_VA,Phillip_Taylor,1-703-310-7439,9600,XR,V32b,V42\nPvt,264,www.TheLitterBox.org,Bluemont_VA,Tony_Campbell,-Unpublished-,300,IP\n,432,The_Idea_Link,Wheaton_MD,Andrew_Miller,1-301-949-5764,9600,CM,XR,V32b,V42\nHub,500,Greater_PG_Co_Lcl_Hub,Laurel,Frank_Reid,1-757-481-6611,9600,CM,XA,V32b,V42b,V34\nPvt,560,The_Play_Pen,Upper_Marlboro_MD,Jeffrey_Estevez,-Unpublished-,300,IP\n,567,www.bbsdoors.com,Laurel_MD,Frank_Reid,-Unpublished-,300,CM,IBN:bbsdoors.com\n,568,Eagle's_Dare,Upper_Marlboro_MD,Frank_Reid,1-757-481-6611,9600,CM,XA,V32b,V42b,V34\n,909,Lincoln_Legacy,Leesburg_VA,John_Covici,1-703-777-8383,9600,CM,HST,V42B,V32B\n;\n;\nHost,102,SoCalNet,Aptos_CA,Sysop_Name102,-Unpublished-,300,CM,XX,INA:realitycheckbbs.org,IBN,IFC\n,501,iNK_tWO,Covina_CA,Sysop_Name102_501,-Unpublished-,300,CM,XA,INA:bbs.inktwo.com,IBN\nDown,943,Mysteria,Sierra_Madre_CA,Sysop_Name102_943,1-626-555-51212,9600,CM,XA,H16,V32b,V42b,V34,VFC,INA:mysteria.com,IBN\n;\nHost,123,South_Carogawgabama_Net,Spartanburg_SC,Sysop_Name123,-Unpublished-,300,CM,MO,INA:the-estar.com,IBN\n,5,Hard_Drive_Cafe,Montgomery_AL,Sysop_Name123_5,-Unpublished-,300,CM,INA:irex.hdcbbs.com,ibn\nPvt,789,The_Eastern_Star_Fidonet_Via_Newsreader,Spartanburg_SC,Sysop_Name123_789,-Unpublished-,300\n;\n;\nHost,261,Maryland_Central_Net,NC,Sysop_Name261,-Unpublished-,300,CM,XX,INA:bbs.weather-station.org,IBN:24555\n,1,Weather_Station_Hub,Bel_Air_MD,Sysop_Name261_1,-Unpublished-,300,CM,XX,INA:bbs.weather-station.org,IBN:24555\n,1300,Weather_Station_BBS_(Mystic),Bel_Air_MD,Sysop_Name261_1300,-Unpublished-,300,CM,XX,INA:bbs.weather-station.org,IBN:24557\n;\n;\n;\nZone,42,Mars,Slaterville_Springs_NY,Sysop_Name1,1-607-555-1212,9600,CM,XX,H16,V32b,V42b,V34,V32T,X2C,INA:filegate.net,IBN,IBN:24555,IFT,ITN\n,20,The_Martian_Backbone,Zone_1,Sysop_Name1_20,-Unpublished-,300,CM,MO,XX,INA:the-estar.com,IBN\n;\nRegion,21,Mars_Station,Station_1,Sysop_Name10,-Unpublished-,300,CM,XX,INA:elonsbbs.example.org,IBN,IFC\n,1,Region_10_Echomail_Coordinator_Mars_Station,Mars_Station,Sysop_Name10_1,-Unpublished-,300,CM,XX,INA:elonsbbs.example.org,IBN,IFC\n;\nHost,123,Elons_BBS,Mars_Station,Sysop_Name123,-Unpublished-,300,CM,MO,INA:elonsbbs.example.org,IBN\n;\n;\n)\";\n\nTEST(NodelistTest, Basic) {\n  const auto e = NodelistEntry::ParseDataLine(\n      \",1,system_name,location,sysop_name,phone_number,baud_rate,CM,INA:host:port\");\n  ASSERT_TRUE(e);\n  EXPECT_EQ(e->name(), \"system name\");\n}\n\nTEST(NodelistTest, Zone) {\n  const auto e = NodelistEntry::ParseDataLine(\n      \"Zone,1,system_name,location,sysop_name,phone_number,baud_rate,CM,INA:host:port\");\n  ASSERT_TRUE(e);\n  EXPECT_EQ(e->keyword(), NodelistKeyword::zone);\n}\n\nTEST(NodelistTest, Smoke) {\n  const auto lines = SplitString(raw, \"\\n\");\n  Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  const auto n1_261_1 = nl.entry(1, 261, 1);\n  ASSERT_TRUE(n1_261_1 != nullptr);\n  EXPECT_EQ(\"Weather Station Hub\", n1_261_1->name());\n  EXPECT_EQ(\"Sysop Name261 1\", n1_261_1->sysop_name());\n  EXPECT_EQ(\"Bel Air MD\", n1_261_1->location());\n  EXPECT_TRUE(n1_261_1->binkp());\n  EXPECT_EQ(\"bbs.weather-station.org\", n1_261_1->hostname());\n  EXPECT_EQ(\"bbs.weather-station.org\", n1_261_1->binkp_hostname());\n  EXPECT_EQ(24555u, n1_261_1->binkp_port());\n  EXPECT_FALSE(n1_261_1->vmodem());\n}\n\nTEST(NodelistTest, ZoneNet) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  auto n261 = nl.entries(1, 261);\n  EXPECT_EQ(FidoAddress(\"1:261/1\"), n261.front().address());\n}\n\nTEST(NodelistTest, Zones) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  const auto zones = nl.zones();\n  EXPECT_EQ(2u, zones.size());\n  EXPECT_THAT(zones, testing::ElementsAre(static_cast<uint16_t>(1), static_cast<uint16_t>(42)));\n}\n\nTEST(NodelistTest, Has_Zone) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  auto zones = nl.zones();\n  EXPECT_TRUE(nl.has_zone(1));\n  EXPECT_TRUE(nl.has_zone(42));\n  EXPECT_FALSE(nl.has_zone(8));\n}\n\n\nTEST(NodelistTest, Nets) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  const auto nets = nl.nets(1);\n  const std::vector<uint16_t>expected{10, 102 ,109, 123, 261};\n  EXPECT_EQ(expected, nets);\n}\n\nTEST(NodelistTest, Nodes_With_Hub_109) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  const auto nets = nl.nodes(1, 109);\n  // 500 is the hub entry in net 109\n  EXPECT_THAT(nets, testing::Contains(500));\n}\n\nTEST(NodelistTest, Nodes_261) {\n  const auto lines = SplitString(raw, \"\\n\");\n  const Nodelist nl(lines, \"\");\n  ASSERT_TRUE(nl);\n\n  const auto nets = nl.nodes(1, 261);\n  EXPECT_THAT(nets, testing::ElementsAre(1, 1300));\n}"
  },
  {
    "path": "sdk/fido/test/ftn_directories_test_helper.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FIDO_TEST_FTN_DIRECTORIES_TEST_HELPER_H\n#define INCLUDED_SDK_FIDO_TEST_FTN_DIRECTORIES_TEST_HELPER_H\n\n#include \"sdk/fido/fido_directories.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk::fido::test {\n\nstatic wwiv::sdk::net::Network CreateTestNetwork(const std::filesystem::path& dir) { \n  wwiv::sdk::net::Network n(wwiv::sdk::net::network_type_t::ftn, \"TestNET\", dir,\n                            FTN_FAKE_OUTBOUND_NODE);\n  n.fido.inbound_dir = \"in\";\n  n.fido.outbound_dir = \"out\";\n  n.fido.temp_inbound_dir = \"tempin\";\n  n.fido.temp_outbound_dir = \"tempout\";\n  n.fido.unknown_dir = \"unknown\";\n  n.fido.bad_packets_dir = \"bad\";\n  n.fido.netmail_dir = \"netmail\";\n  n.fido.fido_address = \"21:12/2112\";\n  return n;\n}\n\n/**\n * Helper class for tests requiring local filesystem access.\n *\n * Note: This class can not use File since it is used by the tests for File.\n */\nclass FtnDirectoriesTestHelper {\npublic:\n  FtnDirectoriesTestHelper(wwiv::core::test::FileHelper& h)\n      : net_(CreateTestNetwork(h.Dir(\"network\"))),\n        dirs_(h.TempDir(), net_) {}\n\n  const wwiv::sdk::fido::FtnDirectories& dirs() const { return dirs_; }\n  wwiv::sdk::net::Network& net() { return net_; }\n\nprivate:\n  wwiv::sdk::net::Network net_;\n  wwiv::sdk::fido::FtnDirectories dirs_;\n};\n\n} // namespace wwiv::sdk::fido::test\n\n#endif\n"
  },
  {
    "path": "sdk/fido/test/ftn_directories_test_helper_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/fido/test/ftn_directories_test_helper.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::test;\nusing namespace wwiv::sdk::fido::test;\n\nclass FtnDirectoriesTestHelperTest : public testing::Test {\npublic:\n  FtnDirectoriesTestHelperTest() : file_helper_(), helper_(file_helper_) {}\n\nprotected:\n  FileHelper file_helper_;\n  FtnDirectoriesTestHelper helper_;\n  std::filesystem::path net_dir_;\n};\n\nTEST_F(FtnDirectoriesTestHelperTest, Name) { ASSERT_EQ(\"TestNET\", helper_.net().name); }\n\nTEST_F(FtnDirectoriesTestHelperTest, Address) {\n  ASSERT_EQ(\"21:12/2112\", helper_.net().fido.fido_address);\n}\n\nTEST_F(FtnDirectoriesTestHelperTest, In) {\n  ASSERT_EQ(FilePath(file_helper_.TempDir(), \"network/in\"), helper_.dirs().inbound_dir());\n}\n\nTEST_F(FtnDirectoriesTestHelperTest, Out) {\n  ASSERT_EQ(FilePath(file_helper_.TempDir(), \"network/out\"), helper_.dirs().outbound_dir());\n}\n\nTEST_F(FtnDirectoriesTestHelperTest, NetDir) {\n  ASSERT_EQ(FilePath(file_helper_.TempDir(), \"network\"), helper_.dirs().net_dir());\n}\n"
  },
  {
    "path": "sdk/filenames.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_FILENAMES_H\n#define INCLUDED_FILENAMES_H\n\n#define ACCT_INI \"acct.ini\"\n#define ADDRESS_NET \"address.net\"\n#define ALLOW_NET \"allow.net\"\n#define ALLOW_DAT \"allow.dat\"\n#define ATTACH_DAT \"attach.dat\"\n#define ARCHIVER_DAT \"archiver.dat\"\n#define AUTO_MSG \"auto.msg\"\n#define ASV_NOEXT \"asv\"\n\n#define BBSDATA_NET \"bbsdata.net\"\n#define BBSDATA_IND \"bbsdata.ind\"\n#define BBSDATA_REG \"bbsdata.reg\"\n#define BBSDATA_ROU \"bbsdata.rou\"\n#define BBSLIST_NET \"bbslist.net\"\n\n#define BBSLIST_MSG \"bbslist.msg\"\n#define BBSLIST_TMP \"bbslist.tmp\"\n#define BBSLIST_UPD \"bbslist.upd\"\n#define BBSLIST_JSON \"bbslist.json\"\n#define BINKP_NET \"binkp.net\"\n\n#define CALLOUT_NET \"callout.net\"\n#define CATEG_NET \"categ.net\"\n#define CHAT_NOEXT \"chat\"\nconstexpr auto DISALLOW_NET = \"disallow.net\";\nconstexpr auto DROPFILE_CHAIN_TXT = \"chain.txt\";\nconstexpr auto CHAINS_DAT = \"chains.dat\";\nconstexpr auto CHAINS_REG = \"chains.reg\";\nconstexpr auto CHAINS_JSON = \"chains.json\";\n\n#define CHAINS_NOEXT \"chains\"\n\n#define CHAT_INI \"chat.ini\"\n#define CHECK_NET \"check.net\"\n\n#define CONFIG_DAT \"config.dat\"\n#define CONFIG_JSON \"config.json\"\n#define CONFIG_OVR \"config.ovr\"\n\n#define COMMENT_TXT \"comment.txt\"\n#define CONNECT_NET \"connect.net\"\n#define CONNECT_UPD \"connect.upd\"\n#define CONTACT_NET \"contact.net\"\n\n#define CS_EMAIL_NOEXT \"cs-email\"\n\n#define DEAD_NET \"dead.net\"\n#define DEFAULTS_NOEXT \"legacy_defaults\"\n#define DESC_SDI \"DESC.SDI\"\n#define DESCRIPT_ION \"descript.ion\"\n#define DIRS_DAT \"dirs.dat\"\n#define DIRS_CNF \"dirs.cnf\"\n#define DIRS_JSON \"dirs.json\"\n#define DISABLE_TAG \"disable.tag\"\n#define DOWNLOAD_NOEXT \"download\"\n\n#define EDITORS_DAT \"editors.dat\"\n#define EDITOR_INF \"editor.inf\"\n#define EDITOR_NOEXT \"editor\"\n#define EMAIL_DAT \"email.dat\"\n#define EMAIL_NOEXT \"email\"\n#define EPROGS_NET \"eprogs.net\"\n\n\n#define FEDIT_INF \"fedit.inf\"\n#define FEEDBACK_NOEXT \"feedback\"\n#define FIDO_CALLOUT_JSON \"fido_callout.json\"\n#define FILESDL_NOEXT \"filesdl\"\n#define FILESUL_NOEXT \"filesul\"\n#define FILE_ID_DIZ \"FILE_ID.DIZ\"\n#define FSED_NOEXT \"fsed\"\n\n#define FORMASV_MSG \"formasv.msg\"\n\n#define GENERAL_TAG \"general.tag\"\n#define GFILE_DAT \"gfile.dat\"\n#define GFILES_NOEXT \"gfiles\"\n#define GUEST_NOEXT \"guest\"\n\n#define INPUT_MSG \"input.msg\"\n#define INSTANCE_DAT \"instance.dat\"\n\n#define LANGUAGE_DAT \"language.dat\"\n#define LASTON_TXT \"laston.txt\"\n#define LISTPLUS_CFG \"listplus.cfg\"\n#define LISTPLUS_HLP \"listplus.hlp\"\n#define LOCAL_NET \"local.net\"\n#define LOCKAUTO_MSG \"lockauto.msg\"\n#define LOGOFF_MAT \"logoff.mat\"\n#define LOGOFF_NOEXT \"logoff\"\n#define LOGON_NOEXT \"logon\"\n#define LPCONFIG_NOEXT \"lpconfig\"\n#define LPFREQ_NOEXT \"lpfreq\"\n#define LPSEARCH_NOEXT \"lpsearch\"\n#define LPSYSOP_NOEXT \"lpsysop\"\n\n#define MBMAIN_NOEXT \"mbmain\"\n#define MBFSED_NOEXT \"mbfsed\"\n#define MBFSED_SYSOP_NOEXT \"mbfsed-sysop\"\n\n// QWK\n#define MESSAGES_DAT \"MESSAGES.DAT\"\n\n#define MENUWEL_NOEXT \"menuwel\"\n#define MEXTRACT_NOEXT \"mextract\"\n#define MMAIL_NOEXT \"mmail\"\n\n// FTN style message IDs\n#define MSGDUPE_DAT \"msgdupe.dat\"\n#define MSGID_DAT \"msgid.dat\"\n\n// Used by QBBS style editors.\n#define MSGINF \"msginf\"\n#define MSGTMP \"msgtmp\"\n\n#define MUSTREAD_NOEXT \"mustread\"\n\n#define NAMES_LST \"names.lst\"\n#define NET_LOG \"net.log\"\n#define NETWORKS_DAT \"networks.dat\"\n#define NETWORKS_JSON \"networks.json\"\n#define NEWUSER_NOEXT \"newuser\"\n#define NEWMAIL_MSG \"newmail.msg\"\n#define NEWSYSOP_MSG \"newsysop.msg\"\n#define NEXTERN_DAT \"nextern.dat\"\n#define NINTERN_DAT \"nintern.dat\"\n#define NOFBACK_NOEXT \"nofback\"\n\n#define OFFLINE_NOEXT \"offline\"\n\n#define PHONENUM_DAT \"phonenum.dat\"\n\n#define QUOTE_NOEXT \"quote\"\n#define QUOTES_TXT \"quotes.txt\"\n#define QWK_CFG \"qwk.cfg\"\n#define QWK_JSON \"qwk.json\"\n\n#define REGIONS_DAT \"regions.dat\"\n#define REGIONS_DIR \"regions\"\n#define REJECT_NOEXT \"reject\"\n#define RESULT_ED \"result.ed\"\n\n#define RS_EMAIL_NOEXT \"rs-email\"\n\n#define SCONFIG_HLP \"sconfig.hlp\"\n#define SMW_DAT \"smw.dat\"\n#define SMBMAIN_NOEXT \"smbmain\"\n#define SONLINE_NOEXT \"sonline\"\n#define SRESTRCT_NOEXT \"srestrct\"\n#define STATUS_DAT \"status.dat\"\n#define SUBS_CNF \"subs.cnf\"\n#define SUBS_DAT \"subs.dat\"\n#define SUBS_JSON \"subs.json\"\n#define SUBS_LST \"subs.lst\"\n#define SUBS_NOEXT \"subs\"\n#define SUBS_XTR \"subs.xtr\"\n#define SWFC_NOEXT \"swfc\"\n#define SYSTEM_NOEXT \"system\"\n\n#define SY_EMAIL_NOEXT \"sy-email\"\n\n#define TBATCH_NOEXT \"tbatch\"\n#define TITLE_FSED_NOEXT \"title-fsed\"\n#define TRASHCAN_TXT \"trashcan.txt\"\n#define TRY2UL_NOEXT \"try2ul\"\n#define TTAGGING_NOEXT \"ttagging\"\n#define UPLOAD_NOEXT \"upload\"\n\n#define USER_LOG \"user.log\"\n#define USER_LST \"user.lst\"\n#define USER_QSC \"user.qsc\"\n\n#define VOTING_DAT \"voting.dat\"\n#define VOTING_TXT \"voting.txt\"\n\n#define WELCOME_NOEXT \"welcome\"\n#define WELCOME_ANS \"welcome.ans\"\n#define WELCOME_MSG \"welcome.msg\"\n#define WFC_DAT \"wfc.dat\"\n#define WWIV_INI \"wwiv.ini\"\n\n#define ZIPCITY_DIR \"zip-city\"\n#define ZLOG_DAT \"zlog.dat\"\n#define ZUPLOAD_NOEXT \"zupload\"\n\n#define FILENAME_DAT_EXTENSION \".dat\"\n\n#endif  // INCLUDED_FILENAMES_H\n"
  },
  {
    "path": "sdk/files/allow.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/allow.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/files/file_record.h\"\n#include <algorithm>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\n// TODO(rushfan): Maybe move this to files_record.h and\n// get rid of the one in bbs/utility\nstatic std::string _stripfn(const std::string& file_name) {\n  const std::filesystem::path p(file_name);\n  if (!p.has_filename()) {\n    return {};\n  }\n  return wwiv::sdk::files::unalign(p.filename().string());\n}\n\nAllow::Allow(const wwiv::sdk::Config& config) : data_directory_(config.datadir()) {\n  loaded_ = Load();\n}\n\nstatic bool icompare_equals(const allow_entry_t& i, const allow_entry_t& j) {\n  return StringCompareIgnoreCase(i.a, j.a) == 0;\n}\n\nstatic bool icompare_lessthan(const allow_entry_t& i, const allow_entry_t& j) {\n  return StringCompareIgnoreCase(i.a, j.a) < 0;\n}\n\nallow_entry_t to_allow_entry(const std::string& fn) {\n  allow_entry_t e{};\n  to_char_array(e.a, _stripfn(fn));\n  return e;\n}\n\nbool operator==(const allow_entry_t& lhs, const allow_entry_t& rhs) { \n  return icompare_equals(lhs, rhs); \n}\n\n bool Allow::Add(const std::string& unaligned_filename) {\n   const auto fn = align(unaligned_filename);\n  if (fn.size() != 12) {\n    LOG(ERROR) << \"Can't add filename: '\" << fn << \"' to allow.dat, not 12 chars\";\n    return false;\n  }\n  allow_.emplace_back(to_allow_entry(fn));\n  std::sort(std::begin(allow_), std::end(allow_), icompare_lessthan);\n  return true;\n}\n\nbool Allow::Remove(const std::string& unaligned_filename) {\n  const auto e = to_allow_entry(align(unaligned_filename));\n  const auto it = std::find(std::begin(allow_), std::end(allow_), e);\n  if (it != std::end(allow_)) {\n    allow_.erase(it);\n    return true;\n  }\n  return false;\n}\n\nbool Allow::Load() {\n  DataFile<allow_entry_t> file(wwiv::core::FilePath(data_directory_, ALLOW_DAT));\n  if (!file) {\n    // Handle empty file for the 1st time.  This is fine.\n    return true;\n  }\n  allow_.clear();\n  return file.ReadVector(allow_);\n}\n\nbool Allow::Save() {\n  DataFile<allow_entry_t> file(wwiv::core::FilePath(data_directory_, ALLOW_DAT),\n                               File::modeReadWrite | File::modeBinary | File::modeTruncate | File::modeCreateFile);\n  if (!file) {\n    LOG(ERROR) << \"Error saving allow.dat\";\n    return false;\n  }\n\n  std::sort(std::begin(allow_), std::end(allow_), icompare_lessthan);\n  return file.WriteVector(allow_);\n}\n\nbool Allow::IsAllowed(const std::string& unaligned_filename) {\n  if (!loaded_) {\n    LOG(ERROR) << \"Allow::IsAllowed called when !loaded_\";\n    return false;\n  }\n  const auto e = to_allow_entry(align(unaligned_filename));\n  return !std::binary_search(std::begin(allow_), std::end(allow_), e, icompare_lessthan);\n}\n\nint Allow::size() const {\n  return wwiv::stl::size_int(allow_);\n}\n\nAllow::~Allow() {\n  if (!save_on_exit_) {\n    return;\n  }\n  try {\n    Save();\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught exception in Allow::~Allow: \" << e.what();\n  }\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/files/allow.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ALLOW_H\n#define INCLUDED_SDK_ALLOW_H\n\n#include <filesystem>\n#include <string>\n#include <vector>\n\n#include \"sdk/config.h\"\n\nnamespace wwiv::sdk::files {\n\n\nstruct allow_entry_t {\n  char a[13];\n};\n\n// Helpers for allow_entry_t.  Useful in tests.\nbool operator==(const allow_entry_t& lhs, const allow_entry_t& rhs);\nallow_entry_t to_allow_entry(const std::string& fn);\n\nclass Allow {\npublic:\n  explicit Allow(const wwiv::sdk::Config& config);\n  virtual ~Allow();\n\n  bool Add(const std::string& filename);\n  bool Remove(const std::string& filename);\n  bool Load();\n  bool Save();\n  bool IsAllowed(const std::string& filename);\n\n  [[nodiscard]] const std::vector<allow_entry_t>& allow_vector() const { return allow_; }\n  [[nodiscard]] int size() const;\n  void set_save_on_exit(bool save_on_exit) { save_on_exit_ = save_on_exit; }\n  [[nodiscard]] bool save_on_exit() const { return save_on_exit_;  }\n\nprivate:\n  const std::filesystem::path data_directory_;\n  bool loaded_{false};\n  bool save_on_exit_{false};\n  std::vector<allow_entry_t> allow_;\n};\n\n} // namespace \n\n#endif  // INCLUDED_SDK_ALLOW_H\n"
  },
  {
    "path": "sdk/files/allow_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/allow.h\"\n#include \"sdk/sdk_helper.h\"\n#include <string>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::strings;\n\nclass AllowTest : public testing::Test {\npublic:\n  AllowTest() {}\n\n  void SetUp() override { helper.SetUp(); }\n\n  SdkHelper helper;\n};\n\nTEST_F(AllowTest, Empty) {\n  const Allow a(helper.config());\n  const auto& v = a.allow_vector();\n  EXPECT_EQ(0, wwiv::stl::ssize(v));\n}\n\nTEST_F(AllowTest, Add) {\n  Allow a(helper.config());\n  a.Add(\"1.zip\");\n  a.Add(\"2.zip\");\n  a.Add(\"3.zip\");\n  const auto v = a.allow_vector();\n  ASSERT_EQ(3, wwiv::stl::ssize(v));\n  const auto f = to_allow_entry(\"1.zip\");\n  EXPECT_EQ(f, v.front());\n  const auto b = to_allow_entry(\"3.zip\");\n  EXPECT_EQ(b, v.back());\n}\n\nTEST_F(AllowTest, IsAllowed) {\n  Allow a(helper.config());\n  a.Load();\n  EXPECT_TRUE(a.IsAllowed(\"1.zip\"));\n  a.Add(\"1.zip\");\n  EXPECT_FALSE(a.IsAllowed(\"1.zip\"));\n}\n\nTEST_F(AllowTest, Remove) {\n  Allow a(helper.config());\n  a.Add(\"1.zip\");\n  a.Add(\"2.zip\");\n  a.Add(\"3.zip\");\n  EXPECT_FALSE(a.IsAllowed(\"2.zip\"));\n  a.Remove(\"2.zip\");\n  EXPECT_TRUE(a.IsAllowed(\"2.zip\"));\n}\n\nTEST_F(AllowTest, Load) {\n  const std::string contents(\"badworld.zip\\0foobar2u.arc\\0\", 26);\n  const auto path = helper.files().CreateTempFilePath(\"bbs/data/allow.dat\");\n  {\n    File f(path);\n    ASSERT_TRUE(\n        f.Open(File::modeBinary | File::modeCreateFile | File::modeTruncate | File::modeReadWrite));\n    f.Write(contents);\n  }\n  Allow a(helper.config());\n  ASSERT_TRUE(a.Load());\n  EXPECT_EQ(2, wwiv::stl::ssize(a.allow_vector()));\n  EXPECT_EQ(to_allow_entry(\"badworld.zip\"), a.allow_vector().front());\n  EXPECT_FALSE(a.IsAllowed(\"foobar2u.arc\"));\n  EXPECT_TRUE(a.IsAllowed(\"foobar2u.zip\"));\n}\n\nTEST_F(AllowTest, Save) {\n  const std::string contents(\"badworld.zip\\0foobar2u.arc\\0\", 26);\n  auto path = helper.files().CreateTempFilePath(\"bbs/data/allow.dat\");\n  {\n    File f(path);\n    ASSERT_TRUE(\n        f.Open(File::modeBinary | File::modeCreateFile | File::modeTruncate | File::modeReadWrite));\n    f.Write(contents);\n  }\n  // Load default allow.data\n  Allow a(helper.config());\n  ASSERT_TRUE(a.Load());\n  EXPECT_EQ(2, wwiv::stl::ssize(a.allow_vector()));\n  // Add a new one then save the reload it\n  a.Add(\"1.zip\");\n  ASSERT_TRUE(a.Save());\n  ASSERT_TRUE(a.Load());\n  // Now we are using the reloaded version.\n  EXPECT_EQ(3, wwiv::stl::ssize(a.allow_vector()));\n  EXPECT_FALSE(a.IsAllowed(\"1.zip\"));\n  EXPECT_TRUE(a.IsAllowed(\"2.zip\"));\n}\n"
  },
  {
    "path": "sdk/files/arc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/arc.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\n/* Convert DOS date and time to time_t. */\nstatic time_t dos2time_t(uint16_t dos_date, uint16_t dos_time) {\n  struct tm tm{};\n\n  tm.tm_sec = (dos_time & 0x1f) * 2;  /* Bits 0--4:  Secs divided by 2. */\n  tm.tm_min = (dos_time >> 5) & 0x3f; /* Bits 5--10: Minute. */\n  tm.tm_hour = (dos_time >> 11);      /* Bits 11-15: Hour (0--23). */\n\n  tm.tm_mday = (dos_date & 0x1f);          /* Bits 0--4: Day (1--31). */\n  tm.tm_mon = ((dos_date >> 5) & 0xf) - 1; /* Bits 5--8: Month (1--12). */\n  tm.tm_year = (dos_date >> 9) + 80;       /* Bits 9--15: Year-1980. */\n\n  tm.tm_isdst = -1;\n\n  return mktime(&tm);\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// ZIP FILE\n//\n// https://www.hanshq.net/zip.html\n\n\n// .ZIP structures and defines\nstatic constexpr uint32_t ZIP_LOCAL_SIG = 0x04034b50;\nstatic constexpr uint32_t ZIP_CENT_START_SIG = 0x02014b50;\nstatic constexpr uint32_t ZIP_CENT_END_SIG = 0x06054b50;\n\n#pragma pack(push, 1)\nstruct zip_local_header {\n  uint32_t signature; // 0x04034b50\n  uint16_t extract_ver;\n  uint16_t flags;\n  uint16_t comp_meth;\n  uint16_t mod_time;\n  uint16_t mod_date;\n  uint32_t crc_32;\n  uint32_t comp_size;\n  uint32_t uncomp_size;\n  uint16_t filename_len;\n  uint16_t extra_length;\n};\n\nstruct zip_central_dir {\n  uint32_t signature; // 0x02014b50\n  uint16_t made_ver;\n  uint16_t extract_ver;\n  uint16_t flags;\n  uint16_t comp_meth;\n  uint16_t mod_time;\n  uint16_t mod_date;\n  uint32_t crc_32;\n  uint32_t comp_size;\n  uint32_t uncomp_size;\n  uint16_t filename_len;\n  uint16_t extra_len;\n  uint16_t comment_len;\n  uint16_t disk_start;\n  uint16_t int_attr;\n  uint32_t ext_attr;\n  uint32_t rel_ofs_header;\n};\n\nstruct zip_end_dir {\n  uint32_t signature; // 0x06054b50\n  uint16_t disk_num;\n  uint16_t cent_dir_disk_num;\n  uint16_t total_entries_this_disk;\n  uint16_t total_entries_total;\n  uint32_t central_dir_size;\n  uint32_t ofs_cent_dir;\n  uint16_t comment_len;\n};\n#pragma pack(pop)\n\narchive_method_t zip_method(int z) {\n  if (z == 0) {\n    return archive_method_t::ZIP_STORED;\n  }\n  if (z == 8) {\n    return archive_method_t::ZIP_DEFLATED;\n  }\n  return archive_method_t::UNKNOWN;\n}\n\ntemplate <typename Z> archive_entry_t create_archive_entry(const Z& z, const char* fn) { \n  archive_entry_t a;\n  a.filename =  StringTrim(fn);\n  a.crc32 = z.crc_32;\n  a.dt = dos2time_t(z.mod_date, z.mod_time);\n  a.compress_size = z.comp_size;\n  a.uncompress_size = z.uncomp_size;\n  a.method = zip_method(z.comp_meth);\n  return a;\n}\n\nstatic std::optional<std::vector<archive_entry_t>>\nlist_archive_zip(const std::filesystem::path& path) {\n  std::vector<archive_entry_t> files;\n\n  File file(path);\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    return std::nullopt;\n  }\n  long l = 0;\n  const auto len = file.length();\n  bool done = false;\n  while (l < len && !done) {\n    long sig = 0;\n    file.Seek(l, File::Whence::begin);\n    file.Read(&sig, 4);\n    file.Seek(l, File::Whence::begin);\n    switch (sig) {\n    case ZIP_LOCAL_SIG: {\n      zip_local_header zl{};\n      char s[1024];\n      file.Read(&zl, sizeof(zl));\n      file.Read(s, zl.filename_len);\n      s[zl.filename_len] = '\\0';\n      // Since zip_central_dir and zip_local_header both have the same\n      // information, don't add it here.\n      // files.emplace_back(create_archive_entry(zl, s));\n      // VLOG(1) << \"ZIP_LOCAL_SIG: \" << s;\n      l += static_cast<long>(sizeof(zl)) + zl.comp_size + zl.filename_len + zl.extra_length;\n    } break;\n    case ZIP_CENT_START_SIG: {\n      zip_central_dir zc{};\n      char s[1024];\n      file.Read(&zc, sizeof(zc));\n      file.Read(s, zc.filename_len);\n      s[zc.filename_len] = '\\0';\n      VLOG(1) << \"ZIP_CENT_START_SIG: \" << s;\n      files.emplace_back(create_archive_entry(zc, s));\n      l += sizeof(zc);\n      l += zc.filename_len + zc.extra_len;\n    } break;\n    case ZIP_CENT_END_SIG:\n      [[fallthrough]];\n    default: \n      done = true;\n      break;\n    }\n  }\n  file.Close();\n  return {files};\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// ARC FILE\n// http://fileformats.archiveteam.org/wiki/ARC_(compression_format)\n\n#pragma pack(push, 1)\nstruct arch {\n  uint8_t type;\n  char name[13];\n  int32_t len;\n  int16_t date, time, crc;\n  int32_t size;\n};\n#pragma pack(pop)\n\nstatic std::optional<std::vector<archive_entry_t>> list_archive_arc(const std::filesystem::path& path) {\n  File file(path);\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    return std::nullopt;\n  }\n  arch a{};\n  const auto file_size = file.length();\n  long pos = 1;\n  file.Seek(0, File::Whence::begin);\n  file.Read(&a, 1);\n  if (a.type != 0x1a) {\n    return std::nullopt;\n  }\n\n  std::vector<archive_entry_t> files;\n  while (pos < file_size) {\n    file.Seek(pos, File::Whence::begin);\n    const auto num_read = file.Read(&a, sizeof(arch));\n    if (num_read != sizeof(arch)) {\n      // early EOF\n      return files;\n    }\n    pos += sizeof(arch);\n    if (a.type == 1) {\n      pos -= 4;\n      a.size = a.len;\n    }\n    if (!a.type) {\n      return files;\n    }\n    pos += a.len;\n    ++pos;\n    archive_entry_t ae{};\n    const auto arc_fn = trim_to_size(a.name, 13);\n    ae.filename = arc_fn;\n    ae.crc32 = a.crc;\n    ae.compress_size = a.len;\n    ae.uncompress_size = a.size;\n    ae.dt = dos2time_t(a.date, a.time);\n    files.emplace_back(ae);\n  }\n  return files;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// LZH FILE\n// http://www33146ue.sakura.ne.jp/staff/iz/formats/lzh.html\n// http://web.archive.org/web/20021219165813/http://www.osirusoft.com/joejared/lzhformat.html\n//\n#pragma pack(push, 1)\n\n// This doesn't include the size bit at the front\n// or   uint8_t fn_len at the end of level 0 and 1\n \nstruct lharc_header {\n  uint8_t checksum;\n  char ctype[5];\n  int32_t comp_size;\n  int32_t uncomp_size;\n  uint16_t time;\n  uint16_t date;\n  uint8_t attr;\n  uint8_t level;\n};\n#pragma pack(pop)\n\nstatic std::optional<std::vector<archive_entry_t>> list_archive_lzh(const std::filesystem::path& path) {\n\n  const auto fn = path.filename().string();\n  File file(path);\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    return std::nullopt;\n  }\n  std::vector<archive_entry_t> files;\n  const auto file_size = file.length();\n\n  for (long l = 0; l < file_size; ) {\n    lharc_header a{};\n    file.Seek(l, File::Whence::begin);\n    char flag;\n    file.Read(&flag, 1);\n    if (!flag) {\n      break;\n    }\n    const auto num_read = file.Read(&a, sizeof(lharc_header));\n    if (num_read != sizeof(lharc_header)) {\n      // Early EOF\n      return {files};\n    }\n\n    archive_entry_t ae{};\n    if (a.level == 0 || a.level == 1) {\n      /*\n       * 21      1 byte   Filename / path length in bytes (f)\n       * 22     (f)bytes  Filename / path\n       * 22+(f)  2 bytes  CRC-16 of original file\n       * [[ LEVEL 0 ]]\n       * 24+(f) (n)bytes  Compressed data\n       * [[ LEVEL 1 ]]\n       * 24+(f)  1 byte   OS ID\n       * 25+(f)  2 bytes  Next header size(x) (0 means no extension header)\n       * [ // Extension headers\n       *         1 byte   Extension type\n       *     (x)-3 bytes  Extension fields\n       *         2 bytes  Next header size(x) (0 means no next extension header)\n       * ]*\n       *        (n)bytes  Compressed data\n       */\n\n      uint8_t fn_len;\n      if (1 != file.Read(&fn_len, 1)) {\n        LOG(ERROR) << \"Error reading fn_len\" << \" on file: \" << path;\n        return {files};\n      }\n\n      char buffer[256];\n      if (fn_len != file.Read(buffer, fn_len)) {\n        // Early EOF\n        return {files};\n      }\n      buffer[fn_len] = '\\0';\n      ae.filename = buffer;\n\n      uint16_t crc;\n      file.Read(&crc, sizeof(crc));\n      l += static_cast<int>(sizeof(lharc_header) + fn_len + sizeof(fn_len) + sizeof(crc) + sizeof(flag)) + a.comp_size;\n      if (a.level == 1) {\n        // Read extra headers and OS ID\n        uint8_t os_id;\n        if (1 != file.Read(&os_id, 1)) {\n          LOG(ERROR) << \"Error reading os_id\" << \" on file: \" << path;\n          return {files};\n        }\n        uint16_t ext_size = 0;\n        if (2 != file.Read(&ext_size, 2)) {\n          LOG(ERROR) << \"Error reading os_id\"<< \" on file: \" << path;\n          return {files};\n        }\n        l += sizeof(uint8_t) + sizeof(uint16_t); // os_id and ext_size\n\n        do {\n          if (ext_size < 3) {\n            LOG(ERROR) << \"Invalid ext_size on\" << \" on file: \" << path;\n            return {files};\n          }\n          char ext[1024];\n          if (ext_size > 1024) {\n            LOG(ERROR) << \"Huge ext_size on file: \" << path;\n            return {files};\n          }\n          if (ext_size != file.Read(&ext, ext_size)) {\n            LOG(ERROR) << \"Invalid ext on\" << \" on file: \" << path;\n            return {files};\n          }\n\n          uint8_t ext_type = ext[0];\n          VLOG(1) << \"ext_type: \" << ext_type;\n          ext_size = ext[ext_size - 1] << 8 | ext[ext_size - 2];\n        } while (ext_size != 0);\n      }\n    } else {\n      LOG(ERROR) << \"Unknown LZH level: \" << a.level << \" on file: \" << path;\n      return {files};\n    }\n    ae.dt = dos2time_t(a.date, a.time);\n    ae.compress_size = a.comp_size;\n    ae.uncompress_size = a.uncomp_size;\n    ae.crc32 = a.checksum;\n    files.emplace_back(ae);\n  }\n  return {files};\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// ARJ FILE\n// http://manual.freeshell.org/unarj/technote.txt\n//\n\n#pragma pack(push, 1)\n\nstruct arj_header_t {\n  uint16_t header_id; // 0x60ea\n  // basic header size (from 'first_hdr_size' thru 'comment' below)\n  // = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1 =\n  //      0 if end of archive maximum header size is 2600\n  uint16_t basic_header_size;\n  // (size up to and including 'extra data')\n  uint8_t first_hdr_size;\n  // archiver version number\n  uint8_t archiver_version;\n  // minimum archiver version to extract\n  uint8_t min_archiver_version;\n  //(0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MAC - OS)\n  // (5 = OS / 2, 6 = APPLE GS, 7 = ATARI ST,\n  // 8 = NEXT)(9 = VAX VMS)\n  uint8_t host_os;\n  // (0x01 = GARBLED_FLAG) indicates password protected file\n  // (0x02 = NOT USED)\n  // (0x04 = VOLUME_FLAG)  indicates continued file to next volume (file is split)\n  // (0x08 = EXTFILE_FLAG) indicates file starting position field (for split files)\n  // (0x10 = PATHSYM_FLAG) indicates filename translated (\"\\\" changed to \"/\")\n  // (0x20 = BACKUP_FLAG)  indicates file marked as backup\n  uint8_t flags;\n\n  //(0 = stored, 1 = compressed most ... 4 compressed fastest)\n  uint8_t method;\n\n  // (0 = binary,    1 = 7-bit text) (3 = directory, 4 = volume label)\n  uint8_t file_type;\n  uint8_t reserved;\n  // date time modified\n  uint16_t time;\n  uint16_t date;\n  uint32_t compressed_size;\n  uint32_t original_size;\n  // original file's CRC\n  uint32_t crc32;\n  // filespec position in filename \n  uint16_t filespec_pos;\n  // file access mode\n  uint16_t fileaccess_mode;\n  // host data (currently not used)\n  uint16_t host_data;\n};\n\n#pragma pack(pop)\n\nstatic std::optional<std::vector<archive_entry_t>> list_archive_arj(const std::filesystem::path& path) {\n\n  const auto fn = path.filename().string();\n  File file(path);\n  if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n    return std::nullopt;\n  }\n  std::vector<archive_entry_t> files;\n  const auto file_size = file.length();\n  long pos = 0;\n  file.Seek(0L, File::Whence::begin);\n  bool file_header = true;\n  while (pos < file_size) {\n    arj_header_t h{};\n    file.Seek(pos, File::Whence::begin);\n    uint16_t magic;\n    if (2 != file.Read(&magic, 2) || magic != 0xea60) {\n      // LOG(error) << \"EOF: \" << std::hex << magic;\n      return {files};\n    }\n    file.Seek(pos, File::Whence::begin);\n    file.Read(&h, sizeof(h));\n    if (h.basic_header_size == 0) {\n      // End of Archive\n      return {files};\n    }\n    int header_sizeof = sizeof(arj_header_t) - 4;\n    int ext_data_size = h.first_hdr_size - header_sizeof;\n    char ext_data[200];\n    if (ext_data_size > 0) {\n      // Have extra header;\n      file.Read(ext_data, ext_data_size);\n    }\n    auto file_and_comment_size = h.basic_header_size - h.first_hdr_size;\n    auto buffer = std::make_unique<char[]>(file_and_comment_size);\n    file.Read(buffer.get(), file_and_comment_size);\n    std::string filename = buffer.get();\n    // 4 for first two fields, 4 for header CRC, and 2 for ext header.\n    // We can skip the ext header since arj never used it.\n    pos += h.basic_header_size + 4 + 4 + 2;\n    if (!file_header) {\n      pos += static_cast<long>(h.compressed_size);\n      archive_entry_t ae{};\n      ae.filename = filename;\n      ae.compress_size = h.compressed_size;\n      ae.uncompress_size = h.original_size;\n      ae.crc32 = h.crc32;\n      ae.dt = dos2time_t(h.date, h.time);\n      files.emplace_back(ae);\n    }\n    file_header = false;\n    if (h.flags & 0x08) {\n      pos += 4;\n    }\n  }\n  return {files};\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n// Generic Archive\n//\n\nstd::optional<std::vector<archive_entry_t>> list_archive(const std::filesystem::path& path) {\n  struct arc_command {\n    const std::string arc_name;\n    std::function<std::optional<std::vector<archive_entry_t>>(const std::filesystem::path&)> func;\n  };\n\n  const std::vector<arc_command> arc_t = {\n    {\"ZIP\", list_archive_zip}, \n    {\"ARC\", list_archive_arc},\n    {\"LZH\", list_archive_lzh},\n    {\"ARJ\", list_archive_arj},\n  };\n\n  if (!path.has_extension()) {\n    // no extension?\n    return std::nullopt;\n  }\n  auto ext = ToStringUpperCase(path.extension().string());\n  if (ext.front() == '.') {\n    // trim leading . for extension\n    ext = ext.substr(1);\n  }\n  for (const auto& t : arc_t) {\n    if (iequals(ext, t.arc_name)) {\n      return t.func(path);\n    }\n  }\n  return std::nullopt;\n}\n\n// One thing to note, if an 'arc' is found, it uses pak, and returns that\n// The reason being, PAK does all ARC does, plus a little more, I believe\n// PAK has its own special modes, but still look like an ARC, thus, an ARC\n// Will puke if it sees this\nstd::optional<std::string> determine_arc_extension(const std::filesystem::path& filename) {\n  File f(filename);\n  if (!f.Open(File::modeReadOnly | File::modeBinary)) {\n    return std::nullopt;\n  }\n\n  char header[10];\n  const auto num_read = f.Read(&header, 10);\n  if (num_read < 10) {\n    return std::nullopt;\n  }\n\n  switch (header[0]) {\n  case 0x60:\n    if (static_cast<unsigned char>(header[1]) == static_cast<unsigned char>(0xEA))\n      return {\"ARJ\"};\n    break;\n  case 0x1a:\n    return {\"ARC\"};\n  case 'P':\n    if (header[1] == 'K')\n      return {\"ZIP\"};\n    break;\n  case 'R':\n    if (header[1] == 'a')\n      return {\"RAR\"};\n    break;\n  case 'Z':\n    if (header[1] == 'O' && header[2] == 'O')\n      return {\"ZOO\"};\n    break;\n  }\n  if (header[0] == 'P') {\n    return std::nullopt;\n  }\n  header[9] = 0;\n  if (strstr(header, \"-lh\")) {\n    return {\"LZH\"};\n  }\n  return std::nullopt;\n}\n\nstd::vector<arcrec> read_arcs(const std::filesystem::path& datadir) {\n  std::vector<arcrec> arcs;\n  if (auto file = DataFile<arcrec>(FilePath(datadir, ARCHIVER_DAT))) {\n    file.ReadVector(arcs, 20);\n  }\n  return arcs;\n}\n\n/** returns the arcrec for the extension, or the 1st one if none match */\nstatic std::optional<arcrec> find_arc_by_extension(const std::vector<arcrec> arcs, const std::string& extension) {\n  const auto ue = ToStringUpperCase(extension);\n  for (const auto& a : arcs) {\n    if (ue == a.extension) {\n      return {a};\n    }\n  }\n  return std::nullopt;\n}\n\nstd::optional<arcrec> find_arcrec(const std::vector<arcrec>& arcs,\n                                  const std::filesystem::path& path) {\n  if (const auto ext = determine_arc_extension(path)) {\n    return find_arc_by_extension(arcs, ext.value());\n  }\n  return std::nullopt;\n}\n\nstd::optional<arcrec> find_arcrec(const std::vector<arcrec> arcs, const std::filesystem::path& path,\n                                  const std::string& default_ext) {\n  if (const auto ext = determine_arc_extension(path)) {\n    return find_arc_by_extension(arcs, ext.value());\n  }\n  return find_arc_by_extension(arcs, ToStringUpperCase(default_ext));\n}\n\n} // namespace wwiv::sdk::files"
  },
  {
    "path": "sdk/files/arc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FILES_ARC_H\n#define INCLUDED_SDK_FILES_ARC_H\n\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nstruct arcrec;\n\nnamespace wwiv::sdk::files {\n\n// https://www.hanshq.net/zip.html\n\nenum class archive_method_t {\n  UNKNOWN = -1,\n  ZIP_STORED = 0,\n  ZIP_DEFLATED = 1 // 8\n};\n\nstruct archive_entry_t {\n  std::string filename;\n  time_t dt;\n  archive_method_t method;\n  int32_t compress_size;\n  int32_t uncompress_size;\n  uint32_t crc32;\n};\n\n/**\n * Reads data/archiver.dat and populates a vector of arcrec from it.\n */\nstd::vector<arcrec> read_arcs(const std::filesystem::path& datadir);\n\n/**\n * Returns an optional vector of archive_entry_t containing the files of archive\n * file identified by path.\n */\nstd::optional<std::vector<archive_entry_t>> list_archive(const std::filesystem::path& path);\n\n/**\n * Returns the arc extension for the file identified by filename or std::nullopt of none\n * could be determined.  The contents of the file are checked first and if there is no\n * match then the filename's extension is consulted.\n *\n * This method is ideal when you do not know the archive type, like with QWK packets and\n * also FTN network bundles.\n */\nstd::optional<std::string> determine_arc_extension(const std::filesystem::path& filename);\n\n/**\n * Returns the arcrec for the archive type identified by filename or std::nullopt of none\n * could be determined.  The contents of the file are checked first and if there is no\n * match then the filename's extension is consulted.\n *\n * This method is ideal when you do not know the archive type, like with QWK packets and\n * also FTN network bundles.\n */\nstd::optional<arcrec> find_arcrec(const std::vector<arcrec>& arcs,\n                                  const std::filesystem::path& path);\n\n/**\n * Returns the arcrec for the archive type identified by filename or std::nullopt of none\n * could be determined.  The contents of the file are checked first and if there is no\n * match then the filename's extension is consulted.\n *\n * Finally if there is no match, use default_ext as the file extension to use when locating\n * the archiver record for this file.\n *\n * This method is ideal when you do not know the archive type, like with QWK packets and\n * also FTN network bundles.\n */\nstd::optional<arcrec> find_arcrec(const std::vector<arcrec> arcs, const std::filesystem::path& path,\n                                  const std::string& default_ext);\n\n} // namespace wwiv::sdk::files\n\n#endif"
  },
  {
    "path": "sdk/files/dirs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/files/dirs.h\"\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/archives/json.hpp>\n#include <cereal/types/memory.hpp>\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"core/cereal_utils.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/acs/expr.h\"\n#include \"sdk/files/dirs_cereal.h\"\n#include <string>\n#include <utility>\n#include <vector>\n\nusing cereal::make_nvp;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\nstd::ostream& operator<<(std::ostream& os, const sdk::files::directory_t& d) {\n  os << d.name << \" (\" << d.filename << \")\";\n  return os;\n}\n\nbool Dirs::LoadFromJSON(const std::filesystem::path& dir, const std::string& filename, std::vector<directory_t>& entries) {\n  entries.clear();\n  JsonFile f(FilePath(dir, filename), \"dirs\", entries, 1);\n  return f.Load();\n}\n\n//static \nbool Dirs::SaveToJSON(const std::filesystem::path& dir, const std::string& filename, const std::vector<directory_t>& entries) {\n  JsonFile f(FilePath(dir, filename), \"dirs\", entries, 1);\n  return f.Save();\n}\n\nbool Dirs::set_dirs(const std::vector<directory_t>& dirs) {\n  dirs_ = dirs;\n  return true;\n}\n\nstd::vector<directoryrec_422_t> read_dirs(const std::filesystem::path& datadir) {\n  DataFile<directoryrec_422_t> file(FilePath(datadir, DIRS_DAT));\n  if (!file) {\n    // LOG(ERROR) << file.file() << \" NOT FOUND.\";\n    return{};\n  }\n  std::vector<directoryrec_422_t> dirs;\n  if (!file.ReadVector(dirs)) {\n    return{};\n  }\n  return dirs;\n}\n\nbool write_dirs(const std::filesystem::path& datadir, const std::vector<directoryrec_422_t>& dirs) {\n  DataFile<directoryrec_422_t> file(FilePath(datadir, DIRS_DAT),\n                                        File::modeBinary | File::modeReadWrite |\n                                            File::modeCreateFile | File::modeTruncate,\n                                        File::shareDenyReadWrite);\n  if (!file) {\n    return false;\n  }\n  return file.WriteVector(dirs);\n}\n\n\n// Classes\n\nDirs::Dirs(std::filesystem::path datadir, int max_backups) : datadir_(std::move(datadir)), max_backups_(max_backups) {};\n\nDirs::~Dirs() = default;\n\nbool Dirs::Load() {\n  if (!LoadFromJSON(datadir_.string(), DIRS_JSON, dirs_)) {\n    return LoadLegacy();\n  }\n  return true;\n}\n\nbool Dirs::LoadLegacy() {\n  LOG(INFO) << \"Reading Legacy Dirs\";\n  auto old_dirs = read_dirs(datadir_);\n\n  dirs_.clear();\n  for (auto i = 0; i < wwiv::stl::ssize(old_dirs); i++) {\n    const auto& olds = stl::at(old_dirs, i);\n    directory_t dir{};\n    dir.name = olds.name;\n    dir.filename = olds.filename;\n    dir.path = olds.path;\n    acs::AcsExpr ae;\n    dir.acs = ae.min_dsl(olds.dsl).min_age(olds.age).dar_int(olds.dar).get();\n    dir.maxfiles = olds.maxfiles;\n    dir.mask = olds.mask;\n    dirs_.emplace_back(std::move(dir));\n  }\n  return true;\n}\n\nbool Dirs::Save() {\n  std::vector<directoryrec_422_t> dirs;\n\n  for (const auto& s : dirs_) {\n    directoryrec_422_t ls{};\n    to_char_array(ls.name, s.name);\n    to_char_array(ls.filename, s.filename);\n    to_char_array(ls.path, s.path);\n    //ls.dsl = s.dsl;\n    //ls.age = s.age;\n    //ls.dar = s.dar;\n    ls.maxfiles = s.maxfiles;\n    ls.mask = s.mask;\n    dirs.emplace_back(ls);\n  }\n\n  if (!write_dirs(datadir_, dirs)) {\n    LOG(ERROR) << \"Error saving dirs\";\n    return false;\n  }\n  // Backup dirs.json\n  backup_file(FilePath(datadir_, DIRS_JSON), max_backups_);\n\n  // Save dirs.\n  return SaveToJSON(datadir_, DIRS_JSON, dirs_);\n}\n\nbool Dirs::insert(int n, directory_t r) {\n  return insert_at(dirs_, n, r);\n}\n\nbool Dirs::erase(int n) {\n  return erase_at(dirs_, n);\n}\n\nconst directory_t& Dirs::dir(const std::string& filename) const {\n  for (const auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find dir of filename: \", filename));\n}\n\ndirectory_t& Dirs::dir(const std::string& filename) {\n  for (auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find dir of filename: \", filename));\n}\n\nbool Dirs::exists(const std::string& filename) const {\n  for (const auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n}\n"
  },
  {
    "path": "sdk/files/dirs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_FILES_DIRS_H\n#define INCLUDED_SDK_FILES_DIRS_H\n\n#include \"core/stl.h\"\n#include \"core/uuid.h\"\n#include \"sdk/conf/conf_set.h\"\n#include <filesystem>\n#include <set>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk::files {\n\nstruct dir_area_t {\n  std::string area_tag;\n  core::uuid_t net_uuid;  \n};\n\n// 5.5 style directory. \nstruct directory_55_t {\n  // directory name\n  std::string name;\n  // direct database filename\n  std::string filename;\n  // filename path\n  std::string path;\n  // DSL for directory\n  uint8_t dsl;\n  // minimum age for directory\n  uint8_t age;\n  // DAR for directory\n  uint16_t dar;\n  // max files for directory\n  uint16_t maxfiles;\n  // file type mask\n  uint16_t mask;\n  // AREA TAGs (used for FTN File Echos)\n  std::vector<dir_area_t> area_tags;\n};\n\n// 5.6+ style directory. \nstruct directory_t {\n  // directory name\n  std::string name;\n  // direct database filename\n  std::string filename;\n  // directory path\n  std::string path;\n  // ACS for accessing this area.\n  std::string acs;\n  // max files for directory\n  uint16_t maxfiles{500};\n  // file type mask\n  uint16_t mask{};\n  // AREA TAGs (used for FTN File Echos)\n  std::vector<dir_area_t> area_tags;\n  // Conference keys.\n  conf_set_t conf;\n\n  friend std::ostream& operator<<(std::ostream& os, const directory_t& f);\n};\n\nclass Dirs final {\npublic:\n  typedef directory_t& reference;\n  typedef const directory_t& const_reference;\n  explicit Dirs(std::filesystem::path datadir, int max_backups);\n  ~Dirs();\n\n  bool LoadLegacy();\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] const directory_t& dir(std::size_t n) const { return stl::at(dirs_, n); }\n  [[nodiscard]] const directory_t& dir(const std::string& filename) const;\n  directory_t& dir(std::size_t n) { return dirs_[n]; }\n  directory_t& dir(const std::string& filename);\n\n  const directory_t& operator[](std::size_t n) const { return dir(n); }\n  const directory_t& operator[](const std::string& filename) const { return dir(filename); }\n  directory_t& operator[](std::size_t n) { return dir(n); }\n  directory_t& operator[](const std::string& filename) { return dir(filename); }\n\n  [[nodiscard]] bool exists(const std::string& filename) const;\n\n  void set_dir(int n, directory_t s) { dirs_[n] = std::move(s); }\n  [[nodiscard]] const std::vector<directory_t>& dirs() const { return dirs_; }\n  bool insert(int n, directory_t r);\n  bool erase(int n);\n  [[nodiscard]] int size() const { return stl::size_int(dirs_); }\n  [[nodiscard]] bool empty() const { return dirs_.empty(); }\n\n  static bool LoadFromJSON(const std::filesystem::path& dir, const std::string& filename, std::vector<directory_t>& entries);\n  static bool SaveToJSON(const std::filesystem::path& dir, const std::string& filename, const std::vector<directory_t>& entries);\n\n  bool set_dirs(const std::vector<directory_t>& dirs);\n\nprivate:\n  const std::filesystem::path datadir_;\n  const int max_backups_;\n  std::vector<directory_t> dirs_;\n};\n\n}\n\n\n#endif\n\n"
  },
  {
    "path": "sdk/files/dirs_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_FILES_DIRS_CEREAL_H\n#define INCLUDED_SDK_FILES_DIRS_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/uuid_cereal.h\"\n#include \"sdk/files/dirs.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/conf/conf_set_cereal.h\"\n\nnamespace wwiv::sdk::files {\n\n\ntemplate <class Archive>\nvoid serialize (Archive& ar, dir_area_t& d) {\n  SERIALIZE(d, area_tag);\n  SERIALIZE(d, net_uuid);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, directory_55_t& s) {\n  SERIALIZE(s, name);\n  SERIALIZE(s, filename);\n  SERIALIZE(s, path);\n  SERIALIZE(s, dsl);\n  SERIALIZE(s, age);\n  SERIALIZE(s, dar);\n  SERIALIZE(s, maxfiles);\n  SERIALIZE(s, mask);\n  SERIALIZE(s, area_tags);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, directory_t& s) {\n  SERIALIZE(s, name);\n  SERIALIZE(s, filename);\n  SERIALIZE(s, path);\n  SERIALIZE(s, acs);\n  SERIALIZE(s, maxfiles);\n  SERIALIZE(s, mask);\n  SERIALIZE(s, area_tags);\n  SERIALIZE(s, conf);\n}\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/files/dirs_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/sdk_helper.h\"\n#include <string>\n#include <vector>\n#include \"cereal/external/rapidjson/document.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass DirsTest: public testing::Test {\nprotected:\n  void SetUp() override { \n    helper.SetUp(); \n  }\n  SdkHelper helper;\n};\n\nTEST_F(DirsTest, Smoke) {\n  directoryrec_422_t ld{};\n  to_char_array(ld.name, \"Sysop Dir\");\n  to_char_array(ld.filename, \"SYSOP\");\n  to_char_array(ld.path, \"/wwiv/dloads/sysop/\");\n  ld.dsl = 240;\n\n  std::vector<directoryrec_422_t> v;\n  v.emplace_back(ld);\n  const auto datadir = helper.files_.TempDir();\n  {\n    DataFile<directoryrec_422_t> f(FilePath(datadir, DIRS_DAT),\n                                   File::modeReadWrite | File::modeCreateFile | File::modeBinary |\n                                       File::modeTruncate);\n    ASSERT_TRUE(f.WriteVectorAndTruncate(v));\n  }\n  files::Dirs dirs(datadir, 0);\n  ASSERT_TRUE(dirs.LoadLegacy());\n\n  EXPECT_EQ(dirs.size(), 1);\n  EXPECT_TRUE(dirs.Save());\n  EXPECT_TRUE(File::Exists(FilePath(datadir, DIRS_JSON)));\n\n  std::vector<files::directory_t> new_dirs;\n  {\n    TextFile f(FilePath(datadir, DIRS_JSON), \"rt\");\n    ASSERT_TRUE(f.IsOpen());\n    auto s = f.ReadFileIntoVector();\n    EXPECT_EQ(\"{\", s.at(0));\n    EXPECT_EQ(\"    \\\"version\\\": 1,\", s.at(1));\n    EXPECT_EQ(\"    \\\"dirs\\\": [\", s.at(2));\n    EXPECT_NE(s.at(4).find(\"Sysop Dir\"), std::string::npos);\n  }\n  {\n    TextFile f(FilePath(datadir, DIRS_JSON), \"rt\");\n    ASSERT_TRUE(f.IsOpen());\n    auto s = f.ReadFileIntoString();\n    rapidjson::Document d;\n    d.Parse(s.c_str());\n    ASSERT_FALSE(d.HasParseError());\n    auto dirlist = d[\"dirs\"].GetArray();\n    EXPECT_EQ(1u, dirlist.Size());\n    const auto& d1 = dirlist[0];\n    EXPECT_STREQ(d1[\"name\"].GetString(), \"Sysop Dir\");\n    EXPECT_STREQ(d1[\"filename\"].GetString(), \"SYSOP\");\n  }\n\n}"
  },
  {
    "path": "sdk/files/diz.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/diz.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include <utility>\n\nstatic const char* invalid_chars = \"ڿĳôɻȼͺ̹ոԾͳƵַӽĺǶװ\";\n\nwwiv::sdk::files::Diz::Diz(std::string description, std::string extended_description)\n    : description_(std::move(description)), extended_description_(std::move(extended_description)) {}\n\nstd::string wwiv::sdk::files::Diz::description() const noexcept { return description_; }\n\nstd::string wwiv::sdk::files::Diz::extended_description() const noexcept {\n  return extended_description_;\n}\n\nwwiv::sdk::files::DizParser::DizParser(bool firstline_as_desc)\n    : firstline_as_desc_(firstline_as_desc) {}\n\n\nstatic bool valid_desc(const std::string& description) {\n  // I don't think this function is really doing what it should\n  // be doing, but am not sure what it should be doing instead.\n  for (const auto& c : description) {\n    if (c > '@' && c < '{') {\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic std::string fixup_diz_string(const std::string& orig) {\n  auto s{orig};\n  std::replace(s.begin(), s.end(), '\\x0c', ' ');\n  std::replace(s.begin(), s.end(), '\\x1a', ' ');\n  return s;\n}\n\nstd::optional<wwiv::sdk::files::Diz> wwiv::sdk::files::DizParser::parse(\n    const std::filesystem::path& path) const {\n  if (!core::File::Exists(path)) {\n    VLOG(1) << \":DizParser::parse: path not exist: \" << path;\n    return std::nullopt;\n  }\n\n  std::string description;\n\n  TextFile file(path, \"rt\");\n  auto lines = file.ReadFileIntoVector();\n  auto iter = std::begin(lines);\n  const auto end = std::end(lines);\n  while (iter != end && iter->empty()) {\n    // skip over any empty lines at the start.\n    ++iter;\n  }\n  // Save off the first non empty line.\n  const auto first_real_line = iter;\n  if (lines.empty()) {\n    VLOG(1) << \"DizParser::parse: lines empty\";\n    return std::nullopt;\n  }\n\n  if (firstline_as_desc_) {\n    auto ss = *iter;\n    if (!ss.empty()) {\n      for (auto& s : ss) {\n        if (strchr(invalid_chars, s) != nullptr && s != 26) {\n          s = ' ';\n        }\n      }\n      if (!valid_desc(ss)) {\n        do {\n          ++iter;\n          ss = *iter;\n        } while (!valid_desc(ss) && iter != end);\n      }\n    }\n    if (!ss.empty() && ss.back() == '\\r') {\n      ss.pop_back();\n    }\n\n    description = strings::StringTrim(ss);\n    // Only bail here if we have nothing.\n    if (description.empty()) {\n      VLOG(1) << \"Description is empty, failed to parse.\";\n      return std::nullopt;\n    }\n\n    ++iter;\n  } else {\n    iter = first_real_line;\n  }\n  std::string ext;\n  for (; iter != end; ++iter) {\n    ext.append(fixup_diz_string(*iter));\n    ext.append(\"\\n\");\n  }\n\n  if (description.empty() && ext.empty()) {\n    return std::nullopt;\n  }\n\n  return {Diz(description, ext)};\n}\n"
  },
  {
    "path": "sdk/files/diz.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_FILES_DIZ_H__\n#define __INCLUDED_SDK_FILES_DIZ_H__\n\n#include <filesystem>\n#include <optional>\n#include <string>\n\nnamespace wwiv::sdk::files {\n\nclass Diz final {\npublic:\n  explicit Diz(std::string description, std::string extended_description);\n  Diz() = delete;\n  ~Diz() = default;\n\n  [[nodiscard]] std::string description() const noexcept;\n  [[nodiscard]] std::string extended_description() const noexcept;\nprivate:\n  const std::string description_;\n  const std::string extended_description_;\n};\n\nclass DizParser final {\npublic:\n  explicit DizParser(bool firstline_as_desc);\n  DizParser() = delete;\n  ~DizParser() = default;\n\n  [[nodiscard]] std::optional<Diz> parse(const std::filesystem::path& path) const;\nprivate:\n  bool firstline_as_desc_;\n};\n\n}\n\n#endif"
  },
  {
    "path": "sdk/files/diz_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/log.h\"\n#include \"core/strings.h\"\n\n#include \"gtest/gtest.h\"\n\n#include \"core/test/file_helper.h\"\n#include \"sdk/files/diz.h\"\n\nclass DizTest : public testing::Test {\npublic:\n  DizTest() {}\n  wwiv::core::test::FileHelper helper;\n};\n\nTEST_F(DizTest, Smoke) {\n  const std::string kDIZ = R\"(Line1\nLine2\nLine3)\";\n\n  const auto file = helper.CreateTempFile(\"FILE_ID.DIZ\", kDIZ);\n\n  wwiv::sdk::files::DizParser p(true);\n  auto o = p.parse(file);\n  ASSERT_TRUE(o);\n\n  auto d = o.value();\n  EXPECT_EQ(d.description(), \"Line1\");\n  EXPECT_EQ(d.extended_description(), \"Line2\\nLine3\\n\");\n}\n\nTEST_F(DizTest, Smoke_NotDescription) {\n  const std::string kDIZ = R\"(Line1\nLine2\nLine3)\";\n\n  const auto file = helper.CreateTempFile(\"FILE_ID.DIZ\", kDIZ);\n\n  wwiv::sdk::files::DizParser p(false);\n  auto o = p.parse(file);\n  ASSERT_TRUE(o);\n\n  auto d = o.value();\n  EXPECT_EQ(d.description(), \"\");\n  EXPECT_EQ(d.extended_description(), \"Line1\\nLine2\\nLine3\\n\");\n}\n\nTEST_F(DizTest, BlockChars) {\n  const char kTEXT[] =\n\"\\xDA\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4[ CyberWall v2.0\\xE1\"\"L ]\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4Ŀ\\n\"\n\"\\xB3 Smaller  version  of  the  popular  door \\xB3\\n\"\n\"\\xB3 CyberWall.   Simple  and  easy  to  use, \\xB3\\n\"\n\"\\xB3 really  cool ANSi. Not  as many features \\xB3\\n\"\n\"\\xB3 as  the  full  version,  but  this  is a \\xB3\\n\"\n\"\\xB3 freeware copy if you don't wanna pay for \\xB3\\n\"\n\"\\xB3 the   full   version.   Freeware   Copy. \\xB3\\n\"\n\"\\xB3\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4ĳ\\n\"\n\"\\xB3        --- LiQUID pRODUCTIoNS ---        \\xB3\\n\"\n\"\\xB3 MegaStuff BBS % (317) 873-5173 % 8am-5pm \\xB3\\n\"\n\"\\xB3\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xC4\\xB3\\n\";\n\n  const auto file = helper.CreateTempFile(\"FILE_ID.DIZ\", kTEXT);\n\n  wwiv::sdk::files::DizParser p(true);\n  auto o = p.parse(file);\n  ASSERT_TRUE(o);\n\n  auto d = o.value();\n  EXPECT_EQ(d.description(), \"[ CyberWall v2.0\\xE1L ]\");\n\n  auto v = wwiv::strings::SplitString(d.extended_description(), \"\\n\");\n  EXPECT_EQ(10u, v.size());\n}\n\nTEST_F(DizTest, EmptyLinesAtStart) {\n  const auto* kTEXT = R\"(\n  <<< null e-magazine x00A (exec edition) >>>\n      ____  _____          _____   _____\n  ___/.   \\/    /_________/.   /__/.   /__jp!_\n //_       \\    .   /         /   \\   /    _//\n   /____/\\____/    /    /__________________\\\n    +--- ---- \\________/ --- -------- ----+\n    : bbs scene and retro computing e-mag .\n    :     https://github.com/xqtr/null    :\n    '  telnet // andr01d.zapto.org:9999   :\n    +---- -  ---------  ---------- -------+)\";\n\n  const auto file = helper.CreateTempFile(\"FILE_ID.DIZ\", kTEXT);\n\n  wwiv::sdk::files::DizParser p(true);\n  auto o = p.parse(file);\n  ASSERT_TRUE(o);\n\n  const auto& d = o.value();\n  EXPECT_EQ(d.description(), \"<<< null e-magazine x00A (exec edition) >>>\");\n}\n\n/**\n\n\n */"
  },
  {
    "path": "sdk/files/file_record.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/file_record.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/files_ext.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\nnamespace {\nconst char* WWIV_FILE_DATE_FORMAT = \"%m/%d/%y\";\n}\n\nstatic void _align(char* fn) {\n  // TODO Modify this to handle long file names\n  char name[40], ext[40];\n\n  auto invalid = false;\n  if (fn[0] == '.') {\n    invalid = true;\n  }\n\n  for (int i = 0; i < ssize(fn); i++) {\n    if (fn[i] == '\\\\' || fn[i] == '/' || fn[i] == ':' || fn[i] == '<' || fn[i] == '>' ||\n        fn[i] == '|') {\n      invalid = true;\n    }\n  }\n  if (invalid) {\n    strcpy(fn, \"        .   \");\n    return;\n  }\n  auto* s2 = strrchr(fn, '.');\n  if (s2 == nullptr || strrchr(fn, '\\\\') > s2) {\n    ext[0] = '\\0';\n  } else {\n    strcpy(ext, &(s2[1]));\n    ext[3] = '\\0';\n    s2[0] = '\\0';\n  }\n  strcpy(name, fn);\n\n  for (int j = ssize(name); j < 8; j++) {\n    name[j] = ' ';\n  }\n  name[8] = '\\0';\n  auto has_wildcard = false;\n  auto has_space = false;\n  for (auto k = 0; k < 8; k++) {\n    if (name[k] == '*') {\n      has_wildcard = true;\n    }\n    if (name[k] == ' ') {\n      has_space = true;\n    }\n    if (has_space) {\n      name[k] = ' ';\n    }\n    if (has_wildcard) {\n      name[k] = '?';\n    }\n  }\n\n  for (int i2 = ssize(ext); i2 < 3; i2++) {\n    ext[i2] = ' ';\n  }\n  ext[3] = '\\0';\n  has_wildcard = false;\n  for (int i3 = 0; i3 < 3; i3++) {\n    if (ext[i3] == '*') {\n      has_wildcard = true;\n    }\n    if (has_wildcard) {\n      ext[i3] = '?';\n    }\n  }\n\n  char buffer[MAX_PATH];\n  for (auto i4 = 0; i4 < 12; i4++) {\n    buffer[i4] = SPACE;\n  }\n  strcpy(buffer, name);\n  buffer[8] = '.';\n  strcpy(&(buffer[9]), ext);\n  strcpy(fn, buffer);\n  for (auto i5 = 0; i5 < 12; i5++) {\n    fn[i5] = to_upper_case<char>(fn[i5]);\n  }\n}\n\nstd::string align(const std::string& file_name) {\n  if (file_name.size() >= 1024) {\n    throw std::runtime_error(\"size to align >=1024 chars\");\n  }\n  char s[1024];\n  to_char_array(s, file_name);\n  _align(s);\n  return s;\n}\n\nstd::string unalign(const std::string& file_name) {\n  auto s{file_name};\n  s.erase(remove(s.begin(), s.end(), ' '), s.end());\n  if (s.empty()) {\n    return {};\n  }\n  if (s.back() == '.') {\n    s.pop_back();\n  }\n  return ToStringLowerCase(s);\n}\n\nFileName::FileName(std::string aligned_filename)\n    : aligned_filename_(align(aligned_filename)), unaligned_filename_(unalign(aligned_filename_)) {}\n\nFileName::FileName(const FileName& that)\n    : aligned_filename_(that.aligned_filename()), unaligned_filename_(that.unaligned_filename()) {}\n\nconst std::string& FileName::aligned_filename() const noexcept {\n  return aligned_filename_;\n}\n\nconst std::string& FileName::unaligned_filename() const noexcept {\n  return unaligned_filename_;\n}\n\nstd::string FileName::basename() const {\n  return StringTrim(aligned_filename_.substr(0, 8));\n}\n\nstd::string FileName::extension() const {\n  return StringTrim(aligned_filename_.substr(9));\n}\n\n//static\nstd::optional<FileName> FileName::FromUnaligned(const std::string& unaligned_name) {\n  return {FileName(align(unaligned_name))};\n}\n\nFileRecord::FileRecord() : FileRecord(uploadsrec{}) {}\n\nFileRecord::FileRecord(const FileRecord& that) : u_(that.u()) {}\n\nFileRecord& FileRecord::operator=(const FileRecord& that) {\n  u_ = that.u();\n  return *this;\n}\n\n\nbool FileRecord::has_extended_description() const noexcept {\n  return mask(mask_extended);\n}\n\nvoid FileRecord::set_extended_description(bool b) {\n  set_mask(mask_extended, b);\n}\n\nvoid FileRecord::set_mask(int mask, bool on) {\n  if (on) {\n    u_.mask |= mask;\n  } else {\n    u_.mask &= ~mask;\n  }\n}\n\nbool FileRecord::mask(int mask) const {\n  return u_.mask & mask;\n}\n\nbool FileRecord::set_filename(const FileName& filename) {\n  return set_filename(filename.unaligned_filename());\n}\n\nbool FileRecord::set_filename(const std::string& unaligned_filename) {\n  if (unaligned_filename.size() > 12) {\n    return false;\n  }\n  to_char_array(u_.filename, align(unaligned_filename));\n  return true;\n}\n\nuint32_t FileRecord::numbytes() const noexcept {\n  return u_.numbytes;\n}\n\nvoid FileRecord::set_numbytes(int size) {\n  u_.numbytes = static_cast<daten_t>(size);\n}\n\nuint16_t FileRecord::ownerusr() const noexcept {\n  return u_.ownerusr;\n}\n\nvoid FileRecord::set_ownerusr(int o) {\n  u_.ownerusr = static_cast<uint16_t>(o);\n}\n\nuint16_t FileRecord::ownersys() const noexcept {\n  return u_.ownersys;\n}\n\nvoid FileRecord::set_ownersys(int o) {\n  u_.ownersys = static_cast<uint16_t>(o);\n}\n\nbool FileRecord::set_description(const std::string& desc) {\n  auto d = desc;\n  if (d.size() > 55u) {\n    d.resize(55);\n  }\n  to_char_array(u_.description, d);\n  return true;\n}\n\nbool FileRecord::set_uploaded_by(const std::string& name) {\n  auto d = name;\n  if (d.size() > 35u) {\n    d.resize(35);\n  }\n  to_char_array(u_.upby, d);\n  return true;\n}\n\nstd::string FileRecord::uploaded_by() const {\n  return u_.upby;\n}\n\nstd::string FileRecord::description() const {\n  return u_.description;\n}\n\nwwiv::core::DateTime FileRecord::date() const {\n  return DateTime::from_daten(u_.daten);\n}\n\nstd::string FileRecord::actual_date() const {\n  return std::string(u_.actualdate);\n}\n\nbool FileRecord::set_date(const wwiv::core::DateTime& dt) {\n  const auto d = dt.to_time_t() == 0 ? DateTime::now() : dt;\n  to_char_array(u_.date, d.to_string(WWIV_FILE_DATE_FORMAT));\n  u_.daten = d.to_daten_t();\n  return true;\n}\n\nbool FileRecord::set_actual_date(const wwiv::core::DateTime& dt) {\n  const auto d = dt.to_time_t() == 0 ? DateTime::now() : dt;\n  to_char_array(u_.actualdate, d.to_string(WWIV_FILE_DATE_FORMAT));\n  return true;\n}\n\nFileName FileRecord::filename() const {\n  return FileName(u_.filename);\n}\n\nstd::string FileRecord::aligned_filename() const {\n  return align(u_.filename);\n}\n\nstd::string FileRecord::unaligned_filename() const {\n  return unalign(u_.filename);\n}\n\nstd::filesystem::path FilePath(const std::filesystem::path& directory_name,\n                                   const FileRecord& f) {\n  if (directory_name.empty()) {\n    return f.unaligned_filename();\n  }\n  return directory_name / f.unaligned_filename();\n}\n\nstd::filesystem::path FilePath(const std::filesystem::path& directory_name,\n                                   const FileName& f) {\n  if (directory_name.empty()) {\n    return f.unaligned_filename();\n  }\n  return directory_name / f.unaligned_filename();\n}\n\nstd::ostream& operator<<(std::ostream& os, const FileName& f) {\n  os << f.unaligned_filename();\n  return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const FileRecord& f) {\n  os << f.unaligned_filename();\n  return os;\n}\n\n} // namespace wwiv::sdk::files\n"
  },
  {
    "path": "sdk/files/file_record.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FILES_FILE_RECORD_H\n#define INCLUDED_SDK_FILES_FILE_RECORD_H\n\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"sdk/vardec.h\"\n\n#include <optional>\n#include <string>\n\nnamespace wwiv::core {\nclass DateTime;\n}\n\nnamespace wwiv::sdk::files {\n\nclass FileName final {\npublic:\n  explicit FileName(std::string aligned_filename);\n  FileName(const FileName& that);\n  ~FileName() = default;\n\n  /** Returns the aligned version of the filename, this is padded and uppercase as 8.3. */\n  [[nodiscard]] const std::string& aligned_filename() const noexcept;\n  /** Returns the unaligned version of the filename, this is nonpadded and lowercase. */\n  [[nodiscard]] const std::string& unaligned_filename() const noexcept;\n  /** Returns the basename of the filename, this is not space padded */\n  [[nodiscard]] std::string basename() const;\n  /** Returns the extension of the filename, this is not space padded */\n  [[nodiscard]] std::string extension() const;\n\n  static std::optional<FileName> FromUnaligned(const std::string& unaligned_name);\n  friend std::ostream& operator<<(std::ostream& os, const FileName& f);\n\nprivate:\n  const std::string aligned_filename_;\n  const std::string unaligned_filename_;\n};\n\nclass FileRecord final {\npublic:\n  explicit FileRecord(const uploadsrec& u) : u_(u) {}\n  FileRecord();\n  FileRecord(const FileRecord&);\n  FileRecord& operator=(const FileRecord&);\n  ~FileRecord() = default;\n\n  [[nodiscard]] uploadsrec& u() { return u_; }\n  [[nodiscard]] const uploadsrec& u() const { return u_; }\n  [[nodiscard]] uint32_t numbytes() const noexcept;\n  void set_numbytes(int size);\n  [[nodiscard]] uint16_t ownerusr() const noexcept;\n  void set_ownerusr(int o);\n  [[nodiscard]] uint16_t ownersys() const noexcept;\n  void set_ownersys(int o);\n  [[nodiscard]] bool has_extended_description() const noexcept;\n  void set_extended_description(bool b);\n\n  [[nodiscard]] bool pd_or_shareware() const noexcept { return mask(mask_PD); }\n  void set_pd_or_shareware(bool b) { set_mask(mask_PD, b); }\n\n  [[nodiscard]] bool mask(int mask) const;\n  void set_mask(int mask, bool on);\n\n  bool set_filename(const FileName& filename);\n  bool set_filename(const std::string& unaligned_filename);\n  bool set_description(const std::string& desc);\n  [[nodiscard]] std::string description() const;\n  bool set_uploaded_by(const std::string& name);\n  [[nodiscard]] std::string uploaded_by() const;\n  [[nodiscard]] wwiv::core::DateTime date() const;\n  [[nodiscard]] std::string actual_date() const;\n  bool set_date(const wwiv::core::DateTime& dt);\n  bool set_actual_date(const wwiv::core::DateTime& dt);\n  [[nodiscard]] FileName filename() const;\n  [[nodiscard]] std::string aligned_filename() const;\n  [[nodiscard]] std::string unaligned_filename() const;\n  friend std::ostream& operator<<(std::ostream& os, const FileRecord& f);\n\nprivate:\n  uploadsrec u_;\n};\n\nstd::string align(const std::string& file_name);\nstd::string unalign(const std::string& file_name);\n\nstd::filesystem::path FilePath(const std::filesystem::path& directory_name,\n                                   const FileRecord& f);\n\nstd::filesystem::path FilePath(const std::filesystem::path& directory_name,\n                                   const FileName& f);\n} // namespace wwiv::sdk::files\n\ntemplate <> struct fmt::formatter<wwiv::sdk::files::FileRecord> : fmt::formatter<string_view> {\n  // parse is inherited from formatter<string_view>.\n  template <typename FormatContext>\n  auto format(wwiv::sdk::files::FileRecord r, FormatContext& ctx) {\n    return formatter<string_view>::format(r.unaligned_filename(), ctx);\n  }\n};\n\n#endif  // INCLUDED_SDK_FILES_FILE_RECORD_H\n"
  },
  {
    "path": "sdk/files/files.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/files.h\"\n\n#include \"dirs.h\"\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/files_ext.h\"\n#include <algorithm>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\nFileApi::FileApi(const std::filesystem::path& data_directory)\n: data_directory_(data_directory) {\n  clock_ = std::make_unique<SystemClock>();\n};\n\nbool FileApi::Exist(const std::string& filename) const {\n  return File::Exists(::FilePath(data_directory_, StrCat(filename, \".dir\")));\n}\n\nbool FileApi::Exist(const directory_t& dir) const {\n  return Exist(dir.filename);\n}\n\nbool FileApi::Create(const std::string& filename) {\n  if (Exist(filename)) {\n    return false;\n  }\n\n  FileArea area(this, data_directory_, filename);\n  // Close should save and write header if needed.\n  return area.Close();\n}\n\nbool FileApi::Create(const directory_t& dir) {\n  return Create(dir.filename);  \n}\n\n\nbool FileApi::Remove(const std::string&) {\n  // TODO(rushfan): Implement me.\n  return false;\n}\n\nstd::unique_ptr<FileArea> FileApi::Open(const std::string& filename) {\n  if (!Exist(filename)) {\n    return {};\n  }\n  return std::make_unique<FileArea>(this, data_directory_, filename);\n}\n\nstd::unique_ptr<FileArea> FileApi::Open(const directory_t& dir) {\n  return Open(dir.filename);\n}\n\nstd::unique_ptr<FileArea> FileApi::CreateOrOpen(const directory_t& dir) {\n  if (auto o = Open(dir); o) {\n    return o;\n  }\n  if (Create(dir)) {\n    return Open(dir);\n  }\n  return {};\n}\n\nconst Clock* FileApi::clock() const noexcept {\n  return clock_.get();  \n}\n\nvoid FileApi::set_clock(std::unique_ptr<Clock> clock) {\n  clock_ = std::move(clock);\n}\n\nFileAreaHeader::FileAreaHeader(const uploadsrec& u) : u_(u) {}\n\nbool FileAreaHeader::FixHeader(const Clock& clock, uint32_t num_files) {\n  // Always overwrite marker.\n  to_char_array(u_.filename, \"|MARKER|\");\n  if (u_.daten == 0) {\n    const auto now = clock.Now();\n    u_.daten = now.to_daten_t();\n  }\n  u_.numbytes = num_files;\n  return true;\n}\n\nvoid FileAreaHeader::set_daten(daten_t d) {\n  u_.daten = d;\n}\n\ndaten_t FileAreaHeader::daten() const {\n  return u_.daten;\n}\n\n// Delegates to other constructor\nFileArea::FileArea(FileApi* api, const std::filesystem::path& data_directory, const directory_t& dir)\n    : FileArea(api, data_directory, dir.filename) {\n  dir_ = dir; \n}\n\n// Real constructor that does all of the work.\nFileArea::FileArea(FileApi* api, const std::filesystem::path& data_directory,\n                   const std::string& filename)\n    : api_(api), data_directory_(data_directory), base_filename_(filename),\n      filename_(StrCat(filename, \".dir\")) {\n  open_ = Load();\n  // Load up extended descriptions\n  ext_desc();\n}\n\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool FileArea::FixFileHeader() {\n  return header_->FixHeader(*api_->clock(), files_.empty() ? 0 : stl::size_uint32(files_) - 1);\n}\n\nFileAreaHeader& FileArea::header() const {\n  return *header_;\n}\n\nbool FileArea::Load() {\n  dirty_ = false;\n\n  if (auto file = DataFile<uploadsrec>(path(), File::modeReadOnly | File::modeBinary)) {\n    if (file.ReadVector(files_)) {\n      open_ = true;\n    }\n  }\n  if (files_.empty()) {\n    files_.emplace_back();\n    open_ = dirty_ = true;\n  }\n  header_ = std::make_unique<FileAreaHeader>(files_.front());\n  header_->FixHeader(*api_->clock(), files_.empty() ? 0 : stl::size_uint32(files_) - 1);\n  return open_;\n}\n\nbool FileArea::Close() {\n  if (open_ && dirty_) {\n    const auto r = Save();\n    ext_desc_.reset();\n    open_ = false;\n    return r;\n  }\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nbool FileArea::Lock() { return false; }\n// ReSharper disable once CppMemberFunctionMayBeStatic\nbool FileArea::Unlock() { return false; }\n\nint FileArea::number_of_files() const {\n  if (!open_) {\n    return 0;\n  }\n\n  if (files_.empty()) {\n    return 0;\n  }\n\n  return wwiv::stl::size_int32(files_) - 1;\n}\n\ntypedef std::function<bool(const uploadsrec& l, const uploadsrec& r)> UlrCompare;\n\nstd::map<FileAreaSortType, UlrCompare> CreateSortFunctions() {\n  std::map<FileAreaSortType, UlrCompare> m;\n  m.emplace(FileAreaSortType::DATE_ASC, [](const uploadsrec& l, const uploadsrec& r){\n    return l.daten < r.daten;\n  });\n  m.emplace(FileAreaSortType::DATE_DESC, [](const uploadsrec& l, const uploadsrec& r){\n    return r.daten < l.daten;\n  });\n  m.emplace(FileAreaSortType::FILENAME_ASC, [](const uploadsrec& l, const uploadsrec& r){\n    return StringCompare(l.filename, r.filename) == -1;\n  });\n  m.emplace(FileAreaSortType::FILENAME_DESC, [](const uploadsrec& l, const uploadsrec& r){\n    return StringCompare(r.filename, l.filename) == -1;\n  });\n  return m;\n}\n\nbool FileArea::Sort(FileAreaSortType type) {\n  if (files_.size() <= 1) {\n    return false;\n  }\n\n  const auto compare_funcs = CreateSortFunctions();\n  // stl::at didn't work\n  const auto& f = compare_funcs.at(type);\n  std::sort(std::begin(files_) + 1, std::end(files_), f);\n  dirty_ = true;\n  return true;\n}\n\n// File specific\nFileRecord FileArea::ReadFile(int num) {\n  return FileRecord(wwiv::stl::at(files_, num));\n}\n\nbool FileArea::AddFile(const FileRecord& f) {\n  if (files_.size() <= 1) {\n    files_.push_back(f.u());\n  } else {\n    files_.insert(std::begin(files_) + 1, f.u());\n  }\n  header_->set_num_files(stl::size_uint32(files_) - 1);\n  header_->set_daten(std::max(header_->daten(), f.u().daten));\n  dirty_ = true;\n  return true;\n}\n\nbool FileArea::AddFile(FileRecord& f, const std::string& ext_desc) {\n  f.set_extended_description(!ext_desc.empty());\n  if (!AddFile(f)) {\n    return false;\n  }\n  if (ext_desc.empty()) {\n    return true;\n  }\n  return AddExtendedDescription(f, ext_desc);\n}\n\nbool FileArea::UpdateFile(FileRecord& f, int num) {\n  files_.at(num) = f.u();\n  header_->set_daten(std::max(header_->daten(), f.u().daten));\n  dirty_ = true;\n  return true;\n}\n\nbool FileArea::UpdateFile(FileRecord& f, int num, const std::string& ext_desc) {\n  f.set_extended_description(!ext_desc.empty());\n  if (!UpdateFile(f, num)) {\n    return false;\n  }\n  if (ext_desc.empty()) {\n    return true;\n  }\n  // Delete any old description before adding new ones.\n  DeleteExtendedDescription(f, num);\n  return AddExtendedDescription(f, num, ext_desc);\n}\n\nbool FileArea::DeleteFile(const FileRecord& f, int file_number) {\n  if (!ValidateFileNum(f, file_number)) {\n    return false;\n  }\n  return DeleteFile(file_number);\n}\n\nbool FileArea::DeleteFile(int file_number) {\n  const auto old = stl::at(files_, file_number);\n  if (!stl::erase_at(files_, file_number)) {\n    return false;\n  }\n  // Attempt to delete the extended descriptions if they existed.\n  if (old.mask & mask_extended) {\n    DeleteExtendedDescription(old.filename);\n  }\n  dirty_ = true;\n  header_->set_num_files(files_.empty() ? 0 : stl::size_uint32(files_) - 1);\n\n  return true;\n}\n\nstd::optional<FileAreaExtendedDesc*> FileArea::ext_desc(bool reload) {\n  if (!open_) {\n    return std::nullopt;\n  }\n  if (!ext_desc_ || reload) {\n    ext_desc_ = std::make_unique<FileAreaExtendedDesc>(\n      api_, data_directory_, base_filename_, number_of_files());\n  }\n  return {ext_desc_.get()};\n}\n\nbool FileArea::AddExtendedDescription(FileRecord& f, int num, const std::string& text) {\n  if (!ValidateFileNum(f, num)) {\n    return false;\n  }\n  const auto r = AddExtendedDescription(f, text);\n  const auto need_ext_desc_set = !f.has_extended_description();\n  f.set_extended_description(true);\n  if (need_ext_desc_set && num > 0) {\n    UpdateFile(f, num);\n  }\n  return r;\n}\n\nbool FileArea::AddExtendedDescription(const std::string& file_name, const std::string& text) {\n  auto o = ext_desc();\n  if (!o) {\n    return false;\n  }\n  return o.value()->AddExtended(file_name, text);\n}\n\nbool FileArea::AddExtendedDescription(const FileRecord& f, const std::string& text) {\n  return AddExtendedDescription(f.aligned_filename(), text);\n}\n\nbool FileArea::AddExtendedDescription(const FileName& f, const std::string& text) {\n  return AddExtendedDescription(f.aligned_filename(), text);\n}\n\nbool FileArea::DeleteExtendedDescription(FileRecord& f, int num) {\n  if (!ValidateFileNum(f, num)) {\n    return false;\n  }\n  const auto result = DeleteExtendedDescription(f.aligned_filename());\n  f.set_extended_description(false);\n  if (num > 0) {\n    UpdateFile(f, num);\n  }\n  return result;\n}\n\nbool FileArea::DeleteExtendedDescription(const std::string& file_name) {\n  auto o = ext_desc();\n  if (!o) {\n    return false;\n  }\n  return o.value()->DeleteExtended(file_name);\n}\n\nbool FileArea::DeleteExtendedDescription(const FileName& f) {\n  return DeleteExtendedDescription(f.aligned_filename());\n}\n\nstd::optional<std::string> FileArea::ReadExtendedDescriptionAsString(FileName& f) {\n  return ReadExtendedDescriptionAsString(f.aligned_filename());\n}\n\nstd::optional<std::string> FileArea::ReadExtendedDescriptionAsString(FileRecord& f) {\n  return ReadExtendedDescriptionAsString(f.aligned_filename());\n}\n\nstd::optional<std::string> FileArea::ReadExtendedDescriptionAsString(\n    const std::string& aligned_name) {\n  auto o = ext_desc();\n  if (!o) {\n    return std::nullopt;\n  }\n  return o.value()->ReadExtended(aligned_name);\n}\n\nconst std::vector<uploadsrec>& FileArea::raw_files() const {\n  return files_;\n}\n\nbool FileArea::set_raw_files(std::vector<uploadsrec> nf) {\n  files_ = std::move(nf);\n  return true;\n}\n\nstd::optional<int> FileArea::FindFile(const FileRecord& f) {\n  return FindFile(f.aligned_filename());\n}\n\nstd::optional<int> FileArea::FindFile(const FileName& f) {\n  return FindFile(f.aligned_filename());\n}\n\nstd::optional<int> FileArea::FindFile(const std::string& file_name) {\n  for (auto i = 0; i < stl::ssize(files_); i++) {\n    if (const auto & c = stl::at(files_, i); file_name == c.filename) {\n      return {i};\n    }\n  }\n  return std::nullopt;\n}\n\nbool aligned_wildcard_match(const std::string& l, const std::string& r) {\n  if (l.size() != 12 || r.size() != 12) {\n    LOG(ERROR) << \"Invalid params to aligned_wildcard_match: l:'\" << l << \"'; r:'\" << r << \"'\";\n    return false;\n  }\n  for (auto i = 0; i < 12; i++) {\n    if (l[i] != r[i] && l[i] != '?' && r[i] != '?') {\n      return false;\n    }\n  }\n  return true;\n}\n\nstd::optional<int> FileArea::SearchFile(const std::string& filemask, int start_num) {\n  if (const auto numf = number_of_files(); numf < 1 || start_num > numf) { // was >=\n    return std::nullopt;\n  }\n\n  for (auto i = start_num; i < stl::ssize(files_); i++) {\n    if (const auto & c = stl::at(files_, i); aligned_wildcard_match(filemask, c.filename)) {\n      return {i};\n    }\n  }\n  return std::nullopt;\n}\n\n\nbool FileArea::Save() {\n  DataFile<uploadsrec> file(path(), File::modeReadWrite | File::modeCreateFile | File::modeBinary);\n\n  if (!file) {\n    return false;\n  }\n\n  // Update Header\n  FixFileHeader();\n  files_.at(0) = header_->u();\n\n  const auto result = file.WriteVectorAndTruncate(files_);\n  if (result) {\n    dirty_ = false;\n  }\n  return result;\n}\n\nstd::filesystem::path FileArea::path() const noexcept {\n  return ::FilePath(data_directory_, filename_);\n}\n\nstd::filesystem::path FileArea::ext_path() {\n  const auto e = ext_desc(false);\n  if (!e) {\n    auto p = path();\n    return p.replace_extension(\".ext\");\n  }\n  return e.value()->path();\n}\n\nbool FileArea::ValidateFileNum(const FileRecord& f, int num) {\n  if (const auto & o = stl::at(files_, num); f.aligned_filename() != o.filename) {\n    LOG(ERROR) << \"Mismatched File call for \" << f.aligned_filename() << \" vs: \" << o.filename\n               << \" at pos: \" << num;\n    return false;\n  }\n  return true;\n}\n\n\n} // namespace wwiv::sdk::files\n"
  },
  {
    "path": "sdk/files/files.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FILES_FILES_H\n#define INCLUDED_SDK_FILES_FILES_H\n\n#include \"dirs.h\"\n#include \"core/clock.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/file_record.h\"\n#include \"sdk/files/files_ext.h\"\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::files {\n\nclass FileArea;\n\nenum class FileAreaSortType {\n  FILENAME_ASC,\n  FILENAME_DESC,\n  DATE_ASC,\n  DATE_DESC\n};\n\nclass FileApi {\npublic:\n  virtual ~FileApi() = default;\n  explicit FileApi(const std::filesystem::path& data_directory);\n\n  [[nodiscard]] bool Exist(const std::string& filename) const;\n  [[nodiscard]] bool Exist(const directory_t& dir) const;\n  [[nodiscard]] bool Create(const std::string& filename);\n  [[nodiscard]] bool Create(const directory_t& dir);\n  [[nodiscard]] bool Remove(const std::string& filename);\n  [[nodiscard]] std::unique_ptr<FileArea> Open(const std::string& filename);\n  [[nodiscard]] std::unique_ptr<FileArea> Open(const directory_t& dir);\n  [[nodiscard]] std::unique_ptr<FileArea> CreateOrOpen(const directory_t& dir);\n\n  [[nodiscard]] const core::Clock* clock() const noexcept;\n  void set_clock(std::unique_ptr<core::Clock> clock);\n\nprivate:\n  const std::filesystem::path data_directory_;\n  std::unique_ptr<core::Clock> clock_;\n};\n\n/**\n * Represents a file area header.\n * Internally this is stuffed into an uploadsrec re-purposing some\n * of the fields:\n *\n * filename must contain \"|MARKER|\"\n * numbytes is the total number of files in this area.\n * daten is the date of the newest file.\n */\nclass FileAreaHeader {\npublic:\n  explicit FileAreaHeader(const uploadsrec& u);\n  ~FileAreaHeader() = default;\n\n  [[nodiscard]] uint32_t num_files() const { return u_.numbytes; }\n  bool set_num_files(uint32_t n) { u_.numbytes = n; return true; }\n  bool FixHeader(const core::Clock& clock, uint32_t num_files);\n  uploadsrec& u() { return u_; }\n  void set_daten(daten_t d);\n  [[nodiscard]] daten_t daten() const;\nprivate:\n  uploadsrec u_;\n};\n\nclass FileArea final {\npublic:\n  using iterator_category = std::forward_iterator_tag;\n  using value_type = FileRecord;\n  using difference_type = int;\n  using pointer = FileRecord*;\n  using reference = FileRecord&;\n\n  FileArea(FileApi* api, const std::filesystem::path& data_directory, const directory_t& dir);\n  FileArea(FileApi* api, const std::filesystem::path& data_directory, const std::string& filename);\n  ~FileArea() = default;\n  \n  // File Header specific\n  bool FixFileHeader();\n  [[nodiscard]] FileAreaHeader& header() const;\n\n  // File Dir Specific Operations\n\n  // Loads the data on disk to the FileArea class\n  bool Load();\n  // Saves all changes to Disk. Note that extended\n  // description changes happen immediately.\n  bool Save();\n  // Saves (if dirty and open) and marks this file areas as closed.\n  bool Close();\n  bool Lock();\n  bool Unlock();\n  [[nodiscard]] int number_of_files() const;\n\n  // Sorts the files in memory.\n  bool Sort(FileAreaSortType type);\n\n  // File specific\n  /** Optionally returns the file position for any exact match */\n  std::optional<int> FindFile(const FileRecord& f);\n  /** Optionally returns the file position for any exact match */\n  std::optional<int> FindFile(const FileName& f);\n  /** Optionally returns the file position for any exact match */\n  std::optional<int> FindFile(const std::string& file_name);\n\n  /** Searches for a file mask on an aligned file. i.e. 'FOO?????.ZIP' */\n  std::optional<int> SearchFile(const std::string& filemask, int start_num = 1);\n\n  FileRecord ReadFile(int num);\n  bool AddFile(const FileRecord& f);\n  bool AddFile(FileRecord& f, const std::string& ext_desc);\n  bool UpdateFile(FileRecord& f, int num);\n  bool UpdateFile(FileRecord& f, int num, const std::string& ext_desc);\n  bool DeleteFile(const FileRecord& f, int file_number);\n  bool DeleteFile(int file_number);\n\n  // Extended Descriptions\n  // Gets or creates the FileAreaExtendedDesc class.  If reload is true then\n  // the class will be reloaded.\n  std::optional<FileAreaExtendedDesc*> ext_desc(bool reload = false);\n  // Adds an extended description to file f at pos num.  If num is -1\n  // then don't update f.\n  bool AddExtendedDescription(FileRecord& f, int num, const std::string& text);\n  bool AddExtendedDescription(const std::string& file_name, const std::string& text);\n  bool AddExtendedDescription(const FileRecord& f, const std::string& text);\n  bool AddExtendedDescription(const FileName& f, const std::string& text);\n  bool DeleteExtendedDescription(FileRecord& f, int num);\n  bool DeleteExtendedDescription(const std::string& file_name);\n  bool DeleteExtendedDescription(const FileName& f);\n  std::optional<std::string> ReadExtendedDescriptionAsString(FileName& f);\n  std::optional<std::string> ReadExtendedDescriptionAsString(FileRecord& f);\n  std::optional<std::string> ReadExtendedDescriptionAsString(const std::string& aligned_name);\n\n  // Gets the raw files\n  [[nodiscard]] const std::vector<uploadsrec>& raw_files() const;\n  // Sets the raw files.  Do not use unless you are doing a \"fix\" type tool\n  [[nodiscard]] bool set_raw_files(std::vector<uploadsrec>);\n  [[nodiscard]] std::filesystem::path path() const noexcept;\n  [[nodiscard]] std::filesystem::path ext_path();\n\nprotected:\n  bool ValidateFileNum(const FileRecord& f, int num);\n\n  // Not owned.\n  FileApi* api_;\n  const std::filesystem::path data_directory_;\n  const std::string base_filename_;\n  const std::string filename_;\n  directory_t dir_{};\n\n  bool dirty_{false};\n  bool open_{false};\n  std::vector<uploadsrec> files_;\n\n  std::unique_ptr<FileAreaHeader> header_;\n  std::unique_ptr<FileAreaExtendedDesc> ext_desc_;\n};\n\n/**\n * Return true if two files {l, r} match each other either exactly or using\n * aligned wildcards.\n *\n * An aligned wildcard is of the form: \"[A-Z? ]{8}\\.[A-Z? ]{3}\"\n */\nbool aligned_wildcard_match(const std::string& l, const std::string& r);\n\n} // namespace wwiv::sdk::files\n\n#endif  // __INCLUDED_SDK_FILES_FILES_H__\n"
  },
  {
    "path": "sdk/files/files_ext.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/files_ext.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/files/file_record.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/vardec.h\"\n#include <algorithm>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::files {\n\nFileAreaExtendedDesc::FileAreaExtendedDesc(FileApi* api,\n                                           const std::filesystem::path& data_directory,\n                                           const directory_t& dir, int num_files)\n    : FileAreaExtendedDesc(api, data_directory, dir.filename, num_files) {\n  dir_ = dir;\n}\n\nFileAreaExtendedDesc::FileAreaExtendedDesc(FileApi* api,\n                                           const std::filesystem::path& data_directory,\n                                           const std::string& filename, int num_files)\n    : api_(api), data_directory_(data_directory), filename_(StrCat(filename, \".ext\")),\n      num_files_(std::max<int>(std::numeric_limits<int16_t>::max(), num_files)) {}\n\nbool FileAreaExtendedDesc::Load() {\n  Close();\n\n  File f(path());\n  if (!f.Open(File::modeReadOnly | File::modeBinary)) {\n    return false;\n  }\n  const auto file_size = f.length();\n  if (!file_size) {\n    open_ = true;\n    return true;\n  }\n  for (long file_pos = 0, count = 0; file_pos < file_size && count <= num_files_; count++) {\n    f.Seek(file_pos, File::Whence::begin);\n    ext_desc_type ed{};\n    if (const auto num_read = f.Read(&ed, sizeof(ext_desc_type)); num_read != sizeof(ext_desc_type)) {\n      // LOG ERROR? Return false here?\n      break;\n    }\n    ext_desc_rec e{};\n    strcpy(e.name, ed.name);\n    e.offset = file_pos;\n    ext_.emplace_back(e);\n\n    file_pos += ed.len + static_cast<int>(sizeof(ext_desc_type));\n  }\n  open_ = true;\n  return true;\n}\n\nbool FileAreaExtendedDesc::Save() {\n  return false;\n}\n\nbool FileAreaExtendedDesc::Close() {\n  ext_.clear();\n  open_ = false;\n  return true;\n}\n\nint FileAreaExtendedDesc::number_of_ext_descriptions() {\n  if (!open_) {\n    Load();\n  }\n  return wwiv::stl::size_int(ext_);\n}\n\nbool FileAreaExtendedDesc::AddExtended(const FileRecord& f, const std::string& text) {\n  return AddExtended(f.aligned_filename(), text);\n}\n\nbool FileAreaExtendedDesc::AddExtended(const std::string& file_name, const std::string& text) {\n  Close();\n\n  ext_desc_type ed{};\n  to_char_array(ed.name, file_name);\n  ed.len = static_cast<int16_t>(text.size());\n\n  {\n    File file(path());\n    if (!file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      return false;\n    }\n    file.Seek(0L, File::Whence::end);\n    file.Write(&ed, sizeof(ext_desc_type));\n    file.Write(text.c_str(), ed.len);\n    file.Close();\n  }\n  return Close();\n}\n\nbool FileAreaExtendedDesc::DeleteExtended(const FileRecord& f) {\n  const auto file_name = f.aligned_filename();\n  return DeleteExtended(file_name);\n}\n\nbool FileAreaExtendedDesc::DeleteExtended(const std::string& file_name) {\n\n  ext_desc_type ed{};\n\n  File file(path());\n  if (!file.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n    return false;\n  }\n  const auto file_size = file.length();\n  File::size_type r = 0, w = 0;\n  while (r < file_size) {\n    file.Seek(r, File::Whence::begin);\n    file.Read(&ed, sizeof(ext_desc_type));\n    if (ed.len < 10000) {\n      std::string ss;\n      ss.resize(ed.len);\n      file.Read(&ss[0], ed.len);\n      if (file_name != ed.name) {\n        if (r != w) {\n          file.Seek(w, File::Whence::begin);\n          file.Write(&ed, sizeof(ext_desc_type));\n          file.Write(ss.data(), ed.len);\n        }\n        w += sizeof(ext_desc_type) + ed.len;\n      }\n    }\n    r += sizeof(ext_desc_type) + ed.len;\n  }\n  file.Close();\n  file.set_length(w);\n\n  return Close();\n}\n\nstd::optional<std::string> FileAreaExtendedDesc::ReadExtended(const FileRecord& f) {\n  return ReadExtended(f.aligned_filename());\n}\n\nstd::optional<std::string> FileAreaExtendedDesc::ReadExtended(const std::string& file_name) {\n    if (!open_) {\n    if (!Load()) {\n      return std::nullopt;\n    }\n  }\n  for (const auto& ext : ext_) {\n    if (file_name != ext.name) {\n      continue;\n    }\n    File file(path());\n    if (!file.Open(File::modeBinary | File::modeReadOnly)) {\n      return std::nullopt;\n    }\n    file.Seek(ext.offset, File::Whence::begin);\n    ext_desc_type ed{};\n    if (const auto num_read = file.Read(&ed, sizeof(ext_desc_type));\n        num_read != sizeof(ext_desc_type) || file_name != ed.name) {\n      Close();\n      return std::nullopt;\n    }\n    std::string ss;\n    ss.resize(ed.len);\n    file.Read(&ss[0], ed.len);\n    file.Close();\n\n    return StringTrimEnd(ss);\n  }\n  return std::nullopt;\n}\n\nstd::optional<std::vector<std::string>> FileAreaExtendedDesc::ReadExtendedAsLines(\n    const FileRecord& f) {\n  return ReadExtendedAsLines(f.aligned_filename());\n}\n\nstd::optional<std::vector<std::string>> FileAreaExtendedDesc::ReadExtendedAsLines(\n    const std::string& file_name) {\n  auto o = ReadExtended(file_name);\n  if (!o) {\n    return std::nullopt;\n  }\n  std::vector<std::string> out;\n  auto lines = SplitString(o.value(), \"\\r\", false);\n  for (auto l : lines) {\n    StringTrimCRLF(&l);\n    if (!l.empty()) {\n      out.push_back(l);\n    }\n  }\n  return {out};\n}\n\nstd::filesystem::path FileAreaExtendedDesc::path() const noexcept {\n  return ::FilePath(data_directory_, filename_);\n}\n\n} // namespace wwiv::sdk::files\n"
  },
  {
    "path": "sdk/files/files_ext.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FILES_FILES_EXT_H\n#define INCLUDED_SDK_FILES_FILES_EXT_H\n\n#include \"dirs.h\"\n#include \"sdk/files/file_record.h\"\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::files {\n\n\nclass FileApi;\nclass FileRecord;\n\nclass FileAreaExtendedDesc final {\npublic:\n\n  FileAreaExtendedDesc(FileApi* api, const std::filesystem::path& data_directory,\n                       const directory_t& dir, int num_files);\n  FileAreaExtendedDesc(FileApi* api, const std::filesystem::path& data_directory,\n                       const std::string& filename, int num_files);\n  ~FileAreaExtendedDesc() = default;\n  \n  // File Dir Specific Operations\n  bool Load();\n  bool Save(); // NOP?\n  bool Close();\n  [[nodiscard]] bool Lock() { return true; }\n  [[nodiscard]] bool Unlock() { return true; }\n  int max_number_of_files() const noexcept { return num_files_; };\n  int number_of_ext_descriptions();\n  [[nodiscard]] bool Compact() { return false; }\n\n  // File specific\n  bool AddExtended(const FileRecord& f, const std::string& text);\n  bool AddExtended(const std::string& file_name, const std::string& text);\n  bool DeleteExtended(const FileRecord& f);\n  bool DeleteExtended(const std::string& file_name);\n  std::optional<std::string> ReadExtended(const FileRecord& f);\n  std::optional<std::string> ReadExtended(const std::string& file_name);\n  std::optional<std::vector<std::string>> ReadExtendedAsLines(const FileRecord& f);\n  std::optional<std::vector<std::string>> ReadExtendedAsLines(const std::string& file_name);\n  bool UpdateExtended(const FileRecord& f, const std::string& text);\n\n  [[nodiscard]] std::filesystem::path path() const noexcept;\n\nprotected:\n\n  // Not owned.\n  FileApi* api_;\n  const std::filesystem::path data_directory_;\n  const std::string filename_;\n  directory_t dir_{};\n\n  bool dirty_{false};\n  bool open_{false};\n  std::vector<ext_desc_rec> ext_;\n  int num_files_{0};\n};\n\nstd::string align(const std::string& file_name);\nstd::string unalign(const std::string& file_name);\n\n} // namespace wwiv::sdk::files\n\n#endif  // __INCLUDED_SDK_FILES_FILES_EXT_H__\n"
  },
  {
    "path": "sdk/files/files_ext_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"filesapi_helper.h\"\n#include \"core/datafile.h\"\n#include \"core/fake_clock.h\"\n\n\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/files/files_ext.h\"\n#include \"sdk/sdk_helper.h\"\n#include <string>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::strings;\n\n\nclass FilesExtTest : public testing::Test {\npublic:\n  FilesExtTest() : api_(helper.datadir()), api_helper_(&api_) {\n  }\n\n  void SetUp() override { helper.SetUp(); }\n\n  [[nodiscard]] std::filesystem::path path_for(const std::string& filename) const {\n    return FilePath(helper.config().datadir(), StrCat(filename, \".dir\"));\n  }\n\n  [[nodiscard]] std::vector<uploadsrec> read_dir(const std::string& filename) const {\n    DataFile<uploadsrec> file(path_for(filename));\n    if (!file) {\n      return {};\n    }\n    std::vector<uploadsrec> v;\n    if (!file.ReadVector(v)) {\n      return {};\n    }\n    return v;\n  }\n\n  SdkHelper helper;\n  FileApi api_;\n  FilesApiHelper api_helper_;\n};\n\nTEST_F(FilesExtTest, Smoke) {\n  const string name = test_info_->name();\n\n  const FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234)};\n  const std::string s1 = \"This\\r\\nIs\\r\\nF1\";\n  const FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234)};\n  const std::string s2 = \"This\\r\\nIs\\r\\nF2\";\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2});\n  ASSERT_TRUE(area);\n  ASSERT_EQ(2, area->number_of_files());\n\n  auto* e = area->ext_desc().value();\n  EXPECT_EQ(0, e->number_of_ext_descriptions());\n  EXPECT_TRUE(e->AddExtended(f1, s1));\n  EXPECT_TRUE(e->AddExtended(f2, s2));\n  EXPECT_EQ(2, e->number_of_ext_descriptions());\n\n  EXPECT_EQ(s1, e->ReadExtended(f1).value());\n  EXPECT_EQ(s2, e->ReadExtended(f2).value());\n}\n"
  },
  {
    "path": "sdk/files/files_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/datafile.h\"\n#include \"core/fake_clock.h\"\n\n\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/sdk_helper.h\"\n#include \"sdk/files/filesapi_helper.h\"\n#include <string>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::strings;\n\n\nclass FilesTest : public testing::Test {\npublic:\n  FilesTest() : api_(helper.datadir()), api_helper_(&api_) {\n    files_.emplace_back(ul(\"FILE0001.ZIP\", \"\", 1234));\n    files_.emplace_back(ul(\"FILE0002.ZIP\", \"\", 2345));\n    files_.emplace_back(ul(\"FILE0003.ZIP\", \"\", 3456));\n  }\n\n  void SetUp() override {\n    helper.SetUp();\n  }\n\n  [[nodiscard]] std::filesystem::path path_for(const std::string& filename) const {\n    return FilePath(helper.config().datadir(), StrCat(filename, \".dir\"));\n  }\n\n  [[nodiscard]] std::vector<uploadsrec> read_dir(const std::string& filename) const {\n    DataFile<uploadsrec> file(path_for(filename));\n    if (!file) {\n      return {};\n    }\n    std::vector<uploadsrec> v;\n    if (!file.ReadVector(v)) {\n      return {};\n    }\n    return v;\n  }\n\n  SdkHelper helper;\n  FileApi api_;\n  FilesApiHelper api_helper_;\n  std::vector<FileRecord> files_;\n};\n\nTEST_F(FilesTest, Smoke) {\n  const string name = test_info_->name();\n  auto area = api_helper_.CreateAndPopulate(name, {});\n  ASSERT_TRUE(area);\n  EXPECT_EQ(0, area->number_of_files());\n}\n\nTEST_F(FilesTest, Create) {\n  const string name = test_info_->name();\n\n  FileApi api(helper.datadir());\n  ASSERT_FALSE(File::Exists(path_for(name)));\n  ASSERT_TRUE(api.Create(name));\n  EXPECT_TRUE(File::Exists(path_for(name)));\n}\n\nTEST_F(FilesTest, Header) {\n  const string name = test_info_->name();\n\n  const auto dt = DateTime::now() - std::chrono::hours(1000);\n  api_.set_clock(std::make_unique<FakeClock>(dt));\n  auto area = api_helper_.CreateAndPopulate(name, {});\n  auto& h = area->header();\n  EXPECT_EQ(h.u().daten, dt.to_daten_t());\n  EXPECT_EQ(0u, h.u().numbytes);\n}\n\nTEST_F(FilesTest, Add) {\n  const string name = test_info_->name();\n  FileRecord f{ul(\"FILENAME.ZIP\", \"\", 1234)};\n  {\n    auto area = api_helper_.CreateAndPopulate(name, {f});\n    ASSERT_EQ(1, area->number_of_files());\n    area->Close();\n  }\n\n  auto cu = read_dir(name);\n  EXPECT_EQ(2, wwiv::stl::ssize(cu));\n  EXPECT_STREQ(f.u().filename, cu.at(1).filename);\n}\n\nTEST_F(FilesTest, Add_ExtendedDescription) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  auto area = api_helper_.CreateAndPopulate(name, {});\n\n  ASSERT_TRUE(area->AddFile(f1, \"Hello\"));\n  auto opos = area->FindFile(f1);\n  ASSERT_TRUE(opos);\n  auto af = area->ReadFile(opos.value());\n  EXPECT_TRUE(af.has_extended_description());\n  EXPECT_STREQ(\"Hello\", area->ReadExtendedDescriptionAsString(af).value().c_str());\n}\n\nTEST_F(FilesTest, Add_Order) {\n  const string name = test_info_->name();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2});\n  ASSERT_EQ(2, area->number_of_files());\n\n  EXPECT_EQ(area->ReadFile(1).aligned_filename(), \"FILE0002.ZIP\");\n  EXPECT_EQ(area->ReadFile(2).aligned_filename(), \"FILE0001.ZIP\");\n}\n\n\nTEST_F(FilesTest, Add_Sort_FileName_Asc) {\n  const string name = test_info_->name();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f3, f2});\n\n  ASSERT_TRUE(area->Sort(FileAreaSortType::FILENAME_ASC));\n  area->Save();\n\n  EXPECT_EQ(area->ReadFile(1).aligned_filename(), \"FILE0001.ZIP\");\n  EXPECT_EQ(area->ReadFile(2).aligned_filename(), \"FILE0002.ZIP\");\n  EXPECT_EQ(area->ReadFile(3).aligned_filename(), \"FILE0003.ZIP\");\n}\n\nTEST_F(FilesTest, Add_Sort_FileName_Desc) {\n  const string name = test_info_->name();\n\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f3, f2});\n\n  ASSERT_TRUE(area->Sort(FileAreaSortType::FILENAME_DESC));\n  EXPECT_TRUE(area->Save());\n\n  EXPECT_EQ(area->ReadFile(1).aligned_filename(), \"FILE0003.ZIP\");\n  EXPECT_EQ(area->ReadFile(2).aligned_filename(), \"FILE0002.ZIP\");\n  EXPECT_EQ(area->ReadFile(3).aligned_filename(), \"FILE0001.ZIP\");\n}\n\nTEST_F(FilesTest, Add_Sort_FileDate_Asc) {\n  const string name = test_info_->name();\n\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 100)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 200)};\n  auto area = api_helper_.CreateAndPopulate(name, {f2, f1, f3});\n\n  ASSERT_TRUE(area->Sort(FileAreaSortType::DATE_ASC));\n  EXPECT_TRUE(area->Save());\n\n  EXPECT_EQ(area->ReadFile(1).aligned_filename(), \"FILE0003.ZIP\");\n  EXPECT_EQ(area->ReadFile(2).aligned_filename(), \"FILE0002.ZIP\");\n  EXPECT_EQ(area->ReadFile(3).aligned_filename(), \"FILE0001.ZIP\");\n}\n\nTEST_F(FilesTest, Add_Sort_FileDate_Desc) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  ASSERT_TRUE(area->Sort(FileAreaSortType::DATE_DESC));\n  area->Save();\n\n  EXPECT_EQ(area->ReadFile(1).aligned_filename(), \"FILE0001.ZIP\");\n  EXPECT_EQ(area->ReadFile(2).aligned_filename(), \"FILE0003.ZIP\");\n  EXPECT_EQ(area->ReadFile(3).aligned_filename(), \"FILE0002.ZIP\");\n}\n\nTEST_F(FilesTest, DeleteFile) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  auto pos = area->FindFile(f1);\n  ASSERT_EQ(3, pos.value());\n  EXPECT_TRUE(area->DeleteFile(f1, pos.value()));\n}\n\nTEST_F(FilesTest, DeleteFile_WrongFile) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  auto pos = area->FindFile(f1);\n  EXPECT_FALSE(area->DeleteFile(f3, pos.value()));\n}\n\nTEST_F(FilesTest, DeleteFile_Ext) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  auto pos = area->FindFile(f1);\n  ASSERT_EQ(3, pos.value());\n  auto f = area->ReadFile(pos.value());\n  EXPECT_FALSE(f.has_extended_description());\n\n  EXPECT_TRUE(area->AddExtendedDescription(f, pos.value(), \"Hello\"));\n  f = area->ReadFile(pos.value());\n  EXPECT_TRUE(f.has_extended_description());\n  auto o = area->ext_desc().value()->ReadExtended(f);\n  EXPECT_TRUE(o.has_value());\n  EXPECT_STREQ(\"Hello\", o.value().c_str());\n\n  // Try to delete the wrong one\n  EXPECT_FALSE(area->DeleteExtendedDescription(f3, pos.value()));\n\n  EXPECT_TRUE(area->DeleteFile(pos.value()));\n\n  EXPECT_FALSE(area->ext_desc().value()->ReadExtended(\"FILE0001.ZIP\"));\n}\n\nTEST_F(FilesTest, DeleteExtendedDescription) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  auto pos = area->FindFile(f1);\n  EXPECT_TRUE(area->AddExtendedDescription(f1, pos.value(), \"Hello\"));\n  EXPECT_STREQ(\"Hello\", area->ext_desc().value()->ReadExtended(f1).value().c_str());\n\n  // Try to delete the wrong one\n  EXPECT_FALSE(area->DeleteExtendedDescription(f3, pos.value()));\n  // Delete the right one\n  EXPECT_TRUE(area->DeleteExtendedDescription(f1, pos.value()));\n  EXPECT_FALSE(area->ext_desc().value()->ReadExtended(f1).has_value());\n}\n\nTEST_F(FilesTest, FindFile) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  EXPECT_EQ(3, area->FindFile(f1).value());\n  EXPECT_EQ(2, area->FindFile(f2).value());\n}\n\nTEST_F(FilesTest, SearchFile) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  EXPECT_EQ(1, area->SearchFile(\"F???????.ZIP\").value());\n  EXPECT_EQ(1, area->SearchFile(\"F???????.ZIP\", 1).value());\n  EXPECT_EQ(3, area->SearchFile(\"FILE0001.ZIP\").value());\n  EXPECT_EQ(2, area->SearchFile(\"F???????.ZIP\", 2).value());\n  EXPECT_FALSE(area->SearchFile(\"F???????.ZIP\", 4).has_value());\n}\n\nTEST_F(FilesTest, UpdateFile) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  FileRecord f2{ul(\"FILE0002.ZIP\", \"\", 1234, now - 200)};\n  FileRecord f3{ul(\"FILE0003.ZIP\", \"\", 1234, now - 100)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1, f2, f3});\n\n  auto pos = area->FindFile(f1);\n  f1.set_filename(\"foo.zip\");\n  EXPECT_TRUE(area->UpdateFile(f1, pos.value()));\n\n  const auto f = area->ReadFile(pos.value());\n  EXPECT_EQ(f.aligned_filename(), \"FOO     .ZIP\");\n}\n\nTEST_F(FilesTest, Update_ExtendedDescription) {\n  const string name = test_info_->name();\n  const auto now = DateTime::now().to_daten_t();\n  FileRecord f1{ul(\"FILE0001.ZIP\", \"\", 1234, now)};\n  auto area = api_helper_.CreateAndPopulate(name, {f1});\n\n  auto opos = area->FindFile(f1);\n  const auto pos = opos.value();\n  f1.set_numbytes(4321);\n  ASSERT_TRUE(area->UpdateFile(f1, pos, \"Hello\"));\n  ASSERT_TRUE(opos);\n  auto af = area->ReadFile(opos.value());\n  EXPECT_TRUE(af.has_extended_description());\n  EXPECT_STREQ(\"Hello\", area->ReadExtendedDescriptionAsString(af).value().c_str());\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// FileRecordTest\n//\n\nTEST(FileRecordTest, Smoke) {\n  FileRecord f(ul(\"foo.bar\", \"desc\", 12345));\n\n  EXPECT_EQ(\"FOO     .BAR\", f.aligned_filename());\n  EXPECT_EQ(\"foo.bar\", f.unaligned_filename());\n}\n\nTEST(FileRecordTest, Set_FileName) {\n  FileRecord f(ul(\"foo.bar\", \"desc\", 12345));\n  ASSERT_TRUE(f.set_filename(\"bar.baz\"));\n\n  EXPECT_EQ(\"BAR     .BAZ\", f.aligned_filename());\n  EXPECT_EQ(\"bar.baz\", f.unaligned_filename());\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// FileAlignTest\n//\n\nTEST(FileAlignTest, Align) {\n  EXPECT_EQ(\"        .   \", align(\"\"));\n  EXPECT_EQ(\"X       .   \", align(\"x\"));\n  EXPECT_EQ(\"X       .Z  \", align(\"x.z\"));\n  EXPECT_EQ(\"X       .ZZ \", align(\"x.zz\"));\n  EXPECT_EQ(\"X       .ZZ \", align(\"x  x.zz\"));\n  EXPECT_EQ(\"FILENAME.ZIP\", align(\"FILENAME.ZIP\"));\n  EXPECT_EQ(\"FILENAME.ZIP\", align(\"filename.zip\"));\n}\n\nTEST(FileAlignTest, Align_WildCard) {\n  EXPECT_EQ(\"X???????.Z  \", align(\"x*.z\"));\n  EXPECT_EQ(\"X?      .Z  \", align(\"x?.z\"));\n  EXPECT_EQ(\"FILENAME.Z??\", align(\"filename.z*\"));\n  EXPECT_EQ(\"FILENAME.Z? \", align(\"filename.z?\"));\n}\n\nTEST(FileAlignTest, UnAlign) {\n  EXPECT_EQ(unalign(\"        .   \"), \"\");\n  EXPECT_EQ(unalign(\"X       .   \"), \"x\");\n  EXPECT_EQ(unalign(\"X       .Z  \"), \"x.z\");\n  EXPECT_EQ(unalign(\"X       .ZZ \"), \"x.zz\");\n  EXPECT_EQ(unalign(\"FILENAME.ZIP\"), \"filename.zip\");\n}\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// FileName\n//\n\nTEST(FileNameTest, Smoke) {\n  const FileName f(\"FOO     .BAR\");\n\n  EXPECT_EQ(\"FOO     .BAR\", f.aligned_filename());\n  EXPECT_EQ(\"foo.bar\", f.unaligned_filename());\n  EXPECT_EQ(\"FOO\", f.basename());\n  EXPECT_EQ(\"BAR\", f.extension());\n}"
  },
  {
    "path": "sdk/files/filesapi_helper.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_TEST_FILES_FILESAPI_HELPER_H__\n#define __INCLUDED_SDK_TEST_FILES_FILESAPI_HELPER_H__\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/files/files.h\"\n#include \"sdk/files/files_ext.h\"\n\ninline uploadsrec ul(const std::string& fn, const std::string& desc, uint32_t size, daten_t daten) {\n  uploadsrec u{};\n  wwiv::strings::to_char_array(u.filename, wwiv::sdk::files::align(fn));\n  wwiv::strings::to_char_array(u.description, desc);\n  u.numbytes = size;\n  u.daten = daten;\n  return u;\n}\n\ninline uploadsrec ul(const std::string& fn, const std::string& desc, uint32_t size) {\n  const auto now = wwiv::core::DateTime::now();\n  return ul(fn, desc, size, now.to_daten_t());\n}\n\nclass FilesApiHelper {\npublic:\n  explicit FilesApiHelper(wwiv::sdk::files::FileApi* api) : api_(api) {}\n  ~FilesApiHelper() = default;\n\n  std::unique_ptr<wwiv::sdk::files::FileArea> CreateAndPopulate(const std::string& name,\n                                                                const std::initializer_list<wwiv::sdk::files::FileRecord> files) {\n\n    if (api_->Exist(name)) {\n      LOG(ERROR) << \"Area '\" << name << \"' already exists\";\n      return {};\n    }\n    if(!api_->Create(name)) {\n      LOG(ERROR) << \"Failed to create area: '\" << name << \"'\";\n      return {};\n    }\n    auto area = api_->Open(name);\n    if (!area) {\n      LOG(ERROR) << \"Failed to open area: '\" << name << \"'\";\n      return {};\n    }\n\n    for (const auto& f : files) {\n      area->AddFile(f);\n    }\n    area->Save();\n    return area;\n  }\n\nprivate:\n  wwiv::sdk::files::FileApi* api_;\n};\n\n#endif  // __INCLUDED_SDK_TEST_FILES_FILESAPI_HELPER_H__\n"
  },
  {
    "path": "sdk/files/tic.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/tic.h\"\n\n#include \"core/crc32.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk::files {\n\nTic::Tic(std::filesystem::path path)\n    : path_(std::move(path)), valid_(false) {\n}\n\nbool Tic::IsValid() const {\n  return valid_ && exists() && crc_valid() && size_valid();\n}\n\nbool Tic::crc_valid() const {\n  const auto actual_int = wwiv::core::crc32file(fpath());\n  const auto actual = fmt::sprintf(\"%8.8x\", actual_int);\n\n  const auto crc_valid = iequals(crc, actual);\n  if (!crc_valid) {\n    LOG(INFO) << \"CRC: actual: \" << actual << \"; expected: \" << crc;\n  }\n  return crc_valid;\n}\n\nbool Tic::size_valid() const {\n  const File f(fpath());\n  const int actual_size = static_cast<int>(f.length());\n  if (actual_size != size()) {\n    LOG(INFO) << \"Tic FileSize !valid. actual: \" << actual_size << \"; expected: \" << size();\n    return false;\n  }\n  return true;\n}\n\nbool Tic::exists() const {\n  return File::Exists(fpath());\n}\n\nint Tic::size() const {\n  if (size_ != 0) {\n    return size_;\n  }\n  const File f(fpath());\n  return static_cast<int>(f.length());\n}\n\ncore::DateTime Tic::date() const {\n  if (date_.to_time_t() == 0) {\n    const auto t = File::last_write_time(fpath());\n    return DateTime::from_time_t(t);\n  }\n  return date_;\n}\n\nstd::filesystem::path Tic::fpath() const {\n  auto fp = FilePath(path_.parent_path(), file);\n  return fp;\n}\n\nTicParser::TicParser(std::filesystem::path dir) : dir_(std::move(dir)) {}\n\nstatic std::tuple<std::string, std::string, bool> split_tic_line(const std::string& line) {\n  const auto idx = line.find_first_of(\" \\t\");\n  if (idx == std::string::npos) {\n    return std::make_tuple(\"\", \"\", true);\n  }\n  const auto keyword = StringTrimEnd(ToStringLowerCase(line.substr(0, idx)));\n  const auto params = StringTrim(line.substr(idx + 1));\n  return std::make_tuple(keyword, params, false);\n}\n\nstd::optional<Tic> TicParser::parse(const std::string& filename) const {\n  TextFile f(FilePath(dir_, filename), \"rt\");\n  if (!f) {\n    return std::nullopt;\n  }\n  const auto lines = f.ReadFileIntoVector();\n  return parse(filename, lines);\n}\n\nstd::optional<Tic> TicParser::parse(const std::string& filename, const std::vector<std::string>& lines) const {\n  const auto p = FilePath(dir_, filename);\n  Tic t(p);\n\n  for (const auto& l : lines) {\n    auto [keyword, params, error] = split_tic_line(l);\n    if (error) {\n      continue;\n    }\n    if (keyword == \"area\") {\n      t.area = params;\n    } else if (keyword == \"areadesc\") {\n      t.area_description = params;\n    } else if (keyword == \"origin\") {\n      if (const auto o = fido::try_parse_fidoaddr(params, fido::fidoaddr_parse_t::lax)) {\n        t.origin = o.value();\n      } else {\n        LOG(WARNING) << \"Unable to parse 'origin' from : '\" << params << \"'\";\n      }\n    } else if (keyword == \"from\") {\n      if (const auto o = fido::try_parse_fidoaddr(params, fido::fidoaddr_parse_t::lax)) {\n        t.from = o.value();\n      } else {\n        LOG(WARNING) << \"Unable to parse 'from' from : '\" << params << \"'\";\n      }\n    } else if (keyword == \"to\") {\n      if (const auto o = fido::try_parse_fidoaddr(params, fido::fidoaddr_parse_t::lax)) {\n        t.to = o.value();\n      } else {\n        LOG(WARNING) << \"Unable to parse 'to' from : '\" << params << \"'\";\n      }\n    } else if (keyword == \"file\") {\n      t.file = params;\n    } else if (keyword == \"lfile\" || keyword == \"fullname\") {\n      t.lfile = params;\n    } else if (keyword == \"size\") {\n      t.size_ = to_number<int>(params);\n    } else if (keyword == \"date\") {\n      const auto dtt = to_number<time_t>(params);\n      t.date_ = DateTime::from_time_t(dtt);\n    } else if (keyword == \"desc\") {\n      t.desc = params;\n    } else if (keyword == \"ldesc\") {\n      t.ldesc.push_back(params);\n    } else if (keyword == \"created\") {\n      t.created = params;\n    } else if (keyword == \"magic\") {\n      t.magic = params;\n    } else if (keyword == \"replaces\") {\n      t.replaces = params;\n    } else if (keyword == \"crc\") {\n      t.crc = params;\n    } else if (keyword == \"path\") {\n      // TODO(rushfan): Path and seenby are blocks like key path, numerous seen-by items for/\n      // that path.\n      t.ftn_path = params;\n    } else if (keyword == \"seenby\") {\n      t.seen_by = params;\n    } else if (keyword == \"pw\") {\n      t.pw = params;\n    }\n  }\n  t.valid_ = true;\n  return {t};\n}\n\nstd::optional<directory_t> FindFileAreaForTic(const files::Dirs& dirs, const Tic& tic,\n                                              const Network& net) {\n  const auto area_tag = tic.area;\n  for (const auto& d : dirs.dirs()) {\n    for (const auto& dt : d.area_tags) {\n      VLOG(3) << \"Checking area: '\" << dt.area_tag << \"'\";\n      if (iequals(area_tag, dt.area_tag)) {\n        VLOG(3) << \"Found matching area, checking UUID for area: '\" << dt.net_uuid << \"'\";\n        if (dt.net_uuid == net.uuid) {\n          return {d};\n        }\n        VLOG(1) << \"UUID didn't match: [dir] \" << dt.net_uuid << \" != [net]:  \" << net.uuid;\n      }\n    }\n  }\n  return std::nullopt;\n}\n\n} // namespace wwiv::sdk::files\n"
  },
  {
    "path": "sdk/files/tic.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FILES_TIC_H\n#define INCLUDED_SDK_FILES_TIC_H\n\n#include \"core/datetime.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/files/dirs.h\"\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::net {\nclass Network;\n}\n\nnamespace wwiv::sdk::files {\n\nclass Tic {\npublic:\n  explicit Tic(std::filesystem::path path);\n  Tic() = delete;\n  ~Tic() = default;\n\n  // True if everything is valid (file exists, PW correct, and CRC matches)\n  [[nodiscard]] bool IsValid() const;\n  [[nodiscard]] bool crc_valid() const;\n  [[nodiscard]] bool size_valid() const;\n  [[nodiscard]] bool exists() const;\n  [[nodiscard]] int size() const;\n  [[nodiscard]] core::DateTime date() const;\n  [[nodiscard]] std::filesystem::path fpath() const;\n\n  std::string area;\n  std::string area_description;\n  fido::FidoAddress origin;\n  fido::FidoAddress from;\n  fido::FidoAddress to;\n  std::string file;\n  std::string lfile;\n  core::DateTime date_;\n  std::string desc;\n  std::vector<std::string> ldesc;\n  std::string created;\n  std::string magic;\n  std::string replaces;\n  std::string crc;\n  std::string ftn_path;\n  std::string seen_by;\n  std::string pw;\nprivate:\n  std::filesystem::path path_;\n  bool valid_;\n  int size_{};\n  friend class TicParser;\n};  // class\n\nclass TicParser {\npublic:\n  explicit TicParser(std::filesystem::path dir);\n  [[nodiscard]] std::optional<Tic> parse(const std::string& filename) const;\n  [[nodiscard]] std::optional<Tic> parse(const std::string& filename, const std::vector<std::string>& lines) const;\n\nprivate:\n\n  const std::filesystem::path dir_;\n};\n\n// Helper classes\n\nstd::optional<directory_t> FindFileAreaForTic(const files::Dirs& dirs, const Tic& tic,\n                                              const sdk::net::Network& net);\n\n} \n\n#endif\n"
  },
  {
    "path": "sdk/files/tic_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/files/tic.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::net;\n\nTEST(TicTest, Smoke) {\n  wwiv::core::test::FileHelper helper;\n\n  const std::string kFSXINFO = R\"(\nCreated by HTick, written by Gabriel Plutzar\nFile fsxinfo.zip\nArea fsx_info\nAreadesc Weekly Infopacks (fsxNet, etc.)\nDesc Weekly infopack for fsxNet\nLDesc             ���              ���\nLDesc         ���߰�� �ܰ�߰�� ��� ���\nLDesc     �   ��� ۰��۰������ܰ�� ۰� net �\nLDesc  �����  ��� ��� ���  �۰ ��߲���  �����\nLDesc  �  ��  �����   ���  ��� ����۰�  ��� �\nLDesc  � ���� ���     �۰� ��� ��� �۰ ���  �\nLDesc  � ���� ���     �������  ��� ���  �   �\nLDesc  � ��           ���           ��      �\nLDesc  � �  fsxnet.txt  -- Info & App       �\nLDesc  � �  fsxnet.xxx  -- Nodelist         �\nLDesc  �    fsxnet.zaa  -- Nodelist (ZIP)   �\nLDesc  � �  history.txt -- History          �\nLDesc  �    systems.txt -- BBS in fsxNet    �\nLDesc  �    fsxnet.na   -- Echo list        �\nLDesc  �    fsx_file.na -- File echo list   �\nLDesc  � �                                  �\nLDesc  � ��                    ��� infopack �\nLDesc  �������������������������ܱ�����������\nReplaces fsxinfo.zip\nFrom 21:2/100\nTo 21:2/115\nOrigin 21:1/1\nSize 12\nCrc AF083B2D\nPath 21:1/1 1591287303 Thu Jun 04 16:15:03 2020 UTC htick/w32-mvcdll 1.9.0-cur 17-08-15\nSeenby 21:1/1\nSeenby 21:1/2\nPw WELCOME\nPath 21:1/100 1591287395 Thu Jun 04 16:16:35 2020 UTC Mystic/1.12 A46\nSeenby 21:1/100\nSeenby 21:1/101\nSeenby 21:1/151\nPath 21:2/100 1591287460 Thu Jun 04 16:17:40 2020 UTC Mystic/1.12 A46\n  )\";\n\n  const auto file = helper.CreateTempFile(\"fsxinfo.tic\", kFSXINFO);\n  const auto arc_path = wwiv::core::FilePath(helper.TempDir(), \"fsxinfo.zip\");\n  {\n    File af(arc_path);\n    ASSERT_TRUE(af.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite));\n    ASSERT_EQ(12, af.Write(\"hello world\\n\"));\n    af.Close();\n  }\n\n  wwiv::sdk::files::TicParser p(file.parent_path());\n  auto o = p.parse(\"fsxinfo.tic\");\n  ASSERT_TRUE(o);\n\n  auto t = o.value();\n  EXPECT_EQ(t.area, \"fsx_info\");\n  EXPECT_EQ(18u, t.ldesc.size());\n  EXPECT_EQ(\"Weekly infopack for fsxNet\", t.desc);\n  EXPECT_EQ(\"fsxinfo.zip\", t.file);\n  EXPECT_EQ(\"fsxinfo.zip\", t.replaces);\n  EXPECT_TRUE(t.exists());\n  EXPECT_TRUE(t.crc_valid());\n  EXPECT_TRUE(t.size_valid());\n  EXPECT_TRUE(t.IsValid());\n}\n\n\nTEST(TicTest, Malformed_Addresses) {\n  wwiv::core::test::FileHelper helper;\n\n  const std::string kFSXINFO = R\"(\nCreated by PXTIC/Win v7.0 (c) 2018 Santronics\nArea [HNET] INFO\nOrigin Me, 954:895/1\nFrom Me, 954:895/1\nTo Morgul, 954:895/5\nFile HOBBYNET.ZIP\n  )\";\n\n  const auto file = helper.CreateTempFile(\"HOBBYNET.tic\", kFSXINFO);\n\n  wwiv::sdk::files::TicParser p(file.parent_path());\n  auto o = p.parse(\"HOBBYNET.tic\");\n  ASSERT_TRUE(o);\n\n  const auto& t = o.value();\n  EXPECT_EQ(\"954:895/5\", t.to.as_string(false, false));\n  EXPECT_EQ(\"954:895/1\", t.origin.as_string(false, false));\n  EXPECT_EQ(\"954:895/1\", t.from.as_string(false, false));\n}\n\nTEST(TicTest, FindFileAreaForTic) {\n  wwiv::core::test::FileHelper helper;\n\n  const std::string contents = R\"(\nArea AREANAME\nSize 12\nCrc AF083B2D\nFile sample.zip\n)\";\n  const auto tic_path = helper.CreateTempFile(\"sample.tic\", contents);\n  const auto arc_path = wwiv::core::FilePath(helper.TempDir(), \"sample.zip\");\n  {\n    File af(arc_path);\n    ASSERT_TRUE(af.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite));\n    ASSERT_EQ(12, af.Write(\"hello world\\n\"));\n    af.Close();\n  }\n\n  const auto data = helper.Dir(\"data\");\n  std::random_device rd{};\n  wwiv::core::uuid_generator generator(rd);\n  auto uuid = generator.generate();\n\n  Network net{};\n  net.name = \"foo\";\n  net.uuid = uuid;\n\n  wwiv::sdk::files::dir_area_t dt;\n  dt.net_uuid = uuid;\n  dt.area_tag = \"AREANAME\";\n  wwiv::sdk::files::directory_t dir;\n  dir.area_tags.emplace_back(dt);\n  dir.name = \"d1\";\n\n  wwiv::sdk::files::Dirs dirs(data, 0);\n  dirs.set_dirs({dir});\n\n  wwiv::sdk::files::TicParser p(tic_path.parent_path());\n  auto ot = p.parse(\"sample.tic\");\n  ASSERT_TRUE(ot);\n  auto tic = ot.value();\n\n  auto o = wwiv::sdk::files::FindFileAreaForTic(dirs, tic, net);\n  ASSERT_TRUE(o.has_value());\n  auto area = o.value();\n  EXPECT_EQ(dir.name, \"d1\");\n}\n\nTEST(TicTest, FindFileAreaForTic_NotFound) {\n  wwiv::core::test::FileHelper helper;\n\n  const std::string contents = R\"(\nArea AREANAME\nSize 12\nCrc AF083B2D\nFile sample.zip\n)\";\n  const auto tic_path = helper.CreateTempFile(\"sample.tic\", contents);\n  const auto arc_path = wwiv::core::FilePath(helper.TempDir(), \"sample.zip\");\n  {\n    File af(arc_path);\n    ASSERT_TRUE(af.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite));\n    ASSERT_EQ(12, af.Write(\"hello world\\n\"));\n    af.Close();\n  }\n\n  const auto data = helper.Dir(\"data\");\n  std::random_device rd{};\n  wwiv::core::uuid_generator generator(rd);\n  auto uuid = generator.generate();\n\n  Network net{};\n  net.name = \"foo\";\n  net.uuid = uuid;\n\n  wwiv::sdk::files::dir_area_t dt;\n  dt.net_uuid = uuid;\n  dt.area_tag = \"2REANAME\";\n  wwiv::sdk::files::directory_t dir;\n  dir.area_tags.emplace_back(dt);\n  dir.name = \"d1\";\n\n  wwiv::sdk::files::Dirs dirs(data, 0);\n  dirs.set_dirs({dir});\n\n  wwiv::sdk::files::TicParser p(tic_path.parent_path());\n  auto ot = p.parse(\"sample.tic\");\n  ASSERT_TRUE(ot);\n  auto tic = ot.value();\n\n  auto o = wwiv::sdk::files::FindFileAreaForTic(dirs, tic, net);\n  ASSERT_FALSE(o.has_value());\n}\n"
  },
  {
    "path": "sdk/gfiles.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/gfiles.h\"\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/archives/json.hpp>\n#include <cereal/types/memory.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/gfiles_cereal.h\"\n\n#include \"core/cereal_utils.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/acs/expr.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include <string>\n#include <utility>\n#include <vector>\n\nusing cereal::make_nvp;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n#pragma pack(push, 1)\n\nstruct gfiledirrec {\n  char name[41],   // g-file section name\n      filename[9]; // g-file database filename\n\n  uint8_t sl, // sl required to read\n      age;    // minimum age for section\n\n  uint16_t maxfiles, // max # of files\n      ar;            // AR for g-file section\n};\n\nstruct gfilerec {\n  char description[81], // description of file\n      filename[13];     // filename of file\n\n  daten_t daten; // date added\n};\n\nstatic_assert(sizeof(gfilerec) == 98, \"gfilerec == 98\");\nstatic_assert(sizeof(gfiledirrec) == 56, \"gfiledirrec == 56\");\n\n#pragma pack(pop)\n\nnamespace wwiv::sdk {\n\nbool GFiles::LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                          std::vector<gfile_dir_t>& entries) {\n  entries.clear();\n  JsonFile f(FilePath(dir, filename), \"gfiles\", entries, 1);\n  return f.Load();\n}\n\nbool GFiles::SaveToJSON(const std::filesystem::path& dir, const std::string& filename,\n                        const std::vector<gfile_dir_t>& entries) {\n  const auto path = FilePath(dir, filename);\n  backup_file(path, max_backups_);\n  JsonFile f(path, \"gfiles\", entries, 1);\n  return f.Save();\n}\n\nbool GFiles::set_dirs(const std::vector<gfile_dir_t>& dirs) {\n  dirs_ = dirs;\n  return true;\n}\n\nGFiles::GFiles(std::filesystem::path datadir, int max_backups)\n    : datadir_(std::move(datadir)), max_backups_(max_backups){};\n\nGFiles::~GFiles() = default;\n\nbool GFiles::LoadLegacy() {\n  std::vector<gfiledirrec> gfilesec;\n  if (DataFile<gfiledirrec> file(FilePath(datadir_, GFILE_DAT)); file) {\n    file.ReadVector(gfilesec);\n  }\n  for (const auto& o : gfilesec) {\n    gfile_dir_t gf{};\n    gf.name = o.name;\n    gf.filename = o.filename;\n    gf.maxfiles = o.maxfiles;\n    acs::AcsExpr ae;\n    gf.acs = ae.min_sl(o.sl).min_age(o.age).ar_int(o.ar).get();\n\n    const auto gfl_file_name = StrCat(gf.filename, \".gfl\");\n    const auto gfl_path = FilePath(datadir_, gfl_file_name);\n    if (DataFile<gfilerec> gfile(gfl_path); gfile) {\n      if (std::vector<gfilerec> files; gfile.ReadVector(files)) {\n        for (const auto& of : files) {\n          gfile_t f{};\n          f.filename = of.filename;\n          f.daten = of.daten;\n          f.description = of.description;\n          gf.files.emplace_back(f);\n        }\n      }\n    }\n    dirs_.emplace_back(gf);\n  }\n  return true;\n}\n\nbool GFiles::Load() {\n  const auto json_path = FilePath(datadir_, \"gfiles.json\");\n  const auto legacy_path = FilePath(datadir_, GFILE_DAT);\n  if (!File::Exists(json_path) && File::Exists(legacy_path)) {\n    const auto loaded = LoadLegacy();\n    if (loaded) {\n      return Save();\n    }\n    return false;\n  }\n  return LoadFromJSON(datadir_, \"gfiles.json\", dirs_);\n}\n\nbool GFiles::Save() { return SaveToJSON(datadir_, \"gfiles.json\", dirs_); }\n\nbool GFiles::insert(int n, gfile_dir_t r) { return insert_at(dirs_, n, r); }\n\nbool GFiles::erase(int n) { return erase_at(dirs_, n); }\n\nconst gfile_dir_t& GFiles::dir(const std::string& filename) const {\n  for (const auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find dir of filename: \", filename));\n}\n\ngfile_dir_t& GFiles::dir(const std::string& filename) {\n  for (auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find dir of filename: \", filename));\n}\n\nbool GFiles::exists(const std::string& filename) const {\n  for (const auto& n : dirs_) {\n    if (iequals(filename, n.filename)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/gfiles.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_GFILES_H\n#define INCLUDED_SDK_GFILES_H\n\n#include \"core/stl.h\"\n#include <filesystem>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk {\n\nstruct gfile_t {\n  // description of file\n  std::string description;\n  // filename of file\n  std::string filename;\n  // date added\n  daten_t daten;\n};\n\nstruct gfile_dir_t {\n  // g-file section name\n  std::string name;\n  // g-file database filename\n  std::string filename;\n  // ACS for accessing this area.\n  std::string acs;\n  // max files for directory\n  int maxfiles{500};\n  // The gfiles for this area.\n  std::vector<gfile_t> files;\n};\n\n\nclass GFiles final {\npublic:\n  typedef gfile_dir_t& reference;\n  typedef const gfile_dir_t& const_reference;\n  explicit GFiles(std::filesystem::path datadir, int max_backups);\n  ~GFiles();\n\n  bool LoadLegacy();\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] const gfile_dir_t& dir(std::size_t n) const { return stl::at(dirs_, n); }\n  [[nodiscard]] const gfile_dir_t& dir(const std::string& filename) const;\n  gfile_dir_t& dir(std::size_t n) { return dirs_[n]; }\n  gfile_dir_t& dir(const std::string& filename);\n\n  const gfile_dir_t& operator[](std::size_t n) const { return dir(n); }\n  const gfile_dir_t& operator[](const std::string& filename) const { return dir(filename); }\n  gfile_dir_t& operator[](std::size_t n) { return dir(n); }\n  gfile_dir_t& operator[](const std::string& filename) { return dir(filename); }\n\n  [[nodiscard]] bool exists(const std::string& filename) const;\n\n  void set_dir(int n, gfile_dir_t s) { dirs_[n] = std::move(s); }\n  [[nodiscard]] const std::vector<gfile_dir_t>& dirs() const { return dirs_; }\n  bool insert(int n, gfile_dir_t r);\n  bool erase(int n);\n  [[nodiscard]] int size() const { return stl::size_int(dirs_); }\n\n  static bool LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                           std::vector<gfile_dir_t>& entries);\n  bool SaveToJSON(const std::filesystem::path& dir, const std::string& filename,\n                  const std::vector<gfile_dir_t>& entries);\n\n  bool set_dirs(const std::vector<gfile_dir_t>& dirs);\n\nprivate:\n  const std::filesystem::path datadir_;\n  const int max_backups_;\n  std::vector<gfile_dir_t> dirs_;\n};\n\n} // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/gfiles_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_GFILES_CEREAL_H\n#define INCLUDED_SDK_GFILES_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/gfiles.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/conf/conf_set_cereal.h\"\n\nnamespace wwiv::sdk {\n\n\ntemplate <class Archive>\nvoid serialize (Archive& ar, gfile_t& d) {\n  SERIALIZE(d, filename);\n  SERIALIZE(d, daten);\n  SERIALIZE(d, description);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, gfile_dir_t& s) {\n  SERIALIZE(s, name);\n  SERIALIZE(s, filename);\n  SERIALIZE(s, acs);\n  SERIALIZE(s, maxfiles);\n  SERIALIZE(s, files);\n}\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/instance.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/instance.h\"\n\n\n#include \"bbs/instmsg.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/dirs.h\"\n\n#include <algorithm>\n#include <filesystem>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nconst std::filesystem::path& Instances::fn_path() const {\n  return path_;\n}\n\nInstance::Instance(std::filesystem::path root_dir, std::filesystem::path data_dir, instancerec ir)\n  : root_dir_(root_dir), data_dir_(data_dir), ir_(ir) {\n}\n\nInstance::Instance(std::filesystem::path root_dir, std::filesystem::path data_dir, int instance_num)\n    : root_dir_(root_dir), data_dir_(data_dir), ir_() {\n  ir_.number = static_cast<int16_t>(instance_num);\n}\n\nInstance::Instance(Instance&& o) noexcept : root_dir_(o.root_dir_), data_dir_(o.data_dir_), ir_(o.ir_) {}\n\nInstance& Instance::operator=(const Instance& o) {\n  data_dir_ = o.data_dir_;\n  root_dir_ = o.root_dir_;\n  ir_ = o.ir_;\n  return *this;\n}\n  \n//Instance& Instance::operator=(Instance&& o) noexcept {\n//  data_dir_ = o.data_dir_;\n//  ir_ = o.ir_;\n//  return *this;\n//}\n\nconst instancerec& Instance::ir() const {\n  return ir_;\n}\n\ninstancerec& Instance::ir() {\n  return ir_;\n}\n\nstd::filesystem::path Instance::root_directory() const {\n  return root_dir_;\n}\n\nint Instance::node_number() const noexcept {\n  return ir_.number;\n}\n\nint Instance::user_number() const noexcept {\n  return ir_.user;\n}\n\nbool Instance::available() const noexcept {\n  return online() && ir_.flags & INST_FLAGS_MSG_AVAIL;\n}\n\nbool Instance::online() const noexcept {\n return ir_.flags & INST_FLAGS_ONLINE;\n}\n\nbool Instance::invisible() const noexcept {\n return ir_.flags & INST_FLAGS_INVIS;\n}\n\nstd::string Instance::location_description() const {\n  if (ir_.loc >= INST_LOC_CH1 && ir_.loc <= INST_LOC_CH10) {\n    return \"WWIV Chatroom\";\n  }\n  switch (ir_.loc) {\n  case INST_LOC_DOWN:\n    return \"Offline\";\n  case INST_LOC_INIT:\n    return \"Initializing BBS\";\n  case INST_LOC_EMAIL:\n    return \"Sending Email\";\n  case INST_LOC_MAIN:\n    return \"Main Menu\";\n  case INST_LOC_XFER: {\n    wwiv::sdk::files::Dirs dirs(data_dir_, 0);\n    if (dirs.Load()) {\n      if (ir_.subloc < dirs.size()) {\n        return fmt::format(\"Transfer Area: Dir : {}\", stripcolors(dirs[ir_.subloc].name));\n      }\n    }\n    return \"Transfer Area\";\n  }\n  case INST_LOC_CHAINS: {\n    Chains chains(data_dir_);\n    if (chains.Load()) {\n      if (ir_.subloc > 0 && ir_.subloc <= chains.size()) {\n        const auto& c = chains.at(ir_.subloc - 1);\n        return fmt::format(\"Chains: Door: {}\", stripcolors(c.description));\n      }\n    }\n  }\n  return \"Chains\";\n  case INST_LOC_NET:\n    return \"Network Transmission\";\n  case INST_LOC_GFILES:\n    return \"GFiles\";\n  case INST_LOC_BEGINDAY:\n    return \"Running BeginDay\";\n  case INST_LOC_EVENT:\n    return \"Executing Event\";\n  case INST_LOC_CHAT:\n    return \"Normal Chat\";\n  case INST_LOC_CHAT2:\n    return \"SplitScreen Chat\";\n  case INST_LOC_CHATROOM:\n    return \"ChatRoom\";\n  case INST_LOC_LOGON:\n    return \"Logging On\";\n  case INST_LOC_LOGOFF:\n    return \"Logging off\";\n  case INST_LOC_FSED:\n    return \"FullScreen Editor\";\n  case INST_LOC_UEDIT:\n    return \"In UEDIT\";\n  case INST_LOC_CHAINEDIT:\n    return \"In CHAINEDIT\";\n  case INST_LOC_BOARDEDIT:\n    return \"In BOARDEDIT\";\n  case INST_LOC_DIREDIT:\n    return \"In DIREDIT\";\n  case INST_LOC_GFILEEDIT:\n    return \"In GFILEEDIT\";\n  case INST_LOC_CONFEDIT:\n    return \"In CONFEDIT\";\n  case INST_LOC_DOS:\n    return \"In DOS\";\n  case INST_LOC_DEFAULTS:\n    return \"In Defaults\";\n  case INST_LOC_REBOOT:\n    return \"Rebooting\";\n  case INST_LOC_RELOAD:\n    return \"Reloading BBS data\";\n  case INST_LOC_VOTE:\n    return \"Voting\";\n  case INST_LOC_BANK:\n    return \"In TimeBank\";\n  case INST_LOC_AMSG:\n    return \"AutoMessage\";\n  case INST_LOC_SUBS: {\n    std::vector<net::Network> nets;\n    Subs subs(data_dir_, nets, 0);\n    if (subs.Load()) {\n      if (ir_.subloc < subs.size()) {\n        return fmt::format(\"Reading Messages: (Sub: {})\", stripcolors(subs.sub(ir_.subloc).name));\n      }\n    }\n  }\n  return \"Reading Messages\";\n  case INST_LOC_CHUSER:\n    return \"Changing User\";\n  case INST_LOC_TEDIT:\n    return \"In TEDIT\";\n  case INST_LOC_MAILR:\n    return \"Reading All Mail\";\n  case INST_LOC_RESETQSCAN:\n    return \"Resetting QSCAN pointers\";\n  case INST_LOC_VOTEEDIT:\n    return \"In VOTEEDIT\";\n  case INST_LOC_VOTEPRINT:\n    return \"Printing Voting Data\";\n  case INST_LOC_RESETF:\n    return \"Resetting NAMES.LST\";\n  case INST_LOC_FEEDBACK:\n    return \"Leaving Feedback\";\n  case INST_LOC_KILLEMAIL:\n    return \"Viewing Old Email\";\n  case INST_LOC_POST: {\n    std::vector<net::Network> nets;\n    Subs subs(data_dir_, nets, 0);\n    if (subs.Load()) {\n      if (ir_.subloc < subs.size()) {\n        return fmt::format(\"Posting a Message: (Sub: {})\", stripcolors(subs.sub(ir_.subloc).name));\n      }\n    }\n  }\n  return \"Posting a Message\";\n  case INST_LOC_NEWUSER:\n    return \"Registering a Newuser\";\n  case INST_LOC_RMAIL:\n    return \"Reading Email\";\n  case INST_LOC_DOWNLOAD:\n    return \"Downloading\";\n  case INST_LOC_UPLOAD:\n    return \"Uploading\";\n  case INST_LOC_BIXFER:\n    return \"Bi-directional Transfer\";\n  case INST_LOC_NETLIST:\n    return \"Listing Net Info\";\n  case INST_LOC_TERM:\n    return \"In a terminal program\";\n  case INST_LOC_GETUSER:\n    return \"Getting User ID\";\n  case INST_LOC_WFC:\n    return \"Waiting for Call\";\n  case INST_LOC_QWK:\n    return \"In QWK\";\n  }\n  return \"Unknown BBS Location!\";\n}\n\nint Instance::loc_code() const noexcept {\n  return ir_.loc;\n}\n\nbool Instance::in_channel() const noexcept {\n  return ir_.loc >= INST_LOC_CH1 && ir_.loc <= INST_LOC_CH10;\n}\n\nint Instance::modem_speed() const noexcept {\n  return ir_.modem_speed;\n}\n\nint Instance::subloc_code() const noexcept {\n  return ir_.subloc;\n}\n\nDateTime Instance::started() const {\n  return DateTime::from_daten(ir_.inst_started);\n}\n\nDateTime Instance::updated() const {\n  return DateTime::from_daten(ir_.last_update);\n}\n\nInstances::Instances(const Config& config)\n    : path_(FilePath(config.datadir(), INSTANCE_DAT)), root_dir_(config.root_directory()),\n      data_dir_(config.datadir()) {\n  initialized_ = File::Exists(path_);\n  instances_ = all();\n}\n\nInstances::size_type Instances::size() const {\n  if (const auto file = DataFile<instancerec>(path_, File::modeBinary | File::modeReadOnly)) {\n    return std::max<int>(0, file.number_of_records() - 1);\n  }\n  return 0;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nInstance Instances::at(size_type pos) {\n  if (auto file = DataFile<instancerec>(path_, File::modeBinary | File::modeReadOnly)) {\n    instancerec ir{};\n    if (file.Read(pos, &ir)) {\n      return Instance(root_dir_, data_dir_, ir);\n    }\n  }\n  return Instance(root_dir_, data_dir_, pos);\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nstd::vector<Instance> Instances::all() {\n  if (auto file = DataFile<instancerec>(path_, File::modeBinary | File::modeReadOnly)) {\n    std::vector<instancerec> ir;\n    if (file.ReadVector(ir)) {\n      std::vector<Instance> r;\n      for (const auto& i : ir) {\n        r.emplace_back(root_dir_, data_dir_, i);\n      }\n      return r;\n    }\n  }\n  return {};\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool Instances::upsert(size_type pos, const instancerec& ir) {\n  instancerec mir{ ir };\n  mir.last_update = daten_t_now();\n  if (auto file = DataFile<instancerec>(path_, File::modeBinary | File::modeReadWrite |\n                                                   File::modeCreateFile)) {\n    return file.Write(pos, &mir);\n  }\n  return false;\n}\n\nbool Instances::upsert(size_type pos, const Instance& ir) {\n  return upsert(pos, ir.ir());\n}\n\n}\n"
  },
  {
    "path": "sdk/instance.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_INSTANCE_H\n#define INCLUDED_SDK_INSTANCE_H\n\n#include \"core/datetime.h\"\n\n#include \"sdk/config.h\"\n#include \"sdk/vardec.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\n  // (moved from vardec.h)\n\n  /* Instance status flags */\n  constexpr int INST_FLAGS_NONE = 0x0000;  // No flags at all\n  constexpr int INST_FLAGS_ONLINE = 0x0001;  // User online\n  constexpr int INST_FLAGS_MSG_AVAIL = 0x0002;  // Available for inst msgs\n  constexpr int INST_FLAGS_INVIS = 0x0004;  // For invisibility\n\n  /* Instance primary location points */\n  constexpr int INST_LOC_DOWN = 0;\n  constexpr int INST_LOC_INIT = 1;\n  constexpr int INST_LOC_EMAIL = 2;\n  constexpr int INST_LOC_MAIN = 3;\n  constexpr int INST_LOC_XFER = 4;\n  constexpr int INST_LOC_CHAINS = 5;\n  constexpr int INST_LOC_NET = 6;\n  constexpr int INST_LOC_GFILES = 7;\n  constexpr int INST_LOC_BEGINDAY = 8;\n  constexpr int INST_LOC_EVENT = 9;\n  constexpr int INST_LOC_CHAT = 10;\n  constexpr int INST_LOC_CHAT2 = 11;\n  constexpr int INST_LOC_CHATROOM = 12;\n  constexpr int INST_LOC_LOGON = 13;\n  constexpr int INST_LOC_LOGOFF = 14;\n  constexpr int INST_LOC_FSED = 15;\n  constexpr int INST_LOC_UEDIT = 16;\n  constexpr int INST_LOC_CHAINEDIT = 17;\n  constexpr int INST_LOC_BOARDEDIT = 18;\n  constexpr int INST_LOC_DIREDIT = 19;\n  constexpr int INST_LOC_GFILEEDIT = 20;\n  constexpr int INST_LOC_CONFEDIT = 21;\n  constexpr int INST_LOC_DOS = 22;\n  constexpr int INST_LOC_DEFAULTS = 23;\n  constexpr int INST_LOC_REBOOT = 24;\n  constexpr int INST_LOC_RELOAD = 25;\n  constexpr int INST_LOC_VOTE = 26;\n  constexpr int INST_LOC_BANK = 27;\n  constexpr int INST_LOC_AMSG = 28;\n  constexpr int INST_LOC_SUBS = 29;\n  constexpr int INST_LOC_CHUSER = 30;\n  constexpr int INST_LOC_TEDIT = 31;\n  constexpr int INST_LOC_MAILR = 32;\n  constexpr int INST_LOC_RESETQSCAN = 33;\n  constexpr int INST_LOC_VOTEEDIT = 34;\n  constexpr int INST_LOC_VOTEPRINT = 35;\n  constexpr int INST_LOC_RESETF = 36;\n  constexpr int INST_LOC_FEEDBACK = 37;\n  constexpr int INST_LOC_KILLEMAIL = 38;\n  constexpr int INST_LOC_POST = 39;\n  constexpr int INST_LOC_NEWUSER = 40;\n  constexpr int INST_LOC_RMAIL = 41;\n  constexpr int INST_LOC_DOWNLOAD = 42;\n  constexpr int INST_LOC_UPLOAD = 43;\n  constexpr int INST_LOC_BIXFER = 44;\n  constexpr int INST_LOC_NETLIST = 45;\n  constexpr int INST_LOC_TERM = 46;\n  //constexpr int INST_LOC_EVENTEDIT = 47;  NO LONGER USED\n  constexpr int INST_LOC_GETUSER = 48;\n  constexpr int INST_LOC_QWK = 49;\n  constexpr int INST_LOC_CH1 = 5000;\n  constexpr int INST_LOC_CH2 = 5001;\n  constexpr int INST_LOC_CH3 = 5002;\n  constexpr int INST_LOC_CH5 = 5004;\n  constexpr int INST_LOC_CH6 = 5005;\n  constexpr int INST_LOC_CH7 = 5006;\n  constexpr int INST_LOC_CH8 = 5007;\n  constexpr int INST_LOC_CH9 = 5008;\n  constexpr int INST_LOC_CH10 = 5009;\n  constexpr int INST_LOC_WFC = 65535;\n\n\n  /****************************************************************************/\n\n\n// Generated from constants using:\n// awk '{print \"constexpr char s\" $3 \"[] = \" \"\\\"\"$3\"\\\";\"}' x\n\nconstexpr char sINST_LOC_DOWN[] = \"INST_LOC_DOWN\";\nconstexpr char sINST_LOC_INIT[] = \"INST_LOC_INIT\";\nconstexpr char sINST_LOC_EMAIL[] = \"INST_LOC_EMAIL\";\nconstexpr char sINST_LOC_MAIN[] = \"INST_LOC_MAIN\";\nconstexpr char sINST_LOC_XFER[] = \"INST_LOC_XFER\";\nconstexpr char sINST_LOC_CHAINS[] = \"INST_LOC_CHAINS\";\nconstexpr char sINST_LOC_NET[] = \"INST_LOC_NET\";\nconstexpr char sINST_LOC_GFILES[] = \"INST_LOC_GFILES\";\nconstexpr char sINST_LOC_BEGINDAY[] = \"INST_LOC_BEGINDAY\";\nconstexpr char sINST_LOC_EVENT[] = \"INST_LOC_EVENT\";\nconstexpr char sINST_LOC_CHAT[] = \"INST_LOC_CHAT\";\nconstexpr char sINST_LOC_CHAT2[] = \"INST_LOC_CHAT2\";\nconstexpr char sINST_LOC_CHATROOM[] = \"INST_LOC_CHATROOM\";\nconstexpr char sINST_LOC_LOGON[] = \"INST_LOC_LOGON\";\nconstexpr char sINST_LOC_LOGOFF[] = \"INST_LOC_LOGOFF\";\nconstexpr char sINST_LOC_FSED[] = \"INST_LOC_FSED\";\nconstexpr char sINST_LOC_UEDIT[] = \"INST_LOC_UEDIT\";\nconstexpr char sINST_LOC_CHAINEDIT[] = \"INST_LOC_CHAINEDIT\";\nconstexpr char sINST_LOC_BOARDEDIT[] = \"INST_LOC_BOARDEDIT\";\nconstexpr char sINST_LOC_DIREDIT[] = \"INST_LOC_DIREDIT\";\nconstexpr char sINST_LOC_GFILEEDIT[] = \"INST_LOC_GFILEEDIT\";\nconstexpr char sINST_LOC_CONFEDIT[] = \"INST_LOC_CONFEDIT\";\nconstexpr char sINST_LOC_DOS[] = \"INST_LOC_DOS\";\nconstexpr char sINST_LOC_DEFAULTS[] = \"INST_LOC_DEFAULTS\";\nconstexpr char sINST_LOC_REBOOT[] = \"INST_LOC_REBOOT\";\nconstexpr char sINST_LOC_RELOAD[] = \"INST_LOC_RELOAD\";\nconstexpr char sINST_LOC_VOTE[] = \"INST_LOC_VOTE\";\nconstexpr char sINST_LOC_BANK[] = \"INST_LOC_BANK\";\nconstexpr char sINST_LOC_AMSG[] = \"INST_LOC_AMSG\";\nconstexpr char sINST_LOC_SUBS[] = \"INST_LOC_SUBS\";\nconstexpr char sINST_LOC_CHUSER[] = \"INST_LOC_CHUSER\";\nconstexpr char sINST_LOC_TEDIT[] = \"INST_LOC_TEDIT\";\nconstexpr char sINST_LOC_MAILR[] = \"INST_LOC_MAILR\";\nconstexpr char sINST_LOC_RESETQSCAN[] = \"INST_LOC_RESETQSCAN\";\nconstexpr char sINST_LOC_VOTEEDIT[] = \"INST_LOC_VOTEEDIT\";\nconstexpr char sINST_LOC_VOTEPRINT[] = \"INST_LOC_VOTEPRINT\";\nconstexpr char sINST_LOC_RESETF[] = \"INST_LOC_RESETF\";\nconstexpr char sINST_LOC_FEEDBACK[] = \"INST_LOC_FEEDBACK\";\nconstexpr char sINST_LOC_KILLEMAIL[] = \"INST_LOC_KILLEMAIL\";\nconstexpr char sINST_LOC_POST[] = \"INST_LOC_POST\";\nconstexpr char sINST_LOC_NEWUSER[] = \"INST_LOC_NEWUSER\";\nconstexpr char sINST_LOC_RMAIL[] = \"INST_LOC_RMAIL\";\nconstexpr char sINST_LOC_DOWNLOAD[] = \"INST_LOC_DOWNLOAD\";\nconstexpr char sINST_LOC_UPLOAD[] = \"INST_LOC_UPLOAD\";\nconstexpr char sINST_LOC_BIXFER[] = \"INST_LOC_BIXFER\";\nconstexpr char sINST_LOC_NETLIST[] = \"INST_LOC_NETLIST\";\nconstexpr char sINST_LOC_TERM[] = \"INST_LOC_TERM\";\nconstexpr char sINST_LOC_EVENTEDIT[] = \"INST_LOC_EVENTEDIT\";\nconstexpr char sINST_LOC_GETUSER[] = \"INST_LOC_GETUSER\";\nconstexpr char sINST_LOC_QWK[] = \"INST_LOC_QWK\";\nconstexpr char sINST_LOC_CH1[] = \"INST_LOC_CH1\";\nconstexpr char sINST_LOC_CH2[] = \"INST_LOC_CH2\";\nconstexpr char sINST_LOC_CH3[] = \"INST_LOC_CH3\";\nconstexpr char sINST_LOC_CH5[] = \"INST_LOC_CH5\";\nconstexpr char sINST_LOC_CH6[] = \"INST_LOC_CH6\";\nconstexpr char sINST_LOC_CH7[] = \"INST_LOC_CH7\";\nconstexpr char sINST_LOC_CH8[] = \"INST_LOC_CH8\";\nconstexpr char sINST_LOC_CH9[] = \"INST_LOC_CH9\";\nconstexpr char sINST_LOC_CH10[] = \"INST_LOC_CH10\";\nconstexpr char sINST_LOC_WFC[] = \"INST_LOC_WFC\";\n\nclass Instance final {\npublic:\n  Instance(std::filesystem::path root_dir, std::filesystem::path data_dir, instancerec ir);\n  Instance(std::filesystem::path root_dir, std::filesystem::path data_dir, int instance_num);\n  Instance(std::filesystem::path root_dir, std::filesystem::path data_dir) : Instance(root_dir, data_dir, 0) {}\n  Instance(const Instance&) = delete;\n  Instance(Instance&&) noexcept;\n  Instance& operator=(const Instance&);\n  //Instance& operator=(Instance&&) noexcept;\n  ~Instance() = default;\n\n  /**\n   * Mutable member to manipulate the instance record.\n   */\n  [[nodiscard]] const instancerec& ir() const;\n  [[nodiscard]] instancerec& ir();\n\n  /**\n   * The root directory for this WWIV instance BBS.\n   */\n  [[nodiscard]] std::filesystem::path root_directory() const;\n\n  /**\n   * The node number for this instance metadata.\n   */\n  [[nodiscard]] int node_number() const noexcept;\n\n  /**\n   * The user number for this current or last user on this node.\n   */\n  [[nodiscard]] int user_number() const noexcept;\n\n  /**\n   * Is this instance available with a user online who can receive messages.\n   */\n  [[nodiscard]] bool available() const noexcept;\n\n  /**\n   * Is this instance available with a user online who can receive messages.\n   */\n  [[nodiscard]] bool online() const noexcept;\n\n  /**\n   * Is this node active with a user.\n   */\n  [[nodiscard]] bool invisible() const noexcept;\n\n  /**\n   * Description of the caller's location within the BBS.\n   */\n  [[nodiscard]] std::string location_description() const;\n\n  /**\n   * The integer code for the location.\n   */\n  [[nodiscard]] int loc_code() const noexcept;\n\n  /**\n   * Is the caller in a numbered channel\n   */\n  [[nodiscard]] bool in_channel() const noexcept;\n\n  /**\n   * The connection speed of the current or last session on this node.\n   */\n  [[nodiscard]] int modem_speed() const noexcept;\n\n  /**\n   * The sub-location code. This is typically a pointer into the list of\n   * items referred to by location.  For example, in subs, it's the index\n   * number of the sub the user is browsing.\n   */\n  [[nodiscard]] int subloc_code() const noexcept;\n\n  /**\n   * When was this instance started.\n   */\n  [[nodiscard]] core::DateTime started() const;\n\n  /**\n   * When was this instance's metadata last updated.\n   */\n  [[nodiscard]] core::DateTime updated() const;\n\nprivate:\n  std::filesystem::path root_dir_;\n  std::filesystem::path data_dir_;\n  instancerec ir_;\n};\n\nclass Instances final {\npublic:\n  typedef std::vector<Instance>::iterator iterator;\n  typedef std::vector<Instance>::const_iterator const_iterator;\n  typedef std::size_t size_type;\n\n  [[nodiscard]] iterator begin() { return instances_.begin(); }\n  [[nodiscard]] const_iterator begin() const { return instances_.begin(); }\n  [[nodiscard]] const_iterator cbegin() const { return instances_.cbegin(); }\n  [[nodiscard]] iterator end() { return instances_.end(); }\n  [[nodiscard]] const_iterator end() const { return instances_.end(); }\n  [[nodiscard]] const_iterator cend() const { return instances_.cend(); }\n\n  Instances() = delete;\n  Instances(const Instances&) = delete;\n  Instances(Instances&&) = delete;\n  explicit Instances(const Config& config);\n  Instances& operator=(const Instances&) = delete;\n  Instances& operator=(Instances&&) = delete;\n  ~Instances() = default;\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n\n  size_type size() const;\n  Instance at(size_type pos);\n  std::vector<Instance> all();\n\n  bool upsert(size_type pos, const instancerec& ir);\n  bool upsert(size_type pos, const Instance& ir);\n\n  explicit operator bool() const noexcept { return IsInitialized(); }\n\nprivate:\n  [[nodiscard]] const std::filesystem::path& fn_path() const;\n\n  bool initialized_;\n  const std::filesystem::path path_;\n  const std::filesystem::path root_dir_;\n  const std::filesystem::path data_dir_;\n  std::vector<Instance> instances_;\n};\n\n} // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/instance_message.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */ \n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/instance_message.h\"\n\n#include \"bbs/instmsg.h\"\n#include \"cereal/archives/json.hpp\"\n#include \"core/cereal_utils.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/format.h\"\n\n#include <filesystem>\n#include <cereal/specialize.hpp>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\n// We want to override how we store some enums as a string, not int.\n// This has to be in the global namespace.\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::instance_message_type_t, specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const wwiv::sdk::instance_message_type_t& t) {\n  return to_enum_string<wwiv::sdk::instance_message_type_t>(t, {\"user\", \"system\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, wwiv::sdk::instance_message_type_t& t, const std::string& s) {\n  t = from_enum_string<wwiv::sdk::instance_message_type_t>(s, {\"user\", \"system\"});\n}\n\ntemplate <class Archive> void serialize(Archive& ar, wwiv::sdk::instance_message_t& n) {\n  SERIALIZE(n, message_type);\n  SERIALIZE(n, from_instance);\n  SERIALIZE(n, from_user);\n  SERIALIZE(n, dest_inst);\n  SERIALIZE(n, daten);\n  SERIALIZE(n, message);\n}\n}\n\nnamespace wwiv::sdk {\n\nstatic std::optional<File> create_file(const std::filesystem::path& path, const std::string& fn_pattern) {\n  for (auto i = 0; i < 1000; i++) {\n    File file(FilePath(path, fmt::format(fn_pattern, i)));\n    if (file.Open(File::modeText | File::modeReadWrite | File::modeCreateFile | File::modeExclusive, File::shareDenyReadWrite)) {\n      return file;\n    }\n  }\n  return std::nullopt;\n}\n\nbool send_instance_message(const Config& config, instance_message_t& msg) {\n  const auto scratch = config.scratch_dir(msg.dest_inst);\n  if (auto o = create_file(scratch, \"msg{}.json\")) {\n    std::ostringstream ss;\n    try {\n      {\n        cereal::JSONOutputArchive ar(ss);\n        serialize(ar, msg);\n      }\n      o.value().Write(ss.str());\n    } catch (const cereal::RapidJSONException& e) {\n      LOG(ERROR) << \"Caught cereal::RapidJSONException: \" << e.what();\n      return false;\n    }\n  }\n  return false;\n}\n\nstd::filesystem::path instance_message_filespec(const Config& config, int instance_num) {\n  const auto scratch = config.scratch_dir(instance_num);\n  return FilePath(scratch, \"msg*.json\");\n}\n\nbool send_instance_string(const Config& config, instance_message_type_t t, int dest_instance,\n    int from_user, int from_instance, const std::string& text) {\n  instance_message_t m{};\n  m.message_type = t;\n  m.dest_inst = dest_instance;\n  m.daten = DateTime::now().to_daten_t();\n  m.from_instance = from_instance;\n  m.from_user = from_user;\n  m.message = text;\n\n  return send_instance_message(config, m);\n}\n\nstd::vector<instance_message_t> read_all_instance_messages(const Config& config, int instance_num, int limit) {\n  const auto fndspec = instance_message_filespec(config, instance_num);\n  FindFiles ff(fndspec, FindFiles::FindFilesType::files);\n  auto current = 0;\n  std::vector<instance_message_t> out;\n  for (const auto& f : ff) {\n    TextFile tf(FilePath(config.scratch_dir(instance_num), f.name), \"rt\");\n    if (!tf) {\n      continue;\n    }\n    auto s = tf.ReadFileIntoString();\n    std::stringstream ss(s);\n    tf.Close();\n    if (!File::Remove(tf.full_pathname())) {\n      VLOG(1) << \"Failed to delete instance message: \" << tf.full_pathname();\n    }\n    instance_message_t msg;\n    try {\n      cereal::JSONInputArchive ar(ss);\n      serialize(ar, msg);\n    } catch (const cereal::RapidJSONException& e) {\n      LOG(ERROR) << \"Exception parsing: \" << e.what();\n      LOG(ERROR) << \"FileName: \" << tf.full_pathname();\n      LOG(ERROR) << \"Text: \" << s;\n    }\n    out.emplace_back(msg);\n    if (++current > limit) {\n      VLOG(1) << \"Hit limit, ending early\";\n      break;\n    }\n  }\n\n  return out;\n}\n\n}\n"
  },
  {
    "path": "sdk/instance_message.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_INSTANCE_MESSAGE_H\n#define INCLUDED_SDK_INSTANCE_MESSAGE_H\n\n#include \"core/datetime.h\"\n\n#include <filesystem>\n#include <string>\n#include <vector>\n#include \"sdk/config.h\"\n\nnamespace wwiv::sdk {\n\nenum class instance_message_type_t {\n  user,\n  system\n};\n\n/*\n * Structure for inter-instance messages.\n */\nstruct instance_message_t {\n  // Message main type\n  instance_message_type_t message_type;\n  // Originating instance\n  int from_instance;\n  // Originating sess->usernum\n  int from_user;\n  // Destination instance\n  int dest_inst;\n\n  // Timestamp the message was sent.\n  daten_t daten;\n  // Message text\n  std::string message;\n};\n\n/**\n * Sends an instance message to the instance pointed to by msg.\n */\nbool send_instance_message(const Config& config, const instance_message_t& msg);\n\nstd::filesystem::path instance_message_filespec(const Config& config, int instance_num);\n\n\nbool send_instance_string(const Config& config, instance_message_type_t t, int dest_instance,\n                          int from_user, int from_instance, const std::string& text);\n\nstd::vector<instance_message_t> read_all_instance_messages(const Config& config, int instance_num, int limit = 1000);\n\n}\n\n\n#endif \n"
  },
  {
    "path": "sdk/instance_message_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2007-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"sdk/instance_message.h\"\n#include \"sdk/sdk_helper.h\"\n\nusing namespace wwiv::sdk;\n\nclass InstanceMessageTest : public testing::Test {\npublic:\n  InstanceMessageTest() {}\n\n  SdkHelper helper;\n};\n\nTEST_F(InstanceMessageTest, Smoke) {\n  send_instance_string(helper.config(), instance_message_type_t::user, 2, 1, 1, \"test\");\n  const auto im2 = read_all_instance_messages(helper.config(), 2);\n  EXPECT_EQ(1u, im2.size());\n  EXPECT_EQ(\"test\", im2.front().message);\n\n  const auto im1 = read_all_instance_messages(helper.config(), 1);\n  EXPECT_TRUE(im1.empty());\n}\n"
  },
  {
    "path": "sdk/key.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_KEY_H\n#define INCLUDED_SDK_KEY_H\n\n#include <iostream>\n\nnamespace wwiv::sdk {\n\nclass key_t final {\npublic:\n  key_t() = default;\n  explicit key_t(char key) : key_(key) {}\n\n  void key(char k) noexcept { key_ = k; }\n  [[nodiscard]] char key() const noexcept { return key_; }\n\n  char key_;\n};\n\ninline bool operator< (const key_t &c, const key_t & c2) { return c.key_ < c2.key_; }\ninline bool operator< (const char &c, const key_t & c2) { return c < c2.key_; }\ninline bool operator< (const key_t &c, const char & c2) { return c.key_ < c2; }\ninline bool operator== (const key_t &c, const key_t & c2) { return c.key_ == c2.key_; }\ninline bool operator== (const char &c, const key_t & c2) { return c == c2.key_; }\ninline bool operator== (const key_t &c, const char & c2) { return c.key_ == c2; }\n\ninline std::ostream& operator<<(std::ostream& os, const key_t& c) {\n  os << c.key();\n  return os;\n}\n\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/key_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_KEY_CEREAL_H\n#define INCLUDED_SDK_KEY_CEREAL_H\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"core/cereal_utils.h\"\n#include \"sdk/key.h\"\n\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::key_t, specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const wwiv::sdk::key_t& t) {\n  if (t.key_ == 0) {\n    return {};\n  }\n  return wwiv::strings::StrCat(t.key_);\n}\n\ntemplate <class Archive>\nvoid load_minimal(Archive const&, wwiv::sdk::key_t& t, const std::string& s) {\n  t.key(s.empty() ? 0 : s.front());\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/menus/menu.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/menus/menu.h\"\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/archives/json.hpp>\n#include <cereal/types/memory.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/menus/menus_cereal.h\"\n#include \"sdk/menus/menu_set.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/expr.h\"\n\n#include <string>\n#include <utility>\n#include <vector>\n\nusing cereal::make_nvp;\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::menus {\n\nMenu430::Menu430(std::filesystem::path menu_dir, std::string menu_set, std::string menu_name)\n    : menu_dir_(std::move(menu_dir)), menu_set_(std::move(menu_set)),\n      menu_name_(std::move(menu_name)) {\n  initialized_ = Load();\n}\n\nbool Menu430::Load() {\n  const auto menu_dir = FilePath(menu_dir_, menu_set_);\n  const auto menu_name = StrCat(menu_name_, \".mnu\");\n  const auto path = FilePath(menu_dir, menu_name);\n  File menu_file(path);\n  if (!menu_file.Open(File::modeBinary | File::modeReadOnly, File::shareDenyNone)) {\n    // Unable to open menu\n    return false;\n  }\n\n  // Read the header (control) record into memory\n  menu_file.Read(&header, sizeof(menu_header_430_t));\n\n  const auto num_items = static_cast<int>(menu_file.length() / sizeof(menu_rec_430_t));\n\n  for (auto nn = 1; nn < num_items; nn++) {\n    menu_rec_430_t menu{};\n    menu_file.Read(&menu, sizeof(menu_rec_430_t));\n    recs.emplace_back(menu);\n  }\n  initialized_ = true;\n  return true;\n}\n\nmenu_action_56_t CreateActionFrom43Execute(const std::string& exec) {\n  menu_action_56_t a{};\n  if (!contains(exec, ' ')) {\n    a.cmd = ToStringLowerCase(exec);\n    return a;\n  }\n  const auto space = exec.find(' ');\n  a.cmd = ToStringLowerCase(exec.substr(0, space));\n  auto data = StringTrim(exec.substr(space + 1));\n  if (data.size() > 2) {\n    if (data.back() == ')') {\n      data.pop_back();\n    }\n    if (data.front() == '(') {\n      data = data.substr(1);\n    }\n  }\n  a.data = data;\n  return a;\n}\n\nMenu56::Menu56(std::filesystem::path menu_dir, const MenuSet56& menu_set, std::string menu_name)\n    : menu_dir_(std::move(menu_dir)), menu_set_(menu_set.menu_set.name),\n      menu_name_(std::move(menu_name)) {\n  initialized_ = Load();\n}\n\nbool Menu56::Load() {\n  const auto dir = FilePath(menu_dir_, menu_set_);\n  const auto name = StrCat(menu_name_, \".mnu.json\");\n  JsonFile f(FilePath(dir, name), \"menu\", menu, 1);\n  return f.Load();\n}\n\nbool Menu56::Save() {\n  const auto dir = FilePath(menu_dir_, menu_set_);\n  const auto name = StrCat(menu_name_, \".mnu.json\");\n  JsonFile f(FilePath(dir, name), \"menu\", menu, 1);\n  return f.Save();\n}\n\nstd::optional<Menu56> Create56MenuFrom43(const Menu430& m4, int max_backups) {\n  const auto dir = FilePath(m4.menu_dir_, m4.menu_set_);\n  const auto name = StrCat(m4.menu_name_, \".mnu.json\");\n  const auto path = FilePath(dir, name);\n  if (backup_file(path, max_backups)) {\n    File::Remove(path);\n  }\n  MenuSet56 menuset;\n  menuset.menu_set.name = m4.menu_set_;\n  Menu56 m5(m4.menu_dir_, menuset, m4.menu_name_);\n\n  auto& h = m5.menu;\n  const auto& oh = m4.header;\n  h.logging_action = to_menu_logtype(oh.nLogging);\n  h.num_action = to_menu_numflag_t(oh.nums);\n  h.help_type = to_menu_help_display(oh.nForceHelp);\n\n  auto& g = h.generated_menu;\n  g.color_title = fmt::format(\"|{:02}\", oh.nTitleColor);\n  g.color_item_key = fmt::format(\"|{:02}\", oh.nItemTextHLColor);\n  g.color_item_braces = fmt::format(\"|{:02}\", oh.nItemBorderColor);\n  g.color_item_text = fmt::format(\"|{:02}\", oh.nItemTextColor);\n\n  h.title = oh.szMenuTitle;\n  {\n    acs::AcsExpr ae;\n    ae.min_dsl(oh.nMinDSL).dar_int(oh.uDAR).min_sl(oh.nMinSL).ar_int(oh.uAR);\n    ae.sysop(oh.nSysop).cosysop(oh.nCoSysop);\n    h.acs = ae.get();\n  }\n  h.password = oh.szPassWord;\n  if (oh.szScript[0]) {\n    h.enter_actions.emplace_back(CreateActionFrom43Execute(oh.szScript));\n  }\n  if (oh.szExitScript[0]) {\n    h.exit_actions.emplace_back(CreateActionFrom43Execute(oh.szScript));\n  }\n\n  // Add the items now.\n  for (const auto& o : m4.recs) {\n    menu_item_56_t i{};\n    i.item_key = o.szKey;\n    i.item_text = o.szMenuText;\n    i.help_text = o.szHelp;\n    i.log_text = o.szSysopLog;\n    i.instance_message = o.szInstanceMessage;\n\n    {\n      // TODO(rushfan): restrict into ACS.\n      acs::AcsExpr ae;\n      ae.min_sl(o.nMinSL)\n          .max_sl(o.iMaxSL)\n          .min_dsl(o.nMinDSL)\n          .max_dsl(o.iMaxDSL)\n          .ar_int(o.uAR)\n          .dar_int(o.uDAR);\n      ae.sysop(o.nSysop).cosysop(o.nCoSysop);\n      i.acs = ae.get();\n    }\n\n    i.password = o.szPassWord;\n    i.actions.emplace_back(CreateActionFrom43Execute(o.szExecute));\n\n    h.items.emplace_back(i);\n  }\n\n  m5.set_initialized(true);\n  return {m5};\n}\n\n// What does a number key do in this menu.\nmenu_numflag_t to_menu_numflag_t(int n) {\n  switch (n) {\n  case MENU_NUMFLAG_NOTHING:\n    return menu_numflag_t::none;\n  case MENU_NUMFLAG_DIRNUMBER:\n    return menu_numflag_t::dirs;\n  case MENU_NUMFLAG_SUBNUMBER:\n    return menu_numflag_t::subs;\n  default:\n    return menu_numflag_t::none;\n  }\n}\n\n// What to log for this command.\nmenu_logtype_t to_menu_logtype(int n) {\n  switch (n) {\n  case MENU_LOGTYPE_NONE:\n    return menu_logtype_t::none;\n  case MENU_LOGTYPE_COMMAND:\n    return menu_logtype_t::command;\n  case MENU_LOGTYPE_DESC:\n    return menu_logtype_t::description;\n  case MENU_LOGTYPE_KEY:\n    return menu_logtype_t::key;\n  default:\n    return menu_logtype_t::none;\n  }\n}\n\nmenu_help_display_t to_menu_help_display(int n) {\n  if (n == MENU_HELP_DONTFORCE) {\n    return menu_help_display_t::user_choice;\n  }\n  if (n == MENU_HELP_ONENTRANCE) {\n    return menu_help_display_t::on_entrance;\n  }\n  return menu_help_display_t::always;\n}\n\nstd::vector<menu_command_help_t> LoadCommandHelpJSON(const std::filesystem::path& datadir) {\n  std::vector<menu_command_help_t> cmds;\n  const auto path = FilePath(datadir, \"menu_commands.json\");\n  JsonFile f(path, \"commands\", cmds, 1);\n  if (!f.Load()) {\n    return {};\n  }\n  return cmds;\n\n}\n\nbool SaveCommandHelpJSON(const std::filesystem::path& datadir,\n                         const std::vector<menu_command_help_t>& cmds) {\n  VLOG(1) << \"SaveCommandHelpJSON\";\n  const auto path = FilePath(datadir, \"menu_commands.json\");\n  JsonFile f(path, \"commands\", cmds, 1);\n  return f.Save();\n}\n\n\n\n} // namespace wwiv::sdk::menus\n"
  },
  {
    "path": "sdk/menus/menu.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MENUS_MENU_H\n#define INCLUDED_SDK_MENUS_MENU_H\n\n#include <cstdint>\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\n  class Config;\nclass User;\n\n}\n\nconstexpr uint8_t MENU_FLAG_DELETED = 0x01;\nconstexpr uint8_t MENU_FLAG_MAINMENU = 0x02;\n\nconstexpr uint8_t MENU_NUMFLAG_NOTHING = 0;\nconstexpr uint8_t MENU_NUMFLAG_SUBNUMBER = 1;\nconstexpr uint8_t MENU_NUMFLAG_DIRNUMBER = 2;\n\nconstexpr uint8_t MENU_LOGTYPE_KEY = 0;\nconstexpr uint8_t MENU_LOGTYPE_NONE = 1;\nconstexpr uint8_t MENU_LOGTYPE_COMMAND = 2;\nconstexpr uint8_t MENU_LOGTYPE_DESC = 3;\nconstexpr uint8_t MENU_LOGTYPE_LAST = 4;\n\nconstexpr uint8_t MENU_HELP_DONTFORCE = 0;\nconstexpr uint8_t MENU_HELP_FORCE = 1;\nconstexpr uint8_t MENU_HELP_ONENTRANCE = 2;\n\nconstexpr int MENU_MAX_KEYS = 10;\n\n#pragma pack(push, 1)\n\nstruct menu_header_430_t {\n  char szSig[10];      /* Menu Signature WWIV431\\x1a */\n  char unused[54];\n\n  uint16_t  nVersion;\n  uint16_t  nEmpty;\n  uint8_t   nFlags;\n\n  uint8_t   nums;     /* What does a number do?  Set sub#, Dir#, nothing? */\n  uint8_t   nLogging;     /* Types of logging, Key, None, command, desc       */\n\n  uint8_t   nForceHelp;   /* force, don't force, on entrance only              */\n  uint8_t   nAllowedMenu; /* Can pull down, regular or both menus be used?     */\n\n  uint8_t  nTitleColor, nMainBorderColor, nMainBoxColor, nMainTextColor,\n           nMainTextHLColor, nMainSelectedColor, nMainSelectedHLColor;\n\n  uint8_t  nItemBorderColor, nItemBoxColor, nItemTextColor, nItemTextHLColor,\n           nItemSelectedColor, nItemSelectedHLColor;\n\n  char   szMenuTitle[21];\n  char   unused_misc2[60];\n  char   szPassWord[21];     /* required for entry of menu */\n  uint16_t nMinSL, nMinDSL;    /* required for entry of menu */\n  uint16_t uAR, uDAR;          /* required for entry of menu */\n  uint16_t uRestrict;          /* not allowed restrictions   */\n  bool nSysop, nCoSysop;   /* Must be either sysop or co */\n  char   misc3[30];\n  char   szScript[101];      /* Gets executed on entry     */\n  char   szExitScript[101];  /* Executed on rtn from menu  */\n  char unused_padding[109];\n};\n\nstruct menu_rec_430_t {\n  uint8_t nFlags;   /* AFLAG_????? */\n\n  char szKey[MENU_MAX_KEYS + 1]; /* Keystroke to execute menu item   */\n  char szExecute[101];           /* Command to execute               */\n  char szMenuText[41];           /* Menu description                 */\n  char unused_szPDText[41];      /* Pull down menu text               */\n\n  char szHelp[81];               /* Help for this item               */\n  char szSysopLog[51];           /* Msg to put in the log            */\n\n  char szInstanceMessage[81];\n\n  /* Security */\n  uint16_t nMinSL, iMaxSL;\n  uint16_t nMinDSL, iMaxDSL;\n  uint16_t uAR, uDAR;        /* Must match all specified to be able to run     */\n  uint16_t uRestrict;        /* If any of these restrictions, you cant execute */\n  bool nSysop, nCoSysop;  /* true and false, does it take a co/sysop to run */\n  char szPassWord[21];\n\n  uint16_t nHide;            /* Hide text from PD/Regular/both or no menus */\n  uint16_t unused_nPDFlags;  /* special characteristics for pull downs       */\n\n  char unused_data[92];\n};\n\n#pragma pack(pop)\n\nnamespace wwiv::sdk::menus {\n\nclass MenuSet56;\n\nclass Menu430 {\npublic:\n  Menu430(std::filesystem::path menu_dir, std::string menu_set, std::string menu_name);\n  [[nodiscard]] bool Load();\n  [[nodiscard]] bool initialized() const noexcept { return initialized_; }\n\n  menu_header_430_t header{};\n  std::vector<menu_rec_430_t> recs;\n\n  const std::filesystem::path menu_dir_;\n  const std::string menu_set_;\n  const std::string menu_name_;\n  bool initialized_{false};\n};\n\nstatic_assert(sizeof(menu_rec_430_t) == sizeof(menu_header_430_t), \"sizeof(menu_rec_430_t) == sizeof(menu_header_430_t)\");\n\n// What does a number key do in this menu.\nenum class menu_numflag_t { none, subs, dirs };\n\n// What to log for this command.\nenum class menu_logtype_t { key, command, description, none };\n\n// When is the menu displayed.\nenum class menu_help_display_t { always, never, on_entrance, user_choice };\n\nstruct menu_action_56_t {\n  // MenuCommand to execute\n  std::string cmd;\n  // Data to pass to menu command\n  std::string data;\n  // ACS needed to execute this menu action\n  std::string acs;\n};\n\nstruct menu_item_56_t {\n  // KEY of the item (such as 'C' or \"CHAINEDIT\")\n  std::string item_key;\n  // Text for the item (i.e. \"Chain Edit\")\n  std::string item_text;\n  // Is this item visible in generated menus\n  bool visible{true};\n  // Help text to display in help screen\n  std::string help_text;\n  // What to log to sysops log when this menu item is invoked\n  std::string log_text;\n  // What to set for the instance message when this menu item is invoked.\n  std::string instance_message;\n  // ACS needed to invoke this command\n  std::string acs;\n  // password needed to invoke this menu item\n  std::string password;\n  // All of the actions to run when invoking this menu item\n  std::vector<menu_action_56_t> actions;\n};\n\nstruct generated_menu_56_t {\n  int num_cols{3};\n  // Colors\n  std::string color_title{\"|#4\"};\n  std::string color_item_text{\"|#0\"};\n  std::string color_item_key{\"|#2\"};\n  std::string color_item_braces{\"|#1\"};\n  bool show_empty_text{false};\n  int num_newlines_at_end{1};\n};\n\nstruct menu_56_t {\n  /** Clear screen before displaying menu? */\n  bool cls{false};\n  /* What does a number do?  Set sub#, Set dir#, nothing? */\n  menu_numflag_t num_action;\n  /* Types of logging, Key, None, command, desc */\n  menu_logtype_t logging_action;\n  /* force, display always, display on entrance only */\n  menu_help_display_t help_type;\n\n  // Details for generated menus.\n  generated_menu_56_t generated_menu;\n\n  // Title of this menu\n  std::string title;\n  // ACS needed to execute this menu\n  std::string acs;\n  // password needed to execute this menu\n  std::string password;\n\n  // Actions to invoke when entering this menu\n  std::vector<menu_action_56_t> enter_actions;\n  // Actions to invoke when exiting this menu\n  std::vector<menu_action_56_t> exit_actions;\n  // Menu items\n  std::vector<menu_item_56_t> items;\n};\n\n/**\n * Represents a menuset, which is a collection of menus.\n */\nstruct menu_set_t {\n  // Name of this menuset\n  std::string name;\n  // Description of this menuset.\n  std::string description;\n  // ACS needed to use this menuset.\n  std::string acs;\n  // Global menu items. These will be available in every menu in this menuset.\n  std::vector<menu_item_56_t> items;\n};\n\nclass Menu56 {\npublic:\n  Menu56(std::filesystem::path menu_dir, const MenuSet56& menu_set,\n          std::string menu_name);\n  [[nodiscard]] bool Load();\n  [[nodiscard]] bool Save();\n  [[nodiscard]] bool initialized() const noexcept { return initialized_; }\n  void set_initialized(bool i) { initialized_ = i; }\n\n  menu_56_t menu{};\n\n  private:\n  const std::filesystem::path menu_dir_;\n  const std::string menu_set_;\n  const std::string menu_name_;\n  bool initialized_{false};\n};\n\nstd::optional<Menu56> Create56MenuFrom43(const Menu430& m4, int max_backups);\n\n// What does a number key do in this menu.\nmenu_numflag_t to_menu_numflag_t(int n);\n\n// What to log for this command.\nmenu_logtype_t to_menu_logtype(int n);\n\n// Converts help int to menu_help_display_t\nmenu_help_display_t to_menu_help_display(int n);\n\nstruct menu_command_help_t {\n  // MenuCommand category\n  std::string cat;\n  // MenuCommand name\n  std::string cmd;\n  // Help text.\n  std::string help;\n\n  bool operator<(const menu_command_help_t& other) const {\n    if (cat == other.cat) {\n      return cmd < other.cmd;\n    }\n    return cat < other.cat;\n  }\n};\n\nstd::vector<menu_command_help_t> LoadCommandHelpJSON(const std::filesystem::path& datadir);\nbool SaveCommandHelpJSON(const std::filesystem::path& datadir, const std::vector<menu_command_help_t>& cmds);\n\nenum class menu_type_t { short_menu, long_menu };\n\n\n} \n#endif"
  },
  {
    "path": "sdk/menus/menu_set.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/menus/menu_set.h\"\n\n#include \"core/findfiles.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/menus/menus_cereal.h\"\n\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk::menus {\n\n///////////////////////////////////////////////////////////////////////\n//\n// MenuSet\n//\n\nMenuSet56::MenuSet56(std::filesystem::path dir)\n    : menuset_dir_(std::move(dir)), initialized_(true) {\n  if (!Load()) {\n    // Create default empty Menuset from DESCRIPTION.ION\n    MenuDescriptions descr(menuset_dir_.parent_path());\n    const auto name = menuset_dir_.filename().string();\n    menu_set.name = name;\n    menu_set.description = descr.description(name);\n    if (!Save()) {\n      LOG(WARNING) << \"Failed to save newly created MenuSet: \" << menuset_dir_;\n    }\n  }\n}\n\nMenuSet56::MenuSet56() { \n  menu_set.name = \"UNKNOWN\";\n}\n\nMenuSet56& MenuSet56::operator=(const MenuSet56& o) {\n  initialized_ = o.initialized();\n  menuset_dir_ = o.menuset_dir_;\n  menu_set = o.menu_set;\n  return *this;\n}\n\nMenuSet56::~MenuSet56() = default;\n\nbool MenuSet56::Load() {\n  const auto dir = FilePath(menuset_dir_, \"menuset.json\");\n  JsonFile f(dir, \"menuset\", menu_set, 1);\n  return f.Load();\n}\n\nbool MenuSet56::Save() {\n  const auto dir = FilePath(menuset_dir_, \"menuset.json\");\n  JsonFile f(dir, \"menuset\", menu_set, 1);\n  return f.Save();\n}\n\n///////////////////////////////////////////////////////////////////////\n//\n// MenuDescriptions: DESCRIPT.ION format\n//\n\nMenuDescriptions::MenuDescriptions(const std::filesystem::path& menupath) : menupath_(menupath) {\n  TextFile file(FilePath(menupath, DESCRIPT_ION), \"rt\");\n  if (file.IsOpen()) {\n    std::string s;\n    while (file.ReadLine(&s)) {\n      StringTrim(&s);\n      const auto space = s.find(' ');\n      if (s.empty() || space == std::string::npos) {\n        continue;\n      }\n      descriptions_.emplace(ToStringLowerCase(s.substr(0, space)),\n                            ToStringLowerCase(s.substr(space + 1)));\n    }\n  }\n}\n\nMenuDescriptions::~MenuDescriptions() = default;\n\nstd::string MenuDescriptions::description(const std::string& name) const {\n  if (contains(descriptions_, name)) {\n    return wwiv::stl::at(descriptions_, name);\n  }\n  return {};\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/menus/menu_set.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MENUS_MENU_SET_H\n#define INCLUDED_SDK_MENUS_MENU_SET_H\n\n#include \"core/stl.h\"\n#include \"sdk/menus/menu.h\"\n#include <map>\n#include <string>\n\nnamespace wwiv::sdk::menus {\n\n\nclass MenuDescriptions {\npublic:\n  explicit MenuDescriptions(const std::filesystem::path& menupath);\n  ~MenuDescriptions();\n  [[nodiscard]] std::string description(const std::string& name) const;\n\nprivate:\n  const std::filesystem::path menupath_;\n  std::map<std::string, std::string, wwiv::stl::ci_less> descriptions_;\n};\n\nclass MenuSet56 final {\npublic:\n  explicit MenuSet56(std::filesystem::path dir);\n  MenuSet56& operator=(const MenuSet56&);\n  /** Creates a dummy menuset */\n  MenuSet56();\n  ~MenuSet56();\n  [[nodiscard]] bool Load();\n  [[nodiscard]] bool Save();\n  [[nodiscard]] bool initialized() const noexcept { return initialized_; }\n  void set_initialized(bool i) { initialized_ = i; }\n\n  menu_set_t menu_set{};\n  const std::filesystem::path& menuset_dir() const noexcept { return menuset_dir_;  }\n\nprivate:\n  std::filesystem::path menuset_dir_;\n  bool initialized_{false};\n};\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/menus/menus_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_FILES_MENUS_CEREAL_H\n#define INCLUDED_SDK_FILES_MENUS_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/uuid_cereal.h\"\n#include \"sdk/menus/menu.h\"\n\nnamespace cereal {\nusing namespace wwiv::sdk::menus;\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const menu_numflag_t& t) {\n  return to_enum_string<menu_numflag_t>(t, {\"none\", \"subs\", \"dirs\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, menu_numflag_t& t, const std::string& s) {\n  t = from_enum_string<menu_numflag_t>(s, {\"none\", \"subs\", \"dirs\"});\n}\n\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const menu_help_display_t& t) {\n  return to_enum_string<menu_help_display_t>(t, {\"always\", \"never\", \"on_entrance\", \"user_choice\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, menu_help_display_t& t, const std::string& s) {\n  t = from_enum_string<menu_help_display_t>(s, {\"always\", \"never\", \"on_entrance\", \"user_choice\"});\n}\n\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const&, const menu_logtype_t& t) {\n  return to_enum_string<menu_logtype_t>(t, {\"key\", \"command\", \"description\", \"none\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const&, menu_logtype_t& t, const std::string& s) {\n  t = from_enum_string<menu_logtype_t>(s, {\"key\", \"command\", \"description\", \"none\"});\n}\n\n}\n\nnamespace wwiv::sdk::menus {\n\ntemplate <class Archive>\nvoid serialize (Archive& ar, menu_action_56_t& d) {\n  SERIALIZE(d, cmd);\n  SERIALIZE(d, data);\n  SERIALIZE(d, acs);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, menu_item_56_t& s) {\n  SERIALIZE(s, item_key);\n  SERIALIZE(s, item_text);\n  SERIALIZE(s, visible);\n  SERIALIZE(s, help_text);\n  SERIALIZE(s, log_text);\n  SERIALIZE(s, instance_message);\n  SERIALIZE(s, acs);\n  SERIALIZE(s, password);\n  SERIALIZE(s, actions);\n}\n\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, generated_menu_56_t& s) {\n  SERIALIZE(s, num_cols);\n  SERIALIZE(s, color_title);\n  SERIALIZE(s, color_item_key);\n  SERIALIZE(s, color_item_text);\n  SERIALIZE(s, color_item_braces);\n  SERIALIZE(s, show_empty_text);\n  SERIALIZE(s, num_newlines_at_end);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, menu_56_t& s) {\n  SERIALIZE(s, cls);\n  SERIALIZE(s, num_action);\n  SERIALIZE(s, logging_action);\n  SERIALIZE(s, help_type);\n  SERIALIZE(s, generated_menu);\n  SERIALIZE(s, title);\n  SERIALIZE(s, acs);\n  SERIALIZE(s, password);\n  SERIALIZE(s, enter_actions);\n  SERIALIZE(s, exit_actions);\n  SERIALIZE(s, items);\n}\n\ntemplate <class Archive>\nvoid serialize (Archive& ar, menu_command_help_t& d) {\n  SERIALIZE(d, cat);\n  SERIALIZE(d, cmd);\n  SERIALIZE(d, help);\n}\n\n\ntemplate <class Archive> void serialize(Archive& ar, menu_set_t& m) {\n  SERIALIZE(m, name);\n  SERIALIZE(m, description);\n  SERIALIZE(m, acs);\n  SERIALIZE(m, items);\n}\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/msdos_stdint.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_MSDOS_H__\n#define __INCLUDED_SDK_MSDOS_H__\n\n#ifdef __MSDOS__\n\ntypedef signed char int8_t;\ntypedef unsigned char uint8_t;\ntypedef signed short int int16_t;\ntypedef unsigned short int uint16_t;\ntypedef signed long int32_t;\ntypedef unsigned long uint32_t;\n\n#endif  // __MSDOS__\n\n#endif  // __INCLUDED_SDK_MSDOS_H__"
  },
  {
    "path": "sdk/msgapi/email_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include <memory>\n#include <string>\n\n#include \"core/file.h\"\n#include <filesystem>\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"core/datetime.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/msgapi/email_wwiv.h\"\n#include \"sdk/msgapi/msgapi.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/sdk_helper.h\"\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nclass EmailTest: public testing::Test {\npublic:\n  void SetUp() override {\n    MessageApiOptions options{};\n    options.overflow_strategy = OverflowStrategy::delete_none;\n    auto* a = new WWIVMessageApi(options, helper.config(), {}, new NullLastReadImpl());\n    email = a->OpenEmail();\n    api.reset(a);\n  }\n\n  [[nodiscard]] bool Add(uint16_t from, uint16_t to, const std::string& title, const std::string& text) const {\n    EmailData e{};\n    e.title = title;\n    e.text = text;\n    e.daten = daten_t_now();\n    e.from_user = from;\n    e.user_number = to;\n    return email->AddMessage(e);\n  }\n\n  SdkHelper helper;\n  unique_ptr<WWIVMessageApi> api;\n  unique_ptr<WWIVEmail> email;\n};\n\nTEST_F(EmailTest, BasicCase) {\n  // new area.\n  EXPECT_EQ(0, email->number_of_messages());\n\n  EXPECT_TRUE(File::Exists(FilePath(helper.datadir(), EMAIL_DAT)));\n  EXPECT_TRUE(File::Exists(FilePath(helper.msgsdir(), EMAIL_DAT)));\n}\n\nTEST_F(EmailTest, Create) {\n  // new area.\n  EXPECT_EQ(0, email->number_of_messages());\n\n  // Add a new message, expect it to be there.\n  ASSERT_TRUE(Add(1, 2, \"Title\", \"Text\"));\n  EXPECT_EQ(1, email->number_of_messages()) << FilePath(helper.datadir(), EMAIL_DAT);\n\n  // Read it back and make sure.\n  mailrec nm{};\n  ASSERT_TRUE(email->read_email_header(0, nm));\n  EXPECT_STREQ(\"Title\", nm.title);\n}\n\nTEST_F(EmailTest, Delete) {\n  ASSERT_TRUE(Add(1, 2, \"Title\", \"Text\"));\n  ASSERT_TRUE(Add(1, 2, \"Title2\", \"Text2\"));\n  ASSERT_TRUE(Add(1, 3, \"Title3\", \"Text3\"));\n  EXPECT_EQ(3, email->number_of_messages()) << FilePath(helper.datadir(), EMAIL_DAT);\n\n  email->DeleteAllMailToOrFrom(2);\n  EXPECT_EQ(1, email->number_of_messages()) << FilePath(helper.datadir(), EMAIL_DAT);\n  mailrec nm{};\n  EXPECT_FALSE(email->read_email_header(0, nm));\n  EXPECT_FALSE(email->read_email_header(1, nm));\n  EXPECT_TRUE(email->read_email_header(2, nm));\n}\n"
  },
  {
    "path": "sdk/msgapi/email_wwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/email_wwiv.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\nconstexpr char CZ = 26;\n\nWWIVEmail::WWIVEmail(const Config& config, const std::filesystem::path& data_filename,\n                     const std::filesystem::path& text_filename, int max_net_num)\n  : Type2Text(text_filename), \n    config_(config), data_filename_(data_filename),\n    mail_file_(data_filename_, File::modeBinary | File::modeReadWrite, File::shareDenyReadWrite),\n    max_net_num_(max_net_num) {\n  open_ = mail_file_ && File::Exists(data_filename);\n}\n\nbool WWIVEmail::Close() {\n  open_ = false;\n  return true;\n}\n\nstatic bool modify_email_waiting(const Config& config, uint16_t email_usernum, int delta) {\n\n  if (UserManager um(config); auto o = um.readuser(email_usernum)) {\n    auto u = o.value();\n    const auto n = std::min(0, u.email_waiting() + delta);\n    u.email_waiting(n);\n    if (!um.writeuser(&u, email_usernum)) {\n      return false;\n    }\n    return true;\n  }\n  return false;\n}\n\nstatic bool increment_email_counters(const Config& config, uint16_t email_usernum) {\n  statusrec_t statusrec{};\n  DataFile<statusrec_t> file(FilePath(config.datadir(), STATUS_DAT),\n                             File::modeBinary | File::modeReadWrite);\n  if (!file) {\n    return false;\n  }\n  if (!file.Read(0, &statusrec)) {\n    return false;\n  }\n  if (email_usernum == 1) {\n    ++statusrec.fbacktoday;\n  } else {\n    ++statusrec.emailtoday;\n  }\n  if (!file.Write(0, &statusrec)) {\n    return false;\n  }\n\n  return modify_email_waiting(config, email_usernum, 1);\n}\n\n// Expects data.text is of the form:\n// SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\nbool WWIVEmail::AddMessage(EmailData& data) {\n  mailrec m{};\n  to_char_array(m.title, data.title);\n  m.anony = static_cast<unsigned char>(data.anony);\n  m.fromsys = static_cast<uint16_t>(data.from_system);\n  m.fromuser = static_cast<uint16_t>(data.from_user);\n  m.tosys = static_cast<uint16_t>(data.system_number);\n  m.touser = static_cast<uint16_t>(data.user_number);\n  m.status = 0;\n  m.daten = data.daten;\n\n  if (m.fromsys && max_net_num_ > 1) {\n    // always trim to WWIV_MESSAGE_TITLE_LENGTH now.\n    m.title[71] = '\\0';\n    m.status |= status_new_net;\n    m.network.network_msg.net_number = static_cast<int8_t>(data.from_network_number);\n  }\n\n  auto message_text = data.text;\n  // WWIV 4.x requires a control-Z to terminate the message, WWIV 5.x\n  // does not, and removes it on read.\n  if (message_text.back() != CZ) {\n    message_text.push_back(CZ);\n  }\n\n  auto msg = savefile(message_text);\n  if (!msg) {\n    return false;\n  }\n  m.msg = msg.value();\n  increment_email_counters(config_, m.touser);\n  return add_email(m);\n}\n\nstatic bool is_mailrec_deleted(const mailrec& h) {\n  return h.tosys == 0 && h.touser == 0 && h.daten == 0xffffffff;\n}\n\n/** Total number of email messages in the system. */\nint WWIVEmail::number_of_messages() {\n  if (const auto num = mail_file_.number_of_records(); num == 0) {\n    return 0;\n  }\n  std::vector<mailrec> headers;\n  mail_file_.Seek(0);\n  if (!mail_file_.ReadVector(headers)) {\n    // WTF\n    return false;\n  }\n  int count = 0;\n  for (const auto& h : headers) {\n    if (!is_mailrec_deleted(h)) {\n      ++count;\n    }\n  }\n  return count;\n}\n\nint WWIVEmail::number_of_email_records() const {\n  if (!open_ || !mail_file_) {\n    return 0;\n  }\n  return static_cast<int>(mail_file_.number_of_records());\n}\n\n/** Temporary API to read the header from an email message. */\nbool WWIVEmail::read_email_header(int email_number, mailrec& m) {\n  if (!open_) {\n    return false;\n  }\n  if (mail_file_.number_of_records() == 0) {\n    return false;\n  }\n  if (!mail_file_.Read(email_number, &m)) {\n    return false;\n  }\n  if (is_mailrec_deleted(m)) {\n    return false;\n  }\n  return true;\n}\n\n/** Temporary API to read the header and text from an email message. */\nbool WWIVEmail::read_email_header_and_text(int email_number, mailrec& m, std::string& text) {\n  if (!read_email_header(email_number, m)) {\n    return false;\n  }\n  auto o =  readfile(m.msg);\n  if (!o) {\n    return false;\n  }\n  text = o.value();\n  return true;\n}\n\n/** Deletes an email by number */\nbool WWIVEmail::DeleteMessage(int email_number) {\n  if (!open_) { return false; }\n  const auto num_records = static_cast<decltype(email_number)>(mail_file_.number_of_records());\n  if (num_records == 0 || email_number > num_records) {\n    return false;\n  }\n\n  mailrec m{};\n  if (!mail_file_.Read(email_number, &m)) {\n    return false;\n  }\n\n  if (m.touser == 0 && m.tosys == 0) {\n    // Already deleted.\n    return true;\n  }\n\n  bool rm = true;\n  if (m.status & status_multimail) {\n    bool others_found = false;\n    for (auto i = 0; i < num_records; i++) {\n      if (i != email_number) {\n        mailrec m1{};\n        if (!mail_file_.Read(i, &m1)) { continue; }\n        if ((m.msg.stored_as == m1.msg.stored_as) && (m.msg.storage_type == m1.msg.storage_type) && (m1.daten != 0xffffffff)) {\n          others_found = true;\n        }\n      }\n    }\n    if (others_found) {\n      rm = false;\n    }\n  }\n  if (rm) {\n    (void) remove_link(m.msg);\n  }\n\n  if (m.tosys == 0) {\n    modify_email_waiting(config_, m.touser, -1);\n  }\n\n  // Clear out the email record and write it back to EMAIL.DAT\n  // so the slot may be reused later.\n  m.touser = 0;\n  m.tosys = 0;\n  m.daten = 0xffffffff;\n  m.msg.storage_type = 0;\n  m.msg.stored_as = 0xffffffff;\n  return mail_file_.Write(email_number, &m);\n}\n\nbool WWIVEmail::DeleteAllMailToOrFrom(int user_number) {\n  if (user_number <= 1) {\n    // You can not take command.\n    return false;\n  }\n  std::vector<mailrec> headers;\n  mail_file_.Seek(0);\n  if (!mail_file_.ReadVector(headers)) {\n    // WTF\n    return false;\n  }\n  for (auto i = 0; i < ssize(headers); i++) {\n    if (const auto& m = at(headers, i);\n        (m.tosys == 0 && m.touser == user_number) || (m.fromsys == 0 && m.fromuser == user_number)) {\n      DeleteMessage(i);\n    }\n  }\n  return true;\n}\n\n// Implementation Details\n\nbool WWIVEmail::add_email(const mailrec& m) {\n  if (!open_) {\n    return false;\n  }\n  auto recno = 0;\n  if (const int max_size = mail_file_.number_of_records(); max_size > 0) {\n    mailrec temprec{};\n    recno = max_size - 1;\n    mail_file_.Read(recno, &temprec);\n    while (recno > 0 && temprec.tosys == 0 && temprec.touser == 0) {\n      --recno;\n      mail_file_.Read(recno, &temprec);\n    }\n    if (temprec.tosys || temprec.touser) {\n      ++recno;\n    }\n  }\n\n  return mail_file_.Write(recno, &m);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/msgapi/email_wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_EMAIL_WWIV_H\n#define INCLUDED_SDK_EMAIL_WWIV_H\n\n#include \"core/datafile.h\"\n#include \"sdk/config.h\"\n#include \"sdk/msgapi/message.h\"\n#include \"sdk/msgapi/type2_text.h\"\n#include <cstdint>\n#include <string>\n\nnamespace wwiv::sdk::msgapi {\n\nclass WWIVMessageApi;\n\nclass EmailData {\npublic:\n  EmailData() = default;\n\n  /** The title for this email */\n  std::string title;\n  /** \n   * The full text of this email \n   * Expects data.text is of the form:\n   * SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n   */\n  std::string text;\n  /** Anonymous settings for this email. 0 for normal */\n  uint8_t anony = 0;\n  /** The user this email should be sent to (to username) */\n  uint16_t user_number = 0;\n  /** The system to send this email. 0 for local. (to system) */\n  uint16_t system_number = 0;\n  /** The user this email should be sent from. */\n  uint16_t from_user = 0;\n  /** The system that sent this email. 0 for local. */\n  uint16_t from_system = 0;\n  /** The network number that sent this email.*/\n  int from_network_number = 0;\n  /** The time stamp for this email. */\n  daten_t daten = 0;\n};\n\nclass WWIVEmail : private Type2Text {\npublic:\n  WWIVEmail(const wwiv::sdk::Config& config, const std::filesystem::path& data_filename,\n            const std::filesystem::path& text_filename, int max_net_num);\n\n  bool Close();\n\n  bool AddMessage(EmailData& data);\n\n  /** Total number of active email messages in the system. */\n  [[nodiscard]] int number_of_messages();\n  /** Total number of email records in the system. This includes any deleted messages. */\n  [[nodiscard]] int number_of_email_records() const;\n\n  /** Temporary API to read the header from an email message. */\n  bool read_email_header(int email_number, mailrec& m);\n  /** Temporary API to read the header and text from an email message. */\n  bool read_email_header_and_text(int email_number, mailrec& m, std::string& text);\n  /** Deletes an email by number */\n  bool DeleteMessage(int email_number);\n  /** Delete all email to a specified user */\n  bool DeleteAllMailToOrFrom(int user_number);\n\nprivate:\n  bool add_email(const mailrec& m);\n  const Config& config_;\n  const std::filesystem::path data_filename_;\n  core::DataFile<mailrec> mail_file_;\n  bool open_{false};\n  const int max_net_num_{-1};\n\n  static constexpr uint8_t STORAGE_TYPE = 2;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/message.h\"\n\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/msgapi/message_api.h\"\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::msgapi {\n\nMessageHeader::MessageHeader(const MessageApi* api)\n  : header_(postrec{}), api_(api) {}\n\nMessageHeader::MessageHeader(const postrec& header, std::string from, std::string to,\n                                     std::string in_reply_to, const MessageApi* api)\n    : header_(header), from_(std::move(from)), to_(std::move(to)),\n      in_reply_to_(std::move(in_reply_to)), api_(api) {}\n\nbool MessageHeader::local() const {\n  const auto net_num = header_.network.network_msg.net_number;\n  if (net_num >= api_->network().size()) {\n    // not a valid network number.\n    return true;\n  }\n  if (header_.ownersys == 0) {\n    // no network system\n    return true;\n  }\n  const int local_net = stl::at(api_->network(), net_num).sysnum;\n  return local_net == header_.ownersys;\n}\n\nstatic void ToggleBit(uint8_t& word, uint8_t bit, bool b) {\n  if (b) {\n    word |= bit;\n  }\n  else {\n    word &= ~bit;\n  }\n}\n\nvoid MessageHeader::set_locked(bool b) {\n  ToggleBit(header_.status, status_no_delete, b);\n}\n\nbool MessageHeader::deleted() const { return (header_.status & status_delete) != 0; }\n\nbool MessageHeader::unvalidated() const { return (header_.status & status_unvalidated) != 0; }\n\nvoid MessageHeader::set_unvalidated(bool b) {\n  ToggleBit(header_.status, status_unvalidated, b);\n}\n\nbool MessageHeader::locked() const { return (header_.status & status_no_delete) != 0; }\n\nvoid MessageHeader::set_deleted(bool b) {\n  ToggleBit(header_.status, status_delete, b);\n}\n\nint MessageHeader::net_number() const {\n  return header_.network.network_msg.net_number;\n}\n\nvoid MessageHeader::set_net_number(int nn) {\n  header_.network.network_msg.net_number = nn;\n}\n\nbool MessageHeader::pending_network() const {\n  return (header_.status & status_pending_net) != 0;\n}\n\nvoid MessageHeader::set_pending_network(bool b) {\n  ToggleBit(header_.status, status_pending_net, b);\n}\n\nbool MessageHeader::source_verified() const {\n  return (header_.status & status_post_source_verified) != 0;\n}\n\nbool MessageHeader::net_network_post() const {\n  return (header_.status & status_post_new_net) != 0;\n}\n\nuint32_t MessageHeader::last_read() const { return header_.qscan; }\n\nuint8_t MessageHeader::storage_type() const { return header_.msg.storage_type; }\n\nvoid MessageHeader::set_title(const std::string& t) {\n  auto title = t;\n  if (title.size() > 72) {\n    title.resize(72);\n  }\n  to_char_array(header_.title, title);\n}\n\nMessage::Message(MessageHeader&& header, MessageText&& text)\n    : header_(std::move(header)), text_(std::move(text)) {}\n\nMessage::Message(MessageHeader&& header, const std::string& text)\n  : header_(std::move(header)), text_(text) {}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/msgapi/message.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MESSAGE_H\n#define INCLUDED_SDK_MESSAGE_H\n\n#include \"sdk/vardec.h\"\n#include <memory>\n#include <string>\n\n\nnamespace wwiv::sdk::msgapi {\n\nclass MessageApi;\n\nclass MessageHeader {\npublic:\n  explicit MessageHeader(const MessageApi* api);\n\n  // Should only be used when reading a message from a type-2 message file.\n  // Needs to be public so make_unique will work on it.\n  MessageHeader(const postrec& header, std::string from, std::string to,\n    std::string in_reply_to, const MessageApi* api);\n\n  [[nodiscard]] std::string title() const { return header_.title; }\n  void set_title(const std::string&);\n  [[nodiscard]] std::string to() const { return to_.empty() ? \"All\" : to_; }\n  void set_to(const std::string& to) { to_ = to; }\n  [[nodiscard]] std::string from() const { return from_; }\n  void set_from(const std::string& f) { from_ = f; }\n  [[nodiscard]] uint16_t from_usernum() const { return header_.owneruser; }\n  void set_from_usernum(uint16_t n) { header_.owneruser = n; }\n  [[nodiscard]] uint16_t from_system() const { return header_.ownersys; }\n  void set_from_system(uint16_t n) { header_.ownersys = n; }\n  [[nodiscard]] daten_t daten() const { return header_.daten; }\n  void set_daten(daten_t d) { header_.daten = d; }\n  [[nodiscard]] uint8_t status() const { return header_.status; }   // TODO(rushfan): This should be generic\n  void set_status(uint8_t t) { header_.status = t; }\n  [[nodiscard]] uint8_t anony() const { return header_.anony; }      // TODO(rushfan): This should be generic\n  void set_anony(uint8_t a) { header_.anony = a; }\n  [[nodiscard]] std::string oaddress() const { return oaddress_; } // TODO(rushfan): Implement me!\n  void set_oaddress(const std::string& a) { oaddress_ = a; }\n  [[nodiscard]] std::string destination_address() const { return destination_address_; }\n  void set_destination_address(const std::string& a) { destination_address_ = a; }\n  [[nodiscard]] std::string in_reply_to() const { return in_reply_to_; }\n  void set_in_reply_to(const std::string& t) { in_reply_to_ = t; }\n\n  [[nodiscard]] bool local() const;\n  [[nodiscard]] bool private_msg() const { return false; } // we don't support private subs\n  void set_private_msg(bool b) { private_ = b; }\n\n  [[nodiscard]] bool unvalidated() const;\n  void set_unvalidated(bool b);\n  [[nodiscard]] bool locked() const; // \n  void set_locked(bool b);\n  [[nodiscard]] bool deleted() const;\n  void set_deleted(bool b);\n\n  // Return the primary network number this message was received on\n  [[nodiscard]] int net_number() const;\n  // Sets the primary network number this message was received on\n  void set_net_number(int nn);\n\n  [[nodiscard]] bool pending_network() const;\n  void set_pending_network(bool b);\n  [[nodiscard]] bool source_verified() const;\n  [[nodiscard]] bool net_network_post() const;\n\n  [[nodiscard]] const postrec& data() const { return header_; }\n\n  // Read only methods\n  // In WWIV last_read == highest_read.\n  [[nodiscard]] uint32_t last_read() const;\n  [[nodiscard]] uint8_t storage_type() const;\n\n  friend class WWIVMessageArea;\n\nprivate:\n  postrec header_{};\n  std::string from_;\n  std::string to_;\n  std::string in_reply_to_;\n  std::string oaddress_;\n  std::string destination_address_;\n  bool private_{ false };\n  const MessageApi* api_;\n};\n\nclass MessageText {\npublic:\n  MessageText() = default;\n  explicit MessageText(const std::string& text) : text_(text) {}\n  virtual ~MessageText() = default;\n  [[nodiscard]] virtual const std::string& string() const { return text_; }\n  virtual void set_text(const std::string& t) { text_ = t; };\n\nprivate:\n  std::string text_;\n};\n\nclass Message {\npublic:\n  Message(MessageHeader&& header, MessageText&& text);\n  Message(MessageHeader&& header, const std::string& text);\n  Message(MessageApi* api) : header_(api) {}\n  virtual ~Message() = default;\n  [[nodiscard]] virtual MessageHeader& header() { return header_; }\n  [[nodiscard]] virtual const MessageHeader& header() const { return header_; }\n  [[nodiscard]] virtual MessageText& text() { return text_; };\n  virtual void set_text(const std::string& t) { text_.set_text(t); };\n  [[nodiscard]] virtual const MessageText& text() const { return text_; };\nprivate:\n  MessageHeader header_;\n  MessageText text_;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_api.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/message_api.h\"\n\n#include \"core/log.h\"\n#include <string>\n#include <utility>\n\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk::msgapi {\n\nMessageArea::MessageArea(MessageApi* api) : api_(api) {}\nMessageArea::~MessageArea() = default;\n\nint MessageArea::max_messages() const {\n  if (max_messages_ == 0) {\n    return std::numeric_limits<int>::max();\n  }\n  return max_messages_;\n}\n\nMessageApi::MessageApi(const MessageApiOptions& options,\n                       const std::filesystem::path& root_directory,\n                       const std::filesystem::path& subs_directory,\n                       const std::filesystem::path& messages_directory,\n                       std::vector<Network> net_networks)\n    : options_(options), root_directory_(root_directory),\n      subs_directory_(subs_directory),\n      messages_directory_(messages_directory), net_networks_(std::move(net_networks)) {}\n\nstd::unique_ptr<MessageArea> MessageApi::CreateOrOpen(const wwiv::sdk::subboard_t& sub, int subnum) {\n  if (!Exist(sub)) {\n    LOG(INFO) << \"Message area: '\" << sub.filename << \"' does not exist. Attempting to create it.\";\n    // Since the area does not exist, let's create it automatically like WWIV always does.\n    if (!Create(sub, -1)) {\n      LOG(ERROR) << \"Failed to create area: \" << sub.filename << \" let's try to open it anyway.\";\n    }\n  }\n  return Open(sub, subnum);\n}\n\n} // namespace wwiv::sdk::msgapi\n"
  },
  {
    "path": "sdk/msgapi/message_api.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MSGAPI_MESSAGE_API_H\n#define INCLUDED_SDK_MSGAPI_MESSAGE_API_H\n\n#include \"sdk/msgapi/message_area.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/subxtr.h\"\n#include <stdexcept>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nclass MessageArea;\n\nenum class OverflowStrategy {\n  delete_one, delete_all, delete_none\n};\n\nstruct MessageApiOptions {\n  OverflowStrategy overflow_strategy = wwiv::sdk::msgapi::OverflowStrategy::delete_one;\n};\n\nclass bad_message_area : public ::std::runtime_error {\npublic:\n  explicit bad_message_area(const ::std::string& sub_filename) : ::std::runtime_error(sub_filename) {}\n};\n\nclass MessageApi {\npublic:\n  virtual ~MessageApi() = default;\n  MessageApi(\n    const MessageApiOptions& options,\n    const std::filesystem::path& root_directory,\n    const std::filesystem::path& subs_directory,\n    const std::filesystem::path& messages_directory,\n    std::vector<net::Network> net_networks);\n\n  /** Checks to see if the files for a subboard exist. */\n  [[nodiscard]] virtual bool Exist(const wwiv::sdk::subboard_t& sub) const = 0;\n  /** Opens a message area, throwing bad_message_area if it does not exist. */\n  [[nodiscard]] virtual bool Create(const wwiv::sdk::subboard_t& sub, int subnum) = 0;\n  /** Opens a message area, throwing bad_message_area if it does not exist. */\n  [[nodiscard]] virtual std::unique_ptr<MessageArea> Open(const wwiv::sdk::subboard_t& sub,\n                                                          int subnum) = 0;\n  /** Creates or Opens a message area. throwing bad_message_area if it exists but can not be opened.*/\n  [[nodiscard]] virtual std::unique_ptr<MessageArea> CreateOrOpen(const wwiv::sdk::subboard_t& sub,\n                                                                  int subnum);\n  /** Deletes the message area identified by filename: name */\n  [[nodiscard]] virtual bool Remove(const std::string& name) = 0;\n\n  [[nodiscard]] const std::vector<net::Network>& network() const { return net_networks_; }\n  [[nodiscard]] std::filesystem::path root_directory() const { return root_directory_; }\n  [[nodiscard]] MessageApiOptions options() const { return options_; }\n\n  // Last read\n  [[nodiscard]] virtual uint32_t last_read(int area) const = 0;\n  virtual void set_last_read(int area, uint32_t last_read) = 0;\n\n  // TODO(rushfan): Here's where we add hooks to the lastread system\n  // so that message api's created inside the bbs will share *qsc with\n  // the legacy code until it's all removed.\n\nprotected:\n  const MessageApiOptions options_;\n\n  const std::filesystem::path root_directory_;\n  const std::filesystem::path subs_directory_;\n  const std::filesystem::path messages_directory_;\n  std::vector<net::Network> net_networks_;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_api_wwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/message_api_wwiv.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/msgapi/message_area_wwiv.h\"\n\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::msgapi {\n\nWWIVMessageApi::WWIVMessageApi(const MessageApiOptions& options,\n                               const Config& config,\n                               const std::vector<Network>& net_networks,\n                               WWIVLastReadImpl* last_read)\n    : MessageApi(options, config.root_directory(), config.datadir(), config.msgsdir(),\n                 net_networks),\n      last_read_(last_read), config_(config) {}\n\nbool WWIVMessageApi::Exist(const wwiv::sdk::subboard_t& sub) const {\n  return File::Exists(FilePath(subs_directory_, StrCat(sub.filename, \".sub\")));\n}\n\nbool WWIVMessageApi::Create(const wwiv::sdk::subboard_t& sub, int subnum) {\n  return Create(sub.filename, \".sub\", \".dat\", subnum);\n}\n\nbool WWIVMessageApi::Create(const std::string& name, const std::string& sub_ext,\n                            const std::string& text_ext, int) {\n  LOG(INFO) << \"Creating: \" << name;\n  const auto fn = FilePath(subs_directory_, StrCat(name, sub_ext));\n  if (File::Exists(fn)) {\n    // Don't create if it already exists.\n    return false;\n  }\n  {\n    File fileSub(fn);\n    if (fileSub.Open(File::modeReadOnly | File::modeBinary)) {\n      // Don't create if we can open it.\n      return false;\n    }\n  }\n\n  File fileSub(fn);\n  if (!fileSub.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n    // Don't create if we fail to write it.\n    return false;\n  }\n\n  const auto text_filename = StrCat(name, text_ext);\n  File msgs_file(FilePath(messages_directory_, text_filename));\n  if (msgs_file.Open(File::modeReadOnly | File::modeBinary)) {\n    // Don't create since we have this file already.\n    return false;\n  }\n\n  {\n    // Create new Message Text (.DAT ) file.\n    if (msgs_file.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n      // I think we can skip this too since it doesn't do anything as we\n      // set the length on the file which fills it with zeros.\n      uint16_t gat[GAT_NUMBER_ELEMENTS] = { 0 };\n      msgs_file.Write(gat, GAT_SECTION_SIZE);\n      msgs_file.Close();\n      msgs_file.set_length(GAT_SECTION_SIZE + (75L * 1024L));\n    }\n    else {\n      LOG(ERROR) << \"Unable to create msgs file: \" << msgs_file.full_pathname();\n    }\n  }\n\n  if (name != EMAIL_NOEXT) {\n    // Create 5.1 style sub header for subs, but not for email.\n    const WWIVMessageAreaHeader header(wwiv_config_version(), 0);\n    fileSub.Write(&header.header(), sizeof(subfile_header_t));\n  }\n  return true;\n}\n\nbool WWIVMessageApi::Remove(const std::string&) {\n  // todo: delete lastread/qscan\n  // todo: delete sub files.\n  // todo: delete from conf\n  return false;\n}\n\nstd::unique_ptr<MessageArea> WWIVMessageApi::Open(const wwiv::sdk::subboard_t& sub, int subnum) {\n  std::filesystem::path sub_fullpath;\n  std::filesystem::path msgs_fullpath;\n  {\n    const auto sub_fn = FilePath(subs_directory_, StrCat(sub.filename, \".sub\"));\n    const auto msgs_fn = FilePath(messages_directory_, StrCat(sub.filename, \".dat\"));\n    if (!File::Exists(sub_fn)) {\n      throw bad_message_area(sub.filename);\n    }\n    File fileSub(sub_fn);\n    if (!fileSub.Open(File::modeReadOnly | File::modeBinary)) {\n      throw bad_message_area(sub.filename);\n    }\n\n    if (!File::Exists(msgs_fn)) {\n      File create_msgs_file(FilePath(messages_directory_, StrCat(sub.filename, \".dat\")));\n      if (!create_msgs_file.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n        throw bad_message_area(sub.filename);\n      }\n    }\n    File msgs_file(msgs_fn);\n    if (!msgs_file.Open(File::modeReadOnly | File::modeBinary)) {\n      throw bad_message_area(sub.filename);\n    }\n\n    sub_fullpath = sub_fn;\n    msgs_fullpath = msgs_fn;\n  }\n  auto area = std::make_unique<WWIVMessageArea>(this, sub, sub_fullpath, msgs_fullpath, subnum, net_networks_);\n  area->set_max_messages(sub.maxmsgs);\n  area->set_storage_type(sub.storage_type);\n  return area;\n}\n\nstd::unique_ptr<WWIVEmail> WWIVMessageApi::OpenEmail() {\n  const auto data = FilePath(subs_directory_, EMAIL_DAT);\n  const auto text = FilePath(messages_directory_, EMAIL_DAT);\n  {\n    if (!File::Exists(data)) {\n      // Create it if it doesn't exist.  We still can have an odd case\n      // where 1 file exists, but that's not ever normal. so we'll\n      // complain later about not being able to create this.\n      [[maybe_unused]] auto _ = Create(\"email\", \".dat\", \".dat\", 0);\n      // Return the newly created WWIVEmail object.\n      return std::make_unique<WWIVEmail>(config_, data, text, stl::size_int(net_networks_));\n    }\n\n    File datafile(data);\n    if (!datafile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      LOG(ERROR) << \"Unable to open datafile: \" << data;\n      return {};\n    }\n\n    if (!File::Exists(text)) {\n      LOG(ERROR) << \"'\" << data << \"' exists, but '\" << text << \"' does not! \";\n      return {};\n    }\n    File textfile(text);\n    if (!textfile.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n      LOG(ERROR) << \"Unable to open msgsfile: \" << data;\n      return {};\n    }\n  }\n\n  return std::make_unique<WWIVEmail>(config_, data, text, stl::size_int(net_networks_));\n}\n\nuint32_t WWIVMessageApi::last_read(int area) const {\n  if (last_read_) {\n    return last_read_->last_read(area);\n  }\n  return 0;\n}\n\nvoid WWIVMessageApi::set_last_read(int area, uint32_t last_read) {\n  if (last_read_) {\n    last_read_->set_last_read(area, last_read);\n  }\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/msgapi/message_api_wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MSGAPI_MESSAGE_API_WWIV_H\n#define INCLUDED_SDK_MSGAPI_MESSAGE_API_WWIV_H\n\n#include \"sdk/config.h\"\n#include \"sdk/msgapi/email_wwiv.h\"\n#include \"sdk/msgapi/message_api.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nclass WWIVMessageArea;\n\n// Can't merge with MessageAreaLastRead since that knows the area\n// Yet this one knows the user since it's used in the context\n// of a user session, otherwise we ignore the last_read values\n// when used from tools.\nclass WWIVLastReadImpl {\npublic:\n  virtual ~WWIVLastReadImpl() = default;\n  [[nodiscard]] virtual uint32_t last_read(int area) const = 0;\n  virtual void set_last_read(int area, uint32_t last_read) = 0;\n  virtual void Load() = 0;\n  virtual void Save() = 0;\n};\n\nclass NullLastReadImpl final : public WWIVLastReadImpl {\n  [[nodiscard]] uint32_t last_read(int) const override { return 0; }\n  void set_last_read(int, uint32_t) override {}\n  void Load() override {}\n  void Save() override {}\n};\n\nclass WWIVMessageApi final : public MessageApi {\npublic:\n  WWIVMessageApi(const MessageApiOptions& options, const Config& config,\n                 const std::vector<net::Network>& net_networks, WWIVLastReadImpl* last_read);\n\n  [[nodiscard]] bool Exist(const subboard_t& sub) const override;\n  [[nodiscard]] bool Create(const std::string& name, const std::string& sub_ext,\n                      const std::string& text_ext, int subnum);\n  [[nodiscard]] bool Create(const subboard_t& sub, int subnum) override;\n  [[nodiscard]] bool Remove(const std::string& name) override;\n  [[nodiscard]] std::unique_ptr<MessageArea> Open(const subboard_t& sub, int subnum) override;\n  [[nodiscard]] std::unique_ptr<WWIVEmail> OpenEmail();\n  [[nodiscard]] uint32_t last_read(int area) const override;\n  void set_last_read(int area, uint32_t last_read) override;\n  [[nodiscard]] const Config& config() const noexcept { return config_; }\n\nprivate:\n  std::unique_ptr<WWIVLastReadImpl> last_read_;\n  const Config config_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_area.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/message_area_wwiv.h\"\n\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/msgapi/message_api.h\"\n\n#include <string>\n\nnamespace wwiv::sdk::msgapi {\n\n[[nodiscard]] uint32_t MessageAreaLastRead::last_read(int user_number) {\n  if (message_area_number_ < 0) {\n    return 0;\n  }\n  return api_->last_read(message_area_number_);\n}\n\nbool MessageAreaLastRead::set_last_read(int user_number, uint32_t last_read, uint32_t highest_read) {\n  if (message_area_number_ >= 0) {\n    api_->set_last_read(message_area_number_, std::max<uint32_t>(last_read, highest_read));\n  }\n  return true;\n}\n\nbool MessageAreaLastRead::Close() { return true; }\n\n} // namespace wwiv::sdk::msgapi\n"
  },
  {
    "path": "sdk/msgapi/message_area.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MESSAGE_AREA_H\n#define INCLUDED_SDK_MESSAGE_AREA_H\n\n#include \"core/wwivport.h\"\n#include \"sdk/msgapi/message.h\"\n#include <limits>\n#include <memory>\n#include <optional>\n#include <string>\n\nnamespace wwiv::sdk::msgapi {\n\nclass Message;\nclass MessageHeader;\nclass MessageText;\n\nenum class message_anonymous_t {\n  anonymous_none,\n  anonymous_allowed,\n  anonymous_dear_abby,\n  anonymous_forced,\n  anonymous_real_names_only\n};\n\nclass MessageAreaHeader {};\n\n// Since message_api.h includes us, we must forward declare.\nclass MessageApi;\n\nclass MessageAreaLastRead {\npublic:\n  MessageAreaLastRead(MessageApi* api, int message_area_number) :\n    api_(api), message_area_number_(message_area_number) {}\n  virtual ~MessageAreaLastRead() = default;\n\n  [[nodiscard]] uint32_t last_read(int user_number);\n  bool set_last_read(int user_number, uint32_t last_read, uint32_t highest_read);\n  bool Close();\n\nprivate:\n  MessageApi* api_;\n  int message_area_number_;\n};\n\nstruct MessageAreaOptions {\n  /** Should the post also be sent to the network automatically */\n  bool send_post_to_network{false};\n\n  /**\n   * Should a RE and BY line be added automatically.  Note tht this\n   * will only happen if there is no FTN network for the sub, since\n   * the FidoAddr kludge is added in that case instead.\n   */\n  bool add_re_and_by_line{true};\n};\n\nclass MessageArea {\npublic:\n  explicit MessageArea(MessageApi* api);\n  virtual ~MessageArea();\n  \n  // Message Sub Specific Operations\n  virtual bool Close() = 0;\n  virtual bool Lock() = 0;\n  virtual bool Unlock() = 0;\n  [[nodiscard]] virtual std::unique_ptr<MessageAreaHeader> ReadMessageAreaHeader() = 0;\n  virtual void WriteMessageAreaHeader(const MessageAreaHeader& header) = 0;\n  [[nodiscard]] virtual int FindUserMessages(const std::string& user_name) = 0;\n  [[nodiscard]] virtual int number_of_messages() = 0;\n\n  // message specific\n  [[nodiscard]] virtual std::optional<Message> ReadMessage(int message_number) = 0;\n  [[nodiscard]] virtual std::optional<MessageHeader> ReadMessageHeader(int message_number) = 0;\n  [[nodiscard]] virtual std::optional<MessageText> ReadMessageText(int message_number) = 0;\n  [[nodiscard]] virtual bool AddMessage(Message& message, const MessageAreaOptions& options) = 0;\n  [[nodiscard]] virtual bool DeleteMessage(int message_number) = 0;\n  /** Updates message_number to point to the */\n  virtual bool ResyncMessage(int& message_number) = 0;\n  virtual bool ResyncMessage(int& message_number, Message& message) = 0;\n\n  /** Creates a new empty message for this area. */\n  [[nodiscard]] virtual Message CreateMessage() = 0;\n  [[nodiscard]] virtual bool Exists(daten_t d, const std::string& title, uint16_t from_system, uint16_t from_user) = 0;\n\n  [[nodiscard]] int max_messages() const;\n  void set_max_messages(int m) { max_messages_ = m; }\n\n  [[nodiscard]] uint8_t storage_type() const { return storage_type_; }\n  void set_storage_type(uint8_t t) { storage_type_ = t; }\n\n  [[nodiscard]] virtual const MessageAreaLastRead& last_read() const noexcept = 0;\n  [[nodiscard]] virtual message_anonymous_t anonymous_type() const noexcept = 0;\n\nprotected:\n  static constexpr uint8_t DEFAULT_WWIV_STORAGE_TYPE = 2;\n\n  // Not owned.\n  MessageApi* api_;\n  int max_messages_{std::numeric_limits<int>::max()};\n  uint8_t storage_type_{DEFAULT_WWIV_STORAGE_TYPE};\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_area_wwiv.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/message_area_wwiv.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/ssm.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/packets.h\"\n\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\nconstexpr char CZ = 26;\n\nstatic bool WriteHeader(DataFile<postrec>& file, const WWIVMessageAreaHeader& header) {\n  auto p = header.header();\n  // Increment the mod_count every time we write the header.\n  p.mod_count++;\n  return file.Write(0, reinterpret_cast<const postrec*>(&p));\n}\n\nstatic std::unique_ptr<WWIVMessageAreaHeader> ReadHeader(DataFile<postrec>& file) {\n  subfile_header_t raw_header{};\n  if (!file.Read(0, reinterpret_cast<postrec*>(&raw_header))) {\n    // Invalid header.\n    auto header = std::make_unique<WWIVMessageAreaHeader>(0, 0);\n    header->set_initialized(false);\n    return header;\n  }\n  if (raw_header.active_message_count > file.number_of_records()) {\n    VLOG(1) << \"Header claims too many messages, raw_header.active_message_count(\"\n            << raw_header.active_message_count << \") > file.number_of_records(\"\n            << file.number_of_records() << \")\";\n    raw_header.active_message_count = static_cast<uint16_t>(file.number_of_records());\n  }\n\n  if (strncmp(raw_header.signature, \"WWIV\\x1A\", 5) != 0) {\n    VLOG(3) << \"Missing 5.x header on sub: \" << file.file();\n    const auto saved_count = raw_header.active_message_count;\n    memset(&raw_header, 0, sizeof(subfile_header_t));\n    // We don't have a modern header. Create one now. Next write\n    // from here will have it.\n    to_char_array(raw_header.signature, \"WWIV\\x1A\");\n    raw_header.active_message_count = saved_count;\n    raw_header.revision = 1;\n    raw_header.wwiv_version = wwiv_config_version();\n    raw_header.daten_created = DateTime::now().to_daten_t();\n  }\n\n  return std::make_unique<WWIVMessageAreaHeader>(raw_header);\n}\n\n\nWWIVMessageAreaHeader::WWIVMessageAreaHeader(int ver, uint32_t num_messages)\n    : header_(subfile_header_t()) {\n  to_char_array(header_.signature, \"WWIV\\x1A\");\n  header_.revision = 1;\n  header_.wwiv_version = static_cast<uint16_t>(ver);\n  header_.daten_created = DateTime::now().to_daten_t();\n  header_.active_message_count = static_cast<uint16_t>(num_messages);\n}\n\nWWIVMessageArea::WWIVMessageArea(WWIVMessageApi* api, const subboard_t& sub,\n                                 std::filesystem::path sub_filename,\n                                 std::filesystem::path text_filename, int subnum,\n                                 std::vector<Network> net_networks)\n    : MessageArea(api), Type2Text(std::move(text_filename)), wwiv_api_(api), sub_(sub),\n      sub_filename_(std::move(sub_filename)), header_{}, net_networks_(std::move(net_networks)),\n      last_read_(api, subnum) {\n  DataFile<postrec> subfile(sub_filename_, File::modeBinary | File::modeReadOnly);\n  if (!subfile) {\n    // TODO: throw exception\n  } else {\n    const auto h = ReadHeader(subfile);\n    header_ = h->raw_header();\n  }\n  open_ = true;\n}\n\nWWIVMessageArea::~WWIVMessageArea() { WWIVMessageArea::Close(); }\n\nbool WWIVMessageArea::Close() {\n  open_ = false;\n  return true;\n}\n\nbool WWIVMessageArea::Lock() { return false; }\n\nbool WWIVMessageArea::Unlock() { return false; }\n\nstd::unique_ptr<MessageAreaHeader> WWIVMessageArea::ReadMessageAreaHeader() {\n  DataFile<postrec> sub(sub_filename_);\n  auto h = ReadHeader(sub);\n  header_ = h->raw_header();\n  return h;\n}\n\nvoid WWIVMessageArea::WriteMessageAreaHeader(const MessageAreaHeader&) {\n  // Not implemented on wwiv.\n}\n\nint WWIVMessageArea::FindUserMessages(const std::string&) {\n  // Not implemented on wwiv.\n  return 0;\n}\n\nint WWIVMessageArea::number_of_messages() {\n  DataFile<postrec> sub(sub_filename_);\n  if (!sub) {\n    // TODO: throw exception\n    return 0;\n  }\n\n  const auto file_num_records = static_cast<int>(sub.number_of_records());\n  const auto wwiv_header = ReadHeader(sub);\n  if (!wwiv_header->initialized()) {\n    // TODO: throw exception\n    // This is an invalid header.\n    return 0;\n  }\n  const int msgs = wwiv_header->active_message_count();\n  if (msgs > file_num_records) {\n    LOG(ERROR) << \"Mismatch between header: \" << msgs << \" and filesize: \" << file_num_records;\n    return std::min(msgs, file_num_records);\n  }\n  return msgs;\n}\n\nstd::optional<wwiv_parsed_text_fieds> WWIVMessageArea::ParseMessageText(const postrec& header,\n                                                                        int message_number) {\n\n  // Some of the message header information ends up in the text.\n  // line1: From username (i.e. rushfan #1 @5161)\n  // line2: Date (again, same as daten but is formatted by the sender)\n  // optional lines:\n  // RE: Title (title this is a reply to, mostly redundant since the title will contain it too)\n  // BY: Author (author of the post this is a reply to, could be considered the \"to\" person for this\n  // message. ^DControl Lines (we have many) ^D# (0 = network, >0 = tag lines)\n\n  auto o = readfile(header.msg);\n  if (!o) {\n    return std::nullopt;\n  }\n  const auto& raw_text = o.value();\n\n  wwiv_parsed_text_fieds r;\n  // Use the 3 arg form of split string so we don't strip blank lines.\n  auto lines = SplitString(raw_text, \"\\n\", false);\n  auto it = std::begin(lines);\n  if (it == std::end(lines)) {\n    VLOG(1) << \"Malformed message(1) #\" << message_number << \"; title: '\" << header.title << \"' \"\n            << header.owneruser << \"@\" << header.ownersys;\n    return {r};\n  }\n\n  r.from_username = StringTrim(*it++);\n  if (it == lines.end()) {\n    VLOG(1) << \"Malformed message(2) #\" << message_number << \"; title: '\" << header.title << \"' \"\n            << header.owneruser << \"@\" << header.ownersys;\n    return {r};\n  }\n\n  r.date = StringTrim(*it++);\n  if (it == std::end(lines)) {\n    VLOG(1) << \"Malformed message(3) #\" << message_number << \"; title: '\" << header.title << \"' \"\n            << header.owneruser << \"@\" << header.ownersys;\n    return {r};\n  }\n\n  for (; it != std::end(lines); ++it) {\n    auto line = StringTrim(*it);\n    if (!line.empty() && line.front() == CD) {\n      r.text += line;\n      r.text += \"\\r\\n\";\n    } else if (starts_with(line, \"RE:\")) {\n      r.in_reply_to = StringTrim(line.substr(3));\n    } else if (starts_with(line, \"BY:\")) {\n      r.to = StringTrim(line.substr(3));\n    } else {\n      // No more special lines, the rest is just text.\n      for (; it != std::end(lines); ++it) {\n        auto text_line = *it;\n        // Terminate the string with a control-Z.\n        const auto cz_pos = text_line.find(CZ);\n        if (cz_pos != std::string::npos) {\n          text_line = text_line.substr(0, cz_pos);\n        }\n        // Trim all remaining nulls.\n        const auto null_pos = text_line.find(static_cast<char>(0));\n        if (null_pos != std::string::npos) {\n          text_line.resize(null_pos);\n        }\n        StringTrim(&text_line);\n        if (!text_line.empty()) {\n          r.text += text_line;\n          r.text += \"\\r\\n\";\n        }\n      }\n      break;\n    }\n  }\n  return {r};\n}\n\nstd::optional<Message> WWIVMessageArea::ReadMessage(int message_number) {\n  const auto num_messages = number_of_messages();\n  if (message_number < 1) {\n    return std::nullopt;\n  }\n  if (message_number > num_messages) {\n    message_number = num_messages;\n  }\n\n  DataFile<postrec> sub(sub_filename_);\n  if (!sub) {\n    // TODO: throw exception\n    return std::nullopt;\n  }\n  postrec header{};\n  sub.Read(message_number, &header);\n  if (header.msg.storage_type != 2) {\n    // We only support type-2 on the WWIV API.\n    return std::nullopt;\n  }\n\n  if (const auto o = ParseMessageText(header, message_number)) {\n    const auto& r = o.value();\n    return Message(\n        MessageHeader(header, r.from_username, r.to, r.in_reply_to, api_),\n        r.text);\n  }\n  return std::nullopt;\n}\n\nstd::optional<MessageHeader> WWIVMessageArea::ReadMessageHeader(int message_number) {\n  auto msg = ReadMessage(message_number);\n  if (!msg) {\n    return std::nullopt;\n  }\n  return msg->header();\n}\n\nstd::optional<MessageText> WWIVMessageArea::ReadMessageText(int message_number) {\n  auto msg = ReadMessage(message_number);\n  if (!msg) {\n    return std::nullopt;\n  }\n  return msg->text();\n}\n\nstatic uint32_t next_qscan_value_and_increment_post(const std::filesystem::path& bbsdir) {\n  statusrec_t statusrec{};\n  const Config config(bbsdir);\n  if (!config.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load CONFIG.DAT.\";\n    return 1;\n  }\n  DataFile<statusrec_t> file(FilePath(config.datadir(), STATUS_DAT),\n                             File::modeBinary | File::modeReadWrite);\n  if (!file) {\n    return 0;\n  }\n  if (!file.Read(0, &statusrec)) {\n    return 0;\n  }\n  const auto next_qscan = statusrec.qscanptr++;\n  ++statusrec.msgposttoday;\n  if (!file.Write(0, &statusrec)) {\n    return 0;\n  }\n  return next_qscan;\n}\n\n/**\n * Deletes all excess messages in an area, depending on the\n * overflow strategy set on the API.\n *\n * Note: This should be called by AddMessage *after* posting a new\n * message successful, since there's no sense in deleting a post if\n * adding a new one has not succeeded.\n *\n * Returns the number of messages deleted.\n */\nint WWIVMessageArea::DeleteExcess() {\n  if (api_->options().overflow_strategy == OverflowStrategy::delete_none) {\n    LOG(INFO) << \"overflow_strategy is delete_none. Not deleting overflow messages\";\n    return 0;\n  }\n\n  int result = 0;\n  auto done = false;\n  while (!done) {\n    if (api_->options().overflow_strategy == OverflowStrategy::delete_one) {\n      LOG(INFO) << \"overflow_strategy is delete_one.\";\n      done = true;\n    }\n    if (const auto num = number_of_messages(); num <= max_messages_) {\n      VLOG(1) << \"No overflow messages. \" << num << \" <= \" << max_messages_;\n      return result;\n    }\n    int i = 1;\n    int dm = 0;\n    while (i <= number_of_messages()) {\n      const auto pp = ReadMessageHeader(i);\n      if (!pp) {\n        break;\n      }\n      if (!pp->locked()) {\n        dm = i;\n        break;\n      }\n      ++i;\n    }\n    if (dm == 0) {\n      LOG(INFO) << \"DeleteExcess: No message to delete.\";\n      return result;\n    }\n    if (!DeleteMessage(dm)) {\n      LOG(WARNING) << \"DeleteExcess: Failed to delete message #\" << dm;\n      return result;\n    }\n    VLOG(1) << \"DeleteExcess: Deleted message #\" << dm;\n    ++result;\n  }\n  return result;\n}\n\nstatic bool has_ftn_network(const std::vector<subboard_network_data_t>& sub_nets,\n                            const std::vector<Network>& nets) {\n  for (const auto& x : sub_nets) {\n    if (x.net_num >= 0 && x.net_num < stl::ssize(nets)) {\n      if (at(nets, x.net_num).type == network_type_t::ftn) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool WWIVMessageArea::AddMessage(Message& message, const MessageAreaOptions& options) {\n  messagerec m{STORAGE_TYPE, 0xffffff};\n\n  const auto& header = message.header();\n  auto p = header.data();\n  p.anony = 0;\n  p.msg = m;\n  p.ownersys = header.from_system();\n  p.owneruser = header.from_usernum();\n  if (p.qscan == 0) {\n    // new message.\n    VLOG(3) << \"AddMessage needs a qscan\";\n    p.qscan = next_qscan_value_and_increment_post(api_->root_directory());\n    if (p.qscan == 0) {\n      LOG(ERROR) << \"Failed to get qscan value!\";\n      return false;\n    }\n  } else {\n    VLOG(2) << \"AddMessage called with existing qscan ptr: title: \" << message.header().title()\n            << \"; qscan: \" << header.last_read();\n  }\n  p.daten = header.daten();\n  p.status = header.status();\n\n  static const char crlf[] = \"\\r\\n\";\n  // Fix up the text first.\n  {\n    std::ostringstream ss;\n    const auto has_ftn = has_ftn_network(sub_.nets, net_networks_);\n    // Right now we'll only add the Fido Kludge and also PID if we're also\n    // responsible for sending out the message to the network.  Note that we\n    // still add these FTN kludges in all message types.\n    const auto control_d_zero = fmt::sprintf(\"%c0\", CD);\n    auto to_name = message.header().to();\n    if (!to_name.empty() && to_name != \"All\" && has_ftn) {\n      // Only add this if we're sending this out to the network from the\n      // SDK, otherwise whomever is doing that should do so.\n      ss << control_d_zero << \"FidoAddr: \" << message.header().to() << crlf;    \n    }\n    auto title = message.header().title();\n    if (!title.empty() && title.front() != '\"' && !has_ftn && options.add_re_and_by_line) {\n      // Don't add RE: line if we have a \"^D0FidoAddr\" line.\n      ss << \"RE: \" << title << crlf;\n    }\n    if (!to_name.empty() && !has_ftn && options.add_re_and_by_line) {\n      ss << \"BY: \" << to_name << crlf;\n    }\n    ss << message.text().string();\n    message.set_text(ss.str());\n  }\n\n  // if (a()->user()->restrict_validate()) {\n  //  p.status |= status_unvalidated;\n  //}\n  // If we need network validation, then mark it as such.\n  // We force the issue here if it wasn't already done.\n  if (!sub_.nets.empty()) {\n    if (sub_.anony & anony_val_net && !header.pending_network()) {\n      p.status |= status_pending_net;\n      UserManager um(wwiv_api_->config());\n      SSM ssm(wwiv_api_->config(), um);\n      ssm.send_local(1, StrCat(\"Unvalidated net posts on: \", sub_.name));\n    } else if (options.send_post_to_network) {\n      LOG(INFO) << \"** Sending the newly added message out on all of the networks.\";\n      auto net = *sub_.nets.begin();\n      // Create a base packet from the 1st network entry.\n      auto packet = create_packet_from_wwiv_message(message, net.stype, {});\n      // Send the packet to everyone who needs is.\n      send_post_to_subscribers(wwiv_api_->network(), net.net_num, net.stype, sub_, packet, {},\n                               subscribers_send_to_t::all_subscribers);\n    } else {\n      VLOG(1) << \"Not sending message to the network\";\n    }\n  }\n\n  // Set the text to be in WWIV Message Base Format.\n  // FROM<CRLF>DATE<CRLF>TEXT\n  std::ostringstream ss;\n  ss << header.from() << crlf;\n  ss << daten_to_wwivnet_time(header.daten()) << crlf;\n  ss << message.text().string();\n  auto text = ss.str();\n\n  // WWIV 4.x requires a control-Z to terminate the message, WWIV 5.x\n  // does not, and removes it on read.\n  if (text.back() != CZ) {\n    text.push_back(CZ);\n  }\n\n  auto msg = savefile(text);\n  if (!msg) {\n    LOG(ERROR) << \"Failed to save message text.\";\n    return false;\n  }\n  p.msg = msg.value();\n  auto result = add_post(p);\n  if (result) {\n    DeleteExcess();\n  }\n  return result;\n}\n\nbool WWIVMessageArea::DeleteMessage(int message_number) {\n  const auto num_messages = number_of_messages();\n  if (message_number < 1) {\n    return false;\n  }\n  if (message_number > num_messages) {\n    return false;\n  }\n\n  DataFile<postrec> sub(sub_filename_,\n                        File::modeBinary | File::modeCreateFile | File::modeReadWrite);\n  if (!sub) {\n    // TODO: throw exception\n    return false;\n  }\n  postrec post{};\n  sub.Read(message_number, &post);\n  if (post.msg.storage_type != 2) {\n    // We only support type-2 on the WWIV API.\n    return false;\n  }\n\n  // Remove text.  Ignore the return code, try to remove the header anyway.\n  (void)remove_link(post.msg);\n\n  // Remove post record.\n  for (auto cur = message_number + 1; cur <= num_messages; cur++) {\n    postrec tmp{};\n    sub.Read(cur, &tmp);\n    sub.Write(cur - 1, &tmp);\n  }\n\n  // Update header.\n  postrec header{};\n  sub.Read(0, &header);\n  // decrement number of posts.\n  // TODO(rushfan): Should we check these?\n  --header.owneruser;\n  header.owneruser = static_cast<uint16_t>(std::max(0, num_messages - 1));\n  sub.Write(0, &header);\n\n  return true;\n}\n\nbool WWIVMessageArea::ResyncMessage(int& message_number) {\n  const auto m = ReadMessage(message_number);\n  if (!m) {\n    if (const auto num_messages = number_of_messages(); message_number > num_messages) {\n      message_number = num_messages;\n      return true;\n    }\n    return false;\n  }\n\n  if (!HasSubChanged()) {\n    // Since we also use resynch to see if were past the last message...\n    // return true;\n  }\n\n  // remember m is destructed after this message call.\n  return ResyncMessageImpl(message_number, m.value());\n}\n\nbool WWIVMessageArea::HasSubChanged() const {\n  const auto last_read_header = this->header_;\n  DataFile<postrec> sub(sub_filename_, File::modeBinary | File::modeReadOnly);\n  const auto h = ReadHeader(sub);\n  const auto current_read_header = h->raw_header();\n\n  return current_read_header.mod_count > last_read_header.mod_count;\n}\n\nbool WWIVMessageArea::ResyncMessage(int& message_number, Message& raw_message) {\n  if (!HasSubChanged()) {\n    // Since we also use resynch to see if were past the last message...\n    // return true;\n  }\n\n  // Assume it has changed.\n  return ResyncMessageImpl(message_number, raw_message);\n}\n\nstatic bool IsSamePost(const postrec& l, const postrec& r) {\n  return l.qscan == r.qscan && l.anony == r.anony && l.daten == r.daten &&\n         l.ownersys == r.ownersys && l.owneruser == r.owneruser &&\n         l.msg.stored_as == r.msg.stored_as;\n}\n\nbool WWIVMessageArea::ResyncMessageImpl(int& message_number, const Message& message) {\n  const auto& p = message.header().data();\n\n  if (const auto num_messages = number_of_messages(); message_number > num_messages) {\n    message_number = num_messages;\n    return true;\n  }\n\n  auto pp1 = ReadMessageHeader(message_number);\n  if (!pp1) {\n    return true;\n  }\n\n  if (IsSamePost(pp1->header_, p)) {\n    return true;\n  }\n  if (p.qscan < pp1->header_.qscan) {\n    if (const auto num_msgs = number_of_messages(); message_number > num_msgs) {\n      message_number = num_msgs + 1;\n    }\n    for (auto i = message_number - 1; i > 0; i--) {\n      pp1 = ReadMessageHeader(i);\n      if (!pp1) {\n        continue;\n      }\n      if (p.qscan >= pp1->header_.qscan || IsSamePost(p, pp1->header_)) {\n        message_number = i;\n        return true;\n      }\n    }\n    message_number = 0;\n    return true;\n  }\n\n  // Search the full list\n  const auto num_msgs = number_of_messages();\n  for (auto i = message_number + 1; i <= num_msgs; i++) {\n    pp1 = ReadMessageHeader(i);\n    if (!pp1) {\n      continue;\n    }\n    if (p.qscan >= pp1->header_.qscan || IsSamePost(p, pp1->header_)) {\n      message_number = i;\n      return true;\n    }\n  }\n  message_number = num_msgs;\n  return true;\n}\n\nMessage WWIVMessageArea::CreateMessage() {\n  return Message(api_);\n}\n\nbool WWIVMessageArea::Exists(daten_t d, const std::string& title, uint16_t from_system,\n                             uint16_t from_user) {\n  DataFile<postrec> sub(sub_filename_);\n  if (!sub) {\n    return false;\n  }\n  std::vector<postrec> headers;\n  if (!sub.ReadVector(headers)) {\n    return false;\n  }\n\n  for (const auto& h : headers) {\n    if (h.status & status_delete) {\n      continue;\n    }\n    // Since we don't have a global message id, use the combination of\n    // date + title + from system + from user.\n    if (h.daten == d && iequals(h.title, title) && h.ownersys == from_system &&\n        h.owneruser == from_user) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nconst MessageAreaLastRead& WWIVMessageArea::last_read() const noexcept { return last_read_; }\n\nmessage_anonymous_t WWIVMessageArea::anonymous_type() const noexcept {\n  switch (sub_.anony & 0x0f) {\n  case anony_none:\n    return message_anonymous_t::anonymous_none;\n  case anony_enable_anony:\n    return message_anonymous_t::anonymous_allowed;\n  case anony_enable_dear_abby:\n    return message_anonymous_t::anonymous_dear_abby;\n  case anony_force_anony:\n    return message_anonymous_t::anonymous_forced;\n  case anony_real_name:\n    return message_anonymous_t::anonymous_real_names_only;\n  default:\n    // WTF CHECK?\n    return message_anonymous_t::anonymous_none;\n  }\n}\n\n// Implementation Details\n\nbool WWIVMessageArea::add_post(const postrec& post) {\n  DataFile<postrec> sub(sub_filename_, File::modeBinary | File::modeReadWrite);\n  if (!sub) {\n    return false;\n  }\n  if (sub.number_of_records() == 0) {\n    return false;\n  }\n  auto wwiv_header = ReadHeader(sub);\n  if (!wwiv_header->initialized()) {\n    // This is an invalid header.\n    return false;\n  }\n  const uint32_t msgnum = wwiv_header->increment_active_message_count();\n\n  // add the new post\n  if (!sub.Write(msgnum, &post)) {\n    return false;\n  }\n  // No reason other than make sure we're not const.\n  ++nonce_;\n  // Write the header now.\n  return WriteHeader(sub, *wwiv_header);\n}\n\n} // namespace wwiv::sdk::msgapi\n"
  },
  {
    "path": "sdk/msgapi/message_area_wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MESSAGE_AREA_WWIV_H\n#define INCLUDED_SDK_MESSAGE_AREA_WWIV_H\n\n#include \"sdk/msgapi/message.h\"\n#include \"sdk/msgapi/message_api.h\"\n#include \"sdk/msgapi/type2_text.h\"\n#include <cstdint>\n#include <filesystem>\n#include <memory>\n#include <string>\n\nnamespace wwiv::sdk::msgapi {\n\nclass WWIVMessageApi;\n\nclass WWIVMessageAreaHeader : public MessageAreaHeader {\npublic:\n  explicit WWIVMessageAreaHeader(subfile_header_t& header) : header_(header) {}\n  WWIVMessageAreaHeader(int ver, uint32_t num_messages);\n\n  [[nodiscard]] const subfile_header_t& header() const { return header_; }\n  [[nodiscard]] uint16_t active_message_count() const { return header_.active_message_count; }\n  void set_active_message_count(uint16_t active_message_count) {\n    header_.active_message_count = active_message_count;\n  }\n  uint16_t increment_active_message_count() { return ++header_.active_message_count; }\n  [[nodiscard]] bool initialized() const { return initialized_; }\n  void set_initialized(bool initialized) { initialized_ = initialized; }\n\n  [[nodiscard]] subfile_header_t raw_header() const { return header_; }\n\nprivate:\n  subfile_header_t header_{};\n  bool initialized_{true};\n};\n\nstruct wwiv_parsed_text_fieds {\n  std::string from_username;\n  std::string date;\n  std::string to;\n  std::string in_reply_to;\n  std::string text;\n};\n\nclass WWIVMessageArea final : public MessageArea, Type2Text {\npublic:\n  WWIVMessageArea(WWIVMessageApi* api, const subboard_t& sub, \n                  std::filesystem::path sub_filename,\n                  std::filesystem::path text_filename, int subnum,\n                  std::vector<net::Network> net_networks);\n  ~WWIVMessageArea() override;\n\n  // Message Sub Specific Operations\n  bool Close() override;\n  bool Lock() override;\n  bool Unlock() override;\n  std::unique_ptr<MessageAreaHeader> ReadMessageAreaHeader() override;\n  // Note: This is not implemented on wwiv.\n  void WriteMessageAreaHeader(const MessageAreaHeader& header) override;\n  int FindUserMessages(const std::string& user_name) override;\n  int number_of_messages() override;\n\n  // message specific.\n  std::optional<Message> ReadMessage(int message_number) override;\n  std::optional<MessageHeader> ReadMessageHeader(int message_number) override;\n  std::optional<MessageText> ReadMessageText(int message_number) override;\n  bool AddMessage(Message& message, const MessageAreaOptions& options) override;\n  bool DeleteMessage(int message_number) override;\n  bool ResyncMessage(int& message_number) override;\n  bool ResyncMessage(int& message_number, Message& message) override;\n\n  [[nodiscard]] Message CreateMessage() override;\n  [[nodiscard]] bool Exists(daten_t d, const std::string& title, uint16_t from_system,\n                            uint16_t from_user) override;\n  [[nodiscard]] const MessageAreaLastRead& last_read() const noexcept override;\n  [[nodiscard]] message_anonymous_t anonymous_type() const noexcept override;\n\nprivate:\n  int DeleteExcess();\n  [[nodiscard]] bool add_post(const postrec& post);\n  [[nodiscard]] std::optional<wwiv_parsed_text_fieds> ParseMessageText(const postrec& header, int message_number);\n  [[nodiscard]] [[nodiscard]] bool HasSubChanged() const;\n  [[nodiscard]] bool ResyncMessageImpl(int& message_number, const Message& message);\n\n  static constexpr uint8_t STORAGE_TYPE = 2;\n\n  // not owned.  Extra copy of the message API but the\n  // WWIV subclass of it.\n  WWIVMessageApi* wwiv_api_;\n  // The currently opened sub if available.\n  const subboard_t sub_;\n  // Full path to the *.sub filename.\n  const std::filesystem::path sub_filename_;\n  bool open_{false};\n  subfile_header_t header_;\n  const std::vector<net::Network> net_networks_;\n  MessageAreaLastRead last_read_;\n  int nonce_{0};\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_areas.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MESSAGE_AREAS_H\n#define INCLUDED_SDK_MESSAGE_AREAS_H\n\n#include \"sdk/msgapi/message_area.h\"\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/message_utils_wwiv.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_MESSAGE_UTILS_WWIV_H\n#define INCLUDED_SDK_MESSAGE_UTILS_WWIV_H\n\n#include <cstdint>\n\nnamespace wwiv::sdk::msgapi {\n\ntemplate<typename M>\nuint8_t network_number_from(const M* m) {\n  if (!(m->status & status_new_net)) {\n    // Some bits in wwiv, like forwarded mail will not have the network\n    // status set on the original message.  It's also not clear if this\n    // is right, however returning 255 here (no net found), seems to\n    // break things.\n    return 0;\n  }\n  if (m->status & status_source_verified) {\n    return m->network.src_verified_msg.net_number;\n  }\n  return m->network.network_msg.net_number;\n}\n\ntemplate<typename M>\nuint16_t source_verfied_type(const M* m) {\n  if (m->status & status_new_net && m->status & status_source_verified) {\n    return m->network.src_verified_msg.source_verified_type;\n  }\n  return 0;\n}\n\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/msgapi/msgapi.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_MSGAPI_H__\n#define __INCLUDED_SDK_MSGAPI_H__\n\n#include \"sdk/msgapi/message_api.h\"\n#include \"sdk/msgapi/message_area.h\"\n#include \"sdk/msgapi/message_areas.h\"\n#include \"sdk/msgapi/message.h\"\n\n#endif  // __INCLUDED_SDK_MSGAPI_H__\n"
  },
  {
    "path": "sdk/msgapi/msgapi_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/msgapi/msgapi.h\"\n#include \"sdk/sdk_helper.h\"\n#include <memory>\n#include <string>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nclass MsgApiTest : public testing::Test {\npublic:\n  void SetUp() override {\n    MessageApiOptions options;\n    options.overflow_strategy = OverflowStrategy::delete_none;\n    api.reset(new WWIVMessageApi(options, helper.config(), {}, new NullLastReadImpl()));\n  }\n\n  static Message CreateMessage(MessageArea& area, uint16_t from, const string& fromname,\n                               const string& title, const string& text) {\n    auto msg = area.CreateMessage();\n\n    auto& h = msg.header();\n    static uint32_t daten = 915192000;\n\n    h.set_from_system(0);\n    h.set_from_usernum(static_cast<uint16_t>(from));\n    h.set_title(title);\n    h.set_from(fromname);\n    h.set_to(\"To\");\n    h.set_daten(daten++);\n    h.set_in_reply_to(\"IRT\");\n    msg.set_text(text);\n\n    return msg;\n  }\n\n  SdkHelper helper;\n  unique_ptr<MessageApi> api;\n};\n\nTEST_F(MsgApiTest, CreateArea) {\n  subboard_t sub{};\n  sub.filename = \"a1\";\n  ASSERT_TRUE(api->Create(sub, -1));\n  auto a1(api->Open(sub, -1));\n  EXPECT_TRUE(a1->Close());\n\n  EXPECT_TRUE(File::Exists(FilePath(helper.datadir(), \"a1.sub\")));\n  EXPECT_TRUE(File::Exists(FilePath(helper.msgsdir(), \"a1.dat\")));\n}\n\nTEST_F(MsgApiTest, SmokeTest) {\n  subboard_t sub{};\n  sub.filename = \"a1\";\n  {\n    ASSERT_TRUE(api->Create(sub, -1));\n    auto area(api->Open(sub, -1));\n    auto msg(CreateMessage(*area, 1234, \"From\", \"Title\", \"Line1\\r\\nLine2\\r\\n\"));\n    EXPECT_TRUE(area->AddMessage(msg, {}));\n  }\n\n  auto a2(api->Open(sub, -1));\n  EXPECT_EQ(1, a2->number_of_messages());\n  const auto m1 = a2->ReadMessage(1);\n  EXPECT_EQ(\"From\", m1->header().from());\n}\n\nTEST_F(MsgApiTest, ToName) {\n  subboard_t sub{};\n  sub.filename = \"a1\";\n  {\n    ASSERT_TRUE(api->Create(sub, -1));\n    auto area(api->Open(sub, -1));\n    auto msg(CreateMessage(*area, 1234, \"From\", \"Title\", \"Line1\\r\\nLine2\\r\\n\"));\n    msg.header().set_to(\"Dude\");\n    EXPECT_TRUE(area->AddMessage(msg, {}));\n  }\n\n  auto a2(api->Open(sub, -1));\n  const auto m1 = a2->ReadMessage(1);\n  EXPECT_EQ(\"Dude\", m1->header().to()) << \"T:\" << m1->text().string();\n}\n\nTEST_F(MsgApiTest, Resynch) {\n  subboard_t sub{};\n  sub.filename = \"a1\";\n  ASSERT_TRUE(api->Create(sub, -1));\n  auto area(api->Open(sub, -1));\n  {\n    auto m(CreateMessage(*area, 1, \"From1\", \"Title1\", \"Line1\\r\\nLine2\\r\\n\"));\n    EXPECT_TRUE(area->AddMessage(m, {}));\n    m.header().set_from_usernum(2);\n    m.header().set_from(\"From2\");\n    m.header().set_title(\"Title2\");\n    EXPECT_TRUE(area->AddMessage(m, {}));\n    m.header().set_from_usernum(3);\n    m.header().set_from(\"From3\");\n    m.header().set_title(\"Title3\");\n    EXPECT_TRUE(area->AddMessage(m, {}));\n  }\n\n  // Re open the area, ensure that we read back the same first\n  // two messages.\n  auto a2(api->Open(sub, -1));\n  auto m1 = a2->ReadMessage(1);\n  EXPECT_EQ(\"From1\", m1->header().from());\n  auto m2 = a2->ReadMessage(2);\n  EXPECT_EQ(\"From2\", m2->header().from());\n\n  // Delete message #1, now we should just have 1 message.\n  EXPECT_TRUE(a2->DeleteMessage(1));\n  EXPECT_EQ(2, a2->number_of_messages());\n\n  // ResyncMessage should move this to message 1 since\n  // we deleted the old 1.\n  auto msgnum = 2;\n  a2->ResyncMessage(msgnum, *m2);\n  EXPECT_EQ(1, msgnum);\n}\n\nTEST_F(MsgApiTest, Resynch_MessageNumber) {\n  {\n    subboard_t sub{};\n    sub.filename = \"a1\";\n    ASSERT_TRUE(api->Create(sub, -1));\n    auto area(api->Open(sub, -1));\n    auto m(CreateMessage(*area, 1234, \"From\", \"Title\", \"Line1\\r\\nLine2\\r\\n\"));\n    EXPECT_TRUE(area->AddMessage(m, {}));\n    m.header().set_from(\"From2\");\n    EXPECT_TRUE(area->AddMessage(m, {}));\n  }\n\n  // Re open the area, ensure that we read back the same first\n  // two messages.\n  subboard_t sub{};\n  sub.filename = \"a1\";\n  auto a2(api->Open(sub, -1));\n\n  // Delete message #1, now we should just have 1 message.\n  EXPECT_TRUE(a2->DeleteMessage(1));\n  EXPECT_EQ(1, a2->number_of_messages());\n\n  // ResyncMessage should move this to message 1 since\n  // we deleted the old 1.\n  auto msgnum = 2;\n  a2->ResyncMessage(msgnum);\n  EXPECT_EQ(1, msgnum);\n}\n"
  },
  {
    "path": "sdk/msgapi/parsed_message.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/parsed_message.h\"\n\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include <functional>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr char CZ = 26;\n\nstd::vector<std::string> split_wwiv_style_message_text(const std::string& s) {\n  auto temp(s);\n  const auto cz_pos = temp.find(CZ);\n  if (cz_pos != std::string::npos) {\n    // We stop the message at control-Z if it exists.\n    temp = temp.substr(0, cz_pos);\n  }\n  // Instead of splitting on \\r\\n, we remove the \\n and then\n  // split on just \\r.  This also is great that it handles\n  // the cases where we end in only \\r properly.\n  temp.erase(std::remove(temp.begin(), temp.end(), 10), temp.end());\n  // Use SplitString(..., false) so we don't skip blank lines.\n  auto orig =  SplitString(temp, \"\\r\", false);\n\n  std::vector<std::string> out;\n  std::string current_line;\n  for (auto& l : orig) {\n    if (l.empty()) {\n      out.emplace_back(\"\");\n      continue;\n    }\n    if (l.back() == 0x01) { // ^A\n      l.pop_back(); // remove trailing ^A\n      if (!current_line.empty() && current_line.back() != ' ' && l.front() != ' ') {\n        // Make sure we have at least a space between lines. Fix #1498\n        current_line.push_back(' ');\n      }\n      current_line.append(l);\n      continue;\n    }\n    if (current_line.empty()) {\n      out.emplace_back(l);\n    } else {\n      if (!current_line.empty() && current_line.back() != ' ' && l.front() != ' ') {\n        // Make sure we have at least a space between lines. Fix #1498\n        current_line.push_back(' ');\n      }\n      out.emplace_back(current_line.append(l));\n      current_line.clear();\n    }\n  }\n  return out;\n}\n\nParsedMessageText::ParsedMessageText(std::string control_char, const std::string& text,\n                                     const splitfn& split_fn, std::string eol)\n    : control_char_(std::move(control_char)),\n      split_fn_(split_fn), eol_(std::move(eol)) {\n  if (text.empty()) {\n    return;\n  }\n  if (text.back() == CZ) {\n    auto t = text;\n    t.pop_back();\n    lines_ = split_fn(t);\n  } else {\n    lines_ = split_fn(text);\n  }\n  // TODO, lines needs to be a structure that includes metadata\n  // like  centered line, or soft-wrapped line.  WWIV and\n  // FTN have different ways of soft-wrapping and need\n  // to handle both.\n}\n\nParsedMessageText::~ParsedMessageText() = default;\n\nbool ParsedMessageText::add_control_line_after(const std::string& near_line,\n                                               const std::string& line) {\n  for (auto it = std::begin(lines_); it != std::end(lines_); ) {\n    auto l = *it;\n    if (!l.empty() && starts_with(l, control_char_)) {\n      l = l.substr(control_char_.size());\n      if (l.find(near_line) != std::string::npos) {\n        // current item has it.\n        if (it == lines_.end()) {\n          // at the end of the list, add to the end.\n          lines_.push_back(StrCat(control_char_, line));\n        } else {\n          // not at the end of the list, add it *after* the current item.\n          ++it;\n          lines_.insert(it, StrCat(control_char_, line));\n        }\n        return true;\n      }\n    }\n    ++it;\n  }\n  return false;\n}\n\nbool ParsedMessageText::add_control_line(const std::string& line) {\n  auto it = lines_.begin();\n  auto found_control_line = false;\n  while (it != lines_.end()) {\n    auto l = *it;\n    if (l.empty()) {\n      ++it;\n      continue;\n    }\n    if (starts_with(l, control_char_)) {\n      found_control_line = true;\n    } else if (found_control_line) {\n      // We've seen control lines before, and now we don't.\n      // Insert here so we're at the end of the control lines.\n      lines_.insert(it, StrCat(control_char_, line));\n      return true;\n    }\n    ++it;\n  }\n  lines_.push_back(StrCat(control_char_, line));\n  return true;\n}\n\nbool ParsedMessageText::remove_control_line(const std::string& start_of_line) {\n  for (auto it = std::begin(lines_); it != std::end(lines_);) {\n    auto l = *it;\n    if (!l.empty() && starts_with(l, control_char_)) {\n      l = l.substr(control_char_.size());\n      if (l.find(start_of_line) != std::string::npos) {\n        it = lines_.erase(it);\n        return true;\n      }\n    }\n    ++it;\n  }\n  return false;\n}\n\n\nstd::string ParsedMessageText::to_string() const {\n  return JoinStrings(lines_, eol_) + static_cast<char>(CZ);\n}\n\nstatic bool has_quote(const std::string& text) {\n  if (const auto quote_end = text.find_first_of(\">)]\");\n      quote_end != std::string::npos && quote_end < 10) {\n    return true;\n  }\n  return false;\n}\n\nstd::vector<std::string>\nParsedMessageText::to_lines(const parsed_message_lines_style_t& style) const {\n  std::vector<std::string> out;\n  for (auto l : lines_) {\n    if (l.empty()) {\n      out.emplace_back(\"\");\n      continue;\n    }\n    const auto is_control_line = starts_with(l, control_char_);\n    if (!is_control_line) {\n      std::string last_line;\n      do {\n        if (l == last_line) {\n          // We have a loop!\n          VLOG(1) << \"LOOP on line: '\" << l << \"'\";\n          out.push_back(l.substr(0, style.line_length));\n          break;\n        }\n        last_line = l;\n        const auto size_wc = size_without_colors(l);\n        if (size_wc <= style.line_length) {\n          if (style.reattribute_quotes && has_quote(l)) {\n            // If we already have quote line here and we are reattributing them,\n            // then clean up any space in front of it.\n            StringTrimBegin(&l);\n          }\n          out.push_back(l);\n          break;\n        }\n        // We have a long line\n        auto pos = style.line_length;\n        while (pos > 0 && l[pos] > 32) {\n          pos--;\n        }\n        if (pos == 0) {\n          pos = style.line_length;\n        }\n        if (pos < 16) {\n          // We have nothing useful here.  Just dump what we can of L\n          VLOG(1) << \"LOOP (<16) on line: '\" << l << \"'\";\n          out.push_back(l.substr(0, style.line_length));\n          break;\n        }\n        auto subset_of_l = l.substr(0, pos);\n        l = l.substr(pos);\n        if (!l.empty() && l.front() == ' ') {\n          // Trim any leading space char that may have been wrapped from last line.\n          l = l.substr(1);\n        }\n        if (style.reattribute_quotes) {\n          // Here we try to re-attribute quote by looking for quote markers\n          // and adding them to the wrapped lines.\n          if (auto quote_end = subset_of_l.find_first_of(\">)]\");\n              quote_end != std::string::npos && quote_end < 10) {\n            ++quote_end;\n            auto possible_quote = subset_of_l.substr(0, quote_end);\n            if (const auto possible_quote_start = possible_quote.find_last_of(' ');\n                possible_quote_start != std::string::npos) {\n              possible_quote = possible_quote.substr(possible_quote_start + 1);\n              // Trim trailing space on quote.\n              if (possible_quote.back() == ' ') {\n                possible_quote.pop_back();\n              }\n            }\n            l = StrCat(possible_quote, \" \", l);\n            // Remove any space from before the non-wrapped line so it matches.\n            StringTrimBegin(&subset_of_l);\n          }\n        }\n        if (style.add_wrapping_marker) {\n          // A ^A at the end of the line means it was soft wrapped.\n          out.push_back(fmt::sprintf(\"%s%c\", subset_of_l, 0x01));\n        } else {\n          out.push_back(subset_of_l);\n        }\n      } while (true);\n      continue;\n    }\n    switch (style.ctrl_lines) {\n    case control_lines_t::control_lines:\n      out.push_back(l);\n      break;\n    case control_lines_t::control_lines_masked: {\n      auto s{l};\n      StringReplace(&s, control_char_, \"@\");\n      out.push_back(s);\n    } break;\n    case control_lines_t::no_control_lines:\n      if (!is_control_line) {\n        out.push_back(l);\n      }\n      break;\n    default:\n      out.push_back(l);\n    }\n  }\n  return out;\n}\n\nWWIVParsedMessageText::WWIVParsedMessageText(const std::string& text)\n    : ParsedMessageText(\"\\004\"\n                        \"0\",\n                        text, split_wwiv_style_message_text, \"\\r\\n\") {}\n  \nWWIVParsedMessageText::~WWIVParsedMessageText() = default;\n\nFTNParsedMessageText::FTNParsedMessageText(const std::string& text)\n    : ParsedMessageText(\"\\001\", text, split_wwiv_style_message_text, \"\\r\") {}\n\nFTNParsedMessageText::~FTNParsedMessageText() = default;\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/msgapi/parsed_message.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_PARSED_MESSAGE_H\n#define INCLUDED_SDK_PARSED_MESSAGE_H\n\n#include <functional>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\n/**\n * Specifies how to return the text with respect to control lines,\n * \n * * control_lines: Return raw control lines\n * * control_lines_masked: Replace control line character with '@'\n * * no_control_lines: Skip lines containing control lines.\n */\nenum class control_lines_t {\n  /// Return raw control lines\n  control_lines,\n  /// Replace control line character with '@'\n  control_lines_masked,\n  /// Skip lines containing control lines.\n  no_control_lines\n};\n\n/**\n * Controls the style of the text to be returned in ParsedMessageText::to_lines\n */\nstruct parsed_message_lines_style_t {\n  // Controls the including of control lines and how to include.\n  control_lines_t ctrl_lines;\n  // Line length to wrap soft-wrapped lines\n  int line_length{76};\n  // Should the WWIV wrapping marker be added (^A) at the end of\n  // a soft-wrapped line.\n  bool add_wrapping_marker{true};\n  // Attempt to add quote attribution lines to wrapped text of\n  // existing quotes.\n  bool reattribute_quotes{false};\n};\n\n/**\n * Represents a parsed (split into lines) message.  The format can either be in\n * WWIV native (control lines start with ^D0) or FTN (control lines start with ^A),\n * depending on the control_char specified.\n */\nclass ParsedMessageText {\npublic:\n  typedef std::function<std::vector<std::string>(const std::string&)> splitfn;\n\n  bool add_control_line_after(const std::string& near_line, const std::string& line);\n  bool add_control_line(const std::string& line);\n  /** \n   * Removes a single control line starting with start_of_line \n   * returns true if a line was removed, false otherwise\n   */\n  bool remove_control_line(const std::string& start_of_line);\n  [[nodiscard]] std::string to_string() const;\n  [[nodiscard]] std::vector<std::string> to_lines(const parsed_message_lines_style_t& style) const;\n\nprotected:\n  ParsedMessageText(std::string control_char, const std::string& text, const splitfn& s,\n                    std::string eol);\n  virtual ~ParsedMessageText();\n\nprivate:\n  const std::string control_char_;\n  std::vector<std::string> lines_;\n  splitfn split_fn_;\n  const std::string eol_;\n};\n\n/**\n * Represents a parsed (split into lines) message  in WWIV format (control\n * lines start with ^D0) and end of line is \"\\r\\n\".\n */\nclass WWIVParsedMessageText final : public ParsedMessageText {\npublic:\n  WWIVParsedMessageText(const std::string& text);\n  ~WWIVParsedMessageText();\n};\n\n/**\n * Represents a parsed (split into lines) message  in FTN format (control\n * lines start with ^A) and end of line is \"\\r\".\n */\nclass FTNParsedMessageText final : public ParsedMessageText {\npublic:\n  FTNParsedMessageText(const std::string& text);\n  ~FTNParsedMessageText();\n};\n\nstd::vector<std::string> split_wwiv_style_message_text(const std::string& s);\n\n} \n\n#endif // INCLUDED_SDK_PARSED_MESSAGE_H\n"
  },
  {
    "path": "sdk/msgapi/parsed_message_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n#include \"gmock/gmock.h\"\n\n#include \"bbs/msgbase1.h\"\n#include \"core/datetime.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"local_io/keycodes.h\"\n#include \"sdk/msgapi/parsed_message.h\"\n\nusing namespace testing;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk::msgapi;\n\nclass ParsedMessageTest : public ::testing::Test {\nprotected:\n  ParsedMessageTest()\n    : ca(\"\\001\"),\n      cd(\"\\004\"),\n      cz(std::string(1, static_cast<char>(CZ))) {}\n\n  void SetUp() override {\n    expected_list_.emplace_back(\"Title\");\n    expected_list_.push_back(daten_to_wwivnet_time(daten_t_now()));\n    expected_list_.push_back(ca + \"PID\");\n    expected_list_.push_back(ca + \"MSGID 1234\");\n    expected_list_.push_back(ca + \"TZUTC\");\n    expected_list_.emplace_back(\"Line of text\");\n\n    expected_list_new_msgid_.emplace_back(\"Title\");\n    expected_list_new_msgid_.push_back(daten_to_wwivnet_time(daten_t_now()));\n    expected_list_new_msgid_.push_back(ca + \"PID\");\n    expected_list_new_msgid_.push_back(ca + \"MSGID 5678\");\n    expected_list_new_msgid_.push_back(ca + \"TZUTC\");\n    expected_list_new_msgid_.emplace_back(\"Line of text\");\n\n\n    expected_list_wwiv_.emplace_back(\"Title\");\n    expected_list_wwiv_.push_back(daten_to_wwivnet_time(daten_t_now()));\n    expected_list_wwiv_.push_back(cd + \"0PID\");\n    expected_list_wwiv_.push_back(cd + \"0MSGID 1234\");\n    expected_list_wwiv_.push_back(cd + \"0TZUTC\");\n    expected_list_wwiv_.emplace_back(\"Line of text\");\n  }\n\n  std::string expected_string_ftn_format(size_t pos, const std::string& val) {\n    insert_at(expected_list_, pos, val);\n    return JoinStrings(expected_list_, \"\\r\") + cz;\n  }\n\n  std::string expected_string_new_msgid_ftn_format(size_t pos, const std::string& val) {\n    insert_at(expected_list_new_msgid_, pos, val);\n    return JoinStrings(expected_list_new_msgid_, \"\\r\") + cz;\n  }\n\n  std::string expected_string_wwiv(size_t pos, const std::string& val) {\n    insert_at(expected_list_wwiv_, pos, val);\n    return JoinStrings(expected_list_wwiv_, \"\\r\\n\") + cz;\n  }\n\n  void TearDown() override {\n    expected_list_.clear();\n    expected_list_wwiv_.clear();\n  }\n\n  std::string ca;\n  std::string cd;\n  std::string cz;\n\n  std::vector<std::string> expected_list_;\n  std::vector<std::string> expected_list_new_msgid_;\n  std::vector<std::string> expected_list_wwiv_;\n};\n\nTEST_F(ParsedMessageTest, AfterMsgID) {\n  const auto kReply = ca + \"REPLY\";\n  FTNParsedMessageText p(JoinStrings(expected_list_, \"\\r\"));\n  p.add_control_line_after(\"MSGID\", \"REPLY\");\n  const auto actual_string = p.to_string();\n\n  EXPECT_EQ(expected_string_ftn_format(4, kReply), actual_string);\n}\n\nTEST_F(ParsedMessageTest, AddReplyAndReplaceMsgID) {\n  const auto kReply = ca + \"REPLY\";\n  FTNParsedMessageText p(JoinStrings(expected_list_, \"\\r\"));\n  const auto kNewMsgId = ca + \"MSGID 5678\";\n  p.add_control_line_after(\"MSGID\", \"MSGID 5678\");\n  // Remove original msgid\n  p.remove_control_line(\"MSGID\");\n  p.add_control_line_after(\"MSGID\", \"REPLY\");\n  const auto actual_string = p.to_string();\n\n  EXPECT_EQ(expected_string_new_msgid_ftn_format(4, kReply), actual_string);\n}\n\nTEST_F(ParsedMessageTest, AfterMsgID_WWIVControlLines) {\n  const auto kReply = cd + \"0REPLY\";\n  WWIVParsedMessageText p(JoinStrings(expected_list_wwiv_, \"\\r\\n\"));\n  p.add_control_line_after(\"MSGID\", \"REPLY\");\n  const auto actual_string = p.to_string();\n\n  EXPECT_EQ(expected_string_wwiv(4, kReply), actual_string);\n}\n\nTEST_F(ParsedMessageTest, AtEndOfControlLines) {\n  const auto kControlLineWithControlChar = ca + \"DUDE\";\n  const std::string kControlLine = \"DUDE\";\n  FTNParsedMessageText p(JoinStrings(expected_list_, \"\\r\"));\n  p.add_control_line(kControlLine);\n  const auto actual_string = p.to_string();\n\n  EXPECT_EQ(expected_string_ftn_format(5, kControlLineWithControlChar), actual_string);\n}\n\nTEST_F(ParsedMessageTest, AtEndOfControlLines_WWIVControlLines) {\n  const std::string kControlLine = \"DUDE\";\n  const auto kControlLineWithControlChar = cd + \"0DUDE\";\n  WWIVParsedMessageText p(JoinStrings(expected_list_wwiv_, \"\\r\\n\"));\n  p.add_control_line(kControlLine);\n  const auto actual_string = p.to_string();\n\n  EXPECT_EQ(expected_string_wwiv(5, kControlLineWithControlChar), actual_string);\n}\n\nTEST(WWIVParsedMessageTest, ToString_StaysSingleLine) {\n  const std::string cz(1, static_cast<char>(CZ));\n  const std::string text = \"This is a long line and this is a long line and this is a long line and this too is a long line and this too is a long line\";\n\n  const WWIVParsedMessageText p(text);\n  EXPECT_EQ(StrCat(text, \"\\r\\n\", cz), p.to_string());\n}\n\nTEST(WWIVParsedMessageTest, ToString_SplitLineWithContinuations) {\n  const std::string cz(1, static_cast<char>(CZ));\n  const std::string text = \"This is a long line and this is a long line and this is a long line and this\\x1\\r\\n too is a long line and this too is a long line\";\n  const std::string expected = \"This is a long line and this is a long line and this is a long line and this too is a long line and this too is a long line\";\n\n  const WWIVParsedMessageText p(text);\n  EXPECT_EQ(StrCat(expected, \"\\r\\n\", cz), p.to_string());\n}\n\nTEST(WWIVParsedMessageTest, ToLines_Smoke) {\n  const std::string cz(1, static_cast<char>(CZ));\n  const std::string text = \n    \"This is a long line and this is a long line and this is a long line and this\\x1\\r\\n too is a long line and this too is a long line\";\n\n  const WWIVParsedMessageText p(text);\n  parsed_message_lines_style_t style{};\n  style.line_length = 40;\n  const auto lines = p.to_lines(style);\n  EXPECT_EQ(4u, lines.size());\n  EXPECT_EQ(\"This is a long line and this is a long\\x1|\"\n            \"line and this is a long line and this\\x1|\"\n            \"too is a long line and this too is a\\x1|\"\n            \"long line|\",\n            JoinStrings(lines, \"|\"));\n}\n\nTEST(WWIVParsedMessageTest, ToLines_ReattributeQuote) {\n  const std::string cz(1, static_cast<char>(CZ));\n  const std::string text =     \"RF> This is a long line of text\\r\\nRF> xxxx of the text\";\n  const std::string expected = \"RF> This is a long\\x1|RF> line of text|RF> xxxx of the text|\";\n\n  const WWIVParsedMessageText p(text);\n  parsed_message_lines_style_t style{};\n  style.line_length = 20;\n  style.reattribute_quotes = true;\n  const auto lines = p.to_lines(style);\n  EXPECT_EQ(3u, lines.size());\n  EXPECT_EQ(expected,\n            JoinStrings(lines, \"|\"));\n}\n\nTEST(WWIVParsedMessageTest, ToLines_Hang) {\n  const std::string cz(1, static_cast<char>(CZ));\n  //TextFile f(R\"(U:\\wwiv\\gfiles\\message-from-jim-killed-quoting.txt)\", \"rt\");\n  //auto text = f.ReadFileIntoString();\n  std::string raw_text =R\"(Re: WWIV Chat Sunday December 12th\nJimmy Mac #1 @707\nMon Dec  7 22:52:26 2020\n\u00040R 53 - 12/07/20 23:21:22 wwivnet ->513\n\u00040R 38RC6 - 12/07/20 18:06:42 WWIVnet ->1\n\u00040R 38RC6 - 12/07/20 18:06:41 WWIVnet ->1\n\u00040R 53 - 12/07/20 14:53:59 WWIVnet ->707\nRE: Re: WWIV Chat Sunday December 12th\nBY: Rushfan #1 @513\n\n\u00040PID: WWIV 5.6.0.3359\n\n\u00031R\u00037> \u00035Oh, in wwiv.ini back in 5.2 or 5.3, I Changed the defaults for the temp\u00030\n\u00031R\u00037> \u00035and batch directory (it shouldn't impact your use).  You may want to\u00030\n\u00031R\u00037> \u00035change it, it's easier for scripting.  Here's what it is now:\u00030\n\u00031R\u00037> \u00030\n\u00031R\u00037> \u00035;=======================================================================\u00030\n\u00031R\u00037> \u00035=====\u00030\n\u00031R\u00037> \u00035;                        TEMPORARY DIRECTORY SETTING\u00030\n\u00031R\u00037> \u00035;=======================================================================\u00030\n\u00031R\u00037> \u00035=====\u00030\n\u00031R\u00037> \u00035NUM_INSTANCES        = 8\u00030\n\u00031R\u00037> \u00035TEMP_DIRECTORY       = e/%n/temp\u00030\n\u00031R\u00037> \u00035BATCH_DIRECTORY      = e/%n/batch\u00030\n\u00031R\u00037> \u00030\n\u00031R\u00037> \u00035The e is for ephemeral, and it makes it handle to just rmdir /s/q e to\u00030\n\u00031R\u00037> \u00035clean everything up.\u00030\n\u00031R\u00037> \u00030\n\noh!  D'Oh! I'm still using my wwiv.ini from 4.3!  I'll need to review the new \u0001\none to see what else needs updating. So, do the same %x options apply in \u0001\nchainedit? Will changing wwiv.ini impact the games requiring changes?\n\nJ..\n\n\u00041\n\u00042\u00032\u00036<-->     The Blood Stone BBS - Telnet & HTTP www.bsbbs.com      <-->\n\u00043\u00032\u00036 \\/        WWIVnet Node 1@707 - Sonoma County California         \\/\n\u00044\n\u00045\n\n\n  )\";\n  auto raw_lines = SplitString(raw_text, \"\\n\");\n  auto text = JoinStrings(raw_lines, \"\\r\\n\");\n  const std::string expected = \"X\";\n\n  WWIVParsedMessageText p(text);\n  parsed_message_lines_style_t style{};\n  style.line_length = 72;\n  style.ctrl_lines = msgapi::control_lines_t::no_control_lines;\n  style.add_wrapping_marker = false;\n  // experimental\n  style.reattribute_quotes = true;\n  const auto lines = p.to_lines(style);\n  EXPECT_EQ(34u, lines.size()) << JoinStrings(lines, \"\\n\");\n}\n\n\n\nTEST(WWIVParsedMessageTest, ToLines_B1498) {\n  const std::string cz(1, static_cast<char>(CZ));\n  std::string text =\n      R\"(The majority of the storm was here in MD on Thursday night into Friday.  We[^A]\nwent from 57 degrees at 1am Friday morning to 3 degrees Saturday morning.  Very[^A]\nhigh wind gusts and lots of rain, that changed to ice/snow for a bit, but[^A]\ndidn't accumulate to anything.)\";\n\n  const std::string expected = \"RF> This is a long\\x1|RF> line of text|RF> xxxx of the text|\";\n  StringReplace(&text, \"\\n\", \"\\r\\n\");\n  StringReplace(&text, \"[^A]\", \"\\x01\");\n  const WWIVParsedMessageText p(text);\n  parsed_message_lines_style_t style{};\n  style.line_length = 79;\n  style.ctrl_lines = control_lines_t::control_lines;\n  style.add_wrapping_marker = false;\n  const auto lines = p.to_lines(style);\n  EXPECT_EQ(4u, lines.size());\n  EXPECT_THAT(lines[0],\n              Eq(\"The majority of the storm was here in MD on Thursday night into Friday.  We\"))\n      << JoinStrings(lines, \"\\n\");\n  EXPECT_THAT(lines[1],\n              Eq(\"went from 57 degrees at 1am Friday morning to 3 degrees Saturday morning.  Very\"))\n      << JoinStrings(lines, \"\\n\");\n  EXPECT_THAT(lines[2],\n              Eq(\"high wind gusts and lots of rain, that changed to ice/snow for a bit, but\"))\n      << JoinStrings(lines, \"\\n\");\n  EXPECT_THAT(lines[3], Eq(\"didn't accumulate to anything.\")) << JoinStrings(lines, \"\\n\");\n}\n\nTEST(WWIVParsedMessageTest, ToLines_B1498_120) {\n  const std::string cz(1, static_cast<char>(CZ));\n  std::string text =\n      R\"(The majority of the storm was here in MD on Thursday night into Friday.  We[^A]\nwent from 57 degrees at 1am Friday morning to 3 degrees Saturday morning.  Very[^A]\nhigh wind gusts and lots of rain, that changed to ice/snow for a bit, but[^A]\ndidn't accumulate to anything.)\";\n\n  const std::string expected = \"RF> This is a long\\x1|RF> line of text|RF> xxxx of the text|\";\n  StringReplace(&text, \"\\n\", \"\\r\\n\");\n  StringReplace(&text, \"[^A]\", \"\\x01\");\n  const WWIVParsedMessageText p(text);\n  parsed_message_lines_style_t style{};\n  style.line_length = 119;\n  style.ctrl_lines = control_lines_t::control_lines;\n  style.add_wrapping_marker = false;\n  const auto lines = p.to_lines(style);\n  EXPECT_EQ(3u, lines.size());\n  EXPECT_THAT(lines[0], Eq(\"The majority of the storm was here in MD on Thursday night into \"\n                           \"Friday.  We went from 57 degrees at 1am Friday morning\"))\n      << JoinStrings(lines, \"\\n\");\n  EXPECT_THAT(lines[1], Eq(\"to 3 degrees Saturday morning.  Very high wind gusts and lots of rain, \"\n                           \"that changed to ice/snow for a bit, but didn't\"))\n      << JoinStrings(lines, \"\\n\");\n  EXPECT_THAT(lines[2], Eq(\"accumulate to anything.\")) << JoinStrings(lines, \"\\n\");\n\n\n\n\n}"
  },
  {
    "path": "sdk/msgapi/type2_text.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/msgapi/type2_text.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n#include <optional>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk::msgapi {\n\nusing wwiv::core::DataFile;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr char CZ = 26;\n\ntemplate <class S>\nconstexpr auto MSG_STARTING(S section) { return section * GATSECLEN + GAT_SECTION_SIZE; }\n\nType2Text::Type2Text(std::filesystem::path p) : path_(std::move(p)) {}\n\n// Implementation Details\n\nbool Type2Text::remove_link(const messagerec& msg) {\n  auto file = OpenMessageFile();\n  if (!file || !file->IsOpen()) {\n    return false;\n  }\n  const auto section = static_cast<int>(msg.stored_as / GAT_NUMBER_ELEMENTS);\n  auto gat = load_gat(*file, section);\n  auto current_section = msg.stored_as % GAT_NUMBER_ELEMENTS;\n  while (current_section > 0 && current_section < GAT_NUMBER_ELEMENTS) {\n    const uint32_t next_section = static_cast<long>(gat[current_section]);\n    gat[current_section] = 0;\n    current_section = next_section;\n  }\n  save_gat(*file, section, gat);\n  file->Close();\n  return true;\n}\n\n\n/**\n* Opens the message area file {messageAreaFileName} and returns the file handle.\n* Note: This is a Private method to this module.\n*/\nstd::optional<File> Type2Text::OpenMessageFile() const {\n  // TODO(rushfan): Pass in the status manager. this is needed to\n  // set a()->subchg if any of the subs receive a post so that \n  // resynch can work right on multi node configs.\n  // \n  // a()->status_manager()->reload_status();\n\n  File message_file(path_);\n  if (!message_file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    return std::nullopt;\n  }\n  return message_file;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nstd::vector<gati_t> Type2Text::load_gat(File& file, int section) {\n  std::vector<gati_t> gat(GAT_NUMBER_ELEMENTS);\n  auto file_size = file.length();\n  const auto section_pos = static_cast<File::size_type>(section * static_cast<File::size_type>(GATSECLEN));\n  if (file_size < section_pos) {\n    file.set_length(section_pos);\n    file_size = section_pos;\n  }\n  file.Seek(section_pos, File::Whence::begin);\n  if (file_size < section_pos + GAT_SECTION_SIZE) {\n    // TODO(rushfan): Check that gat is loaded.\n    file.Write(&gat[0], GAT_SECTION_SIZE);\n  } else {\n    // TODO(rushfan): Check that gat is loaded.\n    file.Read(&gat[0], GAT_SECTION_SIZE);\n  }\n  return gat;\n}\n\nvoid Type2Text::save_gat(File& file, int section, const std::vector<gati_t>& gat) {\n  auto section_pos = section * GATSECLEN;\n  file.Seek(section_pos, File::Whence::begin);\n  file.Write(&gat[0], GAT_SECTION_SIZE);\n\n  // TODO(rushfan): Pass in the status manager. this is needed to\n  // set a()->subchg if any of the subs receive a post so that \n  // resynch can work right on multi node configs.\n  // \n  // a()->status_manager()->Run([&](Status& status) {\n  //   status.increment_filechanged(Status::file_change_posts);\n  // });\n}\n\nstd::optional<std::string> Type2Text::readfile(const messagerec& msg) {\n  auto file(OpenMessageFile());\n  if (!file || !file->IsOpen()) {\n    // TODO(rushfan): set error code,\n    return std::nullopt;\n  }\n  const uint32_t gat_section = msg.stored_as / GAT_NUMBER_ELEMENTS;\n  auto gat = load_gat(*file, gat_section);\n\n  auto current_section = msg.stored_as % GAT_NUMBER_ELEMENTS;\n  std::string out;\n  while (current_section > 0 && current_section < GAT_NUMBER_ELEMENTS) {\n    const auto pos = file->Seek(MSG_STARTING(gat_section) + MSG_BLOCK_SIZE * current_section, File::Whence::begin);\n    if (pos == -1) {\n      // Error seeking occurred.\n      LOG(ERROR) << \"Error seeking to position for message stored_as: \" << msg.stored_as;\n      return std::nullopt;\n    }\n    char b[MSG_BLOCK_SIZE + 1];\n    const auto ret = file->Read(b, MSG_BLOCK_SIZE);\n    if (ret == -1) {\n      // Error seeking occurred.\n      LOG(ERROR) << \"Error reading block for message stored_as: \" << msg.stored_as;\n      return std::nullopt;\n    }\n    b[MSG_BLOCK_SIZE] = '\\0';\n    out.append(b);\n    current_section = gat[current_section];\n  }\n\n  const long last_cz = out.find_last_of(CZ);\n  const long last_block_start = out.length() - MSG_BLOCK_SIZE;\n  if (last_cz >= 0 && last_block_start >= 0 && last_cz > last_block_start) {\n    // last block has a Control-Z in it.  Make sure we add a 0 after it.\n    out.resize(last_cz);\n  }\n  return {out};\n}\n\nstd::optional<messagerec> Type2Text::savefile(const std::string& text) {\n  std::vector<gati_t> gati;\n  auto msgfile(OpenMessageFile());\n  if (!msgfile || !msgfile->IsOpen()) {\n    // Unable to write to the message file.\n    return std::nullopt;\n  }\n  int section = 0;\n  for (; section < 1024; section++) {\n    auto gat = load_gat(*msgfile, section);\n    const auto num_blocks_required = static_cast<int>((text.length() + MSG_BLOCK_SIZE - 1) / MSG_BLOCK_SIZE);\n    gati_t i4 = 1;\n    gati.clear();\n    while (ssize(gati) < num_blocks_required && i4 < GAT_NUMBER_ELEMENTS) {\n      if (gat[i4] == 0) {\n        gati.push_back(i4);\n      }\n      ++i4;\n    }\n    if (size_int(gati) >= num_blocks_required) {\n      constexpr auto none = static_cast<uint16_t>(-1);\n      gati.push_back(none);\n      const auto text_len = ssize(text);\n      for (auto i = 0; i < num_blocks_required; i++) {\n        char block[MSG_BLOCK_SIZE + 1];\n        memset(block, 0, sizeof(block));\n        msgfile->Seek(MSG_STARTING(section) + MSG_BLOCK_SIZE * static_cast<long>(gati[i]), File::Whence::begin);\n        const auto remaining = std::min(text_len - (i * MSG_BLOCK_SIZE), MSG_BLOCK_SIZE);\n        memcpy(block, &text[i * MSG_BLOCK_SIZE], remaining);\n        msgfile->Write(block, MSG_BLOCK_SIZE);\n        gat[gati[i]] = gati[i + 1];\n      }\n      save_gat(*msgfile, section, gat);\n      break;\n    }\n  }\n  messagerec m{};\n  m.storage_type = STORAGE_TYPE;\n  m.stored_as = static_cast<uint32_t>(gati[0]) + static_cast<uint32_t>(section) * GAT_NUMBER_ELEMENTS;\n  return {m};\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/msgapi/type2_text.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_TYPE2_TEXT_H__\n#define __INCLUDED_SDK_TYPE2_TEXT_H__\n\n#include \"core/file.h\"\n#include \"sdk/msgapi/message.h\"\n#include <cstdint>\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\nnamespace wwiv {\nnamespace sdk {\nnamespace msgapi {\n\ntypedef uint16_t gati_t;\nstatic constexpr int32_t GAT_NUMBER_ELEMENTS = 2048;\nstatic constexpr int32_t GAT_SECTION_SIZE = GAT_NUMBER_ELEMENTS * sizeof(gati_t);\nstatic constexpr int32_t MSG_BLOCK_SIZE = 512;\nstatic constexpr int32_t GATSECLEN = GAT_SECTION_SIZE + GAT_NUMBER_ELEMENTS * MSG_BLOCK_SIZE;\nstatic constexpr uint8_t STORAGE_TYPE = 2;\n\n\nclass Type2Text {\npublic:\n  explicit Type2Text(std::filesystem::path text_filename);\n\n  [[nodiscard]] std::vector<gati_t> load_gat(wwiv::core::File& file, int section);\n  void save_gat(core::File& f, int section, const std::vector<gati_t>& gat);\n  [[nodiscard]] std::optional<std::string> readfile(const messagerec& msg);\n  [[nodiscard]] std::optional<messagerec> savefile(const std::string& text);\n  [[nodiscard]] bool remove_link(const messagerec& msg);\n\nprivate:\n  [[nodiscard]] std::optional<core::File> OpenMessageFile() const;\n  const std::filesystem::path path_;\n};\n\n}  // namespace msgapi\n}  // namespace sdk\n}  // namespace wwiv\n\n\n#endif  // __INCLUDED_SDK_TYPE2_TEXT_H__\n"
  },
  {
    "path": "sdk/msgapi/type2_text_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/msgapi/type2_text.h\"\n#include <memory>\n#include <optional>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nclass Type2TextTest : public testing::Test {\npublic:\n  void SetUp() override {\n    path_ = helper.CreateTempFilePath(\"foo.dat\");\n    t_ = std::make_unique<Type2Text>(path_);\n  }\n\n  [[nodiscard]] bool CreateMsgTextFile() const {\n    File f(path_);\n    if (!f.Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite)) {\n      return false;\n    }\n    f.set_length(GAT_SECTION_SIZE + (75L * 1024L));\n\n    return true;\n  }\n\n  [[nodiscard]] std::optional<messagerec> save_message(const std::string& text) {\n    return t_->savefile(text);\n  }\n\n  [[nodiscard]] std::optional<std::string> readfile(const messagerec& m) const {\n    return t_->readfile(m);\n  }\n\n  wwiv::core::test::FileHelper helper;\n  unique_ptr<Type2Text> t_;\n  std::filesystem::path path_;\n};\n\nTEST_F(Type2TextTest, Empty) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  File f(path_);\n  ASSERT_TRUE(f.Open(File::modeBinary | File::modeReadWrite));\n  auto gat = t_->load_gat(f, 0);\n  for (const auto g : gat) {\n    EXPECT_EQ(g, 0);\n  }\n}\n\nTEST_F(Type2TextTest, NotEmpty) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  auto m = t_->savefile(\"Hello World\");\n  ASSERT_TRUE(m.has_value());\n  EXPECT_EQ(m->stored_as, 1u);\n}\n\nTEST_F(Type2TextTest, Save_Then_Load) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  auto m1 = save_message(\"Hello World\");\n  ASSERT_EQ(1u, m1->stored_as);\n  auto m2 = save_message(\"Hello World2\");\n  ASSERT_EQ(2u, m2->stored_as);\n\n  auto out = readfile(m1.value());\n  ASSERT_EQ(\"Hello World\", *out);\n\n  out = readfile(m2.value());\n  ASSERT_EQ(\"Hello World2\", *out);\n}\n\nTEST_F(Type2TextTest, TwoBlocks) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  auto m1 = save_message(\"Hello World\");\n  ASSERT_EQ(1u, m1->stored_as);\n\n  const std::string two_blocks(513, 'x');\n  auto m2 = save_message(two_blocks);\n  ASSERT_EQ(2u, m2->stored_as);\n\n  auto m4 = save_message(\"Hello World\");\n  ASSERT_EQ(4u, m4->stored_as);\n\n  auto out = readfile(m2.value());\n  ASSERT_EQ(two_blocks, *out);\n}\n\nTEST_F(Type2TextTest, Reuse_Block_After_Delete) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  auto m1 = save_message(\"Hello World\");\n  ASSERT_EQ(1u, m1->stored_as);\n  auto m2 = save_message(\"Hello World2\");\n  ASSERT_EQ(2u, m2->stored_as);\n\n  ASSERT_TRUE(t_->remove_link(m1.value()));\n  auto m3 = save_message(\"Hello World3\");\n  ASSERT_EQ(1u, m3->stored_as);\n\n}\n\nTEST_F(Type2TextTest, Move_To_Next_Gat_Section) {\n  ASSERT_TRUE(CreateMsgTextFile());\n\n  const std::string msg32k(32 * 1024, 'x'); \n  // Fill up first section.  First section will have only 63 free blocks\n  for (auto i = 0; i < 31; i++) {\n    auto m = save_message(msg32k);\n    ASSERT_EQ(static_cast<uint32_t>(i * 64) + 1, m->stored_as);\n  }\n\n  // Need 64 blocks, so will start in 2nd section.\n  auto m2 = save_message(msg32k);\n  ASSERT_EQ(1u, m2->stored_as / 2048);\n  ASSERT_EQ(1u, m2->stored_as % 2048);\n\n  // Need 1 blocks, so will start in 1nd section again.\n  auto m3 = save_message(\"Hello World3\");\n  ASSERT_EQ(0u, m3->stored_as / 2048);\n  ASSERT_EQ(1985u, m3->stored_as % 2048);\n}\n\n\n"
  },
  {
    "path": "sdk/names.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/names.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include <algorithm>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nNames::Names(const wwiv::sdk::Config& config) : data_directory_(config.datadir()) {\n  loaded_ = Load();\n}\n\nstatic smalrec smalrec_for(uint32_t user_number, const std::vector<smalrec>& names) {\n  for (const auto& n : names) {\n    if (n.number == user_number) {\n      return n;\n    }\n  }\n  return smalrec{\"\", 0};\n}\n\nstd::string Names::UserName(uint32_t user_number) const {\n  const auto sr = smalrec_for(user_number, names_);\n  if (sr.number == 0) {\n    return \"\";\n  }\n  const auto name = properize(std::string(reinterpret_cast<const char*>(sr.name)));\n  return fmt::format(\"{} #{}\", name, user_number);\n}\n\nstd::string Names::UserName(uint32_t user_number, uint32_t system_number) const {\n  const auto base = UserName(user_number);\n  if (base.empty()) {\n    return \"\";\n  }\n  return fmt::format(\"{} @{}\", base, system_number);\n}\n\nbool Names::Add(const std::string& name, uint32_t user_number) {\n  const auto upper_case_name = ToStringUpperCase(name);\n  auto it = names_.begin();\n  for (; it != names_.end()\n         && StringCompare(upper_case_name.c_str(), reinterpret_cast<char*>((*it).name)) > 0;\n         ++it) {\n  }\n  smalrec sr{};\n  strcpy(reinterpret_cast<char*>(sr.name), upper_case_name.c_str());\n  sr.number = static_cast<uint16_t>(user_number);\n  names_.insert(it, sr);\n  return true;\n}\n\nbool Names::AddUnsorted(const std::string& name, uint32_t user_number) {\n  const auto upper_case_name = ToStringUpperCase(name);\n  smalrec sr{};\n  strcpy(reinterpret_cast<char*>(sr.name), upper_case_name.c_str());\n  sr.number = static_cast<uint16_t>(user_number);\n  names_.emplace_back(sr);\n  return true;\n}\n\nbool Names::Remove(uint32_t user_number) {\n  const std::string name(reinterpret_cast<char*>(smalrec_for(user_number, names_).name));\n  if (name.empty()) {\n    return false;\n  }\n\n  const auto upper_case_name = ToStringUpperCase(name);\n  auto it = names_.cbegin();\n  for (; it != names_.cend()\n         && StringCompare(upper_case_name.c_str(), reinterpret_cast<const char*>((*it).name)) > 0;\n         ++it) {\n  }\n  if (!IsEquals(upper_case_name.c_str(), reinterpret_cast<const char*>((*it).name))) {\n    return false;\n  }\n  names_.erase(it);\n  return true;\n}\n\nbool Names::Load() {\n  DataFile<smalrec> file(FilePath(data_directory_, NAMES_LST));\n  if (!file) {\n    return false;\n  }\n  names_.clear();\n  return file.ReadVector(names_);\n}\n\nbool Names::Save() {\n  DataFile<smalrec> file(FilePath(data_directory_, NAMES_LST),\n                         File::modeReadWrite | File::modeBinary | File::modeTruncate |\n                             File::modeCreateFile);\n  if (!file) {\n    LOG(ERROR) << \"Error saving NAMES.LST\";\n    return false;\n  }\n\n  std::sort(names_.begin(), names_.end(), [](const smalrec& a, const smalrec& b) -> bool {\n    const auto equal = strcmp((char*)a.name, (char*)b.name);\n    // Sort by user number if names match.\n    if (equal == 0) {\n      return a.number < b.number;\n    }\n    // Otherwise sort by name comparison.\n    return equal < 0;\n  });\n\n  return file.WriteVector(names_);\n}\n\nbool Names::Rebuild(const UserManager& um) {\n  const auto num_user_records = um.num_user_records();\n  if (num_user_records < 1) {\n    return false;\n  }\n\n  names_.clear();\n  for (auto i = 1; i <= num_user_records; i++) {\n    if (const auto user = um.readuser(i, UserManager::mask::active)) {\n      AddUnsorted(user->name(), i);\n    }\n  }\n  return true;\n}\n\n\nint Names::FindUser(const std::string& search_string) {\n  for (const auto& n : names_) {\n    if (iequals(search_string.c_str(), reinterpret_cast<const char*>(n.name))) {\n      return n.number;\n    }\n  }\n  return 0;\n}\n\nNames::~Names() {\n  if (!save_on_exit_) {\n    return;\n  }\n  Save();\n}\n\n}\n"
  },
  {
    "path": "sdk/names.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NAMES_H\n#define INCLUDED_SDK_NAMES_H\n\n#include \"sdk/config.h\"\n#include <filesystem>\n#include <string>\n#include <vector>\n\nstruct smalrec;\n\nnamespace wwiv::sdk {\nclass UserManager;\n\nclass Names final {\npublic:\n  explicit Names(const wwiv::sdk::Config& config);\n  ~Names();\n\n  [[nodiscard]] std::string UserName(uint32_t user_number) const;\n  [[nodiscard]] std::string UserName(uint32_t user_number, uint32_t system_number) const;\n  bool Add(const std::string& name, uint32_t user_number);\n  bool Remove(uint32_t user_number);\n  bool Load();\n  bool Save();\n  bool Rebuild(const UserManager& um);\n  [[nodiscard]] int FindUser(const std::string& search_string);\n\n  [[nodiscard]] const std::vector<smalrec>& names_vector() const { return names_;  }\n  [[nodiscard]] int size() const { return static_cast<int>(names_.size()); }\n  void set_save_on_exit(bool save_on_exit) { save_on_exit_ = save_on_exit; }\n  [[nodiscard]] bool save_on_exit() const { return save_on_exit_;  }\n\nprivate:\n  /*\n   * Adds a new entry to the end vs. in the right spot.  This method\n   * should only be used when adding many items, as Save will sort.\n   */\n  bool AddUnsorted(const std::string& name, uint32_t user_number);\n\n  const std::filesystem::path data_directory_;\n  bool loaded_{false};\n  bool save_on_exit_{false};\n  std::vector<smalrec> names_;\n};\n\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/names_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/sdk_helper.h\"\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass NamesTest : public testing::Test {\npublic:\n  NamesTest() {\n    EXPECT_TRUE(CreateNames());\n    names_.reset(new Names(helper.config()));\n  }\n\n  [[nodiscard]] bool CreateNames() const {\n    File file(FilePath(helper.datadir(), NAMES_LST));\n    file.Open(File::modeBinary|File::modeWriteOnly|File::modeCreateFile, File::shareDenyNone);\n    if (!file.IsOpen()) {\n      return false;\n    }\n\n    smalrec u3{\"A\", 3};\n    smalrec u2{\"B\", 2};\n    smalrec u1{\"C\", 1};\n\n    file.Write(&u3, sizeof(smalrec));\n    file.Write(&u2, sizeof(smalrec));\n    file.Write(&u1, sizeof(smalrec));\n    return true;\n  }\n\n  SdkHelper helper;\n  unique_ptr<Names> names_;\n};\n\nTEST_F(NamesTest, UserName) {\n  EXPECT_STREQ(\"A #3\", names_->UserName(3).c_str());\n  EXPECT_STREQ(\"A #3 @1234\", names_->UserName(3, 1234).c_str());\n}\n\nTEST_F(NamesTest, Remove) {\n  // Force a save/load and make sure it's there.\n  names_->set_save_on_exit(true);\n  ASSERT_EQ(3, names_->size());\n\n  EXPECT_TRUE(names_->Remove(2));\n  EXPECT_EQ(2, names_->size());\n  EXPECT_TRUE(names_->UserName(2).empty());\n\n  // already removed, so nothing do to.\n  EXPECT_FALSE(names_->Remove(2));\n\n  // Release the old names 1st.\n  names_.reset();\n  names_.reset(new Names(helper.config()));\n  // Should still have 2.\n  EXPECT_EQ(2, names_->size());\n}\n\nTEST_F(NamesTest, Insert) {\n  // Force a save/load and make sure it's there.\n  names_->set_save_on_exit(true);\n\n  ASSERT_EQ(3, names_->size());\n\n  EXPECT_TRUE(names_->Add(\"Z\", 26));\n  EXPECT_EQ(4, names_->size());\n\n  EXPECT_EQ(\"Z #26\", names_->UserName(26));\n\n  // Release the old names 1st.\n  names_.reset();\n  names_.reset(new Names(helper.config()));\n  EXPECT_EQ(4, names_->size());\n}\n\nTEST_F(NamesTest, SaveOnExit) {\n  names_->set_save_on_exit(true);\n  ASSERT_TRUE(names_->save_on_exit());\n}\n\nTEST(NamesRebuildTest, Rebuild) {\n  SdkHelper helper;\n\n  UserManager um(helper.config());\n  User u1{};\n  User::CreateNewUserRecord(&u1, 50, 20, 0, 0.1234f, \n  { 7, 11, 14, 13, 31, 10, 12, 9, 5, 3 }, { 7, 15, 15, 15, 112, 15, 15, 7, 7, 7 });\n  u1.set_name(\"FOO\");\n  um.writeuser(&u1, 1);\n  User u2{};\n  User::CreateNewUserRecord(&u2, 50, 20, 0, 0.1234f, \n  { 7, 11, 14, 13, 31, 10, 12, 9, 5, 3 }, { 7, 15, 15, 15, 112, 15, 15, 7, 7, 7 });\n  u2.set_name(\"BAR\");\n  um.writeuser(&u2, 2);\n\n  Names names(helper.config());\n  names.Rebuild(um);\n  ASSERT_TRUE(names.Save());\n\n  auto v = names.names_vector();\n  ASSERT_EQ(2u, v.size());\n  EXPECT_STREQ(\"BAR\", (char*) v.at(0).name);\n  EXPECT_STREQ(\"FOO\", (char*) v.at(1).name);\n}"
  },
  {
    "path": "sdk/net/binkp.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/binkp.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include <map>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk {\n\n// [[ VisibleForTesting ]]\nstd::optional<std::tuple<std::string, binkp_session_config_t>>\nParseBinkConfigLine(const std::string& line) {\n  // A line will be of the format @node host:port\n  if (line.empty() || line[0] != '@') {\n    // skip empty lines and those not starting with @.\n    return std::nullopt;\n  }\n  \n  std::stringstream stream(line);\n  std::string node_str;\n  stream >> node_str;\n  auto node = node_str.substr(1);\n  std::string host_port_str;\n  stream >> host_port_str;\n\n  auto host = host_port_str;\n  uint16_t port = 24554;  // default port\n  if (host_port_str.find(':') != std::string::npos) {\n    auto host_port = SplitString(host_port_str, \":\");\n    host = host_port[0];\n    port = to_number<uint16_t>(host_port[1]);\n  }\n  \n  binkp_session_config_t config;\n  config.host = host;\n  config.port = port;\n\n  return {{node, config}};\n}\n\nstatic bool ParseAddressesFile(std::map<std::string, binkp_session_config_t>* node_config_map, const std::filesystem::path binkp_path) {\n  TextFile node_config_file(binkp_path, \"rt\");\n  \n  if (node_config_file.IsOpen()) {\n    // Only load the configuration file if it exists.\n    std::string line;\n    while (node_config_file.ReadLine(&line)) {\n      StringTrim(&line);\n      auto r = ParseBinkConfigLine(line);\n      if (r) {\n        auto [node_number, node_config] = r.value();\n        // Parsed a line correctly.\n        node_config_map->insert_or_assign(node_number, node_config);\n      }\n    }\n  }\n  return true;\n}\n\nBinkp::Binkp(const std::filesystem::path& network_dir) {\n  // network names will always be compared lower case.\n\n  if (ParseAddressesFile(&node_config_, FilePath(network_dir, BINKP_NET))) {\n    // Override with entries in local override file.\n    ParseAddressesFile(&node_config_, FilePath(network_dir, \"binkp.local.net\"));\n  }\n}\n\nBinkp::~Binkp() = default;\n\nconst binkp_session_config_t* Binkp::binkp_session_config_for(const std::string& node) const {\n  const auto iter = node_config_.find(node);\n  if (iter != end(node_config_)) {\n    return &iter->second;\n  }\n  return nullptr;\n}\n\nconst binkp_session_config_t* Binkp::binkp_session_config_for(uint16_t node) const {\n  return binkp_session_config_for(std::to_string(node));\n}\n\n} // namespace wwiv\n\n"
  },
  {
    "path": "sdk/net/binkp.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NET_BINKP_H\n#define INCLUDED_SDK_NET_BINKP_H\n\n#include \"sdk/net/net.h\"\n#include <cstdint>\n#include <filesystem>\n#include <map>\n#include <optional>\n#include <string>\n#include <tuple>\n\nnamespace wwiv::sdk {\n\nclass Binkp {\n public:\n  Binkp(const std::filesystem::path& network_dir);\n  virtual ~Binkp();\n  const net::binkp_session_config_t* binkp_session_config_for(const std::string& node) const;\n  const net::binkp_session_config_t* binkp_session_config_for(uint16_t node) const;\n\n private:\n  std::map<std::string, net::binkp_session_config_t> node_config_;\n  std::string network_dir_;\n};\n\nstd::optional<std::tuple<std::string, net::binkp_session_config_t>> ParseBinkConfigLine(const std::string& line);\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/net/callout.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/callout.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/networks.h\"\n#include <algorithm>\n#include <iomanip>\n#include <filesystem>\n#include <map>\n#include <sstream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk {\n\n// [[ VisibleForTesting ]]\nbool ParseCalloutNetLine(const std::string& ss, net_call_out_rec* con) {\n  if (ss.empty() || ss[0] != '@') {\n    // skip empty lines and those not starting with @.\n    return false;\n  }\n  con->min_hr = -1;\n  con->max_hr = -1;\n\n  for (auto iter = ss.cbegin(); iter != ss.cend(); ++iter) {\n    switch (*iter) {\n    case '@': {\n      con->sysnum = to_number<decltype(con->sysnum)>(std::string(++iter, ss.end()));\n    } break;\n    case '&':\n      con->options |= unused_options_sendback;\n      break;\n    case '-':\n      con->options |= unused_options_ATT_night;\n      break;\n    case '_':\n      con->options |= unused_options_ppp;\n      break;\n    case '+':\n      con->options |= options_no_call;\n      break;\n    case '~':\n      con->options |= unused_options_receive_only;\n      break;\n    case '!': {\n      con->options |= unused_options_once_per_day;\n      ++iter;\n      //auto unused_times_per_day = to_number<int>(string(++iter, ss.end()));\n    } break;\n    case '%': {\n      con->macnum = to_number<decltype(con->macnum)>(std::string(++iter, ss.end()));\n    } break;\n    case '/': {\n      con->call_every_x_minutes = to_number<decltype(con->call_every_x_minutes)>(std::string(++iter, ss.end()));\n      if (con->call_every_x_minutes > 0) {\n        // Let's set a minimum of 10 minutes in between calls.\n        con->call_every_x_minutes =\n            std::max<decltype(con->call_every_x_minutes)>(con->call_every_x_minutes, 10);\n      }\n    } break;\n    case '(': {\n      con->min_hr = to_number<decltype(con->min_hr)>(std::string(++iter, ss.end()));\n    } break;\n    case ')': {\n      con->max_hr = to_number<decltype(con->max_hr)>(std::string(++iter, ss.end()));\n    } break;\n    case '|': {\n      con->min_k = std::max<uint16_t>(1, to_number<uint16_t>(std::string(++iter, ss.end())));\n    } break;\n    case ';':\n      con->options |= unused_options_compress;\n      break;\n    case '^':\n      con->options |= unused_options_hslink;\n      break;\n    case '$':\n      con->options |= unused_options_force_ac;\n      break;\n    case '=':\n      con->options |= options_hide_pend;\n      break;\n    case '*':\n      con->options |= unused_options_dial_ten;\n      break;\n    case '\\\"': {\n      ++iter; // skip past first \"\n      std::string password;\n      while (iter != ss.end() && *iter != '\\\"') {\n        password.push_back(*iter++);\n      }\n      if (!password.empty() && password.back() == '\\\"') {\n        // remove trailing \"\n        password.pop_back();\n      }\n      con->session_password = password;\n    } break;\n    default:\n      break;\n    }\n  }\n  return true;\n}\n\nstd::string WriteCalloutNetLine(const net_call_out_rec& con) {\n  std::ostringstream ss;\n  if (con.options & unused_options_sendback) {\n    ss << \" &\";\n  }\n  if (con.options & options_no_call) {\n    ss << \" +\";\n  }\n  if (con.options & unused_options_receive_only) {\n    ss << \" ~\";\n  }\n  if (con.options & unused_options_once_per_day) {\n    ss << \" !\";\n  }\n  if (con.options & options_hide_pend) {\n    ss << \" =\";\n  }\n  if (con.macnum > 0) {\n    ss << \" %\" << static_cast<int>(con.macnum);\n  }\n  if (con.call_every_x_minutes > 0) {\n    const int c = std::max(10, static_cast<int>(con.call_every_x_minutes));\n    ss << \" /\" << c;\n  }\n  if (con.min_hr > 0) {\n    ss << \" (\" << static_cast<int>(con.min_hr);\n  }\n  if (con.max_hr > 0) {\n    ss << \" )\" << static_cast<int>(con.max_hr);\n  }\n  if (con.min_k > 0) {\n    ss << \" |\" << static_cast<int>(con.min_k);\n  }\n  const auto options = ss.str();\n  std::ostringstream s;\n  s << \"@\" << std::left << std::setw(5) << con.sysnum;\n  if (options.size() < 20) {\n    s << std::left << std::setw(20);\n  }\n  s << options;\n  s << \" \\\"\" << con.session_password << \"\\\"\";\n  return s.str();\n}\n\nstd::string CalloutOptionsToString(uint16_t options) {\n  std::ostringstream ss;\n  ss << \"{\" << options << \"} \";\n  if (options & options_no_call) {\n    ss << \"[nocall] \";\n  }\n  if (options & options_hide_pend) {\n    ss << \"[hide_pending] \";\n  }\n  return ss.str();\n}\n\nstatic bool ParseCalloutFile(std::map<uint16_t, net_call_out_rec>* node_config_map,\n                             const std::filesystem::path& network_dir) {\n  const auto path = FilePath(network_dir, CALLOUT_NET);\n  if (!File::Exists(path)) {\n    return false;\n  }\n\n  TextFile node_config_file(path, \"rt\");\n  if (!node_config_file.IsOpen()) {\n    return false;\n  }\n  // A line will be of the format @node host:port [password].\n  std::string line;\n  while (node_config_file.ReadLine(&line)) {\n    StringTrim(&line);\n    net_call_out_rec node_config{};\n    if (ParseCalloutNetLine(line, &node_config)) {\n      // Parsed a line correctly.\n      node_config.ftn_address = StrCat(\"20000:20000/\", node_config.sysnum);\n      node_config_map->emplace(node_config.sysnum, node_config);\n    }\n  }\n  return true;\n}\n\nCallout::Callout(const Network& net, int max_backups)\n    : net_(net), max_backups_(max_backups) {\n  ParseCalloutFile(&node_config_, net.dir);\n}\n\nCallout::Callout(std::initializer_list<net_call_out_rec> l) : net_(), max_backups_(0) {\n  for (const auto& r : l) {\n    node_config_.emplace(r.sysnum, r);\n  }\n}\n\nCallout::~Callout() = default;\n\nconst net_call_out_rec* Callout::net_call_out_for(int node) const {\n  VLOG(2) << \"Callout::net_call_out_for(\" << node << \")\";\n  const auto iter = node_config_.find(static_cast<uint16_t>(node));\n  if (iter != end(node_config_)) {\n    return &iter->second;\n  }\n  return nullptr;\n}\n\nconst net_call_out_rec* Callout::net_call_out_for(const std::string& node) const {\n  VLOG(2) << \"Callout::net_call_out_for(\" << node << \")\";\n  if (starts_with(node, \"20000:20000/\")) {\n    auto s = node.substr(12);\n    s = s.substr(0, s.find('/'));\n    return net_call_out_for(to_number<int>(s));\n  }\n  return net_call_out_for(to_number<int>(node));\n}\n\nbool Callout::insert(uint16_t , const net_call_out_rec& orig) {\n  net_call_out_rec c{orig};\n  c.ftn_address = StrCat(\"20000:20000/\", c.sysnum);\n  node_config_.erase(c.sysnum);\n  node_config_.emplace(c.sysnum, c);\n  return true;\n}\n\nbool Callout::erase(uint16_t node) {\n  node_config_.erase(node);\n  return true;\n}\n\nbool Callout::Save() {\n  backup_file(FilePath(net_.dir, CALLOUT_NET));\n  TextFile node_config_file(FilePath(net_.dir, CALLOUT_NET), \"wt\");\n  if (!node_config_file.IsOpen()) {\n    return false;\n  }\n  for (const auto& kv : node_config_) {\n    node_config_file.WriteLine(WriteCalloutNetLine(kv.second));\n  }\n  return true;\n}\n\nstatic std::string DumpCallout(const net_call_out_rec& n) {\n  std::ostringstream ss;\n  ss << \"sysnum:        \" << n.sysnum << std::endl;\n  if (n.macnum) {\n    ss << \"macnum:        \" << std::dec << n.macnum << std::endl;\n  }\n  if (n.options) {\n    ss << \"options:       \" << CalloutOptionsToString(n.options) << std::endl;\n  }\n  if (n.min_hr > 0) {\n    ss << \"min_hr:        \" << static_cast<int>(n.min_hr) << std::endl;\n  }\n  if (n.max_hr > 0) {\n    ss << \"max_hr:        \" << static_cast<int>(n.max_hr) << std::endl;\n  }\n  ss << \"password:       \\\"\" << n.session_password << \"\\\"\" << std::endl;\n  if (n.min_k) {\n    ss << \"min_k:         \" << static_cast<int>(n.min_k) << std::endl;\n  }\n  ss << \"callout.net line: \" << std::endl;\n  ss << WriteCalloutNetLine(n) << std::endl;\n  return ss.str();\n}\n\nstd::string Callout::ToString() const {\n  std::ostringstream ss;\n  for (const auto& kv : node_config_) {\n    ss << DumpCallout(kv.second) << std::endl;\n  }\n  return ss.str();\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/net/callout.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CALLOUT_H\n#define INCLUDED_SDK_CALLOUT_H\n\n#include \"sdk/net/net.h\"\n#include <initializer_list>\n#include <map>\n#include <string>\n\nnamespace wwiv::sdk {\n  \nclass Callout {\n public:\n  Callout(const net::Network& net, int max_backups);\n  // VisibleForTesting\n  Callout(std::initializer_list<net::net_call_out_rec> l);\n  virtual ~Callout();\n  [[nodiscard]] virtual const net::net_call_out_rec* net_call_out_for(int node) const;\n  [[nodiscard]] virtual const net::net_call_out_rec* net_call_out_for(const std::string& node) const;\n  Callout& operator=(const Callout& rhs) { node_config_ = rhs.node_config_; return *this; }\n\n  bool insert(uint16_t node, const net::net_call_out_rec& c);\n  bool erase(uint16_t node);\n  virtual bool Save();\n\n  [[nodiscard]] const std::map<uint16_t, net::net_call_out_rec>& callout_config() const { return node_config_; }\n  [[nodiscard]] std::string ToString() const;\n\n private:\n  net::Network net_;\n  const int max_backups_;\n  std::map<uint16_t, net::net_call_out_rec> node_config_;\n};\n\n[[nodiscard]] bool ParseCalloutNetLine(const std::string& line, net::net_call_out_rec* config);\nstd::string WriteCalloutNetLine(const net::net_call_out_rec& con);\nstd::string CalloutOptionsToString(uint16_t options);\n\n}  // namespace wwiv::net\n\n#endif  // INCLUDED_SDK_CALLOUT_H\n"
  },
  {
    "path": "sdk/net/callout_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/net/callout.h\"\n#include <string>\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nclass CalloutTest : public testing::Test {};\n\nTEST_F(CalloutTest, SimpleLine) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n}\n\nTEST_F(CalloutTest, WithPassword) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &* \\\"pass\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_dial_ten);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass\", con.session_password);\n}\n\nTEST_F(CalloutTest, WithPassword_Bang) {\n  net_call_out_rec con;\n  const std::string line = \"@1 & \\\"pass!\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass!\", con.session_password);\n}\n\nTEST_F(CalloutTest, OncePerDay) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &!24* \\\"pass\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_dial_ten);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass\", con.session_password);\n}\n\nTEST_F(CalloutTest, LotsOfOptions) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &!24%21/60* \\\"pass\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_dial_ten);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass\", con.session_password);\n  EXPECT_EQ(21, con.macnum);\n  EXPECT_EQ(60, con.call_every_x_minutes);\n}\n\nTEST_F(CalloutTest, MinMax) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &(8)12* \\\"pass\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_dial_ten);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass\", con.session_password);\n  EXPECT_EQ(8, con.min_hr);\n  EXPECT_EQ(12, con.max_hr);\n}\n\nTEST_F(CalloutTest, EveryWeekWith10k) {\n  net_call_out_rec con;\n  const std::string line = \"@1234 &*|10 \\\"pass\\\"\";\n  ASSERT_TRUE(ParseCalloutNetLine(line, &con));\n  EXPECT_EQ(1234, con.sysnum);\n  EXPECT_NE(0, con.options & unused_options_dial_ten);\n  EXPECT_NE(0, con.options & unused_options_sendback);\n  EXPECT_EQ(\"pass\", con.session_password);\n  EXPECT_EQ(10, con.min_k);\n}\n\nTEST_F(CalloutTest, InvalidLine) {\n  net_call_out_rec con;\n\n  const std::string line = \"*@1234 &&\";\n  ASSERT_FALSE(ParseCalloutNetLine(line, &con));\n}\n\nTEST_F(CalloutTest, NodeConfig) {\n  wwiv::core::test::FileHelper files;\n  EXPECT_TRUE(files.Mkdir(\"network\"));\n  const std::string line(\"@1 \\\"foo\\\"\");\n  files.CreateTempFile(\"network/callout.net\", line);\n  Network net{};\n  net.name = \"Dummy Network\";\n  net.dir = files.DirName(\"network\");\n  const Callout callout(net, 0);\n  const auto* con = callout.net_call_out_for(1);\n  ASSERT_TRUE(con != nullptr);\n  EXPECT_EQ(\"foo\", con->session_password);\n}\n"
  },
  {
    "path": "sdk/net/callouts.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/callouts.h\"\n\n#include \"core/log.h\"\n#include \"core/numbers.h\"\n\n#include <algorithm>\n#include <chrono>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::sdk::net {\n\nnetwork_callout_config_t to_network_callout_config_t(const net_call_out_rec& con) {\n  network_callout_config_t c{};\n  c.auto_callouts = !(con.options & options_no_call);\n  c.call_every_x_minutes = con.call_every_x_minutes;\n  c.min_k = con.min_k;\n  return c;\n}\n\nbool allowed_to_call(const network_callout_config_t& con) { \n  return con.auto_callouts;\n}\n\nbool allowed_to_call(const net_call_out_rec& con, const DateTime& dt) {\n\n  if (con.options & options_no_call) {\n    VLOG(3) << \"Not Calling: options_no_call\";\n    return false;\n  }\n\n  const auto l = con.min_hr;\n  const auto h = con.max_hr;\n  const auto n = dt.hour();\n  if (l < 0 || h <= 0 || l == h) {\n    return true;\n  }\n  if (l < h) {\n    // Case where we want to allow it from say 0200-2000\n    return n >= l && n < h;\n  }\n  // Case where we want to allow it from say 2000-0200\n  return n >= h && n < l;\n}\n\n/**\n * Checks the net_contact_rec and net_call_out_rec to ensure the node specified\n * is ok to call and does not violate any constraints.\n */\nbool should_call(const NetworkContact& ncn, const net_call_out_rec& con, const DateTime& dt) {\n  const auto callout = to_network_callout_config_t(con);\n  return should_call(ncn, callout, dt);\n}\n\nbool should_call(const NetworkContact& ncn, const network_callout_config_t& callout,\n                 const DateTime& dt) {\n\n  if (!allowed_to_call(callout)) {\n    VLOG(2) << \"!allowed_to_call; skipping\";\n    return false;\n  }\n\n  const auto now = dt.to_system_clock();\n  if (ncn.bytes_waiting() == 0L && !callout.call_every_x_minutes) {\n    VLOG(2) << \"Skipping: No bytes waiting and !call_every_x_minutes\";\n    return false;\n  }\n  const auto min_minutes = std::max<int>(callout.call_every_x_minutes, 1);\n  const auto last_contact = DateTime::from_time_t(ncn.lastcontact()).to_system_clock();\n  const auto next_contact_time = last_contact + minutes(min_minutes);\n\n  if (callout.call_every_x_minutes && now >= next_contact_time) {\n    VLOG(1) << \"Calling anyway since it's been time: \";\n    VLOG(1) << \"Last Try: \" << DateTime::from_time_t(ncn.lastcontact()).to_string();\n    return true;\n  }\n  if (callout.min_k > 0) {\n    // We won't use min_k if it's 0, so only test if it's >0\n    if (bytes_to_k<int>(ncn.bytes_waiting()) >= callout.min_k) {\n      VLOG(1) << \"Calling: min_k: \" << humanize(ncn.bytes_waiting()) << \" > \" << callout.min_k;\n      return true;\n    }\n  }\n  VLOG(2) << \"Skipping; No reason to call.\";\n  return false;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/net/callouts.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NET_CALLOUTS_H\n#define INCLUDED_SDK_NET_CALLOUTS_H\n\n#include \"core/datetime.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/net.h\"\n\nnamespace wwiv::sdk::net {\n\nbool allowed_to_call(const network_callout_config_t& con);\nbool allowed_to_call(const net_call_out_rec& con, const wwiv::core::DateTime& dt);\nbool should_call(const wwiv::sdk::NetworkContact& ncn, const network_callout_config_t& callout,\n                 const wwiv::core::DateTime& dt);\nbool should_call(const wwiv::sdk::NetworkContact& ncn, const net_call_out_rec& con,\n                 const wwiv::core::DateTime& dt);\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/net/callouts_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*              Copyright (C)2017-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/datetime.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/net/callouts.h\"\n#include \"gtest/gtest.h\"\n\n#include <cstdint>\n#include <ctime>\n#include <string>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nstatic time_t to_time_t(int mon, int day, int hour, int min) {\n  struct tm t {};\n  t.tm_hour = hour;\n  t.tm_min = min;\n  t.tm_year = 110; // (2010)\n  t.tm_mon = mon;\n  t.tm_mday = day;\n  return mktime(&t);\n}\n\nstatic time_t fake_time_t() { return to_time_t(0, 1, 6, 1); }\n\nclass CalloutsTest : public testing::Test {\npublic:\n  CalloutsTest() : t_(fake_time_t()), dt_(DateTime::from_time_t(fake_time_t())) { c_.sysnum = 1; }\n\nprotected:\n  wwiv::core::test::FileHelper helper_;\n  net_call_out_rec c_{};\n  NetworkContact ncn_{1};\n  time_t t_;\n  DateTime dt_;\n};\n\nTEST_F(CalloutsTest, NoCall) {\n  ASSERT_TRUE(allowed_to_call(c_, DateTime::now()));\n\n  c_.options = options_no_call;\n  ASSERT_FALSE(allowed_to_call(c_, DateTime::now()));\n}\n\nTEST_F(CalloutsTest, ByTime) {\n\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  c_.min_hr = 5;\n  c_.max_hr = 6;\n  ASSERT_FALSE(allowed_to_call(c_, dt_));\n  c_.min_hr = 0;\n  c_.max_hr = 6;\n  ASSERT_FALSE(allowed_to_call(c_, dt_));\n\n  c_.min_hr = 6;\n  c_.max_hr = 7;\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n  c_.min_hr = 0;\n  c_.max_hr = 7;\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  c_.min_hr = 6;\n  c_.max_hr = 24;\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n  c_.min_hr = 0;\n  c_.max_hr = 24;\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  c_.min_hr = 20;\n  c_.max_hr = 2;\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n}\n\nTEST_F(CalloutsTest, ShouldCall_CallAnyay_TimeToCall) {\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  // Call every 239 minutes\n  c_.call_every_x_minutes = 239;\n  const auto last_connect = dt_ - minutes(240);\n  ncn_.AddConnect(last_connect, 100, 0);\n\n  EXPECT_TRUE(should_call(ncn_, c_, dt_));\n}\n\nTEST_F(CalloutsTest, ShouldCall_CallAnyay_NotTimeYet) {\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  // Call every 239 minutes\n  c_.call_every_x_minutes = 239;\n  const auto last_connect = dt_ - minutes(238);\n  ncn_.AddConnect(last_connect, 100, 0);\n\n  EXPECT_FALSE(should_call(ncn_, c_, dt_));\n}\n\nTEST_F(CalloutsTest, ShouldCall_CallAnyay_MinK) {\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  // Call every 239 minutes\n  c_.call_every_x_minutes = 239;\n  c_.min_k = 10;\n  const auto last_connect = dt_ - minutes(238);\n  ncn_.AddConnect(last_connect, 100, 0);\n  ncn_.set_bytes_waiting((10 * 1024) + 1);\n\n  EXPECT_TRUE(should_call(ncn_, c_, dt_));\n}\n\nTEST_F(CalloutsTest, ShouldCall_CallAnyay_MinKNotMet) {\n  ASSERT_TRUE(allowed_to_call(c_, dt_));\n\n  // Call every 239 minutes\n  c_.call_every_x_minutes = 239;\n  c_.min_k = 10;\n  const auto last_connect = dt_ - minutes(238);\n  ncn_.AddConnect(last_connect, 100, 0);\n  ncn_.set_bytes_waiting(8 * 1024);\n\n  EXPECT_FALSE(should_call(ncn_, c_, dt_));\n}"
  },
  {
    "path": "sdk/net/connect.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/connect.h\"\n\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/networks.h\"\n#include <cctype>\n#include <cfloat>\n#include <map>\n#include <sstream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk {\n\ntemplate <typename I, typename C> \nstatic uint16_t PopStringToUnsignedShort(I& iter, const C& c) {\n  std::string s;\n  while (iter != std::end(c) && std::isdigit(*iter)) {\n    s.push_back(*iter++);\n  }\n  return to_number<uint16_t>(s);\n}\n\ntemplate <typename I, typename C>\nstatic float PopStringToFloat(I& iter, const C& c) {\n  std::string s;\n  while (iter != std::end(c) && (std::isdigit(*iter) || *iter == '.')) {\n    s.push_back(*iter++);\n  }\n  return to_number<float>(s);\n}\n\ntemplate <typename I, typename C>\nstatic void SkipWhiteSpace(I& iter, const C& c) {\n  while (iter != std::end(c) && std::isspace(*iter)) {\n    // skip whitespace\n    ++iter;\n  }\n}\n\n// [[ VisibleForTesting ]]\nbool ParseConnectNetLine(const std::string& ss, net_interconnect_rec* con) {\n  // A line will be of the format: @node (node=cost)+\n  if (ss.empty() || ss[0] != '@') {\n    // skip empty lines and those not starting with @.\n    return false;\n  }\n  // net_interconnect_rec is a struct with vectors now so\n  // we shouldn't just memset it.\n  con->clear();\n  auto iter = ss.begin();\n  // We know 1st char is @\n  ++iter;\n  con->sysnum = PopStringToUnsignedShort(iter, ss);\n  SkipWhiteSpace(iter, ss);\n\n  while (iter != std::end(ss)) {\n      uint16_t dest = PopStringToUnsignedShort(iter, ss);\n    if (*iter != '=') {\n      LOG(ERROR) << \"= expected. at: '\" << *iter << \"' line: \" << ss;\n      return false;\n    }\n    // skip =\n    ++iter;\n    float cost = PopStringToFloat(iter, ss);\n    SkipWhiteSpace(iter, ss);\n    con->connect.push_back(dest);\n    if (cost < FLT_EPSILON) {\n      //HACK - let's put this into a wwiv::core class\n      cost = 0.0f;\n    }\n    con->cost.push_back(cost);\n    con->numsys++;\n  }\n    return true;\n}\n\nstatic bool ParseConnectFile(std::map<uint16_t, net_interconnect_rec>* node_config_map,\n                             const std::filesystem::path& network_dir) {\n  TextFile connect_file(FilePath(network_dir, CONNECT_NET), \"rt\");\n  if (!connect_file.IsOpen()) {\n    return false;\n  }\n  // A line will be of the format: @node (node=cost)+\n  std::string line;\n  while (connect_file.ReadLine(&line)) {\n    StringTrim(&line);\n    net_interconnect_rec rec{};\n    if (ParseConnectNetLine(line, &rec)) {\n      // Parsed a line correctly.\n      node_config_map->emplace(rec.sysnum, rec);\n    }\n  }\n  return true;\n}\n\nConnect::Connect(const std::filesystem::path& network_dir) {\n  ParseConnectFile(&node_config_, network_dir);\n}\n\nConnect::Connect(std::initializer_list<net_interconnect_rec> l) {\n  for (const auto& r : l) {\n    node_config_.emplace(r.sysnum, r);\n  }\n}\n\nConnect::~Connect() = default;\n\nconst net_interconnect_rec* Connect::node_config_for(int node) const {\n  const auto iter = node_config_.find(static_cast<uint16_t>(node));\n  if (iter != end(node_config_)) {\n    return &iter->second;\n  }\n  return nullptr;\n}\n\nstatic std::string DumpConnect(const net_interconnect_rec& n) {\n  std::ostringstream ss;\n  ss << \"@\" << n.sysnum << \" \";\n  auto connect = std::begin(n.connect);\n  auto cost = std::begin(n.cost);\n  while (connect != end(n.connect)) {\n    ss << *connect++;\n    if (cost != end(n.cost)) {\n      ss << \"=\" << *cost++;\n    }\n    ss << \" \";\n  }\n  if (n.connect.size() != n.numsys || n.cost.size() != n.numsys) {\n    ss << \" [\" << std::dec << n.numsys << \"]\";\n  }\n  return ss.str();\n}\n\nstd::string Connect::ToString() const {\n  std::ostringstream ss;\n  for (const auto& kv : node_config_) {\n    ss << DumpConnect(kv.second) << std::endl;\n  }\n  return ss.str();\n}\n\n}  // namespace\n\n"
  },
  {
    "path": "sdk/net/connect.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONNECT_H\n#define INCLUDED_SDK_CONNECT_H\n\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <initializer_list>\n#include <map>\n#include <string>\n\nnamespace wwiv::sdk {\n\n  \nclass Connect {\n public:\n  explicit Connect(const std::filesystem::path& network_dir);\n  // VisibleForTesting\n  Connect(std::initializer_list<net::net_interconnect_rec> l);\n  virtual ~Connect();\n  const net::net_interconnect_rec* node_config_for(int node) const;\n  Connect& operator=(const Connect& rhs) { node_config_ = rhs.node_config_; return *this; }\n  std::string ToString() const;\n  const std::map<uint16_t, net::net_interconnect_rec>& node_config() const { return node_config_; }\n\n private:\n  std::map<uint16_t, net::net_interconnect_rec> node_config_;\n};\n\nbool ParseConnectNetLine(const std::string& line, net::net_interconnect_rec* config);\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/net/contact.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/contact.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/net/networks.h\"\n#include <map>\n#include <sstream>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\n\nnamespace wwiv::sdk {\n\nnamespace {\n// Time\nconstexpr long MINUTES_PER_HOUR = 60L;\nconstexpr long SECONDS_PER_MINUTE = 60L;\nconstexpr long SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE;\nconstexpr long HOURS_PER_DAY = 24L;\nconstexpr long SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;\n} // namespace\n\n// static\nstd::string NetworkContact::CreateFakeFtnAddress(int node) {\n  return wwiv::strings::StrCat(\"20000:20000/\", node);\n}\n\nContact::Contact(const Network& net) : Contact(net, false) {}\n\nContact::Contact(Network net, bool save_on_destructor)\n    : net_(std::move(net)), save_on_destructor_(save_on_destructor) {\n  DataFile<net_contact_rec> file(FilePath(net_.dir, CONTACT_NET),\n                                 File::modeBinary | File::modeReadOnly, File::shareDenyNone);\n  if (!file) {\n    return;\n  }\n\n  std::vector<net_contact_rec> vs;\n  if (file.number_of_records() > 0) {\n    initialized_ = file.ReadVector(vs);\n  }\n\n  for (const auto& v : vs) {\n    if (v.systemnumber == 0) {\n      VLOG(2) << \"Skipping contact.net entry for system #0 from file: \" << file.file();\n      continue;\n    }\n    network_contact_record r{};\n    r.address = NetworkContact::CreateFakeFtnAddress(v.systemnumber);\n    r.ncr = v;\n    contacts_.emplace(r.address, NetworkContact(r));\n  }\n\n  if (!initialized_ && !contacts_.empty()) {\n    // No need to log on noo contacts, just if we had partial read.\n    LOG(ERROR) << \"failed to read the expected number of bytes: \"\n               << contacts_.size() * sizeof(NetworkContact);\n    // TODO(rushfan): Should we move the initialized_ = true into here or\n    // just remove it?\n  }\n  initialized_ = true;\n}\n\nContact::Contact(Network net, std::initializer_list<NetworkContact> l)\n    : net_(std::move(net)), save_on_destructor_(false), initialized_(true) {\n  for (const auto& r : l) {\n    contacts_.emplace(r.address(), r);\n  }\n}\n\nbool Contact::Save() {\n  if (net_.dir.empty()) {\n    return false;\n  }\n\n  VLOG(3) << \"Saving contact.net to: \" << FilePath(net_.dir, CONTACT_NET).string();\n  DataFile<net_contact_rec> file(FilePath(net_.dir, CONTACT_NET),\n                 File::modeBinary | File::modeReadWrite | File::modeCreateFile | File::modeTruncate,\n                 File::shareDenyReadWrite);\n  if (!file) {\n    return false;\n  }\n  if (contacts_.empty()) {\n    return false;\n  }\n\n  std::vector<net_contact_rec> vs;\n  for (const auto& v : contacts_) {\n    vs.emplace_back(v.second.ncr());\n  }\n\n  return file.WriteVector(vs);\n}\n\nContact::~Contact() {\n  if (save_on_destructor_) {\n    Save();\n  }\n}\n\nstatic void fixup_long(daten_t& f) {\n  if (f == 0) {\n    // Don't fixup empty dates.\n    return;\n  }\n  const auto now = daten_t_now();\n  if (f > now) {\n    f = now;\n  }\n  // We used to keep it no more than 1 month old, however that\n  // makes no sense, just clear it if we've aged out past a month.\n  // which is ~720 hours\n  if (f + (SECONDS_PER_DAY * 30L) < now) {\n    f = 0; // now - (SECONDS_PER_DAY * 30L);\n  }\n}\n\nvoid NetworkContact::fixup() {\n  fixup_long(ncr_.ncr.lastcontactsent);\n  fixup_long(ncr_.ncr.lasttry);\n}\n\nvoid NetworkContact::AddContact(const wwiv::core::DateTime& t) {\n  const auto d = t.to_daten_t();\n  ncr_.ncr.lasttry = d;\n  ncr_.ncr.lastcontact = d;\n  ncr_.ncr.numcontacts++;\n\n  if (ncr_.ncr.firstcontact == 0) {\n    ncr_.ncr.firstcontact = d;\n  }\n}\n\nvoid NetworkContact::AddConnect(const wwiv::core::DateTime& t, uint32_t bytes_sent,\n                                uint32_t bytes_received) {\n  AddContact(t);\n\n  if (bytes_sent > 0) {\n    ncr_.ncr.lastcontactsent = t.to_daten_t();\n    ncr_.ncr.bytes_waiting = 0;\n    ncr_.ncr.bytes_sent += bytes_sent;\n  }\n  ncr_.ncr.bytes_received += bytes_received;\n}\n\nvoid NetworkContact::AddFailure(const wwiv::core::DateTime& t) {\n  AddContact(t);\n  ncr_.ncr.numfails++;\n}\n\nNetworkContact* Contact::contact_rec_for(int node) {\n  const auto key = NetworkContact::CreateFakeFtnAddress(node);\n  return contact_rec_for(key);\n}\n\nNetworkContact* Contact::contact_rec_for(const std::string& node) {\n  auto it = contacts_.find(node);\n  if (it == std::end(contacts_)) {\n    return nullptr;\n  }\n  it->second.fixup();\n  return &it->second;\n}\n\nvoid Contact::ensure_rec_for(int node) {\n  const auto key = NetworkContact::CreateFakeFtnAddress(node);\n  return ensure_rec_for(key);\n}\n\nvoid Contact::ensure_rec_for(const std::string& node) {\n  const auto* current = contact_rec_for(node);\n  if (current == nullptr) {\n    network_contact_record ncr{};\n    ncr.address = node;\n    const fido::FidoAddress address(node);\n    ncr.ncr.systemnumber = address.node();\n    contacts_.emplace(node, NetworkContact(ncr));\n  }\n}\n\nvoid Contact::add_connect(int node, const wwiv::core::DateTime& time, uint32_t bytes_sent,\n                          uint32_t bytes_received) {\n  const auto key = NetworkContact::CreateFakeFtnAddress(node);\n  add_connect(key, time, bytes_sent, bytes_received);\n}\n\nvoid Contact::add_connect(const std::string& node, const wwiv::core::DateTime& time,\n                          uint32_t bytes_sent,\n                          uint32_t bytes_received) {\n  const auto key = node;\n  auto* c = contact_rec_for(key);\n  if (c == nullptr) {\n    ensure_rec_for(key);\n    c = contact_rec_for(key);\n    if (c == nullptr) {\n      // Unable to add node in add_connect.\n      return;\n    }\n  }\n  c->AddConnect(time, bytes_sent, bytes_received);\n}\n\nvoid Contact::add_failure(int node, const wwiv::core::DateTime& time) {\n  auto* c = contact_rec_for(node);\n  if (c == nullptr) {\n    ensure_rec_for(node);\n    c = contact_rec_for(node);\n    if (c == nullptr) {\n      // Unable to add node in add_connect.\n      return;\n    }\n  }\n  c->AddFailure(time);\n}\n\nvoid Contact::add_failure(const std::string& n, const wwiv::core::DateTime& time) {\n  auto* c = contact_rec_for(n);\n  if (c == nullptr) {\n    ensure_rec_for(n);\n    c = contact_rec_for(n);\n    if (c == nullptr) {\n      // Unable to add node in add_connect.\n      return;\n    }\n  }\n  c->AddFailure(time);\n}\n\n\nvoid Contact::remove(int node) {\n  const auto sn = NetworkContact::CreateFakeFtnAddress(node);\n  contacts_.erase(sn);\n}\n\n\nvoid Contact::add_contact(NetworkContact* c, const wwiv::core::DateTime& time) {\n  c->AddContact(time);\n}\n\nstatic std::string DumpCallout(const NetworkContact& n) {\n  std::ostringstream ss;\n  ss << \"sysnum:         \" << n.systemnumber() << std::endl;\n  ss << \"numcontacts:    \" << n.numcontacts() << std::endl;\n  ss << \"numfails:       \" << n.numfails() << std::endl;\n  ss << \"firstcontact:   \" << daten_to_wwivnet_time(n.firstcontact()) << std::endl;\n  ss << \"lastcontact:    \" << daten_to_wwivnet_time(n.lastcontact()) << std::endl;\n  ss << \"lastcontatsent: \" << daten_to_wwivnet_time(n.lastcontactsent()) << std::endl;\n  ss << \"lasttry:        \" << daten_to_wwivnet_time(n.lasttry()) << std::endl;\n  ss << \"bytes_received: \" << n.bytes_received() << std::endl;\n  ss << \"bytes_sent:     \" << n.bytes_sent() << std::endl;\n  ss << \"bytes_waiting:  \" << n.bytes_waiting() << std::endl;\n\n  return ss.str();\n}\n\nstd::string Contact::ToString() const {\n  std::ostringstream ss;\n  for (const auto& kv : contacts_) {\n    ss << DumpCallout(kv.second) << std::endl;\n  }\n  return ss.str();\n}\n\nstd::filesystem::path Contact::path() const noexcept { return FilePath(net_.dir, CONTACT_NET); }\n\nstd::string Contact::full_pathname() const noexcept { return path().string(); }\n\nnetwork_contact_record to_network_contact_record(const net_contact_rec& n) {\n  network_contact_record ncr{};\n  ncr.address = NetworkContact::CreateFakeFtnAddress(n.systemnumber);\n  ncr.ncr = n;\n  return ncr;\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/net/contact.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_CONTACT_H\n#define INCLUDED_SDK_CONTACT_H\n\n#include \"core/datetime.h\"\n#include \"core/wwivport.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <initializer_list>\n#include <map>\n#include <string>\n#include <utility>\n\nnamespace wwiv::sdk {\n\nstruct network_contact_record {\n  std::string address;\n  net_contact_rec ncr{};\n};\n\nnetwork_contact_record to_network_contact_record(const net_contact_rec& n);\n\nclass NetworkContact {\npublic:\n  NetworkContact() noexcept : ncr_() {}\n  explicit NetworkContact(uint16_t node): ncr_() { \n    ncr_.ncr.systemnumber = node;\n    ncr_.address = CreateFakeFtnAddress(node); \n  }\n  explicit NetworkContact(const std::string& address): ncr_() { ncr_.address = address; }\n  explicit NetworkContact(const net_contact_rec& ncr): ncr_(to_network_contact_record(ncr)) {}\n  explicit NetworkContact(wwiv::sdk::network_contact_record ncr): ncr_(std::move(ncr)) {}\n  ~NetworkContact() = default;\n\n  [[nodiscard]] std::string address() const { return ncr_.address; }\n  [[nodiscard]] uint16_t systemnumber() const { return ncr_.ncr.systemnumber; }\n  [[nodiscard]] uint16_t numcontacts() const { return ncr_.ncr.numcontacts; }\n  [[nodiscard]] uint16_t numfails() const { return ncr_.ncr.numfails; }\n  [[nodiscard]] daten_t firstcontact() const { return ncr_.ncr.firstcontact; }\n  [[nodiscard]] daten_t lastcontact() const { return ncr_.ncr.lastcontact; }\n  [[nodiscard]] daten_t lastcontactsent() const { return ncr_.ncr.lastcontactsent; }\n  [[nodiscard]] daten_t lasttry() const { return ncr_.ncr.lasttry; }\n  [[nodiscard]] uint32_t bytes_received() const { return ncr_.ncr.bytes_received; }\n  [[nodiscard]] uint32_t bytes_sent() const { return ncr_.ncr.bytes_sent; }\n  [[nodiscard]] uint32_t bytes_waiting() const { return ncr_.ncr.bytes_waiting; }\n  void set_bytes_waiting(int32_t bw) { ncr_.ncr.bytes_waiting = bw; }\n\n  void fixup();\n  void AddContact(const wwiv::core::DateTime& t);\n  void AddConnect(const wwiv::core::DateTime& t, uint32_t bytes_sent, uint32_t bytes_received);\n  void AddFailure(const wwiv::core::DateTime& t);\n\n  [[nodiscard]] const net_contact_rec& ncr() const { return ncr_.ncr; }\n\n  static std::string CreateFakeFtnAddress(int node);\n\nprivate:\n  network_contact_record ncr_{};\n};\n\nstatic_assert(sizeof(network_contact_record) == sizeof(NetworkContact),\n  \"network_contact_record == NetworkContact\");\n\n /**\n  * Class for manipulating contact.net\n  */\nclass Contact {\n\n public:\n  explicit Contact(const net::Network& net);\n  Contact(net::Network net, bool save_on_destructor);\n   // VisibleForTesting\n  Contact(net::Network net, std::initializer_list<NetworkContact> l);\n  virtual ~Contact();\n\n  // Was this list initialized properly.\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  // returns a mutable net_contact_rec for system number \"node\"\n  [[nodiscard]] NetworkContact* contact_rec_for(int node);\n  [[nodiscard]] NetworkContact* contact_rec_for(const std::string& node);\n  void ensure_rec_for(int node);\n  void ensure_rec_for(const std::string& node);\n\n  /** add a connection to node, including bytes send and received. */\n  void add_connect(int node, const wwiv::core::DateTime& time, uint32_t bytes_sent, uint32_t bytes_received);\n  void add_connect(const std::string& node, const wwiv::core::DateTime& time, uint32_t bytes_sent,\n                   uint32_t bytes_received);\n  /** add a failure attempt to node */\n  void add_failure(int node, const wwiv::core::DateTime& time);\n  void add_failure(const std::string& node, const wwiv::core::DateTime& time);\n\n  /** Removes the entry for a node */\n  void remove(int node);\n\n  bool Save();\n  [[nodiscard]] const std::map<std::string, NetworkContact>& contacts() const noexcept { return contacts_; }\n  [[nodiscard]] std::map<std::string, NetworkContact>& mutable_contacts() { return contacts_; }\n  [[nodiscard]] std::string ToString() const;\n  [[nodiscard]] std::string full_pathname() const noexcept;\n  [[nodiscard]] std::filesystem::path path() const noexcept;\n\n private:\n   /** add a contact. called by connect or failure. */\n   void add_contact(NetworkContact* c, const wwiv::core::DateTime& time);\n\n   const net::Network net_;\n   bool save_on_destructor_{false};\n   std::map<std::string, NetworkContact> contacts_;\n   bool initialized_{false};\n\n   NetworkContact empty_contact{};\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/net/contact_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/datetime.h\"\n#include \"core/strings.h\"\n#include \"sdk/net/contact.h\"\n#include \"gtest/gtest.h\"\n#include <chrono>\n#include <cstdint>\n\nusing namespace std::chrono_literals;\nusing std::chrono::seconds;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass ContactTest : public testing::Test {\nprotected:\n  ContactTest() {\n    now = DateTime::now();\n    then = now - 100s;\n  }\n  NetworkContact c1{1};\n  NetworkContact c2{2};\n  DateTime now;\n  DateTime then;\n};\n\nTEST_F(ContactTest, SimpleCase) {\n  Contact c({}, {c1, c2});\n  NetworkContact* ncr1 = c.contact_rec_for(1);\n\n  c.add_connect(1, then, 100, 200);\n\n  EXPECT_EQ(then.to_daten_t(), ncr1->lastcontact());\n  EXPECT_EQ(then.to_daten_t(), ncr1->lastcontactsent());\n  EXPECT_EQ(then.to_daten_t(), ncr1->lasttry());\n  EXPECT_EQ(1, ncr1->numcontacts());\n  EXPECT_EQ(0, ncr1->numfails());\n  EXPECT_EQ(100u, ncr1->bytes_sent());\n  EXPECT_EQ(200u, ncr1->bytes_received());\n  EXPECT_EQ(0u, ncr1->bytes_waiting());\n}\n\nTEST_F(ContactTest, MultipleConnects) {\n  Contact c({}, {c1, c2});\n  NetworkContact* ncr1 = c.contact_rec_for(1);\n\n  c.add_connect(1, then, 100, 200);\n  c.add_connect(1, now, 200, 300);\n\n  EXPECT_EQ(now.to_daten_t(), ncr1->lastcontact());\n  EXPECT_EQ(now.to_daten_t(), ncr1->lastcontactsent());\n  EXPECT_EQ(now.to_daten_t(), ncr1->lasttry());\n  EXPECT_EQ(then.to_daten_t(), ncr1->firstcontact());\n  EXPECT_EQ(2u, ncr1->numcontacts());\n  EXPECT_EQ(0u, ncr1->numfails());\n  EXPECT_EQ(300u, ncr1->bytes_sent());\n  EXPECT_EQ(500u, ncr1->bytes_received());\n  EXPECT_EQ(0u, ncr1->bytes_waiting());\n}\n\nTEST_F(ContactTest, WithFailure) {\n  Contact c({}, {c1, c2});\n  NetworkContact* ncr1 = c.contact_rec_for(1);\n\n  c.add_connect(1, then, 100, 200);\n  c.add_failure(1, now);\n\n  EXPECT_EQ(now.to_daten_t(), ncr1->lastcontact());\n  EXPECT_EQ(now.to_daten_t(), ncr1->lasttry());\n  EXPECT_EQ(then.to_daten_t(), ncr1->lastcontactsent());\n  EXPECT_EQ(then.to_daten_t(), ncr1->firstcontact());\n  EXPECT_EQ(2u, ncr1->numcontacts());\n  EXPECT_EQ(1u, ncr1->numfails());\n  EXPECT_EQ(100u, ncr1->bytes_sent());\n  EXPECT_EQ(200u, ncr1->bytes_received());\n  EXPECT_EQ(0u, ncr1->bytes_waiting());\n}\n\nTEST_F(ContactTest, EnsureBytesWaitingClears) {\n  Contact c({}, {c1, c2});\n  NetworkContact* ncr1 = c.contact_rec_for(1);\n\n  ncr1->set_bytes_waiting(100);\n  c.add_connect(1, then, 100, 200);\n  EXPECT_EQ(0u, ncr1->bytes_waiting());\n\n  ncr1->set_bytes_waiting(100);\n  c.add_failure(1, now);\n  EXPECT_EQ(100u, ncr1->bytes_waiting());\n\n  c.add_connect(1, now + 1s, 100, 200);\n  EXPECT_EQ(0u, ncr1->bytes_waiting());\n}\n\n"
  },
  {
    "path": "sdk/net/ftn_msgdupe.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/ftn_msgdupe.h\"\n\n#include \"core/crc32.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/filenames.h\"\n#include <cstdint>\n#include <ctime>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nFtnMessageDupe::FtnMessageDupe(const Config& config) : FtnMessageDupe(config.datadir(), true) {}\n\nFtnMessageDupe::FtnMessageDupe(const std::filesystem::path& datadir, bool use_filesystem)\n    : datadir_(datadir), use_filesystem_(use_filesystem) {\n  if (!datadir_.empty()) {\n    initialized_ = Load();\n  }\n}\n\nbool FtnMessageDupe::Load() {\n  if (!use_filesystem_) {\n    return true;\n  }\n  DataFile<msgids> file(FilePath(datadir_, MSGDUPE_DAT),\n                        File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  if (!file) {\n    LOG(ERROR) << \"Unable to initialize FtnMessageDupe: Unable to create file.\";\n    return false;\n  }\n\n  const auto num_records = file.number_of_records();\n  if (num_records == 0) {\n    // nothing to read.\n    return true;\n  }\n  if (!file.ReadVector(dupes_)) {\n    LOG(ERROR) << \"Unable to initialize FtnMessageDupe: Read Failed\";\n    return false;\n  }\n  for (const auto& d : dupes_) {\n    header_dupes_.insert(d.header);\n    msgid_dupes_.insert(d.msgid);\n  }\n  return true;\n}\n\nbool FtnMessageDupe::Save() {\n  if (!use_filesystem_) {\n    return true;\n  }\n  DataFile<msgids> file(FilePath(datadir_, MSGDUPE_DAT),\n                        File::modeReadWrite | File::modeBinary | File::modeCreateFile |\n                            File::modeTruncate);\n  if (!file) {\n    return false;\n  }\n  return file.WriteVector(dupes_);\n}\n\nstd::string FtnMessageDupe::CreateMessageID(const wwiv::sdk::fido::FidoAddress& a) {\n  if (!initialized_) {\n    std::string address_string;\n    if (a.point() != 0) {\n      address_string = to_zone_net_node_point(a);\n    } else {\n      address_string = to_zone_net_node(a);\n    }\n    return StrCat(address_string, \" DEADBEEF\");\n  }\n\n  DataFile<uint64_t> file(FilePath(datadir_, MSGID_DAT),\n                          File::modeReadWrite | File::modeBinary | File::modeCreateFile,\n                          File::shareDenyReadWrite);\n  if (!file) {\n    throw std::runtime_error(StrCat(\"Unable to open file: \", file.file()));\n  }\n  const uint64_t now = time(nullptr);\n  uint64_t msg_num;\n  if (!file.Read(0, &msg_num)) {\n    msg_num = now;\n  }\n  if (msg_num < now) {\n    // We always want to be at least equal to the current time.\n    msg_num = now;\n  }\n  ++msg_num;\n  file.file().Seek(0, File::Whence::begin);\n  file.Write(0, &msg_num);\n\n  std::string address_string;\n\n  if (a.point() != 0) {\n    address_string = to_zone_net_node_point(a);\n  } else {\n    address_string = to_zone_net_node(a);\n  }\n  return fmt::sprintf(\"%s %08X\", address_string, msg_num);\n}\n\n// static\nstd::string FtnMessageDupe::GetMessageIDFromText(const std::string& text) {\n  static const std::string kMSGID = \"MSGID: \";\n  auto lines = wwiv::sdk::fido::split_message(text);\n  for (const auto& line : lines) {\n    if (line.empty() || line.front() != '\\001' || line.size() < 2) {\n      continue;\n    }\n    auto s = line.substr(1);\n    if (starts_with(s, kMSGID)) {\n      // Found the message ID, mail here.\n      return StringTrim(s.substr(kMSGID.size()));\n    }\n  }\n  return \"\";\n}\n\n// static\nstd::string FtnMessageDupe::GetMessageIDFromWWIVText(const std::string& text) {\n  static const std::string kMSGID = \"0MSGID: \";\n  auto lines = wwiv::sdk::fido::split_message(text);\n  for (const auto& line : lines) {\n    if (line.empty() || line.front() != '\\004' || line.size() < 2) {\n      continue;\n    }\n    auto s = line.substr(1);\n    if (starts_with(s, kMSGID)) {\n      // Found the message ID, mail here.\n      return StringTrim(s.substr(kMSGID.size()));\n    }\n  }\n  return \"\";\n}\n\n// static\nbool FtnMessageDupe::GetMessageCrc32s(const wwiv::sdk::fido::FidoPackedMessage& msg,\n                                      uint32_t& header_crc32, uint32_t& msgid_crc32) {\n  std::ostringstream s;\n  s << msg.nh.orig_net << \"/\" << msg.nh.orig_node << \"\\r\\n\";\n  s << msg.nh.dest_net << \"/\" << msg.nh.dest_node << \"\\r\\n\";\n  s << msg.vh.date_time << \"\\r\\n\";\n  s << msg.vh.from_user_name << \"\\r\\n\";\n  s << msg.vh.subject << \"\\r\\n\";\n  s << msg.vh.to_user_name << \"\\r\\n\";\n\n  header_crc32 = crc32string(s.str());\n  const auto msgid = FtnMessageDupe::GetMessageIDFromText(msg.vh.text);\n  msgid_crc32 = crc32string(msgid);\n  return true;\n}\n\nbool FtnMessageDupe::add(const FidoPackedMessage& msg) {\n  uint32_t header_crc32 = 0;\n  uint32_t msgid_crc32 = 0;\n\n  if (!GetMessageCrc32s(msg, header_crc32, msgid_crc32)) {\n    return false;\n  }\n\n  return add(header_crc32, msgid_crc32);\n}\n\nbool FtnMessageDupe::add(uint32_t header_crc32, uint32_t msgid_crc32) {\n  if (header_crc32 != 0) {\n    header_dupes_.insert(header_crc32);\n  }\n  if (msgid_crc32 != 0) {\n    msgid_dupes_.insert(msgid_crc32);\n  }\n\n  msgids ids{};\n  ids.header = header_crc32;\n  ids.msgid = msgid_crc32;\n\n  dupes_.emplace_back(ids);\n  return Save();\n}\n\nbool FtnMessageDupe::remove(uint32_t header_crc32, uint32_t msgid_crc32) {\n  for (auto it = dupes_.begin(); it != std::end(dupes_);) {\n    const auto& d = *it;\n    if (d.header == header_crc32 && d.msgid == msgid_crc32) {\n      dupes_.erase(it);\n      header_dupes_.erase(header_crc32);\n      msgid_dupes_.erase(msgid_crc32);\n      return Save();\n    }\n    ++it;\n  }\n  return false;\n}\n\nbool FtnMessageDupe::is_dupe(uint32_t header_crc32, uint32_t msgid_crc32) const {\n  if (contains(header_dupes_, header_crc32) && header_crc32 != 0) {\n    return true;\n  }\n  if (contains(msgid_dupes_, msgid_crc32) && msgid_crc32 != 0) {\n    return true;\n  }\n  return false;\n}\n\nbool FtnMessageDupe::is_dupe(const FidoPackedMessage& msg) const {\n  uint32_t header_crc32 = 0;\n  uint32_t msgid_crc32 = 0;\n\n  if (!GetMessageCrc32s(msg, header_crc32, msgid_crc32)) {\n    return false;\n  }\n  return is_dupe(header_crc32, msgid_crc32);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/net/ftn_msgdupe.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_FTN_MSGDUPE_H\n#define INCLUDED_SDK_FTN_MSGDUPE_H\n\n#include <filesystem>\n#include <string>\n#include <set>\n#include <vector>\n#include \"sdk/config.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/fido/fido_packets.h\"\n\nnamespace wwiv::sdk {\n\n#pragma pack(push, 1)\n struct msgids {\n   uint32_t msgid;\n   uint32_t header;\n };\n#pragma pack(pop)\n\nstatic_assert(std::is_trivial<msgids>::value == true);\nstatic_assert(sizeof(msgids) == sizeof(uint64_t), \"sizeof(msgids) must be the same as an int64.\");\n\nclass FtnMessageDupe final {\npublic:\n  explicit FtnMessageDupe(const Config& config);\n  FtnMessageDupe(const std::filesystem::path& datadir, bool use_filesystem);\n  ~FtnMessageDupe() = default;\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  [[nodiscard]] std::string CreateMessageID(const fido::FidoAddress& a);\n  bool add(const fido::FidoPackedMessage& msg);\n  bool add(uint32_t header_crc32, uint32_t msgid_crc32);\n  bool remove(uint32_t header_crc32, uint32_t msgid_crc32);\n  /** returns true if either the header or msgid crc is duplicated */\n  [[nodiscard]] bool is_dupe(uint32_t header_crc32, uint32_t msgid_crc32) const;\n  [[nodiscard]] bool is_dupe(const fido::FidoPackedMessage& msg) const;\n\n  /** Returns the MSGID from this message or an empty string. */\n  [[nodiscard]] static std::string GetMessageIDFromText(const std::string& text);\n  static bool GetMessageCrc32s(const fido::FidoPackedMessage& msg,\n                               uint32_t& header_crc32, uint32_t& msgid_crc32);\n\n  /**\n   * Returns the MSGID from this message in WWIV format \n   * (^D0MSGID vs. ^AMSGID) or an empty string.\n   */\n  [[nodiscard]] static std::string GetMessageIDFromWWIVText(const std::string& text);\n\nprivate:\n  bool Load();\n  bool Save();\n\n  bool initialized_{ false };\n  const std::filesystem::path datadir_;\n  std::vector<msgids> dupes_;\n  std::set<uint32_t> msgid_dupes_;\n  std::set<uint32_t> header_dupes_;\n  bool use_filesystem_{true};\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/net/ftn_msgdupe_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/fido/fido_address.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/sdk_helper.h\"\n#include <cstdint>\n#include <cstring>\n#include <ctime>\n#include <string>\n#include <vector>\n\nusing namespace std;\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::strings;\n\nclass FtnMsgDupeTest : public testing::Test {\npublic:\n  FtnMsgDupeTest() {}\n\n  [[nodiscard]] bool CreateDupes(const std::vector<msgids>& ids) const {\n    DataFile<msgids> file(FilePath(helper.datadir(), MSGDUPE_DAT),\n                          File::modeReadWrite | File::modeBinary | File::modeCreateFile |\n                              File::modeTruncate);\n    if (!file) {\n      return false;\n    }\n\n    return file.WriteVector(ids);\n  }\n\n  [[nodiscard]] bool SetLastMessageId(uint32_t message_id) const {\n    uint64_t id = message_id;\n    DataFile<uint64_t> file(FilePath(helper.datadir(), MSGID_DAT),\n                            File::modeReadWrite | File::modeBinary | File::modeCreateFile,\n                            File::shareDenyReadWrite);\n    if (!file) {\n      return false;\n    }\n    return file.Write(&id, 1);\n  }\n\n  SdkHelper helper;\n};\n\n// This is what the old msgdupe used.\nuint64_t as64(uint32_t header, uint32_t msgid) {\n  return static_cast<uint64_t>(header) << 32 | msgid;\n}\n\nTEST_F(FtnMsgDupeTest, As64) {\n  const auto i = as64(2, 1);\n  LOG(INFO) << i;\n  LOG(INFO) << \"msgids sizeof: \" << sizeof(msgids);\n  LOG(INFO) << \"i sizeof: \" << sizeof(i);\n  msgids ids{};\n  \n  memcpy(static_cast<void*>(&ids), &i, sizeof(i));\n  LOG(INFO) << \"header: \" << ids.header << \"; msgid: \" << ids.msgid;\n  EXPECT_EQ(2u, ids.header);\n  EXPECT_EQ(1u, ids.msgid);\n}\n\nTEST_F(FtnMsgDupeTest, MsgId_NoExists) { \n  FtnMessageDupe dupe(helper.datadir(), true);\n  const FidoAddress a{\"1:2/3\"};\n  const auto now = time(nullptr);\n  const auto line = dupe.CreateMessageID(a);\n  auto parts = SplitString(line, \" \");\n  ASSERT_EQ(2, wwiv::stl::ssize(parts));\n  EXPECT_TRUE(starts_with(parts.at(0), \"1:2/3\"));\n  const auto id = std::stol(parts.at(1), nullptr, 16);\n\n  EXPECT_LT(std::abs(id - now), 11) << \"id: \" << id << \"; now: \" << now;\n  EXPECT_TRUE(File::Exists(FilePath(helper.datadir(), MSGID_DAT)));\n}\n\nTEST_F(FtnMsgDupeTest, Exists) {\n  const auto now = daten_t_now();\n  const auto last_message_id = now + 10000;\n  ASSERT_TRUE(SetLastMessageId(last_message_id));\n  ASSERT_TRUE(File::Exists(FilePath(helper.datadir(), MSGID_DAT)));\n  FtnMessageDupe dupe(helper.datadir(), true);\n  const FidoAddress a{\"1:2/3\"};\n  const auto line = dupe.CreateMessageID(a);\n  auto parts = SplitString(line, \" \");\n  ASSERT_EQ(2u, parts.size());\n  const auto id = static_cast<unsigned int>(std::stoul(parts.at(1), nullptr, 16));\n\n  EXPECT_EQ(id - last_message_id, 1u) << \"id: \" << id << \"; last_message_id: \" << last_message_id\n                                      << \"; delta: \" << (id - last_message_id);\n}\n\nTEST_F(FtnMsgDupeTest, Smoke) {\n  FtnMessageDupe dupe(helper.datadir(), false);\n  dupe.add(1, 2);\n  EXPECT_TRUE(dupe.is_dupe(1, 2));\n  EXPECT_FALSE(dupe.is_dupe(2, 1));\n}\n\nTEST_F(FtnMsgDupeTest, Remove) {\n  FtnMessageDupe dupe(helper.datadir(), false);\n  dupe.add(1, 2);\n  EXPECT_TRUE(dupe.is_dupe(1, 2));\n  dupe.remove(1, 2);\n  EXPECT_FALSE(dupe.is_dupe(1, 2));\n}"
  },
  {
    "path": "sdk/net/legacy_net.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NET_LEGACY_NET_H\n#define INCLUDED_SDK_NET_LEGACY_NET_H\n\n#include <cstdint>\n\n#ifndef DATEN_T_DEFINED\ntypedef uint32_t daten_t;\n#define DATEN_T_DEFINED\n#endif\n\n#pragma pack(push, 1)\n\n/* All network nodes except the destination will only look at:\n *   tosys - the destination system.  Is 0 if more than one system\n *   list_len - if (tosys==0) then list_len is the number of destination\n *     systems in a list immediately after the header.  NOTE this list will\n *     be 2*list_len bytes long, since each system entry is 2 bytes.\n *   length - is the overall length of the message, not including the header\n *     or the system ist length.  Thus the overall length of a message in\n *     the net will be (sizeof(net_header_rec) + 2*list_len + length)\n */\nstruct net_header_rec {\n  uint16_t tosys,  /* destination system */\n      touser,      /* destination user */\n      fromsys,     /* originating system */\n      fromuser,    /* originating user */\n      main_type,   /* main message type */\n      minor_type,  /* minor message type */\n      list_len;    /* # of entries in system list */\n  daten_t daten;   /* date/time sent */\n  uint32_t length; /* # of bytes of msg after header */\n  uint16_t method; /* method of compression */\n};\n\n/*\n * Please note that not all of these are used yet, some will probably never\n * be used, but sounded like a good idea at the time.\n */\n\nconstexpr uint16_t main_type_net_info = 0x0001;      /* type 1 normal network updates */\nconstexpr uint16_t main_type_email = 0x0002;         /* type 2 email by user number */\nconstexpr uint16_t main_type_post = 0x0003;          /* type 3 post from sub host */\nconstexpr uint16_t main_type_file = 0x0004;          /* type 4 file transfer system */\nconstexpr uint16_t main_type_pre_post = 0x0005;      /* type 5 post to sub host */\nconstexpr uint16_t main_type_external = 0x0006;      /* type 6 external message */\nconstexpr uint16_t main_type_email_name = 0x0007;    /* type 7 email by user name */\nconstexpr uint16_t main_type_net_edit = 0x0008;      /* type 8 network editor packet */\nconstexpr uint16_t main_type_sub_list = 0x0009;      /* type 9 subs.lst update */\nconstexpr uint16_t main_type_extra_data = 0x000a;    /* type 10 unused */\nconstexpr uint16_t main_type_group_bbslist = 0x000b; /* type 11 network update from GC */\nconstexpr uint16_t main_type_group_connect = 0x000c; /* type 12 network update from GC */\nconstexpr uint16_t main_type_group_binkp = 0x000d;   /* type 13 network update from GC */\nconstexpr uint16_t main_type_group_info = 0x000e;    /* type 14 misc update from GC */\nconstexpr uint16_t main_type_ssm = 0x000f;           /* type 15 xxx read your mail */\nconstexpr uint16_t main_type_sub_add_req = 0x0010;   /* type 16 add me to your sub */\nconstexpr uint16_t main_type_sub_drop_req = 0x0011;  /* type 17 remove me from your sub*/\nconstexpr uint16_t main_type_sub_add_resp = 0x0012;  /* type 18 status of add, 0=ok */\nconstexpr uint16_t main_type_sub_drop_resp = 0x0013; /* type 19 status of drop, 0=ok */\nconstexpr uint16_t main_type_sub_list_info = 0x0014; /* type 20 info for subs.lst file */\n\nconstexpr uint16_t main_type_new_post = 0x001a;     /* type 26 post by sub name */\nconstexpr uint16_t main_type_new_external = 0x001b; /* type 27 auto-proc ext. msgs */\nconstexpr uint16_t main_type_game_pack = 0x001c;    /* type 28 game packs */\n\n// Minor types used by main_type_net_info\n\nconstexpr uint16_t net_info_general_message = 0x0000;\nconstexpr uint16_t net_info_bbslist = 0x0001;\nconstexpr uint16_t net_info_connect = 0x0002;\nconstexpr uint16_t net_info_sub_lst = 0x0003;\nconstexpr uint16_t net_info_wwivnews = 0x0004;\nconstexpr uint16_t net_info_fbackhdr = 0x0005;\nconstexpr uint16_t net_info_more_wwivnews = 0x0006;\nconstexpr uint16_t net_info_categ_net = 0x0007;\nconstexpr uint16_t net_info_network_lst = 0x0008;\nconstexpr uint16_t net_info_file = 0x0009;\nconstexpr uint16_t net_info_binkp = 0x0010;\n\n/* these are in main_type_sub_*_resp, as the first byte of the text */\nconstexpr uint16_t sub_adddrop_ok = 0x00;            /* you've been added/removed */\nconstexpr uint16_t sub_adddrop_not_host = 0x01;      /* don't host that sub */\nconstexpr uint16_t sub_adddrop_not_there = 0x02;     /* can't drop, you're not listed */\nconstexpr uint16_t sub_adddrop_not_allowed = 0x03;   /* not allowed to add/drop you */\nconstexpr uint16_t sub_adddrop_already_there = 0x04; /* already in sub */\nconstexpr uint16_t sub_adddrop_error = 0xff;         /* internal error */\n\nstruct net_contact_rec {\n  uint16_t systemnumber,   /* System number of the contact */\n      numcontacts,         /* # of contacts with system */\n      numfails;            /* # of consec failed calls out */\n  uint32_t firstcontact,   /* time of first contact w/ system */\n      lastcontact,         /* time of most recent contact */\n      lastcontactsent,     /* time of last contact w/data sent */\n      lasttry;             /* time of last try to connect */\n  uint32_t bytes_received, /* bytes received from system */\n      bytes_sent,          /* bytes sent to system */\n      bytes_waiting;       /* bytes waiting to be sent */\n};\n\n/* Each system will hold a file of these records.  Each record will hold the\n * data pertaining to all contacts with other systems.\n *\n * systemnumber tells what other system this data is for.\n * numcontacts - how many times a connection has been made with that system\n * numfails tells how many times this system has tried to call this other\n *   system but failed.  This is consecutive times, and is zeroed out\n *   when a successful connection is made by calling out.\n * firstcontact is time in unix format of the last time that system has been\n *   contacted on the net.\n * lastcontact is the time the last contact with that system was made.\n * lastcontactsent is the last time data was SENT to that system.\n * lasttry is the last time we tried to call out to that system.\n * bytes_received is number of bytes received from that system.\n * bytes_sent is number of bytes sent to that system.\n * bytes_waiting is the number of bytes waiting to be sent out to that\n *   system.\n *\n * This data is maintained so that the BBS can decide which other system to\n * attempt connection with next.\n */\nstruct net_system_list_rec {\n  // system number of the system\n  uint16_t sysnum;\n  /* phone number of system */\n  char phone[13];\n  /* name of system */\n  char name[40];\n  /* group of the system */\n  uint8_t group;\n  /* max baud rate of system */\n  uint16_t speed;\n  /* other info about sys (bit-mapped) */\n  uint16_t other;\n  /* how to get there */\n  uint16_t forsys;\n  /* how long to get there */\n  int16_t numhops;\n  union {\n    /* routing factor */\n    uint16_t rout_fact;\n    /* cost factor */\n    float cost;\n    /* temporary variable */\n    int32_t temp;\n  } xx;\n};\n\n/**\n * Contains the metadata for each network.\n *\n * On disk format for networks.dat\n */\nstruct net_networks_rec_disk {\n  /* type of network */\n  uint8_t type;\n  /* network name */\n  char name[16];\n  /* directory for net data */\n  char dir[69];\n  /* system number */\n  uint16_t sysnum;\n  uint8_t padding[12];\n};\n\n#pragma pack(pop)\n\n// This data is all read in from a text file which holds info about all of\n// the systems in the network.  This text file doesn't hold connection info\n// between the systems.  The purpose of all records should be obvious.\n\n// BBSLIST designators\n\nconstexpr uint16_t  other_inet = 0x0001;         /* $ - System is PPP capable         */\nconstexpr uint16_t  other_fido = 0x0002;         /* \\ - System run Fido frontend      */\nconstexpr uint16_t  other_telnet = 0x0004;       /* | - System is a telnet node       */\nconstexpr uint16_t  other_no_links = 0x0008;     /* < - System refuses links          */\nconstexpr uint16_t  other_fts_blt = 0x0010;      /* > - System uses FTS/BLT system    */\nconstexpr uint16_t  other_direct = 0x0020;       /* ! - System accepts direct connects*/\nconstexpr uint16_t  other_unregistered = 0x0040; /* / - System is unregistered        */\nconstexpr uint16_t  other_fax = 0x0080;          /* ? - System accepts faxes          */\nconstexpr uint16_t  other_end_system = 0x0100;   /* _ - System is a dead end node     */\nconstexpr uint16_t  other_net_server = 0x0200;   /* + - System is network server      */\nconstexpr uint16_t  other_unused = 0x0400;       /* = - Unused identifier 2           */\n\n/* system type designators */\nconstexpr uint16_t  other_net_coord = 0x0800;   /* & - NC */\nconstexpr uint16_t  other_group_coord = 0x1000; /* % - GC */\nconstexpr uint16_t  other_area_coord = 0x2000;  /* ^ - AC */\nconstexpr uint16_t  other_subs_coord = 0x4000;  /* ~ - Sub Coordinator */\n\n/* This record holds info about other systems that the sysop has determined\n * that we can call out to.\n *\n * sysnum - system number that we can call\n * macnum - macro/script number to use to call that system.  This is set\n *   to zero if we just dial it directly.\n * options - bit mapped.  See constants below.\n * call_every_x_minutes - if non-zero, then the minimum number of days between calls\n *   to that system, even if there is nothing waiting to be sent there.\n * password - is the password used for connection to this system.\n */\nconstexpr uint16_t unused_options_sendback = 0x0001;     /* & they can send data back */\nconstexpr uint16_t unused_options_ATT_night = 0x0002;    /* - callout only at AT&T nigh hours */\nconstexpr uint16_t unused_options_ppp = 0x0004;          /* _ transfer via PPP */\nconstexpr uint16_t options_no_call = 0x0008;             /* + don't call that system, it will */\nconstexpr uint16_t unused_options_receive_only = 0x0010; /* ~ never send anything */\nconstexpr uint16_t unused_options_once_per_day = 0x0020; /* ! only call once per day */\nconstexpr uint16_t unused_options_compress = 0x0040;     /* ; compress data */\nconstexpr uint16_t unused_options_hslink = 0x0080;       /* ^ use HSLINK if available */\nconstexpr uint16_t unused_options_force_ac = 0x0100;     /* $ force area code on dial */\nconstexpr uint16_t unused_options_dial_ten = 0x0200;     /* * use ten digit dialing format */\nconstexpr uint16_t options_hide_pend = 0x0400;           /* = hide in pending display */\n\n\n\n#endif\n"
  },
  {
    "path": "sdk/net/net.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/networks.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nnamespace wwiv::sdk::net {\n\nbool Network::try_load_nodelist() {\n  if (nodelist && nodelist->initialized() && !nodelist->entries().empty()) {\n    return true;\n  }\n\n  const auto nl_path = fido::Nodelist::FindLatestNodelist(dir, fido.nodelist_base);\n  const auto domain = fido::domain_from_address(fido.fido_address);\n  nodelist = std::make_shared<fido::Nodelist>(core::FilePath(dir, nl_path), domain);\n  return nodelist->initialized();\n}\n\nstd::string to_string(const Network& n) {\n  switch (n.type) {\n  case network_type_t::ftn:\n    return fmt::format(\"|#9(|#2{}|#9@|#1{}|#9) \", n.fido.fido_address, n.name);\n  case network_type_t::internet:\n    return fmt::format(\"|#9(|#2{}|#9@|#1Internet|#9) \", n.name);\n  case network_type_t::news:\n    return fmt::format(\"|#9(|#2{}|#9@|#1News|#9) \", n.name);\n  case network_type_t::wwivnet:\n    return fmt::format(\"|#9(|#2@{}|#9.|#1{}|#9) \", n.sysnum, n.name);\n  case network_type_t::unknown:\n    return \"|#9(|#6unknown|#9) \";\n  }\n  return fmt::format(\"|#9(|#2@{}|#9.|#1{}|#9) \", n.sysnum, n.name);\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/net/net.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NET_NET_H\n#define INCLUDED_SDK_NET_NET_H\n\n#include <cstdint>\n#include <filesystem>\n#include <memory>\n#include <string>\n#include <utility>\n#include <vector>\n#include \"core/uuid.h\"\n#include \"sdk/fido/nodelist.h\"\n\n// We don't want anyone else including legacy_net.h\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/net/legacy_net.h\"\n\n\nnamespace wwiv::sdk::net {\n\n/*\n * This data is also read in from a text file.  It tells how much it costs for\n * sysnum to call out to other systems.  It is stored in connect.net.\n * This is never written as binary data.\n */\nstruct net_interconnect_rec {\n  /* outward calling system */\n  uint16_t sysnum;\n  /* num systems it can call */\n  uint16_t numsys;\n\n  net_interconnect_rec() : sysnum(0), numsys(0) {}\n  void clear() noexcept {\n    numsys = 0;\n    sysnum = 0;\n    connect.clear();\n    cost.clear();\n  }\n  /* points to an array of numsys integers that tell which\n   * other systems sysnum can connect to\n   */\n  std::vector<uint16_t> connect;\n  /*\n   * cost[] - points to an array of numsys floating point numbers telling\n   *   how much it costs to connect to that system, per minute.  ie, it would\n   *   cost (cost[1]) dollars per minute for sysnum to call out to system\n   *   number (connect[1]).\n   */\n  std::vector<float> cost;\n};\n\n/**\n * Contains per-node data in callout.net\n */\nstruct net_call_out_rec {\n  net_call_out_rec() = default;\n  net_call_out_rec(std::string f, uint16_t sn, uint16_t mn, uint16_t op, uint16_t ca, int8_t nh,\n                   int8_t xh, std::string pw, uint8_t, uint16_t nk)\n      : ftn_address(std::move(f)), sysnum(sn), macnum(mn), options(op), call_every_x_minutes(ca),\n        min_hr(nh), max_hr(xh), session_password(std::move(pw)), min_k(nk) {}\n  // FTN Address.\n  std::string ftn_address;\n  /* system number */\n  uint16_t sysnum = 0;\n  /* macro/script to use */\n  uint16_t macnum = 0;\n  /* bit mapped */\n  uint16_t options = 0;\n  /* hours between callouts */\n  uint16_t call_every_x_minutes = 0;\n  /* callout min hour */\n  int8_t min_hr = -1;\n  /* callout max hour */\n  int8_t max_hr = -1;\n  /* password for system */\n  std::string session_password;\n  /* minimum # k before callout */\n  uint16_t min_k = 0;\n};\n\n\n/**\n * Indicates this is the fake FTN outbound node.  This should\n * not be exposed to users unless required. It's an implementation detail.\n */\nstatic constexpr int16_t FTN_FAKE_OUTBOUND_NODE = 32765;\nstatic constexpr char FTN_FAKE_OUTBOUND_ADDRESS[] = \"@32765\";\n\n/**\n * Indicates this is the fake FTN outbound node.  This should\n * not be exposed to users unless required. It's an implementation detail.\n */\nstatic constexpr int16_t INTERNET_NEWS_FAKE_OUTBOUND_NODE = 32766;\nstatic constexpr char INTERNET_NEWS_FAKE_OUTBOUND_ADDRESS[] = \"@32766\";\n\n/**\n * Indicates this is the fake FTN outbound node.  This should\n * not be exposed to users unless required. It's an implementation detail.\n */\nstatic constexpr int16_t INTERNET_EMAIL_FAKE_OUTBOUND_NODE = 32767;\nstatic constexpr char INTERNET_EMAIL_FAKE_OUTBOUND_ADDRESS[] = \"@32767\";\n\n/**\n * Used to indicate no node number in functions that return -1 when no\n * WWIVnet node number is found.\n */\nstatic constexpr uint16_t WWIVNET_NO_NODE = 65535;\n\nenum class fido_packet_t { unset, type2_plus };\nenum class fido_transport_t { unset, directory, binkp };\nenum class fido_mailer_t { unset, flo, attach };\n\nenum class fido_bundle_status_t : char {\n  normal = 'f',\n  crash = 'c',\n  direct = 'd',\n  hold = 'h',\n  immediate = 'i',\n  // Do not use for creating a packet.\n  unknown = 'x'\n};\n\n// Remember to update the serialize function in networks_cereal.h and also\n// the code (packet_config_for) in fido_callout.cpp when updating these.\n/**\n * Fido specific per-packet settings.\n */\nstruct fido_packet_config_t {\n  // Type of packet to create\n  fido_packet_t packet_type = fido_packet_t::unset;\n  // File extension to map to type defined in archivers.dat\n  std::string compression_type;\n  // Password to use in the packet.  It must be <= 8 chars.\n  std::string packet_password;\n  // Password to use for areafix requests. It must be <= 8 chars.\n  std::string tic_password;\n  // Password to use for areafix requests. It must be <= 8 chars.\n  std::string areafix_password;\n  // Maximum size of the bundles in bytes before a new one is created.\n  int max_archive_size = 0;\n  // Maximum size of the packets in bytes before a new one is created.\n  int max_packet_size = 0;\n  // Status used for the bundles or packets to send.\n  // i.e.: CRASH, IMMEDIATE, NORMAL.\n  fido_bundle_status_t netmail_status = fido_bundle_status_t::normal;\n};\n\n/**\n * Contains the binkp session specific settings. This can come\n * from a fidonet nodelist, WWIVnet's binkp.net, or overrides\n * specified in the address settings.\n */\nstruct binkp_session_config_t {\n  std::string host;\n  int port{0};\n  std::string password;\n};\n\n/**\n * Minimal callout configuration\n */\nstruct network_callout_config_t {\n  bool auto_callouts{false};\n  int call_every_x_minutes{15};\n  int min_k{0};\n};\n\n/**\n * Specific config for a fido node.\n */\nstruct fido_node_config_t {\n  // Space separated list of nodes that route through this node.\n  // i.e.: \"1:*\" will route all of zone 1 through this node.\n  std::string routes;\n  // Configuration for packet specific options.\n  fido_packet_config_t packet_config;\n  // BinkP session options.\n  binkp_session_config_t binkp_config;\n  // Automatic callout config\n  network_callout_config_t callout_config;\n};\n\n// ***************************************************************************************\n// ****\n// **** Remember to update the serialize function in networks_cereal.h when updating these.\n// ****\n// ***************************************************************************************\n\n/**\n * 5.8+ specific per-network settings.  \n * \n * These are common across all network types.\n */\nstruct common_network_config_t {\n  // Should unrecognized network subs be automatically added\n  bool auto_add{false};\n  // Configuration INI file for automatically adding subs\n  std::string auto_add_ini;\n};\n\n/**\n * Fido specific per-network settings.\n */\nstruct fido_network_config_t {\n  // Your FTN network address. (i.e. 1:100/123) [3d-5d accepted].\n  std::string fido_address;\n  // Your FTN nodelist base name (i.e. NODELiST)\n  std::string nodelist_base;\n  // Your FTN network backbone.na file (i.e. FSXNET.NA)\n  std::string backbone_filename;\n  // Fidonet mailer type {FLO, Attach}.\n  // Only FLO is even close to being supported.\n  fido_mailer_t mailer_type;\n  // Type of transport to use for this packet.\n  fido_transport_t transport;\n  // Inbound directory for packets\n  std::string inbound_dir;\n  // Inbound temporary directory.\n  std::string temp_inbound_dir;\n  // Outbound temporary directory.\n  std::string temp_outbound_dir;\n  // Outbound directory for packets\n  std::string outbound_dir;\n  // Location of FidoNet NetMail directory.\n  // Note that this usually lives under your mailer's directory\n  // if you are using an ATTACH style mailer.\n  std::string netmail_dir;\n  // Configuration for packet specific options.\n  fido_packet_config_t packet_config;\n  // Location to move bad packets\n  std::string bad_packets_dir;\n  // Place tic files here.  based off of net_dir.\n  std::string tic_dir;\n  // Unknown files go here.  based off of net_dir.\n  std::string unknown_dir;\n  // Default Origin line to use for this network.\n  std::string origin_line;\n  \n  // Process TIC files\n  bool process_tic{false};\n  // Convert wwiv heart codes to standard pipes.\n  bool wwiv_pipe_color_codes{true};\n  // convert wwiv user color pipe codes to standard pipe codes.\n  bool wwiv_heart_color_codes{false};\n  // Allow any pipe codes, WWIV and standard.\n  bool allow_any_pipe_codes{true};\n  // Max number of days old a packet is allowed to be and still be imported.\n  // This should help with dupes.  A value of 0 means no age restriction.\n  int max_echomail_age_days{0};\n};\n\n/**\n * The types of networks currently or optimistically one day supported by WWIV.\n */\nenum class network_type_t : uint8_t { wwivnet = 0, ftn, internet, news, unknown = 255 };\n\n/**\n * Internal class for network defined in networks.json.\n *\n * This class used to be known as net_neworks_rec and is persisted\n * in legacy wwiv format as net_networks_rec_disk.\n */\nclass Network {\npublic:\n  Network() = default;\n  Network(network_type_t t, std::string n) : type(t), name(std::move(n)) {}\n  Network(network_type_t t, std::string n, std::filesystem::path d, uint16_t s)\n      : type(t), name(std::move(n)), dir(std::move(d)), sysnum(s) {}\n\n  /**\n   * Tries to load the Nodelist for this network\n   * returns true if the nodelist is found, and parsed successfully.\n   */\n  [[nodiscard]] bool try_load_nodelist();\n\n  /*\n   * The current network number, assigned when loaded.\n   */\n  [[nodiscard]] int network_number() const noexcept { return network_number_; };\n\n  /* type of network */\n  network_type_t type{network_type_t::unknown};\n  /* network name. Up to 16 chars*/\n  std::string name;\n  /* directory for net data */\n  std::filesystem::path dir;\n  /* system number */\n  uint16_t sysnum{0};\n  /** Additional Common network settings */\n  common_network_config_t settings;\n\n  // Used by FTN type nodes.\n  fido_network_config_t fido{};\n  // uuid_t to identify the network locally.\n  core::uuid_t uuid;\n  // A parsed nodelist if available.\n  std::shared_ptr<fido::Nodelist> nodelist;\n\n// private: TODO make Networks a friend class\n  // The current network number, assigned when loaded.\n  // ** This is a transient field.\n  int network_number_{-1};\n};\n\nstd::string to_string(const net::Network& n);\n\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/net/network_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/sdk_helper.h\"\n#include <cstdint>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass NetworkTest : public testing::Test {\npublic:\n  NetworkTest() {\n    EXPECT_TRUE(CreateNetworksDat({ \"one\", \"two\" }));\n    networks_.reset(new Networks(helper.config()));\n    EXPECT_TRUE(networks_->IsInitialized());\n  }\n\n  void SetUp() override {\n  }\n\n  [[nodiscard]] bool CreateNetworksDat(std::vector<std::string> names) const {\n    std::clog << \"Writing NETWORK.DAT to: \" << helper.datadir() << std::endl;\n    File file(FilePath(helper.datadir(), NETWORKS_DAT));\n    file.Open(File::modeBinary|File::modeWriteOnly|File::modeCreateFile, File::shareDenyNone);\n    if (!file.IsOpen()) {\n      return false;\n    }\n  \n    uint16_t sysnum = 1;\n    for (const auto& name : names) {\n      const auto& dir = name;\n      net_networks_rec_disk rec{};\n      to_char_array(rec.name, name);\n      to_char_array(rec.dir, dir);\n      rec.sysnum = sysnum++;\n      file.Write(&rec, sizeof(net_networks_rec_disk));\n    }\n\n    return true;\n  }\n\n  [[nodiscard]] Networks& test_networks() const { return *networks_; }\n\n  SdkHelper helper;\n  unique_ptr<Networks> networks_;\n};\n\nTEST_F(NetworkTest, Networks_At) {\n  const auto& n = test_networks();\n\n  EXPECT_EQ(\"two\", n.at(1).name);\n  EXPECT_EQ(\"two\", n.at(\"two\").name);\n}\n\nTEST_F(NetworkTest, Networks_Bracket) {\n  const auto& n = test_networks();\n\n  EXPECT_EQ(\"two\", n[1].name);\n  EXPECT_EQ(\"two\", n[\"two\"].name);\n}\n\nTEST_F(NetworkTest, Networks_Dir) {\n  const auto& n = test_networks();\n\n  const std::string expected_two_dir = \"two\";\n  EXPECT_EQ(expected_two_dir, n.at(1).dir);\n  EXPECT_EQ(expected_two_dir, n.at(\"two\").dir);\n  EXPECT_EQ(expected_two_dir, n[1].dir);\n  EXPECT_EQ(expected_two_dir, n[\"two\"].dir);\n}\n\nTEST_F(NetworkTest, Networks_NetworkNumber) {\n  const auto& n = test_networks();\n\n  EXPECT_EQ(0, n.network_number(\"one\"));\n  EXPECT_EQ(1, n.network_number(\"two\"));\n  EXPECT_EQ(-1, n.network_number(\"not-here\"));\n}\n\nTEST_F(NetworkTest, Networks_Contains) {\n  const auto& n = test_networks();\n\n  EXPECT_TRUE(n.contains(\"one\"));\n  EXPECT_FALSE(n.contains(\"foo\"));\n}\n"
  },
  {
    "path": "sdk/net/networks.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/networks.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include <stdexcept>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/net/networks_cereal.h\"\n\nnamespace wwiv::sdk {\n\nconst int Networks::npos; // reserve space.\n\nNetworks::Networks(const Config& config)\n    : root_directory_(config.root_directory()), datadir_(config.datadir()) {\n  if (!File::Exists(FilePath(datadir_, NETWORKS_JSON)) &&\n      !File::Exists(FilePath(datadir_, NETWORKS_DAT))) {\n    // Nothing to do.\n    initialized_ = true;\n    return;\n  }\n\n  initialized_ = Load();\n  if (!initialized_) {\n    LOG(ERROR) << \"Failed to read \" << NETWORKS_JSON << \" or \" << NETWORKS_DAT;\n  }\n  initialized_ = true;\n}\n\nconst Network& Networks::at(const std::string& name) const {\n  for (const auto& n : networks_) {\n    if (iequals(name, n.name)) {\n      return n;\n    }\n  }\n  const auto msg = fmt::format(\"Unable to find network named: {}\", name);\n  LOG(ERROR) << msg;\n  throw std::out_of_range(msg);\n}\n\nstatic std::unique_ptr<Network> create_255_network() {\n  auto net = std::make_unique<Network>();\n  net->sysnum = static_cast<uint16_t>(-1);\n  net->type = network_type_t::wwivnet;\n  net->name = \"<deleted network #255>\";\n  net->dir = \"DELETED\";\n  return net;\n}\n\nstatic auto network_255 = create_255_network();\n\nconst Network& Networks::at(size_type num) const {\n  if (networks_.empty()) {\n    return *network_255;\n  }\n  if (num == 255) {\n    // A network num 255 (-1 wrapped at uint8_t boundary) means an\n    // invalid network in WWIV.\n    return *network_255;\n  }\n  if (num >= size_int(networks_)) {\n    DLOG(FATAL) << \"Out of bounds at Networks::at: \" << num << \">= size: \" << size_int(networks_);\n    LOG(ERROR) << \"Out of bounds at Networks::at: \" << num << \">= size: \" << size_int(networks_);\n    // A network num 255 (-1 wrapped at uint8_t boundary) means an\n    // invalid network in WWIV.\n    return *network_255;\n  }\n  return stl::at(networks_, num);\n}\n\nNetwork& Networks::at(size_type num) {\n  if (networks_.empty()) {\n    return *network_255;\n  }\n  if (num == 255) {\n    // A network num 255 (-1 wrapped at uint8_t boundary) means an\n    // invalid network in WWIV.\n    return *network_255;\n  }\n  if (num >= size_int(networks_)) {\n    DLOG(FATAL) << \"Out of bounds at Networks::at: \" << num << \">= size: \" << size_int(networks_);\n    LOG(ERROR) << \"Out of bounds at Networks::at: \" << num << \">= size: \" << size_int(networks_);\n    // A network num 255 (-1 wrapped at uint8_t boundary) means an\n    // invalid network in WWIV.\n    return *network_255;\n  }\n  return stl::at(networks_, num);\n}\n\nNetwork& Networks::at(const std::string& name) {\n  for (auto& n : networks_) {\n    if (iequals(name, n.name)) {\n      return n;\n    }\n  }\n  const auto msg = fmt::format(\"Unable to find network named: {}\", name);\n  LOG(ERROR) << msg;\n  throw std::out_of_range(msg);\n}\n\nstd::optional<const Network> Networks::by_uuid(const wwiv::core::uuid_t& uuid) {\n  if (uuid.empty()) {\n    return std::nullopt;\n  }\n  for (auto& n : networks_) {\n    if (n.uuid == uuid) {\n      return {n};\n    }\n  }\n\n  return std::nullopt;\n}\n\nstd::optional<const Network> Networks::by_uuid(const std::string& uuid_text) {\n  auto o = uuid_t::from_string(uuid_text);\n  if (!o) {\n    return std::nullopt;\n  }\n  return by_uuid(o.value());\n}\n\nNetworks::~Networks() = default;\n\nauto Networks::network_number(const std::string& network_name) const -> size_type {\n  auto i = 0;\n  for (const auto& n : networks_) {\n    if (iequals(network_name, n.name)) {\n      return i;\n    }\n    ++i;\n  }\n  return npos;\n}\n\nbool Networks::contains(const std::string& network_name) const {\n  for (const auto& n : networks_) {\n    if (iequals(network_name, n.name)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstd::size_t Networks::size() const noexcept { return networks_.size(); }\n\nbool Networks::empty() const noexcept { return networks_.empty(); }\n\nbool Networks::insert(int n, Network r) {\n  if (!insert_at(networks_, n, r)) {\n    return false;\n  }\n  SetNetworkNumbers();\n  return true;\n}\n\nbool Networks::erase(int n) {\n  if (!erase_at(networks_, n)) {\n    return false;\n  }\n  SetNetworkNumbers();\n  return true;\n}\n\nbool Networks::Load() {\n  if (LoadFromJSON()) {\n    return true;\n  }\n  return LoadFromDat();\n}\n\nbool Networks::LoadFromJSON() {\n  networks_.clear();\n  JsonFile json(FilePath(datadir_, NETWORKS_JSON), \"networks\", networks_);\n  if (!json.Load()) {\n    return false;\n  }\n  EnsureNetworksHaveUUID();\n  EnsureNetDirAbsolute();\n  SetNetworkNumbers();\n  return true;\n}\n\nbool Networks::LoadFromDat() {\n  DataFile<net_networks_rec_disk> file(FilePath(datadir_, NETWORKS_DAT),\n                                       File::modeBinary | File::modeReadOnly, File::shareDenyNone);\n  if (!file) {\n    return false;\n  }\n\n  std::vector<net_networks_rec_disk> networks_disk;\n\n  if (!file.ReadVector(networks_disk)) {\n    return false;\n  }\n\n  std::random_device rd;\n  uuid_generator uuid_gen(rd);\n  for (const auto& n : networks_disk) {\n    Network r = {};\n    r.type = static_cast<network_type_t>(n.type);\n    r.name = n.name;\n    r.dir = n.dir;\n    r.sysnum = n.sysnum;\n    r.uuid = uuid_gen.generate();\n    networks_.emplace_back(r);\n  }\n  SetNetworkNumbers();\n  return true;\n}\n\nbool Networks::Save() {\n  const auto dat = SaveToDat();\n  const auto json = SaveToJSON();\n\n  return dat && json;\n}\n\nvoid Networks::EnsureNetworksHaveUUID() {\n  std::random_device rd;\n  uuid_generator uuid_gen(rd);\n  auto added{false};\n  for (auto& n : networks_) {\n    if (n.uuid.empty()) {\n      n.uuid = uuid_gen.generate();\n      added = true;\n    }\n  }\n  if (added) {\n    SaveToJSON();\n  }\n}\n\nvoid Networks::EnsureNetDirAbsolute() {\n  if (root_directory_.empty()) {\n    // Nothing to do if we don't know the root\n    return;\n  }\n  for (auto& n : networks_) {\n    if (n.dir.is_relative()) {\n      // make absolute\n      n.dir = FilePath(root_directory_, n.dir);\n    }\n  }\n}\n\n// Set network_number on each network.\nvoid Networks::SetNetworkNumbers() {\n  auto nn = 0;\n  for (auto& n : networks_) {\n    n.network_number_ = nn++;\n  }\n}\n\nbool Networks::SaveToJSON() {\n  JsonFile json(FilePath(datadir_, NETWORKS_JSON), \"networks\", networks_);\n  return json.Save();\n}\n\nbool Networks::SaveToDat() {\n  std::vector<net_networks_rec_disk> disk;\n\n  for (const auto& from : networks_) {\n    net_networks_rec_disk to{};\n    to.type = static_cast<uint8_t>(from.type);\n    to_char_array(to.name, from.name);\n    to_char_array(to.dir, from.dir.string());\n    to.sysnum = from.sysnum;\n    disk.emplace_back(to);\n  }\n\n  DataFile<net_networks_rec_disk> file(FilePath(datadir_, NETWORKS_DAT),\n                                       File::modeBinary | File::modeReadWrite |\n                                           File::modeCreateFile | File::modeTruncate,\n                                       File::shareDenyReadWrite);\n  if (!file) {\n    return false;\n  }\n  return file.WriteVector(disk);\n}\n\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/net/networks.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NETWORKS_H\n#define INCLUDED_SDK_NETWORKS_H\n\n#include <filesystem>\n#include <initializer_list>\n#include <string>\n#include <vector>\n#include \"sdk/config.h\"\n#include \"sdk/net/net.h\"\n\nnamespace wwiv::sdk {\n\nclass Networks final {\npublic:\n  typedef int size_type;\n  typedef net::Network& reference;\n  typedef const net::Network& const_reference;\n  static const size_type npos = -1;\n  explicit Networks(const Config& config);\n  // [[ VisibleForTesting ]]\n  explicit Networks(std::initializer_list<net::Network> l) : networks_(l) {}\n  ~Networks();\n\n  [[nodiscard]] bool IsInitialized() const { return initialized_; }\n  [[nodiscard]] const std::vector<net::Network>& networks() const { return networks_; }\n  [[nodiscard]] const net::Network& at(size_type num) const;\n  [[nodiscard]] const net::Network& at(const std::string& name) const;\n  net::Network& at(size_type num);\n  net::Network& at(const std::string& name);\n  std::optional<const net::Network> by_uuid(const wwiv::core::uuid_t& uuid);\n  std::optional<const net::Network> by_uuid(const std::string& uuid_text);\n\n  net::Network& operator[](size_type num) { return at(num); }\n  net::Network& operator[](const std::string& name) { return at(name); }\n  const net::Network& operator[](int num) const { return at(num); }\n  const net::Network& operator[](const std::string& name) const { return at(name); }\n\n  [[nodiscard]] size_type network_number(const std::string& network_name) const;\n  [[nodiscard]] bool contains(const std::string& network_name) const;\n  [[nodiscard]] std::size_t size() const noexcept;\n  [[nodiscard]] bool empty() const noexcept;\n\n  bool insert(int n, net::Network r);\n  bool erase(int n);\n  bool Load();\n  bool Save();\n\nprivate:\n  void EnsureNetworksHaveUUID();\n  void EnsureNetDirAbsolute();\n  void SetNetworkNumbers();\n  bool LoadFromJSON();\n  bool LoadFromDat();\n  bool SaveToJSON();\n  bool SaveToDat();\n\n  bool initialized_{false};\n  std::filesystem::path root_directory_;\n  std::filesystem::path datadir_;\n  std::vector<net::Network> networks_;\n};\n\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/net/networks_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_NETWORKS_CEREAL_H__\n#define __INCLUDED_SDK_NETWORKS_CEREAL_H__\n\n// We want to override how we store network_type_t to store it as a string, not int.\n// This has to be in the global namespace. \nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(std::filesystem::path, cereal::specialization::non_member_load_save_minimal);\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(network_type_t, cereal::specialization::non_member_load_save_minimal);\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(fido_packet_t, cereal::specialization::non_member_load_save_minimal);\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(fido_bundle_status_t, cereal::specialization::non_member_load_save_minimal);\n\n#include \"core/cereal_utils.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/uuid_cereal.h\"\n#include <filesystem>\n#include <string>\n\n// ICK. See https://github.com/USCiLab/cereal/issues/562\nnamespace std::filesystem {\n\ntemplate<class Archive>\nvoid CEREAL_LOAD_MINIMAL_FUNCTION_NAME(\n    const Archive&, path& out, const std::string& in)\n{\n  out = in;\n}\n\ntemplate<class Archive>\nstd::string CEREAL_SAVE_MINIMAL_FUNCTION_NAME(const Archive&, const path& p)\n{\n  return p.string();\n}\n\n\n}\nnamespace cereal {\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const &, const network_type_t& t) {\n  return to_enum_string<network_type_t>(t, {\"wwivnet\", \"fido\", \"internet\"});\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const &, network_type_t& t, const std::string& v) {\n  t = from_enum_string<network_type_t>(v, {\"wwivnet\", \"fido\", \"internet\"});\n}\n\ntemplate <class Archive> inline\nstd::string save_minimal(Archive const &, const fido_bundle_status_t& t) {\n  const auto c = static_cast<char>(t);\n  return std::string(1, c);\n}\ntemplate <class Archive>\nvoid load_minimal(Archive const &, fido_bundle_status_t& t, const std::string& v) {\n  auto c = 'f';\n  if (!v.empty()) {\n    c = v.front();\n  }\n  t = static_cast<fido_bundle_status_t>(c);\n}\n\ntemplate <class Archive>\nstd::string save_minimal(Archive const &, const fido_packet_t& t) {\n  return to_enum_string<fido_packet_t>(t, {\"unset\", \"type2+\"});\n}\ntemplate <class Archive> inline\nvoid load_minimal(Archive const &, fido_packet_t& t, const std::string& v) {\n  t = from_enum_string<fido_packet_t>(v, {\"unset\", \"type2+\"});\n}\n\ntemplate <class Archive> inline\nstd::string save_minimal(Archive const &, const fido_transport_t& t) {\n  return to_enum_string<fido_transport_t>(t, {\"unset\", \"directory\", \"binkp\"});\n}\ntemplate <class Archive> inline\nvoid load_minimal(Archive const &, fido_transport_t& t, const std::string& v) {\n  t = from_enum_string<fido_transport_t>(v, {\"unset\", \"directory\", \"binkp\"});\n}\n\ntemplate <class Archive> inline\nstd::string save_minimal(Archive const &, const fido_mailer_t& t) {\n  return to_enum_string<fido_mailer_t>(t, {\"unset\", \"flo\", \"attach\"});\n}\ntemplate <class Archive> inline\nvoid load_minimal(Archive const &, fido_mailer_t& t, const std::string& v) {\n  t = from_enum_string<fido_mailer_t>(v, {\"unset\", \"flo\", \"attach\"});\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, fido_packet_config_t& n) {\n  SERIALIZE(n, packet_type);\n  SERIALIZE(n, compression_type);\n  SERIALIZE(n, packet_password);\n  SERIALIZE(n, tic_password);\n  SERIALIZE(n, areafix_password);\n  SERIALIZE(n, max_archive_size);\n  SERIALIZE(n, max_packet_size);\n  SERIALIZE(n, netmail_status);\n}\n\n// fido_node_config_t\ntemplate <class Archive>\nvoid serialize(Archive & ar, fido_node_config_t& n) {\n  SERIALIZE(n, routes);\n  SERIALIZE(n, packet_config);\n  SERIALIZE(n, binkp_config);\n  SERIALIZE(n, callout_config);\n}\n\n// binkp_session_config_t\ntemplate <class Archive>\nvoid serialize(Archive & ar, binkp_session_config_t& n) {\n  SERIALIZE(n, host);\n  SERIALIZE(n, port);\n  SERIALIZE(n, password);\n}\n\n// network_callout_config_t\ntemplate <class Archive> void serialize(Archive& ar, network_callout_config_t& n) {\n  SERIALIZE(n, auto_callouts);\n  SERIALIZE(n, call_every_x_minutes);\n  SERIALIZE(n, min_k);\n}\n\ntemplate <class Archive>\nvoid load(Archive & ar, fido_network_config_t& n) {\n  SERIALIZE(n, fido_address);\n  SERIALIZE(n, nodelist_base);\n  SERIALIZE(n, backbone_filename);\n  SERIALIZE(n, mailer_type);\n  SERIALIZE(n, transport);\n  SERIALIZE(n, inbound_dir);\n  SERIALIZE(n, temp_inbound_dir);\n  SERIALIZE(n, temp_outbound_dir);\n  SERIALIZE(n, outbound_dir);\n  SERIALIZE(n, netmail_dir);\n  SERIALIZE(n, bad_packets_dir);\n  SERIALIZE(n, tic_dir);\n  SERIALIZE(n, unknown_dir);\n  SERIALIZE(n, origin_line);\n  SERIALIZE(n, packet_config);\n  SERIALIZE(n, process_tic);\n  SERIALIZE(n, wwiv_heart_color_codes);\n  SERIALIZE(n, wwiv_pipe_color_codes);\n  SERIALIZE(n, allow_any_pipe_codes);\n  SERIALIZE(n, max_echomail_age_days);\n}\n\ntemplate <class Archive>\nvoid save(Archive & ar, const fido_network_config_t& n) {\n  SERIALIZE(n, fido_address);\n  SERIALIZE(n, nodelist_base);\n  SERIALIZE(n, backbone_filename);\n  SERIALIZE(n, mailer_type);\n  SERIALIZE(n, transport);\n  SERIALIZE(n, inbound_dir);\n  SERIALIZE(n, temp_inbound_dir);\n  SERIALIZE(n, temp_outbound_dir);\n  SERIALIZE(n, outbound_dir);\n  SERIALIZE(n, netmail_dir);\n  SERIALIZE(n, bad_packets_dir);\n  SERIALIZE(n, tic_dir);\n  SERIALIZE(n, unknown_dir);\n  SERIALIZE(n, origin_line);\n  //SERIALIZE(n, packet_config);\n  SERIALIZE(n, process_tic);\n  SERIALIZE(n, wwiv_heart_color_codes);\n  SERIALIZE(n, wwiv_pipe_color_codes);\n  SERIALIZE(n, allow_any_pipe_codes);\n  SERIALIZE(n, max_echomail_age_days);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, common_network_config_t& n) {\n  SERIALIZE(n, auto_add);\n  SERIALIZE(n, auto_add_ini);\n}\n\n// This has to be in the cereal or default to match Network which\n// is in the default namespace.\ntemplate <class Archive> void serialize(Archive& ar, Network& n) {\n  SERIALIZE(n, type);\n  SERIALIZE(n, name);\n  SERIALIZE(n, dir);\n  SERIALIZE(n, sysnum);\n  SERIALIZE(n, settings);\n  // Serialize the Fido config\n  if (n.type == network_type_t::ftn) {\n    SERIALIZE(n, fido);\n  }\n  SERIALIZE(n, uuid);\n}\n\n} // namespace cereal\n\n\n\n#endif  // __INCLUDED_SDK_NETWORKS_CEREAL_H__\n"
  },
  {
    "path": "sdk/net/packets.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2016-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/packets.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/net/subscribers.h\"\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::stl;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::net {\n\nbool send_local_email(const Network& network, net_header_rec& nh, const std::string& text,\n                      const std::string& byname, const std::string& title) {\n  return send_network_email(LOCAL_NET, network, nh, {}, text, byname, title);\n}\n\nbool send_network_email(const std::string& filename, const Network& network, net_header_rec& nh,\n                        const std::vector<uint16_t>& list, const std::string& text,\n                        const std::string& byname, const std::string& title) {\n\n  LOG(INFO) << \"send_network_email: Writing type \" << nh.main_type << \"/\" << nh.minor_type\n            << \" message to NetPacket: \" << filename << \"; title: \" << title;\n\n  ParsedNetPacketText ppt{nh.main_type};\n  ppt.set_date(nh.daten);\n  ppt.set_title(title);\n  ppt.set_sender(byname);\n  ppt.set_text(text);\n\n  return write_wwivnet_packet(FilePath(network.dir, filename), NetPacket(nh, list, ppt));\n}\n\nbool delete_packet(File& f, NetPacket& packet) {\n  if (packet.source() == NetPacketSource::DISK) {\n    f.Seek(packet.offset(), File::Whence::begin);\n    packet.nh.main_type = 0xFFFF; // 65535\n    f.Write(&packet.nh, sizeof(net_header_rec));\n    // restore current position.\n    f.Seek(packet.end_offset(), File::Whence::begin);\n    return true;\n  }\n  return false;\n}\n\nstd::tuple<NetPacket, ReadNetPacketResponse> read_packet(File& f, bool process_de) {\n  NetPacket packet{};\n  // Since this packet is read from disk, mark it as such, and note the current position\n  // as the packet offset.\n  packet.set_source(NetPacketSource::DISK);\n  packet.set_offset(f.current_position());\n  auto num_read = f.Read(&packet.nh, sizeof(net_header_rec));\n  if (num_read == 0) {\n    // at the end of the NetPacket.\n    return std::make_tuple(packet, ReadNetPacketResponse::END_OF_FILE);\n  }\n\n  if (num_read != sizeof(net_header_rec)) {\n    LOG(INFO) << \"error reading header, got short read of size: \" << num_read\n              << \"; expected: \" << sizeof(net_header_rec);\n    return std::make_tuple(packet, ReadNetPacketResponse::ERROR);\n  }\n\n  if (packet.nh.method > 0) {\n    LOG(INFO) << \"compression: de\" << packet.nh.method;\n  }\n\n  if (packet.nh.list_len > 0) {\n    // skip list of addresses.\n    packet.list.resize(packet.nh.list_len);\n    f.Read(&packet.list[0], sizeof(uint16_t) * packet.nh.list_len);\n  }\n\n  if (packet.nh.length != 0) {\n    const auto length = packet.nh.length;\n\n    if (length > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {\n      LOG(INFO) << \"error reading header, got length too big (underflow?): \" << length;\n      return std::make_tuple(packet, ReadNetPacketResponse::ERROR);\n    }\n\n    if (packet.nh.method == 1  && process_de &&\n        packet.nh.length > 146 /* Make sure we have enough for a header */) {\n      // HACK - this should do this in a shim DE 146 is the sizeof EN/DE header for de1.\n      packet.nh.length -= 146;\n      char header[147];\n      f.Read(header, 146);\n      LOG(INFO) << header;\n    }\n    std::string read_text;\n    read_text.resize(length);\n    num_read = f.Read(&read_text[0], packet.nh.length);\n    read_text.resize(num_read);\n    packet.set_text(std::move(read_text));\n  }\n  packet.set_end_offset(f.current_position());\n  return std::make_tuple(packet, ReadNetPacketResponse::OK);\n}\n\nbool write_deadnet_packet(const std::filesystem::path& dir, NetPacket& packet) {\n  const auto path = dir / DEAD_NET;\n\n  packet.nh.list_len = 0;\n  packet.list.clear();\n\n  return write_wwivnet_packet(path, packet);\n}\n\nbool write_wwivnet_packet(const std::filesystem::path& path, const NetPacket& p) {\n  VLOG(2) << \"write_wwivnet_packet: \" << path.string();\n  LOG(INFO) << \"write_wwivnet_packet: Writing type \" << p.nh.main_type << \"/\" << p.nh.minor_type\n            << \" message to NetPacket: \" << path.string();\n  if (p.nh.length != p.text().size()) {\n    LOG(ERROR) << \"Error while writing NetPacket: \" << path.string();\n    LOG(ERROR) << \"Mismatched text and p.nh.length.  text =\" << p.text().size()\n               << \" nh.length = \" << p.nh.length;\n    return false;\n  }\n  File file(path);\n  if (!file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    LOG(ERROR) << \"Error while writing NetPacket: \" << path.string() << \"Unable to open file.\";\n    return false;\n  }\n  file.Seek(0L, File::Whence::end);\n  const auto num = file.Write(&p.nh, sizeof(net_header_rec));\n  if (num != sizeof(net_header_rec)) {\n    // Let's fail now since we didn't write this right.\n    LOG(ERROR) << \"Error while writing NetPacket: \" << path.string() << \" num written (\" << num\n               << \") != net_header_rec size.\";\n    return false;\n  }\n  if (p.nh.list_len != p.list.size()) {\n    LOG(WARNING) << \"p.nh.list_len [\" << p.nh.list_len << \"] != p.list.size() [\" << p.list.size()\n                 << \"]\";\n  }\n  VLOG(4) << \"p.nh.list_len: \" << p.nh.list_len;\n  if (p.nh.list_len) {\n    file.Write(&p.list[0], sizeof(uint16_t) * (p.nh.list_len));\n  }\n  file.Write(p.text());\n  file.Close();\n  return true;\n}\n\nstatic std::string NetInfoFileName(uint16_t type) {\n  switch (type) {\n  case net_info_bbslist:\n    return BBSLIST_NET;\n  case net_info_connect:\n    return CONNECT_NET;\n  case net_info_sub_lst:\n    return SUBS_LST;\n  case net_info_wwivnews:\n  case net_info_more_wwivnews:\n    return \"wwivnews.net\";\n  case net_info_categ_net:\n    return CATEG_NET;\n  case net_info_network_lst:\n    return \"networks.lst\";\n  case net_info_file:\n    return \"\";\n  case net_info_binkp:\n    return BINKP_NET;\n  default:\n    return {};\n  }\n}\n\nNetInfoFileInfo GetNetInfoFileInfo(NetPacket& p) {\n  NetInfoFileInfo info{};\n  if (p.nh.main_type != main_type_net_info && p.nh.minor_type != net_info_file) {\n    // Everything  here should be a main_type_net_info or net_info_file\n    LOG(ERROR) << \"GetNetInfoFileInfo can't handle type: \" << main_type_name(p.nh.main_type) << \" (\"\n               << p.nh.main_type << \")\";\n    info.valid = false;\n    return info;\n  }\n\n  if (p.nh.minor_type != net_info_file) {\n    // Handle the file types we know about using minor_type\n    info.filename = NetInfoFileName(p.nh.minor_type);\n    info.data = p.text();\n    info.valid = true;\n    info.overwrite = true;\n    return info;\n  }\n  auto text = p.text();\n  if (text.size() < 4) {\n    return info;\n  }\n  const uint16_t flags = (text.at(1) << 8) | text.at(0);\n  VLOG(2) << \"flags: \" << flags;\n  const char* fntemp = &text[2];\n  std::string fn(fntemp);\n  if (fn.empty() || fn.size() > 8) {\n    // still BAD.\n    LOG(ERROR) << \"filename length not right; must be at [0,8]; was: \" << fn.size();\n    return info;\n  }\n  VLOG(2) << \"fn: '\" << fn << \"'; \"\n          << \"len: \" << fn.size();\n  const auto pos = fn.size() + sizeof(uint16_t) + 1;\n  if (text.size() < pos) {\n    // still bad\n    LOG(ERROR) << \"text length too short; must be at least: \" << pos;\n    return info;\n  }\n  info.data = text.substr(pos);\n  // Since Windows is case sensitive, this is fine.  Since we want lower\n  // case filenames on Linux, this is also fine.\n  StringLowerCase(&fn);\n  const auto zip = (flags & 0x02) != 0;\n  if (zip) {\n    info.filename = StrCat(fn, \".zip\");\n  } else {\n    info.filename = StrCat(fn, \".net\");\n  }\n  info.overwrite = (flags & 1) != 0;\n  info.valid = true;\n  return info;\n}\n\nstatic bool need_to_update_routing(uint16_t main_type) {\n  switch (main_type) {\n  case main_type_email:\n  case main_type_post:\n  case main_type_pre_post:\n  case main_type_email_name:\n  case main_type_file:\n  case main_type_new_post:\n    return true;\n  default:\n    return false;\n  }\n}\n\nstatic int number_of_header_lines(uint16_t main_type) {\n  // either 3 or 4.\n  switch (main_type) {\n  case main_type_email:\n  case main_type_post:\n  case main_type_pre_post:\n    return 3;\n  case main_type_email_name:\n  case main_type_file:\n  case main_type_new_post:\n    return 4;\n  default:\n    return 0;\n  }\n}\n\nNetPacket::NetPacket(const net_header_rec& h, std::vector<uint16_t> l, std::string t)\n    : nh(h), list(std::move(l)), text_(std::move(t)) {\n  if (nh.list_len != list.size()) {\n    LOG(ERROR) << \"ERROR: Malformed NetPacket: list_len [\" << nh.list_len << \"] != list.size() [\"\n               << list.size() << \"]\";\n  }\n  if (!list.empty() && nh.tosys != 0) {\n    LOG(ERROR) << \"ERROR: Malformed NetPacket: list is not empty and nh.tosys != 0\";\n  }\n  update_header();\n}\n\nNetPacket::NetPacket(const net_header_rec& h, const std::vector<uint16_t>& l, const ParsedNetPacketText& t)\n    : NetPacket(h, l, ParsedNetPacketText::ToPacketText(t)) {}\n\nNetPacket::NetPacket() = default;\n\nbool NetPacket::UpdateRouting(const Network& net) {\n  if (!need_to_update_routing(nh.main_type)) {\n    return false;\n  }\n\n  std::ostringstream ss;\n  ss << \"\\004\"\n     << \"0R \" << wwiv_network_compatible_version() << \" - \" << date() << \" \" << times() << \" \"\n     << net.name << \" ->\" << net.sysnum << \"\\r\\n\";\n\n  const auto routing_information = ss.str();\n\n  if (nh.length + routing_information.size() >= (32 * 1024)) {\n    LOG(INFO) << \"Can't updating routing information, already have 32k of message.\";\n    return false;\n  }\n  nh.length += size_uint32(routing_information);\n\n  // Need to skip over either 3 or 4 lines 1st depending on the NetPacket type.\n  const auto lines = number_of_header_lines(nh.main_type);\n  auto iter = text_.begin();\n  for (auto i = 0; i < lines; i++) {\n    // Skip over this line\n    [[maybe_unused]] auto _ = get_message_field(text_, iter, {'\\0', '\\r', '\\n'}, 80);\n  }\n\n  const auto pos = std::distance(text_.begin(), iter);\n  text_.insert(pos, routing_information);\n  return true;\n}\n\nvoid NetPacket::set_text(const std::string& text) {\n  text_ = text;\n  update_header();\n}\n\nvoid NetPacket::set_text(std::string&& text) {\n  text_ = std::move(text);\n  update_header();\n}\n\nvoid NetPacket::update_header() {\n  nh.length = stl::size_uint32(text_);\n  nh.list_len = static_cast<uint16_t>(list.size());\n}\n\nint NetPacket::length() const {\n  return nh.length;\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// NetMailFile\n\nNetMailFile::NetMailFile(const std::filesystem::path& path, bool process_de, bool allow_write)\n    : file_(path), process_de_(process_de) {\n  const int mode = File::modeBinary | ((allow_write) ? File::modeReadWrite : File::modeReadOnly);\n  open_ = file_.Open(mode);\n  if (!open_) {\n    LOG(ERROR) << \"Unable to open file: \" << path.string() << \"; error: \" << file_.last_error();\n  }\n}\n\n\nNetMailFile::~NetMailFile() { Close(); }\n\nvoid NetMailFile::Close() noexcept {\n  if (open_) {\n    file_.Close();\n    open_ = false;\n  }\n}\n\n\nstd::tuple<NetPacket, ReadNetPacketResponse> NetMailFile::Read() {\n  auto t = read_packet(file_, process_de_);\n  // Update the the last response.\n  last_read_response_ = std::get<1>(t);\n  return t;\n}\n\n\nNetMailFile::iterator NetMailFile::begin() {\n  file_.Seek(0, File::Whence::begin);\n  return iterator(*this); \n}\n\nNetMailFile::iterator::iterator(NetMailFile& f)\n    : NetMailFile::iterator::iterator(f, ReadNetPacketResponse::NOT_OPENED) {}\n\nNetMailFile::iterator::iterator(NetMailFile& f, ReadNetPacketResponse response)\n    : f_(f), response_(response) {\n  if (response == ReadNetPacketResponse::NOT_OPENED && f_.file_.current_position() == 0) {\n    // start of file that is not yet opened (or unknown).\n    std::tie(packet_, response_) = f_.Read();\n  }\n}\n\n\nuint16_t get_forsys(const wwiv::sdk::BbsListNet& b, uint16_t node) {\n  VLOG(2) << \"get_forsys (forward to systen number) for node: \" << node;\n\n  if (node == 0) {\n    VLOG(2) << \"get_forsys: zero node. \";\n    return 0;\n  }\n\n  auto n = b.node_config_for(node);\n  if (!n) {\n    VLOG(2) << \"get_forsys: no route to node: \" << node;\n    return WWIVNET_NO_NODE;\n  }\n  if (n->forsys == WWIVNET_NO_NODE) {\n    VLOG(2) << \"get_forsys: no route to node: \" << node;\n    return WWIVNET_NO_NODE;\n  }\n  VLOG(2) << \"get_forsys: route to node: \" << node << \"; is through node: \" << n->forsys;\n  return n->forsys;\n}\n\n// static\nstd::filesystem::path NetPacket::wwivnet_packet_path(const Network& net, uint16_t node) {\n  if (node == net.sysnum || node == 0) {\n    // Messages to us to into local.net.\n    return FilePath(net.dir, LOCAL_NET);\n  }\n  if (node == WWIVNET_NO_NODE) {\n    return FilePath(net.dir, DEAD_NET);\n  }\n  return FilePath(net.dir, fmt::format(\"s{}.net\", node));\n}\n\nParsedNetPacketText::ParsedNetPacketText(uint16_t typ) : main_type_(typ) {}\n\nvoid ParsedNetPacketText::set_date(daten_t d) { date_ = daten_to_wwivnet_time(d); }\nvoid ParsedNetPacketText::set_date(const std::string& d) { date_ = d; }\nvoid ParsedNetPacketText::set_subtype(const std::string& s) { subtype_or_email_to_ = s; }\nvoid ParsedNetPacketText::set_to(const std::string& s) { subtype_or_email_to_ = s; }\nvoid ParsedNetPacketText::set_title(const std::string& t) { title_ = t; }\nvoid ParsedNetPacketText::set_sender(const std::string& s) { sender_ = s; }\nvoid ParsedNetPacketText::set_text(const std::string& t) { text_ = t; }\nvoid ParsedNetPacketText::set_main_type(uint16_t t) { main_type_ = t; }\nuint16_t ParsedNetPacketText::main_type() const noexcept { return main_type_; }\n\nconst std::string& ParsedNetPacketText::subtype() const noexcept { return subtype_or_email_to_; }\nconst std::string& ParsedNetPacketText::subtype_or_email_to() const noexcept {\n  return subtype_or_email_to_;\n}\nconst std::string& ParsedNetPacketText::to() const noexcept { return subtype_or_email_to_; }\nconst std::string& ParsedNetPacketText::title() const noexcept { return title_; }\nconst std::string& ParsedNetPacketText::sender() const noexcept { return sender_; }\nconst std::string& ParsedNetPacketText::date() const noexcept { return date_; }\nconst std::string& ParsedNetPacketText::text() const noexcept { return text_; }\n\n// static\nParsedNetPacketText ParsedNetPacketText::FromText(uint16_t typ, const std::string& raw) {\n  auto iter = std::begin(raw);\n  ParsedNetPacketText p{typ};\n  p.subtype_or_email_to_ = get_message_field(raw, iter, {'\\0', '\\r', '\\n'}, 80);\n  p.title_ = get_message_field(raw, iter, {'\\0', '\\r', '\\n'}, 80);\n  p.sender_ = get_message_field(raw, iter, {'\\0', '\\r', '\\n'}, 80);\n  p.date_ = get_message_field(raw, iter, {'\\0', '\\r', '\\n'}, 80);\n\n  // This is the message body including any control lines (^D0 or ^A)\n  // that are part of it.\n  p.text_ = std::string(iter, std::end(raw));\n  return p;\n}\n\n// static\nParsedNetPacketText ParsedNetPacketText::FromNetPacket(const NetPacket& p) {\n  return FromText(p.nh.main_type, p.text());\n}\n\n// static\nstd::string ParsedNetPacketText::ToPacketText(const ParsedNetPacketText& ppt) {\n  std::string text;\n  if (ppt.main_type() == main_type_new_post || ppt.main_type() == main_type_email_name) {\n    // These types put the subtype or to address 1st\n    text.append(ppt.subtype_or_email_to());\n    text.push_back(0);\n  }\n  text.append(ppt.title());\n  text.push_back(0);\n  const std::string crlf{\"\\r\\n\"};\n  text.append(ppt.sender()).append(crlf);\n  text.append(ppt.date()).append(crlf);\n  text.append(ppt.text());\n  return text;\n}\n\nvoid rename_pend(const std::filesystem::path& directory, const std::string& filename, char network_app_id) {\n  const auto pend_filename(FilePath(directory, filename));\n  if (!File::Exists(pend_filename)) {\n    LOG(INFO) << \" pending file does not exist: \" << pend_filename;\n    return;\n  }\n  const auto num = filename.substr(1);\n  const char prefix = (to_number<int>(num)) ? '1' : '0';\n\n  for (int i = 0; i < 1000; i++) {\n    const auto new_basename = fmt::format(\"p{}-{}-{}.net\", prefix, network_app_id, i);\n    const auto new_filename = FilePath(directory, new_basename);\n    if (File::Rename(pend_filename, new_filename)) {\n      LOG(INFO) << \"renamed file: '\" << pend_filename << \"' to: '\" << new_filename << \"'\";\n      return;\n    }\n  }\n  LOG(ERROR) << \"all attempts failed to rename_wwivnet_pend\";\n}\n\nstd::string create_pend(const std::filesystem::path& directory, bool local, char network_app_id) {\n  const uint8_t prefix = (local) ? 0 : 1;\n  for (auto i = 0; i < 1000; i++) {\n    auto filename = fmt::format(\"p{}-{}-{}.net\", prefix, network_app_id, i);\n    const auto pend_fn = FilePath(directory, filename);\n    if (File::Exists(pend_fn)) {\n      continue;\n    }\n    File f(pend_fn);\n    if (f.Open(File::modeCreateFile | File::modeReadWrite | File::modeExclusive)) {\n      LOG(INFO) << \"Created pending file: \" << filename;\n      return filename;\n    }\n  }\n  LOG(ERROR) << \"all attempts failed to create_pend\";\n  return \"\";\n}\n\nstd::string main_type_name(uint16_t typ) {\n  switch (typ) {\n  case main_type_net_info:\n    return \"main_type_net_info\";\n  case main_type_email:\n    return \"main_type_email\";\n  case main_type_post:\n    return \"main_type_post\";\n  case main_type_file:\n    return \"main_type_file\";\n  case main_type_pre_post:\n    return \"main_type_pre_post\";\n  case main_type_external:\n    return \"main_type_external\";\n  case main_type_email_name:\n    return \"main_type_email_name\";\n  case main_type_net_edit:\n    return \"main_type_net_edit\";\n  case main_type_sub_list:\n    return \"main_type_sub_list\";\n  case main_type_extra_data:\n    return \"main_type_extra_data\";\n  case main_type_group_bbslist:\n    return \"main_type_group_bbslist\";\n  case main_type_group_connect:\n    return \"main_type_group_connect\";\n  case main_type_group_binkp:\n    return \"main_type_group_binkp\";\n  case main_type_group_info:\n    return \"main_type_group_info\";\n  case main_type_ssm:\n    return \"main_type_ssm\";\n  case main_type_sub_add_req:\n    return \"main_type_sub_add_req\";\n  case main_type_sub_drop_req:\n    return \"main_type_sub_drop_req\";\n  case main_type_sub_add_resp:\n    return \"main_type_sub_add_resp\";\n  case main_type_sub_drop_resp:\n    return \"main_type_sub_drop_resp\";\n  case main_type_sub_list_info:\n    return \"main_type_sub_list_info\";\n  case main_type_new_post:\n    return \"main_type_new_post\";\n  case main_type_new_external:\n    return \"main_type_new_external\";\n  case main_type_game_pack:\n    return \"main_type_game_pack\";\n  default:\n    return fmt::format(\"UNKNOWN type #{}\", typ);\n  }\n}\n\nstd::string net_info_minor_type_name(uint16_t typ) {\n  switch (typ) {\n  case net_info_general_message:\n    return \"net_info_general_message\";\n  case net_info_bbslist:\n    return \"net_info_bbslist\";\n  case net_info_connect:\n    return \"net_info_connect\";\n  case net_info_sub_lst:\n    return \"net_info_sub_lst\";\n  case net_info_wwivnews:\n    return \"net_info_wwivnews\";\n  case net_info_fbackhdr:\n    return \"net_info_fbackhdr\";\n  case net_info_more_wwivnews:\n    return \"net_info_more_wwivnews\";\n  case net_info_categ_net:\n    return \"net_info_categ_net\";\n  case net_info_network_lst:\n    return \"net_info_network_lst\";\n  case net_info_file:\n    return \"net_info_file\";\n  case net_info_binkp:\n    return \"net_info_binkp\";\n  default:\n    return fmt::format(\"UNKNOWN type #{}\", typ);\n  }\n}\n\nstd::string get_subtype_from_packet_text(const std::string& text) {\n  auto iter = text.begin();\n  return get_message_field(text, iter, {'\\0', '\\r', '\\n'}, 80);\n}\n\n/** Creates an outbound NetPacket to be sent */\nNetPacket create_packet_from_wwiv_message(const wwiv::sdk::msgapi::Message& m,\n                                       const std::string& subtype, std::set<uint16_t> receipients) {\n\n  std::vector<uint16_t> list;\n  net_header_rec nh{};\n  const auto& h = m.header();\n  nh.daten = h.daten();\n  nh.fromsys = h.from_system();\n  nh.fromuser = h.from_usernum();\n  nh.list_len = 0;\n  nh.tosys = 0;\n  if (receipients.size() == 1) {\n    nh.tosys = *receipients.begin();\n  } else {\n    nh.list_len = static_cast<uint16_t>(receipients.size());\n    for (auto r : receipients) {\n      list.push_back(r);\n    }\n  }\n\n  nh.main_type = main_type_new_post;\n  nh.method = 0;\n  nh.minor_type = 0;\n  nh.touser = 0;\n\n  // TODO(rushfan): Use ParsedNetPacketText here?\n  // text is subtype<0>title<0>sender<CRLF>date<crlf>body\n  auto text = subtype;\n  text.push_back(0);\n  text.append(h.title());\n  text.push_back(0);\n  text.append(h.from());\n  text.append(\"\\r\\n\");\n  text.append(daten_to_wwivnet_time(nh.daten));\n  text.append(\"\\r\\n\");\n  text.append(m.text().string());\n\n  nh.length = stl::size_uint32(text);\n\n  NetPacket p(nh, list, text);\n  return p;\n}\n\nstatic std::string change_subtype_to(const std::string& org_text, const std::string& new_subtype) {\n  auto iter = org_text.begin();\n  auto subtype = get_message_field(org_text, iter, {'\\0', '\\r', '\\n'}, 80);\n  auto result = new_subtype;\n  result.push_back(0); // Add NULL\n  result += std::string(iter, std::end(org_text));\n  return result;\n}\n\nbool write_wwivnet_packet_or_log(const Network& net, char network_app_id,\n                                 const NetPacket& p) {\n  const auto fn = create_pend(net.dir, false, network_app_id);\n  if (!write_wwivnet_packet(FilePath(net.dir, fn), p)) {\n    LOG(ERROR) << \"Error writing NetPacket: \" << net.dir << \" \" << fn;\n    return false;\n  }\n  VLOG(1) << \"Wrote NetPacket: \" << fn;\n  return true;\n}\n\n/**\n * Sends the post out via WWIVnet or other networks to the other parties if needed.\n *\n * N.B. If this post originates on this system, use -1 for the original_net_num.\n */\nbool send_post_to_subscribers(const std::vector<Network>& nets, int original_net_num,\n                              const std::string& original_subtype, const subboard_t& sub,\n                              NetPacket& template_packet, const std::set<uint16_t>& subscribers_to_skip,\n                              const subscribers_send_to_t& send_to) {\n  VLOG(1) << \"DEBUG: send_post_to_subscribers; original subtype: \" << original_subtype;\n\n  // TODO(rushfan): Replace '2' with a network_app_id passed in\n  const auto network_app_id = '2';\n  for (const auto& subnet : sub.nets) {\n    auto h = template_packet.nh;\n    VLOG(1) << \"DEBUG: Current network subtype: \" << subnet.stype;\n    VLOG(1) << \"DEBUG: Current network is: \" << nets[subnet.net_num].name;\n    // if subnet.host == 0, we are the host.\n    // if subnet.net_num != context.network_number then we are\n    // gating the sub to another network.\n    auto are_we_hosting = subnet.host == 0;\n    auto are_we_gating = subnet.net_num != original_net_num;\n    const auto& current_net = nets[subnet.net_num];\n    VLOG(1) << \"DEBUG: are_we_hosting: \" << std::boolalpha << are_we_hosting;\n    VLOG(1) << \"DEBUG: are_we_gating:  \" << std::boolalpha << are_we_gating;\n\n    if (!are_we_hosting && !are_we_gating &&\n        send_to == subscribers_send_to_t::hosted_and_gated_only) {\n      // Nothing to do here, so move on to the next subnet in the list\n      VLOG(2) << \"!hosting and !gating on: \" << current_net.name;\n      continue;\n    }\n    if (are_we_gating) {\n      // update fromsys\n      h.fromsys = current_net.sysnum;\n      h.fromuser = 0;\n    }\n    // This is what the BBS does. Do this in all cases in send_net_post\n    if (!h.fromsys) {\n      h.fromsys = current_net.sysnum;\n    }\n    // If the subtype has changed, then change the subtype in the\n    // NetPacket text.\n    const auto text = subnet.stype == original_subtype\n                        ? template_packet.text()\n                        : change_subtype_to(template_packet.text(), subnet.stype);\n    if (subnet.stype != original_subtype) {\n      // we also have to update the nh.length to reflect this change.\n      // TODO(rushfan): Really need higher level interface to manipulating\n      // WWIVnet NetPackets...\n      h.length -= stl::size_uint32(original_subtype);\n      h.length += stl::size_uint32(subnet.stype);\n    }\n    if (current_net.type == network_type_t::ftn) {\n      h.tosys = FTN_FAKE_OUTBOUND_NODE;\n      VLOG(1) << \"current network is FTN\";\n      h.list_len = 0;\n      write_wwivnet_packet_or_log(current_net, network_app_id, NetPacket(h, {}, text));\n    } else if (current_net.type == network_type_t::wwivnet) {\n      if (subnet.host == 0) {\n        // We are the host.\n        auto subscribers = ReadSubcriberFile(FilePath(current_net.dir, StrCat(\"n\", subnet.stype, \".net\")));\n        // Remove the original sender from the set of systems that we will resend this to.\n        subscribers.erase(template_packet.nh.fromsys);\n        for (const auto& skip : subscribers_to_skip) {\n          // Skip the subscribers to skip too.\n          subscribers.erase(skip);\n        }\n        VLOG(1) << \"Removing subscriber (sender): \" << template_packet.nh.fromsys;\n        VLOG(1) << \"Read subscribers #: \" << subscribers.size();\n        VLOG(1) << \"Creating wwivnet NetPacket to: \";\n        for (const auto x : subscribers) {\n          VLOG(1) << \"        @\" << x;\n        }\n\n        if (subscribers.empty()) {\n          VLOG(1) << \"No subscribers left, skipping sending this NetPacket\";\n        }\n        h.list_len = static_cast<uint16_t>(subscribers.size());\n        h.tosys = 0;\n        write_wwivnet_packet_or_log(\n            current_net, network_app_id,\n            NetPacket(h, std::vector<uint16_t>(subscribers.begin(), subscribers.end()), text));\n      } else {\n        // We are not the host.  Send message to host.\n        h.tosys = subnet.host;\n        h.list_len = 0;\n        write_wwivnet_packet_or_log(current_net, network_app_id, NetPacket(h, {}, text));\n      }\n    }\n  }\n  VLOG(1) << \"DEBUG: send_post_to_subscribers exiting with true\";\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/net/packets.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*           Copyright (C)2016-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_NET_PACKETS_H\n#define INCLUDED_SDK_NET_PACKETS_H\n\n#include \"core/file.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/msgapi/message.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <set>\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\nstruct subboard_t;\n}\n\nnamespace wwiv::sdk::net {\n\n#ifdef ERROR\n#undef ERROR\n#endif\n\n// Response from reading a packet from disk. Used by the Iterator from NetMailFile\nenum class ReadNetPacketResponse { NOT_OPENED, OK, ERROR, END_OF_FILE };\n\n// Souce of the NetPacket, either on disk or memory.  New packets will be from memory and ones read\n// from disk, will or course be from disk.\nenum class NetPacketSource { DISK, MEMORY };\n\n// fwd\nclass ParsedNetPacketText;\n\nclass NetPacket final {\npublic:\n  NetPacket(const net_header_rec& h, std::vector<uint16_t> l, std::string t);\n  NetPacket(const net_header_rec& h, const std::vector<uint16_t>& l, const ParsedNetPacketText& t);\n\n  NetPacket();\n  ~NetPacket() = default;\n\n  bool UpdateRouting(const Network& net);\n  static std::filesystem::path wwivnet_packet_path(const Network& net, uint16_t node);\n\n  [[nodiscard]] const std::string& text() const noexcept { return text_; }\n  void set_text(const std::string& text);\n  void set_text(std::string&& text);\n\n  // Gets the source of this packet, either disk or memory\n  NetPacketSource source() const { return source_; }\n  // Sets the source of this packet, either disk or memory\n  void set_source(NetPacketSource s) { source_ = s; }\n\n  // Offset for the start of the packet\n  wwiv::core::File::size_type offset() const { return offset_; }\n  // Sets the offset for the start of the packet\n  void set_offset(wwiv::core::File::size_type o) { offset_ = o; }\n\n  // Offset for the end of the packet\n  wwiv::core::File::size_type end_offset() const { return end_offset_; }\n  // Sets the offset for the start of the packet\n  void set_end_offset(wwiv::core::File::size_type o) { end_offset_ = o; }\n\n  // Updates the lengths in the header for list and text.\n  void update_header();\n  int length() const;\n\n  net_header_rec nh{};\n  std::vector<uint16_t> list;\n\nprivate:\n  std::string text_;\n  // Source of this packet (Disk, memory, or unknown)\n  NetPacketSource source_{NetPacketSource::MEMORY};\n\n  // Offset of this packet if it was loaded from disk, and -1 otherwise.\n  wwiv::core::File::size_type offset_{-1};\n  // Offset of the end of this packet if it was loaded from disk, and -1 otherwise.\n  wwiv::core::File::size_type end_offset_{-1};\n};\n\n// Alpha subtypes are seven characters -- the first must be a letter, but the rest can be any\n// character allowed in a DOS filename.This main_type covers both subscriber - to - host and\n// host - to - subscriber messages. Minor type is always zero(since it's ignored), and the\n// subtype appears as the first part of the message text, followed by a NUL.Thus, the message\n// header info at the beginning of the message text is in the format for new_post is:\n// SUBTYPE<nul>TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n//\n// The format for email_name is:\n// TO_NAME<nul>TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n// \n// The format for email (not by name) and post (not new post) is:\n// TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n//\n// Also remember that inside of the type-2 message text, the 1st 2 lines\n// are sender and date string, so once placed in type-2 message the\n// format is:\n// SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n\n\n/**\n * Represents a parsed NetPacket text for main types: email, email_name, and new_post.\n * \n * That means the text portion here just includes the message body and not the \n * WWIV message fields encoded into the first few lines of message text that\n * exists both in message base format as well as on the network.\n */\nclass ParsedNetPacketText {\npublic:\n  ParsedNetPacketText(uint16_t typ);\n  void set_date(daten_t d);\n  void set_date(const std::string& d);\n  void set_subtype(const std::string& s);\n  void set_to(const std::string& s);\n  void set_title(const std::string& t);\n  void set_sender(const std::string& s);\n  void set_text(const std::string& t);\n  void set_main_type(uint16_t t);\n  [[nodiscard]] uint16_t main_type() const noexcept;\n  [[nodiscard]] const std::string& subtype() const noexcept;\n  [[nodiscard]] const std::string& subtype_or_email_to() const noexcept;\n  [[nodiscard]] const std::string& to() const noexcept;\n  [[nodiscard]] const std::string& title() const noexcept;\n  [[nodiscard]] const std::string& sender() const noexcept;\n  [[nodiscard]] const std::string& date() const noexcept;\n  [[nodiscard]] const std::string& text() const noexcept;\n\n  static ParsedNetPacketText FromText(uint16_t typ, const std::string& raw);\n  static ParsedNetPacketText FromNetPacket(const NetPacket& p);\n  static std::string ToPacketText(const ParsedNetPacketText& ppt);\n\nprivate:\n  uint16_t main_type_;\n  std::string subtype_or_email_to_;\n  std::string title_;\n  std::string sender_;\n  std::string date_;\n  std::string text_;\n};\n\n/**\n * Class for reading a WWIVnet mail file, which contians a series of WWIVnet packets.  \n * \n * // Example:\n * NetMailFile packets(path, true);\n * if (!packets) {\n *   return error;\n * }\n * \n * for (auto packet : packets) {\n *   // Process NetPacket.\n *   process_wwivnet_packet(packet);\n * }\n */\nclass NetMailFile {\npublic:\n  \n  class iterator {\n  public:\n    // iterator traits\n    using difference_type = std::ptrdiff_t;\n    using value_type = NetPacket;\n    using pointer = const NetPacket*;\n    using reference = const NetPacket&;\n    using iterator_category = std::forward_iterator_tag;\n\n    // Constructor and bits to make it work.\n    iterator(NetMailFile& f);\n    iterator(NetMailFile& f, ReadNetPacketResponse response);\n    // prefix (++iter)\n    iterator& operator++() {\n      std::tie(packet_, response_) = f_.Read();\n      ++num_;\n      return *this;\n    }\n    // postfix (iter++)\n    iterator operator++(int) {\n      iterator retval = *this;\n      ++(*this);\n      return retval;\n    }\n    [[nodiscard]] bool operator==(iterator other) const noexcept {\n      if (response_ == ReadNetPacketResponse::END_OF_FILE &&\n          other.response_ == ReadNetPacketResponse::END_OF_FILE) {\n        return true;\n      }\n      return (num_ == other.num_ && response_ == other.response_);\n    }\n    bool operator!=(iterator other) const noexcept { return !(*this == other); }\n    [[nodiscard]] NetPacket operator*() { return packet_; }\n\n  private:\n    int num_{0};\n    NetMailFile& f_;\n    NetPacket packet_;\n    ReadNetPacketResponse response_{ReadNetPacketResponse::NOT_OPENED};\n  };\n  \n  NetMailFile(const std::filesystem::path& path, bool process_de, bool allow_write);\n  NetMailFile(const std::filesystem::path& path, bool process_de)\n      : NetMailFile(path, process_de, false) {}\n  virtual ~NetMailFile();\n\n  // Closes the underlying File object.  This is useful if you need to move the file or reopen it\n  // elsewhere.\n  void Close() noexcept;\n\n  [[nodiscard]] iterator begin();\n  [[nodiscard]] iterator end() { return iterator(*this, ReadNetPacketResponse::END_OF_FILE); }\n\n  explicit operator bool() const noexcept { return file_.IsOpen(); }\n  // Response from the last operation reading from the WWIVnet mail file.\n  [[nodiscard]] ReadNetPacketResponse last_read_response() const noexcept { return last_read_response_; }\n\n  // Reads a packet, returning the packet and repsonse.\n  std::tuple<NetPacket, ReadNetPacketResponse> Read();\n\n  // Returns the underlying file.\n  wwiv::core::File& file() { return file_; }\n\nprivate:\n\n  wwiv::core::File file_;\n  bool process_de_{false};\n  bool open_{false};\n  ReadNetPacketResponse last_read_response_{ReadNetPacketResponse::NOT_OPENED};\n};\n\n\n/**\n * Gets the next message field from a NetPacket text c with iterator iter.\n * The next message field will be the next set of characters that do not include\n * anything in the set of stop characters (stop) and less than a total of max.\n */\ntemplate <typename C, typename I>\nstatic std::string get_message_field(const C& c, I& iter, std::set<char> stop, std::size_t max) {\n  // No need to continue if we're already at the end.\n  if (iter == c.end()) {\n    return {};\n  }\n\n  const auto begin = iter;\n  std::size_t count = 0;\n  while (iter != std::end(c) && stop.find(*iter) == std::end(stop) && ++count < max) {\n    ++iter;\n  }\n  std::string result(begin, iter);\n\n  // Stop over stop chars\n  while (iter != std::end(c) && stop.find(*iter) != std::end(stop)) {\n    ++iter;\n  }\n\n  return result;\n}\n\n/**\n * Gets the WWIVnet system number in the path to system node.\n * For example: if you are @1 and you want to send to @3 and\n * you only connect to @2 (and @2 connects to @3) then this will\n * return @2 as the forward system for @3.\n */\nuint16_t get_forsys(const wwiv::sdk::BbsListNet& b, uint16_t node);\n\n// Read the packet from disk, returning the packet and the response status.\nstd::tuple<NetPacket, ReadNetPacketResponse> read_packet(wwiv::core::File& file, bool process_de);\n\n// Update the packet's header to be marked as deleted, rewrite the packet and seek\n// back to the end_offset of the packet.\nbool delete_packet(wwiv::core::File& f, NetPacket& packet);\n\n/**\n * Apends packet to a wwivnet file specified by path.\n */\nbool write_wwivnet_packet(const std::filesystem::path& path, const NetPacket& packet);\n\n/**\n * Apends packet to a wwivnet DEAD.NET file located in the dir directory.\n */\nbool write_deadnet_packet(const std::filesystem::path& dir, NetPacket& packet);\n\nbool send_local_email(const Network& network, net_header_rec& nh, const std::string& text,\n                      const std::string& byname, const std::string& title);\n\nbool send_network_email(const std::string& filename, const Network& network,\n                        net_header_rec& nh, const std::vector<uint16_t>& list, const std::string& text,\n                        const std::string& byname, const std::string& title);\n\nstruct NetInfoFileInfo {\n  std::string filename;\n  std::string data;\n  bool overwrite{false};\n  bool valid{false};\n};\n\nNetInfoFileInfo GetNetInfoFileInfo(NetPacket& p);\n\nvoid rename_pend(const std::filesystem::path& directory, const std::string& filename, char network_app_id);\nstd::string create_pend(const std::filesystem::path& directory, bool local, char network_app_id);\n\nstd::string main_type_name(uint16_t typ);\nstd::string net_info_minor_type_name(uint16_t typ);\n\n/**\n * Gets the subtype from a main_type_new_post message NetPacket's text.\n * Returns empty string on error.\n */\nstd::string get_subtype_from_packet_text(const std::string& text);\n\n/** Creates an outbound NetPacket to be sent */\nNetPacket create_packet_from_wwiv_message(const wwiv::sdk::msgapi::Message& m,\n                                       const std::string& subtype, std::set<uint16_t> receipients);\n\n// Writes out a WWIVnet NetPacket to the pending file and logs success and failure to the \n// system Logger.\nbool write_wwivnet_packet_or_log(const Network& net, char network_app_id, const NetPacket& p);\n\nenum class subscribers_send_to_t { hosted_and_gated_only, all_subscribers };\nbool send_post_to_subscribers(const std::vector<Network>& nets, int original_net_num,\n                              const std::string& original_subtype, const subboard_t& sub,\n                              NetPacket& template_packet, const std::set<uint16_t>& subscribers_to_skip,\n                              const subscribers_send_to_t& send_to);\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/net/packets_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*              Copyright (C)2017-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/datetime.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/sdk_helper.h\"\n#include \"gtest/gtest.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nclass PacketsTest : public testing::Test {\npublic:\n  PacketsTest(){};\n  std::string CreateFakePacketText(const std::string& subtype, const std::string& title,\n                                   const std::string& sender, const std::string& text) {\n    std::string result;\n    result.reserve(500);\n    result.append(subtype);\n    result.push_back(0);\n    result.append(title);\n    result.push_back(0);\n    result.append(sender).append(\"\\r\\n\");\n\n    const auto now = daten_t_now();\n    const auto date = daten_to_wwivnet_time(now);\n    result.append(date).append(\"\\r\\n\");\n    result.append(text);\n    result.push_back(26);\n    result.shrink_to_fit();\n\n    return result;\n  }\n\n  NetPacket CreatePacket(const std::string& subtype, const std::string& title,\n                         const std::string& sender, const std::string& text) {\n    const auto packet_text = CreateFakePacketText(subtype, title, sender, text);\n    const auto now = daten_t_now();\n\n    net_header_rec nh{};\n    nh.daten = now;\n    nh.fromsys = 1;\n    nh.tosys = 2;\n    nh.fromuser = 1;\n    nh.touser = 2;\n    nh.length = packet_text.size();\n    nh.main_type = main_type_new_post;\n    nh.method = 0;\n    nh.list_len = 0;\n    return NetPacket(nh, {}, packet_text);\n  }\n\nprotected:\n  SdkHelper sdk_helper_;\n};\n\nTEST_F(PacketsTest, GetNetInfoFileInfo_Smoke) {\n  std::string text;\n  text.push_back(1);\n  text.push_back(0);\n  text += \"BINKP\";\n  text.push_back(0);\n  text += \"Hello World\";\n  ASSERT_EQ(19, wwiv::stl::ssize(text));\n\n  net_header_rec nh{};\n  nh.daten = daten_t_now();\n  nh.method = 0;\n  nh.main_type = main_type_file;\n  nh.minor_type = net_info_file;\n  NetPacket p(nh, {}, text);\n\n  auto info = GetNetInfoFileInfo(p);\n  ASSERT_TRUE(info.valid);\n  EXPECT_EQ(\"binkp.net\", info.filename);\n  EXPECT_TRUE(info.overwrite);\n  EXPECT_EQ(\"Hello World\", info.data);\n}\n\nTEST_F(PacketsTest, UpdateRouting_Smoke) {\n  const std::string body = \"Hello World\";\n\n  const auto packet_text = CreateFakePacketText(\"MYSUB\", \"This is a title\", \"Sysop #1\", body);\n  const auto now = daten_t_now();\n\n  net_header_rec nh{};\n  nh.daten = now;\n  nh.fromsys = 1;\n  nh.tosys = 2;\n  nh.fromuser = 1;\n  nh.touser = 1;\n  nh.length = packet_text.size();\n  nh.main_type = main_type_new_post;\n  nh.method = 0;\n  nh.list_len = 0;\n  NetPacket packet(nh, {}, packet_text);\n\n  Network net{};\n  net.dir = \"Z:\\\\\";\n  net.name = \"My Network\";\n  net.sysnum = 2;\n  net.type = network_type_t::wwivnet;\n  packet.UpdateRouting(net);\n\n  auto iter = std::begin(packet.text());\n  get_message_field(packet.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n  get_message_field(packet.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n  get_message_field(packet.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n  get_message_field(packet.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n  const auto actual_route_str = get_message_field(packet.text(), iter, {'\\0', '\\r', '\\n'}, 80);\n\n  EXPECT_TRUE(starts_with(actual_route_str, \"\\004\"\n                                            \"0R\"));\n}\n\nTEST_F(PacketsTest, GetMessageField) {\n  char raw[] = {'a', '\\0', 'b', 'c', '\\r', '\\n', 'd'};\n  std::string text(raw, 7);\n  auto iter = text.begin();\n  const auto a = get_message_field(text, iter, {'\\0', '\\r', '\\n'}, 80);\n  EXPECT_STREQ(\"a\", a.c_str());\n  const auto bc = get_message_field(text, iter, {'\\0', '\\r', '\\n'}, 80);\n  EXPECT_STREQ(\"bc\", bc.c_str());\n  const auto remaining = std::string(iter, text.end());\n  EXPECT_STREQ(\"d\", remaining.c_str());\n}\n\nTEST_F(PacketsTest, FromPacketText_FromPacketText_NewPost) {\n  const std::string s(\"a\\000b\\000c\\r\\nd\\r\\ne\", 11);\n  const auto pp = ParsedNetPacketText::FromText(main_type_new_post, s);\n  EXPECT_EQ(pp.subtype(), \"a\");\n  EXPECT_EQ(pp.title(), \"b\");\n  EXPECT_EQ(pp.sender(), \"c\");\n  EXPECT_EQ(pp.date(), \"d\");\n  EXPECT_EQ(pp.text(), \"e\");\n}\n\nTEST_F(PacketsTest, FromPacketText_ToPacketText_Email_NotName) {\n  const std::string expected(\"b\\000c\\r\\nd\\r\\ne\", 9);\n  ParsedNetPacketText ppt{main_type_email};\n  ppt.set_to(\"a\");\n  ppt.set_title(\"b\");\n  ppt.set_sender(\"c\");\n  ppt.set_date(\"d\");\n  ppt.set_text(\"e\");\n\n  const auto actual = ParsedNetPacketText::ToPacketText(ppt);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(PacketsTest, FromPacketText_ToPacketText_EmailName) {\n  const std::string expected(\"a\\000b\\000c\\r\\nd\\r\\ne\", 11);\n  ParsedNetPacketText ppt{main_type_email_name};\n  ppt.set_to(\"a\");\n  ppt.set_title(\"b\");\n  ppt.set_sender(\"c\");\n  ppt.set_date(\"d\");\n  ppt.set_text(\"e\");\n\n  const auto actual = ParsedNetPacketText::ToPacketText(ppt);\n  EXPECT_EQ(expected, actual);\n}\n\nTEST_F(PacketsTest, FromPacketText_Malformed) {\n  const std::string s(\"a\", 1);\n  const auto pp = ParsedNetPacketText::FromText(main_type_new_post, s);\n  EXPECT_EQ(pp.subtype(), \"a\");\n  EXPECT_EQ(pp.title(), \"\");\n  EXPECT_EQ(pp.sender(), \"\");\n  EXPECT_EQ(pp.date(), \"\");\n}\n\nTEST_F(PacketsTest, PacketFileReader_Smoke) {\n  const auto net = sdk_helper_.CreateTestNetwork(wwiv::sdk::net::network_type_t::wwivnet);\n  const auto path = FilePath(net.dir, LOCAL_NET);\n  ASSERT_TRUE(\n      write_wwivnet_packet(path, CreatePacket(\"MYSUB\", \"Title1\", \"Sysop #1\", \"Hello World\")));\n  ASSERT_TRUE(\n      write_wwivnet_packet(path, CreatePacket(\"MYSUB\", \"Title2\", \"Sysop #1\", \"Hello World\")));\n  ASSERT_TRUE(\n      write_wwivnet_packet(path, CreatePacket(\"MYSUB\", \"Title3\", \"Sysop #1\", \"Hello World\")));\n\n  NetMailFile reader(path, false);\n  auto iter = std::begin(reader);\n  auto end = std::end(reader);\n  ASSERT_NE(iter, end);\n  ASSERT_EQ(ParsedNetPacketText::FromNetPacket(*iter++).title(), \"Title1\");\n  ASSERT_NE(iter, end);\n  ASSERT_EQ(ParsedNetPacketText::FromNetPacket(*iter++).title(), \"Title2\");\n  ASSERT_NE(iter, end);\n  ASSERT_EQ(ParsedNetPacketText::FromNetPacket(*iter++).title(), \"Title3\");\n  ASSERT_EQ(iter, end);\n\n  auto iter2 = std::begin(reader);\n  const auto num = std::count_if(iter2, end, [](NetPacket) { return true; });\n  EXPECT_EQ(3, num);\n}\n"
  },
  {
    "path": "sdk/net/subscribers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2016-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/subscribers.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/fido/fido_address.h\"\n#include <map>\n#include <set>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::fido;\n\nnamespace wwiv::sdk {\n\nstd::set<FidoAddress> ReadFidoSubcriberFile(const std::filesystem::path& path) {\n\n  VLOG(1) << \"ReadFidoSubcriberFile: \" << path;\n  TextFile file(path, \"rt\");\n  if (!file.IsOpen()) {\n    TextFile wf(path, \"wt\");\n    return{};\n  }\n\n  std::set<FidoAddress> subscribers;\n  std::string line;\n  while (file.ReadLine(&line)) {\n    StringTrim(&line);\n    if (line.empty()) {\n      continue;\n    }\n    try {\n      subscribers.insert(FidoAddress(line));\n    } catch (const bad_fidonet_address& e) {\n      LOG(ERROR) << \"ReadFidoSubcriberFile: [\" << path.string() << \"] : \" <<  e.what();\n    }\n  }\n  return subscribers;\n}\n\nstd::set<uint16_t> ReadSubcriberFile(const std::filesystem::path& path) {\n  VLOG(1) << \"ReadSubcriberFile: \" << path;\n\n  TextFile file(path, \"rt\");\n  if (!file.IsOpen()) {\n    TextFile wf(path, \"wt\");\n    return {};\n  }\n\n  std::string line;\n  std::set<uint16_t> subscribers;\n  while (file.ReadLine(&line)) {\n    StringTrim(&line);\n    if (auto s = to_number<uint16_t>(line); s > 0) {\n      subscribers.insert(s);\n    }\n  }\n  return subscribers;\n}\n\nbool WriteSubcriberFile(const std::filesystem::path& path, const std::set<uint16_t>& subscribers) {\n  TextFile file(path, \"wt\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n\n  for (const auto s : subscribers) {\n    file.WriteLine(std::to_string(s));\n  }\n  return true;\n}\n\nbool WriteFidoSubcriberFile(const std::filesystem::path& path, const std::set<FidoAddress>& subscribers) {\n  TextFile file(path, \"wt\");\n  if (!file.IsOpen()) {\n    return false;\n  }\n\n  for (const auto& s : subscribers) {\n    file.WriteLine(s.as_string());\n  }\n  return true;\n}\n\n\n}\n\n"
  },
  {
    "path": "sdk/net/subscribers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_SUBSCRIBERS_H\n#define INCLUDED_SDK_SUBSCRIBERS_H\n\n#include \"sdk/fido/fido_address.h\"\n#include <filesystem>\n#include <set>\n\nnamespace wwiv::sdk {\n\nstd::set<fido::FidoAddress> ReadFidoSubcriberFile(const std::filesystem::path& filename);\nstd::set<uint16_t> ReadSubcriberFile(const std::filesystem::path& path);\nbool WriteSubcriberFile(const std::filesystem::path& path, const std::set<uint16_t>& subscribers);\nbool WriteFidoSubcriberFile(const std::filesystem::path& path,\n                            const std::set<fido::FidoAddress>& subscribers);\n\n} // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/phone_numbers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*            Copyright (C)2015-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/phone_numbers.h\"\n\n#include <algorithm>\n#include <string>\n#include <vector>\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nPhoneNumbers::PhoneNumbers(const Config& config) \n    : initialized_(config.IsInitialized()), datadir_(config.datadir()) {\n  if (initialized_) {\n    initialized_ = Load();\n  }\n}\n\nPhoneNumbers::~PhoneNumbers() = default;\n\nbool PhoneNumbers::insert(int user_number, const std::string& phone_number) {\n  if (phone_number.find(\"000-\") != std::string::npos) {\n    return false;\n  }\n  phonerec p{};\n  p.usernum = static_cast<int16_t>(user_number);\n  to_char_array(p.phone, phone_number);\n  phones_.emplace_back(p);\n  \n  return Save();\n}\n\nbool PhoneNumbers::erase(int user_number, const std::string& phone_number) {\n  const auto predicate = [=](const phonerec& p) {\n    return phone_number == p.phone && p.usernum == user_number;\n  };\n  phones_.erase(std::remove_if(std::begin(phones_), std::end(phones_), predicate), std::end(phones_));\n  return Save();\n}\n\nint PhoneNumbers::find(const std::string& phone_number) const {\n  for (const auto& p : phones_) {\n    if (phone_number == p.phone) {\n      // TODO(rushfan): Also need check if the user is not deleted exists.\n      return p.usernum;\n    }\n  }\n  // not found.\n  return 0;\n}\n\nbool PhoneNumbers::Load() {\n  DataFile<phonerec> file(FilePath(datadir_, PHONENUM_DAT),\n                          File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  if (!file) {\n    return false;\n  }\n\n  return file.ReadVector(phones_);\n}\n\nbool PhoneNumbers::Save() {\n  DataFile<phonerec> file(FilePath(datadir_, PHONENUM_DAT),\n                          File::modeReadWrite | File::modeBinary |\n                                                                File::modeCreateFile |\n                                                                File::modeTruncate);\n  if (!file) {\n    return false;\n  }\n  return file.WriteVector(phones_);\n}\n\n\n}\n"
  },
  {
    "path": "sdk/phone_numbers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_PHONE_NUMBERS_H\n#define INCLUDED_SDK_PHONE_NUMBERS_H\n\n#include <filesystem>\n#include <string>\n#include <vector>\n\nstruct phonerec;\n\nnamespace wwiv::sdk {\n\n class Config;\n\nclass PhoneNumbers {\npublic:\n  explicit PhoneNumbers(const Config& config);\n  virtual ~PhoneNumbers();\n\n  bool IsInitialized() const { return initialized_; }\n  bool insert(int user_number, const std::string& phone_number);\n  bool erase(int user_number, const std::string& phone_number);\n  int find(const std::string& phone_number) const;\n\nprivate:\n  bool Load();\n  bool Save();\n\n  bool initialized_;\n  std::filesystem::path datadir_;\n  std::vector<phonerec> phones_;\n};\n\n}\n\n\n#endif  // __INCLUDED_SDK_PHONE_NUMBERS_H__\n"
  },
  {
    "path": "sdk/phone_numbers_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                           WWIV Version 5.x                             */\n/*            Copyright (C)2015-2022, WWIV Software Services              */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/phone_numbers.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/sdk_helper.h\"\n#include <string>\n#include <vector>\n\nusing namespace std;\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass PhoneNumbersTest : public testing::Test {\npublic:\n  bool CreatePhoneNumDat(const Config& config) {\n    File file(FilePath(config.datadir(), PHONENUM_DAT));\n    file.Open(File::modeBinary|File::modeWriteOnly|File::modeCreateFile, File::shareDenyNone);\n    if (!file) {\n      return false;\n    }\n  \n    phonerec rec{};\n    rec.usernum = 1;\n    to_char_array(rec.phone, \"111-111-1111\");\n    file.Write(&rec, sizeof(phonerec));\n\n    rec.usernum = 2;\n    to_char_array(rec.phone, \"222-222-2222\");\n    file.Write(&rec, sizeof(phonerec));\n\n    return true;\n  }\n\n  SdkHelper helper;\n};\n\nTEST_F(PhoneNumbersTest, Find) {\n  const Config config(helper.root_directory());\n  ASSERT_TRUE(config.IsInitialized());\n  ASSERT_TRUE(CreatePhoneNumDat(config));\n\n  const PhoneNumbers phone_numbers(config);\n  ASSERT_TRUE(phone_numbers.IsInitialized());\n  EXPECT_EQ(0, phone_numbers.find(\"455-555-1234\"));\n  EXPECT_EQ(1, phone_numbers.find(\"111-111-1111\"));\n  EXPECT_EQ(2, phone_numbers.find(\"222-222-2222\"));\n  EXPECT_EQ(0, phone_numbers.find(\"333-333-3333\"));  // not found.\n}\n\nTEST_F(PhoneNumbersTest, Insert) {\n  const Config config(helper.root_directory());\n  ASSERT_TRUE(config.IsInitialized());\n  ASSERT_TRUE(CreatePhoneNumDat(config));\n\n  {\n    PhoneNumbers phone_numbers(config);\n    ASSERT_TRUE(phone_numbers.IsInitialized());\n    EXPECT_EQ(2, phone_numbers.find(\"222-222-2222\"));\n    EXPECT_TRUE(phone_numbers.insert(3, \"333-333-3333\"));\n  }\n  const PhoneNumbers phone_numbers(config);\n  EXPECT_EQ(2, phone_numbers.find(\"222-222-2222\")); // still found.\n  EXPECT_EQ(3, phone_numbers.find(\"333-333-3333\")); // still found.\n}\n\nTEST_F(PhoneNumbersTest, Erase) {\n  const Config config(helper.root_directory());\n  ASSERT_TRUE(config.IsInitialized());\n  ASSERT_TRUE(CreatePhoneNumDat(config));\n\n  {\n    PhoneNumbers phone_numbers(config);\n    ASSERT_TRUE(phone_numbers.IsInitialized());\n    EXPECT_EQ(2, phone_numbers.find(\"222-222-2222\"));\n    EXPECT_TRUE(phone_numbers.erase(2, \"222-222-2222\"));\n  }\n  const PhoneNumbers phone_numbers(config);\n  EXPECT_EQ(0, phone_numbers.find(\"222-222-2222\"));  // not found anymore.\n  EXPECT_EQ(1, phone_numbers.find(\"111-111-1111\"));  // still found.\n}\n"
  },
  {
    "path": "sdk/qscan.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/qscan.h\"\n\n#include <stdexcept>\n#include \"core/log.h\"\n\nnamespace wwiv::sdk {\n\nusing namespace wwiv::core;\n\n/** Calculates the qscan_len field based on max_subs and max_dirs */\nsize_t calculate_qscan_length(size_t max_subs, size_t max_dirs) {\n  const auto bits = 8 * sizeof(uint32_t);\n  return sizeof(uint32_t) * (1 + max_subs + ((max_subs + bits - 1) / bits) + ((max_dirs + bits - 1) / bits));\n}\n\nqscan_bitset::qscan_bitset(uint32_t* q, size_t max_size)\n  : q_(q), max_size_(max_size) {}\n\n  // ReSharper disable CppMemberFunctionMayBeConst\n\nvoid qscan_bitset::set(size_t n) {\n  if (n > max_size_) {\n    throw std::out_of_range(\"qscan_bitset::set out of range\");\n  }\n  q_[n / 32] |= (1L << (n % 32));\n}\n\nvoid qscan_bitset::reset(size_t n) {\n  if (n > max_size_) {\n    throw std::out_of_range(\"qscan_bitset::reset out of range\");\n  }\n  q_[n / 32] &= ~(1L << (n % 32));\n}\n\nbool qscan_bitset::test(size_t n) const {\n  if (n > max_size_) {\n    throw std::out_of_range(\"qscan_bitset::test out of range\");\n  }\n  return q_[n / 32] & (1L << (n % 32));\n}\n\nvoid qscan_bitset::flip(size_t n) {\n  if (n > max_size_) {\n    throw std::out_of_range(\"qscan_bitset::flip out of range\");\n  }\n  q_[n / 32] ^= (1L << (n % 32));\n}\n\nsize_t qscan_bitset::size() const noexcept { return max_size_; }\n\n// ReSharper restore CppMemberFunctionMayBeConst\n\n\nRawUserQScan::RawUserQScan(uint32_t* q, int qscan_length, int max_subs, int max_dirs)\n  : qscan_(std::make_unique<uint32_t[]>(qscan_length)),\n    newscan_dir_(qscan_.get() + 1),\n    newscan_sub_(newscan_dir_ + (max_dirs + 31) / 32),\n    lastread_pointer_(newscan_sub_ + (max_subs + 31) / 32),\n    dirs_(newscan_dir_, max_dirs),\n    subs_(newscan_sub_, max_subs) {\n  if (q != nullptr) {\n    memcpy(qscan_.get(), q, qscan_length);\n  } else {\n    VLOG(1) << \"Creating empty QScan Record\";\n    // Create new empty qscan record.\n    memset(qscan_.get(), 0, qscan_length);\n    *qscan_.get() = 999;\n    memset(qscan_.get() + 1, 0xff, ((max_dirs + 31) / 32) * 4);\n    memset(qscan_.get() + 1 + (max_subs + 31) / 32, 0xff, ((max_subs + 31) / 32) * 4);\n  }\n}\n\nRawUserQScan::RawUserQScan(int qscan_length, int max_subs, int max_dirs)\n  : RawUserQScan(nullptr, qscan_length, max_subs, max_dirs) {\n}\n\nUserQScan::UserQScan(\n  const std::string& filename, int user_number, int qscan_length, int max_subs, int max_dirs)\n  : RawUserQScan(qscan_length, max_subs, max_dirs), file_(filename) {\n\n  const auto pos = user_number * qscan_length;\n  open_ = file_.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  if (open_ && (pos + qscan_length <= file_.length())) {\n    // qsc() is already initialized by the RawUserQScan constructor.\n    file_.Seek(pos, File::Whence::begin);\n    file_.Read(qsc(), qscan_length);\n  }\n\n}\n\nUserQScan::~UserQScan() = default;\n\nbool UserQScan::save() {\n  return false;\n}\n\nbool UserQScan::clear() {\n  return false;\n}\n\n}\n"
  },
  {
    "path": "sdk/qscan.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_QSCAN_H__\n#define __INCLUDED_SDK_QSCAN_H__\n\n#include <memory>\n#include \"core/file.h\"\n\nnamespace wwiv {\nnamespace sdk {\n\nsize_t calculate_qscan_length(size_t max_subs, size_t max_dirs);\n\n// ReSharper disable CppMemberFunctionMayBeConst\n\n/**\n * Bitfield style class for handling qscan on/off for subs and dirs.\n */\nclass qscan_bitset {\npublic:\n  qscan_bitset(uint32_t* q, size_t max_size);\n  qscan_bitset() = delete;\n  ~qscan_bitset() = default;\n\n  void set(size_t n);\n\n  void reset(size_t n);\n\n  [[nodiscard]] bool test(size_t n) const;\n\n  void flip(size_t n);\n\n  [[nodiscard]] size_t size() const noexcept;\n\nprivate:\n  uint32_t* q_;\n  size_t max_size_;\n};\n// ReSharper restore CppMemberFunctionMayBeConst\n\n\nclass RawUserQScan {\npublic:\n  RawUserQScan(uint32_t* q, int qscan_length, int max_subs, int max_dirs);\n  RawUserQScan(int qscan_length, int max_subs, int max_dirs);\n  RawUserQScan() = delete;\n  ~RawUserQScan() = default;\n\n  qscan_bitset& dirs() { return dirs_; };\n  qscan_bitset& subs() { return subs_; };\n\n  [[nodiscard]] uint32_t lastread_pointer(int n) const { return lastread_pointer_[n]; }\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  void lastread_pointer(int n, uint32_t val) { lastread_pointer_[n] = val; }\n  [[nodiscard]] uint32_t* qsc() const { return qscan_.get(); }\n\nprivate:\n  std::unique_ptr<uint32_t[]> qscan_;\n  uint32_t* newscan_dir_{};\n  uint32_t* newscan_sub_{};\n  uint32_t* lastread_pointer_{};\n\n  qscan_bitset dirs_;\n  qscan_bitset subs_;\n};\n\n// Experimental SDK class for working with QScan data.\nclass UserQScan : public RawUserQScan {\npublic:\n  UserQScan(const std::string& filename, int user_number, int qscan_length, int max_subs,\n            int max_dirs);\n  UserQScan() = delete;\n  ~UserQScan();\n\n  bool save();\n  bool clear();\n\nprivate:\n  wwiv::core::File file_;\n  bool open_{false};\n\n};\n\n// TODO(rushfan): Implement this\nclass AllUserQScan {\npublic:\n  AllUserQScan(const std::string& /*filename*/, int /*max_users*/) {}\n  void swap_dir(int num);\n  void swap_sub(int num);\n  bool insert(int pos);\n  bool remove(int pos);\n\n};\n\n} // namespace sdk\n} // namespace wwiv\n\n#endif  // __INCLUDED_SDK_QSCAN_H__\n"
  },
  {
    "path": "sdk/qscan_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/qscan.h\"\n#include \"sdk/sdk_helper.h\"\n#include <vector>\n#include \"core/stl.h\"\n\nusing namespace std;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nclass QScanTest : public testing::Test {\npublic:\n  QScanTest() {}\n\n  SdkHelper helper;\n};\n\nTEST_F(QScanTest, Smoke) {\n  const size_t max_subs = 8u;\n  const size_t max_dirs = 10u;\n  uint32_t q[100];\n  memset(q, 0, sizeof(q));\n  *q = 999;\n  RawUserQScan qscan(&q[0], calculate_qscan_length(max_subs, max_dirs), max_subs, max_dirs);\n  ASSERT_EQ(999u, *qscan.qsc());\n  ASSERT_EQ(max_subs, qscan.subs().size());\n  ASSERT_EQ(max_dirs, qscan.dirs().size());\n}\n\nTEST_F(QScanTest, Dirs_Smoke) {\n  const auto max_subs = 8;\n  const auto max_dirs = 10;\n  const auto qscn_len = calculate_qscan_length(max_subs, max_dirs);\n  RawUserQScan qscan(qscn_len, max_subs, max_dirs);\n\n  // Flip off all dirs (forcefully)\n  qscan.qsc()[1] = 0;\n  auto& x = qscan.dirs();\n  ASSERT_FALSE(x.test(1));\n  \n  // Flip a bit on the dirs.\n  x.set(1);\n  x.set(3);\n  ASSERT_TRUE(x.test(1));\n  ASSERT_TRUE(x.test(3));\n\n  ASSERT_EQ(10u, qscan.qsc()[1]);\n  ASSERT_EQ(static_cast<unsigned>(max_dirs), x.size());\n}\n\nTEST_F(QScanTest, Subs_Smoke) {\n  const auto max_subs = 8;\n  const auto max_dirs = 10;\n  const auto qscn_len = calculate_qscan_length(max_subs, max_dirs);\n  RawUserQScan qscan(qscn_len, max_subs, max_dirs);\n\n  // Flip off all subs (forcefully)\n  qscan.qsc()[2] = 0;\n  auto& x = qscan.subs();\n  ASSERT_FALSE(x.test(1));\n\n  // Flip a bit on the dirs.\n  x.set(1);\n  x.set(3);\n  ASSERT_TRUE(x.test(1));\n  ASSERT_TRUE(x.test(3));\n\n  ASSERT_EQ(10u, qscan.qsc()[2]);\n\n  ASSERT_EQ(max_subs, wwiv::stl::ssize(x));\n}\n\nTEST_F(QScanTest, BitSet) {\n  uint32_t data[2] = {};\n  qscan_bitset b(data, 64);\n\n  b.set(32);\n  ASSERT_EQ(1u, data[1]);\n  ASSERT_TRUE(b.test(32));\n  b.reset(32);\n  ASSERT_FALSE(b.test(32));\n  b.flip(32);\n  ASSERT_TRUE(b.test(32));\n}\n"
  },
  {
    "path": "sdk/qwk_config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/qwk_config.h\"\n\n//#include \"bbs/qwk/qwk_reply.h\"\n#include \"config.h\"\n#include \"core/cereal_utils.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n#include <algorithm>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::sdk{\n\ntemplate <class Archive> void serialize(Archive& ar, qwk_bulletin& s) { \n  SERIALIZE(s, name);\n  SERIALIZE(s, path);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, qwk_config& s) { \n  SERIALIZE(s, fu);\n  SERIALIZE(s, timesd);\n  SERIALIZE(s, timesu);\n  SERIALIZE(s, max_msgs);\n  SERIALIZE(s, hello);\n  SERIALIZE(s, news);\n  SERIALIZE(s, bye);\n  SERIALIZE(s, packet_name);\n  SERIALIZE(s, bulletins);\n}\n\nstd::string qwk_system_name(const qwk_config& c, const std::string& system_name) {\n  auto qwkname = !c.packet_name.empty() ? c.packet_name : system_name;\n\n  if (qwkname.length() > 8) {\n    qwkname.resize(8);\n  }\n  std::replace( qwkname.begin(), qwkname.end(), ' ', '-' );\n  std::replace( qwkname.begin(), qwkname.end(), '.', '-' );\n  return ToStringLowerCase(qwkname);\n}\n\n#define BULL_SIZE     81\n#define BNAME_SIZE    13\n\nstatic qwk_config read_qwk_cfg_430(const Config& config) {\n  const auto filename = FilePath(config.datadir(), QWK_CFG);\n  File f(filename);\n\n  if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n    return {};\n  }\n\n  qwk_config_430 o{};\n  if (f.Read(&o, sizeof(qwk_config_430)) != sizeof(qwk_config_430)) {\n    LOG(ERROR) << \"Read failed on: \" << f;\n    return {};\n  }\n\n  auto x = 0;\n  qwk_config c{};\n  while (x < o.amount_blts) {\n    auto pos = sizeof(qwk_config_430) + (x * BULL_SIZE);\n    f.Seek(pos, File::Whence::begin);\n    char b[BULL_SIZE]{};\n    f.Read(&b, BULL_SIZE);\n    c.bulletins.emplace_back(qwk_bulletin{ \"\", b });\n    ++x;\n  }\n\n  x = 0;\n  for (auto& blt : c.bulletins) {\n    const auto pos = static_cast<int>(sizeof(qwk_config_430)) + (size_int(c.bulletins) * BULL_SIZE) + (x * BNAME_SIZE);\n    f.Seek(pos, File::Whence::begin);\n    char b[BULL_SIZE]{};\n    f.Read(&b, BULL_SIZE);\n    blt.name = b;\n    ++x;\n  }\n  f.Close();\n\n  c.fu = o.fu;\n  c.timesd = o.timesd;\n  c.timesu = o.timesu;\n  c.max_msgs = o.max_msgs;\n  c.hello = o.hello;\n  c.news = o.news;\n  c.bye = o.bye;\n  c.packet_name = o.packet_name;\n  return c;\n}\n\nqwk_config read_qwk_cfg(const Config& config) {\n  const auto path = FilePath(config.datadir(), \"qwk.json\");\n  qwk_config c{};\n  JsonFile f(path, \"qwk\", c, 1);\n  if (f.Load()) {\n    return c;\n  }\n  return read_qwk_cfg_430(config);\n}\n\nvoid write_qwk_cfg(const Config& config, const qwk_config& c) {\n  const auto path = FilePath(config.datadir(), \"qwk.json\");\n  JsonFile f(path, \"qwk\", c, 1);\n  if (!f.Save()) {\n    LOG(ERROR) << \"Failed to save qwk.json\";\n  }\n}\n\n}\n"
  },
  {
    "path": "sdk/qwk_config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_QWK_CONFIG_H\n#define INCLUDED_SDK_QWK_CONFIG_H\n\n#include \"core/wwivport.h\" // daten_t\n#include \"sdk/config.h\"\n\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\nstruct qwk_bulletin {\n  std::string name;\n  std::string path;\n};\n\nstruct qwk_config {\n  daten_t fu;\n  long timesd;\n  long timesu;\n  uint16_t max_msgs;\n\n  std::string hello;\n  std::string news;\n  std::string bye;\n  std::string packet_name;\n\n  std::vector<qwk_bulletin> bulletins;\n};\n\n#pragma pack(push, 1)\n\nstruct qwk_config_430 {\n  daten_t fu;\n  int32_t timesd;\n  int32_t timesu;\n  uint16_t max_msgs;\n\n  char hello[13];\n  char news[13];\n  char bye[13];\n  char packet_name[9];\n  char res[190];\n\n  int32_t amount_blts;\n  char unused_blt_res[8 * 50];\n};\n#pragma pack(pop)\n\n\nstatic_assert(sizeof(qwk_config_430) == 656u, \"qwk_config should be 656 bytes\");\n\nstd::string qwk_system_name(const qwk_config& c, const std::string& system_name);\nqwk_config read_qwk_cfg(const Config& config);\nvoid write_qwk_cfg(const Config& config, const qwk_config& c);\n\n\n}\n\n#endif"
  },
  {
    "path": "sdk/sdk_helper.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/sdk_helper.h\"\n\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/vardec.h\"\n\n#include \"gtest/gtest.h\"\n#include <string>\n#include \"sdk_helper.h\"\n\n\nusing namespace std;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nstatic statusrec_t create_status() {\n  statusrec_t s = {};\n  memset(&s, 0, sizeof(statusrec_t));\n  const auto now{DateTime::now().to_string(\"%m/%d/%y\")};\n  to_char_array(s.date1, now);\n  to_char_array(s.date2, \"00/00/00\");\n  to_char_array(s.date3, \"00/00/00\");\n  to_char_array(s.log1, \"000000.log\");\n  to_char_array(s.log2, \"000000.log\");\n  to_char_array(s.gfiledate, now);\n  s.callernum = 65535;\n  s.qscanptr = 2;\n  s.net_bias = 0.001f;\n  s.net_req_free = 3.0;\n  return s;\n}\n\nSdkHelper::SdkHelper()\n    : saved_dir_(File::current_directory()), \n      root_(files_.CreateTempFilePath(\"bbs\")) {\n  data_ = CreatePath(\"data\");\n  msgs_ = CreatePath(\"msgs\");\n  gfiles_ = CreatePath(\"gfiles\");\n  menus_ = CreatePath(\"menus\");\n  scripts_ = CreatePath(\"scripts\");\n  dloads_ = CreatePath(\"dloads\");\n  logs_ = CreatePath(\"logs\");\n  scratch_ = CreatePath(\"e/scratch\");\n  CreatePath(\"e/scratch/1\");\n  CreatePath(\"e/scratch/2\");\n  CreatePath(\"e/scratch/3\");\n  CreatePath(\"e/scratch/4\");\n\n  {\n    wwiv::sdk::config_t c{};\n    c.msgsdir = \"msgs\";\n    c.gfilesdir = \"gfiles\";\n    c.menudir = \"menus\";\n    c.datadir = \"data\";\n    c.logdir = \"logs\";\n    c.dloadsdir = \"dloads\";\n    c.tempdir_format = \"e/temp/%n\";\n    c.scratchdir_format = \"e/scratch/%n\";\n\n    // Add header version.\n    // TODO(rushfan): This really should all be done in the Config class and also used\n    // by wwivconfig from there.\n    c.header.config_revision_number = 0;\n    c.userreclen = sizeof(userrec);\n    c.header.written_by_wwiv_num_version = wwiv_config_version();\n\n    // Set some more defaults various tests need\n    c.maxusers = 100;\n    c.max_dirs = 64;\n    c.max_subs = 64;\n\n    config_ = std::make_unique<wwiv::sdk::Config>(root_, c);\n    config_->set_paths_for_test(datadir(), msgsdir(), gfilesdir(), menudir(), dloadsdir(), scriptdir());\n\n    // Force this to be read-write since we're in a test environment (same as\n    // in the upgrade case)\n    config_->set_readonly(false);\n    if (!config_->Save()) {\n      throw std::runtime_error(\"failed to create config.json\");\n    }\n  }\n\n  {\n    File sfile(FilePath(data_, STATUS_DAT));\n    if (!sfile.Open(File::modeBinary | File::modeCreateFile | File::modeWriteOnly)) {\n      throw std::runtime_error(\"failed to create status.dat\");\n    }\n    auto s = create_status();\n    sfile.Write(&s, sizeof(statusrec_t));\n    sfile.Close();\n  }\n}\n\nstd::filesystem::path SdkHelper::CreatePath(const string& name) {\n  auto path = files_.CreateTempFilePath(FilePath(\"bbs\", name).string());\n  File::mkdirs(path);\n  return path;\n}\n\nwwiv::sdk::Config& SdkHelper::config() const { \n  return *config_; \n}\n\nwwiv::sdk::net::Network SdkHelper::CreateTestNetwork(network_type_t net_type) {\n  const auto dir = CreatePath(\"network\");\n  const uint16_t node = net_type == network_type_t::ftn ? FTN_FAKE_OUTBOUND_NODE : 1;\n  wwiv::sdk::net::Network n(net_type, \"TestNET\", dir, node);\n  if (net_type == network_type_t::ftn) {\n    n.fido.inbound_dir = \"in\";\n    n.fido.outbound_dir = \"out\";\n    n.fido.temp_inbound_dir = \"tempin\";\n    n.fido.temp_outbound_dir = \"tempout\";\n    n.fido.unknown_dir = \"unknown\";\n    n.fido.bad_packets_dir = \"bad\";\n    n.fido.netmail_dir = \"netmail\";\n    n.fido.fido_address = \"21:12/2112\";\n  }\n  return n;\n}\n\nSdkHelper::~SdkHelper() {\n  try {\n    const auto dir = saved_dir_.string();\n    (void) chdir(dir.c_str());\n  } catch (...) {\n    //\n  }\n}\n"
  },
  {
    "path": "sdk/sdk_helper.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_TEST_SDK_HELPER_H\n#define INCLUDED_SDK_TEST_SDK_HELPER_H\n\n#include <filesystem>\n#include <memory>\n#include <string>\n\n#include \"core/test/file_helper.h\"\n#include \"sdk/bbs_directories.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/net.h\"\n\nclass SdkHelper : public wwiv::sdk::BbsDirectories {\npublic:\n  SdkHelper();\n  ~SdkHelper();\n  bool SetUp() { return true; }\n\n  [[nodiscard]] virtual std::filesystem::path root_directory() const override { return root_; }\n  [[nodiscard]] virtual std::filesystem::path datadir() const override { return data_; }\n  [[nodiscard]] virtual std::filesystem::path msgsdir() const override { return msgs_; }\n  [[nodiscard]] virtual std::filesystem::path gfilesdir() const override { return gfiles_; }\n  [[nodiscard]] virtual std::filesystem::path menudir() const override { return menus_; }\n  [[nodiscard]] virtual std::filesystem::path dloadsdir() const override { return dloads_; }\n  [[nodiscard]] virtual std::filesystem::path scriptdir() const override { return scripts_; }\n  [[nodiscard]] virtual std::filesystem::path logdir() const override { return logs_; }\n  [[nodiscard]] virtual std::filesystem::path scratch_dir(int) const override {\n    return scratch_;\n  }\n\n  [[nodiscard]] std::filesystem::path scratch() const { return scratch_; }\n  [[nodiscard]] wwiv::core::test::FileHelper& files() { return files_; }\n  [[nodiscard]] wwiv::sdk::Config& config() const;\n  [[nodiscard]] wwiv::sdk::net::Network CreateTestNetwork(wwiv::sdk::net::network_type_t net_type);\n\n\n  std::filesystem::path CreatePath(const std::string& name);\n  wwiv::core::test::FileHelper files_;\n  std::filesystem::path data_;\n  std::filesystem::path dloads_;\n  std::filesystem::path msgs_;\n  std::filesystem::path menus_;\n  std::filesystem::path gfiles_;\n  std::filesystem::path scripts_;\n  std::filesystem::path logs_;\n  std::filesystem::path scratch_;\n\nprivate:\n  const std::filesystem::path saved_dir_;\n  const std::filesystem::path root_;\n  std::unique_ptr<wwiv::sdk::Config> config_;\n};\n\n#endif  // INCLUDED_SDK_TEST_SDK_HELPER_H\n"
  },
  {
    "path": "sdk/sdk_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*              Copyright (C)2017-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  } catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n}\n"
  },
  {
    "path": "sdk/ssm.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2014-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/ssm.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/net/net.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nSSM::SSM(const wwiv::sdk::Config& config, wwiv::sdk::UserManager& user_manager)\n  : data_directory_(config.datadir()), user_manager_(user_manager) {\n\n}\n\nSSM::~SSM() = default;\n\nbool SSM::send_remote(const Network& net, uint16_t system_number, uint32_t from_user_number, uint32_t user_number, const std::string& t) {\n  net_header_rec nh{};\n  nh.tosys = system_number;\n  nh.touser = static_cast<uint16_t>(user_number);\n  // This was user_number, but that seems really wrong.  Changing to net.sysnum.\n  nh.fromsys = net.sysnum;\n  nh.fromuser = static_cast<uint16_t>(from_user_number);\n  nh.main_type = main_type_ssm;\n  nh.minor_type = 0;\n  nh.list_len = 0;\n  auto text(t);\n  nh.daten = daten_t_now();\n  if (text.size() > 80) {\n    text.resize(80);\n  }\n  nh.length = stl::size_uint32(text);\n  nh.method = 0;\n  const auto packet_filename = StrCat(net.dir, \"p0.net\");\n  File file(packet_filename);\n  file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  file.Seek(0L, File::Whence::end);\n  file.Write(&nh, sizeof(net_header_rec));\n  file.Write(text.c_str(), nh.length);\n  file.Close();\n  return true;\n}\n\nbool SSM::send_local(uint32_t user_number, const std::string& text) {\n\n  auto user = user_manager_.readuser(user_number, UserManager::mask::non_deleted);\n  if (!user) {\n    return false;\n  }\n  File file(FilePath(data_directory_, SMW_DAT));\n  if (!file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    return false;\n  }\n  auto pos = static_cast<int>(file.length() / sizeof(shortmsgrec)) - 1;\n  shortmsgrec sm{};\n  if (pos >= 0) {\n    file.Seek(pos * sizeof(shortmsgrec), File::Whence::begin);\n    file.Read(&sm, sizeof(shortmsgrec));\n    while (sm.tosys == 0 && sm.touser == 0 && pos > 0) {\n      --pos;\n      file.Seek(pos * sizeof(shortmsgrec), File::Whence::begin);\n      file.Read(&sm, sizeof(shortmsgrec));\n    }\n    if (sm.tosys != 0 || sm.touser != 0) {\n      pos++;\n    }\n  } else {\n    pos = 0;\n  }\n  sm.tosys = static_cast<uint16_t>(0);  // 0 means local\n  sm.touser = static_cast<uint16_t>(user_number);\n  to_char_array_trim(sm.message, text);\n  file.Seek(pos * sizeof(shortmsgrec), File::Whence::begin);\n  file.Write(&sm, sizeof(shortmsgrec));\n  file.Close();\n  user->set_flag(User::SMW);\n  user_manager_.writeuser(user.value(), user_number);\n  return true;\n}\n\nbool SSM::delete_local_to_user(uint32_t user_number) {\n  DataFile<shortmsgrec> file(FilePath(data_directory_, SMW_DAT),\n                             File::modeReadWrite | File::modeBinary | File::modeCreateFile);\n  if (!file) {\n    return false;\n  }\n\n  const int num_recs = file.number_of_records();\n  for (int i = 0; i < num_recs; i++) {\n    shortmsgrec sm{};\n    if (!file.Read(i, &sm)) {\n      break;\n    }\n    if (sm.tosys == 0 && sm.touser == user_number) {\n      memset(&sm, 0, sizeof(sm));\n      file.Write(i, &sm);\n    }\n  }\n  return true;\n}\n\n}\n"
  },
  {
    "path": "sdk/ssm.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_SSM_H\n#define INCLUDED_SDK_SSM_H\n\n#include \"sdk/usermanager.h\"\n#include \"sdk/net/net.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk {\n\nclass SSM {\npublic:\n  SSM(const Config& config, UserManager& user_manager);\n  virtual ~SSM();\n\n  bool send_local(uint32_t user_number, const std::string& text);\n  bool send_remote(const net::Network& net, uint16_t system_number, uint32_t from_user_number,\n                   uint32_t user_number, const std::string& text);\n  bool delete_local_to_user(uint32_t user_number);\nprivate:\n  const std::filesystem::path data_directory_;\n  UserManager& user_manager_;\n};\n\n}\n\n#endif "
  },
  {
    "path": "sdk/status.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/status.h\"\n\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n\n#include <memory>\n#include <string>\n#include <utility>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nstatic std::string sysoplog_filename(const std::string& d) {\n  return fmt::sprintf(\"%c%c%c%c%c%c.log\", d[6], d[7], d[0], d[1], d[3], d[4]);\n}\n\nStatus::Status(const std::filesystem::path& datadir, const statusrec_t& s)\n    : status_(s), datadir_(datadir) {}\n\nStatus::~Status() = default;\n\nstd::string Status::last_date(int days_ago) const {\n  DCHECK_GE(days_ago, 0);\n  DCHECK_LE(days_ago, 2);\n  switch (days_ago) {\n  case 0:\n    return status_.date1;\n  case 1:\n    return status_.date2;\n  case 2:\n    return status_.date3;\n  default:\n    return status_.date1;\n  }\n}\n\nstd::string Status::log_filename(int nDaysAgo) const {\n  DCHECK_GE(nDaysAgo, 0);\n  switch (nDaysAgo) {\n  case 0:\n  {\n    return sysoplog_filename(DateTime::now().to_string(\"%m/%d/%y\"));\n  }\n  case 1:\n    return status_.log1;\n  case 2:\n    return status_.log2;\n  default:\n    return status_.log1;\n  }\n}\n\nvoid Status::ensure_callernum_valid() {\n  if (status_.callernum != 65535) {\n    this->caller_num(status_.callernum);\n    status_.callernum = 65535;\n  }\n}\n\nvoid Status::ensure_dates_valid() {\n  if (status_.date1[8] != '\\0') {\n    status_.date1[6] = '0';\n    status_.date1[7] = '0';\n    status_.date1[8] = '\\0'; // forgot to add null termination\n  }\n\n  auto currentDate = DateTime::now().to_string(\"%m/%d/%y\");\n  if (status_.date3[8] != '\\0') {\n    status_.date3[6] = currentDate[6];\n    status_.date3[7] = currentDate[7];\n    status_.date3[8] = '\\0';\n  }\n  if (status_.date2[8] != '\\0') {\n    status_.date2[6] = currentDate[6];\n    status_.date2[7] = currentDate[7];\n    status_.date2[8] = '\\0';\n  }\n  if (status_.date1[8] != '\\0') {\n    status_.date1[6] = currentDate[6];\n    status_.date1[7] = currentDate[7];\n    status_.date1[8] = '\\0';\n  }\n  if (status_.gfiledate[8] != '\\0') {\n    status_.gfiledate[6] = currentDate[6];\n    status_.gfiledate[7] = currentDate[7];\n    status_.gfiledate[8] = '\\0';\n  }\n}\n\nbool Status::NewDay() {\n  status_.callstoday = 0;\n  status_.msgposttoday = 0;\n  status_.localposts = 0;\n  status_.emailtoday = 0;\n  status_.fbacktoday = 0;\n  status_.uptoday = 0;\n  status_.activetoday = 0;\n  status_.days++;\n\n  // Need to verify the dates aren't trashed otherwise we can crash here.\n  ensure_dates_valid();\n\n  strcpy(status_.date3, status_.date2);\n  strcpy(status_.date2, status_.date1);\n  const auto d = DateTime::now().to_string(\"%m/%d/%y\");\n  to_char_array(status_.date1, d);\n  strcpy(status_.log2, status_.log1);\n\n  const auto log = sysoplog_filename(last_date(1));\n  to_char_array(status_.log1, log);\n  return true;\n}\n\n// StatusMgr\nbool StatusMgr::reload_status() {\n  if (auto file = DataFile<statusrec_t>(FilePath(datadir_, STATUS_DAT),\n                                        File::modeBinary | File::modeReadWrite)) {\n    char oldFileChangeFlags[7];\n    for (auto nFcIndex = 0; nFcIndex < 7; nFcIndex++) {\n      oldFileChangeFlags[nFcIndex] = statusrec_.filechange[nFcIndex];\n    }\n    if (!file.Read(0, &statusrec_)) {\n      return false;\n    }\n    if (!callback_) {\n      return true;\n    }\n    for (auto i = 0; i < 7; i++) {\n      if (oldFileChangeFlags[i] == statusrec_.filechange[i]) {\n        continue;\n      }\n      // Invoke callback on changes only if one is defined\n      callback_(i);\n    }\n    return true;\n  }\n\n  return false;\n}\n\nstd::unique_ptr<Status> StatusMgr::get_status() {\n  this->reload_status();\n  return std::make_unique<Status>(datadir_, statusrec_);\n}\n\nint StatusMgr::user_count() {\n  return get_status()->num_users();\n}\n\nbool StatusMgr::Run(status_txn_fn fn) {\n  auto at_exit = finally([&] { this->reload_status(); });\n  if (auto file = DataFile<statusrec_t>(FilePath(datadir_, STATUS_DAT),\n                                        File::modeBinary | File::modeReadWrite)) {\n    if (file.Read(0, &statusrec_)) {\n      Status status(datadir_, statusrec_);\n      fn(status);\n      file.Write(0, &status.status_);\n    }\n    return true;\n  }\n  return false;\n}\n\n\n}\n"
  },
  {
    "path": "sdk/status.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_STATUS_H\n#define INCLUDED_SDK_STATUS_H\n\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n\n#include <filesystem>\n#include <functional>\n#include <memory>\n#include <string>\n#include <utility>\n\nnamespace wwiv::sdk {\n\nclass Status {\n  friend class StatusMgr;\n\npublic:\n  Status(const std::filesystem::path& datadir, const statusrec_t& s);\n  ~Status();\n\n  /** If the caller number variable is using the old (pre 4.2) location, move it to the new location\n   */\n  void ensure_callernum_valid();\n  /** Checks for corruption in the date strings, and try to fix if the date strings are corrupt */\n  void ensure_dates_valid();\n\n  /** Updates the status object for a new day.  This zeros out daily stats and updates the log file\n   * names */\n  bool NewDay();\n\n  [[nodiscard]] std::string last_date(int days_ago = 0) const;\n  [[nodiscard]] std::string log_filename(int nDaysAgo = 0) const;\n  void gfile_date(const std::string& s) { strings::to_char_array(status_.gfiledate, s); }\n  [[nodiscard]] uint8_t filechanged(int nFlag) const { return status_.filechange[nFlag]; }\n  void increment_filechanged(int nFlag) { status_.filechange[nFlag]++; }\n\n  [[nodiscard]] uint16_t localposts() const { return status_.localposts; }\n  void IncrementNumLocalPosts() { status_.localposts++; }\n  void localposts(int n) { status_.localposts = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] int num_users() const { return status_.users; }\n  void increment_num_users() { status_.users++; }\n  void decrement_num_users() { status_.users--; }\n  void num_users(int n) { status_.users = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] int caller_num() const { return status_.callernum1; }\n  void increment_caller_num() { status_.callernum1++; }\n  void caller_num(unsigned long l) { status_.callernum1 = l; }\n\n  [[nodiscard]] uint16_t calls_today() const { return status_.callstoday; }\n  void increment_calls_today() { status_.callstoday++; }\n  void calls_today(int n) { status_.callstoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t msgs_today() const { return status_.msgposttoday; }\n  void increment_msgs_today() { status_.msgposttoday++; }\n  void msgs_today(int n) { status_.msgposttoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t email_today() const { return status_.emailtoday; }\n  void increment_email_today() { status_.emailtoday++; }\n  void email_today(int n) { status_.emailtoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t feedback_today() const { return status_.fbacktoday; }\n  void increment_feedback_today() { status_.fbacktoday++; }\n  void feedback_today(int n) { status_.fbacktoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t uploads_today() const { return status_.uptoday; }\n  void increment_uploads_today() { status_.uptoday++; }\n  void uploads_today(int n) { status_.uptoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t active_today_minutes() const { return status_.activetoday; }\n  void active_today_minutes(int n) { status_.activetoday = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint32_t qscanptr() const { return status_.qscanptr; }\n  uint32_t next_qscanptr() { return status_.qscanptr++; }\n  void qscanptr(uint32_t l) { status_.qscanptr = l; }\n\n  [[nodiscard]] bool automessage_anon() const { return status_.amsganon ? true : false; }\n  void automessage_anon(bool b) { status_.amsganon = (b) ? 1 : 0; }\n\n  [[nodiscard]] uint16_t automessage_usernum() const { return status_.amsguser; }\n  void automessage_usernum(int n) { status_.amsguser = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t status_wwiv_version() const { return status_.wwiv_version; }\n  void status_wwiv_version(int n) { status_.wwiv_version = static_cast<uint16_t>(n); }\n\n  [[nodiscard]] uint16_t status_net_version() const { return status_.net_version; }\n  [[nodiscard]] uint16_t  days_active() const { return status_.days; }\n  void days_active(int n) { status_.days = static_cast<uint16_t>(n); }\n\n  static constexpr int file_change_names = 0;\n  static constexpr int file_change_upload = 1;\n  static constexpr int file_change_posts = 2;\n  static constexpr int file_change_email = 3;\n  static constexpr int file_change_net = 4;\n\nprivate:\n  statusrec_t status_;\n  const std::filesystem::path datadir_;\n};\n\n/*!\n * @class StatusMgr\n * manages STATUS.DAT\n */\nclass StatusMgr {\npublic:\n  typedef std::function<void(int)> status_callabck_fn;\n  typedef std::function<void(Status& s)> status_txn_fn;\n\n  /*!\n   * @function StatusMgr Constructor\n   */\n  StatusMgr(const std::filesystem::path& datadir, status_callabck_fn callback)\n      : datadir_(datadir), callback_(std::move(callback)) {}\n  explicit StatusMgr(const std::filesystem::path& datadir) : datadir_(datadir) {}\n  virtual ~StatusMgr() = default;\n  /*!\n   * @function Loads the contents of STATUS.DAT\n   * @return true on success\n   */\n  bool reload_status();\n\n  /**\n   * Gets the status object with no locks.  Just delete it when finished\n   */\n  std::unique_ptr<Status> get_status();\n\n  [[nodiscard]] int user_count();\n\n  bool Run(status_txn_fn fn);\n\nprivate:\n  const std::filesystem::path datadir_;\n  status_callabck_fn callback_;\n  statusrec_t statusrec_{};\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/subs_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_SUBS_CEREAL_H\n#define INCLUDED_SDK_SUBS_CEREAL_H\n\n#include \"core/cereal_utils.h\"\n#include \"sdk/subxtr.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/conf/conf_set_cereal.h\"\n\nnamespace wwiv::sdk {\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, subboard_network_data_t& s) {\n  SERIALIZE(s, stype);\n  SERIALIZE(s, flags);\n  SERIALIZE(s, net_num);\n  SERIALIZE(s, host);\n  SERIALIZE(s, category);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, subboard_t& s) { \n  SERIALIZE(s, name);\n  SERIALIZE(s, filename);\n  SERIALIZE(s, key);\n  SERIALIZE(s, read_acs);\n  SERIALIZE(s, post_acs);\n  SERIALIZE(s, anony);\n  SERIALIZE(s, maxmsgs);\n  SERIALIZE(s, storage_type);\n  SERIALIZE(s, nets);\n  SERIALIZE(s, conf);\n  SERIALIZE(s, colorize_text);\n}\n\ntemplate <class Archive> void serialize(Archive& ar, subboard_52_t& s) { \n  SERIALIZE(s, name);\n  SERIALIZE(s, filename);\n  SERIALIZE(s, key);\n  SERIALIZE(s, readsl);\n  SERIALIZE(s, postsl);\n  SERIALIZE(s, anony);\n  SERIALIZE(s, age);\n  SERIALIZE(s, maxmsgs);\n  SERIALIZE(s, ar);\n  SERIALIZE(s, storage_type);\n  SERIALIZE(s, nets);\n}\n\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/subxtr.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/subxtr.h\"\n\n#include \"acs/expr.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/subs_cereal.h\"\n#include \"sdk/vardec.h\"\n#include <sstream>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nnamespace wwiv::sdk {\n\nbool read_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                   const std::vector<subboardrec_422_t>& subs, std::vector<xtrasubsrec>& xsubs);\nbool write_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                    const std::vector<xtrasubsrec>& xsubs, int max_backups);\n\nstd::vector<subboardrec_422_t> read_subs(const std::filesystem::path& datadir);\nbool write_subs(const std::filesystem::path& datadir,\n                const std::vector<subboardrec_422_t>& subboards);\n\n\nbool Subs::LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                        std::vector<subboard_t>& entries) {\n  entries.clear();\n  const auto path = FilePath(dir, filename);\n  JsonFile f(path, \"subs\", entries, 1);\n  return f.Load();\n}\n\n\n//static \nbool Subs::SaveToJSON(const std::filesystem::path& dir, const std::string& filename,\n                      const std::vector<subboard_t>& entries) {\n  const auto path = FilePath(dir, filename);\n  JsonFile f(path, \"subs\", entries, 1);\n  return f.Save();\n}\n\nstatic int FindNetworkByName(const std::vector<Network>& net_networks, const std::string& name) {\n  for (auto i = 0; i < wwiv::stl::ssize(net_networks); i++) {\n    if (iequals(net_networks[i].name, name)) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nbool ParseXSubsLine(const std::vector<Network>& net_networks, const std::string& line, xtrasubsrec& xsub) {\n  std::stringstream stream(line);\n  std::string net_name;\n  stream >> net_name;\n  StringTrim(&net_name);\n  const auto net_num = FindNetworkByName(net_networks, net_name);\n  if (net_num == -1) {\n    return false;\n  }\n\n  xtrasubsnetrec x;\n\n  std::string stype;\n  stream >> stype;\n  StringTrim(&stype);\n  x.stype_str = stype;\n  x.net_num = static_cast<int16_t>(net_num);\n\n  stream >> x.flags;\n  stream >> x.host;\n  stream >> x.category;\n\n  xsub.nets.push_back(x);\n  return true;\n}\n\nbool read_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                   const std::vector<subboardrec_422_t>& subs, std::vector<xtrasubsrec>& xsubs) {\n  // Clear the existing xsubs.\n  xsubs.clear();\n  // add default constructed xtrasubsrec entries\n  xsubs.resize(subs.size());\n\n  // subs.xtr may not exist on new installs.\n  if (!File::Exists(FilePath(datadir, SUBS_XTR))) {\n    return true;\n  }\n\n  TextFile subs_xtr(FilePath(datadir, SUBS_XTR), \"rt\");\n  if (!subs_xtr.IsOpen()) {\n    return false;\n  }\n\n  // Clear the existing xsubs.\n  xsubs.clear();\n  // add default constructed xtrasubsrec entries\n  xsubs.resize(subs.size());\n\n  // Only load the configuration file if it exists.\n  std::string line;\n  auto curn = -1;\n  while (subs_xtr.ReadLine(&line)) {\n    StringTrim(&line);\n    const auto identifier = line.front();\n    line = line.substr(1);\n    switch (identifier) {\n    case '!':\n    {                        /* sub idx */\n      curn = to_number<int>(line);\n      if (curn >= size_int(subs)) {\n        // Bad number on ! line.\n        curn = -1;\n        break;\n      }\n    } break;\n    case '@':                         /* desc */\n      if (curn >= 0) {\n        to_char_array(xsubs[curn].desc, line);\n      }\n      break;\n    case '$':                         /* net info */\n      if (curn >= 0) {\n        ParseXSubsLine(net_networks, line, xsubs[curn]);\n      } break;\n    default:\n      // NOP\n      ;\n    }\n  }\n\n  return true;\n}\n\nbool write_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                    const std::vector<xtrasubsrec>& xsubs, int max_backups) {\n  // Backup subs.xtr\n  const auto sx = FilePath(datadir, SUBS_XTR);\n  backup_file(sx, max_backups);\n\n  TextFile f(sx, \"w\");\n  if (!f.IsOpen()) {\n    return false;\n  }\n\n  auto i = 0;\n  for (const auto& x : xsubs) {\n    if (!x.nets.empty()) {\n      f.Write(fmt::sprintf(\"!%u\\n@%s\\n#0\\n\", i, x.desc));\n      for (const auto& n : x.nets) {\n        if (size_int(net_networks) <= n.net_num || n.net_num < 0) {\n          LOG(ERROR) << \"Unable to write a subs.xtr line for network number: \" << n.net_num\n                     << \" for sub with description: \" << x.desc;\n          continue;\n        }\n        const auto& net = net_networks[n.net_num];\n        f.Write(\n            fmt::sprintf(\"$%s %s %lu %u %u\\n\", net.name, n.stype_str, n.flags, n.host, n.category));\n      }\n    }\n    i++;\n  }\n  return true;\n}\n\nstd::vector<subboardrec_422_t> read_subs(const std::filesystem::path &datadir) {\n  DataFile<subboardrec_422_t> file(FilePath(datadir, SUBS_DAT));\n  if (!file) {\n    // TODO(rushfan): Figure out why this caused link errors. What's missing?\n    //LOG(ERROR) << file.file() << \" NOT FOUND.\";\n    return{};\n  }\n  std::vector<subboardrec_422_t> subboards;\n  if (!file.ReadVector(subboards)) {\n    return{};\n  }\n  return subboards;\n}\n\nbool write_subs(const std::filesystem::path& datadir,\n                const std::vector<subboardrec_422_t>& subboards) {\n  DataFile<subboardrec_422_t> subsfile(FilePath(datadir, SUBS_DAT),\n                                       File::modeBinary | File::modeReadWrite |\n                                           File::modeCreateFile | File::modeTruncate,\n                                       File::shareDenyReadWrite);\n  if (!subsfile) {\n    return false;\n  }\n  return subsfile.WriteVector(subboards);\n}\n\n\n// Classes\n\nSubs::Subs(std::filesystem::path datadir, const std::vector<Network>& net_networks, int max_backups)\n  : datadir_(std::move(datadir)), net_networks_(net_networks), max_backups_(max_backups) {};\n\nSubs::~Subs() = default;\n\nbool Subs::Load() {\n  if (!LoadFromJSON(datadir_, SUBS_JSON, subs_)) {\n    return LoadLegacy();\n  }\n  return true;\n}\n\nbool Subs::LoadLegacy() {\n  auto old_subs = read_subs(datadir_);\n  std::vector<xtrasubsrec> xsubs;\n  if (!read_subs_xtr(datadir_, net_networks_, old_subs, xsubs)) {\n    return false;\n  }\n\n  subs_.clear();\n  for (decltype(old_subs)::size_type i = 0; i < old_subs.size(); i++) {\n    const auto& olds = at(old_subs, i);\n    auto& oldx = xsubs[i];\n    subboard_t sub{};\n    sub.name = olds.name;\n    sub.desc = oldx.desc;\n    sub.filename = olds.filename;\n    sub.key = olds.key;\n    {\n      acs::AcsExpr ae;\n      ae.min_sl(olds.readsl);\n      if (olds.age > 0 && olds.age < 255) {\n        ae.min_age(olds.age);\n      }\n      if (olds.ar != 0) {\n        ae.ar_int(olds.ar);\n      }\n      sub.read_acs = ae.get();\n    }\n    if (olds.postsl) {\n      acs::AcsExpr ae;\n      sub.post_acs = ae.min_sl(olds.postsl).get();\n    }\n    sub.anony = olds.anony;\n    sub.maxmsgs = olds.maxmsgs;\n    sub.storage_type = static_cast<uint8_t>(olds.storage_type);\n    for (const auto& n : oldx.nets) {\n      subboard_network_data_t netdata = {};\n      netdata.stype = n.stype_str;\n      netdata.flags = n.flags;\n      netdata.net_num = n.net_num;\n      netdata.host = n.host;\n      netdata.category = n.category;\n      sub.nets.emplace_back(netdata);\n    }\n    subs_.emplace_back(std::move(sub));\n  }\n  return true;\n}\n\nbool Subs::Save() {\n  std::vector<subboardrec_422_t> subs;\n  std::vector<xtrasubsrec> xsubs;\n\n  for (const auto& s : subs_) {\n    // Only copy over what data fits in the old format.\n    subboardrec_422_t ls{};\n    xtrasubsrec lx{};\n    if (s.name.size() < sizeof ls.name) {\n      to_char_array(ls.name, s.name);\n    }\n    if (s.desc.size() < sizeof lx.desc) {\n      to_char_array(lx.desc, s.desc);\n    }\n    if (s.filename.size() < sizeof ls.filename) {\n      to_char_array(ls.filename, s.filename);\n    }\n    ls.key = s.key;\n    ls.anony = s.anony;\n    ls.maxmsgs = s.maxmsgs;\n    /*\n     * TODO(rushfan): See if we can pull this out of the expression.\n    ls.readsl = s.readsl;\n    ls.postsl = s.postsl;\n    ls.age = s.age;\n    ls.ar = s.ar;\n     */\n    ls.storage_type = s.storage_type;\n    ls.unused_legacy_type = 0;\n    for (const auto& n : s.nets) {\n      xtrasubsnetrec on = {};\n      on.stype_str = n.stype;\n      on.flags = n.flags;\n      on.net_num = n.net_num;\n      on.host = n.host;\n      on.category = n.category;\n      lx.nets.emplace_back(on);\n    }\n    subs.emplace_back(ls);\n    xsubs.emplace_back(lx);\n  }\n\n  if (!write_subs(datadir_, subs)) {\n    LOG(ERROR) << \"Error saving subs\";\n    return false;\n  }\n\n  if (!write_subs_xtr(datadir_, net_networks_, xsubs, max_backups_)) {\n    LOG(ERROR) << \"Error saving xsubs\";\n    return false;\n  }\n\n  // Backup subs.json\n  backup_file(FilePath(datadir_, SUBS_JSON), max_backups_);\n\n  // Save subs.\n  return Subs::SaveToJSON(datadir_, SUBS_JSON, subs_);\n}\n\nbool Subs::insert(int n, subboard_t r) {\n  return insert_at(subs_, n, r);\n}\n\nbool Subs::add(subboard_t r) {\n  subs_.emplace_back(r);\n  return true;\n}\n\nbool Subs::erase(int n) {\n  return erase_at(subs_, n);\n}\n\nconst subboard_t& Subs::sub(const std::string& filename) const {\n  for (const auto& n : subs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find sub of filename: \", filename));\n}\n\nsubboard_t& Subs::sub(const std::string& filename) {\n  for (auto& n : subs_) {\n    if (iequals(filename, n.filename)) {\n      return n;\n    }\n  }\n  throw std::out_of_range(StrCat(\"Unable to find sub of filename: \", filename));\n}\n\nbool Subs::exists(const std::string& filename) const {\n  for (const auto& n : subs_) {\n    if (iequals(filename, n.filename)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n}\n"
  },
  {
    "path": "sdk/subxtr.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_SUBXTR_H\n#define INCLUDED_SDK_SUBXTR_H\n\n#include \"core/stl.h\"\n#include \"fido/fido_address.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/conf/conf_set.h\"\n#include <filesystem>\n#include <set>\n#include <string>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::sdk {\n\n// per-network message data or subboards.\nstruct subboard_network_data_t {\n  std::string stype;\n  int32_t flags = 0;\n  int16_t net_num = 0;\n  int16_t host = 0;\n  int16_t category = 0;\n  std::set<fido::FidoAddress> ftn_uplinks;\n};\n\n// New (5.6+) style sub-board. \nstruct subboard_t {\n  // sub name\n  std::string name;\n  // long description - for subs.lst\n  std::string desc;\n\n  // board database filename\n  std::string filename;\n  // special key\n  char key{0};\n\n  // sl required to read\n  std::string read_acs;\n  // sl required to post\n  std::string post_acs;\n  // anonymous board?\n  uint8_t anony{0};\n\n  // max # of msgs\n  uint16_t maxmsgs{0};\n  // how it is stored (type, 1 or 2)\n  uint8_t storage_type{0};\n  // per-network data type for networked subs.\n  std::vector<subboard_network_data_t> nets;\n  // Conference keys.\n  conf_set_t conf;\n  // Attempt to colorize the text if not colorized?\n  bool colorize_text{false};\n};\n\n// 5.2 style sub-board. \nstruct subboard_52_t {\n  // sub name\n  std::string name;\n  // long description - for subs.lst\n  std::string desc;\n\n  // board database filename\n  std::string filename;\n  // special key\n  char key = 0;\n\n  // sl required to read\n  uint8_t readsl = 0;\n  // sl required to post\n  uint8_t postsl = 0;\n  // anonymous board?\n  uint8_t anony = 0;\n  // minimum age for sub\n  uint8_t age = 0;\n\n  // max # of msgs\n  uint16_t maxmsgs = 0;\n  // AR for sub-board\n  uint16_t ar = 0;\n  // how it is stored (type, 1 or 2)\n  uint8_t storage_type = 0;\n  // per-network data type for networked subs.\n  std::vector<subboard_network_data_t> nets;\n};\n\nclass Subs final {\npublic:\n  Subs(std::filesystem::path datadir, const std::vector<net::Network>& net_networks,\n       int max_backups = 0);\n  ~Subs();\n\n  bool LoadLegacy();\n  bool Load();\n  bool Save();\n\n  [[nodiscard]] const subboard_t& sub(std::size_t n) const { return stl::at(subs_, n); }\n  [[nodiscard]] const subboard_t& sub(const std::string& filename) const;\n  subboard_t& sub(std::size_t n) { return subs_[n]; }\n  subboard_t& sub(const std::string& filename);\n\n  const subboard_t& operator[](std::size_t n) const { return sub(n); }\n  const subboard_t& operator[](const std::string& filename) const { return sub(filename); }\n  subboard_t& operator[](std::size_t n) { return sub(n); }\n  subboard_t& operator[](const std::string& filename) { return sub(filename); }\n\n  [[nodiscard]] bool exists(const std::string& filename) const;\n\n  void set_sub(int n, subboard_t s) { subs_[n] = std::move(s); }\n  [[nodiscard]] const std::vector<subboard_t>& subs() const { return subs_; }\n  bool insert(int n, subboard_t r);\n  bool add(subboard_t r);\n  bool erase(int n);\n  [[nodiscard]] int size() const { return stl::size_int(subs_); }\n\n  static bool LoadFromJSON(const std::filesystem::path& dir, const std::string& filename,\n                           std::vector<subboard_t>& entries);\n\nprivate:\n\n  static bool SaveToJSON(const std::filesystem::path& dir, const std::string& filename,\n                         const std::vector<subboard_t>& entries);\n\n  const std::filesystem::path datadir_;\n  const std::vector<net::Network> net_networks_;\n  const int max_backups_;\n  std::vector<subboard_t> subs_;\n};\n\n// Not serialized as binary on disk.\n/*\n * Info for each network the sub is on.\n *  flags - bitmask\n *  net_num - index into networks.dat\n *  type - numeric sub type = to_number<int>(stype)\n *  host - host system of sub, or 0 if locally hosted\n *  stype - string sub type (up to 7 chars)\n */\nstruct xtrasubsnetrec {\n  long flags{0};\n  int16_t net_num{-1};\n  int16_t host{-1};\n  int16_t category{-1};\n  std::string stype_str;\n};\n\n\n/*\n * Extended info for each sub, relating to network.\n * Note: This structure is not loaded/saved to disk as-is.\n *  flags - bitmask\n *  desc - long description, for auto subs.lst info\n *  nets - vector of network info for sub\n */\nstruct xtrasubsrec {\n  long unused_xtra_flags{0};\n  char desc[61]{};\n  std::vector<xtrasubsnetrec> nets;\n};\n\n#define XTRA_NET_AUTO_ADDDROP 0x00000001    /* can auto add-drop the sub */\n#define XTRA_NET_AUTO_INFO    0x00000002    /* sends subs.lst info for sub */\n\n}\n\n\n#endif\n"
  },
  {
    "path": "sdk/subxtr_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2014-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"gtest/gtest.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/sdk_helper.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\n// Made visible for testing\nnamespace wwiv::sdk {\n\nbool read_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                   const std::vector<subboardrec_422_t>& subs, std::vector<xtrasubsrec>& xsubs);\nbool write_subs_xtr(const std::filesystem::path& datadir, const std::vector<Network>& net_networks,\n                    const std::vector<xtrasubsrec>& xsubs, int);\n\nstd::vector<subboardrec_422_t> read_subs(const std::filesystem::path& datadir);\nbool write_subs(const std::filesystem::path& datadir,\n                const std::vector<subboardrec_422_t>& subboards);\n\n}\n\nclass SubXtrTest: public testing::Test {\nprotected:\n  void SetUp() override { \n    helper.SetUp(); \n    net_networks_.emplace_back(Network{network_type_t::wwivnet, \"testnet\", \"testnet/\", 2});\n    subs_.emplace_back(subboardrec_422_t{\"Sub1\", \"S1\", '1', 10, 10, 0, 0, 500, 0, 2, 0});\n    subs_.emplace_back(subboardrec_422_t{\"Sub2\", \"S2\", '2', 10, 10, 0, 0, 500, 0, 2, 0});\n  }\n\n  [[nodiscard]] std::string dir() const { return helper.files_.TempDir().string(); }\n  void CreateTempFile(const std::string& name, const std::string& contents) {\n    helper.files().CreateTempFile(name, contents);\n  }\n  SdkHelper helper;\n  std::vector<Network> net_networks_;\n  std::vector<subboardrec_422_t> subs_;\n};\n\nTEST_F(SubXtrTest, Write) {\n  std::vector<xtrasubsrec> xsubs;\n  xsubs.emplace_back(xtrasubsrec{0, \"\", {}});\n  xtrasubsrec s2{0, \"this is sub2\", {}};\n  s2.nets.emplace_back(xtrasubsnetrec{0, 0, 1, 1, \"S2\"});\n  xsubs.emplace_back(s2);\n\n  write_subs_xtr(helper.datadir(), net_networks_, xsubs, 0);\n  TextFile subs_xtr_file(FilePath(helper.datadir(), \"subs.xtr\"), \"r\");\n  auto actual = SplitString(subs_xtr_file.ReadFileIntoString(), \"\\n\");\n  ASSERT_EQ(4u, actual.size());\n  std::vector<std::string> expected = {\n    { \"!1\", \"@this is sub2\", \"#0\", \"$testnet S2 0 1 1\"},\n  };\n  EXPECT_TRUE(std::equal(expected.begin(), expected.end(), actual.begin()));\n}\n\nstatic bool equal(const xtrasubsnetrec& x1, const xtrasubsnetrec& x2) {\n  if (x1.category != x2.category) {\n    return false;\n  }\n  if (x1.flags != x2.flags) {\n    return false;\n  }\n  if (x1.host != x2.host) {\n    return false;\n  }\n  if (x1.net_num != x2.net_num) {\n    return false;\n  }\n  return iequals(x1.stype_str, x2.stype_str);\n}\n\nstatic bool equal(const xtrasubsrec& x1, const xtrasubsrec& x2) {\n  if (!IsEquals(x1.desc, x2.desc)) {\n    return false;\n  }\n  if (x1.nets.size() != x2.nets.size()) {\n    return false;\n  }\n  for (auto i = 0; i < wwiv::stl::ssize(x1.nets); i++) {\n    if (!equal(x1.nets[i], x2.nets[i])) {\n      return false;\n    }\n  }\n  return true;\n}\n\nTEST_F(SubXtrTest, Read) {\n  std::vector<xtrasubsrec> expected;\n  expected.emplace_back(xtrasubsrec{0, \"\", {}});\n  xtrasubsrec s2{0, \"this is sub2\", {}};\n  s2.nets.emplace_back(xtrasubsnetrec{0, 0, 1, 1, \"S2\"});\n  expected.emplace_back(s2);\n\n  {\n    std::vector<std::string> contents{\n      {\"!1\", \"@this is sub2\", \"#0\", \"$testnet S2 0 1 1\"},\n    };\n    TextFile subs_xtr_file(FilePath(helper.datadir(), \"subs.xtr\"), \"w\");\n    for (const auto& line : contents) {\n      subs_xtr_file.WriteLine(line);\n    }\n  }\n  std::vector<xtrasubsrec> actual;\n  read_subs_xtr(helper.datadir(), net_networks_, subs_, actual);\n  ASSERT_EQ(subs_.size(), actual.size());\n  ASSERT_EQ(expected.size(), actual.size());\n  for (auto i = 0; i < wwiv::stl::ssize(subs_); i++) {\n    EXPECT_TRUE(equal(expected.at(i), actual.at(i)));\n  }\n}\n\n\nTEST_F(SubXtrTest, JsonSmoke) {\n  const std::string json = R\"(\n  {\n    \"version\": 1,\n    \"subs\": [\n      { \"name\": \"n1\", \"storage_type\": 2 }\n    ]\n  }\n )\";\n  this->CreateTempFile(\"subs.json\", json);\n\n  std::vector<subboard_t> subs;\n  ASSERT_TRUE(Subs::LoadFromJSON(dir(), \"subs.json\", subs));\n\n  ASSERT_EQ(1, wwiv::stl::ssize(subs));\n  EXPECT_EQ(\"n1\", subs[0].name);\n  EXPECT_EQ(2, subs[0].storage_type);\n\n}"
  },
  {
    "path": "sdk/testdata/conf/dirs.cnf",
    "content": "/* !!!-!!! Do not edit this file - use WWIV's conf editor! !!!-!!! */\n\n~A General\n!0 0 255 0 255 0 255 0 2 - -\n@0 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 \n\n"
  },
  {
    "path": "sdk/testdata/fido/00010001.flo",
    "content": "^u:\\mystic\\echomail\\out\\rushnet.015\\00000001.we0\n"
  },
  {
    "path": "sdk/user.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/user.h\"\n\n#include \"core/clock.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/names.h\"\n#include \"sdk/wwivcolors.h\"\n#include <chrono>\n#include <cstring>\n#include <random>\n\nusing namespace std::chrono;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk {\n\nconstexpr int HOTKEYS_ON = 0;\nconstexpr int HOTKEYS_OFF = 1;\n\nUser::User() { ZeroUserData(); }\n\nUser::User(const User& w) {\n  memcpy(&data, &w.data, sizeof(userrec));\n  user_number_ = w.user_number_;\n}\n\nUser::User(User&& u) noexcept {\n  memmove(&data, &u.data, sizeof(userrec));\n  user_number_ = u.user_number_;\n  u.user_number_ = -1;\n}\n\nUser::User(const userrec& rhs, int user_number) {\n  memcpy(&data, &rhs, sizeof(userrec));\n  user_number_ = user_number;\n}\n\nUser& User::operator=(const User& rhs) {\n  if (this == &rhs) {\n    return *this;\n  }\n  memcpy(&data, &rhs.data, sizeof(userrec));\n  user_number_ = rhs.user_number_;\n  return *this;\n}\n\nUser& User::operator=(User&& rhs) noexcept {\n  if (this == &rhs) {\n    return *this;\n  }\n  memmove(&data, &rhs.data, sizeof(userrec));\n  user_number_ = rhs.user_number_;\n  rhs.user_number_ = -1;\n  return *this;\n}\n\nvoid User::FixUp() {\n  data.name[sizeof(data.name) - 1] = '\\0';\n  data.realname[sizeof(data.realname) - 1] = '\\0';\n  data.callsign[sizeof(data.callsign) - 1] = '\\0';\n  data.phone[sizeof(data.phone) - 1] = '\\0';\n  data.dataphone[sizeof(data.dataphone) - 1] = '\\0';\n  data.street[sizeof(data.street) - 1] = '\\0';\n  data.city[sizeof(data.city) - 1] = '\\0';\n  data.state[sizeof(data.state) - 1] = '\\0';\n  data.country[sizeof(data.country) - 1] = '\\0';\n  data.zipcode[sizeof(data.zipcode) - 1] = '\\0';\n  data.pw[sizeof(data.pw) - 1] = '\\0';\n  data.laston[sizeof(data.laston) - 1] = '\\0';\n  data.firston[sizeof(data.firston) - 1] = '\\0';\n  data.firston[2] = '/';\n  data.firston[5] = '/';\n  data.note[sizeof(data.note) - 1] = '\\0';\n  data.macros[0][sizeof(data.macros[0]) - 1] = '\\0';\n  data.macros[1][sizeof(data.macros[1]) - 1] = '\\0';\n  data.macros[2][sizeof(data.macros[2]) - 1] = '\\0';\n}\n\nvoid User::ZeroUserData() { memset(&data, 0, sizeof(userrec)); }\n\nbool User::guest_user() const {\n  return iequals(name(), \"GUEST\");\n}\n\nbool User::CreateRandomPassword() {\n  std::string chars(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\");\n\n  std::random_device rd;\n  std::mt19937 e{rd()};\n  std::uniform_int_distribution<int> dist(0, wwiv::stl::size_int(chars) - 1);\n  std::string p;\n  for (auto i = 0; i < 6; i++) {\n    p.push_back(chars[dist(e)]);\n  }\n  password(p);\n  return true;\n}\n\nbool User::hotkeys() const { return data.hot_keys != HOTKEYS_OFF; }\n\nvoid User::set_hotkeys(bool enabled) { data.hot_keys = enabled ? HOTKEYS_ON : HOTKEYS_OFF; }\n\nstd::string User::menu_set() const { return data.menu_set; }\n\nvoid User::set_menu_set(const std::string& menu_set) { to_char_array(data.menu_set, menu_set); }\n\nbool User::asv(const validation_config_t& v) {\n  if (sl() < v.sl) {\n    sl(v.sl);\n  }\n  if (dsl() < v.dsl) {\n    dsl(v.dsl);\n  }\n  const auto a = ar_int();\n  ar_int(a | v.ar);\n\n  const auto d = dar_int();\n  dar_int(d | v.dar);\n\n  const auto r = restriction();\n  restriction(v.restrict & r);\n\n  return true;\n}\n\n// static\nbool User::CreateNewUserRecord(User* u, uint8_t sl, uint8_t dsl, uint16_t restr, float gold,\n                               const std::vector<uint8_t>& colors,\n                               const std::vector<uint8_t>& bwcolors) {\n  u->ZeroUserData();\n\n  const auto date = DateTime::now().to_string(\"%m/%d/%y\");\n  u->firston(date);\n  u->laston(\"Never.\");\n  u->macro(0, \"Wow! This is a GREAT BBS!\");\n  u->macro(1, \"Guess you forgot to define this one....\");\n  u->macro(2, \"User = Monkey + Keyboard\");\n\n  u->screen_lines(25);\n  u->screen_width(80);\n\n  u->sl(sl);\n  u->dsl(dsl);\n\n  u->data.ontoday = 1;\n  u->data.daten = 0;\n  u->restriction(restr);\n\n  u->set_flag(User::pauseOnPage);\n  u->clear_flag(User::conference);\n  u->clear_flag(User::nscanFileSystem);\n  u->gold(gold);\n  // Set to N so the BBS will prompt.\n  u->gender('N');\n\n  for (int i = 0; i <= 9; i++) {\n    u->color(i, colors[i]);\n    u->bwcolor(i, bwcolors[i]);\n  }\n\n  u->email_address(\"\");\n\n  // Set default menu set abd list plus colors.\n  to_char_array(u->data.menu_set, \"wwiv\");\n  u->data.hot_keys = HOTKEYS_ON;\n  u->data.lp_options = cfl_fname | cfl_extension | cfl_dloads | cfl_kbytes | cfl_description;\n  memset(u->data.lp_colors, static_cast<uint8_t>(Color::CYAN), sizeof(u->data.lp_colors));\n  u->data.lp_colors[0] = static_cast<uint8_t>(Color::LIGHTGREEN);\n  u->data.lp_colors[1] = static_cast<uint8_t>(Color::LIGHTGREEN);\n  u->data.lp_colors[2] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[3] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[4] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  u->data.lp_colors[5] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  u->data.lp_colors[6] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[7] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[8] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[9] = static_cast<uint8_t>(Color::CYAN);\n  u->data.lp_colors[10] = static_cast<uint8_t>(Color::LIGHTCYAN);\n\n  return true;\n}\n\nseconds User::add_extratime(duration<double> extra) {\n  data.extratime += duration_cast<seconds>(extra).count();\n  return seconds(static_cast<int64_t>(data.extratime));\n}\n\nseconds User::subtract_extratime(duration<double> extra) {\n  data.extratime -= duration_cast<seconds>(extra).count();\n  return seconds(static_cast<int64_t>(data.extratime));\n}\n\nduration<double> User::extra_time() const noexcept{\n  const auto extratime_seconds = static_cast<int64_t>(data.extratime);\n  return seconds(extratime_seconds);\n}\n\nseconds User::add_timeon(duration<double> d) {\n  data.timeon += duration_cast<seconds>(d).count();\n  return seconds(static_cast<int64_t>(data.timeon));\n}\n\nseconds User::add_timeon_today(duration<double> d) {\n  data.timeontoday += duration_cast<seconds>(d).count();\n  return seconds(static_cast<int64_t>(data.timeontoday));\n}\n\nseconds User::timeon() const {\n  const auto secs_used = static_cast<int64_t>(data.timeon);\n  return seconds(secs_used);\n}\n\nseconds User::timeontoday() const {\n  const auto secs_used = static_cast<int64_t>(data.timeontoday);\n  return seconds(secs_used);\n}\n\nstd::string User::name_and_number() const {\n  return fmt::format(\"{} #{}\", properize(name()), user_number_);\n}\n\nint User::usernum() const noexcept {\n  return user_number_;\n}\n\nint User::age() const { \n  if (data.year == 0 && data.month == 0 && data.day == 0) {\n    // If the birthday is unset, then the age is also unset.\n    return 0;\n  }\n  SystemClock clock{};\n  return years_old(this, clock);\n}\n\n[[nodiscard]] std::string User::birthday_month_dd_yyyy() const {\n  static const char* mon[] = {\"January\",   \"February\", \"March\",    \"April\",\n                              \"May\",       \"June\",     \"July\",     \"August\",\n                              \"September\", \"October\",  \"November\", \"December\"};\n  return fmt::format(\"{} {}, {}\", mon[birthday_month() - 1], birthday_mday(), birthday_year());\n}\n\n[[nodiscard]] std::string User::birthday_mmddyy() const {\n  return fmt::format(\"{:02}/{:02}/{:02}\", data.month, data.day, data.year);\n}\n\nstd::string User::mailbox_state() const {\n  if (forward_systemnum() == 0 &&\n      forward_usernum() == 0) {\n    return \"Normal\";\n  }\n  if (forward_systemnum() != 0) {\n    if (mailbox_forwarded()) {\n      return fmt::format(\"Forward to #{} @{}\", forward_usernum(), forward_systemnum());\n    }\n    return StrCat(\"Forwarded to: \", email_address());\n  }\n\n  if (mailbox_closed()) {\n    return \"Closed\";\n  }\n\n  return StrCat(\"Forward to: User #\", forward_usernum());\n}\n\nvoid ResetTodayUserStats(User* u) {\n  u->data.ontoday = 0;\n  u->data.timeontoday = 0;\n  u->data.extratime = 0.0;\n  u->posts_today(0);\n  u->email_today(0);\n  u->feedback_today(0);\n}\n\nint AddCallToday(User* u) { \n  u->increment_logons(); \n  return ++u->data.ontoday;\n}\n\nvoid User::birthday_mdy(int m, int d, int y) {\n  data.month = static_cast<uint8_t>(m);\n  data.day = static_cast<uint8_t>(d);\n  if (y == 0) {\n    data.year = 0;\n  } else {\n    data.year = static_cast<uint8_t>(y - 1900);\n  }\n}\n\nint years_old(const User* u, Clock& clock) {\n  return core::years_old(u->birthday_month(), u->birthday_mday(), \n                         u->birthday_year(), clock);\n}\n\nfloat User::ratio() const {\n  if (dk() == 0) {\n    return 99.999f;\n  }\n  const auto r = static_cast<float>(uk()) / static_cast<float>(dk());\n  return std::max<float>(99.998f, r);\n}\n\n} // namespace wwiv::sdk\n"
  },
  {
    "path": "sdk/user.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_USER_H\n#define INCLUDED_SDK_USER_H\n\n#include \"core/datetime.h\"\n#include \"core/ip_address.h\"\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/net/net.h\"\n\n#include <chrono>\n#include <cstdint>\n#include <cstring>\n#include <string>\n#include <vector>\n\n//\n// ListPlus options from lp_options.\n//\nstatic constexpr uint32_t cfl_fname = 0x00000001;\nstatic constexpr uint32_t cfl_extension = 0x00000002;\nstatic constexpr uint32_t cfl_dloads = 0x00000004;\nstatic constexpr uint32_t cfl_kbytes = 0x00000008;\nstatic constexpr uint32_t cfl_date_uploaded = 0x00000010;\nstatic constexpr uint32_t cfl_file_points = 0x00000020;\nstatic constexpr uint32_t cfl_days_old = 0x00000040;\nstatic constexpr uint32_t cfl_upby = 0x00000080;\nstatic constexpr uint32_t unused_cfl_times_a_day_dloaded = 0x00000100;\nstatic constexpr uint32_t unused_cfl_days_between_dloads = 0x00000200;\nstatic constexpr uint32_t cfl_description = 0x00000400;\nstatic constexpr uint32_t cfl_header = 0x80000000;\nstatic constexpr uint32_t cfl_enable = 0x10000000;\n\nnamespace wwiv::sdk {\nstruct validation_config_t;\n\n/**\n * User Class - Represents a User record\n */\nclass User final {\n public:\n  //\n  // Constructor and Destructor\n  //\n  User();\n  ~User() = default;\n\n  User(const User& w);\n  User(User&& u) noexcept;\n  User(const userrec& rhs, int user_number);\n  User& operator=(const User& rhs);\n  User& operator=(User&& rhs) noexcept;\n\n  // Constants\n\n  // USERREC.inact\n  static constexpr int userDeleted                = 0x01;\n  static constexpr int userInactive               = 0x02;\n\n  // USERREC.exempt\n  static constexpr int exemptRatio                = 0x01;\n  static constexpr int exemptTime                 = 0x02;\n  static constexpr int exemptPost                 = 0x04;\n  static constexpr int exemptAll                  = 0x08;\n  static constexpr int exemptAutoDelete           = 0x10;\n\n  // USERREC.restrict\n  static constexpr int restrictLogon              = 0x0001;\n  static constexpr int restrictChat               = 0x0002;\n  static constexpr int restrictValidate           = 0x0004;\n  static constexpr int restrictAutomessage        = 0x0008;\n  static constexpr int restrictAnony              = 0x0010;\n  static constexpr int restrictPost               = 0x0020;\n  static constexpr int restrictEmail              = 0x0040;\n  static constexpr int restrictVote               = 0x0080;\n  static constexpr int restrictMultiNodeChat      = 0x0100;\n  static constexpr int restrictNet                = 0x0200;\n  static constexpr int restrictUpload             = 0x0400;\n\n  // USERREC.sysstatus\n  static constexpr int flag_ansi                  = 0x00000001;\n  static constexpr int status_color               = 0x00000002;\n  static constexpr int flag_music                 = 0x00000004;\n  static constexpr int pauseOnPage                = 0x00000008;\n  static constexpr int flag_expert                = 0x00000010;\n  static constexpr int SMW                        = 0x00000020;\n  static constexpr int fullScreen                 = 0x00000040;\n  static constexpr int nscanFileSystem            = 0x00000080;\n  static constexpr int extraColor                 = 0x00000100;\n  static constexpr int clearScreen                = 0x00000200;\n  static constexpr int msg_show_controlcodes      = 0x00000400;\n  static constexpr int unused_noTag               = 0x00000800;\n  static constexpr int conference                 = 0x00001000;\n  static constexpr int noChat                     = 0x00002000;\n  static constexpr int noMsgs                     = 0x00004000;\n  static constexpr int fullScreenReader           = 0x00008000;\n  static constexpr int unused_listPlus            = 0x00010000;\n  static constexpr int autoQuote                  = 0x00020000;\n  static constexpr int twentyFourHourClock        = 0x00040000;\n  static constexpr int msgPriority                = 0x00080000;  // not used?\n\n  //\n  // Data\n  //\n  struct userrec data{};\n  int user_number_{-1};\n\n  //\n  // Member Functions\n  //\n  void FixUp();    // was function fix_user_rec\n  void ZeroUserData();\n\n  //\n  // Accessor Functions\n  //\n\n  // USERREC.inact\n  void set_inact(int flag) {\n    data.inact |= flag;\n  }\n  void clear_inact(int flag) {\n    data.inact &= ~flag;\n  }\n\n  [[nodiscard]] bool deleted() const {\n    return (data.inact & userDeleted) != 0;\n  }\n  [[nodiscard]] bool inactive() const {\n    return (data.inact & userInactive) != 0;\n  }\n\n  /**\n   * Is this the guest user.\n   */\n  [[nodiscard]] bool guest_user() const;\n\n  // USERREC.sysstatus\n  void set_flag(int flag, bool on) {\n    if (on) {\n      data.sysstatus |= flag;\n    } else {\n      data.sysstatus &= ~flag;\n    }\n  }\n  void set_flag(int flag) {\n    data.sysstatus |= flag;\n  }\n  void toggle_flag(int flag) {\n    data.sysstatus ^= flag;\n  }\n  void clear_flag(int flag) {\n    data.sysstatus &= ~flag;\n  }\n\n  [[nodiscard]] bool has_flag(int flag) const {\n    return (data.sysstatus & flag) != 0;\n  }\n\n  [[nodiscard]] long get_status() const {\n    return static_cast<long>(data.sysstatus);\n  }\n\n  void SetStatus(long l) {\n    data.sysstatus = static_cast<uint32_t>(l);\n  }\n\n  [[nodiscard]] bool ansi() const {\n    return has_flag(flag_ansi);\n  }\n  [[nodiscard]] bool color() const { return has_flag(status_color); }\n\n  [[nodiscard]] bool music() const {\n    return has_flag(flag_music);\n  }\n\n  [[nodiscard]] bool pause() const {\n    return has_flag(pauseOnPage);\n  }\n\n  [[nodiscard]] bool IsExpert() const {\n    return has_flag(flag_expert);\n  }\n\n  [[nodiscard]] bool ssm() const {\n    return has_flag(SMW);\n  }\n\n  [[nodiscard]] bool fullscreen() const {\n    return has_flag(fullScreen);\n  }\n  [[nodiscard]] bool newscan_files() const {\n    return has_flag(nscanFileSystem);\n  }\n  [[nodiscard]] bool extra_color() const {\n    return has_flag(extraColor);\n  }\n  [[nodiscard]] bool clear_screen() const {\n    return has_flag(clearScreen);\n  }\n  [[nodiscard]] bool use_conference() const {\n    return has_flag(conference);\n  }\n  [[nodiscard]] bool nochat() const {\n    return has_flag(noChat);\n  }\n  [[nodiscard]] bool ignore_msgs() const {\n    return has_flag(noMsgs);\n  }\n\n  [[nodiscard]] bool auto_quote() const {\n    return has_flag(autoQuote);\n  }\n  [[nodiscard]] bool twentyfour_clock() const {\n    return has_flag(twentyFourHourClock);\n  }\n\n  [[nodiscard]] bool exempt_ratio() const {\n    return HasExemptFlag(exemptRatio);\n  }\n\n  [[nodiscard]] bool exempt_time() const {\n    return HasExemptFlag(exemptTime);\n  }\n\n  [[nodiscard]] bool exempt_post() const {\n    return HasExemptFlag(exemptPost);\n  }\n\n  [[nodiscard]] bool exempt_all() const {\n    return HasExemptFlag(exemptAll);\n  }\n\n  [[nodiscard]] bool exempt_auto_delete() const {\n    return HasExemptFlag(exemptAutoDelete);\n  }\n\n  // USERREC.restrict\n  void set_restrict(int flag) noexcept {\n    data.restrict |= flag;\n  }\n\n  void toggle_restrict(int flag) noexcept {\n    data.restrict ^= flag;\n  }\n\n  void clear_restrict(int flag) noexcept {\n    data.restrict &= ~flag;\n  }\n\n  [[nodiscard]] bool has_restrict(int flag) const noexcept {\n    return (data.restrict & flag) != 0;\n  }\n\n  [[nodiscard]] uint16_t restriction() const {\n    return data.restrict;\n  }\n\n  void restriction(uint16_t n) {\n    data.restrict = n;\n  }\n\n  [[nodiscard]] bool restrict_logon() const {\n    return has_restrict(restrictLogon);\n  }\n\n  [[nodiscard]] bool restrict_chat() const {\n    return has_restrict(restrictChat);\n  }\n\n  [[nodiscard]] bool restrict_validate() const {\n    return has_restrict(restrictValidate);\n  }\n\n  [[nodiscard]] bool restrict_automessage() const {\n    return has_restrict(restrictAutomessage);\n  }\n\n  [[nodiscard]] bool restrict_anony() const {\n    return has_restrict(restrictAnony);\n  }\n  [[nodiscard]] bool restrict_post() const {\n    return has_restrict(restrictPost);\n  }\n\n  [[nodiscard]] bool restrict_email() const {\n    return has_restrict(restrictEmail);\n  }\n\n  [[nodiscard]] bool restrict_vote() const {\n    return has_restrict(restrictVote);\n  }\n\n  [[nodiscard]] bool restrict_iichat() const {\n    return has_restrict(restrictMultiNodeChat);\n  }\n\n  [[nodiscard]] bool restrict_net() const {\n    return has_restrict(restrictNet);\n  }\n\n  [[nodiscard]] bool restrict_upload() const {\n    return has_restrict(restrictUpload);\n  }\n\n  void toggle_ar(int flag) {\n    data.ar ^= flag;\n  }\n\n  [[nodiscard]] bool has_ar(int ar) const {\n    if (ar == 0) {\n      // Always have the empty ar\n      return true;\n    }\n    return (data.ar & ar) != 0;\n  }\n\n  [[nodiscard]] int ar_int() const {\n    return data.ar;\n  }\n\n  void ar_int(int n) {\n    data.ar = static_cast<uint16_t>(n);\n  }\n\n  void toggle_dar(int flag) {\n    data.dar ^= flag;\n  }\n\n  [[nodiscard]] bool has_dar(int flag) const {\n    if (flag == 0) {\n      // Always have the empty dar\n      return true;\n    }\n    return (data.dar & flag) != 0;\n  }\n\n  [[nodiscard]] int dar_int() const {\n    return data.dar;\n  }\n\n  void dar_int(int n) {\n    data.dar = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] const char *GetName() const {\n    return reinterpret_cast<const char*>(data.name);\n  }\n\n  [[nodiscard]] std::string name() const {\n    return std::string(reinterpret_cast<const char*>(data.name));\n  }\n\n  /**\n   * Returns the user's name and number formatted canonically like:\n   * \"Trader Jack #1\"\n   */\n  [[nodiscard]] std::string name_and_number() const;\n\n  /**\n   * Returns the user's number. \n   * Note: This only works if the user record was loaded from the UserManager class,\n   * otherwise will return -1.\n   */\n  [[nodiscard]] int usernum() const noexcept;\n\n  void set_name(const std::string& s) {\n    strcpy(reinterpret_cast<char*>(data.name), s.c_str());\n  }\n\n  /**\n   * Returns the real name if exists, or handle if no real name exists.\n   */\n  [[nodiscard]] std::string real_name() const {\n    const auto rn = std::string(reinterpret_cast<const char*>(data.realname));\n    return rn.empty() ? name() : rn;\n  }\n\n  /**\n   * Returns the real name if exists, or an empty string if none exists.\n   */\n  [[nodiscard]] std::string real_name_or_empty() const {\n    return std::string(reinterpret_cast<const char*>(data.realname));\n  }\n\n  /**\n   * Sets the real name for this user, use an empty string if none exists.\n   */\n  void real_name(const std::string& s) {\n    strcpy(reinterpret_cast<char*>(data.realname), s.c_str());\n  }\n\n  [[nodiscard]] std::string callsign() const {\n    return std::string(data.callsign);\n  }\n\n  void callsign(const std::string& s) {\n    strcpy(data.callsign, s.c_str());\n  }\n\n  [[nodiscard]] std::string voice_phone() const {\n    return data.phone;\n  }\n  void voice_phone(const std::string& s) {\n    strings::to_char_array(data.phone, s);\n  }\n\n  [[nodiscard]] std::string data_phone() const {\n    return data.dataphone;\n  }\n  void data_phone(const std::string& s) {\n    strings::to_char_array(data.dataphone, s);\n  }\n\n  [[nodiscard]] std::string street() const {\n    return data.street;\n  }\n  void street(const std::string& s) {\n    strings::to_char_array(data.street, s);\n  }\n  [[nodiscard]] std::string city() const {\n    return data.city;\n  }\n  void city(const std::string& s) {\n    strings::to_char_array(data.city, s);\n  }\n  [[nodiscard]] std::string state() const {\n    return data.state;\n  }\n  void state(const std::string& s) {\n    strings::to_char_array(data.state, s);\n  }\n\n  [[nodiscard]] std::string country() const {\n    return data.country;\n  }\n  void country(const std::string& s) {\n    strings::to_char_array(data.country, s);\n  }\n\n  [[nodiscard]] std::string zip_code() const {\n    return data.zipcode;\n  }\n  void zip_code(const std::string& s) {\n    strings::to_char_array(data.zipcode, s);\n  }\n\n  [[nodiscard]] std::string password() const {\n    return std::string(data.pw);\n  }\n  void password(const std::string& s) {\n    strings::to_char_array(data.pw, s);\n  }\n\n  [[nodiscard]] std::string laston() const {\n    return data.laston;\n  }\n\n  void laston(const std::string& s) {\n    strings::to_char_array(data.laston, s);\n  }\n\n  [[nodiscard]] std::string firston() const {\n    return data.firston;\n  }\n  \n  void firston(const std::string& s) {\n    strings::to_char_array(data.firston, s);\n  }\n\n  [[nodiscard]] std::string note() const {\n    return reinterpret_cast<const char*>(data.note);\n  }\n  void note(const std::string& s) {\n    strcpy(data.note, s.c_str());\n  }\n\n  [[nodiscard]] std::string macro(int line) const {\n    return std::string(reinterpret_cast<const char*>(data.macros[line]));\n  }\n  void macro(int nLine, const char *s) {\n    memset(&data.macros[ nLine ][0], 0, 80);\n    strcpy(reinterpret_cast<char*>(data.macros[ nLine ]), s);\n  }\n\n  [[nodiscard]] char gender() const {\n    if (data.sex == 'N') {\n      // N means unknown.  NEWUSER sets it to N to prompt the\n      // user again.\n      return 'N';\n    }\n    return data.sex == 'F' ? 'F' : 'M';\n  }\n  void gender(const char c) {\n    data.sex = static_cast<uint8_t>(c);\n  }\n\n  [[nodiscard]] std::string email_address() const {\n    return data.email;\n  }\n  void email_address(const std::string& s) {\n    strcpy(data.email, s.c_str());\n  }\n\n  [[nodiscard]] int age() const;\n\n  [[nodiscard]] int8_t computer_type() const {\n    return data.comp_type;\n  }\n  void computer_type(int n) {\n    data.comp_type = static_cast<int8_t>(n);\n  }\n\n  [[nodiscard]] int default_protocol() const {\n    return data.defprot;\n  }\n  void default_protocol(int n) {\n    data.defprot = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int default_editor() const {\n    return data.defed;\n  }\n  void default_editor(int n) {\n    data.defed = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int screen_width() const {\n    return data.screenchars == 0 ? 80 : data.screenchars;\n  }\n  void screen_width(int n) {\n    data.screenchars = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int screen_lines() const {\n    return data.screenlines == 0 ? 25 : data.screenlines;\n  }\n  void screen_lines(int n) {\n    data.screenlines = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int GetNumExtended() const {\n    return data.num_extended;\n  }\n  void SetNumExtended(int n) {\n    data.num_extended = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int optional_val() const {\n    return data.optional_val;\n  }\n  void optional_val(int n) {\n    data.optional_val = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int sl() const {\n    return data.sl;\n  }\n  void sl(int n) {\n    data.sl = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int dsl() const {\n    return data.dsl;\n  }\n  void dsl(int n) {\n    data.dsl = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int exempt() const {\n    return data.exempt;\n  }\n  void exempt(int n) {\n    data.exempt = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int raw_color(int n) const {\n    if (n < 0 || n > 9) {\n      return 7; // default color\n    }\n    return data.colors[n];\n  }\n\n  /**\n   * Gets the color number n for this user.  Respects if ansi colors\n   * is enabled or not.\n   */\n  [[nodiscard]] uint8_t color(int n) const { \n    if (n < 0 || n > 9) {\n      return 7; // default color\n    }\n    return static_cast<uint8_t>(ansi() ? raw_color(n) : bwcolor(n));\n  }\n\n  [[nodiscard]] std::vector<uint8_t> colors() const { \n    std::vector<uint8_t> c;\n    for (auto i = 0; i < 10; i++) {\n      if (color()) {\n        c.push_back(data.colors[i]);\n      } else {\n        c.push_back(data.bwcolors[i]);\n      }\n    }\n    return c;\n  }\n  void color(int nColor, unsigned int n) {\n    data.colors[nColor] = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] uint8_t bwcolor(int n) const {\n    if (n < 0 || n > 9) {\n      return 7; // default color\n    }\n    return data.bwcolors[n];\n  }\n  void bwcolor(int nColor, unsigned int n) {\n    data.bwcolors[nColor] = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int votes(int vote_num) const {\n    return data.votes[vote_num];\n  }\n  void votes(int vote_num, int n) {\n    data.votes[vote_num] = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int illegal_logons() const {\n    return data.illegal;\n  }\n  void illegal_logons(int n) {\n    data.illegal = static_cast<uint8_t>(n);\n  }\n  void increment_illegal_logons() {\n    if (data.illegal < std::numeric_limits<decltype(data.illegal)>::max()) {\n      ++data.illegal;      \n    }\n  }\n\n  [[nodiscard]] int email_waiting() const {\n    return data.waiting;\n  }\n  void email_waiting(unsigned int n) {\n    data.waiting = static_cast<uint8_t>(n);\n  }\n\n  [[nodiscard]] int ontoday() const {\n    return data.ontoday;\n  }\n\n  /** \n   * Sets the birthday to month m (1-12), day d (1-31), \n   * year y (full 4 year date)\n   */\n  void birthday_mdy(int m, int d, int y);\n\n  /** Gets the current user's birthday month (1-12) */\n  [[nodiscard]] int birthday_month() const {\n    return data.month;\n  }\n\n  /** Gets the current user's birthday day of the month (1-31) */\n  [[nodiscard]] int birthday_mday() const {\n    return data.day;\n  }\n\n  /** Gets the current user's birthday year (i.e. 1990) */\n  [[nodiscard]] int birthday_year() const {\n    return data.year + 1900;\n  }\n\n  /**\n   * @brief Returns the current user's birthday as \"Month DD, YYYY\".\n   * @return String of user's birthday as \"Month DD, YYYY\".\n  */\n  [[nodiscard]] std::string birthday_month_dd_yyyy() const;\n\n  /** Gets the current user's birthday as a string in format \"mm/dd/yy\" */\n  [[nodiscard]] std::string birthday_mmddyy() const;\n\n  [[nodiscard]] int home_usernum() const {\n    return data.homeuser;\n  }\n\n  void home_usernum(int n) {\n    data.homeuser = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] uint16_t home_systemnum() const {\n    return data.homesys;\n  }\n  void home_systemnum(uint16_t n) {\n    data.homesys = n;\n  }\n\n  [[nodiscard]] uint16_t forward_usernum() const {\n    return data.forwardusr;\n  }\n  void forward_usernum(uint16_t n) {\n    data.forwardusr = n;\n  }\n\n  [[nodiscard]] uint16_t forward_systemnum() const {\n    return data.forwardsys;\n  }\n  void forward_systemnum(uint16_t n) {\n    data.forwardsys = n;\n  }\n\n  [[nodiscard]] int forward_netnum() const {\n    return data.net_num;\n  }\n  void forward_netnum(int n) {\n    data.net_num = static_cast<uint16_t>(n);\n  }\n\n  /** Gets a text description of the mailbox state */\n  [[nodiscard]] std::string mailbox_state() const;\n\n  [[nodiscard]] int messages_posted() const {\n    return data.msgpost;\n  }\n  void messages_posted(int n) {\n    data.msgpost = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int email_sent() const {\n    return data.emailsent;\n  }\n  void email_sent(int n) {\n    data.emailsent = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int feedback_sent() const {\n    return data.feedbacksent;\n  }\n  void feedback_sent(int n) {\n    data.feedbacksent = static_cast<uint16_t>(n);\n  }\n  [[nodiscard]] int feedback_today() const {\n    return data.fsenttoday1;\n  }\n\n  void feedback_today(int n) {\n    data.fsenttoday1 = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int posts_today() const {\n    return data.posttoday;\n  }\n  void posts_today(int n) {\n    data.posttoday = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int email_today() const {\n    return data.etoday;\n  }\n  void email_today(int n) {\n    data.etoday = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int ass_points() const {\n    return data.ass_pts;\n  }\n  void ass_points(int n) {\n    data.ass_pts = static_cast<uint16_t>(n);\n  }\n  void increment_ass_points(int n) {\n    data.ass_pts = data.ass_pts + static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] int uploaded() const {\n    return data.uploaded;\n  }\n  void uploaded(int n) {\n    data.uploaded = static_cast<uint16_t>(n);\n  }\n  void increment_uploaded() {\n    ++data.uploaded;\n  }\n\n  void decrement_uploaded() {\n    --data.uploaded;\n  }\n\n  [[nodiscard]] int downloaded() const {\n    return data.downloaded;\n  }\n  void downloaded(int n) {\n    data.downloaded = static_cast<uint16_t>(n);\n  }\n  void increment_downloaded() {\n    ++data.downloaded;\n  }\n  void decrement_downloaded() {\n    --data.downloaded;\n  }\n\n  [[nodiscard]] uint16_t last_bps() const {\n    return data.lastrate;\n  }\n  void last_bps(int n) {\n    data.lastrate = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] uint16_t logons() const {\n    return data.logons;\n  }\n  void increment_logons() { ++data.logons; }\n\n  void logons(int n) {\n    data.logons = static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] uint16_t email_net() const {\n    return data.emailnet;\n  }\n  void email_net(uint16_t n) {\n    data.emailnet = n;\n  }\n\n  [[nodiscard]] uint16_t posts_net() const {\n    return data.postnet;\n  }\n  void posts_net(uint16_t n) {\n    data.postnet = n;\n  }\n\n  [[nodiscard]] uint16_t deleted_posts() const {\n    return data.deletedposts;\n  }\n  void deleted_posts(uint16_t n) {\n    data.deletedposts = n;\n  }\n\n  [[nodiscard]] uint16_t chains_run() const {\n    return data.chainsrun;\n  }\n  void chains_run(uint16_t n) {\n    data.chainsrun = n;\n  }\n\n  [[nodiscard]] uint16_t gfiles_read() const {\n    return data.gfilesread;\n  }\n  void gfiles_read(uint16_t n) {\n    data.gfilesread = n;\n  }\n\n  [[nodiscard]] uint16_t banktime_minutes() const {\n    return data.banktime;\n  }\n  void banktime_minutes(uint16_t n) {\n    data.banktime = n;\n  }\n  void add_banktime_minutes(int n) {\n    data.banktime += static_cast<uint16_t>(n);\n  }\n  void subtract_banktime_minutes(int n) {\n    data.banktime -= static_cast<uint16_t>(n);\n  }\n\n  [[nodiscard]] uint16_t home_netnum() const {\n    return data.homenet;\n  }\n  void home_netnum(uint16_t n) {\n    data.homenet = n;\n  }\n\n  [[nodiscard]] uint16_t subconf() const {\n    return data.subconf;\n  }\n  void subconf(uint16_t n) {\n    data.subconf = n;\n  }\n\n  [[nodiscard]] uint16_t dirconf() const {\n    return data.dirconf;\n  }\n  void dirconf(uint16_t n) {\n    data.dirconf = n;\n  }\n\n  [[nodiscard]] uint16_t subnum() const {\n    return data.subnum;\n  }\n  void subnum(uint16_t n) {\n    data.subnum = n;\n  }\n\n  [[nodiscard]] uint16_t dirnum() const {\n    return data.dirnum;\n  }\n  void dirnum(uint16_t n) {\n    data.dirnum = n;\n  }\n\n  [[nodiscard]] uint32_t messages_read() const {\n    return data.msgread;\n  }\n  void messages_read(uint32_t l) {\n    data.msgread = l;\n  }\n\n  [[nodiscard]] uint32_t uk() const {\n    return data.uk;\n  }\n  void set_uk(uint32_t l) {\n    data.uk = l;\n  }\n\n  [[nodiscard]] uint32_t dk() const {\n    return data.dk;\n  }\n  void set_dk(uint32_t l) {\n    data.dk = l;\n  }\n\n  [[nodiscard]] daten_t last_daten() const {\n    return data.daten;\n  }\n  void last_daten(daten_t l) {\n    data.daten = l;\n  }\n\n  [[nodiscard]] uint32_t wwiv_regnum() const {\n    return data.wwiv_regnum;\n  }\n  void wwiv_regnum(uint32_t l) {\n    data.wwiv_regnum = l;\n  }\n\n  [[nodiscard]] daten_t nscan_daten() const {\n    return data.datenscan;\n  }\n  void nscan_daten(daten_t l) {\n    data.datenscan = l;\n  }\n\n  /** Adds extra time to the user, returns the new total extra time. */\n  std::chrono::seconds add_extratime(std::chrono::duration<double> extra);\n  \n  /** Subtracts extra time to the user, returns the new total extra time. */\n  std::chrono::seconds subtract_extratime(std::chrono::duration<double> extra);\n\n  /** Total extra time awarded to this user */\n  [[nodiscard]] std::chrono::duration<double> extra_time() const noexcept;\n  \n  /** Time online in total, in seconds */\n  [[nodiscard]] std::chrono::seconds timeon() const;\n  \n  /** Time online today, in seconds */\n  [[nodiscard]] std::chrono::seconds timeontoday() const;\n  \n  /** Add 'd' to the time online in total */\n  std::chrono::seconds add_timeon(std::chrono::duration<double> d);\n  \n  /** Add 'd' to the time online for today */\n  std::chrono::seconds add_timeon_today(std::chrono::duration<double> d);\n\n  /** Returns the time on as seconds. */\n  [[nodiscard]] float gold() const {\n    return data.gold;\n  }\n  void gold(float f) {\n    data.gold = f;\n  }\n\n  [[nodiscard]] bool full_descriptions() const {\n    return data.full_desc ? true : false;\n  }\n  void full_descriptions(bool b) {\n    data.full_desc = b ? 1 : 0;\n  }\n\n  [[nodiscard]] bool mailbox_closed() const { return forward_usernum() == 65535; }\n\n  /**\n   * Close the user's email inbox to disallow receiving emails.\n   */\n  void close_mailbox() {\n    forward_systemnum(0);\n    forward_usernum(65535);\n  }\n\n  [[nodiscard]] bool forwarded_to_internet() const {\n    return forward_usernum() == net::INTERNET_EMAIL_FAKE_OUTBOUND_NODE;\n  }\n\n  [[nodiscard]] bool mailbox_forwarded() const {\n    return forward_usernum() > 0 && forward_usernum() < net::INTERNET_EMAIL_FAKE_OUTBOUND_NODE;\n  }\n\n  void clear_mailbox_forward() {\n    forward_systemnum(0);\n    forward_usernum(0);\n  }\n\n  /** Sets the last IP address from which this user connected. */\n  void last_address(const core::ip_address& a) { data.last_address = a; }\n\n  /** Returns the last IP address from which this user connected. */\n  [[nodiscard]] core::ip_address last_address() const { return data.last_address; }\n\n  /**\n   * Creates a random password in the user's password field.\n   */\n  bool CreateRandomPassword();\n\n  /** Should this user use hot keys? */\n  [[nodiscard]] bool hotkeys() const;\n  void set_hotkeys(bool enabled);\n\n  /** Returns the name of the current menu set for the user. */\n  [[nodiscard]] std::string menu_set() const;\n  \n  /** \n   * Sets the current menu set on the user record.\n   * \n   * Note: This does not validate the menuset or perform any checking. Callers\n   * should use ConfigUserMenuSet(...) to set the menuset, as that will\n   * validate the menuset and optionally query the user for an appropriate\n   * menuset should the selected one not exist or is not available.\n   */\n  void set_menu_set(const std::string& menu_set);\n\n  bool asv(const validation_config_t& v);\n\n  /**\n   * Returns the upload/download ratio.\n   */\n  [[nodiscard]] float ratio() const;\n\n  ///////////////////////////////////////////////////////////////////////////\n  // Static Helper Methods\n\n  /** Creates a new user record in 'u' using the default values passed */\n  static bool CreateNewUserRecord(User* u,\n    uint8_t sl, uint8_t dsl, uint16_t restr, float gold,\n    const std::vector<uint8_t>& newuser_colors,\n    const std::vector<uint8_t>& newuser_bwcolors);\n\nprivate:\n  // USERREC.exempt\n  [[nodiscard]] bool HasExemptFlag(int flag) const {\n    return (data.exempt & flag) != 0;\n  }\n\n};\n\n/** Reset today's user statistics for user u */\nvoid ResetTodayUserStats(User* u);\n\n/** Increments both the total calls and today's call stats for user 'u' */\nint AddCallToday(User* u);\n\n/** Returns the age in years for user 'u' */\nint years_old(const User* u, core::Clock& clock);\n\n\n}  // namespace wwiv::sdk\n\n#endif\n"
  },
  {
    "path": "sdk/user_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*           Copyright (C)2007-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/fake_clock.h\"\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::sdk;\n\nTEST(UserTest, Birthday) {\n  User u;\n  u.birthday_mdy(2, 15, 1980);\n\n  EXPECT_EQ(\"02/15/80\", u.birthday_mmddyy());\n}\n\nTEST(UserTest, YearsOld) {\n  tm t{};\n  t.tm_mon = 9;\n  t.tm_mday = 25;\n  t.tm_year = 120;\n  const auto now = wwiv::core::DateTime::from_tm(&t);\n  wwiv::core::FakeClock clock(now);\n  User u{};\n  u.birthday_mdy(10, 24, 1970);\n  EXPECT_EQ(50, years_old(&u, clock));\n}\n\nTEST(UserAsvTest, SL) {\n  User u{};\n  u.sl(10);\n\n  const validation_config_t v{\"\", 20, 0, 0, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(20, u.sl());\n}\n\nTEST(UserAsvTest, SL_Lower) {\n  User u{};\n  u.sl(50);\n\n  const validation_config_t v{\"\", 20, 0, 0, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(50, u.sl());\n}\n\nTEST(UserAsvTest, DSL) {\n  User u{};\n  u.dsl(30);\n\n  const validation_config_t v{\"\", 20, 50, 0, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(50, u.dsl());\n}\n\nTEST(UserAsvTest, DSL_Lower) {\n  User u{};\n  u.dsl(50);\n\n  const validation_config_t v{\"\", 20, 30, 0, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(50, u.dsl());\n}\n\nUser CreateUser(int sl, int dsl, int ar, int dar, uint16_t r) {\n  User u{};\n  u.sl(sl);\n  u.dsl(dsl);\n  u.ar_int(ar);\n  u.dar_int(dar);\n  u.restriction(r);\n  return u;\n}\n\nTEST(UserAsvTest, AR) {\n  User u = CreateUser(10, 0, 1, 0, 0);\n\n  const validation_config_t v{\"\", 20, 0, 4, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(5, u.ar_int());\n}\n\nTEST(UserAsvTest, AR_Lower) {\n  User u = CreateUser(10, 0, 1, 0, 0);\n\n  const validation_config_t v{\"\", 10, 0, 3, 0, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(3, u.ar_int());\n}\n\nTEST(UserAsvTest, DAR) {\n  User u = CreateUser(10, 0, 0, 1, 0);\n\n  const validation_config_t v{\"\", 20, 0, 0, 4, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(5, u.dar_int());\n}\n\nTEST(UserAsvTest, DAR_Lower) {\n  User u = CreateUser(10, 0, 0, 1, 0);\n\n  const validation_config_t v{\"\", 10, 0, 0, 3, 0};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(3, u.dar_int());\n}\n\nTEST(UserAsvTest, Restrict) {\n  auto u = CreateUser(10, 0, 1, 0, 2);\n\n  const validation_config_t v{\"\", 20, 0, 1, 0, 4};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(0, u.restriction());\n}\n\nTEST(UserAsvTest, Restrict_Lower) {\n  auto u = CreateUser(10, 0, 1, 0, 6);\n\n  const validation_config_t v{\"\", 10, 0, 3, 0, 4};\n  ASSERT_TRUE(u.asv(v));\n  EXPECT_EQ(4, u.restriction());\n}"
  },
  {
    "path": "sdk/usermanager.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/usermanager.h\"\n\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/names.h\"\n#include \"sdk/phone_numbers.h\"\n#include \"sdk/ssm.h\"\n#include \"sdk/status.h\"\n#include \"sdk/user.h\"\n#include \"sdk/msgapi/email_wwiv.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include <memory>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk::msgapi;\n\nnamespace wwiv::sdk {\n\n/////////////////////////////////////////////////////////////////////////////\n// class UserManager\n\nUserManager::UserManager(const wwiv::sdk::Config& config)\n  : config_(config),\n    data_directory_(config.datadir()), \n    userrec_length_(config.userrec_length()), \n    max_number_users_(config.max_users()),\n    allow_writes_(true){\n  if (config.versioned_config_dat()) {\n    CHECK_EQ(config.userrec_length(), sizeof(userrec))\n      << \"For WWIV 5.2 or later, we expect the userrec length to match what's written\\r\\n\"\n      << \" in config.dat.\\r\\n\"\n      << \"Please use a version of this tool compiled with your WWIV BBS.\\r\\n\"\n      << \"If you see this message running against a WWIV 4.x instance, it is a bug.\\r\\n\"\n      << \"config.config()->userreclen: \" << config.userrec_length()\n      << \"; sizeof(userrec): \" << sizeof(userrec) << \"\\r\\n\";\n  }\n}\n\nUserManager::~UserManager() = default;\n\nint  UserManager::num_user_records() const {\n  File userList(FilePath(data_directory_, USER_LST));\n  if (userList.Open(File::modeReadOnly | File::modeBinary)) {\n    return static_cast<int>(userList.length() / userrec_length_) - 1;\n  }\n  return 0;\n}\n\nbool UserManager::readuser(User *u, int user_number) const {\n  File file(FilePath(data_directory_, USER_LST));\n  if (!file.Open(File::modeReadOnly | File::modeBinary)) {\n    u->data.inact = User::userDeleted; \n    u->FixUp();\n    u->user_number_ = user_number;\n    return false;\n  }\n  const auto nSize = file.length();\n  const auto num_user_records = nSize / userrec_length_ - 1;\n\n  if (user_number > num_user_records) {\n    u->data.inact = User::userDeleted;\n    u->FixUp();\n    u->user_number_ = user_number;\n    return false;\n  }\n  const auto pos = userrec_length_ * user_number;\n  file.Seek(pos, File::Whence::begin);\n  file.Read(&u->data, userrec_length_);\n  u->FixUp();\n  u->user_number_ = user_number;\n  return true;\n}\n\nstd::optional<User> UserManager::readuser(int user_number, mask m) const {\n  User u{};\n  if (readuser(&u, user_number)) {\n    if (m == mask::active && (u.deleted() || u.inactive())) {\n      return std::nullopt;\n    }\n    if (m == mask::non_deleted && u.deleted()) {\n      return std::nullopt;\n    }\n    if (m == mask::non_inactive && u.inactive()) {\n      return std::nullopt;\n    }\n    return {u};\n  }\n  return std::nullopt;\n}\n\nbool UserManager::writeuser(const User *pUser, int user_number) {\n  if (user_number < 1 || user_number > max_number_users_ || !user_writes_allowed()) {\n    return true;\n  }\n\n  if (File file(FilePath(data_directory_, USER_LST));\n      file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    const auto pos = static_cast<long>(userrec_length_) * static_cast<long>(user_number);\n    file.Seek(pos, File::Whence::begin);\n    file.Write(&pUser->data, userrec_length_);\n    return true;\n  }\n  return false;\n}\n\nbool UserManager::writeuser(const User& user, int user_number) {\n  return writeuser(&user, user_number);\n}\n\nbool UserManager::writeuser(const std::optional<User>& user, int user_number) {\n  if (!user) {\n    return false;\n  }\n  return writeuser(user.value(), user_number);\n}\n\n// Deletes a record from NAMES.LST (DeleteSmallRec)\nstatic void DeleteSmallRecord(StatusMgr& sm, Names& names, const char *name) {\n  int found_user = names.FindUser(name);\n  if (found_user < 1) {\n    LOG(ERROR) << \"#*#*#*#*#*#*#*# '\" << name << \"' NOT ABLE TO BE DELETED\";\n    LOG(ERROR) << \"#*#*#*#*#*#*#*# Run //RESETF to fix it.\";\n    return;\n  }\n\n  sm.Run([&](Status& s) {\n    names.Remove(found_user);\n    s.decrement_num_users();\n    s.increment_filechanged(Status::file_change_names);\n    names.Save();\n  });\n}\n\n// Inserts a record into NAMES.LST\nstatic void InsertSmallRecord(StatusMgr& sm, Names& names, int user_number, const char *name) {\n  sm.Run([&](Status& s) {\n    names.Add(name, user_number);\n    names.Save();\n    s.increment_num_users();\n    s.increment_filechanged(Status::file_change_names);\n  });\n}\n\nstatic bool delete_votes(const std::filesystem::path& datadir, User& user) {\n  DataFile<votingrec> voteFile(FilePath(datadir, VOTING_DAT),\n                               File::modeReadWrite | File::modeBinary);\n  if (!voteFile) {\n    return false;\n  }\n  std::vector<votingrec> votes;\n  voteFile.ReadVector(votes);\n  const auto num_vote_records = voteFile.number_of_records();\n  for (auto cur_vote = 0; cur_vote < 20; cur_vote++) {\n    if (user.votes(cur_vote)) {\n      if (cur_vote <= num_vote_records) {\n        auto &v = wwiv::stl::at(votes, cur_vote);\n        v.responses[user.votes(cur_vote) - 1].numresponses--;\n      }\n      user.votes(cur_vote, 0);\n    }\n  }\n  voteFile.Seek(0);\n  return voteFile.WriteVector(votes);\n}\n\nstatic bool deluser(int user_number, const Config& config, UserManager& um, \n  StatusMgr& sm, Names& names, WWIVMessageApi& api) {\n  User user;\n  um.readuser(&user, user_number);\n\n  if (user.deleted()) {\n    return true;\n  }\n  SSM ssm(config, um);\n  ssm.delete_local_to_user(user_number);\n  DeleteSmallRecord(sm, names, user.GetName());\n  user.set_inact(User::userDeleted);\n  user.email_waiting(0);\n  {\n    auto email = api.OpenEmail();\n    email->DeleteAllMailToOrFrom(user_number);\n  }\n\n  delete_votes(config.datadir(), user);\n  um.writeuser(&user, user_number);\n\n  // TODO(rushfan): It's unclear if this is really the right place\n  // to do this.  We could go either wya on this, let the caller handle\n  // the other things (like phone numbers), or \n  PhoneNumbers pn(config);\n  if (!pn.IsInitialized()) {\n    return false;\n  }\n  pn.erase(user_number, user.voice_phone());\n  pn.erase(user_number, user.data_phone());\n  return true;\n}\n\nbool UserManager::delete_user(int user_number) {\n  StatusMgr sm(config_.datadir(), [](int) {});\n  Names names(config_);\n  MessageApiOptions options;\n  WWIVMessageApi api(options, config_, {}, new NullLastReadImpl());\n\n  deluser(user_number, config_, *this, sm, names, api);\n  return true;\n}\n\nbool UserManager::restore_user(int user_number) {\n  User user;\n  this->readuser(&user, user_number);\n\n  if (!user.deleted()) {\n    // Not deleted. Nothing to do.\n    return true;\n  }\n\n  StatusMgr sm(config_.datadir(), [](int) {});\n  Names names(config_);\n  InsertSmallRecord(sm, names, user_number, user.GetName());\n  user.clear_inact(User::userDeleted);\n  this->writeuser(&user, user_number);\n\n  PhoneNumbers pn(config_);\n  if (!pn.IsInitialized()) {\n    return false;\n  }\n  pn.insert(user_number, user.voice_phone());\n  pn.insert(user_number, user.data_phone());\n  return true;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "sdk/usermanager.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_USER_MANAGER_H\n#define INCLUDED_USER_MANAGER_H\n\n#include \"sdk/config.h\"\n#include \"sdk/user.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk {\n\n/**\n * WWIV User Manager.\n * \n * Responsible for loading and saving users.\n */\nclass UserManager {\npublic:\n  // active means non_deleted and non_inactive\n  enum class mask { any, non_deleted, non_inactive, active };\n\n  UserManager() = delete;\n   explicit UserManager(const Config& config);\n   virtual ~UserManager();\n   [[nodiscard]] int num_user_records() const;\n   bool readuser(User *user, int user_number) const;\n\n  /**\n    * Optionally returns the user specified by user_number.\n    */\n   [[nodiscard]] std::optional<User> readuser(int user_number, mask m = mask::any) const;\n\n   bool writeuser(const User *pUser, int user_number);\n   bool writeuser(const User &user, int user_number);\n   bool writeuser(const std::optional<User>& user, int user_number);\n\n   bool delete_user(int user_number);\n   bool restore_user(int user_number);\n\n  /**\n   * Setting this to false will disable writing the userrecord to disk.  This should ONLY be false when the\n   * user is the guest user.\n   */\n  void set_user_writes_allowed(bool a) {\n    allow_writes_ = a;\n  }\n\n   [[nodiscard]] bool user_writes_allowed() const {\n    return allow_writes_;\n  }\n\nprivate:\n  const Config config_;\n  const std::filesystem::path data_directory_;\n  int userrec_length_;\n  int max_number_users_;\n  bool allow_writes_{false};\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "sdk/uuid_cereal.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_SDK_UUID_CEREAL_H__\n#define __INCLUDED_SDK_UUID_CEREAL_H__\n\n#include \"cereal/cereal.hpp\"\n#include \"core/uuid.h\"\n\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::core::uuid_t, cereal::specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive>\ninline std::string save_minimal(Archive const&, const wwiv::core::uuid_t& a) {\n  return a.to_string();\n}\n\ntemplate <class Archive>\ninline void load_minimal(Archive const&, wwiv::core::uuid_t& a, const std::string& s) {\n  const auto o = wwiv::core::uuid_t::from_string(s);\n  a = o.value_or(wwiv::core::uuid_t());\n}\n\n}\n#endif // __INCLUDED_SDK_UUID_CEREAL_H__\n"
  },
  {
    "path": "sdk/value/value.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/value/value.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/arword.h\"\n#include \"sdk/user.h\"\n#include \"sdk/acs/eval_error.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace parser;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::value {\n\nAr::Ar(int ar, bool user_side) : ar_(static_cast<uint16_t>(ar)), user_side_(user_side) {}\n\nAr::Ar(char ar) : ar_(static_cast<uint16_t>(1 << (ar - 'A'))) {}\n\nAr::Ar(const std::string& ar, bool user_side) : ar_(str_to_arword(ar)), user_side_(user_side) {}\n\nAr::Ar(const std::string& ar) : ar_(str_to_arword(ar)) {}\n\n\nbool Ar::eq(const Ar& that) const {\n  if (user_side_ && that.user_side_) {\n    DLOG(FATAL) << \"Can not have user side ar on both sides.\";\n    LOG(ERROR) << \"Can not have user side ar on both sides.\";\n    return false;\n  }\n  if (user_side_) {\n    return that.ar_ == 0 || ar_ & that.ar_;\n  }\n  if (that.user_side_) {\n    return that.eq(*this);\n  }\n  DLOG(FATAL) << \"Ar::eq called with no user side.\";\n  LOG(ERROR) << \"Ar::eq called with no user side.\";\n  // Neither is a user side, so return exact match.\n  // Always return true if either side allows everything.\n  return ar_ & that.ar_;\n}\n\nstd::string Ar::as_string() const { return fmt::format(\"Ar({})\", word_to_arstr(ar_, \"\"));  }\n\nint Ar::as_integer() const { return ar_; }\n\nstd::ostream& operator<<(std::ostream& os, const Ar& a) {\n  os << a.as_string();\n  return os;\n}\n\n\nstd::ostream& operator<<(std::ostream& os, const Value& a) {\n  if (a.value_type == ValueType::number) {\n    os << std::any_cast<int>(a.value_);\n  } else if (a.value_type == ValueType::string) {\n    os << std::any_cast<std::string>(a.value_);\n  } else if (a.value_type == ValueType::boolean) {\n    os << (std::any_cast<bool>(a.value_) ? \"true\" : \"false\");\n  } else if (a.value_type == ValueType::ar) {\n    os << std::any_cast<Ar>(a.value_);\n  } else {\n    os << \"[unknown value_ of type: \" << a.value_.type().name() << \"]\";\n  }\n  return os;\n}\n\n//static \nValue Value::eval(Value l, Operator op, Value r) {\n  const auto vt = l.value_type;\n  switch (op) {\n  case Operator::add:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() + r.as_number());\n    }\n    return Value(StrCat(l.as_string(), r.as_string()));\n  case Operator::sub:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() - r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::mul:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() * r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::div:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() / r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::gt:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() > r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::ge:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() >= r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::lt:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() < r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::le:\n    if (vt == ValueType::number) {\n      return Value(l.as_number() <= r.as_number());\n    }\n    LOG(ERROR) << to_string(op) << \" is only allowed on numbers\";\n    break;\n  case Operator::eq: {\n    if (vt == ValueType::number) {\n      return Value(l.as_number() == r.as_number());\n    }\n    if (vt == ValueType::boolean) {\n      return Value(l.as_boolean() == r.as_boolean());\n    }\n    if (vt == ValueType::string) {\n      return Value(iequals(l.as_string(), r.as_string()));\n    }\n    if (vt == ValueType::ar) {\n      return Value(l.as_ar() == r.as_ar());\n    }\n  }\n  break;\n  case Operator::ne: {\n    if (vt == ValueType::number) {\n      return Value(l.as_number() != r.as_number());\n    }\n    if (vt == ValueType::boolean) {\n      return Value(l.as_boolean() != r.as_boolean());\n    }\n    if (vt == ValueType::string) {\n      return Value(!iequals(l.as_string(), r.as_string()));\n    }\n    if (vt == ValueType::ar) {\n      return Value(l.as_ar() != r.as_ar());\n    }\n  }\n  break;\n  case Operator::logical_or:\n    return Value(l.as_boolean() || r.as_boolean());\n  case Operator::logical_and:\n    return Value(l.as_boolean() && r.as_boolean());\n  case Operator::UNKNOWN:\n    return Value(false);\n  }\n  return Value(false);\n}\n\n\nint Value::as_number() const{\n  switch (value_type) {\n  case ValueType::number:\n    return std::any_cast<int>(value_);\n  case ValueType::string:\n    return to_number<int>(std::any_cast<std::string>(value_));\n  case ValueType::boolean: {\n    const auto b = std::any_cast<bool>(value_);\n    return b ? 1 : 0;\n  }\n  case ValueType::ar:\n    return std::any_cast<Ar>(value_).as_integer();\n  case ValueType::unknown:\n    return 0;\n  }\n  return 0;\n}\n\nstd::string Value::as_string() const {\n  switch (value_type) {\n  case ValueType::number:\n    return std::to_string(std::any_cast<int>(value_));\n  case ValueType::string:\n    return std::any_cast<std::string>(value_);\n  case ValueType::boolean: {\n    const auto b = std::any_cast<bool>(value_);\n    return b ? \"true\" : \"false\";\n  }\n  case ValueType::ar:\n    return std::any_cast<Ar>(value_).as_string();\n  case ValueType::unknown:\n    DLOG(FATAL) << \"unknown value type: \" << static_cast<int>(value_type);\n    return \"\";\n  }\n  DLOG(FATAL) << \"unknown value type: \" << static_cast<int>(value_type);\n  return \"\";\n}\n\nbool Value::as_boolean() const {\n  switch (value_type) {\n  case ValueType::string: {\n    const auto s = std::any_cast<std::string>(value_);\n    return iequals(s, \"true\");\n  }\n  case ValueType::number:\n    return std::any_cast<int>(value_) != 0;\n  case ValueType::boolean:\n    return std::any_cast<bool>(value_);\n  case ValueType::ar:\n  case ValueType::unknown:\n    return false;\n  }\n  return false;\n}\n\nAr Value::as_ar() const {\n  switch (value_type) {\n  case ValueType::ar:\n    return std::any_cast<Ar>(value_);\n  case ValueType::boolean:\n  case ValueType::number:\n    // This is not a user value since it didn't come from\n    // the UserProvider.\n    return Ar(0, false);\n  case ValueType::string:\n    return Ar(std::any_cast<std::string>(value_));\n  case ValueType::unknown:\n    DLOG(FATAL) << \"ValueType::unknown\";\n    break;\n  }\n  throw acs::eval_error(fmt::format(\"Unable to coerce valuetype: {} to Ar\", static_cast<int>(value_type)));\n}\n\n\n}"
  },
  {
    "path": "sdk/value/value.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_ACS_VALUE_H\n#define INCLUDED_SDK_ACS_VALUE_H\n\n#include \"core/parser/ast.h\"\n#include \"fmt/format.h\"\n#include \"sdk/user.h\"\n#include <any>\n#include <iostream>\n#include <memory>\n#include <string>\n\nnamespace wwiv::sdk::value {\n\nclass Ar {\npublic:\n  // AR set of multiple AR values.  If user_side is true then\n  // This AR set represents the set of AR values possessed\n  // and the other side represents the AR values required.\n  Ar(int ar, bool user_side);\n  // Don't be explicit so that we can let the equality operators\n  // work easily below.\n  // ReSharper disable once CppNonExplicitConvertingConstructor\n  Ar(char ar);\n  // ReSharper disable once CppNonExplicitConvertingConstructor\n  Ar(const std::string& ar, bool user_side);\n  // ReSharper disable once CppNonExplicitConvertingConstructor\n  Ar(const std::string& ar);\n  // ReSharper disable once CppNonExplicitConvertingConstructor\n  Ar(const char* ar) : Ar(std::string(ar)) {}\n\n  [[nodiscard]] bool eq(const Ar& that) const;\n  [[nodiscard]] std::string as_string() const;\n  [[nodiscard]] int as_integer() const;\n\n  uint16_t ar_;\n  bool user_side_{false};\n};\n\ninline bool operator==(const Ar& lhs, const Ar& rhs) { return lhs.eq(rhs); }\ninline bool operator!=(const Ar& lhs, const Ar& rhs) { return !lhs.eq(rhs); }\nstd::ostream& operator<<(std::ostream& os, const Ar& a);\n\n\nenum class ValueType { unknown, number, string, boolean, ar };\n\nclass Value {\npublic:\n  Value() : value_type(ValueType::unknown) {}\n  explicit Value(bool v) : value_type(ValueType::boolean), value_(std::make_any<bool>(v)) {}\n  explicit Value(int v) : value_type(ValueType::number), value_(std::make_any<int>(v)) {}\n  explicit Value(unsigned v)\n      : value_type(ValueType::number), value_(std::make_any<int>(static_cast<int>(v))) {}\n  explicit Value(const std::string& v) : value_type(ValueType::string), value_(std::make_any<std::string>(v)) {}\n  explicit Value(const char* v) : Value(std::string(v)) {}\n  explicit Value(Ar a) : value_type(ValueType::ar), value_(std::make_any<Ar>(a)) {}\n\n  [[nodiscard]] int as_number() const;\n  [[nodiscard]] std::string as_string() const;\n  [[nodiscard]] bool as_boolean() const;\n  [[nodiscard]] Ar as_ar() const;\n\n  [[nodiscard]] bool is_boolean() const { return value_type == ValueType::boolean; }\n\n  [[nodiscard]] static Value eval(Value l, wwiv::core::parser::Operator op, Value r);\n\n  friend bool operator==(const Ar& lhs, const Ar& rhs);\n  friend bool operator!=(const Ar& lhs, const Ar& rhs);\n  friend std::ostream& operator<<(std::ostream& os, const Value& a);\n\nprivate: \n  ValueType value_type;\n  std::any value_;\n};\n\nstd::ostream& operator<<(std::ostream& os, const Value& a);\n\n}\n\n// Custom formatter for FidoAddress\ntemplate <> struct fmt::formatter<wwiv::sdk::value::Value> : fmt::formatter<string_view> {\n  // parse is inherited from formatter<string_view>.\n  template <typename FormatContext>\n  auto format(const wwiv::sdk::value::Value& v, FormatContext& ctx) {\n    return formatter<string_view>::format(v.as_string(), ctx);\n  }\n};\n\n#endif\n"
  },
  {
    "path": "sdk/value/valueprovider.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/value/value.h\"\n\n#include \"core/strings.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::core::parser;\nusing namespace wwiv::strings;\n\nnamespace wwiv::sdk::value {\n\n\n}"
  },
  {
    "path": "sdk/value/valueprovider.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_VALUEPROVIDER_VALUEPROIVDER_H\n#define INCLUDED_SDK_VALUEPROVIDER_VALUEPROIVDER_H\n\n#include \"sdk/value/value.h\"\n#include <optional>\n#include <string>\n#include <utility>\n\nnamespace wwiv::sdk::value {\n\n/** Provides a value for an identifier of the form \"object.attribute\" */\nclass ValueProvider {\npublic:\n  explicit ValueProvider(std::string prefix) : prefix_(std::move(prefix)) {}\n  virtual ~ValueProvider() = default;\n\n  /** \n   * Optionally gets the attribute for this object.  name should just be\n   * the 'attribute' and not the full object.attribute name. *\n   */\n  [[nodiscard]] virtual std::optional<Value> value(const std::string& name) const = 0;\n\n  /**\n   * Returns the prefix for this value provider. i.e. \"user\"\n   */\n  [[nodiscard]] std::string prefix() const { return prefix_; }\n\nprivate:\n  const std::string prefix_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "sdk/vardec.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              Wwiv Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#ifndef INCLUDED_SDK_VARDEC_H\n#define INCLUDED_SDK_VARDEC_H\n\n#include \"core/ip_address.h\"\n\n#ifdef __MSDOS__\n#include \"sdk/msdos_stdint.h\"\n#else\n#include <cstddef>\n#include <cstdint>\n#endif // __MSDOS__\n#include <string>\n\n#ifndef __MSDOS__\n#pragma pack(push, 1)\n#endif // __MSDOS__\n\n#ifndef DATEN_T_DEFINED\ntypedef uint32_t daten_t;\n#define DATEN_T_DEFINED\n#endif\n\n// DATA FOR EVERY USER\nstruct userrec {\n  // user's name/handle\n  unsigned char name[31];\n  // user's real name\n  unsigned char realname[21];\n  // user's amateur callsign\n  char callsign[7];\n  // user's phone number\n  char phone[13];\n  // user's data phone\n  char dataphone[13];\n  // street address\n  char street[31];\n  // city\n  char city[31];\n  // state code [MO, CA, etc]\n  char state[3];\n  // country [USA, CAN, FRA, etc]\n  char country[4];\n  // zipcode [#####-####]\n  char zipcode[11];\n  // user's password\n  char pw[9];\n  // last date on\n  char laston[9];\n  // first date on\n  char firston[9];\n  // sysop's note about user\n  char note[61];\n  // macro keys\n  unsigned char macros[3][81];\n  // gender.\n  char sex;\n\n  // Internet mail address\n  char email[65];\n  // bytes for more strings\n  char res_char[13];\n\n  // user's age.  No longer used, instead use User::age()\n  // to get it calculated on demand.\n  uint8_t unused_age;\n  // Flags that specifify if deleted or inactive\n  uint8_t inact;\n\n  // computer type\n  int8_t comp_type;\n\n  uint8_t defprot,  // default transfer protocol\n      defed,        // default editor\n      screenchars,  // screen width\n      screenlines,  // screen height\n      num_extended, // extended description lines\n      optional_val, // optional lines in msgs\n      sl,           // security level\n      dsl,          // transfer security level\n      exempt,       // exempt from ratios, etc\n      colors[10],   // user's colors\n      bwcolors[10], // user's b&w colors\n      votes[20],    // user's votes\n      illegal,      // illegal logons\n      waiting,      // number mail waiting\n      ontoday,      // num times on today\n      month,        // birth month\n      day,          // birth day\n      year,         // birth year\n      // language to use. This has been replaced by using the language\n      // associated with the menuset.\n      unused_language,\n      // Previously use to indicate that this user has been called back\n      // and validated.\n      unused_cbv;   \n\n  // In 4.3 these were part of the separate user config file\n  // and moved into userrec in 5.x.\n  uint32_t lp_options;\n  uint8_t lp_colors[32];\n  // Selected AMENU set to use\n  char menu_set[9];\n  // Use hot keys in AMENU\n  uint8_t hot_keys;\n\n  char res_byte[3];\n\n  uint16_t homeuser, // user number where user can found\n      homesys,       // system where user can be found\n      forwardusr,    // mail forwarded to this user number\n      forwardsys,    // mail forwarded to this sys number\n      net_num,       // net num for forwarding\n      msgpost,       // number messages posted\n      emailsent,     // number of email sent\n      feedbacksent,  // number of f-back sent\n      fsenttoday1,   // feedbacks today\n      posttoday,     // number posts today\n      etoday,        // number emails today\n      ar,            // board access\n      dar,           // directory access\n      restrict,      // restrictions on account\n      ass_pts,       // bad things the user did\n      uploaded,      // number files uploaded\n      downloaded,    // number files downloaded\n      lastrate,      // last baud rate on\n      logons,        // total number of logons\n      emailnet,      // email sent via net\n      postnet,       // posts sent thru net\n      deletedposts,  // how many posts deleted\n      chainsrun,     // how many \"chains\" run\n      gfilesread,    // how many gfiles read\n      banktime,      // how many mins in timebank\n      homenet,       // home net number\n      subconf,       // previous conference subs\n      dirconf;       // previous conference dirs\n\n  // last sub at logoff\n  uint16_t subnum;\n  // last dir at logoff\n  uint16_t dirnum;\n\n  // reserved for short values\n  char res_short[40];\n\n  // total num msgs read\n  uint32_t msgread;\n  // number of k uploaded\n  uint32_t uk;\n  // number of k downloaded\n  uint32_t dk;\n  // numerical time last on\n  daten_t daten;\n  // status/defaults\n  uint32_t sysstatus;\n  // user's WWIV reg number\n  uint32_t wwiv_regnum;\n  // points to spend for files\n  uint32_t unused_filepoints;\n  // numerical registration date\n  daten_t unused_registered;\n  // numerical expiration date\n  daten_t unused_expires;\n  // numerical date of last file scan\n  daten_t datenscan;\n  // bit mapping for name case\n  uint32_t unued_nameinfo;\n\n  // reserved for long values\n  char res_long[40];\n\n  // time on today in seconds.\n  float timeontoday;\n  // extra seconds to add to the call/day.  This can come from many\n  // places.\n  float extratime;\n  // total time on system\n  float timeon;\n  // $ credit\n  float unused_pos_account;\n  // $ debit\n  float unused_neg_account;\n\n  // game money\n  float gold;\n\n  // reserved for real values\n  char res_float[16];\n  // last used IP Address.\n  wwiv::core::ip_address last_address;\n  // reserved for whatever\n  char res_gp[94];\n\n  uint16_t qwk_max_msgs;\n  uint16_t qwk_max_msgs_per_sub;\n  uint16_t qwk_dont_scan_mail : 1;\n  uint16_t qwk_delete_mail : 1;\n  uint16_t qwk_dontsetnscan : 1;\n  uint16_t qwk_remove_color : 1;\n  uint16_t qwk_convert_color : 1;\n  uint16_t qwk_archive : 3;\n  uint16_t qwk_leave_bulletin : 1;\n  uint16_t qwk_dontscanfiles : 1;\n  uint16_t qwk_keep_routing : 1;\n  uint16_t full_desc : 1;\n  uint16_t qwk_protocol : 4;\n};\n\n// SECLEV DATA FOR 1 SL\nstruct slrec {\n  uint16_t time_per_day, // time allowed on per day\n      time_per_logon,    // time allowed on per logon\n      messages_read,     // messages allowed to read\n      emails,            // number emails allowed\n      posts;             // number posts allowed\n  uint32_t ability;      // bit mapped abilities\n};\n\n// AUTO-VALIDATION DATA\nstruct valrec {\n  uint8_t sl, // SL\n      dsl;    // DSL\n\n  uint16_t ar,  // AR\n      dar,      // DAR\n      restrict; // restrictions\n};\n\nstruct arcrec_424_t {\n  char extension[4], // extension for archive\n      arca[32],      // add commandline\n      arce[32],      // extract commandline\n      arcl[32];      // list commandline\n};\n\n// Archiver Configuration introduced in WWIV 4.30\nstruct arcrec {\n  char name[32],    // name of the archiver\n      extension[4], // extension for archive\n      arca[50],     // add commandline\n      arce[50],     // extract commandline\n      arcl[50],     // list commandline\n      arcd[50],     // delete commandline\n      arck[50],     // comment commandline\n      arct[50];     // test commandline\n};\n\n/*\n * WWIV 5.2+ config.dat header.\n */\nstruct configrec_header_t {\n  // \"WWIV\"+ NULL\n  char signature[5];\n  uint8_t padding[1];\n  uint16_t written_by_wwiv_num_version;\n  uint32_t config_revision_number;\n  uint32_t config_size;\n  uint8_t unused[5];\n};\n\nconstexpr uint16_t script_flag_disable_script = 0x0001;\nconstexpr uint16_t script_flag_enable_file    = 0x0002;\nconstexpr uint16_t script_flag_enable_os      = 0x0004;\n\n// STATIC SYSTEM INFORMATION\nstruct configrec {\n  union {\n    // new user password\n    char newuserpw[21];\n    configrec_header_t header;\n  } header;\n\n  // system password\n  char systempw[21],\n      // path for msgs directory\n      msgsdir[81],\n      // path for gfiles dir\n      gfilesdir[81],\n      // path for data directory\n      datadir[81],\n      // path for dloads dir\n      dloadsdir[81],\n      // drive for ramdisk\n      unused_ramdrive,\n      // former path for temporary directory, now mirrors node 1 temp dir\n      // for legacy compatibility.\n      tempdir[81],\n      // 0xff  \n      xmark,\n      // former reg code + modem config.\n      // Script base directory.  Typically C:\\wwiv\\scripts\n      scriptdir[81], \n      // New in 5.4: Default Log Directory to use.\n      logdir[81],\n      // Unused space (can be used for future expansion)\n      unused1[161],\n      // BBS system name\n      systemname[51],\n      // BBS system phone number\n      systemphone[13],\n      // sysop's name\n      sysopname[51],\n      // Old single event command (removed in 4.3i0)\n      unused2[51];\n\n  // new user SL\n  uint8_t newusersl,\n      // new user DSL\n      newuserdsl,\n      // max mail waiting\n      maxwaiting,\n      unused3[10],\n      // primary comm port\n      primaryport,\n      // file dir new uploads go\n      newuploads,\n      // if system is closed\n      closedsystem;\n\n  // BBS system number before multiple nets were allowed.\n  uint16_t unused_systemnumber; \n\n  // Former baud rate and comports\n  uint8_t unused4[20];\n  // max users on system\n  uint16_t maxusers;\n  // new user restrictions\n  uint16_t newuser_restrict;\n  // System configuration\n  uint16_t sysconfig;\n  // Chat time on\n  uint16_t sysoplowtime;\n  // Chat time off\n  uint16_t sysophightime;\n  // time to run mail router\n  uint16_t unused_executetime;\n  // Formerly required up/down ratio. This has been moved to wwiv.ini\n  float req_ratio;\n  // new user gold\n  float newusergold;\n  // security level data\n  slrec sl[256];\n  // sysop quik-validation data\n  valrec autoval[10];\n  uint8_t unused5[151];\n  // old archivers (4.24 format)\n  arcrec_424_t arcs[4];\n  uint8_t unused6[102];\n  // user record length\n  int16_t userreclen;\n  // mail waiting offset\n  int16_t waitingoffset;\n  // inactive offset\n  int16_t inactoffset;\n  // formerly newuser event\n  uint8_t unused7[51]; \n  // SysOp's WWIV 4.x Registration Number\n  uint32_t wwiv_reg_number; \n  // New User Password\n  char newuserpw[21];\n  // Post/Call Ratio required to access transfers\n  float post_call_ratio;\n  uint8_t unused8[222];\n  // system status offset\n  int16_t sysstatusoffset;\n  // Formerly network type ID?\n  char unused_network_type; \n  // offset values into user record, used by net3x.\n  int16_t fuoffset, fsoffset, fnoffset; \n\n  // max subboards\n  uint16_t max_subs;\n  // max directories\n  uint16_t max_dirs;\n  // qscan pointer length in bytes\n  uint16_t qscn_len;\n  /** Max number of backup files to make of datafiles. 0 = unlimited */\n  uint8_t max_backups;\n  /** Flags that control the execution of scripts */\n  uint16_t script_flags;\n  /** Unused space, may be used for new values in the future. */\n  uint8_t unused9[6];\n  // path for menu dir\n  char menudir[81]; \n  uint8_t res[502];\n};\n\n// overlay information per instance\nstruct legacy_configovrrec_424_t {\n  uint8_t unused1[9];\n  uint8_t primaryport;\n  uint8_t unused2[27];\n  char tempdir[81];\n  char batchdir[81];\n  char unused3[313];\n};\n\n// DYNAMIC SYSTEM STATUS\nstruct statusrec_t {\n  // last date active\n  char date1[9];\n  // date before now\n  char date2[9];\n  // two days ago\n  char date3[9];\n  // yesterday's log\n  char log1[13];\n  // two days ago log\n  char log2[13];\n  // date gfiles last updated\n  char gfiledate[9];\n  // flags for files changing\n  uint8_t filechange[7];\n\n  // how many local posts today\n  uint16_t localposts;\n  // Current number of users\n  uint16_t users;\n  // Current caller number\n  uint16_t callernum;\n  // Number of calls today\n  uint16_t callstoday;\n  // Messages posted today\n  uint16_t msgposttoday;\n  // Email sent today\n  uint16_t emailtoday;\n  // Feedback sent today\n  uint16_t fbacktoday;\n  // files uploaded today\n  uint16_t uptoday;\n  // Minutes active today\n  uint16_t activetoday;\n  // Q-scan pointer value\n  uint32_t qscanptr;\n  // auto-message anony stat\n  char amsganon;\n  // user who wrote a-msg\n  uint16_t amsguser;\n  // caller number\n  uint32_t callernum1;\n  // word for net editor\n  uint16_t unused_net_edit_stuff;\n  // tell what version it is\n  uint16_t wwiv_version;\n  // tell what version of net\n  uint16_t net_version;\n  // network bias factor\n  float net_bias;\n  // date last connect.net\n  int32_t last_connect;\n  // date last bbslist.net\n  int32_t last_bbslist;\n  // net free factor def 3\n  float net_req_free;\n  // # days BBS active\n  uint16_t days;\n  // RESERVED\n  char res[29];\n};\n\n/**\n * ON DISK format for MESSAGE BASE INFORMATION (SUBS.DAT)\n * This has been the same since *at least* 4.22.\n */\nstruct subboardrec_422_t {\n  // board name\n  char name[41];\n  // board database filename\n  char filename[9];\n  // board special key\n  char key;\n\n  // sl required to read\n  uint8_t readsl;\n  // sl required to post\n  uint8_t postsl;\n  // anonymous board?\n  uint8_t anony;\n  // minimum age for sub\n  uint8_t age;\n  // max # of msgs\n  uint16_t maxmsgs;\n  // AR for sub-board\n  uint16_t ar;\n  // how messages are stored\n  uint16_t storage_type;\n  // 4 digit board type\n  uint16_t unused_legacy_type;\n};\n\n/**\n * ON DISK format for UPLOAD DIRECTORY INFORMATION (DIRS.DAT)\n * This has been the same since *at least* 4.22.\n */\nstruct directoryrec_422_t {\n  // directory name\n  char name[41];\n  // direct database filename\n  char filename[9];\n  // filename path\n  char path[81];\n  // DSL for directory\n  uint8_t dsl;\n  // minimum age for directory\n  uint8_t age;\n  // DAR for directory\n  uint16_t dar;\n  // max files for directory\n  uint16_t maxfiles;\n  // file type mask\n  uint16_t mask;\n  // 4 digit directory type\n  uint16_t unused_legacy_dirtype;\n};\n\n// QUICK REFERENCE TO FIND USER NUMBER FROM NAME\nstruct smalrec {\n  // User name.\n  unsigned char name[31];\n  // User number.\n  uint16_t number;\n};\n\n// TYPE-1 and TYPE-2 locator to find the message text.\nstruct messagerec {\n  // how it is stored (type, 1 or 2)\n  uint8_t storage_type;\n  // where it is stored (type specific)\n  uint32_t stored_as;\n};\n\n// Union types used by postrec/mailrec network settings.\n// Used when it is source verified.\nstruct source_verified_message_t {\n  // network number for the message\n  uint8_t net_number;\n  // Type for a verified message. (same as minor type)\n  uint16_t source_verified_type;\n};\n\n// Union types used by postrec/mailrec network settings.\n// Used when it's not source verified.\nstruct network_message_t {\n  uint16_t unused;\n  // network number for the message\n  uint8_t net_number;\n};\n\nstruct subfile_header_t {\n  // \"WWIV^Z\\000\"\n  char signature[6];\n  // WWIV version used to create this sub.\n  uint16_t wwiv_version;\n  // Message SDK compatibility revision used to create this sub.\n  // Currently only value is 1.\n  uint32_t revision;\n  // 32-bit time_t value for when this sub was created.\n  int64_t daten_created;\n  // Modification count for this sub.  Every write to this file should\n  // Increase the mod count.  This can be used for caching.\n  uint64_t mod_count;\n  // For future expansion: 32-bit CRC password to access this sub.\n  uint32_t password_crc32;\n  // in WWIV type-2 message bases, this is always 0.\n  uint32_t base_message_num;\n  // UNUSED\n  uint8_t padding_1[49];\n  // Number of messages in this area.\n  uint16_t active_message_count;\n  // UNUSED\n  uint8_t padding_2[13];\n};\n\n// DATA HELD FOR EVERY POST\nstruct postrec {\n  // title of post\n  char title[72];\n  // UNUSED padding from title.\n  uint8_t padding_from_title[6];\n  union {\n    // Used if this is a source verified message.\n    source_verified_message_t src_verified_msg;\n    // Used if this is a network message.\n    network_message_t network_msg;\n  } network;\n\n  // anony-stat of message\n  uint8_t anony;\n  // bit-mapped status\n  uint8_t status;\n\n  // what system it came from\n  uint16_t ownersys;\n  // User number who posted it\n  uint16_t owneruser;\n\n  // qscan pointer\n  uint32_t qscan;\n  // 32-bit time_t value for the date posted\n  daten_t daten;\n\n  // where to find it in the type-2 messagebase.\n  messagerec msg;\n};\n\n// DATA HELD FOR EVERY E-MAIL OR F-BACK\nstruct mailrec {\n  char title[72]; // title of message\n  uint8_t padding_from_title[6];\n  union {\n    source_verified_message_t src_verified_msg;\n    network_message_t network_msg;\n  } network;\n\n  uint8_t anony, // anonymous mail?\n      status;    // status for e-mail\n\n  uint16_t fromsys, // originating system\n      fromuser,     // originating user\n      tosys,        // destination system\n      touser;       // destination user\n\n  daten_t daten; // date it was sent\n\n  messagerec msg; // where to find it\n};\n\n// SHORT RESPONSE FOR USER, TELLING HIS MAIL HAS BEEN READ\nstruct shortmsgrec {\n  char message[81]; // short message to user\n\n  uint16_t tosys, touser; // who it is to\n};\n\n// VOTING RESPONSE DATA\nstruct voting_response {\n  char response[81]; // Voting question response\n\n  uint16_t numresponses; // number of responses\n};\n\n// VOTING DATA INFORMATION\nstruct votingrec {\n  char question[81]; // Question\n\n  uint8_t numanswers; // number of responses\n\n  voting_response responses[20]; // actual responses\n};\n\n// DATA HELD FOR EVERY UPLOAD\nstruct uploadsrec {\n  char filename[13],   // filename\n      description[59], // file description\n      date[9],         // date u/l'ed\n      upby[37],        // name of upload user\n      actualdate[9];   // actual file date\n\n  uint8_t unused_filetype; // file type for apples\n\n  uint16_t numdloads,     // number times d/l'ed\n      ownersys, ownerusr, // who uploaded it\n      mask;               // file type mask\n\n  daten_t daten;    // date uploaded\n  daten_t numbytes; // number bytes long file is\n};\n\n// ZLOG INFORMATION FOR PAST SYSTEM USAGE\nstruct zlogrec {\n  char date[9]; // zlog for what date\n\n  uint16_t active, // number minutes active\n      calls,       // number calls\n      posts,       // number posts\n      email,       // number e-mail\n      fback,       // number f-back\n      up;          // number uploads\n};\n\n// DATA FOR OTHER PROGRAMS AVAILABLE\nstruct chainfilerec_422 {\n  char filename[81],   // filename for .chn file\n      description[81]; // description of it\n\n  uint8_t sl, // seclev restriction\n      ansir;  // chain flags (ANSI required, FOSSIL, etc)\n\n  uint16_t ar; // AR restriction\n};\n\nstruct chainregrec_422 {\n  // who registered\n  int16_t regby[5];\n  // number of runs\n  uint16_t usage;\n  // minimum age necessary\n  uint8_t minage;\n  // maximum age allowed\n  uint8_t maxage; \n  // reserved space\n  char space[50]; \n};\n\n// DATA FOR EXTERNAL PROTOCOLS\n\nstruct newexternalrec {\n  char description[81],     // protocol description\n      receivefn[81],        // receive filename\n      sendfn[81],           // send filename\n      receivebatchfn[81],   // batch receive cmd\n      sendbatchfn[81],      // batch send cmd\n      unused_bibatchfn[81]; // batch send/receive cmd\n\n  uint16_t ok1, // if sent\n      othr;     // other flags\n\n  char pad[22];\n};\n\n#define EDITORREC_EDITOR_TYPE_WWIV 0\n#define EDITORREC_EDITOR_TYPE_QBBS 1\n\n// DATA FOR EXTERNAL EDITORS\nstruct editorrec {\n  char description[81], // description of editor\n      filename[81];     // how to run the editor\n  uint8_t bbs_type;     // 0=WWIV, 1=QBBS\n  uint8_t old_ansir;        // Editor Flags (ANSI required, FOSSIL, etc)\n  uint16_t ansir;    // new wide editor flags.\n\n  char filenamecon[81]; // how to run locally\n\n  char res[119];\n};\n\n// DATA FOR CONVERSION OF MAIN MENU KEYS TO SUB-BOARD NUMBERS\nstruct usersubrec {\n  std::string keys;\n\n  int16_t subnum;\n};\n\n#define restrict_string \"LCMA*PEVKNU     \"\n\n// USERREC.sysstatus\n#define sysstatus_ansi 0x00000001\n#define sysstatus_color 0x00000002\n#define sysstatus_music 0x00000004\n#define sysstatus_pause_on_page 0x00000008\n#define sysstatus_expert 0x00000010\n#define sysstatus_smw 0x00000020\n#define sysstatus_full_screen 0x00000040\n#define sysstatus_nscan_file_system 0x00000080\n#define sysstatus_extra_color 0x00000100\n#define sysstatus_clr_scrn 0x00000200\n#define sysstatus_upper_ASCII 0x00000400\n#define sysstatus_no_tag 0x00000800\n#define sysstatus_conference 0x00001000\n#define sysstatus_nochat 0x00002000\n#define sysstatus_no_msgs 0x00004000\n#define sysstatus_menusys 0x00008000\n#define sysstatus_listplus 0x00010000\n#define sysstatus_auto_quote 0x00020000\n#define sysstatus_24hr_clock 0x00040000\n#define sysstatus_msg_priority 0x00080000\n\n// slrec.ability\n#define ability_post_anony 0x0001\n#define ability_email_anony 0x0002\n#define ability_read_post_anony 0x0004\n#define ability_read_email_anony 0x0008\n#define ability_limited_cosysop 0x0010\n#define ability_cosysop 0x0020\n#define ability_val_net 0x0040\n\n// subs anony and flags. Lower half of this is anoymous\n// and the high bit is flags.\n#define anony_none 0x00\n#define anony_enable_anony 0x01\n#define anony_enable_dear_abby 0x02\n#define anony_force_anony 0x04\n#define anony_real_name 0x08\n#define anony_val_net 0x10\n#define anony_ansi_only 0x20\n#define anony_no_tag 0x40\n// Don't use the full screen reader for displaying message text.\n// This is used for ANSI art subs.\n#define anony_no_fullscreen 0x80\n\n// postrec.anony, mailrec.anony\n#define anony_sender 0x01\n#define anony_sender_da 0x02\n#define anony_sender_pp 0x04\n#define anony_receiver 0x10\n#define anony_receiver_da 0x20\n#define anony_receiver_pp 0x40\n\n// directoryrec_422_t.mask\n#define mask_PD 0x0001\n#define mask_no_uploads 0x0004\n#define mask_archive 0x0008\n#define unused_mask_pending_batch 0x0010\n#define mask_no_ratio 0x0020\n#define mask_cdrom 0x0040\n#define mask_offline 0x0080\n#define mask_uploadall 0x0200\n#define mask_guest 0x0400\n#define mask_extended 0x0800\n#define mask_wwivreg 0x1000\n\n// postrec.status\n#define status_unvalidated 0x01\n#define status_delete 0x02\n#define status_no_delete 0x04\n#define status_pending_net 0x08\n#define status_post_source_verified 0x10\n#define status_post_new_net 0x20\n\n// mailrec.status\n#define status_multimail 0x01\n#define status_source_verified 0x02\n#define status_new_net 0x04\n#define status_seen 0x08\n#define status_replied 0x10\n#define status_forwarded 0x20\n#define status_file 0x80\n\n// configrec.sysconfig\n//#define unused_sysconfig_no_local 0x00001\n//#define unused_sysconfig_no_beep    0x00002\n//#define unused_sysconfig_enable_pipes 0x00004\n#define sysconfig_no_newuser_feedback 0x00008\n//#define unused_sysconfig_two_color 0x00010\n//#define unused_sysconfig_enable_mci 0x00020\n#define sysconfig_titlebar 0x00040\n//#define unused_sysconfig_list 0x00080\n//#define unused_sysconfig_no_xfer 0x00100\n#define sysconfig_2_way 0x00200\n#define sysconfig_allow_alias 0x00400\n#define sysconfig_all_sysop 0x00800\n#define sysconfig_free_phone 0x02000\n#define sysconfig_log_dl 0x04000\n//#define unused_sysconfig_extended_info 0x08000\n//#define unused_sysconfig_1 0x10000\n//#define unused_sysconfig_2 0x20000\n\n#define ansir_ansi 0x01\n#define ansir_no_DOS 0x02\n#define ansir_emulate_fossil 0x04\n#define ansir_stdio 0x08\n// Execute this command from the instance temp directory\n// instead of the main BBS directory.\n#define ansir_temp_dir 0x10\n#define ansir_local_only 0x20\n#define ansir_multi_user 0x40\n#define ansir_binary 0x80\n// First new wide (16-bit) ansir value\n#define ansir_netfoss 0x0100\n\n// newexternalrec.othr\n#define othr_error_correct 0x0001\n#define othr_bimodem 0x0002\n#define othr_override_internal 0x0004\n\n// statusrec.filechange [0..6]\n#define filechange_names 0\n#define filechange_upload 1\n#define filechange_posts 2\n#define filechange_email 3\n#define filechange_net 4\n\nstruct ext_desc_type {\n  char name[13];\n\n  int16_t len;\n};\n\n// conferencing stuff\n\n#define conf_status_ansi 0x0001    // ANSI required\n#define conf_status_wwivreg 0x0002 // WWIV regnum required\n\nconstexpr int MAX_CONFERENCES = 26;\nconstexpr int WWIV_MESSAGE_TITLE_LENGTH = 72;\n\nstruct filestatusrec {\n  int16_t user;\n\n  char filename[13];\n\n  int32_t id;\n\n  uint32_t numbytes;\n};\n\n///////////////////////////////////////////////////////////////////////////////\n// Execute Flags.  Used when spawning chains and external programs.\n\n// Default option, do nothing.\nconstexpr uint32_t EFLAG_NONE = 0x0000;\n// Don't allow running a basic script using the format: '@basic:scriptname.bas'\nconstexpr uint32_t EFLAG_NOSCRIPT = 0x0001;\n// Don't reset or change the directory.\nconstexpr uint32_t EFLAG_NO_CHANGE_DIR = 0x0002;\n// don't check for hangup (typically used for the upload event)\nconstexpr uint32_t  EFLAG_NOHUP = 0x0004;\n// redirect DOS IO to com port\nconstexpr uint32_t  EFLAG_COMIO = 0x0008;\n// Binary Mode: Don't expand telnet IAC or LF -> CR/LF Translation\nconstexpr uint32_t  EFLAG_BINARY = 0x0010;\n// try running out of net dir first\nconstexpr uint32_t  EFLAG_NETPROG = 0x0080;\n// Use Win32 Emulated FOSSIL using NetFOSS\nconstexpr uint32_t  EFLAG_NETFOSS = 0x0100;\n// Use Win32 Emulated FOSSIL using SyncFOSS\nconstexpr uint32_t  EFLAG_SYNC_FOSSIL = 0x0200;\n// Use STDIO based doors for Window/Linux.  This will set the stdin/stdout\n// file descriptors to the socket before spawning the chain.\nconstexpr uint32_t  EFLAG_STDIO = 0x0400;\n// Run out of the TEMP directory instead of the BBS directory\nconstexpr uint32_t  EFLAG_TEMP_DIR = 0x0800;\n// Run out of the BATCH directory instead of the BBS directory\nconstexpr uint32_t  EFLAG_BATCH_DIR = 0x1000;\n// Run out of the QWK directory instead of the BBS directory\nconstexpr uint32_t EFLAG_QWK_DIR = 0x2000;\n\n// Use Listening TCP Socket for connectivity\nconstexpr uint32_t EFLAG_LISTEN_SOCK = 0x4000;\n// Use Listening UNIX Socket for connectivity\nconstexpr uint32_t EFLAG_UNIX_SOCK = 0x8000;\n\n///////////////////////////////////////////////////////////////////////////////\n\nconstexpr const char* SPAWNOPT_NEWUSER = \"NEWUSER\";\nconstexpr const char* SPAWNOPT_BEGINDAY = \"BEGINDAY\";\nconstexpr const char* SPAWNOPT_LOGON = \"LOGON\";\nconstexpr const char* SPAWNOPT_CLEANUP = \"CLEANUP\";\nconstexpr const char* SPAWNOPT_ULCHK = \"ULCHK\";\nconstexpr const char* SPAWNOPT_PROT_SINGLE = \"PROT_SINGLE\";\nconstexpr const char* SPAWNOPT_PROT_BATCH = \"PROT_BATCH\";\nconstexpr const char* SPAWNOPT_ARCH_E = \"ARCH_E\";\nconstexpr const char* SPAWNOPT_ARCH_L = \"ARCH_L\";\nconstexpr const char* SPAWNOPT_ARCH_A = \"ARCH_A\";\nconstexpr const char* SPAWNOPT_ARCH_D = \"ARCH_D\";\nconstexpr const char* SPAWNOPT_ARCH_K = \"ARCH_K\";\nconstexpr const char* SPAWNOPT_ARCH_T = \"ARCH_T\";\nconstexpr const char* SPAWNOPT_LOGOFF = \"LOGOFF\";\n\n///////////////////////////////////////////////////////////////////////////////\n#define INI_TAG \"WWIV\"\n\n#define OP_FLAGS_FORCE_NEWUSER_FEEDBACK 0x00000001\n// #define UNUSED_OP_FLAGS_CHECK_DUPE_PHONENUM 0x00000002\n//#define UNUSED_OP_FLAGS_HANGUP_DUPE_PHONENUM 0x00000004\n#define OP_FLAGS_SIMPLE_ASV 0x00000008\n#define OP_FLAGS_POSTTIME_COMPENSATE 0x00000010\n//#define UNUSED_OP_FLAGS_SHOW_HIER 0x00000020\n#define OP_FLAGS_IDZ_DESC 0x00000040\n//#define UNUSED_OP_FLAGS_SETLDATE 0x00000080\n#define OP_FLAGS_UNUSED_1 0x00000200\n#define OP_FLAGS_READ_CD_IDZ 0x00000400\n#define OP_FLAGS_FSED_EXT_DESC 0x00000800\n//#define UNUSED_OP_FLAGS_FAST_TAG_RELIST 0x00001000\n#define OP_FLAGS_MAIL_PROMPT 0x00002000\n#define OP_FLAGS_SHOW_CITY_ST 0x00004000\n#define OP_FLAGS_UNUSED_7 0x00020000\n#define OP_FLAGS_UNUSED_5 0x00040000\n//#define UNUSED_OP_FLAGS_WFC_SCREEN 0x00080000\n#define OP_FLAGS_MSG_TAG 0x00400000\n//#define OP_FLAGS_CHAIN_REG 0x00800000\n#define OP_FLAGS_CAN_SAVE_SSM 0x01000000\n#define OP_FLAGS_UNUSED_6 0x02000000\n#define OP_FLAGS_USE_FORCESCAN 0x04000000\n//#define UNUSED_OP_FLAGS_NEWUSER_MIN 0x08000000\n#define OP_FLAGS_UNUSED_2 0x20000000\n#define OP_FLAGS_UNUSED_4 0x40000000\n\n// QUICK REFERNCE TO FIND USER INPUT_MODE_PHONE NUMBER\n\nstruct phonerec {\n  int16_t usernum; // user's number\n  char phone[13];  // user's phone number\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\nstruct ext_desc_rec {\n  char name[13];\n  int32_t offset;\n};\n\nstruct instancerec {\n  int16_t number, user;\n  uint16_t flags, loc, subloc;\n  daten_t last_update;\n  uint16_t modem_speed;\n  daten_t inst_started;\n  uint8_t extra[80];\n};\n\n#ifndef __MSDOS__\n\nstatic_assert(sizeof(wwiv::core::ip_address) == 16, \"wwiv::core::ip_address == 16\");\nstatic_assert(sizeof(userrec) == 1024, \"userrec == 1024\");\nstatic_assert(sizeof(slrec) == 14, \"slrec == 14\");\nstatic_assert(sizeof(valrec) == 8, \"valrec == 8\");\nstatic_assert(sizeof(arcrec) == 336, \"arcrec == 336\");\nstatic_assert(sizeof(configrec) == 6228, \"configrec == 6228\");\nstatic_assert(sizeof(legacy_configovrrec_424_t) == 512, \"legacy_configovrrec_424_t == 512\");\nstatic_assert(sizeof(statusrec_t) == 151, \"statusrec == 151\");\nstatic_assert(sizeof(subboardrec_422_t) == 63, \"subboardrec_422_t == 63\");\nstatic_assert(sizeof(directoryrec_422_t) == 141, \"directoryrec_422_t == 141\");\nstatic_assert(sizeof(smalrec) == 33, \"smalrec == 33\");\nstatic_assert(sizeof(messagerec) == 5, \"messagerec == 5\");\nstatic_assert(sizeof(postrec) == 100, \"postrec == 100\");\nstatic_assert(sizeof(subfile_header_t) == 100, \"subfile_header_t == 100\");\nstatic_assert(offsetof(postrec, owneruser) == offsetof(subfile_header_t, active_message_count),\n              \"owneruser offset != active_message_count: \");\nstatic_assert(sizeof(mailrec) == 100, \"mailrec == 100\");\nstatic_assert(sizeof(shortmsgrec) == 85, \"shortmsgrec == 85\");\nstatic_assert(sizeof(voting_response) == 83, \"voting_response == 83\");\nstatic_assert(sizeof(uploadsrec) == 144, \"uploadsrec == 144\");\nstatic_assert(sizeof(zlogrec) == 21, \"zlogrec == 21\");\nstatic_assert(sizeof(chainfilerec_422) == 166, \"chainfilerec_422 == 166\");\nstatic_assert(sizeof(chainregrec_422) == 64, \"chainregrec_422 == 64\");\nstatic_assert(sizeof(newexternalrec) == 512, \"newexternalrec == 512\");\nstatic_assert(sizeof(editorrec) == 366, \"editorrec == 366\");\nstatic_assert(sizeof(ext_desc_type) == 15, \"ext_desc_type == 15\");\nstatic_assert(sizeof(filestatusrec) == 23, \"filestatusrec == 23\");\nstatic_assert(sizeof(phonerec) == 15, \"phonerec == 15\");\nstatic_assert(sizeof(ext_desc_rec) == 17, \"ext_desc_rec == 17\");\nstatic_assert(sizeof(instancerec) == 100, \"instancerec == 100\");\n\n#pragma pack(pop)\n\n#endif // __MSDOS__\n\n#endif // __INCLUDED_VARDEC_H__\n"
  },
  {
    "path": "sdk/wwivcolors.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2014-2016 WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef __INCLUDED_WWIVCOLORS_H__\n#define __INCLUDED_WWIVCOLORS_H__\n\n#include <cstdint>\n\nnamespace wwiv {\nnamespace sdk {\n\nenum class Color : uint8_t {\n  BLACK,\n  BLUE,\n  GREEN,\n  CYAN,\n  RED,\n  MAGENTA,\n  BROWN,\n  LIGHTGRAY,\n  DARKGRAY,\n  LIGHTBLUE,\n  LIGHTGREEN,\n  LIGHTCYAN,\n  LIGHTRED,\n  LIGHTMAGENTA,\n  YELLOW,\n  WHITE\n};\n\t\n}\n}\n\n\n#endif  // __INCLUDED_WWIVCOLORS_H__"
  },
  {
    "path": "sdk/wwivd_config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"sdk/wwivd_config.h\"\n\n#include \"core/cereal_utils.h\"\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n#include \"sdk/config.h\"\n\n#include <cereal/access.hpp>\n#include <cereal/cereal.hpp>\n\nusing namespace wwiv::core;\n\n#ifdef DELETE\n#undef DELETE\n#endif  // DELETE\n\nCEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(wwiv::sdk::wwivd_data_mode_t,\n                                   cereal::specialization::non_member_load_save_minimal);\n\nnamespace cereal {\n\ntemplate <class Archive> std::string save_minimal(Archive const&, const wwiv::sdk::wwivd_data_mode_t& t) {\n  return to_enum_string<wwiv::sdk::wwivd_data_mode_t>(\n      t, {\"socket\", \"pipe\"});\n}\n\ntemplate <class Archive>\nvoid load_minimal(Archive const&, wwiv::sdk::wwivd_data_mode_t& t, const std::string& v) {\n  t = from_enum_string<wwiv::sdk::wwivd_data_mode_t>(\n      v, {\"socket\", \"pipe\"});\n}\n\n} // namespace cereal\n\nnamespace wwiv::sdk {\n\ntemplate <class Archive>\nvoid serialize(Archive& ar, wwivd_blocking_t &b) {\n  SERIALIZE(b, mailer_mode);\n  SERIALIZE(b,use_badip_txt);\n  SERIALIZE(b, use_goodip_txt);\n  SERIALIZE(b, max_concurrent_sessions);\n\n  SERIALIZE(b, auto_blocklist);\n  SERIALIZE(b, auto_bl_sessions);\n  SERIALIZE(b, auto_bl_seconds);\n  SERIALIZE(b, use_dns_rbl);\n  SERIALIZE(b, dns_rbl_server);\n  SERIALIZE(b, use_dns_cc);\n  SERIALIZE(b, dns_cc_server);\n  SERIALIZE(b, block_cc_countries);\n  SERIALIZE(b, block_duration);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive& ar, wwivd_matrix_entry_t &a) {\n  SERIALIZE(a, description);\n  SERIALIZE(a, end_node);\n  SERIALIZE(a, key);\n  SERIALIZE(a, local_node);\n  SERIALIZE(a, name);\n  SERIALIZE(a, require_ansi);\n  SERIALIZE(a, ssh_cmd);\n  SERIALIZE(a, start_node);\n  SERIALIZE(a, telnet_cmd);\n  SERIALIZE(a, data_mode);\n  SERIALIZE(a, working_directory);\n  SERIALIZE(a, wwiv_bbs);\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, wwivd_config_t &a) {\n  SERIALIZE(a, telnet_port);\n  SERIALIZE(a, ssh_port);\n  SERIALIZE(a, binkp_port);\n  SERIALIZE(a, binkp_cmd);\n  SERIALIZE(a, do_network_callouts);\n  SERIALIZE(a, network_callout_cmd);\n  SERIALIZE(a, do_beginday_event);\n  SERIALIZE(a, beginday_cmd);\n  SERIALIZE(a, http_address);\n  SERIALIZE(a, http_port);\n  SERIALIZE(a, bbses);\n  SERIALIZE(a, launch_minimized);\n  SERIALIZE(a, blocking);\n}\n\nbool wwivd_config_t::Load(const Config & config) {\n  JsonFile<wwivd_config_t> file(FilePath(config.datadir(), \"wwivd.json\"), \"wwivd\", *this);\n  return file.Load();\n}\n\nbool wwivd_config_t::Save(const Config & config) {\n  JsonFile<wwivd_config_t> file(FilePath(config.datadir(), \"wwivd.json\"), \"wwivd\", *this);\n  return file.Save();\n}\n\n}\n"
  },
  {
    "path": "sdk/wwivd_config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2017-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_SDK_WWIVD_CONFIG_H\n#define INCLUDED_SDK_WWIVD_CONFIG_H\n\n#include \"sdk/config.h\"\n#include <string>\n#include <vector>\n\nnamespace wwiv::sdk {\n\nstruct wwivd_blocking_t {\n  bool mailer_mode = false;\n\n  bool use_badip_txt = true;\n  bool use_goodip_txt = true;\n  int max_concurrent_sessions = 1;\n  bool auto_blocklist = true;\n  int auto_bl_sessions = 3;\n  int auto_bl_seconds = 30;\n\n  bool use_dns_rbl = true;\n  // xbl.spamhaus.org\n  std::string dns_rbl_server{\"xbl.spamhaus.org\"};\n\n  bool use_dns_cc = false;\n  // zz.countries.nerd.dk\n  std::string dns_cc_server{\"zz.countries.nerd.dk\"};\n  std::vector<int> block_cc_countries;\n  std::vector<std::string> block_duration;\n};\n\nenum class wwivd_data_mode_t { socket, pipe };\n\nstruct wwivd_matrix_entry_t {\n  /** Key to use when displaying this BBS in the matrix logon. */\n  char key;\n  /**\n   * Used for semaphore names and also short-hand way to call the bbs.\n   * It should be not more than 8-12 characters in length.\n   */\n  std::string name;\n  /** Description to use to display this BBS in the matrix logon. */\n  std::string description;\n  /** Command to launch this BBS over Telnet */\n  std::string telnet_cmd;\n  /** Command to launch this BBS over SSH */\n  std::string ssh_cmd;\n  /** Working directory to use when launching the BBS */\n  std::string working_directory;\n  /** Does using this BBS require ANSI? */\n  bool require_ansi{false};\n  /** Start node for this bbs */\n  int start_node;\n  /** End node for this bbs */\n  int end_node;\n  /** Local node for this bbs */\n  int local_node;\n  /** Mode for passing data to the BBS: Socket or Named Pipe */\n  wwivd_data_mode_t data_mode{wwivd_data_mode_t::socket};\n  /** Is this the primary WWIV BBS */\n  bool wwiv_bbs{ true };\n};\n\nclass wwivd_config_t {\npublic:\n  /** Configuration for non-bbs invocations. */\n\n  int binkp_port{-1};\n  std::string binkp_cmd;\n  bool do_network_callouts{false};\n  std::string network_callout_cmd;\n  bool do_beginday_event{true};\n  std::string beginday_cmd;\n\n  int http_port{-1};\n  std::string http_address;\n\n  /** Blocking configuration */\n  wwivd_blocking_t blocking;\n\n  /**\n   * Matrix Logon Settings\n   */\n\n  int telnet_port = \n#ifdef _WIN32\n    23;\n#else\n    2323;\n#endif\n  int ssh_port{-1};\n  /** Filename (under WWIV/GFILES) to display before showing the shuttle logon menu */\n  std::string matrix_filename;\n  /** Vector of BBS'es to display in the matrix logon. */\n  std::vector<wwivd_matrix_entry_t> bbses;\n  /** Should the network and bbs connections be launched minimized */\n  bool launch_minimized{false};\n\n  bool Load(const Config& config);\n  bool Save(const Config& config);\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "specs/areafix/AREAFIX.DOC",
    "content": "\n\n\n\n\n\n\n\n\n\n\n\n                               Areafix Revision 1.30\n\n\n\n\n\n                         Originally Written by Greg Dawson\n\n\n\n\n\n         (C) Copyright 1988-92 by Greg Dawson and George Peace (1:270/101).\n                                All Rights Reserved.\n\n\n\n\n\n                                   January, 1992\f\n\n     Areafix v1.30                                                     Page 2\n     ------------------------------------------------------------------------\n\n\n\n                                 Table of Contents\n\n\n       INTRODUCTION.........................................................4\n\n       WHAT'S NEW SINCE 1.20?...............................................4\n\n       WHAT'S NEW SINCE 1.10?...............................................6\n\n       COMMAND LINE OPTIONS.................................................7\n         EC.................................................................7\n         FIND...............................................................7\n         ADD................................................................7\n         DELETE.............................................................7\n         DROP...............................................................8\n         REMOTEDELETEAREA...................................................8\n         NOTIFY.............................................................8\n         QUERY..............................................................8\n         <node>.............................................................9\n         <echo(s)>..........................................................9\n         -c<Areafix.Ctl>....................................................9\n         -a<Areas.Bbs>......................................................9\n         -e.................................................................9\n         -h<1|2>...........................................................10\n         -k................................................................10\n         -l................................................................10\n         -m................................................................11\n         -n<filename.ext>..................................................11\n         -r................................................................11\n\n       CONFIGURATION FILE..................................................12\n         Address...........................................................12\n         Assume............................................................12\n         PointNet..........................................................12\n         NetMail...........................................................13\n         ScanPath..........................................................13\n         AreasFile.........................................................13\n         SystemType........................................................13\n         Sysop.............................................................13\n         LogFile...........................................................14\n         LogAllChanges.....................................................14\n         SortNodes.........................................................14\n         Format............................................................14\n         Alias.............................................................15\n         FileShare.........................................................15\n         NewAreasProcess...................................................15\n         NewAreasPath......................................................16\n         NewAreasNoDir.....................................................16\n         NewAreasNoPassthru................................................16\n         NewAreaNumber.....................................................16\n         NewAreasNodes.....................................................17\n         NewAreasCreate....................................................17\n         PurgeAreas........................................................17\n         PurgeFile.........................................................18\f\n\n     Areafix v1.30                                                     Page 3\n     ------------------------------------------------------------------------\n\n\n\n         PurgeRemove.......................................................18\n         KeyDefault........................................................18\n         Password (Address Access).........................................19\n         ProtectDefault....................................................20\n         LockDefault.......................................................20\n         Protect (Area Access).............................................20\n         Echo_List.........................................................21\n         NoRescan..........................................................21\n         NoQuery...........................................................21\n         QuickBBSRescanList................................................21\n         RescanList........................................................22\n         RescanListAddress.................................................23\n         ShowFeeds.........................................................23\n         SaveProcessedMsgs.................................................23\n         KillSent..........................................................23\n         ForceIntl.........................................................23\n         AlertNode.........................................................23\n         No_Response_List..................................................24\n         NotifyHeader......................................................24\n         NotifyExclude.....................................................24\n         NotifyWithEchoList................................................24\n         No_Notify_List....................................................24\n         RemoteDeletion....................................................25\n         RemoteDeletionNotify..............................................25\n         RemoteDeletionForward.............................................25\n         RemoteDeletionRemove..............................................25\n         Forward_List......................................................26\n         Forward_Que.......................................................26\n\n       DOS ERRORLEVEL EXIT CODES...........................................28\n\n       CONFIGURATION MAXIMUMS..............................................28\n\n       ENVIRONMENT VARIABLE................................................28\n\n       PACKAGING LIST......................................................29\n\n       BUG REPORTS.........................................................29\n\n       DISCLAIMER..........................................................29\n\n       BEGWARE.............................................................30\f\n\n     Areafix v1.30                                                     Page 4\n     ------------------------------------------------------------------------\n\n\n\n                                    INTRODUCTION\n\n\n       Areafix is  a maintenance  utility  for  EchoMail  distribution  lists\n       (Areas.Bbs). It  accepts input  from command  line  or  NetMail.  This\n       document covers  installation parameters  and command  line operation.\n       The file Areafix.Use covers NetMail access.\n\n       Please look  over the  documentation carefully.  Though  most  of  the\n       commands have  not changed,  you might rediscover some old tricks that\n       have faded from memory with time.\n\n       If you  are upgrading  from v1.10 to this version you will need to add\n       your zone number to the \"address\" definition in Areafix.Ctl. All other\n       Areafix.Ctl directives  can remain as they were with v1.10. No changes\n       are required  to plug  in this version if you are upgrading from v1.20\n       though you might receive a benign Areafix.Ctl warning message.\n\n\n\n                               WHAT'S NEW SINCE 1.20?\n\n\n         *  AreaFix.Ctl accepts as many Password and Protect lines as\n            available memory will permit.\n\n         *  Remote area deletion requests can be forwarded to your up-/down-\n            links.\n\n         *  A default security profile can be assigned to areas with no\n            Protect entry in Areafix.Ctl.\n\n         *  Lock/key security is available to supplement Password and Protect\n            security levels.\n\n         *  Privilege masks are available to tailor Password entries.\n\n         *  Dead-end passthru EchoMail areas can be purged from Areas.Bbs\n            automatically.\n\n         *  Purge and remote deletion operations can be configured to remove\n            affected message subdirectories.\n\n         *  Find and Query output (manual or remote) includes queued forward\n            request information.\n\n         *  4-D addressing (zone:net/node.point) is supported throughout\n            Areafix.Ctl and Areas.Bbs.\n\n         *  Notify messages can be generated for individual addresses.\n\n         *  Remote requests that fail security checks are always saved.\n\n         *  INTL kludge lines can be forced on all Areafix output messages.\f\n\n     Areafix v1.30                                                     Page 5\n     ------------------------------------------------------------------------\n\n\n\n         *  Areafix can assume alternate Zone: or Zone:Net identities for\n            multi-address environments.\n\n         *  Areafix no longer reads the entire message body until processing\n            is actually required.\n\n         *  ShortForm and LongForm directives for Areas.Bbs format control\n            have been replaced by the Format directive. Format accepts one of\n            three choices: Short, Long, or Zone. Absence of a Format\n            directive implies \"normal\" Areas.Bbs format with zone information\n            provided where necessary and net number provided on all entries.\n\n            Format Short   all entries are abbreviated to their shortest form\n            Format Long    all entries are expanded to include full notation\n            Format Zone    the first entry for each area always includes zone\n\n         *  Netmail replies to areafix requests can be shortened to omit the\n            list of active areas.\f\n\n     Areafix v1.30                                                     Page 6\n     ------------------------------------------------------------------------\n\n\n\n                               WHAT'S NEW SINCE 1.10?\n\n\n         *  AreaFix is now \"zone aware\" using INTL or MSGID addressing\n            extensions. All addresses in AreaFix.Ctl and on the command line\n            now accept a zone number. Except for the \"address\" definition in\n            Areafix.Ctl zones are optional.\n\n         *  AreaFix recognizes add/delete requests from \"your\" points using\n            MSGID or FMPT addressing extensions. AreaFix translates the point\n            format to/from pointnet/point.\n\n         *  Configuration maximums have been expanded to more closely reflect\n            current processing needs.\n\n         *  Command line switch -R is available to force a rescan when doing\n            a manual add.\n\n         *  Forward requests are now limited to one per day for each\n            area/address combination to help limit uplink netmail area\n            flooding.\n\n         *  Actual area names are now used for request processing in addition\n            to the original CRC16 method. This eliminates 'dupe CRC' problems\n            while retaining most of the speed advantage of CRC checking.\n\n         *  NetMail responses with =many= add/delete requests no longer\n            overrun the 16k message buffer. Large responses are split into\n            multiple messages.\n\n         *  A delete request for a non-existent echo no longer generates an\n            auto-request to your feed.\n\n         *  A NetMail query (-Q) is no longer honored if the password is\n            incorrect.\n\n         *  A netmail add request for a protected area returns an already\n            active response if the area is already active. The previous\n            version returned a misleading protected area rejection response.\n\n         *  Forward list processing now recognizes the specified list format\n            if different from areas.bbs format.\f\n\n     Areafix v1.30                                                     Page 7\n     ------------------------------------------------------------------------\n\n\n\n                                COMMAND LINE OPTIONS\n\n\n                 Areafix [<[EC] [FIND] [ADD] [DELETE] [NOTIFY] [QUERY] [DROP]\n                 [REMOTEAREADELETE]>] [<node>] [<echo(s)>] [-c<Areafix.Ctl>]\n                 [-a<Areas.Bbs>]\n                 [-e] [-h<1|2>] [-k] [-l] [-m] [-n<notify.Txt>] [-r]\n\n\n       EC                                                                    \n\n\n       Automatic Echo  Change. This  tells Areafix  to process  any  net/node\n       changes and/or  new echomail areas. This is what you would call normal\n       Areafix operation. Example:\n\n                 Areafix EC\n\n\n       FIND                                                                  \n\n\n       Command line  mode. Find  the echos  a specific  node is  listed  for.\n       Example:\n\n                 Areafix FIND 106/111\n\n\n       ADD                                                                   \n\n\n       Command line  mode. This  instructs Areafix  to add a specific node to\n       one or more echos. Example:\n\n                 Areafix ADD 1:106/111 Tech C_Echo Comm\n                 Areafix ADD 106/111 all\n\n\n       DELETE                                                                \n\n\n       Command line  mode. This  instructs Areafix  to delete a specific node\n       from one or more echos. Example:\n\n                 Areafix DELETE 106/111 Tech C_Echo Comm\n                 Areafix DELETE 1:106/111 all\f\n\n     Areafix v1.30                                                     Page 8\n     ------------------------------------------------------------------------\n\n\n\n       DROP                                                                  \n\n\n       Command line mode. Areafix will perform a single level deletion of all\n       links for the requested areas. Links with Areafix.Ctl Password entries\n       will receive  delete requests  addressed to Areafix (-areaname). Links\n       without Password  entries will  receive text requests. The Areafix.Ctl\n       PurgeRemove directive  controls deletion  of messages  and directories\n       orphaned by this operation.\n\n                 Areafix DROP Sysop Flame\n\n\n       REMOTEDELETEAREA                                                      \n\n\n       Command line  mode. Areafix  will remove  specified areas as if remote\n       area delete  requests (AutoDelete  or ~areaname)  had arrived. Actions\n       are determined by the RemoteDeletion series of Areafix.Ctl directives.\n       Be careful with this one! Example:\n\n                 Areafix REMOTEDELETEAREA Sysop Flame\n\n\n       NOTIFY                                                                \n\n\n       Notify will send a list of connected areas to all your the uplinks and\n       downlinks. Areafix.Ctl directive NotifyHeader defines a file to import\n       into each  notification message  sent. NotifyWithList will file-attach\n       the Echo_List filename to all notify messages. Example:\n\n                 Areafix NOTIFY\n\n       If you'd  like to  exclude certain nodes, see the control file command\n       'NotifyExclude'.\n\n       If you  want  to  generate  notification  messages  for  only  certain\n       addresses list those addresses on the command line:\n\n                 Areafix NOTIFY 270/1 101 211 273/715 6:62/2\n\n\n       QUERY                                                                 \n\n\n       This is functionally the same as the subject line switch '-q'. It will\n       return a list of echos that are available to a given node.\f\n\n     Areafix v1.30                                                     Page 9\n     ------------------------------------------------------------------------\n\n\n\n       <node>                                                                \n\n\n       The Zone:Net/Node.Point  for command  line mode.  If you leave out the\n       zone or  zone and network number, the program will default to your own\n       zone or zone and net. Point defaults to 0. Example:\n\n                 Areafix FIND 1:106/111\n                 Areafix FIND 106/111\n                 Areafix FIND 111\n                 Areafix FIND 270/101.8\n\n\n       <echo(s)>                                                             \n\n\n       The list  of echos  for ADD  and DELETE  modes. \"All\"  is  a  wildcard\n       areaname that performs the operation on all areanames.\n\n\n       -c<Areafix.Ctl>                                                       \n\n\n       By default,  Areafix will  look for the configuration file by the name\n       'Areafix.Ctl' in  the default  directory.  If  you'd  like  to  use  a\n       different name or path, here's the place. Example:\n\n                 Areafix EC -cC:\\Config\\Areafix.Ctl\n\n       Note: This  will override the environment variable. For information on\n       that, see the section entitled \"Environment variable\".\n\n\n       -a<Areas.Bbs>                                                         \n\n\n       Areafix will  use the  EchoMail  control  file  as  specified  in  the\n       configuration file  'Areafix.Ctl'. This option can be used to override\n       that. Example:\n\n                 Areafix EC -aC:\\Config\\Areas.Bbs\n\n\n       -e                                                                    \n\n\n       This switch  will reverse  the effect  of specifying or not specifying\n       the \"NewAreasProcess\"  option in  the Areafix  configuration file.  In\n       other words,  if you specify \"NewAreasProcess\" =and= the -e switch, no\n       new areas  will be  processed. On the other hand, if you don't specify\n       \"NewAreasProcess\" and  =do= specify  the -e switch, the new areas will\n       be processed. Example:\f\n\n     Areafix v1.30                                                    Page 10\n     ------------------------------------------------------------------------\n\n\n\n                 %         <\n                 NewAreasProcess     <  Under this configuration, new\n                 %         <  areas WILL NOT be processed.\n                           <\n\n                 Areafix EC -e       <\n\n\n\n                 %         <\n                 % NewAreasProcess   <  Under this configuration, the new\n                 %         <  areas WILL be processed.\n                           <\n\n                 Areafix EC -e       <\n\n\n       -h<1|2>                                                               \n\n\n       A previous version of Areafix would delete 1.msg from each area if the\n       user specified  a '-r'  for \"rescan\"  on the  message subject line. If\n       you're running  with two  high water marks, this can become a problem.\n       By default,  Areafix will reset high water mark #1 to do a rescan. Use\n       this option  if you'd  like to  specify high  water mark  #2  instead.\n       Example:\n\n                 Areafix EC -h2\n\n\n       -k                                                                    \n\n\n       This tells  Areafix to  always flag any messages created as kill after\n       sending. Example:\n\n                 Areafix QUERY 1:106/111 -m -k\n\n\n       -l                                                                    \n\n\n       Temporarily  reverses   the  action   of  the  Areafix.Ctl  directives\n       No_Response_List and  No_Notify_List. For  example,  if  you  normally\n       operate  with   notify   generating   the   list   of   active   areas\n       (No_Notify_List commented  out) this  switch can be used together with\n       the -n  switch to  generate a  special text-only mailing to all active\n       echomail connections:\n\n                 Areafix NOTIFY -l -nC:\\MYFILES\\I_QUIT.TXT\f\n\n     Areafix v1.30                                                    Page 11\n     ------------------------------------------------------------------------\n\n\n\n       -m                                                                    \n\n\n       This switch  will cause Areafix to create a message to the listed node\n       when doing  a FIND, ADD, DELETE, or QUERY. The letter 'k' can be added\n       to this  switch (as in -mk) to flag any messages creates as kill after\n       sending. This has the same effect as -m -k. Example:\n\n                 Areafix FIND 106/111 -m\n\n       This will  create a  message to  106/111 informing  him of which areas\n       he's active  for. This switch will do nothing when used in conjunction\n       with the EC and NOTIFY functions.\n\n\n       -n<filename.ext>                                                      \n\n\n       Overrides the  Areafix.Ctl NotifyHeader parameter. This switch is used\n       as a temporary override of the standard Areafix notify header text. If\n       the file  named on  the parameter is found its entire contents will be\n       transferred to  the body  of all  Notify messages.  The file  must  be\n       standard ANSI  text suitable  for NetMail  exchange.  See  -l  for  an\n       example.\n\n\n       -r                                                                    \n\n\n       This switch  forces a  rescan of  all areas  added via  a command line\n       manual add request. The areafix.ctl norescan parameter is ignored.\f\n\n     Areafix v1.30                                                    Page 12\n     ------------------------------------------------------------------------\n\n\n\n                                 CONFIGURATION FILE\n\n\n\n       Address                                                      (Limit 1)\n       Aka                                                                   \n\n       Defines your  primary zone:net/node  number and  optionally up  to 255\n       additional addresses. All three primary address components (zone, net,\n       node) =must=  be provided.  Point number  is not  required unless non-\n       zero:\n\n                 Address   <Zone:Net/Node.Point>\n                 Aka       <Zone:Net/Node.Point>\n\n       The first  Address or  Aka defined  is the  default or primary address\n       Areafix will  use thruout  its processing.  Additional  addresses  are\n       interpreted as  \"aka\" addresses.  All addresses  should be defined via\n       the Address  parameter. Aka  is maintained only for compatibility with\n       previous Areafix versions.\n\n       The zone from the first directive will be used as the default zone for\n       all following control file processing and request processing.\n\n\n       Assume Zone                                                 (Limit: 1)\n       Assume Net                                                            \n\n       This activates  either  ZONE  or  ZONE:NET  address  assumption.  This\n       feature tries  to be  smart about  multi-zone operations.  When either\n       type of  address assumption  is active  areafix uses  the netmail \"to\"\n       address only  until the  request is  validated against your configured\n       addresses. At  that point your system identity is changed to match the\n       caller's.\n\n       If ZONE  assumption is  active Areafix  locates the  first address/aka\n       defined for  a matching  ZONE and  assumes that  Zone:Net/Node as  its\n       primary address.  NET  assumption  locates  the  first  entry  with  a\n       matching ZONE:NET.\n\n       From this  point on  all mail  Areafix generates  will ASSUME the full\n       ZONE:NET/NODE identity  of the  matching address/aka.  If no  matching\n       address is  located Areafix  uses the  first  Address/Aka  configured.\n       Example:\n\n                 Assume Net\n\n\n       PointNet                                                    (Limit: 1)\n\n       This parameter is provided for compatibility with Areafix version 1.20\n       control files  and mail  handlers that  do not  use 4-D  addressing in\n       Areas.Bbs handling.\f\n\n     Areafix v1.30                                                    Page 13\n     ------------------------------------------------------------------------\n\n\n\n       Defines your  private net  number for  limited point  support. NetMail\n       requests  arriving   from  one   of  your  points  (FMPT  #  or  MSGID\n       z:n/n.point)  will   be  changed  to  pointnet/point  for  processing.\n       Example:\n\n                 PointNet 30500\n\n       If your  address is defined as 1:270/101 and your pointnet as 30500, a\n       request from 1:270/101.13 will be 'remapped' to address 1:30500/13 for\n       request processing.\n\n\n       NetMail <path>                                              (Limit: 1)\n\n       The full  path to your where your net messages are kept. This is where\n       Areafix searches for incoming requests and places its responses:\n\n                 C:\\Msg\\NetMail\n\n\n       ScanPath <path>                                             (Limit: 6)\n\n       You can  specify up  to 3  additional paths  to scan from. One example\n       might be your bad message directory (for creation of new areas):\n\n                 C:\\Msg\\Bad_Msgs\n\n\n       AreasFile <file>                 (Limit: 10 files totaling 2048 areas)\n\n       This is  the name  of your EchoMail control file(s). It's important to\n       know that  Areafix searches  them  sequentially  when  looking  for  a\n       matching area. It will only add and delete nodes from the first match.\n       New areas will always be added to the last control file listed.\n\n\n       SystemType <type>                                           (Limit: 1)\n\n       Defines the  format for all defined AreasFile lists. This controls how\n       Areafix interprets  directory and  passthru  information  as  well  as\n       creation of  new areas. Valid system types are ConfMail, QM, Opus, PM,\n       QuickBBS, and  Squish. It  is important  to specify the proper control\n       file type.  If you don't, you run the risk of scrambling the format of\n       the file. Be sure it's set properly.\n\n       Example: SystemType QM\n\n\n       Sysop <your name>                                           (Limit: 1)\n\n       This is  your name.  It'll default  to \"SysOp\"  if  not  present.  All\n       response and  notification  messages  generated  by  AreaFix  will  be\n       addressed \"from\" this name. The string can be up to 35 characters.\f\n\n     Areafix v1.30                                                    Page 14\n     ------------------------------------------------------------------------\n\n\n\n       LogFile <file>                                              (Limit: 1)\n\n       If you  specify a  file here,  Areafix will  keep a log of what it has\n       done. If you comment this out, there will be no log file.\n\n\n       LogAllChanges\n\n       This instructs  Areafix to  log any  activities done in manual mode as\n       well as auto mode. The default is only do logging in auto mode.\n\n\n       SortNodes\n\n       When Areafix creates or changes an area, all but the first node listed\n       (the feed) will be sorted if this option is enabled.\n\n\n       Format Short\n\n       By default,  Areafix will use the net/node form of nodes when updating\n       an area entry. The form is as such:\n\n                 106/111 106/112 106/113 106/113.2 106/113.4 22/4 22/5\n\n       Optionally, you can tell Areafix to use the short from:\n\n                 106/111 112 113 .2 .4 22/4 5\n\n       Keep in  mind, though,  that some programs might not support the short\n       form and  thus might not work properly with this setting. Format Short\n       and Format Zone can be combined.\n\n       It should  be noted  that areafix can always READ the short form. This\n       option just tells the program whether or not to WRITE it that way. One\n       quick way  to convert  your control  to and from the short form is the\n       following...\n\n       To make  all nodes  the 'short' form (net/node 999/999 can be any node\n       you don't list):\n\n                 %\n                 Format Short\n                 %\n\n                 Areafix ADD 999/999 all\n                 Areafix DEL 999/999 all\n\n       And, to convert it back to the normal form:\n\n                 %\n                 % Format Short\n                 %\f\n\n     Areafix v1.30                                                    Page 15\n     ------------------------------------------------------------------------\n\n\n\n                 Areafix ADD 999/999 all\n                 Areafix DEL 999/999 all\n\n\n       Format Long\n\n       This command directs areafix to use the full zone:net/node format when\n       updating an area entry. The format is:\n\n                 1:106/111 1:106/112 1:106/113 1:106/113.2 1:106/113.4\n\n       This format wastes space in your EchoMail control files and may not be\n       fully compatible with some toss/scan/edit programs.\n\n\n       Format Zone\n\n       This command  directs areafix  to always  use the  full  zone:net/node\n       format on  the first  entry for each area when updating an area entry.\n       The format is:\n\n                 1:106/111 106/112 106/113 106/113.2 106/113.4\n\n       This format wastes space in your EchoMail control files and may not be\n       fully compatible  with some  toss/scan/edit programs. Format Short and\n       Format Zone can be combined.\n\n\n       Alias <name>                                               (Limit: 10)\n\n       When looking for messages to process, Areafix will always look for the\n       message  subject   line  addressed   to  \"Areafix\".  You  can  specify\n       additional names here. Example:\n\n                 Alias Autoecho\n                 Alias Areamanager\n\n\n       FileShare\n\n       Activates support  for MS-DOS  (v3 and above) and OS/2 file sharing on\n       all control  and message  files except Areafix.Ctl. All opens will use\n       the Deny None attribute. Example:\n\n                 FileShare\n\n\n       NewAreasProcess\n\n       This  command   tells  Areafix  to  automatically  create  new  areas,\n       subdirectories (see  NewAreasNoDir), and  control  file  entries  upon\n       encountering unknown  areas. Under  QuickBBS, the  subdirectory is not\n       created.\f\n\n     Areafix v1.30                                                    Page 16\n     ------------------------------------------------------------------------\n\n\n\n       For more  information, see the '-e' command line switch and the config\n       file option \"QuickBBSRescanList\".\n\n\n       NewAreasPath <path>                                         (Limit: 1)\n\n       This is  the subdirectory off which the new areas are created. Areafix\n       will add  a backslash if you do not provide one. Both of the following\n       are the same as far as Areafix is concerned:\n\n                 NewAreasPath C:\\Msg\n                 NewAreasPath C:\\Msg\\\n\n       Areafix  will   try  to  create  area  TEST  as  C:\\Msg\\TEST.  If  the\n       subdirectory  cannot   be  created   Areafix  will  try  creating  the\n       subdirectory by  removing the last character as in C:\\Msg\\TES and then\n       C:\\Msg\\TE and  finally C:\\Msg\\T. Areafix will report failure only when\n       it has run through all the (shortened) possibilities.\n\n\n       NewAreasNoDir\n\n       If enabled  (not commented  out) this  will turn off efforts to create\n       subdirectories for  new areas. NewAreasNoDir is assumed for SystemType\n       QuickBBS and Squish operations.\n\n       Note  that  when  directories  are  not  created  Areafix  treats  the\n       directory name  as a  comment field  and  does  not  assure  that  all\n       directory names placed in Areas.Bbs are unique.\n\n\n       NewAreasNoPassthru\n\n       If enabled  (not commented out) this tells Areafix to create new areas\n       as  non-passthru  local  areas  by  omitting  the  passthru  indicator\n       character (#).  This  affects  all  SystemTypes  except  ConfMail  and\n       QuickBBS. ConfMail  defaults to  non-passthru and QuickBBS format uses\n       NewAreaNumber to control passthru area creation.\n\n\n       NewAreaNumber <tag>                                         (Limit: 1)\n\n       If you  have \"NewAreasProcess\"  enabled, and an Opus or QuickBBS style\n       control file,  then you can tell areafix which area number (or tag) it\n       should use  for the  new areas.  Keep in mind that under Opus, Areafix\n       will, by default, mark the area pass-through with the '#' sign between\n       the area name and node numbers.\n\n       If you don't specify a <tag>, then it defaults to \"99\" under Opus, and\n       \"P\" under QuickBBS. Here's an example of a newly created area:\n\n            Opus:\n\n                 <tag> <Subdirectory> <Area name> # <nodes>\f\n\n     Areafix v1.30                                                    Page 17\n     ------------------------------------------------------------------------\n\n\n\n            QuickBBS:\n\n       <tag>\n\n\n\n       <Area name> <nodes>\n\n\n       NewAreasNodes <nodes>                      (Limit: 255 on only 1 line)\n\n       These are  the nodes  to add  when a new area is created. Areafix will\n       add the originating node as the first address if it is not one of your\n       configured addresses:\n\n                 NewAreasNodes 1:106/111 1:270/211\n\n\n       NewAreasCreate <nodes>                     (Limit: 255 on only 1 line)\n\n       Normally, when  everything is set correctly, Areafix will create a new\n       area no  matter where  the  message  originated  from.  Here  you  can\n       instruct Areafix to only create the new area if the message originated\n       from one of '<nodes>'. Looky here...\n\n                 NewAreasCreate 106/386 889\n\n       In the  above example,  Areafix will  only create  the new area if the\n       message came  from either  106/386 or  106/889. If  no  NewAreasCreate\n       addresses were defined any address could create a new area.\n\n\n       PurgeAreas\n\n       Enables automatic  EchoMail area Purge operations. A Purge occurs when\n       an incoming  area delete  request leaves  only  one  connection  to  a\n       passthru area.  The Purge  operation sends  a delete  request  to  the\n       remaining feed  address, deletes  the area from Areas.Bbs, and records\n       the purge  data. The  data is stored in the filename identified by the\n       PurgeFile directive.  This stored  information is  used  to  determine\n       action if additional traffic arrives in a purged area.\n\n       Unsolicited traffic  arriving from a purged address will be recognized\n       and deleted.  Add /  Delete requests  from any  address as well as new\n       traffic from a non-purged address will clear purged status for an area\n       and allow  normal operations  [request forward and new area create] to\n       resume.\n\n       A global Purge operation can be forced by adding a nonexistent address\n       to all areas (AreaFix Add 9999/9999 All) and immediately removing that\n       address (AreaFix  Del 9999/9999  All). This  effectively \"touches\" all\n       areas defined in all defined area definition files.\f\n\n     Areafix v1.30                                                    Page 18\n     ------------------------------------------------------------------------\n\n\n\n       PurgeFile <filename>                                        (Limit: 1)\n\n       Identifies the  location and  name (as  a full  filespec) of the Purge\n       data file.  Information pertaining  to automatic  passthru area  purge\n       operations is  stored in this file. Information includes the area tag,\n       purge date,  and last  feed  address.  This  information  is  used  to\n       intercept additional traffic arriving from the purged feed address and\n       to recognize  any valid  new \"feeds\"  for affected echos.. The default\n       filespec is AreaFix.Del.\n\n       You can  make manual entries in the file. The format of entries in the\n       file is:\n\n            P <purged (feed) node> <area name> <purge date as mm/dd/yyyy>\n\n       Example: Purge_File O:\\Areafix\\Areafix.Del\n\n\n       PurgeRemove\n\n       Triggers removal  of message  subdirectories for  all  purged  message\n       areas.  All   files  are   deleted  from   the  subdirectory  and  the\n       subdirectory itself  is removed.  File protection  and  subdirectories\n       within a  message subdirectory  will prevent  the operation from being\n       completed. The Areafix program will not abort if this operation fails.\n\n       Example: PurgeRemove\n\n\n       KeyDefault\n\n       Defines the  default password  Key string. This key string is assigned\n       to all addresses (Password entries) without key values or with the \".\"\n       default substitution  key value.  This value  can be  used  to  reduce\n       Areafix.Ctl maintenance requirements. If no KeyDefault string is found\n       AreaFix will  default to  \"KeyDefault ?*\"  to allow request forwarding\n       and  idle   passthru  area  purge.  The  KeyDefault  can  contain  any\n       combination of:\n\n         +  List privilege settings in response messages to this address\n\n         ~  Allow remote deletion requests from this address\n\n         @  Allow remote deletion request forwarding to this address\n\n         ?  Allow requests from this address to be forwarded to uplinks\n\n         *  Allow dead-end areas to be purged if this address is the feed\n\n         &  Allow new areas to be created by this address\n\n         #  Add this address to new areas created.\f\n\n     Areafix v1.30                                                    Page 19\n     ------------------------------------------------------------------------\n\n\n\n         $  Always include the active area list with reply/notify messages.\n            This should be set to allow overrides of the global\n            No_Response_List and No_Notify_List parameters.\n\n       NOTE: Area request forwarding WILL NOT WORK unless the node making the\n       request is  configured to  forward either  via the KeyDefault ? or the\n       Password key ? setting.\n\n        Example:\n\n                 KeyDefault PAY@?\n\n\n       Password <net/node> <password> <accesslevel> [key [sysop]]     (Limit:\n                                                                        none)\n\n       In order for a node to have access to Areafix, it must have a password\n       set here.  The password is then entered on the message subject line of\n       the change  request message.  The access level may be from 0 to 32767,\n       with 32767  being the  highest, most  privileged level.  The length of\n       passwords  should  be  limited  to  8  characters,  and  is  NOT  case\n       sensitive.\n\n       An optional  security \"key\"  can be  defined for  a node.  Once access\n       level is  validated the  key will  be used in conjunction with an area\n       LOCK to  further qualify  access for  an EchoMail area. The key string\n       can include any or all of A-Z and 0-5.\n\n       In addition to the 32 optional key characters, the following privilege\n       option mask characters can be added to the field:\n\n         .  KeyDefault key and privilege values will be assigned to this\n            address. Other key values can be used with this flag.\n\n         -  No key or privilege values are assigned to this address.\n\n         +  List privilege settings in response messages to this address\n\n         ~  Allow remote deletion requests from this address\n\n         @  Allow remote deletion request forwarding to this address\n\n         ?  Allow requests from this address to be forwarded to uplinks\n\n         *  Allow dead-end areas to be purged if this address is the feed\n\n         &  Allow new areas to be created by this address\n\n         #  Add this address to new areas created.\n\n         $  Always include the active area list with reply/notify messages.\n            This should be set to allow individual overrides of the global\n            No_Response_List and No_Notify_List parameters.\f\n\n     Areafix v1.30                                                    Page 20\n     ------------------------------------------------------------------------\n\n\n\n       An optional  sysop name can follow the key/privilege field. Sysop name\n       is a  positional parameter  -- it  must be  the  fifth  field  on  the\n       Password line.  As such  the key/privilege  field must be specified if\n       sysop name  is specified. The Sysop name can be any number of words up\n       to 35 characters. Underlines will be converted to blanks.\n\n       The '.'  and '-'  privilege option masks can be used in cases where no\n       explicit list is wanted or needed.\n\n       Example:\n\n                 Password  106/111   Teddy     100       ABCDEF4@*\n                 Password  270/211   Friend    101       ~@*?      Gary Rux\n                 Password  13/13     Bug       24        .         No Name\n\n       Node 106/111 can add any EchoMail area with a security level of 100 or\n       below and with a Lock string consisting of ABCDEF4 or ABC or ADF or 4.\n       Access to  an area  with a  lock string  of ABCDEFG4  would be  denied\n       because the node does not have 'G' in the key string.\n\n       Option  mask   values  @   and  *   are  also   active   to   indicate\n       RemoteDeletionForward is enabled and Purge is disabled for the node.\n\n\n       ProtectDefault\n\n       Defines the  default protect  security level.  This security  level is\n       assigned to  all EchoMail areas not named on Protect lines. This might\n       be useful  in a situation where most areas are a single level. In that\n       case ProtectDefault  can be  used for global security level assignment\n       and Protect can be used for exceptions. Example:\n\n                 ProtectDefault 10\n\n\n       LockDefault\n\n       Defines the  default protect Lock string. This lock string is assigned\n       to all  EchoMail areas  not named  on Protect  lines as  well  as  all\n       EchoMail areas  with no lock/privilege values assigned. It can be used\n       in the same way as ProtectDefault and KeyDefault to reduce Areafix.Ctl\n       maintenance requirements. Example:\n\n                 LockDefault PAY*\n\n\n       Protect <area> <minimum access level> [lock]             (Limit: none)\n\n       The minimum  access level  can be from 0 to 32767. A user must have at\n       least that access level or higher (listed with the 'password' command)\n       to add the area. He can always delete himself from the area, no matter\n       what the access level is.\f\n\n     Areafix v1.30                                                    Page 21\n     ------------------------------------------------------------------------\n\n\n\n       An optional  security \"lock\"  can be  defined for an area. Once access\n       level is  validated access  to an area with a Lock string defined will\n       be limited to nodes with a matching Key. An area with a lock string of\n       ABC can  be accessed  by keys ABC, ABC123, and ABCDEF4. Nodes with key\n       strings AC and AB will not be able to access the area.\n\n       Example:\n\n                 Protect   qm_echo   10        \n                 Protect   qm_beta   0         GREG\n\n       If LockDefault is set to  PAY*  the first Protect line will be treated\n       internally as if entered as:\n\n                 Protect   qm_echo   10        PAY*\n\n\n       Echo_List <path>                                            (Limit: 1)\n\n       When the  user specifies a '-l' subject line switch, Areafix will send\n       back the  first matching  file (if  one is specified) listed here. You\n       may use wildcards, the program will only send the first match, though.\n\n\n       NoRescan\n\n       This switch  will cause  Areafix to  ignore the  message subject  line\n       switch '-r'.\n\n\n       NoQuery\n\n       This switch  will cause  Areafix to  ignore the  message subject  line\n       switch '-q'.\n\n\n       QuickBBSRescanList <file>                                   (Limit: 1)\n\n       Areafix can  do  =kludge=  rescans  with  QuickBBS  when  operated  in\n       conjunction with  Fastfwd.Exe (available  from a number of BBSs). With\n       this option  enabled, Areafix  will  create  a  batch  file  named  as\n       '<file>'.  The format being...\n\n                 FASTFWD A 1 <area number> <area name> <net/node>\n\n       Each area the user wants to rescan will have an entry here. It is your\n       responsibility to  delete the file after running it, otherwise it will\n       be appended to by Areafix.\n\n       If you  need further  information,  please  read  the  docs  that  are\n       included in Fastfwd or an equivalent program.\n\n\n       RescanList <filename   command...>                          (Limit: 1)\f\n\n     Areafix v1.30                                                    Page 22\n     ------------------------------------------------------------------------\n\n\n\n\n       Directs Areafix  to generate lines in a text file for each request for\n       an area  rescan. The  first  parameter  following  RescanList  is  the\n       filename that will receive the rescan text lines. Anything else on the\n       line will be copied to each rescan text line as the command string and\n       will be followed by 5 fields.\n\n       The filename is the required name of the file that will receive rescan\n       list entries.  Command is  optional and  defines the command that will\n       precede area  / address  information in  rescan list  entries. If  the\n       command parameter  is not  used the  word \"Rescan\"  is inserted.  Five\n       'arguments' will be written to rescan list entries:\n\n       The format of lines in the file are ...\n\n                 <command...>  area  zone  net  node  point\n\n       The parameters  are presented separately for flexibility. Programs can\n       use the  individual address  components individually  or combine  them\n       into one or more strings if needed.\n\n       The 5  arguments are  always present  and will  always be separated by\n       spaces. This  allows BATch  file parameter  substitution  with  little\n       difficulty. For example, considering the command line:\n\n                 Areafix Add 2:243/47 INTERUSER FN_SYSOP -R\n\n       If Areafix.Ctl shows:\n\n                 RescanList C:\\Files\\Rescan.Bat ReScanMe\n\n       lines will be written to C:\\Files\\Rescan.Bat as:\n\n                 ReScanMe INTERUSER 2 243 47 0\n                 ReScanMe FN_SYSOP 2 243 47 0\n\n       Or if Areafix.Ctl shows:\n\n                 RescanList C:\\Files\\Rescan.Bat Command /C DoIt\n\n       lines will be written to C:\\Files\\Rescan.Bat as:\n\n                 Command /C DoIt INTERUSER 2 243 47 0\n                 Command /C DoIt FN_SYSOP 2 243 47 0\n\n       In this second example if DoIt is a BATch file it might look like:\n\n                 MyProg ReScan %1 %2:%3/%4\n\n       The resulting lines will resolve to:\n\n                 MyProg ReScan INTERUSER 2:243/47\n                 MyProg ReScan FN_SYSOP 2:243/47\f\n\n     Areafix v1.30                                                    Page 23\n     ------------------------------------------------------------------------\n\n\n\n       RescanListAddress                                           (Limit: 1)\n\n       Controls the  format of  the address  field in  RescanList output. The\n       parameter accepts  one argument  -- either List or String. List is the\n       default.\n\n       List format  presents the address components as space separated fields\n       as in the example above.\n\n       String format presents the address in the familiar zone:net/node.point\n       format. The point is omitted if zero.\n\n\n       ShowFeeds\n\n       At the  end of  a return  message, Areafix  will list  which echos the\n       receiving node  is currently setup for. If you specify this option and\n       the receiving  node is  the FIRST  node listed  for the  in the  area,\n       Areafix will  put a  '*' (asterisk)  beside the  area (on  the  return\n       message), indicating he's the feed.\n\n\n       SaveProcessedMsgs\n\n       By default,  Areafix will  delete the inbound messages after they have\n       been processed. If you'd rather save them, specify this option and the\n       program will  mark them  with the \"Received\" flag instead. The program\n       will skip any messages marked with that flag.\n\n\n       KillSent\n\n       To mark  return messages  as Kill  after Sending, use this option. See\n       the command line \"-k\" option to override this.\n\n\n       ForceIntl\n\n       Forces all  messages generated  by AreaFix  to include an ^AINTL line.\n       The line  is ordinarily  generated  only  when  the  destination  zone\n       differs  from  the  home  zone.  This  switch  forces  the  INTL  line\n       regardless of origin or destination zone.\n\n       ForecIntl is  forced active  whenever using  an aka address to process\n       requests. This is done to assure that return messages are addressed to\n       the proper zone.\n\n\n       AlertNode <net/node>                                        (Limit: 1)\n\n       This option  allows you  to forward  a copy  of return  messages to  a\n       specific address ( zone:net/node.point ). The copy will be bypassed of\n       the return message is already going to the alert address.\f\n\n     Areafix v1.30                                                    Page 24\n     ------------------------------------------------------------------------\n\n\n\n       No_Response_List\n\n       Indicates (when uncommented) that return messages should not include a\n       list of  active areas.  The default  is  to  include  the  list.  This\n       parameter can  save a  considerable  amount  of  processing  and  disk\n       resources on an active system. Examples:\n\n                 include list of active areas: % No_Response_List\n                 omit list of active areas:    No_Response_List\n\n       The command  line -l  switch provides  a temporary  reversal  of  this\n       parameter.\n\n\n       NotifyHeader <file>                                         (Limit: 1)\n\n       The default header message for the NOTIFY function is...\n\n            \"Please check the following list against your EchoMail control\n            file.\"\n\n       If you'd  like to  use something  different, then  specify the file in\n       which your  message is located. Although not absolutely necessary, try\n       to keep the size of this file under 4k.\n\n       The -n command line switch is a temporary override of this parameter.\n\n\n       NotifyExclude <nodes>                                      (Limit: 64)\n\n       If you'd  like to  exclude certain  nodes from  the  NOTIFY  function,\n       specify them here.\n\n\n       NotifyWithEchoList\n\n       This instructs  Areafix to enclose what's listed under 'EchoList' with\n       each NOTIFY message.\n\n\n       No_Notify_List\n\n       Indicates (when uncommented) that Notify messages should not include a\n       list of  active areas.  The default  is  to  include  the  list.  This\n       parameter can  save a  considerable  amount  of  processing  and  disk\n       resources on an active system. Examples:\n\n                 include list of active areas: % No_Notify_List\n                 omit list of active areas:    No_Notify_List\n\n       The command  line -l  switch provides  a temporary  reversal  of  this\n       parameter.\f\n\n     Areafix v1.30                                                    Page 25\n     ------------------------------------------------------------------------\n\n\n\n       RemoteDeletion <node> <to> <password (subj)>               (Limit: 10)\n\n       This option  should be  used  with  extreme  care.  It  gives  certain\n       individuals the power to delete any given area from your control file.\n       The program  will not,  however, remove  any files  from the messages'\n       subdirectory.\n\n       Use this  option if  you'd like  someone (probably  your net EC) to be\n       able to  manage your  control file  remotely. It can come in handy for\n       deleting non-distributed areas without sysop intervention.\n\n       In order for it to work, the message must addressed to the name listed\n       in the  message '<to>'  field, with the proper password (subject line)\n       entry. The  format for  the body  of the  message is  simply the  area\n       name(s) to be deleted, the same way Areafix works.\n\n\n       RemoteDeletionNotify\n\n       When  an  area  is  discontinued,  all  listed  nodes  (that  are  not\n       configured to  forward) will  be sent  a termination  notice with this\n       command enabled.\n\n\n       RemoteDeletionForward\n\n       This is both very POWERFUL and very DANGEROUS. It can be a useful tool\n       but must be used carefully and conservatively.\n\n       When an area is discontinued via a RemoteDeletion request AreaFix will\n       send automated  RemoteDeletion  requests  to  all  affected  addresses\n       rather than notifying them as with RemoteDeletionNotify.\n\n       If an  affected address is listed on a Protect configuration directive\n       and the   @   privilege  flag  value  is  set  for  that  address  the\n       RemoteDeletionNotify message  is replaced  by a  message addressed  to\n       AutoDelete using  the password  listed on  the  Protect  line.  If  no\n       Protect line  exists for  an address the standard RemoteDeletionNotify\n       message is generated.\n\n       The end  result is  that each  system in  the distribution  chain  can\n       configure whether to accept AutoDelete traffic, from whom, and whether\n       and to  whom to  forward the  messages farther  along the distribution\n       chain.\n\n\n       RemoteDeletionRemove\n\n       Triggers removal  of message  subdirectories for  all remotely deleted\n       message areas.  All files  are deleted  from the  subdirectory and the\n       subdirectory itself  is removed.  File protection  and  subdirectories\n       within a  message subdirectory  will prevent  the operation from being\n       completed.\f\n\n     Areafix v1.30                                                    Page 26\n     ------------------------------------------------------------------------\n\n\n\n                 Example: RemoteDeletionRemove\n\n\n       Forward_List <list file> <format> <node> <password> [from] (Limit: 10)\n\n       In the  past, it was necessary for the sysop to manually request areas\n       from his  uplink when  one  of  his  downlinks  wanted  something  not\n       carried. This feature solves that problem.\n\n       You can specify up to 10 files that contain a list of what's available\n       from your  uplink(s). The  files will  be searched in sequential order\n       for the  first area name match. Then, Areafix will send an Areafix add\n       message to the listed node requesting the area and add an entry to the\n       Forward_Que file (see below).\n\n       When the  area arrives,  Areafix will  create the  new area,  add  the\n       original requesting  node(s), inform  them  that  the  area  has  been\n       activated.\n\n       Valid system  types are  ConfMail, Opus, PM, QM, QuickBBS, Squish, and\n       Text. Text format is one area name per line. The area name must be the\n       first field  (word) on the line. Additional information can follow the\n       area name but will be ignored:\n\n                 COMM      PC Communications\n                 TECH      PC Technical\n                 ^Z\n\n       The optional  FROM  field  lets  you  define  a  network  address  (as\n       Zone:Net/Node) that  Areafix will  use  in  requests  it  forwards  to\n       uplinks.\n\n\n       Forward_Que <file>                                          (Limit: 1)\n\n       This is  the file that holds the request forwarding queue. The file is\n       scanned every  time you do an \"Areafix EC\" function. If one or more of\n       the areas  listed here  are found  in the  EchoMail control  file, the\n       corresponding net/node will be added and notified.\n\n       Keep in  mind, though,  that Areafix  treats the new addition the same\n       way it would treat an inbound change request (in a message).\n\n       Thus if  the node  no longer  has a password, or the area is protected\n       higher than  his access  level, the change request will fail. Both the\n       sysop (via  the log  file) and  the end  user (via  a message) will be\n       informed.\n\n       You may make manual additions to this file if you wish. The format is:\n\n                 <requesting (downlink) node> <uplink (feed) node> <area\n                 name> <date>\f\n\n     Areafix v1.30                                                    Page 27\n     ------------------------------------------------------------------------\n\n\n\n       A typical entry might go as follows:\n\n                 1:104/1 1:13/13 CHATTER 10/1/1991\f\n\n     Areafix v1.30                                                    Page 28\n     ------------------------------------------------------------------------\n\n\n\n                             DOS ERRORLEVEL EXIT CODES\n\n\n       Areafix will terminate with one of the following DOS errorlevels set:\n\n         0  No messages were processed, or there were no changes made.\n\n         1  Areafix messages were processed and/or NetMail was generated.\n\n         2  New areas were created (and possibly Areafix messages were\n            processed).\n\n         3  Error during processing.\n\n\n\n\n                               CONFIGURATION MAXIMUMS\n\n\n       These are  the maximum  values configured  into Areafix. If a value is\n       not listed the maximum value is determined by available memory and the\n       combination of options and features selected.\n\n                 Max areas in all files.............2048\n                 Max line length in areas.bbs.......4096\n                 Max forward que file slots.........none\n                 Max purge log file slots...........none\n                 Max nodes in all areas.............1024\n                 Max nodes per area.................1024\n                 Max password defines...............none\n                 Max protect defines................none\n                 Max new areas per execution........128\n                 Max inbound messages per run.......50\n                 Max aka addresses..................255\n                 Max alias names....................10\n                 Max area control files.............10\n                 Max forward_list entries...........10\n                 Max forward list areas.............none\n                 Max purge list entries.............none\n                 Max remote delete requests.........10\n                 Max request scan paths.............6\n\n\n\n                                ENVIRONMENT VARIABLE\n\n\n       If you  intend to  run Areafix  from  a  path  other  than  where  the\n       configuration file  is located  and would  rather  not  use  the  '-c'\n       command  line   option,  you   can  use   the   environment   variable\n       \"AREAFIX=<pathname>\" to locate the file. Example:\n\n                 C:\\> Set AREAFIX=C:\\Config\\Areafix.Ctl\f\n\n     Areafix v1.30                                                    Page 29\n     ------------------------------------------------------------------------\n\n\n\n\n\n                                   PACKAGING LIST\n\n\n                 Read.Me..................Information file.\n\n                 Areafix.Ctl..............Sample configuration file.\n\n                 Areafix.Exe..............The executable.\n\n                 Areafix.Doc..............Documentation.\n\n                 Areafix.Use..............User Guide (for you and your\n                                          downlinks) originally by Jeffrey\n                                          Nonken (1:273/715)\n\n\n\n                                    BUG REPORTS\n\n\n       If you  experience  a  problem  with  Areafix,  please  send  as  much\n       information as  possible about  it to  George Peace at 1:270/101. Your\n       report will  be worked  on as  available  time  permits.  Include  (if\n       possible) at least the following in a uniquely named archive:\n\n         *  Your Areafix control file (Areafix.Ctl).\n\n         *  Your EchoMail control files (Areas.Bbs).\n\n         *  The command line you used to invoke Areafix.\n\n         *  The messages (if any) Areafix had problems with.\n\n         *  Both your Config.Sys and Autoexec.Bat files.\n\n         *  A full description of what happened and how to recreate the\n            trouble.\n\n\n\n                                     DISCLAIMER\n\n\n       This program  is guaranteed  to do  absolutely nothing. Use it at your\n       own risk.  No warranty  is stated or implied. The authors shall not be\n       responsible for  any damages  resulting  from  its  use,  directly  or\n       indirectly.\n\n       This program  is copyrighted  and is the sole property of the authors.\n       It may not be distributed in modified form or without documentation.\f\n\n     Areafix v1.30                                                    Page 30\n     ------------------------------------------------------------------------\n\n\n\n       No fee  other than  the cost of duplication/postage may be charged for\n       distribution of this program.\n\n       You may use the software only after agreeing upon the above terms.\n\n\n\n                                      BEGWARE\n\n\n       As always,  the Areafix  program may  be  used  without  registration,\n       crippled code,  or demands  for payment  to the  author. It's  been my\n       pleasure to participate in the Areafix project for all of us.\n\n       If you  enjoy using  Areafix and  the World's economy has been kind to\n       you I  hope you  will consider  forwarding $10(USD) to George Peace at\n       P.O. Box 6501, Harrisburg, Pa 17112, USA. It would mean alot to me.\n\n\n\n       Thanks for using Areafix!\f"
  },
  {
    "path": "specs/ftn/areasbbs-fmail.txt",
    "content": "(from fmail documentation: https://www.pcorner.com/list/BBS/FM106.ZIP)\n\nTHE AREAS.BBS FILE\n==================\n\nThis section demonstrates everything FreeMail will understand in an AREAS.BBS\nfile and explains the rules it follows in interpreting the lines. It is aimed\nat the user who is not familiar with FidoNet mail programs. I recommend all\nusers at least skim it to get the syntaxes FreeMail allows.\n\nAREAS.BBS is a text file which gives FreeMail (and most other FidoNet\ncompatable mail programs) the information it needs about the message areas. It\nis required. Notice that everything after a semicolon (;) is ignored, and can\nbe used for comments.\n\nThe accepted format for each line is...\n\n... (; )\n\n...where is the official area tag of the echo, and the\nes\nare addresses of other systems which you share this echo with. The\ntells FreeMail where and how to store the messages for that area; the format\ndepends on the type of message-base you use:\n\n(a single-Hudson-base board)\n@ (a multiple-Hudson-base board)\n! (a Spitfire conference number)\n(a *.MSG echomail directory)\n# (a pass-through area; the is optional)\nP (alternate pass-through designation)\n\n\nFreeMail also recognises three control lines in the AREAS.BBS file. The first\nis the /FROM line. This is used when running echomail in multiple networks. It\ntells FreeMail to use one of your alternate addresses as the primary address\nfor the areas following it. For example, if you had an AREAS.BBS file like\nthis:\n\n!05 HOUSTON_CHAT 1:106/1000 ;Houston Chit-Chat conference\n!06 SPITFIRE 1:106/1000 ;Spitfire Support conference\n!07 DBASE 1:106/1000\n/FROM 81:400/21\n!81 OS2MSGS 81:400/100\n!82 OS2BUGS 81:400/100\n\nEvery area listed after a /FROM line will use the address on the /FROM line as\nthe origin. The message will be shown to have come from that address, and the\nOrigin line (if FreeMail has to append one) will use it also. The address\n*must* be one of yours, listed in an ADDRESS or AKA statement in the\nFreeMail.CFG file. If it isn't, FreeMail will complain and refuse to run.\n\nThe second control line FreeMail understands is the /ORG line, to specify a\ncustomized Origin line for one or more echo areas. This is mostly useful only\nin Spitfire setups, in which FreeMail must add an Origin line to every\noutgoing message. Like the /FROM line, it affects every area listed after it,\nuntil another /ORG line overrides it. If you had:\n\n/ORG The Jhereg's Den -- Home of FreeMail\n!10 FREEMAIL 106/4196\n!11 SPITFIRE 109/50\n/ORG The Jhereg's Den -- An it harm none...\n!21 MUNDANE 109/120\n\nThe first /ORG line would affect both the FREEMAIL and SPITFIRE conferences.\nThe second would affect MUNDANE and any conferences listed after it. Those\nareas which have no /ORG line will use the SYSTEM line from the FREEMAIL.CFG\nfile, or a default origin line if SYSTEM is not specified.\n\nThe last control line is the /GATE. This allows you to set up a \"gateway\"\nbetween two different echo areas. All messages going into one of these areas\nwill be \"gated\" into the other as well. Most people will never need this.\n\nThe format of the /GATE line is:\n\n/GATE\n...\n\n...where the is the address (must be one of yours!) that you\nwant these messages to come from; the is the name of the gated\necho, and the\nes are the systems you want to send that echo to.\n\nTo set up a gateway between the echos ERIS and ERIS&MOO, for instance:\n\n/FROM 1:109/536\n!93 ERIS 1:109/120 228\n/GATE 93:9800/0 ERIS&MOO 93:9300/0 9800/3 9810/0\n\nUsing these lines, the ERIS echo would be stored in the Spitfire message area\n93, and sent from 1:109/536 to 1:109/120 and 1:109/228. It would also be gated\nto the ERIS&MOO echo in zone 93, from 93:9800/0 to 93:9300/0, 93:9800/3, and\n93:9810/0. Any messages coming into either of these echos would go out in\nboth, with the proper origin lines appended on the gated side. WARNING:\nBecause gating removes all SEEN-BY and PATH information, there must only be\n*one* system doing the gating per echo area!\n\n\nExamples:\n\n2 L_SYSOP 271/247 ; Felicia's Local messages-to-sysop area\n9 SYSOP-109 109/5 40 400 500 700 800 ; Sysop-only echo for net109\n\nIn the first example, the first line shows that the echo L_SYSOP should be\nstored in the Hudson-style echomail area #2, and it is being sent and received\nfrom 271/247. The zone, if not specified, will default to that of the origin\naddress for that echo.\n\nThe second line is similar. The echo SYSOP-109 is being sent to six different\naddresses from here. Notice the short-form address list -- you don't have to\nspecify the \"net\" portion again if it's the same as the previous one on that\nline. The same it true for the zone, if you use multiple zones.\n\nHudson-style message bases are limited to 200 areas each. The board number\nMUST be between 1 and 200, inclusive, or FreeMail will complain and refuse to\nrun. I don't know of any specific limit on the number of Spitfire areas. There\nis no limit to the number of areas FreeMail can handle except memory; it\nstores the area file in a digested form for speed. One beta-tester runs over\n520 areas with no problems.\n\n\nC:\\BBS\\FUBAR\\ FOOBAR 109/542 536 271/248\n\nThis line says that the FOOBAR echo is a *.MSG-style area, stored in the\nC:\\BBS\\FUBAR directory. It is being passed to three other systems: 109/542,\n109/536, and 271/248. The trailing backslash on the directory name is\noptional.\n\n\n# SAMPLE 109/542 271/248\nP SAMPLE 109/542 271/248\n\nThese lines are identicle in meaning. They say that the echo SAMPLE is being\npassed between 109/542 and 271/248 through my system, but not stored here --\nit is a PASS-THROUGH area. I don't read the hypothetical SAMPLE echo, and my\nusers aren't interested, so I don't want to keep it around taking up disk\nspace.\n\nMost Hudson-base mail programs use the 'P' to designate pass-through; most\nothers use a pound sign (#) followed by a directory name. FreeMail recognises\neither, but does NOT need a directory name for such areas. It uses one pass to\ntoss and scan such messages and does not store them locally.\n\n\nAn Example of a simple Spitfire AREAS.BBS File:\n\n!05 HOUSTON_CHAT 1:106/1000 ;Houston Chit-Chat conference\n!06 SPITFIRE 1:106/1000 ;Spitfire Support conference\n!07 DBASE 1:106/1000\n!08 CLIPPER 1:106/1000\n!09 FOXPRO 1:106/1000\n!10 PARADOX 1:106/1000\n!11 CLARION 1:106/1000\n!12 CONSULTING 1:106/1000\n!13 PC_CONSULT 1:106/1000\n!14 DBRIDGE 1:106/1000\n!15 NEW_SYSOP 1:106/1000\n!16 SYSOP 1:106/1000"
  },
  {
    "path": "specs/ftn/areasbbs-golded.txt",
    "content": "Format\n\n[optional] filename/number/dir echo tag links\n\noptional\n========\n! JAM\nP WildCat\n$ Squish\n"
  },
  {
    "path": "specs/jam/jam.txt",
    "content": "Filename....: JAM-001\nRev.........: 001\nDated.......: 93-07-01\nStatus .....: Released\nSubject.....: JAM message base proposal\nAuthor......: Joaquim Homrighausen\nCo-Authors..: Andrew Milner, Mats Birch, Mats Wallin\n\n    ---------------------------------------------------------------------\n                                  JAM(mbp)\n                The Joaquim-Andrew-Mats Message Base Proposal\n    ---------------------------------------------------------------------\n            Copyright 1993 Joaquim Homrighausen, Andrew Milner,\n                           Mats Birch, Mats Wallin.\n                             ALL RIGHTS RESERVED.\n    ---------------------------------------------------------------------\n\n\n    =====================================================================\n    Restrictions\n    ---------------------------------------------------------------------\n    JAM may be used by any developer as long as these specifications are\n    followed exactly. JAM may be used free-of-charge by any developer\n    for any purpose, commercially or otherwise.\n\n    This document may be freely copied and distributed, but must NEVER be\n    distributed in a modified form. If you have an enhancement request,\n    please contact the author of this document; do not change it\n    yourself.\n\n    All applications that support JAM must include one of the following\n    notices in their documentation and somewhere in the product's credit\n    section:\n\n    \"JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner,\n                               Mats Birch, Mats Wallin.\n                               ALL RIGHTS RESERVED.\"\n\n    or\n\n    \"This product uses the JAM(mbp) API -\n     Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch,\n                    Mats Wallin. ALL RIGHTS RESERVED.\"\n\n    No organization, company, person, entity, or other being may impose\n    any fees for any reason for providing this document or the\n    accompanying API. This document and the accompanying API may not be\n    sold or otherwise transferred for personal or company gain under any\n    circumstances.\n\n    =====================================================================\n    Definitions and general notes\n    ---------------------------------------------------------------------\n    CURRENTREV                1\n\n    JAM                       The JAM message base format.\n\n    CRC                       Cyclic Redundancy Check. All CRC values\n                              calculated on strings must assume that the\n                              data within the string has been converted\n                              to lowercase (A-Z = a-z).\n\n    CRC-32                    32-bit CRC (as used in the Zmodem file\n                              transfer protocol) value. The polynom for\n                              a CRC-32 is edb88320H and the CRC-32 seed\n                              is -1L (ffffffffH).\n\n    uchar                     Unsigned 8-bit value\n\n    ushort                    Unsigned 16-bit value\n\n    ulong                     Unsigned 32-bit value\n\n    UNIX date                 An ulong representing the number of seconds\n                              since midnight, January 1, 1970. UNIX-style\n                              dates is the only form of time stamps used\n                              in JAM (1).\n\n    Message #                 The physical record number within the index\n                              file is used as a message number. The\n                              lowest message number is one (1) and the\n                              highest message number is 4294967295\n                              (ffffffffH).\n\n    FTN                       FidoNet Technology Network\n\n    FTS                       FidoNet Technical Standard\n\n    (1) All timestamps created locally (i.e. those not imported from\n        other systems) are stored in local time.\n\n    =====================================================================\n    Files\n    ---------------------------------------------------------------------\n    Each conference is made up from four files. How and where these files\n    are stored and named is implementation dependant. The only file with\n    a fixed minimum size is the .JHR (header data) file. It has a 1024-\n    byte block used to hold information about a specific message area as\n    described later.\n\n    filename.JHR - Message header data\n    filename.JDT - Message text data\n    filename.JDX - Message index\n    filename.JLR - Lastread information\n\n    A future revision of JAM may also include a file that holds the\n    following three items:\n\n      - The highest assigned user number\n      - The last generated message ID\n      - A global conference list with the conference name, description,\n        and physical location of the message base.\n\n    =====================================================================\n    .JHR file header\n    ---------------------------------------------------------------------\n    Below is the format of the 1024-byte record at the beginning of all\n    .JHR files. The first actual message header starts at offset 1024 in\n    the .JHR file.\n\n    FixedHeaderInfoStruct:\n        ulong   Signature;       // <J><A><M> followed by <NUL>\n        ulong   datecreated;     // Creation date\n        ulong   modcounter;      // Update counter\n        ulong   activemsgs;      // Number of active (not deleted) msgs\n        ulong   passwordcrc;     // CRC-32 of password to access\n        ulong   basemsgnum;      // Lowest message number in index file\n        uchar   RESERVED[1000];  // Reserved space\n    end;\n\n    MODCOUNTER must be incremented and updated on disk each time an\n    application modifies the contents of the message base. When it\n    reaches ffffffffH, it wraps to zero.\n\n    ---------------------------------------------------------------------\n    BaseMsgNum                        Lowest message number in index file\n    ---------------------------------------------------------------------\n    This field determines the lowest message number in the index file.\n    The value for this field is one (1) when a message area is first\n    created. By using this field, a message area can be packed (deleted\n    messages are removed) without renumbering it. If BaseMsgNum contains\n    500, the first index record points to message number 500.\n\n    BaseMsgNum has to be taken into account when an application\n    calculates the next available message number (for creating new\n    messages) as well as the highest and lowest message number in a\n    message area.\n\n    ---------------------------------------------------------------------\n    ????????.JHR                                          Message headers\n    ---------------------------------------------------------------------\n    The .JHR file contains none or more Header records. Each record\n    define one message and contains information about the message and its\n    text (if any). The Header record is of variable length. The layout of\n    the Header record follows.\n\n    MessageHeader:\n        MessageFixedHeader:\n            ulong  Signature;    // <J><A><M> followed by <NUL>\n            ushort Revision;     // Revision level of header          (1)\n            ushort ReservedWord; // Reserved for future use\n            ulong  SubfieldLen;  // Length of subfields               (2)\n            ulong  TimesRead;    // Number of times message read\n            ulong  MSGIDcrc;     // CRC-32 of MSGID line              (3)\n            ulong  REPLYcrc;     // CRC-32 of REPLY line              (3)\n            ulong  ReplyTo;      // This msg is a reply to..\n            ulong  Reply1st;     // First reply to this msg\n            ulong  Replynext;    // Next msg in reply chain\n            ulong  DateWritten;  // When msg was written\n            ulong  DateReceived; // When msg was read by recipient\n            ulong  DateProcessed;// When msg was processed by tosser/\n                                 // scanner\n            ulong  MessageNumber;// Message number (1-based)\n            ulong  Attribute;    // Msg attribute, see \"Msg Attributes\"\n            ulong  Attribute2;   // Reserved for future use\n            ulong  Offset;       // Offset of text in ????????.JDT file\n            ulong  TxtLen;       // Length of message text\n            ulong  PasswordCRC;  // CRC-32 of password to access message\n            ulong  Cost;         // Cost of message\n        end;\n        SubField1                // Extra fields as defined below\n        .\n        .\n        SubFieldXX\n    end;\n\n    (1) This field is intended for future revisions of the specifications\n        to allow the use of a different fixed-length binary message\n        header. The current revision level is one (1).\n\n    (2) The SubfieldLen field is set to zero (0) if the header does not\n        have any subfield data. I.e. the length of the binary header is\n        not included in this field.\n\n    (3) When calculating the CRC-32 of the MSGID and REPLY lines, the\n        text ^aMSGID: and ^aREPLY: should be removed as well as all\n        leading and trailing white space characters.\n\n\n    The SubField structure is made up of an ID, a length specifier, and\n    a block of data. Zero or more subfields may follow the fixed-length\n    binary header. SubFields are not stored in any specific order and\n    are not terminated by any specific character unless otherwise\n    specified.\n\n    SubField:\n        ushort  LoID;            // Field ID, 0-65535\n        ushort  HiID;            // Reserved for future use\n        ulong   datlen;          // Length of buffer that follows\n        uchar   Buffer[datlen];  // DATLEN bytes of data\n    end;\n\n    ---------------------------------------------------------------------\n    Defined LoID codes\n    ---------------------------------------------------------------------\n\n    ID=0, Name=OADDRESS\n\n    A network address. This is used to specify the originating address.\n    More than one OADDRESS field may exist. DATLEN must not exceed 100\n    characters. For a FidoNet-style address, this field must follow the\n    ZONE:NET/NODE.POINT@DOMAIN format where .POINT is excluded if zero\n    and @DOMAIN is excluded if unknown.\n\n\n    ID=1, Name=DADDRESS\n\n    A network address. This is used to specify the destination address.\n    More than one DADDRESS field may exist (e.g. carbon copies). DATLEN\n    must not exceed 100 characters. For a FidoNet-style address, this\n    field must follow the ZONE:NET/NODE.POINT@DOMAIN format where .POINT\n    is excluded if zero and @DOMAIN is excluded if unknown.\n\n\n    ID=2, Name=SENDERNAME\n\n    The sender (author) of the message. DATLEN must not exceed 100\n    characters.\n\n\n    ID=3, Name=RECEIVERNAME\n\n    The recipient of the message. DATLEN must not exceed 100 characters.\n\n\n    ID=4, Name=MSGID\n\n    Used to store the message identification data. All data not relevant\n    to the actual ID string, including leading and trailing white space\n    characters should be removed. DATLEN must not exceed 100 characters.\n\n\n    ID=5, Name=REPLYID\n\n    Used to store the message reply data. All data not relevant to the\n    actual reply string, including leading and trailing white space\n    characters should be removed. DATLEN must not exceed 100 characters.\n\n\n    ID=6, Name=SUBJECT\n\n    The subject of the message. DATLEN must not exceed 100 characters.\n    Note that this field may not be used for FidoNet-style file attaches\n    or file requests.\n\n\n    ID=7, Name=PID\n\n    Used to store the FTN PID kludge line. Only the actual PID data is\n    stored and ^aPID: is stripped along with any leading and trailing\n    white space characters. DATLEN must not exceed 40 characters.\n\n\n    ID=8, Name=TRACE\n\n    This is also referred to as ^aVia information in FTNs. It contains\n    information about a system which the message has travelled through.\n    The format of the field is <YYYYMMDDHHMMSS><Network address> where:\n\n       YYYY is the year (1992-9999)\n         MM is the month (01-12)\n         DD is the day (01-31)\n         HH is the hour (00-23)\n         MM is the minute (00-59)\n         SS is the second (00-59)\n\n    The timestamp is stored in ASCII (0-9) characters. The network\n    address is the address of the system. It is expressed in ASCII\n    notation in the native format of the forwarding system.\n\n\n    ID=9, Name=ENCLOSEDFILE\n\n    A file attached to the message. Only one filename may be specified\n    per subfield. No wildcard characters are allowed. If this subfield\n    is present in a message header, the ATTRIBUTE must include the\n    MSG_FILEATTACH bit.\n\n\n    ID=10, Name=ENCLOSEDFILEWALIAS\n\n    Identical to ENCLOSEDFILE with the exception that the filename is\n    followed by a <NUL> (00H) and an alias filename to be transmited to\n    the remote system in place of the local name of the file.\n\n\n    ID=11, Name=ENCLOSEDFREQ\n\n    A request for one or more files. Only one filemask may be specified\n    per subfield. If the filemask contains a complete path, it is to be\n    regarded as an update file request. If this subfield is present in a\n    message header, the ATTRIBUTE must include the MSG_FILEREQUEST bit.\n    To indicate that a password is to be transmitted along with the\n    request, a <NUL> (00H) character followed by the password is\n    appended. E.g. SECRET*.*<NUL>MYPASSWORD.\n\n\n    ID=12, Name=ENCLOSEDFILEWCARD\n\n    One or more files attached to the message. Only one filename may be\n    specified per subfield. Wildcard characters are allowed. If this\n    subfield is present in a message header, the ATTRIBUTE must include\n    the MSG_FILEATTACH bit.\n\n\n    ID=13, Name=ENCLOSEDINDIRECTFILE\n\n    One or more files attached to the message. The filename points to an\n    ASCII file with one filename entry per line. If alias filenames are\n    to be used, they are specified after the actual filename and\n    separated by a <NUL> (00H) character, e.g. C:\\MYFILE.LZH<NUL>NEWS.\n    Wildcard characters are not allowed.\n\n\n    ID=1000, Name=EMBINDAT\n\n    Reserved for future use.\n\n\n    ID=2000, Name=FTSKLUDGE\n\n    An FTS-compliant \"kludge\" line not otherwise represented here. All\n    data not relevant to the actual kludge line, including leading and\n    trailing white space and ^A (01H) characters should be removed.\n    DATLEN must not exceed 255 characters. The FTS kludges INTL, TOPT,\n    and FMPT must never be stored as separate SubFields. Their data must\n    be extracted and used for the address SubFields.\n\n\n    ID=2001, Name=SEENBY2D\n\n    Used to store two-dimensional (net/node) SEEN-BY information often\n    used in FTN conference environments. Only the actual SEEN-BY data is\n    stored and ^aSEEN-BY: or SEEN-BY: is stripped along with any leading\n    and trailing white space characters.\n\n\n    ID=2002, Name=PATH2D\n\n    Used to store two-dimensional (net/node) PATH information often used\n    in FTN conference environments. Only the actual PATH data is stored\n    and ^aPATH: is stripped along with any leading and trailing white\n    space characters.\n\n\n    ID=2003, Name=FLAGS\n\n    Used to store the FTN FLAGS kludge information. Note that all FLAG\n    options that have binary representation in the JAM message header\n    must be removed from the FLAGS string prior to storing it. Only\n    the actual flags option string is stored and ^aFLAGS is stripped\n    along with any leading and trailing white space characters.\n\n\n    ID=2004, Name=TZUTCINFO\n\n    Time zone information. This subfield consists of four mandatory\n    bytes and one optional. The first character may be a plus (+) or a\n    minus (-) character to indicate a location east (plus) or west\n    (minus) of UTC 0000. The plus character is implied unless the first\n    character is a minus character. The following four bytes must be\n    digits in the range zero through nine and indicates the offset in\n    hours and minutes. E.g. 0100 indicates an offset of one hour east of\n    UTC.\n\n    ---------------------------------------------------------------------\n    Message attributes\n    ---------------------------------------------------------------------\n    MSG_LOCAL       (0x00000001L)   // Msg created locally\n    MSG_INTRANSIT   (0x00000002L)   // Msg is in-transit\n    MSG_PRIVATE     (0x00000004L)   // Private\n    MSG_READ        (0x00000008L)   // Read by addressee\n    MSG_SENT        (0x00000010L)   // Sent to remote\n    MSG_KILLSENT    (0x00000020L)   // Kill when sent\n    MSG_ARCHIVESENT (0x00000040L)   // Archive when sent\n    MSG_HOLD        (0x00000080L)   // Hold for pick-up\n    MSG_CRASH       (0x00000100L)   // Crash\n    MSG_IMMEDIATE   (0x00000200L)   // Send Msg now, ignore restrictions\n    MSG_DIRECT      (0x00000400L)   // Send directly to destination\n    MSG_GATE        (0x00000800L)   // Send via gateway\n    MSG_FILEREQUEST (0x00001000L)   // File request\n    MSG_FILEATTACH  (0x00002000L)   // File(s) attached to Msg\n    MSG_TRUNCFILE   (0x00004000L)   // Truncate file(s) when sent\n    MSG_KILLFILE    (0x00008000L)   // Delete file(s) when sent\n    MSG_RECEIPTREQ  (0x00010000L)   // Return receipt requested\n    MSG_CONFIRMREQ  (0x00020000L)   // Confirmation receipt requested\n    MSG_ORPHAN      (0x00040000L)   // Unknown destination\n    MSG_ENCRYPT     (0x00080000L)   // Msg text is encrypted          (1)\n    MSG_COMPRESS    (0x00100000L)   // Msg text is compressed         (1)\n    MSG_ESCAPED     (0x00200000L)   // Msg text is seven bit ASCII    (1)\n    MSG_FPU         (0x00400000L)   // Force pickup\n    MSG_TYPELOCAL   (0x00800000L)   // Msg is for local use only\n    MSG_TYPEECHO    (0x01000000L)   // Msg is for conference distribution\n    MSG_TYPENET     (0x02000000L)   // Msg is direct network mail\n    MSG_NODISP      (0x20000000L)   // Msg may not be displayed to user\n    MSG_LOCKED      (0x40000000L)   // Msg is locked, no editing possible\n    MSG_DELETED     (0x80000000L)   // Msg is deleted\n\n    (1) This revision of JAM does not include compression, encryption, or\n        escaping. The bits are reserved for future use.\n\n    =====================================================================\n    ????????.JDT                                             Message text\n    ---------------------------------------------------------------------\n    The .JDT file contains the text of messages. The text is stored as an\n    stream of seven or eight bit ASCII data. Allowed characters in the\n    text are 00H through ffH unless the header ATTRIBUTE field has the\n    MSG_ESCAPED bit enabled, in which case the legal range of data is 20H\n    through 7eH.\n\n    An escaped character is stored as \\<hex> where <hex> is the two digit\n    hexadecimal ASCII value of the character. A single \\ is stored as \\\\\n    or \\5C. The case of the hexadecimal ASCII value is irrelevant, i.e.\n    5c is treated as 5C.\n\n    =====================================================================\n    ????????.JDX                                            Message index\n    ---------------------------------------------------------------------\n    The .JDX file is used to quickly locate messages for any given user\n    name or to locate a message with a specific number. Each record in\n    the file consists of two ulongs. The first ulong holds the CRC-32 of\n    the recipient's name (lowercase), the second ulong holds the\n    physical offset of the message header in the .JHR (header) file.\n\n    The record number (+BaseMsgNum) within the .JDX file determines a\n    message's number.\n\n    If both ulongs are -1 (ffffffffH), there is no corresponding message\n    header.\n\n    =====================================================================\n    ????????.JLR                                         Lastread storage\n    ---------------------------------------------------------------------\n    The .JLR file is used to maintain a user's position within a message\n    area. The layout of the \"lastread\" record follows. One record per\n    user is required.\n\n    LastRead:\n        ulong   UserCRC;         // CRC-32 of user name (lowercase)   (1)\n        ulong   UserID;          // Unique UserID\n        ulong   LastReadMsg;     // Last read message number\n        ulong   HighReadMsg;     // Highest read message number\n    end;\n\n    (1) The functions to convert a string to lowercase characters that\n        are provided in the API will only convert characters A-Z (into\n        a-z). It is required that this convention is followed by all\n        applications.\n\n    The UserID field is a unique number for each user. If the \"lastread\"\n    record is deleted, UserCRC and UserID are both set to -1\n    (ffffffffH). An application may not depend on any specific order in\n    the .JLR file. A user's \"lastread\" record may appear anywhere in the\n    file and must be searched for when retrieving it and when storing an\n    updated record.\n\n    =====================================================================\n    Updating message headers\n    ---------------------------------------------------------------------\n    If a header record grows after is has been retrieved from the .JHR\n    file, it must be appended to the end of the .JHR file since it would\n    overwrite the following header otherwise. The .JDX file must be\n    properly updated to indicate the new location of the header record.\n    The old header record must be changed to indicate that it has been\n    deleted by setting the MSG_DELETED bit in the Attribute field and the\n    TextLen field to zero (to prevent a maintenance program from removing\n    the message text that is now pointed to by another header).\n\n    =====================================================================\n    Message base sharing and locking\n    ---------------------------------------------------------------------\n    To allow several programs to access the message base at any given\n    time, region locking is used to protect the message base from being\n    corrupted during updates.\n\n    When an application needs to write to any of the message base files,\n    it must first attempt to lock the first byte of the .JHR (header)\n    file. If the lock call fails, the application must either fail or\n    attempt to lock the file again. The message base files may under no\n    circumstances be updated if the application cannot successfully lock\n    the .JHR file.\n\n    Note that data acquired (read) from the message base may not be used\n    when writing data to the message base, unless the application has\n    maintained a lock of the message base from the time the data was\n    acquired or the MODCOUNTER field is the same as when the data was\n    acquired.\n\n    The application must open the files in shareable (DENYNONE) read/\n    write or readonly mode. The only exception to this is an application\n    that requires exclusive access to the message base, such as a message\n    base maintenance utility, it should open the files in non-shareable\n    (DENYALL) read/write mode.\n\n    =====================================================================\n    Reply threads and linking\n    ---------------------------------------------------------------------\n    JAM introduces a new reply link pointer, not commonly used today.\n    This section is an attempt to describe how reply threads, reply\n    linking, and this new reply link pointer is implemented in JAM.\n\n    One of the major differences is that reply threads in JAM are not\n    based on similar or identical subjects of messages since this method\n    does not allow for proper reply threads.\n\n    The method used in JAM is based on the immediate relation between any\n    given message and direct replies to it. This is supported by many\n    message editors by using the MSGID and REPLY FTS kludge fields. These\n    are common, although expressed differently, in messages not based on\n    FidoNet technology, such as RFC-822. The obvious advantages include\n    allowing a program to easily find the original message to a reply,\n    and to find all replies to any given message.\n\n    The reply thread information consists of three fields: ReplyTo,\n    Reply1st, and ReplyNext. The reason for three fields, as opposed to\n    just two, is that with two fields, it is only possible to keep track\n    of the original message of a reply (which is sufficient) and one\n    reply to any given message (which is not sufficient). With three\n    fields, it is possible to maintain a thread of any number of replies\n    to any given message.\n\n    In the description of the different fields below, the following\n    messages and message numbers will be referred to:\n\n      1 -> 2 -> 4 -> 5\n      :    :\n      :    +--> 8\n      :\n      +--> 3 -> 7\n      :\n      +--> 6\n\n    Message number two, three, and six are replies to message number one.\n    Message number four and eight are replies to message number two.\n    Message number seven is a reply to message number three.\n    Message number five is a reply to message number four.\n\n    ---------------------------------------------------------------------\n    ReplyTo\n    ---------------------------------------------------------------------\n    This field holds the number of the message that this message is a\n    reply to. In the example above, the ReplyTo field would contain the\n    following values:\n\n    Message number one would contain zero; message number two, three, and\n    six, would contain one; message number four and eight would contain\n    two; message number seven would contain three, and message number\n    five would contain four.\n\n    ---------------------------------------------------------------------\n    Reply1st\n    ---------------------------------------------------------------------\n    This field holds the number of the first message that is a reply to\n    this message. In the example above, the Reply1st field would contain\n    the following values:\n\n    Message number one would contain two, message number three would\n    contain seven, and message number four would contain five. All other\n    messages would contain zero.\n\n    ---------------------------------------------------------------------\n    ReplyNext\n    ---------------------------------------------------------------------\n    This field is used to create the actual message thread or chain. In\n    the event that there is more than one reply to any given message, it\n    is necessary to maintain a thread of all the replies; this is due to\n    the fact that the original message can only hold information about\n    the first reply (the Reply1st field) to it.\n\n    The first reply (which the original message's Reply1st field holds),\n    has its ReplyNext field pointing to the second reply, the second\n    reply's ReplyNext field poinst to the third reply, and so on.\n\n    In the example above, the ReplyNext field would contain the following\n    values:\n\n    Message number two would contain three, message number three would\n    contain six, and message number four would contain eight. All other\n    messages would contain zero.\n\n    =====================================================================\n    Contacts\n    ---------------------------------------------------------------------\n    Joaquim Homrighausen                            Telefax: +352 316 702\n    389, route d'Arlon                                Modem: +352 316 702\n    L-8011 Strassen                               eMail: 2:270/17@fidonet\n    Luxembourg                                                joho@abs.lu\n\n    Andrew Milner                                   Telefax: +352 251 621\n    9a, Boulevard Joseph II                           Modem: +352 251 621\n    L-1840 Belair                                 eMail: 2:270/18@fidonet\n    Luxembourg                                             andrew@fido.lu\n\n    Mats Wallin                                    Telefax: +46 8 6453285\n    Frskottsvgen 11                                Modem: +46 8 6453882\n    S-126 44 Hgersten                           eMail: 2:201/329@fidonet\n    Sweden                                                     mw@fido.lu\n\n    // end of file \"jam.doc\"\n"
  },
  {
    "path": "specs/jam/license.txt",
    "content": "    ---------------------------------------------------------------------\n                                  JAM(mbp)\n                The Joaquim-Andrew-Mats Message Base Proposal\n    ---------------------------------------------------------------------\n            Copyright 1993 Joaquim Homrighausen, Andrew Milner,\n                           Mats Birch, Mats Wallin.\n                             ALL RIGHTS RESERVED.\n    ---------------------------------------------------------------------\n\n\n    =====================================================================\n    LEGAL NOTICE\n    ---------------------------------------------------------------------\n\n    The JAM(mbp) documentation and JAM API and information attached\n    hereto, hereafter referred to as JAM, is protected by applicable\n    copyright laws and international treaty provisions. JAM is provided\n    \"as is\", without warranty of any kind or fitness for a particular\n    purpose, either expressed or implied, all of are hereby explicitly\n    disclaimed. The authors only guarantees that JAM will occupy disk\n    space.\n\n    The entire risk as to the quality and performance of JAM is with you.\n    Should JAM prove defective or incorrect, you assume the entire cost\n    of all necessary servicing, repair, and/or correction. In no event\n    shall the authors be liable to the you or anyone else for any damages\n    or costs, including, but not limited to, any lost profits, lost\n    savings, lost income, lost information, loss of the right to use JAM,\n    or other incidental or consequential damages arising out of the use\n    or inability to use JAM.\n\n    All information provided in JAM is subject to change without further\n    notice.\n\n    JAM may be published and distributed to other people as long as no\n    part of it is modified by any means, this includes translation to\n    any other language (technical or social), and as long as no charges\n    are applied (including but not limited to trading). This information\n    may not be used to reverse engineer any application developed by the\n    authors.\n\n    All applications that support JAM must include one of the following\n    notices in their documentation and somewhere in the product's credit\n    section:\n\n    \"JAM(mbp) - Copyright 1993 Joaquim Homrighausen, Andrew Milner,\n                               Mats Birch, Mats Wallin.\n                               ALL RIGHTS RESERVED.\"\n\n    or\n\n    \"This product uses the JAM(mbp) API -\n     Copyright 1993 Joaquim Homrighausen, Andrew Milner, Mats Birch,\n                    Mats Wallin. ALL RIGHTS RESERVED.\"\n\n    All trademarks are trademarks or registered trademarks of their\n    respective holders.\n\n// end of file \"license.txt\"\n"
  },
  {
    "path": "specs/netdocs/network.txt",
    "content": "\n\n\n\n\n\n\n\n                     WWIV Network Docs\n                         v5.3\n                                                            \n                                                            \n                                                            \n                                                            \n                                                            \n       Copyright (c) 2004-2022, WWIV Software Services\n    Copyright (c) 1998-2004, WWIV Software Services, LLC\n               Copyright (c) 1995, Wayne Bell\n\n\n                          Contents\n  1 HISTORY ...........................................     \n  2 INTRODUCTION ......................................     \n  3 REGISTRATION ......................................     \n  4 ORGANIZATION ......................................     \n  5 WWIV SOFTWARE .....................................     \n  6 INSTALLATION ......................................     \n  7 USING THE NETWORK .................................     \n  8 NETWORK FILES .....................................     \n  9 STARTING YOUR OWN NETWORK .........................     \n 10 TROUBLE-SHOOTING NETWORK CONNECTIONS ..............     \n 11 FUTURE DIRECTIONS .................................\n Appendix A - Network message types ...................\n Appendix B - Identifiers Used in BBSLIST .............\n Appendix C - Private Networks ........................\n Appendix D - Automated subboard requests .............\n Appendix E - Multi-Networking ........................\n Appendix F - Symbols in SUBS.XTR .....................\n Appendix G - External Message Interface ..............\n                                                            \n\n======================================================\n1.  HISTORY\n======================================================\n                                                            \n    The first version of WWIVnet Docs was written by Will   \nDaystrom, also known as The Captain (1 @2370), who ran the  \nWhite Star Line and who copyrighted the Documentation for   \nWWIV v4.10 and WWIVnet Docs under White Star Line Software. \nHis documentation was excellent and would not have needed   \nto be rewritten if the WWIV BBS software and the networks   \nassociated with it were not growing and dynamic.  However,  \nv4.21a of WWIV introduced the ability for a BBS to be on    \nmore than one network, and with that ability many new       \nnetworks were started.  This documentation has been         \nrewritten with those changes in mind, so that the current   \ndocumentation will be useful regardless of which WWIV-based \nnetworks a board happens to belong to.  The part of the     \ndocumentation detailing the policies and procedures of      \nWWIVnet has been moved to a separate document.              \n                                                            \n    The second version of the WWIVnet Docs was written by\nFilo in 1995, and was copyrighted by Wayne Bell and WWIV\nSoftware Services (WSS) in order that future versions\ncould be built upon it without anyone's having to worry\nabout copyright infringements.\n\n    This version incorporates all changes up to an including\nthe newly created net51 which is a modern reimplementation\nof the classic Net38 software maintained and distributed by WSS.\n                                                            \n======================================================\n2. INTRODUCTION\n======================================================\n                                                            \n    A network is a voluntary association of bulletin boards \nusing WWIV software and participating in a network by\ncalling one another to facilitate the transfer of elec-     \ntronic mail (email) and message bases (subs).\n                                                            \n    Through this network, a user of any of the bulletin     \nboards that are members may send email to a user of any     \nother board.  A user may also post on a message base which  \nmay be read by the users of systems which subscribe to that \nmessage base; thus, many of the networked subs have         \ninternational distribution.  Because this system of communi-\ncation is read by others and because it has an effect on    \nsystems other than the one on which it originates, a spirit \nof cooperation must prevail.                                \n                                                            \n    Out of this spirit grows systems of organization and    \nregulation which are known as networks and which are        \ndiscussed in separate documents distributed by those        \nnetworks.  This document covers some of the aspects of the  \nsoftware which should be of interest to users and/or sysops \nregardless of the particular WWIV-based network(s) with     \nwhich they are affiliated.                                  \n                                                            \n======================================================\n3. REGISTRATION\n======================================================\n                                                            \n  Registration is not needed for net38.\n\n4.  ORGANIZATION\n======================================================\n                                                            \n    WWIVnet originally began in 1988 with 25 charter        \nmembers who helped Wayne Bell develop the network software  \nand debug it.  Since that time it has spread from a small   \nLos Angeles-based system of local boards to several inter-  \nnational networks.\n\n    When WSS was purchased in 1998, the WWIVnet and the\nsoftware itself were separated from each other to allow\nfor a more flexible operation and administration of the\nnetwork independant of any ties to the software business\nand vice versa.\n                                                            \n     WWIVnet policies are explained in separate document\nprovided by Snorkel 1@2100, the current Network Coordinator.\n\n\n5. WWIV SOFTWARE\n======================================================\n                                                            \n   WWIV v4.20e and up support the automatic request for a\nsub and the automatic removal provided that each board has  \nthe network software to support the feature and provided    \nthat the sysop has configured his board to allow auto-      \nrequests.  Beginning with NET32, the automatic request      \nfeature and an option for the description of the sub in the \nSUBS.LST is included in BOARDEDIT.  This feature should     \nfacilitate a board's adding or dropping subs that are       \nsubscribed to.                                              \n                                                            \n    The network software includes the creation of informa-  \ntional files on each network system which reflects subs or  \nmessages received that have 'no place to go.'  In effect    \nthat would mean that the receiving sysop has not created a  \nmessage base for that sub or has deleted it but is still    \nreceiving mail for it.  The sysop should check this file    \nregularly and if he is receiving subs that he has not       \nordered or does not want, he should notify the sending      \nhost to please remove his system from the distribution      \nlist.  This information and other information on network    \nconnections may be found in your GFILES directory in files  \nnamed NETDAT0.LOG, NETDAT1.LOG and NETDAT2.LOG.  The        \nNETDAT0 is the newest log and NETDAT2 is the oldest log.    \nThese logs are only kept for a three day period unless you  \nmake other provisions to have them saved.  They may         \nprovide useful information to you in terms of what you      \nare/are not receiving and in terms of problems that may     \noccur in your network connection.  Under v4.22 of the BBS   \nsoftware the sysop can access these logs from the bulletin  \nboard by typing a comma at the main menu.                   \n                                                            \n    The sysop should also occasionally review his dead.net  \nfile which will be in DATA.  Messages in this file are      \nthose which were bound for another system but which cannot  \nbe delivered after having arrived on your system.  Often    \nthese are due to one of two factors.  The first case might  \nbe due to a board's having subscribed to a sub and having   \nbeen put on the distribution list for it before that board  \nhas been added to the bbslist.  Thus the system does not    \nknow where to deliver it.  If that is the case, the         \ndead.net should be left alone because once the system is    \nadded, the network software will deliver that mail to the   \nnew system.    The second case would occur when a board has \nleft the network or has been temporarily disconnected from  \nthe network.  It may still be receiving mail because either \nthe sysop failed to notify the host, mail was already in    \nthe system, or because the host sysop has failed to remove  \nthe board from the distribution list.  In that case, the    \nmail may be safely deleted.  Before deleting the mail,      \nyou should check with the board's AC to be sure that the    \nboard is out of the network.                                \n                                                            \n    In addition, the sysop should write the host of the sub \nwhose mail is going to dead.net and inform the host of      \nwhich board is no longer on the network and request that    \nhost delete the board from the distribution list. NET32     \nand up also has a feature to report on undeliverable e-mail \nto another system in the form of a System Short Message     \n(SSM).                                                      \n                                                            \n    Sysops who receive subs from other systems have the     \nresponsibility to restrict access to the sub according to   \nthe rules of the host.  For example, some subs may limit    \naccess to User Number 1, to users with 255 access, or some  \nother requirements such as all posts must not have tag      \nlines.  The receiving sysop must also take steps to inform  \nusers of the rules applying to a particular sub.  GFILES    \nare often a good way of doing this.                         \n                                                            \n    These guidelines for sysops are nothing more than       \ncommon sense and normal courtesy which reflect the desire   \non the part of all to cooperate in order to make the        \nnetwork work properly and efficiently.  One of the          \ninteresting features of the network is that it is a great   \nleveler.  No one (except possibly a few sysops) knows the   \nage of the person making the post; therefore, people's      \nimpressions of the person who posts is made entirely based  \nupon the language used and the thought expressed.  As a     \nconsequence many a young user can convey the impression     \nthat he is much older and more mature, and some older users \nmay convey the impression that they are irresponsible,      \nilliterate users.  One hopes that users will opt to convey  \nthe impression that they are mature, responsible human      \nbeings.                                                     \n                                                            \n    Sysops may choose to promote responsible use of the     \nnetwork by asking users to make their network posts conform \nto certain suggested guidelines.  For example, the Sysop    \nmay request that users:                                     \n                                                            \n   o    Not Use Foul language on the network                \n   o    Not make personal attacks against others            \n   o    Not post a lot of one-line messages on the network  \n   o    Learn the differences between using A, W, or P to   \n        respond to network messages.                        \n                                                            \n    These are merely suggestions for responsible use of the \nnetwork and are not requirements; however, some of those    \nsuggestions are also found in the rules of the hosts of many\nnetwork subs.  Where they reflect the host rules, they are  \ngenerally considered network rules for that sub.            \n                                                            \n     The following information lets you see at a glance the \ntype of message (ie where it originated) when reading       \nmessage bases:                                              \n                                                            \n   [1] = messages posted by you                             \n   <2> = messages posted by someone else remotely           \n   (3) = messages posted by someone else locally            \n                                                            \n     //BOARDEDIT now manages additional information for     \nyou, such as the host system #, whether a sub you host is   \nauto-requestable, and whether the sub is automatically      \nreported for SUBS.LST updates.  This additional info is     \nstored in the \"SUBS.XTR\" file in your data directory, but   \nDO NOT MODIFY THAT FILE DIRECTLY.  Use //BOARDEDIT all the  \ntime.  If you're using net31 or earlier, you'll notice that \nyour nnall.net, allow.net, and subs.pub files will auto-    \nmatically be updated for you.  With net32 or later, the     \nfiles will be deleted, as all the info is now in the        \nSUBS.XTR FILE.                                              \n                                                            \n    You can now gate subboards among networks your system   \nis a member of.  This is done in //BOARDEDIT, simply by     \nentering net info for multiple networks.    \nDo not try listing different sub types in the same network, \nas it probably won't work. Gating DOES work with            \nnet-validation.  You can gate subs as either the host or    \nas a subscriber system, but please do not gate subs unless  \nyou really have a good reason, and know what you're doing.  \nAdditionally, you need the permission of the original sub   \nhost in order to gate messages.                             \n                                                            \n   You must now net subboards by sub name (instead of just   \nsub type). A sub name is 1-7 chars of upper-case letters   \nand numbers, and doesn't start with a number.\n                                                            \nIf you connect to the same system number in multiple        \nnetworks, you can now force a callout to either one (you    \nare prompted to select which one).  Future versions of the  \nnetwork software will allow you to pick up all network      \nmessages for your system on one call to the same connecting \nsystem.                                                     \n                                                            \n    You can now (correctly) forward mail between networks.  \nIf you're using net32 or later, if the person you forward   \nthe email to auto-replies, the reply will correctly go back \nto the original person who sent the email.  System Operators\nalso have the ability to Mail a received e-mail to someone  \nelse and add a message of their own.  In this case, a reply \nis sent to the sytem operator rather than to the original   \nauthor of the mail.  This feature is available in WWIV v4.24\nand higher.                                                 \n                                                            \n6.  INSTALLATION\n======================================================\n                                                            \n    This section takes you step-by-step through the\ninstallation process involved in setting up the network\nexecutbles and other files necessary to the operation of\na WWIV-based network.\n                                                            \n=================================\n  Apply for Network Node Number                           \n=================================\n                                                            \n    The first step is to obtain a node number.  The         \nappropriate method for doing this varies from network to    \nnetwork and is covered in the documentation specific to the \nnetwork that you are interested in.  You may consult the    \nNETWORKS.LST file included with this documentation to       \ndetermine if a \"contact person\" has been designated for the \nnetwork you are interested in.\n\n    The node number should be entered in wwivconfig under the\nnetwork settings. You should also insure that your     \nboard name and telephone number are entered exactly as they \nare shown in the bbslist.net file which are also discussed later.                                   \n                                                            \n=============                                               \n callout.net                                               \n=============                                               \n                                                            \n    You will have a callout.net file which should be placed \nin your DATA directory, or in the case of multiple-networks-\n -in the date directory for each network, and which will    \n show the systems that you connect with. This file is in    \nthe following format:                                       \n                                                            \n  @node [macro options] [transmit options] [callout         \n         options] [password]                                \n                                                            \n   Each of these options is discussed in turn.  The node is \nthe node number of the board you are connecting with.       \n                                                            \n==================\n Transmit Options\n==================\n   Transmit options are basically two.  You may use the &&  \nparameter which means that files will be transferred each   \ndirection when a connection takes place.  If the && is      \nomitted then the transfer will be uni-directional; from you \nto the other board.  In such a situation, you pay to send   \nyour files to the other board, and presumably, it will pay  \nto send its files to you.  This is not a very efficient     \narrangement and is basically discouraged.                   \n                                                            \n                                                            \n=================                                           \n Callout options\n=================                                           \n   These options affect when your board will call the other \nboard.                                                      \n                                                            \n    /x   Call every x minutes, where x is an integer between 10 \n and 1440.  If x is less than 10, then 10 will be used.       \n                                                            \nThis means that the network will force a callout to that    \nboard every x minutes, even if there is no mail waiting to be\nsent to that system.  This parameter is often set to ensure\nthat a system will frequently poll another one.  \n\nNote: that this is changed since net38 and lower, this used\nto be call every hour, but in WWIV 5.2 (net52) was changed\nto be minutes instead of hours.\n\n    =   This means to call during the hours of 6 pm to 6 am \nMonday thru Friday and anytime on weekends).  These para-   \nmeters are handy for those long distance connections        \nutilizing certain LD calling plans.                         \n                                                            \n   -    The minus parameter means to call during times when \nrates are  cheapest (11 pm to 7 am and anytime on           \nweekends).  This parameter is recommended for long distance \nconnections in order to minimize your phone bill.           \n                                                            \n   !    This limits the number of calls per day to 1.  The  \nboard will attempt to call out starting 20 hours after the  \nlast successful connect.  This feature only works with WWIV \nv4.12 or higher.                                            \n                                                            \n   !x   Where x is an integer.  This limits the number of   \ncalls per day to 20 divided by x.  The board will attempt   \nto call out every 20/x hours after the last connect.  This  \nfeature only works with WWIV v4.12 or higher.               \n                                                            \n  +    The plus parameter indicates that your board does    \nnot call the indicated node; instead, that node should be   \ncalling you. If both of you have the + parameter in         \ncallout.net then no transfers will take place between you.  \n                                                            \n  ~    The tilde (~) means that your system will never call \nout to the other system, and that the other system will     \nnever call yours to pick up mail.  The other system will    \nonly call yours to send data to you.                        \n                                                            \n  ^    The caret (^) is used to enable the HSLINK  protocol \nbetween your system and another.  If present on both        \nsystems (and the HSLINK executable is found on both         \nsystems), the network will attempt to use HSLINK as the     \nprotocol instead of Zmodem (or ymodem).  CAUTION: Be sure   \nyou do NOT have the -! modifier in your HSLINK.CFG file.    \nNET32 now appends that modifier to the command line for     \noutgoing Net calls.  If the -! is present in the HSLINK.CFG \nfile, it may cause conflicts that could prevent optimium    \nperformance when recieving Net calls.  See Appendix for     \ndetails on setting up HS/Link for WWIV.\n\n  *    The asterisk (*) is used to force 10 digit dialing\nrequired by many telephone systems due to the increasing\nnumber of telephones and area codes.\n                                                            \n    Another set of parameters may be used to designate that \nthe board should call between certain hours.  These         \nparameters are illustrated below:                           \n                                                            \n  (3 )5     would mean that the board should call between 3 \nam and 5 am.  Times are specified in 24 hour time.  Mid-    \nnight is specified as 0.\n\n  These parameters are useful if you are having a        \nconnection with a board that runs a NET TIME PERIOD or to   \ninsure that local connections take place during non-busy    \nhours.  If none of these time delimiting parameters are     \nused, your board will make the connection with the other    \nanytime that there is mail to go out and the board is not   \nbusy.  This is NOT recommended for long distance            \nconnections unless you are using a WATTS line or other      \nsystem that makes long distance a fixed cost.  It may be    \nused for local connections if desired.\n\n===========\n Passwords                                                  \n===========\n   You should enter the password in your callout.net that\nyou and your connection agreed upon.     \nFor more information on passwords, see the section on Trouble        \nShooting NetWork Connections.  Also note that the password  \nwill be in quotation marks as the last item on each line    \nof callout.net.  If you lose your password for some reason  \nsuch as corrupt files or hard disk failure, you will need   \nto contact the other sysop to have the password removed     \nfrom his callout.net file so that a new one may be          \nestablished.     \n\n==================\n Network Software                                          \n==================\n    Starting with Net51, the network software is included\nwith the BBS distribution and belongs in the same directory\nas bbs and config.dat.\n                                                                                                                     \n=====================\n BBSLIST and CONNECT                                        \n=====================\n   There are basically two ways of using the network        \nsoftware.  One of these ways is best suited for small       \nnetworks and the other lends itself to larger networks.     \nWhile both methods will work for small networks, the large  \nmethod must be used when a network approaches 500 systems   \ndue to the way that some of the software functions.  A      \nsmall network will only need two of the files mentioned     \nbelow (bbslist.net and connect.net) and all nodes will      \nhave a listing in each.  Large networks will use several    \nBBSLIST and CONNECT files.  All of these files should be    \nplaced in the DATA directory if your board is only on one   \nnetwork.  If you are on more than one network, then the     \nfiles for a particular network should be in its separate    \ndirectory as you defined it in wwivconfig option N.     \n\nNote: Net51 and later only support the bbslist.net and\nconnect.net format (not the .## formats).          \n                                                            \n   bbslist.net -  For a small network, this file can list   \nall nodes participating in the network.  The general format \nof this file is discussed in the appendices.  A small       \nnetwork does not need any of the remaining BBSLIST.x files. \nIn a large network, this file functions as a time/date      \nstamp and will normally be two bytes long.  If you did      \nnot get a file like this with your network data files and   \nif things are not functioning properly, you may need to     \ncreate this file.  All that is necessary is to create a     \nfile name of bbslist.net and put a single space inside of   \nit and save it.                                             \n                                                            \n  connect.net -- This file will reflect the connections of\n    all nodes in the network.  For a large network, this will   \n    be a time/date stamp type file similar to that discussed \n    for the bbslist.net.  If things do not work right and the           \n    connect.net file is missing, try creating it with a space\n    inside.                    \n\n     If your connection within the group will be calling    \nyou, then you need only wait until you receive the files.   \nThus, once this update arrives at the board which will be   \ncalling you, that board will callout to you and you will    \nreceive the necessary files.  One exception to this is that \nsome smaller networks use a different method of sending     \nnetwork updates.  If you are on a small, private network,   \nthen you should check with your network administrator       \nregarding what you should do (if anything) in order to      \nreceive updates.                                            \n                                                            \n  If you are to call the other board (and it does not call  \nyou), then you will need to keep in touch with that sysop   \nso that you have an idea of when the network update comes   \nin.  If you obtain new network files via a download or some \nprocess other than receiving them through the network as an \nupdate, then you may need to force the network software to  \ndo an analysis.  This may be done by using the following    \ncommand at the DOS level.  (Note: if you are on more than   \none network, you may need to use \"dot commands\" as          \ndiscussed in the appendix.                                  \n                                                            \n      NETWORK3                                              \n                                                            \nThat will run NETWORK3.EXE which analyzes your BBSLIST,     \nCONNECT, and callout.net files.  If you add a Y after the   \ncommand (ie space Y) then the network will send you a form  \nletter as feedback letting you know the results of the      \nanalysis and sometimes identifying problems with your       \nsetup.                                                      \n                                                            \n     Although it is natural for you to want to begin to     \nsubscribe to subs and so forth, you should exercise         \npatience until you are 'officially' in the network.  If     \nyou order subs before your board is official, then your     \nsystem will show up as \"unknown\" and the mail will not      \nreach you.  Since many hosts of subs like to send new       \nsubscribers the rules regarding posting on that sub, the    \nfact that you are an unknown system may result in a delay   \nin your receiving the sub.  If you wait until you are       \nofficially in the network, then these problems are          \navoided.                                                    \n                                                            \n   If you are joining more than one network, it is          \nimportant that you establish these connections ONE AT A     \nTIME.  The reason for this is simply that if you have       \nseveral callout.net files that have not established         \npasswords and so forth for your connections, it is          \npossible to have the passwords get confused (ie an          \nincorrect association between network and password          \nestablished).  This may be avoided if you proceed in        \nan orderly fashion and add one network at a time.           \n                                                            \n=========================================\n Information Needed for BBSLIST listings                    \n=========================================\n  Your Board Name -- exactly as you want it to appear in    \nthe Network.  You may wish to peruse a current listing of   \nboards on the network in order to select a name that is     \nunique.                                                     \n                                                            \n  Your telephone  -- this should include both area code and \ncomplete number.                                            \n                                                            \n  Maximum Baud -- this should be the maximum baud rate that \nyou can support.  If you are using a high speed modem       \ncapable of more than 2400 bps then you should indicate the  \nmaximum throughput for your modem in modem-to-modem         \nexchanges.                                                  \n                                                            \n                                                            \n  Some networks will also want either your registration     \nnumber (if you are registered).  That information may (or   \nmay not) be reported in brackets in the BBSLIST             \ninformation.                                                \n                                                            \n  The information above will be included in the BBSLIST.XXX \nfor your group along with a group identification number.    \nIn that listing, some networks identify area coordinators   \n(AC's) by a ^ next to the telephone number.  Group or Zone  \nCoordinators are often identified with a %.                 \n                                                            \nFIDONET INSTALLATION                                        \n                                                            \n     Use networkf to interface with FidoNet or other FTN\nbased networks.\n\n\n7.  USING THE NETWORK\n======================================================\n                                                            \n   Using the network is relatively simple.  Sending         \nnetmail, subscribing to network subs and hosting network    \nsubs are discussed in this section.                         \n\n=================\n Sending Netmail                                            \n=================\n   Netmail is like email on your local system.  That is,    \nusers on your board may send email to one another by enter- \ning either the name or user number of the person that the   \nmail is to be sent to.  In netmail, you must also use the   \nnode number as part of the addressing scheme.  Suppose that \nuser number 5 on your system wishes to send netmail to      \nuser 4 (Dr. Seuss) at 4000.  In that case, the netmail could\nbe addressed as follows:                                    \n                                                            \n       4 @4000                                              \n        -or-                                                \n       Dr Seuss @4000                                       \n                                                            \nPlease note that this is merely an example; there is no     \nuser named DR SEUSS @4000.  If the BBS is using NET32 or    \nlater and v4.22 or later, and that board is on multiple     \nnetworks, the software will provide a listing of choices if \nthe node number given is not unique (ie exists on more than \none network to which the board is a member.)                \n                                                            \n     Such mail may be sent by the user in one of several    \nways. The user could simply use the E option to send email  \nand then address it properly.  The user might use the A     \nresponse to send a private message to someone who has       \nposted on a national message base, or the user might use    \neither the A or S to respond to a message received          \nprivately from another system.  Any of these methods will   \nresult in netmail being sent to another system.             \n                                                            \n   Mail may also be sent from one WWIV-based NetWork to     \nanother by using the following type of addressing:          \n                                                            \nNETWORK NAME #UserNumber AT NodeNumber @XXXX where XXXX     \nis the gateway node number.  For example to send mail from  \nWWIVLink to user #1 at node number 1 on WWIVnet, the mail   \nwould be addressed as follows:                              \n                                                            \nWWIVNET #1 AT 1 @4000                                       \n                                                            \nThat is just an example.  Any node that is running the      \nNET32 software can function as a gateway node provided that \nit has connections in both networks.  Addressing gateway    \nmail by name is also permissable.  For example, to address  \nWayne Bell by name in the previous example, you would use:  \n                                                            \nWWIVNET RANDOM AT 1 @4000                                   \nFor those who care, Random is Wayne Bell's handle.          \n                                                            \n=============================\n Subscribing to a Netted Sub                                \n=============================\n                                                           \n   Use B (for boardedit) when\nyou are at  W-F-C or type //boardedit when you are logged   \nonto your BBS and then set up the message base.  Be sure    \nto indicate the sub-type number in the option for that:     \nCompleted result for the New Sysop's Sub might look like    \nthe following :                                 \n                                                            \n                                                            \n  A. Name       : WWIV New Sysop's Forum                    \n  B. Filename   : NEWSYS                                    \n  C. Key        : None                                      \n  D. Read SL    : 60                                        \n  E. Post SL    : 60                                        \n  F. Anony      : No.                                       \n  G. Min. Age   : 0                                         \n  H. Max Msgs   : 50                                        \n  I. AR         : C                                         \n  J. Net Info   :                                           \n         Network     Type   Host    Flags                   \n      a) WWIVNet     22050  4000                            \n  K. Storage typ: 2                                         \n  L. NetValidate:  No                                       \n  M. Require Ansi:  No                                      \n  N. Disable Tag:  No                                       \n  O. Description:  WWIV New Sysop's Forum for Help & Advice \n                                                            \n    Since the host of New Sysop's Forum permits visiting    \nsysops to read and post and since the sysop of this board   \nassigns an SL of 60 and an AR of C to visiting WWIV sysops, \nhe can be sure that the host's requirements are met.        \n                                                            \n    Although you are not required to do so, it is a good    \nidea to send a short thank you or other acknowledgement to  \nthe host to let him know when you begin to successfully     \nreceive messages on the sub.  If the host has special rules \nand regulations that you need to inform your users of, you  \nmay do this in several ways.  You could include such        \ninformation in a form message (i.e., a message named        \nFORMxx.MSG where the xx may be either integers or letters)  \nwhich you send to all users.  You also might make the first \nmessage on the message base contain the rules and then make \nit a permanent message.  If you choose this form, be sure   \nto make such a message before you get hooked up to receive  \nthe messages, else your message will go out on the network. \nFinally, you could put a synopsis of special rules in the   \nGFILES area and direct your users to read that.             \n======================\n Hosting a Netted Sub                                       \n======================\n     As part of some networks, you will receive SUBS.LST, a \nlisting to be found in your network DATA directory regarding\nthe various networked subs that are available for you to    \nsubscribe to.  At some point, you may wish to host a netted \nsub yourself.  If you do, you should first make sure that   \nthere is not another sub already out there serving the same \nneed.  If there is, then you should only host a sub on the  \nsame topic because you think that you can do it better or   \nbecause yours will have a special slant. On the other hand, \nyou may have expertise in an area or information on a       \nsubject which is not being currently addressed on your      \nnetwork and for which you think that there might be a       \ndemand.  In that case, you could decide to host such a sub. \n                                                            \n   To host a sub, you must create an Nsub-type.NET file in  \nDATA and in it, you should keep a list of the systems which \nsubscribe.  The list may be vertical or horizontal as long  \nas there is a space between numbers when they are placed    \nhorizontally.  Personally, I recommend a vertical listing   \nfrom lowest to highest; that way you can easily tell when a \nsub has already subscribed.                                 \n                                                            \n    Because telephone companies are changing the tradition  \nmethod of numbering areas codes in 1995, the use of numeric \nsub-types will certainly decrease.  Each network will have  \nits own policy with respect to whether or not numeric       \nsubtypes can be used and if so under what circumstances.    \nThe documentation here, will illustrate sub-by-name rather  \nthan a numeric subtype.                                     \n                                                            \n    Net32 and V4.22 of WWIV support a Sub-by-Name concept   \nwhich means that you may use any legal 6 letters or         \ncharacters as a SubType.  This numbering convention will    \nenable boards to handle more subs than was possible before  \nunder the sub-as-integer concept.  NOTE that future changes \n(see Section 10 Future Directions) may effectively          \nnecesitate your being able to use the sub-by-name approach. \nThus if you have not upgraded your WWIV version, you should \ngive some thought to doing so soon.                         \n                                                            \n    You may want to develop a form message to send to those \nsysops who subscribe to your sub.  Such a message should    \nremind them of the name, sub-type, and host and it should   \nprovide any rules that you may have regarding who may       \naccess the sub or who may read/post there.  Also you        \nshould get in the habit of reading your mail regularly and  \nresponding quickly to requests for the sub.  If you have    \nindicated (under NET32 and version 4.22) that the sub may   \nbe auto-requested, then if you have a file called           \nSA......NET in GFILES, and if the dots are replaced with    \neither the subtype number of the first 6 letters of the     \nsub-by-name, then that letter will automatically be sent    \nto those who subscribe to the sub with the autorequest      \nfunction.                                                   \n                                                            \n    You may wish to advertise your sub.  There are some     \nNational netted subs which have been developed just for     \nthat purpose and you should use them if you can.            \n                                                            \n    The host has the right to run his sub as he sees fit    \nand may establish any rules he wishes.  The only            \nrestriction on sub topics is that they be legal.  If a host \nchooses to 'throw' someone off of a sub,   the individual   \nhas no recourse.  Of course someone may start her own sub   \nif she wishes.  These rules are followed on most networks,  \nhowever, you should refer to the documentation for the      \nparticular networks you are a member of to see if that net- \nwork has different rules for sub hosts.                     \n                                                            \n   WWIV v4.12 and following introduced a feature known as   \nNet Validation.  This feature may be toggled on or off in   \nBOARDEDIT.  When it is toggled on, messages will not leave  \nyour system until they have been validated.  A host, when   \nreading new messages on a sub, may press X to prevent a     \nmessage from being sent out.  After reading the messages,   \nshe will be asked, \"Net Validate these Messages?\"  A Y      \nresponse will result in all messages being sent out except  \nthose where an X was pressed.  After all messages have been \nread, pressing X will cause them to be sent again.          \nNOTE: This should not be done for it may result in sending  \nout duplicate messages across the network.                  \n                                                            \n8.  NETWORK FILES\n======================================================\n\n     The files discussed below are the Network executable\nfiles which should be placed in the same directory as your  \nBBS.EXE file.  The files which belong in your DATA          \ndirectory are discussed in the next section.                \n                                                            \n  1)   network.exe - This file is provided for compatibility\nwith legacy net38 and below. It spawns networkb for binkp\nconnections over the internet.                             \n\n  2)   network1.exe - This program analyzes P*.NET files to\ndetermine which are for local distribution and which are to \nbe sent to boards that you connect with.  The latter files  \nwill be stored in DATA in sxxxx.net files where xxxx is the \nnode number of the receiving board.                                \n                                                            \n  3)   network2.exe - This program analyzes local mail and\ndistributes it to the proper message sub or to email.       \n                                                            \n  4)   network3.exe - This program analyzes connect.net and\nbbslist.net. The analysis may cause the network software to \nleave you messages.  The sysop should read these messages   \nand respond to them ASAP.  These messages are discussed in  \nthe Appendix.\n                                                         \n  5)   LNET.EXE - This program allows the deletion of\ncorrupted messages prior to their being sent over the net-  \nwork.  It can also be used to delete a message which the    \nSysop does not want to go out over the network....such as   \none which violates the spirit or rules of a Sub.  As a      \ngeneral rule, a Sysop should not use LNET to read outgoing  \nmessages.  One exception to this is to use LNET to read     \nthe messages in dead.net.                                \n                                                            \n   dead.net is a file to be found in DATA for messages      \nthat could not be delivered because the system and/or       \nrouting was in error.  The header for these messages in     \ndead.net indicates the systems which it is for and the      \nnumber of days since it was written.  Sometimes messages    \ngo there because a new board has not gotten set up yet; but \noften they go there because one or more of the destination  \nboards have gone down.  If these messages are several weeks \nold, there is probably no harm in deleting the dead.net.    \n                                                            \n  6)   NETINIT.C - This file needs to be used only if you   \nhave modified the structure or size of the userrec structure.  \nIf you have modified it, compile and run NETINIT and it will \nstore information necessary for the network in the CONFIG.DAT file.\n                                                            \n  7)   REQ.EXE - This file is provided to allow those       \nsystems that do not run WWIV BBS software a means of auto-  \nrequesting subs.   \n\n  8) wwivutil - This is the main utility program for WWIV\n  and has a \"net command to handle various WWIVnet operations.                                         \n                                                            \n  Additional files may be added to the network as the       \ndevelopment progresses or some of the existing files may be \nchanged and/or eliminated.                                  \n                                                            \n======================================\n Files in your Network Data Directory                       \n======================================\n    The files that belong in your network data directory    \nwill vary somewhat from network to network depending upon   \nwhether the \"large\" or \"small\" form or file organization is \nbeing used and upon whether or not the network employs      \ngroup or zone coordinators who send out updates.  As        \nmentioned earlier, those executables (like DEx.EXE type     \nfiles) belong in the network data directory.                \n                                                            \n   In addition, the bbslist.net and possibly BBSLIST.1,     \nBBSLIST.2, etc., the connect.net and possibly CONNECT.1,    \nCONNECT.2, etc. and the callout.net files must be present   \nin order for the network to function properly.  When the    \nnetwork analysis is performed by NETWORK3.EXE, additional   \nbinary data files will be created such as CONTACT.NET,      \nBBSDATA.*, etc.                                             \n   You may also find FBACKHDR.NET (an information file      \ndistributed by the net coordinator for the network),        \nSUBS.LST and perhaps SUBS.1, SUBS.2, etc which provide      \ninformation on the subs available in the network.           \nCATEG.NET, an information file that permits sub hosts to    \ncategorize their subs so that they automatically show up    \nin SUBS.LST according to the proper category.               \nNETWORKS.LST, a file showing the various WWIV networks and  \nwhom to contact for additional information on that network  \nas well as information on the coordinator of that list so   \nthat persons creating a network will know whom to contact   \nto get their network on the listing.                        \n                                                            \n                                                            \n\"Dot Commands\"                                              \n                                                            \n    Beginning with NET32, it is possible to use \"dot        \ncommands\" when it is desireable to force a network          \nexecutable to work with a specific network.  If no \"dot     \ncommand\" is used, the program defaults to using the network \nexecutable with data in the DATA directory.  On the         \nother hand, if you are on more than one network, Option N   \nin wwivconfig will create a file called NETWORKS.DAT in the DATA  \ndirectory.  Dot commands work by using data from the        \nnetworks in the order listed in the NETWORKS.DAT file which \nis the same order that you see when you use option N in     \nwwivconfig.  The first network listed is associated with .0; the  \nsecond with .1, etc.                                        \n                                                            \n   For example, to force LNET to run on the dead.net file   \nin the second network listed, you would use LNET .1.  To    \nforce a network analysis on the third network listed, you   \nwould use NETWORK3 Y .2.  Under NET31, it was necessary to  \nset environmental variables to make these commands work.    \nThese environmental variables are no longer needed under    \nNET32 and should NOT be used.\n                               \n9. STARTING YOUR OWN NETWORK by Jim Nunn, Former NC of IceNET\n======================================================\n\n==================================\n A BASIC COST-FACTOR WWIV NETWORK                           \n==================================\n                                                            \nThe following will describe a basic two node WWIV network.  \nThe steps involved are recruiting another node, creating    \nthe nodelist files which are common to all systems in your  \nnetwork, creating unique callout.net files for each node    \nin your network (usually done by each sysop), adding the    \nnetwork information in section N of wwivconfig, adding the        \nnetworking software to both boards, analyzing the network   \n(automatically done by WWIV or can be manually done), and   \nmaking a network connection via modem to the other node.    \n                                                            \nFirst of all, you need to find ONE other system willing to  \njoin your network. Once this recruitment task is complete,  \nyou need to create two network files:                       \n                                                            \n   connect.net                                              \n   ~~~~~~~~~~~                                              \n     @1  2=0.00                                             \n     @2  1=0.00                                             \n                                                            \n     bbslist.net                                            \n     ~~~~~~~~~~~                                            \n     @1   &  *111-111-1111 #2400  \"@1's BBS\"                \n     @2      *222-222-2222 #2400  \"@2's BBS\"                \n                                                            \nEach node has both these files in their network data        \ndirectories.  To establish the network data directory, go   \ninto wwivconfig, section N, and add in the information as         \nrequested in the menu there (Network Name, node number,     \ndata directory).                                            \n                                                            \nEach node creates their own callout.net file, which goes    \nin the network data directory, thusly:                      \n                                                            \n     For @1:                                                \n     callout.net                                            \n     ~~~~~~~~~~~                                            \n     @2                                                     \n                                                            \n     For @2                                                 \n     callout.net                                            \n     ~~~~~~~~~~~                                            \n     @1                                                     \n                                                            \n                                                            \nYou'll both need to unzip NET33 into your main BBS          \ndirectory.  The files required are the 4 basic networking   \nfiles, NETWORK.EXE, NETWORK1.EXE, NETWORK2.EXE, and         \nNETWORK3.EXE.                                               \n                                                            \nWhen you start the bbs with all these files properly        \ninstalled, WWIV will automatically perform a network        \nanalysis.  If you have done everything right, you'll        \nreceive feedback email from your network, and at the        \nbottom, you'll see the message \"Everything is fine\".        \n                                                            \nWith these basic steps done, email the other node in the    \nnetwork, then sit back and watch as WWIV will automatically \ncallout to the other system within two minutes or so.  Upon \nmaking the first connect, a password will be added to your  \ncallout.net file.   You now have a completely functional    \nnetwork of two systems.                                     \n                                                            \n     OTHER CONSIDERATIONS                                   \n     ~~~~~~~~~~~~~~~~~~~~                                   \nThe basic network above is called a 'cost factored'         \nnetwork.  You'll notice network cost factors after each     \nnode number in a connect line in the connect.net file       \n(e.g. 1=0.00).  These cost factors are taken into account   \nby the networking software to determine routing of email.   \nIt really won't matter in a two node network just how the   \ncosts are set since regardless of cost, you can only send   \nmail to one other node. However, by setting a cost factor   \non one node higher than another, mail will be routed via    \nthe node with the lower cost factor where that node has     \nmultiple network connects.                                  \n                                                            \nBy now, you may be wondering why there's no mention of the  \nmore familiar bbslist.0, bbslist.1, bbslist.2, etc type     \nfiles you have seen in WWIVnet, WWIVlink, IceNET, etc.      \nThese networks have enough systems in them that the         \nnetworking administration task has been split up into       \ngroups, so that several network administrators are          \nresponsible for updating the files, rather than having      \none person do it all.                                       \n                                                            \nHowever, it's awkward to use the multiple bbslist/          \nonnect files for a small network.  WWIVnet started using    \nthem when the network grew to around 575 nodes or so,       \nIceNET at about 400, and WWIVlink at about 550.  Up til     \nyour network is in that range, you'll find it much easier   \nto edit only two files instead of the larger number in the  \ngroup based network.  Once your bbslist gets to around      \n20-25k or so, you need to begin thinking about switching to \nthe group approach.                                         \n                                                            \n     STARTING YOUR OWN WWIV NETWORK                         \n     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                          \nI am frequently asked questions about how to start and run  \na network. With the multi-networking capabilities of        \nWWIV421a+, many of you have thought about how much fun it   \nwould be to have that '1@1' designation by your name.  Let  \nme assure you, it is INDEED fun. However, when I started    \nIceNET, along with a few of my friends, there really were   \nno other major networks besides WWIVnet and WWIVlink, and   \nIceNET found it's niche because it is something new and     \ndifferent, with a personality of it's own.                  \n                                                            \nSo, how DO you start a network today? It's simple. Get one  \nother board to join with you, and you have a two system     \nnetwork, as described above. But if your serious about it,  \nthen I think you should consider several things:            \n                                                            \n     1 - What is the PURPOSE of the network I'm going       \n         to start?                                          \n                                                            \n         Your network should have a THEME and a PURPOSE.    \n                                                            \n     2 - Your network should have a POLICY and GUIDELINES   \n         for operation.                                     \n                                                            \n         A policy is a way of acting, or proceding; a       \n         course.                                            \n                                                            \n     3 - How do I send out network updates?                 \n                                                            \n         To keep your network running smoothly, each system \n         must be using the same nodelists. As the network   \n         grows, you will need to distribute the new files   \n         to each system in a timely and efficient manner.   \n                                                            \n     YOUR NETWORK THEME                                     \n     ~~~~~~~~~~~~~~~~~~                                     \nThink of this just like you would think of hosting a        \nmessage base, but in this case, you are 'hosting' and       \nentire network of systems. Everything that goes on in your  \nnetwork doesn't necessarily have to involve the theme; but  \nyour theme and purpose is the foundation. The theme         \nprovides a special focus for your network, and new systems  \ninterested in your theme will be attracted.                 \n                                                            \n     YOUR NETWORK POLICY                                    \n     ~~~~~~~~~~~~~~~~~~~                                    \nThe policy you establish will be the reference source for   \ndealing with problems and issues as they arise in your      \nnetwork. When something is wrong, you should be able to     \nlook in the policy to get some answers about how to         \nproceed to resolve the problem. You don't have to re-invent \nthe wheel to write a good policy.  Look for the basics in   \nthe WWIVNET guidelines, which contain sound practices which \nhave been demonstrated to work quite well. I believe that a \nshort, elegant, well thought out policy can put your        \nnetwork on a firm footing right from the beginning.         \nInvolve others in the preparation of your policy, then      \nestablish, maintain, and enforce your policy.               \n                                                            \n                                                            \n     A TECHNICAL MATTER - UPDATING THE NETWORK              \n     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~              \nAs your network grows, you will need to edit the            \nconnect.net and bbslist.net files for new systems, remove   \nsystems that drop out, connection changes, and numerous     \nother things that systems within your network will want     \nchanged.                                                    \n                                                            \nOne big question then, is how to get these edited files     \ndistributed to all systems in the network. There are at     \nleast three methods to do this:                             \n                                                            \n     1 - The email method.                                  \n                                                            \n     2 - The message base method.                           \n                                                            \n     3 - Using Wayne Bell's NETUP program, or one of        \n         several NETUP clones.                              \n                                                            \n                                                            \n     THE EMAIL METHOD                                       \n     ~~~~~~~~~~~~~~~~                                       \nIn the beginning, with only a few systems, you can update   \nyour network easily via email, or by just making the files  \navailable for download from your system.  This method is    \nprobably adequate up to about 25 systems.  If your network  \ngrows beyond this size, you will begin to find problems:    \n                                                            \n  o    Some sysops just don't get around to installing the  \n       files                                                \n  o    Unknown systems will begin to show up in email and   \n       message bases on BBS's where the sysop has not       \n       updated his board with the new files.                \n                                                            \n \n     USING NETUP                                            \n     ~~~~~~~~~~                                             \n                                                            \nWhen IceNET grew to about 75 systems, I realized that       \nsomething must be done to improve the updating technique.   \nWe had gone though the stages of using email, a message     \nbase, and even had ICENETUD, a special program written by   \nIcefreezr, IceNET 3@1 (Alan Carauna) that worked with a     \nmessage base somewhat similar to the way Space Dynasty      \nworks.                                                      \n                                                            \nFrom a suggestion by DEATH KNIGHT, IceNET 1@7, I emailed    \nWayne Bell, telling him 'IceNET needs your help', to which  \nhe graciously responded to by offering me NETUP for $300.   \nWhen you buy NETUP, you get three files, the NETUP.EXE,     \nand two special files DE1.EXE and EN1.EXE.  As the Network  \nCoordinator for your network, only YOU have EN1.EXE on your \nsystem, and all other systems have the special DE1.EXE      \n(this file goes into the special DATA directory you set up  \nin WWIV421A+ just for your network).                        \n                                                            \nWhen you execute NETUP.EXE, you will see the following menu \non your system.  Just hit the letter, and the rest is       \nautomatic.                                                  \n                                                            \n                                                            \n     Found:     22 AC's    278 systems                      \n     Using standard bbslist.net and connect.net files.      \n     B> Send bbslist.net to network                         \n     C> Send connect.net to network                         \n     H> Send FBACKHDR                                       \n     N> Send WWIVnews                                       \n     F> Send feedback                                       \n     R> Check registration info                             \n     Q> Quit                                                \n     Which?                                                 \n                                                            \n                                                            \nFor normal updates, I just type in NETUP B C, and don't     \neven have to use the menu.  Recently, in order to have the  \nupdating more uniform, I've begun running NETUP in a batch  \nfile during maintenance, which runs every other day.  With  \nthe rapid growth of IceNET in recent times, this frequency  \nof network updates is required.                             \n                                                            \nIf you are going to run a WWIV network, you will not find a \nbetter resource than Wayne Bell to help you with your       \nsoftware needs for updating your network. As usual with     \nWayne's policy, once you've registered NETUP, he will be    \nthere for you to answer questions and provide updates to    \nNETUP as they are released.                                 \n                                                            \nIn conclusion, if you want to start a network, then do it   \nright.  Work with others to establish your THEME, POLICY,   \nand GUIDELINES.  Use the methods above to begin updating    \nyour network. If you a lucky, and have a lot of friends to  \nhelp you like I did, one day you probably will buy NETUP,   \nas your network will have grown to the point it's a         \nnecessity.                                                  \n                                                            \nI'd like to thank all of the sysops who are in IceNET, and  \nin effect, allow me to be a 1@1 for a premium network. I'd  \nalso like to thank Wayne Bell, and Filo for all their       \nsupport in so many ways.                                    \n                                                            \nRunning a network is a lot of work and responsibility.      \nIt's also a tremendous amount of fun. I'm having the time   \nof my life!                                                 \n                                                            \nIf you have any questions or there is something I can help  \nyou with in starting your network, feel free to email me,   \nJim, 1@1, IceNET :).  If you haven't yet joined IceNET, let \nme know and I'll send you an application, which also        \nincludes the IceNET Policy Statement. As a member of        \nIceNET, you can see how we do things by your participation  \non the IceNET Sysop's Only sub, or the IceNET Guidelines    \nFormation Committee sub. Your users will also gain access   \nto a wide variety of IceNET message bases.                  \n                                                            \nHappy Networking!                                           \n                                                            \n   Jim 1@1 IceNET, August 1993                              \n                                                            \n\n10.  TROUBLE-SHOOTING NETWORK CONNECTIONS\n======================================================\n                                                            \n       Utilizing the NETWORK is really very simple.  If you \nhave tried everything you can think of to remedy a problem  \nand are unable to do so, contact one of the Sysops of a     \nSUPPORT Board and enlist aid.  Sometimes there are problems\nwith the code and/or its compatibility with different       \nmodems; however, those type of problems can only be         \naddressed after all other avenues have been thoroughly      \nexplored, and even then that may not be the solution.  For  \nexample, some WWIV Sysops have made extensive       \nmodifications to the BBS.EXE.  In that event, it may be a   \nmodification that is causing the problem rather than the    \nnetwork software.                                           \n                                                            \n    When seeking help, be prepared to provide information   \non your system, your modem, the error messages you get and  \nso forth.  Debugging network problems is usually a process  \nof eliminating the various possible sources of problems one \nby one.  Any information which you can provide to speed     \nthis process makes it easier on all concerned.              \n                                                            \n    A few common problems, and their solutions, are describ-\ned next.                                                    \n                                                            \nYou force callout and the cursor returns to WFC             \n===============================================             \n                                                            \n    First, be sure that you are attempting to force the     \ncall during any agreed upon hours.  If it is not during     \nthe agreed upon hours, the network software will prompt     \nyou \"Are you sure?\"  An affirmative response will allow the \ncall to proceed.  If the call does not connect, you should  \ndouble check the callout.net, CONNECT.0, and BBSLIST.x to   \nbe sure that no typographical errors were made.  Zeros can- \nnot be o's, group designators must be correct, etc.         \n                                                            \n    Also, under Net20 and later you should ensure that all  \nfiles in your network dATA directory are correct as they    \naffect your board and the board that you connect with.  For \nexample, a failure to show your connection will cause an    \nerror.                                                      \n                                                            \n    If no typographical errors were made, run network3.exe  \nfrom DOS level and force a reanalysis.  If after doing all  \nof these things, the board will still not call out, go to   \nyour network data and delete bbsdata.net, bbsdata.ind, and  \nbbsdata.rou as well as CONTACT.NET and rerun the NETWORK3   \nprogram which will force the reestablishment of the deleted \nfiles.  This will often cure the problem.  If it does not,  \nfirst check your NETDAT0.LOG in GFILES to see if it         \nprovides any clue as to the nature of the problem.  If not, \nyou should then contact one of the support boards and       \nexplain your problem in full detail.   The command line     \nNETWORK3 Y will force local feedback to be sent to you from \nthe network software.  The resulting information may be     \nuseful in determining problems in your network setup.       \n                                                            \nYour board calls out and gets a \"Bad PW\" message            \n===============================================             \n   The \"Bad Password\" message will show up in your net log  \nwhich is readable from WFC by pressing N.  If that is the   \ncase and a successful connection has never been made, then  \nthe remote sysop should ascertain that the callout.net is   \ncorrect.  If so, then check the CONNECT.x and BBSLIST.x.    \nIf a successful connection has been made in the past and a  \npassword between the two boards has been established, then  \ntry again as line noise may be the culprit.  If the \"Wrong  \nPassword\" persists over several tries, then it is possible  \nthat a file has become corrupted.  In this event, both you  \nand the remote sysop need to delete the password which was  \ngenerated by the network and let the net software           \nreestablish the password.  If you have never successfully   \nconnected with the other board, then the error may be due   \nto the other sysop's not having setup for the connection.   \nYou should contact him and ascertain whether or not the     \nconnection if reflected in his CONNECT.xxx file or          \ncallout.net file.  It may also be that a faulty connection  \ncaused his board to create a password whereas yours did     \nnot.                                                        \n                                                            \nYour board calls and gets a \"NO NET\" message                \n============================================                \n    This occurs when an unsuccessful connection occurred.   \nOften it is only because the other board is busy.  The      \nremedy is to try again.  If the board is a new board and    \nyou know it is not busy, then both you and the other sysop  \nshould make certain that all files are in the proper        \nplaces.  There are several Binary files created by the      \nnetwork.  These are CONTACT.NET and BBSDATA.*. Sometimes    \nthese files will become corrupted and this may be the       \ncause of a failure to establish a connection.  You may      \ndelete these two files from the DATA directory and then run \nNETWORK3.EXE again.  This re-analysis will recreate those   \ntwo files and may cure the problem.  This problem (no net)  \nmay also occur when the modems have connected but are not   \nrecognizing each other's signal. It may be that one modem   \nthinks the connection is at 14.4k whereas the other thinks  \nit is at 12k or something else.                             \n                                                            \n                                                            \n11.  FUTURE DIRECTIONS\n======================================================\n                                                            \n    In the near future, WWIV BBS software is likely to      \ninclude some of the following features:\n\n    Networked File Directories - The NFD concept is\nsimilar to message bases.  You subscribe to a NFD\nand when you or one of your users select a file from\nthat directory, a request is sent to the host system\nfor that file subject to Sysop approval.\n\n    File Transfer System - FTS is based on the FILEnet\nfile transfer software.  This future enhancement will\nallow a network to permit the transfer of files in much\nthe same way as messages and email are sent today.  This\nsystem further allows the ability to send files as\nattachments to messages.\n\n    DirectMail - Based on the FidoNet crash mail concept.\nUsers with a sufficient SL have the option of flagging a\nmessage as DirectMail which will be sent directly to the\ndestination system (if it accepts DirectMail) upon logoff.\n\n    Internal Packet Linking -  IPL is based on FLink by\nDennis Meyers. WSS has aquired the rights to FLink and\nwill be incorporating the abililty to link packets from\ndifferent networks over a single connection in a future\nversion of the software.\n                                                            \n                                                            \n                                                            \nAppendix A - Network message types\n======================================================\n                                                            \n   The network recognizes various types of major and        \nminor type messages, and these are often reflected during   \nthe analysis which takes place after a network message is   \nreceived.  The information which follows briefly explains   \neach of these message types.                                \n                                                            \nThese types may be expanded in the future.                  \n                                                            \nmain type 1 - net info                                      \n     (all type 1 msgs must be use method==1)                \n     0 - feedback to sysop                                  \n     1 - bbslist.net                                        \n     2 - connect.net                                        \n     3 - subs.lst                                           \n     4 - wwivnews.net                                       \n     5 - fbackhdr.net                                       \n     6 - Additional wwivnews.net text                       \n     7 - categ.net                                          \n     8 - networks.lst                                       \n     9 - Files sent from NC                                 \n                                                            \n                                                            \nmain type 2 - email                                         \n     (no method requirements)                               \n     minor type not used                                    \n                                                            \n                                                            \nmain type 3 - post (from host to subscriber.                \n                    numeric sub types only)                 \n     (no method requirements)                               \n     minor type is sub type                                 \n                                                            \n                                                            \nmain type 4 - Network Files (future)\n                                                            \nmain type 5 - pre-post (from subscriber to host.            \n              numeric sub types only)                       \n     (no method requirements)                               \n     minor type is sub type                                 \n                                                            \n                                                            \nmain type 6 - external msgs                                 \n     (no method requirements)                               \n     minor type is external message type                    \n                                                            \n                                                            \nmain type 7 - email by name                                 \n     (no method requirements)                               \n     minor type not used                                    \n     (name of destination user at start of msg text)        \n                                                            \n                                                            \nmain type 8 - net edit msgs                                 \n     0  - A partial update to the BBSLIST information.      \n     1  - A request for BBSLIST information to be changed.  \n     2  - A partial update to the connection information.   \n     3  - A request for connection information to change.   \n     4  - An update to NETEDIT's registration record.       \n     5  - A transmittal of the installation message.        \n     6  - A request for to transmit a registration record.  \n     7  - A response to request for a registration record.  \n     8  - A remote request for a net analysis (\"/A\").       \n     9  - An ASCII text response to a remote analysis.      \n     10 - Network Editor E-mail and/or automatic feedback.  \n     11 - A message reporting an error condition.           \n     12 - A request for installation and ver information.   \n     13 - A request for a remote node's ALIASES.NET file.   \n     14 - A request for a node's aliases.                   \n     15 - A response to the alias request.                  \n                                                            \nmain type 9 - subs.lst                                      \n     0 - subs.lst                                           \n     1 - subs.1                                             \n     2 - subs.2                                             \n     ...                                                    \n                                                            \n                                                            \nmain type 10 - UNUSED                                       \n                                                            \n                                                            \nmain type 11 - bbslist.*                                    \n     (method must be 1 or ((minor_type % 256)+256))         \n 0..255   - bbslist.<minor-type>                            \n          - full bbslist update NC-net                      \n 257..511 - bbslist.a<minor-less-256-in-hex>                \n          - full bbslist update GC-NC                       \n 513..767 - bbslist.<minor-type>                            \n          - partial bbslist up NC-net                       \n                                                            \n                                                            \nmain type 12 - connect.*                                    \n     (method must be 1 or ((minor_type % 256)+256))         \n 0..255   - bbslist.<minor-type>                            \n          - full connect update NC-net                      \n 257..511 - bbslist.a<minor-less-256-in-hex>                \n          - full connect update GC-NC                       \n                                                            \n                                                            \nmain type 13 - unused                                       \n                                                            \n                                                            \nmain type 14 - group info (from GC)                         \n     (method must be 257..511)                              \n     0 - email to sysop                                     \n                                                            \n                                                            \nmain type 15 - ssm                                          \n     (no method requirement)                                \n     minor type unused                                      \n                                                            \n                                                            \nmain type 16 - sub add request                              \n     (no method requirement)                                \n     0 - sub by name, sub name first part of text           \n     other - minor-type is sub-type                         \n                                                            \n                                                            \nmain type 17 - sub drop request                             \n     (no method requirement)                                \n     0 - sub by name, sub name first part of text           \n     other - sub type is minor type                         \n                                                            \n                                                            \nmain type 18 - sub add response                             \n     0 - sub by name, sub name is first part of text        \n     other - sub type is minor type                         \n     first byte of text (after sub name, if any) is status  \n     of request                                             \n                                                            \n                                                            \nmain type 19 - sub drop response                            \n     0 - sub by name, sub name is first part of text        \n     other - sub type is minor type                         \n     first byte of text (after sub name, if any) is status  \n     of request                                             \n     1 - not host                                           \n     2 - not there (can't drop you)                         \n                                                            \n                                                            \nmain type 26 - post by name                                 \n     (no method requirements)                               \n     minor type unused                                      \n     sub type is first part of msg text                     \n     This is from subscriber to host, and from host to net  \n                                                            \nmain type 27 - new external                                 \n     (no method requirements)                               \n     minor type is external type                            \n     (see Appendix J)\n\nmain type 28 - game packs\n     minor type assigned by WSS\n     Used for transmitting game data\n                                                            \n  NOTE: all major type 1, 11, 12, and 14 messages are       \nappropriately source-verified.                              \n                                                            \n  Information for this appendix supplied by Wayne Bell\n                                                  \n\nAppendix B - Identifiers Used in BBSLIST\n======================================================\n\n    Effective in Net37, the BBSlist identifiers have\nbeen changed.  The previous modem type identifiers have\nnot been used since net34 was released.  To allow for a\nmore seamless operation with third party add-ons and to\nprovide future expanability some of the identifiers have\nbeen changed.  It is IMPERATIVE that network coordinators\nmake the required changes in their respective network\nfiles as soon as is possible to prevent network problems.\nThe following are the identifiers in use as of Net38:\n\n\n  $ - System is PPP capable (See PPP Project Documentation)\n  \\ - System runs Fido frontend\n  | - System is a telnet node\n  < - System refuses links           (future expansion)\n  > - System uses FTS/BLT system     (future expansion)\n  ! - System accepts direct connects (future expansion)\n  / - System is unregistered\n  ? - System accepts faxes\n  _ - System is a dead end node\n  + - System is network server\n  = - Unused\n\n  & - Network Coordinator\n  % - Group Coordinator\n  ^ - Area Coordinator\n  ~ - Subs Coordinator\n                                                            \n    The identifiers above may be stacked together.  For     \nexample, \"$\\|\" would indicate the system participate in the PPP Project,\nhas a Fido Front End and is telnet capable.\n                                                            \n    The identifier for a dead-end node should not be used   \nexcept in emergencies.  It is a means to force the network  \nto treat a node that would NOT normally be a dead end node  \nas if it were one in order to facilitate temporary          \nre-routing of messages.                                     \n                                                            \nAppendix C - Private Networks\n======================================================\n                                                            \n   The network software may be used for any legitimate      \nprivate network as long as the user understands that the    \nauthor is under no obligation to provide the software which \ndistributes network updates and as long as the functioning  \nof the private network does not interfere in any way with   \nthe functioning of other WWIV-based networks.  WSS\nassumes no responsibility for insuring the operation of\nany private networks utilizing the software.\n\nAppendix D - Automated subboard requests\n======================================================\n                                                            \n  Net29 and above support automated subboard subscriptions. \nIn order for this to work, BOTH systems (the host and the   \nsubscriber) must be running Net29 or later.  The program    \n'REQ.EXE' can be used to subscribe or drop subboards.       \n                                                            \n  There are some files associated with automated            \nsubscription under Net29, Net30, and Net 31:                \n                                                            \n  ALLOW.NET (in the DATA directory) - lists subboard types  \nthat are under automated control.  If you host sub type     \n1701, and you want systems to be able to automatically      \nsubscribe to it, you would have the number 1701 in the      \nALLOW.NET file.  If a sub type is not listed in the file,   \nor the file does not exist, then sysops will not be able to \nautomatically subscribe to the subboard.                    \n                                                            \n  DISALLOW.NET (in the DATA directory) - lists system       \nnumbers that are NOT allowed to automatically subscribe     \n/drop subboards.  If you want to keep a certain system      \nfrom subscribing to any of your subs, place their system    \nnumber in the DISALLOW.NET file.                            \n                                                            \nSA*.NET (in gfiles directory) - This is a text file that is \nsent, as part of a pseudo-email, to a sysop when they are   \nadded to a sub.  If you host sub 1701, then the file        \n'SA1701.NET' would be appended as part of a piece of mail   \nto the sysop that is subscribed to the sub.  It can give    \nany rules of the sub, etc.                                  \n                                                            \nThe DISALLOW.NET file may still be used with NET32 and      \nhigher.                                                     \n                                                            \n    SR*.NET (in gfiles directory) - If a system is not      \nallowed to automatically subscribe to a sub (if the sub     \nisn't listed in the ALLOW.NET, for example), then this      \npiece of mail is appended to a message informing the        \nsysop that he cannot be automatically added to the sub.     \nThe file should list why it isn't under automated control,  \nand if it would be worth the effort to email the sysop      \nand ask for it.  This option also works with NET32 and      \nhigher.                                                     \n                                                            \n  The REQ.EXE program is very simple to use.  You need to   \nknow only if you want to add or drop the subboard, the sub  \ntype, and the host.  You then put all this info on a        \ncommand-line, such as:                                      \n                                                            \n  REQ A 1701 1                                              \n                                                            \n  To REQuest an Add to type 1701 hosted by @1.  To drop the \nsub, you'd say:                                             \n                                                            \n  REQ D 1701 1                                              \n                                                            \n  You should get email back from the system when you are    \nautomatically added/dropped from a subboard.  You will get  \nno mail back, and nothing will happen, if the remote system \nisn't running net29 or later.  If you request to be added   \nto a subboard that you don't have configured into your      \nsystem (in //boardedit), then when the response comes back  \nindicating you were added, the network will automatically   \nrequest that you be dropped from the subboard (since there  \nis nowhere for the  messages to go), and you will NOT get   \nan indication in feedback.                                  \n                                                            \nAppendix E - Multi-Networking\n======================================================\n                                                            \n     Beginning with NET31 and v4.21a of WWIV it is possible \nto network among WWIV-based networks rather easily.  The    \nmethodology for doing this is discussed more thoroughly in  \nthe documentation for WWIV v4.22.  Key things to remember   \nabout multi-networking:                                     \n                                                            \n     a)  Each network should be in its own data directory.  \n     b)  Each network should be setup in wwivconfig option N      \n     c)  All files unique to a network should be put in     \n         that network's DATA directory.                     \n     d)  Network directories should be DOS legal names.     \n\n                                                            \nAppendix F - Symbols in SUBS.XTR\n======================================================\n                                                            \n    You are reminded that you should not modify these       \nsymbols directly.  Always use BOARDEDIT when making changes \nto this file.                                               \n                                                            \nMeaning of symbols                                          \n                                                            \n    A typical entry in SUBS.XTR might look like this:       \n                                                            \n  !8                                                        \n  @Novice & Veteran Sysops Helping Each other with WWIV     \n  #0                                                        \n  $WWIVnet 22050 3 0                                        \n                                                            \n!x  =   The number of the Sub on the board (ie the sub      \n        index in BOARDEDIT.                                 \n@   =   The long description for the sub (for auto-subs-    \n        info)                                               \n#0  =   Flags (currently not used but for future expansion) \n$NETWORK  SubType Flags  Host Category                      \n                                                            \nFlags are 1 for auto-addrop, 2 for auto-info (3 for both).  \n                                                            \nHost is 0 if you are the host (you host it), otherwise the  \nhost system #.                                              \n                                                            \nCategory will be an option that will permit the sysop to    \nself-classify a sub according to pre-defined categories,    \nthus facilitating the maintenance of network wide SUBS.LST  \ntype files.  The categories will be listed in CATEG.NET     \nwhich will be found in the network data directory.          \n                                                            \n                                                            \nAppendix G - External Message Interface\n======================================================\n                                                            \n   Net33 (and later versions) will include a method whereby \nmessages for external programs can be transferred through   \nthe network.  This does not describe how to read network    \ndata files, or how to write net packets, only how to        \nintegrate a program that does those things with the         \nnetwork.  (see the WWIV source code, or WWIVnet technical   \ndocs, for info on that.)                                    \n                                                            \n    All received message packets that are destined for the  \nlocal system are stored into \"local.net\" in your network    \ndata directory.  The network2.exe program is then run to    \nprocess the messages.  If any messages are of the \"new      \nexternal\" type (main_type_new_extern, 0x001b), then they    \nmay be saved for processing by an external net program.     \n                                                            \n                                                            \n    Each external network program requires a program (.exe  \nor .com, NOT .bat), which will take as parameters a         \nfilename of a network file (p*.net format), and a network   \nnumber identifier (.net_num).  Each external network        \nprogram can take as input a contiguous range of             \nminor_type's.                                               \n                                                            \n    External network programs are described in the          \n'EPROGS.NET' which (optionally) exists in the network data  \ndirectory.  The eprogs.net file is a text file, and has a   \nline describing one external net program per line.  Each    \nline has three pieces of information: the program name      \n(1-8 chars), the starting minor_type, and the stopping      \nminor_type.  So, for example, if an external net program    \n'netprog.exe' is to handle main_type 0x1b, minor types      \n100-103, then the line in the eprogs.net file for that      \nprocessor would be:                                         \n                                                            \nnetprog 100 103                                             \n                                                            \n(If the program handles only one minor_type, then the       \nstarting and stopping minor_types should both be the same,  \nand equal to the minor_type to be processed.)               \n                                                            \n   As local.net is processed, any main_type_new_extern      \nmessages encountered cause network2 to search the           \neprogs.net file to see if any external net programs are     \nset up to handle that minor_type.  If none are found, the   \nnet message is thrown away.  If there are two or more       \nprograms listed to process that minor_type, only the first  \nreceives the message.  Net messages accepted for an         \nexternal net program are stored to a temporary file while   \nlocal.net has been processed.  After local.net has been     \ncompletely processed, and deleted, network2 runs the        \nexternal net programs, in order, passing them the           \nfilename of the temporary net file for that program, and    \nan indication of which network is being processed.  After   \nthe program exits, the temporary net file is deleted.       \n                                                            \n   Note that it IS allowable for an external net program    \nto create a p*.net file for outgoing messages, OR to put    \nnet messages to the local.net file which will be            \nimmediately re-processed by the BBS.                        \n                                                            \n   Please do not blindly grab minor_types.  If you need a   \nlot of separate message types, the message type can be      \nstored in the text part of the message and a single         \nminor_type used instead.                                    \n                                                            \n   There are also local.net pre-processors allowed in       \nnet32.  The preprocessors are listed in the 'epreproc.net'  \nfile in the network data directory, one per line.  BEFORE   \nnetwork2 processes ANY of local.net, each preprocessor is   \nrun, in order, passing each the \".net_num\" parameter to     \nindicate which network is being processed.  The pre-        \nprocessor may then scan through local.net, and mark as      \ndeleted (main_type=65535) any message processed by that     \npreprocessor.  The preprocessor may even append additional  \nmessages to the local.net file, if that is desired.\n\n** Note: These are not supported in Net51 or later.\n"
  },
  {
    "path": "specs/netdocs/network_tech.txt",
    "content": "\n\n              Network Technical Documentation\n\n\n                       version 3.0.52\n                             by\n                       Wayne Heyward\n                  aka Midnight Tree Bandit\n                   Updated for Net37, WSS\n                   Updated for Net52, WSS\n\n   Copyright (c) 1998-2022, WWIV Software Services\n               Copyright (c) 1995, Wayne Bell\n\n\n======================================================\n0. Table of Contents\n======================================================\n\n  1.  INTRODUCTION\n  2.  GENERAL OVERVIEW OF WWIV NETWORKING\n  3.  MAKING CONNECTIONS\n  4.  MESSAGE PACKETS\n  5.  BBSLIST/CONNECT FILES AND MESSAGE ROUTING\n  6.  TIPS FOR WRITING WWIVNET SOFTWARE\n\n\n======================================================\n1. INTRODUCTION\n======================================================\n\n A.   History\n\n  Back in 1989, Wayne Bell released the first technical\n  documentation covering the technical workings of the\n  WWIV networking software.  While much of the information\n  in that document is still relevant now, much has changed\n  since 1989.  The Group structure has been added, support\n  for more message types, and support for preprocessors to\n  the packet tossers has been added.\n\n  So in late 1992 or early 1993 Wayne asked for volunteers\n  to rewrite the Network Technical documentation.  No one\n  spoke up. Then in March I started providing WWIV support\n  on the GEnie information service, and some people started\n  asking about getting technical information so they could\n  get their non-WWIV boards to communicate with WWIV\n  networks.  Looking around, I found the original doc, and\n  asked Wayne if anyone had answered his call.  As it\n  turned out, I became the volunteer.  After much\n  procrastination and \"How's the doc coming?\" from Wayne,\n  here it is.\n\n B.   Purpose, Limitations, and Other Info\n\n  The purpose for this document is to explain WWIV based\n  networking interface for those who wish to write software\n  which communicates with WWIV based systems, either\n  independently or as an extra utility for the existing\n  NETXX software.\n\n  The documentation that you are reading now is more an\n  expansion and clarification of the original docs than it\n  is a total rewrite.  Now that the bulk of the work is done,\n  the plan is to update them with each release of NETxx to\n  reflect new features.  The information in this document\n  is current as of the Net52 release (NET52).\n\n  First clarification: in the context of this document, the\n  term \"NETXX\" refers to the software for interfacing\n  WWIV-type networks and any network which uses that\n  software.\n\n  This documentation assumes that the reader at least: a)\n  has a good working knowledge of C and the various C data\n  types and data structures. b)   has a general familiarity\n  of how file transfer protocols work.\n\n  This document is not a replacement for the NetXX\n  Software Documentation.  This doc does not describe how\n  to use the network software, only how it works.  For\n  instructions on using the NETXX software and familiarize\n  yourself with how to use it, see the documentation,\n  which can be found in the current NetXX release.\n\n  A note on the numbering for this document.  This is\n  version 3.0.51.  The first number indicates that this is\n  a major rewrite from the Midnight Tree Bandit which was\n  a rewrite of the original by Wayne Bell.  Unless\n  a major overhaul is done, this is not likely to change.\n  The 0 in the second part indicates that this is the first\n  version of this document.  If there are any major changes\n  or additions made, this will be incremented.  The 52\n  indicates that this information is current as of version\n  52 of the NETXX software (NET52).  Minor changes\n  reflecting small interface changes in the NETXX\n  software will cause this number to be changed.  This\n  number will not always be the same as the latest version\n  of the NETXX software; if there are no changes in the\n  external interface, this document will not be updated.\n\n  Comments concerning this document are welcome as are\n  suggestions for additional information to include,\n  things that could be explained more fully, and so\n  forth. For comments please log a bug on github at \n  http://github.com/wwivbbs/wwiv/issues\n\n C.   Relevant Copyrights and Acknowledgements\n  This document is Copyright 1994 by Wayne Heyward (aka\n  Midnight Tree Bandit) and updated by WWIV Software\n  Services (WSS).  It may be freely distributed provided\n  it is not altered in any way.  This is copyrighted to\n  prevent unauthorized (and possibly inaccurate) changes\n  from being made to this document by anyone other than\n  myself or any other appointed by WWIV Software Services (\n  should I be unable to continue updating this document).\n\n  WWIV BBS and the NETXX software (distributed as NETxx)\n  are Copyright 1989-1995 by Wayne Bell\n  and Copyright 1998-2016, WWIV Software Services.\n\n  The NETXX interface information and code in this\n  document is placed in the public domain, and may be\n  freely used for the purpose of interfacing with WWIV\n  networks and network software.\n\n  I would like to thank Wayne Bell, not only for creating a\n  top notch BBS program that is both powerful and easy to\n  use, but creating a networking scheme that is more\n  painless to set up and operate than any other out there.\n  He has said often that if he knew then what he does now,\n  things would have been different.  I cannot help thinking\n  that the result would have been less elegant or easy to\n  use.\n\n  I would also like to thank Wayne for his patience over\n  the last year and a half, waiting for me to get this\n  document started. I've fired thousands of questions at\n  him the last few weeks in an effort to make this\n  documentation as complete as possible, and he answered\n  every one.\n\n  And finally thanks to Filo, who also provided vital\n  information and advice without which this documentation\n  would be incomplete.\n\n======================================================\n2.  GENERAL OVERVIEW OF WWIV NETWORKING\n======================================================\n\n A WWIV network is basically a loose confederation of WWIV\n BBS systems that use the NETXX (or compatible) software.\n\n The software does not limit the connection structure, so\n the member sysops can connect to anyone they wish (subject\n to the rules of their network).  For ease of\n administration, the network may be split up into Groups,\n each with their own coordinator.  Node numbers are an\n unsigned short int, so that nodes may be assigned a value\n from 1 to 65535. Node numbers from 32000 to 32767 are \n reserved for internal use by WWIV.  For example 32767\n is reserved for Internet network Gateway, and 32765 is\n reserved for native FTN style networking.\n\n The lists of nodes are distributed in two sets of files:\n bbslist.net and connect.net.  The connect.net file\n assigns costs to each connection for each system.\n\n Like all BBS networks, the primary purpose is to exchange\n private mail and public posts between BBSes. The passing\n of files in binary form, however, is not currently\n supported by the NETXX software. There are some third party\n programs and in fact, an entire network which can handle\n the network transfer of files.  All messages also have a\n maximum size limit of 32k.\n\n NETXX (NET38) and earlier is proprietary software, from\n WSS, distributed in netXX.zip by WSS.  Since NET51, the\n network software is a new implementation of a subset of\n this technical specification.  It is not related at all\n in either code or complete functionality to NET38 and\n earlier.\n\n The basic NETXX software distributed as part of the\n BBS software.  It consists of the following programs: \n  * network\n  * networkb\n  * networkc\n  * networkf\n  * network1\n  * network2\n  * network3\n\n NETWORK.EXE is a shim to invoke networkb.exe using the\n same arguments as the legacy networking software.\n\n NETWORKB.EXE is the WWIVnet transport software, it's\n implemented as a BINKP'ish protocol.\n\n NETWORKC.EXE is similar to the old CLNUP.EXE software by\n Cerebrum Software.  It runs the other network{1,2,3} \n commands as needed.\n\n network1 is the first of the two mail tossers.  This\n one takes the incoming packet received by NETWORK.EXE and\n distributed the messages within to their rightful places.\n Local mail goes into local.net, while mail passing through\n to other systems is tossed into packet files for the next\n hop.\n\n network2 tosses the local messages in local.net.  Most\n are messages for email or local subboards, but there are\n also network updates, sub REQuests, software \"pings,\" and\n other special purpose message types.  It also has the\n ability to call on third-party preprocessors for special\n handling of certain types of messages.\n\n network3 processes all the network updates that come\n in.  This helps determine what routing off-system mail\n will take.\n\n Each WWIV network also has its own special encoding and\n decoding programs for handling of updates and network mail\n from the Network Coordinator and Group Coordinators.\n These are the DEmmm.EXE files (mmm corresponding to the\n message type).  The DEmmm.EXE cannot be replaced, so any\n network2 replacement must be able to recognize the\n need for calling the appropriate DEmmm.EXE, as described\n below.\n\n======================================================\n3. MAKING CONNECTIONS\n======================================================\n\n Starting with With Net51, connections happen outside \n of the network software. You use networkb to call out\n to another node or use networkb directly or use a\n proxy like wwivserver or wwivd to listen on BinkP and\n spawn networkb on demand.\n               \n======================================================\n4.  MESSAGE PACKETS\n======================================================\n\n The most important component of any network is the mail\n file, which contains all the public posts, email, and\n network information which makes the BBS network what it\n is.  NETXX mail files consist of a series of mail\n packets, each with its own header segment describing the\n type and size of the packet.\n\n There are two types of mail files in NETXX, each similar\n but processed differently.  The netmail file is the file\n received from another system, and contains packets\n destined for that system as well as other systems in the\n network (if the BBS has more than one connect). The local \n mail file contains the packets from\n the netmail file which are destined for the BBS only.\n\n A.   Message Header\n\n  Each message sent through the network has a header.  The\n  header tells which user/system originated the message,\n  where it is to be sent to, the type of message, and other\n  information.  The structure of the header is:\n\nstruct net_header_rec {\n  uint16_t  tosys,    /* destination system */\n           touser,     /* destination user */\n           fromsys,    /* originating system */\n           fromuser,   /* originating user */\n           main_type,  /* main message type */\n           minor_type, /* minor message type */\n           list_len;   /* # of entries in system list */\n  uint32_t   daten,    /* date/time sent */\n             length;   /* # of bytes of msg after header */\n  uint16_t  method;    /* method of compression */\n};\n\n  Each header is 24 bytes long.  The fields, in detail,\n  are:\n\n  tosys, touser\n\n   The destination of this message (system number and user\n   number, if applicable).  The touser field will be zero in\n   all cases except for email (main_type==2) and SSMs\n   (main_type==15).\n\n  fromsys, fromuser\n\n   The origin of the message (system number and user number).\n   This contains the user number/system number combination of\n   who actually wrote the message.\n\n  main_type, minor_type\n\n   The type of message this is.  The main type stores the\n   actual type (email, post), and the minor_type is used to\n   specify what sub-type it is.  For example, the main_type for\n   a post is 3.  The minor_type is then used to specify what\n   type of post it is, what subboard the post is to go on to.\n   A list of main and minor types is found in section IV(D),\n   below.\n\n  daten\n\n   The time the message was sent, stored in unix time, as the\n   number of seconds since Jan 1, 1970.\n\n  length\n\n   The length of the message.  This includes any information\n   between the packet header and the message itself, such as\n   the sender's name, message title, and so forth.  Note that\n   the length does not include the node list indicated by\n   list_len.\n\n  method\n\n   If the file is encrypted or source-verified,\n   this describes the type of encryption used.\n   This will tell NETWORK2 (or other local mail tosser) which\n   DEmmm.EXE to execute.  DEmmm.EXE is explained in more detail\n   in the next section, below.\n\n  list_len\n\n   Some messages need to go to more than one system.  For\n   example, networked posts may go to over 20 different\n   systems.  It makes no sense to have a separate copy of\n   the message for each destination system, so the same\n   copy of the header and message is used.  (This is\n   referred to as \"stacking\" the message).  The list_len\n   specifies the number of destination systems listed.  If\n   list_len is non-zero, then the touser and tosys fields\n   are ignored.  The list_len is not used for e-mail to a\n   user (main_type is 2 or 7).\n\n   When a message has only one destination system, the\n   destina tion system is stored in tosys, and list_len is\n   zero.  If there are two or more destinations, then tosys\n   is 0, and list_len holds the number of destination\n   systems.\n\n   When list_len is non-zero, the list of destination\n   systems is stored immediately after the header, but\n   before the actual message itself.  The length of the\n   list is not included in the length field in the header;\n   the length stored in the header is the length of the\n   message only.\n\n   Each entry in the destination system list is two bytes\n   long, and is stored in the standard byte-reversed format\n   of 80x86 chips.\n\n   For example, if a post is destined to system 1, the\n   tosys field will be 1, and list_len will be 0.  If the\n   post is destined to systems 1 and 2, tosys will be 0,\n   list_len will be 2, and there will be 4 bytes between\n   the header and message.  The bytes will be: 01 00 02 00\n   (remember, byte-reversed format).  The rest of the\n   header will be the same for both messages.\n\n  A packet thus consists of a net header, a destination\n  list (if any), and the text of the message.  The length\n  of a full message packet is thus: 24 + 2*list_len +\n  msg_length.\n\n  The message text (the part following the header) for a\n  post or email begins with information intended for the\n  message header shown when the message is displayed.  Each\n  piece of information is followed by a carriage return and\n  line feed (cr/lf) character to separate it from the next\n  except for the message title, which is followed by a NUL\n  character.  For most posts and email, that information\n  is:\n\n  Message Title\n\n    Whatever title the user gave to the post.\n\n  Sender name\n\n    usually the name and number of the user who wrote\n    the message with the system number, in whatever\n    format the sending BBS uses.\n\n  Date string\n\n   Formatted date the post was written, in whatever\n   format the BBS uses.\n\n  So the message header format for most posts and email\n  would be\n  TITLE<nul>SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n  Some main_types have other information, as noted in the\n  main_type descriptions in section IV(D).\n\n B.  Mail File Processing\n\n  A NETXX file is simply several packets appended into\n  one file. \n\n  Once it has been received the mail file should be processed \n  following these steps:\n\n  1.   Open the file, and set the current message pointer\n       to the beginning of the file.\n\n  2.   Read in the net header (24 bytes).\n\n  3.   If list_len is non-zero, read in the list following\n       the header (2 * list_len bytes).\n\n  4.   Read in the message itself (length bytes).\n\n  5.   Process the message.\n\n  6.   If not the end of file, go to step 2.\n\n  To ensure the integrity of the mail file, an initial pass\n  over it should be done.  This pass would step through\n  each packet in the file, reading each header and making\n  sure no packets are truncated.  If the file ends in the\n  middle of a packet, then it is obviously corrupted and\n  cannot be processed properly.  At this point, either\n  throw away the whole file or remove the truncated packet\n  and process the remaining packets.\n\n  During the packet tossing, each packet needs to be marked\n  as processed.  Thus, if analysis is interrupted before\n  completion, the packet analyzer can skip over those\n  packets already processed when run again.  To mark the\n  packet as already processed (or deleted), set the\n  main_type to 65535.  Any packet with a main_type of 65535\n  should therefore not be processed.\n\n  The analyzer should follow these steps when processing\n  each packet:\n\n  1.   If main_type is 65535 (deleted), skip the message.\n\n  2.   If list_len is non-zero, do steps 3-6 for each entry\n       in the list, substituting that entry for \"tosys\"\n\n  3.   If tosys is this system, process the file locally\n       (in the case of network1, the message is copied\n       to local.net for processing by the local packet\n       processor).\n\n  4.   If tosys is an unknown system or unreachable, put\n       the packet in the dead mail file.\n\n  5.   If the next system to forward the packet to (\"next\n       hop\") is the system that the message was last\n       received from, put the packet in the dead mail file.\n       This prevents messages from looping\n\n  6.   If the tosys is okay, put the packet into the file\n       that is to be sent to the next hop.\n\n  Of course, it is more complicated than that.  If list_len\n  is non-zero, all destination systems should be processed\n  before the message is stored anywhere.  This way, if the\n  message has 10 destinations, each of which has the same\n  next hop, only one copy of the message will be printed\n  out, that packet with 10 systems in its destination list.\n  Likewise, for a system with more than one connection, if\n  a message has 4 destination systems going through one\n  next hop and 3 going through another, one copy of the\n  message will go into each hop's file -- one with four\n  systems in the node list, the other with the remaining\n  three.\n\n  The dead mail file is reprocessed whenever a network\n  update (new BBSlist or connection list) is received.\n\n C.   Local Mail Processing and DEmmm.EXE\n\n  Processing of local mail packets should be similar to\n  processing of incoming netmail packets.  The main\n  difference between netmail tossing and local mail tossing\n  is that the main and minor types are ignored during\n  netmail processing, and the list_len and node list are\n  ignored (since there won't be a list on local mail).\n\n  1.   Open the file, and set the current message pointer\n       to the beginning of the file.\n\n  2.   Read in the net header (24 bytes).\n\n  3.   Read in the message itself (length bytes).\n\n  4.   Process the message.  This is done according to the\n       main_type and (if applicable) minor_type of the\n       message.\n\n  5.   If not the end of file, go to step 2.\n\n  A few main_types (noted below) cause return messages to\n  be generated to go back out to other systems.  The local\n  mail file analyzer should place these into an interim\n  mail file that will be processed by the netmail file\n  analyzer after local mail processing has been completed.\n  The NETXX local mail analyzer (network2) puts these\n  messages into P1.001 or P2.001.  Then network1\n  analyzes this file and places them into outgoing netmail\n  files for the system's connections.\n\n  Some types of messages that contain network related files\n  such as updates to the nodelists and connect lists and\n  email to all sysops from the NC.  For the sake of\n  network security, these messages have a\n  source-verification signature at the beginning (using,\n  for example, RSA or a similar algorithm). There are\n  several \"methods\" used to handle these messages, and each\n  requires a decryption program, or DEmmm.EXE (where \"mmm\"\n  is the encryption method, as listed in the 'method. field\n  of the net header).  These DEmmm.EXE files MUST be\n  supplied by the NC of each network, and each\n  network's DEmmm.EXE are unique to that network.  That is,\n  NETXX's DE1.EXE will not handle method 1 messages from\n  WWIVLink, nor vice versa.\n\n  When a message is encountered with 'method!=0', the\n  following steps are taken:\n\n  1.   The local packet analyzer writes out the text of the\n       message (no header or node list) to a temporary file\n       (TEMPDE.XXX) in the data directory for the relevant\n       network.\n\n  2.   A command line for calling the appropriate DEmmm.EXE\n       is created using the C command \"sprintf(cmd, \"de%u\n       %s/tempde.xxx\", nh.method, net_data);\" ('nh' is a\n       structure of type net_header_record, 'net_data' is\n       the network data directory).  The command is then\n       executed.\n\n  3.   The DEmmm.EXE program is then responsible for\n       reading the TEMPDE.XXX in from disk, deleting it,\n       then attempting to decode it.  Two things can then\n       happen: a.   If the TEMPDE.XXX fails decoding (bad\n       CRC), DEmmm.EXE just exits (returning to the local\n       packet analyzer). If the analyzer finds the\n       TEMPDE.XXX file does not exist, the message is\n       deleted and the program goes to the next packet. b.\n       If the CRC checks out in the DEmmm.EXE program, it\n       writes out the decoded text into a new TEMPDE.XXX\n       file and exits.  The local packet analyzer reads in\n       the data from that file and replaces the text of the\n       message with that, then goes ahead and processes the\n       packet as determined by main_type.\n\n  Network operators who wish to write EN/DE programs for\n  their own netwide messages may wish to consider using the\n  RSAREF library to develop their own source-verification\n  scheme.\n\n D.   Main and Minor Message Types\n\n  The main and minor type of each message determines how it\n  is processed (where it goes, whether it's a sub post,\n  email, or network info, etc.).  The analyzer reads the\n  message header in first to get the main and minor types,\n  then performs the operation indicated by those fields.\n\n  Here is a list of the main_ and minor_types, along with\n  the WWIV BBS #define name and descriptions of the\n  processing required. Encoding method is assumed to be\n  zero unless otherwise noted. Note that while these\n  descriptions concern analyzing local mail packets, they\n  also apply to how to create outgoing netmail packets.\n\n  main_type 1 (0x0001) -- main_type_net_info\n\n       These messages contain various network information\n       files, encoded with method 1 (requiring DE1.EXE).\n       Once DE1.EXE has verified the source and returned to\n       the analyzer, the file is created in the network's\n       DATA directory with the filename determined by the\n       minor_type (except minor_type 1).\n\n        0 -- Feedback to sysop from the NC.  This is sent\n       to the #1 account as source-verified email.\n\n        1 -- bbslist.net -- Node list.\n\n        2 -- connect.net -- Connections list.\n\n        3 -- SUBS.LST -- List of subboards (\"subs\")\n       available through the network.  This has been\n       replaced by main_type 9.\n\n        4 -- WWIVNEWS.NET -- An electronic magazine of\n       sorts distributed within some networks, usually\n       monthly.\n\n        5 -- FBACKHDR.NET -- a header file added to network\n       update reports for the network.\n\n        6 -- Additional WWIVNEWS.NET text -- appended to\n       the existing WWIVNEWS.NET file.\n\n        7 -- CATEG.NET -- List of sub categories.  WWIV's\n       sub setup facility uses this list so the sysop can\n       specify what category a netted sub falls into.  The\n       network's SUBS.LST compiler uses this information\n       for compiling the subs lists sent out as main_type\n       9.\n\n       8 -- NETWORKS.LST -- A list of all current NETXX\n       type networks.\n\n       This message type is source-verified.  That is,\n       there is a digital signature at the beginning of the\n       message text which is decoded by the DE1.EXE to\n       verify that it has come from a \"legal\" source.  This\n       helps make sure that the network info will only come\n       from the Network Coordinator.  If the source-\n       verification fails, the packet is discarded.\n\n  main_type 2 (0x0002) -- main_type_email\n\n       This is regular email sent to a user number at this\n       system (see tosys and touser, above).  Note that\n       this type of mail should only be received by systems\n       that assign numbers to users (WWIV, VBBS, etc.).\n       BBSes in a WWIV network that only identify users by\n       name (PCBoard, RBBS, etc.) can only receive\n       email-by-name (see main_type 7, below).  Email has\n       no minor type, so minor_type will always be zero.\n\n       Processing of the email is straightforward.  The\n       analyzer looks for the user number indicated by the\n       touser field.  If the number exists and the user has\n       not been deleted from the BBS, the message is\n       written into the email file, addressed to the user\n       indicated.  If the number does not exist or the user\n       at that number has been deleted, the packet is\n       deleted without processing.   Alternatively, the\n       analyzer may generate a return message (as email) to\n       the sender telling him that the mail was not\n       delivered and quoting the message back to him.\n\n  main_type 3 (0x0003) -- main_type_post\n\n       NET51 and later only supports type main_type_new_post.\n\n  main_type 4 (0x0004) -- UNUSED\n\n  main_type 5 (0x0005) -- main_type_obsolete_pre_post\n\n       NET51 only suppors type main_type_new_post.  \n       text (and the list_len field modified reflecting the\n       addition of the node list).  If the file cannot be\n       found, the analyzer assumes the BBS does not host\n       the sub and deletes the packet.\n\n       Many WWIV sysops use a feature of the software known\n       as network validation (\"netval\").  When a sub is set\n       for netval (this is found in the SUBS.DAT record for\n       the sub), the analyzer does not send the post out to\n       the network.  The sysop must validate the post on\n       the BBS, at which point it is sent out by the BBS.\n       This also applies to pre-posts for main_type 26\n       (main_type_new_post).\n\n  main_type 6 (0x0006) -- main_type_unused_external\n\n\n  main_type 7 (0x0007) -- main_type_email_name\n\n       The other email type.  The touser field is zero, and\n       the name is found at the beginning of the message\n       text, followed by a NUL character.  Minor_type will\n       always be zero.\n\n       When this type of packet is encountered, the\n       analyzer gets the name from the beginning of the\n       message text and searches through the BBS's user\n       list to find the specified name.  If it is found,\n       the message is written into the email file for the\n       BBS.  If it is not, the message will be deleted or a\n       return email may be sent back to the sender,\n       explaining that the message was not delivered and\n       quoting the email back.\n\n       The destination user's name is prepended to the\n       beginning of the message text, followed by a NUL,\n       then the rest of the usual message header info and\n       the message text.  The message header info at the\n       beginning of email-by-name messages is thus\n       DEST_USER_NAME<nul>TITLE<nul>SENDER_NAME<cr/lf>\n       DATE_STRING<cr/lf>MESSAGE_TEXT.\n\n  main_type 8 (0x0008) -- main_type_obsolete_net_edit\n\n  main_type 9 (0x0009) -- main_type_sub_list\n\n       Networks with large subs lists (over 32k) break them\n       up into parts and send the set out under this main\n       type rather than the subs.lst type under main_type\n       1.  The minor_type indicates the part of the subs\n       list.\n\n       When the analyzer processes this type, it creates a\n       file in the appropriate network directory and copies\n       the message text into it.  Minor_type zero creates\n       the file SUBS.LST, and all other minor_types create\n       a SUBS.x file where 'x' is the minor_type.\n\n  main_type 10 (0x000a) -- UNUSED\n\n  main_type 11 (0x000b) -- main_type_not_implemented_group_bbslist\n\n  main_type 12 (0x000c) -- main_type_not_implemented_group_connect\n\n  main_type 13 (0x000d) -- UNUSED\n\n  main_type 14 (0x000e) -- main_type_not_implemented_group_info\n\n  main_type 15 (0x000f) -- main_type_ssm\n\n       WWIV BBSes also send out small messages, known as\n       \"SSMs\", across the network.  These are little\n       one-line messages generally telling users when their\n       mail has been read and so forth.  Some BBSes have\n       been modified to send other types of messages.  At\n       any rate, main_type handles these small messages.\n       Minor_type is always zero.\n\n       Like email, the analyzer searches for the user\n       number in the BBS's user list.  If found, the\n       message is written into the SSM file for the BBS.\n       Since this is a feature most non-WWIV systems do not\n       support, they can be ignored.\n\n  One feature of WWIV networking is the ability fpr network\n  sysops to send \"REQs\" to the hosts of subs, enabling them\n  to automati cally subscribe to and drop subs they belong\n  to.  Main_types 16 through 19 handle REQs and their\n  responses.\n\n  main_type 16 (0x0010) -- main_type_sub_add_req\n\n       This is for requests to add the sending system to a\n       sub's subscriber list.  Minor_type will be the\n       numeric sub type, or zero for alphanumeric sub\n       types.  For minor_type==0, the sub type (followed by\n       NUL) will be the message text. Otherwise, there\n       should be no message text (if there is, ignore it).\n\n       When this message type is received, the analyzer\n       should search for the subtype's subscriber file\n       (N[subtype].NET for WWIV systems).  If the file is\n       found, the system number of the new subscriber is\n       added, if it is not in there already. If the add is\n       successful, it will then look for a text file in the\n       data directory (SA[subtype].NET for the NETXX\n       software) that contains information the sysop wants\n       to send back to the subscriber.   A type 18 message\n       is sent to the subscriber indicating status of the\n       add request (see below) and including the text in\n       the SA[subtype].NET file, if one is found.  If the\n       add is not allowed, the analyzer looks for\n       SR[subtype].NET and sends that text back to the\n       requester. If the add is otherwise unsuccessful, the\n       type 18 message will include the status and a short\n       explanation of why the add was not succcessful.\n\n  main_type 17 (0x0011) -- main_type_sub_drop_req\n\n       This is the same as a main_type 16 message, except\n       that it is sent by a subscriber wishing to drop a\n       sub.  The minor_type is determined the same way as\n       main_type 16. There should be no message text, but\n       if there is any, it is ignored.\n\n       Processing is similar to a type 16 message.  The\n       analyzer searches for the subtype's subscriber file,\n       and upon finding it removes the subscriber's system\n       number from it, if it is there.  Status of the drop\n       request is returned to the sender in a main_type 19\n       message, with a short message appended that explains\n       the status.\n\n  main_type 18 (0x0012) -- main_type_sub_add_resp\n\n       This carries the status response to a main_type 16\n       (sub add request).  The minor_type is determined the\n       same way as type 16 message.  The first byte of\n       message text (after the subtype, if minor_type==0)\n       is the status of the add request. Possible status\n       byte values are:\n\n       0 -- Subscriber added successfully.\n\n       1 -- This system is not the host (N[subtype].NET not\n       found).\n\n       3 -- Not allowed to add subscribers automatically.\n\n       4 -- System number already there (can't add it\n       again).\n\n\n       When received, the processor will send the message\n       text mentioned in the main_type 16 description\n       (minus the status byte) to the sysop as email.\n\n  main_type 19 (0x0013)- main_type_sub_drop_resp\n\n       Similar to main_type 18, this carries the response\n       to a sub drop request, with the minor_type following\n       the same conventions as above.  This also carries a\n       status byte as the message text:\n\n       0 -- Sub dropped successfully.\n\n       1 -- This system is not the host.\n\n       2 -- System number is not there (can't drop it).\n\n       3 - not allowed to drop subscribers automatically.\n\n       When received, the processor will send the message\n       text mentioned in ther main_type 17 description\n       (minus the status byte) to the sysop as email.\n\n  main_type 20 (0x0014) -- main_type_sub_list_info\n\n       In many WWIV networks, the subs list coordinator\n       (SLC) occasionally sends out \"pings\" to all network\n       members.\n\n       When this message type is received from the SLC\n       (minor_type 0), the analyzer checks the BBS's sub\n       data file.  If there are any subs hosted by the\n       receiving system which are flagged for inclusion in\n       the distributed SUBS.LST, a list of them is returned\n       to the SLC via another main_type 20 message with\n       minor_type==1).  When the SLC recieves the reply, it\n       is written into SUBS.INF in the network's data\n       directory (appended if the file exists).\n\n  main_type 26 (0x001a) -- main_type_new_post\n\n       Subtypes are seven characters -- the first must be a\n       letter, but the rest can be any character allowed in\n       a DOS filename.  This main_types covers both\n       subscriber- to-host and host-to-subscriber messages.\n       Minor type is always zero (since it's ignored), and\n       the subtype appears as the first part of the message\n       text, followed by a NUL. Thus, the message header\n       info at the beginning of the message text is in the\n       format SUBTYPE<nul>TITLE<nul>\n       SENDER_NAME<cr/lf>DATE_STRING<cr/lf>MESSAGE_TEXT.\n\n  main_type 27 (0x001b) -- main_type_unused_new_external\n\n======================================================\n5.  BBSLIST/CONNECT FILES AND MESSAGE ROUTING\n======================================================\n\nSo how does the network software know where to send an\noff-system message, especially if the BBS has more than one\nconnect?  FidoNet has its nodelists, and so does NETXX.\nNETXX actually has two different types of node lists, as\nmentioned elsewhere.  We'll take these separately, then\ndiscuss figuring out the routing.\n\n A.  NETXX -- bbslist.net & connect.net\n\n In the beginning of NETXX, there were only two files\n needed to keep up with the systems in the network --\n bbslist.net and connect.net.  Though this is rarely used\n now, there are still some smaller networks which use these\n files, so they should be discussed.\n\n bbslist.net holds a listing of what systems are in the\n network. Each system has an entry, with the systems\n usually grouped by area code.  The format for each\n system's line: system number (preceded by @), system phone\n number (preceded by *), max bps rate of the system\n (preceded by #), system flags if any, WWIV registration\n number or date of entry (enclosed in brackets), and system\n name (enclosed in \"\").  For example, the BBSLIST line for\n Amber in NETXX could be:\n\n @1     *310-798-9993  #14400 <  !$     [1]  \"Amber\"\n\n Most of the system flags after the modem speed indicate\n the kind of high-speed modem being used by the system.\n Currently, these flags are:\n\n | -- Telebit-compatible (PEP) modem.\n < -- USR HST 9600+bps modem.\n > -- Hayes V-Series compatible 9600+bps modem.\n Z -- Zoom V.32terbo (19.2kpbs) modem.\n / -- CompuCom 9600+bps modem.\n ! -- CCITT V.32 (9600bps) modem.\n $ -- CCITT V.32bis (14.4kbps) modem.\n ~ -- V.FAST (28.8kbps) modem.\n ? -- Fax-capable modem (not currently used)\n\n Other system flags used which are not modem designators:\n\n + -- The system is a dedicated mail server.  That is, it\n      is not a true BBS, only handles the transfer of\n      network mail for an area or region.\n\n \\ -- Fidonet system.  Some systems in the network have\n      \"gateways\" into Fidonet (or Fidonet compatible, such\n      as GlobalNet).\n\n = -- PCPursuitable system.  This is actually not useful\n      since PCPursuit has gone out of business (though\n      there are other similar networks still operating).\n\n _ -- End node.  That is, a system with only one\n      connection.\n\n There can also be one of three flags appearing before the\n phone number: ^ -- Area Code coordinator (AC). & --\n Network Coordinator (NC). % -- Group Coordinator (GC) Note\n that since there can only be one Network Coordinator, the\n \"&\" should only appear once in the bbslist.net file. Also,\n the \"%\" is not likely to be seen except in the Group setup\n described below, since this setup has no Groups.\n\n The first line of the bbslist.net must be a tilde (~)\n followed by the Unix timestamp (seconds since midnight,\n Jan 1, 1970) indicating the date and time the file was\n sent out by the NC or GC.\n\n connect.net lists the connection costs between systems.\n The cost listed should be the cost per minute, though for\n most networks using this system, the rule of thumb is 0.00\n for local connects, 0.01 for long distance connects, and\n more for long distance connects that one wants to route\n less mail through.\n\n Each entry in the connect.net file specifies a one-way\n connection between two systems.  The entries in the\n connect.net file do NOT need to be in any specific order.\n The format for system's connection entry is: the system\n number (preceded by \"@\"), first connection and cost\n (separated by \"=\"), second connection and cost, and so\n forth.  Like bbslist.net, the first line is a tilde (~)\n followed by the UNIX timestamp.\n\n Examples:\n 1.   If there are two systems, numbered 1 and 2, and each\n      can call each other for free, the connect.net file\n      would look like:\n\n      @1      2=0.00\n      @2      1=0.00\n\n      Note that the routing analysis software should make\n      sure both ends of the connection have entries\n      referring to each other.\n\n 2.   If there are three systems, each can call the others\n      for free, the connect.net file would look like:\n\n      @1      2=0.00 3=0.00\n      @2      1=0.00 3=0.00\n      @3      1=0.00 2=0.00\n\n 3.   If system 3 called the other two for $0.10, the\n      connect.net file would look like:\n\n      @1      2=0.00 3=0.10\n      @2      1=0.00 3=0.10\n      @3      1=0.10 2=0.10\n\n\n In both bbslist.net and connect.net file, each entry\n begins with identifying the system number (preceded with\n @), allowing system entries to take up more than one line\n -- in larger networks a connect.net entry can fill more\n than one line.  Everything after the system number\n identifier up to the next \"@\", corresponds to that system.\n Thus, the connect.net files above could also be listed as:\n\n @1 2=0.00 3=0.10 @2 1=0.00 3=0.10 @3 1=0.10 2=0.10\n\n or\n\n @1\n 2=0.00\n 3=0.10\n @2\n 1=0.00\n 2=0.10\n @3\n 1=0.10\n 2=0.10\n\n Thus, the end-of-line indicator (EOL) should be IGNORED.\n\n Neither the bbslist.net nor connect.net file need to be in\n any specific order.  There cannot, however, be multiple\n entries per system in either bbslist.net or connect.net.\n\n It is possible for a system to have references in one or\n both of the .NET files, but not be reachable from any\n other system.  For example, two systems may be listed in\n bbslist.net, and listed in connect.net, but each can only\n call the other.  No other system in the network can\n connect with them, so they don't exist, essentially.\n Also, a system can be listed in bbslist.net, but not have\n any entries in connect.net.  This usually happens for\n systems just joining the network, and those systems\n essentially don't exist either.\n\n It is also possible for one system to call another, but\n the second system can't call back the first.  This is\n unusual, but valid.  Also, the cost of a connection can be\n different in one direction than it is in the other.  This\n is also valid.\n\n bbslist.net is received across the network as main_type 1,\n minor_type 1 (1/1).  connect.net is received as main_type\n 1, minor_type 2 (1/2).\n\n C.  Figuring the Routing\n\n  There are three ways message routing could be determined:\n\n  1.   Each time you need to route a message, find the\n       least cost or shortest path (depending on whether\n       new or old update files are being used);\n\n  2.   Each time one of the network programs that has to\n       route messages is run, the least-cost or shortest\n       route to each system is decided; or\n\n  3.   Each time an update to the .NET files is received,\n       the least cost route is decided to each system.\n\n  Options 1 and 2 are simply not practical.  Depending on\n  network size and system speed, it can take a minute or\n  more to analyze the network data files and determine the\n  optimal route.  Finding the best route to a specific\n  system requires the same operation as finding the best\n  route to all systems, so option #1 is a waste of time\n  (besides possibly requiring the BBS to have the path-\n  finding code in it).  Option #2 holds no advantages over\n  option #3 because it will tie up the BBS unnecessarily.\n\n  Therefore, the optimal routes to all the systems in the\n  network should be analyzed only when a network update is\n  received. This routing analysis can be done any way, as\n  long as it determines the best route.  The best way,\n  however, could follow these steps:\n\n  1.   System records are read into an array from\n       bbslist.net. The array is of struct \n       net_system_list_rec (see below).  All\n       fields are filled from the bbslist.net except numhops\n       and forsys, which are set to 65535 and 0, respec\n       tively.  For the Group setup, the bbslist.net\n       partial updates (.513-.768) are read in next, and\n       the indicated changes (existing systems replaced,\n       new systems added, systems indicated with \".\"\n       deleted) are made in the array and in the BBSLIST\n       files themselves.  After processing, the partial\n       updates are deleted.\n\n  2.   Next, the CONNECT files are read into another array.\n       Since system records may be repeated in the CONNECT\n       files, make sure, when each system record is read\n       in, a check is made in the array to see if there is\n       already an entry for it.  If there is, add the\n       connections in the new record to the existing\n       record.\n\n  3.   Then, the analysis starts.  The analyzer uses the\n       system's callout list (callout.net for NETxx) as a\n       base, starting with the first entry and checking\n       each of its connnects, spreading out from there to\n       THEIR connects.  This is done for each system in the\n       callout list.\n\n       For each destination system checked, the number of\n       hops found is compared to that entered in the\n       network data array (numhops) and changed if it is\n       less.  The forsys is also changed, if that is\n       different.  This is for the Group setup.\n\n       If the network is using the old NETXX setup, cost,\n       rather than number of hops, is considered.  In this\n       case, when figuring cost, the speed of a connection\n       (highest speed two connecting systems will support)\n       needs to be considered. For instance, two systems\n       connecting at 14400bps at a cost of 0.10 would take\n       precedence over two systems connectiung at 2400bps\n       at a cost of 0.10 (assuming that they are on the\n       path to the same destination system, and all other\n       scosts are equal).\n\n  4.   When all systems in the callout list are processed,\n       analysis is complete and the network data array is\n       written to disk. If specified, a piece of mail is\n       then sent to the sysop giving the results of the\n       analysis (for instance, how many valid systems are\n       in the network, how many systems route through each\n       of this system's connections, who the NC and GC and\n       AC are, and so forth).\n\n  The data structure NETxx's network3 uses for the\n  network data file is:\n\n  struct net_system_list_rec {\n  // system number of the system\n  uint16_t  sysnum;\n  /* phone number of system */\n  char phone[13];\n  /* name of system */\n  char name[40];\n  /* group of the system */\n  uint8_t   group;\n  /* max baud rate of system */\n  uint16_t  speed;\n  /* other info about sys (bit-mapped) */\n  uint16_t other;\n  /* how to get there */\n  uint16_t forsys;\n  /* how long to get there */\n  int16_t numhops;\n  union {\n    /* routing factor */\n    uint16_t  rout_fact;\n    /* cost factor */\n    float  cost;\n    /* temporary variable */\n    int32_t temp;\n  } xx;\n};\n\n  It is encouraged that this structure be used by any\n  NETXX compatible analyzer.  Not only is this used by\n  the WWIV BBS software, but some NETXX add-ons also use\n  this file, so supporting this structure will enhance\n  compatibility with NETXX.\n\n  The fields: sysnum, phone, name, group, and speed should\n  be self-explanatory.\n\n  other --  This is bitmapped, and contains the modem and\n            other information shown in BBSLIST.  The bitmap\n            values are (with corresponding BBSLIST flag):\n\n            \\    other_fido          0x0001\n            |    other_Telebit_19200 0x0002\n            <    other_USR_9600      0x0004\n            >    other_Hayes_9600    0x0008\n            ^    other_area_coord    0x0010\n            !    other_V32           0x0020\n            $    other_V32bis        0x0040\n            =    other_PCP           0x0080\n            %    other_group_coord   0x0100\n            &    other_net_coord     0x0200\n            /    other_compucom      0x0400\n            +    other_net_server    0x0800\n            ?    other_FAX           0x1000\n            _    other_end_system    0x2000\n            ~    other_VFAST         0x4000\n\n  forsys -- Where to forward messages destined for this\n            system, also known as \"next hop\".  For example,\n            if a message going from system 1 to system 5\n            passes through systems 2 and 4, then forsys==2.\n            When it is determined that the system is\n            unreachable (listed in BBSLIST but no\n            connections listed), forsys==65535.\n\n  rout_fact -- This is the routing factor, but is currently\n            not used by the NETxx software.\n\n  cost --   this holds the cost of the call, calculated as\n            the sum of costs for each hop to the\n            destination.\n\n  When all systems have been processed, you should have a\n  database containing all systems in the network and how\n  they may be reached.  Whenever a packet that is not\n  destined for the local system is processed, the data file\n  is searched to find the system entry for the destination\n  system.  If it is not found, then the system is unknown.\n  If the system is identified as unreachable\n  (forsys==65535), the system is also considered unknown.\n\n======================================================\n6.  TIPS FOR WRITING WWIVNET SOFTWARE\n======================================================\n\n That about covers all the technical details for designing\n software compatible with WWIV networks.  Now for some\n things to consider for those wishing to design a NETXX\n interface for a non-WWIV BBS, or add-ons to existing\n NETXX software.\n\n A.   NETXX Interface Software\n\n  The information provided in this document is enough for\n  anyone wishing to write NETXX interface software from\n  scratch.  Unless you are writing for a BBS on a non-PC\n  platform (such as Hermes for Macintosh), there is no need\n  to rewrite all of the software to interface a PC-based\n  BBS to a WWIV network.  Since the local mail processor\n  (network2) is the only program that writes to BBS\n  message bases, that is really the only one needing\n  replace ment.  If any of the NETxx programs are used, it\n  is essential that all of the supporting data files used\n  by that software be present.  For details on those files,\n  see the NETXX software documentation.\n\n  Some additional programming may be necessary, though.\n  For one, a shell would be useful for executing the\n  various network programs, unless the BBS can be modified\n  to make the calls itself.  A batch file could do it, but\n  a program such as Jim Wire's CLOUT makes it much easier.\n  Any shell or BBS modification should follow these steps\n  (filenames in parentheses are programs from NET34 or\n  files created/used by them):\n\n  1.   Choose a system to call (or have one specified),\n       then execute the network callout program\n       (NETWORK.EXE).  If successful, proceed to step 2.\n       If not, either try again or end processing.\n\n  2.   Check for the incoming netmail file (P*.NET).  If\n       there isn't one, end processing.  If there is one,\n       run the netmail packet analyzer (network1).\n\n  3.   Check for the local mail file packet (local.net).\n       If there is none, end processing.  If there is one,\n       run the local mail packet analyzer (network2).\n\n  4.   Check again for a netmail packet (outgoing messages\n       result ing from local mail processing).  If there is\n       one run the netmail analyzer, otherwise proceed to\n       the next step.\n\n  5.   Check for a BBSLIST or CONNECT update.  The most\n       reliable way to do this is to compare the filedates\n       of the CONNECT and BBSLIST files against the\n       filedate of the database file created last time the\n       routing analyzer ran.  If one or more of the files\n       is new (or there is a partial BBSLIST update), run\n       the routing analyzer (network3).\n\n  If the software cannot be modified to handle these steps,\n  it is probably best to use a front-end such as Front Door\n  or Binkleyterm, then set up events that would run the\n  shell for making the network calls and processing.\n\n  The trickiest part is exporting messages from the BBS to\n  a WWIV network file.  Possibly the easiest way to pack\n  new messages is to have the BBS write them out to Fido\n  packets (if the BBS is Fido-compatible), then when\n  control returns to the front end, run an event that\n  converts the Fido packet to a WWIV mail file.  When doing\n  this, keep in mind that WWIV networks do not have all of\n  the fields a WWIV packet does, most notably the \"To:\"\n  field.\n\n  Another method could be a program that, after the BBS\n  returns control to the front end, scans the BBS's message\n  bases for new messages on the NETXX subboards.  This\n  would work best for BBS programs that cannot export Fido\n  messages.  In either case, it is important that the\n  netmail file processor analyze the outgoing message file\n  (P*.NET) for tossing into the various connection files\n  (S*.NET).\n\n  Of course, the optimal solution, if possible, would be to\n  modify the BBS software to export the messages directly\n  into a NETXX compatible mail file, and run the other\n  network programs as needed without the shell.\n\n  This is probably be a good time to discuss the naming of\n  the incoming and pending netmail files, mentioned in step\n  2 above. The actual name of the P*.NET can vary,\n  depending on NETxx version and what program generates it.\n  network.exe receives the file as p1-0-1.net. The \"-0\" in the\n  middle indicates that network.exe created the file (think\n  of it as network0).  When other NETXX programs generate\n  pending netmail files, the middle number indicates which\n  program created it (network2, the local mail\n  processor, would create a pending netmail file named\n  p1-2-1.net).  The main reason for this naming system\n  is so that we can tell the source of a p*.net file being\n  processed by the netmail analyzer.\n\n  The WWIV BBS just creates p0.net (network email,\n  generally) and P1.NET (outggoing sub posts, generally).\n  Multi-instance WWIV create P*.nnn (where 'nnn' is the\n  instance number, such as p*.001 for instance 1) while a\n  user is online, but they are renamed to P*.NET after the\n  user logs off.\n\n  The network1 processes all of the P*.NET files, until\n  none are left.  It is important that an alternate\n  netmail file analyzer be able to recognize and handle any\n  p*.NET file, not just pN.net.\n\n\n B.   NETXX Software Add-ons\n\n  There are two possible types of add-ons supported by the\n  NETXX software, both working with the local mail\n  processor.\n\n  A common use for external messages is what is known as a\n  \"ping,\" used by the authors of some WWIV network\n  utilities who wish to gain some information about the use\n  of their software.  The author sends out a main_type 27\n  message with the minor_type they are using.  If a\n  receiving system is using the software and it is\n  installed properly, it will execute after local mail\n  processing, and process the request in the external\n  message.\n\n  The local mail processor also supports use of\n  \"pre-processors,\" generally used to scan the local mail\n  file for certain types of messages before the local mail\n  processor gets to it.  One example is JAFO's AUTOSEND,\n  which looks for sub requests and sends out messages from\n  the system's subs to new subscribers.  These, also, are\n  described in the NETXX Software Documentation.\n\n  Naturally, any external message processor or preprocessor\n  that generates new outgoing network messages must put\n  them into a p*.net file so that network1 can find it\n  and process it.\n"
  },
  {
    "path": "specs/qwk/command.txt",
    "content": "\n                     Old style configuration commands\n\n      To: QMAIL (or whatever)\n\n      Subject contains one of the following commands:\n\n      ADD                   Add current conference\n      ADD -20               Add current conference and set lastread pointer\n                            20 below the end\n      ADD 9876              Add current conference and set lastread pointer\n                            to message number 9876\n      DROP                  Drop current conference\n      RESET                 Reset current conference lastread pointer to\n                            the end\n      RESET -20             Reset current conference lastread pointer to\n                            20 below the end\n      RESET 9876            Reset current conference lastread pointer to\n                            message number 9876\n      BLTS ON               Turn bulletins on\n      BLTS OFF              Turn bulletins off\n      FILES ON              Turn new files list on\n      FILES OFF             Turn new files list off\n      WELCOME ON            Turn welcome screen on\n      WELCOME OFF           Turn welcome screen off\n      GOODBYE ON            Turn goodbye screen on\n      GOODBYE OFF           Turn goodbye screen off\n\n      If the subject is CONFIG, see the new format in COMMAND.TXT\n      for an explanation.\n"
  },
  {
    "path": "specs/qwk/config.txt",
    "content": "\n\n                 New (04/91) format for configuration messages\n\n        To: QMAIL (or whatever)\n        Subject: CONFIG\n\n        Text has one command per line with the following options:\n\n        ADD <conf>                  adds a conference\n        DROP <conf>                 drops a conference\n        RESET <conf> <value>        resets message pointer to value or\n                                    can use HIGH-xxx\n        CITY <string>               changes bbs user city\n        PASSWORD <string>           changes bbs user password\n        BPHONE <string>             changes bbs user business/data phone\n        HPHONE <string>             changes bbs user home/voice phone\n        PCBEXPERT [ON|OFF]          turns bbs user expert mode on or off\n        PCBPROT <char>              sets bbs user protocol to char (A thru Z)\n        PCBCOMMENT <string>         sets bbs user comment\n        PAGELEN <value>             sets bbs use pagelength\n        PROTOCOL <char>             sets QWK door protocol to char (A thru Z)\n        EXPERT [ON|OFF]             sets QWK door expert mode on or off\n        MAXSIZE <value>             sets maximum QWK size in bytes\n        MAXNUMBER <value>           sets maximum msgs per conference\n        AUTOSTART                   QWK door autostart\n\n"
  },
  {
    "path": "specs/qwk/control.txt",
    "content": "\n\n                        Format of Control.Dat file\n\n      Control.Dat is a normal CR/LF style text file with the\n      following lines in exactly the order shown.\n\nBBS name\nBBS City, BBS State\nBBS phone number                     {AAA-EEE-NNNN}\nSysop name,Sysop                     {Sysop name in upper case followed\n                                      by the literal ',Sysop'}\nSerial number ,BBS ID                {Serial Number, UpperCase BBSID}\nDate of mail packet, time of packet  {MM-DD-YYYY,HH:MM:SS}\nCaller's name                        {Uppercase}\nblank\n0\n0\nNumber of conferences (in additon to conference 0 which is main)\n                      (ie use number of conferences minus one)\nConference number\nName of Conference    (should be limited to maximum length of 12 characters)\n...\n...\n...\n...\n...\nConference number\nName of Conference\nname of BBS welcome file\nname of NEWS file\nname of BBS goodbye file\n\nOther optional data may occur after the Goodbye file line, but the\ntrend is to omit this data.  If included it is as follows:\n\n0                                    {Unknown}\nScreen Length\nUSER NAME                            {Upper case}\nFirstName                            {Proper case}\nCITY, ST                             {Upper case}\nData Phone                           {AAA EEE-NNNN}\nVoice Phone                          {AAA EEE-NNNN}\nSecurity Level\nExpiration Date                      {MM-DD-YY}\nLast On Date                         {MM-DD-YY}\nLast On Time                         {HH:MM}\nNumber of calls\n0                                    {Unknown}\nDownLoaded Bytes\nDownLoaded Count\nUploaded Bytes\nUploaded Count\nTime Limit Per Day                   {Minutes}\nTime Remaining                       {Minutes}\nTime Used Today                      {Minutes}\nDownLoad Limit/Day                   {Kilobytes}\nDownLoad Bytes Remaining Today       {Bytes}\nDownLoaded Today                     {Bytes}\nCurrent Time                         {HH:MM}\nCurrent Date                         {MM-DD-YY}\nSystem Tag Line\n"
  },
  {
    "path": "specs/qwk/doorid.txt",
    "content": "\n\n          DOOR.ID\n\n          Many maildoors now produce (and readers use) a file called\n          Door.Id that was developed by Greg Hewgill.  It is intended\n          to give the reader information on the capabilities of the\n          door that produced the packet (and presumably will process\n          the *.REP produced).  It is a straight text file with the\n          following format.  Each line is in the format ControlWord\n          space equals space value.\n\n\n          DOOR = <doorname>\n               This is the name of the door that created the QWK\n               packet, eg.  <doorname> = Tomcat.\n\n          VERSION = <doorversion>\n               This is the version number of the door that created\n               the packet,  eg. <doorversion> = 2.9.\n\n          SYSTEM = <systemtype>\n               This is the underlying BBS system type and version,\n               eg. <systemtype> = Wildcat 2.55.\n\n          CONTROLNAME = <controlname>\n               This is the name to which the reader should send\n               control messages, eg. <controlname> = TOMCAT.\n\n          CONTROLTYPE = <controltype>\n               This can be one of ADD, DROP, or REQUEST (or others).\n               ADD and DROP are pretty obvious (they work as in\n               Markmail), and REQUEST is for use with BBS systems\n               that support file attachments.  Try out SLMR with\n               CONTROLTYPE = REQUEST and use the Q function.\n\n          RECEIPT\n               This flag indicates that the door/BBS is capable of\n               return receipts when a message is received.  If the\n               first three letters of the subject are RRR, then the\n               door should strip the RRR and set the 'return-receipt-\n               requested' flag on the corresponding message.\n\u001a"
  },
  {
    "path": "specs/qwk/filename.txt",
    "content": "\n\n                   Filenames used by the *.QWK format\n\n        BBSID.QWK is an archive containing the files from the\n        message door being sent to the caller.\n\n            MESSAGES.DAT - a file containing the messages themselves\n               in 128 byte records.\n\n            CONTROL.DAT - a file with info on the system, caller, and\n               conference names and numbers.\n\n            999.NDX - one file for each selected conference that\n               contains pointers to the messages in MESSAGES.DAT\n               There are usually several *.NDX files in each\n               QWK file.  (Right justified, padded with leading\n               zeros to make the 3 characters).\n\n            PERSONAL.NDX - an optional file that is in the same\n               format as the other *.NDX files except that it\n               contains index records for all messages to the caller\n               regardless of which conference they were in.\n\n            NEWFILES.DAT - an optional file that contains a list\n               of new files from the Bbs.\n\n            BLT-0.99 - optional files containing ascii or ansi\n               bulletins.  The 99 extension is replaced by the\n               bulletin number (Left justified not padded).\n\n            DOOR.ID - an optional text file that contains info\n               on the capabilities of the door that produced the\n               QWK packet (so that the reader will only send\n               control messages that can be handled).\n\n            SESSION.TXT - an optional ascii/ansi file containing\n               info on the activity occuring in the mail door.\n\n            Optionally it may also contain ascii or ansi screens for\n            Welcome, News, and Goodbye as named in the CONTROL.DAT\n            file.\n\n        BBSID.REP is an archive containing a single file of the\n        messages sent from the caller to the Bbs.\n\n            BBSID.MSG - a file containing the messages themselves\n               in 128 byte records.  The format is similar to\n               MESSAGES.DAT.\n\u001a"
  },
  {
    "path": "specs/qwk/messages.txt",
    "content": "\n\n              Format of the exported messages in Messages.Dat\n\n\n         This file contains records with a length of 128 bytes.  There\n         are 3 types of these records: (1) Packet Header, (2) Message\n         Header, and (3) Message Text.  All unused fields in the\n         records are normally filled with spaces, although you will\n         sometimes find the final Message text record will be filled\n         with nulls (#0) after the last text.\n\n\n                              Packet Header\n\n         Packet Header - is always the first record in the file and\n         only occurs once.  It contains only normal ascii text\n         (limitted to at most 128 characters) and should always\n         start with \"Produced by \".  The remaining text normally\n         includes a product name and copyright message.\n\n\n                              Message Header\n\n         A message header immediately preceeds zero or more message\n         text records.  Each Message header has the following\n         format:\n\n         Start\n          Pos  Length              Description\n        ------ ------ -----------------------------------------\n           1      1   Message status flag (see below)\n           2      7   Message number (ascii left justified)\n           9      8   Date (MM-DD-YY)\n          17      5   Time (HH:MM)\n          22     25   To (left justified space filled - uppercase)\n                      (Be sure to check the to field to spot\n                      configuration type messages)\n          47     25   From (left justified space filled - uppercase)\n          72     25   Subject (left justified space filled - uppercase)\n                      (a subject starting \"NE:\" should not be\n                      echoed into a network)\n          97     12   Password (not really used leave blank)\n         109      8   Message reference number (ascii left justified)\n         117      6   Number of blocks (ascii left justified - number\n                      of 128 byte blocks including 1 for the message\n                      header)\n         123      1   Message active( or #225 = Active,\n                       or #226 = Inactive)\n         124      2   Conference number (Binary Word) (Lo in 124, Hi\n                      in 125).  Note that some older programs only\n                      supported conferences 0 thru 255 and left byte\n                      125 as a \"blank\" unused field.  I recommend\n                      checking the word value and if it is over 8191\n                      to only use the lower (0 thru 255) part of it.\n                      I've also seen notes that this field is really\n                      a 4 byte LongInt field, although with the above\n                      limitation (and 8000 conference seeming sufficient\n                      for a while), I documented it this way.\n\n         128      1   Indicates whether the message has a Network\n                      tagline or not.  A value of \"*\" indicates that\n                      a network tagline is present, a value of \" \"\n                      indicates there isn't.  Messages sent to readers\n                      (non-net-status) generally leave this as always\n                      blank since only net utils need this info.\n\n         Message Status Flag has the following possibilities:\n\n         '`'  Comment to sysop, read      '~'  Comment to sysop, unread\n         '-'  Public, read                ' '  Public, unread\n         '*'  Private, read               '+'  Private, unread\n         '^'  Password protected, read    '%'  Password protected, unread\n         '#'  Group password, read        '!'  Group password, unread\n         '$'  Group password to all\n\n\n\n                             Message Text Records\n\n         The message text records immediately follow the the message\n         header.  They contain straight ascii text (lines are\n         normally limitted to 72 chars/line although you may see\n         longer lines).  Each line is followed by a \"\" or #227\n         character to mark the end of the line (in place of the normal\n         CR/LF that would exist in a straight text file).  The text\n         continues consecutavly and text lines do continue across\n         block boundaries.  Some systems or readers may have problems\n         with messages longer than 99 lines or 199 lines, although more\n         recently this no longer seems to be a limit.  The last block\n         should be padded with blanks to fill the block, although on\n         input you may find it padded with nulls (#0).\n\u001a"
  },
  {
    "path": "specs/qwk/ndx.txt",
    "content": "\n\n\n                           Format of Index files\n\n      Index files are named XXX.NDX (where XXX is the conference\n      number padded with leading zeros to make it three characters\n      long.  There is one *.NDX file for each conference chosen that\n      contains messages in the MESSAGES.DAT file.\n\n      The *.NDX file contain records five characters long that point\n      to each message in that conference.\n\n\n      NdxRecord = Record\n        MsgPointer: BasicReal\n        Conference: Byte;\n        End;\n\n      The BasicReal is a four byte number in BASIC MKS$ format.\n\n\n      The following is a sample program unit for TurboPascal that\n      converts between BasicReal format and LongInt format.\n\n------------------------------------------------------------------------------\n\nUnit BasicConvert;\n\nInterface\n  Function BasicReal2Long(InValue: LongInt): LongInt;\n                {Convert Basic Short Reals to LongInts}\n\n  Function Long2BasicReal(InValue: LongInt): LongInt;\n                {Convert LongInts to Basic Short Reals}\n\nImplementation\n\nFunction BasicReal2Long(InValue: LongInt): LongInt;\n\n  Var\n  Temp: LongInt;\n  Expon: Integer;\n\n  Begin\n  Expon := ((InValue shr 24) and $ff) - 152;\n  Temp := (InValue and $007FFFFF) or $00800000;\n  If Expon < 0 Then\n    Temp := Temp shr Abs(Expon)\n  Else\n    Temp := Temp shl Expon;\n  If (InValue and $00800000) <> 0 Then\n    BasicReal2Long := -Temp\n  Else\n    BasicReal2Long := Temp;\n  If Expon = 0 Then\n    BasicReal2Long := 0;\n  End;\n\n\nFunction Long2BasicReal(InValue: LongInt): LongInt;\n  Var\n  Negative: Boolean;\n  Expon: LongInt;\n\n  Begin\n  If InValue = 0 Then\n    Long2BasicReal := 0\n  Else\n    Begin\n    If InValue < 0 Then\n      Begin\n      Negative := True;\n      InValue := Abs(InValue);\n      End\n    Else\n      Negative := False;\n    Expon := 152;\n    If InValue < $007FFFFF Then\n      While ((InValue and $00800000) = 0) Do\n        Begin\n        InValue := InValue shl 1;\n        Dec(Expon);\n        End\n    Else\n      While ((InValue And $FF000000) <> 0) Do\n        Begin\n        InValue := InValue shr 1;\n        Inc(Expon);\n        End;\n    InValue := InValue And $007FFFFF;\n    If Negative Then\n      InValue := InValue Or $00800000;\n    Long2BasicReal := InValue + (Expon shl 24);\n    End;\n  End;\n\nEnd.\n\n------------------------------------------------------------------------------\n\nA quick and dirty conversion (handles positive numbers only) is possible\nwith the following expression:\n\nMKSToNum := ((x AND NOT $ff000000) OR $00800000)\n             SHR (24 - ((x SHR 24) AND $7f));\n\n------------------------------------------------------------------------------\n\n      The number contained in the MsgPointer is the record number\n      (128 byte records - starting numbering from record 1 not 0)\n      of the message header.  Note that since the 1st record contains\n      packet header, the lowest MsgPointer that can exist is 2.\n\n      Some message readers will reformat the *.NDX files so that the\n      MsgPointer becomes a LongInt fileseek position (using a record\n      size of 1).  To determine which type of index you are reading\n      you should look at the size of the number.  Any BasicReal will\n      appear as a huge number that would unlikely ever be a byte\n      seek positon.\n\n      An additional file PERSONAL.NDX is also optionally added to the\n      QWK archive.  This file has the same record format as the other\n      *.NDX files.  It contains index records pointing to messages to\n      the caller from all conferences (ie it is used by the mail reader\n      to do a quick search for personal mail in all areas).\n\u001a"
  },
  {
    "path": "specs/qwk/qwk.txt",
    "content": "                     QWK Mail Packet File Layout\n                          by Patrick Y. Lee\n\nVersion 1.6 - December 19, 1992\n     Added off-line commands for QSO (door for TBBS), thanks to\n     message from Bob Hartman in the FidoNet Off-line echo.  All\n     8-bit characters have been replaced with either blanks or\n     equivalent 7-bit characters so I can send this file easily via\n     Internet email.  Line 9 of the CONTROL.DAT file seems to be\n     used by a few doors to indicate the NetMail conference.\nVersion 1.5 - July 30, 1992\n     Added off-line commands for Cam-Mail door.  Fixed error in the\n     status flag section.  The descriptions for `*' and `+' are\n     incorrect.  Thanks to Bob Blaylock for bringing this up.\nVersion 1.4 - July 18, 1992\n     Fixed a few minor mistakes in the documentation (thanks to\n     Cody Gibson).  Nothing really major.  Also completed the\n     Netmail section of the documentation.\nVersion 1.3 - July 6, 1992\n     Added changes to the QWK format adopted by Qmail door.  Spe-\n     cifically line 10 of CONTROL.DAT file and bytes 126-127 of\n     MESSAGES.DAT file.  Please refer to the appropriate section\n     for the changes.\nVersion 1.2 - May 31, 1992\n     Added a few items to the DOOR.ID file that is being supported\n     by Qmail DeLuxe2 version 1.25.\nVersion 1.1 - March 15, 1992\n     Minor fixes here and there to make everything just right.\nVersion 1.0 - February 23, 1992\n     First release.\n\nThis document is Copyright 1992 by Patrick Y. Lee.\n\nThe QWK-format is Copyright 1987 by Sparkware.\n\nAll program names mentioned in this document are either Copyright\nor Trademark of respective owners.\n\nThe author provides this file as-is without warranty of any kind,\neither expressed or implied.  You are using the information in this\nfile at your own discretion.  The author assumes no responsibili-\nties for damages, either physically or financially, from the use of\nthis information.\n\nThis document may be freely distributed by any means (electronical-\nly, paper, etc.), provided that it is distributed in its entirety. \nPortions of this document may be reproduced without credit.\n\nThe latest version of this file can always be found on Aardvark BBS\n(New York, NY) at (212) 496-8324.  It can also be found in the Lu-\nnatic Fringe BBS (Plano, TX) at (214) 422-2936 USR HST DS.  First\ntime caller can download on both boards.  The file can also be sent\nvia Internet email to anyone who asks.  Mail request to\npatlee@panix.com.\n\n                    -=-=-=-=-=-=-<>-=-=-=-=-=-=-\n\n                          Table of Contents\n\n1.  Introduction\n    1.1.  Intent\n    1.2.  History\n    1.3.  Questions, corrections, etc.\n2.  Conventions & overview\n    2.1.  The BBS ID\n    2.2.  Packet compression\n    2.3.  Packet transfer & protocols\n    2.4.  Limitations\n3.  QWK files\n    3.1.  Naming convention\n    3.2.  Control file (CONTROL.DAT)\n    3.3.  Welcome file\n    3.4.  Goodbye file\n    3.5.  News file\n    3.6.  Qmail DeLuxe2 menu file\n    3.7.  New uploads listing (NEWFILES.DAT)\n    3.8.  Bulletin file(s) (BLT-x.y)\n    3.9.  Message file (MESSAGES.DAT)\n    3.10.  Index files (*.NDX)\n        3.10.1.  Conference indices\n        3.10.2.  Personal index (PERSONAL.NDX)\n    3.11.  Pointer file\n    3.12.  SESSION.TXT\n4.  REP files\n    4.1.  Naming convention\n    4.2.  Message file (BBSID.MSG)\n    4.3.  Door control messages\n    4.3.1.  DOOR.ID file\n    4.3.2.  Qmail\n    4.3.3.  MarkMail\n    4.3.4.  KMail\n    4.3.5.  RoseMail\n    4.3.6.  Complete Mail Door\n    4.3.7.  The MainMail System\n    4.3.8.  BGQWK\n    4.3.9.  UltraBBS\n    4.3.10.  TriMail\n    4.3.11.  Cam-Mail\n    4.3.12.  QSO\n    4.4.  Turning off the echo flag\n    4.5.  Tag-lines\n5.  Net mail\nA.  Credits & contributions\nB.  Sample Turbo Pascal and C code\nC.  Sample message\nD.  Sample index file\n\n                    -=-=-=-=-=-=-<>-=-=-=-=-=-=-\n\nTo search for a specific section, look for \"[x.x]\" using your edi-\ntor or viewer.  For example, to jump to the tag-lines portion of\nthis file, search for \"[4.5]\" with your editor or text viewer.\n\n                    -=-=-=-=-=-=-<>-=-=-=-=-=-=-\n\n[1]  Introduction\n\n[1.1]  Intent\n\nThis document is written to facilitate programmers who want to write\nQWK-format mail doors or readers.  It is intended to be a comprehen-\nsive reference covering all areas of QWK-format mail processing. \nDetailed break down of each file is included, as are implementation\ninformation.  In addition, door and reader specific information may be\nincluded, when such information are available to me.\n\n[1.2]  History\n\nThe QWK-format was invented by Mark \"Sparky\" Herring in 1987.  It was\nbased on Clark Development Corporation's PCBoard version 12.0 message\nbase format.  Off-line mail reading has become popular only in recent\nyears.  Prior to summer of 1990, there were only two QWK-format off-\nline mail reader programs.  They were Qmail DeLuxe by Mark Herring and\nEZ-Reader by Eric Cockrell.  Similarly for the doors, there were only\ntwo -- Qmail by Mark Herring and MarkMail by Mark Turner.  They were\nboth for PCBoard systems.\n\nA lot has changed in both off-line reader and mail door markets since\nsummer 1990.  Now, there are more than a dozen off-line mail readers\nfor the PC.  Readers for the Macintosh, Amiga, and Atari exist as\nwell.  There are over a half dozen doors for PCBoard, and QWK-format\ndoors exist for virtually all of the popular BBS softwares.  All of\nthese happened in less than two years!  More readers and doors are in\ndevelopment as I write this, keep up the excellent work.  In addition\nto doors, some BBS softwares has QWK-format mail facility built in.\n\nOff-line mail reading is an integral part of BBS calling.  Conference\ntraffic and selection on all networks have grown dramatically in re-\ncent years that on-line reading is a thing of the past.  Off-line mail\nreading offers an alternative to reading mail on-line -- It offers\nspeed that cannot be achieved with on-line mail reading.\n\nThe reason why QWK-format readers and doors seem to have gained popu-\nlarity is probably dued to its openness.  The format is readily avail-\nable to any programmer who wishes to write a program that utilize it. \nProprietary is a thing of the past, it does not work!  Openness is\nhere to stay and QWK-format is a part of it.\n\n[1.3]  Questions, corrections, etc.\n\nMost of the message networks today have a conference/echo devoted to\ndiscussion of off-line readers and mail doors.  The ones I know are on\nFidoNet, ILink, Intelec, and RIME.  If you have questions after read-\ning anything in here, feel free to drop by any of the above conference\n/echo and I am sure other QWK authors will try to help.\n\nI can be reached at:\n\nCompuServe: >INTERNET:patlee@panix.com\nFidoNet: Off-line echo\nILink: Off-line conference\nIntelec: Off-line conference\nInternet: patlee@panix.com\nPlanoNet: Reviews conference\nRIME: ->RUNNINGB, Off-line, Common, Net Admin., Shareware, New Users,\nand Session Manager conferences\n\nAny corrections, extensions, comments, and criticisms are welcomed. \nMessages from Internet and RIME will probably be answered first.  But\nI do check mail on all other places at least once a week.\n\n[2]  Conventions & overview\n\nAll offsets referenced in this document will be relative to 1.  I am\nnot a computer, I start counting at one, not zero!\n\nWords which are enclosed in quotes should be entered as-is.  The quo-\ntations are not part of the string unless noted.\n\nYou may have noticed I use the phrase \"mail program\" or \"mail facili-\nty\" instead of mail doors.  This is because some BBS softwares offer\nthe option of creating QWK-format mail packets right from the BBS. \nWith those, there is no need for an external mail door.\n\n[2.1]  The BBS ID\n\nThe BBS ID (denoted as BBSID) is a 1-8 characters word that identifies\na particular BBS.  This identifier should be obtained from line 5 of\nthe CONTROL.DAT file (see section 3.2.1).\n\n[2.2]  Packet compression\n\nMost mail packets are compressed when created by the mail door in\norder to save download time and disk space.  However, many off-line\nreader programs allow the user to unarchive a mail packet outside of\nthe reader program, so the reader will not have to unarchive it.  Upon\nexit, the reader will not call the archiver to save it.  It is up to\nthe user to archive the replies.  This is useful if the user has lim-\nited memory and cannot shell out to DOS to run the unarchive program. \nFor readers based on non-PC equipment, the user may be using less\ncommon compression program that does not have command line equivalent.\n\n[2.3]  Packet transfer & protocols\n\nThere is no set rule on what transfer protocol should be used.  Howev-\ner, it would be nice for the mail program on the BBS to provide the\nSysop with options as to what to offer.  This should be a configura-\ntion option for the user.\n\n[2.4]  Specifications & limitations\n\nThere aren't many known limits in the QWK specification.  However,\nvarious networks seem to impose artificial limits.  On many of the PC-\nbased networks, 99-lines appears to be the upper limit for some\nsoftwares.  However, most of the readers can handle more than that. \nReader authors reading this may want to offer the option to split\nreplies into n lines each (the actual length should be user definable\nso when the network software permits, the user can increase this num-\nber).\n\n[3]  QWK files\n\n[3.1]  Naming convention\n\nGenerally, the name of the mail packet is BBSID.QWK.  However, this\ndoes not have to be the case.  When the user downloads more than one\nmail packet at one time, either the mail program or the transfer pro-\ntocol program will rename the second and subsequent mail packets to\nother names.  They will either change the file extension or add a\nnumber to the end of the filename.  In either case, you should not\nrely on the name of the QWK file as the BBSID.  The BBSID, as men-\ntioned before, should be obtained from line 5 of the CONTROL.DAT file. \nIn addition, mail packets do not have to end with QWK extension ei-\nther.  The user may choose to name them with other file extensions.\n\n[3.2]  Control file (CONTROL.DAT)\n\nThe CONTROL.DAT file is a simple ASCII file.  Each line is terminated\nwith a carriage return and line feed combination.  All lines should\nstart on the first column.\n\nLine #\n 1   My BBS                   BBS name\n 2   New York, NY             BBS city and state\n 3   212-555-1212             BBS phone number\n 4   John Doe, Sysop          BBS Sysop name\n 5   20052,MYBBS              Mail door registration #, BBSID\n 6   01-01-1991,23:59:59      Mail packet creation time\n 7   JANE DOE                 User name (upper case)\n 8                            Name of menu for Qmail, blank if none\n 9   0                        ? Seem to be always zero.  A few doors,\n                              such as DCQWK for TAG is using this\n                              field to indicate the conference where\n                              Fido NetMail should be placed.  This\n                              gives the reader program the ability\n                              easily send NetMail.\n10   999                      Total number of messages in packet\n11   121                      Total number of conference minus 1\n12   0                        1st conf. number\n13   Main Board               1st conf. name (13 characters or less)\n14   1                        2nd conf. number\n15   General                  2nd conf. name\n..   3                        etc. onward until it hits max. conf.\n..   123                      Last conf. number\n..   Amiga_I                  Last conf. name\n..   HELLO                    Welcome screen file\n..   NEWS                     BBS news file\n..   SCRIPT0                  Log off screen\n\nSome mail doors, such as MarkMail, will send additional information\nabout the user from here on.\n\n0                             ?\n25                            Number of lines that follow this one\nJANE DOE                      User name in uppercase\nJane                          User first name in mixed case\nNEW YORK, NY                  User city information\n718 555-1212                  User data phone number\n718 555-1212                  User home phone number\n108                           Security level\n00-00-00                      Expiration date\n01-01-91                      Last log on date\n23:59                         Last log on time\n999                           Log on count\n0                             Current conference number on the BBS\n0                             Total KB downloaded\n999                           Download count\n0                             Total KB uploaded\n999                           Upload count\n999                           Minutes per day\n999                           Minutes remaining today\n999                           Minutes used this call\n32767                         Max. download KB per day\n32767                         Remaining KB today\n0                             KB downloaded today\n23:59                         Current time on BBS\n01-01-91                      Current date on BBS\nMy BBS                        BBS network tag-line\n0                             ?\n\nSome mail doors will offer the option of sending an abbreviated con-\nference list.  That means the list will contain only conferences the\nuser has selected.  This is done because some mail readers cannot\nhandle more than n conferences at this time.  Users using those read-\ners will need this option if the BBS they call have too many confer-\nences.\n\n[3.3]  Welcome file\n\nThis file usually contains the log on screen from the BBS.  The exact\nfilename is specified in the CONTROL.DAT file, after the conference\nlist.  This file may be in any format the Sysop chooses it be -- usu-\nally either in plain ASCII or with ANSI screen control code.  Some\nSysops (notably PCBoard Sysops) may use BBS-specific color change code\nin this file as well.  Current mail programs seem to handle the trans-\nlations between BBS-specific code to ANSI based screen control codes.\n\nEven if the CONTROL.DAT file contains the filename of this file, it\nmay not actually exist in the mail packet.  Sometimes, users will\nmanually delete this file before entering the mail reader.  Some off-\nline readers offer the option to not display this welcome screen; some\nwill display this file regardless.  Some doors, similarly, will offer\noption to the user to not send this file.\n\n[3.4]  Goodbye file\n\nSimilar to the welcome file above, the filename to the goodbye file is\nin the CONTROL.DAT file.  This is the file the BBS displays when the\nuser logs off the board.  It is optional, as always, to send this file\nor to display it.\n\n[3.5]  News file\n\nMany mail doors offer the option to send the news file from the BBS. \nMost will only send this when it has been updated.  Like the welcome\nand goodbye files, the filename to the news file is found in the CON-\nTROL.DAT file.  It can be in any format the Sysop chooses, but usually\nin either ASCII or ANSI.  Like the welcome screen, current mail facil-\nities seem to handle translation between BBS-specific control codes to\nANSI screen control codes.\n\n[3.6]  Qmail DeLuxe2 menu file\n\nThis file is of use only for Qmail DeLuxe2 mail reader by Sparkware. \nThe filename is found on line 8 of the CONTROL.DAT file.\n\n[3.7]  New uploads listing (NEWFILES.DAT)\n\nMost mail programs on the BBS will offer the option to scan new files\nuploaded to the BBS.  The result is found in a file named\nNEWFILES.DAT.  The mail program, if implementing this, should update\nthe last file scan field in the user's profile, if there is such a\nfield, as well as other information required by the BBS.  The mail\nprogram should, of course, scan new files only in those areas the user\nis allowed access.\n\n[3.8]  Bulletin files (BLT-x.y)\n\nMost mail programs will also offer the option to include updated bul-\nletin files found on the BBS in the mail packet.  The bulletins are\nnamed BLT-x.y, where x is the conference/echo the bulletin came from,\nand y the bulletin's actual number.  The mail program will have to\ntake care of updating the last read date on the bulletins in the user\nrecord.\n\n[3.9]  Message file (MESSAGES.DAT)\n\nThe MESSAGES.DAT file is the most important.  This is where all of the\nmessages are contained in.  The QWK file format is based on PCBoard\n12.0 message base format from Clark Development Corporation (maker of\nPCBoard BBS software).\n\nThe file has a logical record length of 128-bytes.  The first record\nof MESSAGES.DAT always contain a copyright notice saying \"Produced by\nQmail...Copyright (c) 1987 by Sparkware.  All Rights Reserved\".  The\nrest of the record is space filled.  Actual messages consist of a 128-\nbytes header, plus one or more 128-bytes block with the message text. \nActual messages start in record 2.  The header block is layed out as\nfollows:\n\nOffset  Length  Description\n------  ------  ----------------------------------------------------   \n    1       1   Message status flag (unsigned character)\n                ' ' = public, unread\n                '-' = public, read\n                '*' = private, read by someone but not by intended\n                recipient\n                '+' = private, read by official recipient\n                '~' = comment to Sysop, unread\n                '`' = comment to Sysop, read\n                '%' = sender password protected, unread\n                '^' = sender password protected, read\n                '!' = group password protected, unread\n                '#' = group password protected, read\n                '$' = group password protected to all\n    2       7   Message number (in ASCII)\n    9       8   Date (mm-dd-yy, in ASCII)\n   17       5   Time (24 hour hh:mm, in ASCII)\n   22      25   To (uppercase, left justified)\n   47      25   From (uppercase, left justified)\n   72      25   Subject of message (mixed case)\n   97      12   Password (space filled)\n  109       8   Reference message number (in ASCII)\n  117       6   Number of 128-bytes blocks in message (including the\n                header, in ASCII; the lowest value should be 2, header\n                plus one block message; this number may not be left\n                flushed within the field)\n  123       1   Flag (ASCII 225 means message is active; ASCII 226\n                means this message is to be killed)\n  124       2   Conference number (unsigned word)\n  126       2   Logical message number in the current packet; i.e.\n                this number will be 1 for the first message, 2 for the\n                second, and so on. (unsigned word)\n  128       1   Indicates whether the message has a network tag-line\n                or not.  A value of '*' indicates that a network tag-\n                line is present; a value of ' ' (space) indicates\n                there isn't one.  Messages sent to readers (non-net-\n                status) generally leave this as a space.  Only network\n                softwares need this information.\n\nFields such as To, From, Subject, Message #, Reference #, and the like\nare space padded if they are shorter than the field's length.\n\nThe message text starts in the next record.  You can find out how many\nblocks make up one message by looking at the value of \"Number of 128\nbyte blocks\".  Instead of carriage return and line feed combination,\neach line in the message end with an ASCII 227 (pi character) symbol. \nThere are reports that some (buggy) readers have problems with messag-\nes which do not end the last line in the message with an ASCII 227. \nIf a message does not completely occupy the 128-bytes block, the re-\nmainder of the block is padded with space or null.\n\nNote that there seems to exist old doors which will use one byte to\nrepresent the conference number and pad the other one with an ASCII 32\ncharacter.  The program reading this information will have to deter-\nmine whether the ASCII 32 in byte 125 of the header is a filler or\npart of the unsigned word.  One method is to look in the CONTROL.DAT\nfile to determine the highest conference number.\n\nEven though most mail programs will generate MESSAGES.DAT files that\nappear in conference order, this is not always the case.  Tomcat!\n(mail door for Wildcat! BBS) generates MESSAGES.DAT that is not in\nconference order.  This is due to how Wildcat! itself stores mail on\nthe BBS.  Another known system that behaves this way is Auntie, which\nhas its mail door QWiKer.\n\nNote that some mail doors offer the option of sending a mail packet\neven though there may be no messages to send -- thus an empty MESSAG-\nES.DAT file.  This was tested with Qmail 4.0 door and it sent a MES-\nSAGES.DAT file that contains a few empty 128-bytes blocks.  Other mail\ndoors seem to be able to produce QWK files without the MESSAGES.DAT\nfile at all!  Apparently, there was no standard established in this\nprocedure.\n\n[3.10]  Index files (*.NDX)\n\n[3.10.1]  Conference indices\n\nThe index files contain a list of pointers pointing to the beginning\nof messages in the MESSAGES.DAT file.  The pointer is in terms of the\n128-bytes block logical record that the MESSAGES.DAT file is in.  Each\nconference has its own xxx.NDX file, where xxx is the conference num-\nber left padded with zeroes.  Some mail programs offer the user the\noption to not generate index files.  So the mail readers need to cre-\nate the index files if they are missing.\n\nEZ-Reader 1.xx versions will convert the NDX files from Microsoft MKS\nformat into IEEE long integer format.  The bad part about this is that\nthe user may store those index files back into the QWK file.  When\nanother reader reads the index files, it will be very confused!\n\nSpecial note for BBSes with more than 999 conferences: Index files for\nconferences with four digit conference numbers is named xxxx.NDX,\nwhere xxxx is the conference number (left padded with zeroes).  The\nfilenames for three digit conferences are still named xxx.NDX on these\nboards.  I would assume filenames for conferences in the five digit\nrange is xxxxx.NDX, but I have not seen a BBS with 10,000 or more\nconferences yet!\n\nEach NDX file uses a five bytes logical record length and is formatted\nto:\n\nOffset  Length  Description\n------  ------  ------------------------------------------------------\n    1       4   Record number pointing to corresponding message in\n                MESSAGES.DAT.  This number is in the Microsoft MKS$\n                BASIC format.\n    5       1   Conference number of the message.  This byte should\n                not be used because it duplicates both the filename of\n                the index file and the conference # in the header.  It\n                is also one byte long, which is insufficient to handle\n                conferences over 255.\n\nPlease refer to appendix B for routines to deal with MKS numbers.\n\n[3.10.2]  Personal index (PERSONAL.NDX)\n\nThere is a special index file named PERSONAL.NDX.  This file contains\npointers to messages which are addressed to the user, i.e. personal\nmessages.  Some mail door and utility programs also allow the selec-\ntion of other messages to be flagged as personal messages.\n\n[3.11]  Pointer file\n\nPointer file is generally included so that the user can reset the last\nread pointers on the mail program, in case there is a crash on the BBS\nor some other mishaps.  There should be little reason for the reader\nprogram to access the pointer file.\n\nThe pointer files I have seen are:\n\nKMail          BBSID.PNT\nMarkMail       BBSID.PNT\nQmail          BBSID.PTR\nQWiKer         HMP.PTR\nSFMailQwk      BBSID.SFP\n\nAdditions to this list are welcomed.\n\n[3.12]  SESSION.TXT\n\nThis file, if included, will contain the message scanning screen the\nuser sees from the door.\n\n[4]  REP files\n\n[4.1]  Naming convention\n\nThe reply file is named BBSID.MSG, where BBSID is the ID code for the\nBBS found on line 5 of the CONTROL.DAT file.  Once this file has been\ncreated, the mail reader can archive it up into a file with REP exten-\nsion.\n\n[4.2]  Message file (BBSID.MSG)\n\nReplies use the same format as the MESSAGES.DAT file, except that\nmessage number field will contain the conference number instead.  In\nother words, the conference number will be placed in the two bytes\n(binary) starting at offset 124, as well as the message number field\n(ASCII) at offset 2.\n\nA private message is indicated by '*' in the message status flag.  For\nsome reason, most mail doors only accept '*' as a private message and\nnot '+'.\n\nThe first 128-bytes record of the file is the header.  Instead of the\ncopyright notice, it contains the BBSID of the BBS.  This 1-8 charac-\nter BBSID must start at the very first byte and must match what the\nBBS has.  The rest of the record is space padded.  The replies start\nat record 2.  Each reply message will have a 128-bytes header, plus\none or more for the message text; followed by another header, and so\non.\n\nThe mail program must check to make sure the BBSID in the first block\nof the BBSID.MSG file matches what the BBS has!\n\n[4.3]  Door control messages\n\nThese messages allow the user to change their setup on the BBS by\nsimply entering a message.  The goal is to allow the user to be able\nto control most areas of the BBS via the mail door.  Different mail\ndoors have different capabilities.  Most all of them offer the ability\nto add and drop a conference, as well as reset the last read pointers\nin a conference.\n\nThere are two trends being developed for door control messages.  The\none being referred to as the \"old\" style accepts one command per mes-\nsage (command entered in the subject line); whereas the \"new\" style\naccepts multiple commands per message (commands entered in the message\nbody).  The old style is by far the more popular but more and more\ndoors are beginning to offer both.\n\n[4.3.1]  DOOR.ID file\n\nThe DOOR.ID file was first introduced by Greg Hewgill with Tomcat!\nmail door and SLMR mail reader.  Since then, many other authors have\npicked up this idea and use the format.  This file provides the neces-\nsary identifiers a reader needs to send add, drop, etc. messages to\nthe mail door.  It tells the reader who to address the message to and\nwhat can be put in the subject line.\n\nDOOR = <doorname>             This is the name of the door that creat-\n                              ed the QWK packet, i.e. <doorname> =\n                              Tomcat.\nVERSION = <doorversion>       This is the version number of the door\n                              that created the packet, i.e.\n                              <doorversion> = 2.9.\nSYSTEM = <systemtype>         This is the underlying BBS system type\n                              and version, i.e. <systemtype> = Wildcat\n                              2.55.\nCONTROLNAME = <controlname>   This is the name to which the reader\n                              should send control messages, eg.\n                              <controlname> = TOMCAT.\nCONTROLTYPE = <controltype>   This can be one of ADD, DROP, REQUEST,\n                              or others.  ADD and DROP are pretty\n                              obvious (they work as in MarkMail), and\n                              REQUEST is for use with BBS systems that\n                              support file attachments.  Try out SLMR\n                              with CONTROLTYPE = REQUEST and use the Q\n                              function.  (This seems to be a Wildcat!\n                              BBS feature.)\nRECEIPT                       This flag indicates that the door/BBS is\n                              capable of return receipts when a mes-\n                              sage is received.  If the first three\n                              letters of the subject are RRR, then the\n                              door should strip the RRR and set the\n                              'return-receipt-requested' flag on the\n                              corresponding message.  When the ad-\n                              dressee reads this message, the BBS\n                              generates a message with the date/time\n                              it was read.\nMIXEDCASE = YES               If this line is found then the reader\n                              will let you use upper and lower case\n                              names and subjects.  This is first found\n                              in Qmail DeLuxe2 1.25 version.  Most\n                              other QWK readers permit the use of\n                              mixed case subject lines but force the\n                              names to upper case only.\nFIDOTAG = YES                 If this line is found then the reader\n                              will automatically use FidoNet compliant\n                              tag-lines.\n\nNone of the lines are actually required and they may appear in any\norder.  Of course, you would need a CONTROLNAME if you have any\nCONTROLTYPE lines.\n\n[4.3.2]  Qmail\n\nQmail uses the \"new\" style of control message; therefore, send a mes-\nsage addressed to \"QMAIL\" with a subject of \"CONFIG\".  Then, enter any\nof the commands listed below inside the text of your message.  Remem-\nber to use one command per line.\n\nADD <confnum>            Add a conference into the Qmail Door scanning\n                         list.  \"YOURS\" can also be added to the com-\n                         mand if the user wishes to receive messages\n                         only addressed them.  i.e. \"ADD 1 YOURS\". \n                         \"YOURS ALL\" can be added to select a confer-\n                         ence for all mailed addressed to the user and\n                         to \"ALL\".\nDROP <confnum>           Drop a conference from the Qmail Door scan-\n                         ning list.\nRESET <confnum> <value>  Resets a conference to a particular value.\n                         The user can use \"HIGH-xxx\" to set the con-\n                         ference to the highest message in the base.\nCITY <value>             Changes the \"city\" field in the user's\n                         PCBoard entry.\nPASSWORD <value>         Changes the user's login password.\nBPHONE <value>           Business/data phone number\nHPHONE <value>           Home/voice phone number\nPCBEXPERT <on|off>       Turns the PCBoard expert mode ON or OFF.\nPCBPROT <value>          PCBoard file transfer protocol (A-Z).\nPAGELEN <value>          Set page length inside PCBoard.\nPCBCOMMENT <value>       Set user maintained comment.\nAUTOSTART <value>        Qmail Door autostart command.\nPROTOCOL <value>         Qmail Door file transfer protocol (A-Z).\nEXPERT <ON or OFF>       Turns the Qmail Door expert mode ON or OFF.\nMAXSIZE <value>          Maximum size of the user's .QWK packet (in\n                         bytes)\nMAXNUMBER <value>        Maximum number of messages per conference.\n\n[4.3.3]  MarkMail\n\nSend a message addressed to \"MARKMAIL\" with the subject line saying:\n\nADD [value]         in the conference you want to add\nDROP                in the conference you want to drop\nYOUR [value]        in the conference you want only your mail sent\nYA [value]          in the conference you want only your mail + mail\n                    addressed to \"ALL\"\nFILES ON or OFF     in any conference to tell MarkMail whether to scan\n                    for new files or not.\nBLTS ON or OFF      to turn on and off, respectively, of receiving\n                    bulletins.\nOWN ON or OFF       to turn on and off, respectively, of receiving\n                    messages you sent\nDELUXE ON or OFF    to turn on and off, respectively, of receiving\n                    DeLuxe menu\nLIMIT <size>        to set the maximum size of MESSAGES.DAT file can\n                    be, it cannot exceed what the Sysop has set up\n\nAn optional number can be added onto the commands \"ADD\", \"YOUR\", and\n\"YA\".  If this number is positive, then it will be treated as an abso-\nlute message number.  MarkMail will set your last read pointer to that\nnumber.  If it is negative, MarkMail will set your last read pointer\nto the highest minus that number.  For example: \"ADD -50\" will add the\nconference and set the last read pointer to the highest in the confer-\nence minus 50.\n\n[4.3.4]  KMail\n\nSend a private message addressed to \"KMAIL\" in the conference that you\nwant to add, drop, or reset.  The commands are \"ADD\", \"DROP\", and\n\"RESET #\", respectively.  The \"#\" is the message number you want your\nlast read pointer in the conference be set to.\n\n[4.3.5]  RoseMail\n\nThe RoseMail door allows configuration information be placed in either\nthe subject line or message text.  The message must be addressed to\n\"ROSEMAIL\".  For only one command, it can be placed in the subject\nline.  For more than one changes, the subject line must say \"CONFIG\"\nand each change be placed in the message text.  Every line should be\nleft justified.  Valid commands are:\n\nCommand                                           Example\n------------------------------------------------- ------------------\nADD <Conference> [<Message #>] [<Yours>]          ADD 2 -3 Y\nDROP <Conference>                                 DROP 2\nRESET <Conference> <Message #>                    RESET 12 5000\nPCBEXPERT <ON | OFF> - PCBoard expert mode        PCBEXPERT ON\nEXPERT <ON | OFF>    - RoseMail expert mode       EXPERT OFF\nPCBPROT <A - Z>      - PCBoard protocol           PCBPROT Z\nPROT <A - Z>         - RoseMail protocol          PROT G\nPAGELEN <Number>     - Page length                PAGELEN 20\nMAXSIZE <Kbytes>     - Max packet size in Kb      MAXSIZE 100\nMAXNUMBER <max msgs/conference>                   MAXNUMBER 100\nJUMPSTART <Sequence or OFF>                       JUMPSTART D;Y;Q\nMAXPACKET <max msgs/packet>                       MAXPACKET 500\nAUTOSTART <Sequence or OFF> - same as jumpstart   AUTOSTART OFF\nOPT <##> <ON | OFF>  - set door option            OPT 2 OFF\n\n[4.3.6]  Complete Mail Door\n\nSend message to \"CMPMAIL\", the commands are \"ADD\" and \"DROP\".  This\nmessage must be sent in the conference that you want to add or drop.\n\n[4.3.7]  The MainMail System\n\nSend a message addressed to \"MAINMAIL\" with the subject line saying:\n\nADD [value]         in the conference you want to add\nDROP                in the conference you want to drop\nYOURS [value]       in the conference you want only your mail sent\nYOURS ALL [value]   in the conference you want only your mail + mail\n                    addressed to \"ALL\"\n\nThe optional [value] parameter functions identically to the MarkMail\ndoor -- positive number indicates an absolute message number, negative\nnumber will set your last read pointer that many messages from the\nlast message.\n\n[4.3.8]  BGQWK\n\nThe BGQWK mail door for GT Power supports file request via message. \nTo request a file, simply enter a message:\n\n     To: BGQWK\nSubject: DL:FILENAME.EXT\n\nThe FILENAME.EXT has to be exact name, wildcard is not supported.  The\nmessage text can be left blank.\n\nThe only limit on the file request feature is your time and/or your\nfile ratio.  The transfer of the requested file(s) will start right\nafter the QWK download is completed.  The only exception is when the\nuser is using a bidirectional transfer protocol.  There, the REP and\nQWK are sent at the same time, hence, the file request cannot be pro-\ncessed until the QWK transfer is completed.\n\n[4.3.9]  UltraBBS\n\nSend a private message addressed to \"ULTRABBS\" in the conference that\nyou want to add, drop, or reset.  The commands are \"ADD\", \"DROP\", and\n\"RESET #\", respectively.  The \"#\" is the message number you want your\nlast read pointer in the conference be set to.  The QWK mail door for\nUltraBBS is built in and it generates the DOOR.ID file as well.\n\n[4.3.10]  TriMail\n\nTriMail is the QWK door for TriBBS.  This door will accept off-line\nconfiguration options sent to Qmail, MarkMail, or TriMail.  This means\nyou can send the message to: \"QMAIL\", \"MARKMAIL\", or \"TRIMAIL\" in the\nappropriate conference and it will work.  The available options are:\n\nBLTS ON             Turn bulletin scan on\nBLTS OFF            Turn bulletin scan off\nFILES ON            Turn new files scan on\nFILES OFF           Turn new files scan off\nRESET <value>       Reset last message read pointer\nDROP                Drop this conference\nADD [value]         Add this conference.  The [value] is optional and\n                    will set the last message read pointer.\n\n[4.3.11]  Cam-Mail\n\nAddress your message to either QMAIL or CAM-MAIL.  Then enter the\ncommand in the subject line.  Valid commands are:\n\nAdd                 Add conferences for scanning\nBulletins On        Download all new bulletins in QWK packet\nBulletins Off       Turn off download of new bulletins\nColor On            Download the QWK packet in color, if available\nColor Off           Turn off download in color\nDrop                Drop a conference from scanning\nDuplicates On       Turn on duplicate checking in REP files\nDuplicates Off      Turn off duplicate checking\nFiles On            Download new files list in QWK packet\nFiles Off           Turn off download of new files list\nGoodbye On          Send the Goodbye files with the QWK packet\nGoodbye Off         Does not send the Goodbye files\nMailflags On        Notifies users they have mail\nMailflags Off       Does not notify users of mail\nNDX On              Create NDX files for QWK packet\nNDX Off             Does not create NDX files\nWelcome On          Send the Welcome file with the QWK packet\nWelcome Off         Does not send the Welcome file\n\n[4.3.12]  QSO\n\nQSO supports both \"old\" and \"new\" style off-line configuration com-\nmands.  For the \"old\" style, message should be addressed to either\nQMAIL or QSO.  The message must be entered in the conference it af-\nfects, with the subject line containing:\n\nADD                 Add conference\nADD -20             Add conference and set last read pointer to the\n                    highest number in conference minus 20\nADD HIGH-20         Same as above\nADD LOW+50          Add conference and set last read pointer to the\n                    lowest number in conference plus 50\nADD 1234            Add conference and set last read pointer to a\n                    specific message number\nADD YOURS           Add conference for messages addressed to you only;\n                    the YOURS keyword may appear before or after the\n                    message number; YOURS may be abbreviated as just Y\nDROP                Drop the conference\nRESET               Reset last read pointer to highest in conference\nRESET -20           Reset to highest number minus 20\nRESET HIGH-20       Same as above\nRESET LOW+50        Reset to lowest number plus 50\nRESET 1234          Reset last read pointer to specific number\n\nFor the \"new\" style message, enter the message addressed to either\n\"QMAIL\" or \"QSO\" with the subject line saying \"CONFIG\".  The message\ntext should have commands similar to the ones listed above.  The only\nexception is that the conference number must be entered immediately\nafter the first keyword.  For example:\n\nADD 15 -20          Add conference 15, reset pointer to high minus 20\nDROP 137            Drop conference 137\nADD 20 HIGH-50 Y    Add conference 20 for mail addressed to user only,\n                    and set the pointer to highest minus 50\n\nQSO supports file sending in the mail packet as well.  Attached files\nhave the name EMnnnnn, where nnnnn is a five digit leading zero padded\nnumber indicating the message number in which the request was sent. \nThe plain text file ATTACHED.LST lists the real name of the file, and\nhas the following format (one line per record):\n\n     <conference #>, <message #>, <EMnnnnn filename>, <real name>\n\n<conference #>      Conference where the request came from\n<message #>         Message number where request came from\n<EMnnnnn filename>  File as named inside the QWK file\n<real name>         Original filename as seen on the BBS\n\nFor messages that has an enclosed file, the last line of the message\nhas the line: \n\n*Enclosed file: filename.ext\n\nThe reader program must send a request to obtain this file.  The re-\nquest is in the format similar to any other control messages:\n\nTo: QSO\nSubject: REQUEST nnnnn\n\nwhere nnnnn is the message number that contains this attached file. \nThis message must be sent in the conference where that contains that\nmessage.  Alternatively, the \"new\" style can also be used.  With the\nline \"REQUEST confnum nnnnn\" in the message text.\n\nTo upload a file that is attached to a message, the file ATTXREF.DAT\nmust be created.  The file is a plain text file with one line corre-\nsponding to each message in the reply file.  Blank lines must be in-\ncluded for those messages that do not have files attached to them.  A\nnon-blank line has the following format to indicate a file is attached\nto that message:\n\n<internal name>, <real name>\n\n<internal name>     is any non-conflicting filename\n<real name>         the name as it should appear on the BBS\n\n[4.4]  Turning off the echo flag\n\nIn order to send a non-echoed message (not send out to other BBSs), a\nuser can enter \"NE:\" in front of the subject line.  This feature may\nnot be offered in all mail doors.\n\nSome mail doors strip out the \"NE:\" from the subject line.  However,\nthat leaves the recipient with nothing to tell that the message was\nnot echoed.  Therefore, it is better if \"NE:\" is not stripped.\n\n[4.5]  Tag-lines\n\nThe most common format for a reader tag-line is:\n\n---\n * My reader v1.00 * The rest of the tag-line.\n\n(The asterisks above should be replaced by IBM extended character\nnumber 254 - a square block.)\n\nThe three dashes is called a tear-line.  The tag-line is appended to\nthe end of the message and is usually one line only.  It is preferred\nthat tag-lines conform to this format so that networking softwares\nsuch as QNet and RNet will not add another tearline to the message\nwhen they process it.\n\nSoftwares on FidoNet does not like mail readers adding a tear-line of\ntheir own, so if your mail reader offers a FidoNet mode, you will need\nto get rid of the tear-line.  Another item which differs between the\nFidoNet and PC-based networks is that FidoNet does not like extended\nASCII characters.  So your reader may want to strip high ASCII if the\nuser has FidoNet mode on.  Acceptable tag-line style, I believe, is\njust this:\n\n * My Reader v1.00 * The rest of the tag-line.\n\n[5]  Net mail\n\nQWK mail doors can be used along or in conjunction with QWK network\nsoftwares to operate a network.  Many such network exists.  A Net-\nStatus packet (one that can be imported to BBS message base) is very\nsimilar to a normal mail packet users get.  The only difference is at\nthe end of the MESSAGES.DAT file.  There, a series of 128 byte blocks\nare appended to indicate Net-Status.  \n\nOne byte represent one conference, in groups of 128.  A non-zero value\nmeans the user is allowed Net Mail status for that conference.  The\nnumber of Net Status blocks appended to the MESSAGES.DAT file only\nneeds to cover the highest conference the user has access to.\n\nThe reason these packets have to be different?  Using QWK mail doors\nto send and receive messages require you to be able to send messages\nin other user's name as well as receive private messages in conferenc-\nes.  The Net-Status tells the mail door to import the messages even if\nthey are from another name.\n\nThe only weird implementation here is that the block with the highest\nconference numbers come before the lower ones.  Hence, to illustrate:\n\n       Conference 128\n       |  Conference 129\n       |  |\n      vv vv\n0000  00 00 FF 00 00 00 00 00-00 00 00 00 00 00 00 00  Flags for\n0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  conferences\n0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  128-255\n0030  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n0040  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n0050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n0060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n0070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 FF 00\n\n       Conference 0\n       |  Conference 1\n       |  |\n      vv vv\n0080  00 FF 00 00 00 00 00 00-00 00 00 00 00 00 00 00  Flags for\n0090  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  conferences\n00A0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  0-127\n00B0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n00C0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n00D0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n00E0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00\n00F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 FF\n\nThis example shows that this user has Net Status in conferences 1,\n127, 130, and 254.\n\nMarkMail and KMail doors (both for PCBoard) choos to implement things\na little differently.  Instead of appending Net-Status blocks to the\nend of the MESSAGES.DAT file, they simply put \"MarkMail\" or \"Kmail...\"\nin the first 8 position of the file and the user is granted Net-Status\nin all conferences.\n\n                     -=-=-=-=-=-=-<>-=-=-=-=-=-=-\n\n[A]  Credits and Contributions\n\nMark \"Sparky\" Herring, who originated the QWK-format.\n\nTim Farley, who started this documentation back in the summer of 1990. \nThe general outline here is the work of Tim.  I filled in the blanks.\n\nJeffery Foy, who gave us the format for Microsoft single binary versus\nIEEE format.\n\nGreg Hewgill, who (if I remember correctly) wrote the Turbo Pascal\nroutines (included in here) to convert between MKS and TP LongInt.\n\nDennis McCunney, who is the host of the Off-line conference on RIME,\nis very knowledgeable in off-line reading concept and programs.  His\ngoal is to have one reader that can read mail packet from any source.\n\nCody Gibson and Jeffery Foy, whose information on Net-Status packet\nare included here.\n\nAll those who have been around the Off-line conferences on ILink (the\noldest of the four I participate), RIME, Fido, and Intelec, who have\nprovided great help over the past three years.  The bulk of the infor-\nmation presented here are from messages in those conferences.  These\npeople include, but are no limited to, the followings: Dane Beko,\nJoseph Carnage, Marcos Della, Joey Lizzi, Mark May, and Jim Smith.\n\n[B]  Sample Turbo Pascal and C code\n\nHere are a few routines in Turbo Pascal and C to convert Microsoft\nBASIC MKS format to usable IEEE long integer.  These are collected\nover the networks and there is no guarantee that they will work for\nyou!\n\nTurbo Pascal (Greg Hewgill ?):\n\ntype\n     bsingle = array [0..3] of byte;\n\n{ converts TP real to Microsoft 4 bytes single }\n\nprocedure real_to_msb (preal : real; var b : bsingle);\nvar\n     r : array [0 .. 5] of byte absolute preal;\nbegin\n     b [3] := r [0];\n     move (r [3], b [0], 3);\nend; { procedure real_to_msb }\n\n{ converts Microsoft 4 bytes single to TP real }\n\nfunction msb_to_real (b : bsingle) : real;\nvar\n     preal : real;\n     r : array [0..5] of byte absolute preal;\nbegin\n     r [0] := b [3];\n     r [1] := 0;\n     r [2] := 0;\n     move (b [0], r [3], 3);\n     msb_to_real := preal;\nend; { function msb_to_real }\n\nAnother Turbo Pascal routine to convert Microsoft single to TP LongInt\n(Marcos Della):\n\nindex := ((mssingle and not $ff000000) or $00800000) shr (24 -\n((mssingle shr 24) and $7f)) - 1;\n\nC (identify yourself if you wrote this routine):\n\n/* converts 4 bytes Microsoft MKS format to long integer */\n\nunsigned long mbf_to_int (m1, m2, m3, exp)\nunsigned int m1, m2, m3, exp;\n{\n     return (((m1 + ((unsigned long) m2 << 8) + ((unsigned long) m3 <<\n     16)) | 0x800000L) >> (24 - (exp - 0x80)));\n}\n\nMicrosoft binary (by Jeffery Foy):\n\n   31 - 24    23     22 - 0        <-- bit position\n+-----------------+----------+\n| exponent | sign | mantissa |\n+----------+------+----------+\n\nIEEE (C/Pascal/etc.):\n\n   31     30 - 23    22 - 0        <-- bit position\n+----------------------------+\n| sign | exponent | mantissa |\n+------+----------+----------+\n\nIn both cases, the sign is one bit, the exponent is 8 bits, and the\nmantissa is 23 bits.  You can write your own, optimized, routine to\nconvert between the two formats using the above bit layout.\n\n[C]  Sample message\n\nHere is a sample message in hex and ASCII format:\n\n019780  20 34 32 33 32 20 20 20 30 32 2D 31 35 2D 39 32   4232   02-15-92\n019790  31 33 3A 34 35 52 49 43 48 41 52 44 20 42 4C 41  13:45RICHARD BLA\n0197A0  43 4B 42 55 52 4E 20 20 20 20 20 20 20 20 53 54  CKBURN        ST\n0197B0  45 56 45 20 43 4F 4C 45 54 54 49 20 20 20 20 20  EVE COLETTI     \n0197C0  20 20 20 20 20 20 20 51 45 44 49 54 20 48 41 43         QEDIT HAC\n0197D0  4B 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  K               \n0197E0  20 20 20 20 20 20 20 20 20 20 20 20 34 30 33 36              4036\n0197F0  20 20 20 20 37 20 20 20 20 20 E1 0A 01 00 00 20      7           \n019800  2A 20 49 6E 20 61 20 6D 65 73 73 61 67 65 20 64  * In a message d\n019810  61 74 65 64 20 30 32 2D 30 39 2D 39 32 20 74 6F  ated 02-09-92 to\n019820  20 53 74 65 76 65 20 43 6F 6C 65 74 74 69 2C 20   Steve Coletti, \n019830  52 69 63 68 61 72 64 20 42 6C 61 63 6B 62 75 72  Richard Blackbur\n019840  6E 20 73 61 69 64 3A E3 E3 52 42 3E 53 43 20 AF  n said:  RB>SC  \n019850  20 65 64 69 74 6F 72 20 69 6E 20 74 68 65 20 28   editor in the (\n019860  6D 61 69 6E 66 72 61 6D 65 29 20 56 4D 2F 43 4D  mainframe) VM/CM\n019870  53 20 70 72 6F 64 75 63 74 20 6C 69 6E 65 20 69  S product line i\n[ etc. ]\n019A00  6E 6F 74 20 61 20 44 6F 63 74 6F 72 2C 20 62 75  not a Doctor, bu\n019A10  74 20 49 20 70 6C 61 79 20 6F 6E 65 20 61 74 20  t I play one at \n019A20  74 68 65 20 48 6F 73 70 69 74 61 6C 2E E3 20 20  the Hospital.   \n019A30  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n019A40  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n019A50  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n019A60  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n019A70  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n019A80  E3 50 43 52 65 6C 61 79 3A 4D 4F 4F 4E 44 4F 47   PCRelay:MOONDOG\n019A90  20 2D 3E 20 23 33 35 20 52 65 6C 61 79 4E 65 74   -> #35 RelayNet\n019AA0  20 28 74 6D 29 E3 34 2E 31 30 20 20 20 20 20 20   (tm) 4.10      \n019AB0  20 20 20 20 20 20 20 20 20 48 55 42 4D 4F 4F 4E           HUBMOON\n019AC0  2D 4D 6F 6F 6E 44 6F 67 20 42 42 53 2C 20 42 72  -MoonDog BBS, Br\n019AD0  6F 6F 6B 6C 79 6E 2C 4E 59 20 37 31 38 20 36 39  ooklyn,NY 718 69\n019AE0  32 2D 32 34 39 38 E3 20 20 20 20 20 20 20 20 20  2-2498          \n019AF0  20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  \n\n[D]  Sample index file\n\nHere is a sample index file in hex format:\n\n000000  00 00 28 87 19 00 00 30 87 19 00 00 38 87 19 00\n000010  00 7E 87 19 00 00 07 88 19 00 00 0B 88 19 00 00\n000020  0F 88 19 00 00 14 88 19 00 00 19 88 19 00 00 1E\n000030  88 19 00 00 22 88 19 00 00 27 88 19 00 00 2C 88\n000040  19 00 00 31 88 19 00 00 3B 88 19 00 00 40 88 19\n000050  00 00 46 88 19 00 00 49 88 19 00 00 4D 88 19 00\n000060  00 52 88 19 00 00 55 88 19 00 00 59 88 19 00 00\n000070  60 88 19 00 00 66 88 19 00 00 70 88 19\n\nThis index file is for conference 25.  The values for the offset are as\nfollows: 84, 88, 92, 127, 135, 139, 143, 148, 153, 158, 162, 167, 172,\n177, 187, 192, 198, 201, 205 210, 213, 217, 224, 230, and 240.\n\u001a"
  },
  {
    "path": "specs/qwk/qwke.txt",
    "content": "\n                           QWKE Specifications 1.02\n      (also known as EQWK - pronounced Quicky, and E-quick respectively)\n\n\n                      Copyright 1994-1997, Peter Rocca\n                             Fidonet 1:2401/305\n                       Email: support@multiboard.com\n                         http://www.multiboard.com/\n                               (519) 660-3574\n\n\n This documentation may be freely used to enhance/create 1st, 2nd or 3rd\n party applications or utilities without any legal obligation to the author.\n Please do not extend or further the QWKE without contacting Pete Rocca, in\n order to keep the standard from becoming a 'non-standard'. - Thank you.\n\n\n QWKE Specifications\n \n\n All files and formats match the QWK 1.0 standards.  If you are not familiar\n with them, I would suggest getting QWKLAY??.ZIP by Patrick Y. Lee. (it is\n freqable from my system)\n\n The only differences to the standard QWK format lay in four files.\n\n         CONTROL.DAT  - conference area names are no longer limited\n                        to 13 characters, they are limited to 255\n                        characters now.\n\n         DOOR.ID      - contains additional CONTROLTYPE names.\n\n         TOREADER.EXT - a file created by the door that contains\n                        additional information for the reader.\n\n         TODOOR.EXT   - a file created by the reader that contains\n                        additional information for the door.\n\n In addition, certain kludge lines should be imported to messages when\n downloading, if their length exceeds 25 characters.\n\n   These kludges are...\n\n                           To:\n                           From:\n                           Subject:\n\n   ...they should be at the top of the message, and terminated by\n   either a carriage return, or the '' QWK terminator.  At the end\n   of the last imported kludge, there should be a blank line, however\n   you should program to handle if one is not present.  Additional\n   kludge names can be created, but your reader/door should at least\n   handle these three.\n\n   Also, the kludge lines To/Subject should be imported into the message\n   fields when posting the messages. (uploading)  The From kludge can\n   be accepted, but remember to check the security of it (ie make sure\n   that the name is allowed, ie alias base, etc)  Also, regarding the\n   To: kludge... keep in mind that UUCP software likes the To: line\n   left in the first line of a message, therefore it should not be\n   removed from the message if this message is destined to be sent\n   through an UUCP gateway.\n\n   A sample message with kludge lines might look like:\n\n     1       10        20   25\n     |---+----|----+----|----|\n  TO:PETER ROCCAZISKINZIDONING\nFROM:BOB WILIKERS\nSUBJ:This is a test of the sys                       <--- HEADER\n     --------------------------------------------------------------------\n     To: PETER ROCCAZISKINZIDONINGLY                 <--- MESSAGE TEXT\n     Subject: This is a test of the system, as you can see!\n     <blank line>\n     The real message starts here now, but it was short, so\n     see you later.\n\n   As you can see, only the To/Subject lines were imported, since the\n   From line did not exceed the 25 character limit.\n\n   One command question is NETMAIL? How do you do it?  A standard that\n   I would suggest is the \"Subject line method\" which is simply an \"at\"\n   symbol, followed by the full netmail address.  For example to send\n   mail to Pete Rocca at 1:2401/305.200, the message header would look\n   like this:\n\n   To: PETE ROCCA\n   Fm: JOE USER\n   Sb: @1:2401/305.200\n\n   How about internet mail?\n\n   Well, internet mail going out a fido gateway would simply be a netmail\n   message with a To: <address> on the first line. It is upto the mail\n   door not to import a \"To:\" kludge when sending internet netmail mail.\n   For example (Fido->Internet)\n\n   To: UUCP\n   Fm: JOE USER\n   Sb: @1:1/31\n   ------------------------------------\n   To: support@mbcc.com\n   Subject: Hello there\n\n   A regular internet message would simply be a regular message, but with\n   a \"To\" kludge to avoid the 25 character limit in the To field.\n   For example (regular Internet)\n\n   To: INTERNET                         <--- this gets replaced on import\n   Fm: JOE USER\n   Sb: Hello there\n   ------------------------------------\n   To: support@mbcc.com\n\n   Of course, as a door or reader author, you can make this completely\n   transparent to the user.\n\n\n\n\n File: TOREADER.EXT\n \n\n  Desc: This file is simply an ASCII text file that is included\n        in the QWK packet, and contains information used by the\n        QWK reader. (created by the mail door)\n\n Each line has an identifier, followed by the relevant information\n for the extended information. (Arguments in < > are required,\n and ones in [ ] are optional)\n\n   ALIAS     <users' alias name>\n   AREA      <conference#> <settings>\n   BULL      <filename> <description>\n   ATTACH    <filename> <conference#> <message#>\n   FILE      <filename> [description]\n   KEYWORD   <keyword>\n   FILTER    <filter>\n   TWIT      <twit>\n\n\n\nIdentifier: ALIAS <users' alias name>\n\n   This simply passes the users' alias name to the door in order to be\n   able to present it to the user when entering mail in 'alias' areas.\n\n   An example would be: ALIAS Rawhide\n\n\n\nIdentifier: AREA <conference#> <settings>\n\n   This presents a list of selected areas (or all areas optionally), and\n   what the flag settings for each area are.  The <conference#> is the\n   number of the area that is selected and the <settings> contains the\n   flags for that area.\n\n   The possible flags are:\n\n       a   for all messages\n       p   for personal messages\n       g   for general messages (personal and those addressed to 'ALL')\n\n   In addition, some mail doors can add the following flags: (this\n   information is set by the mail door itself, and overrides and standard\n   BBS settings)\n\n       w   if this area should include mail written by themselves\n       k   if this area should be included in keyword searches\n       f   if this area should be included in filter exclude searches\n       F   if this area is forced to be read\n       B   if this area is blocked from getting replies\n\n   In further addition, area information should be given - this information\n   is gathered from the BBS records.\n\n       P   if the area is private mail only\n       O   if the area is public mail only\n       X   if either private or public mail is allowed\n       R   if the area is read-only (no posting at all allowed)\n       Z   if the area doesn't allow replies (no continuation of thread)\n\n       L   if the area is a local message area\n       N   if the area is a netmail area\n       E   if the area is an echomail area\n       I   if the area is an internet area\n       U   if the area is an newsgroup area\n\n       H   if the area is an handles only message area\n       A   if the area allows messages 'from' any name (pick-an-alias)\n       &   if the area allows file attaches\n           (does not override CONTROLTYPE=ALLOWATTACH)\n\n   Again the door should enforce security to messages with private\n   flags and/or different names to ensure that they are allowed.\n\n   For example, if a user had 4 areas selected, it might look like this:\n\n   AREA 23 awOU\n   AREA 31 aFPLA\n   AREA 44 pkPN&\n   AREA 172 gwkfPI\n\n   ...please note that the flags ARE case sensitive & and any unknown\n   flags should be ignored.\n\n\n\nIdentifier: BULL <filename> <description>\n\n   This is a way of describing the bulletins a little better than\n   the file name BLT-x.y method.  The actual files should still be\n   in the BLT-x.y format to ensure backward compatibility, but by\n   describing the filenames here, you can have something like\n   looks like:\n\n        Bulletins\n          - System Stats\n          - Top Users\n          - Contest galore!\n\n   Instead of:\n\n        Bulletins\n          - BLT-1.4\n          - BLT-3.2\n          - BLT-6.1\n\n   In this example, the TOREADER.EXT file would have three lines\n   added to create these descriptions:\n\n   BULL BLT-1.4 System Stats\n   BULL BLT-3.2 Top Users\n   BULL BLT-6.1 Contest galore!\n\n\n\nIdentifier: ATTACH <filename> <conference#> <message#>\n\n   This is a method used to identify which messages have files attached\n   that were downloaded with the packet.  It is upto the mail door\n   to decide whether or not to send attached files, this is simply a\n   method for the reader to acknowledge such files.\n\n   For an example:  Say that message number 782 in conference 12 had\n   the file TEST.ZIP attached to it, and the mail door included this\n   TEST.ZIP file in the BOARDID.QWK archive.  The TOREADER.EXT file\n   would have the follow entry to let the mail reader know about this\n   file.\n\n   ATTACH TEST.ZIP 12 782\n\n\n\nIdentifier: FILE <filename> [description]\n\n   This is a method used to identify which files in the QWK archive\n   are file requests from the bulletin board.  It is upto the mail door\n   to decide whether or not to send these requested files, and this\n   is simply a method for the reader to acknowledge such files.\n\n   For an example:  Say that the file GOODGAME.ARJ was requested and\n   added to the BOARDID.QWK archive.  When the mail reader expanded it,\n   it would not know which files had been requested by the user, nor\n   what the description of those files were.  Place using the FILE\n   identifier, the reader can easily present a nice listing of requested\n   files, rather than having to guess at the file names, and having\n   no idea of the description (although the description is optional).\n   In the GOODGAME.ARJ example, the mail door should add the following\n   line to the TOREADER.EXT file.\n\n   FILE GOODGAME.ARJ This is a great new SVGA action game!\n\n   or\n\n   FILE GOODGAME.ARJ\n\n\n\nIdentifier: KEYWORD <data>\nIdentifier: FILTER  <data>\nIdentifier: TWIT    <data>\n\n   These identifiers are for mail doors that can process keywords,\n   filters and twit listings. It is used only to inform the mail\n   reader of the settings used, in order to make offline configuration\n   much easier for the user.  For example, if the TOREADER.EXT file\n   had the following lines...\n\n   KEYWORD olms\n   KEYWORD qwk\n   FILTER hacking\n   TWIT Death Wizard\n\n   ...then the mail reader could present a list of these settings\n   and allow changes to be made to them, and create the proper\n   TODOOR.EXT lines to alter the configuration.\n\n\n\n File: TODOOR.EXT\n \n\n  Desc: This file is simply an ASCII text file that is included\n        in the QWK packet, and contains information used by the\n        QWK mail door. (created by the mail reader) It must be\n        read back and processed by the door.\n\n Each line has an identifier, followed by the relevant information\n for the extended information. (Arguments in < > are required,\n and ones in [ ] are optional)\n\n   AREA      <conference#> <settings>\n   RESET     <conference#> [#ofmessages]\n   ATTACH    <filename> <reply#>\n   FILE      <filename> [description]\n   REQUEST   <filename>\n   REQUEST   <conference#> <message#>\n   KEYWORD   [-]<keyword>\n   FILTER    [-]<filter>\n   TWIT      [-]<twit>\n\n\n\nIdentifier: AREA <conference#> <settings>\n\n   This presents a list of CHANGES areas, and what the flag settings\n   for each area changed are. The <conference#> is the number of the area\n   that is to be changed and the <settings> contains the flags for that area.\n\n   The possible flags are:\n\n       D   drop area\n       a   for all messages\n       p   for personal messages\n       g   for general messages (personal and those addressed to 'ALL')\n\n   In addition, some mail doors can add the following flags:\n\n       w   if this area should include mail written by themselves\n       k   if this area should be included in keyword searches\n       f   if this area should be included in filter exclude searches\n\n   For example, if a user had changed 2 areas, it might look like this:\n\n   AREA 23 D\n   AREA 44 gf\n\n\n\nIdentifier: RESET <conference#> [#ofmessages]\n\n   This presents a list of pointer changes to be made.  The pointers should\n   be changed for the <conference#> given.  If the [#ofmessages] is blank\n   then the pointer should be set back to the start of the message base,\n   otherwise it should be set back [#ofmessages] back from the end of\n   the message base.\n\n   For example, if a user had modified 2 areas, it might look like this:\n\n   RESET 23 100\n   RESET 44\n\n\n\nIdentifier: ATTACH <filename> <reply#>\n\n   This is a method of creating messages that have files attached\n   to them.  The mail reader should pack the <filename> into the\n   BOARDID.REP file, and add this line in the TODOOR.EXT file,\n   which is also included in the BOARDID.REP file.\n\n   The <reply#> is the number of the message in the reply packet.\n   For example, if the third message in the reply packet had the\n   file ATTACHME.ZIP attached to it:  The BOARDID.REP file should\n   contain the file ATTACHME.ZIP, BOARDID.MSG and the TODOOR.EXT\n   file.  The TODOOR.EXT file would contain the line...\n\n   ATTACH ATTACHME.ZIP 3\n\n   ...within it. NOTE! that it is upto the mail door whether or not\n   it will allow files to be attached to messages.  This is governed\n   by the mail door inserting the line CONTROLTYPE=ALLOWATTACH in\n   the DOOR.ID file.\n\n\n\nIdentifier: FILE <filename> [description]\n\n   This is a method of uploading files in your mail packet.  These\n   are general public files, and should be processed for credit on\n   the bulletin board.\n\n   For example, if you included a file called GOODGAME.ZIP in your\n   BOARDID.REP file for credit on the BBS, the mail reader should\n   insert the line...\n\n   FILE GOODGAME.ZIP This is a great new game!\n\n   ... in the TODOOR.EXT file.  It is upto the mail door whether\n   or not it accepts files to be uploaded with the mail packets.\n   This can be detected by the CONTROLTYPE=ALLOWFILES line\n   being added to the DOOR.ID file in the downloaded packet.\n\n\n\nIdentifier: REQUEST <filename>\nIdentifier: REQUEST <conference#> <message#>\n\n   These are file requests, either for files on the board, or files that\n   are attached to messages.\n\n   \"REQUEST bob.zip\", would request the file BOB.ZIP from the BBS's file\n   collection, whereas \"REQUEST 12 333\", would request the files attached\n   to message #333 in conference #12.  It is upto the door to provide\n   security as to what can be requested.\n\n\n\nIdentifier: KEYWORD [-]<data>\nIdentifier: FILTER  [-]<data>\nIdentifier: TWIT    [-]<data>\n\n   These identifiers are for changes made to the keywords, filters\n   and twit listings. It is used only to process CHANGES therefore\n   if the setting \"KEYWORD bob\" was given, it does not mean it is\n   the only keyword in the list, rather added to the list of keywords.\n   To remove an entry, precede it with a minus sign (-), so an example\n   to remove a keyword \"bob\" from the list of keywords would be\n   \"KEYWORD -bob\"\n\n\n\n Additional CONTROLTYPE= settings (DOOR.ID file)\n \n\n    CONTROLTYPE=MAXKEYWORDS <#>  -> max keywords the door can handle\n    CONTROLTYPE=MAXFILTERS <#>   -> max filters the door can handle\n    CONTROLTYPE=MAXTWITS <#>     -> max twits the door can handle\n    CONTROLTYPE=ALLOWATTACH      -> if the door allows file attachments\n    CONTROLTYPE=ALLOWFILES       -> if the door allows files to be uploaded\n    CONTROLTYPE=ALLOWREQUESTS    -> if the door allows files to be requested\n    CONTROLTYPE=MAXREQUESTS      -> max number of daily file requests\n\n\n\n\n History\n \n\n Rev 1.02, 10/17/95 : Fixed a few typos\n Rev 1.01, 12/04/94 : Added information on netmail and internet mail\n Rev 1.00, 10/12/94 : Released official standard\n\n\n                            - End Documentation -\n"
  },
  {
    "path": "specs/qwk/qwkinfo.txt",
    "content": "\n\n                        QWK mail format information\n\n                 By Mark May - Mythical Kingdom Software\n\n        While writing a QWK utility, I found that there was no\n        one place where all the necessary info on the QWK format\n        was available.  Thru messages in several network echo\n        conferences (Thanks to Tim Farley, Mark Goodwin, Randy\n        Blackmond, Mark Herring, Patrick Lee, Greg Hewgill, and\n        others), I gradually collected the information enclosed\n        in this archive.\n\n        To save others the time collecting this information, I've\n        put together this set of files by editing the information\n        from the various sources so that it is conveniently\n        available.\n\n        Tim Farley is working on a more rigorous specification and\n        I'm sure all of us would appreciate any help you can give\n        him in this.   If you find any errors or additional\n        information, I'd also appreciate hearing about it so that\n        I can further update this set of files.\n\n        I am working on an Object-Oriented set of TurboPascal routines\n        that I hope to release to make working with QWK/REP files\n        easier.\n\n        Note that this packet of information does not document net-status.\n        QWK packets that are marked as having net-status may be imported\n        by one of the NET utils (QNet, RNet, MKNet, etc) into a Bbs.\n        Because normal users of a QWK door should not be able to hack a\n        packet to give it net-status (and import it into their system),\n        that info has been left out of this set of documents.  You may\n        contact me (or one of the other QWK authors) directly for this\n        info.\n\n\n        You may contact me at:\n\n        Fido - 1:110/290\n        RIME - ->MYTHKING\n        Normal Bbs 513-237-7737 (at 9600 HST/V32)\n\n        You may also contact me in the P/Net (programmers network)\n        Bbs/Utils developers conference.\n\n\n        Changes:\n\n        v1.2 01/01/92 Added info on Personal.Ndx\n                      Cleaned up code appearance on BasicReal conversions\n                      Added note about missing net-status info\n\n        v1.1 08/17/91 Added information on Door.Id\n                      Added info on conferences above 255\n                      Added info on message has tagline field\n                      Corrected info on message status values\n\n        v1.0 05/28/91 Initial release\n\u001a"
  },
  {
    "path": "specs/qwk/rep.txt",
    "content": "\n\n\n                 Format of the BBSID.REP file for replies\n\n\n      The record format of the BBSID.MSG file in the BBSID.REP file\n      is exactly identical to the MESSAGES.DAT format except the\n      packet header which now is filled with blanks except that it\n      contains the BBSID as the first few characters.\n\n\n      On the Message Headers there is also one change.  The ascii\n      field which normally contains the message number is now filled\n      (in ascii) with the conference number of the message.  Note\n      that some readers which place the conference number here,\n      neglect to fill in the normal Message Header conference\n      number field.\n"
  },
  {
    "path": "specs/qwk/synchronet_qwk_networking.txt",
    "content": "Synchronet QWK Network Extenstions 03/23/95\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\nThis document is intended for developers of QWK off-line readers or mail doors\nfor non-Synchronet BBS packages.\n\nSynchronet multinode BBS software (by Digital Dynamics) has never had a QWK\ndoor written for it, because it has had extensive internal QWK off-line reader\nand network support since version 1 (1992). Since QWK networking is such an\nintegrated component of Synchronet, it is extremely easy to setup and maintain\nin comparison to other network technologies (Fido, PostLink, Internet, etc.)\nwhich are also internally supported, but not as easy to setup for novice\nsysops.\n\nThrough our (Digital Dynamics) own extensions to the QWKnet pseudo-standard,\nwe have filled many of the gaps that left QWK behind when it came to more\nadvanced network needs (most notably, routed NetMail).\n\nNot all of the information in this document will be relevant to your\ndevelopment, but we would much rather give too much information, than not\nenough. If other BBS program/mail-door authors choose not to implement this\nstandard, it WON'T be because we didn't supply enough information!\n\nOur QWKnet extensions are an evolving entity and we're definitely open\nto suggestions for future enhancements/compatibilty issues. See the end of\nthis document for ways to contact Digital Dynamics. We encourage other\ndevelopers to contact us directly for questions or notification of\ncompatibility or intended compatibility between their product and ours.\n\nBasics\n------\nSynchronet has an entirely separate message area specifically designed for\nlocal E-mail and NetMail (as opposed to public message areas or \"echoes\").\nThis \"e-mail\" message area is always conference number 0 in a QWK or REP\npacket. All non-zero conferences are sub-boards (AKA \"Echoes\", \"SIGs\",\n\"Forums\", etc).\n\nQWK IDs (AKA BBSID) consist of between two and eight valid DOS characters and\nthe first character must be alphabetic. QWK IDs must not contain the '@'\ncharacter. It is extremely beneficial if all QWK IDs are unique in a given\nnetwork of systems. QWK IDs that do not match this format may work for basic\nQWKnet functions, but many features may not work. QWK IDs are always considered\ncase insensitive. The strings \"SYSOP\" and \"NETMAIL\" must are not valid QWK IDs.\n\nA QWKnet node on a Synchronet BBS must be created specifically for QWK\nnetworking. This is done by using the node's QWK ID as the user name on the\nBBS and the sysop must give the account the 'Q' restriction. This restriction\nallows the uploaded REP packets to come from any user name (AKA Net Status)\nand automatically eliminates non-QWK networked sub-boards from the QWK packets.\nThe 'Q' restriction causes the QWK menu to immediately come up at logon\n(rather than the normal \"user\" logon procedure), taglines are added to\nlocally created messages being exported to REP packets, as well as other\nbehavior differences from normal \"user\" accounts. Synchronet creates a\nNETFLAGS.DAT file for 'Q' restricted accounts that haven't disabled CONTROL\nfiles in the QWK packets, though Synchronet itself does not ever use the\nNETFLAGS.DAT - it's created for compatibility with non-Synchronet QWKnet nodes.\n\nConference Numbers\n------------------\nWhen calling a Synchronet BBS for QWK packets, conference numbers will start\nat 0 (for E-mail) and then jump to 1001 or 2001 or a similar number.\nThe thousands place represents the message Group number and the hundreds place\nrepresents the Sub-board number within that group. Conference numbers are\nnot necessarily consequetive, though they are (at this time) always sequential.\nThe CONTROL.DAT file will contain a list of all the conferences (and numbers)\nthe current account has access to. Here is an example CONTROL.DAT:\n\n--------------------------------[ Cut Here ]-----------------------------------\nVertrauen\nFullerton, CA\n714-529-9525\nDigital Man, Sysop\n0000,VERT\n02-28-1995,03:22:02\nTmbbs\n\n0\n0\n88\n0\nE-mail\n1001\nNotices\n1002\nGeneral\n1003\nSoftware\n1004\nHardware\n1005\nProgrmming\n1006\nR.F.I.M.\n1007\nOpinion\n2001\nDOVE-Net\n2002\nAds\n2003\nEntertain\n2004\nDebate\n2005\nComputers\n2006\nProgrammin\n2007\nSynchronet\n2008\nSBBS Sysop\n2009\nDomain Ent\n2010\nSyncData\n3001\nFidoNet\n3002\nMusicians\n3003\nprog rock\n3004\nMonte Pyth\n3005\nGaming\n3006\nFlight-Sim\nHELLO\nBBSNEWS\nGOODBYE\n--------------------------------[ Cut Here ]-----------------------------------\n\nWhen a Synchronet system calls a QWKnet hub, it can use any conference number\nscheme the hub system is using (max conference number 65535), but NetMail is\nalways assumed to be sent and received from conference number 0.\n\nREP Packet Control Messages\n---------------------------\nWhen calling a Synchronet BBS, the following control messages are supported\nwhen included in an uploaded REP packet:\n\nSubj: DROP [conf#]\nNote: Drop current conference (or specified conference #) from future packets\n\nSubj: ADD [ptr | -msgs | mm/dd/yy]\nNote: Add current conference to future packets and optionally set message ptr\n\nSubj: ADD [YOURS] [ptr | -msgs | mm/dd/yy]\nNote: Add current conference to future packets and optionally set message ptr\n      If \"YOURS\" is specified, only mail addressed to you will be packed for\n      this conference. Not applicable for QWKnet node accounts.\n\nSubj: YOURS [ptr | -msgs | mm/dd/yy]\nNote: Same as \"ADD YOURS\"\n\nSubj: RESET [ptr | -msgs | mm/dd/yy]\nNote: Set message pointer for current conference, - indicates offset from last\n\nSubj: RESETALL [ptr | -msgs | mm/dd/yy]\nNote: Set message pointers for all conferences\n\nSubj: FREQ <filename>\nNote: File Request from file transfer database (not attachments)\n\nSubj: FILES [ON | OFF | mm/dd/yy]\nNote: Include files list in packet and/or specify new-scan date\n\nSubj: ATTACH [ON | OFF]\nNote: Include file attachments in packet automatically (e-mail only)\n\nSubj: MAIL [ALL | ON | OFF]\nNote: Include private mail-box (ALL includes previously read mail)\n\nSubj: DELMAIL [ON | OFF]\nNote: Automatically delete mail-box after successful packet download\n\nSubj: CTRL-A [KEEP | EXPAND | STRIP]\nNote: Ctrl-A color/attribute codes - leave-in, expand to ANSI, or remove\n\nSubj: NDX [ON | OFF]\nNote: Include index (.NDX) files (not necessary for Synchronet QWKnet)\n\nSubj: CONTROL [ON | OFF]\nNote: Include control files (DOOR.ID, CONTROL.DAT, NETFLAGS.DAT, etc)\n\nSubj: VIA [ON | OFF]\nNote: Include messge path (@VIA) line in messages\n\nSubj: TZ [ON | OFF]\nNote: Include time zone (@TZ) line in messages\n\nExample DOOR.ID created by Synchronet v2.11:\n\n--------------------------------[ Cut Here ]-----------------------------------\nDOOR = Synchronet\nVERSION = 2.11\nSYSTEM = Synchronet v2.11\nCONTROLNAME = SBBS\nCONTROLTYPE = ADD\nCONTROLTYPE = DROP\nCONTROLTYPE = YOURS\nCONTROLTYPE = RESET\nCONTROLTYPE = RESETALL\nCONTROLTYPE = FILES\nCONTROLTYPE = ATTACH\nCONTROLTYPE = OWN\nCONTROLTYPE = MAIL\nCONTROLTYPE = DELMAIL\nCONTROLTYPE = CTRL-A\nCONTROLTYPE = FREQ\nCONTROLTYPE = NDX\nCONTROLTYPE = TZ\nCONTROLTYPE = VIA\nCONTROLTYPE = CONTROL\nMIXEDCASE = YES\n--------------------------------[ Cut Here ]-----------------------------------\n\nTransferring Files Between Nodes and Hubs\n-----------------------------------------\nAny non-QWK related files included in a QWKnet REP packet uploaded to a\nSynchronet BBS (or QWK packets received from a QWKnet hub) will be\nautomatically moved into the DATA\\QNET\\<QWKID.IN> directory (where QWKID is the\nQWK ID of the node or hub that sent the file) and the sysop will be notified of\nthe received file.\n\nIf a Synchronet sysop wishes to send a QWKnet node or hub a file, he need only\ncreate the directory DATA\\QNET\\<QWKID.OUT> (where QWKID is the QWK ID of the\ndestination node) and copy the file(s) into this directory. The next time this\nnode calls and downloads a REP packet (or a QWK is packed for the hub), this\nfile will be archived in the packet automatically and then deleted from the\n.OUT directory. This is NOT the same as FREQing (File Requesting) a file. It is\njust a simple means of transferring files between QWKnet nodes and hubs.\n\nNetMail\n-------\nWhen downloading a QWKnet packet from a Synchronet BBS, any e-mail (conf #0)\nwaiting for the QWKnet node account will be automatically included in the\npacket. If the TO: name is the node's QWK ID or the word \"SYSOP\" (not case\nsensitive), the NetMail should be assumed to be intended for the Sysop.\nOtherwise if the TO: name is not \"NETMAIL\" (not case sensitive), then it is a\nsingle hop NetMail message intended for a user on the node's system going by\nthe TO: name. The same holds true for REP packets sent to hubs containing\nmessages in conf #0.\n\nRouted NetMail\n--------------\nMessages sent to \"NETMAIL\" (not case sensitve) in conference number 0 are\nintended for another system that the current system unpacking the packet\nmust forward the message to. The destination user name and address will be\non the VERY first line of the message text in the following format:\n\"name@addr\"\nWhere \"name\" is the full user name (25 chars max) and \"addr\" is EITHER the\ndestination node's QWK ID or the complete routing address. Complete routing\naddresses are stored as: \"NEXTID/.../DESTID\", where NEXTID is the QWK ID of\nnext system in the link and DESTID is the inteded destination's QWK ID. The\n\"...\" portion of the above routed address designates a variable number of\nQWK IDs to pass through before reaching the DESTID.\n\nSynchronet, automatically expands QWK ID's to complete routing addresses\nwhenever possible (when the path is known), so expect to find the complete\nrouting address more often than just the destination QWK ID.\n\nWhen a system discovers a routed NetMail message in a QWK or REP packet it\nneeds to determine if the next hop is the destination node, and if so, change\nthe TO: field to the destination user name and eliminate the \"user@addr\"\nline from the message.\n\nIf the next hop is not the destination node, it needs to leave the TO: field\nas \"NETMAIL\" and remove itself and the next hop from the \"addr\" portion of\nthe \"user@addr\" line before creating the QWK or REP packet for the next hop.\nAfter exporting the NetMail message sucessfully to QWK or REP, it should be\ndeleted.\n\nEchoMail\n--------\nSo, you're probably asking yourself, how does Synchronet know how to expand\na QWK ID into a complete routing address? Well, the @VIA: line is the key.\nEvery mail message (EchoMail and NetMail) that has passed through at least one\nsystem to reach the current system will contain a special first line in the\nbody text:\n\"@VIA: QWKID/.../ORGID\"\nWhere QWKID is the ID of the system that sent the message to the system that\ncreated the QWK or REP packet being unpacked and ORGID is the originating\nsystem's QWK ID.\n\nMail that originates on a node or hub will not contain an @VIA: line when\nexported to nodes or hub that are directly connected to it. Only when THOSE\nsystems then export the message again, is the @VIA: line added.\n\nSynchronet parses the @VIA: line (if it exists) to automatically maintain\na dynamic \"route map\" (filename DATA\\QNET\\ROUTE.DAT). Each line contains\ninformation about a QWKnet system that is not directly connected. The format\n(though not necessarily relevant to other BBS packages) is:\n\"MM/DD/YY DESTID:QWKID/QWKID/QWKID/...\"\nWhere MM/DD/YY is the date the entry was last updated in the route file, DESTID\nis the QWK ID of the system which we are defining the routing, and QWKID/QWKID\netc. are the QWK IDs of the systems necessary to reach DESTID.\n\nSynchronet updates entries for existing DESTID, so if the routing changes,\nthe route file changes automatically. Old entries (indicating no mail traffic\nfrom DESTID in X number of days) are automatically deleted. Synchronet uses 90\ndays as maximum age to keep old route entries.\n\nSynchronet comes with a utility (QWKNODES.EXE) that can be used to manually\nscan the existing message bases and create a ROUTE.DAT file (mentioned above),\na USERS.DAT file (for automatically looking up user names on other systems),\nand a NODES.DAT file (not currently used by Synchronet, mainly for human\nconsumption - finding a QWKnode near you!). The format of the USERS.DAT file\nis each line:\n\"username                   DESTID    MM/DD/YY  (QWKID/.../DESTID)\"\nWhere username is the user's full name, DESTID is the QWK ID of the system\nthe user is on (or last posted from), MM/DD/YY is the date the message was\nimported, and QWKID/.../ is the path to the DESTID (if not direct connection).\nThe only parts Synchronet uses at this time are username and DESTID (ROUTE.DAT\nis used to expand to complete routing address if necessary).\n\nWhen importing mail with an @VIA: line, Synchronet also checks to make\nsure that the current system's QWK ID is not present in the list of QWK IDs.\nIf it is present, then the message is assumed to be an erroneous dupe loop and\nis ignored (not imported). This is called \"circular path detection\" and is\ncaused by systems that accidentally hub off of more than one system in the\nsame QWK network causing a message \"loop\".\n\n@VIA: lines can be disabled on a Synchronet hub by sending a message to \"SBBS\"\nwith a title of \"VIA OFF\".\n\nSynchronet automatically disables @VIA: lines for hubs when \"Ctrl-A Codes\" are\nnot set to \"Leave-in\" (this is done by the Synchronet sysop in SCFG), assuming\nthis indicates the hub BBS is not a Synchronet system. So, if you're receiving\n@VIA: codes from a Synchronet BBS that is a node (not a hub) off of your\nsystem, expect to receive Synchronet Ctrl-A codes too! :) Synchronet Ctrl-A\ncodes are ANSI equivalents (using a more simple escape sequence) defined as:\n\n(All attribute codes are be preceeded by a Ctrl-A character - ASCII 1)\n\n\tForeground  Background\nBlack\t    K\t\t0\nRed\t    R\t\t1\nGreen\t    G\t\t2\nYellow\t    Y\t\t3\nBlue\t    B\t\t4\nMagenta     M\t\t 5\nCyan\t    C\t\t6\nWhite\t    W\t\t7\n\nHigh\t    H\tHigh Intensity\nBlink\t    I\tBlinking\nNormal      N   No Special Attributes\nPause       P   Insert a Pause Prompt into message\nCLS         L   Insert a Form Feed into message\n\n\nTime Zone\n---------\nAnother missing element of the QWK format is time zone information. Synchronet\noffers time zone information in QWK messages by adding an @TZ: line before the\nmessage body (below \"name@addr\" and \"@VIA:\" lines if they exist). The time\nzone specified is of the originating system. The format is:\n\"@TZ: xxxx\"\nWhere xxxx are four hex digits (16-bit signed value). The value of the hex\ndigits is defined in the SMB (Synchronet Message Base) specification, but for\nyour convenience, we have included it here:\n\n\tIf the zone is in the range -720 to +720, it represents the\n\tnumber of minutes east or west of UT. Values in this range\n\tshould only be used for time zones not otherwise represented\n\there.\n\n\tIf the zone is greater than 720 or less than -720, then the\n\tfollowing bits have special meaning:\n\n\t(1<<12) \t// Non-US time zone\t(east of UT)\n\t(1<<13) \t// Non-US time zone\t(west of UT)\n\t(1<<14) \t// U.S. time zone\n\t(1<<15) \t// Daylight savings\n\n\tThe lower 12 bits (0 through 11) contain the number of minutes\n\teast or west of UT (not accounting for daylight savings).\n\n\tIf the time zone is one specified in the U.S. Uniform Time Act,\n\tthe following values represent the zone:\n\n\tAST 0x40F0\t// Atlantic\t\t(-04:00)\n\tEST 0x412C\t// Eastern\t\t(-05:00)\n\tCST 0x4168\t// Central\t\t(-06:00)\n\tMST 0x41A4\t// Mountain\t\t(-07:00)\n\tPST 0x41E0\t// Pacific\t\t(-08:00)\n\tYST 0x421C\t// Yukon\t\t(-09:00)\n\tHST 0x4258\t// Hawaii/Alaska\t(-10:00)\n\tBST 0x4294\t// Bering\t\t(-11:00)\n\n\tWith bit 15 set, the following values represent the same zone\n\twith the presence of daylight savings:\n\n\tADT 0xC0F0\t// Atlantic\t\t(-03:00)\n\tEDT 0xC12C\t// Eastern\t\t(-04:00)\n\tCDT 0xC168\t// Central\t\t(-05:00)\n\tMDT 0xC1A4\t// Mountain\t\t(-06:00)\n\tPDT 0xC1E0\t// Pacific\t\t(-07:00)\n\tYDT 0xC21C\t// Yukon\t\t(-08:00)\n\tHDT 0xC258\t// Hawaii/Alaska\t(-09:00)\n\tBDT 0xC294\t// Bering\t\t(-10:00)\n\n\tThe following non-standard time zone specifications may also be\n\tused:\n\n\tMID 0x2294\t// Midway\t\t(-11:00)\n\tVAN 0x21E0\t// Vancouver\t\t(-08:00)\n\tEDM 0x21A4\t// Edmonton\t\t(-07:00)\n\tWIN 0x2168\t// Winnipeg\t\t(-06:00)\n\tBOG 0x212C\t// Bogota\t\t(-05:00)\n\tCAR 0x20F0\t// Caracas\t\t(-04:00)\n\tRIO 0x20B4\t// Rio de Janeiro\t(-03:00)\n\tFER 0x2078\t// Fernando de Noronha\t(-02:00)\n\tAZO 0x203C\t// Azores\t\t(-01:00)\n\tLON 0x1000\t// London\t\t(+00:00)\n\tBER 0x103C\t// Berlin\t\t(+01:00)\n\tATH 0x1078\t// Athens\t\t(+02:00)\n\tMOS 0x10B4\t// Moscow\t\t(+03:00)\n\tDUB 0x10F0\t// Dubai\t\t(+04:00)\n\tKAB 0x110E\t// Kabul\t\t(+04:30)\n\tKAR 0x112C\t// Karachi\t\t(+05:00)\n\tBOM 0x114A\t// Bombay\t\t(+05:30)\n\tKAT 0x1159\t// Kathmandu\t\t(+05:45)\n\tDHA 0x1168\t// Dhaka\t\t(+06:00)\n\tBAN 0x11A4\t// Bangkok\t\t(+07:00)\n\tHON 0x11E0\t// Hong Kong\t\t(+08:00)\n\tTOK 0x121C\t// Tokyo\t\t(+09:00)\n\tSYD 0x1258\t// Sydney\t\t(+10:00)\n\tNOU 0x1294\t// Noumea\t\t(+11:00)\n\tWEL 0x12D0\t// Wellington\t\t(+12:00)\n\nExamples\n--------\nExamples are usually helpful at understanding concepts, so we are going to\nuse a real-life Synchronet extended QWK network (DOVE-Net) to deomonstrate\nhow the above extensions work.\n\nFirst, the network topology (abbreviated for this example):\n\n\t   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄVERTÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n\t   ³\t\t    ³\t       ³\t\t\t³\n  ÚÄÄÄÄÄÄPHOUSEÄÄÄÄÄ¿\t  DOMAIN    NITEMOVE\t       ÚÄÄÄÄÄÄCENTURYÄÄÄÄÄÄ¿\n  ³\t   ³\t    ³\t\t       ³\t       ³\t³\t   ³\nCIRCLE7  FANTAIR  KRYSTAL      ÚÄÄÄÄÄÄTLOCÄÄÄÄÄÄ¿    TALONBBS  VSS_BBS\tPHOENIX\n\t\t\t       ³\t\t³\n\t\t\t     BLAZING\t   WILDHARE\n\n\nThe ROUTE.DAT on VERT (main hub) for the above (in case you were curious):\n\n--------------------------------[ Cut Here ]-----------------------------------\n03/22/95 CIRCLE7:PHOUSE\n03/22/95 TLOC:NITEMOVE\n03/22/95 FANTAIR:PHOUSE\n03/20/95 TALONBBS:CENTURY\n03/17/95 BLAZING:NITEMOVE/TLOC\n03/19/95 KRYSTAL:PHOUSE\n03/19/95 VSS_BBS:CENTURY\n03/20/95 PHOENIX:CENTURY\n03/20/95 WILDHARE:NITEMOVE/TLOC\n--------------------------------[ Cut Here ]-----------------------------------\n\nMail originating on VERT would NOT contain an @VIA: line when sent to the\nfollowing systems: PHOUSE, DOMAIN, NITEMOVE, and CENTURY. Mail originating on\nVERT would contain \"@VIA: VERT\" when sent to the systems: CIRCLE7, FANTAIR,\nKRYSTAL, TLOC, TALONBBS, VSS_BBS, and PHOENIX. Mail originating on VERT would\ncontain \"@VIA: NITEMOVE/VERT\" went sent to the following systems: BLAZING and\nWILDHARE.\n\nMail originating on BLAZING would contain the following @VIA: lines when sent\nto the following systems:\n\nTLOC:\t   <none>\nWILDHARE:  \"@VIA: BLAZING\"\nNITEMOVE:  \"@VIA: BLAZING\"\nVERT:\t   \"@VIA: TLOC/BLAZING\"\nDOMAIN:    \"@VIA: NITEMOVE/TLOC/BLAZING\"\nPHOUSE:    \"@VIA: NITEMOVE/TLOC/BLAZING\"\nCIRCLE7:   \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\nFANTAIR:   \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\nKRYSTAL:   \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\nCENTURY:   \"@VIA: NITEMOVE/TLOC/BLAZING\"\nTALONBBS:  \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\nVSS_BBS:   \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\nPHOENIX:   \"@VIA: VERT/NITEMOVE/TLOC/BLAZING\"\n\nEach of the above systems needs to have its own way of storing the QWK ID of\nthe system the message last came from, so it can build the entire return\naddress. Luckily, all of the above are Synchronet systems, which stores the\ncomplete route address in the SMB format message header. Different BBS packages\nwill need different ways of storing the originating QWK ID or (preferrably)\nthe complete route address (built from the above VIA path with the last hop\nQWK prepended to the address).\n\nUsing the above example, VERT would store the QWKnet address of mail\noriginating from WILDHARE as \"NITEMOVE/TLOC/WILDHARE\". Synchronet does not\nactually store addresses in its local message bases using @VIA:. This is\nonly used for extended the QWK format (which doesn't have a storage area for\nnetwork addresses). The @VIA: portion of the message body is added and removed\nautomatically from each message imported from or exported to QWK format (if\napplicable).\n\nUsing a Route Map\n-----------------\nIf the BBS software or mail door uses a route map, (similar to the ROUTE.DAT\nthat Synchronet uses), it should be able to insert routing information on\nthe fly.\n\nIf for example, a user on VERT sent NetMail to a user on WILDHARE, Synchronet\nwould look in the ROUTE.DAT and find an entry for WILDHARE and automatically\nexpand the address from \"user@WILDHARE\" to \"user@NITEMOVE/TLOC/WILDHARE\".\nIf a user on VERT were to send NetMail to \"user@WILDHARE/BIGBBS\", Synchronet\nwould not even look for BIGBBS in the ROUTE.DAT (it only looks for the first\nhop in the routing), so it would still route the message properly to WILDHARE\nby changing the address to NITEMOVE/TLOC/WILDHARE/BIGBBS.\n\nEach system that receives NetMail should compare the destination QWK ID to\nall the QWKnet nodes it feeds and the hubs it calls. If a match is found, it\nshould ignore the routing information and send it directly (overriding the\nspecified routing). Example, a user on TALONBBS sends NetMail to\n\"user@CENTURY/VERT/PHOUSE/NITEMOVE\" (an incorrect route, but valid as far as\nCENTURY knows) - it is possible that PHOUSE now feeds NITEMOVE and CENTURY does\nnot yet know about it, so it leaves the route address intact and passes the\nmessage on to VERT. VERT sees that it feeds NITEMOVE directly, so it sends the\nmail directly (removing the routing information).\n\nNetMail (again)\n---------------\nUsing the above example network topology, if a user were to send NetMail\nfrom BLAZING to a user on CIRCLE7:\n\nREP sent from BLAZING to TLOC:\nConf #0 - To: NETMAIL\n\t  1stLine: username@NITEMOVE/VERT/PHOUSE/CIRCLE7\n\nREP sent from TLOC to NITEMOVE:\nConf #0 - To: NETMAIL\n\t  1stLine: username@VERT/PHOUSE/CIRCLE7\n\t  2ndLine: @VIA: BLAZING\n\nREP sent from NITEMOVE to VERT:\nConf #0 - To: NETMAIL\n\t  1stLine: username@PHOUSE/CIRCLE7\n\t  2ndLine: @VIA: TLOC/BLAZING\n\nQWK sent from VERT to PHOUSE:\nConf #0 - To: NETMAIL\n\t  1stLine: username@CIRCLE7\n\t  2ndLine: @VIA: NITEMOVE/TLOC/BLAZING\n\nQWK sent from PHOUSE to CIRCLE7:\nConf #0 - To: username\n\t  1stLine: @VIA: VERT/NITEMOVE/TLOC/BLAZING\n\n\nContact Information\n-------------------\nDigital Dynamics\nPO Box 501\nYorba Linda, CA 92686\n714-529-6328 Voice\n714-529-9271 FAX\n714-529-9525 BBS 14.4k V.32bis\n714-529-9547 BBS 28.8k V.FC\n714-529-9721 BBS 19.2k ZyXEL (reserved for networking)\nFidoNet:  1:103/705 V.32bis\n\t  1:103/706 V.FC\nRelayNet: 5115\nInternet: sysop@f705.n103.z1.fidonet.org\nDOVE-Net: sysop@vert\n\n/* End of SYNCQNET.DOC */"
  },
  {
    "path": "todo.md",
    "content": "# WWIV BBS TODO List\n# Copyright 2002-2021, WWIV Software Services\n***\n\n# TODO debugger\n\n\n# TODO Cleanups\n* make a SideMenu class so we don't need statics in side_menu method.\n* redo readmail(...) It's a friggin mess.\n* make nightly event or fix check for mail forwarded to a deleted user, and then fix that.\n\n\n# Things to add to fix.\n\n* Check for no conferences\n* Check for subs or dirs not part of any conference\n* sub storage type != 2\n\n# CONFIG.JSON\n\n* make sure wwivconfig can edit wwivd and networks for legacy 4.24 and 4.30 format\n* Save off config.dat when saving config.json from wwivconfig if it already exists.\n\n# WWIVconfig\n\n# MCI|PIPE\n* Add tests for BbsMacroFilter (also make sure it works now)\n* Use BbsMacroFilter in wwivutil print.\n\nTODO Expression:\n|{uppercase user.name)}\n\n# Install\ncurl https://build.wwivbbs.org/jenkins/job/wwiv/lastStableBuild/label=linux-debian10/api/json\n?pretty=true > jenkins.json\njq \".url+.artifacts[].relativePath\" jenkins.json\njq \".number\" jenkins.json\n\n## Networking Cleanup\n***\n* Figure out why new networking stack doesn't work for mark. \n* Use fixup_user_entered_email in email address fixing up.\n  also create one to fixup ftn address (add @32765)\n  and use this consistently (i.e. in '1' from msgscan)\n\n## FTN\n***\n* add option to save packets\n* ability to put more than 1 message per packet.\n* zone:region/node is acceptible (not just zone:net/node)\n* Add ability to convert between a FidoPackedMessage and FidoStoredMessage.\n  Then we can move dupes to a badmessage area as FidoStoredMessage (.msg)\n* Update BBS list for network to use FTN nodelist.\n* Doesn't seem that wwivd checks for crash status on callout since\n  wwiv::sdk::callout never has the right file sizes for FTN, so it doesn't\n  know if anything is waiting.\n\n\n## Container work\n***\n* Add WWIV_CONFIG_DIR to point to where the config.json file lives\n  (default to config.dat's data)\n* Create default directory structure for in containers\n* move all binaries to bin, see what breaks\n\n\n## Infrastructure Cleanup\n***\n* Make sure the Network.network_number is accurate, then try\n  to get rid of the other network_numbers everywhere.\n* Try to remove a()->current_net() and a()->net_num(), pass in the net \n  as much as possible.\n* cleanup wfc since we aren't waiting for a call\n* add tests for usermanager and user (in SDK)\n* stop using strncpy, strcpy.\n* Create a SDK QScan class to wrap interacting with the WWIV qscan\n  variables and also load/save user.qsc\n* Move to LibSSH on all platforms\n* Run various asan/tsan's regularly with gcc via CMake\n* start using clock more.\n* move to datetime as much as possible.\n* Stop calling input use the input_xxx routines instead.  Make Input1 \n  just support a fixed set of characters (like numbers, A-Z, \n  high ascii too, etc).\n* cleanup context class (doc comments, treat type-0 as email api\n* Move the userrec from User class to heap from stack.\n* add to_number<T> override that takes a default value, and then \n  change to_number<T>\n  to return an std::optional<T> as the return type.\n* Switch all BBS LocalIO subclasses to use curses KEY types not Win32 key code\n  types for characters >0xff. (i.e. KEY_LEFT not LEFT)\n* Finish making bbs only use UserManager that returns optional\n\n\n## core::File Improvements\n***\n* File::lock doesn't seem to be finished\n\n\n## Linux Work\n***\n* TopScreen doesn't work with CursesIO\n\n## Message Areas\n***\n* detangle global net_email_name (maybe it needs to be added to EmailData?)\n* Make the emailmessage extend the message so most things are common\n  between them.\n* Use read_type2_message everywhere\n* make read_type2_message use the msgapi\n* use the msgapi more in WWIV code.\n\n# File Areas\n***\n* cleanup char[] usage\n* support moving file in sdk. (Maybe FileApi::MoveFile(old_area, new_area))\n* Move more batch code into batch class.\n* move FileList into context (for tagged files)\n* get rid of stripfn\n* move core logic from get_file_idz into sdk\n* make wwivutil fix use filesapi for extended descriptions.\n* Add overload of AddFile, UpdateFile and handles external \n  descirptions too, i.e. add a 3rd parameter for the external\n  description.  Or put it into the FileRecord\n  class.\n\n## Closed Questions\n***\n\n1) Guest user account. Is it useful?   - Yes, it just needs to be improved\n   and documented.\n"
  },
  {
    "path": "vcpkg.json",
    "content": "{\n    \"name\": \"wwiv\",\n    \"version-string\": \"5.8.0\",\n  \"dependencies\": [\n    \"cereal\",\n    \"fmt\",\n    \"cpp-httplib\",\n    \"nlohmann-json\",\n    \"gtest\"\n  ]\n  }"
  },
  {
    "path": "wwivconfig/CMakeLists.txt",
    "content": "# CMake for WWIV 5\nInclude(FindWWIVCurses)\n\nset(COMMON_SOURCES\n  \"archivers.cpp\"\n  \"autoval.cpp\"\n  \"colors.cpp\"\n  \"convert.cpp\"\n  \"editors.cpp\"\n  \"levels.cpp\"\n  \"menus.cpp\"\n  \"networks.cpp\"\n  \"new_user.cpp\"\n  \"newinit.cpp\"\n  \"paths.cpp\"\n  \"protocols.cpp\"\n  \"script_ui.cpp\"\n  \"subacc.cpp\"\n  \"subsdirs.cpp\"\n  \"system_info.cpp\"\n  \"sysop_account.cpp\"\n  \"toggles.cpp\"\n  \"user_editor.cpp\"\n  \"utility.cpp\"\n  \"wwivd_ui.cpp\"\n  )\n\nadd_library(wwivconfig_lib ${COMMON_SOURCES})\ntarget_link_libraries(wwivconfig_lib localui common core sdk ${CURSES_LIBRARIES})\n\nif (WWIV_BUILD_TESTS)\n\n  set(wwivconfig_test_sources\n    convert_test.cpp\n    wwivconfig_test_main.cpp\n  )\n\n  add_executable(wwivconfig_tests ${wwivconfig_test_sources})\n  set_max_warnings(wwivconfig_tests)\n  target_link_libraries(wwivconfig_tests \n      ${CURSES_LIBRARIES} \n      core \n      core_fixtures\n      GTest::gtest \n      localui common \n      sdk \n      sdk_fixtures\n      wwivconfig_lib \n  )\n\n  gtest_discover_tests(wwivconfig_tests)\n\nendif()\n\nadd_executable(wwivconfig \"wwivconfig.cpp\")\nset_max_warnings(wwivconfig)\ntarget_link_libraries(wwivconfig wwivconfig_lib localui common core sdk ${CURSES_LIBRARIES})\n"
  },
  {
    "path": "wwivconfig/archivers.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/archivers.h\"\r\n\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"local_io/wconstants.h\" // for MAX_ARCHIVERS\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/vardec.h\"\r\n#include <filesystem>\r\n#include <vector>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::strings;\r\n\r\nstatic void edit_arc(int arc_number, arcrec* a) {\r\n  auto y = 1;\r\n  EditItems items{};\r\n\r\n  items.add(new Label(\"Archiver Name:\"), new StringEditItem<char*>(31, a->name, EditLineMode::ALL),\r\n            \"Recognizable name you can assign to the archive type\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Archiver Extension:\"),\r\n            new StringEditItem<char*>(3, a->extension, EditLineMode::UPPER_ONLY), \r\n    \"The three letter file extension used by this archive type\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"List Archive:\"), new CommandLineItem(49, a->arcl),\r\n    \"Command to list the contents of the archive without extracting the files\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Extract Archive:\"), new CommandLineItem(49, a->arce),\r\n    \"Command to extract the files to the node's temp directory\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Add to Archive:\"), new CommandLineItem(49, a->arca), \r\n    \"Command to add a file to the archive.\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Delete from Archive:\"), new CommandLineItem(49, a->arcd),\r\n    \"Command to delete a file from the archive\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Comment Archive:\"), new CommandLineItem(49, a->arck), \r\n    \"Command to add a comment to the archive. %K means gfiles/comment.txt\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Test Archive:\"), new CommandLineItem(49, a->arct), \r\n    \"Command to test the archive for validity and integrity\", 1, y);\r\n\r\n  y+=2;\r\n  items.add(new MultilineLabel(R\"\"\"\"(%1 %2 etc. are parameters passed.  Minimum of two on Add and\r\nExtract command lines. For added security, a complete path to\r\nthe archiver and extension should be used. i.e.:\r\nc:\\bin\\arcs\\zip.exe -a %1 %2)\"\"\"\" ), 1, y);\r\n\r\n  items.relayout_items_and_labels();\r\n  items.Run(fmt::format(\"Archiver #{}  {}\", arc_number, ((arc_number == 1) ? \"(Default)\" : \"\")));\r\n}\r\n\r\nbool create_arcs(UIWindow* window, const std::filesystem::path& datadir) {\r\n  std::vector<arcrec> arc;\r\n  arc.emplace_back(arcrec{\"Zip\", \"ZIP\", \"zip -j %1 %2\", \"unzip -o -j -C %1 %2\", \"@internal\",\r\n                          \"zip -d %1 -@ < BBSADS.TXT\", \"zip -z %1 < COMMENT.TXT\", \"unzip -t %1\"});\r\n  arc.emplace_back(arcrec{\"Arj\", \"ARJ\", \"arj.exe a %1 %2\", \"arj.exe e %1 %2\", \"@internal\",\r\n                          \"arj.exe d %1 !BBSADS.TXT\", \"arj.exe c %1 -zCOMMENT.TXT\",\r\n                          \"arj.exe t %1\"});\r\n  arc.emplace_back(arcrec{\"Rar\", \"RAR\", \"rar.exe a -std -s- %1 %2\", \"rar.exe e -std -o+ %1 %2\",\r\n                          \"rar.exe l -std %1\", \"rar.exe d -std %1 < BBSADS.TXT \",\r\n                          \"rar.exe zCOMMENT.TXT -std %1\", \"rar.exe t -std %1\"});\r\n  arc.emplace_back(arcrec{\"Lzh\", \"LZH\", \"lha.exe a %1 %2\", \"lha.exe eo  %1 %2\", \"@internal\",\r\n                          \"lha.exe d %1  < BBSADS.TXT\", \"\", \"lha.exe t %1\"});\r\n  arc.emplace_back(arcrec{\"Pak\", \"PAK\", \"pkpak.exe -a %1 %2\", \"pkunpak.exe -e  %1 %2\",\r\n                          \"@internal\", \"pkpak.exe -d %1  @BBSADS.TXT\",\r\n                          \"pkpak.exe -c %1 < COMMENT.TXT \", \"pkunpak.exe -t %1\"});\r\n  arc.emplace_back(arcrec{\"Arc\", \"ARC\", \"pkpak.exe -a %1 %2\", \"pkunpak.exe -e  %1 %2\",\r\n                          \"@internal\", \"pkpak.exe -d %1  @BBSADS.TXT\",\r\n                          \"pkpak.exe -c %1 < COMMENT.TXT \", \"pkunpak.exe -t %1\"});\r\n\r\n  for (int i = wwiv::stl::size_int(arc); i < MAX_ARCS; i++) {\r\n    arc.emplace_back(arcrec{\"New Archiver Name\", \"EXT\", \"archive add command\",\r\n                            \"archive extract command\", \"archive list command\",\r\n                            \"archive delete command\", \"archive comment command\",\r\n                            \"archive test command\"});\r\n  }\r\n\r\n  File file(FilePath(datadir, ARCHIVER_DAT));\r\n  if (!file.Open(File::modeWriteOnly | File::modeBinary | File::modeCreateFile)) {\r\n    messagebox(window,\r\n               fmt::format(\"Couldn't open '{}' for writing.\\n\", file.full_pathname()));\r\n    return false;\r\n  }\r\n  file.Write(&arc[0], MAX_ARCS * sizeof(arcrec));\r\n  return true;\r\n}\r\n\r\nbool edit_archivers(wwiv::sdk::Config& config) {\r\n  arcrec arc[MAX_ARCS];\r\n\r\n  File file(FilePath(config.datadir(), ARCHIVER_DAT));\r\n  if (!file.Open(File::modeReadWrite | File::modeBinary)) {\r\n    if (!create_arcs(curses_out->window(), config.datadir())) {\r\n      return false;\r\n    }\r\n    file.Open(File::modeReadWrite | File::modeBinary);\r\n  }\r\n  file.Read(&arc, MAX_ARCS * sizeof(arcrec));\r\n\r\n  auto done = false;\r\n  do {\r\n    curses_out->Cls(ACS_CKBOARD);\r\n    std::vector<ListBoxItem> items;\r\n    for (auto& i : arc) {\r\n      items.emplace_back(fmt::format(\"[{}] {}\", i.extension, i.name));\r\n    }\r\n    ListBox list(curses_out->window(), \"Select Archiver\", items);\r\n\r\n    list.selection_returns_hotkey(true);\r\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}});\r\n    if (const auto result = list.Run(); result.type == ListBoxResultType::HOTKEY) {\r\n    } else if (result.type == ListBoxResultType::SELECTION) {\r\n      edit_arc(result.selected + 1, &arc[result.selected]);\r\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n      done = true;\r\n    }\r\n  } while (!done);\r\n\r\n  // seek to beginning of file, write arcrec, close file\r\n  file.Seek(0, File::Whence::begin);\r\n  file.Write(arc, MAX_ARCS * sizeof(arcrec));\r\n  return true;\r\n}\r\n"
  },
  {
    "path": "wwivconfig/archivers.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_ARCHIVERS_H\r\n#define INCLUDED_WWIVCONFIG_ARCHIVERS_H\r\n\r\n#include \"sdk/config.h\"\r\n#include <filesystem>\r\n\r\nnamespace wwiv::local::ui {\r\nclass UIWindow;\r\n}\r\n\r\nbool edit_archivers(wwiv::sdk::Config&);\r\nbool create_arcs(wwiv::local::ui::UIWindow* window, const std::filesystem::path& datadir);\r\n\r\n#endif\r\n"
  },
  {
    "path": "wwivconfig/autoval.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"localui/wwiv_curses.h\"\n\n#include \"core/strings.h\"\n#include \"core/wwivport.h\"\n#include \"fmt/format.h\"\n#include \"fmt/printf.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n#include \"localui/listbox.h\"\n#include \"sdk/vardec.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic std::string create_autoval_line(Config& config, int n) {\n  char ar[20], dar[20], r[20];\n  const auto v = config.auto_val(n);\n  std::string res_str = restrict_string;\n  for (int8_t i = 0; i <= 15; i++) {\n    if (v.ar & (1 << i)) {\n      ar[i] = static_cast<char>('A' + i);\n    } else {\n      ar[i] = 32;\n    }\n    if (v.dar & (1 << i)) {\n      dar[i] = static_cast<char>('A' + i);\n    } else {\n      dar[i] = 32;\n    }\n    if (v.restrict & (1 << i)) {\n      r[i] = res_str[i];\n    } else {\n      r[i] = 32;\n    }\n  }\n  r[16] = 0;\n  ar[16] = 0;\n  dar[16] = 0;\n  const auto key = fmt::format(\"ALT-F{}\", n);\n  return fmt::sprintf(\"%-7s  %3d  %3d  %16s  %16s  %20s\", key, v.sl, v.dsl, ar, dar, r);\n}\n\nstatic void edit_autoval(Config& config, int n) {\n  auto v = config.auto_val(n);\n  EditItems items{};\n  auto y = 1;\n  items.add(new Label(\"Name:\"), new StringEditItem<std::string&>(30, v.name, EditLineMode::ALL),\n            \"Security Level (SL) to grant when using this auto-validation key.\", 1, y);\n  ++y;\n  items.add(new Label(\"SL:\"), new NumberEditItem<uint8_t>(&v.sl),\n            \"Security Level (SL) to grant when using this auto-validation key.\", 1, y);\n  ++y;\n  items.add(new Label(\"DSL:\"), new NumberEditItem<uint8_t>(&v.dsl),\n            \"Download Security Level (DSL) to grant when using this auto-validation key\", 1, y);\n  ++y;\n  items.add(new Label(\"AR:\"), new ArEditItem(&v.ar),\n            \"Access Retriction (AR) to grant when using this auto-validation key.\", 1, y);\n  ++y;\n  items.add(new Label(\"DAR:\"), new ArEditItem(&v.dar),\n            \"Download Access (SL) to grant when using this auto-validation key.\", 1, y);\n  ++y;\n  items.add(new Label(\"Restrictions:\"), new RestrictionsEditItem(&v.restrict),\n            \"System Restrictions to grant when using this auto-validation key.\", 1, y);\n\n  items.relayout_items_and_labels();\n  items.Run(fmt::format(\"Auto-validation data for: Alt-F{}\", n));\n  config.auto_val(n, v);\n}\n\nvoid autoval_levs(Config& config) {\n  auto done = false;\n  do {\n    curses_out->Cls(ACS_CKBOARD);\n    std::vector<ListBoxItem> items;\n    for (auto i = 1; i <= 10; i++) {\n      items.emplace_back(create_autoval_line(config, i));\n    }\n    ListBox list(curses_out->window(), \"Select AutoVal\", items);\n\n    list.selection_returns_hotkey(true);\n    list.set_additional_hotkeys(\"DI\");\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}});\n    const auto result = list.Run();\n\n    if (result.type == ListBoxResultType::HOTKEY) {\n    } else if (result.type == ListBoxResultType::SELECTION) {\n      edit_autoval(config, result.selected + 1);\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\n      done = true;\n    }\n  } while (!done);\n  config.Save();\n}\n"
  },
  {
    "path": "wwivconfig/autoval.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_AUTOVAL_H\n#define INCLUDED_WWIVCONFIG_AUTOVAL_H\n\n#include \"sdk/config.h\"\n\nvoid autoval_levs(wwiv::sdk::Config& config);\n\n#endif"
  },
  {
    "path": "wwivconfig/changelog",
    "content": "\tInit Change Log\r\n\t~~~~~~~~~~~~~~~\r\n\r\n \r\n01-Jan-2001 Rushfan\r\n\tRenamed C files to cpp files, made new directory structure for \r\n\tinit 5.0.\r\n\r\n04-Jan-2001 Rushfan\r\n\tFirst completed working WIN32 port of INIT 5.0\r\n\t\r\n12-7-2003 Rushfan \r\n\tFixed modems list not scrolling\r\n\t\r\n12-7-2003 Rushfan \r\n\tControl-A and Control-E now move to the beginning and end of the editfield.\r\n\tFixed GPF's on a 1st run of init 5.0\r\n\r\n12-9-2003 Rushfan \r\n\tremoved corruption issues\r\n\tchange exit(-1) to exit(2)\r\n\t\r\n12-10-2003 Rushfan \r\n\tRemoved global datadirok, made read_status return a bool\r\n\t\r\n19-Feb-2004 Rushfan\r\n\tDisabled registration information, you can now use any number of instances you want.\r\n\tRemoved LLC from WWIV Software Services.\r\n\r\n02-Mar-2014 WSS\r\n    Updated headers to reflect licensing change.\r\n    Removed all references to registration requirement and set max_inst to 999.\r\n    \r\n03-Mar-2014 Rushfan\r\n    Fixed up code to compile with VS2013 and current WWIV sources. \r\n\r\n06-Mar-2014 Rushfan\r\n    Fixed project references to be relative to $(ProjectDir)\r\n\t\r\n"
  },
  {
    "path": "wwivconfig/colors.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/colors.h\"\n\n#include \"core/strings.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n#include \"sdk/config.h\"\n\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid colors(Config&, color_config_t& c, CursesWindow* ) {\n\n  // Set defaults if needed\n  if (c.msg.tear_color.empty()) {\n    c.msg.tear_color = \"|#5\";\n  }\n  if (c.msg.origin_color.empty()) {\n    c.msg.origin_color = \"|#5\";\n  }\n  if (c.msg.quote_color.empty()) {\n    c.msg.quote_color = \"|#1\";\n  }\n  if (c.msg.text_color.empty()) {\n    c.msg.text_color = \"|#0\";\n  }\n  if (c.msg.kludge_color.empty()) {\n    c.msg.kludge_color = \"|08\";\n  }\n\n  constexpr int MAX_STRING_LEN = 10;\n  auto y = 1;\n  EditItems items{};\n  items.add(new Label(\"Text Color:\"),\n            new StringEditItem<std::string&>(MAX_STRING_LEN, c.msg.text_color, EditLineMode::ALL),\n            \"Color for plain message text.\", 1, y);\n  ++y;\n  items.add(new Label(\"Quote Color:\"),\n            new StringEditItem<std::string&>(MAX_STRING_LEN, c.msg.quote_color, EditLineMode::ALL),\n            \"Color for quoted message text.\", 1, y);\n  ++y;\n  items.add(new Label(\"Kludge Color:\"),\n            new StringEditItem<std::string&>(MAX_STRING_LEN, c.msg.kludge_color, EditLineMode::ALL),\n            \"Color for kludge lines in the message text.\", 1, y);\n  ++y;\n  items.add(new Label(\"Tear Color:\"),\n            new StringEditItem<std::string&>(MAX_STRING_LEN, c.msg.tear_color, EditLineMode::ALL),\n            \"Color for tear lines in the message text.\", 1, y);\n  ++y;\n  items.add(new Label(\"Origin Color:\"),\n            new StringEditItem<std::string&>(MAX_STRING_LEN, c.msg.origin_color, EditLineMode::ALL),\n            \"Color for origin lines in the message text.\", 1, y);\n  ++y;\n\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"System Colors\");\n}\n"
  },
  {
    "path": "wwivconfig/colors.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2022, WWIV Software Services                */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_COLORS_H\n#define INCLUDED_WWIVCONFIG_COLORS_H\n\n#include \"localui/curses_win.h\"\n#include \"sdk/config.h\"\n\nvoid colors(wwiv::sdk::Config& config, wwiv::sdk::color_config_t& b_,\n            wwiv::local::ui::CursesWindow* window);\n\n#endif // INCLUDED_WWIVCONFIG_COLORS_H"
  },
  {
    "path": "wwivconfig/convert.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/convert.h\"\n\n#include \"bbs/conf.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/inifile.h\"\n#include \"core/jsonfile.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"localui/curses_io.h\"\n#include \"localui/input.h\"\n#include \"localui/wwiv_curses.h\"\n#include \"local_io/wconstants.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/config430.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/gfiles.h\"\n#include \"sdk/qwk_config.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/wwivcolors.h\"\n#include \"sdk/acs/expr.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/files/dirs.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/net/networks.h\"\n#include \"wwivconfig/archivers.h\"\n#include \"wwivconfig/convert_jsonfile.h\"\n\n#include <cstring>\n#include <filesystem>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::sdk::menus;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivconfig::convert {\n\nstruct user_config {\n  char name[31]; // verify against a user\n\n  unsigned long unused_status;\n\n  unsigned long lp_options;\n  unsigned char lp_colors[32];\n\n  char menu_set[9]; // Selected AMENU set to use\n  char hot_keys;    // Use hot keys in AMENU\n\n  char junk[119]; // AMENU took 11 bytes from here\n};\n\nvoid write_and_log(UIWindow* window, const std::string& m) {\n  LOG(INFO) << m;\n  window->Puts(StrCat(m, \"\\n\"));\n}\n\nint final_wwiv_config_dat_version() {\n  // TODO(rushfan): Update when we add a new version.\n  return 6;\n}\n\n\nstatic void ShowBanner(UIWindow* window, const std::string& m) {\n  // TODO(rushfan): make a sub-window here but until this clear the altcharset background.\n  curses_out->window()->Bkgd(' ');\n  window->SetColor(SchemeId::INFO);\n  write_and_log(window, m);\n  window->SetColor(SchemeId::NORMAL);\n}\n\nbool ensure_offsets_are_updated(UIWindow* window, const Config430& config) {\n  File file(config.config_filename());\n  if (!file.Open(File::modeBinary | File::modeReadWrite)) {\n    return false;\n  }\n\n  // update user info data\n  auto userreclen = static_cast<int16_t>(sizeof(userrec));\n  int16_t waitingoffset = offsetof(userrec, waiting);\n  int16_t inactoffset = offsetof(userrec, inact);\n  int16_t sysstatusoffset = offsetof(userrec, sysstatus);\n  int16_t fuoffset = offsetof(userrec, forwardusr);\n  int16_t fsoffset = offsetof(userrec, forwardsys);\n  int16_t fnoffset = offsetof(userrec, net_num);\n  configrec syscfg53{};\n  file.Seek(0, File::Whence::begin);\n  file.Read(&syscfg53, sizeof(configrec));\n\n  if (userreclen != config.config()->userreclen || waitingoffset != config.config()->waitingoffset ||\n      inactoffset != config.config()->inactoffset || sysstatusoffset != config.config()->sysstatusoffset ||\n      fuoffset != config.config()->fuoffset || fsoffset != config.config()->fsoffset ||\n      fnoffset != config.config()->fnoffset) {\n\n    ShowBanner(window, \"Updating Offsets...\");\n    syscfg53.userreclen = userreclen;\n    syscfg53.waitingoffset = waitingoffset;\n    syscfg53.inactoffset = inactoffset;\n    syscfg53.sysstatusoffset = sysstatusoffset;\n    syscfg53.fuoffset = fuoffset;\n    syscfg53.fsoffset = fsoffset;\n    syscfg53.fnoffset = fnoffset;\n\n    // Write it all back.\n    file.Seek(0, File::Whence::begin);\n    file.Write(&syscfg53, sizeof(configrec));\n    file.Close();\n  }\n  return true;\n}\n\nconfig_upgrade_state_t convert_config_to_52(UIWindow* window, const std::filesystem::path& config_filename) {\n  File file(config_filename);\n  if (!file.Open(File::modeBinary | File::modeReadWrite)) {\n    return config_upgrade_state_t::already_latest;\n  }\n\n  ShowBanner(window, \"Converting config.dat to 4.3/5.x format...\");\n  configrec syscfg53{};\n  file.Read(&syscfg53, sizeof(configrec));\n\n  configrec_header_t h = {};\n  h.config_revision_number = 0;\n  h.config_size = sizeof(configrec);\n  h.written_by_wwiv_num_version = wwiv_config_version();\n  to_char_array(h.signature, \"WWIV\");\n\n  // Save old new  user password.\n  std::string newuserpw = syscfg53.header.newuserpw;\n  // Update new user password to new location.\n  to_char_array(syscfg53.newuserpw, newuserpw);\n  // Set new header on config.dat.\n  syscfg53.header.header = h;\n\n  // Write it all back.\n  file.Seek(0, File::Whence::begin);\n  file.Write(&syscfg53, sizeof(configrec));\n  file.Close();\n  return config_upgrade_state_t::upgraded;\n}\n\n\nstatic bool convert_to_v1(UIWindow* window, Config& config) {\n  ShowBanner(window, \"Updating to 5.2.1+ format...\");\n\n  const auto users_lst = FilePath(config.datadir(), USER_LST);\n  auto backup_file = users_lst;\n  backup_file += \".backup.pre-wwivconfig-upgrade\";\n\n  // Make a backup file.\n  std::error_code ec;\n  // Note we ignore the ec since we fail open.\n  copy_file(users_lst, backup_file, ec);\n\n  DataFile<userrec> usersFile(FilePath(config.datadir(), USER_LST),\n                              File::modeReadWrite | File::modeBinary | File::modeCreateFile,\n                              File::shareDenyReadWrite);\n  if (!usersFile) {\n    LOG(ERROR) << \"Unable to open user.lst.\";\n    messagebox(window, \"Unable to open user.lst.\");\n    return false;\n  }\n\n  std::vector<userrec> users;\n  if (!usersFile.ReadVector(users)) {\n    LOG(ERROR) << \"Unable to read user.lst.\";\n    messagebox(window, \"Unable to read user.lst.\");\n    return false;\n  }\n\n  // zero out the res_xxx records for good housekeeping.\n  for (auto& u : users) {\n    memset(u.res_byte, 0, sizeof(u.res_byte));\n    memset(u.res_char, 0, sizeof(u.res_char));\n    memset(u.res_float, 0, sizeof(u.res_float));\n    memset(u.res_gp, 0, sizeof(u.res_gp));\n    memset(u.res_long, 0, sizeof(u.res_long));\n    memset(u.res_short, 0, sizeof(u.res_short));\n    memset(u.menu_set, 0, sizeof(u.menu_set));\n\n    // Set new defaults.\n    memset(u.lp_colors, static_cast<uint8_t>(Color::CYAN), sizeof(u.lp_colors));\n    u.lp_colors[0] = static_cast<uint8_t>(Color::LIGHTGREEN);\n    u.lp_colors[1] = static_cast<uint8_t>(Color::LIGHTGREEN);\n    u.lp_colors[2] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[3] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[4] = static_cast<uint8_t>(Color::LIGHTCYAN);\n    u.lp_colors[5] = static_cast<uint8_t>(Color::LIGHTCYAN);\n    u.lp_colors[6] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[7] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[8] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[9] = static_cast<uint8_t>(Color::CYAN);\n    u.lp_colors[10] = static_cast<uint8_t>(Color::LIGHTCYAN);\n    u.lp_options = cfl_fname | cfl_extension | cfl_dloads | cfl_kbytes | cfl_description;\n    u.hot_keys = 0;\n    to_char_array(u.menu_set, \"wwiv\");\n  }\n\n  // Save where we are.\n  usersFile.Seek(0);\n  usersFile.WriteVector(users);\n\n  // Update config.dat with new version to consider this \"successful\"\n  // enough of an upgrade at this point.\n  config.config_revision_number(1);\n\n  const auto config_usr_filename = FilePath(config.datadir(), \"config.usr\");\n  DataFile<user_config> configUsrFile(config_usr_filename, File::modeReadOnly | File::modeBinary,\n                                      File::shareDenyWrite);\n  if (!configUsrFile) {\n    LOG(ERROR) << \"No config.usr file to upgrade.\";\n    return false;\n  }\n\n  std::vector<user_config> second_config;\n  if (!configUsrFile.ReadVector(second_config)) {\n    LOG(ERROR) << \"Unable to read config.usr file to upgrade.\";\n    return false;\n  }\n\n  // merge in data from user_config\n  for (auto i = 0; i < stl::ssize(users); i++) {\n    auto& u = stl::at(users, i);\n    if (i >= stl::ssize(second_config)) {\n      continue;\n    }\n    const auto& c = stl::at(second_config, i);\n    u.hot_keys = c.hot_keys;\n    u.lp_options = c.lp_options;\n    memcpy(u.lp_colors, c.lp_colors, sizeof(u.lp_colors));\n  }\n\n  // Save where we are.\n  usersFile.Seek(0);\n  if (!usersFile.WriteVector(users)) {\n    LOG(ERROR) << \"Unable to write user.lst.\";\n    messagebox(window, \"Unable to write user.lst.\");\n    return false;\n  }\n\n  // Close the user_config file (config.usr) and delete it.\n  configUsrFile.Close();\n  File::Remove(config_usr_filename);\n\n  // 2nd version of config.usr that wwivconfig was mistakenly creating.\n  File::Remove(FilePath(config.datadir(), \"user.dat\"));\n\n  LOG(INFO) << \"Converted to config version v1\";\n  messagebox(window, \"Converted to config version v1\");\n  return true;\n}\n\ntemplate <>\n// ReSharper disable once CppMemberFunctionMayBeStatic\nsubboard_t ConvertJsonFile<subboard_52_t, subboard_t>::ConvertType(const subboard_52_t& os) {\n  subboard_t s{};\n  s.nets = os.nets;\n  {\n    acs::AcsExpr ae;\n    s.read_acs = ae.ar_int(os.ar).min_sl(os.readsl).min_age(os.age).get();\n  }\n  {\n    acs::AcsExpr ae;\n    s.post_acs = ae.min_sl(os.postsl).get();\n  }\n  s.anony = os.anony;\n  s.desc = os.desc;\n  s.filename = os.filename;\n  s.key = os.key;\n  s.maxmsgs = os.maxmsgs;\n  s.name = os.name;\n  s.storage_type = os.storage_type;\n  return s;\n}\n\ntemplate <>\n// ReSharper disable once CppMemberFunctionMayBeStatic\ndirectory_t ConvertJsonFile<directory_55_t, directory_t>::ConvertType(const directory_55_t& od) {\n  directory_t d{};\n  d.area_tags = od.area_tags;\n  acs::AcsExpr ae;\n  d.acs = ae.min_dsl(od.dsl).min_age(od.age).dar_int(od.dar).get();\n  d.filename = od.filename;\n  d.mask = od.mask;\n  d.maxfiles = od.maxfiles;\n  d.name = od.name;\n  d.path = od.path;\n  return d;\n}\n\ntemplate <>\n// ReSharper disable once CppMemberFunctionMayBeStatic\nchain_t ConvertJsonFile<chain_55_t, chain_t>::ConvertType(const chain_55_t& oc) {\n  chain_t c{};\n  acs::AcsExpr ae;\n  c.acs = ae.min_sl(oc.sl).ar_int(oc.ar).min_age(oc.minage).max_age(oc.maxage).get();\n  c.ansi = oc.ansi;\n  c.description = oc.description;\n  c.dir = oc.dir;\n  c.exec_mode = oc.exec_mode;\n  c.filename = oc.filename;\n  c.local_only = oc.local_only;\n  c.multi_user = oc.multi_user;\n  c.regby = oc.regby;\n  c.usage = oc.usage;\n  return c;\n}\n\nstatic bool convert_to_v2(UIWindow* window, Config& config) {\n  LOG(INFO) << \"Updating to 5.2+ v2 format...\";\n  ShowBanner(window, \"Updating to 5.2+ v2 format...\");\n\n  const auto datadir = config.datadir();\n  LOG(INFO) << \"Upgrading subs.json\";\n  ConvertJsonFile<subboard_52_t, subboard_t> cs(datadir, SUBS_JSON, \"subs\", 0, 1);\n  cs.Convert();\n\n  LOG(INFO) << \"Upgrading dirs.json\";\n  ConvertJsonFile<directory_55_t, directory_t> cd(datadir, DIRS_JSON, \"dirs\", 0, 1);\n  cd.Convert();\n\n  LOG(INFO) << \"Upgrading chains.json\";\n  ConvertJsonFile<chain_55_t, chain_t> cc(datadir, CHAINS_JSON, \"chains\", 0, 1);\n  cc.Convert();\n\n  // Mark config.dat as upgraded.\n  config.config_revision_number(2);\n  return true;\n}\n\nstatic bool convert_menu(const std::filesystem::path& menu_dir, const std::string& menu_set,\n                         const std::string& menu_name, int max_backups) {\n\n  const auto dir = FilePath(menu_dir, menu_set);\n  const auto fname = StrCat(menu_name, \".mnu.json\");\n  const auto path = FilePath(dir, fname);\n  if (File::Exists(path)) {\n    LOG(INFO) << \"Menu already exists in 5.6+ format: \" << path.string();\n    return true;\n  }\n\n  const Menu430 m4(menu_dir, menu_set, menu_name);\n  if (m4.initialized()) {\n    if (auto om5 = Create56MenuFrom43(m4, max_backups)) {\n      auto& m5 = om5.value();\n      if (m5.Save()) {\n        LOG(INFO) << \"Converted menu: \" << menu_set << File::pathSeparatorChar << menu_name\n                  << std::endl;\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nstatic bool convert_to_v3(UIWindow* window, Config& config) {\n  ShowBanner(window, \"Updating to 5.2+ v3 format...\");\n\n  auto dirs = FindFiles(FilePath(config.menudir(), \"*\"), FindFiles::FindFilesType::directories);\n\n  for (const auto& d : dirs) {\n    const auto& menu_set = d.name;\n    const auto path = FilePath(config.menudir(), menu_set);\n    auto menus = FindFiles(FilePath(path, \"*\"), FindFiles::FindFilesType::files, FindFiles::WinNameType::long_name);\n    for (const auto& m : menus) {\n      auto lm = ToStringLowerCase(m.name);\n      if (ends_with(lm, \".mnu\")) {\n        const auto name = m.name.substr(0, m.name.size() - 4 ); \n        if (!convert_menu(config.menudir(), menu_set, name, config.max_backups())) {\n          LOG(ERROR) << \"Unable to convert 4.3 menu:\" << menu_set << File::pathSeparatorChar\n                     << name << std::endl;\n        }\n      }\n    }\n  }\n\n  // Mark config.dat as upgraded.\n  config.config_revision_number(3);\n  return true;\n}\n\nstatic bool convert_to_v4(UIWindow* window, Config& config) {\n  ShowBanner(window, \"Updating to 5.2+ v4 format...\");\n\n  Networks networks(config);\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks (needed to load subs)\";\n    return false;\n  }\n\n  const auto datadir = config.datadir();\n  Subs subs(datadir, networks.networks());\n  Dirs dirs(datadir, 0);\n  if (!subs.Load()) {\n    std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n    return false;\n  }\n  if (!dirs.Load()) {\n    std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n    return false;\n  }\n  Conferences confs(datadir, subs, dirs, 0);\n\n  const auto f = UpgradeConferences(config, subs, dirs);\n  if (!confs.LoadFromFile(f)) {\n    std::cout << \"Failed to upgrade conferences\";\n  }\n\n  // Save conferences to new version.\n  if (confs.Save()) {\n    if (!subs.Save()) {\n      LOG(ERROR) << \"Saved new conference, but failed to save subs\";\n    }\n    if (!dirs.Save()) {\n      LOG(ERROR) << \"Saved new conference, but failed to save dirs\";\n    }\n  }\n\n  // Mark config.dat as upgraded.\n  config.config_revision_number(4);\n  return true;\n}\n\n\nbool convert_to_v5(UIWindow* window, Config& config) {\n  ShowBanner(window, \"Updating to 5.2+ v5 format...\");\n  Networks networks(config);\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks (needed to load subs)\";\n    return false;\n  }\n\n  // Update GFiles to JSON\n  GFiles gfiles(config.datadir(), config.max_backups());\n  if (gfiles.Load()) {\n    gfiles.Save();\n  }\n\n  // Update networks to get rid of base packet config.\n  for (const auto& net : networks.networks()) {\n    if (net.type == network_type_t::ftn) {\n      fido::FidoCallout callout(config.root_directory(), config.max_backups(), net);\n      for (auto& [a, node_config] : callout.node_configs_map()) {\n        auto merged_config = callout.merged_packet_config_for(a, net.fido.packet_config);\n        node_config.packet_config = merged_config;\n      }\n      callout.Save();\n    }\n  }\n  networks.Save();\n\n  // Update QWK to new version.\n  auto qwk_config = read_qwk_cfg(config);\n  write_qwk_cfg(config, qwk_config);\n\n  // Mark config.dat as upgraded.\n  config.config_revision_number(5);\n  return true;\n}\n\nstatic bool UseMinimalNewUserInfo(IniFile& ini) {\n  if (ini.IsOpen()) {\n    return ini.value<bool>(\"NEWUSER_MIN\");\n  }\n  return false;\n}\n\n// This is the first one of 5.7\nbool convert_to_v6(UIWindow* window, Config& config) {\n  ShowBanner(window, \"Updating to 5.7+ v6 format...\");\n  IniFile ini(FilePath(config.root_directory(), WWIV_INI), INI_TAG);\n  auto minimal = true;\n  int num_instances = 8;\n  std::string temp_directory = \"e/%n/temp\";\n  std::string batch_directory = \"e/%n/batch\";\n  std::string scratch_directory = \"e/%n/scratch\";\n  if (ini.IsOpen()) {\n    minimal = UseMinimalNewUserInfo(ini);\n    temp_directory = ini.value<std::string>(\"TEMP_DIRECTORY\", \"e/%n/temp\");\n    batch_directory = ini.value<std::string>(\"BATCH_DIRECTORY\", \"e/%n/temp\");\n    num_instances = ini.value<int>(\"NUM_INSTANCES\", 8);\n  }\n  auto& nc = config.newuser_config();\n  if (minimal) {\n    nc.use_real_name = newuser_item_type_t::unused;\n    nc.use_voice_phone = newuser_item_type_t::unused;\n    nc.use_data_phone = newuser_item_type_t::unused;\n    nc.use_address_street = newuser_item_type_t::unused;\n    nc.use_callsign = newuser_item_type_t::unused;\n    nc.use_computer_type = newuser_item_type_t::unused;\n    nc.use_email_address = newuser_item_type_t::optional;\n  }\n\n  config.batch_format(batch_directory);\n  config.scratch_format(scratch_directory);\n  config.temp_format(temp_directory);\n  config.num_instances(num_instances);\n  // Mark config.dat as upgraded.\n  config.config_revision_number(6);\n  return true;\n}\n\nstatic config_upgrade_state_t ensure_latest_5x_config(UIWindow* window, Config& config) {\n  const auto config_revision_number = config.config_revision_number();\n  VLOG(1) << \"ensure_latest_5x_config: desired version=\" << config_revision_number;\n  if (config_revision_number >= final_wwiv_config_dat_version()) {\n    VLOG(1) << \"ensure_latest_5x_config: ALREADY LATEST\";\n    return config_upgrade_state_t::already_latest;\n  }\n  // v1 is the GA 5.5 config version.\n  if (config_revision_number < 1) {\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v1\";\n    convert_to_v1(window, config);\n  }\n  // v2-v5 added during 5.6.  Likely v5 will be the GA 5.6 version.\n  if (config_revision_number < 2) {\n    // Versioned subs, chains, and dirs\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v2\";\n    convert_to_v2(window, config);\n  }\n  if (config_revision_number < 3) {\n    // menus in JSON format.\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v3\";\n    convert_to_v3(window, config);\n  }\n  if (config_revision_number < 4) {\n    // Conferences in JSON\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v4\";\n    convert_to_v4(window, config);\n  }\n  if (config_revision_number < 5) {\n    // gfiles in JSON format.\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v5\";\n    convert_to_v5(window, config);\n  }\n  if (config_revision_number < 6) {\n    // Newuser info by-field.\n    LOG(INFO) << \"ensure_latest_5x_config: converting to v6\";\n    convert_to_v6(window, config);\n  }\n  VLOG(1) << \"ensure_latest_5x_config: UPGRADED\";\n  return config_upgrade_state_t::upgraded;\n}\n\nbool convert_config_424_to_430(UIWindow* window, const std::filesystem::path& config_filename) {\n  File file(config_filename);\n  if (!file.Open(File::modeBinary | File::modeReadWrite)) {\n    return false;\n  }\n  window->SetColor(SchemeId::INFO);\n  write_and_log(window, \"Converting config.dat to 4.3/5.x format...\\n\");\n  window->SetColor(SchemeId::NORMAL);\n  configrec syscfg53{};\n  file.Read(&syscfg53, sizeof(configrec));\n  auto menus_dir = File::EnsureTrailingSlash(\"menus\");\n  to_char_array(syscfg53.menudir, FilePath(syscfg53.gfilesdir, menus_dir).string());\n\n  arcrec arc[MAX_ARCS]{};\n  for (auto i = 0; i < MAX_ARCS; i++) {\n    if (syscfg53.arcs[i].extension[0] && i < 4) {\n      to_char_array(arc[i].name, syscfg53.arcs[i].extension);\n      to_char_array(arc[i].extension, syscfg53.arcs[i].extension);\n      to_char_array(arc[i].arca, syscfg53.arcs[i].arca);\n      to_char_array(arc[i].arce, syscfg53.arcs[i].arce);\n      to_char_array(arc[i].arcl, syscfg53.arcs[i].arcl);\n    } else {\n      to_char_array(arc[i].name, \"New Archiver Name\");\n      to_char_array(arc[i].extension, \"EXT\");\n      to_char_array(arc[i].arca, \"archive add command\");\n      to_char_array(arc[i].arce, \"archive extract command\");\n      to_char_array(arc[i].arcl, \"archive list command\");\n    }\n  }\n  file.Seek(0, File::Whence::begin);\n  file.Write(&syscfg53, sizeof(configrec));\n  file.Close();\n\n  File archiver(FilePath(syscfg53.datadir, ARCHIVER_DAT));\n  if (!archiver.Open(File::modeBinary | File::modeWriteOnly | File::modeCreateFile)) {\n    write_and_log(window, \"Couldn't open 'ARCHIVER_DAT' for writing.\\n\");\n    write_and_log(window, \"Creating new file....\\n\");\n    create_arcs(window, syscfg53.datadir);\n    window->Puts( \"\\n\");\n    if (!archiver.Open(File::modeBinary | File::modeWriteOnly | File::modeCreateFile)) {\n      messagebox(window, \"Still unable to open archiver.dat. Something is really wrong.\");\n      return false;\n    }\n  }\n  return archiver.Write(arc, MAX_ARCS * sizeof(arcrec));\n}\n\n\n\nShouldContinue do_wwiv_upgrades(UIWindow* window, const std::string& bbsdir) {\n  // Start by checking if we're already at the latest.\n  if (File::Exists(FilePath(bbsdir, CONFIG_JSON))) {\n    // Good, we have a config.json already, now make sure it's at the latest 5.x config version.\n    Config config56(bbsdir);\n    if (!config56.IsInitialized()) {\n      messagebox(window, \"Unable to load config.json\");\n      return ShouldContinue::EXIT;\n    }\n    if (auto state = ensure_latest_5x_config(window, config56);\n        state == config_upgrade_state_t::upgraded) {\n      if (!config56.Save()) {\n        messagebox(window, \"Unable to save upgrades config.json\");\n        return ShouldContinue::EXIT;\n      }\n    }\n    return ShouldContinue::CONTINUE;\n  }\n\n  if (const auto path = FilePath(bbsdir, CONFIG_DAT); File::Exists(path)) {\n    // Now start with 4.24 and work forwards, doing each upgrade one at a time.\n    // We have a config.dat at least.  \n    const File file(FilePath(bbsdir, CONFIG_DAT));\n    backup_file(path, 10);\n    if (file.length() != sizeof(configrec)) {\n      // Convert 4.2X to 4.3 format if needed.\n      // TODO(rushfan): make a sub-window here but until this clear the altcharset background.\n      if (!dialog_yn(curses_out->window(), \"Upgrade config.dat from 4.x format?\")) {\n        return ShouldContinue::EXIT;\n      }\n      window->Bkgd(' ');\n      if (!convert_config_424_to_430(window, path)) {\n        LOG(ERROR) << \"Failed to upgrade to 4.3\";\n        return ShouldContinue::EXIT;\n      }\n      // TODO(rushfan): We need to create the 4.3 menus here or later.\n    }\n  }\n\n  Config430 c430(bbsdir);\n  if (!c430.IsInitialized()) {\n    LOG(ERROR) << \"Expected a valid 4.30 system at this point. Can't load config.dat\";\n    return ShouldContinue::EXIT;\n  }\n\n  // Check for 5.2+ config\n  if (!c430.versioned_config_dat()) {\n    // We don't have a 5.2 header, let's convert.\n    if (!dialog_yn(curses_out->window(), \"Upgrade config.dat to 5.2+ format?\")) {\n      return ShouldContinue::EXIT;\n    }\n\n    backup_file(c430.config_filename(), 10);\n    convert_config_to_52(window, c430.config_filename());\n  }\n  // Reload changed config\n  c430.Load();\n  ensure_offsets_are_updated(window, c430);\n\n  // Were done changing config430 at this point.\n  // Now create the 5.x JSON. We know we have config.dat and no config.json\n  backup_file(c430.config_filename(), 10);\n  Config config56(bbsdir, c430.to_json_config());\n  // By default a config created any other way is read only.\n  config56.set_readonly(false);\n  if (!config56.Save()) {\n    messagebox(window, \"Unable to save config.json\");\n    return ShouldContinue::EXIT;\n  }\n\n  if (auto state = ensure_latest_5x_config(window, config56);\n      state == config_upgrade_state_t::upgraded) {\n    if (!config56.Save()) {\n      messagebox(window, \"Unable to save upgrades config.json\");\n      return ShouldContinue::EXIT;\n    }\n  }\n  return ShouldContinue::CONTINUE;\n}\n\n} // namespace wwivconfig::convert\n"
  },
  {
    "path": "wwivconfig/convert.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_CONVERT_H\n#define INCLUDED_WWIVCONFIG_CONVERT_H\n\n#include <filesystem>\n\nnamespace wwiv::local::ui {\n  class UIWindow;\n}\nnamespace wwiv::sdk {\nclass Config430;\n}\nnamespace wwiv::wwivconfig::convert {\n\nenum class ShouldContinue { CONTINUE, EXIT };\n\nenum class config_upgrade_state_t { already_latest, upgraded };\nbool ensure_offsets_are_updated(local::ui::UIWindow* window, const sdk::Config430&);\nbool convert_config_424_to_430(local::ui::UIWindow* window, const std::filesystem::path& config_filename);\nconfig_upgrade_state_t convert_config_to_52(local::ui::UIWindow* window, const std::filesystem::path& config_filename);\nint final_wwiv_config_dat_version();\n\nShouldContinue do_wwiv_upgrades(local::ui::UIWindow* window, const std::string& bbsdir);\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivconfig/convert_jsonfile.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_CONVERT_DATAFILE_H\n#define INCLUDED_WWIVCONFIG_CONVERT_DATAFILE_H\n\n#include \"core/file.h\"\n#include \"core/jsonfile.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/chains_cereal.h\"\n#include \"sdk/subs_cereal.h\"\n#include \"wwivconfig/convert.h\"\n\n#include <filesystem>\n#include <optional>\n#include <string>\n#include <vector>\n\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/files/dirs_cereal.h\"\n\nnamespace wwiv::wwivconfig::convert {\n\ntemplate <typename OLDT, typename NEWT>\nclass ConvertJsonFile final {\npublic:\n  ConvertJsonFile(std::filesystem::path dir, std::string file_name, std::string key,\n                  int old_version, int new_version)\n      : dir_(std::move(dir)), file_name_(std::move(file_name)), key_(std::move(key)),\n        old_version_(old_version), new_version_(new_version) {}\n\n  bool Convert() {\n    if (const auto ov = Load()) {\n      std::vector<NEWT> nv;\n      for (const auto&o : ov.value()) {\n        nv.emplace_back(ConvertType(o));\n      }\n      return Save(nv);\n    }\n    return false;\n  }\n\n private:\n  NEWT ConvertType(const OLDT& o);\n\n  std::optional<std::vector<OLDT>> Load() {\n    std::vector<OLDT> old;\n    const auto path = wwiv::core::FilePath(dir_, file_name_);\n    wwiv::core::JsonFile f(path, key_, old, old_version_);\n    if (!f.Load()) {\n      return std::nullopt;\n    }\n    if (f.loaded_version() != old_version_) {\n      return std::nullopt;\n    }\n    return { old };\n  }\n\n  bool Save(const std::vector<NEWT>& e) {\n    const auto path = wwiv::core::FilePath(dir_, file_name_);\n    const auto saved_path =\n        wwiv::core::FilePath(dir_, wwiv::strings::StrCat(file_name_, \"v\", old_version_));\n    wwiv::core::File::Copy(path, saved_path);\n    wwiv::core::JsonFile f(path, key_, e, new_version_);\n    return f.Save();\n  }\n\n  std::filesystem::path dir_;\n  std::string file_name_;\n  std::string key_;\n  int old_version_;\n  int new_version_;\n};\n\n}\n\n#endif // INCLUDED_WWIVCONFIG_CONVERT_H\n"
  },
  {
    "path": "wwivconfig/convert_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n\n\n"
  },
  {
    "path": "wwivconfig/editors.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/editors.h\"\r\n\r\n#include \"core/datafile.h\"\r\n#include \"core/file.h\"\r\n#include \"core/stl.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/vardec.h\"\r\n\r\n#include <cstdint>\r\n#include <vector>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::stl;\r\nusing namespace wwiv::strings;\r\n\r\nstatic void edit_editor(editorrec& e) {\r\n  constexpr uint8_t bbs_type_wwiv = 0;\r\n  constexpr uint8_t bbs_type_quickbbs = 1;\r\n\r\n  constexpr int fossil_type_none = 0;\r\n  constexpr int fossil_type_netfoss = 1;\r\n  constexpr int fossil_type_syncfoss = 2;\r\n\r\n  const std::vector<std::pair<uint8_t, std::string>> bbs_types = {{bbs_type_wwiv, \"WWIV\"},\r\n                                                             {bbs_type_quickbbs, \"QuickBBS\"}};\r\n  const std::vector<std::pair<int, std::string>> fossil_types = {\r\n      {fossil_type_none, \"No\"},\r\n      {fossil_type_syncfoss, \"SyncFoss\"},\r\n      {fossil_type_netfoss, \"NetFoss\"},\r\n  };\r\n\r\n  if (e.old_ansir != 0 && e.ansir == 0) {\r\n    // update to wide ansir.\r\n    e.ansir = e.old_ansir;\r\n  }\r\n  if (!(e.ansir & ansir_ansi)) {\r\n    e.ansir |= ansir_netfoss;\r\n    e.ansir |= ansir_no_DOS;\r\n    e.ansir |= ansir_ansi;\r\n    e.ansir |= ansir_temp_dir;\r\n  }\r\n\r\n  auto fossil_type = fossil_type_none;\r\n  if (e.ansir & ansir_emulate_fossil) {\r\n    fossil_type = fossil_type_syncfoss;\r\n  } else if (e.ansir & ansir_netfoss) {\r\n    fossil_type = fossil_type_netfoss;\r\n  }\r\n\r\n  auto y = 1;\r\n  EditItems items{};\r\n  items.add(new Label(\"Name:\"), new StringEditItem<char*>(35, e.description, EditLineMode::ALL),\r\n            \"The name of this editor, will be displayed to users\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"BBS Type:\"), new ToggleEditItem<uint8_t>(bbs_types, &e.bbs_type),\r\n            \"Type of BBS to emulate with editor control files:  WWIV or QuickBBS\", 1, y);\r\n#ifndef _WIN32\r\n  ++y;\r\n  items.add(new Label(\"Use STDIO:\"),\r\n            new FlagEditItem<uint16_t>(ansir_stdio, \"Yes\", \"No \", &e.ansir),\r\n            \"Use stdin/stdout from the door for I/O\", 1, y);\r\n  // Clear the FOSSIL flags if they are set accidentally.\r\n  e.ansir &= ~ansir_netfoss;\r\n  e.ansir &= ~ansir_emulate_fossil;\r\n#else\r\n  ++y;\r\n  items.add(new Label(\"FOSSIL:\"), new ToggleEditItem<int>(fossil_types, &fossil_type),\r\n            \"Should a FOSSIL be emulated through NetFoss, SyncFoss, or None\", 1, y);\r\n  // Clear the stdio flag if it's set accidentally.\r\n  e.ansir &= ~ansir_stdio;\r\n#endif\r\n  ++y;\r\n  items.add(new Label(\"Use Temp:\"),\r\n            new FlagEditItem<uint16_t>(ansir_temp_dir, \"Yes\", \"No \", &e.ansir),\r\n            \"Launch using the temp directory as the current directory (recommended)\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Remote:\"), new CommandLineItem(66, e.filename),\r\n            \"Commandline to use when executing this editor remotely\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Local:\"), new CommandLineItem(66, e.filenamecon),\r\n            \"Commandline to use when executing this editor locally\", 1, y);\r\n\r\n  y += 2;\r\n  items.add(new MultilineLabel(R\"\"\"\"(%1 = filename to edit   %N = Node Number\r\n%2 = chars per line     %H = Socket Handle\r\n%3 = lines per page     %I = Temp directory\r\n%4 = max lines\r\n\r\nNote: All Other Chain Parameters are allowed. See \r\nhttp://docs.wwivbbs.org/en/latest/chains/parameters for the full list.\r\n)\"\"\"\"),\r\n            1, y);\r\n  items.relayout_items_and_labels();\r\n  items.Run(\"External Editor Configuration\");\r\n\r\n  switch (fossil_type) {\r\n  case fossil_type_netfoss: {\r\n    e.ansir |= ansir_no_DOS;\r\n    e.ansir |= ansir_netfoss;\r\n    e.ansir &= ~ansir_emulate_fossil;\r\n  } break;\r\n  case fossil_type_syncfoss: {\r\n    e.ansir |= ansir_no_DOS;\r\n    e.ansir &= ~ansir_netfoss;\r\n    e.ansir |= ansir_emulate_fossil;\r\n  } break;\r\n  case fossil_type_none:\r\n  default: {\r\n    e.ansir &= ~ansir_netfoss;\r\n    e.ansir &= ~ansir_emulate_fossil;\r\n  }\r\n  }\r\n}\r\n\r\nvoid extrn_editors(const wwiv::sdk::Config& config) {\r\n  std::vector<editorrec> editors;\r\n  if (auto file = DataFile<editorrec>(FilePath(config.datadir(), EDITORS_DAT))) {\r\n    file.ReadVector(editors, 10);\r\n    file.Close();\r\n  }\r\n\r\n  auto done = false;\r\n  do {\r\n    curses_out->Cls(ACS_CKBOARD);\r\n    std::vector<ListBoxItem> items;\r\n    for (size_t i = 0; i < editors.size(); i++) {\r\n      items.emplace_back(fmt::format(\"{}. {}\", i + 1, editors[i].description));\r\n    }\r\n    auto* window = curses_out->window();\r\n    ListBox list(window, \"Select Editor\", items);\r\n\r\n    list.selection_returns_hotkey(true);\r\n    list.set_additional_hotkeys(\"DI\");\r\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\r\n    if (auto result = list.Run(); result.type == ListBoxResultType::HOTKEY) {\r\n      switch (result.hotkey) {\r\n      case 'D': {\r\n        if (!editors.empty()) {\r\n          auto prompt = fmt::format(\"Delete '{}' ?\", items[result.selected].text());\r\n          bool yn = dialog_yn(window, prompt);\r\n          if (!yn) {\r\n            break;\r\n          }\r\n          erase_at(editors, result.selected);\r\n        }\r\n      } break;\r\n      case 'I': {\r\n        if (editors.size() >= 10) {\r\n          messagebox(curses_out->window(), \"Too many editors.\");\r\n          break;\r\n        }\r\n        auto prompt = fmt::format(\"Insert before which (1-{}) : \", editors.size() + 1);\r\n        auto i = dialog_input_number(curses_out->window(), prompt, 1, size_int(editors) + 1);\r\n        editorrec e{};\r\n        memset(&e, 0, sizeof(editorrec));\r\n        // N.B. i is one based, result.selected is 0 based.\r\n        if (i <= 0 || i > wwiv::stl::ssize(editors) + 1) {\r\n          break;\r\n        }\r\n        if (i > wwiv::stl::ssize(editors)) {\r\n          editors.push_back(e);\r\n          edit_editor(editors.back());\r\n        } else {\r\n          auto it = editors.begin();\r\n          std::advance(it, i - 1);\r\n          auto new_editor_it = editors.insert(it, e);\r\n          edit_editor(*new_editor_it);\r\n        }\r\n      } break;\r\n      }\r\n    } else if (result.type == ListBoxResultType::SELECTION) {\r\n      edit_editor(editors[result.selected]);\r\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n      done = true;\r\n    }\r\n  } while (!done);\r\n\r\n  DataFile<editorrec> editors_dat(FilePath(config.datadir(), EDITORS_DAT),\r\n                                  File::modeReadWrite | File::modeBinary | File::modeCreateFile |\r\n                                      File::modeTruncate,\r\n                                  File::shareDenyReadWrite);\r\n  if (editors_dat) {\r\n    editors_dat.WriteVector(editors);\r\n  }\r\n}\r\n"
  },
  {
    "path": "wwivconfig/editors.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_EDITORS_H\r\n#define INCLUDED_WWIVCONFIG_EDITORS_H\r\n\r\n#include \"sdk/config.h\"\r\n\r\nvoid extrn_editors(const wwiv::sdk::Config&);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_EDITORS_H\r\n"
  },
  {
    "path": "wwivconfig/levels.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"core/strings.h\"\r\n#include \"core/wwivport.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"sdk/vardec.h\"\r\n#include <memory>\r\n\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::sdk;\r\nusing namespace wwiv::strings;\r\n\r\nstatic constexpr int MAX_SL = 255;\r\nstatic constexpr int MIN_SL = 0;\r\n\r\nstatic std::vector<HelpItem> create_extra_help_items() {\r\n  std::vector<HelpItem> help_items = {{\"J\", \"Jump\"}};\r\n  return help_items;\r\n}\r\n\r\nstatic uint8_t JumpToSl(CursesWindow* window) {\r\n  std::vector<ListBoxItem> items;\r\n  for (int i = MIN_SL; i < MAX_SL; i++) {\r\n    items.emplace_back(fmt::format(\"SL #{}\", i), 0, i);\r\n  }\r\n\r\n  ListBox list(window, \"Select SL\", items);\r\n  const auto result = list.Run();\r\n  if (result.type == ListBoxResultType::SELECTION) {\r\n    return static_cast<uint8_t>(items[result.selected].data());\r\n  }\r\n  return 0;\r\n}\r\n\r\nvoid sec_levs(Config& config) {\r\n  uint8_t cursl = 10;\r\n  auto sl = config.sl(cursl);\r\n  EditItems items{};\r\n  auto y = 1;\r\n  items.add(new Label(\"Security level:\"),\r\n      new NumberEditItem<uint8_t>(&cursl), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Time per day:\"),\r\n      new NumberEditItem<uint16_t>(&sl.time_per_day), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Time per logon:\"),\r\n      new NumberEditItem<uint16_t>(&sl.time_per_logon), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Messages read:\"),\r\n      new NumberEditItem<uint16_t>(&sl.messages_read), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Emails per day:\"),\r\n      new NumberEditItem<uint16_t>(&sl.emails), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Posts per day:\"),\r\n      new NumberEditItem<uint16_t>(&sl.posts), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Post anony:\"),\r\n      new FlagEditItem<uint32_t>(ability_post_anony, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Email anony:\"),\r\n      new FlagEditItem<uint32_t>(ability_email_anony, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Read anony posts:\"),\r\n      new FlagEditItem<uint32_t>(ability_read_post_anony, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Read anony email:\"),\r\n      new FlagEditItem<uint32_t>(ability_read_email_anony, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Limited co-sysop:\"),\r\n      new FlagEditItem<uint32_t>(ability_limited_cosysop, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n  ++y;\r\n  items.add(new Label(\"Co-sysop:\"),\r\n      new FlagEditItem<uint32_t>(ability_cosysop, \"Yes\", \"No \",\r\n                                 &sl.ability), \"\", 1, y);\r\n\r\n  items.relayout_items_and_labels();\r\n  items.set_navigation_extra_help_items(create_extra_help_items());\r\n  curses_out->Cls(ACS_CKBOARD);\r\n  items.create_window(\"Security Level Editor\");\r\n  items.Display();\r\n\r\n  const NavigationKeyConfig nav(\"J\\r\");\r\n\r\n  for (;;) {\r\n    const auto ch = items.GetKeyWithNavigation(nav);\r\n    switch (ch) {\r\n    case '\\r': {\r\n      items.Run();\r\n      config.sl(cursl, sl);\r\n      items.window()->Refresh();\r\n    } break;\r\n    case 'J': {\r\n      cursl = JumpToSl(items.window());\r\n    } break;\r\n    case 'Q':\r\n      return;\r\n    case ']':\r\n      if (++cursl > MAX_SL) {\r\n        cursl = MIN_SL;\r\n      }\r\n      break;\r\n    case '[': {\r\n      // Wraps around at 0 == 255\r\n      --cursl;\r\n    } break;\r\n    case '}':\r\n      cursl += 10;\r\n      if (cursl > MAX_SL) {\r\n        cursl = MIN_SL;\r\n      }\r\n      break;\r\n    case '{':\r\n      // Auto wraps\r\n      cursl -= 10;\r\n      break;\r\n    default:\r\n      continue;\r\n    }\r\n    sl = config.sl(cursl);\r\n    items.Display();\r\n  }\r\n}\r\n"
  },
  {
    "path": "wwivconfig/levels.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_LEVELS_H\r\n#define INCLUDED_WWIVCONFIG_LEVELS_H\r\n\r\n#include \"sdk/config.h\"\r\n\r\nvoid sec_levs(wwiv::sdk::Config& config);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_LEVELS_H\r\n"
  },
  {
    "path": "wwivconfig/menus.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2017-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/menus.h\"\n\n#include \"common/menus/menu_generator.h\"\n#include \"common/value/bbsvalueprovider.h\"\n#include \"common/value/uservalueprovider.h\"\n#include \"core/file.h\"\n#include \"core/findfiles.h\"\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"local_io/null_local_io.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n#include \"localui/listbox.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/menus/menu.h\"\n#include \"sdk/menus/menu_set.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/value/valueprovider.h\"\n\n#include <filesystem>\n#include <string>\n#include <utility>\n#include <vector>\n\nusing namespace wwiv::common::value;\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nclass ActionPickerSubDialog final : public SubDialog<std::string> {\npublic:\n  ActionPickerSubDialog(const Config& config, std::vector<menus::menu_command_help_t> cmds,\n                        int width, std::string& c)\n      : SubDialog(config, c), cmds_(std::move(cmds)) {\n    this->width_ = width;\n  }\n  ~ActionPickerSubDialog() override = default;\n\n  void RunSubDialog(CursesWindow* window) override {\n    do {\n      std::vector<ListBoxItem> items;\n      auto selected = -1;\n      auto count = 0;\n      for (const auto& e : cmds_) {\n        const auto cat = StrCat(\"[\", e.cat, \"]\");\n        auto help = e.help;\n        help.erase(std::remove(help.begin(), help.end(), 10), help.end());\n        help.erase(std::remove(help.begin(), help.end(), 13), help.end());\n        items.emplace_back(fmt::format(\"{:20.20} {:13.13} {:44.44}\", e.cmd, cat, help), 0, count);\n        if (iequals(e.cmd, t_)) {\n          selected = count;\n        }\n        ++count;\n      }\n      ListBox list(window, \"Select Command\", items);\n      list.set_selected(selected);\n      list.selection_returns_hotkey(true);\n      list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Select\"}, {\"/\", \"Filter\"}});\n      const auto result = list.Run();\n      if (result.type == ListBoxResultType::SELECTION) {\n        const auto selected_cmd = cmds_[result.selected].cmd;\n        t_ = selected_cmd;\n        return;\n      }\n      if (result.type == ListBoxResultType::NO_SELECTION) {\n        return;\n      }\n    } while (true);\n  }\n\n  [[nodiscard]] std::string menu_label() const override {\n    return fmt::format(\"[Edit] '{:<.{}}'\", t_, width());\n  }\n\nprivate:\n  const std::vector<menus::menu_command_help_t> cmds_;\n};\n\nstatic void edit_menu_action(const Config& config, menus::menu_action_56_t& a,\n                             std::vector<const value::ValueProvider*> providers) {\n  const auto cmds = menus::LoadCommandHelpJSON(config.datadir());\n\n  EditItems items{};\n  auto y = 1;\n  items.add(new Label(\"Cmd:\"), new ActionPickerSubDialog(config, cmds, 40, a.cmd),\n            \"Command to execute\", 1, y);\n  y++;\n  items.add(new Label(\"Data:\"), new StringEditItem<std::string&>(70, a.data, EditLineMode::ALL),\n            \"Optional data to pass to the command\", 1, y);\n  y++;\n  items.add(new Label(\"ACS:\"), new ACSEditItem(config,  providers, 70, a.acs),\n            \"WWIV ACS required to execute this command\", 1, y);\n\n  items.relayout_items_and_labels();\n  items.Run(\"Edit Action\");\n}\n\nclass ActionSubDialog final : public SubDialog<std::vector<menus::menu_action_56_t>> {\npublic:\n  ActionSubDialog(const Config& config, std::vector<menus::menu_action_56_t>& actions,\n                  std::vector<const value::ValueProvider*> p)\n      : SubDialog(config, actions), providers_(std::move(p)) {}\n  ~ActionSubDialog() override = default;\n\n  void RunSubDialog(CursesWindow* window) override {\n    auto done = false;\n    auto selected = -1;\n    do {\n      std::vector<ListBoxItem> items;\n      for (auto i = 0; i < wwiv::stl::ssize(t_); i++) {\n        const auto& m = t_.at(i);\n        auto s = fmt::format(\"{}:{}\", m.cmd, m.data);\n        items.emplace_back(s, 0, i);\n      }\n      ListBox list(window, \"[Edit Actions]\", items);\n\n      list.set_additional_hotkeys(\"DIM\");\n      list.set_help_items(\n          {{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}, {\"M\", \"Move\"}});\n      list.set_selected(selected);\n      const auto result = list.Run();\n      selected = list.selected();\n\n      if (result.type == ListBoxResultType::SELECTION) {\n        edit_menu_action(config(), t_[items[result.selected].data()], providers_);\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\n        done = true;\n      } else if (result.type == ListBoxResultType::HOTKEY) {\n        const auto key = static_cast<char>(result.hotkey);\n        const auto num = result.selected > 0 ? items[result.selected].data() : 0;\n        switch (key) {\n        case 'D': {\n          if (t_.empty()) {\n            break;\n          }\n          const auto& item = t_[num];\n          if (dialog_yn(window, StrCat(\"Do you want to delete #\", num, \" [\", item.cmd, \"]\"))) {\n            erase_at(t_, num);\n          }\n        } break;\n        case 'I': {\n          if (num <= 0 || num >= size_int(items)) {\n            t_.push_back({});\n          } else {\n            menus::menu_action_56_t mr{};\n            insert_at(t_, num, mr);\n          }\n        } break;\n        case 'M': {\n          auto maxnum = size_int(t_) + 1;\n          auto prompt = fmt::format(\"Move to before which (1-{}) : \", maxnum);\n          auto new_pos = dialog_input_number(window, prompt, 1, maxnum);\n          if (new_pos >= 1) {\n            auto saved = t_.at(num);\n            if (erase_at(t_, num)) {\n              insert_at(t_, new_pos, saved);\n            }\n          }\n        } break;\n        }\n      }\n    } while (!done);\n  }\n\n  [[nodiscard]] std::string menu_label() const override {\n    switch (t_.size()) {\n    case 0:\n      return \"[Edit] No actions.\";\n    case 1:\n      return fmt::format(\"[Edit] cmd: '{}'\", t_.at(0).cmd);\n    default:\n      return fmt::format(\"[Edit] {} actions.\", t_.size());\n    }\n  }\n  std::vector<const value::ValueProvider*> providers_;\n};\n\nstatic void edit_menu_item(const Config& config, menus::menu_item_56_t& m, std::vector<const value::ValueProvider*> providers) {\n  EditItems items{};\n  auto y = 1;\n  items.add(new Label(\"Menu Key:\"),\n            new StringEditItem<std::string&>(10, m.item_key, EditLineMode::UPPER_ONLY),\n            \"Key(s) to execute command\", 1, y);\n  y++;\n  items.add(new Label(\"Menu Text:\"),\n            new StringEditItemWithPipeCodes(60, m.item_text, EditLineMode::ALL),\n            \"What to show on generated menu\", 1, y);\n  y++;\n  items.add(new Label(\"Actions:\"), new ActionSubDialog(config, m.actions, providers), \n    \"The actions to execute when this menu is selected\", 1, y);\n  y++;\n  items.add(new Label(\"Help Text:\"),\n            new StringEditItemWithPipeCodes(60, m.help_text, EditLineMode::ALL),\n            \"One line help for command\", 1, y);\n  y++;\n  items.add(new Label(\"Sysop Log:\"),\n            new StringEditItem<std::string&>(50, m.log_text, EditLineMode::ALL),\n            \"What to show in sysop log\", 1, y);\n  y++;\n  items.add(new Label(\"Instance:\"),\n            new StringEditItem<std::string&>(60, m.instance_message, EditLineMode::ALL),\n            \"Instance message to send to all users\", 1, y);\n  y++;\n  items.add(new Label(\"ACS:\"), new ACSEditItem(config, providers, 60, m.acs),\n            \"WWIV ACS required to access this menu item\", 1, y);\n  y++;\n  items.add(new Label(\"Password:\"),\n            new StringEditItem<std::string&>(20, m.password, EditLineMode::UPPER_ONLY),\n            \"Password required to access this menu item\", 1, y);\n  y++;\n  items.add(new Label(\"Visible:\"),\n            new BooleanEditItem(&m.visible),\n            \"Is this item included in the generated menus.\", 1, y);\n\n  items.relayout_items_and_labels();\n  items.Run(StrCat(\"Menu: \", m.item_key));\n}\n\nclass MenuItemsSubDialog : public SubDialog<std::vector<menus::menu_item_56_t>> {\npublic:\n  MenuItemsSubDialog(const Config& config, std::vector<menus::menu_item_56_t>& menu_items,\n    std::vector<const value::ValueProvider*> providers)\n      : SubDialog(config, menu_items), providers_(providers) {}\n  ~MenuItemsSubDialog() override = default;\n\n  void RunSubDialog(CursesWindow* window) override {\n    try {\n      auto done = false;\n      auto selected = -1;\n      do {\n        std::vector<ListBoxItem> items;\n        for (auto i = 0; i < wwiv::stl::ssize(t_); i++) {\n          const auto& m = t_.at(i);\n          auto key = fmt::format(\"({})\", m.item_key);\n          auto s = fmt::format(\"#{} {:<12} '{}'\", i, key, m.item_text);\n          if (!m.actions.empty()) {\n            s += fmt::format(\" [{}]\", m.actions.front().cmd);\n          }\n          items.emplace_back(s, 0, i);\n        }\n        ListBox list(curses_out->window(), \"[Edit Menu Items]\", items);\n\n        list.set_additional_hotkeys(\"DIM\");\n        list.set_help_items(\n            {{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}, {\"M\", \"Move\"}});\n        list.set_selected(selected);\n        auto result = list.Run();\n        window->RedrawWin();\n        selected = list.selected();\n\n        if (result.type == ListBoxResultType::SELECTION) {\n          edit_menu_item(config(), t_[items[result.selected].data()], providers_);\n        } else if (result.type == ListBoxResultType::NO_SELECTION) {\n          done = true;\n        } else if (result.type == ListBoxResultType::HOTKEY) {\n          const auto key = static_cast<char>(result.hotkey);\n          const auto num = result.selected > 0 ? items[result.selected].data() : 0;\n          switch (key) {\n          case 'D': {\n            const auto& item = t_[items[result.selected].data()];\n            if (dialog_yn(window,\n                          StrCat(\"Do you want to delete #\", num, \"[\", item.item_key, \"]\"))) {\n              erase_at(t_, num);\n            }\n          } break;\n          case 'I': {\n            if (num <= 0 || num >= size_int(items)) {\n              t_.push_back({});\n            } else {\n              menus::menu_item_56_t mr{};\n              insert_at(t_, num, mr);\n            }\n          } break;\n          case 'M': {\n            auto maxnum = size_int(t_) + 1;\n            auto prompt = fmt::format(\"Move to before which (1-{}) : \", maxnum);\n            auto new_pos = dialog_input_number(window, prompt, 1, maxnum);\n            if (new_pos >= 1) {\n              auto saved = t_.at(num);\n              if (erase_at(t_, num)) {\n                insert_at(t_, new_pos, saved);\n              }\n            }\n          } break;\n          }\n        }\n      } while (!done);\n    } catch (const std::exception& e) {\n      LOG(ERROR) << e.what();\n    }\n  }\n\n  [[nodiscard]] std::string menu_label() const override { return \"[Edit]\"; }\n  std::vector<const value::ValueProvider*> providers_;\n};\n\n\n// Base item of an editable value, this class does not use templates.\nclass GeneratedMenuSubDialog : public SubDialog<menus::generated_menu_56_t> {\npublic:\n  GeneratedMenuSubDialog() = delete;\n  GeneratedMenuSubDialog(const GeneratedMenuSubDialog&) = delete;\n  GeneratedMenuSubDialog(GeneratedMenuSubDialog&&) = delete;\n  GeneratedMenuSubDialog& operator=(const GeneratedMenuSubDialog&) = delete;\n  GeneratedMenuSubDialog& operator=(GeneratedMenuSubDialog&&) = delete;\n  GeneratedMenuSubDialog(const Config& config, menus::generated_menu_56_t& d)\n      : SubDialog(config, d) {}\n  ~GeneratedMenuSubDialog() override = default;\n\n  void RunSubDialog(CursesWindow* window) override {\n    EditItems items{};\n    constexpr int MAX_STRING_LEN = 10;\n    auto y = 1;\n\n    items.add(new Label(\"Num Columns:\"),\n              new NumberEditItem<int, 1>(&t_.num_cols),\n              \"How many columns should the generated menu contain\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Title Color:\"),\n              new StringEditItem<std::string&>(MAX_STRING_LEN, t_.color_title, EditLineMode::ALL),\n              \"This system's FTN address for use on the network.\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Brace Color:\"),\n              new StringEditItem<std::string&>(MAX_STRING_LEN, t_.color_item_braces, EditLineMode::ALL),\n              \"Pipe code to use to color the braces surrounding the key in generated menus.\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Key Color:\"),\n              new StringEditItem<std::string&>(MAX_STRING_LEN, t_.color_item_key, EditLineMode::ALL),\n              \"Pipe code to use to color each menu item key in generated menus.\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Text Color:\"),\n              new StringEditItem<std::string&>(MAX_STRING_LEN, t_.color_item_text, EditLineMode::ALL),\n              \"Pipe code to use to color the text description in generated menus\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Show Empty:\"),\n              new BooleanEditItem(&t_.show_empty_text),\n              \"Display menu items that have no text.\", 1, y);\n    ++y;\n\n    items.add(new Label(\"Num Newlines:\"),\n              new NumberEditItem<int, 2>(&t_.num_newlines_at_end),\n              \"Number of blank lines to add between generated menu and prompt.\", 1, y);\n    ++y;\n\n    window->GotoXY(x_, y_);\n\n    items.relayout_items_and_labels();\n    items.Run(\"Generated Menu Settings\");\n    window->RedrawWin();\n  }\nprotected:\n  [[nodiscard]] std::string menu_label() const override { return \"[Edit]\"; }\n};\n\n/**\n * EditItem that executes a std::function<T, CursesWindow*> to\n * edit the items. It is intended that this function will invoke\n * a new EditItem dialog or ListBox for editing.\n */\nclass ShowGeneratedMenuSubDialog : public BaseEditItem {\npublic:\n  ShowGeneratedMenuSubDialog(const Config& config, std::vector<const value::ValueProvider*> p,\n                             const wwiv::sdk::menus::MenuSet56& menu_set,\n                             const menus::menu_56_t& menu)\n      : BaseEditItem(10), config_(config), providers_(p), menu_set_(menu_set), menu_(menu) {}\n  ~ShowGeneratedMenuSubDialog() override = default;\n  ShowGeneratedMenuSubDialog() = delete;\n  ShowGeneratedMenuSubDialog(ShowGeneratedMenuSubDialog const&) = delete;\n  ShowGeneratedMenuSubDialog(ShowGeneratedMenuSubDialog&&) = delete;\n  ShowGeneratedMenuSubDialog& operator=(ShowGeneratedMenuSubDialog const&) = delete;\n  ShowGeneratedMenuSubDialog& operator=(ShowGeneratedMenuSubDialog&&) = delete;\n\n  EditlineResult Run(CursesWindow* window) override {\n    auto at_exit = finally([] { curses_out->footer()->SetDefaultFooter(); });\n    curses_out->footer()->ShowHelpItems(0, {});\n    curses_out->footer()->ShowContextHelp(\"Viewing Menu: Press any key to continue.\");\n    window->GotoXY(x_, y_);\n    uint32_t old_attr;\n    short old_pair;\n    window->AttrGet(&old_attr, &old_pair);\n    window->SetColor(SchemeId::EDITLINE);\n    window->PutsXY(x_, y_, menu_label());\n    window->GotoXY(x_, y_);\n    const auto ch = window->GetChar();\n    window->AttrSet(COLOR_PAIR(old_pair) | old_attr);\n    if (ch == KEY_ENTER || ch == wwiv::local::io::TAB || ch == wwiv::local::io::ENTER) {\n      curses_out->Cls();\n      User user{};\n      user.screen_width(80);\n      user.screen_lines(24);\n      user.sl(255);\n      user.dsl(255);\n      const auto lines = wwiv::common::menus::GenerateMenuLines(\n          config_, menu_set_, menu_, user, providers_, menus::menu_type_t::short_menu);\n      auto y = 1;\n      for (const auto& l : lines) {\n        curses_out->window()->PutsWithPipeColors(0, y++, l);\n      }\n      (void) curses_out->window()->GetChar();\n      curses_out->Cls(ACS_CKBOARD);\n      // This clears up everything anyway.\n      curses_out->ReenableLocalIO();\n      window->RedrawWin();\n    } else if (ch == KEY_UP || ch == KEY_BTAB) {\n      return EditlineResult::PREV;\n    } else if (ch == wwiv::local::io::ESC) {\n      return EditlineResult::DONE;\n    }\n    return EditlineResult::NEXT;\n  }\n\n  void Display(CursesWindow* window) const override {\n    window->SetColor(SchemeId::WINDOW_DATA);\n    window->PutsXY(x_, y_, menu_label());\n  }\n\nprotected:\n  [[nodiscard]] virtual std::string menu_label() const { return \"[View]\"; }\n\n  const Config& config_;\n  const std::vector<const value::ValueProvider*> providers_;\n  const wwiv::sdk::menus::MenuSet56& menu_set_;\n  const menus::menu_56_t& menu_;\n};\n\nstatic void edit_settings(const Config& config, wwiv::sdk::menus::MenuSet56& menu_set) {\n  const auto& menu_path = menu_set.menuset_dir();\n\n  const UserManager um(config);\n  User user{};\n  if (!um.readuser(&user, 1)) {\n    user.set_name(\"SYSOP\");\n    user.sl(255);\n    user.dsl(255);\n  }\n  UserValueProvider up(config, user, 255, config.sl(255));\n\n  wwiv::local::io::NullLocalIO null_io;\n  const wwiv::common::SessionContext sess(&null_io);\n  BbsValueProvider bbs_provider(config, sess);\n\n  std::vector<const value::ValueProvider*> providers{&up, &bbs_provider};\n\n  EditItems items{};\n  auto& h = menu_set.menu_set;\n  const auto title = fmt::format(\"Edit Menu Set: {}\", h.name);\n\n  auto y = 1;\n  items.add(new Label(\"Description:\"),\n            new StringEditItem<std::string&>(40, h.description, EditLineMode::ALL),\n            \"Enter the description of this menuset\", 1, y);\n  ++y;\n  items.add(new Label(\"ACS:\"), new ACSEditItem(config, providers, 70, h.acs),\n            \"WWIV ACS required to use this menuset\", 1, y);\n  ++y;\n  items.add(new Label(\"Global Menu Items:\"), new MenuItemsSubDialog(config, h.items, providers),\n            \"Menu items to add to every menu globally\", 1, y);\n  items.relayout_items_and_labels();\n  items.Run(title);\n\n  if (!menu_set.Save()) {\n    messagebox(curses_out->window(), \"Error saving menuset.\");\n  }\n}\n\nstatic void edit_menu(const Config& config, const std::filesystem::path& menu_dir,\n                      const wwiv::sdk::menus::MenuSet56& menu_set, const std::string& menu_name) {\n  menus::Menu56 m(menu_dir, menu_set, menu_name);\n  const auto menu_path = menu_set.menuset_dir();\n\n  if (!m.initialized()) {\n    m.set_initialized(true);\n    m.menu.title = \"New WWIV Menu\";\n  }\n\n  const std::vector<std::pair<wwiv::sdk::menus::menu_numflag_t, std::string>> numbers_action = {\n      {menus::menu_numflag_t::none, \"Nothing\"},\n      {menus::menu_numflag_t::subs, \"Set Sub Number\"},\n      {menus::menu_numflag_t::dirs, \"Set Dir Number\"}};\n\n  const std::vector<std::pair<menus::menu_logtype_t, std::string>> logging_action = {\n      {menus::menu_logtype_t::none, \"Nothing\"},\n      {menus::menu_logtype_t::command, \"Command\"},\n      {menus::menu_logtype_t::key, \"Key\"},\n      {menus::menu_logtype_t::description, \"Description\"}};\n\n  const std::vector<std::pair<menus::menu_help_display_t, std::string>> help_action = {\n      {menus::menu_help_display_t::never, \"Never\"},\n      {menus::menu_help_display_t::always, \"Always\"},\n      {menus::menu_help_display_t::on_entrance, \"On Entrance\"},\n      {menus::menu_help_display_t::user_choice, \"User Choice\"}};\n\n  EditItems items{};\n  const auto title = StrCat(\"Menu: \", menu_name);\n  auto y = 1;\n  auto& h = m.menu;\n\n  const UserManager um(config);\n  User user{};\n  if (!um.readuser(&user, 1)) {\n    user.set_name(\"SYSOP\");\n    user.sl(255);\n    user.dsl(255);\n  }\n  UserValueProvider up(config, user, 255, config.sl(255));\n\n  wwiv::local::io::NullLocalIO null_io;\n  const wwiv::common::SessionContext sess(&null_io);\n  BbsValueProvider bbs_provider(config, sess);\n\n  std::vector<const value::ValueProvider*> providers{&up, &bbs_provider};\n\n  items.add(new Label(\"Title:\"),\n            new StringEditItemWithPipeCodes(55, h.title, EditLineMode::ALL),\n            \"This is the title to display at the top of the menu\", 1, y);\n  y++;\n  items.add(new Label(\"ACS:\"), new ACSEditItem(config, providers, 55, h.acs),\n            \"WWIV ACS required to access this menu\", 1, y);\n  y++;\n  items.add(new Label(\"Number Keys:\"),\n            new ToggleEditItem<menus::menu_numflag_t>(numbers_action, &h.num_action),\n            \"Select what number keys do in this menu\", 1, y);\n  y++;\n  items.add(new Label(\"Logging Type:\"),\n            new ToggleEditItem<menus::menu_logtype_t>(logging_action, &h.logging_action),\n            \"Select what will appear in the sysop log when the user executes the commands\", 1, y);\n  y++;\n  items.add(new Label(\"Display Help:\"),\n            new ToggleEditItem<menus::menu_help_display_t>(help_action, &h.help_type),\n            \"When is the help screen (menu MSG/ANS/or generated help) displayed\", 1, y);\n  y++;\n  items.add(new Label(\"Enter Actions:\"), new ActionSubDialog(config, h.enter_actions, providers),\n            \"Menu actions to execute when entering this menu\", 1, y);\n  y++;\n  items.add(new Label(\"Exit Actions:\"), new ActionSubDialog(config, h.exit_actions, providers),\n            \"Menu actions to execute when leaving this menu\", 1, y);\n  y++;\n  items.add(new Label(\"Password:\"),\n            new StringEditItem<std::string&>(20, h.password, EditLineMode::UPPER_ONLY),\n            \"Password to access menu. You may use '*SYSTEM' for system password.\", 1, y);\n  y++;\n  items.add(new Label(\"Clear Screen:\"),\n            new BooleanEditItem(&h.cls),\n            \"Clear the screen before displaying menu.\", 1, y);\n  y++;\n  items.add(new Label(\"Menu Settings:\"), new GeneratedMenuSubDialog(config, h.generated_menu), \n    \"Edits the settings for a generated menu (not using .msg/.ans file)\", 1, y);\n  y++;\n  const auto p = FilePath(menu_path, StrCat(menu_name, \".pro\"));\n  items.add(new Label(\"Edit Prompt:\"), new EditExternalFileItem(p), 1, y);\n  y++;\n  items.add(new Label(\"Menu Items:\"), new MenuItemsSubDialog(config, h.items, providers), \"\", 1, y);\n  y++;\n  items.add(new Label(\"View Menu:\"), new ShowGeneratedMenuSubDialog(config, providers, menu_set, h), \n    \"Display the generated menu for the sysop user.\", 1, y);\n  y++;\n\n  items.relayout_items_and_labels();\n  items.Run(title);\n\n  if (!m.Save()) {\n    messagebox(curses_out->window(), \"Error saving menu\");\n  }\n}\n\nstatic void select_menu(const wwiv::sdk::Config& config, const std::filesystem::path& menu_dir,\n                        const std::string& dir) {\n  const auto full_dir_path = FilePath(menu_dir, dir);\n  wwiv::sdk::menus::MenuSet56 menu_set(full_dir_path);\n  \n  auto selected = -1;\n  try {\n    auto done{false};\n    do {\n      auto menus = FindFiles(FilePath(full_dir_path, \"*\"), FindFiles::FindFilesType::files,\n                             FindFiles::WinNameType::long_name);\n      std::vector<ListBoxItem> items;\n      for (const auto& m : menus) {\n        auto lm = ToStringLowerCase(m.name);\n        if (!ends_with(lm, \".mnu.json\")) {\n          continue;\n        }\n        const auto name = m.name.substr(0, m.name.size() - 9);\n        items.emplace_back(name);\n      }\n      auto* window = curses_out->window();\n      auto title = StrCat(\"Select Menu from [\", dir, \"]\");\n      ListBox list(window, title, items);\n      list.set_selected(selected);\n      list.set_additional_hotkeys(\"CDIS\");\n      list.set_help_items({{\"Esc\", \"Exit\"},\n                           {\"Enter\", \"Edit\"},\n                           {\"D\", \"Delete\"},\n                           {\"I\", \"Insert\"},\n                           {\"C\", \"Copy\"},\n                           {\"S\", \"Settings\"}});\n      auto result = list.Run();\n      selected = list.selected();\n\n      if (result.type == ListBoxResultType::SELECTION) {\n        const auto& menu_name = items[result.selected].text();\n        edit_menu(config, menu_dir, menu_set, menu_name);\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\n        done = true;\n      } else if (result.type == ListBoxResultType::HOTKEY) {\n        if (result.hotkey == 'I') {\n          auto menu_name = dialog_input_string(window, \"Enter Menu Name: \", 8);\n          if (!menu_name.empty()) {\n            edit_menu(config, menu_dir, menu_set, menu_name);\n          }\n        } else if (result.hotkey == 'C') {\n          const auto& old_menu_name = items[result.selected].text();\n          if (auto menu_name = dialog_input_string(window, \"Enter New Menu Name: \", 8); !menu_name.empty()) {\n            const auto old_name = FilePath(full_dir_path, StrCat(old_menu_name, \".mnu.json\"));\n            const auto new_name = FilePath(full_dir_path, StrCat(menu_name, \".mnu.json\"));\n            File::Copy(old_name, new_name);\n            edit_menu(config, menu_dir, menu_set, menu_name);\n          }\n        } else if (result.hotkey == 'D') {\n          const auto& menu_name = items[result.selected].text();\n          if (dialog_yn(window, StrCat(\"Do you want to delete menu: \", menu_name))) {\n            const auto fn = StrCat(menu_name, \".mnu.json\");\n            const auto ofn = StrCat(fn, \".deleted\");\n            File::Move(FilePath(full_dir_path, fn), FilePath(full_dir_path, ofn));\n          }\n        } else if (result.hotkey == 'S') {\n          edit_settings(config, menu_set);\n        }\n      }\n    } while (!done);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << e.what();\n  }\n}\n\nstatic bool check_for_menu_help(const std::filesystem::path& datadir) {\n  const auto path = FilePath(datadir, \"menu_commands.json\");\n  if (!File::Exists(path)) {\n    auto* window = curses_out->window();\n    const std::vector<std::string> msg{\n        \"menu_commands.json does not exist in the WWIV/datadir.\", \"\",\n        \"Please either run 'bbs -oj' to create it, or copy it from data.zip\",\n        \"in the WWIV installation.\"};\n    messagebox(window, msg);\n    return false;\n  }\n  return true;\n}\n\nvoid menus(const Config& config) {\n  try {\n    const auto menu_dir = config.menudir();\n    if (!check_for_menu_help(config.datadir())) {\n      return;\n    }\n    auto done = false;\n    auto selected = -1;\n    do {\n      auto dirs = FindFiles(FilePath(menu_dir, \"*\"), FindFiles::FindFilesType::directories);\n      std::vector<ListBoxItem> items;\n      for (const auto& d : dirs) {\n        if (starts_with(d.name, \".\")) {\n          continue;\n        }\n        items.emplace_back(d.name);\n      }\n      auto* window = curses_out->window();\n      ListBox list(window, \"Select Menu Set\", items);\n      list.set_selected(selected);\n      list.selection_returns_hotkey(true);\n      list.set_additional_hotkeys(\"I\");\n      list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"/\", \"Filter\"}, {\"I\", \"Insert\"}});\n      const auto result = list.Run();\n      selected = list.selected();\n\n      if (result.type == ListBoxResultType::SELECTION) {\n        const auto& sel_dir = items[result.selected].text();\n        select_menu(config, menu_dir, sel_dir);\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\n        done = true;\n      } else if (result.type == ListBoxResultType::HOTKEY) {\n        switch (result.hotkey) {\n        case 'I':\n          const auto sel_dir = dialog_input_string(window, \"Enter Menu Set Name: \", 8);\n          File::mkdirs(FilePath(menu_dir, sel_dir));\n          break;\n        }\n      }\n    } while (!done);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << e.what();\n  }\n}\n\n"
  },
  {
    "path": "wwivconfig/menus.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                   WWIV Initialization Utility Version 5                */\n/*               Copyright (C)2017-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_MENUS_H\n#define INCLUDED_WWIVCONFIG_MENUS_H\n\n#include \"sdk/config.h\"\n\nvoid menus(const wwiv::sdk::Config& config);\n\n#endif\n"
  },
  {
    "path": "wwivconfig/networks.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n// ReSharper disable CppAssignedValueIsNeverUsed\r\n#include \"sdk/net/networks.h\"\r\n#include \"wwivconfig/networks.h\"\r\n\r\n#include \"core/file.h\"\r\n#include \"core/log.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"fmt/printf.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/subxtr.h\"\r\n#include \"sdk/vardec.h\"\r\n#include \"sdk/fido/fido_callout.h\"\r\n#include \"wwivconfig/subacc.h\"\r\n#include \"wwivconfig/utility.h\"\r\n\r\n#include <cstring>\r\n#include <string>\r\n#include <utility>\r\n#include <vector>\r\n\r\nconstexpr ssize_t MAX_NETWORKS = 100;\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::sdk;\r\nusing namespace wwiv::sdk::fido;\r\nusing namespace wwiv::sdk::net;\r\nusing namespace wwiv::strings;\r\n\r\nstatic bool del_net(const Config& config, Networks& networks, int nn) {\r\n  Subs subs(config.datadir(), networks.networks());\r\n  if (!subs.Load()) {\r\n    return false;\r\n  }\r\n  if (subs.subs().empty()) {\r\n    return false;\r\n  }\r\n\r\n  // TODO(rushfan): Ensure that no subs are using it.\r\n  for (auto i = 0; i < wwiv::stl::ssize(subs.subs()); i++) {\r\n    int i2;\r\n    for (i2 = 0; i2 < i; i2++) {\r\n      if (subs.sub(i).filename == subs.sub(i2).filename) {\r\n        break;\r\n      }\r\n    }\r\n    if (i2 >= i) {\r\n      iscan1(i, subs, config);\r\n      open_sub(true);\r\n      for (auto i1 = 1; i1 <= GetNumMessagesInCurrentMessageArea(); i1++) {\r\n        auto p = get_post(i1);\r\n        if (!p) {\r\n          continue;\r\n        }\r\n        if (!(p->status & status_post_new_net)) {\r\n          continue;\r\n        }\r\n        if (p->network.network_msg.net_number == nn) {\r\n          p->network.network_msg.net_number = static_cast<uint8_t>('\\xff');\r\n        } else if (p->network.network_msg.net_number > nn) {\r\n          p->network.network_msg.net_number--;\r\n        }\r\n        write_post(i1, p.value());\r\n      }\r\n      close_sub();\r\n    }\r\n  }\r\n\r\n  // Now we update the email.\r\n  File emailfile(FilePath(config.datadir(), EMAIL_DAT));\r\n  if (emailfile.Open(File::modeBinary | File::modeReadWrite)) {\r\n    auto t = static_cast<int>(emailfile.length() / sizeof(mailrec));\r\n    for (auto r = 0; r < t; r++) {\r\n      mailrec m = {};\r\n      emailfile.Seek(r * sizeof(mailrec), File::Whence::begin);\r\n      emailfile.Read(&m, sizeof(mailrec));\r\n      if (((m.tosys != 0) || (m.touser != 0)) && m.fromsys) {\r\n        if (strnlen(m.title, WWIV_MESSAGE_TITLE_LENGTH) >= WWIV_MESSAGE_TITLE_LENGTH) {\r\n          // always trim to WWIV_MESSAGE_TITLE_LENGTH now.\r\n          m.title[WWIV_MESSAGE_TITLE_LENGTH - 1] = 0;\r\n        }\r\n        m.status |= status_new_net;\r\n        if (m.status & status_source_verified) {\r\n          if (m.network.src_verified_msg.net_number == nn) {\r\n            m.network.src_verified_msg.net_number = static_cast<uint8_t>('\\xff');\r\n          } else if (m.network.src_verified_msg.net_number > nn) {\r\n            m.network.src_verified_msg.net_number--;\r\n          }\r\n        } else {\r\n          if (m.network.network_msg.net_number == nn) {\r\n            m.network.network_msg.net_number = static_cast<uint8_t>('\\xff');\r\n          } else if (m.network.network_msg.net_number > nn) {\r\n            m.network.network_msg.net_number--;\r\n          }\r\n        }\r\n        emailfile.Seek(r * sizeof(mailrec), File::Whence::begin);\r\n        emailfile.Write(&m, sizeof(mailrec));\r\n      }\r\n    }\r\n  }\r\n\r\n  // Update the user\r\n  userrec u{};\r\n  const auto nu = number_userrecs(config.datadir());\r\n  for (auto i = 1; i <= nu; i++) {\r\n    read_user(config, i, &u);\r\n    if (u.net_num == nn) {\r\n      u.forwardsys = u.forwardusr = u.net_num = 0;\r\n      write_user(config, i, &u);\r\n    } else if (u.net_num > nn) {\r\n      u.net_num--;\r\n      write_user(config, i, &u);\r\n    }\r\n  }\r\n\r\n  // Finally delete it from networks.dat\r\n  networks.erase(nn);\r\n  return networks.Save();\r\n}\r\n\r\n// Base item of an editable value, this class does not use templates.\r\nclass FidoNetworkConfigSubDialog : public SubDialog<Network> {\r\npublic:\r\n  FidoNetworkConfigSubDialog(const Config& config, std::filesystem::path netdir,\r\n                             Network& d)\r\n      : SubDialog(config, d), netdir_(std::move(netdir)) {}\r\n  ~FidoNetworkConfigSubDialog() override = default;\r\n\r\n  void RunSubDialog(CursesWindow* window) override {\r\n    EditItems items{};\r\n    if (t_.type != network_type_t::ftn) {\r\n      return;\r\n    }\r\n    constexpr int MAX_STRING_LEN = 56;\r\n    auto* n = &t_.fido;\r\n    auto y = 1;\r\n\r\n    items.add(new Label(\"FTN Address:\"),\r\n              new FidoAddressStringEditItem(MAX_STRING_LEN, n->fido_address),\r\n              \"The FTN address for this system (example 21:9/123@fsxnet).\", 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Nodelist Base:\"),\r\n              new StringEditItem<std::string&>(MAX_STRING_LEN, n->nodelist_base, EditLineMode::ALL),\r\n      \"Base filename for the nodelist without path or extension. (e.g. FSXNET)\", 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Backbone File:\"),\r\n              new StringEditItem<std::string&>(MAX_STRING_LEN, n->backbone_filename, EditLineMode::ALL),\r\n              \"Filename of ECHOLIST in BACKBONE.NA format (e.g. FSXNET.NA)\", 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Inbound Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->inbound_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Temp In Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->temp_inbound_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Temp Out Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->temp_outbound_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Outbound Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->outbound_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"NetMail Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->netmail_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"BadPacket Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->bad_packets_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"TIC Dir:\"), new StringFilePathItem(MAX_STRING_LEN, netdir_, n->tic_dir), 1,\r\n              y);\r\n    ++y;\r\n    items.add(new Label(\"Unknown Dir:\"),\r\n              new StringFilePathItem(MAX_STRING_LEN, netdir_, n->unknown_dir), 1, y);\r\n    ++y;\r\n    items.add(new Label(\"Origin Line:\"),\r\n              new StringEditItem<std::string&>(MAX_STRING_LEN, n->origin_line, EditLineMode::ALL),\r\n      \"Origin line to add to outgoing echomail messages from this system\", \r\n              1, y);\r\n    ++y;\r\n    const std::vector<std::pair<fido_mailer_t, std::string>> mailerlist = {\r\n        {fido_mailer_t::flo, \"BSO (FLO) [Recommended]\"},\r\n        {fido_mailer_t::attach, \"NetMail (ATTACH)\"}};\r\n    items.add(new Label(\"Mailer:\"), new ToggleEditItem<fido_mailer_t>(mailerlist, &n->mailer_type),\r\n              \"Select BSO if using WWIV's Native BinkP.\", 1, y);\r\n    dy_start_ = y++;\r\n\r\n    const std::vector<std::pair<fido_transport_t, std::string>> transportlist = {\r\n        {fido_transport_t::directory, \"Directory\"}, {fido_transport_t::binkp, \"WWIV BinkP\"}};\r\n    items.add(new Label(\"Transport:\"),\r\n              new ToggleEditItem<fido_transport_t>(transportlist, &n->transport),\r\n              \"This isn't currently used, but you likely want WWIV BinkP\", 1, y);\r\n    ++y;\r\n\r\n    items.add(new Label(\"Max Age:\"), new NumberEditItem<int>(&n->max_echomail_age_days),\r\n              \"Max number of days old a packet is allowed to be and still be imported. 0=any\", 1,\r\n              y);\r\n    ++y;\r\n\r\n    //////////////////////////////////////////////////////////////////////////////////////\r\n    // New column: dy_start\r\n\r\n    auto dy = dy_start_;\r\n    items.add(new Label(\"Process TIC  :\"), new BooleanEditItem(&n->process_tic),\r\n              \"Process TIC files for this network.\", 3, dy);\r\n    ++dy;\r\n    items.add(new Label(\"Cvt Hearts   :\"), new BooleanEditItem(&n->wwiv_heart_color_codes),\r\n              \"Convert WWIV Heart codes into PIPE color codes.\", 3, dy);\r\n    ++dy;\r\n    items.add(new Label(\"Cvt WWIV Pipe:\"), new BooleanEditItem(&n->wwiv_pipe_color_codes),\r\n              \"Convert WWIV user color pipe codes into standard PIPE color codes.\", 3, dy);\r\n    ++dy;\r\n    items.add(new Label(\"Allow Pipe Codes:\"), new BooleanEditItem(&n->allow_any_pipe_codes),\r\n              \"Allow pipe codes, don't strip outbound PIPE codes.\", 3, dy);\r\n    ++dy;\r\n    window->GotoXY(x_, y_);\r\n\r\n    items.add_aligned_width_column(1);\r\n    items.relayout_items_and_labels();\r\n    items.Run(menu_label());\r\n    window->RedrawWin();\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path netdir_;\r\n  int dy_start_{0};\r\n};\r\n\r\nstatic void edit_fido_node_config(const FidoAddress& a, fido_node_config_t& n) {\r\n  auto& p = n.packet_config;\r\n  EditItems items{};\r\n  const std::vector<std::pair<fido_packet_t, std::string>> packetlist = {\r\n      {fido_packet_t::unset, \"unset\"}, {fido_packet_t::type2_plus, \"FSC-0039 Type 2+\"}};\r\n\r\n  auto y = 1;\r\n  auto& b = n.binkp_config;\r\n  items.add(new Label(\"BinkP Host:\"),\r\n            new StringEditItem<std::string&>(40, b.host, EditLineMode::ALL),\r\n            \"BinkP hostname to override default from nodelist\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"BinkP Port:\"), new NumberEditItem<int>(&b.port),\r\n            \"BinkP post number to override default from nodelist\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Session PW:\"),\r\n            new StringEditItem<std::string&>(8, b.password, EditLineMode::UPPER_ONLY),\r\n            \"BinkP password to use when connection to this host.\", 1, y);\r\n  y += 2;\r\n\r\n  items.add(new Label(\"Routes:\"), new StringEditItem<std::string&>(40, n.routes, EditLineMode::ALL),\r\n            \"Systems who route this this host. i.e. 1:*\", 1, y);\r\n\r\n  ++y;\r\n  items.add(new Label(\"Packet Type:\"),\r\n            new ToggleEditItem<fido_packet_t>(packetlist, &p.packet_type), 1, y);\r\n  y++;\r\n  items.add(new Label(\"Compression:\"),\r\n            new StringListItem({\"ZIP\", \"ARC\", \"PKT\", \"\"}, p.compression_type), 1, y);\r\n  y++;\r\n  items.add(new Label(\"Max Arc Size:\"), new NumberEditItem<int>(&p.max_archive_size),\r\n            \"NOT IMPLEMENTED YET\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Max Pkt Size:\"), new NumberEditItem<int>(&p.max_packet_size),\r\n            \"NOT IMPLEMENTED YET\", 1, y);\r\n\r\n  const std::vector<std::pair<fido_bundle_status_t, std::string>> bundlestatuslist = {\r\n      {fido_bundle_status_t::normal, \"Normal\"}, {fido_bundle_status_t::crash, \"Crash\"},\r\n      {fido_bundle_status_t::direct, \"Direct\"}, {fido_bundle_status_t::immediate, \"Immediate\"},\r\n      {fido_bundle_status_t::hold, \"Hold\"},\r\n  };\r\n  y++;\r\n  items.add(new Label(\"Bundle Status:\"),\r\n            new ToggleEditItem<fido_bundle_status_t>(bundlestatuslist, &p.netmail_status),\r\n            \"Default bundle status to use when creating FTN Bundles\", 1, y);\r\n  y += 2;\r\n  auto y2 = y;\r\n  items.add(new Label(\"Packet PW:\"),\r\n            new StringEditItem<std::string&>(8, p.packet_password, EditLineMode::UPPER_ONLY),\r\n            \"Password to use in the FTN packet.\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Tic PW:\"),\r\n            new StringEditItem<std::string&>(8, p.tic_password, EditLineMode::UPPER_ONLY),\r\n            \"If set, the password an incoming TIC file must use.\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"AreaFix PW:\"),\r\n            new StringEditItem<std::string&>(8, p.areafix_password, EditLineMode::UPPER_ONLY),\r\n            \"NOT IMPLEMENTED YET\", 1, y);\r\n  y = y2;\r\n\r\n  auto& c = n.callout_config;\r\n  items.add(new Label(\"Auto Callout:\"), new BooleanEditItem(&c.auto_callouts),\r\n            \"Should wwivd automatically call out to this node?\", 3, y);\r\n  y++;\r\n  items.add(new Label(\"Every N min:\"),\r\n            new NumberEditItem<decltype(c.call_every_x_minutes)>(&c.call_every_x_minutes),\r\n            \"Force a callout every N minutes.\", 3, y);\r\n  y++;\r\n  items.add(new Label(\"Min K:\"), new NumberEditItem<decltype(c.min_k)>(&c.min_k),\r\n            \"Attempt callout sooner if a packet is larger than this size in (K)ilobytes\", 3, y);\r\n\r\n  items.add_aligned_width_column(1);\r\n  items.relayout_items_and_labels();\r\n  items.Run(StrCat(\"Address: \", a.as_string(true, true)));\r\n}\r\n\r\n// Base item of an editable value, this class does not use templates.\r\nclass FidoPacketConfigSubDialog : public SubDialog<Network> {\r\npublic:\r\n  FidoPacketConfigSubDialog(const Config& config, std::filesystem::path bbsdir, Network& t)\r\n      : SubDialog(config, t), netdir_(std::move(bbsdir)) {}\r\n  ~FidoPacketConfigSubDialog() override = default;\r\n\r\n  void RunSubDialog(CursesWindow* window) override {\r\n    window->GotoXY(x_, y_);\r\n    FidoCallout callout(config().root_directory(), config().max_backups(), t_);\r\n    if (!callout.IsInitialized()) {\r\n      messagebox(window, \"Unable to initialize fido_callout.json.\");\r\n      return;\r\n    }\r\n    auto done = false;\r\n    do {\r\n      std::vector<ListBoxItem> items;\r\n      for (const auto& e : callout.node_configs_map()) {\r\n        items.emplace_back(e.first.as_string());\r\n      }\r\n      ListBox list(window, \"Select Address\", items);\r\n\r\n      list.selection_returns_hotkey(true);\r\n      list.set_additional_hotkeys(\"DI\");\r\n      list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\r\n      if (auto result = list.Run(); result.type == ListBoxResultType::HOTKEY) {\r\n        switch (result.hotkey) {\r\n        case 'D': {\r\n          if (items.empty()) {\r\n            break;\r\n          }\r\n          if (!dialog_yn(window, StrCat(\"Delete '\", items[result.selected].text(), \"' ?\"))) {\r\n            break;\r\n          }\r\n          if (const auto o = try_parse_fidoaddr(items[result.selected].text())) {\r\n            callout.erase(o.value());\r\n          }\r\n        } break;\r\n        case 'I': {\r\n          const std::string prompt = \"Enter Address (Z:N/O) : \";\r\n          const auto address_string = dialog_input_string(window, prompt, 20);\r\n          if (address_string.empty()) {\r\n            break;\r\n          }\r\n          FidoAddress address(address_string);\r\n          fido_node_config_t config{};\r\n          config.binkp_config.port = 24554;\r\n          edit_fido_node_config(address, config);\r\n          callout.insert(address, config);\r\n        } break;\r\n        }\r\n      } else if (result.type == ListBoxResultType::SELECTION) {\r\n        const auto address_string = wwiv::stl::at(items, result.selected).text();\r\n        FidoAddress address(address_string);\r\n        auto c = callout.fido_node_config_for(address);\r\n        edit_fido_node_config(address, c);\r\n        callout.insert(address, c);\r\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n        done = true;\r\n      }\r\n    } while (!done);\r\n    callout.Save();\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path netdir_;\r\n  const std::string title_;\r\n};\r\n\r\nstatic void edit_wwivnet_node_config(const Network& net, net_call_out_rec& c) {\r\n  int y = 1;\r\n\r\n  EditItems items{};\r\n  items.add(new Label(\"Password:\"),\r\n            new StringEditItem<std::string&>(20, c.session_password, EditLineMode::ALL),\r\n            \"WWIVnet password to use when connecting to this node\", 1, y);\r\n\r\n  y++;\r\n  items.add(new Label(\"Allow Outbound Connections:\"),\r\n            new FlagEditItem<decltype(c.options)>(options_no_call, \"No\", \"Yes\", &c.options),\r\n            \"Is our system allowed to callout to this one?\", 1, y);\r\n  y += 2;\r\n  items.add(new Label(\"Call every N minutes:\"),\r\n            new NumberEditItem<decltype(c.call_every_x_minutes)>(&c.call_every_x_minutes),\r\n            \"Automatically call out every N minutes\", 1, y);\r\n\r\n  y++;\r\n  items.add(new Label(\"Call when minimum k waiting:\"),\r\n            new NumberEditItem<decltype(c.min_k)>(&c.min_k),\r\n            \"Automatically call out when K kilobytes of packet is pending\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Call between hours of:\"), new NumberEditItem<int8_t>(&c.min_hr),\r\n            \"Only call automatically between the house of X and Y\", 1, y);\r\n  items.add(new Label(\"and:\"), new NumberEditItem<int8_t>(&c.max_hr),\r\n            \"Only call automatically between the house of X and Y\", 3, y);\r\n  y++;\r\n  items.add(new Label(\"Hide from Pending List:\"),\r\n            new FlagEditItem<decltype(c.options)>(options_hide_pend, \"Yes \", \"No\", &c.options),\r\n            \"Hide this node from the WFC pending system display\", 1, y);\r\n\r\n  items.add_aligned_width_column(1);\r\n  items.relayout_items_and_labels();\r\n  items.Run(StrCat(\"Node: @\", c.sysnum, \".\", net.name));\r\n}\r\n\r\n// Base item of an editable value, this class does not use templates.\r\nclass CalloutNetSubDialog final : public SubDialog<Network> {\r\npublic:\r\n  CalloutNetSubDialog(const Config& config, std::filesystem::path bbsdir, Network& d)\r\n      : SubDialog(config, d), netdir_(std::move(bbsdir)) {}\r\n  ~CalloutNetSubDialog() override = default;\r\n\r\n  void RunSubDialog(CursesWindow* window) override {\r\n    Callout callout(t_, config().max_backups());\r\n    auto done = false;\r\n    do {\r\n      std::vector<ListBoxItem> items;\r\n      for (const auto& e : callout.callout_config()) {\r\n        items.emplace_back(StrCat(\"@\", e.first));\r\n      }\r\n      ListBox list(window, \"Select Address\", items);\r\n\r\n      list.selection_returns_hotkey(true);\r\n      list.set_additional_hotkeys(\"DI\");\r\n      list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\r\n      auto result = list.Run();\r\n      if (result.type == ListBoxResultType::HOTKEY) {\r\n        switch (result.hotkey) {\r\n        case 'D': {\r\n          if (items.empty()) {\r\n            break;\r\n          }\r\n          if (!dialog_yn(window, StrCat(\"Delete '\", items[result.selected].text(), \"' ?\"))) {\r\n            break;\r\n          }\r\n          const auto node_with_at = items[result.selected].text();\r\n          if (node_with_at.size() > 1) {\r\n            const auto node = to_number<uint16_t>(node_with_at.substr(1));\r\n            callout.erase(node);\r\n          }\r\n        } break;\r\n        case 'I': {\r\n          const std::string prompt = \"Enter Address (Node number only) : @\";\r\n          const auto address_string = dialog_input_string(window, prompt, 20);\r\n          if (address_string.empty()) {\r\n            break;\r\n          }\r\n          auto node_number = to_number<uint16_t>(address_string);\r\n          if (0 == node_number) {\r\n            break;\r\n          }\r\n          net_call_out_rec config{};\r\n          config.sysnum = node_number;\r\n          edit_wwivnet_node_config(t_, config);\r\n          callout.insert(node_number, config);\r\n        } break;\r\n        }\r\n      } else if (result.type == ListBoxResultType::SELECTION) {\r\n        if (const auto node_with_at = items[result.selected].text(); node_with_at.size() > 1) {\r\n          const auto node = to_number<uint16_t>(node_with_at.substr(1));\r\n          if (const auto* c1 = callout.net_call_out_for(node); c1 != nullptr) {\r\n            auto c = *c1;\r\n            edit_wwivnet_node_config(t_, c);\r\n            callout.insert(node, c);\r\n          }\r\n        }\r\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n        done = true;\r\n      }\r\n    } while (!done);\r\n    callout.Save();\r\n  }\r\n\r\nprivate:\r\n  const std::filesystem::path netdir_;\r\n};\r\n\r\nstatic void edit_net(const Config& config, Networks& networks, int nn) {\r\n  const std::vector<std::pair<network_type_t, std::string>> nettypes{\r\n      {network_type_t::wwivnet, \"WWIVnet \"},\r\n      {network_type_t::ftn, \"Fido    \"},\r\n      {network_type_t::internet, \"Internet\"},\r\n      {network_type_t::news, \"Newsgroup (not supported yet)\"}};\r\n\r\n  Subs subs(config.datadir(), networks.networks());\r\n  const auto subs_loaded = subs.Load();\r\n\r\n  auto& n = wwiv::stl::at(networks, nn);\r\n  const auto orig_network_name(n.name);\r\n\r\n  auto y = 1;\r\n  EditItems items{};\r\n  items.add(new Label(\"Net Name:\"), new StringEditItem<std::string&>(15, n.name, EditLineMode::ALL),\r\n            \"Name of the network to use to display to bbs callers\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Directory:\"), new FileSystemFilePathItem(60, config.root_directory(), n.dir),\r\n            1, y);\r\n  y++;\r\n\r\n  const auto net_dir = File::absolute(config.root_directory(), n.dir);\r\n  if (n.type == network_type_t::ftn) {\r\n    items.add(new Label(\"Auto Add Subs:\"), new BooleanEditItem(&n.settings.auto_add),\r\n              \"When importing echomail, automatically add WWIV subs that don't exist\", 1, y);\r\n    y++;\r\n    items.add(new Label(\"Auto Add INI:\"),\r\n              new StringFileNameItem(60, n.dir, n.settings.auto_add_ini),\r\n              \"INI file to use for defaults when automatically creating missing subs\", 1, y);\r\n    y++;\r\n    items.add(new Label(\"Settings:\"), new FidoNetworkConfigSubDialog(config, net_dir, n),\r\n              \"Edit settings for this network\", 1, y);\r\n    y++;\r\n    items.add(new Label(\"Addresses:\"), new FidoPacketConfigSubDialog(config, net_dir, n),\r\n              \"Configure settings for systems allowed to connect in this network\", 1, y);\r\n    y++;\r\n  } else if (n.type == network_type_t::wwivnet) {\r\n    items.add(new Label(\"Node #:\"), new NumberEditItem<uint16_t>(&n.sysnum), \"WWIVnet node number\",\r\n              1, y);\r\n    y++;\r\n    items.add(new Label(\"Callout.net:\"), new CalloutNetSubDialog(config, net_dir, n), \r\n      \"Edit the settings that define when to call out to a remote system\", 1, y);\r\n    y++;\r\n  }\r\n\r\n  const auto title = fmt::format(\"Net: {} [.{}] ({})\", n.name, nn,\r\n                                 StringTrim(wwiv::stl::at(nettypes, static_cast<int>(n.type)).second));\r\n\r\n  items.relayout_items_and_labels();\r\n  items.Run(title);\r\n\r\n  if (subs_loaded && orig_network_name != n.name) {\r\n    subs.Save();\r\n  }\r\n\r\n  networks.Save();\r\n}\r\n\r\nstatic bool insert_net(const Config& config, Networks& networks, int nn, network_type_t type) {\r\n  Subs subs(config.datadir(), networks.networks());\r\n  if (!subs.Load()) {\r\n    return false;\r\n  }\r\n  if (subs.subs().empty()) {\r\n    return false;\r\n  }\r\n\r\n  for (auto i = 0; i < wwiv::stl::ssize(subs.subs()); i++) {\r\n    auto i2 = 0;\r\n    for (i2 = 0; i2 < i; i2++) {\r\n      if (subs.sub(i).filename == subs.sub(i2).filename) {\r\n        break;\r\n      }\r\n    }\r\n    if (i2 >= i) {\r\n      iscan1(i, subs, config);\r\n      open_sub(true);\r\n      for (auto i1 = 1; i1 <= GetNumMessagesInCurrentMessageArea(); i1++) {\r\n        auto p = get_post(i1);\r\n        if (!p) {\r\n          continue;\r\n        }\r\n        if (p->status & status_post_new_net) {\r\n          if (p->network.network_msg.net_number >= nn) {\r\n            p->network.network_msg.net_number++;\r\n            write_post(i1, p.value());\r\n          }\r\n        }\r\n      }\r\n      close_sub();\r\n    }\r\n  }\r\n\r\n  // same as del_net, don't think we need to do this here.\r\n  // wwiv::sdk::write_subs(config.datadir(), subboards);\r\n  File emailfile(FilePath(config.datadir(), EMAIL_DAT));\r\n  if (emailfile.Open(File::modeBinary | File::modeReadWrite)) {\r\n    auto t = static_cast<int>(emailfile.length() / sizeof(mailrec));\r\n    for (auto r = 0; r < t; r++) {\r\n      mailrec m{};\r\n      emailfile.Seek(sizeof(mailrec) * r, File::Whence::begin);\r\n      emailfile.Read(&m, sizeof(mailrec));\r\n      if ((m.tosys != 0 || m.touser != 0) && m.fromsys) {\r\n        if (strlen(m.title) >= WWIV_MESSAGE_TITLE_LENGTH) {\r\n          // always trim to WWIV_MESSAGE_TITLE_LENGTH now.\r\n          m.title[71] = 0;\r\n        }\r\n        m.status |= status_new_net;\r\n        if (m.status & status_source_verified) {\r\n          if (m.network.src_verified_msg.net_number >= nn) {\r\n            m.network.src_verified_msg.net_number++;\r\n          }\r\n        } else {\r\n          if (m.network.network_msg.net_number >= nn) {\r\n            m.network.network_msg.net_number++;\r\n          }\r\n        }\r\n        emailfile.Seek(sizeof(mailrec) * r, File::Whence::begin);\r\n        emailfile.Write(&m, sizeof(mailrec));\r\n      }\r\n    }\r\n  }\r\n\r\n  userrec u{};\r\n  auto nu = number_userrecs(config.datadir());\r\n  for (auto i = 1; i <= nu; i++) {\r\n    read_user(config, i, &u);\r\n    if (u.net_num >= nn) {\r\n      u.net_num++;\r\n      write_user(config, i, &u);\r\n    }\r\n  }\r\n\r\n  {\r\n    Network n{};\r\n    n.type = type;\r\n    if (type == network_type_t::ftn) {\r\n      n.sysnum = 1;\r\n      n.name = \"New FTNNet\";\r\n      auto& f = n.fido;\r\n      f.bad_packets_dir = File::EnsureTrailingSlash(\"badpackets\");\r\n      f.inbound_dir = File::EnsureTrailingSlash(\"in\");\r\n      f.netmail_dir = File::EnsureTrailingSlash(\"netmail\");\r\n      f.outbound_dir = File::EnsureTrailingSlash(\"out\");\r\n      f.tic_dir = File::EnsureTrailingSlash(\"tic\");\r\n      f.temp_outbound_dir = File::EnsureTrailingSlash(\"tempout\");\r\n      f.temp_inbound_dir = File::EnsureTrailingSlash(\"tempin\");\r\n      f.unknown_dir = File::EnsureTrailingSlash(\"unknown\");\r\n    } else if (type == network_type_t::wwivnet) {\r\n      n.name = \"New WWIVnet\";\r\n    }\r\n    n.dir = File::EnsureTrailingSlash(\"newnet.dir\");\r\n    networks.insert(nn, n);\r\n  }\r\n\r\n  edit_net(config, networks, nn);\r\n  return true;\r\n}\r\n\r\nvoid networks(const wwiv::sdk::Config& config, std::set<int>& need_network3) {\r\n  try {\r\n    Networks networks(config);\r\n\r\n    bool done = false;\r\n    do {\r\n      std::vector<ListBoxItem> items;\r\n      int num = 0;\r\n      for (const auto& n : networks.networks()) {\r\n        items.emplace_back(fmt::sprintf(\"@%-5u %-16s [.%d]\", n.sysnum, n.name, num++));\r\n      }\r\n      auto* window = curses_out->window();\r\n      ListBox list(window, \"Select Network\", items);\r\n\r\n      list.selection_returns_hotkey(true);\r\n      list.set_additional_hotkeys(\"DI\");\r\n      list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\r\n      auto result = list.Run();\r\n\r\n      if (result.type == ListBoxResultType::SELECTION) {\r\n        edit_net(config, networks, result.selected);\r\n        need_network3.insert(result.selected);\r\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n        done = true;\r\n      } else if (result.type == ListBoxResultType::HOTKEY) {\r\n        switch (result.hotkey) {\r\n        case 'D':\r\n          if (networks.networks().size() > 1) {\r\n            const auto prompt = fmt::format(\"Delete '{}'\", wwiv::stl::at(networks, result.selected).name);\r\n            auto yn = dialog_yn(window, prompt);\r\n            if (yn) {\r\n              yn = dialog_yn(window, \"Are you REALLY sure? \");\r\n              if (yn) {\r\n                del_net(config, networks, result.selected);\r\n              }\r\n            }\r\n          } else {\r\n            messagebox(window, \"You must leave at least one network.\");\r\n          }\r\n          break;\r\n        case 'I':\r\n          if (networks.networks().size() >= MAX_NETWORKS) {\r\n            messagebox(window, \"Too many networks.\");\r\n            break;\r\n          }\r\n          const auto prompt =\r\n              fmt::format(\"Insert before which (1-{}) ? \", networks.networks().size() + 1);\r\n          const auto net_num =\r\n              dialog_input_number(window, prompt, 1, wwiv::stl::size_int(networks.networks()) + 1);\r\n          if (net_num > 0 && net_num <= wwiv::stl::ssize(networks.networks()) + 1) {\r\n\r\n            const std::vector<std::string> nettypes{\r\n                {\"WWIVnet \"}, {\"Fido    \"}, {\"Internet\"}, {\"Newsgroup (not supported yet)\"}};\r\n            const auto net_type =\r\n                input_select_item(window, \"Select Network Type of (Q) to Quit: \", nettypes);\r\n            if (net_type == 'Q') {\r\n              continue;\r\n            }\r\n            if (dialog_yn(window, \"Are you sure? \")) {\r\n              insert_net(config, networks, net_num - 1,\r\n                         static_cast<network_type_t>(net_type - '0'));\r\n              need_network3.insert(net_num - 1);\r\n            }\r\n          }\r\n          break;\r\n        }\r\n      }\r\n    } while (!done);\r\n    networks.Save();\r\n  } catch (const std::exception& e) {\r\n    LOG(ERROR) << e.what();\r\n  }\r\n}\r\n"
  },
  {
    "path": "wwivconfig/networks.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_NETWORKS_H\r\n#define INCLUDED_WWIVCONFIG_NETWORKS_H\r\n\r\n#include \"sdk/config.h\"\r\n#include <set>\r\n\r\nvoid networks(const wwiv::sdk::Config& config, std::set<int>& need_network3);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_NETWORKS_H\r\n"
  },
  {
    "path": "wwivconfig/new_user.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/new_user.h\"\n\n#include \"core/strings.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n\n#include <cstdint>\n#include <string>\n\nusing namespace wwiv::local::ui;\nusing namespace wwiv::strings;\n\nvoid newuser_settings(wwiv::sdk::Config& config, wwiv::sdk::newuser_config_t& nc, CursesWindow*) {\n  const std::vector<std::pair<wwiv::sdk::newuser_item_type_t, std::string>> newuser_item_type_list =\n      {{wwiv::sdk::newuser_item_type_t::unused, \"Unused\"},\n       {wwiv::sdk::newuser_item_type_t::optional, \"Optional\"},\n       {wwiv::sdk::newuser_item_type_t::required, \"Required\"}};\n\n  auto closed_system = config.closed_system();\n  auto newuser_gold = static_cast<int>(config.newuser_gold());\n  auto newuser_pw = config.newuser_password();\n  auto newusersl = config.newuser_sl();\n  auto newuserdsl = config.newuser_dsl();\n  auto newuser_restrict = config.newuser_restrict();\n  const auto validated_sl = config.validated_sl();\n\n  auto y = 1;\n  EditItems items{};\n  items.add(new Label(\"Closed system:\"),\n            new BooleanEditItem(&closed_system),\n    \"Are users allowed to establish accounts on this BBS\", 1, y);\n  items.add(\n      new Label(\"Password:\"),\n      new StringEditItem<std::string&>(20, newuser_pw, EditLineMode::UPPER_ONLY),\n    \"Optional password users must provide in order create an account\", 3, y);\n  ++y;\n  items.add(new Label(\"SL:\"),\n            new NumberEditItem<uint8_t>(&newusersl),\n    \"The security level that all new users are given. The default is 10\", 1, y);\n  items.add(new Label(\"DSL:\"),\n            new NumberEditItem<uint8_t>(&newuserdsl),\n        \"The download security level that all new users are given. The default is 10\", 3, y);\n  ++y;\n  items.add(new Label(\"Gold:\"),\n            new NumberEditItem<int>(&newuser_gold),\n    \"The default amount of gold given to new users\", 1, y);\n  items.add(new Label(\"Restrict:\"),\n            new RestrictionsEditItem(&newuser_restrict),\n    \"Restrictions given to new users from certain features of the system.\", 3, y);\n  ++y;\n  items.add(new Label(\"Validated SL:\"),\n            new NumberEditItem<uint8_t>(&newusersl),\n    \"The lowest security level that means validated. For autoval set this == Newuser SL\", 1, y);\n\n  ++y;\n  ++y;\n  items.add(new Label(\"Real Name:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_real_name),\n    \"Ask Callers for a real name. This may be needed for some networks\", 1, y);\n  items.add(new Label(\"First & Last Name Required:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.first_last_name_required),\n    \"Require both a first and last name if real name is required\", 3, y);\n  ++y;\n  items.add(new Label(\"Email Address:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_email_address),\n    \"Ask callers for an email address\", 1, y);\n  ++y;\n  ++y;\n  items.add(new Label(\"Voice Phone:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_voice_phone),\n    \"Ask Callers for a void phone number\", 1, y);\n  items.add(new Label(\"Data Phone:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_data_phone),\n    \"Ask callers for a modem/data phone number\", 3, y);\n  ++y;\n  items.add(new Label(\"Street Address:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_address_street),\n    \"Ask Callers for a street address\", 1, y);\n  items.add(new Label(\"City/State:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_address_city_state),\n    \"Ask callers the city they are calling from\", 3, y);\n  ++y;\n  items.add(new Label(\"ZipCode:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_address_zipcode),\n    \"Ask callers for the zip code they are calling from\", 1, y);\n  items.add(new Label(\"Country:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_address_country),\n    \"Ask Callers for the country they are calling from\", 3, y);\n  ++y;\n  items.add(new Label(\"Gender:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_gender),\n    \"Ask Callers for their gender (may be used to limit access)\", 1, y);\n  items.add(new Label(\"Birthday:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_birthday),\n    \"Ask callers for their date of birth (may be used to limit access)\", 3, y);\n  ++y;\n  items.add(new Label(\"Computer Type:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_computer_type),\n    \"Ask Callers for their computer type.\", 1, y);\n  items.add(new Label(\"Callsign:\"),\n            new ToggleEditItem<wwiv::sdk::newuser_item_type_t>(newuser_item_type_list, &nc.use_callsign),\n    \"Ask callers for their amateur radio callsign (if they have one)\", 3, y);\n\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"New User Configuration\");\n  config.closed_system(closed_system);\n  config.newuser_password(newuser_pw);\n  config.newuser_sl(newusersl);\n  config.newuser_dsl(newuserdsl);\n  config.validated_sl(validated_sl);\n  config.newuser_restrict(newuser_restrict);\n  config.newuser_gold(static_cast<float>(newuser_gold));\n}\n"
  },
  {
    "path": "wwivconfig/new_user.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_NEW_USER_H\n#define INCLUDED_WWIVCONFIG_NEW_USER_H\n\n// Minimal New User is:\n// Country first then:\n// Alias, Birthday, Gender, Zip, (city/state filled in or prompted), then email.\n// Example:\n/*  Mystic Rhythms BBS New User Registration\n\n[A] Name (real or alias)    : RNEW\n[B] Birth Date (MM/DD/YYYY) : January 01, 1980 (41 years old)\n[C] Sex (Gender)            : Male\n[D] Country                 : USA\n[E] ZIP or Postal Code      : 94105\n[F] City/State/Province     : San Francisco, CA\n[G] Internet Mail Address   : rushfan@me.com\n\nItem to change or [Q] to Quit :\n*/\n\n// Full Example:\n/*\nEnter your country (i.e. USA).\nHit Enter for \"USA\"\n:USA\n\nEnter your full name, or your alias.\nRNEW2\n\nEnter your FULL real name.\nRob Cole\n\nEnter your VOICE phone no. in the form:\n ###-###-####\n:415-555-1212\n\n Enter your amateur radio callsign, or just hit <ENTER> if none.\n:*/\n\nnamespace wwiv {\nnamespace local {\nnamespace ui {\nclass CursesWindow;\n}\n}\n\nnamespace sdk {\nclass Config;\nstruct newuser_config_t;\n}\n}\n\nvoid newuser_settings(wwiv::sdk::Config& config, wwiv::sdk::newuser_config_t& nc,\n                      wwiv::local::ui::CursesWindow*);\n\n#endif // INCLUDED_WWIVCONFIG_NEW_USER_H"
  },
  {
    "path": "wwivconfig/newinit.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/newinit.h\"\n\n#include \"subsdirs.h\"\n#include \"core/datafile.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"core/wwivport.h\"\n#include \"localui/input.h\"\n#include \"localui/ui_win.h\"\n#include \"localui/wwiv_curses.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/user.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/wwivcolors.h\"\n#include \"sdk/files/dirs.h\"\n#include \"wwivconfig/archivers.h\"\n#include \"wwivconfig/utility.h\"\n#include \"wwivconfig/wwivd_ui.h\"\n\n#include <cstdint>\n#include <cstdlib>\n#include <cstring>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nstatic void write_qscn(const Config& config, unsigned int un, uint32_t* qscn) {\n  File file(FilePath(config.datadir(), USER_QSC));\n  if (file.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\n    file.Seek(config.qscn_len() * un, File::Whence::begin);\n    file.Write(qscn, config.qscn_len());\n    file.Close();\n  }\n}\n\nstatic bool unzip_file(UIWindow* window, const std::string& zipfile, const std::string& dir) {\n  if (File::Exists(zipfile)) {\n    window->SetColor(SchemeId::NORMAL);\n    window->Puts(fmt::format(\"Decompressing file: {} to dir: {}\\n\", zipfile, dir));\n    const auto unzip_cmd = StrCat(\"unzip -qq -o \", zipfile, \" -d\", dir);\n    const auto rc = system(unzip_cmd.c_str());\n    if (rc != 0) {\n      window->SetColor(SchemeId::ERROR_TEXT);\n      window->Puts(\"ERROR Unable to unzip file.\\n\");\n    }\n\n    const auto sysop_dir = FilePath(\"dloads\", \"sysop\");\n    File::Rename(zipfile, FilePath(sysop_dir, zipfile));\n    return true;\n  }\n  return false;\n}\n\nstatic void init_files(UIWindow* window, const std::string& bbsdir, bool unzip_files) {\n  window->SetColor(SchemeId::PROMPT);\n  window->Puts(\"Creating Data Files.\\n\");\n  window->SetColor(SchemeId::NORMAL);\n\n  config_t cfg{};\n\n  // Set header\n  cfg.header.config_revision_number = 5;\n  cfg.header.written_by_wwiv_num_version = wwiv_config_version();\n  cfg.header.last_written_date = DateTime::now().to_string();\n\n  cfg.systempw = \"SYSOP\";\n  cfg.systemname = \"My WWIV BBS\";\n  cfg.systemphone = \"   -   -    \";\n  cfg.sysopname = \"The New Sysop\";\n\n  cfg.datadir = \"data\";\n  cfg.msgsdir = \"msgs\";\n  cfg.gfilesdir = \"gfiles\";\n  cfg.dloadsdir = \"dloads\";\n  cfg.menudir = \"menus\";\n  cfg.scriptdir = \"scripts\";\n  cfg.logdir = \"logs\";\n\n  cfg.tempdir_format = \"e/%n/temp\";\n  cfg.batchdir_format = \"e/%n/batch\";\n  cfg.scratchdir_format = \"e/%n/scratch\";\n  cfg.num_instances = 8;\n\n  cfg.newusersl = 10;\n  cfg.newuserdsl = 0;\n  cfg.validated_sl = cfg.newusersl + 1;\n  cfg.maxwaiting = 50;\n\n  cfg.newuploads = 0;\n  cfg.maxusers = 500;\n  cfg.newuser_restrict = User::restrictValidate;\n  cfg.req_ratio = 0.0;\n  cfg.newusergold = 100.0;\n\n  validation_config_t v{};\n  v.sl = 10;\n  v.dsl = 0;\n  v.ar = 0;\n  v.dar = 0;\n  v.restrict = 0;\n\n  for (auto i = 1; i <= 10; i++) {\n    v.name = fmt::format(\"Validation #{}\", i);\n    cfg.autoval.emplace(i, v);\n  }\n  for (auto i = 0; i < 256; i++) {\n    slrec sl{};\n    sl.time_per_logon = static_cast<uint16_t>((i / 10) * 10);\n    sl.time_per_day = static_cast<uint16_t>(sl.time_per_logon * 2.5);\n    sl.messages_read = static_cast<uint16_t>((i / 10) * 100);\n    if (i < 10) {\n      sl.emails = 0;\n    } else if (i <= 19) {\n      sl.emails = 5;\n    } else {\n      sl.emails = 20;\n    }\n\n    if (i <= 25) {\n      sl.posts = 10;\n    } else if (i <= 79) {\n      sl.posts = 20;\n    } else {\n      sl.posts = 50;\n    }\n\n    sl.ability = 0;\n    if (i >= 150) {\n      sl.ability |= ability_cosysop;\n    }\n    if (i >= 100) {\n      sl.ability |= ability_limited_cosysop;\n    }\n    if (i >= 90) {\n      sl.ability |= ability_read_email_anony;\n    }\n    if (i >= 80) {\n      sl.ability |= ability_read_post_anony;\n    }\n    if (i >= 70) {\n      sl.ability |= ability_email_anony;\n    }\n    if (i >= 60) {\n      sl.ability |= ability_post_anony;\n    }\n    if (i == 255) {\n      sl.time_per_logon = 255;\n      sl.time_per_day = 1440;\n      sl.posts = 255;\n      sl.emails = 255;\n    }\n    cfg.sl.emplace(i, sl);\n  }\n\n  cfg.userreclen = sizeof(userrec);\n  cfg.waitingoffset = offsetof(userrec, waiting);\n  cfg.inactoffset = offsetof(userrec, inact);\n  cfg.sysstatusoffset = offsetof(userrec, sysstatus);\n  cfg.fuoffset = offsetof(userrec, forwardusr);\n  cfg.fsoffset = offsetof(userrec, forwardsys);\n  cfg.fnoffset = offsetof(userrec, net_num);\n\n  cfg.max_subs = default_num_subs;\n  cfg.max_dirs = default_num_dirs;\n  cfg.qscn_len =\n      4 * (1 + cfg.max_subs + (cfg.max_subs + 31) / 32 + (cfg.max_dirs + 31) / 32);\n\n  cfg.post_call_ratio = 0.0;\n\n  // Create a 5.6+ style config.json\n  Config config(bbsdir, cfg);\n  // Since this was not loaded from disk as JSON, mark it mutable so it can\n  // be saved as JSON.\n  config.set_readonly(false);\n  config.Save();\n\n  const auto datadir = FilePath(bbsdir, \"data\");\n  create_arcs(window, datadir);\n  statusrec_t statusrec{};\n  memset(&statusrec, 0, sizeof(statusrec_t));\n  auto now = date();\n  to_char_array(statusrec.date1, now);\n  to_char_array(statusrec.date2, \"00/00/00\");\n  to_char_array(statusrec.date3, \"00/00/00\");\n  to_char_array(statusrec.log1, \"000000.log\");\n  to_char_array(statusrec.log2, \"000000.log\");\n  to_char_array(statusrec.gfiledate, now);\n  statusrec.callernum = 65535;\n  statusrec.qscanptr = 2;\n  statusrec.net_bias = 0.001f;\n  statusrec.net_req_free = 3.0;\n\n  auto qsc = std::make_unique<uint32_t[]>(config.qscn_len() / sizeof(uint32_t));\n\n  save_status(datadir.string(), statusrec);\n  userrec u{};\n  memset(&u, 0, sizeof(u));\n  write_user(config, 0, &u);\n  write_qscn(config, 0, qsc.get());\n\n  // Note: this is where wwivconfig makes a user record #1 that is deleted for new installs.\n  // TODO(rushfan): We should use User::CreateNewUserRecord here.\n  u.inact = User::userDeleted;\n  memset(u.lp_colors, static_cast<uint8_t>(Color::CYAN), sizeof(u.lp_colors));\n  u.lp_colors[0] = static_cast<uint8_t>(Color::LIGHTGREEN);\n  u.lp_colors[1] = static_cast<uint8_t>(Color::LIGHTGREEN);\n  u.lp_colors[2] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[3] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[4] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  u.lp_colors[5] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  u.lp_colors[6] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[7] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[8] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[9] = static_cast<uint8_t>(Color::CYAN);\n  u.lp_colors[10] = static_cast<uint8_t>(Color::LIGHTCYAN);\n  u.lp_options = cfl_fname | cfl_extension | cfl_dloads | cfl_kbytes | cfl_description;\n  u.hot_keys = 0;\n  to_char_array(u.menu_set, \"wwiv\");\n\n  write_user(config, 1, &u);\n  write_qscn(config, 1, qsc.get());\n  {\n    File namesfile(FilePath(\"data\", NAMES_LST));\n    namesfile.Open(File::modeBinary | File::modeReadWrite | File::modeCreateFile);\n  }\n  {\n    subboard_t r{};\n    r.name = \"General\";\n    r.filename = \"GENERAL\";\n    r.read_acs = \"user.sl >= 10\";\n    r.post_acs = \"user.sl >= 20\";\n    r.maxmsgs = 50;\n    r.storage_type = 2;\n\n    Subs subs(\"data/\", {});\n    subs.insert(0, r);\n    // TODO(rushfan): Check for error.\n    subs.Save();\n  }\n\n  {\n    files::Dirs dirs(\"data/\", 0);\n    {\n      files::directory_t d1{};\n      d1.name = \"Sysop\";\n      d1.filename = \"SYSOP\";\n      d1.path = File::EnsureTrailingSlash(FilePath(\"dloads\", \"sysop\").string());\n      File::mkdir(d1.path);\n      d1.acs = \"user.dsl >= 100\";\n      d1.maxfiles = 50;\n\n      dirs.insert(0, d1);\n    }\n    {\n      files::directory_t d1{};\n      d1.name = \"Miscellaneous\";\n      d1.filename = \"misc\";\n      d1.path = File::EnsureTrailingSlash(FilePath(\"dloads\", \"misc\").string());\n      File::mkdir(d1.path);\n      d1.acs = \"user.dsl >= 10\";\n      d1.maxfiles = 50;\n      d1.mask = 0;\n      dirs.insert(1, d1);\n    }\n    dirs.Save();\n  }\n\n  // Create wwivd.json\n  auto c = LoadDaemonConfig(config);\n  if (!SaveDaemonConfig(config, c)) {\n    LOG(ERROR) << \"Error saving wwivd.json\";\n  }\n  window->Puts(\".\\n\");\n\n  window->SetColor(SchemeId::PROMPT);\n  window->Puts(\"Copying String and Miscellaneous files.\\n\");\n  window->SetColor(SchemeId::NORMAL);\n\n  window->Puts(\".\\n\");\n\n  window->SetColor(SchemeId::PROMPT);\n  window->Puts(\"Decompressing archives.  Please wait\");\n  window->SetColor(SchemeId::NORMAL);\n\n  if (unzip_files) {\n    unzip_file(window, \"inifiles.zip\", bbsdir);\n    unzip_file(window, \"gfiles.zip\", \"gfiles\");\n    unzip_file(window, \"scripts.zip\", \"scripts\");\n    unzip_file(window, \"data.zip\", \"data\");\n    unzip_file(window, \"menus.zip\", \"menus\");\n    unzip_file(window, \"regions.zip\", StrCat(\"data\", File::pathSeparatorChar, \"regions\"));\n    unzip_file(window, \"zip-city.zip\", StrCat(\"data\", File::pathSeparatorChar, \"zip-city\"));\n\n#ifdef WIN32\n    // Unzip netfoss to \"${WWIV_DIR}/netfoss\"\n    unzip_file(window, \"netf124.zip\", \"netfoss\");\n#endif\n  }\n\n  window->SetColor(SchemeId::NORMAL);\n}\n\nbool new_init(UIWindow* window, const std::string& bbsdir, bool unzip_files) {\n  const std::vector<std::string> dirnames = {\n      \"attach\", \"data\",        \"data/regions\", \"data/zip-city\", \"gfiles\",  \"menus\", \"msgs\",\n      \"dloads\", \"dloads/misc\", \"dloads/sysop\", \"temp\",          \"temp/1\",  \"temp/2\",       \"temp/3\",\n      \"temp/4\", \"batch\",       \"batch/1\",      \"batch/2\",       \"batch/3\", \"batch/4\",\n      \"logs\"};\n  window->SetColor(SchemeId::PROMPT);\n  window->Puts(\"\\n\\nNow performing installation.  Please wait...\\n\\n\");\n  window->Puts(\"Creating Directories\\n\");\n  window->SetColor(SchemeId::NORMAL);\n  for (const auto& dirname : dirnames) {\n    window->SetColor(SchemeId::NORMAL);\n    if (const auto chdir_ok = File::set_current_directory(dirname); !chdir_ok) {\n      if (!File::mkdir(dirname)) {\n        window->SetColor(SchemeId::ERROR_TEXT);\n        window->Puts(StrCat(\"\\n\\nERROR!!! Couldn't make '\", dirname, \"' Sub-Dir.\\nExiting...\"));\n        return false;\n      }\n    } else {\n      File::set_current_directory(bbsdir);\n    }\n  }\n\n  init_files(window, bbsdir, unzip_files);\n  return true;\n}\n"
  },
  {
    "path": "wwivconfig/newinit.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_NEWINIT_H\n#define INCLUDED_WWIVCONFIG_NEWINIT_H\n\n#include <string>\n\nnamespace wwiv::local::ui {\nclass UIWindow;\n}\n\nbool new_init(wwiv::local::ui::UIWindow* window, const std::string& bbsdir, bool unzip_files);\n\n#endif // INCLUDED_WWIVCONFIG_NEWINIT_H\n"
  },
  {
    "path": "wwivconfig/paths.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/paths.h\"\r\n\r\n#include \"core/strings.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include <string>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::strings;\r\n\r\n/* change msgsdir, gfilesdir, datadir, dloadsdir, ramdrive, tempdir, scriptdir, logdir */\r\nvoid setpaths(wwiv::sdk::Config& config) {\r\n  EditItems items{};\r\n\r\n  auto y = 1;\r\n  auto msgsdir = config.raw_config().msgsdir;\r\n  auto gfilesdir = config.raw_config().gfilesdir;\r\n  auto menudir = config.raw_config().menudir;\r\n  auto datadir = config.raw_config().datadir;\r\n  auto logdir = config.raw_config().logdir;\r\n  auto scriptdir= config.raw_config().scriptdir;\r\n  auto dloadsdir = config.raw_config().dloadsdir;\r\n\r\n  auto tempdir = config.temp_format();\r\n  auto batchdir = config.batch_format();\r\n  auto scratchdir = config.scratch_format();\r\n\r\n  items.add(new Label(\"Messages:\"),\r\n            new StringFilePathItem(60, config.root_directory(), msgsdir), 1, y++);\r\n  items.add(new Label(\"GFiles:\"),\r\n      new StringFilePathItem(60, config.root_directory(), gfilesdir), 1, y++);\r\n  items.add(new Label(\"Menus:\"),\r\n      new StringFilePathItem(60, config.root_directory(), menudir), 1, y++);\r\n  items.add(new Label(\"Data:\"),\r\n      new StringFilePathItem(60, config.root_directory(), datadir), 1, y++);\r\n  items.add(new Label(\"Logs:\"),\r\n      new StringFilePathItem(60, config.root_directory(), logdir), 1, y++);\r\n  items.add(new Label(\"Scripts:\"),\r\n      new StringFilePathItem(60, config.root_directory(), scriptdir), 1, y++);\r\n  items.add(new Label(\"Downloads:\"),\r\n      new StringFilePathItem(60, config.root_directory(), dloadsdir), 1, y++);\r\n  y++;\r\n  items.add(new Label(\"Temp:\"),\r\n      new StringEditItem<std::string&>(60, tempdir, EditLineMode::ALL), \r\n    \"relative path to temp dir. '%n' replaced by instance # and is required.\", 1, y++);\r\n  items.add(new Label(\"Batch:\"),\r\n      new StringEditItem<std::string&>(60, batchdir, EditLineMode::ALL), \r\n    \"relative path to batch dir. '%n' replaced by instance # and is required.\", 1, y++);\r\n  items.add(new Label(\"Scratch:\"),\r\n      new StringEditItem<std::string&>(60, scratchdir, EditLineMode::ALL), \r\n    \"relative path to scratch space. '%n' replaced by instance # and is required.\", 1, y++);\r\n  y++;\r\n  items.add(new MultilineLabel(R\"(CAUTION: ONLY EXPERIENCED SYSOPS SHOULD MODIFY THESE SETTINGS.\r\nChanging any of these requires YOU to MANUALLY move files and/or\r\ndirectory structures.)\"), 1, y++)->set_right_justified(false);\r\n\r\n  if (config.scriptdir().empty()) {\r\n    // This is added in 5.3\r\n    config.scriptdir(FilePath(config.root_directory(), \"scripts\").string());\r\n  }\r\n  items.relayout_items_and_labels();\r\n  items.Run(\"System Paths\");\r\n  config.msgsdir(msgsdir);\r\n  config.gfilesdir(gfilesdir);\r\n  config.menudir(menudir);\r\n  config.datadir(datadir);\r\n  config.logdir(logdir);\r\n  config.scriptdir(scriptdir);\r\n  config.dloadsdir(dloadsdir);\r\n\r\n  config.temp_format(tempdir);\r\n  config.batch_format(batchdir);\r\n  config.scratch_format(scratchdir);\r\n}\r\n\r\n"
  },
  {
    "path": "wwivconfig/paths.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_PATHS_H\r\n#define INCLUDED_WWIVCONFIG_PATHS_H\r\n\r\n#include \"sdk/config.h\"\r\n\r\nvoid setpaths(wwiv::sdk::Config& config);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_PATHS_H\r\n"
  },
  {
    "path": "wwivconfig/protocols.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/protocols.h\"\r\n\r\n#include \"core/datafile.h\"\r\n#include \"core/file.h\"\r\n#include \"core/stl.h\"\r\n#include \"core/strings.h\"\r\n#include \"core/wwivport.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/vardec.h\"\r\n#include <cstdint>\r\n#include <cstring>\r\n#include <filesystem>\r\n#include <string>\r\n#include <vector>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::stl;\r\nusing namespace wwiv::strings;\r\n\r\nstatic std::string prot_name(const std::vector<newexternalrec>& externs, int pn) {\r\n  switch (pn) {\r\n  case 1:\r\n    return \"ASCII\";\r\n  case 2:\r\n    return \"Xmodem\";\r\n  case 3:\r\n    return \"Xmodem-CRC\";\r\n  case 4:\r\n    return \"Ymodem\";\r\n  case 5:\r\n    return \"Batch\";\r\n  default:\r\n    if (pn > 5 || pn < (ssize(externs) + 6)) {\r\n      return externs[pn - 6].description;\r\n    }\r\n  }\r\n  return \">NONE<\";\r\n}\r\n\r\nstatic void load_protocols(const std::filesystem::path& datadir, std::vector<newexternalrec>& externs,\r\n                           std::vector<newexternalrec>& over_intern) {\r\n  externs.clear();\r\n  over_intern.clear();\r\n  if (auto file = DataFile<newexternalrec>(FilePath(datadir, NEXTERN_DAT),\r\n                                           File::modeBinary | File::modeReadWrite)) {\r\n    file.ReadVector(externs, 15);\r\n  }\r\n  if (auto file = DataFile<newexternalrec>(FilePath(datadir, NINTERN_DAT),\r\n                                File::modeBinary | File::modeReadWrite)) {\r\n    file.ReadVector(over_intern, 3);\r\n  } else {\r\n    for (auto i = 0; i < 3; i++) {\r\n      over_intern.push_back({});\r\n    }\r\n  }\r\n}\r\n\r\nstatic void edit_prot(std::vector<newexternalrec>& externs,\r\n                      std::vector<newexternalrec>& over_intern, int n) {\r\n  if (n == 5) {\r\n    // This is the \"Batch\" protocol which has no override.\r\n    return;\r\n  }\r\n\r\n  newexternalrec c;\r\n  if (n >= 6) {\r\n    c = externs[n - 6];\r\n  } else {\r\n    c = over_intern[n - 2];\r\n    to_char_array(c.description, prot_name(over_intern, n));\r\n  }\r\n\r\n  auto y = 1;\r\n  EditItems items{};\r\n  items.add(new Label(\"Description:\"), 1, y);\r\n  if (n >= 4) {\r\n    items.add(new StringEditItem<char*>(45, c.description, EditLineMode::ALL), 2, 1);\r\n  } else {\r\n    items.add(new Label(c.description), 2, 1)->set_right_justified(false);\r\n  }\r\n  y++;\r\n  items.add(new Label(\"Xfer OK code:\"), new NumberEditItem<uint16_t>(&c.ok1), 1, y++);\r\n  items.add(new Label(\"Receive command line:\"), 1, y);\r\n  items.add(new Label(\"\"), 2, y++);  // hack to fix layout\r\n  items.add(new CommandLineItem(70, c.receivefn), 1, y++);\r\n  items.add(new Label(\"Send command line:\"), 1, y);\r\n  items.add(new Label(\"\"), 2, y++);  // hack to fix layout\r\n  items.add(new CommandLineItem(70, c.sendfn), 1, y++);\r\n  items.add(new Label(\"Receive batch command line:\"), 1, y);\r\n  items.add(new Label(\"\"), 2, y++);  // hack to fix layout\r\n  const auto receive_batch_pos = y++;\r\n  items.add(new Label(\"Send batch command line:\"), 1, y);\r\n  items.add(new Label(\"\"), 2, y++);  // hack to fix layout\r\n  const auto send_batch_pos = y++;\r\n  // Not else since we want the n >= 4 to be invoked.\r\n  if (n >= 6) {\r\n    items.add(new CommandLineItem(70, c.receivebatchfn), 1, receive_batch_pos);\r\n    items.add(new CommandLineItem(70, c.sendbatchfn), 1, send_batch_pos);\r\n  } else if (n >= 4) {\r\n    items.add(new CommandLineItem(70, c.sendbatchfn), 1, send_batch_pos);\r\n    items.add(new Label(\"-- N/A --\"), 1, receive_batch_pos)->set_right_justified(false);\r\n  } else {\r\n    items.add(new Label(\"-- N/A --\"), 1, send_batch_pos)->set_right_justified(false);\r\n    items.add(new Label(\"-- N/A --\"), 1, receive_batch_pos)->set_right_justified(false);\r\n  }\r\n  ++y;\r\n  items.add(new MultilineLabel(R\"\"\"\"(%1 = com port baud rate\r\n%2 = port number\r\n%3 = filename to transfer, filename list to send for batch\r\n%4 = modem speed\r\n%5 = filename list to receive for batch UL\r\nNOTE: Batch protocols >MUST< correctly support DSZLOG.)\"\"\"\"), 1, y);\r\n//  items.cell(y, 1).colspan_ = 2;\r\n  items.relayout_items_and_labels();\r\n  items.Run(\"Protocol Configuration\");\r\n\r\n  if (n >= 6) {\r\n    externs[n - 6] = c;\r\n  } else {\r\n    if (c.receivefn[0] || c.sendfn[0] || (c.sendbatchfn[0] && n == 4)) {\r\n      c.othr |= othr_override_internal;\r\n    } else {\r\n      c.othr &= ~othr_override_internal;\r\n    }\r\n    over_intern[n - 2] = c;\r\n  }\r\n}\r\n\r\nvoid extrn_prots(const std::filesystem::path& datadir) {\r\n  std::vector<newexternalrec> externs;\r\n  std::vector<newexternalrec> over_interns;\r\n  load_protocols(datadir, externs, over_interns);\r\n\r\n  bool done = false;\r\n  do {\r\n    curses_out->Cls(ACS_CKBOARD);\r\n    std::vector<ListBoxItem> items;\r\n    items.emplace_back(\"2. XModem (Internal)\", 0, 2);\r\n    items.emplace_back(\"X. XModem CRC (Internal)\", 0, 3);\r\n    items.emplace_back(\"Y. YModem (Internal)\", 0, 4);\r\n    for (auto i = 0; i < wwiv::stl::ssize(externs); i++) {\r\n      items.emplace_back(fmt::format(\"{}. {} (External)\", i + 6, prot_name(externs, i+6)), 0, i+6);\r\n    }\r\n    CursesWindow* window(curses_out->window());\r\n    ListBox list(window, \"Select Protocol\", items);\r\n\r\n    list.selection_returns_hotkey(true);\r\n    list.set_additional_hotkeys(\"DI\");\r\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"} });\r\n    auto result = list.Run();\r\n    const auto max_protocol_number = size_int(externs) -1 + 6;\r\n\r\n    if (result.type == ListBoxResultType::HOTKEY) {\r\n      switch (result.hotkey) {\r\n      case 'D': {\r\n        if (!externs.empty()) {\r\n          if (items[result.selected].data() < 6) {\r\n            messagebox(curses_out->window(), \"You can only delete external protocols.\");\r\n            break;\r\n          }\r\n          auto prompt = fmt::format(\"Delete '{}' ?\", items[result.selected].text());\r\n          auto yn = dialog_yn(window, prompt);\r\n          if (!yn) {\r\n            break;\r\n          }\r\n          auto pos = result.selected - 3; // 3 is the number of internal protocols listed.\r\n          erase_at(externs, pos);\r\n        }\r\n      } break;\r\n      case 'I': {\r\n        if (externs.size() >= 15) {\r\n          messagebox(curses_out->window(), \"Too many external protocols.\");\r\n          break;\r\n        }\r\n        auto prompt = fmt::format(\"Insert before which (6-{}) ? \", max_protocol_number + 1);\r\n        auto pos = dialog_input_number(curses_out->window(), prompt, 2, max_protocol_number + 1);\r\n        if (pos >= 6 && pos <= wwiv::stl::ssize(externs) + 6) {\r\n          size_t extern_pos = pos - 6;\r\n          newexternalrec e{};\r\n          memset(&e, 0, sizeof(newexternalrec));\r\n          if (extern_pos > externs.size()) {\r\n            externs.push_back(e);\r\n          } else {\r\n            insert_at(externs, extern_pos, e);\r\n          }\r\n          edit_prot(externs, over_interns, pos);\r\n        } else {\r\n          messagebox(curses_out->window(), fmt::format(\"Invalid entry: {}\", pos));\r\n        }\r\n      } break;\r\n      }\r\n    } else if (result.type == ListBoxResultType::SELECTION) {\r\n      edit_prot(externs, over_interns, items[result.selected].data());\r\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\r\n      done = true;\r\n    }\r\n  } while (!done);\r\n\r\n  DataFile<newexternalrec> newexternfile(FilePath(datadir, NEXTERN_DAT),\r\n    File::modeBinary | File::modeReadWrite | File::modeCreateFile | File::modeTruncate);\r\n  if (newexternfile) {\r\n    newexternfile.WriteVector(externs);\r\n  }\r\n  newexternfile.Close();\r\n\r\n  if ((over_interns[0].othr | over_interns[1].othr | over_interns[2].othr)&othr_override_internal) {\r\n    DataFile<newexternalrec> internfile(FilePath(datadir, NINTERN_DAT),\r\n      File::modeBinary | File::modeReadWrite | File::modeCreateFile | File::modeTruncate);\r\n    if (internfile) {\r\n      internfile.WriteVector(over_interns);\r\n    }\r\n  } else {\r\n    File::Remove(FilePath(datadir, NINTERN_DAT));\r\n  }\r\n}\r\n\r\n"
  },
  {
    "path": "wwivconfig/protocols.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_PROTOCOLS_H\r\n#define INCLUDED_WWIVCONFIG_PROTOCOLS_H\r\n\r\n#include <filesystem>\r\n#include <string>\r\n\r\nvoid extrn_prots(const std::filesystem::path& datadir);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_PROTOCOLS_H\r\n"
  },
  {
    "path": "wwivconfig/script_ui.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"core/strings.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nvoid script_ui(Config& config) {\n  auto allow_script = config.scripting_enabled();\n  auto enable_file = config.script_package_file_enabled();\n  auto enable_os = config.script_package_os_enabled();\n\n  auto y = 1;\n  EditItems items{};\n  items.add(new Label(\"Enable Scripting:\"),\n            new BooleanEditItem(&allow_script),\n    \"Are WWIVbasic scripts allowed to be executed anywhere.\", 1, y);\n  ++y;\n  items.add(new Label(\"Enable Package FILE:\"),\n            new BooleanEditItem(&enable_file),\n    \"Enable package wwiv.io.file.\", 1, y);\n  ++y;\n  items.add(new Label(\"Enable Package OS:\"),\n            new BooleanEditItem(&enable_os),\n    \"Enable package wwiv.os (allows executing external binaries).\", 1, y);\n  ++y;\n\n  items.relayout_items_and_labels();\n  items.Run(\"Scripting Configuration\");\n\n  config.scripting_enabled(allow_script);\n  config.script_package_os_enabled(enable_os);\n  config.script_package_file_enabled(enable_file);\n}\n"
  },
  {
    "path": "wwivconfig/script_ui.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*           Copyright (C)2020-2022, WWIV Software Services               */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_SCRIPT_UI_H\n#define INCLUDED_WWIVCONFIG_SCRIPT_UI_H\n\n#include \"sdk/config.h\"\n\nvoid script_ui(wwiv::sdk::Config& config);\n\n#endif\n"
  },
  {
    "path": "wwivconfig/subacc.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/subacc.h\"\r\n\r\n#include \"core/file.h\"\r\n#include \"core/stl.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"sdk/config.h\"\r\n#include \"sdk/subxtr.h\"\r\n#include \"sdk/vardec.h\"\r\n#include <memory>\r\n#include <string>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::stl;\r\nusing namespace wwiv::strings;\r\n\r\n// File object for '.sub' file\r\nstatic std::unique_ptr<File> fileSub;             \r\n// filename of .sub file. Ideally this shoudn't be a string but we don't use it\r\n// from joined threads nor from other initializers executed before the program starts\r\nstatic std::filesystem::path subdat_fn; \r\n\r\n// locals\r\nstatic int current_read_message_area, subchg;\r\nstatic int GetCurrentReadMessageArea() { return current_read_message_area; }\r\n\r\nstatic void SetCurrentReadMessageArea(int n) { current_read_message_area = n; }\r\n\r\nstatic int nNumMsgsInCurrentSub;\r\n\r\nint GetNumMessagesInCurrentMessageArea() { return nNumMsgsInCurrentSub; }\r\n\r\nstatic void SetNumMessagesInCurrentMessageArea(int n) { nNumMsgsInCurrentSub = n; }\r\n\r\nvoid close_sub() {\r\n  if (fileSub) {\r\n    fileSub.reset();\r\n  }\r\n}\r\n\r\nbool open_sub(bool wr) {\r\n  postrec p{};\r\n\r\n  close_sub();\r\n\r\n  if (wr) {\r\n    fileSub.reset(new File(subdat_fn));\r\n    fileSub->Open(File::modeBinary | File::modeCreateFile | File::modeReadWrite);\r\n\r\n    if (fileSub->IsOpen()) {\r\n      // re-read info from file, to be safe\r\n      fileSub->Seek(0L, File::Whence::begin);\r\n      fileSub->Read(&p, sizeof(postrec));\r\n      SetNumMessagesInCurrentMessageArea(p.owneruser);\r\n    }\r\n  } else {\r\n    fileSub.reset(new File(subdat_fn));\r\n    fileSub->Open(File::modeReadOnly | File::modeBinary);\r\n  }\r\n\r\n  return fileSub->IsOpen();\r\n}\r\n\r\nbool iscan1(int si, const wwiv::sdk::Subs& subs, const wwiv::sdk::Config& config) {\r\n  // Initializes use of a sub value (subs[], not a()->usub[]).  If quick, then\r\n  // don't worry about anything detailed, just grab qscan info.\r\n  postrec p{};\r\n\r\n  // forget it if an invalid sub #\r\n  if (si < 0 || si >= size_int(subs.subs())) {\r\n    return false;\r\n  }\r\n\r\n  // see if a sub has changed\r\n  if (subchg) {\r\n    SetCurrentReadMessageArea(-1);\r\n  }\r\n\r\n  // if already have this one set, nothing more to do\r\n  if (si == GetCurrentReadMessageArea()) {\r\n    return true;\r\n  }\r\n\r\n  // set sub filename\r\n  subdat_fn = FilePath(config.datadir(), fmt::format(\"{}.sub\", subs.sub(si).filename));\r\n\r\n  // open file, and create it if necessary\r\n  if (!File::Exists(subdat_fn)) {\r\n    if (!open_sub(true)) {\r\n      return false;\r\n    }\r\n    p.owneruser = 0;\r\n    fileSub->Write(&p, sizeof(postrec));\r\n  } else if (!open_sub(false)) {\r\n    return false;\r\n  }\r\n\r\n  // set sub\r\n  SetCurrentReadMessageArea(si);\r\n  subchg = 0;\r\n\r\n  // read in first rec, specifying # posts\r\n  fileSub->Seek(0L, File::Whence::begin);\r\n  fileSub->Read(&p, sizeof(postrec));\r\n  SetNumMessagesInCurrentMessageArea(p.owneruser);\r\n\r\n  // close file\r\n  close_sub();\r\n\r\n  // iscanned correctly\r\n  return true;\r\n}\r\n\r\nstd::optional<postrec> get_post(int mn) {\r\n  // Returns info for a post.  Does not correct anything if the sub has changed.\r\n  // returns null optional if msg # invalid\r\n  if (mn < 1) {\r\n    return std::nullopt;\r\n  }\r\n  // adjust msgnum, if it is no longer valid\r\n  if (mn > GetNumMessagesInCurrentMessageArea()) {\r\n    mn = GetNumMessagesInCurrentMessageArea();\r\n  }\r\n\r\n  // read in some sub info\r\n  postrec p{};\r\n  fileSub->Seek(mn * sizeof(postrec), File::Whence::begin);\r\n  fileSub->Read(&p, sizeof(postrec));\r\n  return {p};\r\n}\r\n\r\nvoid write_post(int mn, const postrec& pp) {\r\n  if (fileSub->IsOpen()) {\r\n    fileSub->Seek(mn * sizeof(postrec), File::Whence::begin);\r\n    fileSub->Write(&pp, sizeof(postrec));\r\n  }\r\n}\r\n"
  },
  {
    "path": "wwivconfig/subacc.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_SUBACC_H\r\n#define INCLUDED_WWIVCONFIG_SUBACC_H\r\n\r\n#include \"sdk/subxtr.h\"\r\n#include <optional>\r\n\r\nnamespace wwiv::sdk {\r\nclass Config;\r\n}\r\n\r\nstruct postrec;\r\nvoid close_sub();\r\nbool open_sub(bool wr);\r\nbool iscan1(int si, const wwiv::sdk::Subs&, const wwiv::sdk::Config&);\r\nstd::optional<postrec> get_post(int mn);\r\nvoid write_post(int mn, const postrec& pp);\r\n\r\nint GetNumMessagesInCurrentMessageArea();\r\n\r\n#endif  // INCLUDED_WWIVCONFIG_SUBACC_H"
  },
  {
    "path": "wwivconfig/subsdirs.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/subsdirs.h\"\r\n\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include \"fmt/format.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"sdk/filenames.h\"\r\n\r\n#include <memory>\r\n#include <string>\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::sdk;\r\nusing namespace wwiv::strings;\r\n\r\ntemplate<typename T>\r\nstatic auto input_number(CursesWindow* window, int max_digits) -> T {\r\n  std::string s;\r\n  editline(window, &s, max_digits, EditLineMode::NUM_ONLY, \"\");\r\n  if (s.empty()) {\r\n    return 0;\r\n  }\r\n  try {\r\n    auto num = std::stoi(s);\r\n    return static_cast<T>(num);\r\n  } catch (const std::logic_error&) { \r\n    // No conversion possible.\r\n    return 0;\r\n  }\r\n}\r\n\r\nstatic void convert_to(CursesWindow* window, uint16_t num_subs, uint16_t num_dirs,\r\n                       Config& config) {\r\n  int l1, l2, l3;\r\n\r\n  if (num_subs % 32) {\r\n    num_subs = (num_subs / 32 + 1) * 32;\r\n  }\r\n  if (num_dirs % 32) {\r\n    num_dirs = (num_dirs / 32 + 1) * 32;\r\n  }\r\n\r\n  if (num_subs < 32) {\r\n    num_subs = 32;\r\n  }\r\n  if (num_dirs < 32) {\r\n    num_dirs = 32;\r\n  }\r\n\r\n  if (num_subs > max_num_subs_and_dirs) {\r\n    num_subs = max_num_subs_and_dirs;\r\n  }\r\n  if (num_dirs > max_num_subs_and_dirs) {\r\n    num_dirs = max_num_subs_and_dirs;\r\n  }\r\n\r\n  const auto nqscn_len =\r\n      static_cast<uint16_t>(4 * (1 + num_subs + ((num_subs + 31) / 32) + ((num_dirs + 31) / 32)));\r\n  const auto nqsc = std::make_unique<uint32_t[]>(nqscn_len);\r\n  auto* nqsc_n = nqsc.get() + 1;\r\n  auto* nqsc_q = nqsc_n + ((num_dirs + 31) / 32);\r\n  auto* nqsc_p = nqsc_q + ((num_subs + 31) / 32);\r\n\r\n  memset(nqsc_n, 0xff, ((num_dirs + 31) / 32) * 4);\r\n  memset(nqsc_q, 0xff, ((num_subs + 31) / 32) * 4);\r\n\r\n  const auto oqsc = std::make_unique<uint32_t[]>(nqscn_len);\r\n  const auto* oqsc_n = oqsc.get() + 1;\r\n  const auto* oqsc_q = oqsc_n + ((config.max_dirs() + 31) / 32);\r\n  const auto* oqsc_p = oqsc_q + ((config.max_subs() + 31) / 32);\r\n\r\n  if (num_dirs < config.max_dirs()) {\r\n    l1 = ((num_dirs + 31) / 32) * 4;\r\n  } else {\r\n    l1 = ((config.max_dirs() + 31) / 32) * 4;\r\n  }\r\n\r\n  if (num_subs < config.max_subs()) {\r\n    l2 = ((num_subs + 31) / 32) * 4;\r\n    l3 = num_subs * 4;\r\n  } else {\r\n    l2 = ((config.max_subs() + 31) / 32) * 4;\r\n    l3 = config.max_subs() * 4;\r\n  }\r\n\r\n  const auto oqf_fn = FilePath(config.datadir(), USER_QSC);\r\n  File oqf(oqf_fn);\r\n  if (!oqf.Open(File::modeBinary|File::modeReadWrite)) {\r\n    messagebox(window, \"Could not open user.qsc\");\r\n    return;\r\n  }\r\n  File nqf(FilePath(config.datadir(), \"userqsc.new\"));\r\n  if (!nqf.Open(File::modeBinary|File::modeReadWrite|File::modeCreateFile|File::modeTruncate)) {\r\n    messagebox(window, \"Could not open userqsc.new\");\r\n    return;\r\n  }\r\n\r\n  const auto nu = oqf.length() / config.qscn_len();\r\n  for (auto i = 0; i < nu; i++) {\r\n    if (i % 10 == 0) {\r\n      window->Puts(StrCat(i, \"/\", nu, \"\\r\"));\r\n    }\r\n    oqf.Read(oqsc.get(), config.qscn_len());\r\n\r\n    *nqsc.get() = *oqsc.get();  // NOLINT(readability-redundant-smartptr-get)\r\n    memcpy(nqsc_n, oqsc_n, l1);\r\n    memcpy(nqsc_q, oqsc_q, l2);\r\n    memcpy(nqsc_p, oqsc_p, l3);\r\n    nqf.Write(nqsc.get(), nqscn_len);\r\n  }\r\n\r\n  oqf.Close();\r\n  nqf.Close();\r\n  File::Remove(oqf_fn);\r\n  File::Rename(nqf.path(), oqf.path());\r\n\r\n  config.max_subs(num_subs);\r\n  config.max_dirs(num_dirs);\r\n  config.qscn_len(nqscn_len);\r\n  window->Puts(\"Done\\n\");\r\n}\r\n\r\nvoid up_subs_dirs(wwiv::sdk::Config& config) {\r\n  curses_out->Cls(ACS_CKBOARD);\r\n  std::unique_ptr<CursesWindow> window(\r\n      curses_out->CreateBoxedWindow(\"Update Sub/Directory Maximums\", 16, 76));\r\n\r\n  int y=1;\r\n  window->PutsXY(2, y++, StrCat(\"Current max # subs: \", config.max_subs()));\r\n  window->PutsXY(2, y++, StrCat(\"Current max # dirs: \", config.max_dirs()));\r\n\r\n  if (dialog_yn(window.get(), \"Change # subs or # dirs?\")) { \r\n    y+=2;\r\n    window->SetColor(SchemeId::INFO);\r\n    window->PutsXY(2, y++, \"Enter the new max subs/dirs you wish.  Just hit <enter> to leave that\");\r\n    window->PutsXY(2, y++, \"value unchanged.  All values will be rounded up to the next 32.\");\r\n    window->PutsXY(2, y++, \"Values can range from 32-1024\");\r\n\r\n    y++;\r\n    window->SetColor(SchemeId::PROMPT);\r\n    window->PutsXY(2, y++, \"New max subs: \");\r\n    auto num_subs = input_number<uint16_t>(window.get(), 4);\r\n    if (!num_subs) {\r\n      num_subs = config.max_subs();\r\n    }\r\n    window->SetColor(SchemeId::PROMPT);\r\n    window->PutsXY(2, y, \"New max dirs: \");\r\n    auto num_dirs = input_number<uint16_t>(window.get(), 4);\r\n    if (!num_dirs) {\r\n      num_dirs = config.max_dirs();\r\n    }\r\n\r\n    if (num_subs % 32) {\r\n      num_subs = (num_subs / 32 + 1) * 32;\r\n    }\r\n    if (num_dirs % 32) {\r\n      num_dirs = (num_dirs / 32 + 1) * 32;\r\n    }\r\n\r\n    if (num_subs < min_num_subs_and_dirs) {\r\n      num_subs = min_num_subs_and_dirs;\r\n    }\r\n    if (num_dirs < min_num_subs_and_dirs) {\r\n      num_dirs = min_num_subs_and_dirs;\r\n    }\r\n\r\n    if (num_subs > max_num_subs_and_dirs) {\r\n      num_subs = max_num_subs_and_dirs;\r\n    }\r\n    if (num_dirs > max_num_subs_and_dirs) {\r\n      num_dirs = max_num_subs_and_dirs;\r\n    }\r\n\r\n    if (num_subs != config.max_subs() || num_dirs != config.max_dirs()) {\r\n      const auto text = fmt::format(\"Change to {} subs and {} dirs? \", num_subs, num_dirs);\r\n      if (dialog_yn(window.get(), text)) {\r\n        window->SetColor(SchemeId::INFO);\r\n        window->Puts(\"Please wait...\\n\");\r\n        convert_to(window.get(), num_subs, num_dirs, config);\r\n      }\r\n    }\r\n  }\r\n}\r\n"
  },
  {
    "path": "wwivconfig/subsdirs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_SUBSDIRS_H\n#define INCLUDED_WWIVCONFIG_SUBSDIRS_H\n\n#include \"sdk/config.h\"\n\nstatic constexpr int min_num_subs_and_dirs = 128;\nstatic constexpr int default_num_subs = 256;\nstatic constexpr int default_num_dirs = 128;\nstatic constexpr int max_num_subs_and_dirs = 4096;\n\nvoid up_subs_dirs(wwiv::sdk::Config& config);\n\n#endif // INCLUDED_WWIVCONFIG_SUBSDIRS_H\n"
  },
  {
    "path": "wwivconfig/sysop_account.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/sysop_account.h\"\n\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n#include \"localui/listbox.h\"\n#include \"localui/wwiv_curses.h\"\n#include \"sdk/names.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include \"wwivconfig/utility.h\"\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nvoid create_sysop_account(Config& config) {\n  curses_out->Cls(ACS_CKBOARD);\n\n  std::vector<uint8_t> newuser_colors{7, 11, 14, 13, 31, 10, 12, 9, 5, 3};\n  std::vector<uint8_t> newuser_bwcolors{7, 15, 15, 15, 112, 15, 15, 7, 7, 7};\n\n  IniFile ini(FilePath(config.root_directory(), \"wwiv.ini\"), \"WWIV\");\n  if (ini.IsOpen()) {\n    for (auto i = 0; i < 10; i++) {\n      {\n        const auto key_name = fmt::format(\"{}[{}]\", \"NUCOLOR\", i);\n        auto num = ini.value<uint8_t>(key_name);\n        if (num != 0) {\n          newuser_colors[i] = num;\n        }\n      }\n      {\n        const auto key_name = fmt::format(\"{}[{}]\", \"NUCOLORBW\", i);\n        auto num = ini.value<uint8_t>(key_name);\n        if (num != 0) {\n          newuser_bwcolors[i] = num;\n        }\n      }\n    }\n  }\n  UserManager usermanager(config);\n\n  auto y = 1;\n\n  User u{};\n  u.ZeroUserData();\n  User::CreateNewUserRecord(&u, config.newuser_sl(), config.newuser_dsl(),\n                            config.newuser_restrict(), config.newuser_gold(), newuser_colors,\n                            newuser_bwcolors);\n  EditItems items{};\n  items.add(new Label(\"Sysop Name/Handle:\"),\n            new StringEditItem<unsigned char*>(30, u.data.name, EditLineMode::UPPER_ONLY), 1, y);\n  ++y;\n  items.add(new Label(\"Real Name:\"),\n            new StringEditItem<unsigned char*>(20, u.data.realname, EditLineMode::ALL), 1,\n            y);\n  ++y;\n  items.add(new Label(\"Password:\"),\n            new StringEditItem<char*>(8, u.data.pw, EditLineMode::UPPER_ONLY), 1, y);\n  ++y;\n  items.add(new Label(\"BBS Phone Number:\"),\n            new StringEditItem<char*>(12, u.data.phone, EditLineMode::UPPER_ONLY), 1, y);\n\n  items.relayout_items_and_labels();\n  items.Run(\"Create Sysop Account\");\n\n  u.data.sl = 255;\n  u.data.dsl = 255;\n  u.data.restrict = 0;\n  u.set_flag(User::flag_ansi);\n  u.set_flag(User::status_color);\n  u.set_flag(User::extraColor);\n  // Enable the internal FSED and full screen reader for the sysop.\n  u.default_editor(0xff);\n  u.set_flag(User::fullScreenReader);\n  usermanager.writeuser(&u, 1);\n\n  {\n    Names names(config);\n    names.Load();\n    names.Add(u.name(), 1);\n    names.Save();\n  }\n\n  if (statusrec_t statusrec{}; read_status(config.datadir(), statusrec)) {\n    statusrec.users++;\n    save_status(config.datadir(), statusrec);\n  }\n}\n"
  },
  {
    "path": "wwivconfig/sysop_account.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_SYSOP_ACCOUNT_H\n#define INCLUDED_WWIVCONFIG_SYSOP_ACCOUNT_H\n\n#include \"sdk/config.h\"\n\nvoid create_sysop_account(wwiv::sdk::Config& config);\n\n#endif // INCLUDED_WWIVCONFIG_SYSOP_ACCOUNT_H\n"
  },
  {
    "path": "wwivconfig/system_info.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/system_info.h\"\n\n#include \"core/strings.h\"\n#include \"fmt/printf.h\"\n#include \"localui/input.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/edit_items.h\"\n#include \"sdk/vardec.h\"\n#include \"wwivconfig/new_user.h\"\n#include \"wwivconfig/colors.h\"\n#include \"wwivconfig/toggles.h\"\n#include \"wwivconfig/utility.h\"\n#include <cstdint>\n#include <string>\n\nusing namespace wwiv::local::ui;\nusing namespace wwiv::strings;\n\nstatic std::string print_time(uint16_t t) {\n  return fmt::sprintf(\"%02d:%02d\", t / 60, t % 60);\n}\n\nstatic uint16_t get_time(const std::string& s) {\n  if (s[2] != ':') {\n    return std::numeric_limits<uint16_t>::max();\n  }\n\n  const auto h = to_number<uint16_t>(s);\n  const auto minutes = s.substr(3);\n  const auto m = to_number<uint16_t>(minutes);\n  if (h > 23 || m > 59) {\n    return std::numeric_limits<uint16_t>::max();\n  }\n  return static_cast<uint16_t>(h * 60 + m);\n}\n\nstatic const int MAX_TIME_EDIT_LEN = 5;\n\nclass TimeEditItem final : public EditItem<uint16_t*> {\npublic:\n  TimeEditItem(uint16_t* data) : EditItem<uint16_t*>(5, data) {}\n  ~TimeEditItem() override = default;\n\n  EditlineResult Run(CursesWindow* window) override {\n    window->GotoXY(this->x_, this->y_);\n    auto s = print_time(*this->data_);\n    const auto return_code = editline(window, &s, MAX_TIME_EDIT_LEN + 1, EditLineMode::ALL, \"\");\n    *this->data_ = get_time(s);\n    return return_code;\n  }\n\nprotected:\n  void DefaultDisplay(CursesWindow* window) const override {\n    const auto s = print_time(*this->data_);\n    DefaultDisplayString(window, s);\n  }\n};\n\nclass Float53EditItem final : public EditItem<float*> {\npublic:\n  Float53EditItem(float* data) : EditItem<float*>(5, data) {}\n  ~Float53EditItem() override = default;\n\n  EditlineResult Run(CursesWindow* window) override {\n    window->GotoXY(this->x_, this->y_);\n   \n    // passing *this->data_ to String Printf is causing a bus error\n    // on GCC/ARM (RPI).  See http://stackoverflow.com/questions/26158510\n    const auto d = *this->data_;\n    auto s = fmt::sprintf(\"%5.3f\", d);\n    const auto return_code = editline(window, &s, 5 + 1, EditLineMode::NUM_ONLY, \"\");\n\n    char* e;\n    auto f = strtof(s.c_str(), &e);\n    if (f > 9.999 || f < 0.001) {\n      f = 0.0;\n    }\n    *this->data_ = f;\n    return return_code;\n  }\n\nprotected:\n  void DefaultDisplay(CursesWindow* window) const override {\n    // passing *this->data_ to fmt::sprintf is causing a bus error\n    // on GCC/ARM (RPI).  See http://stackoverflow.com/questions/26158510\n    const auto d = *this->data_;\n    const auto s = fmt::sprintf(\"%5.3f\", d);\n    DefaultDisplayString(window, s);\n  }\n};\n\n\ntemplate <class T> class NewUserSubDialog final : public SubDialog<T> {\npublic:\n  NewUserSubDialog(wwiv::sdk::Config& c, T& t,\n                   std::function<void(wwiv::sdk::Config&, T&, CursesWindow*)> fn)\n      : SubDialog<T>(c, t), c_(c), t__(t), fn_(std::move(fn)) {}\n  ~NewUserSubDialog() override = default;\n\n  void RunSubDialog(CursesWindow* window) override { fn_(c_, t__, window); }\n\nprivate:\n  // For some reason GCC couldn't find config() or t_ from SubDialog.\n  wwiv::sdk::Config& c_;\n  T& t__;\n  std::function<void(wwiv::sdk::Config&, T&, CursesWindow*)> fn_;\n};\n\n\nvoid sysinfo1(wwiv::sdk::Config& config) {\n  statusrec_t statusrec{};\n  read_status(config.datadir(), statusrec);\n\n  if (statusrec.callernum != 65535) {\n    statusrec.callernum1 = static_cast<long>(statusrec.callernum);\n    statusrec.callernum = 65535;\n    save_status(config.datadir(), statusrec);\n  }\n\n  auto system_name = config.system_name();\n  auto sysop_name = config.sysop_name();\n  auto system_phone = config.system_phone();\n  auto system_pw = config.system_password();\n  auto sysoplowtime = config.sysop_low_time();\n  auto sysophightime = config.sysop_high_time();\n  auto req_ratio = config.req_ratio();\n  auto post_call_ratio = config.post_to_call_ratio();\n  auto max_users = config.max_users();\n  int max_waiting = config.max_waiting();\n  int wwiv_reg_number = config.wwiv_reg_number();\n  int max_backups = config.max_backups();\n  int num_instances = config.num_instances();\n\n  auto y = 1;\n  EditItems items{};\n  items.add(new Label(\"System name:\"),\n            new StringEditItem<std::string&>(50, system_name, EditLineMode::ALL),\n    \"Name of the BBS System\", 1, y);\n  ++y;\n  items.add(new Label(\"Sysop name:\"),\n            new StringEditItem<std::string&>(50, sysop_name, EditLineMode::ALL),\n    \"The name (or handle/alias) of the System Operator\", 1, y);\n  ++y;\n  items.add(\n      new Label(\"System phone:\"),\n      new StringEditItem<std::string&>(12, system_phone, EditLineMode::UPPER_ONLY),\n    \"Phone number for the BBS (if you have one)\", 1, y);\n  ++y;\n  items.add(new Label(\"System PW:\"),\n            new StringEditItem<std::string&>(20, system_pw, EditLineMode::UPPER_ONLY),\n            \"Password needed to log in as sysop\", 1, y);\n  y+=2;\n  items.add(new Label(\"Sysop time: from:\"),\n            new TimeEditItem(&sysoplowtime),\n    \"Set the time limits that the sysop is available for chat\", 1, y);\n  items.add(new Label(\"to:\"),\n            new TimeEditItem(&sysophightime),\n    \"Set the time limits that the sysop is available for chat\", 3, y);\n  ++y;\n  items.add(new Label(\"Ratios    :  U/D:\"),\n            new Float53EditItem(&req_ratio),\n    \"Optional required ratio of (uploads/downloads) for downloading files\", 1, y);\n  items.add(new Label(\"Post/Call:\"),\n            new Float53EditItem(&post_call_ratio),\n    \"Optional required ratio of (uploads/downloads) for downloading files\", 3, y);\n  ++y;\n  items.add(new Label(\"Max waiting:\"),\n            new NumberEditItem<int, 3>(&max_waiting),\n    \"Maximum number of emails allowed for a user\", 1, y);\n  items.add(new Label(\"Max users:\"),\n            new NumberEditItem<uint16_t>(&max_users),\n    \"The maximum number of users that can be on the system\", 3, y);\n  ++y;\n  items.add(new Label(\"Total Calls:\"),\n            new NumberEditItem<uint32_t>(&statusrec.callernum1),\n    \"Caller number for the last call to the BBS.\", 1, y);\n  items.add(new Label(\"Days active:\"),\n            new NumberEditItem<uint16_t>(&statusrec.days),\n    \"Number of days the BBS has been active\", 3, y);\n  ++y;\n  items.add(new Label(\"4.x Reg Number:\"),\n            new NumberEditItem<int>(&wwiv_reg_number),\n    \"Legacy registration # from WWIV 4.xx. Just used for bragging rights\", 1, y);\n\n  items.add(new Label(\"Max Backups:\"),\n            new NumberEditItem<int, 3>(&max_backups),\n    \"Max number of backup to keep when making new datafile backups (0=unlimited)\", 3, y);\n  ++y;\n  items.add(new Label(\"Max Instances:\"),\n            new NumberEditItem<int, 3>(&num_instances),\n    \"Max number of BBS instances allowed.\", 1, y);\n\n  y += 2;\n  items.add(new Label(\"Newuser Settings:\"),\n            new NewUserSubDialog<wwiv::sdk::newuser_config_t>(config, config.newuser_config(), newuser_settings),\n            1, y);\n  ++y;\n  items.add(new Label(\"System Toggles:\"),\n            new NewUserSubDialog<wwiv::sdk::system_toggles_t>(config, config.toggles(), toggles), 1,\n            y);\n  ++y;\n  items.add(new Label(\"System Colors:\"),\n            new NewUserSubDialog<wwiv::sdk::color_config_t>(config, config.colors(), colors), 1,\n            y);\n  ++y;\n\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"System Configuration\");\n\n  config.system_name(system_name);\n  config.sysop_name(sysop_name);\n  config.system_phone(system_phone);\n  config.system_password(system_pw);\n  config.sysop_low_time(sysoplowtime);\n  config.sysop_high_time(sysophightime);\n  config.req_ratio(req_ratio);\n  config.post_to_call_ratio(post_call_ratio);\n  config.max_users(max_users);\n  config.max_waiting(max_waiting);\n  config.wwiv_reg_number(wwiv_reg_number);\n  config.max_backups(max_backups);\n  config.num_instances(num_instances);\n\n  save_status(config.datadir(), statusrec);\n}\n"
  },
  {
    "path": "wwivconfig/system_info.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_SYSTEM_INFO_H\r\n#define INCLUDED_WWIVCONFIG_SYSTEM_INFO_H\r\n\r\n#include \"sdk/config.h\"\r\n\r\nvoid sysinfo1(wwiv::sdk::Config& config);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_SYSTEM_INFO_H"
  },
  {
    "path": "wwivconfig/template.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                 WWIV Initialization Utility Version 5.0                */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"template.h\"\r\n\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"localui/input.h\"\r\n#include \"wwivconfig/wwivconfig.h\"\r\n#include \"sdk/vardec.h\"\r\n\r\n"
  },
  {
    "path": "wwivconfig/toggles.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/toggles.h\"\n\n#include \"core/strings.h\"\n#include \"localui/curses_win.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n\nusing namespace wwiv::local::ui;\nusing namespace wwiv::strings;\n\nvoid toggles(wwiv::sdk::Config&, wwiv::sdk::system_toggles_t& t, CursesWindow*) {\n\n  auto y = 1;\n  EditItems items{};\n  items.add(new Label(\"LastNet at Logon:\"),\n            new BooleanEditItem(&t.lastnet_at_logon),\n    \"Show the most recent network connections at logon\", 1, y);\n  ++y;\n  items.add(new Label(\"Show Chain Usage:\"),\n            new BooleanEditItem(&t.show_chain_usage),\n    \"Show usage stats in chain display\", 1, y);\n\n\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"System Toggles\");\n}\n"
  },
  {
    "path": "wwivconfig/toggles.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_TOGGLES_H\n#define INCLUDED_WWIVCONFIG_TOGGLES_H\n\n#include \"localui/curses_win.h\"\n#include \"sdk/config.h\"\n\nvoid toggles(wwiv::sdk::Config& config, wwiv::sdk::system_toggles_t& b_, wwiv::local::ui::CursesWindow* window);\n\n#endif // INCLUDED_WWIVCONFIG_NEW_USER_H"
  },
  {
    "path": "wwivconfig/user_editor.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#include \"wwivconfig/user_editor.h\"\r\n\r\n#include \"core/datafile.h\"\r\n#include \"core/datetime.h\"\r\n#include \"core/file.h\"\r\n#include \"core/strings.h\"\r\n#include \"core/textfile.h\"\r\n#include \"fmt/format.h\"\r\n#include \"fmt/printf.h\"\r\n#include \"localui/edit_items.h\"\r\n#include \"localui/input.h\"\r\n#include \"localui/listbox.h\"\r\n#include \"localui/wwiv_curses.h\"\r\n#include \"sdk/config.h\"\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/instance.h\"\r\n#include \"sdk/names.h\"\r\n#include \"sdk/user.h\"\r\n#include \"sdk/usermanager.h\"\r\n#include \"sdk/vardec.h\"\r\n#include \"wwivconfig/utility.h\"\r\n\r\n#include <cstdint>\r\n#include <string>\r\n#include <vector>\r\n\r\nstatic constexpr int NONEDITABLE_DATA_POS = 50;\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::local::ui;\r\nusing namespace wwiv::strings;\r\n\r\nstatic bool IsUserDeleted(userrec* user) { return user->inact & wwiv::sdk::User::userDeleted; }\r\n\r\nstatic void show_user(EditItems* items, userrec* user) {\r\n  items->window()->SetColor(SchemeId::WINDOW_TEXT);\r\n  const auto height = items->window()->GetMaxY() - 2;\r\n  const auto width = items->window()->GetMaxX() - 2;\r\n  const std::string blank(width - NONEDITABLE_DATA_POS, ' ');\r\n  items->window()->SetColor(SchemeId::WINDOW_TEXT);\r\n  for (int i = 1; i < height; i++) {\r\n    items->window()->PutsXY(NONEDITABLE_DATA_POS, i, blank);\r\n  }\r\n  if (IsUserDeleted(user)) {\r\n    items->window()->SetColor(SchemeId::ERROR_TEXT);\r\n    items->window()->PutsXY(NONEDITABLE_DATA_POS, 1, \"[[ DELETED USER ]] \");\r\n  } else if (user->inact & wwiv::sdk::User::userInactive) {\r\n    items->window()->SetColor(SchemeId::ERROR_TEXT);\r\n    items->window()->PutsXY(NONEDITABLE_DATA_POS, 1, \"[[ INACTIVE USER ]]\");\r\n  }\r\n  items->window()->SetColor(SchemeId::WINDOW_TEXT);\r\n  auto y = 2;\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"First on     : \", user->firston));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Last on      : \", user->laston));\r\n  y++;\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Total Calls  : \", user->logons));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Today Calls  : \", static_cast<unsigned>(user->ontoday)));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Bad Logins   : \", static_cast<unsigned>(user->illegal)));\r\n  y++;\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Num of Posts : \", user->msgpost));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Num of Emails: \", user->emailsent));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Feedback Sent: \", user->feedbacksent));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Msgs Waiting : \", static_cast<unsigned>(user->waiting)));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Netmail Sent : \", user->emailnet));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y++, StrCat(\"Deleted Posts: \", user->deletedposts));\r\n  items->window()->PutsXY(NONEDITABLE_DATA_POS, y,     StrCat(\"Extra Time   : \", user->extratime));\r\n\r\n  items->Display();\r\n}\r\n\r\nstatic void show_error_no_users(CursesWindow* window) {\r\n  messagebox(window, \"You must have users added before using user editor.\");\r\n}\r\n\r\nstatic std::vector<HelpItem> create_extra_help_items() {\r\n  std::vector<HelpItem> help_items = {{\"D\", \"Delete\"}, {\"J\", \"Jump\"}, {\"R\", \"Restore\"}};\r\n  return help_items;\r\n}\r\n\r\nstatic int JumpToUser(CursesWindow* window, const std::filesystem::path& datadir) {\r\n  std::vector<ListBoxItem> items;\r\n  {\r\n    DataFile<smalrec> file(FilePath(datadir, NAMES_LST), File::modeReadOnly | File::modeBinary,\r\n                           File::shareDenyWrite);\r\n    if (!file) {\r\n      show_error_no_users(window);\r\n      return -1;\r\n    }\r\n\r\n    const auto num_records = file.number_of_records();\r\n    for (auto i = 0; i < num_records; i++) {\r\n      smalrec name{};\r\n      if (!file.Read(&name)) {\r\n        messagebox(window, \"Error reading smalrec\");\r\n        return -1;\r\n      }\r\n      items.emplace_back(fmt::format(\"{} #{}\", reinterpret_cast<char*>(name.name), name.number), 0, name.number);\r\n    }\r\n  }\r\n\r\n  ListBox list(window, \"Select User\", items);\r\n  list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Select\"}, {\"/\", \"Filter\"}, {\"I\", \"Insert\"}});\r\n  if (const auto result = list.Run(); result.type == ListBoxResultType::SELECTION) {\r\n    return items[result.selected].data();\r\n  }\r\n  return -1;\r\n}\r\n\r\nstatic void write_semaphore_if_user_online(const wwiv::sdk::Config& config, int current_usernum) {\r\n  wwiv::sdk::Instances instances(config);\r\n  if (!instances) {\r\n    std::cout << \"Unable to read Instance information.\";\r\n    return;\r\n  }\r\n\r\n  for (const auto& inst : instances) {\r\n    if (!inst.online()) {\r\n      continue;\r\n    }\r\n    if (inst.user_number() != current_usernum) {\r\n      continue;\r\n    }\r\n    // we have user.\r\n    const auto path = config.scratch_dir(inst.node_number());\r\n    const auto fn = FilePath(path, \"readuser.wwiv\");\r\n    if (TextFile tf(fn, \"wt\"); tf) {\r\n      tf.Write(\"User edited in wwivconfig usereditor\");\r\n    }\r\n    return;\r\n  }\r\n}\r\n\r\nvoid user_editor(const wwiv::sdk::Config& config) {\r\n  if (config.userrec_length() != sizeof(userrec)) {\r\n    messagebox(curses_out->window(), \"Userrec size doesn't match. User Editor not allowed\");\r\n    return;\r\n  }\r\n  auto number_users = number_userrecs(config.datadir());\r\n  curses_out->Cls(ACS_CKBOARD);\r\n  auto need_names_list_rebuilt{false};\r\n\r\n  if (number_users < 1) {\r\n    std::unique_ptr<CursesWindow> window(curses_out->CreateBoxedWindow(\"User Editor\", 18, 76));\r\n    show_error_no_users(window.get());\r\n    return;\r\n  }\r\n\r\n  auto current_usernum = 1;\r\n  userrec user{};\r\n  read_user(config, current_usernum, &user);\r\n\r\n  auto* user_name_field =\r\n      new StringEditItem<unsigned char*>(30, user.name, EditLineMode::UPPER_ONLY);\r\n  user_name_field->set_displayfn(\r\n      // Not sure why but fmt::format(\"{} #{}\"...) was crashing on linux.\r\n      [&]() -> std::string { return StrCat(user.name, \" #\", current_usernum); });\r\n\r\n  auto* birthday_field = new CustomEditItem(\r\n      10,\r\n      [&]() -> std::string {\r\n        return fmt::sprintf(\"%2.2d/%2.2d/%4.4d\", user.month, user.day, user.year + 1900);\r\n      },\r\n      [&](const std::string& s) {\r\n        if (s[2] != '/' || s[5] != '/') {\r\n          return;\r\n        }\r\n        const auto month = to_number<uint8_t>(s.substr(0, 2));\r\n        if (month < 1 || month > 12) {\r\n          return;\r\n        }\r\n        const auto day = to_number<uint8_t>(s.substr(3, 2));\r\n        if (day < 1 || day > 31) {\r\n          return;\r\n        }\r\n        const auto year = to_number<int>(s.substr(6, 4));\r\n        const auto dt = DateTime::now();\r\n        if (const auto current_year = dt.year(); year < 1900 || year > current_year) {\r\n          return;\r\n        }\r\n        user.month = month;\r\n        user.day = day;\r\n        user.year = static_cast<uint8_t>(year - 1900);\r\n      });\r\n\r\n  auto* gender_field = new CustomEditItem(\r\n      1,\r\n      [&]() -> std::string {\r\n        return std::string(1, user.sex);\r\n      },\r\n      [&](const std::string& s) {\r\n        if (s.empty()) {\r\n          user.sex = 0;\r\n          return;\r\n        }\r\n        const auto g = to_upper_case_char(s.front());\r\n        user.sex = (g == 'U') ? 0 : g;\r\n      });\r\n\r\n  auto y = 1;\r\n  EditItems items{};\r\n  items.add(new Label(\"Name/Handle:\"), user_name_field, \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Real Name:\"),\r\n            new StringEditItem<unsigned char*>(20, user.realname, EditLineMode::ALL), \"\", 1, y);\r\n\r\n  // SL/DSL on same line now.\r\n  y++;\r\n  items.add(new Label(\"SL:\"),\r\n      new NumberEditItem<uint8_t>(&user.sl), \"\", 1, y);\r\n  items.add(new Label(\"DSL:\"),\r\n      new NumberEditItem<uint8_t>(&user.dsl), \"\", 3, y);\r\n  // AR/DAR\r\n  y++;\r\n  items.add(new Label(\"AR:\"), new ArEditItem(&user.ar), 1, y);\r\n  y++;\r\n  items.add(new Label(\"DAR:\"), new ArEditItem(&user.dar), 1, y);\r\n\r\n  y++;\r\n  items.add(new Label(\"Address:\"),\r\n      new StringEditItem<char*>(30, user.street, EditLineMode::ALL), \"\", 1, y);\r\n  y++;\r\n  items.add(  new Label(\"City:\"),\r\n      new StringEditItem<char*>(30, user.city, EditLineMode::ALL), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"State:\"),\r\n      new StringEditItem<char*>( 2, user.state, EditLineMode::ALL), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Postal Code:\"),\r\n      new StringEditItem<char*>(10, user.zipcode, EditLineMode::UPPER_ONLY), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Birthday:\"),\r\n      birthday_field, \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Password:\"),\r\n      new StringEditItem<char*>(8, user.pw, EditLineMode::UPPER_ONLY), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Phone Number:\"),\r\n      new StringEditItem<char*>(12, user.phone, EditLineMode::UPPER_ONLY), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Data Number:\"),\r\n      new StringEditItem<char*>(12, user.dataphone, EditLineMode::UPPER_ONLY), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Computer Type:\"),\r\n      new NumberEditItem<int8_t>(&user.comp_type), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Gender:\"),\r\n      gender_field, \"Enter (M)ale, (F)emale, (N)eed to ask again, (U)nused\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Restrictions:\"),\r\n      new RestrictionsEditItem(&user.restrict), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"WWIV Reg:\"),\r\n      new NumberEditItem<uint32_t>(&user.wwiv_regnum), \"\", 1, y);\r\n  y++;\r\n  items.add( new Label(\"Email Address:\"),\r\n      new StringEditItem<char*>(57, user.email, EditLineMode::ALL), \"\", 1, y);\r\n  y++;\r\n  items.add(new Label(\"Sysop Note:\"),\r\n      new StringEditItem<char*>(57, user.note, EditLineMode::ALL), \"\", 1, y);\r\n\r\n  items.add_aligned_width_column(1);\r\n  items.relayout_items_and_labels();\r\n  items.set_navigation_extra_help_items(create_extra_help_items());\r\n  items.create_window(\"User Editor\");\r\n  items.Display();\r\n  show_user(&items, &user);\r\n\r\n  const NavigationKeyConfig nav(\"DJR\\r\");\r\n  for (;;) {\r\n    switch (const auto ch = items.GetKeyWithNavigation(nav); ch) {\r\n    case '\\r': {\r\n      if (IsUserDeleted(&user)) {\r\n        items.window()->SetColor(SchemeId::ERROR_TEXT);\r\n        messagebox(items.window(), \"Can not edit a deleted user.\");\r\n      } else {\r\n        items.Run();\r\n        if (dialog_yn(items.window(), \"Save User?\")) {\r\n          write_user(config, current_usernum, &user);\r\n          write_semaphore_if_user_online(config, current_usernum);\r\n          need_names_list_rebuilt = true;\r\n        }\r\n      }\r\n      items.window()->Refresh();\r\n    } break;\r\n    case 'D': {\r\n      // Delete user.\r\n      wwiv::sdk::User u(user, current_usernum);\r\n      if (u.deleted()) {\r\n        break;\r\n      }\r\n      if (!dialog_yn(items.window(),\r\n                     StrCat(\"Are you sure you want to delete \", u.name(), \"? \"))) {\r\n        break;\r\n      }\r\n      if (wwiv::sdk::UserManager um(config); !um.delete_user(current_usernum)) {\r\n        messagebox(items.window(), \"Error trying to restore user.\");\r\n      }\r\n      need_names_list_rebuilt = true;\r\n    } break;\r\n    case 'J': {\r\n      if (const auto user_number = JumpToUser(items.window(), config.datadir()); user_number >= 1) {\r\n        current_usernum = user_number;\r\n      }\r\n    } break;\r\n    case 'R': {\r\n      if (wwiv::sdk::User u(user, current_usernum); !u.deleted()) {\r\n        break;\r\n      }\r\n      if (wwiv::sdk::UserManager um(config); !um.restore_user(current_usernum)) {\r\n        messagebox(items.window(), \"Error trying to restore user.\");\r\n      }\r\n      need_names_list_rebuilt = true;\r\n    } break;\r\n    case 'Q': {\r\n      if (need_names_list_rebuilt) {\r\n        // If we made changes here, let's be safe and rebuild\r\n        // the names.lst file.\r\n        wwiv::sdk::UserManager um(config);\r\n        wwiv::sdk::Names names(config);\r\n        names.set_save_on_exit(false);\r\n        names.Rebuild(um);\r\n        names.Save();\r\n      }      \r\n      return;\r\n    }\r\n    case ']':\r\n      if (++current_usernum > number_users) {\r\n        current_usernum = 1;\r\n      }\r\n      break;\r\n    case '[': {\r\n      if (--current_usernum < 1) {\r\n        current_usernum = number_users;\r\n      }\r\n    } break;\r\n    case '}':\r\n      current_usernum += 10;\r\n      if (current_usernum > number_users) {\r\n        current_usernum = number_users;\r\n      }\r\n      break;\r\n    case '{':\r\n      current_usernum -= 10;\r\n      if (current_usernum < 1) {\r\n        current_usernum = 1;\r\n      }\r\n      break;\r\n    default:\r\n      continue;\r\n    }\r\n\r\n    read_user(config, current_usernum, &user);\r\n    show_user(&items, &user);\r\n  }\r\n\r\n}\r\n"
  },
  {
    "path": "wwivconfig/user_editor.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*               Copyright (C)2014-2022, WWIV Software Services           */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_USER_EDITOR_H\r\n#define INCLUDED_WWIVCONFIG_USER_EDITOR_H\r\n\r\n#include \"sdk/config.h\"\r\n\r\nvoid user_editor(const wwiv::sdk::Config&);\r\n\r\n#endif // INCLUDED_WWIVCONFIG_USER_EDITOR_H"
  },
  {
    "path": "wwivconfig/utility.cpp",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n\r\n#include \"core/datafile.h\"\r\n#include \"core/file.h\"\r\n#include \"localui/input.h\"\r\n#include \"sdk/config.h\"\r\n#include \"sdk/filenames.h\"\r\n#include \"sdk/vardec.h\"\r\n\r\n#include <filesystem>\r\n#include <string>\r\n\r\n// Make sure it's after windows.h\r\n#include \"sdk/user.h\"\r\n\r\nusing namespace wwiv::core;\r\nusing namespace wwiv::sdk;\r\nusing namespace wwiv::strings;\r\n\r\nstatic void fix_user_rec(userrec* u) {\r\n  u->name[sizeof(u->name) - 1] = 0;\r\n  u->realname[sizeof(u->realname) - 1] = 0;\r\n  u->callsign[sizeof(u->callsign) - 1] = 0;\r\n  u->phone[sizeof(u->phone) - 1] = 0;\r\n  u->pw[sizeof(u->pw) - 1] = 0;\r\n  u->laston[sizeof(u->laston) - 1] = 0;\r\n  u->note[sizeof(u->note) - 1] = 0;\r\n  u->macros[0][sizeof(u->macros[0]) - 1] = 0;\r\n  u->macros[1][sizeof(u->macros[1]) - 1] = 0;\r\n  u->macros[2][sizeof(u->macros[2]) - 1] = 0;\r\n}\r\n\r\nint number_userrecs(const std::filesystem::path& datadir) {\r\n  if (const auto file =\r\n          DataFile<userrec>(FilePath(datadir, USER_LST),\r\n                            File::modeReadWrite | File::modeBinary | File::modeCreateFile,\r\n                            File::shareDenyReadWrite)) {\r\n    return file.number_of_records() - 1;\r\n  }\r\n  return -1;\r\n}\r\n\r\nvoid read_user(const Config& config, int un, userrec* u) {\r\n  if (auto file = DataFile<userrec>(FilePath(config.datadir(), USER_LST),\r\n                                    File::modeReadWrite | File::modeBinary | File::modeCreateFile,\r\n                                    File::shareDenyReadWrite)) {\r\n    if (const auto nu = file.number_of_records() - 1; un > nu) {\r\n      u->inact = User::userDeleted;\r\n      fix_user_rec(u);\r\n      return;\r\n    }\r\n    file.Seek(un);\r\n    file.Read(u);\r\n    fix_user_rec(u);\r\n  } else {\r\n    u->inact = User::userDeleted;\r\n    fix_user_rec(u);\r\n  }\r\n}\r\n\r\nvoid write_user(const Config& config, int un, userrec* u) {\r\n  if (un < 1 || un > config.max_users()) {\r\n    return;\r\n  }\r\n\r\n  if (auto file =\r\n          DataFile<userrec>(FilePath(config.datadir(), USER_LST),\r\n                            File::modeReadWrite | File::modeBinary | File::modeCreateFile)) {\r\n    file.Seek(un);\r\n    file.Write(u);\r\n  }\r\n}\r\n\r\nvoid save_status(const std::filesystem::path& datadir, const statusrec_t& statusrec) {\r\n  if (auto file =\r\n          DataFile<statusrec_t>(FilePath(datadir, STATUS_DAT),\r\n                                File::modeBinary | File::modeReadWrite | File::modeCreateFile)) {\r\n    file.Write(&statusrec);\r\n  }\r\n}\r\n\r\n/** returns true if \"status.dat\" is read correctly */\r\nbool read_status(const std::filesystem::path& datadir, statusrec_t& statusrec) {\r\n  if (auto file = DataFile<statusrec_t>(FilePath(datadir, STATUS_DAT),\r\n                                        File::modeBinary | File::modeReadWrite)) {\r\n    return file.Read(&statusrec);\r\n  }\r\n  return false;\r\n}\r\n"
  },
  {
    "path": "wwivconfig/utility.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_UTILITY_H\n#define INCLUDED_WWIVCONFIG_UTILITY_H\n\n#include <filesystem>\n#include <string>\n\nstruct statusrec_t;\nstruct userrec;\n\nnamespace wwiv::sdk {\n  class Config;\n}\n\nint number_userrecs(const std::filesystem::path& datadir);\nvoid save_status(const std::filesystem::path& datadir, const statusrec_t& statusrec);\nbool read_status(const std::filesystem::path& datadir, statusrec_t& statusrec);\nvoid read_user(const wwiv::sdk::Config& config, int un, userrec* u);\nvoid write_user(const wwiv::sdk::Config& config, int un, userrec* u);\n\n#endif\n"
  },
  {
    "path": "wwivconfig/wwivconfig.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/wwivconfig.h\"\n\n#include \"common/datetime.h\"\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"localui/curses_io.h\"\n#include \"localui/input.h\"\n#include \"localui/listbox.h\"\n#include \"localui/stdio_win.h\"\n#include \"localui/ui_win.h\"\n#include \"localui/wwiv_curses.h\"\n#include \"sdk/config.h\"\n#include \"sdk/config430.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/vardec.h\"\n#include \"wwivconfig/archivers.h\"\n#include \"wwivconfig/autoval.h\"\n#include \"wwivconfig/convert.h\"\n#include \"wwivconfig/editors.h\"\n#include \"wwivconfig/levels.h\"\n#include \"wwivconfig/menus.h\"\n#include \"wwivconfig/networks.h\"\n#include \"wwivconfig/newinit.h\"\n#include \"wwivconfig/paths.h\"\n#include \"wwivconfig/protocols.h\"\n#include \"wwivconfig/script_ui.h\"\n#include \"wwivconfig/subsdirs.h\"\n#include \"wwivconfig/sysop_account.h\"\n#include \"wwivconfig/system_info.h\"\n#include \"wwivconfig/user_editor.h\"\n#include \"wwivconfig/wwivd_ui.h\"\n\n#include <clocale>\n#include <cstdlib>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::wwivconfig::convert;\n\nstatic bool CreateConfigOvrAndUpdateSysConfig(Config& config, const std::string& bbsdir) {\n  IniFile oini(WWIV_INI, \"WWIV\");\n  auto num_instances = oini.value(\"NUM_INSTANCES\", 4);\n\n  std::vector<legacy_configovrrec_424_t> config_ovr_data;\n  for (auto i = 1; i <= num_instances; i++) {\n\n    // TEMP_DIRECTORY is defined in wwiv.ini, therefore use it over config.ovr, also\n    // default the batch_directory to TEMP_DIRECTORY if BATCH_DIRECTORY does not exist.\n    auto temp_directory = config.temp_format();\n    auto batch_directory = config.batch_format();\n\n    // Replace %n with instance number value.\n    const auto instance_num_string = std::to_string(i);\n    StringReplace(&temp_directory, \"%n\", instance_num_string);\n    StringReplace(&batch_directory, \"%n\", instance_num_string);\n\n    temp_directory = File::EnsureTrailingSlash(File::absolute(bbsdir, temp_directory));\n    batch_directory = File::EnsureTrailingSlash(File::absolute(bbsdir, batch_directory));\n\n    legacy_configovrrec_424_t r{};\n    r.primaryport = 1;\n    to_char_array(r.batchdir, batch_directory);\n    to_char_array(r.tempdir, temp_directory);\n\n    config_ovr_data.emplace_back(r);\n  }\n\n  DataFile<legacy_configovrrec_424_t> file(CONFIG_OVR, File::modeBinary | File::modeReadWrite |\n                                                           File::modeCreateFile |\n                                                           File::modeTruncate);\n  if (!file) {\n    LOG(ERROR) << \"Unable to open CONFIG.OVR for writing.\";\n    return false;\n  }\n\n  if (!file.WriteVector(config_ovr_data)) {\n    LOG(ERROR) << \"Unable to write to CONFIG.OVR.\";\n    return false;\n  }\n\n  // Duplicated from xinit.cpp\n  // Since we never save config.dat from the BBS, we need to also\n  // update them here so they'll get saved back to config.dat for\n  // legacy applications that use it.  This still needs to happen\n  // in the BBS anyway since we use the values there.\n  constexpr auto INI_STR_2WAY_CHAT = \"2WAY_CHAT\";\n  constexpr auto INI_STR_NO_NEWUSER_FEEDBACK = \"NO_NEWUSER_FEEDBACK\";\n  constexpr auto INI_STR_TITLEBAR = \"TITLEBAR\";\n  constexpr auto INI_STR_LOG_DOWNLOADS = \"LOG_DOWNLOADS\";\n  constexpr auto INI_STR_ALL_UL_TO_SYSOP = \"ALL_UL_TO_SYSOP\";\n  constexpr auto INI_STR_ALLOW_ALIASES = \"ALLOW_ALIASES\";\n  constexpr auto INI_STR_FREE_PHONE = \"FREE_PHONE\";\n  static std::vector<ini_flags_type> sysconfig_flags = {\n    {INI_STR_2WAY_CHAT, sysconfig_2_way},\n    {INI_STR_NO_NEWUSER_FEEDBACK, sysconfig_no_newuser_feedback},\n    {INI_STR_TITLEBAR, sysconfig_titlebar},\n    {INI_STR_LOG_DOWNLOADS, sysconfig_log_dl},\n    {INI_STR_ALL_UL_TO_SYSOP, sysconfig_all_sysop},\n    {INI_STR_ALLOW_ALIASES, sysconfig_allow_alias},\n    {INI_STR_FREE_PHONE, sysconfig_free_phone}};\n\n  config.set_sysconfig(oini.GetFlags(sysconfig_flags, config.sysconfig_flags()));\n\n  return true;\n}\n\nWWIVConfigApplication::WWIVConfigApplication() = default;\n\nWWIVConfigApplication::~WWIVConfigApplication() {\n  // Don't leak the localIO (also fix the color when the app exits)\n  delete curses_out;\n  curses_out = nullptr;\n}\n\nint main(int argc, char* argv[]) {\n  try {\n    LoggerConfig config(LogDirFromConfig);\n    Logger::Init(argc, argv, config);\n    auto at_exit = finally(Logger::ExitLogger);\n\n    const WWIVConfigApplication app{};\n    return app.Main(argc, argv);\n  } catch (const std::exception& e) {\n    LOG(INFO) << \"Fatal exception launching WWIVconfig: \" << e.what();\n  } catch (...) {\n    LOG(INFO) << \"Unknown fatal exception launching WWIVconfig.\";\n  }\n}\n\nstatic bool CreateSysopAccountIfNeeded(const std::string& bbsdir) {\n  Config config(bbsdir);\n  if (!config.IsInitialized()) {\n    // We only create the sysop account if we're in config.json mode.\n    return false;\n  }\n  {\n    const UserManager usermanager(config);\n    const auto num_users = usermanager.num_user_records();\n    for (auto n = 1; n <= num_users; n++) {\n      if (auto u = usermanager.readuser(n, UserManager::mask::non_deleted)) {\n        return true;\n      }\n    }\n  }\n\n  curses_out->Cls(ACS_CKBOARD);\n  if (!dialog_yn(curses_out->window(), \"Would you like to create a sysop account now?\")) {\n    messagebox(curses_out->window(), \"You will need to log in locally and manually create one\");\n    return true;\n  }\n\n  create_sysop_account(config);\n  return true;\n}\n\nstatic void ShowHelp(CommandLine& cmdline) {\n  std::cout << cmdline.GetHelp() << std::endl;\n  exit(1);\n}\n\nstatic bool config430_offsets_matches_actual(const Config430& config) {\n  File file(config.config_filename());\n  if (!file.Open(File::modeBinary | File::modeReadWrite)) {\n    return false;\n  }\n  configrec x{};\n  file.Read(&x, sizeof(configrec));\n\n  // update user info data\n  auto userreclen = static_cast<int16_t>(sizeof(userrec));\n  int16_t waitingoffset = offsetof(userrec, waiting);\n  int16_t inactoffset = offsetof(userrec, inact);\n  int16_t sysstatusoffset = offsetof(userrec, sysstatus);\n  int16_t fuoffset = offsetof(userrec, forwardusr);\n  int16_t fsoffset = offsetof(userrec, forwardsys);\n  int16_t fnoffset = offsetof(userrec, net_num);\n\n  if (userreclen != x.userreclen || waitingoffset != x.waitingoffset ||\n      inactoffset != x.inactoffset || sysstatusoffset != x.sysstatusoffset ||\n      fuoffset != x.fuoffset || fsoffset != x.fsoffset || fnoffset != x.fnoffset) {\n    return false;\n  }\n  return true;\n}\n\nstatic bool config_dat_or_json_exists() {\n  return File::Exists(CONFIG_DAT) || File::Exists(CONFIG_JSON);\n}\n\nbool legacy_4xx_menu(const Config430& config430, UIWindow* window) {\n  auto done = false;\n  auto selected = -1;\n\n  std::vector<arcrec> arcs;\n  Config config(config430.root_directory(), config430.to_json_config(arcs));\n  do {\n    curses_out->Cls(ACS_CKBOARD);\n    curses_out->footer()->SetDefaultFooter();\n\n    std::vector<ListBoxItem> items = {{\"N. Network Configuration\", 'N'},\n                                      {\"U. User Editor\", 'U'},\n                                      {\"W. wwivd Configuration\", 'W'},\n                                      {\"Q. Quit\", 'Q'}};\n\n    auto selected_hotkey = -1;\n    {\n      ListBox list(window, \"Main Menu\", items);\n      list.selection_returns_hotkey(true);\n      list.set_additional_hotkeys(\"$\");\n      list.set_selected(selected);\n      auto result = list.Run();\n      selected = list.selected();\n      if (result.type == ListBoxResultType::HOTKEY) {\n        selected_hotkey = result.hotkey;\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\n        done = true;\n      }\n    }\n    curses_out->footer()->SetDefaultFooter();\n\n    // It's easier to use the hotkey for this case statement so it's simple to know\n    // which case statement matches which item.\n    switch (selected_hotkey) {\n    case 'Q':\n      done = true;\n      break;\n    case 'N': {\n      std::set<int> need_network3;\n      networks(config, need_network3);\n    } break;\n    case 'U':\n      user_editor(config);\n      break;\n    case 'W':\n      wwivd_ui(config);\n      break;\n    case '$': {\n      std::vector<std::string> lines;\n      std::ostringstream ss;\n      ss << \"WWIV \" << full_version() << \" WWIVconfig compiled \" << wwiv_compile_datetime();\n      lines.push_back(ss.str());\n      lines.push_back(StrCat(\"QSCan Lenth: \", config.qscn_len()));\n      messagebox(window, lines);\n    } break;\n    default: ;\n    }\n    curses_out->SetIndicatorMode(IndicatorMode::none);\n  } while (!done);\n\n  return true;\n}\n\nint WWIVConfigApplication::Main(int argc, char** argv) const {\n  setlocale(LC_ALL, \"\");\n\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.AddStandardArgs();\n  cmdline.set_no_args_allowed(true);\n  cmdline.add_argument(BooleanCommandLineArgument(\n      \"initialize\", \"Initialize the datafiles for the 1st time and exit.\", false));\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"user_editor\", 'U', \"Run the user editor and then exit.\", false));\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"menu_editor\", 'M', \"Run the menu editor and then exit.\", false));\n  cmdline.add_argument(BooleanCommandLineArgument(\"network_editor\", 'N',\n                                                  \"Run the network editor and then exit.\", false));\n  cmdline.add_argument(\n      BooleanCommandLineArgument(\"4xx\", '4', \"Only run editors that work on WWIV 4.xx.\", false));\n\n  if (!cmdline.Parse() || cmdline.help_requested()) {\n    ShowHelp(cmdline);\n    return 0;\n  }\n\n  auto bbsdir = File::EnsureTrailingSlash(cmdline.bbsdir());\n  const auto forced_initialize = cmdline.barg(\"initialize\");\n  UIWindow* window;\n  if (forced_initialize) {\n    window = new StdioWindow(nullptr, new ColorScheme());\n  } else {\n    CursesIO::Init(fmt::format(\"WWIV {} Configuration Program.\", full_version()));\n    window = curses_out->window();\n    curses_out->Cls(ACS_CKBOARD);\n    window->SetColor(SchemeId::NORMAL);\n  }\n\n  if (forced_initialize && config_dat_or_json_exists()) {\n    messagebox(window, \"Unable to use --initialize when CONFIG.DAT exists.\");\n    return 1;\n  }\n\n  if (!config_dat_or_json_exists() || forced_initialize) {\n    // If this is true, we need to initialize\n    window->Bkgd(' ');\n    if (!new_init(window, bbsdir, true)) {\n      return 2;\n    }\n  }\n\n  auto legacy_4xx_mode = cmdline.barg(\"4xx\");\n  if (legacy_4xx_mode) {\n    Config430 config43(bbsdir);\n    if (!config430_offsets_matches_actual(config43)) {\n      return 1;\n    }\n    legacy_4xx_menu(config43, window);\n    return 0;\n  }\n\n  std::set<int> need_network3;\n\n  if (cmdline.barg(\"menu_editor\")) {\n    curses_out->Cls(ACS_CKBOARD);\n    curses_out->footer()->SetDefaultFooter();\n    Config config(bbsdir);\n    if (!config.IsInitialized() || legacy_4xx_mode) {\n      return 1;\n    }\n    menus(config);\n    return 0;\n  }\n  if (cmdline.barg(\"user_editor\")) {\n    curses_out->Cls(ACS_CKBOARD);\n    curses_out->footer()->SetDefaultFooter();\n    Config config(bbsdir);\n    if (!config.IsInitialized() || legacy_4xx_mode) {\n      return 1;\n    }\n    user_editor(config);\n    return 0;\n  }\n  if (cmdline.barg(\"network_editor\")) {\n    curses_out->Cls(ACS_CKBOARD);\n    curses_out->footer()->SetDefaultFooter();\n    Config config(bbsdir);\n    if (!config.IsInitialized() || legacy_4xx_mode) {\n      return 1;\n    }\n    networks(config, need_network3);\n    return 0;\n  }\n  \n  if (const auto config = load_any_config(bbsdir)) {\n    // Create archiver.dat with defaults if it does not exist.\n    {\n      File archiverfile(FilePath(config->datadir(), ARCHIVER_DAT));\n      if (!archiverfile.Open(File::modeBinary | File::modeReadOnly)) {\n        create_arcs(window, config->datadir());\n      }\n    }\n\n    // Create wwivd.json with defaults if it does not exist.\n    if (!File::Exists(FilePath(config->datadir(), \"wwivd.json\"))) {\n      auto c = LoadDaemonConfig(*config);\n      if (!SaveDaemonConfig(*config, c)) {\n        LOG(ERROR) << \"Error saving wwivd.json\";\n      }\n    }\n  } else {\n    messagebox(window, \"Unable to load any config: 4.24-5.x\");\n    return 1;\n  }\n\n  if (forced_initialize) {\n    return 0;\n  }\n\n  // This has to happen after --initialize since it needs a real curses UI.\n  CreateSysopAccountIfNeeded(bbsdir);\n\n  // Check for Upgrades needed.\n  if (do_wwiv_upgrades(window, bbsdir) == ShouldContinue::EXIT) {\n    return 1;\n  }\n\n  // We should be able to load a modern config.json here.\n  Config config(bbsdir);\n  if (!config.IsInitialized()) {\n    messagebox(window, \"Unable to load 5.6+ JSON config\");\n    return 1;\n  }\n\n  // We have a modern config, let's go.\n  auto done = false;\n  auto selected = -1;\n  do {\n    curses_out->Cls(ACS_CKBOARD);\n    curses_out->footer()->SetDefaultFooter();\n\n    std::vector<ListBoxItem> items = { {\"G. General System Configuration\", 'G'},\n                                       {\"P. System Paths\", 'P'},\n                                       {\"T. External Transfer Protocol Configuration\", 'T'},\n                                       {\"E. External Editor Configuration\", 'E'},\n                                       {\"S. Security Level Configuration\", 'S'},\n                                       {\"V. Auto-Validation Level Configuration\", 'V'},\n                                       {\"A. Archiver Configuration\", 'A'},\n                                       {\"M. Menu Editor\", 'M'},\n                                       {\"N. Network Configuration\", 'N'},\n                                       {\"U. User Editor\", 'U'},\n                                       {\"X. Update Sub/Directory Maximums\", 'X'},\n                                       {\"W. wwivd Configuration\", 'W'},\n                                       {\"R. Scripting Configuration\", 'R'},\n                                       {\"Q. Quit\", 'Q'} };\n\n    auto selected_hotkey = -1;\n    {\n      ListBox list(window, \"Main Menu\", items);\n      list.selection_returns_hotkey(true);\n      list.set_additional_hotkeys(\"$\");\n      list.set_selected(selected);\n      auto result = list.Run();\n      selected = list.selected();\n      if (result.type == ListBoxResultType::HOTKEY) {\n        selected_hotkey = result.hotkey;\n      } else if (result.type == ListBoxResultType::NO_SELECTION) {\n        done = true;\n      }\n    }\n    curses_out->footer()->SetDefaultFooter();\n\n    // It's easier to use the hotkey for this case statement so it's simple to know\n    // which case statement matches which item.\n    switch (selected_hotkey) {\n    case 'Q':\n      done = true;\n      break;\n    case 'G':\n      sysinfo1(config);\n      break;\n    case 'P':\n      setpaths(config);\n      break;\n    case 'T':\n      extrn_prots(config.datadir());\n      break;\n    case 'E':\n      extrn_editors(config);\n      break;\n    case 'S':\n      sec_levs(config);\n      break;\n    case 'V':\n      autoval_levs(config);\n      break;\n    case 'A':\n      edit_archivers(config);\n      break;\n    case 'N':\n      networks(config, need_network3);\n      break;\n    case 'M':\n      menus(config);\n      break;\n    case 'U':\n      user_editor(config);\n      break;\n    case 'W':\n      wwivd_ui(config);\n      break;\n    case 'R':\n      script_ui(config);\n      break;\n    case 'X':\n      up_subs_dirs(config);\n      break;\n    case '$': {\n      std::vector<std::string> lines;\n      lines.emplace_back(fmt::format(\"WWIV {} WWIVconfig compiled {}\", full_version(), wwiv_compile_datetime()));\n      lines.emplace_back(fmt::format(\"QScan Length: {}\", config.qscn_len()));\n      messagebox(window, lines);\n    } break;\n    default: break;\n    }\n    curses_out->SetIndicatorMode(IndicatorMode::none);\n  } while (!done);\n\n  config.Save();\n  // Write out config.ovr for compatibility reasons.\n  CreateConfigOvrAndUpdateSysConfig(config, bbsdir);\n\n  // Write out config.dat\n  auto c430 = std::make_unique<Config430>(config.root_directory(), config.to_config_t());\n  if (!c430 || !c430->Save()) {\n    LOG(INFO) << \"Failed to write legacy condig.dat\";\n  }\n\n  for (const auto nn : need_network3) {\n    const auto path = FilePath(File::current_directory(), \"network3\");\n    std::ostringstream ss;\n    ss << path;\n#ifdef _WIN32\n    ss << \".exe\";\n#endif\n    ss << \" .\" << nn << \" Y\";\n    system(ss.str().c_str());\n  }\n  return 0;\n}\n"
  },
  {
    "path": "wwivconfig/wwivconfig.h",
    "content": "/**************************************************************************/\r\n/*                                                                        */\r\n/*                  WWIV Initialization Utility Version 5                 */\r\n/*             Copyright (C)1998-2022, WWIV Software Services             */\r\n/*                                                                        */\r\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\r\n/*    you may not use this  file  except in compliance with the License.  */\r\n/*    You may obtain a copy of the License at                             */\r\n/*                                                                        */\r\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\r\n/*                                                                        */\r\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\r\n/*    software  distributed  under  the  License  is  distributed on an   */\r\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\r\n/*    either  express  or implied.  See  the  License for  the specific   */\r\n/*    language governing permissions and limitations under the License.   */\r\n/*                                                                        */\r\n/**************************************************************************/\r\n#ifndef INCLUDED_WWIVCONFIG_WWIVCONFIG_H\r\n#define INCLUDED_WWIVCONFIG_WWIVCONFIG_H\r\n\r\n/**\r\n * Main Application object for WWIV.\r\n */\r\nclass WWIVConfigApplication final {\r\n public:\r\n  WWIVConfigApplication();\r\n  ~WWIVConfigApplication();\r\n\r\n  int Main(int argc, char* argv[]) const;\r\n};\r\n\r\n\r\n#endif"
  },
  {
    "path": "wwivconfig/wwivconfig_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"core/test/wwivtest.h\"\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  try {\n    wwiv::core::test::InitTestForMain(argc, argv);\n    return RUN_ALL_TESTS();\n  }\n  catch (const std::exception& e) {\n    std::cerr << e.what();\n    return 1;\n  }\n}\n"
  },
  {
    "path": "wwivconfig/wwivd_ui.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivconfig/wwivd_ui.h\"\n\n#include \"core/strings.h\"\n#include \"localui/edit_items.h\"\n#include \"localui/input.h\"\n#include \"localui/listbox.h\"\n#include \"sdk/wwivd_config.h\"\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\n\nstatic void blocked_country_subdialog(const Config&, wwivd_blocking_t& b_, CursesWindow* window) {\n  auto done = false;\n  do {\n    std::vector<ListBoxItem> items;\n    for (const auto& e : b_.block_cc_countries) {\n      items.emplace_back(std::to_string(e));\n    }\n    ListBox list(window, \"Select Country Code\", items);\n\n    list.selection_returns_hotkey(true);\n    list.set_additional_hotkeys(\"DI\");\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\n    if (const auto result = list.Run(); result.type == ListBoxResultType::HOTKEY) {\n      switch (result.hotkey) {\n      case 'D': {\n        if (items.empty()) {\n          break;\n        }\n        if (!dialog_yn(window, StrCat(\"Delete '\", items[result.selected].text(), \"' ?\"))) {\n          break;\n        }\n        erase_at(b_.block_cc_countries, result.selected);\n      } break;\n      case 'I': {\n        const auto code_str =\n            dialog_input_string(window, \"Enter ISO-3166 Numeric Country Code: \", 8);\n        if (code_str.empty()) {\n          break;\n        }\n        auto code_num = to_number<int>(code_str);\n        if (const auto pos = result.selected; pos >= 0 && pos < size_int(items)) {\n          insert_at(b_.block_cc_countries, pos, code_num);\n        } else {\n          b_.block_cc_countries.push_back(code_num);\n        }\n      } break;\n      }\n    } else if (result.type == ListBoxResultType::SELECTION) {\n      auto& b = b_.block_cc_countries.at(result.selected);\n      const auto code_str = dialog_input_string(window, \"Enter ISO-3166 Numeric Country Code: \", 8);\n      if (code_str.empty()) {\n        break;\n      }\n      b = to_number<int>(code_str);\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\n      done = true;\n    }\n  } while (!done);\n}\n\n// Base item of an editable value, this class does not use templates.\nstatic void edit_blocking(const Config& config, wwivd_blocking_t& b, CursesWindow*) {\n  EditItems items{};\n  int y = 1;\n  items.add(new Label(\"Use goodip.txt?\"), new BooleanEditItem(&b.use_goodip_txt), \n    \"If enabled, use an allow-list in data/goodip.txt\", 1, y);\n\n  y++;\n  items.add(new Label(\"Use badip.txt?\"), new BooleanEditItem(&b.use_badip_txt), \n    \"If enabled, use an block-list in data/badip.txt\", 1, y);\n\n  y++;\n  items.add(new Label(\"Use CC Server?\"), new BooleanEditItem(&b.use_dns_cc), \n    \"Use a server to lookup country codes like (zz.countries.nerd.dk)\", 1, y);\n\n  y++;\n  items.add(new Label(\"DNS CC Server:\"),\n            new StringEditItem<std::string&>(40, b.dns_cc_server, EditLineMode::ALL), \n    \"DNS CC server to use (format must match that of zz.countries.nerd.dk)\", 1, y);\n\n  y++;\n  items.add(new Label(\"Blocked Countries:\"),\n            new SubDialogFunction<wwivd_blocking_t>(config, b, blocked_country_subdialog), \n    \"List of ISO 3166 country codes (numeric) to block\", 1, y);\n\n  y += 2;\n  items.add(new Label(\"Enable Auto Blocking?\"), new BooleanEditItem(&b.auto_blocklist), \n    \"Enable auto-blocking rules\", 1, y);\n  y++;\n  items.add(new Label(\"# connects needed to block:\"),\n            new NumberEditItem<int>(&b.auto_bl_sessions), \n    \"Auto-block X connection within Y seconds\", 1, y);\n  items.add(new Label(\"Within seconds:\"), new NumberEditItem<int>(&b.auto_bl_seconds),\n            \"Auto-block X connection within Y seconds\", 3, y);\n  y++;\n  if (b.block_duration.empty()) {\n    b.block_duration.emplace_back(\"15m\");\n  }\n  if (b.block_duration.size() < 2) {\n    b.block_duration.emplace_back(\"1h\");\n  }\n  if (b.block_duration.size() < 3) {\n    b.block_duration.emplace_back(\"1d\");\n  }\n  if (b.block_duration.size() < 4) {\n    b.block_duration.emplace_back(\"30d\");\n  }\n  items.add(new Label(\"Blocking Time #1:\"),\n            new StringEditItem<std::string&>(4, b.block_duration[0], EditLineMode::LOWER), \n    \"Amount of time to block when banning for the nth time\", 1, y);\n  items.add(new Label(\"#2:\"),\n            new StringEditItem<std::string&>(4, b.block_duration[1], EditLineMode::LOWER), \n    \"Amount of time to block when banning for the nth time\", 3, y);\n  items.add(new Label(\"#3:\"),\n            new StringEditItem<std::string&>(4, b.block_duration[2], EditLineMode::LOWER), \n    \"Amount of time to block when banning for the nth time\", 5, y);\n  items.add(new Label(\"#4:\"),\n            new StringEditItem<std::string&>(4, b.block_duration[3], EditLineMode::LOWER), \n    \"Amount of time to block when banning for the nth time\", 7, y);\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"Blocking Configuration\");\n}\n\nstatic void edit_matrix_entry(const Config& config, wwivd_matrix_entry_t& b) {\n  EditItems items{};\n  char key[2] = {b.key, 0};\n\n  const std::vector<std::pair<wwiv::sdk::wwivd_data_mode_t, std::string>> data_modes = {\n      {wwivd_data_mode_t::socket, \"Socket\"},\n      {wwivd_data_mode_t::pipe, \"Named Pipe\"}};\n\n  {\n    int y = 1;\n    items.add(new Label(\"Key:\"), \n      new StringEditItem<char*>(1, key, EditLineMode::ALL),\n      \"Key to press to select this bbs\", 1, y);\n    y++;\n    items.add(new Label(\"Name:\"), new StringEditItem<std::string&>(12, b.name, EditLineMode::ALL),\n              \"Name of the BBS (i.e WWIV)\", 1, y);\n    y++;\n    items.add(new Label(\"Description:\"),\n              new StringEditItem<std::string&>(52, b.description, EditLineMode::ALL),\n              \"Longer description for this BBS\", 1, y);\n    y++;\n    items.add(new Label(\"Working Dir:\"),\n              new StringFilePathItem(52, config.root_directory(), b.working_directory), \n              \"Directory to set as working directory when launching the BBS\", 1, y);\n    y++;\n    items.add(new Label(\"Telnet Command:\"),\n              new StringEditItem<std::string&>(52, b.telnet_cmd, EditLineMode::ALL), \n              \"Commandline to use when launching the BBS for a telnet connection\", 1, y);\n    y++;\n    items.add(new Label(\"SSH Command:\"),\n              new StringEditItem<std::string&>(52, b.ssh_cmd, EditLineMode::ALL), \n              \"Commandline to use when launching the BBS for a SSH connection\", 1, y);\n    y++;\n    items.add(new Label(\"Require Ansi:\"), new BooleanEditItem(&b.require_ansi), \n              \"Does this BBS require ANSI support\", 1, y);\n    y++;\n    items.add(new Label(\"Start Node:\"), new NumberEditItem<int>(&b.start_node), \n              \"Starting node number to use for telnet/SSH connections\", 1, y);\n    y++;\n    items.add(new Label(\"End Node:\"), new NumberEditItem<int>(&b.end_node), \n              \"Ending node number to use for telnet/SSH connections\", 1, y);\n    y++;\n    items.add(new Label(\"Local Node:\"), new NumberEditItem<int>(&b.local_node), \n              \"node number to use for local BBS session\", 1, y);\n    y++;\n    items.add(new Label(\"Data Mode:\"),\n              new ToggleEditItem<wwiv::sdk::wwivd_data_mode_t>(data_modes, &b.data_mode),\n              \"The way to communicate from wwivd to bbs (default is socket handle)\", 1, y);\n    y++;\n    items.add(new Label(\"WWIV BBS:\"), new BooleanEditItem(&b.wwiv_bbs),\n      \"Is this the primary WWIV BBS for this WWIVD.\", 1, y);\n  }\n\n  items.relayout_items_and_labels();\n  items.Run(StrCat(\"Matrix Config: \", b.name));\n  // Need to update key since we have no single char edit item.\n  b.key = key[0];\n}\n\nstatic void matrix_subdialog(const Config& config, wwivd_config_t& c, CursesWindow* window) {\n  auto done = false;\n  do {\n    std::vector<ListBoxItem> items;\n    for (const auto& e : c.bbses) {\n      items.emplace_back(e.name);\n    }\n    ListBox list(window, \"Select BBS\", items);\n\n    list.selection_returns_hotkey(true);\n    list.set_additional_hotkeys(\"DI\");\n    list.set_help_items({{\"Esc\", \"Exit\"}, {\"Enter\", \"Edit\"}, {\"D\", \"Delete\"}, {\"I\", \"Insert\"}});\n    if (auto result = list.Run(); result.type == ListBoxResultType::HOTKEY) {\n      switch (result.hotkey) {\n      case 'D': {\n        if (items.empty()) {\n          break;\n        }\n        if (!dialog_yn(window, StrCat(\"Delete '\", items[result.selected].text(), \"' ?\"))) {\n          break;\n        }\n        erase_at(c.bbses, result.selected);\n      } break;\n      case 'I': {\n        const auto name = dialog_input_string(window, \"Enter BBS Name: \", 8);\n        if (name.empty()) {\n          break;\n        }\n        wwivd_matrix_entry_t e{};\n        e.name = name;\n        e.key = name.front();\n        if (auto pos = result.selected; pos >= 0 && pos < size_int(items)) {\n          insert_at(c.bbses, pos, e);\n        } else {\n          c.bbses.push_back(e);\n        }\n      } break;\n      }\n    } else if (result.type == ListBoxResultType::SELECTION) {\n      auto& b = c.bbses.at(result.selected);\n      edit_matrix_entry(config, b);\n    } else if (result.type == ListBoxResultType::NO_SELECTION) {\n      done = true;\n    }\n  } while (!done);\n}\n\nstatic wwivd_matrix_entry_t CreateWWIVMatrixEntry() {\n  wwivd_matrix_entry_t e{};\n  e.key = 'W';\n  e.description = \"WWIV\";\n  e.name = \"WWIV\";\n  e.require_ansi = false;\n  e.start_node = 1;\n  e.end_node = 3;\n  e.local_node = 4;\n#if defined(__OS2__)\n  e.working_directory = File::current_directory().string();\n  e.telnet_cmd = File::FixPathSeparators(\"bbs.exe -XP -N@N\");\n  e.ssh_cmd = \"\";\n  e.data_mode = wwivd_data_mode_t::pipe;\n#else\n  e.telnet_cmd = File::FixPathSeparators(\"./bbs -XT -H@H -N@N\");\n  e.ssh_cmd = File::FixPathSeparators(\"./bbs -XS -H@H -N@N\");\n  e.data_mode = wwivd_data_mode_t::socket;\n#endif\n  return e;\n}\n\nbool SaveDaemonConfig(const wwiv::sdk::Config& config, wwivd_config_t& c) { return c.Save(config); }\n\nwwivd_config_t LoadDaemonConfig(const wwiv::sdk::Config& config) {\n  wwivd_config_t c{};\n  if (!c.Load(config)) {\n    c.binkp_port = -1;\n    c.ssh_port = 22;\n    c.telnet_port = 23;\n#if defined(__unix__)\n    c.telnet_port = 2323;\n#elif defined(__OS2__)\n    c.ssh_port = -1;\n#endif\n    c.http_port = 59948; // 5WWIV on the telephone keypad.\n    c.http_address = \"127.0.0.1\";\n    c.binkp_cmd = File::FixPathSeparators(\"./networkb --receive --handle=@H\");\n    c.network_callout_cmd = File::FixPathSeparators(\"./networkb --send --net=@T --node=@N\");\n    c.beginday_cmd = File::FixPathSeparators(\"./bbs -e\");\n\n    c.bbses.push_back(CreateWWIVMatrixEntry());\n  } else {\n    if (c.network_callout_cmd.empty()) {\n      c.network_callout_cmd = File::FixPathSeparators(\"./networkb --send --net=@T --node=@N\");\n    }\n    if (c.beginday_cmd.empty()) {\n      c.beginday_cmd = File::FixPathSeparators(\"./bbs -e\");\n    }\n    if (c.binkp_cmd.empty()) {\n      c.binkp_cmd = File::FixPathSeparators(\"./networkb --receive --handle=@H\");\n    }\n  }\n\n  if (c.bbses.empty()) {\n    // If we have no entries in the Matrix, then let's add\n    // a default entry for WWIV.\n    c.bbses.push_back(CreateWWIVMatrixEntry());\n  }\n  return c;\n}\n\nvoid wwivd_ui(const Config& config) {\n  auto c = LoadDaemonConfig(config);\n\n  EditItems items{};\n  auto y = 1;\n  items.add(new Label(\"Telnet Port:\"),\n            new NumberEditItem<int>(&c.telnet_port),\n            \"Telnet Server Port Number (or -1 to disable).\", 1, y);\n  items.add(new Label(\"SSH Port:\"),\n            new NumberEditItem<int>(&c.ssh_port),\n            \"SSH Server Port Number (or -1 to disable).\", 3, y);\n  y++;\n  items.add(\n      new Label(\"Status Address:\"),\n      new StringEditItem<std::string&>(16, c.http_address, EditLineMode::ALL),\n      \"Network address for the BBS node status HTTP Server.\", 1, y);\n  items.add(new Label(\"Status Port:\"),\n            new NumberEditItem<int>(&c.http_port),\n            \"Used for BBS node status [/status] (or -1 to disable).\", 3, y);\n  y++;\n  items.add(new Label(\"BinkP Port:\"),\n            new NumberEditItem<int>(&c.binkp_port),\n            \"BINKP Server Port Number (or -1 to disable).\", 1, y);\n  y++;\n  items.add(new Label(\"Fake Mailer?\"), new BooleanEditItem(&c.blocking.mailer_mode), \n    \"Emulate legacy FTN mailer with a 'Press <ESC> for BBS' prompt as a captcha.\", 1, y);\n  y++;\n  items.add(new Label(\"Max Concurrent:\"),\n            new NumberEditItem<int>(&c.blocking.max_concurrent_sessions), \n    \"Maximum number of concurrent sessions allowed per IP address.\", 1, y);\n  y+=2;\n  items.add(new Label(\"Launch Minimized:\"),\n            new BooleanEditItem(&c.launch_minimized),\n            \"Should wwivd launch bbs and network commands minimized (WIN32 Only)\", 1, y);\n  y++;\n  items.add(new Label(\"Run BeginDay:\"),\n            new BooleanEditItem(&c.do_beginday_event),\n            \"Should wwivd execute the beginday event for WWIV.\", 1, y);\n  y++;\n  items.add(\n      new Label(\"BeginDay Cmd:\"),\n      new StringEditItem<std::string&>(52, c.beginday_cmd, EditLineMode::ALL),\n      \"Command to execute for the beginday event.\", 1, y);\n\n  y+=2;\n  items.add(new Label(\"Net Callouts:\"),\n            new BooleanEditItem(&c.do_network_callouts),\n            \"Command to execute to perform a network callout.\", 1, y);\n\n  y++;\n  items.add(new Label(\"Net Callout Cmd:\"),\n            new StringEditItem<std::string&>(52, c.network_callout_cmd,\n                                             EditLineMode::ALL),\n            \"Command to execute to perform a network callout.\", 1, y);\n  y++;\n  items.add(new Label(\"Net receive cmd:\"),\n            new StringEditItem<std::string&>(52, c.binkp_cmd, EditLineMode::ALL),\n            \"Command to execute for an inbound network request.\", 1, y);\n  y+=2;\n  items.add(\n      new Label(\"Matrix Filename:\"),\n      new StringEditItem<std::string&>(12, c.matrix_filename, EditLineMode::ALL),\n      \"Filename to display without extension before matrix bbs menu.\", 1, y);\n  y++;\n  items.add(new Label(\"Matrix Settings:\"),\n            new SubDialogFunction<wwivd_config_t>(config, c, matrix_subdialog),\n            \"Create/Edit/Delete Matrix BBS settings.\", 1, y);\n  y++;\n  items.add(\n      new Label(\"Blocking:\"),\n      new SubDialogFunction<wwivd_blocking_t>(config, c.blocking, edit_blocking),\n      \"IP Blocking Settings.\", 1, y);\n\n  items.add_aligned_width_column(1);\n  items.relayout_items_and_labels();\n  items.Run(\"wwivd Configuration\");\n  if (!SaveDaemonConfig(config, c)) {\n    messagebox(items.window(), \"Error saving wwivd.json\");\n  }\n}\n"
  },
  {
    "path": "wwivconfig/wwivd_ui.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                  WWIV Initialization Utility Version 5                 */\n/*               Copyright (C)2014-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVCONFIG_WWIVD_UI_H\n#define INCLUDED_WWIVCONFIG_WWIVD_UI_H\n\n#include \"sdk/config.h\"\n#include \"sdk/wwivd_config.h\"\n\nvoid wwivd_ui(const wwiv::sdk::Config& config);\nwwiv::sdk::wwivd_config_t LoadDaemonConfig(const wwiv::sdk::Config& config);\nbool SaveDaemonConfig(const wwiv::sdk::Config& config, wwiv::sdk::wwivd_config_t& c);\n\n#endif // INCLUDED_WWIVCONFIG_WWIVD_UI_H\n"
  },
  {
    "path": "wwivd/CMakeLists.txt",
    "content": "# CMake for WWIV Daemon\n\nfind_package(nlohmann_json CONFIG REQUIRED)\n\nset(WWIVD_SOURCES \n\tips.cpp\n\tnets.cpp\n    node_manager.cpp\n    wwivd_http.cpp\n    wwivd_non_http.cpp\n    )\n\nset(WWIVD_MAIN wwivd.cpp)\n\nif (UNIX)\n  find_package (Threads)\n  list(APPEND WWIVD_SOURCES wwivd_unix.cpp)\n  if(CMAKE_SYSTEM_NAME MATCHES \"SunOS.*\")\n    set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl -lkstat -lssp\")\n  endif()\nelseif(WIN32)\n    list(APPEND WWIVD_SOURCES wwivd_win.cpp)\nelseif(OS2)\n  list(APPEND WWIVD_SOURCES wwivd_os2.cpp)\nendif()\n\nadd_library(wwivd_lib ${WWIVD_SOURCES})\nset_max_warnings(wwivd_lib)\ntarget_link_libraries(wwivd_lib sdk core sdk ${CMAKE_THREAD_LIBS_INIT})\nadd_executable(wwivd ${WWIVD_MAIN})\ntarget_link_libraries(wwivd wwivd_lib)\n\n## Tests\nif (WWIV_BUILD_TESTS)\n\n  set(test_sources\n    wwivd_non_http_test.cpp\n  )\n  list(APPEND test_sources wwivd_test_main.cpp)\n\n  add_executable(wwivd_tests ${test_sources})\n  set_max_warnings(wwivd_tests)\n  target_link_libraries(wwivd_tests wwivd_lib core_fixtures core sdk GTest::gtest)\n  gtest_discover_tests(wwivd_tests)\n\nendif()\n\n\n"
  },
  {
    "path": "wwivd/connection_data.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef __INCLUDED_WWIVD_CONNECTION_DATA_H__\n#define __INCLUDED_WWIVD_CONNECTION_DATA_H__\n\n#include \"core/net.h\"\n#include \"sdk/config.h\"\n#include \"sdk/wwivd_config.h\"\n#include \"wwivd/ips.h\"\n#include \"wwivd/node_manager.h\"\n#include <map>\n#include <memory>\n\nnamespace wwiv {\nnamespace wwivd {\n\nstruct ConnectionData {\n  ConnectionData(const ::wwiv::sdk::Config* g, const wwiv::sdk::wwivd_config_t* t,\n    std::map<const std::string, std::shared_ptr<NodeManager>>* n,\n    std::shared_ptr<ConcurrentConnections> concurrent_connections)\n      : config(g), c(t), nodes(n), concurrent_connections_(concurrent_connections) {}\n  const wwiv::sdk::Config* config;\n  const wwiv::sdk::wwivd_config_t* c;\n  std::map<const std::string, std::shared_ptr<NodeManager>>* nodes;\n  std::shared_ptr<ConcurrentConnections> concurrent_connections_;\n  std::shared_ptr<GoodIp> good_ips_;\n  std::shared_ptr<BadIp> bad_ips_;\n  std::shared_ptr<AutoBlocker> auto_blocker_;\n};\n\n}  // namespace wwivd\n}  // namespace wwiv\n\n#endif  // __INCLUDED_WWIVD_CONNECTION_DATA_H__\n"
  },
  {
    "path": "wwivd/ips.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivd/ips.h\"\n\n#include \"core/clock.h\"\n#include \"core/datetime.h\"\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"wwivd/connection_data.h\"\n#include <cereal/archives/json.hpp>\n#include <cereal/types/memory.hpp>\n#include <map>\n#include <memory>\n#include <string>\n#include <unordered_set>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::wwivd {\n\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nstatic bool LoadLinesIntoSet(std::unordered_set<std::string>& s, const std::vector<std::string>& lines) {\n  for (auto line : lines) {\n    const auto space = line.find(' ');\n    if (space != std::string::npos) {\n      line = line.substr(0, space);\n    }\n    s.emplace(StringTrim(line));\n  }\n  return true;\n}\n\nGoodIp::GoodIp(const std::vector<std::string>& lines) { (void)LoadLines(lines); }\n\nbool GoodIp::LoadLines(const std::vector<std::string>& lines) {\n  return LoadLinesIntoSet(ips_, lines);\n}\n\nGoodIp::GoodIp(const std::filesystem::path& fn) {\n  TextFile f(fn, \"r\");\n  if (f) {\n    const auto lines = f.ReadFileIntoVector();\n    (void)LoadLines(lines);\n  }\n}\n\nbool GoodIp::IsAlwaysAllowed(const std::string& ip) {\n  if (ips_.empty()) {\n    return false;\n  }\n  return ips_.find(ip) != ips_.end();\n}\n\nBadIp::BadIp(const std::filesystem::path& fn, Clock& clock) : fn_(fn), clock_(clock) {\n  TextFile f(fn, \"r\");\n  if (f) {\n    const auto lines = f.ReadFileIntoVector();\n    LoadLinesIntoSet(ips_, lines);\n  }\n}\n\nbool BadIp::IsBlocked(const std::string& ip) {\n  if (ips_.empty()) {\n    return false;\n  }\n  return ips_.find(ip) != ips_.end();\n}\nbool BadIp::Block(const std::string& ip) {\n  ips_.emplace(ip);\n  TextFile appender(fn_, \"at\");\n  const auto now = clock_.Now();\n  const auto written =\n      appender.WriteLine(StrCat(ip, \" # AutoBlocked by wwivd on: \", now.to_string(\"%FT%T\")));\n  return written > 0;\n}\n\nAutoBlocker::AutoBlocker(std::shared_ptr<BadIp> bip, wwivd_blocking_t b, std::filesystem::path datadir, Clock& clock)\n    : bip_(std::move(bip)), b_(std::move(b)), datadir_(std::move(datadir)), clock_(clock) {\n  if (b_.block_duration.empty()) {\n    b_.block_duration.emplace_back(\"15m\");\n  }\n  if (b_.block_duration.size() < 2) {\n    b_.block_duration.emplace_back(\"1h\");\n  }\n  if (b_.block_duration.size() < 3) {\n    b_.block_duration.emplace_back(\"1d\");\n  }\n  if (b_.block_duration.size() < 4) {\n    b_.block_duration.emplace_back(\"30d\");\n  }\n  auto modified = !Load();\n\n  // Cleanup the autoblock list.\n  const auto now = clock_.Now().to_time_t();\n  for (auto iter = std::begin(auto_blocked_); iter != std::end(auto_blocked_); ) {\n    if (iter->second.expiration < now) {\n      LOG(INFO) << \"Removing Entry from autoblock list: \" << iter->first;\n      iter = auto_blocked_.erase(iter);\n      modified = true;\n    } else {\n      ++iter;\n    }\n  }\n  if (modified) {\n    Save();\n  }\n}\n\nAutoBlocker::~AutoBlocker() = default;\n\n\nvoid AutoBlocker::escalate_block(const std::string& ip) {\n  LOG(INFO) << \"escalate_block: \" << ip;\n  auto& item = auto_blocked_[ip];\n  const auto now = clock_.Now();\n  ++item.count;\n  if (item.count <= size_int(b_.block_duration)) {\n    const auto bt = parse_time_span(at(b_.block_duration, item.count - 1)).value_or(std::chrono::minutes(10));\n    LOG(INFO) << \"escalate_block: count: \" << item.count << \"; new blocked time: \" << wwiv::core::to_string(bt);\n    const auto exp = now + bt;\n    item.expiration = exp.to_time_t();\n  } else {\n    LOG(INFO) << \"escalate_block: permanent block; count: \" << item.count;\n    // We've run out of auto-blocks.  Replace this with the permanent one.\n    auto_blocked_.erase(ip);\n    bip_->Block(ip);\n  }\n  Save();\n}\n\nbool AutoBlocker::Connection(const std::string& ip) {\n  VLOG(1) << \"AutoBlocker::Connection: Checking status for: \" << ip;\n  if (!b_.auto_blocklist) {\n    return true;\n  }\n\n  const auto now = clock_.Now();\n\n  //\n  // Synchronized from here on down\n  //\n  std::lock_guard<std::mutex> lock(mu_);\n\n  if (blocked(ip)) {\n    // We have an auto-block and we're still blocked.\n    LOG(INFO) << \"Still in auto-block for ip: \" << ip;\n    return false;\n  }\n\n  const auto auto_bl_sessions = b_.auto_bl_sessions;\n  const auto auto_bl_seconds = b_.auto_bl_seconds;\n  const auto oldest_in_window = now.to_time_t() - auto_bl_seconds;\n\n  auto& s = sessions_[ip];\n  s.emplace(now.to_time_t());\n  if (s.size() == 1) {\n    VLOG(1) << \"OK: num sessions: \" << size_int(s);\n    return true;\n  }\n\n  for (auto iter = s.begin(); iter != s.end();) {\n    if (*iter < oldest_in_window) {\n      VLOG(1) << \"Erasing old session for IP: \" << ip;\n      iter = s.erase(iter);\n    } else {\n      ++iter;\n    }\n  }\n\n  if (ssize(s) >= auto_bl_sessions) {\n    LOG(INFO) << \"Blocking since we have \" << s.size() << \" sessions within \" << auto_bl_seconds\n              << \" seconds.\";\n    // Don't do the hard block here, just escalate.\n    escalate_block(ip);\n    return false;\n  }\n  VLOG(1) << \"OK: num sessions: \" << size_int(s);\n  return true;\n}\n\ntemplate <class Archive>\nvoid serialize(Archive & ar, auto_blocked_entry_t &a) {\n  SERIALIZE(a, count);\n  SERIALIZE(a, expiration);\n}\n\nbool AutoBlocker::Save() {\n  LOG(INFO) << \"AutoBlocker: Save\";\n  JsonFile<std::map<std::string, auto_blocked_entry_t>> file(FilePath(datadir_, \"wwivd.autoblock.json\"), \"autoblock\", auto_blocked_);\n  return file.Save();\n}\n\nbool AutoBlocker::blocked(const std::string& ip) const {\n  const auto now = clock_.Now();\n  if (const auto iter = auto_blocked_.find(ip); iter != std::end(auto_blocked_)) {\n    if (iter->second.expiration > now.to_time_t()) {\n      // We have an auto-block and we're still blocked.\n      LOG(INFO) << \"Still in auto-block for ip: \" << ip;\n      return true;\n    }\n    // TODO: We're good.  Remove this entry once it ages out, what'd be an appropriate age? 1d? 1week? 1 month?\n    // auto_blocked_.erase(iter);\n    // Save();\n  }\n  return false;\n}\n\nbool AutoBlocker::Load() {\n  VLOG(1) << \"AutoBlocker: Load\";\n  JsonFile<std::map<std::string, auto_blocked_entry_t>> file(FilePath(datadir_, \"wwivd.autoblock.json\"), \"autoblock\", auto_blocked_);\n  return file.Load();\n}\n\n} // namespace wwiv::wwivd\n"
  },
  {
    "path": "wwivd/ips.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVD_IPS_H\n#define INCLUDED_WWIVD_IPS_H\n\n#include \"core/clock.h\"\n#include \"sdk/wwivd_config.h\"\n#include <ctime>\n#include <filesystem>\n#include <memory>\n#include <mutex>\n#include <set>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n\nnamespace wwiv::wwivd {\n\nusing namespace wwiv::core;\n\nclass GoodIp {\npublic:\n  explicit GoodIp(const std::filesystem::path& fn);\n  explicit GoodIp(const std::vector<std::string>& lines);\n  [[nodiscard]] bool IsAlwaysAllowed(const std::string& ip);\n\nprivate:\n  [[nodiscard]] bool LoadLines(const std::vector<std::string>& ips);\n  std::unordered_set<std::string> ips_;\n};\n\nclass BadIp {\npublic:\n  BadIp(const std::filesystem::path& fn, Clock& clock);\n  [[nodiscard]] bool IsBlocked(const std::string& ip);\n  bool Block(const std::string& ip);\n\nprivate:\n  const std::filesystem::path fn_;\n  std::unordered_set<std::string> ips_;\n  Clock& clock_;\n};\n\nstruct auto_blocked_entry_t {\n  int count{0};\n  time_t expiration{0};\n};\n\nclass AutoBlocker final {\npublic:\n  AutoBlocker(std::shared_ptr<BadIp> bip, sdk::wwivd_blocking_t b, std::filesystem::path datadir, Clock& clock);\n  ~AutoBlocker();\n  void escalate_block(const std::string& ip);\n  bool Connection(const std::string& ip);\n  bool Save();\n\n  // Used for testing\n  const std::map<std::string, std::set<time_t>>& recent_sessions() const { return sessions_; }\n  // Used for testing\n  const std::map<std::string, auto_blocked_entry_t>& auto_blocked() const { return auto_blocked_; }\n\n  [[nodiscard]] bool blocked(const std::string& ip) const;\n\nprivate:\n  bool Load();\n  std::shared_ptr<BadIp> bip_;\n  sdk::wwivd_blocking_t b_;\n  std::filesystem::path datadir_;\n  std::map<std::string, std::set<time_t>> sessions_;\n  std::map<std::string, auto_blocked_entry_t> auto_blocked_;\n  Clock& clock_;\n  std::mutex mu_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "wwivd/nets.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/status.h\"\n#include \"sdk/fido/fido_callout.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/callouts.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/networks.h\"\n#include \"wwivd/connection_data.h\"\n#include \"wwivd/wwivd.h\"\n#include \"wwivd/wwivd_non_http.h\"\n\n#include <atomic>\n#include <map>\n#include <memory>\n#include <string>\n#include <thread>\n#include <vector>\n\nnamespace wwiv::wwivd {\n\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nstd::atomic<bool> need_to_exit;\nstd::atomic<bool> need_to_reload_config;\n\n// TODO(rushfan): Add tests for new stuff in here.\n\nstatic NetworkContact network_contact_from_last_time(const fido::FidoAddress& address,\n                                                     const DateTime& t, int ftn_bytes_waiting) {\n  network_contact_record ncr{};\n  ncr.address = address.as_string();\n  ncr.ncr.bytes_waiting = ftn_bytes_waiting;\n  ncr.ncr.lastcontact = t.to_daten_t();\n  ncr.ncr.lasttry = t.to_daten_t();\n  return NetworkContact{ncr};\n}\n\nstatic void one_net_ftn_callout(const Config& config, const Network& net, const wwivd_config_t& c,\n                                std::shared_ptr<NodeManager> nodes, int network_number) {\n  const fido::FidoCallout callout(config.root_directory(), config.max_backups(), net);\n\n  // TODO(rushfan): 1. Right now we just keep the map of last call-out\n  // time in memory, but we should checkpoint this to disk and reload\n  // on startup.\n  // 2. Also we should look for files outbound to the node so that we can\n  // handle min_k right.\n  // 3. We should look for outbound files to other addresses we don't\n  // know about and then figure out how to contact them (since their\n  // address is in the nodelist_.\n  static std::map<int, std::map<fido::FidoAddress, time_t>> last_contact;\n  auto& current_last_contact = last_contact[network_number];\n\n  for (const auto& [address, node_config] : callout.node_configs_map()) {\n    const auto& callout_config = node_config.callout_config;\n    if (!allowed_to_call(callout_config)) {\n      // Is the call out bit set.\n      continue;\n    }\n    auto ncn = network_contact_from_last_time(address,\n                                              DateTime::from_time_t(current_last_contact[address]),\n                                              ftn_bytes_waiting(net, address));\n    if (!should_call(ncn, callout_config, DateTime::now())) {\n      // Has it been long enough, or do we have enough k waiting.\n      continue;\n    }\n    // 1: Update the last contact time to now.\n    current_last_contact[address] = DateTime::now().to_time_t();\n    // 2: Call it.\n    LOG(INFO) << \"ftn: should call out to: \" << address.as_string() << \".\" << net.name;\n    const std::map<char, std::string> params = {{'N', address.as_string()},\n                                           {'T', std::to_string(network_number)}};\n    const auto cmd = CreateCommandLine(c.network_callout_cmd, params);\n    if (!ExecCommandAndWait(c, *nodes, cmd, StrCat(\"[\", get_pid(), \"]\"), -1, INVALID_SOCKET)) {\n      LOG(ERROR) << \"Error executing command: '\" << cmd << \"'\";\n    }\n  }\n}\n\nstatic void one_net_wwivnet_callout(const Network& net, const wwivd_config_t& c,\n                                    std::shared_ptr<NodeManager> nodes, int network_number) {\n  VLOG(2) << \"one_net_wwivnet_callout: @\" << net.sysnum << \"; name: \" << net.name;\n  Contact contact(net);\n  const Callout callout(net, 0);\n  for (const auto& kv : callout.callout_config()) {\n    VLOG(2) << \"one_net_wwivnet_callout: node @\" << kv.first;\n    auto* const ncn = contact.contact_rec_for(kv.first);\n    if (ncn == nullptr) {\n      VLOG(2) << \"ncn == nullptr for node @\" << kv.first;\n      continue;\n    }\n    if (!allowed_to_call(kv.second, DateTime::now())) {\n      VLOG(2) << \"!allowed_to_call: #\" << kv.second.sysnum;\n      continue;\n    }\n    if (!should_call(*ncn, kv.second, DateTime::now())) {\n      VLOG(2) << \"!should_call: #\" << kv.second.sysnum;\n      continue;\n    }\n    // Call it.\n    LOG(INFO) << \"should call out to: \" << kv.first << \".\" << net.name;\n    const std::map<char, std::string> params = {{'N', std::to_string(kv.first)},\n                                           {'T', std::to_string(network_number)}};\n    const auto cmd = CreateCommandLine(c.network_callout_cmd, params);\n    if (!ExecCommandAndWait(c, *nodes, cmd, StrCat(\"[\", get_pid(), \"]\"), -1, INVALID_SOCKET)) {\n      LOG(ERROR) << \"Error executing command: \" << cmd;\n    }\n  }\n}\n\nstatic void one_callout_loop(const Config& config, const wwivd_config_t& c, std::shared_ptr<NodeManager> nodes) {\n  VLOG(1) << \"do_wwivd_callouts: one_callout_loop: \";\n  const Networks networks(config);\n  const auto& nets = networks.networks();\n  auto network_number = 0;\n  for (const auto& net : nets) {\n    if (net.type == network_type_t::wwivnet) {\n      one_net_wwivnet_callout(net, c, nodes, network_number++);\n    } else if (net.type == network_type_t::ftn) {\n      one_net_ftn_callout(config, net, c, nodes, network_number++);\n    }\n  }\n}\n\n// This is called from the thread\nstatic void do_wwivd_callout_loop(const Config& config, const wwivd_config_t& original_config,\n                                  std::shared_ptr<NodeManager> nodes) {\n  auto c{original_config};\n\n  StatusMgr sm(config.datadir(), [](int) {});\n  auto e = need_to_exit.load();\n  auto last_callout = DateTime::now().to_system_clock();\n  while (!e) {\n    // Reload the config if we've gotten a HUP?\n    if (need_to_reload_config.load()) {\n      LOG(INFO) << \"Received HUP: Reloading Configuration for Callouts.\";\n      need_to_reload_config.store(false);\n      c.Load(config);\n    }\n    if (c.do_network_callouts) {\n      if (auto now = DateTime::now().to_system_clock(); now - last_callout > 60s) {\n        last_callout = DateTime::now().to_system_clock();\n        one_callout_loop(config, c, nodes);\n      }\n    }\n    if (need_to_exit.load()) {\n      return;\n    }\n    sleep_for(5s);\n    e = need_to_exit.load();\n\n    if (c.do_beginday_event) {\n      const auto last_date_status = sm.get_status();\n      auto ld = last_date_status->last_date();\n      const auto d = date();\n      VLOG(4) << \"Doing beginday check\";\n      if (d != ld) {\n        LOG(INFO) << \"Executing beginday event. (\" << d << \" != \" << ld << \")\";\n        const std::map<char, std::string> params{};\n        const auto cmd = CreateCommandLine(c.beginday_cmd, params);\n        if (!ExecCommandAndWait(c, *nodes, cmd, StrCat(\"[\", get_pid(), \"]\"), -1, INVALID_SOCKET)) {\n          LOG(ERROR) << \"Error executing [BeginDay Event]: '\" << cmd << \"'\";\n        }\n      }\n    }\n  }\n}\n\nvoid do_wwivd_callouts(const Config& config, const wwivd_config_t& c, std::shared_ptr<NodeManager> nodes) {\n  if (c.do_network_callouts) {\n    LOG(INFO) << \"WWIVD is handling network callouts.\";\n  }\n  if (c.do_beginday_event) {\n    LOG(INFO) << \"WWIVD is handling beginday event.\";\n  }\n  std::thread callout_thread(do_wwivd_callout_loop, std::cref(config), std::cref(c), nodes);\n  callout_thread.detach();\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivd/nets.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVD_NETS_H\n#define INCLUDED_WWIVD_NETS_H\n#include <memory>\n\n#include \"sdk/config.h\"\n// ReSharper disable once CppUnusedIncludeDirective\n#include \"sdk/wwivd_config.h\"\n\nnamespace wwiv::wwivd {\nclass NodeManager;\n\nvoid do_wwivd_callouts(const sdk::Config& config, const sdk::wwivd_config_t& c, std::shared_ptr<NodeManager> nodes);\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "wwivd/node_manager.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivd/node_manager.h\"\n\n#include \"sdk/config.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/wwivd_config.h\"\n\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include <chrono>\n#include <memory>\n#include <mutex>\n#include <unordered_map>\n\nusing wwiv::stl::contains;\n\nnamespace wwiv::wwivd {\n\nstd::string to_string(ConnectionType t) {\n  switch (t) {\n  case ConnectionType::BINKP:\n    return \"BinkP\";\n  case ConnectionType::HTTP:\n    return \"HTTP\";\n  case ConnectionType::SSH:\n    return \"SSH\";\n  case ConnectionType::TELNET:\n    return \"Telnet\";\n  case ConnectionType::UNKNOWN:\n    return \"*UNKNOWN*\";\n  }\n  return \"*UNKNOWN*\";\n}\n\nNodeManager::NodeManager(const wwiv::sdk::Config& config, const std::string& name,\n                         ConnectionType type, int start, int end, bool wwiv_bbs)\n    : config_(config), name_(name), type_(type), start_(start), end_(end), wwiv_bbs_(wwiv_bbs) {\n  for (auto i = start; i <= end; i++) {\n    clear_node(i);\n  }\n}\n\nNodeManager::NodeManager(const wwiv::sdk::Config& config, const wwiv::sdk::wwivd_matrix_entry_t& bbs)\n  : NodeManager(config, bbs.name, ConnectionType::TELNET, bbs.start_node, bbs.end_node, bbs.wwiv_bbs) {}\n\nNodeManager::NodeManager(const wwiv::sdk::Config& config, ConnectionType type)\n  : NodeManager(config, to_string(type), type, 0, 0, false) {}\n\nNodeManager::~NodeManager() = default;\n\n// static \nstd::string NodeManager::status_string(const NodeStatus& n) {\n  auto s = n.description;\n  if (n.connected) {\n    s += \" [\";\n    s += to_string(n.type);\n    s += \"]\";\n  }\n  return s;\n}\n\nstd::vector<std::string> NodeManager::status_lines() const {\n  std::lock_guard<std::mutex> lock(mu_);\n  std::vector<std::string> v;\n  for (const auto& n : nodes_) {\n    std::ostringstream ss;\n    ss << this->name_ << \" \";\n    if (n.first > 0) {\n      ss << \"Node #\" << n.first << \" \";\n    }\n    ss << status_string(n.second);\n    v.push_back(ss.str());\n  }\n\n  return v;\n}\n\nbool NodeManager::update_nodes() {\n  if (!wwiv_bbs_) {\n    return false;\n  }\n\n  wwiv::sdk::Instances instances(config_);\n  if (!instances) {\n    LOG(WARNING) << \"Unable to read Instance information.\";\n    return false;\n  }\n\n  std::lock_guard<std::mutex> lock(mu_);\n  for (const auto& inst : instances) {\n    if (inst.node_number() < start_ || inst.node_number() > this->end_) {\n      continue;\n    }\n    auto& n = status_for_unlocked(inst.node_number());\n    if (inst.updated().to_system_clock() < (std::chrono::system_clock::now() - std::chrono::hours(6))) {\n      LOG(WARNING) << \"Stale instance: \" << inst.updated().to_string();\n    }\n    n.connected = inst.online();\n    if (n.connected) {\n      n.description = inst.location_description();\n      n.connection_time = inst.started().to_time_t();\n    }\n  }\n  return true;\n}\n\nstd::vector<NodeStatus> NodeManager::nodes() const {\n  std::lock_guard<std::mutex> lock(mu_);\n  std::vector<NodeStatus> v;\n  for (const auto& n : nodes_) {\n    v.emplace_back(n.second);\n  }\n\n  return v;\n}\n\nNodeStatus& NodeManager::status_for_unlocked(int node) { return nodes_[node]; }\n\nNodeStatus NodeManager::status_for_copy(int node) {\n  std::lock_guard<std::mutex> lock(mu_);\n  auto n = status_for_unlocked(node);\n  return n;\n}\n\nvoid NodeManager::set_node(int node, ConnectionType type, const std::string& description) {\n  std::lock_guard<std::mutex> lock(mu_);\n  auto& n = status_for_unlocked(node);\n  n.node = node;\n  n.type = type;\n  n.description = description;\n  n.connected = true;\n}\n\nvoid NodeManager::set_pid(int node, int pid) {\n  std::lock_guard<std::mutex> lock(mu_);\n  auto& n = status_for_unlocked(node);\n  n.pid = pid;\n}\n\nvoid NodeManager::clear_node(int node) {\n  std::lock_guard<std::mutex> lock(mu_);\n  auto& n = status_for_unlocked(node);\n  n.node = node;\n  n.type = type_;\n  n.connected = false;\n  n.description = \"Waiting for Call\";\n}\n\nint NodeManager::nodes_used() const {\n  std::lock_guard<std::mutex> lock(mu_);\n  auto count = 0;\n  for (const auto& e : nodes_) {\n    if (e.second.connected) {\n      count++;\n    }\n  }\n  return count;\n}\n\nbool NodeManager::AcquireNode(int& node, const std::string& peer) {\n  std::lock_guard<std::mutex> lock(mu_);\n  for (auto& e : nodes_) {\n    if (!e.second.connected) {\n      e.second.connected = true;\n      e.second.type = type_;\n      e.second.peer = peer;\n      auto const now = std::chrono::system_clock::now();\n      e.second.connection_time = std::chrono::system_clock::to_time_t(now);\n      e.second.description = \"Connecting...\";\n      node = e.second.node;\n      return true;\n    }\n  }\n  // None\n  node = -1;\n  return false;\n}\n\nbool NodeManager::ReleaseNode(int node) {\n  std::lock_guard<std::mutex> lock(mu_);\n  if (!contains(nodes_, node)) {\n    return false;\n  }\n  auto& n = nodes_.at(node);\n  if (!n.connected) {\n    return false;\n  }\n  n.connected = false;\n  n.type = type_;\n  n.description = \"Waiting For Call\";\n  return true;\n}\n\nConcurrentConnections::ConcurrentConnections(int max_num) : max_num_(max_num) {}\nConcurrentConnections::~ConcurrentConnections() = default;\n\nbool ConcurrentConnections::aquire(const std::string& peer) {\n  VLOG(1) << \"ConcurrentConnections::aquire: \" << peer;\n  std::lock_guard<std::mutex> lock(connection_mu_);\n  const auto cur = map_[peer];\n  VLOG(2) << \"ConcurrentConnections: cur: \" << cur << \"; max_num_: \" << max_num_;\n  if (cur < max_num_) {\n    map_[peer] = cur + 1;\n    VLOG(2) << \"ConcurrentConnections: (post increment) cur: \" << cur << \"; max_num_: \" << max_num_;\n    return true;\n  }\n  return false;\n}\n\nbool ConcurrentConnections::release(const std::string& peer) {\n  std::lock_guard<std::mutex> lock(connection_mu_);\n  const auto cur = map_[peer] - 1;\n  if (cur > 0) {\n    map_[peer] = cur;\n  } else {\n    map_.erase(peer);\n  }\n  return true;\n}\n\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivd/node_manager.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVD_NODE_MANAGER_H\n#define INCLUDED_WWIVD_NODE_MANAGER_H\n\n#include \"sdk/config.h\"\n#include \"sdk/instance.h\"\n#include <ctime>\n#include <map>\n#include <mutex>\n#include <string>\n#include <vector>\n#include <unordered_map>\n\nnamespace wwiv::sdk {\n  struct wwivd_matrix_entry_t;\n}\n\nnamespace wwiv::wwivd {\n\nenum class ConnectionType { UNKNOWN, SSH, TELNET, BINKP, HTTP };\n\n/**\n* \\brief\n* returns a human readable version of ConnectionType\n*\n* \\param t Type of Connection\n* \\return Textual description of ConnectionType\n*/\nstd::string to_string(ConnectionType t);\n\nstruct NodeStatus {\n  ConnectionType type = ConnectionType::UNKNOWN;\n  int node = 0;\n  std::string peer;\n  time_t connection_time;\n  std::string description;\n  int pid;\n  bool connected = false;\n};\n\nclass NodeManager final {\nprivate:\n  NodeManager(const wwiv::sdk::Config& config, const std::string& name, ConnectionType type, int start, int end, bool wwiv_bbs);\npublic:\n  explicit NodeManager(const wwiv::sdk::Config& config, const wwiv::sdk::wwivd_matrix_entry_t& bbs);\n  explicit NodeManager(const wwiv::sdk::Config& config, ConnectionType type);\n  ~NodeManager();\n\n  // Get rid of unwanted forms.\n  NodeManager() = delete;\n  NodeManager(const NodeManager&) = delete;\n  NodeManager(NodeManager&&) = delete;\n  NodeManager& operator=(const NodeManager&) = delete;\n  NodeManager& operator=(NodeManager&&) = delete;\n\n  [[nodiscard]] static std::string status_string(const NodeStatus& n);\n\n  [[nodiscard]] std::vector<std::string> status_lines() const;\n\n  // Updates the node statuses from the BBS.\n  [[nodiscard]] bool update_nodes();\n\n  [[nodiscard]] std::vector<NodeStatus> nodes() const;\n\n  [[nodiscard]] NodeStatus& status_for_unlocked(int node);\n\n  [[nodiscard]] NodeStatus status_for_copy(int node);\n\n  void set_node(int node, ConnectionType type, const std::string& description);\n  void set_pid(int node, int pid);\n\n  void clear_node(int node);\n\n  [[nodiscard]] int nodes_used() const;\n\n  bool AcquireNode(int& node, const std::string& peer);\n\n  bool ReleaseNode(int node);\n\n  [[nodiscard]] int total_nodes() const { return end_ - start_ + 1; }\n  [[nodiscard]] int start_node() const { return start_; }\n  [[nodiscard]] int end_node() const { return end_; }\n\nprivate:\n  wwiv::sdk::Config config_;\n  const std::string name_;\n  const ConnectionType type_;\n  int start_ = 0;\n  int end_ = 0;\n  bool wwiv_bbs_{ false };\n  std::map<int, NodeStatus> nodes_;\n\n  mutable std::mutex mu_;\n};\n\n\nclass ConcurrentConnections final {\npublic:\n  explicit ConcurrentConnections(int max_num);\n  ~ConcurrentConnections();\n\n  ConcurrentConnections() = delete;\n  ConcurrentConnections(const ConcurrentConnections&) = delete;\n  ConcurrentConnections(ConcurrentConnections&&) = delete;\n  ConcurrentConnections& operator=(const ConcurrentConnections&) = delete;\n  ConcurrentConnections& operator=(ConcurrentConnections&&) = delete;\n\n  bool aquire(const std::string& peer);\n  bool release(const std::string& peer);\n\nprivate:\n  int max_num_{1};\n  std::mutex connection_mu_;\n  std::unordered_map<std::string, int> map_;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivd/wwivd.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivd/wwivd.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"sdk/config.h\"\n#include \"wwivd/connection_data.h\"\n#include \"wwivd/nets.h\"\n#include \"wwivd/node_manager.h\"\n#include \"wwivd/wwivd_http.h\"\n#include \"wwivd/wwivd_non_http.h\"\n#include <atomic>\n#include <csignal>\n#include <iostream>\n#include <map>\n#include <memory>\n#include <string>\n#include <thread>\n#include <utility>\n#include <vector>\n\n#ifdef _WIN32\n#include <WS2tcpip.h>\n#else // _WIN32\n#include <arpa/inet.h>\n#include <netinet/tcp.h>\n#include <spawn.h>\n#include <sys/socket.h>\n#include <sys/wait.h>\n#include <unistd.h>\n#endif // __linux__\n\n#include \"httplib.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\n#ifdef DELETE\n#undef DELETE\n#endif // DELETE\n\nnamespace wwiv::wwivd {\n\nextern std::atomic<bool> need_to_exit;\nextern std::atomic<bool> need_to_reload_config;\n\nstatic bool DeleteAllSemaphores(const Config& config, int start_node, int end_node) {\n  // Delete telnet/SSH node semaphore files.\n  for (auto i = start_node; i <= end_node; i++) {\n    if (const auto fn = node_file(config, ConnectionType::TELNET, i); File::Exists(fn)) {\n      File::Remove(fn);\n    }\n  }\n\n  if (const auto binkp_file = node_file(config, ConnectionType::BINKP, 0); File::Exists(binkp_file)) {\n    File::Remove(binkp_file);\n  }\n\n  return true;\n}\n\n/**\n *  This program is the manager of the nodes for the WWIV BBS software\n *  on UNIX platforms.\n */\nint Main(CommandLine& cmdline) {\n  const auto wwiv_dir = cmdline.bbsdir();\n  VLOG(2) << \"Using WWIV_DIR: \" << wwiv_dir;\n\n  const auto wwiv_user = cmdline.arg(\"wwiv_user\").as_string();\n  VLOG(2) << \"Using WWIV_USER: \" << wwiv_user;\n\n  const Config config{wwiv_dir};\n  if (!config.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load CONFIG.DAT\";\n    return EXIT_FAILURE;\n  }\n\n  wwivd_config_t c{};\n  c.Load(config);\n  File::set_current_directory(config.root_directory());\n  LOG(INFO) << \"Loaded BBSES:\\r\\n\" << to_string(c.bbses);\n  BeforeStartServer();\n\n  std::map<const std::string, std::shared_ptr<NodeManager>> nodes;\n\n  for (const auto& b : c.bbses) {\n    nodes[b.name] = std::make_shared<NodeManager>(config, b);\n  }\n  // Add node manager for binkp.\n  nodes[\"BINKP\"] = std::make_shared<NodeManager>(config, ConnectionType::BINKP);\n\n  // Add node for each BBS.\n  for (const auto& n : nodes) {\n    if (!DeleteAllSemaphores(config, n.second->start_node(), n.second->end_node())) {\n      LOG(ERROR) << \"Unable to clear semaphores.\";\n    }\n  }\n\n  const auto concurrent_connections =\n      std::make_shared<ConcurrentConnections>(c.blocking.max_concurrent_sessions);\n\n  ConnectionData data(&config, &c, &nodes, concurrent_connections);\n  if (c.blocking.use_goodip_txt) {\n    data.good_ips_ = std::make_shared<GoodIp>(FilePath(config.datadir(), \"goodip.txt\"));\n  }\n  // This needs to stay in scople for the lifetime of the AutoBlocker\n  SystemClock clock;\n  if (c.blocking.use_badip_txt) {\n    data.bad_ips_ = std::make_shared<BadIp>(FilePath(config.datadir(), \"badip.txt\"), clock);\n  }\n  if (c.blocking.auto_blocklist) {\n    if (!data.bad_ips_) {\n      data.bad_ips_ = std::make_shared<BadIp>(FilePath(config.datadir(), \"badip.txt\"), clock);\n    }\n    data.auto_blocker_ = std::make_shared<AutoBlocker>(data.bad_ips_, c.blocking, config.datadir(), clock);\n  }\n\n  auto telnet_or_ssh_fn = [&](accepted_socket_t r) {\n    std::thread client(HandleConnection, std::make_unique<ConnectionHandler>(data, r));\n    client.detach();\n  };\n  auto binkp_fn = [&](accepted_socket_t r) {\n    std::thread client(HandleBinkPConnection, std::make_unique<ConnectionHandler>(data, r));\n    client.detach();\n  };\n\n  SocketSet sockets(10);\n  if (c.telnet_port > 0) {\n    sockets.add(c.telnet_port, telnet_or_ssh_fn, \"TELNET\");\n  }\n  if (c.ssh_port > 0) {\n    sockets.add(c.ssh_port, telnet_or_ssh_fn, \"SSH\");\n  }\n  if (c.binkp_port > 0) {\n    sockets.add(c.binkp_port, binkp_fn, \"BINKP\");\n  }\n\n  SwitchToNonRootUser(wwiv_user);\n  need_to_exit.store(false);\n  need_to_reload_config.store(false);\n\n  // Do network callouts if enabled.\n  auto& nodemgr = data.nodes->at(\"BINKP\");\n  do_wwivd_callouts(config, c, nodemgr);\n\n  std::unique_ptr<httplib::Server> svr;\n  std::thread srv_thread;\n  if (c.http_port > 0) {\n    using namespace std::placeholders;\n    svr = std::make_unique<httplib::Server>();    \n    svr->Get(\"/status\", std::bind(StatusHandler, data.nodes, _1, _2));\n    svr->set_logger(\n        [](const httplib::Request& req, const httplib::Response& res) { VLOG(1) << res.body; });\n    srv_thread = std::thread([&](const std::string http_address, int p) { \n      svr->listen(http_address, p); \n      }, c.http_address, c.http_port);\n  }\n\n  int result = EXIT_SUCCESS;\n  if (!sockets.Run(need_to_exit)) {\n    LOG(INFO) << \"Error accepting client socket. \" << errno;\n    result = 2;\n  }\n\n  if (svr) {\n    svr->stop();\n    srv_thread.join();\n  }\n\n  return result;\n}\n\n} // namespace wwiv\n\nint main(int argc, char* argv[]) {\n  LoggerConfig config(LogDirFromConfig);\n  Logger::Init(argc, argv, config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.AddStandardArgs();\n  cmdline.add_argument({\"wwiv_user\", \"WWIV User to use.\", \"wwiv\", \"WWIV_USER\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"version\", 'V', \"Display version.\", false});\n  cmdline.set_no_args_allowed(true);\n\n  if (!cmdline.Parse()) {\n    std::cout << cmdline.GetHelp() << std::endl;\n    return EXIT_FAILURE;\n  }\n  if (cmdline.help_requested()) {\n    std::cout << cmdline.GetHelp() << std::endl;\n    return EXIT_SUCCESS;\n  }\n  if (cmdline.barg(\"version\")) {\n    std::cout << full_version() << std::endl;\n    return 0;\n  }\n\n  LOG(INFO) << \"wwivd - WWIV Daemon.\";\n\n  try {\n    return wwiv::wwivd::Main(cmdline);\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught top level exception: \" << e.what();\n    return EXIT_FAILURE;\n  }\n}\n"
  },
  {
    "path": "wwivd/wwivd.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2017-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIV_WWIV_WWIVD_H\n#define INCLUDED_WWIV_WWIV_WWIVD_H\n\n#include <string>\n#include <tuple>\n#include <core/net.h>\n#include \"sdk/config.h\"\n\nnamespace wwiv::sdk {\nclass wwivd_config_t;\n}\n\nnamespace wwiv::wwivd {\nclass NodeManager;\n}\n\nvoid BeforeStartServer();\nvoid signal_handler(int mysignal);\nvoid SwitchToNonRootUser(const std::string& wwiv_user);\n\n/**\n * Executes a command and waits. \n * If sock is > -1 then we'll close the socket after executing the command \n * since this is the child socket.\n * pid and node_number is just used for logging.\n */\nbool ExecCommandAndWait(const wwiv::sdk::wwivd_config_t& wc, wwiv::wwivd::NodeManager& node_manager,\n                        const std::string& cmd, const std::string& pid, int node_number,\n                        SOCKET sock);\n\n#endif\n"
  },
  {
    "path": "wwivd/wwivd_http.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n\n#include <ctime>\n#include <mutex>\n#include <string>\n#include <vector>\n\n#include <cereal/archives/json.hpp>\n#include <cereal/cereal.hpp>\n#include <cereal/types/memory.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/string.hpp>\n// ReSharper disable once CppUnusedIncludeDirective\n#include <cereal/types/vector.hpp>\n#include <nlohmann/json.hpp>\n\n#include \"core/jsonfile.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/socket_connection.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"httplib.h\"\n#include \"sdk/config.h\"\n#include \"wwivd/connection_data.h\"\n#include \"wwivd/node_manager.h\"\n\n#include <string>\n\nnamespace wwiv::wwivd {\n\nstatic const char MIME_TYPE_JSON[] = \"application/json\";\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nstruct status_reponse_v0_t {\n  int num_instances;\n  int used_instances;\n  std::vector<std::string> lines;\n};\n\nstruct status_line_t {\n  // Name of BBS or binkp\n  std::string name;\n  // BBS node number \n  int node;\n  // PID of bbs binary\n  int pid;\n  // is this node connected\n  bool connected{ false };\n  // Textual status of node.\n  std::string status;\n  // Remote address.\n  std::string remote;\n  // Connection time in ISO8601\n  time_t connect_time;\n};\n\nstruct status_reponse_t {\n  int num_instances;\n  int used_instances;\n  std::vector<status_line_t> lines;\n};\n\n// v0\nvoid to_json(nlohmann::json& j, const status_reponse_v0_t& v) {\n  j = nlohmann::json{\n      {\"num_instances\", v.num_instances}, {\"used_instances\", v.used_instances}, {\"lines\", v.lines}};\n}\n\nvoid from_json(const nlohmann::json& j, status_reponse_v0_t& v) {\n  j.at(\"num_instances\").get_to(v.num_instances);\n  j.at(\"used_instances\").get_to(v.used_instances);\n  j.at(\"lines\").get_to(v.lines);\n}\n\n// v1\nvoid to_json(nlohmann::json& j, const status_line_t& v) {\n  j = nlohmann::json{{\"name\", v.name},\n                     {\"node\", v.node},\n                     {\"pid\", v.pid},\n                     {\"remote\", v.remote},\n                     {\"connected\", v.connected},\n                     {\"status\", v.status},\n                     {\"connect_time\", v.connect_time}};\n}\n\nvoid from_json(const nlohmann::json& j, status_line_t& v) {\n  j.at(\"name\").get_to(v.name);\n  j.at(\"node\").get_to(v.node);\n  j.at(\"pid\").get_to(v.pid);\n  j.at(\"remote\").get_to(v.remote);\n  j.at(\"connected\").get_to(v.connected);\n  j.at(\"status\").get_to(v.status);\n  j.at(\"connect_time\").get_to(v.connect_time);\n}\n\nvoid to_json(nlohmann::json& j, const status_reponse_t& v) {\n  j = nlohmann::json{\n      {\"num_instances\", v.num_instances}, {\"used_instances\", v.used_instances}, {\"lines\", v.lines}};\n}\n\nvoid from_json(const nlohmann::json& j, status_reponse_t& v) {\n  j.at(\"num_instances\").get_to(v.num_instances);\n  j.at(\"used_instances\").get_to(v.used_instances);\n  j.at(\"lines\").get_to(v.lines);\n}\n\nstd::string ToJson(status_reponse_t r) {\n  using json = nlohmann::json;\n  json j;\n  j[\"status\"] = r;\n  return j.dump(4);\n}\n\nstd::string ToJson(status_reponse_v0_t r) {\n  using json = nlohmann::json;\n  json j;\n  j[\"status\"] = r;\n  return j.dump(4);\n}\n\n// JSON\nstatic std::map<std::string, int> version_map = {{\"2023-01\", 0}, {\"2023-05\", 1}};\n\nvoid StatusHandler(std::map<const std::string, std::shared_ptr<NodeManager>>* nodes,\n                   const httplib::Request& req, httplib::Response& res) {\n  static std::mutex mu;\n  std::lock_guard<std::mutex> lock(mu);\n\n  int version = 0;\n  if (req.has_param(\"version\")) {\n    const auto v = req.get_param_value(\"version\");\n    version = wwiv::stl::get_or_default(version_map, v, 0);\n  }\n\n  // We only handle status\n  switch (version) {\n  case 1: {\n    status_reponse_t r{};\n    for (const auto& n : *nodes) {\n      const auto& bbs_name = n.first;\n      const auto& nm = n.second;\n      r.num_instances += nm->total_nodes();\n      r.used_instances += nm->nodes_used();\n      // Read the latest state from the instance.dat.\n      (void) nm->update_nodes();\n      for (const auto& node : nm->nodes()) {\n        status_line_t l{};\n        l.name = bbs_name;\n        l.node = node.node;\n        l.status = node.description;\n        l.connected = node.connected;\n        l.connect_time = node.connection_time;\n        l.remote = node.peer;\n        l.pid = node.pid;\n        r.lines.push_back(l);\n      }\n    }\n\n    const auto source = ToJson(r);\n    res.set_content(source, MIME_TYPE_JSON);\n    return;\n  } break;\n  case 0:\n  default: {\n    status_reponse_v0_t r{};\n    for (const auto& n : *nodes) {\n      const auto v = n.second->status_lines();\n      r.num_instances += n.second->total_nodes();\n      r.used_instances += n.second->nodes_used();\n      for (const auto& l : v) {\n        r.lines.push_back(l);\n      }\n    }\n    const auto source = ToJson(r);\n    res.set_content(source, MIME_TYPE_JSON);\n    return;\n  } break;\n  }\n}\n\n} // namespace wwiv::wwivd\n"
  },
  {
    "path": "wwivd/wwivd_http.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVD_WWIVD_HTTP_H\n#define INCLUDED_WWIVD_WWIVD_HTTP_H\n\n#include \"wwivd/connection_data.h\"\n\nnamespace httplib {\n  struct Response;\n  struct Request;\n  class Server;\n} // namespace httplib\n\n\nnamespace wwiv::wwivd {\n\nvoid StatusHandler(std::map<const std::string, std::shared_ptr<NodeManager>>* nodes,\n                   const httplib::Request&, httplib::Response& res);\n\n} // namespace wwiv::wwivd\n\n#endif\n"
  },
  {
    "path": "wwivd/wwivd_non_http.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivd/wwivd_non_http.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/semaphore_file.h\"\n#include \"core/socket_connection.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/format.h\"\n#include \"sdk/ansi/makeansi.h\"\n#include \"sdk/config.h\"\n#include \"wwivd/connection_data.h\"\n#include \"wwivd/node_manager.h\"\n#include \"wwivd/wwivd.h\"\n#include <cctype>\n#include <filesystem>\n#include <memory>\n#include <string>\n#include <thread>\n#include <tuple>\n#include <utility>\n#include <vector>\n\n#ifdef WWIV_USE_PIPES\n#include \"core/pipe.h\"\n#endif\n\nnamespace wwiv::wwivd {\n\nusing namespace std::chrono;\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nstd::string to_string(const wwivd_matrix_entry_t& e) {\n  std::ostringstream ss;\n  ss << \"[\" << e.key << \"] \" << e.name << \" (\" << e.description << \")\";\n  return ss.str();\n}\n\nstd::string to_string(const std::vector<wwivd_matrix_entry_t>& elements) {\n  std::ostringstream ss;\n  for (const auto& e : elements) {\n    ss << \"{\" << to_string(e) << \"}\" << std::endl;\n  }\n  return ss.str();\n}\n\nstd::string CreateCommandLine(const std::string& tmpl, std::map<char, std::string> params) {\n  std::string out;\n\n  for (auto it = tmpl.begin(); it != tmpl.end(); ++it) {\n    if (*it == '@') {\n      ++it;\n      if (it == tmpl.end()) {\n        out.push_back('@');\n        break;\n      }\n      try {\n        out.append(params.at(*it));\n      } catch (const std::out_of_range&) {\n        out.push_back(*it);\n      }\n    } else {\n      out.push_back(*it);\n    }\n  }\n\n  return out;\n}\n\nstd::filesystem::path node_file(const Config& config, ConnectionType ct, int node_number) {\n  if (ct == ConnectionType::BINKP) {\n    return FilePath(config.datadir(), \"binkpinuse\");\n  }\n  return FilePath(config.datadir(), StrCat(\"nodeinuse.\", node_number));\n}\n\n// HACK: Copied out of SocketConnection class\n// TODO(rushfan): Make this available in core::net\nbool SetNoDelayMode(SOCKET sock, bool no_delay) {\n#ifdef _WIN32\n  int one = no_delay ? 1 : 0;\n  return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&one), sizeof(one)) !=\n         SOCKET_ERROR;\n\n#else // _WIN32\n  // TODO(rushfan): set TCP_NODELAY\n  return true;\n#endif // _WIN32\n}\n\nstatic bool telnet_to(const std::string& host_port, int /*node_number*/, SOCKET sock) { \n  LOG(INFO) << \"telnet_to: \" << host_port;\n  auto idx = host_port.find(':');\n  std::string host = host_port;\n  int port = 23;\n  if (idx != std::string::npos) {\n    host = host_port.substr(0, idx);\n    port = to_number<int>(host_port.substr(idx + 1));\n  }\n  auto out = Connect(host, port);\n  if (!out || !out->is_open()) {\n    LOG(ERROR) << \"Unable to connect to: host: \" << host << \"; port: \" << port;\n    return false;\n  }\n  SetBlockingMode(out->socket());\n  SetNoDelayMode(out->socket(), false);\n  SocketConnection in(sock);\n  const auto max_fd = std::max<int>(sock, out->socket());\n  struct timeval ts {};\n  VLOG(4) << \"telnet_to: outside loop\";\n  char data[1025];\n  while (out->is_open() && in.is_open()) {\n    VLOG(4) << \"telnet_to: loop\";\n    // If we had more than 2 here, should move this out of the loop.\n    fd_set sock_set;\n    FD_ZERO(&sock_set);\n    FD_SET(sock, &sock_set);\n    FD_SET(out->socket(), &sock_set);\n    // Some OSes change this to be the time remaining per call, so reset it\n    // each time. ick\n    ts.tv_sec = 5;\n    ts.tv_usec = 0;\n    VLOG(3) << \"  ** max_fd: \" << max_fd << \"; out: \" << out->socket() << \"; in: \" << sock;\n    auto rc = select(max_fd + 1, &sock_set, nullptr, nullptr, &ts);\n    if (rc < 0) {\n      LOG(ERROR) << \"select failed:\" << max_fd;\n      break;\n    } else if (rc == 0) {\n      // loop.\n      VLOG(3) << \"telnet_to: select timed out\";\n      continue;\n    } \n\n    // We got one!\n    if (FD_ISSET(out->socket(), &sock_set)) {\n      VLOG(4) << \"FD_ISSET: out\";\n      if (auto num_read = recv(out->socket(), data, 1024, 0); num_read > 0) {\n        if (send(in.socket(), data, num_read, 0) < 0) {\n          VLOG(1) << \"telnet_to: write to in failed\";\n          // TODO(rushfan): Care to check ENOWOULDBLOCK?\n          break;\n        }\n      } else if (num_read == 0) {\n        LOG(INFO) << \"Remote session closed; read returned 0\";\n        out->close();\n      }\n    }\n\n    if (FD_ISSET(sock, &sock_set)) {\n      VLOG(4) << \"FD_ISSET: in\";\n      if (auto num_read = recv(sock, data, 1024, 0); num_read > 0) {\n        if (send(out->socket(), data, num_read, 0) < 0) {\n          // TODO(rushfan): Care to check ENOWOULDBLOCK?\n          VLOG(1) << \"telnet_to: write to out failed\";\n          break;\n        }\n      } else {\n        LOG(INFO) << \"Remote session closed; read returned 0\";\n        in.close();\n      }\n    }\n  }\n  VLOG(1) << \"TELNET Loop done;\";\n  return true;\n}\n\n#if defined(WWIV_USE_PIPES)\nstatic bool socket_pipe_loop_one(SOCKET sock, Pipe& data_pipe, Pipe& control_pipe) {\n  LOG(INFO) << \"Starting socket_pipe_loop_one\";\n  if (!data_pipe.Create()) {\n    LOG(ERROR) << \"Failed to create pipe: \" << data_pipe.name();\n    return false;\n  }\n  if (!control_pipe.Create()) {\n    LOG(ERROR) << \"Failed to create pipe: \" << data_pipe.name();\n    //return false;\n  }\n  if (!data_pipe.WaitForClient(std::chrono::seconds(10))) {\n    LOG(ERROR) << \"Failed to connect bbs end of data pipe: \" << data_pipe.name();\n    return false;\n  }\n  if (!control_pipe.WaitForClient(std::chrono::seconds(5))) {\n    LOG(WARNING) << \"Failed to connect bbs end of control pipe: \" << control_pipe.name();\n    //return false;\n  }\n\n  struct timeval ts {};\n  VLOG(2) << \"socket_pipe_loop: outside loop; sock: \" << sock;\n  char data[1025];\n  while (sock != INVALID_SOCKET) {\n    VLOG(4) << \"socket_pipe_loop: loop\";\n    bool handled_anything{false};\n    // If we had more than 2 here, should move this out of the loop.\n    fd_set sock_set;\n    FD_ZERO(&sock_set);\n    FD_SET(sock, &sock_set);\n    ts.tv_sec = 0;\n    ts.tv_usec = 100; // 100ms\n    VLOG(3) << \"before select\";\n    auto rc = select(sock + 1, &sock_set, nullptr, nullptr, &ts);\n    if (rc < 0) {\n      LOG(ERROR) << \"select failed; socket: \" << sock << \"; errno: \" << errno;\n      return true;\n    } else if (rc == 0) {\n      // loop.\n      VLOG(3) << \"socket_pipe_loop: select timed out\";\n    }\n\n    if (!data_pipe.IsOpen()) {\n      VLOG(1) << \"Data Pipe was closed; exiting.\";\n      return true;\n    }\n\n    if (data_pipe.peek()) {\n      VLOG(3) << \"Pipe has something\";\n      if (const auto o = data_pipe.read(data, 1024)) {\n\t      // We got something from the pipe.\n\t      handled_anything = true;\n        if (send(sock, data, o.value(), 0) < 0) {\n          VLOG(1) << \"socket_pipe_loop: write to in failed\";\n          // TODO(rushfan): Care to check ENOWOULDBLOCK?\n\t        return true;\n        }\n      } else {\n\t      VLOG(1) << \"ERROR: read failed after peek was true.\";\n      }\n    }\n    // We got something from the socket!\n    if (FD_ISSET(sock, &sock_set)) {\n      handled_anything = true;\n      VLOG(4) << \"FD_ISSET: in\";\n      if (auto num_read = recv(sock, data, 1024, 0); num_read > 0) {\n        if (!data_pipe.write(data, num_read)) {\n          LOG(ERROR) << \"Failed to write to pipe\";\n\t        return true; // recent change\n        }\n      } else {\n        LOG(INFO) << \"Remote session closed; read returned 0\";\n\t      return true;\n      }\n    }\n    if (!handled_anything) {\n      wwiv::os::sleep_for(milliseconds(200));\n    }\n  }\n  VLOG(1) << \"[socket_pipe_loop]: Loop done;\";\n  return true;\n}\n\nstatic void socket_pipe_loop(SOCKET sock, Pipe& data_pipe, Pipe& control_pipe) {\n  VLOG(1) << \"socket_pipe_loop\";\n  bool keep_going;\n  do {\n    keep_going = socket_pipe_loop_one(sock, data_pipe, control_pipe);\n  } while (keep_going);\n}\n#endif\n\nstatic bool launch_cmd(const wwivd_config_t& wc, const std::string& raw_cmd,\n                       const std::string& working_dir, const std::shared_ptr<NodeManager>& nodes,\n                       int node_number, SOCKET sock, ConnectionType connection_type,\n                       const std::string& remote_peer) {\n\n  const auto wwiv_pid = fmt::format(\"[{}] \", get_pid());\n  nodes->set_node(node_number, connection_type, StrCat(\"Connected: \", remote_peer));\n\n  const std::map<char, std::string> params = {\n    {'N', std::to_string(node_number)}, \n    {'H', std::to_string(sock)},\n    {'P', std::to_string(get_pid())},\n};\n\n  if (sock != INVALID_SOCKET) {\n    // Reset the socket back to blocking mode\n    VLOG(2) << \"Setting blocking mode.\";\n    if (!SetBlockingMode(sock)) {\n      LOG(ERROR) << \"Failed to reset the socket to blocking mode.\";\n    }\n  }\n\n  VLOG(2) << \"raw_cmd: \" << raw_cmd;\n  auto at_exit = finally([=] { nodes->ReleaseNode(node_number); });\n  if (starts_with(raw_cmd, \"@telnet:\")) {\n    return telnet_to(raw_cmd.substr(8), node_number, sock);\n  }\n  const auto cmd = CreateCommandLine(raw_cmd, params);\n  File::set_current_directory(working_dir);\n  return ExecCommandAndWait(wc, *nodes, cmd, wwiv_pid, node_number, sock);\n}\n\nstatic bool launch_node(const Config& config, const wwivd_config_t& wc, wwivd_matrix_entry_t& bbs,\n                        const std::shared_ptr<NodeManager>& nodes, int node_number, SOCKET sock,\n                        ConnectionType connection_type, const std::string& remote_peer) {\n  const auto& raw_cmd = connection_type == ConnectionType::SSH ? bbs.ssh_cmd : bbs.telnet_cmd;\n  const auto root = config.root_directory();\n  const auto working_dir =\n      bbs.working_directory.empty() ? \"\" : FilePath(root, bbs.working_directory).string();\n\n  auto at_exit = finally([=] {\n    VLOG(1) << \"closing socket: \" << sock;\n    closesocket(sock);\n    VLOG(2) << \"closed socket: \" << sock;\n  });\n\n  const auto wwiv_pid = fmt::format(\"[{}] \", get_pid());\n  VLOG(1) << wwiv_pid << \": launching node(\" << node_number << \")\";\n  const auto sem_text = fmt::format(\"Created by pid: {}\\nremote peer: {}\", wwiv_pid, remote_peer);\n  const auto sem_path = node_file(config, connection_type, node_number);\n\n  try {\n    const auto semaphore_file = SemaphoreFile::try_acquire(sem_path, sem_text, std::chrono::seconds(60));\n#ifdef WWIV_USE_PIPES\n    Pipe data_pipe(node_number, false);\n    Pipe control_pipe(node_number, true);\n#endif    \n    [[maybe_unused]] auto real_sock = sock;\n    std::thread pipes_thread;\n    if (bbs.data_mode == wwivd_data_mode_t::pipe) {\n      // Spawn named pipes\n#if defined(_WIN32) && defined(WWIV_USE_PIPES)\n      VLOG(1) << \"Spawning socket_pipe_loop. sock: \" << sock;\n      std::thread t(socket_pipe_loop, sock, std::ref(data_pipe), std::ref(control_pipe));\n      std::swap(t, pipes_thread);\n#endif\n      sock = INVALID_SOCKET;\n    }\n    auto result = launch_cmd(wc, raw_cmd, working_dir, nodes, node_number, sock, connection_type, remote_peer);\n    VLOG(1) << \"after launch_cmd\";\n#if defined(WWIV_USE_PIPES)\n#if defined(__OS2__)\n    if (bbs.data_mode == wwivd_data_mode_t::pipe) {\n      socket_pipe_loop(real_sock, data_pipe, control_pipe);\n      // Force a close on the socket to make this terminate.\n      closesocket(real_sock);\n    }\n#elif defined(_WIN32) \n    if (pipes_thread.joinable()) {\n      pipes_thread.join();\n      closesocket(real_sock);\n    }\n#endif\n#endif\n    return result;\n  } catch (const semaphore_not_acquired& e) {\n    LOG(ERROR) << wwiv_pid << \"Unable to create semaphore file: \" << sem_path << \"; errno: \" << errno\n               << \"; what: \" << e.what();\n    return false;\n  }\n}\n\nstatic ConnectionType connection_type_for(const wwivd_config_t& c, int port) {\n  if (port == c.telnet_port) {\n    return ConnectionType::TELNET;\n  }\n  if (port == c.binkp_port) {\n    return ConnectionType::BINKP;\n  }\n  if (port == c.ssh_port) {\n    return ConnectionType::SSH;\n  }\n  if (port == c.http_port) {\n    return ConnectionType::HTTP;\n  }\n  LOG(WARNING) << \"Defaulting to TELNET for unknown connection type for port: \" << port;\n  return ConnectionType::TELNET;\n}\n\nstatic bool check_ansi(SocketConnection& conn) {\n  const auto d = 3s;\n  conn.send(\"Checking for ANSI Graphics... \", d);\n  conn.send(\"\\x1b[6n\", d);\n  const auto res = conn.receive_upto(10, d);\n  if (!res.empty() && res.front() == 27) {\n    conn.send_line(\"ANSI detected.\", d);\n    return true;\n  }\n  conn.send_line(\"No ANSI detected.\", d);\n  return false;\n}\n\nstd::string Color(int c, bool ansi) {\n  static auto wwivd_curatr = 7;\n  if (!ansi) {\n    return \"\";\n  }\n\n  // Not const so we can move s\n  auto s = ansi::makeansi(c, wwivd_curatr);\n  wwivd_curatr = 0;\n  return s;\n}\n\nConnectionHandler::ConnectionHandler(ConnectionData d, accepted_socket_t a)\n    : data(std::move(d)), r(a) {}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nwwivd_matrix_entry_t ConnectionHandler::DoMatrixLogon(const wwivd_config_t& c) {\n\n  SocketConnection conn(r.client_socket, SocketConnection::ExitMode::LEAVE_SOCKET_OPEN);\n  if (c.bbses.empty()) {\n    // This should be checked before calling this method.\n    throw std::runtime_error(\"c.bbses.empty()\");\n  }\n  if (c.bbses.size() == 1) {\n    // Only have 1 entry, that's the one to display.\n    return c.bbses.front();\n  }\n\n  const auto ansi = check_ansi(conn);\n  const auto d = 1s;\n  for (auto tries = 0; tries < 3; tries++) {\n    conn.send_line(StrCat(Color(10, ansi), \"Matrix Logon Menu\"), d);\n    conn.send_line(\"\\r\\n\", d);\n    for (const auto& b : c.bbses) {\n      // Skip ones that require ANSI.\n      if (b.require_ansi && !ansi) {\n        continue;\n      }\n      std::ostringstream ss;\n      ss << Color(14, ansi) << b.key << Color(3, ansi) << \") \" << Color(10, ansi) << b.name;\n      if (!b.description.empty()) {\n        ss << Color(11, ansi) << \"  (\" << b.description << \")\";\n      }\n      conn.send_line(ss.str(), d);\n    }\n    std::ostringstream ss;\n    ss << Color(14, ansi) << '!' << Color(3, ansi) << \") \" << Color(11, ansi) << \" Logoff/Quit.\";\n    conn.send_line(ss.str(), d);\n\n    conn.send_line(\"\\r\\n\", d);\n    conn.send(StrCat(Color(3, ansi), \"Enter Selection: \"), d);\n    const auto key_str = conn.receive_upto(1, std::chrono::seconds(15));\n    // dump left overs\n    conn.receive_upto(1024, std::chrono::milliseconds(1));\n    if (key_str.empty()) {\n      continue;\n    }\n    const auto key = key_str.front();\n\n    for (const auto& b : c.bbses) {\n      if (std::toupper(b.key) == std::toupper(key)) {\n        conn.send_line(\"\\r\\n\", d);\n        return b;\n      }\n    }\n    // Hangup\n    if (key == '!') {\n      conn.close();\n      return {};\n    }\n  }\n\n  conn.close();\n  return {};\n}\n\n\n// Can throw\n// ReSharper disable once CppMemberFunctionMayBeConst\nConnectionHandler::BlockedConnectionResult ConnectionHandler::CheckForBlockedConnection() {\n  const auto sock = r.client_socket;\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (1): \" << sock;\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (2): \" << sock;\n  // We fail open when we can't get the remote peer\n  const auto o = GetRemotePeerAddress(sock);\n  if (!o) {\n    LOG(ERROR) << \"CheckForBlockedConnection: Allowing connections we can't determine the remote peer.\";\n    return BlockedConnectionResult(BlockedConnectionAction::ALLOW, \"???\");\n  }\n  const auto remote_peer = o.value();\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (3): \" << sock;\n  const auto& b = data.c->blocking;\n  // Check for always allowed addresses\n  if (b.use_goodip_txt && data.good_ips_) {\n    if (data.good_ips_->IsAlwaysAllowed(remote_peer)) {\n      LOG(INFO) << \"Allowing connection for goodip.txt always-allowed peer: \" << remote_peer;\n      return BlockedConnectionResult(BlockedConnectionAction::ALLOW, remote_peer);\n    }\n  }\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (4): \" << sock;\n  // Check for always blocked addresses\n  if (b.use_badip_txt && data.bad_ips_) {\n    if (data.bad_ips_->IsBlocked(remote_peer)) {\n      // We have a connection from a blocked country\n      LOG(INFO) << \"Denying connection attempt from badip.txt blocked peer: \" << remote_peer;\n      return BlockedConnectionResult(BlockedConnectionAction::DENY, remote_peer);\n    }\n  }\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (5a): \" << sock;\n  if (is_rfc1918_private_address(remote_peer)) {\n    LOG(INFO) << \"Allowing connection for peer from RFC1918 address space: \" << remote_peer;\n    return BlockedConnectionResult(BlockedConnectionAction::ALLOW, remote_peer);\n  }\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (5b): \" << sock;\n  // Check for country blocking if we have a DNS cc server defined.\n  if (b.use_dns_cc && !b.dns_cc_server.empty() && !ends_with(b.dns_cc_server, \"nerd.dk\")) {\n    // TODO(rushfan): HACK to disable using nerd.dk which is down.\n    const auto cc = get_dns_cc(remote_peer, b.dns_cc_server);\n    LOG(INFO) << \"Validating country code for connection on port: \" << r.port\n              << \"; from peer: \" << remote_peer << \"; country code: \" << cc;\n    if (contains(data.c->blocking.block_cc_countries, cc)) {\n      // We have a connection from a blocked country\n      LOG(INFO) << \"Denying connection attempt from country \" << cc << \" for peer: \" << remote_peer;\n      return BlockedConnectionResult(BlockedConnectionAction::DENY, remote_peer);\n    }\n  }\n\n  VLOG(4) << \"ConnectionHandler::CheckForBlockedConnection; (6): \" << sock;\n  // Not blocked address nor blocked country. See if it's a new\n  // connection, and if so, should we block it now.\n  if (b.auto_blocklist && data.auto_blocker_) {\n    if (!data.auto_blocker_->Connection(remote_peer)) {\n      // We have a newly blocked address.\n      LOG(INFO) << \"Denying connection attempt from AutoBlocker: \" << remote_peer;\n      return BlockedConnectionResult(BlockedConnectionAction::DENY, remote_peer);\n    }\n  }\n\n  // Nothing left to check, let the connection through.\n  LOG(INFO) << \"Allowing connection for peer: \" << remote_peer;\n  return BlockedConnectionResult(BlockedConnectionAction::ALLOW, remote_peer);\n}\n\nvoid ConnectionHandler::HandleBinkPConnection() {\n  const auto sock = r.client_socket;\n  try {\n    const auto result = CheckForBlockedConnection();\n    if (result.action == BlockedConnectionAction::DENY) {\n      VLOG(1) << \" BINKP BUSY (Blocked): \" << result.remote_peer;\n      SocketConnection conn(r.client_socket);\n      conn.send_line(\"BUSY (Blocked)\\r\\n\", 10s);\n      closesocket(sock);\n      return;\n    }\n    if (!data.concurrent_connections_->aquire(result.remote_peer)) {\n      LOG(INFO) << \" BINKP BUSY (Concurrent Limit Reached): \" << result.remote_peer;\n      SocketConnection conn(r.client_socket);\n      conn.send_line(\"BUSY (Concurrent Limit Reached)\\r\\n\", 10s);\n      closesocket(sock);\n      return;\n    }\n    auto at_exit = finally([&] { data.concurrent_connections_->release(result.remote_peer); });\n\n    auto& nodemgr = data.nodes->at(\"BINKP\");\n    auto node = -1;\n    if (nodemgr->AcquireNode(node, result.remote_peer)) {\n      auto at_exit2 = finally([=] {\n        closesocket(sock);\n        VLOG(2) << \"closed socket: \" << sock;\n      });\n      launch_cmd(*data.c, data.c->binkp_cmd, \"\", nodemgr, 0, sock, ConnectionType::BINKP,\n                 result.remote_peer);\n    }\n\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"HandleBinkPConnection: Handled Uncaught Exception: \" << e.what();\n  }\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nConnectionHandler::MailerModeResult ConnectionHandler::DoMailerMode() {\n  SocketConnection conn(r.client_socket, SocketConnection::ExitMode::RESET_TO_BLOCKING);\n\n  const auto text = fmt::format(\n      \"CONNECT 2400\\r\\nWWIV - Server {}\\r\\nPress <ESC> twice for the BBS...\\r\\n\", full_version());\n  VLOG(1) << \"In DoMailerMode.\";\n  conn.send_line(text, 10s);\n\n  const auto end = system_clock::now() + 10s;\n  auto num_escapes = 0;\n  while (system_clock::now() < end && num_escapes < 2) {\n    conn.send(\".\", 1s);\n    if (auto received = conn.receive_upto(1, 1s); !received.empty() && received.front() == 27) {\n      ++num_escapes;\n    }\n  }\n\n  conn.send(\"\\r\\n\\r\\n\", 1s);\n\n  return num_escapes > 1 ? MailerModeResult::ALLOW : MailerModeResult::DENY;\n}\n\nvoid ConnectionHandler::HandleConnection() {\n  const auto sock = r.client_socket;\n  VLOG(4) << \"ConnectionHandler::HandleConnection; sock: \" << sock;\n  try {\n    VLOG(4) << \"ConnectionHandler::HandleConnection; (1): \" << sock;\n    SocketConnection conn(sock);\n    VLOG(4) << \"ConnectionHandler::HandleConnection; (2): \" << sock;\n    const auto result = CheckForBlockedConnection();\n    VLOG(4) << \"ConnectionHandler::HandleConnection; (3): \" << sock;\n    if (result.action == BlockedConnectionAction::DENY) {\n      VLOG(1) << \"HandleConnection: BUSY (Blocked): \" << result.remote_peer;\n      conn.send_line(\"BUSY (Blocked)\\r\\n\", 10s);\n      closesocket(sock);\n      return;\n    }\n    VLOG(4) << \"After block check\";\n    if (!data.concurrent_connections_->aquire(result.remote_peer)) {\n      LOG(INFO) << \" BUSY (Concurrent Limit Reached): \" << result.remote_peer;\n      conn.send_line(\"BUSY (Concurrent Limit Reached)\\r\\n\", 10s);\n      closesocket(sock);\n      return;\n    }\n    VLOG(4) << \"After concurrent check\";\n    auto at_exit = finally([&] { data.concurrent_connections_->release(result.remote_peer); });\n    const auto connection_type = connection_type_for(*data.c, r.port);\n\n    if (data.c->blocking.mailer_mode && connection_type == ConnectionType::TELNET) {\n      VLOG(4) << \"doing mailer mode check\";\n      if (const auto mailer_result = DoMailerMode(); mailer_result == MailerModeResult::DENY) {\n        LOG(INFO) << \"DENY (from MailerMode, didn't press ESC twice)\";\n        closesocket(sock);\n        return;\n      }\n      LOG(INFO) << \"ACCEPT (From MailerMode)\";\n    }\n\n    if (data.c->bbses.empty()) {\n      // If no bbses are defined, bail early and let someone know.\n      LOG(ERROR) << \"No BBSes defined in WWIVconfig for the Matrix.\";\n      conn.send_line(\"No BBSes defined in WWIVconfig for the Matrix.  Please tell the SysOp.\",\n                     std::chrono::seconds(1));\n      return;\n    }\n\n    wwivd_matrix_entry_t bbs;\n    if (connection_type == ConnectionType::TELNET) {\n      VLOG(4) << \"connection_type: ConnectionType::TELNET\";\n      bbs = DoMatrixLogon(*data.c);\n    } else if (connection_type == ConnectionType::SSH) {\n      VLOG(4) << \"connection_type: ConnectionType::SSH\";\n      bbs = data.c->bbses.front();\n    }\n\n    VLOG(2) << \"BBS is: \" << bbs.name;\n\n    if (!contains(*data.nodes, bbs.name)) {\n      // HOW???\n      conn.send_line(StrCat(\"Can't find config for bbs: \", bbs.name), std::chrono::seconds(1));\n      return;\n    }\n    auto& nodemgr = data.nodes->at(bbs.name);\n\n    // Telnet or SSH connection.  Find open node number and launch the child.\n    auto node = -1;\n    if (nodemgr->AcquireNode(node, result.remote_peer)) {\n      auto current_dir = File::current_directory();\n      launch_node(*data.config, *data.c, bbs, nodemgr, node, sock, connection_type, result.remote_peer);\n      File::set_current_directory(current_dir);\n      VLOG(1) << \"Exiting HandleConnection (launch_node)\";\n    } else {\n      using namespace std::chrono_literals;\n      LOG(INFO) << \"Sending BUSY. No available node to handle connection.\";\n      conn.send_line(\"BUSY (No Available Nodes)\\r\\n\", 10s);\n      VLOG(1) << \"Exiting HandleConnection: BUSY (No Available Nodes)\";\n    }\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Handled Uncaught Exception: \" << e.what();\n  } catch (...) {\n    LOG(ERROR) << \"Handled Uncaught Exception: !!!\";\n  }\n}\n\nvoid HandleConnection(std::unique_ptr<ConnectionHandler> h) { h->HandleConnection(); }\n\nvoid HandleBinkPConnection(std::unique_ptr<ConnectionHandler> h) { h->HandleBinkPConnection(); }\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivd/wwivd_non_http.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV BBS Software                             */\n/*             Copyright (C)2017-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVD_WWIVD_NON_HTTP_H\n#define INCLUDED_WWIVD_WWIVD_NON_HTTP_H\n\n#include \"core/socket_connection.h\"\n#include \"sdk/wwivd_config.h\"\n#include \"wwivd/connection_data.h\"\n#include \"wwivd/node_manager.h\"\n#include <filesystem>\n#include <map>\n#include <memory>\n#include <utility>\n#include <vector>\n\nnamespace wwiv::wwivd {\n\nstd::string to_string(const wwiv::sdk::wwivd_matrix_entry_t& e);\nstd::string to_string(const std::vector<wwiv::sdk::wwivd_matrix_entry_t>& elements);\nstd::filesystem::path node_file(const wwiv::sdk::Config& config, ConnectionType ct,\n                                int node_number);\nstd::string CreateCommandLine(const std::string& tmpl, std::map<char, std::string> params);\n\nclass ConnectionHandler {\npublic:\n  enum class BlockedConnectionAction { ALLOW, DENY };\n  enum class MailerModeResult { ALLOW, DENY };\n\n  struct BlockedConnectionResult {\n    BlockedConnectionResult(const BlockedConnectionAction& a, std::string r)\n        : action(a), remote_peer(std::move(r)) {}\n    BlockedConnectionAction action{BlockedConnectionAction::ALLOW};\n    std::string remote_peer;\n  };\n\n  ConnectionHandler() = delete;\n  ConnectionHandler(ConnectionData d, wwiv::core::accepted_socket_t a);\n\n  void HandleConnection();\n  void HandleBinkPConnection();\n\nprivate:\n  MailerModeResult DoMailerMode();\n  BlockedConnectionResult CheckForBlockedConnection();\n  wwiv::sdk::wwivd_matrix_entry_t DoMatrixLogon(const wwiv::sdk::wwivd_config_t& c);\n  ConnectionData data;\n  wwiv::core::accepted_socket_t r;\n};\n\nvoid HandleConnection(std::unique_ptr<ConnectionHandler> h);\nvoid HandleBinkPConnection(std::unique_ptr<ConnectionHandler> h);\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "wwivd/wwivd_non_http_test.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                 Copyright (C)2018-2022, WWIV Software Services         */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/clock.h\"\n#include \"core/fake_clock.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/test/file_helper.h\"\n#include \"sdk/wwivd_config.h\"\n#include \"wwivd/wwivd_non_http.h\"\n\n#include \"gtest/gtest.h\"\n#include <chrono>\n#include <string>\n#include <vector>\n\nusing namespace std::chrono_literals;\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\nusing namespace wwiv::wwivd;\n\nTEST(GoodIps, IsAlwaysAllowed) {\n  const std::vector<std::string> lines{\"10.0.0.1\", \"192.168.0.1 # This is line #2\"};\n  GoodIp ip(lines);\n  EXPECT_TRUE(ip.IsAlwaysAllowed(\"10.0.0.1\"));\n  EXPECT_TRUE(ip.IsAlwaysAllowed(\"192.168.0.1\"));\n\n  EXPECT_FALSE(ip.IsAlwaysAllowed(\"10.0.0.2\"));\n}\n\nTEST(BadIps, Smoke) {\n  wwiv::core::test::FileHelper helper;\n  auto fn = helper.CreateTempFile(\"badip.txt\", \"10.0.0.1\\r\\n8.8.8.8\\r\\n\");\n  FakeClock clock(DateTime::now());\n  BadIp ip(fn, clock);\n  EXPECT_TRUE(ip.IsBlocked(\"10.0.0.1\"));\n  EXPECT_TRUE(ip.IsBlocked(\"8.8.8.8\"));\n  EXPECT_FALSE(ip.IsBlocked(\"4.4.4.4\"));\n  ip.Block(\"1.1.1.1\");\n  EXPECT_TRUE(ip.IsBlocked(\"1.1.1.1\"));\n\n  TextFile tf(fn, \"rt\");\n  auto contents = tf.ReadFileIntoString();\n  EXPECT_TRUE(contents.find(\"1.1.1.1\") != contents.npos);\n  EXPECT_TRUE(ip.IsBlocked(\"10.0.0.1\"));\n  EXPECT_TRUE(ip.IsBlocked(\"8.8.8.8\"));\n  EXPECT_FALSE(ip.IsBlocked(\"4.4.4.4\"));\n}\n\nTEST(AutoBlock, ShouldBlock) {\n  wwivd_blocking_t b{};\n  b.auto_blocklist = true;\n  b.auto_bl_seconds = 2;\n  b.auto_bl_sessions = 1;\n  wwiv::core::test::FileHelper helper;\n  const auto fn = helper.CreateTempFile(\"badip.txt\", \"10.0.0.1\\r\\n8.8.8.8\\r\\n\");\n  FakeClock clock(DateTime::now());\n  auto bip = std::make_shared<BadIp>(fn, clock);\n  AutoBlocker blocker(bip, b, helper.TempDir(), clock);\n  EXPECT_FALSE(blocker.blocked(\"1.1.1.1\"));\n  blocker.Connection(\"1.1.1.1\");\n  clock.tick(1s);\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n}\n\nTEST(AutoBlock, Escalate1) {\n  wwivd_blocking_t b{};\n  b.auto_blocklist = true;\n  b.auto_bl_seconds = 2;\n  b.auto_bl_sessions = 1;\n  wwiv::core::test::FileHelper helper;\n  const auto fn = helper.CreateTempFile(\"badip.txt\", \"10.0.0.1\\r\\n8.8.8.8\\r\\n\");\n  FakeClock clock(DateTime::now());\n  auto bip = std::make_shared<BadIp>(fn, clock);\n  AutoBlocker blocker(bip, b, helper.TempDir(), clock);\n  EXPECT_FALSE(blocker.blocked(\"1.1.1.1\"));\n  blocker.Connection(\"1.1.1.1\");\n  clock.tick(1s);\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_EQ(1, blocker.auto_blocked().at(\"1.1.1.1\").count);\n  // not blocked permanently yet.\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n}\n\nTEST(AutoBlock, Escalate_All) {\n  wwivd_blocking_t b{};\n  b.auto_blocklist = true;\n  b.auto_bl_seconds = 2;\n  b.auto_bl_sessions = 1;\n  b.block_duration.emplace_back(\"1m\");\n  b.block_duration.emplace_back(\"2m\");\n  b.block_duration.emplace_back(\"3m\");\n  b.block_duration.emplace_back(\"4m\");\n  wwiv::core::test::FileHelper helper;\n  const auto fn = helper.CreateTempFile(\"badip.txt\", \"10.0.0.1\\r\\n8.8.8.8\\r\\n\");\n  FakeClock clock(DateTime::now());\n  auto bip = std::make_shared<BadIp>(fn, clock);\n  AutoBlocker blocker(bip, b, helper.TempDir(), clock);\n  EXPECT_FALSE(blocker.blocked(\"1.1.1.1\"));\n  blocker.Connection(\"1.1.1.1\");\n  clock.tick(1s);\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_EQ(1, blocker.auto_blocked().at(\"1.1.1.1\").count);\n  // not blocked permanently yet.\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n\n  clock.tick(61s);\n  blocker.Connection(\"1.1.1.1\");\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_EQ(2, blocker.auto_blocked().at(\"1.1.1.1\").count);\n  // not blocked permanently yet.\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n\n  clock.tick(121s);\n  blocker.Connection(\"1.1.1.1\");\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_EQ(3, blocker.auto_blocked().at(\"1.1.1.1\").count);\n  // not blocked permanently yet.\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n\n  clock.tick(181s);\n  blocker.Connection(\"1.1.1.1\");\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_TRUE(blocker.blocked(\"1.1.1.1\"));\n  EXPECT_EQ(4, blocker.auto_blocked().at(\"1.1.1.1\").count);\n  // not blocked permanently yet.\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n\n\n  clock.tick(241s);\n  blocker.Connection(\"1.1.1.1\");\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_FALSE(blocker.blocked(\"1.1.1.1\"));\n  // blocked permanently yet.\n  EXPECT_TRUE(bip->IsBlocked(\"1.1.1.1\"));\n}\n\nTEST(AutoBlock, ShouldNotBlock) {\n  wwivd_blocking_t b{};\n  b.auto_blocklist = true;\n  b.auto_bl_seconds = 1;\n  b.auto_bl_sessions = 1;\n  wwiv::core::test::FileHelper helper;\n  const auto fn = helper.CreateTempFile(\"badip.txt\", \"10.0.0.1\\r\\n8.8.8.8\\r\\n\");\n  FakeClock clock(DateTime::now());\n  auto bip = std::make_shared<BadIp>(fn, clock);\n  AutoBlocker blocker(bip, b, helper.TempDir(), clock);\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n  blocker.Connection(\"1.1.1.1\");\n  clock.tick(2s);\n  blocker.Connection(\"1.1.1.1\");\n  EXPECT_FALSE(bip->IsBlocked(\"1.1.1.1\"));\n}\n\n"
  },
  {
    "path": "wwivd/wwivd_os2.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivd/wwivd.h\"\n\n#define INCL_DOSPROCESS\n#define INCL_DOSSESMGR\n#include <os2.h>\n#include <emx/umalloc.h> // for _lmalloc()\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/socket_connection.h\"\n#include \"core/strings.h\"\n#include \"sdk/wwivd_config.h\"\n#include \"wwivd/node_manager.h\"\n\n#include <atomic>\n#include <iostream>\n#include <csignal>\n#include <string>\n#include <process.h>\n#include <libcx/spawn2.h>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nnamespace wwiv::wwivd {\n\nextern std::atomic<bool> need_to_exit;\n} // namespace wwiv\n\nusing namespace wwiv::wwivd;\n\nvoid signal_handler(int mysignal) {\n  switch (mysignal) {\n  // Graceful exit\n  case SIGTERM: {\n    std::cerr << \"SIGTERM: \" << mysignal << std::endl;\n    // On Windows since we do this, we re-raise it.\n    signal(mysignal, SIG_DFL);\n    raise(mysignal);\n  } break;\n  // Interrupts\n  case SIGINT: {\n    std::cerr << \"SIGINT: \" << mysignal << std::endl;\n    need_to_exit.store(true);\n    // call default handler\n  } break;\n  default: {\n    std::cerr << \"Unknown signal: \" << mysignal << std::endl;\n  }\n  }\n}\n\nvoid BeforeStartServer() {\n  // Not the best place, but this works.\n  InitializeSockets();\n  signal(SIGTERM, signal_handler);\n  signal(SIGINT, signal_handler);\n  std::cerr << \"set signal handlers\" << std::endl;\n}\n\nvoid SwitchToNonRootUser(const std::string&) {\n}\n\n\nbool ExecCommandAndWait(const wwivd_config_t& wc, wwiv::wwivd::NodeManager& node_manager,\n                        const std::string& cmd, const std::string& pid, int node_number,\n                        SOCKET sock) {\n\n  LOG(INFO) << pid << \"Invoking Command Line (Win32):\" << cmd;\n\n  std::string exe = cmd;\n  auto ss = wwiv::strings::SplitString(cmd, \" \");\n  char* argv = (char*) _lmalloc(1024);\n  memset(argv, 0, 1024);\n  const auto len = cmd.size();\n  strcpy(argv, cmd.c_str());\n  char* args = strchr(argv, ' ');\n  if (args) { ++args; }\n\n  std::ostringstream sso;\n  for (int i=0; i<=cmd.size() + 1; i++) {\n    if (argv[i] < 32) {\n      sso << \"[\\\\\" << (int)argv[i] << \"]\";\n    } else {\n      sso << argv[i];\n    }\n  }\n  VLOG(3) << \"OS2 style args: \" << sso.str();\n\n\n  STARTDATA data;\n  memset(&data, sizeof(data), 0);\n  data.Length = sizeof(data);\n  data.Related = SSF_RELATED_INDEPENDENT;\n  data.FgBg = SSF_FGBG_FORE;\n  data.TraceOpt = SSF_TRACEOPT_NONE;\n  data.PgmTitle = (PSZ) \"WWIV BBS\";\n  data.PgmName = (PSZ) \"C:\\\\WWIV\\\\BBS.EXE\"; // &argv[0];\n  data.PgmInputs = (PSZ) args;\n  data.TermQ = NULL;\n  data.Environment = NULL;\n  data.InheritOpt = SSF_INHERTOPT_PARENT;\n  data.IconFile = NULL;\n  data.PgmHandle = NULLHANDLE;\n  data.InitXPos = data.InitYPos = data.InitXSize = data.InitYSize = 0;\n  data.Reserved = 0;\n  data.ObjectBuffer = NULL;\n  data.ObjectBuffLen = 0;\n  data.SessionType = SSF_TYPE_WINDOWABLEVIO;\n\n  ULONG ulSid = 0, ulPid = 0;\n  APIRET arc = DosStartSession(&data, &ulSid, &ulPid);\n  LOG(INFO) << \"DosStartSession ret: \" << arc << \"; child pid: \" << ulPid;\n  int child_pid = ulPid;\n\n  RESULTCODES code;  // Result code for the child process\n  PID pidOut = child_pid;\n  node_manager.set_pid(node_number, child_pid);\n\n\n  if(APIRET rc = DosWaitChild(DCWA_PROCESS, DCWW_WAIT, &code, &pidOut, child_pid); rc != NO_ERROR) {\n    LOG(ERROR) << \"DosWaitChild failed: Error: \" << rc;\n  }\n\n  if (sock != INVALID_SOCKET) {\n    // We're done with this socket.\n    closesocket(sock);\n  }\n\n  if (node_number > 0) {\n    LOG(INFO) << \"Node #\" << node_number << \" exited with error code: \" << code.codeResult;\n  } else {\n    LOG(INFO) << \"Command: '\" << cmd << \"' exited with error code: \" << code.codeResult;\n  }\n  return true;\n}\n\n"
  },
  {
    "path": "wwivd/wwivd_test_main.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                 Copyright (C)2018-2022, WWIV Software Services         */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/test/wwivtest.h\"\n\n#include \"gtest/gtest.h\"\n\nusing namespace wwiv::core;\n\nint main(int argc, char* argv[]) {\n  wwiv::core::test::InitTestForMain(argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "wwivd/wwivd_unix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivd/wwivd.h\"\n\n#include <atomic>\n#include <iostream>\n#include <map>\n#include <string>\n\n#include <pwd.h>\n#include <signal.h>\n#include <spawn.h>\n#include <string>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"core/net.h\"\n#include \"core/os.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/wwivport.h\"\n#include \"sdk/config.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/filenames.h\"\n#include \"wwivd/node_manager.h\"\n\nusing std::cerr;\nusing std::clog;\nusing std::cout;\nusing std::endl;\nusing std::map;\nusing std::string;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\n// From wwivd.cpp\n\npid_t bbs_pid = 0;\nextern char **environ;\n\nnamespace wwiv::wwivd {\n\nextern std::atomic<bool> need_to_exit;\nextern std::atomic<bool> need_to_reload_config;\n\n} // namespace wwiv::wwivd\n\nusing namespace wwiv::wwivd;\n\nvoid signal_handler(int mysignal) {\n  cerr << \"Received signal: \" << mysignal << endl;\n  switch (mysignal) {\n  case SIGHUP: {\n    cerr << \"Received SIGHUP\" << endl;\n    need_to_reload_config.store(true);\n    break;\n  }\n  case SIGINT: {\n    cerr << endl;\n    if (bbs_pid != 0) {\n      cerr << \"Sending SIGINT to BBS after receiving \" << mysignal << \"...\" << endl;\n      kill(bbs_pid, mysignal); // send SIGHUP to process group\n    }\n  } break;\n  // Graceful exit\n  case SIGTERM: {\n    cerr << \"Received SIGTERM\" << endl;\n    need_to_exit.store(true);\n  } break;\n  // Not graceful exit\n  case SIGKILL: {\n    cerr << \"Received SIGKILL\" << endl;\n    need_to_exit.store(true);\n  } break;\n  }\n\n}\n\nvoid BeforeStartServer() {\n  struct sigaction sa {};\n  sigfillset(&sa.sa_mask);\n  sa.sa_handler = signal_handler;\n  if (sigaction(SIGHUP, &sa, nullptr) == -1) {\n    LOG(ERROR) << \"Unable to install signal handler for SIGINT\";\n  }\n  if (sigaction(SIGINT, &sa, nullptr) == -1) {\n    LOG(ERROR) << \"Unable to install signal handler for SIGINT\";\n  }\n  if (sigaction(SIGTERM, &sa, nullptr) == -1) {\n    LOG(ERROR) << \"Unable to install signal handler for SIGINT\";\n  }\n  if (sigaction(SIGKILL, &sa, nullptr) == -1) {\n    LOG(ERROR) << \"Unable to install signal handler for SIGINT\";\n  }\n  // Ignore SIGCHLD\n  signal(SIGCHLD, SIG_IGN);\n  // Let the socket library handle EPIPE\n  signal(SIGPIPE, SIG_IGN);\n}\n\nstatic uid_t GetWWIVUserId(const string& username) {\n  passwd* pw = getpwnam(username.c_str());\n  if (pw == nullptr) {\n    // Unable to find user, let's return our current uid.\n    LOG(ERROR) << \"Unable to find uid for username: \" << username;\n    return getuid();\n  }\n  return pw->pw_uid;\n}\n\nstatic gid_t GetWWIVUserGroupId(const string& username) {\n  passwd* pw = getpwnam(username.c_str());\n  if (pw == nullptr) {\n    // Unable to find user, let's return our current uid.\n    LOG(ERROR) << \"Unable to find uid for username: \" << username;\n    return getgid();\n  }\n  return pw->pw_gid;\n}\n\nvoid SwitchToNonRootUser(const std::string& wwiv_user) {\n  auto current_uid = getuid();\n  auto wwiv_uid = GetWWIVUserId(wwiv_user);\n  if (wwiv_uid != current_uid) {\n    // Try to set the group ID before user ID, since otherwise we don't\n    // have permissions to set the groupid after becoming non-root.\n    auto wwiv_gid = GetWWIVUserGroupId(wwiv_user);\n    if (setgid(wwiv_gid) != 0) {\n      LOG(ERROR) << \"Unable to call setgid(\" << wwiv_gid << \"); errno: \" << errno;\n    }\n    if (setuid(wwiv_uid) != 0) {\n      LOG(ERROR) << \"Unable to call setuid(\" << wwiv_uid << \"); errno: \" << errno;\n    }\n  }\n}\n\nbool ExecCommandAndWait(const wwivd_config_t& wc, wwiv::wwivd::NodeManager& node_manager,\n                        const std::string& cmd, const std::string& pid, int node_number,\n                        SOCKET sock) {\n  char sh[21];\n  char dc[21];\n  char cmdstr[4000];\n  to_char_array(sh, \"sh\");\n  to_char_array(dc, \"-c\");\n  to_char_array(cmdstr, cmd);\n  char* argv[] = { sh, dc, cmdstr, NULL };\n\n  VLOG(2) << pid << \"Invoking Command Line (posix_spawn):\" << cmd;\n  pid_t child_pid = 0;\n  int ret = posix_spawn(&child_pid, \"/bin/sh\", NULL, NULL, argv, environ);\n  if (sock != SOCKET_ERROR) {\n    // close the socket since we've forked.\n    closesocket(sock);\n  }\n  VLOG(2) << \"after posix_spawn; ret: \" << ret;\n  if (ret != 0) {\n    // fork failed.\n    LOG(ERROR) << pid << \"Error forking WWIV.\";\n    return false;\n  }\n  bbs_pid = child_pid;\n  node_manager.set_pid(node_number, bbs_pid);\n  int status = 0;\n  VLOG(2) << pid << \"before waitpid\";\n  while (waitpid(child_pid, &status, 0) == -1) {\n    if (errno != EINTR) {\n      break;\n    }\n  }\n  VLOG(2) << pid << \"after waitpid\";\n\n  std::ostringstream errs;\n  errs << pid;\n  if (node_number > 0) {\n    errs << \"Node #\" << node_number;\n  } else {\n    errs << \"cmd: \" << cmd;\n  }\n  const auto err = errs.str();\n  if (WIFEXITED(status)) {\n    // Process exited.\n    LOG(INFO) << err << \" exited with error code: \" << WEXITSTATUS(status);\n  }\n  else if (WIFSIGNALED(status)) {\n    LOG(INFO) << err << \" killed by signal: \" << WTERMSIG(status);\n  }\n  else if (WIFSTOPPED(status)) {\n    LOG(INFO) << err << \" stopped by signal: \" << WSTOPSIG(status);\n  }\n\n  return true;\n}\n\n"
  },
  {
    "path": "wwivd/wwivd_win.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5                            */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivd/wwivd.h\"\n\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/os.h\"\n#include \"core/socket_connection.h\"\n#include \"core/strings.h\"\n#include \"sdk/wwivd_config.h\"\n#include \"wwivd/node_manager.h\"\n#include <atomic>\n#include <iostream>\n#include <csignal>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\nusing namespace wwiv::os;\n\nnamespace wwiv::wwivd {\n\nextern std::atomic<bool> need_to_exit;\n} // namespace wwiv\n\nusing namespace wwiv::wwivd;\n\nvoid signal_handler(int mysignal) {\n  switch (mysignal) {\n  // Graceful exit\n  case SIGTERM: {\n    std::cerr << \"SIGTERM: \" << mysignal << std::endl;\n    // On Windows since we do this, we re-raise it.\n    signal(mysignal, SIG_DFL);\n    raise(mysignal);\n  } break;\n  // Interrupts\n  case SIGINT: {\n    std::cerr << \"SIGINT: \" << mysignal << std::endl;\n    need_to_exit.store(true);\n    // call default handler\n  } break;\n  default: {\n    std::cerr << \"Unknown signal: \" << mysignal << std::endl;\n  }\n  }\n}\n\n/*\n  #define CTRL_C_EVENT        0\n  #define CTRL_BREAK_EVENT    1\n  #define CTRL_CLOSE_EVENT    2\n  #define CTRL_LOGOFF_EVENT   5\n  #define CTRL_SHUTDOWN_EVENT 6\n */\nstatic BOOL WINAPI WWIVDConsoleHandlerRoutine(_In_ DWORD dwCtrlType) {\n  static std::string consoleHandlerNames[]{\n    \"CTRL_C_EVENT\", \"CTRL_BREAK_EVENT\", \"CTRL_CLOSE_EVENT\", \"???\", \"???\", \"CTRL_LOGOFF_EVENT\", \"CTRL_SHUTDOWN_EVENT\"\n  };\n  std::cerr << \"WWIVDConsoleHandlerRoutine: \" << consoleHandlerNames[dwCtrlType] << std::endl;\n  need_to_exit.store(true);\n  return TRUE;\n}\n\nvoid BeforeStartServer() {\n  // Not the best place, but this works.\n  InitializeSockets();\n  signal(SIGTERM, signal_handler);\n  signal(SIGINT, signal_handler);\n\n  // Set the console handler.\n  if (!SetConsoleCtrlHandler(WWIVDConsoleHandlerRoutine, TRUE)) {\n    LOG(WARNING) << \"SetConsoleCtrlHandler failed\";\n  }\n\n  std::cerr << \"set signal handlers\" << std::endl;\n}\n\nvoid SwitchToNonRootUser(const std::string&) {\n}\n\nbool ExecCommandAndWait(const wwivd_config_t& wc, wwiv::wwivd::NodeManager& node_manager,\n                        const std::string& cmd, const std::string& pid, int node_number,\n                        SOCKET sock) {\n\n  LOG(INFO) << pid << \"Invoking Command Line (Win32):\" << cmd;\n\n  STARTUPINFO si{};\n  si.cb = sizeof(STARTUPINFO);\n\n  if (wc.launch_minimized) {\n    // dwFlags says to look at wShowWindow, and wShowWindow\n    // says to minimize\n    si.dwFlags = STARTF_USESHOWWINDOW;\n    si.wShowWindow = SW_MINIMIZE;\n  }\n\n  PROCESS_INFORMATION pi{};\n  char cmdstr[4000];\n  to_char_array(cmdstr, cmd);\n\n  const DWORD creation_flags = CREATE_NEW_CONSOLE;\n\n  const auto current_dir = File::current_directory().string();\n  const auto ok = CreateProcess(\n    nullptr, \n    cmdstr,\n    nullptr,\n    nullptr,\n    TRUE,\n    creation_flags,\n    nullptr,\n    current_dir.c_str(),\n    &si,\n    &pi);\n\n  if (!ok) {\n    // CreateProcess failed.\n    LOG(ERROR) << \"Error invoking CreateProcess.\";\n    return false;\n  }\n\n  if (sock != INVALID_SOCKET) {\n    // We're done with this socket and the child has another reference count\n    // to it.\n    closesocket(sock);\n  }\n\n  node_manager.set_pid(node_number, pi.dwProcessId);\n\n  // Wait until child process exits.\n  auto dwExitCode = WaitForSingleObject(pi.hProcess, INFINITE);\n  GetExitCodeProcess(pi.hProcess, &dwExitCode);\n\n  // Close process and thread handles. \n  CloseHandle(pi.hProcess);\n  CloseHandle(pi.hThread);\n  if (node_number > 0) {\n    LOG(INFO) << \"Node #\" << node_number << \" exited with error code: \" << dwExitCode;\n  } else {\n    LOG(INFO) << \"Command: '\" << cmd << \"' exited with error code: \" << dwExitCode;\n  }\n  return true;\n}\n\n"
  },
  {
    "path": "wwivfsed/CMakeLists.txt",
    "content": "# CMake for WWIVfsed\n\n\nif(UNIX) \n  find_package (Threads)\n  set(FORKPTY_LIB util)\nendif()\n\nadd_executable(wwivfsed wwivfsed.cpp fsedconfig.cpp)\nset_max_warnings(wwivfsed)\ntarget_link_libraries(wwivfsed \n\tcommon \n\tcore\n\tfsed\n\tsdk\n  ${CMAKE_THREAD_LIBS_INIT} \n  ${FORKPTY_LIB}\n\t)\n"
  },
  {
    "path": "wwivfsed/fsedconfig.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivfsed/fsedconfig.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/inifile.h\"\n#include \"core/log.h\"\n#include \"common/null_remote_io.h\"\n#include \"common/remote_socket_io.h\"\n#include \"core/strings.h\"\n#include \"local_io/null_local_io.h\"\n// isatty\n#ifdef _WIN32\n#include \"local_io/local_io_win32.h\"\n#include <io.h>\n#else\n// Needed on Linux to init curses with the title/\n#include \"core/version.h\"\n#include \"local_io/local_io_curses.h\"\n#include \"localui/curses_io.h\"\nusing namespace wwiv::local::ui;\n#include <unistd.h>\n#endif\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::local::io;\n\nnamespace wwiv::wwivfsed {\n\nFsedConfig::FsedConfig(const CommandLine& cmdline) \n  : root_(cmdline.program_path().parent_path()), help_path_(FilePath(root_, \"gfiles\")) {\n  auto path = FilePath(root_, \"wwivfsed.ini\");\n  IniFile ini(path, \"WWIVFSED\");\n  if (ini.IsOpen()) {\n    VLOG(1) << \"Using wwivfsed.ini: '\" << path.string() << \"'\";\n    auto bt = ini.value<std::string>(\"bbs_type\", \"wwiv\");\n    bbs_type_ = strings::iequals(bt, \"wwiv\") ? bbs_type_t::wwiv : bbs_type_t::qbbs;\n    std::filesystem::path p = ini.value<std::string>(\"help_path\", \"gfiles\");\n    help_path_ = File::absolute(root_, p);\n  }\n\n  if (!File::Exists(help_path_)) {\n    LOG(WARNING) << \"Help Path does not exist '\" << help_path_ << \"'\";\n  }\n  local_ = cmdline.barg(\"local\");\n  pause_ = cmdline.barg(\"pause\");\n  file_ = cmdline.barg(\"file\");\n  wrap_ = cmdline.sarg(\"wrap\") == \"wwiv\";\n  if (file_) {\n    // Always local if we're editing a file\n    local_ = true;\n  }\n  socket_handle_ = cmdline.iarg(\"socket_handle\");\n  if (!cmdline.remaining().empty()) {\n    file_path_ = cmdline.remaining().front();\n  }\n\n}\n\nLocalIO* FsedConfig::CreateLocalIO() const {\n  if (local_ && !isatty(fileno(stdin))) {\n    LOG(ERROR) << \"WTF - No isatty?\";\n  }\n  if (local_) {\n#if defined(_WIN32)\n    return new Win32ConsoleIO();\n#else\n    if (local_) {\n      CursesIO::Init(fmt::sprintf(\"WWIVfsed %s\", full_version()));\n      return new CursesLocalIO(curses_out->GetMaxY(), curses_out->GetMaxX());\n    }\n#endif\n  }\n  return new NullLocalIO();\n}\n\nRemoteIO* FsedConfig::CreateRemoteIO(local::io::LocalIO* local_io) const {\n  if (local_) {\n    return new NullRemoteIO(local_io);\n  }\n  return new RemoteSocketIO(socket_handle_, false);\n}\n\nstd::filesystem::path FsedConfig::help_path() const { return help_path_; }\n\nstd::filesystem::path FsedConfig::file_path() const {\n  if (!file_path_.empty()) {\n    return file_path_;\n  }\n\n  return bbs_type() == bbs_type_t::wwiv ? \"input.msg\" : \"msgtmp\";\n}\n\n\n}\n\n"
  },
  {
    "path": "wwivfsed/fsedconfig.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVFSED_FSEDCONFIG_H\n#define INCLUDED_WWIVFSED_FSEDCONFIG_H\n\n#include \"common/remote_io.h\"\n#include \"core/command_line.h\"\n#include \"local_io/local_io.h\"\n#include <filesystem>\n\nnamespace wwiv::wwivfsed {\n\nclass FsedConfig final  {\npublic:\n  explicit FsedConfig(const core::CommandLine& cmdline);\n  ~FsedConfig() = default;\n\n  enum class bbs_type_t { wwiv, qbbs };\n\n  [[nodiscard]] bbs_type_t bbs_type() const noexcept { return bbs_type_; }\n  [[nodiscard]] int socket_handle() const noexcept { return socket_handle_; }\n  [[nodiscard]] bool local() const noexcept { return local_; }\n  [[nodiscard]] bool file() const noexcept { return file_; }\n  [[nodiscard]] bool pause() const noexcept { return pause_; }\n  [[nodiscard]] bool wrap() const noexcept { return wrap_; }\n  [[nodiscard]] const std::filesystem::path& root() const noexcept { return root_; }\n  [[nodiscard]] std::filesystem::path help_path() const;  \n  [[nodiscard]] std::filesystem::path file_path() const;\n\n  [[nodiscard]] local::io::LocalIO* CreateLocalIO() const;\n  [[nodiscard]] common::RemoteIO* CreateRemoteIO(local::io::LocalIO*) const;\n\nprivate:\n  const std::filesystem::path root_;\n  std::filesystem::path help_path_;\n  bbs_type_t bbs_type_{bbs_type_t::wwiv};\n  int socket_handle_{-1};\n  bool local_{false};\n  bool file_{false};\n  bool pause_{false};\n  bool wrap_{true};\n  std::filesystem::path file_path_;\n};\n\n} // namespace wwiv::wwivfsed\n\n#endif"
  },
  {
    "path": "wwivfsed/wwivfsed.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivfsed/wwivfsed.h\"\n\n#include \"common/common_events.h\"\n#include \"common/exceptions.h\"\n#include \"common/input.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/output.h\"\n#include \"common/quote.h\"\n#include \"common/remote_io.h\"\n#include \"core/command_line.h\"\n#include \"core/eventbus.h\"\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"core/version.h\"\n#include \"fsed/common.h\"\n#include \"fsed/fsed.h\"\n#include \"fsed/model.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/chains.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/menus/menu_set.h\"\n#include \"wwivfsed/fsedconfig.h\"\n\n#include <cstdlib>\n#include <exception>\n#include <string>\n\n#ifndef _WIN32\n#include \"localui/curses_io.h\"\nusing namespace wwiv::local::ui;\n#endif\n\n\nusing namespace wwiv::common;\nusing namespace wwiv::core;\nusing namespace wwiv::fsed;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivfsed {\n\nFsedContext::FsedContext(local::io::LocalIO* local_io)\n    : sess_(local_io), config_(\"\", {}), chains_(config_) {}\n  \n\nFsedApplication::FsedApplication(std::unique_ptr<FsedConfig> config)\n    : config_(std::move(config)), \n      local_io_(config_->CreateLocalIO()), \n      remote_io_(config_->CreateRemoteIO(local_io_.get())), \n      context_(local_io_.get()),\n      fake_macro_context_(&context_) {\n  bout.SetLocalIO(local_io_.get());\n  bout.SetComm(remote_io_.get());\n  bout.set_context_provider([this]() -> wwiv::common::Context& { return this->context(); });\n  bout.set_macro_context_provider(\n      [this]() -> wwiv::common::MacroContext& { return fake_macro_context_; });\n\n  bin.SetLocalIO(local_io_.get());\n  bin.SetComm(remote_io_.get());\n  bin.set_context_provider([this]() -> wwiv::common::Context& { return this->context(); });\n\n  if (config_->local()) {\n    context_.sess_.incom(false);\n    context_.sess_.outcom(false);\n    context_.sess_.using_modem(false);\n  } else {\n    context_.sess_.incom(true);\n    context_.sess_.outcom(true);\n    context_.sess_.using_modem(true);\n    context_.sess_.ok_modem_stuff(true);\n  }\n  // Make a dummy user record.\n  auto& u = context().u();\n  u.screen_width(80);\n  u.screen_lines(25);\n  u.set_flag(User::flag_ansi);\n  u.set_flag(User::status_color);\n  u.set_flag(User::extraColor);\n  u.set_flag(User::fullScreenReader);\n\n  const auto colors = {7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n  auto i = 0;\n  for (const auto c : colors) {\n    u.color(i++, c);\n  }\n\n  bus().add_handler<CheckForHangupEvent>([this]() { \n    if (config_->local()) {\n      return;\n    }\n    if (!context_.sess_.hangup() && !remote_io_->connected()) {\n      bus().invoke<HangupEvent>(HangupEvent{hangup_type_t::user_disconnected});\n    }\n  });\n  bus().add_handler<HangupEvent>([this]() { \n    if (context_.sess_.hangup()) {\n      // already hung-up\n      return;\n    }\n    VLOG(1) << \"Invoked Hangup()\";\n    context_.sess_.hangup(true);\n    throw hangup_error(hangup_type_t::user_logged_off, \"\"); // username\n  });\n\n  Dirs dirs(config_->root());\n  dirs.gfiles_directory(config_->help_path().string());\n  context_.sess_.dirs(dirs);\n}\n\nFsedApplication::~FsedApplication() {\n#ifndef _WIN32\n  // CursesIO.\n  delete curses_out;\n  curses_out = nullptr;\n#endif\n  remote_io_->close(false);\n}\n\nMessageEditorData FsedApplication::CreateMessageEditorData() {\n  \n  if (config().bbs_type() == FsedConfig::bbs_type_t::wwiv) {\n    // WWIV: editor.inf\n    TextFile f(FilePath(File::current_directory(), \"editor.inf\"), \"rt\");\n    auto lines = f.ReadFileIntoVector();\n    lines.resize(9);\n\n    MessageEditorData data(lines.at(3));\n    data.msged_flags = to_number<int>(lines.at(6));\n    if (data.msged_flags & 2 /* MSGED_FLAG_HAS_REPLY_NAME */) {\n      // TODO(rushfan): Figure out how to get to_name from text.\n      //data.to_name = lines.at()\n    }\n    data.title = lines.at(0);\n    data.sub_name = lines.at(1);\n    LoadQuotesWWIV(data);\n    return data;\n  }\n  // QuickBBS: MSGINF\n  TextFile f(FilePath(File::current_directory(), \"msginf\"), \"rt\");\n  auto lines = f.ReadFileIntoVector();\n  lines.resize(6);\n  MessageEditorData data(lines.at(0));\n  data.to_name = lines.at(1);\n  data.title = lines.at(2);\n  data.sub_name = lines.at(4);\n\n  LoadQuotesQBBS(data);\n  return data;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool FsedApplication::LoadQuotesWWIV(const MessageEditorData& data) {\n  TextFile f(FilePath(File::current_directory(), QUOTES_TXT), \"rt\");\n  if (!f) {\n    return false;\n  }\n  auto orig_lines = f.ReadFileIntoVector();\n  std::size_t min_size = 2;\n  if (data.msged_flags & 2) {\n    min_size++;\n  }\n  if (data.msged_flags & 4) {\n    min_size++;\n  }\n  if (orig_lines.size() <= min_size) {\n    return false;\n  }\n  std::vector<std::string> lines(std::begin(orig_lines) + min_size, std::end(orig_lines));\n\n  set_quotes_ind(std::make_unique<std::vector<std::string>>(lines));\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nbool FsedApplication::LoadQuotesQBBS(const MessageEditorData&) {\n  TextFile f(FilePath(File::current_directory(), MSGTMP), \"rt\");\n  if (!f) {\n    return false;\n  }\n  auto lines = f.ReadFileIntoVector();\n  if (lines.size() <= 1) {\n    return false;\n  }\n\n  set_quotes_ind(std::make_unique<std::vector<std::string>>(lines));\n  return true;\n}\n\nbool FsedApplication::DoFsed() {\n  auto path = config_->file_path();\n\n  // Create MessageEditorData and Load Quotes.\n  auto data{CreateMessageEditorData()};\n\n  // Data needs to_name, from_name, sub_name, title\n  FsedModel ed(1000);\n  if (auto file_lines = read_file(path, ed.maxli()); !file_lines.empty()) {\n    ed.set_lines(std::move(file_lines));\n  }\n  if (config_->file()) {\n    data.title = path.string();\n  }\n  // We don't want control-A,D,F to work natively so key bindings will.\n  bin.okskey(false);\n  if (auto save = fsed::fsed(context(), ed, data, config_->file()); !save) {\n    return false;\n  }\n\n  TextFile f(path, \"wt\");\n  if (!f) {\n    return false;\n  }\n  for (const auto& l : ed.to_lines(config_->wrap())) {\n    f.WriteLine(l);\n  }\n  return true;\n}\n\n\nint FsedApplication::Run() { \n  if (config_->pause()) {\n    local_io_->Puts(\"pause...\");\n    local_io_->GetChar();\n  }\n\n  if (!config_->local() && config_->socket_handle() == 0) {\n    LOG(ERROR) << \"Invalid Socket Handle Provided: \" << config_->socket_handle();\n  }\n\n  if (!remote_io_->open()) {\n    // Remote side disconnected.\n    LOG(ERROR) << \"Remote side disconnected.\";\n    return 1;\n  }\n\n  return DoFsed() ? 0 : 1;\n}\n\n\n} // namespace\n\nint main(int argc, char** argv) {\n  LoggerConfig logger_config(LogDirFromConfig);\n  Logger::Init(argc, argv, logger_config);\n\n  auto at_exit = finally(Logger::ExitLogger);\n  CommandLine cmdline(argc, argv, \"net\");\n  cmdline.AddStandardArgs();\n  cmdline.add_argument({\"socket_handle\", 'H', \"Socket Handle from BBS.\"});\n  cmdline.add_argument(BooleanCommandLineArgument{\"version\", 'V', \"Display version.\", false});\n  cmdline.add_argument(BooleanCommandLineArgument{\"local\", 'L', \"Run the door locally.\", false});\n  cmdline.add_argument(\n      BooleanCommandLineArgument{\"file\", 'F', \"Run locally to edit a file.\", false});\n  cmdline.add_argument({\"wrap\", 'W', \"Wrap lines using with 'wwiv' or 'none'.\", \"wwiv\"});\n  cmdline.add_argument(\n      BooleanCommandLineArgument{\"pause\", 'Z', \"Pause to attach the debugger.\", false});\n  cmdline.set_no_args_allowed(true);\n\n  if (!cmdline.Parse()) {\n    std::cout << cmdline.GetHelp() << std::endl;\n    return EXIT_FAILURE;\n  }\n  if (cmdline.help_requested()) {\n    std::cout << cmdline.GetHelp() << std::endl;\n    return EXIT_SUCCESS;\n  }\n  if (cmdline.barg(\"version\")) {\n    std::cout << full_version() << std::endl;\n    return 0;\n  }\n\n  LOG(INFO) << \"wwivfsed - WWIV5 Full-Screen Editor.\";\n\n  try {\n    auto app = std::make_unique<wwiv::wwivfsed::FsedApplication>(\n        std::make_unique<wwiv::wwivfsed::FsedConfig>(cmdline));\n    return app->Run();\n  } catch (const std::exception& e) {\n    LOG(ERROR) << \"Caught top level exception: \" << e.what();\n  }\n  return EXIT_FAILURE;\n}\n"
  },
  {
    "path": "wwivfsed/wwivfsed.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*              Copyright (C)2020-2022, WWIV Software Services            */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVFSED_WWIVFSED_H\n#define INCLUDED_WWIVFSED_WWIVFSED_H\n\n#include \"common/context.h\"\n#include \"common/macro_context.h\"\n#include \"common/message_editor_data.h\"\n#include \"common/remote_io.h\"\n#include \"local_io/local_io.h\"\n#include \"sdk/chains.h\"\n#include \"wwivfsed/fsedconfig.h\"\n#include <filesystem>\n#include <string>\n\nnamespace wwiv::sdk {\nclass Chains;\n}\nnamespace wwiv::wwivfsed {\n\nclass FakeMacroContext final : public common::MacroContext {\npublic:\n  FakeMacroContext() = delete;\n  FakeMacroContext(const FakeMacroContext&) = delete;\n  FakeMacroContext(FakeMacroContext&&) = delete;\n  FakeMacroContext& operator=(const FakeMacroContext&) = delete;\n  FakeMacroContext& operator=(FakeMacroContext&&) = delete;\n  explicit FakeMacroContext(common::Context* context) : MacroContext(context) {}\n  ~FakeMacroContext() override = default;\n\n  [[nodiscard]] std::string interpret_macro_char(char) const override { return \"\"; }  \n  [[nodiscard]] common::Interpreted interpret_string(const std::string&) const override {\n    return {};\n  }\n  [[nodiscard]] common::Interpreted evaluate_expression(const std::string&) const override {\n    return {};\n  }\n  \n};\n\nclass FsedContext final : public common::Context {\npublic:\n  FsedContext() = delete;\n  FsedContext(const FsedContext&) = delete;\n  FsedContext(FsedContext&&) = delete;\n  FsedContext& operator=(const FsedContext&) = delete;\n  FsedContext& operator=(FsedContext&&) = delete;\n  explicit FsedContext(local::io::LocalIO* local_io);\n  ~FsedContext() override = default;\n  [[nodiscard]] sdk::Config& config() override { return config_; }\n  [[nodiscard]] sdk::User& u() override { return user_; }\n  [[nodiscard]] common::SessionContext& session_context() override { return sess_; }\n  [[nodiscard]] bool mci_enabled() const override { return false; }\n  [[nodiscard]] const std::vector<editorrec>& editors() const override { return editors_; }\n  [[nodiscard]] const sdk::Chains& chains() const override { return chains_; }\n\n  sdk::User user_;\n  common::SessionContext sess_;\n  sdk::Config config_;\n  std::vector<editorrec> editors_;\n  sdk::Chains chains_;\n};\n\nclass FsedApplication final {\npublic:\n  FsedApplication() = delete;\n  FsedApplication(const FsedApplication&) = delete;\n  FsedApplication(FsedApplication&&) = delete;\n  FsedApplication& operator=(const FsedApplication&) = delete;\n  FsedApplication& operator=(FsedApplication&&) = delete;\n  explicit FsedApplication(std::unique_ptr<FsedConfig> config);\n  ~FsedApplication();\n  int Run();\n\n\nprivate:\n  // Creates a MessageEditorData by reading the message editor\n  // information files from the BBS.\n  common::MessageEditorData CreateMessageEditorData();\n  bool LoadQuotesWWIV(const wwiv::common::MessageEditorData& data);\n  bool LoadQuotesQBBS(const wwiv::common::MessageEditorData& data);\n  bool DoFsed();\n\n  [[nodiscard]] common::Context& context() { return context_; }\n  [[nodiscard]] const wwiv::common::Context& context() const { return context_; }\n  [[nodiscard]] FsedConfig& config() const { return *config_; }\n\n  const std::unique_ptr<FsedConfig> config_;\n  std::unique_ptr<local::io::LocalIO> local_io_;\n  std::unique_ptr<common::RemoteIO> remote_io_;\n  FsedContext context_;\n  FakeMacroContext fake_macro_context_;\n};\n\n}\n\n\n#endif"
  },
  {
    "path": "wwivutil/CMakeLists.txt",
    "content": "# CMake for WWIV 5\n\nset(WWIVUTIL_MAIN wwivutil.cpp)\n\nset(COMMAND_SOURCES\n  \"command.cpp\"\n  \"acs/acs.cpp\"\n  \"conf/conf.cpp\"\n  \"config/config.cpp\"\n  \"email/email.cpp\"\n  \"fido/fido.cpp\"\n  \"fido/dump_fido_packet.cpp\"\n  \"fido/dump_nodelist.cpp\"\n  \"fido/dump_fido_subscribers.cpp\"\n  \"files/allow.cpp\"\n  \"files/arc.cpp\"\n  \"files/files.cpp\"\n  \"files/tic.cpp\"\n  \"fix/dirs.cpp\"\n  \"fix/fix.cpp\"\n  \"fix/users.cpp\"\n  \"instance/instance.cpp\"\n  \"messages/messages.cpp\"\n  \"menus/menus.cpp\"\n  \"net/dump_bbsdata.cpp\"\n  \"net/dump_callout.cpp\"\n  \"net/dump_connect.cpp\"\n  \"net/dump_contact.cpp\"\n  \"net/dump_subscribers.cpp\"\n  \"net/dump_packet.cpp\"\n  \"net/list.cpp\"\n  \"net/net.cpp\"\n  \"net/req.cpp\"\n  \"net/send.cpp\"\n  \"print/print.cpp\"\n  \"status/status.cpp\"\n  \"subs/import.cpp\"\n  \"subs/subs.cpp\"\n  \"users/users.cpp\"\n  \"help.cpp\"\n  \"util.cpp\"\n  )\n\n\nadd_executable(wwivutil ${WWIVUTIL_MAIN} ${COMMAND_SOURCES})\nset_max_warnings(wwivutil)\ntarget_link_libraries(wwivutil common core binkp_lib sdk)\n"
  },
  {
    "path": "wwivutil/acs/acs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/acs/acs.h\"\n\n#include \"common/value/uservalueprovider.h\"\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include \"sdk/acs/eval.h\"\n\n#include <iostream>\n#include <string>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::acs;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::acs {\n\nAcsCommand::AcsCommand() : UtilCommand(\"acs\", \"Evaluates an ACS expression for a user.\") {}\n\nstd::string AcsCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage: \" << std::endl << std::endl;\n  ss << \"  acs : Evaluates an ACS expression for a user.\" << std::endl;\n  return ss.str();\n}\n\nint AcsCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const auto expr = remaining().front();\n  const auto user_number = iarg(\"user\");\n\n  const UserManager um(*config()->config());\n  const auto user = um.readuser(user_number);\n  if (!user) {\n    LOG(ERROR) << \"Failed to load user number \" << user_number;\n    return 1;\n  }\n\n  Eval eval(expr);\n  const auto sl = user->sl();\n  const auto& slr = config()->config()->sl(sl);\n  common::value::UserValueProvider u(*config()->config(), user.value(), sl, slr);\n  eval.add(&u);\n\n  const auto result = eval.eval();\n  std::cout << \"Evaluate: '\" << expr << \"' \";\n  if (!result) {\n    std::cout << \"evaluated to FALSE\" << std::endl;\n  } else {\n    std::cout << \"evaluated to TRUE\" << std::endl;\n  }\n  std::cout << std::endl;\n\n  if (eval.error()) {\n    std::cout << \"Expression has the following error: \" << eval.error_text()\n              << std::endl;\n    return 1;\n  }\n\n  if (barg(\"debug\")) {\n    std::cout << \"Execution Trace: \" << std::endl;\n    for (const auto& l : eval.debug_info()) {\n      std::cout << \"       + \" << l << std::endl;\n    }\n  }\n\n  return 0;\n}\n\nbool AcsCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument{\"debug\", \"Display expression evaluation at end of execution.\", true});\n  add_argument({\"user\", \"user number to use while evaluating the expression\", \"1\"});\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/acs/acs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_ACS_ACS_H\n#define INCLUDED_WWIVUTIL_ACS_ACS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::acs {\n\nclass AcsCommand final : public UtilCommand {\npublic:\n  AcsCommand();\n  AcsCommand(const AcsCommand&) = delete;\n  AcsCommand(AcsCommand&&) = delete;\n  AcsCommand& operator=(const AcsCommand&) = delete;\n  AcsCommand& operator=(AcsCommand&&) = delete;\n\n  [[nodiscard]] std::string GetUsage() const override;\n  ~AcsCommand() override = default;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif"
  },
  {
    "path": "wwivutil/command.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivutil/command.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivutil {\n\n// WWIVutil commands\n\nUtilCommand::UtilCommand(const std::string& name, const std::string& description)\n  : CommandLineCommand(name, description) {}\nUtilCommand::~UtilCommand() = default;\n\nbool UtilCommand::add(std::shared_ptr<UtilCommand> cmd) {\n  subcommands_.push_back(cmd);\n  cmd->AddStandardArgs();\n  const auto added = CommandLineCommand::add(cmd);\n  // We want to add the sub commands after we add this one\n  cmd->AddSubCommands();\n  return added;\n}\n\nConfiguration* UtilCommand::config() const {\n  return config_.get();\n}\n\nbool UtilCommand::set_config(const std::shared_ptr<Configuration>& config) { \n  for (const auto& s : subcommands_) {\n    s->set_config(config);\n  }\n  config_ = config;\n  return true; \n}\n\n}  // namespace\n"
  },
  {
    "path": "wwivutil/command.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_COMMAND_H\n#define INCLUDED_WWIVUTIL_COMMAND_H\n\n#include \"core/command_line.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/networks.h\"\n\n#include <memory>\n#include <memory>\n#include <string>\n\nnamespace wwiv::wwivutil {\nclass UtilCommand;\n\nclass Configuration final {\npublic:\n  explicit Configuration(std::unique_ptr<sdk::Config>&& config)\n      : config_(std::move(config)), networks_(*config_) {\n    if (!networks_.IsInitialized()) {\n      initialized_ = false;\n    }\n  }\n  ~Configuration() = default;\n\n  Configuration() = delete;\n  Configuration(const Configuration&) = delete;\n  Configuration(Configuration&&) = delete;\n  Configuration& operator=(const Configuration&) = delete;\n  Configuration& operator=(Configuration&&) = delete;\n\n  [[nodiscard]] sdk::Config* config() const { return config_.get(); }\n  [[nodiscard]] bool initialized() const { return initialized_; }\n  [[nodiscard]] const sdk::Networks& networks() const { return networks_; }\n  [[nodiscard]] const std::vector<UtilCommand*>& subcommands() const { return subcommands_; }\n  void set_subcommands(std::vector<UtilCommand*>& scs) { subcommands_ = scs; }\n\nprivate:\n  const std::string bbsdir_;\n  std::unique_ptr<sdk::Config> config_;\n  sdk::Networks networks_;\n  bool initialized_{true};\n  std::vector<UtilCommand*> subcommands_;\n};\n\n/** WWIVutil Command */\nclass UtilCommand : public core::CommandLineCommand {\npublic:\n  UtilCommand(const std::string& name, const std::string& description);\n  ~UtilCommand() override;\n\n  UtilCommand() = delete;\n  UtilCommand(const UtilCommand&) = delete;\n  UtilCommand(UtilCommand&&) = delete;\n  UtilCommand& operator=(const UtilCommand&) = delete;\n  UtilCommand& operator=(UtilCommand&&) = delete;\n\n  // Override to add all commands.\n  virtual bool AddSubCommands() = 0;\n  bool add(std::shared_ptr<UtilCommand> cmd);\n\n  [[nodiscard]] Configuration* config() const;\n  bool set_config(const std::shared_ptr<Configuration>& config);\n\nprivate:\n  std::shared_ptr<Configuration> config_;\n  std::vector<std::shared_ptr<UtilCommand>> subcommands_;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/conf/conf.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/conf/conf.h\"\n#include \"wwivutil/conf/conf.h\"\n\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"wwivutil/util.h\"\n\n#include <iomanip>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil {\n\nstatic void DisplayConferences(const std::set<conference_t>& c5, char key = 0) {\n  for (const auto& item : c5) {\n    if (key == '\\0' || item.key == key) {\n      std::cout << item.key << \") '\" << item.conf_name << \"' \" << std::endl;\n      std::cout << \"  [ACS: \" << item.acs << \"]\" << std::endl;\n    }\n  }\n}\n\nclass ConfDumpCommand final : public UtilCommand {\npublic:\n  ConfDumpCommand() : UtilCommand(\"dump\", \"Displays the info about a conference\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   dump --conf_type=[subs|dirs] [conf key]\" << std::endl;\n    ss << \"Example: dump --conf_type=subs A\" << std::endl << std::endl;\n    ss << \"         Note that an empty conference key dumps all converences\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    char key = 0;\n    if (!remaining().empty()) {\n      key = to_upper_case_char(remaining().front().front());\n    }\n\n    const auto datadir = config()->config()->datadir();\n    Subs subs(datadir, config()->networks().networks());\n    files::Dirs dirs(datadir, 0);\n    if (!subs.Load()) {\n      std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n      return 3;\n    }\n    if (!dirs.Load()) {\n      std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n      return 3;\n    }\n\n    const Conferences confs(datadir, subs, dirs, 0);\n\n    const auto kind_subs = iequals(sarg(\"conf_type\"), \"subs\");\n\n    auto& c = kind_subs ? confs.subs_conf() : confs.dirs_conf();\n\n    DisplayConferences(c.confs(), key);\n\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument(\"full\", \"Display full info about every command.\", false));\n    add_argument({\"conf_type\", \"The conference type ('subs' or 'dirs')\", \"subs\"});\n    return true;\n  }\n};\n\nclass ConfConvertCommand final : public UtilCommand {\npublic:\n  ConfConvertCommand() : UtilCommand(\"convert\", \"Converts 4.3x conferences to 5.6 format\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   convert \" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    const auto datadir = config()->config()->datadir();\n    Subs subs(datadir, config()->networks().networks());\n    files::Dirs dirs(datadir, 0);\n    if (!subs.Load()) {\n      std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n      return 3;\n    }\n    if (!dirs.Load()) {\n      std::cout << \"Unable to load subs.json. Aborting.\" << std::endl;\n      return 3;\n    }\n    Conferences confs(datadir, subs, dirs, 0);\n\n    const auto f = UpgradeConferences(*config()->config(), subs, dirs);\n    if (!confs.LoadFromFile(f)) {\n      std::cout << \"Failed to upgrade conferences\";\n    }\n\n    std::cout << \"Subs: \" << std::endl;\n    DisplayConferences(confs.subs_conf().confs());\n    std::cout << \"Dirs: \" << std::endl;\n    DisplayConferences(confs.dirs_conf().confs());\n    std::cout << std::endl << std::endl;\n\n    // Save confs to new version.\n    if (confs.Save()) {\n      if (!subs.Save()) {\n        LOG(ERROR) << \"Saved new conference, but failed to save subs\";\n      }\n      if (!dirs.Save()) {\n        LOG(ERROR) << \"Saved new conference, but failed to save dirs\";\n      }\n    }\n\n    return 0;\n  }\n\n  bool AddSubCommands() override final {\n    add_argument({\"menu_set\", \"The menuset to use\", \"wwiv\"});\n    add_argument({\"conf_type\", \"The conference type ('subs' or 'dirs')\", \"subs\"});\n    return true;\n  }\n};\n\nbool ConfCommand::AddSubCommands() {\n  if (!add(std::make_unique<ConfDumpCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<ConfConvertCommand>())) {\n    return false;\n  }\n\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/conf/conf.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_CONF_CONF_H\n#define INCLUDED_WWIVUTIL_CONF_CONF_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass ConfCommand final : public UtilCommand {\npublic:\n  ConfCommand(): UtilCommand(\"conf\", \"WWIV conference system commands.\") {}\n  ~ConfCommand() override = default;\n  bool AddSubCommands() override;\n};\n\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/config/config.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/config/config.h\"\n\n#include \"sdk/config.h\"\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/strings.h\"\n#include \"sdk/config430.h\"\n\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstatic int show_version(const Config& config) {\n  std::cout << \"5.2 Versioned Config    : \" << std::boolalpha << config.versioned_config_dat()\n       << std::endl;\n  std::cout << \"Written By WWIV Version : \" << config.written_by_wwiv_num_version() << std::endl;\n  std::cout << \"Config Revision #       : \" << config.config_revision_number() << std::endl;\n\n  return 0;\n}\n\nstatic bool set_version(Config& config, uint16_t wwiv_ver, uint32_t revision) {\n  if (!config.versioned_config_dat()) {\n    std::cout << \"Can only set the wwiv_version and config revision on a 5.1 or higher versioned \"\n            \"config.dat\"\n         << std::endl;\n    return false;\n  }\n\n  auto& h = config.header();\n  if (wwiv_ver >= 500) {\n    std::cout << \"setting wwiv_ver to \" << wwiv_ver << std::endl;\n    h.written_by_wwiv_num_version = wwiv_ver;\n  }\n  if (revision > 0) {\n    std::cout << \"setting revision to \" << revision << std::endl;\n    h.config_revision_number = revision;\n  }\n\n  if (wwiv_ver >= 500 || revision > 0) {\n    std::cout << \"Wrote Config.dat\" << std::endl;\n    config.Save();\n  }\n  std::cout << \"Nothing changed; Nothing to do.\" << std::endl << std::endl;\n  return false;\n}\n\nclass ConfigVersionCommand final : public UtilCommand {\npublic:\n  ConfigVersionCommand() : UtilCommand(\"version\", \"Sets or Gets the config version\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  get : Gets the config.dat version information.\" << std::endl;\n    ss << \"  set : Sets the config.dat version information.\" << std::endl << std::endl;\n    return ss.str();\n  }\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n    const auto set_or_get = ToStringLowerCase(remaining().front());\n\n    if (set_or_get == \"get\") {\n      return show_version(*this->config()->config());\n    }\n    if (set_or_get == \"set\") {\n      if (!set_version(*this->config()->config(), static_cast<uint16_t>(iarg(\"wwiv_version\")),\n                       iarg(\"revision\"))) {\n        std::cout << GetUsage() << GetHelp() << std::endl;\n        return 1;\n      }\n      return 0;\n    }\n    return 1;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"wwiv_version\", \"WWIV Version that created this config.dat\", \"\"});\n    add_argument({\"revision\", \"Configuration revision number\", \"\"});\n    return true;\n  }\n};\n\nclass ConfigConvertCommand final : public UtilCommand {\npublic:\n  ConfigConvertCommand() : UtilCommand(\"convert\", \"converts the config to either JSON or DAT format\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  json : Writes a config.json.\" << std::endl;\n    ss << \"  dat : Writes a config.dat.\" << std::endl << std::endl;\n    return ss.str();\n  }\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n    const auto out_format = ToStringLowerCase(remaining().front());\n\n    if (out_format == \"dat\") {\n      Config430 c430(config()->config()->to_config_t());\n      c430.Save();\n      return show_version(*this->config()->config());\n    }\n    if (out_format == \"json\") {\n      if (!set_version(*this->config()->config(), static_cast<uint16_t>(iarg(\"wwiv_version\")),\n                       iarg(\"revision\"))) {\n        std::cout << GetUsage() << GetHelp() << std::endl;\n        return 1;\n      }\n      return 0;\n    }\n    return 1;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"wwiv_version\", \"WWIV Version that created this config.dat\", \"\"});\n    add_argument({\"revision\", \"Configuration revision number\", \"\"});\n    return true;\n  }\n};\n\nbool ConfigCommand::AddSubCommands() {\n  add(std::make_unique<ConfigVersionCommand>());\n  add(std::make_unique<ConfigConvertCommand>());\n  return true;\n}\n\n} // namespace"
  },
  {
    "path": "wwivutil/config/config.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_CONFIG_H\n#define INCLUDED_WWIVUTIL_CONFIG_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass ConfigCommand final : public UtilCommand {\npublic:\n  ConfigCommand(): UtilCommand(\"config\", \"WWIV config commands.\") {}\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/email/email.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/email/email.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/names.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/networks.h\"\n#include \"wwivutil/util.h\"\n\n#include <ctime>\n#include <iomanip>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil {\n\nbool BaseEmailSubCommand::CreateMessageApi() {\n  if (api_) {\n    return true;\n  }\n  const MessageApiOptions options;\n  auto* x = new NullLastReadImpl();\n  api_ = std::make_unique<WWIVMessageApi>(options, *config()->config(),\n                                          config()->networks().networks(), x);\n  return true;\n}\n\nWWIVMessageApi& BaseEmailSubCommand::api() noexcept {\n  if (!api_) {\n    CreateMessageApi();\n  }\n  DCHECK(api_);\n  return *api_;\n}\n\nclass DeleteEmailCommand final : public BaseEmailSubCommand {\npublic:\n  DeleteEmailCommand()\n      : BaseEmailSubCommand(\"delete\", \"Deletes email number specified by '--num'.\") {}\n\n  ~DeleteEmailCommand() override = default;\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   delete --num=NN <base sub filename>\" << std::endl;\n    ss << \"Example: delete --num=10 general\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n\n    if (!CreateMessageApi()) {\n      std::clog << \"Error Creating message apis.\" << std::endl;\n      return 1;\n    }\n\n    auto email = api().OpenEmail();\n    if (!email) {\n      std::clog << \"Unable to Open email\" << std::endl;\n      return 1;\n    }\n\n    const auto num_messages = email->number_of_messages();\n    const auto message_number = iarg(\"num\");\n    std::cout << \"Email has \" << num_messages << \" messages.\" << std::endl;\n    std::cout << std::string(72, '-') << std::endl;\n\n    if (message_number < 0 || message_number > num_messages) {\n      LOG(ERROR) << \"Invalid message number #\" << message_number;\n      return 1;\n    }\n    \n    if (const auto success = email->DeleteMessage(message_number); !success) {\n      LOG(ERROR) << \"Unable to delete message #\" << message_number << \".\";\n      return 1;\n    }\n\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"num\", \"Message Number to delete.\", \"-1\"});\n    return true;\n  }\n};\n\nclass AddEmailCommand final : public BaseEmailSubCommand {\npublic:\n  AddEmailCommand() : BaseEmailSubCommand(\"add\", \"Creates/Adds a new email.\") {}\n\n  bool AddSubCommands() override {\n    add_argument({\"title\", \"email title to use\", \"\"});\n    add_argument({\"from\", \"The sender user number of this email\", \"\"});\n    add_argument({\"from_usernum\", \"The sender user name of this email\", \"\"});\n    add_argument({\"to\", \"The receiver user number for this email\", \"\"});\n    add_argument({\"date\", \"Date to use in 'Www Mmm dd hh:mm:ss yyyy' format (or empty for current date).\", \"\"});\n\n    return true;\n  }\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   add --title=\\\"Welcome\\\" --from=1 <text filename>\"\n       << std::endl;\n    ss << \"Example: add --from=1 --to=${to_usernum} welcome_email_text.txt\" << std::endl;\n    return ss.str();\n  }\n\n  [[nodiscard]] int Execute() override {\n\n\n    if (!CreateMessageApi()) {\n      std::clog << \"Error Creating message api.\" << std::endl;\n      return 1;\n    }\n\n    if (remaining().empty()) {\n      std::clog << \"Missing text filename.\" << std::endl;\n      return 1;\n    }\n\n    const auto filename(remaining().front());\n    auto from_usernum = iarg(\"from_usernum\");\n    if (from_usernum < 1) {\n      std::clog << \"--from_usernum must be user number >= 1\" << std::endl;\n      return 1;\n    }\n    auto from_name = sarg(\"from\");\n    auto title = sarg(\"title\");\n    if (title.empty()) {\n      std::clog << \"--title must be specified.\" << std::endl;\n      return 1;\n    }\n    auto to_num = iarg(\"to\");\n    if (to_num < 1) {\n      std::clog << \"--to must be user number >= 1\" << std::endl;\n      return 1;\n    }\n    auto daten = DateTime::now();\n    if (auto date_str = sarg(\"date\"); !date_str.empty()) {\n      std::istringstream ss(date_str);\n      std::tm dt = {};\n      ss >> std::get_time(&dt, \"Www Mmm dd hh:mm:ss yyyy\");\n      if (!ss.fail()) {\n        daten = DateTime::from_time_t(mktime(&dt));\n        std::clog << \"Error parsing date, defaulting to now: \" << daten.to_string() << std::endl;\n      }\n    }\n\n    auto area = api().OpenEmail();\n    if (!area) {\n      std::clog << \"Error opening email message area.\" << std::endl;\n      return 1;\n    }\n\n    TextFile text_file(filename, \"r\");\n    auto raw_text = text_file.ReadFileIntoString();\n    auto lines = SplitString(raw_text, \"\\n\", false);\n\n    EmailData header{};\n    header.from_system = 0;\n    header.from_user = static_cast<uint16_t>(from_usernum);\n    header.title = title;\n    header.from_network_number = 0;\n    header.user_number = static_cast<uint16_t>(to_num);\n    header.daten = daten.to_daten_t();\n\n    std::ostringstream ss;\n    if (from_usernum >= 1 && from_name.empty()) {\n      Names names(*config()->config());\n      from_name = names.UserName(from_usernum);\n    }\n    ss << from_name << \"\\r\\n\";\n    ss << daten.to_string() << \"\\r\\n\";\n    ss << JoinStrings(lines, \"\\r\\n\");\n    header.text = ss.str();\n\n    return area->AddMessage(header) ? 0 : 1;\n  }\n};\n\n\nbool EmailCommand::AddSubCommands() {\n  if (!add(std::make_unique<EmailDumpCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<DeleteEmailCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<AddEmailCommand>())) {\n    return false;\n  }\n  \n  return true;\n}\n\nEmailDumpCommand::EmailDumpCommand()\n    : BaseEmailSubCommand(\"dump\", \"Displays message header and text information.\") {}\n\nstd::string EmailDumpCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   dump <base sub filename>\" << std::endl;\n  ss << \"Example: dump general\" << std::endl;\n  return ss.str();\n}\n\nbool EmailDumpCommand::AddSubCommands() {\n  add_argument({\"start\", \"Starting message number.\", \"0\"});\n  add_argument({\"end\", \"Last message number.\", \"-1\"});\n  add_argument(BooleanCommandLineArgument(\"all\", \"dumps everything, control lines too\", false));\n\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nint EmailDumpCommand::ExecuteImpl(WWIVEmail* area, int start, int end, bool all) {\n\n  const Names names(*config()->config());\n\n  const auto last_message = end >= 0 ? end : area->number_of_messages();\n  std::cout << \"Email has \" << area->number_of_messages() << \" messages.\" << std::endl;\n  std::cout << std::string(72, '-') << std::endl;\n  for (auto current = start; current < last_message; current++) {\n    mailrec m{};\n    std::string text;\n    if (!area->read_email_header_and_text(current, m, text)) {\n      std::cout << \"#\" << current << \"  ERROR \" << std::endl;\n      VLOG(1) << \"Failed to read message number: \" << current;\n      std::cout << std::string(72, '-') << std::endl;\n      continue;\n    }\n    std::cout << \"Email #\" << current << std::endl;\n    const auto from_name  = names.UserName(m.fromuser);\n    std::cout << \"From: #\" << m.fromuser << \" (\" << from_name << \")\";\n    if (m.fromsys) {\n      std::cout << \"@\" << m.fromsys;\n      if (m.status & status_source_verified) {\n        std::cout << \" at network #\" << static_cast<int>(m.network.src_verified_msg.net_number) << std::endl;\n        std::cout << \"Source Verified Type: \" << m.network.src_verified_msg.source_verified_type;\n      } else {\n        std::cout << \" at network #\" << static_cast<int>(m.network.network_msg.net_number);\n      }\n    }\n    std::cout << std::endl;\n    const auto to_name  = names.UserName(m.touser);\n    std::cout << \"To:   #\" << m.touser << \" (\" << to_name << \")\";\n    if (m.tosys) {\n      std::cout << \"@\" << m.tosys;\n    }\n    std::cout << std::endl;\n    std::cout << \"date:  \" << daten_to_wwivnet_time(m.daten) << std::endl;\n    std::cout << \"title: \" << m.title << std::endl;\n\n    if (m.anony) {\n      std::cout << \"title: \" << m.anony << std::endl;\n    }\n    auto has_status = false;\n    if (m.status & status_multimail) {\n      std::cout << \"[MULTI]\";\n      has_status = true;\n    }\n    if (m.status & status_source_verified) {\n      std::cout << \"[VERIFIED]\";\n      has_status = true;\n    }\n    if (m.status & status_new_net) {\n      std::cout << \"[NET]\";\n      has_status = true;\n    }\n    if (m.status & status_seen) {\n      std::cout << \"[SEEN]\";\n      has_status = true;\n    }\n    if (m.status & status_replied) {\n      std::cout << \"[REPLIED]\";\n      has_status = true;\n    }\n    if (m.status & status_forwarded) {\n      std::cout << \"[FORWARDED]\";\n      has_status = true;\n    }\n    if (m.status & status_file) {\n      std::cout << \"[FILE]\";\n      has_status = true;\n    }\n    if (has_status) {\n      std::cout << std::endl;\n    }\n    std::cout << std::string(72, '-') << std::endl;\n    auto lines = wwiv::strings::SplitString(text, \"\\n\", false);\n    for (const auto& line : lines) {\n      if (line.empty()) {\n        continue;\n      }\n      if (line.front() != CD || all) {\n        for (const auto ch : line) {\n          dump_char(std::cout, ch);\n        }\n        std::cout << std::endl;\n      }\n    }\n    std::cout << \"------------------------------------------------------------------------\" << std::endl;\n  }\n  return 0;\n}\n\nint EmailDumpCommand::Execute() {\n  if (!CreateMessageApi()) {\n    std::clog << \"Error Creating message api.\" << std::endl;\n    return 1;\n  }\n    \n  const auto start = iarg(\"start\");\n  const auto end = iarg(\"end\");\n  const auto start_date = sarg(\"start_date\");\n  const auto end_date = sarg(\"end_date\");\n  const auto all = barg(\"all\");\n\n  if (auto area = api().OpenEmail()) {\n    // If we have dates, update the start and end numbers based on the dates.\n    const auto last_message = end >= 0 ? end : area->number_of_messages();\n    VLOG(1) << \"start: \" << start << \"; end: \" << last_message << std::endl;\n    return ExecuteImpl(area.get(), start, last_message, all);\n  }\n  std::clog << \"Error opening email area.\" << std::endl;\n  return 1;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/email/email.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_EMAIL_EMAIL_H\n#define INCLUDED_WWIVUTIL_EMAIL_EMAIL_H\n\n#include \"sdk/subxtr.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/msgapi/email_wwiv.h\"\n#include \"wwivutil/command.h\"\n#include <memory>\n\nnamespace wwiv::wwivutil {\n\nclass BaseEmailSubCommand : public UtilCommand {\npublic:\n  BaseEmailSubCommand() = delete;\n  BaseEmailSubCommand(const BaseEmailSubCommand&) = delete;\n  BaseEmailSubCommand& operator=(const BaseEmailSubCommand&) = delete;\n  BaseEmailSubCommand& operator=(BaseEmailSubCommand&&) = delete;\n  BaseEmailSubCommand(const std::string& name, const std::string& descr)\n      : UtilCommand(name, descr) {}\n  bool CreateMessageApi();\n  // N.B. if this doesn't exist this message will crash.\n  sdk::msgapi::WWIVMessageApi& api() noexcept;\n\nprotected:\n  std::unique_ptr<sdk::msgapi::WWIVMessageApi> api_;\n\nprivate:\n  std::string basename_;\n};\n\nclass EmailCommand final : public UtilCommand {\npublic:\n  EmailCommand(): UtilCommand(\"email\", \"WWIV email commands.\") {}\n  bool AddSubCommands() override;\n};\n\nclass EmailDumpCommand final: public BaseEmailSubCommand {\npublic:\n  EmailDumpCommand();\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n\nprotected:\n  int ExecuteImpl(sdk::msgapi::WWIVEmail* area, int start, int end, bool all);\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/fido/dump_fido_packet.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/fido/dump_fido_packet.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/fido/fido_packets.h\"\n#include \"sdk/fido/fido_util.h\"\n#include \"sdk/net/ftn_msgdupe.h\"\n#include \"sdk/net/packets.h\"\n#include \"wwivutil/util.h\"\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::fido {\n\nstatic std::string fido_attrib_to_string(uint16_t a) {\n  std::string s;\n  if (a & MSGPRIVATE)\n    s += \"[PRIVATE]\";\n  if (a & MSGCRASH)\n    s += \"[CRASH] \";\n  if (a & MSGREAD)\n    s += \"[READ] \";\n  if (a & MSGSENT)\n    s += \"[SENT] \";\n  if (a & MSGFILE)\n    s += \"[FILE] \";\n  if (a & MSGTRANSIT)\n    s += \"[TRANSIT] \";\n  if (a & MSGORPHAN)\n    s += \"[ORPHAN]\";\n  if (a & MSGKILL)\n    s += \"[KILL]\";\n  if (a & MSGLOCAL)\n    s += \"[LOCAL]\";\n  if (a & MSGHOLD)\n    s += \"[HOLD]\";\n  if (a & MSGUNUSED)\n    s += \"[UNUSED]\";\n  if (a & MSGFREQ)\n    s += \"[FREQ]\";\n  if (a & MSGRRREQ)\n    s += \"[RRREQ]\";\n  if (a & MSGISRR)\n    s += \"[ISRR]\";\n  if (a & MSGAREQ)\n    s += \"[AREQ]\";\n  if (a & MSGFUPDREQ)\n    s += \"[UPDREQ]\";\n\n  return s;\n}\n\nstatic int dump_stored_message(const std::string& filename) {\n  File f(filename);\n  if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n    LOG(ERROR) << \"Unable to open file: \" << filename;\n    return 1;\n  }\n\n  FidoStoredMessage msg;\n  const auto response = read_stored_message(f, msg);\n  if (response == ReadNetPacketResponse::END_OF_FILE) {\n    return 0;\n  }\n  if (response == ReadNetPacketResponse::ERROR) {\n    return 1;\n  }\n\n  const auto& h = msg.nh;\n  const auto from_address = get_address_from_stored_message(msg);\n  const auto dt = fido_to_daten(h.date_time);\n  const auto roundtrip_dt = daten_to_fido(dt);\n\n  std::cout << std::dec << \"==============================================================================\"\n       << std::endl;\n  std::cout << \"cost:    \" << h.cost << std::endl;\n  std::cout << \"to:      \" << h.to << \"(\" << h.dest_zone << \":\" << h.dest_net << \"/\" << h.dest_node\n       << \".\" << h.dest_point << \")\" << std::endl;\n  std::cout << \"from:    \" << h.from << \"(\" << from_address.as_string() << \".\" << h.orig_point << \")\"\n       << std::endl;\n  std::cout << \"subject: \" << h.subject << std::endl;\n  std::cout << \"date:    \" << h.date_time << \"; [\" << roundtrip_dt << \"]\" << std::endl;\n  std::cout << \"# read:  \" << h.times_read << \"; reply_to: \" << h.reply_to << std::endl;\n  std::cout << \"attrib:  \" << fido_attrib_to_string(h.attribute);\n  std::cout << std::endl;\n  std::cout << \"text: \" << std::endl << std::endl;\n  for (const auto ch : FidoToWWIVText(msg.text, false)) {\n    dump_char(std::cout, ch);\n  }\n  std::cout << std::endl;\n  return 0;\n}\n\nstatic int dump_packet_file(const std::string& filename) {\n  File f(filename);\n  if (!f.Open(File::modeBinary | File::modeReadOnly)) {\n    LOG(ERROR) << \"Unable to open file: \" << filename;\n    return 1;\n  }\n\n  auto done = false;\n  packet_header_2p_t header = {};\n  auto num_header_read = f.Read(&header, sizeof(packet_header_2p_t));\n  if (num_header_read < static_cast<int>(sizeof(packet_header_2p_t))) {\n    LOG(ERROR) << \"Read less than packet header\";\n    return 1;\n  }\n\n  while (!done) {\n    FidoPackedMessage msg;\n    auto response = read_packed_message(f, msg);\n    if (response == ReadNetPacketResponse::END_OF_FILE) {\n      return 0;\n    }\n    if (response == ReadNetPacketResponse::ERROR) {\n      return 1;\n    }\n\n    auto from_address = get_address_from_packet(msg, header);\n    auto dt = fido_to_daten(msg.vh.date_time);\n    auto roundtrip_dt = daten_to_fido(dt);\n\n    std::cout << \"==[ HEADER ]==================================================================\"\n         << std::endl;\n    auto year = header.year;\n    if (year < 1000) {\n      year += 1900;\n    }\n    std::cout << \"Packet date: \" << (1900 + year) << \"-\" << header.month + 1 << \"-\" << header.day\n         << std::endl;\n    std::cout << \"         PW: '\" << header.password << \"'\" << std::endl;\n    uint32_t hc{}, mc{};\n    if (wwiv::sdk::FtnMessageDupe::GetMessageCrc32s(msg, hc, mc)) {\n      std::cout << \" Header CRC: '\" << std::hex << hc << \"'\" << std::endl;\n      std::cout << \"Message CRC: '\" << std::hex << mc << \"'\" << std::endl;\n    }\n    std::cout << std::dec << \"==============================================================================\"\n         << std::endl;\n    std::cout << \"   msg_type: \" << msg.nh.message_type << std::endl;\n    std::cout << \"       cost: \" << msg.nh.cost << std::endl;\n    std::cout << \"         to: \" << msg.vh.to_user_name << \"(\" << msg.nh.dest_net << \"/\"\n         << msg.nh.dest_node << \")\" << std::endl;\n    std::cout << \"       from: \" << msg.vh.from_user_name << \"(\" << from_address << \")\" << std::endl;\n    std::cout << \"    subject: \" << msg.vh.subject << std::endl;\n    std::cout << \"       date: \" << msg.vh.date_time << \"; [\" << roundtrip_dt << \"]\" << std::endl;\n    std::cout << \"       text: \" << std::endl << std::endl;\n    for (const auto ch : FidoToWWIVText(msg.vh.text, false)) {\n      dump_char(std::cout, ch);\n    }\n    std::cout << std::endl;\n    std::cout << \"==============================================================================\"\n         << std::endl;\n  }\n  return 0;\n}\n\nstatic int dump_file(const std::string& filename) {\n  const auto s = ToStringLowerCase(filename);\n\n  if (ends_with(s, \".msg\")) {\n    return dump_stored_message(filename);\n  }\n  if (ends_with(s, \".pkt\")) {\n    return dump_packet_file(filename);\n  }\n\n  std::cout << \"Can't tell filetype for: \" << filename;\n  return 1;\n}\n\nstd::string DumpFidoPacketCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   dump <filename>\" << std::endl;\n  ss << \"Example: dump 02054366.PKT\" << std::endl;\n  return ss.str();\n}\n\nint DumpFidoPacketCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const auto filename(remaining().front());\n  return dump_file(filename);\n}\n\nbool DumpFidoPacketCommand::AddSubCommands() { return true; }\n\n} \n"
  },
  {
    "path": "wwivutil/fido/dump_fido_packet.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_FIDO_PACKET_H\n#define INCLUDED_WWIVUTIL_DUMP_FIDO_PACKET_H\n\n#include \"core/command_line.h\"\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::fido {\n\nclass DumpFidoPacketCommand final : public UtilCommand {\npublic:\n  DumpFidoPacketCommand() : UtilCommand(\"dump\", \"Dumps contents of a fido packet\") {}\n  std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/fido/dump_fido_subscribers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/fido/dump_fido_subscribers.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/subscribers.h\"\n\n#include <chrono>\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing wwiv::core::CommandLineCommand;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::fido {\n\nstatic int dump_file(const std::filesystem::path& filename) {\n\n  if (!File::Exists(filename)) {\n    LOG(ERROR) << \"subscriber file: '\" << filename << \"' does not exist.\";\n    return 1;\n  }\n\n  const auto start = std::chrono::steady_clock::now();\n  auto subscribers = ReadFidoSubcriberFile(filename);\n  const auto end = std::chrono::steady_clock::now();\n  if (subscribers.empty()) {\n    LOG(INFO) << \"No Subscribers: \" << filename;\n    return 0;\n  }\n\n  const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);\n  std::cout << \"Read \" << subscribers.size() << \" in \" << elapsed.count() << \" milliseconds. \"\n       << std::endl;\n  std::cout << \"Read \" << subscribers.size() << \" in \" << elapsed.count() / 1000 << \" seconds. \"\n       << std::endl;\n\n  for (const auto& e : subscribers) {\n    std::cout << e.as_string() << std::endl;\n  }\n  return 0;\n}\n\nstd::string DumpFidoSubscribersCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   subscribers <subscriber filename>\" << std::endl;\n  ss << \"Example: subscribers net/ftn/nGENCHAT.net\" << std::endl;\n  return ss.str();\n}\n\nint DumpFidoSubscribersCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const std::filesystem::path p{remaining().front()};\n  return dump_file(p);\n}\n\nbool DumpFidoSubscribersCommand::AddSubCommands() {\n  return true;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/fido/dump_fido_subscribers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2018-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_FIDO_SUBSCRIBERS_H\n#define INCLUDED_WWIVUTIL_DUMP_FIDO_SUBSCRIBERS_H\n\n#include \"core/command_line.h\"\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::fido {\n\nclass DumpFidoSubscribersCommand final : public UtilCommand {\npublic:\n  DumpFidoSubscribersCommand()\n      : UtilCommand(\"subscribers\", \"Dumps contents of a fido subscriber list\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/fido/dump_nodelist.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/fido/dump_nodelist.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/fido/nodelist.h\"\n#include \"sdk/net/net.h\"\n\n#include <chrono>\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing wwiv::core::CommandLineCommand;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::fido {\n\nstatic int dump_file(const std::string& filename) {\n\n  const auto start = std::chrono::steady_clock::now();\n  const Nodelist n(filename, \"\");\n  const auto end = std::chrono::steady_clock::now();\n  if (!n.initialized()) {\n    LOG(ERROR) << \"Unable to load nodelist: \" << filename;\n    return 1;\n  }\n\n  const auto& entries = n.entries();\n\n  const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);\n  std::cout << \"Parsed \" << entries.size() << \" in \" << elapsed.count() << \" milliseconds. \" << std::endl;\n  std::cout << \"Parsed \" << entries.size() << \" in \" << elapsed.count()/1000 << \" seconds. \" << std::endl;\n  std::cout << std::endl;\n\n  for (const auto& e : entries) {\n    std::cout << e.first << \": \" << e.second.name() << std::endl;\n  }\n  return 0;\n}\n\nstd::string DumpNodelistCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   nodelist <nodelistfilename>\" << std::endl;\n  ss << \"Example: nodelist nodelist.123\" << std::endl;\n  return ss.str();\n}\n\nint DumpNodelistCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const auto filename(remaining().front());\n  return dump_file(filename);\n}\n\nbool DumpNodelistCommand::AddSubCommands() {\n  return true;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/fido/dump_nodelist.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_NODELIST_H\n#define INCLUDED_WWIVUTIL_DUMP_NODELIST_H\n\n#include \"core/command_line.h\"\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::fido {\n\nclass DumpNodelistCommand final : public UtilCommand {\npublic:\n  DumpNodelistCommand() : UtilCommand(\"nodelist\", \"Dumps contents of a fido nodelist\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/fido/fido.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/fido/fido.h\"\n\n#include \"core/command_line.h\"\n#include \"sdk/config.h\"\n#include \"wwivutil/fido/dump_fido_packet.h\"\n#include \"wwivutil/fido/dump_fido_subscribers.h\"\n#include \"wwivutil/fido/dump_nodelist.h\"\n\n#include <memory>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivutil::fido {\n\nbool FidoCommand::AddSubCommands() {\n  add(std::make_unique<DumpFidoPacketCommand>());\n  add(std::make_unique<DumpNodelistCommand>());\n  add(std::make_unique<DumpFidoSubscribersCommand>());\n  return true;\n}\n\n\n}  // namespace\n\n"
  },
  {
    "path": "wwivutil/fido/fido.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FIDO_H\n#define INCLUDED_WWIVUTIL_FIDO_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::fido {\n\nclass FidoCommand final : public UtilCommand {\npublic:\n  FidoCommand(): UtilCommand(\"fido\", \"WWIV fido commands.\") {}\n  bool AddSubCommands() override final;\n};\n\n}\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/files/allow.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/allow.h\"\n#include \"wwivutil/files/allow.h\"\n\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/filenames.h\"\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::files;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::files {\n\n\nclass AllowListCommand final : public UtilCommand {\npublic:\n  AllowListCommand() : UtilCommand(\"list\", \"Lists the contents of allow.dat\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   list [search spec]\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    std::string pattern;\n    if (!remaining().empty()) {\n      pattern = ToStringUpperCase(remaining().front());\n    }\n    const Allow allow(*config()->config());\n    const auto& all = allow.allow_vector();\n    for (const auto& a : all) {\n      const auto fn = ToStringUpperCase(a.a);\n      if (pattern.empty() || fn.find(pattern) != std::string::npos) {\n        std::cout << a.a << \"\\n\";\n      }\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nclass AllowAddCommand final : public UtilCommand {\npublic:\n  AllowAddCommand() : UtilCommand(\"add\", \"Add to the contents of allow.dat\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   add <filename>\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n    const auto& fn = remaining().front();\n    Allow allow(*config()->config());\n    if (!allow.Add(fn)) {\n      LOG(ERROR) << \"Failed to add file: \" << fn;\n      return 1;\n    }\n    if (!allow.Save()) {\n      LOG(ERROR) << \"Failed to add file (save failed) : \" << ALLOW_DAT;\n      return 1;\n    }\n    std::cout << \"Added file: \" << fn;\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nclass AllowedCommand final : public UtilCommand {\npublic:\n  AllowedCommand() : UtilCommand(\"allowed\", \"Is the file allowed (i.e. not in the list)\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   allowed <filename>\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n    const auto& fn = remaining().front();\n    Allow allow(*config()->config());\n    if (const auto allowed = allow.IsAllowed(fn); allowed) {\n      std::cout << \"filename allowed:     \" << fn;\n    } else {\n      std::cout << \"filename NOT allowed: \" << fn;\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nclass AllowDeleteCommand final : public UtilCommand {\npublic:\n  AllowDeleteCommand() : UtilCommand(\"delete\", \"Delete from the contents of allow.dat\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   delete <filename>\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n    const auto& fn = remaining().front();\n    Allow allow(*config()->config());\n    if (!allow.Remove(fn)) {\n      LOG(ERROR) << \"Failed to delete file: \" << fn;\n      return 1;\n    }\n    if (!allow.Save()) {\n      LOG(ERROR) << \"Failed to save : \" << ALLOW_DAT;\n      return 1;\n    }\n    std::cout << \"Deleted file: \" << fn;\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nstd::string AllowCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   allow \" << std::endl;\n  return ss.str();\n}\n\nbool AllowCommand::AddSubCommands() {\n  if (!add(std::make_unique<AllowListCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<AllowAddCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<AllowedCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<AllowDeleteCommand>())) {\n    return false;\n  }\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/files/allow.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless required  by  applicable  law  or agreed to  in writing,     */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FILES_ALLOW_H\n#define INCLUDED_WWIVUTIL_FILES_ALLOW_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil::files {\n\nclass AllowCommand final: public UtilCommand {\npublic:\n  AllowCommand() : UtilCommand(\"allow\", \"Manipulate allow.dat\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n} // namespace\n\n#endif"
  },
  {
    "path": "wwivutil/files/arc.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/files/arc.h\"\n\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"sdk/files/arc.h\"\n#include \"sdk/vardec.h\"\n\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::files {\n\n\nclass ArcViewCommand final : public UtilCommand {\npublic:\n  ArcViewCommand() : UtilCommand(\"view\", \"Views the contents of an archive.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   view [filename]\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n    const std::filesystem::path fn{remaining().front()};\n\n    auto o = sdk::files::list_archive(fn);\n    if (!o) {\n      LOG(INFO) << \"Unable to view archive: '\" << fn.string() << \"'.\";\n      return 1;\n    }\n    const auto& files = o.value();\n    std::cout << \"CompSize     Size   Date   Time  CRC-32   File Name\" << std::endl;\n    std::cout << \"======== -------- ======== ----- ======== ----------------------------------\"\n              << std::endl;\n    for (const auto& f : files) {\n      const auto dt = DateTime::from_time_t(f.dt);\n      auto d = dt.to_string(\"%m/%d/%y\");\n      auto t = dt.to_string(\"%I:%M\");\n      auto line = fmt::format(\"{:>8} {:>8} {:<8} {:<5} {:>08x} {}\", \n        f.compress_size, f.uncompress_size, d, t, f.crc32, f.filename);\n      std::cout << line << std::endl;\n    }\n\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nclass ArcCmdCommand final : public UtilCommand {\npublic:\n  ArcCmdCommand() : UtilCommand(\"cmd\", \"Gets the commands to use for an archive.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   cmd [filename]\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n\n    const auto arcs = sdk::files::read_arcs(config()->config()->datadir());\n    const std::filesystem::path fn{remaining().front()};\n\n    if (auto oa = sdk::files::find_arcrec(arcs, fn)) {\n      const auto& a = oa.value();\n      std::cout << \"Add:     \" << a.arca << std::endl;\n      std::cout << \"Delete:  \" << a.arcd << std::endl;\n      std::cout << \"Extract: \" << a.arce << std::endl;\n      std::cout << \"Comment: \" << a.arck << std::endl;\n      std::cout << \"List:    \" << a.arcl << std::endl;\n      std::cout << \"Test:    \" << a.arct << std::endl;\n      return 0;\n    }\n    LOG(ERROR) << \"Unable to determine the type of archive for \" << fn.string();\n    return 1;\n  }\n\n  bool AddSubCommands() override { return true; }\n  };\n\n  [[nodiscard]] std::string ArcCommand::GetUsage() const {\n    std::ostringstream ss;\n    ss << \"Usage:   arc \" << std::endl;\n    return ss.str();\n  }\n\n  bool ArcCommand::AddSubCommands() {\n    if (!add(std::make_unique<ArcViewCommand>())) {\n      return false;\n    }\n    if (!add(std::make_unique<ArcCmdCommand>())) {\n      return false;\n    }\n    return true;\n  }\n\n  } // namespace wwiv\n"
  },
  {
    "path": "wwivutil/files/arc.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless required  by  applicable  law  or agreed to  in writing,     */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FILES_ARC_H\n#define INCLUDED_WWIVUTIL_FILES_ARC_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil::files {\n\nclass ArcCommand final: public UtilCommand {\npublic:\n  ArcCommand() : UtilCommand(\"arc\", \"Manipulate archives\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n} // namespace wwiv\n\n#endif\n"
  },
  {
    "path": "wwivutil/files/files.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/files.h\"\n#include \"wwivutil/files/files.h\"\n\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/config.h\"\n#include \"wwivutil/files/allow.h\"\n#include \"wwivutil/files/arc.h\"\n#include \"wwivutil/files/tic.h\"\n\n#include <algorithm>\n#include <iomanip>\n#include <filesystem>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::stl;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil::files {\n\nstatic std::optional<std::vector<sdk::files::directory_t>>\nReadAreas(const std::filesystem::path& datadir) {\n  sdk::files::Dirs dirs(datadir, 0);\n  if (dirs.Load()) {\n    return {dirs.dirs()};\n  }\n  return std::nullopt;\n}\n\nclass AreasCommand final : public UtilCommand {\npublic:\n  AreasCommand()\n    : UtilCommand(\"areas\", \"Lists the file areas\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   areas\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    auto dirs = ReadAreas(config()->config()->datadir());\n    if (!dirs) {\n      return 2;\n    }\n\n    int num = 0;\n    std::cout << \"#Num FileName \" << std::setw(30) << std::left << \"Name\" << \" \" \n         << \"Path\" << std::endl;\n    std::cout << std::string(78, '=') << std::endl;\n    for (const auto& d : dirs.value()) {\n      std::cout << \"#\" << std::setw(3) << std::left << num++ << \" \"\n           << std::setw(8) << d.filename << \" \" \n           << std::setw(30) << d.name << \" \" << d.path\n           << std::endl;\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument(\"full\", \"Display full info about every area.\", false));\n    return true;\n  }\n};\n\nclass ListCommand final : public UtilCommand {\npublic:\n  ListCommand()\n    : UtilCommand(\"list\", \"Lists the files in an area\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   list [num]\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::clog << \"Missing file areas #.\" << std::endl;\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n    auto o = ReadAreas(config()->config()->datadir());\n    if (!o) {\n      return 2;\n    }\n    const auto& area_string = remaining().front();\n    if (area_string.empty()) {\n      LOG(ERROR) << \"No file area specified\";\n      return 1;\n    }\n    if (!isdigit(area_string.front())) {\n      LOG(ERROR) << \"No file area number specified.  Input given: \" << area_string;\n      return 1;\n    }\n    const auto area_num = to_number<int>(area_string);\n    const auto& dirs = o.value();\n\n    if (area_num < 0 || area_num >= size_int(dirs)) {\n      LOG(ERROR) << \"invalid area number '\" << area_num << \"' specified. \";\n      const auto max_size = std::max<int>(0, dirs.size() - 1);\n      LOG(ERROR) << \"area_num must be between 0 and \" << max_size;\n      return 1;\n    }\n    sdk::files::FileApi api(config()->config()->datadir());\n    const auto& dir = at(dirs, area_num);\n    auto area = api.Open(dir);\n    if (!area) {\n      LOG(ERROR) << \"Unable to open area: #\" << area_num << \"; filename: \" << dir.filename;\n      return 1;\n    }\n    auto num_files = area->number_of_files();\n    std::cout << fmt::format(\"File Area: {} ({} files)\", dir.name, num_files) << std::endl;\n    std::cout << std::endl;\n    const auto& h = area->header();\n    if (static_cast<int>(h.num_files()) != num_files) {\n      std::cout << fmt::format(\"WARNING: Header doesn't match header:{} vs. size:{}\", h.num_files(),\n                          num_files)\n           << std::endl;\n    }\n    std::cout << \"#Num File Name   \" << std::left << \"Description\" << std::endl;\n    std::cout << std::string(78, '=') << std::endl;\n    for (auto num = 1; num <= num_files; num++) {\n      auto f = area->ReadFile(num);\n      std::cout << fmt::format(\"#{: <3} {: <12} {}\", num, f.unaligned_filename(), f.description()) << std::endl;\n      if (f.has_extended_description() && barg(\"ext\")) {\n        auto so = area->ReadExtendedDescriptionAsString(f);\n        if (!so) {\n          continue;\n        }\n        auto lines = SplitString(so.value(), \"\\n\", false);\n        for(const auto& l : lines) {\n          std::cout << std::string(18, ' ') << StringTrim(l) << std::endl;\n        }\n      }\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument(\"ext\", \"Display extended descriptions.\", false));\n    return true;\n  }\n};\n\nclass DeleteFileCommand final : public UtilCommand {\npublic:\n  DeleteFileCommand() : UtilCommand(\"delete\", \"Deleate a file in an area\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   delete --num=NN <sub #>\" << std::endl;\n    ss << \"Example: delete --num=10 1\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::clog << \"Missing file area #.\" << std::endl;\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n\n    auto o = ReadAreas(config()->config()->datadir());\n    if (!o) {\n      return 2;\n    }\n    const auto area_num = to_number<int>(remaining().front());\n    const auto dirs = o.value();\n    if (area_num < 0 || area_num >= size_int(dirs)) {\n      LOG(ERROR) << \"invalid area number '\" << area_num << \"' specified. \";\n      const auto max_size = std::max<int>(0, dirs.size() - 1);\n      LOG(ERROR) << \"area_num must be between 0 and \" << max_size;\n      return 1;\n    }\n\n    const auto& dir = at(dirs, area_num);\n    sdk::files::FileApi api(config()->config()->datadir());\n    auto area = api.Open(dir);\n    if (!area) {\n      LOG(ERROR) << \"Unable to open file: \" << dir.filename;\n      return 1;\n    }\n\n    const auto file_number = arg(\"num\").as_int();\n    if (file_number < 1 || file_number > area->number_of_files()) {\n      LOG(ERROR) << \"invalid file number '\" << file_number << \"' specified. \";\n      LOG(ERROR) << \"num must be between 1 and \" << area->number_of_files();\n      return 1;\n    }\n    const auto f = area->ReadFile(file_number);\n    std::cout << \"Attempting to delete file: \" << f.unaligned_filename();\n    if (!area->DeleteFile(file_number)) {\n      LOG(ERROR) << \"Unable to delete file.\";\n      return 1;\n    }\n    return area->Close() ? 0: 1;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"num\", \"File Number to delete.\", \"-1\"});\n    return true;\n  }\n};\n\nbool FilesCommand::AddSubCommands() {\n  if (!add(std::make_unique<AllowCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<ArcCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<TicCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<AreasCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<ListCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<DeleteFileCommand>())) {\n    return false;\n  }\n  return true;\n}\n\n} // namespace\n"
  },
  {
    "path": "wwivutil/files/files.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FILES_H\n#define INCLUDED_WWIVUTIL_FILES_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::files {\n\nclass FilesCommand final : public UtilCommand {\npublic:\n  FilesCommand(): UtilCommand(\"files\", \"WWIV file commands.\") {}\n  bool AddSubCommands() override;\n};\n\n} // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/files/tic.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/files/tic.h\"\n#include \"wwivutil/files/tic.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n\n#include <iostream>\n#include <string>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::files {\n\n\nclass TicValidateCommand final : public UtilCommand {\npublic:\n  TicValidateCommand() : UtilCommand(\"validate\", \"Validates the contents of a TIC file.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   list [search spec]\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cerr << \"missing filename\";\n      return 2;\n    }\n    const std::filesystem::path fn{remaining().front()};\n    const auto dir = fn.parent_path();\n    const sdk::files::TicParser parser(dir);\n    const auto otic = parser.parse(fn.filename().string());\n    if (!otic) {\n      LOG(ERROR) << \"Failed to parse TIC file: \" << fn.string();\n      return 1;\n    }\n    if (const auto & tic = otic.value(); !tic.IsValid()) {\n      LOG(INFO) << \"TIC file:   '\" << fn.string() << \" is not valid. \";\n      LOG(INFO) << \"crc_valid:  \" << tic.crc_valid();\n      LOG(INFO) << \"size_valid: \" << tic.size_valid();\n      LOG(INFO) << \"Exists:     \" << tic.exists();\n      LOG(INFO) << \"IsValid:    \" << tic.IsValid();\n      return 1;\n    }\n    LOG(INFO) << \"TIC file:   '\" << fn.string() << \" is valid. \";\n    return 0;\n  }\n\n  bool AddSubCommands() override { return true; }\n};\n\nstd::string TicCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   tic \" << std::endl;\n  return ss.str();\n}\n\nbool TicCommand::AddSubCommands() {\n  if (!add(std::make_unique<TicValidateCommand>())) {\n    return false;\n  }\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/files/tic.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless required  by  applicable  law  or agreed to  in writing,     */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FILES_TIC_H\n#define INCLUDED_WWIVUTIL_FILES_TIC_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil::files {\n\nclass TicCommand final: public UtilCommand {\npublic:\n  TicCommand() : UtilCommand(\"tic\", \"Manipulate TIC files\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n} // namespace wwiv\n\n#endif\n"
  },
  {
    "path": "wwivutil/fix/dirs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivutil/fix/dirs.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datafile.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/vardec.h\"\n#include \"sdk/files/files.h\"\n\n#include <iostream>\n#include <string>\n#include <unordered_set>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::stl;\n\nnamespace wwiv::wwivutil {\n\nnamespace {\nconst char* WWIV_FILE_DATE_FORMAT = \"%m/%d/%y\";\n}\n\nstatic bool ensure_path_exists(const wwiv::sdk::files::directory_t& d, bool dry_run) {\n  if (File::Exists(d.path)) {\n    return true;\n  }\n\n  LOG(INFO) << \"Missing directory for file area: \" << d;\n  LOG(INFO) << \"Path: \" << d.path;\n  if (dry_run) {\n    LOG(INFO) << \"Please create it.\";\n    return false;\n  }\n  LOG(INFO) << \"Creating directory: \" << d.path;\n  return File::mkdirs(d.path);\n}\n\nstd::unordered_set<std::string> CheckDirForDuplicates(sdk::files::FileArea& area, bool dry_run) {\n  std::unordered_set<std::string> files;\n  std::vector<uploadsrec> data;\n  const auto& raw_files = area.raw_files();\n  for (const auto& r : raw_files) {\n    auto [it, added] = files.insert(r.filename);\n    if (added) {\n      data.push_back(r);\n    } else {\n      LOG(INFO) << \"Found duplicate file: \" << r.filename;\n    }\n  }\n  if (data.size() != raw_files.size()) {\n    // We deleted some, time to save.\n    LOG(INFO) << \"Removed \" << std::abs(size_int(data) - size_int(raw_files)) << \" duplicate files\";\n    if (area.set_raw_files(data)) {\n      if (!dry_run) {\n        area.Save();\n      }\n    }\n  }\n  return files;\n}\n\nstatic std::optional<std::unordered_set<std::string>>\nRewriteExtendedDescriptions(const wwiv::sdk::Config& config, const sdk::files::directory_t& dir, sdk::files::FileArea& area,\n                            std::unordered_set<std::string> actual_files, bool dry_run) {\n  VLOG(1) << \"Rewriting extended descriptions for: \" << dir;\n  auto ext_path = area.ext_path();\n\n  if (!File::Exists(ext_path)) {\n    VLOG(1) << \"No extended descriptions for: \" << dir;\n    return std::nullopt;\n  }\n  auto tmp_path{ext_path};\n  tmp_path.replace_extension(\".tmp\");\n\n  std::unordered_set<std::string> files_with_ext_desc;\n  if (!backup_file(ext_path, config.max_backups())) {\n    LOG(ERROR) << \"Error creating backup of Extended Description file: \" << dir;\n  }\n\n  // move to .TMP\n  if (dry_run) {\n    if (!File::Copy(ext_path, tmp_path)) {\n      LOG(ERROR) << \"Error Copying Extended Description file: \" << dir;\n      return std::nullopt;\n    }\n  } else {\n    if (!File::Move(ext_path, tmp_path)) {\n      LOG(ERROR) << \"Error Moving Extended Description file: \" << dir;\n      return std::nullopt;\n    }\n  }\n\n  File in(tmp_path);\n  if (!in.Open(File::modeReadOnly | File::modeBinary)) {\n    LOG(ERROR) << \"Error Reading Extended Description file: \" << dir;\n    return std::nullopt;\n  }\n  const auto file_size = in.length();\n  if (!file_size) {\n    VLOG(1) << \"Extended description file is empty.\";\n    return std::nullopt;\n  }\n\n  File out(ext_path);\n  if (!dry_run) {\n    if (!out.Open(File::modeReadWrite | File::modeBinary | File::modeCreateFile | File::modeTruncate)) {\n      LOG(ERROR) << \"Error Opening Extended Description file for Write: \" << dir;\n      return std::nullopt;\n    }\n  }\n\n  for (long file_pos = 0; file_pos < file_size; ) {\n    in.Seek(file_pos, File::Whence::begin);\n    ext_desc_type ed{};\n    if (const auto num_read = in.Read(&ed, sizeof(ext_desc_type)); num_read != sizeof(ext_desc_type)) {\n      // LOG ERROR? Return false here?\n      break;\n    }\n    if (contains(actual_files, ed.name)) {\n      // The file exists in the list, so let's write it and then remove\n      // it, so we don't write dupes.\n      actual_files.erase(ed.name);\n      files_with_ext_desc.insert(ed.name);\n      if (!dry_run) {\n        out.Write(&ed, sizeof(ext_desc_type));\n      }\n\n      std::string ss;\n      ss.resize(ed.len);\n      in.Read(&ss[0], ed.len);\n      if (!dry_run) {\n        out.Write(&ss[0], ed.len);\n      }\n    } else {\n      LOG(INFO) << \"Removing file from ext description [does not exist] : \" << ed.name;\n    }\n    file_pos += ed.len + static_cast<int>(sizeof(ext_desc_type));\n  }\n  return {files_with_ext_desc};\n}\n\nstatic uint32_t file_size(const std::filesystem::path& path) {\n  const File f(path);\n  return static_cast<uint32_t>(f.length());\n}\n\nstatic bool CheckAttributes(const wwiv::sdk::files::directory_t& dir, sdk::files::FileArea& area,\n  const std::unordered_set<std::string>& files_with_ext_desc, bool dry_run) {\n  const auto nf = area.number_of_files();\n  auto area_dirty{false};\n  for (auto i = 1; i < nf; i++) {\n    auto dirty{false};\n    auto f = area.ReadFile(i);\n    if (const auto actual_extended = contains(files_with_ext_desc, f.aligned_filename()); actual_extended != f.has_extended_description()) {\n      dirty = true;\n      LOG(INFO) << \"Fixing ext desc mask on: \" << f.filename();\n      f.set_extended_description(actual_extended);\n    }\n    const auto path = FilePath(dir.path, f);\n    const auto actual_size = wwiv::wwivutil::file_size(path);\n    if (actual_size != f.numbytes()) {\n      dirty = true;\n      LOG(INFO) << \"Fixing file size for: \" << f.filename();\n      f.set_numbytes(actual_size);\n    }\n    auto actual_dt = DateTime::from_time_t(File::last_write_time(path));\n    const auto actual_dts = actual_dt.to_string(WWIV_FILE_DATE_FORMAT);\n    if (!iequals(actual_dts, f.actual_date())) {\n      dirty = true;\n      LOG(INFO) << \"Fixing file actual date for: \" << f.filename() << \"; date: \" << actual_dts;\n      f.set_actual_date(actual_dt);\n    }\n\n    if (dirty && !dry_run) {\n      area_dirty = true;\n      if (!area.UpdateFile(f, i)) {\n        LOG(ERROR) << \"Error Updating file: \" << f.filename();\n      }\n    }\n  }\n\n  if (area_dirty && !dry_run) {\n    return area.Save();\n  }\n  return true;\n}\n\nbool CheckExtendedDirAndAttributes(const wwiv::sdk::Config& config, const sdk::files::directory_t& dir, sdk::files::FileArea& area, bool dry_run) {\n  const auto actual_files = CheckDirForDuplicates(area, dry_run);\n  std::unordered_set<std::string> empty_set;\n  const auto files_with_ext_desc =\n      RewriteExtendedDescriptions(config, dir, area, actual_files, dry_run).value_or(empty_set);\n  // Reload areas since duplicates could have been removed.\n  area.Close();\n  area.Load();\n  return CheckAttributes(dir, area, files_with_ext_desc, dry_run);\n}\n\nstatic void checkFileAreas(const wwiv::sdk::Config& config, bool /* verbose */, bool dry_run) {\n  const auto datadir = config.datadir();\n  sdk::files::Dirs dirs(datadir, config.max_backups());\n  if (!dirs.Load()) {\n    LOG(ERROR) << \"Unble to load dirs.dat\";\n    return;\n  }\n  sdk::files::FileApi api(datadir);\n  const auto& directories = dirs.dirs();\n\n  LOG(INFO) << \"Checking \" << directories.size() << \" directories.\";\n  for (const auto& d : directories) {\n    if (d.mask & mask_cdrom) {\n      LOG(INFO) << \"Skipping directory '\" << d.name << \"' [CD-ROM]\";\n      continue;\n    }\n    if (d.mask & mask_offline) {\n      LOG(INFO) << \"Skipping directory '\" << d.name << \"' [OFFLINE]\";\n      continue;\n    }\n    if (!ensure_path_exists(d, dry_run)) {\n      continue;\n    }\n    if (d.conf.empty()) {\n      LOG(WARNING) << \"** PLEASE FIX: Dir: \" << d.filename << \" is not part of any conference.\";\n    }\n    auto area = api.Open(d);\n    if (!area) {\n      LOG(ERROR) << \"Unable to open file area: \" << d;\n      continue;\n    }\n    if (!area->FixFileHeader()) {\n      LOG(ERROR) << \"Error fixing file header\";\n    }\n    if (!CheckExtendedDirAndAttributes(config, d, *area, dry_run)) {\n      LOG(ERROR) <<\"Failed to fix directory: \" << d;\n    }\n  }\n}\n\nstd::string FixDirectoriesCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss<< \"Usage:   fix dirs\" << std::endl;\n  ss << \"Example: WWIVUTIL fix dirs\" << std::endl;\n  return ss.str();\n}\n\nbool FixDirectoriesCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument(\"verbose\", 'v', \"Enable verbose output.\", false));\n  add_argument(BooleanCommandLineArgument(\"dry_run\", 'x', \"Enable dry run mode (report errors, do not fix).\", false));\n\n  return true;\n}\n\nint FixDirectoriesCommand::Execute() {\n  std::cout << \"Runnning FixDirectoriesCommand::Execute\" << std::endl;\n\n  CHECK(config()->config());\n  checkFileAreas(*config()->config(), verbose(), dry_run());\n  return 0;\n}\n\nbool FixDirectoriesCommand::verbose() const {\n  return arg(\"verbose\").as_bool();\n}\n\nbool FixDirectoriesCommand::dry_run() const {\n  return arg(\"dry_run\").as_bool();\n}\n\n} // namespace wwiv\n\n"
  },
  {
    "path": "wwivutil/fix/dirs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FIX_DIRS_H\n#define INCLUDED_WWIVUTIL_FIX_DIRS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass FixDirectoriesCommand final: public UtilCommand {\npublic:\n  FixDirectoriesCommand()\n    : UtilCommand(\"dirs\", \"Fix File Directories.\") {}\n  int Execute() override;\n  [[nodiscard]] bool verbose() const;\n  [[nodiscard]] bool dry_run() const;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/fix/fix.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/fix/fix.h\"\n\n#include \"core/command_line.h\"\n#include \"sdk/config.h\"\n#include \"wwivutil/fix/dirs.h\"\n#include \"wwivutil/fix/users.h\"\n\n#include <memory>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivutil {\n\nbool FixCommand::AddSubCommands() {\n  add(std::make_unique<FixUsersCommand>());\n  add(std::make_unique<FixDirectoriesCommand>());\n\n  return true;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/fix/fix.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FIX_FIX_H\n#define INCLUDED_WWIVUTIL_FIX_FIX_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass FixCommand final: public UtilCommand {\npublic:\n  FixCommand(): UtilCommand(\"fix\", \"WWIV fix commands.\") {}\n  ~FixCommand() = default;\n  bool AddSubCommands() override final;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/fix/users.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivutil/fix/users.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"core/version.h\"\n#include \"fmt/printf.h\"\n#include \"sdk/filenames.h\"\n#include \"sdk/user.h\"\n#include \"sdk/usermanager.h\"\n#include <algorithm>\n#include <set>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nnamespace {\nstatusrec_t st;\n}\n\nstatic char* dateFromTimeT(time_t t) {\n  static char date_string[11];\n  const auto ds = DateTime::from_time_t(t).to_string(\"%m/%d/%y\");\n  to_char_array(date_string, ds);\n  return date_string;\n}\n\nstatic std::string dateFromTimeTForLog(time_t t) {\n  const auto dt = DateTime::from_time_t(t);\n  return dt.to_string(\"%y%m%d\");\n}\n\nstatic bool checkFileSize(File& file, unsigned long len) {\n  if (!file.IsOpen()) {\n    file.Open(File::modeReadOnly | File::modeBinary);\n  }\n  const unsigned long actual = file.length();\n  file.Close();\n  if (actual < len) {\n    LOG(INFO) << file << \" too short (\" << actual << \"<\" << len << \").\";\n    return false;\n  }\n  if (actual > len) {\n    LOG(INFO) << file << \" too long (\" << actual << \">\" << len << \").\";\n    LOG(INFO) << \"Attempting to continue.\";\n  }\n  return true;\n}\n\nstatic void saveStatus(const std::filesystem::path& datadir) {\n  File statusDat(FilePath(datadir, STATUS_DAT));\n\n  statusDat.Open(File::modeReadWrite | File::modeBinary);\n  statusDat.Write(&st, sizeof(statusrec_t));\n  statusDat.Close();\n}\n\nstatic bool initStatusDat(const std::filesystem::path& datadir) {\n  const auto nFileMode = File::modeReadOnly | File::modeBinary;\n  auto update = false;\n  const auto status_fn = FilePath(datadir, STATUS_DAT);\n  if (!File::Exists(status_fn)) {\n    LOG(INFO) << status_fn << \" NOT FOUND!\";\n    LOG(INFO) << \"Recreating \" << status_fn;\n    memset(&st, 0, sizeof(statusrec_t));\n    to_char_array(st.date1, \"00/00/00\");\n    to_char_array(st.date2, st.date1);\n    to_char_array(st.date3, st.date1);\n    to_char_array(st.log1, \"000000.log\");\n    to_char_array(st.log2, \"000000.log\");\n    to_char_array(st.gfiledate, \"00/00/00\");\n    st.callernum = 65535;\n    st.wwiv_version = wwiv_config_version();\n    update = true;\n  } else {\n    File statusDat(status_fn);\n    checkFileSize(statusDat, sizeof(statusrec_t));\n    LOG(INFO) << \"Reading \" << statusDat << \"...\";\n    if (!statusDat.Open(nFileMode)) {\n      LOG(INFO) << statusDat << \" NOT FOUND.\";\n      return false;\n    }\n    statusDat.Read(&st, sizeof(statusrec_t));\n    statusDat.Close();\n\n    // version check\n    if (st.wwiv_version > wwiv_config_version()) {\n      LOG(INFO) << \"Incorrect version of fix (this is for \" << wwiv_config_version() << \", you need \"\n                << st.wwiv_version << \")\";\n    }\n\n    const auto dt = DateTime::now();\n    auto val = dt.to_time_t();\n    auto* cur_date = dateFromTimeT(val);\n    VLOG(1) << \"st.date1: \" << st.date1 << \"; expected: \" << cur_date\n            << \"; equals: \" << std::boolalpha << iequals(cur_date, st.date1);\n    if (!iequals(st.date1, cur_date)) {\n      to_char_array(st.date1, cur_date);\n      update = true;\n      LOG(INFO) << \"Date error in STATUS.DAT (st.date1) corrected\";\n      LOG(INFO) << \"was: \" << st.date1 << \"; expected: \" << cur_date;\n    }\n\n    val -= 86400L;\n    cur_date = dateFromTimeT(val);\n    VLOG(1) << \"st.date2: \" << st.date2 << \"; expected: \" << cur_date\n            << \"; equals: \" << std::boolalpha << iequals(cur_date, st.date2);\n    if (!iequals(st.date2, cur_date)) {\n      strcpy(st.date2, cur_date);\n      update = true;\n      LOG(INFO) << \"Date error in STATUS.DAT (st.date2) corrected\";\n      LOG(INFO) << \"was: \" << st.date2 << \"; expected: \" << cur_date;\n    }\n    auto log_file = StrCat(dateFromTimeTForLog(val), \".log\");\n    VLOG(1) << \"st.log1: \" << st.log1 << \"; expected: \" << log_file\n            << \"; equals: \" << std::boolalpha << iequals(log_file, st.log1);\n    if (!iequals(log_file, st.log1)) {\n      to_char_array(st.log1, log_file);\n      update = true;\n      LOG(INFO) << \"Log filename error in STATUS.DAT (st.log1) corrected\";\n      LOG(INFO) << \"was: \" << st.log1 << \"; expected: \" << log_file;\n    }\n\n    val -= 86400L;\n    cur_date = dateFromTimeT(val);\n    VLOG(1) << \"st.date3: \" << st.date3 << \"; expected: \" << cur_date\n            << \"; equals: \" << std::boolalpha << iequals(cur_date, st.date3);\n    if (!iequals(st.date3, cur_date)) {\n      strcpy(st.date3, cur_date);\n      update = true;\n      LOG(INFO) << \"Date error in STATUS.DAT (st.date3) corrected\";\n    }\n    log_file = StrCat(dateFromTimeTForLog(val), \".log\");\n    if (!iequals(log_file, st.log2)) {\n      to_char_array(st.log2, log_file);\n      update = true;\n      LOG(INFO) << \"Log filename error in STATUS.DAT (st.log2) corrected\";\n    }\n  }\n  if (update) {\n    saveStatus(datadir);\n  }\n  return true;\n}\n\nbool FixUsersCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument(\"exp\", 'x', \"Enable experimental features.\", false));\n  add_argument(BooleanCommandLineArgument(\"verbose\", 'v', \"Enable verbose output.\", false));\n\n  return true;\n}\n\nstd::string FixUsersCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   fix users\";\n  ss << \"Example: WWIVutil fix users\";\n  return ss.str();\n}\n\nint FixUsersCommand::Execute() {\n  initStatusDat(config()->config()->datadir());\n  const auto user_fn = FilePath(config()->config()->datadir(), USER_LST);\n  if (!File::Exists(user_fn)) {\n    LOG(ERROR) << user_fn << \" does not exist.\";\n    return 1;\n  }\n\n  UserManager userMgr(*config()->config());\n  LOG(INFO) << \"Checking USER.LST... found \" << userMgr.num_user_records() << \" user records.\";\n  LOG(INFO) << \"TBD: Check for trashed user records.\";\n  if (userMgr.num_user_records() > config()->config()->max_users()) {\n    LOG(INFO) << \"Might be too many.\";\n    if (!arg(\"exp\").as_bool()) {\n      return 1;\n    }\n  } else {\n    LOG(INFO) << \"Reasonable number.\";\n  }\n\n  std::vector<smalrec> smallrecords;\n  std::set<std::string> names;\n\n  const auto num_user_records = userMgr.num_user_records();\n  for (auto i = 1; i <= num_user_records; i++) {\n    User user;\n    userMgr.readuser(&user, i);\n    user.FixUp();\n    userMgr.writeuser(&user, i);\n    if (!user.deleted() && !user.inactive()) {\n      smalrec sr{};\n      const auto name = user.name();\n      strcpy(reinterpret_cast<char*>(sr.name), name.c_str());\n      sr.number = static_cast<uint16_t>(i);\n      if (names.find(name) == names.end()) {\n        smallrecords.push_back(sr);\n        names.insert(name);\n        if (arg(\"verbose\").as_bool()) {\n          LOG(INFO) << \"Keeping user: \" << sr.name << \" #\" << sr.number;\n        }\n      } else {\n        LOG(INFO) << \"[skipping duplicate user: \" << name << \" #\" << sr.number << \"]\";\n      }\n    }\n  }\n\n  std::sort(smallrecords.begin(), smallrecords.end(),\n            [](const smalrec& a, const smalrec& b) -> bool {\n              const auto equal = strcmp((char*)a.name, (char*)b.name);\n\n              // Sort by user number if names match.\n              if (equal == 0) {\n                return a.number < b.number;\n              }\n\n              // Otherwise sort by name comparison.\n              return equal < 0;\n            });\n\n  fmt::print(\"size={} {}\\n\", smallrecords.size(), sizeof(smalrec) * smallrecords.size());\n  LOG(INFO) << \"Checking NAMES.LST\";\n  const auto name_fn = FilePath(config()->config()->datadir(), NAMES_LST);\n  if (!File::Exists(name_fn)) {\n    LOG(INFO) << name_fn << \" does not exist, regenerating with \" << smallrecords.size()\n              << \" names\";\n    File nameFile(name_fn);\n    nameFile.Open(File::modeCreateFile | File::modeBinary | File::modeWriteOnly);\n    nameFile.Write(&smallrecords[0], sizeof(smalrec) * smallrecords.size());\n    nameFile.Close();\n  } else {\n    File nameFile(name_fn);\n    if (nameFile.Open(File::modeReadOnly | File::modeBinary)) {\n      const auto size = nameFile.length();\n      const auto recs = static_cast<uint16_t>(size / sizeof(smalrec));\n      if (recs != st.users) {\n        LOG(INFO) << \"STATUS.DAT contained an incorrect user count.\";\n        LOG(INFO) << \"status.users: \" << st.users << \"; expected from user.lst: \" << recs;\n        st.users = recs;\n        saveStatus(config()->config()->datadir());\n      } else {\n        LOG(INFO) << \"STATUS.DAT matches expected user count of \" << st.users << \" users.\";\n      }\n    }\n    nameFile.Close();\n  }\n  return 0;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/fix/users.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_FIX_USERS_H\n#define INCLUDED_WWIVUTIL_FIX_USERS_H\n\n#include \"core/command_line.h\"\n#include \"wwivutil/command.h\"\n\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass FixUsersCommand final: public UtilCommand {\npublic:\n  FixUsersCommand()\n    : UtilCommand(\"users\", \"Fix users.\") {}\n  [[nodiscard]] std::string GetUsage() const override final;\n  int Execute() override final;\n  bool AddSubCommands() override final;\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/help.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/help.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include <iomanip>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nHelpCommand::HelpCommand()\n  : UtilCommand(\"help\", \"Displays help on wwivutil and commands.\") {\n}\n\n[[nodiscard]] std::string HelpCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage: \" << std::endl << std::endl;\n  ss << \"  help : Displays WWIVutil help.\" << std::endl << std::endl;\n  return ss.str();\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nstd::string HelpCommand::LongHelpForArg(const core::CommandLineArgument& c, int max_len) {\n  const auto md = markdown();\n  std::ostringstream ss;\n  if (md) {\n    ss << \"| \";\n  }\n  if (c.key_ != 0) {\n    ss << \"-\" << c.key_ << \" \";\n  } else {\n    ss << \"   \";\n  }\n  ss << \"--\";\n  if (!md) {\n    ss << std::left << std::setw(max_len);\n  }\n  ss << c.name_ << \"  \";\n  if (md) {\n    ss << \" | \";\n  }\n  if (c.is_boolean) {\n    ss << \"[boolean] \";\n  }\n  ss << c.help_text() << std::endl;\n  return ss.str();\n}\n\nstd::string HelpCommand::HelpForCommand(const CommandLineCommand& c,\n    const std::string& cmdpath) {\n  if (barg(\"full\") || markdown()) {\n    return FullHelpForCommand(c, cmdpath);\n  }\n  return ShortHelpForCommand(c, cmdpath);\n}\n\n\nstd::string HelpCommand::FullHelpForCommand(const CommandLineCommand& uc,\n                                            const std::string& cmdpath) {\n  std::ostringstream ss;\n  const auto md = markdown();\n  if (md) {\n    ss << \"## \";\n  }\n  ss << cmdpath << std::endl << std::endl;\n  ss << uc.help_text() << std::endl << std::endl;\n  if (!uc.args_allowed().empty()) {\n    if (md) {\n      ss << std::endl;\n      ss << \"| Arg     | Description |\" << std::endl;\n      ss << \"| ------- | ----------- |\" << std::endl;\n    } else {\n      ss << \"Args:\" << std::endl;\n    }\n    for (const auto& [_, c] : uc.args_allowed()) {\n      ss << LongHelpForArg(c, 15);\n    }\n    if (md) {\n      ss << \"\\r\\n<br/>\\r\\n\";\n    }\n  }\n  ss << std::endl;\n  ss << std::endl;\n  if (!uc.commands_allowed().empty()) {\n    for (const auto& [_, c] : uc.commands_allowed()) {\n      auto full_command_name = fmt::format(\"{} {}\", cmdpath, c->name());\n      ss << FullHelpForCommand(*c, full_command_name);\n      ss << std::endl;\n    }\n  }\n  return ss.str();\n}\n\n// ReSharper disable once CppMemberFunctionMayBeStatic\nstd::string HelpCommand::ShortHelpForCommand(const CommandLineCommand& c,\n                                             const std::string& cmdpath) {\n  std::ostringstream ss;\n  ss << cmdpath << std::endl;\n  ss << c.GetUsage() << std::endl;\n  ss << c.GetHelp() << std::endl;\n  return ss.str();\n}\n\nbool HelpCommand::ShowHelpForPath(std::vector<std::string> path, const core::CommandLineCommand* c) {\n  const auto e = std::end(path);\n  if (path.empty()) {\n    return false;\n  }\n  auto cmdpath = fmt::format(\"wwivutil {}\", path.front());\n  for (auto b = std::begin(path) + 1; b != e; ++b) {\n    if (const auto it = c->commands_allowed().find(ToStringLowerCase(*b));\n        it != std::end(c->commands_allowed())) {\n      cmdpath += \" \";\n      cmdpath += it->first;\n      c = it->second.get();\n    }\n  }\n\n  std::cout << HelpForCommand(*c, cmdpath);\n  std::cout << std::endl << std::endl;\n  return true;\n}\n\nint HelpCommand::Execute() {\n  // note that our docs is generated by running the following command:\n  // wwivutil help  --format=markdown > wwivutil.md\n  if (markdown()) {\n    std::cout << R\"(\n# WWIVutil Help\n\nWWIVutil is WWIV's Swiss Army Knife utilty program.  It handles many different\ntypes of commands for WWIV.  It's also replaces the 4.x FIX command.\n\nHere's documentation for the various commands.\n\n\n## Table of Contents\n\n[TOC]\n\n\n)\";\n  } else {\n    std::cout << \"WWIVutil Help\" << std::endl;\n    std::cout << std::endl;\n  }\n\n  if (!remaining().empty()) {\n    // We have a command:\n    const auto& cmdname = remaining().front();\n    for (const CommandLineCommand* c : config()->subcommands()) {\n      if (iequals(cmdname, c->name())) {\n        // Should we walk?\n        if (ShowHelpForPath(remaining(), c)) {\n          return 0;\n        }\n      }\n    }\n  }\n\n  // no command name found, displaying help for everything.\n  for (const auto* c : config()->subcommands()) {\n    const auto cmdpath = fmt::format(\"wwivutil {}\", c->name());\n    std::cout << HelpForCommand(*c, cmdpath);\n    std::cout << std::endl << std::endl;\n  }\n  return 0;\n}\n\nbool HelpCommand::markdown() const {\n  return iequals(sarg(\"format\"), \"markdown\");\n}\n\nbool HelpCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument(\"full\", \"Display long format for help.\", false));\n  // TODO: implement format.\n  add_argument({\"format\", \"The format of the help to use (text | markdown)\", \"text\"});\n  return true;\n}\n\n} // namespace wwiv::wwivutil\n"
  },
  {
    "path": "wwivutil/help.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_HELP_H\n#define INCLUDED_WWIVUTIL_HELP_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass HelpCommand final : public UtilCommand {\npublic:\n  HelpCommand();\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n  int Execute() override;\n\nprivate:\n  [[nodiscard]] bool markdown() const;\n  bool ShowHelpForPath(std::vector<std::string> path, const core::CommandLineCommand* c);\n  [[nodiscard]] std::string LongHelpForArg(const core::CommandLineArgument& c,\n                                                     int max_len);\n\n  [[nodiscard]] std::string HelpForCommand(const CommandLineCommand& uc,\n                                           const std::string& command_base);\n  [[nodiscard]] std::string FullHelpForCommand(const CommandLineCommand& uc,\n                                           const std::string& cmdpath);\n  [[nodiscard]] std::string ShortHelpForCommand(const core::CommandLineCommand& c,\n                                           const std::string& cmdpath);\n\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/instance/instance.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/instance.h\"\n#include \"wwivutil/instance/instance.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n\n#include <iostream>\n#include <memory>\n#include <string>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\n/* Instance status flags */\nconstexpr int INST_FLAGS_NONE = 0x0000;  // No flags at all\nconstexpr int INST_FLAGS_ONLINE = 0x0001;  // User online\nconstexpr int INST_FLAGS_MSG_AVAIL = 0x0002;  // Available for inst messages\nconstexpr int INST_FLAGS_INVIS = 0x0004;  // For invisibility\n\n\nclass InstanceDumpCommand final : public UtilCommand {\npublic:\n  InstanceDumpCommand(): UtilCommand(\"dump\", \"Displays WWIV instance information.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  dump : Displays instance information.\" << std::endl << std::endl;\n    return ss.str();\n  }\n\n  [[nodiscard]] static std::string flags_to_string(uint16_t flags) {\n    std::ostringstream ss;\n    if (flags & INST_FLAGS_ONLINE) {\n      ss << \"[online] \";\n    }\n    if (flags & INST_FLAGS_MSG_AVAIL) {\n      ss << \"[msg avail] \";\n    }\n    if (flags & INST_FLAGS_INVIS) {\n      ss << \"[invisible] \";\n    }\n    return ss.str();\n  }\n\n  int Execute() override {\n    Instances instances(*config()->config());\n    if (!instances) {\n      std::cout << \"Unable to read Instance information.\";\n      return 1;\n    }\n    const auto num = instances.size();\n    std::cout << \"num instances:  \" << num << std::endl;\n    for (const auto& instance : instances) {\n      std::cout << \"=======================================================================\" << std::endl;\n      std::cout << \"Instance    : #\" << instance.node_number() << std::endl;\n      std::cout << \"User        : #\" << instance.user_number() << std::endl;\n      std::cout << \"Location    : \" << instance.location_description() << std::endl;\n      std::cout << \"SubLoc      : \" << instance.subloc_code() << std::endl;\n      std::cout << \"Flags       : \" << flags_to_string(instance.ir().flags) << std::endl;\n      std::cout << \"Modem Speed : \" << instance.modem_speed() << std::endl;\n      std::cout << \"Started     : \" << instance.started().to_string() << std::endl;\n      std::cout << \"Updated     : \" << instance.updated().to_string() << std::endl;\n    }\n    std::cout << \"=======================================================================\" << std::endl;\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    return true;\n  }\n\n};\n\nbool InstanceCommand::AddSubCommands() {\n  add(std::make_unique<InstanceDumpCommand>());\n  return true;\n}\n\n\n}  // namespace\n"
  },
  {
    "path": "wwivutil/instance/instance.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_INSTANCE_INSTANCE_H\n#define INCLUDED_WWIVUTIL_INSTANCE_INSTANCE_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass InstanceCommand final: public UtilCommand {\npublic:\n  InstanceCommand(): UtilCommand(\"instance\", \"WWIV status commands.\") {}\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/menus/menus.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/menus/menus.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/menus/menu.h\"\n#include \"wwivutil/util.h\"\n\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n#include \"sdk/menus/menu_set.h\"\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::menus;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil {\n\nstatic void DisplayMenu(const menus::Menu56& m5) {\n  std::cout << \"Title: \" << m5.menu.title;\n  for (const auto& item : m5.menu.items) {\n    std::cout << item.item_key << \") '\" << item.item_text << \"' \";\n    for (const auto& a : item.actions) {\n      std::cout << \"[\" << a.cmd;\n      if (!a.data.empty()) {\n        std::cout << \" {\" << a.data << \"}\";\n      }\n      std::cout << \"] \";\n    }\n    std::cout << std::endl;\n  }\n}\n\nclass MenusDumpCommand final : public UtilCommand {\npublic:\n  MenusDumpCommand() : UtilCommand(\"dump\", \"Displays the info of a menu\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   dump --menu_set=[menu set] <menu name>\" << std::endl;\n    ss << \"Example: dump --menu_set=wwiv main.mnu\" << std::endl << std::endl;\n    ss << \"         Note that menu_set defaults to 'wwiv'\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    const auto menu_set = sarg(\"menu_set\");\n    if (menu_set.empty()) {\n      std::cout << \"--menu_set is missing. \" << std::endl;\n      std::cout << GetUsage();\n      return 2;\n    }\n\n    if (remaining().empty()) {\n      std::cout << \"<menu name> is missing. \" << std::endl;\n      std::cout << GetUsage();\n      return 2;\n    }\n    const auto& menu_name = remaining().front();\n    MenuSet56 menuset(FilePath(config()->config()->menudir(), menu_set));\n\n    const menus::Menu56 m5(config()->config()->menudir(), menuset, menu_name);\n    if (!m5.initialized()) {\n      std::cout << \"Unable to parse menu.\" << std::endl;\n      return 1;\n    }\n\n    DisplayMenu(m5);\n\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument(\"full\", \"Display full info about every command.\", false));\n    add_argument({\"menu_set\", \"The menuset to use\", \"wwiv\"});\n    return true;\n  }\n};\n\nclass MenusConvertCommand final : public UtilCommand {\npublic:\n  MenusConvertCommand() : UtilCommand(\"convert\", \"Converts a 4.3x menu to 5.6 format\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   convert --menu_set=<menu set> <menu name>\" << std::endl;\n    ss << \"Example: convert --menu_set=wwiv main\" << std::endl;\n    ss << \"         Note that menu_set defaults to 'wwiv'\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    const auto menu_set = sarg(\"menu_set\");\n    if (menu_set.empty()) {\n      std::cout << \"--menu_set is missing. \" << std::endl;\n      std::cout << GetUsage();\n      return 2;\n    }\n\n    if (remaining().empty()) {\n      std::cout << \"<menu name> is missing. \" << std::endl;\n      std::cout << GetUsage();\n      return 2;\n    }\n    const auto& menu_name = remaining().front();\n    const menus::Menu430 m4(config()->config()->menudir(), menu_set, menu_name);\n    if (!m4.initialized()) {\n      std::cout << \"Unable to 4.3 parse menu.\" << std::endl;\n      return 1;\n    }\n\n    if (auto om5 = Create56MenuFrom43(m4, config()->config()->max_backups())) {\n      auto& m5 = om5.value();\n      return m5.Save() ? 0 : 1;\n    }\n    std::cout << \"Failed to create 5.6 style menu from 4.3x style menu.\";\n    return 1;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"menu_set\", \"The menuset to use\", \"wwiv\"});\n    return true;\n  }\n};\n\nbool MenusCommand::AddSubCommands() {\n  if (!add(std::make_unique<MenusDumpCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<MenusConvertCommand>())) {\n    return false;\n  }\n\n  \n  \n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/menus/menus.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_MENUS_MENUS_H\n#define INCLUDED_WWIVUTIL_MENUS_MENUS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass MenusCommand final : public UtilCommand {\npublic:\n  MenusCommand(): UtilCommand(\"menus\", \"WWIV menu commands.\") {}\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/messages/messages.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/messages/messages.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/config.h\"\n#include \"sdk/names.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/msgapi/msgapi.h\"\n#include \"sdk/net/networks.h\"\n#include \"wwivutil/util.h\"\n\n#include <ctime>\n#include <iomanip>\n#include <iostream>\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil {\n\nstatic subboard_t default_sub(const std::string& fn) {\n  subboard_t sub{};\n  sub.storage_type = 2;\n  sub.filename = fn;\n  return sub;\n}\n\n// N.B(rushfan): This is similar to the one in post.cpp.  But that one uses\n// network number and network name as key and not filename for sub file.\nstatic std::optional<subboard_t> find_sub(const wwiv::sdk::Subs& subs, const std::string& filename) {\n  for (const auto& x : subs.subs()) {\n    if (iequals(filename, x.filename)) {\n      return {x};\n    }\n  }\n  return std::nullopt;\n}\n\nbool BaseMessagesSubCommand::CreateMessageApiMap(const std::string& basename) {\n  const auto& datadir = config()->config()->datadir();\n  const auto& nets = config()->networks().networks();\n\n  subs_ = std::make_unique<Subs>(datadir, nets, config()->config()->max_backups());\n  if (!subs_->Load()) {\n    LOG(ERROR) << \"Unable to open subs. \";\n    return false;\n  }\n  if (!subs_->exists(basename)) {\n    LOG(ERROR) << \"No sub exists with filename: \" << basename;\n    return false;\n  }\n\n  const MessageApiOptions options;\n  auto* x = new NullLastReadImpl();\n  sub_ = find_sub(*subs_, basename).value_or(default_sub(basename));\n\n  apis_[sub_.storage_type] = std::make_unique<WWIVMessageApi>(options, *config()->config(),\n                                                            config()->networks().networks(), x);\n\n  if (!stl::contains(apis_, 2)) {\n    // We always want to add type 2 \n    apis_[2] = std::make_unique<WWIVMessageApi>(options, *config()->config(),\n                                                config()->networks().networks(), x);\n  }\n\n  // We try to open or create the sub later.\n\n  //if (!apis_[sub_.storage_type]->Exist(sub_)) {\n  //  clog << \"Message area: '\" << sub_.filename << \"' does not exist.\" << std::endl;\n  //  return false;\n  //}\n  return true;\n}\n\nclass DeleteMessageCommand final : public BaseMessagesSubCommand {\npublic:\n  DeleteMessageCommand()\n      : BaseMessagesSubCommand(\"delete\", \"Deletes message number specified by '--num'.\") {}\n\n  ~DeleteMessageCommand() override = default;\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   delete --num=NN <base sub filename>\" << std::endl;\n    ss << \"Example: delete --num=10 general\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (remaining().empty()) {\n      std::clog << \"Missing sub basename.\" << std::endl;\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n\n    const auto basename(remaining().front());\n    if (!CreateMessageApiMap(basename)) {\n      std::clog << \"Error Creating message apis.\" << std::endl;\n      return 1;\n    }\n    \n    auto area(api().CreateOrOpen(sub(), -1));\n    if (!area) {\n      std::clog << \"Unable to Open message area: '\" << sub().filename << \"'.\" << std::endl;\n      return 1;\n    }\n\n    const auto num_messages = area->number_of_messages();\n    const auto message_number = arg(\"num\").as_int();\n    std::cout << \"Message Sub: '\" << basename << \"' has \" << num_messages << \" messages.\" << std::endl;\n    std::cout << std::string(72, '-') << std::endl;\n\n    if (message_number < 0 || message_number > num_messages) {\n      LOG(ERROR) << \"Invalid message number #\" << message_number;\n      return 1;\n    }\n    \n    if (const auto success = area->DeleteMessage(message_number); !success) {\n      LOG(ERROR) << \"Unable to delete message #\" << message_number << \"; Try packing this sub.\";\n      return 1;\n    }\n\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"num\", \"Message Number to delete.\", \"-1\"});\n    return true;\n  }\n};\n\nclass PostMessageCommand final : public BaseMessagesSubCommand {\npublic:\n  PostMessageCommand() : BaseMessagesSubCommand(\"post\", \"Posts a new message.\") {}\n\n  bool AddSubCommands() override {\n    add_argument({\"title\", \"title of post\", \"\"});\n    add_argument({\"from\", \"user name sending the post\", \"\"});\n    add_argument({\"from_usernum\", \"usernum sending the post\", \"\"});\n    add_argument({\"to\", \"who the post is addressed to\", \"\"});\n    add_argument({\"date\", \"date of post\", \"\"});\n    add_argument({\"in_reply_to\", \"who this post is a reply to\", \"\"});\n    add_argument({\"delete_overflow\",\n                  \"Strategy for deleting excess messages when adding new ones. (none|one|all)\",\n                  \"none\"});\n    add_argument({\"use_re_and_by\",\"use re and by lines\", \"\"});\n\n    return true;\n  }\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   post --title=\\\"Welcome\\\" --from_usernum=1 <base sub filename> <text filename>\"\n       << std::endl;\n    ss << \"Example: post general mymessage.txt\" << std::endl;\n    return ss.str();\n  }\n\n  [[nodiscard]] int Execute() override {\n    if (remaining().size() < 2) {\n      std::clog << \"Missing sub basename.\" << std::endl;\n      std::cout << GetUsage() << GetHelp();\n      return 2;\n    }\n\n    const auto basename(remaining().front());\n    if (!CreateMessageApiMap(basename)) {\n      std::clog << \"Error Creating message apis.\" << std::endl;\n      return 1;\n    }\n    \n    auto area(api().CreateOrOpen(sub_, -1));\n    if (!area) {\n      std::clog << \"Error opening message area: '\" << basename << \"'.\" << std::endl;\n      return 1;\n    }\n\n    const auto& filename = stl::at(remaining(),1);\n    auto from = arg(\"from\").as_string();\n    auto title = arg(\"title\").as_string();\n    auto to = arg(\"to\").as_string();\n    auto daten = DateTime::now();\n    if (auto date_str = arg(\"date\").as_string(); !date_str.empty()) {\n      std::istringstream ss(date_str);\n      std::tm dt = {};\n      ss >> std::get_time(&dt, \"Www Mmm dd hh:mm:ss yyyy\");\n      if (!ss.fail()) {\n        daten = DateTime::from_time_t(mktime(&dt));\n      }\n    }\n    auto in_reply_to = arg(\"in_reply_to\").as_string();\n    auto from_usernum = arg(\"from_usernum\").as_int();\n    if (from_usernum >= 1 && from.empty()) {\n      Names names(*config()->config());\n      from = names.UserName(from_usernum);\n    }\n\n    TextFile text_file(filename, \"r\");\n    auto raw_text = text_file.ReadFileIntoString();\n    auto lines = SplitString(raw_text, \"\\n\", false);\n\n    auto msg = area->CreateMessage();\n    auto& header = msg.header();\n    header.set_from_system(0);\n    header.set_from_usernum(static_cast<uint16_t>(from_usernum));\n    header.set_title(title);\n    header.set_from(from);\n    header.set_to(to);\n    header.set_daten(daten.to_daten_t());\n    header.set_in_reply_to(in_reply_to);\n    msg.set_text(JoinStrings(lines, \"\\r\\n\"));\n\n    MessageAreaOptions area_options{};\n    area_options.send_post_to_network = true;\n    area_options.add_re_and_by_line = arg(\"use_re_and_by\").as_bool();\n    return area->AddMessage(msg, area_options) ? 0 : 1;\n  }\n};\n\nclass PackMessageCommand final : public BaseMessagesSubCommand {\npublic:\n  PackMessageCommand() : BaseMessagesSubCommand(\"pack\", \"Packs a WWIV type-2 message area.\") {}\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument{\"backup\", \"make a backup of the subs\", true});\n    add_argument({\"delete_overflow\",\n                  \"Strategy for deleting excess messages when adding new ones. (none|one|all)\",\n                  \"none\"});\n    return true;\n  }\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   pack <base sub filename>\" << std::endl;\n    ss << \"Example: post general\" << std::endl;\n    return ss.str();\n  }\n\n  static bool backup(const Config& config, const std::string& name) {\n    const auto max_backups = config.max_backups();\n    const auto sb = backup_file(FilePath(config.datadir(), StrCat(name, \".sub\")), max_backups);\n    const auto db = backup_file(FilePath(config.msgsdir(), StrCat(name, \".dat\")), max_backups);\n    return sb && db;\n  }\n\n   int Execute() override {\n    if (remaining().empty()) {\n      std::clog << \"Missing sub basename.\" << std::endl;\n      std::cout << GetUsage() << GetHelp();\n      return 2;\n    }\n\n    const auto basename(remaining().front());\n    if (!CreateMessageApiMap(basename)) {\n      std::clog << \"Error Creating message apis.\" << std::endl;\n      return 1;\n    }\n\n    // Ensure we can open it.\n    {\n      try {\n        auto area(api().CreateOrOpen(sub(), -1));\n      } catch (const bad_message_area&) {\n        std::clog << \"Error opening message area: '\" << basename << \"'.\" << std::endl;\n        return 1;\n      }\n    }\n\n    if (barg(\"backup\")) {\n      backup(*config()->config(), basename);\n    }\n\n    auto newsub = sub();\n    newsub.filename = StrCat(basename, \".new\");\n    {\n      auto area(api().Open(sub(), -1));\n      if (!api().Create(newsub, -1)) {\n        std::clog << \"Unable to create new area: \" << newsub.filename;\n        return 1;\n      }\n      auto newarea(api().Open(newsub, -1));\n      const auto total = area->number_of_messages();\n      for (auto i = 1; i <= total; i++) {\n        auto message(area->ReadMessage(i));\n        if (!message) {\n          LOG(ERROR) << \"Unable to load message #\" << i;\n          continue;\n        }\n        if (!newarea->AddMessage(*message, {})) {\n          LOG(ERROR) << \"Error adding message: \" << message->header().title();\n        } else {\n          std::cout << \"[\" << i << \"]\";\n        }\n      }\n    }\n\n    // Copy \"new\" versions back to sub and dat\n    const auto orig_sub_fn = FilePath(config()->config()->datadir(), StrCat(basename, \".sub\"));\n    const auto new_sub_fn =\n        FilePath(config()->config()->datadir(), StrCat(newsub.filename, \".sub\"));\n    File::Remove(orig_sub_fn);\n    if (!File::Rename(new_sub_fn, orig_sub_fn)) {\n      std::clog << \"Unable to move sub\";\n    }\n    const auto orig_dat_fn =\n        FilePath(config()->config()->msgsdir(), StrCat(newsub.filename, \".dat\"));\n    const auto new_dat_fn =\n        FilePath(config()->config()->msgsdir(), StrCat(newsub.filename, \".dat\"));\n    File::Remove(orig_dat_fn);\n    if (!File::Rename(new_dat_fn, orig_dat_fn)) {\n      std::clog << \"Unable to move dat\";\n    }\n\n    return 0;\n  }\n};\n\n\nbool MessagesCommand::AddSubCommands() {\n  if (!add(std::make_unique<MessagesDumpCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<DeleteMessageCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<PostMessageCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<PackMessageCommand>())) {\n    return false;\n  }\n  \n  return true;\n}\n\nMessagesDumpCommand::MessagesDumpCommand()\n    : BaseMessagesSubCommand(\"dump\", \"Displays message header and text information.\") {}\n\nstd::string MessagesDumpCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   dump <base sub filename>\" << std::endl;\n  ss << \"Example: dump general\" << std::endl;\n  return ss.str();\n}\n\nbool MessagesDumpCommand::AddSubCommands() {\n  add_argument({\"start\", \"Starting message number.\", \"1\"});\n  add_argument({\"end\", \"Last message number.\", \"-1\"});\n  add_argument({\"start_date\", \"Date for starting message in format yyyy-mm-dd[ h:m:s].\", \"\"});\n  add_argument({\"end_date\", \"Date for ending message in format yyyy-mm-dd[ h:m:s].\", \"\"});\n  add_argument(BooleanCommandLineArgument(\"all\", \"dumps everything, control lines too\", false));\n\n  return true;\n}\n\n// ReSharper disable once CppMemberFunctionMayBeConst\nint MessagesDumpCommand::ExecuteImpl(MessageArea* area, const std::string& basename, int start, int end,\n                                     bool all) {\n  const auto total = area->number_of_messages();\n  if (start < 1) {\n    start = 1;\n  } else if (start > total) {\n    start = total;\n  }\n  if (end <= 0) {\n    end = total;\n  } else if (end < start) {\n    end = start;\n  } else if (end > total) {\n    end = total;\n  }\n  std::cout << \"Message Sub: '\" << basename << \"' has \" << total << \" messages.\" << std::endl;\n  std::cout << std::string(72, '-') << std::endl;\n  for (auto current = start; current <= end; current++) {\n    const auto message = area->ReadMessage(current);\n    if (!message) {\n      std::cout << \"#\" << current << \"  ERROR \" << std::endl;\n      VLOG(1) << \"Failed to read message number: \" << current;\n      std::cout << std::string(72, '-') << std::endl;\n      continue;\n    }\n    const auto& header = message->header();\n    std::cout << \"#\" << std::setw(5) << std::left << current << \" From: \" << std::setw(20) << header.from()\n         << \"date: \" << daten_to_wwivnet_time(header.daten()) << std::endl\n         << \"title: \" << header.title();\n    if (header.local()) {\n      std::cout << \"[LOCAL]\";\n    }\n    if (header.deleted()) {\n      std::cout << \"[DELETED]\";\n    }\n    if (header.locked()) {\n      std::cout << \"[LOCKED]\";\n    }\n    if (header.private_msg()) {\n      std::cout << \"[PRIVATE]\";\n    }\n    std::cout << std::endl;\n    if (all) {\n      std::cout << \"qscan: \" << header.last_read() << std::endl;\n    }\n    if (header.deleted()) {\n      // Don't try to read the text of deleted messages.\n      continue;\n    }\n    const auto& text = message->text();\n    std::cout << std::string(72, '-') << std::endl;\n    auto lines = wwiv::strings::SplitString(text.string(), \"\\n\", false);\n    for (const auto& line : lines) {\n      if (line.empty()) {\n        continue;\n      }\n      if (line.front() != CD || all) {\n        for (const auto ch : line) {\n          dump_char(std::cout, ch);\n        }\n        std::cout << std::endl;\n      }\n    }\n    std::cout << \"------------------------------------------------------------------------\" << std::endl;\n  }\n  return 0;\n}\n\nint MessagesDumpCommand::Execute() {\n  if (remaining().empty()) {\n    std::clog << \"Missing sub basename.\" << std::endl;\n    std::cout << GetUsage() << GetHelp();\n    return 2;\n  }\n\n  const auto basename(remaining().front());\n  if (!CreateMessageApiMap(basename)) {\n    std::clog << \"Error Creating message apis.\" << std::endl;\n    return 1;\n  }\n    \n  auto start = iarg(\"start\");\n  auto end = iarg(\"end\");\n  const auto start_date = sarg(\"start_date\");\n  const auto end_date = sarg(\"end_date\");\n  const auto all = barg(\"all\");\n\n  auto area(api().Open(sub_, -1));\n  if (!area) {\n    std::clog << \"Error opening message area: '\" << sub().filename << \"'.\" << std::endl;\n    return 1;\n  }\n  area->set_storage_type(sub().storage_type);\n  area->set_max_messages(sub().maxmsgs);\n\n  // If we have dates, update the start and end numbers based\n  // on the dates.\n  const auto last_message = (end >= 0) ? end : area->number_of_messages();\n  if (!start_date.empty()) {\n    const auto start_dt = parse_yyyymmdd_with_optional_hms(start_date).to_daten_t();\n    for (start = 1; start <= last_message; start++) {\n      if (const auto h = area->ReadMessageHeader(start); start_dt < h->daten()) {\n        // We're past the start date, so use last message number.\n        break;\n      }\n    }\n    // Find the closest message to the start date, or leave it -1\n  }\n  if (!end_date.empty()) {\n    const auto end_dt = parse_yyyymmdd_with_optional_hms(end_date).to_daten_t();\n    // Find the closest message to the end date, or leave it -1\n    for (auto i = 1, before_end = 1; i<= last_message; i++) {\n      if (const auto h = area->ReadMessageHeader(i); end_dt < h->daten()) {\n        // We're past the end date, so use last message number.\n        end = before_end;\n        break;\n      }\n      before_end = i;\n    }\n  }\n  VLOG(1) << \"start: \" << start << \"; end: \" << end << std::endl;\n  return ExecuteImpl(area.get(), basename, start, end, all);\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/messages/messages.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_MESSAGES_MESSAGES_H\n#define INCLUDED_WWIVUTIL_MESSAGES_MESSAGES_H\n\n#include \"sdk/subxtr.h\"\n#include \"sdk/msgapi/message_api.h\"\n#include \"wwivutil/command.h\"\n\n#include <memory>\n\nnamespace wwiv::wwivutil {\n\nclass BaseMessagesSubCommand : public UtilCommand {\npublic:\n  BaseMessagesSubCommand(const std::string& name, const std::string& descr)\n      : UtilCommand(name, descr) {}\n  virtual ~BaseMessagesSubCommand() = default;\n  bool CreateMessageApiMap(const std::string& basename);\n  [[nodiscard]] const std::string& basename() const noexcept { return basename_; }\n  [[nodiscard]] const wwiv::sdk::subboard_t& sub() const noexcept { return sub_; }\n  // N.B. if this doesn't exist this message will crash.\n  sdk::msgapi::MessageApi& api() noexcept {\n    return *apis_.at(sub_.storage_type).get();\n  }\n\nprotected:\n  std::map<int, std::unique_ptr<sdk::msgapi::MessageApi>> apis_;\n  std::unique_ptr<sdk::Subs> subs_;\n  sdk::subboard_t sub_;\n\nprivate:\n  std::string basename_;\n};\n\nclass MessagesCommand final : public UtilCommand {\npublic:\n  MessagesCommand(): UtilCommand(\"messages\", \"WWIV message commands.\") {}\n  ~MessagesCommand() override = default;\n  bool AddSubCommands() override;\n};\n\nclass MessagesDumpCommand final: public BaseMessagesSubCommand {\npublic:\n  MessagesDumpCommand();\n  ~MessagesDumpCommand() override = default;\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n\nprotected:\n  int ExecuteImpl(sdk::msgapi::MessageArea* area, const std::string& basename, int start, int end, bool all);\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_bbsdata.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_bbsdata.h\"\n\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/net/networks.h\"\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string DumpBbsDataCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   dump_bbsdata\" << std::endl;\n  ss << \"Example: dump_bbsdata\" << std::endl;\n  return ss.str();\n}\n\nbool DumpBbsDataCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument(\"bbslist\", 'l', \"Parse bbslist.net vs. bbsdata.net\", false));\n\n  return true;\n}\n\nint DumpBbsDataCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  std::map<const std::string, BbsListNet> bbslists;\n  for (const auto& net : networks.networks()) {\n    const auto lower_case_network_name = ToStringLowerCase(net.name);\n    if (barg(\"bbslist\")) {\n      LOG(INFO) << \"Parsing bbslist.net\";\n      bbslists.emplace(lower_case_network_name, BbsListNet::ParseBbsListNet(net.sysnum, net.dir));\n    } else {\n      LOG(INFO) << \"Reading bbsdata.net\";\n      bbslists.emplace(lower_case_network_name, BbsListNet::ReadBbsDataNet(net.dir));\n    }\n  }\n\n  for (const auto& [net_name, b] : bbslists) {\n    std::cout << \"bbsdata.net information: : \" << net_name << std::endl;\n    std::cout << \"===========================================================\" << std::endl;\n    std::cout << b.ToString() << std::endl;\n  }\n\n  return 0;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_bbsdata.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_BBSDATA_H\n#define INCLUDED_WWIVUTIL_DUMP_BBSDATA_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass DumpBbsDataCommand final: public UtilCommand {\npublic:\n  DumpBbsDataCommand()\n    : UtilCommand(\"dump_bbsdata\", \"Dumps parsed representation of BBSDATA.*\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_callout.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_callout.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/callout.h\"\n#include \"sdk/net/networks.h\"\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string DumpCalloutCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   callout\" << std::endl;\n  ss << \"Example: callout\" << std::endl;\n  return ss.str();\n}\n\nint DumpCalloutCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  std::map<const std::string, Callout> callouts;\n  for (const auto& net : networks.networks()) {\n    const auto lnn = ToStringLowerCase(net.name);\n    callouts.emplace(lnn, Callout(net, config()->config()->max_backups()));\n  }\n\n  for (const auto& c : callouts) {\n    std::cout << \"callout.net information: : \" << c.first << std::endl;\n    std::cout << \"===========================================================\" << std::endl;\n    std::cout << c.second.ToString() << std::endl;\n  }\n\n  return 0;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_callout.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_CALLOUT_H\n#define INCLUDED_WWIVUTIL_DUMP_CALLOUT_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass DumpCalloutCommand final: public UtilCommand {\npublic:\n  DumpCalloutCommand()\n    : UtilCommand(\"callout\", \"Dumps parsed representation of callout.net\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override { return true; }\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_connect.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_connect.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/net/connect.h\"\n#include \"sdk/net/networks.h\"\n#include <iostream>\n#include <map>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string DumpConnectCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   connect\" << std::endl;\n  ss << \"Example: connect\" << std::endl;\n  return ss.str();\n}\n\nint DumpConnectCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  std::map<const std::string, Connect> connects;\n  for (const auto& net : networks.networks()) {\n    const auto lnn = ToStringLowerCase(net.name);\n    connects.emplace(lnn, Connect(net.dir));\n  }\n\n  for (const auto& c : connects) {\n    std::cout << \"connect.net information: : \" << c.first << std::endl;\n    std::cout << \"===========================================================\" << std::endl;\n    std::cout << c.second.ToString() << std::endl;\n  }\n\n  return 0;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_connect.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_CONNECT_H\n#define INCLUDED_WWIVUTIL_DUMP_CONNECT_H\n\n#include <string>\n\n#include \"core/command_line.h\"\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass DumpConnectCommand final: public UtilCommand {\npublic:\n  DumpConnectCommand()\n    : UtilCommand(\"connect\", \"Dumps parsed representation of connect.net\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override { return true; }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_contact.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_contact.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/net/contact.h\"\n#include \"sdk/net/networks.h\"\n\n#include <iostream>\n#include <map>\n#include <string>\n#include <vector>\n\nusing wwiv::sdk::Contact;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string DumpContactCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   contact\" << std::endl;\n  ss << \"Example: contact\" << std::endl;\n  return ss.str();\n}\n\nbool DumpContactCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument{\"save\", \"Save/cleanup contact.net in all subs\", false});\n  add_argument(BooleanCommandLineArgument{\"backup\", \"make a backup of the contact.net files\", false});\n  return true;\n}\n\nint DumpContactCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  std::map<const std::string, Contact> contacts;\n  for (const auto& net : networks.networks()) {\n    const auto lower_case_network_name = ToStringLowerCase(net.name);\n    contacts.emplace(lower_case_network_name, Contact(net, false));\n  }\n\n  for (const auto& c : contacts) {\n    std::cout << \"contact.net information: : \" << c.first << std::endl;\n    std::cout << \"===========================================================\" << std::endl;\n    std::cout << c.second.ToString() << std::endl;\n  }\n\n  if (barg(\"save\")) {\n    for (auto& c : contacts) {\n      if (barg(\"backup\")) {\n        backup_file(c.second.path(), config()->config()->max_backups());\n      }\n      c.second.Save();\n    }\n  }\n\n  return 0;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_contact.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_CONTACT_H\n#define INCLUDED_WWIVUTIL_DUMP_CONTACT_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass DumpContactCommand final: public UtilCommand {\npublic:\n  DumpContactCommand()\n    : UtilCommand(\"contact\", \"Dumps parsed representation of contact.net\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_packet.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_packet.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/net/net.h\"\n#include \"sdk/net/packets.h\"\n#include \"wwivutil/util.h\"\n#include <filesystem>\n#include <iomanip>\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing wwiv::core::CommandLineCommand;\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nint dump_file(const std::filesystem::path& filename) {\n  NetMailFile file(filename, true);\n  if (!file) {\n    LOG(ERROR) << \"Unable to open file: \" << filename;\n    return 1;\n  }\n\n  auto current{0};\n  for (auto packet : file) {\n    std::cout << \"Header for Packet Index Number: #\" << std::setw(5) << std::left << current++ << std::endl;\n    std::cout << \"==============================================================================\"\n         << std::endl;\n\n    std::cout << \" destination: \" << packet.nh.touser << \"@\" << packet.nh.tosys << std::endl;\n    std::cout << \"        from: \" << packet.nh.fromuser << \"@\" << packet.nh.fromsys << std::endl;\n    std::cout << \"        type: (\" << main_type_name(packet.nh.main_type);\n    if (packet.nh.main_type == main_type_net_info) {\n      std::cout << \"/\" << net_info_minor_type_name(packet.nh.minor_type);\n    } else if (packet.nh.main_type > 0) {\n      std::cout << \"/\" << packet.nh.minor_type;\n    }\n    std::cout << \")\" << std::endl;\n    std::cout << \"    list_len: \" << packet.nh.list_len << std::endl;\n    std::cout << \"       daten: \" << daten_to_wwivnet_time(packet.nh.daten) << std::endl;\n    std::cout << \"      length: \" << packet.nh.length << std::endl;\n    if (packet.nh.method > 0) {\n      std::cout << \"compression: de\" << packet.nh.method << std::endl;\n    }\n\n    if (packet.nh.list_len > 0) {\n      // read list of addresses.\n      std::cout << \"System List: \";\n      for (const auto item : packet.list) {\n        std::cout << item << \" \";\n      }\n      std::cout << std::endl;\n    }\n    if (packet.nh.length) {\n      std::cout << \"==============================================================================\"\n           << std::endl;\n      std::cout << \"Raw Packet Text:\" << std::endl;\n      std::cout << \"==============================================================================\"\n                << std::endl;\n      for (const auto ch : packet.text()) {\n        dump_char(std::cout, ch);\n      }\n      std::cout << std::endl << std::endl;\n    }\n    std::cout << \"==============================================================================\"\n              << std::endl;\n  }\n  return file.last_read_response() == ReadNetPacketResponse::END_OF_FILE ? 0 : 1;\n}\n\nstd::string DumpPacketCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   dump <filename>\" << std::endl;\n  ss << \"Example: dump s1.net\" << std::endl;\n  return ss.str();\n}\n\nint DumpPacketCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const std::filesystem::path filename(remaining().front());\n  return dump_file(filename);\n}\n\nbool DumpPacketCommand::AddSubCommands() {\n  return true;\n}\n\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_packet.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_DUMP_PACKET_H\n#define INCLUDED_WWIVUTIL_DUMP_PACKET_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass DumpPacketCommand final: public UtilCommand {\npublic:\n  DumpPacketCommand(): UtilCommand(\"dump\", \"Dumps contents of a network packet\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/dump_subscribers.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/dump_subscribers.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/net/subscribers.h\"\n#include <chrono>\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::net {\n\nstatic int dump_file(const std::string& filename) {\n\n  if (!File::Exists(filename)) {\n    LOG(ERROR) << \"subscriber file: '\" << filename << \"' does not exist.\";\n    return 1;\n  }\n\n  const auto start = std::chrono::steady_clock::now();\n  const auto subscribers = ReadSubcriberFile(filename);\n  const auto end = std::chrono::steady_clock::now();\n  if (subscribers.empty()) {\n    LOG(INFO) << \"No Subscribers: \" << filename;\n    return 0;\n  }\n\n  const auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);\n  std::cout << \"Read \" << subscribers.size() << \" in \" << elapsed.count() << \" milliseconds. \"\n       << std::endl;\n  std::cout << \"Read \" << subscribers.size() << \" in \" << elapsed.count() / 1000 << \" seconds. \"\n       << std::endl;\n\n  for (const auto& e : subscribers) {\n    std::cout << \"@\" << e << std::endl;\n  }\n  return 0;\n}\n\nstd::string DumpSubscribersCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   subscribers <subscriber filename>\" << std::endl;\n  ss << \"Example: subscribers net/ftn/nGENCHAT.net\" << std::endl;\n  return ss.str();\n}\n\nint DumpSubscribersCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  const auto filename = remaining().front();\n  return dump_file(filename);\n}\n\nbool DumpSubscribersCommand::AddSubCommands() {\n  return true;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/net/dump_subscribers.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*               Copyright (C)2018-2022, WWIV Software Services           */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_NET_DUMP_SUBSCRIBERS_H\n#define INCLUDED_WWIVUTIL_NET_DUMP_SUBSCRIBERS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil::net {\n\nclass DumpSubscribersCommand final : public UtilCommand {\npublic:\n  DumpSubscribersCommand()\n      : UtilCommand(\"subscribers\", \"Dumps contents of a WWIVnet subscriber list\") {}\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n} // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/list.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/list.h\"\n\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"fmt/format.h\"\n#include \"sdk/net/packets.h\"\n#include \"sdk/net/networks.h\"\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string NetListCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   list \" << std::endl;\n  return ss.str();\n}\n\nbool NetListCommand::AddSubCommands() {\n  return true;\n}\n\nint NetListCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  auto nn = 0;\n  for (const auto& net : networks.networks()) {\n    const auto s = fmt::format(\".{:<2} {:<17}({})\", nn++, net.name, net.dir.string());\n    std::cout << s << std::endl;\n  }\n  return 0;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/net/list.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2018-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_LIST_H\n#define INCLUDED_WWIVUTIL_LIST_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass NetListCommand final: public UtilCommand {\npublic:\n  NetListCommand() : UtilCommand(\"list\", \"List WWIV Networks\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/net.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"sdk/net/net.h\"\n#include \"wwivutil/net/net.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"wwivutil/net/dump_bbsdata.h\"\n#include \"wwivutil/net/dump_callout.h\"\n#include \"wwivutil/net/dump_connect.h\"\n#include \"wwivutil/net/dump_contact.h\"\n#include \"wwivutil/net/dump_packet.h\"\n#include \"wwivutil/net/dump_subscribers.h\"\n#include \"wwivutil/net/list.h\"\n#include \"wwivutil/net/req.h\"\n#include \"wwivutil/net/send.h\"\n\n#include <memory>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivutil {\n\nbool NetCommand::AddSubCommands() {\n  add(std::make_unique<DumpPacketCommand>());\n  add(std::make_unique<DumpCalloutCommand>());\n  add(std::make_unique<DumpConnectCommand>());\n  add(std::make_unique<DumpContactCommand>());\n  add(std::make_unique<DumpBbsDataCommand>());\n  add(std::make_unique<wwiv::wwivutil::net::DumpSubscribersCommand>());\n  add(std::make_unique<SubReqCommand>());\n  add(std::make_unique<NetListCommand>());\n  add(std::make_unique<net::SubSendCommand>());\n  return true;\n}\n\n\n}  // namespace\n"
  },
  {
    "path": "wwivutil/net/net.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_NET_H\n#define INCLUDED_WWIVUTIL_NET_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass NetCommand final : public UtilCommand {\npublic:\n  NetCommand(): UtilCommand(\"net\", \"WWIV network commands.\") {}\n  virtual ~NetCommand() = default;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/req.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/req.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/packets.h\"\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstd::string SubReqCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   req <A|D> <subtype> <host>\" << std::endl;\n  ss << \"Example: req A GENCHAT 1\" << std::endl;\n  return ss.str();\n}\n\nbool SubReqCommand::AddSubCommands() {\n  add_argument({\"net\", \"Network number to use (i.e. 0).\", \"0\"});\n\n  return true;\n}\n\nint SubReqCommand::Execute() {\n  const Networks networks(*config()->config());\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  const auto r = this->remaining();\n  if (r.size() < 3) {\n    std::cout << GetUsage() << GetHelp();\n    return 2;\n  }\n\n  const auto net = stl::at(config()->networks(),arg(\"net\").as_int());\n  const auto packet_filename = create_pend(net.dir, false, 'r');\n  const auto add_drop = upcase(stl::at(r, 0).front());\n\n  net_header_rec nh = {};\n  auto host = to_number<uint16_t>(stl::at(r, 2));\n  nh.tosys = static_cast<uint16_t>(host);\n  nh.touser = 1;\n  nh.fromsys = net.sysnum;\n  nh.fromuser = 1;\n  nh.main_type = add_drop == 'A' ?  main_type_sub_add_req : main_type_sub_drop_req;\n  // always use 0 since we use the stype\n  nh.minor_type = 0;\n  nh.list_len = 0;\n  nh.daten = daten_t_now();\n  nh.method = 0;\n  // This is an alphanumeric sub type.\n  const auto& subtype = stl::at(r, 1);\n  nh.length = subtype.size() + 1;\n  auto text = ToStringUpperCase(subtype);\n  text.push_back('\\0');\n  NetPacket packet(nh, {}, text);\n  const auto ok = write_wwivnet_packet(FilePath(net.dir, packet_filename), packet);\n  if (!ok) {\n    LOG(ERROR) << \"Error writing packet: \" << packet_filename;\n    return 1;\n  }\n  LOG(INFO) << \"Wrote Packet: \" << packet_filename;\n  return 0;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/net/req.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_REQ_H\n#define INCLUDED_WWIVUTIL_REQ_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil {\n\nclass SubReqCommand final: public UtilCommand {\npublic:\n  SubReqCommand()\n    : UtilCommand(\"req\", \"Add/Drop WWIVnet Sub\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/net/send.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/net/send.h\"\n\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/bbslist.h\"\n#include \"sdk/config.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/networks.h\"\n#include \"sdk/net/packets.h\"\n\n#include <iostream>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil::net {\n\n// Based off one from post.cpp\nstatic std::optional<subboard_t> find_sub(const Subs& subs, int network_number, const std::string& netname) {\n  auto current = 0;\n  VLOG(3) << \"find_sub: subs.subs().size(): \" << subs.subs().size()\n          << \"; net_num: \" << network_number;\n  for (const auto& x : subs.subs()) {\n    for (const auto& n : x.nets) {\n      if (n.net_num == network_number) {\n        VLOG(4) << \"netname: \" << netname << \"; n.stype: \" << n.stype;\n        if (iequals(netname, n.stype)) {\n          VLOG(2) << \"MATCH: netname: \" << netname << \"; n.stype: \" << n.stype;\n          // Since the subtype matches, we need to find the sub-board base filename.\n          // and return that.\n          auto sub = subs.sub(current);\n          return { sub };\n        }\n      }\n    }\n    ++current;\n  }\n  return std::nullopt;\n}\n\n\n// (from autosend.doc): AUTOSEND <sub type> <node> <.net> [num msgs]\n\nstd::string SubSendCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage:   send --net=N <sub type> <node> [num msgs]\" << std::endl;\n  ss << \"Example: send --net=1 GENCHAT 1 25\" << std::endl;\n  return ss.str();\n}\n\nbool SubSendCommand::AddSubCommands() {\n  add_argument({\"net\", \"Network number to use (i.e. 0).\", \"0\"});\n\n  return true;\n}\n\nint SubSendCommand::Execute() {\n  const auto& networks = config()->networks();\n  if (!networks.IsInitialized()) {\n    LOG(ERROR) << \"Unable to load networks.\";\n    return 1;\n  }\n\n  const auto r = this->remaining();\n  if (r.size() < 2) {\n    std::cout << GetUsage() << GetHelp();\n    return 2;\n  }\n\n  const auto net_num = arg(\"net\").as_int();\n  const auto net = stl::at(networks, net_num);\n  const auto subtype = stl::at(r, 0);\n  const auto host = to_number<uint16_t>(stl::at(r, 1));\n  auto num = 10;\n  if (r.size() > 2) {\n    num = to_number<int>(stl::at(r, 2));\n  }\n  \n  Subs subs(config()->config()->datadir(), networks.networks());\n  if (!subs.Load()) {\n    LOG(ERROR) << \"Failed to load subs\";\n    return 1;\n  }\n\n  VLOG(1) << \"SubType : \" << subtype;\n  VLOG(1) << \"Host:     \" << host;\n  VLOG(1) << \"Num:      \" << net_num;\n  VLOG(1) << \"Network:  \" << net.name;\n\n  if (net.type != network_type_t::wwivnet) {\n    LOG(ERROR) << \"Can only send posts to WWIVnet type networks.\";\n    return 1;\n  }\n\n  auto so = find_sub(subs, net_num, subtype);\n\n  if (!so) {\n    LOG(ERROR) << \"Unable to find subtype: '\" << subtype << \"' on network: \" << net.name;\n    return 1;\n  }\n\n  VLOG(1) << \"Sub:      \" << so->name;\n  VLOG(1) << \"Filename: \" << so->filename;\n  VLOG(1) << \"Descr:    \" << so->desc;\n\n  // TODO(rushfan): Should this be enforced, if not we can\n  // let people peer to peer seed subs if needed.\n  for (const auto& n : so->nets) {\n    if (n.net_num == net_num && n.host != 0) {\n      LOG(WARNING) << \"Should only send posts for subs we host\";\n    }\n  }\n\n  const MessageApiOptions options{};\n  auto* x = new NullLastReadImpl();\n  auto api = std::make_unique<WWIVMessageApi>(options, *config()->config(),\n                                              config()->networks().networks(), x);\n  if (!api->Exist(*so)) {\n    LOG(ERROR) << \"Sub doesn't exist in this message type\";\n    return 1;\n  }\n  auto area(api->Open(*so, -1));\n  if (!area) {\n    LOG(ERROR) << \"Unable to open message area.\";\n    return 1;\n  }\n  for (auto i = std::max<int>(1, area->number_of_messages() - num); i <= area->number_of_messages();\n       i++) {\n    auto message = area->ReadMessage(i);\n    auto packet = create_packet_from_wwiv_message(*message, subtype, {host});\n    LOG(INFO) << \"Writing packet for message: \" << message->header().title();\n    // TODO(rushfan): make documented list of what network_app_id codes\n    // are used when writing pending packets.\n    write_wwivnet_packet_or_log(net, 'u', packet);\n  }\n\n  return 0;\n}\n\n} // namespace wwiv::wwivutil::net"
  },
  {
    "path": "wwivutil/net/send.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)2020-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_SEND_H\n#define INCLUDED_WWIVUTIL_SEND_H\n\n#include \"wwivutil/command.h\"\n#include <string>\n\nnamespace wwiv::wwivutil::net {\n\nclass SubSendCommand final: public UtilCommand {\npublic:\n  // (from autosend.doc): AUTOSEND <sub type> <node> <.net> [num msgs]\n  SubSendCommand()\n    : UtilCommand(\"send\", \"<sub type> <node> <.net> [num msgs]\") {}\n  int Execute() override;\n  [[nodiscard]] std::string GetUsage() const override;\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n#endif\n"
  },
  {
    "path": "wwivutil/print/print.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/print/print.h\"\n\n#include \"core/command_line.h\"\n#include \"core/datetime.h\"\n#include \"core/log.h\"\n#include \"core/file.h\"\n#include \"core/os.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"local_io/local_io_curses.h\"\n#include \"local_io/local_io_win32.h\"\n#include \"localui/curses_io.h\"\n#include \"sdk/ansi/ansi.h\"\n#include \"sdk/ansi/localio_screen.h\"\n#include \"sdk/ansi/makeansi.h\"\n#include <iostream>\n#include <string>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace std::chrono_literals;\nusing namespace wwiv::local::io;\nusing namespace wwiv::local::ui;\nusing namespace wwiv::os;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::ansi;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nPrintCommand::PrintCommand() : UtilCommand(\"print\", \"prints a textfile\") {}\n\nstd::string PrintCommand::GetUsage() const {\n  std::ostringstream ss;\n  ss << \"Usage: \" << std::endl << std::endl;\n  ss << \"  print : Prints a textfile.\" << std::endl;\n  return ss.str();\n}\n\n std::vector<int> colors = {7, 11, 14, 5, 31, 2, 12, 9, 6, 3};\n\n enum class pipe_state_t { text, pipe };\n static std::string PipeCodesToAnsi(const std::string & s) { \n   std::string out;\n   out.reserve(static_cast<int>(wwiv::stl::ssize(s) * 1.1));\n   auto state = pipe_state_t::text;\n   std::string curpipe;\n   auto curatr = 0x07;\n   for (auto it = std::begin(s); it != std::end(s); ++it) {\n     const auto c = *it;\n     switch (state) {\n     case pipe_state_t::text: {\n       if (c == '|') {\n         state = pipe_state_t::pipe;\n         curpipe.push_back(c);\n       } else {\n         out.push_back(c);\n       }\n     } break;\n     // grab first\n     case pipe_state_t::pipe: {\n       const auto pipe_size = stl::ssize(curpipe);\n       if (std::isdigit(c) && pipe_size == 2) {\n         curpipe.push_back(c);\n         std::string ansitext;\n         if (curpipe[1] == '#') {\n           const auto color = stl::at(colors, curpipe[2] - '0');\n           ansitext = makeansi(color, curatr);\n           curatr = color;\n         } else {\n           const auto color = to_number<int>(curpipe.substr(1));\n           ansitext = makeansi(color, curatr);\n           curatr = color;\n         }\n         out.append(ansitext);\n         curpipe.clear();\n         state = pipe_state_t::text;\n       } else if ((std::isdigit(c) || c == '#') && pipe_size == 1) {\n         curpipe.push_back(c);\n       } else {\n         state = pipe_state_t::text;\n         out.append(curpipe);\n         curpipe.clear();\n       }\n     } break;\n     }\n   } \n   out.shrink_to_fit();\n   return out;\n }\n\n\nint PrintCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << GetHelp() << std::endl;\n    return 2;\n  }\n  TextFile tf(remaining().front(), \"rt\");\n  auto s = tf.ReadFileIntoString();\n\n  if (s.find('|') != std::string::npos) {\n    s = PipeCodesToAnsi(s);\n  }\n\n  auto need_pause = false;\n  if (!barg(\"ansi\")) {\n    std::cout << s << std::endl;\n  } else {\n    std::unique_ptr<LocalIO> io;\n    const auto io_type = sarg(\"io\");\n    const auto bps = iarg(\"bps\");\n#ifdef _WIN32\n    if (io_type == \"win32\") {\n      io = std::make_unique<Win32ConsoleIO>();\n    }\n#endif\n    if (!io) {\n      need_pause = true;\n      CursesIO::Init(\"wwivutil\");\n      io = std::make_unique<CursesLocalIO>(curses_out->GetMaxY(), curses_out->GetMaxX());\n    }\n    LocalIOScreen screen(io.get(), 80);\n    AnsiCallbacks cb;\n    cb.move_ = [](int x, int y) { VLOG(2) << \"moved: x: \" << x << \"; y:\" << y; };\n    Ansi ansi(&screen, cb, 0x07);\n    HeartAndPipeCodeFilter heart(&ansi, {7, 11, 14, 5, 31, 2, 12, 9, 6, 3});\n\n    screen.clear();\n    auto count = 0;\n    const auto allowed_per_100ms = bps / 100;\n\n    auto start = core::DateTime::now();\n    for (const auto c : s) {\n      if (allowed_per_100ms > 0 && (++count % allowed_per_100ms == 0)) {\n        sleep_for(100ms);\n      }\n      heart.write(c);\n    }\n    heart.close();\n    auto end = core::DateTime::now();\n\n    if (need_pause) {\n      io->GetChar();\n    }\n    const auto time_taken = end.to_time_t() - start.to_time_t();\n    VLOG(1) << \"Wrote: \" << count << \" chars.\";\n    if (time_taken > 0) {\n      VLOG(1) << \"CPS = \" << count / (end.to_time_t() - start.to_time_t());\n    }\n  }\n  // Cleanup CursesIO.\n  if (curses_out != nullptr) {\n    delete curses_out;\n    curses_out = nullptr;\n  }\n\n  return 0;\n}\n\nbool PrintCommand::AddSubCommands() {\n  add_argument(BooleanCommandLineArgument{\"ansi\", \"Display the file as an ANSI file.\", true});\n  add_argument({\"io\", \"What type of IO to use, win32 | curses\",\n#ifdef _WIN32\n                \"win32\"});\n#else\n                \"curses\"});\n#endif\n  add_argument({\"bps\", \"What BPS to emulate\", \"14400\"});\n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/print/print.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_PRINT_H\n#define INCLUDED_WWIVUTIL_PRINT_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass PrintCommand final : public UtilCommand {\npublic:\n  PrintCommand();\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/status/status.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/status/status.h\"\n\n#include \"sdk/status.h\"\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nstatic int show_qscan(const Config& config) {\n  StatusMgr mgr(config.datadir(), [](int) {});\n  const auto status = mgr.get_status();\n  std::cout << \"QScan Pointer : \" << status->qscanptr() << std::endl;\n  return 0;\n}\n\nstatic int set_qscan(const Config& config, uint32_t qscan) {\n  StatusMgr mgr(config.datadir(), [](int) {});\n  mgr.Run([=](Status& s) {\n    s.qscanptr(qscan);\n  });\n\n  const auto status = mgr.get_status();\n  std::cout << \"QScan Pointer : \" << status->qscanptr() << std::endl;\n  return 0;\n}\n\nclass StatusQScanCommand final : public UtilCommand {\npublic:\n  StatusQScanCommand(): UtilCommand(\"qscan\", \"Sets or Gets the qscan high water mark.\") {}\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  get : Gets the qscptr information.\" << std::endl << std::endl;\n    return ss.str();\n  }\n  int Execute() override {\n    if (remaining().empty()) {\n      std::cout << GetUsage() << GetHelp() << std::endl;\n      return 2;\n    }\n    const auto set_or_get = ToStringLowerCase(remaining().front());\n\n    if (set_or_get == \"get\") {\n      return show_qscan(*this->config()->config());\n    }\n    if (set_or_get == \"set\") {\n      if (remaining().size() < 2) {\n        std::cout << \"qscan set requires a value\" << std::endl;\n        return 2;\n      }\n      const auto s = stl::at(remaining(), 1);\n      const auto v = to_number<uint32_t>(s);\n      if (v <= 0) {\n        std::cout << \"invalid value: '\" << s << \"' (\" << v << \")\" << std::endl;\n        return 1;\n      }\n      std::cout << \"Setting qscanptr to : \" << v << std::endl;\n      set_qscan(*this->config()->config(), v);\n    }\n    return 1;\n  }\n\n  bool AddSubCommands() override {\n    return true;\n  }\n\n};\n\nclass StatusDumpCommand final : public UtilCommand {\npublic:\n  StatusDumpCommand(): UtilCommand(\"dump\", \"Displays status.dat.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  dump : Displays status.dat.\" << std::endl << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    StatusMgr mgr(config()->config()->datadir());\n    const auto s = mgr.get_status();\n    std::cout << \"num_users:     \" << s->num_users() << std::endl;\n    std::cout << \"caller_num:    \" << s->caller_num() << std::endl;\n    std::cout << \"days_active:   \" << s->days_active() << std::endl;\n    std::cout << \"qscanptr:      \" << s->qscanptr() << std::endl;\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    return true;\n  }\n\n};\n\nbool StatusCommand::AddSubCommands() {\n  add(std::make_unique<StatusQScanCommand>());\n  add(std::make_unique<StatusDumpCommand>());\n  return true;\n}\n\n\n}  // namespace \n"
  },
  {
    "path": "wwivutil/status/status.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_STATUS_H\n#define INCLUDED_WWIVUTIL_STATUS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass StatusCommand final : public UtilCommand {\npublic:\n  StatusCommand(): UtilCommand(\"status\", \"WWIV status commands.\") {}\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/subs/import.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/subs/import.h\"\n\n#include \"core/file.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"core/textfile.h\"\n#include \"sdk/subxtr.h\"\n#include \"sdk/fido/backbone.h\"\n#include \"sdk/net/subscribers.h\"\n#include <iostream>\n#include <sstream>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk::fido;\nusing namespace wwiv::sdk::net;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\n\n\nstd::string SubsImportCommand::GetUsage() const {\nreturn R\"(\nImports subs using the backbone file and values specified in the ini file\nspecified in wwivconfig for the network or override using --defaults.\n\nUsage:   import --net=NN [--defaults=import.ini] [backbone.na]\n\nExample: wwivutil subs import --net=1\n\n  Sample import.ini:\n\n  [backbone]\n  post_acs = user.sl >= 20\n  read_acs = user.sl >= 10\n  maxmsgs = 5000\n  uplink = 21:2/100\n  conf = ANF\n)\";\n}\n\nbool SubsImportCommand::AddSubCommands() {\n  add_argument({\"backbone\", 'b', \"Override the backbone.na file defined in wwivconfig.\", \"\"});\n  add_argument({\"defaults\", 'd', \"Override the ini file defined in wwivconfig.\", \"\"});\n  add_argument({\"net\", \"Network number to use (i.e. 0).\", \"\"});\n\n  return true;\n}\n\nint SubsImportCommand::Execute() {\n  if (remaining().empty()) {\n    std::cout << GetUsage() << std::endl;\n    return 1;\n  }\n\n  auto defaults_fn = sarg(\"defaults\");\n  int16_t net_num = 0;\n  if (!arg(\"net\").as_string().empty()) {\n    // Use the network number on the commandline as an override.\n    net_num = iarg<int16_t>(\"net\");\n  }\n  const auto& net = config()->networks().at(net_num);\n\n  if (net.type != network_type_t::ftn) {\n    std::cout << \"Can only import subs for FTN network\" << std::endl;\n    std::cout << GetUsage() << std::endl;\n  }\n\n  if (defaults_fn.empty()) {\n    // If --defaults is empty, use the one from networks.json\n    defaults_fn = net.settings.auto_add_ini;\n  }\n  if (defaults_fn.empty() || !core::File::Exists(defaults_fn)) {\n    std::cout << \"Defaults INI file: \" << defaults_fn << \" does not exist \" << std::endl;\n    std::cout << GetUsage() << std::endl;\n    return 1;\n  }\n\n  std::filesystem::path backbone_filename = sarg(\"backbone\");\n  if (!backbone_filename.empty()) {\n    // Override the backbone filename\n    backbone_filename = FilePath(net.dir, net.fido.backbone_filename);\n  }\n  if (backbone_filename.empty() || !core::File::Exists(backbone_filename)) {\n    std::cout << \"BACKBONE.NA file: \" << backbone_filename << \" does not exist \" << std::endl;\n    std::cout << GetUsage() << std::endl;\n    return 1;\n  }\n\n  sdk::Subs subs(config()->config()->datadir(), config()->networks().networks(),\n                 config()->config()->max_backups());\n  if (!subs.Load()) {\n    std::cout << \"Unable to load subs.json\" << std::endl;\n    return 1;\n  }\n\n  IniFile ini(defaults_fn, \"backbone\");\n  if (!ini.IsOpen()) {\n    std::cout << \"Unable to open INI file: \" << defaults_fn << std::endl;\n    return 1;\n  }\n\n  auto backbone_echos = ParseBackboneFile(backbone_filename);\n  if (backbone_echos.empty()) {\n    std::cout << \"Nothing to do, no subs parsed out of \" << backbone_filename << std::endl;\n    return 0;\n  }\n\n  //\n  // From here down we assume backbone filename, net, etc are all set\n  //\n\n  auto r = ImportSubsFromBackbone(subs, net, net_num, ini, backbone_echos);\n\n  if (r.success && r.subs_dirty) {\n    if (!subs.Save()) {\n      LOG(ERROR) << \"Error Saving subs.dat\";\n    }\n  }\n\n  std::cout << \"Done!\" << std::endl;\n  return 0;\n}\n\n}\n"
  },
  {
    "path": "wwivutil/subs/import.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_SUBS_IMPORT_H\n#define INCLUDED_WWIVUTIL_SUBS_IMPORT_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass SubsImportCommand final: public UtilCommand {\npublic:\n  SubsImportCommand() : UtilCommand(\"import\", \"Import wwiv subboards.\") {}\n  ~SubsImportCommand() override = default;\n  [[nodiscard]] std::string GetUsage() const override;\n  int Execute() override;\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/subs/subs.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/subs/subs.h\"\n\n#include \"core/command_line.h\"\n#include \"core/file.h\"\n#include \"core/log.h\"\n#include \"core/strings.h\"\n#include \"sdk/config.h\"\n#include \"sdk/msgapi/message_api_wwiv.h\"\n#include \"sdk/net/networks.h\"\n#include \"wwivutil/util.h\"\n#include \"wwivutil/subs/import.h\"\n\n#include <iomanip>\n#include <iostream>\n#include <memory>\n#include <string>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::sdk;\nusing namespace wwiv::sdk::msgapi;\nusing namespace wwiv::strings;\n\nconstexpr char CD = 4;\n\nnamespace wwiv::wwivutil {\n\n\n// This is hacked from subacc.cpp.\n// TODO(rushfan): move this into the message sdk.\nstatic uint32_t WWIVReadLastRead(const std::filesystem::path& datadir, const std::string& sub_filename) {\n  // open file, and create it if necessary\n  postrec p{};\n\n  const auto sub_fn = FilePath(datadir, StrCat(sub_filename, \".sub\"));\n  if (!File::Exists(sub_fn)) {\n    return 1;\n  }\n  File subFile(sub_fn);\n  if (!subFile.Open(File::modeBinary | File::modeReadOnly)) {\n    return 0;\n  }\n  // read in first rec, specifying # posts\n  // p.owneruser contains # of posts.\n  subFile.Read(&p, sizeof(postrec));\n\n  if (p.owneruser == 0) {\n    // Not sure why but iscan1 returned 1 for empty subs.\n    return 1;\n  }\n\n  // read in sub date, if don't already know it\n  subFile.Seek(p.owneruser * sizeof(postrec), File::Whence::begin);\n  subFile.Read(&p, sizeof(postrec));\n  return p.qscan;\n}\n\nclass SubsListCommand final : public UtilCommand {\npublic:\n  SubsListCommand() : UtilCommand(\"areas\", \"Lists the message areas\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage:   areas\" << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    Subs subs(config()->config()->datadir(), config()->networks().networks());\n    if (!subs.Load()) {\n      LOG(ERROR) << \"Unable to load subs\";\n      return 2;\n    }\n\n    int num = 0;\n    std::cout << \"#Num FileName LastRead   \" << std::setw(30) << std::left << \"Name\"\n         << \" \" << std::endl;\n    std::cout << std::string(78, '=') << std::endl;\n    for (const auto& d : subs.subs()) {\n      const auto lastread = WWIVReadLastRead(config()->config()->datadir(), d.filename);\n      std::cout << \"#\" << std::setw(3) << std::left << num++ << \" \" \n           << std::setw(8) << d.filename << \" \"\n           << std::setw(std::numeric_limits<uint32_t>::digits10 + 1) << lastread << \" \"\n           << std::setw(30) << d.name << std::endl;\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument(BooleanCommandLineArgument(\"full\", \"Display full info about every area.\", false));\n    return true;\n  }\n};\n\nbool SubsCommand::AddSubCommands() {\n  if (!add(std::make_unique<SubsImportCommand>())) {\n    return false;\n  }\n  if (!add(std::make_unique<SubsListCommand>())) {\n    return false;\n  }\n  \n  return true;\n}\n\n} // namespace wwiv\n"
  },
  {
    "path": "wwivutil/subs/subs.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_SUBS_SUBS_H\n#define INCLUDED_WWIVUTIL_SUBS_SUBS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass SubsCommand final : public UtilCommand {\npublic:\n  SubsCommand(): UtilCommand(\"subs\", \"WWIV subboard commands.\") {}\n  bool AddSubCommands() override;\n};\n\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/users/users.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                          WWIV Version 5.x                              */\n/*             Copyright (C)2015-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#include \"wwivutil/users/users.h\"\n\n#include \"core/command_line.h\"\n#include \"core/stl.h\"\n#include \"core/strings.h\"\n#include \"sdk/instance.h\"\n#include \"sdk/usermanager.h\"\n\n#include <iostream>\n#include <memory>\n#include <string>\n\nusing wwiv::core::BooleanCommandLineArgument;\nusing namespace wwiv::sdk;\nusing namespace wwiv::strings;\n\nnamespace wwiv::wwivutil {\n\nclass UsersAsvCommand final : public UtilCommand {\npublic:\n  UsersAsvCommand(): UtilCommand(\"asv\", \"Execute automatic sysop validation on a user.\") {}\n\n  [[nodiscard]] std::string GetUsage() const override {\n    std::ostringstream ss;\n    ss << \"Usage: \" << std::endl << std::endl;\n    ss << \"  asv --user=<num> --asv=1 : Autoval user.\" << std::endl << std::endl;\n    return ss.str();\n  }\n\n  int Execute() override {\n    if (const auto asv_string = sarg(\"asv\"); asv_string.empty()) {\n      std::cerr << \"--asv must be specified.\" << std::endl;\n      std::cerr << GetUsage();\n      return 1;\n    }    \n    if (const auto user_string = sarg(\"user\"); user_string.empty()) {\n      std::cerr << \"--user must be specified.\" << std::endl;\n      std::cerr << GetUsage();\n      return 1;\n    }\n\n    const auto user_number = iarg(\"user\");\n    UserManager um(*config()->config());\n    if (user_number < 1 || user_number > um.num_user_records()) {\n      std::cerr << \"invalid user number for --user specified: \" << user_number << std::endl;\n      std::cerr << GetUsage();\n      return 1;\n    }\n    const auto asv_num = iarg(\"asv\");\n    if (asv_num < 1 || asv_num > 10) {\n      std::cerr << \"invalid user number for --asv specified: \" << asv_num << std::endl;\n      std::cerr << GetUsage();\n      return 1;\n    }\n\n    if (auto o = um.readuser(user_number)) {\n      auto& user = o.value();\n      if (const auto& v = config()->config()->auto_val(asv_num); !user.asv(v)) {\n        std::cout << \"Failed to apply ASV to user number: \" << user_number;\n        return 1;\n      }\n      if (!um.writeuser(&user, user_number)) {\n        std::cout << \"Unable to save user number: \" << user_number;\n        return 1;\n      }\n      std::cout << \"Done!\";\n    } else {\n      std::cout << \"Unable to find user number: \" << user_number;\n      return 1;\n    }\n    return 0;\n  }\n\n  bool AddSubCommands() override {\n    add_argument({\"user\", \"user number to use while evaluating the expression\", \"\"});\n    add_argument({\"asv\", \"user number to use while evaluating the expression\", \"\"});\n    return true;\n  }\n\n};\n\nbool UsersCommand::AddSubCommands() {\n  add(std::make_unique<UsersAsvCommand>());\n  return true;\n}\n\n\n} \n"
  },
  {
    "path": "wwivutil/users/users.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                            WWIV Version 5                              */\n/*             Copyright (C)2021-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_USERS_USERS_H\n#define INCLUDED_WWIVUTIL_USERS_USERS_H\n\n#include \"wwivutil/command.h\"\n\nnamespace wwiv::wwivutil {\n\nclass UsersCommand final: public UtilCommand {\npublic:\n  UsersCommand(): UtilCommand(\"users\", \"WWIV user commands.\") {}\n  bool AddSubCommands() override;\n};\n\n}  // namespace\n\n\n#endif\n"
  },
  {
    "path": "wwivutil/util.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2018-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"wwivutil/util.h\"\n\nnamespace wwiv::wwivutil {\n\nvoid dump_char(std::ostream& out, char ch) { \n  \n  switch (ch) { \n  case 0:\n  case 1:\n  case 2:\n  case 3:\n  case 4:\n  case 5:\n  case 6:\n  case 7:\n  case 8:\n  case 9:\n  case 11:\n  case 12:\n  case 14:\n  case 15:\n  case 16:\n  case 17:\n  case 18:\n  case 19:\n  case 20:\n  case 21:\n  case 22:\n  case 23:\n  case 24:\n  case 25:\n  case 26:\n    out << \"[^\" << static_cast<char>('@' + ch) << \"]\";\n    break;\n  case 27:\n    out << \"[ESC]\";\n    break;\n  case 28:\n  case 29:\n  case 30:\n  case 31:\n    out << \"[#\" << ch << \"]\";\n    break;\n  default:\n      out << ch;\n    break;\n  }\n}\n\n\n} // namespace wwivutil::wwiv\n"
  },
  {
    "path": "wwivutil/util.h",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*                Copyright (C)2018-2022, WWIV Software Services          */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#ifndef INCLUDED_WWIVUTIL_UTIL_H\n#define INCLUDED_WWIVUTIL_UTIL_H\n\n#include <ostream>\n\nnamespace wwiv::wwivutil {\n\nvoid dump_char(std::ostream& out, char ch);\n\n} // namespace \n\n#endif\n"
  },
  {
    "path": "wwivutil/wwivutil.cpp",
    "content": "/**************************************************************************/\n/*                                                                        */\n/*                              WWIV Version 5.x                          */\n/*             Copyright (C)1998-2022, WWIV Software Services             */\n/*                                                                        */\n/*    Licensed  under the  Apache License, Version  2.0 (the \"License\");  */\n/*    you may not use this  file  except in compliance with the License.  */\n/*    You may obtain a copy of the License at                             */\n/*                                                                        */\n/*                http://www.apache.org/licenses/LICENSE-2.0              */\n/*                                                                        */\n/*    Unless  required  by  applicable  law  or agreed to  in  writing,   */\n/*    software  distributed  under  the  License  is  distributed on an   */\n/*    \"AS IS\"  BASIS, WITHOUT  WARRANTIES  OR  CONDITIONS OF ANY  KIND,   */\n/*    either  express  or implied.  See  the  License for  the specific   */\n/*    language governing permissions and limitations under the License.   */\n/*                                                                        */\n/**************************************************************************/\n#include \"core/command_line.h\"\n#include \"core/log.h\"\n#include \"core/scope_exit.h\"\n#include \"core/strings.h\"\n#include \"instance/instance.h\"\n#include \"sdk/config.h\"\n#include \"wwivutil/help.h\"\n#include \"wwivutil/acs/acs.h\"\n#include \"wwivutil/conf/conf.h\"\n#include \"wwivutil/config/config.h\"\n#include \"wwivutil/email/email.h\"\n#include \"wwivutil/fido/fido.h\"\n#include \"wwivutil/files/files.h\"\n#include \"wwivutil/fix/fix.h\"\n#include \"wwivutil/messages/messages.h\"\n#include \"wwivutil/menus/menus.h\"\n#include \"wwivutil/net/net.h\"\n#include \"wwivutil/users/users.h\"\n#include \"wwivutil/print/print.h\"\n#include \"wwivutil/status/status.h\"\n#include \"wwivutil/subs/subs.h\"\n#include <algorithm>\n#include <memory>\n#include <vector>\n\nusing namespace wwiv::core;\nusing namespace wwiv::strings;\nusing namespace wwiv::sdk;\n\nnamespace wwiv::wwivutil {\n\nclass WWIVUtil final {\npublic:\n  WWIVUtil() = delete;\n  WWIVUtil(const WWIVUtil&) = delete;\n  WWIVUtil(WWIVUtil&&) = delete;\n  WWIVUtil& operator=(const WWIVUtil&) = delete;\n  WWIVUtil& operator=(WWIVUtil&&) = delete;\n\n  WWIVUtil(int argc, char *argv[]) : cmdline_(argc, argv, \"net\") {\n    LoggerConfig config(LogDirFromConfig);\n    Logger::Init(argc, argv, config);\n\n    cmdline_.AddStandardArgs();\n  }\n  ~WWIVUtil() = default;\n\n  int Main() {\n    auto at_exit = finally(Logger::ExitLogger);\n    try {\n      Add(std::make_unique<acs::AcsCommand>());\n      Add(std::make_unique<ConfCommand>());\n      Add(std::make_unique<ConfigCommand>());\n      Add(std::make_unique<EmailCommand>());\n      Add(std::make_unique<fido::FidoCommand>());\n      Add(std::make_unique<files::FilesCommand>());\n      Add(std::make_unique<FixCommand>());\n      Add(std::make_unique<HelpCommand>());\n      Add(std::make_unique<InstanceCommand>());\n      Add(std::make_unique<MessagesCommand>());\n      Add(std::make_unique<MenusCommand>());\n      Add(std::make_unique<NetCommand>());\n      Add(std::make_unique<PrintCommand>());\n      Add(std::make_unique<StatusCommand>());\n      Add(std::make_unique<SubsCommand>());\n      Add(std::make_unique<UsersCommand>());\n      if (!cmdline_.Parse()) {\n        return 1;\n      }\n      auto config = load_any_config(cmdline_.bbsdir());\n      if (!config) {\n        LOG(ERROR) << \"Unable to load config.json or config.dat\";\n        return 1;\n      }\n      command_config_ = std::make_shared<Configuration>(std::move(config));\n      if (!command_config_->initialized()) {\n        LOG(ERROR) << \"Unable to load NETWORKS.\";\n        return 1;\n      }\n      SetConfigs();\n      return cmdline_.Execute();\n    } catch (const std::exception& e) {\n      LOG(ERROR) << e.what();\n    }\n    return 1;\n  }\n\nprivate:\n  void Add(std::unique_ptr<UtilCommand>&& cmd) {\n    auto* c = cmd.get();\n    cmdline_.add(std::move(cmd));\n    c->AddStandardArgs();\n    c->AddSubCommands();\n    subcommands_.push_back(c);\n  }\n\n  // ReSharper disable once CppMemberFunctionMayBeConst\n  void SetConfigs() {\n    for (auto* s : subcommands_) {\n      s->set_config(command_config_);\n    }\n    command_config_->set_subcommands(subcommands_);\n  }\n  CommandLine cmdline_;\n  std::shared_ptr<Configuration> command_config_;\n  std::vector<UtilCommand*> subcommands_;\n};\n\n}  // namespace\n\nint main(int argc, char *argv[]) {\n  wwiv::wwivutil::WWIVUtil wwivutil(argc, argv);\n  return wwivutil.Main();\n}\n"
  }
]